From 0795a654977dc5c79cb55db7a41155a9d5ccccf8 Mon Sep 17 00:00:00 2001 From: tconley1428 Date: Mon, 16 Mar 2026 09:23:32 -0700 Subject: [PATCH 001/226] Add experimental notices to ADK top level objects (#1363) * Add experimental notices to ADK top level objects * Add experimental notices to ADK top level objects --- temporalio/contrib/google_adk_agents/_mcp.py | 8 ++++++++ temporalio/contrib/google_adk_agents/_plugin.py | 8 ++++++++ temporalio/contrib/google_adk_agents/workflow.py | 4 ++++ 3 files changed, 20 insertions(+) diff --git a/temporalio/contrib/google_adk_agents/_mcp.py b/temporalio/contrib/google_adk_agents/_mcp.py index c4b6cdf5f..6c6123806 100644 --- a/temporalio/contrib/google_adk_agents/_mcp.py +++ b/temporalio/contrib/google_adk_agents/_mcp.py @@ -82,6 +82,10 @@ class _CallToolArguments: class TemporalMcpToolSetProvider: """Provider for creating Temporal-aware MCP toolsets. + .. warning:: + This class is experimental and may change in future versions. + Use with caution in production environments. + Manages the creation of toolset activities and handles tool execution within Temporal workflows. """ @@ -198,6 +202,10 @@ async def run_async( class TemporalMcpToolSet(BaseToolset): """Temporal-aware MCP toolset implementation. + .. warning:: + This class is experimental and may change in future versions. + Use with caution in production environments. + Executes MCP tools as Temporal activities, providing proper isolation and execution guarantees within workflows. """ diff --git a/temporalio/contrib/google_adk_agents/_plugin.py b/temporalio/contrib/google_adk_agents/_plugin.py index 89dc7fc99..03cb78998 100644 --- a/temporalio/contrib/google_adk_agents/_plugin.py +++ b/temporalio/contrib/google_adk_agents/_plugin.py @@ -23,6 +23,10 @@ def setup_deterministic_runtime(): """Configures ADK runtime for Temporal determinism. + .. warning:: + This function is experimental and may change in future versions. + Use with caution in production environments. + This should be called at the start of a Temporal Workflow before any ADK components (like SessionService) are used, if they rely on runtime.get_time() or runtime.new_uuid(). """ @@ -52,6 +56,10 @@ def _deterministic_id_provider() -> str: class GoogleAdkPlugin(SimplePlugin): """A Temporal Worker Plugin configured for ADK. + .. warning:: + This class is experimental and may change in future versions. + Use with caution in production environments. + This plugin configures: - Pydantic Payload Converter (required for ADK objects). - Sandbox Passthrough for google.adk and google.genai modules. diff --git a/temporalio/contrib/google_adk_agents/workflow.py b/temporalio/contrib/google_adk_agents/workflow.py index 0a65809cd..42ff7246f 100644 --- a/temporalio/contrib/google_adk_agents/workflow.py +++ b/temporalio/contrib/google_adk_agents/workflow.py @@ -9,6 +9,10 @@ def activity_tool(activity_def: Callable, **kwargs: Any) -> Callable: """Decorator/Wrapper to wrap a Temporal Activity as an ADK Tool. + .. warning:: + This function is experimental and may change in future versions. + Use with caution in production environments. + This ensures the activity's signature is preserved for ADK's tool schema generation while marking it as a tool that executes via 'workflow.execute_activity'. """ From 1978919b71cbf13b7a244f60947efa5ba7070d7c Mon Sep 17 00:00:00 2001 From: Justin Anderson <44687433+jmaeagle99@users.noreply.github.com> Date: Mon, 16 Mar 2026 12:15:01 -0700 Subject: [PATCH 002/226] Split converter.py into submodules (#1365) --- temporalio/client.py | 9 +- temporalio/converter.py | 2148 ----------------- temporalio/converter/__init__.py | 81 + temporalio/converter/_data_converter.py | 325 +++ temporalio/converter/_failure_converter.py | 468 ++++ temporalio/converter/_payload_codec.py | 115 + temporalio/converter/_payload_converter.py | 951 ++++++++ temporalio/converter/_payload_limits.py | 47 + temporalio/converter/_search_attributes.py | 213 ++ .../converter/_serialization_context.py | 121 + temporalio/worker/_activity.py | 10 +- temporalio/worker/_nexus.py | 4 +- temporalio/worker/_worker.py | 2 +- temporalio/worker/_workflow.py | 6 +- tests/test_converter.py | 2 +- 15 files changed, 2344 insertions(+), 2158 deletions(-) delete mode 100644 temporalio/converter.py create mode 100644 temporalio/converter/__init__.py create mode 100644 temporalio/converter/_data_converter.py create mode 100644 temporalio/converter/_failure_converter.py create mode 100644 temporalio/converter/_payload_codec.py create mode 100644 temporalio/converter/_payload_converter.py create mode 100644 temporalio/converter/_payload_limits.py create mode 100644 temporalio/converter/_search_attributes.py create mode 100644 temporalio/converter/_serialization_context.py diff --git a/temporalio/client.py b/temporalio/client.py index af49f9a06..22b07b1c1 100644 --- a/temporalio/client.py +++ b/temporalio/client.py @@ -54,6 +54,7 @@ import temporalio.api.workflowservice.v1 import temporalio.common import temporalio.converter +import temporalio.converter._search_attributes import temporalio.exceptions import temporalio.nexus import temporalio.nexus._operation_context @@ -4433,7 +4434,9 @@ def _from_raw( return ActivityExecutionCountAggregationGroup( count=raw.count, group_values=[ - temporalio.converter._decode_search_attribute_value(v) + temporalio.converter._search_attributes._decode_search_attribute_value( + v + ) for v in raw.group_values ], ) @@ -5127,7 +5130,9 @@ def _from_raw( return WorkflowExecutionCountAggregationGroup( count=raw.count, group_values=[ - temporalio.converter._decode_search_attribute_value(v) + temporalio.converter._search_attributes._decode_search_attribute_value( + v + ) for v in raw.group_values ], ) diff --git a/temporalio/converter.py b/temporalio/converter.py deleted file mode 100644 index dc37f5039..000000000 --- a/temporalio/converter.py +++ /dev/null @@ -1,2148 +0,0 @@ -"""Base converter and implementations for data conversion.""" - -from __future__ import annotations - -import collections -import collections.abc -import dataclasses -import functools -import inspect -import json -import sys -import traceback -import typing -import uuid -import warnings -from abc import ABC, abstractmethod -from collections.abc import Awaitable, Callable, Mapping, Sequence -from dataclasses import dataclass -from datetime import datetime -from enum import IntEnum -from itertools import zip_longest -from logging import getLogger -from typing import ( - Any, - ClassVar, - Literal, - NewType, - TypeVar, - get_type_hints, - overload, -) - -import google.protobuf.json_format -import google.protobuf.message -import google.protobuf.symbol_database -import nexusrpc -import typing_extensions -from typing_extensions import Self - -import temporalio.api.common.v1 -import temporalio.api.enums.v1 -import temporalio.api.failure.v1 -import temporalio.common -import temporalio.exceptions -import temporalio.types - -if sys.version_info < (3, 11): - # Python's datetime.fromisoformat doesn't support certain formats pre-3.11 - from dateutil import parser # type: ignore -# StrEnum is available in 3.11+ -if sys.version_info >= (3, 11): - from enum import StrEnum # type: ignore[reportUnreachable] - -from types import UnionType - -logger = getLogger(__name__) - -_TEMPORAL_FAILURE_PROTO_TYPE = "temporal.api.failure.v1.Failure" - - -class SerializationContext(ABC): - """Base serialization context. - - Provides contextual information during serialization and deserialization operations. - - Examples: - In client code, when starting a workflow, or sending a signal/update/query to a workflow, - or receiving the result of an update/query, or handling an exception from a workflow, the - context type is :py:class:`WorkflowSerializationContext` and the workflow ID set of the - target workflow will be set in the context. - - In workflow code, when operating on a payload being sent/received to/from a child workflow, - or handling an exception from a child workflow, the context type is - :py:class:`WorkflowSerializationContext` and the workflow ID is that of the child workflow, - not of the currently executing (i.e. parent) workflow. - - In workflow code, when operating on a payload to be sent/received to/from an activity, the - context type is :py:class:`ActivitySerializationContext` and the workflow ID is that of the - currently-executing workflow. ActivitySerializationContext is also set on data converter - operations in the activity context. - """ - - pass - - -@dataclass(frozen=True) -class WorkflowSerializationContext(SerializationContext): - """Serialization context for workflows. - - See :py:class:`SerializationContext` for more details. - """ - - namespace: str - """The namespace the workflow is running in.""" - - workflow_id: str - """The ID of the workflow. - - Note that this is the ID of the workflow of which the payload being operated on is an input or - output. Note also that when creating/describing schedules, this may be the workflow ID prefix - as configured, not the final workflow ID when the workflow is created by the schedule. - """ - - -@dataclass(frozen=True) -class ActivitySerializationContext(SerializationContext): - """Serialization context for activities. - - See :py:class:`SerializationContext` for more details. - """ - - namespace: str - """Workflow/activity namespace.""" - - activity_id: str | None - """Activity ID. Optional if this is an activity started from a workflow.""" - - activity_type: str | None - """Activity type. - - .. deprecated:: - This value may not be set in some bidirectional situations, it should - not be relied on. - """ - - activity_task_queue: str | None - """Activity task queue. - - .. deprecated:: - This value may not be set in some bidirectional situations, it should - not be relied on. - """ - - workflow_id: str | None - """Workflow ID. Only set if this is an activity started from a workflow. - - Note, when creating/describing schedules, this may be the workflow ID prefix as - configured, not the final workflow ID when the workflow is created by the schedule.""" - - workflow_type: str | None - """Workflow type if this is an activity started from a workflow.""" - - is_local: bool - """Whether the activity is a local activity started from a workflow.""" - - -class WithSerializationContext(ABC): - """Interface for classes that can use serialization context. - - The following classes may implement this interface: - - :py:class:`PayloadConverter` - - :py:class:`PayloadCodec` - - :py:class:`FailureConverter` - - :py:class:`EncodingPayloadConverter` - - During data converter operations (encoding/decoding, serialization/deserialization, and failure - conversion), instances of classes implementing this interface will be replaced by the result of - calling with_context(context). This allows overridden methods (encode/decode, - to_payload/from_payload, etc) to use the context. - """ - - def with_context(self, context: SerializationContext) -> Self: # type: ignore[reportUnusedParameter] - """Return a copy of this object configured to use the given context. - - Args: - context: The serialization context to use. - - Returns: - A new instance configured with the context. - """ - raise NotImplementedError() - - -class PayloadConverter(ABC): - """Base payload converter to/from multiple payloads/values.""" - - default: ClassVar[PayloadConverter] - """Default payload converter.""" - - @abstractmethod - def to_payloads( - self, values: Sequence[Any] - ) -> list[temporalio.api.common.v1.Payload]: - """Encode values into payloads. - - Implementers are expected to just return the payload for - :py:class:`temporalio.common.RawValue`. - - Args: - values: Values to be converted. - - Returns: - Converted payloads. Note, this does not have to be the same number - as values given, but must be at least one and cannot be more than - was given. - - Raises: - Exception: Any issue during conversion. - """ - raise NotImplementedError - - @abstractmethod - def from_payloads( - self, - payloads: Sequence[temporalio.api.common.v1.Payload], - type_hints: list[type] | None = None, - ) -> list[Any]: - """Decode payloads into values. - - Implementers are expected to treat a type hint of - :py:class:`temporalio.common.RawValue` as just the raw value. - - Args: - payloads: Payloads to convert to Python values. - type_hints: Types that are expected if any. This may not have any - types if there are no annotations on the target. If this is - present, it must have the exact same length as payloads even if - the values are just "object". - - Returns: - Collection of Python values. Note, this does not have to be the same - number as values given, but at least one must be present. - - Raises: - Exception: Any issue during conversion. - """ - raise NotImplementedError - - def to_payloads_wrapper( - self, values: Sequence[Any] - ) -> temporalio.api.common.v1.Payloads: - """:py:meth:`to_payloads` for the - :py:class:`temporalio.api.common.v1.Payloads` wrapper. - """ - return temporalio.api.common.v1.Payloads(payloads=self.to_payloads(values)) - - def from_payloads_wrapper( - self, payloads: temporalio.api.common.v1.Payloads | None - ) -> list[Any]: - """:py:meth:`from_payloads` for the - :py:class:`temporalio.api.common.v1.Payloads` wrapper. - """ - if not payloads or not payloads.payloads: - return [] - return self.from_payloads(payloads.payloads) - - def to_payload(self, value: Any) -> temporalio.api.common.v1.Payload: - """Convert a single value to a payload. - - This is a shortcut for :py:meth:`to_payloads` with a single-item list - and result. - - Args: - value: Value to convert to a single payload. - - Returns: - Single converted payload. - """ - return self.to_payloads([value])[0] - - @overload - def from_payload(self, payload: temporalio.api.common.v1.Payload) -> Any: ... - - @overload - def from_payload( - self, - payload: temporalio.api.common.v1.Payload, - type_hint: type[temporalio.types.AnyType], - ) -> temporalio.types.AnyType: ... - - def from_payload( - self, - payload: temporalio.api.common.v1.Payload, - type_hint: type | None = None, - ) -> Any: - """Convert a single payload to a value. - - This is a shortcut for :py:meth:`from_payloads` with a single-item list - and result. - - Args: - payload: Payload to convert to value. - type_hint: Optional type hint to say which type to convert to. - - Returns: - Single converted value. - """ - return self.from_payloads([payload], [type_hint] if type_hint else None)[0] - - -class EncodingPayloadConverter(ABC): - """Base converter to/from single payload/value with a known encoding for use in CompositePayloadConverter.""" - - @property - @abstractmethod - def encoding(self) -> str: - """Encoding for the payload this converter works with.""" - raise NotImplementedError - - @abstractmethod - def to_payload(self, value: Any) -> temporalio.api.common.v1.Payload | None: - """Encode a single value to a payload or None. - - Args: - value: Value to be converted. - - Returns: - Payload of the value or None if unable to convert. - - Raises: - TypeError: Value is not the expected type. - ValueError: Value is of the expected type but otherwise incorrect. - RuntimeError: General error during encoding. - """ - raise NotImplementedError - - @abstractmethod - def from_payload( - self, - payload: temporalio.api.common.v1.Payload, - type_hint: type | None = None, - ) -> Any: - """Decode a single payload to a Python value or raise exception. - - Args: - payload: Payload to convert to Python value. - type_hint: Type that is expected if any. This may not have a type if - there are no annotations on the target. - - Return: - The decoded value from the payload. Since the encoding is checked by - the caller, this should raise an exception if the payload cannot be - converted. - - Raises: - RuntimeError: General error during decoding. - """ - raise NotImplementedError - - -class CompositePayloadConverter(PayloadConverter, WithSerializationContext): - """Composite payload converter that delegates to a list of encoding payload converters. - - Encoding/decoding are attempted on each payload converter successively until - it succeeds. - - Attributes: - converters: List of payload converters to delegate to, in order. - """ - - converters: Mapping[bytes, EncodingPayloadConverter] - - def __init__(self, *converters: EncodingPayloadConverter) -> None: - """Initializes the data converter. - - Args: - converters: Payload converters to delegate to, in order. - """ - self._set_converters(*converters) - - def _set_converters(self, *converters: EncodingPayloadConverter) -> None: - self.converters = {c.encoding.encode(): c for c in converters} - - def to_payloads( - self, values: Sequence[Any] - ) -> list[temporalio.api.common.v1.Payload]: - """Encode values trying each converter. - - See base class. Always returns the same number of payloads as values. - - Raises: - RuntimeError: No known converter - """ - payloads = [] - for index, value in enumerate(values): - # We intentionally attempt these serially just in case a stateful - # converter may rely on the previous values - payload = None - # RawValue should just pass through - if isinstance(value, temporalio.common.RawValue): - payload = value.payload - else: - for converter in self.converters.values(): - payload = converter.to_payload(value) - if payload is not None: - break - if payload is None: - raise RuntimeError( - f"Value at index {index} of type {type(value)} has no known converter" - ) - payloads.append(payload) - return payloads - - def from_payloads( - self, - payloads: Sequence[temporalio.api.common.v1.Payload], - type_hints: list[type] | None = None, - ) -> list[Any]: - """Decode values trying each converter. - - See base class. Always returns the same number of values as payloads. - - Raises: - KeyError: Unknown payload encoding - RuntimeError: Error during decode - """ - values = [] - type_hints = type_hints or [] - for index, (payload, type_hint) in enumerate(zip_longest(payloads, type_hints)): - # Raw value should just wrap - if type_hint == temporalio.common.RawValue: - values.append(temporalio.common.RawValue(payload)) - continue - encoding = payload.metadata.get("encoding", b"") - converter = self.converters.get(encoding) - if converter is None: - raise KeyError(f"Unknown payload encoding {encoding.decode()}") - try: - values.append(converter.from_payload(payload, type_hint)) - except RuntimeError as err: - raise RuntimeError( - f"Payload at index {index} with encoding {encoding.decode()} could not be converted" - ) from err - return values - - def with_context(self, context: SerializationContext) -> Self: - """Return a new instance with context set on the component converters. - - If none of the component converters returned new instances, return self. - """ - converters = self.get_converters_with_context(context) - if converters is None: - return self - new_instance = type(self)() # Must have a nullary constructor - new_instance._set_converters(*converters) - return new_instance - - def get_converters_with_context( - self, context: SerializationContext - ) -> list[EncodingPayloadConverter] | None: - """Return converter instances with context set. - - If no converter uses context, return None. - """ - if not self._any_converter_takes_context: - return None - converters: list[EncodingPayloadConverter] = [] - any_with_context = False - for c in self.converters.values(): - if isinstance(c, WithSerializationContext): - converters.append(c.with_context(context)) - any_with_context |= converters[-1] is not c - else: - converters.append(c) - - return converters if any_with_context else None - - @functools.cached_property - def _any_converter_takes_context(self) -> bool: - return any( - isinstance(c, WithSerializationContext) for c in self.converters.values() - ) - - -class DefaultPayloadConverter(CompositePayloadConverter): - """Default payload converter compatible with other Temporal SDKs. - - This handles None, bytes, all protobuf message types, and any type that - :py:func:`json.dump` accepts. A singleton instance of this is available at - :py:attr:`PayloadConverter.default`. - """ - - default_encoding_payload_converters: tuple[EncodingPayloadConverter, ...] - """Default set of encoding payload converters the default payload converter - uses. - """ - - def __init__(self) -> None: - """Create a default payload converter.""" - super().__init__(*DefaultPayloadConverter.default_encoding_payload_converters) - - -class BinaryNullPayloadConverter(EncodingPayloadConverter): - """Converter for 'binary/null' payloads supporting None values.""" - - @property - def encoding(self) -> str: - """See base class.""" - return "binary/null" - - def to_payload(self, value: Any) -> temporalio.api.common.v1.Payload | None: - """See base class.""" - if value is None: - return temporalio.api.common.v1.Payload( - metadata={"encoding": self.encoding.encode()} - ) - return None - - def from_payload( - self, - payload: temporalio.api.common.v1.Payload, - type_hint: type | None = None, - ) -> Any: - """See base class.""" - if len(payload.data) > 0: - raise RuntimeError("Expected empty data set for binary/null") - return None - - -class BinaryPlainPayloadConverter(EncodingPayloadConverter): - """Converter for 'binary/plain' payloads supporting bytes values.""" - - @property - def encoding(self) -> str: - """See base class.""" - return "binary/plain" - - def to_payload(self, value: Any) -> temporalio.api.common.v1.Payload | None: - """See base class.""" - if isinstance(value, bytes): - return temporalio.api.common.v1.Payload( - metadata={"encoding": self.encoding.encode()}, data=value - ) - return None - - def from_payload( - self, - payload: temporalio.api.common.v1.Payload, - type_hint: type | None = None, - ) -> Any: - """See base class.""" - return payload.data - - -_sym_db = google.protobuf.symbol_database.Default() - - -class JSONProtoPayloadConverter(EncodingPayloadConverter): - """Converter for 'json/protobuf' payloads supporting protobuf Message values.""" - - def __init__(self, ignore_unknown_fields: bool = False): - """Initialize a JSON proto converter. - - Args: - ignore_unknown_fields: Determines whether converter should error if - unknown fields are detected - """ - super().__init__() - self._ignore_unknown_fields = ignore_unknown_fields - - @property - def encoding(self) -> str: - """See base class.""" - return "json/protobuf" - - def to_payload(self, value: Any) -> temporalio.api.common.v1.Payload | None: - """See base class.""" - if ( - isinstance(value, google.protobuf.message.Message) - and value.DESCRIPTOR is not None # type:ignore[reportUnnecessaryComparison] - ): - # We have to convert to dict then to JSON because MessageToJson does - # not have a compact option removing spaces and newlines - json_str = json.dumps( - google.protobuf.json_format.MessageToDict(value), - separators=(",", ":"), - sort_keys=True, - ) - return temporalio.api.common.v1.Payload( - metadata={ - "encoding": self.encoding.encode(), - "messageType": value.DESCRIPTOR.full_name.encode(), - }, - data=json_str.encode(), - ) - return None - - def from_payload( - self, - payload: temporalio.api.common.v1.Payload, - type_hint: type | None = None, - ) -> Any: - """See base class.""" - message_type = payload.metadata.get("messageType", b"").decode() - try: - value = _sym_db.GetSymbol(message_type)() - return google.protobuf.json_format.Parse( - payload.data, - value, - ignore_unknown_fields=self._ignore_unknown_fields, - ) - except KeyError as err: - raise RuntimeError(f"Unknown Protobuf type {message_type}") from err - except google.protobuf.json_format.ParseError as err: - raise RuntimeError("Failed parsing") from err - - -class BinaryProtoPayloadConverter(EncodingPayloadConverter): - """Converter for 'binary/protobuf' payloads supporting protobuf Message values.""" - - @property - def encoding(self) -> str: - """See base class.""" - return "binary/protobuf" - - def to_payload(self, value: Any) -> temporalio.api.common.v1.Payload | None: - """See base class.""" - if ( - isinstance(value, google.protobuf.message.Message) - and value.DESCRIPTOR is not None # type:ignore[reportUnnecessaryComparison] - ): - return temporalio.api.common.v1.Payload( - metadata={ - "encoding": self.encoding.encode(), - "messageType": value.DESCRIPTOR.full_name.encode(), - }, - data=value.SerializeToString(), - ) - return None - - def from_payload( - self, - payload: temporalio.api.common.v1.Payload, - type_hint: type | None = None, - ) -> Any: - """See base class.""" - message_type = payload.metadata.get("messageType", b"").decode() - try: - value = _sym_db.GetSymbol(message_type)() - value.ParseFromString(payload.data) - return value - except KeyError as err: - raise RuntimeError(f"Unknown Protobuf type {message_type}") from err - except google.protobuf.message.DecodeError as err: - raise RuntimeError("Failed parsing") from err - - -class AdvancedJSONEncoder(json.JSONEncoder): - """Advanced JSON encoder. - - This encoder supports dataclasses and all iterables as lists. - - It also uses Pydantic v1's "dict" methods if available on the object, - but this is deprecated. Pydantic users should upgrade to v2 and use - temporalio.contrib.pydantic.pydantic_data_converter. - """ - - def default(self, o: Any) -> Any: - """Override JSON encoding default. - - See :py:meth:`json.JSONEncoder.default`. - """ - # Datetime support - if isinstance(o, datetime): - return o.isoformat() - # Dataclass support - if dataclasses.is_dataclass(o) and not isinstance(o, type): - return dataclasses.asdict(o) - # Support for Pydantic v1's dict method - dict_fn = getattr(o, "dict", None) - if callable(dict_fn): - return dict_fn() - # Support for non-list iterables like set - if not isinstance(o, list) and isinstance(o, collections.abc.Iterable): - return list(o) - # Support for UUID - if isinstance(o, uuid.UUID): - return str(o) - return super().default(o) - - -class JSONPlainPayloadConverter(EncodingPayloadConverter): - """Converter for 'json/plain' payloads supporting common Python values. - - For encoding, this supports all values that :py:func:`json.dump` supports - and by default adds extra encoding support for dataclasses, classes with - ``dict()`` methods, and all iterables. - - For decoding, this uses type hints to attempt to rebuild the type from the - type hint. - """ - - _encoder: type[json.JSONEncoder] | None - _decoder: type[json.JSONDecoder] | None - _encoding: str - - def __init__( - self, - *, - encoder: type[json.JSONEncoder] | None = AdvancedJSONEncoder, - decoder: type[json.JSONDecoder] | None = None, - encoding: str = "json/plain", - custom_type_converters: Sequence[JSONTypeConverter] = [], - ) -> None: - """Initialize a JSON data converter. - - Args: - encoder: Custom encoder class object to use. - decoder: Custom decoder class object to use. - encoding: Encoding name to use. - custom_type_converters: Set of custom type converters that are used - when converting from a payload to type-hinted values. - """ - super().__init__() - self._encoder = encoder - self._decoder = decoder - self._encoding = encoding - self._custom_type_converters = custom_type_converters - - @property - def encoding(self) -> str: - """See base class.""" - return self._encoding - - def to_payload(self, value: Any) -> temporalio.api.common.v1.Payload | None: - """See base class.""" - # Check for Pydantic v1 - if hasattr(value, "parse_obj"): - warnings.warn( - "If you're using Pydantic v2, use temporalio.contrib.pydantic.pydantic_data_converter. " - "If you're using Pydantic v1 and cannot upgrade, refer to https://github.com/temporalio/samples-python/tree/main/pydantic_converter_v1 for better v1 support." - ) - # We let JSON conversion errors be thrown to caller - return temporalio.api.common.v1.Payload( - metadata={"encoding": self._encoding.encode()}, - data=json.dumps( - value, cls=self._encoder, separators=(",", ":"), sort_keys=True - ).encode(), - ) - - def from_payload( - self, - payload: temporalio.api.common.v1.Payload, - type_hint: type | None = None, - ) -> Any: - """See base class.""" - try: - obj = json.loads(payload.data, cls=self._decoder) - if type_hint: - obj = value_to_type(type_hint, obj, self._custom_type_converters) - return obj - except json.JSONDecodeError as err: - raise RuntimeError("Failed parsing") from err - - -_JSONTypeConverterUnhandled = NewType("_JSONTypeConverterUnhandled", object) - - -class JSONTypeConverter(ABC): - """Converter for converting an object from Python :py:func:`json.loads` - result (e.g. scalar, list, or dict) to a known type. - """ - - Unhandled = _JSONTypeConverterUnhandled(object()) - """Sentinel value that must be used as the result of - :py:meth:`to_typed_value` to say the given type is not handled by this - converter.""" - - @abstractmethod - def to_typed_value( - self, hint: type, value: Any - ) -> Any | None | _JSONTypeConverterUnhandled: - """Convert the given value to a type based on the given hint. - - Args: - hint: Type hint to use to help in converting the value. - value: Value as returned by :py:func:`json.loads`. Usually a scalar, - list, or dict. - - Returns: - The converted value or :py:attr:`Unhandled` if this converter does - not handle this situation. - """ - raise NotImplementedError - - -class PayloadCodec(ABC): - """Codec for encoding/decoding to/from bytes. - - Commonly used for compression or encryption. - """ - - @abstractmethod - async def encode( - self, payloads: Sequence[temporalio.api.common.v1.Payload] - ) -> list[temporalio.api.common.v1.Payload]: - """Encode the given payloads. - - Args: - payloads: Payloads to encode. This value should not be mutated. - - Returns: - Encoded payloads. Note, this does not have to be the same number as - payloads given, but must be at least one and cannot be more than was - given. - """ - raise NotImplementedError - - @abstractmethod - async def decode( - self, payloads: Sequence[temporalio.api.common.v1.Payload] - ) -> list[temporalio.api.common.v1.Payload]: - """Decode the given payloads. - - Args: - payloads: Payloads to decode. This value should not be mutated. - - Returns: - Decoded payloads. Note, this does not have to be the same number as - payloads given, but must be at least one and cannot be more than was - given. - """ - raise NotImplementedError - - async def encode_wrapper(self, payloads: temporalio.api.common.v1.Payloads) -> None: - """:py:meth:`encode` for the - :py:class:`temporalio.api.common.v1.Payloads` wrapper. - - This replaces the payloads within the wrapper. - """ - new_payloads = await self.encode(payloads.payloads) - del payloads.payloads[:] - # TODO(cretz): Copy too expensive? - payloads.payloads.extend(new_payloads) - - async def decode_wrapper(self, payloads: temporalio.api.common.v1.Payloads) -> None: - """:py:meth:`decode` for the - :py:class:`temporalio.api.common.v1.Payloads` wrapper. - - This replaces the payloads within. - """ - new_payloads = await self.decode(payloads.payloads) - del payloads.payloads[:] - # TODO(cretz): Copy too expensive? - payloads.payloads.extend(new_payloads) - - async def encode_failure(self, failure: temporalio.api.failure.v1.Failure) -> None: - """Encode payloads of a failure. Intended as a helper method, not for overriding. - It is not guaranteed that all failures will be encoded with this method rather - than encoding the underlying payloads. - """ - await DataConverter._apply_to_failure_payloads(failure, self.encode_wrapper) - - async def decode_failure(self, failure: temporalio.api.failure.v1.Failure) -> None: - """Decode payloads of a failure. Intended as a helper method, not for overriding. - It is not guaranteed that all failures will be decoded with this method rather - than decoding the underlying payloads. - """ - await DataConverter._apply_to_failure_payloads(failure, self.decode_wrapper) - - -class FailureConverter(ABC): - """Base failure converter to/from errors. - - Note, for workflow exceptions, :py:attr:`to_failure` is only invoked if the - exception is an instance of :py:class:`temporalio.exceptions.FailureError`. - Users should extend :py:class:`temporalio.exceptions.ApplicationError` if - they want a custom workflow exception to work with this class. - """ - - default: ClassVar[FailureConverter] - """Default failure converter.""" - - @abstractmethod - def to_failure( - self, - exception: BaseException, - payload_converter: PayloadConverter, - failure: temporalio.api.failure.v1.Failure, - ) -> None: - """Convert the given exception to a Temporal failure. - - Users should make sure not to alter the ``exception`` input. - - Args: - exception: The exception to convert. - payload_converter: The payload converter to use if needed. - failure: The failure to update with error information. - """ - raise NotImplementedError - - @abstractmethod - def from_failure( - self, - failure: temporalio.api.failure.v1.Failure, - payload_converter: PayloadConverter, - ) -> BaseException: - """Convert the given Temporal failure to an exception. - - Users should make sure not to alter the ``failure`` input. - - Args: - failure: The failure to convert. - payload_converter: The payload converter to use if needed. - - Returns: - Converted error. - """ - raise NotImplementedError - - -class DefaultFailureConverter(FailureConverter): - """Default failure converter. - - A singleton instance of this is available at - :py:attr:`FailureConverter.default`. - """ - - def __init__(self, *, encode_common_attributes: bool = False) -> None: - """Create the default failure converter. - - Args: - encode_common_attributes: If ``True``, the message and stack trace - of the failure will be moved into the encoded attribute section - of the failure which can be encoded with a codec. - """ - super().__init__() - self._encode_common_attributes = encode_common_attributes - - def to_failure( - self, - exception: BaseException, - payload_converter: PayloadConverter, - failure: temporalio.api.failure.v1.Failure, - ) -> None: - """See base class.""" - # If already a failure error, use that - if isinstance(exception, temporalio.exceptions.FailureError): - self._error_to_failure(exception, payload_converter, failure) - elif isinstance(exception, nexusrpc.HandlerError): - self._nexus_handler_error_to_failure(exception, payload_converter, failure) - else: - # Convert to failure error - failure_error = temporalio.exceptions.ApplicationError( - str(exception), - type="PayloadSizeError" - if isinstance(exception, _PayloadSizeError) - else exception.__class__.__name__, - ) - failure_error.__traceback__ = exception.__traceback__ - failure_error.__cause__ = exception.__cause__ - self._error_to_failure(failure_error, payload_converter, failure) - # Encode common attributes if requested - if self._encode_common_attributes: - # Move message and stack trace to encoded attribute payload - failure.encoded_attributes.CopyFrom( - payload_converter.to_payloads( - [{"message": failure.message, "stack_trace": failure.stack_trace}] - )[0] - ) - failure.message = "Encoded failure" - failure.stack_trace = "" - - def _error_to_failure( - self, - error: temporalio.exceptions.FailureError, - payload_converter: PayloadConverter, - failure: temporalio.api.failure.v1.Failure, - ) -> None: - # If there is an underlying proto already, just use that - if error.failure: - failure.CopyFrom(error.failure) - return - - # Set message, stack, and cause. Obtaining cause follows rules from - # https://docs.python.org/3/library/exceptions.html#exception-context - failure.message = error.message - if error.__traceback__: - failure.stack_trace = "\n".join(traceback.format_tb(error.__traceback__)) - if error.__cause__: - self.to_failure(error.__cause__, payload_converter, failure.cause) - elif not error.__suppress_context__ and error.__context__: - self.to_failure(error.__context__, payload_converter, failure.cause) - - # Set specific subclass values - if isinstance(error, temporalio.exceptions.ApplicationError): - failure.application_failure_info.SetInParent() - if error.type: - failure.application_failure_info.type = error.type - failure.application_failure_info.non_retryable = error.non_retryable - if error.details: - failure.application_failure_info.details.CopyFrom( - payload_converter.to_payloads_wrapper(error.details) - ) - if error.next_retry_delay: - failure.application_failure_info.next_retry_delay.FromTimedelta( - error.next_retry_delay - ) - if error.category: - failure.application_failure_info.category = ( - temporalio.api.enums.v1.ApplicationErrorCategory.ValueType( - error.category - ) - ) - elif isinstance(error, temporalio.exceptions.TimeoutError): - failure.timeout_failure_info.SetInParent() - failure.timeout_failure_info.timeout_type = ( - temporalio.api.enums.v1.TimeoutType.ValueType(error.type or 0) - ) - if error.last_heartbeat_details: - failure.timeout_failure_info.last_heartbeat_details.CopyFrom( - payload_converter.to_payloads_wrapper(error.last_heartbeat_details) - ) - elif isinstance(error, temporalio.exceptions.CancelledError): - failure.canceled_failure_info.SetInParent() - if error.details: - failure.canceled_failure_info.details.CopyFrom( - payload_converter.to_payloads_wrapper(error.details) - ) - elif isinstance(error, temporalio.exceptions.TerminatedError): - failure.terminated_failure_info.SetInParent() - elif isinstance(error, temporalio.exceptions.ServerError): - failure.server_failure_info.SetInParent() - failure.server_failure_info.non_retryable = error.non_retryable - elif isinstance(error, temporalio.exceptions.ActivityError): - failure.activity_failure_info.SetInParent() - failure.activity_failure_info.scheduled_event_id = error.scheduled_event_id - failure.activity_failure_info.started_event_id = error.started_event_id - failure.activity_failure_info.identity = error.identity - failure.activity_failure_info.activity_type.name = error.activity_type - failure.activity_failure_info.activity_id = error.activity_id - failure.activity_failure_info.retry_state = ( - temporalio.api.enums.v1.RetryState.ValueType(error.retry_state or 0) - ) - elif isinstance(error, temporalio.exceptions.ChildWorkflowError): - failure.child_workflow_execution_failure_info.SetInParent() - failure.child_workflow_execution_failure_info.namespace = error.namespace - failure.child_workflow_execution_failure_info.workflow_execution.workflow_id = error.workflow_id - failure.child_workflow_execution_failure_info.workflow_execution.run_id = ( - error.run_id - ) - failure.child_workflow_execution_failure_info.workflow_type.name = ( - error.workflow_type - ) - failure.child_workflow_execution_failure_info.initiated_event_id = ( - error.initiated_event_id - ) - failure.child_workflow_execution_failure_info.started_event_id = ( - error.started_event_id - ) - failure.child_workflow_execution_failure_info.retry_state = ( - temporalio.api.enums.v1.RetryState.ValueType(error.retry_state or 0) - ) - elif isinstance(error, temporalio.exceptions.NexusOperationError): - failure.nexus_operation_execution_failure_info.SetInParent() - failure.nexus_operation_execution_failure_info.scheduled_event_id = ( - error.scheduled_event_id - ) - failure.nexus_operation_execution_failure_info.endpoint = error.endpoint - failure.nexus_operation_execution_failure_info.service = error.service - failure.nexus_operation_execution_failure_info.operation = error.operation - failure.nexus_operation_execution_failure_info.operation_token = ( - error.operation_token - ) - - def _nexus_handler_error_to_failure( - self, - error: nexusrpc.HandlerError, - payload_converter: PayloadConverter, - failure: temporalio.api.failure.v1.Failure, - ) -> None: - if error.original_failure: - self._nexus_failure_to_temporal_failure( - error.original_failure, True, failure - ) - else: - failure.message = error.message - if stack_trace := error.stack_trace: - failure.stack_trace = stack_trace - elif tb := error.__traceback__: - failure.stack_trace = "\n".join(traceback.format_tb(tb)) - if error.__cause__: - self.to_failure(error.__cause__, payload_converter, failure.cause) - failure.nexus_handler_failure_info.SetInParent() - failure.nexus_handler_failure_info.type = error.type.name - failure.nexus_handler_failure_info.retry_behavior = temporalio.api.enums.v1.NexusHandlerErrorRetryBehavior.ValueType( - temporalio.api.enums.v1.NexusHandlerErrorRetryBehavior.NEXUS_HANDLER_ERROR_RETRY_BEHAVIOR_RETRYABLE - if error.retryable_override is True - else temporalio.api.enums.v1.NexusHandlerErrorRetryBehavior.NEXUS_HANDLER_ERROR_RETRY_BEHAVIOR_NON_RETRYABLE - if error.retryable_override is False - else temporalio.api.enums.v1.NexusHandlerErrorRetryBehavior.NEXUS_HANDLER_ERROR_RETRY_BEHAVIOR_UNSPECIFIED - ) - - def _temporal_failure_to_nexus_failure( - self, failure: temporalio.api.failure.v1.Failure - ) -> nexusrpc.Failure: - message, failure.message = failure.message, "" - stack_trace, failure.stack_trace = failure.stack_trace, "" - failure_dict = google.protobuf.json_format.MessageToDict(failure) - failure.message = message - failure.stack_trace = stack_trace - return nexusrpc.Failure( - message=message, - stack_trace=stack_trace, - metadata={ - "type": _TEMPORAL_FAILURE_PROTO_TYPE, - }, - details=failure_dict, - ) - - def _nexus_failure_to_temporal_failure( - self, - failure: nexusrpc.Failure, - retryable: bool, - temporal_failure: temporalio.api.failure.v1.Failure, - ) -> None: - if ( - failure.metadata - and failure.metadata.get("type") == _TEMPORAL_FAILURE_PROTO_TYPE - ): - google.protobuf.json_format.ParseDict(failure.details, temporal_failure) - else: - temporal_failure.application_failure_info.SetInParent() - temporal_failure.application_failure_info.type = "NexusFailure" - temporal_failure.application_failure_info.non_retryable = not retryable - temporal_failure.application_failure_info.details.SetInParent() - temporal_failure.application_failure_info.details.payloads.append( - temporalio.api.common.v1.Payload( - metadata={"encoding": b"json/plain"}, - data=json.dumps( - dataclasses.replace(failure, message=""), separators=(",", ":") - ).encode("utf-8"), - ) - ) - - temporal_failure.message = failure.message - temporal_failure.stack_trace = failure.stack_trace or "" - - def from_failure( - self, - failure: temporalio.api.failure.v1.Failure, - payload_converter: PayloadConverter, - ) -> BaseException: - """See base class.""" - # If encoded attributes are present and have the fields we expect, - # extract them - if failure.HasField("encoded_attributes"): - # Clone the failure to not mutate the incoming failure - new_failure = temporalio.api.failure.v1.Failure() - new_failure.CopyFrom(failure) - failure = new_failure - try: - encoded_attributes: dict[str, Any] = payload_converter.from_payloads( - [failure.encoded_attributes] - )[0] - if isinstance(encoded_attributes, dict): - message = encoded_attributes.get("message") - if isinstance(message, str): - failure.message = message - stack_trace = encoded_attributes.get("stack_trace") - if isinstance(stack_trace, str): - failure.stack_trace = stack_trace - except: - pass - - err: temporalio.exceptions.FailureError | nexusrpc.HandlerError - match failure.WhichOneof("failure_info"): - case "application_failure_info": - app_info = failure.application_failure_info - err = temporalio.exceptions.ApplicationError( - failure.message or "Application error", - *payload_converter.from_payloads_wrapper(app_info.details), - type=app_info.type or None, - non_retryable=app_info.non_retryable, - next_retry_delay=app_info.next_retry_delay.ToTimedelta(), - category=temporalio.exceptions.ApplicationErrorCategory( - int(app_info.category) - ), - ) - - case "timeout_failure_info": - timeout_info = failure.timeout_failure_info - err = temporalio.exceptions.TimeoutError( - failure.message or "Timeout", - type=temporalio.exceptions.TimeoutType( - int(timeout_info.timeout_type) - ) - if timeout_info.timeout_type - else None, - last_heartbeat_details=payload_converter.from_payloads_wrapper( - timeout_info.last_heartbeat_details - ), - ) - - case "canceled_failure_info": - cancel_info = failure.canceled_failure_info - err = temporalio.exceptions.CancelledError( - failure.message or "Cancelled", - *payload_converter.from_payloads_wrapper(cancel_info.details), - ) - case "terminated_failure_info": - err = temporalio.exceptions.TerminatedError( - failure.message or "Terminated" - ) - - case "server_failure_info": - server_info = failure.server_failure_info - err = temporalio.exceptions.ServerError( - failure.message or "Server error", - non_retryable=server_info.non_retryable, - ) - - case "activity_failure_info": - act_info = failure.activity_failure_info - err = temporalio.exceptions.ActivityError( - failure.message or "Activity error", - scheduled_event_id=act_info.scheduled_event_id, - started_event_id=act_info.started_event_id, - identity=act_info.identity, - activity_type=act_info.activity_type.name, - activity_id=act_info.activity_id, - retry_state=temporalio.exceptions.RetryState( - int(act_info.retry_state) - ) - if act_info.retry_state - else None, - ) - - case "child_workflow_execution_failure_info": - child_info = failure.child_workflow_execution_failure_info - err = temporalio.exceptions.ChildWorkflowError( - failure.message or "Child workflow error", - namespace=child_info.namespace, - workflow_id=child_info.workflow_execution.workflow_id, - run_id=child_info.workflow_execution.run_id, - workflow_type=child_info.workflow_type.name, - initiated_event_id=child_info.initiated_event_id, - started_event_id=child_info.started_event_id, - retry_state=temporalio.exceptions.RetryState( - int(child_info.retry_state) - ) - if child_info.retry_state - else None, - ) - - case "nexus_handler_failure_info": - nexus_handler_failure_info = failure.nexus_handler_failure_info - try: - _type = nexusrpc.HandlerErrorType[nexus_handler_failure_info.type] - except KeyError: - logger.warning( - f"Unknown Nexus HandlerErrorType: {nexus_handler_failure_info.type}" - ) - _type = nexusrpc.HandlerErrorType.INTERNAL - - retryable_override: bool | None - match nexus_handler_failure_info.retry_behavior: - case temporalio.api.enums.v1.NexusHandlerErrorRetryBehavior.NEXUS_HANDLER_ERROR_RETRY_BEHAVIOR_RETRYABLE: - retryable_override = True - case temporalio.api.enums.v1.NexusHandlerErrorRetryBehavior.NEXUS_HANDLER_ERROR_RETRY_BEHAVIOR_NON_RETRYABLE: - retryable_override = False - case _: - retryable_override = None - - err = nexusrpc.HandlerError( - failure.message or "Nexus handler error", - type=_type, - retryable_override=retryable_override, - stack_trace=failure.stack_trace if failure.stack_trace else None, - original_failure=self._temporal_failure_to_nexus_failure(failure), - ) - - case "nexus_operation_execution_failure_info": - nexus_op_failure_info = failure.nexus_operation_execution_failure_info - err = temporalio.exceptions.NexusOperationError( - failure.message or "Nexus operation error", - scheduled_event_id=nexus_op_failure_info.scheduled_event_id, - endpoint=nexus_op_failure_info.endpoint, - service=nexus_op_failure_info.service, - operation=nexus_op_failure_info.operation, - operation_token=nexus_op_failure_info.operation_token, - ) - - case "reset_workflow_failure_info" | None: - err = temporalio.exceptions.FailureError( - failure.message or "Failure error", - ) - - if isinstance(err, temporalio.exceptions.FailureError): - err._failure = failure - if failure.HasField("cause"): - err.__cause__ = self.from_failure(failure.cause, payload_converter) - return err - - -class DefaultFailureConverterWithEncodedAttributes(DefaultFailureConverter): - """Implementation of :py:class:`DefaultFailureConverter` which moves message - and stack trace to encoded attributes subject to a codec. - """ - - def __init__(self) -> None: - """Create a default failure converter with encoded attributes.""" - super().__init__(encode_common_attributes=True) - - -@dataclass(frozen=True) -class PayloadLimitsConfig: - """Configuration for when payload sizes exceed limits.""" - - memo_size_warning: int = 2 * 1024 - """The limit (in bytes) at which a memo size warning is logged.""" - - payload_size_warning: int = 512 * 1024 - """The limit (in bytes) at which a payload size warning is logged.""" - - -class PayloadSizeWarning(RuntimeWarning): - """The size of payloads is above the warning limit.""" - - -class _PayloadSizeError(temporalio.exceptions.TemporalError): - """Error raised when payloads size exceeds payload size limits.""" - - def __init__(self, message: str): - """Initialize a payloads size error.""" - super().__init__(message) - self._message = message - - @property - def message(self) -> str: - """Message.""" - return self._message - - -@dataclass(frozen=True) -class _ServerPayloadErrorLimits: - """Error limits for payloads as described by the Temporal server.""" - - memo_size_error: int - """The limit (in bytes) at which a memo size error is raised.""" - - payload_size_error: int - """The limit (in bytes) at which a payload size error is raised.""" - - -@dataclass(frozen=True) -class DataConverter(WithSerializationContext): - """Data converter for converting and encoding payloads to/from Python values. - - This combines :py:class:`PayloadConverter` which converts values with - :py:class:`PayloadCodec` which encodes bytes. - """ - - payload_converter_class: type[PayloadConverter] = DefaultPayloadConverter - """Class to instantiate for payload conversion.""" - - payload_codec: PayloadCodec | None = None - """Optional codec for encoding payload bytes.""" - - failure_converter_class: type[FailureConverter] = DefaultFailureConverter - """Class to instantiate for failure conversion.""" - - payload_converter: PayloadConverter = dataclasses.field(init=False) - """Payload converter created from the :py:attr:`payload_converter_class`.""" - - failure_converter: FailureConverter = dataclasses.field(init=False) - """Failure converter created from the :py:attr:`failure_converter_class`.""" - - payload_limits: PayloadLimitsConfig = PayloadLimitsConfig() - """Settings for payload size limits.""" - - default: ClassVar[DataConverter] - """Singleton default data converter.""" - - _payload_error_limits: _ServerPayloadErrorLimits | None = None - """Server-reported limits for payloads.""" - - def __post_init__(self) -> None: # noqa: D105 - object.__setattr__(self, "payload_converter", self.payload_converter_class()) - object.__setattr__(self, "failure_converter", self.failure_converter_class()) - - async def encode( - self, values: Sequence[Any] - ) -> list[temporalio.api.common.v1.Payload]: - """Encode values into payloads. - - First converts values to payloads then encodes payloads using codec. - - Args: - values: Values to be converted and encoded. - - Returns: - Converted and encoded payloads. Note, this does not have to be the - same number as values given, but must be at least one and cannot be - more than was given. - """ - payloads = self.payload_converter.to_payloads(values) - payloads = await self._encode_payload_sequence(payloads) - return payloads - - async def decode( - self, - payloads: Sequence[temporalio.api.common.v1.Payload], - type_hints: list[type] | None = None, - ) -> list[Any]: - """Decode payloads into values. - - First decodes payloads using codec then converts payloads to values. - - Args: - payloads: Payloads to be decoded and converted. - - Returns: - Decoded and converted values. - """ - payloads = await self._decode_payload_sequence(payloads) - return self.payload_converter.from_payloads(payloads, type_hints) - - async def encode_wrapper( - self, values: Sequence[Any] - ) -> temporalio.api.common.v1.Payloads: - """:py:meth:`encode` for the - :py:class:`temporalio.api.common.v1.Payloads` wrapper. - """ - return temporalio.api.common.v1.Payloads(payloads=(await self.encode(values))) - - async def decode_wrapper( - self, - payloads: temporalio.api.common.v1.Payloads | None, - type_hints: list[type] | None = None, - ) -> list[Any]: - """:py:meth:`decode` for the - :py:class:`temporalio.api.common.v1.Payloads` wrapper. - """ - if not payloads or not payloads.payloads: - return [] - return await self.decode(payloads.payloads, type_hints) - - async def encode_failure( - self, exception: BaseException, failure: temporalio.api.failure.v1.Failure - ) -> None: - """Convert and encode failure.""" - self.failure_converter.to_failure(exception, self.payload_converter, failure) - await DataConverter._apply_to_failure_payloads(failure, self._encode_payloads) - - async def decode_failure( - self, failure: temporalio.api.failure.v1.Failure - ) -> BaseException: - """Decode and convert failure.""" - await DataConverter._apply_to_failure_payloads(failure, self._decode_payloads) - return self.failure_converter.from_failure(failure, self.payload_converter) - - def with_context(self, context: SerializationContext) -> Self: - """Return an instance with context set on the component converters.""" - payload_converter = self.payload_converter - payload_codec = self.payload_codec - failure_converter = self.failure_converter - if isinstance(payload_converter, WithSerializationContext): - payload_converter = payload_converter.with_context(context) - if isinstance(payload_codec, WithSerializationContext): - payload_codec = payload_codec.with_context(context) - if isinstance(failure_converter, WithSerializationContext): - failure_converter = failure_converter.with_context(context) - if all( - new is orig - for new, orig in [ - (payload_converter, self.payload_converter), - (payload_codec, self.payload_codec), - (failure_converter, self.failure_converter), - ] - ): - return self - cloned = dataclasses.replace(self) - object.__setattr__(cloned, "payload_converter", payload_converter) - object.__setattr__(cloned, "payload_codec", payload_codec) - object.__setattr__(cloned, "failure_converter", failure_converter) - return cloned - - def _with_payload_error_limits( - self, limits: _ServerPayloadErrorLimits | None - ) -> DataConverter: - return dataclasses.replace(self, _payload_error_limits=limits) - - async def _decode_memo( - self, - source: temporalio.api.common.v1.Memo, - ) -> Mapping[str, Any]: - mapping: dict[str, Any] = {} - for k, v in source.fields.items(): - mapping[k] = (await self.decode([v]))[0] - return mapping - - async def _decode_memo_field( - self, - source: temporalio.api.common.v1.Memo, - key: str, - default: Any, - type_hint: type | None, - ) -> dict[str, Any]: - payload = source.fields.get(key) - if not payload: - if default is temporalio.common._arg_unset: - raise KeyError(f"Memo does not have a value for key {key}") - return default - return (await self.decode([payload], [type_hint] if type_hint else None))[0] - - async def _encode_memo( - self, source: Mapping[str, Any] - ) -> temporalio.api.common.v1.Memo: - memo = temporalio.api.common.v1.Memo() - await self._encode_memo_existing(source, memo) - return memo - - async def _encode_memo_existing( - self, source: Mapping[str, Any], memo: temporalio.api.common.v1.Memo - ): - for k, v in source.items(): - payload = v - if not isinstance(v, temporalio.api.common.v1.Payload): - payload = (await self.encode([v]))[0] - memo.fields[k].CopyFrom(payload) - # Memos have their field payloads validated all together in one unit - DataConverter._validate_limits( - list(memo.fields.values()), - self._payload_error_limits.memo_size_error - if self._payload_error_limits - else None, - "[TMPRL1103] Attempted to upload memo with size that exceeded the error limit.", - self.payload_limits.memo_size_warning, - "[TMPRL1103] Attempted to upload memo with size that exceeded the warning limit.", - ) - - async def _encode_payload( - self, payload: temporalio.api.common.v1.Payload - ) -> temporalio.api.common.v1.Payload: - if self.payload_codec: - payload = (await self.payload_codec.encode([payload]))[0] - self._validate_payload_limits([payload]) - return payload - - async def _encode_payloads(self, payloads: temporalio.api.common.v1.Payloads): - if self.payload_codec: - await self.payload_codec.encode_wrapper(payloads) - self._validate_payload_limits(payloads.payloads) - - async def _encode_payload_sequence( - self, payloads: Sequence[temporalio.api.common.v1.Payload] - ) -> list[temporalio.api.common.v1.Payload]: - encoded_payloads = list(payloads) - if self.payload_codec: - encoded_payloads = await self.payload_codec.encode(encoded_payloads) - self._validate_payload_limits(encoded_payloads) - return encoded_payloads - - async def _decode_payload( - self, payload: temporalio.api.common.v1.Payload - ) -> temporalio.api.common.v1.Payload: - if self.payload_codec: - payload = (await self.payload_codec.decode([payload]))[0] - return payload - - async def _decode_payloads(self, payloads: temporalio.api.common.v1.Payloads): - if self.payload_codec: - await self.payload_codec.decode_wrapper(payloads) - - async def _decode_payload_sequence( - self, payloads: Sequence[temporalio.api.common.v1.Payload] - ) -> list[temporalio.api.common.v1.Payload]: - if not self.payload_codec: - return list(payloads) - return await self.payload_codec.decode(payloads) - - # Temporary shortcircuit detection while the _decode_* methods may no-op if - # a payload codec is not configured. Remove once those paths have more to them. - @property - def _decode_payload_has_effect(self) -> bool: - return self.payload_codec is not None - - @staticmethod - async def _apply_to_failure_payloads( - failure: temporalio.api.failure.v1.Failure, - cb: Callable[[temporalio.api.common.v1.Payloads], Awaitable[None]], - ) -> None: - if failure.HasField("encoded_attributes"): - # Wrap in payloads and merge back - payloads = temporalio.api.common.v1.Payloads( - payloads=[failure.encoded_attributes] - ) - await cb(payloads) - failure.encoded_attributes.CopyFrom(payloads.payloads[0]) - if failure.HasField( - "application_failure_info" - ) and failure.application_failure_info.HasField("details"): - await cb(failure.application_failure_info.details) - elif failure.HasField( - "timeout_failure_info" - ) and failure.timeout_failure_info.HasField("last_heartbeat_details"): - await cb(failure.timeout_failure_info.last_heartbeat_details) - elif failure.HasField( - "canceled_failure_info" - ) and failure.canceled_failure_info.HasField("details"): - await cb(failure.canceled_failure_info.details) - elif failure.HasField( - "reset_workflow_failure_info" - ) and failure.reset_workflow_failure_info.HasField("last_heartbeat_details"): - await cb(failure.reset_workflow_failure_info.last_heartbeat_details) - if failure.HasField("cause"): - await DataConverter._apply_to_failure_payloads(failure.cause, cb) - - def _validate_payload_limits( - self, - payloads: Sequence[temporalio.api.common.v1.Payload], - ): - DataConverter._validate_limits( - payloads, - self._payload_error_limits.payload_size_error - if self._payload_error_limits - else None, - "[TMPRL1103] Attempted to upload payloads with size that exceeded the error limit.", - self.payload_limits.payload_size_warning, - "[TMPRL1103] Attempted to upload payloads with size that exceeded the warning limit.", - ) - - @staticmethod - def _validate_limits( - payloads: Sequence[temporalio.api.common.v1.Payload], - error_limit: int | None, - error_message: str, - warning_limit: int, - warning_message: str, - ): - total_size = sum(payload.ByteSize() for payload in payloads) - - if error_limit and error_limit > 0 and total_size > error_limit: - raise _PayloadSizeError( - f"{error_message} Size: {total_size} bytes, Limit: {error_limit} bytes" - ) - - if warning_limit > 0 and total_size > warning_limit: - # TODO: Use a context aware logger to log extra information about workflow/activity/etc - warnings.warn( - f"{warning_message} Size: {total_size} bytes, Limit: {warning_limit} bytes", - PayloadSizeWarning, - ) - - -DefaultPayloadConverter.default_encoding_payload_converters = ( - BinaryNullPayloadConverter(), - BinaryPlainPayloadConverter(), - JSONProtoPayloadConverter(), - BinaryProtoPayloadConverter(), - JSONPlainPayloadConverter(), # JSON Plain needs to remain in last because it throws on unknown types -) - -DataConverter.default = DataConverter() - -PayloadConverter.default = DataConverter.default.payload_converter - -FailureConverter.default = DataConverter.default.failure_converter - - -def default() -> DataConverter: - """Default data converter. - - .. deprecated:: - Use :py:meth:`DataConverter.default` instead. - """ - return DataConverter.default - - -def encode_search_attributes( - attributes: ( - temporalio.common.SearchAttributes | temporalio.common.TypedSearchAttributes - ), - api: temporalio.api.common.v1.SearchAttributes, -) -> None: - """Convert search attributes into an API message. - - Args: - attributes: Search attributes to convert. The dictionary form of this is - DEPRECATED. - api: API message to set converted attributes on. - """ - if isinstance(attributes, temporalio.common.TypedSearchAttributes): - for typed_k, typed_v in attributes: - api.indexed_fields[typed_k.name].CopyFrom( - encode_typed_search_attribute_value(typed_k, typed_v) - ) - return - elif not attributes: - return - for k, v in attributes.items(): - api.indexed_fields[k].CopyFrom(encode_search_attribute_values(v)) - - -def encode_typed_search_attribute_value( - key: temporalio.common.SearchAttributeKey[ - temporalio.common.SearchAttributeValueType - ], - value: temporalio.common.SearchAttributeValue | None, -) -> temporalio.api.common.v1.Payload: - """Convert typed search attribute value into a payload. - - Args: - key: Key for the value. - value: Value to convert. - - Returns: - Payload for the value. - """ - # For server search attributes to work properly, we cannot set the metadata - # type when we set null - if value is None: - return default().payload_converter.to_payload(None) - if not isinstance(value, key.origin_value_type): - raise TypeError( - f"Value of type {value} not suitable for indexed value type {key.indexed_value_type}" - ) - # datetime needs to be in isoformat - if isinstance(value, datetime): - value = value.isoformat() - # We'll do an extra sanity check for keyword list and check every value - if isinstance(value, Sequence): - for v in value: - if not isinstance(v, str): - raise TypeError("All values of a keyword list must be strings") - # Convert value - payload = default().payload_converter.to_payload(value) - # Set metadata type - payload.metadata["type"] = key._metadata_type.encode() - return payload - - -def encode_search_attribute_values( - vals: temporalio.common.SearchAttributeValues, -) -> temporalio.api.common.v1.Payload: - """Convert search attribute values into a payload. - - .. deprecated:: - Use typed search attributes instead. - - Args: - vals: List of values to convert. - """ - if not isinstance(vals, list): - raise TypeError("Search attribute values must be lists") # type:ignore[reportUnreachable] - # Confirm all types are the same - val_type: type | None = None - # Convert dates to strings - safe_vals = [] - for v in vals: - if isinstance(v, datetime): - if v.tzinfo is None: - raise ValueError( - "Timezone must be present on all search attribute dates" - ) - v = v.isoformat() - elif not isinstance(v, (str, int, float, bool)): - raise TypeError( - f"Search attribute value of type {type(v).__name__} not one of str, int, float, bool, or datetime" - ) - elif val_type and type(v) is not val_type: - raise TypeError( - "Search attribute values must have the same type for the same key" - ) - elif not val_type: - val_type = type(v) - safe_vals.append(v) - return default().payload_converter.to_payloads([safe_vals])[0] - - -def _encode_maybe_typed_search_attributes( # type:ignore[reportUnusedFunction] - non_typed_attributes: temporalio.common.SearchAttributes | None, - typed_attributes: temporalio.common.TypedSearchAttributes | None, - api: temporalio.api.common.v1.SearchAttributes, -) -> None: - if non_typed_attributes: - if typed_attributes and typed_attributes.search_attributes: - raise ValueError( - "Cannot provide both deprecated search attributes and typed search attributes" - ) - encode_search_attributes(non_typed_attributes, api) - elif typed_attributes and typed_attributes.search_attributes: - encode_search_attributes(typed_attributes, api) - - -def _get_iso_datetime_parser() -> Callable[[str], datetime]: - """Isolates system version check and returns relevant datetime passer - - Returns: - A callable to parse date strings into datetimes. - """ - if sys.version_info >= (3, 11): - return datetime.fromisoformat # type:ignore[reportUnreachable] # noqa - else: - # Isolate import for py > 3.11, as dependency only installed for < 3.11 - return parser.isoparse # type:ignore[reportUnreachable] - - -def decode_search_attributes( - api: temporalio.api.common.v1.SearchAttributes, -) -> temporalio.common.SearchAttributes: - """Decode API search attributes to values. - - .. deprecated:: - Use typed search attributes instead. - - Args: - api: API message with search attribute values to convert. - - Returns: - Converted search attribute values (new mapping every time). - """ - conv = default().payload_converter - ret = {} - for k, v in api.indexed_fields.items(): - val = conv.from_payloads([v])[0] - # If a value did not come back as a list, make it a single-item list - if not isinstance(val, list): - val = [val] - # Convert each item to datetime if necessary - if v.metadata.get("type") == b"Datetime": - parser = _get_iso_datetime_parser() - val = [parser(v) for v in val] - ret[k] = val - return ret - - -def decode_typed_search_attributes( - api: temporalio.api.common.v1.SearchAttributes, -) -> temporalio.common.TypedSearchAttributes: - """Decode API search attributes to typed search attributes. - - Args: - api: API message with search attribute values to convert. - - Returns: - Typed search attribute collection (new object every time). - """ - conv = default().payload_converter - pairs: list[temporalio.common.SearchAttributePair] = [] - for k, v in api.indexed_fields.items(): - # We want the "type" metadata, but if it is not present or an unknown - # type, we will just ignore - metadata_type = v.metadata.get("type") - if not metadata_type: - continue - key = temporalio.common.SearchAttributeKey._from_metadata_type( - k, metadata_type.decode() - ) - if not key: - continue - val = conv.from_payload(v) - # If the value is a list but the type is not keyword list, pull out - # single item or consider this an invalid value and ignore - if ( - key.indexed_value_type - != temporalio.common.SearchAttributeIndexedValueType.KEYWORD_LIST - and isinstance(val, list) - ): - if len(val) != 1: - continue - val = val[0] - if ( - key.indexed_value_type - == temporalio.common.SearchAttributeIndexedValueType.DATETIME - ): - parser = _get_iso_datetime_parser() - # We will let this throw - val = parser(val) - # If the value isn't the right type, we need to ignore - if isinstance(val, key.origin_value_type): - pairs.append(temporalio.common.SearchAttributePair(key, val)) - return temporalio.common.TypedSearchAttributes(pairs) - - -def _decode_search_attribute_value( # type:ignore[reportUnusedFunction] - payload: temporalio.api.common.v1.Payload, -) -> temporalio.common.SearchAttributeValue: - val = default().payload_converter.from_payload(payload) - if isinstance(val, str) and payload.metadata.get("type") == b"Datetime": - val = _get_iso_datetime_parser()(val) - return val # type: ignore - - -def value_to_type( - hint: type, - value: Any, - custom_converters: Sequence[JSONTypeConverter] = [], -) -> Any: - """Convert a given value to the given type hint. - - This is used internally to convert a raw JSON loaded value to a specific - type hint. - - Args: - hint: Type hint to convert the value to. - value: Raw value (e.g. primitive, dict, or list) to convert from. - custom_converters: Set of custom converters to try before doing default - conversion. Converters are tried in order and the first value that - is not :py:attr:`JSONTypeConverter.Unhandled` will be returned from - this function instead of doing default behavior. - - Returns: - Converted value. - - Raises: - TypeError: Unable to convert to the given hint. - """ - # Try custom converters - for conv in custom_converters: - ret = conv.to_typed_value(hint, value) - if ret is not JSONTypeConverter.Unhandled: - return ret - - # Any or primitives - if hint is Any: - return value - elif hint is datetime: - if isinstance(value, str): - try: - return _get_iso_datetime_parser()(value) - except ValueError as err: - raise TypeError(f"Failed parsing datetime string: {value}") from err - elif isinstance(value, datetime): - return value - raise TypeError(f"Expected datetime or ISO8601 string, got {type(value)}") - elif hint is int or hint is float: - if not isinstance(value, (int, float)): - raise TypeError(f"Expected value to be int|float, was {type(value)}") - return hint(value) - elif hint is bool: - if not isinstance(value, bool): - raise TypeError(f"Expected value to be bool, was {type(value)}") - return bool(value) - elif hint is str: - if not isinstance(value, str): - raise TypeError(f"Expected value to be str, was {type(value)}") - return str(value) - elif hint is bytes: - if not isinstance(value, (str, bytes, list)): - raise TypeError(f"Expected value to be bytes, was {type(value)}") - # In some other SDKs, this is serialized as a base64 string, but in - # Python this is a numeric array. - return bytes(value) # type: ignore - elif hint is type(None): - if value is not None: - raise TypeError(f"Expected None, got value of type {type(value)}") - return None - - # NewType. Note we cannot simply check isinstance NewType here because it's - # only been a class since 3.10. Instead we'll just check for the presence - # of a supertype. - supertype = getattr(hint, "__supertype__", None) - if supertype: - return value_to_type(supertype, value, custom_converters) - - # Load origin for other checks - origin = getattr(hint, "__origin__", hint) - type_args: tuple = getattr(hint, "__args__", ()) - - # Literal - if origin is Literal or origin is typing_extensions.Literal: - if value not in type_args: - raise TypeError(f"Value {value} not in literal values {type_args}") - return value - - is_union = origin is typing.Union # type:ignore[reportDeprecated] - is_union = is_union or isinstance(origin, UnionType) - - # Union - if is_union: - # Try each one. Note, Optional is just a union w/ none. - for arg in type_args: - try: - return value_to_type(arg, value, custom_converters) - except Exception: - pass - raise TypeError(f"Failed converting to {hint} from {value}") - - # Mapping - if inspect.isclass(origin) and issubclass(origin, collections.abc.Mapping): - if not isinstance(value, collections.abc.Mapping): - raise TypeError(f"Expected {hint}, value was {type(value)}") - ret_dict = {} - # If there are required or optional keys that means we are a TypedDict - # and therefore can extract per-key types - per_key_types: dict[str, type] | None = None - if getattr(origin, "__required_keys__", None) or getattr( - origin, "__optional_keys__", None - ): - per_key_types = get_type_hints(origin) - key_type = ( - type_args[0] - if len(type_args) > 0 - and type_args[0] is not Any - and not isinstance(type_args[0], TypeVar) - else None - ) - value_type = ( - type_args[1] - if len(type_args) > 1 - and type_args[1] is not Any - and not isinstance(type_args[1], TypeVar) - else None - ) - # Convert each key/value - for key, value in value.items(): - this_value_type = value_type - if per_key_types: - # TODO(cretz): Strict mode would fail an unknown key - this_value_type = per_key_types.get(key) - - if key_type: - # This function is used only by JSONPlainPayloadConverter. When - # serializing to JSON, Python supports key types str, int, float, bool, - # and None, serializing all to string representations. We now attempt to - # use the provided type annotation to recover the original value with its - # original type. - try: - if isinstance(key, str): - if key_type is int or key_type is float: - key = key_type(key) - elif key_type is bool: - key = {"true": True, "false": False}[key] - elif key_type is type(None): - key = {"null": None}[key] - - if not isinstance(key_type, type) or not isinstance(key, key_type): - key = value_to_type(key_type, key, custom_converters) - except Exception as err: - raise TypeError( - f"Failed converting key {repr(key)} to type {key_type} in mapping {hint}" - ) from err - - if this_value_type: - try: - value = value_to_type(this_value_type, value, custom_converters) - except Exception as err: - raise TypeError( - f"Failed converting value for key {repr(key)} in mapping {hint}" - ) from err - ret_dict[key] = value - # If there are per-key types, it's a typed dict and we want to attempt - # instantiation to get its validation - if per_key_types: - ret_dict = hint(**ret_dict) - return ret_dict - - # Dataclass - if dataclasses.is_dataclass(hint): - if not isinstance(value, dict): - raise TypeError( - f"Cannot convert to dataclass {hint}, value is {type(value)} not dict" - ) - # Obtain dataclass fields and check that all dict fields are there and - # that no required fields are missing. Unknown fields are silently - # ignored. - fields = dataclasses.fields(hint) - field_hints = get_type_hints(hint) - field_values = {} - for field in fields: - field_value = value.get(field.name, dataclasses.MISSING) - # We do not check whether field is required here. Rather, we let the - # attempted instantiation of the dataclass raise if a field is - # missing - if field_value is not dataclasses.MISSING: - try: - field_values[field.name] = value_to_type( - field_hints[field.name], field_value, custom_converters - ) - except Exception as err: - raise TypeError( - f"Failed converting field {field.name} on dataclass {hint}" - ) from err - # Simply instantiate the dataclass. This will fail as expected when - # missing required fields. - # TODO(cretz): Want way to convert snake case to camel case? - return hint(**field_values) - - # Pydantic model instance - # Pydantic users should use Pydantic v2 with - # temporalio.contrib.pydantic.pydantic_data_converter, in which case a - # pydantic model instance will have been handled by the custom_converters at - # the start of this function. We retain the following for backwards - # compatibility with pydantic v1 users, but this is deprecated. - parse_obj_attr = inspect.getattr_static(hint, "parse_obj", None) - if isinstance(parse_obj_attr, classmethod) or isinstance( - parse_obj_attr, staticmethod - ): - if not isinstance(value, dict): - raise TypeError( - f"Cannot convert to {hint}, value is {type(value)} not dict" - ) - return getattr(hint, "parse_obj")(value) - - # IntEnum - if inspect.isclass(hint) and issubclass(hint, IntEnum): - if not isinstance(value, int): - raise TypeError( - f"Cannot convert to enum {hint}, value not an integer, value is {type(value)}" - ) - return hint(value) - - # StrEnum, available in 3.11+ - if sys.version_info >= (3, 11): - if inspect.isclass(hint) and issubclass(hint, StrEnum): # type:ignore[reportUnreachable] - if not isinstance(value, str): - raise TypeError( - f"Cannot convert to enum {hint}, value not a string, value is {type(value)}" - ) - return hint(value) - - # UUID - if inspect.isclass(hint) and issubclass(hint, uuid.UUID): - return hint(value) - - # Iterable. We intentionally put this last as it catches several others. - if inspect.isclass(origin) and issubclass(origin, collections.abc.Iterable): - if not isinstance(value, collections.abc.Iterable): - raise TypeError(f"Expected {hint}, value was {type(value)}") - ret_list = [] - # If there is no type arg, just return value as is - if not type_args or ( - len(type_args) == 1 - and (isinstance(type_args[0], TypeVar) or type_args[0] is Ellipsis) - ): - ret_list = list(value) - else: - # Otherwise convert - for i, item in enumerate(value): - # Non-tuples use first type arg, tuples use arg set or one - # before ellipsis if that's set - if origin is not tuple: - arg_type = type_args[0] - elif len(type_args) > i and type_args[i] is not Ellipsis: - arg_type = type_args[i] - elif type_args[-1] is Ellipsis: - # Ellipsis means use the second to last one - arg_type = type_args[-2] # type: ignore - else: - raise TypeError( - f"Type {hint} only expecting {len(type_args)} values, got at least {i + 1}" - ) - try: - ret_list.append(value_to_type(arg_type, item, custom_converters)) - except Exception as err: - raise TypeError(f"Failed converting {hint} index {i}") from err - # If tuple, set, or deque convert back to that type - if origin is tuple: - return tuple(ret_list) - elif origin is set: - return set(ret_list) - elif origin is collections.deque: - return collections.deque(ret_list) - return ret_list - - raise TypeError(f"Unserializable type during conversion: {hint}") diff --git a/temporalio/converter/__init__.py b/temporalio/converter/__init__.py new file mode 100644 index 000000000..d70bd6e76 --- /dev/null +++ b/temporalio/converter/__init__.py @@ -0,0 +1,81 @@ +"""Base converter and implementations for data conversion.""" + +from temporalio.converter._data_converter import ( + DataConverter, + default, +) +from temporalio.converter._failure_converter import ( + DefaultFailureConverter, + DefaultFailureConverterWithEncodedAttributes, + FailureConverter, +) +from temporalio.converter._payload_codec import PayloadCodec +from temporalio.converter._payload_converter import ( + AdvancedJSONEncoder, + BinaryNullPayloadConverter, + BinaryPlainPayloadConverter, + BinaryProtoPayloadConverter, + CompositePayloadConverter, + DefaultPayloadConverter, + EncodingPayloadConverter, + JSONPlainPayloadConverter, + JSONProtoPayloadConverter, + JSONTypeConverter, + PayloadConverter, + value_to_type, +) +from temporalio.converter._payload_limits import ( + PayloadLimitsConfig, + PayloadSizeWarning, +) +from temporalio.converter._search_attributes import ( + decode_search_attributes, + decode_typed_search_attributes, + encode_search_attribute_values, + encode_search_attributes, + encode_typed_search_attribute_value, +) +from temporalio.converter._serialization_context import ( + ActivitySerializationContext, + SerializationContext, + WithSerializationContext, + WorkflowSerializationContext, +) + +__all__ = [ + "ActivitySerializationContext", + "AdvancedJSONEncoder", + "BinaryNullPayloadConverter", + "BinaryPlainPayloadConverter", + "BinaryProtoPayloadConverter", + "CompositePayloadConverter", + "DataConverter", + "DefaultFailureConverter", + "DefaultFailureConverterWithEncodedAttributes", + "DefaultPayloadConverter", + "EncodingPayloadConverter", + "FailureConverter", + "JSONPlainPayloadConverter", + "JSONProtoPayloadConverter", + "JSONTypeConverter", + "PayloadCodec", + "PayloadConverter", + "PayloadLimitsConfig", + "PayloadSizeWarning", + "SerializationContext", + "WithSerializationContext", + "WorkflowSerializationContext", + "decode_search_attributes", + "decode_typed_search_attributes", + "default", + "encode_search_attribute_values", + "encode_search_attributes", + "encode_typed_search_attribute_value", + "value_to_type", +] + +DataConverter.default = DataConverter() + +PayloadConverter.default = DataConverter.default.payload_converter + +FailureConverter.default = DataConverter.default.failure_converter diff --git a/temporalio/converter/_data_converter.py b/temporalio/converter/_data_converter.py new file mode 100644 index 000000000..e9ac33158 --- /dev/null +++ b/temporalio/converter/_data_converter.py @@ -0,0 +1,325 @@ +"""DataConverter: the top-level data conversion orchestrator.""" + +from __future__ import annotations + +import dataclasses +import warnings +from collections.abc import Mapping, Sequence +from dataclasses import dataclass +from logging import getLogger +from typing import TYPE_CHECKING, Any, ClassVar + +from typing_extensions import Self + +import temporalio.api.common.v1 +import temporalio.api.failure.v1 +import temporalio.common +from temporalio.converter._failure_converter import ( + FailureConverter, +) +from temporalio.converter._payload_codec import ( + PayloadCodec, + _apply_to_failure_payloads, +) +from temporalio.converter._payload_converter import ( + PayloadConverter, +) +from temporalio.converter._payload_limits import ( + PayloadLimitsConfig, + PayloadSizeWarning, + _PayloadSizeError, + _ServerPayloadErrorLimits, +) +from temporalio.converter._serialization_context import ( + SerializationContext, + WithSerializationContext, +) + +# Import defaults from public API to avoid pydoctor cross-reference issues +if TYPE_CHECKING: + from temporalio.converter import DefaultFailureConverter, DefaultPayloadConverter +else: + # Import from private modules for runtime to avoid circular imports + from temporalio.converter._failure_converter import DefaultFailureConverter + from temporalio.converter._payload_converter import DefaultPayloadConverter + +logger = getLogger("temporalio.converter") + + +@dataclass(frozen=True) +class DataConverter(WithSerializationContext): + """Data converter for converting and encoding payloads to/from Python values. + + This combines :py:class:`PayloadConverter` which converts values with + :py:class:`PayloadCodec` which encodes bytes. + """ + + payload_converter_class: type[PayloadConverter] = DefaultPayloadConverter + """Class to instantiate for payload conversion.""" + + payload_codec: PayloadCodec | None = None + """Optional codec for encoding payload bytes.""" + + failure_converter_class: type[FailureConverter] = DefaultFailureConverter + """Class to instantiate for failure conversion.""" + + payload_converter: PayloadConverter = dataclasses.field(init=False) + """Payload converter created from the :py:attr:`payload_converter_class`.""" + + failure_converter: FailureConverter = dataclasses.field(init=False) + """Failure converter created from the :py:attr:`failure_converter_class`.""" + + payload_limits: PayloadLimitsConfig = PayloadLimitsConfig() + """Settings for payload size limits.""" + + default: ClassVar[DataConverter] + """Singleton default data converter.""" + + _payload_error_limits: _ServerPayloadErrorLimits | None = None + """Server-reported limits for payloads.""" + + def __post_init__(self) -> None: # noqa: D105 + object.__setattr__(self, "payload_converter", self.payload_converter_class()) + object.__setattr__(self, "failure_converter", self.failure_converter_class()) + + async def encode( + self, values: Sequence[Any] + ) -> list[temporalio.api.common.v1.Payload]: + """Encode values into payloads. + + First converts values to payloads then encodes payloads using codec. + + Args: + values: Values to be converted and encoded. + + Returns: + Converted and encoded payloads. Note, this does not have to be the + same number as values given, but must be at least one and cannot be + more than was given. + """ + payloads = self.payload_converter.to_payloads(values) + payloads = await self._encode_payload_sequence(payloads) + return payloads + + async def decode( + self, + payloads: Sequence[temporalio.api.common.v1.Payload], + type_hints: list[type] | None = None, + ) -> list[Any]: + """Decode payloads into values. + + First decodes payloads using codec then converts payloads to values. + + Args: + payloads: Payloads to be decoded and converted. + + Returns: + Decoded and converted values. + """ + payloads = await self._decode_payload_sequence(payloads) + return self.payload_converter.from_payloads(payloads, type_hints) + + async def encode_wrapper( + self, values: Sequence[Any] + ) -> temporalio.api.common.v1.Payloads: + """:py:meth:`encode` for the + :py:class:`temporalio.api.common.v1.Payloads` wrapper. + """ + return temporalio.api.common.v1.Payloads(payloads=(await self.encode(values))) + + async def decode_wrapper( + self, + payloads: temporalio.api.common.v1.Payloads | None, + type_hints: list[type] | None = None, + ) -> list[Any]: + """:py:meth:`decode` for the + :py:class:`temporalio.api.common.v1.Payloads` wrapper. + """ + if not payloads or not payloads.payloads: + return [] + return await self.decode(payloads.payloads, type_hints) + + async def encode_failure( + self, exception: BaseException, failure: temporalio.api.failure.v1.Failure + ) -> None: + """Convert and encode failure.""" + self.failure_converter.to_failure(exception, self.payload_converter, failure) + await _apply_to_failure_payloads(failure, self._encode_payloads) + + async def decode_failure( + self, failure: temporalio.api.failure.v1.Failure + ) -> BaseException: + """Decode and convert failure.""" + await _apply_to_failure_payloads(failure, self._decode_payloads) + return self.failure_converter.from_failure(failure, self.payload_converter) + + def with_context(self, context: SerializationContext) -> Self: + """Return an instance with context set on the component converters.""" + payload_converter = self.payload_converter + payload_codec = self.payload_codec + failure_converter = self.failure_converter + if isinstance(payload_converter, WithSerializationContext): + payload_converter = payload_converter.with_context(context) + if isinstance(payload_codec, WithSerializationContext): + payload_codec = payload_codec.with_context(context) + if isinstance(failure_converter, WithSerializationContext): + failure_converter = failure_converter.with_context(context) + if all( + new is orig + for new, orig in [ + (payload_converter, self.payload_converter), + (payload_codec, self.payload_codec), + (failure_converter, self.failure_converter), + ] + ): + return self + cloned = dataclasses.replace(self) + object.__setattr__(cloned, "payload_converter", payload_converter) + object.__setattr__(cloned, "payload_codec", payload_codec) + object.__setattr__(cloned, "failure_converter", failure_converter) + return cloned + + def _with_payload_error_limits( + self, limits: _ServerPayloadErrorLimits | None + ) -> DataConverter: + return dataclasses.replace(self, _payload_error_limits=limits) + + async def _decode_memo( + self, + source: temporalio.api.common.v1.Memo, + ) -> Mapping[str, Any]: + mapping: dict[str, Any] = {} + for k, v in source.fields.items(): + mapping[k] = (await self.decode([v]))[0] + return mapping + + async def _decode_memo_field( + self, + source: temporalio.api.common.v1.Memo, + key: str, + default: Any, + type_hint: type | None, + ) -> dict[str, Any]: + payload = source.fields.get(key) + if not payload: + if default is temporalio.common._arg_unset: + raise KeyError(f"Memo does not have a value for key {key}") + return default + return (await self.decode([payload], [type_hint] if type_hint else None))[0] + + async def _encode_memo( + self, source: Mapping[str, Any] + ) -> temporalio.api.common.v1.Memo: + memo = temporalio.api.common.v1.Memo() + await self._encode_memo_existing(source, memo) + return memo + + async def _encode_memo_existing( + self, source: Mapping[str, Any], memo: temporalio.api.common.v1.Memo + ): + for k, v in source.items(): + payload = v + if not isinstance(v, temporalio.api.common.v1.Payload): + payload = (await self.encode([v]))[0] + memo.fields[k].CopyFrom(payload) + # Memos have their field payloads validated all together in one unit + DataConverter._validate_limits( + list(memo.fields.values()), + self._payload_error_limits.memo_size_error + if self._payload_error_limits + else None, + "[TMPRL1103] Attempted to upload memo with size that exceeded the error limit.", + self.payload_limits.memo_size_warning, + "[TMPRL1103] Attempted to upload memo with size that exceeded the warning limit.", + ) + + async def _encode_payload( + self, payload: temporalio.api.common.v1.Payload + ) -> temporalio.api.common.v1.Payload: + if self.payload_codec: + payload = (await self.payload_codec.encode([payload]))[0] + self._validate_payload_limits([payload]) + return payload + + async def _encode_payloads(self, payloads: temporalio.api.common.v1.Payloads): + if self.payload_codec: + await self.payload_codec.encode_wrapper(payloads) + self._validate_payload_limits(payloads.payloads) + + async def _encode_payload_sequence( + self, payloads: Sequence[temporalio.api.common.v1.Payload] + ) -> list[temporalio.api.common.v1.Payload]: + encoded_payloads = list(payloads) + if self.payload_codec: + encoded_payloads = await self.payload_codec.encode(encoded_payloads) + self._validate_payload_limits(encoded_payloads) + return encoded_payloads + + async def _decode_payload( + self, payload: temporalio.api.common.v1.Payload + ) -> temporalio.api.common.v1.Payload: + if self.payload_codec: + payload = (await self.payload_codec.decode([payload]))[0] + return payload + + async def _decode_payloads(self, payloads: temporalio.api.common.v1.Payloads): + if self.payload_codec: + await self.payload_codec.decode_wrapper(payloads) + + async def _decode_payload_sequence( + self, payloads: Sequence[temporalio.api.common.v1.Payload] + ) -> list[temporalio.api.common.v1.Payload]: + if not self.payload_codec: + return list(payloads) + return await self.payload_codec.decode(payloads) + + # Temporary shortcircuit detection while the _decode_* methods may no-op if + # a payload codec is not configured. Remove once those paths have more to them. + @property + def _decode_payload_has_effect(self) -> bool: + return self.payload_codec is not None + + def _validate_payload_limits( + self, + payloads: Sequence[temporalio.api.common.v1.Payload], + ): + DataConverter._validate_limits( + payloads, + self._payload_error_limits.payload_size_error + if self._payload_error_limits + else None, + "[TMPRL1103] Attempted to upload payloads with size that exceeded the error limit.", + self.payload_limits.payload_size_warning, + "[TMPRL1103] Attempted to upload payloads with size that exceeded the warning limit.", + ) + + @staticmethod + def _validate_limits( + payloads: Sequence[temporalio.api.common.v1.Payload], + error_limit: int | None, + error_message: str, + warning_limit: int, + warning_message: str, + ): + total_size = sum(payload.ByteSize() for payload in payloads) + + if error_limit and error_limit > 0 and total_size > error_limit: + raise _PayloadSizeError( + f"{error_message} Size: {total_size} bytes, Limit: {error_limit} bytes" + ) + + if warning_limit > 0 and total_size > warning_limit: + # TODO: Use a context aware logger to log extra information about workflow/activity/etc + warnings.warn( + f"{warning_message} Size: {total_size} bytes, Limit: {warning_limit} bytes", + PayloadSizeWarning, + ) + + +def default() -> DataConverter: + """Default data converter. + + .. deprecated:: + Use :py:meth:`DataConverter.default` instead. + """ + return DataConverter.default diff --git a/temporalio/converter/_failure_converter.py b/temporalio/converter/_failure_converter.py new file mode 100644 index 000000000..5b2bf2fdb --- /dev/null +++ b/temporalio/converter/_failure_converter.py @@ -0,0 +1,468 @@ +"""Failure converters for converting exceptions to/from Temporal Failure protos.""" + +from __future__ import annotations + +import dataclasses +import json +import traceback +from abc import ABC, abstractmethod +from logging import getLogger +from typing import Any, ClassVar + +import google.protobuf.json_format +import nexusrpc + +import temporalio.api.common.v1 +import temporalio.api.enums.v1 +import temporalio.api.failure.v1 +import temporalio.exceptions +from temporalio.converter._payload_converter import PayloadConverter +from temporalio.converter._payload_limits import _PayloadSizeError + +logger = getLogger("temporalio.converter") + +_TEMPORAL_FAILURE_PROTO_TYPE = "temporal.api.failure.v1.Failure" + + +class FailureConverter(ABC): + """Base failure converter to/from errors. + + Note, for workflow exceptions, :py:attr:`to_failure` is only invoked if the + exception is an instance of :py:class:`temporalio.exceptions.FailureError`. + Users should extend :py:class:`temporalio.exceptions.ApplicationError` if + they want a custom workflow exception to work with this class. + """ + + default: ClassVar[FailureConverter] + """Default failure converter.""" + + @abstractmethod + def to_failure( + self, + exception: BaseException, + payload_converter: PayloadConverter, + failure: temporalio.api.failure.v1.Failure, + ) -> None: + """Convert the given exception to a Temporal failure. + + Users should make sure not to alter the ``exception`` input. + + Args: + exception: The exception to convert. + payload_converter: The payload converter to use if needed. + failure: The failure to update with error information. + """ + raise NotImplementedError + + @abstractmethod + def from_failure( + self, + failure: temporalio.api.failure.v1.Failure, + payload_converter: PayloadConverter, + ) -> BaseException: + """Convert the given Temporal failure to an exception. + + Users should make sure not to alter the ``failure`` input. + + Args: + failure: The failure to convert. + payload_converter: The payload converter to use if needed. + + Returns: + Converted error. + """ + raise NotImplementedError + + +class DefaultFailureConverter(FailureConverter): + """Default failure converter. + + A singleton instance of this is available at + :py:attr:`FailureConverter.default`. + """ + + def __init__(self, *, encode_common_attributes: bool = False) -> None: + """Create the default failure converter. + + Args: + encode_common_attributes: If ``True``, the message and stack trace + of the failure will be moved into the encoded attribute section + of the failure which can be encoded with a codec. + """ + super().__init__() + self._encode_common_attributes = encode_common_attributes + + def to_failure( + self, + exception: BaseException, + payload_converter: PayloadConverter, + failure: temporalio.api.failure.v1.Failure, + ) -> None: + """See base class.""" + # If already a failure error, use that + if isinstance(exception, temporalio.exceptions.FailureError): + self._error_to_failure(exception, payload_converter, failure) + elif isinstance(exception, nexusrpc.HandlerError): + self._nexus_handler_error_to_failure(exception, payload_converter, failure) + else: + # Convert to failure error + failure_error = temporalio.exceptions.ApplicationError( + str(exception), + type="PayloadSizeError" + if isinstance(exception, _PayloadSizeError) + else exception.__class__.__name__, + ) + failure_error.__traceback__ = exception.__traceback__ + failure_error.__cause__ = exception.__cause__ + self._error_to_failure(failure_error, payload_converter, failure) + # Encode common attributes if requested + if self._encode_common_attributes: + # Move message and stack trace to encoded attribute payload + failure.encoded_attributes.CopyFrom( + payload_converter.to_payloads( + [{"message": failure.message, "stack_trace": failure.stack_trace}] + )[0] + ) + failure.message = "Encoded failure" + failure.stack_trace = "" + + def _error_to_failure( + self, + error: temporalio.exceptions.FailureError, + payload_converter: PayloadConverter, + failure: temporalio.api.failure.v1.Failure, + ) -> None: + # If there is an underlying proto already, just use that + if error.failure: + failure.CopyFrom(error.failure) + return + + # Set message, stack, and cause. Obtaining cause follows rules from + # https://docs.python.org/3/library/exceptions.html#exception-context + failure.message = error.message + if error.__traceback__: + failure.stack_trace = "\n".join(traceback.format_tb(error.__traceback__)) + if error.__cause__: + self.to_failure(error.__cause__, payload_converter, failure.cause) + elif not error.__suppress_context__ and error.__context__: + self.to_failure(error.__context__, payload_converter, failure.cause) + + # Set specific subclass values + if isinstance(error, temporalio.exceptions.ApplicationError): + failure.application_failure_info.SetInParent() + if error.type: + failure.application_failure_info.type = error.type + failure.application_failure_info.non_retryable = error.non_retryable + if error.details: + failure.application_failure_info.details.CopyFrom( + payload_converter.to_payloads_wrapper(error.details) + ) + if error.next_retry_delay: + failure.application_failure_info.next_retry_delay.FromTimedelta( + error.next_retry_delay + ) + if error.category: + failure.application_failure_info.category = ( + temporalio.api.enums.v1.ApplicationErrorCategory.ValueType( + error.category + ) + ) + elif isinstance(error, temporalio.exceptions.TimeoutError): + failure.timeout_failure_info.SetInParent() + failure.timeout_failure_info.timeout_type = ( + temporalio.api.enums.v1.TimeoutType.ValueType(error.type or 0) + ) + if error.last_heartbeat_details: + failure.timeout_failure_info.last_heartbeat_details.CopyFrom( + payload_converter.to_payloads_wrapper(error.last_heartbeat_details) + ) + elif isinstance(error, temporalio.exceptions.CancelledError): + failure.canceled_failure_info.SetInParent() + if error.details: + failure.canceled_failure_info.details.CopyFrom( + payload_converter.to_payloads_wrapper(error.details) + ) + elif isinstance(error, temporalio.exceptions.TerminatedError): + failure.terminated_failure_info.SetInParent() + elif isinstance(error, temporalio.exceptions.ServerError): + failure.server_failure_info.SetInParent() + failure.server_failure_info.non_retryable = error.non_retryable + elif isinstance(error, temporalio.exceptions.ActivityError): + failure.activity_failure_info.SetInParent() + failure.activity_failure_info.scheduled_event_id = error.scheduled_event_id + failure.activity_failure_info.started_event_id = error.started_event_id + failure.activity_failure_info.identity = error.identity + failure.activity_failure_info.activity_type.name = error.activity_type + failure.activity_failure_info.activity_id = error.activity_id + failure.activity_failure_info.retry_state = ( + temporalio.api.enums.v1.RetryState.ValueType(error.retry_state or 0) + ) + elif isinstance(error, temporalio.exceptions.ChildWorkflowError): + failure.child_workflow_execution_failure_info.SetInParent() + failure.child_workflow_execution_failure_info.namespace = error.namespace + failure.child_workflow_execution_failure_info.workflow_execution.workflow_id = error.workflow_id + failure.child_workflow_execution_failure_info.workflow_execution.run_id = ( + error.run_id + ) + failure.child_workflow_execution_failure_info.workflow_type.name = ( + error.workflow_type + ) + failure.child_workflow_execution_failure_info.initiated_event_id = ( + error.initiated_event_id + ) + failure.child_workflow_execution_failure_info.started_event_id = ( + error.started_event_id + ) + failure.child_workflow_execution_failure_info.retry_state = ( + temporalio.api.enums.v1.RetryState.ValueType(error.retry_state or 0) + ) + elif isinstance(error, temporalio.exceptions.NexusOperationError): + failure.nexus_operation_execution_failure_info.SetInParent() + failure.nexus_operation_execution_failure_info.scheduled_event_id = ( + error.scheduled_event_id + ) + failure.nexus_operation_execution_failure_info.endpoint = error.endpoint + failure.nexus_operation_execution_failure_info.service = error.service + failure.nexus_operation_execution_failure_info.operation = error.operation + failure.nexus_operation_execution_failure_info.operation_token = ( + error.operation_token + ) + + def _nexus_handler_error_to_failure( + self, + error: nexusrpc.HandlerError, + payload_converter: PayloadConverter, + failure: temporalio.api.failure.v1.Failure, + ) -> None: + if error.original_failure: + self._nexus_failure_to_temporal_failure( + error.original_failure, True, failure + ) + else: + failure.message = error.message + if stack_trace := error.stack_trace: + failure.stack_trace = stack_trace + elif tb := error.__traceback__: + failure.stack_trace = "\n".join(traceback.format_tb(tb)) + if error.__cause__: + self.to_failure(error.__cause__, payload_converter, failure.cause) + failure.nexus_handler_failure_info.SetInParent() + failure.nexus_handler_failure_info.type = error.type.name + failure.nexus_handler_failure_info.retry_behavior = temporalio.api.enums.v1.NexusHandlerErrorRetryBehavior.ValueType( + temporalio.api.enums.v1.NexusHandlerErrorRetryBehavior.NEXUS_HANDLER_ERROR_RETRY_BEHAVIOR_RETRYABLE + if error.retryable_override is True + else temporalio.api.enums.v1.NexusHandlerErrorRetryBehavior.NEXUS_HANDLER_ERROR_RETRY_BEHAVIOR_NON_RETRYABLE + if error.retryable_override is False + else temporalio.api.enums.v1.NexusHandlerErrorRetryBehavior.NEXUS_HANDLER_ERROR_RETRY_BEHAVIOR_UNSPECIFIED + ) + + def _temporal_failure_to_nexus_failure( + self, failure: temporalio.api.failure.v1.Failure + ) -> nexusrpc.Failure: + message, failure.message = failure.message, "" + stack_trace, failure.stack_trace = failure.stack_trace, "" + failure_dict = google.protobuf.json_format.MessageToDict(failure) + failure.message = message + failure.stack_trace = stack_trace + return nexusrpc.Failure( + message=message, + stack_trace=stack_trace, + metadata={ + "type": _TEMPORAL_FAILURE_PROTO_TYPE, + }, + details=failure_dict, + ) + + def _nexus_failure_to_temporal_failure( + self, + failure: nexusrpc.Failure, + retryable: bool, + temporal_failure: temporalio.api.failure.v1.Failure, + ) -> None: + if ( + failure.metadata + and failure.metadata.get("type") == _TEMPORAL_FAILURE_PROTO_TYPE + ): + google.protobuf.json_format.ParseDict(failure.details, temporal_failure) + else: + temporal_failure.application_failure_info.SetInParent() + temporal_failure.application_failure_info.type = "NexusFailure" + temporal_failure.application_failure_info.non_retryable = not retryable + temporal_failure.application_failure_info.details.SetInParent() + temporal_failure.application_failure_info.details.payloads.append( + temporalio.api.common.v1.Payload( + metadata={"encoding": b"json/plain"}, + data=json.dumps( + dataclasses.replace(failure, message=""), separators=(",", ":") + ).encode("utf-8"), + ) + ) + + temporal_failure.message = failure.message + temporal_failure.stack_trace = failure.stack_trace or "" + + def from_failure( + self, + failure: temporalio.api.failure.v1.Failure, + payload_converter: PayloadConverter, + ) -> BaseException: + """See base class.""" + # If encoded attributes are present and have the fields we expect, + # extract them + if failure.HasField("encoded_attributes"): + # Clone the failure to not mutate the incoming failure + new_failure = temporalio.api.failure.v1.Failure() + new_failure.CopyFrom(failure) + failure = new_failure + try: + encoded_attributes: dict[str, Any] = payload_converter.from_payloads( + [failure.encoded_attributes] + )[0] + if isinstance(encoded_attributes, dict): + message = encoded_attributes.get("message") + if isinstance(message, str): + failure.message = message + stack_trace = encoded_attributes.get("stack_trace") + if isinstance(stack_trace, str): + failure.stack_trace = stack_trace + except: + pass + + err: temporalio.exceptions.FailureError | nexusrpc.HandlerError + match failure.WhichOneof("failure_info"): + case "application_failure_info": + app_info = failure.application_failure_info + err = temporalio.exceptions.ApplicationError( + failure.message or "Application error", + *payload_converter.from_payloads_wrapper(app_info.details), + type=app_info.type or None, + non_retryable=app_info.non_retryable, + next_retry_delay=app_info.next_retry_delay.ToTimedelta(), + category=temporalio.exceptions.ApplicationErrorCategory( + int(app_info.category) + ), + ) + + case "timeout_failure_info": + timeout_info = failure.timeout_failure_info + err = temporalio.exceptions.TimeoutError( + failure.message or "Timeout", + type=temporalio.exceptions.TimeoutType( + int(timeout_info.timeout_type) + ) + if timeout_info.timeout_type + else None, + last_heartbeat_details=payload_converter.from_payloads_wrapper( + timeout_info.last_heartbeat_details + ), + ) + + case "canceled_failure_info": + cancel_info = failure.canceled_failure_info + err = temporalio.exceptions.CancelledError( + failure.message or "Cancelled", + *payload_converter.from_payloads_wrapper(cancel_info.details), + ) + case "terminated_failure_info": + err = temporalio.exceptions.TerminatedError( + failure.message or "Terminated" + ) + + case "server_failure_info": + server_info = failure.server_failure_info + err = temporalio.exceptions.ServerError( + failure.message or "Server error", + non_retryable=server_info.non_retryable, + ) + + case "activity_failure_info": + act_info = failure.activity_failure_info + err = temporalio.exceptions.ActivityError( + failure.message or "Activity error", + scheduled_event_id=act_info.scheduled_event_id, + started_event_id=act_info.started_event_id, + identity=act_info.identity, + activity_type=act_info.activity_type.name, + activity_id=act_info.activity_id, + retry_state=temporalio.exceptions.RetryState( + int(act_info.retry_state) + ) + if act_info.retry_state + else None, + ) + + case "child_workflow_execution_failure_info": + child_info = failure.child_workflow_execution_failure_info + err = temporalio.exceptions.ChildWorkflowError( + failure.message or "Child workflow error", + namespace=child_info.namespace, + workflow_id=child_info.workflow_execution.workflow_id, + run_id=child_info.workflow_execution.run_id, + workflow_type=child_info.workflow_type.name, + initiated_event_id=child_info.initiated_event_id, + started_event_id=child_info.started_event_id, + retry_state=temporalio.exceptions.RetryState( + int(child_info.retry_state) + ) + if child_info.retry_state + else None, + ) + + case "nexus_handler_failure_info": + nexus_handler_failure_info = failure.nexus_handler_failure_info + try: + _type = nexusrpc.HandlerErrorType[nexus_handler_failure_info.type] + except KeyError: + logger.warning( + f"Unknown Nexus HandlerErrorType: {nexus_handler_failure_info.type}" + ) + _type = nexusrpc.HandlerErrorType.INTERNAL + + retryable_override: bool | None + match nexus_handler_failure_info.retry_behavior: + case temporalio.api.enums.v1.NexusHandlerErrorRetryBehavior.NEXUS_HANDLER_ERROR_RETRY_BEHAVIOR_RETRYABLE: + retryable_override = True + case temporalio.api.enums.v1.NexusHandlerErrorRetryBehavior.NEXUS_HANDLER_ERROR_RETRY_BEHAVIOR_NON_RETRYABLE: + retryable_override = False + case _: + retryable_override = None + + err = nexusrpc.HandlerError( + failure.message or "Nexus handler error", + type=_type, + retryable_override=retryable_override, + stack_trace=failure.stack_trace if failure.stack_trace else None, + original_failure=self._temporal_failure_to_nexus_failure(failure), + ) + + case "nexus_operation_execution_failure_info": + nexus_op_failure_info = failure.nexus_operation_execution_failure_info + err = temporalio.exceptions.NexusOperationError( + failure.message or "Nexus operation error", + scheduled_event_id=nexus_op_failure_info.scheduled_event_id, + endpoint=nexus_op_failure_info.endpoint, + service=nexus_op_failure_info.service, + operation=nexus_op_failure_info.operation, + operation_token=nexus_op_failure_info.operation_token, + ) + + case "reset_workflow_failure_info" | None: + err = temporalio.exceptions.FailureError( + failure.message or "Failure error", + ) + + if isinstance(err, temporalio.exceptions.FailureError): + err._failure = failure + if failure.HasField("cause"): + err.__cause__ = self.from_failure(failure.cause, payload_converter) + return err + + +class DefaultFailureConverterWithEncodedAttributes(DefaultFailureConverter): + """Implementation of :py:class:`DefaultFailureConverter` which moves message + and stack trace to encoded attributes subject to a codec. + """ + + def __init__(self) -> None: + """Create a default failure converter with encoded attributes.""" + super().__init__(encode_common_attributes=True) diff --git a/temporalio/converter/_payload_codec.py b/temporalio/converter/_payload_codec.py new file mode 100644 index 000000000..93f689509 --- /dev/null +++ b/temporalio/converter/_payload_codec.py @@ -0,0 +1,115 @@ +"""PayloadCodec and failure payload traversal.""" + +from __future__ import annotations + +from abc import ABC, abstractmethod +from collections.abc import Awaitable, Callable, Sequence + +import temporalio.api.common.v1 +import temporalio.api.failure.v1 + + +class PayloadCodec(ABC): + """Codec for encoding/decoding to/from bytes. + + Commonly used for compression or encryption. + """ + + @abstractmethod + async def encode( + self, payloads: Sequence[temporalio.api.common.v1.Payload] + ) -> list[temporalio.api.common.v1.Payload]: + """Encode the given payloads. + + Args: + payloads: Payloads to encode. This value should not be mutated. + + Returns: + Encoded payloads. Note, this does not have to be the same number as + payloads given, but must be at least one and cannot be more than was + given. + """ + raise NotImplementedError + + @abstractmethod + async def decode( + self, payloads: Sequence[temporalio.api.common.v1.Payload] + ) -> list[temporalio.api.common.v1.Payload]: + """Decode the given payloads. + + Args: + payloads: Payloads to decode. This value should not be mutated. + + Returns: + Decoded payloads. Note, this does not have to be the same number as + payloads given, but must be at least one and cannot be more than was + given. + """ + raise NotImplementedError + + async def encode_wrapper(self, payloads: temporalio.api.common.v1.Payloads) -> None: + """:py:meth:`encode` for the + :py:class:`temporalio.api.common.v1.Payloads` wrapper. + + This replaces the payloads within the wrapper. + """ + new_payloads = await self.encode(payloads.payloads) + del payloads.payloads[:] + # TODO(cretz): Copy too expensive? + payloads.payloads.extend(new_payloads) + + async def decode_wrapper(self, payloads: temporalio.api.common.v1.Payloads) -> None: + """:py:meth:`decode` for the + :py:class:`temporalio.api.common.v1.Payloads` wrapper. + + This replaces the payloads within. + """ + new_payloads = await self.decode(payloads.payloads) + del payloads.payloads[:] + # TODO(cretz): Copy too expensive? + payloads.payloads.extend(new_payloads) + + async def encode_failure(self, failure: temporalio.api.failure.v1.Failure) -> None: + """Encode payloads of a failure. Intended as a helper method, not for overriding. + It is not guaranteed that all failures will be encoded with this method rather + than encoding the underlying payloads. + """ + await _apply_to_failure_payloads(failure, self.encode_wrapper) + + async def decode_failure(self, failure: temporalio.api.failure.v1.Failure) -> None: + """Decode payloads of a failure. Intended as a helper method, not for overriding. + It is not guaranteed that all failures will be decoded with this method rather + than decoding the underlying payloads. + """ + await _apply_to_failure_payloads(failure, self.decode_wrapper) + + +async def _apply_to_failure_payloads( + failure: temporalio.api.failure.v1.Failure, + cb: Callable[[temporalio.api.common.v1.Payloads], Awaitable[None]], +) -> None: + if failure.HasField("encoded_attributes"): + # Wrap in payloads and merge back + payloads = temporalio.api.common.v1.Payloads( + payloads=[failure.encoded_attributes] + ) + await cb(payloads) + failure.encoded_attributes.CopyFrom(payloads.payloads[0]) + if failure.HasField( + "application_failure_info" + ) and failure.application_failure_info.HasField("details"): + await cb(failure.application_failure_info.details) + elif failure.HasField( + "timeout_failure_info" + ) and failure.timeout_failure_info.HasField("last_heartbeat_details"): + await cb(failure.timeout_failure_info.last_heartbeat_details) + elif failure.HasField( + "canceled_failure_info" + ) and failure.canceled_failure_info.HasField("details"): + await cb(failure.canceled_failure_info.details) + elif failure.HasField( + "reset_workflow_failure_info" + ) and failure.reset_workflow_failure_info.HasField("last_heartbeat_details"): + await cb(failure.reset_workflow_failure_info.last_heartbeat_details) + if failure.HasField("cause"): + await _apply_to_failure_payloads(failure.cause, cb) diff --git a/temporalio/converter/_payload_converter.py b/temporalio/converter/_payload_converter.py new file mode 100644 index 000000000..d2effc9d1 --- /dev/null +++ b/temporalio/converter/_payload_converter.py @@ -0,0 +1,951 @@ +"""Payload converter types and implementations for data conversion.""" + +from __future__ import annotations + +import collections +import collections.abc +import dataclasses +import functools +import inspect +import json +import sys +import typing +import uuid +import warnings +from abc import ABC, abstractmethod +from collections.abc import Callable, Mapping, Sequence +from datetime import datetime +from enum import IntEnum +from itertools import zip_longest +from types import UnionType +from typing import ( + Any, + ClassVar, + Literal, + NewType, + TypeVar, + get_type_hints, + overload, +) + +import google.protobuf.json_format +import google.protobuf.message +import google.protobuf.symbol_database +import typing_extensions +from typing_extensions import Self + +import temporalio.api.common.v1 +import temporalio.common +import temporalio.types + +if sys.version_info < (3, 11): + # Python's datetime.fromisoformat doesn't support certain formats pre-3.11 + from dateutil import parser # type: ignore +# StrEnum is available in 3.11+ +if sys.version_info >= (3, 11): + from enum import StrEnum # type: ignore[reportUnreachable] + +from temporalio.converter._serialization_context import ( + SerializationContext, + WithSerializationContext, +) + +_sym_db = google.protobuf.symbol_database.Default() + + +class PayloadConverter(ABC): + """Base payload converter to/from multiple payloads/values.""" + + default: ClassVar[PayloadConverter] + """Default payload converter.""" + + @abstractmethod + def to_payloads( + self, values: Sequence[Any] + ) -> list[temporalio.api.common.v1.Payload]: + """Encode values into payloads. + + Implementers are expected to just return the payload for + :py:class:`temporalio.common.RawValue`. + + Args: + values: Values to be converted. + + Returns: + Converted payloads. Note, this does not have to be the same number + as values given, but must be at least one and cannot be more than + was given. + + Raises: + Exception: Any issue during conversion. + """ + raise NotImplementedError + + @abstractmethod + def from_payloads( + self, + payloads: Sequence[temporalio.api.common.v1.Payload], + type_hints: list[type] | None = None, + ) -> list[Any]: + """Decode payloads into values. + + Implementers are expected to treat a type hint of + :py:class:`temporalio.common.RawValue` as just the raw value. + + Args: + payloads: Payloads to convert to Python values. + type_hints: Types that are expected if any. This may not have any + types if there are no annotations on the target. If this is + present, it must have the exact same length as payloads even if + the values are just "object". + + Returns: + Collection of Python values. Note, this does not have to be the same + number as values given, but at least one must be present. + + Raises: + Exception: Any issue during conversion. + """ + raise NotImplementedError + + def to_payloads_wrapper( + self, values: Sequence[Any] + ) -> temporalio.api.common.v1.Payloads: + """:py:meth:`to_payloads` for the + :py:class:`temporalio.api.common.v1.Payloads` wrapper. + """ + return temporalio.api.common.v1.Payloads(payloads=self.to_payloads(values)) + + def from_payloads_wrapper( + self, payloads: temporalio.api.common.v1.Payloads | None + ) -> list[Any]: + """:py:meth:`from_payloads` for the + :py:class:`temporalio.api.common.v1.Payloads` wrapper. + """ + if not payloads or not payloads.payloads: + return [] + return self.from_payloads(payloads.payloads) + + def to_payload(self, value: Any) -> temporalio.api.common.v1.Payload: + """Convert a single value to a payload. + + This is a shortcut for :py:meth:`to_payloads` with a single-item list + and result. + + Args: + value: Value to convert to a single payload. + + Returns: + Single converted payload. + """ + return self.to_payloads([value])[0] + + @overload + def from_payload(self, payload: temporalio.api.common.v1.Payload) -> Any: ... + + @overload + def from_payload( + self, + payload: temporalio.api.common.v1.Payload, + type_hint: type[temporalio.types.AnyType], + ) -> temporalio.types.AnyType: ... + + def from_payload( + self, + payload: temporalio.api.common.v1.Payload, + type_hint: type | None = None, + ) -> Any: + """Convert a single payload to a value. + + This is a shortcut for :py:meth:`from_payloads` with a single-item list + and result. + + Args: + payload: Payload to convert to value. + type_hint: Optional type hint to say which type to convert to. + + Returns: + Single converted value. + """ + return self.from_payloads([payload], [type_hint] if type_hint else None)[0] + + +class EncodingPayloadConverter(ABC): + """Base converter to/from single payload/value with a known encoding for use in CompositePayloadConverter.""" + + @property + @abstractmethod + def encoding(self) -> str: + """Encoding for the payload this converter works with.""" + raise NotImplementedError + + @abstractmethod + def to_payload(self, value: Any) -> temporalio.api.common.v1.Payload | None: + """Encode a single value to a payload or None. + + Args: + value: Value to be converted. + + Returns: + Payload of the value or None if unable to convert. + + Raises: + TypeError: Value is not the expected type. + ValueError: Value is of the expected type but otherwise incorrect. + RuntimeError: General error during encoding. + """ + raise NotImplementedError + + @abstractmethod + def from_payload( + self, + payload: temporalio.api.common.v1.Payload, + type_hint: type | None = None, + ) -> Any: + """Decode a single payload to a Python value or raise exception. + + Args: + payload: Payload to convert to Python value. + type_hint: Type that is expected if any. This may not have a type if + there are no annotations on the target. + + Return: + The decoded value from the payload. Since the encoding is checked by + the caller, this should raise an exception if the payload cannot be + converted. + + Raises: + RuntimeError: General error during decoding. + """ + raise NotImplementedError + + +class CompositePayloadConverter(PayloadConverter, WithSerializationContext): + """Composite payload converter that delegates to a list of encoding payload converters. + + Encoding/decoding are attempted on each payload converter successively until + it succeeds. + + Attributes: + converters: List of payload converters to delegate to, in order. + """ + + converters: Mapping[bytes, EncodingPayloadConverter] + + def __init__(self, *converters: EncodingPayloadConverter) -> None: + """Initializes the data converter. + + Args: + converters: Payload converters to delegate to, in order. + """ + self._set_converters(*converters) + + def _set_converters(self, *converters: EncodingPayloadConverter) -> None: + self.converters = {c.encoding.encode(): c for c in converters} + + def to_payloads( + self, values: Sequence[Any] + ) -> list[temporalio.api.common.v1.Payload]: + """Encode values trying each converter. + + See base class. Always returns the same number of payloads as values. + + Raises: + RuntimeError: No known converter + """ + payloads = [] + for index, value in enumerate(values): + # We intentionally attempt these serially just in case a stateful + # converter may rely on the previous values + payload = None + # RawValue should just pass through + if isinstance(value, temporalio.common.RawValue): + payload = value.payload + else: + for converter in self.converters.values(): + payload = converter.to_payload(value) + if payload is not None: + break + if payload is None: + raise RuntimeError( + f"Value at index {index} of type {type(value)} has no known converter" + ) + payloads.append(payload) + return payloads + + def from_payloads( + self, + payloads: Sequence[temporalio.api.common.v1.Payload], + type_hints: list[type] | None = None, + ) -> list[Any]: + """Decode values trying each converter. + + See base class. Always returns the same number of values as payloads. + + Raises: + KeyError: Unknown payload encoding + RuntimeError: Error during decode + """ + values = [] + type_hints = type_hints or [] + for index, (payload, type_hint) in enumerate(zip_longest(payloads, type_hints)): + # Raw value should just wrap + if type_hint == temporalio.common.RawValue: + values.append(temporalio.common.RawValue(payload)) + continue + encoding = payload.metadata.get("encoding", b"") + converter = self.converters.get(encoding) + if converter is None: + raise KeyError(f"Unknown payload encoding {encoding.decode()}") + try: + values.append(converter.from_payload(payload, type_hint)) + except RuntimeError as err: + raise RuntimeError( + f"Payload at index {index} with encoding {encoding.decode()} could not be converted" + ) from err + return values + + def with_context(self, context: SerializationContext) -> Self: + """Return a new instance with context set on the component converters. + + If none of the component converters returned new instances, return self. + """ + converters = self.get_converters_with_context(context) + if converters is None: + return self + new_instance = type(self)() # Must have a nullary constructor + new_instance._set_converters(*converters) + return new_instance + + def get_converters_with_context( + self, context: SerializationContext + ) -> list[EncodingPayloadConverter] | None: + """Return converter instances with context set. + + If no converter uses context, return None. + """ + if not self._any_converter_takes_context: + return None + converters: list[EncodingPayloadConverter] = [] + any_with_context = False + for c in self.converters.values(): + if isinstance(c, WithSerializationContext): + converters.append(c.with_context(context)) + any_with_context |= converters[-1] is not c + else: + converters.append(c) + + return converters if any_with_context else None + + @functools.cached_property + def _any_converter_takes_context(self) -> bool: + return any( + isinstance(c, WithSerializationContext) for c in self.converters.values() + ) + + +class DefaultPayloadConverter(CompositePayloadConverter): + """Default payload converter compatible with other Temporal SDKs. + + This handles None, bytes, all protobuf message types, and any type that + :py:func:`json.dump` accepts. A singleton instance of this is available at + :py:attr:`PayloadConverter.default`. + """ + + default_encoding_payload_converters: tuple[EncodingPayloadConverter, ...] + """Default set of encoding payload converters the default payload converter + uses. + """ + + def __init__(self) -> None: + """Create a default payload converter.""" + super().__init__(*DefaultPayloadConverter.default_encoding_payload_converters) + + +class BinaryNullPayloadConverter(EncodingPayloadConverter): + """Converter for 'binary/null' payloads supporting None values.""" + + @property + def encoding(self) -> str: + """See base class.""" + return "binary/null" + + def to_payload(self, value: Any) -> temporalio.api.common.v1.Payload | None: + """See base class.""" + if value is None: + return temporalio.api.common.v1.Payload( + metadata={"encoding": self.encoding.encode()} + ) + return None + + def from_payload( + self, + payload: temporalio.api.common.v1.Payload, + type_hint: type | None = None, + ) -> Any: + """See base class.""" + if len(payload.data) > 0: + raise RuntimeError("Expected empty data set for binary/null") + return None + + +class BinaryPlainPayloadConverter(EncodingPayloadConverter): + """Converter for 'binary/plain' payloads supporting bytes values.""" + + @property + def encoding(self) -> str: + """See base class.""" + return "binary/plain" + + def to_payload(self, value: Any) -> temporalio.api.common.v1.Payload | None: + """See base class.""" + if isinstance(value, bytes): + return temporalio.api.common.v1.Payload( + metadata={"encoding": self.encoding.encode()}, data=value + ) + return None + + def from_payload( + self, + payload: temporalio.api.common.v1.Payload, + type_hint: type | None = None, + ) -> Any: + """See base class.""" + return payload.data + + +class JSONProtoPayloadConverter(EncodingPayloadConverter): + """Converter for 'json/protobuf' payloads supporting protobuf Message values.""" + + def __init__(self, ignore_unknown_fields: bool = False): + """Initialize a JSON proto converter. + + Args: + ignore_unknown_fields: Determines whether converter should error if + unknown fields are detected + """ + super().__init__() + self._ignore_unknown_fields = ignore_unknown_fields + + @property + def encoding(self) -> str: + """See base class.""" + return "json/protobuf" + + def to_payload(self, value: Any) -> temporalio.api.common.v1.Payload | None: + """See base class.""" + if ( + isinstance(value, google.protobuf.message.Message) + and value.DESCRIPTOR is not None # type:ignore[reportUnnecessaryComparison] + ): + # We have to convert to dict then to JSON because MessageToJson does + # not have a compact option removing spaces and newlines + json_str = json.dumps( + google.protobuf.json_format.MessageToDict(value), + separators=(",", ":"), + sort_keys=True, + ) + return temporalio.api.common.v1.Payload( + metadata={ + "encoding": self.encoding.encode(), + "messageType": value.DESCRIPTOR.full_name.encode(), + }, + data=json_str.encode(), + ) + return None + + def from_payload( + self, + payload: temporalio.api.common.v1.Payload, + type_hint: type | None = None, + ) -> Any: + """See base class.""" + message_type = payload.metadata.get("messageType", b"").decode() + try: + value = _sym_db.GetSymbol(message_type)() + return google.protobuf.json_format.Parse( + payload.data, + value, + ignore_unknown_fields=self._ignore_unknown_fields, + ) + except KeyError as err: + raise RuntimeError(f"Unknown Protobuf type {message_type}") from err + except google.protobuf.json_format.ParseError as err: + raise RuntimeError("Failed parsing") from err + + +class BinaryProtoPayloadConverter(EncodingPayloadConverter): + """Converter for 'binary/protobuf' payloads supporting protobuf Message values.""" + + @property + def encoding(self) -> str: + """See base class.""" + return "binary/protobuf" + + def to_payload(self, value: Any) -> temporalio.api.common.v1.Payload | None: + """See base class.""" + if ( + isinstance(value, google.protobuf.message.Message) + and value.DESCRIPTOR is not None # type:ignore[reportUnnecessaryComparison] + ): + return temporalio.api.common.v1.Payload( + metadata={ + "encoding": self.encoding.encode(), + "messageType": value.DESCRIPTOR.full_name.encode(), + }, + data=value.SerializeToString(), + ) + return None + + def from_payload( + self, + payload: temporalio.api.common.v1.Payload, + type_hint: type | None = None, + ) -> Any: + """See base class.""" + message_type = payload.metadata.get("messageType", b"").decode() + try: + value = _sym_db.GetSymbol(message_type)() + value.ParseFromString(payload.data) + return value + except KeyError as err: + raise RuntimeError(f"Unknown Protobuf type {message_type}") from err + except google.protobuf.message.DecodeError as err: + raise RuntimeError("Failed parsing") from err + + +class AdvancedJSONEncoder(json.JSONEncoder): + """Advanced JSON encoder. + + This encoder supports dataclasses and all iterables as lists. + + It also uses Pydantic v1's "dict" methods if available on the object, + but this is deprecated. Pydantic users should upgrade to v2 and use + temporalio.contrib.pydantic.pydantic_data_converter. + """ + + def default(self, o: Any) -> Any: + """Override JSON encoding default. + + See :py:meth:`json.JSONEncoder.default`. + """ + # Datetime support + if isinstance(o, datetime): + return o.isoformat() + # Dataclass support + if dataclasses.is_dataclass(o) and not isinstance(o, type): + return dataclasses.asdict(o) + # Support for Pydantic v1's dict method + dict_fn = getattr(o, "dict", None) + if callable(dict_fn): + return dict_fn() + # Support for non-list iterables like set + if not isinstance(o, list) and isinstance(o, collections.abc.Iterable): + return list(o) + # Support for UUID + if isinstance(o, uuid.UUID): + return str(o) + return super().default(o) + + +_JSONTypeConverterUnhandled = NewType("_JSONTypeConverterUnhandled", object) + + +class JSONTypeConverter(ABC): + """Converter for converting an object from Python :py:func:`json.loads` + result (e.g. scalar, list, or dict) to a known type. + """ + + Unhandled = _JSONTypeConverterUnhandled(object()) + """Sentinel value that must be used as the result of + :py:meth:`to_typed_value` to say the given type is not handled by this + converter.""" + + @abstractmethod + def to_typed_value( + self, hint: type, value: Any + ) -> Any | None | _JSONTypeConverterUnhandled: + """Convert the given value to a type based on the given hint. + + Args: + hint: Type hint to use to help in converting the value. + value: Value as returned by :py:func:`json.loads`. Usually a scalar, + list, or dict. + + Returns: + The converted value or :py:attr:`Unhandled` if this converter does + not handle this situation. + """ + raise NotImplementedError + + +class JSONPlainPayloadConverter(EncodingPayloadConverter): + """Converter for 'json/plain' payloads supporting common Python values. + + For encoding, this supports all values that :py:func:`json.dump` supports + and by default adds extra encoding support for dataclasses, classes with + ``dict()`` methods, and all iterables. + + For decoding, this uses type hints to attempt to rebuild the type from the + type hint. + """ + + _encoder: type[json.JSONEncoder] | None + _decoder: type[json.JSONDecoder] | None + _encoding: str + + def __init__( + self, + *, + encoder: type[json.JSONEncoder] | None = AdvancedJSONEncoder, + decoder: type[json.JSONDecoder] | None = None, + encoding: str = "json/plain", + custom_type_converters: Sequence[JSONTypeConverter] = [], + ) -> None: + """Initialize a JSON data converter. + + Args: + encoder: Custom encoder class object to use. + decoder: Custom decoder class object to use. + encoding: Encoding name to use. + custom_type_converters: Set of custom type converters that are used + when converting from a payload to type-hinted values. + """ + super().__init__() + self._encoder = encoder + self._decoder = decoder + self._encoding = encoding + self._custom_type_converters = custom_type_converters + + @property + def encoding(self) -> str: + """See base class.""" + return self._encoding + + def to_payload(self, value: Any) -> temporalio.api.common.v1.Payload | None: + """See base class.""" + # Check for Pydantic v1 + if hasattr(value, "parse_obj"): + warnings.warn( + "If you're using Pydantic v2, use temporalio.contrib.pydantic.pydantic_data_converter. " + "If you're using Pydantic v1 and cannot upgrade, refer to https://github.com/temporalio/samples-python/tree/main/pydantic_converter_v1 for better v1 support." + ) + # We let JSON conversion errors be thrown to caller + return temporalio.api.common.v1.Payload( + metadata={"encoding": self._encoding.encode()}, + data=json.dumps( + value, cls=self._encoder, separators=(",", ":"), sort_keys=True + ).encode(), + ) + + def from_payload( + self, + payload: temporalio.api.common.v1.Payload, + type_hint: type | None = None, + ) -> Any: + """See base class.""" + try: + obj = json.loads(payload.data, cls=self._decoder) + if type_hint: + obj = value_to_type(type_hint, obj, self._custom_type_converters) + return obj + except json.JSONDecodeError as err: + raise RuntimeError("Failed parsing") from err + + +def _get_iso_datetime_parser() -> Callable[[str], datetime]: + """Isolates system version check and returns relevant datetime passer + + Returns: + A callable to parse date strings into datetimes. + """ + if sys.version_info >= (3, 11): + return datetime.fromisoformat # type:ignore[reportUnreachable] # noqa + else: + # Isolate import for py > 3.11, as dependency only installed for < 3.11 + return parser.isoparse # type:ignore[reportUnreachable] + + +def value_to_type( + hint: type, + value: Any, + custom_converters: Sequence[JSONTypeConverter] = [], +) -> Any: + """Convert a given value to the given type hint. + + This is used internally to convert a raw JSON loaded value to a specific + type hint. + + Args: + hint: Type hint to convert the value to. + value: Raw value (e.g. primitive, dict, or list) to convert from. + custom_converters: Set of custom converters to try before doing default + conversion. Converters are tried in order and the first value that + is not :py:attr:`JSONTypeConverter.Unhandled` will be returned from + this function instead of doing default behavior. + + Returns: + Converted value. + + Raises: + TypeError: Unable to convert to the given hint. + """ + # Try custom converters + for conv in custom_converters: + ret = conv.to_typed_value(hint, value) + if ret is not JSONTypeConverter.Unhandled: + return ret + + # Any or primitives + if hint is Any: + return value + elif hint is datetime: + if isinstance(value, str): + try: + return _get_iso_datetime_parser()(value) + except ValueError as err: + raise TypeError(f"Failed parsing datetime string: {value}") from err + elif isinstance(value, datetime): + return value + raise TypeError(f"Expected datetime or ISO8601 string, got {type(value)}") + elif hint is int or hint is float: + if not isinstance(value, (int, float)): + raise TypeError(f"Expected value to be int|float, was {type(value)}") + return hint(value) + elif hint is bool: + if not isinstance(value, bool): + raise TypeError(f"Expected value to be bool, was {type(value)}") + return bool(value) + elif hint is str: + if not isinstance(value, str): + raise TypeError(f"Expected value to be str, was {type(value)}") + return str(value) + elif hint is bytes: + if not isinstance(value, (str, bytes, list)): + raise TypeError(f"Expected value to be bytes, was {type(value)}") + # In some other SDKs, this is serialized as a base64 string, but in + # Python this is a numeric array. + return bytes(value) # type: ignore + elif hint is type(None): + if value is not None: + raise TypeError(f"Expected None, got value of type {type(value)}") + return None + + # NewType. Note we cannot simply check isinstance NewType here because it's + # only been a class since 3.10. Instead we'll just check for the presence + # of a supertype. + supertype = getattr(hint, "__supertype__", None) + if supertype: + return value_to_type(supertype, value, custom_converters) + + # Load origin for other checks + origin = getattr(hint, "__origin__", hint) + type_args: tuple = getattr(hint, "__args__", ()) + + # Literal + if origin is Literal or origin is typing_extensions.Literal: + if value not in type_args: + raise TypeError(f"Value {value} not in literal values {type_args}") + return value + + is_union = origin is typing.Union # type:ignore[reportDeprecated] + is_union = is_union or isinstance(origin, UnionType) + + # Union + if is_union: + # Try each one. Note, Optional is just a union w/ none. + for arg in type_args: + try: + return value_to_type(arg, value, custom_converters) + except Exception: + pass + raise TypeError(f"Failed converting to {hint} from {value}") + + # Mapping + if inspect.isclass(origin) and issubclass(origin, collections.abc.Mapping): + if not isinstance(value, collections.abc.Mapping): + raise TypeError(f"Expected {hint}, value was {type(value)}") + ret_dict = {} + # If there are required or optional keys that means we are a TypedDict + # and therefore can extract per-key types + per_key_types: dict[str, type] | None = None + if getattr(origin, "__required_keys__", None) or getattr( + origin, "__optional_keys__", None + ): + per_key_types = get_type_hints(origin) + key_type = ( + type_args[0] + if len(type_args) > 0 + and type_args[0] is not Any + and not isinstance(type_args[0], TypeVar) + else None + ) + value_type = ( + type_args[1] + if len(type_args) > 1 + and type_args[1] is not Any + and not isinstance(type_args[1], TypeVar) + else None + ) + # Convert each key/value + for key, value in value.items(): + this_value_type = value_type + if per_key_types: + # TODO(cretz): Strict mode would fail an unknown key + this_value_type = per_key_types.get(key) + + if key_type: + # This function is used only by JSONPlainPayloadConverter. When + # serializing to JSON, Python supports key types str, int, float, bool, + # and None, serializing all to string representations. We now attempt to + # use the provided type annotation to recover the original value with its + # original type. + try: + if isinstance(key, str): + if key_type is int or key_type is float: + key = key_type(key) + elif key_type is bool: + key = {"true": True, "false": False}[key] + elif key_type is type(None): + key = {"null": None}[key] + + if not isinstance(key_type, type) or not isinstance(key, key_type): + key = value_to_type(key_type, key, custom_converters) + except Exception as err: + raise TypeError( + f"Failed converting key {repr(key)} to type {key_type} in mapping {hint}" + ) from err + + if this_value_type: + try: + value = value_to_type(this_value_type, value, custom_converters) + except Exception as err: + raise TypeError( + f"Failed converting value for key {repr(key)} in mapping {hint}" + ) from err + ret_dict[key] = value + # If there are per-key types, it's a typed dict and we want to attempt + # instantiation to get its validation + if per_key_types: + ret_dict = hint(**ret_dict) + return ret_dict + + # Dataclass + if dataclasses.is_dataclass(hint): + if not isinstance(value, dict): + raise TypeError( + f"Cannot convert to dataclass {hint}, value is {type(value)} not dict" + ) + # Obtain dataclass fields and check that all dict fields are there and + # that no required fields are missing. Unknown fields are silently + # ignored. + fields = dataclasses.fields(hint) + field_hints = get_type_hints(hint) + field_values = {} + for field in fields: + field_value = value.get(field.name, dataclasses.MISSING) + # We do not check whether field is required here. Rather, we let the + # attempted instantiation of the dataclass raise if a field is + # missing + if field_value is not dataclasses.MISSING: + try: + field_values[field.name] = value_to_type( + field_hints[field.name], field_value, custom_converters + ) + except Exception as err: + raise TypeError( + f"Failed converting field {field.name} on dataclass {hint}" + ) from err + # Simply instantiate the dataclass. This will fail as expected when + # missing required fields. + # TODO(cretz): Want way to convert snake case to camel case? + return hint(**field_values) + + # Pydantic model instance + # Pydantic users should use Pydantic v2 with + # temporalio.contrib.pydantic.pydantic_data_converter, in which case a + # pydantic model instance will have been handled by the custom_converters at + # the start of this function. We retain the following for backwards + # compatibility with pydantic v1 users, but this is deprecated. + parse_obj_attr = inspect.getattr_static(hint, "parse_obj", None) + if isinstance(parse_obj_attr, classmethod) or isinstance( + parse_obj_attr, staticmethod + ): + if not isinstance(value, dict): + raise TypeError( + f"Cannot convert to {hint}, value is {type(value)} not dict" + ) + return getattr(hint, "parse_obj")(value) + + # IntEnum + if inspect.isclass(hint) and issubclass(hint, IntEnum): + if not isinstance(value, int): + raise TypeError( + f"Cannot convert to enum {hint}, value not an integer, value is {type(value)}" + ) + return hint(value) + + # StrEnum, available in 3.11+ + if sys.version_info >= (3, 11): + if inspect.isclass(hint) and issubclass(hint, StrEnum): # type:ignore[reportUnreachable] + if not isinstance(value, str): + raise TypeError( + f"Cannot convert to enum {hint}, value not a string, value is {type(value)}" + ) + return hint(value) + + # UUID + if inspect.isclass(hint) and issubclass(hint, uuid.UUID): + return hint(value) + + # Iterable. We intentionally put this last as it catches several others. + if inspect.isclass(origin) and issubclass(origin, collections.abc.Iterable): + if not isinstance(value, collections.abc.Iterable): + raise TypeError(f"Expected {hint}, value was {type(value)}") + ret_list = [] + # If there is no type arg, just return value as is + if not type_args or ( + len(type_args) == 1 + and (isinstance(type_args[0], TypeVar) or type_args[0] is Ellipsis) + ): + ret_list = list(value) + else: + # Otherwise convert + for i, item in enumerate(value): + # Non-tuples use first type arg, tuples use arg set or one + # before ellipsis if that's set + if origin is not tuple: + arg_type = type_args[0] + elif len(type_args) > i and type_args[i] is not Ellipsis: + arg_type = type_args[i] + elif type_args[-1] is Ellipsis: + # Ellipsis means use the second to last one + arg_type = type_args[-2] # type: ignore + else: + raise TypeError( + f"Type {hint} only expecting {len(type_args)} values, got at least {i + 1}" + ) + try: + ret_list.append(value_to_type(arg_type, item, custom_converters)) + except Exception as err: + raise TypeError(f"Failed converting {hint} index {i}") from err + # If tuple, set, or deque convert back to that type + if origin is tuple: + return tuple(ret_list) + elif origin is set: + return set(ret_list) + elif origin is collections.deque: + return collections.deque(ret_list) + return ret_list + + raise TypeError(f"Unserializable type during conversion: {hint}") + + +# Set up after all converter classes are defined to avoid forward-reference issues. +DefaultPayloadConverter.default_encoding_payload_converters = ( + BinaryNullPayloadConverter(), + BinaryPlainPayloadConverter(), + JSONProtoPayloadConverter(), + BinaryProtoPayloadConverter(), + JSONPlainPayloadConverter(), # JSON Plain needs to remain last because it throws on unknown types +) diff --git a/temporalio/converter/_payload_limits.py b/temporalio/converter/_payload_limits.py new file mode 100644 index 000000000..d6eb0b1d2 --- /dev/null +++ b/temporalio/converter/_payload_limits.py @@ -0,0 +1,47 @@ +"""Payload size limit configuration and related types.""" + +from __future__ import annotations + +from dataclasses import dataclass + +import temporalio.exceptions + + +@dataclass(frozen=True) +class PayloadLimitsConfig: + """Configuration for when payload sizes exceed limits.""" + + memo_size_warning: int = 2 * 1024 + """The limit (in bytes) at which a memo size warning is logged.""" + + payload_size_warning: int = 512 * 1024 + """The limit (in bytes) at which a payload size warning is logged.""" + + +class PayloadSizeWarning(RuntimeWarning): + """The size of payloads is above the warning limit.""" + + +class _PayloadSizeError(temporalio.exceptions.TemporalError): # type:ignore[reportUnusedClass] + """Error raised when payloads size exceeds payload size limits.""" + + def __init__(self, message: str): + """Initialize a payloads size error.""" + super().__init__(message) + self._message = message + + @property + def message(self) -> str: + """Message.""" + return self._message + + +@dataclass(frozen=True) +class _ServerPayloadErrorLimits: # type:ignore[reportUnusedClass] + """Error limits for payloads as described by the Temporal server.""" + + memo_size_error: int + """The limit (in bytes) at which a memo size error is raised.""" + + payload_size_error: int + """The limit (in bytes) at which a payload size error is raised.""" diff --git a/temporalio/converter/_search_attributes.py b/temporalio/converter/_search_attributes.py new file mode 100644 index 000000000..4ec154d6f --- /dev/null +++ b/temporalio/converter/_search_attributes.py @@ -0,0 +1,213 @@ +"""Utilities for encoding and decoding Temporal search attributes.""" + +from __future__ import annotations + +from collections.abc import Sequence +from datetime import datetime + +import temporalio.api.common.v1 +import temporalio.common +from temporalio.converter._data_converter import default +from temporalio.converter._payload_converter import _get_iso_datetime_parser + + +def encode_search_attributes( + attributes: ( + temporalio.common.SearchAttributes | temporalio.common.TypedSearchAttributes + ), + api: temporalio.api.common.v1.SearchAttributes, +) -> None: + """Convert search attributes into an API message. + + Args: + attributes: Search attributes to convert. The dictionary form of this is + DEPRECATED. + api: API message to set converted attributes on. + """ + if isinstance(attributes, temporalio.common.TypedSearchAttributes): + for typed_k, typed_v in attributes: + api.indexed_fields[typed_k.name].CopyFrom( + encode_typed_search_attribute_value(typed_k, typed_v) + ) + return + elif not attributes: + return + for k, v in attributes.items(): + api.indexed_fields[k].CopyFrom(encode_search_attribute_values(v)) + + +def encode_typed_search_attribute_value( + key: temporalio.common.SearchAttributeKey[ + temporalio.common.SearchAttributeValueType + ], + value: temporalio.common.SearchAttributeValue | None, +) -> temporalio.api.common.v1.Payload: + """Convert typed search attribute value into a payload. + + Args: + key: Key for the value. + value: Value to convert. + + Returns: + Payload for the value. + """ + # For server search attributes to work properly, we cannot set the metadata + # type when we set null + if value is None: + return default().payload_converter.to_payload(None) + if not isinstance(value, key.origin_value_type): + raise TypeError( + f"Value of type {value} not suitable for indexed value type {key.indexed_value_type}" + ) + # datetime needs to be in isoformat + if isinstance(value, datetime): + value = value.isoformat() + # We'll do an extra sanity check for keyword list and check every value + if isinstance(value, Sequence): + for v in value: + if not isinstance(v, str): + raise TypeError("All values of a keyword list must be strings") + # Convert value + payload = default().payload_converter.to_payload(value) + # Set metadata type + payload.metadata["type"] = key._metadata_type.encode() + return payload + + +def encode_search_attribute_values( + vals: temporalio.common.SearchAttributeValues, +) -> temporalio.api.common.v1.Payload: + """Convert search attribute values into a payload. + + .. deprecated:: + Use typed search attributes instead. + + Args: + vals: List of values to convert. + """ + if not isinstance(vals, list): + raise TypeError("Search attribute values must be lists") # type:ignore[reportUnreachable] + # Confirm all types are the same + val_type: type | None = None + # Convert dates to strings + safe_vals = [] + for v in vals: + if isinstance(v, datetime): + if v.tzinfo is None: + raise ValueError( + "Timezone must be present on all search attribute dates" + ) + v = v.isoformat() + elif not isinstance(v, (str, int, float, bool)): + raise TypeError( + f"Search attribute value of type {type(v).__name__} not one of str, int, float, bool, or datetime" + ) + elif val_type and type(v) is not val_type: + raise TypeError( + "Search attribute values must have the same type for the same key" + ) + elif not val_type: + val_type = type(v) + safe_vals.append(v) + return default().payload_converter.to_payloads([safe_vals])[0] + + +def _encode_maybe_typed_search_attributes( # type:ignore[reportUnusedFunction] + non_typed_attributes: temporalio.common.SearchAttributes | None, + typed_attributes: temporalio.common.TypedSearchAttributes | None, + api: temporalio.api.common.v1.SearchAttributes, +) -> None: + if non_typed_attributes: + if typed_attributes and typed_attributes.search_attributes: + raise ValueError( + "Cannot provide both deprecated search attributes and typed search attributes" + ) + encode_search_attributes(non_typed_attributes, api) + elif typed_attributes and typed_attributes.search_attributes: + encode_search_attributes(typed_attributes, api) + + +def decode_search_attributes( + api: temporalio.api.common.v1.SearchAttributes, +) -> temporalio.common.SearchAttributes: + """Decode API search attributes to values. + + .. deprecated:: + Use typed search attributes instead. + + Args: + api: API message with search attribute values to convert. + + Returns: + Converted search attribute values (new mapping every time). + """ + conv = default().payload_converter + ret = {} + for k, v in api.indexed_fields.items(): + val = conv.from_payloads([v])[0] + # If a value did not come back as a list, make it a single-item list + if not isinstance(val, list): + val = [val] + # Convert each item to datetime if necessary + if v.metadata.get("type") == b"Datetime": + parser = _get_iso_datetime_parser() + val = [parser(v) for v in val] + ret[k] = val + return ret + + +def decode_typed_search_attributes( + api: temporalio.api.common.v1.SearchAttributes, +) -> temporalio.common.TypedSearchAttributes: + """Decode API search attributes to typed search attributes. + + Args: + api: API message with search attribute values to convert. + + Returns: + Typed search attribute collection (new object every time). + """ + conv = default().payload_converter + pairs: list[temporalio.common.SearchAttributePair] = [] + for k, v in api.indexed_fields.items(): + # We want the "type" metadata, but if it is not present or an unknown + # type, we will just ignore + metadata_type = v.metadata.get("type") + if not metadata_type: + continue + key = temporalio.common.SearchAttributeKey._from_metadata_type( + k, metadata_type.decode() + ) + if not key: + continue + val = conv.from_payload(v) + # If the value is a list but the type is not keyword list, pull out + # single item or consider this an invalid value and ignore + if ( + key.indexed_value_type + != temporalio.common.SearchAttributeIndexedValueType.KEYWORD_LIST + and isinstance(val, list) + ): + if len(val) != 1: + continue + val = val[0] + if ( + key.indexed_value_type + == temporalio.common.SearchAttributeIndexedValueType.DATETIME + ): + parser = _get_iso_datetime_parser() + # We will let this throw + val = parser(val) + # If the value isn't the right type, we need to ignore + if isinstance(val, key.origin_value_type): + pairs.append(temporalio.common.SearchAttributePair(key, val)) + return temporalio.common.TypedSearchAttributes(pairs) + + +def _decode_search_attribute_value( # type:ignore[reportUnusedFunction] + payload: temporalio.api.common.v1.Payload, +) -> temporalio.common.SearchAttributeValue: + val = default().payload_converter.from_payload(payload) + if isinstance(val, str) and payload.metadata.get("type") == b"Datetime": + val = _get_iso_datetime_parser()(val) + return val # type: ignore diff --git a/temporalio/converter/_serialization_context.py b/temporalio/converter/_serialization_context.py new file mode 100644 index 000000000..73a4a7104 --- /dev/null +++ b/temporalio/converter/_serialization_context.py @@ -0,0 +1,121 @@ +"""Serialization context types for data conversion.""" + +from __future__ import annotations + +from abc import ABC +from dataclasses import dataclass + +from typing_extensions import Self + + +class SerializationContext(ABC): + """Base serialization context. + + Provides contextual information during serialization and deserialization operations. + + Examples: + In client code, when starting a workflow, or sending a signal/update/query to a workflow, + or receiving the result of an update/query, or handling an exception from a workflow, the + context type is :py:class:`WorkflowSerializationContext` and the workflow ID set of the + target workflow will be set in the context. + + In workflow code, when operating on a payload being sent/received to/from a child workflow, + or handling an exception from a child workflow, the context type is + :py:class:`WorkflowSerializationContext` and the workflow ID is that of the child workflow, + not of the currently executing (i.e. parent) workflow. + + In workflow code, when operating on a payload to be sent/received to/from an activity, the + context type is :py:class:`ActivitySerializationContext` and the workflow ID is that of the + currently-executing workflow. ActivitySerializationContext is also set on data converter + operations in the activity context. + """ + + pass + + +@dataclass(frozen=True) +class WorkflowSerializationContext(SerializationContext): + """Serialization context for workflows. + + See :py:class:`SerializationContext` for more details. + """ + + namespace: str + """The namespace the workflow is running in.""" + + workflow_id: str + """The ID of the workflow. + + Note that this is the ID of the workflow of which the payload being operated on is an input or + output. Note also that when creating/describing schedules, this may be the workflow ID prefix + as configured, not the final workflow ID when the workflow is created by the schedule. + """ + + +@dataclass(frozen=True) +class ActivitySerializationContext(SerializationContext): + """Serialization context for activities. + + See :py:class:`SerializationContext` for more details. + """ + + namespace: str + """Workflow/activity namespace.""" + + activity_id: str | None + """Activity ID. Optional if this is an activity started from a workflow.""" + + activity_type: str | None + """Activity type. + + .. deprecated:: + This value may not be set in some bidirectional situations, it should + not be relied on. + """ + + activity_task_queue: str | None + """Activity task queue. + + .. deprecated:: + This value may not be set in some bidirectional situations, it should + not be relied on. + """ + + workflow_id: str | None + """Workflow ID. Only set if this is an activity started from a workflow. + + Note, when creating/describing schedules, this may be the workflow ID prefix as + configured, not the final workflow ID when the workflow is created by the schedule.""" + + workflow_type: str | None + """Workflow type if this is an activity started from a workflow.""" + + is_local: bool + """Whether the activity is a local activity started from a workflow.""" + + +class WithSerializationContext(ABC): + """Interface for classes that can use serialization context. + + The following classes may implement this interface: + - :py:class:`PayloadConverter` + - :py:class:`PayloadCodec` + - :py:class:`FailureConverter` + - :py:class:`EncodingPayloadConverter` + + During data converter operations (encoding/decoding, serialization/deserialization, and failure + conversion), instances of classes implementing this interface will be replaced by the result of + calling with_context(context). This allows overridden methods (encode/decode, + to_payload/from_payload, etc) to use the context. + """ + + def with_context(self, context: SerializationContext) -> Self: # type: ignore[reportUnusedParameter] + """Return a copy of this object configured to use the given context. + + Args: + context: The serialization context to use. + + Returns: + A new instance configured with the context. + """ + raise NotImplementedError() diff --git a/temporalio/worker/_activity.py b/temporalio/worker/_activity.py index 4e6e06282..9c4d0ec17 100644 --- a/temporalio/worker/_activity.py +++ b/temporalio/worker/_activity.py @@ -32,6 +32,7 @@ import temporalio.client import temporalio.common import temporalio.converter +import temporalio.converter._payload_limits import temporalio.exceptions from ._interceptor import ( @@ -128,7 +129,8 @@ def __init__( async def run( self, - payload_error_limits: temporalio.converter._ServerPayloadErrorLimits | None, + payload_error_limits: temporalio.converter._payload_limits._ServerPayloadErrorLimits + | None, ) -> None: """Continually poll for activity tasks and dispatch to handlers.""" self._data_converter = self._data_converter._with_payload_error_limits( @@ -403,7 +405,7 @@ async def _handle_start_activity_task( ) elif isinstance( err, - temporalio.converter._PayloadSizeError, + temporalio.converter._payload_limits._PayloadSizeError, ): temporalio.activity.logger.warning( err.message, @@ -444,7 +446,9 @@ async def _handle_start_activity_task( if isinstance(err, concurrent.futures.BrokenExecutor): self._fail_worker_exception_queue.put_nowait(err) # Handle PayloadSizeError from attempting to encode failure information - except temporalio.converter._PayloadSizeError as inner_err: + except ( + temporalio.converter._payload_limits._PayloadSizeError + ) as inner_err: temporalio.activity.logger.exception(inner_err.message) completion.result.Clear() await data_converter.encode_failure( diff --git a/temporalio/worker/_nexus.py b/temporalio/worker/_nexus.py index 35339cc66..278337746 100644 --- a/temporalio/worker/_nexus.py +++ b/temporalio/worker/_nexus.py @@ -29,6 +29,7 @@ import temporalio.client import temporalio.common import temporalio.converter +import temporalio.converter._payload_limits import temporalio.nexus from temporalio.bridge.worker import PollShutdownError from temporalio.exceptions import ( @@ -95,7 +96,8 @@ def __init__( async def run( self, - payload_error_limits: temporalio.converter._ServerPayloadErrorLimits | None, + payload_error_limits: temporalio.converter._payload_limits._ServerPayloadErrorLimits + | None, ) -> None: """Continually poll for Nexus tasks and dispatch to handlers.""" self._data_converter = self._data_converter._with_payload_error_limits( diff --git a/temporalio/worker/_worker.py b/temporalio/worker/_worker.py index 3564f4577..83c21e91e 100644 --- a/temporalio/worker/_worker.py +++ b/temporalio/worker/_worker.py @@ -29,7 +29,7 @@ VersioningBehavior, WorkerDeploymentVersion, ) -from temporalio.converter import _ServerPayloadErrorLimits +from temporalio.converter._payload_limits import _ServerPayloadErrorLimits from ._activity import SharedStateManager, _ActivityWorker from ._interceptor import Interceptor diff --git a/temporalio/worker/_workflow.py b/temporalio/worker/_workflow.py index 18f5599ba..2f8e7560f 100644 --- a/temporalio/worker/_workflow.py +++ b/temporalio/worker/_workflow.py @@ -21,6 +21,7 @@ import temporalio.bridge.worker import temporalio.common import temporalio.converter +import temporalio.converter._payload_limits import temporalio.exceptions import temporalio.workflow from temporalio.api.enums.v1 import WorkflowTaskFailedCause @@ -166,7 +167,8 @@ def __init__( async def run( self, - payload_error_limits: temporalio.converter._ServerPayloadErrorLimits | None, + payload_error_limits: temporalio.converter._payload_limits._ServerPayloadErrorLimits + | None, ) -> None: self._data_converter = self._data_converter._with_payload_error_limits( payload_error_limits @@ -381,7 +383,7 @@ async def _handle_activation( data_converter, encode_headers=self._encode_headers, ) - except temporalio.converter._PayloadSizeError as err: + except temporalio.converter._payload_limits._PayloadSizeError as err: logger.warning(err.message) completion.failed.Clear() await data_converter.encode_failure(err, completion.failed.failure) diff --git a/tests/test_converter.py b/tests/test_converter.py index 8ef5f8a68..dfe8860d1 100644 --- a/tests/test_converter.py +++ b/tests/test_converter.py @@ -41,11 +41,11 @@ JSONPlainPayloadConverter, JSONTypeConverter, PayloadCodec, - _JSONTypeConverterUnhandled, decode_search_attributes, encode_search_attribute_values, value_to_type, ) +from temporalio.converter._payload_converter import _JSONTypeConverterUnhandled from temporalio.exceptions import ( ApplicationError, FailureError, From 610a0bbdde893c1db6c85f4e2fb1f43ec7d04240 Mon Sep 17 00:00:00 2001 From: James Watkins-Harvey Date: Mon, 16 Mar 2026 19:12:29 -0400 Subject: [PATCH 003/226] Validate deployment config and test worker with versioning off and custom build ID (#1361) Co-authored-by: Claude Opus 4.6 --- temporalio/worker/_worker.py | 10 +++++++ tests/worker/test_worker.py | 57 ++++++++++++++++++++++++++++++++++++ 2 files changed, 67 insertions(+) diff --git a/temporalio/worker/_worker.py b/temporalio/worker/_worker.py index 83c21e91e..2c3a1666d 100644 --- a/temporalio/worker/_worker.py +++ b/temporalio/worker/_worker.py @@ -410,6 +410,16 @@ def _init_from_config(self, client: temporalio.client.Client, config: WorkerConf raise ValueError( "deployment_config cannot be used with build_id or use_worker_versioning" ) + _deployment_config = config.get("deployment_config") + if ( + _deployment_config is not None + and not _deployment_config.use_worker_versioning + and _deployment_config.default_versioning_behavior + != VersioningBehavior.UNSPECIFIED + ): + raise ValueError( + "default_versioning_behavior must be UNSPECIFIED when use_worker_versioning is False" + ) # Prepend applicable client interceptors to the given ones client_config = config["client"].config(active_config=True) # type: ignore[reportTypedDictNotRequiredAccess] diff --git a/tests/worker/test_worker.py b/tests/worker/test_worker.py index 333142992..4c76a7ba9 100644 --- a/tests/worker/test_worker.py +++ b/tests/worker/test_worker.py @@ -1008,6 +1008,63 @@ async def test_workflows_can_use_default_versioning_behavior( ) +async def test_worker_deployment_config_without_versioning( + client: Client, env: WorkflowEnvironment +): + if env.supports_time_skipping: + pytest.skip("Test Server doesn't support worker deployments") + + build_id = "my-custom-build-id-1.0" + deployment_name = f"deployment-no-versioning-{uuid.uuid4()}" + + async with new_worker( + client, + NoVersioningAnnotationWorkflow, + deployment_config=WorkerDeploymentConfig( + version=WorkerDeploymentVersion( + deployment_name=deployment_name, build_id=build_id + ), + use_worker_versioning=False, + ), + ) as worker: + handle = await client.start_workflow( + NoVersioningAnnotationWorkflow.run, + id=f"no-versioning-build-id-{uuid.uuid4()}", + task_queue=worker.task_queue, + ) + result = await handle.result() + assert result == "whee" + + history = await handle.fetch_history() + assert any( + event.workflow_task_completed_event_attributes + and event.workflow_task_completed_event_attributes.worker_version + and event.workflow_task_completed_event_attributes.worker_version.build_id + == build_id + for event in history.events + ), "Expected build ID to appear in workflow history" + + +async def test_deployment_config_rejects_versioning_behavior_without_versioning( + client: Client, +): + with pytest.raises( + ValueError, match="default_versioning_behavior must be UNSPECIFIED" + ): + Worker( + client, + task_queue=f"task-queue-{uuid.uuid4()}", + workflows=[NoVersioningAnnotationWorkflow], + deployment_config=WorkerDeploymentConfig( + version=WorkerDeploymentVersion( + deployment_name="whatever", build_id="1.0" + ), + use_worker_versioning=False, + default_versioning_behavior=VersioningBehavior.AUTO_UPGRADE, + ), + ) + + async def test_workflows_can_use_versioning_override( client: Client, env: WorkflowEnvironment ): From 47b68a0f851f7fd07680927391045102a46d6db3 Mon Sep 17 00:00:00 2001 From: Alex Mazzeo Date: Mon, 16 Mar 2026 16:17:06 -0700 Subject: [PATCH 004/226] Remove HTTP port now that it's unused by nexus tests (#1368) --- tests/conftest.py | 5 ----- 1 file changed, 5 deletions(-) diff --git a/tests/conftest.py b/tests/conftest.py index 468579720..c813f91f9 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -98,7 +98,6 @@ def env_type(request: pytest.FixtureRequest) -> str: @pytest_asyncio.fixture(scope="session") # type: ignore[reportUntypedFunctionDecorator] async def env(env_type: str) -> AsyncGenerator[WorkflowEnvironment, None]: if env_type == "local": - http_port = 7243 env = await WorkflowEnvironment.start_local( dev_server_extra_args=[ "--dynamic-config-value", @@ -125,13 +124,9 @@ async def env(env_type: str) -> AsyncGenerator[WorkflowEnvironment, None]: "history.enableChasm=true", "--dynamic-config-value", "history.enableTransitionHistory=true", - "--http-port", - str(http_port), ], dev_server_download_version=DEV_SERVER_DOWNLOAD_VERSION, ) - # TODO(nexus-preview): expose this in a more principled way - env._http_port = http_port # type: ignore elif env_type == "time-skipping": env = await WorkflowEnvironment.start_time_skipping() else: From bb44cb8c321bded769a7179bcd4b654b5d5f38f8 Mon Sep 17 00:00:00 2001 From: Justin Anderson <44687433+jmaeagle99@users.noreply.github.com> Date: Mon, 16 Mar 2026 18:47:20 -0700 Subject: [PATCH 005/226] Experimental: External Payload Storage (#1341) --- README.md | 132 ++++- temporalio/bridge/worker.py | 7 +- temporalio/converter/__init__.py | 14 + temporalio/converter/_data_converter.py | 60 ++- temporalio/converter/_extstore.py | 433 +++++++++++++++ temporalio/worker/_activity.py | 2 +- temporalio/worker/_workflow.py | 53 +- temporalio/worker/_workflow_instance.py | 6 +- tests/test_extstore.py | 677 ++++++++++++++++++++++++ tests/worker/test_extstore.py | 554 +++++++++++++++++++ 10 files changed, 1909 insertions(+), 29 deletions(-) create mode 100644 temporalio/converter/_extstore.py create mode 100644 tests/test_extstore.py create mode 100644 tests/worker/test_extstore.py diff --git a/README.md b/README.md index f26c7b837..223a1f113 100644 --- a/README.md +++ b/README.md @@ -54,6 +54,9 @@ informal introduction to the features and their implementation. - [Data Conversion](#data-conversion) - [Pydantic Support](#pydantic-support) - [Custom Type Data Conversion](#custom-type-data-conversion) + - [External Storage](#external-storage) + - [Driver Selection](#driver-selection) + - [Custom Drivers](#custom-drivers) - [Workers](#workers) - [Workflows](#workflows) - [Definition](#definition) @@ -309,8 +312,9 @@ other_ns_client = Client(**config) Data converters are used to convert raw Temporal payloads to/from actual Python types. A custom data converter of type `temporalio.converter.DataConverter` can be set via the `data_converter` parameter of the `Client` constructor. Data -converters are a combination of payload converters, payload codecs, and failure converters. Payload converters convert -Python values to/from serialized bytes. Payload codecs convert bytes to bytes (e.g. for compression or encryption). +converters are a combination of payload converters, external storage, payload codecs, and failure converters. Payload +converters convert Python values to/from serialized bytes. External payload storage optionally stores and retrieves payloads +to/from external storage services using drivers. Payload codecs convert bytes to bytes (e.g. for compression or encryption). Failure converters convert exceptions to/from serialized failures. The default data converter supports converting multiple types including: @@ -455,6 +459,130 @@ my_data_converter = dataclasses.replace( Now `IPv4Address` can be used in type hints including collections, optionals, etc. +##### External Storage + +⚠️ **External storage support is currently at an experimental release stage.** ⚠️ + +External storage allows large payloads to be offloaded to an external storage service (such as Amazon S3) rather than stored inline in workflow history. This is useful when workflows or activities work with data that would otherwise exceed Temporal's payload size limits. + +External storage is configured via the `external_storage` parameter on `DataConverter`. It should be configured on the `Client` both for clients of your workflow as well as on the worker -- anywhere large payloads may be uploaded or downloaded. + +A `StorageDriver` handles uploading and downloading payloads. Temporal provides built-in drivers for common storage solutions, or you may customize one. Here's an example using our provided `InMemoryTestDriver`. + +```python +import dataclasses +from temporalio.client import Client +from temporalio.converter import DataConverter +from temporalio.converter import ExternalStorage + +driver = InMemoryTestDriver() + +client = await Client.connect( + "localhost:7233", + data_converter=dataclasses.replace( + DataConverter.default, + external_storage=ExternalStorage(drivers=[driver]), + ), +) +``` + +Some things to note about external storage: + +* Only payloads that meet or exceed `ExternalStorage.payload_size_threshold` (default 256 KiB) are offloaded. Smaller payloads are stored inline as normal. +* External storage applies transparently to all payloads, whether they are workflow inputs/outputs, activity inputs/outputs, signal inputs, query outputs, update inputs/outputs, or failure details. +* The `DataConverter`'s `payload_codec` (if configured) is applied to the payload *before* it is handed to the storage driver, so the driver always stores encoded bytes. The reference payload written to workflow history is not encoded by the `DataConverter` codec. +* Setting `ExternalStorage.payload_size_threshold` to `None` causes every payload to be considered for external storage regardless of size. + +###### Driver Selection + +When multiple storage backends are needed, list all drivers in `ExternalStorage.drivers` and provide a `driver_selector` to control which driver stores new payloads. Any driver in the list not chosen for storing is still available for retrieval, which is useful when migrating between storage backends. + +```python +from temporalio.converter import ExternalStorage + +options = ExternalStorage( + drivers=[hot_driver, cold_driver], + driver_selector=lambda context, payload: ( + hot_driver if payload.ByteSize() < 5 * 1024 * 1024 else cold_driver + ), +) +``` + +For more complex selection logic, use a plain callable that reads from the `StorageDriverStoreContext`: + +```python +import temporalio.converter +from temporalio.api.common.v1 import Payload + +def feature_flag_is_on(workflow_id: str | None) -> bool: + """Check whether external storage is enabled for this workflow via a feature flag service.""" + return workflow_id is not None and len(workflow_id) % 2 == 0 + +def feature_flag_selector( + context: temporalio.converter.StorageDriverStoreContext, _payload: Payload +) -> temporalio.converter.StorageDriver | None: + workflow_id = None + if isinstance(context.serialization_context, temporalio.converter.WorkflowSerializationContext): + workflow_id = context.serialization_context.workflow_id + elif isinstance(context.serialization_context, temporalio.converter.ActivitySerializationContext): + workflow_id = context.serialization_context.workflow_id + return my_driver if feature_flag_is_on(workflow_id) else None + +options = ExternalStorage( + drivers=[my_driver], + driver_selector=feature_flag_selector, +) +``` + +Some things to note about driver selection: + +* A `driver_selector` is required when more than one driver is registered. With a single driver, `driver_selector` may be omitted and that driver is used for all store operations. +* Returning `None` from a selector leaves the payload stored inline in workflow history rather than offloading it. +* The driver instance returned by the selector must be one of the instances registered in `ExternalStorage.drivers`. If it is not, an error is raised. + +###### Custom Drivers + +Implement `temporalio.converter.StorageDriver` to integrate with an external storage system: + +```python +from collections.abc import Sequence +from temporalio.converter import StorageDriver, StorageDriverClaim, StorageDriverRetrieveContext, StorageDriverStoreContext +from temporalio.api.common.v1 import Payload + +class MyDriver(StorageDriver): + def __init__(self, driver_name: str | None = None): + self._driver_name = driver_name or "my-org:driver:my-driver" + + def name(self) -> str: + return self._driver_name + + async def store( + self, context: StorageDriverStoreContext, payloads: Sequence[Payload] + ) -> list[StorageDriverClaim]: + claims = [] + for payload in payloads: + key = await my_storage.put(payload.SerializeToString()) + claims.append(StorageDriverClaim(data={"key": key})) + return claims + + async def retrieve( + self, context: StorageDriverRetrieveContext, claims: Sequence[StorageDriverClaim] + ) -> list[Payload]: + payloads = [] + for claim in claims: + data = await my_storage.get(claim.data["key"]) + p = Payload() + p.ParseFromString(data) + payloads.append(p) + return payloads +``` + +Some things to note about implementing a custom driver: + +* `StorageDriver.name()` must return a string that is unique among all drivers in `ExternalStorage.drivers`. This name is embedded in the reference payload stored in workflow history and used to look up the correct driver during retrieval — changing it after payloads have been stored will break retrieval. +* `StorageDriver.type()` is automatically implemented to return the name of the class. This can be overridden in subclasses but must remain consistent across all instances of the subclass. +* Implement `temporalio.converter.WithSerializationContext` on your driver to receive workflow or activity context (namespace, workflow ID, activity ID, etc.) at serialization time. + ### Workers Workers host workflows and/or activities. Here's how to run a worker: diff --git a/temporalio/bridge/worker.py b/temporalio/bridge/worker.py index c98afefca..c2e426d28 100644 --- a/temporalio/bridge/worker.py +++ b/temporalio/bridge/worker.py @@ -303,10 +303,9 @@ async def decode_activation( decode_headers: bool, ) -> None: """Decode all payloads in the activation.""" - if data_converter._decode_payload_has_effect: - await CommandAwarePayloadVisitor( - skip_search_attributes=True, skip_headers=not decode_headers - ).visit(_Visitor(data_converter._decode_payload_sequence), activation) + await CommandAwarePayloadVisitor( + skip_search_attributes=True, skip_headers=not decode_headers + ).visit(_Visitor(data_converter._decode_payload_sequence), activation) async def encode_completion( diff --git a/temporalio/converter/__init__.py b/temporalio/converter/__init__.py index d70bd6e76..2777e7e80 100644 --- a/temporalio/converter/__init__.py +++ b/temporalio/converter/__init__.py @@ -4,6 +4,14 @@ DataConverter, default, ) +from temporalio.converter._extstore import ( + ExternalStorage, + StorageDriver, + StorageDriverClaim, + StorageDriverRetrieveContext, + StorageDriverStoreContext, + StorageWarning, +) from temporalio.converter._failure_converter import ( DefaultFailureConverter, DefaultFailureConverterWithEncodedAttributes, @@ -44,6 +52,12 @@ __all__ = [ "ActivitySerializationContext", + "ExternalStorage", + "StorageDriver", + "StorageDriverClaim", + "StorageDriverRetrieveContext", + "StorageDriverStoreContext", + "StorageWarning", "AdvancedJSONEncoder", "BinaryNullPayloadConverter", "BinaryPlainPayloadConverter", diff --git a/temporalio/converter/_data_converter.py b/temporalio/converter/_data_converter.py index e9ac33158..9c2163774 100644 --- a/temporalio/converter/_data_converter.py +++ b/temporalio/converter/_data_converter.py @@ -14,6 +14,11 @@ import temporalio.api.common.v1 import temporalio.api.failure.v1 import temporalio.common +from temporalio.converter._extstore import ( + _REFERENCE_ENCODING, + ExternalStorage, + StorageWarning, +) from temporalio.converter._failure_converter import ( FailureConverter, ) @@ -72,6 +77,13 @@ class DataConverter(WithSerializationContext): payload_limits: PayloadLimitsConfig = PayloadLimitsConfig() """Settings for payload size limits.""" + external_storage: ExternalStorage | None = None + """Options for external storage. If None, external storage is disabled. + + .. warning:: + This API is experimental. + """ + default: ClassVar[DataConverter] """Singleton default data converter.""" @@ -158,18 +170,22 @@ def with_context(self, context: SerializationContext) -> Self: payload_converter = self.payload_converter payload_codec = self.payload_codec failure_converter = self.failure_converter + external_storage = self.external_storage if isinstance(payload_converter, WithSerializationContext): payload_converter = payload_converter.with_context(context) if isinstance(payload_codec, WithSerializationContext): payload_codec = payload_codec.with_context(context) if isinstance(failure_converter, WithSerializationContext): failure_converter = failure_converter.with_context(context) + if isinstance(external_storage, WithSerializationContext): + external_storage = external_storage.with_context(context) if all( new is orig for new, orig in [ (payload_converter, self.payload_converter), (payload_codec, self.payload_codec), (failure_converter, self.failure_converter), + (external_storage, self.external_storage), ] ): return self @@ -177,6 +193,7 @@ def with_context(self, context: SerializationContext) -> Self: object.__setattr__(cloned, "payload_converter", payload_converter) object.__setattr__(cloned, "payload_codec", payload_codec) object.__setattr__(cloned, "failure_converter", failure_converter) + object.__setattr__(cloned, "external_storage", external_storage) return cloned def _with_payload_error_limits( @@ -238,12 +255,16 @@ async def _encode_payload( ) -> temporalio.api.common.v1.Payload: if self.payload_codec: payload = (await self.payload_codec.encode([payload]))[0] + if self.external_storage: + payload = await self.external_storage._store_payload(payload) self._validate_payload_limits([payload]) return payload async def _encode_payloads(self, payloads: temporalio.api.common.v1.Payloads): if self.payload_codec: await self.payload_codec.encode_wrapper(payloads) + if self.external_storage: + await self.external_storage._store_payloads(payloads) self._validate_payload_limits(payloads.payloads) async def _encode_payload_sequence( @@ -252,32 +273,63 @@ async def _encode_payload_sequence( encoded_payloads = list(payloads) if self.payload_codec: encoded_payloads = await self.payload_codec.encode(encoded_payloads) + if self.external_storage: + encoded_payloads = await self.external_storage._store_payload_sequence( + encoded_payloads + ) self._validate_payload_limits(encoded_payloads) return encoded_payloads async def _decode_payload( self, payload: temporalio.api.common.v1.Payload ) -> temporalio.api.common.v1.Payload: + if self.external_storage: + payload = await self.external_storage._retrieve_payload(payload) if self.payload_codec: payload = (await self.payload_codec.decode([payload]))[0] return payload async def _decode_payloads(self, payloads: temporalio.api.common.v1.Payloads): + if self.external_storage: + await self.external_storage._retrieve_payloads(payloads) + else: + if any( + p.metadata.get("encoding") == _REFERENCE_ENCODING + for p in payloads.payloads + ): + warnings.warn( + "[TMPRL1105] Detected externally stored payload(s) but external storage is not configured.", + StorageWarning, + ) if self.payload_codec: await self.payload_codec.decode_wrapper(payloads) async def _decode_payload_sequence( self, payloads: Sequence[temporalio.api.common.v1.Payload] ) -> list[temporalio.api.common.v1.Payload]: - if not self.payload_codec: - return list(payloads) - return await self.payload_codec.decode(payloads) + decoded_payloads = list(payloads) + if self.external_storage: + decoded_payloads = await self.external_storage._retrieve_payload_sequence( + decoded_payloads + ) + else: + if any( + p.metadata.get("encoding") == _REFERENCE_ENCODING + for p in decoded_payloads + ): + warnings.warn( + "[TMPRL1105] Detected externally stored payload(s) but external storage is not configured.", + StorageWarning, + ) + if self.payload_codec: + decoded_payloads = await self.payload_codec.decode(decoded_payloads) + return decoded_payloads # Temporary shortcircuit detection while the _decode_* methods may no-op if # a payload codec is not configured. Remove once those paths have more to them. @property def _decode_payload_has_effect(self) -> bool: - return self.payload_codec is not None + return self.payload_codec is not None or self.external_storage is not None def _validate_payload_limits( self, diff --git a/temporalio/converter/_extstore.py b/temporalio/converter/_extstore.py new file mode 100644 index 000000000..614c8ac10 --- /dev/null +++ b/temporalio/converter/_extstore.py @@ -0,0 +1,433 @@ +"""External payload storage support for offloading payloads to external storage +systems. +""" + +from __future__ import annotations + +import asyncio +import dataclasses +from abc import ABC, abstractmethod +from collections.abc import Callable, Coroutine, Mapping, Sequence +from dataclasses import dataclass +from typing import Any, ClassVar, TypeVar + +from typing_extensions import Self + +from temporalio.api.common.v1 import Payload, Payloads +from temporalio.converter._payload_converter import JSONPlainPayloadConverter +from temporalio.converter._serialization_context import ( + SerializationContext, + WithSerializationContext, +) + +_T = TypeVar("_T") + +_REFERENCE_ENCODING = b"json/external-storage-reference" + + +async def _gather_cancel_on_error( + coros: Sequence[Coroutine[Any, Any, _T]], +) -> list[_T]: + """Run coroutines concurrently; cancel all remaining tasks if any one fails.""" + tasks = [asyncio.create_task(c) for c in coros] + try: + return await asyncio.gather(*tasks) + except BaseException: + for task in tasks: + task.cancel() + await asyncio.gather(*tasks, return_exceptions=True) + raise + + +@dataclass(frozen=True) +class StorageDriverClaim: + """A driver-defined reference to an externally-stored payload that can be used to + retrieve it. + + .. warning:: + This API is experimental. + """ + + claim_data: Mapping[str, str] + """Driver-defined data for identifying and retrieving an externally stored + payload. + """ + + +@dataclass(frozen=True) +class StorageDriverStoreContext: + """Context passed to :meth:`StorageDriver.store` and ``driver_selector`` calls. + + .. warning:: + This API is experimental. + """ + + serialization_context: SerializationContext | None = None + """The serialization context active when this store operation was initiated, + or ``None`` if no context has been set. + """ + + +@dataclass(frozen=True) +class StorageDriverRetrieveContext: + """Context passed to :meth:`StorageDriver.retrieve` calls. + + .. warning:: + This API is experimental. + """ + + +class StorageDriver(ABC): + """Base driver for storing and retrieve payloads from external storage systems. + + .. warning:: + This API is experimental. + """ + + @abstractmethod + def name(self) -> str: + """Returns the name of this driver instance. A driver may allow + its name to be parameterized at construction time so that multiple + instances of the same driver class can coexist in + :attr:`ExternalStorage.drivers` with distinct names. + """ + raise NotImplementedError + + def type(self) -> str: + """Returns the type of the storage driver. This string should be + the same across all instantiations of the same driver class. This + allows the equivalent driver implementation in different languages + to be named the same. + + Defaults to the class name. Subclasses may override this to return a + stable, language-agnostic identifier. + """ + return type(self).__name__ + + @abstractmethod + async def store( + self, + context: StorageDriverStoreContext, + payloads: Sequence[Payload], + ) -> list[StorageDriverClaim]: + """Stores payloads in external storage and returns a + :class:`StorageDriverClaim` for each one. The returned list must be the + same length as ``payloads``. + """ + raise NotImplementedError + + @abstractmethod + async def retrieve( + self, + context: StorageDriverRetrieveContext, + claims: Sequence[StorageDriverClaim], + ) -> list[Payload]: + """Retrieves payloads from external storage for the given + :class:`StorageDriverClaim` list. The returned list must be the same + length as ``claims``. + """ + raise NotImplementedError + + +class StorageWarning(RuntimeWarning): + """Warning for external storage issues. + + .. warning:: + This API is experimental. + """ + + +@dataclass(frozen=True) +class _StorageReference: + driver_name: str + driver_claim: StorageDriverClaim + + +@dataclass(frozen=True) +class ExternalStorage(WithSerializationContext): + """Configuration for external storage behavior. + + .. warning:: + This API is experimental. + """ + + drivers: Sequence[StorageDriver] + """Drivers available for storing and retrieving payloads. At least one + driver must be provided. If more than one driver is registered, + :attr:`driver_selector` must also be set. + + Drivers in this list are looked up by :meth:`StorageDriver.name` during + retrieval, so each driver must have a unique name. + """ + + driver_selector: ( + Callable[[StorageDriverStoreContext, Payload], StorageDriver | None] | None + ) = None + """Controls which driver stores a given payload. A callable that returns the + driver instance to use, or ``None`` to leave the payload stored inline. + The returned driver must be one of the instances registered in + :attr:`drivers`. + + Required when more than one driver is registered. When ``None`` and only + one driver is registered, that driver is used for all store operations. + """ + + payload_size_threshold: int | None = 256 * 1024 + """Minimum payload size in bytes before external storage is considered. + Defaults to 256 KiB. Set to ``None`` to consider every payload for + external storage regardless of size. + """ + + _driver_map: dict[str, StorageDriver] = dataclasses.field( + init=False, repr=False, compare=False + ) + """Name-keyed index of :attr:`drivers`, built at construction time. Used + for retrieval lookups. + """ + + _context: SerializationContext | None = dataclasses.field( + init=False, default=None, repr=False, compare=False + ) + + _claim_converter: ClassVar[JSONPlainPayloadConverter] = JSONPlainPayloadConverter( + encoding=_REFERENCE_ENCODING.decode() + ) + + def __post_init__(self) -> None: + """Validate drivers and build the internal name-keyed driver map. + + Raises :exc:`ValueError` if no drivers are provided, if more than one + driver is registered without a :attr:`driver_selector`, or if any two + drivers share the same name. + """ + if not self.drivers: + raise ValueError( + "ExternalStorage.drivers must contain at least one driver." + ) + if len(self.drivers) > 1 and self.driver_selector is None: + raise ValueError( + "ExternalStorage.driver_selector must be specified if multiple drivers are registered." + ) + driver_map: dict[str, StorageDriver] = {} + for driver in self.drivers: + name = driver.name() + if name in driver_map: + raise ValueError( + f"ExternalStorage.drivers contains multiple drivers with name '{name}'. " + "Each driver must have a unique name." + ) + driver_map[name] = driver + object.__setattr__(self, "_driver_map", driver_map) + + def with_context(self, context: SerializationContext) -> Self: + """Return a copy of these options with the serialization context applied.""" + result = dataclasses.replace(self) + object.__setattr__(result, "_context", context) + return result + + def _select_driver( + self, context: StorageDriverStoreContext, payload: Payload + ) -> StorageDriver | None: + """Returns the driver to use for this payload, or None to pass through.""" + if ( + self.payload_size_threshold is not None + and payload.ByteSize() < self.payload_size_threshold + ): + return None + selector = self.driver_selector + if selector is None: + return self.drivers[0] if self.drivers else None + driver = selector(context, payload) + if driver is None: + return None + registered = self._driver_map.get(driver.name()) + if registered is not driver: + raise ValueError( + f"Driver '{driver.name()}' returned by driver_selector is not registered in ExternalStorage.drivers" + ) + return driver + + def _get_driver_by_name(self, name: str) -> StorageDriver: + """Looks up a driver by name, raising :class:`ValueError` if not found.""" + driver = self._driver_map.get(name) + if driver is None: + raise ValueError(f"No driver found with name '{name}'") + return driver + + async def _store_payload(self, payload: Payload) -> Payload: + context = StorageDriverStoreContext(serialization_context=self._context) + + driver = self._select_driver(context, payload) + if driver is None: + return payload + + claims = await driver.store(context, [payload]) + + self._validate_claim_length(claims, expected=1, driver=driver) + + reference = _StorageReference( + driver_name=driver.name(), + driver_claim=claims[0], + ) + reference_payload = self._claim_converter.to_payload(reference) + if reference_payload is None: + raise ValueError( + f"Failed to serialize storage reference for driver '{driver.name()}'" + ) + reference_payload.external_payloads.add().size_bytes = payload.ByteSize() + return reference_payload + + async def _store_payloads(self, payloads: Payloads): + stored_payloads = await self._store_payload_sequence(payloads.payloads) + for i, payload in enumerate(stored_payloads): + payloads.payloads[i].CopyFrom(payload) + + async def _store_payload_sequence( + self, + payloads: Sequence[Payload], + ) -> list[Payload]: + if len(payloads) == 1: + return [await self._store_payload(payloads[0])] + + results = list(payloads) + context = StorageDriverStoreContext(serialization_context=self._context) + + to_store: list[tuple[int, Payload, StorageDriver]] = [] + for index, payload in enumerate(payloads): + driver = self._select_driver(context, payload) + if driver is None: + continue + to_store.append((index, payload, driver)) + + if not to_store: + return results + + driver_groups: dict[StorageDriver, list[tuple[int, Payload]]] = {} + for orig_index, payload, driver in to_store: + driver_groups.setdefault(driver, []).append((orig_index, payload)) + + driver_group_list = list(driver_groups.items()) + + all_claims = await _gather_cancel_on_error( + [ + driver.store(context, [p for _, p in indexed_payloads]) + for driver, indexed_payloads in driver_group_list + ] + ) + + for (driver, indexed_payloads), claims in zip(driver_group_list, all_claims): + indices = [idx for idx, _ in indexed_payloads] + sizes = [p.ByteSize() for _, p in indexed_payloads] + + self._validate_claim_length(claims, expected=len(indices), driver=driver) + + for i, claim in enumerate(claims): + reference = _StorageReference( + driver_name=driver.name(), + driver_claim=claim, + ) + reference_payload = self._claim_converter.to_payload(reference) + if reference_payload is None: + raise ValueError( + f"Failed to serialize storage reference for driver '{driver.name()}'" + ) + reference_payload.external_payloads.add().size_bytes = sizes[i] + results[indices[i]] = reference_payload + + return results + + async def _retrieve_payload(self, payload: Payload) -> Payload: + if len(payload.external_payloads) == 0: + return payload + + reference = self._claim_converter.from_payload(payload, _StorageReference) + if not isinstance(reference, _StorageReference): + return payload + + driver = self._get_driver_by_name(reference.driver_name) + context = StorageDriverRetrieveContext() + + stored_payloads = await driver.retrieve(context, [reference.driver_claim]) + + self._validate_payload_length(stored_payloads, expected=1, driver=driver) + + return stored_payloads[0] + + async def _retrieve_payloads(self, payloads: Payloads): + stored_payloads = await self._retrieve_payload_sequence(payloads.payloads) + for i, payload in enumerate(stored_payloads): + payloads.payloads[i].CopyFrom(payload) + + async def _retrieve_payload_sequence( + self, + payloads: Sequence[Payload], + ) -> list[Payload]: + results = list(payloads) + + if len(payloads) == 1: + return [await self._retrieve_payload(payloads[0])] + + driver_claims: dict[StorageDriver, list[tuple[int, StorageDriverClaim]]] = {} + for index, payload in enumerate(payloads): + if len(payload.external_payloads) == 0: + continue + + reference = self._claim_converter.from_payload(payload, _StorageReference) + if not isinstance(reference, _StorageReference): + continue + + driver = self._get_driver_by_name(reference.driver_name) + driver_claims.setdefault(driver, []).append((index, reference.driver_claim)) + + if not driver_claims: + return results + + context = StorageDriverRetrieveContext() + stored_by_index: dict[int, Payload] = {} + + driver_claim_list = list(driver_claims.items()) + + all_stored = await _gather_cancel_on_error( + [ + driver.retrieve(context, [claim for _, claim in indexed_claims]) + for driver, indexed_claims in driver_claim_list + ] + ) + + for (driver, indexed_claims), stored_payloads in zip( + driver_claim_list, all_stored + ): + indices = [idx for idx, _ in indexed_claims] + + self._validate_payload_length( + stored_payloads, + expected=len(indexed_claims), + driver=driver, + ) + + for idx, stored_payload in zip(indices, stored_payloads): + stored_by_index[idx] = stored_payload + + retrieve_indices = sorted(stored_by_index.keys()) + stored_list = [stored_by_index[idx] for idx in retrieve_indices] + + for i, retrieved_payload in enumerate(stored_list): + results[retrieve_indices[i]] = retrieved_payload + + return results + + def _validate_claim_length( + self, claims: Sequence[StorageDriverClaim], expected: int, driver: StorageDriver + ) -> None: + if len(claims) != expected: + raise ValueError( + f"Driver '{driver.name()}' returned {len(claims)} claims, expected {expected}", + ) + + def _validate_payload_length( + self, payloads: Sequence[Payload], expected: int, driver: StorageDriver + ) -> None: + if len(payloads) != expected: + raise ValueError( + f"Driver '{driver.name()}' returned {len(payloads)} payloads, expected {expected}", + ) diff --git a/temporalio/worker/_activity.py b/temporalio/worker/_activity.py index 9c4d0ec17..7b67734d9 100644 --- a/temporalio/worker/_activity.py +++ b/temporalio/worker/_activity.py @@ -629,7 +629,7 @@ async def _execute_activity( else None, ) - if self._encode_headers and data_converter._decode_payload_has_effect: + if self._encode_headers: for payload in start.header_fields.values(): payload.CopyFrom(await data_converter._decode_payload(payload)) diff --git a/temporalio/worker/_workflow.py b/temporalio/worker/_workflow.py index 2f8e7560f..b305bd3e0 100644 --- a/temporalio/worker/_workflow.py +++ b/temporalio/worker/_workflow.py @@ -342,21 +342,44 @@ async def _handle_activation( "Failed handling activation on workflow with run ID %s", act.run_id ) - completion.failed.failure.SetInParent() - try: - data_converter.failure_converter.to_failure( - err, - data_converter.payload_converter, - completion.failed.failure, - ) - except Exception as inner_err: - logger.exception( - "Failed converting activation exception on workflow with run ID %s", - act.run_id, - ) - completion.failed.failure.message = ( - f"Failed converting activation exception: {inner_err}" - ) + if ( + isinstance(err, temporalio.exceptions.ApplicationError) + and err.non_retryable + ): + # Fail the workflow execution terminally rather than failing the task + command = completion.successful.commands.add() + failure = command.fail_workflow_execution.failure + failure.SetInParent() + try: + data_converter.failure_converter.to_failure( + err, + data_converter.payload_converter, + failure, + ) + except Exception as inner_err: + logger.exception( + "Failed converting activation exception on workflow with run ID %s", + act.run_id, + ) + failure.message = ( + f"Failed converting activation exception: {inner_err}" + ) + else: + completion.failed.failure.SetInParent() + try: + data_converter.failure_converter.to_failure( + err, + data_converter.payload_converter, + completion.failed.failure, + ) + except Exception as inner_err: + logger.exception( + "Failed converting activation exception on workflow with run ID %s", + act.run_id, + ) + completion.failed.failure.message = ( + f"Failed converting activation exception: {inner_err}" + ) completion.run_id = act.run_id diff --git a/temporalio/worker/_workflow_instance.py b/temporalio/worker/_workflow_instance.py index 1fa7e2eae..1bfa77c3c 100644 --- a/temporalio/worker/_workflow_instance.py +++ b/temporalio/worker/_workflow_instance.py @@ -1794,9 +1794,9 @@ def workflow_set_current_details(self, details: str): self._current_details = details def workflow_is_failure_exception(self, err: BaseException) -> bool: - # An exception is a failure instead of a task fail if it's already a - # failure error or if it is a timeout error or if it is an instance of - # any of the failure types in the worker or workflow-level setting + # An exception causes the workflow to fail (rather than the task) if it + # is already a failure error, a timeout error, or an instance of any of the + # failure exception types configured at the worker or workflow level. wf_failure_exception_types = self._defn.failure_exception_types if self._dynamic_failure_exception_types is not None: wf_failure_exception_types = self._dynamic_failure_exception_types diff --git a/tests/test_extstore.py b/tests/test_extstore.py new file mode 100644 index 000000000..8a8a8b6d6 --- /dev/null +++ b/tests/test_extstore.py @@ -0,0 +1,677 @@ +"""Tests for external storage functionality.""" + +import asyncio +from collections.abc import Sequence + +import pytest + +from temporalio.api.common.v1 import Payload +from temporalio.converter import ( + DataConverter, + ExternalStorage, + JSONPlainPayloadConverter, + PayloadCodec, + StorageDriver, + StorageDriverClaim, + StorageDriverRetrieveContext, + StorageDriverStoreContext, +) +from temporalio.converter._extstore import _StorageReference +from temporalio.exceptions import ApplicationError + + +class InMemoryTestDriver(StorageDriver): + """In-memory storage driver for testing.""" + + def __init__( + self, + driver_name: str = "test-driver", + ): + self._driver_name = driver_name + self._storage: dict[str, bytes] = {} + self._store_calls = 0 + self._retrieve_calls = 0 + + def name(self) -> str: + return self._driver_name + + async def store( + self, + context: StorageDriverStoreContext, + payloads: Sequence[Payload], + ) -> list[StorageDriverClaim]: + self._store_calls += 1 + start_index = len(self._storage) + + entries = [ + (f"payload-{start_index + i}", payload.SerializeToString()) + for i, payload in enumerate(payloads) + ] + self._storage.update(entries) + + return [StorageDriverClaim(claim_data={"key": key}) for key, _ in entries] + + async def retrieve( + self, + context: StorageDriverRetrieveContext, + claims: Sequence[StorageDriverClaim], + ) -> list[Payload]: + self._retrieve_calls += 1 + + def parse_claim( + claim: StorageDriverClaim, + ) -> Payload: + key = claim.claim_data["key"] + if key not in self._storage: + raise ApplicationError( + f"Payload not found for key '{key}'", non_retryable=True + ) + payload = Payload() + payload.ParseFromString(self._storage[key]) + return payload + + return [parse_claim(claim) for claim in claims] + + +class TestDataConverterExternalStorage: + """Tests for DataConverter with external storage.""" + + async def test_extstore_encode_decode(self): + """Test that large payloads are stored externally.""" + driver = InMemoryTestDriver() + + # Configure with 100-byte threshold + converter = DataConverter( + external_storage=ExternalStorage( + drivers=[driver], + payload_size_threshold=100, + ) + ) + + # Small value should not be externalized + small_value = "small" + encoded_small = await converter.encode([small_value]) + assert len(encoded_small) == 1 + assert not encoded_small[0].external_payloads # Not externalized + assert driver._store_calls == 0 + + # Large value should be externalized + large_value = "x" * 200 + encoded_large = await converter.encode([large_value]) + assert len(encoded_large) == 1 + assert len(encoded_large[0].external_payloads) > 0 # Externalized + assert driver._store_calls == 1 + + # Decode large value + decoded = await converter.decode(encoded_large, [str]) + assert len(decoded) == 1 + assert decoded[0] == large_value + assert driver._retrieve_calls == 1 + + async def test_extstore_reference_structure(self): + """Test that external storage creates proper reference structure.""" + converter = DataConverter( + external_storage=ExternalStorage( + drivers=[InMemoryTestDriver("test-driver")], + payload_size_threshold=50, + ) + ) + + # Create large payload + large_value = "x" * 100 + encoded = await converter.encode([large_value]) + + # Verify reference structure + reference_payload = encoded[0] + assert len(reference_payload.external_payloads) > 0 + + # The payload should contain a serialized _ExternalStorageReference + # Deserialize it to verify structure using the same encoding + claim_converter = JSONPlainPayloadConverter( + encoding="json/external-storage-reference" + ) + reference = claim_converter.from_payload(reference_payload, _StorageReference) + + assert isinstance(reference, _StorageReference) + assert "test-driver" == reference.driver_name + assert isinstance(reference.driver_claim, StorageDriverClaim) + assert "key" in reference.driver_claim.claim_data + + async def test_extstore_composite_conditional(self): + """Test using multiple drivers based on size.""" + hot_driver = InMemoryTestDriver("hot-storage") + cold_driver = InMemoryTestDriver("cold-storage") + + options = ExternalStorage( + drivers=[hot_driver, cold_driver], + driver_selector=lambda context, payload: hot_driver + if payload.ByteSize() < 500 + else cold_driver, + payload_size_threshold=100, + ) + converter = DataConverter(external_storage=options) + + # Small payload (not externalized) + small = "x" * 50 + encoded_small = await converter.encode([small]) + assert not encoded_small[0].external_payloads + assert hot_driver._store_calls == 0 + assert cold_driver._store_calls == 0 + + # Medium payload (hot storage) + medium = "x" * 200 + encoded_medium = await converter.encode([medium]) + assert len(encoded_medium[0].external_payloads) > 0 + assert hot_driver._store_calls == 1 + assert cold_driver._store_calls == 0 + + # Large payload (cold storage) + large = "x" * 2000 + encoded_large = await converter.encode([large]) + assert len(encoded_large[0].external_payloads) > 0 + assert hot_driver._store_calls == 1 # Unchanged + assert cold_driver._store_calls == 1 + + # Verify retrieval from correct drivers + decoded_medium = await converter.decode(encoded_medium, [str]) + assert decoded_medium[0] == medium + assert hot_driver._retrieve_calls == 1 + + decoded_large = await converter.decode(encoded_large, [str]) + assert decoded_large[0] == large + assert cold_driver._retrieve_calls == 1 + + +class TestDriverError: + """Tests for ValueError raised when a driver violates its contract.""" + + async def test_encode_wrong_claim_count_raises_runtime_error(self): + """store() returning fewer claims than payloads must raise ValueError.""" + + class _NoClaimsDriver(InMemoryTestDriver): + async def store( + self, context: StorageDriverStoreContext, payloads: Sequence[Payload] + ) -> list[StorageDriverClaim]: + return [] + + driver = _NoClaimsDriver() + converter = DataConverter( + external_storage=ExternalStorage( + drivers=[driver], + payload_size_threshold=10, + ) + ) + with pytest.raises( + ValueError, + match=f"Driver '{driver.name()}' returned 0 claims, expected 1", + ): + await converter.encode(["x" * 200]) + + async def test_decode_wrong_payload_count_raises_runtime_error(self): + """retrieve() returning fewer payloads than claims must raise ValueError.""" + good_converter = DataConverter( + external_storage=ExternalStorage( + drivers=[InMemoryTestDriver()], + payload_size_threshold=10, + ) + ) + encoded = await good_converter.encode(["x" * 200]) + + class _NoPayloadsDriver(InMemoryTestDriver): + async def retrieve( + self, + context: StorageDriverRetrieveContext, + claims: Sequence[StorageDriverClaim], + ) -> list[Payload]: + return [] + + driver = _NoPayloadsDriver() + bad_converter = DataConverter( + external_storage=ExternalStorage( + drivers=[driver], + payload_size_threshold=10, + ) + ) + with pytest.raises( + ValueError, + match=f"Driver '{driver.name()}' returned 0 payloads, expected 1", + ): + await bad_converter.decode(encoded, [str]) + + async def test_store_cancels_in_flight_driver_on_error(self): + """When one driver raises during concurrent store, other in-flight drivers are cancelled.""" + store_cancelled = asyncio.Event() + + class _SleepingStoreDriver(InMemoryTestDriver): + def __init__(self): + super().__init__("sleeping") + + async def store( + self, + context: StorageDriverStoreContext, + payloads: Sequence[Payload], + ) -> list[StorageDriverClaim]: + try: + await asyncio.sleep(float("inf")) + except asyncio.CancelledError: + store_cancelled.set() + raise + return [] # unreachable + + class _FailingStoreDriver(InMemoryTestDriver): + def __init__(self): + super().__init__("failing") + + async def store( + self, + context: StorageDriverStoreContext, + payloads: Sequence[Payload], + ) -> list[StorageDriverClaim]: + raise ValueError( + "failed to store payloads because remote service is unavailable" + ) + + drivers = [_SleepingStoreDriver(), _FailingStoreDriver()] + drivers_iter = iter(drivers) + converter = DataConverter( + external_storage=ExternalStorage( + drivers=drivers, + driver_selector=lambda ctx, p: next(drivers_iter), + payload_size_threshold=None, + ) + ) + + with pytest.raises( + ValueError, + match="^failed to store payloads because remote service is unavailable$", + ): + await converter.encode(["payload_a", "payload_b"]) + + assert store_cancelled.is_set() + + async def test_retrieve_cancels_in_flight_driver_on_error(self): + """When one driver raises during concurrent retrieve, other in-flight drivers are cancelled.""" + retrieve_cancelled = asyncio.Event() + + class _SleepingRetrieveDriver(InMemoryTestDriver): + def __init__(self): + super().__init__("sleeping") + + async def retrieve( + self, + context: StorageDriverRetrieveContext, + claims: Sequence[StorageDriverClaim], + ) -> list[Payload]: + try: + await asyncio.sleep(float("inf")) + except asyncio.CancelledError: + retrieve_cancelled.set() + raise + return [] # unreachable + + class _FailingRetrieveDriver(InMemoryTestDriver): + def __init__(self): + super().__init__("failing") + + async def retrieve( + self, + context: StorageDriverRetrieveContext, + claims: Sequence[StorageDriverClaim], + ) -> list[Payload]: + raise ValueError( + "failed to retrieve a payload because the object key does not exist" + ) + + drivers: list[StorageDriver] = [ + _SleepingRetrieveDriver(), + _FailingRetrieveDriver(), + ] + drivers_iter = iter(drivers) + converter = DataConverter( + external_storage=ExternalStorage( + drivers=drivers, + driver_selector=lambda ctx, p: next(drivers_iter), + payload_size_threshold=None, + ) + ) + encoded = await converter.encode(["payload_a", "payload_b"]) + + with pytest.raises( + ValueError, + match="^failed to retrieve a payload because the object key does not exist$", + ): + await converter.decode(encoded, [str, str]) + + assert retrieve_cancelled.is_set() + + +class RecordingPayloadCodec(PayloadCodec): + """Codec that wraps each payload under a recognisable ``encoding`` label. + + Encode sets ``metadata["encoding"]`` to ``encoding_label`` and stores the + serialised inner payload as ``data``. Decode reverses that. The call + counters let tests assert exactly how many payloads each codec processed. + """ + + def __init__(self, encoding_label: str) -> None: + self._encoding_label = encoding_label.encode() + self.encoded_count = 0 + self.decoded_count = 0 + + async def encode(self, payloads: Sequence[Payload]) -> list[Payload]: + self.encoded_count += len(payloads) + results = [] + for p in payloads: + wrapped = Payload() + wrapped.metadata["encoding"] = self._encoding_label + wrapped.data = p.SerializeToString() + results.append(wrapped) + return results + + async def decode(self, payloads: Sequence[Payload]) -> list[Payload]: + self.decoded_count += len(payloads) + results = [] + for p in payloads: + inner = Payload() + inner.ParseFromString(p.data) + results.append(inner) + return results + + +class TestPayloadCodecWithExternalStorage: + """Tests for interaction between DataConverter.payload_codec and external storage.""" + + async def test_dc_payload_codec_encodes_stored_bytes(self): + """DataConverter.payload_codec encodes the bytes handed to the driver + for storage. The reference payload written to workflow history is NOT + encoded by the DataConverter codec.""" + driver = InMemoryTestDriver() + dc_codec = RecordingPayloadCodec("binary/dc-encoded") + + converter = DataConverter( + payload_codec=dc_codec, + external_storage=ExternalStorage( + drivers=[driver], + payload_size_threshold=50, + ), + ) + + large_value = "x" * 200 + encoded = await converter.encode([large_value]) + assert len(encoded) == 1 + assert driver._store_calls == 1 + + # The reference payload written to history must NOT carry the dc_codec label. + assert dc_codec.encoded_count == 1 + assert encoded[0].metadata.get("encoding") != b"binary/dc-encoded" + + # The bytes given to the driver must carry the dc_codec label. + stored_payload = Payload() + stored_payload.ParseFromString(next(iter(driver._storage.values()))) + assert stored_payload.metadata.get("encoding") == b"binary/dc-encoded" + + # Round-trip must recover the original value. + decoded = await converter.decode(encoded, [str]) + assert decoded[0] == large_value + assert dc_codec.decoded_count == 1 + assert driver._retrieve_calls == 1 + + async def test_dc_payload_codec_does_not_encode_reference_payload(self): + """The reference payload stored in workflow history is NOT encoded by + DataConverter.payload_codec – encoding is applied to the stored bytes + instead.""" + driver = InMemoryTestDriver() + dc_codec = RecordingPayloadCodec("binary/dc-encoded") + + converter = DataConverter( + payload_codec=dc_codec, + external_storage=ExternalStorage( + drivers=[driver], + payload_size_threshold=50, + ), + ) + + large_value = "x" * 200 + encoded = await converter.encode([large_value]) + assert len(encoded) == 1 + assert driver._store_calls == 1 + + # Reference payload in history is NOT encoded by DataConverter.payload_codec. + assert dc_codec.encoded_count == 1 + assert encoded[0].metadata.get("encoding") != b"binary/dc-encoded" + + # Stored bytes ARE encoded by DataConverter.payload_codec. + stored_payload = Payload() + stored_payload.ParseFromString(next(iter(driver._storage.values()))) + assert stored_payload.metadata.get("encoding") == b"binary/dc-encoded" + + # Round-trip. + decoded = await converter.decode(encoded, [str]) + assert decoded[0] == large_value + assert dc_codec.decoded_count == 1 + assert driver._retrieve_calls == 1 + + +class TestMultiDriver: + """Tests for ExternalStorage with multiple drivers.""" + + async def test_selector_always_first_driver_handles_all_stores(self): + """A selector that always picks the first driver routes all store + operations there. The second driver is never called for store.""" + first = InMemoryTestDriver("driver-first") + second = InMemoryTestDriver("driver-second") + + converter = DataConverter( + external_storage=ExternalStorage( + drivers=[first, second], + driver_selector=lambda _ctx, _p: first, + payload_size_threshold=50, + ) + ) + + large = "x" * 200 + encoded = await converter.encode([large]) + + assert first._store_calls == 1 + assert second._store_calls == 0 + + # The reference in history names the first driver. + ref = JSONPlainPayloadConverter( + encoding="json/external-storage-reference" + ).from_payload(encoded[0], _StorageReference) + assert ref.driver_name == "driver-first" + + # Retrieval also goes to the first driver. + decoded = await converter.decode(encoded, [str]) + assert decoded[0] == large + assert first._retrieve_calls == 1 + assert second._retrieve_calls == 0 + + async def test_no_selector_second_driver_is_retrieve_only(self): + """A driver that is second in the list acts as a retrieve-only driver. + References are resolved by name, not by position, so a payload stored + by driver-b is retrieved correctly even when driver-a is listed first.""" + driver_a = InMemoryTestDriver("driver-a") + driver_b = InMemoryTestDriver("driver-b") + + # Store with driver-b as the sole driver. + store_converter = DataConverter( + external_storage=ExternalStorage( + drivers=[driver_b], + payload_size_threshold=50, + ) + ) + large = "y" * 200 + encoded = await store_converter.encode([large]) + + # Retrieve with driver-a listed first, driver-b second. + # The "driver-b" name in the reference must route to driver-b. + retrieve_converter = DataConverter( + external_storage=ExternalStorage( + drivers=[driver_a, driver_b], + driver_selector=lambda _ctx, _p: driver_a, + payload_size_threshold=50, + ) + ) + decoded = await retrieve_converter.decode(encoded, [str]) + assert decoded[0] == large + assert driver_a._retrieve_calls == 0 # never consulted + assert driver_b._retrieve_calls == 1 + + async def test_selector_routes_payloads_to_different_drivers_in_single_batch(self): + """When a selector routes different payloads to different drivers, a + single encode([v1, v2, ...]) call batches payloads per driver so each + driver receives exactly one store() call regardless of how many + payloads are routed to it.""" + driver_a = InMemoryTestDriver("driver-a") + driver_b = InMemoryTestDriver("driver-b") + + # Route payloads that serialise to < 500 bytes to driver_a, larger ones + # to driver_b. + def selector(_ctx: object, payload: Payload) -> StorageDriver: + return driver_a if payload.ByteSize() < 500 else driver_b + + converter = DataConverter( + external_storage=ExternalStorage( + drivers=[driver_a, driver_b], + driver_selector=selector, + payload_size_threshold=50, + ) + ) + + small_ext = "a" * 100 # above threshold, serialises well below 500 B + large_ext = "b" * 1000 # serialises above 500 B + + # Encode both values in a single call — they should be batched per driver. + encoded = await converter.encode([small_ext, large_ext]) + assert driver_a._store_calls == 1 # one batched call, not two individual ones + assert driver_b._store_calls == 1 + + # Full round-trip. + decoded = await converter.decode(encoded, [str, str]) + assert decoded == [small_ext, large_ext] + assert driver_a._retrieve_calls == 1 + assert driver_b._retrieve_calls == 1 + + async def test_selector_returning_none_keeps_payload_inline(self): + """A selector that returns None for a payload leaves it stored inline + in workflow history rather than offloading it to any driver, even when + the payload exceeds the size threshold.""" + driver = InMemoryTestDriver("driver-a") + + converter = DataConverter( + external_storage=ExternalStorage( + drivers=[driver], + driver_selector=lambda _ctx, _payload: None, + payload_size_threshold=50, + ) + ) + + large = "x" * 200 + encoded = await converter.encode([large]) + + assert driver._store_calls == 0 + assert len(encoded[0].external_payloads) == 0 # payload is inline + + decoded = await converter.decode(encoded, [str]) + assert decoded[0] == large + assert driver._retrieve_calls == 0 + + async def test_selector_returns_unregistered_driver_raises(self): + """A selector that returns a driver instance not present in + ExternalStorage.drivers raises ValueError during encode.""" + registered = InMemoryTestDriver("registered") + unregistered = InMemoryTestDriver("unregistered") + + converter = DataConverter( + external_storage=ExternalStorage( + drivers=[registered], + driver_selector=lambda _ctx, _payload: unregistered, + payload_size_threshold=50, + ) + ) + + with pytest.raises(ValueError): + await converter.encode(["x" * 200]) + + async def test_selector_dispatches_drivers_concurrently(self): + started_a = asyncio.Event() + started_b = asyncio.Event() + + class BarrierDriver(InMemoryTestDriver): + def __init__( + self, name: str, my_event: asyncio.Event, their_event: asyncio.Event + ): + super().__init__(name) + self._my_event = my_event + self._their_event = their_event + + async def store( + self, + context: StorageDriverStoreContext, + payloads: Sequence[Payload], + ) -> list[StorageDriverClaim]: + self._my_event.set() + await asyncio.wait_for(self._their_event.wait(), timeout=2.0) + return await super().store(context, payloads) + + driver_a = BarrierDriver("driver-a", started_a, started_b) + driver_b = BarrierDriver("driver-b", started_b, started_a) + + def selector(_ctx: object, payload: Payload) -> StorageDriver: + return driver_a if payload.ByteSize() < 500 else driver_b + + converter = DataConverter( + external_storage=ExternalStorage( + drivers=[driver_a, driver_b], + driver_selector=selector, + payload_size_threshold=None, + ) + ) + + small_ext = "a" * 100 # routes to driver-a + large_ext = "b" * 1000 # routes to driver-b + + # This will deadlock (and timeout) if the two store() calls are not + # dispatched concurrently. + encoded = await asyncio.wait_for( + converter.encode([small_ext, large_ext]), timeout=5.0 + ) + + decoded = await converter.decode(encoded, [str, str]) + assert decoded == [small_ext, large_ext] + + def test_multiple_drivers_without_selector_raises(self): + """Registering more than one driver without a driver_selector raises + ValueError immediately when constructing ExternalStorage.""" + first = InMemoryTestDriver("driver-a") + second = InMemoryTestDriver("driver-b") + + with pytest.raises( + ValueError, + match=r"^ExternalStorage\.driver_selector must be specified if multiple drivers are registered\.$", + ): + ExternalStorage( + drivers=[first, second], + payload_size_threshold=50, + ) + + def test_duplicate_driver_names_raises(self): + """Registering two drivers with identical names raises ValueError immediately + when constructing ExternalStorage.""" + first = InMemoryTestDriver("dup-name") + duplicate = InMemoryTestDriver("dup-name") + + with pytest.raises( + ValueError, + match=r"^ExternalStorage\.drivers contains multiple drivers with name 'dup-name'\. Each driver must have a unique name\.$", + ): + ExternalStorage( + drivers=[first, duplicate], + driver_selector=lambda _ctx, _p: first, + payload_size_threshold=50, + ) + + +if __name__ == "__main__": + pytest.main([__file__, "-v"]) diff --git a/tests/worker/test_extstore.py b/tests/worker/test_extstore.py new file mode 100644 index 000000000..921e8a3f1 --- /dev/null +++ b/tests/worker/test_extstore.py @@ -0,0 +1,554 @@ +import dataclasses +import uuid +from collections.abc import Sequence +from dataclasses import dataclass +from datetime import timedelta + +import pytest + +import temporalio +import temporalio.converter +from temporalio import activity, workflow +from temporalio.api.common.v1 import Payload +from temporalio.client import Client, WorkflowFailureError, WorkflowHandle +from temporalio.common import RetryPolicy +from temporalio.converter import ( + ExternalStorage, + StorageDriverClaim, + StorageDriverRetrieveContext, + StorageDriverStoreContext, + StorageWarning, +) +from temporalio.exceptions import ActivityError, ApplicationError +from temporalio.testing._workflow import WorkflowEnvironment +from temporalio.worker import Replayer +from tests.helpers import assert_task_fail_eventually, new_worker +from tests.test_extstore import InMemoryTestDriver + + +@dataclass(frozen=True) +class ExtStoreActivityInput: + input_data: str + output_size: int + pass + + +# --------------------------------------------------------------------------- +# Chained-activity scenario +# --------------------------------------------------------------------------- + + +@dataclass(frozen=True) +class ProcessDataInput: + """Input for the first activity: generate a large result.""" + + size: int + + +@dataclass(frozen=True) +class SummarizeInput: + """Input for the second activity: receives the large result from the first.""" + + data: str + + +@activity.defn +async def process_data(input: ProcessDataInput) -> str: + """Produces a large string result that will be stored externally.""" + return "x" * input.size + + +@activity.defn +async def summarize(input: SummarizeInput) -> str: + """Receives the large result and returns a short summary.""" + return f"received {len(input.data)} bytes" + + +@workflow.defn +class ChainedExtStoreWorkflow: + """Workflow that passes a large activity result directly into a second activity. + + This mirrors a common customer pattern: activity A produces a large payload + (e.g. a fetched document or ML inference result) which is too big to store + inline in workflow history, and is then consumed by activity B. External + storage should transparently offload the payload between the two steps + without any special handling in the workflow code. + """ + + @workflow.run + async def run(self, payload_size: int) -> str: + large_result = await workflow.execute_activity( + process_data, + ProcessDataInput(size=payload_size), + schedule_to_close_timeout=timedelta(seconds=10), + ) + return await workflow.execute_activity( + summarize, + SummarizeInput(data=large_result), + schedule_to_close_timeout=timedelta(seconds=10), + ) + + +@activity.defn +async def ext_store_activity( + input: ExtStoreActivityInput, +) -> str: + return "ao" * int(input.output_size / 2) + + +@dataclass(frozen=True) +class ExtStoreWorkflowInput: + input_data: str + activity_input_size: int + activity_output_size: int + output_size: int + max_activity_attempts: int | None = None + + +@workflow.defn +class ExtStoreWorkflow: + @workflow.run + async def run(self, input: ExtStoreWorkflowInput) -> str: + retry_policy = ( + RetryPolicy(maximum_attempts=input.max_activity_attempts) + if input.max_activity_attempts is not None + else None + ) + await workflow.execute_activity( + ext_store_activity, + ExtStoreActivityInput( + input_data="ai" * int(input.activity_input_size / 2), + output_size=input.activity_output_size, + ), + schedule_to_close_timeout=timedelta(seconds=3), + retry_policy=retry_policy, + ) + return "wo" * int(input.output_size / 2) + + +class BadTestDriver(InMemoryTestDriver): + def __init__( + self, + driver_name: str = "bad-driver", + no_store: bool = False, + no_retrieve: bool = False, + raise_payload_not_found: bool = False, + ): + super().__init__(driver_name) + self._no_store = no_store + self._no_retrieve = no_retrieve + self._raise_payload_not_found = raise_payload_not_found + + async def store( + self, + context: StorageDriverStoreContext, + payloads: Sequence[Payload], + ) -> list[StorageDriverClaim]: + if self._no_store: + return [] + return await super().store(context, payloads) + + async def retrieve( + self, + context: StorageDriverRetrieveContext, + claims: Sequence[StorageDriverClaim], + ) -> list[Payload]: + if self._no_retrieve: + return [] + if self._raise_payload_not_found: + raise ApplicationError( + "Payload not found because the bucket does not exist.", + type="BucketNotFoundError", + non_retryable=True, + ) + return await super().retrieve(context, claims) + + +async def test_extstore_activity_input_no_retrieve( + env: WorkflowEnvironment, +): + """When the driver's retrieve returns no payloads for an externalized + activity input, the activity fails and the workflow terminates with a + WorkflowFailureError wrapping an ActivityError.""" + driver = BadTestDriver(no_retrieve=True) + + client = await Client.connect( + env.client.service_client.config.target_host, + namespace=env.client.namespace, + data_converter=dataclasses.replace( + temporalio.converter.default(), + external_storage=ExternalStorage( + drivers=[driver], + payload_size_threshold=1024, + ), + ), + ) + + async with new_worker( + client, ExtStoreWorkflow, activities=[ext_store_activity] + ) as worker: + handle = await client.start_workflow( + ExtStoreWorkflow.run, + ExtStoreWorkflowInput( + input_data="workflow input", + activity_input_size=1000, + activity_output_size=10, + output_size=10, + max_activity_attempts=1, + ), + id=f"workflow-{uuid.uuid4()}", + task_queue=worker.task_queue, + ) + + with pytest.raises(WorkflowFailureError) as err: + await handle.result() + + assert isinstance(err.value.cause, ActivityError) + assert isinstance(err.value.cause.cause, ApplicationError) + assert err.value.cause.cause.message == "Failed decoding arguments" + + +async def test_extstore_activity_result_no_store( + env: WorkflowEnvironment, +): + """When the driver's store returns no claims for an activity result that + exceeds the size threshold, the activity fails to complete and the workflow + terminates with a WorkflowFailureError wrapping an ActivityError.""" + driver = BadTestDriver(no_store=True) + + client = await Client.connect( + env.client.service_client.config.target_host, + namespace=env.client.namespace, + data_converter=dataclasses.replace( + temporalio.converter.default(), + external_storage=ExternalStorage( + drivers=[driver], + payload_size_threshold=1024, + ), + ), + ) + + async with new_worker( + client, ExtStoreWorkflow, activities=[ext_store_activity] + ) as worker: + handle = await client.start_workflow( + ExtStoreWorkflow.run, + ExtStoreWorkflowInput( + input_data="workflow input", + activity_input_size=10, + activity_output_size=1000, + output_size=10, + max_activity_attempts=1, + ), + id=f"workflow-{uuid.uuid4()}", + task_queue=worker.task_queue, + ) + + with pytest.raises(WorkflowFailureError) as err: + await handle.result() + + assert isinstance(err.value.cause, ActivityError) + assert isinstance(err.value.cause.cause, ApplicationError) + assert ( + err.value.cause.cause.message + == "Driver 'bad-driver' returned 0 claims, expected 1" + ) + assert err.value.cause.cause.type == "ValueError" + + +async def test_extstore_worker_missing_driver( + env: WorkflowEnvironment, +): + """Validate that when a worker is provided a workflow history with + external storage references and the worker is not configured for external + storage, it will cause a workflow task failure. + """ + driver = InMemoryTestDriver() + + far_client = await Client.connect( + env.client.service_client.config.target_host, + namespace=env.client.namespace, + data_converter=dataclasses.replace( + temporalio.converter.default(), + external_storage=ExternalStorage( + drivers=[driver], + payload_size_threshold=1024, + ), + ), + ) + + worker_client = await Client.connect( + env.client.service_client.config.target_host, + namespace=env.client.namespace, + ) + + async with new_worker( + worker_client, ExtStoreWorkflow, activities=[ext_store_activity] + ) as worker: + handle = await far_client.start_workflow( + ExtStoreWorkflow.run, + ExtStoreWorkflowInput( + input_data="wi" * 1024, + activity_input_size=10, + activity_output_size=10, + output_size=10, + ), + id=f"workflow-{uuid.uuid4()}", + task_queue=worker.task_queue, + ) + + await assert_task_fail_eventually(handle) + + +async def test_extstore_payload_not_found_fails_workflow( + env: WorkflowEnvironment, +): + """When a non-retryable ApplicationError is raised while retrieving workflow input, + the workflow must fail terminally (not retry as a task failure). + """ + client = await Client.connect( + env.client.service_client.config.target_host, + namespace=env.client.namespace, + data_converter=dataclasses.replace( + temporalio.converter.default(), + external_storage=ExternalStorage( + drivers=[BadTestDriver(raise_payload_not_found=True)], + payload_size_threshold=1024, + ), + ), + ) + + async with new_worker( + client, ExtStoreWorkflow, activities=[ext_store_activity] + ) as worker: + handle = await client.start_workflow( + ExtStoreWorkflow.run, + ExtStoreWorkflowInput( + input_data="wi" * 512, # exceeds 1024-byte threshold + activity_input_size=10, + activity_output_size=10, + output_size=10, + ), + id=f"workflow-{uuid.uuid4()}", + task_queue=worker.task_queue, + execution_timeout=timedelta(seconds=10), + ) + + with pytest.raises(WorkflowFailureError) as exc_info: + await handle.result() + + assert isinstance(exc_info.value.cause, ApplicationError) + assert ( + exc_info.value.cause.message + == "Payload not found because the bucket does not exist." + ) + assert exc_info.value.cause.type == "BucketNotFoundError" + assert exc_info.value.cause.non_retryable is True + + +async def _run_extstore_workflow_and_fetch_history( + env: WorkflowEnvironment, + driver: InMemoryTestDriver, + *, + input_data: str, + activity_output_size: int = 10, +) -> WorkflowHandle: + """Helper: run ExtStoreWorkflow with the given driver and return its history handle.""" + extstore_client = await Client.connect( + env.client.service_client.config.target_host, + namespace=env.client.namespace, + data_converter=dataclasses.replace( + temporalio.converter.default(), + external_storage=ExternalStorage( + drivers=[driver], + payload_size_threshold=512, + ), + ), + ) + async with new_worker( + extstore_client, ExtStoreWorkflow, activities=[ext_store_activity] + ) as worker: + handle = await extstore_client.start_workflow( + ExtStoreWorkflow.run, + ExtStoreWorkflowInput( + input_data=input_data, + activity_input_size=10, + activity_output_size=activity_output_size, + output_size=10, + ), + id=f"workflow-{uuid.uuid4()}", + task_queue=worker.task_queue, + ) + await handle.result() + return handle + + +async def test_replay_extstore_history_fails_without_extstore( + env: WorkflowEnvironment, +) -> None: + """A history with externalized workflow input fails to replay when the + Replayer has no external storage configured.""" + driver = InMemoryTestDriver() + handle = await _run_extstore_workflow_and_fetch_history( + env, + driver, + input_data="wi" * 512, # exceeds 512-byte threshold + ) + history = await handle.fetch_history() + + # Replay without external storage — the reference payload cannot be decoded. + # The middleware emits a StorageWarning when it encounters a reference payload + # with no driver configured. + with pytest.warns( + StorageWarning, + match=r"^\[TMPRL1105\] Detected externally stored payload\(s\) but external storage is not configured\.$", + ): + result = await Replayer(workflows=[ExtStoreWorkflow]).replay_workflow( + history, raise_on_replay_failure=False + ) + # Must be a task-failure RuntimeError, not a NondeterminismError — external + # storage decode failures are distinct from workflow code changes. + assert isinstance(result.replay_failure, RuntimeError) + assert not isinstance(result.replay_failure, workflow.NondeterminismError) + # The message is the full activation-completion failure string; the + # "Failed decoding arguments" text from _convert_payloads is embedded in it. + assert "Failed decoding arguments" in result.replay_failure.args[0] + + +async def test_replay_extstore_history_succeeds_with_correct_extstore( + env: WorkflowEnvironment, +) -> None: + """A history with externalized workflow input replays successfully when the + Replayer is configured with the same storage driver that holds the data.""" + driver = InMemoryTestDriver() + handle = await _run_extstore_workflow_and_fetch_history( + env, driver, input_data="wi" * 512 + ) + history = await handle.fetch_history() + + # Replay with the same populated driver — must succeed. + await Replayer( + workflows=[ExtStoreWorkflow], + data_converter=dataclasses.replace( + temporalio.converter.default(), + external_storage=ExternalStorage( + drivers=[driver], + payload_size_threshold=512, + ), + ), + ).replay_workflow(history) + + +async def test_replay_extstore_history_fails_with_empty_driver( + env: WorkflowEnvironment, +) -> None: + """A history with external storage references fails to replay when the + Replayer has external storage configured but the driver holds no data + (simulates pointing at the wrong backend or a purged store).""" + driver = InMemoryTestDriver() + handle = await _run_extstore_workflow_and_fetch_history( + env, driver, input_data="wi" * 512 + ) + history = await handle.fetch_history() + + # Replay with a fresh empty driver — retrieval will fail. + result = await Replayer( + workflows=[ExtStoreWorkflow], + data_converter=dataclasses.replace( + temporalio.converter.default(), + external_storage=ExternalStorage( + drivers=[InMemoryTestDriver()], + payload_size_threshold=512, + ), + ), + ).replay_workflow(history, raise_on_replay_failure=False) + # InMemoryTestDriver raises ApplicationError for absent keys. + # ApplicationError is re-raised without wrapping, so it propagates + # through decode_activation (before the workflow task runs). The core SDK + # receives an activation failure, issues a FailWorkflow command, but the + # next history event is ActivityTaskScheduled — causing a NondeterminismError. + assert isinstance(result.replay_failure, workflow.NondeterminismError) + + +async def test_replay_extstore_activity_result_fails_without_extstore( + env: WorkflowEnvironment, +) -> None: + """A history where only the activity result was stored externally (the + workflow input is small enough to be inline) also fails to replay without + external storage — verifying that mid-workflow decode failures are caught.""" + driver = InMemoryTestDriver() + handle = await _run_extstore_workflow_and_fetch_history( + env, + driver, + input_data="small", # well under 512 bytes — stays inline + activity_output_size=2048, # 2 KB result — stored externally + ) + history = await handle.fetch_history() + + # Replay without external storage. The workflow input decodes fine, but + # when the ActivityTaskCompleted result is delivered back to the workflow + # coroutine it cannot be decoded. + with pytest.warns( + StorageWarning, + match=r"^\[TMPRL1105\] Detected externally stored payload\(s\) but external storage is not configured\.$", + ): + result = await Replayer(workflows=[ExtStoreWorkflow]).replay_workflow( + history, raise_on_replay_failure=False + ) + # Mid-workflow decode failure is still a task failure (RuntimeError), not + # nondeterminism. + assert isinstance(result.replay_failure, RuntimeError) + assert not isinstance(result.replay_failure, workflow.NondeterminismError) + # The message is the full activation-completion failure string; the + # "Failed decoding arguments" text from _convert_payloads is embedded in it. + assert "Failed decoding arguments" in result.replay_failure.args[0] + + +async def test_extstore_chained_activities( + env: WorkflowEnvironment, +) -> None: + """Large activity output is transparently offloaded and passed to a second activity. + + This is a representative customer scenario: activity A returns a payload that + exceeds the size threshold (e.g. a fetched document), external storage offloads + it so it never bloats workflow history, and activity B receives it as its input + without any special handling in the workflow code. + """ + driver = InMemoryTestDriver() + + client = await Client.connect( + env.client.service_client.config.target_host, + namespace=env.client.namespace, + data_converter=dataclasses.replace( + temporalio.converter.default(), + external_storage=ExternalStorage( + drivers=[driver], + payload_size_threshold=1024, # 1 KB threshold + ), + ), + ) + + # process_data returns 10 KB — well above the 1 KB threshold. + payload_size = 10_000 + + async with new_worker( + client, + ChainedExtStoreWorkflow, + activities=[process_data, summarize], + ) as worker: + result = await client.execute_workflow( + ChainedExtStoreWorkflow.run, + payload_size, + id=f"workflow-{uuid.uuid4()}", + task_queue=worker.task_queue, + execution_timeout=timedelta(seconds=30), + ) + + # The second activity received the full payload and summarized it correctly. + assert result == f"received {payload_size} bytes" + + # External storage was actually used: the large activity result and its + # re-use as the second activity's input should have triggered at least two + # round-trips (one store on completion, one retrieve on the next WFT). + assert driver._store_calls == 2 + assert driver._retrieve_calls == 2 From a43600e06b19d408b453e75551b5272cdb2e646f Mon Sep 17 00:00:00 2001 From: Drew Hoskins Date: Wed, 18 Mar 2026 10:18:23 -0700 Subject: [PATCH 006/226] ADK: Allow overriding summary for Agents without overriding the start to close timeout (#1370) * Allow overriding summary for agents without overriding the start to close timeout * Add test and change activity_options name --------- Co-authored-by: Tim Conley Co-authored-by: tconley1428 --- .../contrib/google_adk_agents/README.md | 3 ++- .../contrib/google_adk_agents/_model.py | 10 +++++---- .../test_google_adk_agents.py | 22 ++++++++++++++++--- 3 files changed, 27 insertions(+), 8 deletions(-) diff --git a/temporalio/contrib/google_adk_agents/README.md b/temporalio/contrib/google_adk_agents/README.md index bb3d0a289..4fe8440d8 100644 --- a/temporalio/contrib/google_adk_agents/README.md +++ b/temporalio/contrib/google_adk_agents/README.md @@ -71,13 +71,14 @@ Model calls are intercepted and executed as Temporal activities with configurabl **Agent (Workflow) Side:** ```python from temporalio.contrib.google_adk_agents import TemporalModel +from temporalio.workflow import ActivityConfig from google.adk import Agent # Add to agent agent = Agent( name="test_agent", - model=TemporalModel("gemini-2.5-pro"), + model=TemporalModel("gemini-2.5-pro", activity_config=ActivityConfig(summary="Researcher Agent")), ) ``` diff --git a/temporalio/contrib/google_adk_agents/_model.py b/temporalio/contrib/google_adk_agents/_model.py index f0b4a0dcd..80079433c 100644 --- a/temporalio/contrib/google_adk_agents/_model.py +++ b/temporalio/contrib/google_adk_agents/_model.py @@ -39,19 +39,21 @@ class TemporalModel(BaseLlm): """A Temporal-based LLM model that executes model invocations as activities.""" def __init__( - self, model_name: str, activity_options: ActivityConfig | None = None + self, model_name: str, activity_config: ActivityConfig | None = None ) -> None: """Initialize the TemporalModel. Args: model_name: The name of the model to use. - activity_options: Configuration options for the activity execution. + activity_config: Configuration options for the activity execution. """ super().__init__(model=model_name) self._model_name = model_name - self._activity_options = activity_options or ActivityConfig( + self._activity_config = ActivityConfig( start_to_close_timeout=timedelta(seconds=60) ) + if activity_config: + self._activity_config.update(activity_config) async def generate_content_async( self, llm_request: LlmRequest, stream: bool = False @@ -68,7 +70,7 @@ async def generate_content_async( responses = await workflow.execute_activity( invoke_model, args=[llm_request], - **self._activity_options, + **self._activity_config, ) for response in responses: yield response diff --git a/tests/contrib/google_adk_agents/test_google_adk_agents.py b/tests/contrib/google_adk_agents/test_google_adk_agents.py index 370a6e235..4d41b6a82 100644 --- a/tests/contrib/google_adk_agents/test_google_adk_agents.py +++ b/tests/contrib/google_adk_agents/test_google_adk_agents.py @@ -52,6 +52,7 @@ ) from temporalio.contrib.opentelemetry import OpenTelemetryPlugin, create_tracer_provider from temporalio.worker import Worker +from temporalio.workflow import ActivityConfig from tests.contrib.opentelemetry.test_opentelemetry import dump_spans logger = logging.getLogger(__name__) @@ -128,21 +129,31 @@ async def run(self, topic: str, model_name: str) -> str | None: # Sub-agent: Researcher researcher = LlmAgent( name="researcher", - model=TemporalModel(model_name), + model=TemporalModel( + model_name, activity_config=ActivityConfig(summary="Researcher Agent") + ), instruction="You are a researcher. Find information about the topic.", ) # Sub-agent: Writer writer = LlmAgent( name="writer", - model=TemporalModel(model_name), + model=TemporalModel( + model_name, activity_config=ActivityConfig(summary="Writer Agent") + ), instruction="You are a poet. Write a haiku based on the research.", ) # Root Agent: Coordinator coordinator = LlmAgent( name="coordinator", - model=TemporalModel(model_name), + model=TemporalModel( + model_name, + activity_config=ActivityConfig( + start_to_close_timeout=timedelta(seconds=30), + summary="Coordinator Agent", + ), + ), instruction="You are a coordinator. Delegate to researcher then writer.", sub_agents=[researcher, writer], ) @@ -551,3 +562,8 @@ async def test_single_agent_telemetry(client: Client): " StartActivity:invoke_model", " RunActivity:invoke_model", ] + + +async def test_unsetting_timeout(): + model = TemporalModel("", ActivityConfig(start_to_close_timeout=None)) + assert model._activity_config.get("start_to_close_timeout", None) is None From 5ed4a4707ead7e5ad4d16cdadce310399d95ae3f Mon Sep 17 00:00:00 2001 From: tconley1428 Date: Thu, 19 Mar 2026 08:30:11 -0700 Subject: [PATCH 007/226] Update python version to 1.24.0 (#1377) --- pyproject.toml | 2 +- temporalio/service.py | 2 +- uv.lock | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 7a2df7ea8..4bcd3f03e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "temporalio" -version = "1.23.0" +version = "1.24.0" description = "Temporal.io Python SDK" authors = [{ name = "Temporal Technologies Inc", email = "sdk@temporal.io" }] requires-python = ">=3.10" diff --git a/temporalio/service.py b/temporalio/service.py index c01f0c32c..85165356c 100644 --- a/temporalio/service.py +++ b/temporalio/service.py @@ -24,7 +24,7 @@ import temporalio.runtime from temporalio.bridge.client import RPCError as BridgeRPCError -__version__ = "1.23.0" +__version__ = "1.24.0" ServiceRequest = TypeVar("ServiceRequest", bound=google.protobuf.message.Message) ServiceResponse = TypeVar("ServiceResponse", bound=google.protobuf.message.Message) diff --git a/uv.lock b/uv.lock index 9921726a0..a70f170b2 100644 --- a/uv.lock +++ b/uv.lock @@ -4268,7 +4268,7 @@ wheels = [ [[package]] name = "temporalio" -version = "1.23.0" +version = "1.24.0" source = { virtual = "." } dependencies = [ { name = "nexus-rpc" }, From 4578c0c671bca7c7c7dbc886ca8bb56dfb64fb6f Mon Sep 17 00:00:00 2001 From: tconley1428 Date: Thu, 19 Mar 2026 15:38:14 -0700 Subject: [PATCH 008/226] Fix wheel tests (#1379) * Limit test files collected in wheel tests * Add pydantic back * Remove branch --- .github/workflows/build-binaries.yml | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/.github/workflows/build-binaries.yml b/.github/workflows/build-binaries.yml index 0b647c250..a16a61365 100644 --- a/.github/workflows/build-binaries.yml +++ b/.github/workflows/build-binaries.yml @@ -4,8 +4,6 @@ on: branches: - main - "releases/*" - - build-binaries-install-whl - permissions: contents: read @@ -69,9 +67,9 @@ jobs: if [ "$RUNNER_OS" = "Windows" ]; then bindir=Scripts fi - ./.venv/$bindir/pip install pytest pytest_asyncio grpcio pydantic opentelemetry-api opentelemetry-sdk python-dateutil 'openai-agents>=0.2.3,<=0.2.9' 'googleapis-common-protos==1.70.0' + ./.venv/$bindir/pip install pytest pytest_asyncio grpcio pydantic ./.venv/$bindir/pip install --prefer-binary ../dist/*.whl - ./.venv/$bindir/python -m pytest -s -k test_workflow_hello + ./.venv/$bindir/python -m pytest -s tests/worker/test_workflow.py -k test_workflow_hello # Upload dist - uses: actions/upload-artifact@v4 From f7da465e877a5dc85ffc4d973cb93fc36bf1cdb1 Mon Sep 17 00:00:00 2001 From: Quinn Klassen Date: Thu, 19 Mar 2026 16:37:06 -0700 Subject: [PATCH 009/226] Remove experimental notices for Nexus (#1381) Co-authored-by: tconley1428 --- README.md | 2 -- temporalio/nexus/__init__.py | 3 --- temporalio/nexus/_operation_context.py | 15 ++------------- temporalio/nexus/_token.py | 3 --- temporalio/worker/_worker.py | 6 ------ temporalio/workflow.py | 12 +----------- 6 files changed, 3 insertions(+), 38 deletions(-) diff --git a/README.md b/README.md index 223a1f113..6e42a2019 100644 --- a/README.md +++ b/README.md @@ -1514,8 +1514,6 @@ code](https://github.com/temporalio/samples-python/blob/main/context_propagation ### Nexus -⚠️ **Nexus support is currently at an experimental release stage. Backwards-incompatible changes are anticipated until a stable release is announced.** ⚠️ - [Nexus](https://github.com/nexus-rpc/) is a synchronous RPC protocol. Arbitrary duration operations that can respond asynchronously are modeled on top of a set of pre-defined synchronous RPCs. diff --git a/temporalio/nexus/__init__.py b/temporalio/nexus/__init__.py index c647b19a8..ea049d90e 100644 --- a/temporalio/nexus/__init__.py +++ b/temporalio/nexus/__init__.py @@ -1,8 +1,5 @@ """Temporal Nexus support -.. warning:: - Nexus APIs are experimental and unstable. - See https://github.com/temporalio/sdk-python/tree/main#nexus """ diff --git a/temporalio/nexus/_operation_context.py b/temporalio/nexus/_operation_context.py index 76bbdcf64..66e675d27 100644 --- a/temporalio/nexus/_operation_context.py +++ b/temporalio/nexus/_operation_context.py @@ -76,9 +76,6 @@ class Info: """Information about the running Nexus operation. - .. warning:: - This API is experimental and unstable. - Retrieved inside a Nexus operation handler via :py:func:`info`. """ @@ -277,11 +274,7 @@ def _add_outbound_links( class WorkflowRunOperationContext(StartOperationContext): - """Context received by a workflow run operation. - - .. warning:: - This API is experimental and unstable. - """ + """Context received by a workflow run operation.""" def __init__(self, *args: Any, **kwargs: Any) -> None: """Initialize the workflow run operation context.""" @@ -541,11 +534,7 @@ async def start_workflow( @dataclass(frozen=True) class NexusCallback: - """Nexus callback to attach to events such as workflow completion. - - .. warning:: - This API is experimental and unstable. - """ + """Nexus callback to attach to events such as workflow completion.""" url: str """Callback URL.""" diff --git a/temporalio/nexus/_token.py b/temporalio/nexus/_token.py index edd95aa21..0a3d27375 100644 --- a/temporalio/nexus/_token.py +++ b/temporalio/nexus/_token.py @@ -18,9 +18,6 @@ class WorkflowHandle(Generic[OutputT]): """A handle to a workflow that is backing a Nexus operation. - .. warning:: - This API is experimental and unstable. - Do not instantiate this directly. Use :py:func:`temporalio.nexus.WorkflowRunOperationContext.start_workflow` to create a handle. diff --git a/temporalio/worker/_worker.py b/temporalio/worker/_worker.py index 2c3a1666d..05151753d 100644 --- a/temporalio/worker/_worker.py +++ b/temporalio/worker/_worker.py @@ -157,9 +157,6 @@ def __init__( may be async functions or non-async functions. nexus_service_handlers: Instances of Nexus service handler classes decorated with :py:func:`@nexusrpc.handler.service_handler`. - - .. warning:: - This parameter is experimental and unstable. workflows: Workflow classes decorated with :py:func:`@workflow.defn`. activity_executor: Concurrent executor to use for non-async @@ -182,9 +179,6 @@ def __init__( nexus_task_executor: Executor to use for non-async Nexus operations. This is required if any operation start methods are non-``async def``. - - .. warning:: - This parameter is experimental and unstable. workflow_runner: Runner for workflows. unsandboxed_workflow_runner: Runner for workflows that opt-out of sandboxing. diff --git a/temporalio/workflow.py b/temporalio/workflow.py index bff25ffe0..dd8565f78 100644 --- a/temporalio/workflow.py +++ b/temporalio/workflow.py @@ -4656,11 +4656,7 @@ async def execute_child_workflow( class NexusOperationHandle(Generic[OutputT]): - """Handle for interacting with a Nexus operation. - - .. warning:: - This API is experimental and unstable. - """ + """Handle for interacting with a Nexus operation.""" # TODO(nexus-preview): should attempts to instantiate directly throw? @@ -5444,9 +5440,6 @@ class NexusOperationCancellationType(IntEnum): class NexusClient(ABC, Generic[ServiceT]): """A client for invoking Nexus operations. - .. warning:: - This API is experimental and unstable. - Example:: nexus_client = workflow.create_nexus_client( @@ -5858,9 +5851,6 @@ def create_nexus_client( ) -> NexusClient[ServiceT]: """Create a Nexus client. - .. warning:: - This API is experimental and unstable. - Args: service: The Nexus service. endpoint: The Nexus endpoint. From 164096bf7932d81d94d6f9ce395328e1669a64ef Mon Sep 17 00:00:00 2001 From: tconley1428 Date: Thu, 19 Mar 2026 18:37:05 -0700 Subject: [PATCH 010/226] Misc ci fixes (#1380) * Invert loop and try catch. Exception can rarely occur outside the catch * Add sleep before validating list activities * Add RPC cancelled retries to assert_eventually * Switch from sleep to assert_eventually * Format --- tests/helpers/__init__.py | 6 ++++++ tests/test_activity.py | 27 ++++++++++++++++----------- tests/worker/test_workflow.py | 35 +++++++++++++++++++---------------- 3 files changed, 41 insertions(+), 27 deletions(-) diff --git a/tests/helpers/__init__.py b/tests/helpers/__init__.py index 1d2e886cc..b783b9003 100644 --- a/tests/helpers/__init__.py +++ b/tests/helpers/__init__.py @@ -71,6 +71,7 @@ async def assert_eventually( *, timeout: timedelta = timedelta(seconds=10), interval: timedelta = timedelta(milliseconds=200), + retry_on_rpc_cancelled: bool = True, ) -> T: start_sec = time.monotonic() while True: @@ -80,6 +81,11 @@ async def assert_eventually( except AssertionError: if timedelta(seconds=time.monotonic() - start_sec) >= timeout: raise + except RPCError as e: + if retry_on_rpc_cancelled and e.status == RPCStatusCode.CANCELLED: + continue + else: + raise await asyncio.sleep(interval.total_seconds()) diff --git a/tests/test_activity.py b/tests/test_activity.py index 0d9bfecad..8e851c8b1 100644 --- a/tests/test_activity.py +++ b/tests/test_activity.py @@ -28,7 +28,7 @@ from temporalio.service import RPCError, RPCStatusCode from temporalio.testing import WorkflowEnvironment from temporalio.worker import Worker -from tests.helpers import assert_eq_eventually +from tests.helpers import assert_eq_eventually, assert_eventually @activity.defn @@ -507,16 +507,21 @@ async def test_list_activities(client: Client, env: WorkflowEnvironment): start_to_close_timeout=timedelta(seconds=5), ) - executions = [ - e async for e in client.list_activities(f'ActivityId = "{activity_id}"') - ] - assert len(executions) == 1 - execution = executions[0] - assert execution.activity_id == activity_id - assert execution.activity_type == "increment" - assert execution.task_queue == task_queue - assert execution.status == ActivityExecutionStatus.RUNNING - assert execution.state_transition_count is None # Not set until activity completes + async def check_executions(): + executions = [ + e async for e in client.list_activities(f'ActivityId = "{activity_id}"') + ] + assert len(executions) == 1 + execution = executions[0] + assert execution.activity_id == activity_id + assert execution.activity_type == "increment" + assert execution.task_queue == task_queue + assert execution.status == ActivityExecutionStatus.RUNNING + assert ( + execution.state_transition_count is None + ) # Not set until activity completes + + await assert_eventually(check_executions) async def test_count_activities(client: Client, env: WorkflowEnvironment): diff --git a/tests/worker/test_workflow.py b/tests/worker/test_workflow.py index 068716e3f..4ef5c29fa 100644 --- a/tests/worker/test_workflow.py +++ b/tests/worker/test_workflow.py @@ -7725,38 +7725,38 @@ async def test_workflow_missing_local_activity_no_activities(client: Client): async def heartbeat_activity( catch_err: bool = True, ) -> temporalio.activity.ActivityCancellationDetails | None: - while True: - try: + try: + while True: activity.heartbeat() # If we have heartbeat details, we are on the second attempt, we have retried due to pause/unpause. if activity.info().heartbeat_details: return activity.cancellation_details() await asyncio.sleep(0.1) - except (CancelledError, asyncio.CancelledError) as err: - if not catch_err: - raise err - return activity.cancellation_details() - finally: - activity.heartbeat("finally-complete") + except (CancelledError, asyncio.CancelledError) as err: + if not catch_err: + raise err + return activity.cancellation_details() + finally: + activity.heartbeat("finally-complete") @activity.defn def sync_heartbeat_activity( catch_err: bool = True, ) -> temporalio.activity.ActivityCancellationDetails | None: - while True: - try: + try: + while True: activity.heartbeat() # If we have heartbeat details, we are on the second attempt, we have retried due to pause/unpause. if activity.info().heartbeat_details: return activity.cancellation_details() time.sleep(0.1) - except (CancelledError, asyncio.CancelledError) as err: - if not catch_err: - raise err - return activity.cancellation_details() - finally: - activity.heartbeat("finally-complete") + except (CancelledError, asyncio.CancelledError) as err: + if not catch_err: + raise err + return activity.cancellation_details() + finally: + activity.heartbeat("finally-complete") @workflow.defn @@ -7769,6 +7769,7 @@ async def run( result.append( await workflow.execute_activity( sync_heartbeat_activity, + True, activity_id=activity_id, start_to_close_timeout=timedelta(seconds=10), heartbeat_timeout=timedelta(seconds=2), @@ -7778,6 +7779,7 @@ async def run( result.append( await workflow.execute_activity( heartbeat_activity, + True, activity_id=f"{activity_id}-2", start_to_close_timeout=timedelta(seconds=10), heartbeat_timeout=timedelta(seconds=2), @@ -8348,6 +8350,7 @@ async def test_previous_run_failure(client: Client): task_queue=worker.task_queue, retry_policy=RetryPolicy( initial_interval=timedelta(milliseconds=10), + maximum_attempts=2, ), ) result = await handle.result() From 8f003b4f842462a643be23743d5c4a3c4d8249a2 Mon Sep 17 00:00:00 2001 From: tconley1428 Date: Fri, 20 Mar 2026 07:04:02 -0700 Subject: [PATCH 011/226] Remove experimental notices from openai agents except otel integration (#1382) * Remove experimental notices from openai agents except otel integration * Fix indentation * More docstyle fixing --- temporalio/contrib/openai_agents/__init__.py | 4 - .../openai_agents/_temporal_openai_agents.py | 44 ++-------- .../openai_agents/_trace_interceptor.py | 4 - temporalio/contrib/openai_agents/testing.py | 83 ++++--------------- temporalio/contrib/openai_agents/workflow.py | 27 +----- 5 files changed, 20 insertions(+), 142 deletions(-) diff --git a/temporalio/contrib/openai_agents/__init__.py b/temporalio/contrib/openai_agents/__init__.py index eeefbff8c..6d64b0b07 100644 --- a/temporalio/contrib/openai_agents/__init__.py +++ b/temporalio/contrib/openai_agents/__init__.py @@ -2,10 +2,6 @@ This module provides compatibility between the `OpenAI Agents SDK `_ and Temporal workflows. - -.. warning:: - This module is experimental and may change in future versions. - Use with caution in production environments. """ from temporalio.contrib.openai_agents._mcp import ( diff --git a/temporalio/contrib/openai_agents/_temporal_openai_agents.py b/temporalio/contrib/openai_agents/_temporal_openai_agents.py index 16a1403ef..39168d0fd 100644 --- a/temporalio/contrib/openai_agents/_temporal_openai_agents.py +++ b/temporalio/contrib/openai_agents/_temporal_openai_agents.py @@ -44,33 +44,10 @@ @contextmanager -def set_open_ai_agent_temporal_overrides( +def _set_open_ai_agent_temporal_overrides( model_params: ModelActivityParameters, start_spans_in_replay: bool = False, ): - """Configure Temporal-specific overrides for OpenAI agents. - - .. warning:: - This API is experimental and may change in future versions. - Use with caution in production environments. Future versions may wrap the worker directly - instead of requiring this context manager. - - This context manager sets up the necessary Temporal-specific runners and trace providers - for running OpenAI agents within Temporal workflows. It should be called in the main - entry point of your application before initializing the Temporal client and worker. - - The context manager handles: - 1. Setting up a Temporal-specific runner for OpenAI agents - 2. Configuring a Temporal-aware trace provider - 3. Restoring previous settings when the context exits - - Args: - model_params: Configuration parameters for Temporal activity execution of model calls. - start_spans_in_replay: If set to true, start spans even during replay. Primarily used for otel integration. - - Returns: - A context manager that yields the configured TemporalTraceProvider. - """ previous_runner = get_default_agent_runner() previous_trace_provider = get_trace_provider() provider = TemporalTraceProvider( @@ -111,10 +88,6 @@ def _data_converter(converter: DataConverter | None) -> DataConverter: class OpenAIAgentsPlugin(SimplePlugin): """Temporal plugin for integrating OpenAI agents with Temporal workflows. - .. warning:: - This class is experimental and may change in future versions. - Use with caution in production environments. - This plugin provides seamless integration between the OpenAI Agents SDK and Temporal workflows. It automatically configures the necessary interceptors, activities, and data converters to enable OpenAI agents to run within @@ -127,16 +100,6 @@ class OpenAIAgentsPlugin(SimplePlugin): 4. Automatically registers MCP server activities and manages their lifecycles 5. Manages the OpenAI agent runtime overrides during worker execution - Args: - model_params: Configuration parameters for Temporal activity execution - of model calls. If None, default parameters will be used. - model_provider: Optional model provider for custom model implementations. - Useful for testing or custom model integrations. - mcp_server_providers: Sequence of MCP servers to automatically register with the worker. - The plugin will wrap each server in a TemporalMCPServer if needed and - manage their connection lifecycles tied to the worker lifetime. This is - the recommended way to use MCP servers with Temporal workflows. - Example: >>> from temporalio.client import Client >>> from temporalio.worker import Worker @@ -201,6 +164,9 @@ def __init__( but should not be disabled on all workers, or agents will not be able to progress. add_temporal_spans: Whether to add temporal spans to traces use_otel_instrumentation: If set to true, enable open telemetry instrumentation. + Warning: use_otel_instrumentation is experimental and behavior may change in future versions. + Use with caution in production environments. + """ if model_params is None: model_params = ModelActivityParameters() @@ -280,7 +246,7 @@ def workflow_runner(runner: WorkflowRunner | None) -> WorkflowRunner: @asynccontextmanager async def run_context() -> AsyncIterator[None]: with self.tracing_context(): - with set_open_ai_agent_temporal_overrides( + with _set_open_ai_agent_temporal_overrides( model_params, start_spans_in_replay=use_otel_instrumentation ): yield diff --git a/temporalio/contrib/openai_agents/_trace_interceptor.py b/temporalio/contrib/openai_agents/_trace_interceptor.py index c000314da..66297e20b 100644 --- a/temporalio/contrib/openai_agents/_trace_interceptor.py +++ b/temporalio/contrib/openai_agents/_trace_interceptor.py @@ -65,10 +65,6 @@ class OpenAIAgentsContextPropagationInterceptor( ): """Interceptor that propagates OpenAI agent tracing context through Temporal workflows and activities. - .. warning:: - This API is experimental and may change in future versions. - Use with caution in production environments. - This interceptor enables tracing of OpenAI agent operations across Temporal workflows and activities. It propagates trace context through workflow and activity boundaries, allowing for end-to-end tracing of agent operations. diff --git a/temporalio/contrib/openai_agents/testing.py b/temporalio/contrib/openai_agents/testing.py index 45a7a1465..d4641105c 100644 --- a/temporalio/contrib/openai_agents/testing.py +++ b/temporalio/contrib/openai_agents/testing.py @@ -39,19 +39,11 @@ class ResponseBuilders: - """Builders for creating model responses for testing. - - .. warning:: - This API is experimental and may change in the future. - """ + """Builders for creating model responses for testing.""" @staticmethod def model_response(output: TResponseOutputItem) -> ModelResponse: - """Create a ModelResponse with the given output. - - .. warning:: - This API is experimental and may change in the future. - """ + """Create a ModelResponse with the given output.""" return ModelResponse( output=[output], usage=Usage(), @@ -60,11 +52,7 @@ def model_response(output: TResponseOutputItem) -> ModelResponse: @staticmethod def response_output_message(text: str) -> ResponseOutputMessage: - """Create a ResponseOutputMessage with text content. - - .. warning:: - This API is experimental and may change in the future. - """ + """Create a ResponseOutputMessage with text content.""" return ResponseOutputMessage( id="", content=[ @@ -81,11 +69,7 @@ def response_output_message(text: str) -> ResponseOutputMessage: @staticmethod def tool_call(arguments: str, name: str) -> ModelResponse: - """Create a ModelResponse with a function tool call. - - .. warning:: - This API is experimental and may change in the future. - """ + """Create a ModelResponse with a function tool call.""" return ResponseBuilders.model_response( ResponseFunctionToolCall( arguments=arguments, @@ -99,57 +83,33 @@ def tool_call(arguments: str, name: str) -> ModelResponse: @staticmethod def output_message(text: str) -> ModelResponse: - """Create a ModelResponse with an output message. - - .. warning:: - This API is experimental and may change in the future. - """ + """Create a ModelResponse with an output message.""" return ResponseBuilders.model_response( ResponseBuilders.response_output_message(text) ) class TestModelProvider(ModelProvider): - """Test model provider which simply returns the given module. - - .. warning:: - This API is experimental and may change in the future. - """ + """Test model provider which simply returns the given module.""" __test__ = False def __init__(self, model: Model): - """Initialize a test model provider with a model. - - .. warning:: - This API is experimental and may change in the future. - """ + """Initialize a test model provider with a model.""" self._model = model def get_model(self, model_name: str | None) -> Model: - """Get a model from the model provider. - - .. warning:: - This API is experimental and may change in the future. - """ + """Get a model from the model provider.""" return self._model class TestModel(Model): - """Test model for use mocking model responses. - - .. warning:: - This API is experimental and may change in the future. - """ + """Test model for use mocking model responses.""" __test__ = False def __init__(self, fn: Callable[[], ModelResponse]) -> None: - """Initialize a test model with a callable. - - .. warning:: - This API is experimental and may change in the future. - """ + """Initialize a test model with a callable.""" self.fn = fn async def get_response( @@ -182,11 +142,7 @@ def stream_response( @staticmethod def returning_responses(responses: list[ModelResponse]) -> "TestModel": - """Create a mock model which sequentially returns responses from a list. - - .. warning:: - This API is experimental and may change in the future. - """ + """Create a mock model which sequentially returns responses from a list.""" i = iter(responses) return TestModel(lambda: next(i)) @@ -197,9 +153,6 @@ class AgentEnvironment: This async context manager provides a convenient way to set up testing environments for OpenAI agents with mocked model calls and Temporal integration. - .. warning:: - This API is experimental and may change in the future. - Example: >>> from temporalio.contrib.openai_agents.testing import AgentEnvironment, TestModelProvider, ResponseBuilders >>> from temporalio.client import Client @@ -246,9 +199,8 @@ def __init__( register_activities: Whether to register activities during worker execution. add_temporal_spans: Whether to add temporal spans to traces use_otel_instrumentation: If set to true, enable open telemetry instrumentation. - - .. warning:: - This API is experimental and may change in the future. + Warning: use_otel_instrumentation is experimental and behavior may change in future versions. + Use with caution in production environments. """ self._model_params = model_params self._model_provider = None @@ -289,9 +241,6 @@ def applied_on_client(self, client: Client) -> Client: Returns: A new Client instance with the OpenAI agents plugin applied. - - .. warning:: - This API is experimental and may change in the future. """ if self._plugin is None: raise RuntimeError( @@ -305,11 +254,7 @@ def applied_on_client(self, client: Client) -> Client: @property def openai_agents_plugin(self) -> OpenAIAgentsPlugin: - """Get the underlying OpenAI agents plugin. - - .. warning:: - This API is experimental and may change in the future. - """ + """Get the underlying OpenAI agents plugin.""" if self._plugin is None: raise RuntimeError( "AgentEnvironment must be entered before accessing plugin" diff --git a/temporalio/contrib/openai_agents/workflow.py b/temporalio/contrib/openai_agents/workflow.py index 772bf4555..cf9ddbc70 100644 --- a/temporalio/contrib/openai_agents/workflow.py +++ b/temporalio/contrib/openai_agents/workflow.py @@ -51,10 +51,6 @@ def activity_as_tool( ) -> Tool: """Convert a single Temporal activity function to an OpenAI agent tool. - .. warning:: - This API is experimental and may change in future versions. - Use with caution in production environments. - This function takes a Temporal activity function and converts it into an OpenAI agent tool that can be used by the agent to execute the activity during workflow execution. The tool will automatically handle the conversion @@ -171,10 +167,6 @@ def nexus_operation_as_tool( ) -> Tool: """Convert a Nexus operation into an OpenAI agent tool. - .. warning:: - This API is experimental and may change in future versions. - Use with caution in production environments. - This function takes a Nexus operation and converts it into an OpenAI agent tool that can be used by the agent to execute the operation during workflow execution. The tool will automatically handle the conversion @@ -257,10 +249,6 @@ def stateless_mcp_server( ) -> "MCPServer": """A stateless MCP server implementation for Temporal workflows. - .. warning:: - This API is experimental and may change in future versions. - Use with caution in production environments. - This uses a TemporalMCPServer of the same name registered with the OpenAIAgents plugin to implement durable MCP operations statelessly. @@ -292,10 +280,6 @@ def stateful_mcp_server( ) -> AbstractAsyncContextManager["MCPServer"]: """A stateful MCP server implementation for Temporal workflows. - .. warning:: - This API is experimental and may change in future versions. - Use with caution in production environments. - This wraps an MCP server to maintain a persistent connection throughout the workflow execution. It creates a dedicated worker that stays connected to the MCP server and processes operations on a dedicated task queue. @@ -327,10 +311,6 @@ def stateful_mcp_server( class ToolSerializationError(TemporalError): """Error that occurs when a tool output could not be serialized. - .. warning:: - This exception is experimental and may change in future versions. - Use with caution in production environments. - This exception is raised when a tool (created from an activity or Nexus operation) returns a value that cannot be properly serialized for use by the OpenAI agent. All tool outputs must be convertible to strings for the agent to process them. @@ -351,9 +331,4 @@ class ToolSerializationError(TemporalError): class AgentsWorkflowError(TemporalError): - """Error that occurs when the agents SDK raises an error which should terminate the calling workflow or update. - - .. warning:: - This exception is experimental and may change in future versions. - Use with caution in production environments. - """ + """Error that occurs when the agents SDK raises an error which should terminate the calling workflow or update.""" From 8988e5bbd7cfb27fc84ac36c0da2d69a411ace31 Mon Sep 17 00:00:00 2001 From: Justin Anderson <44687433+jmaeagle99@users.noreply.github.com> Date: Mon, 23 Mar 2026 09:58:27 -0700 Subject: [PATCH 012/226] Report driver types through worker heartbeat (#1371) --- temporalio/api/history/v1/__init__.py | 2 + temporalio/api/history/v1/message_pb2.py | 268 ++++++++++-------- temporalio/api/history/v1/message_pb2.pyi | 53 ++++ temporalio/api/worker/v1/__init__.py | 4 + temporalio/api/worker/v1/message_pb2.py | 40 ++- temporalio/api/worker/v1/message_pb2.pyi | 156 ++++++++++ .../v1/request_response_pb2.py | 130 +++++---- .../v1/request_response_pb2.pyi | 30 +- temporalio/bridge/sdk-core | 2 +- temporalio/bridge/src/worker.rs | 9 +- temporalio/bridge/worker.py | 1 + temporalio/worker/_replayer.py | 15 +- temporalio/worker/_worker.py | 8 + tests/worker/test_extstore.py | 62 ++++ 14 files changed, 575 insertions(+), 205 deletions(-) diff --git a/temporalio/api/history/v1/__init__.py b/temporalio/api/history/v1/__init__.py index 649a97cc7..96160cf4f 100644 --- a/temporalio/api/history/v1/__init__.py +++ b/temporalio/api/history/v1/__init__.py @@ -13,6 +13,7 @@ ChildWorkflowExecutionStartedEventAttributes, ChildWorkflowExecutionTerminatedEventAttributes, ChildWorkflowExecutionTimedOutEventAttributes, + DeclinedTargetVersionUpgrade, ExternalWorkflowExecutionCancelRequestedEventAttributes, ExternalWorkflowExecutionSignaledEventAttributes, History, @@ -77,6 +78,7 @@ "ChildWorkflowExecutionStartedEventAttributes", "ChildWorkflowExecutionTerminatedEventAttributes", "ChildWorkflowExecutionTimedOutEventAttributes", + "DeclinedTargetVersionUpgrade", "ExternalWorkflowExecutionCancelRequestedEventAttributes", "ExternalWorkflowExecutionSignaledEventAttributes", "History", diff --git a/temporalio/api/history/v1/message_pb2.py b/temporalio/api/history/v1/message_pb2.py index 858167f85..55a236cdb 100644 --- a/temporalio/api/history/v1/message_pb2.py +++ b/temporalio/api/history/v1/message_pb2.py @@ -55,13 +55,16 @@ ) DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile( - b'\n%temporal/api/history/v1/message.proto\x12\x17temporal.api.history.v1\x1a\x1egoogle/protobuf/duration.proto\x1a\x1fgoogle/protobuf/timestamp.proto\x1a&temporal/api/enums/v1/event_type.proto\x1a(temporal/api/enums/v1/failed_cause.proto\x1a"temporal/api/enums/v1/update.proto\x1a$temporal/api/enums/v1/workflow.proto\x1a$temporal/api/common/v1/message.proto\x1a(temporal/api/deployment/v1/message.proto\x1a%temporal/api/failure/v1/message.proto\x1a\'temporal/api/taskqueue/v1/message.proto\x1a$temporal/api/update/v1/message.proto\x1a&temporal/api/workflow/v1/message.proto\x1a\x30temporal/api/sdk/v1/task_complete_metadata.proto\x1a\'temporal/api/sdk/v1/user_metadata.proto"\xb1\x10\n\'WorkflowExecutionStartedEventAttributes\x12;\n\rworkflow_type\x18\x01 \x01(\x0b\x32$.temporal.api.common.v1.WorkflowType\x12!\n\x19parent_workflow_namespace\x18\x02 \x01(\t\x12$\n\x1cparent_workflow_namespace_id\x18\x1b \x01(\t\x12L\n\x19parent_workflow_execution\x18\x03 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12!\n\x19parent_initiated_event_id\x18\x04 \x01(\x03\x12\x38\n\ntask_queue\x18\x05 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12/\n\x05input\x18\x06 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12=\n\x1aworkflow_execution_timeout\x18\x07 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x37\n\x14workflow_run_timeout\x18\x08 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x38\n\x15workflow_task_timeout\x18\t \x01(\x0b\x32\x19.google.protobuf.Duration\x12"\n\x1a\x63ontinued_execution_run_id\x18\n \x01(\t\x12@\n\tinitiator\x18\x0b \x01(\x0e\x32-.temporal.api.enums.v1.ContinueAsNewInitiator\x12;\n\x11\x63ontinued_failure\x18\x0c \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12@\n\x16last_completion_result\x18\r \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12!\n\x19original_execution_run_id\x18\x0e \x01(\t\x12\x10\n\x08identity\x18\x0f \x01(\t\x12\x1e\n\x16\x66irst_execution_run_id\x18\x10 \x01(\t\x12\x39\n\x0cretry_policy\x18\x11 \x01(\x0b\x32#.temporal.api.common.v1.RetryPolicy\x12\x0f\n\x07\x61ttempt\x18\x12 \x01(\x05\x12\x46\n"workflow_execution_expiration_time\x18\x13 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x15\n\rcron_schedule\x18\x14 \x01(\t\x12>\n\x1b\x66irst_workflow_task_backoff\x18\x15 \x01(\x0b\x32\x19.google.protobuf.Duration\x12*\n\x04memo\x18\x16 \x01(\x0b\x32\x1c.temporal.api.common.v1.Memo\x12\x43\n\x11search_attributes\x18\x17 \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes\x12\x45\n\x16prev_auto_reset_points\x18\x18 \x01(\x0b\x32%.temporal.api.workflow.v1.ResetPoints\x12.\n\x06header\x18\x19 \x01(\x0b\x32\x1e.temporal.api.common.v1.Header\x12&\n\x1eparent_initiated_event_version\x18\x1a \x01(\x03\x12\x13\n\x0bworkflow_id\x18\x1c \x01(\t\x12L\n\x14source_version_stamp\x18\x1d \x01(\x0b\x32*.temporal.api.common.v1.WorkerVersionStampB\x02\x18\x01\x12>\n\x14\x63ompletion_callbacks\x18\x1e \x03(\x0b\x32 .temporal.api.common.v1.Callback\x12J\n\x17root_workflow_execution\x18\x1f \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x1e\n\x12inherited_build_id\x18 \x01(\tB\x02\x18\x01\x12I\n\x13versioning_override\x18! \x01(\x0b\x32,.temporal.api.workflow.v1.VersioningOverride\x12\x33\n\'parent_pinned_worker_deployment_version\x18" \x01(\tB\x02\x18\x01\x12\x32\n\x08priority\x18# \x01(\x0b\x32 .temporal.api.common.v1.Priority\x12U\n\x18inherited_pinned_version\x18% \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersion\x12Y\n\x1binherited_auto_upgrade_info\x18\' \x01(\x0b\x32\x34.temporal.api.deployment.v1.InheritedAutoUpgradeInfo\x12 \n\x18\x65\x61ger_execution_accepted\x18& \x01(\x08J\x04\x08$\x10%R parent_pinned_deployment_version"\xa5\x01\n)WorkflowExecutionCompletedEventAttributes\x12\x30\n\x06result\x18\x01 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12(\n workflow_task_completed_event_id\x18\x02 \x01(\x03\x12\x1c\n\x14new_execution_run_id\x18\x03 \x01(\t"\xdb\x01\n&WorkflowExecutionFailedEventAttributes\x12\x31\n\x07\x66\x61ilure\x18\x01 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12\x36\n\x0bretry_state\x18\x02 \x01(\x0e\x32!.temporal.api.enums.v1.RetryState\x12(\n workflow_task_completed_event_id\x18\x03 \x01(\x03\x12\x1c\n\x14new_execution_run_id\x18\x04 \x01(\t"\x80\x01\n(WorkflowExecutionTimedOutEventAttributes\x12\x36\n\x0bretry_state\x18\x01 \x01(\x0e\x32!.temporal.api.enums.v1.RetryState\x12\x1c\n\x14new_execution_run_id\x18\x02 \x01(\t"\xa5\x07\n.WorkflowExecutionContinuedAsNewEventAttributes\x12\x1c\n\x14new_execution_run_id\x18\x01 \x01(\t\x12;\n\rworkflow_type\x18\x02 \x01(\x0b\x32$.temporal.api.common.v1.WorkflowType\x12\x38\n\ntask_queue\x18\x03 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12/\n\x05input\x18\x04 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x37\n\x14workflow_run_timeout\x18\x05 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x38\n\x15workflow_task_timeout\x18\x06 \x01(\x0b\x32\x19.google.protobuf.Duration\x12(\n workflow_task_completed_event_id\x18\x07 \x01(\x03\x12\x39\n\x16\x62\x61\x63koff_start_interval\x18\x08 \x01(\x0b\x32\x19.google.protobuf.Duration\x12@\n\tinitiator\x18\t \x01(\x0e\x32-.temporal.api.enums.v1.ContinueAsNewInitiator\x12\x35\n\x07\x66\x61ilure\x18\n \x01(\x0b\x32 .temporal.api.failure.v1.FailureB\x02\x18\x01\x12@\n\x16last_completion_result\x18\x0b \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12.\n\x06header\x18\x0c \x01(\x0b\x32\x1e.temporal.api.common.v1.Header\x12*\n\x04memo\x18\r \x01(\x0b\x32\x1c.temporal.api.common.v1.Memo\x12\x43\n\x11search_attributes\x18\x0e \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes\x12\x1c\n\x10inherit_build_id\x18\x0f \x01(\x08\x42\x02\x18\x01\x12[\n\x1binitial_versioning_behavior\x18\x10 \x01(\x0e\x32\x36.temporal.api.enums.v1.ContinueAsNewVersioningBehavior"\xac\x01\n$WorkflowTaskScheduledEventAttributes\x12\x38\n\ntask_queue\x18\x01 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12\x39\n\x16start_to_close_timeout\x18\x02 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x0f\n\x07\x61ttempt\x18\x03 \x01(\x05"\xa0\x03\n"WorkflowTaskStartedEventAttributes\x12\x1a\n\x12scheduled_event_id\x18\x01 \x01(\x03\x12\x10\n\x08identity\x18\x02 \x01(\t\x12\x12\n\nrequest_id\x18\x03 \x01(\t\x12\x1f\n\x17suggest_continue_as_new\x18\x04 \x01(\x08\x12Z\n\x1fsuggest_continue_as_new_reasons\x18\x08 \x03(\x0e\x32\x31.temporal.api.enums.v1.SuggestContinueAsNewReason\x12\x30\n(target_worker_deployment_version_changed\x18\t \x01(\x08\x12\x1a\n\x12history_size_bytes\x18\x05 \x01(\x03\x12\x46\n\x0eworker_version\x18\x06 \x01(\x0b\x32*.temporal.api.common.v1.WorkerVersionStampB\x02\x18\x01\x12%\n\x19\x62uild_id_redirect_counter\x18\x07 \x01(\x03\x42\x02\x18\x01"\x82\x05\n$WorkflowTaskCompletedEventAttributes\x12\x1a\n\x12scheduled_event_id\x18\x01 \x01(\x03\x12\x18\n\x10started_event_id\x18\x02 \x01(\x03\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x1b\n\x0f\x62inary_checksum\x18\x04 \x01(\tB\x02\x18\x01\x12\x46\n\x0eworker_version\x18\x05 \x01(\x0b\x32*.temporal.api.common.v1.WorkerVersionStampB\x02\x18\x01\x12H\n\x0csdk_metadata\x18\x06 \x01(\x0b\x32\x32.temporal.api.sdk.v1.WorkflowTaskCompletedMetadata\x12\x43\n\x11metering_metadata\x18\r \x01(\x0b\x32(.temporal.api.common.v1.MeteringMetadata\x12>\n\ndeployment\x18\x07 \x01(\x0b\x32&.temporal.api.deployment.v1.DeploymentB\x02\x18\x01\x12\x46\n\x13versioning_behavior\x18\x08 \x01(\x0e\x32).temporal.api.enums.v1.VersioningBehavior\x12%\n\x19worker_deployment_version\x18\t \x01(\tB\x02\x18\x01\x12\x1e\n\x16worker_deployment_name\x18\n \x01(\t\x12O\n\x12\x64\x65ployment_version\x18\x0b \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersion"\x95\x01\n#WorkflowTaskTimedOutEventAttributes\x12\x1a\n\x12scheduled_event_id\x18\x01 \x01(\x03\x12\x18\n\x10started_event_id\x18\x02 \x01(\x03\x12\x38\n\x0ctimeout_type\x18\x03 \x01(\x0e\x32".temporal.api.enums.v1.TimeoutType"\x87\x03\n!WorkflowTaskFailedEventAttributes\x12\x1a\n\x12scheduled_event_id\x18\x01 \x01(\x03\x12\x18\n\x10started_event_id\x18\x02 \x01(\x03\x12=\n\x05\x63\x61use\x18\x03 \x01(\x0e\x32..temporal.api.enums.v1.WorkflowTaskFailedCause\x12\x31\n\x07\x66\x61ilure\x18\x04 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12\x10\n\x08identity\x18\x05 \x01(\t\x12\x13\n\x0b\x62\x61se_run_id\x18\x06 \x01(\t\x12\x12\n\nnew_run_id\x18\x07 \x01(\t\x12\x1a\n\x12\x66ork_event_version\x18\x08 \x01(\x03\x12\x1b\n\x0f\x62inary_checksum\x18\t \x01(\tB\x02\x18\x01\x12\x46\n\x0eworker_version\x18\n \x01(\x0b\x32*.temporal.api.common.v1.WorkerVersionStampB\x02\x18\x01"\xc2\x05\n$ActivityTaskScheduledEventAttributes\x12\x13\n\x0b\x61\x63tivity_id\x18\x01 \x01(\t\x12;\n\ractivity_type\x18\x02 \x01(\x0b\x32$.temporal.api.common.v1.ActivityType\x12\x38\n\ntask_queue\x18\x04 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12.\n\x06header\x18\x05 \x01(\x0b\x32\x1e.temporal.api.common.v1.Header\x12/\n\x05input\x18\x06 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12<\n\x19schedule_to_close_timeout\x18\x07 \x01(\x0b\x32\x19.google.protobuf.Duration\x12<\n\x19schedule_to_start_timeout\x18\x08 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x39\n\x16start_to_close_timeout\x18\t \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x34\n\x11heartbeat_timeout\x18\n \x01(\x0b\x32\x19.google.protobuf.Duration\x12(\n workflow_task_completed_event_id\x18\x0b \x01(\x03\x12\x39\n\x0cretry_policy\x18\x0c \x01(\x0b\x32#.temporal.api.common.v1.RetryPolicy\x12!\n\x15use_workflow_build_id\x18\r \x01(\x08\x42\x02\x18\x01\x12\x32\n\x08priority\x18\x0e \x01(\x0b\x32 .temporal.api.common.v1.PriorityJ\x04\x08\x03\x10\x04"\x9e\x02\n"ActivityTaskStartedEventAttributes\x12\x1a\n\x12scheduled_event_id\x18\x01 \x01(\x03\x12\x10\n\x08identity\x18\x02 \x01(\t\x12\x12\n\nrequest_id\x18\x03 \x01(\t\x12\x0f\n\x07\x61ttempt\x18\x04 \x01(\x05\x12\x36\n\x0clast_failure\x18\x05 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12\x46\n\x0eworker_version\x18\x06 \x01(\x0b\x32*.temporal.api.common.v1.WorkerVersionStampB\x02\x18\x01\x12%\n\x19\x62uild_id_redirect_counter\x18\x07 \x01(\x03\x42\x02\x18\x01"\xe8\x01\n$ActivityTaskCompletedEventAttributes\x12\x30\n\x06result\x18\x01 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x1a\n\x12scheduled_event_id\x18\x02 \x01(\x03\x12\x18\n\x10started_event_id\x18\x03 \x01(\x03\x12\x10\n\x08identity\x18\x04 \x01(\t\x12\x46\n\x0eworker_version\x18\x05 \x01(\x0b\x32*.temporal.api.common.v1.WorkerVersionStampB\x02\x18\x01"\x9e\x02\n!ActivityTaskFailedEventAttributes\x12\x31\n\x07\x66\x61ilure\x18\x01 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12\x1a\n\x12scheduled_event_id\x18\x02 \x01(\x03\x12\x18\n\x10started_event_id\x18\x03 \x01(\x03\x12\x10\n\x08identity\x18\x04 \x01(\t\x12\x36\n\x0bretry_state\x18\x05 \x01(\x0e\x32!.temporal.api.enums.v1.RetryState\x12\x46\n\x0eworker_version\x18\x06 \x01(\x0b\x32*.temporal.api.common.v1.WorkerVersionStampB\x02\x18\x01"\xc6\x01\n#ActivityTaskTimedOutEventAttributes\x12\x31\n\x07\x66\x61ilure\x18\x01 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12\x1a\n\x12scheduled_event_id\x18\x02 \x01(\x03\x12\x18\n\x10started_event_id\x18\x03 \x01(\x03\x12\x36\n\x0bretry_state\x18\x04 \x01(\x0e\x32!.temporal.api.enums.v1.RetryState"r\n*ActivityTaskCancelRequestedEventAttributes\x12\x1a\n\x12scheduled_event_id\x18\x01 \x01(\x03\x12(\n workflow_task_completed_event_id\x18\x02 \x01(\x03"\x92\x02\n#ActivityTaskCanceledEventAttributes\x12\x31\n\x07\x64\x65tails\x18\x01 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12(\n latest_cancel_requested_event_id\x18\x02 \x01(\x03\x12\x1a\n\x12scheduled_event_id\x18\x03 \x01(\x03\x12\x18\n\x10started_event_id\x18\x04 \x01(\x03\x12\x10\n\x08identity\x18\x05 \x01(\t\x12\x46\n\x0eworker_version\x18\x06 \x01(\x0b\x32*.temporal.api.common.v1.WorkerVersionStampB\x02\x18\x01"\x93\x01\n\x1bTimerStartedEventAttributes\x12\x10\n\x08timer_id\x18\x01 \x01(\t\x12\x38\n\x15start_to_fire_timeout\x18\x02 \x01(\x0b\x32\x19.google.protobuf.Duration\x12(\n workflow_task_completed_event_id\x18\x03 \x01(\x03"G\n\x19TimerFiredEventAttributes\x12\x10\n\x08timer_id\x18\x01 \x01(\t\x12\x18\n\x10started_event_id\x18\x02 \x01(\x03"\x86\x01\n\x1cTimerCanceledEventAttributes\x12\x10\n\x08timer_id\x18\x01 \x01(\t\x12\x18\n\x10started_event_id\x18\x02 \x01(\x03\x12(\n workflow_task_completed_event_id\x18\x03 \x01(\x03\x12\x10\n\x08identity\x18\x04 \x01(\t"\xc7\x01\n/WorkflowExecutionCancelRequestedEventAttributes\x12\r\n\x05\x63\x61use\x18\x01 \x01(\t\x12#\n\x1b\x65xternal_initiated_event_id\x18\x02 \x01(\x03\x12N\n\x1b\x65xternal_workflow_execution\x18\x03 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x10\n\x08identity\x18\x04 \x01(\t"\x87\x01\n(WorkflowExecutionCanceledEventAttributes\x12(\n workflow_task_completed_event_id\x18\x01 \x01(\x03\x12\x31\n\x07\x64\x65tails\x18\x02 \x01(\x0b\x32 .temporal.api.common.v1.Payloads"\xe9\x02\n\x1dMarkerRecordedEventAttributes\x12\x13\n\x0bmarker_name\x18\x01 \x01(\t\x12T\n\x07\x64\x65tails\x18\x02 \x03(\x0b\x32\x43.temporal.api.history.v1.MarkerRecordedEventAttributes.DetailsEntry\x12(\n workflow_task_completed_event_id\x18\x03 \x01(\x03\x12.\n\x06header\x18\x04 \x01(\x0b\x32\x1e.temporal.api.common.v1.Header\x12\x31\n\x07\x66\x61ilure\x18\x05 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x1aP\n\x0c\x44\x65tailsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12/\n\x05value\x18\x02 \x01(\x0b\x32 .temporal.api.common.v1.Payloads:\x02\x38\x01"\xab\x02\n(WorkflowExecutionSignaledEventAttributes\x12\x13\n\x0bsignal_name\x18\x01 \x01(\t\x12/\n\x05input\x18\x02 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x10\n\x08identity\x18\x03 \x01(\t\x12.\n\x06header\x18\x04 \x01(\x0b\x32\x1e.temporal.api.common.v1.Header\x12\'\n\x1bskip_generate_workflow_task\x18\x05 \x01(\x08\x42\x02\x18\x01\x12N\n\x1b\x65xternal_workflow_execution\x18\x06 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution"\x81\x01\n*WorkflowExecutionTerminatedEventAttributes\x12\x0e\n\x06reason\x18\x01 \x01(\t\x12\x31\n\x07\x64\x65tails\x18\x02 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x10\n\x08identity\x18\x03 \x01(\t"\x9c\x02\n>RequestCancelExternalWorkflowExecutionInitiatedEventAttributes\x12(\n workflow_task_completed_event_id\x18\x01 \x01(\x03\x12\x11\n\tnamespace\x18\x02 \x01(\t\x12\x14\n\x0cnamespace_id\x18\x07 \x01(\t\x12\x45\n\x12workflow_execution\x18\x03 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x13\n\x07\x63ontrol\x18\x04 \x01(\tB\x02\x18\x01\x12\x1b\n\x13\x63hild_workflow_only\x18\x05 \x01(\x08\x12\x0e\n\x06reason\x18\x06 \x01(\t"\xda\x02\n;RequestCancelExternalWorkflowExecutionFailedEventAttributes\x12P\n\x05\x63\x61use\x18\x01 \x01(\x0e\x32\x41.temporal.api.enums.v1.CancelExternalWorkflowExecutionFailedCause\x12(\n workflow_task_completed_event_id\x18\x02 \x01(\x03\x12\x11\n\tnamespace\x18\x03 \x01(\t\x12\x14\n\x0cnamespace_id\x18\x07 \x01(\t\x12\x45\n\x12workflow_execution\x18\x04 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x1a\n\x12initiated_event_id\x18\x05 \x01(\x03\x12\x13\n\x07\x63ontrol\x18\x06 \x01(\tB\x02\x18\x01"\xc5\x01\n7ExternalWorkflowExecutionCancelRequestedEventAttributes\x12\x1a\n\x12initiated_event_id\x18\x01 \x01(\x03\x12\x11\n\tnamespace\x18\x02 \x01(\t\x12\x14\n\x0cnamespace_id\x18\x04 \x01(\t\x12\x45\n\x12workflow_execution\x18\x03 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution"\xfb\x02\n7SignalExternalWorkflowExecutionInitiatedEventAttributes\x12(\n workflow_task_completed_event_id\x18\x01 \x01(\x03\x12\x11\n\tnamespace\x18\x02 \x01(\t\x12\x14\n\x0cnamespace_id\x18\t \x01(\t\x12\x45\n\x12workflow_execution\x18\x03 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x13\n\x0bsignal_name\x18\x04 \x01(\t\x12/\n\x05input\x18\x05 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x13\n\x07\x63ontrol\x18\x06 \x01(\tB\x02\x18\x01\x12\x1b\n\x13\x63hild_workflow_only\x18\x07 \x01(\x08\x12.\n\x06header\x18\x08 \x01(\x0b\x32\x1e.temporal.api.common.v1.Header"\xd3\x02\n4SignalExternalWorkflowExecutionFailedEventAttributes\x12P\n\x05\x63\x61use\x18\x01 \x01(\x0e\x32\x41.temporal.api.enums.v1.SignalExternalWorkflowExecutionFailedCause\x12(\n workflow_task_completed_event_id\x18\x02 \x01(\x03\x12\x11\n\tnamespace\x18\x03 \x01(\t\x12\x14\n\x0cnamespace_id\x18\x07 \x01(\t\x12\x45\n\x12workflow_execution\x18\x04 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x1a\n\x12initiated_event_id\x18\x05 \x01(\x03\x12\x13\n\x07\x63ontrol\x18\x06 \x01(\tB\x02\x18\x01"\xd3\x01\n0ExternalWorkflowExecutionSignaledEventAttributes\x12\x1a\n\x12initiated_event_id\x18\x01 \x01(\x03\x12\x11\n\tnamespace\x18\x02 \x01(\t\x12\x14\n\x0cnamespace_id\x18\x05 \x01(\t\x12\x45\n\x12workflow_execution\x18\x03 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x13\n\x07\x63ontrol\x18\x04 \x01(\tB\x02\x18\x01"\x9e\x01\n-UpsertWorkflowSearchAttributesEventAttributes\x12(\n workflow_task_completed_event_id\x18\x01 \x01(\x03\x12\x43\n\x11search_attributes\x18\x02 \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes"\x8a\x01\n)WorkflowPropertiesModifiedEventAttributes\x12(\n workflow_task_completed_event_id\x18\x01 \x01(\x03\x12\x33\n\rupserted_memo\x18\x02 \x01(\x0b\x32\x1c.temporal.api.common.v1.Memo"\xe8\x07\n3StartChildWorkflowExecutionInitiatedEventAttributes\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x14\n\x0cnamespace_id\x18\x12 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12;\n\rworkflow_type\x18\x03 \x01(\x0b\x32$.temporal.api.common.v1.WorkflowType\x12\x38\n\ntask_queue\x18\x04 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12/\n\x05input\x18\x05 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12=\n\x1aworkflow_execution_timeout\x18\x06 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x37\n\x14workflow_run_timeout\x18\x07 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x38\n\x15workflow_task_timeout\x18\x08 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x45\n\x13parent_close_policy\x18\t \x01(\x0e\x32(.temporal.api.enums.v1.ParentClosePolicy\x12\x13\n\x07\x63ontrol\x18\n \x01(\tB\x02\x18\x01\x12(\n workflow_task_completed_event_id\x18\x0b \x01(\x03\x12N\n\x18workflow_id_reuse_policy\x18\x0c \x01(\x0e\x32,.temporal.api.enums.v1.WorkflowIdReusePolicy\x12\x39\n\x0cretry_policy\x18\r \x01(\x0b\x32#.temporal.api.common.v1.RetryPolicy\x12\x15\n\rcron_schedule\x18\x0e \x01(\t\x12.\n\x06header\x18\x0f \x01(\x0b\x32\x1e.temporal.api.common.v1.Header\x12*\n\x04memo\x18\x10 \x01(\x0b\x32\x1c.temporal.api.common.v1.Memo\x12\x43\n\x11search_attributes\x18\x11 \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes\x12\x1c\n\x10inherit_build_id\x18\x13 \x01(\x08\x42\x02\x18\x01\x12\x32\n\x08priority\x18\x14 \x01(\x0b\x32 .temporal.api.common.v1.Priority"\xd6\x02\n0StartChildWorkflowExecutionFailedEventAttributes\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x14\n\x0cnamespace_id\x18\x08 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12;\n\rworkflow_type\x18\x03 \x01(\x0b\x32$.temporal.api.common.v1.WorkflowType\x12L\n\x05\x63\x61use\x18\x04 \x01(\x0e\x32=.temporal.api.enums.v1.StartChildWorkflowExecutionFailedCause\x12\x13\n\x07\x63ontrol\x18\x05 \x01(\tB\x02\x18\x01\x12\x1a\n\x12initiated_event_id\x18\x06 \x01(\x03\x12(\n workflow_task_completed_event_id\x18\x07 \x01(\x03"\xa7\x02\n,ChildWorkflowExecutionStartedEventAttributes\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x14\n\x0cnamespace_id\x18\x06 \x01(\t\x12\x1a\n\x12initiated_event_id\x18\x02 \x01(\x03\x12\x45\n\x12workflow_execution\x18\x03 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12;\n\rworkflow_type\x18\x04 \x01(\x0b\x32$.temporal.api.common.v1.WorkflowType\x12.\n\x06header\x18\x05 \x01(\x0b\x32\x1e.temporal.api.common.v1.Header"\xc5\x02\n.ChildWorkflowExecutionCompletedEventAttributes\x12\x30\n\x06result\x18\x01 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x11\n\tnamespace\x18\x02 \x01(\t\x12\x14\n\x0cnamespace_id\x18\x07 \x01(\t\x12\x45\n\x12workflow_execution\x18\x03 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12;\n\rworkflow_type\x18\x04 \x01(\x0b\x32$.temporal.api.common.v1.WorkflowType\x12\x1a\n\x12initiated_event_id\x18\x05 \x01(\x03\x12\x18\n\x10started_event_id\x18\x06 \x01(\x03"\xfb\x02\n+ChildWorkflowExecutionFailedEventAttributes\x12\x31\n\x07\x66\x61ilure\x18\x01 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12\x11\n\tnamespace\x18\x02 \x01(\t\x12\x14\n\x0cnamespace_id\x18\x08 \x01(\t\x12\x45\n\x12workflow_execution\x18\x03 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12;\n\rworkflow_type\x18\x04 \x01(\x0b\x32$.temporal.api.common.v1.WorkflowType\x12\x1a\n\x12initiated_event_id\x18\x05 \x01(\x03\x12\x18\n\x10started_event_id\x18\x06 \x01(\x03\x12\x36\n\x0bretry_state\x18\x07 \x01(\x0e\x32!.temporal.api.enums.v1.RetryState"\xc5\x02\n-ChildWorkflowExecutionCanceledEventAttributes\x12\x31\n\x07\x64\x65tails\x18\x01 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x11\n\tnamespace\x18\x02 \x01(\t\x12\x14\n\x0cnamespace_id\x18\x07 \x01(\t\x12\x45\n\x12workflow_execution\x18\x03 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12;\n\rworkflow_type\x18\x04 \x01(\x0b\x32$.temporal.api.common.v1.WorkflowType\x12\x1a\n\x12initiated_event_id\x18\x05 \x01(\x03\x12\x18\n\x10started_event_id\x18\x06 \x01(\x03"\xca\x02\n-ChildWorkflowExecutionTimedOutEventAttributes\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x14\n\x0cnamespace_id\x18\x07 \x01(\t\x12\x45\n\x12workflow_execution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12;\n\rworkflow_type\x18\x03 \x01(\x0b\x32$.temporal.api.common.v1.WorkflowType\x12\x1a\n\x12initiated_event_id\x18\x04 \x01(\x03\x12\x18\n\x10started_event_id\x18\x05 \x01(\x03\x12\x36\n\x0bretry_state\x18\x06 \x01(\x0e\x32!.temporal.api.enums.v1.RetryState"\x94\x02\n/ChildWorkflowExecutionTerminatedEventAttributes\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x14\n\x0cnamespace_id\x18\x06 \x01(\t\x12\x45\n\x12workflow_execution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12;\n\rworkflow_type\x18\x03 \x01(\x0b\x32$.temporal.api.common.v1.WorkflowType\x12\x1a\n\x12initiated_event_id\x18\x04 \x01(\x03\x12\x18\n\x10started_event_id\x18\x05 \x01(\x03"\xca\x02\n.WorkflowExecutionOptionsUpdatedEventAttributes\x12I\n\x13versioning_override\x18\x01 \x01(\x0b\x32,.temporal.api.workflow.v1.VersioningOverride\x12!\n\x19unset_versioning_override\x18\x02 \x01(\x08\x12\x1b\n\x13\x61ttached_request_id\x18\x03 \x01(\t\x12G\n\x1d\x61ttached_completion_callbacks\x18\x04 \x03(\x0b\x32 .temporal.api.common.v1.Callback\x12\x10\n\x08identity\x18\x05 \x01(\t\x12\x32\n\x08priority\x18\x06 \x01(\x0b\x32 .temporal.api.common.v1.Priority"\xc0\x02\n3WorkflowPropertiesModifiedExternallyEventAttributes\x12\x16\n\x0enew_task_queue\x18\x01 \x01(\t\x12<\n\x19new_workflow_task_timeout\x18\x02 \x01(\x0b\x32\x19.google.protobuf.Duration\x12;\n\x18new_workflow_run_timeout\x18\x03 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x41\n\x1enew_workflow_execution_timeout\x18\x04 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x33\n\rupserted_memo\x18\x05 \x01(\x0b\x32\x1c.temporal.api.common.v1.Memo"\x90\x01\n3ActivityPropertiesModifiedExternallyEventAttributes\x12\x1a\n\x12scheduled_event_id\x18\x01 \x01(\x03\x12=\n\x10new_retry_policy\x18\x02 \x01(\x0b\x32#.temporal.api.common.v1.RetryPolicy"\xdc\x01\n.WorkflowExecutionUpdateAcceptedEventAttributes\x12\x1c\n\x14protocol_instance_id\x18\x01 \x01(\t\x12#\n\x1b\x61\x63\x63\x65pted_request_message_id\x18\x02 \x01(\t\x12,\n$accepted_request_sequencing_event_id\x18\x03 \x01(\x03\x12\x39\n\x10\x61\x63\x63\x65pted_request\x18\x04 \x01(\x0b\x32\x1f.temporal.api.update.v1.Request"\xaa\x01\n/WorkflowExecutionUpdateCompletedEventAttributes\x12*\n\x04meta\x18\x01 \x01(\x0b\x32\x1c.temporal.api.update.v1.Meta\x12\x19\n\x11\x61\x63\x63\x65pted_event_id\x18\x03 \x01(\x03\x12\x30\n\x07outcome\x18\x02 \x01(\x0b\x32\x1f.temporal.api.update.v1.Outcome"\x8f\x02\n.WorkflowExecutionUpdateRejectedEventAttributes\x12\x1c\n\x14protocol_instance_id\x18\x01 \x01(\t\x12#\n\x1brejected_request_message_id\x18\x02 \x01(\t\x12,\n$rejected_request_sequencing_event_id\x18\x03 \x01(\x03\x12\x39\n\x10rejected_request\x18\x04 \x01(\x0b\x32\x1f.temporal.api.update.v1.Request\x12\x31\n\x07\x66\x61ilure\x18\x05 \x01(\x0b\x32 .temporal.api.failure.v1.Failure"\xa4\x01\n.WorkflowExecutionUpdateAdmittedEventAttributes\x12\x30\n\x07request\x18\x01 \x01(\x0b\x32\x1f.temporal.api.update.v1.Request\x12@\n\x06origin\x18\x02 \x01(\x0e\x32\x30.temporal.api.enums.v1.UpdateAdmittedEventOrigin"^\n&WorkflowExecutionPausedEventAttributes\x12\x10\n\x08identity\x18\x01 \x01(\t\x12\x0e\n\x06reason\x18\x02 \x01(\t\x12\x12\n\nrequest_id\x18\x03 \x01(\t"`\n(WorkflowExecutionUnpausedEventAttributes\x12\x10\n\x08identity\x18\x01 \x01(\t\x12\x0e\n\x06reason\x18\x02 \x01(\t\x12\x12\n\nrequest_id\x18\x03 \x01(\t"\xb4\x04\n&NexusOperationScheduledEventAttributes\x12\x10\n\x08\x65ndpoint\x18\x01 \x01(\t\x12\x0f\n\x07service\x18\x02 \x01(\t\x12\x11\n\toperation\x18\x03 \x01(\t\x12.\n\x05input\x18\x04 \x01(\x0b\x32\x1f.temporal.api.common.v1.Payload\x12<\n\x19schedule_to_close_timeout\x18\x05 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x66\n\x0cnexus_header\x18\x06 \x03(\x0b\x32P.temporal.api.history.v1.NexusOperationScheduledEventAttributes.NexusHeaderEntry\x12(\n workflow_task_completed_event_id\x18\x07 \x01(\x03\x12\x12\n\nrequest_id\x18\x08 \x01(\t\x12\x13\n\x0b\x65ndpoint_id\x18\t \x01(\t\x12<\n\x19schedule_to_start_timeout\x18\n \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x39\n\x16start_to_close_timeout\x18\x0b \x01(\x0b\x32\x19.google.protobuf.Duration\x1a\x32\n\x10NexusHeaderEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01"\x89\x01\n$NexusOperationStartedEventAttributes\x12\x1a\n\x12scheduled_event_id\x18\x01 \x01(\x03\x12\x18\n\x0coperation_id\x18\x03 \x01(\tB\x02\x18\x01\x12\x12\n\nrequest_id\x18\x04 \x01(\t\x12\x17\n\x0foperation_token\x18\x05 \x01(\t"\x89\x01\n&NexusOperationCompletedEventAttributes\x12\x1a\n\x12scheduled_event_id\x18\x01 \x01(\x03\x12/\n\x06result\x18\x02 \x01(\x0b\x32\x1f.temporal.api.common.v1.Payload\x12\x12\n\nrequest_id\x18\x03 \x01(\t"\x88\x01\n#NexusOperationFailedEventAttributes\x12\x1a\n\x12scheduled_event_id\x18\x01 \x01(\x03\x12\x31\n\x07\x66\x61ilure\x18\x02 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12\x12\n\nrequest_id\x18\x03 \x01(\t"\x8a\x01\n%NexusOperationTimedOutEventAttributes\x12\x1a\n\x12scheduled_event_id\x18\x01 \x01(\x03\x12\x31\n\x07\x66\x61ilure\x18\x02 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12\x12\n\nrequest_id\x18\x03 \x01(\t"\x8a\x01\n%NexusOperationCanceledEventAttributes\x12\x1a\n\x12scheduled_event_id\x18\x01 \x01(\x03\x12\x31\n\x07\x66\x61ilure\x18\x02 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12\x12\n\nrequest_id\x18\x03 \x01(\t"t\n,NexusOperationCancelRequestedEventAttributes\x12\x1a\n\x12scheduled_event_id\x18\x01 \x01(\x03\x12(\n workflow_task_completed_event_id\x18\x02 \x01(\x03"\x97\x01\n3NexusOperationCancelRequestCompletedEventAttributes\x12\x1a\n\x12requested_event_id\x18\x01 \x01(\x03\x12(\n workflow_task_completed_event_id\x18\x02 \x01(\x03\x12\x1a\n\x12scheduled_event_id\x18\x03 \x01(\x03"\xc7\x01\n0NexusOperationCancelRequestFailedEventAttributes\x12\x1a\n\x12requested_event_id\x18\x01 \x01(\x03\x12(\n workflow_task_completed_event_id\x18\x02 \x01(\x03\x12\x31\n\x07\x66\x61ilure\x18\x03 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12\x1a\n\x12scheduled_event_id\x18\x04 \x01(\x03"\xb0=\n\x0cHistoryEvent\x12\x10\n\x08\x65vent_id\x18\x01 \x01(\x03\x12.\n\nevent_time\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x34\n\nevent_type\x18\x03 \x01(\x0e\x32 .temporal.api.enums.v1.EventType\x12\x0f\n\x07version\x18\x04 \x01(\x03\x12\x0f\n\x07task_id\x18\x05 \x01(\x03\x12\x1a\n\x11worker_may_ignore\x18\xac\x02 \x01(\x08\x12\x39\n\ruser_metadata\x18\xad\x02 \x01(\x0b\x32!.temporal.api.sdk.v1.UserMetadata\x12,\n\x05links\x18\xae\x02 \x03(\x0b\x32\x1c.temporal.api.common.v1.Link\x12w\n+workflow_execution_started_event_attributes\x18\x06 \x01(\x0b\x32@.temporal.api.history.v1.WorkflowExecutionStartedEventAttributesH\x00\x12{\n-workflow_execution_completed_event_attributes\x18\x07 \x01(\x0b\x32\x42.temporal.api.history.v1.WorkflowExecutionCompletedEventAttributesH\x00\x12u\n*workflow_execution_failed_event_attributes\x18\x08 \x01(\x0b\x32?.temporal.api.history.v1.WorkflowExecutionFailedEventAttributesH\x00\x12z\n-workflow_execution_timed_out_event_attributes\x18\t \x01(\x0b\x32\x41.temporal.api.history.v1.WorkflowExecutionTimedOutEventAttributesH\x00\x12q\n(workflow_task_scheduled_event_attributes\x18\n \x01(\x0b\x32=.temporal.api.history.v1.WorkflowTaskScheduledEventAttributesH\x00\x12m\n&workflow_task_started_event_attributes\x18\x0b \x01(\x0b\x32;.temporal.api.history.v1.WorkflowTaskStartedEventAttributesH\x00\x12q\n(workflow_task_completed_event_attributes\x18\x0c \x01(\x0b\x32=.temporal.api.history.v1.WorkflowTaskCompletedEventAttributesH\x00\x12p\n(workflow_task_timed_out_event_attributes\x18\r \x01(\x0b\x32<.temporal.api.history.v1.WorkflowTaskTimedOutEventAttributesH\x00\x12k\n%workflow_task_failed_event_attributes\x18\x0e \x01(\x0b\x32:.temporal.api.history.v1.WorkflowTaskFailedEventAttributesH\x00\x12q\n(activity_task_scheduled_event_attributes\x18\x0f \x01(\x0b\x32=.temporal.api.history.v1.ActivityTaskScheduledEventAttributesH\x00\x12m\n&activity_task_started_event_attributes\x18\x10 \x01(\x0b\x32;.temporal.api.history.v1.ActivityTaskStartedEventAttributesH\x00\x12q\n(activity_task_completed_event_attributes\x18\x11 \x01(\x0b\x32=.temporal.api.history.v1.ActivityTaskCompletedEventAttributesH\x00\x12k\n%activity_task_failed_event_attributes\x18\x12 \x01(\x0b\x32:.temporal.api.history.v1.ActivityTaskFailedEventAttributesH\x00\x12p\n(activity_task_timed_out_event_attributes\x18\x13 \x01(\x0b\x32<.temporal.api.history.v1.ActivityTaskTimedOutEventAttributesH\x00\x12^\n\x1etimer_started_event_attributes\x18\x14 \x01(\x0b\x32\x34.temporal.api.history.v1.TimerStartedEventAttributesH\x00\x12Z\n\x1ctimer_fired_event_attributes\x18\x15 \x01(\x0b\x32\x32.temporal.api.history.v1.TimerFiredEventAttributesH\x00\x12~\n/activity_task_cancel_requested_event_attributes\x18\x16 \x01(\x0b\x32\x43.temporal.api.history.v1.ActivityTaskCancelRequestedEventAttributesH\x00\x12o\n\'activity_task_canceled_event_attributes\x18\x17 \x01(\x0b\x32<.temporal.api.history.v1.ActivityTaskCanceledEventAttributesH\x00\x12`\n\x1ftimer_canceled_event_attributes\x18\x18 \x01(\x0b\x32\x35.temporal.api.history.v1.TimerCanceledEventAttributesH\x00\x12\x62\n marker_recorded_event_attributes\x18\x19 \x01(\x0b\x32\x36.temporal.api.history.v1.MarkerRecordedEventAttributesH\x00\x12y\n,workflow_execution_signaled_event_attributes\x18\x1a \x01(\x0b\x32\x41.temporal.api.history.v1.WorkflowExecutionSignaledEventAttributesH\x00\x12}\n.workflow_execution_terminated_event_attributes\x18\x1b \x01(\x0b\x32\x43.temporal.api.history.v1.WorkflowExecutionTerminatedEventAttributesH\x00\x12\x88\x01\n4workflow_execution_cancel_requested_event_attributes\x18\x1c \x01(\x0b\x32H.temporal.api.history.v1.WorkflowExecutionCancelRequestedEventAttributesH\x00\x12y\n,workflow_execution_canceled_event_attributes\x18\x1d \x01(\x0b\x32\x41.temporal.api.history.v1.WorkflowExecutionCanceledEventAttributesH\x00\x12\xa8\x01\nErequest_cancel_external_workflow_execution_initiated_event_attributes\x18\x1e \x01(\x0b\x32W.temporal.api.history.v1.RequestCancelExternalWorkflowExecutionInitiatedEventAttributesH\x00\x12\xa2\x01\nBrequest_cancel_external_workflow_execution_failed_event_attributes\x18\x1f \x01(\x0b\x32T.temporal.api.history.v1.RequestCancelExternalWorkflowExecutionFailedEventAttributesH\x00\x12\x99\x01\n=external_workflow_execution_cancel_requested_event_attributes\x18 \x01(\x0b\x32P.temporal.api.history.v1.ExternalWorkflowExecutionCancelRequestedEventAttributesH\x00\x12\x87\x01\n4workflow_execution_continued_as_new_event_attributes\x18! \x01(\x0b\x32G.temporal.api.history.v1.WorkflowExecutionContinuedAsNewEventAttributesH\x00\x12\x91\x01\n9start_child_workflow_execution_initiated_event_attributes\x18" \x01(\x0b\x32L.temporal.api.history.v1.StartChildWorkflowExecutionInitiatedEventAttributesH\x00\x12\x8b\x01\n6start_child_workflow_execution_failed_event_attributes\x18# \x01(\x0b\x32I.temporal.api.history.v1.StartChildWorkflowExecutionFailedEventAttributesH\x00\x12\x82\x01\n1child_workflow_execution_started_event_attributes\x18$ \x01(\x0b\x32\x45.temporal.api.history.v1.ChildWorkflowExecutionStartedEventAttributesH\x00\x12\x86\x01\n3child_workflow_execution_completed_event_attributes\x18% \x01(\x0b\x32G.temporal.api.history.v1.ChildWorkflowExecutionCompletedEventAttributesH\x00\x12\x80\x01\n0child_workflow_execution_failed_event_attributes\x18& \x01(\x0b\x32\x44.temporal.api.history.v1.ChildWorkflowExecutionFailedEventAttributesH\x00\x12\x84\x01\n2child_workflow_execution_canceled_event_attributes\x18\' \x01(\x0b\x32\x46.temporal.api.history.v1.ChildWorkflowExecutionCanceledEventAttributesH\x00\x12\x85\x01\n3child_workflow_execution_timed_out_event_attributes\x18( \x01(\x0b\x32\x46.temporal.api.history.v1.ChildWorkflowExecutionTimedOutEventAttributesH\x00\x12\x88\x01\n4child_workflow_execution_terminated_event_attributes\x18) \x01(\x0b\x32H.temporal.api.history.v1.ChildWorkflowExecutionTerminatedEventAttributesH\x00\x12\x99\x01\n=signal_external_workflow_execution_initiated_event_attributes\x18* \x01(\x0b\x32P.temporal.api.history.v1.SignalExternalWorkflowExecutionInitiatedEventAttributesH\x00\x12\x93\x01\n:signal_external_workflow_execution_failed_event_attributes\x18+ \x01(\x0b\x32M.temporal.api.history.v1.SignalExternalWorkflowExecutionFailedEventAttributesH\x00\x12\x8a\x01\n5external_workflow_execution_signaled_event_attributes\x18, \x01(\x0b\x32I.temporal.api.history.v1.ExternalWorkflowExecutionSignaledEventAttributesH\x00\x12\x84\x01\n2upsert_workflow_search_attributes_event_attributes\x18- \x01(\x0b\x32\x46.temporal.api.history.v1.UpsertWorkflowSearchAttributesEventAttributesH\x00\x12\x86\x01\n3workflow_execution_update_accepted_event_attributes\x18. \x01(\x0b\x32G.temporal.api.history.v1.WorkflowExecutionUpdateAcceptedEventAttributesH\x00\x12\x86\x01\n3workflow_execution_update_rejected_event_attributes\x18/ \x01(\x0b\x32G.temporal.api.history.v1.WorkflowExecutionUpdateRejectedEventAttributesH\x00\x12\x88\x01\n4workflow_execution_update_completed_event_attributes\x18\x30 \x01(\x0b\x32H.temporal.api.history.v1.WorkflowExecutionUpdateCompletedEventAttributesH\x00\x12\x90\x01\n8workflow_properties_modified_externally_event_attributes\x18\x31 \x01(\x0b\x32L.temporal.api.history.v1.WorkflowPropertiesModifiedExternallyEventAttributesH\x00\x12\x90\x01\n8activity_properties_modified_externally_event_attributes\x18\x32 \x01(\x0b\x32L.temporal.api.history.v1.ActivityPropertiesModifiedExternallyEventAttributesH\x00\x12{\n-workflow_properties_modified_event_attributes\x18\x33 \x01(\x0b\x32\x42.temporal.api.history.v1.WorkflowPropertiesModifiedEventAttributesH\x00\x12\x86\x01\n3workflow_execution_update_admitted_event_attributes\x18\x34 \x01(\x0b\x32G.temporal.api.history.v1.WorkflowExecutionUpdateAdmittedEventAttributesH\x00\x12u\n*nexus_operation_scheduled_event_attributes\x18\x35 \x01(\x0b\x32?.temporal.api.history.v1.NexusOperationScheduledEventAttributesH\x00\x12q\n(nexus_operation_started_event_attributes\x18\x36 \x01(\x0b\x32=.temporal.api.history.v1.NexusOperationStartedEventAttributesH\x00\x12u\n*nexus_operation_completed_event_attributes\x18\x37 \x01(\x0b\x32?.temporal.api.history.v1.NexusOperationCompletedEventAttributesH\x00\x12o\n\'nexus_operation_failed_event_attributes\x18\x38 \x01(\x0b\x32<.temporal.api.history.v1.NexusOperationFailedEventAttributesH\x00\x12s\n)nexus_operation_canceled_event_attributes\x18\x39 \x01(\x0b\x32>.temporal.api.history.v1.NexusOperationCanceledEventAttributesH\x00\x12t\n*nexus_operation_timed_out_event_attributes\x18: \x01(\x0b\x32>.temporal.api.history.v1.NexusOperationTimedOutEventAttributesH\x00\x12\x82\x01\n1nexus_operation_cancel_requested_event_attributes\x18; \x01(\x0b\x32\x45.temporal.api.history.v1.NexusOperationCancelRequestedEventAttributesH\x00\x12\x86\x01\n3workflow_execution_options_updated_event_attributes\x18< \x01(\x0b\x32G.temporal.api.history.v1.WorkflowExecutionOptionsUpdatedEventAttributesH\x00\x12\x91\x01\n9nexus_operation_cancel_request_completed_event_attributes\x18= \x01(\x0b\x32L.temporal.api.history.v1.NexusOperationCancelRequestCompletedEventAttributesH\x00\x12\x8b\x01\n6nexus_operation_cancel_request_failed_event_attributes\x18> \x01(\x0b\x32I.temporal.api.history.v1.NexusOperationCancelRequestFailedEventAttributesH\x00\x12u\n*workflow_execution_paused_event_attributes\x18? \x01(\x0b\x32?.temporal.api.history.v1.WorkflowExecutionPausedEventAttributesH\x00\x12y\n,workflow_execution_unpaused_event_attributes\x18@ \x01(\x0b\x32\x41.temporal.api.history.v1.WorkflowExecutionUnpausedEventAttributesH\x00\x42\x0c\n\nattributes"@\n\x07History\x12\x35\n\x06\x65vents\x18\x01 \x03(\x0b\x32%.temporal.api.history.v1.HistoryEventB\x8e\x01\n\x1aio.temporal.api.history.v1B\x0cMessageProtoP\x01Z%go.temporal.io/api/history/v1;history\xaa\x02\x19Temporalio.Api.History.V1\xea\x02\x1cTemporalio::Api::History::V1b\x06proto3' + b'\n%temporal/api/history/v1/message.proto\x12\x17temporal.api.history.v1\x1a\x1egoogle/protobuf/duration.proto\x1a\x1fgoogle/protobuf/timestamp.proto\x1a&temporal/api/enums/v1/event_type.proto\x1a(temporal/api/enums/v1/failed_cause.proto\x1a"temporal/api/enums/v1/update.proto\x1a$temporal/api/enums/v1/workflow.proto\x1a$temporal/api/common/v1/message.proto\x1a(temporal/api/deployment/v1/message.proto\x1a%temporal/api/failure/v1/message.proto\x1a\'temporal/api/taskqueue/v1/message.proto\x1a$temporal/api/update/v1/message.proto\x1a&temporal/api/workflow/v1/message.proto\x1a\x30temporal/api/sdk/v1/task_complete_metadata.proto\x1a\'temporal/api/sdk/v1/user_metadata.proto"\x91\x11\n\'WorkflowExecutionStartedEventAttributes\x12;\n\rworkflow_type\x18\x01 \x01(\x0b\x32$.temporal.api.common.v1.WorkflowType\x12!\n\x19parent_workflow_namespace\x18\x02 \x01(\t\x12$\n\x1cparent_workflow_namespace_id\x18\x1b \x01(\t\x12L\n\x19parent_workflow_execution\x18\x03 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12!\n\x19parent_initiated_event_id\x18\x04 \x01(\x03\x12\x38\n\ntask_queue\x18\x05 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12/\n\x05input\x18\x06 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12=\n\x1aworkflow_execution_timeout\x18\x07 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x37\n\x14workflow_run_timeout\x18\x08 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x38\n\x15workflow_task_timeout\x18\t \x01(\x0b\x32\x19.google.protobuf.Duration\x12"\n\x1a\x63ontinued_execution_run_id\x18\n \x01(\t\x12@\n\tinitiator\x18\x0b \x01(\x0e\x32-.temporal.api.enums.v1.ContinueAsNewInitiator\x12;\n\x11\x63ontinued_failure\x18\x0c \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12@\n\x16last_completion_result\x18\r \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12!\n\x19original_execution_run_id\x18\x0e \x01(\t\x12\x10\n\x08identity\x18\x0f \x01(\t\x12\x1e\n\x16\x66irst_execution_run_id\x18\x10 \x01(\t\x12\x39\n\x0cretry_policy\x18\x11 \x01(\x0b\x32#.temporal.api.common.v1.RetryPolicy\x12\x0f\n\x07\x61ttempt\x18\x12 \x01(\x05\x12\x46\n"workflow_execution_expiration_time\x18\x13 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x15\n\rcron_schedule\x18\x14 \x01(\t\x12>\n\x1b\x66irst_workflow_task_backoff\x18\x15 \x01(\x0b\x32\x19.google.protobuf.Duration\x12*\n\x04memo\x18\x16 \x01(\x0b\x32\x1c.temporal.api.common.v1.Memo\x12\x43\n\x11search_attributes\x18\x17 \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes\x12\x45\n\x16prev_auto_reset_points\x18\x18 \x01(\x0b\x32%.temporal.api.workflow.v1.ResetPoints\x12.\n\x06header\x18\x19 \x01(\x0b\x32\x1e.temporal.api.common.v1.Header\x12&\n\x1eparent_initiated_event_version\x18\x1a \x01(\x03\x12\x13\n\x0bworkflow_id\x18\x1c \x01(\t\x12L\n\x14source_version_stamp\x18\x1d \x01(\x0b\x32*.temporal.api.common.v1.WorkerVersionStampB\x02\x18\x01\x12>\n\x14\x63ompletion_callbacks\x18\x1e \x03(\x0b\x32 .temporal.api.common.v1.Callback\x12J\n\x17root_workflow_execution\x18\x1f \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x1e\n\x12inherited_build_id\x18 \x01(\tB\x02\x18\x01\x12I\n\x13versioning_override\x18! \x01(\x0b\x32,.temporal.api.workflow.v1.VersioningOverride\x12\x33\n\'parent_pinned_worker_deployment_version\x18" \x01(\tB\x02\x18\x01\x12\x32\n\x08priority\x18# \x01(\x0b\x32 .temporal.api.common.v1.Priority\x12U\n\x18inherited_pinned_version\x18% \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersion\x12Y\n\x1binherited_auto_upgrade_info\x18\' \x01(\x0b\x32\x34.temporal.api.deployment.v1.InheritedAutoUpgradeInfo\x12 \n\x18\x65\x61ger_execution_accepted\x18& \x01(\x08\x12^\n\x1f\x64\x65\x63lined_target_version_upgrade\x18( \x01(\x0b\x32\x35.temporal.api.history.v1.DeclinedTargetVersionUpgradeJ\x04\x08$\x10%R parent_pinned_deployment_version"o\n\x1c\x44\x65\x63linedTargetVersionUpgrade\x12O\n\x12\x64\x65ployment_version\x18\x01 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersion"\xa5\x01\n)WorkflowExecutionCompletedEventAttributes\x12\x30\n\x06result\x18\x01 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12(\n workflow_task_completed_event_id\x18\x02 \x01(\x03\x12\x1c\n\x14new_execution_run_id\x18\x03 \x01(\t"\xdb\x01\n&WorkflowExecutionFailedEventAttributes\x12\x31\n\x07\x66\x61ilure\x18\x01 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12\x36\n\x0bretry_state\x18\x02 \x01(\x0e\x32!.temporal.api.enums.v1.RetryState\x12(\n workflow_task_completed_event_id\x18\x03 \x01(\x03\x12\x1c\n\x14new_execution_run_id\x18\x04 \x01(\t"\x80\x01\n(WorkflowExecutionTimedOutEventAttributes\x12\x36\n\x0bretry_state\x18\x01 \x01(\x0e\x32!.temporal.api.enums.v1.RetryState\x12\x1c\n\x14new_execution_run_id\x18\x02 \x01(\t"\xa5\x07\n.WorkflowExecutionContinuedAsNewEventAttributes\x12\x1c\n\x14new_execution_run_id\x18\x01 \x01(\t\x12;\n\rworkflow_type\x18\x02 \x01(\x0b\x32$.temporal.api.common.v1.WorkflowType\x12\x38\n\ntask_queue\x18\x03 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12/\n\x05input\x18\x04 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x37\n\x14workflow_run_timeout\x18\x05 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x38\n\x15workflow_task_timeout\x18\x06 \x01(\x0b\x32\x19.google.protobuf.Duration\x12(\n workflow_task_completed_event_id\x18\x07 \x01(\x03\x12\x39\n\x16\x62\x61\x63koff_start_interval\x18\x08 \x01(\x0b\x32\x19.google.protobuf.Duration\x12@\n\tinitiator\x18\t \x01(\x0e\x32-.temporal.api.enums.v1.ContinueAsNewInitiator\x12\x35\n\x07\x66\x61ilure\x18\n \x01(\x0b\x32 .temporal.api.failure.v1.FailureB\x02\x18\x01\x12@\n\x16last_completion_result\x18\x0b \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12.\n\x06header\x18\x0c \x01(\x0b\x32\x1e.temporal.api.common.v1.Header\x12*\n\x04memo\x18\r \x01(\x0b\x32\x1c.temporal.api.common.v1.Memo\x12\x43\n\x11search_attributes\x18\x0e \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes\x12\x1c\n\x10inherit_build_id\x18\x0f \x01(\x08\x42\x02\x18\x01\x12[\n\x1binitial_versioning_behavior\x18\x10 \x01(\x0e\x32\x36.temporal.api.enums.v1.ContinueAsNewVersioningBehavior"\xac\x01\n$WorkflowTaskScheduledEventAttributes\x12\x38\n\ntask_queue\x18\x01 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12\x39\n\x16start_to_close_timeout\x18\x02 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x0f\n\x07\x61ttempt\x18\x03 \x01(\x05"\xa0\x03\n"WorkflowTaskStartedEventAttributes\x12\x1a\n\x12scheduled_event_id\x18\x01 \x01(\x03\x12\x10\n\x08identity\x18\x02 \x01(\t\x12\x12\n\nrequest_id\x18\x03 \x01(\t\x12\x1f\n\x17suggest_continue_as_new\x18\x04 \x01(\x08\x12Z\n\x1fsuggest_continue_as_new_reasons\x18\x08 \x03(\x0e\x32\x31.temporal.api.enums.v1.SuggestContinueAsNewReason\x12\x30\n(target_worker_deployment_version_changed\x18\t \x01(\x08\x12\x1a\n\x12history_size_bytes\x18\x05 \x01(\x03\x12\x46\n\x0eworker_version\x18\x06 \x01(\x0b\x32*.temporal.api.common.v1.WorkerVersionStampB\x02\x18\x01\x12%\n\x19\x62uild_id_redirect_counter\x18\x07 \x01(\x03\x42\x02\x18\x01"\x82\x05\n$WorkflowTaskCompletedEventAttributes\x12\x1a\n\x12scheduled_event_id\x18\x01 \x01(\x03\x12\x18\n\x10started_event_id\x18\x02 \x01(\x03\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x1b\n\x0f\x62inary_checksum\x18\x04 \x01(\tB\x02\x18\x01\x12\x46\n\x0eworker_version\x18\x05 \x01(\x0b\x32*.temporal.api.common.v1.WorkerVersionStampB\x02\x18\x01\x12H\n\x0csdk_metadata\x18\x06 \x01(\x0b\x32\x32.temporal.api.sdk.v1.WorkflowTaskCompletedMetadata\x12\x43\n\x11metering_metadata\x18\r \x01(\x0b\x32(.temporal.api.common.v1.MeteringMetadata\x12>\n\ndeployment\x18\x07 \x01(\x0b\x32&.temporal.api.deployment.v1.DeploymentB\x02\x18\x01\x12\x46\n\x13versioning_behavior\x18\x08 \x01(\x0e\x32).temporal.api.enums.v1.VersioningBehavior\x12%\n\x19worker_deployment_version\x18\t \x01(\tB\x02\x18\x01\x12\x1e\n\x16worker_deployment_name\x18\n \x01(\t\x12O\n\x12\x64\x65ployment_version\x18\x0b \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersion"\x95\x01\n#WorkflowTaskTimedOutEventAttributes\x12\x1a\n\x12scheduled_event_id\x18\x01 \x01(\x03\x12\x18\n\x10started_event_id\x18\x02 \x01(\x03\x12\x38\n\x0ctimeout_type\x18\x03 \x01(\x0e\x32".temporal.api.enums.v1.TimeoutType"\x87\x03\n!WorkflowTaskFailedEventAttributes\x12\x1a\n\x12scheduled_event_id\x18\x01 \x01(\x03\x12\x18\n\x10started_event_id\x18\x02 \x01(\x03\x12=\n\x05\x63\x61use\x18\x03 \x01(\x0e\x32..temporal.api.enums.v1.WorkflowTaskFailedCause\x12\x31\n\x07\x66\x61ilure\x18\x04 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12\x10\n\x08identity\x18\x05 \x01(\t\x12\x13\n\x0b\x62\x61se_run_id\x18\x06 \x01(\t\x12\x12\n\nnew_run_id\x18\x07 \x01(\t\x12\x1a\n\x12\x66ork_event_version\x18\x08 \x01(\x03\x12\x1b\n\x0f\x62inary_checksum\x18\t \x01(\tB\x02\x18\x01\x12\x46\n\x0eworker_version\x18\n \x01(\x0b\x32*.temporal.api.common.v1.WorkerVersionStampB\x02\x18\x01"\xc2\x05\n$ActivityTaskScheduledEventAttributes\x12\x13\n\x0b\x61\x63tivity_id\x18\x01 \x01(\t\x12;\n\ractivity_type\x18\x02 \x01(\x0b\x32$.temporal.api.common.v1.ActivityType\x12\x38\n\ntask_queue\x18\x04 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12.\n\x06header\x18\x05 \x01(\x0b\x32\x1e.temporal.api.common.v1.Header\x12/\n\x05input\x18\x06 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12<\n\x19schedule_to_close_timeout\x18\x07 \x01(\x0b\x32\x19.google.protobuf.Duration\x12<\n\x19schedule_to_start_timeout\x18\x08 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x39\n\x16start_to_close_timeout\x18\t \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x34\n\x11heartbeat_timeout\x18\n \x01(\x0b\x32\x19.google.protobuf.Duration\x12(\n workflow_task_completed_event_id\x18\x0b \x01(\x03\x12\x39\n\x0cretry_policy\x18\x0c \x01(\x0b\x32#.temporal.api.common.v1.RetryPolicy\x12!\n\x15use_workflow_build_id\x18\r \x01(\x08\x42\x02\x18\x01\x12\x32\n\x08priority\x18\x0e \x01(\x0b\x32 .temporal.api.common.v1.PriorityJ\x04\x08\x03\x10\x04"\x9e\x02\n"ActivityTaskStartedEventAttributes\x12\x1a\n\x12scheduled_event_id\x18\x01 \x01(\x03\x12\x10\n\x08identity\x18\x02 \x01(\t\x12\x12\n\nrequest_id\x18\x03 \x01(\t\x12\x0f\n\x07\x61ttempt\x18\x04 \x01(\x05\x12\x36\n\x0clast_failure\x18\x05 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12\x46\n\x0eworker_version\x18\x06 \x01(\x0b\x32*.temporal.api.common.v1.WorkerVersionStampB\x02\x18\x01\x12%\n\x19\x62uild_id_redirect_counter\x18\x07 \x01(\x03\x42\x02\x18\x01"\xe8\x01\n$ActivityTaskCompletedEventAttributes\x12\x30\n\x06result\x18\x01 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x1a\n\x12scheduled_event_id\x18\x02 \x01(\x03\x12\x18\n\x10started_event_id\x18\x03 \x01(\x03\x12\x10\n\x08identity\x18\x04 \x01(\t\x12\x46\n\x0eworker_version\x18\x05 \x01(\x0b\x32*.temporal.api.common.v1.WorkerVersionStampB\x02\x18\x01"\x9e\x02\n!ActivityTaskFailedEventAttributes\x12\x31\n\x07\x66\x61ilure\x18\x01 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12\x1a\n\x12scheduled_event_id\x18\x02 \x01(\x03\x12\x18\n\x10started_event_id\x18\x03 \x01(\x03\x12\x10\n\x08identity\x18\x04 \x01(\t\x12\x36\n\x0bretry_state\x18\x05 \x01(\x0e\x32!.temporal.api.enums.v1.RetryState\x12\x46\n\x0eworker_version\x18\x06 \x01(\x0b\x32*.temporal.api.common.v1.WorkerVersionStampB\x02\x18\x01"\xc6\x01\n#ActivityTaskTimedOutEventAttributes\x12\x31\n\x07\x66\x61ilure\x18\x01 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12\x1a\n\x12scheduled_event_id\x18\x02 \x01(\x03\x12\x18\n\x10started_event_id\x18\x03 \x01(\x03\x12\x36\n\x0bretry_state\x18\x04 \x01(\x0e\x32!.temporal.api.enums.v1.RetryState"r\n*ActivityTaskCancelRequestedEventAttributes\x12\x1a\n\x12scheduled_event_id\x18\x01 \x01(\x03\x12(\n workflow_task_completed_event_id\x18\x02 \x01(\x03"\x92\x02\n#ActivityTaskCanceledEventAttributes\x12\x31\n\x07\x64\x65tails\x18\x01 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12(\n latest_cancel_requested_event_id\x18\x02 \x01(\x03\x12\x1a\n\x12scheduled_event_id\x18\x03 \x01(\x03\x12\x18\n\x10started_event_id\x18\x04 \x01(\x03\x12\x10\n\x08identity\x18\x05 \x01(\t\x12\x46\n\x0eworker_version\x18\x06 \x01(\x0b\x32*.temporal.api.common.v1.WorkerVersionStampB\x02\x18\x01"\x93\x01\n\x1bTimerStartedEventAttributes\x12\x10\n\x08timer_id\x18\x01 \x01(\t\x12\x38\n\x15start_to_fire_timeout\x18\x02 \x01(\x0b\x32\x19.google.protobuf.Duration\x12(\n workflow_task_completed_event_id\x18\x03 \x01(\x03"G\n\x19TimerFiredEventAttributes\x12\x10\n\x08timer_id\x18\x01 \x01(\t\x12\x18\n\x10started_event_id\x18\x02 \x01(\x03"\x86\x01\n\x1cTimerCanceledEventAttributes\x12\x10\n\x08timer_id\x18\x01 \x01(\t\x12\x18\n\x10started_event_id\x18\x02 \x01(\x03\x12(\n workflow_task_completed_event_id\x18\x03 \x01(\x03\x12\x10\n\x08identity\x18\x04 \x01(\t"\xc7\x01\n/WorkflowExecutionCancelRequestedEventAttributes\x12\r\n\x05\x63\x61use\x18\x01 \x01(\t\x12#\n\x1b\x65xternal_initiated_event_id\x18\x02 \x01(\x03\x12N\n\x1b\x65xternal_workflow_execution\x18\x03 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x10\n\x08identity\x18\x04 \x01(\t"\x87\x01\n(WorkflowExecutionCanceledEventAttributes\x12(\n workflow_task_completed_event_id\x18\x01 \x01(\x03\x12\x31\n\x07\x64\x65tails\x18\x02 \x01(\x0b\x32 .temporal.api.common.v1.Payloads"\xe9\x02\n\x1dMarkerRecordedEventAttributes\x12\x13\n\x0bmarker_name\x18\x01 \x01(\t\x12T\n\x07\x64\x65tails\x18\x02 \x03(\x0b\x32\x43.temporal.api.history.v1.MarkerRecordedEventAttributes.DetailsEntry\x12(\n workflow_task_completed_event_id\x18\x03 \x01(\x03\x12.\n\x06header\x18\x04 \x01(\x0b\x32\x1e.temporal.api.common.v1.Header\x12\x31\n\x07\x66\x61ilure\x18\x05 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x1aP\n\x0c\x44\x65tailsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12/\n\x05value\x18\x02 \x01(\x0b\x32 .temporal.api.common.v1.Payloads:\x02\x38\x01"\xab\x02\n(WorkflowExecutionSignaledEventAttributes\x12\x13\n\x0bsignal_name\x18\x01 \x01(\t\x12/\n\x05input\x18\x02 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x10\n\x08identity\x18\x03 \x01(\t\x12.\n\x06header\x18\x04 \x01(\x0b\x32\x1e.temporal.api.common.v1.Header\x12\'\n\x1bskip_generate_workflow_task\x18\x05 \x01(\x08\x42\x02\x18\x01\x12N\n\x1b\x65xternal_workflow_execution\x18\x06 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution"\x81\x01\n*WorkflowExecutionTerminatedEventAttributes\x12\x0e\n\x06reason\x18\x01 \x01(\t\x12\x31\n\x07\x64\x65tails\x18\x02 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x10\n\x08identity\x18\x03 \x01(\t"\x9c\x02\n>RequestCancelExternalWorkflowExecutionInitiatedEventAttributes\x12(\n workflow_task_completed_event_id\x18\x01 \x01(\x03\x12\x11\n\tnamespace\x18\x02 \x01(\t\x12\x14\n\x0cnamespace_id\x18\x07 \x01(\t\x12\x45\n\x12workflow_execution\x18\x03 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x13\n\x07\x63ontrol\x18\x04 \x01(\tB\x02\x18\x01\x12\x1b\n\x13\x63hild_workflow_only\x18\x05 \x01(\x08\x12\x0e\n\x06reason\x18\x06 \x01(\t"\xda\x02\n;RequestCancelExternalWorkflowExecutionFailedEventAttributes\x12P\n\x05\x63\x61use\x18\x01 \x01(\x0e\x32\x41.temporal.api.enums.v1.CancelExternalWorkflowExecutionFailedCause\x12(\n workflow_task_completed_event_id\x18\x02 \x01(\x03\x12\x11\n\tnamespace\x18\x03 \x01(\t\x12\x14\n\x0cnamespace_id\x18\x07 \x01(\t\x12\x45\n\x12workflow_execution\x18\x04 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x1a\n\x12initiated_event_id\x18\x05 \x01(\x03\x12\x13\n\x07\x63ontrol\x18\x06 \x01(\tB\x02\x18\x01"\xc5\x01\n7ExternalWorkflowExecutionCancelRequestedEventAttributes\x12\x1a\n\x12initiated_event_id\x18\x01 \x01(\x03\x12\x11\n\tnamespace\x18\x02 \x01(\t\x12\x14\n\x0cnamespace_id\x18\x04 \x01(\t\x12\x45\n\x12workflow_execution\x18\x03 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution"\xfb\x02\n7SignalExternalWorkflowExecutionInitiatedEventAttributes\x12(\n workflow_task_completed_event_id\x18\x01 \x01(\x03\x12\x11\n\tnamespace\x18\x02 \x01(\t\x12\x14\n\x0cnamespace_id\x18\t \x01(\t\x12\x45\n\x12workflow_execution\x18\x03 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x13\n\x0bsignal_name\x18\x04 \x01(\t\x12/\n\x05input\x18\x05 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x13\n\x07\x63ontrol\x18\x06 \x01(\tB\x02\x18\x01\x12\x1b\n\x13\x63hild_workflow_only\x18\x07 \x01(\x08\x12.\n\x06header\x18\x08 \x01(\x0b\x32\x1e.temporal.api.common.v1.Header"\xd3\x02\n4SignalExternalWorkflowExecutionFailedEventAttributes\x12P\n\x05\x63\x61use\x18\x01 \x01(\x0e\x32\x41.temporal.api.enums.v1.SignalExternalWorkflowExecutionFailedCause\x12(\n workflow_task_completed_event_id\x18\x02 \x01(\x03\x12\x11\n\tnamespace\x18\x03 \x01(\t\x12\x14\n\x0cnamespace_id\x18\x07 \x01(\t\x12\x45\n\x12workflow_execution\x18\x04 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x1a\n\x12initiated_event_id\x18\x05 \x01(\x03\x12\x13\n\x07\x63ontrol\x18\x06 \x01(\tB\x02\x18\x01"\xd3\x01\n0ExternalWorkflowExecutionSignaledEventAttributes\x12\x1a\n\x12initiated_event_id\x18\x01 \x01(\x03\x12\x11\n\tnamespace\x18\x02 \x01(\t\x12\x14\n\x0cnamespace_id\x18\x05 \x01(\t\x12\x45\n\x12workflow_execution\x18\x03 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x13\n\x07\x63ontrol\x18\x04 \x01(\tB\x02\x18\x01"\x9e\x01\n-UpsertWorkflowSearchAttributesEventAttributes\x12(\n workflow_task_completed_event_id\x18\x01 \x01(\x03\x12\x43\n\x11search_attributes\x18\x02 \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes"\x8a\x01\n)WorkflowPropertiesModifiedEventAttributes\x12(\n workflow_task_completed_event_id\x18\x01 \x01(\x03\x12\x33\n\rupserted_memo\x18\x02 \x01(\x0b\x32\x1c.temporal.api.common.v1.Memo"\xe8\x07\n3StartChildWorkflowExecutionInitiatedEventAttributes\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x14\n\x0cnamespace_id\x18\x12 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12;\n\rworkflow_type\x18\x03 \x01(\x0b\x32$.temporal.api.common.v1.WorkflowType\x12\x38\n\ntask_queue\x18\x04 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12/\n\x05input\x18\x05 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12=\n\x1aworkflow_execution_timeout\x18\x06 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x37\n\x14workflow_run_timeout\x18\x07 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x38\n\x15workflow_task_timeout\x18\x08 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x45\n\x13parent_close_policy\x18\t \x01(\x0e\x32(.temporal.api.enums.v1.ParentClosePolicy\x12\x13\n\x07\x63ontrol\x18\n \x01(\tB\x02\x18\x01\x12(\n workflow_task_completed_event_id\x18\x0b \x01(\x03\x12N\n\x18workflow_id_reuse_policy\x18\x0c \x01(\x0e\x32,.temporal.api.enums.v1.WorkflowIdReusePolicy\x12\x39\n\x0cretry_policy\x18\r \x01(\x0b\x32#.temporal.api.common.v1.RetryPolicy\x12\x15\n\rcron_schedule\x18\x0e \x01(\t\x12.\n\x06header\x18\x0f \x01(\x0b\x32\x1e.temporal.api.common.v1.Header\x12*\n\x04memo\x18\x10 \x01(\x0b\x32\x1c.temporal.api.common.v1.Memo\x12\x43\n\x11search_attributes\x18\x11 \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes\x12\x1c\n\x10inherit_build_id\x18\x13 \x01(\x08\x42\x02\x18\x01\x12\x32\n\x08priority\x18\x14 \x01(\x0b\x32 .temporal.api.common.v1.Priority"\xd6\x02\n0StartChildWorkflowExecutionFailedEventAttributes\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x14\n\x0cnamespace_id\x18\x08 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12;\n\rworkflow_type\x18\x03 \x01(\x0b\x32$.temporal.api.common.v1.WorkflowType\x12L\n\x05\x63\x61use\x18\x04 \x01(\x0e\x32=.temporal.api.enums.v1.StartChildWorkflowExecutionFailedCause\x12\x13\n\x07\x63ontrol\x18\x05 \x01(\tB\x02\x18\x01\x12\x1a\n\x12initiated_event_id\x18\x06 \x01(\x03\x12(\n workflow_task_completed_event_id\x18\x07 \x01(\x03"\xa7\x02\n,ChildWorkflowExecutionStartedEventAttributes\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x14\n\x0cnamespace_id\x18\x06 \x01(\t\x12\x1a\n\x12initiated_event_id\x18\x02 \x01(\x03\x12\x45\n\x12workflow_execution\x18\x03 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12;\n\rworkflow_type\x18\x04 \x01(\x0b\x32$.temporal.api.common.v1.WorkflowType\x12.\n\x06header\x18\x05 \x01(\x0b\x32\x1e.temporal.api.common.v1.Header"\xc5\x02\n.ChildWorkflowExecutionCompletedEventAttributes\x12\x30\n\x06result\x18\x01 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x11\n\tnamespace\x18\x02 \x01(\t\x12\x14\n\x0cnamespace_id\x18\x07 \x01(\t\x12\x45\n\x12workflow_execution\x18\x03 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12;\n\rworkflow_type\x18\x04 \x01(\x0b\x32$.temporal.api.common.v1.WorkflowType\x12\x1a\n\x12initiated_event_id\x18\x05 \x01(\x03\x12\x18\n\x10started_event_id\x18\x06 \x01(\x03"\xfb\x02\n+ChildWorkflowExecutionFailedEventAttributes\x12\x31\n\x07\x66\x61ilure\x18\x01 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12\x11\n\tnamespace\x18\x02 \x01(\t\x12\x14\n\x0cnamespace_id\x18\x08 \x01(\t\x12\x45\n\x12workflow_execution\x18\x03 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12;\n\rworkflow_type\x18\x04 \x01(\x0b\x32$.temporal.api.common.v1.WorkflowType\x12\x1a\n\x12initiated_event_id\x18\x05 \x01(\x03\x12\x18\n\x10started_event_id\x18\x06 \x01(\x03\x12\x36\n\x0bretry_state\x18\x07 \x01(\x0e\x32!.temporal.api.enums.v1.RetryState"\xc5\x02\n-ChildWorkflowExecutionCanceledEventAttributes\x12\x31\n\x07\x64\x65tails\x18\x01 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x11\n\tnamespace\x18\x02 \x01(\t\x12\x14\n\x0cnamespace_id\x18\x07 \x01(\t\x12\x45\n\x12workflow_execution\x18\x03 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12;\n\rworkflow_type\x18\x04 \x01(\x0b\x32$.temporal.api.common.v1.WorkflowType\x12\x1a\n\x12initiated_event_id\x18\x05 \x01(\x03\x12\x18\n\x10started_event_id\x18\x06 \x01(\x03"\xca\x02\n-ChildWorkflowExecutionTimedOutEventAttributes\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x14\n\x0cnamespace_id\x18\x07 \x01(\t\x12\x45\n\x12workflow_execution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12;\n\rworkflow_type\x18\x03 \x01(\x0b\x32$.temporal.api.common.v1.WorkflowType\x12\x1a\n\x12initiated_event_id\x18\x04 \x01(\x03\x12\x18\n\x10started_event_id\x18\x05 \x01(\x03\x12\x36\n\x0bretry_state\x18\x06 \x01(\x0e\x32!.temporal.api.enums.v1.RetryState"\x94\x02\n/ChildWorkflowExecutionTerminatedEventAttributes\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x14\n\x0cnamespace_id\x18\x06 \x01(\t\x12\x45\n\x12workflow_execution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12;\n\rworkflow_type\x18\x03 \x01(\x0b\x32$.temporal.api.common.v1.WorkflowType\x12\x1a\n\x12initiated_event_id\x18\x04 \x01(\x03\x12\x18\n\x10started_event_id\x18\x05 \x01(\x03"\xca\x02\n.WorkflowExecutionOptionsUpdatedEventAttributes\x12I\n\x13versioning_override\x18\x01 \x01(\x0b\x32,.temporal.api.workflow.v1.VersioningOverride\x12!\n\x19unset_versioning_override\x18\x02 \x01(\x08\x12\x1b\n\x13\x61ttached_request_id\x18\x03 \x01(\t\x12G\n\x1d\x61ttached_completion_callbacks\x18\x04 \x03(\x0b\x32 .temporal.api.common.v1.Callback\x12\x10\n\x08identity\x18\x05 \x01(\t\x12\x32\n\x08priority\x18\x06 \x01(\x0b\x32 .temporal.api.common.v1.Priority"\xc0\x02\n3WorkflowPropertiesModifiedExternallyEventAttributes\x12\x16\n\x0enew_task_queue\x18\x01 \x01(\t\x12<\n\x19new_workflow_task_timeout\x18\x02 \x01(\x0b\x32\x19.google.protobuf.Duration\x12;\n\x18new_workflow_run_timeout\x18\x03 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x41\n\x1enew_workflow_execution_timeout\x18\x04 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x33\n\rupserted_memo\x18\x05 \x01(\x0b\x32\x1c.temporal.api.common.v1.Memo"\x90\x01\n3ActivityPropertiesModifiedExternallyEventAttributes\x12\x1a\n\x12scheduled_event_id\x18\x01 \x01(\x03\x12=\n\x10new_retry_policy\x18\x02 \x01(\x0b\x32#.temporal.api.common.v1.RetryPolicy"\xdc\x01\n.WorkflowExecutionUpdateAcceptedEventAttributes\x12\x1c\n\x14protocol_instance_id\x18\x01 \x01(\t\x12#\n\x1b\x61\x63\x63\x65pted_request_message_id\x18\x02 \x01(\t\x12,\n$accepted_request_sequencing_event_id\x18\x03 \x01(\x03\x12\x39\n\x10\x61\x63\x63\x65pted_request\x18\x04 \x01(\x0b\x32\x1f.temporal.api.update.v1.Request"\xaa\x01\n/WorkflowExecutionUpdateCompletedEventAttributes\x12*\n\x04meta\x18\x01 \x01(\x0b\x32\x1c.temporal.api.update.v1.Meta\x12\x19\n\x11\x61\x63\x63\x65pted_event_id\x18\x03 \x01(\x03\x12\x30\n\x07outcome\x18\x02 \x01(\x0b\x32\x1f.temporal.api.update.v1.Outcome"\x8f\x02\n.WorkflowExecutionUpdateRejectedEventAttributes\x12\x1c\n\x14protocol_instance_id\x18\x01 \x01(\t\x12#\n\x1brejected_request_message_id\x18\x02 \x01(\t\x12,\n$rejected_request_sequencing_event_id\x18\x03 \x01(\x03\x12\x39\n\x10rejected_request\x18\x04 \x01(\x0b\x32\x1f.temporal.api.update.v1.Request\x12\x31\n\x07\x66\x61ilure\x18\x05 \x01(\x0b\x32 .temporal.api.failure.v1.Failure"\xa4\x01\n.WorkflowExecutionUpdateAdmittedEventAttributes\x12\x30\n\x07request\x18\x01 \x01(\x0b\x32\x1f.temporal.api.update.v1.Request\x12@\n\x06origin\x18\x02 \x01(\x0e\x32\x30.temporal.api.enums.v1.UpdateAdmittedEventOrigin"^\n&WorkflowExecutionPausedEventAttributes\x12\x10\n\x08identity\x18\x01 \x01(\t\x12\x0e\n\x06reason\x18\x02 \x01(\t\x12\x12\n\nrequest_id\x18\x03 \x01(\t"`\n(WorkflowExecutionUnpausedEventAttributes\x12\x10\n\x08identity\x18\x01 \x01(\t\x12\x0e\n\x06reason\x18\x02 \x01(\t\x12\x12\n\nrequest_id\x18\x03 \x01(\t"\xb4\x04\n&NexusOperationScheduledEventAttributes\x12\x10\n\x08\x65ndpoint\x18\x01 \x01(\t\x12\x0f\n\x07service\x18\x02 \x01(\t\x12\x11\n\toperation\x18\x03 \x01(\t\x12.\n\x05input\x18\x04 \x01(\x0b\x32\x1f.temporal.api.common.v1.Payload\x12<\n\x19schedule_to_close_timeout\x18\x05 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x66\n\x0cnexus_header\x18\x06 \x03(\x0b\x32P.temporal.api.history.v1.NexusOperationScheduledEventAttributes.NexusHeaderEntry\x12(\n workflow_task_completed_event_id\x18\x07 \x01(\x03\x12\x12\n\nrequest_id\x18\x08 \x01(\t\x12\x13\n\x0b\x65ndpoint_id\x18\t \x01(\t\x12<\n\x19schedule_to_start_timeout\x18\n \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x39\n\x16start_to_close_timeout\x18\x0b \x01(\x0b\x32\x19.google.protobuf.Duration\x1a\x32\n\x10NexusHeaderEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01"\x89\x01\n$NexusOperationStartedEventAttributes\x12\x1a\n\x12scheduled_event_id\x18\x01 \x01(\x03\x12\x18\n\x0coperation_id\x18\x03 \x01(\tB\x02\x18\x01\x12\x12\n\nrequest_id\x18\x04 \x01(\t\x12\x17\n\x0foperation_token\x18\x05 \x01(\t"\x89\x01\n&NexusOperationCompletedEventAttributes\x12\x1a\n\x12scheduled_event_id\x18\x01 \x01(\x03\x12/\n\x06result\x18\x02 \x01(\x0b\x32\x1f.temporal.api.common.v1.Payload\x12\x12\n\nrequest_id\x18\x03 \x01(\t"\x88\x01\n#NexusOperationFailedEventAttributes\x12\x1a\n\x12scheduled_event_id\x18\x01 \x01(\x03\x12\x31\n\x07\x66\x61ilure\x18\x02 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12\x12\n\nrequest_id\x18\x03 \x01(\t"\x8a\x01\n%NexusOperationTimedOutEventAttributes\x12\x1a\n\x12scheduled_event_id\x18\x01 \x01(\x03\x12\x31\n\x07\x66\x61ilure\x18\x02 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12\x12\n\nrequest_id\x18\x03 \x01(\t"\x8a\x01\n%NexusOperationCanceledEventAttributes\x12\x1a\n\x12scheduled_event_id\x18\x01 \x01(\x03\x12\x31\n\x07\x66\x61ilure\x18\x02 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12\x12\n\nrequest_id\x18\x03 \x01(\t"t\n,NexusOperationCancelRequestedEventAttributes\x12\x1a\n\x12scheduled_event_id\x18\x01 \x01(\x03\x12(\n workflow_task_completed_event_id\x18\x02 \x01(\x03"\x97\x01\n3NexusOperationCancelRequestCompletedEventAttributes\x12\x1a\n\x12requested_event_id\x18\x01 \x01(\x03\x12(\n workflow_task_completed_event_id\x18\x02 \x01(\x03\x12\x1a\n\x12scheduled_event_id\x18\x03 \x01(\x03"\xc7\x01\n0NexusOperationCancelRequestFailedEventAttributes\x12\x1a\n\x12requested_event_id\x18\x01 \x01(\x03\x12(\n workflow_task_completed_event_id\x18\x02 \x01(\x03\x12\x31\n\x07\x66\x61ilure\x18\x03 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12\x1a\n\x12scheduled_event_id\x18\x04 \x01(\x03"\xb0=\n\x0cHistoryEvent\x12\x10\n\x08\x65vent_id\x18\x01 \x01(\x03\x12.\n\nevent_time\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x34\n\nevent_type\x18\x03 \x01(\x0e\x32 .temporal.api.enums.v1.EventType\x12\x0f\n\x07version\x18\x04 \x01(\x03\x12\x0f\n\x07task_id\x18\x05 \x01(\x03\x12\x1a\n\x11worker_may_ignore\x18\xac\x02 \x01(\x08\x12\x39\n\ruser_metadata\x18\xad\x02 \x01(\x0b\x32!.temporal.api.sdk.v1.UserMetadata\x12,\n\x05links\x18\xae\x02 \x03(\x0b\x32\x1c.temporal.api.common.v1.Link\x12w\n+workflow_execution_started_event_attributes\x18\x06 \x01(\x0b\x32@.temporal.api.history.v1.WorkflowExecutionStartedEventAttributesH\x00\x12{\n-workflow_execution_completed_event_attributes\x18\x07 \x01(\x0b\x32\x42.temporal.api.history.v1.WorkflowExecutionCompletedEventAttributesH\x00\x12u\n*workflow_execution_failed_event_attributes\x18\x08 \x01(\x0b\x32?.temporal.api.history.v1.WorkflowExecutionFailedEventAttributesH\x00\x12z\n-workflow_execution_timed_out_event_attributes\x18\t \x01(\x0b\x32\x41.temporal.api.history.v1.WorkflowExecutionTimedOutEventAttributesH\x00\x12q\n(workflow_task_scheduled_event_attributes\x18\n \x01(\x0b\x32=.temporal.api.history.v1.WorkflowTaskScheduledEventAttributesH\x00\x12m\n&workflow_task_started_event_attributes\x18\x0b \x01(\x0b\x32;.temporal.api.history.v1.WorkflowTaskStartedEventAttributesH\x00\x12q\n(workflow_task_completed_event_attributes\x18\x0c \x01(\x0b\x32=.temporal.api.history.v1.WorkflowTaskCompletedEventAttributesH\x00\x12p\n(workflow_task_timed_out_event_attributes\x18\r \x01(\x0b\x32<.temporal.api.history.v1.WorkflowTaskTimedOutEventAttributesH\x00\x12k\n%workflow_task_failed_event_attributes\x18\x0e \x01(\x0b\x32:.temporal.api.history.v1.WorkflowTaskFailedEventAttributesH\x00\x12q\n(activity_task_scheduled_event_attributes\x18\x0f \x01(\x0b\x32=.temporal.api.history.v1.ActivityTaskScheduledEventAttributesH\x00\x12m\n&activity_task_started_event_attributes\x18\x10 \x01(\x0b\x32;.temporal.api.history.v1.ActivityTaskStartedEventAttributesH\x00\x12q\n(activity_task_completed_event_attributes\x18\x11 \x01(\x0b\x32=.temporal.api.history.v1.ActivityTaskCompletedEventAttributesH\x00\x12k\n%activity_task_failed_event_attributes\x18\x12 \x01(\x0b\x32:.temporal.api.history.v1.ActivityTaskFailedEventAttributesH\x00\x12p\n(activity_task_timed_out_event_attributes\x18\x13 \x01(\x0b\x32<.temporal.api.history.v1.ActivityTaskTimedOutEventAttributesH\x00\x12^\n\x1etimer_started_event_attributes\x18\x14 \x01(\x0b\x32\x34.temporal.api.history.v1.TimerStartedEventAttributesH\x00\x12Z\n\x1ctimer_fired_event_attributes\x18\x15 \x01(\x0b\x32\x32.temporal.api.history.v1.TimerFiredEventAttributesH\x00\x12~\n/activity_task_cancel_requested_event_attributes\x18\x16 \x01(\x0b\x32\x43.temporal.api.history.v1.ActivityTaskCancelRequestedEventAttributesH\x00\x12o\n\'activity_task_canceled_event_attributes\x18\x17 \x01(\x0b\x32<.temporal.api.history.v1.ActivityTaskCanceledEventAttributesH\x00\x12`\n\x1ftimer_canceled_event_attributes\x18\x18 \x01(\x0b\x32\x35.temporal.api.history.v1.TimerCanceledEventAttributesH\x00\x12\x62\n marker_recorded_event_attributes\x18\x19 \x01(\x0b\x32\x36.temporal.api.history.v1.MarkerRecordedEventAttributesH\x00\x12y\n,workflow_execution_signaled_event_attributes\x18\x1a \x01(\x0b\x32\x41.temporal.api.history.v1.WorkflowExecutionSignaledEventAttributesH\x00\x12}\n.workflow_execution_terminated_event_attributes\x18\x1b \x01(\x0b\x32\x43.temporal.api.history.v1.WorkflowExecutionTerminatedEventAttributesH\x00\x12\x88\x01\n4workflow_execution_cancel_requested_event_attributes\x18\x1c \x01(\x0b\x32H.temporal.api.history.v1.WorkflowExecutionCancelRequestedEventAttributesH\x00\x12y\n,workflow_execution_canceled_event_attributes\x18\x1d \x01(\x0b\x32\x41.temporal.api.history.v1.WorkflowExecutionCanceledEventAttributesH\x00\x12\xa8\x01\nErequest_cancel_external_workflow_execution_initiated_event_attributes\x18\x1e \x01(\x0b\x32W.temporal.api.history.v1.RequestCancelExternalWorkflowExecutionInitiatedEventAttributesH\x00\x12\xa2\x01\nBrequest_cancel_external_workflow_execution_failed_event_attributes\x18\x1f \x01(\x0b\x32T.temporal.api.history.v1.RequestCancelExternalWorkflowExecutionFailedEventAttributesH\x00\x12\x99\x01\n=external_workflow_execution_cancel_requested_event_attributes\x18 \x01(\x0b\x32P.temporal.api.history.v1.ExternalWorkflowExecutionCancelRequestedEventAttributesH\x00\x12\x87\x01\n4workflow_execution_continued_as_new_event_attributes\x18! \x01(\x0b\x32G.temporal.api.history.v1.WorkflowExecutionContinuedAsNewEventAttributesH\x00\x12\x91\x01\n9start_child_workflow_execution_initiated_event_attributes\x18" \x01(\x0b\x32L.temporal.api.history.v1.StartChildWorkflowExecutionInitiatedEventAttributesH\x00\x12\x8b\x01\n6start_child_workflow_execution_failed_event_attributes\x18# \x01(\x0b\x32I.temporal.api.history.v1.StartChildWorkflowExecutionFailedEventAttributesH\x00\x12\x82\x01\n1child_workflow_execution_started_event_attributes\x18$ \x01(\x0b\x32\x45.temporal.api.history.v1.ChildWorkflowExecutionStartedEventAttributesH\x00\x12\x86\x01\n3child_workflow_execution_completed_event_attributes\x18% \x01(\x0b\x32G.temporal.api.history.v1.ChildWorkflowExecutionCompletedEventAttributesH\x00\x12\x80\x01\n0child_workflow_execution_failed_event_attributes\x18& \x01(\x0b\x32\x44.temporal.api.history.v1.ChildWorkflowExecutionFailedEventAttributesH\x00\x12\x84\x01\n2child_workflow_execution_canceled_event_attributes\x18\' \x01(\x0b\x32\x46.temporal.api.history.v1.ChildWorkflowExecutionCanceledEventAttributesH\x00\x12\x85\x01\n3child_workflow_execution_timed_out_event_attributes\x18( \x01(\x0b\x32\x46.temporal.api.history.v1.ChildWorkflowExecutionTimedOutEventAttributesH\x00\x12\x88\x01\n4child_workflow_execution_terminated_event_attributes\x18) \x01(\x0b\x32H.temporal.api.history.v1.ChildWorkflowExecutionTerminatedEventAttributesH\x00\x12\x99\x01\n=signal_external_workflow_execution_initiated_event_attributes\x18* \x01(\x0b\x32P.temporal.api.history.v1.SignalExternalWorkflowExecutionInitiatedEventAttributesH\x00\x12\x93\x01\n:signal_external_workflow_execution_failed_event_attributes\x18+ \x01(\x0b\x32M.temporal.api.history.v1.SignalExternalWorkflowExecutionFailedEventAttributesH\x00\x12\x8a\x01\n5external_workflow_execution_signaled_event_attributes\x18, \x01(\x0b\x32I.temporal.api.history.v1.ExternalWorkflowExecutionSignaledEventAttributesH\x00\x12\x84\x01\n2upsert_workflow_search_attributes_event_attributes\x18- \x01(\x0b\x32\x46.temporal.api.history.v1.UpsertWorkflowSearchAttributesEventAttributesH\x00\x12\x86\x01\n3workflow_execution_update_accepted_event_attributes\x18. \x01(\x0b\x32G.temporal.api.history.v1.WorkflowExecutionUpdateAcceptedEventAttributesH\x00\x12\x86\x01\n3workflow_execution_update_rejected_event_attributes\x18/ \x01(\x0b\x32G.temporal.api.history.v1.WorkflowExecutionUpdateRejectedEventAttributesH\x00\x12\x88\x01\n4workflow_execution_update_completed_event_attributes\x18\x30 \x01(\x0b\x32H.temporal.api.history.v1.WorkflowExecutionUpdateCompletedEventAttributesH\x00\x12\x90\x01\n8workflow_properties_modified_externally_event_attributes\x18\x31 \x01(\x0b\x32L.temporal.api.history.v1.WorkflowPropertiesModifiedExternallyEventAttributesH\x00\x12\x90\x01\n8activity_properties_modified_externally_event_attributes\x18\x32 \x01(\x0b\x32L.temporal.api.history.v1.ActivityPropertiesModifiedExternallyEventAttributesH\x00\x12{\n-workflow_properties_modified_event_attributes\x18\x33 \x01(\x0b\x32\x42.temporal.api.history.v1.WorkflowPropertiesModifiedEventAttributesH\x00\x12\x86\x01\n3workflow_execution_update_admitted_event_attributes\x18\x34 \x01(\x0b\x32G.temporal.api.history.v1.WorkflowExecutionUpdateAdmittedEventAttributesH\x00\x12u\n*nexus_operation_scheduled_event_attributes\x18\x35 \x01(\x0b\x32?.temporal.api.history.v1.NexusOperationScheduledEventAttributesH\x00\x12q\n(nexus_operation_started_event_attributes\x18\x36 \x01(\x0b\x32=.temporal.api.history.v1.NexusOperationStartedEventAttributesH\x00\x12u\n*nexus_operation_completed_event_attributes\x18\x37 \x01(\x0b\x32?.temporal.api.history.v1.NexusOperationCompletedEventAttributesH\x00\x12o\n\'nexus_operation_failed_event_attributes\x18\x38 \x01(\x0b\x32<.temporal.api.history.v1.NexusOperationFailedEventAttributesH\x00\x12s\n)nexus_operation_canceled_event_attributes\x18\x39 \x01(\x0b\x32>.temporal.api.history.v1.NexusOperationCanceledEventAttributesH\x00\x12t\n*nexus_operation_timed_out_event_attributes\x18: \x01(\x0b\x32>.temporal.api.history.v1.NexusOperationTimedOutEventAttributesH\x00\x12\x82\x01\n1nexus_operation_cancel_requested_event_attributes\x18; \x01(\x0b\x32\x45.temporal.api.history.v1.NexusOperationCancelRequestedEventAttributesH\x00\x12\x86\x01\n3workflow_execution_options_updated_event_attributes\x18< \x01(\x0b\x32G.temporal.api.history.v1.WorkflowExecutionOptionsUpdatedEventAttributesH\x00\x12\x91\x01\n9nexus_operation_cancel_request_completed_event_attributes\x18= \x01(\x0b\x32L.temporal.api.history.v1.NexusOperationCancelRequestCompletedEventAttributesH\x00\x12\x8b\x01\n6nexus_operation_cancel_request_failed_event_attributes\x18> \x01(\x0b\x32I.temporal.api.history.v1.NexusOperationCancelRequestFailedEventAttributesH\x00\x12u\n*workflow_execution_paused_event_attributes\x18? \x01(\x0b\x32?.temporal.api.history.v1.WorkflowExecutionPausedEventAttributesH\x00\x12y\n,workflow_execution_unpaused_event_attributes\x18@ \x01(\x0b\x32\x41.temporal.api.history.v1.WorkflowExecutionUnpausedEventAttributesH\x00\x42\x0c\n\nattributes"@\n\x07History\x12\x35\n\x06\x65vents\x18\x01 \x03(\x0b\x32%.temporal.api.history.v1.HistoryEventB\x8e\x01\n\x1aio.temporal.api.history.v1B\x0cMessageProtoP\x01Z%go.temporal.io/api/history/v1;history\xaa\x02\x19Temporalio.Api.History.V1\xea\x02\x1cTemporalio::Api::History::V1b\x06proto3' ) _WORKFLOWEXECUTIONSTARTEDEVENTATTRIBUTES = DESCRIPTOR.message_types_by_name[ "WorkflowExecutionStartedEventAttributes" ] +_DECLINEDTARGETVERSIONUPGRADE = DESCRIPTOR.message_types_by_name[ + "DeclinedTargetVersionUpgrade" +] _WORKFLOWEXECUTIONCOMPLETEDEVENTATTRIBUTES = DESCRIPTOR.message_types_by_name[ "WorkflowExecutionCompletedEventAttributes" ] @@ -265,6 +268,17 @@ ) _sym_db.RegisterMessage(WorkflowExecutionStartedEventAttributes) +DeclinedTargetVersionUpgrade = _reflection.GeneratedProtocolMessageType( + "DeclinedTargetVersionUpgrade", + (_message.Message,), + { + "DESCRIPTOR": _DECLINEDTARGETVERSIONUPGRADE, + "__module__": "temporalio.api.history.v1.message_pb2", + # @@protoc_insertion_point(class_scope:temporal.api.history.v1.DeclinedTargetVersionUpgrade) + }, +) +_sym_db.RegisterMessage(DeclinedTargetVersionUpgrade) + WorkflowExecutionCompletedEventAttributes = _reflection.GeneratedProtocolMessageType( "WorkflowExecutionCompletedEventAttributes", (_message.Message,), @@ -1161,133 +1175,135 @@ "operation_id" ]._serialized_options = b"\030\001" _WORKFLOWEXECUTIONSTARTEDEVENTATTRIBUTES._serialized_start = 617 - _WORKFLOWEXECUTIONSTARTEDEVENTATTRIBUTES._serialized_end = 2714 - _WORKFLOWEXECUTIONCOMPLETEDEVENTATTRIBUTES._serialized_start = 2717 - _WORKFLOWEXECUTIONCOMPLETEDEVENTATTRIBUTES._serialized_end = 2882 - _WORKFLOWEXECUTIONFAILEDEVENTATTRIBUTES._serialized_start = 2885 - _WORKFLOWEXECUTIONFAILEDEVENTATTRIBUTES._serialized_end = 3104 - _WORKFLOWEXECUTIONTIMEDOUTEVENTATTRIBUTES._serialized_start = 3107 - _WORKFLOWEXECUTIONTIMEDOUTEVENTATTRIBUTES._serialized_end = 3235 - _WORKFLOWEXECUTIONCONTINUEDASNEWEVENTATTRIBUTES._serialized_start = 3238 - _WORKFLOWEXECUTIONCONTINUEDASNEWEVENTATTRIBUTES._serialized_end = 4171 - _WORKFLOWTASKSCHEDULEDEVENTATTRIBUTES._serialized_start = 4174 - _WORKFLOWTASKSCHEDULEDEVENTATTRIBUTES._serialized_end = 4346 - _WORKFLOWTASKSTARTEDEVENTATTRIBUTES._serialized_start = 4349 - _WORKFLOWTASKSTARTEDEVENTATTRIBUTES._serialized_end = 4765 - _WORKFLOWTASKCOMPLETEDEVENTATTRIBUTES._serialized_start = 4768 - _WORKFLOWTASKCOMPLETEDEVENTATTRIBUTES._serialized_end = 5410 - _WORKFLOWTASKTIMEDOUTEVENTATTRIBUTES._serialized_start = 5413 - _WORKFLOWTASKTIMEDOUTEVENTATTRIBUTES._serialized_end = 5562 - _WORKFLOWTASKFAILEDEVENTATTRIBUTES._serialized_start = 5565 - _WORKFLOWTASKFAILEDEVENTATTRIBUTES._serialized_end = 5956 - _ACTIVITYTASKSCHEDULEDEVENTATTRIBUTES._serialized_start = 5959 - _ACTIVITYTASKSCHEDULEDEVENTATTRIBUTES._serialized_end = 6665 - _ACTIVITYTASKSTARTEDEVENTATTRIBUTES._serialized_start = 6668 - _ACTIVITYTASKSTARTEDEVENTATTRIBUTES._serialized_end = 6954 - _ACTIVITYTASKCOMPLETEDEVENTATTRIBUTES._serialized_start = 6957 - _ACTIVITYTASKCOMPLETEDEVENTATTRIBUTES._serialized_end = 7189 - _ACTIVITYTASKFAILEDEVENTATTRIBUTES._serialized_start = 7192 - _ACTIVITYTASKFAILEDEVENTATTRIBUTES._serialized_end = 7478 - _ACTIVITYTASKTIMEDOUTEVENTATTRIBUTES._serialized_start = 7481 - _ACTIVITYTASKTIMEDOUTEVENTATTRIBUTES._serialized_end = 7679 - _ACTIVITYTASKCANCELREQUESTEDEVENTATTRIBUTES._serialized_start = 7681 - _ACTIVITYTASKCANCELREQUESTEDEVENTATTRIBUTES._serialized_end = 7795 - _ACTIVITYTASKCANCELEDEVENTATTRIBUTES._serialized_start = 7798 - _ACTIVITYTASKCANCELEDEVENTATTRIBUTES._serialized_end = 8072 - _TIMERSTARTEDEVENTATTRIBUTES._serialized_start = 8075 - _TIMERSTARTEDEVENTATTRIBUTES._serialized_end = 8222 - _TIMERFIREDEVENTATTRIBUTES._serialized_start = 8224 - _TIMERFIREDEVENTATTRIBUTES._serialized_end = 8295 - _TIMERCANCELEDEVENTATTRIBUTES._serialized_start = 8298 - _TIMERCANCELEDEVENTATTRIBUTES._serialized_end = 8432 - _WORKFLOWEXECUTIONCANCELREQUESTEDEVENTATTRIBUTES._serialized_start = 8435 - _WORKFLOWEXECUTIONCANCELREQUESTEDEVENTATTRIBUTES._serialized_end = 8634 - _WORKFLOWEXECUTIONCANCELEDEVENTATTRIBUTES._serialized_start = 8637 - _WORKFLOWEXECUTIONCANCELEDEVENTATTRIBUTES._serialized_end = 8772 - _MARKERRECORDEDEVENTATTRIBUTES._serialized_start = 8775 - _MARKERRECORDEDEVENTATTRIBUTES._serialized_end = 9136 - _MARKERRECORDEDEVENTATTRIBUTES_DETAILSENTRY._serialized_start = 9056 - _MARKERRECORDEDEVENTATTRIBUTES_DETAILSENTRY._serialized_end = 9136 - _WORKFLOWEXECUTIONSIGNALEDEVENTATTRIBUTES._serialized_start = 9139 - _WORKFLOWEXECUTIONSIGNALEDEVENTATTRIBUTES._serialized_end = 9438 - _WORKFLOWEXECUTIONTERMINATEDEVENTATTRIBUTES._serialized_start = 9441 - _WORKFLOWEXECUTIONTERMINATEDEVENTATTRIBUTES._serialized_end = 9570 - _REQUESTCANCELEXTERNALWORKFLOWEXECUTIONINITIATEDEVENTATTRIBUTES._serialized_start = 9573 + _WORKFLOWEXECUTIONSTARTEDEVENTATTRIBUTES._serialized_end = 2810 + _DECLINEDTARGETVERSIONUPGRADE._serialized_start = 2812 + _DECLINEDTARGETVERSIONUPGRADE._serialized_end = 2923 + _WORKFLOWEXECUTIONCOMPLETEDEVENTATTRIBUTES._serialized_start = 2926 + _WORKFLOWEXECUTIONCOMPLETEDEVENTATTRIBUTES._serialized_end = 3091 + _WORKFLOWEXECUTIONFAILEDEVENTATTRIBUTES._serialized_start = 3094 + _WORKFLOWEXECUTIONFAILEDEVENTATTRIBUTES._serialized_end = 3313 + _WORKFLOWEXECUTIONTIMEDOUTEVENTATTRIBUTES._serialized_start = 3316 + _WORKFLOWEXECUTIONTIMEDOUTEVENTATTRIBUTES._serialized_end = 3444 + _WORKFLOWEXECUTIONCONTINUEDASNEWEVENTATTRIBUTES._serialized_start = 3447 + _WORKFLOWEXECUTIONCONTINUEDASNEWEVENTATTRIBUTES._serialized_end = 4380 + _WORKFLOWTASKSCHEDULEDEVENTATTRIBUTES._serialized_start = 4383 + _WORKFLOWTASKSCHEDULEDEVENTATTRIBUTES._serialized_end = 4555 + _WORKFLOWTASKSTARTEDEVENTATTRIBUTES._serialized_start = 4558 + _WORKFLOWTASKSTARTEDEVENTATTRIBUTES._serialized_end = 4974 + _WORKFLOWTASKCOMPLETEDEVENTATTRIBUTES._serialized_start = 4977 + _WORKFLOWTASKCOMPLETEDEVENTATTRIBUTES._serialized_end = 5619 + _WORKFLOWTASKTIMEDOUTEVENTATTRIBUTES._serialized_start = 5622 + _WORKFLOWTASKTIMEDOUTEVENTATTRIBUTES._serialized_end = 5771 + _WORKFLOWTASKFAILEDEVENTATTRIBUTES._serialized_start = 5774 + _WORKFLOWTASKFAILEDEVENTATTRIBUTES._serialized_end = 6165 + _ACTIVITYTASKSCHEDULEDEVENTATTRIBUTES._serialized_start = 6168 + _ACTIVITYTASKSCHEDULEDEVENTATTRIBUTES._serialized_end = 6874 + _ACTIVITYTASKSTARTEDEVENTATTRIBUTES._serialized_start = 6877 + _ACTIVITYTASKSTARTEDEVENTATTRIBUTES._serialized_end = 7163 + _ACTIVITYTASKCOMPLETEDEVENTATTRIBUTES._serialized_start = 7166 + _ACTIVITYTASKCOMPLETEDEVENTATTRIBUTES._serialized_end = 7398 + _ACTIVITYTASKFAILEDEVENTATTRIBUTES._serialized_start = 7401 + _ACTIVITYTASKFAILEDEVENTATTRIBUTES._serialized_end = 7687 + _ACTIVITYTASKTIMEDOUTEVENTATTRIBUTES._serialized_start = 7690 + _ACTIVITYTASKTIMEDOUTEVENTATTRIBUTES._serialized_end = 7888 + _ACTIVITYTASKCANCELREQUESTEDEVENTATTRIBUTES._serialized_start = 7890 + _ACTIVITYTASKCANCELREQUESTEDEVENTATTRIBUTES._serialized_end = 8004 + _ACTIVITYTASKCANCELEDEVENTATTRIBUTES._serialized_start = 8007 + _ACTIVITYTASKCANCELEDEVENTATTRIBUTES._serialized_end = 8281 + _TIMERSTARTEDEVENTATTRIBUTES._serialized_start = 8284 + _TIMERSTARTEDEVENTATTRIBUTES._serialized_end = 8431 + _TIMERFIREDEVENTATTRIBUTES._serialized_start = 8433 + _TIMERFIREDEVENTATTRIBUTES._serialized_end = 8504 + _TIMERCANCELEDEVENTATTRIBUTES._serialized_start = 8507 + _TIMERCANCELEDEVENTATTRIBUTES._serialized_end = 8641 + _WORKFLOWEXECUTIONCANCELREQUESTEDEVENTATTRIBUTES._serialized_start = 8644 + _WORKFLOWEXECUTIONCANCELREQUESTEDEVENTATTRIBUTES._serialized_end = 8843 + _WORKFLOWEXECUTIONCANCELEDEVENTATTRIBUTES._serialized_start = 8846 + _WORKFLOWEXECUTIONCANCELEDEVENTATTRIBUTES._serialized_end = 8981 + _MARKERRECORDEDEVENTATTRIBUTES._serialized_start = 8984 + _MARKERRECORDEDEVENTATTRIBUTES._serialized_end = 9345 + _MARKERRECORDEDEVENTATTRIBUTES_DETAILSENTRY._serialized_start = 9265 + _MARKERRECORDEDEVENTATTRIBUTES_DETAILSENTRY._serialized_end = 9345 + _WORKFLOWEXECUTIONSIGNALEDEVENTATTRIBUTES._serialized_start = 9348 + _WORKFLOWEXECUTIONSIGNALEDEVENTATTRIBUTES._serialized_end = 9647 + _WORKFLOWEXECUTIONTERMINATEDEVENTATTRIBUTES._serialized_start = 9650 + _WORKFLOWEXECUTIONTERMINATEDEVENTATTRIBUTES._serialized_end = 9779 + _REQUESTCANCELEXTERNALWORKFLOWEXECUTIONINITIATEDEVENTATTRIBUTES._serialized_start = 9782 _REQUESTCANCELEXTERNALWORKFLOWEXECUTIONINITIATEDEVENTATTRIBUTES._serialized_end = ( - 9857 + 10066 ) _REQUESTCANCELEXTERNALWORKFLOWEXECUTIONFAILEDEVENTATTRIBUTES._serialized_start = ( - 9860 + 10069 ) - _REQUESTCANCELEXTERNALWORKFLOWEXECUTIONFAILEDEVENTATTRIBUTES._serialized_end = 10206 - _EXTERNALWORKFLOWEXECUTIONCANCELREQUESTEDEVENTATTRIBUTES._serialized_start = 10209 - _EXTERNALWORKFLOWEXECUTIONCANCELREQUESTEDEVENTATTRIBUTES._serialized_end = 10406 - _SIGNALEXTERNALWORKFLOWEXECUTIONINITIATEDEVENTATTRIBUTES._serialized_start = 10409 - _SIGNALEXTERNALWORKFLOWEXECUTIONINITIATEDEVENTATTRIBUTES._serialized_end = 10788 - _SIGNALEXTERNALWORKFLOWEXECUTIONFAILEDEVENTATTRIBUTES._serialized_start = 10791 - _SIGNALEXTERNALWORKFLOWEXECUTIONFAILEDEVENTATTRIBUTES._serialized_end = 11130 - _EXTERNALWORKFLOWEXECUTIONSIGNALEDEVENTATTRIBUTES._serialized_start = 11133 - _EXTERNALWORKFLOWEXECUTIONSIGNALEDEVENTATTRIBUTES._serialized_end = 11344 - _UPSERTWORKFLOWSEARCHATTRIBUTESEVENTATTRIBUTES._serialized_start = 11347 - _UPSERTWORKFLOWSEARCHATTRIBUTESEVENTATTRIBUTES._serialized_end = 11505 - _WORKFLOWPROPERTIESMODIFIEDEVENTATTRIBUTES._serialized_start = 11508 - _WORKFLOWPROPERTIESMODIFIEDEVENTATTRIBUTES._serialized_end = 11646 - _STARTCHILDWORKFLOWEXECUTIONINITIATEDEVENTATTRIBUTES._serialized_start = 11649 - _STARTCHILDWORKFLOWEXECUTIONINITIATEDEVENTATTRIBUTES._serialized_end = 12649 - _STARTCHILDWORKFLOWEXECUTIONFAILEDEVENTATTRIBUTES._serialized_start = 12652 - _STARTCHILDWORKFLOWEXECUTIONFAILEDEVENTATTRIBUTES._serialized_end = 12994 - _CHILDWORKFLOWEXECUTIONSTARTEDEVENTATTRIBUTES._serialized_start = 12997 - _CHILDWORKFLOWEXECUTIONSTARTEDEVENTATTRIBUTES._serialized_end = 13292 - _CHILDWORKFLOWEXECUTIONCOMPLETEDEVENTATTRIBUTES._serialized_start = 13295 - _CHILDWORKFLOWEXECUTIONCOMPLETEDEVENTATTRIBUTES._serialized_end = 13620 - _CHILDWORKFLOWEXECUTIONFAILEDEVENTATTRIBUTES._serialized_start = 13623 - _CHILDWORKFLOWEXECUTIONFAILEDEVENTATTRIBUTES._serialized_end = 14002 - _CHILDWORKFLOWEXECUTIONCANCELEDEVENTATTRIBUTES._serialized_start = 14005 - _CHILDWORKFLOWEXECUTIONCANCELEDEVENTATTRIBUTES._serialized_end = 14330 - _CHILDWORKFLOWEXECUTIONTIMEDOUTEVENTATTRIBUTES._serialized_start = 14333 - _CHILDWORKFLOWEXECUTIONTIMEDOUTEVENTATTRIBUTES._serialized_end = 14663 - _CHILDWORKFLOWEXECUTIONTERMINATEDEVENTATTRIBUTES._serialized_start = 14666 - _CHILDWORKFLOWEXECUTIONTERMINATEDEVENTATTRIBUTES._serialized_end = 14942 - _WORKFLOWEXECUTIONOPTIONSUPDATEDEVENTATTRIBUTES._serialized_start = 14945 - _WORKFLOWEXECUTIONOPTIONSUPDATEDEVENTATTRIBUTES._serialized_end = 15275 - _WORKFLOWPROPERTIESMODIFIEDEXTERNALLYEVENTATTRIBUTES._serialized_start = 15278 - _WORKFLOWPROPERTIESMODIFIEDEXTERNALLYEVENTATTRIBUTES._serialized_end = 15598 - _ACTIVITYPROPERTIESMODIFIEDEXTERNALLYEVENTATTRIBUTES._serialized_start = 15601 - _ACTIVITYPROPERTIESMODIFIEDEXTERNALLYEVENTATTRIBUTES._serialized_end = 15745 - _WORKFLOWEXECUTIONUPDATEACCEPTEDEVENTATTRIBUTES._serialized_start = 15748 - _WORKFLOWEXECUTIONUPDATEACCEPTEDEVENTATTRIBUTES._serialized_end = 15968 - _WORKFLOWEXECUTIONUPDATECOMPLETEDEVENTATTRIBUTES._serialized_start = 15971 - _WORKFLOWEXECUTIONUPDATECOMPLETEDEVENTATTRIBUTES._serialized_end = 16141 - _WORKFLOWEXECUTIONUPDATEREJECTEDEVENTATTRIBUTES._serialized_start = 16144 - _WORKFLOWEXECUTIONUPDATEREJECTEDEVENTATTRIBUTES._serialized_end = 16415 - _WORKFLOWEXECUTIONUPDATEADMITTEDEVENTATTRIBUTES._serialized_start = 16418 - _WORKFLOWEXECUTIONUPDATEADMITTEDEVENTATTRIBUTES._serialized_end = 16582 - _WORKFLOWEXECUTIONPAUSEDEVENTATTRIBUTES._serialized_start = 16584 - _WORKFLOWEXECUTIONPAUSEDEVENTATTRIBUTES._serialized_end = 16678 - _WORKFLOWEXECUTIONUNPAUSEDEVENTATTRIBUTES._serialized_start = 16680 - _WORKFLOWEXECUTIONUNPAUSEDEVENTATTRIBUTES._serialized_end = 16776 - _NEXUSOPERATIONSCHEDULEDEVENTATTRIBUTES._serialized_start = 16779 - _NEXUSOPERATIONSCHEDULEDEVENTATTRIBUTES._serialized_end = 17343 - _NEXUSOPERATIONSCHEDULEDEVENTATTRIBUTES_NEXUSHEADERENTRY._serialized_start = 17293 - _NEXUSOPERATIONSCHEDULEDEVENTATTRIBUTES_NEXUSHEADERENTRY._serialized_end = 17343 - _NEXUSOPERATIONSTARTEDEVENTATTRIBUTES._serialized_start = 17346 - _NEXUSOPERATIONSTARTEDEVENTATTRIBUTES._serialized_end = 17483 - _NEXUSOPERATIONCOMPLETEDEVENTATTRIBUTES._serialized_start = 17486 - _NEXUSOPERATIONCOMPLETEDEVENTATTRIBUTES._serialized_end = 17623 - _NEXUSOPERATIONFAILEDEVENTATTRIBUTES._serialized_start = 17626 - _NEXUSOPERATIONFAILEDEVENTATTRIBUTES._serialized_end = 17762 - _NEXUSOPERATIONTIMEDOUTEVENTATTRIBUTES._serialized_start = 17765 - _NEXUSOPERATIONTIMEDOUTEVENTATTRIBUTES._serialized_end = 17903 - _NEXUSOPERATIONCANCELEDEVENTATTRIBUTES._serialized_start = 17906 - _NEXUSOPERATIONCANCELEDEVENTATTRIBUTES._serialized_end = 18044 - _NEXUSOPERATIONCANCELREQUESTEDEVENTATTRIBUTES._serialized_start = 18046 - _NEXUSOPERATIONCANCELREQUESTEDEVENTATTRIBUTES._serialized_end = 18162 - _NEXUSOPERATIONCANCELREQUESTCOMPLETEDEVENTATTRIBUTES._serialized_start = 18165 - _NEXUSOPERATIONCANCELREQUESTCOMPLETEDEVENTATTRIBUTES._serialized_end = 18316 - _NEXUSOPERATIONCANCELREQUESTFAILEDEVENTATTRIBUTES._serialized_start = 18319 - _NEXUSOPERATIONCANCELREQUESTFAILEDEVENTATTRIBUTES._serialized_end = 18518 - _HISTORYEVENT._serialized_start = 18521 - _HISTORYEVENT._serialized_end = 26377 - _HISTORY._serialized_start = 26379 - _HISTORY._serialized_end = 26443 + _REQUESTCANCELEXTERNALWORKFLOWEXECUTIONFAILEDEVENTATTRIBUTES._serialized_end = 10415 + _EXTERNALWORKFLOWEXECUTIONCANCELREQUESTEDEVENTATTRIBUTES._serialized_start = 10418 + _EXTERNALWORKFLOWEXECUTIONCANCELREQUESTEDEVENTATTRIBUTES._serialized_end = 10615 + _SIGNALEXTERNALWORKFLOWEXECUTIONINITIATEDEVENTATTRIBUTES._serialized_start = 10618 + _SIGNALEXTERNALWORKFLOWEXECUTIONINITIATEDEVENTATTRIBUTES._serialized_end = 10997 + _SIGNALEXTERNALWORKFLOWEXECUTIONFAILEDEVENTATTRIBUTES._serialized_start = 11000 + _SIGNALEXTERNALWORKFLOWEXECUTIONFAILEDEVENTATTRIBUTES._serialized_end = 11339 + _EXTERNALWORKFLOWEXECUTIONSIGNALEDEVENTATTRIBUTES._serialized_start = 11342 + _EXTERNALWORKFLOWEXECUTIONSIGNALEDEVENTATTRIBUTES._serialized_end = 11553 + _UPSERTWORKFLOWSEARCHATTRIBUTESEVENTATTRIBUTES._serialized_start = 11556 + _UPSERTWORKFLOWSEARCHATTRIBUTESEVENTATTRIBUTES._serialized_end = 11714 + _WORKFLOWPROPERTIESMODIFIEDEVENTATTRIBUTES._serialized_start = 11717 + _WORKFLOWPROPERTIESMODIFIEDEVENTATTRIBUTES._serialized_end = 11855 + _STARTCHILDWORKFLOWEXECUTIONINITIATEDEVENTATTRIBUTES._serialized_start = 11858 + _STARTCHILDWORKFLOWEXECUTIONINITIATEDEVENTATTRIBUTES._serialized_end = 12858 + _STARTCHILDWORKFLOWEXECUTIONFAILEDEVENTATTRIBUTES._serialized_start = 12861 + _STARTCHILDWORKFLOWEXECUTIONFAILEDEVENTATTRIBUTES._serialized_end = 13203 + _CHILDWORKFLOWEXECUTIONSTARTEDEVENTATTRIBUTES._serialized_start = 13206 + _CHILDWORKFLOWEXECUTIONSTARTEDEVENTATTRIBUTES._serialized_end = 13501 + _CHILDWORKFLOWEXECUTIONCOMPLETEDEVENTATTRIBUTES._serialized_start = 13504 + _CHILDWORKFLOWEXECUTIONCOMPLETEDEVENTATTRIBUTES._serialized_end = 13829 + _CHILDWORKFLOWEXECUTIONFAILEDEVENTATTRIBUTES._serialized_start = 13832 + _CHILDWORKFLOWEXECUTIONFAILEDEVENTATTRIBUTES._serialized_end = 14211 + _CHILDWORKFLOWEXECUTIONCANCELEDEVENTATTRIBUTES._serialized_start = 14214 + _CHILDWORKFLOWEXECUTIONCANCELEDEVENTATTRIBUTES._serialized_end = 14539 + _CHILDWORKFLOWEXECUTIONTIMEDOUTEVENTATTRIBUTES._serialized_start = 14542 + _CHILDWORKFLOWEXECUTIONTIMEDOUTEVENTATTRIBUTES._serialized_end = 14872 + _CHILDWORKFLOWEXECUTIONTERMINATEDEVENTATTRIBUTES._serialized_start = 14875 + _CHILDWORKFLOWEXECUTIONTERMINATEDEVENTATTRIBUTES._serialized_end = 15151 + _WORKFLOWEXECUTIONOPTIONSUPDATEDEVENTATTRIBUTES._serialized_start = 15154 + _WORKFLOWEXECUTIONOPTIONSUPDATEDEVENTATTRIBUTES._serialized_end = 15484 + _WORKFLOWPROPERTIESMODIFIEDEXTERNALLYEVENTATTRIBUTES._serialized_start = 15487 + _WORKFLOWPROPERTIESMODIFIEDEXTERNALLYEVENTATTRIBUTES._serialized_end = 15807 + _ACTIVITYPROPERTIESMODIFIEDEXTERNALLYEVENTATTRIBUTES._serialized_start = 15810 + _ACTIVITYPROPERTIESMODIFIEDEXTERNALLYEVENTATTRIBUTES._serialized_end = 15954 + _WORKFLOWEXECUTIONUPDATEACCEPTEDEVENTATTRIBUTES._serialized_start = 15957 + _WORKFLOWEXECUTIONUPDATEACCEPTEDEVENTATTRIBUTES._serialized_end = 16177 + _WORKFLOWEXECUTIONUPDATECOMPLETEDEVENTATTRIBUTES._serialized_start = 16180 + _WORKFLOWEXECUTIONUPDATECOMPLETEDEVENTATTRIBUTES._serialized_end = 16350 + _WORKFLOWEXECUTIONUPDATEREJECTEDEVENTATTRIBUTES._serialized_start = 16353 + _WORKFLOWEXECUTIONUPDATEREJECTEDEVENTATTRIBUTES._serialized_end = 16624 + _WORKFLOWEXECUTIONUPDATEADMITTEDEVENTATTRIBUTES._serialized_start = 16627 + _WORKFLOWEXECUTIONUPDATEADMITTEDEVENTATTRIBUTES._serialized_end = 16791 + _WORKFLOWEXECUTIONPAUSEDEVENTATTRIBUTES._serialized_start = 16793 + _WORKFLOWEXECUTIONPAUSEDEVENTATTRIBUTES._serialized_end = 16887 + _WORKFLOWEXECUTIONUNPAUSEDEVENTATTRIBUTES._serialized_start = 16889 + _WORKFLOWEXECUTIONUNPAUSEDEVENTATTRIBUTES._serialized_end = 16985 + _NEXUSOPERATIONSCHEDULEDEVENTATTRIBUTES._serialized_start = 16988 + _NEXUSOPERATIONSCHEDULEDEVENTATTRIBUTES._serialized_end = 17552 + _NEXUSOPERATIONSCHEDULEDEVENTATTRIBUTES_NEXUSHEADERENTRY._serialized_start = 17502 + _NEXUSOPERATIONSCHEDULEDEVENTATTRIBUTES_NEXUSHEADERENTRY._serialized_end = 17552 + _NEXUSOPERATIONSTARTEDEVENTATTRIBUTES._serialized_start = 17555 + _NEXUSOPERATIONSTARTEDEVENTATTRIBUTES._serialized_end = 17692 + _NEXUSOPERATIONCOMPLETEDEVENTATTRIBUTES._serialized_start = 17695 + _NEXUSOPERATIONCOMPLETEDEVENTATTRIBUTES._serialized_end = 17832 + _NEXUSOPERATIONFAILEDEVENTATTRIBUTES._serialized_start = 17835 + _NEXUSOPERATIONFAILEDEVENTATTRIBUTES._serialized_end = 17971 + _NEXUSOPERATIONTIMEDOUTEVENTATTRIBUTES._serialized_start = 17974 + _NEXUSOPERATIONTIMEDOUTEVENTATTRIBUTES._serialized_end = 18112 + _NEXUSOPERATIONCANCELEDEVENTATTRIBUTES._serialized_start = 18115 + _NEXUSOPERATIONCANCELEDEVENTATTRIBUTES._serialized_end = 18253 + _NEXUSOPERATIONCANCELREQUESTEDEVENTATTRIBUTES._serialized_start = 18255 + _NEXUSOPERATIONCANCELREQUESTEDEVENTATTRIBUTES._serialized_end = 18371 + _NEXUSOPERATIONCANCELREQUESTCOMPLETEDEVENTATTRIBUTES._serialized_start = 18374 + _NEXUSOPERATIONCANCELREQUESTCOMPLETEDEVENTATTRIBUTES._serialized_end = 18525 + _NEXUSOPERATIONCANCELREQUESTFAILEDEVENTATTRIBUTES._serialized_start = 18528 + _NEXUSOPERATIONCANCELREQUESTFAILEDEVENTATTRIBUTES._serialized_end = 18727 + _HISTORYEVENT._serialized_start = 18730 + _HISTORYEVENT._serialized_end = 26586 + _HISTORY._serialized_start = 26588 + _HISTORY._serialized_end = 26652 # @@protoc_insertion_point(module_scope) diff --git a/temporalio/api/history/v1/message_pb2.pyi b/temporalio/api/history/v1/message_pb2.pyi index 536da3481..ca5a93da5 100644 --- a/temporalio/api/history/v1/message_pb2.pyi +++ b/temporalio/api/history/v1/message_pb2.pyi @@ -76,6 +76,7 @@ class WorkflowExecutionStartedEventAttributes(google.protobuf.message.Message): INHERITED_PINNED_VERSION_FIELD_NUMBER: builtins.int INHERITED_AUTO_UPGRADE_INFO_FIELD_NUMBER: builtins.int EAGER_EXECUTION_ACCEPTED_FIELD_NUMBER: builtins.int + DECLINED_TARGET_VERSION_UPGRADE_FIELD_NUMBER: builtins.int @property def workflow_type(self) -> temporalio.api.common.v1.message_pb2.WorkflowType: ... parent_workflow_namespace: builtins.str @@ -286,6 +287,19 @@ class WorkflowExecutionStartedEventAttributes(google.protobuf.message.Message): eager execution was accepted by the server. Only populated by server with version >= 1.29.0. """ + @property + def declined_target_version_upgrade(self) -> global___DeclinedTargetVersionUpgrade: + """During a previous run of this workflow, the server may have notified the SDK + that the Target Worker Deployment Version changed, but the SDK declined to + upgrade (e.g., by continuing-as-new with PINNED behavior). This field records + the target version that was declined. + + This is a wrapper message to distinguish "never declined" (nil wrapper) from + "declined an unversioned target" (non-nil wrapper with nil deployment_version). + + Used internally by the server during continue-as-new and retry. + Should not be read or interpreted by SDKs. + """ def __init__( self, *, @@ -340,12 +354,16 @@ class WorkflowExecutionStartedEventAttributes(google.protobuf.message.Message): inherited_auto_upgrade_info: temporalio.api.deployment.v1.message_pb2.InheritedAutoUpgradeInfo | None = ..., eager_execution_accepted: builtins.bool = ..., + declined_target_version_upgrade: global___DeclinedTargetVersionUpgrade + | None = ..., ) -> None: ... def HasField( self, field_name: typing_extensions.Literal[ "continued_failure", b"continued_failure", + "declined_target_version_upgrade", + b"declined_target_version_upgrade", "first_workflow_task_backoff", b"first_workflow_task_backoff", "header", @@ -403,6 +421,8 @@ class WorkflowExecutionStartedEventAttributes(google.protobuf.message.Message): b"continued_failure", "cron_schedule", b"cron_schedule", + "declined_target_version_upgrade", + b"declined_target_version_upgrade", "eager_execution_accepted", b"eager_execution_accepted", "first_execution_run_id", @@ -476,6 +496,39 @@ global___WorkflowExecutionStartedEventAttributes = ( WorkflowExecutionStartedEventAttributes ) +class DeclinedTargetVersionUpgrade(google.protobuf.message.Message): + """Wrapper for a target deployment version that the SDK declined to upgrade to. + See declined_target_version_upgrade on WorkflowExecutionStartedEventAttributes. + """ + + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + DEPLOYMENT_VERSION_FIELD_NUMBER: builtins.int + @property + def deployment_version( + self, + ) -> temporalio.api.deployment.v1.message_pb2.WorkerDeploymentVersion: ... + def __init__( + self, + *, + deployment_version: temporalio.api.deployment.v1.message_pb2.WorkerDeploymentVersion + | None = ..., + ) -> None: ... + def HasField( + self, + field_name: typing_extensions.Literal[ + "deployment_version", b"deployment_version" + ], + ) -> builtins.bool: ... + def ClearField( + self, + field_name: typing_extensions.Literal[ + "deployment_version", b"deployment_version" + ], + ) -> None: ... + +global___DeclinedTargetVersionUpgrade = DeclinedTargetVersionUpgrade + class WorkflowExecutionCompletedEventAttributes(google.protobuf.message.Message): DESCRIPTOR: google.protobuf.descriptor.Descriptor diff --git a/temporalio/api/worker/v1/__init__.py b/temporalio/api/worker/v1/__init__.py index ba261cbe3..bdf9575c6 100644 --- a/temporalio/api/worker/v1/__init__.py +++ b/temporalio/api/worker/v1/__init__.py @@ -1,17 +1,21 @@ from .message_pb2 import ( PluginInfo, + StorageDriverInfo, WorkerHeartbeat, WorkerHostInfo, WorkerInfo, + WorkerListInfo, WorkerPollerInfo, WorkerSlotsInfo, ) __all__ = [ "PluginInfo", + "StorageDriverInfo", "WorkerHeartbeat", "WorkerHostInfo", "WorkerInfo", + "WorkerListInfo", "WorkerPollerInfo", "WorkerSlotsInfo", ] diff --git a/temporalio/api/worker/v1/message_pb2.py b/temporalio/api/worker/v1/message_pb2.py index a2ab9e5c4..cf88c6722 100644 --- a/temporalio/api/worker/v1/message_pb2.py +++ b/temporalio/api/worker/v1/message_pb2.py @@ -25,7 +25,7 @@ ) DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile( - b'\n$temporal/api/worker/v1/message.proto\x12\x16temporal.api.worker.v1\x1a\x1egoogle/protobuf/duration.proto\x1a\x1fgoogle/protobuf/timestamp.proto\x1a(temporal/api/deployment/v1/message.proto\x1a"temporal/api/enums/v1/common.proto"\x82\x01\n\x10WorkerPollerInfo\x12\x17\n\x0f\x63urrent_pollers\x18\x01 \x01(\x05\x12=\n\x19last_successful_poll_time\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x16\n\x0eis_autoscaling\x18\x03 \x01(\x08"\xf1\x01\n\x0fWorkerSlotsInfo\x12\x1f\n\x17\x63urrent_available_slots\x18\x01 \x01(\x05\x12\x1a\n\x12\x63urrent_used_slots\x18\x02 \x01(\x05\x12\x1a\n\x12slot_supplier_kind\x18\x03 \x01(\t\x12\x1d\n\x15total_processed_tasks\x18\x04 \x01(\x05\x12\x1a\n\x12total_failed_tasks\x18\x05 \x01(\x05\x12%\n\x1dlast_interval_processed_tasks\x18\x06 \x01(\x05\x12#\n\x1blast_interval_failure_tasks\x18\x07 \x01(\x05"\x94\x01\n\x0eWorkerHostInfo\x12\x11\n\thost_name\x18\x01 \x01(\t\x12\x1b\n\x13worker_grouping_key\x18\x05 \x01(\t\x12\x12\n\nprocess_id\x18\x02 \x01(\t\x12\x1e\n\x16\x63urrent_host_cpu_usage\x18\x03 \x01(\x02\x12\x1e\n\x16\x63urrent_host_mem_usage\x18\x04 \x01(\x02"\xcf\t\n\x0fWorkerHeartbeat\x12\x1b\n\x13worker_instance_key\x18\x01 \x01(\t\x12\x17\n\x0fworker_identity\x18\x02 \x01(\t\x12\x39\n\thost_info\x18\x03 \x01(\x0b\x32&.temporal.api.worker.v1.WorkerHostInfo\x12\x12\n\ntask_queue\x18\x04 \x01(\t\x12O\n\x12\x64\x65ployment_version\x18\x05 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersion\x12\x10\n\x08sdk_name\x18\x06 \x01(\t\x12\x13\n\x0bsdk_version\x18\x07 \x01(\t\x12\x33\n\x06status\x18\x08 \x01(\x0e\x32#.temporal.api.enums.v1.WorkerStatus\x12.\n\nstart_time\x18\t \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x32\n\x0eheartbeat_time\x18\n \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12?\n\x1c\x65lapsed_since_last_heartbeat\x18\x0b \x01(\x0b\x32\x19.google.protobuf.Duration\x12I\n\x18workflow_task_slots_info\x18\x0c \x01(\x0b\x32\'.temporal.api.worker.v1.WorkerSlotsInfo\x12I\n\x18\x61\x63tivity_task_slots_info\x18\r \x01(\x0b\x32\'.temporal.api.worker.v1.WorkerSlotsInfo\x12\x46\n\x15nexus_task_slots_info\x18\x0e \x01(\x0b\x32\'.temporal.api.worker.v1.WorkerSlotsInfo\x12J\n\x19local_activity_slots_info\x18\x0f \x01(\x0b\x32\'.temporal.api.worker.v1.WorkerSlotsInfo\x12\x46\n\x14workflow_poller_info\x18\x10 \x01(\x0b\x32(.temporal.api.worker.v1.WorkerPollerInfo\x12M\n\x1bworkflow_sticky_poller_info\x18\x11 \x01(\x0b\x32(.temporal.api.worker.v1.WorkerPollerInfo\x12\x46\n\x14\x61\x63tivity_poller_info\x18\x12 \x01(\x0b\x32(.temporal.api.worker.v1.WorkerPollerInfo\x12\x43\n\x11nexus_poller_info\x18\x13 \x01(\x0b\x32(.temporal.api.worker.v1.WorkerPollerInfo\x12\x1e\n\x16total_sticky_cache_hit\x18\x14 \x01(\x05\x12\x1f\n\x17total_sticky_cache_miss\x18\x15 \x01(\x05\x12!\n\x19\x63urrent_sticky_cache_size\x18\x16 \x01(\x05\x12\x33\n\x07plugins\x18\x17 \x03(\x0b\x32".temporal.api.worker.v1.PluginInfo"O\n\nWorkerInfo\x12\x41\n\x10worker_heartbeat\x18\x01 \x01(\x0b\x32\'.temporal.api.worker.v1.WorkerHeartbeat"+\n\nPluginInfo\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x0f\n\x07version\x18\x02 \x01(\tB\x89\x01\n\x19io.temporal.api.worker.v1B\x0cMessageProtoP\x01Z#go.temporal.io/api/worker/v1;worker\xaa\x02\x18Temporalio.Api.Worker.V1\xea\x02\x1bTemporalio::Api::Worker::V1b\x06proto3' + b'\n$temporal/api/worker/v1/message.proto\x12\x16temporal.api.worker.v1\x1a\x1egoogle/protobuf/duration.proto\x1a\x1fgoogle/protobuf/timestamp.proto\x1a(temporal/api/deployment/v1/message.proto\x1a"temporal/api/enums/v1/common.proto"\x82\x01\n\x10WorkerPollerInfo\x12\x17\n\x0f\x63urrent_pollers\x18\x01 \x01(\x05\x12=\n\x19last_successful_poll_time\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x16\n\x0eis_autoscaling\x18\x03 \x01(\x08"\xf1\x01\n\x0fWorkerSlotsInfo\x12\x1f\n\x17\x63urrent_available_slots\x18\x01 \x01(\x05\x12\x1a\n\x12\x63urrent_used_slots\x18\x02 \x01(\x05\x12\x1a\n\x12slot_supplier_kind\x18\x03 \x01(\t\x12\x1d\n\x15total_processed_tasks\x18\x04 \x01(\x05\x12\x1a\n\x12total_failed_tasks\x18\x05 \x01(\x05\x12%\n\x1dlast_interval_processed_tasks\x18\x06 \x01(\x05\x12#\n\x1blast_interval_failure_tasks\x18\x07 \x01(\x05"\x94\x01\n\x0eWorkerHostInfo\x12\x11\n\thost_name\x18\x01 \x01(\t\x12\x1b\n\x13worker_grouping_key\x18\x05 \x01(\t\x12\x12\n\nprocess_id\x18\x02 \x01(\t\x12\x1e\n\x16\x63urrent_host_cpu_usage\x18\x03 \x01(\x02\x12\x1e\n\x16\x63urrent_host_mem_usage\x18\x04 \x01(\x02"\x8b\n\n\x0fWorkerHeartbeat\x12\x1b\n\x13worker_instance_key\x18\x01 \x01(\t\x12\x17\n\x0fworker_identity\x18\x02 \x01(\t\x12\x39\n\thost_info\x18\x03 \x01(\x0b\x32&.temporal.api.worker.v1.WorkerHostInfo\x12\x12\n\ntask_queue\x18\x04 \x01(\t\x12O\n\x12\x64\x65ployment_version\x18\x05 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersion\x12\x10\n\x08sdk_name\x18\x06 \x01(\t\x12\x13\n\x0bsdk_version\x18\x07 \x01(\t\x12\x33\n\x06status\x18\x08 \x01(\x0e\x32#.temporal.api.enums.v1.WorkerStatus\x12.\n\nstart_time\x18\t \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x32\n\x0eheartbeat_time\x18\n \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12?\n\x1c\x65lapsed_since_last_heartbeat\x18\x0b \x01(\x0b\x32\x19.google.protobuf.Duration\x12I\n\x18workflow_task_slots_info\x18\x0c \x01(\x0b\x32\'.temporal.api.worker.v1.WorkerSlotsInfo\x12I\n\x18\x61\x63tivity_task_slots_info\x18\r \x01(\x0b\x32\'.temporal.api.worker.v1.WorkerSlotsInfo\x12\x46\n\x15nexus_task_slots_info\x18\x0e \x01(\x0b\x32\'.temporal.api.worker.v1.WorkerSlotsInfo\x12J\n\x19local_activity_slots_info\x18\x0f \x01(\x0b\x32\'.temporal.api.worker.v1.WorkerSlotsInfo\x12\x46\n\x14workflow_poller_info\x18\x10 \x01(\x0b\x32(.temporal.api.worker.v1.WorkerPollerInfo\x12M\n\x1bworkflow_sticky_poller_info\x18\x11 \x01(\x0b\x32(.temporal.api.worker.v1.WorkerPollerInfo\x12\x46\n\x14\x61\x63tivity_poller_info\x18\x12 \x01(\x0b\x32(.temporal.api.worker.v1.WorkerPollerInfo\x12\x43\n\x11nexus_poller_info\x18\x13 \x01(\x0b\x32(.temporal.api.worker.v1.WorkerPollerInfo\x12\x1e\n\x16total_sticky_cache_hit\x18\x14 \x01(\x05\x12\x1f\n\x17total_sticky_cache_miss\x18\x15 \x01(\x05\x12!\n\x19\x63urrent_sticky_cache_size\x18\x16 \x01(\x05\x12\x33\n\x07plugins\x18\x17 \x03(\x0b\x32".temporal.api.worker.v1.PluginInfo\x12:\n\x07\x64rivers\x18\x18 \x03(\x0b\x32).temporal.api.worker.v1.StorageDriverInfo"O\n\nWorkerInfo\x12\x41\n\x10worker_heartbeat\x18\x01 \x01(\x0b\x32\'.temporal.api.worker.v1.WorkerHeartbeat"\xec\x03\n\x0eWorkerListInfo\x12\x1b\n\x13worker_instance_key\x18\x01 \x01(\t\x12\x17\n\x0fworker_identity\x18\x02 \x01(\t\x12\x12\n\ntask_queue\x18\x03 \x01(\t\x12O\n\x12\x64\x65ployment_version\x18\x04 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersion\x12\x10\n\x08sdk_name\x18\x05 \x01(\t\x12\x13\n\x0bsdk_version\x18\x06 \x01(\t\x12\x33\n\x06status\x18\x07 \x01(\x0e\x32#.temporal.api.enums.v1.WorkerStatus\x12.\n\nstart_time\x18\x08 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x11\n\thost_name\x18\t \x01(\t\x12\x1b\n\x13worker_grouping_key\x18\n \x01(\t\x12\x12\n\nprocess_id\x18\x0b \x01(\t\x12\x33\n\x07plugins\x18\x0c \x03(\x0b\x32".temporal.api.worker.v1.PluginInfo\x12:\n\x07\x64rivers\x18\r \x03(\x0b\x32).temporal.api.worker.v1.StorageDriverInfo"+\n\nPluginInfo\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x0f\n\x07version\x18\x02 \x01(\t"!\n\x11StorageDriverInfo\x12\x0c\n\x04type\x18\x01 \x01(\tB\x89\x01\n\x19io.temporal.api.worker.v1B\x0cMessageProtoP\x01Z#go.temporal.io/api/worker/v1;worker\xaa\x02\x18Temporalio.Api.Worker.V1\xea\x02\x1bTemporalio::Api::Worker::V1b\x06proto3' ) @@ -34,7 +34,9 @@ _WORKERHOSTINFO = DESCRIPTOR.message_types_by_name["WorkerHostInfo"] _WORKERHEARTBEAT = DESCRIPTOR.message_types_by_name["WorkerHeartbeat"] _WORKERINFO = DESCRIPTOR.message_types_by_name["WorkerInfo"] +_WORKERLISTINFO = DESCRIPTOR.message_types_by_name["WorkerListInfo"] _PLUGININFO = DESCRIPTOR.message_types_by_name["PluginInfo"] +_STORAGEDRIVERINFO = DESCRIPTOR.message_types_by_name["StorageDriverInfo"] WorkerPollerInfo = _reflection.GeneratedProtocolMessageType( "WorkerPollerInfo", (_message.Message,), @@ -90,6 +92,17 @@ ) _sym_db.RegisterMessage(WorkerInfo) +WorkerListInfo = _reflection.GeneratedProtocolMessageType( + "WorkerListInfo", + (_message.Message,), + { + "DESCRIPTOR": _WORKERLISTINFO, + "__module__": "temporalio.api.worker.v1.message_pb2", + # @@protoc_insertion_point(class_scope:temporal.api.worker.v1.WorkerListInfo) + }, +) +_sym_db.RegisterMessage(WorkerListInfo) + PluginInfo = _reflection.GeneratedProtocolMessageType( "PluginInfo", (_message.Message,), @@ -101,6 +114,17 @@ ) _sym_db.RegisterMessage(PluginInfo) +StorageDriverInfo = _reflection.GeneratedProtocolMessageType( + "StorageDriverInfo", + (_message.Message,), + { + "DESCRIPTOR": _STORAGEDRIVERINFO, + "__module__": "temporalio.api.worker.v1.message_pb2", + # @@protoc_insertion_point(class_scope:temporal.api.worker.v1.StorageDriverInfo) + }, +) +_sym_db.RegisterMessage(StorageDriverInfo) + if _descriptor._USE_C_DESCRIPTORS == False: DESCRIPTOR._options = None DESCRIPTOR._serialized_options = b"\n\031io.temporal.api.worker.v1B\014MessageProtoP\001Z#go.temporal.io/api/worker/v1;worker\252\002\030Temporalio.Api.Worker.V1\352\002\033Temporalio::Api::Worker::V1" @@ -111,9 +135,13 @@ _WORKERHOSTINFO._serialized_start = 585 _WORKERHOSTINFO._serialized_end = 733 _WORKERHEARTBEAT._serialized_start = 736 - _WORKERHEARTBEAT._serialized_end = 1967 - _WORKERINFO._serialized_start = 1969 - _WORKERINFO._serialized_end = 2048 - _PLUGININFO._serialized_start = 2050 - _PLUGININFO._serialized_end = 2093 + _WORKERHEARTBEAT._serialized_end = 2027 + _WORKERINFO._serialized_start = 2029 + _WORKERINFO._serialized_end = 2108 + _WORKERLISTINFO._serialized_start = 2111 + _WORKERLISTINFO._serialized_end = 2603 + _PLUGININFO._serialized_start = 2605 + _PLUGININFO._serialized_end = 2648 + _STORAGEDRIVERINFO._serialized_start = 2650 + _STORAGEDRIVERINFO._serialized_end = 2683 # @@protoc_insertion_point(module_scope) diff --git a/temporalio/api/worker/v1/message_pb2.pyi b/temporalio/api/worker/v1/message_pb2.pyi index cbf18c352..632dd49dd 100644 --- a/temporalio/api/worker/v1/message_pb2.pyi +++ b/temporalio/api/worker/v1/message_pb2.pyi @@ -216,6 +216,7 @@ class WorkerHeartbeat(google.protobuf.message.Message): TOTAL_STICKY_CACHE_MISS_FIELD_NUMBER: builtins.int CURRENT_STICKY_CACHE_SIZE_FIELD_NUMBER: builtins.int PLUGINS_FIELD_NUMBER: builtins.int + DRIVERS_FIELD_NUMBER: builtins.int worker_instance_key: builtins.str """Worker identifier, should be unique for the namespace. It is distinct from worker identity, which is not necessarily namespace-unique. @@ -279,6 +280,13 @@ class WorkerHeartbeat(google.protobuf.message.Message): global___PluginInfo ]: """Plugins currently in use by this SDK.""" + @property + def drivers( + self, + ) -> google.protobuf.internal.containers.RepeatedCompositeFieldContainer[ + global___StorageDriverInfo + ]: + """Storage drivers in use by this SDK.""" def __init__( self, *, @@ -307,6 +315,7 @@ class WorkerHeartbeat(google.protobuf.message.Message): total_sticky_cache_miss: builtins.int = ..., current_sticky_cache_size: builtins.int = ..., plugins: collections.abc.Iterable[global___PluginInfo] | None = ..., + drivers: collections.abc.Iterable[global___StorageDriverInfo] | None = ..., ) -> None: ... def HasField( self, @@ -350,6 +359,8 @@ class WorkerHeartbeat(google.protobuf.message.Message): b"current_sticky_cache_size", "deployment_version", b"deployment_version", + "drivers", + b"drivers", "elapsed_since_last_heartbeat", b"elapsed_since_last_heartbeat", "heartbeat_time", @@ -394,6 +405,8 @@ class WorkerHeartbeat(google.protobuf.message.Message): global___WorkerHeartbeat = WorkerHeartbeat class WorkerInfo(google.protobuf.message.Message): + """Detailed worker information.""" + DESCRIPTOR: google.protobuf.descriptor.Descriptor WORKER_HEARTBEAT_FIELD_NUMBER: builtins.int @@ -415,6 +428,132 @@ class WorkerInfo(google.protobuf.message.Message): global___WorkerInfo = WorkerInfo +class WorkerListInfo(google.protobuf.message.Message): + """Limited worker information returned in the list response. + When adding fields here, ensure that it is also added to WorkerInfo (as it carries the full worker information). + """ + + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + WORKER_INSTANCE_KEY_FIELD_NUMBER: builtins.int + WORKER_IDENTITY_FIELD_NUMBER: builtins.int + TASK_QUEUE_FIELD_NUMBER: builtins.int + DEPLOYMENT_VERSION_FIELD_NUMBER: builtins.int + SDK_NAME_FIELD_NUMBER: builtins.int + SDK_VERSION_FIELD_NUMBER: builtins.int + STATUS_FIELD_NUMBER: builtins.int + START_TIME_FIELD_NUMBER: builtins.int + HOST_NAME_FIELD_NUMBER: builtins.int + WORKER_GROUPING_KEY_FIELD_NUMBER: builtins.int + PROCESS_ID_FIELD_NUMBER: builtins.int + PLUGINS_FIELD_NUMBER: builtins.int + DRIVERS_FIELD_NUMBER: builtins.int + worker_instance_key: builtins.str + """Worker identifier, should be unique for the namespace. + It is distinct from worker identity, which is not necessarily namespace-unique. + """ + worker_identity: builtins.str + """Worker identity, set by the client, may not be unique. + Usually host_name+(user group name)+process_id, but can be overwritten by the user. + """ + task_queue: builtins.str + """Task queue this worker is polling for tasks.""" + @property + def deployment_version( + self, + ) -> temporalio.api.deployment.v1.message_pb2.WorkerDeploymentVersion: ... + sdk_name: builtins.str + sdk_version: builtins.str + status: temporalio.api.enums.v1.common_pb2.WorkerStatus.ValueType + """Worker status. Defined by SDK.""" + @property + def start_time(self) -> google.protobuf.timestamp_pb2.Timestamp: + """Worker start time. + It can be used to determine worker uptime. (current time - start time) + """ + host_name: builtins.str + """Worker host identifier.""" + worker_grouping_key: builtins.str + """Worker grouping identifier. A key to group workers that share the same client+namespace+process. + This will be used to build the worker command nexus task queue name: + "temporal-sys/worker-commands/{worker_grouping_key}" + """ + process_id: builtins.str + """Worker process identifier. This id only needs to be unique + within one host (so using e.g. a unix pid would be appropriate). + """ + @property + def plugins( + self, + ) -> google.protobuf.internal.containers.RepeatedCompositeFieldContainer[ + global___PluginInfo + ]: + """Plugins currently in use by this SDK.""" + @property + def drivers( + self, + ) -> google.protobuf.internal.containers.RepeatedCompositeFieldContainer[ + global___StorageDriverInfo + ]: + """Storage drivers in use by this SDK.""" + def __init__( + self, + *, + worker_instance_key: builtins.str = ..., + worker_identity: builtins.str = ..., + task_queue: builtins.str = ..., + deployment_version: temporalio.api.deployment.v1.message_pb2.WorkerDeploymentVersion + | None = ..., + sdk_name: builtins.str = ..., + sdk_version: builtins.str = ..., + status: temporalio.api.enums.v1.common_pb2.WorkerStatus.ValueType = ..., + start_time: google.protobuf.timestamp_pb2.Timestamp | None = ..., + host_name: builtins.str = ..., + worker_grouping_key: builtins.str = ..., + process_id: builtins.str = ..., + plugins: collections.abc.Iterable[global___PluginInfo] | None = ..., + drivers: collections.abc.Iterable[global___StorageDriverInfo] | None = ..., + ) -> None: ... + def HasField( + self, + field_name: typing_extensions.Literal[ + "deployment_version", b"deployment_version", "start_time", b"start_time" + ], + ) -> builtins.bool: ... + def ClearField( + self, + field_name: typing_extensions.Literal[ + "deployment_version", + b"deployment_version", + "drivers", + b"drivers", + "host_name", + b"host_name", + "plugins", + b"plugins", + "process_id", + b"process_id", + "sdk_name", + b"sdk_name", + "sdk_version", + b"sdk_version", + "start_time", + b"start_time", + "status", + b"status", + "task_queue", + b"task_queue", + "worker_grouping_key", + b"worker_grouping_key", + "worker_identity", + b"worker_identity", + "worker_instance_key", + b"worker_instance_key", + ], + ) -> None: ... + +global___WorkerListInfo = WorkerListInfo + class PluginInfo(google.protobuf.message.Message): DESCRIPTOR: google.protobuf.descriptor.Descriptor @@ -436,3 +575,20 @@ class PluginInfo(google.protobuf.message.Message): ) -> None: ... global___PluginInfo = PluginInfo + +class StorageDriverInfo(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + TYPE_FIELD_NUMBER: builtins.int + type: builtins.str + """The type of the driver, required.""" + def __init__( + self, + *, + type: builtins.str = ..., + ) -> None: ... + def ClearField( + self, field_name: typing_extensions.Literal["type", b"type"] + ) -> None: ... + +global___StorageDriverInfo = StorageDriverInfo diff --git a/temporalio/api/workflowservice/v1/request_response_pb2.py b/temporalio/api/workflowservice/v1/request_response_pb2.py index 6acfddde4..826936e33 100644 --- a/temporalio/api/workflowservice/v1/request_response_pb2.py +++ b/temporalio/api/workflowservice/v1/request_response_pb2.py @@ -122,7 +122,7 @@ ) DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile( - b'\n6temporal/api/workflowservice/v1/request_response.proto\x12\x1ftemporal.api.workflowservice.v1\x1a+temporal/api/enums/v1/batch_operation.proto\x1a"temporal/api/enums/v1/common.proto\x1a$temporal/api/enums/v1/workflow.proto\x1a%temporal/api/enums/v1/namespace.proto\x1a(temporal/api/enums/v1/failed_cause.proto\x1a!temporal/api/enums/v1/query.proto\x1a!temporal/api/enums/v1/reset.proto\x1a&temporal/api/enums/v1/task_queue.proto\x1a&temporal/api/enums/v1/deployment.proto\x1a"temporal/api/enums/v1/update.proto\x1a$temporal/api/enums/v1/activity.proto\x1a&temporal/api/activity/v1/message.proto\x1a$temporal/api/common/v1/message.proto\x1a%temporal/api/history/v1/message.proto\x1a&temporal/api/workflow/v1/message.proto\x1a%temporal/api/command/v1/message.proto\x1a(temporal/api/deployment/v1/message.proto\x1a%temporal/api/failure/v1/message.proto\x1a$temporal/api/filter/v1/message.proto\x1a&temporal/api/protocol/v1/message.proto\x1a\'temporal/api/namespace/v1/message.proto\x1a#temporal/api/query/v1/message.proto\x1a)temporal/api/replication/v1/message.proto\x1a#temporal/api/rules/v1/message.proto\x1a\'temporal/api/sdk/v1/worker_config.proto\x1a&temporal/api/schedule/v1/message.proto\x1a\'temporal/api/taskqueue/v1/message.proto\x1a$temporal/api/update/v1/message.proto\x1a%temporal/api/version/v1/message.proto\x1a#temporal/api/batch/v1/message.proto\x1a\x30temporal/api/sdk/v1/task_complete_metadata.proto\x1a\'temporal/api/sdk/v1/user_metadata.proto\x1a#temporal/api/nexus/v1/message.proto\x1a$temporal/api/worker/v1/message.proto\x1a\x1egoogle/protobuf/duration.proto\x1a google/protobuf/field_mask.proto\x1a\x1fgoogle/protobuf/timestamp.proto"\x88\x05\n\x18RegisterNamespaceRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0b\x64\x65scription\x18\x02 \x01(\t\x12\x13\n\x0bowner_email\x18\x03 \x01(\t\x12\x46\n#workflow_execution_retention_period\x18\x04 \x01(\x0b\x32\x19.google.protobuf.Duration\x12G\n\x08\x63lusters\x18\x05 \x03(\x0b\x32\x35.temporal.api.replication.v1.ClusterReplicationConfig\x12\x1b\n\x13\x61\x63tive_cluster_name\x18\x06 \x01(\t\x12Q\n\x04\x64\x61ta\x18\x07 \x03(\x0b\x32\x43.temporal.api.workflowservice.v1.RegisterNamespaceRequest.DataEntry\x12\x16\n\x0esecurity_token\x18\x08 \x01(\t\x12\x1b\n\x13is_global_namespace\x18\t \x01(\x08\x12\x44\n\x16history_archival_state\x18\n \x01(\x0e\x32$.temporal.api.enums.v1.ArchivalState\x12\x1c\n\x14history_archival_uri\x18\x0b \x01(\t\x12G\n\x19visibility_archival_state\x18\x0c \x01(\x0e\x32$.temporal.api.enums.v1.ArchivalState\x12\x1f\n\x17visibility_archival_uri\x18\r \x01(\t\x1a+\n\tDataEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01"\x1b\n\x19RegisterNamespaceResponse"\x89\x01\n\x15ListNamespacesRequest\x12\x11\n\tpage_size\x18\x01 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c\x12\x44\n\x10namespace_filter\x18\x03 \x01(\x0b\x32*.temporal.api.namespace.v1.NamespaceFilter"\x81\x01\n\x16ListNamespacesResponse\x12N\n\nnamespaces\x18\x01 \x03(\x0b\x32:.temporal.api.workflowservice.v1.DescribeNamespaceResponse\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c"9\n\x18\x44\x65scribeNamespaceRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\n\n\x02id\x18\x02 \x01(\t"\xec\x02\n\x19\x44\x65scribeNamespaceResponse\x12@\n\x0enamespace_info\x18\x01 \x01(\x0b\x32(.temporal.api.namespace.v1.NamespaceInfo\x12:\n\x06\x63onfig\x18\x02 \x01(\x0b\x32*.temporal.api.namespace.v1.NamespaceConfig\x12S\n\x12replication_config\x18\x03 \x01(\x0b\x32\x37.temporal.api.replication.v1.NamespaceReplicationConfig\x12\x18\n\x10\x66\x61ilover_version\x18\x04 \x01(\x03\x12\x1b\n\x13is_global_namespace\x18\x05 \x01(\x08\x12\x45\n\x10\x66\x61ilover_history\x18\x06 \x03(\x0b\x32+.temporal.api.replication.v1.FailoverStatus"\xcf\x02\n\x16UpdateNamespaceRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x43\n\x0bupdate_info\x18\x02 \x01(\x0b\x32..temporal.api.namespace.v1.UpdateNamespaceInfo\x12:\n\x06\x63onfig\x18\x03 \x01(\x0b\x32*.temporal.api.namespace.v1.NamespaceConfig\x12S\n\x12replication_config\x18\x04 \x01(\x0b\x32\x37.temporal.api.replication.v1.NamespaceReplicationConfig\x12\x16\n\x0esecurity_token\x18\x05 \x01(\t\x12\x19\n\x11\x64\x65lete_bad_binary\x18\x06 \x01(\t\x12\x19\n\x11promote_namespace\x18\x07 \x01(\x08"\xa3\x02\n\x17UpdateNamespaceResponse\x12@\n\x0enamespace_info\x18\x01 \x01(\x0b\x32(.temporal.api.namespace.v1.NamespaceInfo\x12:\n\x06\x63onfig\x18\x02 \x01(\x0b\x32*.temporal.api.namespace.v1.NamespaceConfig\x12S\n\x12replication_config\x18\x03 \x01(\x0b\x32\x37.temporal.api.replication.v1.NamespaceReplicationConfig\x12\x18\n\x10\x66\x61ilover_version\x18\x04 \x01(\x03\x12\x1b\n\x13is_global_namespace\x18\x05 \x01(\x08"F\n\x19\x44\x65precateNamespaceRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x16\n\x0esecurity_token\x18\x02 \x01(\t"\x1c\n\x1a\x44\x65precateNamespaceResponse"\x87\x0c\n\x1dStartWorkflowExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12;\n\rworkflow_type\x18\x03 \x01(\x0b\x32$.temporal.api.common.v1.WorkflowType\x12\x38\n\ntask_queue\x18\x04 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12/\n\x05input\x18\x05 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12=\n\x1aworkflow_execution_timeout\x18\x06 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x37\n\x14workflow_run_timeout\x18\x07 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x38\n\x15workflow_task_timeout\x18\x08 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x10\n\x08identity\x18\t \x01(\t\x12\x12\n\nrequest_id\x18\n \x01(\t\x12N\n\x18workflow_id_reuse_policy\x18\x0b \x01(\x0e\x32,.temporal.api.enums.v1.WorkflowIdReusePolicy\x12T\n\x1bworkflow_id_conflict_policy\x18\x16 \x01(\x0e\x32/.temporal.api.enums.v1.WorkflowIdConflictPolicy\x12\x39\n\x0cretry_policy\x18\x0c \x01(\x0b\x32#.temporal.api.common.v1.RetryPolicy\x12\x15\n\rcron_schedule\x18\r \x01(\t\x12*\n\x04memo\x18\x0e \x01(\x0b\x32\x1c.temporal.api.common.v1.Memo\x12\x43\n\x11search_attributes\x18\x0f \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes\x12.\n\x06header\x18\x10 \x01(\x0b\x32\x1e.temporal.api.common.v1.Header\x12\x1f\n\x17request_eager_execution\x18\x11 \x01(\x08\x12;\n\x11\x63ontinued_failure\x18\x12 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12@\n\x16last_completion_result\x18\x13 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x37\n\x14workflow_start_delay\x18\x14 \x01(\x0b\x32\x19.google.protobuf.Duration\x12>\n\x14\x63ompletion_callbacks\x18\x15 \x03(\x0b\x32 .temporal.api.common.v1.Callback\x12\x38\n\ruser_metadata\x18\x17 \x01(\x0b\x32!.temporal.api.sdk.v1.UserMetadata\x12+\n\x05links\x18\x18 \x03(\x0b\x32\x1c.temporal.api.common.v1.Link\x12I\n\x13versioning_override\x18\x19 \x01(\x0b\x32,.temporal.api.workflow.v1.VersioningOverride\x12H\n\x13on_conflict_options\x18\x1a \x01(\x0b\x32+.temporal.api.workflow.v1.OnConflictOptions\x12\x32\n\x08priority\x18\x1b \x01(\x0b\x32 .temporal.api.common.v1.Priority\x12\\\n\x1f\x65\x61ger_worker_deployment_options\x18\x1c \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentOptions"\x8a\x02\n\x1eStartWorkflowExecutionResponse\x12\x0e\n\x06run_id\x18\x01 \x01(\t\x12\x0f\n\x07started\x18\x03 \x01(\x08\x12>\n\x06status\x18\x05 \x01(\x0e\x32..temporal.api.enums.v1.WorkflowExecutionStatus\x12[\n\x13\x65\x61ger_workflow_task\x18\x02 \x01(\x0b\x32>.temporal.api.workflowservice.v1.PollWorkflowTaskQueueResponse\x12*\n\x04link\x18\x04 \x01(\x0b\x32\x1c.temporal.api.common.v1.Link"\xaa\x02\n"GetWorkflowExecutionHistoryRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12<\n\texecution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x19\n\x11maximum_page_size\x18\x03 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x04 \x01(\x0c\x12\x16\n\x0ewait_new_event\x18\x05 \x01(\x08\x12P\n\x19history_event_filter_type\x18\x06 \x01(\x0e\x32-.temporal.api.enums.v1.HistoryEventFilterType\x12\x15\n\rskip_archival\x18\x07 \x01(\x08"\xba\x01\n#GetWorkflowExecutionHistoryResponse\x12\x31\n\x07history\x18\x01 \x01(\x0b\x32 .temporal.api.history.v1.History\x12\x35\n\x0braw_history\x18\x02 \x03(\x0b\x32 .temporal.api.common.v1.DataBlob\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c\x12\x10\n\x08\x61rchived\x18\x04 \x01(\x08"\xb0\x01\n)GetWorkflowExecutionHistoryReverseRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12<\n\texecution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x19\n\x11maximum_page_size\x18\x03 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x04 \x01(\x0c"x\n*GetWorkflowExecutionHistoryReverseResponse\x12\x31\n\x07history\x18\x01 \x01(\x0b\x32 .temporal.api.history.v1.History\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c"\xfc\x02\n\x1cPollWorkflowTaskQueueRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x38\n\ntask_queue\x18\x02 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x1b\n\x13worker_instance_key\x18\x08 \x01(\t\x12\x1b\n\x0f\x62inary_checksum\x18\x04 \x01(\tB\x02\x18\x01\x12Z\n\x1bworker_version_capabilities\x18\x05 \x01(\x0b\x32\x31.temporal.api.common.v1.WorkerVersionCapabilitiesB\x02\x18\x01\x12O\n\x12\x64\x65ployment_options\x18\x06 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentOptionsJ\x04\x08\x07\x10\x08R\x10worker_heartbeat"\x91\x07\n\x1dPollWorkflowTaskQueueResponse\x12\x12\n\ntask_token\x18\x01 \x01(\x0c\x12\x45\n\x12workflow_execution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12;\n\rworkflow_type\x18\x03 \x01(\x0b\x32$.temporal.api.common.v1.WorkflowType\x12!\n\x19previous_started_event_id\x18\x04 \x01(\x03\x12\x18\n\x10started_event_id\x18\x05 \x01(\x03\x12\x0f\n\x07\x61ttempt\x18\x06 \x01(\x05\x12\x1a\n\x12\x62\x61\x63klog_count_hint\x18\x07 \x01(\x03\x12\x31\n\x07history\x18\x08 \x01(\x0b\x32 .temporal.api.history.v1.History\x12\x17\n\x0fnext_page_token\x18\t \x01(\x0c\x12\x33\n\x05query\x18\n \x01(\x0b\x32$.temporal.api.query.v1.WorkflowQuery\x12K\n\x1dworkflow_execution_task_queue\x18\x0b \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12\x32\n\x0escheduled_time\x18\x0c \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x30\n\x0cstarted_time\x18\r \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\\\n\x07queries\x18\x0e \x03(\x0b\x32K.temporal.api.workflowservice.v1.PollWorkflowTaskQueueResponse.QueriesEntry\x12\x33\n\x08messages\x18\x0f \x03(\x0b\x32!.temporal.api.protocol.v1.Message\x12Q\n\x17poller_scaling_decision\x18\x10 \x01(\x0b\x32\x30.temporal.api.taskqueue.v1.PollerScalingDecision\x1aT\n\x0cQueriesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x33\n\x05value\x18\x02 \x01(\x0b\x32$.temporal.api.query.v1.WorkflowQuery:\x02\x38\x01"\xb5\t\n#RespondWorkflowTaskCompletedRequest\x12\x12\n\ntask_token\x18\x01 \x01(\x0c\x12\x32\n\x08\x63ommands\x18\x02 \x03(\x0b\x32 .temporal.api.command.v1.Command\x12\x10\n\x08identity\x18\x03 \x01(\t\x12O\n\x11sticky_attributes\x18\x04 \x01(\x0b\x32\x34.temporal.api.taskqueue.v1.StickyExecutionAttributes\x12 \n\x18return_new_workflow_task\x18\x05 \x01(\x08\x12&\n\x1e\x66orce_create_new_workflow_task\x18\x06 \x01(\x08\x12\x1b\n\x0f\x62inary_checksum\x18\x07 \x01(\tB\x02\x18\x01\x12m\n\rquery_results\x18\x08 \x03(\x0b\x32V.temporal.api.workflowservice.v1.RespondWorkflowTaskCompletedRequest.QueryResultsEntry\x12\x11\n\tnamespace\x18\t \x01(\t\x12L\n\x14worker_version_stamp\x18\n \x01(\x0b\x32*.temporal.api.common.v1.WorkerVersionStampB\x02\x18\x01\x12\x33\n\x08messages\x18\x0b \x03(\x0b\x32!.temporal.api.protocol.v1.Message\x12H\n\x0csdk_metadata\x18\x0c \x01(\x0b\x32\x32.temporal.api.sdk.v1.WorkflowTaskCompletedMetadata\x12\x43\n\x11metering_metadata\x18\r \x01(\x0b\x32(.temporal.api.common.v1.MeteringMetadata\x12g\n\x0c\x63\x61pabilities\x18\x0e \x01(\x0b\x32Q.temporal.api.workflowservice.v1.RespondWorkflowTaskCompletedRequest.Capabilities\x12>\n\ndeployment\x18\x0f \x01(\x0b\x32&.temporal.api.deployment.v1.DeploymentB\x02\x18\x01\x12\x46\n\x13versioning_behavior\x18\x10 \x01(\x0e\x32).temporal.api.enums.v1.VersioningBehavior\x12O\n\x12\x64\x65ployment_options\x18\x11 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentOptions\x1a_\n\x11QueryResultsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x39\n\x05value\x18\x02 \x01(\x0b\x32*.temporal.api.query.v1.WorkflowQueryResult:\x02\x38\x01\x1a\x45\n\x0c\x43\x61pabilities\x12\x35\n-discard_speculative_workflow_task_with_events\x18\x01 \x01(\x08"\xf5\x01\n$RespondWorkflowTaskCompletedResponse\x12U\n\rworkflow_task\x18\x01 \x01(\x0b\x32>.temporal.api.workflowservice.v1.PollWorkflowTaskQueueResponse\x12V\n\x0e\x61\x63tivity_tasks\x18\x02 \x03(\x0b\x32>.temporal.api.workflowservice.v1.PollActivityTaskQueueResponse\x12\x1e\n\x16reset_history_event_id\x18\x03 \x01(\x03"\xf8\x03\n RespondWorkflowTaskFailedRequest\x12\x12\n\ntask_token\x18\x01 \x01(\x0c\x12=\n\x05\x63\x61use\x18\x02 \x01(\x0e\x32..temporal.api.enums.v1.WorkflowTaskFailedCause\x12\x31\n\x07\x66\x61ilure\x18\x03 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12\x10\n\x08identity\x18\x04 \x01(\t\x12\x1b\n\x0f\x62inary_checksum\x18\x05 \x01(\tB\x02\x18\x01\x12\x11\n\tnamespace\x18\x06 \x01(\t\x12\x33\n\x08messages\x18\x07 \x03(\x0b\x32!.temporal.api.protocol.v1.Message\x12\x46\n\x0eworker_version\x18\x08 \x01(\x0b\x32*.temporal.api.common.v1.WorkerVersionStampB\x02\x18\x01\x12>\n\ndeployment\x18\t \x01(\x0b\x32&.temporal.api.deployment.v1.DeploymentB\x02\x18\x01\x12O\n\x12\x64\x65ployment_options\x18\n \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentOptions"#\n!RespondWorkflowTaskFailedResponse"\xaa\x03\n\x1cPollActivityTaskQueueRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x38\n\ntask_queue\x18\x02 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x1b\n\x13worker_instance_key\x18\x08 \x01(\t\x12I\n\x13task_queue_metadata\x18\x04 \x01(\x0b\x32,.temporal.api.taskqueue.v1.TaskQueueMetadata\x12Z\n\x1bworker_version_capabilities\x18\x05 \x01(\x0b\x32\x31.temporal.api.common.v1.WorkerVersionCapabilitiesB\x02\x18\x01\x12O\n\x12\x64\x65ployment_options\x18\x06 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentOptionsJ\x04\x08\x07\x10\x08R\x10worker_heartbeat"\x88\x08\n\x1dPollActivityTaskQueueResponse\x12\x12\n\ntask_token\x18\x01 \x01(\x0c\x12\x1a\n\x12workflow_namespace\x18\x02 \x01(\t\x12;\n\rworkflow_type\x18\x03 \x01(\x0b\x32$.temporal.api.common.v1.WorkflowType\x12\x45\n\x12workflow_execution\x18\x04 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12;\n\ractivity_type\x18\x05 \x01(\x0b\x32$.temporal.api.common.v1.ActivityType\x12\x13\n\x0b\x61\x63tivity_id\x18\x06 \x01(\t\x12.\n\x06header\x18\x07 \x01(\x0b\x32\x1e.temporal.api.common.v1.Header\x12/\n\x05input\x18\x08 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12;\n\x11heartbeat_details\x18\t \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x32\n\x0escheduled_time\x18\n \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x42\n\x1e\x63urrent_attempt_scheduled_time\x18\x0b \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x30\n\x0cstarted_time\x18\x0c \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x0f\n\x07\x61ttempt\x18\r \x01(\x05\x12<\n\x19schedule_to_close_timeout\x18\x0e \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x39\n\x16start_to_close_timeout\x18\x0f \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x34\n\x11heartbeat_timeout\x18\x10 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x39\n\x0cretry_policy\x18\x11 \x01(\x0b\x32#.temporal.api.common.v1.RetryPolicy\x12Q\n\x17poller_scaling_decision\x18\x12 \x01(\x0b\x32\x30.temporal.api.taskqueue.v1.PollerScalingDecision\x12\x32\n\x08priority\x18\x13 \x01(\x0b\x32 .temporal.api.common.v1.Priority\x12\x17\n\x0f\x61\x63tivity_run_id\x18\x14 \x01(\t"\x90\x01\n"RecordActivityTaskHeartbeatRequest\x12\x12\n\ntask_token\x18\x01 \x01(\x0c\x12\x31\n\x07\x64\x65tails\x18\x02 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x11\n\tnamespace\x18\x04 \x01(\t"p\n#RecordActivityTaskHeartbeatResponse\x12\x18\n\x10\x63\x61ncel_requested\x18\x01 \x01(\x08\x12\x17\n\x0f\x61\x63tivity_paused\x18\x02 \x01(\x08\x12\x16\n\x0e\x61\x63tivity_reset\x18\x03 \x01(\x08"\xba\x01\n&RecordActivityTaskHeartbeatByIdRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x12\x13\n\x0b\x61\x63tivity_id\x18\x04 \x01(\t\x12\x31\n\x07\x64\x65tails\x18\x05 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x10\n\x08identity\x18\x06 \x01(\t"t\n\'RecordActivityTaskHeartbeatByIdResponse\x12\x18\n\x10\x63\x61ncel_requested\x18\x01 \x01(\x08\x12\x17\n\x0f\x61\x63tivity_paused\x18\x02 \x01(\x08\x12\x16\n\x0e\x61\x63tivity_reset\x18\x03 \x01(\x08"\xe9\x02\n#RespondActivityTaskCompletedRequest\x12\x12\n\ntask_token\x18\x01 \x01(\x0c\x12\x30\n\x06result\x18\x02 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x11\n\tnamespace\x18\x04 \x01(\t\x12\x46\n\x0eworker_version\x18\x05 \x01(\x0b\x32*.temporal.api.common.v1.WorkerVersionStampB\x02\x18\x01\x12>\n\ndeployment\x18\x06 \x01(\x0b\x32&.temporal.api.deployment.v1.DeploymentB\x02\x18\x01\x12O\n\x12\x64\x65ployment_options\x18\x07 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentOptions"&\n$RespondActivityTaskCompletedResponse"\xba\x01\n\'RespondActivityTaskCompletedByIdRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x12\x13\n\x0b\x61\x63tivity_id\x18\x04 \x01(\t\x12\x30\n\x06result\x18\x05 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x10\n\x08identity\x18\x06 \x01(\t"*\n(RespondActivityTaskCompletedByIdResponse"\xa9\x03\n RespondActivityTaskFailedRequest\x12\x12\n\ntask_token\x18\x01 \x01(\x0c\x12\x31\n\x07\x66\x61ilure\x18\x02 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x11\n\tnamespace\x18\x04 \x01(\t\x12@\n\x16last_heartbeat_details\x18\x05 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x46\n\x0eworker_version\x18\x06 \x01(\x0b\x32*.temporal.api.common.v1.WorkerVersionStampB\x02\x18\x01\x12>\n\ndeployment\x18\x07 \x01(\x0b\x32&.temporal.api.deployment.v1.DeploymentB\x02\x18\x01\x12O\n\x12\x64\x65ployment_options\x18\x08 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentOptions"W\n!RespondActivityTaskFailedResponse\x12\x32\n\x08\x66\x61ilures\x18\x01 \x03(\x0b\x32 .temporal.api.failure.v1.Failure"\xfa\x01\n$RespondActivityTaskFailedByIdRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x12\x13\n\x0b\x61\x63tivity_id\x18\x04 \x01(\t\x12\x31\n\x07\x66\x61ilure\x18\x05 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12\x10\n\x08identity\x18\x06 \x01(\t\x12@\n\x16last_heartbeat_details\x18\x07 \x01(\x0b\x32 .temporal.api.common.v1.Payloads"[\n%RespondActivityTaskFailedByIdResponse\x12\x32\n\x08\x66\x61ilures\x18\x01 \x03(\x0b\x32 .temporal.api.failure.v1.Failure"\xe9\x02\n"RespondActivityTaskCanceledRequest\x12\x12\n\ntask_token\x18\x01 \x01(\x0c\x12\x31\n\x07\x64\x65tails\x18\x02 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x11\n\tnamespace\x18\x04 \x01(\t\x12\x46\n\x0eworker_version\x18\x05 \x01(\x0b\x32*.temporal.api.common.v1.WorkerVersionStampB\x02\x18\x01\x12>\n\ndeployment\x18\x06 \x01(\x0b\x32&.temporal.api.deployment.v1.DeploymentB\x02\x18\x01\x12O\n\x12\x64\x65ployment_options\x18\x07 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentOptions"%\n#RespondActivityTaskCanceledResponse"\x8b\x02\n&RespondActivityTaskCanceledByIdRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x12\x13\n\x0b\x61\x63tivity_id\x18\x04 \x01(\t\x12\x31\n\x07\x64\x65tails\x18\x05 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x10\n\x08identity\x18\x06 \x01(\t\x12O\n\x12\x64\x65ployment_options\x18\x07 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentOptions")\n\'RespondActivityTaskCanceledByIdResponse"\x84\x02\n%RequestCancelWorkflowExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x45\n\x12workflow_execution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x12\n\nrequest_id\x18\x04 \x01(\t\x12\x1e\n\x16\x66irst_execution_run_id\x18\x05 \x01(\t\x12\x0e\n\x06reason\x18\x06 \x01(\t\x12+\n\x05links\x18\x07 \x03(\x0b\x32\x1c.temporal.api.common.v1.Link"(\n&RequestCancelWorkflowExecutionResponse"\xde\x02\n\x1eSignalWorkflowExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x45\n\x12workflow_execution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x13\n\x0bsignal_name\x18\x03 \x01(\t\x12/\n\x05input\x18\x04 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x10\n\x08identity\x18\x05 \x01(\t\x12\x12\n\nrequest_id\x18\x06 \x01(\t\x12\x13\n\x07\x63ontrol\x18\x07 \x01(\tB\x02\x18\x01\x12.\n\x06header\x18\x08 \x01(\x0b\x32\x1e.temporal.api.common.v1.Header\x12+\n\x05links\x18\n \x03(\x0b\x32\x1c.temporal.api.common.v1.LinkJ\x04\x08\t\x10\n"!\n\x1fSignalWorkflowExecutionResponse"\xf1\t\n\'SignalWithStartWorkflowExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12;\n\rworkflow_type\x18\x03 \x01(\x0b\x32$.temporal.api.common.v1.WorkflowType\x12\x38\n\ntask_queue\x18\x04 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12/\n\x05input\x18\x05 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12=\n\x1aworkflow_execution_timeout\x18\x06 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x37\n\x14workflow_run_timeout\x18\x07 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x38\n\x15workflow_task_timeout\x18\x08 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x10\n\x08identity\x18\t \x01(\t\x12\x12\n\nrequest_id\x18\n \x01(\t\x12N\n\x18workflow_id_reuse_policy\x18\x0b \x01(\x0e\x32,.temporal.api.enums.v1.WorkflowIdReusePolicy\x12T\n\x1bworkflow_id_conflict_policy\x18\x16 \x01(\x0e\x32/.temporal.api.enums.v1.WorkflowIdConflictPolicy\x12\x13\n\x0bsignal_name\x18\x0c \x01(\t\x12\x36\n\x0csignal_input\x18\r \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x13\n\x07\x63ontrol\x18\x0e \x01(\tB\x02\x18\x01\x12\x39\n\x0cretry_policy\x18\x0f \x01(\x0b\x32#.temporal.api.common.v1.RetryPolicy\x12\x15\n\rcron_schedule\x18\x10 \x01(\t\x12*\n\x04memo\x18\x11 \x01(\x0b\x32\x1c.temporal.api.common.v1.Memo\x12\x43\n\x11search_attributes\x18\x12 \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes\x12.\n\x06header\x18\x13 \x01(\x0b\x32\x1e.temporal.api.common.v1.Header\x12\x37\n\x14workflow_start_delay\x18\x14 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x38\n\ruser_metadata\x18\x17 \x01(\x0b\x32!.temporal.api.sdk.v1.UserMetadata\x12+\n\x05links\x18\x18 \x03(\x0b\x32\x1c.temporal.api.common.v1.Link\x12I\n\x13versioning_override\x18\x19 \x01(\x0b\x32,.temporal.api.workflow.v1.VersioningOverride\x12\x32\n\x08priority\x18\x1a \x01(\x0b\x32 .temporal.api.common.v1.PriorityJ\x04\x08\x15\x10\x16"K\n(SignalWithStartWorkflowExecutionResponse\x12\x0e\n\x06run_id\x18\x01 \x01(\t\x12\x0f\n\x07started\x18\x02 \x01(\x08"\xc1\x03\n\x1dResetWorkflowExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x45\n\x12workflow_execution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x0e\n\x06reason\x18\x03 \x01(\t\x12%\n\x1dworkflow_task_finish_event_id\x18\x04 \x01(\x03\x12\x12\n\nrequest_id\x18\x05 \x01(\t\x12G\n\x12reset_reapply_type\x18\x06 \x01(\x0e\x32\'.temporal.api.enums.v1.ResetReapplyTypeB\x02\x18\x01\x12S\n\x1breset_reapply_exclude_types\x18\x07 \x03(\x0e\x32..temporal.api.enums.v1.ResetReapplyExcludeType\x12K\n\x15post_reset_operations\x18\x08 \x03(\x0b\x32,.temporal.api.workflow.v1.PostResetOperation\x12\x10\n\x08identity\x18\t \x01(\t"0\n\x1eResetWorkflowExecutionResponse\x12\x0e\n\x06run_id\x18\x01 \x01(\t"\x9f\x02\n!TerminateWorkflowExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x45\n\x12workflow_execution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x0e\n\x06reason\x18\x03 \x01(\t\x12\x31\n\x07\x64\x65tails\x18\x04 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x10\n\x08identity\x18\x05 \x01(\t\x12\x1e\n\x16\x66irst_execution_run_id\x18\x06 \x01(\t\x12+\n\x05links\x18\x07 \x03(\x0b\x32\x1c.temporal.api.common.v1.Link"$\n"TerminateWorkflowExecutionResponse"z\n\x1e\x44\x65leteWorkflowExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x45\n\x12workflow_execution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution"!\n\x1f\x44\x65leteWorkflowExecutionResponse"\xc9\x02\n!ListOpenWorkflowExecutionsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x19\n\x11maximum_page_size\x18\x02 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c\x12\x42\n\x11start_time_filter\x18\x04 \x01(\x0b\x32\'.temporal.api.filter.v1.StartTimeFilter\x12K\n\x10\x65xecution_filter\x18\x05 \x01(\x0b\x32/.temporal.api.filter.v1.WorkflowExecutionFilterH\x00\x12\x41\n\x0btype_filter\x18\x06 \x01(\x0b\x32*.temporal.api.filter.v1.WorkflowTypeFilterH\x00\x42\t\n\x07\x66ilters"\x82\x01\n"ListOpenWorkflowExecutionsResponse\x12\x43\n\nexecutions\x18\x01 \x03(\x0b\x32/.temporal.api.workflow.v1.WorkflowExecutionInfo\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c"\x8a\x03\n#ListClosedWorkflowExecutionsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x19\n\x11maximum_page_size\x18\x02 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c\x12\x42\n\x11start_time_filter\x18\x04 \x01(\x0b\x32\'.temporal.api.filter.v1.StartTimeFilter\x12K\n\x10\x65xecution_filter\x18\x05 \x01(\x0b\x32/.temporal.api.filter.v1.WorkflowExecutionFilterH\x00\x12\x41\n\x0btype_filter\x18\x06 \x01(\x0b\x32*.temporal.api.filter.v1.WorkflowTypeFilterH\x00\x12=\n\rstatus_filter\x18\x07 \x01(\x0b\x32$.temporal.api.filter.v1.StatusFilterH\x00\x42\t\n\x07\x66ilters"\x84\x01\n$ListClosedWorkflowExecutionsResponse\x12\x43\n\nexecutions\x18\x01 \x03(\x0b\x32/.temporal.api.workflow.v1.WorkflowExecutionInfo\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c"m\n\x1dListWorkflowExecutionsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x11\n\tpage_size\x18\x02 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c\x12\r\n\x05query\x18\x04 \x01(\t"~\n\x1eListWorkflowExecutionsResponse\x12\x43\n\nexecutions\x18\x01 \x03(\x0b\x32/.temporal.api.workflow.v1.WorkflowExecutionInfo\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c"u\n%ListArchivedWorkflowExecutionsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x11\n\tpage_size\x18\x02 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c\x12\r\n\x05query\x18\x04 \x01(\t"\x86\x01\n&ListArchivedWorkflowExecutionsResponse\x12\x43\n\nexecutions\x18\x01 \x03(\x0b\x32/.temporal.api.workflow.v1.WorkflowExecutionInfo\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c"m\n\x1dScanWorkflowExecutionsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x11\n\tpage_size\x18\x02 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c\x12\r\n\x05query\x18\x04 \x01(\t"~\n\x1eScanWorkflowExecutionsResponse\x12\x43\n\nexecutions\x18\x01 \x03(\x0b\x32/.temporal.api.workflow.v1.WorkflowExecutionInfo\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c"B\n\x1e\x43ountWorkflowExecutionsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\r\n\x05query\x18\x02 \x01(\t"\xed\x01\n\x1f\x43ountWorkflowExecutionsResponse\x12\r\n\x05\x63ount\x18\x01 \x01(\x03\x12\x61\n\x06groups\x18\x02 \x03(\x0b\x32Q.temporal.api.workflowservice.v1.CountWorkflowExecutionsResponse.AggregationGroup\x1aX\n\x10\x41ggregationGroup\x12\x35\n\x0cgroup_values\x18\x01 \x03(\x0b\x32\x1f.temporal.api.common.v1.Payload\x12\r\n\x05\x63ount\x18\x02 \x01(\x03"\x1c\n\x1aGetSearchAttributesRequest"\xc9\x01\n\x1bGetSearchAttributesResponse\x12T\n\x04keys\x18\x01 \x03(\x0b\x32\x46.temporal.api.workflowservice.v1.GetSearchAttributesResponse.KeysEntry\x1aT\n\tKeysEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x36\n\x05value\x18\x02 \x01(\x0e\x32\'.temporal.api.enums.v1.IndexedValueType:\x02\x38\x01"\xd0\x02\n RespondQueryTaskCompletedRequest\x12\x12\n\ntask_token\x18\x01 \x01(\x0c\x12>\n\x0e\x63ompleted_type\x18\x02 \x01(\x0e\x32&.temporal.api.enums.v1.QueryResultType\x12\x36\n\x0cquery_result\x18\x03 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x15\n\rerror_message\x18\x04 \x01(\t\x12\x11\n\tnamespace\x18\x06 \x01(\t\x12\x31\n\x07\x66\x61ilure\x18\x07 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12=\n\x05\x63\x61use\x18\x08 \x01(\x0e\x32..temporal.api.enums.v1.WorkflowTaskFailedCauseJ\x04\x08\x05\x10\x06"#\n!RespondQueryTaskCompletedResponse"n\n\x1bResetStickyTaskQueueRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12<\n\texecution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution"\x1e\n\x1cResetStickyTaskQueueResponse"\x9b\x02\n\x15ShutdownWorkerRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x19\n\x11sticky_task_queue\x18\x02 \x01(\t\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x0e\n\x06reason\x18\x04 \x01(\t\x12\x41\n\x10worker_heartbeat\x18\x05 \x01(\x0b\x32\'.temporal.api.worker.v1.WorkerHeartbeat\x12\x1b\n\x13worker_instance_key\x18\x06 \x01(\t\x12\x12\n\ntask_queue\x18\x07 \x01(\t\x12>\n\x10task_queue_types\x18\x08 \x03(\x0e\x32$.temporal.api.enums.v1.TaskQueueType"\x18\n\x16ShutdownWorkerResponse"\xe9\x01\n\x14QueryWorkflowRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12<\n\texecution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x33\n\x05query\x18\x03 \x01(\x0b\x32$.temporal.api.query.v1.WorkflowQuery\x12K\n\x16query_reject_condition\x18\x04 \x01(\x0e\x32+.temporal.api.enums.v1.QueryRejectCondition"\x8d\x01\n\x15QueryWorkflowResponse\x12\x36\n\x0cquery_result\x18\x01 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12<\n\x0equery_rejected\x18\x02 \x01(\x0b\x32$.temporal.api.query.v1.QueryRejected"s\n DescribeWorkflowExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12<\n\texecution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution"\x99\x05\n!DescribeWorkflowExecutionResponse\x12K\n\x10\x65xecution_config\x18\x01 \x01(\x0b\x32\x31.temporal.api.workflow.v1.WorkflowExecutionConfig\x12P\n\x17workflow_execution_info\x18\x02 \x01(\x0b\x32/.temporal.api.workflow.v1.WorkflowExecutionInfo\x12I\n\x12pending_activities\x18\x03 \x03(\x0b\x32-.temporal.api.workflow.v1.PendingActivityInfo\x12M\n\x10pending_children\x18\x04 \x03(\x0b\x32\x33.temporal.api.workflow.v1.PendingChildExecutionInfo\x12P\n\x15pending_workflow_task\x18\x05 \x01(\x0b\x32\x31.temporal.api.workflow.v1.PendingWorkflowTaskInfo\x12\x39\n\tcallbacks\x18\x06 \x03(\x0b\x32&.temporal.api.workflow.v1.CallbackInfo\x12U\n\x18pending_nexus_operations\x18\x07 \x03(\x0b\x32\x33.temporal.api.workflow.v1.PendingNexusOperationInfo\x12W\n\x16workflow_extended_info\x18\x08 \x01(\x0b\x32\x37.temporal.api.workflow.v1.WorkflowExecutionExtendedInfo"\x90\x04\n\x18\x44\x65scribeTaskQueueRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x38\n\ntask_queue\x18\x02 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12=\n\x0ftask_queue_type\x18\x03 \x01(\x0e\x32$.temporal.api.enums.v1.TaskQueueType\x12\x14\n\x0creport_stats\x18\x08 \x01(\x08\x12\x15\n\rreport_config\x18\x0b \x01(\x08\x12%\n\x19include_task_queue_status\x18\x04 \x01(\x08\x42\x02\x18\x01\x12\x42\n\x08\x61pi_mode\x18\x05 \x01(\x0e\x32,.temporal.api.enums.v1.DescribeTaskQueueModeB\x02\x18\x01\x12J\n\x08versions\x18\x06 \x01(\x0b\x32\x34.temporal.api.taskqueue.v1.TaskQueueVersionSelectionB\x02\x18\x01\x12\x42\n\x10task_queue_types\x18\x07 \x03(\x0e\x32$.temporal.api.enums.v1.TaskQueueTypeB\x02\x18\x01\x12\x1a\n\x0ereport_pollers\x18\t \x01(\x08\x42\x02\x18\x01\x12$\n\x18report_task_reachability\x18\n \x01(\x08\x42\x02\x18\x01"\xec\x07\n\x19\x44\x65scribeTaskQueueResponse\x12\x36\n\x07pollers\x18\x01 \x03(\x0b\x32%.temporal.api.taskqueue.v1.PollerInfo\x12\x38\n\x05stats\x18\x05 \x01(\x0b\x32).temporal.api.taskqueue.v1.TaskQueueStats\x12q\n\x15stats_by_priority_key\x18\x08 \x03(\x0b\x32R.temporal.api.workflowservice.v1.DescribeTaskQueueResponse.StatsByPriorityKeyEntry\x12K\n\x0fversioning_info\x18\x04 \x01(\x0b\x32\x32.temporal.api.taskqueue.v1.TaskQueueVersioningInfo\x12:\n\x06\x63onfig\x18\x06 \x01(\x0b\x32*.temporal.api.taskqueue.v1.TaskQueueConfig\x12k\n\x14\x65\x66\x66\x65\x63tive_rate_limit\x18\x07 \x01(\x0b\x32M.temporal.api.workflowservice.v1.DescribeTaskQueueResponse.EffectiveRateLimit\x12I\n\x11task_queue_status\x18\x02 \x01(\x0b\x32*.temporal.api.taskqueue.v1.TaskQueueStatusB\x02\x18\x01\x12g\n\rversions_info\x18\x03 \x03(\x0b\x32L.temporal.api.workflowservice.v1.DescribeTaskQueueResponse.VersionsInfoEntryB\x02\x18\x01\x1a\x64\n\x17StatsByPriorityKeyEntry\x12\x0b\n\x03key\x18\x01 \x01(\x05\x12\x38\n\x05value\x18\x02 \x01(\x0b\x32).temporal.api.taskqueue.v1.TaskQueueStats:\x02\x38\x01\x1at\n\x12\x45\x66\x66\x65\x63tiveRateLimit\x12\x1b\n\x13requests_per_second\x18\x01 \x01(\x02\x12\x41\n\x11rate_limit_source\x18\x02 \x01(\x0e\x32&.temporal.api.enums.v1.RateLimitSource\x1a\x64\n\x11VersionsInfoEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12>\n\x05value\x18\x02 \x01(\x0b\x32/.temporal.api.taskqueue.v1.TaskQueueVersionInfo:\x02\x38\x01"\x17\n\x15GetClusterInfoRequest"\xd1\x03\n\x16GetClusterInfoResponse\x12h\n\x11supported_clients\x18\x01 \x03(\x0b\x32M.temporal.api.workflowservice.v1.GetClusterInfoResponse.SupportedClientsEntry\x12\x16\n\x0eserver_version\x18\x02 \x01(\t\x12\x12\n\ncluster_id\x18\x03 \x01(\t\x12:\n\x0cversion_info\x18\x04 \x01(\x0b\x32$.temporal.api.version.v1.VersionInfo\x12\x14\n\x0c\x63luster_name\x18\x05 \x01(\t\x12\x1b\n\x13history_shard_count\x18\x06 \x01(\x05\x12\x19\n\x11persistence_store\x18\x07 \x01(\t\x12\x18\n\x10visibility_store\x18\x08 \x01(\t\x12 \n\x18initial_failover_version\x18\t \x01(\x03\x12"\n\x1a\x66\x61ilover_version_increment\x18\n \x01(\x03\x1a\x37\n\x15SupportedClientsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01"\x16\n\x14GetSystemInfoRequest"\xf4\x03\n\x15GetSystemInfoResponse\x12\x16\n\x0eserver_version\x18\x01 \x01(\t\x12Y\n\x0c\x63\x61pabilities\x18\x02 \x01(\x0b\x32\x43.temporal.api.workflowservice.v1.GetSystemInfoResponse.Capabilities\x1a\xe7\x02\n\x0c\x43\x61pabilities\x12\x1f\n\x17signal_and_query_header\x18\x01 \x01(\x08\x12&\n\x1einternal_error_differentiation\x18\x02 \x01(\x08\x12*\n"activity_failure_include_heartbeat\x18\x03 \x01(\x08\x12\x1a\n\x12supports_schedules\x18\x04 \x01(\x08\x12"\n\x1a\x65ncoded_failure_attributes\x18\x05 \x01(\x08\x12!\n\x19\x62uild_id_based_versioning\x18\x06 \x01(\x08\x12\x13\n\x0bupsert_memo\x18\x07 \x01(\x08\x12\x1c\n\x14\x65\x61ger_workflow_start\x18\x08 \x01(\x08\x12\x14\n\x0csdk_metadata\x18\t \x01(\x08\x12\'\n\x1f\x63ount_group_by_execution_status\x18\n \x01(\x08\x12\r\n\x05nexus\x18\x0b \x01(\x08"m\n\x1eListTaskQueuePartitionsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x38\n\ntask_queue\x18\x02 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue"\xdf\x01\n\x1fListTaskQueuePartitionsResponse\x12]\n\x1e\x61\x63tivity_task_queue_partitions\x18\x01 \x03(\x0b\x32\x35.temporal.api.taskqueue.v1.TaskQueuePartitionMetadata\x12]\n\x1eworkflow_task_queue_partitions\x18\x02 \x03(\x0b\x32\x35.temporal.api.taskqueue.v1.TaskQueuePartitionMetadata"\xcc\x02\n\x15\x43reateScheduleRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bschedule_id\x18\x02 \x01(\t\x12\x34\n\x08schedule\x18\x03 \x01(\x0b\x32".temporal.api.schedule.v1.Schedule\x12>\n\rinitial_patch\x18\x04 \x01(\x0b\x32\'.temporal.api.schedule.v1.SchedulePatch\x12\x10\n\x08identity\x18\x05 \x01(\t\x12\x12\n\nrequest_id\x18\x06 \x01(\t\x12*\n\x04memo\x18\x07 \x01(\x0b\x32\x1c.temporal.api.common.v1.Memo\x12\x43\n\x11search_attributes\x18\x08 \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes"0\n\x16\x43reateScheduleResponse\x12\x16\n\x0e\x63onflict_token\x18\x01 \x01(\x0c"A\n\x17\x44\x65scribeScheduleRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bschedule_id\x18\x02 \x01(\t"\x8f\x02\n\x18\x44\x65scribeScheduleResponse\x12\x34\n\x08schedule\x18\x01 \x01(\x0b\x32".temporal.api.schedule.v1.Schedule\x12\x34\n\x04info\x18\x02 \x01(\x0b\x32&.temporal.api.schedule.v1.ScheduleInfo\x12*\n\x04memo\x18\x03 \x01(\x0b\x32\x1c.temporal.api.common.v1.Memo\x12\x43\n\x11search_attributes\x18\x04 \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes\x12\x16\n\x0e\x63onflict_token\x18\x05 \x01(\x0c"\xf8\x01\n\x15UpdateScheduleRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bschedule_id\x18\x02 \x01(\t\x12\x34\n\x08schedule\x18\x03 \x01(\x0b\x32".temporal.api.schedule.v1.Schedule\x12\x16\n\x0e\x63onflict_token\x18\x04 \x01(\x0c\x12\x10\n\x08identity\x18\x05 \x01(\t\x12\x12\n\nrequest_id\x18\x06 \x01(\t\x12\x43\n\x11search_attributes\x18\x07 \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes"\x18\n\x16UpdateScheduleResponse"\x9c\x01\n\x14PatchScheduleRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bschedule_id\x18\x02 \x01(\t\x12\x36\n\x05patch\x18\x03 \x01(\x0b\x32\'.temporal.api.schedule.v1.SchedulePatch\x12\x10\n\x08identity\x18\x04 \x01(\t\x12\x12\n\nrequest_id\x18\x05 \x01(\t"\x17\n\x15PatchScheduleResponse"\xa8\x01\n ListScheduleMatchingTimesRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bschedule_id\x18\x02 \x01(\t\x12.\n\nstart_time\x18\x03 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12,\n\x08\x65nd_time\x18\x04 \x01(\x0b\x32\x1a.google.protobuf.Timestamp"S\n!ListScheduleMatchingTimesResponse\x12.\n\nstart_time\x18\x01 \x03(\x0b\x32\x1a.google.protobuf.Timestamp"Q\n\x15\x44\x65leteScheduleRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bschedule_id\x18\x02 \x01(\t\x12\x10\n\x08identity\x18\x03 \x01(\t"\x18\n\x16\x44\x65leteScheduleResponse"l\n\x14ListSchedulesRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x19\n\x11maximum_page_size\x18\x02 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c\x12\r\n\x05query\x18\x04 \x01(\t"p\n\x15ListSchedulesResponse\x12>\n\tschedules\x18\x01 \x03(\x0b\x32+.temporal.api.schedule.v1.ScheduleListEntry\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c"9\n\x15\x43ountSchedulesRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\r\n\x05query\x18\x02 \x01(\t"\xdb\x01\n\x16\x43ountSchedulesResponse\x12\r\n\x05\x63ount\x18\x01 \x01(\x03\x12X\n\x06groups\x18\x02 \x03(\x0b\x32H.temporal.api.workflowservice.v1.CountSchedulesResponse.AggregationGroup\x1aX\n\x10\x41ggregationGroup\x12\x35\n\x0cgroup_values\x18\x01 \x03(\x0b\x32\x1f.temporal.api.common.v1.Payload\x12\r\n\x05\x63ount\x18\x02 \x01(\x03"\x86\x05\n\'UpdateWorkerBuildIdCompatibilityRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x12\n\ntask_queue\x18\x02 \x01(\t\x12-\n#add_new_build_id_in_new_default_set\x18\x03 \x01(\tH\x00\x12\x87\x01\n\x1b\x61\x64\x64_new_compatible_build_id\x18\x04 \x01(\x0b\x32`.temporal.api.workflowservice.v1.UpdateWorkerBuildIdCompatibilityRequest.AddNewCompatibleVersionH\x00\x12!\n\x17promote_set_by_build_id\x18\x05 \x01(\tH\x00\x12%\n\x1bpromote_build_id_within_set\x18\x06 \x01(\tH\x00\x12h\n\nmerge_sets\x18\x07 \x01(\x0b\x32R.temporal.api.workflowservice.v1.UpdateWorkerBuildIdCompatibilityRequest.MergeSetsH\x00\x1ao\n\x17\x41\x64\x64NewCompatibleVersion\x12\x14\n\x0cnew_build_id\x18\x01 \x01(\t\x12$\n\x1c\x65xisting_compatible_build_id\x18\x02 \x01(\t\x12\x18\n\x10make_set_default\x18\x03 \x01(\x08\x1aI\n\tMergeSets\x12\x1c\n\x14primary_set_build_id\x18\x01 \x01(\t\x12\x1e\n\x16secondary_set_build_id\x18\x02 \x01(\tB\x0b\n\toperation"@\n(UpdateWorkerBuildIdCompatibilityResponseJ\x04\x08\x01\x10\x02R\x0eversion_set_id"_\n$GetWorkerBuildIdCompatibilityRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x12\n\ntask_queue\x18\x02 \x01(\t\x12\x10\n\x08max_sets\x18\x03 \x01(\x05"t\n%GetWorkerBuildIdCompatibilityResponse\x12K\n\x12major_version_sets\x18\x01 \x03(\x0b\x32/.temporal.api.taskqueue.v1.CompatibleVersionSet"\xb5\r\n"UpdateWorkerVersioningRulesRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x12\n\ntask_queue\x18\x02 \x01(\t\x12\x16\n\x0e\x63onflict_token\x18\x03 \x01(\x0c\x12\x81\x01\n\x16insert_assignment_rule\x18\x04 \x01(\x0b\x32_.temporal.api.workflowservice.v1.UpdateWorkerVersioningRulesRequest.InsertBuildIdAssignmentRuleH\x00\x12\x83\x01\n\x17replace_assignment_rule\x18\x05 \x01(\x0b\x32`.temporal.api.workflowservice.v1.UpdateWorkerVersioningRulesRequest.ReplaceBuildIdAssignmentRuleH\x00\x12\x81\x01\n\x16\x64\x65lete_assignment_rule\x18\x06 \x01(\x0b\x32_.temporal.api.workflowservice.v1.UpdateWorkerVersioningRulesRequest.DeleteBuildIdAssignmentRuleH\x00\x12\x8c\x01\n\x1c\x61\x64\x64_compatible_redirect_rule\x18\x07 \x01(\x0b\x32\x64.temporal.api.workflowservice.v1.UpdateWorkerVersioningRulesRequest.AddCompatibleBuildIdRedirectRuleH\x00\x12\x94\x01\n replace_compatible_redirect_rule\x18\x08 \x01(\x0b\x32h.temporal.api.workflowservice.v1.UpdateWorkerVersioningRulesRequest.ReplaceCompatibleBuildIdRedirectRuleH\x00\x12\x92\x01\n\x1f\x64\x65lete_compatible_redirect_rule\x18\t \x01(\x0b\x32g.temporal.api.workflowservice.v1.UpdateWorkerVersioningRulesRequest.DeleteCompatibleBuildIdRedirectRuleH\x00\x12l\n\x0f\x63ommit_build_id\x18\n \x01(\x0b\x32Q.temporal.api.workflowservice.v1.UpdateWorkerVersioningRulesRequest.CommitBuildIdH\x00\x1aq\n\x1bInsertBuildIdAssignmentRule\x12\x12\n\nrule_index\x18\x01 \x01(\x05\x12>\n\x04rule\x18\x02 \x01(\x0b\x32\x30.temporal.api.taskqueue.v1.BuildIdAssignmentRule\x1a\x81\x01\n\x1cReplaceBuildIdAssignmentRule\x12\x12\n\nrule_index\x18\x01 \x01(\x05\x12>\n\x04rule\x18\x02 \x01(\x0b\x32\x30.temporal.api.taskqueue.v1.BuildIdAssignmentRule\x12\r\n\x05\x66orce\x18\x03 \x01(\x08\x1a@\n\x1b\x44\x65leteBuildIdAssignmentRule\x12\x12\n\nrule_index\x18\x01 \x01(\x05\x12\r\n\x05\x66orce\x18\x02 \x01(\x08\x1aj\n AddCompatibleBuildIdRedirectRule\x12\x46\n\x04rule\x18\x01 \x01(\x0b\x32\x38.temporal.api.taskqueue.v1.CompatibleBuildIdRedirectRule\x1an\n$ReplaceCompatibleBuildIdRedirectRule\x12\x46\n\x04rule\x18\x01 \x01(\x0b\x32\x38.temporal.api.taskqueue.v1.CompatibleBuildIdRedirectRule\x1a>\n#DeleteCompatibleBuildIdRedirectRule\x12\x17\n\x0fsource_build_id\x18\x01 \x01(\t\x1a\x37\n\rCommitBuildId\x12\x17\n\x0ftarget_build_id\x18\x01 \x01(\t\x12\r\n\x05\x66orce\x18\x02 \x01(\x08\x42\x0b\n\toperation"\xfc\x01\n#UpdateWorkerVersioningRulesResponse\x12U\n\x10\x61ssignment_rules\x18\x01 \x03(\x0b\x32;.temporal.api.taskqueue.v1.TimestampedBuildIdAssignmentRule\x12\x66\n\x19\x63ompatible_redirect_rules\x18\x02 \x03(\x0b\x32\x43.temporal.api.taskqueue.v1.TimestampedCompatibleBuildIdRedirectRule\x12\x16\n\x0e\x63onflict_token\x18\x03 \x01(\x0c"H\n\x1fGetWorkerVersioningRulesRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x12\n\ntask_queue\x18\x02 \x01(\t"\xf9\x01\n GetWorkerVersioningRulesResponse\x12U\n\x10\x61ssignment_rules\x18\x01 \x03(\x0b\x32;.temporal.api.taskqueue.v1.TimestampedBuildIdAssignmentRule\x12\x66\n\x19\x63ompatible_redirect_rules\x18\x02 \x03(\x0b\x32\x43.temporal.api.taskqueue.v1.TimestampedCompatibleBuildIdRedirectRule\x12\x16\n\x0e\x63onflict_token\x18\x03 \x01(\x0c"\x9c\x01\n GetWorkerTaskReachabilityRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x11\n\tbuild_ids\x18\x02 \x03(\t\x12\x13\n\x0btask_queues\x18\x03 \x03(\t\x12=\n\x0creachability\x18\x04 \x01(\x0e\x32\'.temporal.api.enums.v1.TaskReachability"r\n!GetWorkerTaskReachabilityResponse\x12M\n\x15\x62uild_id_reachability\x18\x01 \x03(\x0b\x32..temporal.api.taskqueue.v1.BuildIdReachability"\x85\x02\n\x1eUpdateWorkflowExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x45\n\x12workflow_execution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x1e\n\x16\x66irst_execution_run_id\x18\x03 \x01(\t\x12\x37\n\x0bwait_policy\x18\x04 \x01(\x0b\x32".temporal.api.update.v1.WaitPolicy\x12\x30\n\x07request\x18\x05 \x01(\x0b\x32\x1f.temporal.api.update.v1.Request"\xd7\x01\n\x1fUpdateWorkflowExecutionResponse\x12\x35\n\nupdate_ref\x18\x01 \x01(\x0b\x32!.temporal.api.update.v1.UpdateRef\x12\x30\n\x07outcome\x18\x02 \x01(\x0b\x32\x1f.temporal.api.update.v1.Outcome\x12K\n\x05stage\x18\x03 \x01(\x0e\x32<.temporal.api.enums.v1.UpdateWorkflowExecutionLifecycleStage"\xf4\x07\n\x1aStartBatchOperationRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x18\n\x10visibility_query\x18\x02 \x01(\t\x12\x0e\n\x06job_id\x18\x03 \x01(\t\x12\x0e\n\x06reason\x18\x04 \x01(\t\x12=\n\nexecutions\x18\x05 \x03(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12!\n\x19max_operations_per_second\x18\x06 \x01(\x02\x12Q\n\x15termination_operation\x18\n \x01(\x0b\x32\x30.temporal.api.batch.v1.BatchOperationTerminationH\x00\x12G\n\x10signal_operation\x18\x0b \x01(\x0b\x32+.temporal.api.batch.v1.BatchOperationSignalH\x00\x12S\n\x16\x63\x61ncellation_operation\x18\x0c \x01(\x0b\x32\x31.temporal.api.batch.v1.BatchOperationCancellationH\x00\x12K\n\x12\x64\x65letion_operation\x18\r \x01(\x0b\x32-.temporal.api.batch.v1.BatchOperationDeletionH\x00\x12\x45\n\x0freset_operation\x18\x0e \x01(\x0b\x32*.temporal.api.batch.v1.BatchOperationResetH\x00\x12p\n!update_workflow_options_operation\x18\x0f \x01(\x0b\x32\x43.temporal.api.batch.v1.BatchOperationUpdateWorkflowExecutionOptionsH\x00\x12^\n\x1cunpause_activities_operation\x18\x10 \x01(\x0b\x32\x36.temporal.api.batch.v1.BatchOperationUnpauseActivitiesH\x00\x12Z\n\x1areset_activities_operation\x18\x11 \x01(\x0b\x32\x34.temporal.api.batch.v1.BatchOperationResetActivitiesH\x00\x12g\n!update_activity_options_operation\x18\x12 \x01(\x0b\x32:.temporal.api.batch.v1.BatchOperationUpdateActivityOptionsH\x00\x42\x0b\n\toperation"\x1d\n\x1bStartBatchOperationResponse"`\n\x19StopBatchOperationRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x0e\n\x06job_id\x18\x02 \x01(\t\x12\x0e\n\x06reason\x18\x03 \x01(\t\x12\x10\n\x08identity\x18\x04 \x01(\t"\x1c\n\x1aStopBatchOperationResponse"B\n\x1d\x44\x65scribeBatchOperationRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x0e\n\x06job_id\x18\x02 \x01(\t"\x92\x03\n\x1e\x44\x65scribeBatchOperationResponse\x12\x41\n\x0eoperation_type\x18\x01 \x01(\x0e\x32).temporal.api.enums.v1.BatchOperationType\x12\x0e\n\x06job_id\x18\x02 \x01(\t\x12\x39\n\x05state\x18\x03 \x01(\x0e\x32*.temporal.api.enums.v1.BatchOperationState\x12.\n\nstart_time\x18\x04 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12.\n\nclose_time\x18\x05 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x1d\n\x15total_operation_count\x18\x06 \x01(\x03\x12 \n\x18\x63omplete_operation_count\x18\x07 \x01(\x03\x12\x1f\n\x17\x66\x61ilure_operation_count\x18\x08 \x01(\x03\x12\x10\n\x08identity\x18\t \x01(\t\x12\x0e\n\x06reason\x18\n \x01(\t"[\n\x1aListBatchOperationsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x11\n\tpage_size\x18\x02 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c"y\n\x1bListBatchOperationsResponse\x12\x41\n\x0eoperation_info\x18\x01 \x03(\x0b\x32).temporal.api.batch.v1.BatchOperationInfo\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c"\xb9\x01\n"PollWorkflowExecutionUpdateRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x35\n\nupdate_ref\x18\x02 \x01(\x0b\x32!.temporal.api.update.v1.UpdateRef\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x37\n\x0bwait_policy\x18\x04 \x01(\x0b\x32".temporal.api.update.v1.WaitPolicy"\xdb\x01\n#PollWorkflowExecutionUpdateResponse\x12\x30\n\x07outcome\x18\x01 \x01(\x0b\x32\x1f.temporal.api.update.v1.Outcome\x12K\n\x05stage\x18\x02 \x01(\x0e\x32<.temporal.api.enums.v1.UpdateWorkflowExecutionLifecycleStage\x12\x35\n\nupdate_ref\x18\x03 \x01(\x0b\x32!.temporal.api.update.v1.UpdateRef"\x87\x03\n\x19PollNexusTaskQueueRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x10\n\x08identity\x18\x02 \x01(\t\x12\x1b\n\x13worker_instance_key\x18\x08 \x01(\t\x12\x38\n\ntask_queue\x18\x03 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12Z\n\x1bworker_version_capabilities\x18\x04 \x01(\x0b\x32\x31.temporal.api.common.v1.WorkerVersionCapabilitiesB\x02\x18\x01\x12O\n\x12\x64\x65ployment_options\x18\x06 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentOptions\x12\x41\n\x10worker_heartbeat\x18\x07 \x03(\x0b\x32\'.temporal.api.worker.v1.WorkerHeartbeat"\xb4\x01\n\x1aPollNexusTaskQueueResponse\x12\x12\n\ntask_token\x18\x01 \x01(\x0c\x12/\n\x07request\x18\x02 \x01(\x0b\x32\x1e.temporal.api.nexus.v1.Request\x12Q\n\x17poller_scaling_decision\x18\x03 \x01(\x0b\x32\x30.temporal.api.taskqueue.v1.PollerScalingDecision"\x8e\x01\n RespondNexusTaskCompletedRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x10\n\x08identity\x18\x02 \x01(\t\x12\x12\n\ntask_token\x18\x03 \x01(\x0c\x12\x31\n\x08response\x18\x04 \x01(\x0b\x32\x1f.temporal.api.nexus.v1.Response"#\n!RespondNexusTaskCompletedResponse"\xc3\x01\n\x1dRespondNexusTaskFailedRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x10\n\x08identity\x18\x02 \x01(\t\x12\x12\n\ntask_token\x18\x03 \x01(\x0c\x12\x36\n\x05\x65rror\x18\x04 \x01(\x0b\x32#.temporal.api.nexus.v1.HandlerErrorB\x02\x18\x01\x12\x31\n\x07\x66\x61ilure\x18\x05 \x01(\x0b\x32 .temporal.api.failure.v1.Failure" \n\x1eRespondNexusTaskFailedResponse"\xdf\x02\n\x1c\x45xecuteMultiOperationRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12[\n\noperations\x18\x02 \x03(\x0b\x32G.temporal.api.workflowservice.v1.ExecuteMultiOperationRequest.Operation\x1a\xce\x01\n\tOperation\x12X\n\x0estart_workflow\x18\x01 \x01(\x0b\x32>.temporal.api.workflowservice.v1.StartWorkflowExecutionRequestH\x00\x12Z\n\x0fupdate_workflow\x18\x02 \x01(\x0b\x32?.temporal.api.workflowservice.v1.UpdateWorkflowExecutionRequestH\x00\x42\x0b\n\toperation"\xcc\x02\n\x1d\x45xecuteMultiOperationResponse\x12Z\n\tresponses\x18\x01 \x03(\x0b\x32G.temporal.api.workflowservice.v1.ExecuteMultiOperationResponse.Response\x1a\xce\x01\n\x08Response\x12Y\n\x0estart_workflow\x18\x01 \x01(\x0b\x32?.temporal.api.workflowservice.v1.StartWorkflowExecutionResponseH\x00\x12[\n\x0fupdate_workflow\x18\x02 \x01(\x0b\x32@.temporal.api.workflowservice.v1.UpdateWorkflowExecutionResponseH\x00\x42\n\n\x08response"\xd0\x02\n\x1cUpdateActivityOptionsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12<\n\texecution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x43\n\x10\x61\x63tivity_options\x18\x04 \x01(\x0b\x32).temporal.api.activity.v1.ActivityOptions\x12/\n\x0bupdate_mask\x18\x05 \x01(\x0b\x32\x1a.google.protobuf.FieldMask\x12\x0c\n\x02id\x18\x06 \x01(\tH\x00\x12\x0e\n\x04type\x18\x07 \x01(\tH\x00\x12\x13\n\tmatch_all\x18\t \x01(\x08H\x00\x12\x18\n\x10restore_original\x18\x08 \x01(\x08\x42\n\n\x08\x61\x63tivity"d\n\x1dUpdateActivityOptionsResponse\x12\x43\n\x10\x61\x63tivity_options\x18\x01 \x01(\x0b\x32).temporal.api.activity.v1.ActivityOptions"\xb3\x01\n\x14PauseActivityRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12<\n\texecution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x0c\n\x02id\x18\x04 \x01(\tH\x00\x12\x0e\n\x04type\x18\x05 \x01(\tH\x00\x12\x0e\n\x06reason\x18\x06 \x01(\tB\n\n\x08\x61\x63tivity"\x17\n\x15PauseActivityResponse"\x98\x02\n\x16UnpauseActivityRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12<\n\texecution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x0c\n\x02id\x18\x04 \x01(\tH\x00\x12\x0e\n\x04type\x18\x05 \x01(\tH\x00\x12\x15\n\x0bunpause_all\x18\x06 \x01(\x08H\x00\x12\x16\n\x0ereset_attempts\x18\x07 \x01(\x08\x12\x17\n\x0freset_heartbeat\x18\x08 \x01(\x08\x12)\n\x06jitter\x18\t \x01(\x0b\x32\x19.google.protobuf.DurationB\n\n\x08\x61\x63tivity"\x19\n\x17UnpauseActivityResponse"\xb3\x02\n\x14ResetActivityRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12<\n\texecution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x0c\n\x02id\x18\x04 \x01(\tH\x00\x12\x0e\n\x04type\x18\x05 \x01(\tH\x00\x12\x13\n\tmatch_all\x18\n \x01(\x08H\x00\x12\x17\n\x0freset_heartbeat\x18\x06 \x01(\x08\x12\x13\n\x0bkeep_paused\x18\x07 \x01(\x08\x12)\n\x06jitter\x18\x08 \x01(\x0b\x32\x19.google.protobuf.Duration\x12 \n\x18restore_original_options\x18\t \x01(\x08\x42\n\n\x08\x61\x63tivity"\x17\n\x15ResetActivityResponse"\x9c\x02\n%UpdateWorkflowExecutionOptionsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x45\n\x12workflow_execution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12V\n\x1aworkflow_execution_options\x18\x03 \x01(\x0b\x32\x32.temporal.api.workflow.v1.WorkflowExecutionOptions\x12/\n\x0bupdate_mask\x18\x04 \x01(\x0b\x32\x1a.google.protobuf.FieldMask\x12\x10\n\x08identity\x18\x05 \x01(\t"\x80\x01\n&UpdateWorkflowExecutionOptionsResponse\x12V\n\x1aworkflow_execution_options\x18\x01 \x01(\x0b\x32\x32.temporal.api.workflow.v1.WorkflowExecutionOptions"j\n\x19\x44\x65scribeDeploymentRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12:\n\ndeployment\x18\x02 \x01(\x0b\x32&.temporal.api.deployment.v1.Deployment"a\n\x1a\x44\x65scribeDeploymentResponse\x12\x43\n\x0f\x64\x65ployment_info\x18\x01 \x01(\x0b\x32*.temporal.api.deployment.v1.DeploymentInfo"\xc2\x01\n&DescribeWorkerDeploymentVersionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x07version\x18\x02 \x01(\tB\x02\x18\x01\x12O\n\x12\x64\x65ployment_version\x18\x03 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersion\x12\x1f\n\x17report_task_queue_stats\x18\x04 \x01(\x08"\x8c\x05\n\'DescribeWorkerDeploymentVersionResponse\x12_\n\x1eworker_deployment_version_info\x18\x01 \x01(\x0b\x32\x37.temporal.api.deployment.v1.WorkerDeploymentVersionInfo\x12v\n\x13version_task_queues\x18\x02 \x03(\x0b\x32Y.temporal.api.workflowservice.v1.DescribeWorkerDeploymentVersionResponse.VersionTaskQueue\x1a\x87\x03\n\x10VersionTaskQueue\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x32\n\x04type\x18\x02 \x01(\x0e\x32$.temporal.api.enums.v1.TaskQueueType\x12\x38\n\x05stats\x18\x03 \x01(\x0b\x32).temporal.api.taskqueue.v1.TaskQueueStats\x12\x90\x01\n\x15stats_by_priority_key\x18\x04 \x03(\x0b\x32q.temporal.api.workflowservice.v1.DescribeWorkerDeploymentVersionResponse.VersionTaskQueue.StatsByPriorityKeyEntry\x1a\x64\n\x17StatsByPriorityKeyEntry\x12\x0b\n\x03key\x18\x01 \x01(\x05\x12\x38\n\x05value\x18\x02 \x01(\x0b\x32).temporal.api.taskqueue.v1.TaskQueueStats:\x02\x38\x01"M\n\x1f\x44\x65scribeWorkerDeploymentRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x17\n\x0f\x64\x65ployment_name\x18\x02 \x01(\t"\x8c\x01\n DescribeWorkerDeploymentResponse\x12\x16\n\x0e\x63onflict_token\x18\x01 \x01(\x0c\x12P\n\x16worker_deployment_info\x18\x02 \x01(\x0b\x32\x30.temporal.api.deployment.v1.WorkerDeploymentInfo"l\n\x16ListDeploymentsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x11\n\tpage_size\x18\x02 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c\x12\x13\n\x0bseries_name\x18\x04 \x01(\t"w\n\x17ListDeploymentsResponse\x12\x17\n\x0fnext_page_token\x18\x01 \x01(\x0c\x12\x43\n\x0b\x64\x65ployments\x18\x02 \x03(\x0b\x32..temporal.api.deployment.v1.DeploymentListInfo"\xcd\x01\n\x1bSetCurrentDeploymentRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12:\n\ndeployment\x18\x02 \x01(\x0b\x32&.temporal.api.deployment.v1.Deployment\x12\x10\n\x08identity\x18\x03 \x01(\t\x12M\n\x0fupdate_metadata\x18\x04 \x01(\x0b\x32\x34.temporal.api.deployment.v1.UpdateDeploymentMetadata"\xb9\x01\n\x1cSetCurrentDeploymentResponse\x12K\n\x17\x63urrent_deployment_info\x18\x01 \x01(\x0b\x32*.temporal.api.deployment.v1.DeploymentInfo\x12L\n\x18previous_deployment_info\x18\x02 \x01(\x0b\x32*.temporal.api.deployment.v1.DeploymentInfo"\xe5\x01\n(SetWorkerDeploymentCurrentVersionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x17\n\x0f\x64\x65ployment_name\x18\x02 \x01(\t\x12\x13\n\x07version\x18\x03 \x01(\tB\x02\x18\x01\x12\x10\n\x08\x62uild_id\x18\x07 \x01(\t\x12\x16\n\x0e\x63onflict_token\x18\x04 \x01(\x0c\x12\x10\n\x08identity\x18\x05 \x01(\t\x12"\n\x1aignore_missing_task_queues\x18\x06 \x01(\x08\x12\x18\n\x10\x61llow_no_pollers\x18\t \x01(\x08"\xbf\x01\n)SetWorkerDeploymentCurrentVersionResponse\x12\x16\n\x0e\x63onflict_token\x18\x01 \x01(\x0c\x12\x1c\n\x10previous_version\x18\x02 \x01(\tB\x02\x18\x01\x12\\\n\x1bprevious_deployment_version\x18\x03 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersionB\x02\x18\x01"\xf9\x01\n(SetWorkerDeploymentRampingVersionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x17\n\x0f\x64\x65ployment_name\x18\x02 \x01(\t\x12\x13\n\x07version\x18\x03 \x01(\tB\x02\x18\x01\x12\x10\n\x08\x62uild_id\x18\x08 \x01(\t\x12\x12\n\npercentage\x18\x04 \x01(\x02\x12\x16\n\x0e\x63onflict_token\x18\x05 \x01(\x0c\x12\x10\n\x08identity\x18\x06 \x01(\t\x12"\n\x1aignore_missing_task_queues\x18\x07 \x01(\x08\x12\x18\n\x10\x61llow_no_pollers\x18\n \x01(\x08"\xe0\x01\n)SetWorkerDeploymentRampingVersionResponse\x12\x16\n\x0e\x63onflict_token\x18\x01 \x01(\x0c\x12\x1c\n\x10previous_version\x18\x02 \x01(\tB\x02\x18\x01\x12\\\n\x1bprevious_deployment_version\x18\x04 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersionB\x02\x18\x01\x12\x1f\n\x13previous_percentage\x18\x03 \x01(\x02\x42\x02\x18\x01"]\n\x1cListWorkerDeploymentsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x11\n\tpage_size\x18\x02 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c"\x9f\x05\n\x1dListWorkerDeploymentsResponse\x12\x17\n\x0fnext_page_token\x18\x01 \x01(\x0c\x12r\n\x12worker_deployments\x18\x02 \x03(\x0b\x32V.temporal.api.workflowservice.v1.ListWorkerDeploymentsResponse.WorkerDeploymentSummary\x1a\xf0\x03\n\x17WorkerDeploymentSummary\x12\x0c\n\x04name\x18\x01 \x01(\t\x12/\n\x0b\x63reate_time\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x41\n\x0erouting_config\x18\x03 \x01(\x0b\x32).temporal.api.deployment.v1.RoutingConfig\x12o\n\x16latest_version_summary\x18\x04 \x01(\x0b\x32O.temporal.api.deployment.v1.WorkerDeploymentInfo.WorkerDeploymentVersionSummary\x12p\n\x17\x63urrent_version_summary\x18\x05 \x01(\x0b\x32O.temporal.api.deployment.v1.WorkerDeploymentInfo.WorkerDeploymentVersionSummary\x12p\n\x17ramping_version_summary\x18\x06 \x01(\x0b\x32O.temporal.api.deployment.v1.WorkerDeploymentInfo.WorkerDeploymentVersionSummary"\xc8\x01\n$DeleteWorkerDeploymentVersionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x07version\x18\x02 \x01(\tB\x02\x18\x01\x12O\n\x12\x64\x65ployment_version\x18\x05 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersion\x12\x15\n\rskip_drainage\x18\x03 \x01(\x08\x12\x10\n\x08identity\x18\x04 \x01(\t"\'\n%DeleteWorkerDeploymentVersionResponse"]\n\x1d\x44\x65leteWorkerDeploymentRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x17\n\x0f\x64\x65ployment_name\x18\x02 \x01(\t\x12\x10\n\x08identity\x18\x03 \x01(\t" \n\x1e\x44\x65leteWorkerDeploymentResponse"\xa2\x03\n,UpdateWorkerDeploymentVersionMetadataRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x07version\x18\x02 \x01(\tB\x02\x18\x01\x12O\n\x12\x64\x65ployment_version\x18\x05 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersion\x12x\n\x0eupsert_entries\x18\x03 \x03(\x0b\x32`.temporal.api.workflowservice.v1.UpdateWorkerDeploymentVersionMetadataRequest.UpsertEntriesEntry\x12\x16\n\x0eremove_entries\x18\x04 \x03(\t\x12\x10\n\x08identity\x18\x06 \x01(\t\x1aU\n\x12UpsertEntriesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12.\n\x05value\x18\x02 \x01(\x0b\x32\x1f.temporal.api.common.v1.Payload:\x02\x38\x01"n\n-UpdateWorkerDeploymentVersionMetadataResponse\x12=\n\x08metadata\x18\x01 \x01(\x0b\x32+.temporal.api.deployment.v1.VersionMetadata"\xbd\x01\n!SetWorkerDeploymentManagerRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x17\n\x0f\x64\x65ployment_name\x18\x02 \x01(\t\x12\x1a\n\x10manager_identity\x18\x03 \x01(\tH\x00\x12\x0e\n\x04self\x18\x04 \x01(\x08H\x00\x12\x16\n\x0e\x63onflict_token\x18\x05 \x01(\x0c\x12\x10\n\x08identity\x18\x06 \x01(\tB\x16\n\x14new_manager_identity"c\n"SetWorkerDeploymentManagerResponse\x12\x16\n\x0e\x63onflict_token\x18\x01 \x01(\x0c\x12%\n\x19previous_manager_identity\x18\x02 \x01(\tB\x02\x18\x01"E\n\x1bGetCurrentDeploymentRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bseries_name\x18\x02 \x01(\t"k\n\x1cGetCurrentDeploymentResponse\x12K\n\x17\x63urrent_deployment_info\x18\x01 \x01(\x0b\x32*.temporal.api.deployment.v1.DeploymentInfo"q\n GetDeploymentReachabilityRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12:\n\ndeployment\x18\x02 \x01(\x0b\x32&.temporal.api.deployment.v1.Deployment"\xe3\x01\n!GetDeploymentReachabilityResponse\x12\x43\n\x0f\x64\x65ployment_info\x18\x01 \x01(\x0b\x32*.temporal.api.deployment.v1.DeploymentInfo\x12\x43\n\x0creachability\x18\x02 \x01(\x0e\x32-.temporal.api.enums.v1.DeploymentReachability\x12\x34\n\x10last_update_time\x18\x03 \x01(\x0b\x32\x1a.google.protobuf.Timestamp"\xb4\x01\n\x19\x43reateWorkflowRuleRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x35\n\x04spec\x18\x02 \x01(\x0b\x32\'.temporal.api.rules.v1.WorkflowRuleSpec\x12\x12\n\nforce_scan\x18\x03 \x01(\x08\x12\x12\n\nrequest_id\x18\x04 \x01(\t\x12\x10\n\x08identity\x18\x05 \x01(\t\x12\x13\n\x0b\x64\x65scription\x18\x06 \x01(\t"_\n\x1a\x43reateWorkflowRuleResponse\x12\x31\n\x04rule\x18\x01 \x01(\x0b\x32#.temporal.api.rules.v1.WorkflowRule\x12\x0e\n\x06job_id\x18\x02 \x01(\t"A\n\x1b\x44\x65scribeWorkflowRuleRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x0f\n\x07rule_id\x18\x02 \x01(\t"Q\n\x1c\x44\x65scribeWorkflowRuleResponse\x12\x31\n\x04rule\x18\x01 \x01(\x0b\x32#.temporal.api.rules.v1.WorkflowRule"?\n\x19\x44\x65leteWorkflowRuleRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x0f\n\x07rule_id\x18\x02 \x01(\t"\x1c\n\x1a\x44\x65leteWorkflowRuleResponse"F\n\x18ListWorkflowRulesRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c"h\n\x19ListWorkflowRulesResponse\x12\x32\n\x05rules\x18\x01 \x03(\x0b\x32#.temporal.api.rules.v1.WorkflowRule\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c"\xce\x01\n\x1aTriggerWorkflowRuleRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12<\n\texecution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x0c\n\x02id\x18\x04 \x01(\tH\x00\x12\x37\n\x04spec\x18\x05 \x01(\x0b\x32\'.temporal.api.rules.v1.WorkflowRuleSpecH\x00\x12\x10\n\x08identity\x18\x03 \x01(\tB\x06\n\x04rule".\n\x1bTriggerWorkflowRuleResponse\x12\x0f\n\x07\x61pplied\x18\x01 \x01(\x08"\x86\x01\n\x1cRecordWorkerHeartbeatRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x10\n\x08identity\x18\x02 \x01(\t\x12\x41\n\x10worker_heartbeat\x18\x03 \x03(\x0b\x32\'.temporal.api.worker.v1.WorkerHeartbeat"\x1f\n\x1dRecordWorkerHeartbeatResponse"b\n\x12ListWorkersRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x11\n\tpage_size\x18\x02 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c\x12\r\n\x05query\x18\x04 \x01(\t"h\n\x13ListWorkersResponse\x12\x38\n\x0cworkers_info\x18\x01 \x03(\x0b\x32".temporal.api.worker.v1.WorkerInfo\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c"\xd5\x05\n\x1cUpdateTaskQueueConfigRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x10\n\x08identity\x18\x02 \x01(\t\x12\x12\n\ntask_queue\x18\x03 \x01(\t\x12=\n\x0ftask_queue_type\x18\x04 \x01(\x0e\x32$.temporal.api.enums.v1.TaskQueueType\x12n\n\x17update_queue_rate_limit\x18\x05 \x01(\x0b\x32M.temporal.api.workflowservice.v1.UpdateTaskQueueConfigRequest.RateLimitUpdate\x12}\n&update_fairness_key_rate_limit_default\x18\x06 \x01(\x0b\x32M.temporal.api.workflowservice.v1.UpdateTaskQueueConfigRequest.RateLimitUpdate\x12\x84\x01\n\x1dset_fairness_weight_overrides\x18\x07 \x03(\x0b\x32].temporal.api.workflowservice.v1.UpdateTaskQueueConfigRequest.SetFairnessWeightOverridesEntry\x12\'\n\x1funset_fairness_weight_overrides\x18\x08 \x03(\t\x1a[\n\x0fRateLimitUpdate\x12\x38\n\nrate_limit\x18\x01 \x01(\x0b\x32$.temporal.api.taskqueue.v1.RateLimit\x12\x0e\n\x06reason\x18\x02 \x01(\t\x1a\x41\n\x1fSetFairnessWeightOverridesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\x02:\x02\x38\x01"[\n\x1dUpdateTaskQueueConfigResponse\x12:\n\x06\x63onfig\x18\x01 \x01(\x0b\x32*.temporal.api.taskqueue.v1.TaskQueueConfig"\x89\x01\n\x18\x46\x65tchWorkerConfigRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x10\n\x08identity\x18\x02 \x01(\t\x12\x0e\n\x06reason\x18\x03 \x01(\t\x12\x38\n\x08selector\x18\x06 \x01(\x0b\x32&.temporal.api.common.v1.WorkerSelector"U\n\x19\x46\x65tchWorkerConfigResponse\x12\x38\n\rworker_config\x18\x01 \x01(\x0b\x32!.temporal.api.sdk.v1.WorkerConfig"\xf5\x01\n\x19UpdateWorkerConfigRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x10\n\x08identity\x18\x02 \x01(\t\x12\x0e\n\x06reason\x18\x03 \x01(\t\x12\x38\n\rworker_config\x18\x04 \x01(\x0b\x32!.temporal.api.sdk.v1.WorkerConfig\x12/\n\x0bupdate_mask\x18\x05 \x01(\x0b\x32\x1a.google.protobuf.FieldMask\x12\x38\n\x08selector\x18\x06 \x01(\x0b\x32&.temporal.api.common.v1.WorkerSelector"d\n\x1aUpdateWorkerConfigResponse\x12:\n\rworker_config\x18\x01 \x01(\x0b\x32!.temporal.api.sdk.v1.WorkerConfigH\x00\x42\n\n\x08response"G\n\x15\x44\x65scribeWorkerRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x1b\n\x13worker_instance_key\x18\x02 \x01(\t"Q\n\x16\x44\x65scribeWorkerResponse\x12\x37\n\x0bworker_info\x18\x01 \x01(\x0b\x32".temporal.api.worker.v1.WorkerInfo"\x8d\x01\n\x1dPauseWorkflowExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x12\x10\n\x08identity\x18\x04 \x01(\t\x12\x0e\n\x06reason\x18\x05 \x01(\t\x12\x12\n\nrequest_id\x18\x06 \x01(\t" \n\x1ePauseWorkflowExecutionResponse"\x8f\x01\n\x1fUnpauseWorkflowExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x12\x10\n\x08identity\x18\x04 \x01(\t\x12\x0e\n\x06reason\x18\x05 \x01(\t\x12\x12\n\nrequest_id\x18\x06 \x01(\t""\n UnpauseWorkflowExecutionResponse"\xb4\x07\n\x1dStartActivityExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x10\n\x08identity\x18\x02 \x01(\t\x12\x12\n\nrequest_id\x18\x03 \x01(\t\x12\x13\n\x0b\x61\x63tivity_id\x18\x04 \x01(\t\x12;\n\ractivity_type\x18\x05 \x01(\x0b\x32$.temporal.api.common.v1.ActivityType\x12\x38\n\ntask_queue\x18\x06 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12<\n\x19schedule_to_close_timeout\x18\x07 \x01(\x0b\x32\x19.google.protobuf.Duration\x12<\n\x19schedule_to_start_timeout\x18\x08 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x39\n\x16start_to_close_timeout\x18\t \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x34\n\x11heartbeat_timeout\x18\n \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x39\n\x0cretry_policy\x18\x0b \x01(\x0b\x32#.temporal.api.common.v1.RetryPolicy\x12/\n\x05input\x18\x0c \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x45\n\x0fid_reuse_policy\x18\r \x01(\x0e\x32,.temporal.api.enums.v1.ActivityIdReusePolicy\x12K\n\x12id_conflict_policy\x18\x0e \x01(\x0e\x32/.temporal.api.enums.v1.ActivityIdConflictPolicy\x12\x43\n\x11search_attributes\x18\x0f \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes\x12.\n\x06header\x18\x10 \x01(\x0b\x32\x1e.temporal.api.common.v1.Header\x12\x38\n\ruser_metadata\x18\x11 \x01(\x0b\x32!.temporal.api.sdk.v1.UserMetadata\x12\x32\n\x08priority\x18\x12 \x01(\x0b\x32 .temporal.api.common.v1.Priority"A\n\x1eStartActivityExecutionResponse\x12\x0e\n\x06run_id\x18\x01 \x01(\t\x12\x0f\n\x07started\x18\x02 \x01(\x08"\xa3\x01\n DescribeActivityExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0b\x61\x63tivity_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x12\x15\n\rinclude_input\x18\x04 \x01(\x08\x12\x17\n\x0finclude_outcome\x18\x05 \x01(\x08\x12\x17\n\x0flong_poll_token\x18\x06 \x01(\x0c"\x81\x02\n!DescribeActivityExecutionResponse\x12\x0e\n\x06run_id\x18\x01 \x01(\t\x12=\n\x04info\x18\x02 \x01(\x0b\x32/.temporal.api.activity.v1.ActivityExecutionInfo\x12/\n\x05input\x18\x03 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x43\n\x07outcome\x18\x04 \x01(\x0b\x32\x32.temporal.api.activity.v1.ActivityExecutionOutcome\x12\x17\n\x0flong_poll_token\x18\x05 \x01(\x0c"V\n\x1cPollActivityExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0b\x61\x63tivity_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t"t\n\x1dPollActivityExecutionResponse\x12\x0e\n\x06run_id\x18\x01 \x01(\t\x12\x43\n\x07outcome\x18\x02 \x01(\x0b\x32\x32.temporal.api.activity.v1.ActivityExecutionOutcome"m\n\x1dListActivityExecutionsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x11\n\tpage_size\x18\x02 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c\x12\r\n\x05query\x18\x04 \x01(\t"\x82\x01\n\x1eListActivityExecutionsResponse\x12G\n\nexecutions\x18\x01 \x03(\x0b\x32\x33.temporal.api.activity.v1.ActivityExecutionListInfo\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c"B\n\x1e\x43ountActivityExecutionsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\r\n\x05query\x18\x02 \x01(\t"\xed\x01\n\x1f\x43ountActivityExecutionsResponse\x12\r\n\x05\x63ount\x18\x01 \x01(\x03\x12\x61\n\x06groups\x18\x02 \x03(\x0b\x32Q.temporal.api.workflowservice.v1.CountActivityExecutionsResponse.AggregationGroup\x1aX\n\x10\x41ggregationGroup\x12\x35\n\x0cgroup_values\x18\x01 \x03(\x0b\x32\x1f.temporal.api.common.v1.Payload\x12\r\n\x05\x63ount\x18\x02 \x01(\x03"\x95\x01\n%RequestCancelActivityExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0b\x61\x63tivity_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x12\x10\n\x08identity\x18\x04 \x01(\t\x12\x12\n\nrequest_id\x18\x05 \x01(\t\x12\x0e\n\x06reason\x18\x06 \x01(\t"(\n&RequestCancelActivityExecutionResponse"\x91\x01\n!TerminateActivityExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0b\x61\x63tivity_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x12\x10\n\x08identity\x18\x04 \x01(\t\x12\x12\n\nrequest_id\x18\x05 \x01(\t\x12\x0e\n\x06reason\x18\x06 \x01(\t"$\n"TerminateActivityExecutionResponse"X\n\x1e\x44\x65leteActivityExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0b\x61\x63tivity_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t"!\n\x1f\x44\x65leteActivityExecutionResponseB\xbe\x01\n"io.temporal.api.workflowservice.v1B\x14RequestResponseProtoP\x01Z5go.temporal.io/api/workflowservice/v1;workflowservice\xaa\x02!Temporalio.Api.WorkflowService.V1\xea\x02$Temporalio::Api::WorkflowService::V1b\x06proto3' + b'\n6temporal/api/workflowservice/v1/request_response.proto\x12\x1ftemporal.api.workflowservice.v1\x1a+temporal/api/enums/v1/batch_operation.proto\x1a"temporal/api/enums/v1/common.proto\x1a$temporal/api/enums/v1/workflow.proto\x1a%temporal/api/enums/v1/namespace.proto\x1a(temporal/api/enums/v1/failed_cause.proto\x1a!temporal/api/enums/v1/query.proto\x1a!temporal/api/enums/v1/reset.proto\x1a&temporal/api/enums/v1/task_queue.proto\x1a&temporal/api/enums/v1/deployment.proto\x1a"temporal/api/enums/v1/update.proto\x1a$temporal/api/enums/v1/activity.proto\x1a&temporal/api/activity/v1/message.proto\x1a$temporal/api/common/v1/message.proto\x1a%temporal/api/history/v1/message.proto\x1a&temporal/api/workflow/v1/message.proto\x1a%temporal/api/command/v1/message.proto\x1a(temporal/api/deployment/v1/message.proto\x1a%temporal/api/failure/v1/message.proto\x1a$temporal/api/filter/v1/message.proto\x1a&temporal/api/protocol/v1/message.proto\x1a\'temporal/api/namespace/v1/message.proto\x1a#temporal/api/query/v1/message.proto\x1a)temporal/api/replication/v1/message.proto\x1a#temporal/api/rules/v1/message.proto\x1a\'temporal/api/sdk/v1/worker_config.proto\x1a&temporal/api/schedule/v1/message.proto\x1a\'temporal/api/taskqueue/v1/message.proto\x1a$temporal/api/update/v1/message.proto\x1a%temporal/api/version/v1/message.proto\x1a#temporal/api/batch/v1/message.proto\x1a\x30temporal/api/sdk/v1/task_complete_metadata.proto\x1a\'temporal/api/sdk/v1/user_metadata.proto\x1a#temporal/api/nexus/v1/message.proto\x1a$temporal/api/worker/v1/message.proto\x1a\x1egoogle/protobuf/duration.proto\x1a google/protobuf/field_mask.proto\x1a\x1fgoogle/protobuf/timestamp.proto"\x88\x05\n\x18RegisterNamespaceRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0b\x64\x65scription\x18\x02 \x01(\t\x12\x13\n\x0bowner_email\x18\x03 \x01(\t\x12\x46\n#workflow_execution_retention_period\x18\x04 \x01(\x0b\x32\x19.google.protobuf.Duration\x12G\n\x08\x63lusters\x18\x05 \x03(\x0b\x32\x35.temporal.api.replication.v1.ClusterReplicationConfig\x12\x1b\n\x13\x61\x63tive_cluster_name\x18\x06 \x01(\t\x12Q\n\x04\x64\x61ta\x18\x07 \x03(\x0b\x32\x43.temporal.api.workflowservice.v1.RegisterNamespaceRequest.DataEntry\x12\x16\n\x0esecurity_token\x18\x08 \x01(\t\x12\x1b\n\x13is_global_namespace\x18\t \x01(\x08\x12\x44\n\x16history_archival_state\x18\n \x01(\x0e\x32$.temporal.api.enums.v1.ArchivalState\x12\x1c\n\x14history_archival_uri\x18\x0b \x01(\t\x12G\n\x19visibility_archival_state\x18\x0c \x01(\x0e\x32$.temporal.api.enums.v1.ArchivalState\x12\x1f\n\x17visibility_archival_uri\x18\r \x01(\t\x1a+\n\tDataEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01"\x1b\n\x19RegisterNamespaceResponse"\x89\x01\n\x15ListNamespacesRequest\x12\x11\n\tpage_size\x18\x01 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c\x12\x44\n\x10namespace_filter\x18\x03 \x01(\x0b\x32*.temporal.api.namespace.v1.NamespaceFilter"\x81\x01\n\x16ListNamespacesResponse\x12N\n\nnamespaces\x18\x01 \x03(\x0b\x32:.temporal.api.workflowservice.v1.DescribeNamespaceResponse\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c"9\n\x18\x44\x65scribeNamespaceRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\n\n\x02id\x18\x02 \x01(\t"\xec\x02\n\x19\x44\x65scribeNamespaceResponse\x12@\n\x0enamespace_info\x18\x01 \x01(\x0b\x32(.temporal.api.namespace.v1.NamespaceInfo\x12:\n\x06\x63onfig\x18\x02 \x01(\x0b\x32*.temporal.api.namespace.v1.NamespaceConfig\x12S\n\x12replication_config\x18\x03 \x01(\x0b\x32\x37.temporal.api.replication.v1.NamespaceReplicationConfig\x12\x18\n\x10\x66\x61ilover_version\x18\x04 \x01(\x03\x12\x1b\n\x13is_global_namespace\x18\x05 \x01(\x08\x12\x45\n\x10\x66\x61ilover_history\x18\x06 \x03(\x0b\x32+.temporal.api.replication.v1.FailoverStatus"\xcf\x02\n\x16UpdateNamespaceRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x43\n\x0bupdate_info\x18\x02 \x01(\x0b\x32..temporal.api.namespace.v1.UpdateNamespaceInfo\x12:\n\x06\x63onfig\x18\x03 \x01(\x0b\x32*.temporal.api.namespace.v1.NamespaceConfig\x12S\n\x12replication_config\x18\x04 \x01(\x0b\x32\x37.temporal.api.replication.v1.NamespaceReplicationConfig\x12\x16\n\x0esecurity_token\x18\x05 \x01(\t\x12\x19\n\x11\x64\x65lete_bad_binary\x18\x06 \x01(\t\x12\x19\n\x11promote_namespace\x18\x07 \x01(\x08"\xa3\x02\n\x17UpdateNamespaceResponse\x12@\n\x0enamespace_info\x18\x01 \x01(\x0b\x32(.temporal.api.namespace.v1.NamespaceInfo\x12:\n\x06\x63onfig\x18\x02 \x01(\x0b\x32*.temporal.api.namespace.v1.NamespaceConfig\x12S\n\x12replication_config\x18\x03 \x01(\x0b\x32\x37.temporal.api.replication.v1.NamespaceReplicationConfig\x12\x18\n\x10\x66\x61ilover_version\x18\x04 \x01(\x03\x12\x1b\n\x13is_global_namespace\x18\x05 \x01(\x08"F\n\x19\x44\x65precateNamespaceRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x16\n\x0esecurity_token\x18\x02 \x01(\t"\x1c\n\x1a\x44\x65precateNamespaceResponse"\x87\x0c\n\x1dStartWorkflowExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12;\n\rworkflow_type\x18\x03 \x01(\x0b\x32$.temporal.api.common.v1.WorkflowType\x12\x38\n\ntask_queue\x18\x04 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12/\n\x05input\x18\x05 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12=\n\x1aworkflow_execution_timeout\x18\x06 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x37\n\x14workflow_run_timeout\x18\x07 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x38\n\x15workflow_task_timeout\x18\x08 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x10\n\x08identity\x18\t \x01(\t\x12\x12\n\nrequest_id\x18\n \x01(\t\x12N\n\x18workflow_id_reuse_policy\x18\x0b \x01(\x0e\x32,.temporal.api.enums.v1.WorkflowIdReusePolicy\x12T\n\x1bworkflow_id_conflict_policy\x18\x16 \x01(\x0e\x32/.temporal.api.enums.v1.WorkflowIdConflictPolicy\x12\x39\n\x0cretry_policy\x18\x0c \x01(\x0b\x32#.temporal.api.common.v1.RetryPolicy\x12\x15\n\rcron_schedule\x18\r \x01(\t\x12*\n\x04memo\x18\x0e \x01(\x0b\x32\x1c.temporal.api.common.v1.Memo\x12\x43\n\x11search_attributes\x18\x0f \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes\x12.\n\x06header\x18\x10 \x01(\x0b\x32\x1e.temporal.api.common.v1.Header\x12\x1f\n\x17request_eager_execution\x18\x11 \x01(\x08\x12;\n\x11\x63ontinued_failure\x18\x12 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12@\n\x16last_completion_result\x18\x13 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x37\n\x14workflow_start_delay\x18\x14 \x01(\x0b\x32\x19.google.protobuf.Duration\x12>\n\x14\x63ompletion_callbacks\x18\x15 \x03(\x0b\x32 .temporal.api.common.v1.Callback\x12\x38\n\ruser_metadata\x18\x17 \x01(\x0b\x32!.temporal.api.sdk.v1.UserMetadata\x12+\n\x05links\x18\x18 \x03(\x0b\x32\x1c.temporal.api.common.v1.Link\x12I\n\x13versioning_override\x18\x19 \x01(\x0b\x32,.temporal.api.workflow.v1.VersioningOverride\x12H\n\x13on_conflict_options\x18\x1a \x01(\x0b\x32+.temporal.api.workflow.v1.OnConflictOptions\x12\x32\n\x08priority\x18\x1b \x01(\x0b\x32 .temporal.api.common.v1.Priority\x12\\\n\x1f\x65\x61ger_worker_deployment_options\x18\x1c \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentOptions"\x8a\x02\n\x1eStartWorkflowExecutionResponse\x12\x0e\n\x06run_id\x18\x01 \x01(\t\x12\x0f\n\x07started\x18\x03 \x01(\x08\x12>\n\x06status\x18\x05 \x01(\x0e\x32..temporal.api.enums.v1.WorkflowExecutionStatus\x12[\n\x13\x65\x61ger_workflow_task\x18\x02 \x01(\x0b\x32>.temporal.api.workflowservice.v1.PollWorkflowTaskQueueResponse\x12*\n\x04link\x18\x04 \x01(\x0b\x32\x1c.temporal.api.common.v1.Link"\xaa\x02\n"GetWorkflowExecutionHistoryRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12<\n\texecution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x19\n\x11maximum_page_size\x18\x03 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x04 \x01(\x0c\x12\x16\n\x0ewait_new_event\x18\x05 \x01(\x08\x12P\n\x19history_event_filter_type\x18\x06 \x01(\x0e\x32-.temporal.api.enums.v1.HistoryEventFilterType\x12\x15\n\rskip_archival\x18\x07 \x01(\x08"\xba\x01\n#GetWorkflowExecutionHistoryResponse\x12\x31\n\x07history\x18\x01 \x01(\x0b\x32 .temporal.api.history.v1.History\x12\x35\n\x0braw_history\x18\x02 \x03(\x0b\x32 .temporal.api.common.v1.DataBlob\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c\x12\x10\n\x08\x61rchived\x18\x04 \x01(\x08"\xb0\x01\n)GetWorkflowExecutionHistoryReverseRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12<\n\texecution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x19\n\x11maximum_page_size\x18\x03 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x04 \x01(\x0c"x\n*GetWorkflowExecutionHistoryReverseResponse\x12\x31\n\x07history\x18\x01 \x01(\x0b\x32 .temporal.api.history.v1.History\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c"\xfc\x02\n\x1cPollWorkflowTaskQueueRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x38\n\ntask_queue\x18\x02 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x1b\n\x13worker_instance_key\x18\x08 \x01(\t\x12\x1b\n\x0f\x62inary_checksum\x18\x04 \x01(\tB\x02\x18\x01\x12Z\n\x1bworker_version_capabilities\x18\x05 \x01(\x0b\x32\x31.temporal.api.common.v1.WorkerVersionCapabilitiesB\x02\x18\x01\x12O\n\x12\x64\x65ployment_options\x18\x06 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentOptionsJ\x04\x08\x07\x10\x08R\x10worker_heartbeat"\x91\x07\n\x1dPollWorkflowTaskQueueResponse\x12\x12\n\ntask_token\x18\x01 \x01(\x0c\x12\x45\n\x12workflow_execution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12;\n\rworkflow_type\x18\x03 \x01(\x0b\x32$.temporal.api.common.v1.WorkflowType\x12!\n\x19previous_started_event_id\x18\x04 \x01(\x03\x12\x18\n\x10started_event_id\x18\x05 \x01(\x03\x12\x0f\n\x07\x61ttempt\x18\x06 \x01(\x05\x12\x1a\n\x12\x62\x61\x63klog_count_hint\x18\x07 \x01(\x03\x12\x31\n\x07history\x18\x08 \x01(\x0b\x32 .temporal.api.history.v1.History\x12\x17\n\x0fnext_page_token\x18\t \x01(\x0c\x12\x33\n\x05query\x18\n \x01(\x0b\x32$.temporal.api.query.v1.WorkflowQuery\x12K\n\x1dworkflow_execution_task_queue\x18\x0b \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12\x32\n\x0escheduled_time\x18\x0c \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x30\n\x0cstarted_time\x18\r \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\\\n\x07queries\x18\x0e \x03(\x0b\x32K.temporal.api.workflowservice.v1.PollWorkflowTaskQueueResponse.QueriesEntry\x12\x33\n\x08messages\x18\x0f \x03(\x0b\x32!.temporal.api.protocol.v1.Message\x12Q\n\x17poller_scaling_decision\x18\x10 \x01(\x0b\x32\x30.temporal.api.taskqueue.v1.PollerScalingDecision\x1aT\n\x0cQueriesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x33\n\x05value\x18\x02 \x01(\x0b\x32$.temporal.api.query.v1.WorkflowQuery:\x02\x38\x01"\xb5\t\n#RespondWorkflowTaskCompletedRequest\x12\x12\n\ntask_token\x18\x01 \x01(\x0c\x12\x32\n\x08\x63ommands\x18\x02 \x03(\x0b\x32 .temporal.api.command.v1.Command\x12\x10\n\x08identity\x18\x03 \x01(\t\x12O\n\x11sticky_attributes\x18\x04 \x01(\x0b\x32\x34.temporal.api.taskqueue.v1.StickyExecutionAttributes\x12 \n\x18return_new_workflow_task\x18\x05 \x01(\x08\x12&\n\x1e\x66orce_create_new_workflow_task\x18\x06 \x01(\x08\x12\x1b\n\x0f\x62inary_checksum\x18\x07 \x01(\tB\x02\x18\x01\x12m\n\rquery_results\x18\x08 \x03(\x0b\x32V.temporal.api.workflowservice.v1.RespondWorkflowTaskCompletedRequest.QueryResultsEntry\x12\x11\n\tnamespace\x18\t \x01(\t\x12L\n\x14worker_version_stamp\x18\n \x01(\x0b\x32*.temporal.api.common.v1.WorkerVersionStampB\x02\x18\x01\x12\x33\n\x08messages\x18\x0b \x03(\x0b\x32!.temporal.api.protocol.v1.Message\x12H\n\x0csdk_metadata\x18\x0c \x01(\x0b\x32\x32.temporal.api.sdk.v1.WorkflowTaskCompletedMetadata\x12\x43\n\x11metering_metadata\x18\r \x01(\x0b\x32(.temporal.api.common.v1.MeteringMetadata\x12g\n\x0c\x63\x61pabilities\x18\x0e \x01(\x0b\x32Q.temporal.api.workflowservice.v1.RespondWorkflowTaskCompletedRequest.Capabilities\x12>\n\ndeployment\x18\x0f \x01(\x0b\x32&.temporal.api.deployment.v1.DeploymentB\x02\x18\x01\x12\x46\n\x13versioning_behavior\x18\x10 \x01(\x0e\x32).temporal.api.enums.v1.VersioningBehavior\x12O\n\x12\x64\x65ployment_options\x18\x11 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentOptions\x1a_\n\x11QueryResultsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x39\n\x05value\x18\x02 \x01(\x0b\x32*.temporal.api.query.v1.WorkflowQueryResult:\x02\x38\x01\x1a\x45\n\x0c\x43\x61pabilities\x12\x35\n-discard_speculative_workflow_task_with_events\x18\x01 \x01(\x08"\xf5\x01\n$RespondWorkflowTaskCompletedResponse\x12U\n\rworkflow_task\x18\x01 \x01(\x0b\x32>.temporal.api.workflowservice.v1.PollWorkflowTaskQueueResponse\x12V\n\x0e\x61\x63tivity_tasks\x18\x02 \x03(\x0b\x32>.temporal.api.workflowservice.v1.PollActivityTaskQueueResponse\x12\x1e\n\x16reset_history_event_id\x18\x03 \x01(\x03"\xf8\x03\n RespondWorkflowTaskFailedRequest\x12\x12\n\ntask_token\x18\x01 \x01(\x0c\x12=\n\x05\x63\x61use\x18\x02 \x01(\x0e\x32..temporal.api.enums.v1.WorkflowTaskFailedCause\x12\x31\n\x07\x66\x61ilure\x18\x03 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12\x10\n\x08identity\x18\x04 \x01(\t\x12\x1b\n\x0f\x62inary_checksum\x18\x05 \x01(\tB\x02\x18\x01\x12\x11\n\tnamespace\x18\x06 \x01(\t\x12\x33\n\x08messages\x18\x07 \x03(\x0b\x32!.temporal.api.protocol.v1.Message\x12\x46\n\x0eworker_version\x18\x08 \x01(\x0b\x32*.temporal.api.common.v1.WorkerVersionStampB\x02\x18\x01\x12>\n\ndeployment\x18\t \x01(\x0b\x32&.temporal.api.deployment.v1.DeploymentB\x02\x18\x01\x12O\n\x12\x64\x65ployment_options\x18\n \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentOptions"#\n!RespondWorkflowTaskFailedResponse"\xaa\x03\n\x1cPollActivityTaskQueueRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x38\n\ntask_queue\x18\x02 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x1b\n\x13worker_instance_key\x18\x08 \x01(\t\x12I\n\x13task_queue_metadata\x18\x04 \x01(\x0b\x32,.temporal.api.taskqueue.v1.TaskQueueMetadata\x12Z\n\x1bworker_version_capabilities\x18\x05 \x01(\x0b\x32\x31.temporal.api.common.v1.WorkerVersionCapabilitiesB\x02\x18\x01\x12O\n\x12\x64\x65ployment_options\x18\x06 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentOptionsJ\x04\x08\x07\x10\x08R\x10worker_heartbeat"\x88\x08\n\x1dPollActivityTaskQueueResponse\x12\x12\n\ntask_token\x18\x01 \x01(\x0c\x12\x1a\n\x12workflow_namespace\x18\x02 \x01(\t\x12;\n\rworkflow_type\x18\x03 \x01(\x0b\x32$.temporal.api.common.v1.WorkflowType\x12\x45\n\x12workflow_execution\x18\x04 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12;\n\ractivity_type\x18\x05 \x01(\x0b\x32$.temporal.api.common.v1.ActivityType\x12\x13\n\x0b\x61\x63tivity_id\x18\x06 \x01(\t\x12.\n\x06header\x18\x07 \x01(\x0b\x32\x1e.temporal.api.common.v1.Header\x12/\n\x05input\x18\x08 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12;\n\x11heartbeat_details\x18\t \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x32\n\x0escheduled_time\x18\n \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x42\n\x1e\x63urrent_attempt_scheduled_time\x18\x0b \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x30\n\x0cstarted_time\x18\x0c \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x0f\n\x07\x61ttempt\x18\r \x01(\x05\x12<\n\x19schedule_to_close_timeout\x18\x0e \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x39\n\x16start_to_close_timeout\x18\x0f \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x34\n\x11heartbeat_timeout\x18\x10 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x39\n\x0cretry_policy\x18\x11 \x01(\x0b\x32#.temporal.api.common.v1.RetryPolicy\x12Q\n\x17poller_scaling_decision\x18\x12 \x01(\x0b\x32\x30.temporal.api.taskqueue.v1.PollerScalingDecision\x12\x32\n\x08priority\x18\x13 \x01(\x0b\x32 .temporal.api.common.v1.Priority\x12\x17\n\x0f\x61\x63tivity_run_id\x18\x14 \x01(\t"\x90\x01\n"RecordActivityTaskHeartbeatRequest\x12\x12\n\ntask_token\x18\x01 \x01(\x0c\x12\x31\n\x07\x64\x65tails\x18\x02 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x11\n\tnamespace\x18\x04 \x01(\t"p\n#RecordActivityTaskHeartbeatResponse\x12\x18\n\x10\x63\x61ncel_requested\x18\x01 \x01(\x08\x12\x17\n\x0f\x61\x63tivity_paused\x18\x02 \x01(\x08\x12\x16\n\x0e\x61\x63tivity_reset\x18\x03 \x01(\x08"\xba\x01\n&RecordActivityTaskHeartbeatByIdRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x12\x13\n\x0b\x61\x63tivity_id\x18\x04 \x01(\t\x12\x31\n\x07\x64\x65tails\x18\x05 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x10\n\x08identity\x18\x06 \x01(\t"t\n\'RecordActivityTaskHeartbeatByIdResponse\x12\x18\n\x10\x63\x61ncel_requested\x18\x01 \x01(\x08\x12\x17\n\x0f\x61\x63tivity_paused\x18\x02 \x01(\x08\x12\x16\n\x0e\x61\x63tivity_reset\x18\x03 \x01(\x08"\xe9\x02\n#RespondActivityTaskCompletedRequest\x12\x12\n\ntask_token\x18\x01 \x01(\x0c\x12\x30\n\x06result\x18\x02 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x11\n\tnamespace\x18\x04 \x01(\t\x12\x46\n\x0eworker_version\x18\x05 \x01(\x0b\x32*.temporal.api.common.v1.WorkerVersionStampB\x02\x18\x01\x12>\n\ndeployment\x18\x06 \x01(\x0b\x32&.temporal.api.deployment.v1.DeploymentB\x02\x18\x01\x12O\n\x12\x64\x65ployment_options\x18\x07 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentOptions"&\n$RespondActivityTaskCompletedResponse"\xba\x01\n\'RespondActivityTaskCompletedByIdRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x12\x13\n\x0b\x61\x63tivity_id\x18\x04 \x01(\t\x12\x30\n\x06result\x18\x05 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x10\n\x08identity\x18\x06 \x01(\t"*\n(RespondActivityTaskCompletedByIdResponse"\xa9\x03\n RespondActivityTaskFailedRequest\x12\x12\n\ntask_token\x18\x01 \x01(\x0c\x12\x31\n\x07\x66\x61ilure\x18\x02 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x11\n\tnamespace\x18\x04 \x01(\t\x12@\n\x16last_heartbeat_details\x18\x05 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x46\n\x0eworker_version\x18\x06 \x01(\x0b\x32*.temporal.api.common.v1.WorkerVersionStampB\x02\x18\x01\x12>\n\ndeployment\x18\x07 \x01(\x0b\x32&.temporal.api.deployment.v1.DeploymentB\x02\x18\x01\x12O\n\x12\x64\x65ployment_options\x18\x08 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentOptions"W\n!RespondActivityTaskFailedResponse\x12\x32\n\x08\x66\x61ilures\x18\x01 \x03(\x0b\x32 .temporal.api.failure.v1.Failure"\xfa\x01\n$RespondActivityTaskFailedByIdRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x12\x13\n\x0b\x61\x63tivity_id\x18\x04 \x01(\t\x12\x31\n\x07\x66\x61ilure\x18\x05 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12\x10\n\x08identity\x18\x06 \x01(\t\x12@\n\x16last_heartbeat_details\x18\x07 \x01(\x0b\x32 .temporal.api.common.v1.Payloads"[\n%RespondActivityTaskFailedByIdResponse\x12\x32\n\x08\x66\x61ilures\x18\x01 \x03(\x0b\x32 .temporal.api.failure.v1.Failure"\xe9\x02\n"RespondActivityTaskCanceledRequest\x12\x12\n\ntask_token\x18\x01 \x01(\x0c\x12\x31\n\x07\x64\x65tails\x18\x02 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x11\n\tnamespace\x18\x04 \x01(\t\x12\x46\n\x0eworker_version\x18\x05 \x01(\x0b\x32*.temporal.api.common.v1.WorkerVersionStampB\x02\x18\x01\x12>\n\ndeployment\x18\x06 \x01(\x0b\x32&.temporal.api.deployment.v1.DeploymentB\x02\x18\x01\x12O\n\x12\x64\x65ployment_options\x18\x07 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentOptions"%\n#RespondActivityTaskCanceledResponse"\x8b\x02\n&RespondActivityTaskCanceledByIdRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x12\x13\n\x0b\x61\x63tivity_id\x18\x04 \x01(\t\x12\x31\n\x07\x64\x65tails\x18\x05 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x10\n\x08identity\x18\x06 \x01(\t\x12O\n\x12\x64\x65ployment_options\x18\x07 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentOptions")\n\'RespondActivityTaskCanceledByIdResponse"\x84\x02\n%RequestCancelWorkflowExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x45\n\x12workflow_execution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x12\n\nrequest_id\x18\x04 \x01(\t\x12\x1e\n\x16\x66irst_execution_run_id\x18\x05 \x01(\t\x12\x0e\n\x06reason\x18\x06 \x01(\t\x12+\n\x05links\x18\x07 \x03(\x0b\x32\x1c.temporal.api.common.v1.Link"(\n&RequestCancelWorkflowExecutionResponse"\xde\x02\n\x1eSignalWorkflowExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x45\n\x12workflow_execution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x13\n\x0bsignal_name\x18\x03 \x01(\t\x12/\n\x05input\x18\x04 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x10\n\x08identity\x18\x05 \x01(\t\x12\x12\n\nrequest_id\x18\x06 \x01(\t\x12\x13\n\x07\x63ontrol\x18\x07 \x01(\tB\x02\x18\x01\x12.\n\x06header\x18\x08 \x01(\x0b\x32\x1e.temporal.api.common.v1.Header\x12+\n\x05links\x18\n \x03(\x0b\x32\x1c.temporal.api.common.v1.LinkJ\x04\x08\t\x10\n"!\n\x1fSignalWorkflowExecutionResponse"\xf1\t\n\'SignalWithStartWorkflowExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12;\n\rworkflow_type\x18\x03 \x01(\x0b\x32$.temporal.api.common.v1.WorkflowType\x12\x38\n\ntask_queue\x18\x04 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12/\n\x05input\x18\x05 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12=\n\x1aworkflow_execution_timeout\x18\x06 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x37\n\x14workflow_run_timeout\x18\x07 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x38\n\x15workflow_task_timeout\x18\x08 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x10\n\x08identity\x18\t \x01(\t\x12\x12\n\nrequest_id\x18\n \x01(\t\x12N\n\x18workflow_id_reuse_policy\x18\x0b \x01(\x0e\x32,.temporal.api.enums.v1.WorkflowIdReusePolicy\x12T\n\x1bworkflow_id_conflict_policy\x18\x16 \x01(\x0e\x32/.temporal.api.enums.v1.WorkflowIdConflictPolicy\x12\x13\n\x0bsignal_name\x18\x0c \x01(\t\x12\x36\n\x0csignal_input\x18\r \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x13\n\x07\x63ontrol\x18\x0e \x01(\tB\x02\x18\x01\x12\x39\n\x0cretry_policy\x18\x0f \x01(\x0b\x32#.temporal.api.common.v1.RetryPolicy\x12\x15\n\rcron_schedule\x18\x10 \x01(\t\x12*\n\x04memo\x18\x11 \x01(\x0b\x32\x1c.temporal.api.common.v1.Memo\x12\x43\n\x11search_attributes\x18\x12 \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes\x12.\n\x06header\x18\x13 \x01(\x0b\x32\x1e.temporal.api.common.v1.Header\x12\x37\n\x14workflow_start_delay\x18\x14 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x38\n\ruser_metadata\x18\x17 \x01(\x0b\x32!.temporal.api.sdk.v1.UserMetadata\x12+\n\x05links\x18\x18 \x03(\x0b\x32\x1c.temporal.api.common.v1.Link\x12I\n\x13versioning_override\x18\x19 \x01(\x0b\x32,.temporal.api.workflow.v1.VersioningOverride\x12\x32\n\x08priority\x18\x1a \x01(\x0b\x32 .temporal.api.common.v1.PriorityJ\x04\x08\x15\x10\x16"K\n(SignalWithStartWorkflowExecutionResponse\x12\x0e\n\x06run_id\x18\x01 \x01(\t\x12\x0f\n\x07started\x18\x02 \x01(\x08"\xc1\x03\n\x1dResetWorkflowExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x45\n\x12workflow_execution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x0e\n\x06reason\x18\x03 \x01(\t\x12%\n\x1dworkflow_task_finish_event_id\x18\x04 \x01(\x03\x12\x12\n\nrequest_id\x18\x05 \x01(\t\x12G\n\x12reset_reapply_type\x18\x06 \x01(\x0e\x32\'.temporal.api.enums.v1.ResetReapplyTypeB\x02\x18\x01\x12S\n\x1breset_reapply_exclude_types\x18\x07 \x03(\x0e\x32..temporal.api.enums.v1.ResetReapplyExcludeType\x12K\n\x15post_reset_operations\x18\x08 \x03(\x0b\x32,.temporal.api.workflow.v1.PostResetOperation\x12\x10\n\x08identity\x18\t \x01(\t"0\n\x1eResetWorkflowExecutionResponse\x12\x0e\n\x06run_id\x18\x01 \x01(\t"\x9f\x02\n!TerminateWorkflowExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x45\n\x12workflow_execution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x0e\n\x06reason\x18\x03 \x01(\t\x12\x31\n\x07\x64\x65tails\x18\x04 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x10\n\x08identity\x18\x05 \x01(\t\x12\x1e\n\x16\x66irst_execution_run_id\x18\x06 \x01(\t\x12+\n\x05links\x18\x07 \x03(\x0b\x32\x1c.temporal.api.common.v1.Link"$\n"TerminateWorkflowExecutionResponse"z\n\x1e\x44\x65leteWorkflowExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x45\n\x12workflow_execution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution"!\n\x1f\x44\x65leteWorkflowExecutionResponse"\xc9\x02\n!ListOpenWorkflowExecutionsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x19\n\x11maximum_page_size\x18\x02 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c\x12\x42\n\x11start_time_filter\x18\x04 \x01(\x0b\x32\'.temporal.api.filter.v1.StartTimeFilter\x12K\n\x10\x65xecution_filter\x18\x05 \x01(\x0b\x32/.temporal.api.filter.v1.WorkflowExecutionFilterH\x00\x12\x41\n\x0btype_filter\x18\x06 \x01(\x0b\x32*.temporal.api.filter.v1.WorkflowTypeFilterH\x00\x42\t\n\x07\x66ilters"\x82\x01\n"ListOpenWorkflowExecutionsResponse\x12\x43\n\nexecutions\x18\x01 \x03(\x0b\x32/.temporal.api.workflow.v1.WorkflowExecutionInfo\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c"\x8a\x03\n#ListClosedWorkflowExecutionsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x19\n\x11maximum_page_size\x18\x02 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c\x12\x42\n\x11start_time_filter\x18\x04 \x01(\x0b\x32\'.temporal.api.filter.v1.StartTimeFilter\x12K\n\x10\x65xecution_filter\x18\x05 \x01(\x0b\x32/.temporal.api.filter.v1.WorkflowExecutionFilterH\x00\x12\x41\n\x0btype_filter\x18\x06 \x01(\x0b\x32*.temporal.api.filter.v1.WorkflowTypeFilterH\x00\x12=\n\rstatus_filter\x18\x07 \x01(\x0b\x32$.temporal.api.filter.v1.StatusFilterH\x00\x42\t\n\x07\x66ilters"\x84\x01\n$ListClosedWorkflowExecutionsResponse\x12\x43\n\nexecutions\x18\x01 \x03(\x0b\x32/.temporal.api.workflow.v1.WorkflowExecutionInfo\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c"m\n\x1dListWorkflowExecutionsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x11\n\tpage_size\x18\x02 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c\x12\r\n\x05query\x18\x04 \x01(\t"~\n\x1eListWorkflowExecutionsResponse\x12\x43\n\nexecutions\x18\x01 \x03(\x0b\x32/.temporal.api.workflow.v1.WorkflowExecutionInfo\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c"u\n%ListArchivedWorkflowExecutionsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x11\n\tpage_size\x18\x02 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c\x12\r\n\x05query\x18\x04 \x01(\t"\x86\x01\n&ListArchivedWorkflowExecutionsResponse\x12\x43\n\nexecutions\x18\x01 \x03(\x0b\x32/.temporal.api.workflow.v1.WorkflowExecutionInfo\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c"m\n\x1dScanWorkflowExecutionsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x11\n\tpage_size\x18\x02 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c\x12\r\n\x05query\x18\x04 \x01(\t"~\n\x1eScanWorkflowExecutionsResponse\x12\x43\n\nexecutions\x18\x01 \x03(\x0b\x32/.temporal.api.workflow.v1.WorkflowExecutionInfo\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c"B\n\x1e\x43ountWorkflowExecutionsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\r\n\x05query\x18\x02 \x01(\t"\xed\x01\n\x1f\x43ountWorkflowExecutionsResponse\x12\r\n\x05\x63ount\x18\x01 \x01(\x03\x12\x61\n\x06groups\x18\x02 \x03(\x0b\x32Q.temporal.api.workflowservice.v1.CountWorkflowExecutionsResponse.AggregationGroup\x1aX\n\x10\x41ggregationGroup\x12\x35\n\x0cgroup_values\x18\x01 \x03(\x0b\x32\x1f.temporal.api.common.v1.Payload\x12\r\n\x05\x63ount\x18\x02 \x01(\x03"\x1c\n\x1aGetSearchAttributesRequest"\xc9\x01\n\x1bGetSearchAttributesResponse\x12T\n\x04keys\x18\x01 \x03(\x0b\x32\x46.temporal.api.workflowservice.v1.GetSearchAttributesResponse.KeysEntry\x1aT\n\tKeysEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x36\n\x05value\x18\x02 \x01(\x0e\x32\'.temporal.api.enums.v1.IndexedValueType:\x02\x38\x01"\xd0\x02\n RespondQueryTaskCompletedRequest\x12\x12\n\ntask_token\x18\x01 \x01(\x0c\x12>\n\x0e\x63ompleted_type\x18\x02 \x01(\x0e\x32&.temporal.api.enums.v1.QueryResultType\x12\x36\n\x0cquery_result\x18\x03 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x15\n\rerror_message\x18\x04 \x01(\t\x12\x11\n\tnamespace\x18\x06 \x01(\t\x12\x31\n\x07\x66\x61ilure\x18\x07 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12=\n\x05\x63\x61use\x18\x08 \x01(\x0e\x32..temporal.api.enums.v1.WorkflowTaskFailedCauseJ\x04\x08\x05\x10\x06"#\n!RespondQueryTaskCompletedResponse"n\n\x1bResetStickyTaskQueueRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12<\n\texecution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution"\x1e\n\x1cResetStickyTaskQueueResponse"\x9b\x02\n\x15ShutdownWorkerRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x19\n\x11sticky_task_queue\x18\x02 \x01(\t\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x0e\n\x06reason\x18\x04 \x01(\t\x12\x41\n\x10worker_heartbeat\x18\x05 \x01(\x0b\x32\'.temporal.api.worker.v1.WorkerHeartbeat\x12\x1b\n\x13worker_instance_key\x18\x06 \x01(\t\x12\x12\n\ntask_queue\x18\x07 \x01(\t\x12>\n\x10task_queue_types\x18\x08 \x03(\x0e\x32$.temporal.api.enums.v1.TaskQueueType"\x18\n\x16ShutdownWorkerResponse"\xe9\x01\n\x14QueryWorkflowRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12<\n\texecution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x33\n\x05query\x18\x03 \x01(\x0b\x32$.temporal.api.query.v1.WorkflowQuery\x12K\n\x16query_reject_condition\x18\x04 \x01(\x0e\x32+.temporal.api.enums.v1.QueryRejectCondition"\x8d\x01\n\x15QueryWorkflowResponse\x12\x36\n\x0cquery_result\x18\x01 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12<\n\x0equery_rejected\x18\x02 \x01(\x0b\x32$.temporal.api.query.v1.QueryRejected"s\n DescribeWorkflowExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12<\n\texecution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution"\x99\x05\n!DescribeWorkflowExecutionResponse\x12K\n\x10\x65xecution_config\x18\x01 \x01(\x0b\x32\x31.temporal.api.workflow.v1.WorkflowExecutionConfig\x12P\n\x17workflow_execution_info\x18\x02 \x01(\x0b\x32/.temporal.api.workflow.v1.WorkflowExecutionInfo\x12I\n\x12pending_activities\x18\x03 \x03(\x0b\x32-.temporal.api.workflow.v1.PendingActivityInfo\x12M\n\x10pending_children\x18\x04 \x03(\x0b\x32\x33.temporal.api.workflow.v1.PendingChildExecutionInfo\x12P\n\x15pending_workflow_task\x18\x05 \x01(\x0b\x32\x31.temporal.api.workflow.v1.PendingWorkflowTaskInfo\x12\x39\n\tcallbacks\x18\x06 \x03(\x0b\x32&.temporal.api.workflow.v1.CallbackInfo\x12U\n\x18pending_nexus_operations\x18\x07 \x03(\x0b\x32\x33.temporal.api.workflow.v1.PendingNexusOperationInfo\x12W\n\x16workflow_extended_info\x18\x08 \x01(\x0b\x32\x37.temporal.api.workflow.v1.WorkflowExecutionExtendedInfo"\x90\x04\n\x18\x44\x65scribeTaskQueueRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x38\n\ntask_queue\x18\x02 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12=\n\x0ftask_queue_type\x18\x03 \x01(\x0e\x32$.temporal.api.enums.v1.TaskQueueType\x12\x14\n\x0creport_stats\x18\x08 \x01(\x08\x12\x15\n\rreport_config\x18\x0b \x01(\x08\x12%\n\x19include_task_queue_status\x18\x04 \x01(\x08\x42\x02\x18\x01\x12\x42\n\x08\x61pi_mode\x18\x05 \x01(\x0e\x32,.temporal.api.enums.v1.DescribeTaskQueueModeB\x02\x18\x01\x12J\n\x08versions\x18\x06 \x01(\x0b\x32\x34.temporal.api.taskqueue.v1.TaskQueueVersionSelectionB\x02\x18\x01\x12\x42\n\x10task_queue_types\x18\x07 \x03(\x0e\x32$.temporal.api.enums.v1.TaskQueueTypeB\x02\x18\x01\x12\x1a\n\x0ereport_pollers\x18\t \x01(\x08\x42\x02\x18\x01\x12$\n\x18report_task_reachability\x18\n \x01(\x08\x42\x02\x18\x01"\xec\x07\n\x19\x44\x65scribeTaskQueueResponse\x12\x36\n\x07pollers\x18\x01 \x03(\x0b\x32%.temporal.api.taskqueue.v1.PollerInfo\x12\x38\n\x05stats\x18\x05 \x01(\x0b\x32).temporal.api.taskqueue.v1.TaskQueueStats\x12q\n\x15stats_by_priority_key\x18\x08 \x03(\x0b\x32R.temporal.api.workflowservice.v1.DescribeTaskQueueResponse.StatsByPriorityKeyEntry\x12K\n\x0fversioning_info\x18\x04 \x01(\x0b\x32\x32.temporal.api.taskqueue.v1.TaskQueueVersioningInfo\x12:\n\x06\x63onfig\x18\x06 \x01(\x0b\x32*.temporal.api.taskqueue.v1.TaskQueueConfig\x12k\n\x14\x65\x66\x66\x65\x63tive_rate_limit\x18\x07 \x01(\x0b\x32M.temporal.api.workflowservice.v1.DescribeTaskQueueResponse.EffectiveRateLimit\x12I\n\x11task_queue_status\x18\x02 \x01(\x0b\x32*.temporal.api.taskqueue.v1.TaskQueueStatusB\x02\x18\x01\x12g\n\rversions_info\x18\x03 \x03(\x0b\x32L.temporal.api.workflowservice.v1.DescribeTaskQueueResponse.VersionsInfoEntryB\x02\x18\x01\x1a\x64\n\x17StatsByPriorityKeyEntry\x12\x0b\n\x03key\x18\x01 \x01(\x05\x12\x38\n\x05value\x18\x02 \x01(\x0b\x32).temporal.api.taskqueue.v1.TaskQueueStats:\x02\x38\x01\x1at\n\x12\x45\x66\x66\x65\x63tiveRateLimit\x12\x1b\n\x13requests_per_second\x18\x01 \x01(\x02\x12\x41\n\x11rate_limit_source\x18\x02 \x01(\x0e\x32&.temporal.api.enums.v1.RateLimitSource\x1a\x64\n\x11VersionsInfoEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12>\n\x05value\x18\x02 \x01(\x0b\x32/.temporal.api.taskqueue.v1.TaskQueueVersionInfo:\x02\x38\x01"\x17\n\x15GetClusterInfoRequest"\xd1\x03\n\x16GetClusterInfoResponse\x12h\n\x11supported_clients\x18\x01 \x03(\x0b\x32M.temporal.api.workflowservice.v1.GetClusterInfoResponse.SupportedClientsEntry\x12\x16\n\x0eserver_version\x18\x02 \x01(\t\x12\x12\n\ncluster_id\x18\x03 \x01(\t\x12:\n\x0cversion_info\x18\x04 \x01(\x0b\x32$.temporal.api.version.v1.VersionInfo\x12\x14\n\x0c\x63luster_name\x18\x05 \x01(\t\x12\x1b\n\x13history_shard_count\x18\x06 \x01(\x05\x12\x19\n\x11persistence_store\x18\x07 \x01(\t\x12\x18\n\x10visibility_store\x18\x08 \x01(\t\x12 \n\x18initial_failover_version\x18\t \x01(\x03\x12"\n\x1a\x66\x61ilover_version_increment\x18\n \x01(\x03\x1a\x37\n\x15SupportedClientsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01"\x16\n\x14GetSystemInfoRequest"\xf4\x03\n\x15GetSystemInfoResponse\x12\x16\n\x0eserver_version\x18\x01 \x01(\t\x12Y\n\x0c\x63\x61pabilities\x18\x02 \x01(\x0b\x32\x43.temporal.api.workflowservice.v1.GetSystemInfoResponse.Capabilities\x1a\xe7\x02\n\x0c\x43\x61pabilities\x12\x1f\n\x17signal_and_query_header\x18\x01 \x01(\x08\x12&\n\x1einternal_error_differentiation\x18\x02 \x01(\x08\x12*\n"activity_failure_include_heartbeat\x18\x03 \x01(\x08\x12\x1a\n\x12supports_schedules\x18\x04 \x01(\x08\x12"\n\x1a\x65ncoded_failure_attributes\x18\x05 \x01(\x08\x12!\n\x19\x62uild_id_based_versioning\x18\x06 \x01(\x08\x12\x13\n\x0bupsert_memo\x18\x07 \x01(\x08\x12\x1c\n\x14\x65\x61ger_workflow_start\x18\x08 \x01(\x08\x12\x14\n\x0csdk_metadata\x18\t \x01(\x08\x12\'\n\x1f\x63ount_group_by_execution_status\x18\n \x01(\x08\x12\r\n\x05nexus\x18\x0b \x01(\x08"m\n\x1eListTaskQueuePartitionsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x38\n\ntask_queue\x18\x02 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue"\xdf\x01\n\x1fListTaskQueuePartitionsResponse\x12]\n\x1e\x61\x63tivity_task_queue_partitions\x18\x01 \x03(\x0b\x32\x35.temporal.api.taskqueue.v1.TaskQueuePartitionMetadata\x12]\n\x1eworkflow_task_queue_partitions\x18\x02 \x03(\x0b\x32\x35.temporal.api.taskqueue.v1.TaskQueuePartitionMetadata"\xcc\x02\n\x15\x43reateScheduleRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bschedule_id\x18\x02 \x01(\t\x12\x34\n\x08schedule\x18\x03 \x01(\x0b\x32".temporal.api.schedule.v1.Schedule\x12>\n\rinitial_patch\x18\x04 \x01(\x0b\x32\'.temporal.api.schedule.v1.SchedulePatch\x12\x10\n\x08identity\x18\x05 \x01(\t\x12\x12\n\nrequest_id\x18\x06 \x01(\t\x12*\n\x04memo\x18\x07 \x01(\x0b\x32\x1c.temporal.api.common.v1.Memo\x12\x43\n\x11search_attributes\x18\x08 \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes"0\n\x16\x43reateScheduleResponse\x12\x16\n\x0e\x63onflict_token\x18\x01 \x01(\x0c"A\n\x17\x44\x65scribeScheduleRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bschedule_id\x18\x02 \x01(\t"\x8f\x02\n\x18\x44\x65scribeScheduleResponse\x12\x34\n\x08schedule\x18\x01 \x01(\x0b\x32".temporal.api.schedule.v1.Schedule\x12\x34\n\x04info\x18\x02 \x01(\x0b\x32&.temporal.api.schedule.v1.ScheduleInfo\x12*\n\x04memo\x18\x03 \x01(\x0b\x32\x1c.temporal.api.common.v1.Memo\x12\x43\n\x11search_attributes\x18\x04 \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes\x12\x16\n\x0e\x63onflict_token\x18\x05 \x01(\x0c"\xf8\x01\n\x15UpdateScheduleRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bschedule_id\x18\x02 \x01(\t\x12\x34\n\x08schedule\x18\x03 \x01(\x0b\x32".temporal.api.schedule.v1.Schedule\x12\x16\n\x0e\x63onflict_token\x18\x04 \x01(\x0c\x12\x10\n\x08identity\x18\x05 \x01(\t\x12\x12\n\nrequest_id\x18\x06 \x01(\t\x12\x43\n\x11search_attributes\x18\x07 \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes"\x18\n\x16UpdateScheduleResponse"\x9c\x01\n\x14PatchScheduleRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bschedule_id\x18\x02 \x01(\t\x12\x36\n\x05patch\x18\x03 \x01(\x0b\x32\'.temporal.api.schedule.v1.SchedulePatch\x12\x10\n\x08identity\x18\x04 \x01(\t\x12\x12\n\nrequest_id\x18\x05 \x01(\t"\x17\n\x15PatchScheduleResponse"\xa8\x01\n ListScheduleMatchingTimesRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bschedule_id\x18\x02 \x01(\t\x12.\n\nstart_time\x18\x03 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12,\n\x08\x65nd_time\x18\x04 \x01(\x0b\x32\x1a.google.protobuf.Timestamp"S\n!ListScheduleMatchingTimesResponse\x12.\n\nstart_time\x18\x01 \x03(\x0b\x32\x1a.google.protobuf.Timestamp"Q\n\x15\x44\x65leteScheduleRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bschedule_id\x18\x02 \x01(\t\x12\x10\n\x08identity\x18\x03 \x01(\t"\x18\n\x16\x44\x65leteScheduleResponse"l\n\x14ListSchedulesRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x19\n\x11maximum_page_size\x18\x02 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c\x12\r\n\x05query\x18\x04 \x01(\t"p\n\x15ListSchedulesResponse\x12>\n\tschedules\x18\x01 \x03(\x0b\x32+.temporal.api.schedule.v1.ScheduleListEntry\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c"9\n\x15\x43ountSchedulesRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\r\n\x05query\x18\x02 \x01(\t"\xdb\x01\n\x16\x43ountSchedulesResponse\x12\r\n\x05\x63ount\x18\x01 \x01(\x03\x12X\n\x06groups\x18\x02 \x03(\x0b\x32H.temporal.api.workflowservice.v1.CountSchedulesResponse.AggregationGroup\x1aX\n\x10\x41ggregationGroup\x12\x35\n\x0cgroup_values\x18\x01 \x03(\x0b\x32\x1f.temporal.api.common.v1.Payload\x12\r\n\x05\x63ount\x18\x02 \x01(\x03"\x86\x05\n\'UpdateWorkerBuildIdCompatibilityRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x12\n\ntask_queue\x18\x02 \x01(\t\x12-\n#add_new_build_id_in_new_default_set\x18\x03 \x01(\tH\x00\x12\x87\x01\n\x1b\x61\x64\x64_new_compatible_build_id\x18\x04 \x01(\x0b\x32`.temporal.api.workflowservice.v1.UpdateWorkerBuildIdCompatibilityRequest.AddNewCompatibleVersionH\x00\x12!\n\x17promote_set_by_build_id\x18\x05 \x01(\tH\x00\x12%\n\x1bpromote_build_id_within_set\x18\x06 \x01(\tH\x00\x12h\n\nmerge_sets\x18\x07 \x01(\x0b\x32R.temporal.api.workflowservice.v1.UpdateWorkerBuildIdCompatibilityRequest.MergeSetsH\x00\x1ao\n\x17\x41\x64\x64NewCompatibleVersion\x12\x14\n\x0cnew_build_id\x18\x01 \x01(\t\x12$\n\x1c\x65xisting_compatible_build_id\x18\x02 \x01(\t\x12\x18\n\x10make_set_default\x18\x03 \x01(\x08\x1aI\n\tMergeSets\x12\x1c\n\x14primary_set_build_id\x18\x01 \x01(\t\x12\x1e\n\x16secondary_set_build_id\x18\x02 \x01(\tB\x0b\n\toperation"@\n(UpdateWorkerBuildIdCompatibilityResponseJ\x04\x08\x01\x10\x02R\x0eversion_set_id"_\n$GetWorkerBuildIdCompatibilityRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x12\n\ntask_queue\x18\x02 \x01(\t\x12\x10\n\x08max_sets\x18\x03 \x01(\x05"t\n%GetWorkerBuildIdCompatibilityResponse\x12K\n\x12major_version_sets\x18\x01 \x03(\x0b\x32/.temporal.api.taskqueue.v1.CompatibleVersionSet"\xb5\r\n"UpdateWorkerVersioningRulesRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x12\n\ntask_queue\x18\x02 \x01(\t\x12\x16\n\x0e\x63onflict_token\x18\x03 \x01(\x0c\x12\x81\x01\n\x16insert_assignment_rule\x18\x04 \x01(\x0b\x32_.temporal.api.workflowservice.v1.UpdateWorkerVersioningRulesRequest.InsertBuildIdAssignmentRuleH\x00\x12\x83\x01\n\x17replace_assignment_rule\x18\x05 \x01(\x0b\x32`.temporal.api.workflowservice.v1.UpdateWorkerVersioningRulesRequest.ReplaceBuildIdAssignmentRuleH\x00\x12\x81\x01\n\x16\x64\x65lete_assignment_rule\x18\x06 \x01(\x0b\x32_.temporal.api.workflowservice.v1.UpdateWorkerVersioningRulesRequest.DeleteBuildIdAssignmentRuleH\x00\x12\x8c\x01\n\x1c\x61\x64\x64_compatible_redirect_rule\x18\x07 \x01(\x0b\x32\x64.temporal.api.workflowservice.v1.UpdateWorkerVersioningRulesRequest.AddCompatibleBuildIdRedirectRuleH\x00\x12\x94\x01\n replace_compatible_redirect_rule\x18\x08 \x01(\x0b\x32h.temporal.api.workflowservice.v1.UpdateWorkerVersioningRulesRequest.ReplaceCompatibleBuildIdRedirectRuleH\x00\x12\x92\x01\n\x1f\x64\x65lete_compatible_redirect_rule\x18\t \x01(\x0b\x32g.temporal.api.workflowservice.v1.UpdateWorkerVersioningRulesRequest.DeleteCompatibleBuildIdRedirectRuleH\x00\x12l\n\x0f\x63ommit_build_id\x18\n \x01(\x0b\x32Q.temporal.api.workflowservice.v1.UpdateWorkerVersioningRulesRequest.CommitBuildIdH\x00\x1aq\n\x1bInsertBuildIdAssignmentRule\x12\x12\n\nrule_index\x18\x01 \x01(\x05\x12>\n\x04rule\x18\x02 \x01(\x0b\x32\x30.temporal.api.taskqueue.v1.BuildIdAssignmentRule\x1a\x81\x01\n\x1cReplaceBuildIdAssignmentRule\x12\x12\n\nrule_index\x18\x01 \x01(\x05\x12>\n\x04rule\x18\x02 \x01(\x0b\x32\x30.temporal.api.taskqueue.v1.BuildIdAssignmentRule\x12\r\n\x05\x66orce\x18\x03 \x01(\x08\x1a@\n\x1b\x44\x65leteBuildIdAssignmentRule\x12\x12\n\nrule_index\x18\x01 \x01(\x05\x12\r\n\x05\x66orce\x18\x02 \x01(\x08\x1aj\n AddCompatibleBuildIdRedirectRule\x12\x46\n\x04rule\x18\x01 \x01(\x0b\x32\x38.temporal.api.taskqueue.v1.CompatibleBuildIdRedirectRule\x1an\n$ReplaceCompatibleBuildIdRedirectRule\x12\x46\n\x04rule\x18\x01 \x01(\x0b\x32\x38.temporal.api.taskqueue.v1.CompatibleBuildIdRedirectRule\x1a>\n#DeleteCompatibleBuildIdRedirectRule\x12\x17\n\x0fsource_build_id\x18\x01 \x01(\t\x1a\x37\n\rCommitBuildId\x12\x17\n\x0ftarget_build_id\x18\x01 \x01(\t\x12\r\n\x05\x66orce\x18\x02 \x01(\x08\x42\x0b\n\toperation"\xfc\x01\n#UpdateWorkerVersioningRulesResponse\x12U\n\x10\x61ssignment_rules\x18\x01 \x03(\x0b\x32;.temporal.api.taskqueue.v1.TimestampedBuildIdAssignmentRule\x12\x66\n\x19\x63ompatible_redirect_rules\x18\x02 \x03(\x0b\x32\x43.temporal.api.taskqueue.v1.TimestampedCompatibleBuildIdRedirectRule\x12\x16\n\x0e\x63onflict_token\x18\x03 \x01(\x0c"H\n\x1fGetWorkerVersioningRulesRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x12\n\ntask_queue\x18\x02 \x01(\t"\xf9\x01\n GetWorkerVersioningRulesResponse\x12U\n\x10\x61ssignment_rules\x18\x01 \x03(\x0b\x32;.temporal.api.taskqueue.v1.TimestampedBuildIdAssignmentRule\x12\x66\n\x19\x63ompatible_redirect_rules\x18\x02 \x03(\x0b\x32\x43.temporal.api.taskqueue.v1.TimestampedCompatibleBuildIdRedirectRule\x12\x16\n\x0e\x63onflict_token\x18\x03 \x01(\x0c"\x9c\x01\n GetWorkerTaskReachabilityRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x11\n\tbuild_ids\x18\x02 \x03(\t\x12\x13\n\x0btask_queues\x18\x03 \x03(\t\x12=\n\x0creachability\x18\x04 \x01(\x0e\x32\'.temporal.api.enums.v1.TaskReachability"r\n!GetWorkerTaskReachabilityResponse\x12M\n\x15\x62uild_id_reachability\x18\x01 \x03(\x0b\x32..temporal.api.taskqueue.v1.BuildIdReachability"\x85\x02\n\x1eUpdateWorkflowExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x45\n\x12workflow_execution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x1e\n\x16\x66irst_execution_run_id\x18\x03 \x01(\t\x12\x37\n\x0bwait_policy\x18\x04 \x01(\x0b\x32".temporal.api.update.v1.WaitPolicy\x12\x30\n\x07request\x18\x05 \x01(\x0b\x32\x1f.temporal.api.update.v1.Request"\xd7\x01\n\x1fUpdateWorkflowExecutionResponse\x12\x35\n\nupdate_ref\x18\x01 \x01(\x0b\x32!.temporal.api.update.v1.UpdateRef\x12\x30\n\x07outcome\x18\x02 \x01(\x0b\x32\x1f.temporal.api.update.v1.Outcome\x12K\n\x05stage\x18\x03 \x01(\x0e\x32<.temporal.api.enums.v1.UpdateWorkflowExecutionLifecycleStage"\xf4\x07\n\x1aStartBatchOperationRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x18\n\x10visibility_query\x18\x02 \x01(\t\x12\x0e\n\x06job_id\x18\x03 \x01(\t\x12\x0e\n\x06reason\x18\x04 \x01(\t\x12=\n\nexecutions\x18\x05 \x03(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12!\n\x19max_operations_per_second\x18\x06 \x01(\x02\x12Q\n\x15termination_operation\x18\n \x01(\x0b\x32\x30.temporal.api.batch.v1.BatchOperationTerminationH\x00\x12G\n\x10signal_operation\x18\x0b \x01(\x0b\x32+.temporal.api.batch.v1.BatchOperationSignalH\x00\x12S\n\x16\x63\x61ncellation_operation\x18\x0c \x01(\x0b\x32\x31.temporal.api.batch.v1.BatchOperationCancellationH\x00\x12K\n\x12\x64\x65letion_operation\x18\r \x01(\x0b\x32-.temporal.api.batch.v1.BatchOperationDeletionH\x00\x12\x45\n\x0freset_operation\x18\x0e \x01(\x0b\x32*.temporal.api.batch.v1.BatchOperationResetH\x00\x12p\n!update_workflow_options_operation\x18\x0f \x01(\x0b\x32\x43.temporal.api.batch.v1.BatchOperationUpdateWorkflowExecutionOptionsH\x00\x12^\n\x1cunpause_activities_operation\x18\x10 \x01(\x0b\x32\x36.temporal.api.batch.v1.BatchOperationUnpauseActivitiesH\x00\x12Z\n\x1areset_activities_operation\x18\x11 \x01(\x0b\x32\x34.temporal.api.batch.v1.BatchOperationResetActivitiesH\x00\x12g\n!update_activity_options_operation\x18\x12 \x01(\x0b\x32:.temporal.api.batch.v1.BatchOperationUpdateActivityOptionsH\x00\x42\x0b\n\toperation"\x1d\n\x1bStartBatchOperationResponse"`\n\x19StopBatchOperationRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x0e\n\x06job_id\x18\x02 \x01(\t\x12\x0e\n\x06reason\x18\x03 \x01(\t\x12\x10\n\x08identity\x18\x04 \x01(\t"\x1c\n\x1aStopBatchOperationResponse"B\n\x1d\x44\x65scribeBatchOperationRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x0e\n\x06job_id\x18\x02 \x01(\t"\x92\x03\n\x1e\x44\x65scribeBatchOperationResponse\x12\x41\n\x0eoperation_type\x18\x01 \x01(\x0e\x32).temporal.api.enums.v1.BatchOperationType\x12\x0e\n\x06job_id\x18\x02 \x01(\t\x12\x39\n\x05state\x18\x03 \x01(\x0e\x32*.temporal.api.enums.v1.BatchOperationState\x12.\n\nstart_time\x18\x04 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12.\n\nclose_time\x18\x05 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x1d\n\x15total_operation_count\x18\x06 \x01(\x03\x12 \n\x18\x63omplete_operation_count\x18\x07 \x01(\x03\x12\x1f\n\x17\x66\x61ilure_operation_count\x18\x08 \x01(\x03\x12\x10\n\x08identity\x18\t \x01(\t\x12\x0e\n\x06reason\x18\n \x01(\t"[\n\x1aListBatchOperationsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x11\n\tpage_size\x18\x02 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c"y\n\x1bListBatchOperationsResponse\x12\x41\n\x0eoperation_info\x18\x01 \x03(\x0b\x32).temporal.api.batch.v1.BatchOperationInfo\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c"\xb9\x01\n"PollWorkflowExecutionUpdateRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x35\n\nupdate_ref\x18\x02 \x01(\x0b\x32!.temporal.api.update.v1.UpdateRef\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x37\n\x0bwait_policy\x18\x04 \x01(\x0b\x32".temporal.api.update.v1.WaitPolicy"\xdb\x01\n#PollWorkflowExecutionUpdateResponse\x12\x30\n\x07outcome\x18\x01 \x01(\x0b\x32\x1f.temporal.api.update.v1.Outcome\x12K\n\x05stage\x18\x02 \x01(\x0e\x32<.temporal.api.enums.v1.UpdateWorkflowExecutionLifecycleStage\x12\x35\n\nupdate_ref\x18\x03 \x01(\x0b\x32!.temporal.api.update.v1.UpdateRef"\x87\x03\n\x19PollNexusTaskQueueRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x10\n\x08identity\x18\x02 \x01(\t\x12\x1b\n\x13worker_instance_key\x18\x08 \x01(\t\x12\x38\n\ntask_queue\x18\x03 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12Z\n\x1bworker_version_capabilities\x18\x04 \x01(\x0b\x32\x31.temporal.api.common.v1.WorkerVersionCapabilitiesB\x02\x18\x01\x12O\n\x12\x64\x65ployment_options\x18\x06 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentOptions\x12\x41\n\x10worker_heartbeat\x18\x07 \x03(\x0b\x32\'.temporal.api.worker.v1.WorkerHeartbeat"\xb4\x01\n\x1aPollNexusTaskQueueResponse\x12\x12\n\ntask_token\x18\x01 \x01(\x0c\x12/\n\x07request\x18\x02 \x01(\x0b\x32\x1e.temporal.api.nexus.v1.Request\x12Q\n\x17poller_scaling_decision\x18\x03 \x01(\x0b\x32\x30.temporal.api.taskqueue.v1.PollerScalingDecision"\x8e\x01\n RespondNexusTaskCompletedRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x10\n\x08identity\x18\x02 \x01(\t\x12\x12\n\ntask_token\x18\x03 \x01(\x0c\x12\x31\n\x08response\x18\x04 \x01(\x0b\x32\x1f.temporal.api.nexus.v1.Response"#\n!RespondNexusTaskCompletedResponse"\xc3\x01\n\x1dRespondNexusTaskFailedRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x10\n\x08identity\x18\x02 \x01(\t\x12\x12\n\ntask_token\x18\x03 \x01(\x0c\x12\x36\n\x05\x65rror\x18\x04 \x01(\x0b\x32#.temporal.api.nexus.v1.HandlerErrorB\x02\x18\x01\x12\x31\n\x07\x66\x61ilure\x18\x05 \x01(\x0b\x32 .temporal.api.failure.v1.Failure" \n\x1eRespondNexusTaskFailedResponse"\xdf\x02\n\x1c\x45xecuteMultiOperationRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12[\n\noperations\x18\x02 \x03(\x0b\x32G.temporal.api.workflowservice.v1.ExecuteMultiOperationRequest.Operation\x1a\xce\x01\n\tOperation\x12X\n\x0estart_workflow\x18\x01 \x01(\x0b\x32>.temporal.api.workflowservice.v1.StartWorkflowExecutionRequestH\x00\x12Z\n\x0fupdate_workflow\x18\x02 \x01(\x0b\x32?.temporal.api.workflowservice.v1.UpdateWorkflowExecutionRequestH\x00\x42\x0b\n\toperation"\xcc\x02\n\x1d\x45xecuteMultiOperationResponse\x12Z\n\tresponses\x18\x01 \x03(\x0b\x32G.temporal.api.workflowservice.v1.ExecuteMultiOperationResponse.Response\x1a\xce\x01\n\x08Response\x12Y\n\x0estart_workflow\x18\x01 \x01(\x0b\x32?.temporal.api.workflowservice.v1.StartWorkflowExecutionResponseH\x00\x12[\n\x0fupdate_workflow\x18\x02 \x01(\x0b\x32@.temporal.api.workflowservice.v1.UpdateWorkflowExecutionResponseH\x00\x42\n\n\x08response"\xd0\x02\n\x1cUpdateActivityOptionsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12<\n\texecution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x43\n\x10\x61\x63tivity_options\x18\x04 \x01(\x0b\x32).temporal.api.activity.v1.ActivityOptions\x12/\n\x0bupdate_mask\x18\x05 \x01(\x0b\x32\x1a.google.protobuf.FieldMask\x12\x0c\n\x02id\x18\x06 \x01(\tH\x00\x12\x0e\n\x04type\x18\x07 \x01(\tH\x00\x12\x13\n\tmatch_all\x18\t \x01(\x08H\x00\x12\x18\n\x10restore_original\x18\x08 \x01(\x08\x42\n\n\x08\x61\x63tivity"d\n\x1dUpdateActivityOptionsResponse\x12\x43\n\x10\x61\x63tivity_options\x18\x01 \x01(\x0b\x32).temporal.api.activity.v1.ActivityOptions"\xb3\x01\n\x14PauseActivityRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12<\n\texecution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x0c\n\x02id\x18\x04 \x01(\tH\x00\x12\x0e\n\x04type\x18\x05 \x01(\tH\x00\x12\x0e\n\x06reason\x18\x06 \x01(\tB\n\n\x08\x61\x63tivity"\x17\n\x15PauseActivityResponse"\x98\x02\n\x16UnpauseActivityRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12<\n\texecution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x0c\n\x02id\x18\x04 \x01(\tH\x00\x12\x0e\n\x04type\x18\x05 \x01(\tH\x00\x12\x15\n\x0bunpause_all\x18\x06 \x01(\x08H\x00\x12\x16\n\x0ereset_attempts\x18\x07 \x01(\x08\x12\x17\n\x0freset_heartbeat\x18\x08 \x01(\x08\x12)\n\x06jitter\x18\t \x01(\x0b\x32\x19.google.protobuf.DurationB\n\n\x08\x61\x63tivity"\x19\n\x17UnpauseActivityResponse"\xb3\x02\n\x14ResetActivityRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12<\n\texecution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x0c\n\x02id\x18\x04 \x01(\tH\x00\x12\x0e\n\x04type\x18\x05 \x01(\tH\x00\x12\x13\n\tmatch_all\x18\n \x01(\x08H\x00\x12\x17\n\x0freset_heartbeat\x18\x06 \x01(\x08\x12\x13\n\x0bkeep_paused\x18\x07 \x01(\x08\x12)\n\x06jitter\x18\x08 \x01(\x0b\x32\x19.google.protobuf.Duration\x12 \n\x18restore_original_options\x18\t \x01(\x08\x42\n\n\x08\x61\x63tivity"\x17\n\x15ResetActivityResponse"\x9c\x02\n%UpdateWorkflowExecutionOptionsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x45\n\x12workflow_execution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12V\n\x1aworkflow_execution_options\x18\x03 \x01(\x0b\x32\x32.temporal.api.workflow.v1.WorkflowExecutionOptions\x12/\n\x0bupdate_mask\x18\x04 \x01(\x0b\x32\x1a.google.protobuf.FieldMask\x12\x10\n\x08identity\x18\x05 \x01(\t"\x80\x01\n&UpdateWorkflowExecutionOptionsResponse\x12V\n\x1aworkflow_execution_options\x18\x01 \x01(\x0b\x32\x32.temporal.api.workflow.v1.WorkflowExecutionOptions"j\n\x19\x44\x65scribeDeploymentRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12:\n\ndeployment\x18\x02 \x01(\x0b\x32&.temporal.api.deployment.v1.Deployment"a\n\x1a\x44\x65scribeDeploymentResponse\x12\x43\n\x0f\x64\x65ployment_info\x18\x01 \x01(\x0b\x32*.temporal.api.deployment.v1.DeploymentInfo"\xc2\x01\n&DescribeWorkerDeploymentVersionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x07version\x18\x02 \x01(\tB\x02\x18\x01\x12O\n\x12\x64\x65ployment_version\x18\x03 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersion\x12\x1f\n\x17report_task_queue_stats\x18\x04 \x01(\x08"\x8c\x05\n\'DescribeWorkerDeploymentVersionResponse\x12_\n\x1eworker_deployment_version_info\x18\x01 \x01(\x0b\x32\x37.temporal.api.deployment.v1.WorkerDeploymentVersionInfo\x12v\n\x13version_task_queues\x18\x02 \x03(\x0b\x32Y.temporal.api.workflowservice.v1.DescribeWorkerDeploymentVersionResponse.VersionTaskQueue\x1a\x87\x03\n\x10VersionTaskQueue\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x32\n\x04type\x18\x02 \x01(\x0e\x32$.temporal.api.enums.v1.TaskQueueType\x12\x38\n\x05stats\x18\x03 \x01(\x0b\x32).temporal.api.taskqueue.v1.TaskQueueStats\x12\x90\x01\n\x15stats_by_priority_key\x18\x04 \x03(\x0b\x32q.temporal.api.workflowservice.v1.DescribeWorkerDeploymentVersionResponse.VersionTaskQueue.StatsByPriorityKeyEntry\x1a\x64\n\x17StatsByPriorityKeyEntry\x12\x0b\n\x03key\x18\x01 \x01(\x05\x12\x38\n\x05value\x18\x02 \x01(\x0b\x32).temporal.api.taskqueue.v1.TaskQueueStats:\x02\x38\x01"M\n\x1f\x44\x65scribeWorkerDeploymentRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x17\n\x0f\x64\x65ployment_name\x18\x02 \x01(\t"\x8c\x01\n DescribeWorkerDeploymentResponse\x12\x16\n\x0e\x63onflict_token\x18\x01 \x01(\x0c\x12P\n\x16worker_deployment_info\x18\x02 \x01(\x0b\x32\x30.temporal.api.deployment.v1.WorkerDeploymentInfo"l\n\x16ListDeploymentsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x11\n\tpage_size\x18\x02 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c\x12\x13\n\x0bseries_name\x18\x04 \x01(\t"w\n\x17ListDeploymentsResponse\x12\x17\n\x0fnext_page_token\x18\x01 \x01(\x0c\x12\x43\n\x0b\x64\x65ployments\x18\x02 \x03(\x0b\x32..temporal.api.deployment.v1.DeploymentListInfo"\xcd\x01\n\x1bSetCurrentDeploymentRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12:\n\ndeployment\x18\x02 \x01(\x0b\x32&.temporal.api.deployment.v1.Deployment\x12\x10\n\x08identity\x18\x03 \x01(\t\x12M\n\x0fupdate_metadata\x18\x04 \x01(\x0b\x32\x34.temporal.api.deployment.v1.UpdateDeploymentMetadata"\xb9\x01\n\x1cSetCurrentDeploymentResponse\x12K\n\x17\x63urrent_deployment_info\x18\x01 \x01(\x0b\x32*.temporal.api.deployment.v1.DeploymentInfo\x12L\n\x18previous_deployment_info\x18\x02 \x01(\x0b\x32*.temporal.api.deployment.v1.DeploymentInfo"\xe5\x01\n(SetWorkerDeploymentCurrentVersionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x17\n\x0f\x64\x65ployment_name\x18\x02 \x01(\t\x12\x13\n\x07version\x18\x03 \x01(\tB\x02\x18\x01\x12\x10\n\x08\x62uild_id\x18\x07 \x01(\t\x12\x16\n\x0e\x63onflict_token\x18\x04 \x01(\x0c\x12\x10\n\x08identity\x18\x05 \x01(\t\x12"\n\x1aignore_missing_task_queues\x18\x06 \x01(\x08\x12\x18\n\x10\x61llow_no_pollers\x18\t \x01(\x08"\xbf\x01\n)SetWorkerDeploymentCurrentVersionResponse\x12\x16\n\x0e\x63onflict_token\x18\x01 \x01(\x0c\x12\x1c\n\x10previous_version\x18\x02 \x01(\tB\x02\x18\x01\x12\\\n\x1bprevious_deployment_version\x18\x03 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersionB\x02\x18\x01"\xf9\x01\n(SetWorkerDeploymentRampingVersionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x17\n\x0f\x64\x65ployment_name\x18\x02 \x01(\t\x12\x13\n\x07version\x18\x03 \x01(\tB\x02\x18\x01\x12\x10\n\x08\x62uild_id\x18\x08 \x01(\t\x12\x12\n\npercentage\x18\x04 \x01(\x02\x12\x16\n\x0e\x63onflict_token\x18\x05 \x01(\x0c\x12\x10\n\x08identity\x18\x06 \x01(\t\x12"\n\x1aignore_missing_task_queues\x18\x07 \x01(\x08\x12\x18\n\x10\x61llow_no_pollers\x18\n \x01(\x08"\xe0\x01\n)SetWorkerDeploymentRampingVersionResponse\x12\x16\n\x0e\x63onflict_token\x18\x01 \x01(\x0c\x12\x1c\n\x10previous_version\x18\x02 \x01(\tB\x02\x18\x01\x12\\\n\x1bprevious_deployment_version\x18\x04 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersionB\x02\x18\x01\x12\x1f\n\x13previous_percentage\x18\x03 \x01(\x02\x42\x02\x18\x01"]\n\x1cListWorkerDeploymentsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x11\n\tpage_size\x18\x02 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c"\x9f\x05\n\x1dListWorkerDeploymentsResponse\x12\x17\n\x0fnext_page_token\x18\x01 \x01(\x0c\x12r\n\x12worker_deployments\x18\x02 \x03(\x0b\x32V.temporal.api.workflowservice.v1.ListWorkerDeploymentsResponse.WorkerDeploymentSummary\x1a\xf0\x03\n\x17WorkerDeploymentSummary\x12\x0c\n\x04name\x18\x01 \x01(\t\x12/\n\x0b\x63reate_time\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x41\n\x0erouting_config\x18\x03 \x01(\x0b\x32).temporal.api.deployment.v1.RoutingConfig\x12o\n\x16latest_version_summary\x18\x04 \x01(\x0b\x32O.temporal.api.deployment.v1.WorkerDeploymentInfo.WorkerDeploymentVersionSummary\x12p\n\x17\x63urrent_version_summary\x18\x05 \x01(\x0b\x32O.temporal.api.deployment.v1.WorkerDeploymentInfo.WorkerDeploymentVersionSummary\x12p\n\x17ramping_version_summary\x18\x06 \x01(\x0b\x32O.temporal.api.deployment.v1.WorkerDeploymentInfo.WorkerDeploymentVersionSummary"\xc8\x01\n$DeleteWorkerDeploymentVersionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x07version\x18\x02 \x01(\tB\x02\x18\x01\x12O\n\x12\x64\x65ployment_version\x18\x05 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersion\x12\x15\n\rskip_drainage\x18\x03 \x01(\x08\x12\x10\n\x08identity\x18\x04 \x01(\t"\'\n%DeleteWorkerDeploymentVersionResponse"]\n\x1d\x44\x65leteWorkerDeploymentRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x17\n\x0f\x64\x65ployment_name\x18\x02 \x01(\t\x12\x10\n\x08identity\x18\x03 \x01(\t" \n\x1e\x44\x65leteWorkerDeploymentResponse"\xa2\x03\n,UpdateWorkerDeploymentVersionMetadataRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x07version\x18\x02 \x01(\tB\x02\x18\x01\x12O\n\x12\x64\x65ployment_version\x18\x05 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersion\x12x\n\x0eupsert_entries\x18\x03 \x03(\x0b\x32`.temporal.api.workflowservice.v1.UpdateWorkerDeploymentVersionMetadataRequest.UpsertEntriesEntry\x12\x16\n\x0eremove_entries\x18\x04 \x03(\t\x12\x10\n\x08identity\x18\x06 \x01(\t\x1aU\n\x12UpsertEntriesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12.\n\x05value\x18\x02 \x01(\x0b\x32\x1f.temporal.api.common.v1.Payload:\x02\x38\x01"n\n-UpdateWorkerDeploymentVersionMetadataResponse\x12=\n\x08metadata\x18\x01 \x01(\x0b\x32+.temporal.api.deployment.v1.VersionMetadata"\xbd\x01\n!SetWorkerDeploymentManagerRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x17\n\x0f\x64\x65ployment_name\x18\x02 \x01(\t\x12\x1a\n\x10manager_identity\x18\x03 \x01(\tH\x00\x12\x0e\n\x04self\x18\x04 \x01(\x08H\x00\x12\x16\n\x0e\x63onflict_token\x18\x05 \x01(\x0c\x12\x10\n\x08identity\x18\x06 \x01(\tB\x16\n\x14new_manager_identity"c\n"SetWorkerDeploymentManagerResponse\x12\x16\n\x0e\x63onflict_token\x18\x01 \x01(\x0c\x12%\n\x19previous_manager_identity\x18\x02 \x01(\tB\x02\x18\x01"E\n\x1bGetCurrentDeploymentRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bseries_name\x18\x02 \x01(\t"k\n\x1cGetCurrentDeploymentResponse\x12K\n\x17\x63urrent_deployment_info\x18\x01 \x01(\x0b\x32*.temporal.api.deployment.v1.DeploymentInfo"q\n GetDeploymentReachabilityRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12:\n\ndeployment\x18\x02 \x01(\x0b\x32&.temporal.api.deployment.v1.Deployment"\xe3\x01\n!GetDeploymentReachabilityResponse\x12\x43\n\x0f\x64\x65ployment_info\x18\x01 \x01(\x0b\x32*.temporal.api.deployment.v1.DeploymentInfo\x12\x43\n\x0creachability\x18\x02 \x01(\x0e\x32-.temporal.api.enums.v1.DeploymentReachability\x12\x34\n\x10last_update_time\x18\x03 \x01(\x0b\x32\x1a.google.protobuf.Timestamp"\xb4\x01\n\x19\x43reateWorkflowRuleRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x35\n\x04spec\x18\x02 \x01(\x0b\x32\'.temporal.api.rules.v1.WorkflowRuleSpec\x12\x12\n\nforce_scan\x18\x03 \x01(\x08\x12\x12\n\nrequest_id\x18\x04 \x01(\t\x12\x10\n\x08identity\x18\x05 \x01(\t\x12\x13\n\x0b\x64\x65scription\x18\x06 \x01(\t"_\n\x1a\x43reateWorkflowRuleResponse\x12\x31\n\x04rule\x18\x01 \x01(\x0b\x32#.temporal.api.rules.v1.WorkflowRule\x12\x0e\n\x06job_id\x18\x02 \x01(\t"A\n\x1b\x44\x65scribeWorkflowRuleRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x0f\n\x07rule_id\x18\x02 \x01(\t"Q\n\x1c\x44\x65scribeWorkflowRuleResponse\x12\x31\n\x04rule\x18\x01 \x01(\x0b\x32#.temporal.api.rules.v1.WorkflowRule"?\n\x19\x44\x65leteWorkflowRuleRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x0f\n\x07rule_id\x18\x02 \x01(\t"\x1c\n\x1a\x44\x65leteWorkflowRuleResponse"F\n\x18ListWorkflowRulesRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c"h\n\x19ListWorkflowRulesResponse\x12\x32\n\x05rules\x18\x01 \x03(\x0b\x32#.temporal.api.rules.v1.WorkflowRule\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c"\xce\x01\n\x1aTriggerWorkflowRuleRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12<\n\texecution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x0c\n\x02id\x18\x04 \x01(\tH\x00\x12\x37\n\x04spec\x18\x05 \x01(\x0b\x32\'.temporal.api.rules.v1.WorkflowRuleSpecH\x00\x12\x10\n\x08identity\x18\x03 \x01(\tB\x06\n\x04rule".\n\x1bTriggerWorkflowRuleResponse\x12\x0f\n\x07\x61pplied\x18\x01 \x01(\x08"\x86\x01\n\x1cRecordWorkerHeartbeatRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x10\n\x08identity\x18\x02 \x01(\t\x12\x41\n\x10worker_heartbeat\x18\x03 \x03(\x0b\x32\'.temporal.api.worker.v1.WorkerHeartbeat"\x1f\n\x1dRecordWorkerHeartbeatResponse"b\n\x12ListWorkersRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x11\n\tpage_size\x18\x02 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c\x12\r\n\x05query\x18\x04 \x01(\t"\xa5\x01\n\x13ListWorkersResponse\x12<\n\x0cworkers_info\x18\x01 \x03(\x0b\x32".temporal.api.worker.v1.WorkerInfoB\x02\x18\x01\x12\x37\n\x07workers\x18\x03 \x03(\x0b\x32&.temporal.api.worker.v1.WorkerListInfo\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c"\xd5\x05\n\x1cUpdateTaskQueueConfigRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x10\n\x08identity\x18\x02 \x01(\t\x12\x12\n\ntask_queue\x18\x03 \x01(\t\x12=\n\x0ftask_queue_type\x18\x04 \x01(\x0e\x32$.temporal.api.enums.v1.TaskQueueType\x12n\n\x17update_queue_rate_limit\x18\x05 \x01(\x0b\x32M.temporal.api.workflowservice.v1.UpdateTaskQueueConfigRequest.RateLimitUpdate\x12}\n&update_fairness_key_rate_limit_default\x18\x06 \x01(\x0b\x32M.temporal.api.workflowservice.v1.UpdateTaskQueueConfigRequest.RateLimitUpdate\x12\x84\x01\n\x1dset_fairness_weight_overrides\x18\x07 \x03(\x0b\x32].temporal.api.workflowservice.v1.UpdateTaskQueueConfigRequest.SetFairnessWeightOverridesEntry\x12\'\n\x1funset_fairness_weight_overrides\x18\x08 \x03(\t\x1a[\n\x0fRateLimitUpdate\x12\x38\n\nrate_limit\x18\x01 \x01(\x0b\x32$.temporal.api.taskqueue.v1.RateLimit\x12\x0e\n\x06reason\x18\x02 \x01(\t\x1a\x41\n\x1fSetFairnessWeightOverridesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\x02:\x02\x38\x01"[\n\x1dUpdateTaskQueueConfigResponse\x12:\n\x06\x63onfig\x18\x01 \x01(\x0b\x32*.temporal.api.taskqueue.v1.TaskQueueConfig"\x89\x01\n\x18\x46\x65tchWorkerConfigRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x10\n\x08identity\x18\x02 \x01(\t\x12\x0e\n\x06reason\x18\x03 \x01(\t\x12\x38\n\x08selector\x18\x06 \x01(\x0b\x32&.temporal.api.common.v1.WorkerSelector"U\n\x19\x46\x65tchWorkerConfigResponse\x12\x38\n\rworker_config\x18\x01 \x01(\x0b\x32!.temporal.api.sdk.v1.WorkerConfig"\xf5\x01\n\x19UpdateWorkerConfigRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x10\n\x08identity\x18\x02 \x01(\t\x12\x0e\n\x06reason\x18\x03 \x01(\t\x12\x38\n\rworker_config\x18\x04 \x01(\x0b\x32!.temporal.api.sdk.v1.WorkerConfig\x12/\n\x0bupdate_mask\x18\x05 \x01(\x0b\x32\x1a.google.protobuf.FieldMask\x12\x38\n\x08selector\x18\x06 \x01(\x0b\x32&.temporal.api.common.v1.WorkerSelector"d\n\x1aUpdateWorkerConfigResponse\x12:\n\rworker_config\x18\x01 \x01(\x0b\x32!.temporal.api.sdk.v1.WorkerConfigH\x00\x42\n\n\x08response"G\n\x15\x44\x65scribeWorkerRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x1b\n\x13worker_instance_key\x18\x02 \x01(\t"Q\n\x16\x44\x65scribeWorkerResponse\x12\x37\n\x0bworker_info\x18\x01 \x01(\x0b\x32".temporal.api.worker.v1.WorkerInfo"\x8d\x01\n\x1dPauseWorkflowExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x12\x10\n\x08identity\x18\x04 \x01(\t\x12\x0e\n\x06reason\x18\x05 \x01(\t\x12\x12\n\nrequest_id\x18\x06 \x01(\t" \n\x1ePauseWorkflowExecutionResponse"\x8f\x01\n\x1fUnpauseWorkflowExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x12\x10\n\x08identity\x18\x04 \x01(\t\x12\x0e\n\x06reason\x18\x05 \x01(\t\x12\x12\n\nrequest_id\x18\x06 \x01(\t""\n UnpauseWorkflowExecutionResponse"\xb4\x07\n\x1dStartActivityExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x10\n\x08identity\x18\x02 \x01(\t\x12\x12\n\nrequest_id\x18\x03 \x01(\t\x12\x13\n\x0b\x61\x63tivity_id\x18\x04 \x01(\t\x12;\n\ractivity_type\x18\x05 \x01(\x0b\x32$.temporal.api.common.v1.ActivityType\x12\x38\n\ntask_queue\x18\x06 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12<\n\x19schedule_to_close_timeout\x18\x07 \x01(\x0b\x32\x19.google.protobuf.Duration\x12<\n\x19schedule_to_start_timeout\x18\x08 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x39\n\x16start_to_close_timeout\x18\t \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x34\n\x11heartbeat_timeout\x18\n \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x39\n\x0cretry_policy\x18\x0b \x01(\x0b\x32#.temporal.api.common.v1.RetryPolicy\x12/\n\x05input\x18\x0c \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x45\n\x0fid_reuse_policy\x18\r \x01(\x0e\x32,.temporal.api.enums.v1.ActivityIdReusePolicy\x12K\n\x12id_conflict_policy\x18\x0e \x01(\x0e\x32/.temporal.api.enums.v1.ActivityIdConflictPolicy\x12\x43\n\x11search_attributes\x18\x0f \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes\x12.\n\x06header\x18\x10 \x01(\x0b\x32\x1e.temporal.api.common.v1.Header\x12\x38\n\ruser_metadata\x18\x11 \x01(\x0b\x32!.temporal.api.sdk.v1.UserMetadata\x12\x32\n\x08priority\x18\x12 \x01(\x0b\x32 .temporal.api.common.v1.Priority"A\n\x1eStartActivityExecutionResponse\x12\x0e\n\x06run_id\x18\x01 \x01(\t\x12\x0f\n\x07started\x18\x02 \x01(\x08"\xa3\x01\n DescribeActivityExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0b\x61\x63tivity_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x12\x15\n\rinclude_input\x18\x04 \x01(\x08\x12\x17\n\x0finclude_outcome\x18\x05 \x01(\x08\x12\x17\n\x0flong_poll_token\x18\x06 \x01(\x0c"\x81\x02\n!DescribeActivityExecutionResponse\x12\x0e\n\x06run_id\x18\x01 \x01(\t\x12=\n\x04info\x18\x02 \x01(\x0b\x32/.temporal.api.activity.v1.ActivityExecutionInfo\x12/\n\x05input\x18\x03 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x43\n\x07outcome\x18\x04 \x01(\x0b\x32\x32.temporal.api.activity.v1.ActivityExecutionOutcome\x12\x17\n\x0flong_poll_token\x18\x05 \x01(\x0c"V\n\x1cPollActivityExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0b\x61\x63tivity_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t"t\n\x1dPollActivityExecutionResponse\x12\x0e\n\x06run_id\x18\x01 \x01(\t\x12\x43\n\x07outcome\x18\x02 \x01(\x0b\x32\x32.temporal.api.activity.v1.ActivityExecutionOutcome"m\n\x1dListActivityExecutionsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x11\n\tpage_size\x18\x02 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c\x12\r\n\x05query\x18\x04 \x01(\t"\x82\x01\n\x1eListActivityExecutionsResponse\x12G\n\nexecutions\x18\x01 \x03(\x0b\x32\x33.temporal.api.activity.v1.ActivityExecutionListInfo\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c"B\n\x1e\x43ountActivityExecutionsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\r\n\x05query\x18\x02 \x01(\t"\xed\x01\n\x1f\x43ountActivityExecutionsResponse\x12\r\n\x05\x63ount\x18\x01 \x01(\x03\x12\x61\n\x06groups\x18\x02 \x03(\x0b\x32Q.temporal.api.workflowservice.v1.CountActivityExecutionsResponse.AggregationGroup\x1aX\n\x10\x41ggregationGroup\x12\x35\n\x0cgroup_values\x18\x01 \x03(\x0b\x32\x1f.temporal.api.common.v1.Payload\x12\r\n\x05\x63ount\x18\x02 \x01(\x03"\x95\x01\n%RequestCancelActivityExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0b\x61\x63tivity_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x12\x10\n\x08identity\x18\x04 \x01(\t\x12\x12\n\nrequest_id\x18\x05 \x01(\t\x12\x0e\n\x06reason\x18\x06 \x01(\t"(\n&RequestCancelActivityExecutionResponse"\x91\x01\n!TerminateActivityExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0b\x61\x63tivity_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x12\x10\n\x08identity\x18\x04 \x01(\t\x12\x12\n\nrequest_id\x18\x05 \x01(\t\x12\x0e\n\x06reason\x18\x06 \x01(\t"$\n"TerminateActivityExecutionResponse"X\n\x1e\x44\x65leteActivityExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0b\x61\x63tivity_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t"!\n\x1f\x44\x65leteActivityExecutionResponseB\xbe\x01\n"io.temporal.api.workflowservice.v1B\x14RequestResponseProtoP\x01Z5go.temporal.io/api/workflowservice/v1;workflowservice\xaa\x02!Temporalio.Api.WorkflowService.V1\xea\x02$Temporalio::Api::WorkflowService::V1b\x06proto3' ) @@ -3607,6 +3607,10 @@ _SETWORKERDEPLOYMENTMANAGERRESPONSE.fields_by_name[ "previous_manager_identity" ]._serialized_options = b"\030\001" + _LISTWORKERSRESPONSE.fields_by_name["workers_info"]._options = None + _LISTWORKERSRESPONSE.fields_by_name[ + "workers_info" + ]._serialized_options = b"\030\001" _UPDATETASKQUEUECONFIGREQUEST_SETFAIRNESSWEIGHTOVERRIDESENTRY._options = None _UPDATETASKQUEUECONFIGREQUEST_SETFAIRNESSWEIGHTOVERRIDESENTRY._serialized_options = b"8\001" _REGISTERNAMESPACEREQUEST._serialized_start = 1530 @@ -4035,72 +4039,72 @@ _RECORDWORKERHEARTBEATRESPONSE._serialized_end = 42129 _LISTWORKERSREQUEST._serialized_start = 42131 _LISTWORKERSREQUEST._serialized_end = 42229 - _LISTWORKERSRESPONSE._serialized_start = 42231 - _LISTWORKERSRESPONSE._serialized_end = 42335 - _UPDATETASKQUEUECONFIGREQUEST._serialized_start = 42338 - _UPDATETASKQUEUECONFIGREQUEST._serialized_end = 43063 - _UPDATETASKQUEUECONFIGREQUEST_RATELIMITUPDATE._serialized_start = 42905 - _UPDATETASKQUEUECONFIGREQUEST_RATELIMITUPDATE._serialized_end = 42996 + _LISTWORKERSRESPONSE._serialized_start = 42232 + _LISTWORKERSRESPONSE._serialized_end = 42397 + _UPDATETASKQUEUECONFIGREQUEST._serialized_start = 42400 + _UPDATETASKQUEUECONFIGREQUEST._serialized_end = 43125 + _UPDATETASKQUEUECONFIGREQUEST_RATELIMITUPDATE._serialized_start = 42967 + _UPDATETASKQUEUECONFIGREQUEST_RATELIMITUPDATE._serialized_end = 43058 _UPDATETASKQUEUECONFIGREQUEST_SETFAIRNESSWEIGHTOVERRIDESENTRY._serialized_start = ( - 42998 + 43060 ) _UPDATETASKQUEUECONFIGREQUEST_SETFAIRNESSWEIGHTOVERRIDESENTRY._serialized_end = ( - 43063 + 43125 ) - _UPDATETASKQUEUECONFIGRESPONSE._serialized_start = 43065 - _UPDATETASKQUEUECONFIGRESPONSE._serialized_end = 43156 - _FETCHWORKERCONFIGREQUEST._serialized_start = 43159 - _FETCHWORKERCONFIGREQUEST._serialized_end = 43296 - _FETCHWORKERCONFIGRESPONSE._serialized_start = 43298 - _FETCHWORKERCONFIGRESPONSE._serialized_end = 43383 - _UPDATEWORKERCONFIGREQUEST._serialized_start = 43386 - _UPDATEWORKERCONFIGREQUEST._serialized_end = 43631 - _UPDATEWORKERCONFIGRESPONSE._serialized_start = 43633 - _UPDATEWORKERCONFIGRESPONSE._serialized_end = 43733 - _DESCRIBEWORKERREQUEST._serialized_start = 43735 - _DESCRIBEWORKERREQUEST._serialized_end = 43806 - _DESCRIBEWORKERRESPONSE._serialized_start = 43808 - _DESCRIBEWORKERRESPONSE._serialized_end = 43889 - _PAUSEWORKFLOWEXECUTIONREQUEST._serialized_start = 43892 - _PAUSEWORKFLOWEXECUTIONREQUEST._serialized_end = 44033 - _PAUSEWORKFLOWEXECUTIONRESPONSE._serialized_start = 44035 - _PAUSEWORKFLOWEXECUTIONRESPONSE._serialized_end = 44067 - _UNPAUSEWORKFLOWEXECUTIONREQUEST._serialized_start = 44070 - _UNPAUSEWORKFLOWEXECUTIONREQUEST._serialized_end = 44213 - _UNPAUSEWORKFLOWEXECUTIONRESPONSE._serialized_start = 44215 - _UNPAUSEWORKFLOWEXECUTIONRESPONSE._serialized_end = 44249 - _STARTACTIVITYEXECUTIONREQUEST._serialized_start = 44252 - _STARTACTIVITYEXECUTIONREQUEST._serialized_end = 45200 - _STARTACTIVITYEXECUTIONRESPONSE._serialized_start = 45202 - _STARTACTIVITYEXECUTIONRESPONSE._serialized_end = 45267 - _DESCRIBEACTIVITYEXECUTIONREQUEST._serialized_start = 45270 - _DESCRIBEACTIVITYEXECUTIONREQUEST._serialized_end = 45433 - _DESCRIBEACTIVITYEXECUTIONRESPONSE._serialized_start = 45436 - _DESCRIBEACTIVITYEXECUTIONRESPONSE._serialized_end = 45693 - _POLLACTIVITYEXECUTIONREQUEST._serialized_start = 45695 - _POLLACTIVITYEXECUTIONREQUEST._serialized_end = 45781 - _POLLACTIVITYEXECUTIONRESPONSE._serialized_start = 45783 - _POLLACTIVITYEXECUTIONRESPONSE._serialized_end = 45899 - _LISTACTIVITYEXECUTIONSREQUEST._serialized_start = 45901 - _LISTACTIVITYEXECUTIONSREQUEST._serialized_end = 46010 - _LISTACTIVITYEXECUTIONSRESPONSE._serialized_start = 46013 - _LISTACTIVITYEXECUTIONSRESPONSE._serialized_end = 46143 - _COUNTACTIVITYEXECUTIONSREQUEST._serialized_start = 46145 - _COUNTACTIVITYEXECUTIONSREQUEST._serialized_end = 46211 - _COUNTACTIVITYEXECUTIONSRESPONSE._serialized_start = 46214 - _COUNTACTIVITYEXECUTIONSRESPONSE._serialized_end = 46451 + _UPDATETASKQUEUECONFIGRESPONSE._serialized_start = 43127 + _UPDATETASKQUEUECONFIGRESPONSE._serialized_end = 43218 + _FETCHWORKERCONFIGREQUEST._serialized_start = 43221 + _FETCHWORKERCONFIGREQUEST._serialized_end = 43358 + _FETCHWORKERCONFIGRESPONSE._serialized_start = 43360 + _FETCHWORKERCONFIGRESPONSE._serialized_end = 43445 + _UPDATEWORKERCONFIGREQUEST._serialized_start = 43448 + _UPDATEWORKERCONFIGREQUEST._serialized_end = 43693 + _UPDATEWORKERCONFIGRESPONSE._serialized_start = 43695 + _UPDATEWORKERCONFIGRESPONSE._serialized_end = 43795 + _DESCRIBEWORKERREQUEST._serialized_start = 43797 + _DESCRIBEWORKERREQUEST._serialized_end = 43868 + _DESCRIBEWORKERRESPONSE._serialized_start = 43870 + _DESCRIBEWORKERRESPONSE._serialized_end = 43951 + _PAUSEWORKFLOWEXECUTIONREQUEST._serialized_start = 43954 + _PAUSEWORKFLOWEXECUTIONREQUEST._serialized_end = 44095 + _PAUSEWORKFLOWEXECUTIONRESPONSE._serialized_start = 44097 + _PAUSEWORKFLOWEXECUTIONRESPONSE._serialized_end = 44129 + _UNPAUSEWORKFLOWEXECUTIONREQUEST._serialized_start = 44132 + _UNPAUSEWORKFLOWEXECUTIONREQUEST._serialized_end = 44275 + _UNPAUSEWORKFLOWEXECUTIONRESPONSE._serialized_start = 44277 + _UNPAUSEWORKFLOWEXECUTIONRESPONSE._serialized_end = 44311 + _STARTACTIVITYEXECUTIONREQUEST._serialized_start = 44314 + _STARTACTIVITYEXECUTIONREQUEST._serialized_end = 45262 + _STARTACTIVITYEXECUTIONRESPONSE._serialized_start = 45264 + _STARTACTIVITYEXECUTIONRESPONSE._serialized_end = 45329 + _DESCRIBEACTIVITYEXECUTIONREQUEST._serialized_start = 45332 + _DESCRIBEACTIVITYEXECUTIONREQUEST._serialized_end = 45495 + _DESCRIBEACTIVITYEXECUTIONRESPONSE._serialized_start = 45498 + _DESCRIBEACTIVITYEXECUTIONRESPONSE._serialized_end = 45755 + _POLLACTIVITYEXECUTIONREQUEST._serialized_start = 45757 + _POLLACTIVITYEXECUTIONREQUEST._serialized_end = 45843 + _POLLACTIVITYEXECUTIONRESPONSE._serialized_start = 45845 + _POLLACTIVITYEXECUTIONRESPONSE._serialized_end = 45961 + _LISTACTIVITYEXECUTIONSREQUEST._serialized_start = 45963 + _LISTACTIVITYEXECUTIONSREQUEST._serialized_end = 46072 + _LISTACTIVITYEXECUTIONSRESPONSE._serialized_start = 46075 + _LISTACTIVITYEXECUTIONSRESPONSE._serialized_end = 46205 + _COUNTACTIVITYEXECUTIONSREQUEST._serialized_start = 46207 + _COUNTACTIVITYEXECUTIONSREQUEST._serialized_end = 46273 + _COUNTACTIVITYEXECUTIONSRESPONSE._serialized_start = 46276 + _COUNTACTIVITYEXECUTIONSRESPONSE._serialized_end = 46513 _COUNTACTIVITYEXECUTIONSRESPONSE_AGGREGATIONGROUP._serialized_start = 18770 _COUNTACTIVITYEXECUTIONSRESPONSE_AGGREGATIONGROUP._serialized_end = 18858 - _REQUESTCANCELACTIVITYEXECUTIONREQUEST._serialized_start = 46454 - _REQUESTCANCELACTIVITYEXECUTIONREQUEST._serialized_end = 46603 - _REQUESTCANCELACTIVITYEXECUTIONRESPONSE._serialized_start = 46605 - _REQUESTCANCELACTIVITYEXECUTIONRESPONSE._serialized_end = 46645 - _TERMINATEACTIVITYEXECUTIONREQUEST._serialized_start = 46648 - _TERMINATEACTIVITYEXECUTIONREQUEST._serialized_end = 46793 - _TERMINATEACTIVITYEXECUTIONRESPONSE._serialized_start = 46795 - _TERMINATEACTIVITYEXECUTIONRESPONSE._serialized_end = 46831 - _DELETEACTIVITYEXECUTIONREQUEST._serialized_start = 46833 - _DELETEACTIVITYEXECUTIONREQUEST._serialized_end = 46921 - _DELETEACTIVITYEXECUTIONRESPONSE._serialized_start = 46923 - _DELETEACTIVITYEXECUTIONRESPONSE._serialized_end = 46956 + _REQUESTCANCELACTIVITYEXECUTIONREQUEST._serialized_start = 46516 + _REQUESTCANCELACTIVITYEXECUTIONREQUEST._serialized_end = 46665 + _REQUESTCANCELACTIVITYEXECUTIONRESPONSE._serialized_start = 46667 + _REQUESTCANCELACTIVITYEXECUTIONRESPONSE._serialized_end = 46707 + _TERMINATEACTIVITYEXECUTIONREQUEST._serialized_start = 46710 + _TERMINATEACTIVITYEXECUTIONREQUEST._serialized_end = 46855 + _TERMINATEACTIVITYEXECUTIONRESPONSE._serialized_start = 46857 + _TERMINATEACTIVITYEXECUTIONRESPONSE._serialized_end = 46893 + _DELETEACTIVITYEXECUTIONREQUEST._serialized_start = 46895 + _DELETEACTIVITYEXECUTIONREQUEST._serialized_end = 46983 + _DELETEACTIVITYEXECUTIONRESPONSE._serialized_start = 46985 + _DELETEACTIVITYEXECUTIONRESPONSE._serialized_end = 47018 # @@protoc_insertion_point(module_scope) diff --git a/temporalio/api/workflowservice/v1/request_response_pb2.pyi b/temporalio/api/workflowservice/v1/request_response_pb2.pyi index 4c10f560f..debf89c0c 100644 --- a/temporalio/api/workflowservice/v1/request_response_pb2.pyi +++ b/temporalio/api/workflowservice/v1/request_response_pb2.pyi @@ -9938,8 +9938,8 @@ class ListWorkersRequest(google.protobuf.message.Message): page_size: builtins.int next_page_token: builtins.bytes query: builtins.str - """`query` in ListWorkers is used to filter workers based on worker status info. - The following worker status attributes are expected are supported as part of the query: + """`query` in ListWorkers is used to filter workers based on worker attributes. + Supported attributes: * WorkerInstanceKey * WorkerIdentity * HostName @@ -9949,9 +9949,7 @@ class ListWorkersRequest(google.protobuf.message.Message): * SdkName * SdkVersion * StartTime - * LastHeartbeatTime * Status - Currently metrics are not supported as a part of ListWorkers query. """ def __init__( self, @@ -9981,13 +9979,24 @@ class ListWorkersResponse(google.protobuf.message.Message): DESCRIPTOR: google.protobuf.descriptor.Descriptor WORKERS_INFO_FIELD_NUMBER: builtins.int + WORKERS_FIELD_NUMBER: builtins.int NEXT_PAGE_TOKEN_FIELD_NUMBER: builtins.int @property def workers_info( self, ) -> google.protobuf.internal.containers.RepeatedCompositeFieldContainer[ temporalio.api.worker.v1.message_pb2.WorkerInfo - ]: ... + ]: + """Deprecated: Use workers instead. This field returns full WorkerInfo which + includes expensive runtime metrics. We will stop populating this field in the future. + """ + @property + def workers( + self, + ) -> google.protobuf.internal.containers.RepeatedCompositeFieldContainer[ + temporalio.api.worker.v1.message_pb2.WorkerListInfo + ]: + """Limited worker information.""" next_page_token: builtins.bytes """Next page token""" def __init__( @@ -9997,12 +10006,21 @@ class ListWorkersResponse(google.protobuf.message.Message): temporalio.api.worker.v1.message_pb2.WorkerInfo ] | None = ..., + workers: collections.abc.Iterable[ + temporalio.api.worker.v1.message_pb2.WorkerListInfo + ] + | None = ..., next_page_token: builtins.bytes = ..., ) -> None: ... def ClearField( self, field_name: typing_extensions.Literal[ - "next_page_token", b"next_page_token", "workers_info", b"workers_info" + "next_page_token", + b"next_page_token", + "workers", + b"workers", + "workers_info", + b"workers_info", ], ) -> None: ... diff --git a/temporalio/bridge/sdk-core b/temporalio/bridge/sdk-core index 5f79ef286..f188eb531 160000 --- a/temporalio/bridge/sdk-core +++ b/temporalio/bridge/sdk-core @@ -1 +1 @@ -Subproject commit 5f79ef28684578c391b58bcc71afddb7c964d604 +Subproject commit f188eb5319fb44093e40208471d28946763c777a diff --git a/temporalio/bridge/src/worker.rs b/temporalio/bridge/src/worker.rs index 8de4228b9..a676e3338 100644 --- a/temporalio/bridge/src/worker.rs +++ b/temporalio/bridge/src/worker.rs @@ -14,7 +14,7 @@ use temporalio_common::protos::coresdk::{ nexus::NexusTaskCompletion, ActivityHeartbeat, ActivityTaskCompletion, }; use temporalio_common::protos::temporal::api::history::v1::History; -use temporalio_common::protos::temporal::api::worker::v1::PluginInfo; +use temporalio_common::protos::temporal::api::worker::v1::{PluginInfo, StorageDriverInfo}; use temporalio_sdk_core::replay::{HistoryForReplay, ReplayWorkerInput}; use temporalio_sdk_core::{ PollError, SlotInfo, SlotInfoTrait, SlotKind, SlotKindType, SlotMarkUsedContext, @@ -62,6 +62,7 @@ pub struct WorkerConfig { nondeterminism_as_workflow_fail_for_types: HashSet, nexus_task_poller_behavior: PollerBehavior, plugins: Vec, + storage_drivers: HashSet, } #[derive(FromPyObject)] @@ -762,6 +763,12 @@ fn convert_worker_config( }) .collect(), ) + .storage_drivers( + conf.storage_drivers + .into_iter() + .map(|r#type| StorageDriverInfo { r#type }) + .collect::>(), + ) .build() .map_err(|err| PyValueError::new_err(format!("Invalid worker config: {err}"))) } diff --git a/temporalio/bridge/worker.py b/temporalio/bridge/worker.py index c2e426d28..c2512a28c 100644 --- a/temporalio/bridge/worker.py +++ b/temporalio/bridge/worker.py @@ -56,6 +56,7 @@ class WorkerConfig: nondeterminism_as_workflow_fail_for_types: set[str] nexus_task_poller_behavior: PollerBehavior plugins: Sequence[str] + storage_drivers: set[str] @dataclass diff --git a/temporalio/worker/_replayer.py b/temporalio/worker/_replayer.py index de55c4845..53af4aec5 100644 --- a/temporalio/worker/_replayer.py +++ b/temporalio/worker/_replayer.py @@ -233,6 +233,10 @@ def on_eviction_hook( runtime = ( self._config.get("runtime") or temporalio.runtime.Runtime.default() ) + data_converter = ( + self._config.get("data_converter") + or temporalio.converter.DataConverter.default + ) workflow_worker = _WorkflowWorker( bridge_worker=lambda: bridge_worker, namespace=self._config.get("namespace", "ReplayNamespace"), @@ -246,8 +250,7 @@ def on_eviction_hook( "unsandboxed_workflow_runner" ) or UnsandboxedWorkflowRunner(), - data_converter=self._config.get("data_converter") - or temporalio.converter.DataConverter.default, + data_converter=data_converter, interceptors=self._config.get("interceptors", []), workflow_failure_exception_types=self._config.get( "workflow_failure_exception_types", [] @@ -266,6 +269,13 @@ def on_eviction_hook( ) != HeaderCodecBehavior.NO_CODEC, ) + external_storage = data_converter.external_storage + storage_driver_types = ( + {driver.type() for driver in external_storage.drivers} + if external_storage + else set() + ) + # Create bridge worker bridge_worker, pusher = temporalio.bridge.worker.Worker.for_replay( runtime._core_runtime, @@ -322,6 +332,7 @@ def on_eviction_hook( 1 ), plugins=[plugin.name() for plugin in self.plugins], + storage_drivers=storage_driver_types, ), ) bridge_worker_scope = bridge_worker diff --git a/temporalio/worker/_worker.py b/temporalio/worker/_worker.py index 05151753d..cf805a1be 100644 --- a/temporalio/worker/_worker.py +++ b/temporalio/worker/_worker.py @@ -423,6 +423,10 @@ def _init_from_config(self, client: temporalio.client.Client, config: WorkerConf ) interceptors = interceptors_from_client + list(config["interceptors"]) # type: ignore[reportTypedDictNotRequiredAccess] + # Extract storage drivers from the client's data converter + _ext_storage = client_config["data_converter"].external_storage + self._storage_drivers = list(_ext_storage.drivers) if _ext_storage else [] + # Extract the bridge service client bridge_client = _extract_bridge_client_for_worker(config["client"]) # type: ignore[reportTypedDictNotRequiredAccess] @@ -572,6 +576,9 @@ def check_activity(activity: str): ) deduped_plugin_names = list({plugin.name() for plugin in self._plugins}) + deduped_storage_driver_types = { + driver.type() for driver in self._storage_drivers + } # Create bridge worker last. We have empirically observed that if it is # created before an error is raised from the activity worker @@ -636,6 +643,7 @@ def check_activity(activity: str): "nexus_task_poller_behavior" ]._to_bridge(), # type: ignore[reportTypedDictNotRequiredAccess,reportOptionalMemberAccess] plugins=deduped_plugin_names, + storage_drivers=deduped_storage_driver_types, ), ) diff --git a/tests/worker/test_extstore.py b/tests/worker/test_extstore.py index 921e8a3f1..44c5f5966 100644 --- a/tests/worker/test_extstore.py +++ b/tests/worker/test_extstore.py @@ -3,10 +3,13 @@ from collections.abc import Sequence from dataclasses import dataclass from datetime import timedelta +from unittest import mock import pytest import temporalio +import temporalio.bridge.client +import temporalio.bridge.worker import temporalio.converter from temporalio import activity, workflow from temporalio.api.common.v1 import Payload @@ -552,3 +555,62 @@ async def test_extstore_chained_activities( # round-trips (one store on completion, one retrieve on the next WFT). assert driver._store_calls == 2 assert driver._retrieve_calls == 2 + + +async def test_worker_storage_drivers_populated_from_client( + env: WorkflowEnvironment, +): + """Worker._storage_drivers is populated from the client's ExternalStorage and + passed to the bridge config as a set of driver type strings.""" + + class DifferentTestDriver(InMemoryTestDriver): + def __init__(self, driver_name: str): + super().__init__(driver_name=driver_name) + + driver1 = InMemoryTestDriver(driver_name="driver1") + driver2 = InMemoryTestDriver(driver_name="driver2") + driver3 = DifferentTestDriver(driver_name="driver3") + + client = await Client.connect( + env.client.service_client.config.target_host, + namespace=env.client.namespace, + data_converter=dataclasses.replace( + temporalio.converter.default(), + external_storage=ExternalStorage( + drivers=[driver1, driver2, driver3], + driver_selector=lambda _context, _payload: driver1, + payload_size_threshold=None, + ), + ), + ) + + captured_config: list[temporalio.bridge.worker.WorkerConfig] = [] + original_create = temporalio.bridge.worker.Worker.create + + def capture_config( + bridge_client: temporalio.bridge.client.Client, + config: temporalio.bridge.worker.WorkerConfig, + ): + captured_config.append(config) + return original_create(bridge_client, config) + + with mock.patch.object( + temporalio.bridge.worker.Worker, "create", side_effect=capture_config + ): + async with new_worker( + client, ExtStoreWorkflow, activities=[ext_store_activity] + ) as worker: + assert worker._storage_drivers == [driver1, driver2, driver3] + + assert len(captured_config) == 1 + assert captured_config[0].storage_drivers == {driver1.type(), driver3.type()} + + +async def test_worker_storage_drivers_empty_without_external_storage( + env: WorkflowEnvironment, +): + """Worker._storage_drivers is empty when the client has no ExternalStorage.""" + async with new_worker( + env.client, ExtStoreWorkflow, activities=[ext_store_activity] + ) as worker: + assert worker._storage_drivers == [] From ac842fd699ffa2f654125b46b13f359f8ced3784 Mon Sep 17 00:00:00 2001 From: Justin Anderson <44687433+jmaeagle99@users.noreply.github.com> Date: Mon, 23 Mar 2026 14:11:02 -0700 Subject: [PATCH 013/226] Emit workflow task duration information via logging (#1386) --- temporalio/bridge/worker.py | 35 +++-- temporalio/converter/_extstore.py | 85 +++++++++- temporalio/worker/_workflow.py | 76 ++++++++- tests/helpers/__init__.py | 13 +- tests/test_extstore.py | 6 + tests/worker/test_extstore.py | 247 +++++++++++++++++++++++++++++- 6 files changed, 441 insertions(+), 21 deletions(-) diff --git a/temporalio/bridge/worker.py b/temporalio/bridge/worker.py index c2512a28c..c8856125b 100644 --- a/temporalio/bridge/worker.py +++ b/temporalio/bridge/worker.py @@ -20,6 +20,7 @@ import temporalio.bridge.runtime import temporalio.bridge.temporal_sdk_bridge import temporalio.converter +import temporalio.converter._extstore from temporalio.api.common.v1.message_pb2 import Payload from temporalio.bridge._visitor import VisitorFunctions from temporalio.bridge.temporal_sdk_bridge import ( @@ -302,19 +303,33 @@ async def decode_activation( activation: temporalio.bridge.proto.workflow_activation.WorkflowActivation, data_converter: temporalio.converter.DataConverter, decode_headers: bool, -) -> None: - """Decode all payloads in the activation.""" - await CommandAwarePayloadVisitor( - skip_search_attributes=True, skip_headers=not decode_headers - ).visit(_Visitor(data_converter._decode_payload_sequence), activation) +) -> temporalio.converter._extstore.StorageOperationMetrics: + """Decode all payloads in the activation. + + Returns: + Metrics from any external storage retrieval operations that occurred. + """ + metrics = temporalio.converter._extstore.StorageOperationMetrics() + with metrics.track(): + await CommandAwarePayloadVisitor( + skip_search_attributes=True, skip_headers=not decode_headers + ).visit(_Visitor(data_converter._decode_payload_sequence), activation) + return metrics async def encode_completion( completion: temporalio.bridge.proto.workflow_completion.WorkflowActivationCompletion, data_converter: temporalio.converter.DataConverter, encode_headers: bool, -) -> None: - """Encode all payloads in the completion.""" - await CommandAwarePayloadVisitor( - skip_search_attributes=True, skip_headers=not encode_headers - ).visit(_Visitor(data_converter._encode_payload_sequence), completion) +) -> temporalio.converter._extstore.StorageOperationMetrics: + """Encode all payloads in the completion. + + Returns: + Metrics from any external storage store operations that occurred. + """ + metrics = temporalio.converter._extstore.StorageOperationMetrics() + with metrics.track(): + await CommandAwarePayloadVisitor( + skip_search_attributes=True, skip_headers=not encode_headers + ).visit(_Visitor(data_converter._encode_payload_sequence), completion) + return metrics diff --git a/temporalio/converter/_extstore.py b/temporalio/converter/_extstore.py index 614c8ac10..078d36d98 100644 --- a/temporalio/converter/_extstore.py +++ b/temporalio/converter/_extstore.py @@ -5,10 +5,14 @@ from __future__ import annotations import asyncio +import contextlib +import contextvars import dataclasses +import time from abc import ABC, abstractmethod -from collections.abc import Callable, Coroutine, Mapping, Sequence +from collections.abc import Callable, Coroutine, Generator, Mapping, Sequence from dataclasses import dataclass +from datetime import timedelta from typing import Any, ClassVar, TypeVar from typing_extensions import Self @@ -25,6 +29,40 @@ _REFERENCE_ENCODING = b"json/external-storage-reference" +@dataclass +class StorageOperationMetrics: + """Accumulates metrics from external storage operations.""" + + payload_count: int = 0 + """Number of payloads stored or retrieved externally.""" + + total_size: int = 0 + """Total size in bytes of externally stored/retrieved payloads.""" + + total_duration: timedelta = dataclasses.field(default_factory=timedelta) + """Wall-clock time spent on external storage operations.""" + + def record_batch(self, count: int, size: int, duration: timedelta) -> None: + """Record metrics from a batch of storage operations.""" + self.payload_count += count + self.total_size += size + self.total_duration += duration + + @contextlib.contextmanager + def track(self) -> Generator[Self, None, None]: + """Set this instance as the current metrics context and reset on exit.""" + token = _current_storage_metrics.set(self) + try: + yield self + finally: + _current_storage_metrics.reset(token) + + +_current_storage_metrics: contextvars.ContextVar[StorageOperationMetrics | None] = ( + contextvars.ContextVar("_current_storage_metrics", default=None) +) + + async def _gather_cancel_on_error( coros: Sequence[Coroutine[Any, Any, _T]], ) -> list[_T]: @@ -255,6 +293,7 @@ def _get_driver_by_name(self, name: str) -> StorageDriver: return driver async def _store_payload(self, payload: Payload) -> Payload: + start_time = time.monotonic() context = StorageDriverStoreContext(serialization_context=self._context) driver = self._select_driver(context, payload) @@ -265,6 +304,7 @@ async def _store_payload(self, payload: Payload) -> Payload: self._validate_claim_length(claims, expected=1, driver=driver) + external_size = payload.ByteSize() reference = _StorageReference( driver_name=driver.name(), driver_claim=claims[0], @@ -274,7 +314,10 @@ async def _store_payload(self, payload: Payload) -> Payload: raise ValueError( f"Failed to serialize storage reference for driver '{driver.name()}'" ) - reference_payload.external_payloads.add().size_bytes = payload.ByteSize() + reference_payload.external_payloads.add().size_bytes = external_size + + ExternalStorage._record_metrics(1, external_size, start_time) + return reference_payload async def _store_payloads(self, payloads: Payloads): @@ -289,6 +332,8 @@ async def _store_payload_sequence( if len(payloads) == 1: return [await self._store_payload(payloads[0])] + start_time = time.monotonic() + results = list(payloads) context = StorageDriverStoreContext(serialization_context=self._context) @@ -315,6 +360,8 @@ async def _store_payload_sequence( ] ) + external_count = 0 + external_size = 0 for (driver, indexed_payloads), claims in zip(driver_group_list, all_claims): indices = [idx for idx, _ in indexed_payloads] sizes = [p.ByteSize() for _, p in indexed_payloads] @@ -333,6 +380,11 @@ async def _store_payload_sequence( ) reference_payload.external_payloads.add().size_bytes = sizes[i] results[indices[i]] = reference_payload + external_size += sizes[i] + + external_count += len(claims) + + ExternalStorage._record_metrics(external_count, external_size, start_time) return results @@ -340,6 +392,8 @@ async def _retrieve_payload(self, payload: Payload) -> Payload: if len(payload.external_payloads) == 0: return payload + start_time = time.monotonic() + reference = self._claim_converter.from_payload(payload, _StorageReference) if not isinstance(reference, _StorageReference): return payload @@ -351,7 +405,11 @@ async def _retrieve_payload(self, payload: Payload) -> Payload: self._validate_payload_length(stored_payloads, expected=1, driver=driver) - return stored_payloads[0] + stored_payload = stored_payloads[0] + + ExternalStorage._record_metrics(1, stored_payload.ByteSize(), start_time) + + return stored_payload async def _retrieve_payloads(self, payloads: Payloads): stored_payloads = await self._retrieve_payload_sequence(payloads.payloads) @@ -362,11 +420,13 @@ async def _retrieve_payload_sequence( self, payloads: Sequence[Payload], ) -> list[Payload]: - results = list(payloads) - if len(payloads) == 1: return [await self._retrieve_payload(payloads[0])] + start_time = time.monotonic() + + results = list(payloads) + driver_claims: dict[StorageDriver, list[tuple[int, StorageDriverClaim]]] = {} for index, payload in enumerate(payloads): if len(payload.external_payloads) == 0: @@ -394,6 +454,8 @@ async def _retrieve_payload_sequence( ] ) + external_count = 0 + external_size = 0 for (driver, indexed_claims), stored_payloads in zip( driver_claim_list, all_stored ): @@ -407,6 +469,9 @@ async def _retrieve_payload_sequence( for idx, stored_payload in zip(indices, stored_payloads): stored_by_index[idx] = stored_payload + external_size += stored_payload.ByteSize() + + external_count += len(stored_payloads) retrieve_indices = sorted(stored_by_index.keys()) stored_list = [stored_by_index[idx] for idx in retrieve_indices] @@ -414,6 +479,8 @@ async def _retrieve_payload_sequence( for i, retrieved_payload in enumerate(stored_list): results[retrieve_indices[i]] = retrieved_payload + ExternalStorage._record_metrics(external_count, external_size, start_time) + return results def _validate_claim_length( @@ -431,3 +498,11 @@ def _validate_payload_length( raise ValueError( f"Driver '{driver.name()}' returned {len(payloads)} payloads, expected {expected}", ) + + @staticmethod + def _record_metrics(count: int, size: int, start_time: float): + metrics = _current_storage_metrics.get() + if metrics is not None: + metrics.record_batch( + count, size, timedelta(seconds=time.monotonic() - start_time) + ) diff --git a/temporalio/worker/_workflow.py b/temporalio/worker/_workflow.py index b305bd3e0..30d87227d 100644 --- a/temporalio/worker/_workflow.py +++ b/temporalio/worker/_workflow.py @@ -9,9 +9,10 @@ import os import sys import threading +import time from collections.abc import Awaitable, Callable, MutableMapping, Sequence from dataclasses import dataclass -from datetime import timezone +from datetime import timedelta, timezone from types import TracebackType import temporalio.api.common.v1 @@ -21,6 +22,7 @@ import temporalio.bridge.worker import temporalio.common import temporalio.converter +import temporalio.converter._extstore import temporalio.converter._payload_limits import temporalio.exceptions import temporalio.workflow @@ -255,6 +257,8 @@ async def _handle_activation( completion.successful.SetInParent() workflow = None data_converter = self._data_converter + task_start_time = time.monotonic() + download_metrics = temporalio.converter._extstore.StorageOperationMetrics() try: if LOG_PROTOS: logger.debug("Received workflow activation:\n%s", act) @@ -291,7 +295,7 @@ async def _handle_activation( workflow_context=workflow_context, ), ) - await temporalio.bridge.worker.decode_activation( + download_metrics = await temporalio.bridge.worker.decode_activation( act, data_converter, decode_headers=self._encode_headers, @@ -399,9 +403,10 @@ async def _handle_activation( ), ) + upload_metrics = temporalio.converter._extstore.StorageOperationMetrics() try: try: - await temporalio.bridge.worker.encode_completion( + upload_metrics = await temporalio.bridge.worker.encode_completion( completion, data_converter, encode_headers=self._encode_headers, @@ -429,6 +434,71 @@ async def _handle_activation( "Failed completing activation on workflow with run ID %s", act.run_id ) + # Log workflow task duration with external storage metrics + self._log_workflow_task_duration( + act, task_start_time, download_metrics, upload_metrics + ) + + @staticmethod + def _log_workflow_task_duration( + act: temporalio.bridge.proto.workflow_activation.WorkflowActivation, + task_start_time: float, + download_metrics: temporalio.converter._extstore.StorageOperationMetrics, + upload_metrics: temporalio.converter._extstore.StorageOperationMetrics, + ) -> None: + task_duration = timedelta(seconds=time.monotonic() - task_start_time) + + def _fmt_duration(td: timedelta) -> str: + secs = td.total_seconds() + if secs >= 1: + return f"{secs:.3f}s" + return f"{secs * 1000:.3f}ms" + + msg_details: dict[str, object] = { + "event_id": act.history_length, + "workflow_task_duration": _fmt_duration(task_duration), + } + extra: dict[str, object] = { + "event_id": act.history_length, + "workflow_task_duration": task_duration, + } + if download_metrics.payload_count > 0: + msg_details["payload_download_count"] = download_metrics.payload_count + msg_details["payload_download_size"] = download_metrics.total_size + msg_details["payload_download_duration"] = _fmt_duration( + download_metrics.total_duration + ) + extra["payload_download_count"] = download_metrics.payload_count + extra["payload_download_size"] = download_metrics.total_size + extra["payload_download_duration"] = download_metrics.total_duration + if upload_metrics.payload_count > 0: + msg_details["payload_upload_count"] = upload_metrics.payload_count + msg_details["payload_upload_size"] = upload_metrics.total_size + msg_details["payload_upload_duration"] = _fmt_duration( + upload_metrics.total_duration + ) + extra["payload_upload_count"] = upload_metrics.payload_count + extra["payload_upload_size"] = upload_metrics.total_size + extra["payload_upload_duration"] = upload_metrics.total_duration + if task_duration.total_seconds() > 10: + logger.warning( + "[TMPRL1104] Workflow task exceeded 10 seconds (%s)", + msg_details, + extra=extra, + ) + elif task_duration.total_seconds() > 5: + logger.info( + "[TMPRL1104] Workflow task exceeded 5 seconds (%s)", + msg_details, + extra=extra, + ) + else: + logger.debug( + "[TMPRL1104] Workflow task duration information (%s)", + msg_details, + extra=extra, + ) + async def _handle_cache_eviction( self, act: temporalio.bridge.proto.workflow_activation.WorkflowActivation, diff --git a/tests/helpers/__init__.py b/tests/helpers/__init__.py index b783b9003..d7012213a 100644 --- a/tests/helpers/__init__.py +++ b/tests/helpers/__init__.py @@ -422,12 +422,12 @@ def __init__(self) -> None: self.log_queue: queue.Queue[logging.LogRecord] = queue.Queue() @contextmanager - def logs_captured(self, *loggers: logging.Logger): + def logs_captured(self, *loggers: logging.Logger, level: int = logging.INFO): handler = logging.handlers.QueueHandler(self.log_queue) prev_levels = [l.level for l in loggers] for l in loggers: - l.setLevel(logging.INFO) + l.setLevel(level) l.addHandler(handler) try: yield self @@ -447,6 +447,15 @@ def find( return record return None + def find_all( + self, pred: Callable[[logging.LogRecord], bool] + ) -> list[logging.LogRecord]: + return [ + record + for record in cast(list[logging.LogRecord], self.log_queue.queue) + if pred(record) + ] + class LogHandler: @staticmethod diff --git a/tests/test_extstore.py b/tests/test_extstore.py index 8a8a8b6d6..7cff620ba 100644 --- a/tests/test_extstore.py +++ b/tests/test_extstore.py @@ -49,6 +49,9 @@ async def store( ] self._storage.update(entries) + # Small delay to ensure measurable duration even on low-resolution timers. + await asyncio.sleep(0.02) + return [StorageDriverClaim(claim_data={"key": key}) for key, _ in entries] async def retrieve( @@ -70,6 +73,9 @@ def parse_claim( payload.ParseFromString(self._storage[key]) return payload + # Small delay to ensure measurable duration even on low-resolution timers. + await asyncio.sleep(0.02) + return [parse_claim(claim) for claim in claims] diff --git a/tests/worker/test_extstore.py b/tests/worker/test_extstore.py index 44c5f5966..eb4270d08 100644 --- a/tests/worker/test_extstore.py +++ b/tests/worker/test_extstore.py @@ -1,4 +1,5 @@ import dataclasses +import logging import uuid from collections.abc import Sequence from dataclasses import dataclass @@ -11,6 +12,7 @@ import temporalio.bridge.client import temporalio.bridge.worker import temporalio.converter +import temporalio.worker._workflow from temporalio import activity, workflow from temporalio.api.common.v1 import Payload from temporalio.client import Client, WorkflowFailureError, WorkflowHandle @@ -25,7 +27,7 @@ from temporalio.exceptions import ActivityError, ApplicationError from temporalio.testing._workflow import WorkflowEnvironment from temporalio.worker import Replayer -from tests.helpers import assert_task_fail_eventually, new_worker +from tests.helpers import LogCapturer, assert_task_fail_eventually, new_worker from tests.test_extstore import InMemoryTestDriver @@ -614,3 +616,246 @@ async def test_worker_storage_drivers_empty_without_external_storage( env.client, ExtStoreWorkflow, activities=[ext_store_activity] ) as worker: assert worker._storage_drivers == [] + + +# --------------------------------------------------------------------------- +# TMPRL1104 workflow task duration logging +# --------------------------------------------------------------------------- + +_workflow_logger = logging.getLogger(temporalio.worker._workflow.__name__) + + +def _tmprl1104_records(capturer: LogCapturer) -> list[logging.LogRecord]: + """Return all TMPRL1104 log records from the capturer.""" + return capturer.find_all(lambda r: r.getMessage().startswith("[TMPRL1104]")) + + +async def _expected_payload_size( + converter: temporalio.converter.DataConverter, value: object +) -> int: + """Encode a value and return the protobuf ByteSize of the resulting payload.""" + payloads = converter.payload_converter.to_payloads([value]) + return payloads[0].ByteSize() + + +@workflow.defn +class SimpleWorkflow: + """Minimal workflow for testing logging without external storage.""" + + @workflow.run + async def run(self) -> str: + return "done" + + +async def test_tmprl1104_no_extstore(env: WorkflowEnvironment) -> None: + """Without external storage, TMPRL1104 logs contain duration but no + download/upload metrics.""" + with LogCapturer().logs_captured(_workflow_logger, level=logging.DEBUG) as capturer: + async with new_worker(env.client, SimpleWorkflow) as worker: + await env.client.execute_workflow( + SimpleWorkflow.run, + id=f"workflow-{uuid.uuid4()}", + task_queue=worker.task_queue, + ) + + records = _tmprl1104_records(capturer) + assert len(records) == 1 + record = records[0] + assert record.getMessage().startswith( + "[TMPRL1104] Workflow task duration information (" + ) + assert hasattr(record, "workflow_task_duration") + assert hasattr(record, "event_id") + # No external storage — download/upload fields must be absent + assert not hasattr(record, "payload_download_count") + assert not hasattr(record, "payload_download_size") + assert not hasattr(record, "payload_download_duration") + assert not hasattr(record, "payload_upload_count") + assert not hasattr(record, "payload_upload_size") + assert not hasattr(record, "payload_upload_duration") + + +async def test_tmprl1104_with_extstore_download(env: WorkflowEnvironment) -> None: + """When external storage decodes payloads, TMPRL1104 logs include download + metrics on the activation that retrieves them.""" + driver = InMemoryTestDriver() + data_converter = dataclasses.replace( + temporalio.converter.default(), + external_storage=ExternalStorage( + drivers=[driver], + payload_size_threshold=512, + ), + ) + client = await Client.connect( + env.client.service_client.config.target_host, + namespace=env.client.namespace, + data_converter=data_converter, + ) + + wf_input = ExtStoreWorkflowInput( + input_data="wi" * 512, # exceeds 512-byte threshold → stored externally + activity_input_size=10, + activity_output_size=10, + output_size=10, + ) + expected_input_size = await _expected_payload_size(data_converter, wf_input) + + with LogCapturer().logs_captured(_workflow_logger, level=logging.DEBUG) as capturer: + async with new_worker( + client, ExtStoreWorkflow, activities=[ext_store_activity] + ) as worker: + await client.execute_workflow( + ExtStoreWorkflow.run, + wf_input, + id=f"workflow-{uuid.uuid4()}", + task_queue=worker.task_queue, + ) + + records = _tmprl1104_records(capturer) + assert len(records) == 2 + + # WFT 1: retrieves the externalized workflow input + assert ( + records[0] + .getMessage() + .startswith("[TMPRL1104] Workflow task duration information (") + ) + assert getattr(records[0], "payload_download_count") == 1 + assert getattr(records[0], "payload_download_size") == expected_input_size + assert getattr(records[0], "payload_download_duration") > timedelta(0) + assert not hasattr(records[0], "payload_upload_count") + + # WFT 2: activity result is small — no external storage + assert ( + records[1] + .getMessage() + .startswith("[TMPRL1104] Workflow task duration information (") + ) + assert not hasattr(records[1], "payload_download_count") + assert not hasattr(records[1], "payload_upload_count") + + +async def test_tmprl1104_with_extstore_upload(env: WorkflowEnvironment) -> None: + """When external storage encodes payloads, TMPRL1104 logs include upload + metrics on the WFT that produces them.""" + driver = InMemoryTestDriver() + data_converter = dataclasses.replace( + temporalio.converter.default(), + external_storage=ExternalStorage( + drivers=[driver], + payload_size_threshold=512, + ), + ) + client = await Client.connect( + env.client.service_client.config.target_host, + namespace=env.client.namespace, + data_converter=data_converter, + ) + + wf_output = "wo" * 1024 # 2048 bytes → stored externally + expected_output_size = await _expected_payload_size(data_converter, wf_output) + + with LogCapturer().logs_captured(_workflow_logger, level=logging.DEBUG) as capturer: + async with new_worker( + client, ExtStoreWorkflow, activities=[ext_store_activity] + ) as worker: + await client.execute_workflow( + ExtStoreWorkflow.run, + ExtStoreWorkflowInput( + input_data="small", + activity_input_size=10, + activity_output_size=10, + output_size=2048, # large output → stored externally on completion + ), + id=f"workflow-{uuid.uuid4()}", + task_queue=worker.task_queue, + ) + + records = _tmprl1104_records(capturer) + assert len(records) == 2 + + # WFT 1: small input — no external storage + assert ( + records[0] + .getMessage() + .startswith("[TMPRL1104] Workflow task duration information (") + ) + assert not hasattr(records[0], "payload_download_count") + assert not hasattr(records[0], "payload_upload_count") + + # WFT 2: workflow returns large result → uploaded + assert ( + records[1] + .getMessage() + .startswith("[TMPRL1104] Workflow task duration information (") + ) + assert not hasattr(records[1], "payload_download_count") + assert getattr(records[1], "payload_upload_count") == 1 + assert getattr(records[1], "payload_upload_size") == expected_output_size + assert getattr(records[1], "payload_upload_duration") > timedelta(0) + + +async def test_tmprl1104_with_extstore_download_and_upload( + env: WorkflowEnvironment, +) -> None: + """When both download and upload happen across WFTs, TMPRL1104 logs include + both sets of metrics.""" + driver = InMemoryTestDriver() + data_converter = dataclasses.replace( + temporalio.converter.default(), + external_storage=ExternalStorage( + drivers=[driver], + payload_size_threshold=512, + ), + ) + client = await Client.connect( + env.client.service_client.config.target_host, + namespace=env.client.namespace, + data_converter=data_converter, + ) + + wf_input = ExtStoreWorkflowInput( + input_data="wi" * 512, # large input → download on first WFT + activity_input_size=10, + activity_output_size=10, + output_size=2048, # large output → upload on final WFT + ) + expected_input_size = await _expected_payload_size(data_converter, wf_input) + wf_output = "wo" * 1024 + expected_output_size = await _expected_payload_size(data_converter, wf_output) + + with LogCapturer().logs_captured(_workflow_logger, level=logging.DEBUG) as capturer: + async with new_worker( + client, ExtStoreWorkflow, activities=[ext_store_activity] + ) as worker: + await client.execute_workflow( + ExtStoreWorkflow.run, + wf_input, + id=f"workflow-{uuid.uuid4()}", + task_queue=worker.task_queue, + ) + + records = _tmprl1104_records(capturer) + assert len(records) == 2 + + # WFT 1: retrieves externalized workflow input + assert ( + records[0] + .getMessage() + .startswith("[TMPRL1104] Workflow task duration information (") + ) + assert getattr(records[0], "payload_download_count") == 1 + assert getattr(records[0], "payload_download_size") == expected_input_size + assert getattr(records[0], "payload_download_duration") > timedelta(0) + assert not hasattr(records[0], "payload_upload_count") + + # WFT 2: uploads externalized workflow result + assert ( + records[1] + .getMessage() + .startswith("[TMPRL1104] Workflow task duration information (") + ) + assert not hasattr(records[1], "payload_download_count") + assert getattr(records[1], "payload_upload_count") == 1 + assert getattr(records[1], "payload_upload_size") == expected_output_size + assert getattr(records[1], "payload_upload_duration") > timedelta(0) From 718266dce7153b5121ea8287b385b361241cee31 Mon Sep 17 00:00:00 2001 From: Spencer Judge Date: Tue, 24 Mar 2026 13:17:09 -0700 Subject: [PATCH 014/226] Create cloud-specific tests (#1389) --- .github/workflows/ci.yml | 52 ++++++++++++++++++++---- tests/test_client.py | 15 ------- tests/test_cloud.py | 88 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 131 insertions(+), 24 deletions(-) create mode 100644 tests/test_cloud.py diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d5d94839e..d1223cf44 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -26,7 +26,6 @@ jobs: - os: ubuntu-latest python: "3.14" docsTarget: true - cloudTestTarget: true openaiTestTarget: true clippyLinter: true - os: ubuntu-latest @@ -73,14 +72,6 @@ jobs: - if: ${{ !endsWith(matrix.os, '-arm') }} run: poe test ${{matrix.pytestExtraArgs}} -s --workflow-environment time-skipping --junit-xml=junit-xml/${{ matrix.python }}--${{ matrix.os }}--time-skipping.xml timeout-minutes: 10 - # Check cloud if proper target and not on fork - - if: ${{ matrix.cloudTestTarget && (github.event.pull_request.head.repo.full_name == '' || github.event.pull_request.head.repo.full_name == 'temporalio/sdk-python') }} - run: poe test ${{matrix.pytestExtraArgs}} -s -k test_cloud_client --junit-xml=junit-xml/${{ matrix.python }}--${{ matrix.os }}--cloud.xml - timeout-minutes: 10 - env: - TEMPORAL_CLIENT_CLOUD_API_KEY: ${{ secrets.TEMPORAL_CLIENT_CLOUD_API_KEY }} - TEMPORAL_CLIENT_CLOUD_API_VERSION: 2024-05-13-00 - TEMPORAL_CLIENT_CLOUD_NAMESPACE: sdk-ci.a2dd6 - if: ${{ matrix.openaiTestTarget && (github.event.pull_request.head.repo.full_name == '' || github.event.pull_request.head.repo.full_name == 'temporalio/sdk-python') }} run: poe test tests/contrib/openai_agents/test_openai.py ${{matrix.pytestExtraArgs}} -s --junit-xml=junit-xml/${{ matrix.python }}--${{ matrix.os }}--openai.xml timeout-minutes: 10 @@ -169,6 +160,49 @@ jobs: path: junit-xml retention-days: 14 + # Run tests against Temporal Cloud (skipped on forks) + cloud-test: + if: ${{ github.event.pull_request.head.repo.full_name == '' || github.event.pull_request.head.repo.full_name == 'temporalio/sdk-python' }} + timeout-minutes: 15 + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + submodules: recursive + - uses: dtolnay/rust-toolchain@stable + - uses: Swatinem/rust-cache@v2 + with: + workspaces: temporalio/bridge -> target + - uses: actions/setup-python@v5 + with: + python-version: "3.14" + - uses: arduino/setup-protoc@v3 + with: + # TODO(cretz): Can upgrade proto when https://github.com/arduino/setup-protoc/issues/99 fixed + version: "23.x" + repo-token: ${{ secrets.GITHUB_TOKEN }} + - uses: astral-sh/setup-uv@v5 + - run: uv tool install poethepoet + - run: uv sync --all-extras + - run: poe build-develop + - run: poe test -s tests/test_cloud.py --junit-xml=junit-xml/cloud.xml + timeout-minutes: 10 + env: + TEMPORAL_IS_CLOUD_TESTS: true + TEMPORAL_CLIENT_CLOUD_API_KEY: ${{ secrets.TEMPORAL_CLIENT_CLOUD_API_KEY }} + TEMPORAL_CLIENT_CLOUD_API_VERSION: 2024-05-13-00 + TEMPORAL_CLIENT_CLOUD_NAMESPACE: sdk-ci.a2dd6 + TEMPORAL_CLIENT_CLOUD_TARGET: sdk-ci.a2dd6.tmprl.cloud:7233 + TEMPORAL_CLIENT_CERT: ${{ secrets.TEMPORAL_CLIENT_CERT }} + TEMPORAL_CLIENT_KEY: ${{ secrets.TEMPORAL_CLIENT_KEY }} + - name: "Upload junit-xml artifacts" + uses: actions/upload-artifact@v4 + if: always() + with: + name: junit-xml--${{github.run_id}}--${{github.run_attempt}}--cloud + path: junit-xml + retention-days: 14 + # Runs the sdk features repo tests with this repo's current SDK code features-tests: uses: temporalio/features/.github/workflows/python.yaml@main diff --git a/tests/test_client.py b/tests/test_client.py index 833c97fb0..b8bebdaf7 100644 --- a/tests/test_client.py +++ b/tests/test_client.py @@ -18,7 +18,6 @@ import temporalio.common import temporalio.exceptions from temporalio import workflow -from temporalio.api.cloud.cloudservice.v1 import GetNamespaceRequest from temporalio.api.enums.v1 import ( CancelExternalWorkflowExecutionFailedCause, ContinueAsNewInitiator, @@ -42,7 +41,6 @@ BuildIdOpPromoteSetByBuildId, CancelWorkflowInput, Client, - CloudOperationsClient, Interceptor, OutboundInterceptor, QueryWorkflowInput, @@ -1481,19 +1479,6 @@ async def test_build_id_interactions(client: Client, env: WorkflowEnvironment): assert reachability.build_id_reachability["1.1"].task_queue_reachability[tq] == [] -async def test_cloud_client_simple(): - if "TEMPORAL_CLIENT_CLOUD_API_KEY" not in os.environ: - pytest.skip("No cloud API key") - client = await CloudOperationsClient.connect( - api_key=os.environ["TEMPORAL_CLIENT_CLOUD_API_KEY"], - version=os.environ["TEMPORAL_CLIENT_CLOUD_API_VERSION"], - ) - result = await client.cloud_service.get_namespace( - GetNamespaceRequest(namespace=os.environ["TEMPORAL_CLIENT_CLOUD_NAMESPACE"]) - ) - assert os.environ["TEMPORAL_CLIENT_CLOUD_NAMESPACE"] == result.namespace.namespace - - @workflow.defn class LastCompletionResultWorkflow: @workflow.run diff --git a/tests/test_cloud.py b/tests/test_cloud.py new file mode 100644 index 000000000..b701bdf94 --- /dev/null +++ b/tests/test_cloud.py @@ -0,0 +1,88 @@ +"""Tests that run against Temporal Cloud.""" + +import multiprocessing +import os +from collections.abc import AsyncGenerator, Iterator + +import pytest +import pytest_asyncio + +from temporalio.api.cloud.cloudservice.v1 import GetNamespaceRequest +from temporalio.client import Client, CloudOperationsClient +from temporalio.service import TLSConfig +from temporalio.testing import WorkflowEnvironment +from temporalio.worker import SharedStateManager +from tests.helpers.worker import ExternalPythonWorker, ExternalWorker + +# Skip entire module unless explicitly enabled +pytestmark = pytest.mark.skipif( + "TEMPORAL_IS_CLOUD_TESTS" not in os.environ, + reason="Cloud tests not enabled", +) + + +@pytest_asyncio.fixture(scope="module") # type: ignore[reportUntypedFunctionDecorator] +async def env() -> AsyncGenerator[WorkflowEnvironment, None]: + tls_config: bool | TLSConfig = True + client_cert = os.environ.get("TEMPORAL_CLIENT_CERT") + client_key = os.environ.get("TEMPORAL_CLIENT_KEY") + if client_cert and client_key: + tls_config = TLSConfig( + client_cert=client_cert.encode(), + client_private_key=client_key.encode(), + ) + client = await Client.connect( + os.environ["TEMPORAL_CLIENT_CLOUD_TARGET"], + namespace=os.environ["TEMPORAL_CLIENT_CLOUD_NAMESPACE"], + api_key=os.environ.get("TEMPORAL_CLIENT_CLOUD_API_KEY"), + tls=tls_config, + ) + env = WorkflowEnvironment.from_client(client) + yield env + await env.shutdown() + + +@pytest_asyncio.fixture # type: ignore[reportUntypedFunctionDecorator] +async def client(env: WorkflowEnvironment) -> Client: + return env.client + + +@pytest_asyncio.fixture(scope="module") # type: ignore[reportUntypedFunctionDecorator] +async def worker( + env: WorkflowEnvironment, +) -> AsyncGenerator[ExternalWorker, None]: + w = ExternalPythonWorker(env) + yield w + await w.close() + + +@pytest.fixture(scope="module") +def shared_state_manager() -> Iterator[SharedStateManager]: + mp_mgr = multiprocessing.Manager() + mgr = SharedStateManager.create_from_multiprocessing(mp_mgr) + try: + yield mgr + finally: + mp_mgr.shutdown() + + +# --- Cloud-specific tests --- + + +async def test_cloud_client_simple(): + client = await CloudOperationsClient.connect( + api_key=os.environ["TEMPORAL_CLIENT_CLOUD_API_KEY"], + version=os.environ["TEMPORAL_CLIENT_CLOUD_API_VERSION"], + ) + result = await client.cloud_service.get_namespace( + GetNamespaceRequest(namespace=os.environ["TEMPORAL_CLIENT_CLOUD_NAMESPACE"]) + ) + assert os.environ["TEMPORAL_CLIENT_CLOUD_NAMESPACE"] == result.namespace.namespace + + +# --- Delegated tests --- +# Import test functions to re-run them against cloud fixtures. + +from tests.worker.test_activity import ( # noqa: E402 + test_activity_info, # pyright: ignore[reportUnusedImport] # noqa: F401 +) From 37887856a21741b8305b1878f1d728da25167f57 Mon Sep 17 00:00:00 2001 From: Justin Anderson <44687433+jmaeagle99@users.noreply.github.com> Date: Tue, 24 Mar 2026 18:08:12 -0700 Subject: [PATCH 015/226] Concurrent payload visiting (#1344) --- scripts/gen_payload_visitor.py | 266 ++++++++++++---- temporalio/bridge/_visitor.py | 318 ++++++++++++++------ temporalio/bridge/worker.py | 10 +- temporalio/worker/_command_aware_visitor.py | 21 ++ temporalio/worker/_replayer.py | 1 + temporalio/worker/_worker.py | 16 +- temporalio/worker/_workflow.py | 8 + tests/worker/test_visitor.py | 70 ++++- 8 files changed, 559 insertions(+), 151 deletions(-) diff --git a/scripts/gen_payload_visitor.py b/scripts/gen_payload_visitor.py index eabfd9e6a..5b6f02396 100644 --- a/scripts/gen_payload_visitor.py +++ b/scripts/gen_payload_visitor.py @@ -1,7 +1,6 @@ import subprocess import sys from pathlib import Path -from typing import Optional from google.protobuf.descriptor import Descriptor, FieldDescriptor @@ -21,50 +20,109 @@ def name_for(desc: Descriptor) -> str: return desc.full_name.replace(".", "_") +# --------------------------------------------------------------------------- +# Emitters for the "multi-unit" case: accumulate coroutines into `coros` list +# and let the caller do a single asyncio.gather(*coros) at the end. +# --------------------------------------------------------------------------- + + def emit_loop( field_name: str, iter_expr: str, child_method: str, ) -> str: - # Helper to emit a for-loop over a collection with optional headers guard + # Emit a coros.extend() over a collection with optional skip guard if field_name == "headers": - return f"""\ - if not self.skip_headers: - for v in {iter_expr}: - await self._visit_{child_method}(fs, v)""" + return ( + " if not self.skip_headers:\n" + f" coros.extend(self._visit_{child_method}(fs, v) for v in {iter_expr})" + ) elif field_name == "search_attributes": - return f"""\ - if not self.skip_search_attributes: - for v in {iter_expr}: - await self._visit_{child_method}(fs, v)""" + return ( + " if not self.skip_search_attributes:\n" + f" coros.extend(self._visit_{child_method}(fs, v) for v in {iter_expr})" + ) else: - return f"""\ - for v in {iter_expr}: - await self._visit_{child_method}(fs, v)""" + return f" coros.extend(self._visit_{child_method}(fs, v) for v in {iter_expr})" def emit_singular( field_name: str, access_expr: str, child_method: str, presence_word: str | None ) -> str: - # Helper to emit a singular field visit with presence check and optional headers guard + # Emit a coros.append() with optional HasField check and skip guard if presence_word: if field_name == "headers": - return f"""\ - if not self.skip_headers: - {presence_word} o.HasField("{field_name}"): - await self._visit_{child_method}(fs, {access_expr})""" + return ( + " if not self.skip_headers:\n" + f' {presence_word} o.HasField("{field_name}"):\n' + f" coros.append(self._visit_{child_method}(fs, {access_expr}))" + ) else: - return f"""\ - {presence_word} o.HasField("{field_name}"): - await self._visit_{child_method}(fs, {access_expr})""" + return ( + f' {presence_word} o.HasField("{field_name}"):\n' + f" coros.append(self._visit_{child_method}(fs, {access_expr}))" + ) else: if field_name == "headers": - return f"""\ - if not self.skip_headers: - await self._visit_{child_method}(fs, {access_expr})""" + return ( + " if not self.skip_headers:\n" + f" coros.append(self._visit_{child_method}(fs, {access_expr}))" + ) else: - return f"""\ - await self._visit_{child_method}(fs, {access_expr})""" + return ( + f" coros.append(self._visit_{child_method}(fs, {access_expr}))" + ) + + +# --------------------------------------------------------------------------- +# Emitters for the "single-unit" case: emit a direct await (no list needed). +# --------------------------------------------------------------------------- + + +def emit_loop_direct( + field_name: str, + iter_expr: str, + child_method: str, +) -> str: + # Emit a direct await asyncio.gather(*[...]) with optional skip guard + if field_name == "headers": + return ( + " if not self.skip_headers:\n" + f" await asyncio.gather(*[self._visit_{child_method}(fs, v) for v in {iter_expr}])" + ) + elif field_name == "search_attributes": + return ( + " if not self.skip_search_attributes:\n" + f" await asyncio.gather(*[self._visit_{child_method}(fs, v) for v in {iter_expr}])" + ) + else: + return f" await asyncio.gather(*[self._visit_{child_method}(fs, v) for v in {iter_expr}])" + + +def emit_singular_direct( + field_name: str, access_expr: str, child_method: str, presence_word: str | None +) -> str: + # Emit a direct await self._visit_...() with optional HasField check and skip guard + if presence_word: + if field_name == "headers": + return ( + " if not self.skip_headers:\n" + f' {presence_word} o.HasField("{field_name}"):\n' + f" await self._visit_{child_method}(fs, {access_expr})" + ) + else: + return ( + f' {presence_word} o.HasField("{field_name}"):\n' + f" await self._visit_{child_method}(fs, {access_expr})" + ) + else: + if field_name == "headers": + return ( + " if not self.skip_headers:\n" + f" await self._visit_{child_method}(fs, {access_expr})" + ) + else: + return f" await self._visit_{child_method}(fs, {access_expr})" class VisitorGenerator: @@ -85,15 +143,18 @@ def generate(self, roots: list[Descriptor]) -> str: header = """ # This file is generated by gen_payload_visitor.py. Changes should be made there. import abc +import asyncio +from collections.abc import Coroutine from typing import Any, MutableSequence from temporalio.api.common.v1.message_pb2 import Payload class VisitorFunctions(abc.ABC): - \"\"\"Set of functions which can be called by the visitor. + \"\"\"Set of functions which can be called by the visitor. Allows handling payloads as a sequence. \"\"\" + @abc.abstractmethod async def visit_payload(self, payload: Payload) -> None: \"\"\"Called when encountering a single payload.\"\"\" @@ -104,21 +165,57 @@ async def visit_payloads(self, payloads: MutableSequence[Payload]) -> None: \"\"\"Called when encountering multiple payloads together.\"\"\" raise NotImplementedError() + +class _BoundedVisitorFunctions(VisitorFunctions): + \"\"\"Wraps VisitorFunctions to cap concurrent payload visits via a semaphore.\"\"\" + + def __init__(self, inner: VisitorFunctions, sem: asyncio.Semaphore) -> None: + self._inner = inner + self._sem = sem + + async def visit_payload(self, payload: Payload) -> None: + async with self._sem: + await self._inner.visit_payload(payload) + + async def visit_payloads(self, payloads: MutableSequence[Payload]) -> None: + async with self._sem: + await self._inner.visit_payloads(payloads) + + class PayloadVisitor: - \"\"\"A visitor for payloads. + \"\"\"A visitor for payloads. Applies a function to every payload in a tree of messages. \"\"\" + def __init__( - self, *, skip_search_attributes: bool = False, skip_headers: bool = False + self, + *, + skip_search_attributes: bool = False, + skip_headers: bool = False, + concurrency_limit: int = 1, ): - \"\"\"Creates a new payload visitor.\"\"\" + \"\"\"Creates a new payload visitor. + + Args: + skip_search_attributes: If True, search attributes are not visited. + skip_headers: If True, headers are not visited. + concurrency_limit: Maximum number of payload visits that may run + concurrently during a single call to visit(). Defaults to 1. + The semaphore is applied to each visit_payload / visit_payloads + call, so it limits I/O-level concurrency without risking + deadlock in the recursive traversal. + \"\"\" + if concurrency_limit < 1: + raise ValueError("concurrency_limit must be positive") self.skip_search_attributes = skip_search_attributes self.skip_headers = skip_headers + self._concurrency_limit = concurrency_limit async def visit( self, fs: VisitorFunctions, root: Any ) -> None: \"\"\"Visits the given root message with the given function.\"\"\" + fs = _BoundedVisitorFunctions(fs, asyncio.Semaphore(self._concurrency_limit)) method_name = "_visit_" + root.DESCRIPTOR.full_name.replace(".", "_") method = getattr(self, method_name, None) if method is not None: @@ -152,18 +249,16 @@ async def _visit_payload_container(self, fs, o): """, ] - def check_repeated(self, child_desc, field, iter_expr) -> str | None: - # Special case for repeated payloads, handle them directly + def _collect_repeated( + self, child_desc: Descriptor, field: FieldDescriptor, iter_expr: str + ) -> tuple | None: + """Collect emit item for a non-map repeated field. Returns tuple or None.""" if child_desc.full_name == Payload.DESCRIPTOR.full_name: - return emit_singular(field.name, iter_expr, "payload_container", None) + return ("singular", field.name, iter_expr, "payload_container", None) else: child_needed = self.walk(child_desc) if child_needed: - return emit_loop( - field.name, - iter_expr, - name_for(child_desc), - ) + return ("loop", field.name, iter_expr, name_for(child_desc)) else: return None @@ -177,11 +272,13 @@ def walk(self, desc: Descriptor) -> bool: has_payload = False self.in_progress.add(key) - lines: list[str] = [f" async def _visit_{name_for(desc)}(self, fs, o):"] - # If this is the SearchAttributes message, allow skipping - if desc.full_name == SearchAttributes.DESCRIPTOR.full_name: - lines.append(" if self.skip_search_attributes:") - lines.append(" return") + is_search_attrs = desc.full_name == SearchAttributes.DESCRIPTOR.full_name + + # Collect emit items before generating code. Each item is one of: + # ("loop", field_name, iter_expr, child_method) + # ("singular", field_name, access_expr, child_method, presence_word_or_None) + # ("oneof_group",[(field_name, access_expr, child_method, if_word), ...]) + emit_items: list = [] # Group fields by oneof to generate if/elif chains oneof_fields: dict[int, list[FieldDescriptor]] = {} @@ -217,8 +314,9 @@ def walk(self, desc: Descriptor) -> bool: child_needed = self.walk(child_desc) if child_needed: has_payload = True - lines.append( - emit_loop( + emit_items.append( + ( + "loop", field.name, f"o.{field.name}.values()", name_for(child_desc), @@ -234,34 +332,39 @@ def walk(self, desc: Descriptor) -> bool: child_needed = self.walk(child_desc) if child_needed: has_payload = True - lines.append( - emit_loop( + emit_items.append( + ( + "loop", field.name, f"o.{field.name}.keys()", name_for(child_desc), ) ) else: - child = self.check_repeated( + item = self._collect_repeated( field.message_type, field, f"o.{field.name}" ) - if child is not None: + if item is not None: has_payload = True - lines.append(child) + emit_items.append(item) else: child_desc = field.message_type child_has_payload = self.walk(child_desc) has_payload |= child_has_payload if child_has_payload: - lines.append( - emit_singular( - field.name, f"o.{field.name}", name_for(child_desc), "if" + emit_items.append( + ( + "singular", + field.name, + f"o.{field.name}", + name_for(child_desc), + "if", ) ) # Process oneof fields as if/elif chains for oneof_idx, fields in oneof_fields.items(): - oneof_lines = [] + group = [] first = True for field in fields: child_desc = field.message_type @@ -270,16 +373,61 @@ def walk(self, desc: Descriptor) -> bool: if child_has_payload: if_word = "if" if first else "elif" first = False - line = emit_singular( - field.name, f"o.{field.name}", name_for(child_desc), if_word + group.append( + (field.name, f"o.{field.name}", name_for(child_desc), if_word) ) - oneof_lines.append(line) - if oneof_lines: - lines.extend(oneof_lines) + if group: + emit_items.append(("oneof_group", group)) self.generated[key] = has_payload self.in_progress.discard(key) + if has_payload: + lines: list[str] = [f" async def _visit_{name_for(desc)}(self, fs, o):"] + if is_search_attrs: + lines.append(" if self.skip_search_attributes:") + lines.append(" return") + + # Use coros accumulation only when there are multiple independent units; + # a single unit is emitted with a direct await (no list overhead). + use_coros = len(emit_items) > 1 + if use_coros: + lines.append(" coros: list[Coroutine[Any, Any, None]] = []") + + for item in emit_items: + if item[0] == "loop": + _, field_name, iter_expr, child_method = item + lines.append( + emit_loop(field_name, iter_expr, child_method) + if use_coros + else emit_loop_direct(field_name, iter_expr, child_method) + ) + elif item[0] == "singular": + _, field_name, access_expr, child_method, presence_word = item + lines.append( + emit_singular( + field_name, access_expr, child_method, presence_word + ) + if use_coros + else emit_singular_direct( + field_name, access_expr, child_method, presence_word + ) + ) + else: # oneof_group + for field_name, access_expr, child_method, presence_word in item[1]: + lines.append( + emit_singular( + field_name, access_expr, child_method, presence_word + ) + if use_coros + else emit_singular_direct( + field_name, access_expr, child_method, presence_word + ) + ) + + if use_coros: + lines.append(" await asyncio.gather(*coros)") + self.methods.append("\n".join(lines) + "\n") return has_payload diff --git a/temporalio/bridge/_visitor.py b/temporalio/bridge/_visitor.py index 16876fb59..6f596bc15 100644 --- a/temporalio/bridge/_visitor.py +++ b/temporalio/bridge/_visitor.py @@ -1,5 +1,7 @@ # This file is generated by gen_payload_visitor.py. Changes should be made there. import abc +import asyncio +from collections.abc import Coroutine from typing import Any, MutableSequence from temporalio.api.common.v1.message_pb2 import Payload @@ -21,20 +23,54 @@ async def visit_payloads(self, payloads: MutableSequence[Payload]) -> None: raise NotImplementedError() +class _BoundedVisitorFunctions(VisitorFunctions): + """Wraps VisitorFunctions to cap concurrent payload visits via a semaphore.""" + + def __init__(self, inner: VisitorFunctions, sem: asyncio.Semaphore) -> None: + self._inner = inner + self._sem = sem + + async def visit_payload(self, payload: Payload) -> None: + async with self._sem: + await self._inner.visit_payload(payload) + + async def visit_payloads(self, payloads: MutableSequence[Payload]) -> None: + async with self._sem: + await self._inner.visit_payloads(payloads) + + class PayloadVisitor: """A visitor for payloads. Applies a function to every payload in a tree of messages. """ def __init__( - self, *, skip_search_attributes: bool = False, skip_headers: bool = False + self, + *, + skip_search_attributes: bool = False, + skip_headers: bool = False, + concurrency_limit: int = 1, ): - """Creates a new payload visitor.""" + """Creates a new payload visitor. + + Args: + skip_search_attributes: If True, search attributes are not visited. + skip_headers: If True, headers are not visited. + concurrency_limit: Maximum number of payload visits that may run + concurrently during a single call to visit(). Defaults to 1. + The semaphore is applied to each visit_payload / visit_payloads + call, so it limits I/O-level concurrency without risking + deadlock in the recursive traversal. + """ + if concurrency_limit < 1: + raise ValueError("concurrency_limit must be positive") self.skip_search_attributes = skip_search_attributes self.skip_headers = skip_headers + self._concurrency_limit = concurrency_limit async def visit(self, fs: VisitorFunctions, root: Any) -> None: """Visits the given root message with the given function.""" + fs = _BoundedVisitorFunctions(fs, asyncio.Semaphore(self._concurrency_limit)) method_name = "_visit_" + root.DESCRIPTOR.full_name.replace(".", "_") method = getattr(self, method_name, None) if method is not None: @@ -72,66 +108,104 @@ async def _visit_temporal_api_failure_v1_ResetWorkflowFailureInfo(self, fs, o): ) async def _visit_temporal_api_failure_v1_Failure(self, fs, o): + coros: list[Coroutine[Any, Any, None]] = [] if o.HasField("encoded_attributes"): - await self._visit_temporal_api_common_v1_Payload(fs, o.encoded_attributes) + coros.append( + self._visit_temporal_api_common_v1_Payload(fs, o.encoded_attributes) + ) if o.HasField("cause"): - await self._visit_temporal_api_failure_v1_Failure(fs, o.cause) + coros.append(self._visit_temporal_api_failure_v1_Failure(fs, o.cause)) if o.HasField("application_failure_info"): - await self._visit_temporal_api_failure_v1_ApplicationFailureInfo( - fs, o.application_failure_info + coros.append( + self._visit_temporal_api_failure_v1_ApplicationFailureInfo( + fs, o.application_failure_info + ) ) elif o.HasField("timeout_failure_info"): - await self._visit_temporal_api_failure_v1_TimeoutFailureInfo( - fs, o.timeout_failure_info + coros.append( + self._visit_temporal_api_failure_v1_TimeoutFailureInfo( + fs, o.timeout_failure_info + ) ) elif o.HasField("canceled_failure_info"): - await self._visit_temporal_api_failure_v1_CanceledFailureInfo( - fs, o.canceled_failure_info + coros.append( + self._visit_temporal_api_failure_v1_CanceledFailureInfo( + fs, o.canceled_failure_info + ) ) elif o.HasField("reset_workflow_failure_info"): - await self._visit_temporal_api_failure_v1_ResetWorkflowFailureInfo( - fs, o.reset_workflow_failure_info + coros.append( + self._visit_temporal_api_failure_v1_ResetWorkflowFailureInfo( + fs, o.reset_workflow_failure_info + ) ) + await asyncio.gather(*coros) async def _visit_temporal_api_common_v1_Memo(self, fs, o): - for v in o.fields.values(): - await self._visit_temporal_api_common_v1_Payload(fs, v) + await asyncio.gather( + *[ + self._visit_temporal_api_common_v1_Payload(fs, v) + for v in o.fields.values() + ] + ) async def _visit_temporal_api_common_v1_SearchAttributes(self, fs, o): if self.skip_search_attributes: return - for v in o.indexed_fields.values(): - await self._visit_temporal_api_common_v1_Payload(fs, v) + await asyncio.gather( + *[ + self._visit_temporal_api_common_v1_Payload(fs, v) + for v in o.indexed_fields.values() + ] + ) async def _visit_coresdk_workflow_activation_InitializeWorkflow(self, fs, o): - await self._visit_payload_container(fs, o.arguments) + coros: list[Coroutine[Any, Any, None]] = [] + coros.append(self._visit_payload_container(fs, o.arguments)) if not self.skip_headers: - for v in o.headers.values(): - await self._visit_temporal_api_common_v1_Payload(fs, v) + coros.extend( + self._visit_temporal_api_common_v1_Payload(fs, v) + for v in o.headers.values() + ) if o.HasField("continued_failure"): - await self._visit_temporal_api_failure_v1_Failure(fs, o.continued_failure) + coros.append( + self._visit_temporal_api_failure_v1_Failure(fs, o.continued_failure) + ) if o.HasField("last_completion_result"): - await self._visit_temporal_api_common_v1_Payloads( - fs, o.last_completion_result + coros.append( + self._visit_temporal_api_common_v1_Payloads( + fs, o.last_completion_result + ) ) if o.HasField("memo"): - await self._visit_temporal_api_common_v1_Memo(fs, o.memo) + coros.append(self._visit_temporal_api_common_v1_Memo(fs, o.memo)) if o.HasField("search_attributes"): - await self._visit_temporal_api_common_v1_SearchAttributes( - fs, o.search_attributes + coros.append( + self._visit_temporal_api_common_v1_SearchAttributes( + fs, o.search_attributes + ) ) + await asyncio.gather(*coros) async def _visit_coresdk_workflow_activation_QueryWorkflow(self, fs, o): - await self._visit_payload_container(fs, o.arguments) + coros: list[Coroutine[Any, Any, None]] = [] + coros.append(self._visit_payload_container(fs, o.arguments)) if not self.skip_headers: - for v in o.headers.values(): - await self._visit_temporal_api_common_v1_Payload(fs, v) + coros.extend( + self._visit_temporal_api_common_v1_Payload(fs, v) + for v in o.headers.values() + ) + await asyncio.gather(*coros) async def _visit_coresdk_workflow_activation_SignalWorkflow(self, fs, o): - await self._visit_payload_container(fs, o.input) + coros: list[Coroutine[Any, Any, None]] = [] + coros.append(self._visit_payload_container(fs, o.input)) if not self.skip_headers: - for v in o.headers.values(): - await self._visit_temporal_api_common_v1_Payload(fs, v) + coros.extend( + self._visit_temporal_api_common_v1_Payload(fs, v) + for v in o.headers.values() + ) + await asyncio.gather(*coros) async def _visit_coresdk_activity_result_Success(self, fs, o): if o.HasField("result"): @@ -210,10 +284,14 @@ async def _visit_coresdk_workflow_activation_ResolveRequestCancelExternalWorkflo await self._visit_temporal_api_failure_v1_Failure(fs, o.failure) async def _visit_coresdk_workflow_activation_DoUpdate(self, fs, o): - await self._visit_payload_container(fs, o.input) + coros: list[Coroutine[Any, Any, None]] = [] + coros.append(self._visit_payload_container(fs, o.input)) if not self.skip_headers: - for v in o.headers.values(): - await self._visit_temporal_api_common_v1_Payload(fs, v) + coros.extend( + self._visit_temporal_api_common_v1_Payload(fs, v) + for v in o.headers.values() + ) + await asyncio.gather(*coros) async def _visit_coresdk_workflow_activation_ResolveNexusOperationStart( self, fs, o @@ -280,20 +358,30 @@ async def _visit_coresdk_workflow_activation_WorkflowActivationJob(self, fs, o): ) async def _visit_coresdk_workflow_activation_WorkflowActivation(self, fs, o): - for v in o.jobs: - await self._visit_coresdk_workflow_activation_WorkflowActivationJob(fs, v) + await asyncio.gather( + *[ + self._visit_coresdk_workflow_activation_WorkflowActivationJob(fs, v) + for v in o.jobs + ] + ) async def _visit_temporal_api_sdk_v1_UserMetadata(self, fs, o): + coros: list[Coroutine[Any, Any, None]] = [] if o.HasField("summary"): - await self._visit_temporal_api_common_v1_Payload(fs, o.summary) + coros.append(self._visit_temporal_api_common_v1_Payload(fs, o.summary)) if o.HasField("details"): - await self._visit_temporal_api_common_v1_Payload(fs, o.details) + coros.append(self._visit_temporal_api_common_v1_Payload(fs, o.details)) + await asyncio.gather(*coros) async def _visit_coresdk_workflow_commands_ScheduleActivity(self, fs, o): + coros: list[Coroutine[Any, Any, None]] = [] if not self.skip_headers: - for v in o.headers.values(): - await self._visit_temporal_api_common_v1_Payload(fs, v) - await self._visit_payload_container(fs, o.arguments) + coros.extend( + self._visit_temporal_api_common_v1_Payload(fs, v) + for v in o.headers.values() + ) + coros.append(self._visit_payload_container(fs, o.arguments)) + await asyncio.gather(*coros) async def _visit_coresdk_workflow_commands_QuerySuccess(self, fs, o): if o.HasField("response"): @@ -316,42 +404,64 @@ async def _visit_coresdk_workflow_commands_FailWorkflowExecution(self, fs, o): async def _visit_coresdk_workflow_commands_ContinueAsNewWorkflowExecution( self, fs, o ): - await self._visit_payload_container(fs, o.arguments) - for v in o.memo.values(): - await self._visit_temporal_api_common_v1_Payload(fs, v) + coros: list[Coroutine[Any, Any, None]] = [] + coros.append(self._visit_payload_container(fs, o.arguments)) + coros.extend( + self._visit_temporal_api_common_v1_Payload(fs, v) for v in o.memo.values() + ) if not self.skip_headers: - for v in o.headers.values(): - await self._visit_temporal_api_common_v1_Payload(fs, v) + coros.extend( + self._visit_temporal_api_common_v1_Payload(fs, v) + for v in o.headers.values() + ) if o.HasField("search_attributes"): - await self._visit_temporal_api_common_v1_SearchAttributes( - fs, o.search_attributes + coros.append( + self._visit_temporal_api_common_v1_SearchAttributes( + fs, o.search_attributes + ) ) + await asyncio.gather(*coros) async def _visit_coresdk_workflow_commands_StartChildWorkflowExecution(self, fs, o): - await self._visit_payload_container(fs, o.input) + coros: list[Coroutine[Any, Any, None]] = [] + coros.append(self._visit_payload_container(fs, o.input)) if not self.skip_headers: - for v in o.headers.values(): - await self._visit_temporal_api_common_v1_Payload(fs, v) - for v in o.memo.values(): - await self._visit_temporal_api_common_v1_Payload(fs, v) + coros.extend( + self._visit_temporal_api_common_v1_Payload(fs, v) + for v in o.headers.values() + ) + coros.extend( + self._visit_temporal_api_common_v1_Payload(fs, v) for v in o.memo.values() + ) if o.HasField("search_attributes"): - await self._visit_temporal_api_common_v1_SearchAttributes( - fs, o.search_attributes + coros.append( + self._visit_temporal_api_common_v1_SearchAttributes( + fs, o.search_attributes + ) ) + await asyncio.gather(*coros) async def _visit_coresdk_workflow_commands_SignalExternalWorkflowExecution( self, fs, o ): - await self._visit_payload_container(fs, o.args) + coros: list[Coroutine[Any, Any, None]] = [] + coros.append(self._visit_payload_container(fs, o.args)) if not self.skip_headers: - for v in o.headers.values(): - await self._visit_temporal_api_common_v1_Payload(fs, v) + coros.extend( + self._visit_temporal_api_common_v1_Payload(fs, v) + for v in o.headers.values() + ) + await asyncio.gather(*coros) async def _visit_coresdk_workflow_commands_ScheduleLocalActivity(self, fs, o): + coros: list[Coroutine[Any, Any, None]] = [] if not self.skip_headers: - for v in o.headers.values(): - await self._visit_temporal_api_common_v1_Payload(fs, v) - await self._visit_payload_container(fs, o.arguments) + coros.extend( + self._visit_temporal_api_common_v1_Payload(fs, v) + for v in o.headers.values() + ) + coros.append(self._visit_payload_container(fs, o.arguments)) + await asyncio.gather(*coros) async def _visit_coresdk_workflow_commands_UpsertWorkflowSearchAttributes( self, fs, o @@ -376,60 +486,92 @@ async def _visit_coresdk_workflow_commands_ScheduleNexusOperation(self, fs, o): await self._visit_temporal_api_common_v1_Payload(fs, o.input) async def _visit_coresdk_workflow_commands_WorkflowCommand(self, fs, o): + coros: list[Coroutine[Any, Any, None]] = [] if o.HasField("user_metadata"): - await self._visit_temporal_api_sdk_v1_UserMetadata(fs, o.user_metadata) + coros.append( + self._visit_temporal_api_sdk_v1_UserMetadata(fs, o.user_metadata) + ) if o.HasField("schedule_activity"): - await self._visit_coresdk_workflow_commands_ScheduleActivity( - fs, o.schedule_activity + coros.append( + self._visit_coresdk_workflow_commands_ScheduleActivity( + fs, o.schedule_activity + ) ) elif o.HasField("respond_to_query"): - await self._visit_coresdk_workflow_commands_QueryResult( - fs, o.respond_to_query + coros.append( + self._visit_coresdk_workflow_commands_QueryResult( + fs, o.respond_to_query + ) ) elif o.HasField("complete_workflow_execution"): - await self._visit_coresdk_workflow_commands_CompleteWorkflowExecution( - fs, o.complete_workflow_execution + coros.append( + self._visit_coresdk_workflow_commands_CompleteWorkflowExecution( + fs, o.complete_workflow_execution + ) ) elif o.HasField("fail_workflow_execution"): - await self._visit_coresdk_workflow_commands_FailWorkflowExecution( - fs, o.fail_workflow_execution + coros.append( + self._visit_coresdk_workflow_commands_FailWorkflowExecution( + fs, o.fail_workflow_execution + ) ) elif o.HasField("continue_as_new_workflow_execution"): - await self._visit_coresdk_workflow_commands_ContinueAsNewWorkflowExecution( - fs, o.continue_as_new_workflow_execution + coros.append( + self._visit_coresdk_workflow_commands_ContinueAsNewWorkflowExecution( + fs, o.continue_as_new_workflow_execution + ) ) elif o.HasField("start_child_workflow_execution"): - await self._visit_coresdk_workflow_commands_StartChildWorkflowExecution( - fs, o.start_child_workflow_execution + coros.append( + self._visit_coresdk_workflow_commands_StartChildWorkflowExecution( + fs, o.start_child_workflow_execution + ) ) elif o.HasField("signal_external_workflow_execution"): - await self._visit_coresdk_workflow_commands_SignalExternalWorkflowExecution( - fs, o.signal_external_workflow_execution + coros.append( + self._visit_coresdk_workflow_commands_SignalExternalWorkflowExecution( + fs, o.signal_external_workflow_execution + ) ) elif o.HasField("schedule_local_activity"): - await self._visit_coresdk_workflow_commands_ScheduleLocalActivity( - fs, o.schedule_local_activity + coros.append( + self._visit_coresdk_workflow_commands_ScheduleLocalActivity( + fs, o.schedule_local_activity + ) ) elif o.HasField("upsert_workflow_search_attributes"): - await self._visit_coresdk_workflow_commands_UpsertWorkflowSearchAttributes( - fs, o.upsert_workflow_search_attributes + coros.append( + self._visit_coresdk_workflow_commands_UpsertWorkflowSearchAttributes( + fs, o.upsert_workflow_search_attributes + ) ) elif o.HasField("modify_workflow_properties"): - await self._visit_coresdk_workflow_commands_ModifyWorkflowProperties( - fs, o.modify_workflow_properties + coros.append( + self._visit_coresdk_workflow_commands_ModifyWorkflowProperties( + fs, o.modify_workflow_properties + ) ) elif o.HasField("update_response"): - await self._visit_coresdk_workflow_commands_UpdateResponse( - fs, o.update_response + coros.append( + self._visit_coresdk_workflow_commands_UpdateResponse( + fs, o.update_response + ) ) elif o.HasField("schedule_nexus_operation"): - await self._visit_coresdk_workflow_commands_ScheduleNexusOperation( - fs, o.schedule_nexus_operation + coros.append( + self._visit_coresdk_workflow_commands_ScheduleNexusOperation( + fs, o.schedule_nexus_operation + ) ) + await asyncio.gather(*coros) async def _visit_coresdk_workflow_completion_Success(self, fs, o): - for v in o.commands: - await self._visit_coresdk_workflow_commands_WorkflowCommand(fs, v) + await asyncio.gather( + *[ + self._visit_coresdk_workflow_commands_WorkflowCommand(fs, v) + for v in o.commands + ] + ) async def _visit_coresdk_workflow_completion_Failure(self, fs, o): if o.HasField("failure"): diff --git a/temporalio/bridge/worker.py b/temporalio/bridge/worker.py index c8856125b..297765be0 100644 --- a/temporalio/bridge/worker.py +++ b/temporalio/bridge/worker.py @@ -303,6 +303,7 @@ async def decode_activation( activation: temporalio.bridge.proto.workflow_activation.WorkflowActivation, data_converter: temporalio.converter.DataConverter, decode_headers: bool, + concurrency_limit: int, ) -> temporalio.converter._extstore.StorageOperationMetrics: """Decode all payloads in the activation. @@ -312,7 +313,9 @@ async def decode_activation( metrics = temporalio.converter._extstore.StorageOperationMetrics() with metrics.track(): await CommandAwarePayloadVisitor( - skip_search_attributes=True, skip_headers=not decode_headers + skip_search_attributes=True, + skip_headers=not decode_headers, + concurrency_limit=concurrency_limit, ).visit(_Visitor(data_converter._decode_payload_sequence), activation) return metrics @@ -321,6 +324,7 @@ async def encode_completion( completion: temporalio.bridge.proto.workflow_completion.WorkflowActivationCompletion, data_converter: temporalio.converter.DataConverter, encode_headers: bool, + concurrency_limit: int, ) -> temporalio.converter._extstore.StorageOperationMetrics: """Encode all payloads in the completion. @@ -330,6 +334,8 @@ async def encode_completion( metrics = temporalio.converter._extstore.StorageOperationMetrics() with metrics.track(): await CommandAwarePayloadVisitor( - skip_search_attributes=True, skip_headers=not encode_headers + skip_search_attributes=True, + skip_headers=not encode_headers, + concurrency_limit=concurrency_limit, ).visit(_Visitor(data_converter._encode_payload_sequence), completion) return metrics diff --git a/temporalio/worker/_command_aware_visitor.py b/temporalio/worker/_command_aware_visitor.py index 2d7f3990b..327f8c68c 100644 --- a/temporalio/worker/_command_aware_visitor.py +++ b/temporalio/worker/_command_aware_visitor.py @@ -45,6 +45,27 @@ class CommandAwarePayloadVisitor(PayloadVisitor): activation jobs that have both a 'seq' field and payloads to visit. """ + def __init__( + self, + *, + skip_search_attributes: bool = False, + skip_headers: bool = False, + concurrency_limit: int = 1, + ) -> None: + """Creates a new command-aware payload visitor. + + Args: + skip_search_attributes: If True, search attributes are not visited. + skip_headers: If True, headers are not visited. + concurrency_limit: Maximum number of payload visits that may run + concurrently during a single call to visit(). Defaults to 1. + """ + super().__init__( + skip_search_attributes=skip_search_attributes, + skip_headers=skip_headers, + concurrency_limit=concurrency_limit, + ) + # Workflow commands with payloads async def _visit_coresdk_workflow_commands_ScheduleActivity( self, fs: VisitorFunctions, o: ScheduleActivity diff --git a/temporalio/worker/_replayer.py b/temporalio/worker/_replayer.py index 53af4aec5..30a0f35df 100644 --- a/temporalio/worker/_replayer.py +++ b/temporalio/worker/_replayer.py @@ -268,6 +268,7 @@ def on_eviction_hook( "header_codec_behavior", HeaderCodecBehavior.NO_CODEC ) != HeaderCodecBehavior.NO_CODEC, + max_workflow_task_payload_concurrency=1, ) external_storage = data_converter.external_storage storage_driver_types = ( diff --git a/temporalio/worker/_worker.py b/temporalio/worker/_worker.py index cf805a1be..0baccbe95 100644 --- a/temporalio/worker/_worker.py +++ b/temporalio/worker/_worker.py @@ -36,7 +36,7 @@ from ._nexus import _NexusWorker from ._plugin import Plugin from ._tuning import WorkerTuner -from ._workflow import _WorkflowWorker +from ._workflow import _DEFAULT_WORKFLOW_TASK_PAYLOAD_CONCURRENCY, _WorkflowWorker from ._workflow_instance import UnsandboxedWorkflowRunner, WorkflowRunner from .workflow_sandbox import SandboxedWorkflowRunner @@ -142,6 +142,7 @@ def __init__( maximum=5 ), disable_payload_error_limit: bool = False, + max_workflow_task_payload_concurrency: int = _DEFAULT_WORKFLOW_TASK_PAYLOAD_CONCURRENCY, ) -> None: """Create a worker to process workflows and/or activities. @@ -316,6 +317,10 @@ def __init__( and cause a task failure if the size limit is exceeded. The default is False. See https://docs.temporal.io/troubleshooting/blob-size-limit-error for more details. + max_workflow_task_payload_concurrency: Maximum number of payload + operations (codec encode/decode, external storage I/O, etc.) + that may run concurrently within a single workflow task + activation. Defaults to 1. WARNING: This setting is experimental. """ config = WorkerConfig( @@ -361,6 +366,7 @@ def __init__( activity_task_poller_behavior=activity_task_poller_behavior, nexus_task_poller_behavior=nexus_task_poller_behavior, disable_payload_error_limit=disable_payload_error_limit, + max_workflow_task_payload_concurrency=max_workflow_task_payload_concurrency, ) plugins_from_client = cast( @@ -414,6 +420,12 @@ def _init_from_config(self, client: temporalio.client.Client, config: WorkerConf raise ValueError( "default_versioning_behavior must be UNSPECIFIED when use_worker_versioning is False" ) + max_workflow_task_payload_concurrency = config.get( + "max_workflow_task_payload_concurrency", + _DEFAULT_WORKFLOW_TASK_PAYLOAD_CONCURRENCY, + ) + if max_workflow_task_payload_concurrency < 1: + raise ValueError("max_workflow_task_payload_concurrency must be positive") # Prepend applicable client interceptors to the given ones client_config = config["client"].config(active_config=True) # type: ignore[reportTypedDictNotRequiredAccess] @@ -518,6 +530,7 @@ def check_activity(activity: str): assert_local_activity_valid=check_activity, encode_headers=client_config["header_codec_behavior"] != HeaderCodecBehavior.NO_CODEC, + max_workflow_task_payload_concurrency=max_workflow_task_payload_concurrency, ) tuner = config.get("tuner") @@ -964,6 +977,7 @@ class WorkerConfig(TypedDict, total=False): activity_task_poller_behavior: PollerBehavior nexus_task_poller_behavior: PollerBehavior disable_payload_error_limit: bool + max_workflow_task_payload_concurrency: int def _warn_if_activity_executor_max_workers_is_inconsistent( diff --git a/temporalio/worker/_workflow.py b/temporalio/worker/_workflow.py index 30d87227d..82bdefdc1 100644 --- a/temporalio/worker/_workflow.py +++ b/temporalio/worker/_workflow.py @@ -47,6 +47,8 @@ # Set to true to log all activations and completions LOG_PROTOS = False +_DEFAULT_WORKFLOW_TASK_PAYLOAD_CONCURRENCY: int = 1 + class _WorkflowWorker: # type:ignore[reportUnusedClass] def __init__( @@ -74,6 +76,7 @@ def __init__( should_enforce_versioning_behavior: bool, assert_local_activity_valid: Callable[[str], None], encode_headers: bool, + max_workflow_task_payload_concurrency: int, ) -> None: self._bridge_worker = bridge_worker self._namespace = namespace @@ -112,6 +115,9 @@ def __init__( self._on_eviction_hook = on_eviction_hook self._disable_safe_eviction = disable_safe_eviction self._encode_headers = encode_headers + self._max_workflow_task_payload_concurrency = ( + max_workflow_task_payload_concurrency + ) self._throw_after_activation: Exception | None = None # If there's a debug mode or a truthy TEMPORAL_DEBUG env var, disable @@ -299,6 +305,7 @@ async def _handle_activation( act, data_converter, decode_headers=self._encode_headers, + concurrency_limit=self._max_workflow_task_payload_concurrency, ) if not workflow: assert init_job @@ -410,6 +417,7 @@ async def _handle_activation( completion, data_converter, encode_headers=self._encode_headers, + concurrency_limit=self._max_workflow_task_payload_concurrency, ) except temporalio.converter._payload_limits._PayloadSizeError as err: logger.warning(err.message) diff --git a/tests/worker/test_visitor.py b/tests/worker/test_visitor.py index 5604b8542..9d8463015 100644 --- a/tests/worker/test_visitor.py +++ b/tests/worker/test_visitor.py @@ -1,4 +1,6 @@ +import asyncio import dataclasses +import time from collections.abc import MutableSequence from google.protobuf.duration_pb2 import Duration @@ -205,6 +207,72 @@ async def test_visit_payloads_on_other_commands(): assert ur.completed.metadata["visited"] +async def test_concurrent_throughput(): + """Demonstrate that concurrent visitation is faster than serialized for I/O-bound codecs.""" + N_CMDS = 10 + N_ARGS = 5 + SLEEP = 0.02 + + class SlowVisitor(VisitorFunctions): + def __init__(self, *, blocking: bool = False): + self.visit_count = 0 + self._active = 0 + self.max_concurrent = 0 + self._blocking = blocking + + async def visit_payload(self, payload: Payload) -> None: + return await self._visit(1) + + async def visit_payloads(self, payloads: MutableSequence[Payload]) -> None: + return await self._visit(len(payloads)) + + async def _visit(self, count: int) -> None: + self._active += 1 + self.max_concurrent = max(self.max_concurrent, self._active) + try: + if self._blocking: + time.sleep(SLEEP * count) + else: + await asyncio.sleep(SLEEP * count) + self.visit_count += count + finally: + self._active -= 1 + + completion = WorkflowActivationCompletion( + run_id="1", + successful=Success( + commands=[ + WorkflowCommand( + schedule_activity=ScheduleActivity( + seq=i, + activity_id=str(i), + activity_type="", + task_queue="", + arguments=[ + Payload(data=f"cmd_{i}_arg_{j}".encode()) + for j in range(N_ARGS) + ], + priority=Priority(), + ) + ) + for i in range(N_CMDS) + ] + ), + ) + + visitor_default = SlowVisitor() + await PayloadVisitor().visit(visitor_default, completion) + + assert visitor_default.visit_count == N_CMDS * N_ARGS + assert visitor_default.max_concurrent == 1 + + visitor_concurrent = SlowVisitor() + await PayloadVisitor(concurrency_limit=5).visit(visitor_concurrent, completion) + + assert visitor_concurrent.visit_count == N_CMDS * N_ARGS + assert visitor_concurrent.max_concurrent == 5 + + async def test_bridge_encoding(): comp = WorkflowActivationCompletion( run_id="1", @@ -235,7 +303,7 @@ async def test_bridge_encoding(): payload_codec=SimpleCodec(), ) - await temporalio.bridge.worker.encode_completion(comp, data_converter, True) + await temporalio.bridge.worker.encode_completion(comp, data_converter, True, 1) cmd = comp.successful.commands[0] sa = cmd.schedule_activity From 83738c3f0fcad52ed7242b182313fa41ad393a23 Mon Sep 17 00:00:00 2001 From: Justin Anderson <44687433+jmaeagle99@users.noreply.github.com> Date: Tue, 24 Mar 2026 21:09:48 -0700 Subject: [PATCH 016/226] Fix command context awareness to apply to all of DataConverter (#1387) --- temporalio/worker/_workflow.py | 133 ++++++++++++++++------------ tests/test_serialization_context.py | 86 ++++++++++++++++++ 2 files changed, 163 insertions(+), 56 deletions(-) diff --git a/temporalio/worker/_workflow.py b/temporalio/worker/_workflow.py index 82bdefdc1..4844ec198 100644 --- a/temporalio/worker/_workflow.py +++ b/temporalio/worker/_workflow.py @@ -289,18 +289,13 @@ async def _handle_activation( workflow_id=workflow_id, ) data_converter = self._data_converter.with_context(workflow_context) - if self._data_converter.payload_codec: - assert data_converter.payload_codec - if workflow: - data_converter = dataclasses.replace( - data_converter, - payload_codec=_CommandAwarePayloadCodec( - workflow.instance, - context_free_payload_codec=self._data_converter.payload_codec, - workflow_context_payload_codec=data_converter.payload_codec, - workflow_context=workflow_context, - ), - ) + if workflow: + data_converter = _CommandAwareDataConverter.create( + instance=workflow.instance, + context_free_dc=self._data_converter, + workflow_context_dc=data_converter, + workflow_context=workflow_context, + ) download_metrics = await temporalio.bridge.worker.decode_activation( act, data_converter, @@ -395,19 +390,16 @@ async def _handle_activation( completion.run_id = act.run_id # Encode completion - if self._data_converter.payload_codec and workflow: - assert data_converter.payload_codec - data_converter = dataclasses.replace( - data_converter, - payload_codec=_CommandAwarePayloadCodec( - workflow.instance, - context_free_payload_codec=self._data_converter.payload_codec, - workflow_context_payload_codec=data_converter.payload_codec, - workflow_context=temporalio.converter.WorkflowSerializationContext( - namespace=self._namespace, - workflow_id=workflow.workflow_id, - ), - ), + if workflow: + workflow_context = temporalio.converter.WorkflowSerializationContext( + namespace=self._namespace, + workflow_id=workflow.workflow_id, + ) + data_converter = _CommandAwareDataConverter.create( + instance=workflow.instance, + context_free_dc=self._data_converter, + workflow_context_dc=self._data_converter.with_context(workflow_context), + workflow_context=workflow_context, ) upload_metrics = temporalio.converter._extstore.StorageOperationMetrics() @@ -837,45 +829,74 @@ def attempt_deadlock_interruption(self) -> None: @dataclass(frozen=True) -class _CommandAwarePayloadCodec(temporalio.converter.PayloadCodec): - """A payload codec that sets serialization context for the command associated with each payload. +class _CommandAwareDataConverter(temporalio.converter.DataConverter): + """Data converter that resolves serialization context per-command. - This codec responds to the context variable set by + Responds to the context variable set by :py:class:`_command_aware_visitor.CommandAwarePayloadVisitor`. """ - instance: WorkflowInstance - context_free_payload_codec: temporalio.converter.PayloadCodec - workflow_context_payload_codec: temporalio.converter.PayloadCodec - workflow_context: temporalio.converter.WorkflowSerializationContext - - async def encode( - self, - payloads: Sequence[temporalio.api.common.v1.Payload], - ) -> list[temporalio.api.common.v1.Payload]: - return await self._get_current_command_codec().encode(payloads) - - async def decode( - self, - payloads: Sequence[temporalio.api.common.v1.Payload], - ) -> list[temporalio.api.common.v1.Payload]: - return await self._get_current_command_codec().decode(payloads) + _ca_instance: WorkflowInstance = dataclasses.field( + default=None, + repr=False, + compare=False, # type: ignore[assignment] + ) + _ca_context_free_dc: temporalio.converter.DataConverter = dataclasses.field( + default=None, + repr=False, + compare=False, # type: ignore[assignment] + ) + _ca_workflow_context_dc: temporalio.converter.DataConverter = dataclasses.field( + default=None, + repr=False, + compare=False, # type: ignore[assignment] + ) + _ca_workflow_context: temporalio.converter.WorkflowSerializationContext = ( + dataclasses.field( + default=None, + repr=False, + compare=False, # type: ignore[assignment] + ) + ) - def _get_current_command_codec(self) -> temporalio.converter.PayloadCodec: - if not isinstance( - self.context_free_payload_codec, - temporalio.converter.WithSerializationContext, - ): - return self.context_free_payload_codec + @staticmethod + def create( + instance: WorkflowInstance, + context_free_dc: temporalio.converter.DataConverter, + workflow_context_dc: temporalio.converter.DataConverter, + workflow_context: temporalio.converter.WorkflowSerializationContext, + ) -> _CommandAwareDataConverter: + return _CommandAwareDataConverter( + payload_converter_class=workflow_context_dc.payload_converter_class, + payload_codec=workflow_context_dc.payload_codec, + failure_converter_class=workflow_context_dc.failure_converter_class, + payload_limits=workflow_context_dc.payload_limits, + external_storage=workflow_context_dc.external_storage, + _ca_instance=instance, + _ca_context_free_dc=context_free_dc, + _ca_workflow_context_dc=workflow_context_dc, + _ca_workflow_context=workflow_context, + ) - if context := self.instance.get_serialization_context( + def _get_current_dc(self) -> temporalio.converter.DataConverter: + context = self._ca_instance.get_serialization_context( _command_aware_visitor.current_command_info.get(), - ): - if context == self.workflow_context: - return self.workflow_context_payload_codec - return self.context_free_payload_codec.with_context(context) + ) + if context is None: + return self._ca_context_free_dc + if context == self._ca_workflow_context: + return self._ca_workflow_context_dc + return self._ca_context_free_dc.with_context(context) + + async def _encode_payload_sequence( + self, payloads: Sequence[temporalio.api.common.v1.Payload] + ) -> list[temporalio.api.common.v1.Payload]: + return await self._get_current_dc()._encode_payload_sequence(payloads) - return self.context_free_payload_codec + async def _decode_payload_sequence( + self, payloads: Sequence[temporalio.api.common.v1.Payload] + ) -> list[temporalio.api.common.v1.Payload]: + return await self._get_current_dc()._decode_payload_sequence(payloads) class _InterruptDeadlockError(BaseException): diff --git a/tests/test_serialization_context.py b/tests/test_serialization_context.py index d3ce022f5..ad3768ec8 100644 --- a/tests/test_serialization_context.py +++ b/tests/test_serialization_context.py @@ -40,10 +40,15 @@ DefaultFailureConverter, DefaultPayloadConverter, EncodingPayloadConverter, + ExternalStorage, JSONPlainPayloadConverter, PayloadCodec, PayloadConverter, SerializationContext, + StorageDriver, + StorageDriverClaim, + StorageDriverRetrieveContext, + StorageDriverStoreContext, WithSerializationContext, WorkflowSerializationContext, ) @@ -1914,3 +1919,84 @@ async def test_user_customization_of_default_payload_converter( id=wf_id, task_queue=task_queue, ) + + +# Child workflow external storage context test + + +class ContextTrackingStorageDriver(StorageDriver): + """In-memory driver that records the serialization context on each store/retrieve.""" + + def __init__(self) -> None: + self._storage: dict[str, bytes] = {} + self.store_contexts: list[SerializationContext | None] = [] + + def name(self) -> str: + return "context-tracking" + + async def store( + self, + context: StorageDriverStoreContext, + payloads: Sequence[temporalio.api.common.v1.Payload], + ) -> list[StorageDriverClaim]: + self.store_contexts.append(context.serialization_context) + claims: list[StorageDriverClaim] = [] + for payload in payloads: + key = f"payload-{len(self._storage)}" + self._storage[key] = payload.SerializeToString() + claims.append(StorageDriverClaim(claim_data={"key": key})) + return claims + + async def retrieve( + self, + context: StorageDriverRetrieveContext, + claims: Sequence[StorageDriverClaim], + ) -> list[temporalio.api.common.v1.Payload]: + results: list[temporalio.api.common.v1.Payload] = [] + for claim in claims: + payload = temporalio.api.common.v1.Payload() + payload.ParseFromString(self._storage[claim.claim_data["key"]]) + results.append(payload) + return results + + +async def test_child_workflow_external_storage_with_context(client: Client): + """External storage should receive the child workflow's context, not the parent's.""" + workflow_id = str(uuid.uuid4()) + child_workflow_id = f"{workflow_id}-child" + task_queue = str(uuid.uuid4()) + + driver = ContextTrackingStorageDriver() + config = client.config() + config["data_converter"] = dataclasses.replace( + DataConverter.default, + external_storage=ExternalStorage( + drivers=[driver], + payload_size_threshold=None, + ), + ) + client = Client(**config) + + async with Worker( + client, + task_queue=task_queue, + workflows=[ChildWorkflowCodecTestWorkflow, EchoWorkflow], + workflow_runner=UnsandboxedWorkflowRunner(), + ): + await client.execute_workflow( + ChildWorkflowCodecTestWorkflow.run, + TraceData(), + id=workflow_id, + task_queue=task_queue, + ) + + child_context = WorkflowSerializationContext( + namespace=client.namespace, + workflow_id=child_workflow_id, + ) + # store_contexts[0]: parent input encode → parent context + # store_contexts[1]: child workflow input encode → child context + # store_contexts[2]: child workflow result encode → child context + # store_contexts[3]: parent result encode → parent context + child_context_count = sum(1 for c in driver.store_contexts if c == child_context) + assert child_context_count == 2 From 74001f205875cc9c151db4d49d6c6710ff322f7a Mon Sep 17 00:00:00 2001 From: tconley1428 Date: Wed, 25 Mar 2026 10:29:00 -0700 Subject: [PATCH 017/226] Some fixes to the openai agents readme (#1391) * Some fixes to the openai agents readme * Some fixes to the openai agents readme --- temporalio/contrib/openai_agents/README.md | 25 +++++++--------------- 1 file changed, 8 insertions(+), 17 deletions(-) diff --git a/temporalio/contrib/openai_agents/README.md b/temporalio/contrib/openai_agents/README.md index 45aa51fb6..888490379 100644 --- a/temporalio/contrib/openai_agents/README.md +++ b/temporalio/contrib/openai_agents/README.md @@ -1,6 +1,5 @@ # OpenAI Agents SDK Integration for Temporal -⚠️ **Public Preview** - The interface to this module is subject to change prior to General Availability. We welcome questions and feedback in the [#python-sdk](https://temporalio.slack.com/archives/CTT84RS0P) Slack channel at [temporalio.slack.com](https://temporalio.slack.com/). ## Introduction @@ -538,6 +537,8 @@ SQLite storage is not suited to a distributed environment. ## OpenTelemetry Integration +⚠️ **Public Preview** - This functionality is subject to change prior to General Availability. + This integration provides seamless export of OpenAI agent telemetry to OpenTelemetry (OTEL) endpoints for observability and monitoring. The integration automatically handles workflow replay semantics, ensuring spans are only exported when workflows actually complete. ### Quick Start @@ -545,22 +546,21 @@ This integration provides seamless export of OpenAI agent telemetry to OpenTelem To enable OTEL telemetry export, you need to set up a global `ReplaySafeTracerProvider` and enable the integration in the `OpenAIAgentsPlugin`: ```python -from temporalio.contrib.openai_agents import OpenAIAgentsPlugin +from datetime import timedelta +from temporalio.client import Client +from temporalio.contrib.openai_agents import OpenAIAgentsPlugin, ModelActivityParameters from temporalio.contrib.opentelemetry import create_tracer_provider from opentelemetry.exporter.otlp.proto.grpc.trace_exporter import OTLPSpanExporter from opentelemetry import trace +from opentelemetry.sdk.trace.export import SimpleSpanProcessor # Configure your OTEL exporters -exporters = [ - OTLPSpanExporter(endpoint="http://localhost:4317"), - # Add multiple exporters for different endpoints as needed -] # Set up the global tracer provider -tracer_provider = create_tracer_provider(exporters=exporters) +tracer_provider = create_tracer_provider() +tracer_provider.add_span_processor(SimpleSpanProcessor(OTLPSpanExporter(endpoint="http://localhost:4317"))) trace.set_tracer_provider(tracer_provider) -# For production applications client = await Client.connect( "localhost:7233", plugins=[ @@ -572,15 +572,6 @@ client = await Client.connect( ), ], ) - -# For testing -from temporalio.contrib.openai_agents.testing import AgentEnvironment - -async with AgentEnvironment( - model=my_test_model, - use_otel_instrumentation=True # Enable OTEL integration for tests -) as env: - client = env.applied_on_client(base_client) ``` ### Features From e9ac9a30b3884d3be0643f6abe482dd8384a47da Mon Sep 17 00:00:00 2001 From: tconley1428 Date: Wed, 25 Mar 2026 12:00:11 -0700 Subject: [PATCH 018/226] Add __getattr__ to _ReplaySafeSpan to delegate SDK-specific attributes (#1392) Instrumentation libraries like opentelemetry-instrumentation-asgi access attributes beyond the Span ABC (e.g. .name, .kind, .resource, .attributes) directly on spans. _ReplaySafeSpan now forwards these via __getattr__ to the wrapped span. Also removes dead self._status assignment in set_status. Co-authored-by: Claude Opus 4.6 (1M context) --- .../contrib/opentelemetry/_tracer_provider.py | 4 ++- .../test_opentelemetry_plugin.py | 31 +++++++++++++++++++ 2 files changed, 34 insertions(+), 1 deletion(-) diff --git a/temporalio/contrib/opentelemetry/_tracer_provider.py b/temporalio/contrib/opentelemetry/_tracer_provider.py index 7d592705f..929f8bf27 100644 --- a/temporalio/contrib/opentelemetry/_tracer_provider.py +++ b/temporalio/contrib/opentelemetry/_tracer_provider.py @@ -33,6 +33,9 @@ def __init__(self, span: Span): self._exception: BaseException | None = None self._span = span + def __getattr__(self, name: str) -> object: + return getattr(self._span, name) + def end(self, end_time: int | None = None) -> None: if workflow.in_workflow() and workflow.unsafe.is_replaying_history_events(): # Skip ending spans during workflow replay to avoid duplicate telemetry @@ -75,7 +78,6 @@ def is_recording(self) -> bool: def set_status( self, status: Status | StatusCode, description: str | None = None ) -> None: - self._status = status self._span.set_status(status, description) def record_exception( diff --git a/tests/contrib/opentelemetry/test_opentelemetry_plugin.py b/tests/contrib/opentelemetry/test_opentelemetry_plugin.py index b06bb8bc7..b2ff2f913 100644 --- a/tests/contrib/opentelemetry/test_opentelemetry_plugin.py +++ b/tests/contrib/opentelemetry/test_opentelemetry_plugin.py @@ -576,3 +576,34 @@ async def test_otel_tracing_workflow_failure( assert ( actual_hierarchy == expected_hierarchy ), f"Span hierarchy mismatch.\nExpected:\n{expected_hierarchy}\nActual:\n{actual_hierarchy}" + + +def test_replay_safe_span_delegates_extra_attributes(): + """Test that _ReplaySafeSpan delegates attribute access to the underlying span. + + Concrete span implementations (e.g. opentelemetry.sdk.trace.Span) expose + attributes beyond the Span ABC such as .attributes, .name, .kind, and + .resource. _ReplaySafeSpan must forward these so that instrumentation + libraries that rely on them work correctly. + """ + from opentelemetry.sdk.trace import TracerProvider as SdkTracerProvider + + from temporalio.contrib.opentelemetry._tracer_provider import _ReplaySafeSpan + + provider = SdkTracerProvider() + tracer = provider.get_tracer("test") + inner_span = tracer.start_span("test-span") + + wrapper = _ReplaySafeSpan(inner_span) + + # These properties exist on the SDK span but not on the Span ABC + assert wrapper.name == "test-span" + assert wrapper.kind is not None + assert wrapper.resource is not None + assert wrapper.attributes is not None or wrapper.attributes == {} + + # Verify that AttributeError is still raised for truly missing attributes + with pytest.raises(AttributeError): + _ = wrapper.nonexistent_attribute_xyz + + inner_span.end() From 05971a8b24c4cbd53f22dea1c7bc07de6da5a8d8 Mon Sep 17 00:00:00 2001 From: Justin Anderson <44687433+jmaeagle99@users.noreply.github.com> Date: Wed, 25 Mar 2026 20:23:10 -0700 Subject: [PATCH 019/226] Experimental: AWS S3 storage driver (#1388) --- README.md | 36 +- pyproject.toml | 5 + temporalio/contrib/aws/s3driver/README.md | 104 +++ temporalio/contrib/aws/s3driver/__init__.py | 13 + temporalio/contrib/aws/s3driver/_client.py | 32 + temporalio/contrib/aws/s3driver/_driver.py | 228 +++++ temporalio/contrib/aws/s3driver/aioboto3.py | 71 ++ tests/contrib/aws/__init__.py | 0 tests/contrib/aws/s3driver/__init__.py | 0 tests/contrib/aws/s3driver/conftest.py | 65 ++ tests/contrib/aws/s3driver/test_s3driver.py | 831 ++++++++++++++++++ .../aws/s3driver/test_s3driver_worker.py | 414 +++++++++ tests/contrib/aws/s3driver/workflows.py | 223 +++++ uv.lock | 642 +++++++++++++- 14 files changed, 2635 insertions(+), 29 deletions(-) create mode 100644 temporalio/contrib/aws/s3driver/README.md create mode 100644 temporalio/contrib/aws/s3driver/__init__.py create mode 100644 temporalio/contrib/aws/s3driver/_client.py create mode 100644 temporalio/contrib/aws/s3driver/_driver.py create mode 100644 temporalio/contrib/aws/s3driver/aioboto3.py create mode 100644 tests/contrib/aws/__init__.py create mode 100644 tests/contrib/aws/s3driver/__init__.py create mode 100644 tests/contrib/aws/s3driver/conftest.py create mode 100644 tests/contrib/aws/s3driver/test_s3driver.py create mode 100644 tests/contrib/aws/s3driver/test_s3driver_worker.py create mode 100644 tests/contrib/aws/s3driver/workflows.py diff --git a/README.md b/README.md index 6e42a2019..ca8a000f6 100644 --- a/README.md +++ b/README.md @@ -56,6 +56,7 @@ informal introduction to the features and their implementation. - [Custom Type Data Conversion](#custom-type-data-conversion) - [External Storage](#external-storage) - [Driver Selection](#driver-selection) + - [Built-in Drivers](#built-in-drivers) - [Custom Drivers](#custom-drivers) - [Workers](#workers) - [Workflows](#workflows) @@ -467,25 +468,36 @@ External storage allows large payloads to be offloaded to an external storage se External storage is configured via the `external_storage` parameter on `DataConverter`. It should be configured on the `Client` both for clients of your workflow as well as on the worker -- anywhere large payloads may be uploaded or downloaded. -A `StorageDriver` handles uploading and downloading payloads. Temporal provides built-in drivers for common storage solutions, or you may customize one. Here's an example using our provided `InMemoryTestDriver`. +A `StorageDriver` handles uploading and downloading payloads. Temporal provides [built-in drivers](#built-in-drivers) for common storage solutions, or you may implement a [custom driver](#custom-drivers). Here's an example using the built-in `S3StorageDriver` with the SDK's `aioboto3` client: ```python +import aioboto3 import dataclasses -from temporalio.client import Client +from temporalio.client import Client, ClientConfig +from temporalio.contrib.aws.s3driver import S3StorageDriver +from temporalio.contrib.aws.s3driver.aioboto3 import new_aioboto3_client from temporalio.converter import DataConverter from temporalio.converter import ExternalStorage -driver = InMemoryTestDriver() +client_config = ClientConfig.load_client_connect_config() -client = await Client.connect( - "localhost:7233", - data_converter=dataclasses.replace( - DataConverter.default, - external_storage=ExternalStorage(drivers=[driver]), - ), -) +session = aioboto3.Session() +async with session.client("s3") as s3_client: + driver = S3StorageDriver( + client=new_aioboto3_client(s3_client), + bucket="my-bucket", + ) + client = await Client.connect( + **client_config, + data_converter=dataclasses.replace( + DataConverter.default, + external_storage=ExternalStorage(drivers=[driver]), + ), + ) ``` +See the [S3 driver README](temporalio/contrib/aws/s3driver/) for further details. + Some things to note about external storage: * Only payloads that meet or exceed `ExternalStorage.payload_size_threshold` (default 256 KiB) are offloaded. Smaller payloads are stored inline as normal. @@ -540,6 +552,10 @@ Some things to note about driver selection: * Returning `None` from a selector leaves the payload stored inline in workflow history rather than offloading it. * The driver instance returned by the selector must be one of the instances registered in `ExternalStorage.drivers`. If it is not, an error is raised. +###### Built-in Drivers + +- **[S3 Storage Driver](temporalio/contrib/aws/s3driver/)**: ⚠️ **Experimental** ⚠️ Amazon S3 driver. Ships with an aioboto3 client, or bring your own by subclassing `S3StorageDriverClient`. + ###### Custom Drivers Implement `temporalio.converter.StorageDriver` to integrate with an external storage system: diff --git a/pyproject.toml b/pyproject.toml index 4bcd3f03e..4ee2fed92 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -30,6 +30,10 @@ opentelemetry = ["opentelemetry-api>=1.11.1,<2", "opentelemetry-sdk>=1.11.1,<2"] pydantic = ["pydantic>=2.0.0,<3"] openai-agents = ["openai-agents>=0.3,<0.7", "mcp>=1.9.4, <2"] google-adk = ["google-adk>=1.27.0,<2"] +aioboto3 = [ + "aioboto3>=10.4.0", + "types-aioboto3[s3]>=10.4.0", +] [project.urls] Homepage = "https://github.com/temporalio/sdk-python" @@ -64,6 +68,7 @@ dev = [ "openinference-instrumentation-google-adk>=0.1.8", "googleapis-common-protos==1.70.0", "pytest-rerunfailures>=16.1", + "moto[s3,server]>=5", ] [tool.poe.tasks] diff --git a/temporalio/contrib/aws/s3driver/README.md b/temporalio/contrib/aws/s3driver/README.md new file mode 100644 index 000000000..8e6a3e365 --- /dev/null +++ b/temporalio/contrib/aws/s3driver/README.md @@ -0,0 +1,104 @@ +# AWS Integration for Temporal Python SDK + +> ⚠️ **This package is currently at an experimental release stage.** ⚠️ + +This package provides AWS integrations for the Temporal Python SDK, including an Amazon S3 driver for [external storage](../../../README.md#external-storage). + +## S3 Driver + +`S3StorageDriver` stores and retrieves Temporal payloads in Amazon S3. It accepts any `S3StorageDriverClient` implementation and a `bucket` — either a static name or a callable for dynamic per-payload selection. + +### Using the built-in aioboto3 client + +The SDK ships with an [`aioboto3`](https://github.com/terrycain/aioboto3)-based client. Install the extra to pull in its dependencies: + + python -m pip install "temporalio[aioboto3]" + +```python +import aioboto3 +import dataclasses +from temporalio.client import Client +from temporalio.contrib.aws.s3driver import S3StorageDriver +from temporalio.contrib.aws.s3driver.aioboto3 import new_aioboto3_client +from temporalio.converter import DataConverter, ExternalStorage + +session = aioboto3.Session() +# Credentials and region are resolved automatically from the standard AWS credential +# chain e.g. environment variables, ~/.aws/config, IAM instance profile, and so on. +async with session.client("s3") as s3_client: + driver = S3StorageDriver( + client=new_aioboto3_client(s3_client), + bucket="my-temporal-payloads", + ) + + client = await Client.connect( + "localhost:7233", + data_converter=dataclasses.replace( + DataConverter.default, + external_storage=ExternalStorage(drivers=[driver]), + ), + ) +``` + +### Custom S3 client implementations + +To use a different S3 library, subclass `S3StorageDriverClient` and implement `put_object`, `get_object`, and `object_exists`. The ABC has no external dependencies, so no AWS packages are required to import it. + +```python +from temporalio.contrib.aws.s3driver import S3StorageDriverClient + +class MyS3Client(S3StorageDriverClient): + async def put_object(self, *, bucket: str, key: str, data: bytes) -> None: ... + async def object_exists(self, *, bucket: str, key: str) -> bool: ... + async def get_object(self, *, bucket: str, key: str) -> bytes: ... + +driver = S3StorageDriver(client=MyS3Client(), bucket="my-temporal-payloads") +``` + +### Key structure + +Payloads are stored under content-addressable keys derived from a SHA-256 hash of the serialized payload bytes, segmented by namespace and workflow/activity identifiers when serialization context is available, e.g.: + + v0/ns/my-namespace/wfi/my-workflow-id/d/sha256/ + +### Notes + +* Any driver used to store payloads must also be configured on the component that retrieves them. If the client stores workflow inputs using this driver, the worker must include it in its `ExternalStorage.drivers` list to retrieve them. +* The target S3 bucket must already exist; the driver will not create it. +* Identical serialized bytes within the same namespace and workflow (or activity) share the same S3 object — the key is content-addressable within that scope. The same bytes used across different workflows or namespaces produce distinct S3 objects because the key includes the namespace and workflow/activity identifiers. +* Only payloads at or above `ExternalStorage.payload_size_threshold` (default: 256 KiB) are offloaded; smaller payloads are stored inline. Set `ExternalStorage.payload_size_threshold` to `None` to offload every payload regardless of size. +* `S3StorageDriver.max_payload_size` (default: 50 MiB) sets a hard upper limit on the serialized size of any single payload. A `ValueError` is raised at store time if a payload exceeds this limit. Increase it if your workflows produce payloads larger than 50 MiB. +* Override `S3StorageDriver.driver_name` only when registering multiple `S3StorageDriver` instances with distinct configurations under the same `ExternalStorage.drivers` list. + +### Dynamic Bucket Selection + +To select the S3 bucket per payload, pass a callable as `bucket`: + +```python +from temporalio.contrib.aws.s3driver import S3StorageDriver +from temporalio.contrib.aws.s3driver.aioboto3 import new_aioboto3_client + +driver = S3StorageDriver( + client=new_aioboto3_client(s3_client), + bucket=lambda context, payload: ( + "large-payloads" if payload.ByteSize() > 10 * 1024 * 1024 else "small-payloads" + ), +) +``` + +### Required IAM permissions + +The AWS credentials used by your S3 client must have the following S3 permissions on the target bucket and its objects: + +```json +{ + "Effect": "Allow", + "Action": [ + "s3:PutObject", + "s3:GetObject" + ], + "Resource": "arn:aws:s3:::my-temporal-payloads/*" +} +``` + +`s3:PutObject` is required by components that store payloads (typically the Temporal client and worker sending workflow/activity inputs), and `s3:GetObject` is required by components that retrieve them (typically workers and clients reading results). Components that only retrieve payloads do not need `s3:PutObject`, and vice versa. diff --git a/temporalio/contrib/aws/s3driver/__init__.py b/temporalio/contrib/aws/s3driver/__init__.py new file mode 100644 index 000000000..cdc349e24 --- /dev/null +++ b/temporalio/contrib/aws/s3driver/__init__.py @@ -0,0 +1,13 @@ +"""Amazon S3 storage driver for Temporal external storage. + +.. warning:: + This API is experimental. +""" + +from temporalio.contrib.aws.s3driver._client import S3StorageDriverClient +from temporalio.contrib.aws.s3driver._driver import S3StorageDriver + +__all__ = [ + "S3StorageDriverClient", + "S3StorageDriver", +] diff --git a/temporalio/contrib/aws/s3driver/_client.py b/temporalio/contrib/aws/s3driver/_client.py new file mode 100644 index 000000000..16e4c6a8c --- /dev/null +++ b/temporalio/contrib/aws/s3driver/_client.py @@ -0,0 +1,32 @@ +"""S3 storage driver client abstraction for the S3 storage driver. + +.. warning:: + This API is experimental. +""" + +from __future__ import annotations + +from abc import ABC, abstractmethod + + +class S3StorageDriverClient(ABC): + """Abstract base class for S3 object operations. + + Implementations must support ``put_object`` and ``get_object``. Multipart + upload handling (if needed) is an internal concern of each implementation. + + .. warning:: + This API is experimental. + """ + + @abstractmethod + async def put_object(self, *, bucket: str, key: str, data: bytes) -> None: + """Upload *data* to the given S3 *bucket* and *key*.""" + + @abstractmethod + async def object_exists(self, *, bucket: str, key: str) -> bool: + """Return ``True`` if an object exists at the given *bucket* and *key*.""" + + @abstractmethod + async def get_object(self, *, bucket: str, key: str) -> bytes: + """Download and return the bytes stored at the given S3 *bucket* and *key*.""" diff --git a/temporalio/contrib/aws/s3driver/_driver.py b/temporalio/contrib/aws/s3driver/_driver.py new file mode 100644 index 000000000..481e3a9d4 --- /dev/null +++ b/temporalio/contrib/aws/s3driver/_driver.py @@ -0,0 +1,228 @@ +"""Amazon S3 storage driver for Temporal external storage. + +.. warning:: + This API is experimental. +""" + +from __future__ import annotations + +import asyncio +import hashlib +import urllib.parse +from collections.abc import Callable, Coroutine, Sequence +from typing import Any, TypeVar + +from temporalio.api.common.v1 import Payload +from temporalio.contrib.aws.s3driver._client import S3StorageDriverClient +from temporalio.converter import ( + ActivitySerializationContext, + StorageDriver, + StorageDriverClaim, + StorageDriverRetrieveContext, + StorageDriverStoreContext, + WorkflowSerializationContext, +) + +_T = TypeVar("_T") + + +async def _gather_with_cancellation( + coros: Sequence[Coroutine[Any, Any, _T]], +) -> list[_T]: + """Run coroutines concurrently, cancelling all remaining tasks if one fails.""" + if not coros: + return [] + tasks = [asyncio.ensure_future(c) for c in coros] + try: + return list(await asyncio.gather(*tasks)) + except BaseException: + for t in tasks: + t.cancel() + await asyncio.gather(*tasks, return_exceptions=True) + raise + + +class S3StorageDriver(StorageDriver): + """Driver for storing and retrieving Temporal payloads in Amazon S3. + + Requires an :class:`S3StorageDriverClient` and a ``bucket``. Payloads are keyed by + a SHA-256 hash of their serialized bytes, segmented by namespace and + workflow/activity identifiers derived from the serialization context. + + .. warning:: + This API is experimental. + """ + + def __init__( + self, + client: S3StorageDriverClient, + bucket: str | Callable[[StorageDriverStoreContext, Payload], str], + driver_name: str = "aws.s3driver", + max_payload_size: int = 50 * 1024 * 1024, + ): + """Constructs the S3 driver. + + Args: + client: An :class:`S3StorageDriverClient` implementation. Use + :func:`~temporalio.contrib.aws.s3driver.aioboto3.new_aioboto3_client` to + wrap an aioboto3 S3 client. + bucket: S3 bucket name, access point ARN, or a callable that + accepts ``(StorageDriverStoreContext, Payload)`` and returns + a bucket name. A callable allows dynamic per-payload bucket + selection. + driver_name: Name of this driver instance. Defaults to + ``"aws.s3driver"``. Override when registering + multiple S3StorageDriver instances with distinct configurations + under the same :attr:`~temporalio.extstore.Options.drivers` list. + max_payload_size: Maximum serialized payload size in bytes that the + driver will accept. Defaults to 52428800 (50 MiB). Raise this + value if your workload requires larger payloads; lower it to + enforce stricter limits. + """ + if max_payload_size <= 0: + raise ValueError("max_payload_size must be greater than zero") + self._client = client + self._bucket = bucket + self._driver_name = driver_name or "aws.s3driver" + self._max_payload_size = max_payload_size + + def name(self) -> str: + """Return the driver instance name.""" + return self._driver_name + + def type(self) -> str: + """Return the driver type identifier.""" + return "aws.s3driver" + + def _get_bucket(self, context: StorageDriverStoreContext, payload: Payload) -> str: + """Resolve bucket using the configured strategy.""" + if callable(self._bucket): + return self._bucket(context, payload) + return self._bucket + + async def store( + self, + context: StorageDriverStoreContext, + payloads: Sequence[Payload], + ) -> list[StorageDriverClaim]: + """Stores payloads in S3 and returns a :class:`~temporalio.extstore.DriverClaim` for each one. + + Payloads are keyed by their SHA-256 hash, so identical serialized bytes + share the same S3 object. Deduplication is best-effort because the same + Python value may serialize differently across payload converter versions + (e.g. proto binary). The returned list is the same length as + ``payloads``. + """ + workflow_id: str | None = None + activity_id: str | None = None + namespace: str | None = None + if isinstance(context.serialization_context, WorkflowSerializationContext): + workflow_id = context.serialization_context.workflow_id + namespace = context.serialization_context.namespace + if isinstance(context.serialization_context, ActivitySerializationContext): + # Prioritize workflow over activity so that the same payload that + # may be stored across workflow and activity boundaries are deduplicated. + if context.serialization_context.workflow_id: + workflow_id = context.serialization_context.workflow_id + elif context.serialization_context.activity_id: + activity_id = context.serialization_context.activity_id + namespace = context.serialization_context.namespace + + # URL encode values to avoid characters that break the key format + # e.g. spaces, forward-slashes, etc. + if namespace: + namespace = urllib.parse.quote(namespace, safe="") + if workflow_id: + workflow_id = urllib.parse.quote(workflow_id, safe="") + if activity_id: + activity_id = urllib.parse.quote(activity_id, safe="") + + namespace_segments = f"/ns/{namespace}" if namespace else "" + + context_segments = "" + # Prioritize workflow over activity so that the same payload that + # may be stored across workflow and activity boundaries are deduplicated. + # Workflow and Activity IDs are case sensitive. + if workflow_id: + context_segments += f"/wfi/{workflow_id}" + elif activity_id: + context_segments += f"/aci/{activity_id}" + + async def _upload(payload: Payload) -> StorageDriverClaim: + bucket = self._get_bucket(context, payload) + + payload_bytes = payload.SerializeToString() + if len(payload_bytes) > self._max_payload_size: + raise ValueError( + f"Payload size {len(payload_bytes)} bytes exceeds the configured " + f"max_payload_size of {self._max_payload_size} bytes" + ) + + hash_digest = hashlib.sha256(payload_bytes).hexdigest().lower() + + digest_segments = f"/d/sha256/{hash_digest}" + + key = f"v0{namespace_segments}{context_segments}{digest_segments}" + + try: + if not await self._client.object_exists(bucket=bucket, key=key): + await self._client.put_object( + bucket=bucket, key=key, data=payload_bytes + ) + except Exception as e: + raise RuntimeError( + f"S3StorageDriver store failed [bucket={bucket}, key={key}]" + ) from e + + return StorageDriverClaim( + claim_data={ + "bucket": bucket, + "key": key, + "hash_algorithm": "sha256", + "hash_value": hash_digest, + }, + ) + + return await _gather_with_cancellation([_upload(p) for p in payloads]) + + async def retrieve( + self, + context: StorageDriverRetrieveContext, # noqa: ARG002 + claims: Sequence[StorageDriverClaim], + ) -> list[Payload]: + """Retrieves payloads from S3 for the given :class:`~temporalio.extstore.DriverClaim` list.""" + + async def _download(claim: StorageDriverClaim) -> Payload: + bucket = claim.claim_data["bucket"] + key = claim.claim_data["key"] + + try: + payload_bytes = await self._client.get_object(bucket=bucket, key=key) + except Exception as e: + raise RuntimeError( + f"S3StorageDriver retrieve failed [bucket={bucket}, key={key}]" + ) from e + + expected_hash = claim.claim_data.get("hash_value") + hash_algorithm = claim.claim_data.get("hash_algorithm") + if expected_hash and hash_algorithm: + if hash_algorithm != "sha256": + raise ValueError( + f"S3StorageDriver unsupported hash algorithm " + f"[bucket={bucket}, key={key}]: " + f"expected sha256, got {hash_algorithm}" + ) + actual_hash = hashlib.sha256(payload_bytes).hexdigest().lower() + if actual_hash != expected_hash: + raise ValueError( + f"S3StorageDriver integrity check failed " + f"[bucket={bucket}, key={key}]: " + f"expected {hash_algorithm}:{expected_hash}, " + f"got {hash_algorithm}:{actual_hash}" + ) + + payload = Payload() + payload.ParseFromString(payload_bytes) + return payload + + return await _gather_with_cancellation([_download(c) for c in claims]) diff --git a/temporalio/contrib/aws/s3driver/aioboto3.py b/temporalio/contrib/aws/s3driver/aioboto3.py new file mode 100644 index 000000000..b3da8b7c6 --- /dev/null +++ b/temporalio/contrib/aws/s3driver/aioboto3.py @@ -0,0 +1,71 @@ +"""Aioboto3 adapter for the S3 storage driver client. + +.. warning:: + This API is experimental. +""" + +from __future__ import annotations + +import io + +from botocore.exceptions import ClientError +from types_aiobotocore_s3.client import S3Client + +from temporalio.contrib.aws.s3driver._client import S3StorageDriverClient + + +class _Aioboto3StorageDriverClient(S3StorageDriverClient): + """Adapter that wraps an aioboto3 S3 client as an :class:`S3StorageDriverClient`. + + Internally delegates to ``upload_fileobj`` for uploads (which handles + multipart automatically for objects above the multipart threshold) and + ``get_object`` for downloads. + + .. warning:: + This API is experimental. + """ + + def __init__(self, client: S3Client) -> None: + """Wrap an aioboto3 S3 client. + + Args: + client: An aioboto3 S3 client, typically obtained from + ``aioboto3.Session().client("s3")``. + """ + self._client = client + + async def object_exists(self, *, bucket: str, key: str) -> bool: + """Check existence via aioboto3's ``head_object``.""" + try: + await self._client.head_object(Bucket=bucket, Key=key) + return True + except ClientError as e: + # head_object returns 404 as a ClientError when the key doesn't exist. + if e.response.get("Error", {}).get("Code") == "404": + return False + raise + + async def put_object(self, *, bucket: str, key: str, data: bytes) -> None: + """Upload *data* via aioboto3's ``upload_fileobj``.""" + # upload_fileobj is an aioboto3-specific method not in the + # types_aiobotocore_s3 stubs; it handles multipart automatically. + await self._client.upload_fileobj(io.BytesIO(data), bucket, key) # type: ignore[arg-type] + + async def get_object(self, *, bucket: str, key: str) -> bytes: + """Download bytes via aioboto3's ``get_object``.""" + response = await self._client.get_object(Bucket=bucket, Key=key) + # StreamingBody.read() is untyped in aiobotocore, returns bytes at runtime. + return await response["Body"].read() # type: ignore[no-any-return] + + +def new_aioboto3_client(client: S3Client) -> S3StorageDriverClient: + """Create an :class:`S3StorageDriverClient` from an aioboto3 S3 client. + + Args: + client: An aioboto3 S3 client, typically obtained from + ``aioboto3.Session().client("s3")``. + + .. warning:: + This API is experimental. + """ + return _Aioboto3StorageDriverClient(client) diff --git a/tests/contrib/aws/__init__.py b/tests/contrib/aws/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/tests/contrib/aws/s3driver/__init__.py b/tests/contrib/aws/s3driver/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/tests/contrib/aws/s3driver/conftest.py b/tests/contrib/aws/s3driver/conftest.py new file mode 100644 index 000000000..71a0a8749 --- /dev/null +++ b/tests/contrib/aws/s3driver/conftest.py @@ -0,0 +1,65 @@ +"""Shared fixtures for S3 storage driver tests.""" + +from __future__ import annotations + +import socket +import urllib.request +from collections.abc import AsyncIterator, Iterator + +import aioboto3 +import pytest +from types_aiobotocore_s3.client import S3Client + +from temporalio.contrib.aws.s3driver import S3StorageDriverClient +from temporalio.contrib.aws.s3driver.aioboto3 import new_aioboto3_client + +BUCKET = "test-bucket" +REGION = "us-east-1" + + +def _find_free_port() -> int: + with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s: + s.bind(("127.0.0.1", 0)) + return s.getsockname()[1] + + +@pytest.fixture(scope="session") +def moto_server_url() -> Iterator[str]: + """Start a moto S3 server for the test session and yield its base URL.""" + port = _find_free_port() + from moto.server import ThreadedMotoServer + + server = ThreadedMotoServer(port=port) + server.start() + yield f"http://127.0.0.1:{port}" + server.stop() + + +@pytest.fixture +async def aioboto3_client(moto_server_url: str) -> AsyncIterator[S3Client]: + """Yield an aioboto3 S3 client pointed at the moto server. + + Resets all moto state before each test to guarantee isolation, then + pre-creates the standard test bucket. + """ + urllib.request.urlopen( + urllib.request.Request( + f"{moto_server_url}/moto-api/reset", method="POST", data=b"" + ) + ) + session = aioboto3.Session() + async with session.client( + "s3", + region_name=REGION, + endpoint_url=moto_server_url, + aws_access_key_id="testing", + aws_secret_access_key="testing", + ) as client: + await client.create_bucket(Bucket=BUCKET) + yield client + + +@pytest.fixture +def driver_client(aioboto3_client: S3Client) -> S3StorageDriverClient: + """Wrap the aioboto3 S3 client in an S3StorageDriverClient adapter.""" + return new_aioboto3_client(aioboto3_client) diff --git a/tests/contrib/aws/s3driver/test_s3driver.py b/tests/contrib/aws/s3driver/test_s3driver.py new file mode 100644 index 000000000..46184c8b7 --- /dev/null +++ b/tests/contrib/aws/s3driver/test_s3driver.py @@ -0,0 +1,831 @@ +"""Unit tests for S3StorageDriver using moto's ThreadedMotoServer to mock AWS S3. + +moto's standard mock_aws() context manager intercepts boto3/botocore via the +requests library and does not intercept aiobotocore (which aioboto3 wraps), +because aiobotocore uses aiohttp and returns coroutines where moto's mock +returns plain bytes. ThreadedMotoServer starts a real local HTTP server; the +aioboto3 client is pointed at it via endpoint_url so all API calls are +intercepted correctly. +""" + +from __future__ import annotations + +import asyncio +import hashlib +from collections.abc import Callable, Coroutine +from functools import wraps +from typing import Any +from unittest.mock import MagicMock + +import pytest +from botocore.exceptions import ClientError +from types_aiobotocore_s3.client import S3Client + +from temporalio.api.common.v1 import Payload +from temporalio.contrib.aws.s3driver import ( + S3StorageDriver, + S3StorageDriverClient, +) +from temporalio.converter import ( + ActivitySerializationContext, + JSONPlainPayloadConverter, + StorageDriverClaim, + StorageDriverRetrieveContext, + StorageDriverStoreContext, + WorkflowSerializationContext, +) +from tests.contrib.aws.s3driver.conftest import BUCKET + +_CONVERTER = JSONPlainPayloadConverter() + + +# --------------------------------------------------------------------------- +# Helpers +# --------------------------------------------------------------------------- + + +def make_payload(value: str = "hello") -> Payload: + p = _CONVERTER.to_payload(value) + assert p is not None + return p + + +def make_store_context( + serialization_context: WorkflowSerializationContext + | ActivitySerializationContext + | None = None, +) -> StorageDriverStoreContext: + return StorageDriverStoreContext(serialization_context=serialization_context) + + +def make_workflow_context( + namespace: str = "my-namespace", + workflow_id: str = "my-workflow", +) -> WorkflowSerializationContext: + return WorkflowSerializationContext(namespace=namespace, workflow_id=workflow_id) + + +def make_activity_context( + namespace: str = "my-namespace", + activity_id: str | None = "my-activity", + workflow_id: str | None = None, + activity_task_queue: str | None = None, +) -> ActivitySerializationContext: + return ActivitySerializationContext( + namespace=namespace, + activity_id=activity_id, + activity_type=None, + activity_task_queue=activity_task_queue, + workflow_id=workflow_id, + workflow_type=None, + is_local=False, + ) + + +# --------------------------------------------------------------------------- +# Fixtures +# --------------------------------------------------------------------------- + + +class CountingDriverClient(S3StorageDriverClient): + """S3StorageDriverClient wrapper that counts calls to each method.""" + + def __init__(self, delegate: S3StorageDriverClient) -> None: + self._delegate = delegate + self.put_object_count = 0 + self.get_object_count = 0 + self.object_exists_count = 0 + + async def put_object(self, *, bucket: str, key: str, data: bytes) -> None: + """Delegate to wrapped client and increment put_object counter.""" + self.put_object_count += 1 + await self._delegate.put_object(bucket=bucket, key=key, data=data) + + async def object_exists(self, *, bucket: str, key: str) -> bool: + """Delegate to wrapped client and increment object_exists counter.""" + self.object_exists_count += 1 + return await self._delegate.object_exists(bucket=bucket, key=key) + + async def get_object(self, *, bucket: str, key: str) -> bytes: + """Delegate to wrapped client and increment get_object counter.""" + self.get_object_count += 1 + return await self._delegate.get_object(bucket=bucket, key=key) + + +class FailOnceDriverClient(S3StorageDriverClient): + """S3StorageDriverClient wrapper that fails the first call to a specified + method and blocks subsequent calls until cancelled. + + Used to verify that the driver cancels in-flight tasks when one fails. + """ + + def __init__( + self, + delegate: S3StorageDriverClient, + fail_on: str, + ) -> None: + self._delegate = delegate + self._fail_on = fail_on + self._call_count = 0 + self.cancelled: list[bool] = [] + + async def _maybe_fail(self) -> None: + self._call_count += 1 + if self._call_count == 1: + raise ConnectionError("S3 connection lost") + try: + await asyncio.sleep(60) + except asyncio.CancelledError: + self.cancelled.append(True) + raise + + async def put_object(self, *, bucket: str, key: str, data: bytes) -> None: + """Delegate or fail depending on configuration.""" + if self._fail_on == "put_object": + await self._maybe_fail() + await self._delegate.put_object(bucket=bucket, key=key, data=data) + + async def object_exists(self, *, bucket: str, key: str) -> bool: + """Delegate or fail depending on configuration.""" + if self._fail_on == "object_exists": + await self._maybe_fail() + return await self._delegate.object_exists(bucket=bucket, key=key) + + async def get_object(self, *, bucket: str, key: str) -> bytes: + """Delegate or fail depending on configuration.""" + if self._fail_on == "get_object": + await self._maybe_fail() + return await self._delegate.get_object(bucket=bucket, key=key) + + +@pytest.fixture +def counting_driver_client( + driver_client: S3StorageDriverClient, +) -> CountingDriverClient: + """Wrap the driver client in a counting decorator.""" + return CountingDriverClient(driver_client) + + +# --------------------------------------------------------------------------- +# TestS3StorageDriverInit — no S3 calls; MagicMock client is sufficient +# --------------------------------------------------------------------------- + + +class TestS3StorageDriverInit: + def test_default_name(self) -> None: + driver = S3StorageDriver( + client=MagicMock(spec=S3StorageDriverClient), bucket=BUCKET + ) + assert driver.name() == "aws.s3driver" + + def test_custom_name(self) -> None: + driver = S3StorageDriver( + client=MagicMock(spec=S3StorageDriverClient), + bucket=BUCKET, + driver_name="my-s3", + ) + assert driver.name() == "my-s3" + + def test_type(self) -> None: + driver = S3StorageDriver( + client=MagicMock(spec=S3StorageDriverClient), bucket=BUCKET + ) + assert driver.type() == "aws.s3driver" + + +# --------------------------------------------------------------------------- +# TestS3StorageDriverKeyConstruction +# --------------------------------------------------------------------------- + + +class TestS3StorageDriverKeyConstruction: + async def test_key_context_none(self, driver_client: S3StorageDriverClient) -> None: + driver = S3StorageDriver(client=driver_client, bucket=BUCKET) + payload = make_payload() + [claim] = await driver.store(make_store_context(), [payload]) + expected_hash = hashlib.sha256(payload.SerializeToString()).hexdigest() + assert claim.claim_data["key"] == f"v0/d/sha256/{expected_hash}" + + async def test_key_context_workflow( + self, driver_client: S3StorageDriverClient + ) -> None: + driver = S3StorageDriver(client=driver_client, bucket=BUCKET) + payload = make_payload() + ctx = make_store_context( + make_workflow_context(namespace="ns1", workflow_id="wf1") + ) + [claim] = await driver.store(ctx, [payload]) + expected_hash = hashlib.sha256(payload.SerializeToString()).hexdigest() + assert claim.claim_data["key"] == f"v0/ns/ns1/wfi/wf1/d/sha256/{expected_hash}" + + async def test_key_context_workflow_activity( + self, driver_client: S3StorageDriverClient + ) -> None: + """workflow_id takes priority over activity_id in ActivitySerializationContext.""" + driver = S3StorageDriver(client=driver_client, bucket=BUCKET) + payload = make_payload() + ctx = make_store_context( + make_activity_context( + namespace="ns1", workflow_id="wf1", activity_id="act1" + ) + ) + [claim] = await driver.store(ctx, [payload]) + expected_hash = hashlib.sha256(payload.SerializeToString()).hexdigest() + assert claim.claim_data["key"] == f"v0/ns/ns1/wfi/wf1/d/sha256/{expected_hash}" + + async def test_key_context_standalone_activityt( + self, driver_client: S3StorageDriverClient + ) -> None: + driver = S3StorageDriver(client=driver_client, bucket=BUCKET) + payload = make_payload() + ctx = make_store_context( + make_activity_context(namespace="ns1", activity_id="act1", workflow_id=None) + ) + [claim] = await driver.store(ctx, [payload]) + expected_hash = hashlib.sha256(payload.SerializeToString()).hexdigest() + assert claim.claim_data["key"] == f"v0/ns/ns1/aci/act1/d/sha256/{expected_hash}" + + async def test_key_preserves_case( + self, driver_client: S3StorageDriverClient + ) -> None: + driver = S3StorageDriver(client=driver_client, bucket=BUCKET) + payload = make_payload() + ctx = make_store_context( + make_workflow_context(namespace="MyNamespace", workflow_id="MyWorkflow") + ) + [claim] = await driver.store(ctx, [payload]) + key = claim.claim_data["key"] + assert "MyNamespace" in key + assert "MyWorkflow" in key + + async def test_key_urlencodes_workflow_id_with_slashes( + self, driver_client: S3StorageDriverClient + ) -> None: + driver = S3StorageDriver(client=driver_client, bucket=BUCKET) + payload = make_payload() + ctx = make_store_context( + make_workflow_context(namespace="ns1", workflow_id="order/123/v2") + ) + [claim] = await driver.store(ctx, [payload]) + expected_hash = hashlib.sha256(payload.SerializeToString()).hexdigest() + assert ( + claim.claim_data["key"] + == f"v0/ns/ns1/wfi/order%2F123%2Fv2/d/sha256/{expected_hash}" + ) + + async def test_key_urlencodes_workflow_id_with_special_chars( + self, driver_client: S3StorageDriverClient + ) -> None: + driver = S3StorageDriver(client=driver_client, bucket=BUCKET) + payload = make_payload() + ctx = make_store_context( + make_workflow_context(namespace="ns1", workflow_id="wf#1 &foo=bar") + ) + [claim] = await driver.store(ctx, [payload]) + expected_hash = hashlib.sha256(payload.SerializeToString()).hexdigest() + assert ( + claim.claim_data["key"] + == f"v0/ns/ns1/wfi/wf%231%20%26foo%3Dbar/d/sha256/{expected_hash}" + ) + + async def test_key_urlencodes_activity_id( + self, driver_client: S3StorageDriverClient + ) -> None: + driver = S3StorageDriver(client=driver_client, bucket=BUCKET) + payload = make_payload() + ctx = make_store_context( + make_activity_context( + namespace="ns1", activity_id="act/1#2", workflow_id=None + ) + ) + [claim] = await driver.store(ctx, [payload]) + expected_hash = hashlib.sha256(payload.SerializeToString()).hexdigest() + assert ( + claim.claim_data["key"] + == f"v0/ns/ns1/aci/act%2F1%232/d/sha256/{expected_hash}" + ) + + async def test_key_urlencodes_namespace( + self, driver_client: S3StorageDriverClient + ) -> None: + driver = S3StorageDriver(client=driver_client, bucket=BUCKET) + payload = make_payload() + ctx = make_store_context( + make_workflow_context(namespace="my/ns#1", workflow_id="wf1") + ) + [claim] = await driver.store(ctx, [payload]) + expected_hash = hashlib.sha256(payload.SerializeToString()).hexdigest() + assert ( + claim.claim_data["key"] + == f"v0/ns/my%2Fns%231/wfi/wf1/d/sha256/{expected_hash}" + ) + + async def test_key_urlencoded_roundtrip( + self, driver_client: S3StorageDriverClient + ) -> None: + """Payloads stored with special-char IDs can be retrieved correctly.""" + driver = S3StorageDriver(client=driver_client, bucket=BUCKET) + payload = make_payload("special-char-roundtrip") + ctx = make_store_context( + make_workflow_context(namespace="ns/1", workflow_id="wf/2#3") + ) + [claim] = await driver.store(ctx, [payload]) + [retrieved] = await driver.retrieve(StorageDriverRetrieveContext(), [claim]) + assert retrieved == payload + + +# --------------------------------------------------------------------------- +# TestS3StorageDriverStoreRetrieve +# --------------------------------------------------------------------------- + + +class TestS3StorageDriverStoreRetrieve: + async def test_store_returns_claim_with_bucket_key_and_hash( + self, driver_client: S3StorageDriverClient + ) -> None: + driver = S3StorageDriver(client=driver_client, bucket=BUCKET) + payload = make_payload() + [claim] = await driver.store(make_store_context(), [payload]) + assert claim.claim_data["bucket"] == BUCKET + assert "key" in claim.claim_data + assert claim.claim_data["hash_algorithm"] == "sha256" + expected_hash = hashlib.sha256(payload.SerializeToString()).hexdigest() + assert claim.claim_data["hash_value"] == expected_hash + + async def test_roundtrip_single_payload( + self, driver_client: S3StorageDriverClient + ) -> None: + driver = S3StorageDriver(client=driver_client, bucket=BUCKET) + payload = make_payload("round-trip value") + [claim] = await driver.store(make_store_context(), [payload]) + [retrieved] = await driver.retrieve(StorageDriverRetrieveContext(), [claim]) + assert retrieved == payload + + async def test_roundtrip_multiple_payloads( + self, driver_client: S3StorageDriverClient + ) -> None: + driver = S3StorageDriver(client=driver_client, bucket=BUCKET) + payloads = [make_payload(f"value-{i}") for i in range(3)] + claims = await driver.store(make_store_context(), payloads) + retrieved = await driver.retrieve(StorageDriverRetrieveContext(), claims) + assert retrieved == payloads + + async def test_empty_payloads_returns_empty_list( + self, driver_client: S3StorageDriverClient + ) -> None: + driver = S3StorageDriver(client=driver_client, bucket=BUCKET) + assert await driver.store(make_store_context(), []) == [] + assert await driver.retrieve(StorageDriverRetrieveContext(), []) == [] + + async def test_roundtrip_multipart_payload( + self, aioboto3_client: S3Client, driver_client: S3StorageDriverClient + ) -> None: + """Payloads above the 8 MiB multipart threshold are uploaded via multipart + and retrieved correctly. The S3 ETag for multipart objects contains a '-' + suffix (e.g. 'hash-2'), which we assert to confirm multipart was used.""" + driver = S3StorageDriver(client=driver_client, bucket=BUCKET) + # Slightly above the default 8 MiB multipart_threshold + large_payload = make_payload("x" * (9 * 1024 * 1024)) + [claim] = await driver.store(make_store_context(), [large_payload]) + [retrieved] = await driver.retrieve(StorageDriverRetrieveContext(), [claim]) + assert retrieved == large_payload + head = await aioboto3_client.head_object( + Bucket=BUCKET, Key=claim.claim_data["key"] + ) + assert "-" in head["ETag"], "Expected a multipart ETag (hash-N format)" + + async def test_content_addressable_deduplication( + self, aioboto3_client: S3Client, driver_client: S3StorageDriverClient + ) -> None: + """Two identical payloads produce the same S3 key; only one object is stored.""" + driver = S3StorageDriver(client=driver_client, bucket=BUCKET) + payload = make_payload("same-value") + claims = await driver.store(make_store_context(), [payload, payload]) + assert claims[0].claim_data["key"] == claims[1].claim_data["key"] + response = await aioboto3_client.list_objects_v2(Bucket=BUCKET) + assert response["KeyCount"] == 1 + + async def test_skips_upload_when_key_exists( + self, counting_driver_client: CountingDriverClient + ) -> None: + """When a key already exists in S3, put_object is not called again.""" + driver = S3StorageDriver(client=counting_driver_client, bucket=BUCKET) + payload = make_payload("upload-once") + + await driver.store(make_store_context(), [payload]) + assert counting_driver_client.put_object_count == 1 + + await driver.store(make_store_context(), [payload]) + assert ( + counting_driver_client.put_object_count == 1 + ), "put_object should not be called for an existing key" + + async def test_skips_upload_preserves_data( + self, driver_client: S3StorageDriverClient + ) -> None: + """Storing the same payload twice returns correct data on retrieve.""" + driver = S3StorageDriver(client=driver_client, bucket=BUCKET) + payload = make_payload("preserve-me") + + [claim1] = await driver.store(make_store_context(), [payload]) + [claim2] = await driver.store(make_store_context(), [payload]) + assert claim1 == claim2 + + [retrieved] = await driver.retrieve(StorageDriverRetrieveContext(), [claim2]) + assert retrieved == payload + + async def test_retrieve_validates_hash( + self, driver_client: S3StorageDriverClient + ) -> None: + """Retrieve raises RuntimeError when the hash in the claim doesn't match.""" + driver = S3StorageDriver(client=driver_client, bucket=BUCKET) + payload = make_payload("check-integrity") + [claim] = await driver.store(make_store_context(), [payload]) + + tampered_claim = StorageDriverClaim( + claim_data={ + **claim.claim_data, + "hash_value": "0" * 64, + }, + ) + with pytest.raises( + ValueError, + match=r"S3StorageDriver integrity check failed \[bucket=.+, key=.+\]: expected sha256:.+, got sha256:.+", + ): + await driver.retrieve(StorageDriverRetrieveContext(), [tampered_claim]) + + async def test_retrieve_rejects_unsupported_hash_algorithm( + self, driver_client: S3StorageDriverClient + ) -> None: + """Retrieve raises ValueError when the claim specifies a non-sha256 algorithm.""" + driver = S3StorageDriver(client=driver_client, bucket=BUCKET) + payload = make_payload("unsupported-algo") + [claim] = await driver.store(make_store_context(), [payload]) + + bad_claim = StorageDriverClaim( + claim_data={ + **claim.claim_data, + "hash_algorithm": "md5", + }, + ) + with pytest.raises( + ValueError, + match=r"S3StorageDriver unsupported hash algorithm \[bucket=.+, key=.+\]: expected sha256, got md5", + ): + await driver.retrieve(StorageDriverRetrieveContext(), [bad_claim]) + + async def test_retrieve_without_hash_in_claim( + self, driver_client: S3StorageDriverClient + ) -> None: + """Claims without hash fields still retrieve successfully (backward compat).""" + driver = S3StorageDriver(client=driver_client, bucket=BUCKET) + payload = make_payload("no-hash-claim") + [claim] = await driver.store(make_store_context(), [payload]) + + legacy_claim = StorageDriverClaim( + claim_data={ + "bucket": claim.claim_data["bucket"], + "key": claim.claim_data["key"], + }, + ) + [retrieved] = await driver.retrieve( + StorageDriverRetrieveContext(), [legacy_claim] + ) + assert retrieved == payload + + +# --------------------------------------------------------------------------- +# TestS3StorageDriverBucketCallable +# --------------------------------------------------------------------------- + + +class TestS3StorageDriverBucketCallable: + async def test_callable_selector_routes_bucket( + self, aioboto3_client: S3Client, driver_client: S3StorageDriverClient + ) -> None: + other_bucket = "other-bucket" + await aioboto3_client.create_bucket(Bucket=other_bucket) + driver = S3StorageDriver( + client=driver_client, + bucket=lambda ctx, p: other_bucket, + ) + [claim] = await driver.store(make_store_context(), [make_payload()]) + assert claim.claim_data["bucket"] == other_bucket + + async def test_selector_called_per_payload( + self, driver_client: S3StorageDriverClient + ) -> None: + call_count = 0 + + def counting_selector(_ctx: StorageDriverStoreContext, _p: Payload) -> str: + nonlocal call_count + call_count += 1 + return BUCKET + + driver = S3StorageDriver(client=driver_client, bucket=counting_selector) + await driver.store( + make_store_context(), [make_payload(f"v{i}") for i in range(3)] + ) + assert call_count == 3 + + async def test_selector_routes_by_activity_task_queue( + self, aioboto3_client: S3Client, driver_client: S3StorageDriverClient + ) -> None: + """bucket callable can route payloads to different buckets by activity task queue.""" + bucket_a = "bucket-queue-a" + bucket_b = "bucket-queue-b" + await aioboto3_client.create_bucket(Bucket=bucket_a) + await aioboto3_client.create_bucket(Bucket=bucket_b) + + queue_buckets = {"queue-a": bucket_a, "queue-b": bucket_b} + + def queue_selector(ctx: StorageDriverStoreContext, p: Payload) -> str: + del p + if isinstance(ctx.serialization_context, ActivitySerializationContext): + queue = ctx.serialization_context.activity_task_queue + if queue and queue in queue_buckets: + return queue_buckets[queue] + return BUCKET + + driver = S3StorageDriver(client=driver_client, bucket=queue_selector) + + ctx_a = make_store_context( + make_activity_context( + namespace="ns1", + activity_id="act1", + workflow_id="wf1", + activity_task_queue="queue-a", + ) + ) + [claim_a] = await driver.store(ctx_a, [make_payload("payload-a")]) + assert claim_a.claim_data["bucket"] == bucket_a + + ctx_b = make_store_context( + make_activity_context( + namespace="ns1", + activity_id="act2", + workflow_id="wf1", + activity_task_queue="queue-b", + ) + ) + [claim_b] = await driver.store(ctx_b, [make_payload("payload-b")]) + assert claim_b.claim_data["bucket"] == bucket_b + + async def test_selector_receives_context_and_payload( + self, driver_client: S3StorageDriverClient + ) -> None: + received: list[tuple[StorageDriverStoreContext, Payload]] = [] + + def capturing_selector(ctx: StorageDriverStoreContext, p: Payload) -> str: + received.append((ctx, p)) + return BUCKET + + payload = make_payload() + store_ctx = make_store_context(make_workflow_context()) + driver = S3StorageDriver(client=driver_client, bucket=capturing_selector) + await driver.store(store_ctx, [payload]) + + assert len(received) == 1 + assert received[0][0] is store_ctx + assert received[0][1] == payload + + +# --------------------------------------------------------------------------- +# TestS3StorageDriverErrors +# --------------------------------------------------------------------------- + + +class TestS3StorageDriverErrors: + async def test_store_nonexistent_bucket_raises( + self, driver_client: S3StorageDriverClient + ) -> None: + bucket = "does-not-exist" + payload = make_payload() + driver = S3StorageDriver(client=driver_client, bucket=bucket) + expected_hash = hashlib.sha256(payload.SerializeToString()).hexdigest() + expected_key = f"v0/d/sha256/{expected_hash}" + with pytest.raises(RuntimeError) as exc_info: + await driver.store(make_store_context(), [payload]) + assert ( + str(exc_info.value) + == f"S3StorageDriver store failed [bucket={bucket}, key={expected_key}]" + ) + assert isinstance(exc_info.value.__cause__, ClientError) + assert ( + exc_info.value.__cause__.response.get("Error", {}).get("Code") + == "NoSuchBucket" + ) + + async def test_retrieve_nonexistent_key_raises( + self, driver_client: S3StorageDriverClient + ) -> None: + key = "/d/sha256/nonexistent" + driver = S3StorageDriver(client=driver_client, bucket=BUCKET) + claim = StorageDriverClaim(claim_data={"bucket": BUCKET, "key": key}) + with pytest.raises(RuntimeError) as exc_info: + await driver.retrieve(StorageDriverRetrieveContext(), [claim]) + assert ( + str(exc_info.value) + == f"S3StorageDriver retrieve failed [bucket={BUCKET}, key={key}]" + ) + assert isinstance(exc_info.value.__cause__, ClientError) + assert ( + exc_info.value.__cause__.response.get("Error", {}).get("Code") + == "NoSuchKey" + ) + + async def test_retrieve_nonexistent_bucket_raises( + self, driver_client: S3StorageDriverClient + ) -> None: + bucket = "does-not-exist" + key = "/d/sha256/anything" + driver = S3StorageDriver(client=driver_client, bucket=BUCKET) + claim = StorageDriverClaim(claim_data={"bucket": bucket, "key": key}) + with pytest.raises(RuntimeError) as exc_info: + await driver.retrieve(StorageDriverRetrieveContext(), [claim]) + assert ( + str(exc_info.value) + == f"S3StorageDriver retrieve failed [bucket={bucket}, key={key}]" + ) + assert isinstance(exc_info.value.__cause__, ClientError) + assert ( + exc_info.value.__cause__.response.get("Error", {}).get("Code") + == "NoSuchBucket" + ) + + async def test_bucket_callable_exception_propagates( + self, driver_client: S3StorageDriverClient + ) -> None: + selector = MagicMock(side_effect=RuntimeError("selector failed")) + driver = S3StorageDriver(client=driver_client, bucket=selector) + with pytest.raises(RuntimeError, match="selector failed"): + await driver.store(make_store_context(), [make_payload()]) + + def test_max_payload_size_zero_raises(self) -> None: + with pytest.raises( + ValueError, match="max_payload_size must be greater than zero" + ): + S3StorageDriver( + client=MagicMock(spec=S3StorageDriverClient), + bucket=BUCKET, + max_payload_size=0, + ) + + def test_max_payload_size_negative_raises(self) -> None: + with pytest.raises( + ValueError, match="max_payload_size must be greater than zero" + ): + S3StorageDriver( + client=MagicMock(spec=S3StorageDriverClient), + bucket=BUCKET, + max_payload_size=-1, + ) + + async def test_payload_exceeds_max_size_raises( + self, driver_client: S3StorageDriverClient + ) -> None: + driver = S3StorageDriver( + client=driver_client, bucket=BUCKET, max_payload_size=10 + ) + with pytest.raises( + ValueError, + match=r"Payload size \d+ bytes exceeds the configured max_payload_size of 10 bytes", + ): + await driver.store(make_store_context(), [make_payload("exceeds-limit")]) + + async def test_payload_at_max_size_succeeds( + self, driver_client: S3StorageDriverClient + ) -> None: + payload = make_payload("x") + driver = S3StorageDriver( + client=driver_client, + bucket=BUCKET, + max_payload_size=len(payload.SerializeToString()), + ) + await driver.store(make_store_context(), [payload]) + + +# --------------------------------------------------------------------------- +# TestS3StorageDriverConcurrency +# --------------------------------------------------------------------------- + + +class _AsyncBarrier: + """Minimal asyncio.Barrier equivalent for Python <3.11.""" + + def __init__(self, parties: int) -> None: + self._parties = parties + self._count = 0 + self._event = asyncio.Event() + + async def wait(self) -> None: + self._count += 1 + if self._count >= self._parties: + self._event.set() + else: + await self._event.wait() + + +def _barrier_wrapper( + fn: Callable[..., Coroutine[Any, Any, Any]], barrier: _AsyncBarrier +): + """Wrap an async method to wait at a barrier before proceeding. + + All concurrent callers must reach the barrier before any of them continue. + If the calls are sequential, the barrier will never be satisfied and the + test times out. + """ + + @wraps(fn) + async def wrapper(*args: Any, **kwargs: Any) -> Any: + await asyncio.wait_for(barrier.wait(), timeout=5) + return await fn(*args, **kwargs) + + return wrapper + + +class TestS3StorageDriverConcurrency: + async def test_store_payloads_concurrently( + self, driver_client: S3StorageDriverClient + ) -> None: + """All uploads must be in-flight concurrently. + + A barrier sized to ``num_payloads`` blocks each upload until every + upload has started. If the driver dispatches sequentially the barrier + is never satisfied and the test times out. + """ + num_payloads = 5 + barrier = _AsyncBarrier(num_payloads) + driver_client.put_object = _barrier_wrapper(driver_client.put_object, barrier) # type: ignore[method-assign] + + driver = S3StorageDriver(client=driver_client, bucket=BUCKET) + payloads = [make_payload(f"concurrent-store-{i}") for i in range(num_payloads)] + + claims = await driver.store(make_store_context(), payloads) + assert len(claims) == num_payloads + + async def test_retrieve_payloads_concurrently( + self, driver_client: S3StorageDriverClient + ) -> None: + """All downloads must be in-flight concurrently.""" + num_payloads = 5 + driver = S3StorageDriver(client=driver_client, bucket=BUCKET) + payloads = [ + make_payload(f"concurrent-retrieve-{i}") for i in range(num_payloads) + ] + claims = await driver.store(make_store_context(), payloads) + + barrier = _AsyncBarrier(num_payloads) + driver_client.get_object = _barrier_wrapper(driver_client.get_object, barrier) # type: ignore[method-assign] + + retrieved = await driver.retrieve(StorageDriverRetrieveContext(), claims) + assert retrieved == payloads + + async def test_store_cancels_remaining_on_failure( + self, driver_client: S3StorageDriverClient + ) -> None: + """When one upload fails, all other in-flight uploads are cancelled.""" + faulty_client = FailOnceDriverClient( + delegate=driver_client, + fail_on="object_exists", + ) + driver = S3StorageDriver(client=faulty_client, bucket=BUCKET) + payloads = [make_payload(f"cancel-store-{i}") for i in range(3)] + + with pytest.raises( + RuntimeError, + match=r"S3StorageDriver store failed \[bucket=.+, key=.+\]", + ) as exc_info: + await driver.store(make_store_context(), payloads) + + assert isinstance(exc_info.value.__cause__, ConnectionError) + assert str(exc_info.value.__cause__) == "S3 connection lost" + assert ( + len(faulty_client.cancelled) == 2 + ), "Expected 2 remaining tasks to be cancelled" + + async def test_retrieve_cancels_remaining_on_failure( + self, driver_client: S3StorageDriverClient + ) -> None: + """When one download fails, all other in-flight downloads are cancelled.""" + driver = S3StorageDriver(client=driver_client, bucket=BUCKET) + payloads = [make_payload(f"cancel-retrieve-{i}") for i in range(3)] + claims = await driver.store(make_store_context(), payloads) + + faulty_client = FailOnceDriverClient( + delegate=driver_client, + fail_on="get_object", + ) + driver = S3StorageDriver(client=faulty_client, bucket=BUCKET) + + with pytest.raises( + RuntimeError, + match=r"S3StorageDriver retrieve failed \[bucket=.+, key=.+\]", + ) as exc_info: + await driver.retrieve(StorageDriverRetrieveContext(), claims) + + assert isinstance(exc_info.value.__cause__, ConnectionError) + assert str(exc_info.value.__cause__) == "S3 connection lost" + assert ( + len(faulty_client.cancelled) == 2 + ), "Expected 2 remaining tasks to be cancelled" diff --git a/tests/contrib/aws/s3driver/test_s3driver_worker.py b/tests/contrib/aws/s3driver/test_s3driver_worker.py new file mode 100644 index 000000000..87ab73736 --- /dev/null +++ b/tests/contrib/aws/s3driver/test_s3driver_worker.py @@ -0,0 +1,414 @@ +"""Worker integration tests for S3StorageDriver key structure. + +Runs real Temporal workflows against a real worker (backed by a moto S3 +server) and asserts the S3 object key structure produced for each Temporal +primitive: workflow input/output, activity input/output, signals, queries, +updates, and child workflows. +""" + +from __future__ import annotations + +import dataclasses +import hashlib +import uuid +from collections.abc import AsyncIterator +from datetime import timedelta + +import aioboto3 +import pytest +from types_aiobotocore_s3.client import S3Client + +import temporalio.converter +from temporalio.client import Client, WorkflowFailureError +from temporalio.contrib.aws.s3driver import S3StorageDriver +from temporalio.contrib.aws.s3driver.aioboto3 import new_aioboto3_client +from temporalio.converter import ExternalStorage, JSONPlainPayloadConverter +from temporalio.exceptions import ActivityError, ApplicationError +from temporalio.testing import WorkflowEnvironment +from tests.contrib.aws.s3driver.conftest import BUCKET, REGION +from tests.contrib.aws.s3driver.workflows import ( + LARGE, + ChildWorkflow, + DocumentIngestionWorkflow, + LargeIOWorkflow, + LargeOutputNoRetryWorkflow, + ModelTrainingWorkflow, + OrderFulfillmentWorkflow, + ParentWithChildWorkflow, + PaymentProcessingWorkflow, + SignalQueryUpdateWorkflow, + download_document, + extract_text, + index_document, + large_io_activity, + large_output_activity, +) +from tests.helpers import new_worker + +# --------------------------------------------------------------------------- +# Constants +# --------------------------------------------------------------------------- + +_THRESHOLD = 256 # bytes — low so all test payloads are offloaded + +# --------------------------------------------------------------------------- +# Fixtures +# --------------------------------------------------------------------------- + + +@pytest.fixture +async def tmprl_client( + env: WorkflowEnvironment, aioboto3_client: S3Client +) -> AsyncIterator[Client]: + """Temporal client wired with ExternalStorage backed by the moto S3 server.""" + driver = S3StorageDriver(client=new_aioboto3_client(aioboto3_client), bucket=BUCKET) + yield await Client.connect( + env.client.service_client.config.target_host, + namespace=env.client.namespace, + data_converter=dataclasses.replace( + temporalio.converter.default(), + external_storage=ExternalStorage( + drivers=[driver], + payload_size_threshold=_THRESHOLD, + ), + ), + ) + + +# --------------------------------------------------------------------------- +# Helper +# --------------------------------------------------------------------------- + + +async def _list_keys(aioboto3_client: S3Client) -> list[str]: + resp = await aioboto3_client.list_objects_v2(Bucket=BUCKET) + return sorted( + key for obj in resp.get("Contents", []) if (key := obj.get("Key")) is not None + ) + + +# --------------------------------------------------------------------------- +# Tests +# --------------------------------------------------------------------------- + + +async def test_s3_driver_workflow_input_key( + tmprl_client: Client, aioboto3_client: S3Client +) -> None: + workflow_id = str(uuid.uuid4()) + async with new_worker( + tmprl_client, LargeIOWorkflow, activities=[large_io_activity] + ) as worker: + await tmprl_client.execute_workflow( + LargeIOWorkflow.run, + LARGE, + id=workflow_id, + task_queue=worker.task_queue, + execution_timeout=timedelta(seconds=5), + ) + keys = await _list_keys(aioboto3_client) + assert len(keys) == 1 + assert f"/ns/default/wfi/{workflow_id}/d/sha256/" in keys[0] + + +async def test_s3_driver_workflow_output_key( + tmprl_client: Client, aioboto3_client: S3Client +) -> None: + workflow_id = str(uuid.uuid4()) + async with new_worker( + tmprl_client, LargeIOWorkflow, activities=[large_io_activity] + ) as worker: + result = await tmprl_client.execute_workflow( + LargeIOWorkflow.run, + "small", # small input stays inline; workflow returns LARGE + id=workflow_id, + task_queue=worker.task_queue, + execution_timeout=timedelta(seconds=5), + ) + assert result == LARGE + keys = await _list_keys(aioboto3_client) + assert len(keys) == 1 + assert f"/ns/default/wfi/{workflow_id}/d/sha256/" in keys[0] + + +async def test_s3_driver_workflow_activity_input_key( + tmprl_client: Client, aioboto3_client: S3Client +) -> None: + workflow_id = str(uuid.uuid4()) + async with new_worker( + tmprl_client, LargeIOWorkflow, activities=[large_io_activity] + ) as worker: + await tmprl_client.execute_workflow( + LargeIOWorkflow.run, + LARGE, # passed through as the activity's input + id=workflow_id, + task_queue=worker.task_queue, + execution_timeout=timedelta(seconds=5), + ) + keys = await _list_keys(aioboto3_client) + assert len(keys) == 1 + assert f"/ns/default/wfi/{workflow_id}/" in keys[0] + assert ( + "/aci/" not in keys[0] + ), "Activity input should use workflow_id, not activity_id" + + +async def test_s3_driver_workflow_activity_output_key( + tmprl_client: Client, aioboto3_client: S3Client +) -> None: + workflow_id = str(uuid.uuid4()) + async with new_worker( + tmprl_client, LargeIOWorkflow, activities=[large_io_activity] + ) as worker: + await tmprl_client.execute_workflow( + LargeIOWorkflow.run, + "small", # small input; activity returns LARGE + id=workflow_id, + task_queue=worker.task_queue, + execution_timeout=timedelta(seconds=5), + ) + keys = await _list_keys(aioboto3_client) + assert len(keys) == 1 + assert f"/ns/default/wfi/{workflow_id}/d/sha256/" in keys[0] + + +async def test_s3_driver_signal_arg_key( + tmprl_client: Client, aioboto3_client: S3Client +) -> None: + workflow_id = str(uuid.uuid4()) + async with new_worker(tmprl_client, SignalQueryUpdateWorkflow) as worker: + handle = await tmprl_client.start_workflow( + SignalQueryUpdateWorkflow.run, + id=workflow_id, + task_queue=worker.task_queue, + execution_timeout=timedelta(seconds=5), + ) + await handle.signal(SignalQueryUpdateWorkflow.finish, LARGE) + await handle.result() + keys = await _list_keys(aioboto3_client) + assert len(keys) == 1 + assert f"/ns/default/wfi/{workflow_id}/d/sha256/" in keys[0] + + +async def test_s3_driver_query_result_key( + tmprl_client: Client, aioboto3_client: S3Client +) -> None: + workflow_id = str(uuid.uuid4()) + async with new_worker(tmprl_client, SignalQueryUpdateWorkflow) as worker: + handle = await tmprl_client.start_workflow( + SignalQueryUpdateWorkflow.run, + id=workflow_id, + task_queue=worker.task_queue, + execution_timeout=timedelta(seconds=5), + ) + result = await handle.query(SignalQueryUpdateWorkflow.get_value, LARGE) + assert result == LARGE + await handle.signal(SignalQueryUpdateWorkflow.finish, "done") + await handle.result() + keys = await _list_keys(aioboto3_client) + assert len(keys) == 1 + assert f"/ns/default/wfi/{workflow_id}/d/sha256/" in keys[0] + + +async def test_s3_driver_update_result_key( + tmprl_client: Client, aioboto3_client: S3Client +) -> None: + workflow_id = str(uuid.uuid4()) + async with new_worker(tmprl_client, SignalQueryUpdateWorkflow) as worker: + handle = await tmprl_client.start_workflow( + SignalQueryUpdateWorkflow.run, + id=workflow_id, + task_queue=worker.task_queue, + execution_timeout=timedelta(seconds=5), + ) + result = await handle.execute_update(SignalQueryUpdateWorkflow.do_update, LARGE) + assert result == LARGE + await handle.signal(SignalQueryUpdateWorkflow.finish, "done") + await handle.result() + keys = await _list_keys(aioboto3_client) + assert len(keys) == 1 + assert f"/ns/default/wfi/{workflow_id}/d/sha256/" in keys[0] + + +async def test_s3_driver_child_workflow_input_key( + tmprl_client: Client, aioboto3_client: S3Client +) -> None: + workflow_id = str(uuid.uuid4()) + async with new_worker( + tmprl_client, ParentWithChildWorkflow, ChildWorkflow + ) as worker: + await tmprl_client.execute_workflow( + ParentWithChildWorkflow.run, + id=workflow_id, + task_queue=worker.task_queue, + execution_timeout=timedelta(seconds=5), + ) + keys = await _list_keys(aioboto3_client) + assert len(keys) == 1 + child_workflow_id = f"{workflow_id}-child" + assert f"/ns/default/wfi/{child_workflow_id}/d/sha256/" in keys[0] + + +async def test_s3_driver_identified_casing( + tmprl_client: Client, aioboto3_client: S3Client +) -> None: + workflow_id = f"MyWorkflow-{uuid.uuid4()}" + async with new_worker( + tmprl_client, LargeIOWorkflow, activities=[large_io_activity] + ) as worker: + await tmprl_client.execute_workflow( + LargeIOWorkflow.run, + LARGE, + id=workflow_id, + task_queue=worker.task_queue, + execution_timeout=timedelta(seconds=5), + ) + keys = await _list_keys(aioboto3_client) + assert len(keys) == 1 + assert "/ns/default/" in keys[0], "Namespace segment should be present" + assert ( + f"/wfi/{workflow_id}/" in keys[0] + ), "Workflow ID should preserve original case in the key" + + +async def test_s3_driver_content_dedup( + tmprl_client: Client, aioboto3_client: S3Client +) -> None: + """Document ingestion produces exactly two distinct S3 keys, even though + the payloads are repeatedly passed to different activities.""" + workflow_id = str(uuid.uuid4()) + async with new_worker( + tmprl_client, + DocumentIngestionWorkflow, + activities=[download_document, extract_text, index_document], + ) as worker: + await tmprl_client.execute_workflow( + DocumentIngestionWorkflow.run, + "doc-001", + id=workflow_id, + task_queue=worker.task_queue, + execution_timeout=timedelta(seconds=5), + ) + keys = await _list_keys(aioboto3_client) + assert len(keys) == 2 + assert f"/ns/default/wfi/{workflow_id}/d/sha256/" in keys[0] + assert f"/ns/default/wfi/{workflow_id}/d/sha256/" in keys[1] + assert keys[0] != keys[1] + + +async def test_s3_driver_single_workflow_same_key_namespace( + tmprl_client: Client, aioboto3_client: S3Client +) -> None: + """A training job started with a large config, injected with large override + parameters mid-run, and polled for large metrics — all produce S3 keys + under the same workflow ID prefix, regardless of which primitive carried + the payload.""" + workflow_id = str(uuid.uuid4()) + async with new_worker(tmprl_client, ModelTrainingWorkflow) as worker: + handle = await tmprl_client.start_workflow( + ModelTrainingWorkflow.run, + LARGE, # large training config as workflow input + id=workflow_id, + task_queue=worker.task_queue, + execution_timeout=timedelta(seconds=5), + ) + metrics = await handle.execute_update( + ModelTrainingWorkflow.get_metrics, "checkpoint-1" + ) + assert metrics is not None + await handle.signal(ModelTrainingWorkflow.apply_overrides, LARGE) + await handle.signal(ModelTrainingWorkflow.complete) + await handle.result() + keys = await _list_keys(aioboto3_client) + # LARGE (input + signal arg) and LARGE_2 (metrics result) deduplicate to + # two distinct keys — both anchored under the same workflow ID prefix. + assert len(keys) == 2 + assert all(f"/ns/default/wfi/{workflow_id}/" in key for key in keys) + + +async def test_s3_driver_parent_child_independent_key_namespaces( + tmprl_client: Client, aioboto3_client: S3Client +) -> None: + """An order fulfillment workflow spawns a child payment processor, passes it + a large order payload, and returns the child's large payment confirmation. + Each workflow accumulates S3 keys under its own workflow ID prefix — + parent and child key namespaces are fully independent.""" + workflow_id = str(uuid.uuid4()) + payment_id = f"{workflow_id}-payment" + async with new_worker( + tmprl_client, OrderFulfillmentWorkflow, PaymentProcessingWorkflow + ) as worker: + await tmprl_client.execute_workflow( + OrderFulfillmentWorkflow.run, + LARGE, # large order details passed to parent and forwarded to child + id=workflow_id, + task_queue=worker.task_queue, + execution_timeout=timedelta(seconds=5), + ) + keys = await _list_keys(aioboto3_client) + parent_prefix = f"/ns/default/wfi/{workflow_id}/d/" + child_prefix = f"/ns/default/wfi/{payment_id}/d/" + parent_keys = [k for k in keys if parent_prefix in k] + child_keys = [k for k in keys if child_prefix in k] + # The parent stores its input (LARGE) and the child's result propagated + # back (LARGE_2) under the parent's prefix → 2 keys. + # The child stores its input (LARGE) and its result (LARGE_2) under the + # child's prefix → 2 keys. + assert len(parent_keys) == 2 + assert len(child_keys) == 2 + + +async def test_s3_store_failure_surfaces_in_workflow_history( + env: WorkflowEnvironment, moto_server_url: str +) -> None: + """Verifies that an S3 store failure (nonexistent bucket) produces a + RuntimeError with bucket and key context that is visible in Temporal + workflow history via the WorkflowFailureError cause chain.""" + bad_bucket = "nonexistent-bucket" + session = aioboto3.Session() + async with session.client( + "s3", + region_name=REGION, + endpoint_url=moto_server_url, + aws_access_key_id="testing", + aws_secret_access_key="testing", + ) as client: + driver = S3StorageDriver(client=new_aioboto3_client(client), bucket=bad_bucket) + bad_client = await Client.connect( + env.client.service_client.config.target_host, + namespace=env.client.namespace, + data_converter=dataclasses.replace( + temporalio.converter.default(), + external_storage=ExternalStorage( + drivers=[driver], + payload_size_threshold=_THRESHOLD, + ), + ), + ) + workflow_id = str(uuid.uuid4()) + async with new_worker( + bad_client, LargeOutputNoRetryWorkflow, activities=[large_output_activity] + ) as worker: + with pytest.raises(WorkflowFailureError) as exc_info: + await bad_client.execute_workflow( + LargeOutputNoRetryWorkflow.run, + id=workflow_id, + task_queue=worker.task_queue, + execution_timeout=timedelta(seconds=5), + ) + + large_payload = JSONPlainPayloadConverter().to_payload(LARGE) + assert large_payload is not None + expected_hash = hashlib.sha256(large_payload.SerializeToString()).hexdigest() + expected_key = f"v0/ns/default/wfi/{workflow_id}/d/sha256/{expected_hash}" + + assert isinstance(exc_info.value, WorkflowFailureError) + activity_error = exc_info.value.__cause__ + assert isinstance(activity_error, ActivityError) + app_error = activity_error.__cause__ + assert isinstance(app_error, ApplicationError) + assert app_error.type == "RuntimeError" + assert ( + app_error.message + == f"S3StorageDriver store failed [bucket={bad_bucket}, key={expected_key}]" + ) diff --git a/tests/contrib/aws/s3driver/workflows.py b/tests/contrib/aws/s3driver/workflows.py new file mode 100644 index 000000000..4f4b43099 --- /dev/null +++ b/tests/contrib/aws/s3driver/workflows.py @@ -0,0 +1,223 @@ +"""Workflow and activity definitions for test_s3driver.py integration tests. + +Kept in a separate module so the workflow sandbox does not encounter +aioboto3/aiobotocore/botocore/urllib3 imports when preparing workflow classes. +""" + +from __future__ import annotations + +from datetime import timedelta + +from temporalio import activity, workflow +from temporalio.common import RetryPolicy + +LARGE = "x" * 356 # ~358 bytes as a JSON string, above the 256-byte test threshold +LARGE_2 = "y" * 356 # distinct large payload with a different SHA-256 hash + + +@activity.defn +async def large_io_activity(_data: str) -> str: + return LARGE + + +@activity.defn +async def large_output_activity() -> str: + """Returns a large payload with no retries; used to test S3 store failures.""" + return LARGE + + +@workflow.defn +class LargeOutputNoRetryWorkflow: + """Executes a single activity that returns a large payload with no retries. + + Used to verify that S3 store failures surface in workflow history without + retries masking the error. + """ + + @workflow.run + async def run(self) -> str: + return await workflow.execute_activity( + large_output_activity, + schedule_to_close_timeout=timedelta(seconds=10), + retry_policy=RetryPolicy(maximum_attempts=1), + ) + + +@workflow.defn +class LargeIOWorkflow: + """Passes its input to an activity and returns a large output.""" + + @workflow.run + async def run(self, data: str) -> str: + await workflow.execute_activity( + large_io_activity, + data, + schedule_to_close_timeout=timedelta(seconds=10), + ) + return LARGE + + +@activity.defn +async def download_document(document_id: str) -> str: + """Downloads the raw document content from remote storage.""" + del document_id + return LARGE # simulates a large raw document + + +@activity.defn +async def extract_text(raw_content: str) -> str: + """Extracts and normalizes text from the raw document content.""" + del raw_content + return LARGE_2 # simulates extracted text — different content, different hash + + +@activity.defn +async def index_document(text: str) -> str: + """Indexes the extracted text into the search index. Returns the index record ID.""" + del text + return "idx-00001" # small confirmation — not offloaded to external storage + + +@workflow.defn +class DocumentIngestionWorkflow: + """Downloads a document, extracts its text, and indexes it for search. + + Illustrates how large intermediate payloads (raw document content, extracted + text) are transparently offloaded to S3 between activity boundaries without + any special handling in the workflow code. + """ + + @workflow.run + async def run(self, document_id: str) -> str: + raw_content = await workflow.execute_activity( + download_document, + document_id, + schedule_to_close_timeout=timedelta(seconds=10), + ) + extracted_text = await workflow.execute_activity( + extract_text, + raw_content, + schedule_to_close_timeout=timedelta(seconds=10), + ) + return await workflow.execute_activity( + index_document, + extracted_text, + schedule_to_close_timeout=timedelta(seconds=10), + ) + + +@workflow.defn +class ChildWorkflow: + @workflow.run + async def run(self, data: str) -> str: + return f"{len(data)}" + + +@workflow.defn +class ParentWithChildWorkflow: + """Delegates work to a child workflow whose ID is {parent_id}-child.""" + + @workflow.run + async def run(self) -> str: + child_id = f"{workflow.info().workflow_id}-child" + return await workflow.execute_child_workflow( + ChildWorkflow.run, + LARGE, + id=child_id, + execution_timeout=timedelta(seconds=10), + ) + + +@workflow.defn +class PaymentProcessingWorkflow: + """Processes payment for an order and returns a large payment confirmation. + + Intended to be spawned as a child of OrderFulfillmentWorkflow. + """ + + @workflow.run + async def run(self, order_details: str) -> str: + del order_details + return LARGE_2 # payment confirmation + + +@workflow.defn +class OrderFulfillmentWorkflow: + """Coordinates order fulfillment by delegating payment to a child workflow. + + Passes the large order details to a PaymentProcessingWorkflow child whose ID + is {parent_id}-payment, then returns the child's payment confirmation. + """ + + @workflow.run + async def run(self, order_details: str) -> str: + payment_id = f"{workflow.info().workflow_id}-payment" + return await workflow.execute_child_workflow( + PaymentProcessingWorkflow.run, + order_details, + id=payment_id, + execution_timeout=timedelta(seconds=10), + ) + + +@workflow.defn +class ModelTrainingWorkflow: + """Simulates a long-running ML training job. + + Accepts a large training config as input, allows the caller to inject + override parameters mid-run via signal, and exposes intermediate metrics + via an update. Demonstrates that large payloads crossing all three + primitive boundaries (input, signal arg, update result) are stored under + the same workflow ID prefix in S3. + """ + + def __init__(self) -> None: + self._overrides_received = False + self._done = False + + @workflow.run + async def run(self, training_config: str) -> str: + del training_config + await workflow.wait_condition(lambda: self._done) + return LARGE # final training summary + + @workflow.signal + async def apply_overrides(self, override_params: str) -> None: + """Injects updated hyperparameters into the running training job.""" + del override_params + self._overrides_received = True + + @workflow.signal + async def complete(self) -> None: + self._done = True + + @workflow.update + async def get_metrics(self, checkpoint_id: str) -> str: + """Returns the current training metrics snapshot.""" + del checkpoint_id + return LARGE_2 # large metrics payload + + +@workflow.defn +class SignalQueryUpdateWorkflow: + """Long-running workflow that accepts a signal, query, and update.""" + + def __init__(self) -> None: + self._done = False + + @workflow.run + async def run(self) -> str: + await workflow.wait_condition(lambda: self._done) + return LARGE + + @workflow.signal + async def finish(self, _data: str) -> None: + self._done = True + + @workflow.query + def get_value(self, _data: str) -> str: + return LARGE + + @workflow.update + async def do_update(self, _data: str) -> str: + return LARGE diff --git a/uv.lock b/uv.lock index a70f170b2..c63faefad 100644 --- a/uv.lock +++ b/uv.lock @@ -8,6 +8,51 @@ resolution-markers = [ "python_full_version < '3.11'", ] +[[package]] +name = "aioboto3" +version = "15.5.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "aiobotocore", extra = ["boto3"] }, + { name = "aiofiles" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/a2/01/92e9ab00f36e2899315f49eefcd5b4685fbb19016c7f19a9edf06da80bb0/aioboto3-15.5.0.tar.gz", hash = "sha256:ea8d8787d315594842fbfcf2c4dce3bac2ad61be275bc8584b2ce9a3402a6979", size = 255069, upload-time = "2025-10-30T13:37:16.122Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e5/3e/e8f5b665bca646d43b916763c901e00a07e40f7746c9128bdc912a089424/aioboto3-15.5.0-py3-none-any.whl", hash = "sha256:cc880c4d6a8481dd7e05da89f41c384dbd841454fc1998ae25ca9c39201437a6", size = 35913, upload-time = "2025-10-30T13:37:14.549Z" }, +] + +[[package]] +name = "aiobotocore" +version = "2.25.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "aiohttp" }, + { name = "aioitertools" }, + { name = "botocore" }, + { name = "jmespath" }, + { name = "multidict" }, + { name = "python-dateutil" }, + { name = "wrapt" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/62/94/2e4ec48cf1abb89971cb2612d86f979a6240520f0a659b53a43116d344dc/aiobotocore-2.25.1.tar.gz", hash = "sha256:ea9be739bfd7ece8864f072ec99bb9ed5c7e78ebb2b0b15f29781fbe02daedbc", size = 120560, upload-time = "2025-10-28T22:33:21.787Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/95/2a/d275ec4ce5cd0096665043995a7d76f5d0524853c76a3d04656de49f8808/aiobotocore-2.25.1-py3-none-any.whl", hash = "sha256:eb6daebe3cbef5b39a0bb2a97cffbe9c7cb46b2fcc399ad141f369f3c2134b1f", size = 86039, upload-time = "2025-10-28T22:33:19.949Z" }, +] + +[package.optional-dependencies] +boto3 = [ + { name = "boto3" }, +] + +[[package]] +name = "aiofiles" +version = "25.1.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/41/c3/534eac40372d8ee36ef40df62ec129bee4fdb5ad9706e58a29be53b2c970/aiofiles-25.1.0.tar.gz", hash = "sha256:a8d728f0a29de45dc521f18f07297428d56992a742f0cd2701ba86e44d23d5b2", size = 46354, upload-time = "2025-10-09T20:51:04.358Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/bc/8a/340a1555ae33d7354dbca4faa54948d76d89a27ceef032c8c3bc661d003e/aiofiles-25.1.0-py3-none-any.whl", hash = "sha256:abe311e527c862958650f9438e859c1fa7568a141b22abcd015e120e86a85695", size = 14668, upload-time = "2025-10-09T20:51:03.174Z" }, +] + [[package]] name = "aiohappyeyeballs" version = "2.6.1" @@ -22,14 +67,14 @@ name = "aiohttp" version = "3.13.3" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "aiohappyeyeballs", marker = "python_full_version < '3.14'" }, - { name = "aiosignal", marker = "python_full_version < '3.14'" }, + { name = "aiohappyeyeballs" }, + { name = "aiosignal" }, { name = "async-timeout", marker = "python_full_version < '3.11'" }, - { name = "attrs", marker = "python_full_version < '3.14'" }, - { name = "frozenlist", marker = "python_full_version < '3.14'" }, - { name = "multidict", marker = "python_full_version < '3.14'" }, - { name = "propcache", marker = "python_full_version < '3.14'" }, - { name = "yarl", marker = "python_full_version < '3.14'" }, + { name = "attrs" }, + { name = "frozenlist" }, + { name = "multidict" }, + { name = "propcache" }, + { name = "yarl" }, ] sdist = { url = "https://files.pythonhosted.org/packages/50/42/32cf8e7704ceb4481406eb87161349abb46a57fee3f008ba9cb610968646/aiohttp-3.13.3.tar.gz", hash = "sha256:a949eee43d3782f2daae4f4a2819b2cb9b0c5d3b7f7a927067cc84dafdbb9f88", size = 7844556, upload-time = "2026-01-03T17:33:05.204Z" } wheels = [ @@ -137,12 +182,21 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/b4/63/278a98c715ae467624eafe375542d8ba9b4383a016df8fdefe0ae28382a7/aiohttp-3.13.3-cp314-cp314t-win_amd64.whl", hash = "sha256:44531a36aa2264a1860089ffd4dce7baf875ee5a6079d5fb42e261c704ef7344", size = 499694, upload-time = "2026-01-03T17:32:24.546Z" }, ] +[[package]] +name = "aioitertools" +version = "0.13.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/fd/3c/53c4a17a05fb9ea2313ee1777ff53f5e001aefd5cc85aa2f4c2d982e1e38/aioitertools-0.13.0.tar.gz", hash = "sha256:620bd241acc0bbb9ec819f1ab215866871b4bbd1f73836a55f799200ee86950c", size = 19322, upload-time = "2025-11-06T22:17:07.609Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/10/a1/510b0a7fadc6f43a6ce50152e69dbd86415240835868bb0bd9b5b88b1e06/aioitertools-0.13.0-py3-none-any.whl", hash = "sha256:0be0292b856f08dfac90e31f4739432f4cb6d7520ab9eb73e143f4f2fa5259be", size = 24182, upload-time = "2025-11-06T22:17:06.502Z" }, +] + [[package]] name = "aiosignal" version = "1.4.0" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "frozenlist", marker = "python_full_version < '3.14'" }, + { name = "frozenlist" }, { name = "typing-extensions", marker = "python_full_version < '3.13'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/61/62/06741b579156360248d1ec624842ad0edf697050bbaf7c3e46394e106ad1/aiosignal-1.4.0.tar.gz", hash = "sha256:f47eecd9468083c2029cc99945502cb7708b082c232f9aca65da147157b251c7", size = 25007, upload-time = "2025-07-03T22:54:43.528Z" } @@ -192,6 +246,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/78/b6/6307fbef88d9b5ee7421e68d78a9f162e0da4900bc5f5793f6d3d0e34fb8/annotated_types-0.7.0-py3-none-any.whl", hash = "sha256:1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53", size = 13643, upload-time = "2024-05-20T21:33:24.1Z" }, ] +[[package]] +name = "antlr4-python3-runtime" +version = "4.13.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/33/5f/2cdf6f7aca3b20d3f316e9f505292e1f256a32089bd702034c29ebde6242/antlr4_python3_runtime-4.13.2.tar.gz", hash = "sha256:909b647e1d2fc2b70180ac586df3933e38919c85f98ccc656a96cd3f25ef3916", size = 117467, upload-time = "2024-08-03T19:00:12.757Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/89/03/a851e84fcbb85214dc637b6378121ef9a0dd61b4c65264675d8a5c9b1ae7/antlr4_python3_runtime-4.13.2-py3-none-any.whl", hash = "sha256:fe3835eb8d33daece0e799090eda89719dbccee7aa39ef94eed3818cafa5a7e8", size = 144462, upload-time = "2024-08-03T19:00:11.134Z" }, +] + [[package]] name = "anyio" version = "4.11.0" @@ -246,6 +309,34 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/02/ff/1175b0b7371e46244032d43a56862d0af455823b5280a50c63d99cc50f18/automat-25.4.16-py3-none-any.whl", hash = "sha256:04e9bce696a8d5671ee698005af6e5a9fa15354140a87f4870744604dcdd3ba1", size = 42842, upload-time = "2025-04-16T20:12:14.447Z" }, ] +[[package]] +name = "aws-sam-translator" +version = "1.103.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "boto3" }, + { name = "jsonschema" }, + { name = "pydantic" }, + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/d0/e3/82cc7240504b1c0d2d7ed7028b05ccceedb02932b8638c61a8372a5d875f/aws_sam_translator-1.103.0.tar.gz", hash = "sha256:8317b72ef412db581dc7846932a44dfc1729adea578d9307a3e6ece46a7882ca", size = 344881, upload-time = "2025-11-21T19:50:51.818Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ce/86/6414c215ff0a10b33bf89622951e7d4413106320657535d2ba0e4f634661/aws_sam_translator-1.103.0-py3-none-any.whl", hash = "sha256:d4eb4a1efa62f00b253ee5f8c0084bd4b7687186c6a12338f900ebe07ff74dad", size = 403100, upload-time = "2025-11-21T19:50:50.528Z" }, +] + +[[package]] +name = "aws-xray-sdk" +version = "2.15.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "botocore" }, + { name = "wrapt" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/14/25/0cbd7a440080def5e6f063720c3b190a25f8aa2938c1e34415dc18241596/aws_xray_sdk-2.15.0.tar.gz", hash = "sha256:794381b96e835314345068ae1dd3b9120bd8b4e21295066c37e8814dbb341365", size = 76315, upload-time = "2025-10-29T20:59:45Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ef/c3/f30a7a63e664acc7c2545ca0491b6ce8264536e0e5cad3965f1d1b91e960/aws_xray_sdk-2.15.0-py2.py3-none-any.whl", hash = "sha256:422d62ad7d52e373eebb90b642eb1bb24657afe03b22a8df4a8b2e5108e278a3", size = 103228, upload-time = "2025-10-29T21:00:24.12Z" }, +] + [[package]] name = "backports-tarfile" version = "1.2.0" @@ -276,6 +367,55 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/f4/be/6985abb1011fda8a523cfe21ed9629e397d6e06fb5bae99750402b25c95b/bashlex-0.18-py2.py3-none-any.whl", hash = "sha256:91d73a23a3e51711919c1c899083890cdecffc91d8c088942725ac13e9dcfffa", size = 69539, upload-time = "2023-01-18T15:21:24.167Z" }, ] +[[package]] +name = "blinker" +version = "1.9.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/21/28/9b3f50ce0e048515135495f198351908d99540d69bfdc8c1d15b73dc55ce/blinker-1.9.0.tar.gz", hash = "sha256:b4ce2265a7abece45e7cc896e98dbebe6cead56bcf805a3d23136d145f5445bf", size = 22460, upload-time = "2024-11-08T17:25:47.436Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/10/cb/f2ad4230dc2eb1a74edf38f1a38b9b52277f75bef262d8908e60d957e13c/blinker-1.9.0-py3-none-any.whl", hash = "sha256:ba0efaa9080b619ff2f3459d1d500c57bddea4a6b424b60a91141db6fd2f08bc", size = 8458, upload-time = "2024-11-08T17:25:46.184Z" }, +] + +[[package]] +name = "boto3" +version = "1.40.61" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "botocore" }, + { name = "jmespath" }, + { name = "s3transfer" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/ed/f9/6ef8feb52c3cce5ec3967a535a6114b57ac7949fd166b0f3090c2b06e4e5/boto3-1.40.61.tar.gz", hash = "sha256:d6c56277251adf6c2bdd25249feae625abe4966831676689ff23b4694dea5b12", size = 111535, upload-time = "2025-10-28T19:26:57.247Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/61/24/3bf865b07d15fea85b63504856e137029b6acbc73762496064219cdb265d/boto3-1.40.61-py3-none-any.whl", hash = "sha256:6b9c57b2a922b5d8c17766e29ed792586a818098efe84def27c8f582b33f898c", size = 139321, upload-time = "2025-10-28T19:26:55.007Z" }, +] + +[[package]] +name = "botocore" +version = "1.40.61" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "jmespath" }, + { name = "python-dateutil" }, + { name = "urllib3" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/28/a3/81d3a47c2dbfd76f185d3b894f2ad01a75096c006a2dd91f237dca182188/botocore-1.40.61.tar.gz", hash = "sha256:a2487ad69b090f9cccd64cf07c7021cd80ee9c0655ad974f87045b02f3ef52cd", size = 14393956, upload-time = "2025-10-28T19:26:46.108Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/38/c5/f6ce561004db45f0b847c2cd9b19c67c6bf348a82018a48cb718be6b58b0/botocore-1.40.61-py3-none-any.whl", hash = "sha256:17ebae412692fd4824f99cde0f08d50126dc97954008e5ba2b522eb049238aa7", size = 14055973, upload-time = "2025-10-28T19:26:42.15Z" }, +] + +[[package]] +name = "botocore-stubs" +version = "1.42.41" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "types-awscrt" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/0c/a8/a26608ff39e3a5866c6c79eda10133490205cbddd45074190becece3ff2a/botocore_stubs-1.42.41.tar.gz", hash = "sha256:dbeac2f744df6b814ce83ec3f3777b299a015cbea57a2efc41c33b8c38265825", size = 42411, upload-time = "2026-02-03T20:46:14.479Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/32/76/cab7af7f16c0b09347f2ebe7ffda7101132f786acb767666dce43055faab/botocore_stubs-1.42.41-py3-none-any.whl", hash = "sha256:9423110fb0e391834bd2ed44ae5f879d8cb370a444703d966d30842ce2bcb5f0", size = 66759, upload-time = "2026-02-03T20:46:13.02Z" }, +] + [[package]] name = "bracex" version = "2.6" @@ -394,6 +534,25 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/ae/3a/dbeec9d1ee0844c679f6bb5d6ad4e9f198b1224f4e7a32825f47f6192b0c/cffi-2.0.0-cp314-cp314t-win_arm64.whl", hash = "sha256:0a1527a803f0a659de1af2e1fd700213caba79377e27e4693648c2923da066f9", size = 184195, upload-time = "2025-09-08T23:23:43.004Z" }, ] +[[package]] +name = "cfn-lint" +version = "1.41.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "aws-sam-translator" }, + { name = "jsonpatch" }, + { name = "networkx", version = "3.4.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.11'" }, + { name = "networkx", version = "3.6.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" }, + { name = "pyyaml" }, + { name = "regex" }, + { name = "sympy" }, + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/ee/b5/436c192cdf8dbddd8e09a591384f126c5a47937c14953d87b1dacacd0543/cfn_lint-1.41.0.tar.gz", hash = "sha256:6feca1cf57f9ed2833bab68d9b1d38c8033611e571fa792e45ab4a39e2b8ab57", size = 3408534, upload-time = "2025-11-18T20:03:33.431Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/cf/5e/81ef8f87894543210d783a495c8880cfb0b5baa0ee3bcc6d852f1b343863/cfn_lint-1.41.0-py3-none-any.whl", hash = "sha256:cd43f76f59a664b2bad580840827849fac0d56a3b80e9a41315d8ab5ff6b563a", size = 5674429, upload-time = "2025-11-18T20:03:31.083Z" }, +] + [[package]] name = "charset-normalizer" version = "3.4.4" @@ -742,6 +901,20 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/12/b3/231ffd4ab1fc9d679809f356cebee130ac7daa00d6d6f3206dd4fd137e9e/distro-1.9.0-py3-none-any.whl", hash = "sha256:7bffd925d65168f85027d8da9af6bddab658135b840670a223589bc0c8ef02b2", size = 20277, upload-time = "2023-12-24T09:54:30.421Z" }, ] +[[package]] +name = "docker" +version = "7.1.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "pywin32", marker = "sys_platform == 'win32'" }, + { name = "requests" }, + { name = "urllib3" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/91/9b/4a2ea29aeba62471211598dac5d96825bb49348fa07e906ea930394a83ce/docker-7.1.0.tar.gz", hash = "sha256:ad8c70e6e3f8926cb8a92619b832b4ea5299e2831c14284663184e200546fa6c", size = 117834, upload-time = "2024-05-23T11:13:57.216Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e3/26/57c6fb270950d476074c087527a558ccb6f4436657314bfb6cdf484114c4/docker-7.1.0-py3-none-any.whl", hash = "sha256:c96b93b7f0a746f9e77d325bcfb87422a3d8bd4f03136ae8a85b37f1898d5fc0", size = 147774, upload-time = "2024-05-23T11:13:55.01Z" }, +] + [[package]] name = "docstring-parser" version = "0.17.0" @@ -849,6 +1022,36 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/b5/36/7fb70f04bf00bc646cd5bb45aa9eddb15e19437a28b8fb2b4a5249fac770/filelock-3.20.3-py3-none-any.whl", hash = "sha256:4b0dda527ee31078689fc205ec4f1c1bf7d56cf88b6dc9426c4f230e46c2dce1", size = 16701, upload-time = "2026-01-09T17:55:04.334Z" }, ] +[[package]] +name = "flask" +version = "3.1.3" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "blinker" }, + { name = "click" }, + { name = "itsdangerous" }, + { name = "jinja2" }, + { name = "markupsafe" }, + { name = "werkzeug" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/26/00/35d85dcce6c57fdc871f3867d465d780f302a175ea360f62533f12b27e2b/flask-3.1.3.tar.gz", hash = "sha256:0ef0e52b8a9cd932855379197dd8f94047b359ca0a78695144304cb45f87c9eb", size = 759004, upload-time = "2026-02-19T05:00:57.678Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/7f/9c/34f6962f9b9e9c71f6e5ed806e0d0ff03c9d1b0b2340088a0cf4bce09b18/flask-3.1.3-py3-none-any.whl", hash = "sha256:f4bcbefc124291925f1a26446da31a5178f9483862233b23c0c96a20701f670c", size = 103424, upload-time = "2026-02-19T05:00:56.027Z" }, +] + +[[package]] +name = "flask-cors" +version = "6.0.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "flask" }, + { name = "werkzeug" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/70/74/0fc0fa68d62f21daef41017dafab19ef4b36551521260987eb3a5394c7ba/flask_cors-6.0.2.tar.gz", hash = "sha256:6e118f3698249ae33e429760db98ce032a8bf9913638d085ca0f4c5534ad2423", size = 13472, upload-time = "2025-12-12T20:31:42.861Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/4f/af/72ad54402e599152de6d067324c46fe6a4f531c7c65baf7e96c63db55eaf/flask_cors-6.0.2-py3-none-any.whl", hash = "sha256:e57544d415dfd7da89a9564e1e3a9e515042df76e12130641ca6f3f2f03b699a", size = 13257, upload-time = "2025-12-12T20:31:41.3Z" }, +] + [[package]] name = "frozenlist" version = "1.8.0" @@ -1538,6 +1741,15 @@ grpc = [ { name = "grpcio" }, ] +[[package]] +name = "graphql-core" +version = "3.2.8" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/68/c5/36aa96205c3ecbb3d34c7c24189e4553c7ca2ebc7e1dd07432339b980272/graphql_core-3.2.8.tar.gz", hash = "sha256:015457da5d996c924ddf57a43f4e959b0b94fb695b85ed4c29446e508ed65cf3", size = 513181, upload-time = "2026-03-05T19:55:37.332Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/86/41/cb887d9afc5dabd78feefe6ccbaf83ff423c206a7a1b7aeeac05120b2125/graphql_core-3.2.8-py3-none-any.whl", hash = "sha256:cbee07bee1b3ed5e531723685369039f32ff815ef60166686e0162f540f1520c", size = 207349, upload-time = "2026-03-05T19:55:35.911Z" }, +] + [[package]] name = "graphviz" version = "0.21" @@ -1930,6 +2142,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/2c/e1/e6716421ea10d38022b952c159d5161ca1193197fb744506875fbb87ea7b/iniconfig-2.1.0-py3-none-any.whl", hash = "sha256:9deba5723312380e77435581c6bf4935c94cbfab9b1ed33ef8d238ea168eb760", size = 6050, upload-time = "2025-03-19T20:10:01.071Z" }, ] +[[package]] +name = "itsdangerous" +version = "2.2.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/9c/cb/8ac0172223afbccb63986cc25049b154ecfb5e85932587206f42317be31d/itsdangerous-2.2.0.tar.gz", hash = "sha256:e0050c0b7da1eea53ffaf149c0cfbb5c6e2e2b69c4bef22c81fa6eb73e5f6173", size = 54410, upload-time = "2024-04-16T21:28:15.614Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/04/96/92447566d16df59b2a776c0fb82dbc4d9e07cd95062562af01e408583fc4/itsdangerous-2.2.0-py3-none-any.whl", hash = "sha256:c6242fc49e35958c8b15141343aa660db5fc54d4f13a1db01a3f5891b98700ef", size = 16234, upload-time = "2024-04-16T21:28:14.499Z" }, +] + [[package]] name = "jaraco-classes" version = "3.4.0" @@ -1980,7 +2201,7 @@ name = "jinja2" version = "3.1.6" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "markupsafe", marker = "python_full_version < '3.14'" }, + { name = "markupsafe" }, ] sdist = { url = "https://files.pythonhosted.org/packages/df/bf/f7da0350254c0ed7c72f3e33cef02e048281fec7ecec5f032d4aac52226b/jinja2-3.1.6.tar.gz", hash = "sha256:0137fb05990d35f1275a587e9aee6d56da821fc83491a0fb838183be43f66d6d", size = 245115, upload-time = "2025-03-05T20:05:02.478Z" } wheels = [ @@ -2060,9 +2281,60 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/70/f3/ce100253c80063a7b8b406e1d1562657fd4b9b4e1b562db40e68645342fb/jiter-0.11.0-graalpy311-graalpy242_311_native-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:902b43386c04739229076bd1c4c69de5d115553d982ab442a8ae82947c72ede7", size = 336380, upload-time = "2025-09-15T09:20:36.867Z" }, ] +[[package]] +name = "jmespath" +version = "1.1.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/d3/59/322338183ecda247fb5d1763a6cbe46eff7222eaeebafd9fa65d4bf5cb11/jmespath-1.1.0.tar.gz", hash = "sha256:472c87d80f36026ae83c6ddd0f1d05d4e510134ed462851fd5f754c8c3cbb88d", size = 27377, upload-time = "2026-01-22T16:35:26.279Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/14/2f/967ba146e6d58cf6a652da73885f52fc68001525b4197effc174321d70b4/jmespath-1.1.0-py3-none-any.whl", hash = "sha256:a5663118de4908c91729bea0acadca56526eb2698e83de10cd116ae0f4e97c64", size = 20419, upload-time = "2026-01-22T16:35:24.919Z" }, +] + +[[package]] +name = "joserfc" +version = "1.6.3" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "cryptography" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/ce/90/b8cc8635c4ce2e5e8104bf26ef147f6e599478f6329107283cdc53aae97f/joserfc-1.6.3.tar.gz", hash = "sha256:c00c2830db969b836cba197e830e738dd9dda0955f1794e55d3c636f17f5c9a6", size = 229090, upload-time = "2026-02-25T15:33:38.167Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/12/4f/124b3301067b752f44f292f0b9a74e837dd75ff863ee39500a082fc4c733/joserfc-1.6.3-py3-none-any.whl", hash = "sha256:6beab3635358cbc565cb94fb4c53d0557e6d10a15b933e2134939351590bda9a", size = 70465, upload-time = "2026-02-25T15:33:36.997Z" }, +] + +[[package]] +name = "jsonpatch" +version = "1.33" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "jsonpointer" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/42/78/18813351fe5d63acad16aec57f94ec2b70a09e53ca98145589e185423873/jsonpatch-1.33.tar.gz", hash = "sha256:9fcd4009c41e6d12348b4a0ff2563ba56a2923a7dfee731d004e212e1ee5030c", size = 21699, upload-time = "2023-06-26T12:07:29.144Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/73/07/02e16ed01e04a374e644b575638ec7987ae846d25ad97bcc9945a3ee4b0e/jsonpatch-1.33-py2.py3-none-any.whl", hash = "sha256:0ae28c0cd062bbd8b8ecc26d7d164fbbea9652a1a3693f3b956c1eae5145dade", size = 12898, upload-time = "2023-06-16T21:01:28.466Z" }, +] + +[[package]] +name = "jsonpath-ng" +version = "1.8.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/32/58/250751940d75c8019659e15482d548a4aa3b6ce122c515102a4bfdac50e3/jsonpath_ng-1.8.0.tar.gz", hash = "sha256:54252968134b5e549ea5b872f1df1168bd7defe1a52fed5a358c194e1943ddc3", size = 74513, upload-time = "2026-02-24T14:42:06.182Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/03/99/33c7d78a3fb70d545fd5411ac67a651c81602cc09c9cf0df383733f068c5/jsonpath_ng-1.8.0-py3-none-any.whl", hash = "sha256:b8dde192f8af58d646fc031fac9c99fe4d00326afc4148f1f043c601a8cfe138", size = 67844, upload-time = "2026-02-28T00:53:19.637Z" }, +] + +[[package]] +name = "jsonpointer" +version = "3.0.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/6a/0a/eebeb1fa92507ea94016a2a790b93c2ae41a7e18778f85471dc54475ed25/jsonpointer-3.0.0.tar.gz", hash = "sha256:2b2d729f2091522d61c3b31f82e11870f60b68f43fbc705cb76bf4b832af59ef", size = 9114, upload-time = "2024-06-10T19:24:42.462Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/71/92/5e77f98553e9e75130c78900d000368476aed74276eb8ae8796f65f00918/jsonpointer-3.0.0-py2.py3-none-any.whl", hash = "sha256:13e088adc14fca8b6aa8177c044e12701e6ad4b28ff10e65f2267a90109c9942", size = 7595, upload-time = "2024-06-10T19:24:40.698Z" }, +] + [[package]] name = "jsonschema" -version = "4.25.1" +version = "4.24.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "attrs" }, @@ -2070,9 +2342,23 @@ dependencies = [ { name = "referencing" }, { name = "rpds-py" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/74/69/f7185de793a29082a9f3c7728268ffb31cb5095131a9c139a74078e27336/jsonschema-4.25.1.tar.gz", hash = "sha256:e4a9655ce0da0c0b67a085847e00a3a51449e1157f4f75e9fb5aa545e122eb85", size = 357342, upload-time = "2025-08-18T17:03:50.038Z" } +sdist = { url = "https://files.pythonhosted.org/packages/f1/6e/35174c1d3f30560848c82d3c233c01420e047d70925c897a4d6e932b4898/jsonschema-4.24.1.tar.gz", hash = "sha256:fe45a130cc7f67cd0d67640b4e7e3e2e666919462ae355eda238296eafeb4b5d", size = 356635, upload-time = "2025-07-17T14:40:01.05Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/85/7f/ea48ffb58f9791f9d97ccb35e42fea1ebc81c67ce36dc4b8b2eee60e8661/jsonschema-4.24.1-py3-none-any.whl", hash = "sha256:6b916866aa0b61437785f1277aa2cbd63512e8d4b47151072ef13292049b4627", size = 89060, upload-time = "2025-07-17T14:39:59.471Z" }, +] + +[[package]] +name = "jsonschema-path" +version = "0.4.5" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "pathable" }, + { name = "pyyaml" }, + { name = "referencing" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/5b/8a/7e6102f2b8bdc6705a9eb5294f8f6f9ccd3a8420e8e8e19671d1dd773251/jsonschema_path-0.4.5.tar.gz", hash = "sha256:c6cd7d577ae290c7defd4f4029e86fdb248ca1bd41a07557795b3c95e5144918", size = 15113, upload-time = "2026-03-03T09:56:46.87Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/bf/9c/8c95d856233c1f82500c2450b8c68576b4cf1c871db3afac5c34ff84e6fd/jsonschema-4.25.1-py3-none-any.whl", hash = "sha256:3fba0169e345c7175110351d456342c364814cfcf3b964ba4587f22915230a63", size = 90040, upload-time = "2025-08-18T17:03:48.373Z" }, + { url = "https://files.pythonhosted.org/packages/04/d5/4e96c44f6c1ea3d812cf5391d81a4f5abaa540abf8d04ecd7f66e0ed11df/jsonschema_path-0.4.5-py3-none-any.whl", hash = "sha256:7d77a2c3f3ec569a40efe5c5f942c44c1af2a6f96fe0866794c9ef5b8f87fd65", size = 19368, upload-time = "2026-03-03T09:56:45.39Z" }, ] [[package]] @@ -2105,6 +2391,51 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/d3/32/da7f44bcb1105d3e88a0b74ebdca50c59121d2ddf71c9e34ba47df7f3a56/keyring-25.6.0-py3-none-any.whl", hash = "sha256:552a3f7af126ece7ed5c89753650eec89c7eaae8617d0aa4d9ad2b75111266bd", size = 39085, upload-time = "2024-12-25T15:26:44.377Z" }, ] +[[package]] +name = "lazy-object-proxy" +version = "1.12.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/08/a2/69df9c6ba6d316cfd81fe2381e464db3e6de5db45f8c43c6a23504abf8cb/lazy_object_proxy-1.12.0.tar.gz", hash = "sha256:1f5a462d92fd0cfb82f1fab28b51bfb209fabbe6aabf7f0d51472c0c124c0c61", size = 43681, upload-time = "2025-08-22T13:50:06.783Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d6/2b/d5e8915038acbd6c6a9fcb8aaf923dc184222405d3710285a1fec6e262bc/lazy_object_proxy-1.12.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:61d5e3310a4aa5792c2b599a7a78ccf8687292c8eb09cf187cca8f09cf6a7519", size = 26658, upload-time = "2025-08-22T13:42:23.373Z" }, + { url = "https://files.pythonhosted.org/packages/da/8f/91fc00eeea46ee88b9df67f7c5388e60993341d2a406243d620b2fdfde57/lazy_object_proxy-1.12.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c1ca33565f698ac1aece152a10f432415d1a2aa9a42dfe23e5ba2bc255ab91f6", size = 68412, upload-time = "2025-08-22T13:42:24.727Z" }, + { url = "https://files.pythonhosted.org/packages/07/d2/b7189a0e095caedfea4d42e6b6949d2685c354263bdf18e19b21ca9b3cd6/lazy_object_proxy-1.12.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d01c7819a410f7c255b20799b65d36b414379a30c6f1684c7bd7eb6777338c1b", size = 67559, upload-time = "2025-08-22T13:42:25.875Z" }, + { url = "https://files.pythonhosted.org/packages/a3/ad/b013840cc43971582ff1ceaf784d35d3a579650eb6cc348e5e6ed7e34d28/lazy_object_proxy-1.12.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:029d2b355076710505c9545aef5ab3f750d89779310e26ddf2b7b23f6ea03cd8", size = 66651, upload-time = "2025-08-22T13:42:27.427Z" }, + { url = "https://files.pythonhosted.org/packages/7e/6f/b7368d301c15612fcc4cd00412b5d6ba55548bde09bdae71930e1a81f2ab/lazy_object_proxy-1.12.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:cc6e3614eca88b1c8a625fc0a47d0d745e7c3255b21dac0e30b3037c5e3deeb8", size = 66901, upload-time = "2025-08-22T13:42:28.585Z" }, + { url = "https://files.pythonhosted.org/packages/61/1b/c6b1865445576b2fc5fa0fbcfce1c05fee77d8979fd1aa653dd0f179aefc/lazy_object_proxy-1.12.0-cp310-cp310-win_amd64.whl", hash = "sha256:be5fe974e39ceb0d6c9db0663c0464669cf866b2851c73971409b9566e880eab", size = 26536, upload-time = "2025-08-22T13:42:29.636Z" }, + { url = "https://files.pythonhosted.org/packages/01/b3/4684b1e128a87821e485f5a901b179790e6b5bc02f89b7ee19c23be36ef3/lazy_object_proxy-1.12.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:1cf69cd1a6c7fe2dbcc3edaa017cf010f4192e53796538cc7d5e1fedbfa4bcff", size = 26656, upload-time = "2025-08-22T13:42:30.605Z" }, + { url = "https://files.pythonhosted.org/packages/3a/03/1bdc21d9a6df9ff72d70b2ff17d8609321bea4b0d3cffd2cea92fb2ef738/lazy_object_proxy-1.12.0-cp311-cp311-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:efff4375a8c52f55a145dc8487a2108c2140f0bec4151ab4e1843e52eb9987ad", size = 68832, upload-time = "2025-08-22T13:42:31.675Z" }, + { url = "https://files.pythonhosted.org/packages/3d/4b/5788e5e8bd01d19af71e50077ab020bc5cce67e935066cd65e1215a09ff9/lazy_object_proxy-1.12.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1192e8c2f1031a6ff453ee40213afa01ba765b3dc861302cd91dbdb2e2660b00", size = 69148, upload-time = "2025-08-22T13:42:32.876Z" }, + { url = "https://files.pythonhosted.org/packages/79/0e/090bf070f7a0de44c61659cb7f74c2fe02309a77ca8c4b43adfe0b695f66/lazy_object_proxy-1.12.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:3605b632e82a1cbc32a1e5034278a64db555b3496e0795723ee697006b980508", size = 67800, upload-time = "2025-08-22T13:42:34.054Z" }, + { url = "https://files.pythonhosted.org/packages/cf/d2/b320325adbb2d119156f7c506a5fbfa37fcab15c26d13cf789a90a6de04e/lazy_object_proxy-1.12.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:a61095f5d9d1a743e1e20ec6d6db6c2ca511961777257ebd9b288951b23b44fa", size = 68085, upload-time = "2025-08-22T13:42:35.197Z" }, + { url = "https://files.pythonhosted.org/packages/6a/48/4b718c937004bf71cd82af3713874656bcb8d0cc78600bf33bb9619adc6c/lazy_object_proxy-1.12.0-cp311-cp311-win_amd64.whl", hash = "sha256:997b1d6e10ecc6fb6fe0f2c959791ae59599f41da61d652f6c903d1ee58b7370", size = 26535, upload-time = "2025-08-22T13:42:36.521Z" }, + { url = "https://files.pythonhosted.org/packages/0d/1b/b5f5bd6bda26f1e15cd3232b223892e4498e34ec70a7f4f11c401ac969f1/lazy_object_proxy-1.12.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8ee0d6027b760a11cc18281e702c0309dd92da458a74b4c15025d7fc490deede", size = 26746, upload-time = "2025-08-22T13:42:37.572Z" }, + { url = "https://files.pythonhosted.org/packages/55/64/314889b618075c2bfc19293ffa9153ce880ac6153aacfd0a52fcabf21a66/lazy_object_proxy-1.12.0-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:4ab2c584e3cc8be0dfca422e05ad30a9abe3555ce63e9ab7a559f62f8dbc6ff9", size = 71457, upload-time = "2025-08-22T13:42:38.743Z" }, + { url = "https://files.pythonhosted.org/packages/11/53/857fc2827fc1e13fbdfc0ba2629a7d2579645a06192d5461809540b78913/lazy_object_proxy-1.12.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:14e348185adbd03ec17d051e169ec45686dcd840a3779c9d4c10aabe2ca6e1c0", size = 71036, upload-time = "2025-08-22T13:42:40.184Z" }, + { url = "https://files.pythonhosted.org/packages/2b/24/e581ffed864cd33c1b445b5763d617448ebb880f48675fc9de0471a95cbc/lazy_object_proxy-1.12.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:c4fcbe74fb85df8ba7825fa05eddca764138da752904b378f0ae5ab33a36c308", size = 69329, upload-time = "2025-08-22T13:42:41.311Z" }, + { url = "https://files.pythonhosted.org/packages/78/be/15f8f5a0b0b2e668e756a152257d26370132c97f2f1943329b08f057eff0/lazy_object_proxy-1.12.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:563d2ec8e4d4b68ee7848c5ab4d6057a6d703cb7963b342968bb8758dda33a23", size = 70690, upload-time = "2025-08-22T13:42:42.51Z" }, + { url = "https://files.pythonhosted.org/packages/5d/aa/f02be9bbfb270e13ee608c2b28b8771f20a5f64356c6d9317b20043c6129/lazy_object_proxy-1.12.0-cp312-cp312-win_amd64.whl", hash = "sha256:53c7fd99eb156bbb82cbc5d5188891d8fdd805ba6c1e3b92b90092da2a837073", size = 26563, upload-time = "2025-08-22T13:42:43.685Z" }, + { url = "https://files.pythonhosted.org/packages/f4/26/b74c791008841f8ad896c7f293415136c66cc27e7c7577de4ee68040c110/lazy_object_proxy-1.12.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:86fd61cb2ba249b9f436d789d1356deae69ad3231dc3c0f17293ac535162672e", size = 26745, upload-time = "2025-08-22T13:42:44.982Z" }, + { url = "https://files.pythonhosted.org/packages/9b/52/641870d309e5d1fb1ea7d462a818ca727e43bfa431d8c34b173eb090348c/lazy_object_proxy-1.12.0-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:81d1852fb30fab81696f93db1b1e55a5d1ff7940838191062f5f56987d5fcc3e", size = 71537, upload-time = "2025-08-22T13:42:46.141Z" }, + { url = "https://files.pythonhosted.org/packages/47/b6/919118e99d51c5e76e8bf5a27df406884921c0acf2c7b8a3b38d847ab3e9/lazy_object_proxy-1.12.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:be9045646d83f6c2664c1330904b245ae2371b5c57a3195e4028aedc9f999655", size = 71141, upload-time = "2025-08-22T13:42:47.375Z" }, + { url = "https://files.pythonhosted.org/packages/e5/47/1d20e626567b41de085cf4d4fb3661a56c159feaa73c825917b3b4d4f806/lazy_object_proxy-1.12.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:67f07ab742f1adfb3966c40f630baaa7902be4222a17941f3d85fd1dae5565ff", size = 69449, upload-time = "2025-08-22T13:42:48.49Z" }, + { url = "https://files.pythonhosted.org/packages/58/8d/25c20ff1a1a8426d9af2d0b6f29f6388005fc8cd10d6ee71f48bff86fdd0/lazy_object_proxy-1.12.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:75ba769017b944fcacbf6a80c18b2761a1795b03f8899acdad1f1c39db4409be", size = 70744, upload-time = "2025-08-22T13:42:49.608Z" }, + { url = "https://files.pythonhosted.org/packages/c0/67/8ec9abe15c4f8a4bcc6e65160a2c667240d025cbb6591b879bea55625263/lazy_object_proxy-1.12.0-cp313-cp313-win_amd64.whl", hash = "sha256:7b22c2bbfb155706b928ac4d74c1a63ac8552a55ba7fff4445155523ea4067e1", size = 26568, upload-time = "2025-08-22T13:42:57.719Z" }, + { url = "https://files.pythonhosted.org/packages/23/12/cd2235463f3469fd6c62d41d92b7f120e8134f76e52421413a0ad16d493e/lazy_object_proxy-1.12.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:4a79b909aa16bde8ae606f06e6bbc9d3219d2e57fb3e0076e17879072b742c65", size = 27391, upload-time = "2025-08-22T13:42:50.62Z" }, + { url = "https://files.pythonhosted.org/packages/60/9e/f1c53e39bbebad2e8609c67d0830cc275f694d0ea23d78e8f6db526c12d3/lazy_object_proxy-1.12.0-cp313-cp313t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:338ab2f132276203e404951205fe80c3fd59429b3a724e7b662b2eb539bb1be9", size = 80552, upload-time = "2025-08-22T13:42:51.731Z" }, + { url = "https://files.pythonhosted.org/packages/4c/b6/6c513693448dcb317d9d8c91d91f47addc09553613379e504435b4cc8b3e/lazy_object_proxy-1.12.0-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8c40b3c9faee2e32bfce0df4ae63f4e73529766893258eca78548bac801c8f66", size = 82857, upload-time = "2025-08-22T13:42:53.225Z" }, + { url = "https://files.pythonhosted.org/packages/12/1c/d9c4aaa4c75da11eb7c22c43d7c90a53b4fca0e27784a5ab207768debea7/lazy_object_proxy-1.12.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:717484c309df78cedf48396e420fa57fc8a2b1f06ea889df7248fdd156e58847", size = 80833, upload-time = "2025-08-22T13:42:54.391Z" }, + { url = "https://files.pythonhosted.org/packages/0b/ae/29117275aac7d7d78ae4f5a4787f36ff33262499d486ac0bf3e0b97889f6/lazy_object_proxy-1.12.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:a6b7ea5ea1ffe15059eb44bcbcb258f97bcb40e139b88152c40d07b1a1dfc9ac", size = 79516, upload-time = "2025-08-22T13:42:55.812Z" }, + { url = "https://files.pythonhosted.org/packages/19/40/b4e48b2c38c69392ae702ae7afa7b6551e0ca5d38263198b7c79de8b3bdf/lazy_object_proxy-1.12.0-cp313-cp313t-win_amd64.whl", hash = "sha256:08c465fb5cd23527512f9bd7b4c7ba6cec33e28aad36fbbe46bf7b858f9f3f7f", size = 27656, upload-time = "2025-08-22T13:42:56.793Z" }, + { url = "https://files.pythonhosted.org/packages/ef/3a/277857b51ae419a1574557c0b12e0d06bf327b758ba94cafc664cb1e2f66/lazy_object_proxy-1.12.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:c9defba70ab943f1df98a656247966d7729da2fe9c2d5d85346464bf320820a3", size = 26582, upload-time = "2025-08-22T13:49:49.366Z" }, + { url = "https://files.pythonhosted.org/packages/1a/b6/c5e0fa43535bb9c87880e0ba037cdb1c50e01850b0831e80eb4f4762f270/lazy_object_proxy-1.12.0-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:6763941dbf97eea6b90f5b06eb4da9418cc088fce0e3883f5816090f9afcde4a", size = 71059, upload-time = "2025-08-22T13:49:50.488Z" }, + { url = "https://files.pythonhosted.org/packages/06/8a/7dcad19c685963c652624702f1a968ff10220b16bfcc442257038216bf55/lazy_object_proxy-1.12.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:fdc70d81235fc586b9e3d1aeef7d1553259b62ecaae9db2167a5d2550dcc391a", size = 71034, upload-time = "2025-08-22T13:49:54.224Z" }, + { url = "https://files.pythonhosted.org/packages/12/ac/34cbfb433a10e28c7fd830f91c5a348462ba748413cbb950c7f259e67aa7/lazy_object_proxy-1.12.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:0a83c6f7a6b2bfc11ef3ed67f8cbe99f8ff500b05655d8e7df9aab993a6abc95", size = 69529, upload-time = "2025-08-22T13:49:55.29Z" }, + { url = "https://files.pythonhosted.org/packages/6f/6a/11ad7e349307c3ca4c0175db7a77d60ce42a41c60bcb11800aabd6a8acb8/lazy_object_proxy-1.12.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:256262384ebd2a77b023ad02fbcc9326282bcfd16484d5531154b02bc304f4c5", size = 70391, upload-time = "2025-08-22T13:49:56.35Z" }, + { url = "https://files.pythonhosted.org/packages/59/97/9b410ed8fbc6e79c1ee8b13f8777a80137d4bc189caf2c6202358e66192c/lazy_object_proxy-1.12.0-cp314-cp314-win_amd64.whl", hash = "sha256:7601ec171c7e8584f8ff3f4e440aa2eebf93e854f04639263875b8c2971f819f", size = 26988, upload-time = "2025-08-22T13:49:57.302Z" }, + { url = "https://files.pythonhosted.org/packages/41/a0/b91504515c1f9a299fc157967ffbd2f0321bce0516a3d5b89f6f4cad0355/lazy_object_proxy-1.12.0-pp39.pp310.pp311.graalpy311-none-any.whl", hash = "sha256:c3b2e0af1f7f77c4263759c4824316ce458fabe0fceadcd24ef8ca08b2d1e402", size = 15072, upload-time = "2025-08-22T13:50:05.498Z" }, +] + [[package]] name = "litellm" version = "1.78.0" @@ -2427,6 +2758,59 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/a4/8e/469e5a4a2f5855992e425f3cb33804cc07bf18d48f2db061aec61ce50270/more_itertools-10.8.0-py3-none-any.whl", hash = "sha256:52d4362373dcf7c52546bc4af9a86ee7c4579df9a8dc268be0a2f949d376cc9b", size = 69667, upload-time = "2025-09-02T15:23:09.635Z" }, ] +[[package]] +name = "moto" +version = "5.1.22" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "boto3" }, + { name = "botocore" }, + { name = "cryptography" }, + { name = "jinja2" }, + { name = "python-dateutil" }, + { name = "requests" }, + { name = "responses" }, + { name = "werkzeug" }, + { name = "xmltodict" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/b2/3d/1765accbf753dc1ae52f26a2e2ed2881d78c2eb9322c178e45312472e4a0/moto-5.1.22.tar.gz", hash = "sha256:e5b2c378296e4da50ce5a3c355a1743c8d6d396ea41122f5bb2a40f9b9a8cc0e", size = 8547792, upload-time = "2026-03-08T21:06:43.731Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/46/4f/8812a01e3e0bd6be3e13b90432fb5c696af9a720af3f00e6eba5ad748345/moto-5.1.22-py3-none-any.whl", hash = "sha256:d9f20ae3cf29c44f93c1f8f06c8f48d5560e5dc027816ef1d0d2059741ffcfbe", size = 6617400, upload-time = "2026-03-08T21:06:41.093Z" }, +] + +[package.optional-dependencies] +s3 = [ + { name = "py-partiql-parser" }, + { name = "pyyaml" }, +] +server = [ + { name = "antlr4-python3-runtime" }, + { name = "aws-sam-translator" }, + { name = "aws-xray-sdk" }, + { name = "cfn-lint" }, + { name = "docker" }, + { name = "flask" }, + { name = "flask-cors" }, + { name = "graphql-core" }, + { name = "joserfc" }, + { name = "jsonpath-ng" }, + { name = "openapi-spec-validator" }, + { name = "py-partiql-parser" }, + { name = "pydantic" }, + { name = "pyparsing" }, + { name = "pyyaml" }, + { name = "setuptools" }, +] + +[[package]] +name = "mpmath" +version = "1.3.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/e0/47/dd32fa426cc72114383ac549964eecb20ecfd886d1e5ccf5340b55b02f57/mpmath-1.3.0.tar.gz", hash = "sha256:7a28eb2a9774d00c7bc92411c19a89209d5da7c4c9a9e227be8330a23a25b91f", size = 508106, upload-time = "2023-03-07T16:47:11.061Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/43/e3/7d92a15f894aa0c9c4b49b8ee9ac9850d6e63b03c9c32c0367a13ae62209/mpmath-1.3.0-py3-none-any.whl", hash = "sha256:a0b2b9fe80bbcd81a6647ff13108738cfb482d481d826cc0e02f5b35e5c88d2c", size = 536198, upload-time = "2023-03-07T16:47:09.197Z" }, +] + [[package]] name = "msgpack" version = "1.1.2" @@ -2693,6 +3077,32 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/e8/73/d6b999782ae22f16971cc05378b3b33f6a89ede3b9619e8366aa23484bca/mypy_protobuf-3.6.0-py3-none-any.whl", hash = "sha256:56176e4d569070e7350ea620262478b49b7efceba4103d468448f1d21492fd6c", size = 16434, upload-time = "2024-04-01T20:24:40.583Z" }, ] +[[package]] +name = "networkx" +version = "3.4.2" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version < '3.11'", +] +sdist = { url = "https://files.pythonhosted.org/packages/fd/1d/06475e1cd5264c0b870ea2cc6fdb3e37177c1e565c43f56ff17a10e3937f/networkx-3.4.2.tar.gz", hash = "sha256:307c3669428c5362aab27c8a1260aa8f47c4e91d3891f48be0141738d8d053e1", size = 2151368, upload-time = "2024-10-21T12:39:38.695Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b9/54/dd730b32ea14ea797530a4479b2ed46a6fb250f682a9cfb997e968bf0261/networkx-3.4.2-py3-none-any.whl", hash = "sha256:df5d4365b724cf81b8c6a7312509d0c22386097011ad1abe274afd5e9d3bbc5f", size = 1723263, upload-time = "2024-10-21T12:39:36.247Z" }, +] + +[[package]] +name = "networkx" +version = "3.6.1" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version >= '3.14'", + "python_full_version == '3.13.*'", + "python_full_version >= '3.11' and python_full_version < '3.13'", +] +sdist = { url = "https://files.pythonhosted.org/packages/6a/51/63fe664f3908c97be9d2e4f1158eb633317598cfa6e1fc14af5383f17512/networkx-3.6.1.tar.gz", hash = "sha256:26b7c357accc0c8cde558ad486283728b65b6a95d85ee1cd66bafab4c8168509", size = 2517025, upload-time = "2025-12-08T17:02:39.908Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/9e/c9/b2622292ea83fbb4ec318f5b9ab867d0a28ab43c5717bb85b0a5f6b3b0a4/networkx-3.6.1-py3-none-any.whl", hash = "sha256:d47fbf302e7d9cbbb9e2555a0d267983d2aa476bac30e90dfbe5669bd57f3762", size = 2068504, upload-time = "2025-12-08T17:02:38.159Z" }, +] + [[package]] name = "nexus-rpc" version = "1.4.0" @@ -2805,6 +3215,40 @@ litellm = [ { name = "litellm", marker = "python_full_version < '3.14'" }, ] +[[package]] +name = "openapi-schema-validator" +version = "0.8.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "jsonschema" }, + { name = "jsonschema-specifications" }, + { name = "pydantic" }, + { name = "pydantic-settings" }, + { name = "referencing" }, + { name = "rfc3339-validator" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/21/4b/67b24b2b23d96ea862be2cca3632a546f67a22461200831213e80c3c6011/openapi_schema_validator-0.8.1.tar.gz", hash = "sha256:4c57266ce8cbfa37bb4eb4d62cdb7d19356c3a468e3535743c4562863e1790da", size = 23134, upload-time = "2026-03-02T08:46:29.807Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/6f/87/e9f29f463b230d4b47d65e17858c595153a8ca8c1775f16e406aa82d455d/openapi_schema_validator-0.8.1-py3-none-any.whl", hash = "sha256:0f5859794c5bfa433d478dc5ac5e5768d50adc56b14380c8a6fd3a8113e89c9b", size = 19211, upload-time = "2026-03-02T08:46:28.154Z" }, +] + +[[package]] +name = "openapi-spec-validator" +version = "0.8.4" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "jsonschema" }, + { name = "jsonschema-path" }, + { name = "lazy-object-proxy" }, + { name = "openapi-schema-validator" }, + { name = "pydantic" }, + { name = "pydantic-settings" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/10/de/0199b15f5dde3ca61df6e6b3987420bfd424db077998f0162e8ffe12e4f5/openapi_spec_validator-0.8.4.tar.gz", hash = "sha256:8bb324b9b08b9b368b1359dec14610c60a8f3a3dd63237184eb04456d4546f49", size = 1756847, upload-time = "2026-03-01T15:48:19.499Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/cb/70/52310f9ece5f4eb02e0b31d538b51f729169517767a8d0100a25db31d67f/openapi_spec_validator-0.8.4-py3-none-any.whl", hash = "sha256:cf905117063d7c4d495c8a5a167a1f2a8006da6ffa8ba234a7ed0d0f11454d51", size = 50330, upload-time = "2026-03-01T15:48:17.668Z" }, +] + [[package]] name = "openinference-instrumentation" version = "0.1.42" @@ -3031,6 +3475,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/20/12/38679034af332785aac8774540895e234f4d07f7545804097de4b666afd8/packaging-25.0-py3-none-any.whl", hash = "sha256:29572ef2b1f17581046b3a2227d5c611fb25ec70ca1ba8554b24b0e69331a484", size = 66469, upload-time = "2025-04-19T11:48:57.875Z" }, ] +[[package]] +name = "pathable" +version = "0.5.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/72/55/b748445cb4ea6b125626f15379be7c96d1035d4fa3e8fee362fa92298abf/pathable-0.5.0.tar.gz", hash = "sha256:d81938348a1cacb525e7c75166270644782c0fb9c8cecc16be033e71427e0ef1", size = 16655, upload-time = "2026-02-20T08:47:00.748Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/52/96/5a770e5c461462575474468e5af931cff9de036e7c2b4fea23c1c58d2cbe/pathable-0.5.0-py3-none-any.whl", hash = "sha256:646e3d09491a6351a0c82632a09c02cdf70a252e73196b36d8a15ba0a114f0a6", size = 16867, upload-time = "2026-02-20T08:46:59.536Z" }, +] + [[package]] name = "pathspec" version = "0.12.1" @@ -3222,6 +3675,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/05/33/2d74d588408caedd065c2497bdb5ef83ce6082db01289a1e1147f6639802/psutil-5.9.8-cp38-abi3-macosx_11_0_arm64.whl", hash = "sha256:d16bbddf0693323b8c6123dd804100241da461e41d6e332fb0ba6058f630f8c8", size = 249898, upload-time = "2024-01-19T20:47:59.238Z" }, ] +[[package]] +name = "py-partiql-parser" +version = "0.6.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/56/7a/a0f6bda783eb4df8e3dfd55973a1ac6d368a89178c300e1b5b91cd181e5e/py_partiql_parser-0.6.3.tar.gz", hash = "sha256:09cecf916ce6e3da2c050f0cb6106166de42c33d34a078ec2eb19377ea70389a", size = 17456, upload-time = "2025-10-18T13:56:13.441Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c9/33/a7cbfccc39056a5cf8126b7aab4c8bafbedd4f0ca68ae40ecb627a2d2cd3/py_partiql_parser-0.6.3-py2.py3-none-any.whl", hash = "sha256:deb0769c3346179d2f590dcbde556f708cdb929059fb654bad75f4cf6e07f582", size = 23752, upload-time = "2025-10-18T13:56:12.256Z" }, +] + [[package]] name = "pyarrow" version = "23.0.1" @@ -3311,7 +3773,7 @@ wheels = [ [[package]] name = "pydantic" -version = "2.12.5" +version = "2.12.4" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "annotated-types" }, @@ -3319,9 +3781,9 @@ dependencies = [ { name = "typing-extensions" }, { name = "typing-inspection" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/69/44/36f1a6e523abc58ae5f928898e4aca2e0ea509b5aa6f6f392a5d882be928/pydantic-2.12.5.tar.gz", hash = "sha256:4d351024c75c0f085a9febbb665ce8c0c6ec5d30e903bdb6394b7ede26aebb49", size = 821591, upload-time = "2025-11-26T15:11:46.471Z" } +sdist = { url = "https://files.pythonhosted.org/packages/96/ad/a17bc283d7d81837c061c49e3eaa27a45991759a1b7eae1031921c6bd924/pydantic-2.12.4.tar.gz", hash = "sha256:0f8cb9555000a4b5b617f66bfd2566264c4984b27589d3b845685983e8ea85ac", size = 821038, upload-time = "2025-11-05T10:50:08.59Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/5a/87/b70ad306ebb6f9b585f114d0ac2137d792b48be34d732d60e597c2f8465a/pydantic-2.12.5-py3-none-any.whl", hash = "sha256:e561593fccf61e8a20fc46dfc2dfe075b8be7d0188df33f221ad1f0139180f9d", size = 463580, upload-time = "2025-11-26T15:11:44.605Z" }, + { url = "https://files.pythonhosted.org/packages/82/2f/e68750da9b04856e2a7ec56fc6f034a5a79775e9b9a81882252789873798/pydantic-2.12.4-py3-none-any.whl", hash = "sha256:92d3d202a745d46f9be6df459ac5a064fdaa3c1c4cd8adcfa332ccf3c05f871e", size = 463400, upload-time = "2025-11-05T10:50:06.732Z" }, ] [[package]] @@ -3915,6 +4377,32 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/3f/51/d4db610ef29373b879047326cbf6fa98b6c1969d6f6dc423279de2b1be2c/requests_toolbelt-1.0.0-py2.py3-none-any.whl", hash = "sha256:cccfdd665f0a24fcf4726e690f65639d272bb0637b9b92dfd91a5568ccf6bd06", size = 54481, upload-time = "2023-05-01T04:11:28.427Z" }, ] +[[package]] +name = "responses" +version = "0.26.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "pyyaml" }, + { name = "requests" }, + { name = "urllib3" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/9f/b4/b7e040379838cc71bf5aabdb26998dfbe5ee73904c92c1c161faf5de8866/responses-0.26.0.tar.gz", hash = "sha256:c7f6923e6343ef3682816ba421c006626777893cb0d5e1434f674b649bac9eb4", size = 81303, upload-time = "2026-02-19T14:38:05.574Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ce/04/7f73d05b556da048923e31a0cc878f03be7c5425ed1f268082255c75d872/responses-0.26.0-py3-none-any.whl", hash = "sha256:03ec4409088cd5c66b71ecbbbd27fe2c58ddfad801c66203457b3e6a04868c37", size = 35099, upload-time = "2026-02-19T14:38:03.847Z" }, +] + +[[package]] +name = "rfc3339-validator" +version = "0.1.4" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "six" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/28/ea/a9387748e2d111c3c2b275ba970b735e04e15cdb1eb30693b6b5708c4dbd/rfc3339_validator-0.1.4.tar.gz", hash = "sha256:138a2abdf93304ad60530167e51d2dfb9549521a836871b88d7f4695d0022f6b", size = 5513, upload-time = "2021-05-12T16:37:54.178Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/7b/44/4e421b96b67b2daff264473f7465db72fbdf36a07e05494f50300cc7b0c6/rfc3339_validator-0.1.4-py2.py3-none-any.whl", hash = "sha256:24f6ec1eda14ef823da9e36ec7113124b39c04d50a4d3d3a3c2859577e7791fa", size = 3490, upload-time = "2021-05-12T16:37:52.536Z" }, +] + [[package]] name = "rfc3986" version = "2.0.0" @@ -4109,6 +4597,18 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/38/23/b3763a237d2523d40a31fe2d1a301191fe392dd48d3014977d079cf8c0bd/ruff-0.5.7-py3-none-win_arm64.whl", hash = "sha256:2dca26154ff9571995107221d0aeaad0e75a77b5a682d6236cf89a58c70b76f4", size = 8091891, upload-time = "2024-08-08T15:43:04.162Z" }, ] +[[package]] +name = "s3transfer" +version = "0.14.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "botocore" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/62/74/8d69dcb7a9efe8baa2046891735e5dfe433ad558ae23d9e3c14c633d1d58/s3transfer-0.14.0.tar.gz", hash = "sha256:eff12264e7c8b4985074ccce27a3b38a485bb7f7422cc8046fee9be4983e4125", size = 151547, upload-time = "2025-09-09T19:23:31.089Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/48/f0/ae7ca09223a81a1d890b2557186ea015f6e0502e9b8cb8e1813f1d8cfa4e/s3transfer-0.14.0-py3-none-any.whl", hash = "sha256:ea3b790c7077558ed1f02a3072fb3cb992bbbd253392f4b6e9e8976941c7d456", size = 85712, upload-time = "2025-09-09T19:23:30.041Z" }, +] + [[package]] name = "secretstorage" version = "3.4.0" @@ -4266,6 +4766,18 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/51/da/545b75d420bb23b5d494b0517757b351963e974e79933f01e05c929f20a6/starlette-0.49.1-py3-none-any.whl", hash = "sha256:d92ce9f07e4a3caa3ac13a79523bd18e3bc0042bb8ff2d759a8e7dd0e1859875", size = 74175, upload-time = "2025-10-28T17:34:09.13Z" }, ] +[[package]] +name = "sympy" +version = "1.14.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "mpmath" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/83/d3/803453b36afefb7c2bb238361cd4ae6125a569b4db67cd9e79846ba2d68c/sympy-1.14.0.tar.gz", hash = "sha256:d3d3fe8df1e5a0b42f0e7bdf50541697dbe7d23746e894990c030e2b05e72517", size = 7793921, upload-time = "2025-04-27T18:05:01.611Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/a2/09/77d55d46fd61b4a135c444fc97158ef34a095e5681d0a6c10b75bf356191/sympy-1.14.0-py3-none-any.whl", hash = "sha256:e091cc3e99d2141a0ba2847328f5479b05d94a6635cb96148ccb3f34671bd8f5", size = 6299353, upload-time = "2025-04-27T18:04:59.103Z" }, +] + [[package]] name = "temporalio" version = "1.24.0" @@ -4279,6 +4791,10 @@ dependencies = [ ] [package.optional-dependencies] +aioboto3 = [ + { name = "aioboto3" }, + { name = "types-aioboto3", extra = ["s3"] }, +] google-adk = [ { name = "google-adk" }, ] @@ -4305,6 +4821,7 @@ dev = [ { name = "grpcio-tools" }, { name = "httpx" }, { name = "maturin" }, + { name = "moto", extra = ["s3", "server"] }, { name = "mypy" }, { name = "mypy-protobuf" }, { name = "openai-agents" }, @@ -4328,6 +4845,7 @@ dev = [ [package.metadata] requires-dist = [ + { name = "aioboto3", marker = "extra == 'aioboto3'", specifier = ">=10.4.0" }, { name = "google-adk", marker = "extra == 'google-adk'", specifier = ">=1.27.0,<2" }, { name = "grpcio", marker = "extra == 'grpc'", specifier = ">=1.48.2,<2" }, { name = "mcp", marker = "extra == 'openai-agents'", specifier = ">=1.9.4,<2" }, @@ -4338,10 +4856,11 @@ requires-dist = [ { name = "protobuf", specifier = ">=3.20,<7.0.0" }, { name = "pydantic", marker = "extra == 'pydantic'", specifier = ">=2.0.0,<3" }, { name = "python-dateutil", marker = "python_full_version < '3.11'", specifier = ">=2.8.2,<3" }, + { name = "types-aioboto3", extras = ["s3"], marker = "extra == 'aioboto3'", specifier = ">=10.4.0" }, { name = "types-protobuf", specifier = ">=3.20" }, { name = "typing-extensions", specifier = ">=4.2.0,<5" }, ] -provides-extras = ["grpc", "opentelemetry", "pydantic", "openai-agents", "google-adk"] +provides-extras = ["grpc", "opentelemetry", "pydantic", "openai-agents", "google-adk", "aioboto3"] [package.metadata.requires-dev] dev = [ @@ -4351,6 +4870,7 @@ dev = [ { name = "grpcio-tools", specifier = ">=1.48.2,<2" }, { name = "httpx", specifier = ">=0.28.1" }, { name = "maturin", specifier = ">=1.8.2" }, + { name = "moto", extras = ["s3", "server"], specifier = ">=5" }, { name = "mypy", specifier = "==1.18.2" }, { name = "mypy-protobuf", specifier = ">=3.3.0,<4" }, { name = "openai-agents", marker = "python_full_version >= '3.14'", specifier = ">=0.3,<0.7" }, @@ -4575,6 +5095,60 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/eb/66/ab7efd8941f0bc7b2bd555b0f0471bff77df4c88e0cc31120c82737fec77/twisted-25.5.0-py3-none-any.whl", hash = "sha256:8559f654d01a54a8c3efe66d533d43f383531ebf8d81d9f9ab4769d91ca15df7", size = 3204767, upload-time = "2025-06-07T09:52:21.428Z" }, ] +[[package]] +name = "types-aioboto3" +version = "15.5.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "botocore-stubs" }, + { name = "types-aiobotocore" }, + { name = "types-s3transfer" }, + { name = "typing-extensions", marker = "python_full_version < '3.12'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/56/76/e162ea2ef8d414d4f36f28a6e0b6078ccef3f2f9d5f957859f303995c528/types_aioboto3-15.5.0.tar.gz", hash = "sha256:5769a1c3df7ca1abedf3656ddf0b970c9b0436d0f88cf4686040b55cd2a02925", size = 81059, upload-time = "2025-10-31T01:11:54.445Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ec/1d/e187fbe9771dffb5f0801e315ac23a6c383c14d1cbb90da6ca3ad1ea9b06/types_aioboto3-15.5.0-py3-none-any.whl", hash = "sha256:8aed7c9b6fe9b59e6ce74f7a6db7b8a9912a34c8f80ed639fac1fa59d6b20aa1", size = 42521, upload-time = "2025-10-31T01:11:47.832Z" }, +] + +[package.optional-dependencies] +s3 = [ + { name = "types-aiobotocore-s3" }, +] + +[[package]] +name = "types-aiobotocore" +version = "2.26.0.post2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "botocore-stubs" }, + { name = "typing-extensions", marker = "python_full_version < '3.12'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/3e/27/c60789f312a3630cbc82181e4d6e809bd8801b471de99f14ceb11f4c5c26/types_aiobotocore-2.26.0.post2.tar.gz", hash = "sha256:68ebe5e9de3201442e56359af182493e2e642e855a9133a5918352cbf5ac4e2d", size = 86472, upload-time = "2025-12-02T16:52:55.101Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/3d/47/e080e365376619d4062da8989747ecf7c8404bd94b2de10904239a3104f0/types_aiobotocore-2.26.0.post2-py3-none-any.whl", hash = "sha256:0e19caffd6ce6b1c3e7ba5b085d1d03357672e1aa65e5bcdfd9efb026a1041f7", size = 54207, upload-time = "2025-12-02T16:52:48.246Z" }, +] + +[[package]] +name = "types-aiobotocore-s3" +version = "2.25.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "typing-extensions", marker = "python_full_version < '3.12'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/a7/c6/9bb91a44eed1114690edb15d8251f32392e355dfa0a5b8e1c190b4cf89a4/types_aiobotocore_s3-2.25.2.tar.gz", hash = "sha256:678aa425491af19bd6d011d59ecdbbb7ae7e95800efddcf4fd559ab72c94e194", size = 75955, upload-time = "2025-11-12T01:52:06.536Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b4/0a/d0d9faefd7caa8536eb97647c38c711e73ab83341a65119d08c2cb20957d/types_aiobotocore_s3-2.25.2-py3-none-any.whl", hash = "sha256:151301e84bb2f1cbf30f0d1ef791bb75c141cfbfe47b93fd317b7f1ba3eb35e4", size = 83626, upload-time = "2025-11-12T01:52:04.763Z" }, +] + +[[package]] +name = "types-awscrt" +version = "0.31.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/76/26/0aa563e229c269c528a3b8c709fc671ac2a5c564732fab0852ac6ee006cf/types_awscrt-0.31.3.tar.gz", hash = "sha256:09d3eaf00231e0f47e101bd9867e430873bc57040050e2a3bd8305cb4fc30865", size = 18178, upload-time = "2026-03-08T02:31:14.569Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/3e/e5/47a573bbbd0a790f8f9fe452f7188ea72b212d21c9be57d5fc0cbc442075/types_awscrt-0.31.3-py3-none-any.whl", hash = "sha256:e5ce65a00a2ab4f35eacc1e3d700d792338d56e4823ee7b4dbe017f94cfc4458", size = 43340, upload-time = "2026-03-08T02:31:13.38Z" }, +] + [[package]] name = "types-protobuf" version = "6.32.1.20250918" @@ -4596,6 +5170,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/2a/20/9a227ea57c1285986c4cf78400d0a91615d25b24e257fd9e2969606bdfae/types_requests-2.32.4.20250913-py3-none-any.whl", hash = "sha256:78c9c1fffebbe0fa487a418e0fa5252017e9c60d1a2da394077f1780f655d7e1", size = 20658, upload-time = "2025-09-13T02:40:01.115Z" }, ] +[[package]] +name = "types-s3transfer" +version = "0.16.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/fe/64/42689150509eb3e6e82b33ee3d89045de1592488842ddf23c56957786d05/types_s3transfer-0.16.0.tar.gz", hash = "sha256:b4636472024c5e2b62278c5b759661efeb52a81851cde5f092f24100b1ecb443", size = 13557, upload-time = "2025-12-08T08:13:09.928Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/98/27/e88220fe6274eccd3bdf95d9382918716d312f6f6cef6a46332d1ee2feff/types_s3transfer-0.16.0-py3-none-any.whl", hash = "sha256:1c0cd111ecf6e21437cb410f5cddb631bfb2263b77ad973e79b9c6d0cb24e0ef", size = 19247, upload-time = "2025-12-08T08:13:08.426Z" }, +] + [[package]] name = "typing-extensions" version = "4.15.0" @@ -4761,6 +5344,18 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/fa/a8/5b41e0da817d64113292ab1f8247140aac61cbf6cfd085d6a0fa77f4984f/websockets-15.0.1-py3-none-any.whl", hash = "sha256:f7a866fbc1e97b5c617ee4116daaa09b722101d4a3c170c787450ba409f9736f", size = 169743, upload-time = "2025-03-05T20:03:39.41Z" }, ] +[[package]] +name = "werkzeug" +version = "3.1.6" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "markupsafe" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/61/f1/ee81806690a87dab5f5653c1f146c92bc066d7f4cebc603ef88eb9e13957/werkzeug-3.1.6.tar.gz", hash = "sha256:210c6bede5a420a913956b4791a7f4d6843a43b6fcee4dfa08a65e93007d0d25", size = 864736, upload-time = "2026-02-19T15:17:18.884Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/4d/ec/d58832f89ede95652fd01f4f24236af7d32b70cab2196dfcc2d2fd13c5c2/werkzeug-3.1.6-py3-none-any.whl", hash = "sha256:7ddf3357bb9564e407607f988f683d72038551200c704012bb9a4c523d42f131", size = 225166, upload-time = "2026-02-19T15:17:17.475Z" }, +] + [[package]] name = "wrapt" version = "1.17.3" @@ -4830,14 +5425,23 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/1f/f6/a933bd70f98e9cf3e08167fc5cd7aaaca49147e48411c0bd5ae701bb2194/wrapt-1.17.3-py3-none-any.whl", hash = "sha256:7171ae35d2c33d326ac19dd8facb1e82e5fd04ef8c6c0e394d7af55a55051c22", size = 23591, upload-time = "2025-08-12T05:53:20.674Z" }, ] +[[package]] +name = "xmltodict" +version = "1.0.4" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/19/70/80f3b7c10d2630aa66414bf23d210386700aa390547278c789afa994fd7e/xmltodict-1.0.4.tar.gz", hash = "sha256:6d94c9f834dd9e44514162799d344d815a3a4faec913717a9ecbfa5be1bb8e61", size = 26124, upload-time = "2026-02-22T02:21:22.074Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/38/34/98a2f52245f4d47be93b580dae5f9861ef58977d73a79eb47c58f1ad1f3a/xmltodict-1.0.4-py3-none-any.whl", hash = "sha256:a4a00d300b0e1c59fc2bfccb53d7b2e88c32f200df138a0dd2229f842497026a", size = 13580, upload-time = "2026-02-22T02:21:21.039Z" }, +] + [[package]] name = "yarl" version = "1.22.0" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "idna", marker = "python_full_version < '3.14'" }, - { name = "multidict", marker = "python_full_version < '3.14'" }, - { name = "propcache", marker = "python_full_version < '3.14'" }, + { name = "idna" }, + { name = "multidict" }, + { name = "propcache" }, ] sdist = { url = "https://files.pythonhosted.org/packages/57/63/0c6ebca57330cd313f6102b16dd57ffaf3ec4c83403dcb45dbd15c6f3ea1/yarl-1.22.0.tar.gz", hash = "sha256:bebf8557577d4401ba8bd9ff33906f1376c877aa78d1fe216ad01b4d6745af71", size = 187169, upload-time = "2025-10-06T14:12:55.963Z" } wheels = [ From 9408022baa8dc25dccb7607c1b6dfdabcd7465f3 Mon Sep 17 00:00:00 2001 From: Justin Anderson <44687433+jmaeagle99@users.noreply.github.com> Date: Thu, 26 Mar 2026 14:34:42 -0700 Subject: [PATCH 020/226] Allow external storage to run concurrently and separate from codecs (#1394) --- temporalio/bridge/worker.py | 33 +++++++++--- temporalio/client.py | 2 +- temporalio/converter/_data_converter.py | 70 ++++++++++++++++--------- temporalio/worker/_activity.py | 4 +- temporalio/worker/_replayer.py | 2 +- temporalio/worker/_worker.py | 33 +++++++----- temporalio/worker/_workflow.py | 30 ++++++++--- tests/worker/test_visitor.py | 4 +- 8 files changed, 124 insertions(+), 54 deletions(-) diff --git a/temporalio/bridge/worker.py b/temporalio/bridge/worker.py index 297765be0..a9c857373 100644 --- a/temporalio/bridge/worker.py +++ b/temporalio/bridge/worker.py @@ -303,7 +303,7 @@ async def decode_activation( activation: temporalio.bridge.proto.workflow_activation.WorkflowActivation, data_converter: temporalio.converter.DataConverter, decode_headers: bool, - concurrency_limit: int, + storage_concurrency_limit: int, ) -> temporalio.converter._extstore.StorageOperationMetrics: """Decode all payloads in the activation. @@ -315,8 +315,16 @@ async def decode_activation( await CommandAwarePayloadVisitor( skip_search_attributes=True, skip_headers=not decode_headers, - concurrency_limit=concurrency_limit, - ).visit(_Visitor(data_converter._decode_payload_sequence), activation) + concurrency_limit=storage_concurrency_limit, + ).visit( + _Visitor(data_converter._external_retrieve_payload_sequence), activation + ) + + await CommandAwarePayloadVisitor( + skip_search_attributes=True, + skip_headers=not decode_headers, + ).visit(_Visitor(data_converter._decode_payload_sequence), activation) + return metrics @@ -324,18 +332,31 @@ async def encode_completion( completion: temporalio.bridge.proto.workflow_completion.WorkflowActivationCompletion, data_converter: temporalio.converter.DataConverter, encode_headers: bool, - concurrency_limit: int, + storage_concurrency_limit: int, ) -> temporalio.converter._extstore.StorageOperationMetrics: """Encode all payloads in the completion. Returns: Metrics from any external storage store operations that occurred. """ + await CommandAwarePayloadVisitor( + skip_search_attributes=True, + skip_headers=not encode_headers, + ).visit(_Visitor(data_converter._encode_payload_sequence), completion) + + async def _store_and_validate( + payloads: Sequence[Payload], + ) -> list[Payload]: + stored = await data_converter._external_store_payload_sequence(payloads) + data_converter._validate_payload_limits(stored) + return stored + metrics = temporalio.converter._extstore.StorageOperationMetrics() with metrics.track(): await CommandAwarePayloadVisitor( skip_search_attributes=True, skip_headers=not encode_headers, - concurrency_limit=concurrency_limit, - ).visit(_Visitor(data_converter._encode_payload_sequence), completion) + concurrency_limit=storage_concurrency_limit, + ).visit(_Visitor(_store_and_validate), completion) + return metrics diff --git a/temporalio/client.py b/temporalio/client.py index 22b07b1c1..cc2750ec6 100644 --- a/temporalio/client.py +++ b/temporalio/client.py @@ -9185,7 +9185,7 @@ async def _apply_headers( return if encode_headers: for payload in source.values(): - payload.CopyFrom(await data_converter._encode_payload(payload)) + payload.CopyFrom(await data_converter._transform_outbound_payload(payload)) temporalio.common._apply_headers(source, dest) diff --git a/temporalio/converter/_data_converter.py b/temporalio/converter/_data_converter.py index 9c2163774..99de876ea 100644 --- a/temporalio/converter/_data_converter.py +++ b/temporalio/converter/_data_converter.py @@ -111,6 +111,8 @@ async def encode( """ payloads = self.payload_converter.to_payloads(values) payloads = await self._encode_payload_sequence(payloads) + payloads = await self._external_store_payload_sequence(payloads) + self._validate_payload_limits(payloads) return payloads async def decode( @@ -128,6 +130,7 @@ async def decode( Returns: Decoded and converted values. """ + payloads = await self._external_retrieve_payload_sequence(payloads) payloads = await self._decode_payload_sequence(payloads) return self.payload_converter.from_payloads(payloads, type_hints) @@ -156,13 +159,13 @@ async def encode_failure( ) -> None: """Convert and encode failure.""" self.failure_converter.to_failure(exception, self.payload_converter, failure) - await _apply_to_failure_payloads(failure, self._encode_payloads) + await _apply_to_failure_payloads(failure, self._transform_outbound_payloads) async def decode_failure( self, failure: temporalio.api.failure.v1.Failure ) -> BaseException: """Decode and convert failure.""" - await _apply_to_failure_payloads(failure, self._decode_payloads) + await _apply_to_failure_payloads(failure, self._transform_inbound_payloads) return self.failure_converter.from_failure(failure, self.payload_converter) def with_context(self, context: SerializationContext) -> Self: @@ -250,7 +253,7 @@ async def _encode_memo_existing( "[TMPRL1103] Attempted to upload memo with size that exceeded the warning limit.", ) - async def _encode_payload( + async def _transform_outbound_payload( self, payload: temporalio.api.common.v1.Payload ) -> temporalio.api.common.v1.Payload: if self.payload_codec: @@ -260,27 +263,16 @@ async def _encode_payload( self._validate_payload_limits([payload]) return payload - async def _encode_payloads(self, payloads: temporalio.api.common.v1.Payloads): + async def _transform_outbound_payloads( + self, payloads: temporalio.api.common.v1.Payloads + ): if self.payload_codec: await self.payload_codec.encode_wrapper(payloads) if self.external_storage: await self.external_storage._store_payloads(payloads) self._validate_payload_limits(payloads.payloads) - async def _encode_payload_sequence( - self, payloads: Sequence[temporalio.api.common.v1.Payload] - ) -> list[temporalio.api.common.v1.Payload]: - encoded_payloads = list(payloads) - if self.payload_codec: - encoded_payloads = await self.payload_codec.encode(encoded_payloads) - if self.external_storage: - encoded_payloads = await self.external_storage._store_payload_sequence( - encoded_payloads - ) - self._validate_payload_limits(encoded_payloads) - return encoded_payloads - - async def _decode_payload( + async def _transform_inbound_payload( self, payload: temporalio.api.common.v1.Payload ) -> temporalio.api.common.v1.Payload: if self.external_storage: @@ -289,7 +281,9 @@ async def _decode_payload( payload = (await self.payload_codec.decode([payload]))[0] return payload - async def _decode_payloads(self, payloads: temporalio.api.common.v1.Payloads): + async def _transform_inbound_payloads( + self, payloads: temporalio.api.common.v1.Payloads + ): if self.external_storage: await self.external_storage._retrieve_payloads(payloads) else: @@ -304,23 +298,51 @@ async def _decode_payloads(self, payloads: temporalio.api.common.v1.Payloads): if self.payload_codec: await self.payload_codec.decode_wrapper(payloads) - async def _decode_payload_sequence( + async def _encode_payload_sequence( self, payloads: Sequence[temporalio.api.common.v1.Payload] ) -> list[temporalio.api.common.v1.Payload]: - decoded_payloads = list(payloads) + """Codec encode only.""" + encoded_payloads = list(payloads) + if self.payload_codec: + encoded_payloads = await self.payload_codec.encode(encoded_payloads) + return encoded_payloads + + async def _external_store_payload_sequence( + self, payloads: Sequence[temporalio.api.common.v1.Payload] + ) -> list[temporalio.api.common.v1.Payload]: + """External storage store, then validate payload limits.""" + stored_payloads = list(payloads) + if self.external_storage: + stored_payloads = await self.external_storage._store_payload_sequence( + stored_payloads + ) + return stored_payloads + + async def _external_retrieve_payload_sequence( + self, payloads: Sequence[temporalio.api.common.v1.Payload] + ) -> list[temporalio.api.common.v1.Payload]: + """External storage retrieve only.""" + retrieved_payloads = list(payloads) if self.external_storage: - decoded_payloads = await self.external_storage._retrieve_payload_sequence( - decoded_payloads + retrieved_payloads = await self.external_storage._retrieve_payload_sequence( + retrieved_payloads ) else: if any( p.metadata.get("encoding") == _REFERENCE_ENCODING - for p in decoded_payloads + for p in retrieved_payloads ): warnings.warn( "[TMPRL1105] Detected externally stored payload(s) but external storage is not configured.", StorageWarning, ) + return retrieved_payloads + + async def _decode_payload_sequence( + self, payloads: Sequence[temporalio.api.common.v1.Payload] + ) -> list[temporalio.api.common.v1.Payload]: + """Codec decode only.""" + decoded_payloads = list(payloads) if self.payload_codec: decoded_payloads = await self.payload_codec.decode(decoded_payloads) return decoded_payloads diff --git a/temporalio/worker/_activity.py b/temporalio/worker/_activity.py index 7b67734d9..c7a1032fe 100644 --- a/temporalio/worker/_activity.py +++ b/temporalio/worker/_activity.py @@ -631,7 +631,9 @@ async def _execute_activity( if self._encode_headers: for payload in start.header_fields.values(): - payload.CopyFrom(await data_converter._decode_payload(payload)) + payload.CopyFrom( + await data_converter._transform_inbound_payload(payload) + ) running_activity.info = info input = ExecuteActivityInput( diff --git a/temporalio/worker/_replayer.py b/temporalio/worker/_replayer.py index 30a0f35df..508d5f708 100644 --- a/temporalio/worker/_replayer.py +++ b/temporalio/worker/_replayer.py @@ -268,7 +268,7 @@ def on_eviction_hook( "header_codec_behavior", HeaderCodecBehavior.NO_CODEC ) != HeaderCodecBehavior.NO_CODEC, - max_workflow_task_payload_concurrency=1, + max_workflow_task_external_storage_concurrency=1, ) external_storage = data_converter.external_storage storage_driver_types = ( diff --git a/temporalio/worker/_worker.py b/temporalio/worker/_worker.py index 0baccbe95..9057e1449 100644 --- a/temporalio/worker/_worker.py +++ b/temporalio/worker/_worker.py @@ -36,7 +36,10 @@ from ._nexus import _NexusWorker from ._plugin import Plugin from ._tuning import WorkerTuner -from ._workflow import _DEFAULT_WORKFLOW_TASK_PAYLOAD_CONCURRENCY, _WorkflowWorker +from ._workflow import ( + _DEFAULT_WORKFLOW_TASK_EXTERNAL_STORAGE_CONCURRENCY, + _WorkflowWorker, +) from ._workflow_instance import UnsandboxedWorkflowRunner, WorkflowRunner from .workflow_sandbox import SandboxedWorkflowRunner @@ -142,7 +145,7 @@ def __init__( maximum=5 ), disable_payload_error_limit: bool = False, - max_workflow_task_payload_concurrency: int = _DEFAULT_WORKFLOW_TASK_PAYLOAD_CONCURRENCY, + max_workflow_task_external_storage_concurrency: int = _DEFAULT_WORKFLOW_TASK_EXTERNAL_STORAGE_CONCURRENCY, ) -> None: """Create a worker to process workflows and/or activities. @@ -317,10 +320,10 @@ def __init__( and cause a task failure if the size limit is exceeded. The default is False. See https://docs.temporal.io/troubleshooting/blob-size-limit-error for more details. - max_workflow_task_payload_concurrency: Maximum number of payload - operations (codec encode/decode, external storage I/O, etc.) - that may run concurrently within a single workflow task - activation. Defaults to 1. WARNING: This setting is experimental. + max_workflow_task_external_storage_concurrency: Maximum number of + external storage I/O operations (store/retrieve) that may run + concurrently within a single workflow task activation. + Defaults to 10. WARNING: This setting is experimental. """ config = WorkerConfig( @@ -366,7 +369,7 @@ def __init__( activity_task_poller_behavior=activity_task_poller_behavior, nexus_task_poller_behavior=nexus_task_poller_behavior, disable_payload_error_limit=disable_payload_error_limit, - max_workflow_task_payload_concurrency=max_workflow_task_payload_concurrency, + max_workflow_task_external_storage_concurrency=max_workflow_task_external_storage_concurrency, ) plugins_from_client = cast( @@ -420,12 +423,14 @@ def _init_from_config(self, client: temporalio.client.Client, config: WorkerConf raise ValueError( "default_versioning_behavior must be UNSPECIFIED when use_worker_versioning is False" ) - max_workflow_task_payload_concurrency = config.get( - "max_workflow_task_payload_concurrency", - _DEFAULT_WORKFLOW_TASK_PAYLOAD_CONCURRENCY, + max_workflow_task_external_storage_concurrency = config.get( + "max_workflow_task_external_storage_concurrency", + _DEFAULT_WORKFLOW_TASK_EXTERNAL_STORAGE_CONCURRENCY, ) - if max_workflow_task_payload_concurrency < 1: - raise ValueError("max_workflow_task_payload_concurrency must be positive") + if max_workflow_task_external_storage_concurrency < 1: + raise ValueError( + "max_workflow_task_external_storage_concurrency must be positive" + ) # Prepend applicable client interceptors to the given ones client_config = config["client"].config(active_config=True) # type: ignore[reportTypedDictNotRequiredAccess] @@ -530,7 +535,7 @@ def check_activity(activity: str): assert_local_activity_valid=check_activity, encode_headers=client_config["header_codec_behavior"] != HeaderCodecBehavior.NO_CODEC, - max_workflow_task_payload_concurrency=max_workflow_task_payload_concurrency, + max_workflow_task_external_storage_concurrency=max_workflow_task_external_storage_concurrency, ) tuner = config.get("tuner") @@ -977,7 +982,7 @@ class WorkerConfig(TypedDict, total=False): activity_task_poller_behavior: PollerBehavior nexus_task_poller_behavior: PollerBehavior disable_payload_error_limit: bool - max_workflow_task_payload_concurrency: int + max_workflow_task_external_storage_concurrency: int def _warn_if_activity_executor_max_workers_is_inconsistent( diff --git a/temporalio/worker/_workflow.py b/temporalio/worker/_workflow.py index 4844ec198..914b14370 100644 --- a/temporalio/worker/_workflow.py +++ b/temporalio/worker/_workflow.py @@ -47,7 +47,7 @@ # Set to true to log all activations and completions LOG_PROTOS = False -_DEFAULT_WORKFLOW_TASK_PAYLOAD_CONCURRENCY: int = 1 +_DEFAULT_WORKFLOW_TASK_EXTERNAL_STORAGE_CONCURRENCY: int = 10 class _WorkflowWorker: # type:ignore[reportUnusedClass] @@ -76,7 +76,7 @@ def __init__( should_enforce_versioning_behavior: bool, assert_local_activity_valid: Callable[[str], None], encode_headers: bool, - max_workflow_task_payload_concurrency: int, + max_workflow_task_external_storage_concurrency: int, ) -> None: self._bridge_worker = bridge_worker self._namespace = namespace @@ -115,8 +115,8 @@ def __init__( self._on_eviction_hook = on_eviction_hook self._disable_safe_eviction = disable_safe_eviction self._encode_headers = encode_headers - self._max_workflow_task_payload_concurrency = ( - max_workflow_task_payload_concurrency + self._max_workflow_task_external_storage_concurrency = ( + max_workflow_task_external_storage_concurrency ) self._throw_after_activation: Exception | None = None @@ -300,7 +300,7 @@ async def _handle_activation( act, data_converter, decode_headers=self._encode_headers, - concurrency_limit=self._max_workflow_task_payload_concurrency, + storage_concurrency_limit=self._max_workflow_task_external_storage_concurrency, ) if not workflow: assert init_job @@ -409,7 +409,7 @@ async def _handle_activation( completion, data_converter, encode_headers=self._encode_headers, - concurrency_limit=self._max_workflow_task_payload_concurrency, + storage_concurrency_limit=self._max_workflow_task_external_storage_concurrency, ) except temporalio.converter._payload_limits._PayloadSizeError as err: logger.warning(err.message) @@ -893,11 +893,29 @@ async def _encode_payload_sequence( ) -> list[temporalio.api.common.v1.Payload]: return await self._get_current_dc()._encode_payload_sequence(payloads) + async def _external_store_payload_sequence( + self, payloads: Sequence[temporalio.api.common.v1.Payload] + ) -> list[temporalio.api.common.v1.Payload]: + return await self._get_current_dc()._external_store_payload_sequence(payloads) + + async def _external_retrieve_payload_sequence( + self, payloads: Sequence[temporalio.api.common.v1.Payload] + ) -> list[temporalio.api.common.v1.Payload]: + return await self._get_current_dc()._external_retrieve_payload_sequence( + payloads + ) + async def _decode_payload_sequence( self, payloads: Sequence[temporalio.api.common.v1.Payload] ) -> list[temporalio.api.common.v1.Payload]: return await self._get_current_dc()._decode_payload_sequence(payloads) + def _validate_payload_limits( + self, + payloads: Sequence[temporalio.api.common.v1.Payload], + ) -> None: + self._get_current_dc()._validate_payload_limits(payloads) + class _InterruptDeadlockError(BaseException): pass diff --git a/tests/worker/test_visitor.py b/tests/worker/test_visitor.py index 9d8463015..15860f58c 100644 --- a/tests/worker/test_visitor.py +++ b/tests/worker/test_visitor.py @@ -303,7 +303,9 @@ async def test_bridge_encoding(): payload_codec=SimpleCodec(), ) - await temporalio.bridge.worker.encode_completion(comp, data_converter, True, 1) + await temporalio.bridge.worker.encode_completion( + comp, data_converter, True, storage_concurrency_limit=1 + ) cmd = comp.successful.commands[0] sa = cmd.schedule_activity From d9e52195773c4218c915d8d94e40793377cf71aa Mon Sep 17 00:00:00 2001 From: Justin Anderson <44687433+jmaeagle99@users.noreply.github.com> Date: Wed, 1 Apr 2026 22:04:10 -0700 Subject: [PATCH 021/226] Adjustments to external storage defaults (#1404) --- README.md | 2 +- temporalio/contrib/aws/s3driver/README.md | 2 +- temporalio/converter/_extstore.py | 17 +++++++++-------- temporalio/worker/_worker.py | 7 +++++-- temporalio/worker/_workflow.py | 8 +++++++- tests/test_extstore.py | 21 ++++++++++++++++++--- tests/test_serialization_context.py | 2 +- tests/worker/test_extstore.py | 2 +- 8 files changed, 43 insertions(+), 18 deletions(-) diff --git a/README.md b/README.md index ca8a000f6..6fcd6fecb 100644 --- a/README.md +++ b/README.md @@ -503,7 +503,7 @@ Some things to note about external storage: * Only payloads that meet or exceed `ExternalStorage.payload_size_threshold` (default 256 KiB) are offloaded. Smaller payloads are stored inline as normal. * External storage applies transparently to all payloads, whether they are workflow inputs/outputs, activity inputs/outputs, signal inputs, query outputs, update inputs/outputs, or failure details. * The `DataConverter`'s `payload_codec` (if configured) is applied to the payload *before* it is handed to the storage driver, so the driver always stores encoded bytes. The reference payload written to workflow history is not encoded by the `DataConverter` codec. -* Setting `ExternalStorage.payload_size_threshold` to `None` causes every payload to be considered for external storage regardless of size. +* Setting `ExternalStorage.payload_size_threshold` to `0` causes every payload to be considered for external storage regardless of size. ###### Driver Selection diff --git a/temporalio/contrib/aws/s3driver/README.md b/temporalio/contrib/aws/s3driver/README.md index 8e6a3e365..c9520a688 100644 --- a/temporalio/contrib/aws/s3driver/README.md +++ b/temporalio/contrib/aws/s3driver/README.md @@ -66,7 +66,7 @@ Payloads are stored under content-addressable keys derived from a SHA-256 hash o * Any driver used to store payloads must also be configured on the component that retrieves them. If the client stores workflow inputs using this driver, the worker must include it in its `ExternalStorage.drivers` list to retrieve them. * The target S3 bucket must already exist; the driver will not create it. * Identical serialized bytes within the same namespace and workflow (or activity) share the same S3 object — the key is content-addressable within that scope. The same bytes used across different workflows or namespaces produce distinct S3 objects because the key includes the namespace and workflow/activity identifiers. -* Only payloads at or above `ExternalStorage.payload_size_threshold` (default: 256 KiB) are offloaded; smaller payloads are stored inline. Set `ExternalStorage.payload_size_threshold` to `None` to offload every payload regardless of size. +* Only payloads at or above `ExternalStorage.payload_size_threshold` (default: 256 KiB) are offloaded; smaller payloads are stored inline. Set `ExternalStorage.payload_size_threshold` to `0` to offload every payload regardless of size. * `S3StorageDriver.max_payload_size` (default: 50 MiB) sets a hard upper limit on the serialized size of any single payload. A `ValueError` is raised at store time if a payload exceeds this limit. Increase it if your workflows produce payloads larger than 50 MiB. * Override `S3StorageDriver.driver_name` only when registering multiple `S3StorageDriver` instances with distinct configurations under the same `ExternalStorage.drivers` list. diff --git a/temporalio/converter/_extstore.py b/temporalio/converter/_extstore.py index 078d36d98..28fad00a4 100644 --- a/temporalio/converter/_extstore.py +++ b/temporalio/converter/_extstore.py @@ -210,10 +210,9 @@ class ExternalStorage(WithSerializationContext): one driver is registered, that driver is used for all store operations. """ - payload_size_threshold: int | None = 256 * 1024 + payload_size_threshold: int = 256 * 1024 """Minimum payload size in bytes before external storage is considered. - Defaults to 256 KiB. Set to ``None`` to consider every payload for - external storage regardless of size. + Defaults to 256 KiB. Must be greater than or equal to zero. """ _driver_map: dict[str, StorageDriver] = dataclasses.field( @@ -234,7 +233,8 @@ class ExternalStorage(WithSerializationContext): def __post_init__(self) -> None: """Validate drivers and build the internal name-keyed driver map. - Raises :exc:`ValueError` if no drivers are provided, if more than one + Raises :exc:`ValueError` if no drivers are provided, if + :attr:`payload_size_threshold` is less than zero, if more than one driver is registered without a :attr:`driver_selector`, or if any two drivers share the same name. """ @@ -242,6 +242,10 @@ def __post_init__(self) -> None: raise ValueError( "ExternalStorage.drivers must contain at least one driver." ) + if self.payload_size_threshold < 0: + raise ValueError( + "ExternalStorage.payload_size_threshold must be greater than or equal to zero." + ) if len(self.drivers) > 1 and self.driver_selector is None: raise ValueError( "ExternalStorage.driver_selector must be specified if multiple drivers are registered." @@ -267,10 +271,7 @@ def _select_driver( self, context: StorageDriverStoreContext, payload: Payload ) -> StorageDriver | None: """Returns the driver to use for this payload, or None to pass through.""" - if ( - self.payload_size_threshold is not None - and payload.ByteSize() < self.payload_size_threshold - ): + if payload.ByteSize() < self.payload_size_threshold: return None selector = self.driver_selector if selector is None: diff --git a/temporalio/worker/_worker.py b/temporalio/worker/_worker.py index 9057e1449..332e2ead7 100644 --- a/temporalio/worker/_worker.py +++ b/temporalio/worker/_worker.py @@ -321,9 +321,12 @@ def __init__( See https://docs.temporal.io/troubleshooting/blob-size-limit-error for more details. max_workflow_task_external_storage_concurrency: Maximum number of - external storage I/O operations (store/retrieve) that may run + external storage payload operations (store/retrieve) that may run concurrently within a single workflow task activation. - Defaults to 10. WARNING: This setting is experimental. + Defaults to 3. Adjust this value based on your workload's needs. + Please report any issues you encounter with this setting or if you + feel the default should be changed. + WARNING: This setting is experimental. """ config = WorkerConfig( diff --git a/temporalio/worker/_workflow.py b/temporalio/worker/_workflow.py index 914b14370..fb104b414 100644 --- a/temporalio/worker/_workflow.py +++ b/temporalio/worker/_workflow.py @@ -47,7 +47,13 @@ # Set to true to log all activations and completions LOG_PROTOS = False -_DEFAULT_WORKFLOW_TASK_EXTERNAL_STORAGE_CONCURRENCY: int = 10 +# Value was chosen abitrarily as a small number that allows some concurrency and prevents +# large numbers of concurrent external storage operations causing resource contention. +# This default limit is per workflow task activation and does not limit the total number +# of concurrent external storage operations across all workflow task activations. +# Advise customers to adjust based on their workload needs and to report issues with the +# value if problems are encountered. This setting is experimental. +_DEFAULT_WORKFLOW_TASK_EXTERNAL_STORAGE_CONCURRENCY: int = 3 class _WorkflowWorker: # type:ignore[reportUnusedClass] diff --git a/tests/test_extstore.py b/tests/test_extstore.py index 7cff620ba..1771778a7 100644 --- a/tests/test_extstore.py +++ b/tests/test_extstore.py @@ -283,7 +283,7 @@ async def store( external_storage=ExternalStorage( drivers=drivers, driver_selector=lambda ctx, p: next(drivers_iter), - payload_size_threshold=None, + payload_size_threshold=0, ) ) @@ -337,7 +337,7 @@ async def retrieve( external_storage=ExternalStorage( drivers=drivers, driver_selector=lambda ctx, p: next(drivers_iter), - payload_size_threshold=None, + payload_size_threshold=0, ) ) encoded = await converter.encode(["payload_a", "payload_b"]) @@ -631,7 +631,7 @@ def selector(_ctx: object, payload: Payload) -> StorageDriver: external_storage=ExternalStorage( drivers=[driver_a, driver_b], driver_selector=selector, - payload_size_threshold=None, + payload_size_threshold=0, ) ) @@ -678,6 +678,21 @@ def test_duplicate_driver_names_raises(self): payload_size_threshold=50, ) + @pytest.mark.parametrize("threshold", [-1, -1000]) + def test_negative_payload_size_threshold_raises(self, threshold: int): + """A negative payload_size_threshold raises ValueError immediately + when constructing ExternalStorage.""" + driver = InMemoryTestDriver() + + with pytest.raises( + ValueError, + match=r"^ExternalStorage\.payload_size_threshold must be greater than or equal to zero\.$", + ): + ExternalStorage( + drivers=[driver], + payload_size_threshold=threshold, + ) + if __name__ == "__main__": pytest.main([__file__, "-v"]) diff --git a/tests/test_serialization_context.py b/tests/test_serialization_context.py index ad3768ec8..580926b4b 100644 --- a/tests/test_serialization_context.py +++ b/tests/test_serialization_context.py @@ -1972,7 +1972,7 @@ async def test_child_workflow_external_storage_with_context(client: Client): DataConverter.default, external_storage=ExternalStorage( drivers=[driver], - payload_size_threshold=None, + payload_size_threshold=0, ), ) client = Client(**config) diff --git a/tests/worker/test_extstore.py b/tests/worker/test_extstore.py index eb4270d08..8e2ee763a 100644 --- a/tests/worker/test_extstore.py +++ b/tests/worker/test_extstore.py @@ -581,7 +581,7 @@ def __init__(self, driver_name: str): external_storage=ExternalStorage( drivers=[driver1, driver2, driver3], driver_selector=lambda _context, _payload: driver1, - payload_size_threshold=None, + payload_size_threshold=0, ), ), ) From 496a6507648dd6cd194dcca99f3c9c76dffc7019 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 2 Apr 2026 09:45:02 -0700 Subject: [PATCH 022/226] Bump tar from 0.4.44 to 0.4.45 in /temporalio/bridge (#1383) Bumps [tar](https://github.com/alexcrichton/tar-rs) from 0.4.44 to 0.4.45. - [Commits](https://github.com/alexcrichton/tar-rs/compare/0.4.44...0.4.45) --- updated-dependencies: - dependency-name: tar dependency-version: 0.4.45 dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: tconley1428 --- temporalio/bridge/Cargo.lock | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/temporalio/bridge/Cargo.lock b/temporalio/bridge/Cargo.lock index d5fc84bab..85793c0f3 100644 --- a/temporalio/bridge/Cargo.lock +++ b/temporalio/bridge/Cargo.lock @@ -473,7 +473,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "778e2ac28f6c47af28e4907f13ffd1e1ddbd400980a9abd7c8df189bf578a5ad" dependencies = [ "libc", - "windows-sys 0.60.2", + "windows-sys 0.52.0", ] [[package]] @@ -1914,7 +1914,7 @@ dependencies = [ "once_cell", "socket2 0.5.10", "tracing", - "windows-sys 0.59.0", + "windows-sys 0.52.0", ] [[package]] @@ -2138,7 +2138,7 @@ dependencies = [ "errno", "libc", "linux-raw-sys", - "windows-sys 0.60.2", + "windows-sys 0.52.0", ] [[package]] @@ -2443,9 +2443,9 @@ dependencies = [ [[package]] name = "tar" -version = "0.4.44" +version = "0.4.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d863878d212c87a19c1a610eb53bb01fe12951c0501cf5a0d65f724914a667a" +checksum = "22692a6476a21fa75fdfc11d452fda482af402c008cdbaf3476414e122040973" dependencies = [ "filetime", "libc", @@ -2468,7 +2468,7 @@ dependencies = [ "getrandom 0.3.3", "once_cell", "rustix", - "windows-sys 0.59.0", + "windows-sys 0.52.0", ] [[package]] From 6c1bc4066227d0433e3958a16bb0ed3257e76d65 Mon Sep 17 00:00:00 2001 From: tconley1428 Date: Fri, 3 Apr 2026 13:52:53 -0700 Subject: [PATCH 023/226] Update types-protobuf limit (#1409) --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 4ee2fed92..c8fa96a8d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -12,7 +12,7 @@ dependencies = [ "nexus-rpc==1.4.0", "protobuf>=3.20,<7.0.0", "python-dateutil>=2.8.2,<3 ; python_version < '3.11'", - "types-protobuf>=3.20", + "types-protobuf>=3.20,<7.0.0", "typing-extensions>=4.2.0,<5", ] classifiers = [ From c0a8a01eebf9e8faaeedf7addb5d689bfbda0164 Mon Sep 17 00:00:00 2001 From: Justin Anderson <44687433+jmaeagle99@users.noreply.github.com> Date: Fri, 3 Apr 2026 21:35:09 -0700 Subject: [PATCH 024/226] Update storage driver store context metadata (#1399) --- README.md | 10 +- temporalio/client.py | 133 ++++- temporalio/contrib/aws/s3driver/_driver.py | 55 +- temporalio/converter/__init__.py | 4 + temporalio/converter/_data_converter.py | 20 + temporalio/converter/_extstore.py | 90 ++- temporalio/worker/_activity.py | 42 +- temporalio/worker/_command_aware_visitor.py | 9 + temporalio/worker/_workflow.py | 31 +- temporalio/worker/_workflow_instance.py | 85 ++- .../worker/workflow_sandbox/_in_sandbox.py | 8 + temporalio/worker/workflow_sandbox/_runner.py | 20 + tests/contrib/aws/s3driver/test_s3driver.py | 177 +++--- .../aws/s3driver/test_s3driver_worker.py | 184 ++++-- tests/test_serialization_context.py | 86 --- tests/worker/test_extstore.py | 544 ++++++++++++++++++ tests/worker/test_workflow.py | 7 + 17 files changed, 1196 insertions(+), 309 deletions(-) diff --git a/README.md b/README.md index 6fcd6fecb..f1e995ea6 100644 --- a/README.md +++ b/README.md @@ -533,11 +533,11 @@ def feature_flag_is_on(workflow_id: str | None) -> bool: def feature_flag_selector( context: temporalio.converter.StorageDriverStoreContext, _payload: Payload ) -> temporalio.converter.StorageDriver | None: - workflow_id = None - if isinstance(context.serialization_context, temporalio.converter.WorkflowSerializationContext): - workflow_id = context.serialization_context.workflow_id - elif isinstance(context.serialization_context, temporalio.converter.ActivitySerializationContext): - workflow_id = context.serialization_context.workflow_id + workflow_id = ( + context.target.id + if isinstance(context.target, temporalio.converter.StorageDriverWorkflowInfo) + else None + ) return my_driver if feature_flag_is_on(workflow_id) else None options = ExternalStorage( diff --git a/temporalio/client.py b/temporalio/client.py index cc2750ec6..9e7bc6045 100644 --- a/temporalio/client.py +++ b/temporalio/client.py @@ -66,6 +66,9 @@ ActivitySerializationContext, DataConverter, SerializationContext, + StorageDriverActivityInfo, + StorageDriverStoreContext, + StorageDriverWorkflowInfo, WithSerializationContext, WorkflowSerializationContext, ) @@ -6161,11 +6164,16 @@ async def _to_proto( priority: temporalio.api.common.v1.Priority | None = None if self.priority: priority = self.priority._to_proto() - data_converter = client.data_converter.with_context( + data_converter = client.data_converter._with_contexts( WorkflowSerializationContext( namespace=client.namespace, workflow_id=self.id, - ) + ), + StorageDriverStoreContext( + target=StorageDriverWorkflowInfo( + id=self.id, type=self.workflow, namespace=client.namespace + ), + ), ) action = temporalio.api.schedule.v1.ScheduleAction( start_workflow=temporalio.api.workflow.v1.NewWorkflowExecutionInfo( @@ -6210,7 +6218,8 @@ async def _to_proto( # TODO (dan): confirm whether this be `is not None` if self.typed_search_attributes: temporalio.converter.encode_search_attributes( - self.typed_search_attributes, action.start_workflow.search_attributes + self.typed_search_attributes, + action.start_workflow.search_attributes, ) if self.headers: await _apply_headers( @@ -8077,11 +8086,16 @@ async def _build_signal_with_start_workflow_execution_request( self, input: StartWorkflowInput ) -> temporalio.api.workflowservice.v1.SignalWithStartWorkflowExecutionRequest: assert input.start_signal - data_converter = self._client.data_converter.with_context( + data_converter = self._client.data_converter._with_contexts( WorkflowSerializationContext( namespace=self._client.namespace, workflow_id=input.id, - ) + ), + StorageDriverStoreContext( + target=StorageDriverWorkflowInfo( + id=input.id, type=input.workflow, namespace=self._client.namespace + ), + ), ) req = temporalio.api.workflowservice.v1.SignalWithStartWorkflowExecutionRequest( signal_name=input.start_signal @@ -8108,11 +8122,16 @@ async def _populate_start_workflow_execution_request( ), input: StartWorkflowInput | UpdateWithStartStartWorkflowInput, ) -> None: - data_converter = self._client.data_converter.with_context( + data_converter = self._client.data_converter._with_contexts( WorkflowSerializationContext( namespace=self._client.namespace, workflow_id=input.id, - ) + ), + StorageDriverStoreContext( + target=StorageDriverWorkflowInfo( + id=input.id, type=input.workflow, namespace=self._client.namespace + ), + ), ) req.namespace = self._client.namespace req.workflow_id = input.id @@ -8228,11 +8247,18 @@ async def count_workflows( ) async def query_workflow(self, input: QueryWorkflowInput) -> Any: - data_converter = self._client.data_converter.with_context( + data_converter = self._client.data_converter._with_contexts( WorkflowSerializationContext( namespace=self._client.namespace, workflow_id=input.id, - ) + ), + StorageDriverStoreContext( + target=StorageDriverWorkflowInfo( + id=input.id, + run_id=input.run_id or None, + namespace=self._client.namespace, + ), + ), ) req = temporalio.api.workflowservice.v1.QueryWorkflowRequest( namespace=self._client.namespace, @@ -8255,7 +8281,10 @@ async def query_workflow(self, input: QueryWorkflowInput) -> Any: await self._apply_headers(input.headers, req.query.header.fields) try: resp = await self._client.workflow_service.query_workflow( - req, retry=True, metadata=input.rpc_metadata, timeout=input.rpc_timeout + req, + retry=True, + metadata=input.rpc_metadata, + timeout=input.rpc_timeout, ) except RPCError as err: # If the status is INVALID_ARGUMENT, we can assume it's a query @@ -8281,11 +8310,18 @@ async def query_workflow(self, input: QueryWorkflowInput) -> Any: return results[0] async def signal_workflow(self, input: SignalWorkflowInput) -> None: - data_converter = self._client.data_converter.with_context( + data_converter = self._client.data_converter._with_contexts( WorkflowSerializationContext( namespace=self._client.namespace, workflow_id=input.id, - ) + ), + StorageDriverStoreContext( + target=StorageDriverWorkflowInfo( + id=input.id, + run_id=input.run_id or None, + namespace=self._client.namespace, + ), + ), ) req = temporalio.api.workflowservice.v1.SignalWorkflowExecutionRequest( namespace=self._client.namespace, @@ -8306,11 +8342,18 @@ async def signal_workflow(self, input: SignalWorkflowInput) -> None: ) async def terminate_workflow(self, input: TerminateWorkflowInput) -> None: - data_converter = self._client.data_converter.with_context( + data_converter = self._client.data_converter._with_contexts( WorkflowSerializationContext( namespace=self._client.namespace, workflow_id=input.id, - ) + ), + StorageDriverStoreContext( + target=StorageDriverWorkflowInfo( + id=input.id, + run_id=input.run_id or None, + namespace=self._client.namespace, + ), + ), ) req = temporalio.api.workflowservice.v1.TerminateWorkflowExecutionRequest( namespace=self._client.namespace, @@ -8365,7 +8408,7 @@ async def _build_start_activity_execution_request( self, input: StartActivityInput ) -> temporalio.api.workflowservice.v1.StartActivityExecutionRequest: """Build StartActivityExecutionRequest from input.""" - data_converter = self._client.data_converter.with_context( + data_converter = self._client.data_converter._with_contexts( ActivitySerializationContext( namespace=self._client.namespace, activity_id=input.id, @@ -8374,7 +8417,14 @@ async def _build_start_activity_execution_request( is_local=False, workflow_id=None, workflow_type=None, - ) + ), + StorageDriverStoreContext( + target=StorageDriverActivityInfo( + id=input.id, + type=input.activity_type, + namespace=self._client.namespace, + ), + ), ) req = temporalio.api.workflowservice.v1.StartActivityExecutionRequest( @@ -8560,11 +8610,20 @@ async def _build_update_workflow_execution_request( input: StartWorkflowUpdateInput | UpdateWithStartUpdateWorkflowInput, workflow_id: str, ) -> temporalio.api.workflowservice.v1.UpdateWorkflowExecutionRequest: - data_converter = self._client.data_converter.with_context( + data_converter = self._client.data_converter._with_contexts( WorkflowSerializationContext( namespace=self._client.namespace, workflow_id=workflow_id, - ) + ), + StorageDriverStoreContext( + target=StorageDriverWorkflowInfo( + id=workflow_id, + run_id=(input.run_id or None) + if isinstance(input, StartWorkflowUpdateInput) + else None, + namespace=self._client.namespace, + ), + ), ) run_id, first_execution_run_id = ( ( @@ -8739,10 +8798,34 @@ async def _start_workflow_update_with_start( ### Async activity calls + def _get_async_activity_store_context( + self, id_or_token: AsyncActivityIDReference | bytes + ) -> StorageDriverStoreContext: + if isinstance(id_or_token, AsyncActivityIDReference): + if id_or_token.workflow_id: + return StorageDriverStoreContext( + target=StorageDriverWorkflowInfo( + id=id_or_token.workflow_id or None, + run_id=id_or_token.run_id or None, + namespace=self._client.namespace, + ), + ) + return StorageDriverStoreContext( + target=StorageDriverActivityInfo( + id=id_or_token.activity_id, + run_id=id_or_token.run_id or None, + namespace=self._client.namespace, + ), + ) + else: + return StorageDriverStoreContext(target=None) + async def heartbeat_async_activity( self, input: HeartbeatAsyncActivityInput ) -> None: - data_converter = input.data_converter_override or self._client.data_converter + data_converter = ( + input.data_converter_override or self._client.data_converter + )._with_store_context(self._get_async_activity_store_context(input.id_or_token)) details = ( None if not input.details @@ -8797,7 +8880,9 @@ async def heartbeat_async_activity( ) async def complete_async_activity(self, input: CompleteAsyncActivityInput) -> None: - data_converter = input.data_converter_override or self._client.data_converter + data_converter = ( + input.data_converter_override or self._client.data_converter + )._with_store_context(self._get_async_activity_store_context(input.id_or_token)) result = ( None if input.result is temporalio.common._arg_unset @@ -8831,7 +8916,9 @@ async def complete_async_activity(self, input: CompleteAsyncActivityInput) -> No ) async def fail_async_activity(self, input: FailAsyncActivityInput) -> None: - data_converter = input.data_converter_override or self._client.data_converter + data_converter = ( + input.data_converter_override or self._client.data_converter + )._with_store_context(self._get_async_activity_store_context(input.id_or_token)) failure = temporalio.api.failure.v1.Failure() await data_converter.encode_failure(input.error, failure) @@ -8872,7 +8959,9 @@ async def fail_async_activity(self, input: FailAsyncActivityInput) -> None: async def report_cancellation_async_activity( self, input: ReportCancellationAsyncActivityInput ) -> None: - data_converter = input.data_converter_override or self._client.data_converter + data_converter = ( + input.data_converter_override or self._client.data_converter + )._with_store_context(self._get_async_activity_store_context(input.id_or_token)) details = ( None if not input.details diff --git a/temporalio/contrib/aws/s3driver/_driver.py b/temporalio/contrib/aws/s3driver/_driver.py index 481e3a9d4..1f9d129c9 100644 --- a/temporalio/contrib/aws/s3driver/_driver.py +++ b/temporalio/contrib/aws/s3driver/_driver.py @@ -15,12 +15,12 @@ from temporalio.api.common.v1 import Payload from temporalio.contrib.aws.s3driver._client import S3StorageDriverClient from temporalio.converter import ( - ActivitySerializationContext, StorageDriver, + StorageDriverActivityInfo, StorageDriverClaim, StorageDriverRetrieveContext, StorageDriverStoreContext, - WorkflowSerializationContext, + StorageDriverWorkflowInfo, ) _T = TypeVar("_T") @@ -113,40 +113,25 @@ async def store( (e.g. proto binary). The returned list is the same length as ``payloads``. """ - workflow_id: str | None = None - activity_id: str | None = None - namespace: str | None = None - if isinstance(context.serialization_context, WorkflowSerializationContext): - workflow_id = context.serialization_context.workflow_id - namespace = context.serialization_context.namespace - if isinstance(context.serialization_context, ActivitySerializationContext): - # Prioritize workflow over activity so that the same payload that - # may be stored across workflow and activity boundaries are deduplicated. - if context.serialization_context.workflow_id: - workflow_id = context.serialization_context.workflow_id - elif context.serialization_context.activity_id: - activity_id = context.serialization_context.activity_id - namespace = context.serialization_context.namespace - - # URL encode values to avoid characters that break the key format - # e.g. spaces, forward-slashes, etc. - if namespace: - namespace = urllib.parse.quote(namespace, safe="") - if workflow_id: - workflow_id = urllib.parse.quote(workflow_id, safe="") - if activity_id: - activity_id = urllib.parse.quote(activity_id, safe="") - - namespace_segments = f"/ns/{namespace}" if namespace else "" + def _quote(val: str | None) -> str | None: + return urllib.parse.quote(val, safe="") if val else None + + # Build context segments from the target identity. context_segments = "" - # Prioritize workflow over activity so that the same payload that - # may be stored across workflow and activity boundaries are deduplicated. - # Workflow and Activity IDs are case sensitive. - if workflow_id: - context_segments += f"/wfi/{workflow_id}" - elif activity_id: - context_segments += f"/aci/{activity_id}" + target = context.target + namespace = _quote(target.namespace) if target is not None else None + namespace_segment = f"/ns/{namespace}" if namespace else "" + if isinstance(target, StorageDriverWorkflowInfo): + wf_type = _quote(target.type) or "null" + wf_id = _quote(target.id) or "null" + wf_run_id = _quote(target.run_id) or "null" + context_segments = f"/wt/{wf_type}/wi/{wf_id}/ri/{wf_run_id}" + elif isinstance(target, StorageDriverActivityInfo): + act_type = _quote(target.type) or "null" + act_id = _quote(target.id) or "null" + act_run_id = _quote(target.run_id) or "null" + context_segments = f"/at/{act_type}/ai/{act_id}/ri/{act_run_id}" async def _upload(payload: Payload) -> StorageDriverClaim: bucket = self._get_bucket(context, payload) @@ -162,7 +147,7 @@ async def _upload(payload: Payload) -> StorageDriverClaim: digest_segments = f"/d/sha256/{hash_digest}" - key = f"v0{namespace_segments}{context_segments}{digest_segments}" + key = f"v0{namespace_segment}{context_segments}{digest_segments}" try: if not await self._client.object_exists(bucket=bucket, key=key): diff --git a/temporalio/converter/__init__.py b/temporalio/converter/__init__.py index 2777e7e80..3ca6a3507 100644 --- a/temporalio/converter/__init__.py +++ b/temporalio/converter/__init__.py @@ -7,9 +7,11 @@ from temporalio.converter._extstore import ( ExternalStorage, StorageDriver, + StorageDriverActivityInfo, StorageDriverClaim, StorageDriverRetrieveContext, StorageDriverStoreContext, + StorageDriverWorkflowInfo, StorageWarning, ) from temporalio.converter._failure_converter import ( @@ -54,9 +56,11 @@ "ActivitySerializationContext", "ExternalStorage", "StorageDriver", + "StorageDriverActivityInfo", "StorageDriverClaim", "StorageDriverRetrieveContext", "StorageDriverStoreContext", + "StorageDriverWorkflowInfo", "StorageWarning", "AdvancedJSONEncoder", "BinaryNullPayloadConverter", diff --git a/temporalio/converter/_data_converter.py b/temporalio/converter/_data_converter.py index 99de876ea..0323466e7 100644 --- a/temporalio/converter/_data_converter.py +++ b/temporalio/converter/_data_converter.py @@ -17,6 +17,7 @@ from temporalio.converter._extstore import ( _REFERENCE_ENCODING, ExternalStorage, + StorageDriverStoreContext, StorageWarning, ) from temporalio.converter._failure_converter import ( @@ -199,6 +200,25 @@ def with_context(self, context: SerializationContext) -> Self: object.__setattr__(cloned, "external_storage", external_storage) return cloned + def _with_store_context( + self, store_ctx: StorageDriverStoreContext + ) -> DataConverter: + """Return an instance with ``store_ctx`` bound into :attr:`external_storage`.""" + if self.external_storage is None: + return self + return dataclasses.replace( + self, + external_storage=self.external_storage._with_store_context(store_ctx), + ) + + def _with_contexts( + self, + serialization_ctx: SerializationContext, + store_ctx: StorageDriverStoreContext, + ) -> DataConverter: + """Return an instance with both serialization and store contexts applied.""" + return self.with_context(serialization_ctx)._with_store_context(store_ctx) + def _with_payload_error_limits( self, limits: _ServerPayloadErrorLimits | None ) -> DataConverter: diff --git a/temporalio/converter/_extstore.py b/temporalio/converter/_extstore.py index 28fad00a4..e787652a5 100644 --- a/temporalio/converter/_extstore.py +++ b/temporalio/converter/_extstore.py @@ -19,10 +19,6 @@ from temporalio.api.common.v1 import Payload, Payloads from temporalio.converter._payload_converter import JSONPlainPayloadConverter -from temporalio.converter._serialization_context import ( - SerializationContext, - WithSerializationContext, -) _T = TypeVar("_T") @@ -92,6 +88,48 @@ class StorageDriverClaim: """ +@dataclass(frozen=True, kw_only=True) +class StorageDriverWorkflowInfo: + """Workflow identity information for external storage operations. + + .. warning:: + This API is experimental. + """ + + namespace: str + """The namespace of the workflow execution.""" + + id: str | None = None + """The workflow ID.""" + + run_id: str | None = None + """The workflow run ID, if available.""" + + type: str | None = None + """The workflow type name, if available.""" + + +@dataclass(frozen=True, kw_only=True) +class StorageDriverActivityInfo: + """Activity identity information for external storage operations. + + .. warning:: + This API is experimental. + """ + + namespace: str + """The namespace of the activity execution.""" + + id: str | None = None + """The activity ID.""" + + run_id: str | None = None + """The activity run ID (only for standalone activities).""" + + type: str | None = None + """The activity type name, if available.""" + + @dataclass(frozen=True) class StorageDriverStoreContext: """Context passed to :meth:`StorageDriver.store` and ``driver_selector`` calls. @@ -100,10 +138,14 @@ class StorageDriverStoreContext: This API is experimental. """ - serialization_context: SerializationContext | None = None - """The serialization context active when this store operation was initiated, - or ``None`` if no context has been set. - """ + target: StorageDriverActivityInfo | StorageDriverWorkflowInfo | None = None + """The workflow or activity for which this payload is being stored. + + For payloads being stored on behalf of an explicit target (e.g. a child + workflow being started, an activity being scheduled, an external workflow + being signaled), this is that target's identity. When no explicit target + exists the current execution context (workflow or activity) is used as the + target instead.""" @dataclass(frozen=True) @@ -182,7 +224,7 @@ class _StorageReference: @dataclass(frozen=True) -class ExternalStorage(WithSerializationContext): +class ExternalStorage: """Configuration for external storage behavior. .. warning:: @@ -222,9 +264,13 @@ class ExternalStorage(WithSerializationContext): for retrieval lookups. """ - _context: SerializationContext | None = dataclasses.field( - init=False, default=None, repr=False, compare=False + _store_context: StorageDriverStoreContext = dataclasses.field( + default=StorageDriverStoreContext(target=None), + init=False, + repr=False, + compare=False, ) + """Store context bound to this instance via :meth:`_with_store_context`.""" _claim_converter: ClassVar[JSONPlainPayloadConverter] = JSONPlainPayloadConverter( encoding=_REFERENCE_ENCODING.decode() @@ -261,12 +307,6 @@ def __post_init__(self) -> None: driver_map[name] = driver object.__setattr__(self, "_driver_map", driver_map) - def with_context(self, context: SerializationContext) -> Self: - """Return a copy of these options with the serialization context applied.""" - result = dataclasses.replace(self) - object.__setattr__(result, "_context", context) - return result - def _select_driver( self, context: StorageDriverStoreContext, payload: Payload ) -> StorageDriver | None: @@ -293,15 +333,20 @@ def _get_driver_by_name(self, name: str) -> StorageDriver: raise ValueError(f"No driver found with name '{name}'") return driver + def _with_store_context(self, ctx: StorageDriverStoreContext) -> ExternalStorage: + """Return a copy of this instance with ``ctx`` bound as the store context.""" + result = dataclasses.replace(self) + object.__setattr__(result, "_store_context", ctx) + return result + async def _store_payload(self, payload: Payload) -> Payload: start_time = time.monotonic() - context = StorageDriverStoreContext(serialization_context=self._context) - driver = self._select_driver(context, payload) + driver = self._select_driver(self._store_context, payload) if driver is None: return payload - claims = await driver.store(context, [payload]) + claims = await driver.store(self._store_context, [payload]) self._validate_claim_length(claims, expected=1, driver=driver) @@ -336,11 +381,10 @@ async def _store_payload_sequence( start_time = time.monotonic() results = list(payloads) - context = StorageDriverStoreContext(serialization_context=self._context) to_store: list[tuple[int, Payload, StorageDriver]] = [] for index, payload in enumerate(payloads): - driver = self._select_driver(context, payload) + driver = self._select_driver(self._store_context, payload) if driver is None: continue to_store.append((index, payload, driver)) @@ -356,7 +400,7 @@ async def _store_payload_sequence( all_claims = await _gather_cancel_on_error( [ - driver.store(context, [p for _, p in indexed_payloads]) + driver.store(self._store_context, [p for _, p in indexed_payloads]) for driver, indexed_payloads in driver_group_list ] ) diff --git a/temporalio/worker/_activity.py b/temporalio/worker/_activity.py index c7a1032fe..28cc1458a 100644 --- a/temporalio/worker/_activity.py +++ b/temporalio/worker/_activity.py @@ -34,6 +34,11 @@ import temporalio.converter import temporalio.converter._payload_limits import temporalio.exceptions +from temporalio.converter import ( + StorageDriverActivityInfo, + StorageDriverStoreContext, + StorageDriverWorkflowInfo, +) from ._interceptor import ( ActivityInboundInterceptor, @@ -262,7 +267,17 @@ async def _heartbeat_async( activity_task_queue=self._task_queue, is_local=activity.info.is_local, ) - data_converter = data_converter.with_context(context) + data_converter = data_converter._with_contexts( + context, + StorageDriverStoreContext( + target=StorageDriverActivityInfo( + id=activity.info.activity_id, + type=activity.info.activity_type, + run_id=activity.info.activity_run_id, + namespace=activity.info.namespace, + ), + ), + ) # Perform the heartbeat try: @@ -270,7 +285,6 @@ async def _heartbeat_async( task_token=task_token ) if details: - # Convert to core payloads heartbeat.details.extend(await data_converter.encode(details)) logger.debug("Recording heartbeat with details %s", details) self._bridge_worker().record_activity_heartbeat(heartbeat) @@ -316,6 +330,30 @@ async def _handle_start_activity_task( is_local=start.is_local, ) data_converter = self._data_converter.with_context(context) + + # Build store context for external storage + ns = start.workflow_namespace or self._client.namespace + # Store context is set for the full activity task lifetime (input + # decode, execution, result/failure encode). Each activity task runs + # in its own coroutine so the value won't leak to other tasks. + started_by_workflow = bool(start.workflow_execution.workflow_id) + store_target: StorageDriverWorkflowInfo | StorageDriverActivityInfo + if started_by_workflow: + store_target = StorageDriverWorkflowInfo( + id=start.workflow_execution.workflow_id or None, + type=start.workflow_type or None, + run_id=start.workflow_execution.run_id or None, + namespace=ns, + ) + else: + store_target = StorageDriverActivityInfo( + id=start.activity_id or None, + type=start.activity_type or None, + namespace=ns, + ) + data_converter = self._data_converter._with_contexts( + context, StorageDriverStoreContext(target=store_target) + ) try: result = await self._execute_activity( start, running_activity, task_token, data_converter diff --git a/temporalio/worker/_command_aware_visitor.py b/temporalio/worker/_command_aware_visitor.py index 327f8c68c..f77bea042 100644 --- a/temporalio/worker/_command_aware_visitor.py +++ b/temporalio/worker/_command_aware_visitor.py @@ -17,6 +17,7 @@ ResolveSignalExternalWorkflow, ) from temporalio.bridge.proto.workflow_commands.workflow_commands_pb2 import ( + CompleteWorkflowExecution, ScheduleActivity, ScheduleLocalActivity, ScheduleNexusOperation, @@ -67,6 +68,14 @@ def __init__( ) # Workflow commands with payloads + async def _visit_coresdk_workflow_commands_CompleteWorkflowExecution( + self, fs: VisitorFunctions, o: CompleteWorkflowExecution + ) -> None: + with current_command(CommandType.COMMAND_TYPE_COMPLETE_WORKFLOW_EXECUTION, 0): + await super()._visit_coresdk_workflow_commands_CompleteWorkflowExecution( + fs, o + ) + async def _visit_coresdk_workflow_commands_ScheduleActivity( self, fs: VisitorFunctions, o: ScheduleActivity ) -> None: diff --git a/temporalio/worker/_workflow.py b/temporalio/worker/_workflow.py index fb104b414..b699e421d 100644 --- a/temporalio/worker/_workflow.py +++ b/temporalio/worker/_workflow.py @@ -28,6 +28,7 @@ import temporalio.workflow from temporalio.api.enums.v1 import WorkflowTaskFailedCause from temporalio.bridge.worker import PollShutdownError +from temporalio.converter import StorageDriverStoreContext, StorageDriverWorkflowInfo from . import _command_aware_visitor from ._interceptor import ( @@ -294,7 +295,21 @@ async def _handle_activation( namespace=self._namespace, workflow_id=workflow_id, ) - data_converter = self._data_converter.with_context(workflow_context) + data_converter = self._data_converter._with_contexts( + workflow_context, + StorageDriverStoreContext( + target=StorageDriverWorkflowInfo( + id=workflow_id, + run_id=act.run_id, + type=( + workflow.workflow_type + if workflow + else (init_job.workflow_type if init_job else None) + ), + namespace=self._namespace, + ), + ), + ) if workflow: data_converter = _CommandAwareDataConverter.create( instance=workflow.instance, @@ -313,6 +328,7 @@ async def _handle_activation( workflow = _RunningWorkflow( self._create_workflow_instance(act, init_job), workflow_id, + workflow_type=init_job.workflow_type, ) self._running_workflows[act.run_id] = workflow @@ -802,9 +818,15 @@ def _gen_tb_helper( class _RunningWorkflow: - def __init__(self, instance: WorkflowInstance, workflow_id: str): + def __init__( + self, + instance: WorkflowInstance, + workflow_id: str, + workflow_type: str | None = None, + ): self.instance = instance self.workflow_id = workflow_id + self.workflow_type = workflow_type self.deadlocked_activation_task: Awaitable | None = None self._deadlock_can_be_interrupted_lock = threading.Lock() self._deadlock_can_be_interrupted = False @@ -902,7 +924,10 @@ async def _encode_payload_sequence( async def _external_store_payload_sequence( self, payloads: Sequence[temporalio.api.common.v1.Payload] ) -> list[temporalio.api.common.v1.Payload]: - return await self._get_current_dc()._external_store_payload_sequence(payloads) + command_info = _command_aware_visitor.current_command_info.get() + store_ctx = self._ca_instance.get_external_store_context(command_info) + dc = self._get_current_dc()._with_store_context(store_ctx) + return await dc._external_store_payload_sequence(payloads) async def _external_retrieve_payload_sequence( self, payloads: Sequence[temporalio.api.common.v1.Payload] diff --git a/temporalio/worker/_workflow_instance.py b/temporalio/worker/_workflow_instance.py index 1bfa77c3c..36c7d0007 100644 --- a/temporalio/worker/_workflow_instance.py +++ b/temporalio/worker/_workflow_instance.py @@ -58,6 +58,7 @@ import temporalio.converter import temporalio.exceptions import temporalio.workflow +from temporalio.converter import StorageDriverStoreContext, StorageDriverWorkflowInfo from temporalio.service import __version__ from ..api.failure.v1.message_pb2 import Failure @@ -182,6 +183,21 @@ def get_serialization_context( """ raise NotImplementedError + @abstractmethod + def get_external_store_context( + self, + command_info: _command_aware_visitor.CommandInfo | None, + ) -> StorageDriverStoreContext: + """Return appropriate store context for external storage operations. + + Args: + command_info: Optional information identifying the associated command. + + Returns: + The store context associated with the command. + """ + raise NotImplementedError + def get_thread_id(self) -> int | None: """Return the thread identifier that this workflow is running on. @@ -1851,7 +1867,6 @@ def workflow_register_random_seed_callback( # These are in alphabetical order and all start with "_outbound_". def _outbound_continue_as_new(self, input: ContinueAsNewInput) -> NoReturn: - # Just throw raise _ContinueAsNewError(self, input) def _outbound_schedule_activity( @@ -2222,6 +2237,74 @@ def get_serialization_context( workflow_id=self._info.workflow_id, ) + def get_external_store_context( + self, + command_info: _command_aware_visitor.CommandInfo | None, + ) -> StorageDriverStoreContext: + # The current workflow is the default target for external store + # operations. For commands that target other workflows, those workflows + # are the target for that command's external store operation. For + # workflow activities, the target is the current workflow since the + # activity is bound to the lifetime of the current workflow, the + # activity run information is the same as the current workflow, and + # successfully completed activities are not involved in replay. + # Otherwise, the storage space for a given workflow would be disparate + # if stored under activity information. + current_wf = StorageDriverWorkflowInfo( + id=self._info.workflow_id, + run_id=self._info.run_id, + type=self._info.workflow_type, + namespace=self._info.namespace, + ) + + if command_info is None: + return StorageDriverStoreContext(target=current_wf) + + COMMAND_TYPE = temporalio.api.enums.v1.command_type_pb2.CommandType + + if ( + command_info.command_type + == COMMAND_TYPE.COMMAND_TYPE_START_CHILD_WORKFLOW_EXECUTION + and command_info.command_seq in self._pending_child_workflows + ): + child = self._pending_child_workflows[command_info.command_seq] + return StorageDriverStoreContext( + target=StorageDriverWorkflowInfo( + id=child._input.id, + type=child._input.workflow, + namespace=self._info.namespace, + ), + ) + + elif ( + command_info.command_type + == COMMAND_TYPE.COMMAND_TYPE_SIGNAL_EXTERNAL_WORKFLOW_EXECUTION + and command_info.command_seq in self._pending_external_signals + ): + _, target_id = self._pending_external_signals[command_info.command_seq] + return StorageDriverStoreContext( + target=StorageDriverWorkflowInfo( + id=target_id, namespace=self._info.namespace + ), + ) + + elif ( + command_info.command_type + == COMMAND_TYPE.COMMAND_TYPE_COMPLETE_WORKFLOW_EXECUTION + and self._info.parent is not None + and self._info.continued_run_id is None + ): + return StorageDriverStoreContext( + target=StorageDriverWorkflowInfo( + id=self._info.parent.workflow_id, + run_id=self._info.parent.run_id, + namespace=self._info.parent.namespace, + ), + ) + + else: + return StorageDriverStoreContext(target=current_wf) + def _instantiate_workflow_object(self) -> Any: if not self._workflow_input: raise RuntimeError("Expected workflow input. This is a Python SDK bug.") diff --git a/temporalio/worker/workflow_sandbox/_in_sandbox.py b/temporalio/worker/workflow_sandbox/_in_sandbox.py index eea8f6940..d18374899 100644 --- a/temporalio/worker/workflow_sandbox/_in_sandbox.py +++ b/temporalio/worker/workflow_sandbox/_in_sandbox.py @@ -13,6 +13,7 @@ import temporalio.converter import temporalio.worker._workflow_instance import temporalio.workflow +from temporalio.converter._extstore import StorageDriverStoreContext from temporalio.worker import _command_aware_visitor logger = logging.getLogger(__name__) @@ -88,3 +89,10 @@ def get_serialization_context( ) -> temporalio.converter.SerializationContext | None: """Get serialization context.""" return self.instance.get_serialization_context(command_info) + + def get_external_store_context( + self, + command_info: _command_aware_visitor.CommandInfo | None, + ) -> StorageDriverStoreContext: + """Get store context for external storage.""" + return self.instance.get_external_store_context(command_info) diff --git a/temporalio/worker/workflow_sandbox/_runner.py b/temporalio/worker/workflow_sandbox/_runner.py index 31514e33b..7605f3054 100644 --- a/temporalio/worker/workflow_sandbox/_runner.py +++ b/temporalio/worker/workflow_sandbox/_runner.py @@ -17,6 +17,7 @@ import temporalio.common import temporalio.converter import temporalio.workflow +from temporalio.converter._extstore import StorageDriverStoreContext from temporalio.worker import _command_aware_visitor from ...api.common.v1.message_pb2 import Payloads @@ -205,3 +206,22 @@ def get_serialization_context( return self.globals_and_locals.pop("__temporal_context", None) # type: ignore finally: self.importer.restriction_context.is_runtime = False + + def get_external_store_context( + self, + command_info: _command_aware_visitor.CommandInfo | None, + ) -> StorageDriverStoreContext: + # Forward call to the sandboxed instance + self.importer.restriction_context.is_runtime = True + try: + self._run_code( + "with __temporal_importer.applied():\n" + " __temporal_context = __temporal_in_sandbox.get_external_store_context(__temporal_command_info)\n", + __temporal_importer=self.importer, + __temporal_command_info=command_info, + ) + return self.globals_and_locals.pop( + "__temporal_context", StorageDriverStoreContext(target=None) + ) # type: ignore + finally: + self.importer.restriction_context.is_runtime = False diff --git a/tests/contrib/aws/s3driver/test_s3driver.py b/tests/contrib/aws/s3driver/test_s3driver.py index 46184c8b7..c389fe07c 100644 --- a/tests/contrib/aws/s3driver/test_s3driver.py +++ b/tests/contrib/aws/s3driver/test_s3driver.py @@ -27,12 +27,12 @@ S3StorageDriverClient, ) from temporalio.converter import ( - ActivitySerializationContext, JSONPlainPayloadConverter, + StorageDriverActivityInfo, StorageDriverClaim, StorageDriverRetrieveContext, StorageDriverStoreContext, - WorkflowSerializationContext, + StorageDriverWorkflowInfo, ) from tests.contrib.aws.s3driver.conftest import BUCKET @@ -51,34 +51,36 @@ def make_payload(value: str = "hello") -> Payload: def make_store_context( - serialization_context: WorkflowSerializationContext - | ActivitySerializationContext - | None = None, + target: StorageDriverActivityInfo | StorageDriverWorkflowInfo | None = None, ) -> StorageDriverStoreContext: - return StorageDriverStoreContext(serialization_context=serialization_context) + return StorageDriverStoreContext( + target=target, + ) def make_workflow_context( namespace: str = "my-namespace", workflow_id: str = "my-workflow", -) -> WorkflowSerializationContext: - return WorkflowSerializationContext(namespace=namespace, workflow_id=workflow_id) + workflow_type: str | None = None, + run_id: str | None = None, +) -> StorageDriverStoreContext: + return make_store_context( + target=StorageDriverWorkflowInfo( + id=workflow_id, type=workflow_type, run_id=run_id, namespace=namespace + ), + ) def make_activity_context( namespace: str = "my-namespace", activity_id: str | None = "my-activity", - workflow_id: str | None = None, - activity_task_queue: str | None = None, -) -> ActivitySerializationContext: - return ActivitySerializationContext( - namespace=namespace, - activity_id=activity_id, - activity_type=None, - activity_task_queue=activity_task_queue, - workflow_id=workflow_id, - workflow_type=None, - is_local=False, + activity_type: str | None = None, + run_id: str | None = None, +) -> StorageDriverStoreContext: + return make_store_context( + target=StorageDriverActivityInfo( + id=activity_id, type=activity_type, run_id=run_id, namespace=namespace + ), ) @@ -211,48 +213,70 @@ async def test_key_context_workflow( ) -> None: driver = S3StorageDriver(client=driver_client, bucket=BUCKET) payload = make_payload() - ctx = make_store_context( - make_workflow_context(namespace="ns1", workflow_id="wf1") - ) + ctx = make_workflow_context(namespace="ns1", workflow_id="wf1") [claim] = await driver.store(ctx, [payload]) expected_hash = hashlib.sha256(payload.SerializeToString()).hexdigest() - assert claim.claim_data["key"] == f"v0/ns/ns1/wfi/wf1/d/sha256/{expected_hash}" + assert ( + claim.claim_data["key"] + == f"v0/ns/ns1/wt/null/wi/wf1/ri/null/d/sha256/{expected_hash}" + ) - async def test_key_context_workflow_activity( + async def test_key_context_workflow_with_type_and_run_id( self, driver_client: S3StorageDriverClient ) -> None: - """workflow_id takes priority over activity_id in ActivitySerializationContext.""" driver = S3StorageDriver(client=driver_client, bucket=BUCKET) payload = make_payload() - ctx = make_store_context( - make_activity_context( - namespace="ns1", workflow_id="wf1", activity_id="act1" - ) + ctx = make_workflow_context( + namespace="ns1", + workflow_id="wf1", + workflow_type="MyWorkflow", + run_id="run-abc", ) [claim] = await driver.store(ctx, [payload]) expected_hash = hashlib.sha256(payload.SerializeToString()).hexdigest() - assert claim.claim_data["key"] == f"v0/ns/ns1/wfi/wf1/d/sha256/{expected_hash}" + assert ( + claim.claim_data["key"] + == f"v0/ns/ns1/wt/MyWorkflow/wi/wf1/ri/run-abc/d/sha256/{expected_hash}" + ) - async def test_key_context_standalone_activityt( + async def test_key_context_activity( self, driver_client: S3StorageDriverClient ) -> None: + """activity target uses activity key segment.""" driver = S3StorageDriver(client=driver_client, bucket=BUCKET) payload = make_payload() - ctx = make_store_context( - make_activity_context(namespace="ns1", activity_id="act1", workflow_id=None) + ctx = make_activity_context(namespace="ns1", activity_id="act1") + [claim] = await driver.store(ctx, [payload]) + expected_hash = hashlib.sha256(payload.SerializeToString()).hexdigest() + assert ( + claim.claim_data["key"] + == f"v0/ns/ns1/at/null/ai/act1/ri/null/d/sha256/{expected_hash}" + ) + + async def test_key_context_activity_with_type_and_run_id( + self, driver_client: S3StorageDriverClient + ) -> None: + driver = S3StorageDriver(client=driver_client, bucket=BUCKET) + payload = make_payload() + ctx = make_activity_context( + namespace="ns1", + activity_id="act1", + activity_type="MyActivity", + run_id="run-abc", ) [claim] = await driver.store(ctx, [payload]) expected_hash = hashlib.sha256(payload.SerializeToString()).hexdigest() - assert claim.claim_data["key"] == f"v0/ns/ns1/aci/act1/d/sha256/{expected_hash}" + assert ( + claim.claim_data["key"] + == f"v0/ns/ns1/at/MyActivity/ai/act1/ri/run-abc/d/sha256/{expected_hash}" + ) async def test_key_preserves_case( self, driver_client: S3StorageDriverClient ) -> None: driver = S3StorageDriver(client=driver_client, bucket=BUCKET) payload = make_payload() - ctx = make_store_context( - make_workflow_context(namespace="MyNamespace", workflow_id="MyWorkflow") - ) + ctx = make_workflow_context(namespace="MyNamespace", workflow_id="MyWorkflow") [claim] = await driver.store(ctx, [payload]) key = claim.claim_data["key"] assert "MyNamespace" in key @@ -263,14 +287,12 @@ async def test_key_urlencodes_workflow_id_with_slashes( ) -> None: driver = S3StorageDriver(client=driver_client, bucket=BUCKET) payload = make_payload() - ctx = make_store_context( - make_workflow_context(namespace="ns1", workflow_id="order/123/v2") - ) + ctx = make_workflow_context(namespace="ns1", workflow_id="order/123/v2") [claim] = await driver.store(ctx, [payload]) expected_hash = hashlib.sha256(payload.SerializeToString()).hexdigest() assert ( claim.claim_data["key"] - == f"v0/ns/ns1/wfi/order%2F123%2Fv2/d/sha256/{expected_hash}" + == f"v0/ns/ns1/wt/null/wi/order%2F123%2Fv2/ri/null/d/sha256/{expected_hash}" ) async def test_key_urlencodes_workflow_id_with_special_chars( @@ -278,14 +300,12 @@ async def test_key_urlencodes_workflow_id_with_special_chars( ) -> None: driver = S3StorageDriver(client=driver_client, bucket=BUCKET) payload = make_payload() - ctx = make_store_context( - make_workflow_context(namespace="ns1", workflow_id="wf#1 &foo=bar") - ) + ctx = make_workflow_context(namespace="ns1", workflow_id="wf#1 &foo=bar") [claim] = await driver.store(ctx, [payload]) expected_hash = hashlib.sha256(payload.SerializeToString()).hexdigest() assert ( claim.claim_data["key"] - == f"v0/ns/ns1/wfi/wf%231%20%26foo%3Dbar/d/sha256/{expected_hash}" + == f"v0/ns/ns1/wt/null/wi/wf%231%20%26foo%3Dbar/ri/null/d/sha256/{expected_hash}" ) async def test_key_urlencodes_activity_id( @@ -293,16 +313,12 @@ async def test_key_urlencodes_activity_id( ) -> None: driver = S3StorageDriver(client=driver_client, bucket=BUCKET) payload = make_payload() - ctx = make_store_context( - make_activity_context( - namespace="ns1", activity_id="act/1#2", workflow_id=None - ) - ) + ctx = make_activity_context(namespace="ns1", activity_id="act/1#2") [claim] = await driver.store(ctx, [payload]) expected_hash = hashlib.sha256(payload.SerializeToString()).hexdigest() assert ( claim.claim_data["key"] - == f"v0/ns/ns1/aci/act%2F1%232/d/sha256/{expected_hash}" + == f"v0/ns/ns1/at/null/ai/act%2F1%232/ri/null/d/sha256/{expected_hash}" ) async def test_key_urlencodes_namespace( @@ -310,14 +326,12 @@ async def test_key_urlencodes_namespace( ) -> None: driver = S3StorageDriver(client=driver_client, bucket=BUCKET) payload = make_payload() - ctx = make_store_context( - make_workflow_context(namespace="my/ns#1", workflow_id="wf1") - ) + ctx = make_workflow_context(namespace="my/ns#1", workflow_id="wf1") [claim] = await driver.store(ctx, [payload]) expected_hash = hashlib.sha256(payload.SerializeToString()).hexdigest() assert ( claim.claim_data["key"] - == f"v0/ns/my%2Fns%231/wfi/wf1/d/sha256/{expected_hash}" + == f"v0/ns/my%2Fns%231/wt/null/wi/wf1/ri/null/d/sha256/{expected_hash}" ) async def test_key_urlencoded_roundtrip( @@ -326,9 +340,7 @@ async def test_key_urlencoded_roundtrip( """Payloads stored with special-char IDs can be retrieved correctly.""" driver = S3StorageDriver(client=driver_client, bucket=BUCKET) payload = make_payload("special-char-roundtrip") - ctx = make_store_context( - make_workflow_context(namespace="ns/1", workflow_id="wf/2#3") - ) + ctx = make_workflow_context(namespace="ns/1", workflow_id="wf/2#3") [claim] = await driver.store(ctx, [payload]) [retrieved] = await driver.retrieve(StorageDriverRetrieveContext(), [claim]) assert retrieved == payload @@ -528,45 +540,42 @@ def counting_selector(_ctx: StorageDriverStoreContext, _p: Payload) -> str: ) assert call_count == 3 - async def test_selector_routes_by_activity_task_queue( + async def test_selector_routes_by_activity_type( self, aioboto3_client: S3Client, driver_client: S3StorageDriverClient ) -> None: - """bucket callable can route payloads to different buckets by activity task queue.""" - bucket_a = "bucket-queue-a" - bucket_b = "bucket-queue-b" + """bucket callable can route payloads to different buckets by activity type.""" + bucket_a = "bucket-type-a" + bucket_b = "bucket-type-b" await aioboto3_client.create_bucket(Bucket=bucket_a) await aioboto3_client.create_bucket(Bucket=bucket_b) - queue_buckets = {"queue-a": bucket_a, "queue-b": bucket_b} + type_buckets = {"type-a": bucket_a, "type-b": bucket_b} - def queue_selector(ctx: StorageDriverStoreContext, p: Payload) -> str: + def type_selector(ctx: StorageDriverStoreContext, p: Payload) -> str: del p - if isinstance(ctx.serialization_context, ActivitySerializationContext): - queue = ctx.serialization_context.activity_task_queue - if queue and queue in queue_buckets: - return queue_buckets[queue] + act = ( + ctx.target + if isinstance(ctx.target, StorageDriverActivityInfo) + else None + ) + if act and act.type and act.type in type_buckets: + return type_buckets[act.type] return BUCKET - driver = S3StorageDriver(client=driver_client, bucket=queue_selector) + driver = S3StorageDriver(client=driver_client, bucket=type_selector) - ctx_a = make_store_context( - make_activity_context( - namespace="ns1", - activity_id="act1", - workflow_id="wf1", - activity_task_queue="queue-a", - ) + ctx_a = make_activity_context( + namespace="ns1", + activity_id="act1", + activity_type="type-a", ) [claim_a] = await driver.store(ctx_a, [make_payload("payload-a")]) assert claim_a.claim_data["bucket"] == bucket_a - ctx_b = make_store_context( - make_activity_context( - namespace="ns1", - activity_id="act2", - workflow_id="wf1", - activity_task_queue="queue-b", - ) + ctx_b = make_activity_context( + namespace="ns1", + activity_id="act2", + activity_type="type-b", ) [claim_b] = await driver.store(ctx_b, [make_payload("payload-b")]) assert claim_b.claim_data["bucket"] == bucket_b @@ -581,7 +590,7 @@ def capturing_selector(ctx: StorageDriverStoreContext, p: Payload) -> str: return BUCKET payload = make_payload() - store_ctx = make_store_context(make_workflow_context()) + store_ctx = make_workflow_context() driver = S3StorageDriver(client=driver_client, bucket=capturing_selector) await driver.store(store_ctx, [payload]) diff --git a/tests/contrib/aws/s3driver/test_s3driver_worker.py b/tests/contrib/aws/s3driver/test_s3driver_worker.py index 87ab73736..e25be5fbf 100644 --- a/tests/contrib/aws/s3driver/test_s3driver_worker.py +++ b/tests/contrib/aws/s3driver/test_s3driver_worker.py @@ -107,8 +107,17 @@ async def test_s3_driver_workflow_input_key( execution_timeout=timedelta(seconds=5), ) keys = await _list_keys(aioboto3_client) - assert len(keys) == 1 - assert f"/ns/default/wfi/{workflow_id}/d/sha256/" in keys[0] + + # Client stores workflow input with ri=null (run ID not yet assigned); + # worker stores activity input with ri=run_id — same bytes, two S3 objects. + assert len(keys) == 2 + assert all( + f"/ns/default/wt/LargeIOWorkflow/wi/{workflow_id}/ri/" in k for k in keys + ) + # Client-side store: ri=null because run ID is not yet known. + assert sum(1 for k in keys if "/ri/null/" in k) == 1 + # Worker-side store: ri=run_id, assigned by the server. + assert sum(1 for k in keys if "/ri/null/" not in k) == 1 async def test_s3_driver_workflow_output_key( @@ -127,8 +136,11 @@ async def test_s3_driver_workflow_output_key( ) assert result == LARGE keys = await _list_keys(aioboto3_client) + # Activity result and workflow result dedup to same key assert len(keys) == 1 - assert f"/ns/default/wfi/{workflow_id}/d/sha256/" in keys[0] + assert f"/ns/default/wt/LargeIOWorkflow/wi/{workflow_id}/ri/" in keys[0] + # Run ID is known for both activity completion and workflow completion + assert "/ri/null/" not in keys[0] async def test_s3_driver_workflow_activity_input_key( @@ -146,11 +158,14 @@ async def test_s3_driver_workflow_activity_input_key( execution_timeout=timedelta(seconds=5), ) keys = await _list_keys(aioboto3_client) - assert len(keys) == 1 - assert f"/ns/default/wfi/{workflow_id}/" in keys[0] - assert ( - "/aci/" not in keys[0] - ), "Activity input should use workflow_id, not activity_id" + # Client start (ri=null) + worker schedules activity (ri=run_id) — same bytes, two objects. + assert len(keys) == 2 + # Both keys are under the workflow wi/ri prefix, not the activity. + assert all( + f"/ns/default/wt/LargeIOWorkflow/wi/{workflow_id}/ri/" in k for k in keys + ) + # Activity input is keyed under the scheduling workflow, not the activity. + assert all("/ai/" not in k for k in keys) async def test_s3_driver_workflow_activity_output_key( @@ -168,8 +183,63 @@ async def test_s3_driver_workflow_activity_output_key( execution_timeout=timedelta(seconds=5), ) keys = await _list_keys(aioboto3_client) + # Activity result and workflow result are both LARGE so they deduplicate to one object. assert len(keys) == 1 - assert f"/ns/default/wfi/{workflow_id}/d/sha256/" in keys[0] + assert f"/ns/default/wt/LargeIOWorkflow/wi/{workflow_id}/ri/" in keys[0] + # ri=run_id for both stores (run ID is known by the time the activity completes). + assert "/ri/null/" not in keys[0] + + +async def test_s3_driver_standalone_activity_input_key( + env: WorkflowEnvironment, tmprl_client: Client, aioboto3_client: S3Client +) -> None: + if env.supports_time_skipping: + pytest.skip( + "Java test server: https://github.com/temporalio/sdk-java/issues/2741" + ) + activity_id = str(uuid.uuid4()) + task_queue = str(uuid.uuid4()) + async with new_worker( + tmprl_client, activities=[large_io_activity], task_queue=task_queue + ): + await tmprl_client.execute_activity( + large_io_activity, + LARGE, + id=activity_id, + task_queue=task_queue, + start_to_close_timeout=timedelta(seconds=5), + ) + keys = await _list_keys(aioboto3_client) + # Input and output are the same LARGE bytes, so they deduplicate to one key. + assert len(keys) == 1 + # Keyed under the activity, not a workflow. + assert f"/ns/default/at/large_io_activity/ai/{activity_id}/ri/null/" in keys[0] + assert "/wt/" not in keys[0] + + +async def test_s3_driver_standalone_activity_output_key( + env: WorkflowEnvironment, tmprl_client: Client, aioboto3_client: S3Client +) -> None: + if env.supports_time_skipping: + pytest.skip( + "Java test server: https://github.com/temporalio/sdk-java/issues/2741" + ) + activity_id = str(uuid.uuid4()) + task_queue = str(uuid.uuid4()) + async with new_worker( + tmprl_client, activities=[large_output_activity], task_queue=task_queue + ): + await tmprl_client.execute_activity( + large_output_activity, + id=activity_id, + task_queue=task_queue, + start_to_close_timeout=timedelta(seconds=5), + ) + keys = await _list_keys(aioboto3_client) + # Only the output is large; keyed under the activity. + assert len(keys) == 1 + assert f"/ns/default/at/large_output_activity/ai/{activity_id}/ri/null/" in keys[0] + assert "/wt/" not in keys[0] async def test_s3_driver_signal_arg_key( @@ -186,8 +256,12 @@ async def test_s3_driver_signal_arg_key( await handle.signal(SignalQueryUpdateWorkflow.finish, LARGE) await handle.result() keys = await _list_keys(aioboto3_client) - assert len(keys) == 1 - assert f"/ns/default/wfi/{workflow_id}/d/sha256/" in keys[0] + # Signal arg + workflow result — two distinct keys (different wt and ri). + assert len(keys) == 2 + # Signal arg: client stores with wt=null (type not known) and ri=null. + assert any(f"/wt/null/wi/{workflow_id}/ri/null/" in k for k in keys) + # Workflow result: worker stores with real type and ri=run_id. + assert any(f"/wt/SignalQueryUpdateWorkflow/wi/{workflow_id}/" in k for k in keys) async def test_s3_driver_query_result_key( @@ -206,8 +280,12 @@ async def test_s3_driver_query_result_key( await handle.signal(SignalQueryUpdateWorkflow.finish, "done") await handle.result() keys = await _list_keys(aioboto3_client) - assert len(keys) == 1 - assert f"/ns/default/wfi/{workflow_id}/d/sha256/" in keys[0] + # Query arg + (query result deduplicated with workflow result) — two distinct keys. + assert len(keys) == 2 + # Query arg: client stores with wt=null (type not known) and ri=null. + assert any(f"/wt/null/wi/{workflow_id}/ri/null/" in k for k in keys) + # Query result and workflow result are both LARGE and deduplicate to one key with ri=run_id. + assert any(f"/wt/SignalQueryUpdateWorkflow/wi/{workflow_id}/" in k for k in keys) async def test_s3_driver_update_result_key( @@ -226,8 +304,12 @@ async def test_s3_driver_update_result_key( await handle.signal(SignalQueryUpdateWorkflow.finish, "done") await handle.result() keys = await _list_keys(aioboto3_client) - assert len(keys) == 1 - assert f"/ns/default/wfi/{workflow_id}/d/sha256/" in keys[0] + # Update arg + (update result deduplicated with workflow result) — two distinct keys. + assert len(keys) == 2 + # Update arg: client stores with wt=null (type not known) and ri=null. + assert any(f"/wt/null/wi/{workflow_id}/ri/null/" in k for k in keys) + # Update result and workflow result are both LARGE and deduplicate to one key with ri=run_id. + assert any(f"/wt/SignalQueryUpdateWorkflow/wi/{workflow_id}/" in k for k in keys) async def test_s3_driver_child_workflow_input_key( @@ -244,9 +326,11 @@ async def test_s3_driver_child_workflow_input_key( execution_timeout=timedelta(seconds=5), ) keys = await _list_keys(aioboto3_client) - assert len(keys) == 1 child_workflow_id = f"{workflow_id}-child" - assert f"/ns/default/wfi/{child_workflow_id}/d/sha256/" in keys[0] + # Child input is the only large payload — stored under the child's wi/ri. + assert len(keys) == 1 + # Keyed under the child: child input is stored in the child's context. + assert f"/ns/default/wt/ChildWorkflow/wi/{child_workflow_id}/ri/" in keys[0] async def test_s3_driver_identified_casing( @@ -264,10 +348,11 @@ async def test_s3_driver_identified_casing( execution_timeout=timedelta(seconds=5), ) keys = await _list_keys(aioboto3_client) - assert len(keys) == 1 - assert "/ns/default/" in keys[0], "Namespace segment should be present" - assert ( - f"/wfi/{workflow_id}/" in keys[0] + # Client start (ri=null) + worker stores (ri=run_id) — two objects. + assert len(keys) == 2 + # Workflow ID is percent-encoded but casing is preserved verbatim. + assert all( + f"/ns/default/wt/LargeIOWorkflow/wi/{workflow_id}/ri/" in k for k in keys ), "Workflow ID should preserve original case in the key" @@ -290,9 +375,14 @@ async def test_s3_driver_content_dedup( execution_timeout=timedelta(seconds=5), ) keys = await _list_keys(aioboto3_client) + # Two distinct content hashes (LARGE from download, LARGE_2 from extract) → two keys. assert len(keys) == 2 - assert f"/ns/default/wfi/{workflow_id}/d/sha256/" in keys[0] - assert f"/ns/default/wfi/{workflow_id}/d/sha256/" in keys[1] + # Both are under the same workflow wi/ri prefix despite crossing activity boundaries. + assert all( + f"/ns/default/wt/DocumentIngestionWorkflow/wi/{workflow_id}/ri/" in k + for k in keys + ) + # The two keys differ by content hash only. assert keys[0] != keys[1] @@ -301,8 +391,7 @@ async def test_s3_driver_single_workflow_same_key_namespace( ) -> None: """A training job started with a large config, injected with large override parameters mid-run, and polled for large metrics — all produce S3 keys - under the same workflow ID prefix, regardless of which primitive carried - the payload.""" + containing the same workflow ID.""" workflow_id = str(uuid.uuid4()) async with new_worker(tmprl_client, ModelTrainingWorkflow) as worker: handle = await tmprl_client.start_workflow( @@ -320,19 +409,19 @@ async def test_s3_driver_single_workflow_same_key_namespace( await handle.signal(ModelTrainingWorkflow.complete) await handle.result() keys = await _list_keys(aioboto3_client) - # LARGE (input + signal arg) and LARGE_2 (metrics result) deduplicate to - # two distinct keys — both anchored under the same workflow ID prefix. - assert len(keys) == 2 - assert all(f"/ns/default/wfi/{workflow_id}/" in key for key in keys) + # Four distinct keys: client start, signal arg, update result, workflow result. + assert len(keys) == 4 + # All keys are anchored under the same workflow ID regardless of which primitive carried the payload. + assert all(f"/wi/{workflow_id}/" in k for k in keys) async def test_s3_driver_parent_child_independent_key_namespaces( tmprl_client: Client, aioboto3_client: S3Client ) -> None: - """An order fulfillment workflow spawns a child payment processor, passes it - a large order payload, and returns the child's large payment confirmation. - Each workflow accumulates S3 keys under its own workflow ID prefix — - parent and child key namespaces are fully independent.""" + """An order fulfillment workflow spawns a child payment processor and passes + it a large order payload. Child input is keyed under the parent (it lives in + the parent's history); child output is keyed under the parent (for lifecycle + resilience — the child result lives in the parent's completion history).""" workflow_id = str(uuid.uuid4()) payment_id = f"{workflow_id}-payment" async with new_worker( @@ -346,16 +435,15 @@ async def test_s3_driver_parent_child_independent_key_namespaces( execution_timeout=timedelta(seconds=5), ) keys = await _list_keys(aioboto3_client) - parent_prefix = f"/ns/default/wfi/{workflow_id}/d/" - child_prefix = f"/ns/default/wfi/{payment_id}/d/" - parent_keys = [k for k in keys if parent_prefix in k] - child_keys = [k for k in keys if child_prefix in k] - # The parent stores its input (LARGE) and the child's result propagated - # back (LARGE_2) under the parent's prefix → 2 keys. - # The child stores its input (LARGE) and its result (LARGE_2) under the - # child's prefix → 2 keys. - assert len(parent_keys) == 2 - assert len(child_keys) == 2 + parent_keys = [k for k in keys if f"/wi/{workflow_id}/" in k] + child_keys = [k for k in keys if f"/wi/{payment_id}/" in k] + # Parent accumulates 3 keys: + # 1. Client start stored in parent's key space (ri=null) + # 2. Child result stored in parent's key space + # 3. Parent's own workflow result + assert len(parent_keys) == 3 + # Child accumulates 1 key: its input from the parent + assert len(child_keys) == 1 async def test_s3_store_failure_surfaces_in_workflow_history( @@ -400,7 +488,6 @@ async def test_s3_store_failure_surfaces_in_workflow_history( large_payload = JSONPlainPayloadConverter().to_payload(LARGE) assert large_payload is not None expected_hash = hashlib.sha256(large_payload.SerializeToString()).hexdigest() - expected_key = f"v0/ns/default/wfi/{workflow_id}/d/sha256/{expected_hash}" assert isinstance(exc_info.value, WorkflowFailureError) activity_error = exc_info.value.__cause__ @@ -408,7 +495,8 @@ async def test_s3_store_failure_surfaces_in_workflow_history( app_error = activity_error.__cause__ assert isinstance(app_error, ApplicationError) assert app_error.type == "RuntimeError" - assert ( - app_error.message - == f"S3StorageDriver store failed [bucket={bad_bucket}, key={expected_key}]" - ) + # Key includes run_id which is only known at runtime; use substring checks. + msg = app_error.message + assert f"S3StorageDriver store failed [bucket={bad_bucket}, key=" in msg + assert f"/wt/LargeOutputNoRetryWorkflow/wi/{workflow_id}/ri/" in msg + assert f"/d/sha256/{expected_hash}]" in msg diff --git a/tests/test_serialization_context.py b/tests/test_serialization_context.py index 580926b4b..d3ce022f5 100644 --- a/tests/test_serialization_context.py +++ b/tests/test_serialization_context.py @@ -40,15 +40,10 @@ DefaultFailureConverter, DefaultPayloadConverter, EncodingPayloadConverter, - ExternalStorage, JSONPlainPayloadConverter, PayloadCodec, PayloadConverter, SerializationContext, - StorageDriver, - StorageDriverClaim, - StorageDriverRetrieveContext, - StorageDriverStoreContext, WithSerializationContext, WorkflowSerializationContext, ) @@ -1919,84 +1914,3 @@ async def test_user_customization_of_default_payload_converter( id=wf_id, task_queue=task_queue, ) - - -# Child workflow external storage context test - - -class ContextTrackingStorageDriver(StorageDriver): - """In-memory driver that records the serialization context on each store/retrieve.""" - - def __init__(self) -> None: - self._storage: dict[str, bytes] = {} - self.store_contexts: list[SerializationContext | None] = [] - - def name(self) -> str: - return "context-tracking" - - async def store( - self, - context: StorageDriverStoreContext, - payloads: Sequence[temporalio.api.common.v1.Payload], - ) -> list[StorageDriverClaim]: - self.store_contexts.append(context.serialization_context) - claims: list[StorageDriverClaim] = [] - for payload in payloads: - key = f"payload-{len(self._storage)}" - self._storage[key] = payload.SerializeToString() - claims.append(StorageDriverClaim(claim_data={"key": key})) - return claims - - async def retrieve( - self, - context: StorageDriverRetrieveContext, - claims: Sequence[StorageDriverClaim], - ) -> list[temporalio.api.common.v1.Payload]: - results: list[temporalio.api.common.v1.Payload] = [] - for claim in claims: - payload = temporalio.api.common.v1.Payload() - payload.ParseFromString(self._storage[claim.claim_data["key"]]) - results.append(payload) - return results - - -async def test_child_workflow_external_storage_with_context(client: Client): - """External storage should receive the child workflow's context, not the parent's.""" - workflow_id = str(uuid.uuid4()) - child_workflow_id = f"{workflow_id}-child" - task_queue = str(uuid.uuid4()) - - driver = ContextTrackingStorageDriver() - config = client.config() - config["data_converter"] = dataclasses.replace( - DataConverter.default, - external_storage=ExternalStorage( - drivers=[driver], - payload_size_threshold=0, - ), - ) - client = Client(**config) - - async with Worker( - client, - task_queue=task_queue, - workflows=[ChildWorkflowCodecTestWorkflow, EchoWorkflow], - workflow_runner=UnsandboxedWorkflowRunner(), - ): - await client.execute_workflow( - ChildWorkflowCodecTestWorkflow.run, - TraceData(), - id=workflow_id, - task_queue=task_queue, - ) - - child_context = WorkflowSerializationContext( - namespace=client.namespace, - workflow_id=child_workflow_id, - ) - # store_contexts[0]: parent input encode → parent context - # store_contexts[1]: child workflow input encode → child context - # store_contexts[2]: child workflow result encode → child context - # store_contexts[3]: parent result encode → parent context - child_context_count = sum(1 for c in driver.store_contexts if c == child_context) - assert child_context_count == 2 diff --git a/tests/worker/test_extstore.py b/tests/worker/test_extstore.py index 8e2ee763a..8b47b3f0c 100644 --- a/tests/worker/test_extstore.py +++ b/tests/worker/test_extstore.py @@ -11,6 +11,7 @@ import temporalio import temporalio.bridge.client import temporalio.bridge.worker +import temporalio.client import temporalio.converter import temporalio.worker._workflow from temporalio import activity, workflow @@ -19,9 +20,12 @@ from temporalio.common import RetryPolicy from temporalio.converter import ( ExternalStorage, + StorageDriver, + StorageDriverActivityInfo, StorageDriverClaim, StorageDriverRetrieveContext, StorageDriverStoreContext, + StorageDriverWorkflowInfo, StorageWarning, ) from temporalio.exceptions import ActivityError, ApplicationError @@ -859,3 +863,543 @@ async def test_tmprl1104_with_extstore_download_and_upload( assert getattr(records[1], "payload_upload_count") == 1 assert getattr(records[1], "payload_upload_size") == expected_output_size assert getattr(records[1], "payload_upload_duration") > timedelta(0) + + +# --------------------------------------------------------------------------- +# Store-metadata context tests +# --------------------------------------------------------------------------- + + +class ContextTrackingStorageDriver(StorageDriver): + """In-memory driver that records the store context on each store/retrieve.""" + + def __init__(self) -> None: + self._storage: dict[str, bytes] = {} + self.store_contexts: list[StorageDriverStoreContext] = [] + + def name(self) -> str: + return "context-tracking" + + async def store( + self, + context: StorageDriverStoreContext, + payloads: Sequence[Payload], + ) -> list[StorageDriverClaim]: + self.store_contexts.append(context) + claims: list[StorageDriverClaim] = [] + for payload in payloads: + key = f"payload-{len(self._storage)}" + self._storage[key] = payload.SerializeToString() + claims.append(StorageDriverClaim(claim_data={"key": key})) + return claims + + async def retrieve( + self, + context: StorageDriverRetrieveContext, + claims: Sequence[StorageDriverClaim], + ) -> list[Payload]: + results: list[Payload] = [] + for claim in claims: + payload = Payload() + payload.ParseFromString(self._storage[claim.claim_data["key"]]) + results.append(payload) + return results + + +@workflow.defn +class SignalWaitWorkflow: + def __init__(self) -> None: + self._signal_data: str | None = None + + @workflow.run + async def run(self, _arg: str) -> str: + await workflow.wait_condition(lambda: self._signal_data is not None) + return self._signal_data # type: ignore + + @workflow.signal + async def my_signal(self, data: str) -> None: + self._signal_data = data + + +@workflow.defn +class EchoWorkflow: + @workflow.run + async def run(self, data: str) -> str: + return data + + +@workflow.defn +class ChildWorkflowStoreMetadataTestWorkflow: + @workflow.run + async def run(self, data: str) -> str: + return await workflow.execute_child_workflow( + EchoWorkflow.run, + data, + id=f"{workflow.info().workflow_id}-child", + ) + + +async def _make_tracking_client( + env: WorkflowEnvironment, +) -> tuple[Client, ContextTrackingStorageDriver]: + driver = ContextTrackingStorageDriver() + client = await Client.connect( + env.client.service_client.config.target_host, + namespace=env.client.namespace, + data_converter=dataclasses.replace( + temporalio.converter.default(), + external_storage=ExternalStorage( + drivers=[driver], + payload_size_threshold=0, + ), + ), + ) + return client, driver + + +async def test_store_metadata_start_workflow(env: WorkflowEnvironment) -> None: + """start_workflow should set workflow id and type on store context.""" + client, driver = await _make_tracking_client(env) + workflow_id = str(uuid.uuid4()) + + async with new_worker(client, EchoWorkflow) as worker: + await client.execute_workflow( + EchoWorkflow.run, + "hello", + id=workflow_id, + task_queue=worker.task_queue, + ) + + assert len(driver.store_contexts) == 2 + + # [0] Workflow input arg + client_ctx = driver.store_contexts[0] + assert isinstance(client_ctx.target, StorageDriverWorkflowInfo) + assert client_ctx.target.namespace == client.namespace + assert client_ctx.target.id == workflow_id + assert client_ctx.target.type == "EchoWorkflow" + assert client_ctx.target.run_id is None + + # [1] Workflow result + worker_ctx = driver.store_contexts[1] + assert isinstance(worker_ctx.target, StorageDriverWorkflowInfo) + assert worker_ctx.target.namespace == client.namespace + assert worker_ctx.target.id == workflow_id + assert worker_ctx.target.type == "EchoWorkflow" + assert worker_ctx.target.run_id is not None + + +async def test_store_metadata_signal_with_start(env: WorkflowEnvironment) -> None: + """signal_with_start should set workflow metadata for signal arg encoding.""" + client, driver = await _make_tracking_client(env) + workflow_id = str(uuid.uuid4()) + + async with new_worker(client, SignalWaitWorkflow) as worker: + handle = await client.start_workflow( + SignalWaitWorkflow.run, + "hello", + id=workflow_id, + task_queue=worker.task_queue, + start_signal="my_signal", + start_signal_args=["signal-data"], + ) + await handle.result() + + assert len(driver.store_contexts) == 3 + + # [0] Workflow input arg + input_ctx = driver.store_contexts[0] + assert isinstance(input_ctx.target, StorageDriverWorkflowInfo) + assert input_ctx.target.id == workflow_id + assert input_ctx.target.type == "SignalWaitWorkflow" + assert input_ctx.target.run_id is None + + # [1] Signal arg + signal_ctx = driver.store_contexts[1] + assert isinstance(signal_ctx.target, StorageDriverWorkflowInfo) + assert signal_ctx.target.id == workflow_id + assert signal_ctx.target.type == "SignalWaitWorkflow" + assert signal_ctx.target.run_id is None + + # [2] Workflow result + result_ctx = driver.store_contexts[2] + assert isinstance(result_ctx.target, StorageDriverWorkflowInfo) + assert result_ctx.target.id == workflow_id + assert result_ctx.target.type == "SignalWaitWorkflow" + assert result_ctx.target.run_id is not None + + +async def test_store_metadata_signal_workflow(env: WorkflowEnvironment) -> None: + """signal_workflow should set workflow id on store context.""" + client, driver = await _make_tracking_client(env) + workflow_id = str(uuid.uuid4()) + + async with new_worker(client, SignalWaitWorkflow) as worker: + handle = await client.start_workflow( + SignalWaitWorkflow.run, + "hello", + id=workflow_id, + task_queue=worker.task_queue, + ) + # Signal separately (not signal-with-start) + await handle.signal(SignalWaitWorkflow.my_signal, "signal-data") + await handle.result() + + assert len(driver.store_contexts) == 3 + + # [0] Client starts workflow + start_ctx = driver.store_contexts[0] + assert isinstance(start_ctx.target, StorageDriverWorkflowInfo) + assert start_ctx.target.id == workflow_id + assert start_ctx.target.type == "SignalWaitWorkflow" + assert start_ctx.target.run_id is None + + # [1] Client sends signal: type and run_id are unknown at signal time + signal_ctx = driver.store_contexts[1] + assert isinstance(signal_ctx.target, StorageDriverWorkflowInfo) + assert signal_ctx.target.id == workflow_id + assert signal_ctx.target.type is None + assert signal_ctx.target.run_id is None + + # [2] Workflow worker returns result + result_ctx = driver.store_contexts[2] + assert isinstance(result_ctx.target, StorageDriverWorkflowInfo) + assert result_ctx.target.id == workflow_id + assert result_ctx.target.type == "SignalWaitWorkflow" + assert result_ctx.target.run_id is not None + + +async def test_store_metadata_schedule_action(env: WorkflowEnvironment) -> None: + """Schedule action _to_proto should set workflow metadata.""" + if env.supports_time_skipping: + pytest.skip("Java test server doesn't support schedules") + client, driver = await _make_tracking_client(env) + task_queue = str(uuid.uuid4()) + schedule_id = f"sched-{uuid.uuid4()}" + + try: + await client.create_schedule( + schedule_id, + temporalio.client.Schedule( + action=temporalio.client.ScheduleActionStartWorkflow( + EchoWorkflow.run, + "hello", + id=f"wf-{schedule_id}", + task_queue=task_queue, + ), + spec=temporalio.client.ScheduleSpec(), + ), + ) + + assert len(driver.store_contexts) == 1 + + # [0] Client encodes workflow args when creating the schedule action + ctx = driver.store_contexts[0] + assert isinstance(ctx.target, StorageDriverWorkflowInfo) + assert ctx.target.namespace == client.namespace + assert ctx.target.id == f"wf-{schedule_id}" + assert ctx.target.type == "EchoWorkflow" + assert ctx.target.run_id is None + finally: + try: + handle = client.get_schedule_handle(schedule_id) + await handle.delete() + except Exception: + pass + + +async def test_store_metadata_child_workflow(env: WorkflowEnvironment) -> None: + """External storage should receive the child workflow as the target when scheduling.""" + client, driver = await _make_tracking_client(env) + workflow_id = f"workflow-{uuid.uuid4()}" + child_workflow_id = f"{workflow_id}-child" + + async with new_worker( + client, + ChildWorkflowStoreMetadataTestWorkflow, + EchoWorkflow, + ) as worker: + await client.execute_workflow( + ChildWorkflowStoreMetadataTestWorkflow.run, + "hello", + id=workflow_id, + task_queue=worker.task_queue, + ) + + assert len(driver.store_contexts) == 4 + + # [0] Client starts parent workflow + client_ctx = driver.store_contexts[0] + assert isinstance(client_ctx.target, StorageDriverWorkflowInfo) + assert client_ctx.target.id == workflow_id + assert client_ctx.target.type == "ChildWorkflowStoreMetadataTestWorkflow" + assert client_ctx.target.run_id is None + + # [1] Parent schedules child: target = child workflow + start_child_ctx = driver.store_contexts[1] + assert isinstance(start_child_ctx.target, StorageDriverWorkflowInfo) + assert start_child_ctx.target.id == child_workflow_id + assert start_child_ctx.target.type == "EchoWorkflow" + assert start_child_ctx.target.run_id is None + + # [2] Child returns result: target = parent workflow (child results are + # stored in the parent's key space so they remain accessible during replay) + child_result_ctx = driver.store_contexts[2] + assert isinstance(child_result_ctx.target, StorageDriverWorkflowInfo) + assert child_result_ctx.target.id == workflow_id + # ParentInfo does not carry workflow type + assert child_result_ctx.target.type is None + assert child_result_ctx.target.run_id is not None + + # [3] Parent returns result: target = parent (current execution) + parent_result_ctx = driver.store_contexts[3] + assert isinstance(parent_result_ctx.target, StorageDriverWorkflowInfo) + assert parent_result_ctx.target.id == workflow_id + assert parent_result_ctx.target.type == "ChildWorkflowStoreMetadataTestWorkflow" + assert parent_result_ctx.target.run_id is not None + + +# Workflow definitions for gap tests + + +@activity.defn +async def echo_activity(input: str) -> str: + """Simple activity that returns its input.""" + return input + + +@workflow.defn +class ActivityScheduleMetadataWorkflow: + """Workflow that schedules an activity to test activity metadata on the store context.""" + + @workflow.run + async def run(self, data: str) -> str: + return await workflow.execute_activity( + echo_activity, + data, + activity_id="my-activity-id", + schedule_to_close_timeout=timedelta(seconds=10), + ) + + +@workflow.defn +class SignalExternalMetadataWorkflow: + """Workflow that signals another workflow.""" + + @workflow.run + async def run(self, target_workflow_id: str) -> None: + await workflow.get_external_workflow_handle(target_workflow_id).signal( + SignalWaitWorkflow.my_signal, "signal-from-workflow" + ) + + +async def test_store_metadata_activity_scheduling(env: WorkflowEnvironment) -> None: + """When a workflow schedules an activity, context.activity should be populated.""" + client, driver = await _make_tracking_client(env) + workflow_id = f"workflow-{uuid.uuid4()}" + + async with new_worker( + client, + ActivityScheduleMetadataWorkflow, + activities=[echo_activity], + ) as worker: + await client.execute_workflow( + ActivityScheduleMetadataWorkflow.run, + "hello", + id=workflow_id, + task_queue=worker.task_queue, + ) + + assert len(driver.store_contexts) == 4 + + # [0] Client starts workflow + client_ctx = driver.store_contexts[0] + assert isinstance(client_ctx.target, StorageDriverWorkflowInfo) + assert client_ctx.target.id == workflow_id + assert client_ctx.target.type == "ActivityScheduleMetadataWorkflow" + assert client_ctx.target.run_id is None + + # [1] Workflow worker schedules activity + schedule_ctx = driver.store_contexts[1] + assert isinstance(schedule_ctx.target, StorageDriverWorkflowInfo) + assert schedule_ctx.target.namespace == client.namespace + assert schedule_ctx.target.id == workflow_id + assert schedule_ctx.target.type == "ActivityScheduleMetadataWorkflow" + assert schedule_ctx.target.run_id is not None + + # [2] Activity worker completes + execute_ctx = driver.store_contexts[2] + assert isinstance(execute_ctx.target, StorageDriverWorkflowInfo) + assert execute_ctx.target.namespace == client.namespace + assert execute_ctx.target.id == workflow_id + assert execute_ctx.target.type == "ActivityScheduleMetadataWorkflow" + assert execute_ctx.target.run_id is not None + + # [3] Workflow returns result + result_ctx = driver.store_contexts[3] + assert isinstance(result_ctx.target, StorageDriverWorkflowInfo) + assert result_ctx.target.id == workflow_id + assert result_ctx.target.type == "ActivityScheduleMetadataWorkflow" + assert result_ctx.target.run_id is not None + + +async def test_store_metadata_signal_external_workflow( + env: WorkflowEnvironment, +) -> None: + """Signaling an external workflow should set workflow.id to the target.""" + client, driver = await _make_tracking_client(env) + target_workflow_id = f"target-{uuid.uuid4()}" + sender_workflow_id = f"sender-{uuid.uuid4()}" + + async with new_worker( + client, + SignalExternalMetadataWorkflow, + SignalWaitWorkflow, + ) as worker: + # Start the target workflow first + target_handle = await client.start_workflow( + SignalWaitWorkflow.run, + "waiting", + id=target_workflow_id, + task_queue=worker.task_queue, + ) + # Start the sender which will signal the target + await client.execute_workflow( + SignalExternalMetadataWorkflow.run, + target_workflow_id, + id=sender_workflow_id, + task_queue=worker.task_queue, + ) + await target_handle.result() + + assert len(driver.store_contexts) == 5 + + # [0] Client starts target workflow (SignalWaitWorkflow) + target_start_ctx = driver.store_contexts[0] + assert isinstance(target_start_ctx.target, StorageDriverWorkflowInfo) + assert target_start_ctx.target.id == target_workflow_id + assert target_start_ctx.target.type == "SignalWaitWorkflow" + assert target_start_ctx.target.run_id is None + + # [1] Client starts sender workflow (SignalExternalMetadataWorkflow) + sender_start_ctx = driver.store_contexts[1] + assert isinstance(sender_start_ctx.target, StorageDriverWorkflowInfo) + assert sender_start_ctx.target.id == sender_workflow_id + assert sender_start_ctx.target.type == "SignalExternalMetadataWorkflow" + assert sender_start_ctx.target.run_id is None + + # [2] Sender signals target: target = the workflow being signaled + signal_ctx = driver.store_contexts[2] + assert isinstance(signal_ctx.target, StorageDriverWorkflowInfo) + assert signal_ctx.target.id == target_workflow_id + assert signal_ctx.target.type is None + assert signal_ctx.target.run_id is None + + # [3] and [4] are the sender and target workflow completions in some order. + # The sender's WFT 2 (after signal resolution) and the target's WFT (after + # receiving the signal) are both scheduled by the server at nearly the same + # time, so the order of their completions is non-deterministic. + completion_ctxs = { + ctx.target.id: ctx + for ctx in driver.store_contexts[3:5] + if isinstance(ctx.target, StorageDriverWorkflowInfo) and ctx.target.id + } + assert sender_workflow_id in completion_ctxs + assert target_workflow_id in completion_ctxs + + sender_result_ctx = completion_ctxs[sender_workflow_id] + assert isinstance(sender_result_ctx.target, StorageDriverWorkflowInfo) + assert sender_result_ctx.target.run_id is not None + + target_result_ctx = completion_ctxs[target_workflow_id] + assert isinstance(target_result_ctx.target, StorageDriverWorkflowInfo) + assert target_result_ctx.target.run_id is not None + + +async def test_store_metadata_standalone_activity(env: WorkflowEnvironment) -> None: + """Standalone activity worker should use StorageDriverActivityInfo as target.""" + if env.supports_time_skipping: + pytest.skip( + "Java test server: https://github.com/temporalio/sdk-java/issues/2741" + ) + client, driver = await _make_tracking_client(env) + activity_id = f"activity-{uuid.uuid4()}" + + async with new_worker(client, activities=[echo_activity]) as worker: + await client.execute_activity( + echo_activity, + "hello", + id=activity_id, + task_queue=worker.task_queue, + schedule_to_close_timeout=timedelta(seconds=30), + ) + + assert len(driver.store_contexts) == 2 + + client_ctx = driver.store_contexts[0] + # [0] Client schedules standalone activity + assert isinstance(client_ctx.target, StorageDriverActivityInfo) + assert client_ctx.target.namespace == client.namespace + assert client_ctx.target.id == activity_id + assert client_ctx.target.type == "echo_activity" + assert client_ctx.target.run_id is None + + # [1] Activity worker completes: target = activity (no parent workflow) + execute_ctx = driver.store_contexts[1] + assert isinstance(execute_ctx.target, StorageDriverActivityInfo) + assert execute_ctx.target.namespace == client.namespace + assert execute_ctx.target.id == activity_id + assert execute_ctx.target.type == "echo_activity" + assert execute_ctx.target.run_id is None + + +@workflow.defn +class ContinueAsNewExtStoreWorkflow: + """Workflow that continues-as-new once with a large payload. + + Run 1: called with large_payload, calls continue_as_new with same payload. + Run 2: called with large_payload again (from CaN), returns immediately. + """ + + @workflow.run + async def run(self, large_payload: str) -> str: + if workflow.info().continued_run_id is None: + workflow.continue_as_new(large_payload) + return "done" + + +async def test_extstore_continue_as_new_result_stored_under_current_run( + env: WorkflowEnvironment, +) -> None: + """A CaN continuation's result payloads are stored under the continuation's + own run_id, not under the originating run's run_id. + """ + client, driver = await _make_tracking_client(env) + + async with new_worker(client, ContinueAsNewExtStoreWorkflow) as worker: + handle = await client.start_workflow( + ContinueAsNewExtStoreWorkflow.run, + "x" * 1024, + id=f"workflow-{uuid.uuid4()}", + task_queue=worker.task_queue, + ) + first_run_id = (await handle.describe()).run_id + await handle.result() + last_run_id = (await handle.describe()).run_id + assert len(driver.store_contexts) == 3 + + # [0] Client starts workflow + client_ctx = driver.store_contexts[0] + assert isinstance(client_ctx.target, StorageDriverWorkflowInfo) + assert client_ctx.target.run_id is None + + # [1] Workflow 1 encodes CaN args + can_args_ctx = driver.store_contexts[1] + assert isinstance(can_args_ctx.target, StorageDriverWorkflowInfo) + assert can_args_ctx.target.run_id == first_run_id + + # [2] Workflow 2 encodes result in its own context + result_ctx = driver.store_contexts[2] + assert isinstance(result_ctx.target, StorageDriverWorkflowInfo) + assert result_ctx.target.run_id is not None + assert result_ctx.target.run_id == last_run_id diff --git a/tests/worker/test_workflow.py b/tests/worker/test_workflow.py index 4ef5c29fa..f123e5c61 100644 --- a/tests/worker/test_workflow.py +++ b/tests/worker/test_workflow.py @@ -38,6 +38,7 @@ import temporalio.api.sdk.v1 import temporalio.client import temporalio.converter +import temporalio.converter._extstore import temporalio.worker import temporalio.worker._command_aware_visitor import temporalio.workflow @@ -1626,6 +1627,12 @@ def get_serialization_context( ) -> temporalio.converter.SerializationContext | None: return self._unsandboxed.get_serialization_context(command_info) + def get_external_store_context( + self, + command_info: temporalio.worker._command_aware_visitor.CommandInfo | None, + ) -> temporalio.converter._extstore.StorageDriverStoreContext: + return self._unsandboxed.get_external_store_context(command_info) + async def test_workflow_with_custom_runner(client: Client): runner = CustomWorkflowRunner() From 68561ee72ff65da2b13baf059b4f54956b838173 Mon Sep 17 00:00:00 2001 From: Thomas Hardy Date: Mon, 6 Apr 2026 09:27:08 -0700 Subject: [PATCH 025/226] Bump core commit to latest (#1413) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Bump core commit to latest * Test fix - pass None to worker when deployment versioning is not configured * Support openapiv2 proto annotations sdk-core added protoc-gen-openapiv2 imports to cloud service protos. This broke proto generation in two ways: 1. protoc couldn't resolve the import — none of the existing --proto_path entries covered protoc-gen-openapiv2/. Added the protos/ root dir as a --proto_path so protoc-gen-openapiv2/options/annotations.proto is reachable. 2. The generated service_pb2.py requires the openapiv2 Python modules, which didn't exist. Generated openapiv2 protos and move them into temporalio/api/dependencies/protoc_gen_openapiv2/, with import rewrites to match. Also fixed the Docker proto generation (gen-protos-docker): google-adk requires protobuf>=5 which conflicts with the protobuf<4 downgrade needed for generation. Fix: remove google-adk before downgrading, matching the CI workflow. Mirrors sdk-dotnet#633. --- scripts/_proto/Dockerfile | 1 + scripts/gen_protos.py | 16 +- temporalio/api/cloud/account/v1/__init__.py | 10 +- .../api/cloud/account/v1/message_pb2.py | 41 +- .../api/cloud/account/v1/message_pb2.pyi | 102 +- temporalio/api/cloud/auditlog/__init__.py | 0 temporalio/api/cloud/auditlog/v1/__init__.py | 6 + .../api/cloud/auditlog/v1/message_pb2.py | 56 + .../api/cloud/auditlog/v1/message_pb2.pyi | 138 ++ temporalio/api/cloud/billing/__init__.py | 0 temporalio/api/cloud/billing/v1/__init__.py | 6 + .../api/cloud/billing/v1/message_pb2.py | 79 + .../api/cloud/billing/v1/message_pb2.pyi | 250 ++ .../api/cloud/cloudservice/v1/__init__.py | 40 + .../cloudservice/v1/request_response_pb2.py | 800 +++++-- .../cloudservice/v1/request_response_pb2.pyi | 581 +++++ .../api/cloud/cloudservice/v1/service_pb2.py | 227 +- .../cloud/cloudservice/v1/service_pb2_grpc.py | 450 ++++ .../cloudservice/v1/service_pb2_grpc.pyi | 120 + temporalio/api/cloud/namespace/v1/__init__.py | 6 + .../api/cloud/namespace/v1/message_pb2.py | 301 ++- .../api/cloud/namespace/v1/message_pb2.pyi | 471 +++- temporalio/api/dependencies/__init__.py | 0 .../protoc_gen_openapiv2/__init__.py | 0 .../protoc_gen_openapiv2/options/__init__.py | 43 + .../options/annotations_pb2.py | 65 + .../options/annotations_pb2.pyi | 75 + .../options/openapiv2_pb2.py | 568 +++++ .../options/openapiv2_pb2.pyi | 2102 +++++++++++++++++ temporalio/api/namespace/v1/message_pb2.py | 38 +- temporalio/api/namespace/v1/message_pb2.pyi | 6 + temporalio/api/protometa/__init__.py | 0 temporalio/api/protometa/v1/__init__.py | 5 + .../api/protometa/v1/annotations_pb2.py | 48 + .../api/protometa/v1/annotations_pb2.pyi | 64 + .../v1/request_response_pb2.py | 880 +++---- .../v1/request_response_pb2.pyi | 89 +- .../api/workflowservice/v1/service_pb2.py | 141 +- temporalio/bridge/Cargo.lock | 854 +++++-- temporalio/bridge/Cargo.toml | 8 +- .../proto/activity_task/activity_task_pb2.py | 20 +- .../proto/activity_task/activity_task_pb2.pyi | 6 + temporalio/bridge/sdk-core | 2 +- temporalio/bridge/services_generated.py | 180 ++ temporalio/bridge/src/client_rpc_generated.rs | 90 + temporalio/bridge/src/metric.rs | 3 + temporalio/bridge/src/worker.rs | 16 +- uv.lock | 2 +- 48 files changed, 7829 insertions(+), 1177 deletions(-) create mode 100644 temporalio/api/cloud/auditlog/__init__.py create mode 100644 temporalio/api/cloud/auditlog/v1/__init__.py create mode 100644 temporalio/api/cloud/auditlog/v1/message_pb2.py create mode 100644 temporalio/api/cloud/auditlog/v1/message_pb2.pyi create mode 100644 temporalio/api/cloud/billing/__init__.py create mode 100644 temporalio/api/cloud/billing/v1/__init__.py create mode 100644 temporalio/api/cloud/billing/v1/message_pb2.py create mode 100644 temporalio/api/cloud/billing/v1/message_pb2.pyi create mode 100644 temporalio/api/dependencies/__init__.py create mode 100644 temporalio/api/dependencies/protoc_gen_openapiv2/__init__.py create mode 100644 temporalio/api/dependencies/protoc_gen_openapiv2/options/__init__.py create mode 100644 temporalio/api/dependencies/protoc_gen_openapiv2/options/annotations_pb2.py create mode 100644 temporalio/api/dependencies/protoc_gen_openapiv2/options/annotations_pb2.pyi create mode 100644 temporalio/api/dependencies/protoc_gen_openapiv2/options/openapiv2_pb2.py create mode 100644 temporalio/api/dependencies/protoc_gen_openapiv2/options/openapiv2_pb2.pyi create mode 100644 temporalio/api/protometa/__init__.py create mode 100644 temporalio/api/protometa/v1/__init__.py create mode 100644 temporalio/api/protometa/v1/annotations_pb2.py create mode 100644 temporalio/api/protometa/v1/annotations_pb2.pyi diff --git a/scripts/_proto/Dockerfile b/scripts/_proto/Dockerfile index 36e6d1a6c..2e2f58391 100644 --- a/scripts/_proto/Dockerfile +++ b/scripts/_proto/Dockerfile @@ -8,6 +8,7 @@ VOLUME ["/api_new", "/bridge_new"] COPY ./ ./ RUN mkdir -p ./temporalio/api +RUN uv remove google-adk --optional google-adk RUN uv add "protobuf<4" RUN uv sync --all-extras RUN uv run scripts/gen_protos.py diff --git a/scripts/gen_protos.py b/scripts/gen_protos.py index c1d5360b5..0047952dc 100644 --- a/scripts/gen_protos.py +++ b/scripts/gen_protos.py @@ -39,6 +39,10 @@ partial( re.compile(r"from dependencies\.").sub, r"from temporalio.api.dependencies." ), + partial( + re.compile(r"from protoc_gen_openapiv2\.").sub, + r"from temporalio.api.dependencies.protoc_gen_openapiv2.", + ), partial( re.compile(r"from temporal\.sdk\.core\.").sub, r"from temporalio.bridge.proto." ), @@ -50,6 +54,10 @@ pyi_fixes = [ partial(re.compile(r"temporal\.api\.").sub, r"temporalio.api."), + partial( + re.compile(r"protoc_gen_openapiv2\.").sub, + r"temporalio.api.dependencies.protoc_gen_openapiv2.", + ), partial(re.compile(r"temporal\.sdk\.core\.").sub, r"temporalio.bridge.proto."), ] @@ -163,6 +171,7 @@ def generate_protos(output_dir: Path): f"--proto_path={core_proto_dir}", f"--proto_path={testsrv_proto_dir}", f"--proto_path={health_proto_dir}", + f"--proto_path={proto_dir}", f"--proto_path={test_proto_dir}", f"--proto_path={additional_proto_dir}", f"--python_out={output_dir}", @@ -182,11 +191,16 @@ def generate_protos(output_dir: Path): grpc_file.unlink() # Apply fixes before moving code fix_generated_output(output_dir) + # Move openapiv2 dependency protos + deps_out_dir = api_out_dir / "dependencies" + shutil.rmtree(deps_out_dir / "protoc_gen_openapiv2", ignore_errors=True) + deps_out_dir.mkdir(exist_ok=True) + (output_dir / "protoc_gen_openapiv2").replace(deps_out_dir / "protoc_gen_openapiv2") + (deps_out_dir / "__init__.py").touch() # Move protos for p in (output_dir / "temporal" / "api").iterdir(): shutil.rmtree(api_out_dir / p.name, ignore_errors=True) p.replace(api_out_dir / p.name) - shutil.rmtree(api_out_dir / "dependencies", ignore_errors=True) for p in (output_dir / "temporal" / "sdk" / "core").iterdir(): shutil.rmtree(sdk_out_dir / p.name, ignore_errors=True) p.replace(sdk_out_dir / p.name) diff --git a/temporalio/api/cloud/account/v1/__init__.py b/temporalio/api/cloud/account/v1/__init__.py index ed3d87d9f..b1ef72ede 100644 --- a/temporalio/api/cloud/account/v1/__init__.py +++ b/temporalio/api/cloud/account/v1/__init__.py @@ -1,8 +1,16 @@ -from .message_pb2 import Account, AccountSpec, AuditLogSinkSpec, Metrics, MetricsSpec +from .message_pb2 import ( + Account, + AccountSpec, + AuditLogSink, + AuditLogSinkSpec, + Metrics, + MetricsSpec, +) __all__ = [ "Account", "AccountSpec", + "AuditLogSink", "AuditLogSinkSpec", "Metrics", "MetricsSpec", diff --git a/temporalio/api/cloud/account/v1/message_pb2.py b/temporalio/api/cloud/account/v1/message_pb2.py index 11d4ad75c..c31a2d3e7 100644 --- a/temporalio/api/cloud/account/v1/message_pb2.py +++ b/temporalio/api/cloud/account/v1/message_pb2.py @@ -14,6 +14,8 @@ _sym_db = _symbol_database.Default() +from google.protobuf import timestamp_pb2 as google_dot_protobuf_dot_timestamp__pb2 + from temporalio.api.cloud.resource.v1 import ( message_pb2 as temporal_dot_api_dot_cloud_dot_resource_dot_v1_dot_message__pb2, ) @@ -22,7 +24,7 @@ ) DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile( - b'\n+temporal/api/cloud/account/v1/message.proto\x12\x1dtemporal.api.cloud.account.v1\x1a,temporal/api/cloud/resource/v1/message.proto\x1a(temporal/api/cloud/sink/v1/message.proto")\n\x0bMetricsSpec\x12\x1a\n\x12\x61\x63\x63\x65pted_client_ca\x18\x02 \x01(\x0c"J\n\x0b\x41\x63\x63ountSpec\x12;\n\x07metrics\x18\x01 \x01(\x0b\x32*.temporal.api.cloud.account.v1.MetricsSpec"\x16\n\x07Metrics\x12\x0b\n\x03uri\x18\x01 \x01(\t"\xfc\x01\n\x07\x41\x63\x63ount\x12\n\n\x02id\x18\x01 \x01(\t\x12\x38\n\x04spec\x18\x02 \x01(\x0b\x32*.temporal.api.cloud.account.v1.AccountSpec\x12\x18\n\x10resource_version\x18\x03 \x01(\t\x12<\n\x05state\x18\x04 \x01(\x0e\x32-.temporal.api.cloud.resource.v1.ResourceState\x12\x1a\n\x12\x61sync_operation_id\x18\x05 \x01(\t\x12\x37\n\x07metrics\x18\x06 \x01(\x0b\x32&.temporal.api.cloud.account.v1.Metrics"\xbf\x01\n\x10\x41uditLogSinkSpec\x12\x0c\n\x04name\x18\x01 \x01(\t\x12?\n\x0ckinesis_sink\x18\x02 \x01(\x0b\x32\'.temporal.api.cloud.sink.v1.KinesisSpecH\x00\x12>\n\x0cpub_sub_sink\x18\x03 \x01(\x0b\x32&.temporal.api.cloud.sink.v1.PubSubSpecH\x00\x12\x0f\n\x07\x65nabled\x18\x04 \x01(\x08\x42\x0b\n\tsink_typeB\xa7\x01\n io.temporal.api.cloud.account.v1B\x0cMessageProtoP\x01Z+go.temporal.io/api/cloud/account/v1;account\xaa\x02\x1fTemporalio.Api.Cloud.Account.V1\xea\x02#Temporalio::Api::Cloud::Account::V1b\x06proto3' + b'\n+temporal/api/cloud/account/v1/message.proto\x12\x1dtemporal.api.cloud.account.v1\x1a,temporal/api/cloud/resource/v1/message.proto\x1a(temporal/api/cloud/sink/v1/message.proto\x1a\x1fgoogle/protobuf/timestamp.proto")\n\x0bMetricsSpec\x12\x1a\n\x12\x61\x63\x63\x65pted_client_ca\x18\x02 \x01(\x0c"J\n\x0b\x41\x63\x63ountSpec\x12;\n\x07metrics\x18\x01 \x01(\x0b\x32*.temporal.api.cloud.account.v1.MetricsSpec"\x16\n\x07Metrics\x12\x0b\n\x03uri\x18\x01 \x01(\t"\xfc\x01\n\x07\x41\x63\x63ount\x12\n\n\x02id\x18\x01 \x01(\t\x12\x38\n\x04spec\x18\x02 \x01(\x0b\x32*.temporal.api.cloud.account.v1.AccountSpec\x12\x18\n\x10resource_version\x18\x03 \x01(\t\x12<\n\x05state\x18\x04 \x01(\x0e\x32-.temporal.api.cloud.resource.v1.ResourceState\x12\x1a\n\x12\x61sync_operation_id\x18\x05 \x01(\t\x12\x37\n\x07metrics\x18\x06 \x01(\x0b\x32&.temporal.api.cloud.account.v1.Metrics"\xbf\x01\n\x10\x41uditLogSinkSpec\x12\x0c\n\x04name\x18\x01 \x01(\t\x12?\n\x0ckinesis_sink\x18\x02 \x01(\x0b\x32\'.temporal.api.cloud.sink.v1.KinesisSpecH\x00\x12>\n\x0cpub_sub_sink\x18\x03 \x01(\x0b\x32&.temporal.api.cloud.sink.v1.PubSubSpecH\x00\x12\x0f\n\x07\x65nabled\x18\x04 \x01(\x08\x42\x0b\n\tsink_type"\xb8\x03\n\x0c\x41uditLogSink\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x18\n\x10resource_version\x18\x02 \x01(\t\x12<\n\x05state\x18\x03 \x01(\x0e\x32-.temporal.api.cloud.resource.v1.ResourceState\x12=\n\x04spec\x18\x04 \x01(\x0b\x32/.temporal.api.cloud.account.v1.AuditLogSinkSpec\x12\x42\n\x06health\x18\x05 \x01(\x0e\x32\x32.temporal.api.cloud.account.v1.AuditLogSink.Health\x12\x15\n\rerror_message\x18\x06 \x01(\t\x12\x37\n\x13last_succeeded_time\x18\x07 \x01(\x0b\x32\x1a.google.protobuf.Timestamp"o\n\x06Health\x12\x16\n\x12HEALTH_UNSPECIFIED\x10\x00\x12\r\n\tHEALTH_OK\x10\x01\x12\x19\n\x15HEALTH_ERROR_INTERNAL\x10\x02\x12#\n\x1fHEALTH_ERROR_USER_CONFIGURATION\x10\x03\x42\xa7\x01\n io.temporal.api.cloud.account.v1B\x0cMessageProtoP\x01Z+go.temporal.io/api/cloud/account/v1;account\xaa\x02\x1fTemporalio.Api.Cloud.Account.V1\xea\x02#Temporalio::Api::Cloud::Account::V1b\x06proto3' ) @@ -31,6 +33,8 @@ _METRICS = DESCRIPTOR.message_types_by_name["Metrics"] _ACCOUNT = DESCRIPTOR.message_types_by_name["Account"] _AUDITLOGSINKSPEC = DESCRIPTOR.message_types_by_name["AuditLogSinkSpec"] +_AUDITLOGSINK = DESCRIPTOR.message_types_by_name["AuditLogSink"] +_AUDITLOGSINK_HEALTH = _AUDITLOGSINK.enum_types_by_name["Health"] MetricsSpec = _reflection.GeneratedProtocolMessageType( "MetricsSpec", (_message.Message,), @@ -86,17 +90,32 @@ ) _sym_db.RegisterMessage(AuditLogSinkSpec) +AuditLogSink = _reflection.GeneratedProtocolMessageType( + "AuditLogSink", + (_message.Message,), + { + "DESCRIPTOR": _AUDITLOGSINK, + "__module__": "temporalio.api.cloud.account.v1.message_pb2", + # @@protoc_insertion_point(class_scope:temporal.api.cloud.account.v1.AuditLogSink) + }, +) +_sym_db.RegisterMessage(AuditLogSink) + if _descriptor._USE_C_DESCRIPTORS == False: DESCRIPTOR._options = None DESCRIPTOR._serialized_options = b"\n io.temporal.api.cloud.account.v1B\014MessageProtoP\001Z+go.temporal.io/api/cloud/account/v1;account\252\002\037Temporalio.Api.Cloud.Account.V1\352\002#Temporalio::Api::Cloud::Account::V1" - _METRICSSPEC._serialized_start = 166 - _METRICSSPEC._serialized_end = 207 - _ACCOUNTSPEC._serialized_start = 209 - _ACCOUNTSPEC._serialized_end = 283 - _METRICS._serialized_start = 285 - _METRICS._serialized_end = 307 - _ACCOUNT._serialized_start = 310 - _ACCOUNT._serialized_end = 562 - _AUDITLOGSINKSPEC._serialized_start = 565 - _AUDITLOGSINKSPEC._serialized_end = 756 + _METRICSSPEC._serialized_start = 199 + _METRICSSPEC._serialized_end = 240 + _ACCOUNTSPEC._serialized_start = 242 + _ACCOUNTSPEC._serialized_end = 316 + _METRICS._serialized_start = 318 + _METRICS._serialized_end = 340 + _ACCOUNT._serialized_start = 343 + _ACCOUNT._serialized_end = 595 + _AUDITLOGSINKSPEC._serialized_start = 598 + _AUDITLOGSINKSPEC._serialized_end = 789 + _AUDITLOGSINK._serialized_start = 792 + _AUDITLOGSINK._serialized_end = 1232 + _AUDITLOGSINK_HEALTH._serialized_start = 1121 + _AUDITLOGSINK_HEALTH._serialized_end = 1232 # @@protoc_insertion_point(module_scope) diff --git a/temporalio/api/cloud/account/v1/message_pb2.pyi b/temporalio/api/cloud/account/v1/message_pb2.pyi index 2bd9917e0..859cd6bd5 100644 --- a/temporalio/api/cloud/account/v1/message_pb2.pyi +++ b/temporalio/api/cloud/account/v1/message_pb2.pyi @@ -5,14 +5,17 @@ isort:skip_file import builtins import sys +import typing import google.protobuf.descriptor +import google.protobuf.internal.enum_type_wrapper import google.protobuf.message +import google.protobuf.timestamp_pb2 import temporalio.api.cloud.resource.v1.message_pb2 import temporalio.api.cloud.sink.v1.message_pb2 -if sys.version_info >= (3, 8): +if sys.version_info >= (3, 10): import typing as typing_extensions else: import typing_extensions @@ -200,3 +203,100 @@ class AuditLogSinkSpec(google.protobuf.message.Message): ) -> typing_extensions.Literal["kinesis_sink", "pub_sub_sink"] | None: ... global___AuditLogSinkSpec = AuditLogSinkSpec + +class AuditLogSink(google.protobuf.message.Message): + """AuditLogSink is only used by Audit Log""" + + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + class _Health: + ValueType = typing.NewType("ValueType", builtins.int) + V: typing_extensions.TypeAlias = ValueType + + class _HealthEnumTypeWrapper( + google.protobuf.internal.enum_type_wrapper._EnumTypeWrapper[ + AuditLogSink._Health.ValueType + ], + builtins.type, + ): # noqa: F821 + DESCRIPTOR: google.protobuf.descriptor.EnumDescriptor + HEALTH_UNSPECIFIED: AuditLogSink._Health.ValueType # 0 + HEALTH_OK: AuditLogSink._Health.ValueType # 1 + """The audit log sink is healthy and functioning correctly.""" + HEALTH_ERROR_INTERNAL: AuditLogSink._Health.ValueType # 2 + """The audit log sink has an internal error.""" + HEALTH_ERROR_USER_CONFIGURATION: AuditLogSink._Health.ValueType # 3 + """The audit log sink has a configuration error.""" + + class Health(_Health, metaclass=_HealthEnumTypeWrapper): + """The health status of the audit log sink.""" + + HEALTH_UNSPECIFIED: AuditLogSink.Health.ValueType # 0 + HEALTH_OK: AuditLogSink.Health.ValueType # 1 + """The audit log sink is healthy and functioning correctly.""" + HEALTH_ERROR_INTERNAL: AuditLogSink.Health.ValueType # 2 + """The audit log sink has an internal error.""" + HEALTH_ERROR_USER_CONFIGURATION: AuditLogSink.Health.ValueType # 3 + """The audit log sink has a configuration error.""" + + NAME_FIELD_NUMBER: builtins.int + RESOURCE_VERSION_FIELD_NUMBER: builtins.int + STATE_FIELD_NUMBER: builtins.int + SPEC_FIELD_NUMBER: builtins.int + HEALTH_FIELD_NUMBER: builtins.int + ERROR_MESSAGE_FIELD_NUMBER: builtins.int + LAST_SUCCEEDED_TIME_FIELD_NUMBER: builtins.int + name: builtins.str + """Name of the sink e.g. "audit_log_01" """ + resource_version: builtins.str + """The version of the audit log sink resource.""" + state: temporalio.api.cloud.resource.v1.message_pb2.ResourceState.ValueType + """The current state of the audit log sink.""" + @property + def spec(self) -> global___AuditLogSinkSpec: + """The specification details of the audit log sink.""" + health: global___AuditLogSink.Health.ValueType + """The health status of the audit log sink.""" + error_message: builtins.str + """An error message describing any issues with the audit log sink, if applicable.""" + @property + def last_succeeded_time(self) -> google.protobuf.timestamp_pb2.Timestamp: + """The last succeeded timestamp for the internal workflow responsible for adding data to the sink.""" + def __init__( + self, + *, + name: builtins.str = ..., + resource_version: builtins.str = ..., + state: temporalio.api.cloud.resource.v1.message_pb2.ResourceState.ValueType = ..., + spec: global___AuditLogSinkSpec | None = ..., + health: global___AuditLogSink.Health.ValueType = ..., + error_message: builtins.str = ..., + last_succeeded_time: google.protobuf.timestamp_pb2.Timestamp | None = ..., + ) -> None: ... + def HasField( + self, + field_name: typing_extensions.Literal[ + "last_succeeded_time", b"last_succeeded_time", "spec", b"spec" + ], + ) -> builtins.bool: ... + def ClearField( + self, + field_name: typing_extensions.Literal[ + "error_message", + b"error_message", + "health", + b"health", + "last_succeeded_time", + b"last_succeeded_time", + "name", + b"name", + "resource_version", + b"resource_version", + "spec", + b"spec", + "state", + b"state", + ], + ) -> None: ... + +global___AuditLogSink = AuditLogSink diff --git a/temporalio/api/cloud/auditlog/__init__.py b/temporalio/api/cloud/auditlog/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/temporalio/api/cloud/auditlog/v1/__init__.py b/temporalio/api/cloud/auditlog/v1/__init__.py new file mode 100644 index 000000000..558f70660 --- /dev/null +++ b/temporalio/api/cloud/auditlog/v1/__init__.py @@ -0,0 +1,6 @@ +from .message_pb2 import LogRecord, Principal + +__all__ = [ + "LogRecord", + "Principal", +] diff --git a/temporalio/api/cloud/auditlog/v1/message_pb2.py b/temporalio/api/cloud/auditlog/v1/message_pb2.py new file mode 100644 index 000000000..5714d3d23 --- /dev/null +++ b/temporalio/api/cloud/auditlog/v1/message_pb2.py @@ -0,0 +1,56 @@ +# -*- coding: utf-8 -*- +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: temporal/api/cloud/auditlog/v1/message.proto +"""Generated protocol buffer code.""" + +from google.protobuf import descriptor as _descriptor +from google.protobuf import descriptor_pool as _descriptor_pool +from google.protobuf import message as _message +from google.protobuf import reflection as _reflection +from google.protobuf import symbol_database as _symbol_database + +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + +from google.protobuf import struct_pb2 as google_dot_protobuf_dot_struct__pb2 +from google.protobuf import timestamp_pb2 as google_dot_protobuf_dot_timestamp__pb2 + +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile( + b'\n,temporal/api/cloud/auditlog/v1/message.proto\x12\x1etemporal.api.cloud.auditlog.v1\x1a\x1fgoogle/protobuf/timestamp.proto\x1a\x1cgoogle/protobuf/struct.proto"\x9f\x02\n\tLogRecord\x12-\n\temit_time\x18\x01 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x11\n\toperation\x18\x05 \x01(\t\x12\x0e\n\x06status\x18\x07 \x01(\t\x12\x0f\n\x07version\x18\t \x01(\x05\x12\x0e\n\x06log_id\x18\n \x01(\t\x12<\n\tprincipal\x18\x0c \x01(\x0b\x32).temporal.api.cloud.auditlog.v1.Principal\x12,\n\x0braw_details\x18\r \x01(\x0b\x32\x17.google.protobuf.Struct\x12\x17\n\x0fx_forwarded_for\x18\x0e \x01(\t\x12\x1a\n\x12\x61sync_operation_id\x18\x0f \x01(\t"G\n\tPrincipal\x12\x0c\n\x04type\x18\x01 \x01(\t\x12\n\n\x02id\x18\x02 \x01(\t\x12\x0c\n\x04name\x18\x03 \x01(\t\x12\x12\n\napi_key_id\x18\x04 \x01(\tB\xac\x01\n!io.temporal.api.cloud.auditlog.v1B\x0cMessageProtoP\x01Z-go.temporal.io/api/cloud/auditlog/v1;auditlog\xaa\x02 Temporalio.Api.Cloud.AuditLog.V1\xea\x02$Temporalio::Api::Cloud::AuditLog::V1b\x06proto3' +) + + +_LOGRECORD = DESCRIPTOR.message_types_by_name["LogRecord"] +_PRINCIPAL = DESCRIPTOR.message_types_by_name["Principal"] +LogRecord = _reflection.GeneratedProtocolMessageType( + "LogRecord", + (_message.Message,), + { + "DESCRIPTOR": _LOGRECORD, + "__module__": "temporalio.api.cloud.auditlog.v1.message_pb2", + # @@protoc_insertion_point(class_scope:temporal.api.cloud.auditlog.v1.LogRecord) + }, +) +_sym_db.RegisterMessage(LogRecord) + +Principal = _reflection.GeneratedProtocolMessageType( + "Principal", + (_message.Message,), + { + "DESCRIPTOR": _PRINCIPAL, + "__module__": "temporalio.api.cloud.auditlog.v1.message_pb2", + # @@protoc_insertion_point(class_scope:temporal.api.cloud.auditlog.v1.Principal) + }, +) +_sym_db.RegisterMessage(Principal) + +if _descriptor._USE_C_DESCRIPTORS == False: + DESCRIPTOR._options = None + DESCRIPTOR._serialized_options = b"\n!io.temporal.api.cloud.auditlog.v1B\014MessageProtoP\001Z-go.temporal.io/api/cloud/auditlog/v1;auditlog\252\002 Temporalio.Api.Cloud.AuditLog.V1\352\002$Temporalio::Api::Cloud::AuditLog::V1" + _LOGRECORD._serialized_start = 144 + _LOGRECORD._serialized_end = 431 + _PRINCIPAL._serialized_start = 433 + _PRINCIPAL._serialized_end = 504 +# @@protoc_insertion_point(module_scope) diff --git a/temporalio/api/cloud/auditlog/v1/message_pb2.pyi b/temporalio/api/cloud/auditlog/v1/message_pb2.pyi new file mode 100644 index 000000000..4145313c2 --- /dev/null +++ b/temporalio/api/cloud/auditlog/v1/message_pb2.pyi @@ -0,0 +1,138 @@ +""" +@generated by mypy-protobuf. Do not edit manually! +isort:skip_file +""" + +import builtins +import sys + +import google.protobuf.descriptor +import google.protobuf.message +import google.protobuf.struct_pb2 +import google.protobuf.timestamp_pb2 + +if sys.version_info >= (3, 8): + import typing as typing_extensions +else: + import typing_extensions + +DESCRIPTOR: google.protobuf.descriptor.FileDescriptor + +class LogRecord(google.protobuf.message.Message): + """LogRecord represents an audit log entry from Temporal, structured for easy parsing and analysis.""" + + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + EMIT_TIME_FIELD_NUMBER: builtins.int + OPERATION_FIELD_NUMBER: builtins.int + STATUS_FIELD_NUMBER: builtins.int + VERSION_FIELD_NUMBER: builtins.int + LOG_ID_FIELD_NUMBER: builtins.int + PRINCIPAL_FIELD_NUMBER: builtins.int + RAW_DETAILS_FIELD_NUMBER: builtins.int + X_FORWARDED_FOR_FIELD_NUMBER: builtins.int + ASYNC_OPERATION_ID_FIELD_NUMBER: builtins.int + @property + def emit_time(self) -> google.protobuf.timestamp_pb2.Timestamp: + """Time when the log was emitted.""" + operation: builtins.str + """The operation performed.""" + status: builtins.str + """The status of the operation.""" + version: builtins.int + """The internal version of the log message. Can be used in deduplication if needed.""" + log_id: builtins.str + """Unique ID for the log record.""" + @property + def principal(self) -> global___Principal: + """The principal that performed the operation.""" + @property + def raw_details(self) -> google.protobuf.struct_pb2.Struct: + """The raw details of the operation.""" + x_forwarded_for: builtins.str + """The originating IP address of the request.""" + async_operation_id: builtins.str + """The ID of the async operation.""" + def __init__( + self, + *, + emit_time: google.protobuf.timestamp_pb2.Timestamp | None = ..., + operation: builtins.str = ..., + status: builtins.str = ..., + version: builtins.int = ..., + log_id: builtins.str = ..., + principal: global___Principal | None = ..., + raw_details: google.protobuf.struct_pb2.Struct | None = ..., + x_forwarded_for: builtins.str = ..., + async_operation_id: builtins.str = ..., + ) -> None: ... + def HasField( + self, + field_name: typing_extensions.Literal[ + "emit_time", + b"emit_time", + "principal", + b"principal", + "raw_details", + b"raw_details", + ], + ) -> builtins.bool: ... + def ClearField( + self, + field_name: typing_extensions.Literal[ + "async_operation_id", + b"async_operation_id", + "emit_time", + b"emit_time", + "log_id", + b"log_id", + "operation", + b"operation", + "principal", + b"principal", + "raw_details", + b"raw_details", + "status", + b"status", + "version", + b"version", + "x_forwarded_for", + b"x_forwarded_for", + ], + ) -> None: ... + +global___LogRecord = LogRecord + +class Principal(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + TYPE_FIELD_NUMBER: builtins.int + ID_FIELD_NUMBER: builtins.int + NAME_FIELD_NUMBER: builtins.int + API_KEY_ID_FIELD_NUMBER: builtins.int + type: builtins.str + """The type of the principal. + Possible type values: user, serviceaccount. + """ + id: builtins.str + """The id of the principal.""" + name: builtins.str + """The name of the principal.""" + api_key_id: builtins.str + """The api key id of the principal if provided.""" + def __init__( + self, + *, + type: builtins.str = ..., + id: builtins.str = ..., + name: builtins.str = ..., + api_key_id: builtins.str = ..., + ) -> None: ... + def ClearField( + self, + field_name: typing_extensions.Literal[ + "api_key_id", b"api_key_id", "id", b"id", "name", b"name", "type", b"type" + ], + ) -> None: ... + +global___Principal = Principal diff --git a/temporalio/api/cloud/billing/__init__.py b/temporalio/api/cloud/billing/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/temporalio/api/cloud/billing/v1/__init__.py b/temporalio/api/cloud/billing/v1/__init__.py new file mode 100644 index 000000000..7159e38fc --- /dev/null +++ b/temporalio/api/cloud/billing/v1/__init__.py @@ -0,0 +1,6 @@ +from .message_pb2 import BillingReport, BillingReportSpec + +__all__ = [ + "BillingReport", + "BillingReportSpec", +] diff --git a/temporalio/api/cloud/billing/v1/message_pb2.py b/temporalio/api/cloud/billing/v1/message_pb2.py new file mode 100644 index 000000000..541831f83 --- /dev/null +++ b/temporalio/api/cloud/billing/v1/message_pb2.py @@ -0,0 +1,79 @@ +# -*- coding: utf-8 -*- +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: temporal/api/cloud/billing/v1/message.proto +"""Generated protocol buffer code.""" + +from google.protobuf import descriptor as _descriptor +from google.protobuf import descriptor_pool as _descriptor_pool +from google.protobuf import message as _message +from google.protobuf import reflection as _reflection +from google.protobuf import symbol_database as _symbol_database + +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + +from google.protobuf import duration_pb2 as google_dot_protobuf_dot_duration__pb2 +from google.protobuf import timestamp_pb2 as google_dot_protobuf_dot_timestamp__pb2 + +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile( + b'\n+temporal/api/cloud/billing/v1/message.proto\x12\x1dtemporal.api.cloud.billing.v1\x1a\x1egoogle/protobuf/duration.proto\x1a\x1fgoogle/protobuf/timestamp.proto"\xdf\x01\n\x11\x42illingReportSpec\x12\x38\n\x14start_time_inclusive\x18\x01 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x36\n\x12\x65nd_time_exclusive\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x43\n download_url_expiration_duration\x18\x03 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x13\n\x0b\x64\x65scription\x18\x04 \x01(\t"\xa8\x06\n\rBillingReport\x12\n\n\x02id\x18\x01 \x01(\t\x12N\n\x05state\x18\x02 \x01(\x0e\x32?.temporal.api.cloud.billing.v1.BillingReport.BillingReportState\x12>\n\x04spec\x18\x03 \x01(\x0b\x32\x30.temporal.api.cloud.billing.v1.BillingReportSpec\x12L\n\rdownload_info\x18\x04 \x03(\x0b\x32\x35.temporal.api.cloud.billing.v1.BillingReport.Download\x12\x32\n\x0erequested_time\x18\x05 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x32\n\x0egenerated_time\x18\x06 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x1a\n\x12\x61sync_operation_id\x18\x07 \x01(\t\x1a\x80\x02\n\x08\x44ownload\x12\x0b\n\x03url\x18\x01 \x01(\t\x12\x37\n\x13url_expiration_time\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12U\n\x0b\x66ile_format\x18\x03 \x01(\x0e\x32@.temporal.api.cloud.billing.v1.BillingReport.Download.FileFormat\x12\x17\n\x0f\x66ile_size_bytes\x18\x04 \x01(\x03">\n\nFileFormat\x12\x1b\n\x17\x46ILE_FORMAT_UNSPECIFIED\x10\x00\x12\x13\n\x0f\x46ILE_FORMAT_CSV\x10\x01"\xa5\x01\n\x12\x42illingReportState\x12$\n BILLING_REPORT_STATE_UNSPECIFIED\x10\x00\x12$\n BILLING_REPORT_STATE_IN_PROGRESS\x10\x01\x12"\n\x1e\x42ILLING_REPORT_STATE_GENERATED\x10\x02\x12\x1f\n\x1b\x42ILLING_REPORT_STATE_FAILED\x10\x03\x42\xa7\x01\n io.temporal.api.cloud.billing.v1B\x0cMessageProtoP\x01Z+go.temporal.io/api/cloud/billing/v1;billing\xaa\x02\x1fTemporalio.Api.Cloud.Billing.V1\xea\x02#Temporalio::Api::Cloud::Billing::V1b\x06proto3' +) + + +_BILLINGREPORTSPEC = DESCRIPTOR.message_types_by_name["BillingReportSpec"] +_BILLINGREPORT = DESCRIPTOR.message_types_by_name["BillingReport"] +_BILLINGREPORT_DOWNLOAD = _BILLINGREPORT.nested_types_by_name["Download"] +_BILLINGREPORT_DOWNLOAD_FILEFORMAT = _BILLINGREPORT_DOWNLOAD.enum_types_by_name[ + "FileFormat" +] +_BILLINGREPORT_BILLINGREPORTSTATE = _BILLINGREPORT.enum_types_by_name[ + "BillingReportState" +] +BillingReportSpec = _reflection.GeneratedProtocolMessageType( + "BillingReportSpec", + (_message.Message,), + { + "DESCRIPTOR": _BILLINGREPORTSPEC, + "__module__": "temporalio.api.cloud.billing.v1.message_pb2", + # @@protoc_insertion_point(class_scope:temporal.api.cloud.billing.v1.BillingReportSpec) + }, +) +_sym_db.RegisterMessage(BillingReportSpec) + +BillingReport = _reflection.GeneratedProtocolMessageType( + "BillingReport", + (_message.Message,), + { + "Download": _reflection.GeneratedProtocolMessageType( + "Download", + (_message.Message,), + { + "DESCRIPTOR": _BILLINGREPORT_DOWNLOAD, + "__module__": "temporalio.api.cloud.billing.v1.message_pb2", + # @@protoc_insertion_point(class_scope:temporal.api.cloud.billing.v1.BillingReport.Download) + }, + ), + "DESCRIPTOR": _BILLINGREPORT, + "__module__": "temporalio.api.cloud.billing.v1.message_pb2", + # @@protoc_insertion_point(class_scope:temporal.api.cloud.billing.v1.BillingReport) + }, +) +_sym_db.RegisterMessage(BillingReport) +_sym_db.RegisterMessage(BillingReport.Download) + +if _descriptor._USE_C_DESCRIPTORS == False: + DESCRIPTOR._options = None + DESCRIPTOR._serialized_options = b"\n io.temporal.api.cloud.billing.v1B\014MessageProtoP\001Z+go.temporal.io/api/cloud/billing/v1;billing\252\002\037Temporalio.Api.Cloud.Billing.V1\352\002#Temporalio::Api::Cloud::Billing::V1" + _BILLINGREPORTSPEC._serialized_start = 144 + _BILLINGREPORTSPEC._serialized_end = 367 + _BILLINGREPORT._serialized_start = 370 + _BILLINGREPORT._serialized_end = 1178 + _BILLINGREPORT_DOWNLOAD._serialized_start = 754 + _BILLINGREPORT_DOWNLOAD._serialized_end = 1010 + _BILLINGREPORT_DOWNLOAD_FILEFORMAT._serialized_start = 948 + _BILLINGREPORT_DOWNLOAD_FILEFORMAT._serialized_end = 1010 + _BILLINGREPORT_BILLINGREPORTSTATE._serialized_start = 1013 + _BILLINGREPORT_BILLINGREPORTSTATE._serialized_end = 1178 +# @@protoc_insertion_point(module_scope) diff --git a/temporalio/api/cloud/billing/v1/message_pb2.pyi b/temporalio/api/cloud/billing/v1/message_pb2.pyi new file mode 100644 index 000000000..8a9f262b1 --- /dev/null +++ b/temporalio/api/cloud/billing/v1/message_pb2.pyi @@ -0,0 +1,250 @@ +""" +@generated by mypy-protobuf. Do not edit manually! +isort:skip_file +""" + +import builtins +import collections.abc +import sys +import typing + +import google.protobuf.descriptor +import google.protobuf.duration_pb2 +import google.protobuf.internal.containers +import google.protobuf.internal.enum_type_wrapper +import google.protobuf.message +import google.protobuf.timestamp_pb2 + +if sys.version_info >= (3, 10): + import typing as typing_extensions +else: + import typing_extensions + +DESCRIPTOR: google.protobuf.descriptor.FileDescriptor + +class BillingReportSpec(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + START_TIME_INCLUSIVE_FIELD_NUMBER: builtins.int + END_TIME_EXCLUSIVE_FIELD_NUMBER: builtins.int + DOWNLOAD_URL_EXPIRATION_DURATION_FIELD_NUMBER: builtins.int + DESCRIPTION_FIELD_NUMBER: builtins.int + @property + def start_time_inclusive(self) -> google.protobuf.timestamp_pb2.Timestamp: + """The start time of the billing report (in UTC).""" + @property + def end_time_exclusive(self) -> google.protobuf.timestamp_pb2.Timestamp: + """The end time of the billing report (in UTC).""" + @property + def download_url_expiration_duration(self) -> google.protobuf.duration_pb2.Duration: + """The duration after which the download url will expire. + Optional, default is 5 minutes and maximum is 1 hour. + """ + description: builtins.str + """The description for the billing report. + Optional, default is empty. + """ + def __init__( + self, + *, + start_time_inclusive: google.protobuf.timestamp_pb2.Timestamp | None = ..., + end_time_exclusive: google.protobuf.timestamp_pb2.Timestamp | None = ..., + download_url_expiration_duration: google.protobuf.duration_pb2.Duration + | None = ..., + description: builtins.str = ..., + ) -> None: ... + def HasField( + self, + field_name: typing_extensions.Literal[ + "download_url_expiration_duration", + b"download_url_expiration_duration", + "end_time_exclusive", + b"end_time_exclusive", + "start_time_inclusive", + b"start_time_inclusive", + ], + ) -> builtins.bool: ... + def ClearField( + self, + field_name: typing_extensions.Literal[ + "description", + b"description", + "download_url_expiration_duration", + b"download_url_expiration_duration", + "end_time_exclusive", + b"end_time_exclusive", + "start_time_inclusive", + b"start_time_inclusive", + ], + ) -> None: ... + +global___BillingReportSpec = BillingReportSpec + +class BillingReport(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + class _BillingReportState: + ValueType = typing.NewType("ValueType", builtins.int) + V: typing_extensions.TypeAlias = ValueType + + class _BillingReportStateEnumTypeWrapper( + google.protobuf.internal.enum_type_wrapper._EnumTypeWrapper[ + BillingReport._BillingReportState.ValueType + ], + builtins.type, + ): # noqa: F821 + DESCRIPTOR: google.protobuf.descriptor.EnumDescriptor + BILLING_REPORT_STATE_UNSPECIFIED: ( + BillingReport._BillingReportState.ValueType + ) # 0 + BILLING_REPORT_STATE_IN_PROGRESS: ( + BillingReport._BillingReportState.ValueType + ) # 1 + BILLING_REPORT_STATE_GENERATED: BillingReport._BillingReportState.ValueType # 2 + BILLING_REPORT_STATE_FAILED: BillingReport._BillingReportState.ValueType # 3 + + class BillingReportState( + _BillingReportState, metaclass=_BillingReportStateEnumTypeWrapper + ): ... + BILLING_REPORT_STATE_UNSPECIFIED: BillingReport.BillingReportState.ValueType # 0 + BILLING_REPORT_STATE_IN_PROGRESS: BillingReport.BillingReportState.ValueType # 1 + BILLING_REPORT_STATE_GENERATED: BillingReport.BillingReportState.ValueType # 2 + BILLING_REPORT_STATE_FAILED: BillingReport.BillingReportState.ValueType # 3 + + class Download(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + class _FileFormat: + ValueType = typing.NewType("ValueType", builtins.int) + V: typing_extensions.TypeAlias = ValueType + + class _FileFormatEnumTypeWrapper( + google.protobuf.internal.enum_type_wrapper._EnumTypeWrapper[ + BillingReport.Download._FileFormat.ValueType + ], + builtins.type, + ): # noqa: F821 + DESCRIPTOR: google.protobuf.descriptor.EnumDescriptor + FILE_FORMAT_UNSPECIFIED: BillingReport.Download._FileFormat.ValueType # 0 + FILE_FORMAT_CSV: BillingReport.Download._FileFormat.ValueType # 1 + + class FileFormat(_FileFormat, metaclass=_FileFormatEnumTypeWrapper): ... + FILE_FORMAT_UNSPECIFIED: BillingReport.Download.FileFormat.ValueType # 0 + FILE_FORMAT_CSV: BillingReport.Download.FileFormat.ValueType # 1 + + URL_FIELD_NUMBER: builtins.int + URL_EXPIRATION_TIME_FIELD_NUMBER: builtins.int + FILE_FORMAT_FIELD_NUMBER: builtins.int + FILE_SIZE_BYTES_FIELD_NUMBER: builtins.int + url: builtins.str + """The download url.""" + @property + def url_expiration_time(self) -> google.protobuf.timestamp_pb2.Timestamp: + """The time when the download url will expire.""" + file_format: global___BillingReport.Download.FileFormat.ValueType + """The file format of the billing report""" + file_size_bytes: builtins.int + """The size of the file in bytes. Useful for pre-allocating space, progress indicators, etc.""" + def __init__( + self, + *, + url: builtins.str = ..., + url_expiration_time: google.protobuf.timestamp_pb2.Timestamp | None = ..., + file_format: global___BillingReport.Download.FileFormat.ValueType = ..., + file_size_bytes: builtins.int = ..., + ) -> None: ... + def HasField( + self, + field_name: typing_extensions.Literal[ + "url_expiration_time", b"url_expiration_time" + ], + ) -> builtins.bool: ... + def ClearField( + self, + field_name: typing_extensions.Literal[ + "file_format", + b"file_format", + "file_size_bytes", + b"file_size_bytes", + "url", + b"url", + "url_expiration_time", + b"url_expiration_time", + ], + ) -> None: ... + + ID_FIELD_NUMBER: builtins.int + STATE_FIELD_NUMBER: builtins.int + SPEC_FIELD_NUMBER: builtins.int + DOWNLOAD_INFO_FIELD_NUMBER: builtins.int + REQUESTED_TIME_FIELD_NUMBER: builtins.int + GENERATED_TIME_FIELD_NUMBER: builtins.int + ASYNC_OPERATION_ID_FIELD_NUMBER: builtins.int + id: builtins.str + """The id of the billing report.""" + state: global___BillingReport.BillingReportState.ValueType + """The current state of the billing report.""" + @property + def spec(self) -> global___BillingReportSpec: + """The spec used to generate this billing report.""" + @property + def download_info( + self, + ) -> google.protobuf.internal.containers.RepeatedCompositeFieldContainer[ + global___BillingReport.Download + ]: + """The download information for the billing report. + For future-proofness this is repeated as we may return multiple files (e.g. csv+meta/json, split by size/date, etc.) + """ + @property + def requested_time(self) -> google.protobuf.timestamp_pb2.Timestamp: + """The date and time when the billing report was requested.""" + @property + def generated_time(self) -> google.protobuf.timestamp_pb2.Timestamp: + """The date and time when the billing report generation completed.""" + async_operation_id: builtins.str + """The async operation id associated with the billing report generation.""" + def __init__( + self, + *, + id: builtins.str = ..., + state: global___BillingReport.BillingReportState.ValueType = ..., + spec: global___BillingReportSpec | None = ..., + download_info: collections.abc.Iterable[global___BillingReport.Download] + | None = ..., + requested_time: google.protobuf.timestamp_pb2.Timestamp | None = ..., + generated_time: google.protobuf.timestamp_pb2.Timestamp | None = ..., + async_operation_id: builtins.str = ..., + ) -> None: ... + def HasField( + self, + field_name: typing_extensions.Literal[ + "generated_time", + b"generated_time", + "requested_time", + b"requested_time", + "spec", + b"spec", + ], + ) -> builtins.bool: ... + def ClearField( + self, + field_name: typing_extensions.Literal[ + "async_operation_id", + b"async_operation_id", + "download_info", + b"download_info", + "generated_time", + b"generated_time", + "id", + b"id", + "requested_time", + b"requested_time", + "spec", + b"spec", + "state", + b"state", + ], + ) -> None: ... + +global___BillingReport = BillingReport diff --git a/temporalio/api/cloud/cloudservice/v1/__init__.py b/temporalio/api/cloud/cloudservice/v1/__init__.py index 293d6b837..022ee05cb 100644 --- a/temporalio/api/cloud/cloudservice/v1/__init__.py +++ b/temporalio/api/cloud/cloudservice/v1/__init__.py @@ -3,8 +3,12 @@ AddNamespaceRegionResponse, AddUserGroupMemberRequest, AddUserGroupMemberResponse, + CreateAccountAuditLogSinkRequest, + CreateAccountAuditLogSinkResponse, CreateApiKeyRequest, CreateApiKeyResponse, + CreateBillingReportRequest, + CreateBillingReportResponse, CreateConnectivityRuleRequest, CreateConnectivityRuleResponse, CreateNamespaceExportSinkRequest, @@ -19,6 +23,8 @@ CreateUserGroupResponse, CreateUserRequest, CreateUserResponse, + DeleteAccountAuditLogSinkRequest, + DeleteAccountAuditLogSinkResponse, DeleteApiKeyRequest, DeleteApiKeyResponse, DeleteConnectivityRuleRequest, @@ -39,6 +45,10 @@ DeleteUserResponse, FailoverNamespaceRegionRequest, FailoverNamespaceRegionResponse, + GetAccountAuditLogSinkRequest, + GetAccountAuditLogSinkResponse, + GetAccountAuditLogSinksRequest, + GetAccountAuditLogSinksResponse, GetAccountRequest, GetAccountResponse, GetApiKeyRequest, @@ -47,10 +57,18 @@ GetApiKeysResponse, GetAsyncOperationRequest, GetAsyncOperationResponse, + GetAuditLogsRequest, + GetAuditLogsResponse, + GetBillingReportRequest, + GetBillingReportResponse, GetConnectivityRuleRequest, GetConnectivityRuleResponse, GetConnectivityRulesRequest, GetConnectivityRulesResponse, + GetCurrentIdentityRequest, + GetCurrentIdentityResponse, + GetNamespaceCapacityInfoRequest, + GetNamespaceCapacityInfoResponse, GetNamespaceExportSinkRequest, GetNamespaceExportSinkResponse, GetNamespaceExportSinksRequest, @@ -93,6 +111,8 @@ SetUserGroupNamespaceAccessResponse, SetUserNamespaceAccessRequest, SetUserNamespaceAccessResponse, + UpdateAccountAuditLogSinkRequest, + UpdateAccountAuditLogSinkResponse, UpdateAccountRequest, UpdateAccountResponse, UpdateApiKeyRequest, @@ -122,8 +142,12 @@ "AddNamespaceRegionResponse", "AddUserGroupMemberRequest", "AddUserGroupMemberResponse", + "CreateAccountAuditLogSinkRequest", + "CreateAccountAuditLogSinkResponse", "CreateApiKeyRequest", "CreateApiKeyResponse", + "CreateBillingReportRequest", + "CreateBillingReportResponse", "CreateConnectivityRuleRequest", "CreateConnectivityRuleResponse", "CreateNamespaceExportSinkRequest", @@ -138,6 +162,8 @@ "CreateUserGroupResponse", "CreateUserRequest", "CreateUserResponse", + "DeleteAccountAuditLogSinkRequest", + "DeleteAccountAuditLogSinkResponse", "DeleteApiKeyRequest", "DeleteApiKeyResponse", "DeleteConnectivityRuleRequest", @@ -158,6 +184,10 @@ "DeleteUserResponse", "FailoverNamespaceRegionRequest", "FailoverNamespaceRegionResponse", + "GetAccountAuditLogSinkRequest", + "GetAccountAuditLogSinkResponse", + "GetAccountAuditLogSinksRequest", + "GetAccountAuditLogSinksResponse", "GetAccountRequest", "GetAccountResponse", "GetApiKeyRequest", @@ -166,10 +196,18 @@ "GetApiKeysResponse", "GetAsyncOperationRequest", "GetAsyncOperationResponse", + "GetAuditLogsRequest", + "GetAuditLogsResponse", + "GetBillingReportRequest", + "GetBillingReportResponse", "GetConnectivityRuleRequest", "GetConnectivityRuleResponse", "GetConnectivityRulesRequest", "GetConnectivityRulesResponse", + "GetCurrentIdentityRequest", + "GetCurrentIdentityResponse", + "GetNamespaceCapacityInfoRequest", + "GetNamespaceCapacityInfoResponse", "GetNamespaceExportSinkRequest", "GetNamespaceExportSinkResponse", "GetNamespaceExportSinksRequest", @@ -212,6 +250,8 @@ "SetUserGroupNamespaceAccessResponse", "SetUserNamespaceAccessRequest", "SetUserNamespaceAccessResponse", + "UpdateAccountAuditLogSinkRequest", + "UpdateAccountAuditLogSinkResponse", "UpdateAccountRequest", "UpdateAccountResponse", "UpdateApiKeyRequest", diff --git a/temporalio/api/cloud/cloudservice/v1/request_response_pb2.py b/temporalio/api/cloud/cloudservice/v1/request_response_pb2.py index 589d4c4f9..23f1b7fad 100644 --- a/temporalio/api/cloud/cloudservice/v1/request_response_pb2.py +++ b/temporalio/api/cloud/cloudservice/v1/request_response_pb2.py @@ -19,6 +19,12 @@ from temporalio.api.cloud.account.v1 import ( message_pb2 as temporal_dot_api_dot_cloud_dot_account_dot_v1_dot_message__pb2, ) +from temporalio.api.cloud.auditlog.v1 import ( + message_pb2 as temporal_dot_api_dot_cloud_dot_auditlog_dot_v1_dot_message__pb2, +) +from temporalio.api.cloud.billing.v1 import ( + message_pb2 as temporal_dot_api_dot_cloud_dot_billing_dot_v1_dot_message__pb2, +) from temporalio.api.cloud.connectivityrule.v1 import ( message_pb2 as temporal_dot_api_dot_cloud_dot_connectivityrule_dot_v1_dot_message__pb2, ) @@ -42,10 +48,16 @@ ) DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile( - b'\n9temporal/api/cloud/cloudservice/v1/request_response.proto\x12"temporal.api.cloud.cloudservice.v1\x1a\x1fgoogle/protobuf/timestamp.proto\x1a-temporal/api/cloud/operation/v1/message.proto\x1a,temporal/api/cloud/identity/v1/message.proto\x1a-temporal/api/cloud/namespace/v1/message.proto\x1a)temporal/api/cloud/nexus/v1/message.proto\x1a*temporal/api/cloud/region/v1/message.proto\x1a+temporal/api/cloud/account/v1/message.proto\x1a)temporal/api/cloud/usage/v1/message.proto\x1a\x34temporal/api/cloud/connectivityrule/v1/message.proto"Z\n\x0fGetUsersRequest\x12\x11\n\tpage_size\x18\x01 \x01(\x05\x12\x12\n\npage_token\x18\x02 \x01(\t\x12\r\n\x05\x65mail\x18\x03 \x01(\t\x12\x11\n\tnamespace\x18\x04 \x01(\t"`\n\x10GetUsersResponse\x12\x33\n\x05users\x18\x01 \x03(\x0b\x32$.temporal.api.cloud.identity.v1.User\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\t"!\n\x0eGetUserRequest\x12\x0f\n\x07user_id\x18\x01 \x01(\t"E\n\x0fGetUserResponse\x12\x32\n\x04user\x18\x01 \x01(\x0b\x32$.temporal.api.cloud.identity.v1.User"g\n\x11\x43reateUserRequest\x12\x36\n\x04spec\x18\x01 \x01(\x0b\x32(.temporal.api.cloud.identity.v1.UserSpec\x12\x1a\n\x12\x61sync_operation_id\x18\x02 \x01(\t"o\n\x12\x43reateUserResponse\x12\x0f\n\x07user_id\x18\x01 \x01(\t\x12H\n\x0f\x61sync_operation\x18\x02 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"\x92\x01\n\x11UpdateUserRequest\x12\x0f\n\x07user_id\x18\x01 \x01(\t\x12\x36\n\x04spec\x18\x02 \x01(\x0b\x32(.temporal.api.cloud.identity.v1.UserSpec\x12\x18\n\x10resource_version\x18\x03 \x01(\t\x12\x1a\n\x12\x61sync_operation_id\x18\x04 \x01(\t"^\n\x12UpdateUserResponse\x12H\n\x0f\x61sync_operation\x18\x01 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"Z\n\x11\x44\x65leteUserRequest\x12\x0f\n\x07user_id\x18\x01 \x01(\t\x12\x18\n\x10resource_version\x18\x02 \x01(\t\x12\x1a\n\x12\x61sync_operation_id\x18\x03 \x01(\t"^\n\x12\x44\x65leteUserResponse\x12H\n\x0f\x61sync_operation\x18\x01 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"\xba\x01\n\x1dSetUserNamespaceAccessRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x0f\n\x07user_id\x18\x02 \x01(\t\x12?\n\x06\x61\x63\x63\x65ss\x18\x03 \x01(\x0b\x32/.temporal.api.cloud.identity.v1.NamespaceAccess\x12\x18\n\x10resource_version\x18\x04 \x01(\t\x12\x1a\n\x12\x61sync_operation_id\x18\x05 \x01(\t"j\n\x1eSetUserNamespaceAccessResponse\x12H\n\x0f\x61sync_operation\x18\x01 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"6\n\x18GetAsyncOperationRequest\x12\x1a\n\x12\x61sync_operation_id\x18\x01 \x01(\t"e\n\x19GetAsyncOperationResponse\x12H\n\x0f\x61sync_operation\x18\x01 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"\xf3\x01\n\x16\x43reateNamespaceRequest\x12<\n\x04spec\x18\x02 \x01(\x0b\x32..temporal.api.cloud.namespace.v1.NamespaceSpec\x12\x1a\n\x12\x61sync_operation_id\x18\x03 \x01(\t\x12R\n\x04tags\x18\x04 \x03(\x0b\x32\x44.temporal.api.cloud.cloudservice.v1.CreateNamespaceRequest.TagsEntry\x1a+\n\tTagsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01"v\n\x17\x43reateNamespaceResponse\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12H\n\x0f\x61sync_operation\x18\x02 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"K\n\x14GetNamespacesRequest\x12\x11\n\tpage_size\x18\x01 \x01(\x05\x12\x12\n\npage_token\x18\x02 \x01(\t\x12\x0c\n\x04name\x18\x03 \x01(\t"p\n\x15GetNamespacesResponse\x12>\n\nnamespaces\x18\x01 \x03(\x0b\x32*.temporal.api.cloud.namespace.v1.Namespace\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\t"(\n\x13GetNamespaceRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t"U\n\x14GetNamespaceResponse\x12=\n\tnamespace\x18\x01 \x01(\x0b\x32*.temporal.api.cloud.namespace.v1.Namespace"\x9f\x01\n\x16UpdateNamespaceRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12<\n\x04spec\x18\x02 \x01(\x0b\x32..temporal.api.cloud.namespace.v1.NamespaceSpec\x12\x18\n\x10resource_version\x18\x03 \x01(\t\x12\x1a\n\x12\x61sync_operation_id\x18\x04 \x01(\t"c\n\x17UpdateNamespaceResponse\x12H\n\x0f\x61sync_operation\x18\x01 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"\xc6\x01\n"RenameCustomSearchAttributeRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12-\n%existing_custom_search_attribute_name\x18\x02 \x01(\t\x12(\n new_custom_search_attribute_name\x18\x03 \x01(\t\x12\x18\n\x10resource_version\x18\x04 \x01(\t\x12\x1a\n\x12\x61sync_operation_id\x18\x05 \x01(\t"o\n#RenameCustomSearchAttributeResponse\x12H\n\x0f\x61sync_operation\x18\x01 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"a\n\x16\x44\x65leteNamespaceRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x18\n\x10resource_version\x18\x02 \x01(\t\x12\x1a\n\x12\x61sync_operation_id\x18\x03 \x01(\t"c\n\x17\x44\x65leteNamespaceResponse\x12H\n\x0f\x61sync_operation\x18\x01 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"_\n\x1e\x46\x61iloverNamespaceRegionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x0e\n\x06region\x18\x02 \x01(\t\x12\x1a\n\x12\x61sync_operation_id\x18\x03 \x01(\t"k\n\x1f\x46\x61iloverNamespaceRegionResponse\x12H\n\x0f\x61sync_operation\x18\x01 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"t\n\x19\x41\x64\x64NamespaceRegionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x0e\n\x06region\x18\x02 \x01(\t\x12\x18\n\x10resource_version\x18\x03 \x01(\t\x12\x1a\n\x12\x61sync_operation_id\x18\x04 \x01(\t"f\n\x1a\x41\x64\x64NamespaceRegionResponse\x12H\n\x0f\x61sync_operation\x18\x01 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"w\n\x1c\x44\x65leteNamespaceRegionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x0e\n\x06region\x18\x02 \x01(\t\x12\x18\n\x10resource_version\x18\x03 \x01(\t\x12\x1a\n\x12\x61sync_operation_id\x18\x04 \x01(\t"i\n\x1d\x44\x65leteNamespaceRegionResponse\x12H\n\x0f\x61sync_operation\x18\x01 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"\x13\n\x11GetRegionsRequest"K\n\x12GetRegionsResponse\x12\x35\n\x07regions\x18\x01 \x03(\x0b\x32$.temporal.api.cloud.region.v1.Region""\n\x10GetRegionRequest\x12\x0e\n\x06region\x18\x01 \x01(\t"I\n\x11GetRegionResponse\x12\x34\n\x06region\x18\x01 \x01(\x0b\x32$.temporal.api.cloud.region.v1.Region"\xae\x01\n\x11GetApiKeysRequest\x12\x11\n\tpage_size\x18\x01 \x01(\x05\x12\x12\n\npage_token\x18\x02 \x01(\t\x12\x10\n\x08owner_id\x18\x03 \x01(\t\x12!\n\x15owner_type_deprecated\x18\x04 \x01(\tB\x02\x18\x01\x12=\n\nowner_type\x18\x05 \x01(\x0e\x32).temporal.api.cloud.identity.v1.OwnerType"g\n\x12GetApiKeysResponse\x12\x38\n\x08\x61pi_keys\x18\x01 \x03(\x0b\x32&.temporal.api.cloud.identity.v1.ApiKey\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\t""\n\x10GetApiKeyRequest\x12\x0e\n\x06key_id\x18\x01 \x01(\t"L\n\x11GetApiKeyResponse\x12\x37\n\x07\x61pi_key\x18\x01 \x01(\x0b\x32&.temporal.api.cloud.identity.v1.ApiKey"k\n\x13\x43reateApiKeyRequest\x12\x38\n\x04spec\x18\x01 \x01(\x0b\x32*.temporal.api.cloud.identity.v1.ApiKeySpec\x12\x1a\n\x12\x61sync_operation_id\x18\x02 \x01(\t"\x7f\n\x14\x43reateApiKeyResponse\x12\x0e\n\x06key_id\x18\x01 \x01(\t\x12\r\n\x05token\x18\x02 \x01(\t\x12H\n\x0f\x61sync_operation\x18\x03 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"\x95\x01\n\x13UpdateApiKeyRequest\x12\x0e\n\x06key_id\x18\x01 \x01(\t\x12\x38\n\x04spec\x18\x02 \x01(\x0b\x32*.temporal.api.cloud.identity.v1.ApiKeySpec\x12\x18\n\x10resource_version\x18\x03 \x01(\t\x12\x1a\n\x12\x61sync_operation_id\x18\x04 \x01(\t"`\n\x14UpdateApiKeyResponse\x12H\n\x0f\x61sync_operation\x18\x01 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"[\n\x13\x44\x65leteApiKeyRequest\x12\x0e\n\x06key_id\x18\x01 \x01(\t\x12\x18\n\x10resource_version\x18\x02 \x01(\t\x12\x1a\n\x12\x61sync_operation_id\x18\x03 \x01(\t"`\n\x14\x44\x65leteApiKeyResponse\x12H\n\x0f\x61sync_operation\x18\x01 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"\x87\x01\n\x18GetNexusEndpointsRequest\x12\x11\n\tpage_size\x18\x01 \x01(\x05\x12\x12\n\npage_token\x18\x02 \x01(\t\x12\x1b\n\x13target_namespace_id\x18\x03 \x01(\t\x12\x19\n\x11target_task_queue\x18\x04 \x01(\t\x12\x0c\n\x04name\x18\x05 \x01(\t"n\n\x19GetNexusEndpointsResponse\x12\x38\n\tendpoints\x18\x01 \x03(\x0b\x32%.temporal.api.cloud.nexus.v1.Endpoint\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\t".\n\x17GetNexusEndpointRequest\x12\x13\n\x0b\x65ndpoint_id\x18\x01 \x01(\t"S\n\x18GetNexusEndpointResponse\x12\x37\n\x08\x65ndpoint\x18\x01 \x01(\x0b\x32%.temporal.api.cloud.nexus.v1.Endpoint"q\n\x1a\x43reateNexusEndpointRequest\x12\x37\n\x04spec\x18\x01 \x01(\x0b\x32).temporal.api.cloud.nexus.v1.EndpointSpec\x12\x1a\n\x12\x61sync_operation_id\x18\x02 \x01(\t"|\n\x1b\x43reateNexusEndpointResponse\x12\x13\n\x0b\x65ndpoint_id\x18\x01 \x01(\t\x12H\n\x0f\x61sync_operation\x18\x02 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"\xa0\x01\n\x1aUpdateNexusEndpointRequest\x12\x13\n\x0b\x65ndpoint_id\x18\x01 \x01(\t\x12\x37\n\x04spec\x18\x02 \x01(\x0b\x32).temporal.api.cloud.nexus.v1.EndpointSpec\x12\x18\n\x10resource_version\x18\x03 \x01(\t\x12\x1a\n\x12\x61sync_operation_id\x18\x04 \x01(\t"g\n\x1bUpdateNexusEndpointResponse\x12H\n\x0f\x61sync_operation\x18\x01 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"g\n\x1a\x44\x65leteNexusEndpointRequest\x12\x13\n\x0b\x65ndpoint_id\x18\x01 \x01(\t\x12\x18\n\x10resource_version\x18\x02 \x01(\t\x12\x1a\n\x12\x61sync_operation_id\x18\x03 \x01(\t"g\n\x1b\x44\x65leteNexusEndpointResponse\x12H\n\x0f\x61sync_operation\x18\x01 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"\xf5\x02\n\x14GetUserGroupsRequest\x12\x11\n\tpage_size\x18\x01 \x01(\x05\x12\x12\n\npage_token\x18\x02 \x01(\t\x12\x11\n\tnamespace\x18\x03 \x01(\t\x12\x14\n\x0c\x64isplay_name\x18\x04 \x01(\t\x12`\n\x0cgoogle_group\x18\x05 \x01(\x0b\x32J.temporal.api.cloud.cloudservice.v1.GetUserGroupsRequest.GoogleGroupFilter\x12\\\n\nscim_group\x18\x06 \x01(\x0b\x32H.temporal.api.cloud.cloudservice.v1.GetUserGroupsRequest.SCIMGroupFilter\x1a*\n\x11GoogleGroupFilter\x12\x15\n\remail_address\x18\x01 \x01(\t\x1a!\n\x0fSCIMGroupFilter\x12\x0e\n\x06idp_id\x18\x01 \x01(\t"k\n\x15GetUserGroupsResponse\x12\x39\n\x06groups\x18\x01 \x03(\x0b\x32).temporal.api.cloud.identity.v1.UserGroup\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\t"\'\n\x13GetUserGroupRequest\x12\x10\n\x08group_id\x18\x01 \x01(\t"P\n\x14GetUserGroupResponse\x12\x38\n\x05group\x18\x01 \x01(\x0b\x32).temporal.api.cloud.identity.v1.UserGroup"q\n\x16\x43reateUserGroupRequest\x12;\n\x04spec\x18\x01 \x01(\x0b\x32-.temporal.api.cloud.identity.v1.UserGroupSpec\x12\x1a\n\x12\x61sync_operation_id\x18\x02 \x01(\t"u\n\x17\x43reateUserGroupResponse\x12\x10\n\x08group_id\x18\x01 \x01(\t\x12H\n\x0f\x61sync_operation\x18\x02 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"\x9d\x01\n\x16UpdateUserGroupRequest\x12\x10\n\x08group_id\x18\x01 \x01(\t\x12;\n\x04spec\x18\x02 \x01(\x0b\x32-.temporal.api.cloud.identity.v1.UserGroupSpec\x12\x18\n\x10resource_version\x18\x03 \x01(\t\x12\x1a\n\x12\x61sync_operation_id\x18\x04 \x01(\t"c\n\x17UpdateUserGroupResponse\x12H\n\x0f\x61sync_operation\x18\x01 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"`\n\x16\x44\x65leteUserGroupRequest\x12\x10\n\x08group_id\x18\x01 \x01(\t\x12\x18\n\x10resource_version\x18\x02 \x01(\t\x12\x1a\n\x12\x61sync_operation_id\x18\x03 \x01(\t"c\n\x17\x44\x65leteUserGroupResponse\x12H\n\x0f\x61sync_operation\x18\x01 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"\xc0\x01\n"SetUserGroupNamespaceAccessRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x10\n\x08group_id\x18\x02 \x01(\t\x12?\n\x06\x61\x63\x63\x65ss\x18\x03 \x01(\x0b\x32/.temporal.api.cloud.identity.v1.NamespaceAccess\x12\x18\n\x10resource_version\x18\x04 \x01(\t\x12\x1a\n\x12\x61sync_operation_id\x18\x05 \x01(\t"o\n#SetUserGroupNamespaceAccessResponse\x12H\n\x0f\x61sync_operation\x18\x01 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"\x8f\x01\n\x19\x41\x64\x64UserGroupMemberRequest\x12\x10\n\x08group_id\x18\x01 \x01(\t\x12\x44\n\tmember_id\x18\x02 \x01(\x0b\x32\x31.temporal.api.cloud.identity.v1.UserGroupMemberId\x12\x1a\n\x12\x61sync_operation_id\x18\x03 \x01(\t"f\n\x1a\x41\x64\x64UserGroupMemberResponse\x12H\n\x0f\x61sync_operation\x18\x01 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"\x92\x01\n\x1cRemoveUserGroupMemberRequest\x12\x10\n\x08group_id\x18\x01 \x01(\t\x12\x44\n\tmember_id\x18\x02 \x01(\x0b\x32\x31.temporal.api.cloud.identity.v1.UserGroupMemberId\x12\x1a\n\x12\x61sync_operation_id\x18\x03 \x01(\t"i\n\x1dRemoveUserGroupMemberResponse\x12H\n\x0f\x61sync_operation\x18\x01 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"U\n\x1aGetUserGroupMembersRequest\x12\x11\n\tpage_size\x18\x01 \x01(\x05\x12\x12\n\npage_token\x18\x02 \x01(\t\x12\x10\n\x08group_id\x18\x03 \x01(\t"x\n\x1bGetUserGroupMembersResponse\x12@\n\x07members\x18\x01 \x03(\x0b\x32/.temporal.api.cloud.identity.v1.UserGroupMember\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\t"{\n\x1b\x43reateServiceAccountRequest\x12@\n\x04spec\x18\x01 \x01(\x0b\x32\x32.temporal.api.cloud.identity.v1.ServiceAccountSpec\x12\x1a\n\x12\x61sync_operation_id\x18\x02 \x01(\t"\x84\x01\n\x1c\x43reateServiceAccountResponse\x12\x1a\n\x12service_account_id\x18\x01 \x01(\t\x12H\n\x0f\x61sync_operation\x18\x02 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"6\n\x18GetServiceAccountRequest\x12\x1a\n\x12service_account_id\x18\x01 \x01(\t"d\n\x19GetServiceAccountResponse\x12G\n\x0fservice_account\x18\x01 \x01(\x0b\x32..temporal.api.cloud.identity.v1.ServiceAccount"B\n\x19GetServiceAccountsRequest\x12\x11\n\tpage_size\x18\x01 \x01(\x05\x12\x12\n\npage_token\x18\x02 \x01(\t"~\n\x1aGetServiceAccountsResponse\x12G\n\x0fservice_account\x18\x01 \x03(\x0b\x32..temporal.api.cloud.identity.v1.ServiceAccount\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\t"\xb1\x01\n\x1bUpdateServiceAccountRequest\x12\x1a\n\x12service_account_id\x18\x01 \x01(\t\x12@\n\x04spec\x18\x02 \x01(\x0b\x32\x32.temporal.api.cloud.identity.v1.ServiceAccountSpec\x12\x18\n\x10resource_version\x18\x03 \x01(\t\x12\x1a\n\x12\x61sync_operation_id\x18\x04 \x01(\t"h\n\x1cUpdateServiceAccountResponse\x12H\n\x0f\x61sync_operation\x18\x01 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"\xcf\x01\n\'SetServiceAccountNamespaceAccessRequest\x12\x1a\n\x12service_account_id\x18\x01 \x01(\t\x12\x11\n\tnamespace\x18\x02 \x01(\t\x12?\n\x06\x61\x63\x63\x65ss\x18\x03 \x01(\x0b\x32/.temporal.api.cloud.identity.v1.NamespaceAccess\x12\x18\n\x10resource_version\x18\x04 \x01(\t\x12\x1a\n\x12\x61sync_operation_id\x18\x05 \x01(\t"t\n(SetServiceAccountNamespaceAccessResponse\x12H\n\x0f\x61sync_operation\x18\x01 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"o\n\x1b\x44\x65leteServiceAccountRequest\x12\x1a\n\x12service_account_id\x18\x01 \x01(\t\x12\x18\n\x10resource_version\x18\x02 \x01(\t\x12\x1a\n\x12\x61sync_operation_id\x18\x03 \x01(\t"h\n\x1c\x44\x65leteServiceAccountResponse\x12H\n\x0f\x61sync_operation\x18\x01 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"\xaa\x01\n\x0fGetUsageRequest\x12\x38\n\x14start_time_inclusive\x18\x01 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x36\n\x12\x65nd_time_exclusive\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x11\n\tpage_size\x18\x03 \x01(\x05\x12\x12\n\npage_token\x18\x04 \x01(\t"d\n\x10GetUsageResponse\x12\x37\n\tsummaries\x18\x01 \x03(\x0b\x32$.temporal.api.cloud.usage.v1.Summary\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\t"\x13\n\x11GetAccountRequest"M\n\x12GetAccountResponse\x12\x37\n\x07\x61\x63\x63ount\x18\x01 \x01(\x0b\x32&.temporal.api.cloud.account.v1.Account"\x86\x01\n\x14UpdateAccountRequest\x12\x38\n\x04spec\x18\x01 \x01(\x0b\x32*.temporal.api.cloud.account.v1.AccountSpec\x12\x18\n\x10resource_version\x18\x02 \x01(\t\x12\x1a\n\x12\x61sync_operation_id\x18\x03 \x01(\t"a\n\x15UpdateAccountResponse\x12H\n\x0f\x61sync_operation\x18\x01 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"\x90\x01\n CreateNamespaceExportSinkRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12=\n\x04spec\x18\x02 \x01(\x0b\x32/.temporal.api.cloud.namespace.v1.ExportSinkSpec\x12\x1a\n\x12\x61sync_operation_id\x18\x03 \x01(\t"m\n!CreateNamespaceExportSinkResponse\x12H\n\x0f\x61sync_operation\x18\x01 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"@\n\x1dGetNamespaceExportSinkRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x0c\n\x04name\x18\x02 \x01(\t"[\n\x1eGetNamespaceExportSinkResponse\x12\x39\n\x04sink\x18\x01 \x01(\x0b\x32+.temporal.api.cloud.namespace.v1.ExportSink"Z\n\x1eGetNamespaceExportSinksRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x11\n\tpage_size\x18\x02 \x01(\x05\x12\x12\n\npage_token\x18\x03 \x01(\t"v\n\x1fGetNamespaceExportSinksResponse\x12:\n\x05sinks\x18\x01 \x03(\x0b\x32+.temporal.api.cloud.namespace.v1.ExportSink\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\t"\xaa\x01\n UpdateNamespaceExportSinkRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12=\n\x04spec\x18\x02 \x01(\x0b\x32/.temporal.api.cloud.namespace.v1.ExportSinkSpec\x12\x18\n\x10resource_version\x18\x03 \x01(\t\x12\x1a\n\x12\x61sync_operation_id\x18\x04 \x01(\t"m\n!UpdateNamespaceExportSinkResponse\x12H\n\x0f\x61sync_operation\x18\x01 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"y\n DeleteNamespaceExportSinkRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x0c\n\x04name\x18\x02 \x01(\t\x12\x18\n\x10resource_version\x18\x03 \x01(\t\x12\x1a\n\x12\x61sync_operation_id\x18\x04 \x01(\t"m\n!DeleteNamespaceExportSinkResponse\x12H\n\x0f\x61sync_operation\x18\x01 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"v\n"ValidateNamespaceExportSinkRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12=\n\x04spec\x18\x02 \x01(\x0b\x32/.temporal.api.cloud.namespace.v1.ExportSinkSpec"%\n#ValidateNamespaceExportSinkResponse"\x82\x02\n\x1aUpdateNamespaceTagsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12h\n\x0etags_to_upsert\x18\x02 \x03(\x0b\x32P.temporal.api.cloud.cloudservice.v1.UpdateNamespaceTagsRequest.TagsToUpsertEntry\x12\x16\n\x0etags_to_remove\x18\x03 \x03(\t\x12\x1a\n\x12\x61sync_operation_id\x18\x04 \x01(\t\x1a\x33\n\x11TagsToUpsertEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01"g\n\x1bUpdateNamespaceTagsResponse\x12H\n\x0f\x61sync_operation\x18\x01 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"\x87\x01\n\x1d\x43reateConnectivityRuleRequest\x12J\n\x04spec\x18\x01 \x01(\x0b\x32<.temporal.api.cloud.connectivityrule.v1.ConnectivityRuleSpec\x12\x1a\n\x12\x61sync_operation_id\x18\x02 \x01(\t"\x88\x01\n\x1e\x43reateConnectivityRuleResponse\x12\x1c\n\x14\x63onnectivity_rule_id\x18\x01 \x01(\t\x12H\n\x0f\x61sync_operation\x18\x02 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation":\n\x1aGetConnectivityRuleRequest\x12\x1c\n\x14\x63onnectivity_rule_id\x18\x01 \x01(\t"r\n\x1bGetConnectivityRuleResponse\x12S\n\x11\x63onnectivity_rule\x18\x01 \x01(\x0b\x32\x38.temporal.api.cloud.connectivityrule.v1.ConnectivityRule"W\n\x1bGetConnectivityRulesRequest\x12\x11\n\tpage_size\x18\x01 \x01(\x05\x12\x12\n\npage_token\x18\x02 \x01(\t\x12\x11\n\tnamespace\x18\x03 \x01(\t"\x8d\x01\n\x1cGetConnectivityRulesResponse\x12T\n\x12\x63onnectivity_rules\x18\x01 \x03(\x0b\x32\x38.temporal.api.cloud.connectivityrule.v1.ConnectivityRule\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\t"s\n\x1d\x44\x65leteConnectivityRuleRequest\x12\x1c\n\x14\x63onnectivity_rule_id\x18\x01 \x01(\t\x12\x18\n\x10resource_version\x18\x02 \x01(\t\x12\x1a\n\x12\x61sync_operation_id\x18\x03 \x01(\t"j\n\x1e\x44\x65leteConnectivityRuleResponse\x12H\n\x0f\x61sync_operation\x18\x01 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"c\n"ValidateAccountAuditLogSinkRequest\x12=\n\x04spec\x18\x01 \x01(\x0b\x32/.temporal.api.cloud.account.v1.AuditLogSinkSpec"%\n#ValidateAccountAuditLogSinkResponseB\xc8\x01\n%io.temporal.api.cloud.cloudservice.v1B\x14RequestResponseProtoP\x01Z5go.temporal.io/api/cloud/cloudservice/v1;cloudservice\xaa\x02$Temporalio.Api.Cloud.CloudService.V1\xea\x02(Temporalio::Api::Cloud::CloudService::V1b\x06proto3' + b'\n9temporal/api/cloud/cloudservice/v1/request_response.proto\x12"temporal.api.cloud.cloudservice.v1\x1a\x1fgoogle/protobuf/timestamp.proto\x1a-temporal/api/cloud/operation/v1/message.proto\x1a,temporal/api/cloud/identity/v1/message.proto\x1a-temporal/api/cloud/namespace/v1/message.proto\x1a)temporal/api/cloud/nexus/v1/message.proto\x1a*temporal/api/cloud/region/v1/message.proto\x1a+temporal/api/cloud/account/v1/message.proto\x1a)temporal/api/cloud/usage/v1/message.proto\x1a\x34temporal/api/cloud/connectivityrule/v1/message.proto\x1a,temporal/api/cloud/auditlog/v1/message.proto\x1a+temporal/api/cloud/billing/v1/message.proto"\x1b\n\x19GetCurrentIdentityRequest"\xed\x01\n\x1aGetCurrentIdentityResponse\x12\x34\n\x04user\x18\x01 \x01(\x0b\x32$.temporal.api.cloud.identity.v1.UserH\x00\x12I\n\x0fservice_account\x18\x02 \x01(\x0b\x32..temporal.api.cloud.identity.v1.ServiceAccountH\x00\x12\x41\n\x11principal_api_key\x18\x03 \x01(\x0b\x32&.temporal.api.cloud.identity.v1.ApiKeyB\x0b\n\tprincipal"Z\n\x0fGetUsersRequest\x12\x11\n\tpage_size\x18\x01 \x01(\x05\x12\x12\n\npage_token\x18\x02 \x01(\t\x12\r\n\x05\x65mail\x18\x03 \x01(\t\x12\x11\n\tnamespace\x18\x04 \x01(\t"`\n\x10GetUsersResponse\x12\x33\n\x05users\x18\x01 \x03(\x0b\x32$.temporal.api.cloud.identity.v1.User\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\t"!\n\x0eGetUserRequest\x12\x0f\n\x07user_id\x18\x01 \x01(\t"E\n\x0fGetUserResponse\x12\x32\n\x04user\x18\x01 \x01(\x0b\x32$.temporal.api.cloud.identity.v1.User"g\n\x11\x43reateUserRequest\x12\x36\n\x04spec\x18\x01 \x01(\x0b\x32(.temporal.api.cloud.identity.v1.UserSpec\x12\x1a\n\x12\x61sync_operation_id\x18\x02 \x01(\t"o\n\x12\x43reateUserResponse\x12\x0f\n\x07user_id\x18\x01 \x01(\t\x12H\n\x0f\x61sync_operation\x18\x02 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"\x92\x01\n\x11UpdateUserRequest\x12\x0f\n\x07user_id\x18\x01 \x01(\t\x12\x36\n\x04spec\x18\x02 \x01(\x0b\x32(.temporal.api.cloud.identity.v1.UserSpec\x12\x18\n\x10resource_version\x18\x03 \x01(\t\x12\x1a\n\x12\x61sync_operation_id\x18\x04 \x01(\t"^\n\x12UpdateUserResponse\x12H\n\x0f\x61sync_operation\x18\x01 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"Z\n\x11\x44\x65leteUserRequest\x12\x0f\n\x07user_id\x18\x01 \x01(\t\x12\x18\n\x10resource_version\x18\x02 \x01(\t\x12\x1a\n\x12\x61sync_operation_id\x18\x03 \x01(\t"^\n\x12\x44\x65leteUserResponse\x12H\n\x0f\x61sync_operation\x18\x01 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"\xba\x01\n\x1dSetUserNamespaceAccessRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x0f\n\x07user_id\x18\x02 \x01(\t\x12?\n\x06\x61\x63\x63\x65ss\x18\x03 \x01(\x0b\x32/.temporal.api.cloud.identity.v1.NamespaceAccess\x12\x18\n\x10resource_version\x18\x04 \x01(\t\x12\x1a\n\x12\x61sync_operation_id\x18\x05 \x01(\t"j\n\x1eSetUserNamespaceAccessResponse\x12H\n\x0f\x61sync_operation\x18\x01 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"6\n\x18GetAsyncOperationRequest\x12\x1a\n\x12\x61sync_operation_id\x18\x01 \x01(\t"e\n\x19GetAsyncOperationResponse\x12H\n\x0f\x61sync_operation\x18\x01 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"\xf3\x01\n\x16\x43reateNamespaceRequest\x12<\n\x04spec\x18\x02 \x01(\x0b\x32..temporal.api.cloud.namespace.v1.NamespaceSpec\x12\x1a\n\x12\x61sync_operation_id\x18\x03 \x01(\t\x12R\n\x04tags\x18\x04 \x03(\x0b\x32\x44.temporal.api.cloud.cloudservice.v1.CreateNamespaceRequest.TagsEntry\x1a+\n\tTagsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01"v\n\x17\x43reateNamespaceResponse\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12H\n\x0f\x61sync_operation\x18\x02 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"K\n\x14GetNamespacesRequest\x12\x11\n\tpage_size\x18\x01 \x01(\x05\x12\x12\n\npage_token\x18\x02 \x01(\t\x12\x0c\n\x04name\x18\x03 \x01(\t"p\n\x15GetNamespacesResponse\x12>\n\nnamespaces\x18\x01 \x03(\x0b\x32*.temporal.api.cloud.namespace.v1.Namespace\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\t"(\n\x13GetNamespaceRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t"U\n\x14GetNamespaceResponse\x12=\n\tnamespace\x18\x01 \x01(\x0b\x32*.temporal.api.cloud.namespace.v1.Namespace"\x9f\x01\n\x16UpdateNamespaceRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12<\n\x04spec\x18\x02 \x01(\x0b\x32..temporal.api.cloud.namespace.v1.NamespaceSpec\x12\x18\n\x10resource_version\x18\x03 \x01(\t\x12\x1a\n\x12\x61sync_operation_id\x18\x04 \x01(\t"c\n\x17UpdateNamespaceResponse\x12H\n\x0f\x61sync_operation\x18\x01 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"\xc6\x01\n"RenameCustomSearchAttributeRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12-\n%existing_custom_search_attribute_name\x18\x02 \x01(\t\x12(\n new_custom_search_attribute_name\x18\x03 \x01(\t\x12\x18\n\x10resource_version\x18\x04 \x01(\t\x12\x1a\n\x12\x61sync_operation_id\x18\x05 \x01(\t"o\n#RenameCustomSearchAttributeResponse\x12H\n\x0f\x61sync_operation\x18\x01 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"a\n\x16\x44\x65leteNamespaceRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x18\n\x10resource_version\x18\x02 \x01(\t\x12\x1a\n\x12\x61sync_operation_id\x18\x03 \x01(\t"c\n\x17\x44\x65leteNamespaceResponse\x12H\n\x0f\x61sync_operation\x18\x01 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"_\n\x1e\x46\x61iloverNamespaceRegionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x0e\n\x06region\x18\x02 \x01(\t\x12\x1a\n\x12\x61sync_operation_id\x18\x03 \x01(\t"k\n\x1f\x46\x61iloverNamespaceRegionResponse\x12H\n\x0f\x61sync_operation\x18\x01 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"t\n\x19\x41\x64\x64NamespaceRegionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x0e\n\x06region\x18\x02 \x01(\t\x12\x18\n\x10resource_version\x18\x03 \x01(\t\x12\x1a\n\x12\x61sync_operation_id\x18\x04 \x01(\t"f\n\x1a\x41\x64\x64NamespaceRegionResponse\x12H\n\x0f\x61sync_operation\x18\x01 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"w\n\x1c\x44\x65leteNamespaceRegionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x0e\n\x06region\x18\x02 \x01(\t\x12\x18\n\x10resource_version\x18\x03 \x01(\t\x12\x1a\n\x12\x61sync_operation_id\x18\x04 \x01(\t"i\n\x1d\x44\x65leteNamespaceRegionResponse\x12H\n\x0f\x61sync_operation\x18\x01 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"\x13\n\x11GetRegionsRequest"K\n\x12GetRegionsResponse\x12\x35\n\x07regions\x18\x01 \x03(\x0b\x32$.temporal.api.cloud.region.v1.Region""\n\x10GetRegionRequest\x12\x0e\n\x06region\x18\x01 \x01(\t"I\n\x11GetRegionResponse\x12\x34\n\x06region\x18\x01 \x01(\x0b\x32$.temporal.api.cloud.region.v1.Region"\xae\x01\n\x11GetApiKeysRequest\x12\x11\n\tpage_size\x18\x01 \x01(\x05\x12\x12\n\npage_token\x18\x02 \x01(\t\x12\x10\n\x08owner_id\x18\x03 \x01(\t\x12!\n\x15owner_type_deprecated\x18\x04 \x01(\tB\x02\x18\x01\x12=\n\nowner_type\x18\x05 \x01(\x0e\x32).temporal.api.cloud.identity.v1.OwnerType"g\n\x12GetApiKeysResponse\x12\x38\n\x08\x61pi_keys\x18\x01 \x03(\x0b\x32&.temporal.api.cloud.identity.v1.ApiKey\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\t""\n\x10GetApiKeyRequest\x12\x0e\n\x06key_id\x18\x01 \x01(\t"L\n\x11GetApiKeyResponse\x12\x37\n\x07\x61pi_key\x18\x01 \x01(\x0b\x32&.temporal.api.cloud.identity.v1.ApiKey"k\n\x13\x43reateApiKeyRequest\x12\x38\n\x04spec\x18\x01 \x01(\x0b\x32*.temporal.api.cloud.identity.v1.ApiKeySpec\x12\x1a\n\x12\x61sync_operation_id\x18\x02 \x01(\t"\x7f\n\x14\x43reateApiKeyResponse\x12\x0e\n\x06key_id\x18\x01 \x01(\t\x12\r\n\x05token\x18\x02 \x01(\t\x12H\n\x0f\x61sync_operation\x18\x03 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"\x95\x01\n\x13UpdateApiKeyRequest\x12\x0e\n\x06key_id\x18\x01 \x01(\t\x12\x38\n\x04spec\x18\x02 \x01(\x0b\x32*.temporal.api.cloud.identity.v1.ApiKeySpec\x12\x18\n\x10resource_version\x18\x03 \x01(\t\x12\x1a\n\x12\x61sync_operation_id\x18\x04 \x01(\t"`\n\x14UpdateApiKeyResponse\x12H\n\x0f\x61sync_operation\x18\x01 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"[\n\x13\x44\x65leteApiKeyRequest\x12\x0e\n\x06key_id\x18\x01 \x01(\t\x12\x18\n\x10resource_version\x18\x02 \x01(\t\x12\x1a\n\x12\x61sync_operation_id\x18\x03 \x01(\t"`\n\x14\x44\x65leteApiKeyResponse\x12H\n\x0f\x61sync_operation\x18\x01 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"\x87\x01\n\x18GetNexusEndpointsRequest\x12\x11\n\tpage_size\x18\x01 \x01(\x05\x12\x12\n\npage_token\x18\x02 \x01(\t\x12\x1b\n\x13target_namespace_id\x18\x03 \x01(\t\x12\x19\n\x11target_task_queue\x18\x04 \x01(\t\x12\x0c\n\x04name\x18\x05 \x01(\t"n\n\x19GetNexusEndpointsResponse\x12\x38\n\tendpoints\x18\x01 \x03(\x0b\x32%.temporal.api.cloud.nexus.v1.Endpoint\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\t".\n\x17GetNexusEndpointRequest\x12\x13\n\x0b\x65ndpoint_id\x18\x01 \x01(\t"S\n\x18GetNexusEndpointResponse\x12\x37\n\x08\x65ndpoint\x18\x01 \x01(\x0b\x32%.temporal.api.cloud.nexus.v1.Endpoint"q\n\x1a\x43reateNexusEndpointRequest\x12\x37\n\x04spec\x18\x01 \x01(\x0b\x32).temporal.api.cloud.nexus.v1.EndpointSpec\x12\x1a\n\x12\x61sync_operation_id\x18\x02 \x01(\t"|\n\x1b\x43reateNexusEndpointResponse\x12\x13\n\x0b\x65ndpoint_id\x18\x01 \x01(\t\x12H\n\x0f\x61sync_operation\x18\x02 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"\xa0\x01\n\x1aUpdateNexusEndpointRequest\x12\x13\n\x0b\x65ndpoint_id\x18\x01 \x01(\t\x12\x37\n\x04spec\x18\x02 \x01(\x0b\x32).temporal.api.cloud.nexus.v1.EndpointSpec\x12\x18\n\x10resource_version\x18\x03 \x01(\t\x12\x1a\n\x12\x61sync_operation_id\x18\x04 \x01(\t"g\n\x1bUpdateNexusEndpointResponse\x12H\n\x0f\x61sync_operation\x18\x01 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"g\n\x1a\x44\x65leteNexusEndpointRequest\x12\x13\n\x0b\x65ndpoint_id\x18\x01 \x01(\t\x12\x18\n\x10resource_version\x18\x02 \x01(\t\x12\x1a\n\x12\x61sync_operation_id\x18\x03 \x01(\t"g\n\x1b\x44\x65leteNexusEndpointResponse\x12H\n\x0f\x61sync_operation\x18\x01 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"\xf5\x02\n\x14GetUserGroupsRequest\x12\x11\n\tpage_size\x18\x01 \x01(\x05\x12\x12\n\npage_token\x18\x02 \x01(\t\x12\x11\n\tnamespace\x18\x03 \x01(\t\x12\x14\n\x0c\x64isplay_name\x18\x04 \x01(\t\x12`\n\x0cgoogle_group\x18\x05 \x01(\x0b\x32J.temporal.api.cloud.cloudservice.v1.GetUserGroupsRequest.GoogleGroupFilter\x12\\\n\nscim_group\x18\x06 \x01(\x0b\x32H.temporal.api.cloud.cloudservice.v1.GetUserGroupsRequest.SCIMGroupFilter\x1a*\n\x11GoogleGroupFilter\x12\x15\n\remail_address\x18\x01 \x01(\t\x1a!\n\x0fSCIMGroupFilter\x12\x0e\n\x06idp_id\x18\x01 \x01(\t"k\n\x15GetUserGroupsResponse\x12\x39\n\x06groups\x18\x01 \x03(\x0b\x32).temporal.api.cloud.identity.v1.UserGroup\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\t"\'\n\x13GetUserGroupRequest\x12\x10\n\x08group_id\x18\x01 \x01(\t"P\n\x14GetUserGroupResponse\x12\x38\n\x05group\x18\x01 \x01(\x0b\x32).temporal.api.cloud.identity.v1.UserGroup"q\n\x16\x43reateUserGroupRequest\x12;\n\x04spec\x18\x01 \x01(\x0b\x32-.temporal.api.cloud.identity.v1.UserGroupSpec\x12\x1a\n\x12\x61sync_operation_id\x18\x02 \x01(\t"u\n\x17\x43reateUserGroupResponse\x12\x10\n\x08group_id\x18\x01 \x01(\t\x12H\n\x0f\x61sync_operation\x18\x02 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"\x9d\x01\n\x16UpdateUserGroupRequest\x12\x10\n\x08group_id\x18\x01 \x01(\t\x12;\n\x04spec\x18\x02 \x01(\x0b\x32-.temporal.api.cloud.identity.v1.UserGroupSpec\x12\x18\n\x10resource_version\x18\x03 \x01(\t\x12\x1a\n\x12\x61sync_operation_id\x18\x04 \x01(\t"c\n\x17UpdateUserGroupResponse\x12H\n\x0f\x61sync_operation\x18\x01 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"`\n\x16\x44\x65leteUserGroupRequest\x12\x10\n\x08group_id\x18\x01 \x01(\t\x12\x18\n\x10resource_version\x18\x02 \x01(\t\x12\x1a\n\x12\x61sync_operation_id\x18\x03 \x01(\t"c\n\x17\x44\x65leteUserGroupResponse\x12H\n\x0f\x61sync_operation\x18\x01 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"\xc0\x01\n"SetUserGroupNamespaceAccessRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x10\n\x08group_id\x18\x02 \x01(\t\x12?\n\x06\x61\x63\x63\x65ss\x18\x03 \x01(\x0b\x32/.temporal.api.cloud.identity.v1.NamespaceAccess\x12\x18\n\x10resource_version\x18\x04 \x01(\t\x12\x1a\n\x12\x61sync_operation_id\x18\x05 \x01(\t"o\n#SetUserGroupNamespaceAccessResponse\x12H\n\x0f\x61sync_operation\x18\x01 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"\x8f\x01\n\x19\x41\x64\x64UserGroupMemberRequest\x12\x10\n\x08group_id\x18\x01 \x01(\t\x12\x44\n\tmember_id\x18\x02 \x01(\x0b\x32\x31.temporal.api.cloud.identity.v1.UserGroupMemberId\x12\x1a\n\x12\x61sync_operation_id\x18\x03 \x01(\t"f\n\x1a\x41\x64\x64UserGroupMemberResponse\x12H\n\x0f\x61sync_operation\x18\x01 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"\x92\x01\n\x1cRemoveUserGroupMemberRequest\x12\x10\n\x08group_id\x18\x01 \x01(\t\x12\x44\n\tmember_id\x18\x02 \x01(\x0b\x32\x31.temporal.api.cloud.identity.v1.UserGroupMemberId\x12\x1a\n\x12\x61sync_operation_id\x18\x03 \x01(\t"i\n\x1dRemoveUserGroupMemberResponse\x12H\n\x0f\x61sync_operation\x18\x01 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"U\n\x1aGetUserGroupMembersRequest\x12\x11\n\tpage_size\x18\x01 \x01(\x05\x12\x12\n\npage_token\x18\x02 \x01(\t\x12\x10\n\x08group_id\x18\x03 \x01(\t"x\n\x1bGetUserGroupMembersResponse\x12@\n\x07members\x18\x01 \x03(\x0b\x32/.temporal.api.cloud.identity.v1.UserGroupMember\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\t"{\n\x1b\x43reateServiceAccountRequest\x12@\n\x04spec\x18\x01 \x01(\x0b\x32\x32.temporal.api.cloud.identity.v1.ServiceAccountSpec\x12\x1a\n\x12\x61sync_operation_id\x18\x02 \x01(\t"\x84\x01\n\x1c\x43reateServiceAccountResponse\x12\x1a\n\x12service_account_id\x18\x01 \x01(\t\x12H\n\x0f\x61sync_operation\x18\x02 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"6\n\x18GetServiceAccountRequest\x12\x1a\n\x12service_account_id\x18\x01 \x01(\t"d\n\x19GetServiceAccountResponse\x12G\n\x0fservice_account\x18\x01 \x01(\x0b\x32..temporal.api.cloud.identity.v1.ServiceAccount"B\n\x19GetServiceAccountsRequest\x12\x11\n\tpage_size\x18\x01 \x01(\x05\x12\x12\n\npage_token\x18\x02 \x01(\t"~\n\x1aGetServiceAccountsResponse\x12G\n\x0fservice_account\x18\x01 \x03(\x0b\x32..temporal.api.cloud.identity.v1.ServiceAccount\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\t"\xb1\x01\n\x1bUpdateServiceAccountRequest\x12\x1a\n\x12service_account_id\x18\x01 \x01(\t\x12@\n\x04spec\x18\x02 \x01(\x0b\x32\x32.temporal.api.cloud.identity.v1.ServiceAccountSpec\x12\x18\n\x10resource_version\x18\x03 \x01(\t\x12\x1a\n\x12\x61sync_operation_id\x18\x04 \x01(\t"h\n\x1cUpdateServiceAccountResponse\x12H\n\x0f\x61sync_operation\x18\x01 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"\xcf\x01\n\'SetServiceAccountNamespaceAccessRequest\x12\x1a\n\x12service_account_id\x18\x01 \x01(\t\x12\x11\n\tnamespace\x18\x02 \x01(\t\x12?\n\x06\x61\x63\x63\x65ss\x18\x03 \x01(\x0b\x32/.temporal.api.cloud.identity.v1.NamespaceAccess\x12\x18\n\x10resource_version\x18\x04 \x01(\t\x12\x1a\n\x12\x61sync_operation_id\x18\x05 \x01(\t"t\n(SetServiceAccountNamespaceAccessResponse\x12H\n\x0f\x61sync_operation\x18\x01 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"o\n\x1b\x44\x65leteServiceAccountRequest\x12\x1a\n\x12service_account_id\x18\x01 \x01(\t\x12\x18\n\x10resource_version\x18\x02 \x01(\t\x12\x1a\n\x12\x61sync_operation_id\x18\x03 \x01(\t"h\n\x1c\x44\x65leteServiceAccountResponse\x12H\n\x0f\x61sync_operation\x18\x01 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"\xaa\x01\n\x0fGetUsageRequest\x12\x38\n\x14start_time_inclusive\x18\x01 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x36\n\x12\x65nd_time_exclusive\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x11\n\tpage_size\x18\x03 \x01(\x05\x12\x12\n\npage_token\x18\x04 \x01(\t"d\n\x10GetUsageResponse\x12\x37\n\tsummaries\x18\x01 \x03(\x0b\x32$.temporal.api.cloud.usage.v1.Summary\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\t"\x13\n\x11GetAccountRequest"M\n\x12GetAccountResponse\x12\x37\n\x07\x61\x63\x63ount\x18\x01 \x01(\x0b\x32&.temporal.api.cloud.account.v1.Account"\x86\x01\n\x14UpdateAccountRequest\x12\x38\n\x04spec\x18\x01 \x01(\x0b\x32*.temporal.api.cloud.account.v1.AccountSpec\x12\x18\n\x10resource_version\x18\x02 \x01(\t\x12\x1a\n\x12\x61sync_operation_id\x18\x03 \x01(\t"a\n\x15UpdateAccountResponse\x12H\n\x0f\x61sync_operation\x18\x01 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"\x90\x01\n CreateNamespaceExportSinkRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12=\n\x04spec\x18\x02 \x01(\x0b\x32/.temporal.api.cloud.namespace.v1.ExportSinkSpec\x12\x1a\n\x12\x61sync_operation_id\x18\x03 \x01(\t"m\n!CreateNamespaceExportSinkResponse\x12H\n\x0f\x61sync_operation\x18\x01 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"@\n\x1dGetNamespaceExportSinkRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x0c\n\x04name\x18\x02 \x01(\t"[\n\x1eGetNamespaceExportSinkResponse\x12\x39\n\x04sink\x18\x01 \x01(\x0b\x32+.temporal.api.cloud.namespace.v1.ExportSink"Z\n\x1eGetNamespaceExportSinksRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x11\n\tpage_size\x18\x02 \x01(\x05\x12\x12\n\npage_token\x18\x03 \x01(\t"v\n\x1fGetNamespaceExportSinksResponse\x12:\n\x05sinks\x18\x01 \x03(\x0b\x32+.temporal.api.cloud.namespace.v1.ExportSink\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\t"\xaa\x01\n UpdateNamespaceExportSinkRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12=\n\x04spec\x18\x02 \x01(\x0b\x32/.temporal.api.cloud.namespace.v1.ExportSinkSpec\x12\x18\n\x10resource_version\x18\x03 \x01(\t\x12\x1a\n\x12\x61sync_operation_id\x18\x04 \x01(\t"m\n!UpdateNamespaceExportSinkResponse\x12H\n\x0f\x61sync_operation\x18\x01 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"y\n DeleteNamespaceExportSinkRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x0c\n\x04name\x18\x02 \x01(\t\x12\x18\n\x10resource_version\x18\x03 \x01(\t\x12\x1a\n\x12\x61sync_operation_id\x18\x04 \x01(\t"m\n!DeleteNamespaceExportSinkResponse\x12H\n\x0f\x61sync_operation\x18\x01 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"v\n"ValidateNamespaceExportSinkRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12=\n\x04spec\x18\x02 \x01(\x0b\x32/.temporal.api.cloud.namespace.v1.ExportSinkSpec"%\n#ValidateNamespaceExportSinkResponse"\x82\x02\n\x1aUpdateNamespaceTagsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12h\n\x0etags_to_upsert\x18\x02 \x03(\x0b\x32P.temporal.api.cloud.cloudservice.v1.UpdateNamespaceTagsRequest.TagsToUpsertEntry\x12\x16\n\x0etags_to_remove\x18\x03 \x03(\t\x12\x1a\n\x12\x61sync_operation_id\x18\x04 \x01(\t\x1a\x33\n\x11TagsToUpsertEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01"g\n\x1bUpdateNamespaceTagsResponse\x12H\n\x0f\x61sync_operation\x18\x01 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"\x87\x01\n\x1d\x43reateConnectivityRuleRequest\x12J\n\x04spec\x18\x01 \x01(\x0b\x32<.temporal.api.cloud.connectivityrule.v1.ConnectivityRuleSpec\x12\x1a\n\x12\x61sync_operation_id\x18\x02 \x01(\t"\x88\x01\n\x1e\x43reateConnectivityRuleResponse\x12\x1c\n\x14\x63onnectivity_rule_id\x18\x01 \x01(\t\x12H\n\x0f\x61sync_operation\x18\x02 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation":\n\x1aGetConnectivityRuleRequest\x12\x1c\n\x14\x63onnectivity_rule_id\x18\x01 \x01(\t"r\n\x1bGetConnectivityRuleResponse\x12S\n\x11\x63onnectivity_rule\x18\x01 \x01(\x0b\x32\x38.temporal.api.cloud.connectivityrule.v1.ConnectivityRule"W\n\x1bGetConnectivityRulesRequest\x12\x11\n\tpage_size\x18\x01 \x01(\x05\x12\x12\n\npage_token\x18\x02 \x01(\t\x12\x11\n\tnamespace\x18\x03 \x01(\t"\x8d\x01\n\x1cGetConnectivityRulesResponse\x12T\n\x12\x63onnectivity_rules\x18\x01 \x03(\x0b\x32\x38.temporal.api.cloud.connectivityrule.v1.ConnectivityRule\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\t"s\n\x1d\x44\x65leteConnectivityRuleRequest\x12\x1c\n\x14\x63onnectivity_rule_id\x18\x01 \x01(\t\x12\x18\n\x10resource_version\x18\x02 \x01(\t\x12\x1a\n\x12\x61sync_operation_id\x18\x03 \x01(\t"j\n\x1e\x44\x65leteConnectivityRuleResponse\x12H\n\x0f\x61sync_operation\x18\x01 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"\xae\x01\n\x13GetAuditLogsRequest\x12\x11\n\tpage_size\x18\x01 \x01(\x05\x12\x12\n\npage_token\x18\x02 \x01(\t\x12\x38\n\x14start_time_inclusive\x18\x03 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x36\n\x12\x65nd_time_exclusive\x18\x04 \x01(\x0b\x32\x1a.google.protobuf.Timestamp"h\n\x14GetAuditLogsResponse\x12\x37\n\x04logs\x18\x01 \x03(\x0b\x32).temporal.api.cloud.auditlog.v1.LogRecord\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\t"c\n"ValidateAccountAuditLogSinkRequest\x12=\n\x04spec\x18\x01 \x01(\x0b\x32/.temporal.api.cloud.account.v1.AuditLogSinkSpec"%\n#ValidateAccountAuditLogSinkResponse"}\n CreateAccountAuditLogSinkRequest\x12=\n\x04spec\x18\x01 \x01(\x0b\x32/.temporal.api.cloud.account.v1.AuditLogSinkSpec\x12\x1a\n\x12\x61sync_operation_id\x18\x02 \x01(\t"m\n!CreateAccountAuditLogSinkResponse\x12H\n\x0f\x61sync_operation\x18\x01 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"-\n\x1dGetAccountAuditLogSinkRequest\x12\x0c\n\x04name\x18\x01 \x01(\t"[\n\x1eGetAccountAuditLogSinkResponse\x12\x39\n\x04sink\x18\x01 \x01(\x0b\x32+.temporal.api.cloud.account.v1.AuditLogSink"G\n\x1eGetAccountAuditLogSinksRequest\x12\x11\n\tpage_size\x18\x01 \x01(\x05\x12\x12\n\npage_token\x18\x02 \x01(\t"v\n\x1fGetAccountAuditLogSinksResponse\x12:\n\x05sinks\x18\x01 \x03(\x0b\x32+.temporal.api.cloud.account.v1.AuditLogSink\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\t"\x97\x01\n UpdateAccountAuditLogSinkRequest\x12=\n\x04spec\x18\x01 \x01(\x0b\x32/.temporal.api.cloud.account.v1.AuditLogSinkSpec\x12\x18\n\x10resource_version\x18\x02 \x01(\t\x12\x1a\n\x12\x61sync_operation_id\x18\x03 \x01(\t"m\n!UpdateAccountAuditLogSinkResponse\x12H\n\x0f\x61sync_operation\x18\x01 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"f\n DeleteAccountAuditLogSinkRequest\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x18\n\x10resource_version\x18\x02 \x01(\t\x12\x1a\n\x12\x61sync_operation_id\x18\x03 \x01(\t"m\n!DeleteAccountAuditLogSinkResponse\x12H\n\x0f\x61sync_operation\x18\x01 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"4\n\x1fGetNamespaceCapacityInfoRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t"q\n GetNamespaceCapacityInfoResponse\x12M\n\rcapacity_info\x18\x01 \x01(\x0b\x32\x36.temporal.api.cloud.namespace.v1.NamespaceCapacityInfo"x\n\x1a\x43reateBillingReportRequest\x12>\n\x04spec\x18\x01 \x01(\x0b\x32\x30.temporal.api.cloud.billing.v1.BillingReportSpec\x12\x1a\n\x12\x61sync_operation_id\x18\x02 \x01(\t"\x82\x01\n\x1b\x43reateBillingReportResponse\x12\x19\n\x11\x62illing_report_id\x18\x01 \x01(\t\x12H\n\x0f\x61sync_operation\x18\x02 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"4\n\x17GetBillingReportRequest\x12\x19\n\x11\x62illing_report_id\x18\x01 \x01(\t"`\n\x18GetBillingReportResponse\x12\x44\n\x0e\x62illing_report\x18\x01 \x01(\x0b\x32,.temporal.api.cloud.billing.v1.BillingReportB\xc8\x01\n%io.temporal.api.cloud.cloudservice.v1B\x14RequestResponseProtoP\x01Z5go.temporal.io/api/cloud/cloudservice/v1;cloudservice\xaa\x02$Temporalio.Api.Cloud.CloudService.V1\xea\x02(Temporalio::Api::Cloud::CloudService::V1b\x06proto3' ) +_GETCURRENTIDENTITYREQUEST = DESCRIPTOR.message_types_by_name[ + "GetCurrentIdentityRequest" +] +_GETCURRENTIDENTITYRESPONSE = DESCRIPTOR.message_types_by_name[ + "GetCurrentIdentityResponse" +] _GETUSERSREQUEST = DESCRIPTOR.message_types_by_name["GetUsersRequest"] _GETUSERSRESPONSE = DESCRIPTOR.message_types_by_name["GetUsersResponse"] _GETUSERREQUEST = DESCRIPTOR.message_types_by_name["GetUserRequest"] @@ -290,12 +302,80 @@ _DELETECONNECTIVITYRULERESPONSE = DESCRIPTOR.message_types_by_name[ "DeleteConnectivityRuleResponse" ] +_GETAUDITLOGSREQUEST = DESCRIPTOR.message_types_by_name["GetAuditLogsRequest"] +_GETAUDITLOGSRESPONSE = DESCRIPTOR.message_types_by_name["GetAuditLogsResponse"] _VALIDATEACCOUNTAUDITLOGSINKREQUEST = DESCRIPTOR.message_types_by_name[ "ValidateAccountAuditLogSinkRequest" ] _VALIDATEACCOUNTAUDITLOGSINKRESPONSE = DESCRIPTOR.message_types_by_name[ "ValidateAccountAuditLogSinkResponse" ] +_CREATEACCOUNTAUDITLOGSINKREQUEST = DESCRIPTOR.message_types_by_name[ + "CreateAccountAuditLogSinkRequest" +] +_CREATEACCOUNTAUDITLOGSINKRESPONSE = DESCRIPTOR.message_types_by_name[ + "CreateAccountAuditLogSinkResponse" +] +_GETACCOUNTAUDITLOGSINKREQUEST = DESCRIPTOR.message_types_by_name[ + "GetAccountAuditLogSinkRequest" +] +_GETACCOUNTAUDITLOGSINKRESPONSE = DESCRIPTOR.message_types_by_name[ + "GetAccountAuditLogSinkResponse" +] +_GETACCOUNTAUDITLOGSINKSREQUEST = DESCRIPTOR.message_types_by_name[ + "GetAccountAuditLogSinksRequest" +] +_GETACCOUNTAUDITLOGSINKSRESPONSE = DESCRIPTOR.message_types_by_name[ + "GetAccountAuditLogSinksResponse" +] +_UPDATEACCOUNTAUDITLOGSINKREQUEST = DESCRIPTOR.message_types_by_name[ + "UpdateAccountAuditLogSinkRequest" +] +_UPDATEACCOUNTAUDITLOGSINKRESPONSE = DESCRIPTOR.message_types_by_name[ + "UpdateAccountAuditLogSinkResponse" +] +_DELETEACCOUNTAUDITLOGSINKREQUEST = DESCRIPTOR.message_types_by_name[ + "DeleteAccountAuditLogSinkRequest" +] +_DELETEACCOUNTAUDITLOGSINKRESPONSE = DESCRIPTOR.message_types_by_name[ + "DeleteAccountAuditLogSinkResponse" +] +_GETNAMESPACECAPACITYINFOREQUEST = DESCRIPTOR.message_types_by_name[ + "GetNamespaceCapacityInfoRequest" +] +_GETNAMESPACECAPACITYINFORESPONSE = DESCRIPTOR.message_types_by_name[ + "GetNamespaceCapacityInfoResponse" +] +_CREATEBILLINGREPORTREQUEST = DESCRIPTOR.message_types_by_name[ + "CreateBillingReportRequest" +] +_CREATEBILLINGREPORTRESPONSE = DESCRIPTOR.message_types_by_name[ + "CreateBillingReportResponse" +] +_GETBILLINGREPORTREQUEST = DESCRIPTOR.message_types_by_name["GetBillingReportRequest"] +_GETBILLINGREPORTRESPONSE = DESCRIPTOR.message_types_by_name["GetBillingReportResponse"] +GetCurrentIdentityRequest = _reflection.GeneratedProtocolMessageType( + "GetCurrentIdentityRequest", + (_message.Message,), + { + "DESCRIPTOR": _GETCURRENTIDENTITYREQUEST, + "__module__": "temporalio.api.cloud.cloudservice.v1.request_response_pb2", + # @@protoc_insertion_point(class_scope:temporal.api.cloud.cloudservice.v1.GetCurrentIdentityRequest) + }, +) +_sym_db.RegisterMessage(GetCurrentIdentityRequest) + +GetCurrentIdentityResponse = _reflection.GeneratedProtocolMessageType( + "GetCurrentIdentityResponse", + (_message.Message,), + { + "DESCRIPTOR": _GETCURRENTIDENTITYRESPONSE, + "__module__": "temporalio.api.cloud.cloudservice.v1.request_response_pb2", + # @@protoc_insertion_point(class_scope:temporal.api.cloud.cloudservice.v1.GetCurrentIdentityResponse) + }, +) +_sym_db.RegisterMessage(GetCurrentIdentityResponse) + GetUsersRequest = _reflection.GeneratedProtocolMessageType( "GetUsersRequest", (_message.Message,), @@ -1590,6 +1670,28 @@ ) _sym_db.RegisterMessage(DeleteConnectivityRuleResponse) +GetAuditLogsRequest = _reflection.GeneratedProtocolMessageType( + "GetAuditLogsRequest", + (_message.Message,), + { + "DESCRIPTOR": _GETAUDITLOGSREQUEST, + "__module__": "temporalio.api.cloud.cloudservice.v1.request_response_pb2", + # @@protoc_insertion_point(class_scope:temporal.api.cloud.cloudservice.v1.GetAuditLogsRequest) + }, +) +_sym_db.RegisterMessage(GetAuditLogsRequest) + +GetAuditLogsResponse = _reflection.GeneratedProtocolMessageType( + "GetAuditLogsResponse", + (_message.Message,), + { + "DESCRIPTOR": _GETAUDITLOGSRESPONSE, + "__module__": "temporalio.api.cloud.cloudservice.v1.request_response_pb2", + # @@protoc_insertion_point(class_scope:temporal.api.cloud.cloudservice.v1.GetAuditLogsResponse) + }, +) +_sym_db.RegisterMessage(GetAuditLogsResponse) + ValidateAccountAuditLogSinkRequest = _reflection.GeneratedProtocolMessageType( "ValidateAccountAuditLogSinkRequest", (_message.Message,), @@ -1612,6 +1714,182 @@ ) _sym_db.RegisterMessage(ValidateAccountAuditLogSinkResponse) +CreateAccountAuditLogSinkRequest = _reflection.GeneratedProtocolMessageType( + "CreateAccountAuditLogSinkRequest", + (_message.Message,), + { + "DESCRIPTOR": _CREATEACCOUNTAUDITLOGSINKREQUEST, + "__module__": "temporalio.api.cloud.cloudservice.v1.request_response_pb2", + # @@protoc_insertion_point(class_scope:temporal.api.cloud.cloudservice.v1.CreateAccountAuditLogSinkRequest) + }, +) +_sym_db.RegisterMessage(CreateAccountAuditLogSinkRequest) + +CreateAccountAuditLogSinkResponse = _reflection.GeneratedProtocolMessageType( + "CreateAccountAuditLogSinkResponse", + (_message.Message,), + { + "DESCRIPTOR": _CREATEACCOUNTAUDITLOGSINKRESPONSE, + "__module__": "temporalio.api.cloud.cloudservice.v1.request_response_pb2", + # @@protoc_insertion_point(class_scope:temporal.api.cloud.cloudservice.v1.CreateAccountAuditLogSinkResponse) + }, +) +_sym_db.RegisterMessage(CreateAccountAuditLogSinkResponse) + +GetAccountAuditLogSinkRequest = _reflection.GeneratedProtocolMessageType( + "GetAccountAuditLogSinkRequest", + (_message.Message,), + { + "DESCRIPTOR": _GETACCOUNTAUDITLOGSINKREQUEST, + "__module__": "temporalio.api.cloud.cloudservice.v1.request_response_pb2", + # @@protoc_insertion_point(class_scope:temporal.api.cloud.cloudservice.v1.GetAccountAuditLogSinkRequest) + }, +) +_sym_db.RegisterMessage(GetAccountAuditLogSinkRequest) + +GetAccountAuditLogSinkResponse = _reflection.GeneratedProtocolMessageType( + "GetAccountAuditLogSinkResponse", + (_message.Message,), + { + "DESCRIPTOR": _GETACCOUNTAUDITLOGSINKRESPONSE, + "__module__": "temporalio.api.cloud.cloudservice.v1.request_response_pb2", + # @@protoc_insertion_point(class_scope:temporal.api.cloud.cloudservice.v1.GetAccountAuditLogSinkResponse) + }, +) +_sym_db.RegisterMessage(GetAccountAuditLogSinkResponse) + +GetAccountAuditLogSinksRequest = _reflection.GeneratedProtocolMessageType( + "GetAccountAuditLogSinksRequest", + (_message.Message,), + { + "DESCRIPTOR": _GETACCOUNTAUDITLOGSINKSREQUEST, + "__module__": "temporalio.api.cloud.cloudservice.v1.request_response_pb2", + # @@protoc_insertion_point(class_scope:temporal.api.cloud.cloudservice.v1.GetAccountAuditLogSinksRequest) + }, +) +_sym_db.RegisterMessage(GetAccountAuditLogSinksRequest) + +GetAccountAuditLogSinksResponse = _reflection.GeneratedProtocolMessageType( + "GetAccountAuditLogSinksResponse", + (_message.Message,), + { + "DESCRIPTOR": _GETACCOUNTAUDITLOGSINKSRESPONSE, + "__module__": "temporalio.api.cloud.cloudservice.v1.request_response_pb2", + # @@protoc_insertion_point(class_scope:temporal.api.cloud.cloudservice.v1.GetAccountAuditLogSinksResponse) + }, +) +_sym_db.RegisterMessage(GetAccountAuditLogSinksResponse) + +UpdateAccountAuditLogSinkRequest = _reflection.GeneratedProtocolMessageType( + "UpdateAccountAuditLogSinkRequest", + (_message.Message,), + { + "DESCRIPTOR": _UPDATEACCOUNTAUDITLOGSINKREQUEST, + "__module__": "temporalio.api.cloud.cloudservice.v1.request_response_pb2", + # @@protoc_insertion_point(class_scope:temporal.api.cloud.cloudservice.v1.UpdateAccountAuditLogSinkRequest) + }, +) +_sym_db.RegisterMessage(UpdateAccountAuditLogSinkRequest) + +UpdateAccountAuditLogSinkResponse = _reflection.GeneratedProtocolMessageType( + "UpdateAccountAuditLogSinkResponse", + (_message.Message,), + { + "DESCRIPTOR": _UPDATEACCOUNTAUDITLOGSINKRESPONSE, + "__module__": "temporalio.api.cloud.cloudservice.v1.request_response_pb2", + # @@protoc_insertion_point(class_scope:temporal.api.cloud.cloudservice.v1.UpdateAccountAuditLogSinkResponse) + }, +) +_sym_db.RegisterMessage(UpdateAccountAuditLogSinkResponse) + +DeleteAccountAuditLogSinkRequest = _reflection.GeneratedProtocolMessageType( + "DeleteAccountAuditLogSinkRequest", + (_message.Message,), + { + "DESCRIPTOR": _DELETEACCOUNTAUDITLOGSINKREQUEST, + "__module__": "temporalio.api.cloud.cloudservice.v1.request_response_pb2", + # @@protoc_insertion_point(class_scope:temporal.api.cloud.cloudservice.v1.DeleteAccountAuditLogSinkRequest) + }, +) +_sym_db.RegisterMessage(DeleteAccountAuditLogSinkRequest) + +DeleteAccountAuditLogSinkResponse = _reflection.GeneratedProtocolMessageType( + "DeleteAccountAuditLogSinkResponse", + (_message.Message,), + { + "DESCRIPTOR": _DELETEACCOUNTAUDITLOGSINKRESPONSE, + "__module__": "temporalio.api.cloud.cloudservice.v1.request_response_pb2", + # @@protoc_insertion_point(class_scope:temporal.api.cloud.cloudservice.v1.DeleteAccountAuditLogSinkResponse) + }, +) +_sym_db.RegisterMessage(DeleteAccountAuditLogSinkResponse) + +GetNamespaceCapacityInfoRequest = _reflection.GeneratedProtocolMessageType( + "GetNamespaceCapacityInfoRequest", + (_message.Message,), + { + "DESCRIPTOR": _GETNAMESPACECAPACITYINFOREQUEST, + "__module__": "temporalio.api.cloud.cloudservice.v1.request_response_pb2", + # @@protoc_insertion_point(class_scope:temporal.api.cloud.cloudservice.v1.GetNamespaceCapacityInfoRequest) + }, +) +_sym_db.RegisterMessage(GetNamespaceCapacityInfoRequest) + +GetNamespaceCapacityInfoResponse = _reflection.GeneratedProtocolMessageType( + "GetNamespaceCapacityInfoResponse", + (_message.Message,), + { + "DESCRIPTOR": _GETNAMESPACECAPACITYINFORESPONSE, + "__module__": "temporalio.api.cloud.cloudservice.v1.request_response_pb2", + # @@protoc_insertion_point(class_scope:temporal.api.cloud.cloudservice.v1.GetNamespaceCapacityInfoResponse) + }, +) +_sym_db.RegisterMessage(GetNamespaceCapacityInfoResponse) + +CreateBillingReportRequest = _reflection.GeneratedProtocolMessageType( + "CreateBillingReportRequest", + (_message.Message,), + { + "DESCRIPTOR": _CREATEBILLINGREPORTREQUEST, + "__module__": "temporalio.api.cloud.cloudservice.v1.request_response_pb2", + # @@protoc_insertion_point(class_scope:temporal.api.cloud.cloudservice.v1.CreateBillingReportRequest) + }, +) +_sym_db.RegisterMessage(CreateBillingReportRequest) + +CreateBillingReportResponse = _reflection.GeneratedProtocolMessageType( + "CreateBillingReportResponse", + (_message.Message,), + { + "DESCRIPTOR": _CREATEBILLINGREPORTRESPONSE, + "__module__": "temporalio.api.cloud.cloudservice.v1.request_response_pb2", + # @@protoc_insertion_point(class_scope:temporal.api.cloud.cloudservice.v1.CreateBillingReportResponse) + }, +) +_sym_db.RegisterMessage(CreateBillingReportResponse) + +GetBillingReportRequest = _reflection.GeneratedProtocolMessageType( + "GetBillingReportRequest", + (_message.Message,), + { + "DESCRIPTOR": _GETBILLINGREPORTREQUEST, + "__module__": "temporalio.api.cloud.cloudservice.v1.request_response_pb2", + # @@protoc_insertion_point(class_scope:temporal.api.cloud.cloudservice.v1.GetBillingReportRequest) + }, +) +_sym_db.RegisterMessage(GetBillingReportRequest) + +GetBillingReportResponse = _reflection.GeneratedProtocolMessageType( + "GetBillingReportResponse", + (_message.Message,), + { + "DESCRIPTOR": _GETBILLINGREPORTRESPONSE, + "__module__": "temporalio.api.cloud.cloudservice.v1.request_response_pb2", + # @@protoc_insertion_point(class_scope:temporal.api.cloud.cloudservice.v1.GetBillingReportResponse) + }, +) +_sym_db.RegisterMessage(GetBillingReportResponse) + if _descriptor._USE_C_DESCRIPTORS == False: DESCRIPTOR._options = None DESCRIPTOR._serialized_options = b"\n%io.temporal.api.cloud.cloudservice.v1B\024RequestResponseProtoP\001Z5go.temporal.io/api/cloud/cloudservice/v1;cloudservice\252\002$Temporalio.Api.Cloud.CloudService.V1\352\002(Temporalio::Api::Cloud::CloudService::V1" @@ -1623,244 +1901,284 @@ ]._serialized_options = b"\030\001" _UPDATENAMESPACETAGSREQUEST_TAGSTOUPSERTENTRY._options = None _UPDATENAMESPACETAGSREQUEST_TAGSTOUPSERTENTRY._serialized_options = b"8\001" - _GETUSERSREQUEST._serialized_start = 499 - _GETUSERSREQUEST._serialized_end = 589 - _GETUSERSRESPONSE._serialized_start = 591 - _GETUSERSRESPONSE._serialized_end = 687 - _GETUSERREQUEST._serialized_start = 689 - _GETUSERREQUEST._serialized_end = 722 - _GETUSERRESPONSE._serialized_start = 724 - _GETUSERRESPONSE._serialized_end = 793 - _CREATEUSERREQUEST._serialized_start = 795 - _CREATEUSERREQUEST._serialized_end = 898 - _CREATEUSERRESPONSE._serialized_start = 900 - _CREATEUSERRESPONSE._serialized_end = 1011 - _UPDATEUSERREQUEST._serialized_start = 1014 - _UPDATEUSERREQUEST._serialized_end = 1160 - _UPDATEUSERRESPONSE._serialized_start = 1162 - _UPDATEUSERRESPONSE._serialized_end = 1256 - _DELETEUSERREQUEST._serialized_start = 1258 - _DELETEUSERREQUEST._serialized_end = 1348 - _DELETEUSERRESPONSE._serialized_start = 1350 - _DELETEUSERRESPONSE._serialized_end = 1444 - _SETUSERNAMESPACEACCESSREQUEST._serialized_start = 1447 - _SETUSERNAMESPACEACCESSREQUEST._serialized_end = 1633 - _SETUSERNAMESPACEACCESSRESPONSE._serialized_start = 1635 - _SETUSERNAMESPACEACCESSRESPONSE._serialized_end = 1741 - _GETASYNCOPERATIONREQUEST._serialized_start = 1743 - _GETASYNCOPERATIONREQUEST._serialized_end = 1797 - _GETASYNCOPERATIONRESPONSE._serialized_start = 1799 - _GETASYNCOPERATIONRESPONSE._serialized_end = 1900 - _CREATENAMESPACEREQUEST._serialized_start = 1903 - _CREATENAMESPACEREQUEST._serialized_end = 2146 - _CREATENAMESPACEREQUEST_TAGSENTRY._serialized_start = 2103 - _CREATENAMESPACEREQUEST_TAGSENTRY._serialized_end = 2146 - _CREATENAMESPACERESPONSE._serialized_start = 2148 - _CREATENAMESPACERESPONSE._serialized_end = 2266 - _GETNAMESPACESREQUEST._serialized_start = 2268 - _GETNAMESPACESREQUEST._serialized_end = 2343 - _GETNAMESPACESRESPONSE._serialized_start = 2345 - _GETNAMESPACESRESPONSE._serialized_end = 2457 - _GETNAMESPACEREQUEST._serialized_start = 2459 - _GETNAMESPACEREQUEST._serialized_end = 2499 - _GETNAMESPACERESPONSE._serialized_start = 2501 - _GETNAMESPACERESPONSE._serialized_end = 2586 - _UPDATENAMESPACEREQUEST._serialized_start = 2589 - _UPDATENAMESPACEREQUEST._serialized_end = 2748 - _UPDATENAMESPACERESPONSE._serialized_start = 2750 - _UPDATENAMESPACERESPONSE._serialized_end = 2849 - _RENAMECUSTOMSEARCHATTRIBUTEREQUEST._serialized_start = 2852 - _RENAMECUSTOMSEARCHATTRIBUTEREQUEST._serialized_end = 3050 - _RENAMECUSTOMSEARCHATTRIBUTERESPONSE._serialized_start = 3052 - _RENAMECUSTOMSEARCHATTRIBUTERESPONSE._serialized_end = 3163 - _DELETENAMESPACEREQUEST._serialized_start = 3165 - _DELETENAMESPACEREQUEST._serialized_end = 3262 - _DELETENAMESPACERESPONSE._serialized_start = 3264 - _DELETENAMESPACERESPONSE._serialized_end = 3363 - _FAILOVERNAMESPACEREGIONREQUEST._serialized_start = 3365 - _FAILOVERNAMESPACEREGIONREQUEST._serialized_end = 3460 - _FAILOVERNAMESPACEREGIONRESPONSE._serialized_start = 3462 - _FAILOVERNAMESPACEREGIONRESPONSE._serialized_end = 3569 - _ADDNAMESPACEREGIONREQUEST._serialized_start = 3571 - _ADDNAMESPACEREGIONREQUEST._serialized_end = 3687 - _ADDNAMESPACEREGIONRESPONSE._serialized_start = 3689 - _ADDNAMESPACEREGIONRESPONSE._serialized_end = 3791 - _DELETENAMESPACEREGIONREQUEST._serialized_start = 3793 - _DELETENAMESPACEREGIONREQUEST._serialized_end = 3912 - _DELETENAMESPACEREGIONRESPONSE._serialized_start = 3914 - _DELETENAMESPACEREGIONRESPONSE._serialized_end = 4019 - _GETREGIONSREQUEST._serialized_start = 4021 - _GETREGIONSREQUEST._serialized_end = 4040 - _GETREGIONSRESPONSE._serialized_start = 4042 - _GETREGIONSRESPONSE._serialized_end = 4117 - _GETREGIONREQUEST._serialized_start = 4119 - _GETREGIONREQUEST._serialized_end = 4153 - _GETREGIONRESPONSE._serialized_start = 4155 - _GETREGIONRESPONSE._serialized_end = 4228 - _GETAPIKEYSREQUEST._serialized_start = 4231 - _GETAPIKEYSREQUEST._serialized_end = 4405 - _GETAPIKEYSRESPONSE._serialized_start = 4407 - _GETAPIKEYSRESPONSE._serialized_end = 4510 - _GETAPIKEYREQUEST._serialized_start = 4512 - _GETAPIKEYREQUEST._serialized_end = 4546 - _GETAPIKEYRESPONSE._serialized_start = 4548 - _GETAPIKEYRESPONSE._serialized_end = 4624 - _CREATEAPIKEYREQUEST._serialized_start = 4626 - _CREATEAPIKEYREQUEST._serialized_end = 4733 - _CREATEAPIKEYRESPONSE._serialized_start = 4735 - _CREATEAPIKEYRESPONSE._serialized_end = 4862 - _UPDATEAPIKEYREQUEST._serialized_start = 4865 - _UPDATEAPIKEYREQUEST._serialized_end = 5014 - _UPDATEAPIKEYRESPONSE._serialized_start = 5016 - _UPDATEAPIKEYRESPONSE._serialized_end = 5112 - _DELETEAPIKEYREQUEST._serialized_start = 5114 - _DELETEAPIKEYREQUEST._serialized_end = 5205 - _DELETEAPIKEYRESPONSE._serialized_start = 5207 - _DELETEAPIKEYRESPONSE._serialized_end = 5303 - _GETNEXUSENDPOINTSREQUEST._serialized_start = 5306 - _GETNEXUSENDPOINTSREQUEST._serialized_end = 5441 - _GETNEXUSENDPOINTSRESPONSE._serialized_start = 5443 - _GETNEXUSENDPOINTSRESPONSE._serialized_end = 5553 - _GETNEXUSENDPOINTREQUEST._serialized_start = 5555 - _GETNEXUSENDPOINTREQUEST._serialized_end = 5601 - _GETNEXUSENDPOINTRESPONSE._serialized_start = 5603 - _GETNEXUSENDPOINTRESPONSE._serialized_end = 5686 - _CREATENEXUSENDPOINTREQUEST._serialized_start = 5688 - _CREATENEXUSENDPOINTREQUEST._serialized_end = 5801 - _CREATENEXUSENDPOINTRESPONSE._serialized_start = 5803 - _CREATENEXUSENDPOINTRESPONSE._serialized_end = 5927 - _UPDATENEXUSENDPOINTREQUEST._serialized_start = 5930 - _UPDATENEXUSENDPOINTREQUEST._serialized_end = 6090 - _UPDATENEXUSENDPOINTRESPONSE._serialized_start = 6092 - _UPDATENEXUSENDPOINTRESPONSE._serialized_end = 6195 - _DELETENEXUSENDPOINTREQUEST._serialized_start = 6197 - _DELETENEXUSENDPOINTREQUEST._serialized_end = 6300 - _DELETENEXUSENDPOINTRESPONSE._serialized_start = 6302 - _DELETENEXUSENDPOINTRESPONSE._serialized_end = 6405 - _GETUSERGROUPSREQUEST._serialized_start = 6408 - _GETUSERGROUPSREQUEST._serialized_end = 6781 - _GETUSERGROUPSREQUEST_GOOGLEGROUPFILTER._serialized_start = 6704 - _GETUSERGROUPSREQUEST_GOOGLEGROUPFILTER._serialized_end = 6746 - _GETUSERGROUPSREQUEST_SCIMGROUPFILTER._serialized_start = 6748 - _GETUSERGROUPSREQUEST_SCIMGROUPFILTER._serialized_end = 6781 - _GETUSERGROUPSRESPONSE._serialized_start = 6783 - _GETUSERGROUPSRESPONSE._serialized_end = 6890 - _GETUSERGROUPREQUEST._serialized_start = 6892 - _GETUSERGROUPREQUEST._serialized_end = 6931 - _GETUSERGROUPRESPONSE._serialized_start = 6933 - _GETUSERGROUPRESPONSE._serialized_end = 7013 - _CREATEUSERGROUPREQUEST._serialized_start = 7015 - _CREATEUSERGROUPREQUEST._serialized_end = 7128 - _CREATEUSERGROUPRESPONSE._serialized_start = 7130 - _CREATEUSERGROUPRESPONSE._serialized_end = 7247 - _UPDATEUSERGROUPREQUEST._serialized_start = 7250 - _UPDATEUSERGROUPREQUEST._serialized_end = 7407 - _UPDATEUSERGROUPRESPONSE._serialized_start = 7409 - _UPDATEUSERGROUPRESPONSE._serialized_end = 7508 - _DELETEUSERGROUPREQUEST._serialized_start = 7510 - _DELETEUSERGROUPREQUEST._serialized_end = 7606 - _DELETEUSERGROUPRESPONSE._serialized_start = 7608 - _DELETEUSERGROUPRESPONSE._serialized_end = 7707 - _SETUSERGROUPNAMESPACEACCESSREQUEST._serialized_start = 7710 - _SETUSERGROUPNAMESPACEACCESSREQUEST._serialized_end = 7902 - _SETUSERGROUPNAMESPACEACCESSRESPONSE._serialized_start = 7904 - _SETUSERGROUPNAMESPACEACCESSRESPONSE._serialized_end = 8015 - _ADDUSERGROUPMEMBERREQUEST._serialized_start = 8018 - _ADDUSERGROUPMEMBERREQUEST._serialized_end = 8161 - _ADDUSERGROUPMEMBERRESPONSE._serialized_start = 8163 - _ADDUSERGROUPMEMBERRESPONSE._serialized_end = 8265 - _REMOVEUSERGROUPMEMBERREQUEST._serialized_start = 8268 - _REMOVEUSERGROUPMEMBERREQUEST._serialized_end = 8414 - _REMOVEUSERGROUPMEMBERRESPONSE._serialized_start = 8416 - _REMOVEUSERGROUPMEMBERRESPONSE._serialized_end = 8521 - _GETUSERGROUPMEMBERSREQUEST._serialized_start = 8523 - _GETUSERGROUPMEMBERSREQUEST._serialized_end = 8608 - _GETUSERGROUPMEMBERSRESPONSE._serialized_start = 8610 - _GETUSERGROUPMEMBERSRESPONSE._serialized_end = 8730 - _CREATESERVICEACCOUNTREQUEST._serialized_start = 8732 - _CREATESERVICEACCOUNTREQUEST._serialized_end = 8855 - _CREATESERVICEACCOUNTRESPONSE._serialized_start = 8858 - _CREATESERVICEACCOUNTRESPONSE._serialized_end = 8990 - _GETSERVICEACCOUNTREQUEST._serialized_start = 8992 - _GETSERVICEACCOUNTREQUEST._serialized_end = 9046 - _GETSERVICEACCOUNTRESPONSE._serialized_start = 9048 - _GETSERVICEACCOUNTRESPONSE._serialized_end = 9148 - _GETSERVICEACCOUNTSREQUEST._serialized_start = 9150 - _GETSERVICEACCOUNTSREQUEST._serialized_end = 9216 - _GETSERVICEACCOUNTSRESPONSE._serialized_start = 9218 - _GETSERVICEACCOUNTSRESPONSE._serialized_end = 9344 - _UPDATESERVICEACCOUNTREQUEST._serialized_start = 9347 - _UPDATESERVICEACCOUNTREQUEST._serialized_end = 9524 - _UPDATESERVICEACCOUNTRESPONSE._serialized_start = 9526 - _UPDATESERVICEACCOUNTRESPONSE._serialized_end = 9630 - _SETSERVICEACCOUNTNAMESPACEACCESSREQUEST._serialized_start = 9633 - _SETSERVICEACCOUNTNAMESPACEACCESSREQUEST._serialized_end = 9840 - _SETSERVICEACCOUNTNAMESPACEACCESSRESPONSE._serialized_start = 9842 - _SETSERVICEACCOUNTNAMESPACEACCESSRESPONSE._serialized_end = 9958 - _DELETESERVICEACCOUNTREQUEST._serialized_start = 9960 - _DELETESERVICEACCOUNTREQUEST._serialized_end = 10071 - _DELETESERVICEACCOUNTRESPONSE._serialized_start = 10073 - _DELETESERVICEACCOUNTRESPONSE._serialized_end = 10177 - _GETUSAGEREQUEST._serialized_start = 10180 - _GETUSAGEREQUEST._serialized_end = 10350 - _GETUSAGERESPONSE._serialized_start = 10352 - _GETUSAGERESPONSE._serialized_end = 10452 - _GETACCOUNTREQUEST._serialized_start = 10454 - _GETACCOUNTREQUEST._serialized_end = 10473 - _GETACCOUNTRESPONSE._serialized_start = 10475 - _GETACCOUNTRESPONSE._serialized_end = 10552 - _UPDATEACCOUNTREQUEST._serialized_start = 10555 - _UPDATEACCOUNTREQUEST._serialized_end = 10689 - _UPDATEACCOUNTRESPONSE._serialized_start = 10691 - _UPDATEACCOUNTRESPONSE._serialized_end = 10788 - _CREATENAMESPACEEXPORTSINKREQUEST._serialized_start = 10791 - _CREATENAMESPACEEXPORTSINKREQUEST._serialized_end = 10935 - _CREATENAMESPACEEXPORTSINKRESPONSE._serialized_start = 10937 - _CREATENAMESPACEEXPORTSINKRESPONSE._serialized_end = 11046 - _GETNAMESPACEEXPORTSINKREQUEST._serialized_start = 11048 - _GETNAMESPACEEXPORTSINKREQUEST._serialized_end = 11112 - _GETNAMESPACEEXPORTSINKRESPONSE._serialized_start = 11114 - _GETNAMESPACEEXPORTSINKRESPONSE._serialized_end = 11205 - _GETNAMESPACEEXPORTSINKSREQUEST._serialized_start = 11207 - _GETNAMESPACEEXPORTSINKSREQUEST._serialized_end = 11297 - _GETNAMESPACEEXPORTSINKSRESPONSE._serialized_start = 11299 - _GETNAMESPACEEXPORTSINKSRESPONSE._serialized_end = 11417 - _UPDATENAMESPACEEXPORTSINKREQUEST._serialized_start = 11420 - _UPDATENAMESPACEEXPORTSINKREQUEST._serialized_end = 11590 - _UPDATENAMESPACEEXPORTSINKRESPONSE._serialized_start = 11592 - _UPDATENAMESPACEEXPORTSINKRESPONSE._serialized_end = 11701 - _DELETENAMESPACEEXPORTSINKREQUEST._serialized_start = 11703 - _DELETENAMESPACEEXPORTSINKREQUEST._serialized_end = 11824 - _DELETENAMESPACEEXPORTSINKRESPONSE._serialized_start = 11826 - _DELETENAMESPACEEXPORTSINKRESPONSE._serialized_end = 11935 - _VALIDATENAMESPACEEXPORTSINKREQUEST._serialized_start = 11937 - _VALIDATENAMESPACEEXPORTSINKREQUEST._serialized_end = 12055 - _VALIDATENAMESPACEEXPORTSINKRESPONSE._serialized_start = 12057 - _VALIDATENAMESPACEEXPORTSINKRESPONSE._serialized_end = 12094 - _UPDATENAMESPACETAGSREQUEST._serialized_start = 12097 - _UPDATENAMESPACETAGSREQUEST._serialized_end = 12355 - _UPDATENAMESPACETAGSREQUEST_TAGSTOUPSERTENTRY._serialized_start = 12304 - _UPDATENAMESPACETAGSREQUEST_TAGSTOUPSERTENTRY._serialized_end = 12355 - _UPDATENAMESPACETAGSRESPONSE._serialized_start = 12357 - _UPDATENAMESPACETAGSRESPONSE._serialized_end = 12460 - _CREATECONNECTIVITYRULEREQUEST._serialized_start = 12463 - _CREATECONNECTIVITYRULEREQUEST._serialized_end = 12598 - _CREATECONNECTIVITYRULERESPONSE._serialized_start = 12601 - _CREATECONNECTIVITYRULERESPONSE._serialized_end = 12737 - _GETCONNECTIVITYRULEREQUEST._serialized_start = 12739 - _GETCONNECTIVITYRULEREQUEST._serialized_end = 12797 - _GETCONNECTIVITYRULERESPONSE._serialized_start = 12799 - _GETCONNECTIVITYRULERESPONSE._serialized_end = 12913 - _GETCONNECTIVITYRULESREQUEST._serialized_start = 12915 - _GETCONNECTIVITYRULESREQUEST._serialized_end = 13002 - _GETCONNECTIVITYRULESRESPONSE._serialized_start = 13005 - _GETCONNECTIVITYRULESRESPONSE._serialized_end = 13146 - _DELETECONNECTIVITYRULEREQUEST._serialized_start = 13148 - _DELETECONNECTIVITYRULEREQUEST._serialized_end = 13263 - _DELETECONNECTIVITYRULERESPONSE._serialized_start = 13265 - _DELETECONNECTIVITYRULERESPONSE._serialized_end = 13371 - _VALIDATEACCOUNTAUDITLOGSINKREQUEST._serialized_start = 13373 - _VALIDATEACCOUNTAUDITLOGSINKREQUEST._serialized_end = 13472 - _VALIDATEACCOUNTAUDITLOGSINKRESPONSE._serialized_start = 13474 - _VALIDATEACCOUNTAUDITLOGSINKRESPONSE._serialized_end = 13511 + _GETCURRENTIDENTITYREQUEST._serialized_start = 590 + _GETCURRENTIDENTITYREQUEST._serialized_end = 617 + _GETCURRENTIDENTITYRESPONSE._serialized_start = 620 + _GETCURRENTIDENTITYRESPONSE._serialized_end = 857 + _GETUSERSREQUEST._serialized_start = 859 + _GETUSERSREQUEST._serialized_end = 949 + _GETUSERSRESPONSE._serialized_start = 951 + _GETUSERSRESPONSE._serialized_end = 1047 + _GETUSERREQUEST._serialized_start = 1049 + _GETUSERREQUEST._serialized_end = 1082 + _GETUSERRESPONSE._serialized_start = 1084 + _GETUSERRESPONSE._serialized_end = 1153 + _CREATEUSERREQUEST._serialized_start = 1155 + _CREATEUSERREQUEST._serialized_end = 1258 + _CREATEUSERRESPONSE._serialized_start = 1260 + _CREATEUSERRESPONSE._serialized_end = 1371 + _UPDATEUSERREQUEST._serialized_start = 1374 + _UPDATEUSERREQUEST._serialized_end = 1520 + _UPDATEUSERRESPONSE._serialized_start = 1522 + _UPDATEUSERRESPONSE._serialized_end = 1616 + _DELETEUSERREQUEST._serialized_start = 1618 + _DELETEUSERREQUEST._serialized_end = 1708 + _DELETEUSERRESPONSE._serialized_start = 1710 + _DELETEUSERRESPONSE._serialized_end = 1804 + _SETUSERNAMESPACEACCESSREQUEST._serialized_start = 1807 + _SETUSERNAMESPACEACCESSREQUEST._serialized_end = 1993 + _SETUSERNAMESPACEACCESSRESPONSE._serialized_start = 1995 + _SETUSERNAMESPACEACCESSRESPONSE._serialized_end = 2101 + _GETASYNCOPERATIONREQUEST._serialized_start = 2103 + _GETASYNCOPERATIONREQUEST._serialized_end = 2157 + _GETASYNCOPERATIONRESPONSE._serialized_start = 2159 + _GETASYNCOPERATIONRESPONSE._serialized_end = 2260 + _CREATENAMESPACEREQUEST._serialized_start = 2263 + _CREATENAMESPACEREQUEST._serialized_end = 2506 + _CREATENAMESPACEREQUEST_TAGSENTRY._serialized_start = 2463 + _CREATENAMESPACEREQUEST_TAGSENTRY._serialized_end = 2506 + _CREATENAMESPACERESPONSE._serialized_start = 2508 + _CREATENAMESPACERESPONSE._serialized_end = 2626 + _GETNAMESPACESREQUEST._serialized_start = 2628 + _GETNAMESPACESREQUEST._serialized_end = 2703 + _GETNAMESPACESRESPONSE._serialized_start = 2705 + _GETNAMESPACESRESPONSE._serialized_end = 2817 + _GETNAMESPACEREQUEST._serialized_start = 2819 + _GETNAMESPACEREQUEST._serialized_end = 2859 + _GETNAMESPACERESPONSE._serialized_start = 2861 + _GETNAMESPACERESPONSE._serialized_end = 2946 + _UPDATENAMESPACEREQUEST._serialized_start = 2949 + _UPDATENAMESPACEREQUEST._serialized_end = 3108 + _UPDATENAMESPACERESPONSE._serialized_start = 3110 + _UPDATENAMESPACERESPONSE._serialized_end = 3209 + _RENAMECUSTOMSEARCHATTRIBUTEREQUEST._serialized_start = 3212 + _RENAMECUSTOMSEARCHATTRIBUTEREQUEST._serialized_end = 3410 + _RENAMECUSTOMSEARCHATTRIBUTERESPONSE._serialized_start = 3412 + _RENAMECUSTOMSEARCHATTRIBUTERESPONSE._serialized_end = 3523 + _DELETENAMESPACEREQUEST._serialized_start = 3525 + _DELETENAMESPACEREQUEST._serialized_end = 3622 + _DELETENAMESPACERESPONSE._serialized_start = 3624 + _DELETENAMESPACERESPONSE._serialized_end = 3723 + _FAILOVERNAMESPACEREGIONREQUEST._serialized_start = 3725 + _FAILOVERNAMESPACEREGIONREQUEST._serialized_end = 3820 + _FAILOVERNAMESPACEREGIONRESPONSE._serialized_start = 3822 + _FAILOVERNAMESPACEREGIONRESPONSE._serialized_end = 3929 + _ADDNAMESPACEREGIONREQUEST._serialized_start = 3931 + _ADDNAMESPACEREGIONREQUEST._serialized_end = 4047 + _ADDNAMESPACEREGIONRESPONSE._serialized_start = 4049 + _ADDNAMESPACEREGIONRESPONSE._serialized_end = 4151 + _DELETENAMESPACEREGIONREQUEST._serialized_start = 4153 + _DELETENAMESPACEREGIONREQUEST._serialized_end = 4272 + _DELETENAMESPACEREGIONRESPONSE._serialized_start = 4274 + _DELETENAMESPACEREGIONRESPONSE._serialized_end = 4379 + _GETREGIONSREQUEST._serialized_start = 4381 + _GETREGIONSREQUEST._serialized_end = 4400 + _GETREGIONSRESPONSE._serialized_start = 4402 + _GETREGIONSRESPONSE._serialized_end = 4477 + _GETREGIONREQUEST._serialized_start = 4479 + _GETREGIONREQUEST._serialized_end = 4513 + _GETREGIONRESPONSE._serialized_start = 4515 + _GETREGIONRESPONSE._serialized_end = 4588 + _GETAPIKEYSREQUEST._serialized_start = 4591 + _GETAPIKEYSREQUEST._serialized_end = 4765 + _GETAPIKEYSRESPONSE._serialized_start = 4767 + _GETAPIKEYSRESPONSE._serialized_end = 4870 + _GETAPIKEYREQUEST._serialized_start = 4872 + _GETAPIKEYREQUEST._serialized_end = 4906 + _GETAPIKEYRESPONSE._serialized_start = 4908 + _GETAPIKEYRESPONSE._serialized_end = 4984 + _CREATEAPIKEYREQUEST._serialized_start = 4986 + _CREATEAPIKEYREQUEST._serialized_end = 5093 + _CREATEAPIKEYRESPONSE._serialized_start = 5095 + _CREATEAPIKEYRESPONSE._serialized_end = 5222 + _UPDATEAPIKEYREQUEST._serialized_start = 5225 + _UPDATEAPIKEYREQUEST._serialized_end = 5374 + _UPDATEAPIKEYRESPONSE._serialized_start = 5376 + _UPDATEAPIKEYRESPONSE._serialized_end = 5472 + _DELETEAPIKEYREQUEST._serialized_start = 5474 + _DELETEAPIKEYREQUEST._serialized_end = 5565 + _DELETEAPIKEYRESPONSE._serialized_start = 5567 + _DELETEAPIKEYRESPONSE._serialized_end = 5663 + _GETNEXUSENDPOINTSREQUEST._serialized_start = 5666 + _GETNEXUSENDPOINTSREQUEST._serialized_end = 5801 + _GETNEXUSENDPOINTSRESPONSE._serialized_start = 5803 + _GETNEXUSENDPOINTSRESPONSE._serialized_end = 5913 + _GETNEXUSENDPOINTREQUEST._serialized_start = 5915 + _GETNEXUSENDPOINTREQUEST._serialized_end = 5961 + _GETNEXUSENDPOINTRESPONSE._serialized_start = 5963 + _GETNEXUSENDPOINTRESPONSE._serialized_end = 6046 + _CREATENEXUSENDPOINTREQUEST._serialized_start = 6048 + _CREATENEXUSENDPOINTREQUEST._serialized_end = 6161 + _CREATENEXUSENDPOINTRESPONSE._serialized_start = 6163 + _CREATENEXUSENDPOINTRESPONSE._serialized_end = 6287 + _UPDATENEXUSENDPOINTREQUEST._serialized_start = 6290 + _UPDATENEXUSENDPOINTREQUEST._serialized_end = 6450 + _UPDATENEXUSENDPOINTRESPONSE._serialized_start = 6452 + _UPDATENEXUSENDPOINTRESPONSE._serialized_end = 6555 + _DELETENEXUSENDPOINTREQUEST._serialized_start = 6557 + _DELETENEXUSENDPOINTREQUEST._serialized_end = 6660 + _DELETENEXUSENDPOINTRESPONSE._serialized_start = 6662 + _DELETENEXUSENDPOINTRESPONSE._serialized_end = 6765 + _GETUSERGROUPSREQUEST._serialized_start = 6768 + _GETUSERGROUPSREQUEST._serialized_end = 7141 + _GETUSERGROUPSREQUEST_GOOGLEGROUPFILTER._serialized_start = 7064 + _GETUSERGROUPSREQUEST_GOOGLEGROUPFILTER._serialized_end = 7106 + _GETUSERGROUPSREQUEST_SCIMGROUPFILTER._serialized_start = 7108 + _GETUSERGROUPSREQUEST_SCIMGROUPFILTER._serialized_end = 7141 + _GETUSERGROUPSRESPONSE._serialized_start = 7143 + _GETUSERGROUPSRESPONSE._serialized_end = 7250 + _GETUSERGROUPREQUEST._serialized_start = 7252 + _GETUSERGROUPREQUEST._serialized_end = 7291 + _GETUSERGROUPRESPONSE._serialized_start = 7293 + _GETUSERGROUPRESPONSE._serialized_end = 7373 + _CREATEUSERGROUPREQUEST._serialized_start = 7375 + _CREATEUSERGROUPREQUEST._serialized_end = 7488 + _CREATEUSERGROUPRESPONSE._serialized_start = 7490 + _CREATEUSERGROUPRESPONSE._serialized_end = 7607 + _UPDATEUSERGROUPREQUEST._serialized_start = 7610 + _UPDATEUSERGROUPREQUEST._serialized_end = 7767 + _UPDATEUSERGROUPRESPONSE._serialized_start = 7769 + _UPDATEUSERGROUPRESPONSE._serialized_end = 7868 + _DELETEUSERGROUPREQUEST._serialized_start = 7870 + _DELETEUSERGROUPREQUEST._serialized_end = 7966 + _DELETEUSERGROUPRESPONSE._serialized_start = 7968 + _DELETEUSERGROUPRESPONSE._serialized_end = 8067 + _SETUSERGROUPNAMESPACEACCESSREQUEST._serialized_start = 8070 + _SETUSERGROUPNAMESPACEACCESSREQUEST._serialized_end = 8262 + _SETUSERGROUPNAMESPACEACCESSRESPONSE._serialized_start = 8264 + _SETUSERGROUPNAMESPACEACCESSRESPONSE._serialized_end = 8375 + _ADDUSERGROUPMEMBERREQUEST._serialized_start = 8378 + _ADDUSERGROUPMEMBERREQUEST._serialized_end = 8521 + _ADDUSERGROUPMEMBERRESPONSE._serialized_start = 8523 + _ADDUSERGROUPMEMBERRESPONSE._serialized_end = 8625 + _REMOVEUSERGROUPMEMBERREQUEST._serialized_start = 8628 + _REMOVEUSERGROUPMEMBERREQUEST._serialized_end = 8774 + _REMOVEUSERGROUPMEMBERRESPONSE._serialized_start = 8776 + _REMOVEUSERGROUPMEMBERRESPONSE._serialized_end = 8881 + _GETUSERGROUPMEMBERSREQUEST._serialized_start = 8883 + _GETUSERGROUPMEMBERSREQUEST._serialized_end = 8968 + _GETUSERGROUPMEMBERSRESPONSE._serialized_start = 8970 + _GETUSERGROUPMEMBERSRESPONSE._serialized_end = 9090 + _CREATESERVICEACCOUNTREQUEST._serialized_start = 9092 + _CREATESERVICEACCOUNTREQUEST._serialized_end = 9215 + _CREATESERVICEACCOUNTRESPONSE._serialized_start = 9218 + _CREATESERVICEACCOUNTRESPONSE._serialized_end = 9350 + _GETSERVICEACCOUNTREQUEST._serialized_start = 9352 + _GETSERVICEACCOUNTREQUEST._serialized_end = 9406 + _GETSERVICEACCOUNTRESPONSE._serialized_start = 9408 + _GETSERVICEACCOUNTRESPONSE._serialized_end = 9508 + _GETSERVICEACCOUNTSREQUEST._serialized_start = 9510 + _GETSERVICEACCOUNTSREQUEST._serialized_end = 9576 + _GETSERVICEACCOUNTSRESPONSE._serialized_start = 9578 + _GETSERVICEACCOUNTSRESPONSE._serialized_end = 9704 + _UPDATESERVICEACCOUNTREQUEST._serialized_start = 9707 + _UPDATESERVICEACCOUNTREQUEST._serialized_end = 9884 + _UPDATESERVICEACCOUNTRESPONSE._serialized_start = 9886 + _UPDATESERVICEACCOUNTRESPONSE._serialized_end = 9990 + _SETSERVICEACCOUNTNAMESPACEACCESSREQUEST._serialized_start = 9993 + _SETSERVICEACCOUNTNAMESPACEACCESSREQUEST._serialized_end = 10200 + _SETSERVICEACCOUNTNAMESPACEACCESSRESPONSE._serialized_start = 10202 + _SETSERVICEACCOUNTNAMESPACEACCESSRESPONSE._serialized_end = 10318 + _DELETESERVICEACCOUNTREQUEST._serialized_start = 10320 + _DELETESERVICEACCOUNTREQUEST._serialized_end = 10431 + _DELETESERVICEACCOUNTRESPONSE._serialized_start = 10433 + _DELETESERVICEACCOUNTRESPONSE._serialized_end = 10537 + _GETUSAGEREQUEST._serialized_start = 10540 + _GETUSAGEREQUEST._serialized_end = 10710 + _GETUSAGERESPONSE._serialized_start = 10712 + _GETUSAGERESPONSE._serialized_end = 10812 + _GETACCOUNTREQUEST._serialized_start = 10814 + _GETACCOUNTREQUEST._serialized_end = 10833 + _GETACCOUNTRESPONSE._serialized_start = 10835 + _GETACCOUNTRESPONSE._serialized_end = 10912 + _UPDATEACCOUNTREQUEST._serialized_start = 10915 + _UPDATEACCOUNTREQUEST._serialized_end = 11049 + _UPDATEACCOUNTRESPONSE._serialized_start = 11051 + _UPDATEACCOUNTRESPONSE._serialized_end = 11148 + _CREATENAMESPACEEXPORTSINKREQUEST._serialized_start = 11151 + _CREATENAMESPACEEXPORTSINKREQUEST._serialized_end = 11295 + _CREATENAMESPACEEXPORTSINKRESPONSE._serialized_start = 11297 + _CREATENAMESPACEEXPORTSINKRESPONSE._serialized_end = 11406 + _GETNAMESPACEEXPORTSINKREQUEST._serialized_start = 11408 + _GETNAMESPACEEXPORTSINKREQUEST._serialized_end = 11472 + _GETNAMESPACEEXPORTSINKRESPONSE._serialized_start = 11474 + _GETNAMESPACEEXPORTSINKRESPONSE._serialized_end = 11565 + _GETNAMESPACEEXPORTSINKSREQUEST._serialized_start = 11567 + _GETNAMESPACEEXPORTSINKSREQUEST._serialized_end = 11657 + _GETNAMESPACEEXPORTSINKSRESPONSE._serialized_start = 11659 + _GETNAMESPACEEXPORTSINKSRESPONSE._serialized_end = 11777 + _UPDATENAMESPACEEXPORTSINKREQUEST._serialized_start = 11780 + _UPDATENAMESPACEEXPORTSINKREQUEST._serialized_end = 11950 + _UPDATENAMESPACEEXPORTSINKRESPONSE._serialized_start = 11952 + _UPDATENAMESPACEEXPORTSINKRESPONSE._serialized_end = 12061 + _DELETENAMESPACEEXPORTSINKREQUEST._serialized_start = 12063 + _DELETENAMESPACEEXPORTSINKREQUEST._serialized_end = 12184 + _DELETENAMESPACEEXPORTSINKRESPONSE._serialized_start = 12186 + _DELETENAMESPACEEXPORTSINKRESPONSE._serialized_end = 12295 + _VALIDATENAMESPACEEXPORTSINKREQUEST._serialized_start = 12297 + _VALIDATENAMESPACEEXPORTSINKREQUEST._serialized_end = 12415 + _VALIDATENAMESPACEEXPORTSINKRESPONSE._serialized_start = 12417 + _VALIDATENAMESPACEEXPORTSINKRESPONSE._serialized_end = 12454 + _UPDATENAMESPACETAGSREQUEST._serialized_start = 12457 + _UPDATENAMESPACETAGSREQUEST._serialized_end = 12715 + _UPDATENAMESPACETAGSREQUEST_TAGSTOUPSERTENTRY._serialized_start = 12664 + _UPDATENAMESPACETAGSREQUEST_TAGSTOUPSERTENTRY._serialized_end = 12715 + _UPDATENAMESPACETAGSRESPONSE._serialized_start = 12717 + _UPDATENAMESPACETAGSRESPONSE._serialized_end = 12820 + _CREATECONNECTIVITYRULEREQUEST._serialized_start = 12823 + _CREATECONNECTIVITYRULEREQUEST._serialized_end = 12958 + _CREATECONNECTIVITYRULERESPONSE._serialized_start = 12961 + _CREATECONNECTIVITYRULERESPONSE._serialized_end = 13097 + _GETCONNECTIVITYRULEREQUEST._serialized_start = 13099 + _GETCONNECTIVITYRULEREQUEST._serialized_end = 13157 + _GETCONNECTIVITYRULERESPONSE._serialized_start = 13159 + _GETCONNECTIVITYRULERESPONSE._serialized_end = 13273 + _GETCONNECTIVITYRULESREQUEST._serialized_start = 13275 + _GETCONNECTIVITYRULESREQUEST._serialized_end = 13362 + _GETCONNECTIVITYRULESRESPONSE._serialized_start = 13365 + _GETCONNECTIVITYRULESRESPONSE._serialized_end = 13506 + _DELETECONNECTIVITYRULEREQUEST._serialized_start = 13508 + _DELETECONNECTIVITYRULEREQUEST._serialized_end = 13623 + _DELETECONNECTIVITYRULERESPONSE._serialized_start = 13625 + _DELETECONNECTIVITYRULERESPONSE._serialized_end = 13731 + _GETAUDITLOGSREQUEST._serialized_start = 13734 + _GETAUDITLOGSREQUEST._serialized_end = 13908 + _GETAUDITLOGSRESPONSE._serialized_start = 13910 + _GETAUDITLOGSRESPONSE._serialized_end = 14014 + _VALIDATEACCOUNTAUDITLOGSINKREQUEST._serialized_start = 14016 + _VALIDATEACCOUNTAUDITLOGSINKREQUEST._serialized_end = 14115 + _VALIDATEACCOUNTAUDITLOGSINKRESPONSE._serialized_start = 14117 + _VALIDATEACCOUNTAUDITLOGSINKRESPONSE._serialized_end = 14154 + _CREATEACCOUNTAUDITLOGSINKREQUEST._serialized_start = 14156 + _CREATEACCOUNTAUDITLOGSINKREQUEST._serialized_end = 14281 + _CREATEACCOUNTAUDITLOGSINKRESPONSE._serialized_start = 14283 + _CREATEACCOUNTAUDITLOGSINKRESPONSE._serialized_end = 14392 + _GETACCOUNTAUDITLOGSINKREQUEST._serialized_start = 14394 + _GETACCOUNTAUDITLOGSINKREQUEST._serialized_end = 14439 + _GETACCOUNTAUDITLOGSINKRESPONSE._serialized_start = 14441 + _GETACCOUNTAUDITLOGSINKRESPONSE._serialized_end = 14532 + _GETACCOUNTAUDITLOGSINKSREQUEST._serialized_start = 14534 + _GETACCOUNTAUDITLOGSINKSREQUEST._serialized_end = 14605 + _GETACCOUNTAUDITLOGSINKSRESPONSE._serialized_start = 14607 + _GETACCOUNTAUDITLOGSINKSRESPONSE._serialized_end = 14725 + _UPDATEACCOUNTAUDITLOGSINKREQUEST._serialized_start = 14728 + _UPDATEACCOUNTAUDITLOGSINKREQUEST._serialized_end = 14879 + _UPDATEACCOUNTAUDITLOGSINKRESPONSE._serialized_start = 14881 + _UPDATEACCOUNTAUDITLOGSINKRESPONSE._serialized_end = 14990 + _DELETEACCOUNTAUDITLOGSINKREQUEST._serialized_start = 14992 + _DELETEACCOUNTAUDITLOGSINKREQUEST._serialized_end = 15094 + _DELETEACCOUNTAUDITLOGSINKRESPONSE._serialized_start = 15096 + _DELETEACCOUNTAUDITLOGSINKRESPONSE._serialized_end = 15205 + _GETNAMESPACECAPACITYINFOREQUEST._serialized_start = 15207 + _GETNAMESPACECAPACITYINFOREQUEST._serialized_end = 15259 + _GETNAMESPACECAPACITYINFORESPONSE._serialized_start = 15261 + _GETNAMESPACECAPACITYINFORESPONSE._serialized_end = 15374 + _CREATEBILLINGREPORTREQUEST._serialized_start = 15376 + _CREATEBILLINGREPORTREQUEST._serialized_end = 15496 + _CREATEBILLINGREPORTRESPONSE._serialized_start = 15499 + _CREATEBILLINGREPORTRESPONSE._serialized_end = 15629 + _GETBILLINGREPORTREQUEST._serialized_start = 15631 + _GETBILLINGREPORTREQUEST._serialized_end = 15683 + _GETBILLINGREPORTRESPONSE._serialized_start = 15685 + _GETBILLINGREPORTRESPONSE._serialized_end = 15781 # @@protoc_insertion_point(module_scope) diff --git a/temporalio/api/cloud/cloudservice/v1/request_response_pb2.pyi b/temporalio/api/cloud/cloudservice/v1/request_response_pb2.pyi index 2d41774e1..9de8a7930 100644 --- a/temporalio/api/cloud/cloudservice/v1/request_response_pb2.pyi +++ b/temporalio/api/cloud/cloudservice/v1/request_response_pb2.pyi @@ -13,6 +13,8 @@ import google.protobuf.message import google.protobuf.timestamp_pb2 import temporalio.api.cloud.account.v1.message_pb2 +import temporalio.api.cloud.auditlog.v1.message_pb2 +import temporalio.api.cloud.billing.v1.message_pb2 import temporalio.api.cloud.connectivityrule.v1.message_pb2 import temporalio.api.cloud.identity.v1.message_pb2 import temporalio.api.cloud.namespace.v1.message_pb2 @@ -28,6 +30,73 @@ else: DESCRIPTOR: google.protobuf.descriptor.FileDescriptor +class GetCurrentIdentityRequest(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + def __init__( + self, + ) -> None: ... + +global___GetCurrentIdentityRequest = GetCurrentIdentityRequest + +class GetCurrentIdentityResponse(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + USER_FIELD_NUMBER: builtins.int + SERVICE_ACCOUNT_FIELD_NUMBER: builtins.int + PRINCIPAL_API_KEY_FIELD_NUMBER: builtins.int + @property + def user(self) -> temporalio.api.cloud.identity.v1.message_pb2.User: + """The user is a regular user""" + @property + def service_account( + self, + ) -> temporalio.api.cloud.identity.v1.message_pb2.ServiceAccount: + """The user is a service account""" + @property + def principal_api_key(self) -> temporalio.api.cloud.identity.v1.message_pb2.ApiKey: + """The API key info used to authenticate the request, if any""" + def __init__( + self, + *, + user: temporalio.api.cloud.identity.v1.message_pb2.User | None = ..., + service_account: temporalio.api.cloud.identity.v1.message_pb2.ServiceAccount + | None = ..., + principal_api_key: temporalio.api.cloud.identity.v1.message_pb2.ApiKey + | None = ..., + ) -> None: ... + def HasField( + self, + field_name: typing_extensions.Literal[ + "principal", + b"principal", + "principal_api_key", + b"principal_api_key", + "service_account", + b"service_account", + "user", + b"user", + ], + ) -> builtins.bool: ... + def ClearField( + self, + field_name: typing_extensions.Literal[ + "principal", + b"principal", + "principal_api_key", + b"principal_api_key", + "service_account", + b"service_account", + "user", + b"user", + ], + ) -> None: ... + def WhichOneof( + self, oneof_group: typing_extensions.Literal["principal", b"principal"] + ) -> typing_extensions.Literal["user", "service_account"] | None: ... + +global___GetCurrentIdentityResponse = GetCurrentIdentityResponse + class GetUsersRequest(google.protobuf.message.Message): DESCRIPTOR: google.protobuf.descriptor.Descriptor @@ -1157,6 +1226,7 @@ class GetApiKeysRequest(google.protobuf.message.Message): owner_type_deprecated: builtins.str """Filter api keys by owner type - optional. Possible values: user, service-account + temporal:versioning:max_version=v0.3.0 """ owner_type: temporalio.api.cloud.identity.v1.message_pb2.OwnerType.ValueType """Filter api keys by owner type - optional. @@ -3688,6 +3758,90 @@ class DeleteConnectivityRuleResponse(google.protobuf.message.Message): global___DeleteConnectivityRuleResponse = DeleteConnectivityRuleResponse +class GetAuditLogsRequest(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + PAGE_SIZE_FIELD_NUMBER: builtins.int + PAGE_TOKEN_FIELD_NUMBER: builtins.int + START_TIME_INCLUSIVE_FIELD_NUMBER: builtins.int + END_TIME_EXCLUSIVE_FIELD_NUMBER: builtins.int + page_size: builtins.int + """The requested size of the page to retrieve - optional. + Cannot exceed 1000. Defaults to 100. + """ + page_token: builtins.str + """The page token if this is continuing from another response - optional.""" + @property + def start_time_inclusive(self) -> google.protobuf.timestamp_pb2.Timestamp: + """Filter for UTC time >= (defaults to 30 days ago) - optional.""" + @property + def end_time_exclusive(self) -> google.protobuf.timestamp_pb2.Timestamp: + """Filter for UTC time < (defaults to current time) - optional.""" + def __init__( + self, + *, + page_size: builtins.int = ..., + page_token: builtins.str = ..., + start_time_inclusive: google.protobuf.timestamp_pb2.Timestamp | None = ..., + end_time_exclusive: google.protobuf.timestamp_pb2.Timestamp | None = ..., + ) -> None: ... + def HasField( + self, + field_name: typing_extensions.Literal[ + "end_time_exclusive", + b"end_time_exclusive", + "start_time_inclusive", + b"start_time_inclusive", + ], + ) -> builtins.bool: ... + def ClearField( + self, + field_name: typing_extensions.Literal[ + "end_time_exclusive", + b"end_time_exclusive", + "page_size", + b"page_size", + "page_token", + b"page_token", + "start_time_inclusive", + b"start_time_inclusive", + ], + ) -> None: ... + +global___GetAuditLogsRequest = GetAuditLogsRequest + +class GetAuditLogsResponse(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + LOGS_FIELD_NUMBER: builtins.int + NEXT_PAGE_TOKEN_FIELD_NUMBER: builtins.int + @property + def logs( + self, + ) -> google.protobuf.internal.containers.RepeatedCompositeFieldContainer[ + temporalio.api.cloud.auditlog.v1.message_pb2.LogRecord + ]: + """The list of audit logs ordered by emit time, log_id""" + next_page_token: builtins.str + """The next page's token.""" + def __init__( + self, + *, + logs: collections.abc.Iterable[ + temporalio.api.cloud.auditlog.v1.message_pb2.LogRecord + ] + | None = ..., + next_page_token: builtins.str = ..., + ) -> None: ... + def ClearField( + self, + field_name: typing_extensions.Literal[ + "logs", b"logs", "next_page_token", b"next_page_token" + ], + ) -> None: ... + +global___GetAuditLogsResponse = GetAuditLogsResponse + class ValidateAccountAuditLogSinkRequest(google.protobuf.message.Message): DESCRIPTOR: google.protobuf.descriptor.Descriptor @@ -3717,3 +3871,430 @@ class ValidateAccountAuditLogSinkResponse(google.protobuf.message.Message): ) -> None: ... global___ValidateAccountAuditLogSinkResponse = ValidateAccountAuditLogSinkResponse + +class CreateAccountAuditLogSinkRequest(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + SPEC_FIELD_NUMBER: builtins.int + ASYNC_OPERATION_ID_FIELD_NUMBER: builtins.int + @property + def spec(self) -> temporalio.api.cloud.account.v1.message_pb2.AuditLogSinkSpec: + """The specification for the audit log sink.""" + async_operation_id: builtins.str + """Optional. The ID to use for this async operation.""" + def __init__( + self, + *, + spec: temporalio.api.cloud.account.v1.message_pb2.AuditLogSinkSpec | None = ..., + async_operation_id: builtins.str = ..., + ) -> None: ... + def HasField( + self, field_name: typing_extensions.Literal["spec", b"spec"] + ) -> builtins.bool: ... + def ClearField( + self, + field_name: typing_extensions.Literal[ + "async_operation_id", b"async_operation_id", "spec", b"spec" + ], + ) -> None: ... + +global___CreateAccountAuditLogSinkRequest = CreateAccountAuditLogSinkRequest + +class CreateAccountAuditLogSinkResponse(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + ASYNC_OPERATION_FIELD_NUMBER: builtins.int + @property + def async_operation( + self, + ) -> temporalio.api.cloud.operation.v1.message_pb2.AsyncOperation: + """The async operation.""" + def __init__( + self, + *, + async_operation: temporalio.api.cloud.operation.v1.message_pb2.AsyncOperation + | None = ..., + ) -> None: ... + def HasField( + self, + field_name: typing_extensions.Literal["async_operation", b"async_operation"], + ) -> builtins.bool: ... + def ClearField( + self, + field_name: typing_extensions.Literal["async_operation", b"async_operation"], + ) -> None: ... + +global___CreateAccountAuditLogSinkResponse = CreateAccountAuditLogSinkResponse + +class GetAccountAuditLogSinkRequest(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + NAME_FIELD_NUMBER: builtins.int + name: builtins.str + """The name of the sink to retrieve.""" + def __init__( + self, + *, + name: builtins.str = ..., + ) -> None: ... + def ClearField( + self, field_name: typing_extensions.Literal["name", b"name"] + ) -> None: ... + +global___GetAccountAuditLogSinkRequest = GetAccountAuditLogSinkRequest + +class GetAccountAuditLogSinkResponse(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + SINK_FIELD_NUMBER: builtins.int + @property + def sink(self) -> temporalio.api.cloud.account.v1.message_pb2.AuditLogSink: + """The audit log sink retrieved.""" + def __init__( + self, + *, + sink: temporalio.api.cloud.account.v1.message_pb2.AuditLogSink | None = ..., + ) -> None: ... + def HasField( + self, field_name: typing_extensions.Literal["sink", b"sink"] + ) -> builtins.bool: ... + def ClearField( + self, field_name: typing_extensions.Literal["sink", b"sink"] + ) -> None: ... + +global___GetAccountAuditLogSinkResponse = GetAccountAuditLogSinkResponse + +class GetAccountAuditLogSinksRequest(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + PAGE_SIZE_FIELD_NUMBER: builtins.int + PAGE_TOKEN_FIELD_NUMBER: builtins.int + page_size: builtins.int + """The requested size of the page to retrieve. Cannot exceed 1000. + Defaults to 100 if not specified. + """ + page_token: builtins.str + """The page token if this is continuing from another response - optional.""" + def __init__( + self, + *, + page_size: builtins.int = ..., + page_token: builtins.str = ..., + ) -> None: ... + def ClearField( + self, + field_name: typing_extensions.Literal[ + "page_size", b"page_size", "page_token", b"page_token" + ], + ) -> None: ... + +global___GetAccountAuditLogSinksRequest = GetAccountAuditLogSinksRequest + +class GetAccountAuditLogSinksResponse(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + SINKS_FIELD_NUMBER: builtins.int + NEXT_PAGE_TOKEN_FIELD_NUMBER: builtins.int + @property + def sinks( + self, + ) -> google.protobuf.internal.containers.RepeatedCompositeFieldContainer[ + temporalio.api.cloud.account.v1.message_pb2.AuditLogSink + ]: + """The list of audit log sinks retrieved.""" + next_page_token: builtins.str + """The next page token, set if there is another page.""" + def __init__( + self, + *, + sinks: collections.abc.Iterable[ + temporalio.api.cloud.account.v1.message_pb2.AuditLogSink + ] + | None = ..., + next_page_token: builtins.str = ..., + ) -> None: ... + def ClearField( + self, + field_name: typing_extensions.Literal[ + "next_page_token", b"next_page_token", "sinks", b"sinks" + ], + ) -> None: ... + +global___GetAccountAuditLogSinksResponse = GetAccountAuditLogSinksResponse + +class UpdateAccountAuditLogSinkRequest(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + SPEC_FIELD_NUMBER: builtins.int + RESOURCE_VERSION_FIELD_NUMBER: builtins.int + ASYNC_OPERATION_ID_FIELD_NUMBER: builtins.int + @property + def spec(self) -> temporalio.api.cloud.account.v1.message_pb2.AuditLogSinkSpec: + """The updated audit log sink specification.""" + resource_version: builtins.str + """The version of the audit log sink to update. The latest version can be + retrieved using the GetAuditLogSink call. + """ + async_operation_id: builtins.str + """The ID to use for this async operation - optional.""" + def __init__( + self, + *, + spec: temporalio.api.cloud.account.v1.message_pb2.AuditLogSinkSpec | None = ..., + resource_version: builtins.str = ..., + async_operation_id: builtins.str = ..., + ) -> None: ... + def HasField( + self, field_name: typing_extensions.Literal["spec", b"spec"] + ) -> builtins.bool: ... + def ClearField( + self, + field_name: typing_extensions.Literal[ + "async_operation_id", + b"async_operation_id", + "resource_version", + b"resource_version", + "spec", + b"spec", + ], + ) -> None: ... + +global___UpdateAccountAuditLogSinkRequest = UpdateAccountAuditLogSinkRequest + +class UpdateAccountAuditLogSinkResponse(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + ASYNC_OPERATION_FIELD_NUMBER: builtins.int + @property + def async_operation( + self, + ) -> temporalio.api.cloud.operation.v1.message_pb2.AsyncOperation: + """The async operation.""" + def __init__( + self, + *, + async_operation: temporalio.api.cloud.operation.v1.message_pb2.AsyncOperation + | None = ..., + ) -> None: ... + def HasField( + self, + field_name: typing_extensions.Literal["async_operation", b"async_operation"], + ) -> builtins.bool: ... + def ClearField( + self, + field_name: typing_extensions.Literal["async_operation", b"async_operation"], + ) -> None: ... + +global___UpdateAccountAuditLogSinkResponse = UpdateAccountAuditLogSinkResponse + +class DeleteAccountAuditLogSinkRequest(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + NAME_FIELD_NUMBER: builtins.int + RESOURCE_VERSION_FIELD_NUMBER: builtins.int + ASYNC_OPERATION_ID_FIELD_NUMBER: builtins.int + name: builtins.str + """The name of the sink to delete.""" + resource_version: builtins.str + """The version of the sink to delete. The latest version can be + retrieved using the GetAccountAuditLogSink call. + """ + async_operation_id: builtins.str + """The ID to use for this async operation - optional.""" + def __init__( + self, + *, + name: builtins.str = ..., + resource_version: builtins.str = ..., + async_operation_id: builtins.str = ..., + ) -> None: ... + def ClearField( + self, + field_name: typing_extensions.Literal[ + "async_operation_id", + b"async_operation_id", + "name", + b"name", + "resource_version", + b"resource_version", + ], + ) -> None: ... + +global___DeleteAccountAuditLogSinkRequest = DeleteAccountAuditLogSinkRequest + +class DeleteAccountAuditLogSinkResponse(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + ASYNC_OPERATION_FIELD_NUMBER: builtins.int + @property + def async_operation( + self, + ) -> temporalio.api.cloud.operation.v1.message_pb2.AsyncOperation: + """The async operation.""" + def __init__( + self, + *, + async_operation: temporalio.api.cloud.operation.v1.message_pb2.AsyncOperation + | None = ..., + ) -> None: ... + def HasField( + self, + field_name: typing_extensions.Literal["async_operation", b"async_operation"], + ) -> builtins.bool: ... + def ClearField( + self, + field_name: typing_extensions.Literal["async_operation", b"async_operation"], + ) -> None: ... + +global___DeleteAccountAuditLogSinkResponse = DeleteAccountAuditLogSinkResponse + +class GetNamespaceCapacityInfoRequest(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + NAMESPACE_FIELD_NUMBER: builtins.int + namespace: builtins.str + """The namespace identifier. + Required. + """ + def __init__( + self, + *, + namespace: builtins.str = ..., + ) -> None: ... + def ClearField( + self, field_name: typing_extensions.Literal["namespace", b"namespace"] + ) -> None: ... + +global___GetNamespaceCapacityInfoRequest = GetNamespaceCapacityInfoRequest + +class GetNamespaceCapacityInfoResponse(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + CAPACITY_INFO_FIELD_NUMBER: builtins.int + @property + def capacity_info( + self, + ) -> temporalio.api.cloud.namespace.v1.message_pb2.NamespaceCapacityInfo: + """Capacity information for the namespace.""" + def __init__( + self, + *, + capacity_info: temporalio.api.cloud.namespace.v1.message_pb2.NamespaceCapacityInfo + | None = ..., + ) -> None: ... + def HasField( + self, field_name: typing_extensions.Literal["capacity_info", b"capacity_info"] + ) -> builtins.bool: ... + def ClearField( + self, field_name: typing_extensions.Literal["capacity_info", b"capacity_info"] + ) -> None: ... + +global___GetNamespaceCapacityInfoResponse = GetNamespaceCapacityInfoResponse + +class CreateBillingReportRequest(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + SPEC_FIELD_NUMBER: builtins.int + ASYNC_OPERATION_ID_FIELD_NUMBER: builtins.int + @property + def spec(self) -> temporalio.api.cloud.billing.v1.message_pb2.BillingReportSpec: + """The specification for the billing report.""" + async_operation_id: builtins.str + """Optional, if not provided a random id will be generated.""" + def __init__( + self, + *, + spec: temporalio.api.cloud.billing.v1.message_pb2.BillingReportSpec + | None = ..., + async_operation_id: builtins.str = ..., + ) -> None: ... + def HasField( + self, field_name: typing_extensions.Literal["spec", b"spec"] + ) -> builtins.bool: ... + def ClearField( + self, + field_name: typing_extensions.Literal[ + "async_operation_id", b"async_operation_id", "spec", b"spec" + ], + ) -> None: ... + +global___CreateBillingReportRequest = CreateBillingReportRequest + +class CreateBillingReportResponse(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + BILLING_REPORT_ID_FIELD_NUMBER: builtins.int + ASYNC_OPERATION_FIELD_NUMBER: builtins.int + billing_report_id: builtins.str + """The id of the billing report created.""" + @property + def async_operation( + self, + ) -> temporalio.api.cloud.operation.v1.message_pb2.AsyncOperation: + """The async operation.""" + def __init__( + self, + *, + billing_report_id: builtins.str = ..., + async_operation: temporalio.api.cloud.operation.v1.message_pb2.AsyncOperation + | None = ..., + ) -> None: ... + def HasField( + self, + field_name: typing_extensions.Literal["async_operation", b"async_operation"], + ) -> builtins.bool: ... + def ClearField( + self, + field_name: typing_extensions.Literal[ + "async_operation", + b"async_operation", + "billing_report_id", + b"billing_report_id", + ], + ) -> None: ... + +global___CreateBillingReportResponse = CreateBillingReportResponse + +class GetBillingReportRequest(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + BILLING_REPORT_ID_FIELD_NUMBER: builtins.int + billing_report_id: builtins.str + """The id of the billing report to retrieve.""" + def __init__( + self, + *, + billing_report_id: builtins.str = ..., + ) -> None: ... + def ClearField( + self, + field_name: typing_extensions.Literal[ + "billing_report_id", b"billing_report_id" + ], + ) -> None: ... + +global___GetBillingReportRequest = GetBillingReportRequest + +class GetBillingReportResponse(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + BILLING_REPORT_FIELD_NUMBER: builtins.int + @property + def billing_report( + self, + ) -> temporalio.api.cloud.billing.v1.message_pb2.BillingReport: + """The billing report retrieved.""" + def __init__( + self, + *, + billing_report: temporalio.api.cloud.billing.v1.message_pb2.BillingReport + | None = ..., + ) -> None: ... + def HasField( + self, field_name: typing_extensions.Literal["billing_report", b"billing_report"] + ) -> builtins.bool: ... + def ClearField( + self, field_name: typing_extensions.Literal["billing_report", b"billing_report"] + ) -> None: ... + +global___GetBillingReportResponse = GetBillingReportResponse diff --git a/temporalio/api/cloud/cloudservice/v1/service_pb2.py b/temporalio/api/cloud/cloudservice/v1/service_pb2.py index 6a5d7beab..c7c772860 100644 --- a/temporalio/api/cloud/cloudservice/v1/service_pb2.py +++ b/temporalio/api/cloud/cloudservice/v1/service_pb2.py @@ -19,308 +19,291 @@ from temporalio.api.cloud.cloudservice.v1 import ( request_response_pb2 as temporal_dot_api_dot_cloud_dot_cloudservice_dot_v1_dot_request__response__pb2, ) +from temporalio.api.dependencies.protoc_gen_openapiv2.options import ( + annotations_pb2 as protoc__gen__openapiv2_dot_options_dot_annotations__pb2, +) DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile( - b'\n0temporal/api/cloud/cloudservice/v1/service.proto\x12"temporal.api.cloud.cloudservice.v1\x1a\x39temporal/api/cloud/cloudservice/v1/request_response.proto\x1a\x1cgoogle/api/annotations.proto2\xeeV\n\x0c\x43loudService\x12\x8b\x01\n\x08GetUsers\x12\x33.temporal.api.cloud.cloudservice.v1.GetUsersRequest\x1a\x34.temporal.api.cloud.cloudservice.v1.GetUsersResponse"\x14\x82\xd3\xe4\x93\x02\x0e\x12\x0c/cloud/users\x12\x92\x01\n\x07GetUser\x12\x32.temporal.api.cloud.cloudservice.v1.GetUserRequest\x1a\x33.temporal.api.cloud.cloudservice.v1.GetUserResponse"\x1e\x82\xd3\xe4\x93\x02\x18\x12\x16/cloud/users/{user_id}\x12\x94\x01\n\nCreateUser\x12\x35.temporal.api.cloud.cloudservice.v1.CreateUserRequest\x1a\x36.temporal.api.cloud.cloudservice.v1.CreateUserResponse"\x17\x82\xd3\xe4\x93\x02\x11"\x0c/cloud/users:\x01*\x12\x9e\x01\n\nUpdateUser\x12\x35.temporal.api.cloud.cloudservice.v1.UpdateUserRequest\x1a\x36.temporal.api.cloud.cloudservice.v1.UpdateUserResponse"!\x82\xd3\xe4\x93\x02\x1b"\x16/cloud/users/{user_id}:\x01*\x12\x9b\x01\n\nDeleteUser\x12\x35.temporal.api.cloud.cloudservice.v1.DeleteUserRequest\x1a\x36.temporal.api.cloud.cloudservice.v1.DeleteUserResponse"\x1e\x82\xd3\xe4\x93\x02\x18*\x16/cloud/users/{user_id}\x12\xe0\x01\n\x16SetUserNamespaceAccess\x12\x41.temporal.api.cloud.cloudservice.v1.SetUserNamespaceAccessRequest\x1a\x42.temporal.api.cloud.cloudservice.v1.SetUserNamespaceAccessResponse"?\x82\xd3\xe4\x93\x02\x39"4/cloud/namespaces/{namespace}/users/{user_id}/access:\x01*\x12\xc0\x01\n\x11GetAsyncOperation\x12<.temporal.api.cloud.cloudservice.v1.GetAsyncOperationRequest\x1a=.temporal.api.cloud.cloudservice.v1.GetAsyncOperationResponse".\x82\xd3\xe4\x93\x02(\x12&/cloud/operations/{async_operation_id}\x12\xa8\x01\n\x0f\x43reateNamespace\x12:.temporal.api.cloud.cloudservice.v1.CreateNamespaceRequest\x1a;.temporal.api.cloud.cloudservice.v1.CreateNamespaceResponse"\x1c\x82\xd3\xe4\x93\x02\x16"\x11/cloud/namespaces:\x01*\x12\x9f\x01\n\rGetNamespaces\x12\x38.temporal.api.cloud.cloudservice.v1.GetNamespacesRequest\x1a\x39.temporal.api.cloud.cloudservice.v1.GetNamespacesResponse"\x19\x82\xd3\xe4\x93\x02\x13\x12\x11/cloud/namespaces\x12\xa8\x01\n\x0cGetNamespace\x12\x37.temporal.api.cloud.cloudservice.v1.GetNamespaceRequest\x1a\x38.temporal.api.cloud.cloudservice.v1.GetNamespaceResponse"%\x82\xd3\xe4\x93\x02\x1f\x12\x1d/cloud/namespaces/{namespace}\x12\xb4\x01\n\x0fUpdateNamespace\x12:.temporal.api.cloud.cloudservice.v1.UpdateNamespaceRequest\x1a;.temporal.api.cloud.cloudservice.v1.UpdateNamespaceResponse"(\x82\xd3\xe4\x93\x02""\x1d/cloud/namespaces/{namespace}:\x01*\x12\xf7\x01\n\x1bRenameCustomSearchAttribute\x12\x46.temporal.api.cloud.cloudservice.v1.RenameCustomSearchAttributeRequest\x1aG.temporal.api.cloud.cloudservice.v1.RenameCustomSearchAttributeResponse"G\x82\xd3\xe4\x93\x02\x41".temporal.api.cloud.cloudservice.v1.AddNamespaceRegionResponse"3\x82\xd3\xe4\x93\x02-"(/cloud/namespaces/{namespace}/add-region:\x01*\x12\xd4\x01\n\x15\x44\x65leteNamespaceRegion\x12@.temporal.api.cloud.cloudservice.v1.DeleteNamespaceRegionRequest\x1a\x41.temporal.api.cloud.cloudservice.v1.DeleteNamespaceRegionResponse"6\x82\xd3\xe4\x93\x02\x30*./cloud/namespaces/{namespace}/regions/{region}\x12\x93\x01\n\nGetRegions\x12\x35.temporal.api.cloud.cloudservice.v1.GetRegionsRequest\x1a\x36.temporal.api.cloud.cloudservice.v1.GetRegionsResponse"\x16\x82\xd3\xe4\x93\x02\x10\x12\x0e/cloud/regions\x12\x99\x01\n\tGetRegion\x12\x34.temporal.api.cloud.cloudservice.v1.GetRegionRequest\x1a\x35.temporal.api.cloud.cloudservice.v1.GetRegionResponse"\x1f\x82\xd3\xe4\x93\x02\x19\x12\x17/cloud/regions/{region}\x12\x94\x01\n\nGetApiKeys\x12\x35.temporal.api.cloud.cloudservice.v1.GetApiKeysRequest\x1a\x36.temporal.api.cloud.cloudservice.v1.GetApiKeysResponse"\x17\x82\xd3\xe4\x93\x02\x11\x12\x0f/cloud/api-keys\x12\x9a\x01\n\tGetApiKey\x12\x34.temporal.api.cloud.cloudservice.v1.GetApiKeyRequest\x1a\x35.temporal.api.cloud.cloudservice.v1.GetApiKeyResponse" \x82\xd3\xe4\x93\x02\x1a\x12\x18/cloud/api-keys/{key_id}\x12\x9d\x01\n\x0c\x43reateApiKey\x12\x37.temporal.api.cloud.cloudservice.v1.CreateApiKeyRequest\x1a\x38.temporal.api.cloud.cloudservice.v1.CreateApiKeyResponse"\x1a\x82\xd3\xe4\x93\x02\x14"\x0f/cloud/api-keys:\x01*\x12\xa6\x01\n\x0cUpdateApiKey\x12\x37.temporal.api.cloud.cloudservice.v1.UpdateApiKeyRequest\x1a\x38.temporal.api.cloud.cloudservice.v1.UpdateApiKeyResponse"#\x82\xd3\xe4\x93\x02\x1d"\x18/cloud/api-keys/{key_id}:\x01*\x12\xa3\x01\n\x0c\x44\x65leteApiKey\x12\x37.temporal.api.cloud.cloudservice.v1.DeleteApiKeyRequest\x1a\x38.temporal.api.cloud.cloudservice.v1.DeleteApiKeyResponse" \x82\xd3\xe4\x93\x02\x1a*\x18/cloud/api-keys/{key_id}\x12\xb0\x01\n\x11GetNexusEndpoints\x12<.temporal.api.cloud.cloudservice.v1.GetNexusEndpointsRequest\x1a=.temporal.api.cloud.cloudservice.v1.GetNexusEndpointsResponse"\x1e\x82\xd3\xe4\x93\x02\x18\x12\x16/cloud/nexus/endpoints\x12\xbb\x01\n\x10GetNexusEndpoint\x12;.temporal.api.cloud.cloudservice.v1.GetNexusEndpointRequest\x1a<.temporal.api.cloud.cloudservice.v1.GetNexusEndpointResponse",\x82\xd3\xe4\x93\x02&\x12$/cloud/nexus/endpoints/{endpoint_id}\x12\xb9\x01\n\x13\x43reateNexusEndpoint\x12>.temporal.api.cloud.cloudservice.v1.CreateNexusEndpointRequest\x1a?.temporal.api.cloud.cloudservice.v1.CreateNexusEndpointResponse"!\x82\xd3\xe4\x93\x02\x1b"\x16/cloud/nexus/endpoints:\x01*\x12\xc7\x01\n\x13UpdateNexusEndpoint\x12>.temporal.api.cloud.cloudservice.v1.UpdateNexusEndpointRequest\x1a?.temporal.api.cloud.cloudservice.v1.UpdateNexusEndpointResponse"/\x82\xd3\xe4\x93\x02)"$/cloud/nexus/endpoints/{endpoint_id}:\x01*\x12\xc4\x01\n\x13\x44\x65leteNexusEndpoint\x12>.temporal.api.cloud.cloudservice.v1.DeleteNexusEndpointRequest\x1a?.temporal.api.cloud.cloudservice.v1.DeleteNexusEndpointResponse",\x82\xd3\xe4\x93\x02&*$/cloud/nexus/endpoints/{endpoint_id}\x12\xa0\x01\n\rGetUserGroups\x12\x38.temporal.api.cloud.cloudservice.v1.GetUserGroupsRequest\x1a\x39.temporal.api.cloud.cloudservice.v1.GetUserGroupsResponse"\x1a\x82\xd3\xe4\x93\x02\x14\x12\x12/cloud/user-groups\x12\xa8\x01\n\x0cGetUserGroup\x12\x37.temporal.api.cloud.cloudservice.v1.GetUserGroupRequest\x1a\x38.temporal.api.cloud.cloudservice.v1.GetUserGroupResponse"%\x82\xd3\xe4\x93\x02\x1f\x12\x1d/cloud/user-groups/{group_id}\x12\xa9\x01\n\x0f\x43reateUserGroup\x12:.temporal.api.cloud.cloudservice.v1.CreateUserGroupRequest\x1a;.temporal.api.cloud.cloudservice.v1.CreateUserGroupResponse"\x1d\x82\xd3\xe4\x93\x02\x17"\x12/cloud/user-groups:\x01*\x12\xb4\x01\n\x0fUpdateUserGroup\x12:.temporal.api.cloud.cloudservice.v1.UpdateUserGroupRequest\x1a;.temporal.api.cloud.cloudservice.v1.UpdateUserGroupResponse"(\x82\xd3\xe4\x93\x02""\x1d/cloud/user-groups/{group_id}:\x01*\x12\xb1\x01\n\x0f\x44\x65leteUserGroup\x12:.temporal.api.cloud.cloudservice.v1.DeleteUserGroupRequest\x1a;.temporal.api.cloud.cloudservice.v1.DeleteUserGroupResponse"%\x82\xd3\xe4\x93\x02\x1f*\x1d/cloud/user-groups/{group_id}\x12\xf6\x01\n\x1bSetUserGroupNamespaceAccess\x12\x46.temporal.api.cloud.cloudservice.v1.SetUserGroupNamespaceAccessRequest\x1aG.temporal.api.cloud.cloudservice.v1.SetUserGroupNamespaceAccessResponse"F\x82\xd3\xe4\x93\x02@";/cloud/namespaces/{namespace}/user-groups/{group_id}/access:\x01*\x12\xc5\x01\n\x12\x41\x64\x64UserGroupMember\x12=.temporal.api.cloud.cloudservice.v1.AddUserGroupMemberRequest\x1a>.temporal.api.cloud.cloudservice.v1.AddUserGroupMemberResponse"0\x82\xd3\xe4\x93\x02*"%/cloud/user-groups/{group_id}/members:\x01*\x12\xd4\x01\n\x15RemoveUserGroupMember\x12@.temporal.api.cloud.cloudservice.v1.RemoveUserGroupMemberRequest\x1a\x41.temporal.api.cloud.cloudservice.v1.RemoveUserGroupMemberResponse"6\x82\xd3\xe4\x93\x02\x30"+/cloud/user-groups/{group_id}/remove-member:\x01*\x12\xc5\x01\n\x13GetUserGroupMembers\x12>.temporal.api.cloud.cloudservice.v1.GetUserGroupMembersRequest\x1a?.temporal.api.cloud.cloudservice.v1.GetUserGroupMembersResponse"-\x82\xd3\xe4\x93\x02\'\x12%/cloud/user-groups/{group_id}/members\x12\xbd\x01\n\x14\x43reateServiceAccount\x12?.temporal.api.cloud.cloudservice.v1.CreateServiceAccountRequest\x1a@.temporal.api.cloud.cloudservice.v1.CreateServiceAccountResponse""\x82\xd3\xe4\x93\x02\x1c"\x17/cloud/service-accounts:\x01*\x12\xc6\x01\n\x11GetServiceAccount\x12<.temporal.api.cloud.cloudservice.v1.GetServiceAccountRequest\x1a=.temporal.api.cloud.cloudservice.v1.GetServiceAccountResponse"4\x82\xd3\xe4\x93\x02.\x12,/cloud/service-accounts/{service_account_id}\x12\xb4\x01\n\x12GetServiceAccounts\x12=.temporal.api.cloud.cloudservice.v1.GetServiceAccountsRequest\x1a>.temporal.api.cloud.cloudservice.v1.GetServiceAccountsResponse"\x1f\x82\xd3\xe4\x93\x02\x19\x12\x17/cloud/service-accounts\x12\xd2\x01\n\x14UpdateServiceAccount\x12?.temporal.api.cloud.cloudservice.v1.UpdateServiceAccountRequest\x1a@.temporal.api.cloud.cloudservice.v1.UpdateServiceAccountResponse"7\x82\xd3\xe4\x93\x02\x31",/cloud/service-accounts/{service_account_id}:\x01*\x12\x94\x02\n SetServiceAccountNamespaceAccess\x12K.temporal.api.cloud.cloudservice.v1.SetServiceAccountNamespaceAccessRequest\x1aL.temporal.api.cloud.cloudservice.v1.SetServiceAccountNamespaceAccessResponse"U\x82\xd3\xe4\x93\x02O"J/cloud/namespaces/{namespace}/service-accounts/{service_account_id}/access:\x01*\x12\xcf\x01\n\x14\x44\x65leteServiceAccount\x12?.temporal.api.cloud.cloudservice.v1.DeleteServiceAccountRequest\x1a@.temporal.api.cloud.cloudservice.v1.DeleteServiceAccountResponse"4\x82\xd3\xe4\x93\x02.*,/cloud/service-accounts/{service_account_id}\x12\x8b\x01\n\x08GetUsage\x12\x33.temporal.api.cloud.cloudservice.v1.GetUsageRequest\x1a\x34.temporal.api.cloud.cloudservice.v1.GetUsageResponse"\x14\x82\xd3\xe4\x93\x02\x0e\x12\x0c/cloud/usage\x12\x93\x01\n\nGetAccount\x12\x35.temporal.api.cloud.cloudservice.v1.GetAccountRequest\x1a\x36.temporal.api.cloud.cloudservice.v1.GetAccountResponse"\x16\x82\xd3\xe4\x93\x02\x10\x12\x0e/cloud/account\x12\x9f\x01\n\rUpdateAccount\x12\x38.temporal.api.cloud.cloudservice.v1.UpdateAccountRequest\x1a\x39.temporal.api.cloud.cloudservice.v1.UpdateAccountResponse"\x19\x82\xd3\xe4\x93\x02\x13"\x0e/cloud/account:\x01*\x12\xdf\x01\n\x19\x43reateNamespaceExportSink\x12\x44.temporal.api.cloud.cloudservice.v1.CreateNamespaceExportSinkRequest\x1a\x45.temporal.api.cloud.cloudservice.v1.CreateNamespaceExportSinkResponse"5\x82\xd3\xe4\x93\x02/"*/cloud/namespaces/{namespace}/export-sinks:\x01*\x12\xda\x01\n\x16GetNamespaceExportSink\x12\x41.temporal.api.cloud.cloudservice.v1.GetNamespaceExportSinkRequest\x1a\x42.temporal.api.cloud.cloudservice.v1.GetNamespaceExportSinkResponse"9\x82\xd3\xe4\x93\x02\x33\x12\x31/cloud/namespaces/{namespace}/export-sinks/{name}\x12\xd6\x01\n\x17GetNamespaceExportSinks\x12\x42.temporal.api.cloud.cloudservice.v1.GetNamespaceExportSinksRequest\x1a\x43.temporal.api.cloud.cloudservice.v1.GetNamespaceExportSinksResponse"2\x82\xd3\xe4\x93\x02,\x12*/cloud/namespaces/{namespace}/export-sinks\x12\xeb\x01\n\x19UpdateNamespaceExportSink\x12\x44.temporal.api.cloud.cloudservice.v1.UpdateNamespaceExportSinkRequest\x1a\x45.temporal.api.cloud.cloudservice.v1.UpdateNamespaceExportSinkResponse"A\x82\xd3\xe4\x93\x02;"6/cloud/namespaces/{namespace}/export-sinks/{spec.name}:\x01*\x12\xe3\x01\n\x19\x44\x65leteNamespaceExportSink\x12\x44.temporal.api.cloud.cloudservice.v1.DeleteNamespaceExportSinkRequest\x1a\x45.temporal.api.cloud.cloudservice.v1.DeleteNamespaceExportSinkResponse"9\x82\xd3\xe4\x93\x02\x33*1/cloud/namespaces/{namespace}/export-sinks/{name}\x12\xee\x01\n\x1bValidateNamespaceExportSink\x12\x46.temporal.api.cloud.cloudservice.v1.ValidateNamespaceExportSinkRequest\x1aG.temporal.api.cloud.cloudservice.v1.ValidateNamespaceExportSinkResponse">\x82\xd3\xe4\x93\x02\x38"3/cloud/namespaces/{namespace}/export-sinks/validate:\x01*\x12\xcc\x01\n\x13UpdateNamespaceTags\x12>.temporal.api.cloud.cloudservice.v1.UpdateNamespaceTagsRequest\x1a?.temporal.api.cloud.cloudservice.v1.UpdateNamespaceTagsResponse"4\x82\xd3\xe4\x93\x02.")/cloud/namespaces/{namespace}/update-tags:\x01*\x12\xc5\x01\n\x16\x43reateConnectivityRule\x12\x41.temporal.api.cloud.cloudservice.v1.CreateConnectivityRuleRequest\x1a\x42.temporal.api.cloud.cloudservice.v1.CreateConnectivityRuleResponse"$\x82\xd3\xe4\x93\x02\x1e"\x19/cloud/connectivity-rules:\x01*\x12\xd0\x01\n\x13GetConnectivityRule\x12>.temporal.api.cloud.cloudservice.v1.GetConnectivityRuleRequest\x1a?.temporal.api.cloud.cloudservice.v1.GetConnectivityRuleResponse"8\x82\xd3\xe4\x93\x02\x32\x12\x30/cloud/connectivity-rules/{connectivity_rule_id}\x12\xbc\x01\n\x14GetConnectivityRules\x12?.temporal.api.cloud.cloudservice.v1.GetConnectivityRulesRequest\x1a@.temporal.api.cloud.cloudservice.v1.GetConnectivityRulesResponse"!\x82\xd3\xe4\x93\x02\x1b\x12\x19/cloud/connectivity-rules\x12\xd9\x01\n\x16\x44\x65leteConnectivityRule\x12\x41.temporal.api.cloud.cloudservice.v1.DeleteConnectivityRuleRequest\x1a\x42.temporal.api.cloud.cloudservice.v1.DeleteConnectivityRuleResponse"8\x82\xd3\xe4\x93\x02\x32*0/cloud/connectivity-rules/{connectivity_rule_id}\x12\xe2\x01\n\x1bValidateAccountAuditLogSink\x12\x46.temporal.api.cloud.cloudservice.v1.ValidateAccountAuditLogSinkRequest\x1aG.temporal.api.cloud.cloudservice.v1.ValidateAccountAuditLogSinkResponse"2\x82\xd3\xe4\x93\x02,"\'/cloud/account/audit-logs/sink/validate:\x01*B\xc0\x01\n%io.temporal.api.cloud.cloudservice.v1B\x0cServiceProtoP\x01Z5go.temporal.io/api/cloud/cloudservice/v1;cloudservice\xaa\x02$Temporalio.Api.Cloud.CloudService.V1\xea\x02(Temporalio::Api::Cloud::CloudService::V1b\x06proto3' + b'\n0temporal/api/cloud/cloudservice/v1/service.proto\x12"temporal.api.cloud.cloudservice.v1\x1a\x39temporal/api/cloud/cloudservice/v1/request_response.proto\x1a\x1cgoogle/api/annotations.proto\x1a.protoc-gen-openapiv2/options/annotations.proto2\xb6\xbe\x01\n\x0c\x43loudService\x12\xb0\x02\n\x12GetCurrentIdentity\x12=.temporal.api.cloud.cloudservice.v1.GetCurrentIdentityRequest\x1a>.temporal.api.cloud.cloudservice.v1.GetCurrentIdentityResponse"\x9a\x01\x82\xd3\xe4\x93\x02\x19\x12\x17/cloud/current-identity\x92\x41x\n\x07\x41\x63\x63ount\x12\x14Get current identity\x1aWReturns information about the currently authenticated user or service account principal\x12\xa5\x02\n\x08GetUsers\x12\x33.temporal.api.cloud.cloudservice.v1.GetUsersRequest\x1a\x34.temporal.api.cloud.cloudservice.v1.GetUsersResponse"\xad\x01\x82\xd3\xe4\x93\x02\x0e\x12\x0c/cloud/users\x92\x41\x95\x01\n\x05Users\x12\x0eList all users\x1a*Returns a list of all users in the account"E\n\x1dUser management documentation\x12$https://docs.temporal.io/cloud/users*\tlistUsers\x12\x9c\x02\n\x07GetUser\x12\x32.temporal.api.cloud.cloudservice.v1.GetUserRequest\x1a\x33.temporal.api.cloud.cloudservice.v1.GetUserResponse"\xa7\x01\x82\xd3\xe4\x93\x02\x18\x12\x16/cloud/users/{user_id}\x92\x41\x85\x01\n\x05Users\x12\x0eGet user by ID\x1a%Takes a user ID, returns user details"E\n\x1dUser management documentation\x12$https://docs.temporal.io/cloud/users\x12\xd0\x01\n\nCreateUser\x12\x35.temporal.api.cloud.cloudservice.v1.CreateUserRequest\x1a\x36.temporal.api.cloud.cloudservice.v1.CreateUserResponse"S\x82\xd3\xe4\x93\x02\x11"\x0c/cloud/users:\x01*\x92\x41\x39\n\x05Users\x12\rCreate a user\x1a!Creates a new user in the account\x12\xdb\x01\n\nUpdateUser\x12\x35.temporal.api.cloud.cloudservice.v1.UpdateUserRequest\x1a\x36.temporal.api.cloud.cloudservice.v1.UpdateUserResponse"^\x82\xd3\xe4\x93\x02\x1b"\x16/cloud/users/{user_id}:\x01*\x92\x41:\n\x05Users\x12\rUpdate a user\x1a"Updates an existing user\'s details\x12\xd5\x01\n\nDeleteUser\x12\x35.temporal.api.cloud.cloudservice.v1.DeleteUserRequest\x1a\x36.temporal.api.cloud.cloudservice.v1.DeleteUserResponse"X\x82\xd3\xe4\x93\x02\x18*\x16/cloud/users/{user_id}\x92\x41\x37\n\x05Users\x12\rDelete a user\x1a\x1fRemoves a user from the account\x12\xaa\x03\n\x16SetUserNamespaceAccess\x12\x41.temporal.api.cloud.cloudservice.v1.SetUserNamespaceAccessRequest\x1a\x42.temporal.api.cloud.cloudservice.v1.SetUserNamespaceAccessResponse"\x88\x02\x82\xd3\xe4\x93\x02\x39"4/cloud/namespaces/{namespace}/users/{user_id}/access:\x01*\x92\x41\xc5\x01\n\x05Users\x12\x19Set user namespace access\x1a\x38\x43onfigures a user\'s permissions for a specific namespace"g\n#Namespace permissions documentation\x12@https://docs.temporal.io/cloud/users-namespace-level-permissions\x12\xb1\x02\n\x11GetAsyncOperation\x12<.temporal.api.cloud.cloudservice.v1.GetAsyncOperationRequest\x1a=.temporal.api.cloud.cloudservice.v1.GetAsyncOperationResponse"\x9e\x01\x82\xd3\xe4\x93\x02(\x12&/cloud/operations/{async_operation_id}\x92\x41m\n\nOperations\x12\x1aGet async operation status\x1a\x43Returns the current status and details of an asynchronous operation\x12\xc6\x02\n\x0f\x43reateNamespace\x12:.temporal.api.cloud.cloudservice.v1.CreateNamespaceRequest\x1a;.temporal.api.cloud.cloudservice.v1.CreateNamespaceResponse"\xb9\x01\x82\xd3\xe4\x93\x02\x16"\x11/cloud/namespaces:\x01*\x92\x41\x99\x01\n\nNamespaces\x12\x12\x43reate a namespace\x1a&Creates a new namespace in the account"O\n"Namespace management documentation\x12)https://docs.temporal.io/cloud/namespaces\x12\xc7\x02\n\rGetNamespaces\x12\x38.temporal.api.cloud.cloudservice.v1.GetNamespacesRequest\x1a\x39.temporal.api.cloud.cloudservice.v1.GetNamespacesResponse"\xc0\x01\x82\xd3\xe4\x93\x02\x13\x12\x11/cloud/namespaces\x92\x41\xa3\x01\n\nNamespaces\x12\x13List all namespaces\x1a/Returns a list of all namespaces in the account"O\n"Namespace management documentation\x12)https://docs.temporal.io/cloud/namespaces\x12\xda\x02\n\x0cGetNamespace\x12\x37.temporal.api.cloud.cloudservice.v1.GetNamespaceRequest\x1a\x38.temporal.api.cloud.cloudservice.v1.GetNamespaceResponse"\xd6\x01\x82\xd3\xe4\x93\x02\x1f\x12\x1d/cloud/namespaces/{namespace}\x92\x41\xad\x01\n\nNamespaces\x12\x15Get namespace details\x1a\x37Returns detailed information about a specific namespace"O\n"Namespace management documentation\x12)https://docs.temporal.io/cloud/namespaces\x12\xdb\x02\n\x0fUpdateNamespace\x12:.temporal.api.cloud.cloudservice.v1.UpdateNamespaceRequest\x1a;.temporal.api.cloud.cloudservice.v1.UpdateNamespaceResponse"\xce\x01\x82\xd3\xe4\x93\x02""\x1d/cloud/namespaces/{namespace}:\x01*\x92\x41\xa2\x01\n\nNamespaces\x12\x12Update a namespace\x1a/Updates configuration for an existing namespace"O\n"Namespace management documentation\x12)https://docs.temporal.io/cloud/namespaces\x12\xc7\x03\n\x1bRenameCustomSearchAttribute\x12\x46.temporal.api.cloud.cloudservice.v1.RenameCustomSearchAttributeRequest\x1aG.temporal.api.cloud.cloudservice.v1.RenameCustomSearchAttributeResponse"\x96\x02\x82\xd3\xe4\x93\x02\x41".temporal.api.cloud.cloudservice.v1.AddNamespaceRegionResponse"\xed\x01\x82\xd3\xe4\x93\x02-"(/cloud/namespaces/{namespace}/add-region:\x01*\x92\x41\xb6\x01\n\x11High Availability\x12\x15\x41\x64\x64 namespace replica\x1a+Adds a new replica to an existing namespace"]\n)High availability namespace documentation\x12\x30https://docs.temporal.io/cloud/high-availability\x12\x9b\x03\n\x15\x44\x65leteNamespaceRegion\x12@.temporal.api.cloud.cloudservice.v1.DeleteNamespaceRegionRequest\x1a\x41.temporal.api.cloud.cloudservice.v1.DeleteNamespaceRegionResponse"\xfc\x01\x82\xd3\xe4\x93\x02\x30*./cloud/namespaces/{namespace}/regions/{region}\x92\x41\xc2\x01\n\x11High Availability\x12\x18Remove namespace replica\x1a\x34Removes a replica from a high availability namespace"]\n)High availability namespace documentation\x12\x30https://docs.temporal.io/cloud/high-availability\x12\xa3\x02\n\nGetRegions\x12\x35.temporal.api.cloud.cloudservice.v1.GetRegionsRequest\x1a\x36.temporal.api.cloud.cloudservice.v1.GetRegionsResponse"\xa5\x01\x82\xd3\xe4\x93\x02\x10\x12\x0e/cloud/regions\x92\x41\x8b\x01\n\x07Regions\x12\x10List all regions\x1a-Returns a list of all available cloud regions"?\n\x15Regions documentation\x12&https://docs.temporal.io/cloud/regions\x12\xb2\x02\n\tGetRegion\x12\x34.temporal.api.cloud.cloudservice.v1.GetRegionRequest\x1a\x35.temporal.api.cloud.cloudservice.v1.GetRegionResponse"\xb7\x01\x82\xd3\xe4\x93\x02\x19\x12\x17/cloud/regions/{region}\x92\x41\x94\x01\n\x07Regions\x12\x12Get region details\x1a\x34Returns detailed information about a specific region"?\n\x15Regions documentation\x12&https://docs.temporal.io/cloud/regions\x12\xa8\x02\n\nGetApiKeys\x12\x35.temporal.api.cloud.cloudservice.v1.GetApiKeysRequest\x1a\x36.temporal.api.cloud.cloudservice.v1.GetApiKeysResponse"\xaa\x01\x82\xd3\xe4\x93\x02\x11\x12\x0f/cloud/api-keys\x92\x41\x8f\x01\n\x08\x41PI Keys\x12\x11List all API keys\x1a-Returns a list of all API keys in the account"A\n\x16\x41PI Keys documentation\x12\'https://docs.temporal.io/cloud/api-keys\x12\xb8\x02\n\tGetApiKey\x12\x34.temporal.api.cloud.cloudservice.v1.GetApiKeyRequest\x1a\x35.temporal.api.cloud.cloudservice.v1.GetApiKeyResponse"\xbd\x01\x82\xd3\xe4\x93\x02\x1a\x12\x18/cloud/api-keys/{key_id}\x92\x41\x99\x01\n\x08\x41PI Keys\x12\x13Get API key details\x1a\x35Returns detailed information about a specific API key"A\n\x16\x41PI Keys documentation\x12\'https://docs.temporal.io/cloud/api-keys\x12\xb1\x02\n\x0c\x43reateApiKey\x12\x37.temporal.api.cloud.cloudservice.v1.CreateApiKeyRequest\x1a\x38.temporal.api.cloud.cloudservice.v1.CreateApiKeyResponse"\xad\x01\x82\xd3\xe4\x93\x02\x14"\x0f/cloud/api-keys:\x01*\x92\x41\x8f\x01\n\x08\x41PI Keys\x12\x11\x43reate an API key\x1a-Creates a new API key for programmatic access"A\n\x16\x41PI Keys documentation\x12\'https://docs.temporal.io/cloud/api-keys\x12\xb5\x02\n\x0cUpdateApiKey\x12\x37.temporal.api.cloud.cloudservice.v1.UpdateApiKeyRequest\x1a\x38.temporal.api.cloud.cloudservice.v1.UpdateApiKeyResponse"\xb1\x01\x82\xd3\xe4\x93\x02\x1d"\x18/cloud/api-keys/{key_id}:\x01*\x92\x41\x8a\x01\n\x08\x41PI Keys\x12\x11Update an API key\x1a(Updates an existing API key\'s properties"A\n\x16\x41PI Keys documentation\x12\'https://docs.temporal.io/cloud/api-keys\x12\xa8\x02\n\x0c\x44\x65leteApiKey\x12\x37.temporal.api.cloud.cloudservice.v1.DeleteApiKeyRequest\x1a\x38.temporal.api.cloud.cloudservice.v1.DeleteApiKeyResponse"\xa4\x01\x82\xd3\xe4\x93\x02\x1a*\x18/cloud/api-keys/{key_id}\x92\x41\x80\x01\n\x08\x41PI Keys\x12\x11\x44\x65lete an API key\x1a\x1eRevokes and deletes an API key"A\n\x16\x41PI Keys documentation\x12\'https://docs.temporal.io/cloud/api-keys\x12\xc3\x02\n\x11GetNexusEndpoints\x12<.temporal.api.cloud.cloudservice.v1.GetNexusEndpointsRequest\x1a=.temporal.api.cloud.cloudservice.v1.GetNexusEndpointsResponse"\xb0\x01\x82\xd3\xe4\x93\x02\x18\x12\x16/cloud/nexus/endpoints\x92\x41\x8e\x01\n\x05Nexus\x12\x18List all Nexus endpoints\x1a\x34Returns a list of all Nexus endpoints in the account"5\n\x13Nexus documentation\x12\x1ehttps://docs.temporal.io/nexus\x12\xd8\x02\n\x10GetNexusEndpoint\x12;.temporal.api.cloud.cloudservice.v1.GetNexusEndpointRequest\x1a<.temporal.api.cloud.cloudservice.v1.GetNexusEndpointResponse"\xc8\x01\x82\xd3\xe4\x93\x02&\x12$/cloud/nexus/endpoints/{endpoint_id}\x92\x41\x98\x01\n\x05Nexus\x12\x1aGet Nexus endpoint details\x1a.temporal.api.cloud.cloudservice.v1.CreateNexusEndpointRequest\x1a?.temporal.api.cloud.cloudservice.v1.CreateNexusEndpointResponse"\xbc\x01\x82\xd3\xe4\x93\x02\x1b"\x16/cloud/nexus/endpoints:\x01*\x92\x41\x97\x01\n\x05Nexus\x12\x17\x43reate a Nexus endpoint\x1a>Creates a new Nexus endpoint for cross-namespace communication"5\n\x13Nexus documentation\x12\x1ehttps://docs.temporal.io/nexus\x12\xd7\x02\n\x13UpdateNexusEndpoint\x12>.temporal.api.cloud.cloudservice.v1.UpdateNexusEndpointRequest\x1a?.temporal.api.cloud.cloudservice.v1.UpdateNexusEndpointResponse"\xbe\x01\x82\xd3\xe4\x93\x02)"$/cloud/nexus/endpoints/{endpoint_id}:\x01*\x92\x41\x8b\x01\n\x05Nexus\x12\x17Update a Nexus endpoint\x1a\x32Updates an existing Nexus endpoint\'s configuration"5\n\x13Nexus documentation\x12\x1ehttps://docs.temporal.io/nexus\x12\xcb\x02\n\x13\x44\x65leteNexusEndpoint\x12>.temporal.api.cloud.cloudservice.v1.DeleteNexusEndpointRequest\x1a?.temporal.api.cloud.cloudservice.v1.DeleteNexusEndpointResponse"\xb2\x01\x82\xd3\xe4\x93\x02&*$/cloud/nexus/endpoints/{endpoint_id}\x92\x41\x82\x01\n\x05Nexus\x12\x17\x44\x65lete a Nexus endpoint\x1a)Removes a Nexus endpoint from the account"5\n\x13Nexus documentation\x12\x1ehttps://docs.temporal.io/nexus\x12\xcc\x02\n\rGetUserGroups\x12\x38.temporal.api.cloud.cloudservice.v1.GetUserGroupsRequest\x1a\x39.temporal.api.cloud.cloudservice.v1.GetUserGroupsResponse"\xc5\x01\x82\xd3\xe4\x93\x02\x14\x12\x12/cloud/user-groups\x92\x41\xa7\x01\n\x06Groups\x12\x14List all user groups\x1a\x30Returns a list of all user groups in the account"U\n\x19User groups documentation\x12\x38https://docs.temporal.io/cloud/users-account-level-roles\x12\xd0\x02\n\x0cGetUserGroup\x12\x37.temporal.api.cloud.cloudservice.v1.GetUserGroupRequest\x1a\x38.temporal.api.cloud.cloudservice.v1.GetUserGroupResponse"\xcc\x01\x82\xd3\xe4\x93\x02\x1f\x12\x1d/cloud/user-groups/{group_id}\x92\x41\xa3\x01\n\x06Groups\x12\x16Get user group details\x1a\x38Returns detailed information about a specific user group"G\n\x19User groups documentation\x12*https://docs.temporal.io/cloud/user-groups\x12\xc7\x02\n\x0f\x43reateUserGroup\x12:.temporal.api.cloud.cloudservice.v1.CreateUserGroupRequest\x1a;.temporal.api.cloud.cloudservice.v1.CreateUserGroupResponse"\xba\x01\x82\xd3\xe4\x93\x02\x17"\x12/cloud/user-groups:\x01*\x92\x41\x99\x01\n\x06Groups\x12\x13\x43reate a user group\x1a\x31\x43reates a new user group for managing permissions"G\n\x19User groups documentation\x12*https://docs.temporal.io/cloud/user-groups\x12\xcc\x02\n\x0fUpdateUserGroup\x12:.temporal.api.cloud.cloudservice.v1.UpdateUserGroupRequest\x1a;.temporal.api.cloud.cloudservice.v1.UpdateUserGroupResponse"\xbf\x01\x82\xd3\xe4\x93\x02""\x1d/cloud/user-groups/{group_id}:\x01*\x92\x41\x93\x01\n\x06Groups\x12\x13Update a user group\x1a+Updates an existing user group\'s properties"G\n\x19User groups documentation\x12*https://docs.temporal.io/cloud/user-groups\x12\xc3\x02\n\x0f\x44\x65leteUserGroup\x12:.temporal.api.cloud.cloudservice.v1.DeleteUserGroupRequest\x1a;.temporal.api.cloud.cloudservice.v1.DeleteUserGroupResponse"\xb6\x01\x82\xd3\xe4\x93\x02\x1f*\x1d/cloud/user-groups/{group_id}\x92\x41\x8d\x01\n\x06Groups\x12\x13\x44\x65lete a user group\x1a%Removes a user group from the account"G\n\x19User groups documentation\x12*https://docs.temporal.io/cloud/user-groups\x12\xad\x03\n\x1bSetUserGroupNamespaceAccess\x12\x46.temporal.api.cloud.cloudservice.v1.SetUserGroupNamespaceAccessRequest\x1aG.temporal.api.cloud.cloudservice.v1.SetUserGroupNamespaceAccessResponse"\xfc\x01\x82\xd3\xe4\x93\x02@";/cloud/namespaces/{namespace}/user-groups/{group_id}/access:\x01*\x92\x41\xb2\x01\n\x06Groups\x12\x1fSet user group namespace access\x1a>Configures a user group\'s permissions for a specific namespace"G\n\x19User groups documentation\x12*https://docs.temporal.io/cloud/user-groups\x12\xdf\x02\n\x12\x41\x64\x64UserGroupMember\x12=.temporal.api.cloud.cloudservice.v1.AddUserGroupMemberRequest\x1a>.temporal.api.cloud.cloudservice.v1.AddUserGroupMemberResponse"\xc9\x01\x82\xd3\xe4\x93\x02*"%/cloud/user-groups/{group_id}/members:\x01*\x92\x41\x95\x01\n\x06Groups\x12\x11\x41\x64\x64 user to group\x1a/Adds a user to a user group (Cloud groups only)"G\n\x19User groups documentation\x12*https://docs.temporal.io/cloud/user-groups\x12\xf8\x02\n\x15RemoveUserGroupMember\x12@.temporal.api.cloud.cloudservice.v1.RemoveUserGroupMemberRequest\x1a\x41.temporal.api.cloud.cloudservice.v1.RemoveUserGroupMemberResponse"\xd9\x01\x82\xd3\xe4\x93\x02\x30"+/cloud/user-groups/{group_id}/remove-member:\x01*\x92\x41\x9f\x01\n\x06Groups\x12\x16Remove user from group\x1a\x34Removes a user from a user group (Cloud groups only)"G\n\x19User groups documentation\x12*https://docs.temporal.io/cloud/user-groups\x12\xdf\x02\n\x13GetUserGroupMembers\x12>.temporal.api.cloud.cloudservice.v1.GetUserGroupMembersRequest\x1a?.temporal.api.cloud.cloudservice.v1.GetUserGroupMembersResponse"\xc6\x01\x82\xd3\xe4\x93\x02\'\x12%/cloud/user-groups/{group_id}/members\x92\x41\x95\x01\n\x06Groups\x12\x15List users in a group\x1a+Returns a list of all users in a user group"G\n\x19User groups documentation\x12*https://docs.temporal.io/cloud/user-groups\x12\xf5\x02\n\x14\x43reateServiceAccount\x12?.temporal.api.cloud.cloudservice.v1.CreateServiceAccountRequest\x1a@.temporal.api.cloud.cloudservice.v1.CreateServiceAccountResponse"\xd9\x01\x82\xd3\xe4\x93\x02\x1c"\x17/cloud/service-accounts:\x01*\x92\x41\xb3\x01\n\x10Service Accounts\x12\x18\x43reate a service account\x1a\x32\x43reates a new service account for automated access"Q\n\x1eService Accounts documentation\x12/https://docs.temporal.io/cloud/service-accounts\x12\x8c\x03\n\x11GetServiceAccount\x12<.temporal.api.cloud.cloudservice.v1.GetServiceAccountRequest\x1a=.temporal.api.cloud.cloudservice.v1.GetServiceAccountResponse"\xf9\x01\x82\xd3\xe4\x93\x02.\x12,/cloud/service-accounts/{service_account_id}\x92\x41\xc1\x01\n\x10Service Accounts\x12\x1bGet service account details\x1a=Returns detailed information about a specific service account"Q\n\x1eService Accounts documentation\x12/https://docs.temporal.io/cloud/service-accounts\x12\xf0\x02\n\x12GetServiceAccounts\x12=.temporal.api.cloud.cloudservice.v1.GetServiceAccountsRequest\x1a>.temporal.api.cloud.cloudservice.v1.GetServiceAccountsResponse"\xda\x01\x82\xd3\xe4\x93\x02\x19\x12\x17/cloud/service-accounts\x92\x41\xb7\x01\n\x10Service Accounts\x12\x19List all service accounts\x1a\x35Returns a list of all service accounts in the account"Q\n\x1eService Accounts documentation\x12/https://docs.temporal.io/cloud/service-accounts\x12\x88\x03\n\x14UpdateServiceAccount\x12?.temporal.api.cloud.cloudservice.v1.UpdateServiceAccountRequest\x1a@.temporal.api.cloud.cloudservice.v1.UpdateServiceAccountResponse"\xec\x01\x82\xd3\xe4\x93\x02\x31",/cloud/service-accounts/{service_account_id}:\x01*\x92\x41\xb1\x01\n\x10Service Accounts\x12\x18Update a service account\x1a\x30Updates an existing service account\'s properties"Q\n\x1eService Accounts documentation\x12/https://docs.temporal.io/cloud/service-accounts\x12\xe9\x03\n SetServiceAccountNamespaceAccess\x12K.temporal.api.cloud.cloudservice.v1.SetServiceAccountNamespaceAccessRequest\x1aL.temporal.api.cloud.cloudservice.v1.SetServiceAccountNamespaceAccessResponse"\xa9\x02\x82\xd3\xe4\x93\x02O"J/cloud/namespaces/{namespace}/service-accounts/{service_account_id}/access:\x01*\x92\x41\xd0\x01\n\x10Service Accounts\x12$Set service account namespace access\x1a\x43\x43onfigures a service account\'s permissions for a specific namespace"Q\n\x1eService Accounts documentation\x12/https://docs.temporal.io/cloud/service-accounts\x12\xff\x02\n\x14\x44\x65leteServiceAccount\x12?.temporal.api.cloud.cloudservice.v1.DeleteServiceAccountRequest\x1a@.temporal.api.cloud.cloudservice.v1.DeleteServiceAccountResponse"\xe3\x01\x82\xd3\xe4\x93\x02.*,/cloud/service-accounts/{service_account_id}\x92\x41\xab\x01\n\x10Service Accounts\x12\x18\x44\x65lete a service account\x1a*Removes a service account from the account"Q\n\x1eService Accounts documentation\x12/https://docs.temporal.io/cloud/service-accounts\x12\xcb\x01\n\x08GetUsage\x12\x33.temporal.api.cloud.cloudservice.v1.GetUsageRequest\x1a\x34.temporal.api.cloud.cloudservice.v1.GetUsageResponse"T\x82\xd3\xe4\x93\x02\x0e\x12\x0c/cloud/usage\x92\x41=\n\x07\x41\x63\x63ount\x12\x0eGet usage data\x1a Get usage data across namespacesX\x01\x12\xb0\x02\n\nGetAccount\x12\x35.temporal.api.cloud.cloudservice.v1.GetAccountRequest\x1a\x36.temporal.api.cloud.cloudservice.v1.GetAccountResponse"\xb2\x01\x82\xd3\xe4\x93\x02\x10\x12\x0e/cloud/account\x92\x41\x98\x01\n\x07\x41\x63\x63ount\x12\x13Get account details\x1a.Returns detailed information about the account"H\n\x15\x42illing documentation\x12/https://docs.temporal.io/cloud/billing-and-cost\x12\xbb\x02\n\rUpdateAccount\x12\x38.temporal.api.cloud.cloudservice.v1.UpdateAccountRequest\x1a\x39.temporal.api.cloud.cloudservice.v1.UpdateAccountResponse"\xb4\x01\x82\xd3\xe4\x93\x02\x13"\x0e/cloud/account:\x01*\x92\x41\x97\x01\n\x07\x41\x63\x63ount\x12\x16Update account details\x1a*Updates account configuration and settings"H\n\x15\x42illing documentation\x12/https://docs.temporal.io/cloud/billing-and-cost\x12\xf3\x02\n\x19\x43reateNamespaceExportSink\x12\x44.temporal.api.cloud.cloudservice.v1.CreateNamespaceExportSinkRequest\x1a\x45.temporal.api.cloud.cloudservice.v1.CreateNamespaceExportSinkResponse"\xc8\x01\x82\xd3\xe4\x93\x02/"*/cloud/namespaces/{namespace}/export-sinks:\x01*\x92\x41\x8f\x01\n\x06\x45xport\x12\x1a\x43reate history export sink\x1a*Creates a new workflow history export sink"=\n\x14\x45xport documentation\x12%https://docs.temporal.io/cloud/export\x12\x8c\x03\n\x16GetNamespaceExportSink\x12\x41.temporal.api.cloud.cloudservice.v1.GetNamespaceExportSinkRequest\x1a\x42.temporal.api.cloud.cloudservice.v1.GetNamespaceExportSinkResponse"\xea\x01\x82\xd3\xe4\x93\x02\x33\x12\x31/cloud/namespaces/{namespace}/export-sinks/{name}\x92\x41\xad\x01\n\x06\x45xport\x12\x18Get history sink details\x1aJReturns detailed information about a specific workflow history export sink"=\n\x14\x45xport documentation\x12%https://docs.temporal.io/cloud/export\x12\x82\x03\n\x17GetNamespaceExportSinks\x12\x42.temporal.api.cloud.cloudservice.v1.GetNamespaceExportSinksRequest\x1a\x43.temporal.api.cloud.cloudservice.v1.GetNamespaceExportSinksResponse"\xdd\x01\x82\xd3\xe4\x93\x02,\x12*/cloud/namespaces/{namespace}/export-sinks\x92\x41\xa7\x01\n\x06\x45xport\x12\x19List history export sinks\x1a\x43Returns a list of all workflow history export sinks for a namespace"=\n\x14\x45xport documentation\x12%https://docs.temporal.io/cloud/export\x12\x95\x03\n\x19UpdateNamespaceExportSink\x12\x44.temporal.api.cloud.cloudservice.v1.UpdateNamespaceExportSinkRequest\x1a\x45.temporal.api.cloud.cloudservice.v1.UpdateNamespaceExportSinkResponse"\xea\x01\x82\xd3\xe4\x93\x02;"6/cloud/namespaces/{namespace}/export-sinks/{spec.name}:\x01*\x92\x41\xa5\x01\n\x06\x45xport\x12\x1aUpdate history export sink\x1a@Updates an existing workflow history export sink\'s configuration"=\n\x14\x45xport documentation\x12%https://docs.temporal.io/cloud/export\x12\x84\x03\n\x19\x44\x65leteNamespaceExportSink\x12\x44.temporal.api.cloud.cloudservice.v1.DeleteNamespaceExportSinkRequest\x1a\x45.temporal.api.cloud.cloudservice.v1.DeleteNamespaceExportSinkResponse"\xd9\x01\x82\xd3\xe4\x93\x02\x33*1/cloud/namespaces/{namespace}/export-sinks/{name}\x92\x41\x9c\x01\n\x06\x45xport\x12\x1a\x44\x65lete history export sink\x1a\x37Removes a workflow history export sink from a namespace"=\n\x14\x45xport documentation\x12%https://docs.temporal.io/cloud/export\x12\xc9\x03\n\x1bValidateNamespaceExportSink\x12\x46.temporal.api.cloud.cloudservice.v1.ValidateNamespaceExportSinkRequest\x1aG.temporal.api.cloud.cloudservice.v1.ValidateNamespaceExportSinkResponse"\x98\x02\x82\xd3\xe4\x93\x02\x37"2/cloud/namespaces/{namespace}/export-sink-validate:\x01*\x92\x41\xd7\x01\n\x06\x45xport\x12*Validate history export sink configuration\x1a\x62Tests workflow history export sink configuration by delivering a test file to verify accessibility"=\n\x14\x45xport documentation\x12%https://docs.temporal.io/cloud/export\x12\xfc\x02\n\x13UpdateNamespaceTags\x12>.temporal.api.cloud.cloudservice.v1.UpdateNamespaceTagsRequest\x1a?.temporal.api.cloud.cloudservice.v1.UpdateNamespaceTagsResponse"\xe3\x01\x82\xd3\xe4\x93\x02.")/cloud/namespaces/{namespace}/update-tags:\x01*\x92\x41\xab\x01\n\nNamespaces\x12\x15Update namespace tags\x1a,Updates the tags associated with a namespace"X\n\x1bNamespace tag documentation\x12\x39https://docs.temporal.io/cloud/namespaces#tag-a-namespace\x12\xff\x02\n\x16\x43reateConnectivityRule\x12\x41.temporal.api.cloud.cloudservice.v1.CreateConnectivityRuleRequest\x1a\x42.temporal.api.cloud.cloudservice.v1.CreateConnectivityRuleResponse"\xdd\x01\x82\xd3\xe4\x93\x02\x1e"\x19/cloud/connectivity-rules:\x01*\x92\x41\xb5\x01\n\x12\x43onnectivity Rules\x12\x18\x43reate connectivity rule\x1a:Creates a new connectivity rule for network access control"I\n\x1a\x43onnectivity documentation\x12+https://docs.temporal.io/cloud/connectivity\x12\x94\x03\n\x13GetConnectivityRule\x12>.temporal.api.cloud.cloudservice.v1.GetConnectivityRuleRequest\x1a?.temporal.api.cloud.cloudservice.v1.GetConnectivityRuleResponse"\xfb\x01\x82\xd3\xe4\x93\x02\x32\x12\x30/cloud/connectivity-rules/{connectivity_rule_id}\x92\x41\xbf\x01\n\x12\x43onnectivity Rules\x12\x1dGet connectivity rule details\x1a?Returns detailed information about a specific connectivity rule"I\n\x1a\x43onnectivity documentation\x12+https://docs.temporal.io/cloud/connectivity\x12\xf6\x02\n\x14GetConnectivityRules\x12?.temporal.api.cloud.cloudservice.v1.GetConnectivityRulesRequest\x1a@.temporal.api.cloud.cloudservice.v1.GetConnectivityRulesResponse"\xda\x01\x82\xd3\xe4\x93\x02\x1b\x12\x19/cloud/connectivity-rules\x92\x41\xb5\x01\n\x12\x43onnectivity Rules\x12\x1bList all connectivity rules\x1a\x37Returns a list of all connectivity rules in the account"I\n\x1a\x43onnectivity documentation\x12+https://docs.temporal.io/cloud/connectivity\x12\x85\x03\n\x16\x44\x65leteConnectivityRule\x12\x41.temporal.api.cloud.cloudservice.v1.DeleteConnectivityRuleRequest\x1a\x42.temporal.api.cloud.cloudservice.v1.DeleteConnectivityRuleResponse"\xe3\x01\x82\xd3\xe4\x93\x02\x32*0/cloud/connectivity-rules/{connectivity_rule_id}\x92\x41\xa7\x01\n\x12\x43onnectivity Rules\x12\x18\x44\x65lete connectivity rule\x1a,Removes a connectivity rule from the account"I\n\x1a\x43onnectivity documentation\x12+https://docs.temporal.io/cloud/connectivity\x12\xe2\x02\n\x0cGetAuditLogs\x12\x37.temporal.api.cloud.cloudservice.v1.GetAuditLogsRequest\x1a\x38.temporal.api.cloud.cloudservice.v1.GetAuditLogsResponse"\xde\x01\x82\xd3\xe4\x93\x02\x13\x12\x11/cloud/audit-logs\x92\x41\xc1\x01\n\x07\x41\x63\x63ount\x12\x0eGet audit logs\x1aYReturns a paginated list of audit logs for the account, optionally filtered by time range"K\n\x1b\x41udit logging documentation\x12,https://docs.temporal.io/cloud/audit-logging\x12\xb4\x04\n\x1bValidateAccountAuditLogSink\x12\x46.temporal.api.cloud.cloudservice.v1.ValidateAccountAuditLogSinkRequest\x1aG.temporal.api.cloud.cloudservice.v1.ValidateAccountAuditLogSinkResponse"\x83\x03\x82\xd3\xe4\x93\x02#"\x1e/cloud/audit-log-sink-validate:\x01*\x92\x41\xd6\x02\n\x07\x41\x63\x63ount\x12\x17Validate audit log sink\x1a\xe4\x01Validate customer audit log sink is accessible from Temporal\'s workflow by delivering an empty file to the specified sink. The operation verifies that the sink is correctly configured, accessible and ready to receive audit logs."K\n\x1b\x41udit logging documentation\x12,https://docs.temporal.io/cloud/audit-logging\x12\xf4\x02\n\x19\x43reateAccountAuditLogSink\x12\x44.temporal.api.cloud.cloudservice.v1.CreateAccountAuditLogSinkRequest\x1a\x45.temporal.api.cloud.cloudservice.v1.CreateAccountAuditLogSinkResponse"\xc9\x01\x82\xd3\xe4\x93\x02\x1b"\x16/cloud/audit-log-sinks:\x01*\x92\x41\xa4\x01\n\x07\x41\x63\x63ount\x12\x15\x43reate audit log sink\x1a\x35\x43reates a new audit log sink for exporting audit logs"K\n\x1b\x41udit logging documentation\x12,https://docs.temporal.io/cloud/audit-logging\x12\xfb\x02\n\x16GetAccountAuditLogSink\x12\x41.temporal.api.cloud.cloudservice.v1.GetAccountAuditLogSinkRequest\x1a\x42.temporal.api.cloud.cloudservice.v1.GetAccountAuditLogSinkResponse"\xd9\x01\x82\xd3\xe4\x93\x02\x1f\x12\x1d/cloud/audit-log-sinks/{name}\x92\x41\xb0\x01\n\x07\x41\x63\x63ount\x12\x1aGet audit log sink details\x1a.temporal.api.cloud.cloudservice.v1.CreateBillingReportRequest\x1a?.temporal.api.cloud.cloudservice.v1.CreateBillingReportResponse"\xc1\x01\x82\xd3\xe4\x93\x02\x1b"\x16/cloud/billing-reports:\x01*\x92\x41\x9c\x01\n\x07\x41\x63\x63ount\x12\x17\x43reate a billing report\x1a(Creates a billing report for the account"N\n\x1c\x42illing report documentation\x12.https://docs.temporal.io/cloud/billing-reports\x12\xe6\x02\n\x10GetBillingReport\x12;.temporal.api.cloud.cloudservice.v1.GetBillingReportRequest\x1a<.temporal.api.cloud.cloudservice.v1.GetBillingReportResponse"\xd6\x01\x82\xd3\xe4\x93\x02,\x12*/cloud/billing-reports/{billing_report_id}\x92\x41\xa0\x01\n\x07\x41\x63\x63ount\x12\x14Get a billing report\x1a/Gets an existing billing report for the account"N\n\x1c\x42illing report documentation\x12.https://docs.temporal.io/cloud/billing-reportsB\x86\x15\n%io.temporal.api.cloud.cloudservice.v1B\x0cServiceProtoP\x01Z5go.temporal.io/api/cloud/cloudservice/v1;cloudservice\xaa\x02$Temporalio.Api.Cloud.CloudService.V1\xea\x02(Temporalio::Api::Cloud::CloudService::V1\x92\x41\xc2\x13\x12\xe0\r\n\x16Temporal Cloud Ops API\x12\x96\x0cProgrammatic access to manage Temporal Cloud control plane resources including namespaces, users, service accounts, and more.\n\n## Authentication\n\nAll API requests require authentication using an API Key. Include your API key in the `Authorization` header using the Bearer scheme:\n\n```\nAuthorization: Bearer YOUR_API_KEY\n```\n\nAPI keys can be created and managed through the [API Keys endpoints](#tag/API-Keys) or via the Temporal Cloud UI. For more information, see [API Keys Documentation](https://docs.temporal.io/cloud/api-keys).\n\n## Authorization\n\nThe API uses Role-Based Access Control (RBAC) to manage permissions. Each operation requires specific role-based permissions in addition to a valid API key.\n\n### Account-Level Roles\n\n- **Account Owner** - Full account administration access\n- **Account Admin** - Manage namespaces, users, and service accounts \n- **Account Developer** - Create namespaces and manage Nexus endpoints\n- **Finance Admin** - View usage and billing information\n- **Account Read** - Read-only access to account resources\n\n### Namespace-Level Roles\n\n- **Namespace Admin** - Full access to namespace configuration and data\n- **Namespace Write** - Execute workflows and modify workflow data\n- **Namespace Read** - Read-only access to namespace data\n\nNamespace-level permissions are scoped to specific namespaces. A user or service account may have different permission levels across different namespaces.\n\nFor detailed information about roles and permissions, see [Access Control Documentation](https://docs.temporal.io/cloud/users).2\x03\x31.0:\xa7\x01\n\x06x-logo\x12\x9c\x01*\x99\x01\n\x96\x01\n\x03url\x12\x8e\x01\x1a\x8b\x01https://images.ctfassets.net/0uuz8ydxyd9p/4YGUnEoCaH9SyoUDhlJkau/e1600205d17eeee3033d926ef06664a9/Temporal_LogoLockup_Horizontal_dark_1.svgj.\n\nNamespaces\x12 Manage Temporal Cloud namespacesj0\n\x05Users\x12\'Manage users and their namespace accessjF\n\x10Service Accounts\x12\x32Manage service accounts and their namespace accessj.\n\x08\x41PI Keys\x12"Manage API keys for authenticationj1\n\x06Groups\x12\'Manage user groups and group membershipj\x1f\n\x05Nexus\x12\x16Manage Nexus endpointsj\x7f\n\x11High Availability\x12jManage high availability (multi-region, multi-cloud, and same-region replication) namespace configurationsj7\n\x06\x45xport\x12-Manage workflow history export configurationsj7\n\x12\x43onnectivity Rules\x12!Manage network connectivity rulesj"\n\x07Regions\x12\x17Query available regionsj,\n\x07\x41\x63\x63ount\x12!Manage account settings and usagej*\n\nOperations\x12\x1cQuery async operation statusr>\n\x1cTemporal Cloud Documentation\x12\x1ehttps://docs.temporal.io/cloudb\x06proto3' ) _CLOUDSERVICE = DESCRIPTOR.services_by_name["CloudService"] if _descriptor._USE_C_DESCRIPTORS == False: DESCRIPTOR._options = None - DESCRIPTOR._serialized_options = b"\n%io.temporal.api.cloud.cloudservice.v1B\014ServiceProtoP\001Z5go.temporal.io/api/cloud/cloudservice/v1;cloudservice\252\002$Temporalio.Api.Cloud.CloudService.V1\352\002(Temporalio::Api::Cloud::CloudService::V1" + DESCRIPTOR._serialized_options = b"\n%io.temporal.api.cloud.cloudservice.v1B\014ServiceProtoP\001Z5go.temporal.io/api/cloud/cloudservice/v1;cloudservice\252\002$Temporalio.Api.Cloud.CloudService.V1\352\002(Temporalio::Api::Cloud::CloudService::V1\222A\302\023\022\340\r\n\026Temporal Cloud Ops API\022\226\014Programmatic access to manage Temporal Cloud control plane resources including namespaces, users, service accounts, and more.\n\n## Authentication\n\nAll API requests require authentication using an API Key. Include your API key in the `Authorization` header using the Bearer scheme:\n\n```\nAuthorization: Bearer YOUR_API_KEY\n```\n\nAPI keys can be created and managed through the [API Keys endpoints](#tag/API-Keys) or via the Temporal Cloud UI. For more information, see [API Keys Documentation](https://docs.temporal.io/cloud/api-keys).\n\n## Authorization\n\nThe API uses Role-Based Access Control (RBAC) to manage permissions. Each operation requires specific role-based permissions in addition to a valid API key.\n\n### Account-Level Roles\n\n- **Account Owner** - Full account administration access\n- **Account Admin** - Manage namespaces, users, and service accounts \n- **Account Developer** - Create namespaces and manage Nexus endpoints\n- **Finance Admin** - View usage and billing information\n- **Account Read** - Read-only access to account resources\n\n### Namespace-Level Roles\n\n- **Namespace Admin** - Full access to namespace configuration and data\n- **Namespace Write** - Execute workflows and modify workflow data\n- **Namespace Read** - Read-only access to namespace data\n\nNamespace-level permissions are scoped to specific namespaces. A user or service account may have different permission levels across different namespaces.\n\nFor detailed information about roles and permissions, see [Access Control Documentation](https://docs.temporal.io/cloud/users).2\0031.0:\247\001\n\006x-logo\022\234\001*\231\001\n\226\001\n\003url\022\216\001\032\213\001https://images.ctfassets.net/0uuz8ydxyd9p/4YGUnEoCaH9SyoUDhlJkau/e1600205d17eeee3033d926ef06664a9/Temporal_LogoLockup_Horizontal_dark_1.svgj.\n\nNamespaces\022 Manage Temporal Cloud namespacesj0\n\005Users\022'Manage users and their namespace accessjF\n\020Service Accounts\0222Manage service accounts and their namespace accessj.\n\010API Keys\022\"Manage API keys for authenticationj1\n\006Groups\022'Manage user groups and group membershipj\037\n\005Nexus\022\026Manage Nexus endpointsj\177\n\021High Availability\022jManage high availability (multi-region, multi-cloud, and same-region replication) namespace configurationsj7\n\006Export\022-Manage workflow history export configurationsj7\n\022Connectivity Rules\022!Manage network connectivity rulesj\"\n\007Regions\022\027Query available regionsj,\n\007Account\022!Manage account settings and usagej*\n\nOperations\022\034Query async operation statusr>\n\034Temporal Cloud Documentation\022\036https://docs.temporal.io/cloud" + _CLOUDSERVICE.methods_by_name["GetCurrentIdentity"]._options = None + _CLOUDSERVICE.methods_by_name[ + "GetCurrentIdentity" + ]._serialized_options = b"\202\323\344\223\002\031\022\027/cloud/current-identity\222Ax\n\007Account\022\024Get current identity\032WReturns information about the currently authenticated user or service account principal" _CLOUDSERVICE.methods_by_name["GetUsers"]._options = None _CLOUDSERVICE.methods_by_name[ "GetUsers" - ]._serialized_options = b"\202\323\344\223\002\016\022\014/cloud/users" + ]._serialized_options = b'\202\323\344\223\002\016\022\014/cloud/users\222A\225\001\n\005Users\022\016List all users\032*Returns a list of all users in the account"E\n\035User management documentation\022$https://docs.temporal.io/cloud/users*\tlistUsers' _CLOUDSERVICE.methods_by_name["GetUser"]._options = None _CLOUDSERVICE.methods_by_name[ "GetUser" - ]._serialized_options = b"\202\323\344\223\002\030\022\026/cloud/users/{user_id}" + ]._serialized_options = b'\202\323\344\223\002\030\022\026/cloud/users/{user_id}\222A\205\001\n\005Users\022\016Get user by ID\032%Takes a user ID, returns user details"E\n\035User management documentation\022$https://docs.temporal.io/cloud/users' _CLOUDSERVICE.methods_by_name["CreateUser"]._options = None _CLOUDSERVICE.methods_by_name[ "CreateUser" - ]._serialized_options = b'\202\323\344\223\002\021"\014/cloud/users:\001*' + ]._serialized_options = b'\202\323\344\223\002\021"\014/cloud/users:\001*\222A9\n\005Users\022\rCreate a user\032!Creates a new user in the account' _CLOUDSERVICE.methods_by_name["UpdateUser"]._options = None _CLOUDSERVICE.methods_by_name[ "UpdateUser" - ]._serialized_options = b'\202\323\344\223\002\033"\026/cloud/users/{user_id}:\001*' + ]._serialized_options = b'\202\323\344\223\002\033"\026/cloud/users/{user_id}:\001*\222A:\n\005Users\022\rUpdate a user\032"Updates an existing user\'s details' _CLOUDSERVICE.methods_by_name["DeleteUser"]._options = None _CLOUDSERVICE.methods_by_name[ "DeleteUser" - ]._serialized_options = b"\202\323\344\223\002\030*\026/cloud/users/{user_id}" + ]._serialized_options = b"\202\323\344\223\002\030*\026/cloud/users/{user_id}\222A7\n\005Users\022\rDelete a user\032\037Removes a user from the account" _CLOUDSERVICE.methods_by_name["SetUserNamespaceAccess"]._options = None _CLOUDSERVICE.methods_by_name[ "SetUserNamespaceAccess" - ]._serialized_options = b'\202\323\344\223\0029"4/cloud/namespaces/{namespace}/users/{user_id}/access:\001*' + ]._serialized_options = b'\202\323\344\223\0029"4/cloud/namespaces/{namespace}/users/{user_id}/access:\001*\222A\305\001\n\005Users\022\031Set user namespace access\0328Configures a user\'s permissions for a specific namespace"g\n#Namespace permissions documentation\022@https://docs.temporal.io/cloud/users-namespace-level-permissions' _CLOUDSERVICE.methods_by_name["GetAsyncOperation"]._options = None _CLOUDSERVICE.methods_by_name[ "GetAsyncOperation" - ]._serialized_options = ( - b"\202\323\344\223\002(\022&/cloud/operations/{async_operation_id}" - ) + ]._serialized_options = b"\202\323\344\223\002(\022&/cloud/operations/{async_operation_id}\222Am\n\nOperations\022\032Get async operation status\032CReturns the current status and details of an asynchronous operation" _CLOUDSERVICE.methods_by_name["CreateNamespace"]._options = None _CLOUDSERVICE.methods_by_name[ "CreateNamespace" - ]._serialized_options = b'\202\323\344\223\002\026"\021/cloud/namespaces:\001*' + ]._serialized_options = b'\202\323\344\223\002\026"\021/cloud/namespaces:\001*\222A\231\001\n\nNamespaces\022\022Create a namespace\032&Creates a new namespace in the account"O\n"Namespace management documentation\022)https://docs.temporal.io/cloud/namespaces' _CLOUDSERVICE.methods_by_name["GetNamespaces"]._options = None _CLOUDSERVICE.methods_by_name[ "GetNamespaces" - ]._serialized_options = b"\202\323\344\223\002\023\022\021/cloud/namespaces" + ]._serialized_options = b'\202\323\344\223\002\023\022\021/cloud/namespaces\222A\243\001\n\nNamespaces\022\023List all namespaces\032/Returns a list of all namespaces in the account"O\n"Namespace management documentation\022)https://docs.temporal.io/cloud/namespaces' _CLOUDSERVICE.methods_by_name["GetNamespace"]._options = None _CLOUDSERVICE.methods_by_name[ "GetNamespace" - ]._serialized_options = ( - b"\202\323\344\223\002\037\022\035/cloud/namespaces/{namespace}" - ) + ]._serialized_options = b'\202\323\344\223\002\037\022\035/cloud/namespaces/{namespace}\222A\255\001\n\nNamespaces\022\025Get namespace details\0327Returns detailed information about a specific namespace"O\n"Namespace management documentation\022)https://docs.temporal.io/cloud/namespaces' _CLOUDSERVICE.methods_by_name["UpdateNamespace"]._options = None _CLOUDSERVICE.methods_by_name[ "UpdateNamespace" - ]._serialized_options = ( - b'\202\323\344\223\002""\035/cloud/namespaces/{namespace}:\001*' - ) + ]._serialized_options = b'\202\323\344\223\002""\035/cloud/namespaces/{namespace}:\001*\222A\242\001\n\nNamespaces\022\022Update a namespace\032/Updates configuration for an existing namespace"O\n"Namespace management documentation\022)https://docs.temporal.io/cloud/namespaces' _CLOUDSERVICE.methods_by_name["RenameCustomSearchAttribute"]._options = None _CLOUDSERVICE.methods_by_name[ "RenameCustomSearchAttribute" - ]._serialized_options = b'\202\323\344\223\002A"Creates a new Nexus endpoint for cross-namespace communication"5\n\023Nexus documentation\022\036https://docs.temporal.io/nexus' _CLOUDSERVICE.methods_by_name["UpdateNexusEndpoint"]._options = None _CLOUDSERVICE.methods_by_name[ "UpdateNexusEndpoint" - ]._serialized_options = ( - b'\202\323\344\223\002)"$/cloud/nexus/endpoints/{endpoint_id}:\001*' - ) + ]._serialized_options = b'\202\323\344\223\002)"$/cloud/nexus/endpoints/{endpoint_id}:\001*\222A\213\001\n\005Nexus\022\027Update a Nexus endpoint\0322Updates an existing Nexus endpoint\'s configuration"5\n\023Nexus documentation\022\036https://docs.temporal.io/nexus' _CLOUDSERVICE.methods_by_name["DeleteNexusEndpoint"]._options = None _CLOUDSERVICE.methods_by_name[ "DeleteNexusEndpoint" - ]._serialized_options = ( - b"\202\323\344\223\002&*$/cloud/nexus/endpoints/{endpoint_id}" - ) + ]._serialized_options = b'\202\323\344\223\002&*$/cloud/nexus/endpoints/{endpoint_id}\222A\202\001\n\005Nexus\022\027Delete a Nexus endpoint\032)Removes a Nexus endpoint from the account"5\n\023Nexus documentation\022\036https://docs.temporal.io/nexus' _CLOUDSERVICE.methods_by_name["GetUserGroups"]._options = None _CLOUDSERVICE.methods_by_name[ "GetUserGroups" - ]._serialized_options = b"\202\323\344\223\002\024\022\022/cloud/user-groups" + ]._serialized_options = b'\202\323\344\223\002\024\022\022/cloud/user-groups\222A\247\001\n\006Groups\022\024List all user groups\0320Returns a list of all user groups in the account"U\n\031User groups documentation\0228https://docs.temporal.io/cloud/users-account-level-roles' _CLOUDSERVICE.methods_by_name["GetUserGroup"]._options = None _CLOUDSERVICE.methods_by_name[ "GetUserGroup" - ]._serialized_options = ( - b"\202\323\344\223\002\037\022\035/cloud/user-groups/{group_id}" - ) + ]._serialized_options = b'\202\323\344\223\002\037\022\035/cloud/user-groups/{group_id}\222A\243\001\n\006Groups\022\026Get user group details\0328Returns detailed information about a specific user group"G\n\031User groups documentation\022*https://docs.temporal.io/cloud/user-groups' _CLOUDSERVICE.methods_by_name["CreateUserGroup"]._options = None _CLOUDSERVICE.methods_by_name[ "CreateUserGroup" - ]._serialized_options = b'\202\323\344\223\002\027"\022/cloud/user-groups:\001*' + ]._serialized_options = b'\202\323\344\223\002\027"\022/cloud/user-groups:\001*\222A\231\001\n\006Groups\022\023Create a user group\0321Creates a new user group for managing permissions"G\n\031User groups documentation\022*https://docs.temporal.io/cloud/user-groups' _CLOUDSERVICE.methods_by_name["UpdateUserGroup"]._options = None _CLOUDSERVICE.methods_by_name[ "UpdateUserGroup" - ]._serialized_options = ( - b'\202\323\344\223\002""\035/cloud/user-groups/{group_id}:\001*' - ) + ]._serialized_options = b'\202\323\344\223\002""\035/cloud/user-groups/{group_id}:\001*\222A\223\001\n\006Groups\022\023Update a user group\032+Updates an existing user group\'s properties"G\n\031User groups documentation\022*https://docs.temporal.io/cloud/user-groups' _CLOUDSERVICE.methods_by_name["DeleteUserGroup"]._options = None _CLOUDSERVICE.methods_by_name[ "DeleteUserGroup" - ]._serialized_options = ( - b"\202\323\344\223\002\037*\035/cloud/user-groups/{group_id}" - ) + ]._serialized_options = b'\202\323\344\223\002\037*\035/cloud/user-groups/{group_id}\222A\215\001\n\006Groups\022\023Delete a user group\032%Removes a user group from the account"G\n\031User groups documentation\022*https://docs.temporal.io/cloud/user-groups' _CLOUDSERVICE.methods_by_name["SetUserGroupNamespaceAccess"]._options = None _CLOUDSERVICE.methods_by_name[ "SetUserGroupNamespaceAccess" - ]._serialized_options = b'\202\323\344\223\002@";/cloud/namespaces/{namespace}/user-groups/{group_id}/access:\001*' + ]._serialized_options = b'\202\323\344\223\002@";/cloud/namespaces/{namespace}/user-groups/{group_id}/access:\001*\222A\262\001\n\006Groups\022\037Set user group namespace access\032>Configures a user group\'s permissions for a specific namespace"G\n\031User groups documentation\022*https://docs.temporal.io/cloud/user-groups' _CLOUDSERVICE.methods_by_name["AddUserGroupMember"]._options = None _CLOUDSERVICE.methods_by_name[ "AddUserGroupMember" - ]._serialized_options = ( - b'\202\323\344\223\002*"%/cloud/user-groups/{group_id}/members:\001*' - ) + ]._serialized_options = b'\202\323\344\223\002*"%/cloud/user-groups/{group_id}/members:\001*\222A\225\001\n\006Groups\022\021Add user to group\032/Adds a user to a user group (Cloud groups only)"G\n\031User groups documentation\022*https://docs.temporal.io/cloud/user-groups' _CLOUDSERVICE.methods_by_name["RemoveUserGroupMember"]._options = None _CLOUDSERVICE.methods_by_name[ "RemoveUserGroupMember" - ]._serialized_options = ( - b'\202\323\344\223\0020"+/cloud/user-groups/{group_id}/remove-member:\001*' - ) + ]._serialized_options = b'\202\323\344\223\0020"+/cloud/user-groups/{group_id}/remove-member:\001*\222A\237\001\n\006Groups\022\026Remove user from group\0324Removes a user from a user group (Cloud groups only)"G\n\031User groups documentation\022*https://docs.temporal.io/cloud/user-groups' _CLOUDSERVICE.methods_by_name["GetUserGroupMembers"]._options = None _CLOUDSERVICE.methods_by_name[ "GetUserGroupMembers" - ]._serialized_options = ( - b"\202\323\344\223\002'\022%/cloud/user-groups/{group_id}/members" - ) + ]._serialized_options = b"\202\323\344\223\002'\022%/cloud/user-groups/{group_id}/members\222A\225\001\n\006Groups\022\025List users in a group\032+Returns a list of all users in a user group\"G\n\031User groups documentation\022*https://docs.temporal.io/cloud/user-groups" _CLOUDSERVICE.methods_by_name["CreateServiceAccount"]._options = None _CLOUDSERVICE.methods_by_name[ "CreateServiceAccount" - ]._serialized_options = ( - b'\202\323\344\223\002\034"\027/cloud/service-accounts:\001*' - ) + ]._serialized_options = b'\202\323\344\223\002\034"\027/cloud/service-accounts:\001*\222A\263\001\n\020Service Accounts\022\030Create a service account\0322Creates a new service account for automated access"Q\n\036Service Accounts documentation\022/https://docs.temporal.io/cloud/service-accounts' _CLOUDSERVICE.methods_by_name["GetServiceAccount"]._options = None _CLOUDSERVICE.methods_by_name[ "GetServiceAccount" - ]._serialized_options = ( - b"\202\323\344\223\002.\022,/cloud/service-accounts/{service_account_id}" - ) + ]._serialized_options = b'\202\323\344\223\002.\022,/cloud/service-accounts/{service_account_id}\222A\301\001\n\020Service Accounts\022\033Get service account details\032=Returns detailed information about a specific service account"Q\n\036Service Accounts documentation\022/https://docs.temporal.io/cloud/service-accounts' _CLOUDSERVICE.methods_by_name["GetServiceAccounts"]._options = None _CLOUDSERVICE.methods_by_name[ "GetServiceAccounts" - ]._serialized_options = b"\202\323\344\223\002\031\022\027/cloud/service-accounts" + ]._serialized_options = b'\202\323\344\223\002\031\022\027/cloud/service-accounts\222A\267\001\n\020Service Accounts\022\031List all service accounts\0325Returns a list of all service accounts in the account"Q\n\036Service Accounts documentation\022/https://docs.temporal.io/cloud/service-accounts' _CLOUDSERVICE.methods_by_name["UpdateServiceAccount"]._options = None _CLOUDSERVICE.methods_by_name[ "UpdateServiceAccount" - ]._serialized_options = ( - b'\202\323\344\223\0021",/cloud/service-accounts/{service_account_id}:\001*' - ) + ]._serialized_options = b'\202\323\344\223\0021",/cloud/service-accounts/{service_account_id}:\001*\222A\261\001\n\020Service Accounts\022\030Update a service account\0320Updates an existing service account\'s properties"Q\n\036Service Accounts documentation\022/https://docs.temporal.io/cloud/service-accounts' _CLOUDSERVICE.methods_by_name["SetServiceAccountNamespaceAccess"]._options = None _CLOUDSERVICE.methods_by_name[ "SetServiceAccountNamespaceAccess" - ]._serialized_options = b'\202\323\344\223\002O"J/cloud/namespaces/{namespace}/service-accounts/{service_account_id}/access:\001*' + ]._serialized_options = b'\202\323\344\223\002O"J/cloud/namespaces/{namespace}/service-accounts/{service_account_id}/access:\001*\222A\320\001\n\020Service Accounts\022$Set service account namespace access\032CConfigures a service account\'s permissions for a specific namespace"Q\n\036Service Accounts documentation\022/https://docs.temporal.io/cloud/service-accounts' _CLOUDSERVICE.methods_by_name["DeleteServiceAccount"]._options = None _CLOUDSERVICE.methods_by_name[ "DeleteServiceAccount" - ]._serialized_options = ( - b"\202\323\344\223\002.*,/cloud/service-accounts/{service_account_id}" - ) + ]._serialized_options = b'\202\323\344\223\002.*,/cloud/service-accounts/{service_account_id}\222A\253\001\n\020Service Accounts\022\030Delete a service account\032*Removes a service account from the account"Q\n\036Service Accounts documentation\022/https://docs.temporal.io/cloud/service-accounts' _CLOUDSERVICE.methods_by_name["GetUsage"]._options = None _CLOUDSERVICE.methods_by_name[ "GetUsage" - ]._serialized_options = b"\202\323\344\223\002\016\022\014/cloud/usage" + ]._serialized_options = b"\202\323\344\223\002\016\022\014/cloud/usage\222A=\n\007Account\022\016Get usage data\032 Get usage data across namespacesX\001" _CLOUDSERVICE.methods_by_name["GetAccount"]._options = None _CLOUDSERVICE.methods_by_name[ "GetAccount" - ]._serialized_options = b"\202\323\344\223\002\020\022\016/cloud/account" + ]._serialized_options = b'\202\323\344\223\002\020\022\016/cloud/account\222A\230\001\n\007Account\022\023Get account details\032.Returns detailed information about the account"H\n\025Billing documentation\022/https://docs.temporal.io/cloud/billing-and-cost' _CLOUDSERVICE.methods_by_name["UpdateAccount"]._options = None _CLOUDSERVICE.methods_by_name[ "UpdateAccount" - ]._serialized_options = b'\202\323\344\223\002\023"\016/cloud/account:\001*' + ]._serialized_options = b'\202\323\344\223\002\023"\016/cloud/account:\001*\222A\227\001\n\007Account\022\026Update account details\032*Updates account configuration and settings"H\n\025Billing documentation\022/https://docs.temporal.io/cloud/billing-and-cost' _CLOUDSERVICE.methods_by_name["CreateNamespaceExportSink"]._options = None _CLOUDSERVICE.methods_by_name[ "CreateNamespaceExportSink" - ]._serialized_options = ( - b'\202\323\344\223\002/"*/cloud/namespaces/{namespace}/export-sinks:\001*' - ) + ]._serialized_options = b'\202\323\344\223\002/"*/cloud/namespaces/{namespace}/export-sinks:\001*\222A\217\001\n\006Export\022\032Create history export sink\032*Creates a new workflow history export sink"=\n\024Export documentation\022%https://docs.temporal.io/cloud/export' _CLOUDSERVICE.methods_by_name["GetNamespaceExportSink"]._options = None _CLOUDSERVICE.methods_by_name[ "GetNamespaceExportSink" - ]._serialized_options = ( - b"\202\323\344\223\0023\0221/cloud/namespaces/{namespace}/export-sinks/{name}" - ) + ]._serialized_options = b'\202\323\344\223\0023\0221/cloud/namespaces/{namespace}/export-sinks/{name}\222A\255\001\n\006Export\022\030Get history sink details\032JReturns detailed information about a specific workflow history export sink"=\n\024Export documentation\022%https://docs.temporal.io/cloud/export' _CLOUDSERVICE.methods_by_name["GetNamespaceExportSinks"]._options = None _CLOUDSERVICE.methods_by_name[ "GetNamespaceExportSinks" - ]._serialized_options = ( - b"\202\323\344\223\002,\022*/cloud/namespaces/{namespace}/export-sinks" - ) + ]._serialized_options = b'\202\323\344\223\002,\022*/cloud/namespaces/{namespace}/export-sinks\222A\247\001\n\006Export\022\031List history export sinks\032CReturns a list of all workflow history export sinks for a namespace"=\n\024Export documentation\022%https://docs.temporal.io/cloud/export' _CLOUDSERVICE.methods_by_name["UpdateNamespaceExportSink"]._options = None _CLOUDSERVICE.methods_by_name[ "UpdateNamespaceExportSink" - ]._serialized_options = b'\202\323\344\223\002;"6/cloud/namespaces/{namespace}/export-sinks/{spec.name}:\001*' + ]._serialized_options = b'\202\323\344\223\002;"6/cloud/namespaces/{namespace}/export-sinks/{spec.name}:\001*\222A\245\001\n\006Export\022\032Update history export sink\032@Updates an existing workflow history export sink\'s configuration"=\n\024Export documentation\022%https://docs.temporal.io/cloud/export' _CLOUDSERVICE.methods_by_name["DeleteNamespaceExportSink"]._options = None _CLOUDSERVICE.methods_by_name[ "DeleteNamespaceExportSink" - ]._serialized_options = ( - b"\202\323\344\223\0023*1/cloud/namespaces/{namespace}/export-sinks/{name}" - ) + ]._serialized_options = b'\202\323\344\223\0023*1/cloud/namespaces/{namespace}/export-sinks/{name}\222A\234\001\n\006Export\022\032Delete history export sink\0327Removes a workflow history export sink from a namespace"=\n\024Export documentation\022%https://docs.temporal.io/cloud/export' _CLOUDSERVICE.methods_by_name["ValidateNamespaceExportSink"]._options = None _CLOUDSERVICE.methods_by_name[ "ValidateNamespaceExportSink" - ]._serialized_options = b'\202\323\344\223\0028"3/cloud/namespaces/{namespace}/export-sinks/validate:\001*' + ]._serialized_options = b'\202\323\344\223\0027"2/cloud/namespaces/{namespace}/export-sink-validate:\001*\222A\327\001\n\006Export\022*Validate history export sink configuration\032bTests workflow history export sink configuration by delivering a test file to verify accessibility"=\n\024Export documentation\022%https://docs.temporal.io/cloud/export' _CLOUDSERVICE.methods_by_name["UpdateNamespaceTags"]._options = None _CLOUDSERVICE.methods_by_name[ "UpdateNamespaceTags" - ]._serialized_options = ( - b'\202\323\344\223\002.")/cloud/namespaces/{namespace}/update-tags:\001*' - ) + ]._serialized_options = b'\202\323\344\223\002.")/cloud/namespaces/{namespace}/update-tags:\001*\222A\253\001\n\nNamespaces\022\025Update namespace tags\032,Updates the tags associated with a namespace"X\n\033Namespace tag documentation\0229https://docs.temporal.io/cloud/namespaces#tag-a-namespace' _CLOUDSERVICE.methods_by_name["CreateConnectivityRule"]._options = None _CLOUDSERVICE.methods_by_name[ "CreateConnectivityRule" - ]._serialized_options = ( - b'\202\323\344\223\002\036"\031/cloud/connectivity-rules:\001*' - ) + ]._serialized_options = b'\202\323\344\223\002\036"\031/cloud/connectivity-rules:\001*\222A\265\001\n\022Connectivity Rules\022\030Create connectivity rule\032:Creates a new connectivity rule for network access control"I\n\032Connectivity documentation\022+https://docs.temporal.io/cloud/connectivity' _CLOUDSERVICE.methods_by_name["GetConnectivityRule"]._options = None _CLOUDSERVICE.methods_by_name[ "GetConnectivityRule" - ]._serialized_options = ( - b"\202\323\344\223\0022\0220/cloud/connectivity-rules/{connectivity_rule_id}" - ) + ]._serialized_options = b'\202\323\344\223\0022\0220/cloud/connectivity-rules/{connectivity_rule_id}\222A\277\001\n\022Connectivity Rules\022\035Get connectivity rule details\032?Returns detailed information about a specific connectivity rule"I\n\032Connectivity documentation\022+https://docs.temporal.io/cloud/connectivity' _CLOUDSERVICE.methods_by_name["GetConnectivityRules"]._options = None _CLOUDSERVICE.methods_by_name[ "GetConnectivityRules" - ]._serialized_options = b"\202\323\344\223\002\033\022\031/cloud/connectivity-rules" + ]._serialized_options = b'\202\323\344\223\002\033\022\031/cloud/connectivity-rules\222A\265\001\n\022Connectivity Rules\022\033List all connectivity rules\0327Returns a list of all connectivity rules in the account"I\n\032Connectivity documentation\022+https://docs.temporal.io/cloud/connectivity' _CLOUDSERVICE.methods_by_name["DeleteConnectivityRule"]._options = None _CLOUDSERVICE.methods_by_name[ "DeleteConnectivityRule" - ]._serialized_options = ( - b"\202\323\344\223\0022*0/cloud/connectivity-rules/{connectivity_rule_id}" - ) + ]._serialized_options = b'\202\323\344\223\0022*0/cloud/connectivity-rules/{connectivity_rule_id}\222A\247\001\n\022Connectivity Rules\022\030Delete connectivity rule\032,Removes a connectivity rule from the account"I\n\032Connectivity documentation\022+https://docs.temporal.io/cloud/connectivity' + _CLOUDSERVICE.methods_by_name["GetAuditLogs"]._options = None + _CLOUDSERVICE.methods_by_name[ + "GetAuditLogs" + ]._serialized_options = b'\202\323\344\223\002\023\022\021/cloud/audit-logs\222A\301\001\n\007Account\022\016Get audit logs\032YReturns a paginated list of audit logs for the account, optionally filtered by time range"K\n\033Audit logging documentation\022,https://docs.temporal.io/cloud/audit-logging' _CLOUDSERVICE.methods_by_name["ValidateAccountAuditLogSink"]._options = None _CLOUDSERVICE.methods_by_name[ "ValidateAccountAuditLogSink" - ]._serialized_options = ( - b"\202\323\344\223\002,\"'/cloud/account/audit-logs/sink/validate:\001*" - ) - _CLOUDSERVICE._serialized_start = 178 - _CLOUDSERVICE._serialized_end = 11296 + ]._serialized_options = b'\202\323\344\223\002#"\036/cloud/audit-log-sink-validate:\001*\222A\326\002\n\007Account\022\027Validate audit log sink\032\344\001Validate customer audit log sink is accessible from Temporal\'s workflow by delivering an empty file to the specified sink. The operation verifies that the sink is correctly configured, accessible and ready to receive audit logs."K\n\033Audit logging documentation\022,https://docs.temporal.io/cloud/audit-logging' + _CLOUDSERVICE.methods_by_name["CreateAccountAuditLogSink"]._options = None + _CLOUDSERVICE.methods_by_name[ + "CreateAccountAuditLogSink" + ]._serialized_options = b'\202\323\344\223\002\033"\026/cloud/audit-log-sinks:\001*\222A\244\001\n\007Account\022\025Create audit log sink\0325Creates a new audit log sink for exporting audit logs"K\n\033Audit logging documentation\022,https://docs.temporal.io/cloud/audit-logging' + _CLOUDSERVICE.methods_by_name["GetAccountAuditLogSink"]._options = None + _CLOUDSERVICE.methods_by_name[ + "GetAccountAuditLogSink" + ]._serialized_options = b'\202\323\344\223\002\037\022\035/cloud/audit-log-sinks/{name}\222A\260\001\n\007Account\022\032Get audit log sink details\032 None: ... + GetCurrentIdentity: grpc.UnaryUnaryMultiCallable[ + temporalio.api.cloud.cloudservice.v1.request_response_pb2.GetCurrentIdentityRequest, + temporalio.api.cloud.cloudservice.v1.request_response_pb2.GetCurrentIdentityResponse, + ] + """Get information about the current authenticated user or service account principal""" GetUsers: grpc.UnaryUnaryMultiCallable[ temporalio.api.cloud.cloudservice.v1.request_response_pb2.GetUsersRequest, temporalio.api.cloud.cloudservice.v1.request_response_pb2.GetUsersResponse, @@ -303,6 +308,11 @@ class CloudServiceStub: temporalio.api.cloud.cloudservice.v1.request_response_pb2.DeleteConnectivityRuleResponse, ] """Deletes a connectivity rule by id""" + GetAuditLogs: grpc.UnaryUnaryMultiCallable[ + temporalio.api.cloud.cloudservice.v1.request_response_pb2.GetAuditLogsRequest, + temporalio.api.cloud.cloudservice.v1.request_response_pb2.GetAuditLogsResponse, + ] + """Get audit logs""" ValidateAccountAuditLogSink: grpc.UnaryUnaryMultiCallable[ temporalio.api.cloud.cloudservice.v1.request_response_pb2.ValidateAccountAuditLogSinkRequest, temporalio.api.cloud.cloudservice.v1.request_response_pb2.ValidateAccountAuditLogSinkResponse, @@ -310,12 +320,59 @@ class CloudServiceStub: """Validate customer audit log sink is accessible from Temporal's workflow by delivering an empty file to the specified sink. The operation verifies that the sink is correctly configured, accessible and ready to receive audit logs. """ + CreateAccountAuditLogSink: grpc.UnaryUnaryMultiCallable[ + temporalio.api.cloud.cloudservice.v1.request_response_pb2.CreateAccountAuditLogSinkRequest, + temporalio.api.cloud.cloudservice.v1.request_response_pb2.CreateAccountAuditLogSinkResponse, + ] + """Create an audit log sink""" + GetAccountAuditLogSink: grpc.UnaryUnaryMultiCallable[ + temporalio.api.cloud.cloudservice.v1.request_response_pb2.GetAccountAuditLogSinkRequest, + temporalio.api.cloud.cloudservice.v1.request_response_pb2.GetAccountAuditLogSinkResponse, + ] + """Get an audit log sink""" + GetAccountAuditLogSinks: grpc.UnaryUnaryMultiCallable[ + temporalio.api.cloud.cloudservice.v1.request_response_pb2.GetAccountAuditLogSinksRequest, + temporalio.api.cloud.cloudservice.v1.request_response_pb2.GetAccountAuditLogSinksResponse, + ] + """Get audit log sinks""" + UpdateAccountAuditLogSink: grpc.UnaryUnaryMultiCallable[ + temporalio.api.cloud.cloudservice.v1.request_response_pb2.UpdateAccountAuditLogSinkRequest, + temporalio.api.cloud.cloudservice.v1.request_response_pb2.UpdateAccountAuditLogSinkResponse, + ] + """Update an audit log sink""" + DeleteAccountAuditLogSink: grpc.UnaryUnaryMultiCallable[ + temporalio.api.cloud.cloudservice.v1.request_response_pb2.DeleteAccountAuditLogSinkRequest, + temporalio.api.cloud.cloudservice.v1.request_response_pb2.DeleteAccountAuditLogSinkResponse, + ] + """Delete an audit log sink""" + GetNamespaceCapacityInfo: grpc.UnaryUnaryMultiCallable[ + temporalio.api.cloud.cloudservice.v1.request_response_pb2.GetNamespaceCapacityInfoRequest, + temporalio.api.cloud.cloudservice.v1.request_response_pb2.GetNamespaceCapacityInfoResponse, + ] + """Get namespace capacity information""" + CreateBillingReport: grpc.UnaryUnaryMultiCallable[ + temporalio.api.cloud.cloudservice.v1.request_response_pb2.CreateBillingReportRequest, + temporalio.api.cloud.cloudservice.v1.request_response_pb2.CreateBillingReportResponse, + ] + """Create a billing report""" + GetBillingReport: grpc.UnaryUnaryMultiCallable[ + temporalio.api.cloud.cloudservice.v1.request_response_pb2.GetBillingReportRequest, + temporalio.api.cloud.cloudservice.v1.request_response_pb2.GetBillingReportResponse, + ] + """Get a billing report""" class CloudServiceServicer(metaclass=abc.ABCMeta): """WARNING: This service is currently experimental and may change in incompatible ways. """ + @abc.abstractmethod + def GetCurrentIdentity( + self, + request: temporalio.api.cloud.cloudservice.v1.request_response_pb2.GetCurrentIdentityRequest, + context: grpc.ServicerContext, + ) -> temporalio.api.cloud.cloudservice.v1.request_response_pb2.GetCurrentIdentityResponse: + """Get information about the current authenticated user or service account principal""" @abc.abstractmethod def GetUsers( self, @@ -725,6 +782,13 @@ class CloudServiceServicer(metaclass=abc.ABCMeta): ) -> temporalio.api.cloud.cloudservice.v1.request_response_pb2.DeleteConnectivityRuleResponse: """Deletes a connectivity rule by id""" @abc.abstractmethod + def GetAuditLogs( + self, + request: temporalio.api.cloud.cloudservice.v1.request_response_pb2.GetAuditLogsRequest, + context: grpc.ServicerContext, + ) -> temporalio.api.cloud.cloudservice.v1.request_response_pb2.GetAuditLogsResponse: + """Get audit logs""" + @abc.abstractmethod def ValidateAccountAuditLogSink( self, request: temporalio.api.cloud.cloudservice.v1.request_response_pb2.ValidateAccountAuditLogSinkRequest, @@ -733,6 +797,62 @@ class CloudServiceServicer(metaclass=abc.ABCMeta): """Validate customer audit log sink is accessible from Temporal's workflow by delivering an empty file to the specified sink. The operation verifies that the sink is correctly configured, accessible and ready to receive audit logs. """ + @abc.abstractmethod + def CreateAccountAuditLogSink( + self, + request: temporalio.api.cloud.cloudservice.v1.request_response_pb2.CreateAccountAuditLogSinkRequest, + context: grpc.ServicerContext, + ) -> temporalio.api.cloud.cloudservice.v1.request_response_pb2.CreateAccountAuditLogSinkResponse: + """Create an audit log sink""" + @abc.abstractmethod + def GetAccountAuditLogSink( + self, + request: temporalio.api.cloud.cloudservice.v1.request_response_pb2.GetAccountAuditLogSinkRequest, + context: grpc.ServicerContext, + ) -> temporalio.api.cloud.cloudservice.v1.request_response_pb2.GetAccountAuditLogSinkResponse: + """Get an audit log sink""" + @abc.abstractmethod + def GetAccountAuditLogSinks( + self, + request: temporalio.api.cloud.cloudservice.v1.request_response_pb2.GetAccountAuditLogSinksRequest, + context: grpc.ServicerContext, + ) -> temporalio.api.cloud.cloudservice.v1.request_response_pb2.GetAccountAuditLogSinksResponse: + """Get audit log sinks""" + @abc.abstractmethod + def UpdateAccountAuditLogSink( + self, + request: temporalio.api.cloud.cloudservice.v1.request_response_pb2.UpdateAccountAuditLogSinkRequest, + context: grpc.ServicerContext, + ) -> temporalio.api.cloud.cloudservice.v1.request_response_pb2.UpdateAccountAuditLogSinkResponse: + """Update an audit log sink""" + @abc.abstractmethod + def DeleteAccountAuditLogSink( + self, + request: temporalio.api.cloud.cloudservice.v1.request_response_pb2.DeleteAccountAuditLogSinkRequest, + context: grpc.ServicerContext, + ) -> temporalio.api.cloud.cloudservice.v1.request_response_pb2.DeleteAccountAuditLogSinkResponse: + """Delete an audit log sink""" + @abc.abstractmethod + def GetNamespaceCapacityInfo( + self, + request: temporalio.api.cloud.cloudservice.v1.request_response_pb2.GetNamespaceCapacityInfoRequest, + context: grpc.ServicerContext, + ) -> temporalio.api.cloud.cloudservice.v1.request_response_pb2.GetNamespaceCapacityInfoResponse: + """Get namespace capacity information""" + @abc.abstractmethod + def CreateBillingReport( + self, + request: temporalio.api.cloud.cloudservice.v1.request_response_pb2.CreateBillingReportRequest, + context: grpc.ServicerContext, + ) -> temporalio.api.cloud.cloudservice.v1.request_response_pb2.CreateBillingReportResponse: + """Create a billing report""" + @abc.abstractmethod + def GetBillingReport( + self, + request: temporalio.api.cloud.cloudservice.v1.request_response_pb2.GetBillingReportRequest, + context: grpc.ServicerContext, + ) -> temporalio.api.cloud.cloudservice.v1.request_response_pb2.GetBillingReportResponse: + """Get a billing report""" def add_CloudServiceServicer_to_server( servicer: CloudServiceServicer, server: grpc.Server diff --git a/temporalio/api/cloud/namespace/v1/__init__.py b/temporalio/api/cloud/namespace/v1/__init__.py index ed81cf865..7bf5d0446 100644 --- a/temporalio/api/cloud/namespace/v1/__init__.py +++ b/temporalio/api/cloud/namespace/v1/__init__.py @@ -1,6 +1,8 @@ from .message_pb2 import ( ApiKeyAuthSpec, AWSPrivateLinkInfo, + Capacity, + CapacitySpec, CertificateFilterSpec, CodecServerSpec, Endpoints, @@ -11,6 +13,7 @@ Limits, MtlsAuthSpec, Namespace, + NamespaceCapacityInfo, NamespaceRegionStatus, NamespaceSpec, PrivateConnectivity, @@ -19,6 +22,8 @@ __all__ = [ "AWSPrivateLinkInfo", "ApiKeyAuthSpec", + "Capacity", + "CapacitySpec", "CertificateFilterSpec", "CodecServerSpec", "Endpoints", @@ -29,6 +34,7 @@ "Limits", "MtlsAuthSpec", "Namespace", + "NamespaceCapacityInfo", "NamespaceRegionStatus", "NamespaceSpec", "PrivateConnectivity", diff --git a/temporalio/api/cloud/namespace/v1/message_pb2.py b/temporalio/api/cloud/namespace/v1/message_pb2.py index 17f25d185..5cd6c00c2 100644 --- a/temporalio/api/cloud/namespace/v1/message_pb2.py +++ b/temporalio/api/cloud/namespace/v1/message_pb2.py @@ -27,13 +27,14 @@ ) DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile( - b'\n-temporal/api/cloud/namespace/v1/message.proto\x12\x1ftemporal.api.cloud.namespace.v1\x1a,temporal/api/cloud/resource/v1/message.proto\x1a\x1fgoogle/protobuf/timestamp.proto\x1a(temporal/api/cloud/sink/v1/message.proto\x1a\x34temporal/api/cloud/connectivityrule/v1/message.proto"\x81\x01\n\x15\x43\x65rtificateFilterSpec\x12\x13\n\x0b\x63ommon_name\x18\x01 \x01(\t\x12\x14\n\x0corganization\x18\x02 \x01(\t\x12\x1b\n\x13organizational_unit\x18\x03 \x01(\t\x12 \n\x18subject_alternative_name\x18\x04 \x01(\t"\xb7\x01\n\x0cMtlsAuthSpec\x12%\n\x1d\x61\x63\x63\x65pted_client_ca_deprecated\x18\x01 \x01(\t\x12\x1a\n\x12\x61\x63\x63\x65pted_client_ca\x18\x04 \x01(\x0c\x12S\n\x13\x63\x65rtificate_filters\x18\x02 \x03(\x0b\x32\x36.temporal.api.cloud.namespace.v1.CertificateFilterSpec\x12\x0f\n\x07\x65nabled\x18\x03 \x01(\x08"!\n\x0e\x41piKeyAuthSpec\x12\x0f\n\x07\x65nabled\x18\x01 \x01(\x08"\xf4\x02\n\x0f\x43odecServerSpec\x12\x10\n\x08\x65ndpoint\x18\x01 \x01(\t\x12\x19\n\x11pass_access_token\x18\x02 \x01(\x08\x12(\n include_cross_origin_credentials\x18\x03 \x01(\x08\x12\x61\n\x14\x63ustom_error_message\x18\x04 \x01(\x0b\x32\x43.temporal.api.cloud.namespace.v1.CodecServerSpec.CustomErrorMessage\x1a\xa6\x01\n\x12\x43ustomErrorMessage\x12\x61\n\x07\x64\x65\x66\x61ult\x18\x01 \x01(\x0b\x32P.temporal.api.cloud.namespace.v1.CodecServerSpec.CustomErrorMessage.ErrorMessage\x1a-\n\x0c\x45rrorMessage\x12\x0f\n\x07message\x18\x01 \x01(\t\x12\x0c\n\x04link\x18\x02 \x01(\t"1\n\rLifecycleSpec\x12 \n\x18\x65nable_delete_protection\x18\x01 \x01(\x08"8\n\x14HighAvailabilitySpec\x12 \n\x18\x64isable_managed_failover\x18\x01 \x01(\x08"\x89\t\n\rNamespaceSpec\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x0f\n\x07regions\x18\x02 \x03(\t\x12\x16\n\x0eretention_days\x18\x03 \x01(\x05\x12@\n\tmtls_auth\x18\x04 \x01(\x0b\x32-.temporal.api.cloud.namespace.v1.MtlsAuthSpec\x12\x45\n\x0c\x61pi_key_auth\x18\x07 \x01(\x0b\x32/.temporal.api.cloud.namespace.v1.ApiKeyAuthSpec\x12p\n\x18\x63ustom_search_attributes\x18\x05 \x03(\x0b\x32J.temporal.api.cloud.namespace.v1.NamespaceSpec.CustomSearchAttributesEntryB\x02\x18\x01\x12_\n\x11search_attributes\x18\x08 \x03(\x0b\x32\x44.temporal.api.cloud.namespace.v1.NamespaceSpec.SearchAttributesEntry\x12\x46\n\x0c\x63odec_server\x18\x06 \x01(\x0b\x32\x30.temporal.api.cloud.namespace.v1.CodecServerSpec\x12\x41\n\tlifecycle\x18\t \x01(\x0b\x32..temporal.api.cloud.namespace.v1.LifecycleSpec\x12P\n\x11high_availability\x18\n \x01(\x0b\x32\x35.temporal.api.cloud.namespace.v1.HighAvailabilitySpec\x12\x1d\n\x15\x63onnectivity_rule_ids\x18\x0b \x03(\t\x1a=\n\x1b\x43ustomSearchAttributesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x1a{\n\x15SearchAttributesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12Q\n\x05value\x18\x02 \x01(\x0e\x32\x42.temporal.api.cloud.namespace.v1.NamespaceSpec.SearchAttributeType:\x02\x38\x01"\xac\x02\n\x13SearchAttributeType\x12%\n!SEARCH_ATTRIBUTE_TYPE_UNSPECIFIED\x10\x00\x12\x1e\n\x1aSEARCH_ATTRIBUTE_TYPE_TEXT\x10\x01\x12!\n\x1dSEARCH_ATTRIBUTE_TYPE_KEYWORD\x10\x02\x12\x1d\n\x19SEARCH_ATTRIBUTE_TYPE_INT\x10\x03\x12 \n\x1cSEARCH_ATTRIBUTE_TYPE_DOUBLE\x10\x04\x12\x1e\n\x1aSEARCH_ATTRIBUTE_TYPE_BOOL\x10\x05\x12"\n\x1eSEARCH_ATTRIBUTE_TYPE_DATETIME\x10\x06\x12&\n"SEARCH_ATTRIBUTE_TYPE_KEYWORD_LIST\x10\x07"Q\n\tEndpoints\x12\x13\n\x0bweb_address\x18\x01 \x01(\t\x12\x19\n\x11mtls_grpc_address\x18\x02 \x01(\t\x12\x14\n\x0cgrpc_address\x18\x03 \x01(\t"*\n\x06Limits\x12 \n\x18\x61\x63tions_per_second_limit\x18\x01 \x01(\x05"X\n\x12\x41WSPrivateLinkInfo\x12\x1e\n\x16\x61llowed_principal_arns\x18\x01 \x03(\t\x12"\n\x1avpc_endpoint_service_names\x18\x02 \x03(\t"t\n\x13PrivateConnectivity\x12\x0e\n\x06region\x18\x01 \x01(\t\x12M\n\x10\x61ws_private_link\x18\x02 \x01(\x0b\x32\x33.temporal.api.cloud.namespace.v1.AWSPrivateLinkInfo"\xc6\x07\n\tNamespace\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x18\n\x10resource_version\x18\x02 \x01(\t\x12<\n\x04spec\x18\x03 \x01(\x0b\x32..temporal.api.cloud.namespace.v1.NamespaceSpec\x12\x1c\n\x10state_deprecated\x18\x04 \x01(\tB\x02\x18\x01\x12<\n\x05state\x18\r \x01(\x0e\x32-.temporal.api.cloud.resource.v1.ResourceState\x12\x1a\n\x12\x61sync_operation_id\x18\x05 \x01(\t\x12=\n\tendpoints\x18\x06 \x01(\x0b\x32*.temporal.api.cloud.namespace.v1.Endpoints\x12\x15\n\ractive_region\x18\x07 \x01(\t\x12\x37\n\x06limits\x18\x08 \x01(\x0b\x32\'.temporal.api.cloud.namespace.v1.Limits\x12T\n\x16private_connectivities\x18\t \x03(\x0b\x32\x34.temporal.api.cloud.namespace.v1.PrivateConnectivity\x12\x30\n\x0c\x63reated_time\x18\n \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x36\n\x12last_modified_time\x18\x0b \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12S\n\rregion_status\x18\x0c \x03(\x0b\x32<.temporal.api.cloud.namespace.v1.Namespace.RegionStatusEntry\x12T\n\x12\x63onnectivity_rules\x18\x0e \x03(\x0b\x32\x38.temporal.api.cloud.connectivityrule.v1.ConnectivityRule\x12\x42\n\x04tags\x18\x0f \x03(\x0b\x32\x34.temporal.api.cloud.namespace.v1.Namespace.TagsEntry\x1ak\n\x11RegionStatusEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x45\n\x05value\x18\x02 \x01(\x0b\x32\x36.temporal.api.cloud.namespace.v1.NamespaceRegionStatus:\x02\x38\x01\x1a+\n\tTagsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01"\x9b\x02\n\x15NamespaceRegionStatus\x12\x1c\n\x10state_deprecated\x18\x01 \x01(\tB\x02\x18\x01\x12K\n\x05state\x18\x03 \x01(\x0e\x32<.temporal.api.cloud.namespace.v1.NamespaceRegionStatus.State\x12\x1a\n\x12\x61sync_operation_id\x18\x02 \x01(\t"{\n\x05State\x12\x15\n\x11STATE_UNSPECIFIED\x10\x00\x12\x10\n\x0cSTATE_ADDING\x10\x01\x12\x10\n\x0cSTATE_ACTIVE\x10\x02\x12\x11\n\rSTATE_PASSIVE\x10\x03\x12\x12\n\x0eSTATE_REMOVING\x10\x04\x12\x10\n\x0cSTATE_FAILED\x10\x05"\x91\x01\n\x0e\x45xportSinkSpec\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x0f\n\x07\x65nabled\x18\x02 \x01(\x08\x12.\n\x02s3\x18\x03 \x01(\x0b\x32".temporal.api.cloud.sink.v1.S3Spec\x12\x30\n\x03gcs\x18\x04 \x01(\x0b\x32#.temporal.api.cloud.sink.v1.GCSSpec"\xf6\x03\n\nExportSink\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x18\n\x10resource_version\x18\x02 \x01(\t\x12<\n\x05state\x18\x03 \x01(\x0e\x32-.temporal.api.cloud.resource.v1.ResourceState\x12=\n\x04spec\x18\x04 \x01(\x0b\x32/.temporal.api.cloud.namespace.v1.ExportSinkSpec\x12\x42\n\x06health\x18\x05 \x01(\x0e\x32\x32.temporal.api.cloud.namespace.v1.ExportSink.Health\x12\x15\n\rerror_message\x18\x06 \x01(\t\x12;\n\x17latest_data_export_time\x18\x07 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12:\n\x16last_health_check_time\x18\x08 \x01(\x0b\x32\x1a.google.protobuf.Timestamp"o\n\x06Health\x12\x16\n\x12HEALTH_UNSPECIFIED\x10\x00\x12\r\n\tHEALTH_OK\x10\x01\x12\x19\n\x15HEALTH_ERROR_INTERNAL\x10\x02\x12#\n\x1fHEALTH_ERROR_USER_CONFIGURATION\x10\x03\x42\xb1\x01\n"io.temporal.api.cloud.namespace.v1B\x0cMessageProtoP\x01Z/go.temporal.io/api/cloud/namespace/v1;namespace\xaa\x02!Temporalio.Api.Cloud.Namespace.V1\xea\x02%Temporalio::Api::Cloud::Namespace::V1b\x06proto3' + b'\n-temporal/api/cloud/namespace/v1/message.proto\x12\x1ftemporal.api.cloud.namespace.v1\x1a,temporal/api/cloud/resource/v1/message.proto\x1a\x1fgoogle/protobuf/timestamp.proto\x1a(temporal/api/cloud/sink/v1/message.proto\x1a\x34temporal/api/cloud/connectivityrule/v1/message.proto"\x81\x01\n\x15\x43\x65rtificateFilterSpec\x12\x13\n\x0b\x63ommon_name\x18\x01 \x01(\t\x12\x14\n\x0corganization\x18\x02 \x01(\t\x12\x1b\n\x13organizational_unit\x18\x03 \x01(\t\x12 \n\x18subject_alternative_name\x18\x04 \x01(\t"\xbb\x01\n\x0cMtlsAuthSpec\x12)\n\x1d\x61\x63\x63\x65pted_client_ca_deprecated\x18\x01 \x01(\tB\x02\x18\x01\x12\x1a\n\x12\x61\x63\x63\x65pted_client_ca\x18\x04 \x01(\x0c\x12S\n\x13\x63\x65rtificate_filters\x18\x02 \x03(\x0b\x32\x36.temporal.api.cloud.namespace.v1.CertificateFilterSpec\x12\x0f\n\x07\x65nabled\x18\x03 \x01(\x08"!\n\x0e\x41piKeyAuthSpec\x12\x0f\n\x07\x65nabled\x18\x01 \x01(\x08"1\n\rLifecycleSpec\x12 \n\x18\x65nable_delete_protection\x18\x01 \x01(\x08"\xf4\x02\n\x0f\x43odecServerSpec\x12\x10\n\x08\x65ndpoint\x18\x01 \x01(\t\x12\x19\n\x11pass_access_token\x18\x02 \x01(\x08\x12(\n include_cross_origin_credentials\x18\x03 \x01(\x08\x12\x61\n\x14\x63ustom_error_message\x18\x04 \x01(\x0b\x32\x43.temporal.api.cloud.namespace.v1.CodecServerSpec.CustomErrorMessage\x1a\xa6\x01\n\x12\x43ustomErrorMessage\x12\x61\n\x07\x64\x65\x66\x61ult\x18\x01 \x01(\x0b\x32P.temporal.api.cloud.namespace.v1.CodecServerSpec.CustomErrorMessage.ErrorMessage\x1a-\n\x0c\x45rrorMessage\x12\x0f\n\x07message\x18\x01 \x01(\t\x12\x0c\n\x04link\x18\x02 \x01(\t"8\n\x14HighAvailabilitySpec\x12 \n\x18\x64isable_managed_failover\x18\x01 \x01(\x08"\xdf\x01\n\x0c\x43\x61pacitySpec\x12K\n\ton_demand\x18\x01 \x01(\x0b\x32\x36.temporal.api.cloud.namespace.v1.CapacitySpec.OnDemandH\x00\x12P\n\x0bprovisioned\x18\x02 \x01(\x0b\x32\x39.temporal.api.cloud.namespace.v1.CapacitySpec.ProvisionedH\x00\x1a\n\n\x08OnDemand\x1a\x1c\n\x0bProvisioned\x12\r\n\x05value\x18\x01 \x01(\x01\x42\x06\n\x04spec"\xdc\x05\n\x08\x43\x61pacity\x12G\n\ton_demand\x18\x01 \x01(\x0b\x32\x32.temporal.api.cloud.namespace.v1.Capacity.OnDemandH\x00\x12L\n\x0bprovisioned\x18\x02 \x01(\x0b\x32\x35.temporal.api.cloud.namespace.v1.Capacity.ProvisionedH\x00\x12I\n\x0elatest_request\x18\x03 \x01(\x0b\x32\x31.temporal.api.cloud.namespace.v1.Capacity.Request\x1a\n\n\x08OnDemand\x1a$\n\x0bProvisioned\x12\x15\n\rcurrent_value\x18\x01 \x01(\x01\x1a\xab\x03\n\x07Request\x12\x46\n\x05state\x18\x01 \x01(\x0e\x32\x37.temporal.api.cloud.namespace.v1.Capacity.Request.State\x12.\n\nstart_time\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12,\n\x08\x65nd_time\x18\x03 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x1a\n\x12\x61sync_operation_id\x18\x04 \x01(\t\x12;\n\x04spec\x18\x05 \x01(\x0b\x32-.temporal.api.cloud.namespace.v1.CapacitySpec"\xa0\x01\n\x05State\x12&\n"STATE_CAPACITY_REQUEST_UNSPECIFIED\x10\x00\x12$\n STATE_CAPACITY_REQUEST_COMPLETED\x10\x01\x12&\n"STATE_CAPACITY_REQUEST_IN_PROGRESS\x10\x02\x12!\n\x1dSTATE_CAPACITY_REQUEST_FAILED\x10\x03\x42\x0e\n\x0c\x63urrent_mode"\xcf\t\n\rNamespaceSpec\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x0f\n\x07regions\x18\x02 \x03(\t\x12\x16\n\x0eretention_days\x18\x03 \x01(\x05\x12@\n\tmtls_auth\x18\x04 \x01(\x0b\x32-.temporal.api.cloud.namespace.v1.MtlsAuthSpec\x12\x45\n\x0c\x61pi_key_auth\x18\x07 \x01(\x0b\x32/.temporal.api.cloud.namespace.v1.ApiKeyAuthSpec\x12p\n\x18\x63ustom_search_attributes\x18\x05 \x03(\x0b\x32J.temporal.api.cloud.namespace.v1.NamespaceSpec.CustomSearchAttributesEntryB\x02\x18\x01\x12_\n\x11search_attributes\x18\x08 \x03(\x0b\x32\x44.temporal.api.cloud.namespace.v1.NamespaceSpec.SearchAttributesEntry\x12\x46\n\x0c\x63odec_server\x18\x06 \x01(\x0b\x32\x30.temporal.api.cloud.namespace.v1.CodecServerSpec\x12\x41\n\tlifecycle\x18\t \x01(\x0b\x32..temporal.api.cloud.namespace.v1.LifecycleSpec\x12P\n\x11high_availability\x18\n \x01(\x0b\x32\x35.temporal.api.cloud.namespace.v1.HighAvailabilitySpec\x12\x1d\n\x15\x63onnectivity_rule_ids\x18\x0b \x03(\t\x12\x44\n\rcapacity_spec\x18\x0c \x01(\x0b\x32-.temporal.api.cloud.namespace.v1.CapacitySpec\x1a=\n\x1b\x43ustomSearchAttributesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x1a{\n\x15SearchAttributesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12Q\n\x05value\x18\x02 \x01(\x0e\x32\x42.temporal.api.cloud.namespace.v1.NamespaceSpec.SearchAttributeType:\x02\x38\x01"\xac\x02\n\x13SearchAttributeType\x12%\n!SEARCH_ATTRIBUTE_TYPE_UNSPECIFIED\x10\x00\x12\x1e\n\x1aSEARCH_ATTRIBUTE_TYPE_TEXT\x10\x01\x12!\n\x1dSEARCH_ATTRIBUTE_TYPE_KEYWORD\x10\x02\x12\x1d\n\x19SEARCH_ATTRIBUTE_TYPE_INT\x10\x03\x12 \n\x1cSEARCH_ATTRIBUTE_TYPE_DOUBLE\x10\x04\x12\x1e\n\x1aSEARCH_ATTRIBUTE_TYPE_BOOL\x10\x05\x12"\n\x1eSEARCH_ATTRIBUTE_TYPE_DATETIME\x10\x06\x12&\n"SEARCH_ATTRIBUTE_TYPE_KEYWORD_LIST\x10\x07"Q\n\tEndpoints\x12\x13\n\x0bweb_address\x18\x01 \x01(\t\x12\x19\n\x11mtls_grpc_address\x18\x02 \x01(\t\x12\x14\n\x0cgrpc_address\x18\x03 \x01(\t"*\n\x06Limits\x12 \n\x18\x61\x63tions_per_second_limit\x18\x01 \x01(\x05"X\n\x12\x41WSPrivateLinkInfo\x12\x1e\n\x16\x61llowed_principal_arns\x18\x01 \x03(\t\x12"\n\x1avpc_endpoint_service_names\x18\x02 \x03(\t"t\n\x13PrivateConnectivity\x12\x0e\n\x06region\x18\x01 \x01(\t\x12M\n\x10\x61ws_private_link\x18\x02 \x01(\x0b\x32\x33.temporal.api.cloud.namespace.v1.AWSPrivateLinkInfo"\x83\x08\n\tNamespace\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x18\n\x10resource_version\x18\x02 \x01(\t\x12<\n\x04spec\x18\x03 \x01(\x0b\x32..temporal.api.cloud.namespace.v1.NamespaceSpec\x12\x1c\n\x10state_deprecated\x18\x04 \x01(\tB\x02\x18\x01\x12<\n\x05state\x18\r \x01(\x0e\x32-.temporal.api.cloud.resource.v1.ResourceState\x12\x1a\n\x12\x61sync_operation_id\x18\x05 \x01(\t\x12=\n\tendpoints\x18\x06 \x01(\x0b\x32*.temporal.api.cloud.namespace.v1.Endpoints\x12\x15\n\ractive_region\x18\x07 \x01(\t\x12\x37\n\x06limits\x18\x08 \x01(\x0b\x32\'.temporal.api.cloud.namespace.v1.Limits\x12T\n\x16private_connectivities\x18\t \x03(\x0b\x32\x34.temporal.api.cloud.namespace.v1.PrivateConnectivity\x12\x30\n\x0c\x63reated_time\x18\n \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x36\n\x12last_modified_time\x18\x0b \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12S\n\rregion_status\x18\x0c \x03(\x0b\x32<.temporal.api.cloud.namespace.v1.Namespace.RegionStatusEntry\x12T\n\x12\x63onnectivity_rules\x18\x0e \x03(\x0b\x32\x38.temporal.api.cloud.connectivityrule.v1.ConnectivityRule\x12\x42\n\x04tags\x18\x0f \x03(\x0b\x32\x34.temporal.api.cloud.namespace.v1.Namespace.TagsEntry\x12;\n\x08\x63\x61pacity\x18\x10 \x01(\x0b\x32).temporal.api.cloud.namespace.v1.Capacity\x1ak\n\x11RegionStatusEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x45\n\x05value\x18\x02 \x01(\x0b\x32\x36.temporal.api.cloud.namespace.v1.NamespaceRegionStatus:\x02\x38\x01\x1a+\n\tTagsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01"\x9b\x02\n\x15NamespaceRegionStatus\x12\x1c\n\x10state_deprecated\x18\x01 \x01(\tB\x02\x18\x01\x12K\n\x05state\x18\x03 \x01(\x0e\x32<.temporal.api.cloud.namespace.v1.NamespaceRegionStatus.State\x12\x1a\n\x12\x61sync_operation_id\x18\x02 \x01(\t"{\n\x05State\x12\x15\n\x11STATE_UNSPECIFIED\x10\x00\x12\x10\n\x0cSTATE_ADDING\x10\x01\x12\x10\n\x0cSTATE_ACTIVE\x10\x02\x12\x11\n\rSTATE_PASSIVE\x10\x03\x12\x12\n\x0eSTATE_REMOVING\x10\x04\x12\x10\n\x0cSTATE_FAILED\x10\x05"\x91\x01\n\x0e\x45xportSinkSpec\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x0f\n\x07\x65nabled\x18\x02 \x01(\x08\x12.\n\x02s3\x18\x03 \x01(\x0b\x32".temporal.api.cloud.sink.v1.S3Spec\x12\x30\n\x03gcs\x18\x04 \x01(\x0b\x32#.temporal.api.cloud.sink.v1.GCSSpec"\xf6\x03\n\nExportSink\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x18\n\x10resource_version\x18\x02 \x01(\t\x12<\n\x05state\x18\x03 \x01(\x0e\x32-.temporal.api.cloud.resource.v1.ResourceState\x12=\n\x04spec\x18\x04 \x01(\x0b\x32/.temporal.api.cloud.namespace.v1.ExportSinkSpec\x12\x42\n\x06health\x18\x05 \x01(\x0e\x32\x32.temporal.api.cloud.namespace.v1.ExportSink.Health\x12\x15\n\rerror_message\x18\x06 \x01(\t\x12;\n\x17latest_data_export_time\x18\x07 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12:\n\x16last_health_check_time\x18\x08 \x01(\x0b\x32\x1a.google.protobuf.Timestamp"o\n\x06Health\x12\x16\n\x12HEALTH_UNSPECIFIED\x10\x00\x12\r\n\tHEALTH_OK\x10\x01\x12\x19\n\x15HEALTH_ERROR_INTERNAL\x10\x02\x12#\n\x1fHEALTH_ERROR_USER_CONFIGURATION\x10\x03"\x9f\x06\n\x15NamespaceCapacityInfo\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x19\n\x11has_legacy_limits\x18\x02 \x01(\x08\x12\x43\n\x10\x63urrent_capacity\x18\x03 \x01(\x0b\x32).temporal.api.cloud.namespace.v1.Capacity\x12`\n\x0cmode_options\x18\x04 \x01(\x0b\x32J.temporal.api.cloud.namespace.v1.NamespaceCapacityInfo.CapacityModeOptions\x12K\n\x05stats\x18\x05 \x01(\x0b\x32<.temporal.api.cloud.namespace.v1.NamespaceCapacityInfo.Stats\x1a\xd3\x02\n\x13\x43\x61pacityModeOptions\x12k\n\x0bprovisioned\x18\x01 \x01(\x0b\x32V.temporal.api.cloud.namespace.v1.NamespaceCapacityInfo.CapacityModeOptions.Provisioned\x12\x66\n\ton_demand\x18\x02 \x01(\x0b\x32S.temporal.api.cloud.namespace.v1.NamespaceCapacityInfo.CapacityModeOptions.OnDemand\x1aH\n\x0bProvisioned\x12\x18\n\x10valid_tru_values\x18\x01 \x03(\x01\x12\x1f\n\x17max_available_tru_value\x18\x02 \x01(\x01\x1a\x1d\n\x08OnDemand\x12\x11\n\taps_limit\x18\x01 \x01(\x01\x1a\x8d\x01\n\x05Stats\x12Q\n\x03\x61ps\x18\x01 \x01(\x0b\x32\x44.temporal.api.cloud.namespace.v1.NamespaceCapacityInfo.Stats.Summary\x1a\x31\n\x07Summary\x12\x0c\n\x04mean\x18\x01 \x01(\x01\x12\x0b\n\x03p90\x18\x02 \x01(\x01\x12\x0b\n\x03p99\x18\x03 \x01(\x01\x42\xb1\x01\n"io.temporal.api.cloud.namespace.v1B\x0cMessageProtoP\x01Z/go.temporal.io/api/cloud/namespace/v1;namespace\xaa\x02!Temporalio.Api.Cloud.Namespace.V1\xea\x02%Temporalio::Api::Cloud::Namespace::V1b\x06proto3' ) _CERTIFICATEFILTERSPEC = DESCRIPTOR.message_types_by_name["CertificateFilterSpec"] _MTLSAUTHSPEC = DESCRIPTOR.message_types_by_name["MtlsAuthSpec"] _APIKEYAUTHSPEC = DESCRIPTOR.message_types_by_name["ApiKeyAuthSpec"] +_LIFECYCLESPEC = DESCRIPTOR.message_types_by_name["LifecycleSpec"] _CODECSERVERSPEC = DESCRIPTOR.message_types_by_name["CodecServerSpec"] _CODECSERVERSPEC_CUSTOMERRORMESSAGE = _CODECSERVERSPEC.nested_types_by_name[ "CustomErrorMessage" @@ -41,8 +42,14 @@ _CODECSERVERSPEC_CUSTOMERRORMESSAGE_ERRORMESSAGE = ( _CODECSERVERSPEC_CUSTOMERRORMESSAGE.nested_types_by_name["ErrorMessage"] ) -_LIFECYCLESPEC = DESCRIPTOR.message_types_by_name["LifecycleSpec"] _HIGHAVAILABILITYSPEC = DESCRIPTOR.message_types_by_name["HighAvailabilitySpec"] +_CAPACITYSPEC = DESCRIPTOR.message_types_by_name["CapacitySpec"] +_CAPACITYSPEC_ONDEMAND = _CAPACITYSPEC.nested_types_by_name["OnDemand"] +_CAPACITYSPEC_PROVISIONED = _CAPACITYSPEC.nested_types_by_name["Provisioned"] +_CAPACITY = DESCRIPTOR.message_types_by_name["Capacity"] +_CAPACITY_ONDEMAND = _CAPACITY.nested_types_by_name["OnDemand"] +_CAPACITY_PROVISIONED = _CAPACITY.nested_types_by_name["Provisioned"] +_CAPACITY_REQUEST = _CAPACITY.nested_types_by_name["Request"] _NAMESPACESPEC = DESCRIPTOR.message_types_by_name["NamespaceSpec"] _NAMESPACESPEC_CUSTOMSEARCHATTRIBUTESENTRY = _NAMESPACESPEC.nested_types_by_name[ "CustomSearchAttributesEntry" @@ -60,6 +67,21 @@ _NAMESPACEREGIONSTATUS = DESCRIPTOR.message_types_by_name["NamespaceRegionStatus"] _EXPORTSINKSPEC = DESCRIPTOR.message_types_by_name["ExportSinkSpec"] _EXPORTSINK = DESCRIPTOR.message_types_by_name["ExportSink"] +_NAMESPACECAPACITYINFO = DESCRIPTOR.message_types_by_name["NamespaceCapacityInfo"] +_NAMESPACECAPACITYINFO_CAPACITYMODEOPTIONS = ( + _NAMESPACECAPACITYINFO.nested_types_by_name["CapacityModeOptions"] +) +_NAMESPACECAPACITYINFO_CAPACITYMODEOPTIONS_PROVISIONED = ( + _NAMESPACECAPACITYINFO_CAPACITYMODEOPTIONS.nested_types_by_name["Provisioned"] +) +_NAMESPACECAPACITYINFO_CAPACITYMODEOPTIONS_ONDEMAND = ( + _NAMESPACECAPACITYINFO_CAPACITYMODEOPTIONS.nested_types_by_name["OnDemand"] +) +_NAMESPACECAPACITYINFO_STATS = _NAMESPACECAPACITYINFO.nested_types_by_name["Stats"] +_NAMESPACECAPACITYINFO_STATS_SUMMARY = ( + _NAMESPACECAPACITYINFO_STATS.nested_types_by_name["Summary"] +) +_CAPACITY_REQUEST_STATE = _CAPACITY_REQUEST.enum_types_by_name["State"] _NAMESPACESPEC_SEARCHATTRIBUTETYPE = _NAMESPACESPEC.enum_types_by_name[ "SearchAttributeType" ] @@ -98,6 +120,17 @@ ) _sym_db.RegisterMessage(ApiKeyAuthSpec) +LifecycleSpec = _reflection.GeneratedProtocolMessageType( + "LifecycleSpec", + (_message.Message,), + { + "DESCRIPTOR": _LIFECYCLESPEC, + "__module__": "temporalio.api.cloud.namespace.v1.message_pb2", + # @@protoc_insertion_point(class_scope:temporal.api.cloud.namespace.v1.LifecycleSpec) + }, +) +_sym_db.RegisterMessage(LifecycleSpec) + CodecServerSpec = _reflection.GeneratedProtocolMessageType( "CodecServerSpec", (_message.Message,), @@ -129,27 +162,88 @@ _sym_db.RegisterMessage(CodecServerSpec.CustomErrorMessage) _sym_db.RegisterMessage(CodecServerSpec.CustomErrorMessage.ErrorMessage) -LifecycleSpec = _reflection.GeneratedProtocolMessageType( - "LifecycleSpec", +HighAvailabilitySpec = _reflection.GeneratedProtocolMessageType( + "HighAvailabilitySpec", (_message.Message,), { - "DESCRIPTOR": _LIFECYCLESPEC, + "DESCRIPTOR": _HIGHAVAILABILITYSPEC, "__module__": "temporalio.api.cloud.namespace.v1.message_pb2", - # @@protoc_insertion_point(class_scope:temporal.api.cloud.namespace.v1.LifecycleSpec) + # @@protoc_insertion_point(class_scope:temporal.api.cloud.namespace.v1.HighAvailabilitySpec) }, ) -_sym_db.RegisterMessage(LifecycleSpec) +_sym_db.RegisterMessage(HighAvailabilitySpec) -HighAvailabilitySpec = _reflection.GeneratedProtocolMessageType( - "HighAvailabilitySpec", +CapacitySpec = _reflection.GeneratedProtocolMessageType( + "CapacitySpec", (_message.Message,), { - "DESCRIPTOR": _HIGHAVAILABILITYSPEC, + "OnDemand": _reflection.GeneratedProtocolMessageType( + "OnDemand", + (_message.Message,), + { + "DESCRIPTOR": _CAPACITYSPEC_ONDEMAND, + "__module__": "temporalio.api.cloud.namespace.v1.message_pb2", + # @@protoc_insertion_point(class_scope:temporal.api.cloud.namespace.v1.CapacitySpec.OnDemand) + }, + ), + "Provisioned": _reflection.GeneratedProtocolMessageType( + "Provisioned", + (_message.Message,), + { + "DESCRIPTOR": _CAPACITYSPEC_PROVISIONED, + "__module__": "temporalio.api.cloud.namespace.v1.message_pb2", + # @@protoc_insertion_point(class_scope:temporal.api.cloud.namespace.v1.CapacitySpec.Provisioned) + }, + ), + "DESCRIPTOR": _CAPACITYSPEC, "__module__": "temporalio.api.cloud.namespace.v1.message_pb2", - # @@protoc_insertion_point(class_scope:temporal.api.cloud.namespace.v1.HighAvailabilitySpec) + # @@protoc_insertion_point(class_scope:temporal.api.cloud.namespace.v1.CapacitySpec) }, ) -_sym_db.RegisterMessage(HighAvailabilitySpec) +_sym_db.RegisterMessage(CapacitySpec) +_sym_db.RegisterMessage(CapacitySpec.OnDemand) +_sym_db.RegisterMessage(CapacitySpec.Provisioned) + +Capacity = _reflection.GeneratedProtocolMessageType( + "Capacity", + (_message.Message,), + { + "OnDemand": _reflection.GeneratedProtocolMessageType( + "OnDemand", + (_message.Message,), + { + "DESCRIPTOR": _CAPACITY_ONDEMAND, + "__module__": "temporalio.api.cloud.namespace.v1.message_pb2", + # @@protoc_insertion_point(class_scope:temporal.api.cloud.namespace.v1.Capacity.OnDemand) + }, + ), + "Provisioned": _reflection.GeneratedProtocolMessageType( + "Provisioned", + (_message.Message,), + { + "DESCRIPTOR": _CAPACITY_PROVISIONED, + "__module__": "temporalio.api.cloud.namespace.v1.message_pb2", + # @@protoc_insertion_point(class_scope:temporal.api.cloud.namespace.v1.Capacity.Provisioned) + }, + ), + "Request": _reflection.GeneratedProtocolMessageType( + "Request", + (_message.Message,), + { + "DESCRIPTOR": _CAPACITY_REQUEST, + "__module__": "temporalio.api.cloud.namespace.v1.message_pb2", + # @@protoc_insertion_point(class_scope:temporal.api.cloud.namespace.v1.Capacity.Request) + }, + ), + "DESCRIPTOR": _CAPACITY, + "__module__": "temporalio.api.cloud.namespace.v1.message_pb2", + # @@protoc_insertion_point(class_scope:temporal.api.cloud.namespace.v1.Capacity) + }, +) +_sym_db.RegisterMessage(Capacity) +_sym_db.RegisterMessage(Capacity.OnDemand) +_sym_db.RegisterMessage(Capacity.Provisioned) +_sym_db.RegisterMessage(Capacity.Request) NamespaceSpec = _reflection.GeneratedProtocolMessageType( "NamespaceSpec", @@ -290,9 +384,74 @@ ) _sym_db.RegisterMessage(ExportSink) +NamespaceCapacityInfo = _reflection.GeneratedProtocolMessageType( + "NamespaceCapacityInfo", + (_message.Message,), + { + "CapacityModeOptions": _reflection.GeneratedProtocolMessageType( + "CapacityModeOptions", + (_message.Message,), + { + "Provisioned": _reflection.GeneratedProtocolMessageType( + "Provisioned", + (_message.Message,), + { + "DESCRIPTOR": _NAMESPACECAPACITYINFO_CAPACITYMODEOPTIONS_PROVISIONED, + "__module__": "temporalio.api.cloud.namespace.v1.message_pb2", + # @@protoc_insertion_point(class_scope:temporal.api.cloud.namespace.v1.NamespaceCapacityInfo.CapacityModeOptions.Provisioned) + }, + ), + "OnDemand": _reflection.GeneratedProtocolMessageType( + "OnDemand", + (_message.Message,), + { + "DESCRIPTOR": _NAMESPACECAPACITYINFO_CAPACITYMODEOPTIONS_ONDEMAND, + "__module__": "temporalio.api.cloud.namespace.v1.message_pb2", + # @@protoc_insertion_point(class_scope:temporal.api.cloud.namespace.v1.NamespaceCapacityInfo.CapacityModeOptions.OnDemand) + }, + ), + "DESCRIPTOR": _NAMESPACECAPACITYINFO_CAPACITYMODEOPTIONS, + "__module__": "temporalio.api.cloud.namespace.v1.message_pb2", + # @@protoc_insertion_point(class_scope:temporal.api.cloud.namespace.v1.NamespaceCapacityInfo.CapacityModeOptions) + }, + ), + "Stats": _reflection.GeneratedProtocolMessageType( + "Stats", + (_message.Message,), + { + "Summary": _reflection.GeneratedProtocolMessageType( + "Summary", + (_message.Message,), + { + "DESCRIPTOR": _NAMESPACECAPACITYINFO_STATS_SUMMARY, + "__module__": "temporalio.api.cloud.namespace.v1.message_pb2", + # @@protoc_insertion_point(class_scope:temporal.api.cloud.namespace.v1.NamespaceCapacityInfo.Stats.Summary) + }, + ), + "DESCRIPTOR": _NAMESPACECAPACITYINFO_STATS, + "__module__": "temporalio.api.cloud.namespace.v1.message_pb2", + # @@protoc_insertion_point(class_scope:temporal.api.cloud.namespace.v1.NamespaceCapacityInfo.Stats) + }, + ), + "DESCRIPTOR": _NAMESPACECAPACITYINFO, + "__module__": "temporalio.api.cloud.namespace.v1.message_pb2", + # @@protoc_insertion_point(class_scope:temporal.api.cloud.namespace.v1.NamespaceCapacityInfo) + }, +) +_sym_db.RegisterMessage(NamespaceCapacityInfo) +_sym_db.RegisterMessage(NamespaceCapacityInfo.CapacityModeOptions) +_sym_db.RegisterMessage(NamespaceCapacityInfo.CapacityModeOptions.Provisioned) +_sym_db.RegisterMessage(NamespaceCapacityInfo.CapacityModeOptions.OnDemand) +_sym_db.RegisterMessage(NamespaceCapacityInfo.Stats) +_sym_db.RegisterMessage(NamespaceCapacityInfo.Stats.Summary) + if _descriptor._USE_C_DESCRIPTORS == False: DESCRIPTOR._options = None DESCRIPTOR._serialized_options = b'\n"io.temporal.api.cloud.namespace.v1B\014MessageProtoP\001Z/go.temporal.io/api/cloud/namespace/v1;namespace\252\002!Temporalio.Api.Cloud.Namespace.V1\352\002%Temporalio::Api::Cloud::Namespace::V1' + _MTLSAUTHSPEC.fields_by_name["accepted_client_ca_deprecated"]._options = None + _MTLSAUTHSPEC.fields_by_name[ + "accepted_client_ca_deprecated" + ]._serialized_options = b"\030\001" _NAMESPACESPEC_CUSTOMSEARCHATTRIBUTESENTRY._options = None _NAMESPACESPEC_CUSTOMSEARCHATTRIBUTESENTRY._serialized_options = b"8\001" _NAMESPACESPEC_SEARCHATTRIBUTESENTRY._options = None @@ -314,49 +473,77 @@ _CERTIFICATEFILTERSPEC._serialized_start = 258 _CERTIFICATEFILTERSPEC._serialized_end = 387 _MTLSAUTHSPEC._serialized_start = 390 - _MTLSAUTHSPEC._serialized_end = 573 - _APIKEYAUTHSPEC._serialized_start = 575 - _APIKEYAUTHSPEC._serialized_end = 608 - _CODECSERVERSPEC._serialized_start = 611 - _CODECSERVERSPEC._serialized_end = 983 - _CODECSERVERSPEC_CUSTOMERRORMESSAGE._serialized_start = 817 - _CODECSERVERSPEC_CUSTOMERRORMESSAGE._serialized_end = 983 - _CODECSERVERSPEC_CUSTOMERRORMESSAGE_ERRORMESSAGE._serialized_start = 938 - _CODECSERVERSPEC_CUSTOMERRORMESSAGE_ERRORMESSAGE._serialized_end = 983 - _LIFECYCLESPEC._serialized_start = 985 - _LIFECYCLESPEC._serialized_end = 1034 - _HIGHAVAILABILITYSPEC._serialized_start = 1036 - _HIGHAVAILABILITYSPEC._serialized_end = 1092 - _NAMESPACESPEC._serialized_start = 1095 - _NAMESPACESPEC._serialized_end = 2256 - _NAMESPACESPEC_CUSTOMSEARCHATTRIBUTESENTRY._serialized_start = 1767 - _NAMESPACESPEC_CUSTOMSEARCHATTRIBUTESENTRY._serialized_end = 1828 - _NAMESPACESPEC_SEARCHATTRIBUTESENTRY._serialized_start = 1830 - _NAMESPACESPEC_SEARCHATTRIBUTESENTRY._serialized_end = 1953 - _NAMESPACESPEC_SEARCHATTRIBUTETYPE._serialized_start = 1956 - _NAMESPACESPEC_SEARCHATTRIBUTETYPE._serialized_end = 2256 - _ENDPOINTS._serialized_start = 2258 - _ENDPOINTS._serialized_end = 2339 - _LIMITS._serialized_start = 2341 - _LIMITS._serialized_end = 2383 - _AWSPRIVATELINKINFO._serialized_start = 2385 - _AWSPRIVATELINKINFO._serialized_end = 2473 - _PRIVATECONNECTIVITY._serialized_start = 2475 - _PRIVATECONNECTIVITY._serialized_end = 2591 - _NAMESPACE._serialized_start = 2594 - _NAMESPACE._serialized_end = 3560 - _NAMESPACE_REGIONSTATUSENTRY._serialized_start = 3408 - _NAMESPACE_REGIONSTATUSENTRY._serialized_end = 3515 - _NAMESPACE_TAGSENTRY._serialized_start = 3517 - _NAMESPACE_TAGSENTRY._serialized_end = 3560 - _NAMESPACEREGIONSTATUS._serialized_start = 3563 - _NAMESPACEREGIONSTATUS._serialized_end = 3846 - _NAMESPACEREGIONSTATUS_STATE._serialized_start = 3723 - _NAMESPACEREGIONSTATUS_STATE._serialized_end = 3846 - _EXPORTSINKSPEC._serialized_start = 3849 - _EXPORTSINKSPEC._serialized_end = 3994 - _EXPORTSINK._serialized_start = 3997 - _EXPORTSINK._serialized_end = 4499 - _EXPORTSINK_HEALTH._serialized_start = 4388 - _EXPORTSINK_HEALTH._serialized_end = 4499 + _MTLSAUTHSPEC._serialized_end = 577 + _APIKEYAUTHSPEC._serialized_start = 579 + _APIKEYAUTHSPEC._serialized_end = 612 + _LIFECYCLESPEC._serialized_start = 614 + _LIFECYCLESPEC._serialized_end = 663 + _CODECSERVERSPEC._serialized_start = 666 + _CODECSERVERSPEC._serialized_end = 1038 + _CODECSERVERSPEC_CUSTOMERRORMESSAGE._serialized_start = 872 + _CODECSERVERSPEC_CUSTOMERRORMESSAGE._serialized_end = 1038 + _CODECSERVERSPEC_CUSTOMERRORMESSAGE_ERRORMESSAGE._serialized_start = 993 + _CODECSERVERSPEC_CUSTOMERRORMESSAGE_ERRORMESSAGE._serialized_end = 1038 + _HIGHAVAILABILITYSPEC._serialized_start = 1040 + _HIGHAVAILABILITYSPEC._serialized_end = 1096 + _CAPACITYSPEC._serialized_start = 1099 + _CAPACITYSPEC._serialized_end = 1322 + _CAPACITYSPEC_ONDEMAND._serialized_start = 1274 + _CAPACITYSPEC_ONDEMAND._serialized_end = 1284 + _CAPACITYSPEC_PROVISIONED._serialized_start = 1286 + _CAPACITYSPEC_PROVISIONED._serialized_end = 1314 + _CAPACITY._serialized_start = 1325 + _CAPACITY._serialized_end = 2057 + _CAPACITY_ONDEMAND._serialized_start = 1274 + _CAPACITY_ONDEMAND._serialized_end = 1284 + _CAPACITY_PROVISIONED._serialized_start = 1575 + _CAPACITY_PROVISIONED._serialized_end = 1611 + _CAPACITY_REQUEST._serialized_start = 1614 + _CAPACITY_REQUEST._serialized_end = 2041 + _CAPACITY_REQUEST_STATE._serialized_start = 1881 + _CAPACITY_REQUEST_STATE._serialized_end = 2041 + _NAMESPACESPEC._serialized_start = 2060 + _NAMESPACESPEC._serialized_end = 3291 + _NAMESPACESPEC_CUSTOMSEARCHATTRIBUTESENTRY._serialized_start = 2802 + _NAMESPACESPEC_CUSTOMSEARCHATTRIBUTESENTRY._serialized_end = 2863 + _NAMESPACESPEC_SEARCHATTRIBUTESENTRY._serialized_start = 2865 + _NAMESPACESPEC_SEARCHATTRIBUTESENTRY._serialized_end = 2988 + _NAMESPACESPEC_SEARCHATTRIBUTETYPE._serialized_start = 2991 + _NAMESPACESPEC_SEARCHATTRIBUTETYPE._serialized_end = 3291 + _ENDPOINTS._serialized_start = 3293 + _ENDPOINTS._serialized_end = 3374 + _LIMITS._serialized_start = 3376 + _LIMITS._serialized_end = 3418 + _AWSPRIVATELINKINFO._serialized_start = 3420 + _AWSPRIVATELINKINFO._serialized_end = 3508 + _PRIVATECONNECTIVITY._serialized_start = 3510 + _PRIVATECONNECTIVITY._serialized_end = 3626 + _NAMESPACE._serialized_start = 3629 + _NAMESPACE._serialized_end = 4656 + _NAMESPACE_REGIONSTATUSENTRY._serialized_start = 4504 + _NAMESPACE_REGIONSTATUSENTRY._serialized_end = 4611 + _NAMESPACE_TAGSENTRY._serialized_start = 4613 + _NAMESPACE_TAGSENTRY._serialized_end = 4656 + _NAMESPACEREGIONSTATUS._serialized_start = 4659 + _NAMESPACEREGIONSTATUS._serialized_end = 4942 + _NAMESPACEREGIONSTATUS_STATE._serialized_start = 4819 + _NAMESPACEREGIONSTATUS_STATE._serialized_end = 4942 + _EXPORTSINKSPEC._serialized_start = 4945 + _EXPORTSINKSPEC._serialized_end = 5090 + _EXPORTSINK._serialized_start = 5093 + _EXPORTSINK._serialized_end = 5595 + _EXPORTSINK_HEALTH._serialized_start = 5484 + _EXPORTSINK_HEALTH._serialized_end = 5595 + _NAMESPACECAPACITYINFO._serialized_start = 5598 + _NAMESPACECAPACITYINFO._serialized_end = 6397 + _NAMESPACECAPACITYINFO_CAPACITYMODEOPTIONS._serialized_start = 5914 + _NAMESPACECAPACITYINFO_CAPACITYMODEOPTIONS._serialized_end = 6253 + _NAMESPACECAPACITYINFO_CAPACITYMODEOPTIONS_PROVISIONED._serialized_start = 6150 + _NAMESPACECAPACITYINFO_CAPACITYMODEOPTIONS_PROVISIONED._serialized_end = 6222 + _NAMESPACECAPACITYINFO_CAPACITYMODEOPTIONS_ONDEMAND._serialized_start = 6224 + _NAMESPACECAPACITYINFO_CAPACITYMODEOPTIONS_ONDEMAND._serialized_end = 6253 + _NAMESPACECAPACITYINFO_STATS._serialized_start = 6256 + _NAMESPACECAPACITYINFO_STATS._serialized_end = 6397 + _NAMESPACECAPACITYINFO_STATS_SUMMARY._serialized_start = 6348 + _NAMESPACECAPACITYINFO_STATS_SUMMARY._serialized_end = 6397 # @@protoc_insertion_point(module_scope) diff --git a/temporalio/api/cloud/namespace/v1/message_pb2.pyi b/temporalio/api/cloud/namespace/v1/message_pb2.pyi index ef666d6e5..147e50616 100644 --- a/temporalio/api/cloud/namespace/v1/message_pb2.pyi +++ b/temporalio/api/cloud/namespace/v1/message_pb2.pyi @@ -151,6 +151,26 @@ class ApiKeyAuthSpec(google.protobuf.message.Message): global___ApiKeyAuthSpec = ApiKeyAuthSpec +class LifecycleSpec(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + ENABLE_DELETE_PROTECTION_FIELD_NUMBER: builtins.int + enable_delete_protection: builtins.bool + """Flag to enable delete protection for the namespace.""" + def __init__( + self, + *, + enable_delete_protection: builtins.bool = ..., + ) -> None: ... + def ClearField( + self, + field_name: typing_extensions.Literal[ + "enable_delete_protection", b"enable_delete_protection" + ], + ) -> None: ... + +global___LifecycleSpec = LifecycleSpec + class CodecServerSpec(google.protobuf.message.Message): DESCRIPTOR: google.protobuf.descriptor.Descriptor @@ -241,45 +261,239 @@ class CodecServerSpec(google.protobuf.message.Message): global___CodecServerSpec = CodecServerSpec -class LifecycleSpec(google.protobuf.message.Message): +class HighAvailabilitySpec(google.protobuf.message.Message): DESCRIPTOR: google.protobuf.descriptor.Descriptor - ENABLE_DELETE_PROTECTION_FIELD_NUMBER: builtins.int - enable_delete_protection: builtins.bool - """Flag to enable delete protection for the namespace.""" + DISABLE_MANAGED_FAILOVER_FIELD_NUMBER: builtins.int + disable_managed_failover: builtins.bool + """Flag to disable managed failover for the namespace.""" def __init__( self, *, - enable_delete_protection: builtins.bool = ..., + disable_managed_failover: builtins.bool = ..., ) -> None: ... def ClearField( self, field_name: typing_extensions.Literal[ - "enable_delete_protection", b"enable_delete_protection" + "disable_managed_failover", b"disable_managed_failover" ], ) -> None: ... -global___LifecycleSpec = LifecycleSpec +global___HighAvailabilitySpec = HighAvailabilitySpec + +class CapacitySpec(google.protobuf.message.Message): + """temporal:versioning:min_version=v0.10.0""" -class HighAvailabilitySpec(google.protobuf.message.Message): DESCRIPTOR: google.protobuf.descriptor.Descriptor - DISABLE_MANAGED_FAILOVER_FIELD_NUMBER: builtins.int - disable_managed_failover: builtins.bool - """Flag to disable managed failover for the namespace.""" + class OnDemand(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + def __init__( + self, + ) -> None: ... + + class Provisioned(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + VALUE_FIELD_NUMBER: builtins.int + value: builtins.float + """The units of provisioned capacity in TRU (Temporal Resource Units). + Each TRU unit assigned to the namespace will entitle it with additional APS limits as specified in the documentation. + """ + def __init__( + self, + *, + value: builtins.float = ..., + ) -> None: ... + def ClearField( + self, field_name: typing_extensions.Literal["value", b"value"] + ) -> None: ... + + ON_DEMAND_FIELD_NUMBER: builtins.int + PROVISIONED_FIELD_NUMBER: builtins.int + @property + def on_demand(self) -> global___CapacitySpec.OnDemand: + """The on-demand capacity mode configuration.""" + @property + def provisioned(self) -> global___CapacitySpec.Provisioned: + """The provisioned capacity mode configuration.""" def __init__( self, *, - disable_managed_failover: builtins.bool = ..., + on_demand: global___CapacitySpec.OnDemand | None = ..., + provisioned: global___CapacitySpec.Provisioned | None = ..., ) -> None: ... + def HasField( + self, + field_name: typing_extensions.Literal[ + "on_demand", b"on_demand", "provisioned", b"provisioned", "spec", b"spec" + ], + ) -> builtins.bool: ... def ClearField( self, field_name: typing_extensions.Literal[ - "disable_managed_failover", b"disable_managed_failover" + "on_demand", b"on_demand", "provisioned", b"provisioned", "spec", b"spec" ], ) -> None: ... + def WhichOneof( + self, oneof_group: typing_extensions.Literal["spec", b"spec"] + ) -> typing_extensions.Literal["on_demand", "provisioned"] | None: ... -global___HighAvailabilitySpec = HighAvailabilitySpec +global___CapacitySpec = CapacitySpec + +class Capacity(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + class OnDemand(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + def __init__( + self, + ) -> None: ... + + class Provisioned(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + CURRENT_VALUE_FIELD_NUMBER: builtins.int + current_value: builtins.float + """The current provisioned capacity for the namespace in Temporal Resource Units. + Can be different from the requested capacity in latest_request if the request is still in progress. + """ + def __init__( + self, + *, + current_value: builtins.float = ..., + ) -> None: ... + def ClearField( + self, + field_name: typing_extensions.Literal["current_value", b"current_value"], + ) -> None: ... + + class Request(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + class _State: + ValueType = typing.NewType("ValueType", builtins.int) + V: typing_extensions.TypeAlias = ValueType + + class _StateEnumTypeWrapper( + google.protobuf.internal.enum_type_wrapper._EnumTypeWrapper[ + Capacity.Request._State.ValueType + ], + builtins.type, + ): # noqa: F821 + DESCRIPTOR: google.protobuf.descriptor.EnumDescriptor + STATE_CAPACITY_REQUEST_UNSPECIFIED: Capacity.Request._State.ValueType # 0 + STATE_CAPACITY_REQUEST_COMPLETED: Capacity.Request._State.ValueType # 1 + STATE_CAPACITY_REQUEST_IN_PROGRESS: Capacity.Request._State.ValueType # 2 + STATE_CAPACITY_REQUEST_FAILED: Capacity.Request._State.ValueType # 3 + + class State(_State, metaclass=_StateEnumTypeWrapper): ... + STATE_CAPACITY_REQUEST_UNSPECIFIED: Capacity.Request.State.ValueType # 0 + STATE_CAPACITY_REQUEST_COMPLETED: Capacity.Request.State.ValueType # 1 + STATE_CAPACITY_REQUEST_IN_PROGRESS: Capacity.Request.State.ValueType # 2 + STATE_CAPACITY_REQUEST_FAILED: Capacity.Request.State.ValueType # 3 + + STATE_FIELD_NUMBER: builtins.int + START_TIME_FIELD_NUMBER: builtins.int + END_TIME_FIELD_NUMBER: builtins.int + ASYNC_OPERATION_ID_FIELD_NUMBER: builtins.int + SPEC_FIELD_NUMBER: builtins.int + state: global___Capacity.Request.State.ValueType + """The current state of the capacity request (e.g. in-progress, completed, failed).""" + @property + def start_time(self) -> google.protobuf.timestamp_pb2.Timestamp: + """The date and time when the capacity request was created.""" + @property + def end_time(self) -> google.protobuf.timestamp_pb2.Timestamp: + """The date and time when the capacity request was completed or failed.""" + async_operation_id: builtins.str + """The id of the async operation that is creating/updating/deleting the capacity, if any.""" + @property + def spec(self) -> global___CapacitySpec: + """The requested capacity specification.""" + def __init__( + self, + *, + state: global___Capacity.Request.State.ValueType = ..., + start_time: google.protobuf.timestamp_pb2.Timestamp | None = ..., + end_time: google.protobuf.timestamp_pb2.Timestamp | None = ..., + async_operation_id: builtins.str = ..., + spec: global___CapacitySpec | None = ..., + ) -> None: ... + def HasField( + self, + field_name: typing_extensions.Literal[ + "end_time", b"end_time", "spec", b"spec", "start_time", b"start_time" + ], + ) -> builtins.bool: ... + def ClearField( + self, + field_name: typing_extensions.Literal[ + "async_operation_id", + b"async_operation_id", + "end_time", + b"end_time", + "spec", + b"spec", + "start_time", + b"start_time", + "state", + b"state", + ], + ) -> None: ... + + ON_DEMAND_FIELD_NUMBER: builtins.int + PROVISIONED_FIELD_NUMBER: builtins.int + LATEST_REQUEST_FIELD_NUMBER: builtins.int + @property + def on_demand(self) -> global___Capacity.OnDemand: + """The status of on-demand capacity mode.""" + @property + def provisioned(self) -> global___Capacity.Provisioned: + """The status of provisioned capacity mode.""" + @property + def latest_request(self) -> global___Capacity.Request: + """The latest requested capacity for the namespace, if any.""" + def __init__( + self, + *, + on_demand: global___Capacity.OnDemand | None = ..., + provisioned: global___Capacity.Provisioned | None = ..., + latest_request: global___Capacity.Request | None = ..., + ) -> None: ... + def HasField( + self, + field_name: typing_extensions.Literal[ + "current_mode", + b"current_mode", + "latest_request", + b"latest_request", + "on_demand", + b"on_demand", + "provisioned", + b"provisioned", + ], + ) -> builtins.bool: ... + def ClearField( + self, + field_name: typing_extensions.Literal[ + "current_mode", + b"current_mode", + "latest_request", + b"latest_request", + "on_demand", + b"on_demand", + "provisioned", + b"provisioned", + ], + ) -> None: ... + def WhichOneof( + self, oneof_group: typing_extensions.Literal["current_mode", b"current_mode"] + ) -> typing_extensions.Literal["on_demand", "provisioned"] | None: ... + +global___Capacity = Capacity class NamespaceSpec(google.protobuf.message.Message): DESCRIPTOR: google.protobuf.descriptor.Descriptor @@ -369,6 +583,7 @@ class NamespaceSpec(google.protobuf.message.Message): LIFECYCLE_FIELD_NUMBER: builtins.int HIGH_AVAILABILITY_FIELD_NUMBER: builtins.int CONNECTIVITY_RULE_IDS_FIELD_NUMBER: builtins.int + CAPACITY_SPEC_FIELD_NUMBER: builtins.int name: builtins.str """The name to use for the namespace. This will create a namespace that's available at '..tmprl.cloud:7233'. @@ -451,6 +666,15 @@ class NamespaceSpec(google.protobuf.message.Message): This will apply the connectivity rules specified to the namespace. temporal:versioning:min_version=v0.6.0 """ + @property + def capacity_spec(self) -> global___CapacitySpec: + """The capacity configuration for the namespace. + There are two capacity modes: on-demand and provisioned. + On-demand capacity mode allows the namespace to scale automatically based on usage. + Provisioned capacity mode allows the user to specify a fixed amount of capacity (in TRUs) for the namespace. + Can be changed only when the last capacity request is not in progress. + temporal:versioning:min_version=v0.10.0 + """ def __init__( self, *, @@ -469,12 +693,15 @@ class NamespaceSpec(google.protobuf.message.Message): lifecycle: global___LifecycleSpec | None = ..., high_availability: global___HighAvailabilitySpec | None = ..., connectivity_rule_ids: collections.abc.Iterable[builtins.str] | None = ..., + capacity_spec: global___CapacitySpec | None = ..., ) -> None: ... def HasField( self, field_name: typing_extensions.Literal[ "api_key_auth", b"api_key_auth", + "capacity_spec", + b"capacity_spec", "codec_server", b"codec_server", "high_availability", @@ -490,6 +717,8 @@ class NamespaceSpec(google.protobuf.message.Message): field_name: typing_extensions.Literal[ "api_key_auth", b"api_key_auth", + "capacity_spec", + b"capacity_spec", "codec_server", b"codec_server", "connectivity_rule_ids", @@ -692,6 +921,7 @@ class Namespace(google.protobuf.message.Message): REGION_STATUS_FIELD_NUMBER: builtins.int CONNECTIVITY_RULES_FIELD_NUMBER: builtins.int TAGS_FIELD_NUMBER: builtins.int + CAPACITY_FIELD_NUMBER: builtins.int namespace: builtins.str """The namespace identifier.""" resource_version: builtins.str @@ -758,6 +988,9 @@ class Namespace(google.protobuf.message.Message): self, ) -> google.protobuf.internal.containers.ScalarMap[builtins.str, builtins.str]: """The tags for the namespace.""" + @property + def capacity(self) -> global___Capacity: + """The status of namespace's capacity, if any.""" def __init__( self, *, @@ -783,10 +1016,13 @@ class Namespace(google.protobuf.message.Message): ] | None = ..., tags: collections.abc.Mapping[builtins.str, builtins.str] | None = ..., + capacity: global___Capacity | None = ..., ) -> None: ... def HasField( self, field_name: typing_extensions.Literal[ + "capacity", + b"capacity", "created_time", b"created_time", "endpoints", @@ -806,6 +1042,8 @@ class Namespace(google.protobuf.message.Message): b"active_region", "async_operation_id", b"async_operation_id", + "capacity", + b"capacity", "connectivity_rules", b"connectivity_rules", "created_time", @@ -930,7 +1168,9 @@ class ExportSinkSpec(google.protobuf.message.Message): """The S3 configuration details when destination_type is S3.""" @property def gcs(self) -> temporalio.api.cloud.sink.v1.message_pb2.GCSSpec: - """The GCS configuration details when destination_type is GCS.""" + """This is a feature under development. We will allow GCS sink support for GCP Namespaces. + The GCS configuration details when destination_type is GCS. + """ def __init__( self, *, @@ -985,7 +1225,7 @@ class ExportSink(google.protobuf.message.Message): LATEST_DATA_EXPORT_TIME_FIELD_NUMBER: builtins.int LAST_HEALTH_CHECK_TIME_FIELD_NUMBER: builtins.int name: builtins.str - """The unique name of the export sink.""" + """The unique name of the export sink, once set it can't be changed""" resource_version: builtins.str """The version of the export sink resource.""" state: temporalio.api.cloud.resource.v1.message_pb2.ResourceState.ValueType @@ -1049,3 +1289,202 @@ class ExportSink(google.protobuf.message.Message): ) -> None: ... global___ExportSink = ExportSink + +class NamespaceCapacityInfo(google.protobuf.message.Message): + """NamespaceCapacityInfo contains detailed capacity information for a namespace.""" + + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + class CapacityModeOptions(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + class Provisioned(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + VALID_TRU_VALUES_FIELD_NUMBER: builtins.int + MAX_AVAILABLE_TRU_VALUE_FIELD_NUMBER: builtins.int + @property + def valid_tru_values( + self, + ) -> google.protobuf.internal.containers.RepeatedScalarFieldContainer[ + builtins.float + ]: + """The valid TRU (Temporal Resource Unit) values that can be set. + These are the discrete capacity tiers available for selection. + """ + max_available_tru_value: builtins.float + """The maximum TRU value that can currently be set for this namespace. + This may be lower than the highest value in valid_tru_values due to + inventory constraints. + """ + def __init__( + self, + *, + valid_tru_values: collections.abc.Iterable[builtins.float] | None = ..., + max_available_tru_value: builtins.float = ..., + ) -> None: ... + def ClearField( + self, + field_name: typing_extensions.Literal[ + "max_available_tru_value", + b"max_available_tru_value", + "valid_tru_values", + b"valid_tru_values", + ], + ) -> None: ... + + class OnDemand(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + APS_LIMIT_FIELD_NUMBER: builtins.int + aps_limit: builtins.float + """The APS limit that would apply to this namespace in on-demand mode. + See: https://docs.temporal.io/cloud/limits#actions-per-second + """ + def __init__( + self, + *, + aps_limit: builtins.float = ..., + ) -> None: ... + def ClearField( + self, field_name: typing_extensions.Literal["aps_limit", b"aps_limit"] + ) -> None: ... + + PROVISIONED_FIELD_NUMBER: builtins.int + ON_DEMAND_FIELD_NUMBER: builtins.int + @property + def provisioned( + self, + ) -> global___NamespaceCapacityInfo.CapacityModeOptions.Provisioned: + """Provisioned capacity options and entitlements.""" + @property + def on_demand( + self, + ) -> global___NamespaceCapacityInfo.CapacityModeOptions.OnDemand: + """On-Demand capacity information.""" + def __init__( + self, + *, + provisioned: global___NamespaceCapacityInfo.CapacityModeOptions.Provisioned + | None = ..., + on_demand: global___NamespaceCapacityInfo.CapacityModeOptions.OnDemand + | None = ..., + ) -> None: ... + def HasField( + self, + field_name: typing_extensions.Literal[ + "on_demand", b"on_demand", "provisioned", b"provisioned" + ], + ) -> builtins.bool: ... + def ClearField( + self, + field_name: typing_extensions.Literal[ + "on_demand", b"on_demand", "provisioned", b"provisioned" + ], + ) -> None: ... + + class Stats(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + class Summary(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + MEAN_FIELD_NUMBER: builtins.int + P90_FIELD_NUMBER: builtins.int + P99_FIELD_NUMBER: builtins.int + mean: builtins.float + p90: builtins.float + p99: builtins.float + def __init__( + self, + *, + mean: builtins.float = ..., + p90: builtins.float = ..., + p99: builtins.float = ..., + ) -> None: ... + def ClearField( + self, + field_name: typing_extensions.Literal[ + "mean", b"mean", "p90", b"p90", "p99", b"p99" + ], + ) -> None: ... + + APS_FIELD_NUMBER: builtins.int + @property + def aps(self) -> global___NamespaceCapacityInfo.Stats.Summary: + """Actions-per-second measurements summarized over the last 7 days.""" + def __init__( + self, + *, + aps: global___NamespaceCapacityInfo.Stats.Summary | None = ..., + ) -> None: ... + def HasField( + self, field_name: typing_extensions.Literal["aps", b"aps"] + ) -> builtins.bool: ... + def ClearField( + self, field_name: typing_extensions.Literal["aps", b"aps"] + ) -> None: ... + + NAMESPACE_FIELD_NUMBER: builtins.int + HAS_LEGACY_LIMITS_FIELD_NUMBER: builtins.int + CURRENT_CAPACITY_FIELD_NUMBER: builtins.int + MODE_OPTIONS_FIELD_NUMBER: builtins.int + STATS_FIELD_NUMBER: builtins.int + namespace: builtins.str + """The namespace identifier.""" + has_legacy_limits: builtins.bool + """Whether the namespace's APS limit was set by Temporal Support. + When true, adjusting the namespace's capacity will reset this limit. + """ + @property + def current_capacity(self) -> global___Capacity: + """The current capacity of the namespace. + Includes the current mode (on-demand or provisioned) and latest request status. + """ + @property + def mode_options(self) -> global___NamespaceCapacityInfo.CapacityModeOptions: + """Available capacity mode options for this namespace. + Contains configuration limits for both provisioned and on-demand modes. + """ + @property + def stats(self) -> global___NamespaceCapacityInfo.Stats: + """Usage statistics for the namespace over the last 7 days. + Used to calculate On-Demand capacity limits, also useful for capacity planning. + """ + def __init__( + self, + *, + namespace: builtins.str = ..., + has_legacy_limits: builtins.bool = ..., + current_capacity: global___Capacity | None = ..., + mode_options: global___NamespaceCapacityInfo.CapacityModeOptions | None = ..., + stats: global___NamespaceCapacityInfo.Stats | None = ..., + ) -> None: ... + def HasField( + self, + field_name: typing_extensions.Literal[ + "current_capacity", + b"current_capacity", + "mode_options", + b"mode_options", + "stats", + b"stats", + ], + ) -> builtins.bool: ... + def ClearField( + self, + field_name: typing_extensions.Literal[ + "current_capacity", + b"current_capacity", + "has_legacy_limits", + b"has_legacy_limits", + "mode_options", + b"mode_options", + "namespace", + b"namespace", + "stats", + b"stats", + ], + ) -> None: ... + +global___NamespaceCapacityInfo = NamespaceCapacityInfo diff --git a/temporalio/api/dependencies/__init__.py b/temporalio/api/dependencies/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/temporalio/api/dependencies/protoc_gen_openapiv2/__init__.py b/temporalio/api/dependencies/protoc_gen_openapiv2/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/temporalio/api/dependencies/protoc_gen_openapiv2/options/__init__.py b/temporalio/api/dependencies/protoc_gen_openapiv2/options/__init__.py new file mode 100644 index 000000000..f828cbf23 --- /dev/null +++ b/temporalio/api/dependencies/protoc_gen_openapiv2/options/__init__.py @@ -0,0 +1,43 @@ +from .openapiv2_pb2 import ( + Contact, + EnumSchema, + ExternalDocumentation, + Header, + HeaderParameter, + Info, + JSONSchema, + License, + Operation, + Parameters, + Response, + Schema, + Scheme, + Scopes, + SecurityDefinitions, + SecurityRequirement, + SecurityScheme, + Swagger, + Tag, +) + +__all__ = [ + "Contact", + "EnumSchema", + "ExternalDocumentation", + "Header", + "HeaderParameter", + "Info", + "JSONSchema", + "License", + "Operation", + "Parameters", + "Response", + "Schema", + "Scheme", + "Scopes", + "SecurityDefinitions", + "SecurityRequirement", + "SecurityScheme", + "Swagger", + "Tag", +] diff --git a/temporalio/api/dependencies/protoc_gen_openapiv2/options/annotations_pb2.py b/temporalio/api/dependencies/protoc_gen_openapiv2/options/annotations_pb2.py new file mode 100644 index 000000000..3d0ab9f2e --- /dev/null +++ b/temporalio/api/dependencies/protoc_gen_openapiv2/options/annotations_pb2.py @@ -0,0 +1,65 @@ +# -*- coding: utf-8 -*- +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: protoc-gen-openapiv2/options/annotations.proto +"""Generated protocol buffer code.""" + +from google.protobuf import descriptor as _descriptor +from google.protobuf import descriptor_pool as _descriptor_pool +from google.protobuf import message as _message +from google.protobuf import reflection as _reflection +from google.protobuf import symbol_database as _symbol_database + +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + +from google.protobuf import descriptor_pb2 as google_dot_protobuf_dot_descriptor__pb2 + +from temporalio.api.dependencies.protoc_gen_openapiv2.options import ( + openapiv2_pb2 as protoc__gen__openapiv2_dot_options_dot_openapiv2__pb2, +) + +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile( + b"\n.protoc-gen-openapiv2/options/annotations.proto\x12)grpc.gateway.protoc_gen_openapiv2.options\x1a google/protobuf/descriptor.proto\x1a,protoc-gen-openapiv2/options/openapiv2.proto:l\n\x11openapiv2_swagger\x12\x1c.google.protobuf.FileOptions\x18\x92\x08 \x01(\x0b\x32\x32.grpc.gateway.protoc_gen_openapiv2.options.Swagger:r\n\x13openapiv2_operation\x12\x1e.google.protobuf.MethodOptions\x18\x92\x08 \x01(\x0b\x32\x34.grpc.gateway.protoc_gen_openapiv2.options.Operation:m\n\x10openapiv2_schema\x12\x1f.google.protobuf.MessageOptions\x18\x92\x08 \x01(\x0b\x32\x31.grpc.gateway.protoc_gen_openapiv2.options.Schema:l\n\x0eopenapiv2_enum\x12\x1c.google.protobuf.EnumOptions\x18\x92\x08 \x01(\x0b\x32\x35.grpc.gateway.protoc_gen_openapiv2.options.EnumSchema:g\n\ropenapiv2_tag\x12\x1f.google.protobuf.ServiceOptions\x18\x92\x08 \x01(\x0b\x32..grpc.gateway.protoc_gen_openapiv2.options.Tag:n\n\x0fopenapiv2_field\x12\x1d.google.protobuf.FieldOptions\x18\x92\x08 \x01(\x0b\x32\x35.grpc.gateway.protoc_gen_openapiv2.options.JSONSchemaBHZFgithub.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2/optionsb\x06proto3" +) + + +OPENAPIV2_SWAGGER_FIELD_NUMBER = 1042 +openapiv2_swagger = DESCRIPTOR.extensions_by_name["openapiv2_swagger"] +OPENAPIV2_OPERATION_FIELD_NUMBER = 1042 +openapiv2_operation = DESCRIPTOR.extensions_by_name["openapiv2_operation"] +OPENAPIV2_SCHEMA_FIELD_NUMBER = 1042 +openapiv2_schema = DESCRIPTOR.extensions_by_name["openapiv2_schema"] +OPENAPIV2_ENUM_FIELD_NUMBER = 1042 +openapiv2_enum = DESCRIPTOR.extensions_by_name["openapiv2_enum"] +OPENAPIV2_TAG_FIELD_NUMBER = 1042 +openapiv2_tag = DESCRIPTOR.extensions_by_name["openapiv2_tag"] +OPENAPIV2_FIELD_FIELD_NUMBER = 1042 +openapiv2_field = DESCRIPTOR.extensions_by_name["openapiv2_field"] + +if _descriptor._USE_C_DESCRIPTORS == False: + google_dot_protobuf_dot_descriptor__pb2.FileOptions.RegisterExtension( + openapiv2_swagger + ) + google_dot_protobuf_dot_descriptor__pb2.MethodOptions.RegisterExtension( + openapiv2_operation + ) + google_dot_protobuf_dot_descriptor__pb2.MessageOptions.RegisterExtension( + openapiv2_schema + ) + google_dot_protobuf_dot_descriptor__pb2.EnumOptions.RegisterExtension( + openapiv2_enum + ) + google_dot_protobuf_dot_descriptor__pb2.ServiceOptions.RegisterExtension( + openapiv2_tag + ) + google_dot_protobuf_dot_descriptor__pb2.FieldOptions.RegisterExtension( + openapiv2_field + ) + + DESCRIPTOR._options = None + DESCRIPTOR._serialized_options = ( + b"ZFgithub.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2/options" + ) +# @@protoc_insertion_point(module_scope) diff --git a/temporalio/api/dependencies/protoc_gen_openapiv2/options/annotations_pb2.pyi b/temporalio/api/dependencies/protoc_gen_openapiv2/options/annotations_pb2.pyi new file mode 100644 index 000000000..1d2f3de31 --- /dev/null +++ b/temporalio/api/dependencies/protoc_gen_openapiv2/options/annotations_pb2.pyi @@ -0,0 +1,75 @@ +""" +@generated by mypy-protobuf. Do not edit manually! +isort:skip_file +""" + +import builtins + +import google.protobuf.descriptor +import google.protobuf.descriptor_pb2 +import google.protobuf.internal.extension_dict + +import temporalio.api.dependencies.protoc_gen_openapiv2.options.openapiv2_pb2 + +DESCRIPTOR: google.protobuf.descriptor.FileDescriptor + +OPENAPIV2_SWAGGER_FIELD_NUMBER: builtins.int +OPENAPIV2_OPERATION_FIELD_NUMBER: builtins.int +OPENAPIV2_SCHEMA_FIELD_NUMBER: builtins.int +OPENAPIV2_ENUM_FIELD_NUMBER: builtins.int +OPENAPIV2_TAG_FIELD_NUMBER: builtins.int +OPENAPIV2_FIELD_FIELD_NUMBER: builtins.int +openapiv2_swagger: google.protobuf.internal.extension_dict._ExtensionFieldDescriptor[ + google.protobuf.descriptor_pb2.FileOptions, + temporalio.api.dependencies.protoc_gen_openapiv2.options.openapiv2_pb2.Swagger, +] +"""ID assigned by protobuf-global-extension-registry@google.com for gRPC-Gateway project. + +All IDs are the same, as assigned. It is okay that they are the same, as they extend +different descriptor messages. +""" +openapiv2_operation: google.protobuf.internal.extension_dict._ExtensionFieldDescriptor[ + google.protobuf.descriptor_pb2.MethodOptions, + temporalio.api.dependencies.protoc_gen_openapiv2.options.openapiv2_pb2.Operation, +] +"""ID assigned by protobuf-global-extension-registry@google.com for gRPC-Gateway project. + +All IDs are the same, as assigned. It is okay that they are the same, as they extend +different descriptor messages. +""" +openapiv2_schema: google.protobuf.internal.extension_dict._ExtensionFieldDescriptor[ + google.protobuf.descriptor_pb2.MessageOptions, + temporalio.api.dependencies.protoc_gen_openapiv2.options.openapiv2_pb2.Schema, +] +"""ID assigned by protobuf-global-extension-registry@google.com for gRPC-Gateway project. + +All IDs are the same, as assigned. It is okay that they are the same, as they extend +different descriptor messages. +""" +openapiv2_enum: google.protobuf.internal.extension_dict._ExtensionFieldDescriptor[ + google.protobuf.descriptor_pb2.EnumOptions, + temporalio.api.dependencies.protoc_gen_openapiv2.options.openapiv2_pb2.EnumSchema, +] +"""ID assigned by protobuf-global-extension-registry@google.com for gRPC-Gateway project. + +All IDs are the same, as assigned. It is okay that they are the same, as they extend +different descriptor messages. +""" +openapiv2_tag: google.protobuf.internal.extension_dict._ExtensionFieldDescriptor[ + google.protobuf.descriptor_pb2.ServiceOptions, + temporalio.api.dependencies.protoc_gen_openapiv2.options.openapiv2_pb2.Tag, +] +"""ID assigned by protobuf-global-extension-registry@google.com for gRPC-Gateway project. + +All IDs are the same, as assigned. It is okay that they are the same, as they extend +different descriptor messages. +""" +openapiv2_field: google.protobuf.internal.extension_dict._ExtensionFieldDescriptor[ + google.protobuf.descriptor_pb2.FieldOptions, + temporalio.api.dependencies.protoc_gen_openapiv2.options.openapiv2_pb2.JSONSchema, +] +"""ID assigned by protobuf-global-extension-registry@google.com for gRPC-Gateway project. + +All IDs are the same, as assigned. It is okay that they are the same, as they extend +different descriptor messages. +""" diff --git a/temporalio/api/dependencies/protoc_gen_openapiv2/options/openapiv2_pb2.py b/temporalio/api/dependencies/protoc_gen_openapiv2/options/openapiv2_pb2.py new file mode 100644 index 000000000..ea0b8eec5 --- /dev/null +++ b/temporalio/api/dependencies/protoc_gen_openapiv2/options/openapiv2_pb2.py @@ -0,0 +1,568 @@ +# -*- coding: utf-8 -*- +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: protoc-gen-openapiv2/options/openapiv2.proto +"""Generated protocol buffer code.""" + +from google.protobuf import descriptor as _descriptor +from google.protobuf import descriptor_pool as _descriptor_pool +from google.protobuf import message as _message +from google.protobuf import reflection as _reflection +from google.protobuf import symbol_database as _symbol_database +from google.protobuf.internal import enum_type_wrapper + +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + +from google.protobuf import struct_pb2 as google_dot_protobuf_dot_struct__pb2 + +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile( + b'\n,protoc-gen-openapiv2/options/openapiv2.proto\x12)grpc.gateway.protoc_gen_openapiv2.options\x1a\x1cgoogle/protobuf/struct.proto"\x95\x07\n\x07Swagger\x12\x0f\n\x07swagger\x18\x01 \x01(\t\x12=\n\x04info\x18\x02 \x01(\x0b\x32/.grpc.gateway.protoc_gen_openapiv2.options.Info\x12\x0c\n\x04host\x18\x03 \x01(\t\x12\x11\n\tbase_path\x18\x04 \x01(\t\x12\x42\n\x07schemes\x18\x05 \x03(\x0e\x32\x31.grpc.gateway.protoc_gen_openapiv2.options.Scheme\x12\x10\n\x08\x63onsumes\x18\x06 \x03(\t\x12\x10\n\x08produces\x18\x07 \x03(\t\x12T\n\tresponses\x18\n \x03(\x0b\x32\x41.grpc.gateway.protoc_gen_openapiv2.options.Swagger.ResponsesEntry\x12\\\n\x14security_definitions\x18\x0b \x01(\x0b\x32>.grpc.gateway.protoc_gen_openapiv2.options.SecurityDefinitions\x12P\n\x08security\x18\x0c \x03(\x0b\x32>.grpc.gateway.protoc_gen_openapiv2.options.SecurityRequirement\x12<\n\x04tags\x18\r \x03(\x0b\x32..grpc.gateway.protoc_gen_openapiv2.options.Tag\x12W\n\rexternal_docs\x18\x0e \x01(\x0b\x32@.grpc.gateway.protoc_gen_openapiv2.options.ExternalDocumentation\x12V\n\nextensions\x18\x0f \x03(\x0b\x32\x42.grpc.gateway.protoc_gen_openapiv2.options.Swagger.ExtensionsEntry\x1a\x65\n\x0eResponsesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x42\n\x05value\x18\x02 \x01(\x0b\x32\x33.grpc.gateway.protoc_gen_openapiv2.options.Response:\x02\x38\x01\x1aI\n\x0f\x45xtensionsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12%\n\x05value\x18\x02 \x01(\x0b\x32\x16.google.protobuf.Value:\x02\x38\x01J\x04\x08\x08\x10\tJ\x04\x08\t\x10\n"\xb1\x06\n\tOperation\x12\x0c\n\x04tags\x18\x01 \x03(\t\x12\x0f\n\x07summary\x18\x02 \x01(\t\x12\x13\n\x0b\x64\x65scription\x18\x03 \x01(\t\x12W\n\rexternal_docs\x18\x04 \x01(\x0b\x32@.grpc.gateway.protoc_gen_openapiv2.options.ExternalDocumentation\x12\x14\n\x0coperation_id\x18\x05 \x01(\t\x12\x10\n\x08\x63onsumes\x18\x06 \x03(\t\x12\x10\n\x08produces\x18\x07 \x03(\t\x12V\n\tresponses\x18\t \x03(\x0b\x32\x43.grpc.gateway.protoc_gen_openapiv2.options.Operation.ResponsesEntry\x12\x42\n\x07schemes\x18\n \x03(\x0e\x32\x31.grpc.gateway.protoc_gen_openapiv2.options.Scheme\x12\x12\n\ndeprecated\x18\x0b \x01(\x08\x12P\n\x08security\x18\x0c \x03(\x0b\x32>.grpc.gateway.protoc_gen_openapiv2.options.SecurityRequirement\x12X\n\nextensions\x18\r \x03(\x0b\x32\x44.grpc.gateway.protoc_gen_openapiv2.options.Operation.ExtensionsEntry\x12I\n\nparameters\x18\x0e \x01(\x0b\x32\x35.grpc.gateway.protoc_gen_openapiv2.options.Parameters\x1a\x65\n\x0eResponsesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x42\n\x05value\x18\x02 \x01(\x0b\x32\x33.grpc.gateway.protoc_gen_openapiv2.options.Response:\x02\x38\x01\x1aI\n\x0f\x45xtensionsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12%\n\x05value\x18\x02 \x01(\x0b\x32\x16.google.protobuf.Value:\x02\x38\x01J\x04\x08\x08\x10\t"Y\n\nParameters\x12K\n\x07headers\x18\x01 \x03(\x0b\x32:.grpc.gateway.protoc_gen_openapiv2.options.HeaderParameter"\xf8\x01\n\x0fHeaderParameter\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x13\n\x0b\x64\x65scription\x18\x02 \x01(\t\x12M\n\x04type\x18\x03 \x01(\x0e\x32?.grpc.gateway.protoc_gen_openapiv2.options.HeaderParameter.Type\x12\x0e\n\x06\x66ormat\x18\x04 \x01(\t\x12\x10\n\x08required\x18\x05 \x01(\x08"E\n\x04Type\x12\x0b\n\x07UNKNOWN\x10\x00\x12\n\n\x06STRING\x10\x01\x12\n\n\x06NUMBER\x10\x02\x12\x0b\n\x07INTEGER\x10\x03\x12\x0b\n\x07\x42OOLEAN\x10\x04J\x04\x08\x06\x10\x07J\x04\x08\x07\x10\x08"\xab\x01\n\x06Header\x12\x13\n\x0b\x64\x65scription\x18\x01 \x01(\t\x12\x0c\n\x04type\x18\x02 \x01(\t\x12\x0e\n\x06\x66ormat\x18\x03 \x01(\t\x12\x0f\n\x07\x64\x65\x66\x61ult\x18\x06 \x01(\t\x12\x0f\n\x07pattern\x18\r \x01(\tJ\x04\x08\x04\x10\x05J\x04\x08\x05\x10\x06J\x04\x08\x07\x10\x08J\x04\x08\x08\x10\tJ\x04\x08\t\x10\nJ\x04\x08\n\x10\x0bJ\x04\x08\x0b\x10\x0cJ\x04\x08\x0c\x10\rJ\x04\x08\x0e\x10\x0fJ\x04\x08\x0f\x10\x10J\x04\x08\x10\x10\x11J\x04\x08\x11\x10\x12J\x04\x08\x12\x10\x13"\xc2\x04\n\x08Response\x12\x13\n\x0b\x64\x65scription\x18\x01 \x01(\t\x12\x41\n\x06schema\x18\x02 \x01(\x0b\x32\x31.grpc.gateway.protoc_gen_openapiv2.options.Schema\x12Q\n\x07headers\x18\x03 \x03(\x0b\x32@.grpc.gateway.protoc_gen_openapiv2.options.Response.HeadersEntry\x12S\n\x08\x65xamples\x18\x04 \x03(\x0b\x32\x41.grpc.gateway.protoc_gen_openapiv2.options.Response.ExamplesEntry\x12W\n\nextensions\x18\x05 \x03(\x0b\x32\x43.grpc.gateway.protoc_gen_openapiv2.options.Response.ExtensionsEntry\x1a\x61\n\x0cHeadersEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12@\n\x05value\x18\x02 \x01(\x0b\x32\x31.grpc.gateway.protoc_gen_openapiv2.options.Header:\x02\x38\x01\x1a/\n\rExamplesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x1aI\n\x0f\x45xtensionsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12%\n\x05value\x18\x02 \x01(\x0b\x32\x16.google.protobuf.Value:\x02\x38\x01"\xff\x02\n\x04Info\x12\r\n\x05title\x18\x01 \x01(\t\x12\x13\n\x0b\x64\x65scription\x18\x02 \x01(\t\x12\x18\n\x10terms_of_service\x18\x03 \x01(\t\x12\x43\n\x07\x63ontact\x18\x04 \x01(\x0b\x32\x32.grpc.gateway.protoc_gen_openapiv2.options.Contact\x12\x43\n\x07license\x18\x05 \x01(\x0b\x32\x32.grpc.gateway.protoc_gen_openapiv2.options.License\x12\x0f\n\x07version\x18\x06 \x01(\t\x12S\n\nextensions\x18\x07 \x03(\x0b\x32?.grpc.gateway.protoc_gen_openapiv2.options.Info.ExtensionsEntry\x1aI\n\x0f\x45xtensionsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12%\n\x05value\x18\x02 \x01(\x0b\x32\x16.google.protobuf.Value:\x02\x38\x01"3\n\x07\x43ontact\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x0b\n\x03url\x18\x02 \x01(\t\x12\r\n\x05\x65mail\x18\x03 \x01(\t"$\n\x07License\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x0b\n\x03url\x18\x02 \x01(\t"9\n\x15\x45xternalDocumentation\x12\x13\n\x0b\x64\x65scription\x18\x01 \x01(\t\x12\x0b\n\x03url\x18\x02 \x01(\t"\xee\x01\n\x06Schema\x12J\n\x0bjson_schema\x18\x01 \x01(\x0b\x32\x35.grpc.gateway.protoc_gen_openapiv2.options.JSONSchema\x12\x15\n\rdiscriminator\x18\x02 \x01(\t\x12\x11\n\tread_only\x18\x03 \x01(\x08\x12W\n\rexternal_docs\x18\x05 \x01(\x0b\x32@.grpc.gateway.protoc_gen_openapiv2.options.ExternalDocumentation\x12\x0f\n\x07\x65xample\x18\x06 \x01(\tJ\x04\x08\x04\x10\x05"\x83\x03\n\nEnumSchema\x12\x13\n\x0b\x64\x65scription\x18\x01 \x01(\t\x12\x0f\n\x07\x64\x65\x66\x61ult\x18\x02 \x01(\t\x12\r\n\x05title\x18\x03 \x01(\t\x12\x10\n\x08required\x18\x04 \x01(\x08\x12\x11\n\tread_only\x18\x05 \x01(\x08\x12W\n\rexternal_docs\x18\x06 \x01(\x0b\x32@.grpc.gateway.protoc_gen_openapiv2.options.ExternalDocumentation\x12\x0f\n\x07\x65xample\x18\x07 \x01(\t\x12\x0b\n\x03ref\x18\x08 \x01(\t\x12Y\n\nextensions\x18\t \x03(\x0b\x32\x45.grpc.gateway.protoc_gen_openapiv2.options.EnumSchema.ExtensionsEntry\x1aI\n\x0f\x45xtensionsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12%\n\x05value\x18\x02 \x01(\x0b\x32\x16.google.protobuf.Value:\x02\x38\x01"\xa2\x08\n\nJSONSchema\x12\x0b\n\x03ref\x18\x03 \x01(\t\x12\r\n\x05title\x18\x05 \x01(\t\x12\x13\n\x0b\x64\x65scription\x18\x06 \x01(\t\x12\x0f\n\x07\x64\x65\x66\x61ult\x18\x07 \x01(\t\x12\x11\n\tread_only\x18\x08 \x01(\x08\x12\x0f\n\x07\x65xample\x18\t \x01(\t\x12\x13\n\x0bmultiple_of\x18\n \x01(\x01\x12\x0f\n\x07maximum\x18\x0b \x01(\x01\x12\x19\n\x11\x65xclusive_maximum\x18\x0c \x01(\x08\x12\x0f\n\x07minimum\x18\r \x01(\x01\x12\x19\n\x11\x65xclusive_minimum\x18\x0e \x01(\x08\x12\x12\n\nmax_length\x18\x0f \x01(\x04\x12\x12\n\nmin_length\x18\x10 \x01(\x04\x12\x0f\n\x07pattern\x18\x11 \x01(\t\x12\x11\n\tmax_items\x18\x14 \x01(\x04\x12\x11\n\tmin_items\x18\x15 \x01(\x04\x12\x14\n\x0cunique_items\x18\x16 \x01(\x08\x12\x16\n\x0emax_properties\x18\x18 \x01(\x04\x12\x16\n\x0emin_properties\x18\x19 \x01(\x04\x12\x10\n\x08required\x18\x1a \x03(\t\x12\r\n\x05\x61rray\x18" \x03(\t\x12Y\n\x04type\x18# \x03(\x0e\x32K.grpc.gateway.protoc_gen_openapiv2.options.JSONSchema.JSONSchemaSimpleTypes\x12\x0e\n\x06\x66ormat\x18$ \x01(\t\x12\x0c\n\x04\x65num\x18. \x03(\t\x12\x66\n\x13\x66ield_configuration\x18\xe9\x07 \x01(\x0b\x32H.grpc.gateway.protoc_gen_openapiv2.options.JSONSchema.FieldConfiguration\x12Y\n\nextensions\x18\x30 \x03(\x0b\x32\x45.grpc.gateway.protoc_gen_openapiv2.options.JSONSchema.ExtensionsEntry\x1a-\n\x12\x46ieldConfiguration\x12\x17\n\x0fpath_param_name\x18/ \x01(\t\x1aI\n\x0f\x45xtensionsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12%\n\x05value\x18\x02 \x01(\x0b\x32\x16.google.protobuf.Value:\x02\x38\x01"w\n\x15JSONSchemaSimpleTypes\x12\x0b\n\x07UNKNOWN\x10\x00\x12\t\n\x05\x41RRAY\x10\x01\x12\x0b\n\x07\x42OOLEAN\x10\x02\x12\x0b\n\x07INTEGER\x10\x03\x12\x08\n\x04NULL\x10\x04\x12\n\n\x06NUMBER\x10\x05\x12\n\n\x06OBJECT\x10\x06\x12\n\n\x06STRING\x10\x07J\x04\x08\x01\x10\x02J\x04\x08\x02\x10\x03J\x04\x08\x04\x10\x05J\x04\x08\x12\x10\x13J\x04\x08\x13\x10\x14J\x04\x08\x17\x10\x18J\x04\x08\x1b\x10\x1cJ\x04\x08\x1c\x10\x1dJ\x04\x08\x1d\x10\x1eJ\x04\x08\x1e\x10"J\x04\x08%\x10*J\x04\x08*\x10+J\x04\x08+\x10."\xa0\x02\n\x03Tag\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x13\n\x0b\x64\x65scription\x18\x02 \x01(\t\x12W\n\rexternal_docs\x18\x03 \x01(\x0b\x32@.grpc.gateway.protoc_gen_openapiv2.options.ExternalDocumentation\x12R\n\nextensions\x18\x04 \x03(\x0b\x32>.grpc.gateway.protoc_gen_openapiv2.options.Tag.ExtensionsEntry\x1aI\n\x0f\x45xtensionsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12%\n\x05value\x18\x02 \x01(\x0b\x32\x16.google.protobuf.Value:\x02\x38\x01"\xe1\x01\n\x13SecurityDefinitions\x12^\n\x08security\x18\x01 \x03(\x0b\x32L.grpc.gateway.protoc_gen_openapiv2.options.SecurityDefinitions.SecurityEntry\x1aj\n\rSecurityEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12H\n\x05value\x18\x02 \x01(\x0b\x32\x39.grpc.gateway.protoc_gen_openapiv2.options.SecurityScheme:\x02\x38\x01"\xa0\x06\n\x0eSecurityScheme\x12L\n\x04type\x18\x01 \x01(\x0e\x32>.grpc.gateway.protoc_gen_openapiv2.options.SecurityScheme.Type\x12\x13\n\x0b\x64\x65scription\x18\x02 \x01(\t\x12\x0c\n\x04name\x18\x03 \x01(\t\x12H\n\x02in\x18\x04 \x01(\x0e\x32<.grpc.gateway.protoc_gen_openapiv2.options.SecurityScheme.In\x12L\n\x04\x66low\x18\x05 \x01(\x0e\x32>.grpc.gateway.protoc_gen_openapiv2.options.SecurityScheme.Flow\x12\x19\n\x11\x61uthorization_url\x18\x06 \x01(\t\x12\x11\n\ttoken_url\x18\x07 \x01(\t\x12\x41\n\x06scopes\x18\x08 \x01(\x0b\x32\x31.grpc.gateway.protoc_gen_openapiv2.options.Scopes\x12]\n\nextensions\x18\t \x03(\x0b\x32I.grpc.gateway.protoc_gen_openapiv2.options.SecurityScheme.ExtensionsEntry\x1aI\n\x0f\x45xtensionsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12%\n\x05value\x18\x02 \x01(\x0b\x32\x16.google.protobuf.Value:\x02\x38\x01"K\n\x04Type\x12\x10\n\x0cTYPE_INVALID\x10\x00\x12\x0e\n\nTYPE_BASIC\x10\x01\x12\x10\n\x0cTYPE_API_KEY\x10\x02\x12\x0f\n\x0bTYPE_OAUTH2\x10\x03"1\n\x02In\x12\x0e\n\nIN_INVALID\x10\x00\x12\x0c\n\x08IN_QUERY\x10\x01\x12\r\n\tIN_HEADER\x10\x02"j\n\x04\x46low\x12\x10\n\x0c\x46LOW_INVALID\x10\x00\x12\x11\n\rFLOW_IMPLICIT\x10\x01\x12\x11\n\rFLOW_PASSWORD\x10\x02\x12\x14\n\x10\x46LOW_APPLICATION\x10\x03\x12\x14\n\x10\x46LOW_ACCESS_CODE\x10\x04"\xcd\x02\n\x13SecurityRequirement\x12u\n\x14security_requirement\x18\x01 \x03(\x0b\x32W.grpc.gateway.protoc_gen_openapiv2.options.SecurityRequirement.SecurityRequirementEntry\x1a)\n\x18SecurityRequirementValue\x12\r\n\x05scope\x18\x01 \x03(\t\x1a\x93\x01\n\x18SecurityRequirementEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x66\n\x05value\x18\x02 \x01(\x0b\x32W.grpc.gateway.protoc_gen_openapiv2.options.SecurityRequirement.SecurityRequirementValue:\x02\x38\x01"\x83\x01\n\x06Scopes\x12K\n\x05scope\x18\x01 \x03(\x0b\x32<.grpc.gateway.protoc_gen_openapiv2.options.Scopes.ScopeEntry\x1a,\n\nScopeEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01*;\n\x06Scheme\x12\x0b\n\x07UNKNOWN\x10\x00\x12\x08\n\x04HTTP\x10\x01\x12\t\n\x05HTTPS\x10\x02\x12\x06\n\x02WS\x10\x03\x12\x07\n\x03WSS\x10\x04\x42HZFgithub.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2/optionsb\x06proto3' +) + +_SCHEME = DESCRIPTOR.enum_types_by_name["Scheme"] +Scheme = enum_type_wrapper.EnumTypeWrapper(_SCHEME) +UNKNOWN = 0 +HTTP = 1 +HTTPS = 2 +WS = 3 +WSS = 4 + + +_SWAGGER = DESCRIPTOR.message_types_by_name["Swagger"] +_SWAGGER_RESPONSESENTRY = _SWAGGER.nested_types_by_name["ResponsesEntry"] +_SWAGGER_EXTENSIONSENTRY = _SWAGGER.nested_types_by_name["ExtensionsEntry"] +_OPERATION = DESCRIPTOR.message_types_by_name["Operation"] +_OPERATION_RESPONSESENTRY = _OPERATION.nested_types_by_name["ResponsesEntry"] +_OPERATION_EXTENSIONSENTRY = _OPERATION.nested_types_by_name["ExtensionsEntry"] +_PARAMETERS = DESCRIPTOR.message_types_by_name["Parameters"] +_HEADERPARAMETER = DESCRIPTOR.message_types_by_name["HeaderParameter"] +_HEADER = DESCRIPTOR.message_types_by_name["Header"] +_RESPONSE = DESCRIPTOR.message_types_by_name["Response"] +_RESPONSE_HEADERSENTRY = _RESPONSE.nested_types_by_name["HeadersEntry"] +_RESPONSE_EXAMPLESENTRY = _RESPONSE.nested_types_by_name["ExamplesEntry"] +_RESPONSE_EXTENSIONSENTRY = _RESPONSE.nested_types_by_name["ExtensionsEntry"] +_INFO = DESCRIPTOR.message_types_by_name["Info"] +_INFO_EXTENSIONSENTRY = _INFO.nested_types_by_name["ExtensionsEntry"] +_CONTACT = DESCRIPTOR.message_types_by_name["Contact"] +_LICENSE = DESCRIPTOR.message_types_by_name["License"] +_EXTERNALDOCUMENTATION = DESCRIPTOR.message_types_by_name["ExternalDocumentation"] +_SCHEMA = DESCRIPTOR.message_types_by_name["Schema"] +_ENUMSCHEMA = DESCRIPTOR.message_types_by_name["EnumSchema"] +_ENUMSCHEMA_EXTENSIONSENTRY = _ENUMSCHEMA.nested_types_by_name["ExtensionsEntry"] +_JSONSCHEMA = DESCRIPTOR.message_types_by_name["JSONSchema"] +_JSONSCHEMA_FIELDCONFIGURATION = _JSONSCHEMA.nested_types_by_name["FieldConfiguration"] +_JSONSCHEMA_EXTENSIONSENTRY = _JSONSCHEMA.nested_types_by_name["ExtensionsEntry"] +_TAG = DESCRIPTOR.message_types_by_name["Tag"] +_TAG_EXTENSIONSENTRY = _TAG.nested_types_by_name["ExtensionsEntry"] +_SECURITYDEFINITIONS = DESCRIPTOR.message_types_by_name["SecurityDefinitions"] +_SECURITYDEFINITIONS_SECURITYENTRY = _SECURITYDEFINITIONS.nested_types_by_name[ + "SecurityEntry" +] +_SECURITYSCHEME = DESCRIPTOR.message_types_by_name["SecurityScheme"] +_SECURITYSCHEME_EXTENSIONSENTRY = _SECURITYSCHEME.nested_types_by_name[ + "ExtensionsEntry" +] +_SECURITYREQUIREMENT = DESCRIPTOR.message_types_by_name["SecurityRequirement"] +_SECURITYREQUIREMENT_SECURITYREQUIREMENTVALUE = ( + _SECURITYREQUIREMENT.nested_types_by_name["SecurityRequirementValue"] +) +_SECURITYREQUIREMENT_SECURITYREQUIREMENTENTRY = ( + _SECURITYREQUIREMENT.nested_types_by_name["SecurityRequirementEntry"] +) +_SCOPES = DESCRIPTOR.message_types_by_name["Scopes"] +_SCOPES_SCOPEENTRY = _SCOPES.nested_types_by_name["ScopeEntry"] +_HEADERPARAMETER_TYPE = _HEADERPARAMETER.enum_types_by_name["Type"] +_JSONSCHEMA_JSONSCHEMASIMPLETYPES = _JSONSCHEMA.enum_types_by_name[ + "JSONSchemaSimpleTypes" +] +_SECURITYSCHEME_TYPE = _SECURITYSCHEME.enum_types_by_name["Type"] +_SECURITYSCHEME_IN = _SECURITYSCHEME.enum_types_by_name["In"] +_SECURITYSCHEME_FLOW = _SECURITYSCHEME.enum_types_by_name["Flow"] +Swagger = _reflection.GeneratedProtocolMessageType( + "Swagger", + (_message.Message,), + { + "ResponsesEntry": _reflection.GeneratedProtocolMessageType( + "ResponsesEntry", + (_message.Message,), + { + "DESCRIPTOR": _SWAGGER_RESPONSESENTRY, + "__module__": "protoc_gen_openapiv2.options.openapiv2_pb2", + # @@protoc_insertion_point(class_scope:grpc.gateway.protoc_gen_openapiv2.options.Swagger.ResponsesEntry) + }, + ), + "ExtensionsEntry": _reflection.GeneratedProtocolMessageType( + "ExtensionsEntry", + (_message.Message,), + { + "DESCRIPTOR": _SWAGGER_EXTENSIONSENTRY, + "__module__": "protoc_gen_openapiv2.options.openapiv2_pb2", + # @@protoc_insertion_point(class_scope:grpc.gateway.protoc_gen_openapiv2.options.Swagger.ExtensionsEntry) + }, + ), + "DESCRIPTOR": _SWAGGER, + "__module__": "protoc_gen_openapiv2.options.openapiv2_pb2", + # @@protoc_insertion_point(class_scope:grpc.gateway.protoc_gen_openapiv2.options.Swagger) + }, +) +_sym_db.RegisterMessage(Swagger) +_sym_db.RegisterMessage(Swagger.ResponsesEntry) +_sym_db.RegisterMessage(Swagger.ExtensionsEntry) + +Operation = _reflection.GeneratedProtocolMessageType( + "Operation", + (_message.Message,), + { + "ResponsesEntry": _reflection.GeneratedProtocolMessageType( + "ResponsesEntry", + (_message.Message,), + { + "DESCRIPTOR": _OPERATION_RESPONSESENTRY, + "__module__": "protoc_gen_openapiv2.options.openapiv2_pb2", + # @@protoc_insertion_point(class_scope:grpc.gateway.protoc_gen_openapiv2.options.Operation.ResponsesEntry) + }, + ), + "ExtensionsEntry": _reflection.GeneratedProtocolMessageType( + "ExtensionsEntry", + (_message.Message,), + { + "DESCRIPTOR": _OPERATION_EXTENSIONSENTRY, + "__module__": "protoc_gen_openapiv2.options.openapiv2_pb2", + # @@protoc_insertion_point(class_scope:grpc.gateway.protoc_gen_openapiv2.options.Operation.ExtensionsEntry) + }, + ), + "DESCRIPTOR": _OPERATION, + "__module__": "protoc_gen_openapiv2.options.openapiv2_pb2", + # @@protoc_insertion_point(class_scope:grpc.gateway.protoc_gen_openapiv2.options.Operation) + }, +) +_sym_db.RegisterMessage(Operation) +_sym_db.RegisterMessage(Operation.ResponsesEntry) +_sym_db.RegisterMessage(Operation.ExtensionsEntry) + +Parameters = _reflection.GeneratedProtocolMessageType( + "Parameters", + (_message.Message,), + { + "DESCRIPTOR": _PARAMETERS, + "__module__": "protoc_gen_openapiv2.options.openapiv2_pb2", + # @@protoc_insertion_point(class_scope:grpc.gateway.protoc_gen_openapiv2.options.Parameters) + }, +) +_sym_db.RegisterMessage(Parameters) + +HeaderParameter = _reflection.GeneratedProtocolMessageType( + "HeaderParameter", + (_message.Message,), + { + "DESCRIPTOR": _HEADERPARAMETER, + "__module__": "protoc_gen_openapiv2.options.openapiv2_pb2", + # @@protoc_insertion_point(class_scope:grpc.gateway.protoc_gen_openapiv2.options.HeaderParameter) + }, +) +_sym_db.RegisterMessage(HeaderParameter) + +Header = _reflection.GeneratedProtocolMessageType( + "Header", + (_message.Message,), + { + "DESCRIPTOR": _HEADER, + "__module__": "protoc_gen_openapiv2.options.openapiv2_pb2", + # @@protoc_insertion_point(class_scope:grpc.gateway.protoc_gen_openapiv2.options.Header) + }, +) +_sym_db.RegisterMessage(Header) + +Response = _reflection.GeneratedProtocolMessageType( + "Response", + (_message.Message,), + { + "HeadersEntry": _reflection.GeneratedProtocolMessageType( + "HeadersEntry", + (_message.Message,), + { + "DESCRIPTOR": _RESPONSE_HEADERSENTRY, + "__module__": "protoc_gen_openapiv2.options.openapiv2_pb2", + # @@protoc_insertion_point(class_scope:grpc.gateway.protoc_gen_openapiv2.options.Response.HeadersEntry) + }, + ), + "ExamplesEntry": _reflection.GeneratedProtocolMessageType( + "ExamplesEntry", + (_message.Message,), + { + "DESCRIPTOR": _RESPONSE_EXAMPLESENTRY, + "__module__": "protoc_gen_openapiv2.options.openapiv2_pb2", + # @@protoc_insertion_point(class_scope:grpc.gateway.protoc_gen_openapiv2.options.Response.ExamplesEntry) + }, + ), + "ExtensionsEntry": _reflection.GeneratedProtocolMessageType( + "ExtensionsEntry", + (_message.Message,), + { + "DESCRIPTOR": _RESPONSE_EXTENSIONSENTRY, + "__module__": "protoc_gen_openapiv2.options.openapiv2_pb2", + # @@protoc_insertion_point(class_scope:grpc.gateway.protoc_gen_openapiv2.options.Response.ExtensionsEntry) + }, + ), + "DESCRIPTOR": _RESPONSE, + "__module__": "protoc_gen_openapiv2.options.openapiv2_pb2", + # @@protoc_insertion_point(class_scope:grpc.gateway.protoc_gen_openapiv2.options.Response) + }, +) +_sym_db.RegisterMessage(Response) +_sym_db.RegisterMessage(Response.HeadersEntry) +_sym_db.RegisterMessage(Response.ExamplesEntry) +_sym_db.RegisterMessage(Response.ExtensionsEntry) + +Info = _reflection.GeneratedProtocolMessageType( + "Info", + (_message.Message,), + { + "ExtensionsEntry": _reflection.GeneratedProtocolMessageType( + "ExtensionsEntry", + (_message.Message,), + { + "DESCRIPTOR": _INFO_EXTENSIONSENTRY, + "__module__": "protoc_gen_openapiv2.options.openapiv2_pb2", + # @@protoc_insertion_point(class_scope:grpc.gateway.protoc_gen_openapiv2.options.Info.ExtensionsEntry) + }, + ), + "DESCRIPTOR": _INFO, + "__module__": "protoc_gen_openapiv2.options.openapiv2_pb2", + # @@protoc_insertion_point(class_scope:grpc.gateway.protoc_gen_openapiv2.options.Info) + }, +) +_sym_db.RegisterMessage(Info) +_sym_db.RegisterMessage(Info.ExtensionsEntry) + +Contact = _reflection.GeneratedProtocolMessageType( + "Contact", + (_message.Message,), + { + "DESCRIPTOR": _CONTACT, + "__module__": "protoc_gen_openapiv2.options.openapiv2_pb2", + # @@protoc_insertion_point(class_scope:grpc.gateway.protoc_gen_openapiv2.options.Contact) + }, +) +_sym_db.RegisterMessage(Contact) + +License = _reflection.GeneratedProtocolMessageType( + "License", + (_message.Message,), + { + "DESCRIPTOR": _LICENSE, + "__module__": "protoc_gen_openapiv2.options.openapiv2_pb2", + # @@protoc_insertion_point(class_scope:grpc.gateway.protoc_gen_openapiv2.options.License) + }, +) +_sym_db.RegisterMessage(License) + +ExternalDocumentation = _reflection.GeneratedProtocolMessageType( + "ExternalDocumentation", + (_message.Message,), + { + "DESCRIPTOR": _EXTERNALDOCUMENTATION, + "__module__": "protoc_gen_openapiv2.options.openapiv2_pb2", + # @@protoc_insertion_point(class_scope:grpc.gateway.protoc_gen_openapiv2.options.ExternalDocumentation) + }, +) +_sym_db.RegisterMessage(ExternalDocumentation) + +Schema = _reflection.GeneratedProtocolMessageType( + "Schema", + (_message.Message,), + { + "DESCRIPTOR": _SCHEMA, + "__module__": "protoc_gen_openapiv2.options.openapiv2_pb2", + # @@protoc_insertion_point(class_scope:grpc.gateway.protoc_gen_openapiv2.options.Schema) + }, +) +_sym_db.RegisterMessage(Schema) + +EnumSchema = _reflection.GeneratedProtocolMessageType( + "EnumSchema", + (_message.Message,), + { + "ExtensionsEntry": _reflection.GeneratedProtocolMessageType( + "ExtensionsEntry", + (_message.Message,), + { + "DESCRIPTOR": _ENUMSCHEMA_EXTENSIONSENTRY, + "__module__": "protoc_gen_openapiv2.options.openapiv2_pb2", + # @@protoc_insertion_point(class_scope:grpc.gateway.protoc_gen_openapiv2.options.EnumSchema.ExtensionsEntry) + }, + ), + "DESCRIPTOR": _ENUMSCHEMA, + "__module__": "protoc_gen_openapiv2.options.openapiv2_pb2", + # @@protoc_insertion_point(class_scope:grpc.gateway.protoc_gen_openapiv2.options.EnumSchema) + }, +) +_sym_db.RegisterMessage(EnumSchema) +_sym_db.RegisterMessage(EnumSchema.ExtensionsEntry) + +JSONSchema = _reflection.GeneratedProtocolMessageType( + "JSONSchema", + (_message.Message,), + { + "FieldConfiguration": _reflection.GeneratedProtocolMessageType( + "FieldConfiguration", + (_message.Message,), + { + "DESCRIPTOR": _JSONSCHEMA_FIELDCONFIGURATION, + "__module__": "protoc_gen_openapiv2.options.openapiv2_pb2", + # @@protoc_insertion_point(class_scope:grpc.gateway.protoc_gen_openapiv2.options.JSONSchema.FieldConfiguration) + }, + ), + "ExtensionsEntry": _reflection.GeneratedProtocolMessageType( + "ExtensionsEntry", + (_message.Message,), + { + "DESCRIPTOR": _JSONSCHEMA_EXTENSIONSENTRY, + "__module__": "protoc_gen_openapiv2.options.openapiv2_pb2", + # @@protoc_insertion_point(class_scope:grpc.gateway.protoc_gen_openapiv2.options.JSONSchema.ExtensionsEntry) + }, + ), + "DESCRIPTOR": _JSONSCHEMA, + "__module__": "protoc_gen_openapiv2.options.openapiv2_pb2", + # @@protoc_insertion_point(class_scope:grpc.gateway.protoc_gen_openapiv2.options.JSONSchema) + }, +) +_sym_db.RegisterMessage(JSONSchema) +_sym_db.RegisterMessage(JSONSchema.FieldConfiguration) +_sym_db.RegisterMessage(JSONSchema.ExtensionsEntry) + +Tag = _reflection.GeneratedProtocolMessageType( + "Tag", + (_message.Message,), + { + "ExtensionsEntry": _reflection.GeneratedProtocolMessageType( + "ExtensionsEntry", + (_message.Message,), + { + "DESCRIPTOR": _TAG_EXTENSIONSENTRY, + "__module__": "protoc_gen_openapiv2.options.openapiv2_pb2", + # @@protoc_insertion_point(class_scope:grpc.gateway.protoc_gen_openapiv2.options.Tag.ExtensionsEntry) + }, + ), + "DESCRIPTOR": _TAG, + "__module__": "protoc_gen_openapiv2.options.openapiv2_pb2", + # @@protoc_insertion_point(class_scope:grpc.gateway.protoc_gen_openapiv2.options.Tag) + }, +) +_sym_db.RegisterMessage(Tag) +_sym_db.RegisterMessage(Tag.ExtensionsEntry) + +SecurityDefinitions = _reflection.GeneratedProtocolMessageType( + "SecurityDefinitions", + (_message.Message,), + { + "SecurityEntry": _reflection.GeneratedProtocolMessageType( + "SecurityEntry", + (_message.Message,), + { + "DESCRIPTOR": _SECURITYDEFINITIONS_SECURITYENTRY, + "__module__": "protoc_gen_openapiv2.options.openapiv2_pb2", + # @@protoc_insertion_point(class_scope:grpc.gateway.protoc_gen_openapiv2.options.SecurityDefinitions.SecurityEntry) + }, + ), + "DESCRIPTOR": _SECURITYDEFINITIONS, + "__module__": "protoc_gen_openapiv2.options.openapiv2_pb2", + # @@protoc_insertion_point(class_scope:grpc.gateway.protoc_gen_openapiv2.options.SecurityDefinitions) + }, +) +_sym_db.RegisterMessage(SecurityDefinitions) +_sym_db.RegisterMessage(SecurityDefinitions.SecurityEntry) + +SecurityScheme = _reflection.GeneratedProtocolMessageType( + "SecurityScheme", + (_message.Message,), + { + "ExtensionsEntry": _reflection.GeneratedProtocolMessageType( + "ExtensionsEntry", + (_message.Message,), + { + "DESCRIPTOR": _SECURITYSCHEME_EXTENSIONSENTRY, + "__module__": "protoc_gen_openapiv2.options.openapiv2_pb2", + # @@protoc_insertion_point(class_scope:grpc.gateway.protoc_gen_openapiv2.options.SecurityScheme.ExtensionsEntry) + }, + ), + "DESCRIPTOR": _SECURITYSCHEME, + "__module__": "protoc_gen_openapiv2.options.openapiv2_pb2", + # @@protoc_insertion_point(class_scope:grpc.gateway.protoc_gen_openapiv2.options.SecurityScheme) + }, +) +_sym_db.RegisterMessage(SecurityScheme) +_sym_db.RegisterMessage(SecurityScheme.ExtensionsEntry) + +SecurityRequirement = _reflection.GeneratedProtocolMessageType( + "SecurityRequirement", + (_message.Message,), + { + "SecurityRequirementValue": _reflection.GeneratedProtocolMessageType( + "SecurityRequirementValue", + (_message.Message,), + { + "DESCRIPTOR": _SECURITYREQUIREMENT_SECURITYREQUIREMENTVALUE, + "__module__": "protoc_gen_openapiv2.options.openapiv2_pb2", + # @@protoc_insertion_point(class_scope:grpc.gateway.protoc_gen_openapiv2.options.SecurityRequirement.SecurityRequirementValue) + }, + ), + "SecurityRequirementEntry": _reflection.GeneratedProtocolMessageType( + "SecurityRequirementEntry", + (_message.Message,), + { + "DESCRIPTOR": _SECURITYREQUIREMENT_SECURITYREQUIREMENTENTRY, + "__module__": "protoc_gen_openapiv2.options.openapiv2_pb2", + # @@protoc_insertion_point(class_scope:grpc.gateway.protoc_gen_openapiv2.options.SecurityRequirement.SecurityRequirementEntry) + }, + ), + "DESCRIPTOR": _SECURITYREQUIREMENT, + "__module__": "protoc_gen_openapiv2.options.openapiv2_pb2", + # @@protoc_insertion_point(class_scope:grpc.gateway.protoc_gen_openapiv2.options.SecurityRequirement) + }, +) +_sym_db.RegisterMessage(SecurityRequirement) +_sym_db.RegisterMessage(SecurityRequirement.SecurityRequirementValue) +_sym_db.RegisterMessage(SecurityRequirement.SecurityRequirementEntry) + +Scopes = _reflection.GeneratedProtocolMessageType( + "Scopes", + (_message.Message,), + { + "ScopeEntry": _reflection.GeneratedProtocolMessageType( + "ScopeEntry", + (_message.Message,), + { + "DESCRIPTOR": _SCOPES_SCOPEENTRY, + "__module__": "protoc_gen_openapiv2.options.openapiv2_pb2", + # @@protoc_insertion_point(class_scope:grpc.gateway.protoc_gen_openapiv2.options.Scopes.ScopeEntry) + }, + ), + "DESCRIPTOR": _SCOPES, + "__module__": "protoc_gen_openapiv2.options.openapiv2_pb2", + # @@protoc_insertion_point(class_scope:grpc.gateway.protoc_gen_openapiv2.options.Scopes) + }, +) +_sym_db.RegisterMessage(Scopes) +_sym_db.RegisterMessage(Scopes.ScopeEntry) + +if _descriptor._USE_C_DESCRIPTORS == False: + DESCRIPTOR._options = None + DESCRIPTOR._serialized_options = ( + b"ZFgithub.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2/options" + ) + _SWAGGER_RESPONSESENTRY._options = None + _SWAGGER_RESPONSESENTRY._serialized_options = b"8\001" + _SWAGGER_EXTENSIONSENTRY._options = None + _SWAGGER_EXTENSIONSENTRY._serialized_options = b"8\001" + _OPERATION_RESPONSESENTRY._options = None + _OPERATION_RESPONSESENTRY._serialized_options = b"8\001" + _OPERATION_EXTENSIONSENTRY._options = None + _OPERATION_EXTENSIONSENTRY._serialized_options = b"8\001" + _RESPONSE_HEADERSENTRY._options = None + _RESPONSE_HEADERSENTRY._serialized_options = b"8\001" + _RESPONSE_EXAMPLESENTRY._options = None + _RESPONSE_EXAMPLESENTRY._serialized_options = b"8\001" + _RESPONSE_EXTENSIONSENTRY._options = None + _RESPONSE_EXTENSIONSENTRY._serialized_options = b"8\001" + _INFO_EXTENSIONSENTRY._options = None + _INFO_EXTENSIONSENTRY._serialized_options = b"8\001" + _ENUMSCHEMA_EXTENSIONSENTRY._options = None + _ENUMSCHEMA_EXTENSIONSENTRY._serialized_options = b"8\001" + _JSONSCHEMA_EXTENSIONSENTRY._options = None + _JSONSCHEMA_EXTENSIONSENTRY._serialized_options = b"8\001" + _TAG_EXTENSIONSENTRY._options = None + _TAG_EXTENSIONSENTRY._serialized_options = b"8\001" + _SECURITYDEFINITIONS_SECURITYENTRY._options = None + _SECURITYDEFINITIONS_SECURITYENTRY._serialized_options = b"8\001" + _SECURITYSCHEME_EXTENSIONSENTRY._options = None + _SECURITYSCHEME_EXTENSIONSENTRY._serialized_options = b"8\001" + _SECURITYREQUIREMENT_SECURITYREQUIREMENTENTRY._options = None + _SECURITYREQUIREMENT_SECURITYREQUIREMENTENTRY._serialized_options = b"8\001" + _SCOPES_SCOPEENTRY._options = None + _SCOPES_SCOPEENTRY._serialized_options = b"8\001" + _SCHEME._serialized_start = 6978 + _SCHEME._serialized_end = 7037 + _SWAGGER._serialized_start = 122 + _SWAGGER._serialized_end = 1039 + _SWAGGER_RESPONSESENTRY._serialized_start = 851 + _SWAGGER_RESPONSESENTRY._serialized_end = 952 + _SWAGGER_EXTENSIONSENTRY._serialized_start = 954 + _SWAGGER_EXTENSIONSENTRY._serialized_end = 1027 + _OPERATION._serialized_start = 1042 + _OPERATION._serialized_end = 1859 + _OPERATION_RESPONSESENTRY._serialized_start = 851 + _OPERATION_RESPONSESENTRY._serialized_end = 952 + _OPERATION_EXTENSIONSENTRY._serialized_start = 954 + _OPERATION_EXTENSIONSENTRY._serialized_end = 1027 + _PARAMETERS._serialized_start = 1861 + _PARAMETERS._serialized_end = 1950 + _HEADERPARAMETER._serialized_start = 1953 + _HEADERPARAMETER._serialized_end = 2201 + _HEADERPARAMETER_TYPE._serialized_start = 2120 + _HEADERPARAMETER_TYPE._serialized_end = 2189 + _HEADER._serialized_start = 2204 + _HEADER._serialized_end = 2375 + _RESPONSE._serialized_start = 2378 + _RESPONSE._serialized_end = 2956 + _RESPONSE_HEADERSENTRY._serialized_start = 2735 + _RESPONSE_HEADERSENTRY._serialized_end = 2832 + _RESPONSE_EXAMPLESENTRY._serialized_start = 2834 + _RESPONSE_EXAMPLESENTRY._serialized_end = 2881 + _RESPONSE_EXTENSIONSENTRY._serialized_start = 954 + _RESPONSE_EXTENSIONSENTRY._serialized_end = 1027 + _INFO._serialized_start = 2959 + _INFO._serialized_end = 3342 + _INFO_EXTENSIONSENTRY._serialized_start = 954 + _INFO_EXTENSIONSENTRY._serialized_end = 1027 + _CONTACT._serialized_start = 3344 + _CONTACT._serialized_end = 3395 + _LICENSE._serialized_start = 3397 + _LICENSE._serialized_end = 3433 + _EXTERNALDOCUMENTATION._serialized_start = 3435 + _EXTERNALDOCUMENTATION._serialized_end = 3492 + _SCHEMA._serialized_start = 3495 + _SCHEMA._serialized_end = 3733 + _ENUMSCHEMA._serialized_start = 3736 + _ENUMSCHEMA._serialized_end = 4123 + _ENUMSCHEMA_EXTENSIONSENTRY._serialized_start = 954 + _ENUMSCHEMA_EXTENSIONSENTRY._serialized_end = 1027 + _JSONSCHEMA._serialized_start = 4126 + _JSONSCHEMA._serialized_end = 5184 + _JSONSCHEMA_FIELDCONFIGURATION._serialized_start = 4865 + _JSONSCHEMA_FIELDCONFIGURATION._serialized_end = 4910 + _JSONSCHEMA_EXTENSIONSENTRY._serialized_start = 954 + _JSONSCHEMA_EXTENSIONSENTRY._serialized_end = 1027 + _JSONSCHEMA_JSONSCHEMASIMPLETYPES._serialized_start = 4987 + _JSONSCHEMA_JSONSCHEMASIMPLETYPES._serialized_end = 5106 + _TAG._serialized_start = 5187 + _TAG._serialized_end = 5475 + _TAG_EXTENSIONSENTRY._serialized_start = 954 + _TAG_EXTENSIONSENTRY._serialized_end = 1027 + _SECURITYDEFINITIONS._serialized_start = 5478 + _SECURITYDEFINITIONS._serialized_end = 5703 + _SECURITYDEFINITIONS_SECURITYENTRY._serialized_start = 5597 + _SECURITYDEFINITIONS_SECURITYENTRY._serialized_end = 5703 + _SECURITYSCHEME._serialized_start = 5706 + _SECURITYSCHEME._serialized_end = 6506 + _SECURITYSCHEME_EXTENSIONSENTRY._serialized_start = 954 + _SECURITYSCHEME_EXTENSIONSENTRY._serialized_end = 1027 + _SECURITYSCHEME_TYPE._serialized_start = 6272 + _SECURITYSCHEME_TYPE._serialized_end = 6347 + _SECURITYSCHEME_IN._serialized_start = 6349 + _SECURITYSCHEME_IN._serialized_end = 6398 + _SECURITYSCHEME_FLOW._serialized_start = 6400 + _SECURITYSCHEME_FLOW._serialized_end = 6506 + _SECURITYREQUIREMENT._serialized_start = 6509 + _SECURITYREQUIREMENT._serialized_end = 6842 + _SECURITYREQUIREMENT_SECURITYREQUIREMENTVALUE._serialized_start = 6651 + _SECURITYREQUIREMENT_SECURITYREQUIREMENTVALUE._serialized_end = 6692 + _SECURITYREQUIREMENT_SECURITYREQUIREMENTENTRY._serialized_start = 6695 + _SECURITYREQUIREMENT_SECURITYREQUIREMENTENTRY._serialized_end = 6842 + _SCOPES._serialized_start = 6845 + _SCOPES._serialized_end = 6976 + _SCOPES_SCOPEENTRY._serialized_start = 6932 + _SCOPES_SCOPEENTRY._serialized_end = 6976 +# @@protoc_insertion_point(module_scope) diff --git a/temporalio/api/dependencies/protoc_gen_openapiv2/options/openapiv2_pb2.pyi b/temporalio/api/dependencies/protoc_gen_openapiv2/options/openapiv2_pb2.pyi new file mode 100644 index 000000000..458d881f9 --- /dev/null +++ b/temporalio/api/dependencies/protoc_gen_openapiv2/options/openapiv2_pb2.pyi @@ -0,0 +1,2102 @@ +""" +@generated by mypy-protobuf. Do not edit manually! +isort:skip_file +""" + +import builtins +import collections.abc +import sys +import typing + +import google.protobuf.descriptor +import google.protobuf.internal.containers +import google.protobuf.internal.enum_type_wrapper +import google.protobuf.message +import google.protobuf.struct_pb2 + +if sys.version_info >= (3, 10): + import typing as typing_extensions +else: + import typing_extensions + +DESCRIPTOR: google.protobuf.descriptor.FileDescriptor + +class _Scheme: + ValueType = typing.NewType("ValueType", builtins.int) + V: typing_extensions.TypeAlias = ValueType + +class _SchemeEnumTypeWrapper( + google.protobuf.internal.enum_type_wrapper._EnumTypeWrapper[_Scheme.ValueType], + builtins.type, +): # noqa: F821 + DESCRIPTOR: google.protobuf.descriptor.EnumDescriptor + UNKNOWN: _Scheme.ValueType # 0 + HTTP: _Scheme.ValueType # 1 + HTTPS: _Scheme.ValueType # 2 + WS: _Scheme.ValueType # 3 + WSS: _Scheme.ValueType # 4 + +class Scheme(_Scheme, metaclass=_SchemeEnumTypeWrapper): + """Scheme describes the schemes supported by the OpenAPI Swagger + and Operation objects. + """ + +UNKNOWN: Scheme.ValueType # 0 +HTTP: Scheme.ValueType # 1 +HTTPS: Scheme.ValueType # 2 +WS: Scheme.ValueType # 3 +WSS: Scheme.ValueType # 4 +global___Scheme = Scheme + +class Swagger(google.protobuf.message.Message): + """`Swagger` is a representation of OpenAPI v2 specification's Swagger object. + + See: https://github.com/OAI/OpenAPI-Specification/blob/3.0.0/versions/2.0.md#swaggerObject + + Example: + + option (grpc.gateway.temporalio.api.dependencies.protoc_gen_openapiv2.options.openapiv2_swagger) = { + info: { + title: "Echo API"; + version: "1.0"; + description: ""; + contact: { + name: "gRPC-Gateway project"; + url: "https://github.com/grpc-ecosystem/grpc-gateway"; + email: "none@example.com"; + }; + license: { + name: "BSD 3-Clause License"; + url: "https://github.com/grpc-ecosystem/grpc-gateway/blob/main/LICENSE"; + }; + }; + schemes: HTTPS; + consumes: "application/json"; + produces: "application/json"; + }; + """ + + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + class ResponsesEntry(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + KEY_FIELD_NUMBER: builtins.int + VALUE_FIELD_NUMBER: builtins.int + key: builtins.str + @property + def value(self) -> global___Response: ... + def __init__( + self, + *, + key: builtins.str = ..., + value: global___Response | None = ..., + ) -> None: ... + def HasField( + self, field_name: typing_extensions.Literal["value", b"value"] + ) -> builtins.bool: ... + def ClearField( + self, + field_name: typing_extensions.Literal["key", b"key", "value", b"value"], + ) -> None: ... + + class ExtensionsEntry(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + KEY_FIELD_NUMBER: builtins.int + VALUE_FIELD_NUMBER: builtins.int + key: builtins.str + @property + def value(self) -> google.protobuf.struct_pb2.Value: ... + def __init__( + self, + *, + key: builtins.str = ..., + value: google.protobuf.struct_pb2.Value | None = ..., + ) -> None: ... + def HasField( + self, field_name: typing_extensions.Literal["value", b"value"] + ) -> builtins.bool: ... + def ClearField( + self, + field_name: typing_extensions.Literal["key", b"key", "value", b"value"], + ) -> None: ... + + SWAGGER_FIELD_NUMBER: builtins.int + INFO_FIELD_NUMBER: builtins.int + HOST_FIELD_NUMBER: builtins.int + BASE_PATH_FIELD_NUMBER: builtins.int + SCHEMES_FIELD_NUMBER: builtins.int + CONSUMES_FIELD_NUMBER: builtins.int + PRODUCES_FIELD_NUMBER: builtins.int + RESPONSES_FIELD_NUMBER: builtins.int + SECURITY_DEFINITIONS_FIELD_NUMBER: builtins.int + SECURITY_FIELD_NUMBER: builtins.int + TAGS_FIELD_NUMBER: builtins.int + EXTERNAL_DOCS_FIELD_NUMBER: builtins.int + EXTENSIONS_FIELD_NUMBER: builtins.int + swagger: builtins.str + """Specifies the OpenAPI Specification version being used. It can be + used by the OpenAPI UI and other clients to interpret the API listing. The + value MUST be "2.0". + """ + @property + def info(self) -> global___Info: + """Provides metadata about the API. The metadata can be used by the + clients if needed. + """ + host: builtins.str + """The host (name or ip) serving the API. This MUST be the host only and does + not include the scheme nor sub-paths. It MAY include a port. If the host is + not included, the host serving the documentation is to be used (including + the port). The host does not support path templating. + """ + base_path: builtins.str + """The base path on which the API is served, which is relative to the host. If + it is not included, the API is served directly under the host. The value + MUST start with a leading slash (/). The basePath does not support path + templating. + Note that using `base_path` does not change the endpoint paths that are + generated in the resulting OpenAPI file. If you wish to use `base_path` + with relatively generated OpenAPI paths, the `base_path` prefix must be + manually removed from your `google.api.http` paths and your code changed to + serve the API from the `base_path`. + """ + @property + def schemes( + self, + ) -> google.protobuf.internal.containers.RepeatedScalarFieldContainer[ + global___Scheme.ValueType + ]: + """The transfer protocol of the API. Values MUST be from the list: "http", + "https", "ws", "wss". If the schemes is not included, the default scheme to + be used is the one used to access the OpenAPI definition itself. + """ + @property + def consumes( + self, + ) -> google.protobuf.internal.containers.RepeatedScalarFieldContainer[builtins.str]: + """A list of MIME types the APIs can consume. This is global to all APIs but + can be overridden on specific API calls. Value MUST be as described under + Mime Types. + """ + @property + def produces( + self, + ) -> google.protobuf.internal.containers.RepeatedScalarFieldContainer[builtins.str]: + """A list of MIME types the APIs can produce. This is global to all APIs but + can be overridden on specific API calls. Value MUST be as described under + Mime Types. + """ + @property + def responses( + self, + ) -> google.protobuf.internal.containers.MessageMap[ + builtins.str, global___Response + ]: + """An object to hold responses that can be used across operations. This + property does not define global responses for all operations. + """ + @property + def security_definitions(self) -> global___SecurityDefinitions: + """Security scheme definitions that can be used across the specification.""" + @property + def security( + self, + ) -> google.protobuf.internal.containers.RepeatedCompositeFieldContainer[ + global___SecurityRequirement + ]: + """A declaration of which security schemes are applied for the API as a whole. + The list of values describes alternative security schemes that can be used + (that is, there is a logical OR between the security requirements). + Individual operations can override this definition. + """ + @property + def tags( + self, + ) -> google.protobuf.internal.containers.RepeatedCompositeFieldContainer[ + global___Tag + ]: + """A list of tags for API documentation control. Tags can be used for logical + grouping of operations by resources or any other qualifier. + """ + @property + def external_docs(self) -> global___ExternalDocumentation: + """Additional external documentation.""" + @property + def extensions( + self, + ) -> google.protobuf.internal.containers.MessageMap[ + builtins.str, google.protobuf.struct_pb2.Value + ]: + """Custom properties that start with "x-" such as "x-foo" used to describe + extra functionality that is not covered by the standard OpenAPI Specification. + See: https://swagger.io/docs/specification/2-0/swagger-extensions/ + """ + def __init__( + self, + *, + swagger: builtins.str = ..., + info: global___Info | None = ..., + host: builtins.str = ..., + base_path: builtins.str = ..., + schemes: collections.abc.Iterable[global___Scheme.ValueType] | None = ..., + consumes: collections.abc.Iterable[builtins.str] | None = ..., + produces: collections.abc.Iterable[builtins.str] | None = ..., + responses: collections.abc.Mapping[builtins.str, global___Response] + | None = ..., + security_definitions: global___SecurityDefinitions | None = ..., + security: collections.abc.Iterable[global___SecurityRequirement] | None = ..., + tags: collections.abc.Iterable[global___Tag] | None = ..., + external_docs: global___ExternalDocumentation | None = ..., + extensions: collections.abc.Mapping[ + builtins.str, google.protobuf.struct_pb2.Value + ] + | None = ..., + ) -> None: ... + def HasField( + self, + field_name: typing_extensions.Literal[ + "external_docs", + b"external_docs", + "info", + b"info", + "security_definitions", + b"security_definitions", + ], + ) -> builtins.bool: ... + def ClearField( + self, + field_name: typing_extensions.Literal[ + "base_path", + b"base_path", + "consumes", + b"consumes", + "extensions", + b"extensions", + "external_docs", + b"external_docs", + "host", + b"host", + "info", + b"info", + "produces", + b"produces", + "responses", + b"responses", + "schemes", + b"schemes", + "security", + b"security", + "security_definitions", + b"security_definitions", + "swagger", + b"swagger", + "tags", + b"tags", + ], + ) -> None: ... + +global___Swagger = Swagger + +class Operation(google.protobuf.message.Message): + """`Operation` is a representation of OpenAPI v2 specification's Operation object. + + See: https://github.com/OAI/OpenAPI-Specification/blob/3.0.0/versions/2.0.md#operationObject + + Example: + + service EchoService { + rpc Echo(SimpleMessage) returns (SimpleMessage) { + option (google.api.http) = { + get: "/v1/example/echo/{id}" + }; + + option (grpc.gateway.temporalio.api.dependencies.protoc_gen_openapiv2.options.openapiv2_operation) = { + summary: "Get a message."; + operation_id: "getMessage"; + tags: "echo"; + responses: { + key: "200" + value: { + description: "OK"; + } + } + }; + } + } + """ + + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + class ResponsesEntry(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + KEY_FIELD_NUMBER: builtins.int + VALUE_FIELD_NUMBER: builtins.int + key: builtins.str + @property + def value(self) -> global___Response: ... + def __init__( + self, + *, + key: builtins.str = ..., + value: global___Response | None = ..., + ) -> None: ... + def HasField( + self, field_name: typing_extensions.Literal["value", b"value"] + ) -> builtins.bool: ... + def ClearField( + self, + field_name: typing_extensions.Literal["key", b"key", "value", b"value"], + ) -> None: ... + + class ExtensionsEntry(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + KEY_FIELD_NUMBER: builtins.int + VALUE_FIELD_NUMBER: builtins.int + key: builtins.str + @property + def value(self) -> google.protobuf.struct_pb2.Value: ... + def __init__( + self, + *, + key: builtins.str = ..., + value: google.protobuf.struct_pb2.Value | None = ..., + ) -> None: ... + def HasField( + self, field_name: typing_extensions.Literal["value", b"value"] + ) -> builtins.bool: ... + def ClearField( + self, + field_name: typing_extensions.Literal["key", b"key", "value", b"value"], + ) -> None: ... + + TAGS_FIELD_NUMBER: builtins.int + SUMMARY_FIELD_NUMBER: builtins.int + DESCRIPTION_FIELD_NUMBER: builtins.int + EXTERNAL_DOCS_FIELD_NUMBER: builtins.int + OPERATION_ID_FIELD_NUMBER: builtins.int + CONSUMES_FIELD_NUMBER: builtins.int + PRODUCES_FIELD_NUMBER: builtins.int + RESPONSES_FIELD_NUMBER: builtins.int + SCHEMES_FIELD_NUMBER: builtins.int + DEPRECATED_FIELD_NUMBER: builtins.int + SECURITY_FIELD_NUMBER: builtins.int + EXTENSIONS_FIELD_NUMBER: builtins.int + PARAMETERS_FIELD_NUMBER: builtins.int + @property + def tags( + self, + ) -> google.protobuf.internal.containers.RepeatedScalarFieldContainer[builtins.str]: + """A list of tags for API documentation control. Tags can be used for logical + grouping of operations by resources or any other qualifier. + """ + summary: builtins.str + """A short summary of what the operation does. For maximum readability in the + swagger-ui, this field SHOULD be less than 120 characters. + """ + description: builtins.str + """A verbose explanation of the operation behavior. GFM syntax can be used for + rich text representation. + """ + @property + def external_docs(self) -> global___ExternalDocumentation: + """Additional external documentation for this operation.""" + operation_id: builtins.str + """Unique string used to identify the operation. The id MUST be unique among + all operations described in the API. Tools and libraries MAY use the + operationId to uniquely identify an operation, therefore, it is recommended + to follow common programming naming conventions. + """ + @property + def consumes( + self, + ) -> google.protobuf.internal.containers.RepeatedScalarFieldContainer[builtins.str]: + """A list of MIME types the operation can consume. This overrides the consumes + definition at the OpenAPI Object. An empty value MAY be used to clear the + global definition. Value MUST be as described under Mime Types. + """ + @property + def produces( + self, + ) -> google.protobuf.internal.containers.RepeatedScalarFieldContainer[builtins.str]: + """A list of MIME types the operation can produce. This overrides the produces + definition at the OpenAPI Object. An empty value MAY be used to clear the + global definition. Value MUST be as described under Mime Types. + """ + @property + def responses( + self, + ) -> google.protobuf.internal.containers.MessageMap[ + builtins.str, global___Response + ]: + """The list of possible responses as they are returned from executing this + operation. + """ + @property + def schemes( + self, + ) -> google.protobuf.internal.containers.RepeatedScalarFieldContainer[ + global___Scheme.ValueType + ]: + """The transfer protocol for the operation. Values MUST be from the list: + "http", "https", "ws", "wss". The value overrides the OpenAPI Object + schemes definition. + """ + deprecated: builtins.bool + """Declares this operation to be deprecated. Usage of the declared operation + should be refrained. Default value is false. + """ + @property + def security( + self, + ) -> google.protobuf.internal.containers.RepeatedCompositeFieldContainer[ + global___SecurityRequirement + ]: + """A declaration of which security schemes are applied for this operation. The + list of values describes alternative security schemes that can be used + (that is, there is a logical OR between the security requirements). This + definition overrides any declared top-level security. To remove a top-level + security declaration, an empty array can be used. + """ + @property + def extensions( + self, + ) -> google.protobuf.internal.containers.MessageMap[ + builtins.str, google.protobuf.struct_pb2.Value + ]: + """Custom properties that start with "x-" such as "x-foo" used to describe + extra functionality that is not covered by the standard OpenAPI Specification. + See: https://swagger.io/docs/specification/2-0/swagger-extensions/ + """ + @property + def parameters(self) -> global___Parameters: + """Custom parameters such as HTTP request headers. + See: https://swagger.io/docs/specification/2-0/describing-parameters/ + and https://swagger.io/specification/v2/#parameter-object. + """ + def __init__( + self, + *, + tags: collections.abc.Iterable[builtins.str] | None = ..., + summary: builtins.str = ..., + description: builtins.str = ..., + external_docs: global___ExternalDocumentation | None = ..., + operation_id: builtins.str = ..., + consumes: collections.abc.Iterable[builtins.str] | None = ..., + produces: collections.abc.Iterable[builtins.str] | None = ..., + responses: collections.abc.Mapping[builtins.str, global___Response] + | None = ..., + schemes: collections.abc.Iterable[global___Scheme.ValueType] | None = ..., + deprecated: builtins.bool = ..., + security: collections.abc.Iterable[global___SecurityRequirement] | None = ..., + extensions: collections.abc.Mapping[ + builtins.str, google.protobuf.struct_pb2.Value + ] + | None = ..., + parameters: global___Parameters | None = ..., + ) -> None: ... + def HasField( + self, + field_name: typing_extensions.Literal[ + "external_docs", b"external_docs", "parameters", b"parameters" + ], + ) -> builtins.bool: ... + def ClearField( + self, + field_name: typing_extensions.Literal[ + "consumes", + b"consumes", + "deprecated", + b"deprecated", + "description", + b"description", + "extensions", + b"extensions", + "external_docs", + b"external_docs", + "operation_id", + b"operation_id", + "parameters", + b"parameters", + "produces", + b"produces", + "responses", + b"responses", + "schemes", + b"schemes", + "security", + b"security", + "summary", + b"summary", + "tags", + b"tags", + ], + ) -> None: ... + +global___Operation = Operation + +class Parameters(google.protobuf.message.Message): + """`Parameters` is a representation of OpenAPI v2 specification's parameters object. + Note: This technically breaks compatibility with the OpenAPI 2 definition structure as we only + allow header parameters to be set here since we do not want users specifying custom non-header + parameters beyond those inferred from the Protobuf schema. + See: https://swagger.io/specification/v2/#parameter-object + """ + + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + HEADERS_FIELD_NUMBER: builtins.int + @property + def headers( + self, + ) -> google.protobuf.internal.containers.RepeatedCompositeFieldContainer[ + global___HeaderParameter + ]: + """`Headers` is one or more HTTP header parameter. + See: https://swagger.io/docs/specification/2-0/describing-parameters/#header-parameters + """ + def __init__( + self, + *, + headers: collections.abc.Iterable[global___HeaderParameter] | None = ..., + ) -> None: ... + def ClearField( + self, field_name: typing_extensions.Literal["headers", b"headers"] + ) -> None: ... + +global___Parameters = Parameters + +class HeaderParameter(google.protobuf.message.Message): + """`HeaderParameter` a HTTP header parameter. + See: https://swagger.io/specification/v2/#parameter-object + """ + + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + class _Type: + ValueType = typing.NewType("ValueType", builtins.int) + V: typing_extensions.TypeAlias = ValueType + + class _TypeEnumTypeWrapper( + google.protobuf.internal.enum_type_wrapper._EnumTypeWrapper[ + HeaderParameter._Type.ValueType + ], + builtins.type, + ): # noqa: F821 + DESCRIPTOR: google.protobuf.descriptor.EnumDescriptor + UNKNOWN: HeaderParameter._Type.ValueType # 0 + STRING: HeaderParameter._Type.ValueType # 1 + NUMBER: HeaderParameter._Type.ValueType # 2 + INTEGER: HeaderParameter._Type.ValueType # 3 + BOOLEAN: HeaderParameter._Type.ValueType # 4 + + class Type(_Type, metaclass=_TypeEnumTypeWrapper): + """`Type` is a supported HTTP header type. + See https://swagger.io/specification/v2/#parameterType. + """ + + UNKNOWN: HeaderParameter.Type.ValueType # 0 + STRING: HeaderParameter.Type.ValueType # 1 + NUMBER: HeaderParameter.Type.ValueType # 2 + INTEGER: HeaderParameter.Type.ValueType # 3 + BOOLEAN: HeaderParameter.Type.ValueType # 4 + + NAME_FIELD_NUMBER: builtins.int + DESCRIPTION_FIELD_NUMBER: builtins.int + TYPE_FIELD_NUMBER: builtins.int + FORMAT_FIELD_NUMBER: builtins.int + REQUIRED_FIELD_NUMBER: builtins.int + name: builtins.str + """`Name` is the header name.""" + description: builtins.str + """`Description` is a short description of the header.""" + type: global___HeaderParameter.Type.ValueType + """`Type` is the type of the object. The value MUST be one of "string", "number", "integer", or "boolean". The "array" type is not supported. + See: https://swagger.io/specification/v2/#parameterType. + """ + format: builtins.str + """`Format` The extending format for the previously mentioned type.""" + required: builtins.bool + """`Required` indicates if the header is optional""" + def __init__( + self, + *, + name: builtins.str = ..., + description: builtins.str = ..., + type: global___HeaderParameter.Type.ValueType = ..., + format: builtins.str = ..., + required: builtins.bool = ..., + ) -> None: ... + def ClearField( + self, + field_name: typing_extensions.Literal[ + "description", + b"description", + "format", + b"format", + "name", + b"name", + "required", + b"required", + "type", + b"type", + ], + ) -> None: ... + +global___HeaderParameter = HeaderParameter + +class Header(google.protobuf.message.Message): + """`Header` is a representation of OpenAPI v2 specification's Header object. + + See: https://github.com/OAI/OpenAPI-Specification/blob/3.0.0/versions/2.0.md#headerObject + """ + + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + DESCRIPTION_FIELD_NUMBER: builtins.int + TYPE_FIELD_NUMBER: builtins.int + FORMAT_FIELD_NUMBER: builtins.int + DEFAULT_FIELD_NUMBER: builtins.int + PATTERN_FIELD_NUMBER: builtins.int + description: builtins.str + """`Description` is a short description of the header.""" + type: builtins.str + """The type of the object. The value MUST be one of "string", "number", "integer", or "boolean". The "array" type is not supported.""" + format: builtins.str + """`Format` The extending format for the previously mentioned type.""" + default: builtins.str + """`Default` Declares the value of the header that the server will use if none is provided. + See: https://tools.ietf.org/html/draft-fge-json-schema-validation-00#section-6.2. + Unlike JSON Schema this value MUST conform to the defined type for the header. + """ + pattern: builtins.str + """'Pattern' See https://tools.ietf.org/html/draft-fge-json-schema-validation-00#section-5.2.3.""" + def __init__( + self, + *, + description: builtins.str = ..., + type: builtins.str = ..., + format: builtins.str = ..., + default: builtins.str = ..., + pattern: builtins.str = ..., + ) -> None: ... + def ClearField( + self, + field_name: typing_extensions.Literal[ + "default", + b"default", + "description", + b"description", + "format", + b"format", + "pattern", + b"pattern", + "type", + b"type", + ], + ) -> None: ... + +global___Header = Header + +class Response(google.protobuf.message.Message): + """`Response` is a representation of OpenAPI v2 specification's Response object. + + See: https://github.com/OAI/OpenAPI-Specification/blob/3.0.0/versions/2.0.md#responseObject + """ + + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + class HeadersEntry(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + KEY_FIELD_NUMBER: builtins.int + VALUE_FIELD_NUMBER: builtins.int + key: builtins.str + @property + def value(self) -> global___Header: ... + def __init__( + self, + *, + key: builtins.str = ..., + value: global___Header | None = ..., + ) -> None: ... + def HasField( + self, field_name: typing_extensions.Literal["value", b"value"] + ) -> builtins.bool: ... + def ClearField( + self, + field_name: typing_extensions.Literal["key", b"key", "value", b"value"], + ) -> None: ... + + class ExamplesEntry(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + KEY_FIELD_NUMBER: builtins.int + VALUE_FIELD_NUMBER: builtins.int + key: builtins.str + value: builtins.str + def __init__( + self, + *, + key: builtins.str = ..., + value: builtins.str = ..., + ) -> None: ... + def ClearField( + self, + field_name: typing_extensions.Literal["key", b"key", "value", b"value"], + ) -> None: ... + + class ExtensionsEntry(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + KEY_FIELD_NUMBER: builtins.int + VALUE_FIELD_NUMBER: builtins.int + key: builtins.str + @property + def value(self) -> google.protobuf.struct_pb2.Value: ... + def __init__( + self, + *, + key: builtins.str = ..., + value: google.protobuf.struct_pb2.Value | None = ..., + ) -> None: ... + def HasField( + self, field_name: typing_extensions.Literal["value", b"value"] + ) -> builtins.bool: ... + def ClearField( + self, + field_name: typing_extensions.Literal["key", b"key", "value", b"value"], + ) -> None: ... + + DESCRIPTION_FIELD_NUMBER: builtins.int + SCHEMA_FIELD_NUMBER: builtins.int + HEADERS_FIELD_NUMBER: builtins.int + EXAMPLES_FIELD_NUMBER: builtins.int + EXTENSIONS_FIELD_NUMBER: builtins.int + description: builtins.str + """`Description` is a short description of the response. + GFM syntax can be used for rich text representation. + """ + @property + def schema(self) -> global___Schema: + """`Schema` optionally defines the structure of the response. + If `Schema` is not provided, it means there is no content to the response. + """ + @property + def headers( + self, + ) -> google.protobuf.internal.containers.MessageMap[builtins.str, global___Header]: + """`Headers` A list of headers that are sent with the response. + `Header` name is expected to be a string in the canonical format of the MIME header key + See: https://golang.org/pkg/net/textproto/#CanonicalMIMEHeaderKey + """ + @property + def examples( + self, + ) -> google.protobuf.internal.containers.ScalarMap[builtins.str, builtins.str]: + """`Examples` gives per-mimetype response examples. + See: https://github.com/OAI/OpenAPI-Specification/blob/3.0.0/versions/2.0.md#example-object + """ + @property + def extensions( + self, + ) -> google.protobuf.internal.containers.MessageMap[ + builtins.str, google.protobuf.struct_pb2.Value + ]: + """Custom properties that start with "x-" such as "x-foo" used to describe + extra functionality that is not covered by the standard OpenAPI Specification. + See: https://swagger.io/docs/specification/2-0/swagger-extensions/ + """ + def __init__( + self, + *, + description: builtins.str = ..., + schema: global___Schema | None = ..., + headers: collections.abc.Mapping[builtins.str, global___Header] | None = ..., + examples: collections.abc.Mapping[builtins.str, builtins.str] | None = ..., + extensions: collections.abc.Mapping[ + builtins.str, google.protobuf.struct_pb2.Value + ] + | None = ..., + ) -> None: ... + def HasField( + self, field_name: typing_extensions.Literal["schema", b"schema"] + ) -> builtins.bool: ... + def ClearField( + self, + field_name: typing_extensions.Literal[ + "description", + b"description", + "examples", + b"examples", + "extensions", + b"extensions", + "headers", + b"headers", + "schema", + b"schema", + ], + ) -> None: ... + +global___Response = Response + +class Info(google.protobuf.message.Message): + """`Info` is a representation of OpenAPI v2 specification's Info object. + + See: https://github.com/OAI/OpenAPI-Specification/blob/3.0.0/versions/2.0.md#infoObject + + Example: + + option (grpc.gateway.temporalio.api.dependencies.protoc_gen_openapiv2.options.openapiv2_swagger) = { + info: { + title: "Echo API"; + version: "1.0"; + description: ""; + contact: { + name: "gRPC-Gateway project"; + url: "https://github.com/grpc-ecosystem/grpc-gateway"; + email: "none@example.com"; + }; + license: { + name: "BSD 3-Clause License"; + url: "https://github.com/grpc-ecosystem/grpc-gateway/blob/main/LICENSE"; + }; + }; + ... + }; + """ + + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + class ExtensionsEntry(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + KEY_FIELD_NUMBER: builtins.int + VALUE_FIELD_NUMBER: builtins.int + key: builtins.str + @property + def value(self) -> google.protobuf.struct_pb2.Value: ... + def __init__( + self, + *, + key: builtins.str = ..., + value: google.protobuf.struct_pb2.Value | None = ..., + ) -> None: ... + def HasField( + self, field_name: typing_extensions.Literal["value", b"value"] + ) -> builtins.bool: ... + def ClearField( + self, + field_name: typing_extensions.Literal["key", b"key", "value", b"value"], + ) -> None: ... + + TITLE_FIELD_NUMBER: builtins.int + DESCRIPTION_FIELD_NUMBER: builtins.int + TERMS_OF_SERVICE_FIELD_NUMBER: builtins.int + CONTACT_FIELD_NUMBER: builtins.int + LICENSE_FIELD_NUMBER: builtins.int + VERSION_FIELD_NUMBER: builtins.int + EXTENSIONS_FIELD_NUMBER: builtins.int + title: builtins.str + """The title of the application.""" + description: builtins.str + """A short description of the application. GFM syntax can be used for rich + text representation. + """ + terms_of_service: builtins.str + """The Terms of Service for the API.""" + @property + def contact(self) -> global___Contact: + """The contact information for the exposed API.""" + @property + def license(self) -> global___License: + """The license information for the exposed API.""" + version: builtins.str + """Provides the version of the application API (not to be confused + with the specification version). + """ + @property + def extensions( + self, + ) -> google.protobuf.internal.containers.MessageMap[ + builtins.str, google.protobuf.struct_pb2.Value + ]: + """Custom properties that start with "x-" such as "x-foo" used to describe + extra functionality that is not covered by the standard OpenAPI Specification. + See: https://swagger.io/docs/specification/2-0/swagger-extensions/ + """ + def __init__( + self, + *, + title: builtins.str = ..., + description: builtins.str = ..., + terms_of_service: builtins.str = ..., + contact: global___Contact | None = ..., + license: global___License | None = ..., + version: builtins.str = ..., + extensions: collections.abc.Mapping[ + builtins.str, google.protobuf.struct_pb2.Value + ] + | None = ..., + ) -> None: ... + def HasField( + self, + field_name: typing_extensions.Literal[ + "contact", b"contact", "license", b"license" + ], + ) -> builtins.bool: ... + def ClearField( + self, + field_name: typing_extensions.Literal[ + "contact", + b"contact", + "description", + b"description", + "extensions", + b"extensions", + "license", + b"license", + "terms_of_service", + b"terms_of_service", + "title", + b"title", + "version", + b"version", + ], + ) -> None: ... + +global___Info = Info + +class Contact(google.protobuf.message.Message): + """`Contact` is a representation of OpenAPI v2 specification's Contact object. + + See: https://github.com/OAI/OpenAPI-Specification/blob/3.0.0/versions/2.0.md#contactObject + + Example: + + option (grpc.gateway.temporalio.api.dependencies.protoc_gen_openapiv2.options.openapiv2_swagger) = { + info: { + ... + contact: { + name: "gRPC-Gateway project"; + url: "https://github.com/grpc-ecosystem/grpc-gateway"; + email: "none@example.com"; + }; + ... + }; + ... + }; + """ + + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + NAME_FIELD_NUMBER: builtins.int + URL_FIELD_NUMBER: builtins.int + EMAIL_FIELD_NUMBER: builtins.int + name: builtins.str + """The identifying name of the contact person/organization.""" + url: builtins.str + """The URL pointing to the contact information. MUST be in the format of a + URL. + """ + email: builtins.str + """The email address of the contact person/organization. MUST be in the format + of an email address. + """ + def __init__( + self, + *, + name: builtins.str = ..., + url: builtins.str = ..., + email: builtins.str = ..., + ) -> None: ... + def ClearField( + self, + field_name: typing_extensions.Literal[ + "email", b"email", "name", b"name", "url", b"url" + ], + ) -> None: ... + +global___Contact = Contact + +class License(google.protobuf.message.Message): + """`License` is a representation of OpenAPI v2 specification's License object. + + See: https://github.com/OAI/OpenAPI-Specification/blob/3.0.0/versions/2.0.md#licenseObject + + Example: + + option (grpc.gateway.temporalio.api.dependencies.protoc_gen_openapiv2.options.openapiv2_swagger) = { + info: { + ... + license: { + name: "BSD 3-Clause License"; + url: "https://github.com/grpc-ecosystem/grpc-gateway/blob/main/LICENSE"; + }; + ... + }; + ... + }; + """ + + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + NAME_FIELD_NUMBER: builtins.int + URL_FIELD_NUMBER: builtins.int + name: builtins.str + """The license name used for the API.""" + url: builtins.str + """A URL to the license used for the API. MUST be in the format of a URL.""" + def __init__( + self, + *, + name: builtins.str = ..., + url: builtins.str = ..., + ) -> None: ... + def ClearField( + self, field_name: typing_extensions.Literal["name", b"name", "url", b"url"] + ) -> None: ... + +global___License = License + +class ExternalDocumentation(google.protobuf.message.Message): + """`ExternalDocumentation` is a representation of OpenAPI v2 specification's + ExternalDocumentation object. + + See: https://github.com/OAI/OpenAPI-Specification/blob/3.0.0/versions/2.0.md#externalDocumentationObject + + Example: + + option (grpc.gateway.temporalio.api.dependencies.protoc_gen_openapiv2.options.openapiv2_swagger) = { + ... + external_docs: { + description: "More about gRPC-Gateway"; + url: "https://github.com/grpc-ecosystem/grpc-gateway"; + } + ... + }; + """ + + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + DESCRIPTION_FIELD_NUMBER: builtins.int + URL_FIELD_NUMBER: builtins.int + description: builtins.str + """A short description of the target documentation. GFM syntax can be used for + rich text representation. + """ + url: builtins.str + """The URL for the target documentation. Value MUST be in the format + of a URL. + """ + def __init__( + self, + *, + description: builtins.str = ..., + url: builtins.str = ..., + ) -> None: ... + def ClearField( + self, + field_name: typing_extensions.Literal[ + "description", b"description", "url", b"url" + ], + ) -> None: ... + +global___ExternalDocumentation = ExternalDocumentation + +class Schema(google.protobuf.message.Message): + """`Schema` is a representation of OpenAPI v2 specification's Schema object. + + See: https://github.com/OAI/OpenAPI-Specification/blob/3.0.0/versions/2.0.md#schemaObject + """ + + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + JSON_SCHEMA_FIELD_NUMBER: builtins.int + DISCRIMINATOR_FIELD_NUMBER: builtins.int + READ_ONLY_FIELD_NUMBER: builtins.int + EXTERNAL_DOCS_FIELD_NUMBER: builtins.int + EXAMPLE_FIELD_NUMBER: builtins.int + @property + def json_schema(self) -> global___JSONSchema: ... + discriminator: builtins.str + """Adds support for polymorphism. The discriminator is the schema property + name that is used to differentiate between other schema that inherit this + schema. The property name used MUST be defined at this schema and it MUST + be in the required property list. When used, the value MUST be the name of + this schema or any schema that inherits it. + """ + read_only: builtins.bool + """Relevant only for Schema "properties" definitions. Declares the property as + "read only". This means that it MAY be sent as part of a response but MUST + NOT be sent as part of the request. Properties marked as readOnly being + true SHOULD NOT be in the required list of the defined schema. Default + value is false. + """ + @property + def external_docs(self) -> global___ExternalDocumentation: + """Additional external documentation for this schema.""" + example: builtins.str + """A free-form property to include an example of an instance for this schema in JSON. + This is copied verbatim to the output. + """ + def __init__( + self, + *, + json_schema: global___JSONSchema | None = ..., + discriminator: builtins.str = ..., + read_only: builtins.bool = ..., + external_docs: global___ExternalDocumentation | None = ..., + example: builtins.str = ..., + ) -> None: ... + def HasField( + self, + field_name: typing_extensions.Literal[ + "external_docs", b"external_docs", "json_schema", b"json_schema" + ], + ) -> builtins.bool: ... + def ClearField( + self, + field_name: typing_extensions.Literal[ + "discriminator", + b"discriminator", + "example", + b"example", + "external_docs", + b"external_docs", + "json_schema", + b"json_schema", + "read_only", + b"read_only", + ], + ) -> None: ... + +global___Schema = Schema + +class EnumSchema(google.protobuf.message.Message): + """`EnumSchema` is subset of fields from the OpenAPI v2 specification's Schema object. + Only fields that are applicable to Enums are included + See: https://github.com/OAI/OpenAPI-Specification/blob/3.0.0/versions/2.0.md#schemaObject + + Example: + + option (grpc.gateway.temporalio.api.dependencies.protoc_gen_openapiv2.options.openapiv2_enum) = { + ... + title: "MyEnum"; + description:"This is my nice enum"; + example: "ZERO"; + required: true; + ... + }; + """ + + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + class ExtensionsEntry(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + KEY_FIELD_NUMBER: builtins.int + VALUE_FIELD_NUMBER: builtins.int + key: builtins.str + @property + def value(self) -> google.protobuf.struct_pb2.Value: ... + def __init__( + self, + *, + key: builtins.str = ..., + value: google.protobuf.struct_pb2.Value | None = ..., + ) -> None: ... + def HasField( + self, field_name: typing_extensions.Literal["value", b"value"] + ) -> builtins.bool: ... + def ClearField( + self, + field_name: typing_extensions.Literal["key", b"key", "value", b"value"], + ) -> None: ... + + DESCRIPTION_FIELD_NUMBER: builtins.int + DEFAULT_FIELD_NUMBER: builtins.int + TITLE_FIELD_NUMBER: builtins.int + REQUIRED_FIELD_NUMBER: builtins.int + READ_ONLY_FIELD_NUMBER: builtins.int + EXTERNAL_DOCS_FIELD_NUMBER: builtins.int + EXAMPLE_FIELD_NUMBER: builtins.int + REF_FIELD_NUMBER: builtins.int + EXTENSIONS_FIELD_NUMBER: builtins.int + description: builtins.str + """A short description of the schema.""" + default: builtins.str + title: builtins.str + """The title of the schema.""" + required: builtins.bool + read_only: builtins.bool + @property + def external_docs(self) -> global___ExternalDocumentation: + """Additional external documentation for this schema.""" + example: builtins.str + ref: builtins.str + """Ref is used to define an external reference to include in the message. + This could be a fully qualified proto message reference, and that type must + be imported into the protofile. If no message is identified, the Ref will + be used verbatim in the output. + For example: + `ref: ".google.protobuf.Timestamp"`. + """ + @property + def extensions( + self, + ) -> google.protobuf.internal.containers.MessageMap[ + builtins.str, google.protobuf.struct_pb2.Value + ]: + """Custom properties that start with "x-" such as "x-foo" used to describe + extra functionality that is not covered by the standard OpenAPI Specification. + See: https://swagger.io/docs/specification/2-0/swagger-extensions/ + """ + def __init__( + self, + *, + description: builtins.str = ..., + default: builtins.str = ..., + title: builtins.str = ..., + required: builtins.bool = ..., + read_only: builtins.bool = ..., + external_docs: global___ExternalDocumentation | None = ..., + example: builtins.str = ..., + ref: builtins.str = ..., + extensions: collections.abc.Mapping[ + builtins.str, google.protobuf.struct_pb2.Value + ] + | None = ..., + ) -> None: ... + def HasField( + self, field_name: typing_extensions.Literal["external_docs", b"external_docs"] + ) -> builtins.bool: ... + def ClearField( + self, + field_name: typing_extensions.Literal[ + "default", + b"default", + "description", + b"description", + "example", + b"example", + "extensions", + b"extensions", + "external_docs", + b"external_docs", + "read_only", + b"read_only", + "ref", + b"ref", + "required", + b"required", + "title", + b"title", + ], + ) -> None: ... + +global___EnumSchema = EnumSchema + +class JSONSchema(google.protobuf.message.Message): + """`JSONSchema` represents properties from JSON Schema taken, and as used, in + the OpenAPI v2 spec. + + This includes changes made by OpenAPI v2. + + See: https://github.com/OAI/OpenAPI-Specification/blob/3.0.0/versions/2.0.md#schemaObject + + See also: https://cswr.github.io/JsonSchema/spec/basic_types/, + https://github.com/json-schema-org/json-schema-spec/blob/master/schema.json + + Example: + + message SimpleMessage { + option (grpc.gateway.temporalio.api.dependencies.protoc_gen_openapiv2.options.openapiv2_schema) = { + json_schema: { + title: "SimpleMessage" + description: "A simple message." + required: ["id"] + } + }; + + // Id represents the message identifier. + string id = 1; [ + (grpc.gateway.temporalio.api.dependencies.protoc_gen_openapiv2.options.openapiv2_field) = { + description: "The unique identifier of the simple message." + }]; + } + """ + + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + class _JSONSchemaSimpleTypes: + ValueType = typing.NewType("ValueType", builtins.int) + V: typing_extensions.TypeAlias = ValueType + + class _JSONSchemaSimpleTypesEnumTypeWrapper( + google.protobuf.internal.enum_type_wrapper._EnumTypeWrapper[ + JSONSchema._JSONSchemaSimpleTypes.ValueType + ], + builtins.type, + ): # noqa: F821 + DESCRIPTOR: google.protobuf.descriptor.EnumDescriptor + UNKNOWN: JSONSchema._JSONSchemaSimpleTypes.ValueType # 0 + ARRAY: JSONSchema._JSONSchemaSimpleTypes.ValueType # 1 + BOOLEAN: JSONSchema._JSONSchemaSimpleTypes.ValueType # 2 + INTEGER: JSONSchema._JSONSchemaSimpleTypes.ValueType # 3 + NULL: JSONSchema._JSONSchemaSimpleTypes.ValueType # 4 + NUMBER: JSONSchema._JSONSchemaSimpleTypes.ValueType # 5 + OBJECT: JSONSchema._JSONSchemaSimpleTypes.ValueType # 6 + STRING: JSONSchema._JSONSchemaSimpleTypes.ValueType # 7 + + class JSONSchemaSimpleTypes( + _JSONSchemaSimpleTypes, metaclass=_JSONSchemaSimpleTypesEnumTypeWrapper + ): ... + UNKNOWN: JSONSchema.JSONSchemaSimpleTypes.ValueType # 0 + ARRAY: JSONSchema.JSONSchemaSimpleTypes.ValueType # 1 + BOOLEAN: JSONSchema.JSONSchemaSimpleTypes.ValueType # 2 + INTEGER: JSONSchema.JSONSchemaSimpleTypes.ValueType # 3 + NULL: JSONSchema.JSONSchemaSimpleTypes.ValueType # 4 + NUMBER: JSONSchema.JSONSchemaSimpleTypes.ValueType # 5 + OBJECT: JSONSchema.JSONSchemaSimpleTypes.ValueType # 6 + STRING: JSONSchema.JSONSchemaSimpleTypes.ValueType # 7 + + class FieldConfiguration(google.protobuf.message.Message): + """'FieldConfiguration' provides additional field level properties used when generating the OpenAPI v2 file. + These properties are not defined by OpenAPIv2, but they are used to control the generation. + """ + + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + PATH_PARAM_NAME_FIELD_NUMBER: builtins.int + path_param_name: builtins.str + """Alternative parameter name when used as path parameter. If set, this will + be used as the complete parameter name when this field is used as a path + parameter. Use this to avoid having auto generated path parameter names + for overlapping paths. + """ + def __init__( + self, + *, + path_param_name: builtins.str = ..., + ) -> None: ... + def ClearField( + self, + field_name: typing_extensions.Literal[ + "path_param_name", b"path_param_name" + ], + ) -> None: ... + + class ExtensionsEntry(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + KEY_FIELD_NUMBER: builtins.int + VALUE_FIELD_NUMBER: builtins.int + key: builtins.str + @property + def value(self) -> google.protobuf.struct_pb2.Value: ... + def __init__( + self, + *, + key: builtins.str = ..., + value: google.protobuf.struct_pb2.Value | None = ..., + ) -> None: ... + def HasField( + self, field_name: typing_extensions.Literal["value", b"value"] + ) -> builtins.bool: ... + def ClearField( + self, + field_name: typing_extensions.Literal["key", b"key", "value", b"value"], + ) -> None: ... + + REF_FIELD_NUMBER: builtins.int + TITLE_FIELD_NUMBER: builtins.int + DESCRIPTION_FIELD_NUMBER: builtins.int + DEFAULT_FIELD_NUMBER: builtins.int + READ_ONLY_FIELD_NUMBER: builtins.int + EXAMPLE_FIELD_NUMBER: builtins.int + MULTIPLE_OF_FIELD_NUMBER: builtins.int + MAXIMUM_FIELD_NUMBER: builtins.int + EXCLUSIVE_MAXIMUM_FIELD_NUMBER: builtins.int + MINIMUM_FIELD_NUMBER: builtins.int + EXCLUSIVE_MINIMUM_FIELD_NUMBER: builtins.int + MAX_LENGTH_FIELD_NUMBER: builtins.int + MIN_LENGTH_FIELD_NUMBER: builtins.int + PATTERN_FIELD_NUMBER: builtins.int + MAX_ITEMS_FIELD_NUMBER: builtins.int + MIN_ITEMS_FIELD_NUMBER: builtins.int + UNIQUE_ITEMS_FIELD_NUMBER: builtins.int + MAX_PROPERTIES_FIELD_NUMBER: builtins.int + MIN_PROPERTIES_FIELD_NUMBER: builtins.int + REQUIRED_FIELD_NUMBER: builtins.int + ARRAY_FIELD_NUMBER: builtins.int + TYPE_FIELD_NUMBER: builtins.int + FORMAT_FIELD_NUMBER: builtins.int + ENUM_FIELD_NUMBER: builtins.int + FIELD_CONFIGURATION_FIELD_NUMBER: builtins.int + EXTENSIONS_FIELD_NUMBER: builtins.int + ref: builtins.str + """Ref is used to define an external reference to include in the message. + This could be a fully qualified proto message reference, and that type must + be imported into the protofile. If no message is identified, the Ref will + be used verbatim in the output. + For example: + `ref: ".google.protobuf.Timestamp"`. + """ + title: builtins.str + """The title of the schema.""" + description: builtins.str + """A short description of the schema.""" + default: builtins.str + read_only: builtins.bool + example: builtins.str + """A free-form property to include a JSON example of this field. This is copied + verbatim to the output swagger.json. Quotes must be escaped. + This property is the same for 2.0 and 3.0.0 https://github.com/OAI/OpenAPI-Specification/blob/3.0.0/versions/3.0.0.md#schemaObject https://github.com/OAI/OpenAPI-Specification/blob/3.0.0/versions/2.0.md#schemaObject + """ + multiple_of: builtins.float + maximum: builtins.float + """Maximum represents an inclusive upper limit for a numeric instance. The + value of MUST be a number, + """ + exclusive_maximum: builtins.bool + minimum: builtins.float + """minimum represents an inclusive lower limit for a numeric instance. The + value of MUST be a number, + """ + exclusive_minimum: builtins.bool + max_length: builtins.int + min_length: builtins.int + pattern: builtins.str + max_items: builtins.int + min_items: builtins.int + unique_items: builtins.bool + max_properties: builtins.int + min_properties: builtins.int + @property + def required( + self, + ) -> google.protobuf.internal.containers.RepeatedScalarFieldContainer[ + builtins.str + ]: ... + @property + def array( + self, + ) -> google.protobuf.internal.containers.RepeatedScalarFieldContainer[builtins.str]: + """Items in 'array' must be unique.""" + @property + def type( + self, + ) -> google.protobuf.internal.containers.RepeatedScalarFieldContainer[ + global___JSONSchema.JSONSchemaSimpleTypes.ValueType + ]: ... + format: builtins.str + """`Format`""" + @property + def enum( + self, + ) -> google.protobuf.internal.containers.RepeatedScalarFieldContainer[builtins.str]: + """Items in `enum` must be unique https://tools.ietf.org/html/draft-fge-json-schema-validation-00#section-5.5.1""" + @property + def field_configuration(self) -> global___JSONSchema.FieldConfiguration: + """Additional field level properties used when generating the OpenAPI v2 file.""" + @property + def extensions( + self, + ) -> google.protobuf.internal.containers.MessageMap[ + builtins.str, google.protobuf.struct_pb2.Value + ]: + """Custom properties that start with "x-" such as "x-foo" used to describe + extra functionality that is not covered by the standard OpenAPI Specification. + See: https://swagger.io/docs/specification/2-0/swagger-extensions/ + """ + def __init__( + self, + *, + ref: builtins.str = ..., + title: builtins.str = ..., + description: builtins.str = ..., + default: builtins.str = ..., + read_only: builtins.bool = ..., + example: builtins.str = ..., + multiple_of: builtins.float = ..., + maximum: builtins.float = ..., + exclusive_maximum: builtins.bool = ..., + minimum: builtins.float = ..., + exclusive_minimum: builtins.bool = ..., + max_length: builtins.int = ..., + min_length: builtins.int = ..., + pattern: builtins.str = ..., + max_items: builtins.int = ..., + min_items: builtins.int = ..., + unique_items: builtins.bool = ..., + max_properties: builtins.int = ..., + min_properties: builtins.int = ..., + required: collections.abc.Iterable[builtins.str] | None = ..., + array: collections.abc.Iterable[builtins.str] | None = ..., + type: collections.abc.Iterable[ + global___JSONSchema.JSONSchemaSimpleTypes.ValueType + ] + | None = ..., + format: builtins.str = ..., + enum: collections.abc.Iterable[builtins.str] | None = ..., + field_configuration: global___JSONSchema.FieldConfiguration | None = ..., + extensions: collections.abc.Mapping[ + builtins.str, google.protobuf.struct_pb2.Value + ] + | None = ..., + ) -> None: ... + def HasField( + self, + field_name: typing_extensions.Literal[ + "field_configuration", b"field_configuration" + ], + ) -> builtins.bool: ... + def ClearField( + self, + field_name: typing_extensions.Literal[ + "array", + b"array", + "default", + b"default", + "description", + b"description", + "enum", + b"enum", + "example", + b"example", + "exclusive_maximum", + b"exclusive_maximum", + "exclusive_minimum", + b"exclusive_minimum", + "extensions", + b"extensions", + "field_configuration", + b"field_configuration", + "format", + b"format", + "max_items", + b"max_items", + "max_length", + b"max_length", + "max_properties", + b"max_properties", + "maximum", + b"maximum", + "min_items", + b"min_items", + "min_length", + b"min_length", + "min_properties", + b"min_properties", + "minimum", + b"minimum", + "multiple_of", + b"multiple_of", + "pattern", + b"pattern", + "read_only", + b"read_only", + "ref", + b"ref", + "required", + b"required", + "title", + b"title", + "type", + b"type", + "unique_items", + b"unique_items", + ], + ) -> None: ... + +global___JSONSchema = JSONSchema + +class Tag(google.protobuf.message.Message): + """`Tag` is a representation of OpenAPI v2 specification's Tag object. + + See: https://github.com/OAI/OpenAPI-Specification/blob/3.0.0/versions/2.0.md#tagObject + """ + + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + class ExtensionsEntry(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + KEY_FIELD_NUMBER: builtins.int + VALUE_FIELD_NUMBER: builtins.int + key: builtins.str + @property + def value(self) -> google.protobuf.struct_pb2.Value: ... + def __init__( + self, + *, + key: builtins.str = ..., + value: google.protobuf.struct_pb2.Value | None = ..., + ) -> None: ... + def HasField( + self, field_name: typing_extensions.Literal["value", b"value"] + ) -> builtins.bool: ... + def ClearField( + self, + field_name: typing_extensions.Literal["key", b"key", "value", b"value"], + ) -> None: ... + + NAME_FIELD_NUMBER: builtins.int + DESCRIPTION_FIELD_NUMBER: builtins.int + EXTERNAL_DOCS_FIELD_NUMBER: builtins.int + EXTENSIONS_FIELD_NUMBER: builtins.int + name: builtins.str + """The name of the tag. Use it to allow override of the name of a + global Tag object, then use that name to reference the tag throughout the + OpenAPI file. + """ + description: builtins.str + """A short description for the tag. GFM syntax can be used for rich text + representation. + """ + @property + def external_docs(self) -> global___ExternalDocumentation: + """Additional external documentation for this tag.""" + @property + def extensions( + self, + ) -> google.protobuf.internal.containers.MessageMap[ + builtins.str, google.protobuf.struct_pb2.Value + ]: + """Custom properties that start with "x-" such as "x-foo" used to describe + extra functionality that is not covered by the standard OpenAPI Specification. + See: https://swagger.io/docs/specification/2-0/swagger-extensions/ + """ + def __init__( + self, + *, + name: builtins.str = ..., + description: builtins.str = ..., + external_docs: global___ExternalDocumentation | None = ..., + extensions: collections.abc.Mapping[ + builtins.str, google.protobuf.struct_pb2.Value + ] + | None = ..., + ) -> None: ... + def HasField( + self, field_name: typing_extensions.Literal["external_docs", b"external_docs"] + ) -> builtins.bool: ... + def ClearField( + self, + field_name: typing_extensions.Literal[ + "description", + b"description", + "extensions", + b"extensions", + "external_docs", + b"external_docs", + "name", + b"name", + ], + ) -> None: ... + +global___Tag = Tag + +class SecurityDefinitions(google.protobuf.message.Message): + """`SecurityDefinitions` is a representation of OpenAPI v2 specification's + Security Definitions object. + + See: https://github.com/OAI/OpenAPI-Specification/blob/3.0.0/versions/2.0.md#securityDefinitionsObject + + A declaration of the security schemes available to be used in the + specification. This does not enforce the security schemes on the operations + and only serves to provide the relevant details for each scheme. + """ + + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + class SecurityEntry(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + KEY_FIELD_NUMBER: builtins.int + VALUE_FIELD_NUMBER: builtins.int + key: builtins.str + @property + def value(self) -> global___SecurityScheme: ... + def __init__( + self, + *, + key: builtins.str = ..., + value: global___SecurityScheme | None = ..., + ) -> None: ... + def HasField( + self, field_name: typing_extensions.Literal["value", b"value"] + ) -> builtins.bool: ... + def ClearField( + self, + field_name: typing_extensions.Literal["key", b"key", "value", b"value"], + ) -> None: ... + + SECURITY_FIELD_NUMBER: builtins.int + @property + def security( + self, + ) -> google.protobuf.internal.containers.MessageMap[ + builtins.str, global___SecurityScheme + ]: + """A single security scheme definition, mapping a "name" to the scheme it + defines. + """ + def __init__( + self, + *, + security: collections.abc.Mapping[builtins.str, global___SecurityScheme] + | None = ..., + ) -> None: ... + def ClearField( + self, field_name: typing_extensions.Literal["security", b"security"] + ) -> None: ... + +global___SecurityDefinitions = SecurityDefinitions + +class SecurityScheme(google.protobuf.message.Message): + """`SecurityScheme` is a representation of OpenAPI v2 specification's + Security Scheme object. + + See: https://github.com/OAI/OpenAPI-Specification/blob/3.0.0/versions/2.0.md#securitySchemeObject + + Allows the definition of a security scheme that can be used by the + operations. Supported schemes are basic authentication, an API key (either as + a header or as a query parameter) and OAuth2's common flows (implicit, + password, application and access code). + """ + + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + class _Type: + ValueType = typing.NewType("ValueType", builtins.int) + V: typing_extensions.TypeAlias = ValueType + + class _TypeEnumTypeWrapper( + google.protobuf.internal.enum_type_wrapper._EnumTypeWrapper[ + SecurityScheme._Type.ValueType + ], + builtins.type, + ): # noqa: F821 + DESCRIPTOR: google.protobuf.descriptor.EnumDescriptor + TYPE_INVALID: SecurityScheme._Type.ValueType # 0 + TYPE_BASIC: SecurityScheme._Type.ValueType # 1 + TYPE_API_KEY: SecurityScheme._Type.ValueType # 2 + TYPE_OAUTH2: SecurityScheme._Type.ValueType # 3 + + class Type(_Type, metaclass=_TypeEnumTypeWrapper): + """The type of the security scheme. Valid values are "basic", + "apiKey" or "oauth2". + """ + + TYPE_INVALID: SecurityScheme.Type.ValueType # 0 + TYPE_BASIC: SecurityScheme.Type.ValueType # 1 + TYPE_API_KEY: SecurityScheme.Type.ValueType # 2 + TYPE_OAUTH2: SecurityScheme.Type.ValueType # 3 + + class _In: + ValueType = typing.NewType("ValueType", builtins.int) + V: typing_extensions.TypeAlias = ValueType + + class _InEnumTypeWrapper( + google.protobuf.internal.enum_type_wrapper._EnumTypeWrapper[ + SecurityScheme._In.ValueType + ], + builtins.type, + ): # noqa: F821 + DESCRIPTOR: google.protobuf.descriptor.EnumDescriptor + IN_INVALID: SecurityScheme._In.ValueType # 0 + IN_QUERY: SecurityScheme._In.ValueType # 1 + IN_HEADER: SecurityScheme._In.ValueType # 2 + + class In(_In, metaclass=_InEnumTypeWrapper): + """The location of the API key. Valid values are "query" or "header".""" + + IN_INVALID: SecurityScheme.In.ValueType # 0 + IN_QUERY: SecurityScheme.In.ValueType # 1 + IN_HEADER: SecurityScheme.In.ValueType # 2 + + class _Flow: + ValueType = typing.NewType("ValueType", builtins.int) + V: typing_extensions.TypeAlias = ValueType + + class _FlowEnumTypeWrapper( + google.protobuf.internal.enum_type_wrapper._EnumTypeWrapper[ + SecurityScheme._Flow.ValueType + ], + builtins.type, + ): # noqa: F821 + DESCRIPTOR: google.protobuf.descriptor.EnumDescriptor + FLOW_INVALID: SecurityScheme._Flow.ValueType # 0 + FLOW_IMPLICIT: SecurityScheme._Flow.ValueType # 1 + FLOW_PASSWORD: SecurityScheme._Flow.ValueType # 2 + FLOW_APPLICATION: SecurityScheme._Flow.ValueType # 3 + FLOW_ACCESS_CODE: SecurityScheme._Flow.ValueType # 4 + + class Flow(_Flow, metaclass=_FlowEnumTypeWrapper): + """The flow used by the OAuth2 security scheme. Valid values are + "implicit", "password", "application" or "accessCode". + """ + + FLOW_INVALID: SecurityScheme.Flow.ValueType # 0 + FLOW_IMPLICIT: SecurityScheme.Flow.ValueType # 1 + FLOW_PASSWORD: SecurityScheme.Flow.ValueType # 2 + FLOW_APPLICATION: SecurityScheme.Flow.ValueType # 3 + FLOW_ACCESS_CODE: SecurityScheme.Flow.ValueType # 4 + + class ExtensionsEntry(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + KEY_FIELD_NUMBER: builtins.int + VALUE_FIELD_NUMBER: builtins.int + key: builtins.str + @property + def value(self) -> google.protobuf.struct_pb2.Value: ... + def __init__( + self, + *, + key: builtins.str = ..., + value: google.protobuf.struct_pb2.Value | None = ..., + ) -> None: ... + def HasField( + self, field_name: typing_extensions.Literal["value", b"value"] + ) -> builtins.bool: ... + def ClearField( + self, + field_name: typing_extensions.Literal["key", b"key", "value", b"value"], + ) -> None: ... + + TYPE_FIELD_NUMBER: builtins.int + DESCRIPTION_FIELD_NUMBER: builtins.int + NAME_FIELD_NUMBER: builtins.int + IN_FIELD_NUMBER: builtins.int + FLOW_FIELD_NUMBER: builtins.int + AUTHORIZATION_URL_FIELD_NUMBER: builtins.int + TOKEN_URL_FIELD_NUMBER: builtins.int + SCOPES_FIELD_NUMBER: builtins.int + EXTENSIONS_FIELD_NUMBER: builtins.int + type: global___SecurityScheme.Type.ValueType + """The type of the security scheme. Valid values are "basic", + "apiKey" or "oauth2". + """ + description: builtins.str + """A short description for security scheme.""" + name: builtins.str + """The name of the header or query parameter to be used. + Valid for apiKey. + """ + flow: global___SecurityScheme.Flow.ValueType + """The flow used by the OAuth2 security scheme. Valid values are + "implicit", "password", "application" or "accessCode". + Valid for oauth2. + """ + authorization_url: builtins.str + """The authorization URL to be used for this flow. This SHOULD be in + the form of a URL. + Valid for oauth2/implicit and oauth2/accessCode. + """ + token_url: builtins.str + """The token URL to be used for this flow. This SHOULD be in the + form of a URL. + Valid for oauth2/password, oauth2/application and oauth2/accessCode. + """ + @property + def scopes(self) -> global___Scopes: + """The available scopes for the OAuth2 security scheme. + Valid for oauth2. + """ + @property + def extensions( + self, + ) -> google.protobuf.internal.containers.MessageMap[ + builtins.str, google.protobuf.struct_pb2.Value + ]: + """Custom properties that start with "x-" such as "x-foo" used to describe + extra functionality that is not covered by the standard OpenAPI Specification. + See: https://swagger.io/docs/specification/2-0/swagger-extensions/ + """ + def __init__( + self, + *, + type: global___SecurityScheme.Type.ValueType = ..., + description: builtins.str = ..., + name: builtins.str = ..., + flow: global___SecurityScheme.Flow.ValueType = ..., + authorization_url: builtins.str = ..., + token_url: builtins.str = ..., + scopes: global___Scopes | None = ..., + extensions: collections.abc.Mapping[ + builtins.str, google.protobuf.struct_pb2.Value + ] + | None = ..., + ) -> None: ... + def HasField( + self, field_name: typing_extensions.Literal["scopes", b"scopes"] + ) -> builtins.bool: ... + def ClearField( + self, + field_name: typing_extensions.Literal[ + "authorization_url", + b"authorization_url", + "description", + b"description", + "extensions", + b"extensions", + "flow", + b"flow", + "in", + b"in", + "name", + b"name", + "scopes", + b"scopes", + "token_url", + b"token_url", + "type", + b"type", + ], + ) -> None: ... + +global___SecurityScheme = SecurityScheme + +class SecurityRequirement(google.protobuf.message.Message): + """`SecurityRequirement` is a representation of OpenAPI v2 specification's + Security Requirement object. + + See: https://github.com/OAI/OpenAPI-Specification/blob/3.0.0/versions/2.0.md#securityRequirementObject + + Lists the required security schemes to execute this operation. The object can + have multiple security schemes declared in it which are all required (that + is, there is a logical AND between the schemes). + + The name used for each property MUST correspond to a security scheme + declared in the Security Definitions. + """ + + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + class SecurityRequirementValue(google.protobuf.message.Message): + """If the security scheme is of type "oauth2", then the value is a list of + scope names required for the execution. For other security scheme types, + the array MUST be empty. + """ + + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + SCOPE_FIELD_NUMBER: builtins.int + @property + def scope( + self, + ) -> google.protobuf.internal.containers.RepeatedScalarFieldContainer[ + builtins.str + ]: ... + def __init__( + self, + *, + scope: collections.abc.Iterable[builtins.str] | None = ..., + ) -> None: ... + def ClearField( + self, field_name: typing_extensions.Literal["scope", b"scope"] + ) -> None: ... + + class SecurityRequirementEntry(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + KEY_FIELD_NUMBER: builtins.int + VALUE_FIELD_NUMBER: builtins.int + key: builtins.str + @property + def value(self) -> global___SecurityRequirement.SecurityRequirementValue: ... + def __init__( + self, + *, + key: builtins.str = ..., + value: global___SecurityRequirement.SecurityRequirementValue | None = ..., + ) -> None: ... + def HasField( + self, field_name: typing_extensions.Literal["value", b"value"] + ) -> builtins.bool: ... + def ClearField( + self, + field_name: typing_extensions.Literal["key", b"key", "value", b"value"], + ) -> None: ... + + SECURITY_REQUIREMENT_FIELD_NUMBER: builtins.int + @property + def security_requirement( + self, + ) -> google.protobuf.internal.containers.MessageMap[ + builtins.str, global___SecurityRequirement.SecurityRequirementValue + ]: + """Each name must correspond to a security scheme which is declared in + the Security Definitions. If the security scheme is of type "oauth2", + then the value is a list of scope names required for the execution. + For other security scheme types, the array MUST be empty. + """ + def __init__( + self, + *, + security_requirement: collections.abc.Mapping[ + builtins.str, global___SecurityRequirement.SecurityRequirementValue + ] + | None = ..., + ) -> None: ... + def ClearField( + self, + field_name: typing_extensions.Literal[ + "security_requirement", b"security_requirement" + ], + ) -> None: ... + +global___SecurityRequirement = SecurityRequirement + +class Scopes(google.protobuf.message.Message): + """`Scopes` is a representation of OpenAPI v2 specification's Scopes object. + + See: https://github.com/OAI/OpenAPI-Specification/blob/3.0.0/versions/2.0.md#scopesObject + + Lists the available scopes for an OAuth2 security scheme. + """ + + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + class ScopeEntry(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + KEY_FIELD_NUMBER: builtins.int + VALUE_FIELD_NUMBER: builtins.int + key: builtins.str + value: builtins.str + def __init__( + self, + *, + key: builtins.str = ..., + value: builtins.str = ..., + ) -> None: ... + def ClearField( + self, + field_name: typing_extensions.Literal["key", b"key", "value", b"value"], + ) -> None: ... + + SCOPE_FIELD_NUMBER: builtins.int + @property + def scope( + self, + ) -> google.protobuf.internal.containers.ScalarMap[builtins.str, builtins.str]: + """Maps between a name of a scope to a short description of it (as the value + of the property). + """ + def __init__( + self, + *, + scope: collections.abc.Mapping[builtins.str, builtins.str] | None = ..., + ) -> None: ... + def ClearField( + self, field_name: typing_extensions.Literal["scope", b"scope"] + ) -> None: ... + +global___Scopes = Scopes diff --git a/temporalio/api/namespace/v1/message_pb2.py b/temporalio/api/namespace/v1/message_pb2.py index 9d17e10ec..31f6941f2 100644 --- a/temporalio/api/namespace/v1/message_pb2.py +++ b/temporalio/api/namespace/v1/message_pb2.py @@ -22,7 +22,7 @@ ) DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile( - b'\n\'temporal/api/namespace/v1/message.proto\x12\x19temporal.api.namespace.v1\x1a\x1egoogle/protobuf/duration.proto\x1a\x1fgoogle/protobuf/timestamp.proto\x1a%temporal/api/enums/v1/namespace.proto"\xec\x05\n\rNamespaceInfo\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x34\n\x05state\x18\x02 \x01(\x0e\x32%.temporal.api.enums.v1.NamespaceState\x12\x13\n\x0b\x64\x65scription\x18\x03 \x01(\t\x12\x13\n\x0bowner_email\x18\x04 \x01(\t\x12@\n\x04\x64\x61ta\x18\x05 \x03(\x0b\x32\x32.temporal.api.namespace.v1.NamespaceInfo.DataEntry\x12\n\n\x02id\x18\x06 \x01(\t\x12K\n\x0c\x63\x61pabilities\x18\x07 \x01(\x0b\x32\x35.temporal.api.namespace.v1.NamespaceInfo.Capabilities\x12?\n\x06limits\x18\x08 \x01(\x0b\x32/.temporal.api.namespace.v1.NamespaceInfo.Limits\x12\x1a\n\x12supports_schedules\x18\x64 \x01(\x08\x1a+\n\tDataEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x1a\xff\x01\n\x0c\x43\x61pabilities\x12\x1c\n\x14\x65\x61ger_workflow_start\x18\x01 \x01(\x08\x12\x13\n\x0bsync_update\x18\x02 \x01(\x08\x12\x14\n\x0c\x61sync_update\x18\x03 \x01(\x08\x12\x19\n\x11worker_heartbeats\x18\x04 \x01(\x08\x12*\n"reported_problems_search_attribute\x18\x05 \x01(\x08\x12\x16\n\x0eworkflow_pause\x18\x06 \x01(\x08\x12\x1d\n\x15standalone_activities\x18\x07 \x01(\x08\x12(\n worker_poll_complete_on_shutdown\x18\x08 \x01(\x08\x1a\x46\n\x06Limits\x12\x1d\n\x15\x62lob_size_limit_error\x18\x01 \x01(\x03\x12\x1d\n\x15memo_size_limit_error\x18\x02 \x01(\x03"\x9e\x04\n\x0fNamespaceConfig\x12\x43\n workflow_execution_retention_ttl\x18\x01 \x01(\x0b\x32\x19.google.protobuf.Duration\x12<\n\x0c\x62\x61\x64_binaries\x18\x02 \x01(\x0b\x32&.temporal.api.namespace.v1.BadBinaries\x12\x44\n\x16history_archival_state\x18\x03 \x01(\x0e\x32$.temporal.api.enums.v1.ArchivalState\x12\x1c\n\x14history_archival_uri\x18\x04 \x01(\t\x12G\n\x19visibility_archival_state\x18\x05 \x01(\x0e\x32$.temporal.api.enums.v1.ArchivalState\x12\x1f\n\x17visibility_archival_uri\x18\x06 \x01(\t\x12u\n\x1f\x63ustom_search_attribute_aliases\x18\x07 \x03(\x0b\x32L.temporal.api.namespace.v1.NamespaceConfig.CustomSearchAttributeAliasesEntry\x1a\x43\n!CustomSearchAttributeAliasesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01"\xb0\x01\n\x0b\x42\x61\x64\x42inaries\x12\x46\n\x08\x62inaries\x18\x01 \x03(\x0b\x32\x34.temporal.api.namespace.v1.BadBinaries.BinariesEntry\x1aY\n\rBinariesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x37\n\x05value\x18\x02 \x01(\x0b\x32(.temporal.api.namespace.v1.BadBinaryInfo:\x02\x38\x01"b\n\rBadBinaryInfo\x12\x0e\n\x06reason\x18\x01 \x01(\t\x12\x10\n\x08operator\x18\x02 \x01(\t\x12/\n\x0b\x63reate_time\x18\x03 \x01(\x0b\x32\x1a.google.protobuf.Timestamp"\xea\x01\n\x13UpdateNamespaceInfo\x12\x13\n\x0b\x64\x65scription\x18\x01 \x01(\t\x12\x13\n\x0bowner_email\x18\x02 \x01(\t\x12\x46\n\x04\x64\x61ta\x18\x03 \x03(\x0b\x32\x38.temporal.api.namespace.v1.UpdateNamespaceInfo.DataEntry\x12\x34\n\x05state\x18\x04 \x01(\x0e\x32%.temporal.api.enums.v1.NamespaceState\x1a+\n\tDataEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01"*\n\x0fNamespaceFilter\x12\x17\n\x0finclude_deleted\x18\x01 \x01(\x08\x42\x98\x01\n\x1cio.temporal.api.namespace.v1B\x0cMessageProtoP\x01Z)go.temporal.io/api/namespace/v1;namespace\xaa\x02\x1bTemporalio.Api.Namespace.V1\xea\x02\x1eTemporalio::Api::Namespace::V1b\x06proto3' + b'\n\'temporal/api/namespace/v1/message.proto\x12\x19temporal.api.namespace.v1\x1a\x1egoogle/protobuf/duration.proto\x1a\x1fgoogle/protobuf/timestamp.proto\x1a%temporal/api/enums/v1/namespace.proto"\x88\x06\n\rNamespaceInfo\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x34\n\x05state\x18\x02 \x01(\x0e\x32%.temporal.api.enums.v1.NamespaceState\x12\x13\n\x0b\x64\x65scription\x18\x03 \x01(\t\x12\x13\n\x0bowner_email\x18\x04 \x01(\t\x12@\n\x04\x64\x61ta\x18\x05 \x03(\x0b\x32\x32.temporal.api.namespace.v1.NamespaceInfo.DataEntry\x12\n\n\x02id\x18\x06 \x01(\t\x12K\n\x0c\x63\x61pabilities\x18\x07 \x01(\x0b\x32\x35.temporal.api.namespace.v1.NamespaceInfo.Capabilities\x12?\n\x06limits\x18\x08 \x01(\x0b\x32/.temporal.api.namespace.v1.NamespaceInfo.Limits\x12\x1a\n\x12supports_schedules\x18\x64 \x01(\x08\x1a+\n\tDataEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x1a\x9b\x02\n\x0c\x43\x61pabilities\x12\x1c\n\x14\x65\x61ger_workflow_start\x18\x01 \x01(\x08\x12\x13\n\x0bsync_update\x18\x02 \x01(\x08\x12\x14\n\x0c\x61sync_update\x18\x03 \x01(\x08\x12\x19\n\x11worker_heartbeats\x18\x04 \x01(\x08\x12*\n"reported_problems_search_attribute\x18\x05 \x01(\x08\x12\x16\n\x0eworkflow_pause\x18\x06 \x01(\x08\x12\x1d\n\x15standalone_activities\x18\x07 \x01(\x08\x12(\n worker_poll_complete_on_shutdown\x18\x08 \x01(\x08\x12\x1a\n\x12poller_autoscaling\x18\t \x01(\x08\x1a\x46\n\x06Limits\x12\x1d\n\x15\x62lob_size_limit_error\x18\x01 \x01(\x03\x12\x1d\n\x15memo_size_limit_error\x18\x02 \x01(\x03"\x9e\x04\n\x0fNamespaceConfig\x12\x43\n workflow_execution_retention_ttl\x18\x01 \x01(\x0b\x32\x19.google.protobuf.Duration\x12<\n\x0c\x62\x61\x64_binaries\x18\x02 \x01(\x0b\x32&.temporal.api.namespace.v1.BadBinaries\x12\x44\n\x16history_archival_state\x18\x03 \x01(\x0e\x32$.temporal.api.enums.v1.ArchivalState\x12\x1c\n\x14history_archival_uri\x18\x04 \x01(\t\x12G\n\x19visibility_archival_state\x18\x05 \x01(\x0e\x32$.temporal.api.enums.v1.ArchivalState\x12\x1f\n\x17visibility_archival_uri\x18\x06 \x01(\t\x12u\n\x1f\x63ustom_search_attribute_aliases\x18\x07 \x03(\x0b\x32L.temporal.api.namespace.v1.NamespaceConfig.CustomSearchAttributeAliasesEntry\x1a\x43\n!CustomSearchAttributeAliasesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01"\xb0\x01\n\x0b\x42\x61\x64\x42inaries\x12\x46\n\x08\x62inaries\x18\x01 \x03(\x0b\x32\x34.temporal.api.namespace.v1.BadBinaries.BinariesEntry\x1aY\n\rBinariesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x37\n\x05value\x18\x02 \x01(\x0b\x32(.temporal.api.namespace.v1.BadBinaryInfo:\x02\x38\x01"b\n\rBadBinaryInfo\x12\x0e\n\x06reason\x18\x01 \x01(\t\x12\x10\n\x08operator\x18\x02 \x01(\t\x12/\n\x0b\x63reate_time\x18\x03 \x01(\x0b\x32\x1a.google.protobuf.Timestamp"\xea\x01\n\x13UpdateNamespaceInfo\x12\x13\n\x0b\x64\x65scription\x18\x01 \x01(\t\x12\x13\n\x0bowner_email\x18\x02 \x01(\t\x12\x46\n\x04\x64\x61ta\x18\x03 \x03(\x0b\x32\x38.temporal.api.namespace.v1.UpdateNamespaceInfo.DataEntry\x12\x34\n\x05state\x18\x04 \x01(\x0e\x32%.temporal.api.enums.v1.NamespaceState\x1a+\n\tDataEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01"*\n\x0fNamespaceFilter\x12\x17\n\x0finclude_deleted\x18\x01 \x01(\x08\x42\x98\x01\n\x1cio.temporal.api.namespace.v1B\x0cMessageProtoP\x01Z)go.temporal.io/api/namespace/v1;namespace\xaa\x02\x1bTemporalio.Api.Namespace.V1\xea\x02\x1eTemporalio::Api::Namespace::V1b\x06proto3' ) @@ -178,27 +178,27 @@ _UPDATENAMESPACEINFO_DATAENTRY._options = None _UPDATENAMESPACEINFO_DATAENTRY._serialized_options = b"8\001" _NAMESPACEINFO._serialized_start = 175 - _NAMESPACEINFO._serialized_end = 923 + _NAMESPACEINFO._serialized_end = 951 _NAMESPACEINFO_DATAENTRY._serialized_start = 550 _NAMESPACEINFO_DATAENTRY._serialized_end = 593 _NAMESPACEINFO_CAPABILITIES._serialized_start = 596 - _NAMESPACEINFO_CAPABILITIES._serialized_end = 851 - _NAMESPACEINFO_LIMITS._serialized_start = 853 - _NAMESPACEINFO_LIMITS._serialized_end = 923 - _NAMESPACECONFIG._serialized_start = 926 - _NAMESPACECONFIG._serialized_end = 1468 - _NAMESPACECONFIG_CUSTOMSEARCHATTRIBUTEALIASESENTRY._serialized_start = 1401 - _NAMESPACECONFIG_CUSTOMSEARCHATTRIBUTEALIASESENTRY._serialized_end = 1468 - _BADBINARIES._serialized_start = 1471 - _BADBINARIES._serialized_end = 1647 - _BADBINARIES_BINARIESENTRY._serialized_start = 1558 - _BADBINARIES_BINARIESENTRY._serialized_end = 1647 - _BADBINARYINFO._serialized_start = 1649 - _BADBINARYINFO._serialized_end = 1747 - _UPDATENAMESPACEINFO._serialized_start = 1750 - _UPDATENAMESPACEINFO._serialized_end = 1984 + _NAMESPACEINFO_CAPABILITIES._serialized_end = 879 + _NAMESPACEINFO_LIMITS._serialized_start = 881 + _NAMESPACEINFO_LIMITS._serialized_end = 951 + _NAMESPACECONFIG._serialized_start = 954 + _NAMESPACECONFIG._serialized_end = 1496 + _NAMESPACECONFIG_CUSTOMSEARCHATTRIBUTEALIASESENTRY._serialized_start = 1429 + _NAMESPACECONFIG_CUSTOMSEARCHATTRIBUTEALIASESENTRY._serialized_end = 1496 + _BADBINARIES._serialized_start = 1499 + _BADBINARIES._serialized_end = 1675 + _BADBINARIES_BINARIESENTRY._serialized_start = 1586 + _BADBINARIES_BINARIESENTRY._serialized_end = 1675 + _BADBINARYINFO._serialized_start = 1677 + _BADBINARYINFO._serialized_end = 1775 + _UPDATENAMESPACEINFO._serialized_start = 1778 + _UPDATENAMESPACEINFO._serialized_end = 2012 _UPDATENAMESPACEINFO_DATAENTRY._serialized_start = 550 _UPDATENAMESPACEINFO_DATAENTRY._serialized_end = 593 - _NAMESPACEFILTER._serialized_start = 1986 - _NAMESPACEFILTER._serialized_end = 2028 + _NAMESPACEFILTER._serialized_start = 2014 + _NAMESPACEFILTER._serialized_end = 2056 # @@protoc_insertion_point(module_scope) diff --git a/temporalio/api/namespace/v1/message_pb2.pyi b/temporalio/api/namespace/v1/message_pb2.pyi index 4326ec4d3..951b2cb81 100644 --- a/temporalio/api/namespace/v1/message_pb2.pyi +++ b/temporalio/api/namespace/v1/message_pb2.pyi @@ -56,6 +56,7 @@ class NamespaceInfo(google.protobuf.message.Message): WORKFLOW_PAUSE_FIELD_NUMBER: builtins.int STANDALONE_ACTIVITIES_FIELD_NUMBER: builtins.int WORKER_POLL_COMPLETE_ON_SHUTDOWN_FIELD_NUMBER: builtins.int + POLLER_AUTOSCALING_FIELD_NUMBER: builtins.int eager_workflow_start: builtins.bool """True if the namespace supports eager workflow start.""" sync_update: builtins.bool @@ -77,6 +78,8 @@ class NamespaceInfo(google.protobuf.message.Message): an empty response. When this flag is true, workers should allow polls to return gracefully rather than terminating any open polls on shutdown. """ + poller_autoscaling: builtins.bool + """True if the namespace supports poller autoscaling""" def __init__( self, *, @@ -88,6 +91,7 @@ class NamespaceInfo(google.protobuf.message.Message): workflow_pause: builtins.bool = ..., standalone_activities: builtins.bool = ..., worker_poll_complete_on_shutdown: builtins.bool = ..., + poller_autoscaling: builtins.bool = ..., ) -> None: ... def ClearField( self, @@ -96,6 +100,8 @@ class NamespaceInfo(google.protobuf.message.Message): b"async_update", "eager_workflow_start", b"eager_workflow_start", + "poller_autoscaling", + b"poller_autoscaling", "reported_problems_search_attribute", b"reported_problems_search_attribute", "standalone_activities", diff --git a/temporalio/api/protometa/__init__.py b/temporalio/api/protometa/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/temporalio/api/protometa/v1/__init__.py b/temporalio/api/protometa/v1/__init__.py new file mode 100644 index 000000000..b63c2e8df --- /dev/null +++ b/temporalio/api/protometa/v1/__init__.py @@ -0,0 +1,5 @@ +from .annotations_pb2 import RequestHeaderAnnotation + +__all__ = [ + "RequestHeaderAnnotation", +] diff --git a/temporalio/api/protometa/v1/annotations_pb2.py b/temporalio/api/protometa/v1/annotations_pb2.py new file mode 100644 index 000000000..3f790e1fd --- /dev/null +++ b/temporalio/api/protometa/v1/annotations_pb2.py @@ -0,0 +1,48 @@ +# -*- coding: utf-8 -*- +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: temporal/api/protometa/v1/annotations.proto +"""Generated protocol buffer code.""" + +from google.protobuf import descriptor as _descriptor +from google.protobuf import descriptor_pool as _descriptor_pool +from google.protobuf import message as _message +from google.protobuf import reflection as _reflection +from google.protobuf import symbol_database as _symbol_database + +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + +from google.protobuf import descriptor_pb2 as google_dot_protobuf_dot_descriptor__pb2 + +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile( + b'\n+temporal/api/protometa/v1/annotations.proto\x12\x19temporal.api.protometa.v1\x1a google/protobuf/descriptor.proto"8\n\x17RequestHeaderAnnotation\x12\x0e\n\x06header\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:m\n\x0erequest_header\x12\x1e.google.protobuf.MethodOptions\x18\xd1\xc3\xb9\x03 \x03(\x0b\x32\x32.temporal.api.protometa.v1.RequestHeaderAnnotationB\x9c\x01\n\x1cio.temporal.api.protometa.v1B\x10\x41nnotationsProtoP\x01Z)go.temporal.io/api/protometa/v1;protometa\xaa\x02\x1bTemporalio.Api.Protometa.V1\xea\x02\x1eTemporalio::Api::Protometa::V1b\x06proto3' +) + + +REQUEST_HEADER_FIELD_NUMBER = 7234001 +request_header = DESCRIPTOR.extensions_by_name["request_header"] + +_REQUESTHEADERANNOTATION = DESCRIPTOR.message_types_by_name["RequestHeaderAnnotation"] +RequestHeaderAnnotation = _reflection.GeneratedProtocolMessageType( + "RequestHeaderAnnotation", + (_message.Message,), + { + "DESCRIPTOR": _REQUESTHEADERANNOTATION, + "__module__": "temporalio.api.protometa.v1.annotations_pb2", + # @@protoc_insertion_point(class_scope:temporal.api.protometa.v1.RequestHeaderAnnotation) + }, +) +_sym_db.RegisterMessage(RequestHeaderAnnotation) + +if _descriptor._USE_C_DESCRIPTORS == False: + google_dot_protobuf_dot_descriptor__pb2.MethodOptions.RegisterExtension( + request_header + ) + + DESCRIPTOR._options = None + DESCRIPTOR._serialized_options = b"\n\034io.temporal.api.protometa.v1B\020AnnotationsProtoP\001Z)go.temporal.io/api/protometa/v1;protometa\252\002\033Temporalio.Api.Protometa.V1\352\002\036Temporalio::Api::Protometa::V1" + _REQUESTHEADERANNOTATION._serialized_start = 108 + _REQUESTHEADERANNOTATION._serialized_end = 164 +# @@protoc_insertion_point(module_scope) diff --git a/temporalio/api/protometa/v1/annotations_pb2.pyi b/temporalio/api/protometa/v1/annotations_pb2.pyi new file mode 100644 index 000000000..143d7d7d9 --- /dev/null +++ b/temporalio/api/protometa/v1/annotations_pb2.pyi @@ -0,0 +1,64 @@ +""" +@generated by mypy-protobuf. Do not edit manually! +isort:skip_file +""" + +import builtins +import sys + +import google.protobuf.descriptor +import google.protobuf.descriptor_pb2 +import google.protobuf.internal.containers +import google.protobuf.internal.extension_dict +import google.protobuf.message + +if sys.version_info >= (3, 8): + import typing as typing_extensions +else: + import typing_extensions + +DESCRIPTOR: google.protobuf.descriptor.FileDescriptor + +class RequestHeaderAnnotation(google.protobuf.message.Message): + """RequestHeaderAnnotation allows specifying that field values from a request + should be propagated as outbound headers. + + The value field supports template interpolation where field paths enclosed + in braces will be replaced with the actual field values from the request. + For example: + value: "{workflow_execution.workflow_id}" + value: "workflow-{workflow_execution.workflow_id}" + value: "{namespace}/{workflow_execution.workflow_id}" + """ + + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + HEADER_FIELD_NUMBER: builtins.int + VALUE_FIELD_NUMBER: builtins.int + header: builtins.str + """The name of the header to set (e.g., "temporal-resource-id")""" + value: builtins.str + """A template string that may contain field paths in braces. + Field paths use dot notation to traverse nested messages. + Example: "{workflow_execution.workflow_id}" + """ + def __init__( + self, + *, + header: builtins.str = ..., + value: builtins.str = ..., + ) -> None: ... + def ClearField( + self, + field_name: typing_extensions.Literal["header", b"header", "value", b"value"], + ) -> None: ... + +global___RequestHeaderAnnotation = RequestHeaderAnnotation + +REQUEST_HEADER_FIELD_NUMBER: builtins.int +request_header: google.protobuf.internal.extension_dict._ExtensionFieldDescriptor[ + google.protobuf.descriptor_pb2.MethodOptions, + google.protobuf.internal.containers.RepeatedCompositeFieldContainer[ + global___RequestHeaderAnnotation + ], +] diff --git a/temporalio/api/workflowservice/v1/request_response_pb2.py b/temporalio/api/workflowservice/v1/request_response_pb2.py index 826936e33..e8ac9b3a0 100644 --- a/temporalio/api/workflowservice/v1/request_response_pb2.py +++ b/temporalio/api/workflowservice/v1/request_response_pb2.py @@ -122,7 +122,7 @@ ) DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile( - b'\n6temporal/api/workflowservice/v1/request_response.proto\x12\x1ftemporal.api.workflowservice.v1\x1a+temporal/api/enums/v1/batch_operation.proto\x1a"temporal/api/enums/v1/common.proto\x1a$temporal/api/enums/v1/workflow.proto\x1a%temporal/api/enums/v1/namespace.proto\x1a(temporal/api/enums/v1/failed_cause.proto\x1a!temporal/api/enums/v1/query.proto\x1a!temporal/api/enums/v1/reset.proto\x1a&temporal/api/enums/v1/task_queue.proto\x1a&temporal/api/enums/v1/deployment.proto\x1a"temporal/api/enums/v1/update.proto\x1a$temporal/api/enums/v1/activity.proto\x1a&temporal/api/activity/v1/message.proto\x1a$temporal/api/common/v1/message.proto\x1a%temporal/api/history/v1/message.proto\x1a&temporal/api/workflow/v1/message.proto\x1a%temporal/api/command/v1/message.proto\x1a(temporal/api/deployment/v1/message.proto\x1a%temporal/api/failure/v1/message.proto\x1a$temporal/api/filter/v1/message.proto\x1a&temporal/api/protocol/v1/message.proto\x1a\'temporal/api/namespace/v1/message.proto\x1a#temporal/api/query/v1/message.proto\x1a)temporal/api/replication/v1/message.proto\x1a#temporal/api/rules/v1/message.proto\x1a\'temporal/api/sdk/v1/worker_config.proto\x1a&temporal/api/schedule/v1/message.proto\x1a\'temporal/api/taskqueue/v1/message.proto\x1a$temporal/api/update/v1/message.proto\x1a%temporal/api/version/v1/message.proto\x1a#temporal/api/batch/v1/message.proto\x1a\x30temporal/api/sdk/v1/task_complete_metadata.proto\x1a\'temporal/api/sdk/v1/user_metadata.proto\x1a#temporal/api/nexus/v1/message.proto\x1a$temporal/api/worker/v1/message.proto\x1a\x1egoogle/protobuf/duration.proto\x1a google/protobuf/field_mask.proto\x1a\x1fgoogle/protobuf/timestamp.proto"\x88\x05\n\x18RegisterNamespaceRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0b\x64\x65scription\x18\x02 \x01(\t\x12\x13\n\x0bowner_email\x18\x03 \x01(\t\x12\x46\n#workflow_execution_retention_period\x18\x04 \x01(\x0b\x32\x19.google.protobuf.Duration\x12G\n\x08\x63lusters\x18\x05 \x03(\x0b\x32\x35.temporal.api.replication.v1.ClusterReplicationConfig\x12\x1b\n\x13\x61\x63tive_cluster_name\x18\x06 \x01(\t\x12Q\n\x04\x64\x61ta\x18\x07 \x03(\x0b\x32\x43.temporal.api.workflowservice.v1.RegisterNamespaceRequest.DataEntry\x12\x16\n\x0esecurity_token\x18\x08 \x01(\t\x12\x1b\n\x13is_global_namespace\x18\t \x01(\x08\x12\x44\n\x16history_archival_state\x18\n \x01(\x0e\x32$.temporal.api.enums.v1.ArchivalState\x12\x1c\n\x14history_archival_uri\x18\x0b \x01(\t\x12G\n\x19visibility_archival_state\x18\x0c \x01(\x0e\x32$.temporal.api.enums.v1.ArchivalState\x12\x1f\n\x17visibility_archival_uri\x18\r \x01(\t\x1a+\n\tDataEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01"\x1b\n\x19RegisterNamespaceResponse"\x89\x01\n\x15ListNamespacesRequest\x12\x11\n\tpage_size\x18\x01 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c\x12\x44\n\x10namespace_filter\x18\x03 \x01(\x0b\x32*.temporal.api.namespace.v1.NamespaceFilter"\x81\x01\n\x16ListNamespacesResponse\x12N\n\nnamespaces\x18\x01 \x03(\x0b\x32:.temporal.api.workflowservice.v1.DescribeNamespaceResponse\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c"9\n\x18\x44\x65scribeNamespaceRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\n\n\x02id\x18\x02 \x01(\t"\xec\x02\n\x19\x44\x65scribeNamespaceResponse\x12@\n\x0enamespace_info\x18\x01 \x01(\x0b\x32(.temporal.api.namespace.v1.NamespaceInfo\x12:\n\x06\x63onfig\x18\x02 \x01(\x0b\x32*.temporal.api.namespace.v1.NamespaceConfig\x12S\n\x12replication_config\x18\x03 \x01(\x0b\x32\x37.temporal.api.replication.v1.NamespaceReplicationConfig\x12\x18\n\x10\x66\x61ilover_version\x18\x04 \x01(\x03\x12\x1b\n\x13is_global_namespace\x18\x05 \x01(\x08\x12\x45\n\x10\x66\x61ilover_history\x18\x06 \x03(\x0b\x32+.temporal.api.replication.v1.FailoverStatus"\xcf\x02\n\x16UpdateNamespaceRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x43\n\x0bupdate_info\x18\x02 \x01(\x0b\x32..temporal.api.namespace.v1.UpdateNamespaceInfo\x12:\n\x06\x63onfig\x18\x03 \x01(\x0b\x32*.temporal.api.namespace.v1.NamespaceConfig\x12S\n\x12replication_config\x18\x04 \x01(\x0b\x32\x37.temporal.api.replication.v1.NamespaceReplicationConfig\x12\x16\n\x0esecurity_token\x18\x05 \x01(\t\x12\x19\n\x11\x64\x65lete_bad_binary\x18\x06 \x01(\t\x12\x19\n\x11promote_namespace\x18\x07 \x01(\x08"\xa3\x02\n\x17UpdateNamespaceResponse\x12@\n\x0enamespace_info\x18\x01 \x01(\x0b\x32(.temporal.api.namespace.v1.NamespaceInfo\x12:\n\x06\x63onfig\x18\x02 \x01(\x0b\x32*.temporal.api.namespace.v1.NamespaceConfig\x12S\n\x12replication_config\x18\x03 \x01(\x0b\x32\x37.temporal.api.replication.v1.NamespaceReplicationConfig\x12\x18\n\x10\x66\x61ilover_version\x18\x04 \x01(\x03\x12\x1b\n\x13is_global_namespace\x18\x05 \x01(\x08"F\n\x19\x44\x65precateNamespaceRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x16\n\x0esecurity_token\x18\x02 \x01(\t"\x1c\n\x1a\x44\x65precateNamespaceResponse"\x87\x0c\n\x1dStartWorkflowExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12;\n\rworkflow_type\x18\x03 \x01(\x0b\x32$.temporal.api.common.v1.WorkflowType\x12\x38\n\ntask_queue\x18\x04 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12/\n\x05input\x18\x05 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12=\n\x1aworkflow_execution_timeout\x18\x06 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x37\n\x14workflow_run_timeout\x18\x07 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x38\n\x15workflow_task_timeout\x18\x08 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x10\n\x08identity\x18\t \x01(\t\x12\x12\n\nrequest_id\x18\n \x01(\t\x12N\n\x18workflow_id_reuse_policy\x18\x0b \x01(\x0e\x32,.temporal.api.enums.v1.WorkflowIdReusePolicy\x12T\n\x1bworkflow_id_conflict_policy\x18\x16 \x01(\x0e\x32/.temporal.api.enums.v1.WorkflowIdConflictPolicy\x12\x39\n\x0cretry_policy\x18\x0c \x01(\x0b\x32#.temporal.api.common.v1.RetryPolicy\x12\x15\n\rcron_schedule\x18\r \x01(\t\x12*\n\x04memo\x18\x0e \x01(\x0b\x32\x1c.temporal.api.common.v1.Memo\x12\x43\n\x11search_attributes\x18\x0f \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes\x12.\n\x06header\x18\x10 \x01(\x0b\x32\x1e.temporal.api.common.v1.Header\x12\x1f\n\x17request_eager_execution\x18\x11 \x01(\x08\x12;\n\x11\x63ontinued_failure\x18\x12 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12@\n\x16last_completion_result\x18\x13 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x37\n\x14workflow_start_delay\x18\x14 \x01(\x0b\x32\x19.google.protobuf.Duration\x12>\n\x14\x63ompletion_callbacks\x18\x15 \x03(\x0b\x32 .temporal.api.common.v1.Callback\x12\x38\n\ruser_metadata\x18\x17 \x01(\x0b\x32!.temporal.api.sdk.v1.UserMetadata\x12+\n\x05links\x18\x18 \x03(\x0b\x32\x1c.temporal.api.common.v1.Link\x12I\n\x13versioning_override\x18\x19 \x01(\x0b\x32,.temporal.api.workflow.v1.VersioningOverride\x12H\n\x13on_conflict_options\x18\x1a \x01(\x0b\x32+.temporal.api.workflow.v1.OnConflictOptions\x12\x32\n\x08priority\x18\x1b \x01(\x0b\x32 .temporal.api.common.v1.Priority\x12\\\n\x1f\x65\x61ger_worker_deployment_options\x18\x1c \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentOptions"\x8a\x02\n\x1eStartWorkflowExecutionResponse\x12\x0e\n\x06run_id\x18\x01 \x01(\t\x12\x0f\n\x07started\x18\x03 \x01(\x08\x12>\n\x06status\x18\x05 \x01(\x0e\x32..temporal.api.enums.v1.WorkflowExecutionStatus\x12[\n\x13\x65\x61ger_workflow_task\x18\x02 \x01(\x0b\x32>.temporal.api.workflowservice.v1.PollWorkflowTaskQueueResponse\x12*\n\x04link\x18\x04 \x01(\x0b\x32\x1c.temporal.api.common.v1.Link"\xaa\x02\n"GetWorkflowExecutionHistoryRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12<\n\texecution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x19\n\x11maximum_page_size\x18\x03 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x04 \x01(\x0c\x12\x16\n\x0ewait_new_event\x18\x05 \x01(\x08\x12P\n\x19history_event_filter_type\x18\x06 \x01(\x0e\x32-.temporal.api.enums.v1.HistoryEventFilterType\x12\x15\n\rskip_archival\x18\x07 \x01(\x08"\xba\x01\n#GetWorkflowExecutionHistoryResponse\x12\x31\n\x07history\x18\x01 \x01(\x0b\x32 .temporal.api.history.v1.History\x12\x35\n\x0braw_history\x18\x02 \x03(\x0b\x32 .temporal.api.common.v1.DataBlob\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c\x12\x10\n\x08\x61rchived\x18\x04 \x01(\x08"\xb0\x01\n)GetWorkflowExecutionHistoryReverseRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12<\n\texecution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x19\n\x11maximum_page_size\x18\x03 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x04 \x01(\x0c"x\n*GetWorkflowExecutionHistoryReverseResponse\x12\x31\n\x07history\x18\x01 \x01(\x0b\x32 .temporal.api.history.v1.History\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c"\xfc\x02\n\x1cPollWorkflowTaskQueueRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x38\n\ntask_queue\x18\x02 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x1b\n\x13worker_instance_key\x18\x08 \x01(\t\x12\x1b\n\x0f\x62inary_checksum\x18\x04 \x01(\tB\x02\x18\x01\x12Z\n\x1bworker_version_capabilities\x18\x05 \x01(\x0b\x32\x31.temporal.api.common.v1.WorkerVersionCapabilitiesB\x02\x18\x01\x12O\n\x12\x64\x65ployment_options\x18\x06 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentOptionsJ\x04\x08\x07\x10\x08R\x10worker_heartbeat"\x91\x07\n\x1dPollWorkflowTaskQueueResponse\x12\x12\n\ntask_token\x18\x01 \x01(\x0c\x12\x45\n\x12workflow_execution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12;\n\rworkflow_type\x18\x03 \x01(\x0b\x32$.temporal.api.common.v1.WorkflowType\x12!\n\x19previous_started_event_id\x18\x04 \x01(\x03\x12\x18\n\x10started_event_id\x18\x05 \x01(\x03\x12\x0f\n\x07\x61ttempt\x18\x06 \x01(\x05\x12\x1a\n\x12\x62\x61\x63klog_count_hint\x18\x07 \x01(\x03\x12\x31\n\x07history\x18\x08 \x01(\x0b\x32 .temporal.api.history.v1.History\x12\x17\n\x0fnext_page_token\x18\t \x01(\x0c\x12\x33\n\x05query\x18\n \x01(\x0b\x32$.temporal.api.query.v1.WorkflowQuery\x12K\n\x1dworkflow_execution_task_queue\x18\x0b \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12\x32\n\x0escheduled_time\x18\x0c \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x30\n\x0cstarted_time\x18\r \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\\\n\x07queries\x18\x0e \x03(\x0b\x32K.temporal.api.workflowservice.v1.PollWorkflowTaskQueueResponse.QueriesEntry\x12\x33\n\x08messages\x18\x0f \x03(\x0b\x32!.temporal.api.protocol.v1.Message\x12Q\n\x17poller_scaling_decision\x18\x10 \x01(\x0b\x32\x30.temporal.api.taskqueue.v1.PollerScalingDecision\x1aT\n\x0cQueriesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x33\n\x05value\x18\x02 \x01(\x0b\x32$.temporal.api.query.v1.WorkflowQuery:\x02\x38\x01"\xb5\t\n#RespondWorkflowTaskCompletedRequest\x12\x12\n\ntask_token\x18\x01 \x01(\x0c\x12\x32\n\x08\x63ommands\x18\x02 \x03(\x0b\x32 .temporal.api.command.v1.Command\x12\x10\n\x08identity\x18\x03 \x01(\t\x12O\n\x11sticky_attributes\x18\x04 \x01(\x0b\x32\x34.temporal.api.taskqueue.v1.StickyExecutionAttributes\x12 \n\x18return_new_workflow_task\x18\x05 \x01(\x08\x12&\n\x1e\x66orce_create_new_workflow_task\x18\x06 \x01(\x08\x12\x1b\n\x0f\x62inary_checksum\x18\x07 \x01(\tB\x02\x18\x01\x12m\n\rquery_results\x18\x08 \x03(\x0b\x32V.temporal.api.workflowservice.v1.RespondWorkflowTaskCompletedRequest.QueryResultsEntry\x12\x11\n\tnamespace\x18\t \x01(\t\x12L\n\x14worker_version_stamp\x18\n \x01(\x0b\x32*.temporal.api.common.v1.WorkerVersionStampB\x02\x18\x01\x12\x33\n\x08messages\x18\x0b \x03(\x0b\x32!.temporal.api.protocol.v1.Message\x12H\n\x0csdk_metadata\x18\x0c \x01(\x0b\x32\x32.temporal.api.sdk.v1.WorkflowTaskCompletedMetadata\x12\x43\n\x11metering_metadata\x18\r \x01(\x0b\x32(.temporal.api.common.v1.MeteringMetadata\x12g\n\x0c\x63\x61pabilities\x18\x0e \x01(\x0b\x32Q.temporal.api.workflowservice.v1.RespondWorkflowTaskCompletedRequest.Capabilities\x12>\n\ndeployment\x18\x0f \x01(\x0b\x32&.temporal.api.deployment.v1.DeploymentB\x02\x18\x01\x12\x46\n\x13versioning_behavior\x18\x10 \x01(\x0e\x32).temporal.api.enums.v1.VersioningBehavior\x12O\n\x12\x64\x65ployment_options\x18\x11 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentOptions\x1a_\n\x11QueryResultsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x39\n\x05value\x18\x02 \x01(\x0b\x32*.temporal.api.query.v1.WorkflowQueryResult:\x02\x38\x01\x1a\x45\n\x0c\x43\x61pabilities\x12\x35\n-discard_speculative_workflow_task_with_events\x18\x01 \x01(\x08"\xf5\x01\n$RespondWorkflowTaskCompletedResponse\x12U\n\rworkflow_task\x18\x01 \x01(\x0b\x32>.temporal.api.workflowservice.v1.PollWorkflowTaskQueueResponse\x12V\n\x0e\x61\x63tivity_tasks\x18\x02 \x03(\x0b\x32>.temporal.api.workflowservice.v1.PollActivityTaskQueueResponse\x12\x1e\n\x16reset_history_event_id\x18\x03 \x01(\x03"\xf8\x03\n RespondWorkflowTaskFailedRequest\x12\x12\n\ntask_token\x18\x01 \x01(\x0c\x12=\n\x05\x63\x61use\x18\x02 \x01(\x0e\x32..temporal.api.enums.v1.WorkflowTaskFailedCause\x12\x31\n\x07\x66\x61ilure\x18\x03 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12\x10\n\x08identity\x18\x04 \x01(\t\x12\x1b\n\x0f\x62inary_checksum\x18\x05 \x01(\tB\x02\x18\x01\x12\x11\n\tnamespace\x18\x06 \x01(\t\x12\x33\n\x08messages\x18\x07 \x03(\x0b\x32!.temporal.api.protocol.v1.Message\x12\x46\n\x0eworker_version\x18\x08 \x01(\x0b\x32*.temporal.api.common.v1.WorkerVersionStampB\x02\x18\x01\x12>\n\ndeployment\x18\t \x01(\x0b\x32&.temporal.api.deployment.v1.DeploymentB\x02\x18\x01\x12O\n\x12\x64\x65ployment_options\x18\n \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentOptions"#\n!RespondWorkflowTaskFailedResponse"\xaa\x03\n\x1cPollActivityTaskQueueRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x38\n\ntask_queue\x18\x02 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x1b\n\x13worker_instance_key\x18\x08 \x01(\t\x12I\n\x13task_queue_metadata\x18\x04 \x01(\x0b\x32,.temporal.api.taskqueue.v1.TaskQueueMetadata\x12Z\n\x1bworker_version_capabilities\x18\x05 \x01(\x0b\x32\x31.temporal.api.common.v1.WorkerVersionCapabilitiesB\x02\x18\x01\x12O\n\x12\x64\x65ployment_options\x18\x06 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentOptionsJ\x04\x08\x07\x10\x08R\x10worker_heartbeat"\x88\x08\n\x1dPollActivityTaskQueueResponse\x12\x12\n\ntask_token\x18\x01 \x01(\x0c\x12\x1a\n\x12workflow_namespace\x18\x02 \x01(\t\x12;\n\rworkflow_type\x18\x03 \x01(\x0b\x32$.temporal.api.common.v1.WorkflowType\x12\x45\n\x12workflow_execution\x18\x04 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12;\n\ractivity_type\x18\x05 \x01(\x0b\x32$.temporal.api.common.v1.ActivityType\x12\x13\n\x0b\x61\x63tivity_id\x18\x06 \x01(\t\x12.\n\x06header\x18\x07 \x01(\x0b\x32\x1e.temporal.api.common.v1.Header\x12/\n\x05input\x18\x08 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12;\n\x11heartbeat_details\x18\t \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x32\n\x0escheduled_time\x18\n \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x42\n\x1e\x63urrent_attempt_scheduled_time\x18\x0b \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x30\n\x0cstarted_time\x18\x0c \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x0f\n\x07\x61ttempt\x18\r \x01(\x05\x12<\n\x19schedule_to_close_timeout\x18\x0e \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x39\n\x16start_to_close_timeout\x18\x0f \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x34\n\x11heartbeat_timeout\x18\x10 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x39\n\x0cretry_policy\x18\x11 \x01(\x0b\x32#.temporal.api.common.v1.RetryPolicy\x12Q\n\x17poller_scaling_decision\x18\x12 \x01(\x0b\x32\x30.temporal.api.taskqueue.v1.PollerScalingDecision\x12\x32\n\x08priority\x18\x13 \x01(\x0b\x32 .temporal.api.common.v1.Priority\x12\x17\n\x0f\x61\x63tivity_run_id\x18\x14 \x01(\t"\x90\x01\n"RecordActivityTaskHeartbeatRequest\x12\x12\n\ntask_token\x18\x01 \x01(\x0c\x12\x31\n\x07\x64\x65tails\x18\x02 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x11\n\tnamespace\x18\x04 \x01(\t"p\n#RecordActivityTaskHeartbeatResponse\x12\x18\n\x10\x63\x61ncel_requested\x18\x01 \x01(\x08\x12\x17\n\x0f\x61\x63tivity_paused\x18\x02 \x01(\x08\x12\x16\n\x0e\x61\x63tivity_reset\x18\x03 \x01(\x08"\xba\x01\n&RecordActivityTaskHeartbeatByIdRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x12\x13\n\x0b\x61\x63tivity_id\x18\x04 \x01(\t\x12\x31\n\x07\x64\x65tails\x18\x05 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x10\n\x08identity\x18\x06 \x01(\t"t\n\'RecordActivityTaskHeartbeatByIdResponse\x12\x18\n\x10\x63\x61ncel_requested\x18\x01 \x01(\x08\x12\x17\n\x0f\x61\x63tivity_paused\x18\x02 \x01(\x08\x12\x16\n\x0e\x61\x63tivity_reset\x18\x03 \x01(\x08"\xe9\x02\n#RespondActivityTaskCompletedRequest\x12\x12\n\ntask_token\x18\x01 \x01(\x0c\x12\x30\n\x06result\x18\x02 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x11\n\tnamespace\x18\x04 \x01(\t\x12\x46\n\x0eworker_version\x18\x05 \x01(\x0b\x32*.temporal.api.common.v1.WorkerVersionStampB\x02\x18\x01\x12>\n\ndeployment\x18\x06 \x01(\x0b\x32&.temporal.api.deployment.v1.DeploymentB\x02\x18\x01\x12O\n\x12\x64\x65ployment_options\x18\x07 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentOptions"&\n$RespondActivityTaskCompletedResponse"\xba\x01\n\'RespondActivityTaskCompletedByIdRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x12\x13\n\x0b\x61\x63tivity_id\x18\x04 \x01(\t\x12\x30\n\x06result\x18\x05 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x10\n\x08identity\x18\x06 \x01(\t"*\n(RespondActivityTaskCompletedByIdResponse"\xa9\x03\n RespondActivityTaskFailedRequest\x12\x12\n\ntask_token\x18\x01 \x01(\x0c\x12\x31\n\x07\x66\x61ilure\x18\x02 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x11\n\tnamespace\x18\x04 \x01(\t\x12@\n\x16last_heartbeat_details\x18\x05 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x46\n\x0eworker_version\x18\x06 \x01(\x0b\x32*.temporal.api.common.v1.WorkerVersionStampB\x02\x18\x01\x12>\n\ndeployment\x18\x07 \x01(\x0b\x32&.temporal.api.deployment.v1.DeploymentB\x02\x18\x01\x12O\n\x12\x64\x65ployment_options\x18\x08 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentOptions"W\n!RespondActivityTaskFailedResponse\x12\x32\n\x08\x66\x61ilures\x18\x01 \x03(\x0b\x32 .temporal.api.failure.v1.Failure"\xfa\x01\n$RespondActivityTaskFailedByIdRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x12\x13\n\x0b\x61\x63tivity_id\x18\x04 \x01(\t\x12\x31\n\x07\x66\x61ilure\x18\x05 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12\x10\n\x08identity\x18\x06 \x01(\t\x12@\n\x16last_heartbeat_details\x18\x07 \x01(\x0b\x32 .temporal.api.common.v1.Payloads"[\n%RespondActivityTaskFailedByIdResponse\x12\x32\n\x08\x66\x61ilures\x18\x01 \x03(\x0b\x32 .temporal.api.failure.v1.Failure"\xe9\x02\n"RespondActivityTaskCanceledRequest\x12\x12\n\ntask_token\x18\x01 \x01(\x0c\x12\x31\n\x07\x64\x65tails\x18\x02 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x11\n\tnamespace\x18\x04 \x01(\t\x12\x46\n\x0eworker_version\x18\x05 \x01(\x0b\x32*.temporal.api.common.v1.WorkerVersionStampB\x02\x18\x01\x12>\n\ndeployment\x18\x06 \x01(\x0b\x32&.temporal.api.deployment.v1.DeploymentB\x02\x18\x01\x12O\n\x12\x64\x65ployment_options\x18\x07 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentOptions"%\n#RespondActivityTaskCanceledResponse"\x8b\x02\n&RespondActivityTaskCanceledByIdRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x12\x13\n\x0b\x61\x63tivity_id\x18\x04 \x01(\t\x12\x31\n\x07\x64\x65tails\x18\x05 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x10\n\x08identity\x18\x06 \x01(\t\x12O\n\x12\x64\x65ployment_options\x18\x07 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentOptions")\n\'RespondActivityTaskCanceledByIdResponse"\x84\x02\n%RequestCancelWorkflowExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x45\n\x12workflow_execution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x12\n\nrequest_id\x18\x04 \x01(\t\x12\x1e\n\x16\x66irst_execution_run_id\x18\x05 \x01(\t\x12\x0e\n\x06reason\x18\x06 \x01(\t\x12+\n\x05links\x18\x07 \x03(\x0b\x32\x1c.temporal.api.common.v1.Link"(\n&RequestCancelWorkflowExecutionResponse"\xde\x02\n\x1eSignalWorkflowExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x45\n\x12workflow_execution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x13\n\x0bsignal_name\x18\x03 \x01(\t\x12/\n\x05input\x18\x04 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x10\n\x08identity\x18\x05 \x01(\t\x12\x12\n\nrequest_id\x18\x06 \x01(\t\x12\x13\n\x07\x63ontrol\x18\x07 \x01(\tB\x02\x18\x01\x12.\n\x06header\x18\x08 \x01(\x0b\x32\x1e.temporal.api.common.v1.Header\x12+\n\x05links\x18\n \x03(\x0b\x32\x1c.temporal.api.common.v1.LinkJ\x04\x08\t\x10\n"!\n\x1fSignalWorkflowExecutionResponse"\xf1\t\n\'SignalWithStartWorkflowExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12;\n\rworkflow_type\x18\x03 \x01(\x0b\x32$.temporal.api.common.v1.WorkflowType\x12\x38\n\ntask_queue\x18\x04 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12/\n\x05input\x18\x05 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12=\n\x1aworkflow_execution_timeout\x18\x06 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x37\n\x14workflow_run_timeout\x18\x07 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x38\n\x15workflow_task_timeout\x18\x08 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x10\n\x08identity\x18\t \x01(\t\x12\x12\n\nrequest_id\x18\n \x01(\t\x12N\n\x18workflow_id_reuse_policy\x18\x0b \x01(\x0e\x32,.temporal.api.enums.v1.WorkflowIdReusePolicy\x12T\n\x1bworkflow_id_conflict_policy\x18\x16 \x01(\x0e\x32/.temporal.api.enums.v1.WorkflowIdConflictPolicy\x12\x13\n\x0bsignal_name\x18\x0c \x01(\t\x12\x36\n\x0csignal_input\x18\r \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x13\n\x07\x63ontrol\x18\x0e \x01(\tB\x02\x18\x01\x12\x39\n\x0cretry_policy\x18\x0f \x01(\x0b\x32#.temporal.api.common.v1.RetryPolicy\x12\x15\n\rcron_schedule\x18\x10 \x01(\t\x12*\n\x04memo\x18\x11 \x01(\x0b\x32\x1c.temporal.api.common.v1.Memo\x12\x43\n\x11search_attributes\x18\x12 \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes\x12.\n\x06header\x18\x13 \x01(\x0b\x32\x1e.temporal.api.common.v1.Header\x12\x37\n\x14workflow_start_delay\x18\x14 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x38\n\ruser_metadata\x18\x17 \x01(\x0b\x32!.temporal.api.sdk.v1.UserMetadata\x12+\n\x05links\x18\x18 \x03(\x0b\x32\x1c.temporal.api.common.v1.Link\x12I\n\x13versioning_override\x18\x19 \x01(\x0b\x32,.temporal.api.workflow.v1.VersioningOverride\x12\x32\n\x08priority\x18\x1a \x01(\x0b\x32 .temporal.api.common.v1.PriorityJ\x04\x08\x15\x10\x16"K\n(SignalWithStartWorkflowExecutionResponse\x12\x0e\n\x06run_id\x18\x01 \x01(\t\x12\x0f\n\x07started\x18\x02 \x01(\x08"\xc1\x03\n\x1dResetWorkflowExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x45\n\x12workflow_execution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x0e\n\x06reason\x18\x03 \x01(\t\x12%\n\x1dworkflow_task_finish_event_id\x18\x04 \x01(\x03\x12\x12\n\nrequest_id\x18\x05 \x01(\t\x12G\n\x12reset_reapply_type\x18\x06 \x01(\x0e\x32\'.temporal.api.enums.v1.ResetReapplyTypeB\x02\x18\x01\x12S\n\x1breset_reapply_exclude_types\x18\x07 \x03(\x0e\x32..temporal.api.enums.v1.ResetReapplyExcludeType\x12K\n\x15post_reset_operations\x18\x08 \x03(\x0b\x32,.temporal.api.workflow.v1.PostResetOperation\x12\x10\n\x08identity\x18\t \x01(\t"0\n\x1eResetWorkflowExecutionResponse\x12\x0e\n\x06run_id\x18\x01 \x01(\t"\x9f\x02\n!TerminateWorkflowExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x45\n\x12workflow_execution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x0e\n\x06reason\x18\x03 \x01(\t\x12\x31\n\x07\x64\x65tails\x18\x04 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x10\n\x08identity\x18\x05 \x01(\t\x12\x1e\n\x16\x66irst_execution_run_id\x18\x06 \x01(\t\x12+\n\x05links\x18\x07 \x03(\x0b\x32\x1c.temporal.api.common.v1.Link"$\n"TerminateWorkflowExecutionResponse"z\n\x1e\x44\x65leteWorkflowExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x45\n\x12workflow_execution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution"!\n\x1f\x44\x65leteWorkflowExecutionResponse"\xc9\x02\n!ListOpenWorkflowExecutionsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x19\n\x11maximum_page_size\x18\x02 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c\x12\x42\n\x11start_time_filter\x18\x04 \x01(\x0b\x32\'.temporal.api.filter.v1.StartTimeFilter\x12K\n\x10\x65xecution_filter\x18\x05 \x01(\x0b\x32/.temporal.api.filter.v1.WorkflowExecutionFilterH\x00\x12\x41\n\x0btype_filter\x18\x06 \x01(\x0b\x32*.temporal.api.filter.v1.WorkflowTypeFilterH\x00\x42\t\n\x07\x66ilters"\x82\x01\n"ListOpenWorkflowExecutionsResponse\x12\x43\n\nexecutions\x18\x01 \x03(\x0b\x32/.temporal.api.workflow.v1.WorkflowExecutionInfo\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c"\x8a\x03\n#ListClosedWorkflowExecutionsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x19\n\x11maximum_page_size\x18\x02 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c\x12\x42\n\x11start_time_filter\x18\x04 \x01(\x0b\x32\'.temporal.api.filter.v1.StartTimeFilter\x12K\n\x10\x65xecution_filter\x18\x05 \x01(\x0b\x32/.temporal.api.filter.v1.WorkflowExecutionFilterH\x00\x12\x41\n\x0btype_filter\x18\x06 \x01(\x0b\x32*.temporal.api.filter.v1.WorkflowTypeFilterH\x00\x12=\n\rstatus_filter\x18\x07 \x01(\x0b\x32$.temporal.api.filter.v1.StatusFilterH\x00\x42\t\n\x07\x66ilters"\x84\x01\n$ListClosedWorkflowExecutionsResponse\x12\x43\n\nexecutions\x18\x01 \x03(\x0b\x32/.temporal.api.workflow.v1.WorkflowExecutionInfo\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c"m\n\x1dListWorkflowExecutionsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x11\n\tpage_size\x18\x02 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c\x12\r\n\x05query\x18\x04 \x01(\t"~\n\x1eListWorkflowExecutionsResponse\x12\x43\n\nexecutions\x18\x01 \x03(\x0b\x32/.temporal.api.workflow.v1.WorkflowExecutionInfo\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c"u\n%ListArchivedWorkflowExecutionsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x11\n\tpage_size\x18\x02 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c\x12\r\n\x05query\x18\x04 \x01(\t"\x86\x01\n&ListArchivedWorkflowExecutionsResponse\x12\x43\n\nexecutions\x18\x01 \x03(\x0b\x32/.temporal.api.workflow.v1.WorkflowExecutionInfo\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c"m\n\x1dScanWorkflowExecutionsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x11\n\tpage_size\x18\x02 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c\x12\r\n\x05query\x18\x04 \x01(\t"~\n\x1eScanWorkflowExecutionsResponse\x12\x43\n\nexecutions\x18\x01 \x03(\x0b\x32/.temporal.api.workflow.v1.WorkflowExecutionInfo\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c"B\n\x1e\x43ountWorkflowExecutionsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\r\n\x05query\x18\x02 \x01(\t"\xed\x01\n\x1f\x43ountWorkflowExecutionsResponse\x12\r\n\x05\x63ount\x18\x01 \x01(\x03\x12\x61\n\x06groups\x18\x02 \x03(\x0b\x32Q.temporal.api.workflowservice.v1.CountWorkflowExecutionsResponse.AggregationGroup\x1aX\n\x10\x41ggregationGroup\x12\x35\n\x0cgroup_values\x18\x01 \x03(\x0b\x32\x1f.temporal.api.common.v1.Payload\x12\r\n\x05\x63ount\x18\x02 \x01(\x03"\x1c\n\x1aGetSearchAttributesRequest"\xc9\x01\n\x1bGetSearchAttributesResponse\x12T\n\x04keys\x18\x01 \x03(\x0b\x32\x46.temporal.api.workflowservice.v1.GetSearchAttributesResponse.KeysEntry\x1aT\n\tKeysEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x36\n\x05value\x18\x02 \x01(\x0e\x32\'.temporal.api.enums.v1.IndexedValueType:\x02\x38\x01"\xd0\x02\n RespondQueryTaskCompletedRequest\x12\x12\n\ntask_token\x18\x01 \x01(\x0c\x12>\n\x0e\x63ompleted_type\x18\x02 \x01(\x0e\x32&.temporal.api.enums.v1.QueryResultType\x12\x36\n\x0cquery_result\x18\x03 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x15\n\rerror_message\x18\x04 \x01(\t\x12\x11\n\tnamespace\x18\x06 \x01(\t\x12\x31\n\x07\x66\x61ilure\x18\x07 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12=\n\x05\x63\x61use\x18\x08 \x01(\x0e\x32..temporal.api.enums.v1.WorkflowTaskFailedCauseJ\x04\x08\x05\x10\x06"#\n!RespondQueryTaskCompletedResponse"n\n\x1bResetStickyTaskQueueRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12<\n\texecution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution"\x1e\n\x1cResetStickyTaskQueueResponse"\x9b\x02\n\x15ShutdownWorkerRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x19\n\x11sticky_task_queue\x18\x02 \x01(\t\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x0e\n\x06reason\x18\x04 \x01(\t\x12\x41\n\x10worker_heartbeat\x18\x05 \x01(\x0b\x32\'.temporal.api.worker.v1.WorkerHeartbeat\x12\x1b\n\x13worker_instance_key\x18\x06 \x01(\t\x12\x12\n\ntask_queue\x18\x07 \x01(\t\x12>\n\x10task_queue_types\x18\x08 \x03(\x0e\x32$.temporal.api.enums.v1.TaskQueueType"\x18\n\x16ShutdownWorkerResponse"\xe9\x01\n\x14QueryWorkflowRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12<\n\texecution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x33\n\x05query\x18\x03 \x01(\x0b\x32$.temporal.api.query.v1.WorkflowQuery\x12K\n\x16query_reject_condition\x18\x04 \x01(\x0e\x32+.temporal.api.enums.v1.QueryRejectCondition"\x8d\x01\n\x15QueryWorkflowResponse\x12\x36\n\x0cquery_result\x18\x01 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12<\n\x0equery_rejected\x18\x02 \x01(\x0b\x32$.temporal.api.query.v1.QueryRejected"s\n DescribeWorkflowExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12<\n\texecution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution"\x99\x05\n!DescribeWorkflowExecutionResponse\x12K\n\x10\x65xecution_config\x18\x01 \x01(\x0b\x32\x31.temporal.api.workflow.v1.WorkflowExecutionConfig\x12P\n\x17workflow_execution_info\x18\x02 \x01(\x0b\x32/.temporal.api.workflow.v1.WorkflowExecutionInfo\x12I\n\x12pending_activities\x18\x03 \x03(\x0b\x32-.temporal.api.workflow.v1.PendingActivityInfo\x12M\n\x10pending_children\x18\x04 \x03(\x0b\x32\x33.temporal.api.workflow.v1.PendingChildExecutionInfo\x12P\n\x15pending_workflow_task\x18\x05 \x01(\x0b\x32\x31.temporal.api.workflow.v1.PendingWorkflowTaskInfo\x12\x39\n\tcallbacks\x18\x06 \x03(\x0b\x32&.temporal.api.workflow.v1.CallbackInfo\x12U\n\x18pending_nexus_operations\x18\x07 \x03(\x0b\x32\x33.temporal.api.workflow.v1.PendingNexusOperationInfo\x12W\n\x16workflow_extended_info\x18\x08 \x01(\x0b\x32\x37.temporal.api.workflow.v1.WorkflowExecutionExtendedInfo"\x90\x04\n\x18\x44\x65scribeTaskQueueRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x38\n\ntask_queue\x18\x02 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12=\n\x0ftask_queue_type\x18\x03 \x01(\x0e\x32$.temporal.api.enums.v1.TaskQueueType\x12\x14\n\x0creport_stats\x18\x08 \x01(\x08\x12\x15\n\rreport_config\x18\x0b \x01(\x08\x12%\n\x19include_task_queue_status\x18\x04 \x01(\x08\x42\x02\x18\x01\x12\x42\n\x08\x61pi_mode\x18\x05 \x01(\x0e\x32,.temporal.api.enums.v1.DescribeTaskQueueModeB\x02\x18\x01\x12J\n\x08versions\x18\x06 \x01(\x0b\x32\x34.temporal.api.taskqueue.v1.TaskQueueVersionSelectionB\x02\x18\x01\x12\x42\n\x10task_queue_types\x18\x07 \x03(\x0e\x32$.temporal.api.enums.v1.TaskQueueTypeB\x02\x18\x01\x12\x1a\n\x0ereport_pollers\x18\t \x01(\x08\x42\x02\x18\x01\x12$\n\x18report_task_reachability\x18\n \x01(\x08\x42\x02\x18\x01"\xec\x07\n\x19\x44\x65scribeTaskQueueResponse\x12\x36\n\x07pollers\x18\x01 \x03(\x0b\x32%.temporal.api.taskqueue.v1.PollerInfo\x12\x38\n\x05stats\x18\x05 \x01(\x0b\x32).temporal.api.taskqueue.v1.TaskQueueStats\x12q\n\x15stats_by_priority_key\x18\x08 \x03(\x0b\x32R.temporal.api.workflowservice.v1.DescribeTaskQueueResponse.StatsByPriorityKeyEntry\x12K\n\x0fversioning_info\x18\x04 \x01(\x0b\x32\x32.temporal.api.taskqueue.v1.TaskQueueVersioningInfo\x12:\n\x06\x63onfig\x18\x06 \x01(\x0b\x32*.temporal.api.taskqueue.v1.TaskQueueConfig\x12k\n\x14\x65\x66\x66\x65\x63tive_rate_limit\x18\x07 \x01(\x0b\x32M.temporal.api.workflowservice.v1.DescribeTaskQueueResponse.EffectiveRateLimit\x12I\n\x11task_queue_status\x18\x02 \x01(\x0b\x32*.temporal.api.taskqueue.v1.TaskQueueStatusB\x02\x18\x01\x12g\n\rversions_info\x18\x03 \x03(\x0b\x32L.temporal.api.workflowservice.v1.DescribeTaskQueueResponse.VersionsInfoEntryB\x02\x18\x01\x1a\x64\n\x17StatsByPriorityKeyEntry\x12\x0b\n\x03key\x18\x01 \x01(\x05\x12\x38\n\x05value\x18\x02 \x01(\x0b\x32).temporal.api.taskqueue.v1.TaskQueueStats:\x02\x38\x01\x1at\n\x12\x45\x66\x66\x65\x63tiveRateLimit\x12\x1b\n\x13requests_per_second\x18\x01 \x01(\x02\x12\x41\n\x11rate_limit_source\x18\x02 \x01(\x0e\x32&.temporal.api.enums.v1.RateLimitSource\x1a\x64\n\x11VersionsInfoEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12>\n\x05value\x18\x02 \x01(\x0b\x32/.temporal.api.taskqueue.v1.TaskQueueVersionInfo:\x02\x38\x01"\x17\n\x15GetClusterInfoRequest"\xd1\x03\n\x16GetClusterInfoResponse\x12h\n\x11supported_clients\x18\x01 \x03(\x0b\x32M.temporal.api.workflowservice.v1.GetClusterInfoResponse.SupportedClientsEntry\x12\x16\n\x0eserver_version\x18\x02 \x01(\t\x12\x12\n\ncluster_id\x18\x03 \x01(\t\x12:\n\x0cversion_info\x18\x04 \x01(\x0b\x32$.temporal.api.version.v1.VersionInfo\x12\x14\n\x0c\x63luster_name\x18\x05 \x01(\t\x12\x1b\n\x13history_shard_count\x18\x06 \x01(\x05\x12\x19\n\x11persistence_store\x18\x07 \x01(\t\x12\x18\n\x10visibility_store\x18\x08 \x01(\t\x12 \n\x18initial_failover_version\x18\t \x01(\x03\x12"\n\x1a\x66\x61ilover_version_increment\x18\n \x01(\x03\x1a\x37\n\x15SupportedClientsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01"\x16\n\x14GetSystemInfoRequest"\xf4\x03\n\x15GetSystemInfoResponse\x12\x16\n\x0eserver_version\x18\x01 \x01(\t\x12Y\n\x0c\x63\x61pabilities\x18\x02 \x01(\x0b\x32\x43.temporal.api.workflowservice.v1.GetSystemInfoResponse.Capabilities\x1a\xe7\x02\n\x0c\x43\x61pabilities\x12\x1f\n\x17signal_and_query_header\x18\x01 \x01(\x08\x12&\n\x1einternal_error_differentiation\x18\x02 \x01(\x08\x12*\n"activity_failure_include_heartbeat\x18\x03 \x01(\x08\x12\x1a\n\x12supports_schedules\x18\x04 \x01(\x08\x12"\n\x1a\x65ncoded_failure_attributes\x18\x05 \x01(\x08\x12!\n\x19\x62uild_id_based_versioning\x18\x06 \x01(\x08\x12\x13\n\x0bupsert_memo\x18\x07 \x01(\x08\x12\x1c\n\x14\x65\x61ger_workflow_start\x18\x08 \x01(\x08\x12\x14\n\x0csdk_metadata\x18\t \x01(\x08\x12\'\n\x1f\x63ount_group_by_execution_status\x18\n \x01(\x08\x12\r\n\x05nexus\x18\x0b \x01(\x08"m\n\x1eListTaskQueuePartitionsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x38\n\ntask_queue\x18\x02 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue"\xdf\x01\n\x1fListTaskQueuePartitionsResponse\x12]\n\x1e\x61\x63tivity_task_queue_partitions\x18\x01 \x03(\x0b\x32\x35.temporal.api.taskqueue.v1.TaskQueuePartitionMetadata\x12]\n\x1eworkflow_task_queue_partitions\x18\x02 \x03(\x0b\x32\x35.temporal.api.taskqueue.v1.TaskQueuePartitionMetadata"\xcc\x02\n\x15\x43reateScheduleRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bschedule_id\x18\x02 \x01(\t\x12\x34\n\x08schedule\x18\x03 \x01(\x0b\x32".temporal.api.schedule.v1.Schedule\x12>\n\rinitial_patch\x18\x04 \x01(\x0b\x32\'.temporal.api.schedule.v1.SchedulePatch\x12\x10\n\x08identity\x18\x05 \x01(\t\x12\x12\n\nrequest_id\x18\x06 \x01(\t\x12*\n\x04memo\x18\x07 \x01(\x0b\x32\x1c.temporal.api.common.v1.Memo\x12\x43\n\x11search_attributes\x18\x08 \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes"0\n\x16\x43reateScheduleResponse\x12\x16\n\x0e\x63onflict_token\x18\x01 \x01(\x0c"A\n\x17\x44\x65scribeScheduleRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bschedule_id\x18\x02 \x01(\t"\x8f\x02\n\x18\x44\x65scribeScheduleResponse\x12\x34\n\x08schedule\x18\x01 \x01(\x0b\x32".temporal.api.schedule.v1.Schedule\x12\x34\n\x04info\x18\x02 \x01(\x0b\x32&.temporal.api.schedule.v1.ScheduleInfo\x12*\n\x04memo\x18\x03 \x01(\x0b\x32\x1c.temporal.api.common.v1.Memo\x12\x43\n\x11search_attributes\x18\x04 \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes\x12\x16\n\x0e\x63onflict_token\x18\x05 \x01(\x0c"\xf8\x01\n\x15UpdateScheduleRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bschedule_id\x18\x02 \x01(\t\x12\x34\n\x08schedule\x18\x03 \x01(\x0b\x32".temporal.api.schedule.v1.Schedule\x12\x16\n\x0e\x63onflict_token\x18\x04 \x01(\x0c\x12\x10\n\x08identity\x18\x05 \x01(\t\x12\x12\n\nrequest_id\x18\x06 \x01(\t\x12\x43\n\x11search_attributes\x18\x07 \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes"\x18\n\x16UpdateScheduleResponse"\x9c\x01\n\x14PatchScheduleRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bschedule_id\x18\x02 \x01(\t\x12\x36\n\x05patch\x18\x03 \x01(\x0b\x32\'.temporal.api.schedule.v1.SchedulePatch\x12\x10\n\x08identity\x18\x04 \x01(\t\x12\x12\n\nrequest_id\x18\x05 \x01(\t"\x17\n\x15PatchScheduleResponse"\xa8\x01\n ListScheduleMatchingTimesRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bschedule_id\x18\x02 \x01(\t\x12.\n\nstart_time\x18\x03 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12,\n\x08\x65nd_time\x18\x04 \x01(\x0b\x32\x1a.google.protobuf.Timestamp"S\n!ListScheduleMatchingTimesResponse\x12.\n\nstart_time\x18\x01 \x03(\x0b\x32\x1a.google.protobuf.Timestamp"Q\n\x15\x44\x65leteScheduleRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bschedule_id\x18\x02 \x01(\t\x12\x10\n\x08identity\x18\x03 \x01(\t"\x18\n\x16\x44\x65leteScheduleResponse"l\n\x14ListSchedulesRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x19\n\x11maximum_page_size\x18\x02 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c\x12\r\n\x05query\x18\x04 \x01(\t"p\n\x15ListSchedulesResponse\x12>\n\tschedules\x18\x01 \x03(\x0b\x32+.temporal.api.schedule.v1.ScheduleListEntry\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c"9\n\x15\x43ountSchedulesRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\r\n\x05query\x18\x02 \x01(\t"\xdb\x01\n\x16\x43ountSchedulesResponse\x12\r\n\x05\x63ount\x18\x01 \x01(\x03\x12X\n\x06groups\x18\x02 \x03(\x0b\x32H.temporal.api.workflowservice.v1.CountSchedulesResponse.AggregationGroup\x1aX\n\x10\x41ggregationGroup\x12\x35\n\x0cgroup_values\x18\x01 \x03(\x0b\x32\x1f.temporal.api.common.v1.Payload\x12\r\n\x05\x63ount\x18\x02 \x01(\x03"\x86\x05\n\'UpdateWorkerBuildIdCompatibilityRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x12\n\ntask_queue\x18\x02 \x01(\t\x12-\n#add_new_build_id_in_new_default_set\x18\x03 \x01(\tH\x00\x12\x87\x01\n\x1b\x61\x64\x64_new_compatible_build_id\x18\x04 \x01(\x0b\x32`.temporal.api.workflowservice.v1.UpdateWorkerBuildIdCompatibilityRequest.AddNewCompatibleVersionH\x00\x12!\n\x17promote_set_by_build_id\x18\x05 \x01(\tH\x00\x12%\n\x1bpromote_build_id_within_set\x18\x06 \x01(\tH\x00\x12h\n\nmerge_sets\x18\x07 \x01(\x0b\x32R.temporal.api.workflowservice.v1.UpdateWorkerBuildIdCompatibilityRequest.MergeSetsH\x00\x1ao\n\x17\x41\x64\x64NewCompatibleVersion\x12\x14\n\x0cnew_build_id\x18\x01 \x01(\t\x12$\n\x1c\x65xisting_compatible_build_id\x18\x02 \x01(\t\x12\x18\n\x10make_set_default\x18\x03 \x01(\x08\x1aI\n\tMergeSets\x12\x1c\n\x14primary_set_build_id\x18\x01 \x01(\t\x12\x1e\n\x16secondary_set_build_id\x18\x02 \x01(\tB\x0b\n\toperation"@\n(UpdateWorkerBuildIdCompatibilityResponseJ\x04\x08\x01\x10\x02R\x0eversion_set_id"_\n$GetWorkerBuildIdCompatibilityRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x12\n\ntask_queue\x18\x02 \x01(\t\x12\x10\n\x08max_sets\x18\x03 \x01(\x05"t\n%GetWorkerBuildIdCompatibilityResponse\x12K\n\x12major_version_sets\x18\x01 \x03(\x0b\x32/.temporal.api.taskqueue.v1.CompatibleVersionSet"\xb5\r\n"UpdateWorkerVersioningRulesRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x12\n\ntask_queue\x18\x02 \x01(\t\x12\x16\n\x0e\x63onflict_token\x18\x03 \x01(\x0c\x12\x81\x01\n\x16insert_assignment_rule\x18\x04 \x01(\x0b\x32_.temporal.api.workflowservice.v1.UpdateWorkerVersioningRulesRequest.InsertBuildIdAssignmentRuleH\x00\x12\x83\x01\n\x17replace_assignment_rule\x18\x05 \x01(\x0b\x32`.temporal.api.workflowservice.v1.UpdateWorkerVersioningRulesRequest.ReplaceBuildIdAssignmentRuleH\x00\x12\x81\x01\n\x16\x64\x65lete_assignment_rule\x18\x06 \x01(\x0b\x32_.temporal.api.workflowservice.v1.UpdateWorkerVersioningRulesRequest.DeleteBuildIdAssignmentRuleH\x00\x12\x8c\x01\n\x1c\x61\x64\x64_compatible_redirect_rule\x18\x07 \x01(\x0b\x32\x64.temporal.api.workflowservice.v1.UpdateWorkerVersioningRulesRequest.AddCompatibleBuildIdRedirectRuleH\x00\x12\x94\x01\n replace_compatible_redirect_rule\x18\x08 \x01(\x0b\x32h.temporal.api.workflowservice.v1.UpdateWorkerVersioningRulesRequest.ReplaceCompatibleBuildIdRedirectRuleH\x00\x12\x92\x01\n\x1f\x64\x65lete_compatible_redirect_rule\x18\t \x01(\x0b\x32g.temporal.api.workflowservice.v1.UpdateWorkerVersioningRulesRequest.DeleteCompatibleBuildIdRedirectRuleH\x00\x12l\n\x0f\x63ommit_build_id\x18\n \x01(\x0b\x32Q.temporal.api.workflowservice.v1.UpdateWorkerVersioningRulesRequest.CommitBuildIdH\x00\x1aq\n\x1bInsertBuildIdAssignmentRule\x12\x12\n\nrule_index\x18\x01 \x01(\x05\x12>\n\x04rule\x18\x02 \x01(\x0b\x32\x30.temporal.api.taskqueue.v1.BuildIdAssignmentRule\x1a\x81\x01\n\x1cReplaceBuildIdAssignmentRule\x12\x12\n\nrule_index\x18\x01 \x01(\x05\x12>\n\x04rule\x18\x02 \x01(\x0b\x32\x30.temporal.api.taskqueue.v1.BuildIdAssignmentRule\x12\r\n\x05\x66orce\x18\x03 \x01(\x08\x1a@\n\x1b\x44\x65leteBuildIdAssignmentRule\x12\x12\n\nrule_index\x18\x01 \x01(\x05\x12\r\n\x05\x66orce\x18\x02 \x01(\x08\x1aj\n AddCompatibleBuildIdRedirectRule\x12\x46\n\x04rule\x18\x01 \x01(\x0b\x32\x38.temporal.api.taskqueue.v1.CompatibleBuildIdRedirectRule\x1an\n$ReplaceCompatibleBuildIdRedirectRule\x12\x46\n\x04rule\x18\x01 \x01(\x0b\x32\x38.temporal.api.taskqueue.v1.CompatibleBuildIdRedirectRule\x1a>\n#DeleteCompatibleBuildIdRedirectRule\x12\x17\n\x0fsource_build_id\x18\x01 \x01(\t\x1a\x37\n\rCommitBuildId\x12\x17\n\x0ftarget_build_id\x18\x01 \x01(\t\x12\r\n\x05\x66orce\x18\x02 \x01(\x08\x42\x0b\n\toperation"\xfc\x01\n#UpdateWorkerVersioningRulesResponse\x12U\n\x10\x61ssignment_rules\x18\x01 \x03(\x0b\x32;.temporal.api.taskqueue.v1.TimestampedBuildIdAssignmentRule\x12\x66\n\x19\x63ompatible_redirect_rules\x18\x02 \x03(\x0b\x32\x43.temporal.api.taskqueue.v1.TimestampedCompatibleBuildIdRedirectRule\x12\x16\n\x0e\x63onflict_token\x18\x03 \x01(\x0c"H\n\x1fGetWorkerVersioningRulesRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x12\n\ntask_queue\x18\x02 \x01(\t"\xf9\x01\n GetWorkerVersioningRulesResponse\x12U\n\x10\x61ssignment_rules\x18\x01 \x03(\x0b\x32;.temporal.api.taskqueue.v1.TimestampedBuildIdAssignmentRule\x12\x66\n\x19\x63ompatible_redirect_rules\x18\x02 \x03(\x0b\x32\x43.temporal.api.taskqueue.v1.TimestampedCompatibleBuildIdRedirectRule\x12\x16\n\x0e\x63onflict_token\x18\x03 \x01(\x0c"\x9c\x01\n GetWorkerTaskReachabilityRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x11\n\tbuild_ids\x18\x02 \x03(\t\x12\x13\n\x0btask_queues\x18\x03 \x03(\t\x12=\n\x0creachability\x18\x04 \x01(\x0e\x32\'.temporal.api.enums.v1.TaskReachability"r\n!GetWorkerTaskReachabilityResponse\x12M\n\x15\x62uild_id_reachability\x18\x01 \x03(\x0b\x32..temporal.api.taskqueue.v1.BuildIdReachability"\x85\x02\n\x1eUpdateWorkflowExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x45\n\x12workflow_execution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x1e\n\x16\x66irst_execution_run_id\x18\x03 \x01(\t\x12\x37\n\x0bwait_policy\x18\x04 \x01(\x0b\x32".temporal.api.update.v1.WaitPolicy\x12\x30\n\x07request\x18\x05 \x01(\x0b\x32\x1f.temporal.api.update.v1.Request"\xd7\x01\n\x1fUpdateWorkflowExecutionResponse\x12\x35\n\nupdate_ref\x18\x01 \x01(\x0b\x32!.temporal.api.update.v1.UpdateRef\x12\x30\n\x07outcome\x18\x02 \x01(\x0b\x32\x1f.temporal.api.update.v1.Outcome\x12K\n\x05stage\x18\x03 \x01(\x0e\x32<.temporal.api.enums.v1.UpdateWorkflowExecutionLifecycleStage"\xf4\x07\n\x1aStartBatchOperationRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x18\n\x10visibility_query\x18\x02 \x01(\t\x12\x0e\n\x06job_id\x18\x03 \x01(\t\x12\x0e\n\x06reason\x18\x04 \x01(\t\x12=\n\nexecutions\x18\x05 \x03(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12!\n\x19max_operations_per_second\x18\x06 \x01(\x02\x12Q\n\x15termination_operation\x18\n \x01(\x0b\x32\x30.temporal.api.batch.v1.BatchOperationTerminationH\x00\x12G\n\x10signal_operation\x18\x0b \x01(\x0b\x32+.temporal.api.batch.v1.BatchOperationSignalH\x00\x12S\n\x16\x63\x61ncellation_operation\x18\x0c \x01(\x0b\x32\x31.temporal.api.batch.v1.BatchOperationCancellationH\x00\x12K\n\x12\x64\x65letion_operation\x18\r \x01(\x0b\x32-.temporal.api.batch.v1.BatchOperationDeletionH\x00\x12\x45\n\x0freset_operation\x18\x0e \x01(\x0b\x32*.temporal.api.batch.v1.BatchOperationResetH\x00\x12p\n!update_workflow_options_operation\x18\x0f \x01(\x0b\x32\x43.temporal.api.batch.v1.BatchOperationUpdateWorkflowExecutionOptionsH\x00\x12^\n\x1cunpause_activities_operation\x18\x10 \x01(\x0b\x32\x36.temporal.api.batch.v1.BatchOperationUnpauseActivitiesH\x00\x12Z\n\x1areset_activities_operation\x18\x11 \x01(\x0b\x32\x34.temporal.api.batch.v1.BatchOperationResetActivitiesH\x00\x12g\n!update_activity_options_operation\x18\x12 \x01(\x0b\x32:.temporal.api.batch.v1.BatchOperationUpdateActivityOptionsH\x00\x42\x0b\n\toperation"\x1d\n\x1bStartBatchOperationResponse"`\n\x19StopBatchOperationRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x0e\n\x06job_id\x18\x02 \x01(\t\x12\x0e\n\x06reason\x18\x03 \x01(\t\x12\x10\n\x08identity\x18\x04 \x01(\t"\x1c\n\x1aStopBatchOperationResponse"B\n\x1d\x44\x65scribeBatchOperationRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x0e\n\x06job_id\x18\x02 \x01(\t"\x92\x03\n\x1e\x44\x65scribeBatchOperationResponse\x12\x41\n\x0eoperation_type\x18\x01 \x01(\x0e\x32).temporal.api.enums.v1.BatchOperationType\x12\x0e\n\x06job_id\x18\x02 \x01(\t\x12\x39\n\x05state\x18\x03 \x01(\x0e\x32*.temporal.api.enums.v1.BatchOperationState\x12.\n\nstart_time\x18\x04 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12.\n\nclose_time\x18\x05 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x1d\n\x15total_operation_count\x18\x06 \x01(\x03\x12 \n\x18\x63omplete_operation_count\x18\x07 \x01(\x03\x12\x1f\n\x17\x66\x61ilure_operation_count\x18\x08 \x01(\x03\x12\x10\n\x08identity\x18\t \x01(\t\x12\x0e\n\x06reason\x18\n \x01(\t"[\n\x1aListBatchOperationsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x11\n\tpage_size\x18\x02 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c"y\n\x1bListBatchOperationsResponse\x12\x41\n\x0eoperation_info\x18\x01 \x03(\x0b\x32).temporal.api.batch.v1.BatchOperationInfo\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c"\xb9\x01\n"PollWorkflowExecutionUpdateRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x35\n\nupdate_ref\x18\x02 \x01(\x0b\x32!.temporal.api.update.v1.UpdateRef\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x37\n\x0bwait_policy\x18\x04 \x01(\x0b\x32".temporal.api.update.v1.WaitPolicy"\xdb\x01\n#PollWorkflowExecutionUpdateResponse\x12\x30\n\x07outcome\x18\x01 \x01(\x0b\x32\x1f.temporal.api.update.v1.Outcome\x12K\n\x05stage\x18\x02 \x01(\x0e\x32<.temporal.api.enums.v1.UpdateWorkflowExecutionLifecycleStage\x12\x35\n\nupdate_ref\x18\x03 \x01(\x0b\x32!.temporal.api.update.v1.UpdateRef"\x87\x03\n\x19PollNexusTaskQueueRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x10\n\x08identity\x18\x02 \x01(\t\x12\x1b\n\x13worker_instance_key\x18\x08 \x01(\t\x12\x38\n\ntask_queue\x18\x03 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12Z\n\x1bworker_version_capabilities\x18\x04 \x01(\x0b\x32\x31.temporal.api.common.v1.WorkerVersionCapabilitiesB\x02\x18\x01\x12O\n\x12\x64\x65ployment_options\x18\x06 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentOptions\x12\x41\n\x10worker_heartbeat\x18\x07 \x03(\x0b\x32\'.temporal.api.worker.v1.WorkerHeartbeat"\xb4\x01\n\x1aPollNexusTaskQueueResponse\x12\x12\n\ntask_token\x18\x01 \x01(\x0c\x12/\n\x07request\x18\x02 \x01(\x0b\x32\x1e.temporal.api.nexus.v1.Request\x12Q\n\x17poller_scaling_decision\x18\x03 \x01(\x0b\x32\x30.temporal.api.taskqueue.v1.PollerScalingDecision"\x8e\x01\n RespondNexusTaskCompletedRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x10\n\x08identity\x18\x02 \x01(\t\x12\x12\n\ntask_token\x18\x03 \x01(\x0c\x12\x31\n\x08response\x18\x04 \x01(\x0b\x32\x1f.temporal.api.nexus.v1.Response"#\n!RespondNexusTaskCompletedResponse"\xc3\x01\n\x1dRespondNexusTaskFailedRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x10\n\x08identity\x18\x02 \x01(\t\x12\x12\n\ntask_token\x18\x03 \x01(\x0c\x12\x36\n\x05\x65rror\x18\x04 \x01(\x0b\x32#.temporal.api.nexus.v1.HandlerErrorB\x02\x18\x01\x12\x31\n\x07\x66\x61ilure\x18\x05 \x01(\x0b\x32 .temporal.api.failure.v1.Failure" \n\x1eRespondNexusTaskFailedResponse"\xdf\x02\n\x1c\x45xecuteMultiOperationRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12[\n\noperations\x18\x02 \x03(\x0b\x32G.temporal.api.workflowservice.v1.ExecuteMultiOperationRequest.Operation\x1a\xce\x01\n\tOperation\x12X\n\x0estart_workflow\x18\x01 \x01(\x0b\x32>.temporal.api.workflowservice.v1.StartWorkflowExecutionRequestH\x00\x12Z\n\x0fupdate_workflow\x18\x02 \x01(\x0b\x32?.temporal.api.workflowservice.v1.UpdateWorkflowExecutionRequestH\x00\x42\x0b\n\toperation"\xcc\x02\n\x1d\x45xecuteMultiOperationResponse\x12Z\n\tresponses\x18\x01 \x03(\x0b\x32G.temporal.api.workflowservice.v1.ExecuteMultiOperationResponse.Response\x1a\xce\x01\n\x08Response\x12Y\n\x0estart_workflow\x18\x01 \x01(\x0b\x32?.temporal.api.workflowservice.v1.StartWorkflowExecutionResponseH\x00\x12[\n\x0fupdate_workflow\x18\x02 \x01(\x0b\x32@.temporal.api.workflowservice.v1.UpdateWorkflowExecutionResponseH\x00\x42\n\n\x08response"\xd0\x02\n\x1cUpdateActivityOptionsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12<\n\texecution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x43\n\x10\x61\x63tivity_options\x18\x04 \x01(\x0b\x32).temporal.api.activity.v1.ActivityOptions\x12/\n\x0bupdate_mask\x18\x05 \x01(\x0b\x32\x1a.google.protobuf.FieldMask\x12\x0c\n\x02id\x18\x06 \x01(\tH\x00\x12\x0e\n\x04type\x18\x07 \x01(\tH\x00\x12\x13\n\tmatch_all\x18\t \x01(\x08H\x00\x12\x18\n\x10restore_original\x18\x08 \x01(\x08\x42\n\n\x08\x61\x63tivity"d\n\x1dUpdateActivityOptionsResponse\x12\x43\n\x10\x61\x63tivity_options\x18\x01 \x01(\x0b\x32).temporal.api.activity.v1.ActivityOptions"\xb3\x01\n\x14PauseActivityRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12<\n\texecution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x0c\n\x02id\x18\x04 \x01(\tH\x00\x12\x0e\n\x04type\x18\x05 \x01(\tH\x00\x12\x0e\n\x06reason\x18\x06 \x01(\tB\n\n\x08\x61\x63tivity"\x17\n\x15PauseActivityResponse"\x98\x02\n\x16UnpauseActivityRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12<\n\texecution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x0c\n\x02id\x18\x04 \x01(\tH\x00\x12\x0e\n\x04type\x18\x05 \x01(\tH\x00\x12\x15\n\x0bunpause_all\x18\x06 \x01(\x08H\x00\x12\x16\n\x0ereset_attempts\x18\x07 \x01(\x08\x12\x17\n\x0freset_heartbeat\x18\x08 \x01(\x08\x12)\n\x06jitter\x18\t \x01(\x0b\x32\x19.google.protobuf.DurationB\n\n\x08\x61\x63tivity"\x19\n\x17UnpauseActivityResponse"\xb3\x02\n\x14ResetActivityRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12<\n\texecution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x0c\n\x02id\x18\x04 \x01(\tH\x00\x12\x0e\n\x04type\x18\x05 \x01(\tH\x00\x12\x13\n\tmatch_all\x18\n \x01(\x08H\x00\x12\x17\n\x0freset_heartbeat\x18\x06 \x01(\x08\x12\x13\n\x0bkeep_paused\x18\x07 \x01(\x08\x12)\n\x06jitter\x18\x08 \x01(\x0b\x32\x19.google.protobuf.Duration\x12 \n\x18restore_original_options\x18\t \x01(\x08\x42\n\n\x08\x61\x63tivity"\x17\n\x15ResetActivityResponse"\x9c\x02\n%UpdateWorkflowExecutionOptionsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x45\n\x12workflow_execution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12V\n\x1aworkflow_execution_options\x18\x03 \x01(\x0b\x32\x32.temporal.api.workflow.v1.WorkflowExecutionOptions\x12/\n\x0bupdate_mask\x18\x04 \x01(\x0b\x32\x1a.google.protobuf.FieldMask\x12\x10\n\x08identity\x18\x05 \x01(\t"\x80\x01\n&UpdateWorkflowExecutionOptionsResponse\x12V\n\x1aworkflow_execution_options\x18\x01 \x01(\x0b\x32\x32.temporal.api.workflow.v1.WorkflowExecutionOptions"j\n\x19\x44\x65scribeDeploymentRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12:\n\ndeployment\x18\x02 \x01(\x0b\x32&.temporal.api.deployment.v1.Deployment"a\n\x1a\x44\x65scribeDeploymentResponse\x12\x43\n\x0f\x64\x65ployment_info\x18\x01 \x01(\x0b\x32*.temporal.api.deployment.v1.DeploymentInfo"\xc2\x01\n&DescribeWorkerDeploymentVersionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x07version\x18\x02 \x01(\tB\x02\x18\x01\x12O\n\x12\x64\x65ployment_version\x18\x03 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersion\x12\x1f\n\x17report_task_queue_stats\x18\x04 \x01(\x08"\x8c\x05\n\'DescribeWorkerDeploymentVersionResponse\x12_\n\x1eworker_deployment_version_info\x18\x01 \x01(\x0b\x32\x37.temporal.api.deployment.v1.WorkerDeploymentVersionInfo\x12v\n\x13version_task_queues\x18\x02 \x03(\x0b\x32Y.temporal.api.workflowservice.v1.DescribeWorkerDeploymentVersionResponse.VersionTaskQueue\x1a\x87\x03\n\x10VersionTaskQueue\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x32\n\x04type\x18\x02 \x01(\x0e\x32$.temporal.api.enums.v1.TaskQueueType\x12\x38\n\x05stats\x18\x03 \x01(\x0b\x32).temporal.api.taskqueue.v1.TaskQueueStats\x12\x90\x01\n\x15stats_by_priority_key\x18\x04 \x03(\x0b\x32q.temporal.api.workflowservice.v1.DescribeWorkerDeploymentVersionResponse.VersionTaskQueue.StatsByPriorityKeyEntry\x1a\x64\n\x17StatsByPriorityKeyEntry\x12\x0b\n\x03key\x18\x01 \x01(\x05\x12\x38\n\x05value\x18\x02 \x01(\x0b\x32).temporal.api.taskqueue.v1.TaskQueueStats:\x02\x38\x01"M\n\x1f\x44\x65scribeWorkerDeploymentRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x17\n\x0f\x64\x65ployment_name\x18\x02 \x01(\t"\x8c\x01\n DescribeWorkerDeploymentResponse\x12\x16\n\x0e\x63onflict_token\x18\x01 \x01(\x0c\x12P\n\x16worker_deployment_info\x18\x02 \x01(\x0b\x32\x30.temporal.api.deployment.v1.WorkerDeploymentInfo"l\n\x16ListDeploymentsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x11\n\tpage_size\x18\x02 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c\x12\x13\n\x0bseries_name\x18\x04 \x01(\t"w\n\x17ListDeploymentsResponse\x12\x17\n\x0fnext_page_token\x18\x01 \x01(\x0c\x12\x43\n\x0b\x64\x65ployments\x18\x02 \x03(\x0b\x32..temporal.api.deployment.v1.DeploymentListInfo"\xcd\x01\n\x1bSetCurrentDeploymentRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12:\n\ndeployment\x18\x02 \x01(\x0b\x32&.temporal.api.deployment.v1.Deployment\x12\x10\n\x08identity\x18\x03 \x01(\t\x12M\n\x0fupdate_metadata\x18\x04 \x01(\x0b\x32\x34.temporal.api.deployment.v1.UpdateDeploymentMetadata"\xb9\x01\n\x1cSetCurrentDeploymentResponse\x12K\n\x17\x63urrent_deployment_info\x18\x01 \x01(\x0b\x32*.temporal.api.deployment.v1.DeploymentInfo\x12L\n\x18previous_deployment_info\x18\x02 \x01(\x0b\x32*.temporal.api.deployment.v1.DeploymentInfo"\xe5\x01\n(SetWorkerDeploymentCurrentVersionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x17\n\x0f\x64\x65ployment_name\x18\x02 \x01(\t\x12\x13\n\x07version\x18\x03 \x01(\tB\x02\x18\x01\x12\x10\n\x08\x62uild_id\x18\x07 \x01(\t\x12\x16\n\x0e\x63onflict_token\x18\x04 \x01(\x0c\x12\x10\n\x08identity\x18\x05 \x01(\t\x12"\n\x1aignore_missing_task_queues\x18\x06 \x01(\x08\x12\x18\n\x10\x61llow_no_pollers\x18\t \x01(\x08"\xbf\x01\n)SetWorkerDeploymentCurrentVersionResponse\x12\x16\n\x0e\x63onflict_token\x18\x01 \x01(\x0c\x12\x1c\n\x10previous_version\x18\x02 \x01(\tB\x02\x18\x01\x12\\\n\x1bprevious_deployment_version\x18\x03 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersionB\x02\x18\x01"\xf9\x01\n(SetWorkerDeploymentRampingVersionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x17\n\x0f\x64\x65ployment_name\x18\x02 \x01(\t\x12\x13\n\x07version\x18\x03 \x01(\tB\x02\x18\x01\x12\x10\n\x08\x62uild_id\x18\x08 \x01(\t\x12\x12\n\npercentage\x18\x04 \x01(\x02\x12\x16\n\x0e\x63onflict_token\x18\x05 \x01(\x0c\x12\x10\n\x08identity\x18\x06 \x01(\t\x12"\n\x1aignore_missing_task_queues\x18\x07 \x01(\x08\x12\x18\n\x10\x61llow_no_pollers\x18\n \x01(\x08"\xe0\x01\n)SetWorkerDeploymentRampingVersionResponse\x12\x16\n\x0e\x63onflict_token\x18\x01 \x01(\x0c\x12\x1c\n\x10previous_version\x18\x02 \x01(\tB\x02\x18\x01\x12\\\n\x1bprevious_deployment_version\x18\x04 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersionB\x02\x18\x01\x12\x1f\n\x13previous_percentage\x18\x03 \x01(\x02\x42\x02\x18\x01"]\n\x1cListWorkerDeploymentsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x11\n\tpage_size\x18\x02 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c"\x9f\x05\n\x1dListWorkerDeploymentsResponse\x12\x17\n\x0fnext_page_token\x18\x01 \x01(\x0c\x12r\n\x12worker_deployments\x18\x02 \x03(\x0b\x32V.temporal.api.workflowservice.v1.ListWorkerDeploymentsResponse.WorkerDeploymentSummary\x1a\xf0\x03\n\x17WorkerDeploymentSummary\x12\x0c\n\x04name\x18\x01 \x01(\t\x12/\n\x0b\x63reate_time\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x41\n\x0erouting_config\x18\x03 \x01(\x0b\x32).temporal.api.deployment.v1.RoutingConfig\x12o\n\x16latest_version_summary\x18\x04 \x01(\x0b\x32O.temporal.api.deployment.v1.WorkerDeploymentInfo.WorkerDeploymentVersionSummary\x12p\n\x17\x63urrent_version_summary\x18\x05 \x01(\x0b\x32O.temporal.api.deployment.v1.WorkerDeploymentInfo.WorkerDeploymentVersionSummary\x12p\n\x17ramping_version_summary\x18\x06 \x01(\x0b\x32O.temporal.api.deployment.v1.WorkerDeploymentInfo.WorkerDeploymentVersionSummary"\xc8\x01\n$DeleteWorkerDeploymentVersionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x07version\x18\x02 \x01(\tB\x02\x18\x01\x12O\n\x12\x64\x65ployment_version\x18\x05 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersion\x12\x15\n\rskip_drainage\x18\x03 \x01(\x08\x12\x10\n\x08identity\x18\x04 \x01(\t"\'\n%DeleteWorkerDeploymentVersionResponse"]\n\x1d\x44\x65leteWorkerDeploymentRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x17\n\x0f\x64\x65ployment_name\x18\x02 \x01(\t\x12\x10\n\x08identity\x18\x03 \x01(\t" \n\x1e\x44\x65leteWorkerDeploymentResponse"\xa2\x03\n,UpdateWorkerDeploymentVersionMetadataRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x07version\x18\x02 \x01(\tB\x02\x18\x01\x12O\n\x12\x64\x65ployment_version\x18\x05 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersion\x12x\n\x0eupsert_entries\x18\x03 \x03(\x0b\x32`.temporal.api.workflowservice.v1.UpdateWorkerDeploymentVersionMetadataRequest.UpsertEntriesEntry\x12\x16\n\x0eremove_entries\x18\x04 \x03(\t\x12\x10\n\x08identity\x18\x06 \x01(\t\x1aU\n\x12UpsertEntriesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12.\n\x05value\x18\x02 \x01(\x0b\x32\x1f.temporal.api.common.v1.Payload:\x02\x38\x01"n\n-UpdateWorkerDeploymentVersionMetadataResponse\x12=\n\x08metadata\x18\x01 \x01(\x0b\x32+.temporal.api.deployment.v1.VersionMetadata"\xbd\x01\n!SetWorkerDeploymentManagerRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x17\n\x0f\x64\x65ployment_name\x18\x02 \x01(\t\x12\x1a\n\x10manager_identity\x18\x03 \x01(\tH\x00\x12\x0e\n\x04self\x18\x04 \x01(\x08H\x00\x12\x16\n\x0e\x63onflict_token\x18\x05 \x01(\x0c\x12\x10\n\x08identity\x18\x06 \x01(\tB\x16\n\x14new_manager_identity"c\n"SetWorkerDeploymentManagerResponse\x12\x16\n\x0e\x63onflict_token\x18\x01 \x01(\x0c\x12%\n\x19previous_manager_identity\x18\x02 \x01(\tB\x02\x18\x01"E\n\x1bGetCurrentDeploymentRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bseries_name\x18\x02 \x01(\t"k\n\x1cGetCurrentDeploymentResponse\x12K\n\x17\x63urrent_deployment_info\x18\x01 \x01(\x0b\x32*.temporal.api.deployment.v1.DeploymentInfo"q\n GetDeploymentReachabilityRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12:\n\ndeployment\x18\x02 \x01(\x0b\x32&.temporal.api.deployment.v1.Deployment"\xe3\x01\n!GetDeploymentReachabilityResponse\x12\x43\n\x0f\x64\x65ployment_info\x18\x01 \x01(\x0b\x32*.temporal.api.deployment.v1.DeploymentInfo\x12\x43\n\x0creachability\x18\x02 \x01(\x0e\x32-.temporal.api.enums.v1.DeploymentReachability\x12\x34\n\x10last_update_time\x18\x03 \x01(\x0b\x32\x1a.google.protobuf.Timestamp"\xb4\x01\n\x19\x43reateWorkflowRuleRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x35\n\x04spec\x18\x02 \x01(\x0b\x32\'.temporal.api.rules.v1.WorkflowRuleSpec\x12\x12\n\nforce_scan\x18\x03 \x01(\x08\x12\x12\n\nrequest_id\x18\x04 \x01(\t\x12\x10\n\x08identity\x18\x05 \x01(\t\x12\x13\n\x0b\x64\x65scription\x18\x06 \x01(\t"_\n\x1a\x43reateWorkflowRuleResponse\x12\x31\n\x04rule\x18\x01 \x01(\x0b\x32#.temporal.api.rules.v1.WorkflowRule\x12\x0e\n\x06job_id\x18\x02 \x01(\t"A\n\x1b\x44\x65scribeWorkflowRuleRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x0f\n\x07rule_id\x18\x02 \x01(\t"Q\n\x1c\x44\x65scribeWorkflowRuleResponse\x12\x31\n\x04rule\x18\x01 \x01(\x0b\x32#.temporal.api.rules.v1.WorkflowRule"?\n\x19\x44\x65leteWorkflowRuleRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x0f\n\x07rule_id\x18\x02 \x01(\t"\x1c\n\x1a\x44\x65leteWorkflowRuleResponse"F\n\x18ListWorkflowRulesRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c"h\n\x19ListWorkflowRulesResponse\x12\x32\n\x05rules\x18\x01 \x03(\x0b\x32#.temporal.api.rules.v1.WorkflowRule\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c"\xce\x01\n\x1aTriggerWorkflowRuleRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12<\n\texecution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x0c\n\x02id\x18\x04 \x01(\tH\x00\x12\x37\n\x04spec\x18\x05 \x01(\x0b\x32\'.temporal.api.rules.v1.WorkflowRuleSpecH\x00\x12\x10\n\x08identity\x18\x03 \x01(\tB\x06\n\x04rule".\n\x1bTriggerWorkflowRuleResponse\x12\x0f\n\x07\x61pplied\x18\x01 \x01(\x08"\x86\x01\n\x1cRecordWorkerHeartbeatRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x10\n\x08identity\x18\x02 \x01(\t\x12\x41\n\x10worker_heartbeat\x18\x03 \x03(\x0b\x32\'.temporal.api.worker.v1.WorkerHeartbeat"\x1f\n\x1dRecordWorkerHeartbeatResponse"b\n\x12ListWorkersRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x11\n\tpage_size\x18\x02 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c\x12\r\n\x05query\x18\x04 \x01(\t"\xa5\x01\n\x13ListWorkersResponse\x12<\n\x0cworkers_info\x18\x01 \x03(\x0b\x32".temporal.api.worker.v1.WorkerInfoB\x02\x18\x01\x12\x37\n\x07workers\x18\x03 \x03(\x0b\x32&.temporal.api.worker.v1.WorkerListInfo\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c"\xd5\x05\n\x1cUpdateTaskQueueConfigRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x10\n\x08identity\x18\x02 \x01(\t\x12\x12\n\ntask_queue\x18\x03 \x01(\t\x12=\n\x0ftask_queue_type\x18\x04 \x01(\x0e\x32$.temporal.api.enums.v1.TaskQueueType\x12n\n\x17update_queue_rate_limit\x18\x05 \x01(\x0b\x32M.temporal.api.workflowservice.v1.UpdateTaskQueueConfigRequest.RateLimitUpdate\x12}\n&update_fairness_key_rate_limit_default\x18\x06 \x01(\x0b\x32M.temporal.api.workflowservice.v1.UpdateTaskQueueConfigRequest.RateLimitUpdate\x12\x84\x01\n\x1dset_fairness_weight_overrides\x18\x07 \x03(\x0b\x32].temporal.api.workflowservice.v1.UpdateTaskQueueConfigRequest.SetFairnessWeightOverridesEntry\x12\'\n\x1funset_fairness_weight_overrides\x18\x08 \x03(\t\x1a[\n\x0fRateLimitUpdate\x12\x38\n\nrate_limit\x18\x01 \x01(\x0b\x32$.temporal.api.taskqueue.v1.RateLimit\x12\x0e\n\x06reason\x18\x02 \x01(\t\x1a\x41\n\x1fSetFairnessWeightOverridesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\x02:\x02\x38\x01"[\n\x1dUpdateTaskQueueConfigResponse\x12:\n\x06\x63onfig\x18\x01 \x01(\x0b\x32*.temporal.api.taskqueue.v1.TaskQueueConfig"\x89\x01\n\x18\x46\x65tchWorkerConfigRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x10\n\x08identity\x18\x02 \x01(\t\x12\x0e\n\x06reason\x18\x03 \x01(\t\x12\x38\n\x08selector\x18\x06 \x01(\x0b\x32&.temporal.api.common.v1.WorkerSelector"U\n\x19\x46\x65tchWorkerConfigResponse\x12\x38\n\rworker_config\x18\x01 \x01(\x0b\x32!.temporal.api.sdk.v1.WorkerConfig"\xf5\x01\n\x19UpdateWorkerConfigRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x10\n\x08identity\x18\x02 \x01(\t\x12\x0e\n\x06reason\x18\x03 \x01(\t\x12\x38\n\rworker_config\x18\x04 \x01(\x0b\x32!.temporal.api.sdk.v1.WorkerConfig\x12/\n\x0bupdate_mask\x18\x05 \x01(\x0b\x32\x1a.google.protobuf.FieldMask\x12\x38\n\x08selector\x18\x06 \x01(\x0b\x32&.temporal.api.common.v1.WorkerSelector"d\n\x1aUpdateWorkerConfigResponse\x12:\n\rworker_config\x18\x01 \x01(\x0b\x32!.temporal.api.sdk.v1.WorkerConfigH\x00\x42\n\n\x08response"G\n\x15\x44\x65scribeWorkerRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x1b\n\x13worker_instance_key\x18\x02 \x01(\t"Q\n\x16\x44\x65scribeWorkerResponse\x12\x37\n\x0bworker_info\x18\x01 \x01(\x0b\x32".temporal.api.worker.v1.WorkerInfo"\x8d\x01\n\x1dPauseWorkflowExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x12\x10\n\x08identity\x18\x04 \x01(\t\x12\x0e\n\x06reason\x18\x05 \x01(\t\x12\x12\n\nrequest_id\x18\x06 \x01(\t" \n\x1ePauseWorkflowExecutionResponse"\x8f\x01\n\x1fUnpauseWorkflowExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x12\x10\n\x08identity\x18\x04 \x01(\t\x12\x0e\n\x06reason\x18\x05 \x01(\t\x12\x12\n\nrequest_id\x18\x06 \x01(\t""\n UnpauseWorkflowExecutionResponse"\xb4\x07\n\x1dStartActivityExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x10\n\x08identity\x18\x02 \x01(\t\x12\x12\n\nrequest_id\x18\x03 \x01(\t\x12\x13\n\x0b\x61\x63tivity_id\x18\x04 \x01(\t\x12;\n\ractivity_type\x18\x05 \x01(\x0b\x32$.temporal.api.common.v1.ActivityType\x12\x38\n\ntask_queue\x18\x06 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12<\n\x19schedule_to_close_timeout\x18\x07 \x01(\x0b\x32\x19.google.protobuf.Duration\x12<\n\x19schedule_to_start_timeout\x18\x08 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x39\n\x16start_to_close_timeout\x18\t \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x34\n\x11heartbeat_timeout\x18\n \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x39\n\x0cretry_policy\x18\x0b \x01(\x0b\x32#.temporal.api.common.v1.RetryPolicy\x12/\n\x05input\x18\x0c \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x45\n\x0fid_reuse_policy\x18\r \x01(\x0e\x32,.temporal.api.enums.v1.ActivityIdReusePolicy\x12K\n\x12id_conflict_policy\x18\x0e \x01(\x0e\x32/.temporal.api.enums.v1.ActivityIdConflictPolicy\x12\x43\n\x11search_attributes\x18\x0f \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes\x12.\n\x06header\x18\x10 \x01(\x0b\x32\x1e.temporal.api.common.v1.Header\x12\x38\n\ruser_metadata\x18\x11 \x01(\x0b\x32!.temporal.api.sdk.v1.UserMetadata\x12\x32\n\x08priority\x18\x12 \x01(\x0b\x32 .temporal.api.common.v1.Priority"A\n\x1eStartActivityExecutionResponse\x12\x0e\n\x06run_id\x18\x01 \x01(\t\x12\x0f\n\x07started\x18\x02 \x01(\x08"\xa3\x01\n DescribeActivityExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0b\x61\x63tivity_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x12\x15\n\rinclude_input\x18\x04 \x01(\x08\x12\x17\n\x0finclude_outcome\x18\x05 \x01(\x08\x12\x17\n\x0flong_poll_token\x18\x06 \x01(\x0c"\x81\x02\n!DescribeActivityExecutionResponse\x12\x0e\n\x06run_id\x18\x01 \x01(\t\x12=\n\x04info\x18\x02 \x01(\x0b\x32/.temporal.api.activity.v1.ActivityExecutionInfo\x12/\n\x05input\x18\x03 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x43\n\x07outcome\x18\x04 \x01(\x0b\x32\x32.temporal.api.activity.v1.ActivityExecutionOutcome\x12\x17\n\x0flong_poll_token\x18\x05 \x01(\x0c"V\n\x1cPollActivityExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0b\x61\x63tivity_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t"t\n\x1dPollActivityExecutionResponse\x12\x0e\n\x06run_id\x18\x01 \x01(\t\x12\x43\n\x07outcome\x18\x02 \x01(\x0b\x32\x32.temporal.api.activity.v1.ActivityExecutionOutcome"m\n\x1dListActivityExecutionsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x11\n\tpage_size\x18\x02 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c\x12\r\n\x05query\x18\x04 \x01(\t"\x82\x01\n\x1eListActivityExecutionsResponse\x12G\n\nexecutions\x18\x01 \x03(\x0b\x32\x33.temporal.api.activity.v1.ActivityExecutionListInfo\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c"B\n\x1e\x43ountActivityExecutionsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\r\n\x05query\x18\x02 \x01(\t"\xed\x01\n\x1f\x43ountActivityExecutionsResponse\x12\r\n\x05\x63ount\x18\x01 \x01(\x03\x12\x61\n\x06groups\x18\x02 \x03(\x0b\x32Q.temporal.api.workflowservice.v1.CountActivityExecutionsResponse.AggregationGroup\x1aX\n\x10\x41ggregationGroup\x12\x35\n\x0cgroup_values\x18\x01 \x03(\x0b\x32\x1f.temporal.api.common.v1.Payload\x12\r\n\x05\x63ount\x18\x02 \x01(\x03"\x95\x01\n%RequestCancelActivityExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0b\x61\x63tivity_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x12\x10\n\x08identity\x18\x04 \x01(\t\x12\x12\n\nrequest_id\x18\x05 \x01(\t\x12\x0e\n\x06reason\x18\x06 \x01(\t"(\n&RequestCancelActivityExecutionResponse"\x91\x01\n!TerminateActivityExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0b\x61\x63tivity_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x12\x10\n\x08identity\x18\x04 \x01(\t\x12\x12\n\nrequest_id\x18\x05 \x01(\t\x12\x0e\n\x06reason\x18\x06 \x01(\t"$\n"TerminateActivityExecutionResponse"X\n\x1e\x44\x65leteActivityExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0b\x61\x63tivity_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t"!\n\x1f\x44\x65leteActivityExecutionResponseB\xbe\x01\n"io.temporal.api.workflowservice.v1B\x14RequestResponseProtoP\x01Z5go.temporal.io/api/workflowservice/v1;workflowservice\xaa\x02!Temporalio.Api.WorkflowService.V1\xea\x02$Temporalio::Api::WorkflowService::V1b\x06proto3' + b'\n6temporal/api/workflowservice/v1/request_response.proto\x12\x1ftemporal.api.workflowservice.v1\x1a+temporal/api/enums/v1/batch_operation.proto\x1a"temporal/api/enums/v1/common.proto\x1a$temporal/api/enums/v1/workflow.proto\x1a%temporal/api/enums/v1/namespace.proto\x1a(temporal/api/enums/v1/failed_cause.proto\x1a!temporal/api/enums/v1/query.proto\x1a!temporal/api/enums/v1/reset.proto\x1a&temporal/api/enums/v1/task_queue.proto\x1a&temporal/api/enums/v1/deployment.proto\x1a"temporal/api/enums/v1/update.proto\x1a$temporal/api/enums/v1/activity.proto\x1a&temporal/api/activity/v1/message.proto\x1a$temporal/api/common/v1/message.proto\x1a%temporal/api/history/v1/message.proto\x1a&temporal/api/workflow/v1/message.proto\x1a%temporal/api/command/v1/message.proto\x1a(temporal/api/deployment/v1/message.proto\x1a%temporal/api/failure/v1/message.proto\x1a$temporal/api/filter/v1/message.proto\x1a&temporal/api/protocol/v1/message.proto\x1a\'temporal/api/namespace/v1/message.proto\x1a#temporal/api/query/v1/message.proto\x1a)temporal/api/replication/v1/message.proto\x1a#temporal/api/rules/v1/message.proto\x1a\'temporal/api/sdk/v1/worker_config.proto\x1a&temporal/api/schedule/v1/message.proto\x1a\'temporal/api/taskqueue/v1/message.proto\x1a$temporal/api/update/v1/message.proto\x1a%temporal/api/version/v1/message.proto\x1a#temporal/api/batch/v1/message.proto\x1a\x30temporal/api/sdk/v1/task_complete_metadata.proto\x1a\'temporal/api/sdk/v1/user_metadata.proto\x1a#temporal/api/nexus/v1/message.proto\x1a$temporal/api/worker/v1/message.proto\x1a\x1egoogle/protobuf/duration.proto\x1a google/protobuf/field_mask.proto\x1a\x1fgoogle/protobuf/timestamp.proto"\x88\x05\n\x18RegisterNamespaceRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0b\x64\x65scription\x18\x02 \x01(\t\x12\x13\n\x0bowner_email\x18\x03 \x01(\t\x12\x46\n#workflow_execution_retention_period\x18\x04 \x01(\x0b\x32\x19.google.protobuf.Duration\x12G\n\x08\x63lusters\x18\x05 \x03(\x0b\x32\x35.temporal.api.replication.v1.ClusterReplicationConfig\x12\x1b\n\x13\x61\x63tive_cluster_name\x18\x06 \x01(\t\x12Q\n\x04\x64\x61ta\x18\x07 \x03(\x0b\x32\x43.temporal.api.workflowservice.v1.RegisterNamespaceRequest.DataEntry\x12\x16\n\x0esecurity_token\x18\x08 \x01(\t\x12\x1b\n\x13is_global_namespace\x18\t \x01(\x08\x12\x44\n\x16history_archival_state\x18\n \x01(\x0e\x32$.temporal.api.enums.v1.ArchivalState\x12\x1c\n\x14history_archival_uri\x18\x0b \x01(\t\x12G\n\x19visibility_archival_state\x18\x0c \x01(\x0e\x32$.temporal.api.enums.v1.ArchivalState\x12\x1f\n\x17visibility_archival_uri\x18\r \x01(\t\x1a+\n\tDataEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01"\x1b\n\x19RegisterNamespaceResponse"\x89\x01\n\x15ListNamespacesRequest\x12\x11\n\tpage_size\x18\x01 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c\x12\x44\n\x10namespace_filter\x18\x03 \x01(\x0b\x32*.temporal.api.namespace.v1.NamespaceFilter"\x81\x01\n\x16ListNamespacesResponse\x12N\n\nnamespaces\x18\x01 \x03(\x0b\x32:.temporal.api.workflowservice.v1.DescribeNamespaceResponse\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c"9\n\x18\x44\x65scribeNamespaceRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\n\n\x02id\x18\x02 \x01(\t"\xec\x02\n\x19\x44\x65scribeNamespaceResponse\x12@\n\x0enamespace_info\x18\x01 \x01(\x0b\x32(.temporal.api.namespace.v1.NamespaceInfo\x12:\n\x06\x63onfig\x18\x02 \x01(\x0b\x32*.temporal.api.namespace.v1.NamespaceConfig\x12S\n\x12replication_config\x18\x03 \x01(\x0b\x32\x37.temporal.api.replication.v1.NamespaceReplicationConfig\x12\x18\n\x10\x66\x61ilover_version\x18\x04 \x01(\x03\x12\x1b\n\x13is_global_namespace\x18\x05 \x01(\x08\x12\x45\n\x10\x66\x61ilover_history\x18\x06 \x03(\x0b\x32+.temporal.api.replication.v1.FailoverStatus"\xcf\x02\n\x16UpdateNamespaceRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x43\n\x0bupdate_info\x18\x02 \x01(\x0b\x32..temporal.api.namespace.v1.UpdateNamespaceInfo\x12:\n\x06\x63onfig\x18\x03 \x01(\x0b\x32*.temporal.api.namespace.v1.NamespaceConfig\x12S\n\x12replication_config\x18\x04 \x01(\x0b\x32\x37.temporal.api.replication.v1.NamespaceReplicationConfig\x12\x16\n\x0esecurity_token\x18\x05 \x01(\t\x12\x19\n\x11\x64\x65lete_bad_binary\x18\x06 \x01(\t\x12\x19\n\x11promote_namespace\x18\x07 \x01(\x08"\xa3\x02\n\x17UpdateNamespaceResponse\x12@\n\x0enamespace_info\x18\x01 \x01(\x0b\x32(.temporal.api.namespace.v1.NamespaceInfo\x12:\n\x06\x63onfig\x18\x02 \x01(\x0b\x32*.temporal.api.namespace.v1.NamespaceConfig\x12S\n\x12replication_config\x18\x03 \x01(\x0b\x32\x37.temporal.api.replication.v1.NamespaceReplicationConfig\x12\x18\n\x10\x66\x61ilover_version\x18\x04 \x01(\x03\x12\x1b\n\x13is_global_namespace\x18\x05 \x01(\x08"F\n\x19\x44\x65precateNamespaceRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x16\n\x0esecurity_token\x18\x02 \x01(\t"\x1c\n\x1a\x44\x65precateNamespaceResponse"\x87\x0c\n\x1dStartWorkflowExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12;\n\rworkflow_type\x18\x03 \x01(\x0b\x32$.temporal.api.common.v1.WorkflowType\x12\x38\n\ntask_queue\x18\x04 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12/\n\x05input\x18\x05 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12=\n\x1aworkflow_execution_timeout\x18\x06 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x37\n\x14workflow_run_timeout\x18\x07 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x38\n\x15workflow_task_timeout\x18\x08 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x10\n\x08identity\x18\t \x01(\t\x12\x12\n\nrequest_id\x18\n \x01(\t\x12N\n\x18workflow_id_reuse_policy\x18\x0b \x01(\x0e\x32,.temporal.api.enums.v1.WorkflowIdReusePolicy\x12T\n\x1bworkflow_id_conflict_policy\x18\x16 \x01(\x0e\x32/.temporal.api.enums.v1.WorkflowIdConflictPolicy\x12\x39\n\x0cretry_policy\x18\x0c \x01(\x0b\x32#.temporal.api.common.v1.RetryPolicy\x12\x15\n\rcron_schedule\x18\r \x01(\t\x12*\n\x04memo\x18\x0e \x01(\x0b\x32\x1c.temporal.api.common.v1.Memo\x12\x43\n\x11search_attributes\x18\x0f \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes\x12.\n\x06header\x18\x10 \x01(\x0b\x32\x1e.temporal.api.common.v1.Header\x12\x1f\n\x17request_eager_execution\x18\x11 \x01(\x08\x12;\n\x11\x63ontinued_failure\x18\x12 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12@\n\x16last_completion_result\x18\x13 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x37\n\x14workflow_start_delay\x18\x14 \x01(\x0b\x32\x19.google.protobuf.Duration\x12>\n\x14\x63ompletion_callbacks\x18\x15 \x03(\x0b\x32 .temporal.api.common.v1.Callback\x12\x38\n\ruser_metadata\x18\x17 \x01(\x0b\x32!.temporal.api.sdk.v1.UserMetadata\x12+\n\x05links\x18\x18 \x03(\x0b\x32\x1c.temporal.api.common.v1.Link\x12I\n\x13versioning_override\x18\x19 \x01(\x0b\x32,.temporal.api.workflow.v1.VersioningOverride\x12H\n\x13on_conflict_options\x18\x1a \x01(\x0b\x32+.temporal.api.workflow.v1.OnConflictOptions\x12\x32\n\x08priority\x18\x1b \x01(\x0b\x32 .temporal.api.common.v1.Priority\x12\\\n\x1f\x65\x61ger_worker_deployment_options\x18\x1c \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentOptions"\x8a\x02\n\x1eStartWorkflowExecutionResponse\x12\x0e\n\x06run_id\x18\x01 \x01(\t\x12\x0f\n\x07started\x18\x03 \x01(\x08\x12>\n\x06status\x18\x05 \x01(\x0e\x32..temporal.api.enums.v1.WorkflowExecutionStatus\x12[\n\x13\x65\x61ger_workflow_task\x18\x02 \x01(\x0b\x32>.temporal.api.workflowservice.v1.PollWorkflowTaskQueueResponse\x12*\n\x04link\x18\x04 \x01(\x0b\x32\x1c.temporal.api.common.v1.Link"\xaa\x02\n"GetWorkflowExecutionHistoryRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12<\n\texecution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x19\n\x11maximum_page_size\x18\x03 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x04 \x01(\x0c\x12\x16\n\x0ewait_new_event\x18\x05 \x01(\x08\x12P\n\x19history_event_filter_type\x18\x06 \x01(\x0e\x32-.temporal.api.enums.v1.HistoryEventFilterType\x12\x15\n\rskip_archival\x18\x07 \x01(\x08"\xba\x01\n#GetWorkflowExecutionHistoryResponse\x12\x31\n\x07history\x18\x01 \x01(\x0b\x32 .temporal.api.history.v1.History\x12\x35\n\x0braw_history\x18\x02 \x03(\x0b\x32 .temporal.api.common.v1.DataBlob\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c\x12\x10\n\x08\x61rchived\x18\x04 \x01(\x08"\xb0\x01\n)GetWorkflowExecutionHistoryReverseRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12<\n\texecution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x19\n\x11maximum_page_size\x18\x03 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x04 \x01(\x0c"x\n*GetWorkflowExecutionHistoryReverseResponse\x12\x31\n\x07history\x18\x01 \x01(\x0b\x32 .temporal.api.history.v1.History\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c"\xfc\x02\n\x1cPollWorkflowTaskQueueRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x38\n\ntask_queue\x18\x02 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x1b\n\x13worker_instance_key\x18\x08 \x01(\t\x12\x1b\n\x0f\x62inary_checksum\x18\x04 \x01(\tB\x02\x18\x01\x12Z\n\x1bworker_version_capabilities\x18\x05 \x01(\x0b\x32\x31.temporal.api.common.v1.WorkerVersionCapabilitiesB\x02\x18\x01\x12O\n\x12\x64\x65ployment_options\x18\x06 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentOptionsJ\x04\x08\x07\x10\x08R\x10worker_heartbeat"\x91\x07\n\x1dPollWorkflowTaskQueueResponse\x12\x12\n\ntask_token\x18\x01 \x01(\x0c\x12\x45\n\x12workflow_execution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12;\n\rworkflow_type\x18\x03 \x01(\x0b\x32$.temporal.api.common.v1.WorkflowType\x12!\n\x19previous_started_event_id\x18\x04 \x01(\x03\x12\x18\n\x10started_event_id\x18\x05 \x01(\x03\x12\x0f\n\x07\x61ttempt\x18\x06 \x01(\x05\x12\x1a\n\x12\x62\x61\x63klog_count_hint\x18\x07 \x01(\x03\x12\x31\n\x07history\x18\x08 \x01(\x0b\x32 .temporal.api.history.v1.History\x12\x17\n\x0fnext_page_token\x18\t \x01(\x0c\x12\x33\n\x05query\x18\n \x01(\x0b\x32$.temporal.api.query.v1.WorkflowQuery\x12K\n\x1dworkflow_execution_task_queue\x18\x0b \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12\x32\n\x0escheduled_time\x18\x0c \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x30\n\x0cstarted_time\x18\r \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\\\n\x07queries\x18\x0e \x03(\x0b\x32K.temporal.api.workflowservice.v1.PollWorkflowTaskQueueResponse.QueriesEntry\x12\x33\n\x08messages\x18\x0f \x03(\x0b\x32!.temporal.api.protocol.v1.Message\x12Q\n\x17poller_scaling_decision\x18\x10 \x01(\x0b\x32\x30.temporal.api.taskqueue.v1.PollerScalingDecision\x1aT\n\x0cQueriesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x33\n\x05value\x18\x02 \x01(\x0b\x32$.temporal.api.query.v1.WorkflowQuery:\x02\x38\x01"\xca\t\n#RespondWorkflowTaskCompletedRequest\x12\x12\n\ntask_token\x18\x01 \x01(\x0c\x12\x32\n\x08\x63ommands\x18\x02 \x03(\x0b\x32 .temporal.api.command.v1.Command\x12\x10\n\x08identity\x18\x03 \x01(\t\x12O\n\x11sticky_attributes\x18\x04 \x01(\x0b\x32\x34.temporal.api.taskqueue.v1.StickyExecutionAttributes\x12 \n\x18return_new_workflow_task\x18\x05 \x01(\x08\x12&\n\x1e\x66orce_create_new_workflow_task\x18\x06 \x01(\x08\x12\x1b\n\x0f\x62inary_checksum\x18\x07 \x01(\tB\x02\x18\x01\x12m\n\rquery_results\x18\x08 \x03(\x0b\x32V.temporal.api.workflowservice.v1.RespondWorkflowTaskCompletedRequest.QueryResultsEntry\x12\x11\n\tnamespace\x18\t \x01(\t\x12\x13\n\x0bresource_id\x18\x12 \x01(\t\x12L\n\x14worker_version_stamp\x18\n \x01(\x0b\x32*.temporal.api.common.v1.WorkerVersionStampB\x02\x18\x01\x12\x33\n\x08messages\x18\x0b \x03(\x0b\x32!.temporal.api.protocol.v1.Message\x12H\n\x0csdk_metadata\x18\x0c \x01(\x0b\x32\x32.temporal.api.sdk.v1.WorkflowTaskCompletedMetadata\x12\x43\n\x11metering_metadata\x18\r \x01(\x0b\x32(.temporal.api.common.v1.MeteringMetadata\x12g\n\x0c\x63\x61pabilities\x18\x0e \x01(\x0b\x32Q.temporal.api.workflowservice.v1.RespondWorkflowTaskCompletedRequest.Capabilities\x12>\n\ndeployment\x18\x0f \x01(\x0b\x32&.temporal.api.deployment.v1.DeploymentB\x02\x18\x01\x12\x46\n\x13versioning_behavior\x18\x10 \x01(\x0e\x32).temporal.api.enums.v1.VersioningBehavior\x12O\n\x12\x64\x65ployment_options\x18\x11 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentOptions\x1a_\n\x11QueryResultsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x39\n\x05value\x18\x02 \x01(\x0b\x32*.temporal.api.query.v1.WorkflowQueryResult:\x02\x38\x01\x1a\x45\n\x0c\x43\x61pabilities\x12\x35\n-discard_speculative_workflow_task_with_events\x18\x01 \x01(\x08"\xf5\x01\n$RespondWorkflowTaskCompletedResponse\x12U\n\rworkflow_task\x18\x01 \x01(\x0b\x32>.temporal.api.workflowservice.v1.PollWorkflowTaskQueueResponse\x12V\n\x0e\x61\x63tivity_tasks\x18\x02 \x03(\x0b\x32>.temporal.api.workflowservice.v1.PollActivityTaskQueueResponse\x12\x1e\n\x16reset_history_event_id\x18\x03 \x01(\x03"\x8d\x04\n RespondWorkflowTaskFailedRequest\x12\x12\n\ntask_token\x18\x01 \x01(\x0c\x12=\n\x05\x63\x61use\x18\x02 \x01(\x0e\x32..temporal.api.enums.v1.WorkflowTaskFailedCause\x12\x31\n\x07\x66\x61ilure\x18\x03 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12\x10\n\x08identity\x18\x04 \x01(\t\x12\x1b\n\x0f\x62inary_checksum\x18\x05 \x01(\tB\x02\x18\x01\x12\x11\n\tnamespace\x18\x06 \x01(\t\x12\x13\n\x0bresource_id\x18\x0b \x01(\t\x12\x33\n\x08messages\x18\x07 \x03(\x0b\x32!.temporal.api.protocol.v1.Message\x12\x46\n\x0eworker_version\x18\x08 \x01(\x0b\x32*.temporal.api.common.v1.WorkerVersionStampB\x02\x18\x01\x12>\n\ndeployment\x18\t \x01(\x0b\x32&.temporal.api.deployment.v1.DeploymentB\x02\x18\x01\x12O\n\x12\x64\x65ployment_options\x18\n \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentOptions"#\n!RespondWorkflowTaskFailedResponse"\xaa\x03\n\x1cPollActivityTaskQueueRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x38\n\ntask_queue\x18\x02 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x1b\n\x13worker_instance_key\x18\x08 \x01(\t\x12I\n\x13task_queue_metadata\x18\x04 \x01(\x0b\x32,.temporal.api.taskqueue.v1.TaskQueueMetadata\x12Z\n\x1bworker_version_capabilities\x18\x05 \x01(\x0b\x32\x31.temporal.api.common.v1.WorkerVersionCapabilitiesB\x02\x18\x01\x12O\n\x12\x64\x65ployment_options\x18\x06 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentOptionsJ\x04\x08\x07\x10\x08R\x10worker_heartbeat"\x88\x08\n\x1dPollActivityTaskQueueResponse\x12\x12\n\ntask_token\x18\x01 \x01(\x0c\x12\x1a\n\x12workflow_namespace\x18\x02 \x01(\t\x12;\n\rworkflow_type\x18\x03 \x01(\x0b\x32$.temporal.api.common.v1.WorkflowType\x12\x45\n\x12workflow_execution\x18\x04 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12;\n\ractivity_type\x18\x05 \x01(\x0b\x32$.temporal.api.common.v1.ActivityType\x12\x13\n\x0b\x61\x63tivity_id\x18\x06 \x01(\t\x12.\n\x06header\x18\x07 \x01(\x0b\x32\x1e.temporal.api.common.v1.Header\x12/\n\x05input\x18\x08 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12;\n\x11heartbeat_details\x18\t \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x32\n\x0escheduled_time\x18\n \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x42\n\x1e\x63urrent_attempt_scheduled_time\x18\x0b \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x30\n\x0cstarted_time\x18\x0c \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x0f\n\x07\x61ttempt\x18\r \x01(\x05\x12<\n\x19schedule_to_close_timeout\x18\x0e \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x39\n\x16start_to_close_timeout\x18\x0f \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x34\n\x11heartbeat_timeout\x18\x10 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x39\n\x0cretry_policy\x18\x11 \x01(\x0b\x32#.temporal.api.common.v1.RetryPolicy\x12Q\n\x17poller_scaling_decision\x18\x12 \x01(\x0b\x32\x30.temporal.api.taskqueue.v1.PollerScalingDecision\x12\x32\n\x08priority\x18\x13 \x01(\x0b\x32 .temporal.api.common.v1.Priority\x12\x17\n\x0f\x61\x63tivity_run_id\x18\x14 \x01(\t"\xa5\x01\n"RecordActivityTaskHeartbeatRequest\x12\x12\n\ntask_token\x18\x01 \x01(\x0c\x12\x31\n\x07\x64\x65tails\x18\x02 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x11\n\tnamespace\x18\x04 \x01(\t\x12\x13\n\x0bresource_id\x18\x05 \x01(\t"p\n#RecordActivityTaskHeartbeatResponse\x12\x18\n\x10\x63\x61ncel_requested\x18\x01 \x01(\x08\x12\x17\n\x0f\x61\x63tivity_paused\x18\x02 \x01(\x08\x12\x16\n\x0e\x61\x63tivity_reset\x18\x03 \x01(\x08"\xcf\x01\n&RecordActivityTaskHeartbeatByIdRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x12\x13\n\x0b\x61\x63tivity_id\x18\x04 \x01(\t\x12\x31\n\x07\x64\x65tails\x18\x05 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x10\n\x08identity\x18\x06 \x01(\t\x12\x13\n\x0bresource_id\x18\x07 \x01(\t"t\n\'RecordActivityTaskHeartbeatByIdResponse\x12\x18\n\x10\x63\x61ncel_requested\x18\x01 \x01(\x08\x12\x17\n\x0f\x61\x63tivity_paused\x18\x02 \x01(\x08\x12\x16\n\x0e\x61\x63tivity_reset\x18\x03 \x01(\x08"\xfe\x02\n#RespondActivityTaskCompletedRequest\x12\x12\n\ntask_token\x18\x01 \x01(\x0c\x12\x30\n\x06result\x18\x02 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x11\n\tnamespace\x18\x04 \x01(\t\x12\x13\n\x0bresource_id\x18\x08 \x01(\t\x12\x46\n\x0eworker_version\x18\x05 \x01(\x0b\x32*.temporal.api.common.v1.WorkerVersionStampB\x02\x18\x01\x12>\n\ndeployment\x18\x06 \x01(\x0b\x32&.temporal.api.deployment.v1.DeploymentB\x02\x18\x01\x12O\n\x12\x64\x65ployment_options\x18\x07 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentOptions"&\n$RespondActivityTaskCompletedResponse"\xcf\x01\n\'RespondActivityTaskCompletedByIdRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x12\x13\n\x0b\x61\x63tivity_id\x18\x04 \x01(\t\x12\x30\n\x06result\x18\x05 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x10\n\x08identity\x18\x06 \x01(\t\x12\x13\n\x0bresource_id\x18\x07 \x01(\t"*\n(RespondActivityTaskCompletedByIdResponse"\xbe\x03\n RespondActivityTaskFailedRequest\x12\x12\n\ntask_token\x18\x01 \x01(\x0c\x12\x31\n\x07\x66\x61ilure\x18\x02 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x11\n\tnamespace\x18\x04 \x01(\t\x12\x13\n\x0bresource_id\x18\t \x01(\t\x12@\n\x16last_heartbeat_details\x18\x05 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x46\n\x0eworker_version\x18\x06 \x01(\x0b\x32*.temporal.api.common.v1.WorkerVersionStampB\x02\x18\x01\x12>\n\ndeployment\x18\x07 \x01(\x0b\x32&.temporal.api.deployment.v1.DeploymentB\x02\x18\x01\x12O\n\x12\x64\x65ployment_options\x18\x08 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentOptions"W\n!RespondActivityTaskFailedResponse\x12\x32\n\x08\x66\x61ilures\x18\x01 \x03(\x0b\x32 .temporal.api.failure.v1.Failure"\x8f\x02\n$RespondActivityTaskFailedByIdRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x12\x13\n\x0b\x61\x63tivity_id\x18\x04 \x01(\t\x12\x31\n\x07\x66\x61ilure\x18\x05 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12\x10\n\x08identity\x18\x06 \x01(\t\x12@\n\x16last_heartbeat_details\x18\x07 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x13\n\x0bresource_id\x18\x08 \x01(\t"[\n%RespondActivityTaskFailedByIdResponse\x12\x32\n\x08\x66\x61ilures\x18\x01 \x03(\x0b\x32 .temporal.api.failure.v1.Failure"\xfe\x02\n"RespondActivityTaskCanceledRequest\x12\x12\n\ntask_token\x18\x01 \x01(\x0c\x12\x31\n\x07\x64\x65tails\x18\x02 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x11\n\tnamespace\x18\x04 \x01(\t\x12\x13\n\x0bresource_id\x18\x08 \x01(\t\x12\x46\n\x0eworker_version\x18\x05 \x01(\x0b\x32*.temporal.api.common.v1.WorkerVersionStampB\x02\x18\x01\x12>\n\ndeployment\x18\x06 \x01(\x0b\x32&.temporal.api.deployment.v1.DeploymentB\x02\x18\x01\x12O\n\x12\x64\x65ployment_options\x18\x07 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentOptions"%\n#RespondActivityTaskCanceledResponse"\xa0\x02\n&RespondActivityTaskCanceledByIdRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x12\x13\n\x0b\x61\x63tivity_id\x18\x04 \x01(\t\x12\x31\n\x07\x64\x65tails\x18\x05 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x10\n\x08identity\x18\x06 \x01(\t\x12O\n\x12\x64\x65ployment_options\x18\x07 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentOptions\x12\x13\n\x0bresource_id\x18\x08 \x01(\t")\n\'RespondActivityTaskCanceledByIdResponse"\x84\x02\n%RequestCancelWorkflowExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x45\n\x12workflow_execution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x12\n\nrequest_id\x18\x04 \x01(\t\x12\x1e\n\x16\x66irst_execution_run_id\x18\x05 \x01(\t\x12\x0e\n\x06reason\x18\x06 \x01(\t\x12+\n\x05links\x18\x07 \x03(\x0b\x32\x1c.temporal.api.common.v1.Link"(\n&RequestCancelWorkflowExecutionResponse"\xde\x02\n\x1eSignalWorkflowExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x45\n\x12workflow_execution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x13\n\x0bsignal_name\x18\x03 \x01(\t\x12/\n\x05input\x18\x04 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x10\n\x08identity\x18\x05 \x01(\t\x12\x12\n\nrequest_id\x18\x06 \x01(\t\x12\x13\n\x07\x63ontrol\x18\x07 \x01(\tB\x02\x18\x01\x12.\n\x06header\x18\x08 \x01(\x0b\x32\x1e.temporal.api.common.v1.Header\x12+\n\x05links\x18\n \x03(\x0b\x32\x1c.temporal.api.common.v1.LinkJ\x04\x08\t\x10\n"!\n\x1fSignalWorkflowExecutionResponse"\xf1\t\n\'SignalWithStartWorkflowExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12;\n\rworkflow_type\x18\x03 \x01(\x0b\x32$.temporal.api.common.v1.WorkflowType\x12\x38\n\ntask_queue\x18\x04 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12/\n\x05input\x18\x05 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12=\n\x1aworkflow_execution_timeout\x18\x06 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x37\n\x14workflow_run_timeout\x18\x07 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x38\n\x15workflow_task_timeout\x18\x08 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x10\n\x08identity\x18\t \x01(\t\x12\x12\n\nrequest_id\x18\n \x01(\t\x12N\n\x18workflow_id_reuse_policy\x18\x0b \x01(\x0e\x32,.temporal.api.enums.v1.WorkflowIdReusePolicy\x12T\n\x1bworkflow_id_conflict_policy\x18\x16 \x01(\x0e\x32/.temporal.api.enums.v1.WorkflowIdConflictPolicy\x12\x13\n\x0bsignal_name\x18\x0c \x01(\t\x12\x36\n\x0csignal_input\x18\r \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x13\n\x07\x63ontrol\x18\x0e \x01(\tB\x02\x18\x01\x12\x39\n\x0cretry_policy\x18\x0f \x01(\x0b\x32#.temporal.api.common.v1.RetryPolicy\x12\x15\n\rcron_schedule\x18\x10 \x01(\t\x12*\n\x04memo\x18\x11 \x01(\x0b\x32\x1c.temporal.api.common.v1.Memo\x12\x43\n\x11search_attributes\x18\x12 \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes\x12.\n\x06header\x18\x13 \x01(\x0b\x32\x1e.temporal.api.common.v1.Header\x12\x37\n\x14workflow_start_delay\x18\x14 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x38\n\ruser_metadata\x18\x17 \x01(\x0b\x32!.temporal.api.sdk.v1.UserMetadata\x12+\n\x05links\x18\x18 \x03(\x0b\x32\x1c.temporal.api.common.v1.Link\x12I\n\x13versioning_override\x18\x19 \x01(\x0b\x32,.temporal.api.workflow.v1.VersioningOverride\x12\x32\n\x08priority\x18\x1a \x01(\x0b\x32 .temporal.api.common.v1.PriorityJ\x04\x08\x15\x10\x16"K\n(SignalWithStartWorkflowExecutionResponse\x12\x0e\n\x06run_id\x18\x01 \x01(\t\x12\x0f\n\x07started\x18\x02 \x01(\x08"\xc1\x03\n\x1dResetWorkflowExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x45\n\x12workflow_execution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x0e\n\x06reason\x18\x03 \x01(\t\x12%\n\x1dworkflow_task_finish_event_id\x18\x04 \x01(\x03\x12\x12\n\nrequest_id\x18\x05 \x01(\t\x12G\n\x12reset_reapply_type\x18\x06 \x01(\x0e\x32\'.temporal.api.enums.v1.ResetReapplyTypeB\x02\x18\x01\x12S\n\x1breset_reapply_exclude_types\x18\x07 \x03(\x0e\x32..temporal.api.enums.v1.ResetReapplyExcludeType\x12K\n\x15post_reset_operations\x18\x08 \x03(\x0b\x32,.temporal.api.workflow.v1.PostResetOperation\x12\x10\n\x08identity\x18\t \x01(\t"0\n\x1eResetWorkflowExecutionResponse\x12\x0e\n\x06run_id\x18\x01 \x01(\t"\x9f\x02\n!TerminateWorkflowExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x45\n\x12workflow_execution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x0e\n\x06reason\x18\x03 \x01(\t\x12\x31\n\x07\x64\x65tails\x18\x04 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x10\n\x08identity\x18\x05 \x01(\t\x12\x1e\n\x16\x66irst_execution_run_id\x18\x06 \x01(\t\x12+\n\x05links\x18\x07 \x03(\x0b\x32\x1c.temporal.api.common.v1.Link"$\n"TerminateWorkflowExecutionResponse"z\n\x1e\x44\x65leteWorkflowExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x45\n\x12workflow_execution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution"!\n\x1f\x44\x65leteWorkflowExecutionResponse"\xc9\x02\n!ListOpenWorkflowExecutionsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x19\n\x11maximum_page_size\x18\x02 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c\x12\x42\n\x11start_time_filter\x18\x04 \x01(\x0b\x32\'.temporal.api.filter.v1.StartTimeFilter\x12K\n\x10\x65xecution_filter\x18\x05 \x01(\x0b\x32/.temporal.api.filter.v1.WorkflowExecutionFilterH\x00\x12\x41\n\x0btype_filter\x18\x06 \x01(\x0b\x32*.temporal.api.filter.v1.WorkflowTypeFilterH\x00\x42\t\n\x07\x66ilters"\x82\x01\n"ListOpenWorkflowExecutionsResponse\x12\x43\n\nexecutions\x18\x01 \x03(\x0b\x32/.temporal.api.workflow.v1.WorkflowExecutionInfo\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c"\x8a\x03\n#ListClosedWorkflowExecutionsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x19\n\x11maximum_page_size\x18\x02 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c\x12\x42\n\x11start_time_filter\x18\x04 \x01(\x0b\x32\'.temporal.api.filter.v1.StartTimeFilter\x12K\n\x10\x65xecution_filter\x18\x05 \x01(\x0b\x32/.temporal.api.filter.v1.WorkflowExecutionFilterH\x00\x12\x41\n\x0btype_filter\x18\x06 \x01(\x0b\x32*.temporal.api.filter.v1.WorkflowTypeFilterH\x00\x12=\n\rstatus_filter\x18\x07 \x01(\x0b\x32$.temporal.api.filter.v1.StatusFilterH\x00\x42\t\n\x07\x66ilters"\x84\x01\n$ListClosedWorkflowExecutionsResponse\x12\x43\n\nexecutions\x18\x01 \x03(\x0b\x32/.temporal.api.workflow.v1.WorkflowExecutionInfo\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c"m\n\x1dListWorkflowExecutionsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x11\n\tpage_size\x18\x02 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c\x12\r\n\x05query\x18\x04 \x01(\t"~\n\x1eListWorkflowExecutionsResponse\x12\x43\n\nexecutions\x18\x01 \x03(\x0b\x32/.temporal.api.workflow.v1.WorkflowExecutionInfo\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c"u\n%ListArchivedWorkflowExecutionsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x11\n\tpage_size\x18\x02 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c\x12\r\n\x05query\x18\x04 \x01(\t"\x86\x01\n&ListArchivedWorkflowExecutionsResponse\x12\x43\n\nexecutions\x18\x01 \x03(\x0b\x32/.temporal.api.workflow.v1.WorkflowExecutionInfo\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c"m\n\x1dScanWorkflowExecutionsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x11\n\tpage_size\x18\x02 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c\x12\r\n\x05query\x18\x04 \x01(\t"~\n\x1eScanWorkflowExecutionsResponse\x12\x43\n\nexecutions\x18\x01 \x03(\x0b\x32/.temporal.api.workflow.v1.WorkflowExecutionInfo\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c"B\n\x1e\x43ountWorkflowExecutionsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\r\n\x05query\x18\x02 \x01(\t"\xed\x01\n\x1f\x43ountWorkflowExecutionsResponse\x12\r\n\x05\x63ount\x18\x01 \x01(\x03\x12\x61\n\x06groups\x18\x02 \x03(\x0b\x32Q.temporal.api.workflowservice.v1.CountWorkflowExecutionsResponse.AggregationGroup\x1aX\n\x10\x41ggregationGroup\x12\x35\n\x0cgroup_values\x18\x01 \x03(\x0b\x32\x1f.temporal.api.common.v1.Payload\x12\r\n\x05\x63ount\x18\x02 \x01(\x03"\x1c\n\x1aGetSearchAttributesRequest"\xc9\x01\n\x1bGetSearchAttributesResponse\x12T\n\x04keys\x18\x01 \x03(\x0b\x32\x46.temporal.api.workflowservice.v1.GetSearchAttributesResponse.KeysEntry\x1aT\n\tKeysEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x36\n\x05value\x18\x02 \x01(\x0e\x32\'.temporal.api.enums.v1.IndexedValueType:\x02\x38\x01"\xd0\x02\n RespondQueryTaskCompletedRequest\x12\x12\n\ntask_token\x18\x01 \x01(\x0c\x12>\n\x0e\x63ompleted_type\x18\x02 \x01(\x0e\x32&.temporal.api.enums.v1.QueryResultType\x12\x36\n\x0cquery_result\x18\x03 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x15\n\rerror_message\x18\x04 \x01(\t\x12\x11\n\tnamespace\x18\x06 \x01(\t\x12\x31\n\x07\x66\x61ilure\x18\x07 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12=\n\x05\x63\x61use\x18\x08 \x01(\x0e\x32..temporal.api.enums.v1.WorkflowTaskFailedCauseJ\x04\x08\x05\x10\x06"#\n!RespondQueryTaskCompletedResponse"n\n\x1bResetStickyTaskQueueRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12<\n\texecution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution"\x1e\n\x1cResetStickyTaskQueueResponse"\x9b\x02\n\x15ShutdownWorkerRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x19\n\x11sticky_task_queue\x18\x02 \x01(\t\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x0e\n\x06reason\x18\x04 \x01(\t\x12\x41\n\x10worker_heartbeat\x18\x05 \x01(\x0b\x32\'.temporal.api.worker.v1.WorkerHeartbeat\x12\x1b\n\x13worker_instance_key\x18\x06 \x01(\t\x12\x12\n\ntask_queue\x18\x07 \x01(\t\x12>\n\x10task_queue_types\x18\x08 \x03(\x0e\x32$.temporal.api.enums.v1.TaskQueueType"\x18\n\x16ShutdownWorkerResponse"\xe9\x01\n\x14QueryWorkflowRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12<\n\texecution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x33\n\x05query\x18\x03 \x01(\x0b\x32$.temporal.api.query.v1.WorkflowQuery\x12K\n\x16query_reject_condition\x18\x04 \x01(\x0e\x32+.temporal.api.enums.v1.QueryRejectCondition"\x8d\x01\n\x15QueryWorkflowResponse\x12\x36\n\x0cquery_result\x18\x01 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12<\n\x0equery_rejected\x18\x02 \x01(\x0b\x32$.temporal.api.query.v1.QueryRejected"s\n DescribeWorkflowExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12<\n\texecution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution"\x99\x05\n!DescribeWorkflowExecutionResponse\x12K\n\x10\x65xecution_config\x18\x01 \x01(\x0b\x32\x31.temporal.api.workflow.v1.WorkflowExecutionConfig\x12P\n\x17workflow_execution_info\x18\x02 \x01(\x0b\x32/.temporal.api.workflow.v1.WorkflowExecutionInfo\x12I\n\x12pending_activities\x18\x03 \x03(\x0b\x32-.temporal.api.workflow.v1.PendingActivityInfo\x12M\n\x10pending_children\x18\x04 \x03(\x0b\x32\x33.temporal.api.workflow.v1.PendingChildExecutionInfo\x12P\n\x15pending_workflow_task\x18\x05 \x01(\x0b\x32\x31.temporal.api.workflow.v1.PendingWorkflowTaskInfo\x12\x39\n\tcallbacks\x18\x06 \x03(\x0b\x32&.temporal.api.workflow.v1.CallbackInfo\x12U\n\x18pending_nexus_operations\x18\x07 \x03(\x0b\x32\x33.temporal.api.workflow.v1.PendingNexusOperationInfo\x12W\n\x16workflow_extended_info\x18\x08 \x01(\x0b\x32\x37.temporal.api.workflow.v1.WorkflowExecutionExtendedInfo"\x90\x04\n\x18\x44\x65scribeTaskQueueRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x38\n\ntask_queue\x18\x02 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12=\n\x0ftask_queue_type\x18\x03 \x01(\x0e\x32$.temporal.api.enums.v1.TaskQueueType\x12\x14\n\x0creport_stats\x18\x08 \x01(\x08\x12\x15\n\rreport_config\x18\x0b \x01(\x08\x12%\n\x19include_task_queue_status\x18\x04 \x01(\x08\x42\x02\x18\x01\x12\x42\n\x08\x61pi_mode\x18\x05 \x01(\x0e\x32,.temporal.api.enums.v1.DescribeTaskQueueModeB\x02\x18\x01\x12J\n\x08versions\x18\x06 \x01(\x0b\x32\x34.temporal.api.taskqueue.v1.TaskQueueVersionSelectionB\x02\x18\x01\x12\x42\n\x10task_queue_types\x18\x07 \x03(\x0e\x32$.temporal.api.enums.v1.TaskQueueTypeB\x02\x18\x01\x12\x1a\n\x0ereport_pollers\x18\t \x01(\x08\x42\x02\x18\x01\x12$\n\x18report_task_reachability\x18\n \x01(\x08\x42\x02\x18\x01"\xec\x07\n\x19\x44\x65scribeTaskQueueResponse\x12\x36\n\x07pollers\x18\x01 \x03(\x0b\x32%.temporal.api.taskqueue.v1.PollerInfo\x12\x38\n\x05stats\x18\x05 \x01(\x0b\x32).temporal.api.taskqueue.v1.TaskQueueStats\x12q\n\x15stats_by_priority_key\x18\x08 \x03(\x0b\x32R.temporal.api.workflowservice.v1.DescribeTaskQueueResponse.StatsByPriorityKeyEntry\x12K\n\x0fversioning_info\x18\x04 \x01(\x0b\x32\x32.temporal.api.taskqueue.v1.TaskQueueVersioningInfo\x12:\n\x06\x63onfig\x18\x06 \x01(\x0b\x32*.temporal.api.taskqueue.v1.TaskQueueConfig\x12k\n\x14\x65\x66\x66\x65\x63tive_rate_limit\x18\x07 \x01(\x0b\x32M.temporal.api.workflowservice.v1.DescribeTaskQueueResponse.EffectiveRateLimit\x12I\n\x11task_queue_status\x18\x02 \x01(\x0b\x32*.temporal.api.taskqueue.v1.TaskQueueStatusB\x02\x18\x01\x12g\n\rversions_info\x18\x03 \x03(\x0b\x32L.temporal.api.workflowservice.v1.DescribeTaskQueueResponse.VersionsInfoEntryB\x02\x18\x01\x1a\x64\n\x17StatsByPriorityKeyEntry\x12\x0b\n\x03key\x18\x01 \x01(\x05\x12\x38\n\x05value\x18\x02 \x01(\x0b\x32).temporal.api.taskqueue.v1.TaskQueueStats:\x02\x38\x01\x1at\n\x12\x45\x66\x66\x65\x63tiveRateLimit\x12\x1b\n\x13requests_per_second\x18\x01 \x01(\x02\x12\x41\n\x11rate_limit_source\x18\x02 \x01(\x0e\x32&.temporal.api.enums.v1.RateLimitSource\x1a\x64\n\x11VersionsInfoEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12>\n\x05value\x18\x02 \x01(\x0b\x32/.temporal.api.taskqueue.v1.TaskQueueVersionInfo:\x02\x38\x01"\x17\n\x15GetClusterInfoRequest"\xd1\x03\n\x16GetClusterInfoResponse\x12h\n\x11supported_clients\x18\x01 \x03(\x0b\x32M.temporal.api.workflowservice.v1.GetClusterInfoResponse.SupportedClientsEntry\x12\x16\n\x0eserver_version\x18\x02 \x01(\t\x12\x12\n\ncluster_id\x18\x03 \x01(\t\x12:\n\x0cversion_info\x18\x04 \x01(\x0b\x32$.temporal.api.version.v1.VersionInfo\x12\x14\n\x0c\x63luster_name\x18\x05 \x01(\t\x12\x1b\n\x13history_shard_count\x18\x06 \x01(\x05\x12\x19\n\x11persistence_store\x18\x07 \x01(\t\x12\x18\n\x10visibility_store\x18\x08 \x01(\t\x12 \n\x18initial_failover_version\x18\t \x01(\x03\x12"\n\x1a\x66\x61ilover_version_increment\x18\n \x01(\x03\x1a\x37\n\x15SupportedClientsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01"\x16\n\x14GetSystemInfoRequest"\xf4\x03\n\x15GetSystemInfoResponse\x12\x16\n\x0eserver_version\x18\x01 \x01(\t\x12Y\n\x0c\x63\x61pabilities\x18\x02 \x01(\x0b\x32\x43.temporal.api.workflowservice.v1.GetSystemInfoResponse.Capabilities\x1a\xe7\x02\n\x0c\x43\x61pabilities\x12\x1f\n\x17signal_and_query_header\x18\x01 \x01(\x08\x12&\n\x1einternal_error_differentiation\x18\x02 \x01(\x08\x12*\n"activity_failure_include_heartbeat\x18\x03 \x01(\x08\x12\x1a\n\x12supports_schedules\x18\x04 \x01(\x08\x12"\n\x1a\x65ncoded_failure_attributes\x18\x05 \x01(\x08\x12!\n\x19\x62uild_id_based_versioning\x18\x06 \x01(\x08\x12\x13\n\x0bupsert_memo\x18\x07 \x01(\x08\x12\x1c\n\x14\x65\x61ger_workflow_start\x18\x08 \x01(\x08\x12\x14\n\x0csdk_metadata\x18\t \x01(\x08\x12\'\n\x1f\x63ount_group_by_execution_status\x18\n \x01(\x08\x12\r\n\x05nexus\x18\x0b \x01(\x08"m\n\x1eListTaskQueuePartitionsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x38\n\ntask_queue\x18\x02 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue"\xdf\x01\n\x1fListTaskQueuePartitionsResponse\x12]\n\x1e\x61\x63tivity_task_queue_partitions\x18\x01 \x03(\x0b\x32\x35.temporal.api.taskqueue.v1.TaskQueuePartitionMetadata\x12]\n\x1eworkflow_task_queue_partitions\x18\x02 \x03(\x0b\x32\x35.temporal.api.taskqueue.v1.TaskQueuePartitionMetadata"\xcc\x02\n\x15\x43reateScheduleRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bschedule_id\x18\x02 \x01(\t\x12\x34\n\x08schedule\x18\x03 \x01(\x0b\x32".temporal.api.schedule.v1.Schedule\x12>\n\rinitial_patch\x18\x04 \x01(\x0b\x32\'.temporal.api.schedule.v1.SchedulePatch\x12\x10\n\x08identity\x18\x05 \x01(\t\x12\x12\n\nrequest_id\x18\x06 \x01(\t\x12*\n\x04memo\x18\x07 \x01(\x0b\x32\x1c.temporal.api.common.v1.Memo\x12\x43\n\x11search_attributes\x18\x08 \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes"0\n\x16\x43reateScheduleResponse\x12\x16\n\x0e\x63onflict_token\x18\x01 \x01(\x0c"A\n\x17\x44\x65scribeScheduleRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bschedule_id\x18\x02 \x01(\t"\x8f\x02\n\x18\x44\x65scribeScheduleResponse\x12\x34\n\x08schedule\x18\x01 \x01(\x0b\x32".temporal.api.schedule.v1.Schedule\x12\x34\n\x04info\x18\x02 \x01(\x0b\x32&.temporal.api.schedule.v1.ScheduleInfo\x12*\n\x04memo\x18\x03 \x01(\x0b\x32\x1c.temporal.api.common.v1.Memo\x12\x43\n\x11search_attributes\x18\x04 \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes\x12\x16\n\x0e\x63onflict_token\x18\x05 \x01(\x0c"\xf8\x01\n\x15UpdateScheduleRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bschedule_id\x18\x02 \x01(\t\x12\x34\n\x08schedule\x18\x03 \x01(\x0b\x32".temporal.api.schedule.v1.Schedule\x12\x16\n\x0e\x63onflict_token\x18\x04 \x01(\x0c\x12\x10\n\x08identity\x18\x05 \x01(\t\x12\x12\n\nrequest_id\x18\x06 \x01(\t\x12\x43\n\x11search_attributes\x18\x07 \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes"\x18\n\x16UpdateScheduleResponse"\x9c\x01\n\x14PatchScheduleRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bschedule_id\x18\x02 \x01(\t\x12\x36\n\x05patch\x18\x03 \x01(\x0b\x32\'.temporal.api.schedule.v1.SchedulePatch\x12\x10\n\x08identity\x18\x04 \x01(\t\x12\x12\n\nrequest_id\x18\x05 \x01(\t"\x17\n\x15PatchScheduleResponse"\xa8\x01\n ListScheduleMatchingTimesRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bschedule_id\x18\x02 \x01(\t\x12.\n\nstart_time\x18\x03 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12,\n\x08\x65nd_time\x18\x04 \x01(\x0b\x32\x1a.google.protobuf.Timestamp"S\n!ListScheduleMatchingTimesResponse\x12.\n\nstart_time\x18\x01 \x03(\x0b\x32\x1a.google.protobuf.Timestamp"Q\n\x15\x44\x65leteScheduleRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bschedule_id\x18\x02 \x01(\t\x12\x10\n\x08identity\x18\x03 \x01(\t"\x18\n\x16\x44\x65leteScheduleResponse"l\n\x14ListSchedulesRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x19\n\x11maximum_page_size\x18\x02 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c\x12\r\n\x05query\x18\x04 \x01(\t"p\n\x15ListSchedulesResponse\x12>\n\tschedules\x18\x01 \x03(\x0b\x32+.temporal.api.schedule.v1.ScheduleListEntry\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c"9\n\x15\x43ountSchedulesRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\r\n\x05query\x18\x02 \x01(\t"\xdb\x01\n\x16\x43ountSchedulesResponse\x12\r\n\x05\x63ount\x18\x01 \x01(\x03\x12X\n\x06groups\x18\x02 \x03(\x0b\x32H.temporal.api.workflowservice.v1.CountSchedulesResponse.AggregationGroup\x1aX\n\x10\x41ggregationGroup\x12\x35\n\x0cgroup_values\x18\x01 \x03(\x0b\x32\x1f.temporal.api.common.v1.Payload\x12\r\n\x05\x63ount\x18\x02 \x01(\x03"\x86\x05\n\'UpdateWorkerBuildIdCompatibilityRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x12\n\ntask_queue\x18\x02 \x01(\t\x12-\n#add_new_build_id_in_new_default_set\x18\x03 \x01(\tH\x00\x12\x87\x01\n\x1b\x61\x64\x64_new_compatible_build_id\x18\x04 \x01(\x0b\x32`.temporal.api.workflowservice.v1.UpdateWorkerBuildIdCompatibilityRequest.AddNewCompatibleVersionH\x00\x12!\n\x17promote_set_by_build_id\x18\x05 \x01(\tH\x00\x12%\n\x1bpromote_build_id_within_set\x18\x06 \x01(\tH\x00\x12h\n\nmerge_sets\x18\x07 \x01(\x0b\x32R.temporal.api.workflowservice.v1.UpdateWorkerBuildIdCompatibilityRequest.MergeSetsH\x00\x1ao\n\x17\x41\x64\x64NewCompatibleVersion\x12\x14\n\x0cnew_build_id\x18\x01 \x01(\t\x12$\n\x1c\x65xisting_compatible_build_id\x18\x02 \x01(\t\x12\x18\n\x10make_set_default\x18\x03 \x01(\x08\x1aI\n\tMergeSets\x12\x1c\n\x14primary_set_build_id\x18\x01 \x01(\t\x12\x1e\n\x16secondary_set_build_id\x18\x02 \x01(\tB\x0b\n\toperation"@\n(UpdateWorkerBuildIdCompatibilityResponseJ\x04\x08\x01\x10\x02R\x0eversion_set_id"_\n$GetWorkerBuildIdCompatibilityRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x12\n\ntask_queue\x18\x02 \x01(\t\x12\x10\n\x08max_sets\x18\x03 \x01(\x05"t\n%GetWorkerBuildIdCompatibilityResponse\x12K\n\x12major_version_sets\x18\x01 \x03(\x0b\x32/.temporal.api.taskqueue.v1.CompatibleVersionSet"\xb5\r\n"UpdateWorkerVersioningRulesRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x12\n\ntask_queue\x18\x02 \x01(\t\x12\x16\n\x0e\x63onflict_token\x18\x03 \x01(\x0c\x12\x81\x01\n\x16insert_assignment_rule\x18\x04 \x01(\x0b\x32_.temporal.api.workflowservice.v1.UpdateWorkerVersioningRulesRequest.InsertBuildIdAssignmentRuleH\x00\x12\x83\x01\n\x17replace_assignment_rule\x18\x05 \x01(\x0b\x32`.temporal.api.workflowservice.v1.UpdateWorkerVersioningRulesRequest.ReplaceBuildIdAssignmentRuleH\x00\x12\x81\x01\n\x16\x64\x65lete_assignment_rule\x18\x06 \x01(\x0b\x32_.temporal.api.workflowservice.v1.UpdateWorkerVersioningRulesRequest.DeleteBuildIdAssignmentRuleH\x00\x12\x8c\x01\n\x1c\x61\x64\x64_compatible_redirect_rule\x18\x07 \x01(\x0b\x32\x64.temporal.api.workflowservice.v1.UpdateWorkerVersioningRulesRequest.AddCompatibleBuildIdRedirectRuleH\x00\x12\x94\x01\n replace_compatible_redirect_rule\x18\x08 \x01(\x0b\x32h.temporal.api.workflowservice.v1.UpdateWorkerVersioningRulesRequest.ReplaceCompatibleBuildIdRedirectRuleH\x00\x12\x92\x01\n\x1f\x64\x65lete_compatible_redirect_rule\x18\t \x01(\x0b\x32g.temporal.api.workflowservice.v1.UpdateWorkerVersioningRulesRequest.DeleteCompatibleBuildIdRedirectRuleH\x00\x12l\n\x0f\x63ommit_build_id\x18\n \x01(\x0b\x32Q.temporal.api.workflowservice.v1.UpdateWorkerVersioningRulesRequest.CommitBuildIdH\x00\x1aq\n\x1bInsertBuildIdAssignmentRule\x12\x12\n\nrule_index\x18\x01 \x01(\x05\x12>\n\x04rule\x18\x02 \x01(\x0b\x32\x30.temporal.api.taskqueue.v1.BuildIdAssignmentRule\x1a\x81\x01\n\x1cReplaceBuildIdAssignmentRule\x12\x12\n\nrule_index\x18\x01 \x01(\x05\x12>\n\x04rule\x18\x02 \x01(\x0b\x32\x30.temporal.api.taskqueue.v1.BuildIdAssignmentRule\x12\r\n\x05\x66orce\x18\x03 \x01(\x08\x1a@\n\x1b\x44\x65leteBuildIdAssignmentRule\x12\x12\n\nrule_index\x18\x01 \x01(\x05\x12\r\n\x05\x66orce\x18\x02 \x01(\x08\x1aj\n AddCompatibleBuildIdRedirectRule\x12\x46\n\x04rule\x18\x01 \x01(\x0b\x32\x38.temporal.api.taskqueue.v1.CompatibleBuildIdRedirectRule\x1an\n$ReplaceCompatibleBuildIdRedirectRule\x12\x46\n\x04rule\x18\x01 \x01(\x0b\x32\x38.temporal.api.taskqueue.v1.CompatibleBuildIdRedirectRule\x1a>\n#DeleteCompatibleBuildIdRedirectRule\x12\x17\n\x0fsource_build_id\x18\x01 \x01(\t\x1a\x37\n\rCommitBuildId\x12\x17\n\x0ftarget_build_id\x18\x01 \x01(\t\x12\r\n\x05\x66orce\x18\x02 \x01(\x08\x42\x0b\n\toperation"\xfc\x01\n#UpdateWorkerVersioningRulesResponse\x12U\n\x10\x61ssignment_rules\x18\x01 \x03(\x0b\x32;.temporal.api.taskqueue.v1.TimestampedBuildIdAssignmentRule\x12\x66\n\x19\x63ompatible_redirect_rules\x18\x02 \x03(\x0b\x32\x43.temporal.api.taskqueue.v1.TimestampedCompatibleBuildIdRedirectRule\x12\x16\n\x0e\x63onflict_token\x18\x03 \x01(\x0c"H\n\x1fGetWorkerVersioningRulesRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x12\n\ntask_queue\x18\x02 \x01(\t"\xf9\x01\n GetWorkerVersioningRulesResponse\x12U\n\x10\x61ssignment_rules\x18\x01 \x03(\x0b\x32;.temporal.api.taskqueue.v1.TimestampedBuildIdAssignmentRule\x12\x66\n\x19\x63ompatible_redirect_rules\x18\x02 \x03(\x0b\x32\x43.temporal.api.taskqueue.v1.TimestampedCompatibleBuildIdRedirectRule\x12\x16\n\x0e\x63onflict_token\x18\x03 \x01(\x0c"\x9c\x01\n GetWorkerTaskReachabilityRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x11\n\tbuild_ids\x18\x02 \x03(\t\x12\x13\n\x0btask_queues\x18\x03 \x03(\t\x12=\n\x0creachability\x18\x04 \x01(\x0e\x32\'.temporal.api.enums.v1.TaskReachability"r\n!GetWorkerTaskReachabilityResponse\x12M\n\x15\x62uild_id_reachability\x18\x01 \x03(\x0b\x32..temporal.api.taskqueue.v1.BuildIdReachability"\x85\x02\n\x1eUpdateWorkflowExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x45\n\x12workflow_execution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x1e\n\x16\x66irst_execution_run_id\x18\x03 \x01(\t\x12\x37\n\x0bwait_policy\x18\x04 \x01(\x0b\x32".temporal.api.update.v1.WaitPolicy\x12\x30\n\x07request\x18\x05 \x01(\x0b\x32\x1f.temporal.api.update.v1.Request"\xd7\x01\n\x1fUpdateWorkflowExecutionResponse\x12\x35\n\nupdate_ref\x18\x01 \x01(\x0b\x32!.temporal.api.update.v1.UpdateRef\x12\x30\n\x07outcome\x18\x02 \x01(\x0b\x32\x1f.temporal.api.update.v1.Outcome\x12K\n\x05stage\x18\x03 \x01(\x0e\x32<.temporal.api.enums.v1.UpdateWorkflowExecutionLifecycleStage"\xf4\x07\n\x1aStartBatchOperationRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x18\n\x10visibility_query\x18\x02 \x01(\t\x12\x0e\n\x06job_id\x18\x03 \x01(\t\x12\x0e\n\x06reason\x18\x04 \x01(\t\x12=\n\nexecutions\x18\x05 \x03(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12!\n\x19max_operations_per_second\x18\x06 \x01(\x02\x12Q\n\x15termination_operation\x18\n \x01(\x0b\x32\x30.temporal.api.batch.v1.BatchOperationTerminationH\x00\x12G\n\x10signal_operation\x18\x0b \x01(\x0b\x32+.temporal.api.batch.v1.BatchOperationSignalH\x00\x12S\n\x16\x63\x61ncellation_operation\x18\x0c \x01(\x0b\x32\x31.temporal.api.batch.v1.BatchOperationCancellationH\x00\x12K\n\x12\x64\x65letion_operation\x18\r \x01(\x0b\x32-.temporal.api.batch.v1.BatchOperationDeletionH\x00\x12\x45\n\x0freset_operation\x18\x0e \x01(\x0b\x32*.temporal.api.batch.v1.BatchOperationResetH\x00\x12p\n!update_workflow_options_operation\x18\x0f \x01(\x0b\x32\x43.temporal.api.batch.v1.BatchOperationUpdateWorkflowExecutionOptionsH\x00\x12^\n\x1cunpause_activities_operation\x18\x10 \x01(\x0b\x32\x36.temporal.api.batch.v1.BatchOperationUnpauseActivitiesH\x00\x12Z\n\x1areset_activities_operation\x18\x11 \x01(\x0b\x32\x34.temporal.api.batch.v1.BatchOperationResetActivitiesH\x00\x12g\n!update_activity_options_operation\x18\x12 \x01(\x0b\x32:.temporal.api.batch.v1.BatchOperationUpdateActivityOptionsH\x00\x42\x0b\n\toperation"\x1d\n\x1bStartBatchOperationResponse"`\n\x19StopBatchOperationRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x0e\n\x06job_id\x18\x02 \x01(\t\x12\x0e\n\x06reason\x18\x03 \x01(\t\x12\x10\n\x08identity\x18\x04 \x01(\t"\x1c\n\x1aStopBatchOperationResponse"B\n\x1d\x44\x65scribeBatchOperationRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x0e\n\x06job_id\x18\x02 \x01(\t"\x92\x03\n\x1e\x44\x65scribeBatchOperationResponse\x12\x41\n\x0eoperation_type\x18\x01 \x01(\x0e\x32).temporal.api.enums.v1.BatchOperationType\x12\x0e\n\x06job_id\x18\x02 \x01(\t\x12\x39\n\x05state\x18\x03 \x01(\x0e\x32*.temporal.api.enums.v1.BatchOperationState\x12.\n\nstart_time\x18\x04 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12.\n\nclose_time\x18\x05 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x1d\n\x15total_operation_count\x18\x06 \x01(\x03\x12 \n\x18\x63omplete_operation_count\x18\x07 \x01(\x03\x12\x1f\n\x17\x66\x61ilure_operation_count\x18\x08 \x01(\x03\x12\x10\n\x08identity\x18\t \x01(\t\x12\x0e\n\x06reason\x18\n \x01(\t"[\n\x1aListBatchOperationsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x11\n\tpage_size\x18\x02 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c"y\n\x1bListBatchOperationsResponse\x12\x41\n\x0eoperation_info\x18\x01 \x03(\x0b\x32).temporal.api.batch.v1.BatchOperationInfo\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c"\xb9\x01\n"PollWorkflowExecutionUpdateRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x35\n\nupdate_ref\x18\x02 \x01(\x0b\x32!.temporal.api.update.v1.UpdateRef\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x37\n\x0bwait_policy\x18\x04 \x01(\x0b\x32".temporal.api.update.v1.WaitPolicy"\xdb\x01\n#PollWorkflowExecutionUpdateResponse\x12\x30\n\x07outcome\x18\x01 \x01(\x0b\x32\x1f.temporal.api.update.v1.Outcome\x12K\n\x05stage\x18\x02 \x01(\x0e\x32<.temporal.api.enums.v1.UpdateWorkflowExecutionLifecycleStage\x12\x35\n\nupdate_ref\x18\x03 \x01(\x0b\x32!.temporal.api.update.v1.UpdateRef"\x87\x03\n\x19PollNexusTaskQueueRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x10\n\x08identity\x18\x02 \x01(\t\x12\x1b\n\x13worker_instance_key\x18\x08 \x01(\t\x12\x38\n\ntask_queue\x18\x03 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12Z\n\x1bworker_version_capabilities\x18\x04 \x01(\x0b\x32\x31.temporal.api.common.v1.WorkerVersionCapabilitiesB\x02\x18\x01\x12O\n\x12\x64\x65ployment_options\x18\x06 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentOptions\x12\x41\n\x10worker_heartbeat\x18\x07 \x03(\x0b\x32\'.temporal.api.worker.v1.WorkerHeartbeat"\xb4\x01\n\x1aPollNexusTaskQueueResponse\x12\x12\n\ntask_token\x18\x01 \x01(\x0c\x12/\n\x07request\x18\x02 \x01(\x0b\x32\x1e.temporal.api.nexus.v1.Request\x12Q\n\x17poller_scaling_decision\x18\x03 \x01(\x0b\x32\x30.temporal.api.taskqueue.v1.PollerScalingDecision"\x8e\x01\n RespondNexusTaskCompletedRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x10\n\x08identity\x18\x02 \x01(\t\x12\x12\n\ntask_token\x18\x03 \x01(\x0c\x12\x31\n\x08response\x18\x04 \x01(\x0b\x32\x1f.temporal.api.nexus.v1.Response"#\n!RespondNexusTaskCompletedResponse"\xc3\x01\n\x1dRespondNexusTaskFailedRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x10\n\x08identity\x18\x02 \x01(\t\x12\x12\n\ntask_token\x18\x03 \x01(\x0c\x12\x36\n\x05\x65rror\x18\x04 \x01(\x0b\x32#.temporal.api.nexus.v1.HandlerErrorB\x02\x18\x01\x12\x31\n\x07\x66\x61ilure\x18\x05 \x01(\x0b\x32 .temporal.api.failure.v1.Failure" \n\x1eRespondNexusTaskFailedResponse"\xf4\x02\n\x1c\x45xecuteMultiOperationRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12[\n\noperations\x18\x02 \x03(\x0b\x32G.temporal.api.workflowservice.v1.ExecuteMultiOperationRequest.Operation\x12\x13\n\x0bresource_id\x18\x03 \x01(\t\x1a\xce\x01\n\tOperation\x12X\n\x0estart_workflow\x18\x01 \x01(\x0b\x32>.temporal.api.workflowservice.v1.StartWorkflowExecutionRequestH\x00\x12Z\n\x0fupdate_workflow\x18\x02 \x01(\x0b\x32?.temporal.api.workflowservice.v1.UpdateWorkflowExecutionRequestH\x00\x42\x0b\n\toperation"\xcc\x02\n\x1d\x45xecuteMultiOperationResponse\x12Z\n\tresponses\x18\x01 \x03(\x0b\x32G.temporal.api.workflowservice.v1.ExecuteMultiOperationResponse.Response\x1a\xce\x01\n\x08Response\x12Y\n\x0estart_workflow\x18\x01 \x01(\x0b\x32?.temporal.api.workflowservice.v1.StartWorkflowExecutionResponseH\x00\x12[\n\x0fupdate_workflow\x18\x02 \x01(\x0b\x32@.temporal.api.workflowservice.v1.UpdateWorkflowExecutionResponseH\x00\x42\n\n\x08response"\xd0\x02\n\x1cUpdateActivityOptionsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12<\n\texecution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x43\n\x10\x61\x63tivity_options\x18\x04 \x01(\x0b\x32).temporal.api.activity.v1.ActivityOptions\x12/\n\x0bupdate_mask\x18\x05 \x01(\x0b\x32\x1a.google.protobuf.FieldMask\x12\x0c\n\x02id\x18\x06 \x01(\tH\x00\x12\x0e\n\x04type\x18\x07 \x01(\tH\x00\x12\x13\n\tmatch_all\x18\t \x01(\x08H\x00\x12\x18\n\x10restore_original\x18\x08 \x01(\x08\x42\n\n\x08\x61\x63tivity"d\n\x1dUpdateActivityOptionsResponse\x12\x43\n\x10\x61\x63tivity_options\x18\x01 \x01(\x0b\x32).temporal.api.activity.v1.ActivityOptions"\xb3\x01\n\x14PauseActivityRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12<\n\texecution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x0c\n\x02id\x18\x04 \x01(\tH\x00\x12\x0e\n\x04type\x18\x05 \x01(\tH\x00\x12\x0e\n\x06reason\x18\x06 \x01(\tB\n\n\x08\x61\x63tivity"\x17\n\x15PauseActivityResponse"\x98\x02\n\x16UnpauseActivityRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12<\n\texecution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x0c\n\x02id\x18\x04 \x01(\tH\x00\x12\x0e\n\x04type\x18\x05 \x01(\tH\x00\x12\x15\n\x0bunpause_all\x18\x06 \x01(\x08H\x00\x12\x16\n\x0ereset_attempts\x18\x07 \x01(\x08\x12\x17\n\x0freset_heartbeat\x18\x08 \x01(\x08\x12)\n\x06jitter\x18\t \x01(\x0b\x32\x19.google.protobuf.DurationB\n\n\x08\x61\x63tivity"\x19\n\x17UnpauseActivityResponse"\xb3\x02\n\x14ResetActivityRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12<\n\texecution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x0c\n\x02id\x18\x04 \x01(\tH\x00\x12\x0e\n\x04type\x18\x05 \x01(\tH\x00\x12\x13\n\tmatch_all\x18\n \x01(\x08H\x00\x12\x17\n\x0freset_heartbeat\x18\x06 \x01(\x08\x12\x13\n\x0bkeep_paused\x18\x07 \x01(\x08\x12)\n\x06jitter\x18\x08 \x01(\x0b\x32\x19.google.protobuf.Duration\x12 \n\x18restore_original_options\x18\t \x01(\x08\x42\n\n\x08\x61\x63tivity"\x17\n\x15ResetActivityResponse"\x9c\x02\n%UpdateWorkflowExecutionOptionsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x45\n\x12workflow_execution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12V\n\x1aworkflow_execution_options\x18\x03 \x01(\x0b\x32\x32.temporal.api.workflow.v1.WorkflowExecutionOptions\x12/\n\x0bupdate_mask\x18\x04 \x01(\x0b\x32\x1a.google.protobuf.FieldMask\x12\x10\n\x08identity\x18\x05 \x01(\t"\x80\x01\n&UpdateWorkflowExecutionOptionsResponse\x12V\n\x1aworkflow_execution_options\x18\x01 \x01(\x0b\x32\x32.temporal.api.workflow.v1.WorkflowExecutionOptions"j\n\x19\x44\x65scribeDeploymentRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12:\n\ndeployment\x18\x02 \x01(\x0b\x32&.temporal.api.deployment.v1.Deployment"a\n\x1a\x44\x65scribeDeploymentResponse\x12\x43\n\x0f\x64\x65ployment_info\x18\x01 \x01(\x0b\x32*.temporal.api.deployment.v1.DeploymentInfo"\xc2\x01\n&DescribeWorkerDeploymentVersionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x07version\x18\x02 \x01(\tB\x02\x18\x01\x12O\n\x12\x64\x65ployment_version\x18\x03 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersion\x12\x1f\n\x17report_task_queue_stats\x18\x04 \x01(\x08"\x8c\x05\n\'DescribeWorkerDeploymentVersionResponse\x12_\n\x1eworker_deployment_version_info\x18\x01 \x01(\x0b\x32\x37.temporal.api.deployment.v1.WorkerDeploymentVersionInfo\x12v\n\x13version_task_queues\x18\x02 \x03(\x0b\x32Y.temporal.api.workflowservice.v1.DescribeWorkerDeploymentVersionResponse.VersionTaskQueue\x1a\x87\x03\n\x10VersionTaskQueue\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x32\n\x04type\x18\x02 \x01(\x0e\x32$.temporal.api.enums.v1.TaskQueueType\x12\x38\n\x05stats\x18\x03 \x01(\x0b\x32).temporal.api.taskqueue.v1.TaskQueueStats\x12\x90\x01\n\x15stats_by_priority_key\x18\x04 \x03(\x0b\x32q.temporal.api.workflowservice.v1.DescribeWorkerDeploymentVersionResponse.VersionTaskQueue.StatsByPriorityKeyEntry\x1a\x64\n\x17StatsByPriorityKeyEntry\x12\x0b\n\x03key\x18\x01 \x01(\x05\x12\x38\n\x05value\x18\x02 \x01(\x0b\x32).temporal.api.taskqueue.v1.TaskQueueStats:\x02\x38\x01"M\n\x1f\x44\x65scribeWorkerDeploymentRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x17\n\x0f\x64\x65ployment_name\x18\x02 \x01(\t"\x8c\x01\n DescribeWorkerDeploymentResponse\x12\x16\n\x0e\x63onflict_token\x18\x01 \x01(\x0c\x12P\n\x16worker_deployment_info\x18\x02 \x01(\x0b\x32\x30.temporal.api.deployment.v1.WorkerDeploymentInfo"l\n\x16ListDeploymentsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x11\n\tpage_size\x18\x02 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c\x12\x13\n\x0bseries_name\x18\x04 \x01(\t"w\n\x17ListDeploymentsResponse\x12\x17\n\x0fnext_page_token\x18\x01 \x01(\x0c\x12\x43\n\x0b\x64\x65ployments\x18\x02 \x03(\x0b\x32..temporal.api.deployment.v1.DeploymentListInfo"\xcd\x01\n\x1bSetCurrentDeploymentRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12:\n\ndeployment\x18\x02 \x01(\x0b\x32&.temporal.api.deployment.v1.Deployment\x12\x10\n\x08identity\x18\x03 \x01(\t\x12M\n\x0fupdate_metadata\x18\x04 \x01(\x0b\x32\x34.temporal.api.deployment.v1.UpdateDeploymentMetadata"\xb9\x01\n\x1cSetCurrentDeploymentResponse\x12K\n\x17\x63urrent_deployment_info\x18\x01 \x01(\x0b\x32*.temporal.api.deployment.v1.DeploymentInfo\x12L\n\x18previous_deployment_info\x18\x02 \x01(\x0b\x32*.temporal.api.deployment.v1.DeploymentInfo"\xe5\x01\n(SetWorkerDeploymentCurrentVersionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x17\n\x0f\x64\x65ployment_name\x18\x02 \x01(\t\x12\x13\n\x07version\x18\x03 \x01(\tB\x02\x18\x01\x12\x10\n\x08\x62uild_id\x18\x07 \x01(\t\x12\x16\n\x0e\x63onflict_token\x18\x04 \x01(\x0c\x12\x10\n\x08identity\x18\x05 \x01(\t\x12"\n\x1aignore_missing_task_queues\x18\x06 \x01(\x08\x12\x18\n\x10\x61llow_no_pollers\x18\t \x01(\x08"\xbf\x01\n)SetWorkerDeploymentCurrentVersionResponse\x12\x16\n\x0e\x63onflict_token\x18\x01 \x01(\x0c\x12\x1c\n\x10previous_version\x18\x02 \x01(\tB\x02\x18\x01\x12\\\n\x1bprevious_deployment_version\x18\x03 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersionB\x02\x18\x01"\xf9\x01\n(SetWorkerDeploymentRampingVersionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x17\n\x0f\x64\x65ployment_name\x18\x02 \x01(\t\x12\x13\n\x07version\x18\x03 \x01(\tB\x02\x18\x01\x12\x10\n\x08\x62uild_id\x18\x08 \x01(\t\x12\x12\n\npercentage\x18\x04 \x01(\x02\x12\x16\n\x0e\x63onflict_token\x18\x05 \x01(\x0c\x12\x10\n\x08identity\x18\x06 \x01(\t\x12"\n\x1aignore_missing_task_queues\x18\x07 \x01(\x08\x12\x18\n\x10\x61llow_no_pollers\x18\n \x01(\x08"\xe0\x01\n)SetWorkerDeploymentRampingVersionResponse\x12\x16\n\x0e\x63onflict_token\x18\x01 \x01(\x0c\x12\x1c\n\x10previous_version\x18\x02 \x01(\tB\x02\x18\x01\x12\\\n\x1bprevious_deployment_version\x18\x04 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersionB\x02\x18\x01\x12\x1f\n\x13previous_percentage\x18\x03 \x01(\x02\x42\x02\x18\x01"]\n\x1cListWorkerDeploymentsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x11\n\tpage_size\x18\x02 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c"\x9f\x05\n\x1dListWorkerDeploymentsResponse\x12\x17\n\x0fnext_page_token\x18\x01 \x01(\x0c\x12r\n\x12worker_deployments\x18\x02 \x03(\x0b\x32V.temporal.api.workflowservice.v1.ListWorkerDeploymentsResponse.WorkerDeploymentSummary\x1a\xf0\x03\n\x17WorkerDeploymentSummary\x12\x0c\n\x04name\x18\x01 \x01(\t\x12/\n\x0b\x63reate_time\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x41\n\x0erouting_config\x18\x03 \x01(\x0b\x32).temporal.api.deployment.v1.RoutingConfig\x12o\n\x16latest_version_summary\x18\x04 \x01(\x0b\x32O.temporal.api.deployment.v1.WorkerDeploymentInfo.WorkerDeploymentVersionSummary\x12p\n\x17\x63urrent_version_summary\x18\x05 \x01(\x0b\x32O.temporal.api.deployment.v1.WorkerDeploymentInfo.WorkerDeploymentVersionSummary\x12p\n\x17ramping_version_summary\x18\x06 \x01(\x0b\x32O.temporal.api.deployment.v1.WorkerDeploymentInfo.WorkerDeploymentVersionSummary"\xc8\x01\n$DeleteWorkerDeploymentVersionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x07version\x18\x02 \x01(\tB\x02\x18\x01\x12O\n\x12\x64\x65ployment_version\x18\x05 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersion\x12\x15\n\rskip_drainage\x18\x03 \x01(\x08\x12\x10\n\x08identity\x18\x04 \x01(\t"\'\n%DeleteWorkerDeploymentVersionResponse"]\n\x1d\x44\x65leteWorkerDeploymentRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x17\n\x0f\x64\x65ployment_name\x18\x02 \x01(\t\x12\x10\n\x08identity\x18\x03 \x01(\t" \n\x1e\x44\x65leteWorkerDeploymentResponse"\xa2\x03\n,UpdateWorkerDeploymentVersionMetadataRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x07version\x18\x02 \x01(\tB\x02\x18\x01\x12O\n\x12\x64\x65ployment_version\x18\x05 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersion\x12x\n\x0eupsert_entries\x18\x03 \x03(\x0b\x32`.temporal.api.workflowservice.v1.UpdateWorkerDeploymentVersionMetadataRequest.UpsertEntriesEntry\x12\x16\n\x0eremove_entries\x18\x04 \x03(\t\x12\x10\n\x08identity\x18\x06 \x01(\t\x1aU\n\x12UpsertEntriesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12.\n\x05value\x18\x02 \x01(\x0b\x32\x1f.temporal.api.common.v1.Payload:\x02\x38\x01"n\n-UpdateWorkerDeploymentVersionMetadataResponse\x12=\n\x08metadata\x18\x01 \x01(\x0b\x32+.temporal.api.deployment.v1.VersionMetadata"\xbd\x01\n!SetWorkerDeploymentManagerRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x17\n\x0f\x64\x65ployment_name\x18\x02 \x01(\t\x12\x1a\n\x10manager_identity\x18\x03 \x01(\tH\x00\x12\x0e\n\x04self\x18\x04 \x01(\x08H\x00\x12\x16\n\x0e\x63onflict_token\x18\x05 \x01(\x0c\x12\x10\n\x08identity\x18\x06 \x01(\tB\x16\n\x14new_manager_identity"c\n"SetWorkerDeploymentManagerResponse\x12\x16\n\x0e\x63onflict_token\x18\x01 \x01(\x0c\x12%\n\x19previous_manager_identity\x18\x02 \x01(\tB\x02\x18\x01"E\n\x1bGetCurrentDeploymentRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bseries_name\x18\x02 \x01(\t"k\n\x1cGetCurrentDeploymentResponse\x12K\n\x17\x63urrent_deployment_info\x18\x01 \x01(\x0b\x32*.temporal.api.deployment.v1.DeploymentInfo"q\n GetDeploymentReachabilityRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12:\n\ndeployment\x18\x02 \x01(\x0b\x32&.temporal.api.deployment.v1.Deployment"\xe3\x01\n!GetDeploymentReachabilityResponse\x12\x43\n\x0f\x64\x65ployment_info\x18\x01 \x01(\x0b\x32*.temporal.api.deployment.v1.DeploymentInfo\x12\x43\n\x0creachability\x18\x02 \x01(\x0e\x32-.temporal.api.enums.v1.DeploymentReachability\x12\x34\n\x10last_update_time\x18\x03 \x01(\x0b\x32\x1a.google.protobuf.Timestamp"\xb4\x01\n\x19\x43reateWorkflowRuleRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x35\n\x04spec\x18\x02 \x01(\x0b\x32\'.temporal.api.rules.v1.WorkflowRuleSpec\x12\x12\n\nforce_scan\x18\x03 \x01(\x08\x12\x12\n\nrequest_id\x18\x04 \x01(\t\x12\x10\n\x08identity\x18\x05 \x01(\t\x12\x13\n\x0b\x64\x65scription\x18\x06 \x01(\t"_\n\x1a\x43reateWorkflowRuleResponse\x12\x31\n\x04rule\x18\x01 \x01(\x0b\x32#.temporal.api.rules.v1.WorkflowRule\x12\x0e\n\x06job_id\x18\x02 \x01(\t"A\n\x1b\x44\x65scribeWorkflowRuleRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x0f\n\x07rule_id\x18\x02 \x01(\t"Q\n\x1c\x44\x65scribeWorkflowRuleResponse\x12\x31\n\x04rule\x18\x01 \x01(\x0b\x32#.temporal.api.rules.v1.WorkflowRule"?\n\x19\x44\x65leteWorkflowRuleRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x0f\n\x07rule_id\x18\x02 \x01(\t"\x1c\n\x1a\x44\x65leteWorkflowRuleResponse"F\n\x18ListWorkflowRulesRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c"h\n\x19ListWorkflowRulesResponse\x12\x32\n\x05rules\x18\x01 \x03(\x0b\x32#.temporal.api.rules.v1.WorkflowRule\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c"\xce\x01\n\x1aTriggerWorkflowRuleRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12<\n\texecution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x0c\n\x02id\x18\x04 \x01(\tH\x00\x12\x37\n\x04spec\x18\x05 \x01(\x0b\x32\'.temporal.api.rules.v1.WorkflowRuleSpecH\x00\x12\x10\n\x08identity\x18\x03 \x01(\tB\x06\n\x04rule".\n\x1bTriggerWorkflowRuleResponse\x12\x0f\n\x07\x61pplied\x18\x01 \x01(\x08"\x9b\x01\n\x1cRecordWorkerHeartbeatRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x10\n\x08identity\x18\x02 \x01(\t\x12\x41\n\x10worker_heartbeat\x18\x03 \x03(\x0b\x32\'.temporal.api.worker.v1.WorkerHeartbeat\x12\x13\n\x0bresource_id\x18\x04 \x01(\t"\x1f\n\x1dRecordWorkerHeartbeatResponse"b\n\x12ListWorkersRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x11\n\tpage_size\x18\x02 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c\x12\r\n\x05query\x18\x04 \x01(\t"\xa5\x01\n\x13ListWorkersResponse\x12<\n\x0cworkers_info\x18\x01 \x03(\x0b\x32".temporal.api.worker.v1.WorkerInfoB\x02\x18\x01\x12\x37\n\x07workers\x18\x03 \x03(\x0b\x32&.temporal.api.worker.v1.WorkerListInfo\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c"\xd5\x05\n\x1cUpdateTaskQueueConfigRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x10\n\x08identity\x18\x02 \x01(\t\x12\x12\n\ntask_queue\x18\x03 \x01(\t\x12=\n\x0ftask_queue_type\x18\x04 \x01(\x0e\x32$.temporal.api.enums.v1.TaskQueueType\x12n\n\x17update_queue_rate_limit\x18\x05 \x01(\x0b\x32M.temporal.api.workflowservice.v1.UpdateTaskQueueConfigRequest.RateLimitUpdate\x12}\n&update_fairness_key_rate_limit_default\x18\x06 \x01(\x0b\x32M.temporal.api.workflowservice.v1.UpdateTaskQueueConfigRequest.RateLimitUpdate\x12\x84\x01\n\x1dset_fairness_weight_overrides\x18\x07 \x03(\x0b\x32].temporal.api.workflowservice.v1.UpdateTaskQueueConfigRequest.SetFairnessWeightOverridesEntry\x12\'\n\x1funset_fairness_weight_overrides\x18\x08 \x03(\t\x1a[\n\x0fRateLimitUpdate\x12\x38\n\nrate_limit\x18\x01 \x01(\x0b\x32$.temporal.api.taskqueue.v1.RateLimit\x12\x0e\n\x06reason\x18\x02 \x01(\t\x1a\x41\n\x1fSetFairnessWeightOverridesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\x02:\x02\x38\x01"[\n\x1dUpdateTaskQueueConfigResponse\x12:\n\x06\x63onfig\x18\x01 \x01(\x0b\x32*.temporal.api.taskqueue.v1.TaskQueueConfig"\x9e\x01\n\x18\x46\x65tchWorkerConfigRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x10\n\x08identity\x18\x02 \x01(\t\x12\x0e\n\x06reason\x18\x03 \x01(\t\x12\x38\n\x08selector\x18\x06 \x01(\x0b\x32&.temporal.api.common.v1.WorkerSelector\x12\x13\n\x0bresource_id\x18\x07 \x01(\t"U\n\x19\x46\x65tchWorkerConfigResponse\x12\x38\n\rworker_config\x18\x01 \x01(\x0b\x32!.temporal.api.sdk.v1.WorkerConfig"\x8a\x02\n\x19UpdateWorkerConfigRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x10\n\x08identity\x18\x02 \x01(\t\x12\x0e\n\x06reason\x18\x03 \x01(\t\x12\x38\n\rworker_config\x18\x04 \x01(\x0b\x32!.temporal.api.sdk.v1.WorkerConfig\x12/\n\x0bupdate_mask\x18\x05 \x01(\x0b\x32\x1a.google.protobuf.FieldMask\x12\x38\n\x08selector\x18\x06 \x01(\x0b\x32&.temporal.api.common.v1.WorkerSelector\x12\x13\n\x0bresource_id\x18\x07 \x01(\t"d\n\x1aUpdateWorkerConfigResponse\x12:\n\rworker_config\x18\x01 \x01(\x0b\x32!.temporal.api.sdk.v1.WorkerConfigH\x00\x42\n\n\x08response"G\n\x15\x44\x65scribeWorkerRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x1b\n\x13worker_instance_key\x18\x02 \x01(\t"Q\n\x16\x44\x65scribeWorkerResponse\x12\x37\n\x0bworker_info\x18\x01 \x01(\x0b\x32".temporal.api.worker.v1.WorkerInfo"\x8d\x01\n\x1dPauseWorkflowExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x12\x10\n\x08identity\x18\x04 \x01(\t\x12\x0e\n\x06reason\x18\x05 \x01(\t\x12\x12\n\nrequest_id\x18\x06 \x01(\t" \n\x1ePauseWorkflowExecutionResponse"\x8f\x01\n\x1fUnpauseWorkflowExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x12\x10\n\x08identity\x18\x04 \x01(\t\x12\x0e\n\x06reason\x18\x05 \x01(\t\x12\x12\n\nrequest_id\x18\x06 \x01(\t""\n UnpauseWorkflowExecutionResponse"\xb4\x07\n\x1dStartActivityExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x10\n\x08identity\x18\x02 \x01(\t\x12\x12\n\nrequest_id\x18\x03 \x01(\t\x12\x13\n\x0b\x61\x63tivity_id\x18\x04 \x01(\t\x12;\n\ractivity_type\x18\x05 \x01(\x0b\x32$.temporal.api.common.v1.ActivityType\x12\x38\n\ntask_queue\x18\x06 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12<\n\x19schedule_to_close_timeout\x18\x07 \x01(\x0b\x32\x19.google.protobuf.Duration\x12<\n\x19schedule_to_start_timeout\x18\x08 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x39\n\x16start_to_close_timeout\x18\t \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x34\n\x11heartbeat_timeout\x18\n \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x39\n\x0cretry_policy\x18\x0b \x01(\x0b\x32#.temporal.api.common.v1.RetryPolicy\x12/\n\x05input\x18\x0c \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x45\n\x0fid_reuse_policy\x18\r \x01(\x0e\x32,.temporal.api.enums.v1.ActivityIdReusePolicy\x12K\n\x12id_conflict_policy\x18\x0e \x01(\x0e\x32/.temporal.api.enums.v1.ActivityIdConflictPolicy\x12\x43\n\x11search_attributes\x18\x0f \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes\x12.\n\x06header\x18\x10 \x01(\x0b\x32\x1e.temporal.api.common.v1.Header\x12\x38\n\ruser_metadata\x18\x11 \x01(\x0b\x32!.temporal.api.sdk.v1.UserMetadata\x12\x32\n\x08priority\x18\x12 \x01(\x0b\x32 .temporal.api.common.v1.Priority"A\n\x1eStartActivityExecutionResponse\x12\x0e\n\x06run_id\x18\x01 \x01(\t\x12\x0f\n\x07started\x18\x02 \x01(\x08"\xa3\x01\n DescribeActivityExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0b\x61\x63tivity_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x12\x15\n\rinclude_input\x18\x04 \x01(\x08\x12\x17\n\x0finclude_outcome\x18\x05 \x01(\x08\x12\x17\n\x0flong_poll_token\x18\x06 \x01(\x0c"\x81\x02\n!DescribeActivityExecutionResponse\x12\x0e\n\x06run_id\x18\x01 \x01(\t\x12=\n\x04info\x18\x02 \x01(\x0b\x32/.temporal.api.activity.v1.ActivityExecutionInfo\x12/\n\x05input\x18\x03 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x43\n\x07outcome\x18\x04 \x01(\x0b\x32\x32.temporal.api.activity.v1.ActivityExecutionOutcome\x12\x17\n\x0flong_poll_token\x18\x05 \x01(\x0c"V\n\x1cPollActivityExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0b\x61\x63tivity_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t"t\n\x1dPollActivityExecutionResponse\x12\x0e\n\x06run_id\x18\x01 \x01(\t\x12\x43\n\x07outcome\x18\x02 \x01(\x0b\x32\x32.temporal.api.activity.v1.ActivityExecutionOutcome"m\n\x1dListActivityExecutionsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x11\n\tpage_size\x18\x02 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c\x12\r\n\x05query\x18\x04 \x01(\t"\x82\x01\n\x1eListActivityExecutionsResponse\x12G\n\nexecutions\x18\x01 \x03(\x0b\x32\x33.temporal.api.activity.v1.ActivityExecutionListInfo\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c"B\n\x1e\x43ountActivityExecutionsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\r\n\x05query\x18\x02 \x01(\t"\xed\x01\n\x1f\x43ountActivityExecutionsResponse\x12\r\n\x05\x63ount\x18\x01 \x01(\x03\x12\x61\n\x06groups\x18\x02 \x03(\x0b\x32Q.temporal.api.workflowservice.v1.CountActivityExecutionsResponse.AggregationGroup\x1aX\n\x10\x41ggregationGroup\x12\x35\n\x0cgroup_values\x18\x01 \x03(\x0b\x32\x1f.temporal.api.common.v1.Payload\x12\r\n\x05\x63ount\x18\x02 \x01(\x03"\x95\x01\n%RequestCancelActivityExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0b\x61\x63tivity_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x12\x10\n\x08identity\x18\x04 \x01(\t\x12\x12\n\nrequest_id\x18\x05 \x01(\t\x12\x0e\n\x06reason\x18\x06 \x01(\t"(\n&RequestCancelActivityExecutionResponse"\x91\x01\n!TerminateActivityExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0b\x61\x63tivity_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x12\x10\n\x08identity\x18\x04 \x01(\t\x12\x12\n\nrequest_id\x18\x05 \x01(\t\x12\x0e\n\x06reason\x18\x06 \x01(\t"$\n"TerminateActivityExecutionResponse"X\n\x1e\x44\x65leteActivityExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0b\x61\x63tivity_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t"!\n\x1f\x44\x65leteActivityExecutionResponseB\xbe\x01\n"io.temporal.api.workflowservice.v1B\x14RequestResponseProtoP\x01Z5go.temporal.io/api/workflowservice/v1;workflowservice\xaa\x02!Temporalio.Api.WorkflowService.V1\xea\x02$Temporalio::Api::WorkflowService::V1b\x06proto3' ) @@ -3654,457 +3654,457 @@ _POLLWORKFLOWTASKQUEUERESPONSE_QUERIESENTRY._serialized_start = 7460 _POLLWORKFLOWTASKQUEUERESPONSE_QUERIESENTRY._serialized_end = 7544 _RESPONDWORKFLOWTASKCOMPLETEDREQUEST._serialized_start = 7547 - _RESPONDWORKFLOWTASKCOMPLETEDREQUEST._serialized_end = 8752 - _RESPONDWORKFLOWTASKCOMPLETEDREQUEST_QUERYRESULTSENTRY._serialized_start = 8586 - _RESPONDWORKFLOWTASKCOMPLETEDREQUEST_QUERYRESULTSENTRY._serialized_end = 8681 - _RESPONDWORKFLOWTASKCOMPLETEDREQUEST_CAPABILITIES._serialized_start = 8683 - _RESPONDWORKFLOWTASKCOMPLETEDREQUEST_CAPABILITIES._serialized_end = 8752 - _RESPONDWORKFLOWTASKCOMPLETEDRESPONSE._serialized_start = 8755 - _RESPONDWORKFLOWTASKCOMPLETEDRESPONSE._serialized_end = 9000 - _RESPONDWORKFLOWTASKFAILEDREQUEST._serialized_start = 9003 - _RESPONDWORKFLOWTASKFAILEDREQUEST._serialized_end = 9507 - _RESPONDWORKFLOWTASKFAILEDRESPONSE._serialized_start = 9509 - _RESPONDWORKFLOWTASKFAILEDRESPONSE._serialized_end = 9544 - _POLLACTIVITYTASKQUEUEREQUEST._serialized_start = 9547 - _POLLACTIVITYTASKQUEUEREQUEST._serialized_end = 9973 - _POLLACTIVITYTASKQUEUERESPONSE._serialized_start = 9976 - _POLLACTIVITYTASKQUEUERESPONSE._serialized_end = 11008 - _RECORDACTIVITYTASKHEARTBEATREQUEST._serialized_start = 11011 - _RECORDACTIVITYTASKHEARTBEATREQUEST._serialized_end = 11155 - _RECORDACTIVITYTASKHEARTBEATRESPONSE._serialized_start = 11157 - _RECORDACTIVITYTASKHEARTBEATRESPONSE._serialized_end = 11269 - _RECORDACTIVITYTASKHEARTBEATBYIDREQUEST._serialized_start = 11272 - _RECORDACTIVITYTASKHEARTBEATBYIDREQUEST._serialized_end = 11458 - _RECORDACTIVITYTASKHEARTBEATBYIDRESPONSE._serialized_start = 11460 - _RECORDACTIVITYTASKHEARTBEATBYIDRESPONSE._serialized_end = 11576 - _RESPONDACTIVITYTASKCOMPLETEDREQUEST._serialized_start = 11579 - _RESPONDACTIVITYTASKCOMPLETEDREQUEST._serialized_end = 11940 - _RESPONDACTIVITYTASKCOMPLETEDRESPONSE._serialized_start = 11942 - _RESPONDACTIVITYTASKCOMPLETEDRESPONSE._serialized_end = 11980 - _RESPONDACTIVITYTASKCOMPLETEDBYIDREQUEST._serialized_start = 11983 - _RESPONDACTIVITYTASKCOMPLETEDBYIDREQUEST._serialized_end = 12169 - _RESPONDACTIVITYTASKCOMPLETEDBYIDRESPONSE._serialized_start = 12171 - _RESPONDACTIVITYTASKCOMPLETEDBYIDRESPONSE._serialized_end = 12213 - _RESPONDACTIVITYTASKFAILEDREQUEST._serialized_start = 12216 - _RESPONDACTIVITYTASKFAILEDREQUEST._serialized_end = 12641 - _RESPONDACTIVITYTASKFAILEDRESPONSE._serialized_start = 12643 - _RESPONDACTIVITYTASKFAILEDRESPONSE._serialized_end = 12730 - _RESPONDACTIVITYTASKFAILEDBYIDREQUEST._serialized_start = 12733 - _RESPONDACTIVITYTASKFAILEDBYIDREQUEST._serialized_end = 12983 - _RESPONDACTIVITYTASKFAILEDBYIDRESPONSE._serialized_start = 12985 - _RESPONDACTIVITYTASKFAILEDBYIDRESPONSE._serialized_end = 13076 - _RESPONDACTIVITYTASKCANCELEDREQUEST._serialized_start = 13079 - _RESPONDACTIVITYTASKCANCELEDREQUEST._serialized_end = 13440 - _RESPONDACTIVITYTASKCANCELEDRESPONSE._serialized_start = 13442 - _RESPONDACTIVITYTASKCANCELEDRESPONSE._serialized_end = 13479 - _RESPONDACTIVITYTASKCANCELEDBYIDREQUEST._serialized_start = 13482 - _RESPONDACTIVITYTASKCANCELEDBYIDREQUEST._serialized_end = 13749 - _RESPONDACTIVITYTASKCANCELEDBYIDRESPONSE._serialized_start = 13751 - _RESPONDACTIVITYTASKCANCELEDBYIDRESPONSE._serialized_end = 13792 - _REQUESTCANCELWORKFLOWEXECUTIONREQUEST._serialized_start = 13795 - _REQUESTCANCELWORKFLOWEXECUTIONREQUEST._serialized_end = 14055 - _REQUESTCANCELWORKFLOWEXECUTIONRESPONSE._serialized_start = 14057 - _REQUESTCANCELWORKFLOWEXECUTIONRESPONSE._serialized_end = 14097 - _SIGNALWORKFLOWEXECUTIONREQUEST._serialized_start = 14100 - _SIGNALWORKFLOWEXECUTIONREQUEST._serialized_end = 14450 - _SIGNALWORKFLOWEXECUTIONRESPONSE._serialized_start = 14452 - _SIGNALWORKFLOWEXECUTIONRESPONSE._serialized_end = 14485 - _SIGNALWITHSTARTWORKFLOWEXECUTIONREQUEST._serialized_start = 14488 - _SIGNALWITHSTARTWORKFLOWEXECUTIONREQUEST._serialized_end = 15753 - _SIGNALWITHSTARTWORKFLOWEXECUTIONRESPONSE._serialized_start = 15755 - _SIGNALWITHSTARTWORKFLOWEXECUTIONRESPONSE._serialized_end = 15830 - _RESETWORKFLOWEXECUTIONREQUEST._serialized_start = 15833 - _RESETWORKFLOWEXECUTIONREQUEST._serialized_end = 16282 - _RESETWORKFLOWEXECUTIONRESPONSE._serialized_start = 16284 - _RESETWORKFLOWEXECUTIONRESPONSE._serialized_end = 16332 - _TERMINATEWORKFLOWEXECUTIONREQUEST._serialized_start = 16335 - _TERMINATEWORKFLOWEXECUTIONREQUEST._serialized_end = 16622 - _TERMINATEWORKFLOWEXECUTIONRESPONSE._serialized_start = 16624 - _TERMINATEWORKFLOWEXECUTIONRESPONSE._serialized_end = 16660 - _DELETEWORKFLOWEXECUTIONREQUEST._serialized_start = 16662 - _DELETEWORKFLOWEXECUTIONREQUEST._serialized_end = 16784 - _DELETEWORKFLOWEXECUTIONRESPONSE._serialized_start = 16786 - _DELETEWORKFLOWEXECUTIONRESPONSE._serialized_end = 16819 - _LISTOPENWORKFLOWEXECUTIONSREQUEST._serialized_start = 16822 - _LISTOPENWORKFLOWEXECUTIONSREQUEST._serialized_end = 17151 - _LISTOPENWORKFLOWEXECUTIONSRESPONSE._serialized_start = 17154 - _LISTOPENWORKFLOWEXECUTIONSRESPONSE._serialized_end = 17284 - _LISTCLOSEDWORKFLOWEXECUTIONSREQUEST._serialized_start = 17287 - _LISTCLOSEDWORKFLOWEXECUTIONSREQUEST._serialized_end = 17681 - _LISTCLOSEDWORKFLOWEXECUTIONSRESPONSE._serialized_start = 17684 - _LISTCLOSEDWORKFLOWEXECUTIONSRESPONSE._serialized_end = 17816 - _LISTWORKFLOWEXECUTIONSREQUEST._serialized_start = 17818 - _LISTWORKFLOWEXECUTIONSREQUEST._serialized_end = 17927 - _LISTWORKFLOWEXECUTIONSRESPONSE._serialized_start = 17929 - _LISTWORKFLOWEXECUTIONSRESPONSE._serialized_end = 18055 - _LISTARCHIVEDWORKFLOWEXECUTIONSREQUEST._serialized_start = 18057 - _LISTARCHIVEDWORKFLOWEXECUTIONSREQUEST._serialized_end = 18174 - _LISTARCHIVEDWORKFLOWEXECUTIONSRESPONSE._serialized_start = 18177 - _LISTARCHIVEDWORKFLOWEXECUTIONSRESPONSE._serialized_end = 18311 - _SCANWORKFLOWEXECUTIONSREQUEST._serialized_start = 18313 - _SCANWORKFLOWEXECUTIONSREQUEST._serialized_end = 18422 - _SCANWORKFLOWEXECUTIONSRESPONSE._serialized_start = 18424 - _SCANWORKFLOWEXECUTIONSRESPONSE._serialized_end = 18550 - _COUNTWORKFLOWEXECUTIONSREQUEST._serialized_start = 18552 - _COUNTWORKFLOWEXECUTIONSREQUEST._serialized_end = 18618 - _COUNTWORKFLOWEXECUTIONSRESPONSE._serialized_start = 18621 - _COUNTWORKFLOWEXECUTIONSRESPONSE._serialized_end = 18858 - _COUNTWORKFLOWEXECUTIONSRESPONSE_AGGREGATIONGROUP._serialized_start = 18770 - _COUNTWORKFLOWEXECUTIONSRESPONSE_AGGREGATIONGROUP._serialized_end = 18858 - _GETSEARCHATTRIBUTESREQUEST._serialized_start = 18860 - _GETSEARCHATTRIBUTESREQUEST._serialized_end = 18888 - _GETSEARCHATTRIBUTESRESPONSE._serialized_start = 18891 - _GETSEARCHATTRIBUTESRESPONSE._serialized_end = 19092 - _GETSEARCHATTRIBUTESRESPONSE_KEYSENTRY._serialized_start = 19008 - _GETSEARCHATTRIBUTESRESPONSE_KEYSENTRY._serialized_end = 19092 - _RESPONDQUERYTASKCOMPLETEDREQUEST._serialized_start = 19095 - _RESPONDQUERYTASKCOMPLETEDREQUEST._serialized_end = 19431 - _RESPONDQUERYTASKCOMPLETEDRESPONSE._serialized_start = 19433 - _RESPONDQUERYTASKCOMPLETEDRESPONSE._serialized_end = 19468 - _RESETSTICKYTASKQUEUEREQUEST._serialized_start = 19470 - _RESETSTICKYTASKQUEUEREQUEST._serialized_end = 19580 - _RESETSTICKYTASKQUEUERESPONSE._serialized_start = 19582 - _RESETSTICKYTASKQUEUERESPONSE._serialized_end = 19612 - _SHUTDOWNWORKERREQUEST._serialized_start = 19615 - _SHUTDOWNWORKERREQUEST._serialized_end = 19898 - _SHUTDOWNWORKERRESPONSE._serialized_start = 19900 - _SHUTDOWNWORKERRESPONSE._serialized_end = 19924 - _QUERYWORKFLOWREQUEST._serialized_start = 19927 - _QUERYWORKFLOWREQUEST._serialized_end = 20160 - _QUERYWORKFLOWRESPONSE._serialized_start = 20163 - _QUERYWORKFLOWRESPONSE._serialized_end = 20304 - _DESCRIBEWORKFLOWEXECUTIONREQUEST._serialized_start = 20306 - _DESCRIBEWORKFLOWEXECUTIONREQUEST._serialized_end = 20421 - _DESCRIBEWORKFLOWEXECUTIONRESPONSE._serialized_start = 20424 - _DESCRIBEWORKFLOWEXECUTIONRESPONSE._serialized_end = 21089 - _DESCRIBETASKQUEUEREQUEST._serialized_start = 21092 - _DESCRIBETASKQUEUEREQUEST._serialized_end = 21620 - _DESCRIBETASKQUEUERESPONSE._serialized_start = 21623 - _DESCRIBETASKQUEUERESPONSE._serialized_end = 22627 - _DESCRIBETASKQUEUERESPONSE_STATSBYPRIORITYKEYENTRY._serialized_start = 22307 - _DESCRIBETASKQUEUERESPONSE_STATSBYPRIORITYKEYENTRY._serialized_end = 22407 - _DESCRIBETASKQUEUERESPONSE_EFFECTIVERATELIMIT._serialized_start = 22409 - _DESCRIBETASKQUEUERESPONSE_EFFECTIVERATELIMIT._serialized_end = 22525 - _DESCRIBETASKQUEUERESPONSE_VERSIONSINFOENTRY._serialized_start = 22527 - _DESCRIBETASKQUEUERESPONSE_VERSIONSINFOENTRY._serialized_end = 22627 - _GETCLUSTERINFOREQUEST._serialized_start = 22629 - _GETCLUSTERINFOREQUEST._serialized_end = 22652 - _GETCLUSTERINFORESPONSE._serialized_start = 22655 - _GETCLUSTERINFORESPONSE._serialized_end = 23120 - _GETCLUSTERINFORESPONSE_SUPPORTEDCLIENTSENTRY._serialized_start = 23065 - _GETCLUSTERINFORESPONSE_SUPPORTEDCLIENTSENTRY._serialized_end = 23120 - _GETSYSTEMINFOREQUEST._serialized_start = 23122 - _GETSYSTEMINFOREQUEST._serialized_end = 23144 - _GETSYSTEMINFORESPONSE._serialized_start = 23147 - _GETSYSTEMINFORESPONSE._serialized_end = 23647 - _GETSYSTEMINFORESPONSE_CAPABILITIES._serialized_start = 23288 - _GETSYSTEMINFORESPONSE_CAPABILITIES._serialized_end = 23647 - _LISTTASKQUEUEPARTITIONSREQUEST._serialized_start = 23649 - _LISTTASKQUEUEPARTITIONSREQUEST._serialized_end = 23758 - _LISTTASKQUEUEPARTITIONSRESPONSE._serialized_start = 23761 - _LISTTASKQUEUEPARTITIONSRESPONSE._serialized_end = 23984 - _CREATESCHEDULEREQUEST._serialized_start = 23987 - _CREATESCHEDULEREQUEST._serialized_end = 24319 - _CREATESCHEDULERESPONSE._serialized_start = 24321 - _CREATESCHEDULERESPONSE._serialized_end = 24369 - _DESCRIBESCHEDULEREQUEST._serialized_start = 24371 - _DESCRIBESCHEDULEREQUEST._serialized_end = 24436 - _DESCRIBESCHEDULERESPONSE._serialized_start = 24439 - _DESCRIBESCHEDULERESPONSE._serialized_end = 24710 - _UPDATESCHEDULEREQUEST._serialized_start = 24713 - _UPDATESCHEDULEREQUEST._serialized_end = 24961 - _UPDATESCHEDULERESPONSE._serialized_start = 24963 - _UPDATESCHEDULERESPONSE._serialized_end = 24987 - _PATCHSCHEDULEREQUEST._serialized_start = 24990 - _PATCHSCHEDULEREQUEST._serialized_end = 25146 - _PATCHSCHEDULERESPONSE._serialized_start = 25148 - _PATCHSCHEDULERESPONSE._serialized_end = 25171 - _LISTSCHEDULEMATCHINGTIMESREQUEST._serialized_start = 25174 - _LISTSCHEDULEMATCHINGTIMESREQUEST._serialized_end = 25342 - _LISTSCHEDULEMATCHINGTIMESRESPONSE._serialized_start = 25344 - _LISTSCHEDULEMATCHINGTIMESRESPONSE._serialized_end = 25427 - _DELETESCHEDULEREQUEST._serialized_start = 25429 - _DELETESCHEDULEREQUEST._serialized_end = 25510 - _DELETESCHEDULERESPONSE._serialized_start = 25512 - _DELETESCHEDULERESPONSE._serialized_end = 25536 - _LISTSCHEDULESREQUEST._serialized_start = 25538 - _LISTSCHEDULESREQUEST._serialized_end = 25646 - _LISTSCHEDULESRESPONSE._serialized_start = 25648 - _LISTSCHEDULESRESPONSE._serialized_end = 25760 - _COUNTSCHEDULESREQUEST._serialized_start = 25762 - _COUNTSCHEDULESREQUEST._serialized_end = 25819 - _COUNTSCHEDULESRESPONSE._serialized_start = 25822 - _COUNTSCHEDULESRESPONSE._serialized_end = 26041 - _COUNTSCHEDULESRESPONSE_AGGREGATIONGROUP._serialized_start = 18770 - _COUNTSCHEDULESRESPONSE_AGGREGATIONGROUP._serialized_end = 18858 - _UPDATEWORKERBUILDIDCOMPATIBILITYREQUEST._serialized_start = 26044 - _UPDATEWORKERBUILDIDCOMPATIBILITYREQUEST._serialized_end = 26690 - _UPDATEWORKERBUILDIDCOMPATIBILITYREQUEST_ADDNEWCOMPATIBLEVERSION._serialized_start = 26491 + _RESPONDWORKFLOWTASKCOMPLETEDREQUEST._serialized_end = 8773 + _RESPONDWORKFLOWTASKCOMPLETEDREQUEST_QUERYRESULTSENTRY._serialized_start = 8607 + _RESPONDWORKFLOWTASKCOMPLETEDREQUEST_QUERYRESULTSENTRY._serialized_end = 8702 + _RESPONDWORKFLOWTASKCOMPLETEDREQUEST_CAPABILITIES._serialized_start = 8704 + _RESPONDWORKFLOWTASKCOMPLETEDREQUEST_CAPABILITIES._serialized_end = 8773 + _RESPONDWORKFLOWTASKCOMPLETEDRESPONSE._serialized_start = 8776 + _RESPONDWORKFLOWTASKCOMPLETEDRESPONSE._serialized_end = 9021 + _RESPONDWORKFLOWTASKFAILEDREQUEST._serialized_start = 9024 + _RESPONDWORKFLOWTASKFAILEDREQUEST._serialized_end = 9549 + _RESPONDWORKFLOWTASKFAILEDRESPONSE._serialized_start = 9551 + _RESPONDWORKFLOWTASKFAILEDRESPONSE._serialized_end = 9586 + _POLLACTIVITYTASKQUEUEREQUEST._serialized_start = 9589 + _POLLACTIVITYTASKQUEUEREQUEST._serialized_end = 10015 + _POLLACTIVITYTASKQUEUERESPONSE._serialized_start = 10018 + _POLLACTIVITYTASKQUEUERESPONSE._serialized_end = 11050 + _RECORDACTIVITYTASKHEARTBEATREQUEST._serialized_start = 11053 + _RECORDACTIVITYTASKHEARTBEATREQUEST._serialized_end = 11218 + _RECORDACTIVITYTASKHEARTBEATRESPONSE._serialized_start = 11220 + _RECORDACTIVITYTASKHEARTBEATRESPONSE._serialized_end = 11332 + _RECORDACTIVITYTASKHEARTBEATBYIDREQUEST._serialized_start = 11335 + _RECORDACTIVITYTASKHEARTBEATBYIDREQUEST._serialized_end = 11542 + _RECORDACTIVITYTASKHEARTBEATBYIDRESPONSE._serialized_start = 11544 + _RECORDACTIVITYTASKHEARTBEATBYIDRESPONSE._serialized_end = 11660 + _RESPONDACTIVITYTASKCOMPLETEDREQUEST._serialized_start = 11663 + _RESPONDACTIVITYTASKCOMPLETEDREQUEST._serialized_end = 12045 + _RESPONDACTIVITYTASKCOMPLETEDRESPONSE._serialized_start = 12047 + _RESPONDACTIVITYTASKCOMPLETEDRESPONSE._serialized_end = 12085 + _RESPONDACTIVITYTASKCOMPLETEDBYIDREQUEST._serialized_start = 12088 + _RESPONDACTIVITYTASKCOMPLETEDBYIDREQUEST._serialized_end = 12295 + _RESPONDACTIVITYTASKCOMPLETEDBYIDRESPONSE._serialized_start = 12297 + _RESPONDACTIVITYTASKCOMPLETEDBYIDRESPONSE._serialized_end = 12339 + _RESPONDACTIVITYTASKFAILEDREQUEST._serialized_start = 12342 + _RESPONDACTIVITYTASKFAILEDREQUEST._serialized_end = 12788 + _RESPONDACTIVITYTASKFAILEDRESPONSE._serialized_start = 12790 + _RESPONDACTIVITYTASKFAILEDRESPONSE._serialized_end = 12877 + _RESPONDACTIVITYTASKFAILEDBYIDREQUEST._serialized_start = 12880 + _RESPONDACTIVITYTASKFAILEDBYIDREQUEST._serialized_end = 13151 + _RESPONDACTIVITYTASKFAILEDBYIDRESPONSE._serialized_start = 13153 + _RESPONDACTIVITYTASKFAILEDBYIDRESPONSE._serialized_end = 13244 + _RESPONDACTIVITYTASKCANCELEDREQUEST._serialized_start = 13247 + _RESPONDACTIVITYTASKCANCELEDREQUEST._serialized_end = 13629 + _RESPONDACTIVITYTASKCANCELEDRESPONSE._serialized_start = 13631 + _RESPONDACTIVITYTASKCANCELEDRESPONSE._serialized_end = 13668 + _RESPONDACTIVITYTASKCANCELEDBYIDREQUEST._serialized_start = 13671 + _RESPONDACTIVITYTASKCANCELEDBYIDREQUEST._serialized_end = 13959 + _RESPONDACTIVITYTASKCANCELEDBYIDRESPONSE._serialized_start = 13961 + _RESPONDACTIVITYTASKCANCELEDBYIDRESPONSE._serialized_end = 14002 + _REQUESTCANCELWORKFLOWEXECUTIONREQUEST._serialized_start = 14005 + _REQUESTCANCELWORKFLOWEXECUTIONREQUEST._serialized_end = 14265 + _REQUESTCANCELWORKFLOWEXECUTIONRESPONSE._serialized_start = 14267 + _REQUESTCANCELWORKFLOWEXECUTIONRESPONSE._serialized_end = 14307 + _SIGNALWORKFLOWEXECUTIONREQUEST._serialized_start = 14310 + _SIGNALWORKFLOWEXECUTIONREQUEST._serialized_end = 14660 + _SIGNALWORKFLOWEXECUTIONRESPONSE._serialized_start = 14662 + _SIGNALWORKFLOWEXECUTIONRESPONSE._serialized_end = 14695 + _SIGNALWITHSTARTWORKFLOWEXECUTIONREQUEST._serialized_start = 14698 + _SIGNALWITHSTARTWORKFLOWEXECUTIONREQUEST._serialized_end = 15963 + _SIGNALWITHSTARTWORKFLOWEXECUTIONRESPONSE._serialized_start = 15965 + _SIGNALWITHSTARTWORKFLOWEXECUTIONRESPONSE._serialized_end = 16040 + _RESETWORKFLOWEXECUTIONREQUEST._serialized_start = 16043 + _RESETWORKFLOWEXECUTIONREQUEST._serialized_end = 16492 + _RESETWORKFLOWEXECUTIONRESPONSE._serialized_start = 16494 + _RESETWORKFLOWEXECUTIONRESPONSE._serialized_end = 16542 + _TERMINATEWORKFLOWEXECUTIONREQUEST._serialized_start = 16545 + _TERMINATEWORKFLOWEXECUTIONREQUEST._serialized_end = 16832 + _TERMINATEWORKFLOWEXECUTIONRESPONSE._serialized_start = 16834 + _TERMINATEWORKFLOWEXECUTIONRESPONSE._serialized_end = 16870 + _DELETEWORKFLOWEXECUTIONREQUEST._serialized_start = 16872 + _DELETEWORKFLOWEXECUTIONREQUEST._serialized_end = 16994 + _DELETEWORKFLOWEXECUTIONRESPONSE._serialized_start = 16996 + _DELETEWORKFLOWEXECUTIONRESPONSE._serialized_end = 17029 + _LISTOPENWORKFLOWEXECUTIONSREQUEST._serialized_start = 17032 + _LISTOPENWORKFLOWEXECUTIONSREQUEST._serialized_end = 17361 + _LISTOPENWORKFLOWEXECUTIONSRESPONSE._serialized_start = 17364 + _LISTOPENWORKFLOWEXECUTIONSRESPONSE._serialized_end = 17494 + _LISTCLOSEDWORKFLOWEXECUTIONSREQUEST._serialized_start = 17497 + _LISTCLOSEDWORKFLOWEXECUTIONSREQUEST._serialized_end = 17891 + _LISTCLOSEDWORKFLOWEXECUTIONSRESPONSE._serialized_start = 17894 + _LISTCLOSEDWORKFLOWEXECUTIONSRESPONSE._serialized_end = 18026 + _LISTWORKFLOWEXECUTIONSREQUEST._serialized_start = 18028 + _LISTWORKFLOWEXECUTIONSREQUEST._serialized_end = 18137 + _LISTWORKFLOWEXECUTIONSRESPONSE._serialized_start = 18139 + _LISTWORKFLOWEXECUTIONSRESPONSE._serialized_end = 18265 + _LISTARCHIVEDWORKFLOWEXECUTIONSREQUEST._serialized_start = 18267 + _LISTARCHIVEDWORKFLOWEXECUTIONSREQUEST._serialized_end = 18384 + _LISTARCHIVEDWORKFLOWEXECUTIONSRESPONSE._serialized_start = 18387 + _LISTARCHIVEDWORKFLOWEXECUTIONSRESPONSE._serialized_end = 18521 + _SCANWORKFLOWEXECUTIONSREQUEST._serialized_start = 18523 + _SCANWORKFLOWEXECUTIONSREQUEST._serialized_end = 18632 + _SCANWORKFLOWEXECUTIONSRESPONSE._serialized_start = 18634 + _SCANWORKFLOWEXECUTIONSRESPONSE._serialized_end = 18760 + _COUNTWORKFLOWEXECUTIONSREQUEST._serialized_start = 18762 + _COUNTWORKFLOWEXECUTIONSREQUEST._serialized_end = 18828 + _COUNTWORKFLOWEXECUTIONSRESPONSE._serialized_start = 18831 + _COUNTWORKFLOWEXECUTIONSRESPONSE._serialized_end = 19068 + _COUNTWORKFLOWEXECUTIONSRESPONSE_AGGREGATIONGROUP._serialized_start = 18980 + _COUNTWORKFLOWEXECUTIONSRESPONSE_AGGREGATIONGROUP._serialized_end = 19068 + _GETSEARCHATTRIBUTESREQUEST._serialized_start = 19070 + _GETSEARCHATTRIBUTESREQUEST._serialized_end = 19098 + _GETSEARCHATTRIBUTESRESPONSE._serialized_start = 19101 + _GETSEARCHATTRIBUTESRESPONSE._serialized_end = 19302 + _GETSEARCHATTRIBUTESRESPONSE_KEYSENTRY._serialized_start = 19218 + _GETSEARCHATTRIBUTESRESPONSE_KEYSENTRY._serialized_end = 19302 + _RESPONDQUERYTASKCOMPLETEDREQUEST._serialized_start = 19305 + _RESPONDQUERYTASKCOMPLETEDREQUEST._serialized_end = 19641 + _RESPONDQUERYTASKCOMPLETEDRESPONSE._serialized_start = 19643 + _RESPONDQUERYTASKCOMPLETEDRESPONSE._serialized_end = 19678 + _RESETSTICKYTASKQUEUEREQUEST._serialized_start = 19680 + _RESETSTICKYTASKQUEUEREQUEST._serialized_end = 19790 + _RESETSTICKYTASKQUEUERESPONSE._serialized_start = 19792 + _RESETSTICKYTASKQUEUERESPONSE._serialized_end = 19822 + _SHUTDOWNWORKERREQUEST._serialized_start = 19825 + _SHUTDOWNWORKERREQUEST._serialized_end = 20108 + _SHUTDOWNWORKERRESPONSE._serialized_start = 20110 + _SHUTDOWNWORKERRESPONSE._serialized_end = 20134 + _QUERYWORKFLOWREQUEST._serialized_start = 20137 + _QUERYWORKFLOWREQUEST._serialized_end = 20370 + _QUERYWORKFLOWRESPONSE._serialized_start = 20373 + _QUERYWORKFLOWRESPONSE._serialized_end = 20514 + _DESCRIBEWORKFLOWEXECUTIONREQUEST._serialized_start = 20516 + _DESCRIBEWORKFLOWEXECUTIONREQUEST._serialized_end = 20631 + _DESCRIBEWORKFLOWEXECUTIONRESPONSE._serialized_start = 20634 + _DESCRIBEWORKFLOWEXECUTIONRESPONSE._serialized_end = 21299 + _DESCRIBETASKQUEUEREQUEST._serialized_start = 21302 + _DESCRIBETASKQUEUEREQUEST._serialized_end = 21830 + _DESCRIBETASKQUEUERESPONSE._serialized_start = 21833 + _DESCRIBETASKQUEUERESPONSE._serialized_end = 22837 + _DESCRIBETASKQUEUERESPONSE_STATSBYPRIORITYKEYENTRY._serialized_start = 22517 + _DESCRIBETASKQUEUERESPONSE_STATSBYPRIORITYKEYENTRY._serialized_end = 22617 + _DESCRIBETASKQUEUERESPONSE_EFFECTIVERATELIMIT._serialized_start = 22619 + _DESCRIBETASKQUEUERESPONSE_EFFECTIVERATELIMIT._serialized_end = 22735 + _DESCRIBETASKQUEUERESPONSE_VERSIONSINFOENTRY._serialized_start = 22737 + _DESCRIBETASKQUEUERESPONSE_VERSIONSINFOENTRY._serialized_end = 22837 + _GETCLUSTERINFOREQUEST._serialized_start = 22839 + _GETCLUSTERINFOREQUEST._serialized_end = 22862 + _GETCLUSTERINFORESPONSE._serialized_start = 22865 + _GETCLUSTERINFORESPONSE._serialized_end = 23330 + _GETCLUSTERINFORESPONSE_SUPPORTEDCLIENTSENTRY._serialized_start = 23275 + _GETCLUSTERINFORESPONSE_SUPPORTEDCLIENTSENTRY._serialized_end = 23330 + _GETSYSTEMINFOREQUEST._serialized_start = 23332 + _GETSYSTEMINFOREQUEST._serialized_end = 23354 + _GETSYSTEMINFORESPONSE._serialized_start = 23357 + _GETSYSTEMINFORESPONSE._serialized_end = 23857 + _GETSYSTEMINFORESPONSE_CAPABILITIES._serialized_start = 23498 + _GETSYSTEMINFORESPONSE_CAPABILITIES._serialized_end = 23857 + _LISTTASKQUEUEPARTITIONSREQUEST._serialized_start = 23859 + _LISTTASKQUEUEPARTITIONSREQUEST._serialized_end = 23968 + _LISTTASKQUEUEPARTITIONSRESPONSE._serialized_start = 23971 + _LISTTASKQUEUEPARTITIONSRESPONSE._serialized_end = 24194 + _CREATESCHEDULEREQUEST._serialized_start = 24197 + _CREATESCHEDULEREQUEST._serialized_end = 24529 + _CREATESCHEDULERESPONSE._serialized_start = 24531 + _CREATESCHEDULERESPONSE._serialized_end = 24579 + _DESCRIBESCHEDULEREQUEST._serialized_start = 24581 + _DESCRIBESCHEDULEREQUEST._serialized_end = 24646 + _DESCRIBESCHEDULERESPONSE._serialized_start = 24649 + _DESCRIBESCHEDULERESPONSE._serialized_end = 24920 + _UPDATESCHEDULEREQUEST._serialized_start = 24923 + _UPDATESCHEDULEREQUEST._serialized_end = 25171 + _UPDATESCHEDULERESPONSE._serialized_start = 25173 + _UPDATESCHEDULERESPONSE._serialized_end = 25197 + _PATCHSCHEDULEREQUEST._serialized_start = 25200 + _PATCHSCHEDULEREQUEST._serialized_end = 25356 + _PATCHSCHEDULERESPONSE._serialized_start = 25358 + _PATCHSCHEDULERESPONSE._serialized_end = 25381 + _LISTSCHEDULEMATCHINGTIMESREQUEST._serialized_start = 25384 + _LISTSCHEDULEMATCHINGTIMESREQUEST._serialized_end = 25552 + _LISTSCHEDULEMATCHINGTIMESRESPONSE._serialized_start = 25554 + _LISTSCHEDULEMATCHINGTIMESRESPONSE._serialized_end = 25637 + _DELETESCHEDULEREQUEST._serialized_start = 25639 + _DELETESCHEDULEREQUEST._serialized_end = 25720 + _DELETESCHEDULERESPONSE._serialized_start = 25722 + _DELETESCHEDULERESPONSE._serialized_end = 25746 + _LISTSCHEDULESREQUEST._serialized_start = 25748 + _LISTSCHEDULESREQUEST._serialized_end = 25856 + _LISTSCHEDULESRESPONSE._serialized_start = 25858 + _LISTSCHEDULESRESPONSE._serialized_end = 25970 + _COUNTSCHEDULESREQUEST._serialized_start = 25972 + _COUNTSCHEDULESREQUEST._serialized_end = 26029 + _COUNTSCHEDULESRESPONSE._serialized_start = 26032 + _COUNTSCHEDULESRESPONSE._serialized_end = 26251 + _COUNTSCHEDULESRESPONSE_AGGREGATIONGROUP._serialized_start = 18980 + _COUNTSCHEDULESRESPONSE_AGGREGATIONGROUP._serialized_end = 19068 + _UPDATEWORKERBUILDIDCOMPATIBILITYREQUEST._serialized_start = 26254 + _UPDATEWORKERBUILDIDCOMPATIBILITYREQUEST._serialized_end = 26900 + _UPDATEWORKERBUILDIDCOMPATIBILITYREQUEST_ADDNEWCOMPATIBLEVERSION._serialized_start = 26701 _UPDATEWORKERBUILDIDCOMPATIBILITYREQUEST_ADDNEWCOMPATIBLEVERSION._serialized_end = ( - 26602 + 26812 ) - _UPDATEWORKERBUILDIDCOMPATIBILITYREQUEST_MERGESETS._serialized_start = 26604 - _UPDATEWORKERBUILDIDCOMPATIBILITYREQUEST_MERGESETS._serialized_end = 26677 - _UPDATEWORKERBUILDIDCOMPATIBILITYRESPONSE._serialized_start = 26692 - _UPDATEWORKERBUILDIDCOMPATIBILITYRESPONSE._serialized_end = 26756 - _GETWORKERBUILDIDCOMPATIBILITYREQUEST._serialized_start = 26758 - _GETWORKERBUILDIDCOMPATIBILITYREQUEST._serialized_end = 26853 - _GETWORKERBUILDIDCOMPATIBILITYRESPONSE._serialized_start = 26855 - _GETWORKERBUILDIDCOMPATIBILITYRESPONSE._serialized_end = 26971 - _UPDATEWORKERVERSIONINGRULESREQUEST._serialized_start = 26974 - _UPDATEWORKERVERSIONINGRULESREQUEST._serialized_end = 28691 - _UPDATEWORKERVERSIONINGRULESREQUEST_INSERTBUILDIDASSIGNMENTRULE._serialized_start = 28026 + _UPDATEWORKERBUILDIDCOMPATIBILITYREQUEST_MERGESETS._serialized_start = 26814 + _UPDATEWORKERBUILDIDCOMPATIBILITYREQUEST_MERGESETS._serialized_end = 26887 + _UPDATEWORKERBUILDIDCOMPATIBILITYRESPONSE._serialized_start = 26902 + _UPDATEWORKERBUILDIDCOMPATIBILITYRESPONSE._serialized_end = 26966 + _GETWORKERBUILDIDCOMPATIBILITYREQUEST._serialized_start = 26968 + _GETWORKERBUILDIDCOMPATIBILITYREQUEST._serialized_end = 27063 + _GETWORKERBUILDIDCOMPATIBILITYRESPONSE._serialized_start = 27065 + _GETWORKERBUILDIDCOMPATIBILITYRESPONSE._serialized_end = 27181 + _UPDATEWORKERVERSIONINGRULESREQUEST._serialized_start = 27184 + _UPDATEWORKERVERSIONINGRULESREQUEST._serialized_end = 28901 + _UPDATEWORKERVERSIONINGRULESREQUEST_INSERTBUILDIDASSIGNMENTRULE._serialized_start = 28236 _UPDATEWORKERVERSIONINGRULESREQUEST_INSERTBUILDIDASSIGNMENTRULE._serialized_end = ( - 28139 + 28349 ) - _UPDATEWORKERVERSIONINGRULESREQUEST_REPLACEBUILDIDASSIGNMENTRULE._serialized_start = 28142 + _UPDATEWORKERVERSIONINGRULESREQUEST_REPLACEBUILDIDASSIGNMENTRULE._serialized_start = 28352 _UPDATEWORKERVERSIONINGRULESREQUEST_REPLACEBUILDIDASSIGNMENTRULE._serialized_end = ( - 28271 + 28481 ) - _UPDATEWORKERVERSIONINGRULESREQUEST_DELETEBUILDIDASSIGNMENTRULE._serialized_start = 28273 + _UPDATEWORKERVERSIONINGRULESREQUEST_DELETEBUILDIDASSIGNMENTRULE._serialized_start = 28483 _UPDATEWORKERVERSIONINGRULESREQUEST_DELETEBUILDIDASSIGNMENTRULE._serialized_end = ( - 28337 + 28547 ) - _UPDATEWORKERVERSIONINGRULESREQUEST_ADDCOMPATIBLEBUILDIDREDIRECTRULE._serialized_start = 28339 - _UPDATEWORKERVERSIONINGRULESREQUEST_ADDCOMPATIBLEBUILDIDREDIRECTRULE._serialized_end = 28445 - _UPDATEWORKERVERSIONINGRULESREQUEST_REPLACECOMPATIBLEBUILDIDREDIRECTRULE._serialized_start = 28447 - _UPDATEWORKERVERSIONINGRULESREQUEST_REPLACECOMPATIBLEBUILDIDREDIRECTRULE._serialized_end = 28557 - _UPDATEWORKERVERSIONINGRULESREQUEST_DELETECOMPATIBLEBUILDIDREDIRECTRULE._serialized_start = 28559 - _UPDATEWORKERVERSIONINGRULESREQUEST_DELETECOMPATIBLEBUILDIDREDIRECTRULE._serialized_end = 28621 - _UPDATEWORKERVERSIONINGRULESREQUEST_COMMITBUILDID._serialized_start = 28623 - _UPDATEWORKERVERSIONINGRULESREQUEST_COMMITBUILDID._serialized_end = 28678 - _UPDATEWORKERVERSIONINGRULESRESPONSE._serialized_start = 28694 - _UPDATEWORKERVERSIONINGRULESRESPONSE._serialized_end = 28946 - _GETWORKERVERSIONINGRULESREQUEST._serialized_start = 28948 - _GETWORKERVERSIONINGRULESREQUEST._serialized_end = 29020 - _GETWORKERVERSIONINGRULESRESPONSE._serialized_start = 29023 - _GETWORKERVERSIONINGRULESRESPONSE._serialized_end = 29272 - _GETWORKERTASKREACHABILITYREQUEST._serialized_start = 29275 - _GETWORKERTASKREACHABILITYREQUEST._serialized_end = 29431 - _GETWORKERTASKREACHABILITYRESPONSE._serialized_start = 29433 - _GETWORKERTASKREACHABILITYRESPONSE._serialized_end = 29547 - _UPDATEWORKFLOWEXECUTIONREQUEST._serialized_start = 29550 - _UPDATEWORKFLOWEXECUTIONREQUEST._serialized_end = 29811 - _UPDATEWORKFLOWEXECUTIONRESPONSE._serialized_start = 29814 - _UPDATEWORKFLOWEXECUTIONRESPONSE._serialized_end = 30029 - _STARTBATCHOPERATIONREQUEST._serialized_start = 30032 - _STARTBATCHOPERATIONREQUEST._serialized_end = 31044 - _STARTBATCHOPERATIONRESPONSE._serialized_start = 31046 - _STARTBATCHOPERATIONRESPONSE._serialized_end = 31075 - _STOPBATCHOPERATIONREQUEST._serialized_start = 31077 - _STOPBATCHOPERATIONREQUEST._serialized_end = 31173 - _STOPBATCHOPERATIONRESPONSE._serialized_start = 31175 - _STOPBATCHOPERATIONRESPONSE._serialized_end = 31203 - _DESCRIBEBATCHOPERATIONREQUEST._serialized_start = 31205 - _DESCRIBEBATCHOPERATIONREQUEST._serialized_end = 31271 - _DESCRIBEBATCHOPERATIONRESPONSE._serialized_start = 31274 - _DESCRIBEBATCHOPERATIONRESPONSE._serialized_end = 31676 - _LISTBATCHOPERATIONSREQUEST._serialized_start = 31678 - _LISTBATCHOPERATIONSREQUEST._serialized_end = 31769 - _LISTBATCHOPERATIONSRESPONSE._serialized_start = 31771 - _LISTBATCHOPERATIONSRESPONSE._serialized_end = 31892 - _POLLWORKFLOWEXECUTIONUPDATEREQUEST._serialized_start = 31895 - _POLLWORKFLOWEXECUTIONUPDATEREQUEST._serialized_end = 32080 - _POLLWORKFLOWEXECUTIONUPDATERESPONSE._serialized_start = 32083 - _POLLWORKFLOWEXECUTIONUPDATERESPONSE._serialized_end = 32302 - _POLLNEXUSTASKQUEUEREQUEST._serialized_start = 32305 - _POLLNEXUSTASKQUEUEREQUEST._serialized_end = 32696 - _POLLNEXUSTASKQUEUERESPONSE._serialized_start = 32699 - _POLLNEXUSTASKQUEUERESPONSE._serialized_end = 32879 - _RESPONDNEXUSTASKCOMPLETEDREQUEST._serialized_start = 32882 - _RESPONDNEXUSTASKCOMPLETEDREQUEST._serialized_end = 33024 - _RESPONDNEXUSTASKCOMPLETEDRESPONSE._serialized_start = 33026 - _RESPONDNEXUSTASKCOMPLETEDRESPONSE._serialized_end = 33061 - _RESPONDNEXUSTASKFAILEDREQUEST._serialized_start = 33064 - _RESPONDNEXUSTASKFAILEDREQUEST._serialized_end = 33259 - _RESPONDNEXUSTASKFAILEDRESPONSE._serialized_start = 33261 - _RESPONDNEXUSTASKFAILEDRESPONSE._serialized_end = 33293 - _EXECUTEMULTIOPERATIONREQUEST._serialized_start = 33296 - _EXECUTEMULTIOPERATIONREQUEST._serialized_end = 33647 - _EXECUTEMULTIOPERATIONREQUEST_OPERATION._serialized_start = 33441 - _EXECUTEMULTIOPERATIONREQUEST_OPERATION._serialized_end = 33647 - _EXECUTEMULTIOPERATIONRESPONSE._serialized_start = 33650 - _EXECUTEMULTIOPERATIONRESPONSE._serialized_end = 33982 - _EXECUTEMULTIOPERATIONRESPONSE_RESPONSE._serialized_start = 33776 - _EXECUTEMULTIOPERATIONRESPONSE_RESPONSE._serialized_end = 33982 - _UPDATEACTIVITYOPTIONSREQUEST._serialized_start = 33985 - _UPDATEACTIVITYOPTIONSREQUEST._serialized_end = 34321 - _UPDATEACTIVITYOPTIONSRESPONSE._serialized_start = 34323 - _UPDATEACTIVITYOPTIONSRESPONSE._serialized_end = 34423 - _PAUSEACTIVITYREQUEST._serialized_start = 34426 - _PAUSEACTIVITYREQUEST._serialized_end = 34605 - _PAUSEACTIVITYRESPONSE._serialized_start = 34607 - _PAUSEACTIVITYRESPONSE._serialized_end = 34630 - _UNPAUSEACTIVITYREQUEST._serialized_start = 34633 - _UNPAUSEACTIVITYREQUEST._serialized_end = 34913 - _UNPAUSEACTIVITYRESPONSE._serialized_start = 34915 - _UNPAUSEACTIVITYRESPONSE._serialized_end = 34940 - _RESETACTIVITYREQUEST._serialized_start = 34943 - _RESETACTIVITYREQUEST._serialized_end = 35250 - _RESETACTIVITYRESPONSE._serialized_start = 35252 - _RESETACTIVITYRESPONSE._serialized_end = 35275 - _UPDATEWORKFLOWEXECUTIONOPTIONSREQUEST._serialized_start = 35278 - _UPDATEWORKFLOWEXECUTIONOPTIONSREQUEST._serialized_end = 35562 - _UPDATEWORKFLOWEXECUTIONOPTIONSRESPONSE._serialized_start = 35565 - _UPDATEWORKFLOWEXECUTIONOPTIONSRESPONSE._serialized_end = 35693 - _DESCRIBEDEPLOYMENTREQUEST._serialized_start = 35695 - _DESCRIBEDEPLOYMENTREQUEST._serialized_end = 35801 - _DESCRIBEDEPLOYMENTRESPONSE._serialized_start = 35803 - _DESCRIBEDEPLOYMENTRESPONSE._serialized_end = 35900 - _DESCRIBEWORKERDEPLOYMENTVERSIONREQUEST._serialized_start = 35903 - _DESCRIBEWORKERDEPLOYMENTVERSIONREQUEST._serialized_end = 36097 - _DESCRIBEWORKERDEPLOYMENTVERSIONRESPONSE._serialized_start = 36100 - _DESCRIBEWORKERDEPLOYMENTVERSIONRESPONSE._serialized_end = 36752 - _DESCRIBEWORKERDEPLOYMENTVERSIONRESPONSE_VERSIONTASKQUEUE._serialized_start = 36361 - _DESCRIBEWORKERDEPLOYMENTVERSIONRESPONSE_VERSIONTASKQUEUE._serialized_end = 36752 - _DESCRIBEWORKERDEPLOYMENTVERSIONRESPONSE_VERSIONTASKQUEUE_STATSBYPRIORITYKEYENTRY._serialized_start = 22307 - _DESCRIBEWORKERDEPLOYMENTVERSIONRESPONSE_VERSIONTASKQUEUE_STATSBYPRIORITYKEYENTRY._serialized_end = 22407 - _DESCRIBEWORKERDEPLOYMENTREQUEST._serialized_start = 36754 - _DESCRIBEWORKERDEPLOYMENTREQUEST._serialized_end = 36831 - _DESCRIBEWORKERDEPLOYMENTRESPONSE._serialized_start = 36834 - _DESCRIBEWORKERDEPLOYMENTRESPONSE._serialized_end = 36974 - _LISTDEPLOYMENTSREQUEST._serialized_start = 36976 - _LISTDEPLOYMENTSREQUEST._serialized_end = 37084 - _LISTDEPLOYMENTSRESPONSE._serialized_start = 37086 - _LISTDEPLOYMENTSRESPONSE._serialized_end = 37205 - _SETCURRENTDEPLOYMENTREQUEST._serialized_start = 37208 - _SETCURRENTDEPLOYMENTREQUEST._serialized_end = 37413 - _SETCURRENTDEPLOYMENTRESPONSE._serialized_start = 37416 - _SETCURRENTDEPLOYMENTRESPONSE._serialized_end = 37601 - _SETWORKERDEPLOYMENTCURRENTVERSIONREQUEST._serialized_start = 37604 - _SETWORKERDEPLOYMENTCURRENTVERSIONREQUEST._serialized_end = 37833 - _SETWORKERDEPLOYMENTCURRENTVERSIONRESPONSE._serialized_start = 37836 - _SETWORKERDEPLOYMENTCURRENTVERSIONRESPONSE._serialized_end = 38027 - _SETWORKERDEPLOYMENTRAMPINGVERSIONREQUEST._serialized_start = 38030 - _SETWORKERDEPLOYMENTRAMPINGVERSIONREQUEST._serialized_end = 38279 - _SETWORKERDEPLOYMENTRAMPINGVERSIONRESPONSE._serialized_start = 38282 - _SETWORKERDEPLOYMENTRAMPINGVERSIONRESPONSE._serialized_end = 38506 - _LISTWORKERDEPLOYMENTSREQUEST._serialized_start = 38508 - _LISTWORKERDEPLOYMENTSREQUEST._serialized_end = 38601 - _LISTWORKERDEPLOYMENTSRESPONSE._serialized_start = 38604 - _LISTWORKERDEPLOYMENTSRESPONSE._serialized_end = 39275 - _LISTWORKERDEPLOYMENTSRESPONSE_WORKERDEPLOYMENTSUMMARY._serialized_start = 38779 - _LISTWORKERDEPLOYMENTSRESPONSE_WORKERDEPLOYMENTSUMMARY._serialized_end = 39275 - _DELETEWORKERDEPLOYMENTVERSIONREQUEST._serialized_start = 39278 - _DELETEWORKERDEPLOYMENTVERSIONREQUEST._serialized_end = 39478 - _DELETEWORKERDEPLOYMENTVERSIONRESPONSE._serialized_start = 39480 - _DELETEWORKERDEPLOYMENTVERSIONRESPONSE._serialized_end = 39519 - _DELETEWORKERDEPLOYMENTREQUEST._serialized_start = 39521 - _DELETEWORKERDEPLOYMENTREQUEST._serialized_end = 39614 - _DELETEWORKERDEPLOYMENTRESPONSE._serialized_start = 39616 - _DELETEWORKERDEPLOYMENTRESPONSE._serialized_end = 39648 - _UPDATEWORKERDEPLOYMENTVERSIONMETADATAREQUEST._serialized_start = 39651 - _UPDATEWORKERDEPLOYMENTVERSIONMETADATAREQUEST._serialized_end = 40069 - _UPDATEWORKERDEPLOYMENTVERSIONMETADATAREQUEST_UPSERTENTRIESENTRY._serialized_start = 39984 + _UPDATEWORKERVERSIONINGRULESREQUEST_ADDCOMPATIBLEBUILDIDREDIRECTRULE._serialized_start = 28549 + _UPDATEWORKERVERSIONINGRULESREQUEST_ADDCOMPATIBLEBUILDIDREDIRECTRULE._serialized_end = 28655 + _UPDATEWORKERVERSIONINGRULESREQUEST_REPLACECOMPATIBLEBUILDIDREDIRECTRULE._serialized_start = 28657 + _UPDATEWORKERVERSIONINGRULESREQUEST_REPLACECOMPATIBLEBUILDIDREDIRECTRULE._serialized_end = 28767 + _UPDATEWORKERVERSIONINGRULESREQUEST_DELETECOMPATIBLEBUILDIDREDIRECTRULE._serialized_start = 28769 + _UPDATEWORKERVERSIONINGRULESREQUEST_DELETECOMPATIBLEBUILDIDREDIRECTRULE._serialized_end = 28831 + _UPDATEWORKERVERSIONINGRULESREQUEST_COMMITBUILDID._serialized_start = 28833 + _UPDATEWORKERVERSIONINGRULESREQUEST_COMMITBUILDID._serialized_end = 28888 + _UPDATEWORKERVERSIONINGRULESRESPONSE._serialized_start = 28904 + _UPDATEWORKERVERSIONINGRULESRESPONSE._serialized_end = 29156 + _GETWORKERVERSIONINGRULESREQUEST._serialized_start = 29158 + _GETWORKERVERSIONINGRULESREQUEST._serialized_end = 29230 + _GETWORKERVERSIONINGRULESRESPONSE._serialized_start = 29233 + _GETWORKERVERSIONINGRULESRESPONSE._serialized_end = 29482 + _GETWORKERTASKREACHABILITYREQUEST._serialized_start = 29485 + _GETWORKERTASKREACHABILITYREQUEST._serialized_end = 29641 + _GETWORKERTASKREACHABILITYRESPONSE._serialized_start = 29643 + _GETWORKERTASKREACHABILITYRESPONSE._serialized_end = 29757 + _UPDATEWORKFLOWEXECUTIONREQUEST._serialized_start = 29760 + _UPDATEWORKFLOWEXECUTIONREQUEST._serialized_end = 30021 + _UPDATEWORKFLOWEXECUTIONRESPONSE._serialized_start = 30024 + _UPDATEWORKFLOWEXECUTIONRESPONSE._serialized_end = 30239 + _STARTBATCHOPERATIONREQUEST._serialized_start = 30242 + _STARTBATCHOPERATIONREQUEST._serialized_end = 31254 + _STARTBATCHOPERATIONRESPONSE._serialized_start = 31256 + _STARTBATCHOPERATIONRESPONSE._serialized_end = 31285 + _STOPBATCHOPERATIONREQUEST._serialized_start = 31287 + _STOPBATCHOPERATIONREQUEST._serialized_end = 31383 + _STOPBATCHOPERATIONRESPONSE._serialized_start = 31385 + _STOPBATCHOPERATIONRESPONSE._serialized_end = 31413 + _DESCRIBEBATCHOPERATIONREQUEST._serialized_start = 31415 + _DESCRIBEBATCHOPERATIONREQUEST._serialized_end = 31481 + _DESCRIBEBATCHOPERATIONRESPONSE._serialized_start = 31484 + _DESCRIBEBATCHOPERATIONRESPONSE._serialized_end = 31886 + _LISTBATCHOPERATIONSREQUEST._serialized_start = 31888 + _LISTBATCHOPERATIONSREQUEST._serialized_end = 31979 + _LISTBATCHOPERATIONSRESPONSE._serialized_start = 31981 + _LISTBATCHOPERATIONSRESPONSE._serialized_end = 32102 + _POLLWORKFLOWEXECUTIONUPDATEREQUEST._serialized_start = 32105 + _POLLWORKFLOWEXECUTIONUPDATEREQUEST._serialized_end = 32290 + _POLLWORKFLOWEXECUTIONUPDATERESPONSE._serialized_start = 32293 + _POLLWORKFLOWEXECUTIONUPDATERESPONSE._serialized_end = 32512 + _POLLNEXUSTASKQUEUEREQUEST._serialized_start = 32515 + _POLLNEXUSTASKQUEUEREQUEST._serialized_end = 32906 + _POLLNEXUSTASKQUEUERESPONSE._serialized_start = 32909 + _POLLNEXUSTASKQUEUERESPONSE._serialized_end = 33089 + _RESPONDNEXUSTASKCOMPLETEDREQUEST._serialized_start = 33092 + _RESPONDNEXUSTASKCOMPLETEDREQUEST._serialized_end = 33234 + _RESPONDNEXUSTASKCOMPLETEDRESPONSE._serialized_start = 33236 + _RESPONDNEXUSTASKCOMPLETEDRESPONSE._serialized_end = 33271 + _RESPONDNEXUSTASKFAILEDREQUEST._serialized_start = 33274 + _RESPONDNEXUSTASKFAILEDREQUEST._serialized_end = 33469 + _RESPONDNEXUSTASKFAILEDRESPONSE._serialized_start = 33471 + _RESPONDNEXUSTASKFAILEDRESPONSE._serialized_end = 33503 + _EXECUTEMULTIOPERATIONREQUEST._serialized_start = 33506 + _EXECUTEMULTIOPERATIONREQUEST._serialized_end = 33878 + _EXECUTEMULTIOPERATIONREQUEST_OPERATION._serialized_start = 33672 + _EXECUTEMULTIOPERATIONREQUEST_OPERATION._serialized_end = 33878 + _EXECUTEMULTIOPERATIONRESPONSE._serialized_start = 33881 + _EXECUTEMULTIOPERATIONRESPONSE._serialized_end = 34213 + _EXECUTEMULTIOPERATIONRESPONSE_RESPONSE._serialized_start = 34007 + _EXECUTEMULTIOPERATIONRESPONSE_RESPONSE._serialized_end = 34213 + _UPDATEACTIVITYOPTIONSREQUEST._serialized_start = 34216 + _UPDATEACTIVITYOPTIONSREQUEST._serialized_end = 34552 + _UPDATEACTIVITYOPTIONSRESPONSE._serialized_start = 34554 + _UPDATEACTIVITYOPTIONSRESPONSE._serialized_end = 34654 + _PAUSEACTIVITYREQUEST._serialized_start = 34657 + _PAUSEACTIVITYREQUEST._serialized_end = 34836 + _PAUSEACTIVITYRESPONSE._serialized_start = 34838 + _PAUSEACTIVITYRESPONSE._serialized_end = 34861 + _UNPAUSEACTIVITYREQUEST._serialized_start = 34864 + _UNPAUSEACTIVITYREQUEST._serialized_end = 35144 + _UNPAUSEACTIVITYRESPONSE._serialized_start = 35146 + _UNPAUSEACTIVITYRESPONSE._serialized_end = 35171 + _RESETACTIVITYREQUEST._serialized_start = 35174 + _RESETACTIVITYREQUEST._serialized_end = 35481 + _RESETACTIVITYRESPONSE._serialized_start = 35483 + _RESETACTIVITYRESPONSE._serialized_end = 35506 + _UPDATEWORKFLOWEXECUTIONOPTIONSREQUEST._serialized_start = 35509 + _UPDATEWORKFLOWEXECUTIONOPTIONSREQUEST._serialized_end = 35793 + _UPDATEWORKFLOWEXECUTIONOPTIONSRESPONSE._serialized_start = 35796 + _UPDATEWORKFLOWEXECUTIONOPTIONSRESPONSE._serialized_end = 35924 + _DESCRIBEDEPLOYMENTREQUEST._serialized_start = 35926 + _DESCRIBEDEPLOYMENTREQUEST._serialized_end = 36032 + _DESCRIBEDEPLOYMENTRESPONSE._serialized_start = 36034 + _DESCRIBEDEPLOYMENTRESPONSE._serialized_end = 36131 + _DESCRIBEWORKERDEPLOYMENTVERSIONREQUEST._serialized_start = 36134 + _DESCRIBEWORKERDEPLOYMENTVERSIONREQUEST._serialized_end = 36328 + _DESCRIBEWORKERDEPLOYMENTVERSIONRESPONSE._serialized_start = 36331 + _DESCRIBEWORKERDEPLOYMENTVERSIONRESPONSE._serialized_end = 36983 + _DESCRIBEWORKERDEPLOYMENTVERSIONRESPONSE_VERSIONTASKQUEUE._serialized_start = 36592 + _DESCRIBEWORKERDEPLOYMENTVERSIONRESPONSE_VERSIONTASKQUEUE._serialized_end = 36983 + _DESCRIBEWORKERDEPLOYMENTVERSIONRESPONSE_VERSIONTASKQUEUE_STATSBYPRIORITYKEYENTRY._serialized_start = 22517 + _DESCRIBEWORKERDEPLOYMENTVERSIONRESPONSE_VERSIONTASKQUEUE_STATSBYPRIORITYKEYENTRY._serialized_end = 22617 + _DESCRIBEWORKERDEPLOYMENTREQUEST._serialized_start = 36985 + _DESCRIBEWORKERDEPLOYMENTREQUEST._serialized_end = 37062 + _DESCRIBEWORKERDEPLOYMENTRESPONSE._serialized_start = 37065 + _DESCRIBEWORKERDEPLOYMENTRESPONSE._serialized_end = 37205 + _LISTDEPLOYMENTSREQUEST._serialized_start = 37207 + _LISTDEPLOYMENTSREQUEST._serialized_end = 37315 + _LISTDEPLOYMENTSRESPONSE._serialized_start = 37317 + _LISTDEPLOYMENTSRESPONSE._serialized_end = 37436 + _SETCURRENTDEPLOYMENTREQUEST._serialized_start = 37439 + _SETCURRENTDEPLOYMENTREQUEST._serialized_end = 37644 + _SETCURRENTDEPLOYMENTRESPONSE._serialized_start = 37647 + _SETCURRENTDEPLOYMENTRESPONSE._serialized_end = 37832 + _SETWORKERDEPLOYMENTCURRENTVERSIONREQUEST._serialized_start = 37835 + _SETWORKERDEPLOYMENTCURRENTVERSIONREQUEST._serialized_end = 38064 + _SETWORKERDEPLOYMENTCURRENTVERSIONRESPONSE._serialized_start = 38067 + _SETWORKERDEPLOYMENTCURRENTVERSIONRESPONSE._serialized_end = 38258 + _SETWORKERDEPLOYMENTRAMPINGVERSIONREQUEST._serialized_start = 38261 + _SETWORKERDEPLOYMENTRAMPINGVERSIONREQUEST._serialized_end = 38510 + _SETWORKERDEPLOYMENTRAMPINGVERSIONRESPONSE._serialized_start = 38513 + _SETWORKERDEPLOYMENTRAMPINGVERSIONRESPONSE._serialized_end = 38737 + _LISTWORKERDEPLOYMENTSREQUEST._serialized_start = 38739 + _LISTWORKERDEPLOYMENTSREQUEST._serialized_end = 38832 + _LISTWORKERDEPLOYMENTSRESPONSE._serialized_start = 38835 + _LISTWORKERDEPLOYMENTSRESPONSE._serialized_end = 39506 + _LISTWORKERDEPLOYMENTSRESPONSE_WORKERDEPLOYMENTSUMMARY._serialized_start = 39010 + _LISTWORKERDEPLOYMENTSRESPONSE_WORKERDEPLOYMENTSUMMARY._serialized_end = 39506 + _DELETEWORKERDEPLOYMENTVERSIONREQUEST._serialized_start = 39509 + _DELETEWORKERDEPLOYMENTVERSIONREQUEST._serialized_end = 39709 + _DELETEWORKERDEPLOYMENTVERSIONRESPONSE._serialized_start = 39711 + _DELETEWORKERDEPLOYMENTVERSIONRESPONSE._serialized_end = 39750 + _DELETEWORKERDEPLOYMENTREQUEST._serialized_start = 39752 + _DELETEWORKERDEPLOYMENTREQUEST._serialized_end = 39845 + _DELETEWORKERDEPLOYMENTRESPONSE._serialized_start = 39847 + _DELETEWORKERDEPLOYMENTRESPONSE._serialized_end = 39879 + _UPDATEWORKERDEPLOYMENTVERSIONMETADATAREQUEST._serialized_start = 39882 + _UPDATEWORKERDEPLOYMENTVERSIONMETADATAREQUEST._serialized_end = 40300 + _UPDATEWORKERDEPLOYMENTVERSIONMETADATAREQUEST_UPSERTENTRIESENTRY._serialized_start = 40215 _UPDATEWORKERDEPLOYMENTVERSIONMETADATAREQUEST_UPSERTENTRIESENTRY._serialized_end = ( - 40069 + 40300 ) - _UPDATEWORKERDEPLOYMENTVERSIONMETADATARESPONSE._serialized_start = 40071 - _UPDATEWORKERDEPLOYMENTVERSIONMETADATARESPONSE._serialized_end = 40181 - _SETWORKERDEPLOYMENTMANAGERREQUEST._serialized_start = 40184 - _SETWORKERDEPLOYMENTMANAGERREQUEST._serialized_end = 40373 - _SETWORKERDEPLOYMENTMANAGERRESPONSE._serialized_start = 40375 - _SETWORKERDEPLOYMENTMANAGERRESPONSE._serialized_end = 40474 - _GETCURRENTDEPLOYMENTREQUEST._serialized_start = 40476 - _GETCURRENTDEPLOYMENTREQUEST._serialized_end = 40545 - _GETCURRENTDEPLOYMENTRESPONSE._serialized_start = 40547 - _GETCURRENTDEPLOYMENTRESPONSE._serialized_end = 40654 - _GETDEPLOYMENTREACHABILITYREQUEST._serialized_start = 40656 - _GETDEPLOYMENTREACHABILITYREQUEST._serialized_end = 40769 - _GETDEPLOYMENTREACHABILITYRESPONSE._serialized_start = 40772 - _GETDEPLOYMENTREACHABILITYRESPONSE._serialized_end = 40999 - _CREATEWORKFLOWRULEREQUEST._serialized_start = 41002 - _CREATEWORKFLOWRULEREQUEST._serialized_end = 41182 - _CREATEWORKFLOWRULERESPONSE._serialized_start = 41184 - _CREATEWORKFLOWRULERESPONSE._serialized_end = 41279 - _DESCRIBEWORKFLOWRULEREQUEST._serialized_start = 41281 - _DESCRIBEWORKFLOWRULEREQUEST._serialized_end = 41346 - _DESCRIBEWORKFLOWRULERESPONSE._serialized_start = 41348 - _DESCRIBEWORKFLOWRULERESPONSE._serialized_end = 41429 - _DELETEWORKFLOWRULEREQUEST._serialized_start = 41431 - _DELETEWORKFLOWRULEREQUEST._serialized_end = 41494 - _DELETEWORKFLOWRULERESPONSE._serialized_start = 41496 - _DELETEWORKFLOWRULERESPONSE._serialized_end = 41524 - _LISTWORKFLOWRULESREQUEST._serialized_start = 41526 - _LISTWORKFLOWRULESREQUEST._serialized_end = 41596 - _LISTWORKFLOWRULESRESPONSE._serialized_start = 41598 - _LISTWORKFLOWRULESRESPONSE._serialized_end = 41702 - _TRIGGERWORKFLOWRULEREQUEST._serialized_start = 41705 - _TRIGGERWORKFLOWRULEREQUEST._serialized_end = 41911 - _TRIGGERWORKFLOWRULERESPONSE._serialized_start = 41913 - _TRIGGERWORKFLOWRULERESPONSE._serialized_end = 41959 - _RECORDWORKERHEARTBEATREQUEST._serialized_start = 41962 - _RECORDWORKERHEARTBEATREQUEST._serialized_end = 42096 - _RECORDWORKERHEARTBEATRESPONSE._serialized_start = 42098 - _RECORDWORKERHEARTBEATRESPONSE._serialized_end = 42129 - _LISTWORKERSREQUEST._serialized_start = 42131 - _LISTWORKERSREQUEST._serialized_end = 42229 - _LISTWORKERSRESPONSE._serialized_start = 42232 - _LISTWORKERSRESPONSE._serialized_end = 42397 - _UPDATETASKQUEUECONFIGREQUEST._serialized_start = 42400 - _UPDATETASKQUEUECONFIGREQUEST._serialized_end = 43125 - _UPDATETASKQUEUECONFIGREQUEST_RATELIMITUPDATE._serialized_start = 42967 - _UPDATETASKQUEUECONFIGREQUEST_RATELIMITUPDATE._serialized_end = 43058 + _UPDATEWORKERDEPLOYMENTVERSIONMETADATARESPONSE._serialized_start = 40302 + _UPDATEWORKERDEPLOYMENTVERSIONMETADATARESPONSE._serialized_end = 40412 + _SETWORKERDEPLOYMENTMANAGERREQUEST._serialized_start = 40415 + _SETWORKERDEPLOYMENTMANAGERREQUEST._serialized_end = 40604 + _SETWORKERDEPLOYMENTMANAGERRESPONSE._serialized_start = 40606 + _SETWORKERDEPLOYMENTMANAGERRESPONSE._serialized_end = 40705 + _GETCURRENTDEPLOYMENTREQUEST._serialized_start = 40707 + _GETCURRENTDEPLOYMENTREQUEST._serialized_end = 40776 + _GETCURRENTDEPLOYMENTRESPONSE._serialized_start = 40778 + _GETCURRENTDEPLOYMENTRESPONSE._serialized_end = 40885 + _GETDEPLOYMENTREACHABILITYREQUEST._serialized_start = 40887 + _GETDEPLOYMENTREACHABILITYREQUEST._serialized_end = 41000 + _GETDEPLOYMENTREACHABILITYRESPONSE._serialized_start = 41003 + _GETDEPLOYMENTREACHABILITYRESPONSE._serialized_end = 41230 + _CREATEWORKFLOWRULEREQUEST._serialized_start = 41233 + _CREATEWORKFLOWRULEREQUEST._serialized_end = 41413 + _CREATEWORKFLOWRULERESPONSE._serialized_start = 41415 + _CREATEWORKFLOWRULERESPONSE._serialized_end = 41510 + _DESCRIBEWORKFLOWRULEREQUEST._serialized_start = 41512 + _DESCRIBEWORKFLOWRULEREQUEST._serialized_end = 41577 + _DESCRIBEWORKFLOWRULERESPONSE._serialized_start = 41579 + _DESCRIBEWORKFLOWRULERESPONSE._serialized_end = 41660 + _DELETEWORKFLOWRULEREQUEST._serialized_start = 41662 + _DELETEWORKFLOWRULEREQUEST._serialized_end = 41725 + _DELETEWORKFLOWRULERESPONSE._serialized_start = 41727 + _DELETEWORKFLOWRULERESPONSE._serialized_end = 41755 + _LISTWORKFLOWRULESREQUEST._serialized_start = 41757 + _LISTWORKFLOWRULESREQUEST._serialized_end = 41827 + _LISTWORKFLOWRULESRESPONSE._serialized_start = 41829 + _LISTWORKFLOWRULESRESPONSE._serialized_end = 41933 + _TRIGGERWORKFLOWRULEREQUEST._serialized_start = 41936 + _TRIGGERWORKFLOWRULEREQUEST._serialized_end = 42142 + _TRIGGERWORKFLOWRULERESPONSE._serialized_start = 42144 + _TRIGGERWORKFLOWRULERESPONSE._serialized_end = 42190 + _RECORDWORKERHEARTBEATREQUEST._serialized_start = 42193 + _RECORDWORKERHEARTBEATREQUEST._serialized_end = 42348 + _RECORDWORKERHEARTBEATRESPONSE._serialized_start = 42350 + _RECORDWORKERHEARTBEATRESPONSE._serialized_end = 42381 + _LISTWORKERSREQUEST._serialized_start = 42383 + _LISTWORKERSREQUEST._serialized_end = 42481 + _LISTWORKERSRESPONSE._serialized_start = 42484 + _LISTWORKERSRESPONSE._serialized_end = 42649 + _UPDATETASKQUEUECONFIGREQUEST._serialized_start = 42652 + _UPDATETASKQUEUECONFIGREQUEST._serialized_end = 43377 + _UPDATETASKQUEUECONFIGREQUEST_RATELIMITUPDATE._serialized_start = 43219 + _UPDATETASKQUEUECONFIGREQUEST_RATELIMITUPDATE._serialized_end = 43310 _UPDATETASKQUEUECONFIGREQUEST_SETFAIRNESSWEIGHTOVERRIDESENTRY._serialized_start = ( - 43060 + 43312 ) _UPDATETASKQUEUECONFIGREQUEST_SETFAIRNESSWEIGHTOVERRIDESENTRY._serialized_end = ( - 43125 + 43377 ) - _UPDATETASKQUEUECONFIGRESPONSE._serialized_start = 43127 - _UPDATETASKQUEUECONFIGRESPONSE._serialized_end = 43218 - _FETCHWORKERCONFIGREQUEST._serialized_start = 43221 - _FETCHWORKERCONFIGREQUEST._serialized_end = 43358 - _FETCHWORKERCONFIGRESPONSE._serialized_start = 43360 - _FETCHWORKERCONFIGRESPONSE._serialized_end = 43445 - _UPDATEWORKERCONFIGREQUEST._serialized_start = 43448 - _UPDATEWORKERCONFIGREQUEST._serialized_end = 43693 - _UPDATEWORKERCONFIGRESPONSE._serialized_start = 43695 - _UPDATEWORKERCONFIGRESPONSE._serialized_end = 43795 - _DESCRIBEWORKERREQUEST._serialized_start = 43797 - _DESCRIBEWORKERREQUEST._serialized_end = 43868 - _DESCRIBEWORKERRESPONSE._serialized_start = 43870 - _DESCRIBEWORKERRESPONSE._serialized_end = 43951 - _PAUSEWORKFLOWEXECUTIONREQUEST._serialized_start = 43954 - _PAUSEWORKFLOWEXECUTIONREQUEST._serialized_end = 44095 - _PAUSEWORKFLOWEXECUTIONRESPONSE._serialized_start = 44097 - _PAUSEWORKFLOWEXECUTIONRESPONSE._serialized_end = 44129 - _UNPAUSEWORKFLOWEXECUTIONREQUEST._serialized_start = 44132 - _UNPAUSEWORKFLOWEXECUTIONREQUEST._serialized_end = 44275 - _UNPAUSEWORKFLOWEXECUTIONRESPONSE._serialized_start = 44277 - _UNPAUSEWORKFLOWEXECUTIONRESPONSE._serialized_end = 44311 - _STARTACTIVITYEXECUTIONREQUEST._serialized_start = 44314 - _STARTACTIVITYEXECUTIONREQUEST._serialized_end = 45262 - _STARTACTIVITYEXECUTIONRESPONSE._serialized_start = 45264 - _STARTACTIVITYEXECUTIONRESPONSE._serialized_end = 45329 - _DESCRIBEACTIVITYEXECUTIONREQUEST._serialized_start = 45332 - _DESCRIBEACTIVITYEXECUTIONREQUEST._serialized_end = 45495 - _DESCRIBEACTIVITYEXECUTIONRESPONSE._serialized_start = 45498 - _DESCRIBEACTIVITYEXECUTIONRESPONSE._serialized_end = 45755 - _POLLACTIVITYEXECUTIONREQUEST._serialized_start = 45757 - _POLLACTIVITYEXECUTIONREQUEST._serialized_end = 45843 - _POLLACTIVITYEXECUTIONRESPONSE._serialized_start = 45845 - _POLLACTIVITYEXECUTIONRESPONSE._serialized_end = 45961 - _LISTACTIVITYEXECUTIONSREQUEST._serialized_start = 45963 - _LISTACTIVITYEXECUTIONSREQUEST._serialized_end = 46072 - _LISTACTIVITYEXECUTIONSRESPONSE._serialized_start = 46075 - _LISTACTIVITYEXECUTIONSRESPONSE._serialized_end = 46205 - _COUNTACTIVITYEXECUTIONSREQUEST._serialized_start = 46207 - _COUNTACTIVITYEXECUTIONSREQUEST._serialized_end = 46273 - _COUNTACTIVITYEXECUTIONSRESPONSE._serialized_start = 46276 - _COUNTACTIVITYEXECUTIONSRESPONSE._serialized_end = 46513 - _COUNTACTIVITYEXECUTIONSRESPONSE_AGGREGATIONGROUP._serialized_start = 18770 - _COUNTACTIVITYEXECUTIONSRESPONSE_AGGREGATIONGROUP._serialized_end = 18858 - _REQUESTCANCELACTIVITYEXECUTIONREQUEST._serialized_start = 46516 - _REQUESTCANCELACTIVITYEXECUTIONREQUEST._serialized_end = 46665 - _REQUESTCANCELACTIVITYEXECUTIONRESPONSE._serialized_start = 46667 - _REQUESTCANCELACTIVITYEXECUTIONRESPONSE._serialized_end = 46707 - _TERMINATEACTIVITYEXECUTIONREQUEST._serialized_start = 46710 - _TERMINATEACTIVITYEXECUTIONREQUEST._serialized_end = 46855 - _TERMINATEACTIVITYEXECUTIONRESPONSE._serialized_start = 46857 - _TERMINATEACTIVITYEXECUTIONRESPONSE._serialized_end = 46893 - _DELETEACTIVITYEXECUTIONREQUEST._serialized_start = 46895 - _DELETEACTIVITYEXECUTIONREQUEST._serialized_end = 46983 - _DELETEACTIVITYEXECUTIONRESPONSE._serialized_start = 46985 - _DELETEACTIVITYEXECUTIONRESPONSE._serialized_end = 47018 + _UPDATETASKQUEUECONFIGRESPONSE._serialized_start = 43379 + _UPDATETASKQUEUECONFIGRESPONSE._serialized_end = 43470 + _FETCHWORKERCONFIGREQUEST._serialized_start = 43473 + _FETCHWORKERCONFIGREQUEST._serialized_end = 43631 + _FETCHWORKERCONFIGRESPONSE._serialized_start = 43633 + _FETCHWORKERCONFIGRESPONSE._serialized_end = 43718 + _UPDATEWORKERCONFIGREQUEST._serialized_start = 43721 + _UPDATEWORKERCONFIGREQUEST._serialized_end = 43987 + _UPDATEWORKERCONFIGRESPONSE._serialized_start = 43989 + _UPDATEWORKERCONFIGRESPONSE._serialized_end = 44089 + _DESCRIBEWORKERREQUEST._serialized_start = 44091 + _DESCRIBEWORKERREQUEST._serialized_end = 44162 + _DESCRIBEWORKERRESPONSE._serialized_start = 44164 + _DESCRIBEWORKERRESPONSE._serialized_end = 44245 + _PAUSEWORKFLOWEXECUTIONREQUEST._serialized_start = 44248 + _PAUSEWORKFLOWEXECUTIONREQUEST._serialized_end = 44389 + _PAUSEWORKFLOWEXECUTIONRESPONSE._serialized_start = 44391 + _PAUSEWORKFLOWEXECUTIONRESPONSE._serialized_end = 44423 + _UNPAUSEWORKFLOWEXECUTIONREQUEST._serialized_start = 44426 + _UNPAUSEWORKFLOWEXECUTIONREQUEST._serialized_end = 44569 + _UNPAUSEWORKFLOWEXECUTIONRESPONSE._serialized_start = 44571 + _UNPAUSEWORKFLOWEXECUTIONRESPONSE._serialized_end = 44605 + _STARTACTIVITYEXECUTIONREQUEST._serialized_start = 44608 + _STARTACTIVITYEXECUTIONREQUEST._serialized_end = 45556 + _STARTACTIVITYEXECUTIONRESPONSE._serialized_start = 45558 + _STARTACTIVITYEXECUTIONRESPONSE._serialized_end = 45623 + _DESCRIBEACTIVITYEXECUTIONREQUEST._serialized_start = 45626 + _DESCRIBEACTIVITYEXECUTIONREQUEST._serialized_end = 45789 + _DESCRIBEACTIVITYEXECUTIONRESPONSE._serialized_start = 45792 + _DESCRIBEACTIVITYEXECUTIONRESPONSE._serialized_end = 46049 + _POLLACTIVITYEXECUTIONREQUEST._serialized_start = 46051 + _POLLACTIVITYEXECUTIONREQUEST._serialized_end = 46137 + _POLLACTIVITYEXECUTIONRESPONSE._serialized_start = 46139 + _POLLACTIVITYEXECUTIONRESPONSE._serialized_end = 46255 + _LISTACTIVITYEXECUTIONSREQUEST._serialized_start = 46257 + _LISTACTIVITYEXECUTIONSREQUEST._serialized_end = 46366 + _LISTACTIVITYEXECUTIONSRESPONSE._serialized_start = 46369 + _LISTACTIVITYEXECUTIONSRESPONSE._serialized_end = 46499 + _COUNTACTIVITYEXECUTIONSREQUEST._serialized_start = 46501 + _COUNTACTIVITYEXECUTIONSREQUEST._serialized_end = 46567 + _COUNTACTIVITYEXECUTIONSRESPONSE._serialized_start = 46570 + _COUNTACTIVITYEXECUTIONSRESPONSE._serialized_end = 46807 + _COUNTACTIVITYEXECUTIONSRESPONSE_AGGREGATIONGROUP._serialized_start = 18980 + _COUNTACTIVITYEXECUTIONSRESPONSE_AGGREGATIONGROUP._serialized_end = 19068 + _REQUESTCANCELACTIVITYEXECUTIONREQUEST._serialized_start = 46810 + _REQUESTCANCELACTIVITYEXECUTIONREQUEST._serialized_end = 46959 + _REQUESTCANCELACTIVITYEXECUTIONRESPONSE._serialized_start = 46961 + _REQUESTCANCELACTIVITYEXECUTIONRESPONSE._serialized_end = 47001 + _TERMINATEACTIVITYEXECUTIONREQUEST._serialized_start = 47004 + _TERMINATEACTIVITYEXECUTIONREQUEST._serialized_end = 47149 + _TERMINATEACTIVITYEXECUTIONRESPONSE._serialized_start = 47151 + _TERMINATEACTIVITYEXECUTIONRESPONSE._serialized_end = 47187 + _DELETEACTIVITYEXECUTIONREQUEST._serialized_start = 47189 + _DELETEACTIVITYEXECUTIONREQUEST._serialized_end = 47277 + _DELETEACTIVITYEXECUTIONRESPONSE._serialized_start = 47279 + _DELETEACTIVITYEXECUTIONRESPONSE._serialized_end = 47312 # @@protoc_insertion_point(module_scope) diff --git a/temporalio/api/workflowservice/v1/request_response_pb2.pyi b/temporalio/api/workflowservice/v1/request_response_pb2.pyi index debf89c0c..7facbef4d 100644 --- a/temporalio/api/workflowservice/v1/request_response_pb2.pyi +++ b/temporalio/api/workflowservice/v1/request_response_pb2.pyi @@ -1423,6 +1423,7 @@ class RespondWorkflowTaskCompletedRequest(google.protobuf.message.Message): BINARY_CHECKSUM_FIELD_NUMBER: builtins.int QUERY_RESULTS_FIELD_NUMBER: builtins.int NAMESPACE_FIELD_NUMBER: builtins.int + RESOURCE_ID_FIELD_NUMBER: builtins.int WORKER_VERSION_STAMP_FIELD_NUMBER: builtins.int MESSAGES_FIELD_NUMBER: builtins.int SDK_METADATA_FIELD_NUMBER: builtins.int @@ -1471,6 +1472,8 @@ class RespondWorkflowTaskCompletedRequest(google.protobuf.message.Message): ]: """Responses to the `queries` field in the task being responded to""" namespace: builtins.str + resource_id: builtins.str + """Resource ID for routing. Contains the workflow ID from the original task.""" @property def worker_version_stamp( self, @@ -1538,6 +1541,7 @@ class RespondWorkflowTaskCompletedRequest(google.protobuf.message.Message): ] | None = ..., namespace: builtins.str = ..., + resource_id: builtins.str = ..., worker_version_stamp: temporalio.api.common.v1.message_pb2.WorkerVersionStamp | None = ..., messages: collections.abc.Iterable[ @@ -1599,6 +1603,8 @@ class RespondWorkflowTaskCompletedRequest(google.protobuf.message.Message): b"namespace", "query_results", b"query_results", + "resource_id", + b"resource_id", "return_new_workflow_task", b"return_new_workflow_task", "sdk_metadata", @@ -1671,6 +1677,7 @@ class RespondWorkflowTaskFailedRequest(google.protobuf.message.Message): IDENTITY_FIELD_NUMBER: builtins.int BINARY_CHECKSUM_FIELD_NUMBER: builtins.int NAMESPACE_FIELD_NUMBER: builtins.int + RESOURCE_ID_FIELD_NUMBER: builtins.int MESSAGES_FIELD_NUMBER: builtins.int WORKER_VERSION_FIELD_NUMBER: builtins.int DEPLOYMENT_FIELD_NUMBER: builtins.int @@ -1691,6 +1698,8 @@ class RespondWorkflowTaskFailedRequest(google.protobuf.message.Message): Worker process' unique binary id """ namespace: builtins.str + resource_id: builtins.str + """Resource ID for routing. Contains the workflow ID from the original task.""" @property def messages( self, @@ -1725,6 +1734,7 @@ class RespondWorkflowTaskFailedRequest(google.protobuf.message.Message): identity: builtins.str = ..., binary_checksum: builtins.str = ..., namespace: builtins.str = ..., + resource_id: builtins.str = ..., messages: collections.abc.Iterable[ temporalio.api.protocol.v1.message_pb2.Message ] @@ -1767,6 +1777,8 @@ class RespondWorkflowTaskFailedRequest(google.protobuf.message.Message): b"messages", "namespace", b"namespace", + "resource_id", + b"resource_id", "task_token", b"task_token", "worker_version", @@ -2090,6 +2102,7 @@ class RecordActivityTaskHeartbeatRequest(google.protobuf.message.Message): DETAILS_FIELD_NUMBER: builtins.int IDENTITY_FIELD_NUMBER: builtins.int NAMESPACE_FIELD_NUMBER: builtins.int + RESOURCE_ID_FIELD_NUMBER: builtins.int task_token: builtins.bytes """The task token as received in `PollActivityTaskQueueResponse`""" @property @@ -2098,6 +2111,8 @@ class RecordActivityTaskHeartbeatRequest(google.protobuf.message.Message): identity: builtins.str """The identity of the worker/client""" namespace: builtins.str + resource_id: builtins.str + """Resource ID for routing. Contains the workflow ID or activity ID for standalone activities.""" def __init__( self, *, @@ -2105,6 +2120,7 @@ class RecordActivityTaskHeartbeatRequest(google.protobuf.message.Message): details: temporalio.api.common.v1.message_pb2.Payloads | None = ..., identity: builtins.str = ..., namespace: builtins.str = ..., + resource_id: builtins.str = ..., ) -> None: ... def HasField( self, field_name: typing_extensions.Literal["details", b"details"] @@ -2118,6 +2134,8 @@ class RecordActivityTaskHeartbeatRequest(google.protobuf.message.Message): b"identity", "namespace", b"namespace", + "resource_id", + b"resource_id", "task_token", b"task_token", ], @@ -2171,6 +2189,7 @@ class RecordActivityTaskHeartbeatByIdRequest(google.protobuf.message.Message): ACTIVITY_ID_FIELD_NUMBER: builtins.int DETAILS_FIELD_NUMBER: builtins.int IDENTITY_FIELD_NUMBER: builtins.int + RESOURCE_ID_FIELD_NUMBER: builtins.int namespace: builtins.str """Namespace of the workflow which scheduled this activity""" workflow_id: builtins.str @@ -2186,6 +2205,8 @@ class RecordActivityTaskHeartbeatByIdRequest(google.protobuf.message.Message): """Arbitrary data, of which the most recent call is kept, to store for this activity""" identity: builtins.str """The identity of the worker/client""" + resource_id: builtins.str + """Resource ID for routing. Contains "workflow:workflow_id" or "activity:activity_id" for standalone activities.""" def __init__( self, *, @@ -2195,6 +2216,7 @@ class RecordActivityTaskHeartbeatByIdRequest(google.protobuf.message.Message): activity_id: builtins.str = ..., details: temporalio.api.common.v1.message_pb2.Payloads | None = ..., identity: builtins.str = ..., + resource_id: builtins.str = ..., ) -> None: ... def HasField( self, field_name: typing_extensions.Literal["details", b"details"] @@ -2210,6 +2232,8 @@ class RecordActivityTaskHeartbeatByIdRequest(google.protobuf.message.Message): b"identity", "namespace", b"namespace", + "resource_id", + b"resource_id", "run_id", b"run_id", "workflow_id", @@ -2265,6 +2289,7 @@ class RespondActivityTaskCompletedRequest(google.protobuf.message.Message): RESULT_FIELD_NUMBER: builtins.int IDENTITY_FIELD_NUMBER: builtins.int NAMESPACE_FIELD_NUMBER: builtins.int + RESOURCE_ID_FIELD_NUMBER: builtins.int WORKER_VERSION_FIELD_NUMBER: builtins.int DEPLOYMENT_FIELD_NUMBER: builtins.int DEPLOYMENT_OPTIONS_FIELD_NUMBER: builtins.int @@ -2276,6 +2301,8 @@ class RespondActivityTaskCompletedRequest(google.protobuf.message.Message): identity: builtins.str """The identity of the worker/client""" namespace: builtins.str + resource_id: builtins.str + """Resource ID for routing. Contains the workflow ID or activity ID for standalone activities.""" @property def worker_version(self) -> temporalio.api.common.v1.message_pb2.WorkerVersionStamp: """Version info of the worker who processed this task. This message's `build_id` field should @@ -2301,6 +2328,7 @@ class RespondActivityTaskCompletedRequest(google.protobuf.message.Message): result: temporalio.api.common.v1.message_pb2.Payloads | None = ..., identity: builtins.str = ..., namespace: builtins.str = ..., + resource_id: builtins.str = ..., worker_version: temporalio.api.common.v1.message_pb2.WorkerVersionStamp | None = ..., deployment: temporalio.api.deployment.v1.message_pb2.Deployment | None = ..., @@ -2331,6 +2359,8 @@ class RespondActivityTaskCompletedRequest(google.protobuf.message.Message): b"identity", "namespace", b"namespace", + "resource_id", + b"resource_id", "result", b"result", "task_token", @@ -2360,6 +2390,7 @@ class RespondActivityTaskCompletedByIdRequest(google.protobuf.message.Message): ACTIVITY_ID_FIELD_NUMBER: builtins.int RESULT_FIELD_NUMBER: builtins.int IDENTITY_FIELD_NUMBER: builtins.int + RESOURCE_ID_FIELD_NUMBER: builtins.int namespace: builtins.str """Namespace of the workflow which scheduled this activity""" workflow_id: builtins.str @@ -2375,6 +2406,8 @@ class RespondActivityTaskCompletedByIdRequest(google.protobuf.message.Message): """The serialized result of activity execution""" identity: builtins.str """The identity of the worker/client""" + resource_id: builtins.str + """Resource ID for routing. Contains "workflow:workflow_id" or "activity:activity_id" for standalone activities.""" def __init__( self, *, @@ -2384,6 +2417,7 @@ class RespondActivityTaskCompletedByIdRequest(google.protobuf.message.Message): activity_id: builtins.str = ..., result: temporalio.api.common.v1.message_pb2.Payloads | None = ..., identity: builtins.str = ..., + resource_id: builtins.str = ..., ) -> None: ... def HasField( self, field_name: typing_extensions.Literal["result", b"result"] @@ -2397,6 +2431,8 @@ class RespondActivityTaskCompletedByIdRequest(google.protobuf.message.Message): b"identity", "namespace", b"namespace", + "resource_id", + b"resource_id", "result", b"result", "run_id", @@ -2428,6 +2464,7 @@ class RespondActivityTaskFailedRequest(google.protobuf.message.Message): FAILURE_FIELD_NUMBER: builtins.int IDENTITY_FIELD_NUMBER: builtins.int NAMESPACE_FIELD_NUMBER: builtins.int + RESOURCE_ID_FIELD_NUMBER: builtins.int LAST_HEARTBEAT_DETAILS_FIELD_NUMBER: builtins.int WORKER_VERSION_FIELD_NUMBER: builtins.int DEPLOYMENT_FIELD_NUMBER: builtins.int @@ -2440,6 +2477,8 @@ class RespondActivityTaskFailedRequest(google.protobuf.message.Message): identity: builtins.str """The identity of the worker/client""" namespace: builtins.str + resource_id: builtins.str + """Resource ID for routing. Contains the workflow ID or activity ID for standalone activities.""" @property def last_heartbeat_details(self) -> temporalio.api.common.v1.message_pb2.Payloads: """Additional details to be stored as last activity heartbeat""" @@ -2468,6 +2507,7 @@ class RespondActivityTaskFailedRequest(google.protobuf.message.Message): failure: temporalio.api.failure.v1.message_pb2.Failure | None = ..., identity: builtins.str = ..., namespace: builtins.str = ..., + resource_id: builtins.str = ..., last_heartbeat_details: temporalio.api.common.v1.message_pb2.Payloads | None = ..., worker_version: temporalio.api.common.v1.message_pb2.WorkerVersionStamp @@ -2506,6 +2546,8 @@ class RespondActivityTaskFailedRequest(google.protobuf.message.Message): b"last_heartbeat_details", "namespace", b"namespace", + "resource_id", + b"resource_id", "task_token", b"task_token", "worker_version", @@ -2552,6 +2594,7 @@ class RespondActivityTaskFailedByIdRequest(google.protobuf.message.Message): FAILURE_FIELD_NUMBER: builtins.int IDENTITY_FIELD_NUMBER: builtins.int LAST_HEARTBEAT_DETAILS_FIELD_NUMBER: builtins.int + RESOURCE_ID_FIELD_NUMBER: builtins.int namespace: builtins.str """Namespace of the workflow which scheduled this activity""" workflow_id: builtins.str @@ -2570,6 +2613,8 @@ class RespondActivityTaskFailedByIdRequest(google.protobuf.message.Message): @property def last_heartbeat_details(self) -> temporalio.api.common.v1.message_pb2.Payloads: """Additional details to be stored as last activity heartbeat""" + resource_id: builtins.str + """Resource ID for routing. Contains "workflow:workflow_id" or "activity:activity_id" for standalone activities.""" def __init__( self, *, @@ -2581,6 +2626,7 @@ class RespondActivityTaskFailedByIdRequest(google.protobuf.message.Message): identity: builtins.str = ..., last_heartbeat_details: temporalio.api.common.v1.message_pb2.Payloads | None = ..., + resource_id: builtins.str = ..., ) -> None: ... def HasField( self, @@ -2601,6 +2647,8 @@ class RespondActivityTaskFailedByIdRequest(google.protobuf.message.Message): b"last_heartbeat_details", "namespace", b"namespace", + "resource_id", + b"resource_id", "run_id", b"run_id", "workflow_id", @@ -2644,6 +2692,7 @@ class RespondActivityTaskCanceledRequest(google.protobuf.message.Message): DETAILS_FIELD_NUMBER: builtins.int IDENTITY_FIELD_NUMBER: builtins.int NAMESPACE_FIELD_NUMBER: builtins.int + RESOURCE_ID_FIELD_NUMBER: builtins.int WORKER_VERSION_FIELD_NUMBER: builtins.int DEPLOYMENT_FIELD_NUMBER: builtins.int DEPLOYMENT_OPTIONS_FIELD_NUMBER: builtins.int @@ -2655,6 +2704,8 @@ class RespondActivityTaskCanceledRequest(google.protobuf.message.Message): identity: builtins.str """The identity of the worker/client""" namespace: builtins.str + resource_id: builtins.str + """Resource ID for routing. Contains the workflow ID or activity ID for standalone activities.""" @property def worker_version(self) -> temporalio.api.common.v1.message_pb2.WorkerVersionStamp: """Version info of the worker who processed this task. This message's `build_id` field should @@ -2680,6 +2731,7 @@ class RespondActivityTaskCanceledRequest(google.protobuf.message.Message): details: temporalio.api.common.v1.message_pb2.Payloads | None = ..., identity: builtins.str = ..., namespace: builtins.str = ..., + resource_id: builtins.str = ..., worker_version: temporalio.api.common.v1.message_pb2.WorkerVersionStamp | None = ..., deployment: temporalio.api.deployment.v1.message_pb2.Deployment | None = ..., @@ -2712,6 +2764,8 @@ class RespondActivityTaskCanceledRequest(google.protobuf.message.Message): b"identity", "namespace", b"namespace", + "resource_id", + b"resource_id", "task_token", b"task_token", "worker_version", @@ -2740,6 +2794,7 @@ class RespondActivityTaskCanceledByIdRequest(google.protobuf.message.Message): DETAILS_FIELD_NUMBER: builtins.int IDENTITY_FIELD_NUMBER: builtins.int DEPLOYMENT_OPTIONS_FIELD_NUMBER: builtins.int + RESOURCE_ID_FIELD_NUMBER: builtins.int namespace: builtins.str """Namespace of the workflow which scheduled this activity""" workflow_id: builtins.str @@ -2760,6 +2815,8 @@ class RespondActivityTaskCanceledByIdRequest(google.protobuf.message.Message): self, ) -> temporalio.api.deployment.v1.message_pb2.WorkerDeploymentOptions: """Worker deployment options that user has set in the worker.""" + resource_id: builtins.str + """Resource ID for routing. Contains "workflow:workflow_id" or "activity:activity_id" for standalone activities.""" def __init__( self, *, @@ -2771,6 +2828,7 @@ class RespondActivityTaskCanceledByIdRequest(google.protobuf.message.Message): identity: builtins.str = ..., deployment_options: temporalio.api.deployment.v1.message_pb2.WorkerDeploymentOptions | None = ..., + resource_id: builtins.str = ..., ) -> None: ... def HasField( self, @@ -2791,6 +2849,8 @@ class RespondActivityTaskCanceledByIdRequest(google.protobuf.message.Message): b"identity", "namespace", b"namespace", + "resource_id", + b"resource_id", "run_id", b"run_id", "workflow_id", @@ -7562,6 +7622,7 @@ class ExecuteMultiOperationRequest(google.protobuf.message.Message): NAMESPACE_FIELD_NUMBER: builtins.int OPERATIONS_FIELD_NUMBER: builtins.int + RESOURCE_ID_FIELD_NUMBER: builtins.int namespace: builtins.str @property def operations( @@ -7578,6 +7639,8 @@ class ExecuteMultiOperationRequest(google.protobuf.message.Message): Note that additional operation-specific restrictions have to be considered. """ + resource_id: builtins.str + """Resource ID for routing. Should match operations[0].start_workflow.workflow_id""" def __init__( self, *, @@ -7586,11 +7649,17 @@ class ExecuteMultiOperationRequest(google.protobuf.message.Message): global___ExecuteMultiOperationRequest.Operation ] | None = ..., + resource_id: builtins.str = ..., ) -> None: ... def ClearField( self, field_name: typing_extensions.Literal[ - "namespace", b"namespace", "operations", b"operations" + "namespace", + b"namespace", + "operations", + b"operations", + "resource_id", + b"resource_id", ], ) -> None: ... @@ -9884,6 +9953,7 @@ class RecordWorkerHeartbeatRequest(google.protobuf.message.Message): NAMESPACE_FIELD_NUMBER: builtins.int IDENTITY_FIELD_NUMBER: builtins.int WORKER_HEARTBEAT_FIELD_NUMBER: builtins.int + RESOURCE_ID_FIELD_NUMBER: builtins.int namespace: builtins.str """Namespace this worker belongs to.""" identity: builtins.str @@ -9894,6 +9964,8 @@ class RecordWorkerHeartbeatRequest(google.protobuf.message.Message): ) -> google.protobuf.internal.containers.RepeatedCompositeFieldContainer[ temporalio.api.worker.v1.message_pb2.WorkerHeartbeat ]: ... + resource_id: builtins.str + """Resource ID for routing. Contains the worker grouping key.""" def __init__( self, *, @@ -9903,6 +9975,7 @@ class RecordWorkerHeartbeatRequest(google.protobuf.message.Message): temporalio.api.worker.v1.message_pb2.WorkerHeartbeat ] | None = ..., + resource_id: builtins.str = ..., ) -> None: ... def ClearField( self, @@ -9911,6 +9984,8 @@ class RecordWorkerHeartbeatRequest(google.protobuf.message.Message): b"identity", "namespace", b"namespace", + "resource_id", + b"resource_id", "worker_heartbeat", b"worker_heartbeat", ], @@ -10196,6 +10271,7 @@ class FetchWorkerConfigRequest(google.protobuf.message.Message): IDENTITY_FIELD_NUMBER: builtins.int REASON_FIELD_NUMBER: builtins.int SELECTOR_FIELD_NUMBER: builtins.int + RESOURCE_ID_FIELD_NUMBER: builtins.int namespace: builtins.str """Namespace this worker belongs to.""" identity: builtins.str @@ -10207,6 +10283,8 @@ class FetchWorkerConfigRequest(google.protobuf.message.Message): """Defines which workers should receive this command. only single worker is supported at this time. """ + resource_id: builtins.str + """Resource ID for routing. Contains the worker grouping key.""" def __init__( self, *, @@ -10214,6 +10292,7 @@ class FetchWorkerConfigRequest(google.protobuf.message.Message): identity: builtins.str = ..., reason: builtins.str = ..., selector: temporalio.api.common.v1.message_pb2.WorkerSelector | None = ..., + resource_id: builtins.str = ..., ) -> None: ... def HasField( self, field_name: typing_extensions.Literal["selector", b"selector"] @@ -10227,6 +10306,8 @@ class FetchWorkerConfigRequest(google.protobuf.message.Message): b"namespace", "reason", b"reason", + "resource_id", + b"resource_id", "selector", b"selector", ], @@ -10265,6 +10346,7 @@ class UpdateWorkerConfigRequest(google.protobuf.message.Message): WORKER_CONFIG_FIELD_NUMBER: builtins.int UPDATE_MASK_FIELD_NUMBER: builtins.int SELECTOR_FIELD_NUMBER: builtins.int + RESOURCE_ID_FIELD_NUMBER: builtins.int namespace: builtins.str """Namespace this worker belongs to.""" identity: builtins.str @@ -10282,6 +10364,8 @@ class UpdateWorkerConfigRequest(google.protobuf.message.Message): @property def selector(self) -> temporalio.api.common.v1.message_pb2.WorkerSelector: """Defines which workers should receive this command.""" + resource_id: builtins.str + """Resource ID for routing. Contains the worker grouping key.""" def __init__( self, *, @@ -10292,6 +10376,7 @@ class UpdateWorkerConfigRequest(google.protobuf.message.Message): | None = ..., update_mask: google.protobuf.field_mask_pb2.FieldMask | None = ..., selector: temporalio.api.common.v1.message_pb2.WorkerSelector | None = ..., + resource_id: builtins.str = ..., ) -> None: ... def HasField( self, @@ -10313,6 +10398,8 @@ class UpdateWorkerConfigRequest(google.protobuf.message.Message): b"namespace", "reason", b"reason", + "resource_id", + b"resource_id", "selector", b"selector", "update_mask", diff --git a/temporalio/api/workflowservice/v1/service_pb2.py b/temporalio/api/workflowservice/v1/service_pb2.py index 810956de6..a4d09080a 100644 --- a/temporalio/api/workflowservice/v1/service_pb2.py +++ b/temporalio/api/workflowservice/v1/service_pb2.py @@ -16,12 +16,15 @@ from google.api import annotations_pb2 as google_dot_api_dot_annotations__pb2 +from temporalio.api.protometa.v1 import ( + annotations_pb2 as temporal_dot_api_dot_protometa_dot_v1_dot_annotations__pb2, +) from temporalio.api.workflowservice.v1 import ( request_response_pb2 as temporal_dot_api_dot_workflowservice_dot_v1_dot_request__response__pb2, ) DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile( - b'\n-temporal/api/workflowservice/v1/service.proto\x12\x1ftemporal.api.workflowservice.v1\x1a\x36temporal/api/workflowservice/v1/request_response.proto\x1a\x1cgoogle/api/annotations.proto2\xb4\xdf\x01\n\x0fWorkflowService\x12\xc3\x01\n\x11RegisterNamespace\x12\x39.temporal.api.workflowservice.v1.RegisterNamespaceRequest\x1a:.temporal.api.workflowservice.v1.RegisterNamespaceResponse"7\x82\xd3\xe4\x93\x02\x31"\x13/cluster/namespaces:\x01*Z\x17"\x12/api/v1/namespaces:\x01*\x12\xd5\x01\n\x11\x44\x65scribeNamespace\x12\x39.temporal.api.workflowservice.v1.DescribeNamespaceRequest\x1a:.temporal.api.workflowservice.v1.DescribeNamespaceResponse"I\x82\xd3\xe4\x93\x02\x43\x12\x1f/cluster/namespaces/{namespace}Z \x12\x1e/api/v1/namespaces/{namespace}\x12\xb4\x01\n\x0eListNamespaces\x12\x36.temporal.api.workflowservice.v1.ListNamespacesRequest\x1a\x37.temporal.api.workflowservice.v1.ListNamespacesResponse"1\x82\xd3\xe4\x93\x02+\x12\x13/cluster/namespacesZ\x14\x12\x12/api/v1/namespaces\x12\xe3\x01\n\x0fUpdateNamespace\x12\x37.temporal.api.workflowservice.v1.UpdateNamespaceRequest\x1a\x38.temporal.api.workflowservice.v1.UpdateNamespaceResponse"]\x82\xd3\xe4\x93\x02W"&/cluster/namespaces/{namespace}/update:\x01*Z*"%/api/v1/namespaces/{namespace}/update:\x01*\x12\x8f\x01\n\x12\x44\x65precateNamespace\x12:.temporal.api.workflowservice.v1.DeprecateNamespaceRequest\x1a;.temporal.api.workflowservice.v1.DeprecateNamespaceResponse"\x00\x12\x92\x02\n\x16StartWorkflowExecution\x12>.temporal.api.workflowservice.v1.StartWorkflowExecutionRequest\x1a?.temporal.api.workflowservice.v1.StartWorkflowExecutionResponse"w\x82\xd3\xe4\x93\x02q"//namespaces/{namespace}/workflows/{workflow_id}:\x01*Z;"6/api/v1/namespaces/{namespace}/workflows/{workflow_id}:\x01*\x12\x98\x01\n\x15\x45xecuteMultiOperation\x12=.temporal.api.workflowservice.v1.ExecuteMultiOperationRequest\x1a>.temporal.api.workflowservice.v1.ExecuteMultiOperationResponse"\x00\x12\xc1\x02\n\x1bGetWorkflowExecutionHistory\x12\x43.temporal.api.workflowservice.v1.GetWorkflowExecutionHistoryRequest\x1a\x44.temporal.api.workflowservice.v1.GetWorkflowExecutionHistoryResponse"\x96\x01\x82\xd3\xe4\x93\x02\x8f\x01\x12\x41/namespaces/{namespace}/workflows/{execution.workflow_id}/historyZJ\x12H/api/v1/namespaces/{namespace}/workflows/{execution.workflow_id}/history\x12\xe6\x02\n"GetWorkflowExecutionHistoryReverse\x12J.temporal.api.workflowservice.v1.GetWorkflowExecutionHistoryReverseRequest\x1aK.temporal.api.workflowservice.v1.GetWorkflowExecutionHistoryReverseResponse"\xa6\x01\x82\xd3\xe4\x93\x02\x9f\x01\x12I/namespaces/{namespace}/workflows/{execution.workflow_id}/history-reverseZR\x12P/api/v1/namespaces/{namespace}/workflows/{execution.workflow_id}/history-reverse\x12\x98\x01\n\x15PollWorkflowTaskQueue\x12=.temporal.api.workflowservice.v1.PollWorkflowTaskQueueRequest\x1a>.temporal.api.workflowservice.v1.PollWorkflowTaskQueueResponse"\x00\x12\xad\x01\n\x1cRespondWorkflowTaskCompleted\x12\x44.temporal.api.workflowservice.v1.RespondWorkflowTaskCompletedRequest\x1a\x45.temporal.api.workflowservice.v1.RespondWorkflowTaskCompletedResponse"\x00\x12\xa4\x01\n\x19RespondWorkflowTaskFailed\x12\x41.temporal.api.workflowservice.v1.RespondWorkflowTaskFailedRequest\x1a\x42.temporal.api.workflowservice.v1.RespondWorkflowTaskFailedResponse"\x00\x12\x98\x01\n\x15PollActivityTaskQueue\x12=.temporal.api.workflowservice.v1.PollActivityTaskQueueRequest\x1a>.temporal.api.workflowservice.v1.PollActivityTaskQueueResponse"\x00\x12\x97\x02\n\x1bRecordActivityTaskHeartbeat\x12\x43.temporal.api.workflowservice.v1.RecordActivityTaskHeartbeatRequest\x1a\x44.temporal.api.workflowservice.v1.RecordActivityTaskHeartbeatResponse"m\x82\xd3\xe4\x93\x02g"*/namespaces/{namespace}/activity-heartbeat:\x01*Z6"1/api/v1/namespaces/{namespace}/activity-heartbeat:\x01*\x12\xfe\x03\n\x1fRecordActivityTaskHeartbeatById\x12G.temporal.api.workflowservice.v1.RecordActivityTaskHeartbeatByIdRequest\x1aH.temporal.api.workflowservice.v1.RecordActivityTaskHeartbeatByIdResponse"\xc7\x02\x82\xd3\xe4\x93\x02\xc0\x02":/namespaces/{namespace}/activities/{activity_id}/heartbeat:\x01*ZF"A/api/v1/namespaces/{namespace}/activities/{activity_id}/heartbeat:\x01*ZW"R/namespaces/{namespace}/workflows/{workflow_id}/activities/{activity_id}/heartbeat:\x01*Z^"Y/api/v1/namespaces/{namespace}/workflows/{workflow_id}/activities/{activity_id}/heartbeat:\x01*\x12\x98\x02\n\x1cRespondActivityTaskCompleted\x12\x44.temporal.api.workflowservice.v1.RespondActivityTaskCompletedRequest\x1a\x45.temporal.api.workflowservice.v1.RespondActivityTaskCompletedResponse"k\x82\xd3\xe4\x93\x02\x65")/namespaces/{namespace}/activity-complete:\x01*Z5"0/api/v1/namespaces/{namespace}/activity-complete:\x01*\x12\xfd\x03\n RespondActivityTaskCompletedById\x12H.temporal.api.workflowservice.v1.RespondActivityTaskCompletedByIdRequest\x1aI.temporal.api.workflowservice.v1.RespondActivityTaskCompletedByIdResponse"\xc3\x02\x82\xd3\xe4\x93\x02\xbc\x02"9/namespaces/{namespace}/activities/{activity_id}/complete:\x01*ZE"@/api/v1/namespaces/{namespace}/activities/{activity_id}/complete:\x01*ZV"Q/namespaces/{namespace}/workflows/{workflow_id}/activities/{activity_id}/complete:\x01*Z]"X/api/v1/namespaces/{namespace}/workflows/{workflow_id}/activities/{activity_id}/complete:\x01*\x12\x87\x02\n\x19RespondActivityTaskFailed\x12\x41.temporal.api.workflowservice.v1.RespondActivityTaskFailedRequest\x1a\x42.temporal.api.workflowservice.v1.RespondActivityTaskFailedResponse"c\x82\xd3\xe4\x93\x02]"%/namespaces/{namespace}/activity-fail:\x01*Z1",/api/v1/namespaces/{namespace}/activity-fail:\x01*\x12\xe4\x03\n\x1dRespondActivityTaskFailedById\x12\x45.temporal.api.workflowservice.v1.RespondActivityTaskFailedByIdRequest\x1a\x46.temporal.api.workflowservice.v1.RespondActivityTaskFailedByIdResponse"\xb3\x02\x82\xd3\xe4\x93\x02\xac\x02"5/namespaces/{namespace}/activities/{activity_id}/fail:\x01*ZA".temporal.api.workflowservice.v1.ResetWorkflowExecutionRequest\x1a?.temporal.api.workflowservice.v1.ResetWorkflowExecutionResponse"\xaa\x01\x82\xd3\xe4\x93\x02\xa3\x01"H/namespaces/{namespace}/workflows/{workflow_execution.workflow_id}/reset:\x01*ZT"O/api/v1/namespaces/{namespace}/workflows/{workflow_execution.workflow_id}/reset:\x01*\x12\xda\x02\n\x1aTerminateWorkflowExecution\x12\x42.temporal.api.workflowservice.v1.TerminateWorkflowExecutionRequest\x1a\x43.temporal.api.workflowservice.v1.TerminateWorkflowExecutionResponse"\xb2\x01\x82\xd3\xe4\x93\x02\xab\x01"L/namespaces/{namespace}/workflows/{workflow_execution.workflow_id}/terminate:\x01*ZX"S/api/v1/namespaces/{namespace}/workflows/{workflow_execution.workflow_id}/terminate:\x01*\x12\x9e\x01\n\x17\x44\x65leteWorkflowExecution\x12?.temporal.api.workflowservice.v1.DeleteWorkflowExecutionRequest\x1a@.temporal.api.workflowservice.v1.DeleteWorkflowExecutionResponse"\x00\x12\xa7\x01\n\x1aListOpenWorkflowExecutions\x12\x42.temporal.api.workflowservice.v1.ListOpenWorkflowExecutionsRequest\x1a\x43.temporal.api.workflowservice.v1.ListOpenWorkflowExecutionsResponse"\x00\x12\xad\x01\n\x1cListClosedWorkflowExecutions\x12\x44.temporal.api.workflowservice.v1.ListClosedWorkflowExecutionsRequest\x1a\x45.temporal.api.workflowservice.v1.ListClosedWorkflowExecutionsResponse"\x00\x12\xf0\x01\n\x16ListWorkflowExecutions\x12>.temporal.api.workflowservice.v1.ListWorkflowExecutionsRequest\x1a?.temporal.api.workflowservice.v1.ListWorkflowExecutionsResponse"U\x82\xd3\xe4\x93\x02O\x12!/namespaces/{namespace}/workflowsZ*\x12(/api/v1/namespaces/{namespace}/workflows\x12\x9a\x02\n\x1eListArchivedWorkflowExecutions\x12\x46.temporal.api.workflowservice.v1.ListArchivedWorkflowExecutionsRequest\x1aG.temporal.api.workflowservice.v1.ListArchivedWorkflowExecutionsResponse"g\x82\xd3\xe4\x93\x02\x61\x12*/namespaces/{namespace}/archived-workflowsZ3\x12\x31/api/v1/namespaces/{namespace}/archived-workflows\x12\x9b\x01\n\x16ScanWorkflowExecutions\x12>.temporal.api.workflowservice.v1.ScanWorkflowExecutionsRequest\x1a?.temporal.api.workflowservice.v1.ScanWorkflowExecutionsResponse"\x00\x12\xfd\x01\n\x17\x43ountWorkflowExecutions\x12?.temporal.api.workflowservice.v1.CountWorkflowExecutionsRequest\x1a@.temporal.api.workflowservice.v1.CountWorkflowExecutionsResponse"_\x82\xd3\xe4\x93\x02Y\x12&/namespaces/{namespace}/workflow-countZ/\x12-/api/v1/namespaces/{namespace}/workflow-count\x12\x92\x01\n\x13GetSearchAttributes\x12;.temporal.api.workflowservice.v1.GetSearchAttributesRequest\x1a<.temporal.api.workflowservice.v1.GetSearchAttributesResponse"\x00\x12\xa4\x01\n\x19RespondQueryTaskCompleted\x12\x41.temporal.api.workflowservice.v1.RespondQueryTaskCompletedRequest\x1a\x42.temporal.api.workflowservice.v1.RespondQueryTaskCompletedResponse"\x00\x12\x95\x01\n\x14ResetStickyTaskQueue\x12<.temporal.api.workflowservice.v1.ResetStickyTaskQueueRequest\x1a=.temporal.api.workflowservice.v1.ResetStickyTaskQueueResponse"\x00\x12\x83\x01\n\x0eShutdownWorker\x12\x36.temporal.api.workflowservice.v1.ShutdownWorkerRequest\x1a\x37.temporal.api.workflowservice.v1.ShutdownWorkerResponse"\x00\x12\xbf\x02\n\rQueryWorkflow\x12\x35.temporal.api.workflowservice.v1.QueryWorkflowRequest\x1a\x36.temporal.api.workflowservice.v1.QueryWorkflowResponse"\xbe\x01\x82\xd3\xe4\x93\x02\xb7\x01"R/namespaces/{namespace}/workflows/{execution.workflow_id}/query/{query.query_type}:\x01*Z^"Y/api/v1/namespaces/{namespace}/workflows/{execution.workflow_id}/query/{query.query_type}:\x01*\x12\xaa\x02\n\x19\x44\x65scribeWorkflowExecution\x12\x41.temporal.api.workflowservice.v1.DescribeWorkflowExecutionRequest\x1a\x42.temporal.api.workflowservice.v1.DescribeWorkflowExecutionResponse"\x85\x01\x82\xd3\xe4\x93\x02\x7f\x12\x39/namespaces/{namespace}/workflows/{execution.workflow_id}ZB\x12@/api/v1/namespaces/{namespace}/workflows/{execution.workflow_id}\x12\x89\x02\n\x11\x44\x65scribeTaskQueue\x12\x39.temporal.api.workflowservice.v1.DescribeTaskQueueRequest\x1a:.temporal.api.workflowservice.v1.DescribeTaskQueueResponse"}\x82\xd3\xe4\x93\x02w\x12\x35/namespaces/{namespace}/task-queues/{task_queue.name}Z>\x12/namespaces/{namespace}/schedules/{schedule_id}/matching-timesZG\x12\x45/api/v1/namespaces/{namespace}/schedules/{schedule_id}/matching-times\x12\xf4\x01\n\x0e\x44\x65leteSchedule\x12\x36.temporal.api.workflowservice.v1.DeleteScheduleRequest\x1a\x37.temporal.api.workflowservice.v1.DeleteScheduleResponse"q\x82\xd3\xe4\x93\x02k*//namespaces/{namespace}/schedules/{schedule_id}Z8*6/api/v1/namespaces/{namespace}/schedules/{schedule_id}\x12\xd5\x01\n\rListSchedules\x12\x35.temporal.api.workflowservice.v1.ListSchedulesRequest\x1a\x36.temporal.api.workflowservice.v1.ListSchedulesResponse"U\x82\xd3\xe4\x93\x02O\x12!/namespaces/{namespace}/schedulesZ*\x12(/api/v1/namespaces/{namespace}/schedules\x12\xe2\x01\n\x0e\x43ountSchedules\x12\x36.temporal.api.workflowservice.v1.CountSchedulesRequest\x1a\x37.temporal.api.workflowservice.v1.CountSchedulesResponse"_\x82\xd3\xe4\x93\x02Y\x12&/namespaces/{namespace}/schedule-countZ/\x12-/api/v1/namespaces/{namespace}/schedule-count\x12\xb9\x01\n UpdateWorkerBuildIdCompatibility\x12H.temporal.api.workflowservice.v1.UpdateWorkerBuildIdCompatibilityRequest\x1aI.temporal.api.workflowservice.v1.UpdateWorkerBuildIdCompatibilityResponse"\x00\x12\xe1\x02\n\x1dGetWorkerBuildIdCompatibility\x12\x45.temporal.api.workflowservice.v1.GetWorkerBuildIdCompatibilityRequest\x1a\x46.temporal.api.workflowservice.v1.GetWorkerBuildIdCompatibilityResponse"\xb0\x01\x82\xd3\xe4\x93\x02\xa9\x01\x12N/namespaces/{namespace}/task-queues/{task_queue}/worker-build-id-compatibilityZW\x12U/api/v1/namespaces/{namespace}/task-queues/{task_queue}/worker-build-id-compatibility\x12\xaa\x01\n\x1bUpdateWorkerVersioningRules\x12\x43.temporal.api.workflowservice.v1.UpdateWorkerVersioningRulesRequest\x1a\x44.temporal.api.workflowservice.v1.UpdateWorkerVersioningRulesResponse"\x00\x12\xc6\x02\n\x18GetWorkerVersioningRules\x12@.temporal.api.workflowservice.v1.GetWorkerVersioningRulesRequest\x1a\x41.temporal.api.workflowservice.v1.GetWorkerVersioningRulesResponse"\xa4\x01\x82\xd3\xe4\x93\x02\x9d\x01\x12H/namespaces/{namespace}/task-queues/{task_queue}/worker-versioning-rulesZQ\x12O/api/v1/namespaces/{namespace}/task-queues/{task_queue}/worker-versioning-rules\x12\x97\x02\n\x19GetWorkerTaskReachability\x12\x41.temporal.api.workflowservice.v1.GetWorkerTaskReachabilityRequest\x1a\x42.temporal.api.workflowservice.v1.GetWorkerTaskReachabilityResponse"s\x82\xd3\xe4\x93\x02m\x12\x30/namespaces/{namespace}/worker-task-reachabilityZ9\x12\x37/api/v1/namespaces/{namespace}/worker-task-reachability\x12\xc8\x02\n\x12\x44\x65scribeDeployment\x12:.temporal.api.workflowservice.v1.DescribeDeploymentRequest\x1a;.temporal.api.workflowservice.v1.DescribeDeploymentResponse"\xb8\x01\x82\xd3\xe4\x93\x02\xb1\x01\x12R/namespaces/{namespace}/deployments/{deployment.series_name}/{deployment.build_id}Z[\x12Y/api/v1/namespaces/{namespace}/deployments/{deployment.series_name}/{deployment.build_id}\x12\xb5\x03\n\x1f\x44\x65scribeWorkerDeploymentVersion\x12G.temporal.api.workflowservice.v1.DescribeWorkerDeploymentVersionRequest\x1aH.temporal.api.workflowservice.v1.DescribeWorkerDeploymentVersionResponse"\xfe\x01\x82\xd3\xe4\x93\x02\xf7\x01\x12u/namespaces/{namespace}/worker-deployment-versions/{deployment_version.deployment_name}/{deployment_version.build_id}Z~\x12|/api/v1/namespaces/{namespace}/worker-deployment-versions/{deployment_version.deployment_name}/{deployment_version.build_id}\x12\xdf\x01\n\x0fListDeployments\x12\x37.temporal.api.workflowservice.v1.ListDeploymentsRequest\x1a\x38.temporal.api.workflowservice.v1.ListDeploymentsResponse"Y\x82\xd3\xe4\x93\x02S\x12#/namespaces/{namespace}/deploymentsZ,\x12*/api/v1/namespaces/{namespace}/deployments\x12\xf7\x02\n\x19GetDeploymentReachability\x12\x41.temporal.api.workflowservice.v1.GetDeploymentReachabilityRequest\x1a\x42.temporal.api.workflowservice.v1.GetDeploymentReachabilityResponse"\xd2\x01\x82\xd3\xe4\x93\x02\xcb\x01\x12_/namespaces/{namespace}/deployments/{deployment.series_name}/{deployment.build_id}/reachabilityZh\x12\x66/api/v1/namespaces/{namespace}/deployments/{deployment.series_name}/{deployment.build_id}/reachability\x12\x99\x02\n\x14GetCurrentDeployment\x12<.temporal.api.workflowservice.v1.GetCurrentDeploymentRequest\x1a=.temporal.api.workflowservice.v1.GetCurrentDeploymentResponse"\x83\x01\x82\xd3\xe4\x93\x02}\x12\x38/namespaces/{namespace}/current-deployment/{series_name}ZA\x12?/api/v1/namespaces/{namespace}/current-deployment/{series_name}\x12\xb6\x02\n\x14SetCurrentDeployment\x12<.temporal.api.workflowservice.v1.SetCurrentDeploymentRequest\x1a=.temporal.api.workflowservice.v1.SetCurrentDeploymentResponse"\xa0\x01\x82\xd3\xe4\x93\x02\x99\x01"C/namespaces/{namespace}/current-deployment/{deployment.series_name}:\x01*ZO"J/api/v1/namespaces/{namespace}/current-deployment/{deployment.series_name}:\x01*\x12\xf7\x02\n!SetWorkerDeploymentCurrentVersion\x12I.temporal.api.workflowservice.v1.SetWorkerDeploymentCurrentVersionRequest\x1aJ.temporal.api.workflowservice.v1.SetWorkerDeploymentCurrentVersionResponse"\xba\x01\x82\xd3\xe4\x93\x02\xb3\x01"P/namespaces/{namespace}/worker-deployments/{deployment_name}/set-current-version:\x01*Z\\"W/api/v1/namespaces/{namespace}/worker-deployments/{deployment_name}/set-current-version:\x01*\x12\xae\x02\n\x18\x44\x65scribeWorkerDeployment\x12@.temporal.api.workflowservice.v1.DescribeWorkerDeploymentRequest\x1a\x41.temporal.api.workflowservice.v1.DescribeWorkerDeploymentResponse"\x8c\x01\x82\xd3\xe4\x93\x02\x85\x01\x12.temporal.api.workflowservice.v1.DeleteWorkerDeploymentRequest\x1a?.temporal.api.workflowservice.v1.DeleteWorkerDeploymentResponse"\x8c\x01\x82\xd3\xe4\x93\x02\x85\x01*.temporal.api.workflowservice.v1.ListWorkerDeploymentsResponse"g\x82\xd3\xe4\x93\x02\x61\x12*/namespaces/{namespace}/worker-deploymentsZ3\x12\x31/api/v1/namespaces/{namespace}/worker-deployments\x12\xf0\x03\n%UpdateWorkerDeploymentVersionMetadata\x12M.temporal.api.workflowservice.v1.UpdateWorkerDeploymentVersionMetadataRequest\x1aN.temporal.api.workflowservice.v1.UpdateWorkerDeploymentVersionMetadataResponse"\xa7\x02\x82\xd3\xe4\x93\x02\xa0\x02"\x85\x01/namespaces/{namespace}/worker-deployment-versions/{deployment_version.deployment_name}/{deployment_version.build_id}/update-metadata:\x01*Z\x92\x01"\x8c\x01/api/v1/namespaces/{namespace}/worker-deployment-versions/{deployment_version.deployment_name}/{deployment_version.build_id}/update-metadata:\x01*\x12\xd2\x02\n\x1aSetWorkerDeploymentManager\x12\x42.temporal.api.workflowservice.v1.SetWorkerDeploymentManagerRequest\x1a\x43.temporal.api.workflowservice.v1.SetWorkerDeploymentManagerResponse"\xaa\x01\x82\xd3\xe4\x93\x02\xa3\x01"H/namespaces/{namespace}/worker-deployments/{deployment_name}/set-manager:\x01*ZT"O/api/v1/namespaces/{namespace}/worker-deployments/{deployment_name}/set-manager:\x01*\x12\xf5\x02\n\x17UpdateWorkflowExecution\x12?.temporal.api.workflowservice.v1.UpdateWorkflowExecutionRequest\x1a@.temporal.api.workflowservice.v1.UpdateWorkflowExecutionResponse"\xd6\x01\x82\xd3\xe4\x93\x02\xcf\x01"^/namespaces/{namespace}/workflows/{workflow_execution.workflow_id}/update/{request.input.name}:\x01*Zj"e/api/v1/namespaces/{namespace}/workflows/{workflow_execution.workflow_id}/update/{request.input.name}:\x01*\x12\xaa\x01\n\x1bPollWorkflowExecutionUpdate\x12\x43.temporal.api.workflowservice.v1.PollWorkflowExecutionUpdateRequest\x1a\x44.temporal.api.workflowservice.v1.PollWorkflowExecutionUpdateResponse"\x00\x12\x8d\x02\n\x13StartBatchOperation\x12;.temporal.api.workflowservice.v1.StartBatchOperationRequest\x1a<.temporal.api.workflowservice.v1.StartBatchOperationResponse"{\x82\xd3\xe4\x93\x02u"1/namespaces/{namespace}/batch-operations/{job_id}:\x01*Z="8/api/v1/namespaces/{namespace}/batch-operations/{job_id}:\x01*\x12\x95\x02\n\x12StopBatchOperation\x12:.temporal.api.workflowservice.v1.StopBatchOperationRequest\x1a;.temporal.api.workflowservice.v1.StopBatchOperationResponse"\x85\x01\x82\xd3\xe4\x93\x02\x7f"6/namespaces/{namespace}/batch-operations/{job_id}/stop:\x01*ZB"=/api/v1/namespaces/{namespace}/batch-operations/{job_id}/stop:\x01*\x12\x90\x02\n\x16\x44\x65scribeBatchOperation\x12>.temporal.api.workflowservice.v1.DescribeBatchOperationRequest\x1a?.temporal.api.workflowservice.v1.DescribeBatchOperationResponse"u\x82\xd3\xe4\x93\x02o\x12\x31/namespaces/{namespace}/batch-operations/{job_id}Z:\x12\x38/api/v1/namespaces/{namespace}/batch-operations/{job_id}\x12\xf5\x01\n\x13ListBatchOperations\x12;.temporal.api.workflowservice.v1.ListBatchOperationsRequest\x1a<.temporal.api.workflowservice.v1.ListBatchOperationsResponse"c\x82\xd3\xe4\x93\x02]\x12(/namespaces/{namespace}/batch-operationsZ1\x12//api/v1/namespaces/{namespace}/batch-operations\x12\x8f\x01\n\x12PollNexusTaskQueue\x12:.temporal.api.workflowservice.v1.PollNexusTaskQueueRequest\x1a;.temporal.api.workflowservice.v1.PollNexusTaskQueueResponse"\x00\x12\xa4\x01\n\x19RespondNexusTaskCompleted\x12\x41.temporal.api.workflowservice.v1.RespondNexusTaskCompletedRequest\x1a\x42.temporal.api.workflowservice.v1.RespondNexusTaskCompletedResponse"\x00\x12\x9b\x01\n\x16RespondNexusTaskFailed\x12>.temporal.api.workflowservice.v1.RespondNexusTaskFailedRequest\x1a?.temporal.api.workflowservice.v1.RespondNexusTaskFailedResponse"\x00\x12\xab\x02\n\x15UpdateActivityOptions\x12=.temporal.api.workflowservice.v1.UpdateActivityOptionsRequest\x1a>.temporal.api.workflowservice.v1.UpdateActivityOptionsResponse"\x92\x01\x82\xd3\xe4\x93\x02\x8b\x01".temporal.api.workflowservice.v1.RecordWorkerHeartbeatResponse"k\x82\xd3\xe4\x93\x02\x65")/namespaces/{namespace}/workers/heartbeat:\x01*Z5"0/api/v1/namespaces/{namespace}/workers/heartbeat:\x01*\x12\xcb\x01\n\x0bListWorkers\x12\x33.temporal.api.workflowservice.v1.ListWorkersRequest\x1a\x34.temporal.api.workflowservice.v1.ListWorkersResponse"Q\x82\xd3\xe4\x93\x02K\x12\x1f/namespaces/{namespace}/workersZ(\x12&/api/v1/namespaces/{namespace}/workers\x12\xaf\x02\n\x15UpdateTaskQueueConfig\x12=.temporal.api.workflowservice.v1.UpdateTaskQueueConfigRequest\x1a>.temporal.api.workflowservice.v1.UpdateTaskQueueConfigResponse"\x96\x01\x82\xd3\xe4\x93\x02\x8f\x01">/namespaces/{namespace}/task-queues/{task_queue}/update-config:\x01*ZJ"E/api/v1/namespaces/{namespace}/task-queues/{task_queue}/update-config:\x01*\x12\xfd\x01\n\x11\x46\x65tchWorkerConfig\x12\x39.temporal.api.workflowservice.v1.FetchWorkerConfigRequest\x1a:.temporal.api.workflowservice.v1.FetchWorkerConfigResponse"q\x82\xd3\xe4\x93\x02k",/namespaces/{namespace}/workers/fetch-config:\x01*Z8"3/api/v1/namespaces/{namespace}/workers/fetch-config:\x01*\x12\x82\x02\n\x12UpdateWorkerConfig\x12:.temporal.api.workflowservice.v1.UpdateWorkerConfigRequest\x1a;.temporal.api.workflowservice.v1.UpdateWorkerConfigResponse"s\x82\xd3\xe4\x93\x02m"-/namespaces/{namespace}/workers/update-config:\x01*Z9"4/api/v1/namespaces/{namespace}/workers/update-config:\x01*\x12\x94\x02\n\x0e\x44\x65scribeWorker\x12\x36.temporal.api.workflowservice.v1.DescribeWorkerRequest\x1a\x37.temporal.api.workflowservice.v1.DescribeWorkerResponse"\x90\x01\x82\xd3\xe4\x93\x02\x89\x01\x12>/namespaces/{namespace}/workers/describe/{worker_instance_key}ZG\x12\x45/api/v1/namespaces/{namespace}/workers/describe/{worker_instance_key}\x12\x9f\x02\n\x16PauseWorkflowExecution\x12>.temporal.api.workflowservice.v1.PauseWorkflowExecutionRequest\x1a?.temporal.api.workflowservice.v1.PauseWorkflowExecutionResponse"\x83\x01\x82\xd3\xe4\x93\x02}"5/namespaces/{namespace}/workflows/{workflow_id}/pause:\x01*ZA"/api/v1/namespaces/{namespace}/workflows/{workflow_id}/unpause:\x01*\x12\x94\x02\n\x16StartActivityExecution\x12>.temporal.api.workflowservice.v1.StartActivityExecutionRequest\x1a?.temporal.api.workflowservice.v1.StartActivityExecutionResponse"y\x82\xd3\xe4\x93\x02s"0/namespaces/{namespace}/activities/{activity_id}:\x01*Z<"7/api/v1/namespaces/{namespace}/activities/{activity_id}:\x01*\x12\x97\x02\n\x19\x44\x65scribeActivityExecution\x12\x41.temporal.api.workflowservice.v1.DescribeActivityExecutionRequest\x1a\x42.temporal.api.workflowservice.v1.DescribeActivityExecutionResponse"s\x82\xd3\xe4\x93\x02m\x12\x30/namespaces/{namespace}/activities/{activity_id}Z9\x12\x37/api/v1/namespaces/{namespace}/activities/{activity_id}\x12\x9c\x02\n\x15PollActivityExecution\x12=.temporal.api.workflowservice.v1.PollActivityExecutionRequest\x1a>.temporal.api.workflowservice.v1.PollActivityExecutionResponse"\x83\x01\x82\xd3\xe4\x93\x02}\x12\x38/namespaces/{namespace}/activities/{activity_id}/outcomeZA\x12?/api/v1/namespaces/{namespace}/activities/{activity_id}/outcome\x12\xf2\x01\n\x16ListActivityExecutions\x12>.temporal.api.workflowservice.v1.ListActivityExecutionsRequest\x1a?.temporal.api.workflowservice.v1.ListActivityExecutionsResponse"W\x82\xd3\xe4\x93\x02Q\x12"/namespaces/{namespace}/activitiesZ+\x12)/api/v1/namespaces/{namespace}/activities\x12\xfd\x01\n\x17\x43ountActivityExecutions\x12?.temporal.api.workflowservice.v1.CountActivityExecutionsRequest\x1a@.temporal.api.workflowservice.v1.CountActivityExecutionsResponse"_\x82\xd3\xe4\x93\x02Y\x12&/namespaces/{namespace}/activity-countZ/\x12-/api/v1/namespaces/{namespace}/activity-count\x12\xbc\x02\n\x1eRequestCancelActivityExecution\x12\x46.temporal.api.workflowservice.v1.RequestCancelActivityExecutionRequest\x1aG.temporal.api.workflowservice.v1.RequestCancelActivityExecutionResponse"\x88\x01\x82\xd3\xe4\x93\x02\x81\x01"7/namespaces/{namespace}/activities/{activity_id}/cancel:\x01*ZC">/api/v1/namespaces/{namespace}/activities/{activity_id}/cancel:\x01*\x12\xb6\x02\n\x1aTerminateActivityExecution\x12\x42.temporal.api.workflowservice.v1.TerminateActivityExecutionRequest\x1a\x43.temporal.api.workflowservice.v1.TerminateActivityExecutionResponse"\x8e\x01\x82\xd3\xe4\x93\x02\x87\x01":/namespaces/{namespace}/activities/{activity_id}/terminate:\x01*ZF"A/api/v1/namespaces/{namespace}/activities/{activity_id}/terminate:\x01*\x12\x9e\x01\n\x17\x44\x65leteActivityExecution\x12?.temporal.api.workflowservice.v1.DeleteActivityExecutionRequest\x1a@.temporal.api.workflowservice.v1.DeleteActivityExecutionResponse"\x00\x42\xb6\x01\n"io.temporal.api.workflowservice.v1B\x0cServiceProtoP\x01Z5go.temporal.io/api/workflowservice/v1;workflowservice\xaa\x02!Temporalio.Api.WorkflowService.V1\xea\x02$Temporalio::Api::WorkflowService::V1b\x06proto3' + b'\n-temporal/api/workflowservice/v1/service.proto\x12\x1ftemporal.api.workflowservice.v1\x1a\x36temporal/api/workflowservice/v1/request_response.proto\x1a\x1cgoogle/api/annotations.proto\x1a+temporal/api/protometa/v1/annotations.proto2\xfb\xf7\x01\n\x0fWorkflowService\x12\xc3\x01\n\x11RegisterNamespace\x12\x39.temporal.api.workflowservice.v1.RegisterNamespaceRequest\x1a:.temporal.api.workflowservice.v1.RegisterNamespaceResponse"7\x82\xd3\xe4\x93\x02\x31"\x13/cluster/namespaces:\x01*Z\x17"\x12/api/v1/namespaces:\x01*\x12\xd5\x01\n\x11\x44\x65scribeNamespace\x12\x39.temporal.api.workflowservice.v1.DescribeNamespaceRequest\x1a:.temporal.api.workflowservice.v1.DescribeNamespaceResponse"I\x82\xd3\xe4\x93\x02\x43\x12\x1f/cluster/namespaces/{namespace}Z \x12\x1e/api/v1/namespaces/{namespace}\x12\xb4\x01\n\x0eListNamespaces\x12\x36.temporal.api.workflowservice.v1.ListNamespacesRequest\x1a\x37.temporal.api.workflowservice.v1.ListNamespacesResponse"1\x82\xd3\xe4\x93\x02+\x12\x13/cluster/namespacesZ\x14\x12\x12/api/v1/namespaces\x12\xe3\x01\n\x0fUpdateNamespace\x12\x37.temporal.api.workflowservice.v1.UpdateNamespaceRequest\x1a\x38.temporal.api.workflowservice.v1.UpdateNamespaceResponse"]\x82\xd3\xe4\x93\x02W"&/cluster/namespaces/{namespace}/update:\x01*Z*"%/api/v1/namespaces/{namespace}/update:\x01*\x12\x8f\x01\n\x12\x44\x65precateNamespace\x12:.temporal.api.workflowservice.v1.DeprecateNamespaceRequest\x1a;.temporal.api.workflowservice.v1.DeprecateNamespaceResponse"\x00\x12\xc6\x02\n\x16StartWorkflowExecution\x12>.temporal.api.workflowservice.v1.StartWorkflowExecutionRequest\x1a?.temporal.api.workflowservice.v1.StartWorkflowExecutionResponse"\xaa\x01\x82\xd3\xe4\x93\x02q"//namespaces/{namespace}/workflows/{workflow_id}:\x01*Z;"6/api/v1/namespaces/{namespace}/workflows/{workflow_id}:\x01*\x8a\x9d\xcc\x1b.\n\x14temporal-resource-id\x12\x16workflow:{workflow_id}\x12\xcb\x01\n\x15\x45xecuteMultiOperation\x12=.temporal.api.workflowservice.v1.ExecuteMultiOperationRequest\x1a>.temporal.api.workflowservice.v1.ExecuteMultiOperationResponse"3\x8a\x9d\xcc\x1b.\n\x14temporal-resource-id\x12\x16workflow:{resource_id}\x12\xfe\x02\n\x1bGetWorkflowExecutionHistory\x12\x43.temporal.api.workflowservice.v1.GetWorkflowExecutionHistoryRequest\x1a\x44.temporal.api.workflowservice.v1.GetWorkflowExecutionHistoryResponse"\xd3\x01\x82\xd3\xe4\x93\x02\x8f\x01\x12\x41/namespaces/{namespace}/workflows/{execution.workflow_id}/historyZJ\x12H/api/v1/namespaces/{namespace}/workflows/{execution.workflow_id}/history\x8a\x9d\xcc\x1b\x38\n\x14temporal-resource-id\x12 workflow:{execution.workflow_id}\x12\xa3\x03\n"GetWorkflowExecutionHistoryReverse\x12J.temporal.api.workflowservice.v1.GetWorkflowExecutionHistoryReverseRequest\x1aK.temporal.api.workflowservice.v1.GetWorkflowExecutionHistoryReverseResponse"\xe3\x01\x82\xd3\xe4\x93\x02\x9f\x01\x12I/namespaces/{namespace}/workflows/{execution.workflow_id}/history-reverseZR\x12P/api/v1/namespaces/{namespace}/workflows/{execution.workflow_id}/history-reverse\x8a\x9d\xcc\x1b\x38\n\x14temporal-resource-id\x12 workflow:{execution.workflow_id}\x12\x98\x01\n\x15PollWorkflowTaskQueue\x12=.temporal.api.workflowservice.v1.PollWorkflowTaskQueueRequest\x1a>.temporal.api.workflowservice.v1.PollWorkflowTaskQueueResponse"\x00\x12\xe0\x01\n\x1cRespondWorkflowTaskCompleted\x12\x44.temporal.api.workflowservice.v1.RespondWorkflowTaskCompletedRequest\x1a\x45.temporal.api.workflowservice.v1.RespondWorkflowTaskCompletedResponse"3\x8a\x9d\xcc\x1b.\n\x14temporal-resource-id\x12\x16workflow:{resource_id}\x12\xd7\x01\n\x19RespondWorkflowTaskFailed\x12\x41.temporal.api.workflowservice.v1.RespondWorkflowTaskFailedRequest\x1a\x42.temporal.api.workflowservice.v1.RespondWorkflowTaskFailedResponse"3\x8a\x9d\xcc\x1b.\n\x14temporal-resource-id\x12\x16workflow:{resource_id}\x12\x98\x01\n\x15PollActivityTaskQueue\x12=.temporal.api.workflowservice.v1.PollActivityTaskQueueRequest\x1a>.temporal.api.workflowservice.v1.PollActivityTaskQueueResponse"\x00\x12\xc2\x02\n\x1bRecordActivityTaskHeartbeat\x12\x43.temporal.api.workflowservice.v1.RecordActivityTaskHeartbeatRequest\x1a\x44.temporal.api.workflowservice.v1.RecordActivityTaskHeartbeatResponse"\x97\x01\x82\xd3\xe4\x93\x02g"*/namespaces/{namespace}/activity-heartbeat:\x01*Z6"1/api/v1/namespaces/{namespace}/activity-heartbeat:\x01*\x8a\x9d\xcc\x1b%\n\x14temporal-resource-id\x12\r{resource_id}\x12\xa8\x04\n\x1fRecordActivityTaskHeartbeatById\x12G.temporal.api.workflowservice.v1.RecordActivityTaskHeartbeatByIdRequest\x1aH.temporal.api.workflowservice.v1.RecordActivityTaskHeartbeatByIdResponse"\xf1\x02\x82\xd3\xe4\x93\x02\xc0\x02":/namespaces/{namespace}/activities/{activity_id}/heartbeat:\x01*ZF"A/api/v1/namespaces/{namespace}/activities/{activity_id}/heartbeat:\x01*ZW"R/namespaces/{namespace}/workflows/{workflow_id}/activities/{activity_id}/heartbeat:\x01*Z^"Y/api/v1/namespaces/{namespace}/workflows/{workflow_id}/activities/{activity_id}/heartbeat:\x01*\x8a\x9d\xcc\x1b%\n\x14temporal-resource-id\x12\r{resource_id}\x12\xc3\x02\n\x1cRespondActivityTaskCompleted\x12\x44.temporal.api.workflowservice.v1.RespondActivityTaskCompletedRequest\x1a\x45.temporal.api.workflowservice.v1.RespondActivityTaskCompletedResponse"\x95\x01\x82\xd3\xe4\x93\x02\x65")/namespaces/{namespace}/activity-complete:\x01*Z5"0/api/v1/namespaces/{namespace}/activity-complete:\x01*\x8a\x9d\xcc\x1b%\n\x14temporal-resource-id\x12\r{resource_id}\x12\xa7\x04\n RespondActivityTaskCompletedById\x12H.temporal.api.workflowservice.v1.RespondActivityTaskCompletedByIdRequest\x1aI.temporal.api.workflowservice.v1.RespondActivityTaskCompletedByIdResponse"\xed\x02\x82\xd3\xe4\x93\x02\xbc\x02"9/namespaces/{namespace}/activities/{activity_id}/complete:\x01*ZE"@/api/v1/namespaces/{namespace}/activities/{activity_id}/complete:\x01*ZV"Q/namespaces/{namespace}/workflows/{workflow_id}/activities/{activity_id}/complete:\x01*Z]"X/api/v1/namespaces/{namespace}/workflows/{workflow_id}/activities/{activity_id}/complete:\x01*\x8a\x9d\xcc\x1b%\n\x14temporal-resource-id\x12\r{resource_id}\x12\xb2\x02\n\x19RespondActivityTaskFailed\x12\x41.temporal.api.workflowservice.v1.RespondActivityTaskFailedRequest\x1a\x42.temporal.api.workflowservice.v1.RespondActivityTaskFailedResponse"\x8d\x01\x82\xd3\xe4\x93\x02]"%/namespaces/{namespace}/activity-fail:\x01*Z1",/api/v1/namespaces/{namespace}/activity-fail:\x01*\x8a\x9d\xcc\x1b%\n\x14temporal-resource-id\x12\r{resource_id}\x12\x8e\x04\n\x1dRespondActivityTaskFailedById\x12\x45.temporal.api.workflowservice.v1.RespondActivityTaskFailedByIdRequest\x1a\x46.temporal.api.workflowservice.v1.RespondActivityTaskFailedByIdResponse"\xdd\x02\x82\xd3\xe4\x93\x02\xac\x02"5/namespaces/{namespace}/activities/{activity_id}/fail:\x01*ZA".temporal.api.workflowservice.v1.ResetWorkflowExecutionRequest\x1a?.temporal.api.workflowservice.v1.ResetWorkflowExecutionResponse"\xf0\x01\x82\xd3\xe4\x93\x02\xa3\x01"H/namespaces/{namespace}/workflows/{workflow_execution.workflow_id}/reset:\x01*ZT"O/api/v1/namespaces/{namespace}/workflows/{workflow_execution.workflow_id}/reset:\x01*\x8a\x9d\xcc\x1b\x41\n\x14temporal-resource-id\x12)workflow:{workflow_execution.workflow_id}\x12\xa0\x03\n\x1aTerminateWorkflowExecution\x12\x42.temporal.api.workflowservice.v1.TerminateWorkflowExecutionRequest\x1a\x43.temporal.api.workflowservice.v1.TerminateWorkflowExecutionResponse"\xf8\x01\x82\xd3\xe4\x93\x02\xab\x01"L/namespaces/{namespace}/workflows/{workflow_execution.workflow_id}/terminate:\x01*ZX"S/api/v1/namespaces/{namespace}/workflows/{workflow_execution.workflow_id}/terminate:\x01*\x8a\x9d\xcc\x1b\x41\n\x14temporal-resource-id\x12)workflow:{workflow_execution.workflow_id}\x12\xe4\x01\n\x17\x44\x65leteWorkflowExecution\x12?.temporal.api.workflowservice.v1.DeleteWorkflowExecutionRequest\x1a@.temporal.api.workflowservice.v1.DeleteWorkflowExecutionResponse"F\x8a\x9d\xcc\x1b\x41\n\x14temporal-resource-id\x12)workflow:{workflow_execution.workflow_id}\x12\xa7\x01\n\x1aListOpenWorkflowExecutions\x12\x42.temporal.api.workflowservice.v1.ListOpenWorkflowExecutionsRequest\x1a\x43.temporal.api.workflowservice.v1.ListOpenWorkflowExecutionsResponse"\x00\x12\xad\x01\n\x1cListClosedWorkflowExecutions\x12\x44.temporal.api.workflowservice.v1.ListClosedWorkflowExecutionsRequest\x1a\x45.temporal.api.workflowservice.v1.ListClosedWorkflowExecutionsResponse"\x00\x12\xf0\x01\n\x16ListWorkflowExecutions\x12>.temporal.api.workflowservice.v1.ListWorkflowExecutionsRequest\x1a?.temporal.api.workflowservice.v1.ListWorkflowExecutionsResponse"U\x82\xd3\xe4\x93\x02O\x12!/namespaces/{namespace}/workflowsZ*\x12(/api/v1/namespaces/{namespace}/workflows\x12\x9a\x02\n\x1eListArchivedWorkflowExecutions\x12\x46.temporal.api.workflowservice.v1.ListArchivedWorkflowExecutionsRequest\x1aG.temporal.api.workflowservice.v1.ListArchivedWorkflowExecutionsResponse"g\x82\xd3\xe4\x93\x02\x61\x12*/namespaces/{namespace}/archived-workflowsZ3\x12\x31/api/v1/namespaces/{namespace}/archived-workflows\x12\x9b\x01\n\x16ScanWorkflowExecutions\x12>.temporal.api.workflowservice.v1.ScanWorkflowExecutionsRequest\x1a?.temporal.api.workflowservice.v1.ScanWorkflowExecutionsResponse"\x00\x12\xfd\x01\n\x17\x43ountWorkflowExecutions\x12?.temporal.api.workflowservice.v1.CountWorkflowExecutionsRequest\x1a@.temporal.api.workflowservice.v1.CountWorkflowExecutionsResponse"_\x82\xd3\xe4\x93\x02Y\x12&/namespaces/{namespace}/workflow-countZ/\x12-/api/v1/namespaces/{namespace}/workflow-count\x12\x92\x01\n\x13GetSearchAttributes\x12;.temporal.api.workflowservice.v1.GetSearchAttributesRequest\x1a<.temporal.api.workflowservice.v1.GetSearchAttributesResponse"\x00\x12\xa4\x01\n\x19RespondQueryTaskCompleted\x12\x41.temporal.api.workflowservice.v1.RespondQueryTaskCompletedRequest\x1a\x42.temporal.api.workflowservice.v1.RespondQueryTaskCompletedResponse"\x00\x12\xd2\x01\n\x14ResetStickyTaskQueue\x12<.temporal.api.workflowservice.v1.ResetStickyTaskQueueRequest\x1a=.temporal.api.workflowservice.v1.ResetStickyTaskQueueResponse"=\x8a\x9d\xcc\x1b\x38\n\x14temporal-resource-id\x12 workflow:{execution.workflow_id}\x12\x83\x01\n\x0eShutdownWorker\x12\x36.temporal.api.workflowservice.v1.ShutdownWorkerRequest\x1a\x37.temporal.api.workflowservice.v1.ShutdownWorkerResponse"\x00\x12\xfc\x02\n\rQueryWorkflow\x12\x35.temporal.api.workflowservice.v1.QueryWorkflowRequest\x1a\x36.temporal.api.workflowservice.v1.QueryWorkflowResponse"\xfb\x01\x82\xd3\xe4\x93\x02\xb7\x01"R/namespaces/{namespace}/workflows/{execution.workflow_id}/query/{query.query_type}:\x01*Z^"Y/api/v1/namespaces/{namespace}/workflows/{execution.workflow_id}/query/{query.query_type}:\x01*\x8a\x9d\xcc\x1b\x38\n\x14temporal-resource-id\x12 workflow:{execution.workflow_id}\x12\xe7\x02\n\x19\x44\x65scribeWorkflowExecution\x12\x41.temporal.api.workflowservice.v1.DescribeWorkflowExecutionRequest\x1a\x42.temporal.api.workflowservice.v1.DescribeWorkflowExecutionResponse"\xc2\x01\x82\xd3\xe4\x93\x02\x7f\x12\x39/namespaces/{namespace}/workflows/{execution.workflow_id}ZB\x12@/api/v1/namespaces/{namespace}/workflows/{execution.workflow_id}\x8a\x9d\xcc\x1b\x38\n\x14temporal-resource-id\x12 workflow:{execution.workflow_id}\x12\xc2\x02\n\x11\x44\x65scribeTaskQueue\x12\x39.temporal.api.workflowservice.v1.DescribeTaskQueueRequest\x1a:.temporal.api.workflowservice.v1.DescribeTaskQueueResponse"\xb5\x01\x82\xd3\xe4\x93\x02w\x12\x35/namespaces/{namespace}/task-queues/{task_queue.name}Z>\x12/namespaces/{namespace}/schedules/{schedule_id}/matching-timesZG\x12\x45/api/v1/namespaces/{namespace}/schedules/{schedule_id}/matching-times\x8a\x9d\xcc\x1b.\n\x14temporal-resource-id\x12\x16schedule:{schedule_id}\x12\xa8\x02\n\x0e\x44\x65leteSchedule\x12\x36.temporal.api.workflowservice.v1.DeleteScheduleRequest\x1a\x37.temporal.api.workflowservice.v1.DeleteScheduleResponse"\xa4\x01\x82\xd3\xe4\x93\x02k*//namespaces/{namespace}/schedules/{schedule_id}Z8*6/api/v1/namespaces/{namespace}/schedules/{schedule_id}\x8a\x9d\xcc\x1b.\n\x14temporal-resource-id\x12\x16schedule:{schedule_id}\x12\xd5\x01\n\rListSchedules\x12\x35.temporal.api.workflowservice.v1.ListSchedulesRequest\x1a\x36.temporal.api.workflowservice.v1.ListSchedulesResponse"U\x82\xd3\xe4\x93\x02O\x12!/namespaces/{namespace}/schedulesZ*\x12(/api/v1/namespaces/{namespace}/schedules\x12\xe2\x01\n\x0e\x43ountSchedules\x12\x36.temporal.api.workflowservice.v1.CountSchedulesRequest\x1a\x37.temporal.api.workflowservice.v1.CountSchedulesResponse"_\x82\xd3\xe4\x93\x02Y\x12&/namespaces/{namespace}/schedule-countZ/\x12-/api/v1/namespaces/{namespace}/schedule-count\x12\xb9\x01\n UpdateWorkerBuildIdCompatibility\x12H.temporal.api.workflowservice.v1.UpdateWorkerBuildIdCompatibilityRequest\x1aI.temporal.api.workflowservice.v1.UpdateWorkerBuildIdCompatibilityResponse"\x00\x12\xe1\x02\n\x1dGetWorkerBuildIdCompatibility\x12\x45.temporal.api.workflowservice.v1.GetWorkerBuildIdCompatibilityRequest\x1a\x46.temporal.api.workflowservice.v1.GetWorkerBuildIdCompatibilityResponse"\xb0\x01\x82\xd3\xe4\x93\x02\xa9\x01\x12N/namespaces/{namespace}/task-queues/{task_queue}/worker-build-id-compatibilityZW\x12U/api/v1/namespaces/{namespace}/task-queues/{task_queue}/worker-build-id-compatibility\x12\xaa\x01\n\x1bUpdateWorkerVersioningRules\x12\x43.temporal.api.workflowservice.v1.UpdateWorkerVersioningRulesRequest\x1a\x44.temporal.api.workflowservice.v1.UpdateWorkerVersioningRulesResponse"\x00\x12\xc6\x02\n\x18GetWorkerVersioningRules\x12@.temporal.api.workflowservice.v1.GetWorkerVersioningRulesRequest\x1a\x41.temporal.api.workflowservice.v1.GetWorkerVersioningRulesResponse"\xa4\x01\x82\xd3\xe4\x93\x02\x9d\x01\x12H/namespaces/{namespace}/task-queues/{task_queue}/worker-versioning-rulesZQ\x12O/api/v1/namespaces/{namespace}/task-queues/{task_queue}/worker-versioning-rules\x12\x97\x02\n\x19GetWorkerTaskReachability\x12\x41.temporal.api.workflowservice.v1.GetWorkerTaskReachabilityRequest\x1a\x42.temporal.api.workflowservice.v1.GetWorkerTaskReachabilityResponse"s\x82\xd3\xe4\x93\x02m\x12\x30/namespaces/{namespace}/worker-task-reachabilityZ9\x12\x37/api/v1/namespaces/{namespace}/worker-task-reachability\x12\xc8\x02\n\x12\x44\x65scribeDeployment\x12:.temporal.api.workflowservice.v1.DescribeDeploymentRequest\x1a;.temporal.api.workflowservice.v1.DescribeDeploymentResponse"\xb8\x01\x82\xd3\xe4\x93\x02\xb1\x01\x12R/namespaces/{namespace}/deployments/{deployment.series_name}/{deployment.build_id}Z[\x12Y/api/v1/namespaces/{namespace}/deployments/{deployment.series_name}/{deployment.build_id}\x12\x81\x04\n\x1f\x44\x65scribeWorkerDeploymentVersion\x12G.temporal.api.workflowservice.v1.DescribeWorkerDeploymentVersionRequest\x1aH.temporal.api.workflowservice.v1.DescribeWorkerDeploymentVersionResponse"\xca\x02\x82\xd3\xe4\x93\x02\xf7\x01\x12u/namespaces/{namespace}/worker-deployment-versions/{deployment_version.deployment_name}/{deployment_version.build_id}Z~\x12|/api/v1/namespaces/{namespace}/worker-deployment-versions/{deployment_version.deployment_name}/{deployment_version.build_id}\x8a\x9d\xcc\x1bG\n\x14temporal-resource-id\x12/deployment:{deployment_version.deployment_name}\x12\xdf\x01\n\x0fListDeployments\x12\x37.temporal.api.workflowservice.v1.ListDeploymentsRequest\x1a\x38.temporal.api.workflowservice.v1.ListDeploymentsResponse"Y\x82\xd3\xe4\x93\x02S\x12#/namespaces/{namespace}/deploymentsZ,\x12*/api/v1/namespaces/{namespace}/deployments\x12\xf7\x02\n\x19GetDeploymentReachability\x12\x41.temporal.api.workflowservice.v1.GetDeploymentReachabilityRequest\x1a\x42.temporal.api.workflowservice.v1.GetDeploymentReachabilityResponse"\xd2\x01\x82\xd3\xe4\x93\x02\xcb\x01\x12_/namespaces/{namespace}/deployments/{deployment.series_name}/{deployment.build_id}/reachabilityZh\x12\x66/api/v1/namespaces/{namespace}/deployments/{deployment.series_name}/{deployment.build_id}/reachability\x12\x99\x02\n\x14GetCurrentDeployment\x12<.temporal.api.workflowservice.v1.GetCurrentDeploymentRequest\x1a=.temporal.api.workflowservice.v1.GetCurrentDeploymentResponse"\x83\x01\x82\xd3\xe4\x93\x02}\x12\x38/namespaces/{namespace}/current-deployment/{series_name}ZA\x12?/api/v1/namespaces/{namespace}/current-deployment/{series_name}\x12\xb6\x02\n\x14SetCurrentDeployment\x12<.temporal.api.workflowservice.v1.SetCurrentDeploymentRequest\x1a=.temporal.api.workflowservice.v1.SetCurrentDeploymentResponse"\xa0\x01\x82\xd3\xe4\x93\x02\x99\x01"C/namespaces/{namespace}/current-deployment/{deployment.series_name}:\x01*ZO"J/api/v1/namespaces/{namespace}/current-deployment/{deployment.series_name}:\x01*\x12\xb0\x03\n!SetWorkerDeploymentCurrentVersion\x12I.temporal.api.workflowservice.v1.SetWorkerDeploymentCurrentVersionRequest\x1aJ.temporal.api.workflowservice.v1.SetWorkerDeploymentCurrentVersionResponse"\xf3\x01\x82\xd3\xe4\x93\x02\xb3\x01"P/namespaces/{namespace}/worker-deployments/{deployment_name}/set-current-version:\x01*Z\\"W/api/v1/namespaces/{namespace}/worker-deployments/{deployment_name}/set-current-version:\x01*\x8a\x9d\xcc\x1b\x34\n\x14temporal-resource-id\x12\x1c\x64\x65ployment:{deployment_name}\x12\xe7\x02\n\x18\x44\x65scribeWorkerDeployment\x12@.temporal.api.workflowservice.v1.DescribeWorkerDeploymentRequest\x1a\x41.temporal.api.workflowservice.v1.DescribeWorkerDeploymentResponse"\xc5\x01\x82\xd3\xe4\x93\x02\x85\x01\x12.temporal.api.workflowservice.v1.DeleteWorkerDeploymentRequest\x1a?.temporal.api.workflowservice.v1.DeleteWorkerDeploymentResponse"\xc5\x01\x82\xd3\xe4\x93\x02\x85\x01*.temporal.api.workflowservice.v1.ListWorkerDeploymentsResponse"g\x82\xd3\xe4\x93\x02\x61\x12*/namespaces/{namespace}/worker-deploymentsZ3\x12\x31/api/v1/namespaces/{namespace}/worker-deployments\x12\xbc\x04\n%UpdateWorkerDeploymentVersionMetadata\x12M.temporal.api.workflowservice.v1.UpdateWorkerDeploymentVersionMetadataRequest\x1aN.temporal.api.workflowservice.v1.UpdateWorkerDeploymentVersionMetadataResponse"\xf3\x02\x82\xd3\xe4\x93\x02\xa0\x02"\x85\x01/namespaces/{namespace}/worker-deployment-versions/{deployment_version.deployment_name}/{deployment_version.build_id}/update-metadata:\x01*Z\x92\x01"\x8c\x01/api/v1/namespaces/{namespace}/worker-deployment-versions/{deployment_version.deployment_name}/{deployment_version.build_id}/update-metadata:\x01*\x8a\x9d\xcc\x1bG\n\x14temporal-resource-id\x12/deployment:{deployment_version.deployment_name}\x12\x8b\x03\n\x1aSetWorkerDeploymentManager\x12\x42.temporal.api.workflowservice.v1.SetWorkerDeploymentManagerRequest\x1a\x43.temporal.api.workflowservice.v1.SetWorkerDeploymentManagerResponse"\xe3\x01\x82\xd3\xe4\x93\x02\xa3\x01"H/namespaces/{namespace}/worker-deployments/{deployment_name}/set-manager:\x01*ZT"O/api/v1/namespaces/{namespace}/worker-deployments/{deployment_name}/set-manager:\x01*\x8a\x9d\xcc\x1b\x34\n\x14temporal-resource-id\x12\x1c\x64\x65ployment:{deployment_name}\x12\xbb\x03\n\x17UpdateWorkflowExecution\x12?.temporal.api.workflowservice.v1.UpdateWorkflowExecutionRequest\x1a@.temporal.api.workflowservice.v1.UpdateWorkflowExecutionResponse"\x9c\x02\x82\xd3\xe4\x93\x02\xcf\x01"^/namespaces/{namespace}/workflows/{workflow_execution.workflow_id}/update/{request.input.name}:\x01*Zj"e/api/v1/namespaces/{namespace}/workflows/{workflow_execution.workflow_id}/update/{request.input.name}:\x01*\x8a\x9d\xcc\x1b\x41\n\x14temporal-resource-id\x12)workflow:{workflow_execution.workflow_id}\x12\xfb\x01\n\x1bPollWorkflowExecutionUpdate\x12\x43.temporal.api.workflowservice.v1.PollWorkflowExecutionUpdateRequest\x1a\x44.temporal.api.workflowservice.v1.PollWorkflowExecutionUpdateResponse"Q\x8a\x9d\xcc\x1bL\n\x14temporal-resource-id\x12\x34workflow:{update_ref.workflow_execution.workflow_id}\x12\xb9\x02\n\x13StartBatchOperation\x12;.temporal.api.workflowservice.v1.StartBatchOperationRequest\x1a<.temporal.api.workflowservice.v1.StartBatchOperationResponse"\xa6\x01\x82\xd3\xe4\x93\x02u"1/namespaces/{namespace}/batch-operations/{job_id}:\x01*Z="8/api/v1/namespaces/{namespace}/batch-operations/{job_id}:\x01*\x8a\x9d\xcc\x1b&\n\x14temporal-resource-id\x12\x0e\x62\x61tch:{job_id}\x12\xc0\x02\n\x12StopBatchOperation\x12:.temporal.api.workflowservice.v1.StopBatchOperationRequest\x1a;.temporal.api.workflowservice.v1.StopBatchOperationResponse"\xb0\x01\x82\xd3\xe4\x93\x02\x7f"6/namespaces/{namespace}/batch-operations/{job_id}/stop:\x01*ZB"=/api/v1/namespaces/{namespace}/batch-operations/{job_id}/stop:\x01*\x8a\x9d\xcc\x1b&\n\x14temporal-resource-id\x12\x0e\x62\x61tch:{job_id}\x12\xbc\x02\n\x16\x44\x65scribeBatchOperation\x12>.temporal.api.workflowservice.v1.DescribeBatchOperationRequest\x1a?.temporal.api.workflowservice.v1.DescribeBatchOperationResponse"\xa0\x01\x82\xd3\xe4\x93\x02o\x12\x31/namespaces/{namespace}/batch-operations/{job_id}Z:\x12\x38/api/v1/namespaces/{namespace}/batch-operations/{job_id}\x8a\x9d\xcc\x1b&\n\x14temporal-resource-id\x12\x0e\x62\x61tch:{job_id}\x12\xf5\x01\n\x13ListBatchOperations\x12;.temporal.api.workflowservice.v1.ListBatchOperationsRequest\x1a<.temporal.api.workflowservice.v1.ListBatchOperationsResponse"c\x82\xd3\xe4\x93\x02]\x12(/namespaces/{namespace}/batch-operationsZ1\x12//api/v1/namespaces/{namespace}/batch-operations\x12\x8f\x01\n\x12PollNexusTaskQueue\x12:.temporal.api.workflowservice.v1.PollNexusTaskQueueRequest\x1a;.temporal.api.workflowservice.v1.PollNexusTaskQueueResponse"\x00\x12\xa4\x01\n\x19RespondNexusTaskCompleted\x12\x41.temporal.api.workflowservice.v1.RespondNexusTaskCompletedRequest\x1a\x42.temporal.api.workflowservice.v1.RespondNexusTaskCompletedResponse"\x00\x12\x9b\x01\n\x16RespondNexusTaskFailed\x12>.temporal.api.workflowservice.v1.RespondNexusTaskFailedRequest\x1a?.temporal.api.workflowservice.v1.RespondNexusTaskFailedResponse"\x00\x12\xe8\x02\n\x15UpdateActivityOptions\x12=.temporal.api.workflowservice.v1.UpdateActivityOptionsRequest\x1a>.temporal.api.workflowservice.v1.UpdateActivityOptionsResponse"\xcf\x01\x82\xd3\xe4\x93\x02\x8b\x01".temporal.api.workflowservice.v1.RecordWorkerHeartbeatResponse"\x9c\x01\x82\xd3\xe4\x93\x02\x65")/namespaces/{namespace}/workers/heartbeat:\x01*Z5"0/api/v1/namespaces/{namespace}/workers/heartbeat:\x01*\x8a\x9d\xcc\x1b,\n\x14temporal-resource-id\x12\x14worker:{resource_id}\x12\xcb\x01\n\x0bListWorkers\x12\x33.temporal.api.workflowservice.v1.ListWorkersRequest\x1a\x34.temporal.api.workflowservice.v1.ListWorkersResponse"Q\x82\xd3\xe4\x93\x02K\x12\x1f/namespaces/{namespace}/workersZ(\x12&/api/v1/namespaces/{namespace}/workers\x12\xe2\x02\n\x15UpdateTaskQueueConfig\x12=.temporal.api.workflowservice.v1.UpdateTaskQueueConfigRequest\x1a>.temporal.api.workflowservice.v1.UpdateTaskQueueConfigResponse"\xc9\x01\x82\xd3\xe4\x93\x02\x8f\x01">/namespaces/{namespace}/task-queues/{task_queue}/update-config:\x01*ZJ"E/api/v1/namespaces/{namespace}/task-queues/{task_queue}/update-config:\x01*\x8a\x9d\xcc\x1b.\n\x14temporal-resource-id\x12\x16taskqueue:{task_queue}\x12\xaf\x02\n\x11\x46\x65tchWorkerConfig\x12\x39.temporal.api.workflowservice.v1.FetchWorkerConfigRequest\x1a:.temporal.api.workflowservice.v1.FetchWorkerConfigResponse"\xa2\x01\x82\xd3\xe4\x93\x02k",/namespaces/{namespace}/workers/fetch-config:\x01*Z8"3/api/v1/namespaces/{namespace}/workers/fetch-config:\x01*\x8a\x9d\xcc\x1b,\n\x14temporal-resource-id\x12\x14worker:{resource_id}\x12\xb4\x02\n\x12UpdateWorkerConfig\x12:.temporal.api.workflowservice.v1.UpdateWorkerConfigRequest\x1a;.temporal.api.workflowservice.v1.UpdateWorkerConfigResponse"\xa4\x01\x82\xd3\xe4\x93\x02m"-/namespaces/{namespace}/workers/update-config:\x01*Z9"4/api/v1/namespaces/{namespace}/workers/update-config:\x01*\x8a\x9d\xcc\x1b,\n\x14temporal-resource-id\x12\x14worker:{resource_id}\x12\xcd\x02\n\x0e\x44\x65scribeWorker\x12\x36.temporal.api.workflowservice.v1.DescribeWorkerRequest\x1a\x37.temporal.api.workflowservice.v1.DescribeWorkerResponse"\xc9\x01\x82\xd3\xe4\x93\x02\x89\x01\x12>/namespaces/{namespace}/workers/describe/{worker_instance_key}ZG\x12\x45/api/v1/namespaces/{namespace}/workers/describe/{worker_instance_key}\x8a\x9d\xcc\x1b\x34\n\x14temporal-resource-id\x12\x1cworker:{worker_instance_key}\x12\xd2\x02\n\x16PauseWorkflowExecution\x12>.temporal.api.workflowservice.v1.PauseWorkflowExecutionRequest\x1a?.temporal.api.workflowservice.v1.PauseWorkflowExecutionResponse"\xb6\x01\x82\xd3\xe4\x93\x02}"5/namespaces/{namespace}/workflows/{workflow_id}/pause:\x01*ZA"/api/v1/namespaces/{namespace}/workflows/{workflow_id}/unpause:\x01*\x8a\x9d\xcc\x1b.\n\x14temporal-resource-id\x12\x16workflow:{workflow_id}\x12\x94\x02\n\x16StartActivityExecution\x12>.temporal.api.workflowservice.v1.StartActivityExecutionRequest\x1a?.temporal.api.workflowservice.v1.StartActivityExecutionResponse"y\x82\xd3\xe4\x93\x02s"0/namespaces/{namespace}/activities/{activity_id}:\x01*Z<"7/api/v1/namespaces/{namespace}/activities/{activity_id}:\x01*\x12\x97\x02\n\x19\x44\x65scribeActivityExecution\x12\x41.temporal.api.workflowservice.v1.DescribeActivityExecutionRequest\x1a\x42.temporal.api.workflowservice.v1.DescribeActivityExecutionResponse"s\x82\xd3\xe4\x93\x02m\x12\x30/namespaces/{namespace}/activities/{activity_id}Z9\x12\x37/api/v1/namespaces/{namespace}/activities/{activity_id}\x12\x9c\x02\n\x15PollActivityExecution\x12=.temporal.api.workflowservice.v1.PollActivityExecutionRequest\x1a>.temporal.api.workflowservice.v1.PollActivityExecutionResponse"\x83\x01\x82\xd3\xe4\x93\x02}\x12\x38/namespaces/{namespace}/activities/{activity_id}/outcomeZA\x12?/api/v1/namespaces/{namespace}/activities/{activity_id}/outcome\x12\xf2\x01\n\x16ListActivityExecutions\x12>.temporal.api.workflowservice.v1.ListActivityExecutionsRequest\x1a?.temporal.api.workflowservice.v1.ListActivityExecutionsResponse"W\x82\xd3\xe4\x93\x02Q\x12"/namespaces/{namespace}/activitiesZ+\x12)/api/v1/namespaces/{namespace}/activities\x12\xfd\x01\n\x17\x43ountActivityExecutions\x12?.temporal.api.workflowservice.v1.CountActivityExecutionsRequest\x1a@.temporal.api.workflowservice.v1.CountActivityExecutionsResponse"_\x82\xd3\xe4\x93\x02Y\x12&/namespaces/{namespace}/activity-countZ/\x12-/api/v1/namespaces/{namespace}/activity-count\x12\xbc\x02\n\x1eRequestCancelActivityExecution\x12\x46.temporal.api.workflowservice.v1.RequestCancelActivityExecutionRequest\x1aG.temporal.api.workflowservice.v1.RequestCancelActivityExecutionResponse"\x88\x01\x82\xd3\xe4\x93\x02\x81\x01"7/namespaces/{namespace}/activities/{activity_id}/cancel:\x01*ZC">/api/v1/namespaces/{namespace}/activities/{activity_id}/cancel:\x01*\x12\xb6\x02\n\x1aTerminateActivityExecution\x12\x42.temporal.api.workflowservice.v1.TerminateActivityExecutionRequest\x1a\x43.temporal.api.workflowservice.v1.TerminateActivityExecutionResponse"\x8e\x01\x82\xd3\xe4\x93\x02\x87\x01":/namespaces/{namespace}/activities/{activity_id}/terminate:\x01*ZF"A/api/v1/namespaces/{namespace}/activities/{activity_id}/terminate:\x01*\x12\x9e\x01\n\x17\x44\x65leteActivityExecution\x12?.temporal.api.workflowservice.v1.DeleteActivityExecutionRequest\x1a@.temporal.api.workflowservice.v1.DeleteActivityExecutionResponse"\x00\x42\xb6\x01\n"io.temporal.api.workflowservice.v1B\x0cServiceProtoP\x01Z5go.temporal.io/api/workflowservice/v1;workflowservice\xaa\x02!Temporalio.Api.WorkflowService.V1\xea\x02$Temporalio::Api::WorkflowService::V1b\x06proto3' ) @@ -48,69 +51,91 @@ _WORKFLOWSERVICE.methods_by_name["StartWorkflowExecution"]._options = None _WORKFLOWSERVICE.methods_by_name[ "StartWorkflowExecution" - ]._serialized_options = b'\202\323\344\223\002q"//namespaces/{namespace}/workflows/{workflow_id}:\001*Z;"6/api/v1/namespaces/{namespace}/workflows/{workflow_id}:\001*' + ]._serialized_options = b'\202\323\344\223\002q"//namespaces/{namespace}/workflows/{workflow_id}:\001*Z;"6/api/v1/namespaces/{namespace}/workflows/{workflow_id}:\001*\212\235\314\033.\n\024temporal-resource-id\022\026workflow:{workflow_id}' + _WORKFLOWSERVICE.methods_by_name["ExecuteMultiOperation"]._options = None + _WORKFLOWSERVICE.methods_by_name[ + "ExecuteMultiOperation" + ]._serialized_options = ( + b"\212\235\314\033.\n\024temporal-resource-id\022\026workflow:{resource_id}" + ) _WORKFLOWSERVICE.methods_by_name["GetWorkflowExecutionHistory"]._options = None _WORKFLOWSERVICE.methods_by_name[ "GetWorkflowExecutionHistory" - ]._serialized_options = b"\202\323\344\223\002\217\001\022A/namespaces/{namespace}/workflows/{execution.workflow_id}/historyZJ\022H/api/v1/namespaces/{namespace}/workflows/{execution.workflow_id}/history" + ]._serialized_options = b"\202\323\344\223\002\217\001\022A/namespaces/{namespace}/workflows/{execution.workflow_id}/historyZJ\022H/api/v1/namespaces/{namespace}/workflows/{execution.workflow_id}/history\212\235\314\0338\n\024temporal-resource-id\022 workflow:{execution.workflow_id}" _WORKFLOWSERVICE.methods_by_name[ "GetWorkflowExecutionHistoryReverse" ]._options = None _WORKFLOWSERVICE.methods_by_name[ "GetWorkflowExecutionHistoryReverse" - ]._serialized_options = b"\202\323\344\223\002\237\001\022I/namespaces/{namespace}/workflows/{execution.workflow_id}/history-reverseZR\022P/api/v1/namespaces/{namespace}/workflows/{execution.workflow_id}/history-reverse" + ]._serialized_options = b"\202\323\344\223\002\237\001\022I/namespaces/{namespace}/workflows/{execution.workflow_id}/history-reverseZR\022P/api/v1/namespaces/{namespace}/workflows/{execution.workflow_id}/history-reverse\212\235\314\0338\n\024temporal-resource-id\022 workflow:{execution.workflow_id}" + _WORKFLOWSERVICE.methods_by_name["RespondWorkflowTaskCompleted"]._options = None + _WORKFLOWSERVICE.methods_by_name[ + "RespondWorkflowTaskCompleted" + ]._serialized_options = ( + b"\212\235\314\033.\n\024temporal-resource-id\022\026workflow:{resource_id}" + ) + _WORKFLOWSERVICE.methods_by_name["RespondWorkflowTaskFailed"]._options = None + _WORKFLOWSERVICE.methods_by_name[ + "RespondWorkflowTaskFailed" + ]._serialized_options = ( + b"\212\235\314\033.\n\024temporal-resource-id\022\026workflow:{resource_id}" + ) _WORKFLOWSERVICE.methods_by_name["RecordActivityTaskHeartbeat"]._options = None _WORKFLOWSERVICE.methods_by_name[ "RecordActivityTaskHeartbeat" - ]._serialized_options = b'\202\323\344\223\002g"*/namespaces/{namespace}/activity-heartbeat:\001*Z6"1/api/v1/namespaces/{namespace}/activity-heartbeat:\001*' + ]._serialized_options = b'\202\323\344\223\002g"*/namespaces/{namespace}/activity-heartbeat:\001*Z6"1/api/v1/namespaces/{namespace}/activity-heartbeat:\001*\212\235\314\033%\n\024temporal-resource-id\022\r{resource_id}' _WORKFLOWSERVICE.methods_by_name["RecordActivityTaskHeartbeatById"]._options = None _WORKFLOWSERVICE.methods_by_name[ "RecordActivityTaskHeartbeatById" - ]._serialized_options = b'\202\323\344\223\002\300\002":/namespaces/{namespace}/activities/{activity_id}/heartbeat:\001*ZF"A/api/v1/namespaces/{namespace}/activities/{activity_id}/heartbeat:\001*ZW"R/namespaces/{namespace}/workflows/{workflow_id}/activities/{activity_id}/heartbeat:\001*Z^"Y/api/v1/namespaces/{namespace}/workflows/{workflow_id}/activities/{activity_id}/heartbeat:\001*' + ]._serialized_options = b'\202\323\344\223\002\300\002":/namespaces/{namespace}/activities/{activity_id}/heartbeat:\001*ZF"A/api/v1/namespaces/{namespace}/activities/{activity_id}/heartbeat:\001*ZW"R/namespaces/{namespace}/workflows/{workflow_id}/activities/{activity_id}/heartbeat:\001*Z^"Y/api/v1/namespaces/{namespace}/workflows/{workflow_id}/activities/{activity_id}/heartbeat:\001*\212\235\314\033%\n\024temporal-resource-id\022\r{resource_id}' _WORKFLOWSERVICE.methods_by_name["RespondActivityTaskCompleted"]._options = None _WORKFLOWSERVICE.methods_by_name[ "RespondActivityTaskCompleted" - ]._serialized_options = b'\202\323\344\223\002e")/namespaces/{namespace}/activity-complete:\001*Z5"0/api/v1/namespaces/{namespace}/activity-complete:\001*' + ]._serialized_options = b'\202\323\344\223\002e")/namespaces/{namespace}/activity-complete:\001*Z5"0/api/v1/namespaces/{namespace}/activity-complete:\001*\212\235\314\033%\n\024temporal-resource-id\022\r{resource_id}' _WORKFLOWSERVICE.methods_by_name["RespondActivityTaskCompletedById"]._options = None _WORKFLOWSERVICE.methods_by_name[ "RespondActivityTaskCompletedById" - ]._serialized_options = b'\202\323\344\223\002\274\002"9/namespaces/{namespace}/activities/{activity_id}/complete:\001*ZE"@/api/v1/namespaces/{namespace}/activities/{activity_id}/complete:\001*ZV"Q/namespaces/{namespace}/workflows/{workflow_id}/activities/{activity_id}/complete:\001*Z]"X/api/v1/namespaces/{namespace}/workflows/{workflow_id}/activities/{activity_id}/complete:\001*' + ]._serialized_options = b'\202\323\344\223\002\274\002"9/namespaces/{namespace}/activities/{activity_id}/complete:\001*ZE"@/api/v1/namespaces/{namespace}/activities/{activity_id}/complete:\001*ZV"Q/namespaces/{namespace}/workflows/{workflow_id}/activities/{activity_id}/complete:\001*Z]"X/api/v1/namespaces/{namespace}/workflows/{workflow_id}/activities/{activity_id}/complete:\001*\212\235\314\033%\n\024temporal-resource-id\022\r{resource_id}' _WORKFLOWSERVICE.methods_by_name["RespondActivityTaskFailed"]._options = None _WORKFLOWSERVICE.methods_by_name[ "RespondActivityTaskFailed" - ]._serialized_options = b'\202\323\344\223\002]"%/namespaces/{namespace}/activity-fail:\001*Z1",/api/v1/namespaces/{namespace}/activity-fail:\001*' + ]._serialized_options = b'\202\323\344\223\002]"%/namespaces/{namespace}/activity-fail:\001*Z1",/api/v1/namespaces/{namespace}/activity-fail:\001*\212\235\314\033%\n\024temporal-resource-id\022\r{resource_id}' _WORKFLOWSERVICE.methods_by_name["RespondActivityTaskFailedById"]._options = None _WORKFLOWSERVICE.methods_by_name[ "RespondActivityTaskFailedById" - ]._serialized_options = b'\202\323\344\223\002\254\002"5/namespaces/{namespace}/activities/{activity_id}/fail:\001*ZA"\022\022/namespaces/{namespace}/schedules/{schedule_id}/matching-timesZG\022E/api/v1/namespaces/{namespace}/schedules/{schedule_id}/matching-times" + ]._serialized_options = b"\202\323\344\223\002\211\001\022>/namespaces/{namespace}/schedules/{schedule_id}/matching-timesZG\022E/api/v1/namespaces/{namespace}/schedules/{schedule_id}/matching-times\212\235\314\033.\n\024temporal-resource-id\022\026schedule:{schedule_id}" _WORKFLOWSERVICE.methods_by_name["DeleteSchedule"]._options = None _WORKFLOWSERVICE.methods_by_name[ "DeleteSchedule" - ]._serialized_options = b"\202\323\344\223\002k*//namespaces/{namespace}/schedules/{schedule_id}Z8*6/api/v1/namespaces/{namespace}/schedules/{schedule_id}" + ]._serialized_options = b"\202\323\344\223\002k*//namespaces/{namespace}/schedules/{schedule_id}Z8*6/api/v1/namespaces/{namespace}/schedules/{schedule_id}\212\235\314\033.\n\024temporal-resource-id\022\026schedule:{schedule_id}" _WORKFLOWSERVICE.methods_by_name["ListSchedules"]._options = None _WORKFLOWSERVICE.methods_by_name[ "ListSchedules" @@ -198,7 +231,7 @@ _WORKFLOWSERVICE.methods_by_name["DescribeWorkerDeploymentVersion"]._options = None _WORKFLOWSERVICE.methods_by_name[ "DescribeWorkerDeploymentVersion" - ]._serialized_options = b"\202\323\344\223\002\367\001\022u/namespaces/{namespace}/worker-deployment-versions/{deployment_version.deployment_name}/{deployment_version.build_id}Z~\022|/api/v1/namespaces/{namespace}/worker-deployment-versions/{deployment_version.deployment_name}/{deployment_version.build_id}" + ]._serialized_options = b"\202\323\344\223\002\367\001\022u/namespaces/{namespace}/worker-deployment-versions/{deployment_version.deployment_name}/{deployment_version.build_id}Z~\022|/api/v1/namespaces/{namespace}/worker-deployment-versions/{deployment_version.deployment_name}/{deployment_version.build_id}\212\235\314\033G\n\024temporal-resource-id\022/deployment:{deployment_version.deployment_name}" _WORKFLOWSERVICE.methods_by_name["ListDeployments"]._options = None _WORKFLOWSERVICE.methods_by_name[ "ListDeployments" @@ -220,25 +253,25 @@ ]._options = None _WORKFLOWSERVICE.methods_by_name[ "SetWorkerDeploymentCurrentVersion" - ]._serialized_options = b'\202\323\344\223\002\263\001"P/namespaces/{namespace}/worker-deployments/{deployment_name}/set-current-version:\001*Z\\"W/api/v1/namespaces/{namespace}/worker-deployments/{deployment_name}/set-current-version:\001*' + ]._serialized_options = b'\202\323\344\223\002\263\001"P/namespaces/{namespace}/worker-deployments/{deployment_name}/set-current-version:\001*Z\\"W/api/v1/namespaces/{namespace}/worker-deployments/{deployment_name}/set-current-version:\001*\212\235\314\0334\n\024temporal-resource-id\022\034deployment:{deployment_name}' _WORKFLOWSERVICE.methods_by_name["DescribeWorkerDeployment"]._options = None _WORKFLOWSERVICE.methods_by_name[ "DescribeWorkerDeployment" - ]._serialized_options = b"\202\323\344\223\002\205\001\022/namespaces/{namespace}/task-queues/{task_queue}/update-config:\001*ZJ"E/api/v1/namespaces/{namespace}/task-queues/{task_queue}/update-config:\001*' + ]._serialized_options = b'\202\323\344\223\002\217\001">/namespaces/{namespace}/task-queues/{task_queue}/update-config:\001*ZJ"E/api/v1/namespaces/{namespace}/task-queues/{task_queue}/update-config:\001*\212\235\314\033.\n\024temporal-resource-id\022\026taskqueue:{task_queue}' _WORKFLOWSERVICE.methods_by_name["FetchWorkerConfig"]._options = None _WORKFLOWSERVICE.methods_by_name[ "FetchWorkerConfig" - ]._serialized_options = b'\202\323\344\223\002k",/namespaces/{namespace}/workers/fetch-config:\001*Z8"3/api/v1/namespaces/{namespace}/workers/fetch-config:\001*' + ]._serialized_options = b'\202\323\344\223\002k",/namespaces/{namespace}/workers/fetch-config:\001*Z8"3/api/v1/namespaces/{namespace}/workers/fetch-config:\001*\212\235\314\033,\n\024temporal-resource-id\022\024worker:{resource_id}' _WORKFLOWSERVICE.methods_by_name["UpdateWorkerConfig"]._options = None _WORKFLOWSERVICE.methods_by_name[ "UpdateWorkerConfig" - ]._serialized_options = b'\202\323\344\223\002m"-/namespaces/{namespace}/workers/update-config:\001*Z9"4/api/v1/namespaces/{namespace}/workers/update-config:\001*' + ]._serialized_options = b'\202\323\344\223\002m"-/namespaces/{namespace}/workers/update-config:\001*Z9"4/api/v1/namespaces/{namespace}/workers/update-config:\001*\212\235\314\033,\n\024temporal-resource-id\022\024worker:{resource_id}' _WORKFLOWSERVICE.methods_by_name["DescribeWorker"]._options = None _WORKFLOWSERVICE.methods_by_name[ "DescribeWorker" - ]._serialized_options = b"\202\323\344\223\002\211\001\022>/namespaces/{namespace}/workers/describe/{worker_instance_key}ZG\022E/api/v1/namespaces/{namespace}/workers/describe/{worker_instance_key}" + ]._serialized_options = b"\202\323\344\223\002\211\001\022>/namespaces/{namespace}/workers/describe/{worker_instance_key}ZG\022E/api/v1/namespaces/{namespace}/workers/describe/{worker_instance_key}\212\235\314\0334\n\024temporal-resource-id\022\034worker:{worker_instance_key}" _WORKFLOWSERVICE.methods_by_name["PauseWorkflowExecution"]._options = None _WORKFLOWSERVICE.methods_by_name[ "PauseWorkflowExecution" - ]._serialized_options = b'\202\323\344\223\002}"5/namespaces/{namespace}/workflows/{workflow_id}/pause:\001*ZA"/api/v1/namespaces/{namespace}/workflows/{workflow_id}/unpause:\001*' + ]._serialized_options = b'\202\323\344\223\002\201\001"7/namespaces/{namespace}/workflows/{workflow_id}/unpause:\001*ZC">/api/v1/namespaces/{namespace}/workflows/{workflow_id}/unpause:\001*\212\235\314\033.\n\024temporal-resource-id\022\026workflow:{workflow_id}' _WORKFLOWSERVICE.methods_by_name["StartActivityExecution"]._options = None _WORKFLOWSERVICE.methods_by_name[ "StartActivityExecution" @@ -373,6 +410,6 @@ _WORKFLOWSERVICE.methods_by_name[ "TerminateActivityExecution" ]._serialized_options = b'\202\323\344\223\002\207\001":/namespaces/{namespace}/activities/{activity_id}/terminate:\001*ZF"A/api/v1/namespaces/{namespace}/activities/{activity_id}/terminate:\001*' - _WORKFLOWSERVICE._serialized_start = 170 - _WORKFLOWSERVICE._serialized_end = 28766 + _WORKFLOWSERVICE._serialized_start = 215 + _WORKFLOWSERVICE._serialized_end = 31954 # @@protoc_insertion_point(module_scope) diff --git a/temporalio/bridge/Cargo.lock b/temporalio/bridge/Cargo.lock index 85793c0f3..daaa824cc 100644 --- a/temporalio/bridge/Cargo.lock +++ b/temporalio/bridge/Cargo.lock @@ -44,15 +44,6 @@ version = "1.0.99" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b0674a1ddeecb70197781e945de4b3b8ffb61fa939a5597bcf48503737663100" -[[package]] -name = "arbitrary" -version = "1.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3d036a3c4ab069c7b410a2ce876bd74808d2d0888a82667669f8e783a898bf1" -dependencies = [ - "derive_arbitrary", -] - [[package]] name = "async-trait" version = "0.1.89" @@ -76,6 +67,28 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" +[[package]] +name = "aws-lc-rs" +version = "1.16.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a054912289d18629dc78375ba2c3726a3afe3ff71b4edba9dedfca0e3446d1fc" +dependencies = [ + "aws-lc-sys", + "zeroize", +] + +[[package]] +name = "aws-lc-sys" +version = "0.39.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83a25cf98105baa966497416dbd42565ce3a8cf8dbfd59803ec9ad46f3126399" +dependencies = [ + "cc", + "cmake", + "dunce", + "fs_extra", +] + [[package]] name = "axum" version = "0.8.4" @@ -155,9 +168,9 @@ checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" [[package]] name = "bitflags" -version = "2.9.2" +version = "2.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a65b545ab31d687cff52899d4890855fec459eb6afe0da6417b8a18da87aa29" +checksum = "843867be96c8daad0d758b57df9392b6d8d271134fce549de6ce169ff98a92af" [[package]] name = "bon" @@ -207,15 +220,22 @@ dependencies = [ [[package]] name = "cc" -version = "1.2.33" +version = "1.2.59" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ee0f8803222ba5a7e2777dd72ca451868909b1ac410621b676adf07280e9b5f" +checksum = "b7a4d3ec6524d28a329fc53654bbadc9bdd7b0431f5d65f1a56ffb28a1ee5283" dependencies = [ + "find-msvc-tools", "jobserver", "libc", "shlex", ] +[[package]] +name = "cesu8" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d43a04d8753f35258c91f8ec639f792891f748a1edbd759cf1dcea3382ad83c" + [[package]] name = "cfg-if" version = "1.0.1" @@ -228,6 +248,17 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" +[[package]] +name = "chacha20" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f8d983286843e49675a4b7a2d174efe136dc93a18d69130dd18198a6c167601" +dependencies = [ + "cfg-if", + "cpufeatures", + "rand_core 0.10.0", +] + [[package]] name = "chrono" version = "0.4.41" @@ -238,6 +269,25 @@ dependencies = [ "serde", ] +[[package]] +name = "cmake" +version = "0.1.58" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0f78a02292a74a88ac736019ab962ece0bc380e3f977bf72e376c5d78ff0678" +dependencies = [ + "cc", +] + +[[package]] +name = "combine" +version = "4.6.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba5a308b75df32fe02788e748662718f03fde005016435c444eea572398219fd" +dependencies = [ + "bytes", + "memchr", +] + [[package]] name = "core-foundation" version = "0.10.1" @@ -254,6 +304,15 @@ version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" +[[package]] +name = "cpufeatures" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b2a41393f66f16b0823bb79094d54ac5fbd34ab292ddafb9a0456ac9f87d201" +dependencies = [ + "libc", +] + [[package]] name = "crc32fast" version = "1.5.0" @@ -272,15 +331,6 @@ dependencies = [ "crossbeam-utils", ] -[[package]] -name = "crossbeam-queue" -version = "0.3.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f58bbc28f91df819d0aa2a2c00cd19754769c2fad90579b3592b1c9ba7a3115" -dependencies = [ - "crossbeam-utils", -] - [[package]] name = "crossbeam-utils" version = "0.8.21" @@ -336,17 +386,6 @@ dependencies = [ "parking_lot_core", ] -[[package]] -name = "derive_arbitrary" -version = "1.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e567bd82dcff979e4b03460c307b3cdc9e96fde3d73bed1496d2bc75d9dd62a" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - [[package]] name = "derive_more" version = "2.0.1" @@ -406,6 +445,12 @@ version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1435fa1053d8b2fbbe9be7e97eca7f33d37b28409959813daefc1446a14247f1" +[[package]] +name = "dunce" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92773504d58c093f6de2459af4af33faa518c13451eb8f2b5698ed3d36e7c813" + [[package]] name = "dyn-clone" version = "1.0.20" @@ -473,7 +518,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "778e2ac28f6c47af28e4907f13ffd1e1ddbd400980a9abd7c8df189bf578a5ad" dependencies = [ "libc", - "windows-sys 0.52.0", + "windows-sys 0.60.2", ] [[package]] @@ -494,6 +539,12 @@ dependencies = [ "windows-sys 0.59.0", ] +[[package]] +name = "find-msvc-tools" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582" + [[package]] name = "fixedbitset" version = "0.5.7" @@ -544,6 +595,12 @@ version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "28dd6caf6059519a65843af8fe2a3ae298b14b80179855aeb4adc2c1934ee619" +[[package]] +name = "fs_extra" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42703706b716c37f96a77aea830392ad231f44c9e9a67872fa5548707e11b11c" + [[package]] name = "futures" version = "0.3.31" @@ -682,11 +739,25 @@ dependencies = [ "cfg-if", "js-sys", "libc", - "r-efi", + "r-efi 5.3.0", "wasi 0.14.2+wasi-0.2.4", "wasm-bindgen", ] +[[package]] +name = "getrandom" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0de51e6874e94e7bf76d726fc5d13ba782deca734ff60d5bb2fb2607c7406555" +dependencies = [ + "cfg-if", + "libc", + "r-efi 6.0.0", + "rand_core 0.10.0", + "wasip2", + "wasip3", +] + [[package]] name = "gimli" version = "0.31.1" @@ -848,7 +919,6 @@ dependencies = [ "hyper", "hyper-util", "rustls", - "rustls-native-certs", "rustls-pki-types", "tokio", "tokio-rustls", @@ -978,6 +1048,12 @@ dependencies = [ "zerovec", ] +[[package]] +name = "id-arena" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d3067d79b975e8844ca9eb072e16b31c3c1c36928edf9c6789548c524d0d954" + [[package]] name = "ident_case" version = "1.0.1" @@ -1007,12 +1083,14 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.10.0" +version = "2.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe4cd85333e22411419a0bcae1297d25e58c9443848b11dc6a86fefe8c78a661" +checksum = "45a8a2b9cb3e0b0c1803dbb0758ffac5de2f425b23c28f518faabd9d805342ff" dependencies = [ "equivalent", - "hashbrown 0.15.5", + "hashbrown 0.16.1", + "serde", + "serde_core", ] [[package]] @@ -1081,6 +1159,50 @@ version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" +[[package]] +name = "jni" +version = "0.21.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a87aa2bb7d2af34197c04845522473242e1aa17c12f4935d5856491a7fb8c97" +dependencies = [ + "cesu8", + "cfg-if", + "combine", + "jni-sys 0.3.1", + "log", + "thiserror 1.0.69", + "walkdir", + "windows-sys 0.45.0", +] + +[[package]] +name = "jni-sys" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41a652e1f9b6e0275df1f15b32661cf0d4b78d4d87ddec5e0c3c20f097433258" +dependencies = [ + "jni-sys 0.4.1", +] + +[[package]] +name = "jni-sys" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c6377a88cb3910bee9b0fa88d4f42e1d2da8e79915598f65fb0c7ee14c878af2" +dependencies = [ + "jni-sys-macros", +] + +[[package]] +name = "jni-sys-macros" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38c0b942f458fe50cdac086d2f946512305e5631e720728f2a61aabcd47a6264" +dependencies = [ + "quote", + "syn", +] + [[package]] name = "jobserver" version = "0.1.33" @@ -1093,10 +1215,12 @@ dependencies = [ [[package]] name = "js-sys" -version = "0.3.77" +version = "0.3.94" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1cfaf33c695fc6e08064efbc1f72ec937429614f25eef83af942d0e227c3a28f" +checksum = "2e04e2ef80ce82e13552136fabeef8a5ed1f985a96805761cbb9a2c34e7664d9" dependencies = [ + "cfg-if", + "futures-util", "once_cell", "wasm-bindgen", ] @@ -1107,6 +1231,12 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" +[[package]] +name = "leb128fmt" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2" + [[package]] name = "libbz2-rs-sys" version = "0.2.2" @@ -1163,9 +1293,9 @@ dependencies = [ [[package]] name = "log" -version = "0.4.27" +version = "0.4.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94" +checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897" [[package]] name = "lru" @@ -1240,9 +1370,9 @@ dependencies = [ [[package]] name = "mockall" -version = "0.13.1" +version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39a6bfcc6c8c7eed5ee98b9c3e33adc726054389233e201c95dab2d41a3839d2" +checksum = "f58d964098a5f9c6b63d0798e5372fd04708193510a7af313c22e9f29b7b620b" dependencies = [ "cfg-if", "downcast", @@ -1254,9 +1384,9 @@ dependencies = [ [[package]] name = "mockall_derive" -version = "0.13.1" +version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25ca3004c2efe9011bd4e461bd8256445052b9615405b4f7ea43fc8ca5c20898" +checksum = "ca41ce716dda6a9be188b385aa78ee5260fc25cd3802cb2a8afdc6afbe6b6dbf" dependencies = [ "cfg-if", "proc-macro2", @@ -1305,18 +1435,18 @@ dependencies = [ [[package]] name = "objc2-core-foundation" -version = "0.3.1" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c10c2894a6fed806ade6027bcd50662746363a9589d3ec9d9bef30a4e4bc166" +checksum = "2a180dd8642fa45cdb7dd721cd4c11b1cadd4929ce112ebd8b9f5803cc79d536" dependencies = [ "bitflags", ] [[package]] name = "objc2-io-kit" -version = "0.3.1" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "71c1c64d6120e51cd86033f67176b1cb66780c2efe34dec55176f77befd93c0a" +checksum = "33fafba39597d6dc1fb709123dfa8289d39406734be322956a69f0931c73bb15" dependencies = [ "libc", "objc2-core-foundation", @@ -1353,7 +1483,7 @@ dependencies = [ "futures-sink", "js-sys", "pin-project-lite", - "thiserror", + "thiserror 2.0.15", "tracing", ] @@ -1367,14 +1497,14 @@ dependencies = [ "bytes", "http", "opentelemetry", - "reqwest", + "reqwest 0.12.28", ] [[package]] name = "opentelemetry-otlp" -version = "0.31.0" +version = "0.31.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a2366db2dca4d2ad033cad11e6ee42844fd727007af5ad04a1730f4cb8163bf" +checksum = "1f69cd6acbb9af919df949cd1ec9e5e7fdc2ef15d234b6b795aaa525cc02f71f" dependencies = [ "http", "opentelemetry", @@ -1382,8 +1512,8 @@ dependencies = [ "opentelemetry-proto", "opentelemetry_sdk", "prost", - "reqwest", - "thiserror", + "reqwest 0.12.28", + "thiserror 2.0.15", "tokio", "tonic", "tracing", @@ -1414,7 +1544,7 @@ dependencies = [ "opentelemetry", "percent-encoding", "rand 0.9.2", - "thiserror", + "thiserror 2.0.15", "tokio", "tokio-stream", ] @@ -1470,21 +1600,6 @@ dependencies = [ "prost-types", ] -[[package]] -name = "pbjson-types" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a14e2757d877c0f607a82ce1b8560e224370f159d66c5d52eb55ea187ef0350e" -dependencies = [ - "bytes", - "chrono", - "pbjson", - "pbjson-build", - "prost", - "prost-build", - "serde", -] - [[package]] name = "percent-encoding" version = "2.3.1" @@ -1637,7 +1752,7 @@ dependencies = [ "lazy_static", "memchr", "parking_lot", - "thiserror", + "thiserror 2.0.15", ] [[package]] @@ -1876,7 +1991,7 @@ dependencies = [ "rustc-hash", "rustls", "socket2 0.5.10", - "thiserror", + "thiserror 2.0.15", "tokio", "tracing", "web-time", @@ -1888,6 +2003,7 @@ version = "0.11.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "434b42fec591c96ef50e21e886936e66d3cc3f737104fdb9b737c40ffb94c098" dependencies = [ + "aws-lc-rs", "bytes", "getrandom 0.3.3", "lru-slab", @@ -1897,7 +2013,7 @@ dependencies = [ "rustls", "rustls-pki-types", "slab", - "thiserror", + "thiserror 2.0.15", "tinyvec", "tracing", "web-time", @@ -1914,7 +2030,7 @@ dependencies = [ "once_cell", "socket2 0.5.10", "tracing", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -1932,6 +2048,12 @@ version = "5.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" +[[package]] +name = "r-efi" +version = "6.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf" + [[package]] name = "rand" version = "0.8.5" @@ -1953,6 +2075,17 @@ dependencies = [ "rand_core 0.9.3", ] +[[package]] +name = "rand" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc266eb313df6c5c09c1c7b1fbe2510961e5bcd3add930c1e31f7ed9da0feff8" +dependencies = [ + "chacha20", + "getrandom 0.4.2", + "rand_core 0.10.0", +] + [[package]] name = "rand_chacha" version = "0.3.1" @@ -1991,6 +2124,12 @@ dependencies = [ "getrandom 0.3.3", ] +[[package]] +name = "rand_core" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c8d0fd677905edcbeedbf2edb6494d676f0e98d54d5cf9bda0b061cb8fb8aba" + [[package]] name = "raw-cpuid" version = "11.5.0" @@ -2017,7 +2156,7 @@ checksum = "a4e608c6638b9c18977b00b475ac1f28d14e84b27d8d42f70e0bf1e3dec127ac" dependencies = [ "getrandom 0.2.16", "libredox", - "thiserror", + "thiserror 2.0.15", ] [[package]] @@ -2051,9 +2190,9 @@ checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" [[package]] name = "reqwest" -version = "0.12.23" +version = "0.12.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d429f34c8092b2d42c7c93cec323bb4adeb7c67698f70839adec842ec10c7ceb" +checksum = "eddd3ca559203180a307f12d114c268abf583f59b03cb906fd0b3ff8646c1147" dependencies = [ "base64", "bytes", @@ -2064,6 +2203,39 @@ dependencies = [ "http-body", "http-body-util", "hyper", + "hyper-util", + "js-sys", + "log", + "percent-encoding", + "pin-project-lite", + "serde", + "serde_json", + "serde_urlencoded", + "sync_wrapper", + "tokio", + "tower", + "tower-http", + "tower-service", + "url", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", +] + +[[package]] +name = "reqwest" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab3f43e3283ab1488b624b44b0e988d0acea0b3214e694730a055cb6b2efa801" +dependencies = [ + "base64", + "bytes", + "futures-core", + "futures-util", + "http", + "http-body", + "http-body-util", + "hyper", "hyper-rustls", "hyper-util", "js-sys", @@ -2072,8 +2244,8 @@ dependencies = [ "pin-project-lite", "quinn", "rustls", - "rustls-native-certs", "rustls-pki-types", + "rustls-platform-verifier", "serde", "serde_json", "serde_urlencoded", @@ -2138,7 +2310,7 @@ dependencies = [ "errno", "libc", "linux-raw-sys", - "windows-sys 0.52.0", + "windows-sys 0.60.2", ] [[package]] @@ -2147,6 +2319,7 @@ version = "0.23.31" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c0ebcbd2f03de0fc1122ad9bb24b127a5a6cd51d72604a3f3c50ac459762b6cc" dependencies = [ + "aws-lc-rs", "log", "once_cell", "ring", @@ -2178,12 +2351,40 @@ dependencies = [ "zeroize", ] +[[package]] +name = "rustls-platform-verifier" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d99feebc72bae7ab76ba994bb5e121b8d83d910ca40b36e0921f53becc41784" +dependencies = [ + "core-foundation", + "core-foundation-sys", + "jni", + "log", + "once_cell", + "rustls", + "rustls-native-certs", + "rustls-platform-verifier-android", + "rustls-webpki", + "security-framework", + "security-framework-sys", + "webpki-root-certs", + "windows-sys 0.60.2", +] + +[[package]] +name = "rustls-platform-verifier-android" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f87165f0995f63a9fbeea62b64d10b4d9d8e78ec6d7d51fb2125fda7bb36788f" + [[package]] name = "rustls-webpki" version = "0.103.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0a17884ae0c1b773f1ccd2bd4a8c72f16da897310a98b0e84bf349ad5ead92fc" dependencies = [ + "aws-lc-rs", "ring", "rustls-pki-types", "untrusted", @@ -2201,6 +2402,15 @@ version = "1.0.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" +[[package]] +name = "same-file" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", +] + [[package]] name = "schannel" version = "0.1.27" @@ -2218,9 +2428,9 @@ checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] name = "security-framework" -version = "3.3.0" +version = "3.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80fb1d92c5028aa318b4b8bd7302a5bfcf48be96a37fc6fc790f806b0004ee0c" +checksum = "b7f4bc775c73d9a02cde8bf7b2ec4c9d12743edf609006c7facc23998404cd1d" dependencies = [ "bitflags", "core-foundation", @@ -2231,28 +2441,44 @@ dependencies = [ [[package]] name = "security-framework-sys" -version = "2.14.0" +version = "2.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49db231d56a190491cb4aeda9527f1ad45345af50b0851622a7adb8c03b01c32" +checksum = "6ce2691df843ecc5d231c0b14ece2acc3efb62c0a398c7e1d875f3983ce020e3" dependencies = [ "core-foundation-sys", "libc", ] +[[package]] +name = "semver" +version = "1.0.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a7852d02fc848982e0c167ef163aaff9cd91dc640ba85e263cb1ce46fae51cd" + [[package]] name = "serde" -version = "1.0.219" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" +dependencies = [ + "serde_core", + "serde_derive", +] + +[[package]] +name = "serde_core" +version = "1.0.228" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6" +checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.219" +version = "1.0.228" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00" +checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" dependencies = [ "proc-macro2", "quote", @@ -2273,11 +2499,11 @@ dependencies = [ [[package]] name = "serde_spanned" -version = "1.0.0" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40734c41988f7306bb04f0ecf60ec0f3f1caa34290e4e8ea471dcd3346483b83" +checksum = "6662b5879511e06e8999a8a235d848113e942c9124f211511b16466ee2995f26" dependencies = [ - "serde", + "serde_core", ] [[package]] @@ -2429,9 +2655,9 @@ dependencies = [ [[package]] name = "sysinfo" -version = "0.37.0" +version = "0.38.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07cec4dc2d2e357ca1e610cfb07de2fa7a10fc3e9fe89f72545f3d244ea87753" +checksum = "92ab6a2f8bfe508deb3c6406578252e491d299cbbf3bc0529ecc3313aee4a52f" dependencies = [ "libc", "memchr", @@ -2468,7 +2694,7 @@ dependencies = [ "getrandom 0.3.3", "once_cell", "rustix", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -2494,7 +2720,7 @@ dependencies = [ [[package]] name = "temporalio-client" -version = "0.1.0" +version = "0.2.0" dependencies = [ "anyhow", "async-trait", @@ -2511,10 +2737,9 @@ dependencies = [ "hyper", "hyper-util", "parking_lot", - "rand 0.9.2", - "slotmap", + "rand 0.10.0", "temporalio-common", - "thiserror", + "thiserror 2.0.15", "tokio", "tonic", "tower", @@ -2525,7 +2750,7 @@ dependencies = [ [[package]] name = "temporalio-common" -version = "0.1.0" +version = "0.2.0" dependencies = [ "anyhow", "async-trait", @@ -2546,17 +2771,16 @@ dependencies = [ "parking_lot", "pbjson", "pbjson-build", - "pbjson-types", "prometheus", "prost", "prost-types", "prost-wkt", "prost-wkt-types", - "rand 0.9.2", + "rand 0.10.0", "ringbuf", "serde", "serde_json", - "thiserror", + "thiserror 2.0.15", "tokio", "toml", "tonic", @@ -2571,9 +2795,8 @@ dependencies = [ [[package]] name = "temporalio-macros" -version = "0.1.0" +version = "0.2.0" dependencies = [ - "derive_more", "proc-macro2", "quote", "syn", @@ -2581,14 +2804,13 @@ dependencies = [ [[package]] name = "temporalio-sdk-core" -version = "0.1.0" +version = "0.2.0" dependencies = [ "anyhow", "async-trait", "backoff", "bon", "crossbeam-channel", - "crossbeam-queue", "crossbeam-utils", "dashmap", "derive_more", @@ -2602,16 +2824,13 @@ dependencies = [ "itertools", "lru", "mockall", - "opentelemetry", - "opentelemetry-otlp", - "opentelemetry_sdk", "parking_lot", "pid", "pin-project", "prost", "prost-wkt-types", - "rand 0.9.2", - "reqwest", + "rand 0.10.0", + "reqwest 0.13.2", "serde", "serde_json", "siphasher", @@ -2621,7 +2840,7 @@ dependencies = [ "temporalio-client", "temporalio-common", "temporalio-macros", - "thiserror", + "thiserror 2.0.15", "tokio", "tokio-stream", "tokio-util", @@ -2638,13 +2857,33 @@ version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f50febec83f5ee1df3015341d8bd429f2d1cc62bcba7ea2076759d315084683" +[[package]] +name = "thiserror" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" +dependencies = [ + "thiserror-impl 1.0.69", +] + [[package]] name = "thiserror" version = "2.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "80d76d3f064b981389ecb4b6b7f45a0bf9fdac1d5b9204c7bd6714fecc302850" dependencies = [ - "thiserror-impl", + "thiserror-impl 2.0.15", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" +dependencies = [ + "proc-macro2", + "quote", + "syn", ] [[package]] @@ -2759,12 +2998,12 @@ dependencies = [ [[package]] name = "toml" -version = "0.9.5" +version = "1.1.2+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75129e1dc5000bfbaa9fee9d1b21f974f9fbad9daec557a521ee6e080825f6e8" +checksum = "81f3d15e84cbcd896376e6730314d59fb5a87f31e4b038454184435cd57defee" dependencies = [ "indexmap", - "serde", + "serde_core", "serde_spanned", "toml_datetime", "toml_parser", @@ -2774,27 +3013,27 @@ dependencies = [ [[package]] name = "toml_datetime" -version = "0.7.0" +version = "1.1.1+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bade1c3e902f58d73d3f294cd7f20391c1cb2fbcb643b73566bc773971df91e3" +checksum = "3165f65f62e28e0115a00b2ebdd37eb6f3b641855f9d636d3cd4103767159ad7" dependencies = [ - "serde", + "serde_core", ] [[package]] name = "toml_parser" -version = "1.0.2" +version = "1.1.2+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b551886f449aa90d4fe2bdaa9f4a2577ad2dde302c61ecf262d80b116db95c10" +checksum = "a2abe9b86193656635d2411dc43050282ca48aa31c2451210f4202550afb7526" dependencies = [ "winnow", ] [[package]] name = "toml_writer" -version = "1.0.2" +version = "1.1.1+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fcc842091f2def52017664b53082ecbbeb5c7731092bad69d2c63050401dfd64" +checksum = "756daf9b1013ebe47a8776667b466417e2d4c5679d441c26230efd9ef78692db" [[package]] name = "tonic" @@ -2887,9 +3126,9 @@ dependencies = [ [[package]] name = "tower-http" -version = "0.6.6" +version = "0.6.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "adc82fd73de2a9722ac5da747f12383d2bfdb93591ee6c58486e0097890f05f2" +checksum = "d4e6559d53cc268e5031cd8429d05415bc4cb4aefc4aa5d6cc35fbf5b924a1f8" dependencies = [ "bitflags", "bytes", @@ -2970,6 +3209,12 @@ version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" +[[package]] +name = "typed-path" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e28f89b80c87b8fb0cf04ab448d5dd0dd0ade2f8891bae878de66a75a28600e" + [[package]] name = "typeid" version = "1.0.3" @@ -3070,6 +3315,16 @@ version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" +[[package]] +name = "walkdir" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" +dependencies = [ + "same-file", + "winapi-util", +] + [[package]] name = "want" version = "0.3.1" @@ -3095,49 +3350,51 @@ dependencies = [ ] [[package]] -name = "wasm-bindgen" -version = "0.2.100" +name = "wasip2" +version = "1.0.2+wasi-0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1edc8929d7499fc4e8f0be2262a241556cfc54a0bea223790e71446f2aab1ef5" +checksum = "9517f9239f02c069db75e65f174b3da828fe5f5b945c4dd26bd25d89c03ebcf5" dependencies = [ - "cfg-if", - "once_cell", - "rustversion", - "wasm-bindgen-macro", + "wit-bindgen", ] [[package]] -name = "wasm-bindgen-backend" -version = "0.2.100" +name = "wasip3" +version = "0.4.0+wasi-0.3.0-rc-2026-01-06" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f0a0651a5c2bc21487bde11ee802ccaf4c51935d0d3d42a6101f98161700bc6" +checksum = "5428f8bf88ea5ddc08faddef2ac4a67e390b88186c703ce6dbd955e1c145aca5" dependencies = [ - "bumpalo", - "log", - "proc-macro2", - "quote", - "syn", + "wit-bindgen", +] + +[[package]] +name = "wasm-bindgen" +version = "0.2.117" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0551fc1bb415591e3372d0bc4780db7e587d84e2a7e79da121051c5c4b89d0b0" +dependencies = [ + "cfg-if", + "once_cell", + "rustversion", + "wasm-bindgen-macro", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-futures" -version = "0.4.50" +version = "0.4.67" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "555d470ec0bc3bb57890405e5d4322cc9ea83cebb085523ced7be4144dac1e61" +checksum = "03623de6905b7206edd0a75f69f747f134b7f0a2323392d664448bf2d3c5d87e" dependencies = [ - "cfg-if", "js-sys", - "once_cell", "wasm-bindgen", - "web-sys", ] [[package]] name = "wasm-bindgen-macro" -version = "0.2.100" +version = "0.2.117" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fe63fc6d09ed3792bd0897b314f53de8e16568c2b3f7982f468c0bf9bd0b407" +checksum = "7fbdf9a35adf44786aecd5ff89b4563a90325f9da0923236f6104e603c7e86be" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -3145,31 +3402,53 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.100" +version = "0.2.117" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de" +checksum = "dca9693ef2bab6d4e6707234500350d8dad079eb508dca05530c85dc3a529ff2" dependencies = [ + "bumpalo", "proc-macro2", "quote", "syn", - "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.100" +version = "0.2.117" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a05d73b933a847d6cccdda8f838a22ff101ad9bf93e33684f39c1f5f0eece3d" +checksum = "39129a682a6d2d841b6c429d0c51e5cb0ed1a03829d8b3d1e69a011e62cb3d3b" dependencies = [ "unicode-ident", ] +[[package]] +name = "wasm-encoder" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "990065f2fe63003fe337b932cfb5e3b80e0b4d0f5ff650e6985b1048f62c8319" +dependencies = [ + "leb128fmt", + "wasmparser", +] + +[[package]] +name = "wasm-metadata" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb0e353e6a2fbdc176932bbaab493762eb1255a7900fe0fea1a2f96c296cc909" +dependencies = [ + "anyhow", + "indexmap", + "wasm-encoder", + "wasmparser", +] + [[package]] name = "wasm-streams" -version = "0.4.2" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15053d8d85c7eccdbefef60f06769760a563c7f0a9d6902a13d35c7800b0ad65" +checksum = "9d1ec4f6517c9e11ae630e200b2b65d193279042e28edd4a2cda233e46670bbb" dependencies = [ "futures-util", "js-sys", @@ -3178,11 +3457,23 @@ dependencies = [ "web-sys", ] +[[package]] +name = "wasmparser" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47b807c72e1bac69382b3a6fb3dbe8ea4c0ed87ff5629b8685ae6b9a611028fe" +dependencies = [ + "bitflags", + "hashbrown 0.15.5", + "indexmap", + "semver", +] + [[package]] name = "web-sys" -version = "0.3.77" +version = "0.3.94" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33b6dd2ef9186f1f2072e409e99cd22a975331a6b3591b12c764e0e55c60d5d2" +checksum = "cd70027e39b12f0849461e08ffc50b9cd7688d942c1c8e3c7b22273236b4dd0a" dependencies = [ "js-sys", "wasm-bindgen", @@ -3198,6 +3489,15 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "webpki-root-certs" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "804f18a4ac2676ffb4e8b5b5fa9ae38af06df08162314f96a68d2a363e21a8ca" +dependencies = [ + "rustls-pki-types", +] + [[package]] name = "winapi" version = "0.3.9" @@ -3214,6 +3514,15 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" +[[package]] +name = "winapi-util" +version = "0.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" +dependencies = [ + "windows-sys 0.60.2", +] + [[package]] name = "winapi-x86_64-pc-windows-gnu" version = "0.4.0" @@ -3222,55 +3531,54 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] name = "windows" -version = "0.61.3" +version = "0.62.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9babd3a767a4c1aef6900409f85f5d53ce2544ccdfaa86dad48c91782c6d6893" +checksum = "527fadee13e0c05939a6a05d5bd6eec6cd2e3dbd648b9f8e447c6518133d8580" dependencies = [ "windows-collections", "windows-core", "windows-future", - "windows-link", "windows-numerics", ] [[package]] name = "windows-collections" -version = "0.2.0" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3beeceb5e5cfd9eb1d76b381630e82c4241ccd0d27f1a39ed41b2760b255c5e8" +checksum = "23b2d95af1a8a14a3c7367e1ed4fc9c20e0a26e79551b1454d72583c97cc6610" dependencies = [ "windows-core", ] [[package]] name = "windows-core" -version = "0.61.2" +version = "0.62.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0fdd3ddb90610c7638aa2b3a3ab2904fb9e5cdbecc643ddb3647212781c4ae3" +checksum = "b8e83a14d34d0623b51dce9581199302a221863196a1dde71a7663a4c2be9deb" dependencies = [ "windows-implement", "windows-interface", - "windows-link", + "windows-link 0.2.1", "windows-result", "windows-strings", ] [[package]] name = "windows-future" -version = "0.2.1" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc6a41e98427b19fe4b73c550f060b59fa592d7d686537eebf9385621bfbad8e" +checksum = "e1d6f90251fe18a279739e78025bd6ddc52a7e22f921070ccdc67dde84c605cb" dependencies = [ "windows-core", - "windows-link", + "windows-link 0.2.1", "windows-threading", ] [[package]] name = "windows-implement" -version = "0.60.0" +version = "0.60.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a47fddd13af08290e67f4acabf4b459f647552718f683a7b415d290ac744a836" +checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf" dependencies = [ "proc-macro2", "quote", @@ -3279,9 +3587,9 @@ dependencies = [ [[package]] name = "windows-interface" -version = "0.59.1" +version = "0.59.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd9211b69f8dcdfa817bfd14bf1c97c9188afa36f4750130fcdf3f400eca9fa8" +checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358" dependencies = [ "proc-macro2", "quote", @@ -3294,32 +3602,47 @@ version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5e6ad25900d524eaabdbbb96d20b4311e1e7ae1699af4fb28c17ae66c80d798a" +[[package]] +name = "windows-link" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" + [[package]] name = "windows-numerics" -version = "0.2.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9150af68066c4c5c07ddc0ce30421554771e528bde427614c61038bc2c92c2b1" +checksum = "6e2e40844ac143cdb44aead537bbf727de9b044e107a0f1220392177d15b0f26" dependencies = [ "windows-core", - "windows-link", + "windows-link 0.2.1", ] [[package]] name = "windows-result" -version = "0.3.4" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56f42bd332cc6c8eac5af113fc0c1fd6a8fd2aa08a0119358686e5160d0586c6" +checksum = "7781fa89eaf60850ac3d2da7af8e5242a5ea78d1a11c49bf2910bb5a73853eb5" dependencies = [ - "windows-link", + "windows-link 0.2.1", ] [[package]] name = "windows-strings" -version = "0.4.2" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7837d08f69c77cf6b07689544538e017c1bfcf57e34b4c0ff58e6c2cd3b37091" +dependencies = [ + "windows-link 0.2.1", +] + +[[package]] +name = "windows-sys" +version = "0.45.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56e6c93f3a0c3b36176cb1327a4958a0353d5d166c2a35cb268ace15e91d3b57" +checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" dependencies = [ - "windows-link", + "windows-targets 0.42.2", ] [[package]] @@ -3349,6 +3672,21 @@ dependencies = [ "windows-targets 0.53.3", ] +[[package]] +name = "windows-targets" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071" +dependencies = [ + "windows_aarch64_gnullvm 0.42.2", + "windows_aarch64_msvc 0.42.2", + "windows_i686_gnu 0.42.2", + "windows_i686_msvc 0.42.2", + "windows_x86_64_gnu 0.42.2", + "windows_x86_64_gnullvm 0.42.2", + "windows_x86_64_msvc 0.42.2", +] + [[package]] name = "windows-targets" version = "0.52.6" @@ -3371,7 +3709,7 @@ version = "0.53.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d5fe6031c4041849d7c496a8ded650796e7b6ecc19df1a431c1a363342e5dc91" dependencies = [ - "windows-link", + "windows-link 0.1.3", "windows_aarch64_gnullvm 0.53.0", "windows_aarch64_msvc 0.53.0", "windows_i686_gnu 0.53.0", @@ -3384,13 +3722,19 @@ dependencies = [ [[package]] name = "windows-threading" -version = "0.1.0" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b66463ad2e0ea3bbf808b7f1d371311c80e115c0b71d60efc142cafbcfb057a6" +checksum = "3949bd5b99cafdf1c7ca86b43ca564028dfe27d66958f2470940f73d86d75b37" dependencies = [ - "windows-link", + "windows-link 0.2.1", ] +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" + [[package]] name = "windows_aarch64_gnullvm" version = "0.52.6" @@ -3403,6 +3747,12 @@ version = "0.53.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "86b8d5f90ddd19cb4a147a5fa63ca848db3df085e25fee3cc10b39b6eebae764" +[[package]] +name = "windows_aarch64_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" + [[package]] name = "windows_aarch64_msvc" version = "0.52.6" @@ -3415,6 +3765,12 @@ version = "0.53.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c7651a1f62a11b8cbd5e0d42526e55f2c99886c77e007179efff86c2b137e66c" +[[package]] +name = "windows_i686_gnu" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" + [[package]] name = "windows_i686_gnu" version = "0.52.6" @@ -3439,6 +3795,12 @@ version = "0.53.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9ce6ccbdedbf6d6354471319e781c0dfef054c81fbc7cf83f338a4296c0cae11" +[[package]] +name = "windows_i686_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" + [[package]] name = "windows_i686_msvc" version = "0.52.6" @@ -3451,6 +3813,12 @@ version = "0.53.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "581fee95406bb13382d2f65cd4a908ca7b1e4c2f1917f143ba16efe98a589b5d" +[[package]] +name = "windows_x86_64_gnu" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" + [[package]] name = "windows_x86_64_gnu" version = "0.52.6" @@ -3463,6 +3831,12 @@ version = "0.53.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2e55b5ac9ea33f2fc1716d1742db15574fd6fc8dadc51caab1c16a3d3b4190ba" +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" + [[package]] name = "windows_x86_64_gnullvm" version = "0.52.6" @@ -3475,6 +3849,12 @@ version = "0.53.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0a6e035dd0599267ce1ee132e51c27dd29437f63325753051e71dd9e42406c57" +[[package]] +name = "windows_x86_64_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" + [[package]] name = "windows_x86_64_msvc" version = "0.52.6" @@ -3489,9 +3869,29 @@ checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486" [[package]] name = "winnow" -version = "0.7.12" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3edebf492c8125044983378ecb5766203ad3b4c2f7a922bd7dd207f6d443e95" +checksum = "09dac053f1cd375980747450bfc7250c264eaae0583872e845c0c7cd578872b5" + +[[package]] +name = "wit-bindgen" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7249219f66ced02969388cf2bb044a09756a083d0fab1e566056b04d9fbcaa5" +dependencies = [ + "wit-bindgen-rust-macro", +] + +[[package]] +name = "wit-bindgen-core" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea61de684c3ea68cb082b7a88508a8b27fcc8b797d738bfc99a82facf1d752dc" +dependencies = [ + "anyhow", + "heck", + "wit-parser", +] [[package]] name = "wit-bindgen-rt" @@ -3502,6 +3902,74 @@ dependencies = [ "bitflags", ] +[[package]] +name = "wit-bindgen-rust" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7c566e0f4b284dd6561c786d9cb0142da491f46a9fbed79ea69cdad5db17f21" +dependencies = [ + "anyhow", + "heck", + "indexmap", + "prettyplease", + "syn", + "wasm-metadata", + "wit-bindgen-core", + "wit-component", +] + +[[package]] +name = "wit-bindgen-rust-macro" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c0f9bfd77e6a48eccf51359e3ae77140a7f50b1e2ebfe62422d8afdaffab17a" +dependencies = [ + "anyhow", + "prettyplease", + "proc-macro2", + "quote", + "syn", + "wit-bindgen-core", + "wit-bindgen-rust", +] + +[[package]] +name = "wit-component" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d66ea20e9553b30172b5e831994e35fbde2d165325bec84fc43dbf6f4eb9cb2" +dependencies = [ + "anyhow", + "bitflags", + "indexmap", + "log", + "serde", + "serde_derive", + "serde_json", + "wasm-encoder", + "wasm-metadata", + "wasmparser", + "wit-parser", +] + +[[package]] +name = "wit-parser" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ecc8ac4bc1dc3381b7f59c34f00b67e18f910c2c0f50015669dde7def656a736" +dependencies = [ + "anyhow", + "id-arena", + "indexmap", + "log", + "semver", + "serde", + "serde_derive", + "serde_json", + "unicode-xid", + "wasmparser", +] + [[package]] name = "writeable" version = "0.6.1" @@ -3624,16 +4092,16 @@ dependencies = [ [[package]] name = "zip" -version = "4.6.1" +version = "8.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "caa8cd6af31c3b31c6631b8f483848b91589021b28fffe50adada48d4f4d2ed1" +checksum = "2726508a48f38dceb22b35ecbbd2430efe34ff05c62bd3285f965d7911b33464" dependencies = [ - "arbitrary", "bzip2", "crc32fast", "flate2", "indexmap", "memchr", + "typed-path", "zopfli", "zstd", ] @@ -3646,9 +4114,9 @@ checksum = "2f06ae92f42f5e5c42443fd094f245eb656abf56dd7cce9b8b263236565e00f2" [[package]] name = "zopfli" -version = "0.8.2" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "edfc5ee405f504cd4984ecc6f14d02d55cfda60fa4b689434ef4102aae150cd7" +checksum = "f05cd8797d63865425ff89b5c4a48804f35ba0ce8d125800027ad6017d2b5249" dependencies = [ "bumpalo", "crc32fast", diff --git a/temporalio/bridge/Cargo.toml b/temporalio/bridge/Cargo.toml index b2d186b5e..e1d375a76 100644 --- a/temporalio/bridge/Cargo.toml +++ b/temporalio/bridge/Cargo.toml @@ -28,11 +28,11 @@ pyo3 = { version = "0.25", features = [ ] } pyo3-async-runtimes = { version = "0.25", features = ["tokio-runtime"] } pythonize = "0.25" -temporalio-client = { version = "0.1.0", path = "./sdk-core/crates/client" } -temporalio-common = { version = "0.1.0", path = "./sdk-core/crates/common", features = [ - "envconfig", +temporalio-client = { version = "0.2.0", path = "./sdk-core/crates/client" } +temporalio-common = { version = "0.2.0", path = "./sdk-core/crates/common", features = [ + "envconfig", "otel" ]} -temporalio-sdk-core = { version = "0.1.0", path = "./sdk-core/crates/sdk-core", features = [ +temporalio-sdk-core = { version = "0.2.0", path = "./sdk-core/crates/sdk-core", features = [ "ephemeral-server", ] } tokio = "1.26" diff --git a/temporalio/bridge/proto/activity_task/activity_task_pb2.py b/temporalio/bridge/proto/activity_task/activity_task_pb2.py index abb166222..0e09839dc 100644 --- a/temporalio/bridge/proto/activity_task/activity_task_pb2.py +++ b/temporalio/bridge/proto/activity_task/activity_task_pb2.py @@ -26,7 +26,7 @@ ) DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile( - b'\n3temporal/sdk/core/activity_task/activity_task.proto\x12\x15\x63oresdk.activity_task\x1a\x1egoogle/protobuf/duration.proto\x1a\x1fgoogle/protobuf/timestamp.proto\x1a$temporal/api/common/v1/message.proto\x1a%temporal/sdk/core/common/common.proto"\x8d\x01\n\x0c\x41\x63tivityTask\x12\x12\n\ntask_token\x18\x01 \x01(\x0c\x12-\n\x05start\x18\x03 \x01(\x0b\x32\x1c.coresdk.activity_task.StartH\x00\x12/\n\x06\x63\x61ncel\x18\x04 \x01(\x0b\x32\x1d.coresdk.activity_task.CancelH\x00\x42\t\n\x07variant"\xa1\x07\n\x05Start\x12\x1a\n\x12workflow_namespace\x18\x01 \x01(\t\x12\x15\n\rworkflow_type\x18\x02 \x01(\t\x12\x45\n\x12workflow_execution\x18\x03 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x13\n\x0b\x61\x63tivity_id\x18\x04 \x01(\t\x12\x15\n\ractivity_type\x18\x05 \x01(\t\x12\x45\n\rheader_fields\x18\x06 \x03(\x0b\x32..coresdk.activity_task.Start.HeaderFieldsEntry\x12.\n\x05input\x18\x07 \x03(\x0b\x32\x1f.temporal.api.common.v1.Payload\x12:\n\x11heartbeat_details\x18\x08 \x03(\x0b\x32\x1f.temporal.api.common.v1.Payload\x12\x32\n\x0escheduled_time\x18\t \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x42\n\x1e\x63urrent_attempt_scheduled_time\x18\n \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x30\n\x0cstarted_time\x18\x0b \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x0f\n\x07\x61ttempt\x18\x0c \x01(\r\x12<\n\x19schedule_to_close_timeout\x18\r \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x39\n\x16start_to_close_timeout\x18\x0e \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x34\n\x11heartbeat_timeout\x18\x0f \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x39\n\x0cretry_policy\x18\x10 \x01(\x0b\x32#.temporal.api.common.v1.RetryPolicy\x12\x32\n\x08priority\x18\x12 \x01(\x0b\x32 .temporal.api.common.v1.Priority\x12\x10\n\x08is_local\x18\x11 \x01(\x08\x1aT\n\x11HeaderFieldsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12.\n\x05value\x18\x02 \x01(\x0b\x32\x1f.temporal.api.common.v1.Payload:\x02\x38\x01"\x8a\x01\n\x06\x43\x61ncel\x12;\n\x06reason\x18\x01 \x01(\x0e\x32+.coresdk.activity_task.ActivityCancelReason\x12\x43\n\x07\x64\x65tails\x18\x02 \x01(\x0b\x32\x32.coresdk.activity_task.ActivityCancellationDetails"\xa0\x01\n\x1b\x41\x63tivityCancellationDetails\x12\x14\n\x0cis_not_found\x18\x01 \x01(\x08\x12\x14\n\x0cis_cancelled\x18\x02 \x01(\x08\x12\x11\n\tis_paused\x18\x03 \x01(\x08\x12\x14\n\x0cis_timed_out\x18\x04 \x01(\x08\x12\x1a\n\x12is_worker_shutdown\x18\x05 \x01(\x08\x12\x10\n\x08is_reset\x18\x06 \x01(\x08*o\n\x14\x41\x63tivityCancelReason\x12\r\n\tNOT_FOUND\x10\x00\x12\r\n\tCANCELLED\x10\x01\x12\r\n\tTIMED_OUT\x10\x02\x12\x13\n\x0fWORKER_SHUTDOWN\x10\x03\x12\n\n\x06PAUSED\x10\x04\x12\t\n\x05RESET\x10\x05\x42\x32\xea\x02/Temporalio::Internal::Bridge::Api::ActivityTaskb\x06proto3' + b'\n3temporal/sdk/core/activity_task/activity_task.proto\x12\x15\x63oresdk.activity_task\x1a\x1egoogle/protobuf/duration.proto\x1a\x1fgoogle/protobuf/timestamp.proto\x1a$temporal/api/common/v1/message.proto\x1a%temporal/sdk/core/common/common.proto"\x8d\x01\n\x0c\x41\x63tivityTask\x12\x12\n\ntask_token\x18\x01 \x01(\x0c\x12-\n\x05start\x18\x03 \x01(\x0b\x32\x1c.coresdk.activity_task.StartH\x00\x12/\n\x06\x63\x61ncel\x18\x04 \x01(\x0b\x32\x1d.coresdk.activity_task.CancelH\x00\x42\t\n\x07variant"\xb1\x07\n\x05Start\x12\x1a\n\x12workflow_namespace\x18\x01 \x01(\t\x12\x15\n\rworkflow_type\x18\x02 \x01(\t\x12\x45\n\x12workflow_execution\x18\x03 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x13\n\x0b\x61\x63tivity_id\x18\x04 \x01(\t\x12\x15\n\ractivity_type\x18\x05 \x01(\t\x12\x45\n\rheader_fields\x18\x06 \x03(\x0b\x32..coresdk.activity_task.Start.HeaderFieldsEntry\x12.\n\x05input\x18\x07 \x03(\x0b\x32\x1f.temporal.api.common.v1.Payload\x12:\n\x11heartbeat_details\x18\x08 \x03(\x0b\x32\x1f.temporal.api.common.v1.Payload\x12\x32\n\x0escheduled_time\x18\t \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x42\n\x1e\x63urrent_attempt_scheduled_time\x18\n \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x30\n\x0cstarted_time\x18\x0b \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x0f\n\x07\x61ttempt\x18\x0c \x01(\r\x12<\n\x19schedule_to_close_timeout\x18\r \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x39\n\x16start_to_close_timeout\x18\x0e \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x34\n\x11heartbeat_timeout\x18\x0f \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x39\n\x0cretry_policy\x18\x10 \x01(\x0b\x32#.temporal.api.common.v1.RetryPolicy\x12\x32\n\x08priority\x18\x12 \x01(\x0b\x32 .temporal.api.common.v1.Priority\x12\x10\n\x08is_local\x18\x11 \x01(\x08\x12\x0e\n\x06run_id\x18\x13 \x01(\t\x1aT\n\x11HeaderFieldsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12.\n\x05value\x18\x02 \x01(\x0b\x32\x1f.temporal.api.common.v1.Payload:\x02\x38\x01"\x8a\x01\n\x06\x43\x61ncel\x12;\n\x06reason\x18\x01 \x01(\x0e\x32+.coresdk.activity_task.ActivityCancelReason\x12\x43\n\x07\x64\x65tails\x18\x02 \x01(\x0b\x32\x32.coresdk.activity_task.ActivityCancellationDetails"\xa0\x01\n\x1b\x41\x63tivityCancellationDetails\x12\x14\n\x0cis_not_found\x18\x01 \x01(\x08\x12\x14\n\x0cis_cancelled\x18\x02 \x01(\x08\x12\x11\n\tis_paused\x18\x03 \x01(\x08\x12\x14\n\x0cis_timed_out\x18\x04 \x01(\x08\x12\x1a\n\x12is_worker_shutdown\x18\x05 \x01(\x08\x12\x10\n\x08is_reset\x18\x06 \x01(\x08*o\n\x14\x41\x63tivityCancelReason\x12\r\n\tNOT_FOUND\x10\x00\x12\r\n\tCANCELLED\x10\x01\x12\r\n\tTIMED_OUT\x10\x02\x12\x13\n\x0fWORKER_SHUTDOWN\x10\x03\x12\n\n\x06PAUSED\x10\x04\x12\t\n\x05RESET\x10\x05\x42\x32\xea\x02/Temporalio::Internal::Bridge::Api::ActivityTaskb\x06proto3' ) _ACTIVITYCANCELREASON = DESCRIPTOR.enum_types_by_name["ActivityCancelReason"] @@ -107,16 +107,16 @@ ) _START_HEADERFIELDSENTRY._options = None _START_HEADERFIELDSENTRY._serialized_options = b"8\001" - _ACTIVITYCANCELREASON._serialized_start = 1600 - _ACTIVITYCANCELREASON._serialized_end = 1711 + _ACTIVITYCANCELREASON._serialized_start = 1616 + _ACTIVITYCANCELREASON._serialized_end = 1727 _ACTIVITYTASK._serialized_start = 221 _ACTIVITYTASK._serialized_end = 362 _START._serialized_start = 365 - _START._serialized_end = 1294 - _START_HEADERFIELDSENTRY._serialized_start = 1210 - _START_HEADERFIELDSENTRY._serialized_end = 1294 - _CANCEL._serialized_start = 1297 - _CANCEL._serialized_end = 1435 - _ACTIVITYCANCELLATIONDETAILS._serialized_start = 1438 - _ACTIVITYCANCELLATIONDETAILS._serialized_end = 1598 + _START._serialized_end = 1310 + _START_HEADERFIELDSENTRY._serialized_start = 1226 + _START_HEADERFIELDSENTRY._serialized_end = 1310 + _CANCEL._serialized_start = 1313 + _CANCEL._serialized_end = 1451 + _ACTIVITYCANCELLATIONDETAILS._serialized_start = 1454 + _ACTIVITYCANCELLATIONDETAILS._serialized_end = 1614 # @@protoc_insertion_point(module_scope) diff --git a/temporalio/bridge/proto/activity_task/activity_task_pb2.pyi b/temporalio/bridge/proto/activity_task/activity_task_pb2.pyi index 6d977759c..1a2f8c7d2 100644 --- a/temporalio/bridge/proto/activity_task/activity_task_pb2.pyi +++ b/temporalio/bridge/proto/activity_task/activity_task_pb2.pyi @@ -159,6 +159,7 @@ class Start(google.protobuf.message.Message): RETRY_POLICY_FIELD_NUMBER: builtins.int PRIORITY_FIELD_NUMBER: builtins.int IS_LOCAL_FIELD_NUMBER: builtins.int + RUN_ID_FIELD_NUMBER: builtins.int workflow_namespace: builtins.str """The namespace the workflow lives in""" workflow_type: builtins.str @@ -224,6 +225,8 @@ class Start(google.protobuf.message.Message): """Set to true if this is a local activity. Note that heartbeating does not apply to local activities. """ + run_id: builtins.str + """Run ID of this activity execution. Only set for standalone activities.""" def __init__( self, *, @@ -254,6 +257,7 @@ class Start(google.protobuf.message.Message): retry_policy: temporalio.api.common.v1.message_pb2.RetryPolicy | None = ..., priority: temporalio.api.common.v1.message_pb2.Priority | None = ..., is_local: builtins.bool = ..., + run_id: builtins.str = ..., ) -> None: ... def HasField( self, @@ -303,6 +307,8 @@ class Start(google.protobuf.message.Message): b"priority", "retry_policy", b"retry_policy", + "run_id", + b"run_id", "schedule_to_close_timeout", b"schedule_to_close_timeout", "scheduled_time", diff --git a/temporalio/bridge/sdk-core b/temporalio/bridge/sdk-core index f188eb531..71a5caa57 160000 --- a/temporalio/bridge/sdk-core +++ b/temporalio/bridge/sdk-core @@ -1 +1 @@ -Subproject commit f188eb5319fb44093e40208471d28946763c777a +Subproject commit 71a5caa57118848bd60843dd7fa867ed73704108 diff --git a/temporalio/bridge/services_generated.py b/temporalio/bridge/services_generated.py index e70c0a7cc..b503aaff0 100644 --- a/temporalio/bridge/services_generated.py +++ b/temporalio/bridge/services_generated.py @@ -2189,6 +2189,24 @@ async def add_user_group_member( timeout=timeout, ) + async def create_account_audit_log_sink( + self, + req: temporalio.api.cloud.cloudservice.v1.CreateAccountAuditLogSinkRequest, + retry: bool = False, + metadata: Mapping[str, str | bytes] = {}, + timeout: timedelta | None = None, + ) -> temporalio.api.cloud.cloudservice.v1.CreateAccountAuditLogSinkResponse: + """Invokes the CloudService.create_account_audit_log_sink rpc method.""" + return await self._client._rpc_call( + rpc="create_account_audit_log_sink", + req=req, + service=self._service, + resp_type=temporalio.api.cloud.cloudservice.v1.CreateAccountAuditLogSinkResponse, + retry=retry, + metadata=metadata, + timeout=timeout, + ) + async def create_api_key( self, req: temporalio.api.cloud.cloudservice.v1.CreateApiKeyRequest, @@ -2207,6 +2225,24 @@ async def create_api_key( timeout=timeout, ) + async def create_billing_report( + self, + req: temporalio.api.cloud.cloudservice.v1.CreateBillingReportRequest, + retry: bool = False, + metadata: Mapping[str, str | bytes] = {}, + timeout: timedelta | None = None, + ) -> temporalio.api.cloud.cloudservice.v1.CreateBillingReportResponse: + """Invokes the CloudService.create_billing_report rpc method.""" + return await self._client._rpc_call( + rpc="create_billing_report", + req=req, + service=self._service, + resp_type=temporalio.api.cloud.cloudservice.v1.CreateBillingReportResponse, + retry=retry, + metadata=metadata, + timeout=timeout, + ) + async def create_connectivity_rule( self, req: temporalio.api.cloud.cloudservice.v1.CreateConnectivityRuleRequest, @@ -2333,6 +2369,24 @@ async def create_user_group( timeout=timeout, ) + async def delete_account_audit_log_sink( + self, + req: temporalio.api.cloud.cloudservice.v1.DeleteAccountAuditLogSinkRequest, + retry: bool = False, + metadata: Mapping[str, str | bytes] = {}, + timeout: timedelta | None = None, + ) -> temporalio.api.cloud.cloudservice.v1.DeleteAccountAuditLogSinkResponse: + """Invokes the CloudService.delete_account_audit_log_sink rpc method.""" + return await self._client._rpc_call( + rpc="delete_account_audit_log_sink", + req=req, + service=self._service, + resp_type=temporalio.api.cloud.cloudservice.v1.DeleteAccountAuditLogSinkResponse, + retry=retry, + metadata=metadata, + timeout=timeout, + ) + async def delete_api_key( self, req: temporalio.api.cloud.cloudservice.v1.DeleteApiKeyRequest, @@ -2531,6 +2585,42 @@ async def get_account( timeout=timeout, ) + async def get_account_audit_log_sink( + self, + req: temporalio.api.cloud.cloudservice.v1.GetAccountAuditLogSinkRequest, + retry: bool = False, + metadata: Mapping[str, str | bytes] = {}, + timeout: timedelta | None = None, + ) -> temporalio.api.cloud.cloudservice.v1.GetAccountAuditLogSinkResponse: + """Invokes the CloudService.get_account_audit_log_sink rpc method.""" + return await self._client._rpc_call( + rpc="get_account_audit_log_sink", + req=req, + service=self._service, + resp_type=temporalio.api.cloud.cloudservice.v1.GetAccountAuditLogSinkResponse, + retry=retry, + metadata=metadata, + timeout=timeout, + ) + + async def get_account_audit_log_sinks( + self, + req: temporalio.api.cloud.cloudservice.v1.GetAccountAuditLogSinksRequest, + retry: bool = False, + metadata: Mapping[str, str | bytes] = {}, + timeout: timedelta | None = None, + ) -> temporalio.api.cloud.cloudservice.v1.GetAccountAuditLogSinksResponse: + """Invokes the CloudService.get_account_audit_log_sinks rpc method.""" + return await self._client._rpc_call( + rpc="get_account_audit_log_sinks", + req=req, + service=self._service, + resp_type=temporalio.api.cloud.cloudservice.v1.GetAccountAuditLogSinksResponse, + retry=retry, + metadata=metadata, + timeout=timeout, + ) + async def get_api_key( self, req: temporalio.api.cloud.cloudservice.v1.GetApiKeyRequest, @@ -2585,6 +2675,42 @@ async def get_async_operation( timeout=timeout, ) + async def get_audit_logs( + self, + req: temporalio.api.cloud.cloudservice.v1.GetAuditLogsRequest, + retry: bool = False, + metadata: Mapping[str, str | bytes] = {}, + timeout: timedelta | None = None, + ) -> temporalio.api.cloud.cloudservice.v1.GetAuditLogsResponse: + """Invokes the CloudService.get_audit_logs rpc method.""" + return await self._client._rpc_call( + rpc="get_audit_logs", + req=req, + service=self._service, + resp_type=temporalio.api.cloud.cloudservice.v1.GetAuditLogsResponse, + retry=retry, + metadata=metadata, + timeout=timeout, + ) + + async def get_billing_report( + self, + req: temporalio.api.cloud.cloudservice.v1.GetBillingReportRequest, + retry: bool = False, + metadata: Mapping[str, str | bytes] = {}, + timeout: timedelta | None = None, + ) -> temporalio.api.cloud.cloudservice.v1.GetBillingReportResponse: + """Invokes the CloudService.get_billing_report rpc method.""" + return await self._client._rpc_call( + rpc="get_billing_report", + req=req, + service=self._service, + resp_type=temporalio.api.cloud.cloudservice.v1.GetBillingReportResponse, + retry=retry, + metadata=metadata, + timeout=timeout, + ) + async def get_connectivity_rule( self, req: temporalio.api.cloud.cloudservice.v1.GetConnectivityRuleRequest, @@ -2621,6 +2747,24 @@ async def get_connectivity_rules( timeout=timeout, ) + async def get_current_identity( + self, + req: temporalio.api.cloud.cloudservice.v1.GetCurrentIdentityRequest, + retry: bool = False, + metadata: Mapping[str, str | bytes] = {}, + timeout: timedelta | None = None, + ) -> temporalio.api.cloud.cloudservice.v1.GetCurrentIdentityResponse: + """Invokes the CloudService.get_current_identity rpc method.""" + return await self._client._rpc_call( + rpc="get_current_identity", + req=req, + service=self._service, + resp_type=temporalio.api.cloud.cloudservice.v1.GetCurrentIdentityResponse, + retry=retry, + metadata=metadata, + timeout=timeout, + ) + async def get_namespace( self, req: temporalio.api.cloud.cloudservice.v1.GetNamespaceRequest, @@ -2639,6 +2783,24 @@ async def get_namespace( timeout=timeout, ) + async def get_namespace_capacity_info( + self, + req: temporalio.api.cloud.cloudservice.v1.GetNamespaceCapacityInfoRequest, + retry: bool = False, + metadata: Mapping[str, str | bytes] = {}, + timeout: timedelta | None = None, + ) -> temporalio.api.cloud.cloudservice.v1.GetNamespaceCapacityInfoResponse: + """Invokes the CloudService.get_namespace_capacity_info rpc method.""" + return await self._client._rpc_call( + rpc="get_namespace_capacity_info", + req=req, + service=self._service, + resp_type=temporalio.api.cloud.cloudservice.v1.GetNamespaceCapacityInfoResponse, + retry=retry, + metadata=metadata, + timeout=timeout, + ) + async def get_namespace_export_sink( self, req: temporalio.api.cloud.cloudservice.v1.GetNamespaceExportSinkRequest, @@ -3017,6 +3179,24 @@ async def update_account( timeout=timeout, ) + async def update_account_audit_log_sink( + self, + req: temporalio.api.cloud.cloudservice.v1.UpdateAccountAuditLogSinkRequest, + retry: bool = False, + metadata: Mapping[str, str | bytes] = {}, + timeout: timedelta | None = None, + ) -> temporalio.api.cloud.cloudservice.v1.UpdateAccountAuditLogSinkResponse: + """Invokes the CloudService.update_account_audit_log_sink rpc method.""" + return await self._client._rpc_call( + rpc="update_account_audit_log_sink", + req=req, + service=self._service, + resp_type=temporalio.api.cloud.cloudservice.v1.UpdateAccountAuditLogSinkResponse, + retry=retry, + metadata=metadata, + timeout=timeout, + ) + async def update_api_key( self, req: temporalio.api.cloud.cloudservice.v1.UpdateApiKeyRequest, diff --git a/temporalio/bridge/src/client_rpc_generated.rs b/temporalio/bridge/src/client_rpc_generated.rs index b3321da8b..8c952e54d 100644 --- a/temporalio/bridge/src/client_rpc_generated.rs +++ b/temporalio/bridge/src/client_rpc_generated.rs @@ -1129,6 +1129,15 @@ impl ClientRef { add_user_group_member ) } + "create_account_audit_log_sink" => { + rpc_call!( + connection, + call, + CloudService, + cloud_service, + create_account_audit_log_sink + ) + } "create_api_key" => { rpc_call!( connection, @@ -1138,6 +1147,15 @@ impl ClientRef { create_api_key ) } + "create_billing_report" => { + rpc_call!( + connection, + call, + CloudService, + cloud_service, + create_billing_report + ) + } "create_connectivity_rule" => { rpc_call!( connection, @@ -1195,6 +1213,15 @@ impl ClientRef { create_user_group ) } + "delete_account_audit_log_sink" => { + rpc_call!( + connection, + call, + CloudService, + cloud_service, + delete_account_audit_log_sink + ) + } "delete_api_key" => { rpc_call!( connection, @@ -1282,6 +1309,24 @@ impl ClientRef { "get_account" => { rpc_call!(connection, call, CloudService, cloud_service, get_account) } + "get_account_audit_log_sink" => { + rpc_call!( + connection, + call, + CloudService, + cloud_service, + get_account_audit_log_sink + ) + } + "get_account_audit_log_sinks" => { + rpc_call!( + connection, + call, + CloudService, + cloud_service, + get_account_audit_log_sinks + ) + } "get_api_key" => { rpc_call!(connection, call, CloudService, cloud_service, get_api_key) } @@ -1297,6 +1342,24 @@ impl ClientRef { get_async_operation ) } + "get_audit_logs" => { + rpc_call!( + connection, + call, + CloudService, + cloud_service, + get_audit_logs + ) + } + "get_billing_report" => { + rpc_call!( + connection, + call, + CloudService, + cloud_service, + get_billing_report + ) + } "get_connectivity_rule" => { rpc_call!( connection, @@ -1315,9 +1378,27 @@ impl ClientRef { get_connectivity_rules ) } + "get_current_identity" => { + rpc_call!( + connection, + call, + CloudService, + cloud_service, + get_current_identity + ) + } "get_namespace" => { rpc_call!(connection, call, CloudService, cloud_service, get_namespace) } + "get_namespace_capacity_info" => { + rpc_call!( + connection, + call, + CloudService, + cloud_service, + get_namespace_capacity_info + ) + } "get_namespace_export_sink" => { rpc_call!( connection, @@ -1477,6 +1558,15 @@ impl ClientRef { update_account ) } + "update_account_audit_log_sink" => { + rpc_call!( + connection, + call, + CloudService, + cloud_service, + update_account_audit_log_sink + ) + } "update_api_key" => { rpc_call!( connection, diff --git a/temporalio/bridge/src/metric.rs b/temporalio/bridge/src/metric.rs index 733bd63f2..445adfea9 100644 --- a/temporalio/bridge/src/metric.rs +++ b/temporalio/bridge/src/metric.rs @@ -268,6 +268,7 @@ pub enum BufferedMetricUpdateValue { U64(u64), U128(u128), F64(f64), + I64(i64), } // WARNING: This must match temporalio.runtime.BufferedMetric protocol @@ -348,6 +349,7 @@ fn convert_metric_event( metrics::core::MetricKind::Histogram | metrics::core::MetricKind::HistogramF64 | metrics::core::MetricKind::HistogramDuration => 2, + metrics::core::MetricKind::UpDownCounter => 3, }, }, ) @@ -412,6 +414,7 @@ fn convert_metric_event( metrics::core::MetricUpdateVal::DeltaF64(v) => BufferedMetricUpdateValue::F64(v), metrics::core::MetricUpdateVal::Value(v) => BufferedMetricUpdateValue::U64(v), metrics::core::MetricUpdateVal::ValueF64(v) => BufferedMetricUpdateValue::F64(v), + metrics::core::MetricUpdateVal::SignedDelta(v) => BufferedMetricUpdateValue::I64(v), }, attributes: attributes .get() diff --git a/temporalio/bridge/src/worker.rs b/temporalio/bridge/src/worker.rs index a676e3338..4820fd843 100644 --- a/temporalio/bridge/src/worker.rs +++ b/temporalio/bridge/src/worker.rs @@ -892,12 +892,16 @@ fn convert_versioning_strategy( build_id: options.version.build_id, }, use_worker_versioning: options.use_worker_versioning, - default_versioning_behavior: Some( - options - .default_versioning_behavior - .try_into() - .unwrap_or_default(), - ), + default_versioning_behavior: if options.use_worker_versioning { + Some( + options + .default_versioning_behavior + .try_into() + .unwrap_or_default(), + ) + } else { + None + }, }, ) } diff --git a/uv.lock b/uv.lock index c63faefad..f1b27b400 100644 --- a/uv.lock +++ b/uv.lock @@ -4857,7 +4857,7 @@ requires-dist = [ { name = "pydantic", marker = "extra == 'pydantic'", specifier = ">=2.0.0,<3" }, { name = "python-dateutil", marker = "python_full_version < '3.11'", specifier = ">=2.8.2,<3" }, { name = "types-aioboto3", extras = ["s3"], marker = "extra == 'aioboto3'", specifier = ">=10.4.0" }, - { name = "types-protobuf", specifier = ">=3.20" }, + { name = "types-protobuf", specifier = ">=3.20,<7.0.0" }, { name = "typing-extensions", specifier = ">=4.2.0,<5" }, ] provides-extras = ["grpc", "opentelemetry", "pydantic", "openai-agents", "google-adk", "aioboto3"] From cd0ce8df449a459fd1b88d87ddc8f619f475492b Mon Sep 17 00:00:00 2001 From: Justin Anderson <44687433+jmaeagle99@users.noreply.github.com> Date: Mon, 6 Apr 2026 12:28:53 -0700 Subject: [PATCH 026/226] Move proto check and test to separate job (#1412) --- .github/workflows/ci.yml | 57 ++++++++++++++++++++++++---------------- 1 file changed, 35 insertions(+), 22 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d1223cf44..6dc1ddb65 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -28,9 +28,6 @@ jobs: docsTarget: true openaiTestTarget: true clippyLinter: true - - os: ubuntu-latest - python: "3.10" - protoCheckTarget: true - python: "3.10" pytestExtraArgs: "--reruns 3 --only-rerun \"RuntimeError: Failed validating workflow\"" - os: ubuntu-arm @@ -85,25 +82,6 @@ jobs: path: junit-xml retention-days: 14 - # Confirm protos are already generated properly with older protobuf - # library and run test with that older version. We must downgrade protobuf - # so we can generate 3.x and 4.x compatible API. We have to use older - # Python to run this check because the grpcio-tools version we use - # is <= 3.10. - - name: Check generated protos and test protobuf 3.x - if: ${{ matrix.protoCheckTarget }} - env: - TEMPORAL_TEST_PROTO3: 1 - run: | - uv remove google-adk --optional google-adk - uv add --python 3.10 "protobuf<4" - uv sync --all-extras - poe build-develop - poe gen-protos - [[ -z $(git status --porcelain temporalio) ]] || (git diff temporalio; echo "Protos changed"; exit 1) - poe test -s --ignore=tests/contrib/google_adk_agents/ - timeout-minutes: 10 - # Do docs stuff (only on one host) - name: Build API docs if: ${{ matrix.docsTarget }} @@ -122,6 +100,41 @@ jobs: run: | npx doctoc README.md [[ -z $(git status --porcelain README.md) ]] || (git diff README.md; echo "README changed"; exit 1) + + check-protos: + timeout-minutes: 30 + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + submodules: recursive + - uses: dtolnay/rust-toolchain@stable + - uses: Swatinem/rust-cache@v2 + with: + workspaces: temporalio/bridge -> target + - uses: actions/setup-python@v5 + with: + python-version: "3.10" + - uses: arduino/setup-protoc@v3 + with: + # TODO(cretz): Can upgrade proto when https://github.com/arduino/setup-protoc/issues/99 fixed + version: "23.x" + repo-token: ${{ secrets.GITHUB_TOKEN }} + - uses: astral-sh/setup-uv@v5 + - run: uv tool install poethepoet + - run: uv remove google-adk --optional google-adk + - run: uv add --python 3.10 "protobuf<4" + - run: uv sync --all-extras + - run: poe build-develop + - run: poe gen-protos + - name: Check generation unchanged + run: | + [[ -z $(git status --porcelain temporalio) ]] || (git diff temporalio; echo "Protos changed"; exit 1) + - name: Test with protobuf 3.x + run: poe test -s --ignore=tests/contrib/google_adk_agents/ + env: + TEMPORAL_TEST_PROTO3: 1 + test-latest-deps: timeout-minutes: 30 runs-on: ubuntu-latest From 27686cf26786fd3a0abd9d8e4f6b508342dcc0c2 Mon Sep 17 00:00:00 2001 From: Justin Anderson <44687433+jmaeagle99@users.noreply.github.com> Date: Mon, 6 Apr 2026 14:17:03 -0700 Subject: [PATCH 027/226] Minimize task creation for concurrent payload visiting (#1414) --- scripts/gen_payload_visitor.py | 165 ++++++---------- temporalio/bridge/_visitor.py | 345 +++++++++++++-------------------- tests/worker/test_visitor.py | 53 +++++ 3 files changed, 252 insertions(+), 311 deletions(-) diff --git a/scripts/gen_payload_visitor.py b/scripts/gen_payload_visitor.py index 5b6f02396..928be03e5 100644 --- a/scripts/gen_payload_visitor.py +++ b/scripts/gen_payload_visitor.py @@ -20,87 +20,26 @@ def name_for(desc: Descriptor) -> str: return desc.full_name.replace(".", "_") -# --------------------------------------------------------------------------- -# Emitters for the "multi-unit" case: accumulate coroutines into `coros` list -# and let the caller do a single asyncio.gather(*coros) at the end. -# --------------------------------------------------------------------------- - - def emit_loop( field_name: str, iter_expr: str, child_method: str, ) -> str: - # Emit a coros.extend() over a collection with optional skip guard + # Emit a for-loop with direct await, with optional skip guard + inner = ( + f"for v in {iter_expr}:\n" + f" await self._visit_{child_method}(fs, v)" + ) if field_name == "headers": - return ( - " if not self.skip_headers:\n" - f" coros.extend(self._visit_{child_method}(fs, v) for v in {iter_expr})" - ) + return f" if not self.skip_headers:\n {inner}" elif field_name == "search_attributes": - return ( - " if not self.skip_search_attributes:\n" - f" coros.extend(self._visit_{child_method}(fs, v) for v in {iter_expr})" - ) + return f" if not self.skip_search_attributes:\n {inner}" else: - return f" coros.extend(self._visit_{child_method}(fs, v) for v in {iter_expr})" + return f" {inner}" def emit_singular( field_name: str, access_expr: str, child_method: str, presence_word: str | None -) -> str: - # Emit a coros.append() with optional HasField check and skip guard - if presence_word: - if field_name == "headers": - return ( - " if not self.skip_headers:\n" - f' {presence_word} o.HasField("{field_name}"):\n' - f" coros.append(self._visit_{child_method}(fs, {access_expr}))" - ) - else: - return ( - f' {presence_word} o.HasField("{field_name}"):\n' - f" coros.append(self._visit_{child_method}(fs, {access_expr}))" - ) - else: - if field_name == "headers": - return ( - " if not self.skip_headers:\n" - f" coros.append(self._visit_{child_method}(fs, {access_expr}))" - ) - else: - return ( - f" coros.append(self._visit_{child_method}(fs, {access_expr}))" - ) - - -# --------------------------------------------------------------------------- -# Emitters for the "single-unit" case: emit a direct await (no list needed). -# --------------------------------------------------------------------------- - - -def emit_loop_direct( - field_name: str, - iter_expr: str, - child_method: str, -) -> str: - # Emit a direct await asyncio.gather(*[...]) with optional skip guard - if field_name == "headers": - return ( - " if not self.skip_headers:\n" - f" await asyncio.gather(*[self._visit_{child_method}(fs, v) for v in {iter_expr}])" - ) - elif field_name == "search_attributes": - return ( - " if not self.skip_search_attributes:\n" - f" await asyncio.gather(*[self._visit_{child_method}(fs, v) for v in {iter_expr}])" - ) - else: - return f" await asyncio.gather(*[self._visit_{child_method}(fs, v) for v in {iter_expr}])" - - -def emit_singular_direct( - field_name: str, access_expr: str, child_method: str, presence_word: str | None ) -> str: # Emit a direct await self._visit_...() with optional HasField check and skip guard if presence_word: @@ -144,7 +83,6 @@ def generate(self, roots: list[Descriptor]) -> str: # This file is generated by gen_payload_visitor.py. Changes should be made there. import abc import asyncio -from collections.abc import Coroutine from typing import Any, MutableSequence from temporalio.api.common.v1.message_pb2 import Payload @@ -167,19 +105,53 @@ async def visit_payloads(self, payloads: MutableSequence[Payload]) -> None: class _BoundedVisitorFunctions(VisitorFunctions): - \"\"\"Wraps VisitorFunctions to cap concurrent payload visits via a semaphore.\"\"\" + \"\"\"Wraps VisitorFunctions to cap concurrent payload visits via a semaphore. + + After the full traversal, call drain() to await all in-flight tasks. + \"\"\" def __init__(self, inner: VisitorFunctions, sem: asyncio.Semaphore) -> None: self._inner = inner self._sem = sem + self._tasks: list[asyncio.Task[None]] = [] async def visit_payload(self, payload: Payload) -> None: - async with self._sem: - await self._inner.visit_payload(payload) + await self._sem.acquire() + + async def _run() -> None: + try: + await self._inner.visit_payload(payload) + finally: + self._sem.release() + + self._tasks.append(asyncio.create_task(_run())) async def visit_payloads(self, payloads: MutableSequence[Payload]) -> None: - async with self._sem: - await self._inner.visit_payloads(payloads) + await self._sem.acquire() + + async def _run() -> None: + try: + await self._inner.visit_payloads(payloads) + finally: + self._sem.release() + + self._tasks.append(asyncio.create_task(_run())) + + async def drain(self) -> None: + \"\"\"Wait for all in-flight background tasks to complete. + + On cancellation or error, cancels all remaining tasks and awaits + them so their finally blocks run before this coroutine returns. + \"\"\" + if not self._tasks: + return + try: + await asyncio.gather(*self._tasks) + except BaseException: + for task in self._tasks: + task.cancel() + await asyncio.gather(*self._tasks, return_exceptions=True) + raise class PayloadVisitor: @@ -200,10 +172,8 @@ def __init__( skip_search_attributes: If True, search attributes are not visited. skip_headers: If True, headers are not visited. concurrency_limit: Maximum number of payload visits that may run - concurrently during a single call to visit(). Defaults to 1. - The semaphore is applied to each visit_payload / visit_payloads - call, so it limits I/O-level concurrency without risking - deadlock in the recursive traversal. + concurrently during a single call to visit(). Defaults to 1 + (sequential). \"\"\" if concurrency_limit < 1: raise ValueError("concurrency_limit must be positive") @@ -215,13 +185,19 @@ async def visit( self, fs: VisitorFunctions, root: Any ) -> None: \"\"\"Visits the given root message with the given function.\"\"\" - fs = _BoundedVisitorFunctions(fs, asyncio.Semaphore(self._concurrency_limit)) method_name = "_visit_" + root.DESCRIPTOR.full_name.replace(".", "_") method = getattr(self, method_name, None) - if method is not None: - await method(fs, root) - else: + if method is None: raise ValueError(f"Unknown root message type: {root.DESCRIPTOR.full_name}") + if self._concurrency_limit == 1: + await method(fs, root) + return + + bounded = _BoundedVisitorFunctions(fs, asyncio.Semaphore(self._concurrency_limit)) + try: + await method(bounded, root) + finally: + await bounded.drain() """ @@ -388,30 +364,16 @@ def walk(self, desc: Descriptor) -> bool: lines.append(" if self.skip_search_attributes:") lines.append(" return") - # Use coros accumulation only when there are multiple independent units; - # a single unit is emitted with a direct await (no list overhead). - use_coros = len(emit_items) > 1 - if use_coros: - lines.append(" coros: list[Coroutine[Any, Any, None]] = []") - for item in emit_items: if item[0] == "loop": _, field_name, iter_expr, child_method = item - lines.append( - emit_loop(field_name, iter_expr, child_method) - if use_coros - else emit_loop_direct(field_name, iter_expr, child_method) - ) + lines.append(emit_loop(field_name, iter_expr, child_method)) elif item[0] == "singular": _, field_name, access_expr, child_method, presence_word = item lines.append( emit_singular( field_name, access_expr, child_method, presence_word ) - if use_coros - else emit_singular_direct( - field_name, access_expr, child_method, presence_word - ) ) else: # oneof_group for field_name, access_expr, child_method, presence_word in item[1]: @@ -419,15 +381,8 @@ def walk(self, desc: Descriptor) -> bool: emit_singular( field_name, access_expr, child_method, presence_word ) - if use_coros - else emit_singular_direct( - field_name, access_expr, child_method, presence_word - ) ) - if use_coros: - lines.append(" await asyncio.gather(*coros)") - self.methods.append("\n".join(lines) + "\n") return has_payload diff --git a/temporalio/bridge/_visitor.py b/temporalio/bridge/_visitor.py index 6f596bc15..0f030ac01 100644 --- a/temporalio/bridge/_visitor.py +++ b/temporalio/bridge/_visitor.py @@ -1,7 +1,6 @@ # This file is generated by gen_payload_visitor.py. Changes should be made there. import abc import asyncio -from collections.abc import Coroutine from typing import Any, MutableSequence from temporalio.api.common.v1.message_pb2 import Payload @@ -24,19 +23,53 @@ async def visit_payloads(self, payloads: MutableSequence[Payload]) -> None: class _BoundedVisitorFunctions(VisitorFunctions): - """Wraps VisitorFunctions to cap concurrent payload visits via a semaphore.""" + """Wraps VisitorFunctions to cap concurrent payload visits via a semaphore. + + After the full traversal, call drain() to await all in-flight tasks. + """ def __init__(self, inner: VisitorFunctions, sem: asyncio.Semaphore) -> None: self._inner = inner self._sem = sem + self._tasks: list[asyncio.Task[None]] = [] async def visit_payload(self, payload: Payload) -> None: - async with self._sem: - await self._inner.visit_payload(payload) + await self._sem.acquire() + + async def _run() -> None: + try: + await self._inner.visit_payload(payload) + finally: + self._sem.release() + + self._tasks.append(asyncio.create_task(_run())) async def visit_payloads(self, payloads: MutableSequence[Payload]) -> None: - async with self._sem: - await self._inner.visit_payloads(payloads) + await self._sem.acquire() + + async def _run() -> None: + try: + await self._inner.visit_payloads(payloads) + finally: + self._sem.release() + + self._tasks.append(asyncio.create_task(_run())) + + async def drain(self) -> None: + """Wait for all in-flight background tasks to complete. + + On cancellation or error, cancels all remaining tasks and awaits + them so their finally blocks run before this coroutine returns. + """ + if not self._tasks: + return + try: + await asyncio.gather(*self._tasks) + except BaseException: + for task in self._tasks: + task.cancel() + await asyncio.gather(*self._tasks, return_exceptions=True) + raise class PayloadVisitor: @@ -57,10 +90,8 @@ def __init__( skip_search_attributes: If True, search attributes are not visited. skip_headers: If True, headers are not visited. concurrency_limit: Maximum number of payload visits that may run - concurrently during a single call to visit(). Defaults to 1. - The semaphore is applied to each visit_payload / visit_payloads - call, so it limits I/O-level concurrency without risking - deadlock in the recursive traversal. + concurrently during a single call to visit(). Defaults to 1 + (sequential). """ if concurrency_limit < 1: raise ValueError("concurrency_limit must be positive") @@ -70,13 +101,21 @@ def __init__( async def visit(self, fs: VisitorFunctions, root: Any) -> None: """Visits the given root message with the given function.""" - fs = _BoundedVisitorFunctions(fs, asyncio.Semaphore(self._concurrency_limit)) method_name = "_visit_" + root.DESCRIPTOR.full_name.replace(".", "_") method = getattr(self, method_name, None) - if method is not None: - await method(fs, root) - else: + if method is None: raise ValueError(f"Unknown root message type: {root.DESCRIPTOR.full_name}") + if self._concurrency_limit == 1: + await method(fs, root) + return + + bounded = _BoundedVisitorFunctions( + fs, asyncio.Semaphore(self._concurrency_limit) + ) + try: + await method(bounded, root) + finally: + await bounded.drain() async def _visit_temporal_api_common_v1_Payload(self, fs, o): await fs.visit_payload(o) @@ -108,104 +147,66 @@ async def _visit_temporal_api_failure_v1_ResetWorkflowFailureInfo(self, fs, o): ) async def _visit_temporal_api_failure_v1_Failure(self, fs, o): - coros: list[Coroutine[Any, Any, None]] = [] if o.HasField("encoded_attributes"): - coros.append( - self._visit_temporal_api_common_v1_Payload(fs, o.encoded_attributes) - ) + await self._visit_temporal_api_common_v1_Payload(fs, o.encoded_attributes) if o.HasField("cause"): - coros.append(self._visit_temporal_api_failure_v1_Failure(fs, o.cause)) + await self._visit_temporal_api_failure_v1_Failure(fs, o.cause) if o.HasField("application_failure_info"): - coros.append( - self._visit_temporal_api_failure_v1_ApplicationFailureInfo( - fs, o.application_failure_info - ) + await self._visit_temporal_api_failure_v1_ApplicationFailureInfo( + fs, o.application_failure_info ) elif o.HasField("timeout_failure_info"): - coros.append( - self._visit_temporal_api_failure_v1_TimeoutFailureInfo( - fs, o.timeout_failure_info - ) + await self._visit_temporal_api_failure_v1_TimeoutFailureInfo( + fs, o.timeout_failure_info ) elif o.HasField("canceled_failure_info"): - coros.append( - self._visit_temporal_api_failure_v1_CanceledFailureInfo( - fs, o.canceled_failure_info - ) + await self._visit_temporal_api_failure_v1_CanceledFailureInfo( + fs, o.canceled_failure_info ) elif o.HasField("reset_workflow_failure_info"): - coros.append( - self._visit_temporal_api_failure_v1_ResetWorkflowFailureInfo( - fs, o.reset_workflow_failure_info - ) + await self._visit_temporal_api_failure_v1_ResetWorkflowFailureInfo( + fs, o.reset_workflow_failure_info ) - await asyncio.gather(*coros) async def _visit_temporal_api_common_v1_Memo(self, fs, o): - await asyncio.gather( - *[ - self._visit_temporal_api_common_v1_Payload(fs, v) - for v in o.fields.values() - ] - ) + for v in o.fields.values(): + await self._visit_temporal_api_common_v1_Payload(fs, v) async def _visit_temporal_api_common_v1_SearchAttributes(self, fs, o): if self.skip_search_attributes: return - await asyncio.gather( - *[ - self._visit_temporal_api_common_v1_Payload(fs, v) - for v in o.indexed_fields.values() - ] - ) + for v in o.indexed_fields.values(): + await self._visit_temporal_api_common_v1_Payload(fs, v) async def _visit_coresdk_workflow_activation_InitializeWorkflow(self, fs, o): - coros: list[Coroutine[Any, Any, None]] = [] - coros.append(self._visit_payload_container(fs, o.arguments)) + await self._visit_payload_container(fs, o.arguments) if not self.skip_headers: - coros.extend( - self._visit_temporal_api_common_v1_Payload(fs, v) - for v in o.headers.values() - ) + for v in o.headers.values(): + await self._visit_temporal_api_common_v1_Payload(fs, v) if o.HasField("continued_failure"): - coros.append( - self._visit_temporal_api_failure_v1_Failure(fs, o.continued_failure) - ) + await self._visit_temporal_api_failure_v1_Failure(fs, o.continued_failure) if o.HasField("last_completion_result"): - coros.append( - self._visit_temporal_api_common_v1_Payloads( - fs, o.last_completion_result - ) + await self._visit_temporal_api_common_v1_Payloads( + fs, o.last_completion_result ) if o.HasField("memo"): - coros.append(self._visit_temporal_api_common_v1_Memo(fs, o.memo)) + await self._visit_temporal_api_common_v1_Memo(fs, o.memo) if o.HasField("search_attributes"): - coros.append( - self._visit_temporal_api_common_v1_SearchAttributes( - fs, o.search_attributes - ) + await self._visit_temporal_api_common_v1_SearchAttributes( + fs, o.search_attributes ) - await asyncio.gather(*coros) async def _visit_coresdk_workflow_activation_QueryWorkflow(self, fs, o): - coros: list[Coroutine[Any, Any, None]] = [] - coros.append(self._visit_payload_container(fs, o.arguments)) + await self._visit_payload_container(fs, o.arguments) if not self.skip_headers: - coros.extend( - self._visit_temporal_api_common_v1_Payload(fs, v) - for v in o.headers.values() - ) - await asyncio.gather(*coros) + for v in o.headers.values(): + await self._visit_temporal_api_common_v1_Payload(fs, v) async def _visit_coresdk_workflow_activation_SignalWorkflow(self, fs, o): - coros: list[Coroutine[Any, Any, None]] = [] - coros.append(self._visit_payload_container(fs, o.input)) + await self._visit_payload_container(fs, o.input) if not self.skip_headers: - coros.extend( - self._visit_temporal_api_common_v1_Payload(fs, v) - for v in o.headers.values() - ) - await asyncio.gather(*coros) + for v in o.headers.values(): + await self._visit_temporal_api_common_v1_Payload(fs, v) async def _visit_coresdk_activity_result_Success(self, fs, o): if o.HasField("result"): @@ -284,14 +285,10 @@ async def _visit_coresdk_workflow_activation_ResolveRequestCancelExternalWorkflo await self._visit_temporal_api_failure_v1_Failure(fs, o.failure) async def _visit_coresdk_workflow_activation_DoUpdate(self, fs, o): - coros: list[Coroutine[Any, Any, None]] = [] - coros.append(self._visit_payload_container(fs, o.input)) + await self._visit_payload_container(fs, o.input) if not self.skip_headers: - coros.extend( - self._visit_temporal_api_common_v1_Payload(fs, v) - for v in o.headers.values() - ) - await asyncio.gather(*coros) + for v in o.headers.values(): + await self._visit_temporal_api_common_v1_Payload(fs, v) async def _visit_coresdk_workflow_activation_ResolveNexusOperationStart( self, fs, o @@ -358,30 +355,20 @@ async def _visit_coresdk_workflow_activation_WorkflowActivationJob(self, fs, o): ) async def _visit_coresdk_workflow_activation_WorkflowActivation(self, fs, o): - await asyncio.gather( - *[ - self._visit_coresdk_workflow_activation_WorkflowActivationJob(fs, v) - for v in o.jobs - ] - ) + for v in o.jobs: + await self._visit_coresdk_workflow_activation_WorkflowActivationJob(fs, v) async def _visit_temporal_api_sdk_v1_UserMetadata(self, fs, o): - coros: list[Coroutine[Any, Any, None]] = [] if o.HasField("summary"): - coros.append(self._visit_temporal_api_common_v1_Payload(fs, o.summary)) + await self._visit_temporal_api_common_v1_Payload(fs, o.summary) if o.HasField("details"): - coros.append(self._visit_temporal_api_common_v1_Payload(fs, o.details)) - await asyncio.gather(*coros) + await self._visit_temporal_api_common_v1_Payload(fs, o.details) async def _visit_coresdk_workflow_commands_ScheduleActivity(self, fs, o): - coros: list[Coroutine[Any, Any, None]] = [] if not self.skip_headers: - coros.extend( - self._visit_temporal_api_common_v1_Payload(fs, v) - for v in o.headers.values() - ) - coros.append(self._visit_payload_container(fs, o.arguments)) - await asyncio.gather(*coros) + for v in o.headers.values(): + await self._visit_temporal_api_common_v1_Payload(fs, v) + await self._visit_payload_container(fs, o.arguments) async def _visit_coresdk_workflow_commands_QuerySuccess(self, fs, o): if o.HasField("response"): @@ -404,64 +391,42 @@ async def _visit_coresdk_workflow_commands_FailWorkflowExecution(self, fs, o): async def _visit_coresdk_workflow_commands_ContinueAsNewWorkflowExecution( self, fs, o ): - coros: list[Coroutine[Any, Any, None]] = [] - coros.append(self._visit_payload_container(fs, o.arguments)) - coros.extend( - self._visit_temporal_api_common_v1_Payload(fs, v) for v in o.memo.values() - ) + await self._visit_payload_container(fs, o.arguments) + for v in o.memo.values(): + await self._visit_temporal_api_common_v1_Payload(fs, v) if not self.skip_headers: - coros.extend( - self._visit_temporal_api_common_v1_Payload(fs, v) - for v in o.headers.values() - ) + for v in o.headers.values(): + await self._visit_temporal_api_common_v1_Payload(fs, v) if o.HasField("search_attributes"): - coros.append( - self._visit_temporal_api_common_v1_SearchAttributes( - fs, o.search_attributes - ) + await self._visit_temporal_api_common_v1_SearchAttributes( + fs, o.search_attributes ) - await asyncio.gather(*coros) async def _visit_coresdk_workflow_commands_StartChildWorkflowExecution(self, fs, o): - coros: list[Coroutine[Any, Any, None]] = [] - coros.append(self._visit_payload_container(fs, o.input)) + await self._visit_payload_container(fs, o.input) if not self.skip_headers: - coros.extend( - self._visit_temporal_api_common_v1_Payload(fs, v) - for v in o.headers.values() - ) - coros.extend( - self._visit_temporal_api_common_v1_Payload(fs, v) for v in o.memo.values() - ) + for v in o.headers.values(): + await self._visit_temporal_api_common_v1_Payload(fs, v) + for v in o.memo.values(): + await self._visit_temporal_api_common_v1_Payload(fs, v) if o.HasField("search_attributes"): - coros.append( - self._visit_temporal_api_common_v1_SearchAttributes( - fs, o.search_attributes - ) + await self._visit_temporal_api_common_v1_SearchAttributes( + fs, o.search_attributes ) - await asyncio.gather(*coros) async def _visit_coresdk_workflow_commands_SignalExternalWorkflowExecution( self, fs, o ): - coros: list[Coroutine[Any, Any, None]] = [] - coros.append(self._visit_payload_container(fs, o.args)) + await self._visit_payload_container(fs, o.args) if not self.skip_headers: - coros.extend( - self._visit_temporal_api_common_v1_Payload(fs, v) - for v in o.headers.values() - ) - await asyncio.gather(*coros) + for v in o.headers.values(): + await self._visit_temporal_api_common_v1_Payload(fs, v) async def _visit_coresdk_workflow_commands_ScheduleLocalActivity(self, fs, o): - coros: list[Coroutine[Any, Any, None]] = [] if not self.skip_headers: - coros.extend( - self._visit_temporal_api_common_v1_Payload(fs, v) - for v in o.headers.values() - ) - coros.append(self._visit_payload_container(fs, o.arguments)) - await asyncio.gather(*coros) + for v in o.headers.values(): + await self._visit_temporal_api_common_v1_Payload(fs, v) + await self._visit_payload_container(fs, o.arguments) async def _visit_coresdk_workflow_commands_UpsertWorkflowSearchAttributes( self, fs, o @@ -486,92 +451,60 @@ async def _visit_coresdk_workflow_commands_ScheduleNexusOperation(self, fs, o): await self._visit_temporal_api_common_v1_Payload(fs, o.input) async def _visit_coresdk_workflow_commands_WorkflowCommand(self, fs, o): - coros: list[Coroutine[Any, Any, None]] = [] if o.HasField("user_metadata"): - coros.append( - self._visit_temporal_api_sdk_v1_UserMetadata(fs, o.user_metadata) - ) + await self._visit_temporal_api_sdk_v1_UserMetadata(fs, o.user_metadata) if o.HasField("schedule_activity"): - coros.append( - self._visit_coresdk_workflow_commands_ScheduleActivity( - fs, o.schedule_activity - ) + await self._visit_coresdk_workflow_commands_ScheduleActivity( + fs, o.schedule_activity ) elif o.HasField("respond_to_query"): - coros.append( - self._visit_coresdk_workflow_commands_QueryResult( - fs, o.respond_to_query - ) + await self._visit_coresdk_workflow_commands_QueryResult( + fs, o.respond_to_query ) elif o.HasField("complete_workflow_execution"): - coros.append( - self._visit_coresdk_workflow_commands_CompleteWorkflowExecution( - fs, o.complete_workflow_execution - ) + await self._visit_coresdk_workflow_commands_CompleteWorkflowExecution( + fs, o.complete_workflow_execution ) elif o.HasField("fail_workflow_execution"): - coros.append( - self._visit_coresdk_workflow_commands_FailWorkflowExecution( - fs, o.fail_workflow_execution - ) + await self._visit_coresdk_workflow_commands_FailWorkflowExecution( + fs, o.fail_workflow_execution ) elif o.HasField("continue_as_new_workflow_execution"): - coros.append( - self._visit_coresdk_workflow_commands_ContinueAsNewWorkflowExecution( - fs, o.continue_as_new_workflow_execution - ) + await self._visit_coresdk_workflow_commands_ContinueAsNewWorkflowExecution( + fs, o.continue_as_new_workflow_execution ) elif o.HasField("start_child_workflow_execution"): - coros.append( - self._visit_coresdk_workflow_commands_StartChildWorkflowExecution( - fs, o.start_child_workflow_execution - ) + await self._visit_coresdk_workflow_commands_StartChildWorkflowExecution( + fs, o.start_child_workflow_execution ) elif o.HasField("signal_external_workflow_execution"): - coros.append( - self._visit_coresdk_workflow_commands_SignalExternalWorkflowExecution( - fs, o.signal_external_workflow_execution - ) + await self._visit_coresdk_workflow_commands_SignalExternalWorkflowExecution( + fs, o.signal_external_workflow_execution ) elif o.HasField("schedule_local_activity"): - coros.append( - self._visit_coresdk_workflow_commands_ScheduleLocalActivity( - fs, o.schedule_local_activity - ) + await self._visit_coresdk_workflow_commands_ScheduleLocalActivity( + fs, o.schedule_local_activity ) elif o.HasField("upsert_workflow_search_attributes"): - coros.append( - self._visit_coresdk_workflow_commands_UpsertWorkflowSearchAttributes( - fs, o.upsert_workflow_search_attributes - ) + await self._visit_coresdk_workflow_commands_UpsertWorkflowSearchAttributes( + fs, o.upsert_workflow_search_attributes ) elif o.HasField("modify_workflow_properties"): - coros.append( - self._visit_coresdk_workflow_commands_ModifyWorkflowProperties( - fs, o.modify_workflow_properties - ) + await self._visit_coresdk_workflow_commands_ModifyWorkflowProperties( + fs, o.modify_workflow_properties ) elif o.HasField("update_response"): - coros.append( - self._visit_coresdk_workflow_commands_UpdateResponse( - fs, o.update_response - ) + await self._visit_coresdk_workflow_commands_UpdateResponse( + fs, o.update_response ) elif o.HasField("schedule_nexus_operation"): - coros.append( - self._visit_coresdk_workflow_commands_ScheduleNexusOperation( - fs, o.schedule_nexus_operation - ) + await self._visit_coresdk_workflow_commands_ScheduleNexusOperation( + fs, o.schedule_nexus_operation ) - await asyncio.gather(*coros) async def _visit_coresdk_workflow_completion_Success(self, fs, o): - await asyncio.gather( - *[ - self._visit_coresdk_workflow_commands_WorkflowCommand(fs, v) - for v in o.commands - ] - ) + for v in o.commands: + await self._visit_coresdk_workflow_commands_WorkflowCommand(fs, v) async def _visit_coresdk_workflow_completion_Failure(self, fs, o): if o.HasField("failure"): diff --git a/tests/worker/test_visitor.py b/tests/worker/test_visitor.py index 15860f58c..876387393 100644 --- a/tests/worker/test_visitor.py +++ b/tests/worker/test_visitor.py @@ -3,6 +3,7 @@ import time from collections.abc import MutableSequence +import pytest from google.protobuf.duration_pb2 import Duration import temporalio.bridge.worker @@ -273,6 +274,58 @@ async def _visit(self, count: int) -> None: assert visitor_concurrent.max_concurrent == 5 +async def test_cancel_drains_background_tasks(): + """Cancelling visit() cancels in-flight tasks and awaits their cleanup.""" + tasks_started = 0 + tasks_cleaned_up = 0 + background_running = asyncio.Event() + + class SlowVisitor(VisitorFunctions): + async def visit_payload(self, payload: Payload) -> None: + pass + + async def visit_payloads(self, payloads: MutableSequence[Payload]) -> None: + nonlocal tasks_started, tasks_cleaned_up + tasks_started += 1 + background_running.set() + try: + await asyncio.sleep(10) + finally: + tasks_cleaned_up += 1 + + completion = WorkflowActivationCompletion( + run_id="1", + successful=Success( + commands=[ + WorkflowCommand( + schedule_activity=ScheduleActivity( + seq=i, + activity_id=str(i), + activity_type="", + task_queue="", + arguments=[Payload(data=f"arg_{i}".encode())], + priority=Priority(), + ) + ) + for i in range(5) + ] + ), + ) + + task = asyncio.create_task( + PayloadVisitor(concurrency_limit=5).visit(SlowVisitor(), completion) + ) + await background_running.wait() + task.cancel() + + with pytest.raises(asyncio.CancelledError): + await task + + # All started tasks ran their finally blocks before drain() returned. + assert tasks_started > 0 + assert tasks_cleaned_up == tasks_started + + async def test_bridge_encoding(): comp = WorkflowActivationCompletion( run_id="1", From f0e85184a26f1c1646657f767ab2707461ef4558 Mon Sep 17 00:00:00 2001 From: Spencer Judge Date: Mon, 6 Apr 2026 15:35:03 -0700 Subject: [PATCH 028/226] Add contrib package for lambda workers (#1408) --- pyproject.toml | 10 + temporalio/client.py | 23 + temporalio/contrib/aws/__init__.py | 1 + .../contrib/aws/lambda_worker/README.md | 104 ++++ .../contrib/aws/lambda_worker/__init__.py | 49 ++ .../contrib/aws/lambda_worker/_configure.py | 72 +++ .../contrib/aws/lambda_worker/_defaults.py | 84 +++ .../contrib/aws/lambda_worker/_run_worker.py | 259 +++++++++ temporalio/contrib/aws/lambda_worker/otel.py | 241 ++++++++ temporalio/contrib/aws/s3driver/_driver.py | 8 +- tests/conftest.py | 12 + tests/contrib/aws/lambda_worker/__init__.py | 0 .../aws/lambda_worker/test_lambda_worker.py | 522 ++++++++++++++++++ tests/contrib/aws/lambda_worker/test_otel.py | 167 ++++++ .../test_google_adk_agents.py | 5 +- .../openai_agents/test_openai_tracing.py | 36 +- .../test_opentelemetry_plugin.py | 11 - tests/test_client.py | 15 + tests/worker/test_worker.py | 15 + uv.lock | 50 +- 20 files changed, 1655 insertions(+), 29 deletions(-) create mode 100644 temporalio/contrib/aws/__init__.py create mode 100644 temporalio/contrib/aws/lambda_worker/README.md create mode 100644 temporalio/contrib/aws/lambda_worker/__init__.py create mode 100644 temporalio/contrib/aws/lambda_worker/_configure.py create mode 100644 temporalio/contrib/aws/lambda_worker/_defaults.py create mode 100644 temporalio/contrib/aws/lambda_worker/_run_worker.py create mode 100644 temporalio/contrib/aws/lambda_worker/otel.py create mode 100644 tests/contrib/aws/lambda_worker/__init__.py create mode 100644 tests/contrib/aws/lambda_worker/test_lambda_worker.py create mode 100644 tests/contrib/aws/lambda_worker/test_otel.py diff --git a/pyproject.toml b/pyproject.toml index c8fa96a8d..e52ad5ead 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -30,6 +30,13 @@ opentelemetry = ["opentelemetry-api>=1.11.1,<2", "opentelemetry-sdk>=1.11.1,<2"] pydantic = ["pydantic>=2.0.0,<3"] openai-agents = ["openai-agents>=0.3,<0.7", "mcp>=1.9.4, <2"] google-adk = ["google-adk>=1.27.0,<2"] +lambda-worker-otel = [ + "opentelemetry-api>=1.11.1,<2", + "opentelemetry-sdk>=1.11.1,<2", + "opentelemetry-exporter-otlp-proto-grpc>=1.11.1,<2", + "opentelemetry-semantic-conventions>=0.40b0,<1", + "opentelemetry-sdk-extension-aws>=2.0.0,<3", +] aioboto3 = [ "aioboto3>=10.4.0", "types-aioboto3[s3]>=10.4.0", @@ -69,6 +76,9 @@ dev = [ "googleapis-common-protos==1.70.0", "pytest-rerunfailures>=16.1", "moto[s3,server]>=5", + "opentelemetry-exporter-otlp-proto-grpc>=1.11.1,<2", + "opentelemetry-semantic-conventions>=0.40b0,<1", + "opentelemetry-sdk-extension-aws>=2.0.0,<3", ] [tool.poe.tasks] diff --git a/temporalio/client.py b/temporalio/client.py index 9e7bc6045..f781774c1 100644 --- a/temporalio/client.py +++ b/temporalio/client.py @@ -2805,6 +2805,29 @@ async def get_worker_task_reachability( ) +class ClientConnectConfig(TypedDict, total=False): + """TypedDict of keyword arguments for :py:meth:`Client.connect`.""" + + target_host: str + namespace: str + api_key: str | None + data_converter: temporalio.converter.DataConverter + plugins: Sequence[Plugin] + interceptors: Sequence[Interceptor] + default_workflow_query_reject_condition: ( + temporalio.common.QueryRejectCondition | None + ) + tls: bool | TLSConfig | None + retry_config: RetryConfig | None + keep_alive_config: KeepAliveConfig | None + rpc_metadata: Mapping[str, str | bytes] + identity: str | None + lazy: bool + runtime: temporalio.runtime.Runtime | None + http_connect_proxy_config: HttpConnectProxyConfig | None + header_codec_behavior: HeaderCodecBehavior + + class ClientConfig(TypedDict, total=False): """TypedDict of config originally passed to :py:meth:`Client`.""" diff --git a/temporalio/contrib/aws/__init__.py b/temporalio/contrib/aws/__init__.py new file mode 100644 index 000000000..a8b8c648f --- /dev/null +++ b/temporalio/contrib/aws/__init__.py @@ -0,0 +1 @@ +"""AWS integrations for Temporal SDK.""" diff --git a/temporalio/contrib/aws/lambda_worker/README.md b/temporalio/contrib/aws/lambda_worker/README.md new file mode 100644 index 000000000..f9166b13d --- /dev/null +++ b/temporalio/contrib/aws/lambda_worker/README.md @@ -0,0 +1,104 @@ +# lambda_worker + +A wrapper for running [Temporal](https://temporal.io) workers inside AWS Lambda. A single +`run_worker` call handles the full per-invocation lifecycle: connecting to the Temporal server, +creating a worker with Lambda-tuned defaults, polling for tasks, and gracefully shutting down before +the invocation deadline. + +## Quick start + +```python +# handler.py +from temporalio.common import WorkerDeploymentVersion +from temporalio.contrib.aws.lambda_worker import LambdaWorkerConfig, run_worker + +from my_workflows import MyWorkflow +from my_activities import my_activity + + +def configure(config: LambdaWorkerConfig) -> None: + config.worker_config["task_queue"] = "my-task-queue" + config.worker_config["workflows"] = [MyWorkflow] + config.worker_config["activities"] = [my_activity] + + +lambda_handler = run_worker( + WorkerDeploymentVersion( + deployment_name="my-service", + build_id="v1.0", + ), + configure, +) +``` + +## Configuration + +Client connection settings (address, namespace, TLS, API key) are loaded +automatically from a TOML config file and/or environment variables via +`temporalio.envconfig`. The config file is resolved in order: + +1. `TEMPORAL_CONFIG_FILE` env var, if set. +2. `temporal.toml` in `$LAMBDA_TASK_ROOT` (typically `/var/task`). +3. `temporal.toml` in the current working directory. + +The file is optional -- if absent, only environment variables are used. + +The configure callback receives a `LambdaWorkerConfig` dataclass with fields +pre-populated with Lambda-appropriate defaults. Override any field directly in +the callback. The `task_queue` key in `worker_config` is pre-populated from the +`TEMPORAL_TASK_QUEUE` environment variable if set. + +## Lambda-tuned worker defaults + +The package applies conservative concurrency limits suited to Lambda's resource +constraints: + +| Setting | Default | +| --- | --- | +| `max_concurrent_activities` | 2 | +| `max_concurrent_workflow_tasks` | 10 | +| `max_concurrent_local_activities` | 2 | +| `max_concurrent_nexus_tasks` | 5 | +| `workflow_task_poller_behavior` | `SimpleMaximum(2)` | +| `activity_task_poller_behavior` | `SimpleMaximum(1)` | +| `nexus_task_poller_behavior` | `SimpleMaximum(1)` | +| `graceful_shutdown_timeout` | 5 seconds | +| `max_cached_workflows` | 100 | +| `disable_eager_activity_execution` | Always `True` | + +Worker Deployment Versioning is always enabled. + +## Observability + +Metrics and tracing are opt-in. The `otel` module provides convenience helpers +for AWS Distro for OpenTelemetry (ADOT): + +```python +from temporalio.common import WorkerDeploymentVersion +from temporalio.contrib.aws.lambda_worker import LambdaWorkerConfig, run_worker +from temporalio.contrib.aws.lambda_worker.otel import apply_defaults, OtelOptions + + +def configure(config: LambdaWorkerConfig) -> None: + config.worker_config["task_queue"] = "my-task-queue" + config.worker_config["workflows"] = [MyWorkflow] + config.worker_config["activities"] = [my_activity] + apply_defaults(config, OtelOptions()) + + +lambda_handler = run_worker( + WorkerDeploymentVersion( + deployment_name="my-service", + build_id="v1.0", + ), + configure, +) +``` + +You can also use `apply_metrics` or `apply_tracing` individually. + +If you use OTEL, you can use +[ADOT](https://aws-otel.github.io/docs/getting-started/lambda/lambda-python) +(the AWS Distro For OpenTelemetry) to automatically integrate with AWS +observability functionality. Namely, you will want to add the Lambda layer in +the aforementioned link. We'll handle setting up the SDK for you. diff --git a/temporalio/contrib/aws/lambda_worker/__init__.py b/temporalio/contrib/aws/lambda_worker/__init__.py new file mode 100644 index 000000000..11f748c9b --- /dev/null +++ b/temporalio/contrib/aws/lambda_worker/__init__.py @@ -0,0 +1,49 @@ +"""A wrapper for running Temporal workers inside AWS Lambda. + +A single :py:func:`run_worker` call handles the full per-invocation lifecycle: connecting to the +Temporal server, creating a worker with Lambda-tuned defaults, polling for tasks, and gracefully +shutting down before the invocation deadline. + +Quick start:: + + from temporalio.common import WorkerDeploymentVersion + from temporalio.contrib.aws.lambda_worker import LambdaWorkerConfig, run_worker + + def configure(config: LambdaWorkerConfig) -> None: + config.worker_config["task_queue"] = "my-task-queue" + config.worker_config["workflows"] = [MyWorkflow] + config.worker_config["activities"] = [my_activity] + + lambda_handler = run_worker( + WorkerDeploymentVersion( + deployment_name="my-service", + build_id="v1.0", + ), + configure, + ) + +Configuration +------------- +Client connection settings (address, namespace, TLS, API key) are loaded automatically from a TOML +config file and/or environment variables via :py:mod:`temporalio.envconfig`. The config file is +resolved in order: + +1. ``TEMPORAL_CONFIG_FILE`` env var, if set. +2. ``temporal.toml`` in ``$LAMBDA_TASK_ROOT`` (typically ``/var/task``). +3. ``temporal.toml`` in the current working directory. + +The file is optional -- if absent, only environment variables are used. + +The configure callback receives a :py:class:`LambdaWorkerConfig` dataclass with fields pre-populated +with Lambda-appropriate defaults. Override any field directly in the callback. The ``task_queue`` +key in ``worker_config`` is pre-populated from the ``TEMPORAL_TASK_QUEUE`` environment variable if +set. +""" + +from temporalio.contrib.aws.lambda_worker._configure import LambdaWorkerConfig +from temporalio.contrib.aws.lambda_worker._run_worker import run_worker + +__all__ = [ + "LambdaWorkerConfig", + "run_worker", +] diff --git a/temporalio/contrib/aws/lambda_worker/_configure.py b/temporalio/contrib/aws/lambda_worker/_configure.py new file mode 100644 index 000000000..dd1657f6d --- /dev/null +++ b/temporalio/contrib/aws/lambda_worker/_configure.py @@ -0,0 +1,72 @@ +"""Configuration for the Lambda worker.""" + +from __future__ import annotations + +import asyncio +import logging +from collections.abc import Awaitable, Callable +from dataclasses import dataclass, field +from datetime import timedelta + +from temporalio.client import ClientConnectConfig +from temporalio.worker import WorkerConfig + +logger = logging.getLogger(__name__) + + +@dataclass +class LambdaWorkerConfig: + """Passed to the configure callback of :py:func:`run_worker`. + + Fields are pre-populated with Lambda-appropriate defaults before the configure callback is + invoked; the callback may read and override any of them. + + Use ``worker_config`` to set task queue, register workflows/activities, and tune worker options. + The ``task_queue`` key is pre-populated from the ``TEMPORAL_TASK_QUEUE`` environment variable if + set. + + Attributes: + client_connect_config: Keyword arguments that will be passed to + :py:meth:`temporalio.client.Client.connect`. Pre-populated from the + config file / environment variables via envconfig, with Lambda + defaults applied. + worker_config: Keyword arguments that will be passed to the + :py:class:`temporalio.worker.Worker` constructor (the ``client`` + key is managed internally). Pre-populated with Lambda-appropriate + defaults (low concurrency, eager activities disabled) and + ``task_queue`` from ``TEMPORAL_TASK_QUEUE`` if set. + shutdown_deadline_buffer: How long before the Lambda invocation + deadline the worker begins its shutdown sequence (worker drain + + shutdown hooks). Pre-populated to + ``graceful_shutdown_timeout + 2s``. If you change + ``graceful_shutdown_timeout`` in ``worker_config``, adjust this + accordingly. + shutdown_hooks: Functions called at the end of each Lambda invocation, + after the worker has stopped. Run in list order. Each may be sync + or async. Use this to flush telemetry providers or release other + per-process resources. + """ + + client_connect_config: ClientConnectConfig = field( + default_factory=ClientConnectConfig + ) + worker_config: WorkerConfig = field(default_factory=WorkerConfig) + shutdown_deadline_buffer: timedelta = field( + default_factory=lambda: timedelta(seconds=7) + ) + shutdown_hooks: list[Callable[[], Awaitable[None] | None]] = field( + default_factory=list + ) + + +async def _run_shutdown_hooks( # type:ignore[reportUnusedFunction] + config: LambdaWorkerConfig, +) -> None: + """Run all registered shutdown hooks in order, logging errors.""" + for fn in config.shutdown_hooks: + try: + result = fn() + if asyncio.iscoroutine(result): + await result + except Exception as e: + logger.error(f"shutdown hook error: {e}") diff --git a/temporalio/contrib/aws/lambda_worker/_defaults.py b/temporalio/contrib/aws/lambda_worker/_defaults.py new file mode 100644 index 000000000..1b93e3407 --- /dev/null +++ b/temporalio/contrib/aws/lambda_worker/_defaults.py @@ -0,0 +1,84 @@ +"""Lambda-tuned defaults for Temporal worker and client configuration.""" + +from __future__ import annotations + +import os +from collections.abc import Callable +from datetime import timedelta +from pathlib import Path + +from temporalio.worker import PollerBehaviorSimpleMaximum, WorkerConfig + +# ---- Lambda-tuned worker defaults ---- +# Conservative concurrency limits suited to Lambda's resource constraints. + +DEFAULT_MAX_CONCURRENT_ACTIVITIES: int = 2 +DEFAULT_MAX_CONCURRENT_WORKFLOW_TASKS: int = 10 +DEFAULT_MAX_CONCURRENT_LOCAL_ACTIVITIES: int = 2 +DEFAULT_MAX_CONCURRENT_NEXUS_TASKS: int = 5 +DEFAULT_GRACEFUL_SHUTDOWN_TIMEOUT: timedelta = timedelta(seconds=5) +DEFAULT_SHUTDOWN_HOOK_BUFFER: timedelta = timedelta(seconds=2) +DEFAULT_MAX_CACHED_WORKFLOWS: int = 30 + +DEFAULT_WORKFLOW_TASK_POLLER_BEHAVIOR = PollerBehaviorSimpleMaximum(maximum=2) +DEFAULT_ACTIVITY_TASK_POLLER_BEHAVIOR = PollerBehaviorSimpleMaximum(maximum=1) +DEFAULT_NEXUS_TASK_POLLER_BEHAVIOR = PollerBehaviorSimpleMaximum(maximum=1) + +# ---- Environment variable names ---- +ENV_TASK_QUEUE = "TEMPORAL_TASK_QUEUE" +ENV_LAMBDA_TASK_ROOT = "LAMBDA_TASK_ROOT" +ENV_CONFIG_FILE = "TEMPORAL_CONFIG_FILE" +DEFAULT_CONFIG_FILE = "temporal.toml" + + +def apply_lambda_worker_defaults(config: WorkerConfig) -> None: + """Apply Lambda-appropriate defaults to worker config. + + Only sets values that have not already been set (i.e. are absent from *config*). + ``disable_eager_activity_execution`` is always set to ``True``. + """ + config.setdefault("max_concurrent_activities", DEFAULT_MAX_CONCURRENT_ACTIVITIES) + config.setdefault( + "max_concurrent_workflow_tasks", DEFAULT_MAX_CONCURRENT_WORKFLOW_TASKS + ) + config.setdefault( + "max_concurrent_local_activities", DEFAULT_MAX_CONCURRENT_LOCAL_ACTIVITIES + ) + config.setdefault("max_concurrent_nexus_tasks", DEFAULT_MAX_CONCURRENT_NEXUS_TASKS) + config.setdefault("graceful_shutdown_timeout", DEFAULT_GRACEFUL_SHUTDOWN_TIMEOUT) + config.setdefault("max_cached_workflows", DEFAULT_MAX_CACHED_WORKFLOWS) + config.setdefault( + "workflow_task_poller_behavior", DEFAULT_WORKFLOW_TASK_POLLER_BEHAVIOR + ) + config.setdefault( + "activity_task_poller_behavior", DEFAULT_ACTIVITY_TASK_POLLER_BEHAVIOR + ) + config.setdefault("nexus_task_poller_behavior", DEFAULT_NEXUS_TASK_POLLER_BEHAVIOR) + # Always disable eager activities in Lambda. + config["disable_eager_activity_execution"] = True + + +def build_lambda_identity(request_id: str, function_arn: str) -> str: + """Build a worker identity string from the Lambda invocation context. + + Format: ``@``. + """ + return f"{request_id or 'unknown'}@{function_arn or 'unknown'}" + + +def lambda_default_config_file_path( + getenv: Callable[[str], str] = os.environ.get, # type: ignore[assignment] +) -> Path: + """Return the config file path for a Lambda environment. + + Resolution order: + + 1. ``TEMPORAL_CONFIG_FILE`` env var, if set. + 2. ``temporal.toml`` in ``$LAMBDA_TASK_ROOT`` (typically ``/var/task``). + 3. ``temporal.toml`` in the current working directory. + """ + config_file = getenv(ENV_CONFIG_FILE) + if config_file: + return Path(config_file) + root = getenv(ENV_LAMBDA_TASK_ROOT) or "." + return Path(root) / DEFAULT_CONFIG_FILE diff --git a/temporalio/contrib/aws/lambda_worker/_run_worker.py b/temporalio/contrib/aws/lambda_worker/_run_worker.py new file mode 100644 index 000000000..6a2cc75a3 --- /dev/null +++ b/temporalio/contrib/aws/lambda_worker/_run_worker.py @@ -0,0 +1,259 @@ +from __future__ import annotations + +import asyncio +import logging +import os +import sys +from collections.abc import Awaitable, Callable +from dataclasses import dataclass, field +from datetime import timedelta +from typing import Any + +import temporalio.client +import temporalio.worker +from temporalio.client import ClientConnectConfig +from temporalio.common import WorkerDeploymentVersion +from temporalio.contrib.aws.lambda_worker._configure import ( + LambdaWorkerConfig, + _run_shutdown_hooks, +) +from temporalio.contrib.aws.lambda_worker._defaults import ( + DEFAULT_SHUTDOWN_HOOK_BUFFER, + apply_lambda_worker_defaults, + build_lambda_identity, + lambda_default_config_file_path, +) +from temporalio.envconfig import ClientConfigProfile +from temporalio.worker import WorkerConfig, WorkerDeploymentConfig + +logger = logging.getLogger(__name__) + + +@dataclass +class _WorkerDeps: + """External dependencies injected for testability.""" + + connect: Callable[..., Awaitable[temporalio.client.Client]] = field( + default_factory=lambda: temporalio.client.Client.connect + ) + create_worker: Callable[..., temporalio.worker.Worker] = field( + default_factory=lambda: temporalio.worker.Worker + ) + load_config: Callable[[], ClientConfigProfile] | None = None + getenv: Callable[[str], str | None] = field(default_factory=lambda: os.environ.get) + extract_lambda_ctx: Callable[[Any], tuple[str, str] | None] | None = None + + +def _default_load_config(getenv: Callable[[str], str | None]) -> ClientConfigProfile: + config_path = lambda_default_config_file_path(getenv) # type: ignore[arg-type] + return ClientConfigProfile.load(config_source=config_path) + + +def _default_extract_lambda_ctx( + lambda_context: Any, +) -> tuple[str, str] | None: + """Extract (request_id, function_arn) from a Lambda context object.""" + if lambda_context is None: + return None + request_id = getattr(lambda_context, "aws_request_id", None) + function_arn = getattr(lambda_context, "invoked_function_arn", None) + if request_id is not None and function_arn is not None: + return (request_id, function_arn) + return None + + +def run_worker( + version: WorkerDeploymentVersion, + configure: Callable[[LambdaWorkerConfig], None], +) -> Callable[[Any, Any], None]: + """Create a Temporal worker Lambda handler. + + Calls the *configure* callback to collect workflow/activity registrations and option overrides, + then returns a Lambda handler function. On each invocation the handler connects to the Temporal + server, starts a worker with Lambda-tuned defaults, polls for tasks until the invocation + deadline approaches, and then gracefully shuts down. + + The *version* parameter identifies this worker's deployment version. ``run_worker`` always + enables Worker Deployment Versioning (``use_worker_versioning=True``). To provide a default + versioning behavior for workflows that do not specify one at registration time, set + ``deployment_config`` in ``worker_config`` in the configure callback. + + The returned handler has the signature ``handler(event, context)`` and should be set as your + Lambda function's handler entry point. + + Args: + version: The worker deployment version. Required. + configure: A callback that receives a :py:class:`LambdaWorkerConfig` + (pre-populated with Lambda defaults) and configures workflows, + activities, and options on it. + + Returns: + A Lambda handler function. + + Example:: + + from temporalio.common import WorkerDeploymentVersion + from temporalio.contrib.aws.lambda_worker import ( + LambdaWorkerConfig, + run_worker, + ) + + def configure(config: LambdaWorkerConfig) -> None: + config.worker_config["task_queue"] = "my-task-queue" + config.worker_config["workflows"] = [MyWorkflow] + config.worker_config["activities"] = [my_activity] + + lambda_handler = run_worker( + WorkerDeploymentVersion( + deployment_name="my-service", + build_id="v1.0", + ), + configure, + ) + """ + deps = _WorkerDeps() + try: + return _run_worker_internal(version, configure, deps) + except Exception as e: + logger.error(f"fatal error running lambda worker: {e}") + sys.exit(1) + + +def _run_worker_internal( + version: WorkerDeploymentVersion, + configure: Callable[[LambdaWorkerConfig], None], + deps: _WorkerDeps, +) -> Callable[[Any, Any], None]: + """Core logic with injected dependencies for testability.""" + if not version.deployment_name or not version.build_id: + raise ValueError( + "version is required (deployment_name and build_id must be set)" + ) + + # Load client config from envconfig / TOML. + load_config = deps.load_config or (lambda: _default_load_config(deps.getenv)) + profile = load_config() + connect_config: ClientConnectConfig = {**profile.to_client_connect_config()} + + # Build worker config with Lambda defaults. + worker_config: WorkerConfig = {} + apply_lambda_worker_defaults(worker_config) + + # Always enable deployment versioning. + worker_config["deployment_config"] = WorkerDeploymentConfig( + version=version, + use_worker_versioning=True, + ) + + # Calculate default shutdown buffer. + graceful_timeout = worker_config.get( + "graceful_shutdown_timeout", timedelta(seconds=5) + ) + shutdown_buffer = graceful_timeout + DEFAULT_SHUTDOWN_HOOK_BUFFER + + # Pre-populate config with defaults. + config = LambdaWorkerConfig( + client_connect_config=connect_config, + worker_config=worker_config, + shutdown_deadline_buffer=shutdown_buffer, + ) + + # Pre-populate task queue from environment if available. + env_tq = deps.getenv("TEMPORAL_TASK_QUEUE") + if env_tq: + config.worker_config["task_queue"] = env_tq + + # Call user configure callback with pre-populated config. + configure(config) + + # Validate task queue. + if not config.worker_config.get("task_queue"): + raise ValueError( + "task queue not configured: set " + 'worker_config["task_queue"] or the ' + "TEMPORAL_TASK_QUEUE environment variable" + ) + + extract_lambda_ctx = deps.extract_lambda_ctx or _default_extract_lambda_ctx + + def _handler(_event: Any, lambda_context: Any) -> None: + asyncio.run( + _invocation_handler( + lambda_context=lambda_context, + config=config, + deps=deps, + extract_lambda_ctx=extract_lambda_ctx, + ) + ) + + return _handler + + +async def _invocation_handler( + *, + lambda_context: Any, + config: LambdaWorkerConfig, + deps: _WorkerDeps, + extract_lambda_ctx: Callable[[Any], tuple[str, str] | None], +) -> None: + """Handle a single Lambda invocation.""" + shutdown_buffer = config.shutdown_deadline_buffer + + # Check deadline feasibility. + remaining_ms_fn = getattr(lambda_context, "get_remaining_time_in_millis", None) + deadline_available = remaining_ms_fn is not None + if deadline_available: + assert remaining_ms_fn is not None + remaining = timedelta(milliseconds=remaining_ms_fn()) + work_time = remaining - shutdown_buffer + if work_time <= timedelta(seconds=1): + raise RuntimeError( + f"Lambda timeout is too short: {remaining.total_seconds():.1f}s " + f"remaining but {shutdown_buffer.total_seconds():.1f}s is " + f"reserved for shutdown, leaving no time for work. " + f"Increase the function timeout or decrease the shutdown " + f"deadline buffer" + ) + elif work_time < timedelta(seconds=5): + logger.warning( + "Lambda timeout leaves less than 5s for work after " + "shutdown buffer; consider increasing the function " + "timeout or decreasing the shutdown deadline buffer " + "(work_time=%s, shutdown_buffer=%s)", + work_time, + shutdown_buffer, + ) + + # Build per-invocation connect kwargs with identity from Lambda context. + invocation_connect_kwargs: ClientConnectConfig = {**config.client_connect_config} + if "identity" not in invocation_connect_kwargs: + ctx_info = extract_lambda_ctx(lambda_context) + if ctx_info is not None: + request_id, function_arn = ctx_info + invocation_connect_kwargs["identity"] = build_lambda_identity( + request_id, function_arn + ) + + # Connect to Temporal. + client = await deps.connect(**invocation_connect_kwargs) + + # Create the worker. + worker = deps.create_worker(client, **config.worker_config) + + # Run the worker until the deadline approaches or context is done. + if deadline_available: + assert remaining_ms_fn is not None + work_time_secs = ( + timedelta(milliseconds=remaining_ms_fn()) - shutdown_buffer + ).total_seconds() + if work_time_secs > 0: + try: + await asyncio.wait_for(worker.run(), timeout=work_time_secs) + except asyncio.TimeoutError: + pass + else: + # No deadline - run until cancelled. + await worker.run() + + # Run shutdown hooks after worker has stopped. + await _run_shutdown_hooks(config) diff --git a/temporalio/contrib/aws/lambda_worker/otel.py b/temporalio/contrib/aws/lambda_worker/otel.py new file mode 100644 index 000000000..216e80f48 --- /dev/null +++ b/temporalio/contrib/aws/lambda_worker/otel.py @@ -0,0 +1,241 @@ +"""OpenTelemetry helpers for Temporal workers running inside AWS Lambda. + +Use :py:func:`apply_defaults` inside a :py:func:`run_worker` configure callback for a +batteries-included setup that creates an OTel collector exporter and tracing plugin, suitable +for use with the AWS Distro for OpenTelemetry (ADOT) Lambda layer. + +Use :py:func:`apply_tracing` or :py:func:`build_metrics_telemetry_config` individually if you only +need one. +""" + +from __future__ import annotations + +import logging +import os +from dataclasses import dataclass, field +from datetime import timedelta + +from opentelemetry.sdk.resources import Resource +from opentelemetry.sdk.trace.export import BatchSpanProcessor +from opentelemetry.semconv.attributes.service_attributes import SERVICE_NAME +from opentelemetry.trace import get_tracer_provider, set_tracer_provider + +from temporalio.contrib.aws.lambda_worker._configure import LambdaWorkerConfig +from temporalio.contrib.opentelemetry import OpenTelemetryPlugin, create_tracer_provider +from temporalio.runtime import OpenTelemetryConfig, Runtime, TelemetryConfig + +logger = logging.getLogger(__name__) + + +@dataclass +class OtelOptions: + """Options for :py:func:`apply_defaults`. + + Attributes: + metric_periodicity: How often the Core SDK exports metrics to the + collector. Defaults to 10 seconds. Set this shorter than your + Lambda timeout to ensure at least one export per invocation. + service_name: OTel service name resource attribute. If empty, + falls back to ``OTEL_SERVICE_NAME``, then + ``AWS_LAMBDA_FUNCTION_NAME``, then + ``"temporal-lambda-worker"``. + collector_endpoint: OTLP collector endpoint (e.g. + ``"http://localhost:4317"``). If empty, falls back to + ``OTEL_EXPORTER_OTLP_ENDPOINT``, then + ``"http://localhost:4317"``. + """ + + metric_periodicity: timedelta = field(default_factory=lambda: timedelta(seconds=10)) + service_name: str = "" + collector_endpoint: str = "" + + +def _resolve_service_name(options: OtelOptions) -> str: + service_name = options.service_name + if not service_name: + service_name = os.environ.get("OTEL_SERVICE_NAME", "") + if not service_name: + service_name = os.environ.get("AWS_LAMBDA_FUNCTION_NAME", "") + if not service_name: + service_name = "temporal-lambda-worker" + return service_name + + +def _resolve_endpoint(options: OtelOptions) -> str: + endpoint = options.collector_endpoint + if not endpoint: + endpoint = os.environ.get("OTEL_EXPORTER_OTLP_ENDPOINT", "") + if not endpoint: + endpoint = "http://localhost:4317" + return endpoint + + +def apply_defaults( + config: LambdaWorkerConfig, + options: OtelOptions | None = None, +) -> None: + """Configure OTel metrics and tracing with AWS Lambda defaults. + + Sets up Core SDK metrics export via a :py:class:`temporalio.runtime.Runtime` with an + :py:class:`temporalio.runtime.OpenTelemetryConfig` pointing at the OTLP collector, and adds the + :py:class:`temporalio.contrib.opentelemetry.OpenTelemetryPlugin` for distributed tracing with + workflow sandbox passthrough. + + Creates a replay-safe ``TracerProvider`` (with X-Ray ID generator and OTLP gRPC exporter if + available) and sets it as the global OpenTelemetry tracer provider. The + :py:class:`temporalio.contrib.opentelemetry.OpenTelemetryPlugin` uses the global provider, so + it must be set before the worker starts. + + The collector endpoint defaults to ``http://localhost:4317``, which is the endpoint expected by + the ADOT collector Lambda layer. + + Registers a per-invocation ``ForceFlush`` shutdown hook for the global ``TracerProvider`` so + pending traces are exported before each Lambda invocation completes. + + Metrics are exported on the ``metric_periodicity`` interval by the runtime's internal thread. + There is no explicit flush API for these metrics; set ``metric_periodicity`` short enough to + ensure at least one export per invocation. + + Args: + config: The :py:class:`LambdaWorkerConfig` to configure. + options: Optional overrides for service name, endpoint, etc. + """ + if options is None: + options = OtelOptions() + + endpoint = _resolve_endpoint(options) + service_name = _resolve_service_name(options) + + telemetry_config = build_metrics_telemetry_config( + endpoint=endpoint, + service_name=service_name, + metric_periodicity=options.metric_periodicity, + ) + runtime = Runtime(telemetry=telemetry_config) + config.client_connect_config["runtime"] = runtime + + resource = Resource.create({SERVICE_NAME: service_name}) + + # Try to use X-Ray ID generator if available. + try: + from opentelemetry.sdk.extension.aws.trace import ( # type: ignore[reportMissingTypeStubs] + AwsXRayIdGenerator, + ) + + tracer_provider = create_tracer_provider( + resource=resource, id_generator=AwsXRayIdGenerator() + ) + except ImportError: + logger.warning( + "opentelemetry-sdk-extension-aws is not installed; " + "X-Ray trace ID generation is disabled. " + "Install the 'lambda-worker-otel' extra for full ADOT support." + ) + tracer_provider = create_tracer_provider(resource=resource) + + # Use OTLP gRPC exporter if available, otherwise skip trace export. + try: + from opentelemetry.exporter.otlp.proto.grpc.trace_exporter import ( + OTLPSpanExporter, + ) + + tracer_provider.add_span_processor( + BatchSpanProcessor(OTLPSpanExporter(endpoint=endpoint, insecure=True)) + ) + except ImportError: + logger.warning( + "opentelemetry-exporter-otlp-proto-grpc is not installed; " + "traces will not be exported to the OTLP collector. " + "Install the 'lambda-worker-otel' extra for full ADOT support." + ) + + # Set as global so the OpenTelemetryPlugin picks it up. + set_tracer_provider(tracer_provider) + + apply_tracing(config) + + +def build_metrics_telemetry_config( + *, + endpoint: str = "", + service_name: str = "", + metric_periodicity: timedelta | None = None, +) -> TelemetryConfig: + """Build a :py:class:`temporalio.runtime.TelemetryConfig` for OTel metrics. + + Returns a ``TelemetryConfig`` with :py:class:`temporalio.runtime.OpenTelemetryConfig` metrics + pointed at the given OTLP collector endpoint. Use this when you need to compose metrics config + with other telemetry settings (e.g. custom logging) into your own + :py:class:`temporalio.runtime.Runtime`. + + Core SDK metrics are exported on the ``metric_periodicity`` interval by the runtime's internal + thread. There is no explicit flush API; set ``metric_periodicity`` short enough to ensure at + least one export per Lambda invocation. + + Example:: + + telemetry = build_metrics_telemetry_config( + endpoint="http://localhost:4317", + service_name="my-service", + ) + # Customize further: + telemetry_config = dataclasses.replace( + telemetry, logging=my_logging_config + ) + runtime = Runtime(telemetry=telemetry_config) + config.client_connect_config["runtime"] = runtime + + Args: + endpoint: OTLP collector endpoint. Defaults to + ``http://localhost:4317``. + service_name: OTel service name. Used as a global tag. + metric_periodicity: How often metrics are exported. + + Returns: + A ``TelemetryConfig`` ready to pass to + :py:class:`temporalio.runtime.Runtime`. + """ + if not endpoint: + endpoint = "http://localhost:4317" + + otel_config = OpenTelemetryConfig( + url=endpoint, + metric_periodicity=metric_periodicity, + ) + + global_tags: dict[str, str] = {} + if service_name: + global_tags["service_name"] = service_name + + return TelemetryConfig( + metrics=otel_config, + global_tags=global_tags, + ) + + +def apply_tracing(config: LambdaWorkerConfig) -> None: + """Configure only OTel tracing (no metrics) on the Lambda worker config. + + Adds an :py:class:`temporalio.contrib.opentelemetry.OpenTelemetryPlugin` to + ``config.worker_config["plugins"]``. The plugin uses the global + ``TracerProvider`` set via ``opentelemetry.trace.set_tracer_provider``. + Ensure your provider is set globally before the worker starts. + + Also registers a ``ForceFlush`` shutdown hook that flushes the global + ``TracerProvider`` (if it supports ``force_flush``). + + Args: + config: The :py:class:`LambdaWorkerConfig` to configure. + """ + plugin = OpenTelemetryPlugin() + plugins = list(config.worker_config.get("plugins", [])) + plugins.append(plugin) + config.worker_config["plugins"] = plugins + + async def _flush() -> None: + provider = get_tracer_provider() + flush = getattr(provider, "force_flush", None) + if flush is not None: + flush() + + config.shutdown_hooks.append(_flush) diff --git a/temporalio/contrib/aws/s3driver/_driver.py b/temporalio/contrib/aws/s3driver/_driver.py index 1f9d129c9..9e68697ac 100644 --- a/temporalio/contrib/aws/s3driver/_driver.py +++ b/temporalio/contrib/aws/s3driver/_driver.py @@ -64,7 +64,7 @@ def __init__( Args: client: An :class:`S3StorageDriverClient` implementation. Use - :func:`~temporalio.contrib.aws.s3driver.aioboto3.new_aioboto3_client` to + :func:`temporalio.contrib.aws.s3driver.aioboto3.new_aioboto3_client` to wrap an aioboto3 S3 client. bucket: S3 bucket name, access point ARN, or a callable that accepts ``(StorageDriverStoreContext, Payload)`` and returns @@ -73,7 +73,7 @@ def __init__( driver_name: Name of this driver instance. Defaults to ``"aws.s3driver"``. Override when registering multiple S3StorageDriver instances with distinct configurations - under the same :attr:`~temporalio.extstore.Options.drivers` list. + under the same ``temporalio.extstore.Options.drivers`` list. max_payload_size: Maximum serialized payload size in bytes that the driver will accept. Defaults to 52428800 (50 MiB). Raise this value if your workload requires larger payloads; lower it to @@ -105,7 +105,7 @@ async def store( context: StorageDriverStoreContext, payloads: Sequence[Payload], ) -> list[StorageDriverClaim]: - """Stores payloads in S3 and returns a :class:`~temporalio.extstore.DriverClaim` for each one. + """Stores payloads in S3 and returns a ``temporalio.extstore.DriverClaim`` for each one. Payloads are keyed by their SHA-256 hash, so identical serialized bytes share the same S3 object. Deduplication is best-effort because the same @@ -175,7 +175,7 @@ async def retrieve( context: StorageDriverRetrieveContext, # noqa: ARG002 claims: Sequence[StorageDriverClaim], ) -> list[Payload]: - """Retrieves payloads from S3 for the given :class:`~temporalio.extstore.DriverClaim` list.""" + """Retrieves payloads from S3 for the given ``temporalio.extstore.DriverClaim`` list.""" async def _download(claim: StorageDriverClaim) -> Payload: bucket = claim.claim_data["bucket"] diff --git a/tests/conftest.py b/tests/conftest.py index c813f91f9..e2ab2149e 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -4,8 +4,10 @@ import sys from collections.abc import AsyncGenerator, Iterator +import opentelemetry.trace import pytest import pytest_asyncio +from opentelemetry.util._once import Once from temporalio.client import Client from temporalio.testing import WorkflowEnvironment @@ -196,3 +198,13 @@ def pytest_cmdline_main(config): # type: ignore[reportMissingParameterType, rep @pytest.fixture def continue_as_new_suggest_history_count() -> int: return CONTINUE_AS_NEW_SUGGEST_HISTORY_COUNT + + +@pytest.fixture +def reset_otel_tracer_provider(): + """Reset global OpenTelemetry tracer provider state around tests.""" + opentelemetry.trace._TRACER_PROVIDER_SET_ONCE = Once() + opentelemetry.trace._TRACER_PROVIDER = None + yield + opentelemetry.trace._TRACER_PROVIDER_SET_ONCE = Once() + opentelemetry.trace._TRACER_PROVIDER = None diff --git a/tests/contrib/aws/lambda_worker/__init__.py b/tests/contrib/aws/lambda_worker/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/tests/contrib/aws/lambda_worker/test_lambda_worker.py b/tests/contrib/aws/lambda_worker/test_lambda_worker.py new file mode 100644 index 000000000..178e078ac --- /dev/null +++ b/tests/contrib/aws/lambda_worker/test_lambda_worker.py @@ -0,0 +1,522 @@ +"""Tests for temporalio.contrib.aws.lambda_worker.""" + +from __future__ import annotations + +from datetime import timedelta +from pathlib import Path +from typing import Any +from unittest.mock import AsyncMock, MagicMock, patch + +import pytest + +from temporalio.common import WorkerDeploymentVersion +from temporalio.contrib.aws.lambda_worker._configure import ( + LambdaWorkerConfig, + _run_shutdown_hooks, +) +from temporalio.contrib.aws.lambda_worker._defaults import ( + DEFAULT_MAX_CACHED_WORKFLOWS, + DEFAULT_MAX_CONCURRENT_ACTIVITIES, + DEFAULT_MAX_CONCURRENT_LOCAL_ACTIVITIES, + DEFAULT_MAX_CONCURRENT_NEXUS_TASKS, + DEFAULT_MAX_CONCURRENT_WORKFLOW_TASKS, + apply_lambda_worker_defaults, + build_lambda_identity, + lambda_default_config_file_path, +) +from temporalio.contrib.aws.lambda_worker._run_worker import ( + _run_worker_internal, + _WorkerDeps, +) +from temporalio.envconfig import ClientConfigProfile +from temporalio.worker import WorkerConfig + +TEST_VERSION = WorkerDeploymentVersion( + deployment_name="test-deployment", + build_id="test-build", +) + + +# ---- LambdaWorkerConfig tests ---- + + +class TestLambdaWorkerConfig: + def test_worker_config_task_queue(self) -> None: + config = LambdaWorkerConfig() + assert config.worker_config.get("task_queue") is None + config.worker_config["task_queue"] = "my-queue" + assert config.worker_config["task_queue"] == "my-queue" + + def test_worker_config_workflows(self) -> None: + config = LambdaWorkerConfig() + + class FakeWorkflow: + pass + + config.worker_config["workflows"] = [FakeWorkflow] + assert FakeWorkflow in config.worker_config["workflows"] + + def test_worker_config_activities(self) -> None: + config = LambdaWorkerConfig() + + def fake_activity() -> None: + pass + + config.worker_config["activities"] = [fake_activity] + assert fake_activity in config.worker_config["activities"] + + def test_client_connect_config_directly_modifiable(self) -> None: + config = LambdaWorkerConfig() + config.client_connect_config["namespace"] = "custom-ns" + assert config.client_connect_config["namespace"] == "custom-ns" + + def test_worker_config_directly_modifiable(self) -> None: + config = LambdaWorkerConfig() + config.worker_config["max_concurrent_activities"] = 42 + assert config.worker_config["max_concurrent_activities"] == 42 + + def test_shutdown_deadline_buffer(self) -> None: + config = LambdaWorkerConfig() + config.shutdown_deadline_buffer = timedelta(seconds=5) + assert config.shutdown_deadline_buffer == timedelta(seconds=5) + + def test_shutdown_hooks_list(self) -> None: + config = LambdaWorkerConfig() + fn = MagicMock() + config.shutdown_hooks.append(fn) + assert fn in config.shutdown_hooks + + @pytest.mark.asyncio + async def test_run_shutdown_hooks_in_order(self) -> None: + config = LambdaWorkerConfig() + order: list[str] = [] + config.shutdown_hooks.append(lambda: order.append("first")) + config.shutdown_hooks.append(lambda: order.append("second")) + await _run_shutdown_hooks(config) + assert order == ["first", "second"] + + @pytest.mark.asyncio + async def test_run_shutdown_hooks_async(self) -> None: + config = LambdaWorkerConfig() + called = False + + async def async_hook() -> None: + nonlocal called + called = True + + config.shutdown_hooks.append(async_hook) + await _run_shutdown_hooks(config) + assert called + + @pytest.mark.asyncio + async def test_run_shutdown_hooks_error_continues(self) -> None: + config = LambdaWorkerConfig() + second_called = False + + def failing_hook() -> None: + raise RuntimeError("flush failed") + + def second_hook() -> None: + nonlocal second_called + second_called = True + + config.shutdown_hooks.append(failing_hook) + config.shutdown_hooks.append(second_hook) + await _run_shutdown_hooks(config) + assert second_called + + def test_is_dataclass(self) -> None: + import dataclasses + + assert dataclasses.is_dataclass(LambdaWorkerConfig) + + def test_default_field_independence(self) -> None: + """Each instance gets its own mutable containers.""" + a = LambdaWorkerConfig() + b = LambdaWorkerConfig() + a.worker_config["max_concurrent_activities"] = 99 + assert "max_concurrent_activities" not in b.worker_config + + +# ---- Defaults tests ---- + + +class TestDefaults: + def test_apply_lambda_worker_defaults(self) -> None: + config: WorkerConfig = {} + apply_lambda_worker_defaults(config) + assert ( + config.get("max_concurrent_activities") == DEFAULT_MAX_CONCURRENT_ACTIVITIES + ) + assert ( + config.get("max_concurrent_workflow_tasks") + == DEFAULT_MAX_CONCURRENT_WORKFLOW_TASKS + ) + assert ( + config.get("max_concurrent_local_activities") + == DEFAULT_MAX_CONCURRENT_LOCAL_ACTIVITIES + ) + assert ( + config.get("max_concurrent_nexus_tasks") + == DEFAULT_MAX_CONCURRENT_NEXUS_TASKS + ) + assert config.get("max_cached_workflows") == DEFAULT_MAX_CACHED_WORKFLOWS + assert config.get("disable_eager_activity_execution") is True + + def test_apply_lambda_worker_defaults_preserves_existing(self) -> None: + config: WorkerConfig = { + "max_concurrent_activities": 50, + "graceful_shutdown_timeout": timedelta(seconds=10), + } + apply_lambda_worker_defaults(config) + assert config.get("max_concurrent_activities") == 50 + assert config.get("graceful_shutdown_timeout") == timedelta(seconds=10) + assert config.get("disable_eager_activity_execution") is True + + def test_build_lambda_identity(self) -> None: + assert ( + build_lambda_identity("req-123", "arn:aws:lambda:us-east-1:123:function:f") + == "req-123@arn:aws:lambda:us-east-1:123:function:f" + ) + + def test_build_lambda_identity_empty(self) -> None: + assert build_lambda_identity("", "") == "unknown@unknown" + + def test_lambda_default_config_file_path_env_var(self) -> None: + env = {"TEMPORAL_CONFIG_FILE": "/custom/path.toml"} + assert ( + lambda_default_config_file_path(env.get) # type: ignore[arg-type] + == Path("/custom/path.toml") + ) + + def test_lambda_default_config_file_path_lambda_root(self) -> None: + env = {"LAMBDA_TASK_ROOT": "/var/task"} + assert ( + lambda_default_config_file_path(env.get) # type: ignore[arg-type] + == Path("/var/task/temporal.toml") + ) + + def test_lambda_default_config_file_path_cwd(self) -> None: + env: dict[str, str] = {} + assert ( + lambda_default_config_file_path(env.get) # type: ignore[arg-type] + == Path("temporal.toml") + ) + + +# ---- RunWorker tests ---- + + +def _make_lambda_context( + *, + remaining_ms: int = 3_600_000, + request_id: str = "req-123", + function_arn: str = "arn:aws:lambda:us-east-1:123:function:my-func", +) -> Any: + """Create a mock Lambda context object.""" + ctx = MagicMock() + ctx.get_remaining_time_in_millis.return_value = remaining_ms + ctx.aws_request_id = request_id + ctx.invoked_function_arn = function_arn + return ctx + + +def _make_test_deps( + *, + connect_kwargs_capture: list[dict[str, Any]] | None = None, + worker_kwargs_capture: list[dict[str, Any]] | None = None, +) -> _WorkerDeps: + """Create test deps with mocked connect and worker.""" + mock_client = MagicMock() + mock_worker = MagicMock() + mock_worker.run = AsyncMock() + + async def fake_connect(**kwargs: Any) -> Any: + if connect_kwargs_capture is not None: + connect_kwargs_capture.append(kwargs) + return mock_client + + def fake_create_worker(_client: Any, **kwargs: Any) -> Any: + if worker_kwargs_capture is not None: + worker_kwargs_capture.append(kwargs) + return mock_worker + + return _WorkerDeps( + connect=fake_connect, + create_worker=fake_create_worker, + load_config=lambda: ClientConfigProfile(), + getenv={"TEMPORAL_TASK_QUEUE": "test-queue"}.get, # type: ignore[arg-type] + extract_lambda_ctx=lambda ctx: ( + ctx.aws_request_id, + ctx.invoked_function_arn, + ) + if hasattr(ctx, "aws_request_id") + else None, + ) + + +class TestRunWorkerInternal: + def test_returns_handler(self) -> None: + deps = _make_test_deps() + handler = _run_worker_internal(TEST_VERSION, lambda config: None, deps) + assert callable(handler) + + def test_success(self) -> None: + deps = _make_test_deps() + + def configure(config: LambdaWorkerConfig) -> None: + config.worker_config["workflows"] = [type("FakeWf", (), {})] + + handler = _run_worker_internal(TEST_VERSION, configure, deps) + handler({}, _make_lambda_context()) + + def test_configure_callback_error(self) -> None: + deps = _make_test_deps() + + def bad_configure(_config: LambdaWorkerConfig) -> None: + raise RuntimeError("bad config") + + with pytest.raises(RuntimeError, match="bad config"): + _run_worker_internal(TEST_VERSION, bad_configure, deps) + + def test_missing_task_queue(self) -> None: + deps = _make_test_deps() + deps.getenv = lambda _: None # type: ignore[assignment] + with pytest.raises(ValueError, match="task queue not configured"): + _run_worker_internal(TEST_VERSION, lambda config: None, deps) + + def test_missing_version(self) -> None: + deps = _make_test_deps() + with pytest.raises(ValueError, match="version is required"): + _run_worker_internal( + WorkerDeploymentVersion(deployment_name="", build_id=""), + lambda config: None, + deps, + ) + + def test_user_overrides_applied(self) -> None: + connect_capture: list[dict[str, Any]] = [] + worker_capture: list[dict[str, Any]] = [] + deps = _make_test_deps( + connect_kwargs_capture=connect_capture, + worker_kwargs_capture=worker_capture, + ) + + def configure(config: LambdaWorkerConfig) -> None: + config.worker_config["task_queue"] = "user-queue" + config.client_connect_config["namespace"] = "custom-ns" + config.worker_config["max_concurrent_activities"] = 99 + + handler = _run_worker_internal(TEST_VERSION, configure, deps) + handler({}, _make_lambda_context()) + + assert connect_capture[0]["namespace"] == "custom-ns" + assert worker_capture[0]["max_concurrent_activities"] == 99 + + def test_lambda_defaults_applied(self) -> None: + worker_capture: list[dict[str, Any]] = [] + deps = _make_test_deps(worker_kwargs_capture=worker_capture) + handler = _run_worker_internal(TEST_VERSION, lambda config: None, deps) + handler({}, _make_lambda_context()) + + kwargs = worker_capture[0] + assert kwargs["max_concurrent_activities"] == DEFAULT_MAX_CONCURRENT_ACTIVITIES + assert ( + kwargs["max_concurrent_workflow_tasks"] + == DEFAULT_MAX_CONCURRENT_WORKFLOW_TASKS + ) + assert kwargs["disable_eager_activity_execution"] is True + dc = kwargs["deployment_config"] + assert dc.use_worker_versioning is True + assert dc.version == TEST_VERSION + + def test_identity_from_lambda_context(self) -> None: + connect_capture: list[dict[str, Any]] = [] + deps = _make_test_deps(connect_kwargs_capture=connect_capture) + handler = _run_worker_internal(TEST_VERSION, lambda config: None, deps) + handler( + {}, + _make_lambda_context( + request_id="req-abc-123", + function_arn="arn:aws:lambda:us-east-1:123456:function:my-func", + ), + ) + + assert ( + connect_capture[0]["identity"] + == "req-abc-123@arn:aws:lambda:us-east-1:123456:function:my-func" + ) + + def test_identity_user_override_wins(self) -> None: + connect_capture: list[dict[str, Any]] = [] + deps = _make_test_deps(connect_kwargs_capture=connect_capture) + + def configure(config: LambdaWorkerConfig) -> None: + config.client_connect_config["identity"] = "my-custom-identity" + + handler = _run_worker_internal(TEST_VERSION, configure, deps) + handler({}, _make_lambda_context()) + assert connect_capture[0]["identity"] == "my-custom-identity" + + def test_identity_no_lambda_context(self) -> None: + connect_capture: list[dict[str, Any]] = [] + deps = _make_test_deps(connect_kwargs_capture=connect_capture) + deps.extract_lambda_ctx = lambda ctx: None + handler = _run_worker_internal(TEST_VERSION, lambda config: None, deps) + handler({}, MagicMock(spec=[])) + assert "identity" not in connect_capture[0] + + def test_shutdown_hooks_called(self) -> None: + deps = _make_test_deps() + shutdown_called = False + + def configure(config: LambdaWorkerConfig) -> None: + def hook() -> None: + nonlocal shutdown_called + shutdown_called = True + + config.shutdown_hooks.append(hook) + + handler = _run_worker_internal(TEST_VERSION, configure, deps) + handler({}, _make_lambda_context()) + assert shutdown_called + + def test_shutdown_hooks_called_per_invocation(self) -> None: + deps = _make_test_deps() + shutdown_count = 0 + + def configure(config: LambdaWorkerConfig) -> None: + def hook() -> None: + nonlocal shutdown_count + shutdown_count += 1 + + config.shutdown_hooks.append(hook) + + handler = _run_worker_internal(TEST_VERSION, configure, deps) + handler({}, _make_lambda_context()) + handler({}, _make_lambda_context()) + handler({}, _make_lambda_context()) + assert shutdown_count == 3 + + def test_shutdown_hooks_multiple_funcs_order(self) -> None: + deps = _make_test_deps() + order: list[str] = [] + + def configure(config: LambdaWorkerConfig) -> None: + config.shutdown_hooks.append(lambda: order.append("first")) + config.shutdown_hooks.append(lambda: order.append("second")) + + handler = _run_worker_internal(TEST_VERSION, configure, deps) + handler({}, _make_lambda_context()) + assert order == ["first", "second"] + + def test_shutdown_hooks_error_continues(self) -> None: + deps = _make_test_deps() + second_called = False + + def configure(config: LambdaWorkerConfig) -> None: + def failing() -> None: + raise RuntimeError("flush failed") + + def second() -> None: + nonlocal second_called + second_called = True + + config.shutdown_hooks.append(failing) + config.shutdown_hooks.append(second) + + handler = _run_worker_internal(TEST_VERSION, configure, deps) + handler({}, _make_lambda_context()) + assert second_called + + def test_tight_deadline_raises_error(self) -> None: + deps = _make_test_deps() + + def configure(config: LambdaWorkerConfig) -> None: + config.shutdown_deadline_buffer = timedelta(milliseconds=1500) + + handler = _run_worker_internal(TEST_VERSION, configure, deps) + with pytest.raises(RuntimeError, match="Lambda timeout is too short"): + handler({}, _make_lambda_context(remaining_ms=2000)) + + def test_tight_deadline_logs_warning(self) -> None: + deps = _make_test_deps() + + def configure(config: LambdaWorkerConfig) -> None: + config.shutdown_deadline_buffer = timedelta(milliseconds=500) + + handler = _run_worker_internal(TEST_VERSION, configure, deps) + with patch( + "temporalio.contrib.aws.lambda_worker._run_worker.logger" + ) as mock_logger: + handler({}, _make_lambda_context(remaining_ms=2000)) + mock_logger.warning.assert_called_once() + assert "less than 5s" in mock_logger.warning.call_args[0][0] + + def test_per_invocation_lifecycle(self) -> None: + """Each invocation creates its own client and worker.""" + connect_count = 0 + deps = _make_test_deps() + original_connect = deps.connect + + async def counting_connect(**kwargs: Any) -> Any: + nonlocal connect_count + connect_count += 1 + return await original_connect(**kwargs) + + deps.connect = counting_connect + + handler = _run_worker_internal(TEST_VERSION, lambda config: None, deps) + handler({}, _make_lambda_context()) + handler({}, _make_lambda_context()) + handler({}, _make_lambda_context()) + assert connect_count == 3 + + def test_task_queue_from_config(self) -> None: + worker_capture: list[dict[str, Any]] = [] + deps = _make_test_deps(worker_kwargs_capture=worker_capture) + deps.getenv = lambda _: None # type: ignore[assignment] + + def configure(config: LambdaWorkerConfig) -> None: + config.worker_config["task_queue"] = "explicit-queue" + + handler = _run_worker_internal(TEST_VERSION, configure, deps) + handler({}, _make_lambda_context()) + assert worker_capture[0]["task_queue"] == "explicit-queue" + + def test_task_queue_pre_populated_from_env(self) -> None: + """Task queue is pre-populated from TEMPORAL_TASK_QUEUE env var.""" + deps = _make_test_deps() + task_queues: list[str | None] = [] + + def configure(config: LambdaWorkerConfig) -> None: + task_queues.append(config.worker_config.get("task_queue")) + + _run_worker_internal(TEST_VERSION, configure, deps) + assert task_queues[0] == "test-queue" + + def test_config_pre_populated_with_defaults(self) -> None: + """Configure callback receives pre-populated LambdaWorkerConfig.""" + deps = _make_test_deps() + captured: list[LambdaWorkerConfig] = [] + + def configure(config: LambdaWorkerConfig) -> None: + captured.append(config) + + _run_worker_internal(TEST_VERSION, configure, deps) + wc = captured[0].worker_config + assert wc.get("max_concurrent_activities") == DEFAULT_MAX_CONCURRENT_ACTIVITIES + assert wc.get("disable_eager_activity_execution") is True + dc = wc.get("deployment_config") + assert dc is not None + assert dc.use_worker_versioning is True + assert dc.version == TEST_VERSION + + def test_no_deadline_runs_until_complete(self) -> None: + """When no deadline is available, worker runs until it completes.""" + deps = _make_test_deps() + handler = _run_worker_internal(TEST_VERSION, lambda config: None, deps) + ctx = MagicMock(spec=["aws_request_id", "invoked_function_arn"]) + ctx.aws_request_id = "req-123" + ctx.invoked_function_arn = "arn:aws:lambda:us-east-1:123:function:f" + handler({}, ctx) diff --git a/tests/contrib/aws/lambda_worker/test_otel.py b/tests/contrib/aws/lambda_worker/test_otel.py new file mode 100644 index 000000000..97f3d9647 --- /dev/null +++ b/tests/contrib/aws/lambda_worker/test_otel.py @@ -0,0 +1,167 @@ +"""Tests for temporalio.contrib.aws.lambda_worker.otel.""" + +from __future__ import annotations + +from datetime import timedelta +from unittest.mock import patch + +import pytest + +from temporalio.contrib.aws.lambda_worker._configure import ( + LambdaWorkerConfig, + _run_shutdown_hooks, +) +from temporalio.contrib.aws.lambda_worker.otel import ( + OtelOptions, + apply_defaults, + apply_tracing, + build_metrics_telemetry_config, +) +from temporalio.contrib.opentelemetry import OpenTelemetryPlugin +from temporalio.runtime import OpenTelemetryConfig, TelemetryConfig + + +class TestApplyTracing: + def test_adds_plugin(self) -> None: + config = LambdaWorkerConfig() + apply_tracing(config) + plugins = config.worker_config.get("plugins", []) + assert len(plugins) == 1 + assert isinstance(plugins[0], OpenTelemetryPlugin) + + def test_appends_to_existing_plugins(self) -> None: + config = LambdaWorkerConfig() + existing = OpenTelemetryPlugin() + config.worker_config["plugins"] = [existing] + apply_tracing(config) + plugins = config.worker_config["plugins"] + assert len(plugins) == 2 + assert plugins[0] is existing + + def test_registers_flush_shutdown_hook(self) -> None: + config = LambdaWorkerConfig() + apply_tracing(config) + assert len(config.shutdown_hooks) == 1 + + @pytest.mark.asyncio + async def test_shutdown_hook_flushes(self) -> None: + config = LambdaWorkerConfig() + apply_tracing(config) + # Should not raise even with the default noop global provider. + await _run_shutdown_hooks(config) + + +class TestBuildMetricsTelemetryConfig: + def test_returns_telemetry_config(self) -> None: + tc = build_metrics_telemetry_config(endpoint="http://localhost:4317") + assert isinstance(tc, TelemetryConfig) + assert isinstance(tc.metrics, OpenTelemetryConfig) + assert tc.metrics.url == "http://localhost:4317" + + def test_default_endpoint(self) -> None: + tc = build_metrics_telemetry_config() + assert isinstance(tc.metrics, OpenTelemetryConfig) + assert tc.metrics.url == "http://localhost:4317" + + def test_service_name_as_global_tag(self) -> None: + tc = build_metrics_telemetry_config(service_name="my-svc") + assert tc.global_tags.get("service_name") == "my-svc" + + def test_no_service_name_no_tag(self) -> None: + tc = build_metrics_telemetry_config() + assert "service_name" not in tc.global_tags + + def test_metric_periodicity(self) -> None: + tc = build_metrics_telemetry_config(metric_periodicity=timedelta(seconds=30)) + assert isinstance(tc.metrics, OpenTelemetryConfig) + assert tc.metrics.metric_periodicity == timedelta(seconds=30) + + def test_composable_with_custom_runtime(self) -> None: + """User can compose the returned config into a custom Runtime.""" + import dataclasses + + tc = build_metrics_telemetry_config(endpoint="http://localhost:4317") + custom_tc = dataclasses.replace(tc, logging=None) + assert custom_tc.logging is None + assert isinstance(custom_tc.metrics, OpenTelemetryConfig) + + +class TestApplyDefaults: + def test_configures_metrics_and_tracing(self) -> None: + config = LambdaWorkerConfig() + apply_defaults(config, OtelOptions(collector_endpoint="http://localhost:4317")) + + # Metrics: runtime should be set. + assert "runtime" in config.client_connect_config + # Tracing: plugin should be added. + plugins = config.worker_config.get("plugins", []) + assert len(plugins) == 1 + assert isinstance(plugins[0], OpenTelemetryPlugin) + # Shutdown hook for tracer flush. + assert len(config.shutdown_hooks) == 1 + + def test_sets_global_tracer_provider(self) -> None: + from opentelemetry.trace import get_tracer_provider + + from temporalio.contrib.opentelemetry._tracer_provider import ( + ReplaySafeTracerProvider, + ) + + config = LambdaWorkerConfig() + apply_defaults(config) + provider = get_tracer_provider() + assert isinstance(provider, ReplaySafeTracerProvider) + + def test_service_name_from_options(self) -> None: + config = LambdaWorkerConfig() + apply_defaults(config, OtelOptions(service_name="my-service")) + assert "runtime" in config.client_connect_config + + def test_service_name_from_env(self) -> None: + config = LambdaWorkerConfig() + with patch.dict("os.environ", {"OTEL_SERVICE_NAME": "env-service"}): + apply_defaults(config) + assert "runtime" in config.client_connect_config + + def test_service_name_from_lambda_function_name(self) -> None: + config = LambdaWorkerConfig() + with patch.dict( + "os.environ", + {"AWS_LAMBDA_FUNCTION_NAME": "my-lambda"}, + clear=True, + ): + apply_defaults(config) + assert "runtime" in config.client_connect_config + + def test_endpoint_from_env(self) -> None: + config = LambdaWorkerConfig() + with patch.dict( + "os.environ", + {"OTEL_EXPORTER_OTLP_ENDPOINT": "http://custom:4317"}, + ): + apply_defaults(config) + assert "runtime" in config.client_connect_config + + def test_default_options_used_when_none(self) -> None: + config = LambdaWorkerConfig() + apply_defaults(config) + assert "runtime" in config.client_connect_config + assert len(config.shutdown_hooks) == 1 + + +class TestOtelOptions: + def test_defaults(self) -> None: + opts = OtelOptions() + assert opts.service_name == "" + assert opts.collector_endpoint == "" + assert opts.metric_periodicity == timedelta(seconds=10) + + def test_custom_values(self) -> None: + opts = OtelOptions( + service_name="svc", + collector_endpoint="http://host:4317", + metric_periodicity=timedelta(seconds=30), + ) + assert opts.service_name == "svc" + assert opts.collector_endpoint == "http://host:4317" + assert opts.metric_periodicity == timedelta(seconds=30) diff --git a/tests/contrib/google_adk_agents/test_google_adk_agents.py b/tests/contrib/google_adk_agents/test_google_adk_agents.py index 4d41b6a82..22e6be4d8 100644 --- a/tests/contrib/google_adk_agents/test_google_adk_agents.py +++ b/tests/contrib/google_adk_agents/test_google_adk_agents.py @@ -501,7 +501,10 @@ async def test_mcp_agent(client: Client, use_local_model: bool): @pytest.mark.asyncio -async def test_single_agent_telemetry(client: Client): +async def test_single_agent_telemetry( + client: Client, + reset_otel_tracer_provider, # type: ignore[reportUnusedParameter] +): exporter = InMemorySpanExporter() provider = create_tracer_provider() provider.add_span_processor(SimpleSpanProcessor(exporter)) diff --git a/tests/contrib/openai_agents/test_openai_tracing.py b/tests/contrib/openai_agents/test_openai_tracing.py index a13911ac2..5414f7916 100644 --- a/tests/contrib/openai_agents/test_openai_tracing.py +++ b/tests/contrib/openai_agents/test_openai_tracing.py @@ -265,19 +265,16 @@ def print_otel_spans(spans: tuple[ReadableSpan, ...]): def set_test_tracer_provider() -> InMemorySpanExporter: exporter = InMemorySpanExporter() - # Reset global so tests don't conflict - from opentelemetry.util._once import Once - - opentelemetry.trace._TRACER_PROVIDER_SET_ONCE = Once() - opentelemetry.trace._TRACER_PROVIDER = None - provider = create_tracer_provider() provider.add_span_processor(SimpleSpanProcessor(exporter)) opentelemetry.trace.set_tracer_provider(provider) return exporter -async def test_external_trace_to_workflow_spans(client: Client): +async def test_external_trace_to_workflow_spans( + client: Client, + reset_otel_tracer_provider: Any, # type: ignore[reportUnusedParameter] +): """Test: External trace -> workflow spans (with worker restart).""" exporter = set_test_tracer_provider() workflow_id = None @@ -364,7 +361,10 @@ async def ready() -> bool: ), f"All spans should have unique IDs, got: {span_ids}" -async def test_external_trace_and_span_to_workflow_spans(client: Client): +async def test_external_trace_and_span_to_workflow_spans( + client: Client, + reset_otel_tracer_provider: Any, # type: ignore[reportUnusedParameter] +): """Test: External trace + span -> workflow spans (with worker restart).""" exporter = set_test_tracer_provider() workflow_id = None @@ -461,7 +461,10 @@ async def ready() -> bool: ), f"All spans should have unique IDs, got: {span_ids}" -async def test_workflow_only_trace_to_spans(client: Client): +async def test_workflow_only_trace_to_spans( + client: Client, + reset_otel_tracer_provider: Any, # type: ignore[reportUnusedParameter] +): """Test: Workflow-only trace -> spans (with worker restart).""" exporter = set_test_tracer_provider() workflow_id = None @@ -551,7 +554,10 @@ async def run(self) -> str: return "done" -async def test_custom_span_without_trace_context(client: Client): +async def test_custom_span_without_trace_context( + client: Client, + reset_otel_tracer_provider: Any, # type: ignore[reportUnusedParameter] +): """Test that custom_span() without a trace context emits no spans. This validates our hypothesis about why the main test fails: @@ -591,7 +597,10 @@ async def test_custom_span_without_trace_context(client: Client): ), f"Expected no spans without trace context, but found: {[s.name for s in spans]}" -async def test_otel_tracing_in_runner(client: Client): +async def test_otel_tracing_in_runner( + client: Client, + reset_otel_tracer_provider: Any, # type: ignore[reportUnusedParameter] +): """Test the tracing when executing an actual OpenAI Runner.""" exporter = set_test_tracer_provider() @@ -750,7 +759,10 @@ def proceed(self) -> None: self._proceed = True -async def test_sdk_trace_to_otel_span_parenting(client: Client): +async def test_sdk_trace_to_otel_span_parenting( + client: Client, + reset_otel_tracer_provider: Any, # type: ignore[reportUnusedParameter] +): """Test that OTEL spans started in workflow are properly parented to client SDK trace.""" exporter = set_test_tracer_provider() workflow_id = None diff --git a/tests/contrib/opentelemetry/test_opentelemetry_plugin.py b/tests/contrib/opentelemetry/test_opentelemetry_plugin.py index b2ff2f913..dd1b20024 100644 --- a/tests/contrib/opentelemetry/test_opentelemetry_plugin.py +++ b/tests/contrib/opentelemetry/test_opentelemetry_plugin.py @@ -13,7 +13,6 @@ from opentelemetry.trace import ( get_tracer, ) -from opentelemetry.util._once import Once import temporalio.contrib.opentelemetry.workflow from temporalio import activity, nexus, workflow @@ -30,16 +29,6 @@ logger = logging.getLogger(__name__) -@pytest.fixture -def reset_otel_tracer_provider(): - """Reset OpenTelemetry tracer provider state to allow multiple test runs.""" - opentelemetry.trace._TRACER_PROVIDER_SET_ONCE = Once() - opentelemetry.trace._TRACER_PROVIDER = None - yield - opentelemetry.trace._TRACER_PROVIDER_SET_ONCE = Once() - opentelemetry.trace._TRACER_PROVIDER = None - - @activity.defn async def simple_no_context_activity() -> str: with get_tracer(__name__).start_as_current_span("Activity"): diff --git a/tests/test_client.py b/tests/test_client.py index b8bebdaf7..530c166f0 100644 --- a/tests/test_client.py +++ b/tests/test_client.py @@ -1552,6 +1552,21 @@ def test_fork_create_client( self.run(mp_fork_ctx) +def test_client_connect_config_matches_connect_params(): + """ClientConnectConfig TypedDict keys must match Client.connect kwargs.""" + import inspect + + from temporalio.client import Client, ClientConnectConfig + + connect_params = set(inspect.signature(Client.connect).parameters.keys()) - {"cls"} + config_keys = set(ClientConnectConfig.__annotations__.keys()) + assert config_keys == connect_params, ( + f"ClientConnectConfig is out of sync with Client.connect. " + f"Missing from config: {connect_params - config_keys}. " + f"Extra in config: {config_keys - connect_params}." + ) + + class TestForkUseClient(_TestFork): async def coro(self): await self._client.start_workflow( diff --git a/tests/worker/test_worker.py b/tests/worker/test_worker.py index 4c76a7ba9..4aa366735 100644 --- a/tests/worker/test_worker.py +++ b/tests/worker/test_worker.py @@ -1543,3 +1543,18 @@ async def test_continue_as_new_with_version_upgrade( # Expect workflow to return "v2.0", indicating that it continued-as-new and completed on v2 result = await handle.result() assert result == "v2.0" + + +def test_worker_config_matches_init_params(): + """WorkerConfig TypedDict keys must match Worker.__init__ kwargs.""" + import inspect + + from temporalio.worker import Worker, WorkerConfig + + init_params = set(inspect.signature(Worker.__init__).parameters.keys()) - {"self"} + config_keys = set(WorkerConfig.__annotations__.keys()) + assert config_keys == init_params, ( + f"WorkerConfig is out of sync with Worker.__init__. " + f"Missing from config: {init_params - config_keys}. " + f"Extra in config: {config_keys - init_params}." + ) diff --git a/uv.lock b/uv.lock index f1b27b400..c0fe6ec17 100644 --- a/uv.lock +++ b/uv.lock @@ -3379,6 +3379,24 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/08/13/b4ef09837409a777f3c0af2a5b4ba9b7af34872bc43609dda0c209e4060d/opentelemetry_exporter_otlp_proto_common-1.37.0-py3-none-any.whl", hash = "sha256:53038428449c559b0c564b8d718df3314da387109c4d36bd1b94c9a641b0292e", size = 18359, upload-time = "2025-09-11T10:28:44.939Z" }, ] +[[package]] +name = "opentelemetry-exporter-otlp-proto-grpc" +version = "1.37.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "googleapis-common-protos" }, + { name = "grpcio" }, + { name = "opentelemetry-api" }, + { name = "opentelemetry-exporter-otlp-proto-common" }, + { name = "opentelemetry-proto" }, + { name = "opentelemetry-sdk" }, + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/d1/11/4ad0979d0bb13ae5a845214e97c8d42da43980034c30d6f72d8e0ebe580e/opentelemetry_exporter_otlp_proto_grpc-1.37.0.tar.gz", hash = "sha256:f55bcb9fc848ce05ad3dd954058bc7b126624d22c4d9e958da24d8537763bec5", size = 24465, upload-time = "2025-09-11T10:29:04.172Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/39/17/46630b74751031a658706bef23ac99cdc2953cd3b2d28ec90590a0766b3e/opentelemetry_exporter_otlp_proto_grpc-1.37.0-py3-none-any.whl", hash = "sha256:aee5104835bf7993b7ddaaf380b6467472abaedb1f1dbfcc54a52a7d781a3890", size = 19305, upload-time = "2025-09-11T10:28:45.776Z" }, +] + [[package]] name = "opentelemetry-exporter-otlp-proto-http" version = "1.37.0" @@ -3453,6 +3471,18 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/9f/62/9f4ad6a54126fb00f7ed4bb5034964c6e4f00fcd5a905e115bd22707e20d/opentelemetry_sdk-1.37.0-py3-none-any.whl", hash = "sha256:8f3c3c22063e52475c5dbced7209495c2c16723d016d39287dfc215d1771257c", size = 131941, upload-time = "2025-09-11T10:28:57.83Z" }, ] +[[package]] +name = "opentelemetry-sdk-extension-aws" +version = "2.1.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "opentelemetry-sdk" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/f5/b3/825c93fe4c238845f1356297abea33d03b2adaafb5ae98fc257b394de124/opentelemetry_sdk_extension_aws-2.1.0.tar.gz", hash = "sha256:ff68ddecc1910f62c019d22ec0f7461713ead7f662d6a2304d4089c1a0b20416", size = 16334, upload-time = "2024-12-24T15:01:57.387Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/02/61/47a6a43b7935d54b5734fbf3fb0357dd5a7d0dfaa9677b7318518fe8d507/opentelemetry_sdk_extension_aws-2.1.0-py3-none-any.whl", hash = "sha256:c7cf6efc275d2c24108a468d954287ce5aab9733bac816a080cfb3117374e63a", size = 18776, upload-time = "2024-12-24T15:01:56.053Z" }, +] + [[package]] name = "opentelemetry-semantic-conventions" version = "0.58b0" @@ -4801,6 +4831,13 @@ google-adk = [ grpc = [ { name = "grpcio" }, ] +lambda-worker-otel = [ + { name = "opentelemetry-api" }, + { name = "opentelemetry-exporter-otlp-proto-grpc" }, + { name = "opentelemetry-sdk" }, + { name = "opentelemetry-sdk-extension-aws" }, + { name = "opentelemetry-semantic-conventions" }, +] openai-agents = [ { name = "mcp" }, { name = "openai-agents" }, @@ -4828,6 +4865,9 @@ dev = [ { name = "openai-agents", extra = ["litellm"], marker = "python_full_version < '3.14'" }, { name = "openinference-instrumentation-google-adk" }, { name = "openinference-instrumentation-openai-agents" }, + { name = "opentelemetry-exporter-otlp-proto-grpc" }, + { name = "opentelemetry-sdk-extension-aws" }, + { name = "opentelemetry-semantic-conventions" }, { name = "psutil" }, { name = "pydocstyle" }, { name = "pydoctor" }, @@ -4851,8 +4891,13 @@ requires-dist = [ { name = "mcp", marker = "extra == 'openai-agents'", specifier = ">=1.9.4,<2" }, { name = "nexus-rpc", specifier = "==1.4.0" }, { name = "openai-agents", marker = "extra == 'openai-agents'", specifier = ">=0.3,<0.7" }, + { name = "opentelemetry-api", marker = "extra == 'lambda-worker-otel'", specifier = ">=1.11.1,<2" }, { name = "opentelemetry-api", marker = "extra == 'opentelemetry'", specifier = ">=1.11.1,<2" }, + { name = "opentelemetry-exporter-otlp-proto-grpc", marker = "extra == 'lambda-worker-otel'", specifier = ">=1.11.1,<2" }, + { name = "opentelemetry-sdk", marker = "extra == 'lambda-worker-otel'", specifier = ">=1.11.1,<2" }, { name = "opentelemetry-sdk", marker = "extra == 'opentelemetry'", specifier = ">=1.11.1,<2" }, + { name = "opentelemetry-sdk-extension-aws", marker = "extra == 'lambda-worker-otel'", specifier = ">=2.0.0,<3" }, + { name = "opentelemetry-semantic-conventions", marker = "extra == 'lambda-worker-otel'", specifier = ">=0.40b0,<1" }, { name = "protobuf", specifier = ">=3.20,<7.0.0" }, { name = "pydantic", marker = "extra == 'pydantic'", specifier = ">=2.0.0,<3" }, { name = "python-dateutil", marker = "python_full_version < '3.11'", specifier = ">=2.8.2,<3" }, @@ -4860,7 +4905,7 @@ requires-dist = [ { name = "types-protobuf", specifier = ">=3.20,<7.0.0" }, { name = "typing-extensions", specifier = ">=4.2.0,<5" }, ] -provides-extras = ["grpc", "opentelemetry", "pydantic", "openai-agents", "google-adk", "aioboto3"] +provides-extras = ["grpc", "opentelemetry", "pydantic", "openai-agents", "google-adk", "lambda-worker-otel", "aioboto3"] [package.metadata.requires-dev] dev = [ @@ -4877,6 +4922,9 @@ dev = [ { name = "openai-agents", extras = ["litellm"], marker = "python_full_version < '3.14'", specifier = ">=0.3,<0.7" }, { name = "openinference-instrumentation-google-adk", specifier = ">=0.1.8" }, { name = "openinference-instrumentation-openai-agents", specifier = ">=0.1.0" }, + { name = "opentelemetry-exporter-otlp-proto-grpc", specifier = ">=1.11.1,<2" }, + { name = "opentelemetry-sdk-extension-aws", specifier = ">=2.0.0,<3" }, + { name = "opentelemetry-semantic-conventions", specifier = ">=0.40b0,<1" }, { name = "psutil", specifier = ">=5.9.3,<6" }, { name = "pydocstyle", specifier = ">=6.3.0,<7" }, { name = "pydoctor", specifier = ">=25.10.1,<26" }, From e8481deed305bb86b7f7033dfa964d7f01668c8c Mon Sep 17 00:00:00 2001 From: Justin Anderson <44687433+jmaeagle99@users.noreply.github.com> Date: Mon, 6 Apr 2026 20:50:10 -0700 Subject: [PATCH 029/226] Provide standalone activity run ID to external storage (#1417) --- temporalio/worker/_activity.py | 1 + .../aws/s3driver/test_s3driver_worker.py | 19 +++++++++++++------ tests/worker/test_extstore.py | 2 +- 3 files changed, 15 insertions(+), 7 deletions(-) diff --git a/temporalio/worker/_activity.py b/temporalio/worker/_activity.py index 28cc1458a..088ed0380 100644 --- a/temporalio/worker/_activity.py +++ b/temporalio/worker/_activity.py @@ -349,6 +349,7 @@ async def _handle_start_activity_task( store_target = StorageDriverActivityInfo( id=start.activity_id or None, type=start.activity_type or None, + run_id=start.run_id or None, namespace=ns, ) data_converter = self._data_converter._with_contexts( diff --git a/tests/contrib/aws/s3driver/test_s3driver_worker.py b/tests/contrib/aws/s3driver/test_s3driver_worker.py index e25be5fbf..86039bfd5 100644 --- a/tests/contrib/aws/s3driver/test_s3driver_worker.py +++ b/tests/contrib/aws/s3driver/test_s3driver_worker.py @@ -210,11 +210,17 @@ async def test_s3_driver_standalone_activity_input_key( start_to_close_timeout=timedelta(seconds=5), ) keys = await _list_keys(aioboto3_client) - # Input and output are the same LARGE bytes, so they deduplicate to one key. - assert len(keys) == 1 - # Keyed under the activity, not a workflow. - assert f"/ns/default/at/large_io_activity/ai/{activity_id}/ri/null/" in keys[0] - assert "/wt/" not in keys[0] + # Input and output are the same LARGE bytes but stored under different keys. + assert len(keys) == 2 + # Both keyed under the activity, not a workflow. + assert all( + f"/ns/default/at/large_io_activity/ai/{activity_id}/ri/" in k for k in keys + ) + assert all("/wt/" not in k for k in keys) + # Client-side store does not have run ID information + assert sum(1 for k in keys if "/ri/null/" in k) == 1 + # Worker-side store does have run ID information + assert sum(1 for k in keys if "/ri/null/" not in k) == 1 async def test_s3_driver_standalone_activity_output_key( @@ -238,7 +244,8 @@ async def test_s3_driver_standalone_activity_output_key( keys = await _list_keys(aioboto3_client) # Only the output is large; keyed under the activity. assert len(keys) == 1 - assert f"/ns/default/at/large_output_activity/ai/{activity_id}/ri/null/" in keys[0] + assert f"/ns/default/at/large_output_activity/ai/{activity_id}/ri/" in keys[0] + assert "/ri/null/" not in keys[0] assert "/wt/" not in keys[0] diff --git a/tests/worker/test_extstore.py b/tests/worker/test_extstore.py index 8b47b3f0c..56ede59d0 100644 --- a/tests/worker/test_extstore.py +++ b/tests/worker/test_extstore.py @@ -1350,7 +1350,7 @@ async def test_store_metadata_standalone_activity(env: WorkflowEnvironment) -> N assert execute_ctx.target.namespace == client.namespace assert execute_ctx.target.id == activity_id assert execute_ctx.target.type == "echo_activity" - assert execute_ctx.target.run_id is None + assert execute_ctx.target.run_id is not None @workflow.defn From c3550649267cb55ea4ebe81fc2358dad857116ea Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 7 Apr 2026 09:34:20 -0700 Subject: [PATCH 030/226] Bump rustls-webpki from 0.103.4 to 0.103.10 in /temporalio/bridge (#1384) Bumps [rustls-webpki](https://github.com/rustls/webpki) from 0.103.4 to 0.103.10. - [Release notes](https://github.com/rustls/webpki/releases) - [Commits](https://github.com/rustls/webpki/compare/v/0.103.4...v/0.103.10) --- updated-dependencies: - dependency-name: rustls-webpki dependency-version: 0.103.10 dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: tconley1428 --- temporalio/bridge/Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/temporalio/bridge/Cargo.lock b/temporalio/bridge/Cargo.lock index daaa824cc..c31dafdb6 100644 --- a/temporalio/bridge/Cargo.lock +++ b/temporalio/bridge/Cargo.lock @@ -2380,9 +2380,9 @@ checksum = "f87165f0995f63a9fbeea62b64d10b4d9d8e78ec6d7d51fb2125fda7bb36788f" [[package]] name = "rustls-webpki" -version = "0.103.4" +version = "0.103.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a17884ae0c1b773f1ccd2bd4a8c72f16da897310a98b0e84bf349ad5ead92fc" +checksum = "df33b2b81ac578cabaf06b89b0631153a3f416b0a886e8a7a1707fb51abbd1ef" dependencies = [ "aws-lc-rs", "ring", From 3dadf7f3dd80d0cea6f8e5baea797a530d22b2f5 Mon Sep 17 00:00:00 2001 From: tconley1428 Date: Tue, 7 Apr 2026 11:39:18 -0700 Subject: [PATCH 031/226] Add xdist parallel test task (#1415) * Add xdist parallel test task * Stabilize flaky parallel workflow tests * Make poe test parallel by default * Use poe test in CI * Stabilize CI workflow tests * Stabilize time-skipping and process cancel tests * Stabilize quick activity cancellation test --- .github/workflows/ci.yml | 2 +- README.md | 7 ++++ pyproject.toml | 3 +- tests/conftest.py | 11 ++++-- tests/nexus/test_workflow_caller.py | 8 ++++- tests/worker/test_activity.py | 2 +- tests/worker/test_workflow.py | 56 ++++++++++++++--------------- uv.lock | 24 +++++++++++++ 8 files changed, 79 insertions(+), 34 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 6dc1ddb65..4c07251ee 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -163,7 +163,7 @@ jobs: - run: poe build-develop - run: poe lint - run: mkdir junit-xml - - run: poe test -s --junit-xml=junit-xml/latest-deps.xml + - run: poe test -s --junit-xml=junit-xml/latest-deps.xml timeout-minutes: 15 - name: "Upload junit-xml artifacts" uses: actions/upload-artifact@v4 diff --git a/README.md b/README.md index f1e995ea6..c65216160 100644 --- a/README.md +++ b/README.md @@ -2066,6 +2066,13 @@ To execute tests: poe test ``` +`poe test` spreads tests across multiple worker processes by default. If you +need a serial run for debugging, invoke pytest directly: + +```bash +uv run pytest +``` + This runs against [Temporalite](https://github.com/temporalio/temporalite). To run against the time-skipping test server, pass `--workflow-environment time-skipping`. To run against the `default` namespace of an already-running server, pass the `host:port` to `--workflow-environment`. Can also use regular pytest arguments. For example, here's how diff --git a/pyproject.toml b/pyproject.toml index e52ad5ead..b7d7b6c93 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -75,6 +75,7 @@ dev = [ "openinference-instrumentation-google-adk>=0.1.8", "googleapis-common-protos==1.70.0", "pytest-rerunfailures>=16.1", + "pytest-xdist>=3.6,<4", "moto[s3,server]>=5", "opentelemetry-exporter-otlp-proto-grpc>=1.11.1,<2", "opentelemetry-semantic-conventions>=0.40b0,<1", @@ -118,7 +119,7 @@ lint-types = [ { cmd = "uv run basedpyright" }, ] run-bench = "uv run python scripts/run_bench.py" -test = "uv run pytest" +test = "uv run pytest -n auto --dist=worksteal" [tool.pytest.ini_options] diff --git a/tests/conftest.py b/tests/conftest.py index e2ab2149e..303af2e3b 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -187,9 +187,16 @@ async def worker( @pytest.hookimpl(hookwrapper=True, trylast=True) def pytest_cmdline_main(config): # type: ignore[reportMissingParameterType, reportUnusedParameter] result = yield - if result.get_result() == 0: + exit_code = result.get_result() + numprocesses = getattr(config.option, "numprocesses", None) + running_with_xdist = hasattr(config, "workerinput") or numprocesses not in ( + None, + 0, + "0", + ) + if exit_code == 0 and not running_with_xdist: os._exit(0) - return result.get_result() + return exit_code CONTINUE_AS_NEW_SUGGEST_HISTORY_COUNT = 50 diff --git a/tests/nexus/test_workflow_caller.py b/tests/nexus/test_workflow_caller.py index 6e69039ad..ca9e2e145 100644 --- a/tests/nexus/test_workflow_caller.py +++ b/tests/nexus/test_workflow_caller.py @@ -1101,10 +1101,13 @@ async def test_async_response( return handler_wf_info = await handler_wf_handle.describe() - assert handler_wf_info.status in [ + expected_statuses = [ WorkflowExecutionStatus.RUNNING, WorkflowExecutionStatus.COMPLETED, ] + if request_cancel: + expected_statuses.append(WorkflowExecutionStatus.CANCELED) + assert handler_wf_info.status in expected_statuses await assert_handler_workflow_has_link_to_caller_workflow( caller_wf_handle, handler_wf_handle ) @@ -1508,6 +1511,9 @@ async def test_workflow_run_operation_can_execute_workflow_before_starting_backi client: Client, env: WorkflowEnvironment, ): + if env.supports_time_skipping: + pytest.skip("Nexus tests don't work with time-skipping server") + task_queue = str(uuid.uuid4()) async with Worker( client, diff --git a/tests/worker/test_activity.py b/tests/worker/test_activity.py index 99efdf30f..df85b89fb 100644 --- a/tests/worker/test_activity.py +++ b/tests/worker/test_activity.py @@ -639,7 +639,7 @@ async def test_sync_activity_process_cancel( picklable_activity_wait_cancel, cancel_after_ms=100, wait_for_cancellation=True, - heartbeat_timeout_ms=3000, + heartbeat_timeout_ms=5000, worker_config={"activity_executor": executor}, shared_state_manager=shared_state_manager, ) diff --git a/tests/worker/test_workflow.py b/tests/worker/test_workflow.py index f123e5c61..428ea3456 100644 --- a/tests/worker/test_workflow.py +++ b/tests/worker/test_workflow.py @@ -331,10 +331,14 @@ async def test_workflow_history_info( # because just a query will have a stale representation of history # counts, but signal forces a new WFT. await handle.signal(HistoryInfoWorkflow.bunch_of_events, 1) - new_info = await handle.query(HistoryInfoWorkflow.get_history_info) - assert new_info.history_length > continue_as_new_suggest_history_count - assert new_info.history_size > orig_info.history_size - assert new_info.continue_as_new_suggested + + async def history_info_updated() -> None: + new_info = await handle.query(HistoryInfoWorkflow.get_history_info) + assert new_info.history_length > continue_as_new_suggest_history_count + assert new_info.history_size > orig_info.history_size + assert new_info.continue_as_new_suggested + + await assert_eventually(history_info_updated) @workflow.defn @@ -5317,7 +5321,11 @@ async def any_task_completed(handle: WorkflowHandle) -> bool: # because we should have timer-done poll completions every 100ms worker.client = other_env.client # Now confirm the other workflow has started - await assert_eq_eventually(True, lambda: any_task_completed(handle2)) + await assert_eq_eventually( + True, + lambda: any_task_completed(handle2), + timeout=timedelta(seconds=30), + ) # Terminate both await handle1.terminate() await handle2.terminate() @@ -8047,8 +8055,10 @@ async def test_quick_activity_swallows_cancellation(client: Client): activities=[short_activity_async], activity_executor=concurrent.futures.ThreadPoolExecutor(max_workers=1), ) as worker: - for i in range(10): - wf_duration = random.uniform(5.0, 15.0) + # Keep this deterministic and bounded. The original randomized 10-iteration + # version could exceed the per-test timeout on slower CI hosts if + # cancellation was delayed a few times in a row. + for i, wf_duration in enumerate((5.0, 7.5, 10.0)): wf_handle = await client.start_workflow( QuickActivityWorkflow.run, id=f"short_activity_wf_id-{i}", @@ -8537,23 +8547,13 @@ def emit(self, record: logging.LogRecord) -> None: async def test_disable_logger_sandbox( client: Client, ): - logger = workflow.logger.logger - handler = CustomLogHandler() - with LogHandler.apply(logger, handler): + async def execute_with_new_worker(*, disable_sandbox: bool) -> None: + workflow.logger.unsafe_disable_sandbox(disable_sandbox) async with new_worker( client, DisableLoggerSandbox, activities=[], ) as worker: - with pytest.raises(WorkflowFailureError): - await client.execute_workflow( - DisableLoggerSandbox.run, - id=f"workflow-{uuid.uuid4()}", - task_queue=worker.task_queue, - run_timeout=timedelta(seconds=1), - retry_policy=RetryPolicy(maximum_attempts=1), - ) - workflow.logger.unsafe_disable_sandbox() await client.execute_workflow( DisableLoggerSandbox.run, id=f"workflow-{uuid.uuid4()}", @@ -8561,15 +8561,15 @@ async def test_disable_logger_sandbox( run_timeout=timedelta(seconds=1), retry_policy=RetryPolicy(maximum_attempts=1), ) - workflow.logger.unsafe_disable_sandbox(False) - with pytest.raises(WorkflowFailureError): - await client.execute_workflow( - DisableLoggerSandbox.run, - id=f"workflow-{uuid.uuid4()}", - task_queue=worker.task_queue, - run_timeout=timedelta(seconds=1), - retry_policy=RetryPolicy(maximum_attempts=1), - ) + + logger = workflow.logger.logger + handler = CustomLogHandler() + with LogHandler.apply(logger, handler): + with pytest.raises(WorkflowFailureError): + await execute_with_new_worker(disable_sandbox=False) + await execute_with_new_worker(disable_sandbox=True) + with pytest.raises(WorkflowFailureError): + await execute_with_new_worker(disable_sandbox=False) @workflow.defn diff --git a/uv.lock b/uv.lock index c0fe6ec17..08ce15aad 100644 --- a/uv.lock +++ b/uv.lock @@ -945,6 +945,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/36/f4/c6e662dade71f56cd2f3735141b265c3c79293c109549c1e6933b0651ffc/exceptiongroup-1.3.0-py3-none-any.whl", hash = "sha256:4d111e6e0c13d0644cad6ddaa7ed0261a0b36971f6d23e7ec9b4b9097da78a10", size = 16674, upload-time = "2025-05-10T17:42:49.33Z" }, ] +[[package]] +name = "execnet" +version = "2.1.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/bf/89/780e11f9588d9e7128a3f87788354c7946a9cbb1401ad38a48c4db9a4f07/execnet-2.1.2.tar.gz", hash = "sha256:63d83bfdd9a23e35b9c6a3261412324f964c2ec8dcd8d3c6916ee9373e0befcd", size = 166622, upload-time = "2025-11-12T09:56:37.75Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ab/84/02fc1827e8cdded4aa65baef11296a9bbe595c474f0d6d758af082d849fd/execnet-2.1.2-py3-none-any.whl", hash = "sha256:67fba928dd5a544b783f6056f449e5e3931a5c378b128bc18501f7ea79e296ec", size = 40708, upload-time = "2025-11-12T09:56:36.333Z" }, +] + [[package]] name = "fastapi" version = "0.135.1" @@ -4120,6 +4129,19 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/fa/b6/3127540ecdf1464a00e5a01ee60a1b09175f6913f0644ac748494d9c4b21/pytest_timeout-2.4.0-py3-none-any.whl", hash = "sha256:c42667e5cdadb151aeb5b26d114aff6bdf5a907f176a007a30b940d3d865b5c2", size = 14382, upload-time = "2025-05-05T19:44:33.502Z" }, ] +[[package]] +name = "pytest-xdist" +version = "3.8.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "execnet" }, + { name = "pytest" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/78/b4/439b179d1ff526791eb921115fca8e44e596a13efeda518b9d845a619450/pytest_xdist-3.8.0.tar.gz", hash = "sha256:7e578125ec9bc6050861aa93f2d59f1d8d085595d6551c2c90b6f4fad8d3a9f1", size = 88069, upload-time = "2025-07-01T13:30:59.346Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ca/31/d4e37e9e550c2b92a9cbc2e4d0b7420a27224968580b5a447f420847c975/pytest_xdist-3.8.0-py3-none-any.whl", hash = "sha256:202ca578cfeb7370784a8c33d6d05bc6e13b4f25b5053c30a152269fd10f0b88", size = 46396, upload-time = "2025-07-01T13:30:56.632Z" }, +] + [[package]] name = "python-dateutil" version = "2.9.0.post0" @@ -4878,6 +4900,7 @@ dev = [ { name = "pytest-pretty" }, { name = "pytest-rerunfailures" }, { name = "pytest-timeout" }, + { name = "pytest-xdist" }, { name = "ruff" }, { name = "toml" }, { name = "twine" }, @@ -4935,6 +4958,7 @@ dev = [ { name = "pytest-pretty", specifier = ">=1.3.0" }, { name = "pytest-rerunfailures", specifier = ">=16.1" }, { name = "pytest-timeout", specifier = "~=2.2" }, + { name = "pytest-xdist", specifier = ">=3.6,<4" }, { name = "ruff", specifier = ">=0.5.0,<0.6" }, { name = "toml", specifier = ">=0.10.2,<0.11" }, { name = "twine", specifier = ">=4.0.1,<5" }, From 9b74089513e1a760e5f86f11f3ea8b68f8b75d60 Mon Sep 17 00:00:00 2001 From: tconley1428 Date: Tue, 7 Apr 2026 12:23:53 -0700 Subject: [PATCH 032/226] Upgrade locked dependencies (#1420) --- pyproject.toml | 1 + uv.lock | 3247 +++++++++++++++++++++++++----------------------- 2 files changed, 1688 insertions(+), 1560 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index b7d7b6c93..8cf2fee1d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -77,6 +77,7 @@ dev = [ "pytest-rerunfailures>=16.1", "pytest-xdist>=3.6,<4", "moto[s3,server]>=5", + "setuptools<82", "opentelemetry-exporter-otlp-proto-grpc>=1.11.1,<2", "opentelemetry-semantic-conventions>=0.40b0,<1", "opentelemetry-sdk-extension-aws>=2.0.0,<3", diff --git a/uv.lock b/uv.lock index 08ce15aad..f5b8b962d 100644 --- a/uv.lock +++ b/uv.lock @@ -64,7 +64,7 @@ wheels = [ [[package]] name = "aiohttp" -version = "3.13.3" +version = "3.13.5" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "aiohappyeyeballs" }, @@ -76,110 +76,110 @@ dependencies = [ { name = "propcache" }, { name = "yarl" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/50/42/32cf8e7704ceb4481406eb87161349abb46a57fee3f008ba9cb610968646/aiohttp-3.13.3.tar.gz", hash = "sha256:a949eee43d3782f2daae4f4a2819b2cb9b0c5d3b7f7a927067cc84dafdbb9f88", size = 7844556, upload-time = "2026-01-03T17:33:05.204Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/36/d6/5aec9313ee6ea9c7cde8b891b69f4ff4001416867104580670a31daeba5b/aiohttp-3.13.3-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:d5a372fd5afd301b3a89582817fdcdb6c34124787c70dbcc616f259013e7eef7", size = 738950, upload-time = "2026-01-03T17:29:13.002Z" }, - { url = "https://files.pythonhosted.org/packages/68/03/8fa90a7e6d11ff20a18837a8e2b5dd23db01aabc475aa9271c8ad33299f5/aiohttp-3.13.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:147e422fd1223005c22b4fe080f5d93ced44460f5f9c105406b753612b587821", size = 496099, upload-time = "2026-01-03T17:29:15.268Z" }, - { url = "https://files.pythonhosted.org/packages/d2/23/b81f744d402510a8366b74eb420fc0cc1170d0c43daca12d10814df85f10/aiohttp-3.13.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:859bd3f2156e81dd01432f5849fc73e2243d4a487c4fd26609b1299534ee1845", size = 491072, upload-time = "2026-01-03T17:29:16.922Z" }, - { url = "https://files.pythonhosted.org/packages/d5/e1/56d1d1c0dd334cd203dd97706ce004c1aa24b34a813b0b8daf3383039706/aiohttp-3.13.3-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:dca68018bf48c251ba17c72ed479f4dafe9dbd5a73707ad8d28a38d11f3d42af", size = 1671588, upload-time = "2026-01-03T17:29:18.539Z" }, - { url = "https://files.pythonhosted.org/packages/5f/34/8d7f962604f4bc2b4e39eb1220dac7d4e4cba91fb9ba0474b4ecd67db165/aiohttp-3.13.3-cp310-cp310-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:fee0c6bc7db1de362252affec009707a17478a00ec69f797d23ca256e36d5940", size = 1640334, upload-time = "2026-01-03T17:29:21.028Z" }, - { url = "https://files.pythonhosted.org/packages/94/1d/fcccf2c668d87337ddeef9881537baee13c58d8f01f12ba8a24215f2b804/aiohttp-3.13.3-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:c048058117fd649334d81b4b526e94bde3ccaddb20463a815ced6ecbb7d11160", size = 1722656, upload-time = "2026-01-03T17:29:22.531Z" }, - { url = "https://files.pythonhosted.org/packages/aa/98/c6f3b081c4c606bc1e5f2ec102e87d6411c73a9ef3616fea6f2d5c98c062/aiohttp-3.13.3-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:215a685b6fbbfcf71dfe96e3eba7a6f58f10da1dfdf4889c7dd856abe430dca7", size = 1817625, upload-time = "2026-01-03T17:29:24.276Z" }, - { url = "https://files.pythonhosted.org/packages/2c/c0/cfcc3d2e11b477f86e1af2863f3858c8850d751ce8dc39c4058a072c9e54/aiohttp-3.13.3-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:de2c184bb1fe2cbd2cefba613e9db29a5ab559323f994b6737e370d3da0ac455", size = 1672604, upload-time = "2026-01-03T17:29:26.099Z" }, - { url = "https://files.pythonhosted.org/packages/1e/77/6b4ffcbcac4c6a5d041343a756f34a6dd26174ae07f977a64fe028dda5b0/aiohttp-3.13.3-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:75ca857eba4e20ce9f546cd59c7007b33906a4cd48f2ff6ccf1ccfc3b646f279", size = 1554370, upload-time = "2026-01-03T17:29:28.121Z" }, - { url = "https://files.pythonhosted.org/packages/f2/f0/e3ddfa93f17d689dbe014ba048f18e0c9f9b456033b70e94349a2e9048be/aiohttp-3.13.3-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:81e97251d9298386c2b7dbeb490d3d1badbdc69107fb8c9299dd04eb39bddc0e", size = 1642023, upload-time = "2026-01-03T17:29:30.002Z" }, - { url = "https://files.pythonhosted.org/packages/eb/45/c14019c9ec60a8e243d06d601b33dcc4fd92379424bde3021725859d7f99/aiohttp-3.13.3-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:c0e2d366af265797506f0283487223146af57815b388623f0357ef7eac9b209d", size = 1649680, upload-time = "2026-01-03T17:29:31.782Z" }, - { url = "https://files.pythonhosted.org/packages/9c/fd/09c9451dae5aa5c5ed756df95ff9ef549d45d4be663bafd1e4954fd836f0/aiohttp-3.13.3-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:4e239d501f73d6db1522599e14b9b321a7e3b1de66ce33d53a765d975e9f4808", size = 1692407, upload-time = "2026-01-03T17:29:33.392Z" }, - { url = "https://files.pythonhosted.org/packages/a6/81/938bc2ec33c10efd6637ccb3d22f9f3160d08e8f3aa2587a2c2d5ab578eb/aiohttp-3.13.3-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:0db318f7a6f065d84cb1e02662c526294450b314a02bd9e2a8e67f0d8564ce40", size = 1543047, upload-time = "2026-01-03T17:29:34.855Z" }, - { url = "https://files.pythonhosted.org/packages/f7/23/80488ee21c8d567c83045e412e1d9b7077d27171591a4eb7822586e8c06a/aiohttp-3.13.3-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:bfc1cc2fe31a6026a8a88e4ecfb98d7f6b1fec150cfd708adbfd1d2f42257c29", size = 1715264, upload-time = "2026-01-03T17:29:36.389Z" }, - { url = "https://files.pythonhosted.org/packages/e2/83/259a8da6683182768200b368120ab3deff5370bed93880fb9a3a86299f34/aiohttp-3.13.3-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:af71fff7bac6bb7508956696dce8f6eec2bbb045eceb40343944b1ae62b5ef11", size = 1657275, upload-time = "2026-01-03T17:29:38.162Z" }, - { url = "https://files.pythonhosted.org/packages/3f/4f/2c41f800a0b560785c10fb316216ac058c105f9be50bdc6a285de88db625/aiohttp-3.13.3-cp310-cp310-win32.whl", hash = "sha256:37da61e244d1749798c151421602884db5270faf479cf0ef03af0ff68954c9dd", size = 434053, upload-time = "2026-01-03T17:29:40.074Z" }, - { url = "https://files.pythonhosted.org/packages/80/df/29cd63c7ecfdb65ccc12f7d808cac4fa2a19544660c06c61a4a48462de0c/aiohttp-3.13.3-cp310-cp310-win_amd64.whl", hash = "sha256:7e63f210bc1b57ef699035f2b4b6d9ce096b5914414a49b0997c839b2bd2223c", size = 456687, upload-time = "2026-01-03T17:29:41.819Z" }, - { url = "https://files.pythonhosted.org/packages/f1/4c/a164164834f03924d9a29dc3acd9e7ee58f95857e0b467f6d04298594ebb/aiohttp-3.13.3-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:5b6073099fb654e0a068ae678b10feff95c5cae95bbfcbfa7af669d361a8aa6b", size = 746051, upload-time = "2026-01-03T17:29:43.287Z" }, - { url = "https://files.pythonhosted.org/packages/82/71/d5c31390d18d4f58115037c432b7e0348c60f6f53b727cad33172144a112/aiohttp-3.13.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:1cb93e166e6c28716c8c6aeb5f99dfb6d5ccf482d29fe9bf9a794110e6d0ab64", size = 499234, upload-time = "2026-01-03T17:29:44.822Z" }, - { url = "https://files.pythonhosted.org/packages/0e/c9/741f8ac91e14b1d2e7100690425a5b2b919a87a5075406582991fb7de920/aiohttp-3.13.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:28e027cf2f6b641693a09f631759b4d9ce9165099d2b5d92af9bd4e197690eea", size = 494979, upload-time = "2026-01-03T17:29:46.405Z" }, - { url = "https://files.pythonhosted.org/packages/75/b5/31d4d2e802dfd59f74ed47eba48869c1c21552c586d5e81a9d0d5c2ad640/aiohttp-3.13.3-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3b61b7169ababd7802f9568ed96142616a9118dd2be0d1866e920e77ec8fa92a", size = 1748297, upload-time = "2026-01-03T17:29:48.083Z" }, - { url = "https://files.pythonhosted.org/packages/1a/3e/eefad0ad42959f226bb79664826883f2687d602a9ae2941a18e0484a74d3/aiohttp-3.13.3-cp311-cp311-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:80dd4c21b0f6237676449c6baaa1039abae86b91636b6c91a7f8e61c87f89540", size = 1707172, upload-time = "2026-01-03T17:29:49.648Z" }, - { url = "https://files.pythonhosted.org/packages/c5/3a/54a64299fac2891c346cdcf2aa6803f994a2e4beeaf2e5a09dcc54acc842/aiohttp-3.13.3-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:65d2ccb7eabee90ce0503c17716fc77226be026dcc3e65cce859a30db715025b", size = 1805405, upload-time = "2026-01-03T17:29:51.244Z" }, - { url = "https://files.pythonhosted.org/packages/6c/70/ddc1b7169cf64075e864f64595a14b147a895a868394a48f6a8031979038/aiohttp-3.13.3-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:5b179331a481cb5529fca8b432d8d3c7001cb217513c94cd72d668d1248688a3", size = 1899449, upload-time = "2026-01-03T17:29:53.938Z" }, - { url = "https://files.pythonhosted.org/packages/a1/7e/6815aab7d3a56610891c76ef79095677b8b5be6646aaf00f69b221765021/aiohttp-3.13.3-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9d4c940f02f49483b18b079d1c27ab948721852b281f8b015c058100e9421dd1", size = 1748444, upload-time = "2026-01-03T17:29:55.484Z" }, - { url = "https://files.pythonhosted.org/packages/6b/f2/073b145c4100da5511f457dc0f7558e99b2987cf72600d42b559db856fbc/aiohttp-3.13.3-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:f9444f105664c4ce47a2a7171a2418bce5b7bae45fb610f4e2c36045d85911d3", size = 1606038, upload-time = "2026-01-03T17:29:57.179Z" }, - { url = "https://files.pythonhosted.org/packages/0a/c1/778d011920cae03ae01424ec202c513dc69243cf2db303965615b81deeea/aiohttp-3.13.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:694976222c711d1d00ba131904beb60534f93966562f64440d0c9d41b8cdb440", size = 1724156, upload-time = "2026-01-03T17:29:58.914Z" }, - { url = "https://files.pythonhosted.org/packages/0e/cb/3419eabf4ec1e9ec6f242c32b689248365a1cf621891f6f0386632525494/aiohttp-3.13.3-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:f33ed1a2bf1997a36661874b017f5c4b760f41266341af36febaf271d179f6d7", size = 1722340, upload-time = "2026-01-03T17:30:01.962Z" }, - { url = "https://files.pythonhosted.org/packages/7a/e5/76cf77bdbc435bf233c1f114edad39ed4177ccbfab7c329482b179cff4f4/aiohttp-3.13.3-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:e636b3c5f61da31a92bf0d91da83e58fdfa96f178ba682f11d24f31944cdd28c", size = 1783041, upload-time = "2026-01-03T17:30:03.609Z" }, - { url = "https://files.pythonhosted.org/packages/9d/d4/dd1ca234c794fd29c057ce8c0566b8ef7fd6a51069de5f06fa84b9a1971c/aiohttp-3.13.3-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:5d2d94f1f5fcbe40838ac51a6ab5704a6f9ea42e72ceda48de5e6b898521da51", size = 1596024, upload-time = "2026-01-03T17:30:05.132Z" }, - { url = "https://files.pythonhosted.org/packages/55/58/4345b5f26661a6180afa686c473620c30a66afdf120ed3dd545bbc809e85/aiohttp-3.13.3-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:2be0e9ccf23e8a94f6f0650ce06042cefc6ac703d0d7ab6c7a917289f2539ad4", size = 1804590, upload-time = "2026-01-03T17:30:07.135Z" }, - { url = "https://files.pythonhosted.org/packages/7b/06/05950619af6c2df7e0a431d889ba2813c9f0129cec76f663e547a5ad56f2/aiohttp-3.13.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:9af5e68ee47d6534d36791bbe9b646d2a7c7deb6fc24d7943628edfbb3581f29", size = 1740355, upload-time = "2026-01-03T17:30:09.083Z" }, - { url = "https://files.pythonhosted.org/packages/3e/80/958f16de79ba0422d7c1e284b2abd0c84bc03394fbe631d0a39ffa10e1eb/aiohttp-3.13.3-cp311-cp311-win32.whl", hash = "sha256:a2212ad43c0833a873d0fb3c63fa1bacedd4cf6af2fee62bf4b739ceec3ab239", size = 433701, upload-time = "2026-01-03T17:30:10.869Z" }, - { url = "https://files.pythonhosted.org/packages/dc/f2/27cdf04c9851712d6c1b99df6821a6623c3c9e55956d4b1e318c337b5a48/aiohttp-3.13.3-cp311-cp311-win_amd64.whl", hash = "sha256:642f752c3eb117b105acbd87e2c143de710987e09860d674e068c4c2c441034f", size = 457678, upload-time = "2026-01-03T17:30:12.719Z" }, - { url = "https://files.pythonhosted.org/packages/a0/be/4fc11f202955a69e0db803a12a062b8379c970c7c84f4882b6da17337cc1/aiohttp-3.13.3-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:b903a4dfee7d347e2d87697d0713be59e0b87925be030c9178c5faa58ea58d5c", size = 739732, upload-time = "2026-01-03T17:30:14.23Z" }, - { url = "https://files.pythonhosted.org/packages/97/2c/621d5b851f94fa0bb7430d6089b3aa970a9d9b75196bc93bb624b0db237a/aiohttp-3.13.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:a45530014d7a1e09f4a55f4f43097ba0fd155089372e105e4bff4ca76cb1b168", size = 494293, upload-time = "2026-01-03T17:30:15.96Z" }, - { url = "https://files.pythonhosted.org/packages/5d/43/4be01406b78e1be8320bb8316dc9c42dbab553d281c40364e0f862d5661c/aiohttp-3.13.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:27234ef6d85c914f9efeb77ff616dbf4ad2380be0cda40b4db086ffc7ddd1b7d", size = 493533, upload-time = "2026-01-03T17:30:17.431Z" }, - { url = "https://files.pythonhosted.org/packages/8d/a8/5a35dc56a06a2c90d4742cbf35294396907027f80eea696637945a106f25/aiohttp-3.13.3-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d32764c6c9aafb7fb55366a224756387cd50bfa720f32b88e0e6fa45b27dcf29", size = 1737839, upload-time = "2026-01-03T17:30:19.422Z" }, - { url = "https://files.pythonhosted.org/packages/bf/62/4b9eeb331da56530bf2e198a297e5303e1c1ebdceeb00fe9b568a65c5a0c/aiohttp-3.13.3-cp312-cp312-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:b1a6102b4d3ebc07dad44fbf07b45bb600300f15b552ddf1851b5390202ea2e3", size = 1703932, upload-time = "2026-01-03T17:30:21.756Z" }, - { url = "https://files.pythonhosted.org/packages/7c/f6/af16887b5d419e6a367095994c0b1332d154f647e7dc2bd50e61876e8e3d/aiohttp-3.13.3-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:c014c7ea7fb775dd015b2d3137378b7be0249a448a1612268b5a90c2d81de04d", size = 1771906, upload-time = "2026-01-03T17:30:23.932Z" }, - { url = "https://files.pythonhosted.org/packages/ce/83/397c634b1bcc24292fa1e0c7822800f9f6569e32934bdeef09dae7992dfb/aiohttp-3.13.3-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:2b8d8ddba8f95ba17582226f80e2de99c7a7948e66490ef8d947e272a93e9463", size = 1871020, upload-time = "2026-01-03T17:30:26Z" }, - { url = "https://files.pythonhosted.org/packages/86/f6/a62cbbf13f0ac80a70f71b1672feba90fdb21fd7abd8dbf25c0105fb6fa3/aiohttp-3.13.3-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9ae8dd55c8e6c4257eae3a20fd2c8f41edaea5992ed67156642493b8daf3cecc", size = 1755181, upload-time = "2026-01-03T17:30:27.554Z" }, - { url = "https://files.pythonhosted.org/packages/0a/87/20a35ad487efdd3fba93d5843efdfaa62d2f1479eaafa7453398a44faf13/aiohttp-3.13.3-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:01ad2529d4b5035578f5081606a465f3b814c542882804e2e8cda61adf5c71bf", size = 1561794, upload-time = "2026-01-03T17:30:29.254Z" }, - { url = "https://files.pythonhosted.org/packages/de/95/8fd69a66682012f6716e1bc09ef8a1a2a91922c5725cb904689f112309c4/aiohttp-3.13.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:bb4f7475e359992b580559e008c598091c45b5088f28614e855e42d39c2f1033", size = 1697900, upload-time = "2026-01-03T17:30:31.033Z" }, - { url = "https://files.pythonhosted.org/packages/e5/66/7b94b3b5ba70e955ff597672dad1691333080e37f50280178967aff68657/aiohttp-3.13.3-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:c19b90316ad3b24c69cd78d5c9b4f3aa4497643685901185b65166293d36a00f", size = 1728239, upload-time = "2026-01-03T17:30:32.703Z" }, - { url = "https://files.pythonhosted.org/packages/47/71/6f72f77f9f7d74719692ab65a2a0252584bf8d5f301e2ecb4c0da734530a/aiohttp-3.13.3-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:96d604498a7c782cb15a51c406acaea70d8c027ee6b90c569baa6e7b93073679", size = 1740527, upload-time = "2026-01-03T17:30:34.695Z" }, - { url = "https://files.pythonhosted.org/packages/fa/b4/75ec16cbbd5c01bdaf4a05b19e103e78d7ce1ef7c80867eb0ace42ff4488/aiohttp-3.13.3-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:084911a532763e9d3dd95adf78a78f4096cd5f58cdc18e6fdbc1b58417a45423", size = 1554489, upload-time = "2026-01-03T17:30:36.864Z" }, - { url = "https://files.pythonhosted.org/packages/52/8f/bc518c0eea29f8406dcf7ed1f96c9b48e3bc3995a96159b3fc11f9e08321/aiohttp-3.13.3-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:7a4a94eb787e606d0a09404b9c38c113d3b099d508021faa615d70a0131907ce", size = 1767852, upload-time = "2026-01-03T17:30:39.433Z" }, - { url = "https://files.pythonhosted.org/packages/9d/f2/a07a75173124f31f11ea6f863dc44e6f09afe2bca45dd4e64979490deab1/aiohttp-3.13.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:87797e645d9d8e222e04160ee32aa06bc5c163e8499f24db719e7852ec23093a", size = 1722379, upload-time = "2026-01-03T17:30:41.081Z" }, - { url = "https://files.pythonhosted.org/packages/3c/4a/1a3fee7c21350cac78e5c5cef711bac1b94feca07399f3d406972e2d8fcd/aiohttp-3.13.3-cp312-cp312-win32.whl", hash = "sha256:b04be762396457bef43f3597c991e192ee7da460a4953d7e647ee4b1c28e7046", size = 428253, upload-time = "2026-01-03T17:30:42.644Z" }, - { url = "https://files.pythonhosted.org/packages/d9/b7/76175c7cb4eb73d91ad63c34e29fc4f77c9386bba4a65b53ba8e05ee3c39/aiohttp-3.13.3-cp312-cp312-win_amd64.whl", hash = "sha256:e3531d63d3bdfa7e3ac5e9b27b2dd7ec9df3206a98e0b3445fa906f233264c57", size = 455407, upload-time = "2026-01-03T17:30:44.195Z" }, - { url = "https://files.pythonhosted.org/packages/97/8a/12ca489246ca1faaf5432844adbfce7ff2cc4997733e0af120869345643a/aiohttp-3.13.3-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:5dff64413671b0d3e7d5918ea490bdccb97a4ad29b3f311ed423200b2203e01c", size = 734190, upload-time = "2026-01-03T17:30:45.832Z" }, - { url = "https://files.pythonhosted.org/packages/32/08/de43984c74ed1fca5c014808963cc83cb00d7bb06af228f132d33862ca76/aiohttp-3.13.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:87b9aab6d6ed88235aa2970294f496ff1a1f9adcd724d800e9b952395a80ffd9", size = 491783, upload-time = "2026-01-03T17:30:47.466Z" }, - { url = "https://files.pythonhosted.org/packages/17/f8/8dd2cf6112a5a76f81f81a5130c57ca829d101ad583ce57f889179accdda/aiohttp-3.13.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:425c126c0dc43861e22cb1c14ba4c8e45d09516d0a3ae0a3f7494b79f5f233a3", size = 490704, upload-time = "2026-01-03T17:30:49.373Z" }, - { url = "https://files.pythonhosted.org/packages/6d/40/a46b03ca03936f832bc7eaa47cfbb1ad012ba1be4790122ee4f4f8cba074/aiohttp-3.13.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:7f9120f7093c2a32d9647abcaf21e6ad275b4fbec5b55969f978b1a97c7c86bf", size = 1720652, upload-time = "2026-01-03T17:30:50.974Z" }, - { url = "https://files.pythonhosted.org/packages/f7/7e/917fe18e3607af92657e4285498f500dca797ff8c918bd7d90b05abf6c2a/aiohttp-3.13.3-cp313-cp313-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:697753042d57f4bf7122cab985bf15d0cef23c770864580f5af4f52023a56bd6", size = 1692014, upload-time = "2026-01-03T17:30:52.729Z" }, - { url = "https://files.pythonhosted.org/packages/71/b6/cefa4cbc00d315d68973b671cf105b21a609c12b82d52e5d0c9ae61d2a09/aiohttp-3.13.3-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:6de499a1a44e7de70735d0b39f67c8f25eb3d91eb3103be99ca0fa882cdd987d", size = 1759777, upload-time = "2026-01-03T17:30:54.537Z" }, - { url = "https://files.pythonhosted.org/packages/fb/e3/e06ee07b45e59e6d81498b591fc589629be1553abb2a82ce33efe2a7b068/aiohttp-3.13.3-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:37239e9f9a7ea9ac5bf6b92b0260b01f8a22281996da609206a84df860bc1261", size = 1861276, upload-time = "2026-01-03T17:30:56.512Z" }, - { url = "https://files.pythonhosted.org/packages/7c/24/75d274228acf35ceeb2850b8ce04de9dd7355ff7a0b49d607ee60c29c518/aiohttp-3.13.3-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f76c1e3fe7d7c8afad7ed193f89a292e1999608170dcc9751a7462a87dfd5bc0", size = 1743131, upload-time = "2026-01-03T17:30:58.256Z" }, - { url = "https://files.pythonhosted.org/packages/04/98/3d21dde21889b17ca2eea54fdcff21b27b93f45b7bb94ca029c31ab59dc3/aiohttp-3.13.3-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:fc290605db2a917f6e81b0e1e0796469871f5af381ce15c604a3c5c7e51cb730", size = 1556863, upload-time = "2026-01-03T17:31:00.445Z" }, - { url = "https://files.pythonhosted.org/packages/9e/84/da0c3ab1192eaf64782b03971ab4055b475d0db07b17eff925e8c93b3aa5/aiohttp-3.13.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:4021b51936308aeea0367b8f006dc999ca02bc118a0cc78c303f50a2ff6afb91", size = 1682793, upload-time = "2026-01-03T17:31:03.024Z" }, - { url = "https://files.pythonhosted.org/packages/ff/0f/5802ada182f575afa02cbd0ec5180d7e13a402afb7c2c03a9aa5e5d49060/aiohttp-3.13.3-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:49a03727c1bba9a97d3e93c9f93ca03a57300f484b6e935463099841261195d3", size = 1716676, upload-time = "2026-01-03T17:31:04.842Z" }, - { url = "https://files.pythonhosted.org/packages/3f/8c/714d53bd8b5a4560667f7bbbb06b20c2382f9c7847d198370ec6526af39c/aiohttp-3.13.3-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:3d9908a48eb7416dc1f4524e69f1d32e5d90e3981e4e37eb0aa1cd18f9cfa2a4", size = 1733217, upload-time = "2026-01-03T17:31:06.868Z" }, - { url = "https://files.pythonhosted.org/packages/7d/79/e2176f46d2e963facea939f5be2d26368ce543622be6f00a12844d3c991f/aiohttp-3.13.3-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:2712039939ec963c237286113c68dbad80a82a4281543f3abf766d9d73228998", size = 1552303, upload-time = "2026-01-03T17:31:08.958Z" }, - { url = "https://files.pythonhosted.org/packages/ab/6a/28ed4dea1759916090587d1fe57087b03e6c784a642b85ef48217b0277ae/aiohttp-3.13.3-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:7bfdc049127717581866fa4708791220970ce291c23e28ccf3922c700740fdc0", size = 1763673, upload-time = "2026-01-03T17:31:10.676Z" }, - { url = "https://files.pythonhosted.org/packages/e8/35/4a3daeb8b9fab49240d21c04d50732313295e4bd813a465d840236dd0ce1/aiohttp-3.13.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:8057c98e0c8472d8846b9c79f56766bcc57e3e8ac7bfd510482332366c56c591", size = 1721120, upload-time = "2026-01-03T17:31:12.575Z" }, - { url = "https://files.pythonhosted.org/packages/bc/9f/d643bb3c5fb99547323e635e251c609fbbc660d983144cfebec529e09264/aiohttp-3.13.3-cp313-cp313-win32.whl", hash = "sha256:1449ceddcdbcf2e0446957863af03ebaaa03f94c090f945411b61269e2cb5daf", size = 427383, upload-time = "2026-01-03T17:31:14.382Z" }, - { url = "https://files.pythonhosted.org/packages/4e/f1/ab0395f8a79933577cdd996dd2f9aa6014af9535f65dddcf88204682fe62/aiohttp-3.13.3-cp313-cp313-win_amd64.whl", hash = "sha256:693781c45a4033d31d4187d2436f5ac701e7bbfe5df40d917736108c1cc7436e", size = 453899, upload-time = "2026-01-03T17:31:15.958Z" }, - { url = "https://files.pythonhosted.org/packages/99/36/5b6514a9f5d66f4e2597e40dea2e3db271e023eb7a5d22defe96ba560996/aiohttp-3.13.3-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:ea37047c6b367fd4bd632bff8077449b8fa034b69e812a18e0132a00fae6e808", size = 737238, upload-time = "2026-01-03T17:31:17.909Z" }, - { url = "https://files.pythonhosted.org/packages/f7/49/459327f0d5bcd8c6c9ca69e60fdeebc3622861e696490d8674a6d0cb90a6/aiohttp-3.13.3-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:6fc0e2337d1a4c3e6acafda6a78a39d4c14caea625124817420abceed36e2415", size = 492292, upload-time = "2026-01-03T17:31:19.919Z" }, - { url = "https://files.pythonhosted.org/packages/e8/0b/b97660c5fd05d3495b4eb27f2d0ef18dc1dc4eff7511a9bf371397ff0264/aiohttp-3.13.3-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:c685f2d80bb67ca8c3837823ad76196b3694b0159d232206d1e461d3d434666f", size = 493021, upload-time = "2026-01-03T17:31:21.636Z" }, - { url = "https://files.pythonhosted.org/packages/54/d4/438efabdf74e30aeceb890c3290bbaa449780583b1270b00661126b8aae4/aiohttp-3.13.3-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:48e377758516d262bde50c2584fc6c578af272559c409eecbdd2bae1601184d6", size = 1717263, upload-time = "2026-01-03T17:31:23.296Z" }, - { url = "https://files.pythonhosted.org/packages/71/f2/7bddc7fd612367d1459c5bcf598a9e8f7092d6580d98de0e057eb42697ad/aiohttp-3.13.3-cp314-cp314-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:34749271508078b261c4abb1767d42b8d0c0cc9449c73a4df494777dc55f0687", size = 1669107, upload-time = "2026-01-03T17:31:25.334Z" }, - { url = "https://files.pythonhosted.org/packages/00/5a/1aeaecca40e22560f97610a329e0e5efef5e0b5afdf9f857f0d93839ab2e/aiohttp-3.13.3-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:82611aeec80eb144416956ec85b6ca45a64d76429c1ed46ae1b5f86c6e0c9a26", size = 1760196, upload-time = "2026-01-03T17:31:27.394Z" }, - { url = "https://files.pythonhosted.org/packages/f8/f8/0ff6992bea7bd560fc510ea1c815f87eedd745fe035589c71ce05612a19a/aiohttp-3.13.3-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:2fff83cfc93f18f215896e3a190e8e5cb413ce01553901aca925176e7568963a", size = 1843591, upload-time = "2026-01-03T17:31:29.238Z" }, - { url = "https://files.pythonhosted.org/packages/e3/d1/e30e537a15f53485b61f5be525f2157da719819e8377298502aebac45536/aiohttp-3.13.3-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:bbe7d4cecacb439e2e2a8a1a7b935c25b812af7a5fd26503a66dadf428e79ec1", size = 1720277, upload-time = "2026-01-03T17:31:31.053Z" }, - { url = "https://files.pythonhosted.org/packages/84/45/23f4c451d8192f553d38d838831ebbc156907ea6e05557f39563101b7717/aiohttp-3.13.3-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:b928f30fe49574253644b1ca44b1b8adbd903aa0da4b9054a6c20fc7f4092a25", size = 1548575, upload-time = "2026-01-03T17:31:32.87Z" }, - { url = "https://files.pythonhosted.org/packages/6a/ed/0a42b127a43712eda7807e7892c083eadfaf8429ca8fb619662a530a3aab/aiohttp-3.13.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:7b5e8fe4de30df199155baaf64f2fcd604f4c678ed20910db8e2c66dc4b11603", size = 1679455, upload-time = "2026-01-03T17:31:34.76Z" }, - { url = "https://files.pythonhosted.org/packages/2e/b5/c05f0c2b4b4fe2c9d55e73b6d3ed4fd6c9dc2684b1d81cbdf77e7fad9adb/aiohttp-3.13.3-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:8542f41a62bcc58fc7f11cf7c90e0ec324ce44950003feb70640fc2a9092c32a", size = 1687417, upload-time = "2026-01-03T17:31:36.699Z" }, - { url = "https://files.pythonhosted.org/packages/c9/6b/915bc5dad66aef602b9e459b5a973529304d4e89ca86999d9d75d80cbd0b/aiohttp-3.13.3-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:5e1d8c8b8f1d91cd08d8f4a3c2b067bfca6ec043d3ff36de0f3a715feeedf926", size = 1729968, upload-time = "2026-01-03T17:31:38.622Z" }, - { url = "https://files.pythonhosted.org/packages/11/3b/e84581290a9520024a08640b63d07673057aec5ca548177a82026187ba73/aiohttp-3.13.3-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:90455115e5da1c3c51ab619ac57f877da8fd6d73c05aacd125c5ae9819582aba", size = 1545690, upload-time = "2026-01-03T17:31:40.57Z" }, - { url = "https://files.pythonhosted.org/packages/f5/04/0c3655a566c43fd647c81b895dfe361b9f9ad6d58c19309d45cff52d6c3b/aiohttp-3.13.3-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:042e9e0bcb5fba81886c8b4fbb9a09d6b8a00245fd8d88e4d989c1f96c74164c", size = 1746390, upload-time = "2026-01-03T17:31:42.857Z" }, - { url = "https://files.pythonhosted.org/packages/1f/53/71165b26978f719c3419381514c9690bd5980e764a09440a10bb816ea4ab/aiohttp-3.13.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:2eb752b102b12a76ca02dff751a801f028b4ffbbc478840b473597fc91a9ed43", size = 1702188, upload-time = "2026-01-03T17:31:44.984Z" }, - { url = "https://files.pythonhosted.org/packages/29/a7/cbe6c9e8e136314fa1980da388a59d2f35f35395948a08b6747baebb6aa6/aiohttp-3.13.3-cp314-cp314-win32.whl", hash = "sha256:b556c85915d8efaed322bf1bdae9486aa0f3f764195a0fb6ee962e5c71ef5ce1", size = 433126, upload-time = "2026-01-03T17:31:47.463Z" }, - { url = "https://files.pythonhosted.org/packages/de/56/982704adea7d3b16614fc5936014e9af85c0e34b58f9046655817f04306e/aiohttp-3.13.3-cp314-cp314-win_amd64.whl", hash = "sha256:9bf9f7a65e7aa20dd764151fb3d616c81088f91f8df39c3893a536e279b4b984", size = 459128, upload-time = "2026-01-03T17:31:49.2Z" }, - { url = "https://files.pythonhosted.org/packages/6c/2a/3c79b638a9c3d4658d345339d22070241ea341ed4e07b5ac60fb0f418003/aiohttp-3.13.3-cp314-cp314t-macosx_10_13_universal2.whl", hash = "sha256:05861afbbec40650d8a07ea324367cb93e9e8cc7762e04dd4405df99fa65159c", size = 769512, upload-time = "2026-01-03T17:31:51.134Z" }, - { url = "https://files.pythonhosted.org/packages/29/b9/3e5014d46c0ab0db8707e0ac2711ed28c4da0218c358a4e7c17bae0d8722/aiohttp-3.13.3-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:2fc82186fadc4a8316768d61f3722c230e2c1dcab4200d52d2ebdf2482e47592", size = 506444, upload-time = "2026-01-03T17:31:52.85Z" }, - { url = "https://files.pythonhosted.org/packages/90/03/c1d4ef9a054e151cd7839cdc497f2638f00b93cbe8043983986630d7a80c/aiohttp-3.13.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:0add0900ff220d1d5c5ebbf99ed88b0c1bbf87aa7e4262300ed1376a6b13414f", size = 510798, upload-time = "2026-01-03T17:31:54.91Z" }, - { url = "https://files.pythonhosted.org/packages/ea/76/8c1e5abbfe8e127c893fe7ead569148a4d5a799f7cf958d8c09f3eedf097/aiohttp-3.13.3-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:568f416a4072fbfae453dcf9a99194bbb8bdeab718e08ee13dfa2ba0e4bebf29", size = 1868835, upload-time = "2026-01-03T17:31:56.733Z" }, - { url = "https://files.pythonhosted.org/packages/8e/ac/984c5a6f74c363b01ff97adc96a3976d9c98940b8969a1881575b279ac5d/aiohttp-3.13.3-cp314-cp314t-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:add1da70de90a2569c5e15249ff76a631ccacfe198375eead4aadf3b8dc849dc", size = 1720486, upload-time = "2026-01-03T17:31:58.65Z" }, - { url = "https://files.pythonhosted.org/packages/b2/9a/b7039c5f099c4eb632138728828b33428585031a1e658d693d41d07d89d1/aiohttp-3.13.3-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:10b47b7ba335d2e9b1239fa571131a87e2d8ec96b333e68b2a305e7a98b0bae2", size = 1847951, upload-time = "2026-01-03T17:32:00.989Z" }, - { url = "https://files.pythonhosted.org/packages/3c/02/3bec2b9a1ba3c19ff89a43a19324202b8eb187ca1e928d8bdac9bbdddebd/aiohttp-3.13.3-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:3dd4dce1c718e38081c8f35f323209d4c1df7d4db4bab1b5c88a6b4d12b74587", size = 1941001, upload-time = "2026-01-03T17:32:03.122Z" }, - { url = "https://files.pythonhosted.org/packages/37/df/d879401cedeef27ac4717f6426c8c36c3091c6e9f08a9178cc87549c537f/aiohttp-3.13.3-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:34bac00a67a812570d4a460447e1e9e06fae622946955f939051e7cc895cfab8", size = 1797246, upload-time = "2026-01-03T17:32:05.255Z" }, - { url = "https://files.pythonhosted.org/packages/8d/15/be122de1f67e6953add23335c8ece6d314ab67c8bebb3f181063010795a7/aiohttp-3.13.3-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:a19884d2ee70b06d9204b2727a7b9f983d0c684c650254679e716b0b77920632", size = 1627131, upload-time = "2026-01-03T17:32:07.607Z" }, - { url = "https://files.pythonhosted.org/packages/12/12/70eedcac9134cfa3219ab7af31ea56bc877395b1ac30d65b1bc4b27d0438/aiohttp-3.13.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:5f8ca7f2bb6ba8348a3614c7918cc4bb73268c5ac2a207576b7afea19d3d9f64", size = 1795196, upload-time = "2026-01-03T17:32:09.59Z" }, - { url = "https://files.pythonhosted.org/packages/32/11/b30e1b1cd1f3054af86ebe60df96989c6a414dd87e27ad16950eee420bea/aiohttp-3.13.3-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:b0d95340658b9d2f11d9697f59b3814a9d3bb4b7a7c20b131df4bcef464037c0", size = 1782841, upload-time = "2026-01-03T17:32:11.445Z" }, - { url = "https://files.pythonhosted.org/packages/88/0d/d98a9367b38912384a17e287850f5695c528cff0f14f791ce8ee2e4f7796/aiohttp-3.13.3-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:a1e53262fd202e4b40b70c3aff944a8155059beedc8a89bba9dc1f9ef06a1b56", size = 1795193, upload-time = "2026-01-03T17:32:13.705Z" }, - { url = "https://files.pythonhosted.org/packages/43/a5/a2dfd1f5ff5581632c7f6a30e1744deda03808974f94f6534241ef60c751/aiohttp-3.13.3-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:d60ac9663f44168038586cab2157e122e46bdef09e9368b37f2d82d354c23f72", size = 1621979, upload-time = "2026-01-03T17:32:15.965Z" }, - { url = "https://files.pythonhosted.org/packages/fa/f0/12973c382ae7c1cccbc4417e129c5bf54c374dfb85af70893646e1f0e749/aiohttp-3.13.3-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:90751b8eed69435bac9ff4e3d2f6b3af1f57e37ecb0fbeee59c0174c9e2d41df", size = 1822193, upload-time = "2026-01-03T17:32:18.219Z" }, - { url = "https://files.pythonhosted.org/packages/3c/5f/24155e30ba7f8c96918af1350eb0663e2430aad9e001c0489d89cd708ab1/aiohttp-3.13.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:fc353029f176fd2b3ec6cfc71be166aba1936fe5d73dd1992ce289ca6647a9aa", size = 1769801, upload-time = "2026-01-03T17:32:20.25Z" }, - { url = "https://files.pythonhosted.org/packages/eb/f8/7314031ff5c10e6ece114da79b338ec17eeff3a079e53151f7e9f43c4723/aiohttp-3.13.3-cp314-cp314t-win32.whl", hash = "sha256:2e41b18a58da1e474a057b3d35248d8320029f61d70a37629535b16a0c8f3767", size = 466523, upload-time = "2026-01-03T17:32:22.215Z" }, - { url = "https://files.pythonhosted.org/packages/b4/63/278a98c715ae467624eafe375542d8ba9b4383a016df8fdefe0ae28382a7/aiohttp-3.13.3-cp314-cp314t-win_amd64.whl", hash = "sha256:44531a36aa2264a1860089ffd4dce7baf875ee5a6079d5fb42e261c704ef7344", size = 499694, upload-time = "2026-01-03T17:32:24.546Z" }, +sdist = { url = "https://files.pythonhosted.org/packages/77/9a/152096d4808df8e4268befa55fba462f440f14beab85e8ad9bf990516918/aiohttp-3.13.5.tar.gz", hash = "sha256:9d98cc980ecc96be6eb4c1994ce35d28d8b1f5e5208a23b421187d1209dbb7d1", size = 7858271, upload-time = "2026-03-31T22:01:03.343Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/bd/85/cebc47ee74d8b408749073a1a46c6fcba13d170dc8af7e61996c6c9394ac/aiohttp-3.13.5-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:02222e7e233295f40e011c1b00e3b0bd451f22cf853a0304c3595633ee47da4b", size = 750547, upload-time = "2026-03-31T21:56:30.024Z" }, + { url = "https://files.pythonhosted.org/packages/05/98/afd308e35b9d3d8c9ec54c0918f1d722c86dc17ddfec272fcdbcce5a3124/aiohttp-3.13.5-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:bace460460ed20614fa6bc8cb09966c0b8517b8c58ad8046828c6078d25333b5", size = 503535, upload-time = "2026-03-31T21:56:31.935Z" }, + { url = "https://files.pythonhosted.org/packages/6f/4d/926c183e06b09d5270a309eb50fbde7b09782bfd305dec1e800f329834fb/aiohttp-3.13.5-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8f546a4dc1e6a5edbb9fd1fd6ad18134550e096a5a43f4ad74acfbd834fc6670", size = 497830, upload-time = "2026-03-31T21:56:33.654Z" }, + { url = "https://files.pythonhosted.org/packages/e4/d6/f47d1c690f115a5c2a5e8938cce4a232a5be9aac5c5fb2647efcbbbda333/aiohttp-3.13.5-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c86969d012e51b8e415a8c6ce96f7857d6a87d6207303ab02d5d11ef0cad2274", size = 1682474, upload-time = "2026-03-31T21:56:35.513Z" }, + { url = "https://files.pythonhosted.org/packages/01/44/056fd37b1bb52eac760303e5196acc74d9d546631b035704ae5927f7b4ac/aiohttp-3.13.5-cp310-cp310-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:b6f6cd1560c5fa427e3b6074bb24d2c64e225afbb7165008903bd42e4e33e28a", size = 1655259, upload-time = "2026-03-31T21:56:37.843Z" }, + { url = "https://files.pythonhosted.org/packages/91/9f/78eb1a20c1c28ae02f6a3c0f4d7b0dcc66abce5290cadd53d78ce3084175/aiohttp-3.13.5-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:636bc362f0c5bbc7372bc3ae49737f9e3030dbce469f0f422c8f38079780363d", size = 1736204, upload-time = "2026-03-31T21:56:39.822Z" }, + { url = "https://files.pythonhosted.org/packages/de/6c/d20d7de23f0b52b8c1d9e2033b2db1ac4dacbb470bb74c56de0f5f86bb4f/aiohttp-3.13.5-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:6a7cbeb06d1070f1d14895eeeed4dac5913b22d7b456f2eb969f11f4b3993796", size = 1826198, upload-time = "2026-03-31T21:56:41.378Z" }, + { url = "https://files.pythonhosted.org/packages/2f/86/a6f3ff1fd795f49545a7c74b2c92f62729135d73e7e4055bf74da5a26c82/aiohttp-3.13.5-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:bca9ef7517fd7874a1a08970ae88f497bf5c984610caa0bf40bd7e8450852b95", size = 1681329, upload-time = "2026-03-31T21:56:43.374Z" }, + { url = "https://files.pythonhosted.org/packages/fb/68/84cd3dab6b7b4f3e6fe9459a961acb142aaab846417f6e8905110d7027e5/aiohttp-3.13.5-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:019a67772e034a0e6b9b17c13d0a8fe56ad9fb150fc724b7f3ffd3724288d9e5", size = 1560023, upload-time = "2026-03-31T21:56:45.031Z" }, + { url = "https://files.pythonhosted.org/packages/41/2c/db61b64b0249e30f954a65ab4cb4970ced57544b1de2e3c98ee5dc24165f/aiohttp-3.13.5-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:f34ecee82858e41dd217734f0c41a532bd066bcaab636ad830f03a30b2a96f2a", size = 1652372, upload-time = "2026-03-31T21:56:47.075Z" }, + { url = "https://files.pythonhosted.org/packages/25/6f/e96988a6c982d047810c772e28c43c64c300c943b0ed5c1c0c4ce1e1027c/aiohttp-3.13.5-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:4eac02d9af4813ee289cd63a361576da36dba57f5a1ab36377bc2600db0cbb73", size = 1662031, upload-time = "2026-03-31T21:56:48.835Z" }, + { url = "https://files.pythonhosted.org/packages/b7/26/a56feace81f3d347b4052403a9d03754a0ab23f7940780dada0849a38c92/aiohttp-3.13.5-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:4beac52e9fe46d6abf98b0176a88154b742e878fdf209d2248e99fcdf73cd297", size = 1708118, upload-time = "2026-03-31T21:56:50.833Z" }, + { url = "https://files.pythonhosted.org/packages/78/6e/b6173a8ff03d01d5e1a694bc06764b5dad1df2d4ed8f0ceec12bb3277936/aiohttp-3.13.5-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:c180f480207a9b2475f2b8d8bd7204e47aec952d084b2a2be58a782ffcf96074", size = 1548667, upload-time = "2026-03-31T21:56:52.81Z" }, + { url = "https://files.pythonhosted.org/packages/16/13/13296ffe2c132d888b3fe2c195c8b9c0c24c89c3fa5cc2c44464dc23b22e/aiohttp-3.13.5-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:2837fb92951564d6339cedae4a7231692aa9f73cbc4fb2e04263b96844e03b4e", size = 1724490, upload-time = "2026-03-31T21:56:54.541Z" }, + { url = "https://files.pythonhosted.org/packages/7a/b4/1f1c287f4a79782ef36e5a6e62954c85343bc30470d862d30bd5f26c9fa2/aiohttp-3.13.5-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:d9010032a0b9710f58012a1e9c222528763d860ba2ee1422c03473eab47703e7", size = 1667109, upload-time = "2026-03-31T21:56:56.21Z" }, + { url = "https://files.pythonhosted.org/packages/ef/42/8461a2aaf60a8f4ea4549a4056be36b904b0eb03d97ca9a8a2604681a500/aiohttp-3.13.5-cp310-cp310-win32.whl", hash = "sha256:7c4b6668b2b2b9027f209ddf647f2a4407784b5d88b8be4efcc72036f365baf9", size = 439478, upload-time = "2026-03-31T21:56:58.292Z" }, + { url = "https://files.pythonhosted.org/packages/e5/71/06956304cb5ee439dfe8d86e1b2e70088bd88ed1ced1f42fb29e5d855f0e/aiohttp-3.13.5-cp310-cp310-win_amd64.whl", hash = "sha256:cd3db5927bf9167d5a6157ddb2f036f6b6b0ad001ac82355d43e97a4bde76d76", size = 462047, upload-time = "2026-03-31T21:57:00.257Z" }, + { url = "https://files.pythonhosted.org/packages/d6/f5/a20c4ac64aeaef1679e25c9983573618ff765d7aa829fa2b84ae7573169e/aiohttp-3.13.5-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:7ab7229b6f9b5c1ba4910d6c41a9eb11f543eadb3f384df1b4c293f4e73d44d6", size = 757513, upload-time = "2026-03-31T21:57:02.146Z" }, + { url = "https://files.pythonhosted.org/packages/75/0a/39fa6c6b179b53fcb3e4b3d2b6d6cad0180854eda17060c7218540102bef/aiohttp-3.13.5-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:8f14c50708bb156b3a3ca7230b3d820199d56a48e3af76fa21c2d6087190fe3d", size = 506748, upload-time = "2026-03-31T21:57:04.275Z" }, + { url = "https://files.pythonhosted.org/packages/87/ec/e38ce072e724fd7add6243613f8d1810da084f54175353d25ccf9f9c7e5a/aiohttp-3.13.5-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:e7d2f8616f0ff60bd332022279011776c3ac0faa0f1b463f7bb12326fbc97a1c", size = 501673, upload-time = "2026-03-31T21:57:06.208Z" }, + { url = "https://files.pythonhosted.org/packages/ba/ba/3bc7525d7e2beaa11b309a70d48b0d3cfc3c2089ec6a7d0820d59c657053/aiohttp-3.13.5-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a2567b72e1ffc3ab25510db43f355b29eeada56c0a622e58dcdb19530eb0a3cb", size = 1763757, upload-time = "2026-03-31T21:57:07.882Z" }, + { url = "https://files.pythonhosted.org/packages/5e/ab/e87744cf18f1bd78263aba24924d4953b41086bd3a31d22452378e9028a0/aiohttp-3.13.5-cp311-cp311-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:fb0540c854ac9c0c5ad495908fdfd3e332d553ec731698c0e29b1877ba0d2ec6", size = 1720152, upload-time = "2026-03-31T21:57:09.946Z" }, + { url = "https://files.pythonhosted.org/packages/6b/f3/ed17a6f2d742af17b50bae2d152315ed1b164b07a5fd5cc1754d99e4dfa5/aiohttp-3.13.5-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:c9883051c6972f58bfc4ebb2116345ee2aa151178e99c3f2b2bbe2af712abd13", size = 1818010, upload-time = "2026-03-31T21:57:12.157Z" }, + { url = "https://files.pythonhosted.org/packages/53/06/ecbc63dc937192e2a5cb46df4d3edb21deb8225535818802f210a6ea5816/aiohttp-3.13.5-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:2294172ce08a82fb7c7273485895de1fa1186cc8294cfeb6aef4af42ad261174", size = 1907251, upload-time = "2026-03-31T21:57:14.023Z" }, + { url = "https://files.pythonhosted.org/packages/7e/a5/0521aa32c1ddf3aa1e71dcc466be0b7db2771907a13f18cddaa45967d97b/aiohttp-3.13.5-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:3a807cabd5115fb55af198b98178997a5e0e57dead43eb74a93d9c07d6d4a7dc", size = 1759969, upload-time = "2026-03-31T21:57:16.146Z" }, + { url = "https://files.pythonhosted.org/packages/f6/78/a38f8c9105199dd3b9706745865a8a59d0041b6be0ca0cc4b2ccf1bab374/aiohttp-3.13.5-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:aa6d0d932e0f39c02b80744273cd5c388a2d9bc07760a03164f229c8e02662f6", size = 1616871, upload-time = "2026-03-31T21:57:17.856Z" }, + { url = "https://files.pythonhosted.org/packages/6f/41/27392a61ead8ab38072105c71aa44ff891e71653fe53d576a7067da2b4e8/aiohttp-3.13.5-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:60869c7ac4aaabe7110f26499f3e6e5696eae98144735b12a9c3d9eae2b51a49", size = 1739844, upload-time = "2026-03-31T21:57:19.679Z" }, + { url = "https://files.pythonhosted.org/packages/6e/55/5564e7ae26d94f3214250009a0b1c65a0c6af4bf88924ccb6fdab901de28/aiohttp-3.13.5-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:26d2f8546f1dfa75efa50c3488215a903c0168d253b75fba4210f57ab77a0fb8", size = 1731969, upload-time = "2026-03-31T21:57:22.006Z" }, + { url = "https://files.pythonhosted.org/packages/6d/c5/705a3929149865fc941bcbdd1047b238e4a72bcb215a9b16b9d7a2e8d992/aiohttp-3.13.5-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:f1162a1492032c82f14271e831c8f4b49f2b6078f4f5fc74de2c912fa225d51d", size = 1795193, upload-time = "2026-03-31T21:57:24.256Z" }, + { url = "https://files.pythonhosted.org/packages/a6/19/edabed62f718d02cff7231ca0db4ef1c72504235bc467f7b67adb1679f48/aiohttp-3.13.5-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:8b14eb3262fad0dc2f89c1a43b13727e709504972186ff6a99a3ecaa77102b6c", size = 1606477, upload-time = "2026-03-31T21:57:26.364Z" }, + { url = "https://files.pythonhosted.org/packages/de/fc/76f80ef008675637d88d0b21584596dc27410a990b0918cb1e5776545b5b/aiohttp-3.13.5-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:ca9ac61ac6db4eb6c2a0cd1d0f7e1357647b638ccc92f7e9d8d133e71ed3c6ac", size = 1813198, upload-time = "2026-03-31T21:57:28.316Z" }, + { url = "https://files.pythonhosted.org/packages/e5/67/5b3ac26b80adb20ea541c487f73730dc8fa107d632c998f25bbbab98fcda/aiohttp-3.13.5-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:7996023b2ed59489ae4762256c8516df9820f751cf2c5da8ed2fb20ee50abab3", size = 1752321, upload-time = "2026-03-31T21:57:30.549Z" }, + { url = "https://files.pythonhosted.org/packages/88/06/e4a2e49255ea23fa4feeb5ab092d90240d927c15e47b5b5c48dff5a9ce29/aiohttp-3.13.5-cp311-cp311-win32.whl", hash = "sha256:77dfa48c9f8013271011e51c00f8ada19851f013cde2c48fca1ba5e0caf5bb06", size = 439069, upload-time = "2026-03-31T21:57:32.388Z" }, + { url = "https://files.pythonhosted.org/packages/c0/43/8c7163a596dab4f8be12c190cf467a1e07e4734cf90eebb39f7f5d53fc6a/aiohttp-3.13.5-cp311-cp311-win_amd64.whl", hash = "sha256:d3a4834f221061624b8887090637db9ad4f61752001eae37d56c52fddade2dc8", size = 462859, upload-time = "2026-03-31T21:57:34.455Z" }, + { url = "https://files.pythonhosted.org/packages/be/6f/353954c29e7dcce7cf00280a02c75f30e133c00793c7a2ed3776d7b2f426/aiohttp-3.13.5-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:023ecba036ddd840b0b19bf195bfae970083fd7024ce1ac22e9bba90464620e9", size = 748876, upload-time = "2026-03-31T21:57:36.319Z" }, + { url = "https://files.pythonhosted.org/packages/f5/1b/428a7c64687b3b2e9cd293186695affc0e1e54a445d0361743b231f11066/aiohttp-3.13.5-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:15c933ad7920b7d9a20de151efcd05a6e38302cbf0e10c9b2acb9a42210a2416", size = 499557, upload-time = "2026-03-31T21:57:38.236Z" }, + { url = "https://files.pythonhosted.org/packages/29/47/7be41556bfbb6917069d6a6634bb7dd5e163ba445b783a90d40f5ac7e3a7/aiohttp-3.13.5-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ab2899f9fa2f9f741896ebb6fa07c4c883bfa5c7f2ddd8cf2aafa86fa981b2d2", size = 500258, upload-time = "2026-03-31T21:57:39.923Z" }, + { url = "https://files.pythonhosted.org/packages/67/84/c9ecc5828cb0b3695856c07c0a6817a99d51e2473400f705275a2b3d9239/aiohttp-3.13.5-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a60eaa2d440cd4707696b52e40ed3e2b0f73f65be07fd0ef23b6b539c9c0b0b4", size = 1749199, upload-time = "2026-03-31T21:57:41.938Z" }, + { url = "https://files.pythonhosted.org/packages/f0/d3/3c6d610e66b495657622edb6ae7c7fd31b2e9086b4ec50b47897ad6042a9/aiohttp-3.13.5-cp312-cp312-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:55b3bdd3292283295774ab585160c4004f4f2f203946997f49aac032c84649e9", size = 1721013, upload-time = "2026-03-31T21:57:43.904Z" }, + { url = "https://files.pythonhosted.org/packages/49/a0/24409c12217456df0bae7babe3b014e460b0b38a8e60753d6cb339f6556d/aiohttp-3.13.5-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:c2b2355dc094e5f7d45a7bb262fe7207aa0460b37a0d87027dcf21b5d890e7d5", size = 1781501, upload-time = "2026-03-31T21:57:46.285Z" }, + { url = "https://files.pythonhosted.org/packages/98/9d/b65ec649adc5bccc008b0957a9a9c691070aeac4e41cea18559fef49958b/aiohttp-3.13.5-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:b38765950832f7d728297689ad78f5f2cf79ff82487131c4d26fe6ceecdc5f8e", size = 1878981, upload-time = "2026-03-31T21:57:48.734Z" }, + { url = "https://files.pythonhosted.org/packages/57/d8/8d44036d7eb7b6a8ec4c5494ea0c8c8b94fbc0ed3991c1a7adf230df03bf/aiohttp-3.13.5-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b18f31b80d5a33661e08c89e202edabf1986e9b49c42b4504371daeaa11b47c1", size = 1767934, upload-time = "2026-03-31T21:57:51.171Z" }, + { url = "https://files.pythonhosted.org/packages/31/04/d3f8211f273356f158e3464e9e45484d3fb8c4ce5eb2f6fe9405c3273983/aiohttp-3.13.5-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:33add2463dde55c4f2d9635c6ab33ce154e5ecf322bd26d09af95c5f81cfa286", size = 1566671, upload-time = "2026-03-31T21:57:53.326Z" }, + { url = "https://files.pythonhosted.org/packages/41/db/073e4ebe00b78e2dfcacff734291651729a62953b48933d765dc513bf798/aiohttp-3.13.5-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:327cc432fdf1356fb4fbc6fe833ad4e9f6aacb71a8acaa5f1855e4b25910e4a9", size = 1705219, upload-time = "2026-03-31T21:57:55.385Z" }, + { url = "https://files.pythonhosted.org/packages/48/45/7dfba71a2f9fd97b15c95c06819de7eb38113d2cdb6319669195a7d64270/aiohttp-3.13.5-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:7c35b0bf0b48a70b4cb4fc5d7bed9b932532728e124874355de1a0af8ec4bc88", size = 1743049, upload-time = "2026-03-31T21:57:57.341Z" }, + { url = "https://files.pythonhosted.org/packages/18/71/901db0061e0f717d226386a7f471bb59b19566f2cae5f0d93874b017271f/aiohttp-3.13.5-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:df23d57718f24badef8656c49743e11a89fd6f5358fa8a7b96e728fda2abf7d3", size = 1749557, upload-time = "2026-03-31T21:57:59.626Z" }, + { url = "https://files.pythonhosted.org/packages/08/d5/41eebd16066e59cd43728fe74bce953d7402f2b4ddfdfef2c0e9f17ca274/aiohttp-3.13.5-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:02e048037a6501a5ec1f6fc9736135aec6eb8a004ce48838cb951c515f32c80b", size = 1558931, upload-time = "2026-03-31T21:58:01.972Z" }, + { url = "https://files.pythonhosted.org/packages/30/e6/4a799798bf05740e66c3a1161079bda7a3dd8e22ca392481d7a7f9af82a6/aiohttp-3.13.5-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:31cebae8b26f8a615d2b546fee45d5ffb76852ae6450e2a03f42c9102260d6fe", size = 1774125, upload-time = "2026-03-31T21:58:04.007Z" }, + { url = "https://files.pythonhosted.org/packages/84/63/7749337c90f92bc2cb18f9560d67aa6258c7060d1397d21529b8004fcf6f/aiohttp-3.13.5-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:888e78eb5ca55a615d285c3c09a7a91b42e9dd6fc699b166ebd5dee87c9ccf14", size = 1732427, upload-time = "2026-03-31T21:58:06.337Z" }, + { url = "https://files.pythonhosted.org/packages/98/de/cf2f44ff98d307e72fb97d5f5bbae3bfcb442f0ea9790c0bf5c5c2331404/aiohttp-3.13.5-cp312-cp312-win32.whl", hash = "sha256:8bd3ec6376e68a41f9f95f5ed170e2fcf22d4eb27a1f8cb361d0508f6e0557f3", size = 433534, upload-time = "2026-03-31T21:58:08.712Z" }, + { url = "https://files.pythonhosted.org/packages/aa/ca/eadf6f9c8fa5e31d40993e3db153fb5ed0b11008ad5d9de98a95045bed84/aiohttp-3.13.5-cp312-cp312-win_amd64.whl", hash = "sha256:110e448e02c729bcebb18c60b9214a87ba33bac4a9fa5e9a5f139938b56c6cb1", size = 460446, upload-time = "2026-03-31T21:58:10.945Z" }, + { url = "https://files.pythonhosted.org/packages/78/e9/d76bf503005709e390122d34e15256b88f7008e246c4bdbe915cd4f1adce/aiohttp-3.13.5-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:a5029cc80718bbd545123cd8fe5d15025eccaaaace5d0eeec6bd556ad6163d61", size = 742930, upload-time = "2026-03-31T21:58:13.155Z" }, + { url = "https://files.pythonhosted.org/packages/57/00/4b7b70223deaebd9bb85984d01a764b0d7bd6526fcdc73cca83bcbe7243e/aiohttp-3.13.5-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:4bb6bf5811620003614076bdc807ef3b5e38244f9d25ca5fe888eaccea2a9832", size = 496927, upload-time = "2026-03-31T21:58:15.073Z" }, + { url = "https://files.pythonhosted.org/packages/9c/f5/0fb20fb49f8efdcdce6cd8127604ad2c503e754a8f139f5e02b01626523f/aiohttp-3.13.5-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:a84792f8631bf5a94e52d9cc881c0b824ab42717165a5579c760b830d9392ac9", size = 497141, upload-time = "2026-03-31T21:58:17.009Z" }, + { url = "https://files.pythonhosted.org/packages/3b/86/b7c870053e36a94e8951b803cb5b909bfbc9b90ca941527f5fcafbf6b0fa/aiohttp-3.13.5-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:57653eac22c6a4c13eb22ecf4d673d64a12f266e72785ab1c8b8e5940d0e8090", size = 1732476, upload-time = "2026-03-31T21:58:18.925Z" }, + { url = "https://files.pythonhosted.org/packages/b5/e5/4e161f84f98d80c03a238671b4136e6530453d65262867d989bbe78244d0/aiohttp-3.13.5-cp313-cp313-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:e5e5f7debc7a57af53fdf5c5009f9391d9f4c12867049d509bf7bb164a6e295b", size = 1706507, upload-time = "2026-03-31T21:58:21.094Z" }, + { url = "https://files.pythonhosted.org/packages/d4/56/ea11a9f01518bd5a2a2fcee869d248c4b8a0cfa0bb13401574fa31adf4d4/aiohttp-3.13.5-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:c719f65bebcdf6716f10e9eff80d27567f7892d8988c06de12bbbd39307c6e3a", size = 1773465, upload-time = "2026-03-31T21:58:23.159Z" }, + { url = "https://files.pythonhosted.org/packages/eb/40/333ca27fb74b0383f17c90570c748f7582501507307350a79d9f9f3c6eb1/aiohttp-3.13.5-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:d97f93fdae594d886c5a866636397e2bcab146fd7a132fd6bb9ce182224452f8", size = 1873523, upload-time = "2026-03-31T21:58:25.59Z" }, + { url = "https://files.pythonhosted.org/packages/f0/d2/e2f77eef1acb7111405433c707dc735e63f67a56e176e72e9e7a2cd3f493/aiohttp-3.13.5-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:3df334e39d4c2f899a914f1dba283c1aadc311790733f705182998c6f7cae665", size = 1754113, upload-time = "2026-03-31T21:58:27.624Z" }, + { url = "https://files.pythonhosted.org/packages/fb/56/3f653d7f53c89669301ec9e42c95233e2a0c0a6dd051269e6e678db4fdb0/aiohttp-3.13.5-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:fe6970addfea9e5e081401bcbadf865d2b6da045472f58af08427e108d618540", size = 1562351, upload-time = "2026-03-31T21:58:29.918Z" }, + { url = "https://files.pythonhosted.org/packages/ec/a6/9b3e91eb8ae791cce4ee736da02211c85c6f835f1bdfac0594a8a3b7018c/aiohttp-3.13.5-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:7becdf835feff2f4f335d7477f121af787e3504b48b449ff737afb35869ba7bb", size = 1693205, upload-time = "2026-03-31T21:58:32.214Z" }, + { url = "https://files.pythonhosted.org/packages/98/fc/bfb437a99a2fcebd6b6eaec609571954de2ed424f01c352f4b5504371dd3/aiohttp-3.13.5-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:676e5651705ad5d8a70aeb8eb6936c436d8ebbd56e63436cb7dd9bb36d2a9a46", size = 1730618, upload-time = "2026-03-31T21:58:34.728Z" }, + { url = "https://files.pythonhosted.org/packages/e4/b6/c8534862126191a034f68153194c389addc285a0f1347d85096d349bbc15/aiohttp-3.13.5-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:9b16c653d38eb1a611cc898c41e76859ca27f119d25b53c12875fd0474ae31a8", size = 1745185, upload-time = "2026-03-31T21:58:36.909Z" }, + { url = "https://files.pythonhosted.org/packages/0b/93/4ca8ee2ef5236e2707e0fd5fecb10ce214aee1ff4ab307af9c558bda3b37/aiohttp-3.13.5-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:999802d5fa0389f58decd24b537c54aa63c01c3219ce17d1214cbda3c2b22d2d", size = 1557311, upload-time = "2026-03-31T21:58:39.38Z" }, + { url = "https://files.pythonhosted.org/packages/57/ae/76177b15f18c5f5d094f19901d284025db28eccc5ae374d1d254181d33f4/aiohttp-3.13.5-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:ec707059ee75732b1ba130ed5f9580fe10ff75180c812bc267ded039db5128c6", size = 1773147, upload-time = "2026-03-31T21:58:41.476Z" }, + { url = "https://files.pythonhosted.org/packages/01/a4/62f05a0a98d88af59d93b7fcac564e5f18f513cb7471696ac286db970d6a/aiohttp-3.13.5-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:2d6d44a5b48132053c2f6cd5c8cb14bc67e99a63594e336b0f2af81e94d5530c", size = 1730356, upload-time = "2026-03-31T21:58:44.049Z" }, + { url = "https://files.pythonhosted.org/packages/e4/85/fc8601f59dfa8c9523808281f2da571f8b4699685f9809a228adcc90838d/aiohttp-3.13.5-cp313-cp313-win32.whl", hash = "sha256:329f292ed14d38a6c4c435e465f48bebb47479fd676a0411936cc371643225cc", size = 432637, upload-time = "2026-03-31T21:58:46.167Z" }, + { url = "https://files.pythonhosted.org/packages/c0/1b/ac685a8882896acf0f6b31d689e3792199cfe7aba37969fa91da63a7fa27/aiohttp-3.13.5-cp313-cp313-win_amd64.whl", hash = "sha256:69f571de7500e0557801c0b51f4780482c0ec5fe2ac851af5a92cfce1af1cb83", size = 458896, upload-time = "2026-03-31T21:58:48.119Z" }, + { url = "https://files.pythonhosted.org/packages/5d/ce/46572759afc859e867a5bc8ec3487315869013f59281ce61764f76d879de/aiohttp-3.13.5-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:eb4639f32fd4a9904ab8fb45bf3383ba71137f3d9d4ba25b3b3f3109977c5b8c", size = 745721, upload-time = "2026-03-31T21:58:50.229Z" }, + { url = "https://files.pythonhosted.org/packages/13/fe/8a2efd7626dbe6049b2ef8ace18ffda8a4dfcbe1bcff3ac30c0c7575c20b/aiohttp-3.13.5-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:7e5dc4311bd5ac493886c63cbf76ab579dbe4641268e7c74e48e774c74b6f2be", size = 497663, upload-time = "2026-03-31T21:58:52.232Z" }, + { url = "https://files.pythonhosted.org/packages/9b/91/cc8cc78a111826c54743d88651e1687008133c37e5ee615fee9b57990fac/aiohttp-3.13.5-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:756c3c304d394977519824449600adaf2be0ccee76d206ee339c5e76b70ded25", size = 499094, upload-time = "2026-03-31T21:58:54.566Z" }, + { url = "https://files.pythonhosted.org/packages/0a/33/a8362cb15cf16a3af7e86ed11962d5cd7d59b449202dc576cdc731310bde/aiohttp-3.13.5-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ecc26751323224cf8186efcf7fbcbc30f4e1d8c7970659daf25ad995e4032a56", size = 1726701, upload-time = "2026-03-31T21:58:56.864Z" }, + { url = "https://files.pythonhosted.org/packages/45/0c/c091ac5c3a17114bd76cbf85d674650969ddf93387876cf67f754204bd77/aiohttp-3.13.5-cp314-cp314-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:10a75acfcf794edf9d8db50e5a7ec5fc818b2a8d3f591ce93bc7b1210df016d2", size = 1683360, upload-time = "2026-03-31T21:58:59.072Z" }, + { url = "https://files.pythonhosted.org/packages/23/73/bcee1c2b79bc275e964d1446c55c54441a461938e70267c86afaae6fba27/aiohttp-3.13.5-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:0f7a18f258d124cd678c5fe072fe4432a4d5232b0657fca7c1847f599233c83a", size = 1773023, upload-time = "2026-03-31T21:59:01.776Z" }, + { url = "https://files.pythonhosted.org/packages/c7/ef/720e639df03004fee2d869f771799d8c23046dec47d5b81e396c7cda583a/aiohttp-3.13.5-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:df6104c009713d3a89621096f3e3e88cc323fd269dbd7c20afe18535094320be", size = 1853795, upload-time = "2026-03-31T21:59:04.568Z" }, + { url = "https://files.pythonhosted.org/packages/bd/c9/989f4034fb46841208de7aeeac2c6d8300745ab4f28c42f629ba77c2d916/aiohttp-3.13.5-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:241a94f7de7c0c3b616627aaad530fe2cb620084a8b144d3be7b6ecfe95bae3b", size = 1730405, upload-time = "2026-03-31T21:59:07.221Z" }, + { url = "https://files.pythonhosted.org/packages/ce/75/ee1fd286ca7dc599d824b5651dad7b3be7ff8d9a7e7b3fe9820d9180f7db/aiohttp-3.13.5-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:c974fb66180e58709b6fc402846f13791240d180b74de81d23913abe48e96d94", size = 1558082, upload-time = "2026-03-31T21:59:09.484Z" }, + { url = "https://files.pythonhosted.org/packages/c3/20/1e9e6650dfc436340116b7aa89ff8cb2bbdf0abc11dfaceaad8f74273a10/aiohttp-3.13.5-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:6e27ea05d184afac78aabbac667450c75e54e35f62238d44463131bd3f96753d", size = 1692346, upload-time = "2026-03-31T21:59:12.068Z" }, + { url = "https://files.pythonhosted.org/packages/d8/40/8ebc6658d48ea630ac7903912fe0dd4e262f0e16825aa4c833c56c9f1f56/aiohttp-3.13.5-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:a79a6d399cef33a11b6f004c67bb07741d91f2be01b8d712d52c75711b1e07c7", size = 1698891, upload-time = "2026-03-31T21:59:14.552Z" }, + { url = "https://files.pythonhosted.org/packages/d8/78/ea0ae5ec8ba7a5c10bdd6e318f1ba5e76fcde17db8275188772afc7917a4/aiohttp-3.13.5-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:c632ce9c0b534fbe25b52c974515ed674937c5b99f549a92127c85f771a78772", size = 1742113, upload-time = "2026-03-31T21:59:17.068Z" }, + { url = "https://files.pythonhosted.org/packages/8a/66/9d308ed71e3f2491be1acb8769d96c6f0c47d92099f3bc9119cada27b357/aiohttp-3.13.5-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:fceedde51fbd67ee2bcc8c0b33d0126cc8b51ef3bbde2f86662bd6d5a6f10ec5", size = 1553088, upload-time = "2026-03-31T21:59:19.541Z" }, + { url = "https://files.pythonhosted.org/packages/da/a6/6cc25ed8dfc6e00c90f5c6d126a98e2cf28957ad06fa1036bd34b6f24a2c/aiohttp-3.13.5-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:f92995dfec9420bb69ae629abf422e516923ba79ba4403bc750d94fb4a6c68c1", size = 1757976, upload-time = "2026-03-31T21:59:22.311Z" }, + { url = "https://files.pythonhosted.org/packages/c1/2b/cce5b0ffe0de99c83e5e36d8f828e4161e415660a9f3e58339d07cce3006/aiohttp-3.13.5-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:20ae0ff08b1f2c8788d6fb85afcb798654ae6ba0b747575f8562de738078457b", size = 1712444, upload-time = "2026-03-31T21:59:24.635Z" }, + { url = "https://files.pythonhosted.org/packages/6c/cf/9e1795b4160c58d29421eafd1a69c6ce351e2f7c8d3c6b7e4ca44aea1a5b/aiohttp-3.13.5-cp314-cp314-win32.whl", hash = "sha256:b20df693de16f42b2472a9c485e1c948ee55524786a0a34345511afdd22246f3", size = 438128, upload-time = "2026-03-31T21:59:27.291Z" }, + { url = "https://files.pythonhosted.org/packages/22/4d/eaedff67fc805aeba4ba746aec891b4b24cebb1a7d078084b6300f79d063/aiohttp-3.13.5-cp314-cp314-win_amd64.whl", hash = "sha256:f85c6f327bf0b8c29da7d93b1cabb6363fb5e4e160a32fa241ed2dce21b73162", size = 464029, upload-time = "2026-03-31T21:59:29.429Z" }, + { url = "https://files.pythonhosted.org/packages/79/11/c27d9332ee20d68dd164dc12a6ecdef2e2e35ecc97ed6cf0d2442844624b/aiohttp-3.13.5-cp314-cp314t-macosx_10_13_universal2.whl", hash = "sha256:1efb06900858bb618ff5cee184ae2de5828896c448403d51fb633f09e109be0a", size = 778758, upload-time = "2026-03-31T21:59:31.547Z" }, + { url = "https://files.pythonhosted.org/packages/04/fb/377aead2e0a3ba5f09b7624f702a964bdf4f08b5b6728a9799830c80041e/aiohttp-3.13.5-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:fee86b7c4bd29bdaf0d53d14739b08a106fdda809ca5fe032a15f52fae5fe254", size = 512883, upload-time = "2026-03-31T21:59:34.098Z" }, + { url = "https://files.pythonhosted.org/packages/bb/a6/aa109a33671f7a5d3bd78b46da9d852797c5e665bfda7d6b373f56bff2ec/aiohttp-3.13.5-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:20058e23909b9e65f9da62b396b77dfa95965cbe840f8def6e572538b1d32e36", size = 516668, upload-time = "2026-03-31T21:59:36.497Z" }, + { url = "https://files.pythonhosted.org/packages/79/b3/ca078f9f2fa9563c36fb8ef89053ea2bb146d6f792c5104574d49d8acb63/aiohttp-3.13.5-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8cf20a8d6868cb15a73cab329ffc07291ba8c22b1b88176026106ae39aa6df0f", size = 1883461, upload-time = "2026-03-31T21:59:38.723Z" }, + { url = "https://files.pythonhosted.org/packages/b7/e3/a7ad633ca1ca497b852233a3cce6906a56c3225fb6d9217b5e5e60b7419d/aiohttp-3.13.5-cp314-cp314t-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:330f5da04c987f1d5bdb8ae189137c77139f36bd1cb23779ca1a354a4b027800", size = 1747661, upload-time = "2026-03-31T21:59:41.187Z" }, + { url = "https://files.pythonhosted.org/packages/33/b9/cd6fe579bed34a906d3d783fe60f2fa297ef55b27bb4538438ee49d4dc41/aiohttp-3.13.5-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:6f1cbf0c7926d315c3c26c2da41fd2b5d2fe01ac0e157b78caefc51a782196cf", size = 1863800, upload-time = "2026-03-31T21:59:43.84Z" }, + { url = "https://files.pythonhosted.org/packages/c0/3f/2c1e2f5144cefa889c8afd5cf431994c32f3b29da9961698ff4e3811b79a/aiohttp-3.13.5-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:53fc049ed6390d05423ba33103ded7281fe897cf97878f369a527070bd95795b", size = 1958382, upload-time = "2026-03-31T21:59:46.187Z" }, + { url = "https://files.pythonhosted.org/packages/66/1d/f31ec3f1013723b3babe3609e7f119c2c2fb6ef33da90061a705ef3e1bc8/aiohttp-3.13.5-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:898703aa2667e3c5ca4c54ca36cd73f58b7a38ef87a5606414799ebce4d3fd3a", size = 1803724, upload-time = "2026-03-31T21:59:48.656Z" }, + { url = "https://files.pythonhosted.org/packages/0e/b4/57712dfc6f1542f067daa81eb61da282fab3e6f1966fca25db06c4fc62d5/aiohttp-3.13.5-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:0494a01ca9584eea1e5fbd6d748e61ecff218c51b576ee1999c23db7066417d8", size = 1640027, upload-time = "2026-03-31T21:59:51.284Z" }, + { url = "https://files.pythonhosted.org/packages/25/3c/734c878fb43ec083d8e31bf029daae1beafeae582d1b35da234739e82ee7/aiohttp-3.13.5-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:6cf81fe010b8c17b09495cbd15c1d35afbc8fb405c0c9cf4738e5ae3af1d65be", size = 1806644, upload-time = "2026-03-31T21:59:53.753Z" }, + { url = "https://files.pythonhosted.org/packages/20/a5/f671e5cbec1c21d044ff3078223f949748f3a7f86b14e34a365d74a5d21f/aiohttp-3.13.5-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:c564dd5f09ddc9d8f2c2d0a301cd30a79a2cc1b46dd1a73bef8f0038863d016b", size = 1791630, upload-time = "2026-03-31T21:59:56.239Z" }, + { url = "https://files.pythonhosted.org/packages/0b/63/fb8d0ad63a0b8a99be97deac8c04dacf0785721c158bdf23d679a87aa99e/aiohttp-3.13.5-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:2994be9f6e51046c4f864598fd9abeb4fba6e88f0b2152422c9666dcd4aea9c6", size = 1809403, upload-time = "2026-03-31T21:59:59.103Z" }, + { url = "https://files.pythonhosted.org/packages/59/0c/bfed7f30662fcf12206481c2aac57dedee43fe1c49275e85b3a1e1742294/aiohttp-3.13.5-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:157826e2fa245d2ef46c83ea8a5faf77ca19355d278d425c29fda0beb3318037", size = 1634924, upload-time = "2026-03-31T22:00:02.116Z" }, + { url = "https://files.pythonhosted.org/packages/17/d6/fd518d668a09fd5a3319ae5e984d4d80b9a4b3df4e21c52f02251ef5a32e/aiohttp-3.13.5-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:a8aca50daa9493e9e13c0f566201a9006f080e7c50e5e90d0b06f53146a54500", size = 1836119, upload-time = "2026-03-31T22:00:04.756Z" }, + { url = "https://files.pythonhosted.org/packages/78/b7/15fb7a9d52e112a25b621c67b69c167805cb1f2ab8f1708a5c490d1b52fe/aiohttp-3.13.5-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:3b13560160d07e047a93f23aaa30718606493036253d5430887514715b67c9d9", size = 1772072, upload-time = "2026-03-31T22:00:07.494Z" }, + { url = "https://files.pythonhosted.org/packages/7e/df/57ba7f0c4a553fc2bd8b6321df236870ec6fd64a2a473a8a13d4f733214e/aiohttp-3.13.5-cp314-cp314t-win32.whl", hash = "sha256:9a0f4474b6ea6818b41f82172d799e4b3d29e22c2c520ce4357856fced9af2f8", size = 471819, upload-time = "2026-03-31T22:00:10.277Z" }, + { url = "https://files.pythonhosted.org/packages/62/29/2f8418269e46454a26171bfdd6a055d74febf32234e474930f2f60a17145/aiohttp-3.13.5-cp314-cp314t-win_amd64.whl", hash = "sha256:18a2f6c1182c51baa1d28d68fea51513cb2a76612f038853c0ad3c145423d3d9", size = 505441, upload-time = "2026-03-31T22:00:12.791Z" }, ] [[package]] @@ -257,17 +257,16 @@ wheels = [ [[package]] name = "anyio" -version = "4.11.0" +version = "4.13.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "exceptiongroup", marker = "python_full_version < '3.11'" }, { name = "idna" }, - { name = "sniffio" }, { name = "typing-extensions", marker = "python_full_version < '3.13'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/c6/78/7d432127c41b50bccba979505f272c16cbcadcc33645d5fa3a738110ae75/anyio-4.11.0.tar.gz", hash = "sha256:82a8d0b81e318cc5ce71a5f1f8b5c4e63619620b63141ef8c995fa0db95a57c4", size = 219094, upload-time = "2025-09-23T09:19:12.58Z" } +sdist = { url = "https://files.pythonhosted.org/packages/19/14/2c5dd9f512b66549ae92767a9c7b330ae88e1932ca57876909410251fe13/anyio-4.13.0.tar.gz", hash = "sha256:334b70e641fd2221c1505b3890c69882fe4a2df910cba14d97019b90b24439dc", size = 231622, upload-time = "2026-03-24T12:59:09.671Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/15/b3/9b1a8074496371342ec1e796a96f99c82c945a339cd81a8e73de28b4cf9e/anyio-4.11.0-py3-none-any.whl", hash = "sha256:0287e96f4d26d4149305414d4e3bc32f0dcd0862365a4bddea19d7a1ec38c4fc", size = 109097, upload-time = "2025-09-23T09:19:10.601Z" }, + { url = "https://files.pythonhosted.org/packages/da/42/e921fccf5015463e32a3cf6ee7f980a6ed0f395ceeaa45060b61d86486c2/anyio-4.13.0-py3-none-any.whl", hash = "sha256:08b310f9e24a9594186fd75b4f73f4a4152069e3853f1ed8bfbf58369f4ad708", size = 114353, upload-time = "2026-03-24T12:59:08.246Z" }, ] [[package]] @@ -281,11 +280,11 @@ wheels = [ [[package]] name = "attrs" -version = "25.4.0" +version = "26.1.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/6b/5c/685e6633917e101e5dcb62b9dd76946cbb57c26e133bae9e0cd36033c0a9/attrs-25.4.0.tar.gz", hash = "sha256:16d5969b87f0859ef33a48b35d55ac1be6e42ae49d5e853b597db70c35c57e11", size = 934251, upload-time = "2025-10-06T13:54:44.725Z" } +sdist = { url = "https://files.pythonhosted.org/packages/9a/8e/82a0fe20a541c03148528be8cac2408564a6c9a0cc7e9171802bc1d26985/attrs-26.1.0.tar.gz", hash = "sha256:d03ceb89cb322a8fd706d4fb91940737b6642aa36998fe130a9bc96c985eff32", size = 952055, upload-time = "2026-03-19T14:22:25.026Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/3a/2a/7cc015f5b9f5db42b7d48157e23356022889fc354a2813c15934b7cb5c0e/attrs-25.4.0-py3-none-any.whl", hash = "sha256:adcf7e2a1fb3b36ac48d97835bb6d8ade15b8dcce26aba8bf1d14847b57a3373", size = 67615, upload-time = "2025-10-06T13:54:43.17Z" }, + { url = "https://files.pythonhosted.org/packages/64/b4/17d4b0b2a2dc85a6df63d1157e028ed19f90d4cd97c36717afef2bc2f395/attrs-26.1.0-py3-none-any.whl", hash = "sha256:c647aa4a12dfbad9333ca4e71fe62ddc36f4e63b2d260a37a8b83d2f043ac309", size = 67548, upload-time = "2026-03-19T14:22:23.645Z" }, ] [[package]] @@ -427,15 +426,15 @@ wheels = [ [[package]] name = "cachecontrol" -version = "0.14.3" +version = "0.14.4" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "msgpack" }, { name = "requests" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/58/3a/0cbeb04ea57d2493f3ec5a069a117ab467f85e4a10017c6d854ddcbff104/cachecontrol-0.14.3.tar.gz", hash = "sha256:73e7efec4b06b20d9267b441c1f733664f989fb8688391b670ca812d70795d11", size = 28985, upload-time = "2025-04-30T16:45:06.135Z" } +sdist = { url = "https://files.pythonhosted.org/packages/2d/f6/c972b32d80760fb79d6b9eeb0b3010a46b89c0b23cf6329417ff7886cd22/cachecontrol-0.14.4.tar.gz", hash = "sha256:e6220afafa4c22a47dd0badb319f84475d79108100d04e26e8542ef7d3ab05a1", size = 16150, upload-time = "2025-11-14T04:32:13.138Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/81/4c/800b0607b00b3fd20f1087f80ab53d6b4d005515b0f773e4831e37cfa83f/cachecontrol-0.14.3-py3-none-any.whl", hash = "sha256:b35e44a3113f17d2a31c1e6b27b9de6d4405f84ae51baa8c1d3cc5b633010cae", size = 21802, upload-time = "2025-04-30T16:45:03.863Z" }, + { url = "https://files.pythonhosted.org/packages/ef/79/c45f2d53efe6ada1110cf6f9fca095e4ff47a0454444aefdde6ac4789179/cachecontrol-0.14.4-py3-none-any.whl", hash = "sha256:b7ac014ff72ee199b5f8af1de29d60239954f223e948196fa3d84adaffc71d2b", size = 22247, upload-time = "2025-11-14T04:32:11.733Z" }, ] [package.optional-dependencies] @@ -445,11 +444,11 @@ filecache = [ [[package]] name = "certifi" -version = "2025.10.5" +version = "2026.2.25" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/4c/5b/b6ce21586237c77ce67d01dc5507039d444b630dd76611bbca2d8e5dcd91/certifi-2025.10.5.tar.gz", hash = "sha256:47c09d31ccf2acf0be3f701ea53595ee7e0b8fa08801c6624be771df09ae7b43", size = 164519, upload-time = "2025-10-05T04:12:15.808Z" } +sdist = { url = "https://files.pythonhosted.org/packages/af/2d/7bf41579a8986e348fa033a31cdd0e4121114f6bce2457e8876010b092dd/certifi-2026.2.25.tar.gz", hash = "sha256:e887ab5cee78ea814d3472169153c2d12cd43b14bd03329a39a9c6e2e80bfba7", size = 155029, upload-time = "2026-02-25T02:54:17.342Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/e4/37/af0d2ef3967ac0d6113837b44a4f0bfe1328c2b9763bd5b1744520e5cfed/certifi-2025.10.5-py3-none-any.whl", hash = "sha256:0f212c2744a9bb6de0c56639a6f68afe01ecd92d91f14ae897c4fe7bbeeef0de", size = 163286, upload-time = "2025-10-05T04:12:14.03Z" }, + { url = "https://files.pythonhosted.org/packages/9a/3c/c17fb3ca2d9c3acff52e30b309f538586f9f5b9c9cf454f3845fc9af4881/certifi-2026.2.25-py3-none-any.whl", hash = "sha256:027692e4402ad994f1c42e52a4997a9763c646b73e4096e4d5d6db8af1d6f0fa", size = 153684, upload-time = "2026-02-25T02:54:15.766Z" }, ] [[package]] @@ -555,96 +554,112 @@ wheels = [ [[package]] name = "charset-normalizer" -version = "3.4.4" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/13/69/33ddede1939fdd074bce5434295f38fae7136463422fe4fd3e0e89b98062/charset_normalizer-3.4.4.tar.gz", hash = "sha256:94537985111c35f28720e43603b8e7b43a6ecfb2ce1d3058bbe955b73404e21a", size = 129418, upload-time = "2025-10-14T04:42:32.879Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/1f/b8/6d51fc1d52cbd52cd4ccedd5b5b2f0f6a11bbf6765c782298b0f3e808541/charset_normalizer-3.4.4-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:e824f1492727fa856dd6eda4f7cee25f8518a12f3c4a56a74e8095695089cf6d", size = 209709, upload-time = "2025-10-14T04:40:11.385Z" }, - { url = "https://files.pythonhosted.org/packages/5c/af/1f9d7f7faafe2ddfb6f72a2e07a548a629c61ad510fe60f9630309908fef/charset_normalizer-3.4.4-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4bd5d4137d500351a30687c2d3971758aac9a19208fc110ccb9d7188fbe709e8", size = 148814, upload-time = "2025-10-14T04:40:13.135Z" }, - { url = "https://files.pythonhosted.org/packages/79/3d/f2e3ac2bbc056ca0c204298ea4e3d9db9b4afe437812638759db2c976b5f/charset_normalizer-3.4.4-cp310-cp310-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:027f6de494925c0ab2a55eab46ae5129951638a49a34d87f4c3eda90f696b4ad", size = 144467, upload-time = "2025-10-14T04:40:14.728Z" }, - { url = "https://files.pythonhosted.org/packages/ec/85/1bf997003815e60d57de7bd972c57dc6950446a3e4ccac43bc3070721856/charset_normalizer-3.4.4-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:f820802628d2694cb7e56db99213f930856014862f3fd943d290ea8438d07ca8", size = 162280, upload-time = "2025-10-14T04:40:16.14Z" }, - { url = "https://files.pythonhosted.org/packages/3e/8e/6aa1952f56b192f54921c436b87f2aaf7c7a7c3d0d1a765547d64fd83c13/charset_normalizer-3.4.4-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:798d75d81754988d2565bff1b97ba5a44411867c0cf32b77a7e8f8d84796b10d", size = 159454, upload-time = "2025-10-14T04:40:17.567Z" }, - { url = "https://files.pythonhosted.org/packages/36/3b/60cbd1f8e93aa25d1c669c649b7a655b0b5fb4c571858910ea9332678558/charset_normalizer-3.4.4-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9d1bb833febdff5c8927f922386db610b49db6e0d4f4ee29601d71e7c2694313", size = 153609, upload-time = "2025-10-14T04:40:19.08Z" }, - { url = "https://files.pythonhosted.org/packages/64/91/6a13396948b8fd3c4b4fd5bc74d045f5637d78c9675585e8e9fbe5636554/charset_normalizer-3.4.4-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:9cd98cdc06614a2f768d2b7286d66805f94c48cde050acdbbb7db2600ab3197e", size = 151849, upload-time = "2025-10-14T04:40:20.607Z" }, - { url = "https://files.pythonhosted.org/packages/b7/7a/59482e28b9981d105691e968c544cc0df3b7d6133152fb3dcdc8f135da7a/charset_normalizer-3.4.4-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:077fbb858e903c73f6c9db43374fd213b0b6a778106bc7032446a8e8b5b38b93", size = 151586, upload-time = "2025-10-14T04:40:21.719Z" }, - { url = "https://files.pythonhosted.org/packages/92/59/f64ef6a1c4bdd2baf892b04cd78792ed8684fbc48d4c2afe467d96b4df57/charset_normalizer-3.4.4-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:244bfb999c71b35de57821b8ea746b24e863398194a4014e4c76adc2bbdfeff0", size = 145290, upload-time = "2025-10-14T04:40:23.069Z" }, - { url = "https://files.pythonhosted.org/packages/6b/63/3bf9f279ddfa641ffa1962b0db6a57a9c294361cc2f5fcac997049a00e9c/charset_normalizer-3.4.4-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:64b55f9dce520635f018f907ff1b0df1fdc31f2795a922fb49dd14fbcdf48c84", size = 163663, upload-time = "2025-10-14T04:40:24.17Z" }, - { url = "https://files.pythonhosted.org/packages/ed/09/c9e38fc8fa9e0849b172b581fd9803bdf6e694041127933934184e19f8c3/charset_normalizer-3.4.4-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:faa3a41b2b66b6e50f84ae4a68c64fcd0c44355741c6374813a800cd6695db9e", size = 151964, upload-time = "2025-10-14T04:40:25.368Z" }, - { url = "https://files.pythonhosted.org/packages/d2/d1/d28b747e512d0da79d8b6a1ac18b7ab2ecfd81b2944c4c710e166d8dd09c/charset_normalizer-3.4.4-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:6515f3182dbe4ea06ced2d9e8666d97b46ef4c75e326b79bb624110f122551db", size = 161064, upload-time = "2025-10-14T04:40:26.806Z" }, - { url = "https://files.pythonhosted.org/packages/bb/9a/31d62b611d901c3b9e5500c36aab0ff5eb442043fb3a1c254200d3d397d9/charset_normalizer-3.4.4-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:cc00f04ed596e9dc0da42ed17ac5e596c6ccba999ba6bd92b0e0aef2f170f2d6", size = 155015, upload-time = "2025-10-14T04:40:28.284Z" }, - { url = "https://files.pythonhosted.org/packages/1f/f3/107e008fa2bff0c8b9319584174418e5e5285fef32f79d8ee6a430d0039c/charset_normalizer-3.4.4-cp310-cp310-win32.whl", hash = "sha256:f34be2938726fc13801220747472850852fe6b1ea75869a048d6f896838c896f", size = 99792, upload-time = "2025-10-14T04:40:29.613Z" }, - { url = "https://files.pythonhosted.org/packages/eb/66/e396e8a408843337d7315bab30dbf106c38966f1819f123257f5520f8a96/charset_normalizer-3.4.4-cp310-cp310-win_amd64.whl", hash = "sha256:a61900df84c667873b292c3de315a786dd8dac506704dea57bc957bd31e22c7d", size = 107198, upload-time = "2025-10-14T04:40:30.644Z" }, - { url = "https://files.pythonhosted.org/packages/b5/58/01b4f815bf0312704c267f2ccb6e5d42bcc7752340cd487bc9f8c3710597/charset_normalizer-3.4.4-cp310-cp310-win_arm64.whl", hash = "sha256:cead0978fc57397645f12578bfd2d5ea9138ea0fac82b2f63f7f7c6877986a69", size = 100262, upload-time = "2025-10-14T04:40:32.108Z" }, - { url = "https://files.pythonhosted.org/packages/ed/27/c6491ff4954e58a10f69ad90aca8a1b6fe9c5d3c6f380907af3c37435b59/charset_normalizer-3.4.4-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:6e1fcf0720908f200cd21aa4e6750a48ff6ce4afe7ff5a79a90d5ed8a08296f8", size = 206988, upload-time = "2025-10-14T04:40:33.79Z" }, - { url = "https://files.pythonhosted.org/packages/94/59/2e87300fe67ab820b5428580a53cad894272dbb97f38a7a814a2a1ac1011/charset_normalizer-3.4.4-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5f819d5fe9234f9f82d75bdfa9aef3a3d72c4d24a6e57aeaebba32a704553aa0", size = 147324, upload-time = "2025-10-14T04:40:34.961Z" }, - { url = "https://files.pythonhosted.org/packages/07/fb/0cf61dc84b2b088391830f6274cb57c82e4da8bbc2efeac8c025edb88772/charset_normalizer-3.4.4-cp311-cp311-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:a59cb51917aa591b1c4e6a43c132f0cdc3c76dbad6155df4e28ee626cc77a0a3", size = 142742, upload-time = "2025-10-14T04:40:36.105Z" }, - { url = "https://files.pythonhosted.org/packages/62/8b/171935adf2312cd745d290ed93cf16cf0dfe320863ab7cbeeae1dcd6535f/charset_normalizer-3.4.4-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:8ef3c867360f88ac904fd3f5e1f902f13307af9052646963ee08ff4f131adafc", size = 160863, upload-time = "2025-10-14T04:40:37.188Z" }, - { url = "https://files.pythonhosted.org/packages/09/73/ad875b192bda14f2173bfc1bc9a55e009808484a4b256748d931b6948442/charset_normalizer-3.4.4-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:d9e45d7faa48ee908174d8fe84854479ef838fc6a705c9315372eacbc2f02897", size = 157837, upload-time = "2025-10-14T04:40:38.435Z" }, - { url = "https://files.pythonhosted.org/packages/6d/fc/de9cce525b2c5b94b47c70a4b4fb19f871b24995c728e957ee68ab1671ea/charset_normalizer-3.4.4-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:840c25fb618a231545cbab0564a799f101b63b9901f2569faecd6b222ac72381", size = 151550, upload-time = "2025-10-14T04:40:40.053Z" }, - { url = "https://files.pythonhosted.org/packages/55/c2/43edd615fdfba8c6f2dfbd459b25a6b3b551f24ea21981e23fb768503ce1/charset_normalizer-3.4.4-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:ca5862d5b3928c4940729dacc329aa9102900382fea192fc5e52eb69d6093815", size = 149162, upload-time = "2025-10-14T04:40:41.163Z" }, - { url = "https://files.pythonhosted.org/packages/03/86/bde4ad8b4d0e9429a4e82c1e8f5c659993a9a863ad62c7df05cf7b678d75/charset_normalizer-3.4.4-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:d9c7f57c3d666a53421049053eaacdd14bbd0a528e2186fcb2e672effd053bb0", size = 150019, upload-time = "2025-10-14T04:40:42.276Z" }, - { url = "https://files.pythonhosted.org/packages/1f/86/a151eb2af293a7e7bac3a739b81072585ce36ccfb4493039f49f1d3cae8c/charset_normalizer-3.4.4-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:277e970e750505ed74c832b4bf75dac7476262ee2a013f5574dd49075879e161", size = 143310, upload-time = "2025-10-14T04:40:43.439Z" }, - { url = "https://files.pythonhosted.org/packages/b5/fe/43dae6144a7e07b87478fdfc4dbe9efd5defb0e7ec29f5f58a55aeef7bf7/charset_normalizer-3.4.4-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:31fd66405eaf47bb62e8cd575dc621c56c668f27d46a61d975a249930dd5e2a4", size = 162022, upload-time = "2025-10-14T04:40:44.547Z" }, - { url = "https://files.pythonhosted.org/packages/80/e6/7aab83774f5d2bca81f42ac58d04caf44f0cc2b65fc6db2b3b2e8a05f3b3/charset_normalizer-3.4.4-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:0d3d8f15c07f86e9ff82319b3d9ef6f4bf907608f53fe9d92b28ea9ae3d1fd89", size = 149383, upload-time = "2025-10-14T04:40:46.018Z" }, - { url = "https://files.pythonhosted.org/packages/4f/e8/b289173b4edae05c0dde07f69f8db476a0b511eac556dfe0d6bda3c43384/charset_normalizer-3.4.4-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:9f7fcd74d410a36883701fafa2482a6af2ff5ba96b9a620e9e0721e28ead5569", size = 159098, upload-time = "2025-10-14T04:40:47.081Z" }, - { url = "https://files.pythonhosted.org/packages/d8/df/fe699727754cae3f8478493c7f45f777b17c3ef0600e28abfec8619eb49c/charset_normalizer-3.4.4-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:ebf3e58c7ec8a8bed6d66a75d7fb37b55e5015b03ceae72a8e7c74495551e224", size = 152991, upload-time = "2025-10-14T04:40:48.246Z" }, - { url = "https://files.pythonhosted.org/packages/1a/86/584869fe4ddb6ffa3bd9f491b87a01568797fb9bd8933f557dba9771beaf/charset_normalizer-3.4.4-cp311-cp311-win32.whl", hash = "sha256:eecbc200c7fd5ddb9a7f16c7decb07b566c29fa2161a16cf67b8d068bd21690a", size = 99456, upload-time = "2025-10-14T04:40:49.376Z" }, - { url = "https://files.pythonhosted.org/packages/65/f6/62fdd5feb60530f50f7e38b4f6a1d5203f4d16ff4f9f0952962c044e919a/charset_normalizer-3.4.4-cp311-cp311-win_amd64.whl", hash = "sha256:5ae497466c7901d54b639cf42d5b8c1b6a4fead55215500d2f486d34db48d016", size = 106978, upload-time = "2025-10-14T04:40:50.844Z" }, - { url = "https://files.pythonhosted.org/packages/7a/9d/0710916e6c82948b3be62d9d398cb4fcf4e97b56d6a6aeccd66c4b2f2bd5/charset_normalizer-3.4.4-cp311-cp311-win_arm64.whl", hash = "sha256:65e2befcd84bc6f37095f5961e68a6f077bf44946771354a28ad434c2cce0ae1", size = 99969, upload-time = "2025-10-14T04:40:52.272Z" }, - { url = "https://files.pythonhosted.org/packages/f3/85/1637cd4af66fa687396e757dec650f28025f2a2f5a5531a3208dc0ec43f2/charset_normalizer-3.4.4-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:0a98e6759f854bd25a58a73fa88833fba3b7c491169f86ce1180c948ab3fd394", size = 208425, upload-time = "2025-10-14T04:40:53.353Z" }, - { url = "https://files.pythonhosted.org/packages/9d/6a/04130023fef2a0d9c62d0bae2649b69f7b7d8d24ea5536feef50551029df/charset_normalizer-3.4.4-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b5b290ccc2a263e8d185130284f8501e3e36c5e02750fc6b6bdeb2e9e96f1e25", size = 148162, upload-time = "2025-10-14T04:40:54.558Z" }, - { url = "https://files.pythonhosted.org/packages/78/29/62328d79aa60da22c9e0b9a66539feae06ca0f5a4171ac4f7dc285b83688/charset_normalizer-3.4.4-cp312-cp312-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:74bb723680f9f7a6234dcf67aea57e708ec1fbdf5699fb91dfd6f511b0a320ef", size = 144558, upload-time = "2025-10-14T04:40:55.677Z" }, - { url = "https://files.pythonhosted.org/packages/86/bb/b32194a4bf15b88403537c2e120b817c61cd4ecffa9b6876e941c3ee38fe/charset_normalizer-3.4.4-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:f1e34719c6ed0b92f418c7c780480b26b5d9c50349e9a9af7d76bf757530350d", size = 161497, upload-time = "2025-10-14T04:40:57.217Z" }, - { url = "https://files.pythonhosted.org/packages/19/89/a54c82b253d5b9b111dc74aca196ba5ccfcca8242d0fb64146d4d3183ff1/charset_normalizer-3.4.4-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:2437418e20515acec67d86e12bf70056a33abdacb5cb1655042f6538d6b085a8", size = 159240, upload-time = "2025-10-14T04:40:58.358Z" }, - { url = "https://files.pythonhosted.org/packages/c0/10/d20b513afe03acc89ec33948320a5544d31f21b05368436d580dec4e234d/charset_normalizer-3.4.4-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:11d694519d7f29d6cd09f6ac70028dba10f92f6cdd059096db198c283794ac86", size = 153471, upload-time = "2025-10-14T04:40:59.468Z" }, - { url = "https://files.pythonhosted.org/packages/61/fa/fbf177b55bdd727010f9c0a3c49eefa1d10f960e5f09d1d887bf93c2e698/charset_normalizer-3.4.4-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:ac1c4a689edcc530fc9d9aa11f5774b9e2f33f9a0c6a57864e90908f5208d30a", size = 150864, upload-time = "2025-10-14T04:41:00.623Z" }, - { url = "https://files.pythonhosted.org/packages/05/12/9fbc6a4d39c0198adeebbde20b619790e9236557ca59fc40e0e3cebe6f40/charset_normalizer-3.4.4-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:21d142cc6c0ec30d2efee5068ca36c128a30b0f2c53c1c07bd78cb6bc1d3be5f", size = 150647, upload-time = "2025-10-14T04:41:01.754Z" }, - { url = "https://files.pythonhosted.org/packages/ad/1f/6a9a593d52e3e8c5d2b167daf8c6b968808efb57ef4c210acb907c365bc4/charset_normalizer-3.4.4-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:5dbe56a36425d26d6cfb40ce79c314a2e4dd6211d51d6d2191c00bed34f354cc", size = 145110, upload-time = "2025-10-14T04:41:03.231Z" }, - { url = "https://files.pythonhosted.org/packages/30/42/9a52c609e72471b0fc54386dc63c3781a387bb4fe61c20231a4ebcd58bdd/charset_normalizer-3.4.4-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:5bfbb1b9acf3334612667b61bd3002196fe2a1eb4dd74d247e0f2a4d50ec9bbf", size = 162839, upload-time = "2025-10-14T04:41:04.715Z" }, - { url = "https://files.pythonhosted.org/packages/c4/5b/c0682bbf9f11597073052628ddd38344a3d673fda35a36773f7d19344b23/charset_normalizer-3.4.4-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:d055ec1e26e441f6187acf818b73564e6e6282709e9bcb5b63f5b23068356a15", size = 150667, upload-time = "2025-10-14T04:41:05.827Z" }, - { url = "https://files.pythonhosted.org/packages/e4/24/a41afeab6f990cf2daf6cb8c67419b63b48cf518e4f56022230840c9bfb2/charset_normalizer-3.4.4-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:af2d8c67d8e573d6de5bc30cdb27e9b95e49115cd9baad5ddbd1a6207aaa82a9", size = 160535, upload-time = "2025-10-14T04:41:06.938Z" }, - { url = "https://files.pythonhosted.org/packages/2a/e5/6a4ce77ed243c4a50a1fecca6aaaab419628c818a49434be428fe24c9957/charset_normalizer-3.4.4-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:780236ac706e66881f3b7f2f32dfe90507a09e67d1d454c762cf642e6e1586e0", size = 154816, upload-time = "2025-10-14T04:41:08.101Z" }, - { url = "https://files.pythonhosted.org/packages/a8/ef/89297262b8092b312d29cdb2517cb1237e51db8ecef2e9af5edbe7b683b1/charset_normalizer-3.4.4-cp312-cp312-win32.whl", hash = "sha256:5833d2c39d8896e4e19b689ffc198f08ea58116bee26dea51e362ecc7cd3ed26", size = 99694, upload-time = "2025-10-14T04:41:09.23Z" }, - { url = "https://files.pythonhosted.org/packages/3d/2d/1e5ed9dd3b3803994c155cd9aacb60c82c331bad84daf75bcb9c91b3295e/charset_normalizer-3.4.4-cp312-cp312-win_amd64.whl", hash = "sha256:a79cfe37875f822425b89a82333404539ae63dbdddf97f84dcbc3d339aae9525", size = 107131, upload-time = "2025-10-14T04:41:10.467Z" }, - { url = "https://files.pythonhosted.org/packages/d0/d9/0ed4c7098a861482a7b6a95603edce4c0d9db2311af23da1fb2b75ec26fc/charset_normalizer-3.4.4-cp312-cp312-win_arm64.whl", hash = "sha256:376bec83a63b8021bb5c8ea75e21c4ccb86e7e45ca4eb81146091b56599b80c3", size = 100390, upload-time = "2025-10-14T04:41:11.915Z" }, - { url = "https://files.pythonhosted.org/packages/97/45/4b3a1239bbacd321068ea6e7ac28875b03ab8bc0aa0966452db17cd36714/charset_normalizer-3.4.4-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:e1f185f86a6f3403aa2420e815904c67b2f9ebc443f045edd0de921108345794", size = 208091, upload-time = "2025-10-14T04:41:13.346Z" }, - { url = "https://files.pythonhosted.org/packages/7d/62/73a6d7450829655a35bb88a88fca7d736f9882a27eacdca2c6d505b57e2e/charset_normalizer-3.4.4-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6b39f987ae8ccdf0d2642338faf2abb1862340facc796048b604ef14919e55ed", size = 147936, upload-time = "2025-10-14T04:41:14.461Z" }, - { url = "https://files.pythonhosted.org/packages/89/c5/adb8c8b3d6625bef6d88b251bbb0d95f8205831b987631ab0c8bb5d937c2/charset_normalizer-3.4.4-cp313-cp313-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:3162d5d8ce1bb98dd51af660f2121c55d0fa541b46dff7bb9b9f86ea1d87de72", size = 144180, upload-time = "2025-10-14T04:41:15.588Z" }, - { url = "https://files.pythonhosted.org/packages/91/ed/9706e4070682d1cc219050b6048bfd293ccf67b3d4f5a4f39207453d4b99/charset_normalizer-3.4.4-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:81d5eb2a312700f4ecaa977a8235b634ce853200e828fbadf3a9c50bab278328", size = 161346, upload-time = "2025-10-14T04:41:16.738Z" }, - { url = "https://files.pythonhosted.org/packages/d5/0d/031f0d95e4972901a2f6f09ef055751805ff541511dc1252ba3ca1f80cf5/charset_normalizer-3.4.4-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:5bd2293095d766545ec1a8f612559f6b40abc0eb18bb2f5d1171872d34036ede", size = 158874, upload-time = "2025-10-14T04:41:17.923Z" }, - { url = "https://files.pythonhosted.org/packages/f5/83/6ab5883f57c9c801ce5e5677242328aa45592be8a00644310a008d04f922/charset_normalizer-3.4.4-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a8a8b89589086a25749f471e6a900d3f662d1d3b6e2e59dcecf787b1cc3a1894", size = 153076, upload-time = "2025-10-14T04:41:19.106Z" }, - { url = "https://files.pythonhosted.org/packages/75/1e/5ff781ddf5260e387d6419959ee89ef13878229732732ee73cdae01800f2/charset_normalizer-3.4.4-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:bc7637e2f80d8530ee4a78e878bce464f70087ce73cf7c1caf142416923b98f1", size = 150601, upload-time = "2025-10-14T04:41:20.245Z" }, - { url = "https://files.pythonhosted.org/packages/d7/57/71be810965493d3510a6ca79b90c19e48696fb1ff964da319334b12677f0/charset_normalizer-3.4.4-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:f8bf04158c6b607d747e93949aa60618b61312fe647a6369f88ce2ff16043490", size = 150376, upload-time = "2025-10-14T04:41:21.398Z" }, - { url = "https://files.pythonhosted.org/packages/e5/d5/c3d057a78c181d007014feb7e9f2e65905a6c4ef182c0ddf0de2924edd65/charset_normalizer-3.4.4-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:554af85e960429cf30784dd47447d5125aaa3b99a6f0683589dbd27e2f45da44", size = 144825, upload-time = "2025-10-14T04:41:22.583Z" }, - { url = "https://files.pythonhosted.org/packages/e6/8c/d0406294828d4976f275ffbe66f00266c4b3136b7506941d87c00cab5272/charset_normalizer-3.4.4-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:74018750915ee7ad843a774364e13a3db91682f26142baddf775342c3f5b1133", size = 162583, upload-time = "2025-10-14T04:41:23.754Z" }, - { url = "https://files.pythonhosted.org/packages/d7/24/e2aa1f18c8f15c4c0e932d9287b8609dd30ad56dbe41d926bd846e22fb8d/charset_normalizer-3.4.4-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:c0463276121fdee9c49b98908b3a89c39be45d86d1dbaa22957e38f6321d4ce3", size = 150366, upload-time = "2025-10-14T04:41:25.27Z" }, - { url = "https://files.pythonhosted.org/packages/e4/5b/1e6160c7739aad1e2df054300cc618b06bf784a7a164b0f238360721ab86/charset_normalizer-3.4.4-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:362d61fd13843997c1c446760ef36f240cf81d3ebf74ac62652aebaf7838561e", size = 160300, upload-time = "2025-10-14T04:41:26.725Z" }, - { url = "https://files.pythonhosted.org/packages/7a/10/f882167cd207fbdd743e55534d5d9620e095089d176d55cb22d5322f2afd/charset_normalizer-3.4.4-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:9a26f18905b8dd5d685d6d07b0cdf98a79f3c7a918906af7cc143ea2e164c8bc", size = 154465, upload-time = "2025-10-14T04:41:28.322Z" }, - { url = "https://files.pythonhosted.org/packages/89/66/c7a9e1b7429be72123441bfdbaf2bc13faab3f90b933f664db506dea5915/charset_normalizer-3.4.4-cp313-cp313-win32.whl", hash = "sha256:9b35f4c90079ff2e2edc5b26c0c77925e5d2d255c42c74fdb70fb49b172726ac", size = 99404, upload-time = "2025-10-14T04:41:29.95Z" }, - { url = "https://files.pythonhosted.org/packages/c4/26/b9924fa27db384bdcd97ab83b4f0a8058d96ad9626ead570674d5e737d90/charset_normalizer-3.4.4-cp313-cp313-win_amd64.whl", hash = "sha256:b435cba5f4f750aa6c0a0d92c541fb79f69a387c91e61f1795227e4ed9cece14", size = 107092, upload-time = "2025-10-14T04:41:31.188Z" }, - { url = "https://files.pythonhosted.org/packages/af/8f/3ed4bfa0c0c72a7ca17f0380cd9e4dd842b09f664e780c13cff1dcf2ef1b/charset_normalizer-3.4.4-cp313-cp313-win_arm64.whl", hash = "sha256:542d2cee80be6f80247095cc36c418f7bddd14f4a6de45af91dfad36d817bba2", size = 100408, upload-time = "2025-10-14T04:41:32.624Z" }, - { url = "https://files.pythonhosted.org/packages/2a/35/7051599bd493e62411d6ede36fd5af83a38f37c4767b92884df7301db25d/charset_normalizer-3.4.4-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:da3326d9e65ef63a817ecbcc0df6e94463713b754fe293eaa03da99befb9a5bd", size = 207746, upload-time = "2025-10-14T04:41:33.773Z" }, - { url = "https://files.pythonhosted.org/packages/10/9a/97c8d48ef10d6cd4fcead2415523221624bf58bcf68a802721a6bc807c8f/charset_normalizer-3.4.4-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8af65f14dc14a79b924524b1e7fffe304517b2bff5a58bf64f30b98bbc5079eb", size = 147889, upload-time = "2025-10-14T04:41:34.897Z" }, - { url = "https://files.pythonhosted.org/packages/10/bf/979224a919a1b606c82bd2c5fa49b5c6d5727aa47b4312bb27b1734f53cd/charset_normalizer-3.4.4-cp314-cp314-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:74664978bb272435107de04e36db5a9735e78232b85b77d45cfb38f758efd33e", size = 143641, upload-time = "2025-10-14T04:41:36.116Z" }, - { url = "https://files.pythonhosted.org/packages/ba/33/0ad65587441fc730dc7bd90e9716b30b4702dc7b617e6ba4997dc8651495/charset_normalizer-3.4.4-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:752944c7ffbfdd10c074dc58ec2d5a8a4cd9493b314d367c14d24c17684ddd14", size = 160779, upload-time = "2025-10-14T04:41:37.229Z" }, - { url = "https://files.pythonhosted.org/packages/67/ed/331d6b249259ee71ddea93f6f2f0a56cfebd46938bde6fcc6f7b9a3d0e09/charset_normalizer-3.4.4-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:d1f13550535ad8cff21b8d757a3257963e951d96e20ec82ab44bc64aeb62a191", size = 159035, upload-time = "2025-10-14T04:41:38.368Z" }, - { url = "https://files.pythonhosted.org/packages/67/ff/f6b948ca32e4f2a4576aa129d8bed61f2e0543bf9f5f2b7fc3758ed005c9/charset_normalizer-3.4.4-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ecaae4149d99b1c9e7b88bb03e3221956f68fd6d50be2ef061b2381b61d20838", size = 152542, upload-time = "2025-10-14T04:41:39.862Z" }, - { url = "https://files.pythonhosted.org/packages/16/85/276033dcbcc369eb176594de22728541a925b2632f9716428c851b149e83/charset_normalizer-3.4.4-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:cb6254dc36b47a990e59e1068afacdcd02958bdcce30bb50cc1700a8b9d624a6", size = 149524, upload-time = "2025-10-14T04:41:41.319Z" }, - { url = "https://files.pythonhosted.org/packages/9e/f2/6a2a1f722b6aba37050e626530a46a68f74e63683947a8acff92569f979a/charset_normalizer-3.4.4-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:c8ae8a0f02f57a6e61203a31428fa1d677cbe50c93622b4149d5c0f319c1d19e", size = 150395, upload-time = "2025-10-14T04:41:42.539Z" }, - { url = "https://files.pythonhosted.org/packages/60/bb/2186cb2f2bbaea6338cad15ce23a67f9b0672929744381e28b0592676824/charset_normalizer-3.4.4-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:47cc91b2f4dd2833fddaedd2893006b0106129d4b94fdb6af1f4ce5a9965577c", size = 143680, upload-time = "2025-10-14T04:41:43.661Z" }, - { url = "https://files.pythonhosted.org/packages/7d/a5/bf6f13b772fbb2a90360eb620d52ed8f796f3c5caee8398c3b2eb7b1c60d/charset_normalizer-3.4.4-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:82004af6c302b5d3ab2cfc4cc5f29db16123b1a8417f2e25f9066f91d4411090", size = 162045, upload-time = "2025-10-14T04:41:44.821Z" }, - { url = "https://files.pythonhosted.org/packages/df/c5/d1be898bf0dc3ef9030c3825e5d3b83f2c528d207d246cbabe245966808d/charset_normalizer-3.4.4-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:2b7d8f6c26245217bd2ad053761201e9f9680f8ce52f0fcd8d0755aeae5b2152", size = 149687, upload-time = "2025-10-14T04:41:46.442Z" }, - { url = "https://files.pythonhosted.org/packages/a5/42/90c1f7b9341eef50c8a1cb3f098ac43b0508413f33affd762855f67a410e/charset_normalizer-3.4.4-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:799a7a5e4fb2d5898c60b640fd4981d6a25f1c11790935a44ce38c54e985f828", size = 160014, upload-time = "2025-10-14T04:41:47.631Z" }, - { url = "https://files.pythonhosted.org/packages/76/be/4d3ee471e8145d12795ab655ece37baed0929462a86e72372fd25859047c/charset_normalizer-3.4.4-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:99ae2cffebb06e6c22bdc25801d7b30f503cc87dbd283479e7b606f70aff57ec", size = 154044, upload-time = "2025-10-14T04:41:48.81Z" }, - { url = "https://files.pythonhosted.org/packages/b0/6f/8f7af07237c34a1defe7defc565a9bc1807762f672c0fde711a4b22bf9c0/charset_normalizer-3.4.4-cp314-cp314-win32.whl", hash = "sha256:f9d332f8c2a2fcbffe1378594431458ddbef721c1769d78e2cbc06280d8155f9", size = 99940, upload-time = "2025-10-14T04:41:49.946Z" }, - { url = "https://files.pythonhosted.org/packages/4b/51/8ade005e5ca5b0d80fb4aff72a3775b325bdc3d27408c8113811a7cbe640/charset_normalizer-3.4.4-cp314-cp314-win_amd64.whl", hash = "sha256:8a6562c3700cce886c5be75ade4a5db4214fda19fede41d9792d100288d8f94c", size = 107104, upload-time = "2025-10-14T04:41:51.051Z" }, - { url = "https://files.pythonhosted.org/packages/da/5f/6b8f83a55bb8278772c5ae54a577f3099025f9ade59d0136ac24a0df4bde/charset_normalizer-3.4.4-cp314-cp314-win_arm64.whl", hash = "sha256:de00632ca48df9daf77a2c65a484531649261ec9f25489917f09e455cb09ddb2", size = 100743, upload-time = "2025-10-14T04:41:52.122Z" }, - { url = "https://files.pythonhosted.org/packages/0a/4c/925909008ed5a988ccbb72dcc897407e5d6d3bd72410d69e051fc0c14647/charset_normalizer-3.4.4-py3-none-any.whl", hash = "sha256:7a32c560861a02ff789ad905a2fe94e3f840803362c84fecf1851cb4cf3dc37f", size = 53402, upload-time = "2025-10-14T04:42:31.76Z" }, +version = "3.4.7" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/e7/a1/67fe25fac3c7642725500a3f6cfe5821ad557c3abb11c9d20d12c7008d3e/charset_normalizer-3.4.7.tar.gz", hash = "sha256:ae89db9e5f98a11a4bf50407d4363e7b09b31e55bc117b4f7d80aab97ba009e5", size = 144271, upload-time = "2026-04-02T09:28:39.342Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/26/08/0f303cb0b529e456bb116f2d50565a482694fbb94340bf56d44677e7ed03/charset_normalizer-3.4.7-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:cdd68a1fb318e290a2077696b7eb7a21a49163c455979c639bf5a5dcdc46617d", size = 315182, upload-time = "2026-04-02T09:25:40.673Z" }, + { url = "https://files.pythonhosted.org/packages/24/47/b192933e94b546f1b1fe4df9cc1f84fcdbf2359f8d1081d46dd029b50207/charset_normalizer-3.4.7-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e17b8d5d6a8c47c85e68ca8379def1303fd360c3e22093a807cd34a71cd082b8", size = 209329, upload-time = "2026-04-02T09:25:42.354Z" }, + { url = "https://files.pythonhosted.org/packages/c2/b4/01fa81c5ca6141024d89a8fc15968002b71da7f825dd14113207113fabbd/charset_normalizer-3.4.7-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:511ef87c8aec0783e08ac18565a16d435372bc1ac25a91e6ac7f5ef2b0bff790", size = 231230, upload-time = "2026-04-02T09:25:44.281Z" }, + { url = "https://files.pythonhosted.org/packages/20/f7/7b991776844dfa058017e600e6e55ff01984a063290ca5622c0b63162f68/charset_normalizer-3.4.7-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:007d05ec7321d12a40227aae9e2bc6dca73f3cb21058999a1df9e193555a9dcc", size = 225890, upload-time = "2026-04-02T09:25:45.475Z" }, + { url = "https://files.pythonhosted.org/packages/20/e7/bed0024a0f4ab0c8a9c64d4445f39b30c99bd1acd228291959e3de664247/charset_normalizer-3.4.7-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:cf29836da5119f3c8a8a70667b0ef5fdca3bb12f80fd06487cfa575b3909b393", size = 216930, upload-time = "2026-04-02T09:25:46.58Z" }, + { url = "https://files.pythonhosted.org/packages/e2/ab/b18f0ab31cdd7b3ddb8bb76c4a414aeb8160c9810fdf1bc62f269a539d87/charset_normalizer-3.4.7-cp310-cp310-manylinux_2_31_armv7l.whl", hash = "sha256:12d8baf840cc7889b37c7c770f478adea7adce3dcb3944d02ec87508e2dcf153", size = 202109, upload-time = "2026-04-02T09:25:48.031Z" }, + { url = "https://files.pythonhosted.org/packages/82/e5/7e9440768a06dfb3075936490cb82dbf0ee20a133bf0dd8551fa096914ec/charset_normalizer-3.4.7-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:d560742f3c0d62afaccf9f41fe485ed69bd7661a241f86a3ef0f0fb8b1a397af", size = 214684, upload-time = "2026-04-02T09:25:49.245Z" }, + { url = "https://files.pythonhosted.org/packages/71/94/8c61d8da9f062fdf457c80acfa25060ec22bf1d34bbeaca4350f13bcfd07/charset_normalizer-3.4.7-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:b14b2d9dac08e28bb8046a1a0434b1750eb221c8f5b87a68f4fa11a6f97b5e34", size = 212785, upload-time = "2026-04-02T09:25:50.671Z" }, + { url = "https://files.pythonhosted.org/packages/66/cd/6e9889c648e72c0ab2e5967528bb83508f354d706637bc7097190c874e13/charset_normalizer-3.4.7-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:bc17a677b21b3502a21f66a8cc64f5bfad4df8a0b8434d661666f8ce90ac3af1", size = 203055, upload-time = "2026-04-02T09:25:51.802Z" }, + { url = "https://files.pythonhosted.org/packages/92/2e/7a951d6a08aefb7eb8e1b54cdfb580b1365afdd9dd484dc4bee9e5d8f258/charset_normalizer-3.4.7-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:750e02e074872a3fad7f233b47734166440af3cdea0add3e95163110816d6752", size = 232502, upload-time = "2026-04-02T09:25:53.388Z" }, + { url = "https://files.pythonhosted.org/packages/58/d5/abcf2d83bf8e0a1286df55cd0dc1d49af0da4282aa77e986df343e7de124/charset_normalizer-3.4.7-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:4e5163c14bffd570ef2affbfdd77bba66383890797df43dc8b4cc7d6f500bf53", size = 214295, upload-time = "2026-04-02T09:25:54.765Z" }, + { url = "https://files.pythonhosted.org/packages/47/3a/7d4cd7ed54be99973a0dc176032cba5cb1f258082c31fa6df35cff46acfc/charset_normalizer-3.4.7-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:6ed74185b2db44f41ef35fd1617c5888e59792da9bbc9190d6c7300617182616", size = 227145, upload-time = "2026-04-02T09:25:55.904Z" }, + { url = "https://files.pythonhosted.org/packages/1d/98/3a45bf8247889cf28262ebd3d0872edff11565b2a1e3064ccb132db3fbb0/charset_normalizer-3.4.7-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:94e1885b270625a9a828c9793b4d52a64445299baa1fea5a173bf1d3dd9a1a5a", size = 218884, upload-time = "2026-04-02T09:25:57.074Z" }, + { url = "https://files.pythonhosted.org/packages/ad/80/2e8b7f8915ed5c9ef13aa828d82738e33888c485b65ebf744d615040c7ea/charset_normalizer-3.4.7-cp310-cp310-win32.whl", hash = "sha256:6785f414ae0f3c733c437e0f3929197934f526d19dfaa75e18fdb4f94c6fb374", size = 148343, upload-time = "2026-04-02T09:25:58.199Z" }, + { url = "https://files.pythonhosted.org/packages/35/1b/3b8c8c77184af465ee9ad88b5aea46ea6b2e1f7b9dc9502891e37af21e30/charset_normalizer-3.4.7-cp310-cp310-win_amd64.whl", hash = "sha256:6696b7688f54f5af4462118f0bfa7c1621eeb87154f77fa04b9295ce7a8f2943", size = 159174, upload-time = "2026-04-02T09:25:59.322Z" }, + { url = "https://files.pythonhosted.org/packages/be/c1/feb40dca40dbb21e0a908801782d9288c64fc8d8e562c2098e9994c8c21b/charset_normalizer-3.4.7-cp310-cp310-win_arm64.whl", hash = "sha256:66671f93accb62ed07da56613636f3641f1a12c13046ce91ffc923721f23c008", size = 147805, upload-time = "2026-04-02T09:26:00.756Z" }, + { url = "https://files.pythonhosted.org/packages/c2/d7/b5b7020a0565c2e9fa8c09f4b5fa6232feb326b8c20081ccded47ea368fd/charset_normalizer-3.4.7-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:7641bb8895e77f921102f72833904dcd9901df5d6d72a2ab8f31d04b7e51e4e7", size = 309705, upload-time = "2026-04-02T09:26:02.191Z" }, + { url = "https://files.pythonhosted.org/packages/5a/53/58c29116c340e5456724ecd2fff4196d236b98f3da97b404bc5e51ac3493/charset_normalizer-3.4.7-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:202389074300232baeb53ae2569a60901f7efadd4245cf3a3bf0617d60b439d7", size = 206419, upload-time = "2026-04-02T09:26:03.583Z" }, + { url = "https://files.pythonhosted.org/packages/b2/02/e8146dc6591a37a00e5144c63f29fb7c97a734ea8a111190783c0e60ab63/charset_normalizer-3.4.7-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:30b8d1d8c52a48c2c5690e152c169b673487a2a58de1ec7393196753063fcd5e", size = 227901, upload-time = "2026-04-02T09:26:04.738Z" }, + { url = "https://files.pythonhosted.org/packages/fb/73/77486c4cd58f1267bf17db420e930c9afa1b3be3fe8c8b8ebbebc9624359/charset_normalizer-3.4.7-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:532bc9bf33a68613fd7d65e4b1c71a6a38d7d42604ecf239c77392e9b4e8998c", size = 222742, upload-time = "2026-04-02T09:26:06.36Z" }, + { url = "https://files.pythonhosted.org/packages/a1/fa/f74eb381a7d94ded44739e9d94de18dc5edc9c17fb8c11f0a6890696c0a9/charset_normalizer-3.4.7-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:2fe249cb4651fd12605b7288b24751d8bfd46d35f12a20b1ba33dea122e690df", size = 214061, upload-time = "2026-04-02T09:26:08.347Z" }, + { url = "https://files.pythonhosted.org/packages/dc/92/42bd3cefcf7687253fb86694b45f37b733c97f59af3724f356fa92b8c344/charset_normalizer-3.4.7-cp311-cp311-manylinux_2_31_armv7l.whl", hash = "sha256:65bcd23054beab4d166035cabbc868a09c1a49d1efe458fe8e4361215df40265", size = 199239, upload-time = "2026-04-02T09:26:09.823Z" }, + { url = "https://files.pythonhosted.org/packages/4c/3d/069e7184e2aa3b3cddc700e3dd267413dc259854adc3380421c805c6a17d/charset_normalizer-3.4.7-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:08e721811161356f97b4059a9ba7bafb23ea5ee2255402c42881c214e173c6b4", size = 210173, upload-time = "2026-04-02T09:26:10.953Z" }, + { url = "https://files.pythonhosted.org/packages/62/51/9d56feb5f2e7074c46f93e0ebdbe61f0848ee246e2f0d89f8e20b89ebb8f/charset_normalizer-3.4.7-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:e060d01aec0a910bdccb8be71faf34e7799ce36950f8294c8bf612cba65a2c9e", size = 209841, upload-time = "2026-04-02T09:26:12.142Z" }, + { url = "https://files.pythonhosted.org/packages/d2/59/893d8f99cc4c837dda1fe2f1139079703deb9f321aabcb032355de13b6c7/charset_normalizer-3.4.7-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:38c0109396c4cfc574d502df99742a45c72c08eff0a36158b6f04000043dbf38", size = 200304, upload-time = "2026-04-02T09:26:13.711Z" }, + { url = "https://files.pythonhosted.org/packages/7d/1d/ee6f3be3464247578d1ed5c46de545ccc3d3ff933695395c402c21fa6b77/charset_normalizer-3.4.7-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:1c2a768fdd44ee4a9339a9b0b130049139b8ce3c01d2ce09f67f5a68048d477c", size = 229455, upload-time = "2026-04-02T09:26:14.941Z" }, + { url = "https://files.pythonhosted.org/packages/54/bb/8fb0a946296ea96a488928bdce8ef99023998c48e4713af533e9bb98ef07/charset_normalizer-3.4.7-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:1a87ca9d5df6fe460483d9a5bbf2b18f620cbed41b432e2bddb686228282d10b", size = 210036, upload-time = "2026-04-02T09:26:16.478Z" }, + { url = "https://files.pythonhosted.org/packages/9a/bc/015b2387f913749f82afd4fcba07846d05b6d784dd16123cb66860e0237d/charset_normalizer-3.4.7-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:d635aab80466bc95771bb78d5370e74d36d1fe31467b6b29b8b57b2a3cd7d22c", size = 224739, upload-time = "2026-04-02T09:26:17.751Z" }, + { url = "https://files.pythonhosted.org/packages/17/ab/63133691f56baae417493cba6b7c641571a2130eb7bceba6773367ab9ec5/charset_normalizer-3.4.7-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:ae196f021b5e7c78e918242d217db021ed2a6ace2bc6ae94c0fc596221c7f58d", size = 216277, upload-time = "2026-04-02T09:26:18.981Z" }, + { url = "https://files.pythonhosted.org/packages/06/6d/3be70e827977f20db77c12a97e6a9f973631a45b8d186c084527e53e77a4/charset_normalizer-3.4.7-cp311-cp311-win32.whl", hash = "sha256:adb2597b428735679446b46c8badf467b4ca5f5056aae4d51a19f9570301b1ad", size = 147819, upload-time = "2026-04-02T09:26:20.295Z" }, + { url = "https://files.pythonhosted.org/packages/20/d9/5f67790f06b735d7c7637171bbfd89882ad67201891b7275e51116ed8207/charset_normalizer-3.4.7-cp311-cp311-win_amd64.whl", hash = "sha256:8e385e4267ab76874ae30db04c627faaaf0b509e1ccc11a95b3fc3e83f855c00", size = 159281, upload-time = "2026-04-02T09:26:21.74Z" }, + { url = "https://files.pythonhosted.org/packages/ca/83/6413f36c5a34afead88ce6f66684d943d91f233d76dd083798f9602b75ae/charset_normalizer-3.4.7-cp311-cp311-win_arm64.whl", hash = "sha256:d4a48e5b3c2a489fae013b7589308a40146ee081f6f509e047e0e096084ceca1", size = 147843, upload-time = "2026-04-02T09:26:22.901Z" }, + { url = "https://files.pythonhosted.org/packages/0c/eb/4fc8d0a7110eb5fc9cc161723a34a8a6c200ce3b4fbf681bc86feee22308/charset_normalizer-3.4.7-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:eca9705049ad3c7345d574e3510665cb2cf844c2f2dcfe675332677f081cbd46", size = 311328, upload-time = "2026-04-02T09:26:24.331Z" }, + { url = "https://files.pythonhosted.org/packages/f8/e3/0fadc706008ac9d7b9b5be6dc767c05f9d3e5df51744ce4cc9605de7b9f4/charset_normalizer-3.4.7-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6178f72c5508bfc5fd446a5905e698c6212932f25bcdd4b47a757a50605a90e2", size = 208061, upload-time = "2026-04-02T09:26:25.568Z" }, + { url = "https://files.pythonhosted.org/packages/42/f0/3dd1045c47f4a4604df85ec18ad093912ae1344ac706993aff91d38773a2/charset_normalizer-3.4.7-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:e1421b502d83040e6d7fb2fb18dff63957f720da3d77b2fbd3187ceb63755d7b", size = 229031, upload-time = "2026-04-02T09:26:26.865Z" }, + { url = "https://files.pythonhosted.org/packages/dc/67/675a46eb016118a2fbde5a277a5d15f4f69d5f3f5f338e5ee2f8948fcf43/charset_normalizer-3.4.7-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:edac0f1ab77644605be2cbba52e6b7f630731fc42b34cb0f634be1a6eface56a", size = 225239, upload-time = "2026-04-02T09:26:28.044Z" }, + { url = "https://files.pythonhosted.org/packages/4b/f8/d0118a2f5f23b02cd166fa385c60f9b0d4f9194f574e2b31cef350ad7223/charset_normalizer-3.4.7-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5649fd1c7bade02f320a462fdefd0b4bd3ce036065836d4f42e0de958038e116", size = 216589, upload-time = "2026-04-02T09:26:29.239Z" }, + { url = "https://files.pythonhosted.org/packages/b1/f1/6d2b0b261b6c4ceef0fcb0d17a01cc5bc53586c2d4796fa04b5c540bc13d/charset_normalizer-3.4.7-cp312-cp312-manylinux_2_31_armv7l.whl", hash = "sha256:203104ed3e428044fd943bc4bf45fa73c0730391f9621e37fe39ecf477b128cb", size = 202733, upload-time = "2026-04-02T09:26:30.5Z" }, + { url = "https://files.pythonhosted.org/packages/6f/c0/7b1f943f7e87cc3db9626ba17807d042c38645f0a1d4415c7a14afb5591f/charset_normalizer-3.4.7-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:298930cec56029e05497a76988377cbd7457ba864beeea92ad7e844fe74cd1f1", size = 212652, upload-time = "2026-04-02T09:26:31.709Z" }, + { url = "https://files.pythonhosted.org/packages/38/dd/5a9ab159fe45c6e72079398f277b7d2b523e7f716acc489726115a910097/charset_normalizer-3.4.7-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:708838739abf24b2ceb208d0e22403dd018faeef86ddac04319a62ae884c4f15", size = 211229, upload-time = "2026-04-02T09:26:33.282Z" }, + { url = "https://files.pythonhosted.org/packages/d5/ff/531a1cad5ca855d1c1a8b69cb71abfd6d85c0291580146fda7c82857caa1/charset_normalizer-3.4.7-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:0f7eb884681e3938906ed0434f20c63046eacd0111c4ba96f27b76084cd679f5", size = 203552, upload-time = "2026-04-02T09:26:34.845Z" }, + { url = "https://files.pythonhosted.org/packages/c1/4c/a5fb52d528a8ca41f7598cb619409ece30a169fbdf9cdce592e53b46c3a6/charset_normalizer-3.4.7-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:4dc1e73c36828f982bfe79fadf5919923f8a6f4df2860804db9a98c48824ce8d", size = 230806, upload-time = "2026-04-02T09:26:36.152Z" }, + { url = "https://files.pythonhosted.org/packages/59/7a/071feed8124111a32b316b33ae4de83d36923039ef8cf48120266844285b/charset_normalizer-3.4.7-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:aed52fea0513bac0ccde438c188c8a471c4e0f457c2dd20cdbf6ea7a450046c7", size = 212316, upload-time = "2026-04-02T09:26:37.672Z" }, + { url = "https://files.pythonhosted.org/packages/fd/35/f7dba3994312d7ba508e041eaac39a36b120f32d4c8662b8814dab876431/charset_normalizer-3.4.7-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:fea24543955a6a729c45a73fe90e08c743f0b3334bbf3201e6c4bc1b0c7fa464", size = 227274, upload-time = "2026-04-02T09:26:38.93Z" }, + { url = "https://files.pythonhosted.org/packages/8a/2d/a572df5c9204ab7688ec1edc895a73ebded3b023bb07364710b05dd1c9be/charset_normalizer-3.4.7-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:bb6d88045545b26da47aa879dd4a89a71d1dce0f0e549b1abcb31dfe4a8eac49", size = 218468, upload-time = "2026-04-02T09:26:40.17Z" }, + { url = "https://files.pythonhosted.org/packages/86/eb/890922a8b03a568ca2f336c36585a4713c55d4d67bf0f0c78924be6315ca/charset_normalizer-3.4.7-cp312-cp312-win32.whl", hash = "sha256:2257141f39fe65a3fdf38aeccae4b953e5f3b3324f4ff0daf9f15b8518666a2c", size = 148460, upload-time = "2026-04-02T09:26:41.416Z" }, + { url = "https://files.pythonhosted.org/packages/35/d9/0e7dffa06c5ab081f75b1b786f0aefc88365825dfcd0ac544bdb7b2b6853/charset_normalizer-3.4.7-cp312-cp312-win_amd64.whl", hash = "sha256:5ed6ab538499c8644b8a3e18debabcd7ce684f3fa91cf867521a7a0279cab2d6", size = 159330, upload-time = "2026-04-02T09:26:42.554Z" }, + { url = "https://files.pythonhosted.org/packages/9e/5d/481bcc2a7c88ea6b0878c299547843b2521ccbc40980cb406267088bc701/charset_normalizer-3.4.7-cp312-cp312-win_arm64.whl", hash = "sha256:56be790f86bfb2c98fb742ce566dfb4816e5a83384616ab59c49e0604d49c51d", size = 147828, upload-time = "2026-04-02T09:26:44.075Z" }, + { url = "https://files.pythonhosted.org/packages/c1/3b/66777e39d3ae1ddc77ee606be4ec6d8cbd4c801f65e5a1b6f2b11b8346dd/charset_normalizer-3.4.7-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:f496c9c3cc02230093d8330875c4c3cdfc3b73612a5fd921c65d39cbcef08063", size = 309627, upload-time = "2026-04-02T09:26:45.198Z" }, + { url = "https://files.pythonhosted.org/packages/2e/4e/b7f84e617b4854ade48a1b7915c8ccfadeba444d2a18c291f696e37f0d3b/charset_normalizer-3.4.7-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0ea948db76d31190bf08bd371623927ee1339d5f2a0b4b1b4a4439a65298703c", size = 207008, upload-time = "2026-04-02T09:26:46.824Z" }, + { url = "https://files.pythonhosted.org/packages/c4/bb/ec73c0257c9e11b268f018f068f5d00aa0ef8c8b09f7753ebd5f2880e248/charset_normalizer-3.4.7-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:a277ab8928b9f299723bc1a2dabb1265911b1a76341f90a510368ca44ad9ab66", size = 228303, upload-time = "2026-04-02T09:26:48.397Z" }, + { url = "https://files.pythonhosted.org/packages/85/fb/32d1f5033484494619f701e719429c69b766bfc4dbc61aa9e9c8c166528b/charset_normalizer-3.4.7-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:3bec022aec2c514d9cf199522a802bd007cd588ab17ab2525f20f9c34d067c18", size = 224282, upload-time = "2026-04-02T09:26:49.684Z" }, + { url = "https://files.pythonhosted.org/packages/fa/07/330e3a0dda4c404d6da83b327270906e9654a24f6c546dc886a0eb0ffb23/charset_normalizer-3.4.7-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e044c39e41b92c845bc815e5ae4230804e8e7bc29e399b0437d64222d92809dd", size = 215595, upload-time = "2026-04-02T09:26:50.915Z" }, + { url = "https://files.pythonhosted.org/packages/e3/7c/fc890655786e423f02556e0216d4b8c6bcb6bdfa890160dc66bf52dee468/charset_normalizer-3.4.7-cp313-cp313-manylinux_2_31_armv7l.whl", hash = "sha256:f495a1652cf3fbab2eb0639776dad966c2fb874d79d87ca07f9d5f059b8bd215", size = 201986, upload-time = "2026-04-02T09:26:52.197Z" }, + { url = "https://files.pythonhosted.org/packages/d8/97/bfb18b3db2aed3b90cf54dc292ad79fdd5ad65c4eae454099475cbeadd0d/charset_normalizer-3.4.7-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:e712b419df8ba5e42b226c510472b37bd57b38e897d3eca5e8cfd410a29fa859", size = 211711, upload-time = "2026-04-02T09:26:53.49Z" }, + { url = "https://files.pythonhosted.org/packages/6f/a5/a581c13798546a7fd557c82614a5c65a13df2157e9ad6373166d2a3e645d/charset_normalizer-3.4.7-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:7804338df6fcc08105c7745f1502ba68d900f45fd770d5bdd5288ddccb8a42d8", size = 210036, upload-time = "2026-04-02T09:26:54.975Z" }, + { url = "https://files.pythonhosted.org/packages/8c/bf/b3ab5bcb478e4193d517644b0fb2bf5497fbceeaa7a1bc0f4d5b50953861/charset_normalizer-3.4.7-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:481551899c856c704d58119b5025793fa6730adda3571971af568f66d2424bb5", size = 202998, upload-time = "2026-04-02T09:26:56.303Z" }, + { url = "https://files.pythonhosted.org/packages/e7/4e/23efd79b65d314fa320ec6017b4b5834d5c12a58ba4610aa353af2e2f577/charset_normalizer-3.4.7-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:f59099f9b66f0d7145115e6f80dd8b1d847176df89b234a5a6b3f00437aa0832", size = 230056, upload-time = "2026-04-02T09:26:57.554Z" }, + { url = "https://files.pythonhosted.org/packages/b9/9f/1e1941bc3f0e01df116e68dc37a55c4d249df5e6fa77f008841aef68264f/charset_normalizer-3.4.7-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:f59ad4c0e8f6bba240a9bb85504faa1ab438237199d4cce5f622761507b8f6a6", size = 211537, upload-time = "2026-04-02T09:26:58.843Z" }, + { url = "https://files.pythonhosted.org/packages/80/0f/088cbb3020d44428964a6c97fe1edfb1b9550396bf6d278330281e8b709c/charset_normalizer-3.4.7-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:3dedcc22d73ec993f42055eff4fcfed9318d1eeb9a6606c55892a26964964e48", size = 226176, upload-time = "2026-04-02T09:27:00.437Z" }, + { url = "https://files.pythonhosted.org/packages/6a/9f/130394f9bbe06f4f63e22641d32fc9b202b7e251c9aef4db044324dac493/charset_normalizer-3.4.7-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:64f02c6841d7d83f832cd97ccf8eb8a906d06eb95d5276069175c696b024b60a", size = 217723, upload-time = "2026-04-02T09:27:02.021Z" }, + { url = "https://files.pythonhosted.org/packages/73/55/c469897448a06e49f8fa03f6caae97074fde823f432a98f979cc42b90e69/charset_normalizer-3.4.7-cp313-cp313-win32.whl", hash = "sha256:4042d5c8f957e15221d423ba781e85d553722fc4113f523f2feb7b188cc34c5e", size = 148085, upload-time = "2026-04-02T09:27:03.192Z" }, + { url = "https://files.pythonhosted.org/packages/5d/78/1b74c5bbb3f99b77a1715c91b3e0b5bdb6fe302d95ace4f5b1bec37b0167/charset_normalizer-3.4.7-cp313-cp313-win_amd64.whl", hash = "sha256:3946fa46a0cf3e4c8cb1cc52f56bb536310d34f25f01ca9b6c16afa767dab110", size = 158819, upload-time = "2026-04-02T09:27:04.454Z" }, + { url = "https://files.pythonhosted.org/packages/68/86/46bd42279d323deb8687c4a5a811fd548cb7d1de10cf6535d099877a9a9f/charset_normalizer-3.4.7-cp313-cp313-win_arm64.whl", hash = "sha256:80d04837f55fc81da168b98de4f4b797ef007fc8a79ab71c6ec9bc4dd662b15b", size = 147915, upload-time = "2026-04-02T09:27:05.971Z" }, + { url = "https://files.pythonhosted.org/packages/97/c8/c67cb8c70e19ef1960b97b22ed2a1567711de46c4ddf19799923adc836c2/charset_normalizer-3.4.7-cp314-cp314-macosx_10_15_universal2.whl", hash = "sha256:c36c333c39be2dbca264d7803333c896ab8fa7d4d6f0ab7edb7dfd7aea6e98c0", size = 309234, upload-time = "2026-04-02T09:27:07.194Z" }, + { url = "https://files.pythonhosted.org/packages/99/85/c091fdee33f20de70d6c8b522743b6f831a2f1cd3ff86de4c6a827c48a76/charset_normalizer-3.4.7-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1c2aed2e5e41f24ea8ef1590b8e848a79b56f3a5564a65ceec43c9d692dc7d8a", size = 208042, upload-time = "2026-04-02T09:27:08.749Z" }, + { url = "https://files.pythonhosted.org/packages/87/1c/ab2ce611b984d2fd5d86a5a8a19c1ae26acac6bad967da4967562c75114d/charset_normalizer-3.4.7-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:54523e136b8948060c0fa0bc7b1b50c32c186f2fceee897a495406bb6e311d2b", size = 228706, upload-time = "2026-04-02T09:27:09.951Z" }, + { url = "https://files.pythonhosted.org/packages/a8/29/2b1d2cb00bf085f59d29eb773ce58ec2d325430f8c216804a0a5cd83cbca/charset_normalizer-3.4.7-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:715479b9a2802ecac752a3b0efa2b0b60285cf962ee38414211abdfccc233b41", size = 224727, upload-time = "2026-04-02T09:27:11.175Z" }, + { url = "https://files.pythonhosted.org/packages/47/5c/032c2d5a07fe4d4855fea851209cca2b6f03ebeb6d4e3afdb3358386a684/charset_normalizer-3.4.7-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:bd6c2a1c7573c64738d716488d2cdd3c00e340e4835707d8fdb8dc1a66ef164e", size = 215882, upload-time = "2026-04-02T09:27:12.446Z" }, + { url = "https://files.pythonhosted.org/packages/2c/c2/356065d5a8b78ed04499cae5f339f091946a6a74f91e03476c33f0ab7100/charset_normalizer-3.4.7-cp314-cp314-manylinux_2_31_armv7l.whl", hash = "sha256:c45e9440fb78f8ddabcf714b68f936737a121355bf59f3907f4e17721b9d1aae", size = 200860, upload-time = "2026-04-02T09:27:13.721Z" }, + { url = "https://files.pythonhosted.org/packages/0c/cd/a32a84217ced5039f53b29f460962abb2d4420def55afabe45b1c3c7483d/charset_normalizer-3.4.7-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:3534e7dcbdcf757da6b85a0bbf5b6868786d5982dd959b065e65481644817a18", size = 211564, upload-time = "2026-04-02T09:27:15.272Z" }, + { url = "https://files.pythonhosted.org/packages/44/86/58e6f13ce26cc3b8f4a36b94a0f22ae2f00a72534520f4ae6857c4b81f89/charset_normalizer-3.4.7-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:e8ac484bf18ce6975760921bb6148041faa8fef0547200386ea0b52b5d27bf7b", size = 211276, upload-time = "2026-04-02T09:27:16.834Z" }, + { url = "https://files.pythonhosted.org/packages/8f/fe/d17c32dc72e17e155e06883efa84514ca375f8a528ba2546bee73fc4df81/charset_normalizer-3.4.7-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:a5fe03b42827c13cdccd08e6c0247b6a6d4b5e3cdc53fd1749f5896adcdc2356", size = 201238, upload-time = "2026-04-02T09:27:18.229Z" }, + { url = "https://files.pythonhosted.org/packages/6a/29/f33daa50b06525a237451cdb6c69da366c381a3dadcd833fa5676bc468b3/charset_normalizer-3.4.7-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:2d6eb928e13016cea4f1f21d1e10c1cebd5a421bc57ddf5b1142ae3f86824fab", size = 230189, upload-time = "2026-04-02T09:27:19.445Z" }, + { url = "https://files.pythonhosted.org/packages/b6/6e/52c84015394a6a0bdcd435210a7e944c5f94ea1055f5cc5d56c5fe368e7b/charset_normalizer-3.4.7-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:e74327fb75de8986940def6e8dee4f127cc9752bee7355bb323cc5b2659b6d46", size = 211352, upload-time = "2026-04-02T09:27:20.79Z" }, + { url = "https://files.pythonhosted.org/packages/8c/d7/4353be581b373033fb9198bf1da3cf8f09c1082561e8e922aa7b39bf9fe8/charset_normalizer-3.4.7-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:d6038d37043bced98a66e68d3aa2b6a35505dc01328cd65217cefe82f25def44", size = 227024, upload-time = "2026-04-02T09:27:22.063Z" }, + { url = "https://files.pythonhosted.org/packages/30/45/99d18aa925bd1740098ccd3060e238e21115fffbfdcb8f3ece837d0ace6c/charset_normalizer-3.4.7-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:7579e913a5339fb8fa133f6bbcfd8e6749696206cf05acdbdca71a1b436d8e72", size = 217869, upload-time = "2026-04-02T09:27:23.486Z" }, + { url = "https://files.pythonhosted.org/packages/5c/05/5ee478aa53f4bb7996482153d4bfe1b89e0f087f0ab6b294fcf92d595873/charset_normalizer-3.4.7-cp314-cp314-win32.whl", hash = "sha256:5b77459df20e08151cd6f8b9ef8ef1f961ef73d85c21a555c7eed5b79410ec10", size = 148541, upload-time = "2026-04-02T09:27:25.146Z" }, + { url = "https://files.pythonhosted.org/packages/48/77/72dcb0921b2ce86420b2d79d454c7022bf5be40202a2a07906b9f2a35c97/charset_normalizer-3.4.7-cp314-cp314-win_amd64.whl", hash = "sha256:92a0a01ead5e668468e952e4238cccd7c537364eb7d851ab144ab6627dbbe12f", size = 159634, upload-time = "2026-04-02T09:27:26.642Z" }, + { url = "https://files.pythonhosted.org/packages/c6/a3/c2369911cd72f02386e4e340770f6e158c7980267da16af8f668217abaa0/charset_normalizer-3.4.7-cp314-cp314-win_arm64.whl", hash = "sha256:67f6279d125ca0046a7fd386d01b311c6363844deac3e5b069b514ba3e63c246", size = 148384, upload-time = "2026-04-02T09:27:28.271Z" }, + { url = "https://files.pythonhosted.org/packages/94/09/7e8a7f73d24dba1f0035fbbf014d2c36828fc1bf9c88f84093e57d315935/charset_normalizer-3.4.7-cp314-cp314t-macosx_10_15_universal2.whl", hash = "sha256:effc3f449787117233702311a1b7d8f59cba9ced946ba727bdc329ec69028e24", size = 330133, upload-time = "2026-04-02T09:27:29.474Z" }, + { url = "https://files.pythonhosted.org/packages/8d/da/96975ddb11f8e977f706f45cddd8540fd8242f71ecdb5d18a80723dcf62c/charset_normalizer-3.4.7-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:fbccdc05410c9ee21bbf16a35f4c1d16123dcdeb8a1d38f33654fa21d0234f79", size = 216257, upload-time = "2026-04-02T09:27:30.793Z" }, + { url = "https://files.pythonhosted.org/packages/e5/e8/1d63bf8ef2d388e95c64b2098f45f84758f6d102a087552da1485912637b/charset_normalizer-3.4.7-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:733784b6d6def852c814bce5f318d25da2ee65dd4839a0718641c696e09a2960", size = 234851, upload-time = "2026-04-02T09:27:32.44Z" }, + { url = "https://files.pythonhosted.org/packages/9b/40/e5ff04233e70da2681fa43969ad6f66ca5611d7e669be0246c4c7aaf6dc8/charset_normalizer-3.4.7-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:a89c23ef8d2c6b27fd200a42aa4ac72786e7c60d40efdc76e6011260b6e949c4", size = 233393, upload-time = "2026-04-02T09:27:34.03Z" }, + { url = "https://files.pythonhosted.org/packages/be/c1/06c6c49d5a5450f76899992f1ee40b41d076aee9279b49cf9974d2f313d5/charset_normalizer-3.4.7-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6c114670c45346afedc0d947faf3c7f701051d2518b943679c8ff88befe14f8e", size = 223251, upload-time = "2026-04-02T09:27:35.369Z" }, + { url = "https://files.pythonhosted.org/packages/2b/9f/f2ff16fb050946169e3e1f82134d107e5d4ae72647ec8a1b1446c148480f/charset_normalizer-3.4.7-cp314-cp314t-manylinux_2_31_armv7l.whl", hash = "sha256:a180c5e59792af262bf263b21a3c49353f25945d8d9f70628e73de370d55e1e1", size = 206609, upload-time = "2026-04-02T09:27:36.661Z" }, + { url = "https://files.pythonhosted.org/packages/69/d5/a527c0cd8d64d2eab7459784fb4169a0ac76e5a6fc5237337982fd61347e/charset_normalizer-3.4.7-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:3c9a494bc5ec77d43cea229c4f6db1e4d8fe7e1bbffa8b6f0f0032430ff8ab44", size = 220014, upload-time = "2026-04-02T09:27:38.019Z" }, + { url = "https://files.pythonhosted.org/packages/7e/80/8a7b8104a3e203074dc9aa2c613d4b726c0e136bad1cc734594b02867972/charset_normalizer-3.4.7-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:8d828b6667a32a728a1ad1d93957cdf37489c57b97ae6c4de2860fa749b8fc1e", size = 218979, upload-time = "2026-04-02T09:27:39.37Z" }, + { url = "https://files.pythonhosted.org/packages/02/9a/b759b503d507f375b2b5c153e4d2ee0a75aa215b7f2489cf314f4541f2c0/charset_normalizer-3.4.7-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:cf1493cd8607bec4d8a7b9b004e699fcf8f9103a9284cc94962cb73d20f9d4a3", size = 209238, upload-time = "2026-04-02T09:27:40.722Z" }, + { url = "https://files.pythonhosted.org/packages/c2/4e/0f3f5d47b86bdb79256e7290b26ac847a2832d9a4033f7eb2cd4bcf4bb5b/charset_normalizer-3.4.7-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:0c96c3b819b5c3e9e165495db84d41914d6894d55181d2d108cc1a69bfc9cce0", size = 236110, upload-time = "2026-04-02T09:27:42.33Z" }, + { url = "https://files.pythonhosted.org/packages/96/23/bce28734eb3ed2c91dcf93abeb8a5cf393a7b2749725030bb630e554fdd8/charset_normalizer-3.4.7-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:752a45dc4a6934060b3b0dab47e04edc3326575f82be64bc4fc293914566503e", size = 219824, upload-time = "2026-04-02T09:27:43.924Z" }, + { url = "https://files.pythonhosted.org/packages/2c/6f/6e897c6984cc4d41af319b077f2f600fc8214eb2fe2d6bcb79141b882400/charset_normalizer-3.4.7-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:8778f0c7a52e56f75d12dae53ae320fae900a8b9b4164b981b9c5ce059cd1fcb", size = 233103, upload-time = "2026-04-02T09:27:45.348Z" }, + { url = "https://files.pythonhosted.org/packages/76/22/ef7bd0fe480a0ae9b656189ec00744b60933f68b4f42a7bb06589f6f576a/charset_normalizer-3.4.7-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:ce3412fbe1e31eb81ea42f4169ed94861c56e643189e1e75f0041f3fe7020abe", size = 225194, upload-time = "2026-04-02T09:27:46.706Z" }, + { url = "https://files.pythonhosted.org/packages/c5/a7/0e0ab3e0b5bc1219bd80a6a0d4d72ca74d9250cb2382b7c699c147e06017/charset_normalizer-3.4.7-cp314-cp314t-win32.whl", hash = "sha256:c03a41a8784091e67a39648f70c5f97b5b6a37f216896d44d2cdcb82615339a0", size = 159827, upload-time = "2026-04-02T09:27:48.053Z" }, + { url = "https://files.pythonhosted.org/packages/7a/1d/29d32e0fb40864b1f878c7f5a0b343ae676c6e2b271a2d55cc3a152391da/charset_normalizer-3.4.7-cp314-cp314t-win_amd64.whl", hash = "sha256:03853ed82eeebbce3c2abfdbc98c96dc205f32a79627688ac9a27370ea61a49c", size = 174168, upload-time = "2026-04-02T09:27:49.795Z" }, + { url = "https://files.pythonhosted.org/packages/de/32/d92444ad05c7a6e41fb2036749777c163baf7a0301a040cb672d6b2b1ae9/charset_normalizer-3.4.7-cp314-cp314t-win_arm64.whl", hash = "sha256:c35abb8bfff0185efac5878da64c45dafd2b37fb0383add1be155a763c1f083d", size = 153018, upload-time = "2026-04-02T09:27:51.116Z" }, + { url = "https://files.pythonhosted.org/packages/db/8f/61959034484a4a7c527811f4721e75d02d653a35afb0b6054474d8185d4c/charset_normalizer-3.4.7-py3-none-any.whl", hash = "sha256:3dce51d0f5e7951f8bb4900c257dad282f49190fdbebecd4ba99bcc41fef404d", size = 61958, upload-time = "2026-04-02T09:28:37.794Z" }, ] [[package]] name = "cibuildwheel" -version = "2.23.3" +version = "2.23.4" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "bashlex" }, @@ -657,21 +672,21 @@ dependencies = [ { name = "tomli", marker = "python_full_version < '3.11'" }, { name = "typing-extensions", marker = "python_full_version < '3.11'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/50/f5/2c06c8229e291e121cb26ed2efa1ba5d89053a93631d8f1d795f2dacabb8/cibuildwheel-2.23.3.tar.gz", hash = "sha256:d85dd15b7eb81711900d8129e67efb32b12f99cc00fc271ab060fa6270c38397", size = 295383, upload-time = "2025-04-26T10:41:28.258Z" } +sdist = { url = "https://files.pythonhosted.org/packages/eb/6c/1934be8118ea842c3ee7542e6e2a0ff9299f632db531f61368b412bb75a7/cibuildwheel-2.23.4.tar.gz", hash = "sha256:5a3e4a3d9c18e77838c37c483642e4f071da06ec05c05336826cc46c97abb708", size = 294641, upload-time = "2026-03-16T19:33:13.649Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/17/8e/127e75e087c0a55903deb447a938e97935c6a56bfd20e6070bcc26c06d1b/cibuildwheel-2.23.3-py3-none-any.whl", hash = "sha256:0fa40073ae23a56d5f995d8405e82c1206049999bb89b92aa0835ee62ab8a891", size = 91792, upload-time = "2025-04-26T10:41:26.148Z" }, + { url = "https://files.pythonhosted.org/packages/66/00/c9e20a77dafae0ff9b02dfca1629950232278dc327d6231d0a0df128d99c/cibuildwheel-2.23.4-py3-none-any.whl", hash = "sha256:2f4300e9709bff0a83fd89d88f418df2c8da69bf40c010aa4a4b80156be3fbd5", size = 91284, upload-time = "2026-03-16T19:33:12.231Z" }, ] [[package]] name = "click" -version = "8.3.0" +version = "8.3.2" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "colorama", marker = "sys_platform == 'win32'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/46/61/de6cd827efad202d7057d93e0fed9294b96952e188f7384832791c7b2254/click-8.3.0.tar.gz", hash = "sha256:e7b8232224eba16f4ebe410c25ced9f7875cb5f3263ffc93cc3e8da705e229c4", size = 276943, upload-time = "2025-09-18T17:32:23.696Z" } +sdist = { url = "https://files.pythonhosted.org/packages/57/75/31212c6bf2503fdf920d87fee5d7a86a2e3bcf444984126f13d8e4016804/click-8.3.2.tar.gz", hash = "sha256:14162b8b3b3550a7d479eafa77dfd3c38d9dc8951f6f69c78913a8f9a7540fd5", size = 302856, upload-time = "2026-04-03T19:14:45.118Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/db/d3/9dcc0f5797f070ec8edf30fbadfb200e71d9db6b84d211e3b2085a7589a0/click-8.3.0-py3-none-any.whl", hash = "sha256:9b9f285302c6e3064f4330c05f05b81945b2a39544279343e6e7c5f27a9baddc", size = 107295, upload-time = "2025-09-18T17:32:22.42Z" }, + { url = "https://files.pythonhosted.org/packages/e4/20/71885d8b97d4f3dde17b1fdb92dbd4908b00541c5a3379787137285f602e/click-8.3.2-py3-none-any.whl", hash = "sha256:1924d2c27c5653561cd2cae4548d1406039cb79b858b747cfea24924bbc1616d", size = 108379, upload-time = "2026-04-03T19:14:43.505Z" }, ] [[package]] @@ -694,11 +709,11 @@ wheels = [ [[package]] name = "configargparse" -version = "1.7.1" +version = "1.7.5" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/85/4d/6c9ef746dfcc2a32e26f3860bb4a011c008c392b83eabdfb598d1a8bbe5d/configargparse-1.7.1.tar.gz", hash = "sha256:79c2ddae836a1e5914b71d58e4b9adbd9f7779d4e6351a637b7d2d9b6c46d3d9", size = 43958, upload-time = "2025-05-23T14:26:17.369Z" } +sdist = { url = "https://files.pythonhosted.org/packages/3f/0b/30328302903c55218ffc5199646d0e9d28348ff26c02ba77b2ffc58d294a/configargparse-1.7.5.tar.gz", hash = "sha256:e3f9a7bb6be34d66b2e3c4a2f58e3045f8dfae47b0dc039f87bcfaa0f193fb0f", size = 53548, upload-time = "2026-03-11T02:19:38.144Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/31/28/d28211d29bcc3620b1fece85a65ce5bb22f18670a03cd28ea4b75ede270c/configargparse-1.7.1-py3-none-any.whl", hash = "sha256:8b586a31f9d873abd1ca527ffbe58863c99f36d896e2829779803125e83be4b6", size = 25607, upload-time = "2025-05-23T14:26:15.923Z" }, + { url = "https://files.pythonhosted.org/packages/fe/19/3ba5e1b0bcc7b91aeab6c258afd70e4907d220fed3972febe38feb40db30/configargparse-1.7.5-py3-none-any.whl", hash = "sha256:1e63fdffedf94da9cd435fc13a1cd24777e76879dd2343912c1f871d4ac8c592", size = 27692, upload-time = "2026-03-11T02:19:36.442Z" }, ] [[package]] @@ -712,101 +727,115 @@ wheels = [ [[package]] name = "coverage" -version = "7.11.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/1c/38/ee22495420457259d2f3390309505ea98f98a5eed40901cf62196abad006/coverage-7.11.0.tar.gz", hash = "sha256:167bd504ac1ca2af7ff3b81d245dfea0292c5032ebef9d66cc08a7d28c1b8050", size = 811905, upload-time = "2025-10-15T15:15:08.542Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/12/95/c49df0aceb5507a80b9fe5172d3d39bf23f05be40c23c8d77d556df96cec/coverage-7.11.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:eb53f1e8adeeb2e78962bade0c08bfdc461853c7969706ed901821e009b35e31", size = 215800, upload-time = "2025-10-15T15:12:19.824Z" }, - { url = "https://files.pythonhosted.org/packages/dc/c6/7bb46ce01ed634fff1d7bb53a54049f539971862cc388b304ff3c51b4f66/coverage-7.11.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:d9a03ec6cb9f40a5c360f138b88266fd8f58408d71e89f536b4f91d85721d075", size = 216198, upload-time = "2025-10-15T15:12:22.549Z" }, - { url = "https://files.pythonhosted.org/packages/94/b2/75d9d8fbf2900268aca5de29cd0a0fe671b0f69ef88be16767cc3c828b85/coverage-7.11.0-cp310-cp310-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:0d7f0616c557cbc3d1c2090334eddcbb70e1ae3a40b07222d62b3aa47f608fab", size = 242953, upload-time = "2025-10-15T15:12:24.139Z" }, - { url = "https://files.pythonhosted.org/packages/65/ac/acaa984c18f440170525a8743eb4b6c960ace2dbad80dc22056a437fc3c6/coverage-7.11.0-cp310-cp310-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:e44a86a47bbdf83b0a3ea4d7df5410d6b1a0de984fbd805fa5101f3624b9abe0", size = 244766, upload-time = "2025-10-15T15:12:25.974Z" }, - { url = "https://files.pythonhosted.org/packages/d8/0d/938d0bff76dfa4a6b228c3fc4b3e1c0e2ad4aa6200c141fcda2bd1170227/coverage-7.11.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:596763d2f9a0ee7eec6e643e29660def2eef297e1de0d334c78c08706f1cb785", size = 246625, upload-time = "2025-10-15T15:12:27.387Z" }, - { url = "https://files.pythonhosted.org/packages/38/54/8f5f5e84bfa268df98f46b2cb396b1009734cfb1e5d6adb663d284893b32/coverage-7.11.0-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:ef55537ff511b5e0a43edb4c50a7bf7ba1c3eea20b4f49b1490f1e8e0e42c591", size = 243568, upload-time = "2025-10-15T15:12:28.799Z" }, - { url = "https://files.pythonhosted.org/packages/68/30/8ba337c2877fe3f2e1af0ed7ff4be0c0c4aca44d6f4007040f3ca2255e99/coverage-7.11.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:9cbabd8f4d0d3dc571d77ae5bdbfa6afe5061e679a9d74b6797c48d143307088", size = 244665, upload-time = "2025-10-15T15:12:30.297Z" }, - { url = "https://files.pythonhosted.org/packages/cc/fb/c6f1d6d9a665536b7dde2333346f0cc41dc6a60bd1ffc10cd5c33e7eb000/coverage-7.11.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:e24045453384e0ae2a587d562df2a04d852672eb63051d16096d3f08aa4c7c2f", size = 242681, upload-time = "2025-10-15T15:12:32.326Z" }, - { url = "https://files.pythonhosted.org/packages/be/38/1b532319af5f991fa153c20373291dc65c2bf532af7dbcffdeef745c8f79/coverage-7.11.0-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:7161edd3426c8d19bdccde7d49e6f27f748f3c31cc350c5de7c633fea445d866", size = 242912, upload-time = "2025-10-15T15:12:34.079Z" }, - { url = "https://files.pythonhosted.org/packages/67/3d/f39331c60ef6050d2a861dc1b514fa78f85f792820b68e8c04196ad733d6/coverage-7.11.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:3d4ed4de17e692ba6415b0587bc7f12bc80915031fc9db46a23ce70fc88c9841", size = 243559, upload-time = "2025-10-15T15:12:35.809Z" }, - { url = "https://files.pythonhosted.org/packages/4b/55/cb7c9df9d0495036ce582a8a2958d50c23cd73f84a23284bc23bd4711a6f/coverage-7.11.0-cp310-cp310-win32.whl", hash = "sha256:765c0bc8fe46f48e341ef737c91c715bd2a53a12792592296a095f0c237e09cf", size = 218266, upload-time = "2025-10-15T15:12:37.429Z" }, - { url = "https://files.pythonhosted.org/packages/68/a8/b79cb275fa7bd0208767f89d57a1b5f6ba830813875738599741b97c2e04/coverage-7.11.0-cp310-cp310-win_amd64.whl", hash = "sha256:24d6f3128f1b2d20d84b24f4074475457faedc3d4613a7e66b5e769939c7d969", size = 219169, upload-time = "2025-10-15T15:12:39.25Z" }, - { url = "https://files.pythonhosted.org/packages/49/3a/ee1074c15c408ddddddb1db7dd904f6b81bc524e01f5a1c5920e13dbde23/coverage-7.11.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:3d58ecaa865c5b9fa56e35efc51d1014d4c0d22838815b9fce57a27dd9576847", size = 215912, upload-time = "2025-10-15T15:12:40.665Z" }, - { url = "https://files.pythonhosted.org/packages/70/c4/9f44bebe5cb15f31608597b037d78799cc5f450044465bcd1ae8cb222fe1/coverage-7.11.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:b679e171f1c104a5668550ada700e3c4937110dbdd153b7ef9055c4f1a1ee3cc", size = 216310, upload-time = "2025-10-15T15:12:42.461Z" }, - { url = "https://files.pythonhosted.org/packages/42/01/5e06077cfef92d8af926bdd86b84fb28bf9bc6ad27343d68be9b501d89f2/coverage-7.11.0-cp311-cp311-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:ca61691ba8c5b6797deb221a0d09d7470364733ea9c69425a640f1f01b7c5bf0", size = 246706, upload-time = "2025-10-15T15:12:44.001Z" }, - { url = "https://files.pythonhosted.org/packages/40/b8/7a3f1f33b35cc4a6c37e759137533119560d06c0cc14753d1a803be0cd4a/coverage-7.11.0-cp311-cp311-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:aef1747ede4bd8ca9cfc04cc3011516500c6891f1b33a94add3253f6f876b7b7", size = 248634, upload-time = "2025-10-15T15:12:45.768Z" }, - { url = "https://files.pythonhosted.org/packages/7a/41/7f987eb33de386bc4c665ab0bf98d15fcf203369d6aacae74f5dd8ec489a/coverage-7.11.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a1839d08406e4cba2953dcc0ffb312252f14d7c4c96919f70167611f4dee2623", size = 250741, upload-time = "2025-10-15T15:12:47.222Z" }, - { url = "https://files.pythonhosted.org/packages/23/c1/a4e0ca6a4e83069fb8216b49b30a7352061ca0cb38654bd2dc96b7b3b7da/coverage-7.11.0-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:e0eb0a2dcc62478eb5b4cbb80b97bdee852d7e280b90e81f11b407d0b81c4287", size = 246837, upload-time = "2025-10-15T15:12:48.904Z" }, - { url = "https://files.pythonhosted.org/packages/5d/03/ced062a17f7c38b4728ff76c3acb40d8465634b20b4833cdb3cc3a74e115/coverage-7.11.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:bc1fbea96343b53f65d5351d8fd3b34fd415a2670d7c300b06d3e14a5af4f552", size = 248429, upload-time = "2025-10-15T15:12:50.73Z" }, - { url = "https://files.pythonhosted.org/packages/97/af/a7c6f194bb8c5a2705ae019036b8fe7f49ea818d638eedb15fdb7bed227c/coverage-7.11.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:214b622259dd0cf435f10241f1333d32caa64dbc27f8790ab693428a141723de", size = 246490, upload-time = "2025-10-15T15:12:52.646Z" }, - { url = "https://files.pythonhosted.org/packages/ab/c3/aab4df02b04a8fde79068c3c41ad7a622b0ef2b12e1ed154da986a727c3f/coverage-7.11.0-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:258d9967520cca899695d4eb7ea38be03f06951d6ca2f21fb48b1235f791e601", size = 246208, upload-time = "2025-10-15T15:12:54.586Z" }, - { url = "https://files.pythonhosted.org/packages/30/d8/e282ec19cd658238d60ed404f99ef2e45eed52e81b866ab1518c0d4163cf/coverage-7.11.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:cf9e6ff4ca908ca15c157c409d608da77a56a09877b97c889b98fb2c32b6465e", size = 247126, upload-time = "2025-10-15T15:12:56.485Z" }, - { url = "https://files.pythonhosted.org/packages/d1/17/a635fa07fac23adb1a5451ec756216768c2767efaed2e4331710342a3399/coverage-7.11.0-cp311-cp311-win32.whl", hash = "sha256:fcc15fc462707b0680cff6242c48625da7f9a16a28a41bb8fd7a4280920e676c", size = 218314, upload-time = "2025-10-15T15:12:58.365Z" }, - { url = "https://files.pythonhosted.org/packages/2a/29/2ac1dfcdd4ab9a70026edc8d715ece9b4be9a1653075c658ee6f271f394d/coverage-7.11.0-cp311-cp311-win_amd64.whl", hash = "sha256:865965bf955d92790f1facd64fe7ff73551bd2c1e7e6b26443934e9701ba30b9", size = 219203, upload-time = "2025-10-15T15:12:59.902Z" }, - { url = "https://files.pythonhosted.org/packages/03/21/5ce8b3a0133179115af4c041abf2ee652395837cb896614beb8ce8ddcfd9/coverage-7.11.0-cp311-cp311-win_arm64.whl", hash = "sha256:5693e57a065760dcbeb292d60cc4d0231a6d4b6b6f6a3191561e1d5e8820b745", size = 217879, upload-time = "2025-10-15T15:13:01.35Z" }, - { url = "https://files.pythonhosted.org/packages/c4/db/86f6906a7c7edc1a52b2c6682d6dd9be775d73c0dfe2b84f8923dfea5784/coverage-7.11.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:9c49e77811cf9d024b95faf86c3f059b11c0c9be0b0d61bc598f453703bd6fd1", size = 216098, upload-time = "2025-10-15T15:13:02.916Z" }, - { url = "https://files.pythonhosted.org/packages/21/54/e7b26157048c7ba555596aad8569ff903d6cd67867d41b75287323678ede/coverage-7.11.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:a61e37a403a778e2cda2a6a39abcc895f1d984071942a41074b5c7ee31642007", size = 216331, upload-time = "2025-10-15T15:13:04.403Z" }, - { url = "https://files.pythonhosted.org/packages/b9/19/1ce6bf444f858b83a733171306134a0544eaddf1ca8851ede6540a55b2ad/coverage-7.11.0-cp312-cp312-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:c79cae102bb3b1801e2ef1511fb50e91ec83a1ce466b2c7c25010d884336de46", size = 247825, upload-time = "2025-10-15T15:13:05.92Z" }, - { url = "https://files.pythonhosted.org/packages/71/0b/d3bcbbc259fcced5fb67c5d78f6e7ee965f49760c14afd931e9e663a83b2/coverage-7.11.0-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:16ce17ceb5d211f320b62df002fa7016b7442ea0fd260c11cec8ce7730954893", size = 250573, upload-time = "2025-10-15T15:13:07.471Z" }, - { url = "https://files.pythonhosted.org/packages/58/8d/b0ff3641a320abb047258d36ed1c21d16be33beed4152628331a1baf3365/coverage-7.11.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:80027673e9d0bd6aef86134b0771845e2da85755cf686e7c7c59566cf5a89115", size = 251706, upload-time = "2025-10-15T15:13:09.4Z" }, - { url = "https://files.pythonhosted.org/packages/59/c8/5a586fe8c7b0458053d9c687f5cff515a74b66c85931f7fe17a1c958b4ac/coverage-7.11.0-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:4d3ffa07a08657306cd2215b0da53761c4d73cb54d9143b9303a6481ec0cd415", size = 248221, upload-time = "2025-10-15T15:13:10.964Z" }, - { url = "https://files.pythonhosted.org/packages/d0/ff/3a25e3132804ba44cfa9a778cdf2b73dbbe63ef4b0945e39602fc896ba52/coverage-7.11.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:a3b6a5f8b2524fd6c1066bc85bfd97e78709bb5e37b5b94911a6506b65f47186", size = 249624, upload-time = "2025-10-15T15:13:12.5Z" }, - { url = "https://files.pythonhosted.org/packages/c5/12/ff10c8ce3895e1b17a73485ea79ebc1896a9e466a9d0f4aef63e0d17b718/coverage-7.11.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:fcc0a4aa589de34bc56e1a80a740ee0f8c47611bdfb28cd1849de60660f3799d", size = 247744, upload-time = "2025-10-15T15:13:14.554Z" }, - { url = "https://files.pythonhosted.org/packages/16/02/d500b91f5471b2975947e0629b8980e5e90786fe316b6d7299852c1d793d/coverage-7.11.0-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:dba82204769d78c3fd31b35c3d5f46e06511936c5019c39f98320e05b08f794d", size = 247325, upload-time = "2025-10-15T15:13:16.438Z" }, - { url = "https://files.pythonhosted.org/packages/77/11/dee0284fbbd9cd64cfce806b827452c6df3f100d9e66188e82dfe771d4af/coverage-7.11.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:81b335f03ba67309a95210caf3eb43bd6fe75a4e22ba653ef97b4696c56c7ec2", size = 249180, upload-time = "2025-10-15T15:13:17.959Z" }, - { url = "https://files.pythonhosted.org/packages/59/1b/cdf1def928f0a150a057cab03286774e73e29c2395f0d30ce3d9e9f8e697/coverage-7.11.0-cp312-cp312-win32.whl", hash = "sha256:037b2d064c2f8cc8716fe4d39cb705779af3fbf1ba318dc96a1af858888c7bb5", size = 218479, upload-time = "2025-10-15T15:13:19.608Z" }, - { url = "https://files.pythonhosted.org/packages/ff/55/e5884d55e031da9c15b94b90a23beccc9d6beee65e9835cd6da0a79e4f3a/coverage-7.11.0-cp312-cp312-win_amd64.whl", hash = "sha256:d66c0104aec3b75e5fd897e7940188ea1892ca1d0235316bf89286d6a22568c0", size = 219290, upload-time = "2025-10-15T15:13:21.593Z" }, - { url = "https://files.pythonhosted.org/packages/23/a8/faa930cfc71c1d16bc78f9a19bb73700464f9c331d9e547bfbc1dbd3a108/coverage-7.11.0-cp312-cp312-win_arm64.whl", hash = "sha256:d91ebeac603812a09cf6a886ba6e464f3bbb367411904ae3790dfe28311b15ad", size = 217924, upload-time = "2025-10-15T15:13:23.39Z" }, - { url = "https://files.pythonhosted.org/packages/60/7f/85e4dfe65e400645464b25c036a26ac226cf3a69d4a50c3934c532491cdd/coverage-7.11.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:cc3f49e65ea6e0d5d9bd60368684fe52a704d46f9e7fc413918f18d046ec40e1", size = 216129, upload-time = "2025-10-15T15:13:25.371Z" }, - { url = "https://files.pythonhosted.org/packages/96/5d/dc5fa98fea3c175caf9d360649cb1aa3715e391ab00dc78c4c66fabd7356/coverage-7.11.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:f39ae2f63f37472c17b4990f794035c9890418b1b8cca75c01193f3c8d3e01be", size = 216380, upload-time = "2025-10-15T15:13:26.976Z" }, - { url = "https://files.pythonhosted.org/packages/b2/f5/3da9cc9596708273385189289c0e4d8197d37a386bdf17619013554b3447/coverage-7.11.0-cp313-cp313-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:7db53b5cdd2917b6eaadd0b1251cf4e7d96f4a8d24e174bdbdf2f65b5ea7994d", size = 247375, upload-time = "2025-10-15T15:13:28.923Z" }, - { url = "https://files.pythonhosted.org/packages/65/6c/f7f59c342359a235559d2bc76b0c73cfc4bac7d61bb0df210965cb1ecffd/coverage-7.11.0-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:10ad04ac3a122048688387828b4537bc9cf60c0bf4869c1e9989c46e45690b82", size = 249978, upload-time = "2025-10-15T15:13:30.525Z" }, - { url = "https://files.pythonhosted.org/packages/e7/8c/042dede2e23525e863bf1ccd2b92689692a148d8b5fd37c37899ba882645/coverage-7.11.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4036cc9c7983a2b1f2556d574d2eb2154ac6ed55114761685657e38782b23f52", size = 251253, upload-time = "2025-10-15T15:13:32.174Z" }, - { url = "https://files.pythonhosted.org/packages/7b/a9/3c58df67bfa809a7bddd786356d9c5283e45d693edb5f3f55d0986dd905a/coverage-7.11.0-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:7ab934dd13b1c5e94b692b1e01bd87e4488cb746e3a50f798cb9464fd128374b", size = 247591, upload-time = "2025-10-15T15:13:34.147Z" }, - { url = "https://files.pythonhosted.org/packages/26/5b/c7f32efd862ee0477a18c41e4761305de6ddd2d49cdeda0c1116227570fd/coverage-7.11.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:59a6e5a265f7cfc05f76e3bb53eca2e0dfe90f05e07e849930fecd6abb8f40b4", size = 249411, upload-time = "2025-10-15T15:13:38.425Z" }, - { url = "https://files.pythonhosted.org/packages/76/b5/78cb4f1e86c1611431c990423ec0768122905b03837e1b4c6a6f388a858b/coverage-7.11.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:df01d6c4c81e15a7c88337b795bb7595a8596e92310266b5072c7e301168efbd", size = 247303, upload-time = "2025-10-15T15:13:40.464Z" }, - { url = "https://files.pythonhosted.org/packages/87/c9/23c753a8641a330f45f221286e707c427e46d0ffd1719b080cedc984ec40/coverage-7.11.0-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:8c934bd088eed6174210942761e38ee81d28c46de0132ebb1801dbe36a390dcc", size = 247157, upload-time = "2025-10-15T15:13:42.087Z" }, - { url = "https://files.pythonhosted.org/packages/c5/42/6e0cc71dc8a464486e944a4fa0d85bdec031cc2969e98ed41532a98336b9/coverage-7.11.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:5a03eaf7ec24078ad64a07f02e30060aaf22b91dedf31a6b24d0d98d2bba7f48", size = 248921, upload-time = "2025-10-15T15:13:43.715Z" }, - { url = "https://files.pythonhosted.org/packages/e8/1c/743c2ef665e6858cccb0f84377dfe3a4c25add51e8c7ef19249be92465b6/coverage-7.11.0-cp313-cp313-win32.whl", hash = "sha256:695340f698a5f56f795b2836abe6fb576e7c53d48cd155ad2f80fd24bc63a040", size = 218526, upload-time = "2025-10-15T15:13:45.336Z" }, - { url = "https://files.pythonhosted.org/packages/ff/d5/226daadfd1bf8ddbccefbd3aa3547d7b960fb48e1bdac124e2dd13a2b71a/coverage-7.11.0-cp313-cp313-win_amd64.whl", hash = "sha256:2727d47fce3ee2bac648528e41455d1b0c46395a087a229deac75e9f88ba5a05", size = 219317, upload-time = "2025-10-15T15:13:47.401Z" }, - { url = "https://files.pythonhosted.org/packages/97/54/47db81dcbe571a48a298f206183ba8a7ba79200a37cd0d9f4788fcd2af4a/coverage-7.11.0-cp313-cp313-win_arm64.whl", hash = "sha256:0efa742f431529699712b92ecdf22de8ff198df41e43aeaaadf69973eb93f17a", size = 217948, upload-time = "2025-10-15T15:13:49.096Z" }, - { url = "https://files.pythonhosted.org/packages/e5/8b/cb68425420154e7e2a82fd779a8cc01549b6fa83c2ad3679cd6c088ebd07/coverage-7.11.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:587c38849b853b157706407e9ebdca8fd12f45869edb56defbef2daa5fb0812b", size = 216837, upload-time = "2025-10-15T15:13:51.09Z" }, - { url = "https://files.pythonhosted.org/packages/33/55/9d61b5765a025685e14659c8d07037247de6383c0385757544ffe4606475/coverage-7.11.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:b971bdefdd75096163dd4261c74be813c4508477e39ff7b92191dea19f24cd37", size = 217061, upload-time = "2025-10-15T15:13:52.747Z" }, - { url = "https://files.pythonhosted.org/packages/52/85/292459c9186d70dcec6538f06ea251bc968046922497377bf4a1dc9a71de/coverage-7.11.0-cp313-cp313t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:269bfe913b7d5be12ab13a95f3a76da23cf147be7fa043933320ba5625f0a8de", size = 258398, upload-time = "2025-10-15T15:13:54.45Z" }, - { url = "https://files.pythonhosted.org/packages/1f/e2/46edd73fb8bf51446c41148d81944c54ed224854812b6ca549be25113ee0/coverage-7.11.0-cp313-cp313t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:dadbcce51a10c07b7c72b0ce4a25e4b6dcb0c0372846afb8e5b6307a121eb99f", size = 260574, upload-time = "2025-10-15T15:13:56.145Z" }, - { url = "https://files.pythonhosted.org/packages/07/5e/1df469a19007ff82e2ca8fe509822820a31e251f80ee7344c34f6cd2ec43/coverage-7.11.0-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:9ed43fa22c6436f7957df036331f8fe4efa7af132054e1844918866cd228af6c", size = 262797, upload-time = "2025-10-15T15:13:58.635Z" }, - { url = "https://files.pythonhosted.org/packages/f9/50/de216b31a1434b94d9b34a964c09943c6be45069ec704bfc379d8d89a649/coverage-7.11.0-cp313-cp313t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:9516add7256b6713ec08359b7b05aeff8850c98d357784c7205b2e60aa2513fa", size = 257361, upload-time = "2025-10-15T15:14:00.409Z" }, - { url = "https://files.pythonhosted.org/packages/82/1e/3f9f8344a48111e152e0fd495b6fff13cc743e771a6050abf1627a7ba918/coverage-7.11.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:eb92e47c92fcbcdc692f428da67db33337fa213756f7adb6a011f7b5a7a20740", size = 260349, upload-time = "2025-10-15T15:14:02.188Z" }, - { url = "https://files.pythonhosted.org/packages/65/9b/3f52741f9e7d82124272f3070bbe316006a7de1bad1093f88d59bfc6c548/coverage-7.11.0-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:d06f4fc7acf3cabd6d74941d53329e06bab00a8fe10e4df2714f0b134bfc64ef", size = 258114, upload-time = "2025-10-15T15:14:03.907Z" }, - { url = "https://files.pythonhosted.org/packages/0b/8b/918f0e15f0365d50d3986bbd3338ca01178717ac5678301f3f547b6619e6/coverage-7.11.0-cp313-cp313t-musllinux_1_2_riscv64.whl", hash = "sha256:6fbcee1a8f056af07ecd344482f711f563a9eb1c2cad192e87df00338ec3cdb0", size = 256723, upload-time = "2025-10-15T15:14:06.324Z" }, - { url = "https://files.pythonhosted.org/packages/44/9e/7776829f82d3cf630878a7965a7d70cc6ca94f22c7d20ec4944f7148cb46/coverage-7.11.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:dbbf012be5f32533a490709ad597ad8a8ff80c582a95adc8d62af664e532f9ca", size = 259238, upload-time = "2025-10-15T15:14:08.002Z" }, - { url = "https://files.pythonhosted.org/packages/9a/b8/49cf253e1e7a3bedb85199b201862dd7ca4859f75b6cf25ffa7298aa0760/coverage-7.11.0-cp313-cp313t-win32.whl", hash = "sha256:cee6291bb4fed184f1c2b663606a115c743df98a537c969c3c64b49989da96c2", size = 219180, upload-time = "2025-10-15T15:14:09.786Z" }, - { url = "https://files.pythonhosted.org/packages/ac/e1/1a541703826be7ae2125a0fb7f821af5729d56bb71e946e7b933cc7a89a4/coverage-7.11.0-cp313-cp313t-win_amd64.whl", hash = "sha256:a386c1061bf98e7ea4758e4313c0ab5ecf57af341ef0f43a0bf26c2477b5c268", size = 220241, upload-time = "2025-10-15T15:14:11.471Z" }, - { url = "https://files.pythonhosted.org/packages/d5/d1/5ee0e0a08621140fd418ec4020f595b4d52d7eb429ae6a0c6542b4ba6f14/coverage-7.11.0-cp313-cp313t-win_arm64.whl", hash = "sha256:f9ea02ef40bb83823b2b04964459d281688fe173e20643870bb5d2edf68bc836", size = 218510, upload-time = "2025-10-15T15:14:13.46Z" }, - { url = "https://files.pythonhosted.org/packages/f4/06/e923830c1985ce808e40a3fa3eb46c13350b3224b7da59757d37b6ce12b8/coverage-7.11.0-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:c770885b28fb399aaf2a65bbd1c12bf6f307ffd112d6a76c5231a94276f0c497", size = 216110, upload-time = "2025-10-15T15:14:15.157Z" }, - { url = "https://files.pythonhosted.org/packages/42/82/cdeed03bfead45203fb651ed756dfb5266028f5f939e7f06efac4041dad5/coverage-7.11.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:a3d0e2087dba64c86a6b254f43e12d264b636a39e88c5cc0a01a7c71bcfdab7e", size = 216395, upload-time = "2025-10-15T15:14:16.863Z" }, - { url = "https://files.pythonhosted.org/packages/fc/ba/e1c80caffc3199aa699813f73ff097bc2df7b31642bdbc7493600a8f1de5/coverage-7.11.0-cp314-cp314-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:73feb83bb41c32811973b8565f3705caf01d928d972b72042b44e97c71fd70d1", size = 247433, upload-time = "2025-10-15T15:14:18.589Z" }, - { url = "https://files.pythonhosted.org/packages/80/c0/5b259b029694ce0a5bbc1548834c7ba3db41d3efd3474489d7efce4ceb18/coverage-7.11.0-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:c6f31f281012235ad08f9a560976cc2fc9c95c17604ff3ab20120fe480169bca", size = 249970, upload-time = "2025-10-15T15:14:20.307Z" }, - { url = "https://files.pythonhosted.org/packages/8c/86/171b2b5e1aac7e2fd9b43f7158b987dbeb95f06d1fbecad54ad8163ae3e8/coverage-7.11.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e9570ad567f880ef675673992222746a124b9595506826b210fbe0ce3f0499cd", size = 251324, upload-time = "2025-10-15T15:14:22.419Z" }, - { url = "https://files.pythonhosted.org/packages/1a/7e/7e10414d343385b92024af3932a27a1caf75c6e27ee88ba211221ff1a145/coverage-7.11.0-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:8badf70446042553a773547a61fecaa734b55dc738cacf20c56ab04b77425e43", size = 247445, upload-time = "2025-10-15T15:14:24.205Z" }, - { url = "https://files.pythonhosted.org/packages/c4/3b/e4f966b21f5be8c4bf86ad75ae94efa0de4c99c7bbb8114476323102e345/coverage-7.11.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:a09c1211959903a479e389685b7feb8a17f59ec5a4ef9afde7650bd5eabc2777", size = 249324, upload-time = "2025-10-15T15:14:26.234Z" }, - { url = "https://files.pythonhosted.org/packages/00/a2/8479325576dfcd909244d0df215f077f47437ab852ab778cfa2f8bf4d954/coverage-7.11.0-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:5ef83b107f50db3f9ae40f69e34b3bd9337456c5a7fe3461c7abf8b75dd666a2", size = 247261, upload-time = "2025-10-15T15:14:28.42Z" }, - { url = "https://files.pythonhosted.org/packages/7b/d8/3a9e2db19d94d65771d0f2e21a9ea587d11b831332a73622f901157cc24b/coverage-7.11.0-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:f91f927a3215b8907e214af77200250bb6aae36eca3f760f89780d13e495388d", size = 247092, upload-time = "2025-10-15T15:14:30.784Z" }, - { url = "https://files.pythonhosted.org/packages/b3/b1/bbca3c472544f9e2ad2d5116b2379732957048be4b93a9c543fcd0207e5f/coverage-7.11.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:cdbcd376716d6b7fbfeedd687a6c4be019c5a5671b35f804ba76a4c0a778cba4", size = 248755, upload-time = "2025-10-15T15:14:32.585Z" }, - { url = "https://files.pythonhosted.org/packages/89/49/638d5a45a6a0f00af53d6b637c87007eb2297042186334e9923a61aa8854/coverage-7.11.0-cp314-cp314-win32.whl", hash = "sha256:bab7ec4bb501743edc63609320aaec8cd9188b396354f482f4de4d40a9d10721", size = 218793, upload-time = "2025-10-15T15:14:34.972Z" }, - { url = "https://files.pythonhosted.org/packages/30/cc/b675a51f2d068adb3cdf3799212c662239b0ca27f4691d1fff81b92ea850/coverage-7.11.0-cp314-cp314-win_amd64.whl", hash = "sha256:3d4ba9a449e9364a936a27322b20d32d8b166553bfe63059bd21527e681e2fad", size = 219587, upload-time = "2025-10-15T15:14:37.047Z" }, - { url = "https://files.pythonhosted.org/packages/93/98/5ac886876026de04f00820e5094fe22166b98dcb8b426bf6827aaf67048c/coverage-7.11.0-cp314-cp314-win_arm64.whl", hash = "sha256:ce37f215223af94ef0f75ac68ea096f9f8e8c8ec7d6e8c346ee45c0d363f0479", size = 218168, upload-time = "2025-10-15T15:14:38.861Z" }, - { url = "https://files.pythonhosted.org/packages/14/d1/b4145d35b3e3ecf4d917e97fc8895bcf027d854879ba401d9ff0f533f997/coverage-7.11.0-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:f413ce6e07e0d0dc9c433228727b619871532674b45165abafe201f200cc215f", size = 216850, upload-time = "2025-10-15T15:14:40.651Z" }, - { url = "https://files.pythonhosted.org/packages/ca/d1/7f645fc2eccd318369a8a9948acc447bb7c1ade2911e31d3c5620544c22b/coverage-7.11.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:05791e528a18f7072bf5998ba772fe29db4da1234c45c2087866b5ba4dea710e", size = 217071, upload-time = "2025-10-15T15:14:42.755Z" }, - { url = "https://files.pythonhosted.org/packages/54/7d/64d124649db2737ceced1dfcbdcb79898d5868d311730f622f8ecae84250/coverage-7.11.0-cp314-cp314t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:cacb29f420cfeb9283b803263c3b9a068924474ff19ca126ba9103e1278dfa44", size = 258570, upload-time = "2025-10-15T15:14:44.542Z" }, - { url = "https://files.pythonhosted.org/packages/6c/3f/6f5922f80dc6f2d8b2c6f974835c43f53eb4257a7797727e6ca5b7b2ec1f/coverage-7.11.0-cp314-cp314t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:314c24e700d7027ae3ab0d95fbf8d53544fca1f20345fd30cd219b737c6e58d3", size = 260738, upload-time = "2025-10-15T15:14:46.436Z" }, - { url = "https://files.pythonhosted.org/packages/0e/5f/9e883523c4647c860b3812b417a2017e361eca5b635ee658387dc11b13c1/coverage-7.11.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:630d0bd7a293ad2fc8b4b94e5758c8b2536fdf36c05f1681270203e463cbfa9b", size = 262994, upload-time = "2025-10-15T15:14:48.3Z" }, - { url = "https://files.pythonhosted.org/packages/07/bb/43b5a8e94c09c8bf51743ffc65c4c841a4ca5d3ed191d0a6919c379a1b83/coverage-7.11.0-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:e89641f5175d65e2dbb44db15fe4ea48fade5d5bbb9868fdc2b4fce22f4a469d", size = 257282, upload-time = "2025-10-15T15:14:50.236Z" }, - { url = "https://files.pythonhosted.org/packages/aa/e5/0ead8af411411330b928733e1d201384b39251a5f043c1612970310e8283/coverage-7.11.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:c9f08ea03114a637dab06cedb2e914da9dc67fa52c6015c018ff43fdde25b9c2", size = 260430, upload-time = "2025-10-15T15:14:52.413Z" }, - { url = "https://files.pythonhosted.org/packages/ae/66/03dd8bb0ba5b971620dcaac145461950f6d8204953e535d2b20c6b65d729/coverage-7.11.0-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:ce9f3bde4e9b031eaf1eb61df95c1401427029ea1bfddb8621c1161dcb0fa02e", size = 258190, upload-time = "2025-10-15T15:14:54.268Z" }, - { url = "https://files.pythonhosted.org/packages/45/ae/28a9cce40bf3174426cb2f7e71ee172d98e7f6446dff936a7ccecee34b14/coverage-7.11.0-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:e4dc07e95495923d6fd4d6c27bf70769425b71c89053083843fd78f378558996", size = 256658, upload-time = "2025-10-15T15:14:56.436Z" }, - { url = "https://files.pythonhosted.org/packages/5c/7c/3a44234a8599513684bfc8684878fd7b126c2760f79712bb78c56f19efc4/coverage-7.11.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:424538266794db2861db4922b05d729ade0940ee69dcf0591ce8f69784db0e11", size = 259342, upload-time = "2025-10-15T15:14:58.538Z" }, - { url = "https://files.pythonhosted.org/packages/e1/e6/0108519cba871af0351725ebdb8660fd7a0fe2ba3850d56d32490c7d9b4b/coverage-7.11.0-cp314-cp314t-win32.whl", hash = "sha256:4c1eeb3fb8eb9e0190bebafd0462936f75717687117339f708f395fe455acc73", size = 219568, upload-time = "2025-10-15T15:15:00.382Z" }, - { url = "https://files.pythonhosted.org/packages/c9/76/44ba876e0942b4e62fdde23ccb029ddb16d19ba1bef081edd00857ba0b16/coverage-7.11.0-cp314-cp314t-win_amd64.whl", hash = "sha256:b56efee146c98dbf2cf5cffc61b9829d1e94442df4d7398b26892a53992d3547", size = 220687, upload-time = "2025-10-15T15:15:02.322Z" }, - { url = "https://files.pythonhosted.org/packages/b9/0c/0df55ecb20d0d0ed5c322e10a441775e1a3a5d78c60f0c4e1abfe6fcf949/coverage-7.11.0-cp314-cp314t-win_arm64.whl", hash = "sha256:b5c2705afa83f49bd91962a4094b6b082f94aef7626365ab3f8f4bd159c5acf3", size = 218711, upload-time = "2025-10-15T15:15:04.575Z" }, - { url = "https://files.pythonhosted.org/packages/5f/04/642c1d8a448ae5ea1369eac8495740a79eb4e581a9fb0cbdce56bbf56da1/coverage-7.11.0-py3-none-any.whl", hash = "sha256:4b7589765348d78fb4e5fb6ea35d07564e387da2fc5efff62e0222971f155f68", size = 207761, upload-time = "2025-10-15T15:15:06.439Z" }, +version = "7.13.5" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/9d/e0/70553e3000e345daff267cec284ce4cbf3fc141b6da229ac52775b5428f1/coverage-7.13.5.tar.gz", hash = "sha256:c81f6515c4c40141f83f502b07bbfa5c240ba25bbe73da7b33f1e5b6120ff179", size = 915967, upload-time = "2026-03-17T10:33:18.341Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/69/33/e8c48488c29a73fd089f9d71f9653c1be7478f2ad6b5bc870db11a55d23d/coverage-7.13.5-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e0723d2c96324561b9aa76fb982406e11d93cdb388a7a7da2b16e04719cf7ca5", size = 219255, upload-time = "2026-03-17T10:29:51.081Z" }, + { url = "https://files.pythonhosted.org/packages/da/bd/b0ebe9f677d7f4b74a3e115eec7ddd4bcf892074963a00d91e8b164a6386/coverage-7.13.5-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:52f444e86475992506b32d4e5ca55c24fc88d73bcbda0e9745095b28ef4dc0cf", size = 219772, upload-time = "2026-03-17T10:29:52.867Z" }, + { url = "https://files.pythonhosted.org/packages/48/cc/5cb9502f4e01972f54eedd48218bb203fe81e294be606a2bc93970208013/coverage-7.13.5-cp310-cp310-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:704de6328e3d612a8f6c07000a878ff38181ec3263d5a11da1db294fa6a9bdf8", size = 246532, upload-time = "2026-03-17T10:29:54.688Z" }, + { url = "https://files.pythonhosted.org/packages/7d/d8/3217636d86c7e7b12e126e4f30ef1581047da73140614523af7495ed5f2d/coverage-7.13.5-cp310-cp310-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:a1a6d79a14e1ec1832cabc833898636ad5f3754a678ef8bb4908515208bf84f4", size = 248333, upload-time = "2026-03-17T10:29:56.221Z" }, + { url = "https://files.pythonhosted.org/packages/2b/30/2002ac6729ba2d4357438e2ed3c447ad8562866c8c63fc16f6dfc33afe56/coverage-7.13.5-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:79060214983769c7ba3f0cee10b54c97609dca4d478fa1aa32b914480fd5738d", size = 250211, upload-time = "2026-03-17T10:29:57.938Z" }, + { url = "https://files.pythonhosted.org/packages/6c/85/552496626d6b9359eb0e2f86f920037c9cbfba09b24d914c6e1528155f7d/coverage-7.13.5-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:356e76b46783a98c2a2fe81ec79df4883a1e62895ea952968fb253c114e7f930", size = 252125, upload-time = "2026-03-17T10:29:59.388Z" }, + { url = "https://files.pythonhosted.org/packages/44/21/40256eabdcbccdb6acf6b381b3016a154399a75fe39d406f790ae84d1f3c/coverage-7.13.5-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:0cef0cdec915d11254a7f549c1170afecce708d30610c6abdded1f74e581666d", size = 247219, upload-time = "2026-03-17T10:30:01.199Z" }, + { url = "https://files.pythonhosted.org/packages/b1/e8/96e2a6c3f21a0ea77d7830b254a1542d0328acc8d7bdf6a284ba7e529f77/coverage-7.13.5-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:dc022073d063b25a402454e5712ef9e007113e3a676b96c5f29b2bda29352f40", size = 248248, upload-time = "2026-03-17T10:30:03.317Z" }, + { url = "https://files.pythonhosted.org/packages/da/ba/8477f549e554827da390ec659f3c38e4b6d95470f4daafc2d8ff94eaa9c2/coverage-7.13.5-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:9b74db26dfea4f4e50d48a4602207cd1e78be33182bc9cbf22da94f332f99878", size = 246254, upload-time = "2026-03-17T10:30:04.832Z" }, + { url = "https://files.pythonhosted.org/packages/55/59/bc22aef0e6aa179d5b1b001e8b3654785e9adf27ef24c93dc4228ebd5d68/coverage-7.13.5-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:ad146744ca4fd09b50c482650e3c1b1f4dfa1d4792e0a04a369c7f23336f0400", size = 250067, upload-time = "2026-03-17T10:30:06.535Z" }, + { url = "https://files.pythonhosted.org/packages/de/1b/c6a023a160806a5137dca53468fd97530d6acad24a22003b1578a9c2e429/coverage-7.13.5-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:c555b48be1853fe3997c11c4bd521cdd9a9612352de01fa4508f16ec341e6fe0", size = 246521, upload-time = "2026-03-17T10:30:08.486Z" }, + { url = "https://files.pythonhosted.org/packages/2d/3f/3532c85a55aa2f899fa17c186f831cfa1aa434d88ff792a709636f64130e/coverage-7.13.5-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:7034b5c56a58ae5e85f23949d52c14aca2cfc6848a31764995b7de88f13a1ea0", size = 247126, upload-time = "2026-03-17T10:30:09.966Z" }, + { url = "https://files.pythonhosted.org/packages/aa/2e/b9d56af4a24ef45dfbcda88e06870cb7d57b2b0bfa3a888d79b4c8debd76/coverage-7.13.5-cp310-cp310-win32.whl", hash = "sha256:eb7fdf1ef130660e7415e0253a01a7d5a88c9c4d158bcf75cbbd922fd65a5b58", size = 221860, upload-time = "2026-03-17T10:30:11.393Z" }, + { url = "https://files.pythonhosted.org/packages/9f/cc/d938417e7a4d7f0433ad4edee8bb2acdc60dc7ac5af19e2a07a048ecbee3/coverage-7.13.5-cp310-cp310-win_amd64.whl", hash = "sha256:3e1bb5f6c78feeb1be3475789b14a0f0a5b47d505bfc7267126ccbd50289999e", size = 222788, upload-time = "2026-03-17T10:30:12.886Z" }, + { url = "https://files.pythonhosted.org/packages/4b/37/d24c8f8220ff07b839b2c043ea4903a33b0f455abe673ae3c03bbdb7f212/coverage-7.13.5-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:66a80c616f80181f4d643b0f9e709d97bcea413ecd9631e1dedc7401c8e6695d", size = 219381, upload-time = "2026-03-17T10:30:14.68Z" }, + { url = "https://files.pythonhosted.org/packages/35/8b/cd129b0ca4afe886a6ce9d183c44d8301acbd4ef248622e7c49a23145605/coverage-7.13.5-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:145ede53ccbafb297c1c9287f788d1bc3efd6c900da23bf6931b09eafc931587", size = 219880, upload-time = "2026-03-17T10:30:16.231Z" }, + { url = "https://files.pythonhosted.org/packages/55/2f/e0e5b237bffdb5d6c530ce87cc1d413a5b7d7dfd60fb067ad6d254c35c76/coverage-7.13.5-cp311-cp311-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:0672854dc733c342fa3e957e0605256d2bf5934feeac328da9e0b5449634a642", size = 250303, upload-time = "2026-03-17T10:30:17.748Z" }, + { url = "https://files.pythonhosted.org/packages/92/be/b1afb692be85b947f3401375851484496134c5554e67e822c35f28bf2fbc/coverage-7.13.5-cp311-cp311-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:ec10e2a42b41c923c2209b846126c6582db5e43a33157e9870ba9fb70dc7854b", size = 252218, upload-time = "2026-03-17T10:30:19.804Z" }, + { url = "https://files.pythonhosted.org/packages/da/69/2f47bb6fa1b8d1e3e5d0c4be8ccb4313c63d742476a619418f85740d597b/coverage-7.13.5-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:be3d4bbad9d4b037791794ddeedd7d64a56f5933a2c1373e18e9e568b9141686", size = 254326, upload-time = "2026-03-17T10:30:21.321Z" }, + { url = "https://files.pythonhosted.org/packages/d5/d0/79db81da58965bd29dabc8f4ad2a2af70611a57cba9d1ec006f072f30a54/coverage-7.13.5-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:4d2afbc5cc54d286bfb54541aa50b64cdb07a718227168c87b9e2fb8f25e1743", size = 256267, upload-time = "2026-03-17T10:30:23.094Z" }, + { url = "https://files.pythonhosted.org/packages/e5/32/d0d7cc8168f91ddab44c0ce4806b969df5f5fdfdbb568eaca2dbc2a04936/coverage-7.13.5-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:3ad050321264c49c2fa67bb599100456fc51d004b82534f379d16445da40fb75", size = 250430, upload-time = "2026-03-17T10:30:25.311Z" }, + { url = "https://files.pythonhosted.org/packages/4d/06/a055311d891ddbe231cd69fdd20ea4be6e3603ffebddf8704b8ca8e10a3c/coverage-7.13.5-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:7300c8a6d13335b29bb76d7651c66af6bd8658517c43499f110ddc6717bfc209", size = 252017, upload-time = "2026-03-17T10:30:27.284Z" }, + { url = "https://files.pythonhosted.org/packages/d6/f6/d0fd2d21e29a657b5f77a2fe7082e1568158340dceb941954f776dce1b7b/coverage-7.13.5-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:eb07647a5738b89baab047f14edd18ded523de60f3b30e75c2acc826f79c839a", size = 250080, upload-time = "2026-03-17T10:30:29.481Z" }, + { url = "https://files.pythonhosted.org/packages/4e/ab/0d7fb2efc2e9a5eb7ddcc6e722f834a69b454b7e6e5888c3a8567ecffb31/coverage-7.13.5-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:9adb6688e3b53adffefd4a52d72cbd8b02602bfb8f74dcd862337182fd4d1a4e", size = 253843, upload-time = "2026-03-17T10:30:31.301Z" }, + { url = "https://files.pythonhosted.org/packages/ba/6f/7467b917bbf5408610178f62a49c0ed4377bb16c1657f689cc61470da8ce/coverage-7.13.5-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:7c8d4bc913dd70b93488d6c496c77f3aff5ea99a07e36a18f865bca55adef8bd", size = 249802, upload-time = "2026-03-17T10:30:33.358Z" }, + { url = "https://files.pythonhosted.org/packages/75/2c/1172fb689df92135f5bfbbd69fc83017a76d24ea2e2f3a1154007e2fb9f8/coverage-7.13.5-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:0e3c426ffc4cd952f54ee9ffbdd10345709ecc78a3ecfd796a57236bfad0b9b8", size = 250707, upload-time = "2026-03-17T10:30:35.2Z" }, + { url = "https://files.pythonhosted.org/packages/67/21/9ac389377380a07884e3b48ba7a620fcd9dbfaf1d40565facdc6b36ec9ef/coverage-7.13.5-cp311-cp311-win32.whl", hash = "sha256:259b69bb83ad9894c4b25be2528139eecba9a82646ebdda2d9db1ba28424a6bf", size = 221880, upload-time = "2026-03-17T10:30:36.775Z" }, + { url = "https://files.pythonhosted.org/packages/af/7f/4cd8a92531253f9d7c1bbecd9fa1b472907fb54446ca768c59b531248dc5/coverage-7.13.5-cp311-cp311-win_amd64.whl", hash = "sha256:258354455f4e86e3e9d0d17571d522e13b4e1e19bf0f8596bcf9476d61e7d8a9", size = 222816, upload-time = "2026-03-17T10:30:38.891Z" }, + { url = "https://files.pythonhosted.org/packages/12/a6/1d3f6155fb0010ca68eba7fe48ca6c9da7385058b77a95848710ecf189b1/coverage-7.13.5-cp311-cp311-win_arm64.whl", hash = "sha256:bff95879c33ec8da99fc9b6fe345ddb5be6414b41d6d1ad1c8f188d26f36e028", size = 221483, upload-time = "2026-03-17T10:30:40.463Z" }, + { url = "https://files.pythonhosted.org/packages/a0/c3/a396306ba7db865bf96fc1fb3b7fd29bcbf3d829df642e77b13555163cd6/coverage-7.13.5-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:460cf0114c5016fa841214ff5564aa4864f11948da9440bc97e21ad1f4ba1e01", size = 219554, upload-time = "2026-03-17T10:30:42.208Z" }, + { url = "https://files.pythonhosted.org/packages/a6/16/a68a19e5384e93f811dccc51034b1fd0b865841c390e3c931dcc4699e035/coverage-7.13.5-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:0e223ce4b4ed47f065bfb123687686512e37629be25cc63728557ae7db261422", size = 219908, upload-time = "2026-03-17T10:30:43.906Z" }, + { url = "https://files.pythonhosted.org/packages/29/72/20b917c6793af3a5ceb7fb9c50033f3ec7865f2911a1416b34a7cfa0813b/coverage-7.13.5-cp312-cp312-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:6e3370441f4513c6252bf042b9c36d22491142385049243253c7e48398a15a9f", size = 251419, upload-time = "2026-03-17T10:30:45.545Z" }, + { url = "https://files.pythonhosted.org/packages/8c/49/cd14b789536ac6a4778c453c6a2338bc0a2fb60c5a5a41b4008328b9acc1/coverage-7.13.5-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:03ccc709a17a1de074fb1d11f217342fb0d2b1582ed544f554fc9fc3f07e95f5", size = 254159, upload-time = "2026-03-17T10:30:47.204Z" }, + { url = "https://files.pythonhosted.org/packages/9d/00/7b0edcfe64e2ed4c0340dac14a52ad0f4c9bd0b8b5e531af7d55b703db7c/coverage-7.13.5-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3f4818d065964db3c1c66dc0fbdac5ac692ecbc875555e13374fdbe7eedb4376", size = 255270, upload-time = "2026-03-17T10:30:48.812Z" }, + { url = "https://files.pythonhosted.org/packages/93/89/7ffc4ba0f5d0a55c1e84ea7cee39c9fc06af7b170513d83fbf3bbefce280/coverage-7.13.5-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:012d5319e66e9d5a218834642d6c35d265515a62f01157a45bcc036ecf947256", size = 257538, upload-time = "2026-03-17T10:30:50.77Z" }, + { url = "https://files.pythonhosted.org/packages/81/bd/73ddf85f93f7e6fa83e77ccecb6162d9415c79007b4bc124008a4995e4a7/coverage-7.13.5-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:8dd02af98971bdb956363e4827d34425cb3df19ee550ef92855b0acb9c7ce51c", size = 251821, upload-time = "2026-03-17T10:30:52.5Z" }, + { url = "https://files.pythonhosted.org/packages/a0/81/278aff4e8dec4926a0bcb9486320752811f543a3ce5b602cc7a29978d073/coverage-7.13.5-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:f08fd75c50a760c7eb068ae823777268daaf16a80b918fa58eea888f8e3919f5", size = 253191, upload-time = "2026-03-17T10:30:54.543Z" }, + { url = "https://files.pythonhosted.org/packages/70/ee/fe1621488e2e0a58d7e94c4800f0d96f79671553488d401a612bebae324b/coverage-7.13.5-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:843ea8643cf967d1ac7e8ecd4bb00c99135adf4816c0c0593fdcc47b597fcf09", size = 251337, upload-time = "2026-03-17T10:30:56.663Z" }, + { url = "https://files.pythonhosted.org/packages/37/a6/f79fb37aa104b562207cc23cb5711ab6793608e246cae1e93f26b2236ed9/coverage-7.13.5-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:9d44d7aa963820b1b971dbecd90bfe5fe8f81cff79787eb6cca15750bd2f79b9", size = 255404, upload-time = "2026-03-17T10:30:58.427Z" }, + { url = "https://files.pythonhosted.org/packages/75/f0/ed15262a58ec81ce457ceb717b7f78752a1713556b19081b76e90896e8d4/coverage-7.13.5-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:7132bed4bd7b836200c591410ae7d97bf7ae8be6fc87d160b2bd881df929e7bf", size = 250903, upload-time = "2026-03-17T10:31:00.093Z" }, + { url = "https://files.pythonhosted.org/packages/0f/e9/9129958f20e7e9d4d56d51d42ccf708d15cac355ff4ac6e736e97a9393d2/coverage-7.13.5-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:a698e363641b98843c517817db75373c83254781426e94ada3197cabbc2c919c", size = 252780, upload-time = "2026-03-17T10:31:01.916Z" }, + { url = "https://files.pythonhosted.org/packages/a4/d7/0ad9b15812d81272db94379fe4c6df8fd17781cc7671fdfa30c76ba5ff7b/coverage-7.13.5-cp312-cp312-win32.whl", hash = "sha256:bdba0a6b8812e8c7df002d908a9a2ea3c36e92611b5708633c50869e6d922fdf", size = 222093, upload-time = "2026-03-17T10:31:03.642Z" }, + { url = "https://files.pythonhosted.org/packages/29/3d/821a9a5799fac2556bcf0bd37a70d1d11fa9e49784b6d22e92e8b2f85f18/coverage-7.13.5-cp312-cp312-win_amd64.whl", hash = "sha256:d2c87e0c473a10bffe991502eac389220533024c8082ec1ce849f4218dded810", size = 222900, upload-time = "2026-03-17T10:31:05.651Z" }, + { url = "https://files.pythonhosted.org/packages/d4/fa/2238c2ad08e35cf4f020ea721f717e09ec3152aea75d191a7faf3ef009a8/coverage-7.13.5-cp312-cp312-win_arm64.whl", hash = "sha256:bf69236a9a81bdca3bff53796237aab096cdbf8d78a66ad61e992d9dac7eb2de", size = 221515, upload-time = "2026-03-17T10:31:07.293Z" }, + { url = "https://files.pythonhosted.org/packages/74/8c/74fedc9663dcf168b0a059d4ea756ecae4da77a489048f94b5f512a8d0b3/coverage-7.13.5-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:5ec4af212df513e399cf11610cc27063f1586419e814755ab362e50a85ea69c1", size = 219576, upload-time = "2026-03-17T10:31:09.045Z" }, + { url = "https://files.pythonhosted.org/packages/0c/c9/44fb661c55062f0818a6ffd2685c67aa30816200d5f2817543717d4b92eb/coverage-7.13.5-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:941617e518602e2d64942c88ec8499f7fbd49d3f6c4327d3a71d43a1973032f3", size = 219942, upload-time = "2026-03-17T10:31:10.708Z" }, + { url = "https://files.pythonhosted.org/packages/5f/13/93419671cee82b780bab7ea96b67c8ef448f5f295f36bf5031154ec9a790/coverage-7.13.5-cp313-cp313-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:da305e9937617ee95c2e39d8ff9f040e0487cbf1ac174f777ed5eddd7a7c1f26", size = 250935, upload-time = "2026-03-17T10:31:12.392Z" }, + { url = "https://files.pythonhosted.org/packages/ac/68/1666e3a4462f8202d836920114fa7a5ee9275d1fa45366d336c551a162dd/coverage-7.13.5-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:78e696e1cc714e57e8b25760b33a8b1026b7048d270140d25dafe1b0a1ee05a3", size = 253541, upload-time = "2026-03-17T10:31:14.247Z" }, + { url = "https://files.pythonhosted.org/packages/4e/5e/3ee3b835647be646dcf3c65a7c6c18f87c27326a858f72ab22c12730773d/coverage-7.13.5-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:02ca0eed225b2ff301c474aeeeae27d26e2537942aa0f87491d3e147e784a82b", size = 254780, upload-time = "2026-03-17T10:31:16.193Z" }, + { url = "https://files.pythonhosted.org/packages/44/b3/cb5bd1a04cfcc49ede6cd8409d80bee17661167686741e041abc7ee1b9a9/coverage-7.13.5-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:04690832cbea4e4663d9149e05dba142546ca05cb1848816760e7f58285c970a", size = 256912, upload-time = "2026-03-17T10:31:17.89Z" }, + { url = "https://files.pythonhosted.org/packages/1b/66/c1dceb7b9714473800b075f5c8a84f4588f887a90eb8645282031676e242/coverage-7.13.5-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:0590e44dd2745c696a778f7bab6aa95256de2cbc8b8cff4f7db8ff09813d6969", size = 251165, upload-time = "2026-03-17T10:31:19.605Z" }, + { url = "https://files.pythonhosted.org/packages/b7/62/5502b73b97aa2e53ea22a39cf8649ff44827bef76d90bf638777daa27a9d/coverage-7.13.5-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:d7cfad2d6d81dd298ab6b89fe72c3b7b05ec7544bdda3b707ddaecff8d25c161", size = 252908, upload-time = "2026-03-17T10:31:21.312Z" }, + { url = "https://files.pythonhosted.org/packages/7d/37/7792c2d69854397ca77a55c4646e5897c467928b0e27f2d235d83b5d08c6/coverage-7.13.5-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:e092b9499de38ae0fbfbc603a74660eb6ff3e869e507b50d85a13b6db9863e15", size = 250873, upload-time = "2026-03-17T10:31:23.565Z" }, + { url = "https://files.pythonhosted.org/packages/a3/23/bc866fb6163be52a8a9e5d708ba0d3b1283c12158cefca0a8bbb6e247a43/coverage-7.13.5-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:48c39bc4a04d983a54a705a6389512883d4a3b9862991b3617d547940e9f52b1", size = 255030, upload-time = "2026-03-17T10:31:25.58Z" }, + { url = "https://files.pythonhosted.org/packages/7d/8b/ef67e1c222ef49860701d346b8bbb70881bef283bd5f6cbba68a39a086c7/coverage-7.13.5-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:2d3807015f138ffea1ed9afeeb8624fd781703f2858b62a8dd8da5a0994c57b6", size = 250694, upload-time = "2026-03-17T10:31:27.316Z" }, + { url = "https://files.pythonhosted.org/packages/46/0d/866d1f74f0acddbb906db212e096dee77a8e2158ca5e6bb44729f9d93298/coverage-7.13.5-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:ee2aa19e03161671ec964004fb74b2257805d9710bf14a5c704558b9d8dbaf17", size = 252469, upload-time = "2026-03-17T10:31:29.472Z" }, + { url = "https://files.pythonhosted.org/packages/7a/f5/be742fec31118f02ce42b21c6af187ad6a344fed546b56ca60caacc6a9a0/coverage-7.13.5-cp313-cp313-win32.whl", hash = "sha256:ce1998c0483007608c8382f4ff50164bfc5bd07a2246dd272aa4043b75e61e85", size = 222112, upload-time = "2026-03-17T10:31:31.526Z" }, + { url = "https://files.pythonhosted.org/packages/66/40/7732d648ab9d069a46e686043241f01206348e2bbf128daea85be4d6414b/coverage-7.13.5-cp313-cp313-win_amd64.whl", hash = "sha256:631efb83f01569670a5e866ceb80fe483e7c159fac6f167e6571522636104a0b", size = 222923, upload-time = "2026-03-17T10:31:33.633Z" }, + { url = "https://files.pythonhosted.org/packages/48/af/fea819c12a095781f6ccd504890aaddaf88b8fab263c4940e82c7b770124/coverage-7.13.5-cp313-cp313-win_arm64.whl", hash = "sha256:f4cd16206ad171cbc2470dbea9103cf9a7607d5fe8c242fdf1edf36174020664", size = 221540, upload-time = "2026-03-17T10:31:35.445Z" }, + { url = "https://files.pythonhosted.org/packages/23/d2/17879af479df7fbbd44bd528a31692a48f6b25055d16482fdf5cdb633805/coverage-7.13.5-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:0428cbef5783ad91fe240f673cc1f76b25e74bbfe1a13115e4aa30d3f538162d", size = 220262, upload-time = "2026-03-17T10:31:37.184Z" }, + { url = "https://files.pythonhosted.org/packages/5b/4c/d20e554f988c8f91d6a02c5118f9abbbf73a8768a3048cb4962230d5743f/coverage-7.13.5-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:e0b216a19534b2427cc201a26c25da4a48633f29a487c61258643e89d28200c0", size = 220617, upload-time = "2026-03-17T10:31:39.245Z" }, + { url = "https://files.pythonhosted.org/packages/29/9c/f9f5277b95184f764b24e7231e166dfdb5780a46d408a2ac665969416d61/coverage-7.13.5-cp313-cp313t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:972a9cd27894afe4bc2b1480107054e062df08e671df7c2f18c205e805ccd806", size = 261912, upload-time = "2026-03-17T10:31:41.324Z" }, + { url = "https://files.pythonhosted.org/packages/d5/f6/7f1ab39393eeb50cfe4747ae8ef0e4fc564b989225aa1152e13a180d74f8/coverage-7.13.5-cp313-cp313t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:4b59148601efcd2bac8c4dbf1f0ad6391693ccf7a74b8205781751637076aee3", size = 263987, upload-time = "2026-03-17T10:31:43.724Z" }, + { url = "https://files.pythonhosted.org/packages/a0/d7/62c084fb489ed9c6fbdf57e006752e7c516ea46fd690e5ed8b8617c7d52e/coverage-7.13.5-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:505d7083c8b0c87a8fa8c07370c285847c1f77739b22e299ad75a6af6c32c5c9", size = 266416, upload-time = "2026-03-17T10:31:45.769Z" }, + { url = "https://files.pythonhosted.org/packages/a9/f6/df63d8660e1a0bff6125947afda112a0502736f470d62ca68b288ea762d8/coverage-7.13.5-cp313-cp313t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:60365289c3741e4db327e7baff2a4aaacf22f788e80fa4683393891b70a89fbd", size = 267558, upload-time = "2026-03-17T10:31:48.293Z" }, + { url = "https://files.pythonhosted.org/packages/5b/02/353ca81d36779bd108f6d384425f7139ac3c58c750dcfaafe5d0bee6436b/coverage-7.13.5-cp313-cp313t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:1b88c69c8ef5d4b6fe7dea66d6636056a0f6a7527c440e890cf9259011f5e606", size = 261163, upload-time = "2026-03-17T10:31:50.125Z" }, + { url = "https://files.pythonhosted.org/packages/2c/16/2e79106d5749bcaf3aee6d309123548e3276517cd7851faa8da213bc61bf/coverage-7.13.5-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:5b13955d31d1633cf9376908089b7cebe7d15ddad7aeaabcbe969a595a97e95e", size = 263981, upload-time = "2026-03-17T10:31:51.961Z" }, + { url = "https://files.pythonhosted.org/packages/29/c7/c29e0c59ffa6942030ae6f50b88ae49988e7e8da06de7ecdbf49c6d4feae/coverage-7.13.5-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:f70c9ab2595c56f81a89620e22899eea8b212a4041bd728ac6f4a28bf5d3ddd0", size = 261604, upload-time = "2026-03-17T10:31:53.872Z" }, + { url = "https://files.pythonhosted.org/packages/40/48/097cdc3db342f34006a308ab41c3a7c11c3f0d84750d340f45d88a782e00/coverage-7.13.5-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:084b84a8c63e8d6fc7e3931b316a9bcafca1458d753c539db82d31ed20091a87", size = 265321, upload-time = "2026-03-17T10:31:55.997Z" }, + { url = "https://files.pythonhosted.org/packages/bb/1f/4994af354689e14fd03a75f8ec85a9a68d94e0188bbdab3fc1516b55e512/coverage-7.13.5-cp313-cp313t-musllinux_1_2_riscv64.whl", hash = "sha256:ad14385487393e386e2ea988b09d62dd42c397662ac2dabc3832d71253eee479", size = 260502, upload-time = "2026-03-17T10:31:58.308Z" }, + { url = "https://files.pythonhosted.org/packages/22/c6/9bb9ef55903e628033560885f5c31aa227e46878118b63ab15dc7ba87797/coverage-7.13.5-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:7f2c47b36fe7709a6e83bfadf4eefb90bd25fbe4014d715224c4316f808e59a2", size = 262688, upload-time = "2026-03-17T10:32:00.141Z" }, + { url = "https://files.pythonhosted.org/packages/14/4f/f5df9007e50b15e53e01edea486814783a7f019893733d9e4d6caad75557/coverage-7.13.5-cp313-cp313t-win32.whl", hash = "sha256:67e9bc5449801fad0e5dff329499fb090ba4c5800b86805c80617b4e29809b2a", size = 222788, upload-time = "2026-03-17T10:32:02.246Z" }, + { url = "https://files.pythonhosted.org/packages/e1/98/aa7fccaa97d0f3192bec013c4e6fd6d294a6ed44b640e6bb61f479e00ed5/coverage-7.13.5-cp313-cp313t-win_amd64.whl", hash = "sha256:da86cdcf10d2519e10cabb8ac2de03da1bcb6e4853790b7fbd48523332e3a819", size = 223851, upload-time = "2026-03-17T10:32:04.416Z" }, + { url = "https://files.pythonhosted.org/packages/3d/8b/e5c469f7352651e5f013198e9e21f97510b23de957dd06a84071683b4b60/coverage-7.13.5-cp313-cp313t-win_arm64.whl", hash = "sha256:0ecf12ecb326fe2c339d93fc131816f3a7367d223db37817208905c89bded911", size = 222104, upload-time = "2026-03-17T10:32:06.65Z" }, + { url = "https://files.pythonhosted.org/packages/8e/77/39703f0d1d4b478bfd30191d3c14f53caf596fac00efb3f8f6ee23646439/coverage-7.13.5-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:fbabfaceaeb587e16f7008f7795cd80d20ec548dc7f94fbb0d4ec2e038ce563f", size = 219621, upload-time = "2026-03-17T10:32:08.589Z" }, + { url = "https://files.pythonhosted.org/packages/e2/3e/51dff36d99ae14639a133d9b164d63e628532e2974d8b1edb99dd1ebc733/coverage-7.13.5-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:9bb2a28101a443669a423b665939381084412b81c3f8c0fcfbac57f4e30b5b8e", size = 219953, upload-time = "2026-03-17T10:32:10.507Z" }, + { url = "https://files.pythonhosted.org/packages/6a/6c/1f1917b01eb647c2f2adc9962bd66c79eb978951cab61bdc1acab3290c07/coverage-7.13.5-cp314-cp314-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:bd3a2fbc1c6cccb3c5106140d87cc6a8715110373ef42b63cf5aea29df8c217a", size = 250992, upload-time = "2026-03-17T10:32:12.41Z" }, + { url = "https://files.pythonhosted.org/packages/22/e5/06b1f88f42a5a99df42ce61208bdec3bddb3d261412874280a19796fc09c/coverage-7.13.5-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:6c36ddb64ed9d7e496028d1d00dfec3e428e0aabf4006583bb1839958d280510", size = 253503, upload-time = "2026-03-17T10:32:14.449Z" }, + { url = "https://files.pythonhosted.org/packages/80/28/2a148a51e5907e504fa7b85490277734e6771d8844ebcc48764a15e28155/coverage-7.13.5-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:380e8e9084d8eb38db3a9176a1a4f3c0082c3806fa0dc882d1d87abc3c789247", size = 254852, upload-time = "2026-03-17T10:32:16.56Z" }, + { url = "https://files.pythonhosted.org/packages/61/77/50e8d3d85cc0b7ebe09f30f151d670e302c7ff4a1bf6243f71dd8b0981fa/coverage-7.13.5-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:e808af52a0513762df4d945ea164a24b37f2f518cbe97e03deaa0ee66139b4d6", size = 257161, upload-time = "2026-03-17T10:32:19.004Z" }, + { url = "https://files.pythonhosted.org/packages/3b/c4/b5fd1d4b7bf8d0e75d997afd3925c59ba629fc8616f1b3aae7605132e256/coverage-7.13.5-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:e301d30dd7e95ae068671d746ba8c34e945a82682e62918e41b2679acd2051a0", size = 251021, upload-time = "2026-03-17T10:32:21.344Z" }, + { url = "https://files.pythonhosted.org/packages/f8/66/6ea21f910e92d69ef0b1c3346ea5922a51bad4446c9126db2ae96ee24c4c/coverage-7.13.5-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:800bc829053c80d240a687ceeb927a94fd108bbdc68dfbe505d0d75ab578a882", size = 252858, upload-time = "2026-03-17T10:32:23.506Z" }, + { url = "https://files.pythonhosted.org/packages/9e/ea/879c83cb5d61aa2a35fb80e72715e92672daef8191b84911a643f533840c/coverage-7.13.5-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:0b67af5492adb31940ee418a5a655c28e48165da5afab8c7fa6fd72a142f8740", size = 250823, upload-time = "2026-03-17T10:32:25.516Z" }, + { url = "https://files.pythonhosted.org/packages/8a/fb/616d95d3adb88b9803b275580bdeee8bd1b69a886d057652521f83d7322f/coverage-7.13.5-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:c9136ff29c3a91e25b1d1552b5308e53a1e0653a23e53b6366d7c2dcbbaf8a16", size = 255099, upload-time = "2026-03-17T10:32:27.944Z" }, + { url = "https://files.pythonhosted.org/packages/1c/93/25e6917c90ec1c9a56b0b26f6cad6408e5f13bb6b35d484a0d75c9cf000d/coverage-7.13.5-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:cff784eef7f0b8f6cb28804fbddcfa99f89efe4cc35fb5627e3ac58f91ed3ac0", size = 250638, upload-time = "2026-03-17T10:32:29.914Z" }, + { url = "https://files.pythonhosted.org/packages/fc/7b/dc1776b0464145a929deed214aef9fb1493f159b59ff3c7eeeedf91eddd0/coverage-7.13.5-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:68a4953be99b17ac3c23b6efbc8a38330d99680c9458927491d18700ef23ded0", size = 252295, upload-time = "2026-03-17T10:32:31.981Z" }, + { url = "https://files.pythonhosted.org/packages/ea/fb/99cbbc56a26e07762a2740713f3c8f9f3f3106e3a3dd8cc4474954bccd34/coverage-7.13.5-cp314-cp314-win32.whl", hash = "sha256:35a31f2b1578185fbe6aa2e74cea1b1d0bbf4c552774247d9160d29b80ed56cc", size = 222360, upload-time = "2026-03-17T10:32:34.233Z" }, + { url = "https://files.pythonhosted.org/packages/8d/b7/4758d4f73fb536347cc5e4ad63662f9d60ba9118cb6785e9616b2ce5d7fa/coverage-7.13.5-cp314-cp314-win_amd64.whl", hash = "sha256:2aa055ae1857258f9e0045be26a6d62bdb47a72448b62d7b55f4820f361a2633", size = 223174, upload-time = "2026-03-17T10:32:36.369Z" }, + { url = "https://files.pythonhosted.org/packages/2c/f2/24d84e1dfe70f8ac9fdf30d338239860d0d1d5da0bda528959d0ebc9da28/coverage-7.13.5-cp314-cp314-win_arm64.whl", hash = "sha256:1b11eef33edeae9d142f9b4358edb76273b3bfd30bc3df9a4f95d0e49caf94e8", size = 221739, upload-time = "2026-03-17T10:32:38.736Z" }, + { url = "https://files.pythonhosted.org/packages/60/5b/4a168591057b3668c2428bff25dd3ebc21b629d666d90bcdfa0217940e84/coverage-7.13.5-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:10a0c37f0b646eaff7cce1874c31d1f1ccb297688d4c747291f4f4c70741cc8b", size = 220351, upload-time = "2026-03-17T10:32:41.196Z" }, + { url = "https://files.pythonhosted.org/packages/f5/21/1fd5c4dbfe4a58b6b99649125635df46decdfd4a784c3cd6d410d303e370/coverage-7.13.5-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:b5db73ba3c41c7008037fa731ad5459fc3944cb7452fc0aa9f822ad3533c583c", size = 220612, upload-time = "2026-03-17T10:32:43.204Z" }, + { url = "https://files.pythonhosted.org/packages/d6/fe/2a924b3055a5e7e4512655a9d4609781b0d62334fa0140c3e742926834e2/coverage-7.13.5-cp314-cp314t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:750db93a81e3e5a9831b534be7b1229df848b2e125a604fe6651e48aa070e5f9", size = 261985, upload-time = "2026-03-17T10:32:45.514Z" }, + { url = "https://files.pythonhosted.org/packages/d7/0d/c8928f2bd518c45990fe1a2ab8db42e914ef9b726c975facc4282578c3eb/coverage-7.13.5-cp314-cp314t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:9ddb4f4a5479f2539644be484da179b653273bca1a323947d48ab107b3ed1f29", size = 264107, upload-time = "2026-03-17T10:32:47.971Z" }, + { url = "https://files.pythonhosted.org/packages/ef/ae/4ae35bbd9a0af9d820362751f0766582833c211224b38665c0f8de3d487f/coverage-7.13.5-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d8a7a2049c14f413163e2bdabd37e41179b1d1ccb10ffc6ccc4b7a718429c607", size = 266513, upload-time = "2026-03-17T10:32:50.1Z" }, + { url = "https://files.pythonhosted.org/packages/9c/20/d326174c55af36f74eac6ae781612d9492f060ce8244b570bb9d50d9d609/coverage-7.13.5-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:e1c85e0b6c05c592ea6d8768a66a254bfb3874b53774b12d4c89c481eb78cb90", size = 267650, upload-time = "2026-03-17T10:32:52.391Z" }, + { url = "https://files.pythonhosted.org/packages/7a/5e/31484d62cbd0eabd3412e30d74386ece4a0837d4f6c3040a653878bfc019/coverage-7.13.5-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:777c4d1eff1b67876139d24288aaf1817f6c03d6bae9c5cc8d27b83bcfe38fe3", size = 261089, upload-time = "2026-03-17T10:32:54.544Z" }, + { url = "https://files.pythonhosted.org/packages/e9/d8/49a72d6de146eebb0b7e48cc0f4bc2c0dd858e3d4790ab2b39a2872b62bd/coverage-7.13.5-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:6697e29b93707167687543480a40f0db8f356e86d9f67ddf2e37e2dfd91a9dab", size = 263982, upload-time = "2026-03-17T10:32:56.803Z" }, + { url = "https://files.pythonhosted.org/packages/06/3b/0351f1bd566e6e4dd39e978efe7958bde1d32f879e85589de147654f57bb/coverage-7.13.5-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:8fdf453a942c3e4d99bd80088141c4c6960bb232c409d9c3558e2dbaa3998562", size = 261579, upload-time = "2026-03-17T10:32:59.466Z" }, + { url = "https://files.pythonhosted.org/packages/5d/ce/796a2a2f4017f554d7810f5c573449b35b1e46788424a548d4d19201b222/coverage-7.13.5-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:32ca0c0114c9834a43f045a87dcebd69d108d8ffb666957ea65aa132f50332e2", size = 265316, upload-time = "2026-03-17T10:33:01.847Z" }, + { url = "https://files.pythonhosted.org/packages/3d/16/d5ae91455541d1a78bc90abf495be600588aff8f6db5c8b0dae739fa39c9/coverage-7.13.5-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:8769751c10f339021e2638cd354e13adeac54004d1941119b2c96fe5276d45ea", size = 260427, upload-time = "2026-03-17T10:33:03.945Z" }, + { url = "https://files.pythonhosted.org/packages/48/11/07f413dba62db21fb3fad5d0de013a50e073cc4e2dc4306e770360f6dfc8/coverage-7.13.5-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:cec2d83125531bd153175354055cdb7a09987af08a9430bd173c937c6d0fba2a", size = 262745, upload-time = "2026-03-17T10:33:06.285Z" }, + { url = "https://files.pythonhosted.org/packages/91/15/d792371332eb4663115becf4bad47e047d16234b1aff687b1b18c58d60ae/coverage-7.13.5-cp314-cp314t-win32.whl", hash = "sha256:0cd9ed7a8b181775459296e402ca4fb27db1279740a24e93b3b41942ebe4b215", size = 223146, upload-time = "2026-03-17T10:33:08.756Z" }, + { url = "https://files.pythonhosted.org/packages/db/51/37221f59a111dca5e85be7dbf09696323b5b9f13ff65e0641d535ed06ea8/coverage-7.13.5-cp314-cp314t-win_amd64.whl", hash = "sha256:301e3b7dfefecaca37c9f1aa6f0049b7d4ab8dd933742b607765d757aca77d43", size = 224254, upload-time = "2026-03-17T10:33:11.174Z" }, + { url = "https://files.pythonhosted.org/packages/54/83/6acacc889de8987441aa7d5adfbdbf33d288dad28704a67e574f1df9bcbb/coverage-7.13.5-cp314-cp314t-win_arm64.whl", hash = "sha256:9dacc2ad679b292709e0f5fc1ac74a6d4d5562e424058962c7bb0c658ad25e45", size = 222276, upload-time = "2026-03-17T10:33:13.466Z" }, + { url = "https://files.pythonhosted.org/packages/9e/ee/a4cf96b8ce1e566ed238f0659ac2d3f007ed1d14b181bcb684e19561a69a/coverage-7.13.5-py3-none-any.whl", hash = "sha256:34b02417cf070e173989b3db962f7ed56d2f644307b2cf9d5a0f258e13084a61", size = 211346, upload-time = "2026-03-17T10:33:15.691Z" }, ] [package.optional-dependencies] @@ -816,67 +845,62 @@ toml = [ [[package]] name = "cryptography" -version = "46.0.2" +version = "46.0.6" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "cffi", marker = "platform_python_implementation != 'PyPy'" }, { name = "typing-extensions", marker = "python_full_version < '3.11'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/4a/9b/e301418629f7bfdf72db9e80ad6ed9d1b83c487c471803eaa6464c511a01/cryptography-46.0.2.tar.gz", hash = "sha256:21b6fc8c71a3f9a604f028a329e5560009cc4a3a828bfea5fcba8eb7647d88fe", size = 749293, upload-time = "2025-10-01T00:29:11.856Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/e0/98/7a8df8c19a335c8028414738490fc3955c0cecbfdd37fcc1b9c3d04bd561/cryptography-46.0.2-cp311-abi3-macosx_10_9_universal2.whl", hash = "sha256:f3e32ab7dd1b1ef67b9232c4cf5e2ee4cd517d4316ea910acaaa9c5712a1c663", size = 7261255, upload-time = "2025-10-01T00:27:22.947Z" }, - { url = "https://files.pythonhosted.org/packages/c6/38/b2adb2aa1baa6706adc3eb746691edd6f90a656a9a65c3509e274d15a2b8/cryptography-46.0.2-cp311-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:1fd1a69086926b623ef8126b4c33d5399ce9e2f3fac07c9c734c2a4ec38b6d02", size = 4297596, upload-time = "2025-10-01T00:27:25.258Z" }, - { url = "https://files.pythonhosted.org/packages/e4/27/0f190ada240003119488ae66c897b5e97149292988f556aef4a6a2a57595/cryptography-46.0.2-cp311-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:bb7fb9cd44c2582aa5990cf61a4183e6f54eea3172e54963787ba47287edd135", size = 4450899, upload-time = "2025-10-01T00:27:27.458Z" }, - { url = "https://files.pythonhosted.org/packages/85/d5/e4744105ab02fdf6bb58ba9a816e23b7a633255987310b4187d6745533db/cryptography-46.0.2-cp311-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:9066cfd7f146f291869a9898b01df1c9b0e314bfa182cef432043f13fc462c92", size = 4300382, upload-time = "2025-10-01T00:27:29.091Z" }, - { url = "https://files.pythonhosted.org/packages/33/fb/bf9571065c18c04818cb07de90c43fc042c7977c68e5de6876049559c72f/cryptography-46.0.2-cp311-abi3-manylinux_2_28_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:97e83bf4f2f2c084d8dd792d13841d0a9b241643151686010866bbd076b19659", size = 4017347, upload-time = "2025-10-01T00:27:30.767Z" }, - { url = "https://files.pythonhosted.org/packages/35/72/fc51856b9b16155ca071080e1a3ad0c3a8e86616daf7eb018d9565b99baa/cryptography-46.0.2-cp311-abi3-manylinux_2_28_ppc64le.whl", hash = "sha256:4a766d2a5d8127364fd936572c6e6757682fc5dfcbdba1632d4554943199f2fa", size = 4983500, upload-time = "2025-10-01T00:27:32.741Z" }, - { url = "https://files.pythonhosted.org/packages/c1/53/0f51e926799025e31746d454ab2e36f8c3f0d41592bc65cb9840368d3275/cryptography-46.0.2-cp311-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:fab8f805e9675e61ed8538f192aad70500fa6afb33a8803932999b1049363a08", size = 4482591, upload-time = "2025-10-01T00:27:34.869Z" }, - { url = "https://files.pythonhosted.org/packages/86/96/4302af40b23ab8aa360862251fb8fc450b2a06ff24bc5e261c2007f27014/cryptography-46.0.2-cp311-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:1e3b6428a3d56043bff0bb85b41c535734204e599c1c0977e1d0f261b02f3ad5", size = 4300019, upload-time = "2025-10-01T00:27:37.029Z" }, - { url = "https://files.pythonhosted.org/packages/9b/59/0be12c7fcc4c5e34fe2b665a75bc20958473047a30d095a7657c218fa9e8/cryptography-46.0.2-cp311-abi3-manylinux_2_34_ppc64le.whl", hash = "sha256:1a88634851d9b8de8bb53726f4300ab191d3b2f42595e2581a54b26aba71b7cc", size = 4950006, upload-time = "2025-10-01T00:27:40.272Z" }, - { url = "https://files.pythonhosted.org/packages/55/1d/42fda47b0111834b49e31590ae14fd020594d5e4dadd639bce89ad790fba/cryptography-46.0.2-cp311-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:be939b99d4e091eec9a2bcf41aaf8f351f312cd19ff74b5c83480f08a8a43e0b", size = 4482088, upload-time = "2025-10-01T00:27:42.668Z" }, - { url = "https://files.pythonhosted.org/packages/17/50/60f583f69aa1602c2bdc7022dae86a0d2b837276182f8c1ec825feb9b874/cryptography-46.0.2-cp311-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:9f13b040649bc18e7eb37936009b24fd31ca095a5c647be8bb6aaf1761142bd1", size = 4425599, upload-time = "2025-10-01T00:27:44.616Z" }, - { url = "https://files.pythonhosted.org/packages/d1/57/d8d4134cd27e6e94cf44adb3f3489f935bde85f3a5508e1b5b43095b917d/cryptography-46.0.2-cp311-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:9bdc25e4e01b261a8fda4e98618f1c9515febcecebc9566ddf4a70c63967043b", size = 4697458, upload-time = "2025-10-01T00:27:46.209Z" }, - { url = "https://files.pythonhosted.org/packages/d1/2b/531e37408573e1da33adfb4c58875013ee8ac7d548d1548967d94a0ae5c4/cryptography-46.0.2-cp311-abi3-win32.whl", hash = "sha256:8b9bf67b11ef9e28f4d78ff88b04ed0929fcd0e4f70bb0f704cfc32a5c6311ee", size = 3056077, upload-time = "2025-10-01T00:27:48.424Z" }, - { url = "https://files.pythonhosted.org/packages/a8/cd/2f83cafd47ed2dc5a3a9c783ff5d764e9e70d3a160e0df9a9dcd639414ce/cryptography-46.0.2-cp311-abi3-win_amd64.whl", hash = "sha256:758cfc7f4c38c5c5274b55a57ef1910107436f4ae842478c4989abbd24bd5acb", size = 3512585, upload-time = "2025-10-01T00:27:50.521Z" }, - { url = "https://files.pythonhosted.org/packages/00/36/676f94e10bfaa5c5b86c469ff46d3e0663c5dc89542f7afbadac241a3ee4/cryptography-46.0.2-cp311-abi3-win_arm64.whl", hash = "sha256:218abd64a2e72f8472c2102febb596793347a3e65fafbb4ad50519969da44470", size = 2927474, upload-time = "2025-10-01T00:27:52.91Z" }, - { url = "https://files.pythonhosted.org/packages/6f/cc/47fc6223a341f26d103cb6da2216805e08a37d3b52bee7f3b2aee8066f95/cryptography-46.0.2-cp314-cp314t-macosx_10_9_universal2.whl", hash = "sha256:bda55e8dbe8533937956c996beaa20266a8eca3570402e52ae52ed60de1faca8", size = 7198626, upload-time = "2025-10-01T00:27:54.8Z" }, - { url = "https://files.pythonhosted.org/packages/93/22/d66a8591207c28bbe4ac7afa25c4656dc19dc0db29a219f9809205639ede/cryptography-46.0.2-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:e7155c0b004e936d381b15425273aee1cebc94f879c0ce82b0d7fecbf755d53a", size = 4287584, upload-time = "2025-10-01T00:27:57.018Z" }, - { url = "https://files.pythonhosted.org/packages/8c/3e/fac3ab6302b928e0398c269eddab5978e6c1c50b2b77bb5365ffa8633b37/cryptography-46.0.2-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:a61c154cc5488272a6c4b86e8d5beff4639cdb173d75325ce464d723cda0052b", size = 4433796, upload-time = "2025-10-01T00:27:58.631Z" }, - { url = "https://files.pythonhosted.org/packages/7d/d8/24392e5d3c58e2d83f98fe5a2322ae343360ec5b5b93fe18bc52e47298f5/cryptography-46.0.2-cp314-cp314t-manylinux_2_28_aarch64.whl", hash = "sha256:9ec3f2e2173f36a9679d3b06d3d01121ab9b57c979de1e6a244b98d51fea1b20", size = 4292126, upload-time = "2025-10-01T00:28:00.643Z" }, - { url = "https://files.pythonhosted.org/packages/ed/38/3d9f9359b84c16c49a5a336ee8be8d322072a09fac17e737f3bb11f1ce64/cryptography-46.0.2-cp314-cp314t-manylinux_2_28_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:2fafb6aa24e702bbf74de4cb23bfa2c3beb7ab7683a299062b69724c92e0fa73", size = 3993056, upload-time = "2025-10-01T00:28:02.8Z" }, - { url = "https://files.pythonhosted.org/packages/d6/a3/4c44fce0d49a4703cc94bfbe705adebf7ab36efe978053742957bc7ec324/cryptography-46.0.2-cp314-cp314t-manylinux_2_28_ppc64le.whl", hash = "sha256:0c7ffe8c9b1fcbb07a26d7c9fa5e857c2fe80d72d7b9e0353dcf1d2180ae60ee", size = 4967604, upload-time = "2025-10-01T00:28:04.783Z" }, - { url = "https://files.pythonhosted.org/packages/eb/c2/49d73218747c8cac16bb8318a5513fde3129e06a018af3bc4dc722aa4a98/cryptography-46.0.2-cp314-cp314t-manylinux_2_28_x86_64.whl", hash = "sha256:5840f05518caa86b09d23f8b9405a7b6d5400085aa14a72a98fdf5cf1568c0d2", size = 4465367, upload-time = "2025-10-01T00:28:06.864Z" }, - { url = "https://files.pythonhosted.org/packages/1b/64/9afa7d2ee742f55ca6285a54386ed2778556a4ed8871571cb1c1bfd8db9e/cryptography-46.0.2-cp314-cp314t-manylinux_2_34_aarch64.whl", hash = "sha256:27c53b4f6a682a1b645fbf1cd5058c72cf2f5aeba7d74314c36838c7cbc06e0f", size = 4291678, upload-time = "2025-10-01T00:28:08.982Z" }, - { url = "https://files.pythonhosted.org/packages/50/48/1696d5ea9623a7b72ace87608f6899ca3c331709ac7ebf80740abb8ac673/cryptography-46.0.2-cp314-cp314t-manylinux_2_34_ppc64le.whl", hash = "sha256:512c0250065e0a6b286b2db4bbcc2e67d810acd53eb81733e71314340366279e", size = 4931366, upload-time = "2025-10-01T00:28:10.74Z" }, - { url = "https://files.pythonhosted.org/packages/eb/3c/9dfc778401a334db3b24435ee0733dd005aefb74afe036e2d154547cb917/cryptography-46.0.2-cp314-cp314t-manylinux_2_34_x86_64.whl", hash = "sha256:07c0eb6657c0e9cca5891f4e35081dbf985c8131825e21d99b4f440a8f496f36", size = 4464738, upload-time = "2025-10-01T00:28:12.491Z" }, - { url = "https://files.pythonhosted.org/packages/dc/b1/abcde62072b8f3fd414e191a6238ce55a0050e9738090dc6cded24c12036/cryptography-46.0.2-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:48b983089378f50cba258f7f7aa28198c3f6e13e607eaf10472c26320332ca9a", size = 4419305, upload-time = "2025-10-01T00:28:14.145Z" }, - { url = "https://files.pythonhosted.org/packages/c7/1f/3d2228492f9391395ca34c677e8f2571fb5370fe13dc48c1014f8c509864/cryptography-46.0.2-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:e6f6775eaaa08c0eec73e301f7592f4367ccde5e4e4df8e58320f2ebf161ea2c", size = 4681201, upload-time = "2025-10-01T00:28:15.951Z" }, - { url = "https://files.pythonhosted.org/packages/de/77/b687745804a93a55054f391528fcfc76c3d6bfd082ce9fb62c12f0d29fc1/cryptography-46.0.2-cp314-cp314t-win32.whl", hash = "sha256:e8633996579961f9b5a3008683344c2558d38420029d3c0bc7ff77c17949a4e1", size = 3022492, upload-time = "2025-10-01T00:28:17.643Z" }, - { url = "https://files.pythonhosted.org/packages/60/a5/8d498ef2996e583de0bef1dcc5e70186376f00883ae27bf2133f490adf21/cryptography-46.0.2-cp314-cp314t-win_amd64.whl", hash = "sha256:48c01988ecbb32979bb98731f5c2b2f79042a6c58cc9a319c8c2f9987c7f68f9", size = 3496215, upload-time = "2025-10-01T00:28:19.272Z" }, - { url = "https://files.pythonhosted.org/packages/56/db/ee67aaef459a2706bc302b15889a1a8126ebe66877bab1487ae6ad00f33d/cryptography-46.0.2-cp314-cp314t-win_arm64.whl", hash = "sha256:8e2ad4d1a5899b7caa3a450e33ee2734be7cc0689010964703a7c4bcc8dd4fd0", size = 2919255, upload-time = "2025-10-01T00:28:21.115Z" }, - { url = "https://files.pythonhosted.org/packages/d5/bb/fa95abcf147a1b0bb94d95f53fbb09da77b24c776c5d87d36f3d94521d2c/cryptography-46.0.2-cp38-abi3-macosx_10_9_universal2.whl", hash = "sha256:a08e7401a94c002e79dc3bc5231b6558cd4b2280ee525c4673f650a37e2c7685", size = 7248090, upload-time = "2025-10-01T00:28:22.846Z" }, - { url = "https://files.pythonhosted.org/packages/b7/66/f42071ce0e3ffbfa80a88feadb209c779fda92a23fbc1e14f74ebf72ef6b/cryptography-46.0.2-cp38-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:d30bc11d35743bf4ddf76674a0a369ec8a21f87aaa09b0661b04c5f6c46e8d7b", size = 4293123, upload-time = "2025-10-01T00:28:25.072Z" }, - { url = "https://files.pythonhosted.org/packages/a8/5d/1fdbd2e5c1ba822828d250e5a966622ef00185e476d1cd2726b6dd135e53/cryptography-46.0.2-cp38-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:bca3f0ce67e5a2a2cf524e86f44697c4323a86e0fd7ba857de1c30d52c11ede1", size = 4439524, upload-time = "2025-10-01T00:28:26.808Z" }, - { url = "https://files.pythonhosted.org/packages/c8/c1/5e4989a7d102d4306053770d60f978c7b6b1ea2ff8c06e0265e305b23516/cryptography-46.0.2-cp38-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:ff798ad7a957a5021dcbab78dfff681f0cf15744d0e6af62bd6746984d9c9e9c", size = 4297264, upload-time = "2025-10-01T00:28:29.327Z" }, - { url = "https://files.pythonhosted.org/packages/28/78/b56f847d220cb1d6d6aef5a390e116ad603ce13a0945a3386a33abc80385/cryptography-46.0.2-cp38-abi3-manylinux_2_28_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:cb5e8daac840e8879407acbe689a174f5ebaf344a062f8918e526824eb5d97af", size = 4011872, upload-time = "2025-10-01T00:28:31.479Z" }, - { url = "https://files.pythonhosted.org/packages/e1/80/2971f214b066b888944f7b57761bf709ee3f2cf805619a18b18cab9b263c/cryptography-46.0.2-cp38-abi3-manylinux_2_28_ppc64le.whl", hash = "sha256:3f37aa12b2d91e157827d90ce78f6180f0c02319468a0aea86ab5a9566da644b", size = 4978458, upload-time = "2025-10-01T00:28:33.267Z" }, - { url = "https://files.pythonhosted.org/packages/a5/84/0cb0a2beaa4f1cbe63ebec4e97cd7e0e9f835d0ba5ee143ed2523a1e0016/cryptography-46.0.2-cp38-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:5e38f203160a48b93010b07493c15f2babb4e0f2319bbd001885adb3f3696d21", size = 4472195, upload-time = "2025-10-01T00:28:36.039Z" }, - { url = "https://files.pythonhosted.org/packages/30/8b/2b542ddbf78835c7cd67b6fa79e95560023481213a060b92352a61a10efe/cryptography-46.0.2-cp38-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:d19f5f48883752b5ab34cff9e2f7e4a7f216296f33714e77d1beb03d108632b6", size = 4296791, upload-time = "2025-10-01T00:28:37.732Z" }, - { url = "https://files.pythonhosted.org/packages/78/12/9065b40201b4f4876e93b9b94d91feb18de9150d60bd842a16a21565007f/cryptography-46.0.2-cp38-abi3-manylinux_2_34_ppc64le.whl", hash = "sha256:04911b149eae142ccd8c9a68892a70c21613864afb47aba92d8c7ed9cc001023", size = 4939629, upload-time = "2025-10-01T00:28:39.654Z" }, - { url = "https://files.pythonhosted.org/packages/f6/9e/6507dc048c1b1530d372c483dfd34e7709fc542765015425f0442b08547f/cryptography-46.0.2-cp38-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:8b16c1ede6a937c291d41176934268e4ccac2c6521c69d3f5961c5a1e11e039e", size = 4471988, upload-time = "2025-10-01T00:28:41.822Z" }, - { url = "https://files.pythonhosted.org/packages/b1/86/d025584a5f7d5c5ec8d3633dbcdce83a0cd579f1141ceada7817a4c26934/cryptography-46.0.2-cp38-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:747b6f4a4a23d5a215aadd1d0b12233b4119c4313df83ab4137631d43672cc90", size = 4422989, upload-time = "2025-10-01T00:28:43.608Z" }, - { url = "https://files.pythonhosted.org/packages/4b/39/536370418b38a15a61bbe413006b79dfc3d2b4b0eafceb5581983f973c15/cryptography-46.0.2-cp38-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:6b275e398ab3a7905e168c036aad54b5969d63d3d9099a0a66cc147a3cc983be", size = 4685578, upload-time = "2025-10-01T00:28:45.361Z" }, - { url = "https://files.pythonhosted.org/packages/15/52/ea7e2b1910f547baed566c866fbb86de2402e501a89ecb4871ea7f169a81/cryptography-46.0.2-cp38-abi3-win32.whl", hash = "sha256:0b507c8e033307e37af61cb9f7159b416173bdf5b41d11c4df2e499a1d8e007c", size = 3036711, upload-time = "2025-10-01T00:28:47.096Z" }, - { url = "https://files.pythonhosted.org/packages/71/9e/171f40f9c70a873e73c2efcdbe91e1d4b1777a03398fa1c4af3c56a2477a/cryptography-46.0.2-cp38-abi3-win_amd64.whl", hash = "sha256:f9b2dc7668418fb6f221e4bf701f716e05e8eadb4f1988a2487b11aedf8abe62", size = 3500007, upload-time = "2025-10-01T00:28:48.967Z" }, - { url = "https://files.pythonhosted.org/packages/3e/7c/15ad426257615f9be8caf7f97990cf3dcbb5b8dd7ed7e0db581a1c4759dd/cryptography-46.0.2-cp38-abi3-win_arm64.whl", hash = "sha256:91447f2b17e83c9e0c89f133119d83f94ce6e0fb55dd47da0a959316e6e9cfa1", size = 2918153, upload-time = "2025-10-01T00:28:51.003Z" }, - { url = "https://files.pythonhosted.org/packages/25/b2/067a7db693488f19777ecf73f925bcb6a3efa2eae42355bafaafa37a6588/cryptography-46.0.2-pp310-pypy310_pp73-macosx_10_9_x86_64.whl", hash = "sha256:f25a41f5b34b371a06dad3f01799706631331adc7d6c05253f5bca22068c7a34", size = 3701860, upload-time = "2025-10-01T00:28:53.003Z" }, - { url = "https://files.pythonhosted.org/packages/87/12/47c2aab2c285f97c71a791169529dbb89f48fc12e5f62bb6525c3927a1a2/cryptography-46.0.2-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:e12b61e0b86611e3f4c1756686d9086c1d36e6fd15326f5658112ad1f1cc8807", size = 3429917, upload-time = "2025-10-01T00:28:55.03Z" }, - { url = "https://files.pythonhosted.org/packages/b7/8c/1aabe338149a7d0f52c3e30f2880b20027ca2a485316756ed6f000462db3/cryptography-46.0.2-pp311-pypy311_pp73-macosx_10_9_x86_64.whl", hash = "sha256:1d3b3edd145953832e09607986f2bd86f85d1dc9c48ced41808b18009d9f30e5", size = 3714495, upload-time = "2025-10-01T00:28:57.222Z" }, - { url = "https://files.pythonhosted.org/packages/e3/0a/0d10eb970fe3e57da9e9ddcfd9464c76f42baf7b3d0db4a782d6746f788f/cryptography-46.0.2-pp311-pypy311_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:fe245cf4a73c20592f0f48da39748b3513db114465be78f0a36da847221bd1b4", size = 4243379, upload-time = "2025-10-01T00:28:58.989Z" }, - { url = "https://files.pythonhosted.org/packages/7d/60/e274b4d41a9eb82538b39950a74ef06e9e4d723cb998044635d9deb1b435/cryptography-46.0.2-pp311-pypy311_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:2b9cad9cf71d0c45566624ff76654e9bae5f8a25970c250a26ccfc73f8553e2d", size = 4409533, upload-time = "2025-10-01T00:29:00.785Z" }, - { url = "https://files.pythonhosted.org/packages/19/9a/fb8548f762b4749aebd13b57b8f865de80258083fe814957f9b0619cfc56/cryptography-46.0.2-pp311-pypy311_pp73-manylinux_2_34_aarch64.whl", hash = "sha256:9bd26f2f75a925fdf5e0a446c0de2714f17819bf560b44b7480e4dd632ad6c46", size = 4243120, upload-time = "2025-10-01T00:29:02.515Z" }, - { url = "https://files.pythonhosted.org/packages/71/60/883f24147fd4a0c5cab74ac7e36a1ff3094a54ba5c3a6253d2ff4b19255b/cryptography-46.0.2-pp311-pypy311_pp73-manylinux_2_34_x86_64.whl", hash = "sha256:7282d8f092b5be7172d6472f29b0631f39f18512a3642aefe52c3c0e0ccfad5a", size = 4408940, upload-time = "2025-10-01T00:29:04.42Z" }, - { url = "https://files.pythonhosted.org/packages/d9/b5/c5e179772ec38adb1c072b3aa13937d2860509ba32b2462bf1dda153833b/cryptography-46.0.2-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:c4b93af7920cdf80f71650769464ccf1fb49a4b56ae0024173c24c48eb6b1612", size = 3438518, upload-time = "2025-10-01T00:29:06.139Z" }, +sdist = { url = "https://files.pythonhosted.org/packages/a4/ba/04b1bd4218cbc58dc90ce967106d51582371b898690f3ae0402876cc4f34/cryptography-46.0.6.tar.gz", hash = "sha256:27550628a518c5c6c903d84f637fbecf287f6cb9ced3804838a1295dc1fd0759", size = 750542, upload-time = "2026-03-25T23:34:53.396Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/47/23/9285e15e3bc57325b0a72e592921983a701efc1ee8f91c06c5f0235d86d9/cryptography-46.0.6-cp311-abi3-macosx_10_9_universal2.whl", hash = "sha256:64235194bad039a10bb6d2d930ab3323baaec67e2ce36215fd0952fad0930ca8", size = 7176401, upload-time = "2026-03-25T23:33:22.096Z" }, + { url = "https://files.pythonhosted.org/packages/60/f8/e61f8f13950ab6195b31913b42d39f0f9afc7d93f76710f299b5ec286ae6/cryptography-46.0.6-cp311-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:26031f1e5ca62fcb9d1fcb34b2b60b390d1aacaa15dc8b895a9ed00968b97b30", size = 4275275, upload-time = "2026-03-25T23:33:23.844Z" }, + { url = "https://files.pythonhosted.org/packages/19/69/732a736d12c2631e140be2348b4ad3d226302df63ef64d30dfdb8db7ad1c/cryptography-46.0.6-cp311-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:9a693028b9cbe51b5a1136232ee8f2bc242e4e19d456ded3fa7c86e43c713b4a", size = 4425320, upload-time = "2026-03-25T23:33:25.703Z" }, + { url = "https://files.pythonhosted.org/packages/d4/12/123be7292674abf76b21ac1fc0e1af50661f0e5b8f0ec8285faac18eb99e/cryptography-46.0.6-cp311-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:67177e8a9f421aa2d3a170c3e56eca4e0128883cf52a071a7cbf53297f18b175", size = 4278082, upload-time = "2026-03-25T23:33:27.423Z" }, + { url = "https://files.pythonhosted.org/packages/5b/ba/d5e27f8d68c24951b0a484924a84c7cdaed7502bac9f18601cd357f8b1d2/cryptography-46.0.6-cp311-abi3-manylinux_2_28_ppc64le.whl", hash = "sha256:d9528b535a6c4f8ff37847144b8986a9a143585f0540fbcb1a98115b543aa463", size = 4926514, upload-time = "2026-03-25T23:33:29.206Z" }, + { url = "https://files.pythonhosted.org/packages/34/71/1ea5a7352ae516d5512d17babe7e1b87d9db5150b21f794b1377eac1edc0/cryptography-46.0.6-cp311-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:22259338084d6ae497a19bae5d4c66b7ca1387d3264d1c2c0e72d9e9b6a77b97", size = 4457766, upload-time = "2026-03-25T23:33:30.834Z" }, + { url = "https://files.pythonhosted.org/packages/01/59/562be1e653accee4fdad92c7a2e88fced26b3fdfce144047519bbebc299e/cryptography-46.0.6-cp311-abi3-manylinux_2_31_armv7l.whl", hash = "sha256:760997a4b950ff00d418398ad73fbc91aa2894b5c1db7ccb45b4f68b42a63b3c", size = 3986535, upload-time = "2026-03-25T23:33:33.02Z" }, + { url = "https://files.pythonhosted.org/packages/d6/8b/b1ebfeb788bf4624d36e45ed2662b8bd43a05ff62157093c1539c1288a18/cryptography-46.0.6-cp311-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:3dfa6567f2e9e4c5dceb8ccb5a708158a2a871052fa75c8b78cb0977063f1507", size = 4277618, upload-time = "2026-03-25T23:33:34.567Z" }, + { url = "https://files.pythonhosted.org/packages/dd/52/a005f8eabdb28df57c20f84c44d397a755782d6ff6d455f05baa2785bd91/cryptography-46.0.6-cp311-abi3-manylinux_2_34_ppc64le.whl", hash = "sha256:cdcd3edcbc5d55757e5f5f3d330dd00007ae463a7e7aa5bf132d1f22a4b62b19", size = 4890802, upload-time = "2026-03-25T23:33:37.034Z" }, + { url = "https://files.pythonhosted.org/packages/ec/4d/8e7d7245c79c617d08724e2efa397737715ca0ec830ecb3c91e547302555/cryptography-46.0.6-cp311-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:d4e4aadb7fc1f88687f47ca20bb7227981b03afaae69287029da08096853b738", size = 4457425, upload-time = "2026-03-25T23:33:38.904Z" }, + { url = "https://files.pythonhosted.org/packages/1d/5c/f6c3596a1430cec6f949085f0e1a970638d76f81c3ea56d93d564d04c340/cryptography-46.0.6-cp311-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:2b417edbe8877cda9022dde3a008e2deb50be9c407eef034aeeb3a8b11d9db3c", size = 4405530, upload-time = "2026-03-25T23:33:40.842Z" }, + { url = "https://files.pythonhosted.org/packages/7e/c9/9f9cea13ee2dbde070424e0c4f621c091a91ffcc504ffea5e74f0e1daeff/cryptography-46.0.6-cp311-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:380343e0653b1c9d7e1f55b52aaa2dbb2fdf2730088d48c43ca1c7c0abb7cc2f", size = 4667896, upload-time = "2026-03-25T23:33:42.781Z" }, + { url = "https://files.pythonhosted.org/packages/ad/b5/1895bc0821226f129bc74d00eccfc6a5969e2028f8617c09790bf89c185e/cryptography-46.0.6-cp311-abi3-win32.whl", hash = "sha256:bcb87663e1f7b075e48c3be3ecb5f0b46c8fc50b50a97cf264e7f60242dca3f2", size = 3026348, upload-time = "2026-03-25T23:33:45.021Z" }, + { url = "https://files.pythonhosted.org/packages/c3/f8/c9bcbf0d3e6ad288b9d9aa0b1dee04b063d19e8c4f871855a03ab3a297ab/cryptography-46.0.6-cp311-abi3-win_amd64.whl", hash = "sha256:6739d56300662c468fddb0e5e291f9b4d084bead381667b9e654c7dd81705124", size = 3483896, upload-time = "2026-03-25T23:33:46.649Z" }, + { url = "https://files.pythonhosted.org/packages/01/41/3a578f7fd5c70611c0aacba52cd13cb364a5dee895a5c1d467208a9380b0/cryptography-46.0.6-cp314-cp314t-macosx_10_9_universal2.whl", hash = "sha256:2ef9e69886cbb137c2aef9772c2e7138dc581fad4fcbcf13cc181eb5a3ab6275", size = 7117147, upload-time = "2026-03-25T23:33:48.249Z" }, + { url = "https://files.pythonhosted.org/packages/fa/87/887f35a6fca9dde90cad08e0de0c89263a8e59b2d2ff904fd9fcd8025b6f/cryptography-46.0.6-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:7f417f034f91dcec1cb6c5c35b07cdbb2ef262557f701b4ecd803ee8cefed4f4", size = 4266221, upload-time = "2026-03-25T23:33:49.874Z" }, + { url = "https://files.pythonhosted.org/packages/aa/a8/0a90c4f0b0871e0e3d1ed126aed101328a8a57fd9fd17f00fb67e82a51ca/cryptography-46.0.6-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:d24c13369e856b94892a89ddf70b332e0b70ad4a5c43cf3e9cb71d6d7ffa1f7b", size = 4408952, upload-time = "2026-03-25T23:33:52.128Z" }, + { url = "https://files.pythonhosted.org/packages/16/0b/b239701eb946523e4e9f329336e4ff32b1247e109cbab32d1a7b61da8ed7/cryptography-46.0.6-cp314-cp314t-manylinux_2_28_aarch64.whl", hash = "sha256:aad75154a7ac9039936d50cf431719a2f8d4ed3d3c277ac03f3339ded1a5e707", size = 4270141, upload-time = "2026-03-25T23:33:54.11Z" }, + { url = "https://files.pythonhosted.org/packages/0f/a8/976acdd4f0f30df7b25605f4b9d3d89295351665c2091d18224f7ad5cdbf/cryptography-46.0.6-cp314-cp314t-manylinux_2_28_ppc64le.whl", hash = "sha256:3c21d92ed15e9cfc6eb64c1f5a0326db22ca9c2566ca46d845119b45b4400361", size = 4904178, upload-time = "2026-03-25T23:33:55.725Z" }, + { url = "https://files.pythonhosted.org/packages/b1/1b/bf0e01a88efd0e59679b69f42d4afd5bced8700bb5e80617b2d63a3741af/cryptography-46.0.6-cp314-cp314t-manylinux_2_28_x86_64.whl", hash = "sha256:4668298aef7cddeaf5c6ecc244c2302a2b8e40f384255505c22875eebb47888b", size = 4441812, upload-time = "2026-03-25T23:33:57.364Z" }, + { url = "https://files.pythonhosted.org/packages/bb/8b/11df86de2ea389c65aa1806f331cae145f2ed18011f30234cc10ca253de8/cryptography-46.0.6-cp314-cp314t-manylinux_2_31_armv7l.whl", hash = "sha256:8ce35b77aaf02f3b59c90b2c8a05c73bac12cea5b4e8f3fbece1f5fddea5f0ca", size = 3963923, upload-time = "2026-03-25T23:33:59.361Z" }, + { url = "https://files.pythonhosted.org/packages/91/e0/207fb177c3a9ef6a8108f234208c3e9e76a6aa8cf20d51932916bd43bda0/cryptography-46.0.6-cp314-cp314t-manylinux_2_34_aarch64.whl", hash = "sha256:c89eb37fae9216985d8734c1afd172ba4927f5a05cfd9bf0e4863c6d5465b013", size = 4269695, upload-time = "2026-03-25T23:34:00.909Z" }, + { url = "https://files.pythonhosted.org/packages/21/5e/19f3260ed1e95bced52ace7501fabcd266df67077eeb382b79c81729d2d3/cryptography-46.0.6-cp314-cp314t-manylinux_2_34_ppc64le.whl", hash = "sha256:ed418c37d095aeddf5336898a132fba01091f0ac5844e3e8018506f014b6d2c4", size = 4869785, upload-time = "2026-03-25T23:34:02.796Z" }, + { url = "https://files.pythonhosted.org/packages/10/38/cd7864d79aa1d92ef6f1a584281433419b955ad5a5ba8d1eb6c872165bcb/cryptography-46.0.6-cp314-cp314t-manylinux_2_34_x86_64.whl", hash = "sha256:69cf0056d6947edc6e6760e5f17afe4bea06b56a9ac8a06de9d2bd6b532d4f3a", size = 4441404, upload-time = "2026-03-25T23:34:04.35Z" }, + { url = "https://files.pythonhosted.org/packages/09/0a/4fe7a8d25fed74419f91835cf5829ade6408fd1963c9eae9c4bce390ecbb/cryptography-46.0.6-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:8e7304c4f4e9490e11efe56af6713983460ee0780f16c63f219984dab3af9d2d", size = 4397549, upload-time = "2026-03-25T23:34:06.342Z" }, + { url = "https://files.pythonhosted.org/packages/5f/a0/7d738944eac6513cd60a8da98b65951f4a3b279b93479a7e8926d9cd730b/cryptography-46.0.6-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:b928a3ca837c77a10e81a814a693f2295200adb3352395fad024559b7be7a736", size = 4651874, upload-time = "2026-03-25T23:34:07.916Z" }, + { url = "https://files.pythonhosted.org/packages/cb/f1/c2326781ca05208845efca38bf714f76939ae446cd492d7613808badedf1/cryptography-46.0.6-cp314-cp314t-win32.whl", hash = "sha256:97c8115b27e19e592a05c45d0dd89c57f81f841cc9880e353e0d3bf25b2139ed", size = 3001511, upload-time = "2026-03-25T23:34:09.892Z" }, + { url = "https://files.pythonhosted.org/packages/c9/57/fe4a23eb549ac9d903bd4698ffda13383808ef0876cc912bcb2838799ece/cryptography-46.0.6-cp314-cp314t-win_amd64.whl", hash = "sha256:c797e2517cb7880f8297e2c0f43bb910e91381339336f75d2c1c2cbf811b70b4", size = 3471692, upload-time = "2026-03-25T23:34:11.613Z" }, + { url = "https://files.pythonhosted.org/packages/c4/cc/f330e982852403da79008552de9906804568ae9230da8432f7496ce02b71/cryptography-46.0.6-cp38-abi3-macosx_10_9_universal2.whl", hash = "sha256:12cae594e9473bca1a7aceb90536060643128bb274fcea0fc459ab90f7d1ae7a", size = 7162776, upload-time = "2026-03-25T23:34:13.308Z" }, + { url = "https://files.pythonhosted.org/packages/49/b3/dc27efd8dcc4bff583b3f01d4a3943cd8b5821777a58b3a6a5f054d61b79/cryptography-46.0.6-cp38-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:639301950939d844a9e1c4464d7e07f902fe9a7f6b215bb0d4f28584729935d8", size = 4270529, upload-time = "2026-03-25T23:34:15.019Z" }, + { url = "https://files.pythonhosted.org/packages/e6/05/e8d0e6eb4f0d83365b3cb0e00eb3c484f7348db0266652ccd84632a3d58d/cryptography-46.0.6-cp38-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:ed3775295fb91f70b4027aeba878d79b3e55c0b3e97eaa4de71f8f23a9f2eb77", size = 4414827, upload-time = "2026-03-25T23:34:16.604Z" }, + { url = "https://files.pythonhosted.org/packages/2f/97/daba0f5d2dc6d855e2dcb70733c812558a7977a55dd4a6722756628c44d1/cryptography-46.0.6-cp38-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:8927ccfbe967c7df312ade694f987e7e9e22b2425976ddbf28271d7e58845290", size = 4271265, upload-time = "2026-03-25T23:34:18.586Z" }, + { url = "https://files.pythonhosted.org/packages/89/06/fe1fce39a37ac452e58d04b43b0855261dac320a2ebf8f5260dd55b201a9/cryptography-46.0.6-cp38-abi3-manylinux_2_28_ppc64le.whl", hash = "sha256:b12c6b1e1651e42ab5de8b1e00dc3b6354fdfd778e7fa60541ddacc27cd21410", size = 4916800, upload-time = "2026-03-25T23:34:20.561Z" }, + { url = "https://files.pythonhosted.org/packages/ff/8a/b14f3101fe9c3592603339eb5d94046c3ce5f7fc76d6512a2d40efd9724e/cryptography-46.0.6-cp38-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:063b67749f338ca9c5a0b7fe438a52c25f9526b851e24e6c9310e7195aad3b4d", size = 4448771, upload-time = "2026-03-25T23:34:22.406Z" }, + { url = "https://files.pythonhosted.org/packages/01/b3/0796998056a66d1973fd52ee89dc1bb3b6581960a91ad4ac705f182d398f/cryptography-46.0.6-cp38-abi3-manylinux_2_31_armv7l.whl", hash = "sha256:02fad249cb0e090b574e30b276a3da6a149e04ee2f049725b1f69e7b8351ec70", size = 3978333, upload-time = "2026-03-25T23:34:24.281Z" }, + { url = "https://files.pythonhosted.org/packages/c5/3d/db200af5a4ffd08918cd55c08399dc6c9c50b0bc72c00a3246e099d3a849/cryptography-46.0.6-cp38-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:7e6142674f2a9291463e5e150090b95a8519b2fb6e6aaec8917dd8d094ce750d", size = 4271069, upload-time = "2026-03-25T23:34:25.895Z" }, + { url = "https://files.pythonhosted.org/packages/d7/18/61acfd5b414309d74ee838be321c636fe71815436f53c9f0334bf19064fa/cryptography-46.0.6-cp38-abi3-manylinux_2_34_ppc64le.whl", hash = "sha256:456b3215172aeefb9284550b162801d62f5f264a081049a3e94307fe20792cfa", size = 4878358, upload-time = "2026-03-25T23:34:27.67Z" }, + { url = "https://files.pythonhosted.org/packages/8b/65/5bf43286d566f8171917cae23ac6add941654ccf085d739195a4eacf1674/cryptography-46.0.6-cp38-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:341359d6c9e68834e204ceaf25936dffeafea3829ab80e9503860dcc4f4dac58", size = 4448061, upload-time = "2026-03-25T23:34:29.375Z" }, + { url = "https://files.pythonhosted.org/packages/e0/25/7e49c0fa7205cf3597e525d156a6bce5b5c9de1fd7e8cb01120e459f205a/cryptography-46.0.6-cp38-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:9a9c42a2723999a710445bc0d974e345c32adfd8d2fac6d8a251fa829ad31cfb", size = 4399103, upload-time = "2026-03-25T23:34:32.036Z" }, + { url = "https://files.pythonhosted.org/packages/44/46/466269e833f1c4718d6cd496ffe20c56c9c8d013486ff66b4f69c302a68d/cryptography-46.0.6-cp38-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:6617f67b1606dfd9fe4dbfa354a9508d4a6d37afe30306fe6c101b7ce3274b72", size = 4659255, upload-time = "2026-03-25T23:34:33.679Z" }, + { url = "https://files.pythonhosted.org/packages/0a/09/ddc5f630cc32287d2c953fc5d32705e63ec73e37308e5120955316f53827/cryptography-46.0.6-cp38-abi3-win32.whl", hash = "sha256:7f6690b6c55e9c5332c0b59b9c8a3fb232ebf059094c17f9019a51e9827df91c", size = 3010660, upload-time = "2026-03-25T23:34:35.418Z" }, + { url = "https://files.pythonhosted.org/packages/1b/82/ca4893968aeb2709aacfb57a30dec6fa2ab25b10fa9f064b8882ce33f599/cryptography-46.0.6-cp38-abi3-win_amd64.whl", hash = "sha256:79e865c642cfc5c0b3eb12af83c35c5aeff4fa5c672dc28c43721c2c9fdd2f0f", size = 3471160, upload-time = "2026-03-25T23:34:37.191Z" }, + { url = "https://files.pythonhosted.org/packages/2e/84/7ccff00ced5bac74b775ce0beb7d1be4e8637536b522b5df9b73ada42da2/cryptography-46.0.6-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:2ea0f37e9a9cf0df2952893ad145fd9627d326a59daec9b0802480fa3bcd2ead", size = 3475444, upload-time = "2026-03-25T23:34:38.944Z" }, + { url = "https://files.pythonhosted.org/packages/bc/1f/4c926f50df7749f000f20eede0c896769509895e2648db5da0ed55db711d/cryptography-46.0.6-pp311-pypy311_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:a3e84d5ec9ba01f8fd03802b2147ba77f0c8f2617b2aff254cedd551844209c8", size = 4218227, upload-time = "2026-03-25T23:34:40.871Z" }, + { url = "https://files.pythonhosted.org/packages/c6/65/707be3ffbd5f786028665c3223e86e11c4cda86023adbc56bd72b1b6bab5/cryptography-46.0.6-pp311-pypy311_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:12f0fa16cc247b13c43d56d7b35287ff1569b5b1f4c5e87e92cc4fcc00cd10c0", size = 4381399, upload-time = "2026-03-25T23:34:42.609Z" }, + { url = "https://files.pythonhosted.org/packages/f3/6d/73557ed0ef7d73d04d9aba745d2c8e95218213687ee5e76b7d236a5030fc/cryptography-46.0.6-pp311-pypy311_pp73-manylinux_2_34_aarch64.whl", hash = "sha256:50575a76e2951fe7dbd1f56d181f8c5ceeeb075e9ff88e7ad997d2f42af06e7b", size = 4217595, upload-time = "2026-03-25T23:34:44.205Z" }, + { url = "https://files.pythonhosted.org/packages/9e/c5/e1594c4eec66a567c3ac4400008108a415808be2ce13dcb9a9045c92f1a0/cryptography-46.0.6-pp311-pypy311_pp73-manylinux_2_34_x86_64.whl", hash = "sha256:90e5f0a7b3be5f40c3a0a0eafb32c681d8d2c181fc2a1bdabe9b3f611d9f6b1a", size = 4380912, upload-time = "2026-03-25T23:34:46.328Z" }, + { url = "https://files.pythonhosted.org/packages/1a/89/843b53614b47f97fe1abc13f9a86efa5ec9e275292c457af1d4a60dc80e0/cryptography-46.0.6-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:6728c49e3b2c180ef26f8e9f0a883a2c585638db64cf265b49c9ba10652d430e", size = 3409955, upload-time = "2026-03-25T23:34:48.465Z" }, ] [[package]] @@ -926,23 +950,23 @@ wheels = [ [[package]] name = "docutils" -version = "0.22.2" +version = "0.22.4" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/4a/c0/89fe6215b443b919cb98a5002e107cb5026854ed1ccb6b5833e0768419d1/docutils-0.22.2.tar.gz", hash = "sha256:9fdb771707c8784c8f2728b67cb2c691305933d68137ef95a75db5f4dfbc213d", size = 2289092, upload-time = "2025-09-20T17:55:47.994Z" } +sdist = { url = "https://files.pythonhosted.org/packages/ae/b6/03bb70946330e88ffec97aefd3ea75ba575cb2e762061e0e62a213befee8/docutils-0.22.4.tar.gz", hash = "sha256:4db53b1fde9abecbb74d91230d32ab626d94f6badfc575d6db9194a49df29968", size = 2291750, upload-time = "2025-12-18T19:00:26.443Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/66/dd/f95350e853a4468ec37478414fc04ae2d61dad7a947b3015c3dcc51a09b9/docutils-0.22.2-py3-none-any.whl", hash = "sha256:b0e98d679283fc3bb0ead8a5da7f501baa632654e7056e9c5846842213d674d8", size = 632667, upload-time = "2025-09-20T17:55:43.052Z" }, + { url = "https://files.pythonhosted.org/packages/02/10/5da547df7a391dcde17f59520a231527b8571e6f46fc8efb02ccb370ab12/docutils-0.22.4-py3-none-any.whl", hash = "sha256:d0013f540772d1420576855455d050a2180186c91c15779301ac2ccb3eeb68de", size = 633196, upload-time = "2025-12-18T19:00:18.077Z" }, ] [[package]] name = "exceptiongroup" -version = "1.3.0" +version = "1.3.1" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "typing-extensions", marker = "python_full_version < '3.11'" }, + { name = "typing-extensions", marker = "python_full_version < '3.13'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/0b/9f/a65090624ecf468cdca03533906e7c69ed7588582240cfe7cc9e770b50eb/exceptiongroup-1.3.0.tar.gz", hash = "sha256:b241f5885f560bc56a59ee63ca4c6a8bfa46ae4ad651af316d4e81817bb9fd88", size = 29749, upload-time = "2025-05-10T17:42:51.123Z" } +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 = [ - { url = "https://files.pythonhosted.org/packages/36/f4/c6e662dade71f56cd2f3735141b265c3c79293c109549c1e6933b0651ffc/exceptiongroup-1.3.0-py3-none-any.whl", hash = "sha256:4d111e6e0c13d0644cad6ddaa7ed0261a0b36971f6d23e7ec9b4b9097da78a10", size = 16674, upload-time = "2025-05-10T17:42:49.33Z" }, + { url = "https://files.pythonhosted.org/packages/8a/0e/97c33bf5009bdbac74fd2beace167cab3f978feb69cc36f1ef79360d6c4e/exceptiongroup-1.3.1-py3-none-any.whl", hash = "sha256:a7a39a3bd276781e98394987d3a5701d0c4edffb633bb7a5144577f82c773598", size = 16740, upload-time = "2025-11-21T23:01:53.443Z" }, ] [[package]] @@ -956,7 +980,7 @@ wheels = [ [[package]] name = "fastapi" -version = "0.135.1" +version = "0.135.3" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "annotated-doc" }, @@ -965,70 +989,81 @@ dependencies = [ { name = "typing-extensions" }, { name = "typing-inspection" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/e7/7b/f8e0211e9380f7195ba3f3d40c292594fd81ba8ec4629e3854c353aaca45/fastapi-0.135.1.tar.gz", hash = "sha256:d04115b508d936d254cea545b7312ecaa58a7b3a0f84952535b4c9afae7668cd", size = 394962, upload-time = "2026-03-01T18:18:29.369Z" } +sdist = { url = "https://files.pythonhosted.org/packages/f7/e6/7adb4c5fa231e82c35b8f5741a9f2d055f520c29af5546fd70d3e8e1cd2e/fastapi-0.135.3.tar.gz", hash = "sha256:bd6d7caf1a2bdd8d676843cdcd2287729572a1ef524fc4d65c17ae002a1be654", size = 396524, upload-time = "2026-04-01T16:23:58.188Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/e4/72/42e900510195b23a56bde950d26a51f8b723846bfcaa0286e90287f0422b/fastapi-0.135.1-py3-none-any.whl", hash = "sha256:46e2fc5745924b7c840f71ddd277382af29ce1cdb7d5eab5bf697e3fb9999c9e", size = 116999, upload-time = "2026-03-01T18:18:30.831Z" }, + { url = "https://files.pythonhosted.org/packages/84/a4/5caa2de7f917a04ada20018eccf60d6cc6145b0199d55ca3711b0fc08312/fastapi-0.135.3-py3-none-any.whl", hash = "sha256:9b0f590c813acd13d0ab43dd8494138eb58e484bfac405db1f3187cfc5810d98", size = 117734, upload-time = "2026-04-01T16:23:59.328Z" }, ] [[package]] name = "fastuuid" -version = "0.13.5" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/15/80/3c16a1edad2e6cd82fbd15ac998cc1b881f478bf1f80ca717d941c441874/fastuuid-0.13.5.tar.gz", hash = "sha256:d4976821ab424d41542e1ea39bc828a9d454c3f8a04067c06fca123c5b95a1a1", size = 18255, upload-time = "2025-09-26T09:05:38.281Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/f0/17/f8ed7f707c1bf994ff4e38f163b367cc2060f13a8aa60b03a3c821daaf0f/fastuuid-0.13.5-cp310-cp310-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:b9edf8ee30718aee787cdd2e9e1ff3d4a3ec6ddb32fba0a23fa04956df69ab07", size = 494134, upload-time = "2025-09-26T09:14:35.852Z" }, - { url = "https://files.pythonhosted.org/packages/18/de/b03e4a083a307fb5a2c8afcfbcc6ab45578fba7996f69f329e35d18e0e67/fastuuid-0.13.5-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:f67ea1e25c5e782f7fb5aaa5208f157d950401dd9321ce56bcc6d4dc3d72ed60", size = 252832, upload-time = "2025-09-26T09:10:21.321Z" }, - { url = "https://files.pythonhosted.org/packages/62/65/3a8be5ce86e2a1eb3947be32512b62fcb0a360a998ba2405cd3e54e54f04/fastuuid-0.13.5-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9ff3fc87e1f19603dd53c38f42c2ea8d5d5462554deab69e9cf1800574e4756c", size = 244309, upload-time = "2025-09-26T09:09:08.333Z" }, - { url = "https://files.pythonhosted.org/packages/ab/eb/7b9c98d25a810fcc5f4a3e10e1e051c18e10cdad4527242e18c998fab4b1/fastuuid-0.13.5-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a6e5337fa7698dc52bc724da7e9239e93c5b24a09f6904b8660dfb8c41ce3dee", size = 271629, upload-time = "2025-09-26T09:13:37.525Z" }, - { url = "https://files.pythonhosted.org/packages/c0/37/6331f626852c2aeea8d666af049b1337e273d11e700a26333c402d0e7a94/fastuuid-0.13.5-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f9db596023c10dabb12489a88c51b75297c3a2478cb2be645e06905934e7b9fc", size = 272312, upload-time = "2025-09-26T09:13:05.252Z" }, - { url = "https://files.pythonhosted.org/packages/ad/d3/e4d3f3c2968689e17d5c73bd0da808d1673329d5ff3b4065db03d58f36e3/fastuuid-0.13.5-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:191ff6192fe53c5fc9d4d241ee1156b30a7ed6f1677b1cc2423e7ecdbc26222b", size = 291049, upload-time = "2025-09-26T09:13:31.817Z" }, - { url = "https://files.pythonhosted.org/packages/4f/4e/f27539c9b15b1947ba50907b1a83bbe905363770472c0a1c3175fb2a0ebf/fastuuid-0.13.5-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:348ce9f296dda701ba46d8dceeff309f90dbc75dd85080bbed2b299aa908890a", size = 453074, upload-time = "2025-09-26T09:11:42.674Z" }, - { url = "https://files.pythonhosted.org/packages/6b/5c/57cba66a8f04cd26d3118b21393a0dda221cb82ac992b9fe153b69a22a0a/fastuuid-0.13.5-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:46954fb644995d7fc8bbd710fbd4c65cedaa48c921c86fdbafef0229168a8c96", size = 468531, upload-time = "2025-09-26T09:10:30.626Z" }, - { url = "https://files.pythonhosted.org/packages/dc/90/dbc19dc18282b3c2264554c595901b520224efe65907c5ff5595e688ab28/fastuuid-0.13.5-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:22da0f66041e1c10c7d465b495cc6cd8e17e080dda34b4bd5ff5240b860fbb82", size = 444933, upload-time = "2025-09-26T09:09:33.405Z" }, - { url = "https://files.pythonhosted.org/packages/5b/03/4652cc314fc5163db12bc451512b087e5b5e4f36ba513f111fd5a5ff1c07/fastuuid-0.13.5-cp310-cp310-win32.whl", hash = "sha256:3e6b548f06c1ed7bad951a17a09eef69d6f24eb2b874cb4833e26b886d82990f", size = 144981, upload-time = "2025-09-26T09:08:14.812Z" }, - { url = "https://files.pythonhosted.org/packages/8f/0b/85b3a68418911923acb8955219ab33ac728eaa9337ef0135b9e5c9d1ed9d/fastuuid-0.13.5-cp310-cp310-win_amd64.whl", hash = "sha256:c82838e52189d16b1307631179cb2cd37778dd8f4ddc00e9ce3c26f920b3b2f7", size = 150741, upload-time = "2025-09-26T09:09:00.161Z" }, - { url = "https://files.pythonhosted.org/packages/04/ab/9351bfc04ff2144115758233130b5469993d3d379323903a4634cb9c78c1/fastuuid-0.13.5-cp311-cp311-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:c122558ca4b5487e2bd0863467e4ccfe636afd1274803741487d48f2e32ea0e1", size = 493910, upload-time = "2025-09-26T09:12:36.995Z" }, - { url = "https://files.pythonhosted.org/packages/b7/ab/84fac529cc12a03d49595e70ac459380f7cb12c70f0fe401781b276f9e94/fastuuid-0.13.5-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:d7abd42a03a17a681abddd19aa4d44ca2747138cf8a48373b395cf1341a10de2", size = 252621, upload-time = "2025-09-26T09:12:22.222Z" }, - { url = "https://files.pythonhosted.org/packages/7f/9d/f4c734d7b74a04ca695781c58a1376f07b206fe2849e58e7778d476a0e94/fastuuid-0.13.5-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:2705cf7c2d6f7c03053404b75a4c44f872a73f6f9d5ea34f1dc6bba400c4a97c", size = 244269, upload-time = "2025-09-26T09:08:31.921Z" }, - { url = "https://files.pythonhosted.org/packages/5b/da/b42b7eb84523d69cfe9dac82950e105061c8d59f4d4d2cc3e170dbd20937/fastuuid-0.13.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5d220a056fcbad25932c1f25304261198612f271f4d150b2a84e81adb877daf7", size = 271528, upload-time = "2025-09-26T09:12:42.718Z" }, - { url = "https://files.pythonhosted.org/packages/1b/45/6eee36929119e9544b0906fd6591e685d682e4b51cfad4c25d96ccf04009/fastuuid-0.13.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2f29f93b5a0c5f5579f97f77d5319e9bfefd61d8678ec59d850201544faf33bf", size = 272168, upload-time = "2025-09-26T09:07:04.238Z" }, - { url = "https://files.pythonhosted.org/packages/ce/ac/75b70f13515e12194a25b0459dd8a8a33de4ab0a92142f0776d21e41ca84/fastuuid-0.13.5-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:399d86623fb806151b1feb9fdd818ebfc1d50387199a35f7264f98dfc1540af5", size = 290948, upload-time = "2025-09-26T09:07:53.433Z" }, - { url = "https://files.pythonhosted.org/packages/76/30/1801326a5b433aafc04eae906e6b005e8a3d1120fd996409fe88124edb06/fastuuid-0.13.5-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:689e8795a1edd573b2c9a455024e4edf605a9690339bba29709857f7180894ea", size = 452932, upload-time = "2025-09-26T09:09:28.017Z" }, - { url = "https://files.pythonhosted.org/packages/61/2a/080b6b2ac4ef2ead54a7463ae4162d66a52867bbd4447ad5354427b82ae2/fastuuid-0.13.5-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:25e82c4a1734da168b36f7308e397afbe9c9b353799a9c69563a605f11dd4641", size = 468384, upload-time = "2025-09-26T09:08:14.32Z" }, - { url = "https://files.pythonhosted.org/packages/b6/d3/4a3ffcaf8d874f7f208dad7e98ded7c5359b6599073960e3aa0530ca6139/fastuuid-0.13.5-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:f62299e3cca69aad6a6fb37e26e45055587954d498ad98903fea24382377ea0e", size = 444815, upload-time = "2025-09-26T09:06:38.691Z" }, - { url = "https://files.pythonhosted.org/packages/9d/a0/08dd8663f7bff3e9c0b2416708b01d1fb65f52bcd4bce18760f77c4735fd/fastuuid-0.13.5-cp311-cp311-win32.whl", hash = "sha256:68227f2230381b89fb1ad362ca6e433de85c6c11c36312b41757cad47b8a8e32", size = 144897, upload-time = "2025-09-26T09:14:53.695Z" }, - { url = "https://files.pythonhosted.org/packages/9e/e2/2c2a37dcc56e2323c6214c38c8faac22f9d03d98c481f8a40843e0b9526a/fastuuid-0.13.5-cp311-cp311-win_amd64.whl", hash = "sha256:4a32306982bd031cb20d5d1a726b7b958a55babebd2300ce6c8e352d3496e931", size = 150523, upload-time = "2025-09-26T09:12:24.031Z" }, - { url = "https://files.pythonhosted.org/packages/21/36/434f137c5970cac19e57834e1f7680e85301619d49891618c00666700c61/fastuuid-0.13.5-cp312-cp312-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:35fe8045e866bc6846f8de6fa05acb1de0c32478048484a995e96d31e21dff2a", size = 494638, upload-time = "2025-09-26T09:14:58.695Z" }, - { url = "https://files.pythonhosted.org/packages/ca/3c/083de2ac007b2b305523b9c006dba5051e5afd87a626ef1a39f76e2c6b82/fastuuid-0.13.5-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:02a460333f52d731a006d18a52ef6fcb2d295a1f5b1a5938d30744191b2f77b7", size = 253138, upload-time = "2025-09-26T09:13:33.283Z" }, - { url = "https://files.pythonhosted.org/packages/73/5e/630cffa1c8775db526e39e9e4c5c7db0c27be0786bb21ba82c912ae19f63/fastuuid-0.13.5-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:74b0e4f8c307b9f477a5d7284db4431ce53a3c1e3f4173db7a97db18564a6202", size = 244521, upload-time = "2025-09-26T09:14:40.682Z" }, - { url = "https://files.pythonhosted.org/packages/4d/51/55d78705f4fbdadf88fb40f382f508d6c7a4941ceddd7825fafebb4cc778/fastuuid-0.13.5-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6955a99ef455c2986f3851f4e0ccc35dec56ac1a7720f2b92e88a75d6684512e", size = 271557, upload-time = "2025-09-26T09:15:09.75Z" }, - { url = "https://files.pythonhosted.org/packages/6a/2b/1b89e90a8635e5587ccdbbeb169c590672ce7637880f2c047482a0359950/fastuuid-0.13.5-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f10c77b826738c1a27dcdaa92ea4dc1ec9d869748a99e1fde54f1379553d4854", size = 272334, upload-time = "2025-09-26T09:07:48.865Z" }, - { url = "https://files.pythonhosted.org/packages/0c/06/4c8207894eeb30414999e5c3f66ac039bc4003437eb4060d8a1bceb4cc6f/fastuuid-0.13.5-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:bb25dccbeb249d16d5e664f65f17ebec05136821d5ef462c4110e3f76b86fb86", size = 290594, upload-time = "2025-09-26T09:12:54.124Z" }, - { url = "https://files.pythonhosted.org/packages/50/69/96d221931a31d77a47cc2487bdfacfb3091edfc2e7a04b1795df1aec05df/fastuuid-0.13.5-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:a5becc646a3eeafb76ce0a6783ba190cd182e3790a8b2c78ca9db2b5e87af952", size = 452835, upload-time = "2025-09-26T09:14:00.994Z" }, - { url = "https://files.pythonhosted.org/packages/25/ef/bf045f0a47dcec96247497ef3f7a31d86ebc074330e2dccc34b8dbc0468a/fastuuid-0.13.5-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:69b34363752d06e9bb0dbdf02ae391ec56ac948c6f2eb00be90dad68e80774b9", size = 468225, upload-time = "2025-09-26T09:13:38.585Z" }, - { url = "https://files.pythonhosted.org/packages/30/46/4817ab5a3778927155a4bde92540d4c4fa996161ec8b8e080c8928b0984e/fastuuid-0.13.5-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:57d0768afcad0eab8770c9b8cf904716bd3c547e8b9a4e755ee8a673b060a3a3", size = 444907, upload-time = "2025-09-26T09:14:30.163Z" }, - { url = "https://files.pythonhosted.org/packages/80/27/ab284117ce4dc9b356a7196bdbf220510285f201d27f1f078592cdc8187b/fastuuid-0.13.5-cp312-cp312-win32.whl", hash = "sha256:8ac6c6f5129d52eaa6ef9ea4b6e2f7c69468a053f3ab8e439661186b9c06bb85", size = 145415, upload-time = "2025-09-26T09:08:59.494Z" }, - { url = "https://files.pythonhosted.org/packages/f4/0c/f970a4222773b248931819f8940800b760283216ca3dda173ed027e94bdd/fastuuid-0.13.5-cp312-cp312-win_amd64.whl", hash = "sha256:ad630e97715beefef07ec37c9c162336e500400774e2c1cbe1a0df6f80d15b9a", size = 150840, upload-time = "2025-09-26T09:13:46.115Z" }, - { url = "https://files.pythonhosted.org/packages/4f/62/74fc53f6e04a4dc5b36c34e4e679f85a4c14eec800dcdb0f2c14b5442217/fastuuid-0.13.5-cp313-cp313-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:ea17dfd35e0e91920a35d91e65e5f9c9d1985db55ac4ff2f1667a0f61189cefa", size = 494678, upload-time = "2025-09-26T09:14:30.908Z" }, - { url = "https://files.pythonhosted.org/packages/09/ba/f28b9b7045738a8bfccfb9cd6aff4b91fce2669e6b383a48b0694ee9b3ff/fastuuid-0.13.5-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:be6ad91e5fefbcc2a4b478858a2715e386d405834ea3ae337c3b6b95cc0e47d6", size = 253162, upload-time = "2025-09-26T09:13:35.879Z" }, - { url = "https://files.pythonhosted.org/packages/b1/18/13fac89cb4c9f0cd7e81a9154a77ecebcc95d2b03477aa91d4d50f7227ee/fastuuid-0.13.5-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:ea6df13a306aab3e0439d58c312ff1e6f4f07f09f667579679239b4a6121f64a", size = 244546, upload-time = "2025-09-26T09:14:58.13Z" }, - { url = "https://files.pythonhosted.org/packages/04/bf/9691167804d59411cc4269841df949f6dd5e76452ab10dcfcd1dbe04c5bc/fastuuid-0.13.5-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2354c1996d3cf12dc2ba3752e2c4d6edc46e1a38c63893146777b1939f3062d4", size = 271528, upload-time = "2025-09-26T09:14:48.996Z" }, - { url = "https://files.pythonhosted.org/packages/a9/b5/7a75a03d1c7aa0b6d573032fcca39391f0aef7f2caabeeb45a672bc0bd3c/fastuuid-0.13.5-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a6cf9b7469fc26d1f9b1c43ac4b192e219e85b88fdf81d71aa755a6c08c8a817", size = 272292, upload-time = "2025-09-26T09:14:42.82Z" }, - { url = "https://files.pythonhosted.org/packages/c0/db/fa0f16cbf76e6880599533af4ef01bb586949c5320612e9d884eff13e603/fastuuid-0.13.5-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:92ba539170097b9047551375f1ca09d8d2b4aefcc79eeae3e1c43fe49b42072e", size = 290466, upload-time = "2025-09-26T09:08:33.161Z" }, - { url = "https://files.pythonhosted.org/packages/1e/02/6b8c45bfbc8500994dd94edba7f59555f9683c4d8c9a164ae1d25d03c7c7/fastuuid-0.13.5-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:dbb81d05617bc2970765c1ad82db7e8716f6a2b7a361a14b83de5b9240ade448", size = 452838, upload-time = "2025-09-26T09:13:44.747Z" }, - { url = "https://files.pythonhosted.org/packages/27/12/85d95a84f265b888e8eb9f9e2b5aaf331e8be60c0a7060146364b3544b6a/fastuuid-0.13.5-cp313-cp313-musllinux_1_1_i686.whl", hash = "sha256:d973bd6bf9d754d3cca874714ac0a6b22a47f239fb3d3c8687569db05aac3471", size = 468149, upload-time = "2025-09-26T09:13:18.712Z" }, - { url = "https://files.pythonhosted.org/packages/ad/da/dd9a137e9ea707e883c92470113a432233482ec9ad3e9b99c4defc4904e6/fastuuid-0.13.5-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:e725ceef79486423f05ee657634d4b4c1ca5fb2c8a94e0708f5d6356a83f2a83", size = 444933, upload-time = "2025-09-26T09:14:09.494Z" }, - { url = "https://files.pythonhosted.org/packages/12/f4/ab363d7f4ac3989691e2dc5ae2d8391cfb0b4169e52ef7fa0ac363e936f0/fastuuid-0.13.5-cp313-cp313-win32.whl", hash = "sha256:a1c430a332ead0b2674f1ef71b17f43b8139ec5a4201182766a21f131a31e021", size = 145462, upload-time = "2025-09-26T09:14:15.105Z" }, - { url = "https://files.pythonhosted.org/packages/aa/8a/52eb77d9c294a54caa0d2d8cc9f906207aa6d916a22de963687ab6db8b86/fastuuid-0.13.5-cp313-cp313-win_amd64.whl", hash = "sha256:241fdd362fd96e6b337db62a65dd7cb3dfac20adf854573247a47510e192db6f", size = 150923, upload-time = "2025-09-26T09:13:03.923Z" }, +version = "0.14.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/c3/7d/d9daedf0f2ebcacd20d599928f8913e9d2aea1d56d2d355a93bfa2b611d7/fastuuid-0.14.0.tar.gz", hash = "sha256:178947fc2f995b38497a74172adee64fdeb8b7ec18f2a5934d037641ba265d26", size = 18232, upload-time = "2025-10-19T22:19:22.402Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ad/b2/731a6696e37cd20eed353f69a09f37a984a43c9713764ee3f7ad5f57f7f9/fastuuid-0.14.0-cp310-cp310-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:6e6243d40f6c793c3e2ee14c13769e341b90be5ef0c23c82fa6515a96145181a", size = 516760, upload-time = "2025-10-19T22:25:21.509Z" }, + { url = "https://files.pythonhosted.org/packages/c5/79/c73c47be2a3b8734d16e628982653517f80bbe0570e27185d91af6096507/fastuuid-0.14.0-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:13ec4f2c3b04271f62be2e1ce7e95ad2dd1cf97e94503a3760db739afbd48f00", size = 264748, upload-time = "2025-10-19T22:41:52.873Z" }, + { url = "https://files.pythonhosted.org/packages/24/c5/84c1eea05977c8ba5173555b0133e3558dc628bcf868d6bf1689ff14aedc/fastuuid-0.14.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:b2fdd48b5e4236df145a149d7125badb28e0a383372add3fbaac9a6b7a394470", size = 254537, upload-time = "2025-10-19T22:33:55.603Z" }, + { url = "https://files.pythonhosted.org/packages/0e/23/4e362367b7fa17dbed646922f216b9921efb486e7abe02147e4b917359f8/fastuuid-0.14.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f74631b8322d2780ebcf2d2d75d58045c3e9378625ec51865fe0b5620800c39d", size = 278994, upload-time = "2025-10-19T22:26:17.631Z" }, + { url = "https://files.pythonhosted.org/packages/b2/72/3985be633b5a428e9eaec4287ed4b873b7c4c53a9639a8b416637223c4cd/fastuuid-0.14.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:83cffc144dc93eb604b87b179837f2ce2af44871a7b323f2bfed40e8acb40ba8", size = 280003, upload-time = "2025-10-19T22:23:45.415Z" }, + { url = "https://files.pythonhosted.org/packages/b3/6d/6ef192a6df34e2266d5c9deb39cd3eea986df650cbcfeaf171aa52a059c3/fastuuid-0.14.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:1a771f135ab4523eb786e95493803942a5d1fc1610915f131b363f55af53b219", size = 303583, upload-time = "2025-10-19T22:26:00.756Z" }, + { url = "https://files.pythonhosted.org/packages/9d/11/8a2ea753c68d4fece29d5d7c6f3f903948cc6e82d1823bc9f7f7c0355db3/fastuuid-0.14.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:4edc56b877d960b4eda2c4232f953a61490c3134da94f3c28af129fb9c62a4f6", size = 460955, upload-time = "2025-10-19T22:36:25.196Z" }, + { url = "https://files.pythonhosted.org/packages/23/42/7a32c93b6ce12642d9a152ee4753a078f372c9ebb893bc489d838dd4afd5/fastuuid-0.14.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:bcc96ee819c282e7c09b2eed2b9bd13084e3b749fdb2faf58c318d498df2efbe", size = 480763, upload-time = "2025-10-19T22:24:28.451Z" }, + { url = "https://files.pythonhosted.org/packages/b9/e9/a5f6f686b46e3ed4ed3b93770111c233baac87dd6586a411b4988018ef1d/fastuuid-0.14.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:7a3c0bca61eacc1843ea97b288d6789fbad7400d16db24e36a66c28c268cfe3d", size = 452613, upload-time = "2025-10-19T22:25:06.827Z" }, + { url = "https://files.pythonhosted.org/packages/b4/c9/18abc73c9c5b7fc0e476c1733b678783b2e8a35b0be9babd423571d44e98/fastuuid-0.14.0-cp310-cp310-win32.whl", hash = "sha256:7f2f3efade4937fae4e77efae1af571902263de7b78a0aee1a1653795a093b2a", size = 155045, upload-time = "2025-10-19T22:28:32.732Z" }, + { url = "https://files.pythonhosted.org/packages/5e/8a/d9e33f4eb4d4f6d9f2c5c7d7e96b5cdbb535c93f3b1ad6acce97ee9d4bf8/fastuuid-0.14.0-cp310-cp310-win_amd64.whl", hash = "sha256:ae64ba730d179f439b0736208b4c279b8bc9c089b102aec23f86512ea458c8a4", size = 156122, upload-time = "2025-10-19T22:23:15.59Z" }, + { url = "https://files.pythonhosted.org/packages/98/f3/12481bda4e5b6d3e698fbf525df4443cc7dce746f246b86b6fcb2fba1844/fastuuid-0.14.0-cp311-cp311-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:73946cb950c8caf65127d4e9a325e2b6be0442a224fd51ba3b6ac44e1912ce34", size = 516386, upload-time = "2025-10-19T22:42:40.176Z" }, + { url = "https://files.pythonhosted.org/packages/59/19/2fc58a1446e4d72b655648eb0879b04e88ed6fa70d474efcf550f640f6ec/fastuuid-0.14.0-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:12ac85024637586a5b69645e7ed986f7535106ed3013640a393a03e461740cb7", size = 264569, upload-time = "2025-10-19T22:25:50.977Z" }, + { url = "https://files.pythonhosted.org/packages/78/29/3c74756e5b02c40cfcc8b1d8b5bac4edbd532b55917a6bcc9113550e99d1/fastuuid-0.14.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:05a8dde1f395e0c9b4be515b7a521403d1e8349443e7641761af07c7ad1624b1", size = 254366, upload-time = "2025-10-19T22:29:49.166Z" }, + { url = "https://files.pythonhosted.org/packages/52/96/d761da3fccfa84f0f353ce6e3eb8b7f76b3aa21fd25e1b00a19f9c80a063/fastuuid-0.14.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:09378a05020e3e4883dfdab438926f31fea15fd17604908f3d39cbeb22a0b4dc", size = 278978, upload-time = "2025-10-19T22:35:41.306Z" }, + { url = "https://files.pythonhosted.org/packages/fc/c2/f84c90167cc7765cb82b3ff7808057608b21c14a38531845d933a4637307/fastuuid-0.14.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bbb0c4b15d66b435d2538f3827f05e44e2baafcc003dd7d8472dc67807ab8fd8", size = 279692, upload-time = "2025-10-19T22:25:36.997Z" }, + { url = "https://files.pythonhosted.org/packages/af/7b/4bacd03897b88c12348e7bd77943bac32ccf80ff98100598fcff74f75f2e/fastuuid-0.14.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:cd5a7f648d4365b41dbf0e38fe8da4884e57bed4e77c83598e076ac0c93995e7", size = 303384, upload-time = "2025-10-19T22:29:46.578Z" }, + { url = "https://files.pythonhosted.org/packages/c0/a2/584f2c29641df8bd810d00c1f21d408c12e9ad0c0dafdb8b7b29e5ddf787/fastuuid-0.14.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:c0a94245afae4d7af8c43b3159d5e3934c53f47140be0be624b96acd672ceb73", size = 460921, upload-time = "2025-10-19T22:36:42.006Z" }, + { url = "https://files.pythonhosted.org/packages/24/68/c6b77443bb7764c760e211002c8638c0c7cce11cb584927e723215ba1398/fastuuid-0.14.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:2b29e23c97e77c3a9514d70ce343571e469098ac7f5a269320a0f0b3e193ab36", size = 480575, upload-time = "2025-10-19T22:28:18.975Z" }, + { url = "https://files.pythonhosted.org/packages/5a/87/93f553111b33f9bb83145be12868c3c475bf8ea87c107063d01377cc0e8e/fastuuid-0.14.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:1e690d48f923c253f28151b3a6b4e335f2b06bf669c68a02665bc150b7839e94", size = 452317, upload-time = "2025-10-19T22:25:32.75Z" }, + { url = "https://files.pythonhosted.org/packages/9e/8c/a04d486ca55b5abb7eaa65b39df8d891b7b1635b22db2163734dc273579a/fastuuid-0.14.0-cp311-cp311-win32.whl", hash = "sha256:a6f46790d59ab38c6aa0e35c681c0484b50dc0acf9e2679c005d61e019313c24", size = 154804, upload-time = "2025-10-19T22:24:15.615Z" }, + { url = "https://files.pythonhosted.org/packages/9c/b2/2d40bf00820de94b9280366a122cbaa60090c8cf59e89ac3938cf5d75895/fastuuid-0.14.0-cp311-cp311-win_amd64.whl", hash = "sha256:e150eab56c95dc9e3fefc234a0eedb342fac433dacc273cd4d150a5b0871e1fa", size = 156099, upload-time = "2025-10-19T22:24:31.646Z" }, + { url = "https://files.pythonhosted.org/packages/02/a2/e78fcc5df65467f0d207661b7ef86c5b7ac62eea337c0c0fcedbeee6fb13/fastuuid-0.14.0-cp312-cp312-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:77e94728324b63660ebf8adb27055e92d2e4611645bf12ed9d88d30486471d0a", size = 510164, upload-time = "2025-10-19T22:31:45.635Z" }, + { url = "https://files.pythonhosted.org/packages/2b/b3/c846f933f22f581f558ee63f81f29fa924acd971ce903dab1a9b6701816e/fastuuid-0.14.0-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:caa1f14d2102cb8d353096bc6ef6c13b2c81f347e6ab9d6fbd48b9dea41c153d", size = 261837, upload-time = "2025-10-19T22:38:38.53Z" }, + { url = "https://files.pythonhosted.org/packages/54/ea/682551030f8c4fa9a769d9825570ad28c0c71e30cf34020b85c1f7ee7382/fastuuid-0.14.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:d23ef06f9e67163be38cece704170486715b177f6baae338110983f99a72c070", size = 251370, upload-time = "2025-10-19T22:40:26.07Z" }, + { url = "https://files.pythonhosted.org/packages/14/dd/5927f0a523d8e6a76b70968e6004966ee7df30322f5fc9b6cdfb0276646a/fastuuid-0.14.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0c9ec605ace243b6dbe3bd27ebdd5d33b00d8d1d3f580b39fdd15cd96fd71796", size = 277766, upload-time = "2025-10-19T22:37:23.779Z" }, + { url = "https://files.pythonhosted.org/packages/16/6e/c0fb547eef61293153348f12e0f75a06abb322664b34a1573a7760501336/fastuuid-0.14.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:808527f2407f58a76c916d6aa15d58692a4a019fdf8d4c32ac7ff303b7d7af09", size = 278105, upload-time = "2025-10-19T22:26:56.821Z" }, + { url = "https://files.pythonhosted.org/packages/2d/b1/b9c75e03b768f61cf2e84ee193dc18601aeaf89a4684b20f2f0e9f52b62c/fastuuid-0.14.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2fb3c0d7fef6674bbeacdd6dbd386924a7b60b26de849266d1ff6602937675c8", size = 301564, upload-time = "2025-10-19T22:30:31.604Z" }, + { url = "https://files.pythonhosted.org/packages/fc/fa/f7395fdac07c7a54f18f801744573707321ca0cee082e638e36452355a9d/fastuuid-0.14.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:ab3f5d36e4393e628a4df337c2c039069344db5f4b9d2a3c9cea48284f1dd741", size = 459659, upload-time = "2025-10-19T22:31:32.341Z" }, + { url = "https://files.pythonhosted.org/packages/66/49/c9fd06a4a0b1f0f048aacb6599e7d96e5d6bc6fa680ed0d46bf111929d1b/fastuuid-0.14.0-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:b9a0ca4f03b7e0b01425281ffd44e99d360e15c895f1907ca105854ed85e2057", size = 478430, upload-time = "2025-10-19T22:26:22.962Z" }, + { url = "https://files.pythonhosted.org/packages/be/9c/909e8c95b494e8e140e8be6165d5fc3f61fdc46198c1554df7b3e1764471/fastuuid-0.14.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:3acdf655684cc09e60fb7e4cf524e8f42ea760031945aa8086c7eae2eeeabeb8", size = 450894, upload-time = "2025-10-19T22:27:01.647Z" }, + { url = "https://files.pythonhosted.org/packages/90/eb/d29d17521976e673c55ef7f210d4cdd72091a9ec6755d0fd4710d9b3c871/fastuuid-0.14.0-cp312-cp312-win32.whl", hash = "sha256:9579618be6280700ae36ac42c3efd157049fe4dd40ca49b021280481c78c3176", size = 154374, upload-time = "2025-10-19T22:29:19.879Z" }, + { url = "https://files.pythonhosted.org/packages/cc/fc/f5c799a6ea6d877faec0472d0b27c079b47c86b1cdc577720a5386483b36/fastuuid-0.14.0-cp312-cp312-win_amd64.whl", hash = "sha256:d9e4332dc4ba054434a9594cbfaf7823b57993d7d8e7267831c3e059857cf397", size = 156550, upload-time = "2025-10-19T22:27:49.658Z" }, + { url = "https://files.pythonhosted.org/packages/a5/83/ae12dd39b9a39b55d7f90abb8971f1a5f3c321fd72d5aa83f90dc67fe9ed/fastuuid-0.14.0-cp313-cp313-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:77a09cb7427e7af74c594e409f7731a0cf887221de2f698e1ca0ebf0f3139021", size = 510720, upload-time = "2025-10-19T22:42:34.633Z" }, + { url = "https://files.pythonhosted.org/packages/53/b0/a4b03ff5d00f563cc7546b933c28cb3f2a07344b2aec5834e874f7d44143/fastuuid-0.14.0-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:9bd57289daf7b153bfa3e8013446aa144ce5e8c825e9e366d455155ede5ea2dc", size = 262024, upload-time = "2025-10-19T22:30:25.482Z" }, + { url = "https://files.pythonhosted.org/packages/9c/6d/64aee0a0f6a58eeabadd582e55d0d7d70258ffdd01d093b30c53d668303b/fastuuid-0.14.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:ac60fc860cdf3c3f327374db87ab8e064c86566ca8c49d2e30df15eda1b0c2d5", size = 251679, upload-time = "2025-10-19T22:36:14.096Z" }, + { url = "https://files.pythonhosted.org/packages/60/f5/a7e9cda8369e4f7919d36552db9b2ae21db7915083bc6336f1b0082c8b2e/fastuuid-0.14.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ab32f74bd56565b186f036e33129da77db8be09178cd2f5206a5d4035fb2a23f", size = 277862, upload-time = "2025-10-19T22:36:23.302Z" }, + { url = "https://files.pythonhosted.org/packages/f0/d3/8ce11827c783affffd5bd4d6378b28eb6cc6d2ddf41474006b8d62e7448e/fastuuid-0.14.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:33e678459cf4addaedd9936bbb038e35b3f6b2061330fd8f2f6a1d80414c0f87", size = 278278, upload-time = "2025-10-19T22:29:43.809Z" }, + { url = "https://files.pythonhosted.org/packages/a2/51/680fb6352d0bbade04036da46264a8001f74b7484e2fd1f4da9e3db1c666/fastuuid-0.14.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:1e3cc56742f76cd25ecb98e4b82a25f978ccffba02e4bdce8aba857b6d85d87b", size = 301788, upload-time = "2025-10-19T22:36:06.825Z" }, + { url = "https://files.pythonhosted.org/packages/fa/7c/2014b5785bd8ebdab04ec857635ebd84d5ee4950186a577db9eff0fb8ff6/fastuuid-0.14.0-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:cb9a030f609194b679e1660f7e32733b7a0f332d519c5d5a6a0a580991290022", size = 459819, upload-time = "2025-10-19T22:35:31.623Z" }, + { url = "https://files.pythonhosted.org/packages/01/d2/524d4ceeba9160e7a9bc2ea3e8f4ccf1ad78f3bde34090ca0c51f09a5e91/fastuuid-0.14.0-cp313-cp313-musllinux_1_1_i686.whl", hash = "sha256:09098762aad4f8da3a888eb9ae01c84430c907a297b97166b8abc07b640f2995", size = 478546, upload-time = "2025-10-19T22:26:03.023Z" }, + { url = "https://files.pythonhosted.org/packages/bc/17/354d04951ce114bf4afc78e27a18cfbd6ee319ab1829c2d5fb5e94063ac6/fastuuid-0.14.0-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:1383fff584fa249b16329a059c68ad45d030d5a4b70fb7c73a08d98fd53bcdab", size = 450921, upload-time = "2025-10-19T22:31:02.151Z" }, + { url = "https://files.pythonhosted.org/packages/fb/be/d7be8670151d16d88f15bb121c5b66cdb5ea6a0c2a362d0dcf30276ade53/fastuuid-0.14.0-cp313-cp313-win32.whl", hash = "sha256:a0809f8cc5731c066c909047f9a314d5f536c871a7a22e815cc4967c110ac9ad", size = 154559, upload-time = "2025-10-19T22:36:36.011Z" }, + { url = "https://files.pythonhosted.org/packages/22/1d/5573ef3624ceb7abf4a46073d3554e37191c868abc3aecd5289a72f9810a/fastuuid-0.14.0-cp313-cp313-win_amd64.whl", hash = "sha256:0df14e92e7ad3276327631c9e7cec09e32572ce82089c55cb1bb8df71cf394ed", size = 156539, upload-time = "2025-10-19T22:33:35.898Z" }, + { url = "https://files.pythonhosted.org/packages/16/c9/8c7660d1fe3862e3f8acabd9be7fc9ad71eb270f1c65cce9a2b7a31329ab/fastuuid-0.14.0-cp314-cp314-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:b852a870a61cfc26c884af205d502881a2e59cc07076b60ab4a951cc0c94d1ad", size = 510600, upload-time = "2025-10-19T22:43:44.17Z" }, + { url = "https://files.pythonhosted.org/packages/4c/f4/a989c82f9a90d0ad995aa957b3e572ebef163c5299823b4027986f133dfb/fastuuid-0.14.0-cp314-cp314-macosx_10_12_x86_64.whl", hash = "sha256:c7502d6f54cd08024c3ea9b3514e2d6f190feb2f46e6dbcd3747882264bb5f7b", size = 262069, upload-time = "2025-10-19T22:43:38.38Z" }, + { url = "https://files.pythonhosted.org/packages/da/6c/a1a24f73574ac995482b1326cf7ab41301af0fabaa3e37eeb6b3df00e6e2/fastuuid-0.14.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:1ca61b592120cf314cfd66e662a5b54a578c5a15b26305e1b8b618a6f22df714", size = 251543, upload-time = "2025-10-19T22:32:22.537Z" }, + { url = "https://files.pythonhosted.org/packages/1a/20/2a9b59185ba7a6c7b37808431477c2d739fcbdabbf63e00243e37bd6bf49/fastuuid-0.14.0-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:aa75b6657ec129d0abded3bec745e6f7ab642e6dba3a5272a68247e85f5f316f", size = 277798, upload-time = "2025-10-19T22:33:53.821Z" }, + { url = "https://files.pythonhosted.org/packages/ef/33/4105ca574f6ded0af6a797d39add041bcfb468a1255fbbe82fcb6f592da2/fastuuid-0.14.0-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a8a0dfea3972200f72d4c7df02c8ac70bad1bb4c58d7e0ec1e6f341679073a7f", size = 278283, upload-time = "2025-10-19T22:29:02.812Z" }, + { url = "https://files.pythonhosted.org/packages/fe/8c/fca59f8e21c4deb013f574eae05723737ddb1d2937ce87cb2a5d20992dc3/fastuuid-0.14.0-cp314-cp314-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:1bf539a7a95f35b419f9ad105d5a8a35036df35fdafae48fb2fd2e5f318f0d75", size = 301627, upload-time = "2025-10-19T22:35:54.985Z" }, + { url = "https://files.pythonhosted.org/packages/cb/e2/f78c271b909c034d429218f2798ca4e89eeda7983f4257d7865976ddbb6c/fastuuid-0.14.0-cp314-cp314-musllinux_1_1_aarch64.whl", hash = "sha256:9a133bf9cc78fdbd1179cb58a59ad0100aa32d8675508150f3658814aeefeaa4", size = 459778, upload-time = "2025-10-19T22:28:00.999Z" }, + { url = "https://files.pythonhosted.org/packages/1e/f0/5ff209d865897667a2ff3e7a572267a9ced8f7313919f6d6043aed8b1caa/fastuuid-0.14.0-cp314-cp314-musllinux_1_1_i686.whl", hash = "sha256:f54d5b36c56a2d5e1a31e73b950b28a0d83eb0c37b91d10408875a5a29494bad", size = 478605, upload-time = "2025-10-19T22:36:21.764Z" }, + { url = "https://files.pythonhosted.org/packages/e0/c8/2ce1c78f983a2c4987ea865d9516dbdfb141a120fd3abb977ae6f02ba7ca/fastuuid-0.14.0-cp314-cp314-musllinux_1_1_x86_64.whl", hash = "sha256:ec27778c6ca3393ef662e2762dba8af13f4ec1aaa32d08d77f71f2a70ae9feb8", size = 450837, upload-time = "2025-10-19T22:34:37.178Z" }, + { url = "https://files.pythonhosted.org/packages/df/60/dad662ec9a33b4a5fe44f60699258da64172c39bd041da2994422cdc40fe/fastuuid-0.14.0-cp314-cp314-win32.whl", hash = "sha256:e23fc6a83f112de4be0cc1990e5b127c27663ae43f866353166f87df58e73d06", size = 154532, upload-time = "2025-10-19T22:35:18.217Z" }, + { url = "https://files.pythonhosted.org/packages/1f/f6/da4db31001e854025ffd26bc9ba0740a9cbba2c3259695f7c5834908b336/fastuuid-0.14.0-cp314-cp314-win_amd64.whl", hash = "sha256:df61342889d0f5e7a32f7284e55ef95103f2110fee433c2ae7c2c0956d76ac8a", size = 156457, upload-time = "2025-10-19T22:33:44.579Z" }, ] [[package]] name = "filelock" -version = "3.20.3" +version = "3.25.2" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/1d/65/ce7f1b70157833bf3cb851b556a37d4547ceafc158aa9b34b36782f23696/filelock-3.20.3.tar.gz", hash = "sha256:18c57ee915c7ec61cff0ecf7f0f869936c7c30191bb0cf406f1341778d0834e1", size = 19485, upload-time = "2026-01-09T17:55:05.421Z" } +sdist = { url = "https://files.pythonhosted.org/packages/94/b8/00651a0f559862f3bb7d6f7477b192afe3f583cc5e26403b44e59a55ab34/filelock-3.25.2.tar.gz", hash = "sha256:b64ece2b38f4ca29dd3e810287aa8c48182bbecd1ae6e9ae126c9b35f1382694", size = 40480, upload-time = "2026-03-11T20:45:38.487Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/b5/36/7fb70f04bf00bc646cd5bb45aa9eddb15e19437a28b8fb2b4a5249fac770/filelock-3.20.3-py3-none-any.whl", hash = "sha256:4b0dda527ee31078689fc205ec4f1c1bf7d56cf88b6dc9426c4f230e46c2dce1", size = 16701, upload-time = "2026-01-09T17:55:04.334Z" }, + { url = "https://files.pythonhosted.org/packages/a4/a5/842ae8f0c08b61d6484b52f99a03510a3a72d23141942d216ebe81fefbce/filelock-3.25.2-py3-none-any.whl", hash = "sha256:ca8afb0da15f229774c9ad1b455ed96e85a81373065fb10446672f64444ddf70", size = 26759, upload-time = "2026-03-11T20:45:37.437Z" }, ] [[package]] @@ -1184,16 +1219,16 @@ wheels = [ [[package]] name = "fsspec" -version = "2025.9.0" +version = "2026.3.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/de/e0/bab50af11c2d75c9c4a2a26a5254573c0bd97cea152254401510950486fa/fsspec-2025.9.0.tar.gz", hash = "sha256:19fd429483d25d28b65ec68f9f4adc16c17ea2c7c7bf54ec61360d478fb19c19", size = 304847, upload-time = "2025-09-02T19:10:49.215Z" } +sdist = { url = "https://files.pythonhosted.org/packages/e1/cf/b50ddf667c15276a9ab15a70ef5f257564de271957933ffea49d2cdbcdfb/fsspec-2026.3.0.tar.gz", hash = "sha256:1ee6a0e28677557f8c2f994e3eea77db6392b4de9cd1f5d7a9e87a0ae9d01b41", size = 313547, upload-time = "2026-03-27T19:11:14.892Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/47/71/70db47e4f6ce3e5c37a607355f80da8860a33226be640226ac52cb05ef2e/fsspec-2025.9.0-py3-none-any.whl", hash = "sha256:530dc2a2af60a414a832059574df4a6e10cce927f6f4a78209390fe38955cfb7", size = 199289, upload-time = "2025-09-02T19:10:47.708Z" }, + { url = "https://files.pythonhosted.org/packages/d5/1f/5f4a3cd9e4440e9d9bc78ad0a91a1c8d46b4d429d5239ebe6793c9fe5c41/fsspec-2026.3.0-py3-none-any.whl", hash = "sha256:d2ceafaad1b3457968ed14efa28798162f1638dbb5d2a6868a2db002a5ee39a4", size = 202595, upload-time = "2026-03-27T19:11:13.595Z" }, ] [[package]] name = "google-adk" -version = "1.27.0" +version = "1.28.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "aiosqlite" }, @@ -1242,14 +1277,14 @@ dependencies = [ { name = "watchdog" }, { name = "websockets" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/bd/c4/0e41560662706b28895438b707dde4c3a86892e97cc2cf2bc4e029a4fb13/google_adk-1.27.0.tar.gz", hash = "sha256:281c1c2617d02645993972cd42cbe898265010ce80cb41e1d3381f78f362097c", size = 2297667, upload-time = "2026-03-12T22:50:15.968Z" } +sdist = { url = "https://files.pythonhosted.org/packages/83/bd/ce670dca7a32b1bc46410edece7781d8db06aa5a48d7323f1c2aa30384b6/google_adk-1.28.1.tar.gz", hash = "sha256:76e6ec4a13f981bd9c2c7782e8b37b0e973b570b699b750a52444998e8886ced", size = 2318960, upload-time = "2026-04-02T22:21:02.796Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/fb/42/0cfb8d7f29bf1665e04d09852868fa93ce269ba8ecca19576f6bc7274188/google_adk-1.27.0-py3-none-any.whl", hash = "sha256:a800684760e299270bbb6836ea4648b5cbf0efdc681dfee4c8d0ca939630f4e5", size = 2688747, upload-time = "2026-03-12T22:50:14.241Z" }, + { url = "https://files.pythonhosted.org/packages/7e/51/1926ef771b3223fcd0ff0568c9f5429d45239cdc6f09d9ecbb7a4cc69c1f/google_adk-1.28.1-py3-none-any.whl", hash = "sha256:ee7cdf90ba05737be3a2aa4867804324a02f2918bd810e746fe6416184e11511", size = 2729150, upload-time = "2026-04-02T22:21:01.096Z" }, ] [[package]] name = "google-api-core" -version = "2.30.0" +version = "2.30.2" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "google-auth" }, @@ -1258,9 +1293,9 @@ dependencies = [ { name = "protobuf" }, { name = "requests" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/22/98/586ec94553b569080caef635f98a3723db36a38eac0e3d7eb3ea9d2e4b9a/google_api_core-2.30.0.tar.gz", hash = "sha256:02edfa9fab31e17fc0befb5f161b3bf93c9096d99aed584625f38065c511ad9b", size = 176959, upload-time = "2026-02-18T20:28:11.926Z" } +sdist = { url = "https://files.pythonhosted.org/packages/1a/2e/83ca41eb400eb228f9279ec14ed66f6475218b59af4c6daec2d5a509fe83/google_api_core-2.30.2.tar.gz", hash = "sha256:9a8113e1a88bdc09a7ff629707f2214d98d61c7f6ceb0ea38c42a095d02dc0f9", size = 176862, upload-time = "2026-04-02T21:23:44.876Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/45/27/09c33d67f7e0dcf06d7ac17d196594e66989299374bfb0d4331d1038e76b/google_api_core-2.30.0-py3-none-any.whl", hash = "sha256:80be49ee937ff9aba0fd79a6eddfde35fe658b9953ab9b79c57dd7061afa8df5", size = 173288, upload-time = "2026-02-18T20:28:10.367Z" }, + { url = "https://files.pythonhosted.org/packages/84/e1/ebd5100cbb202e561c0c8b59e485ef3bd63fa9beb610f3fdcaea443f0288/google_api_core-2.30.2-py3-none-any.whl", hash = "sha256:a4c226766d6af2580577db1f1a51bf53cd262f722b49731ce7414c43068a9594", size = 173236, upload-time = "2026-04-02T21:23:06.395Z" }, ] [package.optional-dependencies] @@ -1271,7 +1306,7 @@ grpc = [ [[package]] name = "google-api-python-client" -version = "2.192.0" +version = "2.193.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "google-api-core" }, @@ -1280,23 +1315,22 @@ dependencies = [ { name = "httplib2" }, { name = "uritemplate" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/85/d8/489052a40935e45b9b5b3d6accc14b041360c1507bdc659c2e1a19aaa3ff/google_api_python_client-2.192.0.tar.gz", hash = "sha256:d48cfa6078fadea788425481b007af33fe0ab6537b78f37da914fb6fc112eb27", size = 14209505, upload-time = "2026-03-05T15:17:01.598Z" } +sdist = { url = "https://files.pythonhosted.org/packages/90/f4/e14b6815d3b1885328dd209676a3a4c704882743ac94e18ef0093894f5c8/google_api_python_client-2.193.0.tar.gz", hash = "sha256:8f88d16e89d11341e0a8b199cafde0fb7e6b44260dffb88d451577cbd1bb5d33", size = 14281006, upload-time = "2026-03-17T18:25:29.415Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/e0/76/ec4128f00fefb9011635ae2abc67d7dacd05c8559378f8f05f0c907c38d8/google_api_python_client-2.192.0-py3-none-any.whl", hash = "sha256:63a57d4457cd97df1d63eb89c5fda03c5a50588dcbc32c0115dd1433c08f4b62", size = 14783267, upload-time = "2026-03-05T15:16:58.804Z" }, + { url = "https://files.pythonhosted.org/packages/f0/6d/fe75167797790a56d17799b75e1129bb93f7ff061efc7b36e9731bd4be2b/google_api_python_client-2.193.0-py3-none-any.whl", hash = "sha256:c42aa324b822109901cfecab5dc4fc3915d35a7b376835233c916c70610322db", size = 14856490, upload-time = "2026-03-17T18:25:26.608Z" }, ] [[package]] name = "google-auth" -version = "2.49.0" +version = "2.49.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "cryptography" }, { name = "pyasn1-modules" }, - { name = "rsa" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/7d/59/7371175bfd949abfb1170aa076352131d7281bd9449c0f978604fc4431c3/google_auth-2.49.0.tar.gz", hash = "sha256:9cc2d9259d3700d7a257681f81052db6737495a1a46b610597f4b8bafe5286ae", size = 333444, upload-time = "2026-03-06T21:53:06.07Z" } +sdist = { url = "https://files.pythonhosted.org/packages/ea/80/6a696a07d3d3b0a92488933532f03dbefa4a24ab80fb231395b9a2a1be77/google_auth-2.49.1.tar.gz", hash = "sha256:16d40da1c3c5a0533f57d268fe72e0ebb0ae1cc3b567024122651c045d879b64", size = 333825, upload-time = "2026-03-12T19:30:58.135Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/37/45/de64b823b639103de4b63dd193480dce99526bd36be6530c2dba85bf7817/google_auth-2.49.0-py3-none-any.whl", hash = "sha256:f893ef7307f19cf53700b7e2f61b5a6affe3aa0edf9943b13788920ab92d8d87", size = 240676, upload-time = "2026-03-06T21:52:38.304Z" }, + { url = "https://files.pythonhosted.org/packages/e9/eb/c6c2478d8a8d633460be40e2a8a6f8f429171997a35a96f81d3b680dec83/google_auth-2.49.1-py3-none-any.whl", hash = "sha256:195ebe3dca18eddd1b3db5edc5189b76c13e96f29e73043b923ebcf3f1a860f7", size = 240737, upload-time = "2026-03-12T19:30:53.159Z" }, ] [package.optional-dependencies] @@ -1309,20 +1343,20 @@ requests = [ [[package]] name = "google-auth-httplib2" -version = "0.3.0" +version = "0.3.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "google-auth" }, { name = "httplib2" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/d5/ad/c1f2b1175096a8d04cf202ad5ea6065f108d26be6fc7215876bde4a7981d/google_auth_httplib2-0.3.0.tar.gz", hash = "sha256:177898a0175252480d5ed916aeea183c2df87c1f9c26705d74ae6b951c268b0b", size = 11134, upload-time = "2025-12-15T22:13:51.825Z" } +sdist = { url = "https://files.pythonhosted.org/packages/ed/99/107612bef8d24b298bb5a7c8466f908ecda791d43f9466f5c3978f5b24c1/google_auth_httplib2-0.3.1.tar.gz", hash = "sha256:0af542e815784cb64159b4469aa5d71dd41069ba93effa006e1916b1dcd88e55", size = 11152, upload-time = "2026-03-30T22:50:26.766Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/99/d5/3c97526c8796d3caf5f4b3bed2b05e8a7102326f00a334e7a438237f3b22/google_auth_httplib2-0.3.0-py3-none-any.whl", hash = "sha256:426167e5df066e3f5a0fc7ea18768c08e7296046594ce4c8c409c2457dd1f776", size = 9529, upload-time = "2025-12-15T22:13:51.048Z" }, + { url = "https://files.pythonhosted.org/packages/97/e9/93afb14d23a949acaa3f4e7cc51a0024671174e116e35f42850764b99634/google_auth_httplib2-0.3.1-py3-none-any.whl", hash = "sha256:682356a90ef4ba3d06548c37e9112eea6fc00395a11b0303a644c1a86abc275c", size = 9534, upload-time = "2026-03-30T22:49:03.384Z" }, ] [[package]] name = "google-cloud-aiplatform" -version = "1.140.0" +version = "1.145.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "docstring-parser" }, @@ -1338,13 +1372,14 @@ dependencies = [ { name = "pydantic" }, { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/1b/14/1c223faf986afffdd61c994a10c30a04985ed5ba072201058af2c6e1e572/google_cloud_aiplatform-1.140.0.tar.gz", hash = "sha256:ea7eb1870b4cf600f8c2472102e21c3a1bcaf723d6e49f00ed51bc6b88d54fff", size = 10146640, upload-time = "2026-03-04T00:56:38.95Z" } +sdist = { url = "https://files.pythonhosted.org/packages/26/e5/6442d9d2c019456638825d4665b1e87ec4eaf1d182950ba426d0f0210eab/google_cloud_aiplatform-1.145.0.tar.gz", hash = "sha256:7894c4f3d2684bdb60e9a122004c01678e3b585174a27298ae7a3ed1e5eaf3bd", size = 10222904, upload-time = "2026-04-02T14:06:58.322Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/c3/5c/bb64aee2da24895d57611eed00fac54739bfa34f98ab344020a6605875bf/google_cloud_aiplatform-1.140.0-py2.py3-none-any.whl", hash = "sha256:e94493a2682b9d17efa7146a53bb3665bf1595c3394fd3d0f45d18f71623fddc", size = 8355660, upload-time = "2026-03-04T00:56:34.441Z" }, + { url = "https://files.pythonhosted.org/packages/3d/c6/23e98d3407d5e2416a3dfaecb0a053da899848c50db69e5f2b61a555ce06/google_cloud_aiplatform-1.145.0-py2.py3-none-any.whl", hash = "sha256:4d1c31797a8bd8f3342ed5f186dd30d1f6bca73ddbee2bde452777100d2ddc11", size = 8396640, upload-time = "2026-04-02T14:06:54.125Z" }, ] [package.optional-dependencies] agent-engines = [ + { name = "aiohttp" }, { name = "cloudpickle" }, { name = "google-cloud-iam" }, { name = "google-cloud-logging" }, @@ -1360,7 +1395,7 @@ agent-engines = [ [[package]] name = "google-cloud-appengine-logging" -version = "1.8.0" +version = "1.9.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "google-api-core", extra = ["grpc"] }, @@ -1369,27 +1404,27 @@ dependencies = [ { name = "proto-plus" }, { name = "protobuf" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/65/38/89317773c64b5a7e9b56b9aecb2e39ac02d8d6d09fb5b276710c6892e690/google_cloud_appengine_logging-1.8.0.tar.gz", hash = "sha256:84b705a69e4109fc2f68dfe36ce3df6a34d5c3d989eee6d0ac1b024dda0ba6f5", size = 18071, upload-time = "2026-01-15T13:14:40.024Z" } +sdist = { url = "https://files.pythonhosted.org/packages/bc/02/800897064ca6f1a26835cdf23939c4b93e38a30f3fb5c7cec7c01ae2edc2/google_cloud_appengine_logging-1.9.0.tar.gz", hash = "sha256:ff397f0bbc1485f979ab45767c38e0f676c9598c97c384f7412216e6ea22f805", size = 17963, upload-time = "2026-03-30T22:51:33.556Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/a2/66/4a9be8afb1d0bf49472478cec20fefe4f4cb3a6e67be2231f097041e7339/google_cloud_appengine_logging-1.8.0-py3-none-any.whl", hash = "sha256:a4ce9ce94a9fd8c89ed07fa0b06fcf9ea3642f9532a1be1a8c7b5f82c0a70ec6", size = 18380, upload-time = "2026-01-09T14:52:58.154Z" }, + { url = "https://files.pythonhosted.org/packages/56/4a/304d42664ab2afbe7be39559c9eb3f81dd06e7ac9284f9f36f726f15939d/google_cloud_appengine_logging-1.9.0-py3-none-any.whl", hash = "sha256:bbf3a7e4dc171678f7f481259d1f68c3ae7d337530f1f2361f8a0b214dbcfe36", size = 18333, upload-time = "2026-03-30T22:49:39.045Z" }, ] [[package]] name = "google-cloud-audit-log" -version = "0.4.0" +version = "0.5.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "googleapis-common-protos" }, { name = "protobuf" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/c7/d2/ad96950410f8a05e921a6da2e1a6ba4aeca674bbb5dda8200c3c7296d7ad/google_cloud_audit_log-0.4.0.tar.gz", hash = "sha256:8467d4dcca9f3e6160520c24d71592e49e874838f174762272ec10e7950b6feb", size = 44682, upload-time = "2025-10-17T02:33:44.641Z" } +sdist = { url = "https://files.pythonhosted.org/packages/be/9f/3aedb3ce1d58c58ec7dd06b3964836eabfd17a16a95b60c8f609c0afff7f/google_cloud_audit_log-0.5.0.tar.gz", hash = "sha256:3b32d5e77db634c46fbd6c5e01f5bda836f420dfbb21d730501c75e9fab4e4a4", size = 44670, upload-time = "2026-03-30T22:50:42.295Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/9b/25/532886995f11102ad6de290496de5db227bd3a73827702445928ad32edcb/google_cloud_audit_log-0.4.0-py3-none-any.whl", hash = "sha256:6b88e2349df45f8f4cc0993b687109b1388da1571c502dc1417efa4b66ec55e0", size = 44890, upload-time = "2025-10-17T02:30:55.11Z" }, + { url = "https://files.pythonhosted.org/packages/64/40/79fa535b6e3321d5e07b2a9ab4bb63860d3fea12230c765837881348003c/google_cloud_audit_log-0.5.0-py3-none-any.whl", hash = "sha256:3f4632f25bf67446fa9085c52868f3cb42fb1afbab9489ba8978e30991afc79f", size = 44862, upload-time = "2026-03-30T22:47:57.533Z" }, ] [[package]] name = "google-cloud-bigquery" -version = "3.40.1" +version = "3.41.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "google-api-core", extra = ["grpc"] }, @@ -1400,14 +1435,14 @@ dependencies = [ { name = "python-dateutil" }, { name = "requests" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/11/0c/153ee546c288949fcc6794d58811ab5420f3ecad5fa7f9e73f78d9512a6e/google_cloud_bigquery-3.40.1.tar.gz", hash = "sha256:75afcfb6e007238fe1deefb2182105249321145ff921784fe7b1de2b4ba24506", size = 511761, upload-time = "2026-02-12T18:44:18.958Z" } +sdist = { url = "https://files.pythonhosted.org/packages/ce/13/6515c7aab55a4a0cf708ffd309fb9af5bab54c13e32dc22c5acd6497193c/google_cloud_bigquery-3.41.0.tar.gz", hash = "sha256:2217e488b47ed576360c9b2cc07d59d883a54b83167c0ef37f915c26b01a06fe", size = 513434, upload-time = "2026-03-30T22:50:55.347Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/7c/f5/081cf5b90adfe524ae0d671781b0d497a75a0f2601d075af518828e22d8f/google_cloud_bigquery-3.40.1-py3-none-any.whl", hash = "sha256:9082a6b8193aba87bed6a2c79cf1152b524c99bb7e7ac33a785e333c09eac868", size = 262018, upload-time = "2026-02-12T18:44:16.913Z" }, + { url = "https://files.pythonhosted.org/packages/40/33/1d3902efadef9194566d499d61507e1f038454e0b55499d2d7f8ab2a4fee/google_cloud_bigquery-3.41.0-py3-none-any.whl", hash = "sha256:2a5b5a737b401cbd824a6e5eac7554100b878668d908e6548836b5d8aaa4dcaa", size = 262343, upload-time = "2026-03-30T22:48:45.444Z" }, ] [[package]] name = "google-cloud-bigquery-storage" -version = "2.36.2" +version = "2.37.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "google-api-core", extra = ["grpc"] }, @@ -1416,14 +1451,14 @@ dependencies = [ { name = "proto-plus" }, { name = "protobuf" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/e0/fa/877e0059349369be38a64586b135c59ceadb87d0386084043d8c440ef929/google_cloud_bigquery_storage-2.36.2.tar.gz", hash = "sha256:ad49d8c09ad6cd82da4efe596fcfcdbc1458bf05b93915e3c5c00f1e700ae128", size = 308672, upload-time = "2026-02-19T16:03:10.544Z" } +sdist = { url = "https://files.pythonhosted.org/packages/13/31/5c6fa9e7b8e266a765ec80d13a2b2852cb0a6d3733572e7dbdc0cb39003c/google_cloud_bigquery_storage-2.37.0.tar.gz", hash = "sha256:f88ee7f1e49db1e639da3d9a8b79835ca4bc47afbb514fb2adfc0ccb41a7fd97", size = 310578, upload-time = "2026-03-30T22:51:13.418Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/1f/07/62dbe78ef773569be0a1d2c1b845e9214889b404e506126519b4d33ee999/google_cloud_bigquery_storage-2.36.2-py3-none-any.whl", hash = "sha256:823a73db0c4564e8ad3eedcfd5049f3d5aa41775267863b5627211ec36be2dbf", size = 304398, upload-time = "2026-02-19T16:02:55.112Z" }, + { url = "https://files.pythonhosted.org/packages/74/0e/2950d4d0160300f51c7397a080b1685d3e25b40badb2c96f03d58d0ee868/google_cloud_bigquery_storage-2.37.0-py3-none-any.whl", hash = "sha256:1e319c27ef60fc31030f6e0b52e5e891e1cdd50551effe8c6f673a4c3c56fcb6", size = 306678, upload-time = "2026-03-30T22:47:42.333Z" }, ] [[package]] name = "google-cloud-bigtable" -version = "2.35.0" +version = "2.36.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "google-api-core", extra = ["grpc"] }, @@ -1434,27 +1469,27 @@ dependencies = [ { name = "proto-plus" }, { name = "protobuf" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/57/c9/aceae21411b1a77fb4d3cde6e6f461321ee33c65fb8dc53480d4e47e1a55/google_cloud_bigtable-2.35.0.tar.gz", hash = "sha256:f5699012c5fea4bd4bdf7e80e5e3a812a847eb8f41bf8dc2f43095d6d876b83b", size = 775613, upload-time = "2025-12-17T15:18:14.303Z" } +sdist = { url = "https://files.pythonhosted.org/packages/52/f5/ad2a48306a7e8d5e47b5203703ce9c343389e60f025b5ea3f0c62ba92129/google_cloud_bigtable-2.36.0.tar.gz", hash = "sha256:d5987733c2f60c739f93f259d2037858411cc994ac37cdfbccb6bb159f3ca43e", size = 796035, upload-time = "2026-04-02T21:23:33.248Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/62/69/03eed134d71f6117ffd9efac2d1033bb2fa2522e9e82545a0828061d32f4/google_cloud_bigtable-2.35.0-py3-none-any.whl", hash = "sha256:f355bfce1f239453ec2bb3839b0f4f9937cf34ef06ef29e1ca63d58fd38d0c50", size = 540341, upload-time = "2025-12-17T15:18:12.176Z" }, + { url = "https://files.pythonhosted.org/packages/d1/19/1cc695fa8489ef446a70ee9e983c12f4b47e0649005758035530eaec4b1c/google_cloud_bigtable-2.36.0-py3-none-any.whl", hash = "sha256:21b2f41231b7368a550b44d5b493b811b3507fcb23eb26d00005cd3f205f2207", size = 552799, upload-time = "2026-04-02T21:23:20.475Z" }, ] [[package]] name = "google-cloud-core" -version = "2.5.0" +version = "2.5.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "google-api-core" }, { name = "google-auth" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/a6/03/ef0bc99d0e0faf4fdbe67ac445e18cdaa74824fd93cd069e7bb6548cb52d/google_cloud_core-2.5.0.tar.gz", hash = "sha256:7c1b7ef5c92311717bd05301aa1a91ffbc565673d3b0b4163a52d8413a186963", size = 36027, upload-time = "2025-10-29T23:17:39.513Z" } +sdist = { url = "https://files.pythonhosted.org/packages/dc/24/6ca08b0a03c7b0c620427503ab00353a4ae806b848b93bcea18b6b76fde6/google_cloud_core-2.5.1.tar.gz", hash = "sha256:3dc94bdec9d05a31d9f355045ed0f369fbc0d8c665076c734f065d729800f811", size = 36078, upload-time = "2026-03-30T22:50:08.057Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/89/20/bfa472e327c8edee00f04beecc80baeddd2ab33ee0e86fd7654da49d45e9/google_cloud_core-2.5.0-py3-none-any.whl", hash = "sha256:67d977b41ae6c7211ee830c7912e41003ea8194bff15ae7d72fd6f51e57acabc", size = 29469, upload-time = "2025-10-29T23:17:38.548Z" }, + { url = "https://files.pythonhosted.org/packages/73/d9/5bb050cb32826466aa9b25f79e2ca2879fe66cb76782d4ed798dd7506151/google_cloud_core-2.5.1-py3-none-any.whl", hash = "sha256:ea62cdf502c20e3e14be8a32c05ed02113d7bef454e40ff3fab6fe1ec9f1f4e7", size = 29452, upload-time = "2026-03-30T22:48:31.567Z" }, ] [[package]] name = "google-cloud-dataplex" -version = "2.16.0" +version = "2.18.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "google-api-core", extra = ["grpc"] }, @@ -1464,9 +1499,9 @@ dependencies = [ { name = "proto-plus" }, { name = "protobuf" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/ac/64/38445469e85e20b6fbb0ad58d0466daa3bd779789729562c12b35cfc24c3/google_cloud_dataplex-2.16.0.tar.gz", hash = "sha256:f9086abb94ae1f35151b2df5b729cc6bbf9361354d5afd22e76515ec0a8e7fdc", size = 766385, upload-time = "2026-01-15T13:15:22.79Z" } +sdist = { url = "https://files.pythonhosted.org/packages/ee/2b/c390bbe1f68015ea57eb9352e90ebbbf459c3139d9e5a8e6faa0b1abdc6e/google_cloud_dataplex-2.18.0.tar.gz", hash = "sha256:ae3f7f1b5c64675e8a4b66725d404eec864e12d29051323a2232bdb05797016d", size = 881810, upload-time = "2026-03-30T22:49:53.747Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/c7/1a/9d0fc0188abcfe3c4e58db72972b100badb9899e34d94471223ac2037816/google_cloud_dataplex-2.16.0-py3-none-any.whl", hash = "sha256:173ce519395cd424c1ae22de4efb194767524fb5a2424194f091e63b34f4dfc1", size = 584533, upload-time = "2026-01-15T13:13:12.348Z" }, + { url = "https://files.pythonhosted.org/packages/b2/9a/8b096a6d772b7abf1c97dfbce17d47ba1d8a944ce8d7a239fd300a3ad8ae/google_cloud_dataplex-2.18.0-py3-none-any.whl", hash = "sha256:6e4ec95b24f64e95cec5f3753fbe7419f78ddb8b1ba90f8d955bc7613bb90764", size = 675743, upload-time = "2026-03-30T20:02:27.12Z" }, ] [[package]] @@ -1486,7 +1521,7 @@ wheels = [ [[package]] name = "google-cloud-iam" -version = "2.21.0" +version = "2.22.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "google-api-core", extra = ["grpc"] }, @@ -1496,14 +1531,14 @@ dependencies = [ { name = "proto-plus" }, { name = "protobuf" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/aa/0b/037b1e1eb601646d6f49bc06d62094c1d0996b373dcbf70c426c6c51572e/google_cloud_iam-2.21.0.tar.gz", hash = "sha256:fc560527e22b97c6cbfba0797d867cf956c727ba687b586b9aa44d78e92281a3", size = 499038, upload-time = "2026-01-15T13:15:08.243Z" } +sdist = { url = "https://files.pythonhosted.org/packages/62/e5/07d4f1daf85a2a0bd9f78ad865ea678d7b4e1227ed76f671c7167aae147f/google_cloud_iam-2.22.0.tar.gz", hash = "sha256:203ddfece17e014ee4fbc5c3244daa14a88b7ee57c8e3a7622d0f2a1a3b8d7f3", size = 502498, upload-time = "2026-03-30T22:51:28.878Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/c8/44/02ac4e147ea034a3d641c11b54c9d8d0b80fc1ea6a8b7d6c1588d208d42a/google_cloud_iam-2.21.0-py3-none-any.whl", hash = "sha256:1b4a21302b186a31f3a516ccff303779638308b7c801fb61a2406b6a0c6293c4", size = 458958, upload-time = "2026-01-15T13:13:40.671Z" }, + { url = "https://files.pythonhosted.org/packages/aa/a8/d721ea11d0eb93803d14cb2e90d0442bb3b269a82f7cb5faff2b98022039/google_cloud_iam-2.22.0-py3-none-any.whl", hash = "sha256:c443b34b5a6a9e51d32cee397879bb781b900af68937c67a275def23bbc025f3", size = 463425, upload-time = "2026-03-30T20:02:42.967Z" }, ] [[package]] name = "google-cloud-logging" -version = "3.14.0" +version = "3.15.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "google-api-core", extra = ["grpc"] }, @@ -1517,14 +1552,14 @@ dependencies = [ { name = "proto-plus" }, { name = "protobuf" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/9d/ce/0d3539008dc33b436e7c5c644abc8f8a7ec5900911d14a8e34e145f0ebe5/google_cloud_logging-3.14.0.tar.gz", hash = "sha256:361e83cd692fecc7da10351f641c474591f586f234fc49394db4ba5c8c5994a7", size = 293452, upload-time = "2026-03-06T21:53:07.526Z" } +sdist = { url = "https://files.pythonhosted.org/packages/99/06/253e9795a5877f35183a7175977ca47a17255fe0c8487155f48b86c83f3e/google_cloud_logging-3.15.0.tar.gz", hash = "sha256:72168a1e98bbfc27c75f0b8f630a7f5d786065f3f1f7e9e53d2d787a03693a4a", size = 294881, upload-time = "2026-03-26T22:18:36.947Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/7b/3e/01795fc20f1b5f8b1d1d22eeb425c9c3396046f1761c4f6b4cc7d8dcab90/google_cloud_logging-3.14.0-py3-none-any.whl", hash = "sha256:4767ebdb3b46a3052d5185a7d5cf02829d33ea12a0aab1d57221110d581b9e1a", size = 232961, upload-time = "2026-03-06T21:52:48.393Z" }, + { url = "https://files.pythonhosted.org/packages/86/0c/fc1a0c57f95d21559ed13e381d9024e9ee9d521489707573fd10af856545/google_cloud_logging-3.15.0-py3-none-any.whl", hash = "sha256:7dcc67434c4e7181510c133d5ac8fd4ce60c23fa4158661f67e54bf440c32450", size = 234212, upload-time = "2026-03-26T22:15:16.404Z" }, ] [[package]] name = "google-cloud-monitoring" -version = "2.29.1" +version = "2.30.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "google-api-core", extra = ["grpc"] }, @@ -1533,34 +1568,34 @@ dependencies = [ { name = "proto-plus" }, { name = "protobuf" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/97/06/9fc0a34bed4221a68eef3e0373ae054de367dc42c0b689d5d917587ef61b/google_cloud_monitoring-2.29.1.tar.gz", hash = "sha256:86cac55cdd2608561819d19544fb3c129bbb7dcecc445d8de426e34cd6fa8e49", size = 404383, upload-time = "2026-02-05T18:59:13.026Z" } +sdist = { url = "https://files.pythonhosted.org/packages/eb/3f/7bc306ebb006114f58fb9143aec91e1b014a11577350d8bbd6bbc38389f9/google_cloud_monitoring-2.30.0.tar.gz", hash = "sha256:a9530aa9aa246c490810dfa7be32d67e8340d19108acc99cbc02d1ed494fba76", size = 407108, upload-time = "2026-03-26T22:17:10.365Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/ac/97/7c27aa95eccf8b62b066295a7c4ad04284364b696d3e7d9d47152b255a24/google_cloud_monitoring-2.29.1-py3-none-any.whl", hash = "sha256:944a57031f20da38617d184d5658c1f938e019e8061f27fd944584831a1b9d5a", size = 387922, upload-time = "2026-02-05T18:58:54.964Z" }, + { url = "https://files.pythonhosted.org/packages/ad/c8/666c21c470b9d6fd62ac9ee74dc265419975228f9b16f8ad72ec22e8d98b/google_cloud_monitoring-2.30.0-py3-none-any.whl", hash = "sha256:2729f3b88a4798b7757b1d9d31b6cb562bb3544e8173765e4e5cd44d8685b1ed", size = 391367, upload-time = "2026-03-26T22:15:04.088Z" }, ] [[package]] name = "google-cloud-pubsub" -version = "2.35.0" +version = "2.36.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", marker = "python_full_version < '3.14'" }, { name = "grpcio-status" }, { name = "opentelemetry-api" }, { name = "opentelemetry-sdk" }, { name = "proto-plus" }, { name = "protobuf" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/65/ad/dde4c0b014247190a4df0dfa9c90de81b47909e22e2e442198f449a3593f/google_cloud_pubsub-2.35.0.tar.gz", hash = "sha256:2c0d1d7ccda52fa12fb73f34b7eb9899381e2fd931c7d47b10f724cdfac06f95", size = 396812, upload-time = "2026-02-05T22:29:14.584Z" } +sdist = { url = "https://files.pythonhosted.org/packages/4e/8d/f5cece431daaa2024129569ed35e6eb90a72bb51f0c96e5c7f5cab6d34d7/google_cloud_pubsub-2.36.0.tar.gz", hash = "sha256:96e057e5f83433ce428852095d652c2f7fc193f0f77db1f27cc39186fe69c1f4", size = 401324, upload-time = "2026-03-12T19:31:02.099Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/40/cb/b783f4e910f0ec4010d279bafce0cd1ed8a10bac41970eb5c6a6416008ab/google_cloud_pubsub-2.35.0-py3-none-any.whl", hash = "sha256:c32e4eb29e532ec784b5abb5d674807715ec07895b7c022b9404871dec09970d", size = 320973, upload-time = "2026-02-05T22:29:13.096Z" }, + { url = "https://files.pythonhosted.org/packages/93/fd/d0a8f0f93a4d115282ecdd8ef0267e4611bde6ca29c9dba803f3ebae7115/google_cloud_pubsub-2.36.0-py3-none-any.whl", hash = "sha256:d6726ccf9373924e0746338dadf8244b9aa1a97a24130b59a2106c926ea37598", size = 323364, upload-time = "2026-03-12T19:30:48.077Z" }, ] [[package]] name = "google-cloud-resource-manager" -version = "1.16.0" +version = "1.17.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "google-api-core", extra = ["grpc"] }, @@ -1570,14 +1605,14 @@ dependencies = [ { name = "proto-plus" }, { name = "protobuf" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/4e/7f/db00b2820475793a52958dc55fe9ec2eb8e863546e05fcece9b921f86ebe/google_cloud_resource_manager-1.16.0.tar.gz", hash = "sha256:cc938f87cc36c2672f062b1e541650629e0d954c405a4dac35ceedee70c267c3", size = 459840, upload-time = "2026-01-15T13:04:07.726Z" } +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/94/ff/4b28bcc791d9d7e4ac8fea00fbd90ccb236afda56746a3b4564d2ae45df3/google_cloud_resource_manager-1.16.0-py3-none-any.whl", hash = "sha256:fb9a2ad2b5053c508e1c407ac31abfd1a22e91c32876c1892830724195819a28", size = 400218, upload-time = "2026-01-15T13:02:47.378Z" }, + { 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.26.0" +version = "2.27.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "google-api-core", extra = ["grpc"] }, @@ -1587,14 +1622,14 @@ dependencies = [ { name = "proto-plus" }, { name = "protobuf" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/c3/9c/a6c7144bc96df77376ae3fcc916fb639c40814c2e4bba2051d31dc136cd0/google_cloud_secret_manager-2.26.0.tar.gz", hash = "sha256:0d1d6f76327685a0ed78a4cf50f289e1bfbbe56026ed0affa98663b86d6d50d6", size = 277603, upload-time = "2025-12-18T00:29:31.065Z" } +sdist = { url = "https://files.pythonhosted.org/packages/6d/df/fbea0536e1baa6ea2239fdd19e9e22c9d64c8e26a0f3921596ecc0e5397d/google_cloud_secret_manager-2.27.0.tar.gz", hash = "sha256:6af864c252bd3c11db7bb02b80cb0b14a8c9a33fc7ec4d6f245f33d8ce1f7cd1", size = 279769, upload-time = "2026-03-26T22:17:15.271Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/c8/30/a58739dd12cec0f7f761ed1efb518aed2250a407d4ed14c5a0eeee7eaaf9/google_cloud_secret_manager-2.26.0-py3-none-any.whl", hash = "sha256:940a5447a6ec9951446fd1a0f22c81a4303fde164cd747aae152c5f5c8e6723e", size = 223623, upload-time = "2025-12-18T00:29:29.311Z" }, + { url = "https://files.pythonhosted.org/packages/1f/4b/6dd1e2efd9a2e73aa847fd455a1ce375d8d3cba1a2c4f7fd69f9bf0b9dce/google_cloud_secret_manager-2.27.0-py3-none-any.whl", hash = "sha256:e5540bece65a3ad720146f3b438973faf9315109b3ffa012a58711843047a3dc", size = 225577, upload-time = "2026-03-26T22:15:19.622Z" }, ] [[package]] name = "google-cloud-spanner" -version = "3.63.0" +version = "3.64.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "google-api-core", extra = ["grpc"] }, @@ -1611,14 +1646,14 @@ dependencies = [ { name = "protobuf" }, { name = "sqlparse" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/82/ee/9ae0794d32ec271b2b2326f17d977d29801e5b960e7a0f03d721aeffe824/google_cloud_spanner-3.63.0.tar.gz", hash = "sha256:e2a4fb3bdbad4688645f455d498705d3f935b7c9011f5c94c137b77569b47a62", size = 729522, upload-time = "2026-02-13T07:35:13.593Z" } +sdist = { url = "https://files.pythonhosted.org/packages/cf/67/573b14674bd74c8f0630125e13fd52791c76e6a34f21862358913fa41742/google_cloud_spanner-3.64.0.tar.gz", hash = "sha256:02c26601eaaef6abba78efe5c55187b16550aeab0671ed0a65ab2d78bf7c019e", size = 884721, upload-time = "2026-04-01T16:14:38.479Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/ed/72/e16c4fe5a7058c5526461ade670a4bec0922bc02c2690df27300e9955925/google_cloud_spanner-3.63.0-py3-none-any.whl", hash = "sha256:6ffae0ed589bbbd2d8831495e266198f3d069005cfe65c664448c9a727c88e7b", size = 518799, upload-time = "2026-02-13T07:35:11.993Z" }, + { url = "https://files.pythonhosted.org/packages/23/93/0ae1f0edfb9d9a0fc85d234b085b1cd7a3c5444f5bb85f1315f76c654313/google_cloud_spanner-3.64.0-py3-none-any.whl", hash = "sha256:9dd8b268c511def6bef118f9d8d9cbea98509727d13388a8365d5b72e13acf7c", size = 607319, upload-time = "2026-04-01T16:14:36.224Z" }, ] [[package]] name = "google-cloud-speech" -version = "2.37.0" +version = "2.38.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "google-api-core", extra = ["grpc"] }, @@ -1627,14 +1662,14 @@ dependencies = [ { name = "proto-plus" }, { name = "protobuf" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/29/f4/ba24128f860639ac7ddef3c1bd2f44b390f3bb0386dda65b3a65948beeed/google_cloud_speech-2.37.0.tar.gz", hash = "sha256:1b2debf721954f1157fb2631d19b29fbeeba5736e58b71aaf10734d6365add59", size = 402950, upload-time = "2026-02-27T14:12:59.384Z" } +sdist = { url = "https://files.pythonhosted.org/packages/21/1f/d0122ad8af8c0608fb3168bd5030e62ce0a1fcc09c730487bc8be541874a/google_cloud_speech-2.38.0.tar.gz", hash = "sha256:1854b51cbb7957273b6ba61f4a6cf49dec8d09ec450991587897e50267eaca51", size = 406015, upload-time = "2026-03-26T22:18:54.434Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/01/c5/7a0a0f6b64cd5b23a4d573d820b03b9569730a9d3dfe5aedb00f8e8a914f/google_cloud_speech-2.37.0-py3-none-any.whl", hash = "sha256:370abd51244ffc68062d655d3063e083fad525416e0cb31737f4804e3cd8588c", size = 343295, upload-time = "2026-02-27T14:12:39.579Z" }, + { url = "https://files.pythonhosted.org/packages/01/96/008365cddc78720d65475091be929466fb16c62b47283546f8eab5ff4445/google_cloud_speech-2.38.0-py3-none-any.whl", hash = "sha256:dbccb340a750a409b0e70c48c16c8d7d5d48a87c70cce2add50f3d571f5375a0", size = 346013, upload-time = "2026-03-26T22:13:50.88Z" }, ] [[package]] name = "google-cloud-storage" -version = "3.9.0" +version = "3.10.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "google-api-core" }, @@ -1644,14 +1679,14 @@ dependencies = [ { name = "google-resumable-media" }, { name = "requests" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/f7/b1/4f0798e88285b50dfc60ed3a7de071def538b358db2da468c2e0deecbb40/google_cloud_storage-3.9.0.tar.gz", hash = "sha256:f2d8ca7db2f652be757e92573b2196e10fbc09649b5c016f8b422ad593c641cc", size = 17298544, upload-time = "2026-02-02T13:36:34.119Z" } +sdist = { url = "https://files.pythonhosted.org/packages/4c/47/205eb8e9a1739b5345843e5a425775cbdc472cc38e7eda082ba5b8d02450/google_cloud_storage-3.10.1.tar.gz", hash = "sha256:97db9aa4460727982040edd2bd13ff3d5e2260b5331ad22895802da1fc2a5286", size = 17309950, upload-time = "2026-03-23T09:35:23.409Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/46/0b/816a6ae3c9fd096937d2e5f9670558908811d57d59ddf69dd4b83b326fd1/google_cloud_storage-3.9.0-py3-none-any.whl", hash = "sha256:2dce75a9e8b3387078cbbdad44757d410ecdb916101f8ba308abf202b6968066", size = 321324, upload-time = "2026-02-02T13:36:32.271Z" }, + { url = "https://files.pythonhosted.org/packages/ad/ff/ca9ab2417fa913d75aae38bf40bf856bb2749a604b2e0f701b37cfcd23cc/google_cloud_storage-3.10.1-py3-none-any.whl", hash = "sha256:a72f656759b7b99bda700f901adcb3425a828d4a29f911bc26b3ea79c5b1217f", size = 324453, upload-time = "2026-03-23T09:35:21.368Z" }, ] [[package]] name = "google-cloud-trace" -version = "1.18.0" +version = "1.19.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "google-api-core", extra = ["grpc"] }, @@ -1660,9 +1695,9 @@ dependencies = [ { name = "proto-plus" }, { name = "protobuf" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/02/34/b1883f4682f1681941100df0e411cb0185013f7c349489ab1330348d7c5c/google_cloud_trace-1.18.0.tar.gz", hash = "sha256:46d42b90273da3bc4850bb0d6b9a205eb826a54561ff1b30ca33cc92174c3f37", size = 103347, upload-time = "2026-01-15T13:04:56.441Z" } +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/87/15/366fd8b028a50a9018c933270d220a4e53dca8022ce9086618b72978ab90/google_cloud_trace-1.18.0-py3-none-any.whl", hash = "sha256:52c002d8d3da802e031fee62cd49a1baf899932d4f548a150f685af6815b5554", size = 107488, upload-time = "2026-01-15T12:17:21.519Z" }, + { 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]] @@ -1702,7 +1737,7 @@ wheels = [ [[package]] name = "google-genai" -version = "1.66.0" +version = "1.70.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "anyio" }, @@ -1716,21 +1751,21 @@ dependencies = [ { name = "typing-extensions" }, { name = "websockets" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/9b/ba/0b343b0770d4710ad2979fd9301d7caa56c940174d5361ed4a7cc4979241/google_genai-1.66.0.tar.gz", hash = "sha256:ffc01647b65046bca6387320057aa51db0ad64bcc72c8e3e914062acfa5f7c49", size = 504386, upload-time = "2026-03-04T22:15:28.156Z" } +sdist = { url = "https://files.pythonhosted.org/packages/74/dd/28e4682904b183acbfad3fe6409f13a42f69bb8eab6e882d3bcbea1dde01/google_genai-1.70.0.tar.gz", hash = "sha256:36b67b0fc6f319e08d1f1efd808b790107b1809c8743a05d55dfcf9d9fad7719", size = 519550, upload-time = "2026-04-01T10:52:46.487Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/d1/dd/403949d922d4e261b08b64aaa132af4e456c3b15c8e2a2d9e6ef693f66e2/google_genai-1.66.0-py3-none-any.whl", hash = "sha256:7f127a39cf695277104ce4091bb26e417c59bb46e952ff3699c3a982d9c474ee", size = 732174, upload-time = "2026-03-04T22:15:26.63Z" }, + { url = "https://files.pythonhosted.org/packages/36/a3/d4564c8a9beaf6a3cef8d70fa6354318572cebfee65db4f01af0d41f45ba/google_genai-1.70.0-py3-none-any.whl", hash = "sha256:b74c24549d8b4208f4c736fd11857374788e1ffffc725de45d706e35c97fceee", size = 760584, upload-time = "2026-04-01T10:52:44.349Z" }, ] [[package]] name = "google-resumable-media" -version = "2.8.0" +version = "2.8.2" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "google-crc32c" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/64/d7/520b62a35b23038ff005e334dba3ffc75fcf583bee26723f1fd8fd4b6919/google_resumable_media-2.8.0.tar.gz", hash = "sha256:f1157ed8b46994d60a1bc432544db62352043113684d4e030ee02e77ebe9a1ae", size = 2163265, upload-time = "2025-11-17T15:38:06.659Z" } +sdist = { url = "https://files.pythonhosted.org/packages/3f/d1/b1ea14b93b6b78f57fc580125de44e9f593ab88dd2460f1a8a8d18f74754/google_resumable_media-2.8.2.tar.gz", hash = "sha256:f3354a182ebd193ae3f42e3ef95e6c9b10f128320de23ac7637236713b1acd70", size = 2164510, upload-time = "2026-03-30T23:34:25.369Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/1f/0b/93afde9cfe012260e9fe1522f35c9b72d6ee222f316586b1f23ecf44d518/google_resumable_media-2.8.0-py3-none-any.whl", hash = "sha256:dd14a116af303845a8d932ddae161a26e86cc229645bc98b39f026f9b1717582", size = 81340, upload-time = "2025-11-17T15:38:05.594Z" }, + { url = "https://files.pythonhosted.org/packages/5e/f8/50bfaf4658431ff9de45c5c3935af7ab01157a4903c603cd0eee6e78e087/google_resumable_media-2.8.2-py3-none-any.whl", hash = "sha256:82b6d8ccd11765268cdd2a2123f417ec806b8eef3000a9a38dfe3033da5fb220", size = 81511, upload-time = "2026-03-30T23:34:09.671Z" }, ] [[package]] @@ -1830,28 +1865,28 @@ wheels = [ [[package]] name = "griffe" -version = "1.14.0" +version = "1.15.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "colorama" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/ec/d7/6c09dd7ce4c7837e4cdb11dce980cb45ae3cd87677298dc3b781b6bce7d3/griffe-1.14.0.tar.gz", hash = "sha256:9d2a15c1eca966d68e00517de5d69dd1bc5c9f2335ef6c1775362ba5b8651a13", size = 424684, upload-time = "2025-09-05T15:02:29.167Z" } +sdist = { url = "https://files.pythonhosted.org/packages/0d/0c/3a471b6e31951dce2360477420d0a8d1e00dea6cf33b70f3e8c3ab6e28e1/griffe-1.15.0.tar.gz", hash = "sha256:7726e3afd6f298fbc3696e67958803e7ac843c1cfe59734b6251a40cdbfb5eea", size = 424112, upload-time = "2025-11-10T15:03:15.52Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/2a/b1/9ff6578d789a89812ff21e4e0f80ffae20a65d5dd84e7a17873fe3b365be/griffe-1.14.0-py3-none-any.whl", hash = "sha256:0e9d52832cccf0f7188cfe585ba962d2674b241c01916d780925df34873bceb0", size = 144439, upload-time = "2025-09-05T15:02:27.511Z" }, + { url = "https://files.pythonhosted.org/packages/9c/83/3b1d03d36f224edded98e9affd0467630fc09d766c0e56fb1498cbb04a9b/griffe-1.15.0-py3-none-any.whl", hash = "sha256:6f6762661949411031f5fcda9593f586e6ce8340f0ba88921a0f2ef7a81eb9a3", size = 150705, upload-time = "2025-11-10T15:03:13.549Z" }, ] [[package]] name = "grpc-google-iam-v1" -version = "0.14.3" +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/76/1e/1011451679a983f2f5c6771a1682542ecb027776762ad031fd0d7129164b/grpc_google_iam_v1-0.14.3.tar.gz", hash = "sha256:879ac4ef33136c5491a6300e27575a9ec760f6cdf9a2518798c1b8977a5dc389", size = 23745, upload-time = "2025-10-15T21:14:53.318Z" } +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/4a/bd/330a1bbdb1afe0b96311249e699b6dc9cfc17916394fd4503ac5aca2514b/grpc_google_iam_v1-0.14.3-py3-none-any.whl", hash = "sha256:7a7f697e017a067206a3dfef44e4c634a34d3dee135fe7d7a4613fe3e59217e6", size = 32690, upload-time = "2025-10-15T21:14:51.72Z" }, + { 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]] @@ -1868,140 +1903,140 @@ wheels = [ [[package]] name = "grpcio" -version = "1.75.1" +version = "1.80.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/9d/f7/8963848164c7604efb3a3e6ee457fdb3a469653e19002bd24742473254f8/grpcio-1.75.1.tar.gz", hash = "sha256:3e81d89ece99b9ace23a6916880baca613c03a799925afb2857887efa8b1b3d2", size = 12731327, upload-time = "2025-09-26T09:03:36.887Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/51/57/89fd829fb00a6d0bee3fbcb2c8a7aa0252d908949b6ab58bfae99d39d77e/grpcio-1.75.1-cp310-cp310-linux_armv7l.whl", hash = "sha256:1712b5890b22547dd29f3215c5788d8fc759ce6dd0b85a6ba6e2731f2d04c088", size = 5705534, upload-time = "2025-09-26T09:00:52.225Z" }, - { url = "https://files.pythonhosted.org/packages/76/dd/2f8536e092551cf804e96bcda79ecfbc51560b214a0f5b7ebc253f0d4664/grpcio-1.75.1-cp310-cp310-macosx_11_0_universal2.whl", hash = "sha256:8d04e101bba4b55cea9954e4aa71c24153ba6182481b487ff376da28d4ba46cf", size = 11484103, upload-time = "2025-09-26T09:00:59.457Z" }, - { url = "https://files.pythonhosted.org/packages/9a/3d/affe2fb897804c98d56361138e73786af8f4dd876b9d9851cfe6342b53c8/grpcio-1.75.1-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:683cfc70be0c1383449097cba637317e4737a357cfc185d887fd984206380403", size = 6289953, upload-time = "2025-09-26T09:01:03.699Z" }, - { url = "https://files.pythonhosted.org/packages/87/aa/0f40b7f47a0ff10d7e482bc3af22dac767c7ff27205915f08962d5ca87a2/grpcio-1.75.1-cp310-cp310-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:491444c081a54dcd5e6ada57314321ae526377f498d4aa09d975c3241c5b9e1c", size = 6949785, upload-time = "2025-09-26T09:01:07.504Z" }, - { url = "https://files.pythonhosted.org/packages/a5/45/b04407e44050781821c84f26df71b3f7bc469923f92f9f8bc27f1406dbcc/grpcio-1.75.1-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:ce08d4e112d0d38487c2b631ec8723deac9bc404e9c7b1011426af50a79999e4", size = 6465708, upload-time = "2025-09-26T09:01:11.028Z" }, - { url = "https://files.pythonhosted.org/packages/09/3e/4ae3ec0a4d20dcaafbb6e597defcde06399ccdc5b342f607323f3b47f0a3/grpcio-1.75.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:5a2acda37fc926ccc4547977ac3e56b1df48fe200de968e8c8421f6e3093df6c", size = 7100912, upload-time = "2025-09-26T09:01:14.393Z" }, - { url = "https://files.pythonhosted.org/packages/34/3f/a9085dab5c313bb0cb853f222d095e2477b9b8490a03634cdd8d19daa5c3/grpcio-1.75.1-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:745c5fe6bf05df6a04bf2d11552c7d867a2690759e7ab6b05c318a772739bd75", size = 8042497, upload-time = "2025-09-26T09:01:17.759Z" }, - { url = "https://files.pythonhosted.org/packages/c3/87/ea54eba931ab9ed3f999ba95f5d8d01a20221b664725bab2fe93e3dee848/grpcio-1.75.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:259526a7159d39e2db40d566fe3e8f8e034d0fb2db5bf9c00e09aace655a4c2b", size = 7493284, upload-time = "2025-09-26T09:01:20.896Z" }, - { url = "https://files.pythonhosted.org/packages/b7/5e/287f1bf1a998f4ac46ef45d518de3b5da08b4e86c7cb5e1108cee30b0282/grpcio-1.75.1-cp310-cp310-win32.whl", hash = "sha256:f4b29b9aabe33fed5df0a85e5f13b09ff25e2c05bd5946d25270a8bd5682dac9", size = 3950809, upload-time = "2025-09-26T09:01:23.695Z" }, - { url = "https://files.pythonhosted.org/packages/a4/a2/3cbfc06a4ec160dc77403b29ecb5cf76ae329eb63204fea6a7c715f1dfdb/grpcio-1.75.1-cp310-cp310-win_amd64.whl", hash = "sha256:cf2e760978dcce7ff7d465cbc7e276c3157eedc4c27aa6de7b594c7a295d3d61", size = 4644704, upload-time = "2025-09-26T09:01:25.763Z" }, - { url = "https://files.pythonhosted.org/packages/0c/3c/35ca9747473a306bfad0cee04504953f7098527cd112a4ab55c55af9e7bd/grpcio-1.75.1-cp311-cp311-linux_armv7l.whl", hash = "sha256:573855ca2e58e35032aff30bfbd1ee103fbcf4472e4b28d4010757700918e326", size = 5709761, upload-time = "2025-09-26T09:01:28.528Z" }, - { url = "https://files.pythonhosted.org/packages/c9/2c/ecbcb4241e4edbe85ac2663f885726fea0e947767401288b50d8fdcb9200/grpcio-1.75.1-cp311-cp311-macosx_11_0_universal2.whl", hash = "sha256:6a4996a2c8accc37976dc142d5991adf60733e223e5c9a2219e157dc6a8fd3a2", size = 11496691, upload-time = "2025-09-26T09:01:31.214Z" }, - { url = "https://files.pythonhosted.org/packages/81/40/bc07aee2911f0d426fa53fe636216100c31a8ea65a400894f280274cb023/grpcio-1.75.1-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:b1ea1bbe77ecbc1be00af2769f4ae4a88ce93be57a4f3eebd91087898ed749f9", size = 6296084, upload-time = "2025-09-26T09:01:34.596Z" }, - { url = "https://files.pythonhosted.org/packages/b8/d1/10c067f6c67396cbf46448b80f27583b5e8c4b46cdfbe18a2a02c2c2f290/grpcio-1.75.1-cp311-cp311-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:e5b425aee54cc5e3e3c58f00731e8a33f5567965d478d516d35ef99fd648ab68", size = 6950403, upload-time = "2025-09-26T09:01:36.736Z" }, - { url = "https://files.pythonhosted.org/packages/3f/42/5f628abe360b84dfe8dd8f32be6b0606dc31dc04d3358eef27db791ea4d5/grpcio-1.75.1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:0049a7bf547dafaeeb1db17079ce79596c298bfe308fc084d023c8907a845b9a", size = 6470166, upload-time = "2025-09-26T09:01:39.474Z" }, - { url = "https://files.pythonhosted.org/packages/c3/93/a24035080251324019882ee2265cfde642d6476c0cf8eb207fc693fcebdc/grpcio-1.75.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:5b8ea230c7f77c0a1a3208a04a1eda164633fb0767b4cefd65a01079b65e5b1f", size = 7107828, upload-time = "2025-09-26T09:01:41.782Z" }, - { url = "https://files.pythonhosted.org/packages/e4/f8/d18b984c1c9ba0318e3628dbbeb6af77a5007f02abc378c845070f2d3edd/grpcio-1.75.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:36990d629c3c9fb41e546414e5af52d0a7af37ce7113d9682c46d7e2919e4cca", size = 8045421, upload-time = "2025-09-26T09:01:45.835Z" }, - { url = "https://files.pythonhosted.org/packages/7e/b6/4bf9aacff45deca5eac5562547ed212556b831064da77971a4e632917da3/grpcio-1.75.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:b10ad908118d38c2453ade7ff790e5bce36580c3742919007a2a78e3a1e521ca", size = 7503290, upload-time = "2025-09-26T09:01:49.28Z" }, - { url = "https://files.pythonhosted.org/packages/3b/15/d8d69d10223cb54c887a2180bd29fe5fa2aec1d4995c8821f7aa6eaf72e4/grpcio-1.75.1-cp311-cp311-win32.whl", hash = "sha256:d6be2b5ee7bea656c954dcf6aa8093c6f0e6a3ef9945c99d99fcbfc88c5c0bfe", size = 3950631, upload-time = "2025-09-26T09:01:51.23Z" }, - { url = "https://files.pythonhosted.org/packages/8a/40/7b8642d45fff6f83300c24eaac0380a840e5e7fe0e8d80afd31b99d7134e/grpcio-1.75.1-cp311-cp311-win_amd64.whl", hash = "sha256:61c692fb05956b17dd6d1ab480f7f10ad0536dba3bc8fd4e3c7263dc244ed772", size = 4646131, upload-time = "2025-09-26T09:01:53.266Z" }, - { url = "https://files.pythonhosted.org/packages/3a/81/42be79e73a50aaa20af66731c2defeb0e8c9008d9935a64dd8ea8e8c44eb/grpcio-1.75.1-cp312-cp312-linux_armv7l.whl", hash = "sha256:7b888b33cd14085d86176b1628ad2fcbff94cfbbe7809465097aa0132e58b018", size = 5668314, upload-time = "2025-09-26T09:01:55.424Z" }, - { url = "https://files.pythonhosted.org/packages/c5/a7/3686ed15822fedc58c22f82b3a7403d9faf38d7c33de46d4de6f06e49426/grpcio-1.75.1-cp312-cp312-macosx_11_0_universal2.whl", hash = "sha256:8775036efe4ad2085975531d221535329f5dac99b6c2a854a995456098f99546", size = 11476125, upload-time = "2025-09-26T09:01:57.927Z" }, - { url = "https://files.pythonhosted.org/packages/14/85/21c71d674f03345ab183c634ecd889d3330177e27baea8d5d247a89b6442/grpcio-1.75.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:bb658f703468d7fbb5dcc4037c65391b7dc34f808ac46ed9136c24fc5eeb041d", size = 6246335, upload-time = "2025-09-26T09:02:00.76Z" }, - { url = "https://files.pythonhosted.org/packages/fd/db/3beb661bc56a385ae4fa6b0e70f6b91ac99d47afb726fe76aaff87ebb116/grpcio-1.75.1-cp312-cp312-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:4b7177a1cdb3c51b02b0c0a256b0a72fdab719600a693e0e9037949efffb200b", size = 6916309, upload-time = "2025-09-26T09:02:02.894Z" }, - { url = "https://files.pythonhosted.org/packages/1e/9c/eda9fe57f2b84343d44c1b66cf3831c973ba29b078b16a27d4587a1fdd47/grpcio-1.75.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:7d4fa6ccc3ec2e68a04f7b883d354d7fea22a34c44ce535a2f0c0049cf626ddf", size = 6435419, upload-time = "2025-09-26T09:02:05.055Z" }, - { url = "https://files.pythonhosted.org/packages/c3/b8/090c98983e0a9d602e3f919a6e2d4e470a8b489452905f9a0fa472cac059/grpcio-1.75.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:3d86880ecaeb5b2f0a8afa63824de93adb8ebe4e49d0e51442532f4e08add7d6", size = 7064893, upload-time = "2025-09-26T09:02:07.275Z" }, - { url = "https://files.pythonhosted.org/packages/ec/c0/6d53d4dbbd00f8bd81571f5478d8a95528b716e0eddb4217cc7cb45aae5f/grpcio-1.75.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:a8041d2f9e8a742aeae96f4b047ee44e73619f4f9d24565e84d5446c623673b6", size = 8011922, upload-time = "2025-09-26T09:02:09.527Z" }, - { url = "https://files.pythonhosted.org/packages/f2/7c/48455b2d0c5949678d6982c3e31ea4d89df4e16131b03f7d5c590811cbe9/grpcio-1.75.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:3652516048bf4c314ce12be37423c79829f46efffb390ad64149a10c6071e8de", size = 7466181, upload-time = "2025-09-26T09:02:12.279Z" }, - { url = "https://files.pythonhosted.org/packages/fd/12/04a0e79081e3170b6124f8cba9b6275871276be06c156ef981033f691880/grpcio-1.75.1-cp312-cp312-win32.whl", hash = "sha256:44b62345d8403975513af88da2f3d5cc76f73ca538ba46596f92a127c2aea945", size = 3938543, upload-time = "2025-09-26T09:02:14.77Z" }, - { url = "https://files.pythonhosted.org/packages/5f/d7/11350d9d7fb5adc73d2b0ebf6ac1cc70135577701e607407fe6739a90021/grpcio-1.75.1-cp312-cp312-win_amd64.whl", hash = "sha256:b1e191c5c465fa777d4cafbaacf0c01e0d5278022082c0abbd2ee1d6454ed94d", size = 4641938, upload-time = "2025-09-26T09:02:16.927Z" }, - { url = "https://files.pythonhosted.org/packages/46/74/bac4ab9f7722164afdf263ae31ba97b8174c667153510322a5eba4194c32/grpcio-1.75.1-cp313-cp313-linux_armv7l.whl", hash = "sha256:3bed22e750d91d53d9e31e0af35a7b0b51367e974e14a4ff229db5b207647884", size = 5672779, upload-time = "2025-09-26T09:02:19.11Z" }, - { url = "https://files.pythonhosted.org/packages/a6/52/d0483cfa667cddaa294e3ab88fd2c2a6e9dc1a1928c0e5911e2e54bd5b50/grpcio-1.75.1-cp313-cp313-macosx_11_0_universal2.whl", hash = "sha256:5b8f381eadcd6ecaa143a21e9e80a26424c76a0a9b3d546febe6648f3a36a5ac", size = 11470623, upload-time = "2025-09-26T09:02:22.117Z" }, - { url = "https://files.pythonhosted.org/packages/cf/e4/d1954dce2972e32384db6a30273275e8c8ea5a44b80347f9055589333b3f/grpcio-1.75.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:5bf4001d3293e3414d0cf99ff9b1139106e57c3a66dfff0c5f60b2a6286ec133", size = 6248838, upload-time = "2025-09-26T09:02:26.426Z" }, - { url = "https://files.pythonhosted.org/packages/06/43/073363bf63826ba8077c335d797a8d026f129dc0912b69c42feaf8f0cd26/grpcio-1.75.1-cp313-cp313-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:9f82ff474103e26351dacfe8d50214e7c9322960d8d07ba7fa1d05ff981c8b2d", size = 6922663, upload-time = "2025-09-26T09:02:28.724Z" }, - { url = "https://files.pythonhosted.org/packages/c2/6f/076ac0df6c359117676cacfa8a377e2abcecec6a6599a15a672d331f6680/grpcio-1.75.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:0ee119f4f88d9f75414217823d21d75bfe0e6ed40135b0cbbfc6376bc9f7757d", size = 6436149, upload-time = "2025-09-26T09:02:30.971Z" }, - { url = "https://files.pythonhosted.org/packages/6b/27/1d08824f1d573fcb1fa35ede40d6020e68a04391709939e1c6f4193b445f/grpcio-1.75.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:664eecc3abe6d916fa6cf8dd6b778e62fb264a70f3430a3180995bf2da935446", size = 7067989, upload-time = "2025-09-26T09:02:33.233Z" }, - { url = "https://files.pythonhosted.org/packages/c6/98/98594cf97b8713feb06a8cb04eeef60b4757e3e2fb91aa0d9161da769843/grpcio-1.75.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:c32193fa08b2fbebf08fe08e84f8a0aad32d87c3ad42999c65e9449871b1c66e", size = 8010717, upload-time = "2025-09-26T09:02:36.011Z" }, - { url = "https://files.pythonhosted.org/packages/8c/7e/bb80b1bba03c12158f9254762cdf5cced4a9bc2e8ed51ed335915a5a06ef/grpcio-1.75.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:5cebe13088b9254f6e615bcf1da9131d46cfa4e88039454aca9cb65f639bd3bc", size = 7463822, upload-time = "2025-09-26T09:02:38.26Z" }, - { url = "https://files.pythonhosted.org/packages/23/1c/1ea57fdc06927eb5640f6750c697f596f26183573069189eeaf6ef86ba2d/grpcio-1.75.1-cp313-cp313-win32.whl", hash = "sha256:4b4c678e7ed50f8ae8b8dbad15a865ee73ce12668b6aaf411bf3258b5bc3f970", size = 3938490, upload-time = "2025-09-26T09:02:40.268Z" }, - { url = "https://files.pythonhosted.org/packages/4b/24/fbb8ff1ccadfbf78ad2401c41aceaf02b0d782c084530d8871ddd69a2d49/grpcio-1.75.1-cp313-cp313-win_amd64.whl", hash = "sha256:5573f51e3f296a1bcf71e7a690c092845fb223072120f4bdb7a5b48e111def66", size = 4642538, upload-time = "2025-09-26T09:02:42.519Z" }, - { url = "https://files.pythonhosted.org/packages/f2/1b/9a0a5cecd24302b9fdbcd55d15ed6267e5f3d5b898ff9ac8cbe17ee76129/grpcio-1.75.1-cp314-cp314-linux_armv7l.whl", hash = "sha256:c05da79068dd96723793bffc8d0e64c45f316248417515f28d22204d9dae51c7", size = 5673319, upload-time = "2025-09-26T09:02:44.742Z" }, - { url = "https://files.pythonhosted.org/packages/c6/ec/9d6959429a83fbf5df8549c591a8a52bb313976f6646b79852c4884e3225/grpcio-1.75.1-cp314-cp314-macosx_11_0_universal2.whl", hash = "sha256:06373a94fd16ec287116a825161dca179a0402d0c60674ceeec8c9fba344fe66", size = 11480347, upload-time = "2025-09-26T09:02:47.539Z" }, - { url = "https://files.pythonhosted.org/packages/09/7a/26da709e42c4565c3d7bf999a9569da96243ce34a8271a968dee810a7cf1/grpcio-1.75.1-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:4484f4b7287bdaa7a5b3980f3c7224c3c622669405d20f69549f5fb956ad0421", size = 6254706, upload-time = "2025-09-26T09:02:50.4Z" }, - { url = "https://files.pythonhosted.org/packages/f1/08/dcb26a319d3725f199c97e671d904d84ee5680de57d74c566a991cfab632/grpcio-1.75.1-cp314-cp314-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:2720c239c1180eee69f7883c1d4c83fc1a495a2535b5fa322887c70bf02b16e8", size = 6922501, upload-time = "2025-09-26T09:02:52.711Z" }, - { url = "https://files.pythonhosted.org/packages/78/66/044d412c98408a5e23cb348845979a2d17a2e2b6c3c34c1ec91b920f49d0/grpcio-1.75.1-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:07a554fa31c668cf0e7a188678ceeca3cb8fead29bbe455352e712ec33ca701c", size = 6437492, upload-time = "2025-09-26T09:02:55.542Z" }, - { url = "https://files.pythonhosted.org/packages/4e/9d/5e3e362815152aa1afd8b26ea613effa005962f9da0eec6e0e4527e7a7d1/grpcio-1.75.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:3e71a2105210366bfc398eef7f57a664df99194f3520edb88b9c3a7e46ee0d64", size = 7081061, upload-time = "2025-09-26T09:02:58.261Z" }, - { url = "https://files.pythonhosted.org/packages/1e/1a/46615682a19e100f46e31ddba9ebc297c5a5ab9ddb47b35443ffadb8776c/grpcio-1.75.1-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:8679aa8a5b67976776d3c6b0521e99d1c34db8a312a12bcfd78a7085cb9b604e", size = 8010849, upload-time = "2025-09-26T09:03:00.548Z" }, - { url = "https://files.pythonhosted.org/packages/67/8e/3204b94ac30b0f675ab1c06540ab5578660dc8b690db71854d3116f20d00/grpcio-1.75.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:aad1c774f4ebf0696a7f148a56d39a3432550612597331792528895258966dc0", size = 7464478, upload-time = "2025-09-26T09:03:03.096Z" }, - { url = "https://files.pythonhosted.org/packages/b7/97/2d90652b213863b2cf466d9c1260ca7e7b67a16780431b3eb1d0420e3d5b/grpcio-1.75.1-cp314-cp314-win32.whl", hash = "sha256:62ce42d9994446b307649cb2a23335fa8e927f7ab2cbf5fcb844d6acb4d85f9c", size = 4012672, upload-time = "2025-09-26T09:03:05.477Z" }, - { url = "https://files.pythonhosted.org/packages/f9/df/e2e6e9fc1c985cd1a59e6996a05647c720fe8a03b92f5ec2d60d366c531e/grpcio-1.75.1-cp314-cp314-win_amd64.whl", hash = "sha256:f86e92275710bea3000cb79feca1762dc0ad3b27830dd1a74e82ab321d4ee464", size = 4772475, upload-time = "2025-09-26T09:03:07.661Z" }, +sdist = { url = "https://files.pythonhosted.org/packages/b7/48/af6173dbca4454f4637a4678b67f52ca7e0c1ed7d5894d89d434fecede05/grpcio-1.80.0.tar.gz", hash = "sha256:29aca15edd0688c22ba01d7cc01cb000d72b2033f4a3c72a81a19b56fd143257", size = 12978905, upload-time = "2026-03-30T08:49:10.502Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/9d/cd/bb7b7e54084a344c03d68144450da7ddd5564e51a298ae1662de65f48e2d/grpcio-1.80.0-cp310-cp310-linux_armv7l.whl", hash = "sha256:886457a7768e408cdce226ad1ca67d2958917d306523a0e21e1a2fdaa75c9c9c", size = 6050363, upload-time = "2026-03-30T08:46:20.894Z" }, + { url = "https://files.pythonhosted.org/packages/16/02/1417f5c3460dea65f7a2e3c14e8b31e77f7ffb730e9bfadd89eda7a9f477/grpcio-1.80.0-cp310-cp310-macosx_11_0_universal2.whl", hash = "sha256:7b641fc3f1dc647bfd80bd713addc68f6d145956f64677e56d9ebafc0bd72388", size = 12026037, upload-time = "2026-03-30T08:46:25.144Z" }, + { url = "https://files.pythonhosted.org/packages/43/98/c910254eedf2cae368d78336a2de0678e66a7317d27c02522392f949b5c6/grpcio-1.80.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:33eb763f18f006dc7fee1e69831d38d23f5eccd15b2e0f92a13ee1d9242e5e02", size = 6602306, upload-time = "2026-03-30T08:46:27.593Z" }, + { url = "https://files.pythonhosted.org/packages/7c/f8/88ca4e78c077b2b2113d95da1e1ab43efd43d723c9a0397d26529c2c1a56/grpcio-1.80.0-cp310-cp310-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:52d143637e3872633fc7dd7c3c6a1c84e396b359f3a72e215f8bf69fd82084fc", size = 7301535, upload-time = "2026-03-30T08:46:29.556Z" }, + { url = "https://files.pythonhosted.org/packages/f9/96/f28660fe2fe0f153288bf4a04e4910b7309d442395135c88ed4f5b3b8b40/grpcio-1.80.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:c51bf8ac4575af2e0678bccfb07e47321fc7acb5049b4482832c5c195e04e13a", size = 6808669, upload-time = "2026-03-30T08:46:31.984Z" }, + { url = "https://files.pythonhosted.org/packages/47/eb/3f68a5e955779c00aeef23850e019c1c1d0e032d90633ba49c01ad5a96e0/grpcio-1.80.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:50a9871536d71c4fba24ee856abc03a87764570f0c457dd8db0b4018f379fed9", size = 7409489, upload-time = "2026-03-30T08:46:34.684Z" }, + { url = "https://files.pythonhosted.org/packages/5b/a7/d2f681a4bfb881be40659a309771f3bdfbfdb1190619442816c3f0ffc079/grpcio-1.80.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:a72d84ad0514db063e21887fbacd1fd7acb4d494a564cae22227cd45c7fbf199", size = 8423167, upload-time = "2026-03-30T08:46:36.833Z" }, + { url = "https://files.pythonhosted.org/packages/97/8a/29b4589c204959aa35ce5708400a05bba72181807c45c47b3ec000c39333/grpcio-1.80.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:f7691a6788ad9196872f95716df5bc643ebba13c97140b7a5ee5c8e75d1dea81", size = 7846761, upload-time = "2026-03-30T08:46:40.091Z" }, + { url = "https://files.pythonhosted.org/packages/6b/d2/ed143e097230ee121ac5848f6ff14372dba91289b10b536d54fb1b7cbae7/grpcio-1.80.0-cp310-cp310-win32.whl", hash = "sha256:46c2390b59d67f84e882694d489f5b45707c657832d7934859ceb8c33f467069", size = 4156534, upload-time = "2026-03-30T08:46:42.026Z" }, + { url = "https://files.pythonhosted.org/packages/d5/c9/df8279bb49b29409995e95efa85b72973d62f8aeff89abee58c91f393710/grpcio-1.80.0-cp310-cp310-win_amd64.whl", hash = "sha256:dc053420fc75749c961e2a4c906398d7c15725d36ccc04ae6d16093167223b58", size = 4889869, upload-time = "2026-03-30T08:46:44.219Z" }, + { url = "https://files.pythonhosted.org/packages/5d/db/1d56e5f5823257b291962d6c0ce106146c6447f405b60b234c4f222a7cde/grpcio-1.80.0-cp311-cp311-linux_armv7l.whl", hash = "sha256:dfab85db094068ff42e2a3563f60ab3dddcc9d6488a35abf0132daec13209c8a", size = 6055009, upload-time = "2026-03-30T08:46:46.265Z" }, + { url = "https://files.pythonhosted.org/packages/6e/18/c83f3cad64c5ca63bca7e91e5e46b0d026afc5af9d0a9972472ceba294b3/grpcio-1.80.0-cp311-cp311-macosx_11_0_universal2.whl", hash = "sha256:5c07e82e822e1161354e32da2662f741a4944ea955f9f580ec8fb409dd6f6060", size = 12035295, upload-time = "2026-03-30T08:46:49.099Z" }, + { url = "https://files.pythonhosted.org/packages/0f/8e/e14966b435be2dda99fbe89db9525ea436edc79780431a1c2875a3582644/grpcio-1.80.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:ba0915d51fd4ced2db5ff719f84e270afe0e2d4c45a7bdb1e8d036e4502928c2", size = 6610297, upload-time = "2026-03-30T08:46:52.123Z" }, + { url = "https://files.pythonhosted.org/packages/cc/26/d5eb38f42ce0e3fdc8174ea4d52036ef8d58cc4426cb800f2610f625dd75/grpcio-1.80.0-cp311-cp311-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:3cb8130ba457d2aa09fa6b7c3ed6b6e4e6a2685fce63cb803d479576c4d80e21", size = 7300208, upload-time = "2026-03-30T08:46:54.859Z" }, + { url = "https://files.pythonhosted.org/packages/25/51/bd267c989f85a17a5b3eea65a6feb4ff672af41ca614e5a0279cc0ea381c/grpcio-1.80.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:09e5e478b3d14afd23f12e49e8b44c8684ac3c5f08561c43a5b9691c54d136ab", size = 6813442, upload-time = "2026-03-30T08:46:57.056Z" }, + { url = "https://files.pythonhosted.org/packages/9e/d9/d80eef735b19e9169e30164bbf889b46f9df9127598a83d174eb13a48b26/grpcio-1.80.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:00168469238b022500e486c1c33916acf2f2a9b2c022202cf8a1885d2e3073c1", size = 7414743, upload-time = "2026-03-30T08:46:59.682Z" }, + { url = "https://files.pythonhosted.org/packages/de/f2/567f5bd5054398ed6b0509b9a30900376dcf2786bd936812098808b49d8d/grpcio-1.80.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:8502122a3cc1714038e39a0b071acb1207ca7844208d5ea0d091317555ee7106", size = 8426046, upload-time = "2026-03-30T08:47:02.474Z" }, + { url = "https://files.pythonhosted.org/packages/62/29/73ef0141b4732ff5eacd68430ff2512a65c004696997f70476a83e548e7e/grpcio-1.80.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:ce1794f4ea6cc3ca29463f42d665c32ba1b964b48958a66497917fe9069f26e6", size = 7851641, upload-time = "2026-03-30T08:47:05.462Z" }, + { url = "https://files.pythonhosted.org/packages/46/69/abbfa360eb229a8623bab5f5a4f8105e445bd38ce81a89514ba55d281ad0/grpcio-1.80.0-cp311-cp311-win32.whl", hash = "sha256:51b4a7189b0bef2aa30adce3c78f09c83526cf3dddb24c6a96555e3b97340440", size = 4154368, upload-time = "2026-03-30T08:47:08.027Z" }, + { url = "https://files.pythonhosted.org/packages/6f/d4/ae92206d01183b08613e846076115f5ac5991bae358d2a749fa864da5699/grpcio-1.80.0-cp311-cp311-win_amd64.whl", hash = "sha256:02e64bb0bb2da14d947a49e6f120a75e947250aebe65f9629b62bb1f5c14e6e9", size = 4894235, upload-time = "2026-03-30T08:47:10.839Z" }, + { url = "https://files.pythonhosted.org/packages/5c/e8/a2b749265eb3415abc94f2e619bbd9e9707bebdda787e61c593004ec927a/grpcio-1.80.0-cp312-cp312-linux_armv7l.whl", hash = "sha256:c624cc9f1008361014378c9d776de7182b11fe8b2e5a81bc69f23a295f2a1ad0", size = 6015616, upload-time = "2026-03-30T08:47:13.428Z" }, + { url = "https://files.pythonhosted.org/packages/3e/97/b1282161a15d699d1e90c360df18d19165a045ce1c343c7f313f5e8a0b77/grpcio-1.80.0-cp312-cp312-macosx_11_0_universal2.whl", hash = "sha256:f49eddcac43c3bf350c0385366a58f36bed8cc2c0ec35ef7b74b49e56552c0c2", size = 12014204, upload-time = "2026-03-30T08:47:15.873Z" }, + { url = "https://files.pythonhosted.org/packages/6e/5e/d319c6e997b50c155ac5a8cb12f5173d5b42677510e886d250d50264949d/grpcio-1.80.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:d334591df610ab94714048e0d5b4f3dd5ad1bee74dfec11eee344220077a79de", size = 6563866, upload-time = "2026-03-30T08:47:18.588Z" }, + { url = "https://files.pythonhosted.org/packages/ae/f6/fdd975a2cb4d78eb67769a7b3b3830970bfa2e919f1decf724ae4445f42c/grpcio-1.80.0-cp312-cp312-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:0cb517eb1d0d0aaf1d87af7cc5b801d686557c1d88b2619f5e31fab3c2315921", size = 7273060, upload-time = "2026-03-30T08:47:21.113Z" }, + { url = "https://files.pythonhosted.org/packages/db/f0/a3deb5feba60d9538a962913e37bd2e69a195f1c3376a3dd44fe0427e996/grpcio-1.80.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:4e78c4ac0d97dc2e569b2f4bcbbb447491167cb358d1a389fc4af71ab6f70411", size = 6782121, upload-time = "2026-03-30T08:47:23.827Z" }, + { url = "https://files.pythonhosted.org/packages/ca/84/36c6dcfddc093e108141f757c407902a05085e0c328007cb090d56646cdf/grpcio-1.80.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:2ed770b4c06984f3b47eb0517b1c69ad0b84ef3f40128f51448433be904634cd", size = 7383811, upload-time = "2026-03-30T08:47:26.517Z" }, + { url = "https://files.pythonhosted.org/packages/7c/ef/f3a77e3dc5b471a0ec86c564c98d6adfa3510d38f8ee99010410858d591e/grpcio-1.80.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:256507e2f524092f1473071a05e65a5b10d84b82e3ff24c5b571513cfaa61e2f", size = 8393860, upload-time = "2026-03-30T08:47:29.439Z" }, + { url = "https://files.pythonhosted.org/packages/9b/8d/9d4d27ed7f33d109c50d6b5ce578a9914aa68edab75d65869a17e630a8d1/grpcio-1.80.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:9a6284a5d907c37db53350645567c522be314bac859a64a7a5ca63b77bb7958f", size = 7830132, upload-time = "2026-03-30T08:47:33.254Z" }, + { url = "https://files.pythonhosted.org/packages/14/e4/9990b41c6d7a44e1e9dee8ac11d7a9802ba1378b40d77468a7761d1ad288/grpcio-1.80.0-cp312-cp312-win32.whl", hash = "sha256:c71309cfce2f22be26aa4a847357c502db6c621f1a49825ae98aa0907595b193", size = 4140904, upload-time = "2026-03-30T08:47:35.319Z" }, + { url = "https://files.pythonhosted.org/packages/2f/2c/296f6138caca1f4b92a31ace4ae1b87dab692fc16a7a3417af3bb3c805bf/grpcio-1.80.0-cp312-cp312-win_amd64.whl", hash = "sha256:9fe648599c0e37594c4809d81a9e77bd138cc82eb8baa71b6a86af65426723ff", size = 4880944, upload-time = "2026-03-30T08:47:37.831Z" }, + { url = "https://files.pythonhosted.org/packages/2f/3a/7c3c25789e3f069e581dc342e03613c5b1cb012c4e8c7d9d5cf960a75856/grpcio-1.80.0-cp313-cp313-linux_armv7l.whl", hash = "sha256:e9e408fc016dffd20661f0126c53d8a31c2821b5c13c5d67a0f5ed5de93319ad", size = 6017243, upload-time = "2026-03-30T08:47:40.075Z" }, + { url = "https://files.pythonhosted.org/packages/04/19/21a9806eb8240e174fd1ab0cd5b9aa948bb0e05c2f2f55f9d5d7405e6d08/grpcio-1.80.0-cp313-cp313-macosx_11_0_universal2.whl", hash = "sha256:92d787312e613754d4d8b9ca6d3297e69994a7912a32fa38c4c4e01c272974b0", size = 12010840, upload-time = "2026-03-30T08:47:43.11Z" }, + { url = "https://files.pythonhosted.org/packages/18/3a/23347d35f76f639e807fb7a36fad3068aed100996849a33809591f26eca6/grpcio-1.80.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:8ac393b58aa16991a2f1144ec578084d544038c12242da3a215966b512904d0f", size = 6567644, upload-time = "2026-03-30T08:47:46.806Z" }, + { url = "https://files.pythonhosted.org/packages/ff/40/96e07ecb604a6a67ae6ab151e3e35b132875d98bc68ec65f3e5ab3e781d7/grpcio-1.80.0-cp313-cp313-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:68e5851ac4b9afe07e7f84483803ad167852570d65326b34d54ca560bfa53fb6", size = 7277830, upload-time = "2026-03-30T08:47:49.643Z" }, + { url = "https://files.pythonhosted.org/packages/9b/e2/da1506ecea1f34a5e365964644b35edef53803052b763ca214ba3870c856/grpcio-1.80.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:873ff5d17d68992ef6605330127425d2fc4e77e612fa3c3e0ed4e668685e3140", size = 6783216, upload-time = "2026-03-30T08:47:52.817Z" }, + { url = "https://files.pythonhosted.org/packages/44/83/3b20ff58d0c3b7f6caaa3af9a4174d4023701df40a3f39f7f1c8e7c48f9d/grpcio-1.80.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:2bea16af2750fd0a899bf1abd9022244418b55d1f37da2202249ba4ba673838d", size = 7385866, upload-time = "2026-03-30T08:47:55.687Z" }, + { url = "https://files.pythonhosted.org/packages/47/45/55c507599c5520416de5eefecc927d6a0d7af55e91cfffb2e410607e5744/grpcio-1.80.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:ba0db34f7e1d803a878284cd70e4c63cb6ae2510ba51937bf8f45ba997cefcf7", size = 8391602, upload-time = "2026-03-30T08:47:58.303Z" }, + { url = "https://files.pythonhosted.org/packages/10/bb/dd06f4c24c01db9cf11341b547d0a016b2c90ed7dbbb086a5710df7dd1d7/grpcio-1.80.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:8eb613f02d34721f1acf3626dfdb3545bd3c8505b0e52bf8b5710a28d02e8aa7", size = 7826752, upload-time = "2026-03-30T08:48:01.311Z" }, + { url = "https://files.pythonhosted.org/packages/f9/1e/9d67992ba23371fd63d4527096eb8c6b76d74d52b500df992a3343fd7251/grpcio-1.80.0-cp313-cp313-win32.whl", hash = "sha256:93b6f823810720912fd131f561f91f5fed0fda372b6b7028a2681b8194d5d294", size = 4142310, upload-time = "2026-03-30T08:48:04.594Z" }, + { url = "https://files.pythonhosted.org/packages/cf/e6/283326a27da9e2c3038bc93eeea36fb118ce0b2d03922a9cda6688f53c5b/grpcio-1.80.0-cp313-cp313-win_amd64.whl", hash = "sha256:e172cf795a3ba5246d3529e4d34c53db70e888fa582a8ffebd2e6e48bc0cba50", size = 4882833, upload-time = "2026-03-30T08:48:07.363Z" }, + { url = "https://files.pythonhosted.org/packages/c5/6d/e65307ce20f5a09244ba9e9d8476e99fb039de7154f37fb85f26978b59c3/grpcio-1.80.0-cp314-cp314-linux_armv7l.whl", hash = "sha256:3d4147a97c8344d065d01bbf8b6acec2cf86fb0400d40696c8bdad34a64ffc0e", size = 6017376, upload-time = "2026-03-30T08:48:10.005Z" }, + { url = "https://files.pythonhosted.org/packages/69/10/9cef5d9650c72625a699c549940f0abb3c4bfdb5ed45a5ce431f92f31806/grpcio-1.80.0-cp314-cp314-macosx_11_0_universal2.whl", hash = "sha256:d8e11f167935b3eb089ac9038e1a063e6d7dbe995c0bb4a661e614583352e76f", size = 12018133, upload-time = "2026-03-30T08:48:12.927Z" }, + { url = "https://files.pythonhosted.org/packages/04/82/983aabaad82ba26113caceeb9091706a0696b25da004fe3defb5b346e15b/grpcio-1.80.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:f14b618fc30de822681ee986cfdcc2d9327229dc4c98aed16896761cacd468b9", size = 6574748, upload-time = "2026-03-30T08:48:16.386Z" }, + { url = "https://files.pythonhosted.org/packages/07/d7/031666ef155aa0bf399ed7e19439656c38bbd143779ae0861b038ce82abd/grpcio-1.80.0-cp314-cp314-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:4ed39fbdcf9b87370f6e8df4e39ca7b38b3e5e9d1b0013c7b6be9639d6578d14", size = 7277711, upload-time = "2026-03-30T08:48:19.627Z" }, + { url = "https://files.pythonhosted.org/packages/e8/43/f437a78f7f4f1d311804189e8f11fb311a01049b2e08557c1068d470cb2e/grpcio-1.80.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:2dcc70e9f0ba987526e8e8603a610fb4f460e42899e74e7a518bf3c68fe1bf05", size = 6785372, upload-time = "2026-03-30T08:48:22.373Z" }, + { url = "https://files.pythonhosted.org/packages/93/3d/f6558e9c6296cb4227faa5c43c54a34c68d32654b829f53288313d16a86e/grpcio-1.80.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:448c884b668b868562b1bda833c5fce6272d26e1926ec46747cda05741d302c1", size = 7395268, upload-time = "2026-03-30T08:48:25.638Z" }, + { url = "https://files.pythonhosted.org/packages/06/21/0fdd77e84720b08843c371a2efa6f2e19dbebf56adc72df73d891f5506f0/grpcio-1.80.0-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:a1dc80fe55685b4a543555e6eef975303b36c8db1023b1599b094b92aa77965f", size = 8392000, upload-time = "2026-03-30T08:48:28.974Z" }, + { url = "https://files.pythonhosted.org/packages/f5/68/67f4947ed55d2e69f2cc199ab9fd85e0a0034d813bbeef84df6d2ba4d4b7/grpcio-1.80.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:31b9ac4ad1aa28ffee5503821fafd09e4da0a261ce1c1281c6c8da0423c83b6e", size = 7828477, upload-time = "2026-03-30T08:48:32.054Z" }, + { url = "https://files.pythonhosted.org/packages/44/b6/8d4096691b2e385e8271911a0de4f35f0a6c7d05aff7098e296c3de86939/grpcio-1.80.0-cp314-cp314-win32.whl", hash = "sha256:367ce30ba67d05e0592470428f0ec1c31714cab9ef19b8f2e37be1f4c7d32fae", size = 4218563, upload-time = "2026-03-30T08:48:34.538Z" }, + { 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.75.1" +version = "1.80.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "googleapis-common-protos" }, { name = "grpcio" }, { name = "protobuf" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/74/5b/1ce0e3eedcdc08b4739b3da5836f31142ec8bee1a9ae0ad8dc0dc39a14bf/grpcio_status-1.75.1.tar.gz", hash = "sha256:8162afa21833a2085c91089cc395ad880fac1378a1d60233d976649ed724cbf8", size = 13671, upload-time = "2025-09-26T09:13:16.412Z" } +sdist = { url = "https://files.pythonhosted.org/packages/b1/ed/105f619bdd00cb47a49aa2feea6232ea2bbb04199d52a22cc6a7d603b5cb/grpcio_status-1.80.0.tar.gz", hash = "sha256:df73802a4c89a3ea88aa2aff971e886fccce162bc2e6511408b3d67a144381cd", size = 13901, upload-time = "2026-03-30T08:54:34.784Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/d8/ad/6f414bb0b36eee20d93af6907256f208ffcda992ae6d3d7b6a778afe31e6/grpcio_status-1.75.1-py3-none-any.whl", hash = "sha256:f681b301be26dcf7abf5c765d4a22e4098765e1a65cbdfa3efca384edf8e4e3c", size = 14428, upload-time = "2025-09-26T09:12:55.516Z" }, + { url = "https://files.pythonhosted.org/packages/76/80/58cd2dfc19a07d022abe44bde7c365627f6c7cb6f692ada6c65ca437d09a/grpcio_status-1.80.0-py3-none-any.whl", hash = "sha256:4b56990363af50dbf2c2ebb80f1967185c07d87aa25aa2bea45ddb75fc181dbe", size = 14638, upload-time = "2026-03-30T08:54:01.569Z" }, ] [[package]] name = "grpcio-tools" -version = "1.75.1" +version = "1.80.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "grpcio" }, { name = "protobuf" }, { name = "setuptools" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/7d/76/0cd2a2bb379275c319544a3ab613dc3cea7a167503908c1b4de55f82bd9e/grpcio_tools-1.75.1.tar.gz", hash = "sha256:bb78960cf3d58941e1fec70cbdaccf255918beed13c34112a6915a6d8facebd1", size = 5390470, upload-time = "2025-09-26T09:10:11.948Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/26/b7/7d1b0b7669f993a6a393083a876937f478ca034c283eb23baf6720d8c85a/grpcio_tools-1.75.1-cp310-cp310-linux_armv7l.whl", hash = "sha256:ae0f04d5ec8b8e13476bf516a08fc1de4e58c6bf79f99123a6b964ca7d02c790", size = 2545419, upload-time = "2025-09-26T09:07:44.432Z" }, - { url = "https://files.pythonhosted.org/packages/3e/c0/db5d052d1ba5e859c833d1366960d784c0b44c8330012717aeaa123b6b9f/grpcio_tools-1.75.1-cp310-cp310-macosx_11_0_universal2.whl", hash = "sha256:24a881ad7292e904fc256892b647da17d9137ef2e72faf8b7c8e515314ad1377", size = 5841650, upload-time = "2025-09-26T09:07:50.987Z" }, - { url = "https://files.pythonhosted.org/packages/af/13/ab49230ef106f2b9de156a813bc14049e6fd4fe9c26fa0cde496f0e86a09/grpcio_tools-1.75.1-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:1b5810ace274dba12ecfac69ac32c8047c6ee0200a23274cb4885ed4187271f8", size = 2591560, upload-time = "2025-09-26T09:07:52.777Z" }, - { url = "https://files.pythonhosted.org/packages/29/fd/1fd3069fb0559c2f90d85b0fd3a73adc3f63966c6300fee01e4e52740229/grpcio_tools-1.75.1-cp310-cp310-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:ab33993288b97b1180e092fa447a8ce00fbc8c59d67b23553245b88d14fe36bb", size = 2904895, upload-time = "2025-09-26T09:07:55.002Z" }, - { url = "https://files.pythonhosted.org/packages/d6/51/e58fae40132a4589819c388333545a33a89f91b8affcac45623ace9ca659/grpcio_tools-1.75.1-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:4cac693621043ef11d3ab2318e811d919779f8cd5011ba8e37f44c178c831d94", size = 2656151, upload-time = "2025-09-26T09:07:56.762Z" }, - { url = "https://files.pythonhosted.org/packages/39/c9/a33736c2a8ceee39991f2c9f67a426ab799c6caf09145120bae6080428d5/grpcio_tools-1.75.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:a09cd5d267b296af67116fe098633ad770bc8c19831a5f3c896f65fad90c1064", size = 3105152, upload-time = "2025-09-26T09:07:58.702Z" }, - { url = "https://files.pythonhosted.org/packages/ac/71/2f09cbe321f057a47a8ae4dacf004bbe8a171fd712b8f7f689ec7b2f1c49/grpcio_tools-1.75.1-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:dff4bcb4d16cf9ef745c1984394ed15187e6c23d73d71377377deaf443d11358", size = 3654551, upload-time = "2025-09-26T09:08:00.87Z" }, - { url = "https://files.pythonhosted.org/packages/05/54/91481a5b96cab2a81326ab1041fd7cfc6b6ce0cd82bab14ebcdb6ed78d4e/grpcio_tools-1.75.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:16d5986b37e2a9203f85e456c7ff8705b932718021d408adfe4a79e0f4d95949", size = 3322220, upload-time = "2025-09-26T09:08:02.724Z" }, - { url = "https://files.pythonhosted.org/packages/a2/07/272955f15a35ef0069ebe17a5fc14282c6dc6690edeb4dbe6a81dd2d1efb/grpcio_tools-1.75.1-cp310-cp310-win32.whl", hash = "sha256:3fbac14998bfadc6b9140b6339dbc5f673700ebb4d45ba0c4d4fbe0ffb8559a9", size = 992986, upload-time = "2025-09-26T09:08:04.6Z" }, - { url = "https://files.pythonhosted.org/packages/16/9a/482b05c1277b3385be7e426f000efb921ce3ae76bcb8aa4f9b9f724c58d3/grpcio_tools-1.75.1-cp310-cp310-win_amd64.whl", hash = "sha256:b56e495844eb899de721eb77d9e077192bdeb40842f598481d32a8f6de3db124", size = 1157427, upload-time = "2025-09-26T09:08:06.246Z" }, - { url = "https://files.pythonhosted.org/packages/45/28/71ab934662d41ded4e451d9af0ec6f9aade3525e470fdfd10bd20e588e44/grpcio_tools-1.75.1-cp311-cp311-linux_armv7l.whl", hash = "sha256:f0635231feb70a9d551452829943a1a5fa651283e7a300aadc22df5ea5da696f", size = 2545461, upload-time = "2025-09-26T09:08:08.514Z" }, - { url = "https://files.pythonhosted.org/packages/69/40/d90f6fdb51f51b2a518401207b3920fcfdfa996ed7bca844096f111ed839/grpcio_tools-1.75.1-cp311-cp311-macosx_11_0_universal2.whl", hash = "sha256:626293296ef7e2d87ab1a80b81a55eef91883c65b59a97576099a28b9535100b", size = 5842958, upload-time = "2025-09-26T09:08:11.468Z" }, - { url = "https://files.pythonhosted.org/packages/b4/b7/52e6f32fd0101e3ac9c654a6441b254ba5874f146b543b20afbcb8246947/grpcio_tools-1.75.1-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:071339d90f1faab332ce4919c815a10b9c3ed2c09473f550f686bf9cc148579f", size = 2591669, upload-time = "2025-09-26T09:08:13.481Z" }, - { url = "https://files.pythonhosted.org/packages/0a/3c/115c59a5c0c8e9d7d99a40bac8d5e91c05b6735b3bb185265d40e9fc4346/grpcio_tools-1.75.1-cp311-cp311-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:44195f58c052fa935b78c7438c85cbcd4b273dd685028e4f6d4d7b30d47daad1", size = 2904952, upload-time = "2025-09-26T09:08:15.299Z" }, - { url = "https://files.pythonhosted.org/packages/a9/cd/d2a3583a5b1d71da88f7998f20fb5a0b6fe5bb96bb916a610c29269063b6/grpcio_tools-1.75.1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:860fafdb85726029d646c99859ff7bdca5aae61b5ff038c3bd355fc1ec6b2764", size = 2656311, upload-time = "2025-09-26T09:08:17.094Z" }, - { url = "https://files.pythonhosted.org/packages/aa/09/67b9215d39add550e430c9677bd43c9a315da07ab62fa3a5f44f1cf5bb75/grpcio_tools-1.75.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:4559547a0cb3d3db1b982eea87d4656036339b400f48127fef932210672fb59e", size = 3105583, upload-time = "2025-09-26T09:08:19.179Z" }, - { url = "https://files.pythonhosted.org/packages/98/d7/d400b90812470f3dc2466964e62fc03592de46b5c824c82ef5303be60167/grpcio_tools-1.75.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:9af65a310807d7f36a8f7cddea142fe97d6dffba74444f38870272f2e5a3a06b", size = 3654677, upload-time = "2025-09-26T09:08:21.227Z" }, - { url = "https://files.pythonhosted.org/packages/9c/93/edf6de71b4f936b3f09461a3286db1f902c6366c5de06ef19a8c2523034a/grpcio_tools-1.75.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:8c1de31aefc0585d2f915a7cd0994d153547495b8d79c44c58048a3ede0b65be", size = 3322147, upload-time = "2025-09-26T09:08:23.08Z" }, - { url = "https://files.pythonhosted.org/packages/80/00/0f8c6204e34070e7d4f344b27e4b1b0320dfdd94574f79738a43504d182e/grpcio_tools-1.75.1-cp311-cp311-win32.whl", hash = "sha256:efaf95fcaa5d3ac1bcfe44ceed9e2512eb95b5c8c476569bdbbe2bee4b59c8a9", size = 993388, upload-time = "2025-09-26T09:08:24.708Z" }, - { url = "https://files.pythonhosted.org/packages/b0/ae/6f738154980f606293988a64ef4bb0ea2bb12029a4529464aac56fe2ab99/grpcio_tools-1.75.1-cp311-cp311-win_amd64.whl", hash = "sha256:7cefe76fc35c825f0148d60d2294a527053d0f5dd6a60352419214a8c53223c9", size = 1157907, upload-time = "2025-09-26T09:08:26.537Z" }, - { url = "https://files.pythonhosted.org/packages/ef/a7/581bb204d19a347303ed5e25b19f7d8c6365a28c242fca013d1d6d78ad7e/grpcio_tools-1.75.1-cp312-cp312-linux_armv7l.whl", hash = "sha256:49b68936cf212052eeafa50b824e17731b78d15016b235d36e0d32199000b14c", size = 2546099, upload-time = "2025-09-26T09:08:28.794Z" }, - { url = "https://files.pythonhosted.org/packages/9f/59/ab65998eba14ff9d292c880f6a276fe7d0571bba3bb4ddf66aca1f8438b5/grpcio_tools-1.75.1-cp312-cp312-macosx_11_0_universal2.whl", hash = "sha256:08cb6e568e58b76a2178ad3b453845ff057131fff00f634d7e15dcd015cd455b", size = 5839838, upload-time = "2025-09-26T09:08:31.038Z" }, - { url = "https://files.pythonhosted.org/packages/7e/65/7027f71069b4c1e8c7b46de8c46c297c9d28ef6ed4ea0161e8c82c75d1d0/grpcio_tools-1.75.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:168402ad29a249092673079cf46266936ec2fb18d4f854d96e9c5fa5708efa39", size = 2592916, upload-time = "2025-09-26T09:08:33.216Z" }, - { url = "https://files.pythonhosted.org/packages/0f/84/1abfb3c679b78c7fca7524031cf9de4c4c509c441b48fd26291ac16dd1af/grpcio_tools-1.75.1-cp312-cp312-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:bbae11c29fcf450730f021bfc14b12279f2f985e2e493ccc2f133108728261db", size = 2905276, upload-time = "2025-09-26T09:08:35.691Z" }, - { url = "https://files.pythonhosted.org/packages/99/cd/7f9e05f1eddccb61bc0ead1e49eb2222441957b02ed11acfcd2f795b03a8/grpcio_tools-1.75.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:38c6c7d5d4800f636ee691cd073db1606d1a6a76424ca75c9b709436c9c20439", size = 2656424, upload-time = "2025-09-26T09:08:38.255Z" }, - { url = "https://files.pythonhosted.org/packages/29/1d/8b7852771c2467728341f7b9c3ca4ebc76e4e23485c6a3e6d97a8323ad2a/grpcio_tools-1.75.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:626f6a61a8f141dde9a657775854d1c0d99509f9a2762b82aa401a635f6ec73d", size = 3108985, upload-time = "2025-09-26T09:08:40.291Z" }, - { url = "https://files.pythonhosted.org/packages/c2/6a/069da89cdf2e97e4558bfceef5b60bf0ef200c443b465e7691869006dd32/grpcio_tools-1.75.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:f61a8334ae38d4f98c744a732b89527e5af339d17180e25fff0676060f8709b7", size = 3657940, upload-time = "2025-09-26T09:08:42.437Z" }, - { url = "https://files.pythonhosted.org/packages/c3/e4/ca8dae800c084beb89e2720346f70012d36dfb9df02d8eacd518c06cf4a0/grpcio_tools-1.75.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:bd0c3fb40d89a1e24a41974e77c7331e80396ab7cde39bc396a13d6b5e2a750b", size = 3324878, upload-time = "2025-09-26T09:08:45.083Z" }, - { url = "https://files.pythonhosted.org/packages/58/06/cbe923679309bf970923f4a11351ea9e485291b504d7243130fdcfdcb03f/grpcio_tools-1.75.1-cp312-cp312-win32.whl", hash = "sha256:004bc5327593eea48abd03be3188e757c3ca0039079587a6aac24275127cac20", size = 993071, upload-time = "2025-09-26T09:08:46.785Z" }, - { url = "https://files.pythonhosted.org/packages/7c/0c/84d6be007262c5d88a590082f3a1fe62d4b0eeefa10c6cdb3548f3663e80/grpcio_tools-1.75.1-cp312-cp312-win_amd64.whl", hash = "sha256:23952692160b5fe7900653dfdc9858dc78c2c42e15c27e19ee780c8917ba6028", size = 1157506, upload-time = "2025-09-26T09:08:48.844Z" }, - { url = "https://files.pythonhosted.org/packages/47/fa/624bbe1b2ccf4f6044bf3cd314fe2c35f78f702fcc2191dc65519baddca4/grpcio_tools-1.75.1-cp313-cp313-linux_armv7l.whl", hash = "sha256:ca9e116aab0ecf4365fc2980f2e8ae1b22273c3847328b9a8e05cbd14345b397", size = 2545752, upload-time = "2025-09-26T09:08:51.433Z" }, - { url = "https://files.pythonhosted.org/packages/b9/4c/6d884e2337feff0a656e395338019adecc3aa1daeae9d7e8eb54340d4207/grpcio_tools-1.75.1-cp313-cp313-macosx_11_0_universal2.whl", hash = "sha256:9fe87a926b65eb7f41f8738b6d03677cc43185ff77a9d9b201bdb2f673f3fa1e", size = 5838163, upload-time = "2025-09-26T09:08:53.858Z" }, - { url = "https://files.pythonhosted.org/packages/d1/2a/2ba7b6911a754719643ed92ae816a7f989af2be2882b9a9e1f90f4b0e882/grpcio_tools-1.75.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:45503a6094f91b3fd31c3d9adef26ac514f102086e2a37de797e220a6791ee87", size = 2592148, upload-time = "2025-09-26T09:08:55.86Z" }, - { url = "https://files.pythonhosted.org/packages/88/db/fa613a45c3c7b00f905bd5ad3a93c73194724d0a2dd72adae3be32983343/grpcio_tools-1.75.1-cp313-cp313-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:b01b60b3de67be531a39fd869d7613fa8f178aff38c05e4d8bc2fc530fa58cb5", size = 2905215, upload-time = "2025-09-26T09:08:58.27Z" }, - { url = "https://files.pythonhosted.org/packages/d7/0c/ee4786972bb82f60e4f313bb2227c79c2cd20eb13c94c0263067923cfd12/grpcio_tools-1.75.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:09e2b9b9488735514777d44c1e4eda813122d2c87aad219f98d5d49b359a8eab", size = 2656251, upload-time = "2025-09-26T09:09:00.249Z" }, - { url = "https://files.pythonhosted.org/packages/77/f1/cc5a50658d705d0b71ff8a4fbbfcc6279d3c95731a2ef7285e13dc40e2fe/grpcio_tools-1.75.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:55e60300e62b220fabe6f062fe69f143abaeff3335f79b22b56d86254f3c3c80", size = 3108911, upload-time = "2025-09-26T09:09:02.515Z" }, - { url = "https://files.pythonhosted.org/packages/09/d8/43545f77c4918e778e90bc2c02b3462ac71cee14f29d85cdb69b089538eb/grpcio_tools-1.75.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:49ce00fcc6facbbf52bf376e55b8e08810cecd03dab0b3a2986d73117c6f6ee4", size = 3657021, upload-time = "2025-09-26T09:09:05.331Z" }, - { url = "https://files.pythonhosted.org/packages/fc/0b/2ae5925374b66bc8df5b828eff1a5f9459349c83dae1773f0aa9858707e6/grpcio_tools-1.75.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:71e95479aea868f8c8014d9dc4267f26ee75388a0d8a552e1648cfa0b53d24b4", size = 3324450, upload-time = "2025-09-26T09:09:07.867Z" }, - { url = "https://files.pythonhosted.org/packages/6e/53/9f887bacbecf892ac5b0b282477ca8cfa5b73911b04259f0d88b52e9a055/grpcio_tools-1.75.1-cp313-cp313-win32.whl", hash = "sha256:fff9d2297416eae8861e53154ccf70a19994e5935e6c8f58ebf431f81cbd8d12", size = 992434, upload-time = "2025-09-26T09:09:09.966Z" }, - { url = "https://files.pythonhosted.org/packages/a5/f0/9979d97002edffdc2a88e5f2e0dccea396dd4a6eab34fa2f705fe43eae2f/grpcio_tools-1.75.1-cp313-cp313-win_amd64.whl", hash = "sha256:1849ddd508143eb48791e81d42ddc924c554d1b4900e06775a927573a8d4267f", size = 1157069, upload-time = "2025-09-26T09:09:12.287Z" }, - { url = "https://files.pythonhosted.org/packages/a6/0b/4ff4ead293f2b016668628a240937828444094778c8037d2bbef700e9097/grpcio_tools-1.75.1-cp314-cp314-linux_armv7l.whl", hash = "sha256:f281b594489184b1f9a337cdfed1fc1ddb8428f41c4b4023de81527e90b38e1e", size = 2545868, upload-time = "2025-09-26T09:09:14.716Z" }, - { url = "https://files.pythonhosted.org/packages/0e/78/aa6bf73a18de5357c01ef87eea92150931586b25196fa4df197a37bae11d/grpcio_tools-1.75.1-cp314-cp314-macosx_11_0_universal2.whl", hash = "sha256:becf8332f391abc62bf4eea488b63be063d76a7cf2ef00b2e36c617d9ee9216b", size = 5838010, upload-time = "2025-09-26T09:09:20.415Z" }, - { url = "https://files.pythonhosted.org/packages/99/65/7eaad673bc971af45e079d3b13c20d9ba9842b8788d31953e3234c2e2cee/grpcio_tools-1.75.1-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:a08330f24e5cd7b39541882a95a8ba04ffb4df79e2984aa0cd01ed26dcdccf49", size = 2593170, upload-time = "2025-09-26T09:09:22.889Z" }, - { url = "https://files.pythonhosted.org/packages/e4/db/57e1e29e9186c7ed223ce8a9b609d3f861c4db015efb643dfe60b403c137/grpcio_tools-1.75.1-cp314-cp314-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:6bf3742bd8f102630072ed317d1496f31c454cd85ad19d37a68bd85bf9d5f8b9", size = 2905167, upload-time = "2025-09-26T09:09:25.96Z" }, - { url = "https://files.pythonhosted.org/packages/cd/7b/894f891f3cf19812192f8bbf1e0e1c958055676ecf0a5466a350730a006d/grpcio_tools-1.75.1-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:f26028949474feb380460ce52d9d090d00023940c65236294a66c42ac5850e8b", size = 2656210, upload-time = "2025-09-26T09:09:28.786Z" }, - { url = "https://files.pythonhosted.org/packages/99/76/8e48427da93ef243c09629969c7b5a2c59dceb674b6b623c1f5fbaa5c8c5/grpcio_tools-1.75.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:1bd68fb98bf08f11b6c3210834a14eefe585bad959bdba38e78b4ae3b04ba5bd", size = 3109226, upload-time = "2025-09-26T09:09:31.307Z" }, - { url = "https://files.pythonhosted.org/packages/b3/7e/ecf71c316c2a88c2478b7c6372d0f82d05f07edbf0f31b6da613df99ec7c/grpcio_tools-1.75.1-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:f1496e21586193da62c3a73cd16f9c63c5b3efd68ff06dab96dbdfefa90d40bf", size = 3657139, upload-time = "2025-09-26T09:09:35.043Z" }, - { url = "https://files.pythonhosted.org/packages/6f/f3/b2613e81da2085f40a989c0601ec9efc11e8b32fcb71b1234b64a18af830/grpcio_tools-1.75.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:14a78b1e36310cdb3516cdf9ee2726107875e0b247e2439d62fc8dc38cf793c1", size = 3324513, upload-time = "2025-09-26T09:09:37.44Z" }, - { url = "https://files.pythonhosted.org/packages/9a/1f/2df4fa8634542524bc22442ffe045d41905dae62cc5dd14408b80c5ac1b8/grpcio_tools-1.75.1-cp314-cp314-win32.whl", hash = "sha256:0e6f916daf222002fb98f9a6f22de0751959e7e76a24941985cc8e43cea77b50", size = 1015283, upload-time = "2025-09-26T09:09:39.461Z" }, - { url = "https://files.pythonhosted.org/packages/23/4f/f27c973ff50486a70be53a3978b6b0244398ca170a4e19d91988b5295d92/grpcio_tools-1.75.1-cp314-cp314-win_amd64.whl", hash = "sha256:878c3b362264588c45eba57ce088755f8b2b54893d41cc4a68cdeea62996da5c", size = 1189364, upload-time = "2025-09-26T09:09:42.036Z" }, +sdist = { url = "https://files.pythonhosted.org/packages/94/c8/1223f29c84a143ae9a56c084fc96894de0ba84b6e8d60a26241abd81d278/grpcio_tools-1.80.0.tar.gz", hash = "sha256:26052b19c6ce0dcf52d1024496aea3e2bdfa864159f06dc7b97b22d041a94b26", size = 6133212, upload-time = "2026-03-30T08:52:39.077Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/7a/54/1de67f5080da305a258758a8deb33f85666fa759f56785042a80b114a53f/grpcio_tools-1.80.0-cp310-cp310-linux_armv7l.whl", hash = "sha256:727477b9afa4b53f5ec70cafb41c3965d893835e0d4ea9b542fe3d0d005602bf", size = 2549601, upload-time = "2026-03-30T08:50:09.498Z" }, + { url = "https://files.pythonhosted.org/packages/9a/b4/6d57ea199c5b880d182a2234aafa9a686f9c54c708ea7be75bd19d5aa825/grpcio_tools-1.80.0-cp310-cp310-macosx_11_0_universal2.whl", hash = "sha256:85fe8d15f146c62cb76f38d963e256392d287442b9232717d30ae9e3bbda9bc3", size = 5712717, upload-time = "2026-03-30T08:50:15.028Z" }, + { url = "https://files.pythonhosted.org/packages/6a/1a/5505ee2277d368b409c796c78f22ea34a2a517b7d16755247efd663dc7af/grpcio_tools-1.80.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:95f0fffb5ca00519f3b602f938169b4dfa04b165e03258323965a9dfe8cc4d80", size = 2595941, upload-time = "2026-03-30T08:50:17.299Z" }, + { url = "https://files.pythonhosted.org/packages/4e/39/7fc1d16d8b767805079d76365d73e82c88dfaf179034473dbc9fbccedb77/grpcio_tools-1.80.0-cp310-cp310-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:7a0106af212748823a6ebd8ffbd9043414216f47cae3835f3187de0a62c415d3", size = 2909304, upload-time = "2026-03-30T08:50:19.485Z" }, + { url = "https://files.pythonhosted.org/packages/97/d8/276ee759755d8f34f2ca5e9d2debd1a59f29f66059fb790bc369f2236c26/grpcio_tools-1.80.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:31fd01a4038b5dfc4ec79504a17061344f670f851833411717fef66920f13cd7", size = 2660269, upload-time = "2026-03-30T08:50:21.266Z" }, + { url = "https://files.pythonhosted.org/packages/51/04/a6bb47942ad52901d777a649324d3203cf19d487f1d446263637f7a5bf12/grpcio_tools-1.80.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:57da9e19607fac4a01c48ead333c0dd15d91ed38794dce1194eda308f73e2038", size = 3109798, upload-time = "2026-03-30T08:50:23.267Z" }, + { url = "https://files.pythonhosted.org/packages/be/50/7ee69b2919916739787d725f205b878e8d1619dd30422b8278e324664669/grpcio_tools-1.80.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:90968f751851abb8b145593609800fa70c837e1c93ba0792c480b1c8d8bc29ef", size = 3658930, upload-time = "2026-03-30T08:50:25.458Z" }, + { url = "https://files.pythonhosted.org/packages/92/61/6d50783092b0e8bbcb04152d5388bf50ecf3ea2f783d95288ff6c3bb00fa/grpcio_tools-1.80.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:b69dc5d6376ab43406304d1e2fc61ccf960b287d4325d77c3d45448c37a9d2da", size = 3326562, upload-time = "2026-03-30T08:50:27.809Z" }, + { url = "https://files.pythonhosted.org/packages/ea/58/d272ba549f6b1f0d8504f5fc4cd0a296f2c495a64d6e987fe871c4151557/grpcio_tools-1.80.0-cp310-cp310-win32.whl", hash = "sha256:3e8dcfebe34cb54df095de3d5871a4562a85a29f26d0f8bb41ee2c3dcfb11c3c", size = 997620, upload-time = "2026-03-30T08:50:29.959Z" }, + { url = "https://files.pythonhosted.org/packages/70/5f/9f45a9946a0298711c72ca48b2c1f46a7d0c207a44cd3e4bb59d04556ba3/grpcio_tools-1.80.0-cp310-cp310-win_amd64.whl", hash = "sha256:fc622ed4ca400695f41c9eae3266276c6ba007e4c28164ce53b44e7ccc5e492b", size = 1162466, upload-time = "2026-03-30T08:50:32.242Z" }, + { url = "https://files.pythonhosted.org/packages/8a/d7/225dc91e6cb4f8d4830f16a478a468e9c6f342dcdf8cacc3772cc1d1f607/grpcio_tools-1.80.0-cp311-cp311-linux_armv7l.whl", hash = "sha256:1c43e5c768578fe0c6de3dbfaabe64af642951e1aa05c487cacedda63fa6c6c4", size = 2549937, upload-time = "2026-03-30T08:50:34.651Z" }, + { url = "https://files.pythonhosted.org/packages/97/3d/a3684cb7677f3bea8db434eae02a9ce30135d7a268cd473b1bc8041c4722/grpcio_tools-1.80.0-cp311-cp311-macosx_11_0_universal2.whl", hash = "sha256:a225348456575f3ac7851d8e23163195e76d2a905ee340cf73f33da62fba08aa", size = 5713099, upload-time = "2026-03-30T08:50:37.158Z" }, + { url = "https://files.pythonhosted.org/packages/b1/81/5665c697173ec346076358bfbfed0f7386825852494593ca14386478dfee/grpcio_tools-1.80.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:a9396f02820d3f51c368c2c9dee15c55c77636c91be48a4d5c702e98d6fe0fdc", size = 2595776, upload-time = "2026-03-30T08:50:39.087Z" }, + { url = "https://files.pythonhosted.org/packages/03/4f/fb81384f08a8226fa079972ba88272ac6277581fc72e8ab234d74c7e065b/grpcio_tools-1.80.0-cp311-cp311-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:797c08460cae16b402326eac329aec720dccf45c9f9279b95a352792eb53cf0f", size = 2909144, upload-time = "2026-03-30T08:50:40.922Z" }, + { url = "https://files.pythonhosted.org/packages/4d/9c/c957618f1c2a3195ecf5e83b03edcb364c2c1391f74183cb76e5763fa536/grpcio_tools-1.80.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:1872a867eb6217de19edb70a4ce4a374ced9d94293533dfd42fa649713f55bf4", size = 2660477, upload-time = "2026-03-30T08:50:42.766Z" }, + { url = "https://files.pythonhosted.org/packages/42/c7/23913da184febfd4eaf04de256a26bc5ff0411a5feb753e2adcff10fa86a/grpcio_tools-1.80.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:db122ba5ee357e3bb14e8944d69bbebcbdae91d5eace29ed4df3edc53cbc6528", size = 3110164, upload-time = "2026-03-30T08:50:44.761Z" }, + { url = "https://files.pythonhosted.org/packages/af/fa/b25ed85ebdb0396910eaa250b1346d75527d22fca586265416bd4330dcd5/grpcio_tools-1.80.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:ddefd48c227e6f4d640fe576fac5fb2c4a8898196f513604c8ec7671b3b3d421", size = 3658988, upload-time = "2026-03-30T08:50:47.546Z" }, + { url = "https://files.pythonhosted.org/packages/60/85/2a55147cc9645e2ed777d1afcd2dc68cb34ba6f6c726bd4378ddb001a5ea/grpcio_tools-1.80.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:970ec058fa469dd6dae6ebc687501c5da670d95dead75f62f5b0933dce2c9794", size = 3326662, upload-time = "2026-03-30T08:50:49.59Z" }, + { url = "https://files.pythonhosted.org/packages/68/ed/b05bee2a992e6f9bda81909692ea920d0896cfa05c5c9dd77ba03f2d22fb/grpcio_tools-1.80.0-cp311-cp311-win32.whl", hash = "sha256:526b4402d47a0e9b31cd6087e42b7674784617916cc73c764e0bc35ed41b4ee5", size = 997969, upload-time = "2026-03-30T08:50:51.539Z" }, + { url = "https://files.pythonhosted.org/packages/b6/9a/cb50c8270e2f6285ff2761130ae257ac4e51789ded4b9d9710ce0381814d/grpcio_tools-1.80.0-cp311-cp311-win_amd64.whl", hash = "sha256:ee101ecda7231770f6a5da1024a9a6ed587a7785f8fe23ab8283f4a1acb3ffe6", size = 1162742, upload-time = "2026-03-30T08:50:54.232Z" }, + { url = "https://files.pythonhosted.org/packages/0c/b9/65929df8c9614792db900a8e45d4997fadbd1734c827da3f0eb1f2fe4866/grpcio_tools-1.80.0-cp312-cp312-linux_armv7l.whl", hash = "sha256:d19d5a8244311947b96f749c417b32d144641c6953f1164824579e1f0a51d040", size = 2550856, upload-time = "2026-03-30T08:50:57.3Z" }, + { url = "https://files.pythonhosted.org/packages/28/17/af1557544d68d1aeca9d9ea53ed16524022d521fec6ba334ab3530e9c1a6/grpcio_tools-1.80.0-cp312-cp312-macosx_11_0_universal2.whl", hash = "sha256:fb599a3dc89ed1bb24489a2724b2f6dd4cddbbf0f7bdd69c073477bab0dc7554", size = 5710883, upload-time = "2026-03-30T08:51:00.077Z" }, + { url = "https://files.pythonhosted.org/packages/cc/48/aa9b4f7519ca972bc40d315d5c28f05ca28fa08de13d4e8b69f551b798ab/grpcio_tools-1.80.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:623ee31fc2ff7df9a987b4f3d139c30af17ce46a861ae0e25fb8c112daa32dd8", size = 2598004, upload-time = "2026-03-30T08:51:02.102Z" }, + { url = "https://files.pythonhosted.org/packages/b4/b8/b01371c119924b3beca1fe3f047b1bc2cdc66b3d37f0f3acc9d10c567a43/grpcio_tools-1.80.0-cp312-cp312-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:b46570a68378539ee2b75a5a43202561f8d753c832798b1047099e3c551cf5d6", size = 2909568, upload-time = "2026-03-30T08:51:04.159Z" }, + { url = "https://files.pythonhosted.org/packages/4f/7c/1108f7bdb58475a7e701ec89b55eb494538b6e76acd211ba0d4cc5fd28e8/grpcio_tools-1.80.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:51caf99c28999e7e0f97e9cea190c1405b7681a57bb2e0631205accd92b43fa4", size = 2660938, upload-time = "2026-03-30T08:51:06.126Z" }, + { url = "https://files.pythonhosted.org/packages/67/59/d1c0063d4cd3b85363c7044ff3e5159d6d5df96e2692a9a5312d9c8cb290/grpcio_tools-1.80.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:cdaa1c9aa8d3a87891a96700cadd29beec214711d6522818d207277f6452567c", size = 3113814, upload-time = "2026-03-30T08:51:08.834Z" }, + { url = "https://files.pythonhosted.org/packages/76/21/18d34a4efe524c903cf66b0cfa5260d81f277b6ae668b647edf795df9ce5/grpcio_tools-1.80.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:3399b5fd7b59bcffd59c6b9975a969d9f37a3c87f3e3d63c3a09c147907acb0d", size = 3662793, upload-time = "2026-03-30T08:51:11.094Z" }, + { url = "https://files.pythonhosted.org/packages/f3/40/cf2d9295a6bd593244ea703858f8fc2efd315046ca3ef7c6f9ebc5b810fa/grpcio_tools-1.80.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:9c6abc08d3485b2aac99bb58afcd31dc6cd4316ce36cf263ff09cb6df15f287f", size = 3329149, upload-time = "2026-03-30T08:51:13.066Z" }, + { url = "https://files.pythonhosted.org/packages/0d/1d/fc34b32167966df20d69429b71dfca83c48434b047a5ac4fd6cd91ca4eed/grpcio_tools-1.80.0-cp312-cp312-win32.whl", hash = "sha256:18c51e07652ac7386fcdbd11866f8d55a795de073337c12447b5805575339f74", size = 997519, upload-time = "2026-03-30T08:51:14.87Z" }, + { url = "https://files.pythonhosted.org/packages/91/98/6d6563cdf51085b75f8ec24605c6f2ce84197571878ca8ab4af949c6be2d/grpcio_tools-1.80.0-cp312-cp312-win_amd64.whl", hash = "sha256:ac6fdd42d5bb18f0d903a067e2825be172deff70cf197164b6f65676cb506c9b", size = 1162407, upload-time = "2026-03-30T08:51:16.793Z" }, + { url = "https://files.pythonhosted.org/packages/44/d9/f7887a4805939e9a85d03744b66fc02575dc1df3c3e8b4d9ec000ee7a33d/grpcio_tools-1.80.0-cp313-cp313-linux_armv7l.whl", hash = "sha256:e7046837859bbfd10b01786056145480155c16b222c9e209215b68d3be13060e", size = 2550319, upload-time = "2026-03-30T08:51:19.117Z" }, + { url = "https://files.pythonhosted.org/packages/57/5a/c8a05b32bd7203f1b9f4c0151090a2d6179d6c97692d32f2066dc29c67a6/grpcio_tools-1.80.0-cp313-cp313-macosx_11_0_universal2.whl", hash = "sha256:a447f28958a8fe84ff0d9d3d9473868feb27ee4a9c9c805e66f5b670121cec59", size = 5709681, upload-time = "2026-03-30T08:51:21.991Z" }, + { url = "https://files.pythonhosted.org/packages/82/6b/794350ed645c12c310008f97068f6a6fd927150b0d0d08aad1d909e880b1/grpcio_tools-1.80.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:75f00450e08fe648ad8a1eeb25bc52219679d54cdd02f04dfdddc747309d83f6", size = 2596820, upload-time = "2026-03-30T08:51:24.323Z" }, + { url = "https://files.pythonhosted.org/packages/f9/b2/b39e7b79f7c878135e0784a53cd7260ee77260c8c7f2c9e46bca8e05d017/grpcio_tools-1.80.0-cp313-cp313-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:3db830eaff1f2c2797328f2fa86c9dcdbd7d81af573a68db81e27afa2182a611", size = 2909193, upload-time = "2026-03-30T08:51:27.025Z" }, + { url = "https://files.pythonhosted.org/packages/10/f3/abe089b058f87f9910c9a458409505cbeb0b3e1c2d993a79721d02ee6a32/grpcio_tools-1.80.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:7982b5fe42f012686b667dda12916884de95c4b1c65ff64371fb7232a1474b23", size = 2660197, upload-time = "2026-03-30T08:51:29.392Z" }, + { url = "https://files.pythonhosted.org/packages/09/c3/3f7806ad8b731d8a89fe3c6ed496473abd1ef4c9c42c9e9a8836ce96e377/grpcio_tools-1.80.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:6451b3f4eb52d12c7f32d04bf8e0185f80521f3f088ad04b8d222b3a4819c71e", size = 3113144, upload-time = "2026-03-30T08:51:31.671Z" }, + { url = "https://files.pythonhosted.org/packages/fe/f5/415ef205e0b7e75d2a2005df6120145c4f02fda28d7b3715b55d924fe1a4/grpcio_tools-1.80.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:258bc30654a9a2236be4ca8e2ad443e2ac6db7c8cc20454d34cce60265922726", size = 3661897, upload-time = "2026-03-30T08:51:34.849Z" }, + { url = "https://files.pythonhosted.org/packages/e3/d3/2ad54764c2a9547080dd8518f4a4dc7899c7e6e747a1b1de542ce6a12066/grpcio_tools-1.80.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:865a2b8e6334c838976ab02a322cbd55c863d2eaf3c1e1a0255883c63996772a", size = 3328786, upload-time = "2026-03-30T08:51:37.265Z" }, + { url = "https://files.pythonhosted.org/packages/eb/63/23ab7db01f9630ab4f3742a2fc9fbff38b0cfc30c976114f913950664a75/grpcio_tools-1.80.0-cp313-cp313-win32.whl", hash = "sha256:f760ac1722f33e774814c37b6aa0444143f612e85088ead7447a0e9cd306a1f1", size = 997087, upload-time = "2026-03-30T08:51:39.137Z" }, + { url = "https://files.pythonhosted.org/packages/9b/af/b1c1c4423fb49cb7c8e9d2c02196b038c44160b7028b425466743c6c81fa/grpcio_tools-1.80.0-cp313-cp313-win_amd64.whl", hash = "sha256:7843b9ac6ff8ca508424d0dd968bd9a1a4559967e4a290f26be5bd6f04af2234", size = 1162167, upload-time = "2026-03-30T08:51:41.498Z" }, + { url = "https://files.pythonhosted.org/packages/0e/44/7beeee2348f9f412804f5bf80b7d13b81d522bf926a338ae3da46b2213b7/grpcio_tools-1.80.0-cp314-cp314-linux_armv7l.whl", hash = "sha256:12f950470449dbeec78317dbc090add7a00eb6ca812af7b0538ab7441e0a42c3", size = 2550303, upload-time = "2026-03-30T08:51:44.373Z" }, + { url = "https://files.pythonhosted.org/packages/2d/aa/f77dd85409a1855f8c6319ffc69d81e8c3ffe122ee3a7136653e1991d8b6/grpcio_tools-1.80.0-cp314-cp314-macosx_11_0_universal2.whl", hash = "sha256:d3f9a376a29c9adf62bb56f7ff5bc81eb4abeaf53d1e7dde5015564832901a51", size = 5709778, upload-time = "2026-03-30T08:51:47.112Z" }, + { url = "https://files.pythonhosted.org/packages/9c/7c/ab7af4883ebdfdc228b853de89fed409703955e8d47285b321a5794856bd/grpcio_tools-1.80.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:1ba1ffbf2cff71533615e2c5a138ed5569611eec9ae7f9c67b8898e127b54ac0", size = 2597928, upload-time = "2026-03-30T08:51:49.494Z" }, + { url = "https://files.pythonhosted.org/packages/22/e8/4381a963d472e3ab6690ba067ed2b1f1abf8518b10f402678bd2dcb79a54/grpcio_tools-1.80.0-cp314-cp314-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:13f60f8d9397c514c6745a967d22b5c8c698347e88deebca1ff2e1b94555e450", size = 2909333, upload-time = "2026-03-30T08:51:52.124Z" }, + { url = "https://files.pythonhosted.org/packages/94/cb/356b5fdf79dd99455b425fb16302fe60995554ceb721afbf3cf770a19208/grpcio_tools-1.80.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:88d77bad5dd3cd5e6f952c4ecdd0ee33e0c02ecfc2e4b0cbee3391ac19e0a431", size = 2660217, upload-time = "2026-03-30T08:51:55.066Z" }, + { url = "https://files.pythonhosted.org/packages/2b/d7/1752018cc2c36b2c5612051379e2e5f59f2dbe612de23e817d2f066a9487/grpcio_tools-1.80.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:017945c3e98a4ed1c4e21399781b4137fc08dfc1f802c8ace2e64ef52d32b142", size = 3113896, upload-time = "2026-03-30T08:51:57.3Z" }, + { url = "https://files.pythonhosted.org/packages/cc/17/695bbe454f70df35c03e22b48c5314683b913d3e6ed35ec90d065418c1ab/grpcio_tools-1.80.0-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:a33e265d4db803495007a6c623eafb0f6b9bb123ff4a0af89e44567dad809b88", size = 3661950, upload-time = "2026-03-30T08:51:59.867Z" }, + { url = "https://files.pythonhosted.org/packages/9c/d0/533d87629ec823c02c9169ee20228f734c264b209dcdf55268b5a14cde0a/grpcio_tools-1.80.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:6c129da370c5f85f569be2e545317dda786a60dd51d7deea29b03b0c05f6aac3", size = 3328755, upload-time = "2026-03-30T08:52:02.942Z" }, + { url = "https://files.pythonhosted.org/packages/08/a1/504d7838770c73a9761e8a8ff4869dba1146b44f297ff0ac6641481942d3/grpcio_tools-1.80.0-cp314-cp314-win32.whl", hash = "sha256:25742de5958ae4325249a37e724e7c0e5120f8e302a24a977ebd1737b48a5e97", size = 1019620, upload-time = "2026-03-30T08:52:05.342Z" }, + { url = "https://files.pythonhosted.org/packages/f3/75/8b7cd281c5cdfb4ca2c308f7e9b2799bab2be6e7a9e9212ea5a82e2aecd4/grpcio_tools-1.80.0-cp314-cp314-win_amd64.whl", hash = "sha256:bbf8eeef78fda1966f732f79c1c802fadd5cfd203d845d2af4d314d18569069c", size = 1194210, upload-time = "2026-03-30T08:52:08.105Z" }, ] [[package]] @@ -2015,17 +2050,34 @@ wheels = [ [[package]] name = "hf-xet" -version = "1.1.10" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/74/31/feeddfce1748c4a233ec1aa5b7396161c07ae1aa9b7bdbc9a72c3c7dd768/hf_xet-1.1.10.tar.gz", hash = "sha256:408aef343800a2102374a883f283ff29068055c111f003ff840733d3b715bb97", size = 487910, upload-time = "2025-09-12T20:10:27.12Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/f7/a2/343e6d05de96908366bdc0081f2d8607d61200be2ac802769c4284cc65bd/hf_xet-1.1.10-cp37-abi3-macosx_10_12_x86_64.whl", hash = "sha256:686083aca1a6669bc85c21c0563551cbcdaa5cf7876a91f3d074a030b577231d", size = 2761466, upload-time = "2025-09-12T20:10:22.836Z" }, - { url = "https://files.pythonhosted.org/packages/31/f9/6215f948ac8f17566ee27af6430ea72045e0418ce757260248b483f4183b/hf_xet-1.1.10-cp37-abi3-macosx_11_0_arm64.whl", hash = "sha256:71081925383b66b24eedff3013f8e6bbd41215c3338be4b94ba75fd75b21513b", size = 2623807, upload-time = "2025-09-12T20:10:21.118Z" }, - { url = "https://files.pythonhosted.org/packages/15/07/86397573efefff941e100367bbda0b21496ffcdb34db7ab51912994c32a2/hf_xet-1.1.10-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6b6bceb6361c80c1cc42b5a7b4e3efd90e64630bcf11224dcac50ef30a47e435", size = 3186960, upload-time = "2025-09-12T20:10:19.336Z" }, - { url = "https://files.pythonhosted.org/packages/01/a7/0b2e242b918cc30e1f91980f3c4b026ff2eedaf1e2ad96933bca164b2869/hf_xet-1.1.10-cp37-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:eae7c1fc8a664e54753ffc235e11427ca61f4b0477d757cc4eb9ae374b69f09c", size = 3087167, upload-time = "2025-09-12T20:10:17.255Z" }, - { url = "https://files.pythonhosted.org/packages/4a/25/3e32ab61cc7145b11eee9d745988e2f0f4fafda81b25980eebf97d8cff15/hf_xet-1.1.10-cp37-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:0a0005fd08f002180f7a12d4e13b22be277725bc23ed0529f8add5c7a6309c06", size = 3248612, upload-time = "2025-09-12T20:10:24.093Z" }, - { url = "https://files.pythonhosted.org/packages/2c/3d/ab7109e607ed321afaa690f557a9ada6d6d164ec852fd6bf9979665dc3d6/hf_xet-1.1.10-cp37-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:f900481cf6e362a6c549c61ff77468bd59d6dd082f3170a36acfef2eb6a6793f", size = 3353360, upload-time = "2025-09-12T20:10:25.563Z" }, - { url = "https://files.pythonhosted.org/packages/ee/0e/471f0a21db36e71a2f1752767ad77e92d8cde24e974e03d662931b1305ec/hf_xet-1.1.10-cp37-abi3-win_amd64.whl", hash = "sha256:5f54b19cc347c13235ae7ee98b330c26dd65ef1df47e5316ffb1e87713ca7045", size = 2804691, upload-time = "2025-09-12T20:10:28.433Z" }, +version = "1.4.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/53/92/ec9ad04d0b5728dca387a45af7bc98fbb0d73b2118759f5f6038b61a57e8/hf_xet-1.4.3.tar.gz", hash = "sha256:8ddedb73c8c08928c793df2f3401ec26f95be7f7e516a7bee2fbb546f6676113", size = 670477, upload-time = "2026-03-31T22:40:07.874Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/72/43/724d307b34e353da0abd476e02f72f735cdd2bc86082dee1b32ea0bfee1d/hf_xet-1.4.3-cp313-cp313t-macosx_10_12_x86_64.whl", hash = "sha256:7551659ba4f1e1074e9623996f28c3873682530aee0a846b7f2f066239228144", size = 3800935, upload-time = "2026-03-31T22:39:49.618Z" }, + { url = "https://files.pythonhosted.org/packages/2b/d2/8bee5996b699262edb87dbb54118d287c0e1b2fc78af7cdc41857ba5e3c4/hf_xet-1.4.3-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:bee693ada985e7045997f05f081d0e12c4c08bd7626dc397f8a7c487e6c04f7f", size = 3558942, upload-time = "2026-03-31T22:39:47.938Z" }, + { url = "https://files.pythonhosted.org/packages/c3/a1/e993d09cbe251196fb60812b09a58901c468127b7259d2bf0f68bf6088eb/hf_xet-1.4.3-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:21644b404bb0100fe3857892f752c4d09642586fd988e61501c95bbf44b393a3", size = 4207657, upload-time = "2026-03-31T22:39:39.69Z" }, + { url = "https://files.pythonhosted.org/packages/64/44/9eb6d21e5c34c63e5e399803a6932fa983cabdf47c0ecbcfe7ea97684b8c/hf_xet-1.4.3-cp313-cp313t-manylinux_2_28_aarch64.whl", hash = "sha256:987f09cfe418237812896a6736b81b1af02a3a6dcb4b4944425c4c4fca7a7cf8", size = 3986765, upload-time = "2026-03-31T22:39:37.936Z" }, + { url = "https://files.pythonhosted.org/packages/ea/7b/8ad6f16fdb82f5f7284a34b5ec48645bd575bdcd2f6f0d1644775909c486/hf_xet-1.4.3-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:60cf7fc43a99da0a853345cf86d23738c03983ee5249613a6305d3e57a5dca74", size = 4188162, upload-time = "2026-03-31T22:39:58.382Z" }, + { url = "https://files.pythonhosted.org/packages/1b/c4/39d6e136cbeea9ca5a23aad4b33024319222adbdc059ebcda5fc7d9d5ff4/hf_xet-1.4.3-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:2815a49a7a59f3e2edf0cf113ae88e8cb2ca2a221bf353fb60c609584f4884d4", size = 4424525, upload-time = "2026-03-31T22:40:00.225Z" }, + { url = "https://files.pythonhosted.org/packages/46/f2/adc32dae6bdbc367853118b9878139ac869419a4ae7ba07185dc31251b76/hf_xet-1.4.3-cp313-cp313t-win_amd64.whl", hash = "sha256:42ee323265f1e6a81b0e11094564fb7f7e0ec75b5105ffd91ae63f403a11931b", size = 3671610, upload-time = "2026-03-31T22:40:10.42Z" }, + { url = "https://files.pythonhosted.org/packages/e2/19/25d897dcc3f81953e0c2cde9ec186c7a0fee413eb0c9a7a9130d87d94d3a/hf_xet-1.4.3-cp313-cp313t-win_arm64.whl", hash = "sha256:27c976ba60079fb8217f485b9c5c7fcd21c90b0367753805f87cb9f3cdc4418a", size = 3528529, upload-time = "2026-03-31T22:40:09.106Z" }, + { url = "https://files.pythonhosted.org/packages/ec/36/3e8f85ca9fe09b8de2b2e10c63b3b3353d7dda88a0b3d426dffbe7b8313b/hf_xet-1.4.3-cp314-cp314t-macosx_10_12_x86_64.whl", hash = "sha256:5251d5ece3a81815bae9abab41cf7ddb7bcb8f56411bce0827f4a3071c92fdc6", size = 3801019, upload-time = "2026-03-31T22:39:56.651Z" }, + { url = "https://files.pythonhosted.org/packages/b5/9c/defb6cb1de28bccb7bd8d95f6e60f72a3d3fa4cb3d0329c26fb9a488bfe7/hf_xet-1.4.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:1feb0f3abeacee143367c326a128a2e2b60868ec12a36c225afb1d6c5a05e6d2", size = 3558746, upload-time = "2026-03-31T22:39:54.766Z" }, + { url = "https://files.pythonhosted.org/packages/c1/bd/8d001191893178ff8e826e46ad5299446e62b93cd164e17b0ffea08832ec/hf_xet-1.4.3-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:8b301fc150290ca90b4fccd079829b84bb4786747584ae08b94b4577d82fb791", size = 4207692, upload-time = "2026-03-31T22:39:46.246Z" }, + { url = "https://files.pythonhosted.org/packages/ce/48/6790b402803250e9936435613d3a78b9aaeee7973439f0918848dde58309/hf_xet-1.4.3-cp314-cp314t-manylinux_2_28_aarch64.whl", hash = "sha256:d972fbe95ddc0d3c0fc49b31a8a69f47db35c1e3699bf316421705741aab6653", size = 3986281, upload-time = "2026-03-31T22:39:44.648Z" }, + { url = "https://files.pythonhosted.org/packages/51/56/ea62552fe53db652a9099eda600b032d75554d0e86c12a73824bfedef88b/hf_xet-1.4.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:c5b48db1ee344a805a1b9bd2cda9b6b65fe77ed3787bd6e87ad5521141d317cd", size = 4187414, upload-time = "2026-03-31T22:40:04.951Z" }, + { url = "https://files.pythonhosted.org/packages/7d/f5/bc1456d4638061bea997e6d2db60a1a613d7b200e0755965ec312dc1ef79/hf_xet-1.4.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:22bdc1f5fb8b15bf2831440b91d1c9bbceeb7e10c81a12e8d75889996a5c9da8", size = 4424368, upload-time = "2026-03-31T22:40:06.347Z" }, + { url = "https://files.pythonhosted.org/packages/e4/76/ab597bae87e1f06d18d3ecb8ed7f0d3c9a37037fc32ce76233d369273c64/hf_xet-1.4.3-cp314-cp314t-win_amd64.whl", hash = "sha256:0392c79b7cf48418cd61478c1a925246cf10639f4cd9d94368d8ca1e8df9ea07", size = 3672280, upload-time = "2026-03-31T22:40:16.401Z" }, + { url = "https://files.pythonhosted.org/packages/62/05/2e462d34e23a09a74d73785dbed71cc5dbad82a72eee2ad60a72a554155d/hf_xet-1.4.3-cp314-cp314t-win_arm64.whl", hash = "sha256:681c92a07796325778a79d76c67011764ecc9042a8c3579332b61b63ae512075", size = 3528945, upload-time = "2026-03-31T22:40:14.995Z" }, + { url = "https://files.pythonhosted.org/packages/ac/9f/9c23e4a447b8f83120798f9279d0297a4d1360bdbf59ef49ebec78fe2545/hf_xet-1.4.3-cp37-abi3-macosx_10_12_x86_64.whl", hash = "sha256:d0da85329eaf196e03e90b84c2d0aca53bd4573d097a75f99609e80775f98025", size = 3805048, upload-time = "2026-03-31T22:39:53.105Z" }, + { url = "https://files.pythonhosted.org/packages/0b/f8/7aacb8e5f4a7899d39c787b5984e912e6c18b11be136ef13947d7a66d265/hf_xet-1.4.3-cp37-abi3-macosx_11_0_arm64.whl", hash = "sha256:e23717ce4186b265f69afa66e6f0069fe7efbf331546f5c313d00e123dc84583", size = 3562178, upload-time = "2026-03-31T22:39:51.295Z" }, + { url = "https://files.pythonhosted.org/packages/df/9a/a24b26dc8a65f0ecc0fe5be981a19e61e7ca963b85e062c083f3a9100529/hf_xet-1.4.3-cp37-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:fc360b70c815bf340ed56c7b8c63aacf11762a4b099b2fe2c9bd6d6068668c08", size = 4212320, upload-time = "2026-03-31T22:39:42.922Z" }, + { url = "https://files.pythonhosted.org/packages/53/60/46d493db155d2ee2801b71fb1b0fd67696359047fdd8caee2c914cc50c79/hf_xet-1.4.3-cp37-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:39f2d2e9654cd9b4319885733993807aab6de9dfbd34c42f0b78338d6617421f", size = 3991546, upload-time = "2026-03-31T22:39:41.335Z" }, + { url = "https://files.pythonhosted.org/packages/bc/f5/067363e1c96c6b17256910830d1b54099d06287e10f4ec6ec4e7e08371fc/hf_xet-1.4.3-cp37-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:49ad8a8cead2b56051aa84d7fce3e1335efe68df3cf6c058f22a65513885baac", size = 4193200, upload-time = "2026-03-31T22:40:01.936Z" }, + { url = "https://files.pythonhosted.org/packages/42/4b/53951592882d9c23080c7644542fda34a3813104e9e11fa1a7d82d419cb8/hf_xet-1.4.3-cp37-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:7716d62015477a70ea272d2d68cd7cad140f61c52ee452e133e139abfe2c17ba", size = 4429392, upload-time = "2026-03-31T22:40:03.492Z" }, + { url = "https://files.pythonhosted.org/packages/8a/21/75a6c175b4e79662ad8e62f46a40ce341d8d6b206b06b4320d07d55b188c/hf_xet-1.4.3-cp37-abi3-win_amd64.whl", hash = "sha256:6b591fcad34e272a5b02607485e4f2a1334aebf1bc6d16ce8eb1eb8978ac2021", size = 3677359, upload-time = "2026-03-31T22:40:13.619Z" }, + { url = "https://files.pythonhosted.org/packages/8a/7c/44314ecd0e89f8b2b51c9d9e5e7a60a9c1c82024ac471d415860557d3cd8/hf_xet-1.4.3-cp37-abi3-win_arm64.whl", hash = "sha256:7c2c7e20bcfcc946dc67187c203463f5e932e395845d098cc2a93f5b67ca0b47", size = 3533664, upload-time = "2026-03-31T22:40:12.152Z" }, ] [[package]] @@ -2079,21 +2131,22 @@ wheels = [ [[package]] name = "huggingface-hub" -version = "0.35.3" +version = "1.9.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "filelock", marker = "python_full_version < '3.14'" }, { name = "fsspec", marker = "python_full_version < '3.14'" }, - { name = "hf-xet", marker = "(python_full_version < '3.14' and platform_machine == 'aarch64') or (python_full_version < '3.14' and platform_machine == 'amd64') or (python_full_version < '3.14' and platform_machine == 'arm64') or (python_full_version < '3.14' and platform_machine == 'x86_64')" }, + { name = "hf-xet", marker = "(python_full_version < '3.14' and platform_machine == 'AMD64') or (python_full_version < '3.14' and platform_machine == 'aarch64') or (python_full_version < '3.14' and platform_machine == 'amd64') or (python_full_version < '3.14' and platform_machine == 'arm64') or (python_full_version < '3.14' and platform_machine == 'x86_64')" }, + { name = "httpx", marker = "python_full_version < '3.14'" }, { name = "packaging", marker = "python_full_version < '3.14'" }, { name = "pyyaml", marker = "python_full_version < '3.14'" }, - { name = "requests", marker = "python_full_version < '3.14'" }, { name = "tqdm", marker = "python_full_version < '3.14'" }, + { name = "typer", marker = "python_full_version < '3.14'" }, { name = "typing-extensions", marker = "python_full_version < '3.14'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/10/7e/a0a97de7c73671863ca6b3f61fa12518caf35db37825e43d63a70956738c/huggingface_hub-0.35.3.tar.gz", hash = "sha256:350932eaa5cc6a4747efae85126ee220e4ef1b54e29d31c3b45c5612ddf0b32a", size = 461798, upload-time = "2025-09-29T14:29:58.625Z" } +sdist = { url = "https://files.pythonhosted.org/packages/44/40/68d9b286b125d9318ae95c8f8b206e8672e7244b0eea61ebb4a88037638c/huggingface_hub-1.9.1.tar.gz", hash = "sha256:442af372207cc24dcb089caf507fcd7dbc1217c11d6059a06f6b90afe64e8bd2", size = 750355, upload-time = "2026-04-07T13:47:59.167Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/31/a0/651f93d154cb72323358bf2bbae3e642bdb5d2f1bfc874d096f7cb159fa0/huggingface_hub-0.35.3-py3-none-any.whl", hash = "sha256:0e3a01829c19d86d03793e4577816fe3bdfc1602ac62c7fb220d593d351224ba", size = 564262, upload-time = "2025-09-29T14:29:55.813Z" }, + { url = "https://files.pythonhosted.org/packages/3d/af/10a89c54937dccf6c10792770f362d96dd67aedfde108e6e1fd7a0836789/huggingface_hub-1.9.1-py3-none-any.whl", hash = "sha256:8dae771b969b318203727a6c6c5209d25e661f6f0dd010fc09cc4a12cf81c657", size = 637356, upload-time = "2026-04-07T13:47:57.239Z" }, ] [[package]] @@ -2119,36 +2172,36 @@ wheels = [ [[package]] name = "importlib-metadata" -version = "8.7.0" +version = "8.7.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "zipp" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/76/66/650a33bd90f786193e4de4b3ad86ea60b53c89b669a5c7be931fac31cdb0/importlib_metadata-8.7.0.tar.gz", hash = "sha256:d13b81ad223b890aa16c5471f2ac3056cf76c5f10f82d6f9292f0b415f389000", size = 56641, upload-time = "2025-04-27T15:29:01.736Z" } +sdist = { url = "https://files.pythonhosted.org/packages/f3/49/3b30cad09e7771a4982d9975a8cbf64f00d4a1ececb53297f1d9a7be1b10/importlib_metadata-8.7.1.tar.gz", hash = "sha256:49fef1ae6440c182052f407c8d34a68f72efc36db9ca90dc0113398f2fdde8bb", size = 57107, upload-time = "2025-12-21T10:00:19.278Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/20/b0/36bd937216ec521246249be3bf9855081de4c5e06a0c9b4219dbeda50373/importlib_metadata-8.7.0-py3-none-any.whl", hash = "sha256:e5dd1551894c77868a30651cef00984d50e1002d06942a7101d34870c5f02afd", size = 27656, upload-time = "2025-04-27T15:29:00.214Z" }, + { url = "https://files.pythonhosted.org/packages/fa/5e/f8e9a1d23b9c20a551a8a02ea3637b4642e22c2626e3a13a9a29cdea99eb/importlib_metadata-8.7.1-py3-none-any.whl", hash = "sha256:5a1f80bf1daa489495071efbb095d75a634cf28a8bc299581244063b53176151", size = 27865, upload-time = "2025-12-21T10:00:18.329Z" }, ] [[package]] name = "incremental" -version = "24.7.2" +version = "24.11.0" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "setuptools" }, + { name = "packaging" }, { name = "tomli", marker = "python_full_version < '3.11'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/27/87/156b374ff6578062965afe30cc57627d35234369b3336cf244b240c8d8e6/incremental-24.7.2.tar.gz", hash = "sha256:fb4f1d47ee60efe87d4f6f0ebb5f70b9760db2b2574c59c8e8912be4ebd464c9", size = 28157, upload-time = "2024-07-29T20:03:55.441Z" } +sdist = { url = "https://files.pythonhosted.org/packages/ef/3c/82e84109e02c492f382c711c58a3dd91badda6d746def81a1465f74dc9f5/incremental-24.11.0.tar.gz", hash = "sha256:87d3480dbb083c1d736222511a8cf380012a8176c2456d01ef483242abbbcf8c", size = 24000, upload-time = "2025-11-28T02:30:17.861Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/0d/38/221e5b2ae676a3938c2c1919131410c342b6efc2baffeda395dd66eeca8f/incremental-24.7.2-py3-none-any.whl", hash = "sha256:8cb2c3431530bec48ad70513931a760f446ad6c25e8333ca5d95e24b0ed7b8fe", size = 20516, upload-time = "2024-07-29T20:03:53.677Z" }, + { url = "https://files.pythonhosted.org/packages/1d/55/0f4df2a44053867ea9cbea73fc588b03c55605cd695cee0a3d86f0029cb2/incremental-24.11.0-py3-none-any.whl", hash = "sha256:a34450716b1c4341fe6676a0598e88a39e04189f4dce5dc96f656e040baa10b3", size = 21109, upload-time = "2025-11-28T02:30:16.442Z" }, ] [[package]] name = "iniconfig" -version = "2.1.0" +version = "2.3.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/f2/97/ebf4da567aa6827c909642694d71c9fcf53e5b504f2d96afea02718862f3/iniconfig-2.1.0.tar.gz", hash = "sha256:3abbd2e30b36733fee78f9c7f7308f2d0050e88f0087fd25c2645f63c773e1c7", size = 4793, upload-time = "2025-03-19T20:09:59.721Z" } +sdist = { url = "https://files.pythonhosted.org/packages/72/34/14ca021ce8e5dfedc35312d08ba8bf51fdd999c576889fc2c24cb97f4f10/iniconfig-2.3.0.tar.gz", hash = "sha256:c76315c77db068650d49c5b56314774a7804df16fee4402c1f19d6d15d8c4730", size = 20503, upload-time = "2025-10-18T21:55:43.219Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/2c/e1/e6716421ea10d38022b952c159d5161ca1193197fb744506875fbb87ea7b/iniconfig-2.1.0-py3-none-any.whl", hash = "sha256:9deba5723312380e77435581c6bf4935c94cbfab9b1ed33ef8d238ea168eb760", size = 6050, upload-time = "2025-03-19T20:10:01.071Z" }, + { url = "https://files.pythonhosted.org/packages/cb/b1/3846dd7f199d53cb17f49cba7e651e9ce294d8497c8c150530ed11865bb8/iniconfig-2.3.0-py3-none-any.whl", hash = "sha256:f631c04d2c48c52b84d0d0549c99ff3859c98df65b3101406327ecc7d53fbf12", size = 7484, upload-time = "2025-10-18T21:55:41.639Z" }, ] [[package]] @@ -2174,26 +2227,26 @@ wheels = [ [[package]] name = "jaraco-context" -version = "6.0.1" +version = "6.1.2" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "backports-tarfile", marker = "python_full_version < '3.12'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/df/ad/f3777b81bf0b6e7bc7514a1656d3e637b2e8e15fab2ce3235730b3e7a4e6/jaraco_context-6.0.1.tar.gz", hash = "sha256:9bae4ea555cf0b14938dc0aee7c9f32ed303aa20a3b73e7dc80111628792d1b3", size = 13912, upload-time = "2024-08-20T03:39:27.358Z" } +sdist = { url = "https://files.pythonhosted.org/packages/af/50/4763cd07e722bb6285316d390a164bc7e479db9d90daa769f22578f698b4/jaraco_context-6.1.2.tar.gz", hash = "sha256:f1a6c9d391e661cc5b8d39861ff077a7dc24dc23833ccee564b234b81c82dfe3", size = 16801, upload-time = "2026-03-20T22:13:33.922Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/ff/db/0c52c4cf5e4bd9f5d7135ec7669a3a767af21b3a308e1ed3674881e52b62/jaraco.context-6.0.1-py3-none-any.whl", hash = "sha256:f797fc481b490edb305122c9181830a3a5b76d84ef6d1aef2fb9b47ab956f9e4", size = 6825, upload-time = "2024-08-20T03:39:25.966Z" }, + { url = "https://files.pythonhosted.org/packages/f2/58/bc8954bda5fcda97bd7c19be11b85f91973d67a706ed4a3aec33e7de22db/jaraco_context-6.1.2-py3-none-any.whl", hash = "sha256:bf8150b79a2d5d91ae48629d8b427a8f7ba0e1097dd6202a9059f29a36379535", size = 7871, upload-time = "2026-03-20T22:13:32.808Z" }, ] [[package]] name = "jaraco-functools" -version = "4.3.0" +version = "4.4.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "more-itertools" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/f7/ed/1aa2d585304ec07262e1a83a9889880701079dde796ac7b1d1826f40c63d/jaraco_functools-4.3.0.tar.gz", hash = "sha256:cfd13ad0dd2c47a3600b439ef72d8615d482cedcff1632930d6f28924d92f294", size = 19755, upload-time = "2025-08-18T20:05:09.91Z" } +sdist = { url = "https://files.pythonhosted.org/packages/0f/27/056e0638a86749374d6f57d0b0db39f29509cce9313cf91bdc0ac4d91084/jaraco_functools-4.4.0.tar.gz", hash = "sha256:da21933b0417b89515562656547a77b4931f98176eb173644c0d35032a33d6bb", size = 19943, upload-time = "2025-12-21T09:29:43.6Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/b4/09/726f168acad366b11e420df31bf1c702a54d373a83f968d94141a8c3fde0/jaraco_functools-4.3.0-py3-none-any.whl", hash = "sha256:227ff8ed6f7b8f62c56deff101545fa7543cf2c8e7b82a7c2116e672f29c26e8", size = 10408, upload-time = "2025-08-18T20:05:08.69Z" }, + { url = "https://files.pythonhosted.org/packages/fd/c4/813bb09f0985cb21e959f21f2464169eca882656849adf727ac7bb7e1767/jaraco_functools-4.4.0-py3-none-any.whl", hash = "sha256:9eec1e36f45c818d9bf307c8948eb03b2b56cd44087b3cdc989abca1f20b9176", size = 10481, upload-time = "2025-12-21T09:29:42.27Z" }, ] [[package]] @@ -2219,75 +2272,99 @@ wheels = [ [[package]] name = "jiter" -version = "0.11.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/9d/c0/a3bb4cc13aced219dd18191ea66e874266bd8aa7b96744e495e1c733aa2d/jiter-0.11.0.tar.gz", hash = "sha256:1d9637eaf8c1d6a63d6562f2a6e5ab3af946c66037eb1b894e8fad75422266e4", size = 167094, upload-time = "2025-09-15T09:20:38.212Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/25/21/7dd1235a19e26979be6098e87e4cced2e061752f3a40a17bbce6dea7fae1/jiter-0.11.0-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:3893ce831e1c0094a83eeaf56c635a167d6fa8cc14393cc14298fd6fdc2a2449", size = 309875, upload-time = "2025-09-15T09:18:48.41Z" }, - { url = "https://files.pythonhosted.org/packages/71/f9/462b54708aa85b135733ccba70529dd68a18511bf367a87c5fd28676c841/jiter-0.11.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:25c625b9b61b5a8725267fdf867ef2e51b429687f6a4eef211f4612e95607179", size = 316505, upload-time = "2025-09-15T09:18:51.057Z" }, - { url = "https://files.pythonhosted.org/packages/bd/40/14e2eeaac6a47bff27d213834795472355fd39769272eb53cb7aa83d5aa8/jiter-0.11.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dd4ca85fb6a62cf72e1c7f5e34ddef1b660ce4ed0886ec94a1ef9777d35eaa1f", size = 337613, upload-time = "2025-09-15T09:18:52.358Z" }, - { url = "https://files.pythonhosted.org/packages/d3/ed/a5f1f8419c92b150a7c7fb5ccba1fb1e192887ad713d780e70874f0ce996/jiter-0.11.0-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:572208127034725e79c28437b82414028c3562335f2b4f451d98136d0fc5f9cd", size = 361438, upload-time = "2025-09-15T09:18:54.637Z" }, - { url = "https://files.pythonhosted.org/packages/dd/f5/70682c023dfcdd463a53faf5d30205a7d99c51d70d3e303c932d0936e5a2/jiter-0.11.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:494ba627c7f550ad3dabb21862864b8f2216098dc18ff62f37b37796f2f7c325", size = 486180, upload-time = "2025-09-15T09:18:56.158Z" }, - { url = "https://files.pythonhosted.org/packages/7c/39/020d08cbab4eab48142ad88b837c41eb08a15c0767fdb7c0d3265128a44b/jiter-0.11.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b8da18a99f58bca3ecc2d2bba99cac000a924e115b6c4f0a2b98f752b6fbf39a", size = 376681, upload-time = "2025-09-15T09:18:57.553Z" }, - { url = "https://files.pythonhosted.org/packages/52/10/b86733f6e594cf51dd142f37c602d8df87c554c5844958deaab0de30eb5d/jiter-0.11.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e4ffd3b0fff3fabbb02cc09910c08144db6bb5697a98d227a074401e01ee63dd", size = 348685, upload-time = "2025-09-15T09:18:59.208Z" }, - { url = "https://files.pythonhosted.org/packages/fb/ee/8861665e83a9e703aa5f65fddddb6225428e163e6b0baa95a7f9a8fb9aae/jiter-0.11.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:8fe6530aa738a4f7d4e4702aa8f9581425d04036a5f9e25af65ebe1f708f23be", size = 385573, upload-time = "2025-09-15T09:19:00.593Z" }, - { url = "https://files.pythonhosted.org/packages/25/74/05afec03600951f128293813b5a208c9ba1bf587c57a344c05a42a69e1b1/jiter-0.11.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:e35d66681c133a03d7e974e7eedae89720fe8ca3bd09f01a4909b86a8adf31f5", size = 516669, upload-time = "2025-09-15T09:19:02.369Z" }, - { url = "https://files.pythonhosted.org/packages/93/d1/2e5bfe147cfbc2a5eef7f73eb75dc5c6669da4fa10fc7937181d93af9495/jiter-0.11.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:c59459beca2fbc9718b6f1acb7bfb59ebc3eb4294fa4d40e9cb679dafdcc6c60", size = 508767, upload-time = "2025-09-15T09:19:04.011Z" }, - { url = "https://files.pythonhosted.org/packages/87/50/597f71307e10426b5c082fd05d38c615ddbdd08c3348d8502963307f0652/jiter-0.11.0-cp310-cp310-win32.whl", hash = "sha256:b7b0178417b0dcfc5f259edbc6db2b1f5896093ed9035ee7bab0f2be8854726d", size = 205476, upload-time = "2025-09-15T09:19:05.594Z" }, - { url = "https://files.pythonhosted.org/packages/c7/86/1e5214b3272e311754da26e63edec93a183811d4fc2e0118addec365df8b/jiter-0.11.0-cp310-cp310-win_amd64.whl", hash = "sha256:11df2bf99fb4754abddd7f5d940a48e51f9d11624d6313ca4314145fcad347f0", size = 204708, upload-time = "2025-09-15T09:19:06.955Z" }, - { url = "https://files.pythonhosted.org/packages/38/55/a69fefeef09c2eaabae44b935a1aa81517e49639c0a0c25d861cb18cd7ac/jiter-0.11.0-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:cb5d9db02979c3f49071fce51a48f4b4e4cf574175fb2b11c7a535fa4867b222", size = 309503, upload-time = "2025-09-15T09:19:08.191Z" }, - { url = "https://files.pythonhosted.org/packages/bd/d5/a6aba9e6551f32f9c127184f398208e4eddb96c59ac065c8a92056089d28/jiter-0.11.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:1dc6a123f3471c4730db7ca8ba75f1bb3dcb6faeb8d46dd781083e7dee88b32d", size = 317688, upload-time = "2025-09-15T09:19:09.918Z" }, - { url = "https://files.pythonhosted.org/packages/bb/f3/5e86f57c1883971cdc8535d0429c2787bf734840a231da30a3be12850562/jiter-0.11.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:09858f8d230f031c7b8e557429102bf050eea29c77ad9c34c8fe253c5329acb7", size = 337418, upload-time = "2025-09-15T09:19:11.078Z" }, - { url = "https://files.pythonhosted.org/packages/5e/4f/a71d8a24c2a70664970574a8e0b766663f5ef788f7fe1cc20ee0c016d488/jiter-0.11.0-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:dbe2196c4a0ce760925a74ab4456bf644748ab0979762139626ad138f6dac72d", size = 361423, upload-time = "2025-09-15T09:19:13.286Z" }, - { url = "https://files.pythonhosted.org/packages/8f/e5/b09076f4e7fd9471b91e16f9f3dc7330b161b738f3b39b2c37054a36e26a/jiter-0.11.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5beb56d22b63647bafd0b74979216fdee80c580c0c63410be8c11053860ffd09", size = 486367, upload-time = "2025-09-15T09:19:14.546Z" }, - { url = "https://files.pythonhosted.org/packages/fb/f1/98cb3a36f5e62f80cd860f0179f948d9eab5a316d55d3e1bab98d9767af5/jiter-0.11.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:97025d09ef549795d8dc720a824312cee3253c890ac73c621721ddfc75066789", size = 376335, upload-time = "2025-09-15T09:19:15.939Z" }, - { url = "https://files.pythonhosted.org/packages/9f/d8/ec74886497ea393c29dbd7651ddecc1899e86404a6b1f84a3ddab0ab59fd/jiter-0.11.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d50880a6da65d8c23a2cf53c412847d9757e74cc9a3b95c5704a1d1a24667347", size = 348981, upload-time = "2025-09-15T09:19:17.568Z" }, - { url = "https://files.pythonhosted.org/packages/24/93/d22ad7fa3b86ade66c86153ceea73094fc2af8b20c59cb7fceab9fea4704/jiter-0.11.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:452d80a1c86c095a242007bd9fc5d21b8a8442307193378f891cb8727e469648", size = 385797, upload-time = "2025-09-15T09:19:19.121Z" }, - { url = "https://files.pythonhosted.org/packages/c8/bd/e25ff4a4df226e9b885f7cb01ee4b9dc74e3000e612d6f723860d71a1f34/jiter-0.11.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:e84e58198d4894668eec2da660ffff60e0f3e60afa790ecc50cb12b0e02ca1d4", size = 516597, upload-time = "2025-09-15T09:19:20.301Z" }, - { url = "https://files.pythonhosted.org/packages/be/fb/beda613db7d93ffa2fdd2683f90f2f5dce8daf4bc2d0d2829e7de35308c6/jiter-0.11.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:df64edcfc5dd5279a791eea52aa113d432c933119a025b0b5739f90d2e4e75f1", size = 508853, upload-time = "2025-09-15T09:19:22.075Z" }, - { url = "https://files.pythonhosted.org/packages/20/64/c5b0d93490634e41e38e2a15de5d54fdbd2c9f64a19abb0f95305b63373c/jiter-0.11.0-cp311-cp311-win32.whl", hash = "sha256:144fc21337d21b1d048f7f44bf70881e1586401d405ed3a98c95a114a9994982", size = 205140, upload-time = "2025-09-15T09:19:23.351Z" }, - { url = "https://files.pythonhosted.org/packages/a1/e6/c347c0e6f5796e97d4356b7e5ff0ce336498b7f4ef848fae621a56f1ccf3/jiter-0.11.0-cp311-cp311-win_amd64.whl", hash = "sha256:b0f32e644d241293b892b1a6dd8f0b9cc029bfd94c97376b2681c36548aabab7", size = 204311, upload-time = "2025-09-15T09:19:24.591Z" }, - { url = "https://files.pythonhosted.org/packages/ba/b5/3009b112b8f673e568ef79af9863d8309a15f0a8cdcc06ed6092051f377e/jiter-0.11.0-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:2fb7b377688cc3850bbe5c192a6bd493562a0bc50cbc8b047316428fbae00ada", size = 305510, upload-time = "2025-09-15T09:19:25.893Z" }, - { url = "https://files.pythonhosted.org/packages/fe/82/15514244e03b9e71e086bbe2a6de3e4616b48f07d5f834200c873956fb8c/jiter-0.11.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:a1b7cbe3f25bd0d8abb468ba4302a5d45617ee61b2a7a638f63fee1dc086be99", size = 316521, upload-time = "2025-09-15T09:19:27.525Z" }, - { url = "https://files.pythonhosted.org/packages/92/94/7a2e905f40ad2d6d660e00b68d818f9e29fb87ffe82774f06191e93cbe4a/jiter-0.11.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c0a7f0ec81d5b7588c5cade1eb1925b91436ae6726dc2df2348524aeabad5de6", size = 338214, upload-time = "2025-09-15T09:19:28.727Z" }, - { url = "https://files.pythonhosted.org/packages/a8/9c/5791ed5bdc76f12110158d3316a7a3ec0b1413d018b41c5ed399549d3ad5/jiter-0.11.0-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:07630bb46ea2a6b9c6ed986c6e17e35b26148cce2c535454b26ee3f0e8dcaba1", size = 361280, upload-time = "2025-09-15T09:19:30.013Z" }, - { url = "https://files.pythonhosted.org/packages/d4/7f/b7d82d77ff0d2cb06424141000176b53a9e6b16a1125525bb51ea4990c2e/jiter-0.11.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7764f27d28cd4a9cbc61704dfcd80c903ce3aad106a37902d3270cd6673d17f4", size = 487895, upload-time = "2025-09-15T09:19:31.424Z" }, - { url = "https://files.pythonhosted.org/packages/42/44/10a1475d46f1fc1fd5cc2e82c58e7bca0ce5852208e0fa5df2f949353321/jiter-0.11.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1d4a6c4a737d486f77f842aeb22807edecb4a9417e6700c7b981e16d34ba7c72", size = 378421, upload-time = "2025-09-15T09:19:32.746Z" }, - { url = "https://files.pythonhosted.org/packages/9a/5f/0dc34563d8164d31d07bc09d141d3da08157a68dcd1f9b886fa4e917805b/jiter-0.11.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cf408d2a0abd919b60de8c2e7bc5eeab72d4dafd18784152acc7c9adc3291591", size = 347932, upload-time = "2025-09-15T09:19:34.612Z" }, - { url = "https://files.pythonhosted.org/packages/f7/de/b68f32a4fcb7b4a682b37c73a0e5dae32180140cd1caf11aef6ad40ddbf2/jiter-0.11.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:cdef53eda7d18e799625023e1e250dbc18fbc275153039b873ec74d7e8883e09", size = 386959, upload-time = "2025-09-15T09:19:35.994Z" }, - { url = "https://files.pythonhosted.org/packages/76/0a/c08c92e713b6e28972a846a81ce374883dac2f78ec6f39a0dad9f2339c3a/jiter-0.11.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:53933a38ef7b551dd9c7f1064f9d7bb235bb3168d0fa5f14f0798d1b7ea0d9c5", size = 517187, upload-time = "2025-09-15T09:19:37.426Z" }, - { url = "https://files.pythonhosted.org/packages/89/b5/4a283bec43b15aad54fcae18d951f06a2ec3f78db5708d3b59a48e9c3fbd/jiter-0.11.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:11840d2324c9ab5162fc1abba23bc922124fedcff0d7b7f85fffa291e2f69206", size = 509461, upload-time = "2025-09-15T09:19:38.761Z" }, - { url = "https://files.pythonhosted.org/packages/34/a5/f8bad793010534ea73c985caaeef8cc22dfb1fedb15220ecdf15c623c07a/jiter-0.11.0-cp312-cp312-win32.whl", hash = "sha256:4f01a744d24a5f2bb4a11657a1b27b61dc038ae2e674621a74020406e08f749b", size = 206664, upload-time = "2025-09-15T09:19:40.096Z" }, - { url = "https://files.pythonhosted.org/packages/ed/42/5823ec2b1469395a160b4bf5f14326b4a098f3b6898fbd327366789fa5d3/jiter-0.11.0-cp312-cp312-win_amd64.whl", hash = "sha256:29fff31190ab3a26de026da2f187814f4b9c6695361e20a9ac2123e4d4378a4c", size = 203520, upload-time = "2025-09-15T09:19:41.798Z" }, - { url = "https://files.pythonhosted.org/packages/97/c4/d530e514d0f4f29b2b68145e7b389cbc7cac7f9c8c23df43b04d3d10fa3e/jiter-0.11.0-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:4441a91b80a80249f9a6452c14b2c24708f139f64de959943dfeaa6cb915e8eb", size = 305021, upload-time = "2025-09-15T09:19:43.523Z" }, - { url = "https://files.pythonhosted.org/packages/7a/77/796a19c567c5734cbfc736a6f987affc0d5f240af8e12063c0fb93990ffa/jiter-0.11.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:ff85fc6d2a431251ad82dbd1ea953affb5a60376b62e7d6809c5cd058bb39471", size = 314384, upload-time = "2025-09-15T09:19:44.849Z" }, - { url = "https://files.pythonhosted.org/packages/14/9c/824334de0b037b91b6f3fa9fe5a191c83977c7ec4abe17795d3cb6d174cf/jiter-0.11.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c5e86126d64706fd28dfc46f910d496923c6f95b395138c02d0e252947f452bd", size = 337389, upload-time = "2025-09-15T09:19:46.094Z" }, - { url = "https://files.pythonhosted.org/packages/a2/95/ed4feab69e6cf9b2176ea29d4ef9d01a01db210a3a2c8a31a44ecdc68c38/jiter-0.11.0-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:4ad8bd82165961867a10f52010590ce0b7a8c53da5ddd8bbb62fef68c181b921", size = 360519, upload-time = "2025-09-15T09:19:47.494Z" }, - { url = "https://files.pythonhosted.org/packages/b5/0c/2ad00f38d3e583caba3909d95b7da1c3a7cd82c0aa81ff4317a8016fb581/jiter-0.11.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b42c2cd74273455ce439fd9528db0c6e84b5623cb74572305bdd9f2f2961d3df", size = 487198, upload-time = "2025-09-15T09:19:49.116Z" }, - { url = "https://files.pythonhosted.org/packages/ea/8b/919b64cf3499b79bdfba6036da7b0cac5d62d5c75a28fb45bad7819e22f0/jiter-0.11.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f0062dab98172dd0599fcdbf90214d0dcde070b1ff38a00cc1b90e111f071982", size = 377835, upload-time = "2025-09-15T09:19:50.468Z" }, - { url = "https://files.pythonhosted.org/packages/29/7f/8ebe15b6e0a8026b0d286c083b553779b4dd63db35b43a3f171b544de91d/jiter-0.11.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bb948402821bc76d1f6ef0f9e19b816f9b09f8577844ba7140f0b6afe994bc64", size = 347655, upload-time = "2025-09-15T09:19:51.726Z" }, - { url = "https://files.pythonhosted.org/packages/8e/64/332127cef7e94ac75719dda07b9a472af6158ba819088d87f17f3226a769/jiter-0.11.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:25a5b1110cca7329fd0daf5060faa1234be5c11e988948e4f1a1923b6a457fe1", size = 386135, upload-time = "2025-09-15T09:19:53.075Z" }, - { url = "https://files.pythonhosted.org/packages/20/c8/557b63527442f84c14774159948262a9d4fabb0d61166f11568f22fc60d2/jiter-0.11.0-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:bf11807e802a214daf6c485037778843fadd3e2ec29377ae17e0706ec1a25758", size = 516063, upload-time = "2025-09-15T09:19:54.447Z" }, - { url = "https://files.pythonhosted.org/packages/86/13/4164c819df4a43cdc8047f9a42880f0ceef5afeb22e8b9675c0528ebdccd/jiter-0.11.0-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:dbb57da40631c267861dd0090461222060960012d70fd6e4c799b0f62d0ba166", size = 508139, upload-time = "2025-09-15T09:19:55.764Z" }, - { url = "https://files.pythonhosted.org/packages/fa/70/6e06929b401b331d41ddb4afb9f91cd1168218e3371972f0afa51c9f3c31/jiter-0.11.0-cp313-cp313-win32.whl", hash = "sha256:8e36924dad32c48d3c5e188d169e71dc6e84d6cb8dedefea089de5739d1d2f80", size = 206369, upload-time = "2025-09-15T09:19:57.048Z" }, - { url = "https://files.pythonhosted.org/packages/f4/0d/8185b8e15de6dce24f6afae63380e16377dd75686d56007baa4f29723ea1/jiter-0.11.0-cp313-cp313-win_amd64.whl", hash = "sha256:452d13e4fd59698408087235259cebe67d9d49173b4dacb3e8d35ce4acf385d6", size = 202538, upload-time = "2025-09-15T09:19:58.35Z" }, - { url = "https://files.pythonhosted.org/packages/13/3a/d61707803260d59520721fa326babfae25e9573a88d8b7b9cb54c5423a59/jiter-0.11.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:089f9df9f69532d1339e83142438668f52c97cd22ee2d1195551c2b1a9e6cf33", size = 313737, upload-time = "2025-09-15T09:19:59.638Z" }, - { url = "https://files.pythonhosted.org/packages/cd/cc/c9f0eec5d00f2a1da89f6bdfac12b8afdf8d5ad974184863c75060026457/jiter-0.11.0-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:29ed1fe69a8c69bf0f2a962d8d706c7b89b50f1332cd6b9fbda014f60bd03a03", size = 346183, upload-time = "2025-09-15T09:20:01.442Z" }, - { url = "https://files.pythonhosted.org/packages/a6/87/fc632776344e7aabbab05a95a0075476f418c5d29ab0f2eec672b7a1f0ac/jiter-0.11.0-cp313-cp313t-win_amd64.whl", hash = "sha256:a4d71d7ea6ea8786291423fe209acf6f8d398a0759d03e7f24094acb8ab686ba", size = 204225, upload-time = "2025-09-15T09:20:03.102Z" }, - { url = "https://files.pythonhosted.org/packages/ee/3b/e7f45be7d3969bdf2e3cd4b816a7a1d272507cd0edd2d6dc4b07514f2d9a/jiter-0.11.0-cp314-cp314-macosx_10_12_x86_64.whl", hash = "sha256:9a6dff27eca70930bdbe4cbb7c1a4ba8526e13b63dc808c0670083d2d51a4a72", size = 304414, upload-time = "2025-09-15T09:20:04.357Z" }, - { url = "https://files.pythonhosted.org/packages/06/32/13e8e0d152631fcc1907ceb4943711471be70496d14888ec6e92034e2caf/jiter-0.11.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:b1ae2a7593a62132c7d4c2abbee80bbbb94fdc6d157e2c6cc966250c564ef774", size = 314223, upload-time = "2025-09-15T09:20:05.631Z" }, - { url = "https://files.pythonhosted.org/packages/0c/7e/abedd5b5a20ca083f778d96bba0d2366567fcecb0e6e34ff42640d5d7a18/jiter-0.11.0-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7b13a431dba4b059e9e43019d3022346d009baf5066c24dcdea321a303cde9f0", size = 337306, upload-time = "2025-09-15T09:20:06.917Z" }, - { url = "https://files.pythonhosted.org/packages/ac/e2/30d59bdc1204c86aa975ec72c48c482fee6633120ee9c3ab755e4dfefea8/jiter-0.11.0-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:af62e84ca3889604ebb645df3b0a3f3bcf6b92babbff642bd214616f57abb93a", size = 360565, upload-time = "2025-09-15T09:20:08.283Z" }, - { url = "https://files.pythonhosted.org/packages/fe/88/567288e0d2ed9fa8f7a3b425fdaf2cb82b998633c24fe0d98f5417321aa8/jiter-0.11.0-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c6f3b32bb723246e6b351aecace52aba78adb8eeb4b2391630322dc30ff6c773", size = 486465, upload-time = "2025-09-15T09:20:09.613Z" }, - { url = "https://files.pythonhosted.org/packages/18/6e/7b72d09273214cadd15970e91dd5ed9634bee605176107db21e1e4205eb1/jiter-0.11.0-cp314-cp314-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:adcab442f4a099a358a7f562eaa54ed6456fb866e922c6545a717be51dbed7d7", size = 377581, upload-time = "2025-09-15T09:20:10.884Z" }, - { url = "https://files.pythonhosted.org/packages/58/52/4db456319f9d14deed325f70102577492e9d7e87cf7097bda9769a1fcacb/jiter-0.11.0-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c9967c2ab338ee2b2c0102fd379ec2693c496abf71ffd47e4d791d1f593b68e2", size = 347102, upload-time = "2025-09-15T09:20:12.175Z" }, - { url = "https://files.pythonhosted.org/packages/ce/b4/433d5703c38b26083aec7a733eb5be96f9c6085d0e270a87ca6482cbf049/jiter-0.11.0-cp314-cp314-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:e7d0bed3b187af8b47a981d9742ddfc1d9b252a7235471ad6078e7e4e5fe75c2", size = 386477, upload-time = "2025-09-15T09:20:13.428Z" }, - { url = "https://files.pythonhosted.org/packages/c8/7a/a60bfd9c55b55b07c5c441c5085f06420b6d493ce9db28d069cc5b45d9f3/jiter-0.11.0-cp314-cp314-musllinux_1_1_aarch64.whl", hash = "sha256:f6fe0283e903ebc55f1a6cc569b8c1f3bf4abd026fed85e3ff8598a9e6f982f0", size = 516004, upload-time = "2025-09-15T09:20:14.848Z" }, - { url = "https://files.pythonhosted.org/packages/2e/46/f8363e5ecc179b4ed0ca6cb0a6d3bfc266078578c71ff30642ea2ce2f203/jiter-0.11.0-cp314-cp314-musllinux_1_1_x86_64.whl", hash = "sha256:4ee5821e3d66606b29ae5b497230b304f1376f38137d69e35f8d2bd5f310ff73", size = 507855, upload-time = "2025-09-15T09:20:16.176Z" }, - { url = "https://files.pythonhosted.org/packages/90/33/396083357d51d7ff0f9805852c288af47480d30dd31d8abc74909b020761/jiter-0.11.0-cp314-cp314-win32.whl", hash = "sha256:c2d13ba7567ca8799f17c76ed56b1d49be30df996eb7fa33e46b62800562a5e2", size = 205802, upload-time = "2025-09-15T09:20:17.661Z" }, - { url = "https://files.pythonhosted.org/packages/e7/ab/eb06ca556b2551d41de7d03bf2ee24285fa3d0c58c5f8d95c64c9c3281b1/jiter-0.11.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:fb4790497369d134a07fc763cc88888c46f734abdd66f9fdf7865038bf3a8f40", size = 313405, upload-time = "2025-09-15T09:20:18.918Z" }, - { url = "https://files.pythonhosted.org/packages/af/22/7ab7b4ec3a1c1f03aef376af11d23b05abcca3fb31fbca1e7557053b1ba2/jiter-0.11.0-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6e2bbf24f16ba5ad4441a9845e40e4ea0cb9eed00e76ba94050664ef53ef4406", size = 347102, upload-time = "2025-09-15T09:20:20.16Z" }, - { url = "https://files.pythonhosted.org/packages/70/f3/ce100253c80063a7b8b406e1d1562657fd4b9b4e1b562db40e68645342fb/jiter-0.11.0-graalpy311-graalpy242_311_native-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:902b43386c04739229076bd1c4c69de5d115553d982ab442a8ae82947c72ede7", size = 336380, upload-time = "2025-09-15T09:20:36.867Z" }, +version = "0.13.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/0d/5e/4ec91646aee381d01cdb9974e30882c9cd3b8c5d1079d6b5ff4af522439a/jiter-0.13.0.tar.gz", hash = "sha256:f2839f9c2c7e2dffc1bc5929a510e14ce0a946be9365fd1219e7ef342dae14f4", size = 164847, upload-time = "2026-02-02T12:37:56.441Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d0/5a/41da76c5ea07bec1b0472b6b2fdb1b651074d504b19374d7e130e0cdfb25/jiter-0.13.0-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:2ffc63785fd6c7977defe49b9824ae6ce2b2e2b77ce539bdaf006c26da06342e", size = 311164, upload-time = "2026-02-02T12:35:17.688Z" }, + { url = "https://files.pythonhosted.org/packages/40/cb/4a1bf994a3e869f0d39d10e11efb471b76d0ad70ecbfb591427a46c880c2/jiter-0.13.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:4a638816427006c1e3f0013eb66d391d7a3acda99a7b0cf091eff4497ccea33a", size = 320296, upload-time = "2026-02-02T12:35:19.828Z" }, + { url = "https://files.pythonhosted.org/packages/09/82/acd71ca9b50ecebadc3979c541cd717cce2fe2bc86236f4fa597565d8f1a/jiter-0.13.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:19928b5d1ce0ff8c1ee1b9bdef3b5bfc19e8304f1b904e436caf30bc15dc6cf5", size = 352742, upload-time = "2026-02-02T12:35:21.258Z" }, + { url = "https://files.pythonhosted.org/packages/71/03/d1fc996f3aecfd42eb70922edecfb6dd26421c874503e241153ad41df94f/jiter-0.13.0-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:309549b778b949d731a2f0e1594a3f805716be704a73bf3ad9a807eed5eb5721", size = 363145, upload-time = "2026-02-02T12:35:24.653Z" }, + { url = "https://files.pythonhosted.org/packages/f1/61/a30492366378cc7a93088858f8991acd7d959759fe6138c12a4644e58e81/jiter-0.13.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:bcdabaea26cb04e25df3103ce47f97466627999260290349a88c8136ecae0060", size = 487683, upload-time = "2026-02-02T12:35:26.162Z" }, + { url = "https://files.pythonhosted.org/packages/20/4e/4223cffa9dbbbc96ed821c5aeb6bca510848c72c02086d1ed3f1da3d58a7/jiter-0.13.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a3a377af27b236abbf665a69b2bdd680e3b5a0bd2af825cd3b81245279a7606c", size = 373579, upload-time = "2026-02-02T12:35:27.582Z" }, + { url = "https://files.pythonhosted.org/packages/fe/c9/b0489a01329ab07a83812d9ebcffe7820a38163c6d9e7da644f926ff877c/jiter-0.13.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fe49d3ff6db74321f144dff9addd4a5874d3105ac5ba7c5b77fac099cfae31ae", size = 362904, upload-time = "2026-02-02T12:35:28.925Z" }, + { url = "https://files.pythonhosted.org/packages/05/af/53e561352a44afcba9a9bc67ee1d320b05a370aed8df54eafe714c4e454d/jiter-0.13.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2113c17c9a67071b0f820733c0893ed1d467b5fcf4414068169e5c2cabddb1e2", size = 392380, upload-time = "2026-02-02T12:35:30.385Z" }, + { url = "https://files.pythonhosted.org/packages/76/2a/dd805c3afb8ed5b326c5ae49e725d1b1255b9754b1b77dbecdc621b20773/jiter-0.13.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:ab1185ca5c8b9491b55ebf6c1e8866b8f68258612899693e24a92c5fdb9455d5", size = 517939, upload-time = "2026-02-02T12:35:31.865Z" }, + { url = "https://files.pythonhosted.org/packages/20/2a/7b67d76f55b8fe14c937e7640389612f05f9a4145fc28ae128aaa5e62257/jiter-0.13.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:9621ca242547edc16400981ca3231e0c91c0c4c1ab8573a596cd9bb3575d5c2b", size = 551696, upload-time = "2026-02-02T12:35:33.306Z" }, + { url = "https://files.pythonhosted.org/packages/85/9c/57cdd64dac8f4c6ab8f994fe0eb04dc9fd1db102856a4458fcf8a99dfa62/jiter-0.13.0-cp310-cp310-win32.whl", hash = "sha256:a7637d92b1c9d7a771e8c56f445c7f84396d48f2e756e5978840ecba2fac0894", size = 204592, upload-time = "2026-02-02T12:35:34.58Z" }, + { url = "https://files.pythonhosted.org/packages/a7/38/f4f3ea5788b8a5bae7510a678cdc747eda0c45ffe534f9878ff37e7cf3b3/jiter-0.13.0-cp310-cp310-win_amd64.whl", hash = "sha256:c1b609e5cbd2f52bb74fb721515745b407df26d7b800458bd97cb3b972c29e7d", size = 206016, upload-time = "2026-02-02T12:35:36.435Z" }, + { url = "https://files.pythonhosted.org/packages/71/29/499f8c9eaa8a16751b1c0e45e6f5f1761d180da873d417996cc7bddc8eef/jiter-0.13.0-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:ea026e70a9a28ebbdddcbcf0f1323128a8db66898a06eaad3a4e62d2f554d096", size = 311157, upload-time = "2026-02-02T12:35:37.758Z" }, + { url = "https://files.pythonhosted.org/packages/50/f6/566364c777d2ab450b92100bea11333c64c38d32caf8dc378b48e5b20c46/jiter-0.13.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:66aa3e663840152d18cc8ff1e4faad3dd181373491b9cfdc6004b92198d67911", size = 319729, upload-time = "2026-02-02T12:35:39.246Z" }, + { url = "https://files.pythonhosted.org/packages/73/dd/560f13ec5e4f116d8ad2658781646cca91b617ae3b8758d4a5076b278f70/jiter-0.13.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c3524798e70655ff19aec58c7d05adb1f074fecff62da857ea9be2b908b6d701", size = 354766, upload-time = "2026-02-02T12:35:40.662Z" }, + { url = "https://files.pythonhosted.org/packages/7c/0d/061faffcfe94608cbc28a0d42a77a74222bdf5055ccdbe5fd2292b94f510/jiter-0.13.0-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ec7e287d7fbd02cb6e22f9a00dd9c9cd504c40a61f2c61e7e1f9690a82726b4c", size = 362587, upload-time = "2026-02-02T12:35:42.025Z" }, + { url = "https://files.pythonhosted.org/packages/92/c9/c66a7864982fd38a9773ec6e932e0398d1262677b8c60faecd02ffb67bf3/jiter-0.13.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:47455245307e4debf2ce6c6e65a717550a0244231240dcf3b8f7d64e4c2f22f4", size = 487537, upload-time = "2026-02-02T12:35:43.459Z" }, + { url = "https://files.pythonhosted.org/packages/6c/86/84eb4352cd3668f16d1a88929b5888a3fe0418ea8c1dfc2ad4e7bf6e069a/jiter-0.13.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ee9da221dca6e0429c2704c1b3655fe7b025204a71d4d9b73390c759d776d165", size = 373717, upload-time = "2026-02-02T12:35:44.928Z" }, + { url = "https://files.pythonhosted.org/packages/6e/09/9fe4c159358176f82d4390407a03f506a8659ed13ca3ac93a843402acecf/jiter-0.13.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:24ab43126d5e05f3d53a36a8e11eb2f23304c6c1117844aaaf9a0aa5e40b5018", size = 362683, upload-time = "2026-02-02T12:35:46.636Z" }, + { url = "https://files.pythonhosted.org/packages/c9/5e/85f3ab9caca0c1d0897937d378b4a515cae9e119730563572361ea0c48ae/jiter-0.13.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:9da38b4fedde4fb528c740c2564628fbab737166a0e73d6d46cb4bb5463ff411", size = 392345, upload-time = "2026-02-02T12:35:48.088Z" }, + { url = "https://files.pythonhosted.org/packages/12/4c/05b8629ad546191939e6f0c2f17e29f542a398f4a52fb987bc70b6d1eb8b/jiter-0.13.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:0b34c519e17658ed88d5047999a93547f8889f3c1824120c26ad6be5f27b6cf5", size = 517775, upload-time = "2026-02-02T12:35:49.482Z" }, + { url = "https://files.pythonhosted.org/packages/4d/88/367ea2eb6bc582c7052e4baf5ddf57ebe5ab924a88e0e09830dfb585c02d/jiter-0.13.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:d2a6394e6af690d462310a86b53c47ad75ac8c21dc79f120714ea449979cb1d3", size = 551325, upload-time = "2026-02-02T12:35:51.104Z" }, + { url = "https://files.pythonhosted.org/packages/f3/12/fa377ffb94a2f28c41afaed093e0d70cfe512035d5ecb0cad0ae4792d35e/jiter-0.13.0-cp311-cp311-win32.whl", hash = "sha256:0f0c065695f616a27c920a56ad0d4fc46415ef8b806bf8fc1cacf25002bd24e1", size = 204709, upload-time = "2026-02-02T12:35:52.467Z" }, + { url = "https://files.pythonhosted.org/packages/cb/16/8e8203ce92f844dfcd3d9d6a5a7322c77077248dbb12da52d23193a839cd/jiter-0.13.0-cp311-cp311-win_amd64.whl", hash = "sha256:0733312953b909688ae3c2d58d043aa040f9f1a6a75693defed7bc2cc4bf2654", size = 204560, upload-time = "2026-02-02T12:35:53.925Z" }, + { url = "https://files.pythonhosted.org/packages/44/26/97cc40663deb17b9e13c3a5cf29251788c271b18ee4d262c8f94798b8336/jiter-0.13.0-cp311-cp311-win_arm64.whl", hash = "sha256:5d9b34ad56761b3bf0fbe8f7e55468704107608512350962d3317ffd7a4382d5", size = 189608, upload-time = "2026-02-02T12:35:55.304Z" }, + { url = "https://files.pythonhosted.org/packages/2e/30/7687e4f87086829955013ca12a9233523349767f69653ebc27036313def9/jiter-0.13.0-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:0a2bd69fc1d902e89925fc34d1da51b2128019423d7b339a45d9e99c894e0663", size = 307958, upload-time = "2026-02-02T12:35:57.165Z" }, + { url = "https://files.pythonhosted.org/packages/c3/27/e57f9a783246ed95481e6749cc5002a8a767a73177a83c63ea71f0528b90/jiter-0.13.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:f917a04240ef31898182f76a332f508f2cc4b57d2b4d7ad2dbfebbfe167eb505", size = 318597, upload-time = "2026-02-02T12:35:58.591Z" }, + { url = "https://files.pythonhosted.org/packages/cf/52/e5719a60ac5d4d7c5995461a94ad5ef962a37c8bf5b088390e6fad59b2ff/jiter-0.13.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c1e2b199f446d3e82246b4fd9236d7cb502dc2222b18698ba0d986d2fecc6152", size = 348821, upload-time = "2026-02-02T12:36:00.093Z" }, + { url = "https://files.pythonhosted.org/packages/61/db/c1efc32b8ba4c740ab3fc2d037d8753f67685f475e26b9d6536a4322bcdd/jiter-0.13.0-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:04670992b576fa65bd056dbac0c39fe8bd67681c380cb2b48efa885711d9d726", size = 364163, upload-time = "2026-02-02T12:36:01.937Z" }, + { url = "https://files.pythonhosted.org/packages/55/8a/fb75556236047c8806995671a18e4a0ad646ed255276f51a20f32dceaeec/jiter-0.13.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5a1aff1fbdb803a376d4d22a8f63f8e7ccbce0b4890c26cc7af9e501ab339ef0", size = 483709, upload-time = "2026-02-02T12:36:03.41Z" }, + { url = "https://files.pythonhosted.org/packages/7e/16/43512e6ee863875693a8e6f6d532e19d650779d6ba9a81593ae40a9088ff/jiter-0.13.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3b3fb8c2053acaef8580809ac1d1f7481a0a0bdc012fd7f5d8b18fb696a5a089", size = 370480, upload-time = "2026-02-02T12:36:04.791Z" }, + { url = "https://files.pythonhosted.org/packages/f8/4c/09b93e30e984a187bc8aaa3510e1ec8dcbdcd71ca05d2f56aac0492453aa/jiter-0.13.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bdaba7d87e66f26a2c45d8cbadcbfc4bf7884182317907baf39cfe9775bb4d93", size = 360735, upload-time = "2026-02-02T12:36:06.994Z" }, + { url = "https://files.pythonhosted.org/packages/1a/1b/46c5e349019874ec5dfa508c14c37e29864ea108d376ae26d90bee238cd7/jiter-0.13.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:7b88d649135aca526da172e48083da915ec086b54e8e73a425ba50999468cc08", size = 391814, upload-time = "2026-02-02T12:36:08.368Z" }, + { url = "https://files.pythonhosted.org/packages/15/9e/26184760e85baee7162ad37b7912797d2077718476bf91517641c92b3639/jiter-0.13.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:e404ea551d35438013c64b4f357b0474c7abf9f781c06d44fcaf7a14c69ff9e2", size = 513990, upload-time = "2026-02-02T12:36:09.993Z" }, + { url = "https://files.pythonhosted.org/packages/e9/34/2c9355247d6debad57a0a15e76ab1566ab799388042743656e566b3b7de1/jiter-0.13.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:1f4748aad1b4a93c8bdd70f604d0f748cdc0e8744c5547798acfa52f10e79228", size = 548021, upload-time = "2026-02-02T12:36:11.376Z" }, + { url = "https://files.pythonhosted.org/packages/ac/4a/9f2c23255d04a834398b9c2e0e665382116911dc4d06b795710503cdad25/jiter-0.13.0-cp312-cp312-win32.whl", hash = "sha256:0bf670e3b1445fc4d31612199f1744f67f889ee1bbae703c4b54dc097e5dd394", size = 203024, upload-time = "2026-02-02T12:36:12.682Z" }, + { url = "https://files.pythonhosted.org/packages/09/ee/f0ae675a957ae5a8f160be3e87acea6b11dc7b89f6b7ab057e77b2d2b13a/jiter-0.13.0-cp312-cp312-win_amd64.whl", hash = "sha256:15db60e121e11fe186c0b15236bd5d18381b9ddacdcf4e659feb96fc6c969c92", size = 205424, upload-time = "2026-02-02T12:36:13.93Z" }, + { url = "https://files.pythonhosted.org/packages/1b/02/ae611edf913d3cbf02c97cdb90374af2082c48d7190d74c1111dde08bcdd/jiter-0.13.0-cp312-cp312-win_arm64.whl", hash = "sha256:41f92313d17989102f3cb5dd533a02787cdb99454d494344b0361355da52fcb9", size = 186818, upload-time = "2026-02-02T12:36:15.308Z" }, + { url = "https://files.pythonhosted.org/packages/91/9c/7ee5a6ff4b9991e1a45263bfc46731634c4a2bde27dfda6c8251df2d958c/jiter-0.13.0-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:1f8a55b848cbabf97d861495cd65f1e5c590246fabca8b48e1747c4dfc8f85bf", size = 306897, upload-time = "2026-02-02T12:36:16.748Z" }, + { url = "https://files.pythonhosted.org/packages/7c/02/be5b870d1d2be5dd6a91bdfb90f248fbb7dcbd21338f092c6b89817c3dbf/jiter-0.13.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:f556aa591c00f2c45eb1b89f68f52441a016034d18b65da60e2d2875bbbf344a", size = 317507, upload-time = "2026-02-02T12:36:18.351Z" }, + { url = "https://files.pythonhosted.org/packages/da/92/b25d2ec333615f5f284f3a4024f7ce68cfa0604c322c6808b2344c7f5d2b/jiter-0.13.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f7e1d61da332ec412350463891923f960c3073cf1aae93b538f0bb4c8cd46efb", size = 350560, upload-time = "2026-02-02T12:36:19.746Z" }, + { url = "https://files.pythonhosted.org/packages/be/ec/74dcb99fef0aca9fbe56b303bf79f6bd839010cb18ad41000bf6cc71eec0/jiter-0.13.0-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:3097d665a27bc96fd9bbf7f86178037db139f319f785e4757ce7ccbf390db6c2", size = 363232, upload-time = "2026-02-02T12:36:21.243Z" }, + { url = "https://files.pythonhosted.org/packages/1b/37/f17375e0bb2f6a812d4dd92d7616e41917f740f3e71343627da9db2824ce/jiter-0.13.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9d01ecc3a8cbdb6f25a37bd500510550b64ddf9f7d64a107d92f3ccb25035d0f", size = 483727, upload-time = "2026-02-02T12:36:22.688Z" }, + { url = "https://files.pythonhosted.org/packages/77/d2/a71160a5ae1a1e66c1395b37ef77da67513b0adba73b993a27fbe47eb048/jiter-0.13.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ed9bbc30f5d60a3bdf63ae76beb3f9db280d7f195dfcfa61af792d6ce912d159", size = 370799, upload-time = "2026-02-02T12:36:24.106Z" }, + { url = "https://files.pythonhosted.org/packages/01/99/ed5e478ff0eb4e8aa5fd998f9d69603c9fd3f32de3bd16c2b1194f68361c/jiter-0.13.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:98fbafb6e88256f4454de33c1f40203d09fc33ed19162a68b3b257b29ca7f663", size = 359120, upload-time = "2026-02-02T12:36:25.519Z" }, + { url = "https://files.pythonhosted.org/packages/16/be/7ffd08203277a813f732ba897352797fa9493faf8dc7995b31f3d9cb9488/jiter-0.13.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:5467696f6b827f1116556cb0db620440380434591e93ecee7fd14d1a491b6daa", size = 390664, upload-time = "2026-02-02T12:36:26.866Z" }, + { url = "https://files.pythonhosted.org/packages/d1/84/e0787856196d6d346264d6dcccb01f741e5f0bd014c1d9a2ebe149caf4f3/jiter-0.13.0-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:2d08c9475d48b92892583df9da592a0e2ac49bcd41fae1fec4f39ba6cf107820", size = 513543, upload-time = "2026-02-02T12:36:28.217Z" }, + { url = "https://files.pythonhosted.org/packages/65/50/ecbd258181c4313cf79bca6c88fb63207d04d5bf5e4f65174114d072aa55/jiter-0.13.0-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:aed40e099404721d7fcaf5b89bd3b4568a4666358bcac7b6b15c09fb6252ab68", size = 547262, upload-time = "2026-02-02T12:36:29.678Z" }, + { url = "https://files.pythonhosted.org/packages/27/da/68f38d12e7111d2016cd198161b36e1f042bd115c169255bcb7ec823a3bf/jiter-0.13.0-cp313-cp313-win32.whl", hash = "sha256:36ebfbcffafb146d0e6ffb3e74d51e03d9c35ce7c625c8066cdbfc7b953bdc72", size = 200630, upload-time = "2026-02-02T12:36:31.808Z" }, + { url = "https://files.pythonhosted.org/packages/25/65/3bd1a972c9a08ecd22eb3b08a95d1941ebe6938aea620c246cf426ae09c2/jiter-0.13.0-cp313-cp313-win_amd64.whl", hash = "sha256:8d76029f077379374cf0dbc78dbe45b38dec4a2eb78b08b5194ce836b2517afc", size = 202602, upload-time = "2026-02-02T12:36:33.679Z" }, + { url = "https://files.pythonhosted.org/packages/15/fe/13bd3678a311aa67686bb303654792c48206a112068f8b0b21426eb6851e/jiter-0.13.0-cp313-cp313-win_arm64.whl", hash = "sha256:bb7613e1a427cfcb6ea4544f9ac566b93d5bf67e0d48c787eca673ff9c9dff2b", size = 185939, upload-time = "2026-02-02T12:36:35.065Z" }, + { url = "https://files.pythonhosted.org/packages/49/19/a929ec002ad3228bc97ca01dbb14f7632fffdc84a95ec92ceaf4145688ae/jiter-0.13.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:fa476ab5dd49f3bf3a168e05f89358c75a17608dbabb080ef65f96b27c19ab10", size = 316616, upload-time = "2026-02-02T12:36:36.579Z" }, + { url = "https://files.pythonhosted.org/packages/52/56/d19a9a194afa37c1728831e5fb81b7722c3de18a3109e8f282bfc23e587a/jiter-0.13.0-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ade8cb6ff5632a62b7dbd4757d8c5573f7a2e9ae285d6b5b841707d8363205ef", size = 346850, upload-time = "2026-02-02T12:36:38.058Z" }, + { url = "https://files.pythonhosted.org/packages/36/4a/94e831c6bf287754a8a019cb966ed39ff8be6ab78cadecf08df3bb02d505/jiter-0.13.0-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9950290340acc1adaded363edd94baebcee7dabdfa8bee4790794cd5cfad2af6", size = 358551, upload-time = "2026-02-02T12:36:39.417Z" }, + { url = "https://files.pythonhosted.org/packages/a2/ec/a4c72c822695fa80e55d2b4142b73f0012035d9fcf90eccc56bc060db37c/jiter-0.13.0-cp313-cp313t-win_amd64.whl", hash = "sha256:2b4972c6df33731aac0742b64fd0d18e0a69bc7d6e03108ce7d40c85fd9e3e6d", size = 201950, upload-time = "2026-02-02T12:36:40.791Z" }, + { url = "https://files.pythonhosted.org/packages/b6/00/393553ec27b824fbc29047e9c7cd4a3951d7fbe4a76743f17e44034fa4e4/jiter-0.13.0-cp313-cp313t-win_arm64.whl", hash = "sha256:701a1e77d1e593c1b435315ff625fd071f0998c5f02792038a5ca98899261b7d", size = 185852, upload-time = "2026-02-02T12:36:42.077Z" }, + { url = "https://files.pythonhosted.org/packages/6e/f5/f1997e987211f6f9bd71b8083047b316208b4aca0b529bb5f8c96c89ef3e/jiter-0.13.0-cp314-cp314-macosx_10_12_x86_64.whl", hash = "sha256:cc5223ab19fe25e2f0bf2643204ad7318896fe3729bf12fde41b77bfc4fafff0", size = 308804, upload-time = "2026-02-02T12:36:43.496Z" }, + { url = "https://files.pythonhosted.org/packages/cd/8f/5482a7677731fd44881f0204981ce2d7175db271f82cba2085dd2212e095/jiter-0.13.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:9776ebe51713acf438fd9b4405fcd86893ae5d03487546dae7f34993217f8a91", size = 318787, upload-time = "2026-02-02T12:36:45.071Z" }, + { url = "https://files.pythonhosted.org/packages/f3/b9/7257ac59778f1cd025b26a23c5520a36a424f7f1b068f2442a5b499b7464/jiter-0.13.0-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:879e768938e7b49b5e90b7e3fecc0dbec01b8cb89595861fb39a8967c5220d09", size = 353880, upload-time = "2026-02-02T12:36:47.365Z" }, + { url = "https://files.pythonhosted.org/packages/c3/87/719eec4a3f0841dad99e3d3604ee4cba36af4419a76f3cb0b8e2e691ad67/jiter-0.13.0-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:682161a67adea11e3aae9038c06c8b4a9a71023228767477d683f69903ebc607", size = 366702, upload-time = "2026-02-02T12:36:48.871Z" }, + { url = "https://files.pythonhosted.org/packages/d2/65/415f0a75cf6921e43365a1bc227c565cb949caca8b7532776e430cbaa530/jiter-0.13.0-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a13b68cd1cd8cc9de8f244ebae18ccb3e4067ad205220ef324c39181e23bbf66", size = 486319, upload-time = "2026-02-02T12:36:53.006Z" }, + { url = "https://files.pythonhosted.org/packages/54/a2/9e12b48e82c6bbc6081fd81abf915e1443add1b13d8fc586e1d90bb02bb8/jiter-0.13.0-cp314-cp314-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:87ce0f14c6c08892b610686ae8be350bf368467b6acd5085a5b65441e2bf36d2", size = 372289, upload-time = "2026-02-02T12:36:54.593Z" }, + { url = "https://files.pythonhosted.org/packages/4e/c1/e4693f107a1789a239c759a432e9afc592366f04e901470c2af89cfd28e1/jiter-0.13.0-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0c365005b05505a90d1c47856420980d0237adf82f70c4aff7aebd3c1cc143ad", size = 360165, upload-time = "2026-02-02T12:36:56.112Z" }, + { url = "https://files.pythonhosted.org/packages/17/08/91b9ea976c1c758240614bd88442681a87672eebc3d9a6dde476874e706b/jiter-0.13.0-cp314-cp314-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:1317fdffd16f5873e46ce27d0e0f7f4f90f0cdf1d86bf6abeaea9f63ca2c401d", size = 389634, upload-time = "2026-02-02T12:36:57.495Z" }, + { url = "https://files.pythonhosted.org/packages/18/23/58325ef99390d6d40427ed6005bf1ad54f2577866594bcf13ce55675f87d/jiter-0.13.0-cp314-cp314-musllinux_1_1_aarch64.whl", hash = "sha256:c05b450d37ba0c9e21c77fef1f205f56bcee2330bddca68d344baebfc55ae0df", size = 514933, upload-time = "2026-02-02T12:36:58.909Z" }, + { url = "https://files.pythonhosted.org/packages/5b/25/69f1120c7c395fd276c3996bb8adefa9c6b84c12bb7111e5c6ccdcd8526d/jiter-0.13.0-cp314-cp314-musllinux_1_1_x86_64.whl", hash = "sha256:775e10de3849d0631a97c603f996f518159272db00fdda0a780f81752255ee9d", size = 548842, upload-time = "2026-02-02T12:37:00.433Z" }, + { url = "https://files.pythonhosted.org/packages/18/05/981c9669d86850c5fbb0d9e62bba144787f9fba84546ba43d624ee27ef29/jiter-0.13.0-cp314-cp314-win32.whl", hash = "sha256:632bf7c1d28421c00dd8bbb8a3bac5663e1f57d5cd5ed962bce3c73bf62608e6", size = 202108, upload-time = "2026-02-02T12:37:01.718Z" }, + { url = "https://files.pythonhosted.org/packages/8d/96/cdcf54dd0b0341db7d25413229888a346c7130bd20820530905fdb65727b/jiter-0.13.0-cp314-cp314-win_amd64.whl", hash = "sha256:f22ef501c3f87ede88f23f9b11e608581c14f04db59b6a801f354397ae13739f", size = 204027, upload-time = "2026-02-02T12:37:03.075Z" }, + { url = "https://files.pythonhosted.org/packages/fb/f9/724bcaaab7a3cd727031fe4f6995cb86c4bd344909177c186699c8dec51a/jiter-0.13.0-cp314-cp314-win_arm64.whl", hash = "sha256:07b75fe09a4ee8e0c606200622e571e44943f47254f95e2436c8bdcaceb36d7d", size = 187199, upload-time = "2026-02-02T12:37:04.414Z" }, + { url = "https://files.pythonhosted.org/packages/62/92/1661d8b9fd6a3d7a2d89831db26fe3c1509a287d83ad7838831c7b7a5c7e/jiter-0.13.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:964538479359059a35fb400e769295d4b315ae61e4105396d355a12f7fef09f0", size = 318423, upload-time = "2026-02-02T12:37:05.806Z" }, + { url = "https://files.pythonhosted.org/packages/4f/3b/f77d342a54d4ebcd128e520fc58ec2f5b30a423b0fd26acdfc0c6fef8e26/jiter-0.13.0-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e104da1db1c0991b3eaed391ccd650ae8d947eab1480c733e5a3fb28d4313e40", size = 351438, upload-time = "2026-02-02T12:37:07.189Z" }, + { url = "https://files.pythonhosted.org/packages/76/b3/ba9a69f0e4209bd3331470c723c2f5509e6f0482e416b612431a5061ed71/jiter-0.13.0-cp314-cp314t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:0e3a5f0cde8ff433b8e88e41aa40131455420fb3649a3c7abdda6145f8cb7202", size = 364774, upload-time = "2026-02-02T12:37:08.579Z" }, + { url = "https://files.pythonhosted.org/packages/b3/16/6cdb31fa342932602458dbb631bfbd47f601e03d2e4950740e0b2100b570/jiter-0.13.0-cp314-cp314t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:57aab48f40be1db920a582b30b116fe2435d184f77f0e4226f546794cedd9cf0", size = 487238, upload-time = "2026-02-02T12:37:10.066Z" }, + { url = "https://files.pythonhosted.org/packages/ed/b1/956cc7abaca8d95c13aa8d6c9b3f3797241c246cd6e792934cc4c8b250d2/jiter-0.13.0-cp314-cp314t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7772115877c53f62beeb8fd853cab692dbc04374ef623b30f997959a4c0e7e95", size = 372892, upload-time = "2026-02-02T12:37:11.656Z" }, + { url = "https://files.pythonhosted.org/packages/26/c4/97ecde8b1e74f67b8598c57c6fccf6df86ea7861ed29da84629cdbba76c4/jiter-0.13.0-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1211427574b17b633cfceba5040de8081e5abf114f7a7602f73d2e16f9fdaa59", size = 360309, upload-time = "2026-02-02T12:37:13.244Z" }, + { url = "https://files.pythonhosted.org/packages/4b/d7/eabe3cf46715854ccc80be2cd78dd4c36aedeb30751dbf85a1d08c14373c/jiter-0.13.0-cp314-cp314t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:7beae3a3d3b5212d3a55d2961db3c292e02e302feb43fce6a3f7a31b90ea6dfe", size = 389607, upload-time = "2026-02-02T12:37:14.881Z" }, + { url = "https://files.pythonhosted.org/packages/df/2d/03963fc0804e6109b82decfb9974eb92df3797fe7222428cae12f8ccaa0c/jiter-0.13.0-cp314-cp314t-musllinux_1_1_aarch64.whl", hash = "sha256:e5562a0f0e90a6223b704163ea28e831bd3a9faa3512a711f031611e6b06c939", size = 514986, upload-time = "2026-02-02T12:37:16.326Z" }, + { url = "https://files.pythonhosted.org/packages/f6/6c/8c83b45eb3eb1c1e18d841fe30b4b5bc5619d781267ca9bc03e005d8fd0a/jiter-0.13.0-cp314-cp314t-musllinux_1_1_x86_64.whl", hash = "sha256:6c26a424569a59140fb51160a56df13f438a2b0967365e987889186d5fc2f6f9", size = 548756, upload-time = "2026-02-02T12:37:17.736Z" }, + { url = "https://files.pythonhosted.org/packages/47/66/eea81dfff765ed66c68fd2ed8c96245109e13c896c2a5015c7839c92367e/jiter-0.13.0-cp314-cp314t-win32.whl", hash = "sha256:24dc96eca9f84da4131cdf87a95e6ce36765c3b156fc9ae33280873b1c32d5f6", size = 201196, upload-time = "2026-02-02T12:37:19.101Z" }, + { url = "https://files.pythonhosted.org/packages/ff/32/4ac9c7a76402f8f00d00842a7f6b83b284d0cf7c1e9d4227bc95aa6d17fa/jiter-0.13.0-cp314-cp314t-win_amd64.whl", hash = "sha256:0a8d76c7524087272c8ae913f5d9d608bd839154b62c4322ef65723d2e5bb0b8", size = 204215, upload-time = "2026-02-02T12:37:20.495Z" }, + { url = "https://files.pythonhosted.org/packages/f9/8e/7def204fea9f9be8b3c21a6f2dd6c020cf56c7d5ff753e0e23ed7f9ea57e/jiter-0.13.0-cp314-cp314t-win_arm64.whl", hash = "sha256:2c26cf47e2cad140fa23b6d58d435a7c0161f5c514284802f25e87fddfe11024", size = 187152, upload-time = "2026-02-02T12:37:22.124Z" }, + { url = "https://files.pythonhosted.org/packages/79/b3/3c29819a27178d0e461a8571fb63c6ae38be6dc36b78b3ec2876bbd6a910/jiter-0.13.0-graalpy311-graalpy242_311_native-macosx_10_12_x86_64.whl", hash = "sha256:b1cbfa133241d0e6bdab48dcdc2604e8ba81512f6bbd68ec3e8e1357dd3c316c", size = 307016, upload-time = "2026-02-02T12:37:42.755Z" }, + { url = "https://files.pythonhosted.org/packages/eb/ae/60993e4b07b1ac5ebe46da7aa99fdbb802eb986c38d26e3883ac0125c4e0/jiter-0.13.0-graalpy311-graalpy242_311_native-macosx_11_0_arm64.whl", hash = "sha256:db367d8be9fad6e8ebbac4a7578b7af562e506211036cba2c06c3b998603c3d2", size = 305024, upload-time = "2026-02-02T12:37:44.774Z" }, + { url = "https://files.pythonhosted.org/packages/77/fa/2227e590e9cf98803db2811f172b2d6460a21539ab73006f251c66f44b14/jiter-0.13.0-graalpy311-graalpy242_311_native-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:45f6f8efb2f3b0603092401dc2df79fa89ccbc027aaba4174d2d4133ed661434", size = 339337, upload-time = "2026-02-02T12:37:46.668Z" }, + { url = "https://files.pythonhosted.org/packages/2d/92/015173281f7eb96c0ef580c997da8ef50870d4f7f4c9e03c845a1d62ae04/jiter-0.13.0-graalpy311-graalpy242_311_native-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:597245258e6ad085d064780abfb23a284d418d3e61c57362d9449c6c7317ee2d", size = 346395, upload-time = "2026-02-02T12:37:48.09Z" }, + { url = "https://files.pythonhosted.org/packages/80/60/e50fa45dd7e2eae049f0ce964663849e897300433921198aef94b6ffa23a/jiter-0.13.0-graalpy312-graalpy250_312_native-macosx_10_12_x86_64.whl", hash = "sha256:3d744a6061afba08dd7ae375dcde870cffb14429b7477e10f67e9e6d68772a0a", size = 305169, upload-time = "2026-02-02T12:37:50.376Z" }, + { url = "https://files.pythonhosted.org/packages/d2/73/a009f41c5eed71c49bec53036c4b33555afcdee70682a18c6f66e396c039/jiter-0.13.0-graalpy312-graalpy250_312_native-macosx_11_0_arm64.whl", hash = "sha256:ff732bd0a0e778f43d5009840f20b935e79087b4dc65bd36f1cd0f9b04b8ff7f", size = 303808, upload-time = "2026-02-02T12:37:52.092Z" }, + { url = "https://files.pythonhosted.org/packages/c4/10/528b439290763bff3d939268085d03382471b442f212dca4ff5f12802d43/jiter-0.13.0-graalpy312-graalpy250_312_native-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ab44b178f7981fcaea7e0a5df20e773c663d06ffda0198f1a524e91b2fde7e59", size = 337384, upload-time = "2026-02-02T12:37:53.582Z" }, + { url = "https://files.pythonhosted.org/packages/67/8a/a342b2f0251f3dac4ca17618265d93bf244a2a4d089126e81e4c1056ac50/jiter-0.13.0-graalpy312-graalpy250_312_native-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7bb00b6d26db67a05fe3e12c76edc75f32077fb51deed13822dc648fa373bc19", size = 343768, upload-time = "2026-02-02T12:37:55.055Z" }, ] [[package]] @@ -2334,11 +2411,11 @@ wheels = [ [[package]] name = "jsonpointer" -version = "3.0.0" +version = "3.1.1" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/6a/0a/eebeb1fa92507ea94016a2a790b93c2ae41a7e18778f85471dc54475ed25/jsonpointer-3.0.0.tar.gz", hash = "sha256:2b2d729f2091522d61c3b31f82e11870f60b68f43fbc705cb76bf4b832af59ef", size = 9114, upload-time = "2024-06-10T19:24:42.462Z" } +sdist = { url = "https://files.pythonhosted.org/packages/18/c7/af399a2e7a67fd18d63c40c5e62d3af4e67b836a2107468b6a5ea24c4304/jsonpointer-3.1.1.tar.gz", hash = "sha256:0b801c7db33a904024f6004d526dcc53bbb8a4a0f4e32bfd10beadf60adf1900", size = 9068, upload-time = "2026-03-23T22:32:32.458Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/71/92/5e77f98553e9e75130c78900d000368476aed74276eb8ae8796f65f00918/jsonpointer-3.0.0-py2.py3-none-any.whl", hash = "sha256:13e088adc14fca8b6aa8177c044e12701e6ad4b28ff10e65f2267a90109c9942", size = 7595, upload-time = "2024-06-10T19:24:40.698Z" }, + { url = "https://files.pythonhosted.org/packages/9e/6a/a83720e953b1682d2d109d3c2dbb0bc9bf28cc1cbc205be4ef4be5da709d/jsonpointer-3.1.1-py3-none-any.whl", hash = "sha256:8ff8b95779d071ba472cf5bc913028df06031797532f08a7d5b602d8b2a488ca", size = 7659, upload-time = "2026-03-23T22:32:31.568Z" }, ] [[package]] @@ -2384,7 +2461,7 @@ wheels = [ [[package]] name = "keyring" -version = "25.6.0" +version = "25.7.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "importlib-metadata", marker = "python_full_version < '3.12'" }, @@ -2395,9 +2472,9 @@ dependencies = [ { name = "pywin32-ctypes", marker = "sys_platform == 'win32'" }, { name = "secretstorage", marker = "sys_platform == 'linux'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/70/09/d904a6e96f76ff214be59e7aa6ef7190008f52a0ab6689760a98de0bf37d/keyring-25.6.0.tar.gz", hash = "sha256:0b39998aa941431eb3d9b0d4b2460bc773b9df6fed7621c2dfb291a7e0187a66", size = 62750, upload-time = "2024-12-25T15:26:45.782Z" } +sdist = { url = "https://files.pythonhosted.org/packages/43/4b/674af6ef2f97d56f0ab5153bf0bfa28ccb6c3ed4d1babf4305449668807b/keyring-25.7.0.tar.gz", hash = "sha256:fe01bd85eb3f8fb3dd0405defdeac9a5b4f6f0439edbb3149577f244a2e8245b", size = 63516, upload-time = "2025-11-16T16:26:09.482Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/d3/32/da7f44bcb1105d3e88a0b74ebdca50c59121d2ddf71c9e34ba47df7f3a56/keyring-25.6.0-py3-none-any.whl", hash = "sha256:552a3f7af126ece7ed5c89753650eec89c7eaae8617d0aa4d9ad2b75111266bd", size = 39085, upload-time = "2024-12-25T15:26:44.377Z" }, + { url = "https://files.pythonhosted.org/packages/81/db/e655086b7f3a705df045bf0933bdd9c2f79bb3c97bfef1384598bb79a217/keyring-25.7.0-py3-none-any.whl", hash = "sha256:be4a0b195f149690c166e850609a477c532ddbfbaed96a404d4e43f8d5e2689f", size = 39160, upload-time = "2025-11-16T16:26:08.402Z" }, ] [[package]] @@ -2447,7 +2524,7 @@ wheels = [ [[package]] name = "litellm" -version = "1.78.0" +version = "1.83.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "aiohttp", marker = "python_full_version < '3.14'" }, @@ -2463,18 +2540,18 @@ dependencies = [ { name = "tiktoken", marker = "python_full_version < '3.14'" }, { name = "tokenizers", marker = "python_full_version < '3.14'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/fd/3e/1a96a3caeeb6092d85e70904e2caa98598abb7179cefe734e2fbffac6978/litellm-1.78.0.tar.gz", hash = "sha256:020e40e0d6e16009bb3a6b156d4c1d98cb5c33704aa340fdf9ffd014bfd31f3b", size = 10684595, upload-time = "2025-10-11T19:28:27.369Z" } +sdist = { url = "https://files.pythonhosted.org/packages/22/92/6ce9737554994ca8e536e5f4f6a87cc7c4774b656c9eb9add071caf7d54b/litellm-1.83.0.tar.gz", hash = "sha256:860bebc76c4bb27b4cf90b4a77acd66dba25aced37e3db98750de8a1766bfb7a", size = 17333062, upload-time = "2026-03-31T05:08:25.331Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/fc/fb/38a48efe3e05a8e9a9765b991740282e0358a83fb896ec00d70bf1448791/litellm-1.78.0-py3-none-any.whl", hash = "sha256:a9d6deee882de8df38ca24beb930689f49209340137ff8a3dcab0c5fc4a0513d", size = 9677983, upload-time = "2025-10-11T19:28:23.242Z" }, + { url = "https://files.pythonhosted.org/packages/19/2c/a670cc050fcd6f45c6199eb99e259c73aea92edba8d5c2fc1b3686d36217/litellm-1.83.0-py3-none-any.whl", hash = "sha256:88c536d339248f3987571493015784671ba3f193a328e1ea6780dbebaa2094a8", size = 15610306, upload-time = "2026-03-31T05:08:21.987Z" }, ] [[package]] name = "lunr" -version = "0.7.0.post1" +version = "0.8.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/8b/92/885c5e6251b76d3a171ff757a4e167cbb44c02fd9aff67b545a246778a6a/lunr-0.7.0.post1.tar.gz", hash = "sha256:00fc98f59b53c7ee0f6384c99e6c099f28cb746ecfff865bbc3705c3e9104bda", size = 1146070, upload-time = "2023-08-16T16:51:34.135Z" } +sdist = { url = "https://files.pythonhosted.org/packages/43/e9/b3dee02312eaa2a1b3212b6e20a90a81adba489b404d4f0ffbbe8258b761/lunr-0.8.0.tar.gz", hash = "sha256:b46cf5059578d277a14bfc901bb3d5666d013bf73c035331ac0222fdac358228", size = 1147598, upload-time = "2025-03-08T13:31:40.907Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/51/6c/9209b793fc98f9211846f3b2ec63e0780d30c26b9a0f2985100430dcd238/lunr-0.7.0.post1-py3-none-any.whl", hash = "sha256:77cce585d195d412cff362698799c9571ff3e285fc6bd8816ecbc9ec82dbb368", size = 35209, upload-time = "2023-08-16T16:51:31.589Z" }, + { url = "https://files.pythonhosted.org/packages/6c/8b/bf975fabd26195915ebdf3e4252baa936f1863bcd9eb49598b705638f5d5/lunr-0.8.0-py3-none-any.whl", hash = "sha256:a2bc4e08dbb35b32723006bf2edbe6dc1f4f4b95955eea0d23165a184d276ce8", size = 35211, upload-time = "2025-03-08T13:31:38.657Z" }, ] [[package]] @@ -2588,31 +2665,31 @@ wheels = [ [[package]] name = "maturin" -version = "1.9.6" +version = "1.12.6" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "tomli", marker = "python_full_version < '3.11'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/9a/35/c3370188492f4c139c7a318f438d01b8185c216303c49c4bc885c98b6afb/maturin-1.9.6.tar.gz", hash = "sha256:2c2ae37144811d365509889ed7220b0598487f1278c2441829c3abf56cc6324a", size = 214846, upload-time = "2025-10-07T12:45:08.408Z" } +sdist = { url = "https://files.pythonhosted.org/packages/0c/18/8b2eebd3ea086a5ec73d7081f95ec64918ceda1900075902fc296ea3ad55/maturin-1.12.6.tar.gz", hash = "sha256:d37be3a811a7f2ee28a0fa0964187efa50e90f21da0c6135c27787fa0b6a89db", size = 269165, upload-time = "2026-03-01T14:54:04.21Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/55/5c/b435418ba4ba2647a1f7a95d53314991b1e556e656ae276dea993c3bce1d/maturin-1.9.6-py3-none-linux_armv6l.whl", hash = "sha256:26e3ab1a42a7145824210e9d763f6958f2c46afb1245ddd0bab7d78b1f59bb3f", size = 8134483, upload-time = "2025-10-07T12:44:44.274Z" }, - { url = "https://files.pythonhosted.org/packages/4d/1c/8e58eda6601f328b412cdeeaa88a9b6a10e591e2a73f313e8c0154d68385/maturin-1.9.6-py3-none-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:5263dda3f71feef2e4122baf5c4620e4b3710dbb7f2121f85a337182de214369", size = 15776470, upload-time = "2025-10-07T12:44:47.476Z" }, - { url = "https://files.pythonhosted.org/packages/6c/33/8c967cce6848cdd87a2e442c86120ac644b80c5ed4c32e3291bde6a17df8/maturin-1.9.6-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:fe78262c2800c92f67d1ce3c0f6463f958a692cc67bfb572e5dbf5b4b696a8ba", size = 8226557, upload-time = "2025-10-07T12:44:49.844Z" }, - { url = "https://files.pythonhosted.org/packages/58/bd/3e2675cdc8b7270700ba30c663c852a35694441732a107ac30ebd6878bd8/maturin-1.9.6-py3-none-manylinux_2_12_i686.manylinux2010_i686.musllinux_1_1_i686.whl", hash = "sha256:7ab827c6e8c022eb2e1e7fb6deede54549c8460b20ccc2e9268cc6e8cde957a8", size = 8166544, upload-time = "2025-10-07T12:44:51.396Z" }, - { url = "https://files.pythonhosted.org/packages/58/1f/a2047ddf2230e700d5f8a13dd4b9af5ce806ad380c32e58105888205926e/maturin-1.9.6-py3-none-manylinux_2_12_x86_64.manylinux2010_x86_64.musllinux_1_1_x86_64.whl", hash = "sha256:0246202377c49449315305209f45c8ecef6e2d6bd27a04b5b6f1ab3e4ea47238", size = 8641010, upload-time = "2025-10-07T12:44:53.658Z" }, - { url = "https://files.pythonhosted.org/packages/be/1f/265d63c7aa6faf363d4a3f23396f51bc6b4d5c7680a4190ae68dba25dea2/maturin-1.9.6-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.musllinux_1_1_aarch64.whl", hash = "sha256:f5bac167700fbb6f8c8ed1a97b494522554b4432d7578e11403b894b6a91d99f", size = 7965945, upload-time = "2025-10-07T12:44:55.248Z" }, - { url = "https://files.pythonhosted.org/packages/4c/ca/a8e61979ccfe080948bcc1bddd79356157aee687134df7fb013050cec783/maturin-1.9.6-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.musllinux_1_1_armv7l.whl", hash = "sha256:7f53d3b1d8396d3fea3e1ee5fd37558bca5719090f3d194ba1c02b0b56327ae3", size = 7978820, upload-time = "2025-10-07T12:44:56.919Z" }, - { url = "https://files.pythonhosted.org/packages/bf/4a/81b412f8ad02a99801ef19ec059fba0822d1d28fb44cb6a92e722f05f278/maturin-1.9.6-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.musllinux_1_1_ppc64le.whl", hash = "sha256:7f506eb358386d94d6ec3208c003130cf4b69cab26034fc0cbbf8bf83afa4c2e", size = 10452064, upload-time = "2025-10-07T12:44:58.232Z" }, - { url = "https://files.pythonhosted.org/packages/5b/12/cc96c7a8cb51d8dcc9badd886c361caa1526fba7fa69d1e7892e613b71d4/maturin-1.9.6-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f2d6984ab690af509f525dbd2b130714207c06ebb14a5814edbe1e42b17ae0de", size = 8852401, upload-time = "2025-10-07T12:44:59.8Z" }, - { url = "https://files.pythonhosted.org/packages/51/8e/653ac3c9f2c25cdd81aefb0a2d17ff140ca5a14504f5e3c7f94dcfe4dbb7/maturin-1.9.6-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:5c2252b0956bb331460ac750c805ddf0d9b44442449fc1f16e3b66941689d0bc", size = 8425057, upload-time = "2025-10-07T12:45:01.711Z" }, - { url = "https://files.pythonhosted.org/packages/db/29/f13490328764ae9bfc1da55afc5b707cebe4fa75ad7a1573bfa82cfae0c6/maturin-1.9.6-py3-none-win32.whl", hash = "sha256:f2c58d29ebdd4346fd004e6be213d071fdd94a77a16aa91474a21a4f9dbf6309", size = 7165956, upload-time = "2025-10-07T12:45:03.766Z" }, - { url = "https://files.pythonhosted.org/packages/db/9f/dd51e5ac1fce47581b8efa03d77a03f928c0ef85b6e48a61dfa37b6b85a2/maturin-1.9.6-py3-none-win_amd64.whl", hash = "sha256:1b39a5d82572c240d20d9e8be024d722dfb311d330c5e28ddeb615211755941a", size = 8145722, upload-time = "2025-10-07T12:45:05.487Z" }, - { url = "https://files.pythonhosted.org/packages/65/f2/e97aaba6d0d78c5871771bf9dd71d4eb8dac15df9109cf452748d2207412/maturin-1.9.6-py3-none-win_arm64.whl", hash = "sha256:ac02a30083553d2a781c10cd6f5480119bf6692fd177e743267406cad2ad198c", size = 6857006, upload-time = "2025-10-07T12:45:06.813Z" }, + { url = "https://files.pythonhosted.org/packages/71/8b/9ddfde8a485489e3ebdc50ee3042ef1c854f00dfea776b951068f6ffe451/maturin-1.12.6-py3-none-linux_armv6l.whl", hash = "sha256:6892b4176992fcc143f9d1c1c874a816e9a041248eef46433db87b0f0aff4278", size = 9789847, upload-time = "2026-03-01T14:54:09.172Z" }, + { url = "https://files.pythonhosted.org/packages/ef/e8/5f7fd3763f214a77ac0388dbcc71cc30aec5490016bd0c8e6bd729fc7b0a/maturin-1.12.6-py3-none-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:c0c742beeeef7fb93b6a81bd53e75507887e396fd1003c45117658d063812dad", size = 19023833, upload-time = "2026-03-01T14:53:46.743Z" }, + { url = "https://files.pythonhosted.org/packages/e0/7f/706ff3839c8b2046436d4c2bc97596c558728264d18abc298a1ad862a4be/maturin-1.12.6-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:2cb41139295eed6411d3cdafc7430738094c2721f34b7eeb44f33cac516115dc", size = 9821620, upload-time = "2026-03-01T14:54:12.04Z" }, + { url = "https://files.pythonhosted.org/packages/0e/9c/70917fb123c8dd6b595e913616c9c72d730cbf4a2b6cac8077dc02a12586/maturin-1.12.6-py3-none-manylinux_2_12_i686.manylinux2010_i686.musllinux_1_1_i686.whl", hash = "sha256:351f3af1488a7cbdcff3b6d8482c17164273ac981378a13a4a9937a49aec7d71", size = 9849107, upload-time = "2026-03-01T14:53:48.971Z" }, + { url = "https://files.pythonhosted.org/packages/59/ea/f1d6ad95c0a12fbe761a7c28a57540341f188564dbe8ad730a4d1788cd32/maturin-1.12.6-py3-none-manylinux_2_12_x86_64.manylinux2010_x86_64.musllinux_1_1_x86_64.whl", hash = "sha256:6dbddfe4dc7ddee60bbac854870bd7cfec660acb54d015d24597d59a1c828f61", size = 10242855, upload-time = "2026-03-01T14:53:44.605Z" }, + { url = "https://files.pythonhosted.org/packages/93/1b/2419843a4f1d2fb4747f3dc3d9c4a2881cd97a3274dd94738fcdf0835e79/maturin-1.12.6-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.musllinux_1_1_aarch64.whl", hash = "sha256:8fdb0f63e77ee3df0f027a120e9af78dbc31edf0eb0f263d55783c250c33b728", size = 9674972, upload-time = "2026-03-01T14:53:52.763Z" }, + { url = "https://files.pythonhosted.org/packages/71/46/b60ab2fc996d904b40e55bd475599dcdccd8f7ad3e649bf95e87970df466/maturin-1.12.6-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.musllinux_1_1_armv7l.whl", hash = "sha256:fa84b7493a2e80759cacc2e668fa5b444d55b9994e90707c42904f55d6322c1e", size = 9645755, upload-time = "2026-03-01T14:53:58.497Z" }, + { url = "https://files.pythonhosted.org/packages/a4/96/03f2b55a8c226805115232fc23c4a4f33f0c9d39e11efab8166dc440f80d/maturin-1.12.6-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.musllinux_1_1_ppc64le.whl", hash = "sha256:e90dc12bc6a38e9495692a36c9e231c4d7e0c9bfde60719468ab7d8673db3c45", size = 12737612, upload-time = "2026-03-01T14:54:05.393Z" }, + { url = "https://files.pythonhosted.org/packages/2b/c2/648667022c5b53cdccefa67c245e8a984970f3045820f00c2e23bdb2aff4/maturin-1.12.6-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:06fc8d089f98623ce924c669b70911dfed30f9a29956c362945f727f9abc546b", size = 10455028, upload-time = "2026-03-01T14:54:07.349Z" }, + { url = "https://files.pythonhosted.org/packages/63/d6/5b5efe3ca0c043357ed3f8d2b2d556169fdbf1ff75e50e8e597708a359d2/maturin-1.12.6-py3-none-manylinux_2_31_riscv64.musllinux_1_1_riscv64.whl", hash = "sha256:75133e56274d43b9227fd49dca9a86e32f1fd56a7b55544910c4ce978c2bb5aa", size = 10014531, upload-time = "2026-03-01T14:53:54.548Z" }, + { url = "https://files.pythonhosted.org/packages/68/d5/39c594c27b1a8b32a0cb95fff9ad60b888c4352d1d1c389ac1bd20dc1e16/maturin-1.12.6-py3-none-win32.whl", hash = "sha256:3f32e0a3720b81423c9d35c14e728cb1f954678124749776dc72d533ea1115e8", size = 8553012, upload-time = "2026-03-01T14:53:50.706Z" }, + { url = "https://files.pythonhosted.org/packages/94/66/b262832a91747e04051e21f986bd01a8af81fbffafacc7d66a11e79aab5f/maturin-1.12.6-py3-none-win_amd64.whl", hash = "sha256:977290159d252db946054a0555263c59b3d0c7957135c69e690f4b1558ee9983", size = 9890470, upload-time = "2026-03-01T14:53:56.659Z" }, + { url = "https://files.pythonhosted.org/packages/e3/47/76b8ca470ddc8d7d36aa8c15f5a6aed1841806bb93a0f4ead8ee61e9a088/maturin-1.12.6-py3-none-win_arm64.whl", hash = "sha256:bae91976cdc8148038e13c881e1e844e5c63e58e026e8b9945aa2d19b3b4ae89", size = 8606158, upload-time = "2026-03-01T14:54:02.423Z" }, ] [[package]] name = "mcp" -version = "1.23.0" +version = "1.27.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "anyio" }, @@ -2630,9 +2707,9 @@ dependencies = [ { name = "typing-inspection" }, { name = "uvicorn", marker = "sys_platform != 'emscripten'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/25/1a/9c8a5362e3448d585081d6c7aa95898a64e0ac59d3e26169ae6c3ca5feaf/mcp-1.23.0.tar.gz", hash = "sha256:84e0c29316d0a8cf0affd196fd000487ac512aa3f771b63b2ea864e22961772b", size = 596506, upload-time = "2025-12-02T13:40:02.558Z" } +sdist = { url = "https://files.pythonhosted.org/packages/8b/eb/c0cfc62075dc6e1ec1c64d352ae09ac051d9334311ed226f1f425312848a/mcp-1.27.0.tar.gz", hash = "sha256:d3dc35a7eec0d458c1da4976a48f982097ddaab87e278c5511d5a4a56e852b83", size = 607509, upload-time = "2026-04-02T14:48:08.88Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/7b/b2/28739ce409f98159c0121eab56e69ad71546c4f34ac8b42e58c03f57dccc/mcp-1.23.0-py3-none-any.whl", hash = "sha256:5a645cf111ed329f4619f2629a3f15d9aabd7adc2ea09d600d31467b51ecb64f", size = 231427, upload-time = "2025-12-02T13:40:00.738Z" }, + { url = "https://files.pythonhosted.org/packages/9c/46/f6b4ad632c67ef35209a66127e4bddc95759649dd595f71f13fba11bdf9a/mcp-1.27.0-py3-none-any.whl", hash = "sha256:5ce1fa81614958e267b21fb2aa34e0aea8e2c6ede60d52aba45fd47246b4d741", size = 215967, upload-time = "2026-04-02T14:48:07.24Z" }, ] [[package]] @@ -2760,11 +2837,11 @@ wheels = [ [[package]] name = "more-itertools" -version = "10.8.0" +version = "11.0.1" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/ea/5d/38b681d3fce7a266dd9ab73c66959406d565b3e85f21d5e66e1181d93721/more_itertools-10.8.0.tar.gz", hash = "sha256:f638ddf8a1a0d134181275fb5d58b086ead7c6a72429ad725c67503f13ba30bd", size = 137431, upload-time = "2025-09-02T15:23:11.018Z" } +sdist = { url = "https://files.pythonhosted.org/packages/24/24/e0acc4bf54cba50c1d432c70a72a3df96db4a321b2c4c68432a60759044f/more_itertools-11.0.1.tar.gz", hash = "sha256:fefaf25b7ab08f0b45fa9f1892cae93b9fc0089ef034d39213bce15f1cc9e199", size = 144739, upload-time = "2026-04-02T16:17:45.061Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/a4/8e/469e5a4a2f5855992e425f3cb33804cc07bf18d48f2db061aec61ce50270/more_itertools-10.8.0-py3-none-any.whl", hash = "sha256:52d4362373dcf7c52546bc4af9a86ee7c4579df9a8dc268be0a2f949d376cc9b", size = 69667, upload-time = "2025-09-02T15:23:09.635Z" }, + { url = "https://files.pythonhosted.org/packages/d8/f4/5e52c7319b8087acef603ed6e50dc325c02eaa999355414830468611f13c/more_itertools-11.0.1-py3-none-any.whl", hash = "sha256:eaf287826069452a8f61026c597eae2428b2d1ba2859083abbf240b46842ce6d", size = 72182, upload-time = "2026-04-02T16:17:43.724Z" }, ] [[package]] @@ -2883,140 +2960,140 @@ wheels = [ [[package]] name = "multidict" -version = "6.7.0" +version = "6.7.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "typing-extensions", marker = "python_full_version < '3.11'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/80/1e/5492c365f222f907de1039b91f922b93fa4f764c713ee858d235495d8f50/multidict-6.7.0.tar.gz", hash = "sha256:c6e99d9a65ca282e578dfea819cfa9c0a62b2499d8677392e09feaf305e9e6f5", size = 101834, upload-time = "2025-10-06T14:52:30.657Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/a9/63/7bdd4adc330abcca54c85728db2327130e49e52e8c3ce685cec44e0f2e9f/multidict-6.7.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:9f474ad5acda359c8758c8accc22032c6abe6dc87a8be2440d097785e27a9349", size = 77153, upload-time = "2025-10-06T14:48:26.409Z" }, - { url = "https://files.pythonhosted.org/packages/3f/bb/b6c35ff175ed1a3142222b78455ee31be71a8396ed3ab5280fbe3ebe4e85/multidict-6.7.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:4b7a9db5a870f780220e931d0002bbfd88fb53aceb6293251e2c839415c1b20e", size = 44993, upload-time = "2025-10-06T14:48:28.4Z" }, - { url = "https://files.pythonhosted.org/packages/e0/1f/064c77877c5fa6df6d346e68075c0f6998547afe952d6471b4c5f6a7345d/multidict-6.7.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:03ca744319864e92721195fa28c7a3b2bc7b686246b35e4078c1e4d0eb5466d3", size = 44607, upload-time = "2025-10-06T14:48:29.581Z" }, - { url = "https://files.pythonhosted.org/packages/04/7a/bf6aa92065dd47f287690000b3d7d332edfccb2277634cadf6a810463c6a/multidict-6.7.0-cp310-cp310-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:f0e77e3c0008bc9316e662624535b88d360c3a5d3f81e15cf12c139a75250046", size = 241847, upload-time = "2025-10-06T14:48:32.107Z" }, - { url = "https://files.pythonhosted.org/packages/94/39/297a8de920f76eda343e4ce05f3b489f0ab3f9504f2576dfb37b7c08ca08/multidict-6.7.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:08325c9e5367aa379a3496aa9a022fe8837ff22e00b94db256d3a1378c76ab32", size = 242616, upload-time = "2025-10-06T14:48:34.054Z" }, - { url = "https://files.pythonhosted.org/packages/39/3a/d0eee2898cfd9d654aea6cb8c4addc2f9756e9a7e09391cfe55541f917f7/multidict-6.7.0-cp310-cp310-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:e2862408c99f84aa571ab462d25236ef9cb12a602ea959ba9c9009a54902fc73", size = 222333, upload-time = "2025-10-06T14:48:35.9Z" }, - { url = "https://files.pythonhosted.org/packages/05/48/3b328851193c7a4240815b71eea165b49248867bbb6153a0aee227a0bb47/multidict-6.7.0-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:4d72a9a2d885f5c208b0cb91ff2ed43636bb7e345ec839ff64708e04f69a13cc", size = 253239, upload-time = "2025-10-06T14:48:37.302Z" }, - { url = "https://files.pythonhosted.org/packages/b1/ca/0706a98c8d126a89245413225ca4a3fefc8435014de309cf8b30acb68841/multidict-6.7.0-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:478cc36476687bac1514d651cbbaa94b86b0732fb6855c60c673794c7dd2da62", size = 251618, upload-time = "2025-10-06T14:48:38.963Z" }, - { url = "https://files.pythonhosted.org/packages/5e/4f/9c7992f245554d8b173f6f0a048ad24b3e645d883f096857ec2c0822b8bd/multidict-6.7.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6843b28b0364dc605f21481c90fadb5f60d9123b442eb8a726bb74feef588a84", size = 241655, upload-time = "2025-10-06T14:48:40.312Z" }, - { url = "https://files.pythonhosted.org/packages/31/79/26a85991ae67efd1c0b1fc2e0c275b8a6aceeb155a68861f63f87a798f16/multidict-6.7.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:23bfeee5316266e5ee2d625df2d2c602b829435fc3a235c2ba2131495706e4a0", size = 239245, upload-time = "2025-10-06T14:48:41.848Z" }, - { url = "https://files.pythonhosted.org/packages/14/1e/75fa96394478930b79d0302eaf9a6c69f34005a1a5251ac8b9c336486ec9/multidict-6.7.0-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:680878b9f3d45c31e1f730eef731f9b0bc1da456155688c6745ee84eb818e90e", size = 233523, upload-time = "2025-10-06T14:48:43.749Z" }, - { url = "https://files.pythonhosted.org/packages/b2/5e/085544cb9f9c4ad2b5d97467c15f856df8d9bac410cffd5c43991a5d878b/multidict-6.7.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:eb866162ef2f45063acc7a53a88ef6fe8bf121d45c30ea3c9cd87ce7e191a8d4", size = 243129, upload-time = "2025-10-06T14:48:45.225Z" }, - { url = "https://files.pythonhosted.org/packages/b9/c3/e9d9e2f20c9474e7a8fcef28f863c5cbd29bb5adce6b70cebe8bdad0039d/multidict-6.7.0-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:df0e3bf7993bdbeca5ac25aa859cf40d39019e015c9c91809ba7093967f7a648", size = 248999, upload-time = "2025-10-06T14:48:46.703Z" }, - { url = "https://files.pythonhosted.org/packages/b5/3f/df171b6efa3239ae33b97b887e42671cd1d94d460614bfb2c30ffdab3b95/multidict-6.7.0-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:661709cdcd919a2ece2234f9bae7174e5220c80b034585d7d8a755632d3e2111", size = 243711, upload-time = "2025-10-06T14:48:48.146Z" }, - { url = "https://files.pythonhosted.org/packages/3c/2f/9b5564888c4e14b9af64c54acf149263721a283aaf4aa0ae89b091d5d8c1/multidict-6.7.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:096f52730c3fb8ed419db2d44391932b63891b2c5ed14850a7e215c0ba9ade36", size = 237504, upload-time = "2025-10-06T14:48:49.447Z" }, - { url = "https://files.pythonhosted.org/packages/6c/3a/0bd6ca0f7d96d790542d591c8c3354c1e1b6bfd2024d4d92dc3d87485ec7/multidict-6.7.0-cp310-cp310-win32.whl", hash = "sha256:afa8a2978ec65d2336305550535c9c4ff50ee527914328c8677b3973ade52b85", size = 41422, upload-time = "2025-10-06T14:48:50.789Z" }, - { url = "https://files.pythonhosted.org/packages/00/35/f6a637ea2c75f0d3b7c7d41b1189189acff0d9deeb8b8f35536bb30f5e33/multidict-6.7.0-cp310-cp310-win_amd64.whl", hash = "sha256:b15b3afff74f707b9275d5ba6a91ae8f6429c3ffb29bbfd216b0b375a56f13d7", size = 46050, upload-time = "2025-10-06T14:48:51.938Z" }, - { url = "https://files.pythonhosted.org/packages/e7/b8/f7bf8329b39893d02d9d95cf610c75885d12fc0f402b1c894e1c8e01c916/multidict-6.7.0-cp310-cp310-win_arm64.whl", hash = "sha256:4b73189894398d59131a66ff157837b1fafea9974be486d036bb3d32331fdbf0", size = 43153, upload-time = "2025-10-06T14:48:53.146Z" }, - { url = "https://files.pythonhosted.org/packages/34/9e/5c727587644d67b2ed479041e4b1c58e30afc011e3d45d25bbe35781217c/multidict-6.7.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:4d409aa42a94c0b3fa617708ef5276dfe81012ba6753a0370fcc9d0195d0a1fc", size = 76604, upload-time = "2025-10-06T14:48:54.277Z" }, - { url = "https://files.pythonhosted.org/packages/17/e4/67b5c27bd17c085a5ea8f1ec05b8a3e5cba0ca734bfcad5560fb129e70ca/multidict-6.7.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:14c9e076eede3b54c636f8ce1c9c252b5f057c62131211f0ceeec273810c9721", size = 44715, upload-time = "2025-10-06T14:48:55.445Z" }, - { url = "https://files.pythonhosted.org/packages/4d/e1/866a5d77be6ea435711bef2a4291eed11032679b6b28b56b4776ab06ba3e/multidict-6.7.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:4c09703000a9d0fa3c3404b27041e574cc7f4df4c6563873246d0e11812a94b6", size = 44332, upload-time = "2025-10-06T14:48:56.706Z" }, - { url = "https://files.pythonhosted.org/packages/31/61/0c2d50241ada71ff61a79518db85ada85fdabfcf395d5968dae1cbda04e5/multidict-6.7.0-cp311-cp311-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:a265acbb7bb33a3a2d626afbe756371dce0279e7b17f4f4eda406459c2b5ff1c", size = 245212, upload-time = "2025-10-06T14:48:58.042Z" }, - { url = "https://files.pythonhosted.org/packages/ac/e0/919666a4e4b57fff1b57f279be1c9316e6cdc5de8a8b525d76f6598fefc7/multidict-6.7.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:51cb455de290ae462593e5b1cb1118c5c22ea7f0d3620d9940bf695cea5a4bd7", size = 246671, upload-time = "2025-10-06T14:49:00.004Z" }, - { url = "https://files.pythonhosted.org/packages/a1/cc/d027d9c5a520f3321b65adea289b965e7bcbd2c34402663f482648c716ce/multidict-6.7.0-cp311-cp311-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:db99677b4457c7a5c5a949353e125ba72d62b35f74e26da141530fbb012218a7", size = 225491, upload-time = "2025-10-06T14:49:01.393Z" }, - { url = "https://files.pythonhosted.org/packages/75/c4/bbd633980ce6155a28ff04e6a6492dd3335858394d7bb752d8b108708558/multidict-6.7.0-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:f470f68adc395e0183b92a2f4689264d1ea4b40504a24d9882c27375e6662bb9", size = 257322, upload-time = "2025-10-06T14:49:02.745Z" }, - { url = "https://files.pythonhosted.org/packages/4c/6d/d622322d344f1f053eae47e033b0b3f965af01212de21b10bcf91be991fb/multidict-6.7.0-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:0db4956f82723cc1c270de9c6e799b4c341d327762ec78ef82bb962f79cc07d8", size = 254694, upload-time = "2025-10-06T14:49:04.15Z" }, - { url = "https://files.pythonhosted.org/packages/a8/9f/78f8761c2705d4c6d7516faed63c0ebdac569f6db1bef95e0d5218fdc146/multidict-6.7.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:3e56d780c238f9e1ae66a22d2adf8d16f485381878250db8d496623cd38b22bd", size = 246715, upload-time = "2025-10-06T14:49:05.967Z" }, - { url = "https://files.pythonhosted.org/packages/78/59/950818e04f91b9c2b95aab3d923d9eabd01689d0dcd889563988e9ea0fd8/multidict-6.7.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:9d14baca2ee12c1a64740d4531356ba50b82543017f3ad6de0deb943c5979abb", size = 243189, upload-time = "2025-10-06T14:49:07.37Z" }, - { url = "https://files.pythonhosted.org/packages/7a/3d/77c79e1934cad2ee74991840f8a0110966d9599b3af95964c0cd79bb905b/multidict-6.7.0-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:295a92a76188917c7f99cda95858c822f9e4aae5824246bba9b6b44004ddd0a6", size = 237845, upload-time = "2025-10-06T14:49:08.759Z" }, - { url = "https://files.pythonhosted.org/packages/63/1b/834ce32a0a97a3b70f86437f685f880136677ac00d8bce0027e9fd9c2db7/multidict-6.7.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:39f1719f57adbb767ef592a50ae5ebb794220d1188f9ca93de471336401c34d2", size = 246374, upload-time = "2025-10-06T14:49:10.574Z" }, - { url = "https://files.pythonhosted.org/packages/23/ef/43d1c3ba205b5dec93dc97f3fba179dfa47910fc73aaaea4f7ceb41cec2a/multidict-6.7.0-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:0a13fb8e748dfc94749f622de065dd5c1def7e0d2216dba72b1d8069a389c6ff", size = 253345, upload-time = "2025-10-06T14:49:12.331Z" }, - { url = "https://files.pythonhosted.org/packages/6b/03/eaf95bcc2d19ead522001f6a650ef32811aa9e3624ff0ad37c445c7a588c/multidict-6.7.0-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:e3aa16de190d29a0ea1b48253c57d99a68492c8dd8948638073ab9e74dc9410b", size = 246940, upload-time = "2025-10-06T14:49:13.821Z" }, - { url = "https://files.pythonhosted.org/packages/e8/df/ec8a5fd66ea6cd6f525b1fcbb23511b033c3e9bc42b81384834ffa484a62/multidict-6.7.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:a048ce45dcdaaf1defb76b2e684f997fb5abf74437b6cb7b22ddad934a964e34", size = 242229, upload-time = "2025-10-06T14:49:15.603Z" }, - { url = "https://files.pythonhosted.org/packages/8a/a2/59b405d59fd39ec86d1142630e9049243015a5f5291ba49cadf3c090c541/multidict-6.7.0-cp311-cp311-win32.whl", hash = "sha256:a90af66facec4cebe4181b9e62a68be65e45ac9b52b67de9eec118701856e7ff", size = 41308, upload-time = "2025-10-06T14:49:16.871Z" }, - { url = "https://files.pythonhosted.org/packages/32/0f/13228f26f8b882c34da36efa776c3b7348455ec383bab4a66390e42963ae/multidict-6.7.0-cp311-cp311-win_amd64.whl", hash = "sha256:95b5ffa4349df2887518bb839409bcf22caa72d82beec453216802f475b23c81", size = 46037, upload-time = "2025-10-06T14:49:18.457Z" }, - { url = "https://files.pythonhosted.org/packages/84/1f/68588e31b000535a3207fd3c909ebeec4fb36b52c442107499c18a896a2a/multidict-6.7.0-cp311-cp311-win_arm64.whl", hash = "sha256:329aa225b085b6f004a4955271a7ba9f1087e39dcb7e65f6284a988264a63912", size = 43023, upload-time = "2025-10-06T14:49:19.648Z" }, - { url = "https://files.pythonhosted.org/packages/c2/9e/9f61ac18d9c8b475889f32ccfa91c9f59363480613fc807b6e3023d6f60b/multidict-6.7.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:8a3862568a36d26e650a19bb5cbbba14b71789032aebc0423f8cc5f150730184", size = 76877, upload-time = "2025-10-06T14:49:20.884Z" }, - { url = "https://files.pythonhosted.org/packages/38/6f/614f09a04e6184f8824268fce4bc925e9849edfa654ddd59f0b64508c595/multidict-6.7.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:960c60b5849b9b4f9dcc9bea6e3626143c252c74113df2c1540aebce70209b45", size = 45467, upload-time = "2025-10-06T14:49:22.054Z" }, - { url = "https://files.pythonhosted.org/packages/b3/93/c4f67a436dd026f2e780c433277fff72be79152894d9fc36f44569cab1a6/multidict-6.7.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2049be98fb57a31b4ccf870bf377af2504d4ae35646a19037ec271e4c07998aa", size = 43834, upload-time = "2025-10-06T14:49:23.566Z" }, - { url = "https://files.pythonhosted.org/packages/7f/f5/013798161ca665e4a422afbc5e2d9e4070142a9ff8905e482139cd09e4d0/multidict-6.7.0-cp312-cp312-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:0934f3843a1860dd465d38895c17fce1f1cb37295149ab05cd1b9a03afacb2a7", size = 250545, upload-time = "2025-10-06T14:49:24.882Z" }, - { url = "https://files.pythonhosted.org/packages/71/2f/91dbac13e0ba94669ea5119ba267c9a832f0cb65419aca75549fcf09a3dc/multidict-6.7.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b3e34f3a1b8131ba06f1a73adab24f30934d148afcd5f5de9a73565a4404384e", size = 258305, upload-time = "2025-10-06T14:49:26.778Z" }, - { url = "https://files.pythonhosted.org/packages/ef/b0/754038b26f6e04488b48ac621f779c341338d78503fb45403755af2df477/multidict-6.7.0-cp312-cp312-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:efbb54e98446892590dc2458c19c10344ee9a883a79b5cec4bc34d6656e8d546", size = 242363, upload-time = "2025-10-06T14:49:28.562Z" }, - { url = "https://files.pythonhosted.org/packages/87/15/9da40b9336a7c9fa606c4cf2ed80a649dffeb42b905d4f63a1d7eb17d746/multidict-6.7.0-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:a35c5fc61d4f51eb045061e7967cfe3123d622cd500e8868e7c0c592a09fedc4", size = 268375, upload-time = "2025-10-06T14:49:29.96Z" }, - { url = "https://files.pythonhosted.org/packages/82/72/c53fcade0cc94dfaad583105fd92b3a783af2091eddcb41a6d5a52474000/multidict-6.7.0-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:29fe6740ebccba4175af1b9b87bf553e9c15cd5868ee967e010efcf94e4fd0f1", size = 269346, upload-time = "2025-10-06T14:49:31.404Z" }, - { url = "https://files.pythonhosted.org/packages/0d/e2/9baffdae21a76f77ef8447f1a05a96ec4bc0a24dae08767abc0a2fe680b8/multidict-6.7.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:123e2a72e20537add2f33a79e605f6191fba2afda4cbb876e35c1a7074298a7d", size = 256107, upload-time = "2025-10-06T14:49:32.974Z" }, - { url = "https://files.pythonhosted.org/packages/3c/06/3f06f611087dc60d65ef775f1fb5aca7c6d61c6db4990e7cda0cef9b1651/multidict-6.7.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:b284e319754366c1aee2267a2036248b24eeb17ecd5dc16022095e747f2f4304", size = 253592, upload-time = "2025-10-06T14:49:34.52Z" }, - { url = "https://files.pythonhosted.org/packages/20/24/54e804ec7945b6023b340c412ce9c3f81e91b3bf5fa5ce65558740141bee/multidict-6.7.0-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:803d685de7be4303b5a657b76e2f6d1240e7e0a8aa2968ad5811fa2285553a12", size = 251024, upload-time = "2025-10-06T14:49:35.956Z" }, - { url = "https://files.pythonhosted.org/packages/14/48/011cba467ea0b17ceb938315d219391d3e421dfd35928e5dbdc3f4ae76ef/multidict-6.7.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:c04a328260dfd5db8c39538f999f02779012268f54614902d0afc775d44e0a62", size = 251484, upload-time = "2025-10-06T14:49:37.631Z" }, - { url = "https://files.pythonhosted.org/packages/0d/2f/919258b43bb35b99fa127435cfb2d91798eb3a943396631ef43e3720dcf4/multidict-6.7.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:8a19cdb57cd3df4cd865849d93ee14920fb97224300c88501f16ecfa2604b4e0", size = 263579, upload-time = "2025-10-06T14:49:39.502Z" }, - { url = "https://files.pythonhosted.org/packages/31/22/a0e884d86b5242b5a74cf08e876bdf299e413016b66e55511f7a804a366e/multidict-6.7.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:9b2fd74c52accced7e75de26023b7dccee62511a600e62311b918ec5c168fc2a", size = 259654, upload-time = "2025-10-06T14:49:41.32Z" }, - { url = "https://files.pythonhosted.org/packages/b2/e5/17e10e1b5c5f5a40f2fcbb45953c9b215f8a4098003915e46a93f5fcaa8f/multidict-6.7.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:3e8bfdd0e487acf992407a140d2589fe598238eaeffa3da8448d63a63cd363f8", size = 251511, upload-time = "2025-10-06T14:49:46.021Z" }, - { url = "https://files.pythonhosted.org/packages/e3/9a/201bb1e17e7af53139597069c375e7b0dcbd47594604f65c2d5359508566/multidict-6.7.0-cp312-cp312-win32.whl", hash = "sha256:dd32a49400a2c3d52088e120ee00c1e3576cbff7e10b98467962c74fdb762ed4", size = 41895, upload-time = "2025-10-06T14:49:48.718Z" }, - { url = "https://files.pythonhosted.org/packages/46/e2/348cd32faad84eaf1d20cce80e2bb0ef8d312c55bca1f7fa9865e7770aaf/multidict-6.7.0-cp312-cp312-win_amd64.whl", hash = "sha256:92abb658ef2d7ef22ac9f8bb88e8b6c3e571671534e029359b6d9e845923eb1b", size = 46073, upload-time = "2025-10-06T14:49:50.28Z" }, - { url = "https://files.pythonhosted.org/packages/25/ec/aad2613c1910dce907480e0c3aa306905830f25df2e54ccc9dea450cb5aa/multidict-6.7.0-cp312-cp312-win_arm64.whl", hash = "sha256:490dab541a6a642ce1a9d61a4781656b346a55c13038f0b1244653828e3a83ec", size = 43226, upload-time = "2025-10-06T14:49:52.304Z" }, - { url = "https://files.pythonhosted.org/packages/d2/86/33272a544eeb36d66e4d9a920602d1a2f57d4ebea4ef3cdfe5a912574c95/multidict-6.7.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:bee7c0588aa0076ce77c0ea5d19a68d76ad81fcd9fe8501003b9a24f9d4000f6", size = 76135, upload-time = "2025-10-06T14:49:54.26Z" }, - { url = "https://files.pythonhosted.org/packages/91/1c/eb97db117a1ebe46d457a3d235a7b9d2e6dcab174f42d1b67663dd9e5371/multidict-6.7.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:7ef6b61cad77091056ce0e7ce69814ef72afacb150b7ac6a3e9470def2198159", size = 45117, upload-time = "2025-10-06T14:49:55.82Z" }, - { url = "https://files.pythonhosted.org/packages/f1/d8/6c3442322e41fb1dd4de8bd67bfd11cd72352ac131f6368315617de752f1/multidict-6.7.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:9c0359b1ec12b1d6849c59f9d319610b7f20ef990a6d454ab151aa0e3b9f78ca", size = 43472, upload-time = "2025-10-06T14:49:57.048Z" }, - { url = "https://files.pythonhosted.org/packages/75/3f/e2639e80325af0b6c6febdf8e57cc07043ff15f57fa1ef808f4ccb5ac4cd/multidict-6.7.0-cp313-cp313-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:cd240939f71c64bd658f186330603aac1a9a81bf6273f523fca63673cb7378a8", size = 249342, upload-time = "2025-10-06T14:49:58.368Z" }, - { url = "https://files.pythonhosted.org/packages/5d/cc/84e0585f805cbeaa9cbdaa95f9a3d6aed745b9d25700623ac89a6ecff400/multidict-6.7.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a60a4d75718a5efa473ebd5ab685786ba0c67b8381f781d1be14da49f1a2dc60", size = 257082, upload-time = "2025-10-06T14:49:59.89Z" }, - { url = "https://files.pythonhosted.org/packages/b0/9c/ac851c107c92289acbbf5cfb485694084690c1b17e555f44952c26ddc5bd/multidict-6.7.0-cp313-cp313-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:53a42d364f323275126aff81fb67c5ca1b7a04fda0546245730a55c8c5f24bc4", size = 240704, upload-time = "2025-10-06T14:50:01.485Z" }, - { url = "https://files.pythonhosted.org/packages/50/cc/5f93e99427248c09da95b62d64b25748a5f5c98c7c2ab09825a1d6af0e15/multidict-6.7.0-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:3b29b980d0ddbecb736735ee5bef69bb2ddca56eff603c86f3f29a1128299b4f", size = 266355, upload-time = "2025-10-06T14:50:02.955Z" }, - { url = "https://files.pythonhosted.org/packages/ec/0c/2ec1d883ceb79c6f7f6d7ad90c919c898f5d1c6ea96d322751420211e072/multidict-6.7.0-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:f8a93b1c0ed2d04b97a5e9336fd2d33371b9a6e29ab7dd6503d63407c20ffbaf", size = 267259, upload-time = "2025-10-06T14:50:04.446Z" }, - { url = "https://files.pythonhosted.org/packages/c6/2d/f0b184fa88d6630aa267680bdb8623fb69cb0d024b8c6f0d23f9a0f406d3/multidict-6.7.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9ff96e8815eecacc6645da76c413eb3b3d34cfca256c70b16b286a687d013c32", size = 254903, upload-time = "2025-10-06T14:50:05.98Z" }, - { url = "https://files.pythonhosted.org/packages/06/c9/11ea263ad0df7dfabcad404feb3c0dd40b131bc7f232d5537f2fb1356951/multidict-6.7.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:7516c579652f6a6be0e266aec0acd0db80829ca305c3d771ed898538804c2036", size = 252365, upload-time = "2025-10-06T14:50:07.511Z" }, - { url = "https://files.pythonhosted.org/packages/41/88/d714b86ee2c17d6e09850c70c9d310abac3d808ab49dfa16b43aba9d53fd/multidict-6.7.0-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:040f393368e63fb0f3330e70c26bfd336656bed925e5cbe17c9da839a6ab13ec", size = 250062, upload-time = "2025-10-06T14:50:09.074Z" }, - { url = "https://files.pythonhosted.org/packages/15/fe/ad407bb9e818c2b31383f6131ca19ea7e35ce93cf1310fce69f12e89de75/multidict-6.7.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:b3bc26a951007b1057a1c543af845f1c7e3e71cc240ed1ace7bf4484aa99196e", size = 249683, upload-time = "2025-10-06T14:50:10.714Z" }, - { url = "https://files.pythonhosted.org/packages/8c/a4/a89abdb0229e533fb925e7c6e5c40201c2873efebc9abaf14046a4536ee6/multidict-6.7.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:7b022717c748dd1992a83e219587aabe45980d88969f01b316e78683e6285f64", size = 261254, upload-time = "2025-10-06T14:50:12.28Z" }, - { url = "https://files.pythonhosted.org/packages/8d/aa/0e2b27bd88b40a4fb8dc53dd74eecac70edaa4c1dd0707eb2164da3675b3/multidict-6.7.0-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:9600082733859f00d79dee64effc7aef1beb26adb297416a4ad2116fd61374bd", size = 257967, upload-time = "2025-10-06T14:50:14.16Z" }, - { url = "https://files.pythonhosted.org/packages/d0/8e/0c67b7120d5d5f6d874ed85a085f9dc770a7f9d8813e80f44a9fec820bb7/multidict-6.7.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:94218fcec4d72bc61df51c198d098ce2b378e0ccbac41ddbed5ef44092913288", size = 250085, upload-time = "2025-10-06T14:50:15.639Z" }, - { url = "https://files.pythonhosted.org/packages/ba/55/b73e1d624ea4b8fd4dd07a3bb70f6e4c7c6c5d9d640a41c6ffe5cdbd2a55/multidict-6.7.0-cp313-cp313-win32.whl", hash = "sha256:a37bd74c3fa9d00be2d7b8eca074dc56bd8077ddd2917a839bd989612671ed17", size = 41713, upload-time = "2025-10-06T14:50:17.066Z" }, - { url = "https://files.pythonhosted.org/packages/32/31/75c59e7d3b4205075b4c183fa4ca398a2daf2303ddf616b04ae6ef55cffe/multidict-6.7.0-cp313-cp313-win_amd64.whl", hash = "sha256:30d193c6cc6d559db42b6bcec8a5d395d34d60c9877a0b71ecd7c204fcf15390", size = 45915, upload-time = "2025-10-06T14:50:18.264Z" }, - { url = "https://files.pythonhosted.org/packages/31/2a/8987831e811f1184c22bc2e45844934385363ee61c0a2dcfa8f71b87e608/multidict-6.7.0-cp313-cp313-win_arm64.whl", hash = "sha256:ea3334cabe4d41b7ccd01e4d349828678794edbc2d3ae97fc162a3312095092e", size = 43077, upload-time = "2025-10-06T14:50:19.853Z" }, - { url = "https://files.pythonhosted.org/packages/e8/68/7b3a5170a382a340147337b300b9eb25a9ddb573bcdfff19c0fa3f31ffba/multidict-6.7.0-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:ad9ce259f50abd98a1ca0aa6e490b58c316a0fce0617f609723e40804add2c00", size = 83114, upload-time = "2025-10-06T14:50:21.223Z" }, - { url = "https://files.pythonhosted.org/packages/55/5c/3fa2d07c84df4e302060f555bbf539310980362236ad49f50eeb0a1c1eb9/multidict-6.7.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:07f5594ac6d084cbb5de2df218d78baf55ef150b91f0ff8a21cc7a2e3a5a58eb", size = 48442, upload-time = "2025-10-06T14:50:22.871Z" }, - { url = "https://files.pythonhosted.org/packages/fc/56/67212d33239797f9bd91962bb899d72bb0f4c35a8652dcdb8ed049bef878/multidict-6.7.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:0591b48acf279821a579282444814a2d8d0af624ae0bc600aa4d1b920b6e924b", size = 46885, upload-time = "2025-10-06T14:50:24.258Z" }, - { url = "https://files.pythonhosted.org/packages/46/d1/908f896224290350721597a61a69cd19b89ad8ee0ae1f38b3f5cd12ea2ac/multidict-6.7.0-cp313-cp313t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:749a72584761531d2b9467cfbdfd29487ee21124c304c4b6cb760d8777b27f9c", size = 242588, upload-time = "2025-10-06T14:50:25.716Z" }, - { url = "https://files.pythonhosted.org/packages/ab/67/8604288bbd68680eee0ab568fdcb56171d8b23a01bcd5cb0c8fedf6e5d99/multidict-6.7.0-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6b4c3d199f953acd5b446bf7c0de1fe25d94e09e79086f8dc2f48a11a129cdf1", size = 249966, upload-time = "2025-10-06T14:50:28.192Z" }, - { url = "https://files.pythonhosted.org/packages/20/33/9228d76339f1ba51e3efef7da3ebd91964d3006217aae13211653193c3ff/multidict-6.7.0-cp313-cp313t-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:9fb0211dfc3b51efea2f349ec92c114d7754dd62c01f81c3e32b765b70c45c9b", size = 228618, upload-time = "2025-10-06T14:50:29.82Z" }, - { url = "https://files.pythonhosted.org/packages/f8/2d/25d9b566d10cab1c42b3b9e5b11ef79c9111eaf4463b8c257a3bd89e0ead/multidict-6.7.0-cp313-cp313t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:a027ec240fe73a8d6281872690b988eed307cd7d91b23998ff35ff577ca688b5", size = 257539, upload-time = "2025-10-06T14:50:31.731Z" }, - { url = "https://files.pythonhosted.org/packages/b6/b1/8d1a965e6637fc33de3c0d8f414485c2b7e4af00f42cab3d84e7b955c222/multidict-6.7.0-cp313-cp313t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:d1d964afecdf3a8288789df2f5751dc0a8261138c3768d9af117ed384e538fad", size = 256345, upload-time = "2025-10-06T14:50:33.26Z" }, - { url = "https://files.pythonhosted.org/packages/ba/0c/06b5a8adbdeedada6f4fb8d8f193d44a347223b11939b42953eeb6530b6b/multidict-6.7.0-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:caf53b15b1b7df9fbd0709aa01409000a2b4dd03a5f6f5cc548183c7c8f8b63c", size = 247934, upload-time = "2025-10-06T14:50:34.808Z" }, - { url = "https://files.pythonhosted.org/packages/8f/31/b2491b5fe167ca044c6eb4b8f2c9f3b8a00b24c432c365358eadac5d7625/multidict-6.7.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:654030da3197d927f05a536a66186070e98765aa5142794c9904555d3a9d8fb5", size = 245243, upload-time = "2025-10-06T14:50:36.436Z" }, - { url = "https://files.pythonhosted.org/packages/61/1a/982913957cb90406c8c94f53001abd9eafc271cb3e70ff6371590bec478e/multidict-6.7.0-cp313-cp313t-musllinux_1_2_armv7l.whl", hash = "sha256:2090d3718829d1e484706a2f525e50c892237b2bf9b17a79b059cb98cddc2f10", size = 235878, upload-time = "2025-10-06T14:50:37.953Z" }, - { url = "https://files.pythonhosted.org/packages/be/c0/21435d804c1a1cf7a2608593f4d19bca5bcbd7a81a70b253fdd1c12af9c0/multidict-6.7.0-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:2d2cfeec3f6f45651b3d408c4acec0ebf3daa9bc8a112a084206f5db5d05b754", size = 243452, upload-time = "2025-10-06T14:50:39.574Z" }, - { url = "https://files.pythonhosted.org/packages/54/0a/4349d540d4a883863191be6eb9a928846d4ec0ea007d3dcd36323bb058ac/multidict-6.7.0-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:4ef089f985b8c194d341eb2c24ae6e7408c9a0e2e5658699c92f497437d88c3c", size = 252312, upload-time = "2025-10-06T14:50:41.612Z" }, - { url = "https://files.pythonhosted.org/packages/26/64/d5416038dbda1488daf16b676e4dbfd9674dde10a0cc8f4fc2b502d8125d/multidict-6.7.0-cp313-cp313t-musllinux_1_2_s390x.whl", hash = "sha256:e93a0617cd16998784bf4414c7e40f17a35d2350e5c6f0bd900d3a8e02bd3762", size = 246935, upload-time = "2025-10-06T14:50:43.972Z" }, - { url = "https://files.pythonhosted.org/packages/9f/8c/8290c50d14e49f35e0bd4abc25e1bc7711149ca9588ab7d04f886cdf03d9/multidict-6.7.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:f0feece2ef8ebc42ed9e2e8c78fc4aa3cf455733b507c09ef7406364c94376c6", size = 243385, upload-time = "2025-10-06T14:50:45.648Z" }, - { url = "https://files.pythonhosted.org/packages/ef/a0/f83ae75e42d694b3fbad3e047670e511c138be747bc713cf1b10d5096416/multidict-6.7.0-cp313-cp313t-win32.whl", hash = "sha256:19a1d55338ec1be74ef62440ca9e04a2f001a04d0cc49a4983dc320ff0f3212d", size = 47777, upload-time = "2025-10-06T14:50:47.154Z" }, - { url = "https://files.pythonhosted.org/packages/dc/80/9b174a92814a3830b7357307a792300f42c9e94664b01dee8e457551fa66/multidict-6.7.0-cp313-cp313t-win_amd64.whl", hash = "sha256:3da4fb467498df97e986af166b12d01f05d2e04f978a9c1c680ea1988e0bc4b6", size = 53104, upload-time = "2025-10-06T14:50:48.851Z" }, - { url = "https://files.pythonhosted.org/packages/cc/28/04baeaf0428d95bb7a7bea0e691ba2f31394338ba424fb0679a9ed0f4c09/multidict-6.7.0-cp313-cp313t-win_arm64.whl", hash = "sha256:b4121773c49a0776461f4a904cdf6264c88e42218aaa8407e803ca8025872792", size = 45503, upload-time = "2025-10-06T14:50:50.16Z" }, - { url = "https://files.pythonhosted.org/packages/e2/b1/3da6934455dd4b261d4c72f897e3a5728eba81db59959f3a639245891baa/multidict-6.7.0-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:3bab1e4aff7adaa34410f93b1f8e57c4b36b9af0426a76003f441ee1d3c7e842", size = 75128, upload-time = "2025-10-06T14:50:51.92Z" }, - { url = "https://files.pythonhosted.org/packages/14/2c/f069cab5b51d175a1a2cb4ccdf7a2c2dabd58aa5bd933fa036a8d15e2404/multidict-6.7.0-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:b8512bac933afc3e45fb2b18da8e59b78d4f408399a960339598374d4ae3b56b", size = 44410, upload-time = "2025-10-06T14:50:53.275Z" }, - { url = "https://files.pythonhosted.org/packages/42/e2/64bb41266427af6642b6b128e8774ed84c11b80a90702c13ac0a86bb10cc/multidict-6.7.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:79dcf9e477bc65414ebfea98ffd013cb39552b5ecd62908752e0e413d6d06e38", size = 43205, upload-time = "2025-10-06T14:50:54.911Z" }, - { url = "https://files.pythonhosted.org/packages/02/68/6b086fef8a3f1a8541b9236c594f0c9245617c29841f2e0395d979485cde/multidict-6.7.0-cp314-cp314-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:31bae522710064b5cbeddaf2e9f32b1abab70ac6ac91d42572502299e9953128", size = 245084, upload-time = "2025-10-06T14:50:56.369Z" }, - { url = "https://files.pythonhosted.org/packages/15/ee/f524093232007cd7a75c1d132df70f235cfd590a7c9eaccd7ff422ef4ae8/multidict-6.7.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4a0df7ff02397bb63e2fd22af2c87dfa39e8c7f12947bc524dbdc528282c7e34", size = 252667, upload-time = "2025-10-06T14:50:57.991Z" }, - { url = "https://files.pythonhosted.org/packages/02/a5/eeb3f43ab45878f1895118c3ef157a480db58ede3f248e29b5354139c2c9/multidict-6.7.0-cp314-cp314-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:7a0222514e8e4c514660e182d5156a415c13ef0aabbd71682fc714e327b95e99", size = 233590, upload-time = "2025-10-06T14:50:59.589Z" }, - { url = "https://files.pythonhosted.org/packages/6a/1e/76d02f8270b97269d7e3dbd45644b1785bda457b474315f8cf999525a193/multidict-6.7.0-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:2397ab4daaf2698eb51a76721e98db21ce4f52339e535725de03ea962b5a3202", size = 264112, upload-time = "2025-10-06T14:51:01.183Z" }, - { url = "https://files.pythonhosted.org/packages/76/0b/c28a70ecb58963847c2a8efe334904cd254812b10e535aefb3bcce513918/multidict-6.7.0-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:8891681594162635948a636c9fe0ff21746aeb3dd5463f6e25d9bea3a8a39ca1", size = 261194, upload-time = "2025-10-06T14:51:02.794Z" }, - { url = "https://files.pythonhosted.org/packages/b4/63/2ab26e4209773223159b83aa32721b4021ffb08102f8ac7d689c943fded1/multidict-6.7.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:18706cc31dbf402a7945916dd5cddf160251b6dab8a2c5f3d6d5a55949f676b3", size = 248510, upload-time = "2025-10-06T14:51:04.724Z" }, - { url = "https://files.pythonhosted.org/packages/93/cd/06c1fa8282af1d1c46fd55c10a7930af652afdce43999501d4d68664170c/multidict-6.7.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:f844a1bbf1d207dd311a56f383f7eda2d0e134921d45751842d8235e7778965d", size = 248395, upload-time = "2025-10-06T14:51:06.306Z" }, - { url = "https://files.pythonhosted.org/packages/99/ac/82cb419dd6b04ccf9e7e61befc00c77614fc8134362488b553402ecd55ce/multidict-6.7.0-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:d4393e3581e84e5645506923816b9cc81f5609a778c7e7534054091acc64d1c6", size = 239520, upload-time = "2025-10-06T14:51:08.091Z" }, - { url = "https://files.pythonhosted.org/packages/fa/f3/a0f9bf09493421bd8716a362e0cd1d244f5a6550f5beffdd6b47e885b331/multidict-6.7.0-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:fbd18dc82d7bf274b37aa48d664534330af744e03bccf696d6f4c6042e7d19e7", size = 245479, upload-time = "2025-10-06T14:51:10.365Z" }, - { url = "https://files.pythonhosted.org/packages/8d/01/476d38fc73a212843f43c852b0eee266b6971f0e28329c2184a8df90c376/multidict-6.7.0-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:b6234e14f9314731ec45c42fc4554b88133ad53a09092cc48a88e771c125dadb", size = 258903, upload-time = "2025-10-06T14:51:12.466Z" }, - { url = "https://files.pythonhosted.org/packages/49/6d/23faeb0868adba613b817d0e69c5f15531b24d462af8012c4f6de4fa8dc3/multidict-6.7.0-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:08d4379f9744d8f78d98c8673c06e202ffa88296f009c71bbafe8a6bf847d01f", size = 252333, upload-time = "2025-10-06T14:51:14.48Z" }, - { url = "https://files.pythonhosted.org/packages/1e/cc/48d02ac22b30fa247f7dad82866e4b1015431092f4ba6ebc7e77596e0b18/multidict-6.7.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:9fe04da3f79387f450fd0061d4dd2e45a72749d31bf634aecc9e27f24fdc4b3f", size = 243411, upload-time = "2025-10-06T14:51:16.072Z" }, - { url = "https://files.pythonhosted.org/packages/4a/03/29a8bf5a18abf1fe34535c88adbdfa88c9fb869b5a3b120692c64abe8284/multidict-6.7.0-cp314-cp314-win32.whl", hash = "sha256:fbafe31d191dfa7c4c51f7a6149c9fb7e914dcf9ffead27dcfd9f1ae382b3885", size = 40940, upload-time = "2025-10-06T14:51:17.544Z" }, - { url = "https://files.pythonhosted.org/packages/82/16/7ed27b680791b939de138f906d5cf2b4657b0d45ca6f5dd6236fdddafb1a/multidict-6.7.0-cp314-cp314-win_amd64.whl", hash = "sha256:2f67396ec0310764b9222a1728ced1ab638f61aadc6226f17a71dd9324f9a99c", size = 45087, upload-time = "2025-10-06T14:51:18.875Z" }, - { url = "https://files.pythonhosted.org/packages/cd/3c/e3e62eb35a1950292fe39315d3c89941e30a9d07d5d2df42965ab041da43/multidict-6.7.0-cp314-cp314-win_arm64.whl", hash = "sha256:ba672b26069957ee369cfa7fc180dde1fc6f176eaf1e6beaf61fbebbd3d9c000", size = 42368, upload-time = "2025-10-06T14:51:20.225Z" }, - { url = "https://files.pythonhosted.org/packages/8b/40/cd499bd0dbc5f1136726db3153042a735fffd0d77268e2ee20d5f33c010f/multidict-6.7.0-cp314-cp314t-macosx_10_13_universal2.whl", hash = "sha256:c1dcc7524066fa918c6a27d61444d4ee7900ec635779058571f70d042d86ed63", size = 82326, upload-time = "2025-10-06T14:51:21.588Z" }, - { url = "https://files.pythonhosted.org/packages/13/8a/18e031eca251c8df76daf0288e6790561806e439f5ce99a170b4af30676b/multidict-6.7.0-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:27e0b36c2d388dc7b6ced3406671b401e84ad7eb0656b8f3a2f46ed0ce483718", size = 48065, upload-time = "2025-10-06T14:51:22.93Z" }, - { url = "https://files.pythonhosted.org/packages/40/71/5e6701277470a87d234e433fb0a3a7deaf3bcd92566e421e7ae9776319de/multidict-6.7.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:2a7baa46a22e77f0988e3b23d4ede5513ebec1929e34ee9495be535662c0dfe2", size = 46475, upload-time = "2025-10-06T14:51:24.352Z" }, - { url = "https://files.pythonhosted.org/packages/fe/6a/bab00cbab6d9cfb57afe1663318f72ec28289ea03fd4e8236bb78429893a/multidict-6.7.0-cp314-cp314t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:7bf77f54997a9166a2f5675d1201520586439424c2511723a7312bdb4bcc034e", size = 239324, upload-time = "2025-10-06T14:51:25.822Z" }, - { url = "https://files.pythonhosted.org/packages/2a/5f/8de95f629fc22a7769ade8b41028e3e5a822c1f8904f618d175945a81ad3/multidict-6.7.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e011555abada53f1578d63389610ac8a5400fc70ce71156b0aa30d326f1a5064", size = 246877, upload-time = "2025-10-06T14:51:27.604Z" }, - { url = "https://files.pythonhosted.org/packages/23/b4/38881a960458f25b89e9f4a4fdcb02ac101cfa710190db6e5528841e67de/multidict-6.7.0-cp314-cp314t-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:28b37063541b897fd6a318007373930a75ca6d6ac7c940dbe14731ffdd8d498e", size = 225824, upload-time = "2025-10-06T14:51:29.664Z" }, - { url = "https://files.pythonhosted.org/packages/1e/39/6566210c83f8a261575f18e7144736059f0c460b362e96e9cf797a24b8e7/multidict-6.7.0-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:05047ada7a2fde2631a0ed706f1fd68b169a681dfe5e4cf0f8e4cb6618bbc2cd", size = 253558, upload-time = "2025-10-06T14:51:31.684Z" }, - { url = "https://files.pythonhosted.org/packages/00/a3/67f18315100f64c269f46e6c0319fa87ba68f0f64f2b8e7fd7c72b913a0b/multidict-6.7.0-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:716133f7d1d946a4e1b91b1756b23c088881e70ff180c24e864c26192ad7534a", size = 252339, upload-time = "2025-10-06T14:51:33.699Z" }, - { url = "https://files.pythonhosted.org/packages/c8/2a/1cb77266afee2458d82f50da41beba02159b1d6b1f7973afc9a1cad1499b/multidict-6.7.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d1bed1b467ef657f2a0ae62844a607909ef1c6889562de5e1d505f74457d0b96", size = 244895, upload-time = "2025-10-06T14:51:36.189Z" }, - { url = "https://files.pythonhosted.org/packages/dd/72/09fa7dd487f119b2eb9524946ddd36e2067c08510576d43ff68469563b3b/multidict-6.7.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:ca43bdfa5d37bd6aee89d85e1d0831fb86e25541be7e9d376ead1b28974f8e5e", size = 241862, upload-time = "2025-10-06T14:51:41.291Z" }, - { url = "https://files.pythonhosted.org/packages/65/92/bc1f8bd0853d8669300f732c801974dfc3702c3eeadae2f60cef54dc69d7/multidict-6.7.0-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:44b546bd3eb645fd26fb949e43c02a25a2e632e2ca21a35e2e132c8105dc8599", size = 232376, upload-time = "2025-10-06T14:51:43.55Z" }, - { url = "https://files.pythonhosted.org/packages/09/86/ac39399e5cb9d0c2ac8ef6e10a768e4d3bc933ac808d49c41f9dc23337eb/multidict-6.7.0-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:a6ef16328011d3f468e7ebc326f24c1445f001ca1dec335b2f8e66bed3006394", size = 240272, upload-time = "2025-10-06T14:51:45.265Z" }, - { url = "https://files.pythonhosted.org/packages/3d/b6/fed5ac6b8563ec72df6cb1ea8dac6d17f0a4a1f65045f66b6d3bf1497c02/multidict-6.7.0-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:5aa873cbc8e593d361ae65c68f85faadd755c3295ea2c12040ee146802f23b38", size = 248774, upload-time = "2025-10-06T14:51:46.836Z" }, - { url = "https://files.pythonhosted.org/packages/6b/8d/b954d8c0dc132b68f760aefd45870978deec6818897389dace00fcde32ff/multidict-6.7.0-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:3d7b6ccce016e29df4b7ca819659f516f0bc7a4b3efa3bb2012ba06431b044f9", size = 242731, upload-time = "2025-10-06T14:51:48.541Z" }, - { url = "https://files.pythonhosted.org/packages/16/9d/a2dac7009125d3540c2f54e194829ea18ac53716c61b655d8ed300120b0f/multidict-6.7.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:171b73bd4ee683d307599b66793ac80981b06f069b62eea1c9e29c9241aa66b0", size = 240193, upload-time = "2025-10-06T14:51:50.355Z" }, - { url = "https://files.pythonhosted.org/packages/39/ca/c05f144128ea232ae2178b008d5011d4e2cea86e4ee8c85c2631b1b94802/multidict-6.7.0-cp314-cp314t-win32.whl", hash = "sha256:b2d7f80c4e1fd010b07cb26820aae86b7e73b681ee4889684fb8d2d4537aab13", size = 48023, upload-time = "2025-10-06T14:51:51.883Z" }, - { url = "https://files.pythonhosted.org/packages/ba/8f/0a60e501584145588be1af5cc829265701ba3c35a64aec8e07cbb71d39bb/multidict-6.7.0-cp314-cp314t-win_amd64.whl", hash = "sha256:09929cab6fcb68122776d575e03c6cc64ee0b8fca48d17e135474b042ce515cd", size = 53507, upload-time = "2025-10-06T14:51:53.672Z" }, - { url = "https://files.pythonhosted.org/packages/7f/ae/3148b988a9c6239903e786eac19c889fab607c31d6efa7fb2147e5680f23/multidict-6.7.0-cp314-cp314t-win_arm64.whl", hash = "sha256:cc41db090ed742f32bd2d2c721861725e6109681eddf835d0a82bd3a5c382827", size = 44804, upload-time = "2025-10-06T14:51:55.415Z" }, - { url = "https://files.pythonhosted.org/packages/b7/da/7d22601b625e241d4f23ef1ebff8acfc60da633c9e7e7922e24d10f592b3/multidict-6.7.0-py3-none-any.whl", hash = "sha256:394fc5c42a333c9ffc3e421a4c85e08580d990e08b99f6bf35b4132114c5dcb3", size = 12317, upload-time = "2025-10-06T14:52:29.272Z" }, +sdist = { url = "https://files.pythonhosted.org/packages/1a/c2/c2d94cbe6ac1753f3fc980da97b3d930efe1da3af3c9f5125354436c073d/multidict-6.7.1.tar.gz", hash = "sha256:ec6652a1bee61c53a3e5776b6049172c53b6aaba34f18c9ad04f82712bac623d", size = 102010, upload-time = "2026-01-26T02:46:45.979Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/84/0b/19348d4c98980c4851d2f943f8ebafdece2ae7ef737adcfa5994ce8e5f10/multidict-6.7.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:c93c3db7ea657dd4637d57e74ab73de31bccefe144d3d4ce370052035bc85fb5", size = 77176, upload-time = "2026-01-26T02:42:59.784Z" }, + { url = "https://files.pythonhosted.org/packages/ef/04/9de3f8077852e3d438215c81e9b691244532d2e05b4270e89ce67b7d103c/multidict-6.7.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:974e72a2474600827abaeda71af0c53d9ebbc3c2eb7da37b37d7829ae31232d8", size = 44996, upload-time = "2026-01-26T02:43:01.674Z" }, + { url = "https://files.pythonhosted.org/packages/31/5c/08c7f7fe311f32e83f7621cd3f99d805f45519cd06fafb247628b861da7d/multidict-6.7.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:cdea2e7b2456cfb6694fb113066fd0ec7ea4d67e3a35e1f4cbeea0b448bf5872", size = 44631, upload-time = "2026-01-26T02:43:03.169Z" }, + { url = "https://files.pythonhosted.org/packages/b7/7f/0e3b1390ae772f27501199996b94b52ceeb64fe6f9120a32c6c3f6b781be/multidict-6.7.1-cp310-cp310-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:17207077e29342fdc2c9a82e4b306f1127bf1ea91f8b71e02d4798a70bb99991", size = 242561, upload-time = "2026-01-26T02:43:04.733Z" }, + { url = "https://files.pythonhosted.org/packages/dd/f4/8719f4f167586af317b69dd3e90f913416c91ca610cac79a45c53f590312/multidict-6.7.1-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d4f49cb5661344764e4c7c7973e92a47a59b8fc19b6523649ec9dc4960e58a03", size = 242223, upload-time = "2026-01-26T02:43:06.695Z" }, + { url = "https://files.pythonhosted.org/packages/47/ab/7c36164cce64a6ad19c6d9a85377b7178ecf3b89f8fd589c73381a5eedfd/multidict-6.7.1-cp310-cp310-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:a9fc4caa29e2e6ae408d1c450ac8bf19892c5fca83ee634ecd88a53332c59981", size = 222322, upload-time = "2026-01-26T02:43:08.472Z" }, + { url = "https://files.pythonhosted.org/packages/f5/79/a25add6fb38035b5337bc5734f296d9afc99163403bbcf56d4170f97eb62/multidict-6.7.1-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:c5f0c21549ab432b57dcc82130f388d84ad8179824cc3f223d5e7cfbfd4143f6", size = 254005, upload-time = "2026-01-26T02:43:10.127Z" }, + { url = "https://files.pythonhosted.org/packages/4a/7b/64a87cf98e12f756fc8bd444b001232ffff2be37288f018ad0d3f0aae931/multidict-6.7.1-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:7dfb78d966b2c906ae1d28ccf6e6712a3cd04407ee5088cd276fe8cb42186190", size = 251173, upload-time = "2026-01-26T02:43:11.731Z" }, + { url = "https://files.pythonhosted.org/packages/4b/ac/b605473de2bb404e742f2cc3583d12aedb2352a70e49ae8fce455b50c5aa/multidict-6.7.1-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9b0d9b91d1aa44db9c1f1ecd0d9d2ae610b2f4f856448664e01a3b35899f3f92", size = 243273, upload-time = "2026-01-26T02:43:13.063Z" }, + { url = "https://files.pythonhosted.org/packages/03/65/11492d6a0e259783720f3bc1d9ea55579a76f1407e31ed44045c99542004/multidict-6.7.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:dd96c01a9dcd4889dcfcf9eb5544ca0c77603f239e3ffab0524ec17aea9a93ee", size = 238956, upload-time = "2026-01-26T02:43:14.843Z" }, + { url = "https://files.pythonhosted.org/packages/5f/a7/7ee591302af64e7c196fb63fe856c788993c1372df765102bd0448e7e165/multidict-6.7.1-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:067343c68cd6612d375710f895337b3a98a033c94f14b9a99eff902f205424e2", size = 233477, upload-time = "2026-01-26T02:43:16.025Z" }, + { url = "https://files.pythonhosted.org/packages/9c/99/c109962d58756c35fd9992fed7f2355303846ea2ff054bb5f5e9d6b888de/multidict-6.7.1-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:5884a04f4ff56c6120f6ccf703bdeb8b5079d808ba604d4d53aec0d55dc33568", size = 243615, upload-time = "2026-01-26T02:43:17.84Z" }, + { url = "https://files.pythonhosted.org/packages/d5/5f/1973e7c771c86e93dcfe1c9cc55a5481b610f6614acfc28c0d326fe6bfad/multidict-6.7.1-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:8affcf1c98b82bc901702eb73b6947a1bfa170823c153fe8a47b5f5f02e48e40", size = 249930, upload-time = "2026-01-26T02:43:19.06Z" }, + { url = "https://files.pythonhosted.org/packages/5d/a5/f170fc2268c3243853580203378cd522446b2df632061e0a5409817854c7/multidict-6.7.1-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:0d17522c37d03e85c8098ec8431636309b2682cf12e58f4dbc76121fb50e4962", size = 243807, upload-time = "2026-01-26T02:43:20.286Z" }, + { url = "https://files.pythonhosted.org/packages/de/01/73856fab6d125e5bc652c3986b90e8699a95e84b48d72f39ade6c0e74a8c/multidict-6.7.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:24c0cf81544ca5e17cfcb6e482e7a82cd475925242b308b890c9452a074d4505", size = 239103, upload-time = "2026-01-26T02:43:21.508Z" }, + { url = "https://files.pythonhosted.org/packages/e7/46/f1220bd9944d8aa40d8ccff100eeeee19b505b857b6f603d6078cb5315b0/multidict-6.7.1-cp310-cp310-win32.whl", hash = "sha256:d82dd730a95e6643802f4454b8fdecdf08667881a9c5670db85bc5a56693f122", size = 41416, upload-time = "2026-01-26T02:43:22.703Z" }, + { url = "https://files.pythonhosted.org/packages/68/00/9b38e272a770303692fc406c36e1a4c740f401522d5787691eb38a8925a8/multidict-6.7.1-cp310-cp310-win_amd64.whl", hash = "sha256:cf37cbe5ced48d417ba045aca1b21bafca67489452debcde94778a576666a1df", size = 46022, upload-time = "2026-01-26T02:43:23.77Z" }, + { url = "https://files.pythonhosted.org/packages/64/65/d8d42490c02ee07b6bbe00f7190d70bb4738b3cce7629aaf9f213ef730dd/multidict-6.7.1-cp310-cp310-win_arm64.whl", hash = "sha256:59bc83d3f66b41dac1e7460aac1d196edc70c9ba3094965c467715a70ecb46db", size = 43238, upload-time = "2026-01-26T02:43:24.882Z" }, + { url = "https://files.pythonhosted.org/packages/ce/f1/a90635c4f88fb913fbf4ce660b83b7445b7a02615bda034b2f8eb38fd597/multidict-6.7.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:7ff981b266af91d7b4b3793ca3382e53229088d193a85dfad6f5f4c27fc73e5d", size = 76626, upload-time = "2026-01-26T02:43:26.485Z" }, + { url = "https://files.pythonhosted.org/packages/a6/9b/267e64eaf6fc637a15b35f5de31a566634a2740f97d8d094a69d34f524a4/multidict-6.7.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:844c5bca0b5444adb44a623fb0a1310c2f4cd41f402126bb269cd44c9b3f3e1e", size = 44706, upload-time = "2026-01-26T02:43:27.607Z" }, + { url = "https://files.pythonhosted.org/packages/dd/a4/d45caf2b97b035c57267791ecfaafbd59c68212004b3842830954bb4b02e/multidict-6.7.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f2a0a924d4c2e9afcd7ec64f9de35fcd96915149b2216e1cb2c10a56df483855", size = 44356, upload-time = "2026-01-26T02:43:28.661Z" }, + { url = "https://files.pythonhosted.org/packages/fd/d2/0a36c8473f0cbaeadd5db6c8b72d15bbceeec275807772bfcd059bef487d/multidict-6.7.1-cp311-cp311-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:8be1802715a8e892c784c0197c2ace276ea52702a0ede98b6310c8f255a5afb3", size = 244355, upload-time = "2026-01-26T02:43:31.165Z" }, + { url = "https://files.pythonhosted.org/packages/5d/16/8c65be997fd7dd311b7d39c7b6e71a0cb449bad093761481eccbbe4b42a2/multidict-6.7.1-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:2e2d2ed645ea29f31c4c7ea1552fcfd7cb7ba656e1eafd4134a6620c9f5fdd9e", size = 246433, upload-time = "2026-01-26T02:43:32.581Z" }, + { url = "https://files.pythonhosted.org/packages/01/fb/4dbd7e848d2799c6a026ec88ad39cf2b8416aa167fcc903baa55ecaa045c/multidict-6.7.1-cp311-cp311-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:95922cee9a778659e91db6497596435777bd25ed116701a4c034f8e46544955a", size = 225376, upload-time = "2026-01-26T02:43:34.417Z" }, + { url = "https://files.pythonhosted.org/packages/b6/8a/4a3a6341eac3830f6053062f8fbc9a9e54407c80755b3f05bc427295c2d0/multidict-6.7.1-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:6b83cabdc375ffaaa15edd97eb7c0c672ad788e2687004990074d7d6c9b140c8", size = 257365, upload-time = "2026-01-26T02:43:35.741Z" }, + { url = "https://files.pythonhosted.org/packages/f7/a2/dd575a69c1aa206e12d27d0770cdf9b92434b48a9ef0cd0d1afdecaa93c4/multidict-6.7.1-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:38fb49540705369bab8484db0689d86c0a33a0a9f2c1b197f506b71b4b6c19b0", size = 254747, upload-time = "2026-01-26T02:43:36.976Z" }, + { url = "https://files.pythonhosted.org/packages/5a/56/21b27c560c13822ed93133f08aa6372c53a8e067f11fbed37b4adcdac922/multidict-6.7.1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:439cbebd499f92e9aa6793016a8acaa161dfa749ae86d20960189f5398a19144", size = 246293, upload-time = "2026-01-26T02:43:38.258Z" }, + { url = "https://files.pythonhosted.org/packages/5a/a4/23466059dc3854763423d0ad6c0f3683a379d97673b1b89ec33826e46728/multidict-6.7.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:6d3bc717b6fe763b8be3f2bee2701d3c8eb1b2a8ae9f60910f1b2860c82b6c49", size = 242962, upload-time = "2026-01-26T02:43:40.034Z" }, + { url = "https://files.pythonhosted.org/packages/1f/67/51dd754a3524d685958001e8fa20a0f5f90a6a856e0a9dcabff69be3dbb7/multidict-6.7.1-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:619e5a1ac57986dbfec9f0b301d865dddf763696435e2962f6d9cf2fdff2bb71", size = 237360, upload-time = "2026-01-26T02:43:41.752Z" }, + { url = "https://files.pythonhosted.org/packages/64/3f/036dfc8c174934d4b55d86ff4f978e558b0e585cef70cfc1ad01adc6bf18/multidict-6.7.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:0b38ebffd9be37c1170d33bc0f36f4f262e0a09bc1aac1c34c7aa51a7293f0b3", size = 245940, upload-time = "2026-01-26T02:43:43.042Z" }, + { url = "https://files.pythonhosted.org/packages/3d/20/6214d3c105928ebc353a1c644a6ef1408bc5794fcb4f170bb524a3c16311/multidict-6.7.1-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:10ae39c9cfe6adedcdb764f5e8411d4a92b055e35573a2eaa88d3323289ef93c", size = 253502, upload-time = "2026-01-26T02:43:44.371Z" }, + { url = "https://files.pythonhosted.org/packages/b1/e2/c653bc4ae1be70a0f836b82172d643fcf1dade042ba2676ab08ec08bff0f/multidict-6.7.1-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:25167cc263257660290fba06b9318d2026e3c910be240a146e1f66dd114af2b0", size = 247065, upload-time = "2026-01-26T02:43:45.745Z" }, + { url = "https://files.pythonhosted.org/packages/c8/11/a854b4154cd3bd8b1fd375e8a8ca9d73be37610c361543d56f764109509b/multidict-6.7.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:128441d052254f42989ef98b7b6a6ecb1e6f708aa962c7984235316db59f50fa", size = 241870, upload-time = "2026-01-26T02:43:47.054Z" }, + { url = "https://files.pythonhosted.org/packages/13/bf/9676c0392309b5fdae322333d22a829715b570edb9baa8016a517b55b558/multidict-6.7.1-cp311-cp311-win32.whl", hash = "sha256:d62b7f64ffde3b99d06b707a280db04fb3855b55f5a06df387236051d0668f4a", size = 41302, upload-time = "2026-01-26T02:43:48.753Z" }, + { url = "https://files.pythonhosted.org/packages/c9/68/f16a3a8ba6f7b6dc92a1f19669c0810bd2c43fc5a02da13b1cbf8e253845/multidict-6.7.1-cp311-cp311-win_amd64.whl", hash = "sha256:bdbf9f3b332abd0cdb306e7c2113818ab1e922dc84b8f8fd06ec89ed2a19ab8b", size = 45981, upload-time = "2026-01-26T02:43:49.921Z" }, + { url = "https://files.pythonhosted.org/packages/ac/ad/9dd5305253fa00cd3c7555dbef69d5bf4133debc53b87ab8d6a44d411665/multidict-6.7.1-cp311-cp311-win_arm64.whl", hash = "sha256:b8c990b037d2fff2f4e33d3f21b9b531c5745b33a49a7d6dbe7a177266af44f6", size = 43159, upload-time = "2026-01-26T02:43:51.635Z" }, + { url = "https://files.pythonhosted.org/packages/8d/9c/f20e0e2cf80e4b2e4b1c365bf5fe104ee633c751a724246262db8f1a0b13/multidict-6.7.1-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:a90f75c956e32891a4eda3639ce6dd86e87105271f43d43442a3aedf3cddf172", size = 76893, upload-time = "2026-01-26T02:43:52.754Z" }, + { url = "https://files.pythonhosted.org/packages/fe/cf/18ef143a81610136d3da8193da9d80bfe1cb548a1e2d1c775f26b23d024a/multidict-6.7.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:3fccb473e87eaa1382689053e4a4618e7ba7b9b9b8d6adf2027ee474597128cd", size = 45456, upload-time = "2026-01-26T02:43:53.893Z" }, + { url = "https://files.pythonhosted.org/packages/a9/65/1caac9d4cd32e8433908683446eebc953e82d22b03d10d41a5f0fefe991b/multidict-6.7.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:b0fa96985700739c4c7853a43c0b3e169360d6855780021bfc6d0f1ce7c123e7", size = 43872, upload-time = "2026-01-26T02:43:55.041Z" }, + { url = "https://files.pythonhosted.org/packages/cf/3b/d6bd75dc4f3ff7c73766e04e705b00ed6dbbaccf670d9e05a12b006f5a21/multidict-6.7.1-cp312-cp312-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:cb2a55f408c3043e42b40cc8eecd575afa27b7e0b956dfb190de0f8499a57a53", size = 251018, upload-time = "2026-01-26T02:43:56.198Z" }, + { url = "https://files.pythonhosted.org/packages/fd/80/c959c5933adedb9ac15152e4067c702a808ea183a8b64cf8f31af8ad3155/multidict-6.7.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:eb0ce7b2a32d09892b3dd6cc44877a0d02a33241fafca5f25c8b6b62374f8b75", size = 258883, upload-time = "2026-01-26T02:43:57.499Z" }, + { url = "https://files.pythonhosted.org/packages/86/85/7ed40adafea3d4f1c8b916e3b5cc3a8e07dfcdcb9cd72800f4ed3ca1b387/multidict-6.7.1-cp312-cp312-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:c3a32d23520ee37bf327d1e1a656fec76a2edd5c038bf43eddfa0572ec49c60b", size = 242413, upload-time = "2026-01-26T02:43:58.755Z" }, + { url = "https://files.pythonhosted.org/packages/d2/57/b8565ff533e48595503c785f8361ff9a4fde4d67de25c207cd0ba3befd03/multidict-6.7.1-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:9c90fed18bffc0189ba814749fdcc102b536e83a9f738a9003e569acd540a733", size = 268404, upload-time = "2026-01-26T02:44:00.216Z" }, + { url = "https://files.pythonhosted.org/packages/e0/50/9810c5c29350f7258180dfdcb2e52783a0632862eb334c4896ac717cebcb/multidict-6.7.1-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:da62917e6076f512daccfbbde27f46fed1c98fee202f0559adec8ee0de67f71a", size = 269456, upload-time = "2026-01-26T02:44:02.202Z" }, + { url = "https://files.pythonhosted.org/packages/f3/8d/5e5be3ced1d12966fefb5c4ea3b2a5b480afcea36406559442c6e31d4a48/multidict-6.7.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:bfde23ef6ed9db7eaee6c37dcec08524cb43903c60b285b172b6c094711b3961", size = 256322, upload-time = "2026-01-26T02:44:03.56Z" }, + { url = "https://files.pythonhosted.org/packages/31/6e/d8a26d81ac166a5592782d208dd90dfdc0a7a218adaa52b45a672b46c122/multidict-6.7.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:3758692429e4e32f1ba0df23219cd0b4fc0a52f476726fff9337d1a57676a582", size = 253955, upload-time = "2026-01-26T02:44:04.845Z" }, + { url = "https://files.pythonhosted.org/packages/59/4c/7c672c8aad41534ba619bcd4ade7a0dc87ed6b8b5c06149b85d3dd03f0cd/multidict-6.7.1-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:398c1478926eca669f2fd6a5856b6de9c0acf23a2cb59a14c0ba5844fa38077e", size = 251254, upload-time = "2026-01-26T02:44:06.133Z" }, + { url = "https://files.pythonhosted.org/packages/7b/bd/84c24de512cbafbdbc39439f74e967f19570ce7924e3007174a29c348916/multidict-6.7.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:c102791b1c4f3ab36ce4101154549105a53dc828f016356b3e3bcae2e3a039d3", size = 252059, upload-time = "2026-01-26T02:44:07.518Z" }, + { url = "https://files.pythonhosted.org/packages/fa/ba/f5449385510825b73d01c2d4087bf6d2fccc20a2d42ac34df93191d3dd03/multidict-6.7.1-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:a088b62bd733e2ad12c50dad01b7d0166c30287c166e137433d3b410add807a6", size = 263588, upload-time = "2026-01-26T02:44:09.382Z" }, + { url = "https://files.pythonhosted.org/packages/d7/11/afc7c677f68f75c84a69fe37184f0f82fce13ce4b92f49f3db280b7e92b3/multidict-6.7.1-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:3d51ff4785d58d3f6c91bdbffcb5e1f7ddfda557727043aa20d20ec4f65e324a", size = 259642, upload-time = "2026-01-26T02:44:10.73Z" }, + { url = "https://files.pythonhosted.org/packages/2b/17/ebb9644da78c4ab36403739e0e6e0e30ebb135b9caf3440825001a0bddcb/multidict-6.7.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:fc5907494fccf3e7d3f94f95c91d6336b092b5fc83811720fae5e2765890dfba", size = 251377, upload-time = "2026-01-26T02:44:12.042Z" }, + { url = "https://files.pythonhosted.org/packages/ca/a4/840f5b97339e27846c46307f2530a2805d9d537d8b8bd416af031cad7fa0/multidict-6.7.1-cp312-cp312-win32.whl", hash = "sha256:28ca5ce2fd9716631133d0e9a9b9a745ad7f60bac2bccafb56aa380fc0b6c511", size = 41887, upload-time = "2026-01-26T02:44:14.245Z" }, + { url = "https://files.pythonhosted.org/packages/80/31/0b2517913687895f5904325c2069d6a3b78f66cc641a86a2baf75a05dcbb/multidict-6.7.1-cp312-cp312-win_amd64.whl", hash = "sha256:fcee94dfbd638784645b066074b338bc9cc155d4b4bffa4adce1615c5a426c19", size = 46053, upload-time = "2026-01-26T02:44:15.371Z" }, + { url = "https://files.pythonhosted.org/packages/0c/5b/aba28e4ee4006ae4c7df8d327d31025d760ffa992ea23812a601d226e682/multidict-6.7.1-cp312-cp312-win_arm64.whl", hash = "sha256:ba0a9fb644d0c1a2194cf7ffb043bd852cea63a57f66fbd33959f7dae18517bf", size = 43307, upload-time = "2026-01-26T02:44:16.852Z" }, + { url = "https://files.pythonhosted.org/packages/f2/22/929c141d6c0dba87d3e1d38fbdf1ba8baba86b7776469f2bc2d3227a1e67/multidict-6.7.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:2b41f5fed0ed563624f1c17630cb9941cf2309d4df00e494b551b5f3e3d67a23", size = 76174, upload-time = "2026-01-26T02:44:18.509Z" }, + { url = "https://files.pythonhosted.org/packages/c7/75/bc704ae15fee974f8fccd871305e254754167dce5f9e42d88a2def741a1d/multidict-6.7.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:84e61e3af5463c19b67ced91f6c634effb89ef8bfc5ca0267f954451ed4bb6a2", size = 45116, upload-time = "2026-01-26T02:44:19.745Z" }, + { url = "https://files.pythonhosted.org/packages/79/76/55cd7186f498ed080a18440c9013011eb548f77ae1b297206d030eb1180a/multidict-6.7.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:935434b9853c7c112eee7ac891bc4cb86455aa631269ae35442cb316790c1445", size = 43524, upload-time = "2026-01-26T02:44:21.571Z" }, + { url = "https://files.pythonhosted.org/packages/e9/3c/414842ef8d5a1628d68edee29ba0e5bcf235dbfb3ccd3ea303a7fe8c72ff/multidict-6.7.1-cp313-cp313-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:432feb25a1cb67fe82a9680b4d65fb542e4635cb3166cd9c01560651ad60f177", size = 249368, upload-time = "2026-01-26T02:44:22.803Z" }, + { url = "https://files.pythonhosted.org/packages/f6/32/befed7f74c458b4a525e60519fe8d87eef72bb1e99924fa2b0f9d97a221e/multidict-6.7.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e82d14e3c948952a1a85503817e038cba5905a3352de76b9a465075d072fba23", size = 256952, upload-time = "2026-01-26T02:44:24.306Z" }, + { url = "https://files.pythonhosted.org/packages/03/d6/c878a44ba877f366630c860fdf74bfb203c33778f12b6ac274936853c451/multidict-6.7.1-cp313-cp313-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:4cfb48c6ea66c83bcaaf7e4dfa7ec1b6bbcf751b7db85a328902796dfde4c060", size = 240317, upload-time = "2026-01-26T02:44:25.772Z" }, + { url = "https://files.pythonhosted.org/packages/68/49/57421b4d7ad2e9e60e25922b08ceb37e077b90444bde6ead629095327a6f/multidict-6.7.1-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:1d540e51b7e8e170174555edecddbd5538105443754539193e3e1061864d444d", size = 267132, upload-time = "2026-01-26T02:44:27.648Z" }, + { url = "https://files.pythonhosted.org/packages/b7/fe/ec0edd52ddbcea2a2e89e174f0206444a61440b40f39704e64dc807a70bd/multidict-6.7.1-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:273d23f4b40f3dce4d6c8a821c741a86dec62cded82e1175ba3d99be128147ed", size = 268140, upload-time = "2026-01-26T02:44:29.588Z" }, + { url = "https://files.pythonhosted.org/packages/b0/73/6e1b01cbeb458807aa0831742232dbdd1fa92bfa33f52a3f176b4ff3dc11/multidict-6.7.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9d624335fd4fa1c08a53f8b4be7676ebde19cd092b3895c421045ca87895b429", size = 254277, upload-time = "2026-01-26T02:44:30.902Z" }, + { url = "https://files.pythonhosted.org/packages/6a/b2/5fb8c124d7561a4974c342bc8c778b471ebbeb3cc17df696f034a7e9afe7/multidict-6.7.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:12fad252f8b267cc75b66e8fc51b3079604e8d43a75428ffe193cd9e2195dfd6", size = 252291, upload-time = "2026-01-26T02:44:32.31Z" }, + { url = "https://files.pythonhosted.org/packages/5a/96/51d4e4e06bcce92577fcd488e22600bd38e4fd59c20cb49434d054903bd2/multidict-6.7.1-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:03ede2a6ffbe8ef936b92cb4529f27f42be7f56afcdab5ab739cd5f27fb1cbf9", size = 250156, upload-time = "2026-01-26T02:44:33.734Z" }, + { url = "https://files.pythonhosted.org/packages/db/6b/420e173eec5fba721a50e2a9f89eda89d9c98fded1124f8d5c675f7a0c0f/multidict-6.7.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:90efbcf47dbe33dcf643a1e400d67d59abeac5db07dc3f27d6bdeae497a2198c", size = 249742, upload-time = "2026-01-26T02:44:35.222Z" }, + { url = "https://files.pythonhosted.org/packages/44/a3/ec5b5bd98f306bc2aa297b8c6f11a46714a56b1e6ef5ebda50a4f5d7c5fb/multidict-6.7.1-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:5c4b9bfc148f5a91be9244d6264c53035c8a0dcd2f51f1c3c6e30e30ebaa1c84", size = 262221, upload-time = "2026-01-26T02:44:36.604Z" }, + { url = "https://files.pythonhosted.org/packages/cd/f7/e8c0d0da0cd1e28d10e624604e1a36bcc3353aaebdfdc3a43c72bc683a12/multidict-6.7.1-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:401c5a650f3add2472d1d288c26deebc540f99e2fb83e9525007a74cd2116f1d", size = 258664, upload-time = "2026-01-26T02:44:38.008Z" }, + { url = "https://files.pythonhosted.org/packages/52/da/151a44e8016dd33feed44f730bd856a66257c1ee7aed4f44b649fb7edeb3/multidict-6.7.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:97891f3b1b3ffbded884e2916cacf3c6fc87b66bb0dde46f7357404750559f33", size = 249490, upload-time = "2026-01-26T02:44:39.386Z" }, + { url = "https://files.pythonhosted.org/packages/87/af/a3b86bf9630b732897f6fc3f4c4714b90aa4361983ccbdcd6c0339b21b0c/multidict-6.7.1-cp313-cp313-win32.whl", hash = "sha256:e1c5988359516095535c4301af38d8a8838534158f649c05dd1050222321bcb3", size = 41695, upload-time = "2026-01-26T02:44:41.318Z" }, + { url = "https://files.pythonhosted.org/packages/b2/35/e994121b0e90e46134673422dd564623f93304614f5d11886b1b3e06f503/multidict-6.7.1-cp313-cp313-win_amd64.whl", hash = "sha256:960c83bf01a95b12b08fd54324a4eb1d5b52c88932b5cba5d6e712bb3ed12eb5", size = 45884, upload-time = "2026-01-26T02:44:42.488Z" }, + { url = "https://files.pythonhosted.org/packages/ca/61/42d3e5dbf661242a69c97ea363f2d7b46c567da8eadef8890022be6e2ab0/multidict-6.7.1-cp313-cp313-win_arm64.whl", hash = "sha256:563fe25c678aaba333d5399408f5ec3c383ca5b663e7f774dd179a520b8144df", size = 43122, upload-time = "2026-01-26T02:44:43.664Z" }, + { url = "https://files.pythonhosted.org/packages/6d/b3/e6b21c6c4f314bb956016b0b3ef2162590a529b84cb831c257519e7fde44/multidict-6.7.1-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:c76c4bec1538375dad9d452d246ca5368ad6e1c9039dadcf007ae59c70619ea1", size = 83175, upload-time = "2026-01-26T02:44:44.894Z" }, + { url = "https://files.pythonhosted.org/packages/fb/76/23ecd2abfe0957b234f6c960f4ade497f55f2c16aeb684d4ecdbf1c95791/multidict-6.7.1-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:57b46b24b5d5ebcc978da4ec23a819a9402b4228b8a90d9c656422b4bdd8a963", size = 48460, upload-time = "2026-01-26T02:44:46.106Z" }, + { url = "https://files.pythonhosted.org/packages/c4/57/a0ed92b23f3a042c36bc4227b72b97eca803f5f1801c1ab77c8a212d455e/multidict-6.7.1-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:e954b24433c768ce78ab7929e84ccf3422e46deb45a4dc9f93438f8217fa2d34", size = 46930, upload-time = "2026-01-26T02:44:47.278Z" }, + { url = "https://files.pythonhosted.org/packages/b5/66/02ec7ace29162e447f6382c495dc95826bf931d3818799bbef11e8f7df1a/multidict-6.7.1-cp313-cp313t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:3bd231490fa7217cc832528e1cd8752a96f0125ddd2b5749390f7c3ec8721b65", size = 242582, upload-time = "2026-01-26T02:44:48.604Z" }, + { url = "https://files.pythonhosted.org/packages/58/18/64f5a795e7677670e872673aca234162514696274597b3708b2c0d276cce/multidict-6.7.1-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:253282d70d67885a15c8a7716f3a73edf2d635793ceda8173b9ecc21f2fb8292", size = 250031, upload-time = "2026-01-26T02:44:50.544Z" }, + { url = "https://files.pythonhosted.org/packages/c8/ed/e192291dbbe51a8290c5686f482084d31bcd9d09af24f63358c3d42fd284/multidict-6.7.1-cp313-cp313t-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:0b4c48648d7649c9335cf1927a8b87fa692de3dcb15faa676c6a6f1f1aabda43", size = 228596, upload-time = "2026-01-26T02:44:51.951Z" }, + { url = "https://files.pythonhosted.org/packages/1e/7e/3562a15a60cf747397e7f2180b0a11dc0c38d9175a650e75fa1b4d325e15/multidict-6.7.1-cp313-cp313t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:98bc624954ec4d2c7cb074b8eefc2b5d0ce7d482e410df446414355d158fe4ca", size = 257492, upload-time = "2026-01-26T02:44:53.902Z" }, + { url = "https://files.pythonhosted.org/packages/24/02/7d0f9eae92b5249bb50ac1595b295f10e263dd0078ebb55115c31e0eaccd/multidict-6.7.1-cp313-cp313t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:1b99af4d9eec0b49927b4402bcbb58dea89d3e0db8806a4086117019939ad3dd", size = 255899, upload-time = "2026-01-26T02:44:55.316Z" }, + { url = "https://files.pythonhosted.org/packages/00/e3/9b60ed9e23e64c73a5cde95269ef1330678e9c6e34dd4eb6b431b85b5a10/multidict-6.7.1-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6aac4f16b472d5b7dc6f66a0d49dd57b0e0902090be16594dc9ebfd3d17c47e7", size = 247970, upload-time = "2026-01-26T02:44:56.783Z" }, + { url = "https://files.pythonhosted.org/packages/3e/06/538e58a63ed5cfb0bd4517e346b91da32fde409d839720f664e9a4ae4f9d/multidict-6.7.1-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:21f830fe223215dffd51f538e78c172ed7c7f60c9b96a2bf05c4848ad49921c3", size = 245060, upload-time = "2026-01-26T02:44:58.195Z" }, + { url = "https://files.pythonhosted.org/packages/b2/2f/d743a3045a97c895d401e9bd29aaa09b94f5cbdf1bd561609e5a6c431c70/multidict-6.7.1-cp313-cp313t-musllinux_1_2_armv7l.whl", hash = "sha256:f5dd81c45b05518b9aa4da4aa74e1c93d715efa234fd3e8a179df611cc85e5f4", size = 235888, upload-time = "2026-01-26T02:44:59.57Z" }, + { url = "https://files.pythonhosted.org/packages/38/83/5a325cac191ab28b63c52f14f1131f3b0a55ba3b9aa65a6d0bf2a9b921a0/multidict-6.7.1-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:eb304767bca2bb92fb9c5bd33cedc95baee5bb5f6c88e63706533a1c06ad08c8", size = 243554, upload-time = "2026-01-26T02:45:01.054Z" }, + { url = "https://files.pythonhosted.org/packages/20/1f/9d2327086bd15da2725ef6aae624208e2ef828ed99892b17f60c344e57ed/multidict-6.7.1-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:c9035dde0f916702850ef66460bc4239d89d08df4d02023a5926e7446724212c", size = 252341, upload-time = "2026-01-26T02:45:02.484Z" }, + { url = "https://files.pythonhosted.org/packages/e8/2c/2a1aa0280cf579d0f6eed8ee5211c4f1730bd7e06c636ba2ee6aafda302e/multidict-6.7.1-cp313-cp313t-musllinux_1_2_s390x.whl", hash = "sha256:af959b9beeb66c822380f222f0e0a1889331597e81f1ded7f374f3ecb0fd6c52", size = 246391, upload-time = "2026-01-26T02:45:03.862Z" }, + { url = "https://files.pythonhosted.org/packages/e5/03/7ca022ffc36c5a3f6e03b179a5ceb829be9da5783e6fe395f347c0794680/multidict-6.7.1-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:41f2952231456154ee479651491e94118229844dd7226541788be783be2b5108", size = 243422, upload-time = "2026-01-26T02:45:05.296Z" }, + { url = "https://files.pythonhosted.org/packages/dc/1d/b31650eab6c5778aceed46ba735bd97f7c7d2f54b319fa916c0f96e7805b/multidict-6.7.1-cp313-cp313t-win32.whl", hash = "sha256:df9f19c28adcb40b6aae30bbaa1478c389efd50c28d541d76760199fc1037c32", size = 47770, upload-time = "2026-01-26T02:45:06.754Z" }, + { url = "https://files.pythonhosted.org/packages/ac/5b/2d2d1d522e51285bd61b1e20df8f47ae1a9d80839db0b24ea783b3832832/multidict-6.7.1-cp313-cp313t-win_amd64.whl", hash = "sha256:d54ecf9f301853f2c5e802da559604b3e95bb7a3b01a9c295c6ee591b9882de8", size = 53109, upload-time = "2026-01-26T02:45:08.044Z" }, + { url = "https://files.pythonhosted.org/packages/3d/a3/cc409ba012c83ca024a308516703cf339bdc4b696195644a7215a5164a24/multidict-6.7.1-cp313-cp313t-win_arm64.whl", hash = "sha256:5a37ca18e360377cfda1d62f5f382ff41f2b8c4ccb329ed974cc2e1643440118", size = 45573, upload-time = "2026-01-26T02:45:09.349Z" }, + { url = "https://files.pythonhosted.org/packages/91/cc/db74228a8be41884a567e88a62fd589a913708fcf180d029898c17a9a371/multidict-6.7.1-cp314-cp314-macosx_10_15_universal2.whl", hash = "sha256:8f333ec9c5eb1b7105e3b84b53141e66ca05a19a605368c55450b6ba208cb9ee", size = 75190, upload-time = "2026-01-26T02:45:10.651Z" }, + { url = "https://files.pythonhosted.org/packages/d5/22/492f2246bb5b534abd44804292e81eeaf835388901f0c574bac4eeec73c5/multidict-6.7.1-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:a407f13c188f804c759fc6a9f88286a565c242a76b27626594c133b82883b5c2", size = 44486, upload-time = "2026-01-26T02:45:11.938Z" }, + { url = "https://files.pythonhosted.org/packages/f1/4f/733c48f270565d78b4544f2baddc2fb2a245e5a8640254b12c36ac7ac68e/multidict-6.7.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:0e161ddf326db5577c3a4cc2d8648f81456e8a20d40415541587a71620d7a7d1", size = 43219, upload-time = "2026-01-26T02:45:14.346Z" }, + { url = "https://files.pythonhosted.org/packages/24/bb/2c0c2287963f4259c85e8bcbba9182ced8d7fca65c780c38e99e61629d11/multidict-6.7.1-cp314-cp314-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:1e3a8bb24342a8201d178c3b4984c26ba81a577c80d4d525727427460a50c22d", size = 245132, upload-time = "2026-01-26T02:45:15.712Z" }, + { url = "https://files.pythonhosted.org/packages/a7/f9/44d4b3064c65079d2467888794dea218d1601898ac50222ab8a9a8094460/multidict-6.7.1-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:97231140a50f5d447d3164f994b86a0bed7cd016e2682f8650d6a9158e14fd31", size = 252420, upload-time = "2026-01-26T02:45:17.293Z" }, + { url = "https://files.pythonhosted.org/packages/8b/13/78f7275e73fa17b24c9a51b0bd9d73ba64bb32d0ed51b02a746eb876abe7/multidict-6.7.1-cp314-cp314-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:6b10359683bd8806a200fd2909e7c8ca3a7b24ec1d8132e483d58e791d881048", size = 233510, upload-time = "2026-01-26T02:45:19.356Z" }, + { url = "https://files.pythonhosted.org/packages/4b/25/8167187f62ae3cbd52da7893f58cb036b47ea3fb67138787c76800158982/multidict-6.7.1-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:283ddac99f7ac25a4acadbf004cb5ae34480bbeb063520f70ce397b281859362", size = 264094, upload-time = "2026-01-26T02:45:20.834Z" }, + { url = "https://files.pythonhosted.org/packages/a1/e7/69a3a83b7b030cf283fb06ce074a05a02322359783424d7edf0f15fe5022/multidict-6.7.1-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:538cec1e18c067d0e6103aa9a74f9e832904c957adc260e61cd9d8cf0c3b3d37", size = 260786, upload-time = "2026-01-26T02:45:22.818Z" }, + { url = "https://files.pythonhosted.org/packages/fe/3b/8ec5074bcfc450fe84273713b4b0a0dd47c0249358f5d82eb8104ffe2520/multidict-6.7.1-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:7eee46ccb30ff48a1e35bb818cc90846c6be2b68240e42a78599166722cea709", size = 248483, upload-time = "2026-01-26T02:45:24.368Z" }, + { url = "https://files.pythonhosted.org/packages/48/5a/d5a99e3acbca0e29c5d9cba8f92ceb15dce78bab963b308ae692981e3a5d/multidict-6.7.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:fa263a02f4f2dd2d11a7b1bb4362aa7cb1049f84a9235d31adf63f30143469a0", size = 248403, upload-time = "2026-01-26T02:45:25.982Z" }, + { url = "https://files.pythonhosted.org/packages/35/48/e58cd31f6c7d5102f2a4bf89f96b9cf7e00b6c6f3d04ecc44417c00a5a3c/multidict-6.7.1-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:2e1425e2f99ec5bd36c15a01b690a1a2456209c5deed58f95469ffb46039ccbb", size = 240315, upload-time = "2026-01-26T02:45:27.487Z" }, + { url = "https://files.pythonhosted.org/packages/94/33/1cd210229559cb90b6786c30676bb0c58249ff42f942765f88793b41fdce/multidict-6.7.1-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:497394b3239fc6f0e13a78a3e1b61296e72bf1c5f94b4c4eb80b265c37a131cd", size = 245528, upload-time = "2026-01-26T02:45:28.991Z" }, + { url = "https://files.pythonhosted.org/packages/64/f2/6e1107d226278c876c783056b7db43d800bb64c6131cec9c8dfb6903698e/multidict-6.7.1-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:233b398c29d3f1b9676b4b6f75c518a06fcb2ea0b925119fb2c1bc35c05e1601", size = 258784, upload-time = "2026-01-26T02:45:30.503Z" }, + { url = "https://files.pythonhosted.org/packages/4d/c1/11f664f14d525e4a1b5327a82d4de61a1db604ab34c6603bb3c2cc63ad34/multidict-6.7.1-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:93b1818e4a6e0930454f0f2af7dfce69307ca03cdcfb3739bf4d91241967b6c1", size = 251980, upload-time = "2026-01-26T02:45:32.603Z" }, + { url = "https://files.pythonhosted.org/packages/e1/9f/75a9ac888121d0c5bbd4ecf4eead45668b1766f6baabfb3b7f66a410e231/multidict-6.7.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:f33dc2a3abe9249ea5d8360f969ec7f4142e7ac45ee7014d8f8d5acddf178b7b", size = 243602, upload-time = "2026-01-26T02:45:34.043Z" }, + { url = "https://files.pythonhosted.org/packages/9a/e7/50bf7b004cc8525d80dbbbedfdc7aed3e4c323810890be4413e589074032/multidict-6.7.1-cp314-cp314-win32.whl", hash = "sha256:3ab8b9d8b75aef9df299595d5388b14530839f6422333357af1339443cff777d", size = 40930, upload-time = "2026-01-26T02:45:36.278Z" }, + { url = "https://files.pythonhosted.org/packages/e0/bf/52f25716bbe93745595800f36fb17b73711f14da59ed0bb2eba141bc9f0f/multidict-6.7.1-cp314-cp314-win_amd64.whl", hash = "sha256:5e01429a929600e7dab7b166062d9bb54a5eed752384c7384c968c2afab8f50f", size = 45074, upload-time = "2026-01-26T02:45:37.546Z" }, + { url = "https://files.pythonhosted.org/packages/97/ab/22803b03285fa3a525f48217963da3a65ae40f6a1b6f6cf2768879e208f9/multidict-6.7.1-cp314-cp314-win_arm64.whl", hash = "sha256:4885cb0e817aef5d00a2e8451d4665c1808378dc27c2705f1bf4ef8505c0d2e5", size = 42471, upload-time = "2026-01-26T02:45:38.889Z" }, + { url = "https://files.pythonhosted.org/packages/e0/6d/f9293baa6146ba9507e360ea0292b6422b016907c393e2f63fc40ab7b7b5/multidict-6.7.1-cp314-cp314t-macosx_10_15_universal2.whl", hash = "sha256:0458c978acd8e6ea53c81eefaddbbee9c6c5e591f41b3f5e8e194780fe026581", size = 82401, upload-time = "2026-01-26T02:45:40.254Z" }, + { url = "https://files.pythonhosted.org/packages/7a/68/53b5494738d83558d87c3c71a486504d8373421c3e0dbb6d0db48ad42ee0/multidict-6.7.1-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:c0abd12629b0af3cf590982c0b413b1e7395cd4ec026f30986818ab95bfaa94a", size = 48143, upload-time = "2026-01-26T02:45:41.635Z" }, + { url = "https://files.pythonhosted.org/packages/37/e8/5284c53310dcdc99ce5d66563f6e5773531a9b9fe9ec7a615e9bc306b05f/multidict-6.7.1-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:14525a5f61d7d0c94b368a42cff4c9a4e7ba2d52e2672a7b23d84dc86fb02b0c", size = 46507, upload-time = "2026-01-26T02:45:42.99Z" }, + { url = "https://files.pythonhosted.org/packages/e4/fc/6800d0e5b3875568b4083ecf5f310dcf91d86d52573160834fb4bfcf5e4f/multidict-6.7.1-cp314-cp314t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:17307b22c217b4cf05033dabefe68255a534d637c6c9b0cc8382718f87be4262", size = 239358, upload-time = "2026-01-26T02:45:44.376Z" }, + { url = "https://files.pythonhosted.org/packages/41/75/4ad0973179361cdf3a113905e6e088173198349131be2b390f9fa4da5fc6/multidict-6.7.1-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:7a7e590ff876a3eaf1c02a4dfe0724b6e69a9e9de6d8f556816f29c496046e59", size = 246884, upload-time = "2026-01-26T02:45:47.167Z" }, + { url = "https://files.pythonhosted.org/packages/c3/9c/095bb28b5da139bd41fb9a5d5caff412584f377914bd8787c2aa98717130/multidict-6.7.1-cp314-cp314t-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:5fa6a95dfee63893d80a34758cd0e0c118a30b8dcb46372bf75106c591b77889", size = 225878, upload-time = "2026-01-26T02:45:48.698Z" }, + { url = "https://files.pythonhosted.org/packages/07/d0/c0a72000243756e8f5a277b6b514fa005f2c73d481b7d9e47cd4568aa2e4/multidict-6.7.1-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:a0543217a6a017692aa6ae5cc39adb75e587af0f3a82288b1492eb73dd6cc2a4", size = 253542, upload-time = "2026-01-26T02:45:50.164Z" }, + { url = "https://files.pythonhosted.org/packages/c0/6b/f69da15289e384ecf2a68837ec8b5ad8c33e973aa18b266f50fe55f24b8c/multidict-6.7.1-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:f99fe611c312b3c1c0ace793f92464d8cd263cc3b26b5721950d977b006b6c4d", size = 252403, upload-time = "2026-01-26T02:45:51.779Z" }, + { url = "https://files.pythonhosted.org/packages/a2/76/b9669547afa5a1a25cd93eaca91c0da1c095b06b6d2d8ec25b713588d3a1/multidict-6.7.1-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9004d8386d133b7e6135679424c91b0b854d2d164af6ea3f289f8f2761064609", size = 244889, upload-time = "2026-01-26T02:45:53.27Z" }, + { url = "https://files.pythonhosted.org/packages/7e/a9/a50d2669e506dad33cfc45b5d574a205587b7b8a5f426f2fbb2e90882588/multidict-6.7.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:e628ef0e6859ffd8273c69412a2465c4be4a9517d07261b33334b5ec6f3c7489", size = 241982, upload-time = "2026-01-26T02:45:54.919Z" }, + { url = "https://files.pythonhosted.org/packages/c5/bb/1609558ad8b456b4827d3c5a5b775c93b87878fd3117ed3db3423dfbce1b/multidict-6.7.1-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:841189848ba629c3552035a6a7f5bf3b02eb304e9fea7492ca220a8eda6b0e5c", size = 232415, upload-time = "2026-01-26T02:45:56.981Z" }, + { url = "https://files.pythonhosted.org/packages/d8/59/6f61039d2aa9261871e03ab9dc058a550d240f25859b05b67fd70f80d4b3/multidict-6.7.1-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:ce1bbd7d780bb5a0da032e095c951f7014d6b0a205f8318308140f1a6aba159e", size = 240337, upload-time = "2026-01-26T02:45:58.698Z" }, + { url = "https://files.pythonhosted.org/packages/a1/29/fdc6a43c203890dc2ae9249971ecd0c41deaedfe00d25cb6564b2edd99eb/multidict-6.7.1-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:b26684587228afed0d50cf804cc71062cc9c1cdf55051c4c6345d372947b268c", size = 248788, upload-time = "2026-01-26T02:46:00.862Z" }, + { url = "https://files.pythonhosted.org/packages/a9/14/a153a06101323e4cf086ecee3faadba52ff71633d471f9685c42e3736163/multidict-6.7.1-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:9f9af11306994335398293f9958071019e3ab95e9a707dc1383a35613f6abcb9", size = 242842, upload-time = "2026-01-26T02:46:02.824Z" }, + { url = "https://files.pythonhosted.org/packages/41/5f/604ae839e64a4a6efc80db94465348d3b328ee955e37acb24badbcd24d83/multidict-6.7.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:b4938326284c4f1224178a560987b6cf8b4d38458b113d9b8c1db1a836e640a2", size = 240237, upload-time = "2026-01-26T02:46:05.898Z" }, + { url = "https://files.pythonhosted.org/packages/5f/60/c3a5187bf66f6fb546ff4ab8fb5a077cbdd832d7b1908d4365c7f74a1917/multidict-6.7.1-cp314-cp314t-win32.whl", hash = "sha256:98655c737850c064a65e006a3df7c997cd3b220be4ec8fe26215760b9697d4d7", size = 48008, upload-time = "2026-01-26T02:46:07.468Z" }, + { url = "https://files.pythonhosted.org/packages/0c/f7/addf1087b860ac60e6f382240f64fb99f8bfb532bb06f7c542b83c29ca61/multidict-6.7.1-cp314-cp314t-win_amd64.whl", hash = "sha256:497bde6223c212ba11d462853cfa4f0ae6ef97465033e7dc9940cdb3ab5b48e5", size = 53542, upload-time = "2026-01-26T02:46:08.809Z" }, + { url = "https://files.pythonhosted.org/packages/4c/81/4629d0aa32302ef7b2ec65c75a728cc5ff4fa410c50096174c1632e70b3e/multidict-6.7.1-cp314-cp314t-win_arm64.whl", hash = "sha256:2bbd113e0d4af5db41d5ebfe9ccaff89de2120578164f86a5d17d5a576d1e5b2", size = 44719, upload-time = "2026-01-26T02:46:11.146Z" }, + { url = "https://files.pythonhosted.org/packages/81/08/7036c080d7117f28a4af526d794aab6a84463126db031b007717c1a6676e/multidict-6.7.1-py3-none-any.whl", hash = "sha256:55d97cc6dae627efa6a6e548885712d4864b81110ac76fa4e534c03819fa4a56", size = 12319, upload-time = "2026-01-26T02:46:44.004Z" }, ] [[package]] @@ -3075,15 +3152,15 @@ wheels = [ [[package]] name = "mypy-protobuf" -version = "3.6.0" +version = "3.7.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "protobuf" }, { name = "types-protobuf" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/4d/6f/282d64d66bf48ce60e38a6560753f784e0f88ab245ac2fb5e93f701a36cd/mypy-protobuf-3.6.0.tar.gz", hash = "sha256:02f242eb3409f66889f2b1a3aa58356ec4d909cdd0f93115622e9e70366eca3c", size = 24445, upload-time = "2024-04-01T20:24:42.837Z" } +sdist = { url = "https://files.pythonhosted.org/packages/99/bd/92ee9e7d2ff30cb57b36bd6f61ee4da8a05acf32f6a6121883b58720e9d4/mypy_protobuf-3.7.0.tar.gz", hash = "sha256:912fb281f7c7b3e3a7c9b8695712618a716fddbab70f6ad63eaf68eda80c5efe", size = 25690, upload-time = "2025-11-17T22:11:12.809Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/e8/73/d6b999782ae22f16971cc05378b3b33f6a89ede3b9619e8366aa23484bca/mypy_protobuf-3.6.0-py3-none-any.whl", hash = "sha256:56176e4d569070e7350ea620262478b49b7efceba4103d468448f1d21492fd6c", size = 16434, upload-time = "2024-04-01T20:24:40.583Z" }, + { url = "https://files.pythonhosted.org/packages/69/32/709df4390d155bd72e75f2a9bce6004c2958a21f31817f3a2c7750299f70/mypy_protobuf-3.7.0-py3-none-any.whl", hash = "sha256:85256e9d4da935722ce8fbaa8d19397e1a2989aa8075c96577987de9fe7cea4d", size = 17488, upload-time = "2025-11-17T22:11:11.62Z" }, ] [[package]] @@ -3126,65 +3203,66 @@ wheels = [ [[package]] name = "nh3" -version = "0.3.1" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/cf/a6/c6e942fc8dcadab08645f57a6d01d63e97114a30ded5f269dc58e05d4741/nh3-0.3.1.tar.gz", hash = "sha256:6a854480058683d60bdc7f0456105092dae17bef1f300642856d74bd4201da93", size = 18590, upload-time = "2025-10-07T03:27:58.217Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/9c/24/4becaa61e066ff694c37627f5ef7528901115ffa17f7a6693c40da52accd/nh3-0.3.1-cp313-cp313t-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:80dc7563a2a3b980e44b221f69848e3645bbf163ab53e3d1add4f47b26120355", size = 1420887, upload-time = "2025-10-07T03:27:25.654Z" }, - { url = "https://files.pythonhosted.org/packages/94/49/16a6ec9098bb9bdf0fb9f09d6464865a3a48858d8d96e779a998ec3bdce0/nh3-0.3.1-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8f600ad86114df21efc4a3592faa6b1d099c0eebc7e018efebb1c133376097da", size = 791700, upload-time = "2025-10-07T03:27:27.041Z" }, - { url = "https://files.pythonhosted.org/packages/1d/cc/1c024d7c23ad031dfe82ad59581736abcc403b006abb0d2785bffa768b54/nh3-0.3.1-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:669a908706cd28203d9cfce2f567575686e364a1bc6074d413d88d456066f743", size = 830225, upload-time = "2025-10-07T03:27:28.315Z" }, - { url = "https://files.pythonhosted.org/packages/89/08/4a87f9212373bd77bba01c1fd515220e0d263316f448d9c8e4b09732a645/nh3-0.3.1-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:a5721f59afa0ab3dcaa0d47e58af33a5fcd254882e1900ee4a8968692a40f79d", size = 999112, upload-time = "2025-10-07T03:27:29.782Z" }, - { url = "https://files.pythonhosted.org/packages/19/cf/94783911eb966881a440ba9641944c27152662a253c917a794a368b92a3c/nh3-0.3.1-cp313-cp313t-musllinux_1_2_armv7l.whl", hash = "sha256:2cb6d9e192fbe0d451c7cb1350dadedbeae286207dbf101a28210193d019752e", size = 1070424, upload-time = "2025-10-07T03:27:31.2Z" }, - { url = "https://files.pythonhosted.org/packages/71/44/efb57b44e86a3de528561b49ed53803e5d42cd0441dcfd29b89422160266/nh3-0.3.1-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:474b176124c1b495ccfa1c20f61b7eb83ead5ecccb79ab29f602c148e8378489", size = 996129, upload-time = "2025-10-07T03:27:32.595Z" }, - { url = "https://files.pythonhosted.org/packages/ee/d3/87c39ea076510e57ee99a27fa4c2335e9e5738172b3963ee7c744a32726c/nh3-0.3.1-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:4a2434668f4eef4eab17c128e565ce6bea42113ce10c40b928e42c578d401800", size = 980310, upload-time = "2025-10-07T03:27:34.282Z" }, - { url = "https://files.pythonhosted.org/packages/bc/30/00cfbd2a4d268e8d3bda9d1542ba4f7a20fbed37ad1e8e51beeee3f6fdae/nh3-0.3.1-cp313-cp313t-win32.whl", hash = "sha256:0f454ba4c6aabafcaae964ae6f0a96cecef970216a57335fabd229a265fbe007", size = 584439, upload-time = "2025-10-07T03:27:36.103Z" }, - { url = "https://files.pythonhosted.org/packages/80/fa/39d27a62a2f39eb88c2bd50d9fee365a3645e456f3ec483c945a49c74f47/nh3-0.3.1-cp313-cp313t-win_amd64.whl", hash = "sha256:22b9e9c9eda497b02b7273b79f7d29e1f1170d2b741624c1b8c566aef28b1f48", size = 592388, upload-time = "2025-10-07T03:27:37.075Z" }, - { url = "https://files.pythonhosted.org/packages/7c/39/7df1c4ee13ef65ee06255df8101141793e97b4326e8509afbce5deada2b5/nh3-0.3.1-cp313-cp313t-win_arm64.whl", hash = "sha256:42e426f36e167ed29669b77ae3c4b9e185e4a1b130a86d7c3249194738a1d7b2", size = 579337, upload-time = "2025-10-07T03:27:38.055Z" }, - { url = "https://files.pythonhosted.org/packages/e1/28/a387fed70438d2810c8ac866e7b24bf1a5b6f30ae65316dfe4de191afa52/nh3-0.3.1-cp38-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:1de5c1a35bed19a1b1286bab3c3abfe42e990a8a6c4ce9bb9ab4bde49107ea3b", size = 1433666, upload-time = "2025-10-07T03:27:39.118Z" }, - { url = "https://files.pythonhosted.org/packages/c7/f9/500310c1f19cc80770a81aac3c94a0c6b4acdd46489e34019173b2b15a50/nh3-0.3.1-cp38-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:eaba26591867f697cffdbc539faddeb1d75a36273f5bfe957eb421d3f87d7da1", size = 819897, upload-time = "2025-10-07T03:27:40.488Z" }, - { url = "https://files.pythonhosted.org/packages/d0/d4/ebb0965d767cba943793fa8f7b59d7f141bd322c86387a5e9485ad49754a/nh3-0.3.1-cp38-abi3-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:489ca5ecd58555c2865701e65f614b17555179e71ecc76d483b6f3886b813a9b", size = 803562, upload-time = "2025-10-07T03:27:41.86Z" }, - { url = "https://files.pythonhosted.org/packages/0a/9c/df037a13f0513283ecee1cf99f723b18e5f87f20e480582466b1f8e3a7db/nh3-0.3.1-cp38-abi3-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:5a25662b392b06f251da6004a1f8a828dca7f429cd94ac07d8a98ba94d644438", size = 1050854, upload-time = "2025-10-07T03:27:43.29Z" }, - { url = "https://files.pythonhosted.org/packages/d0/9d/488fce56029de430e30380ec21f29cfaddaf0774f63b6aa2bf094c8b4c27/nh3-0.3.1-cp38-abi3-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:38b4872499ab15b17c5c6e9f091143d070d75ddad4a4d1ce388d043ca556629c", size = 1002152, upload-time = "2025-10-07T03:27:44.358Z" }, - { url = "https://files.pythonhosted.org/packages/da/4a/24b0118de34d34093bf03acdeca3a9556f8631d4028814a72b9cc5216382/nh3-0.3.1-cp38-abi3-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:48425995d37880281b467f7cf2b3218c1f4750c55bcb1ff4f47f2320a2bb159c", size = 912333, upload-time = "2025-10-07T03:27:45.757Z" }, - { url = "https://files.pythonhosted.org/packages/11/0e/16b3886858b3953ef836dea25b951f3ab0c5b5a431da03f675c0e999afb8/nh3-0.3.1-cp38-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:94292dd1bd2a2e142fa5bb94c0ee1d84433a5d9034640710132da7e0376fca3a", size = 796945, upload-time = "2025-10-07T03:27:47.169Z" }, - { url = "https://files.pythonhosted.org/packages/87/bb/aac139cf6796f2e0fec026b07843cea36099864ec104f865e2d802a25a30/nh3-0.3.1-cp38-abi3-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:dd6d1be301123a9af3263739726eeeb208197e5e78fc4f522408c50de77a5354", size = 837257, upload-time = "2025-10-07T03:27:48.243Z" }, - { url = "https://files.pythonhosted.org/packages/f8/d7/1d770876a288a3f5369fd6c816363a5f9d3a071dba24889458fdeb4f7a49/nh3-0.3.1-cp38-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:b74bbd047b361c0f21d827250c865ff0895684d9fcf85ea86131a78cfa0b835b", size = 1004142, upload-time = "2025-10-07T03:27:49.278Z" }, - { url = "https://files.pythonhosted.org/packages/31/2a/c4259e8b94c2f4ba10a7560e0889a6b7d2f70dce7f3e93f6153716aaae47/nh3-0.3.1-cp38-abi3-musllinux_1_2_armv7l.whl", hash = "sha256:b222c05ae5139320da6caa1c5aed36dd0ee36e39831541d9b56e048a63b4d701", size = 1075896, upload-time = "2025-10-07T03:27:50.527Z" }, - { url = "https://files.pythonhosted.org/packages/59/06/b15ba9fea4773741acb3382dcf982f81e55f6053e8a6e72a97ac91928b1d/nh3-0.3.1-cp38-abi3-musllinux_1_2_i686.whl", hash = "sha256:b0d6c834d3c07366ecbdcecc1f4804c5ce0a77fa52ee4653a2a26d2d909980ea", size = 1003235, upload-time = "2025-10-07T03:27:51.673Z" }, - { url = "https://files.pythonhosted.org/packages/1d/13/74707f99221bbe0392d18611b51125d45f8bd5c6be077ef85575eb7a38b1/nh3-0.3.1-cp38-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:670f18b09f75c86c3865f79543bf5acd4bbe2a5a4475672eef2399dd8cdb69d2", size = 987308, upload-time = "2025-10-07T03:27:53.003Z" }, - { url = "https://files.pythonhosted.org/packages/ee/81/24bf41a5ce7648d7e954de40391bb1bcc4b7731214238c7138c2420f962c/nh3-0.3.1-cp38-abi3-win32.whl", hash = "sha256:d7431b2a39431017f19cd03144005b6c014201b3e73927c05eab6ca37bb1d98c", size = 591695, upload-time = "2025-10-07T03:27:54.43Z" }, - { url = "https://files.pythonhosted.org/packages/a5/ca/263eb96b6d32c61a92c1e5480b7f599b60db7d7fbbc0d944be7532d0ac42/nh3-0.3.1-cp38-abi3-win_amd64.whl", hash = "sha256:c0acef923a1c3a2df3ee5825ea79c149b6748c6449781c53ab6923dc75e87d26", size = 600564, upload-time = "2025-10-07T03:27:55.966Z" }, - { url = "https://files.pythonhosted.org/packages/34/67/d5e07efd38194f52b59b8af25a029b46c0643e9af68204ee263022924c27/nh3-0.3.1-cp38-abi3-win_arm64.whl", hash = "sha256:a3e810a92fb192373204456cac2834694440af73d749565b4348e30235da7f0b", size = 586369, upload-time = "2025-10-07T03:27:57.234Z" }, +version = "0.3.4" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/4e/86/f8d3a7c9bd1bbaa181f6312c757e0b74d25f71ecf84ea3c0dc5e0f01840d/nh3-0.3.4.tar.gz", hash = "sha256:96709a379997c1b28c8974146ca660b0dcd3794f4f6d50c1ea549bab39ac6ade", size = 19520, upload-time = "2026-03-25T10:57:30.789Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/fd/5e/c400663d14be2216bc084ed2befc871b7b12563f85d40904f2a4bf0dd2b7/nh3-0.3.4-cp314-cp314t-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:8b61058f34c2105d44d2a4d4241bacf603a1ef5c143b08766bbd0cf23830118f", size = 1417991, upload-time = "2026-03-25T10:56:59.13Z" }, + { url = "https://files.pythonhosted.org/packages/36/f5/109526f5002ec41322ac8cafd50f0f154bae0c26b9607c0fcb708bdca8ec/nh3-0.3.4-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:554cc2bab281758e94d770c3fb0bf2d8be5fb403ef6b2e8841dd7c1615df7a0f", size = 790566, upload-time = "2026-03-25T10:57:00.445Z" }, + { url = "https://files.pythonhosted.org/packages/7b/66/38950f2b4b316ffd82ee51ed8f9143d1f56fdd620312cacc91613b77b3e7/nh3-0.3.4-cp314-cp314t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:dbe76feaa44e2ef9436f345016012a591550e77818876a8de5c8bc2a248e08df", size = 837538, upload-time = "2026-03-25T10:57:01.848Z" }, + { url = "https://files.pythonhosted.org/packages/d8/9f/9d6da970e9524fe360ea02a2082856390c2c8ba540409d1be6e5851887b3/nh3-0.3.4-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:87dac8d611b4a478400e0821a13b35770e88c266582f065e7249d6a37b0f86e8", size = 1012154, upload-time = "2026-03-25T10:57:03.592Z" }, + { url = "https://files.pythonhosted.org/packages/54/92/7c85c33c241e9dd51dda115bd3f765e940446588cdaaca62ef8edffe675f/nh3-0.3.4-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:8d697e19f2995b337f648204848ac3a528eaafffc39e7ce4ac6b7a2fbe6c84af", size = 1092516, upload-time = "2026-03-25T10:57:04.726Z" }, + { url = "https://files.pythonhosted.org/packages/16/0f/597842bdb2890999a3faa2f3fcb02db8aa6ad09320d3d843ff6d0a1f737b/nh3-0.3.4-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:7cae217f031809321db962cd7e092bda8d4e95a87f78c0226628fa6c2ea8ebc5", size = 1053793, upload-time = "2026-03-25T10:57:06.171Z" }, + { url = "https://files.pythonhosted.org/packages/7d/32/669da65147bc10746d2e1d7a8a3dbfbffe0315f419e74b559e2ee3471a01/nh3-0.3.4-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:07999b998bf89692738f15c0eac76a416382932f855709e0b7488b595c30ec89", size = 1035975, upload-time = "2026-03-25T10:57:07.292Z" }, + { url = "https://files.pythonhosted.org/packages/a1/7e/9e97a8b3c5161c79b4bf21cc54e9334860a52cc54ede15bf2239ef494b73/nh3-0.3.4-cp314-cp314t-win32.whl", hash = "sha256:ca90397c8d36c1535bf1988b2bed006597337843a164c7ec269dc8813f37536b", size = 600419, upload-time = "2026-03-25T10:57:08.342Z" }, + { url = "https://files.pythonhosted.org/packages/e0/c7/6849d8d4295d3997d148eacb2d4b1c9faada4895ee3c1b1e12e72f4611e2/nh3-0.3.4-cp314-cp314t-win_amd64.whl", hash = "sha256:41e46b3499918ab6128b6421677b316e79869d0c140da24069d220a94f4e72d1", size = 613342, upload-time = "2026-03-25T10:57:09.593Z" }, + { url = "https://files.pythonhosted.org/packages/8b/0e/14a3f510f36c20b922c123a2730f071f938d006fb513aacfd46d6cbc03a7/nh3-0.3.4-cp314-cp314t-win_arm64.whl", hash = "sha256:80b955d802bf365bd42e09f6c3d64567dce777d20e97968d94b3e9d9e99b265e", size = 607025, upload-time = "2026-03-25T10:57:10.959Z" }, + { url = "https://files.pythonhosted.org/packages/4a/57/a97955bc95960cfb1f0517043d60a121f4ba93fde252d4d9ffd3c2a9eead/nh3-0.3.4-cp38-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:d8bebcb20ab4b91858385cd98fe58046ec4a624275b45ef9b976475604f45b49", size = 1439519, upload-time = "2026-03-25T10:57:12.019Z" }, + { url = "https://files.pythonhosted.org/packages/2b/60/c9a33361da8cde7c7760f091cd10467bc470634e4eea31c8bb70935b00a4/nh3-0.3.4-cp38-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0d825722a1e8cbc87d7ca1e47ffb1d2a6cf343ad4c1b8465becf7cadcabcdfd0", size = 833798, upload-time = "2026-03-25T10:57:13.264Z" }, + { url = "https://files.pythonhosted.org/packages/6b/19/9487790780b8c94eacca37866c1270b747a4af8e244d43b3b550fddbbf62/nh3-0.3.4-cp38-abi3-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:4aa8b43e68c26b68069a3b6cef09de166d1d7fa140cf8d77e409a46cbf742e44", size = 820414, upload-time = "2026-03-25T10:57:14.236Z" }, + { url = "https://files.pythonhosted.org/packages/6b/b4/c6a340dd321d20b1e4a663307032741da045685c87403926c43656f6f5ec/nh3-0.3.4-cp38-abi3-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:f5f214618ad5eff4f2a6b13a8d4da4d9e7f37c569d90a13fb9f0caaf7d04fe21", size = 1061531, upload-time = "2026-03-25T10:57:15.384Z" }, + { url = "https://files.pythonhosted.org/packages/c4/49/f6b4b474e0032e4bcbb7174b44e4cf6915670e09c62421deb06ccfcb88b8/nh3-0.3.4-cp38-abi3-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3390e4333883673a684ce16c1716b481e91782d6f56dec5c85fed9feedb23382", size = 1021889, upload-time = "2026-03-25T10:57:16.454Z" }, + { url = "https://files.pythonhosted.org/packages/43/da/e52a6941746d1f974752af3fc8591f1dbcdcf7fd8c726c7d99f444ba820e/nh3-0.3.4-cp38-abi3-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:18a2e44ccb29cbb45071b8f3f2dab9ebfb41a6516f328f91f1f1fd18196239a4", size = 912965, upload-time = "2026-03-25T10:57:17.624Z" }, + { url = "https://files.pythonhosted.org/packages/d6/b7/ec1cbc6b297a808c513f59f501656389623fc09ad6a58c640851289c7854/nh3-0.3.4-cp38-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0961a27dc2057c38d0364cb05880e1997ae1c80220cbc847db63213720b8f304", size = 804975, upload-time = "2026-03-25T10:57:18.994Z" }, + { url = "https://files.pythonhosted.org/packages/a9/56/b1275aa2c6510191eed76178da4626b0900402439cb9f27d6b9bf7c6d5e9/nh3-0.3.4-cp38-abi3-manylinux_2_31_riscv64.whl", hash = "sha256:9337517edb7c10228252cce2898e20fb3d77e32ffaccbb3c66897927d74215a0", size = 833400, upload-time = "2026-03-25T10:57:20.086Z" }, + { url = "https://files.pythonhosted.org/packages/7c/a5/5d574ffa3c6e49a5364d1b25ebad165501c055340056671493beb467a15e/nh3-0.3.4-cp38-abi3-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d866701affe67a5171b916b5c076e767a74c6a9efb7fb2006eb8d3c5f9a293d5", size = 854277, upload-time = "2026-03-25T10:57:21.433Z" }, + { url = "https://files.pythonhosted.org/packages/79/36/8aeb2ab21517cefa212db109e41024e02650716cb42bf293d0a88437a92d/nh3-0.3.4-cp38-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:47d749d99ae005ab19517224140b280dd56e77b33afb82f9b600e106d0458003", size = 1022021, upload-time = "2026-03-25T10:57:22.433Z" }, + { url = "https://files.pythonhosted.org/packages/9c/95/9fd860997685e64abe2d5a995ca2eb5004c0fb6d6585429612a7871548b9/nh3-0.3.4-cp38-abi3-musllinux_1_2_armv7l.whl", hash = "sha256:f987cb56458323405e8e5ea827e1befcf141ffa0c0ac797d6d02e6b646056d9a", size = 1103526, upload-time = "2026-03-25T10:57:23.487Z" }, + { url = "https://files.pythonhosted.org/packages/7d/0d/df545070614c1007f0109bb004230226c9000e7857c9785583ec25cda9d7/nh3-0.3.4-cp38-abi3-musllinux_1_2_i686.whl", hash = "sha256:883d5a6d6ee8078c4afc8e96e022fe579c4c265775ff6ee21e39b8c542cabab3", size = 1068050, upload-time = "2026-03-25T10:57:24.624Z" }, + { url = "https://files.pythonhosted.org/packages/94/d5/17b016df52df052f714c53be71df26a1943551d9931e9383b92c998b88f8/nh3-0.3.4-cp38-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:75643c22f5092d8e209f766ee8108c400bc1e44760fc94d2d638eb138d18f853", size = 1046037, upload-time = "2026-03-25T10:57:25.799Z" }, + { url = "https://files.pythonhosted.org/packages/51/39/49f737907e6ab2b4ca71855d3bd63dd7958862e9c8b94fb4e5b18ccf6988/nh3-0.3.4-cp38-abi3-win32.whl", hash = "sha256:72e4e9ca1c4bd41b4a28b0190edc2e21e3f71496acd36a0162858e1a28db3d7e", size = 609542, upload-time = "2026-03-25T10:57:27.112Z" }, + { url = "https://files.pythonhosted.org/packages/73/4f/af8e9071d7464575a7316831938237ffc9d92d27f163dbdd964b1309cd9b/nh3-0.3.4-cp38-abi3-win_amd64.whl", hash = "sha256:c10b1f0c741e257a5cb2978d6bac86e7c784ab20572724b20c6402c2e24bce75", size = 624244, upload-time = "2026-03-25T10:57:28.302Z" }, + { url = "https://files.pythonhosted.org/packages/44/0c/37695d6b0168f6714b5c492331636a9e6123d6ec22d25876c68d06eab1b8/nh3-0.3.4-cp38-abi3-win_arm64.whl", hash = "sha256:43ad4eedee7e049b9069bc015b7b095d320ed6d167ecec111f877de1540656e9", size = 616649, upload-time = "2026-03-25T10:57:29.623Z" }, ] [[package]] name = "nodeenv" -version = "1.9.1" +version = "1.10.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/43/16/fc88b08840de0e0a72a2f9d8c6bae36be573e475a6326ae854bcc549fc45/nodeenv-1.9.1.tar.gz", hash = "sha256:6ec12890a2dab7946721edbfbcd91f3319c6ccc9aec47be7c7e6b7011ee6645f", size = 47437, upload-time = "2024-06-04T18:44:11.171Z" } +sdist = { url = "https://files.pythonhosted.org/packages/24/bf/d1bda4f6168e0b2e9e5958945e01910052158313224ada5ce1fb2e1113b8/nodeenv-1.10.0.tar.gz", hash = "sha256:996c191ad80897d076bdfba80a41994c2b47c68e224c542b48feba42ba00f8bb", size = 55611, upload-time = "2025-12-20T14:08:54.006Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/d2/1d/1b658dbd2b9fa9c4c9f32accbfc0205d532c8c6194dc0f2a4c0428e7128a/nodeenv-1.9.1-py2.py3-none-any.whl", hash = "sha256:ba11c9782d29c27c70ffbdda2d7415098754709be8a7056d79a737cd901155c9", size = 22314, upload-time = "2024-06-04T18:44:08.352Z" }, + { url = "https://files.pythonhosted.org/packages/88/b2/d0896bdcdc8d28a7fc5717c305f1a861c26e18c05047949fb371034d98bd/nodeenv-1.10.0-py2.py3-none-any.whl", hash = "sha256:5bb13e3eed2923615535339b3c620e76779af4cb4c6a90deccc9e36b274d3827", size = 23438, upload-time = "2025-12-20T14:08:52.782Z" }, ] [[package]] name = "nodejs-wheel-binaries" -version = "24.11.1" +version = "24.14.1" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/e4/89/da307731fdbb05a5f640b26de5b8ac0dc463fef059162accfc89e32f73bc/nodejs_wheel_binaries-24.11.1.tar.gz", hash = "sha256:413dfffeadfb91edb4d8256545dea797c237bba9b3faefea973cde92d96bb922", size = 8059, upload-time = "2025-11-18T18:21:58.207Z" } +sdist = { url = "https://files.pythonhosted.org/packages/f1/87/e5755ad739daafce2e152ab609293d65e6c663b399e28a4bbcd0f4af1f45/nodejs_wheel_binaries-24.14.1.tar.gz", hash = "sha256:d00ae0c86d7e1bfa798e8f8ad282db751af157cdcaa1208a1b9a2cf2a85ac821", size = 8056, upload-time = "2026-03-31T14:07:27Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/e4/5f/be5a4112e678143d4c15264d918f9a2dc086905c6426eb44515cf391a958/nodejs_wheel_binaries-24.11.1-py2.py3-none-macosx_13_0_arm64.whl", hash = "sha256:0e14874c3579def458245cdbc3239e37610702b0aa0975c1dc55e2cb80e42102", size = 55114309, upload-time = "2025-11-18T18:21:21.697Z" }, - { url = "https://files.pythonhosted.org/packages/fa/1c/2e9d6af2ea32b65928c42b3e5baa7a306870711d93c3536cb25fc090a80d/nodejs_wheel_binaries-24.11.1-py2.py3-none-macosx_13_0_x86_64.whl", hash = "sha256:c2741525c9874b69b3e5a6d6c9179a6fe484ea0c3d5e7b7c01121c8e5d78b7e2", size = 55285957, upload-time = "2025-11-18T18:21:27.177Z" }, - { url = "https://files.pythonhosted.org/packages/d0/79/35696d7ba41b1bd35ef8682f13d46ba38c826c59e58b86b267458eb53d87/nodejs_wheel_binaries-24.11.1-py2.py3-none-manylinux_2_28_aarch64.whl", hash = "sha256:5ef598101b0fb1c2bf643abb76dfbf6f76f1686198ed17ae46009049ee83c546", size = 59645875, upload-time = "2025-11-18T18:21:33.004Z" }, - { url = "https://files.pythonhosted.org/packages/b4/98/2a9694adee0af72bc602a046b0632a0c89e26586090c558b1c9199b187cc/nodejs_wheel_binaries-24.11.1-py2.py3-none-manylinux_2_28_x86_64.whl", hash = "sha256:cde41d5e4705266688a8d8071debf4f8a6fcea264c61292782672ee75a6905f9", size = 60140941, upload-time = "2025-11-18T18:21:37.228Z" }, - { url = "https://files.pythonhosted.org/packages/d0/d6/573e5e2cba9d934f5f89d0beab00c3315e2e6604eb4df0fcd1d80c5a07a8/nodejs_wheel_binaries-24.11.1-py2.py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:78bc5bb889313b565df8969bb7423849a9c7fc218bf735ff0ce176b56b3e96f0", size = 61644243, upload-time = "2025-11-18T18:21:43.325Z" }, - { url = "https://files.pythonhosted.org/packages/c7/e6/643234d5e94067df8ce8d7bba10f3804106668f7a1050aeb10fdd226ead4/nodejs_wheel_binaries-24.11.1-py2.py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:c79a7e43869ccecab1cae8183778249cceb14ca2de67b5650b223385682c6239", size = 62225657, upload-time = "2025-11-18T18:21:47.708Z" }, - { url = "https://files.pythonhosted.org/packages/4d/1c/2fb05127102a80225cab7a75c0e9edf88a0a1b79f912e1e36c7c1aaa8f4e/nodejs_wheel_binaries-24.11.1-py2.py3-none-win_amd64.whl", hash = "sha256:10197b1c9c04d79403501766f76508b0dac101ab34371ef8a46fcf51773497d0", size = 41322308, upload-time = "2025-11-18T18:21:51.347Z" }, - { url = "https://files.pythonhosted.org/packages/ad/b7/bc0cdbc2cc3a66fcac82c79912e135a0110b37b790a14c477f18e18d90cd/nodejs_wheel_binaries-24.11.1-py2.py3-none-win_arm64.whl", hash = "sha256:376b9ea1c4bc1207878975dfeb604f7aa5668c260c6154dcd2af9d42f7734116", size = 39026497, upload-time = "2025-11-18T18:21:54.634Z" }, + { url = "https://files.pythonhosted.org/packages/8b/b7/9765d9a5d3b95475829ef5965d4a4f6f4badb034ee4e18c2d5f8b9b65d6f/nodejs_wheel_binaries-24.14.1-py2.py3-none-macosx_13_0_arm64.whl", hash = "sha256:d9e856ba0f2d3d2659869e6e0f4cae6874faeeeca7f879131a88451356373ac4", size = 54945603, upload-time = "2026-03-31T14:06:58.526Z" }, + { url = "https://files.pythonhosted.org/packages/6f/15/bc2fa51ee31ce597b2af1905081e5a5add07fe0cf619bfa531d7df2f1f1b/nodejs_wheel_binaries-24.14.1-py2.py3-none-macosx_13_0_x86_64.whl", hash = "sha256:634f57829ebfdfe95d096f32a50c5cdd3a6c72a94dcf2b92a8bef9868cccb13e", size = 55119951, upload-time = "2026-03-31T14:07:02.597Z" }, + { url = "https://files.pythonhosted.org/packages/a6/dd/92ff0831262af4bbb5473d4e7964fd27afb0901a2690a6ff7bc3d220d97f/nodejs_wheel_binaries-24.14.1-py2.py3-none-manylinux_2_28_aarch64.whl", hash = "sha256:404b563467129e6a0ea7006a38b3d8af0ebfbc340b31a6a0af2c59ea3af90b7c", size = 59487620, upload-time = "2026-03-31T14:07:06.198Z" }, + { url = "https://files.pythonhosted.org/packages/45/36/bbbee3adf6afd00944e5a86ebd64987dea90bd347090155a4989dc3e8594/nodejs_wheel_binaries-24.14.1-py2.py3-none-manylinux_2_28_x86_64.whl", hash = "sha256:7863c62f8a3946b727831f71375a9ae00205b3258478476034b49c3a1d57ac12", size = 59986044, upload-time = "2026-03-31T14:07:09.846Z" }, + { url = "https://files.pythonhosted.org/packages/05/16/119e4168bf7ed17ad7961d122701c75ac86135fa243a958b960a3f1b7055/nodejs_wheel_binaries-24.14.1-py2.py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:a3f64daa1235fa6a83c778ded98d5fe4e74979ca54aa2ffb807f0805c57c3abe", size = 61489823, upload-time = "2026-03-31T14:07:13.378Z" }, + { url = "https://files.pythonhosted.org/packages/8c/a6/d581996827b9d1133094dc347f1c4e3d2a70557973ce7a427a03337b1427/nodejs_wheel_binaries-24.14.1-py2.py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:810a48ce096925ead0690f7d143e48fb902ebfc9212097e8f6cb3ac6cbe8f314", size = 62069740, upload-time = "2026-03-31T14:07:17.006Z" }, + { url = "https://files.pythonhosted.org/packages/27/da/396d1a48cbf3d5899461bda12fa97ae4010d7e4013e7f28230cb04af5818/nodejs_wheel_binaries-24.14.1-py2.py3-none-win_amd64.whl", hash = "sha256:7a087b6a727fb9242d1cc83c8b121711bd0e9686408d27de48b34b23dfb26ac5", size = 41400067, upload-time = "2026-03-31T14:07:20.513Z" }, + { url = "https://files.pythonhosted.org/packages/13/b7/adb21cf549934579e98934531e7f9b038d583fc9c2dd4b82ea01cc31bdd2/nodejs_wheel_binaries-24.14.1-py2.py3-none-win_arm64.whl", hash = "sha256:978fdfe76624c48111ab99ed0f99f9d4c1c682e420b0212ac9e1daee52f20283", size = 39096873, upload-time = "2026-03-31T14:07:23.977Z" }, ] [[package]] name = "openai" -version = "2.13.0" +version = "2.30.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "anyio" }, @@ -3196,14 +3274,14 @@ dependencies = [ { name = "tqdm" }, { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/0f/39/8e347e9fda125324d253084bb1b82407e5e3c7777a03dc398f79b2d95626/openai-2.13.0.tar.gz", hash = "sha256:9ff633b07a19469ec476b1e2b5b26c5ef700886524a7a72f65e6f0b5203142d5", size = 626583, upload-time = "2025-12-16T18:19:44.387Z" } +sdist = { url = "https://files.pythonhosted.org/packages/88/15/52580c8fbc16d0675d516e8749806eda679b16de1e4434ea06fb6feaa610/openai-2.30.0.tar.gz", hash = "sha256:92f7661c990bda4b22a941806c83eabe4896c3094465030dd882a71abe80c885", size = 676084, upload-time = "2026-03-25T22:08:59.96Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/bb/d5/eb52edff49d3d5ea116e225538c118699ddeb7c29fa17ec28af14bc10033/openai-2.13.0-py3-none-any.whl", hash = "sha256:746521065fed68df2f9c2d85613bb50844343ea81f60009b60e6a600c9352c79", size = 1066837, upload-time = "2025-12-16T18:19:43.124Z" }, + { url = "https://files.pythonhosted.org/packages/2a/9e/5bfa2270f902d5b92ab7d41ce0475b8630572e71e349b2a4996d14bdda93/openai-2.30.0-py3-none-any.whl", hash = "sha256:9a5ae616888eb2748ec5e0c5b955a51592e0b201a11f4262db920f2a78c5231d", size = 1146656, upload-time = "2026-03-25T22:08:58.2Z" }, ] [[package]] name = "openai-agents" -version = "0.6.3" +version = "0.6.9" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "griffe" }, @@ -3214,9 +3292,9 @@ dependencies = [ { name = "types-requests" }, { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/ac/0b/1bfc1f47708ce5500ad6b05ba8a0a789232ee6f5b9dd68938131c4674533/openai_agents-0.6.3.tar.gz", hash = "sha256:436479f201910cfc466893854b47d0f3acbf7b3bdafa95eedb590ed0d40393ef", size = 2016166, upload-time = "2025-12-11T18:07:47.823Z" } +sdist = { url = "https://files.pythonhosted.org/packages/3a/e3/41f4d83df6b9080ccba444b79e150aa3b57182bcc0deeb6adabe08678407/openai_agents-0.6.9.tar.gz", hash = "sha256:e55623827b4a1b11d66ec0084bd2b9ea2c6d60f233e04547803af433967e2fdb", size = 2152399, upload-time = "2026-01-20T01:57:00.04Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/3e/06/d4bf0a8403ebc7d6b0fb2b45e41d6da6996b20f1dde1debffdac1b5ccb63/openai_agents-0.6.3-py3-none-any.whl", hash = "sha256:ada8b598f4db787939a62c8a291d07cbe68dae2d635955c44a0a0300746ee84f", size = 239015, upload-time = "2025-12-11T18:07:46.275Z" }, + { url = "https://files.pythonhosted.org/packages/a7/9f/1cb6d64487c185c8e775c66314e5c047ca307b3bcd6c5edb97af6c0b5d6e/openai_agents-0.6.9-py3-none-any.whl", hash = "sha256:9e05a96b7610a7a89d6fd9ba379ff840a1aebca150eebcc4d505743ee458f50b", size = 284423, upload-time = "2026-01-20T01:56:57.54Z" }, ] [package.optional-dependencies] @@ -3260,7 +3338,7 @@ wheels = [ [[package]] name = "openinference-instrumentation" -version = "0.1.42" +version = "0.1.46" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "openinference-semantic-conventions" }, @@ -3268,9 +3346,9 @@ dependencies = [ { name = "opentelemetry-sdk" }, { name = "wrapt" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/00/d0/b19061a21fd6127d2857c77744a36073bba9c1502d1d5e8517b708eb8b7c/openinference_instrumentation-0.1.42.tar.gz", hash = "sha256:2275babc34022e151b5492cfba41d3b12e28377f8e08cb45e5d64fe2d9d7fe37", size = 23954, upload-time = "2025-11-05T01:37:46.869Z" } +sdist = { url = "https://files.pythonhosted.org/packages/64/8d/9b76b43e8b2ee2ccf1fe15b21c924095f9c0e4839919bcd4951b1c99c2ab/openinference_instrumentation-0.1.46.tar.gz", hash = "sha256:0b520002a1c682c525dcab49005c209bfd71611e8e4e4933b49779d5e899e6db", size = 23937, upload-time = "2026-03-04T10:13:48.883Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/c3/71/43ee4616fc95dbd2f560550f199c6652a5eb93f84e8aa0039bc95c19cfe0/openinference_instrumentation-0.1.42-py3-none-any.whl", hash = "sha256:e7521ff90833ef7cc65db526a2f59b76a496180abeaaee30ec6abbbc0b43f8ec", size = 30086, upload-time = "2025-11-05T01:37:43.866Z" }, + { url = "https://files.pythonhosted.org/packages/25/d1/f6668492152a4180492044313e2dc427fbc237904f6bb1629abd030e3469/openinference_instrumentation-0.1.46-py3-none-any.whl", hash = "sha256:f7b63ccd5f93ce82e4e40035c9faa6b021984cbe06ad791f4cf033551533bc48", size = 30124, upload-time = "2026-03-04T10:13:47.613Z" }, ] [[package]] @@ -3293,7 +3371,7 @@ wheels = [ [[package]] name = "openinference-instrumentation-openai-agents" -version = "1.4.0" +version = "1.4.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "openinference-instrumentation" }, @@ -3304,31 +3382,31 @@ dependencies = [ { name = "typing-extensions" }, { name = "wrapt" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/f4/40/ac0a3ad5040d2582156f6c0fa2b8f6233af79af295dab154d642d42aed69/openinference_instrumentation_openai_agents-1.4.0.tar.gz", hash = "sha256:2fd50d03f6d999b9793566a1f2787bf9e2cd3774fa8bf32542250dfc61e32d62", size = 12746, upload-time = "2025-12-04T19:58:36.319Z" } +sdist = { url = "https://files.pythonhosted.org/packages/0f/95/9ace0fa5c1455f24b3c6e9c54ff7fbfab752abd66deccd3689f31d9200d3/openinference_instrumentation_openai_agents-1.4.1.tar.gz", hash = "sha256:145741867f809a04fa4640adc188e65e745ed9e3b306f811c3ecd994346f8cca", size = 12783, upload-time = "2026-04-03T21:21:26.042Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/c6/e5/299103b68f5427a7d11acd0f4804c5b3f3e9508a511f8f8078a43ad7e6bd/openinference_instrumentation_openai_agents-1.4.0-py3-none-any.whl", hash = "sha256:539361d0f3bdebdb1e898250fbba8e6173f2bce9d7ba007cf7934f10850f474b", size = 14411, upload-time = "2025-12-04T19:58:34.224Z" }, + { url = "https://files.pythonhosted.org/packages/aa/5a/1e42244b23fba3d785f792fc2783264d3eae033eb785ec9fde260adf81d9/openinference_instrumentation_openai_agents-1.4.1-py3-none-any.whl", hash = "sha256:834c7cbaba2fdd3d2ce75967ef1d9f946e5f29aa8833d69c33d6fb2c85c65896", size = 14489, upload-time = "2026-04-03T21:21:24.892Z" }, ] [[package]] name = "openinference-semantic-conventions" -version = "0.1.25" +version = "0.1.28" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/0b/68/81c8a0b90334ff11e4f285e4934c57f30bea3ef0c0b9f99b65e7b80fae3b/openinference_semantic_conventions-0.1.25.tar.gz", hash = "sha256:f0a8c2cfbd00195d1f362b4803518341e80867d446c2959bf1743f1894fce31d", size = 12767, upload-time = "2025-11-05T01:37:45.89Z" } +sdist = { url = "https://files.pythonhosted.org/packages/df/32/c79bf8bd3ea5a00e492449b31ca600bbc2a8e88a301e42c872af925a156c/openinference_semantic_conventions-0.1.28.tar.gz", hash = "sha256:6388465174e8ab3f27ebc6a9e9bb2e1b804d30caefb57234e16db874da1c6a7b", size = 12893, upload-time = "2026-03-11T04:45:46.543Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/fd/3d/dd14ee2eb8a3f3054249562e76b253a1545c76adbbfd43a294f71acde5c3/openinference_semantic_conventions-0.1.25-py3-none-any.whl", hash = "sha256:3814240f3bd61f05d9562b761de70ee793d55b03bca1634edf57d7a2735af238", size = 10395, upload-time = "2025-11-05T01:37:43.697Z" }, + { url = "https://files.pythonhosted.org/packages/04/40/34b570462c3ce250277254bb0cca655eb39b64c0dffe63cd7751f103f8d6/openinference_semantic_conventions-0.1.28-py3-none-any.whl", hash = "sha256:a2fed5bb167aa56c1c7448cdb7a8d775f989339ba1f8b04a7b45d4f8388cccfb", size = 10522, upload-time = "2026-03-11T04:45:45.423Z" }, ] [[package]] name = "opentelemetry-api" -version = "1.37.0" +version = "1.38.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "importlib-metadata" }, { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/63/04/05040d7ce33a907a2a02257e601992f0cdf11c73b33f13c4492bf6c3d6d5/opentelemetry_api-1.37.0.tar.gz", hash = "sha256:540735b120355bd5112738ea53621f8d5edb35ebcd6fe21ada3ab1c61d1cd9a7", size = 64923, upload-time = "2025-09-11T10:29:01.662Z" } +sdist = { url = "https://files.pythonhosted.org/packages/08/d8/0f354c375628e048bd0570645b310797299754730079853095bf000fba69/opentelemetry_api-1.38.0.tar.gz", hash = "sha256:f4c193b5e8acb0912b06ac5b16321908dd0843d75049c091487322284a3eea12", size = 65242, upload-time = "2025-10-16T08:35:50.25Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/91/48/28ed9e55dcf2f453128df738210a980e09f4e468a456fa3c763dbc8be70a/opentelemetry_api-1.37.0-py3-none-any.whl", hash = "sha256:accf2024d3e89faec14302213bc39550ec0f4095d1cf5ca688e1bfb1c8612f47", size = 65732, upload-time = "2025-09-11T10:28:41.826Z" }, + { url = "https://files.pythonhosted.org/packages/ae/a2/d86e01c28300bd41bab8f18afd613676e2bd63515417b77636fc1add426f/opentelemetry_api-1.38.0-py3-none-any.whl", hash = "sha256:2891b0197f47124454ab9f0cf58f3be33faca394457ac3e09daba13ff50aa582", size = 65947, upload-time = "2025-10-16T08:35:30.23Z" }, ] [[package]] @@ -3378,19 +3456,19 @@ wheels = [ [[package]] name = "opentelemetry-exporter-otlp-proto-common" -version = "1.37.0" +version = "1.38.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "opentelemetry-proto" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/dc/6c/10018cbcc1e6fff23aac67d7fd977c3d692dbe5f9ef9bb4db5c1268726cc/opentelemetry_exporter_otlp_proto_common-1.37.0.tar.gz", hash = "sha256:c87a1bdd9f41fdc408d9cc9367bb53f8d2602829659f2b90be9f9d79d0bfe62c", size = 20430, upload-time = "2025-09-11T10:29:03.605Z" } +sdist = { url = "https://files.pythonhosted.org/packages/19/83/dd4660f2956ff88ed071e9e0e36e830df14b8c5dc06722dbde1841accbe8/opentelemetry_exporter_otlp_proto_common-1.38.0.tar.gz", hash = "sha256:e333278afab4695aa8114eeb7bf4e44e65c6607d54968271a249c180b2cb605c", size = 20431, upload-time = "2025-10-16T08:35:53.285Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/08/13/b4ef09837409a777f3c0af2a5b4ba9b7af34872bc43609dda0c209e4060d/opentelemetry_exporter_otlp_proto_common-1.37.0-py3-none-any.whl", hash = "sha256:53038428449c559b0c564b8d718df3314da387109c4d36bd1b94c9a641b0292e", size = 18359, upload-time = "2025-09-11T10:28:44.939Z" }, + { url = "https://files.pythonhosted.org/packages/a7/9e/55a41c9601191e8cd8eb626b54ee6827b9c9d4a46d736f32abc80d8039fc/opentelemetry_exporter_otlp_proto_common-1.38.0-py3-none-any.whl", hash = "sha256:03cb76ab213300fe4f4c62b7d8f17d97fcfd21b89f0b5ce38ea156327ddda74a", size = 18359, upload-time = "2025-10-16T08:35:34.099Z" }, ] [[package]] name = "opentelemetry-exporter-otlp-proto-grpc" -version = "1.37.0" +version = "1.38.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "googleapis-common-protos" }, @@ -3401,14 +3479,14 @@ dependencies = [ { name = "opentelemetry-sdk" }, { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/d1/11/4ad0979d0bb13ae5a845214e97c8d42da43980034c30d6f72d8e0ebe580e/opentelemetry_exporter_otlp_proto_grpc-1.37.0.tar.gz", hash = "sha256:f55bcb9fc848ce05ad3dd954058bc7b126624d22c4d9e958da24d8537763bec5", size = 24465, upload-time = "2025-09-11T10:29:04.172Z" } +sdist = { url = "https://files.pythonhosted.org/packages/a2/c0/43222f5b97dc10812bc4f0abc5dc7cd0a2525a91b5151d26c9e2e958f52e/opentelemetry_exporter_otlp_proto_grpc-1.38.0.tar.gz", hash = "sha256:2473935e9eac71f401de6101d37d6f3f0f1831db92b953c7dcc912536158ebd6", size = 24676, upload-time = "2025-10-16T08:35:53.83Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/39/17/46630b74751031a658706bef23ac99cdc2953cd3b2d28ec90590a0766b3e/opentelemetry_exporter_otlp_proto_grpc-1.37.0-py3-none-any.whl", hash = "sha256:aee5104835bf7993b7ddaaf380b6467472abaedb1f1dbfcc54a52a7d781a3890", size = 19305, upload-time = "2025-09-11T10:28:45.776Z" }, + { url = "https://files.pythonhosted.org/packages/28/f0/bd831afbdba74ca2ce3982142a2fad707f8c487e8a3b6fef01f1d5945d1b/opentelemetry_exporter_otlp_proto_grpc-1.38.0-py3-none-any.whl", hash = "sha256:7c49fd9b4bd0dbe9ba13d91f764c2d20b0025649a6e4ac35792fb8d84d764bc7", size = 19695, upload-time = "2025-10-16T08:35:35.053Z" }, ] [[package]] name = "opentelemetry-exporter-otlp-proto-http" -version = "1.37.0" +version = "1.38.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "googleapis-common-protos" }, @@ -3419,14 +3497,14 @@ dependencies = [ { name = "requests" }, { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/5d/e3/6e320aeb24f951449e73867e53c55542bebbaf24faeee7623ef677d66736/opentelemetry_exporter_otlp_proto_http-1.37.0.tar.gz", hash = "sha256:e52e8600f1720d6de298419a802108a8f5afa63c96809ff83becb03f874e44ac", size = 17281, upload-time = "2025-09-11T10:29:04.844Z" } +sdist = { url = "https://files.pythonhosted.org/packages/81/0a/debcdfb029fbd1ccd1563f7c287b89a6f7bef3b2902ade56797bfd020854/opentelemetry_exporter_otlp_proto_http-1.38.0.tar.gz", hash = "sha256:f16bd44baf15cbe07633c5112ffc68229d0edbeac7b37610be0b2def4e21e90b", size = 17282, upload-time = "2025-10-16T08:35:54.422Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/e9/e9/70d74a664d83976556cec395d6bfedd9b85ec1498b778367d5f93e373397/opentelemetry_exporter_otlp_proto_http-1.37.0-py3-none-any.whl", hash = "sha256:54c42b39945a6cc9d9a2a33decb876eabb9547e0dcb49df090122773447f1aef", size = 19576, upload-time = "2025-09-11T10:28:46.726Z" }, + { url = "https://files.pythonhosted.org/packages/e5/77/154004c99fb9f291f74aa0822a2f5bbf565a72d8126b3a1b63ed8e5f83c7/opentelemetry_exporter_otlp_proto_http-1.38.0-py3-none-any.whl", hash = "sha256:84b937305edfc563f08ec69b9cb2298be8188371217e867c1854d77198d0825b", size = 19579, upload-time = "2025-10-16T08:35:36.269Z" }, ] [[package]] name = "opentelemetry-instrumentation" -version = "0.58b0" +version = "0.59b0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "opentelemetry-api" }, @@ -3434,21 +3512,21 @@ dependencies = [ { name = "packaging" }, { name = "wrapt" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/f6/36/7c307d9be8ce4ee7beb86d7f1d31027f2a6a89228240405a858d6e4d64f9/opentelemetry_instrumentation-0.58b0.tar.gz", hash = "sha256:df640f3ac715a3e05af145c18f527f4422c6ab6c467e40bd24d2ad75a00cb705", size = 31549, upload-time = "2025-09-11T11:42:14.084Z" } +sdist = { url = "https://files.pythonhosted.org/packages/04/ed/9c65cd209407fd807fa05be03ee30f159bdac8d59e7ea16a8fe5a1601222/opentelemetry_instrumentation-0.59b0.tar.gz", hash = "sha256:6010f0faaacdaf7c4dff8aac84e226d23437b331dcda7e70367f6d73a7db1adc", size = 31544, upload-time = "2025-10-16T08:39:31.959Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/d4/db/5ff1cd6c5ca1d12ecf1b73be16fbb2a8af2114ee46d4b0e6d4b23f4f4db7/opentelemetry_instrumentation-0.58b0-py3-none-any.whl", hash = "sha256:50f97ac03100676c9f7fc28197f8240c7290ca1baa12da8bfbb9a1de4f34cc45", size = 33019, upload-time = "2025-09-11T11:41:00.624Z" }, + { url = "https://files.pythonhosted.org/packages/10/f5/7a40ff3f62bfe715dad2f633d7f1174ba1a7dd74254c15b2558b3401262a/opentelemetry_instrumentation-0.59b0-py3-none-any.whl", hash = "sha256:44082cc8fe56b0186e87ee8f7c17c327c4c2ce93bdbe86496e600985d74368ee", size = 33020, upload-time = "2025-10-16T08:38:31.463Z" }, ] [[package]] name = "opentelemetry-proto" -version = "1.37.0" +version = "1.38.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "protobuf" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/dd/ea/a75f36b463a36f3c5a10c0b5292c58b31dbdde74f6f905d3d0ab2313987b/opentelemetry_proto-1.37.0.tar.gz", hash = "sha256:30f5c494faf66f77faeaefa35ed4443c5edb3b0aa46dad073ed7210e1a789538", size = 46151, upload-time = "2025-09-11T10:29:11.04Z" } +sdist = { url = "https://files.pythonhosted.org/packages/51/14/f0c4f0f6371b9cb7f9fa9ee8918bfd59ac7040c7791f1e6da32a1839780d/opentelemetry_proto-1.38.0.tar.gz", hash = "sha256:88b161e89d9d372ce723da289b7da74c3a8354a8e5359992be813942969ed468", size = 46152, upload-time = "2025-10-16T08:36:01.612Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/c4/25/f89ea66c59bd7687e218361826c969443c4fa15dfe89733f3bf1e2a9e971/opentelemetry_proto-1.37.0-py3-none-any.whl", hash = "sha256:8ed8c066ae8828bbf0c39229979bdf583a126981142378a9cbe9d6fd5701c6e2", size = 72534, upload-time = "2025-09-11T10:28:56.831Z" }, + { url = "https://files.pythonhosted.org/packages/b6/6a/82b68b14efca5150b2632f3692d627afa76b77378c4999f2648979409528/opentelemetry_proto-1.38.0-py3-none-any.whl", hash = "sha256:b6ebe54d3217c42e45462e2a1ae28c3e2bf2ec5a5645236a490f55f45f1a0a18", size = 72535, upload-time = "2025-10-16T08:35:45.749Z" }, ] [[package]] @@ -3468,16 +3546,16 @@ wheels = [ [[package]] name = "opentelemetry-sdk" -version = "1.37.0" +version = "1.38.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "opentelemetry-api" }, { name = "opentelemetry-semantic-conventions" }, { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/f4/62/2e0ca80d7fe94f0b193135375da92c640d15fe81f636658d2acf373086bc/opentelemetry_sdk-1.37.0.tar.gz", hash = "sha256:cc8e089c10953ded765b5ab5669b198bbe0af1b3f89f1007d19acd32dc46dda5", size = 170404, upload-time = "2025-09-11T10:29:11.779Z" } +sdist = { url = "https://files.pythonhosted.org/packages/85/cb/f0eee1445161faf4c9af3ba7b848cc22a50a3d3e2515051ad8628c35ff80/opentelemetry_sdk-1.38.0.tar.gz", hash = "sha256:93df5d4d871ed09cb4272305be4d996236eedb232253e3ab864c8620f051cebe", size = 171942, upload-time = "2025-10-16T08:36:02.257Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/9f/62/9f4ad6a54126fb00f7ed4bb5034964c6e4f00fcd5a905e115bd22707e20d/opentelemetry_sdk-1.37.0-py3-none-any.whl", hash = "sha256:8f3c3c22063e52475c5dbced7209495c2c16723d016d39287dfc215d1771257c", size = 131941, upload-time = "2025-09-11T10:28:57.83Z" }, + { url = "https://files.pythonhosted.org/packages/2f/2e/e93777a95d7d9c40d270a371392b6d6f1ff170c2a3cb32d6176741b5b723/opentelemetry_sdk-1.38.0-py3-none-any.whl", hash = "sha256:1c66af6564ecc1553d72d811a01df063ff097cdc82ce188da9951f93b8d10f6b", size = 132349, upload-time = "2025-10-16T08:35:46.995Z" }, ] [[package]] @@ -3494,24 +3572,24 @@ wheels = [ [[package]] name = "opentelemetry-semantic-conventions" -version = "0.58b0" +version = "0.59b0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "opentelemetry-api" }, { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/aa/1b/90701d91e6300d9f2fb352153fb1721ed99ed1f6ea14fa992c756016e63a/opentelemetry_semantic_conventions-0.58b0.tar.gz", hash = "sha256:6bd46f51264279c433755767bb44ad00f1c9e2367e1b42af563372c5a6fa0c25", size = 129867, upload-time = "2025-09-11T10:29:12.597Z" } +sdist = { url = "https://files.pythonhosted.org/packages/40/bc/8b9ad3802cd8ac6583a4eb7de7e5d7db004e89cb7efe7008f9c8a537ee75/opentelemetry_semantic_conventions-0.59b0.tar.gz", hash = "sha256:7a6db3f30d70202d5bf9fa4b69bc866ca6a30437287de6c510fb594878aed6b0", size = 129861, upload-time = "2025-10-16T08:36:03.346Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/07/90/68152b7465f50285d3ce2481b3aec2f82822e3f52e5152eeeaf516bab841/opentelemetry_semantic_conventions-0.58b0-py3-none-any.whl", hash = "sha256:5564905ab1458b96684db1340232729fce3b5375a06e140e8904c78e4f815b28", size = 207954, upload-time = "2025-09-11T10:28:59.218Z" }, + { url = "https://files.pythonhosted.org/packages/24/7d/c88d7b15ba8fe5c6b8f93be50fc11795e9fc05386c44afaf6b76fe191f9b/opentelemetry_semantic_conventions-0.59b0-py3-none-any.whl", hash = "sha256:35d3b8833ef97d614136e253c1da9342b4c3c083bbaf29ce31d572a1c3825eed", size = 207954, upload-time = "2025-10-16T08:35:48.054Z" }, ] [[package]] name = "packaging" -version = "25.0" +version = "26.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/a1/d4/1fc4078c65507b51b96ca8f8c3ba19e6a61c8253c72794544580a7b6c24d/packaging-25.0.tar.gz", hash = "sha256:d443872c98d677bf60f6a1f2f8c1cb748e8fe762d2bf9d3148b5599295b0fc4f", size = 165727, upload-time = "2025-04-19T11:48:59.673Z" } +sdist = { url = "https://files.pythonhosted.org/packages/65/ee/299d360cdc32edc7d2cf530f3accf79c4fca01e96ffc950d8a52213bd8e4/packaging-26.0.tar.gz", hash = "sha256:00243ae351a257117b6a241061796684b084ed1c516a08c48a3f7e147a9d80b4", size = 143416, upload-time = "2026-01-21T20:50:39.064Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/20/12/38679034af332785aac8774540895e234f4d07f7545804097de4b666afd8/packaging-25.0-py3-none-any.whl", hash = "sha256:29572ef2b1f17581046b3a2227d5c611fb25ec70ca1ba8554b24b0e69331a484", size = 66469, upload-time = "2025-04-19T11:48:57.875Z" }, + { url = "https://files.pythonhosted.org/packages/b7/b9/c538f279a4e237a006a2c98387d081e9eb060d203d8ed34467cc0f0b9b53/packaging-26.0-py3-none-any.whl", hash = "sha256:b36f1fef9334a5588b4166f8bcd26a14e521f2b55e6b9de3aaa80d3ff7a37529", size = 74366, upload-time = "2026-01-21T20:50:37.788Z" }, ] [[package]] @@ -3525,11 +3603,11 @@ wheels = [ [[package]] name = "pathspec" -version = "0.12.1" +version = "1.0.4" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/ca/bc/f35b8446f4531a7cb215605d100cd88b7ac6f44ab3fc94870c120ab3adbf/pathspec-0.12.1.tar.gz", hash = "sha256:a482d51503a1ab33b1c67a6c3813a26953dbdc71c31dacaef9a838c4e29f5712", size = 51043, upload-time = "2023-12-10T22:30:45Z" } +sdist = { url = "https://files.pythonhosted.org/packages/fa/36/e27608899f9b8d4dff0617b2d9ab17ca5608956ca44461ac14ac48b44015/pathspec-1.0.4.tar.gz", hash = "sha256:0210e2ae8a21a9137c0d470578cb0e595af87edaa6ebf12ff176f14a02e0e645", size = 131200, upload-time = "2026-01-27T03:59:46.938Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/cc/20/ff623b09d963f88bfde16306a54e12ee5ea43e9b597108672ff3a408aad6/pathspec-0.12.1-py3-none-any.whl", hash = "sha256:a0d503e138a4c123b27490a4f7beda6a01c6f288df0e4a8b79c7eb0dc7b4cc08", size = 31191, upload-time = "2023-12-10T22:30:43.14Z" }, + { url = "https://files.pythonhosted.org/packages/ef/3c/2c197d226f9ea224a9ab8d197933f9da0ae0aac5b6e0f884e2b8d9c8e9f7/pathspec-1.0.4-py3-none-any.whl", hash = "sha256:fb6ae2fd4e7c921a165808a552060e722767cfa526f99ca5156ed2ce45a5c723", size = 55206, upload-time = "2026-01-27T03:59:45.137Z" }, ] [[package]] @@ -3543,11 +3621,11 @@ wheels = [ [[package]] name = "platformdirs" -version = "4.5.0" +version = "4.9.4" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/61/33/9611380c2bdb1225fdef633e2a9610622310fed35ab11dac9620972ee088/platformdirs-4.5.0.tar.gz", hash = "sha256:70ddccdd7c99fc5942e9fc25636a8b34d04c24b335100223152c2803e4063312", size = 21632, upload-time = "2025-10-08T17:44:48.791Z" } +sdist = { url = "https://files.pythonhosted.org/packages/19/56/8d4c30c8a1d07013911a8fdbd8f89440ef9f08d07a1b50ab8ca8be5a20f9/platformdirs-4.9.4.tar.gz", hash = "sha256:1ec356301b7dc906d83f371c8f487070e99d3ccf9e501686456394622a01a934", size = 28737, upload-time = "2026-03-05T18:34:13.271Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/73/cb/ac7874b3e5d58441674fb70742e6c374b28b0c7cb988d37d991cde47166c/platformdirs-4.5.0-py3-none-any.whl", hash = "sha256:e578a81bb873cbb89a41fcc904c7ef523cc18284b7e3b3ccf06aca1403b7ebd3", size = 18651, upload-time = "2025-10-08T17:44:47.223Z" }, + { url = "https://files.pythonhosted.org/packages/63/d7/97f7e3a6abb67d8080dd406fd4df842c2be0efaf712d1c899c32a075027c/platformdirs-4.9.4-py3-none-any.whl", hash = "sha256:68a9a4619a666ea6439f2ff250c12a853cd1cbd5158d258bd824a7df6be2f868", size = 21216, upload-time = "2026-03-05T18:34:12.172Z" }, ] [[package]] @@ -3675,29 +3753,29 @@ wheels = [ [[package]] name = "proto-plus" -version = "1.27.1" +version = "1.27.2" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "protobuf" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/3a/02/8832cde80e7380c600fbf55090b6ab7b62bd6825dbedde6d6657c15a1f8e/proto_plus-1.27.1.tar.gz", hash = "sha256:912a7460446625b792f6448bade9e55cd4e41e6ac10e27009ef71a7f317fa147", size = 56929, upload-time = "2026-02-02T17:34:49.035Z" } +sdist = { url = "https://files.pythonhosted.org/packages/81/0d/94dfe80193e79d55258345901acd2917523d56e8381bc4dee7fd38e3868a/proto_plus-1.27.2.tar.gz", hash = "sha256:b2adde53adadf75737c44d3dcb0104fde65250dfc83ad59168b4aa3e574b6a24", size = 57204, upload-time = "2026-03-26T22:18:57.174Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/5d/79/ac273cbbf744691821a9cca88957257f41afe271637794975ca090b9588b/proto_plus-1.27.1-py3-none-any.whl", hash = "sha256:e4643061f3a4d0de092d62aa4ad09fa4756b2cbb89d4627f3985018216f9fefc", size = 50480, upload-time = "2026-02-02T17:34:47.339Z" }, + { url = "https://files.pythonhosted.org/packages/84/f3/1fba73eeffafc998a25d59703b63f8be4fe8a5cb12eaff7386a0ba0f7125/proto_plus-1.27.2-py3-none-any.whl", hash = "sha256:6432f75893d3b9e70b9c412f1d2f03f65b11fb164b793d14ae2ca01821d22718", size = 50450, upload-time = "2026-03-26T22:13:42.927Z" }, ] [[package]] name = "protobuf" -version = "6.33.5" +version = "6.33.6" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/ba/25/7c72c307aafc96fa87062aa6291d9f7c94836e43214d43722e86037aac02/protobuf-6.33.5.tar.gz", hash = "sha256:6ddcac2a081f8b7b9642c09406bc6a4290128fce5f471cddd165960bb9119e5c", size = 444465, upload-time = "2026-01-29T21:51:33.494Z" } +sdist = { url = "https://files.pythonhosted.org/packages/66/70/e908e9c5e52ef7c3a6c7902c9dfbb34c7e29c25d2f81ade3856445fd5c94/protobuf-6.33.6.tar.gz", hash = "sha256:a6768d25248312c297558af96a9f9c929e8c4cee0659cb07e780731095f38135", size = 444531, upload-time = "2026-03-18T19:05:00.988Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/b1/79/af92d0a8369732b027e6d6084251dd8e782c685c72da161bd4a2e00fbabb/protobuf-6.33.5-cp310-abi3-win32.whl", hash = "sha256:d71b040839446bac0f4d162e758bea99c8251161dae9d0983a3b88dee345153b", size = 425769, upload-time = "2026-01-29T21:51:21.751Z" }, - { url = "https://files.pythonhosted.org/packages/55/75/bb9bc917d10e9ee13dee8607eb9ab963b7cf8be607c46e7862c748aa2af7/protobuf-6.33.5-cp310-abi3-win_amd64.whl", hash = "sha256:3093804752167bcab3998bec9f1048baae6e29505adaf1afd14a37bddede533c", size = 437118, upload-time = "2026-01-29T21:51:24.022Z" }, - { url = "https://files.pythonhosted.org/packages/a2/6b/e48dfc1191bc5b52950246275bf4089773e91cb5ba3592621723cdddca62/protobuf-6.33.5-cp39-abi3-macosx_10_9_universal2.whl", hash = "sha256:a5cb85982d95d906df1e2210e58f8e4f1e3cdc088e52c921a041f9c9a0386de5", size = 427766, upload-time = "2026-01-29T21:51:25.413Z" }, - { url = "https://files.pythonhosted.org/packages/4e/b1/c79468184310de09d75095ed1314b839eb2f72df71097db9d1404a1b2717/protobuf-6.33.5-cp39-abi3-manylinux2014_aarch64.whl", hash = "sha256:9b71e0281f36f179d00cbcb119cb19dec4d14a81393e5ea220f64b286173e190", size = 324638, upload-time = "2026-01-29T21:51:26.423Z" }, - { url = "https://files.pythonhosted.org/packages/c5/f5/65d838092fd01c44d16037953fd4c2cc851e783de9b8f02b27ec4ffd906f/protobuf-6.33.5-cp39-abi3-manylinux2014_s390x.whl", hash = "sha256:8afa18e1d6d20af15b417e728e9f60f3aa108ee76f23c3b2c07a2c3b546d3afd", size = 339411, upload-time = "2026-01-29T21:51:27.446Z" }, - { url = "https://files.pythonhosted.org/packages/9b/53/a9443aa3ca9ba8724fdfa02dd1887c1bcd8e89556b715cfbacca6b63dbec/protobuf-6.33.5-cp39-abi3-manylinux2014_x86_64.whl", hash = "sha256:cbf16ba3350fb7b889fca858fb215967792dc125b35c7976ca4818bee3521cf0", size = 323465, upload-time = "2026-01-29T21:51:28.925Z" }, - { url = "https://files.pythonhosted.org/packages/57/bf/2086963c69bdac3d7cff1cc7ff79b8ce5ea0bec6797a017e1be338a46248/protobuf-6.33.5-py3-none-any.whl", hash = "sha256:69915a973dd0f60f31a08b8318b73eab2bd6a392c79184b3612226b0a3f8ec02", size = 170687, upload-time = "2026-01-29T21:51:32.557Z" }, + { url = "https://files.pythonhosted.org/packages/fc/9f/2f509339e89cfa6f6a4c4ff50438db9ca488dec341f7e454adad60150b00/protobuf-6.33.6-cp310-abi3-win32.whl", hash = "sha256:7d29d9b65f8afef196f8334e80d6bc1d5d4adedb449971fefd3723824e6e77d3", size = 425739, upload-time = "2026-03-18T19:04:48.373Z" }, + { url = "https://files.pythonhosted.org/packages/76/5d/683efcd4798e0030c1bab27374fd13a89f7c2515fb1f3123efdfaa5eab57/protobuf-6.33.6-cp310-abi3-win_amd64.whl", hash = "sha256:0cd27b587afca21b7cfa59a74dcbd48a50f0a6400cfb59391340ad729d91d326", size = 437089, upload-time = "2026-03-18T19:04:50.381Z" }, + { url = "https://files.pythonhosted.org/packages/5c/01/a3c3ed5cd186f39e7880f8303cc51385a198a81469d53d0fdecf1f64d929/protobuf-6.33.6-cp39-abi3-macosx_10_9_universal2.whl", hash = "sha256:9720e6961b251bde64edfdab7d500725a2af5280f3f4c87e57c0208376aa8c3a", size = 427737, upload-time = "2026-03-18T19:04:51.866Z" }, + { url = "https://files.pythonhosted.org/packages/ee/90/b3c01fdec7d2f627b3a6884243ba328c1217ed2d978def5c12dc50d328a3/protobuf-6.33.6-cp39-abi3-manylinux2014_aarch64.whl", hash = "sha256:e2afbae9b8e1825e3529f88d514754e094278bb95eadc0e199751cdd9a2e82a2", size = 324610, upload-time = "2026-03-18T19:04:53.096Z" }, + { url = "https://files.pythonhosted.org/packages/9b/ca/25afc144934014700c52e05103c2421997482d561f3101ff352e1292fb81/protobuf-6.33.6-cp39-abi3-manylinux2014_s390x.whl", hash = "sha256:c96c37eec15086b79762ed265d59ab204dabc53056e3443e702d2681f4b39ce3", size = 339381, upload-time = "2026-03-18T19:04:54.616Z" }, + { url = "https://files.pythonhosted.org/packages/16/92/d1e32e3e0d894fe00b15ce28ad4944ab692713f2e7f0a99787405e43533a/protobuf-6.33.6-cp39-abi3-manylinux2014_x86_64.whl", hash = "sha256:e9db7e292e0ab79dd108d7f1a94fe31601ce1ee3f7b79e0692043423020b0593", size = 323436, upload-time = "2026-03-18T19:04:55.768Z" }, + { url = "https://files.pythonhosted.org/packages/c4/72/02445137af02769918a93807b2b7890047c32bfb9f90371cbc12688819eb/protobuf-6.33.6-py3-none-any.whl", hash = "sha256:77179e006c476e69bf8e8ce866640091ec42e1beb80b213c3900006ecfba6901", size = 170656, upload-time = "2026-03-18T19:04:59.826Z" }, ] [[package]] @@ -3782,11 +3860,11 @@ wheels = [ [[package]] name = "pyasn1" -version = "0.6.2" +version = "0.6.3" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/fe/b6/6e630dff89739fcd427e3f72b3d905ce0acb85a45d4ec3e2678718a3487f/pyasn1-0.6.2.tar.gz", hash = "sha256:9b59a2b25ba7e4f8197db7686c09fb33e658b98339fadb826e9512629017833b", size = 146586, upload-time = "2026-01-16T18:04:18.534Z" } +sdist = { url = "https://files.pythonhosted.org/packages/5c/5f/6583902b6f79b399c9c40674ac384fd9cd77805f9e6205075f828ef11fb2/pyasn1-0.6.3.tar.gz", hash = "sha256:697a8ecd6d98891189184ca1fa05d1bb00e2f84b5977c481452050549c8a72cf", size = 148685, upload-time = "2026-03-17T01:06:53.382Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/44/b5/a96872e5184f354da9c84ae119971a0a4c221fe9b27a4d94bd43f2596727/pyasn1-0.6.2-py3-none-any.whl", hash = "sha256:1eb26d860996a18e9b6ed05e7aae0e9fc21619fcee6af91cca9bad4fbea224bf", size = 83371, upload-time = "2026-01-16T18:04:17.174Z" }, + { url = "https://files.pythonhosted.org/packages/5d/a0/7d793dce3fa811fe047d6ae2431c672364b462850c6235ae306c0efd025f/pyasn1-0.6.3-py3-none-any.whl", hash = "sha256:a80184d120f0864a52a073acc6fc642847d0be408e7c7252f31390c0f4eadcde", size = 83997, upload-time = "2026-03-17T01:06:52.036Z" }, ] [[package]] @@ -3803,11 +3881,11 @@ wheels = [ [[package]] name = "pycparser" -version = "2.23" +version = "3.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/fe/cf/d2d3b9f5699fb1e4615c8e32ff220203e43b248e1dfcc6736ad9057731ca/pycparser-2.23.tar.gz", hash = "sha256:78816d4f24add8f10a06d6f05b4d424ad9e96cfebf68a4ddc99c65c0720d00c2", size = 173734, upload-time = "2025-09-09T13:23:47.91Z" } +sdist = { url = "https://files.pythonhosted.org/packages/1b/7d/92392ff7815c21062bea51aa7b87d45576f649f16458d78b7cf94b9ab2e6/pycparser-3.0.tar.gz", hash = "sha256:600f49d217304a5902ac3c37e1281c9fe94e4d0489de643a9504c5cdfdfc6b29", size = 103492, upload-time = "2026-01-21T14:26:51.89Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/a0/e3/59cd50310fc9b59512193629e1984c1f95e5c8ae6e5d8c69532ccc65a7fe/pycparser-2.23-py3-none-any.whl", hash = "sha256:e5c6e8d3fbad53479cab09ac03729e0a9faf2bee3db8208a550daf5af81a5934", size = 118140, upload-time = "2025-09-09T13:23:46.651Z" }, + { url = "https://files.pythonhosted.org/packages/0c/c3/44f3fbbfa403ea2a7c779186dc20772604442dde72947e7d01069cbe98e3/pycparser-3.0-py3-none-any.whl", hash = "sha256:b727414169a36b7d524c1c3e31839a521725078d7b2ff038656844266160a992", size = 48172, upload-time = "2026-01-21T14:26:50.693Z" }, ] [[package]] @@ -3945,16 +4023,16 @@ wheels = [ [[package]] name = "pydantic-settings" -version = "2.11.0" +version = "2.13.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "pydantic" }, { name = "python-dotenv" }, { name = "typing-inspection" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/20/c5/dbbc27b814c71676593d1c3f718e6cd7d4f00652cefa24b75f7aa3efb25e/pydantic_settings-2.11.0.tar.gz", hash = "sha256:d0e87a1c7d33593beb7194adb8470fc426e95ba02af83a0f23474a04c9a08180", size = 188394, upload-time = "2025-09-24T14:19:11.764Z" } +sdist = { url = "https://files.pythonhosted.org/packages/52/6d/fffca34caecc4a3f97bda81b2098da5e8ab7efc9a66e819074a11955d87e/pydantic_settings-2.13.1.tar.gz", hash = "sha256:b4c11847b15237fb0171e1462bf540e294affb9b86db4d9aa5c01730bdbe4025", size = 223826, upload-time = "2026-02-19T13:45:08.055Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/83/d6/887a1ff844e64aa823fb4905978d882a633cfe295c32eacad582b78a7d8b/pydantic_settings-2.11.0-py3-none-any.whl", hash = "sha256:fe2cea3413b9530d10f3a5875adffb17ada5c1e1bab0b2885546d7310415207c", size = 48608, upload-time = "2025-09-24T14:19:10.015Z" }, + { url = "https://files.pythonhosted.org/packages/00/4b/ccc026168948fec4f7555b9164c724cf4125eac006e176541483d2c959be/pydantic_settings-2.13.1-py3-none-any.whl", hash = "sha256:d56fd801823dbeae7f0975e1f8c8e25c258eb75d278ea7abb5d9cebb01b56237", size = 58929, upload-time = "2026-02-19T13:45:06.034Z" }, ] [[package]] @@ -3992,20 +4070,23 @@ wheels = [ [[package]] name = "pygments" -version = "2.19.2" +version = "2.20.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/b0/77/a5b8c569bf593b0140bde72ea885a803b82086995367bf2037de0159d924/pygments-2.19.2.tar.gz", hash = "sha256:636cb2477cec7f8952536970bc533bc43743542f70392ae026374600add5b887", size = 4968631, upload-time = "2025-06-21T13:39:12.283Z" } +sdist = { url = "https://files.pythonhosted.org/packages/c3/b2/bc9c9196916376152d655522fdcebac55e66de6603a76a02bca1b6414f6c/pygments-2.20.0.tar.gz", hash = "sha256:6757cd03768053ff99f3039c1a36d6c0aa0b263438fcab17520b30a303a82b5f", size = 4955991, upload-time = "2026-03-29T13:29:33.898Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/c7/21/705964c7812476f378728bdf590ca4b771ec72385c533964653c68e86bdc/pygments-2.19.2-py3-none-any.whl", hash = "sha256:86540386c03d588bb81d44bc3928634ff26449851e99741617ecb9037ee5ec0b", size = 1225217, upload-time = "2025-06-21T13:39:07.939Z" }, + { url = "https://files.pythonhosted.org/packages/f4/7e/a72dd26f3b0f4f2bf1dd8923c85f7ceb43172af56d63c7383eb62b332364/pygments-2.20.0-py3-none-any.whl", hash = "sha256:81a9e26dd42fd28a23a2d169d86d7ac03b46e2f8b59ed4698fb4785f946d0176", size = 1231151, upload-time = "2026-03-29T13:29:30.038Z" }, ] [[package]] name = "pyjwt" -version = "2.10.1" +version = "2.12.1" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/e7/46/bd74733ff231675599650d3e47f361794b22ef3e3770998dda30d3b63726/pyjwt-2.10.1.tar.gz", hash = "sha256:3cc5772eb20009233caf06e9d8a0577824723b44e6648ee0a2aedb6cf9381953", size = 87785, upload-time = "2024-11-28T03:43:29.933Z" } +dependencies = [ + { name = "typing-extensions", marker = "python_full_version < '3.11'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/c2/27/a3b6e5bf6ff856d2509292e95c8f57f0df7017cf5394921fc4e4ef40308a/pyjwt-2.12.1.tar.gz", hash = "sha256:c74a7a2adf861c04d002db713dd85f84beb242228e671280bf709d765b03672b", size = 102564, upload-time = "2026-03-13T19:27:37.25Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/61/ad/689f02752eeec26aed679477e80e632ef1b682313be70793d798c1d5fc8f/PyJWT-2.10.1-py3-none-any.whl", hash = "sha256:dcdd193e30abefd5debf142f9adfcdd2b58004e644f25406ffaebd50bd98dacb", size = 22997, upload-time = "2024-11-28T03:43:27.893Z" }, + { url = "https://files.pythonhosted.org/packages/e5/7a/8dd906bd22e79e47397a61742927f6747fe93242ef86645ee9092e610244/pyjwt-2.12.1-py3-none-any.whl", hash = "sha256:28ca37c070cad8ba8cd9790cd940535d40274d22f80ab87f3ac6a713e6e8454c", size = 29726, upload-time = "2026-03-13T19:27:35.677Z" }, ] [package.optional-dependencies] @@ -4015,15 +4096,15 @@ crypto = [ [[package]] name = "pyopenssl" -version = "25.3.0" +version = "26.0.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "cryptography" }, { name = "typing-extensions", marker = "python_full_version < '3.13'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/80/be/97b83a464498a79103036bc74d1038df4a7ef0e402cfaf4d5e113fb14759/pyopenssl-25.3.0.tar.gz", hash = "sha256:c981cb0a3fd84e8602d7afc209522773b94c1c2446a3c710a75b06fe1beae329", size = 184073, upload-time = "2025-09-17T00:32:21.037Z" } +sdist = { url = "https://files.pythonhosted.org/packages/8e/11/a62e1d33b373da2b2c2cd9eb508147871c80f12b1cacde3c5d314922afdd/pyopenssl-26.0.0.tar.gz", hash = "sha256:f293934e52936f2e3413b89c6ce36df66a0b34ae1ea3a053b8c5020ff2f513fc", size = 185534, upload-time = "2026-03-15T14:28:26.353Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/d1/81/ef2b1dfd1862567d573a4fdbc9f969067621764fbb74338496840a1d2977/pyopenssl-25.3.0-py3-none-any.whl", hash = "sha256:1fda6fc034d5e3d179d39e59c1895c9faeaf40a79de5fc4cbbfbe0d36f4a77b6", size = 57268, upload-time = "2025-09-17T00:32:19.474Z" }, + { url = "https://files.pythonhosted.org/packages/fb/7d/d4f7d908fa8415571771b30669251d57c3cf313b36a856e6d7548ae01619/pyopenssl-26.0.0-py3-none-any.whl", hash = "sha256:df94d28498848b98cc1c0ffb8ef1e71e40210d3b0a8064c9d29571ed2904bf81", size = 57969, upload-time = "2026-03-15T14:28:24.864Z" }, ] [[package]] @@ -4079,16 +4160,16 @@ wheels = [ [[package]] name = "pytest-cov" -version = "7.0.0" +version = "7.1.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "coverage", extra = ["toml"] }, { name = "pluggy" }, { name = "pytest" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/5e/f7/c933acc76f5208b3b00089573cf6a2bc26dc80a8aece8f52bb7d6b1855ca/pytest_cov-7.0.0.tar.gz", hash = "sha256:33c97eda2e049a0c5298e91f519302a1334c26ac65c1a483d6206fd458361af1", size = 54328, upload-time = "2025-09-09T10:57:02.113Z" } +sdist = { url = "https://files.pythonhosted.org/packages/b1/51/a849f96e117386044471c8ec2bd6cfebacda285da9525c9106aeb28da671/pytest_cov-7.1.0.tar.gz", hash = "sha256:30674f2b5f6351aa09702a9c8c364f6a01c27aae0c1366ae8016160d1efc56b2", size = 55592, upload-time = "2026-03-21T20:11:16.284Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/ee/49/1377b49de7d0c1ce41292161ea0f721913fa8722c19fb9c1e3aa0367eecb/pytest_cov-7.0.0-py3-none-any.whl", hash = "sha256:3b8e9558b16cc1479da72058bdecf8073661c7f57f7d3c5f22a1c23507f2d861", size = 22424, upload-time = "2025-09-09T10:57:00.695Z" }, + { url = "https://files.pythonhosted.org/packages/9d/7a/d968e294073affff457b041c2be9868a40c1c71f4a35fcc1e45e5493067b/pytest_cov-7.1.0-py3-none-any.whl", hash = "sha256:a0461110b7865f9a271aa1b51e516c9a95de9d696734a2f71e3e78f46e1d4678", size = 22876, upload-time = "2026-03-21T20:11:14.438Z" }, ] [[package]] @@ -4156,20 +4237,20 @@ wheels = [ [[package]] name = "python-dotenv" -version = "1.1.1" +version = "1.2.2" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/f6/b0/4bc07ccd3572a2f9df7e6782f52b0c6c90dcbb803ac4a167702d7d0dfe1e/python_dotenv-1.1.1.tar.gz", hash = "sha256:a8a6399716257f45be6a007360200409fce5cda2661e3dec71d23dc15f6189ab", size = 41978, upload-time = "2025-06-24T04:21:07.341Z" } +sdist = { url = "https://files.pythonhosted.org/packages/82/ed/0301aeeac3e5353ef3d94b6ec08bbcabd04a72018415dcb29e588514bba8/python_dotenv-1.2.2.tar.gz", hash = "sha256:2c371a91fbd7ba082c2c1dc1f8bf89ca22564a087c2c287cd9b662adde799cf3", size = 50135, upload-time = "2026-03-01T16:00:26.196Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/5f/ed/539768cf28c661b5b068d66d96a2f155c4971a5d55684a514c1a0e0dec2f/python_dotenv-1.1.1-py3-none-any.whl", hash = "sha256:31f23644fe2602f88ff55e1f5c79ba497e01224ee7737937930c448e4d0e24dc", size = 20556, upload-time = "2025-06-24T04:21:06.073Z" }, + { url = "https://files.pythonhosted.org/packages/0b/d7/1959b9648791274998a9c3526f6d0ec8fd2233e4d4acce81bbae76b44b2a/python_dotenv-1.2.2-py3-none-any.whl", hash = "sha256:1d8214789a24de455a8b8bd8ae6fe3c6b69a5e3d64aa8a8e5d68e694bbcb285a", size = 22101, upload-time = "2026-03-01T16:00:25.09Z" }, ] [[package]] name = "python-multipart" -version = "0.0.22" +version = "0.0.24" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/94/01/979e98d542a70714b0cb2b6728ed0b7c46792b695e3eaec3e20711271ca3/python_multipart-0.0.22.tar.gz", hash = "sha256:7340bef99a7e0032613f56dc36027b959fd3b30a787ed62d310e951f7c3a3a58", size = 37612, upload-time = "2026-01-25T10:15:56.219Z" } +sdist = { url = "https://files.pythonhosted.org/packages/8a/45/e23b5dc14ddb9918ae4a625379506b17b6f8fc56ca1d82db62462f59aea6/python_multipart-0.0.24.tar.gz", hash = "sha256:9574c97e1c026e00bc30340ef7c7d76739512ab4dfd428fec8c330fa6a5cc3c8", size = 37695, upload-time = "2026-04-05T20:49:13.829Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/1b/d0/397f9626e711ff749a95d96b7af99b9c566a9bb5129b8e4c10fc4d100304/python_multipart-0.0.22-py3-none-any.whl", hash = "sha256:2b2cd894c83d21bf49d702499531c7bafd057d730c201782048f7945d82de155", size = 24579, upload-time = "2026-01-25T10:15:54.811Z" }, + { url = "https://files.pythonhosted.org/packages/a3/73/89930efabd4da63cea44a3f438aeb753d600123570e6d6264e763617a9ce/python_multipart-0.0.24-py3-none-any.whl", hash = "sha256:9b110a98db707df01a53c194f0af075e736a770dc5058089650d70b4a182f950", size = 24420, upload-time = "2026-04-05T20:49:12.555Z" }, ] [[package]] @@ -4297,114 +4378,128 @@ wheels = [ [[package]] name = "regex" -version = "2025.9.18" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/49/d3/eaa0d28aba6ad1827ad1e716d9a93e1ba963ada61887498297d3da715133/regex-2025.9.18.tar.gz", hash = "sha256:c5ba23274c61c6fef447ba6a39333297d0c247f53059dba0bca415cac511edc4", size = 400917, upload-time = "2025-09-19T00:38:35.79Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/7e/d8/7e06171db8e55f917c5b8e89319cea2d86982e3fc46b677f40358223dece/regex-2025.9.18-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:12296202480c201c98a84aecc4d210592b2f55e200a1d193235c4db92b9f6788", size = 484829, upload-time = "2025-09-19T00:35:05.215Z" }, - { url = "https://files.pythonhosted.org/packages/8d/70/bf91bb39e5bedf75ce730ffbaa82ca585584d13335306d637458946b8b9f/regex-2025.9.18-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:220381f1464a581f2ea988f2220cf2a67927adcef107d47d6897ba5a2f6d51a4", size = 288993, upload-time = "2025-09-19T00:35:08.154Z" }, - { url = "https://files.pythonhosted.org/packages/fe/89/69f79b28365eda2c46e64c39d617d5f65a2aa451a4c94de7d9b34c2dc80f/regex-2025.9.18-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:87f681bfca84ebd265278b5daa1dcb57f4db315da3b5d044add7c30c10442e61", size = 286624, upload-time = "2025-09-19T00:35:09.717Z" }, - { url = "https://files.pythonhosted.org/packages/44/31/81e62955726c3a14fcc1049a80bc716765af6c055706869de5e880ddc783/regex-2025.9.18-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:34d674cbba70c9398074c8a1fcc1a79739d65d1105de2a3c695e2b05ea728251", size = 780473, upload-time = "2025-09-19T00:35:11.013Z" }, - { url = "https://files.pythonhosted.org/packages/fb/23/07072b7e191fbb6e213dc03b2f5b96f06d3c12d7deaded84679482926fc7/regex-2025.9.18-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:385c9b769655cb65ea40b6eea6ff763cbb6d69b3ffef0b0db8208e1833d4e746", size = 849290, upload-time = "2025-09-19T00:35:12.348Z" }, - { url = "https://files.pythonhosted.org/packages/b3/f0/aec7f6a01f2a112210424d77c6401b9015675fb887ced7e18926df4ae51e/regex-2025.9.18-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:8900b3208e022570ae34328712bef6696de0804c122933414014bae791437ab2", size = 897335, upload-time = "2025-09-19T00:35:14.058Z" }, - { url = "https://files.pythonhosted.org/packages/cc/90/2e5f9da89d260de7d0417ead91a1bc897f19f0af05f4f9323313b76c47f2/regex-2025.9.18-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c204e93bf32cd7a77151d44b05eb36f469d0898e3fba141c026a26b79d9914a0", size = 789946, upload-time = "2025-09-19T00:35:15.403Z" }, - { url = "https://files.pythonhosted.org/packages/2b/d5/1c712c7362f2563d389be66bae131c8bab121a3fabfa04b0b5bfc9e73c51/regex-2025.9.18-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:3acc471d1dd7e5ff82e6cacb3b286750decd949ecd4ae258696d04f019817ef8", size = 780787, upload-time = "2025-09-19T00:35:17.061Z" }, - { url = "https://files.pythonhosted.org/packages/4f/92/c54cdb4aa41009632e69817a5aa452673507f07e341076735a2f6c46a37c/regex-2025.9.18-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:6479d5555122433728760e5f29edb4c2b79655a8deb681a141beb5c8a025baea", size = 773632, upload-time = "2025-09-19T00:35:18.57Z" }, - { url = "https://files.pythonhosted.org/packages/db/99/75c996dc6a2231a8652d7ad0bfbeaf8a8c77612d335580f520f3ec40e30b/regex-2025.9.18-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:431bd2a8726b000eb6f12429c9b438a24062a535d06783a93d2bcbad3698f8a8", size = 844104, upload-time = "2025-09-19T00:35:20.259Z" }, - { url = "https://files.pythonhosted.org/packages/1c/f7/25aba34cc130cb6844047dbfe9716c9b8f9629fee8b8bec331aa9241b97b/regex-2025.9.18-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:0cc3521060162d02bd36927e20690129200e5ac9d2c6d32b70368870b122db25", size = 834794, upload-time = "2025-09-19T00:35:22.002Z" }, - { url = "https://files.pythonhosted.org/packages/51/eb/64e671beafa0ae29712268421597596d781704973551312b2425831d4037/regex-2025.9.18-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:a021217b01be2d51632ce056d7a837d3fa37c543ede36e39d14063176a26ae29", size = 778535, upload-time = "2025-09-19T00:35:23.298Z" }, - { url = "https://files.pythonhosted.org/packages/26/33/c0ebc0b07bd0bf88f716cca240546b26235a07710ea58e271cfe390ae273/regex-2025.9.18-cp310-cp310-win32.whl", hash = "sha256:4a12a06c268a629cb67cc1d009b7bb0be43e289d00d5111f86a2efd3b1949444", size = 264115, upload-time = "2025-09-19T00:35:25.206Z" }, - { url = "https://files.pythonhosted.org/packages/59/39/aeb11a4ae68faaec2498512cadae09f2d8a91f1f65730fe62b9bffeea150/regex-2025.9.18-cp310-cp310-win_amd64.whl", hash = "sha256:47acd811589301298c49db2c56bde4f9308d6396da92daf99cba781fa74aa450", size = 276143, upload-time = "2025-09-19T00:35:26.785Z" }, - { url = "https://files.pythonhosted.org/packages/29/04/37f2d3fc334a1031fc2767c9d89cec13c2e72207c7e7f6feae8a47f4e149/regex-2025.9.18-cp310-cp310-win_arm64.whl", hash = "sha256:16bd2944e77522275e5ee36f867e19995bcaa533dcb516753a26726ac7285442", size = 268473, upload-time = "2025-09-19T00:35:28.39Z" }, - { url = "https://files.pythonhosted.org/packages/58/61/80eda662fc4eb32bfedc331f42390974c9e89c7eac1b79cd9eea4d7c458c/regex-2025.9.18-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:51076980cd08cd13c88eb7365427ae27f0d94e7cebe9ceb2bb9ffdae8fc4d82a", size = 484832, upload-time = "2025-09-19T00:35:30.011Z" }, - { url = "https://files.pythonhosted.org/packages/a6/d9/33833d9abddf3f07ad48504ddb53fe3b22f353214bbb878a72eee1e3ddbf/regex-2025.9.18-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:828446870bd7dee4e0cbeed767f07961aa07f0ea3129f38b3ccecebc9742e0b8", size = 288994, upload-time = "2025-09-19T00:35:31.733Z" }, - { url = "https://files.pythonhosted.org/packages/2a/b3/526ee96b0d70ea81980cbc20c3496fa582f775a52e001e2743cc33b2fa75/regex-2025.9.18-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:c28821d5637866479ec4cc23b8c990f5bc6dd24e5e4384ba4a11d38a526e1414", size = 286619, upload-time = "2025-09-19T00:35:33.221Z" }, - { url = "https://files.pythonhosted.org/packages/65/4f/c2c096b02a351b33442aed5895cdd8bf87d372498d2100927c5a053d7ba3/regex-2025.9.18-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:726177ade8e481db669e76bf99de0b278783be8acd11cef71165327abd1f170a", size = 792454, upload-time = "2025-09-19T00:35:35.361Z" }, - { url = "https://files.pythonhosted.org/packages/24/15/b562c9d6e47c403c4b5deb744f8b4bf6e40684cf866c7b077960a925bdff/regex-2025.9.18-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:f5cca697da89b9f8ea44115ce3130f6c54c22f541943ac8e9900461edc2b8bd4", size = 858723, upload-time = "2025-09-19T00:35:36.949Z" }, - { url = "https://files.pythonhosted.org/packages/f2/01/dba305409849e85b8a1a681eac4c03ed327d8de37895ddf9dc137f59c140/regex-2025.9.18-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:dfbde38f38004703c35666a1e1c088b778e35d55348da2b7b278914491698d6a", size = 905899, upload-time = "2025-09-19T00:35:38.723Z" }, - { url = "https://files.pythonhosted.org/packages/fe/d0/c51d1e6a80eab11ef96a4cbad17fc0310cf68994fb01a7283276b7e5bbd6/regex-2025.9.18-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f2f422214a03fab16bfa495cfec72bee4aaa5731843b771860a471282f1bf74f", size = 798981, upload-time = "2025-09-19T00:35:40.416Z" }, - { url = "https://files.pythonhosted.org/packages/c4/5e/72db90970887bbe02296612bd61b0fa31e6d88aa24f6a4853db3e96c575e/regex-2025.9.18-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:a295916890f4df0902e4286bc7223ee7f9e925daa6dcdec4192364255b70561a", size = 781900, upload-time = "2025-09-19T00:35:42.077Z" }, - { url = "https://files.pythonhosted.org/packages/50/ff/596be45eea8e9bc31677fde243fa2904d00aad1b32c31bce26c3dbba0b9e/regex-2025.9.18-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:5db95ff632dbabc8c38c4e82bf545ab78d902e81160e6e455598014f0abe66b9", size = 852952, upload-time = "2025-09-19T00:35:43.751Z" }, - { url = "https://files.pythonhosted.org/packages/e5/1b/2dfa348fa551e900ed3f5f63f74185b6a08e8a76bc62bc9c106f4f92668b/regex-2025.9.18-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:fb967eb441b0f15ae610b7069bdb760b929f267efbf522e814bbbfffdf125ce2", size = 844355, upload-time = "2025-09-19T00:35:45.309Z" }, - { url = "https://files.pythonhosted.org/packages/f4/bf/aefb1def27fe33b8cbbb19c75c13aefccfbef1c6686f8e7f7095705969c7/regex-2025.9.18-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:f04d2f20da4053d96c08f7fde6e1419b7ec9dbcee89c96e3d731fca77f411b95", size = 787254, upload-time = "2025-09-19T00:35:46.904Z" }, - { url = "https://files.pythonhosted.org/packages/e3/4e/8ef042e7cf0dbbb401e784e896acfc1b367b95dfbfc9ada94c2ed55a081f/regex-2025.9.18-cp311-cp311-win32.whl", hash = "sha256:895197241fccf18c0cea7550c80e75f185b8bd55b6924fcae269a1a92c614a07", size = 264129, upload-time = "2025-09-19T00:35:48.597Z" }, - { url = "https://files.pythonhosted.org/packages/b4/7d/c4fcabf80dcdd6821c0578ad9b451f8640b9110fb3dcb74793dd077069ff/regex-2025.9.18-cp311-cp311-win_amd64.whl", hash = "sha256:7e2b414deae99166e22c005e154a5513ac31493db178d8aec92b3269c9cce8c9", size = 276160, upload-time = "2025-09-19T00:36:00.45Z" }, - { url = "https://files.pythonhosted.org/packages/64/f8/0e13c8ae4d6df9d128afaba138342d532283d53a4c1e7a8c93d6756c8f4a/regex-2025.9.18-cp311-cp311-win_arm64.whl", hash = "sha256:fb137ec7c5c54f34a25ff9b31f6b7b0c2757be80176435bf367111e3f71d72df", size = 268471, upload-time = "2025-09-19T00:36:02.149Z" }, - { url = "https://files.pythonhosted.org/packages/b0/99/05859d87a66ae7098222d65748f11ef7f2dff51bfd7482a4e2256c90d72b/regex-2025.9.18-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:436e1b31d7efd4dcd52091d076482031c611dde58bf9c46ca6d0a26e33053a7e", size = 486335, upload-time = "2025-09-19T00:36:03.661Z" }, - { url = "https://files.pythonhosted.org/packages/97/7e/d43d4e8b978890932cf7b0957fce58c5b08c66f32698f695b0c2c24a48bf/regex-2025.9.18-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:c190af81e5576b9c5fdc708f781a52ff20f8b96386c6e2e0557a78402b029f4a", size = 289720, upload-time = "2025-09-19T00:36:05.471Z" }, - { url = "https://files.pythonhosted.org/packages/bb/3b/ff80886089eb5dcf7e0d2040d9aaed539e25a94300403814bb24cc775058/regex-2025.9.18-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:e4121f1ce2b2b5eec4b397cc1b277686e577e658d8f5870b7eb2d726bd2300ab", size = 287257, upload-time = "2025-09-19T00:36:07.072Z" }, - { url = "https://files.pythonhosted.org/packages/ee/66/243edf49dd8720cba8d5245dd4d6adcb03a1defab7238598c0c97cf549b8/regex-2025.9.18-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:300e25dbbf8299d87205e821a201057f2ef9aa3deb29caa01cd2cac669e508d5", size = 797463, upload-time = "2025-09-19T00:36:08.399Z" }, - { url = "https://files.pythonhosted.org/packages/df/71/c9d25a1142c70432e68bb03211d4a82299cd1c1fbc41db9409a394374ef5/regex-2025.9.18-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:7b47fcf9f5316c0bdaf449e879407e1b9937a23c3b369135ca94ebc8d74b1742", size = 862670, upload-time = "2025-09-19T00:36:10.101Z" }, - { url = "https://files.pythonhosted.org/packages/f8/8f/329b1efc3a64375a294e3a92d43372bf1a351aa418e83c21f2f01cf6ec41/regex-2025.9.18-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:57a161bd3acaa4b513220b49949b07e252165e6b6dc910ee7617a37ff4f5b425", size = 910881, upload-time = "2025-09-19T00:36:12.223Z" }, - { url = "https://files.pythonhosted.org/packages/35/9e/a91b50332a9750519320ed30ec378b74c996f6befe282cfa6bb6cea7e9fd/regex-2025.9.18-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4f130c3a7845ba42de42f380fff3c8aebe89a810747d91bcf56d40a069f15352", size = 802011, upload-time = "2025-09-19T00:36:13.901Z" }, - { url = "https://files.pythonhosted.org/packages/a4/1d/6be3b8d7856b6e0d7ee7f942f437d0a76e0d5622983abbb6d21e21ab9a17/regex-2025.9.18-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:5f96fa342b6f54dcba928dd452e8d8cb9f0d63e711d1721cd765bb9f73bb048d", size = 786668, upload-time = "2025-09-19T00:36:15.391Z" }, - { url = "https://files.pythonhosted.org/packages/cb/ce/4a60e53df58bd157c5156a1736d3636f9910bdcc271d067b32b7fcd0c3a8/regex-2025.9.18-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:0f0d676522d68c207828dcd01fb6f214f63f238c283d9f01d85fc664c7c85b56", size = 856578, upload-time = "2025-09-19T00:36:16.845Z" }, - { url = "https://files.pythonhosted.org/packages/86/e8/162c91bfe7217253afccde112868afb239f94703de6580fb235058d506a6/regex-2025.9.18-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:40532bff8a1a0621e7903ae57fce88feb2e8a9a9116d341701302c9302aef06e", size = 849017, upload-time = "2025-09-19T00:36:18.597Z" }, - { url = "https://files.pythonhosted.org/packages/35/34/42b165bc45289646ea0959a1bc7531733e90b47c56a72067adfe6b3251f6/regex-2025.9.18-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:039f11b618ce8d71a1c364fdee37da1012f5a3e79b1b2819a9f389cd82fd6282", size = 788150, upload-time = "2025-09-19T00:36:20.464Z" }, - { url = "https://files.pythonhosted.org/packages/79/5d/cdd13b1f3c53afa7191593a7ad2ee24092a5a46417725ffff7f64be8342d/regex-2025.9.18-cp312-cp312-win32.whl", hash = "sha256:e1dd06f981eb226edf87c55d523131ade7285137fbde837c34dc9d1bf309f459", size = 264536, upload-time = "2025-09-19T00:36:21.922Z" }, - { url = "https://files.pythonhosted.org/packages/e0/f5/4a7770c9a522e7d2dc1fa3ffc83ab2ab33b0b22b447e62cffef186805302/regex-2025.9.18-cp312-cp312-win_amd64.whl", hash = "sha256:3d86b5247bf25fa3715e385aa9ff272c307e0636ce0c9595f64568b41f0a9c77", size = 275501, upload-time = "2025-09-19T00:36:23.4Z" }, - { url = "https://files.pythonhosted.org/packages/df/05/9ce3e110e70d225ecbed455b966003a3afda5e58e8aec2964042363a18f4/regex-2025.9.18-cp312-cp312-win_arm64.whl", hash = "sha256:032720248cbeeae6444c269b78cb15664458b7bb9ed02401d3da59fe4d68c3a5", size = 268601, upload-time = "2025-09-19T00:36:25.092Z" }, - { url = "https://files.pythonhosted.org/packages/d2/c7/5c48206a60ce33711cf7dcaeaed10dd737733a3569dc7e1dce324dd48f30/regex-2025.9.18-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:2a40f929cd907c7e8ac7566ac76225a77701a6221bca937bdb70d56cb61f57b2", size = 485955, upload-time = "2025-09-19T00:36:26.822Z" }, - { url = "https://files.pythonhosted.org/packages/e9/be/74fc6bb19a3c491ec1ace943e622b5a8539068771e8705e469b2da2306a7/regex-2025.9.18-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:c90471671c2cdf914e58b6af62420ea9ecd06d1554d7474d50133ff26ae88feb", size = 289583, upload-time = "2025-09-19T00:36:28.577Z" }, - { url = "https://files.pythonhosted.org/packages/25/c4/9ceaa433cb5dc515765560f22a19578b95b92ff12526e5a259321c4fc1a0/regex-2025.9.18-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:1a351aff9e07a2dabb5022ead6380cff17a4f10e4feb15f9100ee56c4d6d06af", size = 287000, upload-time = "2025-09-19T00:36:30.161Z" }, - { url = "https://files.pythonhosted.org/packages/7d/e6/68bc9393cb4dc68018456568c048ac035854b042bc7c33cb9b99b0680afa/regex-2025.9.18-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:bc4b8e9d16e20ddfe16430c23468a8707ccad3365b06d4536142e71823f3ca29", size = 797535, upload-time = "2025-09-19T00:36:31.876Z" }, - { url = "https://files.pythonhosted.org/packages/6a/1c/ebae9032d34b78ecfe9bd4b5e6575b55351dc8513485bb92326613732b8c/regex-2025.9.18-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:4b8cdbddf2db1c5e80338ba2daa3cfa3dec73a46fff2a7dda087c8efbf12d62f", size = 862603, upload-time = "2025-09-19T00:36:33.344Z" }, - { url = "https://files.pythonhosted.org/packages/3b/74/12332c54b3882557a4bcd2b99f8be581f5c6a43cf1660a85b460dd8ff468/regex-2025.9.18-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:a276937d9d75085b2c91fb48244349c6954f05ee97bba0963ce24a9d915b8b68", size = 910829, upload-time = "2025-09-19T00:36:34.826Z" }, - { url = "https://files.pythonhosted.org/packages/86/70/ba42d5ed606ee275f2465bfc0e2208755b06cdabd0f4c7c4b614d51b57ab/regex-2025.9.18-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:92a8e375ccdc1256401c90e9dc02b8642894443d549ff5e25e36d7cf8a80c783", size = 802059, upload-time = "2025-09-19T00:36:36.664Z" }, - { url = "https://files.pythonhosted.org/packages/da/c5/fcb017e56396a7f2f8357412638d7e2963440b131a3ca549be25774b3641/regex-2025.9.18-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:0dc6893b1f502d73037cf807a321cdc9be29ef3d6219f7970f842475873712ac", size = 786781, upload-time = "2025-09-19T00:36:38.168Z" }, - { url = "https://files.pythonhosted.org/packages/c6/ee/21c4278b973f630adfb3bcb23d09d83625f3ab1ca6e40ebdffe69901c7a1/regex-2025.9.18-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:a61e85bfc63d232ac14b015af1261f826260c8deb19401c0597dbb87a864361e", size = 856578, upload-time = "2025-09-19T00:36:40.129Z" }, - { url = "https://files.pythonhosted.org/packages/87/0b/de51550dc7274324435c8f1539373ac63019b0525ad720132866fff4a16a/regex-2025.9.18-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:1ef86a9ebc53f379d921fb9a7e42b92059ad3ee800fcd9e0fe6181090e9f6c23", size = 849119, upload-time = "2025-09-19T00:36:41.651Z" }, - { url = "https://files.pythonhosted.org/packages/60/52/383d3044fc5154d9ffe4321696ee5b2ee4833a28c29b137c22c33f41885b/regex-2025.9.18-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:d3bc882119764ba3a119fbf2bd4f1b47bc56c1da5d42df4ed54ae1e8e66fdf8f", size = 788219, upload-time = "2025-09-19T00:36:43.575Z" }, - { url = "https://files.pythonhosted.org/packages/20/bd/2614fc302671b7359972ea212f0e3a92df4414aaeacab054a8ce80a86073/regex-2025.9.18-cp313-cp313-win32.whl", hash = "sha256:3810a65675845c3bdfa58c3c7d88624356dd6ee2fc186628295e0969005f928d", size = 264517, upload-time = "2025-09-19T00:36:45.503Z" }, - { url = "https://files.pythonhosted.org/packages/07/0f/ab5c1581e6563a7bffdc1974fb2d25f05689b88e2d416525271f232b1946/regex-2025.9.18-cp313-cp313-win_amd64.whl", hash = "sha256:16eaf74b3c4180ede88f620f299e474913ab6924d5c4b89b3833bc2345d83b3d", size = 275481, upload-time = "2025-09-19T00:36:46.965Z" }, - { url = "https://files.pythonhosted.org/packages/49/22/ee47672bc7958f8c5667a587c2600a4fba8b6bab6e86bd6d3e2b5f7cac42/regex-2025.9.18-cp313-cp313-win_arm64.whl", hash = "sha256:4dc98ba7dd66bd1261927a9f49bd5ee2bcb3660f7962f1ec02617280fc00f5eb", size = 268598, upload-time = "2025-09-19T00:36:48.314Z" }, - { url = "https://files.pythonhosted.org/packages/e8/83/6887e16a187c6226cb85d8301e47d3b73ecc4505a3a13d8da2096b44fd76/regex-2025.9.18-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:fe5d50572bc885a0a799410a717c42b1a6b50e2f45872e2b40f4f288f9bce8a2", size = 489765, upload-time = "2025-09-19T00:36:49.996Z" }, - { url = "https://files.pythonhosted.org/packages/51/c5/e2f7325301ea2916ff301c8d963ba66b1b2c1b06694191df80a9c4fea5d0/regex-2025.9.18-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:1b9d9a2d6cda6621551ca8cf7a06f103adf72831153f3c0d982386110870c4d3", size = 291228, upload-time = "2025-09-19T00:36:51.654Z" }, - { url = "https://files.pythonhosted.org/packages/91/60/7d229d2bc6961289e864a3a3cfebf7d0d250e2e65323a8952cbb7e22d824/regex-2025.9.18-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:13202e4c4ac0ef9a317fff817674b293c8f7e8c68d3190377d8d8b749f566e12", size = 289270, upload-time = "2025-09-19T00:36:53.118Z" }, - { url = "https://files.pythonhosted.org/packages/3c/d7/b4f06868ee2958ff6430df89857fbf3d43014bbf35538b6ec96c2704e15d/regex-2025.9.18-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:874ff523b0fecffb090f80ae53dc93538f8db954c8bb5505f05b7787ab3402a0", size = 806326, upload-time = "2025-09-19T00:36:54.631Z" }, - { url = "https://files.pythonhosted.org/packages/d6/e4/bca99034a8f1b9b62ccf337402a8e5b959dd5ba0e5e5b2ead70273df3277/regex-2025.9.18-cp313-cp313t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:d13ab0490128f2bb45d596f754148cd750411afc97e813e4b3a61cf278a23bb6", size = 871556, upload-time = "2025-09-19T00:36:56.208Z" }, - { url = "https://files.pythonhosted.org/packages/6d/df/e06ffaf078a162f6dd6b101a5ea9b44696dca860a48136b3ae4a9caf25e2/regex-2025.9.18-cp313-cp313t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:05440bc172bc4b4b37fb9667e796597419404dbba62e171e1f826d7d2a9ebcef", size = 913817, upload-time = "2025-09-19T00:36:57.807Z" }, - { url = "https://files.pythonhosted.org/packages/9e/05/25b05480b63292fd8e84800b1648e160ca778127b8d2367a0a258fa2e225/regex-2025.9.18-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5514b8e4031fdfaa3d27e92c75719cbe7f379e28cacd939807289bce76d0e35a", size = 811055, upload-time = "2025-09-19T00:36:59.762Z" }, - { url = "https://files.pythonhosted.org/packages/70/97/7bc7574655eb651ba3a916ed4b1be6798ae97af30104f655d8efd0cab24b/regex-2025.9.18-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:65d3c38c39efce73e0d9dc019697b39903ba25b1ad45ebbd730d2cf32741f40d", size = 794534, upload-time = "2025-09-19T00:37:01.405Z" }, - { url = "https://files.pythonhosted.org/packages/b4/c2/d5da49166a52dda879855ecdba0117f073583db2b39bb47ce9a3378a8e9e/regex-2025.9.18-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:ae77e447ebc144d5a26d50055c6ddba1d6ad4a865a560ec7200b8b06bc529368", size = 866684, upload-time = "2025-09-19T00:37:03.441Z" }, - { url = "https://files.pythonhosted.org/packages/bd/2d/0a5c4e6ec417de56b89ff4418ecc72f7e3feca806824c75ad0bbdae0516b/regex-2025.9.18-cp313-cp313t-musllinux_1_2_s390x.whl", hash = "sha256:e3ef8cf53dc8df49d7e28a356cf824e3623764e9833348b655cfed4524ab8a90", size = 853282, upload-time = "2025-09-19T00:37:04.985Z" }, - { url = "https://files.pythonhosted.org/packages/f4/8e/d656af63e31a86572ec829665d6fa06eae7e144771e0330650a8bb865635/regex-2025.9.18-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:9feb29817df349c976da9a0debf775c5c33fc1c8ad7b9f025825da99374770b7", size = 797830, upload-time = "2025-09-19T00:37:06.697Z" }, - { url = "https://files.pythonhosted.org/packages/db/ce/06edc89df8f7b83ffd321b6071be4c54dc7332c0f77860edc40ce57d757b/regex-2025.9.18-cp313-cp313t-win32.whl", hash = "sha256:168be0d2f9b9d13076940b1ed774f98595b4e3c7fc54584bba81b3cc4181742e", size = 267281, upload-time = "2025-09-19T00:37:08.568Z" }, - { url = "https://files.pythonhosted.org/packages/83/9a/2b5d9c8b307a451fd17068719d971d3634ca29864b89ed5c18e499446d4a/regex-2025.9.18-cp313-cp313t-win_amd64.whl", hash = "sha256:d59ecf3bb549e491c8104fea7313f3563c7b048e01287db0a90485734a70a730", size = 278724, upload-time = "2025-09-19T00:37:10.023Z" }, - { url = "https://files.pythonhosted.org/packages/3d/70/177d31e8089a278a764f8ec9a3faac8d14a312d622a47385d4b43905806f/regex-2025.9.18-cp313-cp313t-win_arm64.whl", hash = "sha256:dbef80defe9fb21310948a2595420b36c6d641d9bea4c991175829b2cc4bc06a", size = 269771, upload-time = "2025-09-19T00:37:13.041Z" }, - { url = "https://files.pythonhosted.org/packages/44/b7/3b4663aa3b4af16819f2ab6a78c4111c7e9b066725d8107753c2257448a5/regex-2025.9.18-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:c6db75b51acf277997f3adcd0ad89045d856190d13359f15ab5dda21581d9129", size = 486130, upload-time = "2025-09-19T00:37:14.527Z" }, - { url = "https://files.pythonhosted.org/packages/80/5b/4533f5d7ac9c6a02a4725fe8883de2aebc713e67e842c04cf02626afb747/regex-2025.9.18-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:8f9698b6f6895d6db810e0bda5364f9ceb9e5b11328700a90cae573574f61eea", size = 289539, upload-time = "2025-09-19T00:37:16.356Z" }, - { url = "https://files.pythonhosted.org/packages/b8/8d/5ab6797c2750985f79e9995fad3254caa4520846580f266ae3b56d1cae58/regex-2025.9.18-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:29cd86aa7cb13a37d0f0d7c21d8d949fe402ffa0ea697e635afedd97ab4b69f1", size = 287233, upload-time = "2025-09-19T00:37:18.025Z" }, - { url = "https://files.pythonhosted.org/packages/cb/1e/95afcb02ba8d3a64e6ffeb801718ce73471ad6440c55d993f65a4a5e7a92/regex-2025.9.18-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:7c9f285a071ee55cd9583ba24dde006e53e17780bb309baa8e4289cd472bcc47", size = 797876, upload-time = "2025-09-19T00:37:19.609Z" }, - { url = "https://files.pythonhosted.org/packages/c8/fb/720b1f49cec1f3b5a9fea5b34cd22b88b5ebccc8c1b5de9cc6f65eed165a/regex-2025.9.18-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:5adf266f730431e3be9021d3e5b8d5ee65e563fec2883ea8093944d21863b379", size = 863385, upload-time = "2025-09-19T00:37:21.65Z" }, - { url = "https://files.pythonhosted.org/packages/a9/ca/e0d07ecf701e1616f015a720dc13b84c582024cbfbb3fc5394ae204adbd7/regex-2025.9.18-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:1137cabc0f38807de79e28d3f6e3e3f2cc8cfb26bead754d02e6d1de5f679203", size = 910220, upload-time = "2025-09-19T00:37:23.723Z" }, - { url = "https://files.pythonhosted.org/packages/b6/45/bba86413b910b708eca705a5af62163d5d396d5f647ed9485580c7025209/regex-2025.9.18-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:7cc9e5525cada99699ca9223cce2d52e88c52a3d2a0e842bd53de5497c604164", size = 801827, upload-time = "2025-09-19T00:37:25.684Z" }, - { url = "https://files.pythonhosted.org/packages/b8/a6/740fbd9fcac31a1305a8eed30b44bf0f7f1e042342be0a4722c0365ecfca/regex-2025.9.18-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:bbb9246568f72dce29bcd433517c2be22c7791784b223a810225af3b50d1aafb", size = 786843, upload-time = "2025-09-19T00:37:27.62Z" }, - { url = "https://files.pythonhosted.org/packages/80/a7/0579e8560682645906da640c9055506465d809cb0f5415d9976f417209a6/regex-2025.9.18-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:6a52219a93dd3d92c675383efff6ae18c982e2d7651c792b1e6d121055808743", size = 857430, upload-time = "2025-09-19T00:37:29.362Z" }, - { url = "https://files.pythonhosted.org/packages/8d/9b/4dc96b6c17b38900cc9fee254fc9271d0dde044e82c78c0811b58754fde5/regex-2025.9.18-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:ae9b3840c5bd456780e3ddf2f737ab55a79b790f6409182012718a35c6d43282", size = 848612, upload-time = "2025-09-19T00:37:31.42Z" }, - { url = "https://files.pythonhosted.org/packages/b3/6a/6f659f99bebb1775e5ac81a3fb837b85897c1a4ef5acffd0ff8ffe7e67fb/regex-2025.9.18-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:d488c236ac497c46a5ac2005a952c1a0e22a07be9f10c3e735bc7d1209a34773", size = 787967, upload-time = "2025-09-19T00:37:34.019Z" }, - { url = "https://files.pythonhosted.org/packages/61/35/9e35665f097c07cf384a6b90a1ac11b0b1693084a0b7a675b06f760496c6/regex-2025.9.18-cp314-cp314-win32.whl", hash = "sha256:0c3506682ea19beefe627a38872d8da65cc01ffa25ed3f2e422dffa1474f0788", size = 269847, upload-time = "2025-09-19T00:37:35.759Z" }, - { url = "https://files.pythonhosted.org/packages/af/64/27594dbe0f1590b82de2821ebfe9a359b44dcb9b65524876cd12fabc447b/regex-2025.9.18-cp314-cp314-win_amd64.whl", hash = "sha256:57929d0f92bebb2d1a83af372cd0ffba2263f13f376e19b1e4fa32aec4efddc3", size = 278755, upload-time = "2025-09-19T00:37:37.367Z" }, - { url = "https://files.pythonhosted.org/packages/30/a3/0cd8d0d342886bd7d7f252d701b20ae1a3c72dc7f34ef4b2d17790280a09/regex-2025.9.18-cp314-cp314-win_arm64.whl", hash = "sha256:6a4b44df31d34fa51aa5c995d3aa3c999cec4d69b9bd414a8be51984d859f06d", size = 271873, upload-time = "2025-09-19T00:37:39.125Z" }, - { url = "https://files.pythonhosted.org/packages/99/cb/8a1ab05ecf404e18b54348e293d9b7a60ec2bd7aa59e637020c5eea852e8/regex-2025.9.18-cp314-cp314t-macosx_10_13_universal2.whl", hash = "sha256:b176326bcd544b5e9b17d6943f807697c0cb7351f6cfb45bf5637c95ff7e6306", size = 489773, upload-time = "2025-09-19T00:37:40.968Z" }, - { url = "https://files.pythonhosted.org/packages/93/3b/6543c9b7f7e734d2404fa2863d0d710c907bef99d4598760ed4563d634c3/regex-2025.9.18-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:0ffd9e230b826b15b369391bec167baed57c7ce39efc35835448618860995946", size = 291221, upload-time = "2025-09-19T00:37:42.901Z" }, - { url = "https://files.pythonhosted.org/packages/cd/91/e9fdee6ad6bf708d98c5d17fded423dcb0661795a49cba1b4ffb8358377a/regex-2025.9.18-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:ec46332c41add73f2b57e2f5b642f991f6b15e50e9f86285e08ffe3a512ac39f", size = 289268, upload-time = "2025-09-19T00:37:44.823Z" }, - { url = "https://files.pythonhosted.org/packages/94/a6/bc3e8a918abe4741dadeaeb6c508e3a4ea847ff36030d820d89858f96a6c/regex-2025.9.18-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b80fa342ed1ea095168a3f116637bd1030d39c9ff38dc04e54ef7c521e01fc95", size = 806659, upload-time = "2025-09-19T00:37:46.684Z" }, - { url = "https://files.pythonhosted.org/packages/2b/71/ea62dbeb55d9e6905c7b5a49f75615ea1373afcad95830047e4e310db979/regex-2025.9.18-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:f4d97071c0ba40f0cf2a93ed76e660654c399a0a04ab7d85472239460f3da84b", size = 871701, upload-time = "2025-09-19T00:37:48.882Z" }, - { url = "https://files.pythonhosted.org/packages/6a/90/fbe9dedb7dad24a3a4399c0bae64bfa932ec8922a0a9acf7bc88db30b161/regex-2025.9.18-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:0ac936537ad87cef9e0e66c5144484206c1354224ee811ab1519a32373e411f3", size = 913742, upload-time = "2025-09-19T00:37:51.015Z" }, - { url = "https://files.pythonhosted.org/packages/f0/1c/47e4a8c0e73d41eb9eb9fdeba3b1b810110a5139a2526e82fd29c2d9f867/regex-2025.9.18-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:dec57f96d4def58c422d212d414efe28218d58537b5445cf0c33afb1b4768571", size = 811117, upload-time = "2025-09-19T00:37:52.686Z" }, - { url = "https://files.pythonhosted.org/packages/2a/da/435f29fddfd015111523671e36d30af3342e8136a889159b05c1d9110480/regex-2025.9.18-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:48317233294648bf7cd068857f248e3a57222259a5304d32c7552e2284a1b2ad", size = 794647, upload-time = "2025-09-19T00:37:54.626Z" }, - { url = "https://files.pythonhosted.org/packages/23/66/df5e6dcca25c8bc57ce404eebc7342310a0d218db739d7882c9a2b5974a3/regex-2025.9.18-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:274687e62ea3cf54846a9b25fc48a04459de50af30a7bd0b61a9e38015983494", size = 866747, upload-time = "2025-09-19T00:37:56.367Z" }, - { url = "https://files.pythonhosted.org/packages/82/42/94392b39b531f2e469b2daa40acf454863733b674481fda17462a5ffadac/regex-2025.9.18-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:a78722c86a3e7e6aadf9579e3b0ad78d955f2d1f1a8ca4f67d7ca258e8719d4b", size = 853434, upload-time = "2025-09-19T00:37:58.39Z" }, - { url = "https://files.pythonhosted.org/packages/a8/f8/dcc64c7f7bbe58842a8f89622b50c58c3598fbbf4aad0a488d6df2c699f1/regex-2025.9.18-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:06104cd203cdef3ade989a1c45b6215bf42f8b9dd705ecc220c173233f7cba41", size = 798024, upload-time = "2025-09-19T00:38:00.397Z" }, - { url = "https://files.pythonhosted.org/packages/20/8d/edf1c5d5aa98f99a692313db813ec487732946784f8f93145e0153d910e5/regex-2025.9.18-cp314-cp314t-win32.whl", hash = "sha256:2e1eddc06eeaffd249c0adb6fafc19e2118e6308c60df9db27919e96b5656096", size = 273029, upload-time = "2025-09-19T00:38:02.383Z" }, - { url = "https://files.pythonhosted.org/packages/a7/24/02d4e4f88466f17b145f7ea2b2c11af3a942db6222429c2c146accf16054/regex-2025.9.18-cp314-cp314t-win_amd64.whl", hash = "sha256:8620d247fb8c0683ade51217b459cb4a1081c0405a3072235ba43a40d355c09a", size = 282680, upload-time = "2025-09-19T00:38:04.102Z" }, - { url = "https://files.pythonhosted.org/packages/1f/a3/c64894858aaaa454caa7cc47e2f225b04d3ed08ad649eacf58d45817fad2/regex-2025.9.18-cp314-cp314t-win_arm64.whl", hash = "sha256:b7531a8ef61de2c647cdf68b3229b071e46ec326b3138b2180acb4275f470b01", size = 273034, upload-time = "2025-09-19T00:38:05.807Z" }, +version = "2026.4.4" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/cb/0e/3a246dbf05666918bd3664d9d787f84a9108f6f43cc953a077e4a7dfdb7e/regex-2026.4.4.tar.gz", hash = "sha256:e08270659717f6973523ce3afbafa53515c4dc5dcad637dc215b6fd50f689423", size = 416000, upload-time = "2026-04-03T20:56:28.155Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/12/59/fd98f8fd54b3feaa76a855324c676c17668c5a1121ec91b7ec96b01bf865/regex-2026.4.4-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:74fa82dcc8143386c7c0392e18032009d1db715c25f4ba22d23dc2e04d02a20f", size = 489403, upload-time = "2026-04-03T20:52:39.742Z" }, + { url = "https://files.pythonhosted.org/packages/6c/64/d0f222f68e3579d50babf0e4fcc9c9639ef0587fecc00b15e1e46bfc32fa/regex-2026.4.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:a85b620a388d6c9caa12189233109e236b3da3deffe4ff11b84ae84e218a274f", size = 291208, upload-time = "2026-04-03T20:52:42.943Z" }, + { url = "https://files.pythonhosted.org/packages/16/7f/3fab9709b0b0060ba81a04b8a107b34147cd14b9c5551b772154d6505504/regex-2026.4.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:2895506ebe32cc63eeed8f80e6eae453171cfccccab35b70dc3129abec35a5b8", size = 289214, upload-time = "2026-04-03T20:52:44.648Z" }, + { url = "https://files.pythonhosted.org/packages/14/bc/f5dcf04fd462139dcd75495c02eee22032ef741cfa151386a39c3f5fc9b5/regex-2026.4.4-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6780f008ee81381c737634e75c24e5a6569cc883c4f8e37a37917ee79efcafd9", size = 785505, upload-time = "2026-04-03T20:52:46.35Z" }, + { url = "https://files.pythonhosted.org/packages/37/36/8a906e216d5b4de7ec3788c1d589b45db40c1c9580cd7b326835cfc976d4/regex-2026.4.4-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:88e9b048345c613f253bea4645b2fe7e579782b82cac99b1daad81e29cc2ed8e", size = 852129, upload-time = "2026-04-03T20:52:48.661Z" }, + { url = "https://files.pythonhosted.org/packages/a5/bb/bad2d79be0917a6ef31f5e0f161d9265cb56fd90a3ae1d2e8d991882a48b/regex-2026.4.4-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:be061028481186ba62a0f4c5f1cc1e3d5ab8bce70c89236ebe01023883bc903b", size = 899578, upload-time = "2026-04-03T20:52:50.61Z" }, + { url = "https://files.pythonhosted.org/packages/1a/b9/7cd0ceb58cd99c70806241636640ae15b4a3fe62e22e9b99afa67a0d7965/regex-2026.4.4-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d2228c02b368d69b724c36e96d3d1da721561fb9cc7faa373d7bf65e07d75cb5", size = 793634, upload-time = "2026-04-03T20:52:53Z" }, + { url = "https://files.pythonhosted.org/packages/2c/fb/c58e3ea40ed183806ccbac05c29a3e8c2f88c1d3a66ed27860d5cad7c62d/regex-2026.4.4-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:0540e5b733618a2f84e9cb3e812c8afa82e151ca8e19cf6c4e95c5a65198236f", size = 786210, upload-time = "2026-04-03T20:52:54.713Z" }, + { url = "https://files.pythonhosted.org/packages/54/a9/53790fc7a6c948a7be2bc7214fd9cabdd0d1ba561b0f401c91f4ff0357f0/regex-2026.4.4-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:cf9b1b2e692d4877880388934ac746c99552ce6bf40792a767fd42c8c99f136d", size = 769930, upload-time = "2026-04-03T20:52:56.825Z" }, + { url = "https://files.pythonhosted.org/packages/e3/3c/29ca44729191c79f5476538cd0fa04fa2553b3c45508519ecea4c7afa8f6/regex-2026.4.4-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:011bb48bffc1b46553ac704c975b3348717f4e4aa7a67522b51906f99da1820c", size = 774892, upload-time = "2026-04-03T20:52:58.934Z" }, + { url = "https://files.pythonhosted.org/packages/3e/db/6ae74ef8a4cfead341c367e4eed45f71fb1aaba35827a775eed4f1ba4f74/regex-2026.4.4-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:8512fcdb43f1bf18582698a478b5ab73f9c1667a5b7548761329ef410cd0a760", size = 848816, upload-time = "2026-04-03T20:53:00.684Z" }, + { url = "https://files.pythonhosted.org/packages/53/9a/f7f2c1c6b610d7c6de1c3dc5951effd92c324b1fde761af2044b4721020f/regex-2026.4.4-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:867bddc63109a0276f5a31999e4c8e0eb7bbbad7d6166e28d969a2c1afeb97f9", size = 758363, upload-time = "2026-04-03T20:53:02.155Z" }, + { url = "https://files.pythonhosted.org/packages/dd/55/e5386d393bbf8b43c8b084703a46d635e7b2bdc6e0f5909a2619ea1125f1/regex-2026.4.4-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:1b9a00b83f3a40e09859c78920571dcb83293c8004079653dd22ec14bbfa98c7", size = 837122, upload-time = "2026-04-03T20:53:03.727Z" }, + { url = "https://files.pythonhosted.org/packages/01/da/cc78710ea2e60b10bacfcc9beb18c67514200ab03597b3b2b319995785c2/regex-2026.4.4-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:e355be718caf838aa089870259cf1776dc2a4aa980514af9d02c59544d9a8b22", size = 782140, upload-time = "2026-04-03T20:53:05.608Z" }, + { url = "https://files.pythonhosted.org/packages/a2/5f/c7bcba41529105d6c2ca7080ecab7184cd00bee2e1ad1fdea80e618704ea/regex-2026.4.4-cp310-cp310-win32.whl", hash = "sha256:33bfda9684646d323414df7abe5692c61d297dbb0530b28ec66442e768813c59", size = 266225, upload-time = "2026-04-03T20:53:07.342Z" }, + { url = "https://files.pythonhosted.org/packages/eb/26/a745729c2c49354ec4f4bce168f29da932ca01b4758227686cc16c7dde1b/regex-2026.4.4-cp310-cp310-win_amd64.whl", hash = "sha256:0709f22a56798457ae317bcce42aacee33c680068a8f14097430d9f9ba364bee", size = 278393, upload-time = "2026-04-03T20:53:08.65Z" }, + { url = "https://files.pythonhosted.org/packages/87/8b/4327eeb9dbb4b098ebecaf02e9f82b79b6077beeb54c43d9a0660cf7c44c/regex-2026.4.4-cp310-cp310-win_arm64.whl", hash = "sha256:ee9627de8587c1a22201cb16d0296ab92b4df5cdcb5349f4e9744d61db7c7c98", size = 270470, upload-time = "2026-04-03T20:53:10.018Z" }, + { url = "https://files.pythonhosted.org/packages/e0/7a/617356cbecdb452812a5d42f720d6d5096b360d4a4c1073af700ea140ad2/regex-2026.4.4-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:b4c36a85b00fadb85db9d9e90144af0a980e1a3d2ef9cd0f8a5bef88054657c6", size = 489415, upload-time = "2026-04-03T20:53:11.645Z" }, + { url = "https://files.pythonhosted.org/packages/20/e6/bf057227144d02e3ba758b66649e87531d744dda5f3254f48660f18ae9d8/regex-2026.4.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:dcb5453ecf9cd58b562967badd1edbf092b0588a3af9e32ee3d05c985077ce87", size = 291205, upload-time = "2026-04-03T20:53:13.289Z" }, + { url = "https://files.pythonhosted.org/packages/eb/3b/637181b787dd1a820ba1c712cee2b4144cd84a32dc776ca067b12b2d70c8/regex-2026.4.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:6aa809ed4dc3706cc38594d67e641601bd2f36d5555b2780ff074edfcb136cf8", size = 289225, upload-time = "2026-04-03T20:53:16.002Z" }, + { url = "https://files.pythonhosted.org/packages/05/21/bac05d806ed02cd4b39d9c8e5b5f9a2998c94c3a351b7792e80671fa5315/regex-2026.4.4-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:33424f5188a7db12958246a54f59a435b6cb62c5cf9c8d71f7cc49475a5fdada", size = 792434, upload-time = "2026-04-03T20:53:17.414Z" }, + { url = "https://files.pythonhosted.org/packages/d9/17/c65d1d8ae90b772d5758eb4014e1e011bb2db353fc4455432e6cc9100df7/regex-2026.4.4-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:7d346fccdde28abba117cc9edc696b9518c3307fbfcb689e549d9b5979018c6d", size = 861730, upload-time = "2026-04-03T20:53:18.903Z" }, + { url = "https://files.pythonhosted.org/packages/ad/64/933321aa082a2c6ee2785f22776143ba89840189c20d3b6b1d12b6aae16b/regex-2026.4.4-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:415a994b536440f5011aa77e50a4274d15da3245e876e5c7f19da349caaedd87", size = 906495, upload-time = "2026-04-03T20:53:20.561Z" }, + { url = "https://files.pythonhosted.org/packages/01/ea/4c8d306e9c36ac22417336b1e02e7b358152c34dc379673f2d331143725f/regex-2026.4.4-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:21e5eb86179b4c67b5759d452ea7c48eb135cd93308e7a260aa489ed2eb423a4", size = 799810, upload-time = "2026-04-03T20:53:22.961Z" }, + { url = "https://files.pythonhosted.org/packages/29/ce/7605048f00e1379eba89d610c7d644d8f695dc9b26d3b6ecfa3132b872ff/regex-2026.4.4-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:312ec9dd1ae7d96abd8c5a36a552b2139931914407d26fba723f9e53c8186f86", size = 774242, upload-time = "2026-04-03T20:53:25.015Z" }, + { url = "https://files.pythonhosted.org/packages/e9/77/283e0d5023fde22cd9e86190d6d9beb21590a452b195ffe00274de470691/regex-2026.4.4-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:a0d2b28aa1354c7cd7f71b7658c4326f7facac106edd7f40eda984424229fd59", size = 781257, upload-time = "2026-04-03T20:53:26.918Z" }, + { url = "https://files.pythonhosted.org/packages/8b/fb/7f3b772be101373c8626ed34c5d727dcbb8abd42a7b1219bc25fd9a3cc04/regex-2026.4.4-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:349d7310eddff40429a099c08d995c6d4a4bfaf3ff40bd3b5e5cb5a5a3c7d453", size = 854490, upload-time = "2026-04-03T20:53:29.065Z" }, + { url = "https://files.pythonhosted.org/packages/85/30/56547b80f34f4dd2986e1cdd63b1712932f63b6c4ce2f79c50a6cd79d1c2/regex-2026.4.4-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:e7ab63e9fe45a9ec3417509e18116b367e89c9ceb6219222a3396fa30b147f80", size = 763544, upload-time = "2026-04-03T20:53:30.917Z" }, + { url = "https://files.pythonhosted.org/packages/ac/2f/ce060fdfea8eff34a8997603532e44cdb7d1f35e3bc253612a8707a90538/regex-2026.4.4-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:fe896e07a5a2462308297e515c0054e9ec2dd18dfdc9427b19900b37dfe6f40b", size = 844442, upload-time = "2026-04-03T20:53:32.463Z" }, + { url = "https://files.pythonhosted.org/packages/e5/44/810cb113096a1dacbe82789fbfab2823f79d19b7f1271acecb7009ba9b88/regex-2026.4.4-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:eb59c65069498dbae3c0ef07bbe224e1eaa079825a437fb47a479f0af11f774f", size = 789162, upload-time = "2026-04-03T20:53:34.039Z" }, + { url = "https://files.pythonhosted.org/packages/20/96/9647dd7f2ecf6d9ce1fb04dfdb66910d094e10d8fe53e9c15096d8aa0bd2/regex-2026.4.4-cp311-cp311-win32.whl", hash = "sha256:2a5d273181b560ef8397c8825f2b9d57013de744da9e8257b8467e5da8599351", size = 266227, upload-time = "2026-04-03T20:53:35.601Z" }, + { url = "https://files.pythonhosted.org/packages/33/80/74e13262460530c3097ff343a17de9a34d040a5dc4de9cf3a8241faab51c/regex-2026.4.4-cp311-cp311-win_amd64.whl", hash = "sha256:9542ccc1e689e752594309444081582f7be2fdb2df75acafea8a075108566735", size = 278399, upload-time = "2026-04-03T20:53:37.021Z" }, + { url = "https://files.pythonhosted.org/packages/1c/3c/39f19f47f19dcefa3403f09d13562ca1c0fd07ab54db2bc03148f3f6b46a/regex-2026.4.4-cp311-cp311-win_arm64.whl", hash = "sha256:b5f9fb784824a042be3455b53d0b112655686fdb7a91f88f095f3fee1e2a2a54", size = 270473, upload-time = "2026-04-03T20:53:38.633Z" }, + { url = "https://files.pythonhosted.org/packages/e5/28/b972a4d3df61e1d7bcf1b59fdb3cddef22f88b6be43f161bb41ebc0e4081/regex-2026.4.4-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:c07ab8794fa929e58d97a0e1796b8b76f70943fa39df225ac9964615cf1f9d52", size = 490434, upload-time = "2026-04-03T20:53:40.219Z" }, + { url = "https://files.pythonhosted.org/packages/84/20/30041446cf6dc3e0eab344fc62770e84c23b6b68a3b657821f9f80cb69b4/regex-2026.4.4-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:2c785939dc023a1ce4ec09599c032cc9933d258a998d16ca6f2b596c010940eb", size = 292061, upload-time = "2026-04-03T20:53:41.862Z" }, + { url = "https://files.pythonhosted.org/packages/62/c8/3baa06d75c98c46d4cc4262b71fd2edb9062b5665e868bca57859dadf93a/regex-2026.4.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:1b1ce5c81c9114f1ce2f9288a51a8fd3aeea33a0cc440c415bf02da323aa0a76", size = 289628, upload-time = "2026-04-03T20:53:43.701Z" }, + { url = "https://files.pythonhosted.org/packages/31/87/3accf55634caad8c0acab23f5135ef7d4a21c39f28c55c816ae012931408/regex-2026.4.4-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:760ef21c17d8e6a4fe8cf406a97cf2806a4df93416ccc82fc98d25b1c20425be", size = 796651, upload-time = "2026-04-03T20:53:45.379Z" }, + { url = "https://files.pythonhosted.org/packages/f6/0c/aaa2c83f34efedbf06f61cb1942c25f6cf1ee3b200f832c4d05f28306c2e/regex-2026.4.4-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:7088fcdcb604a4417c208e2169715800d28838fefd7455fbe40416231d1d47c1", size = 865916, upload-time = "2026-04-03T20:53:47.064Z" }, + { url = "https://files.pythonhosted.org/packages/d9/f6/8c6924c865124643e8f37823eca845dc27ac509b2ee58123685e71cd0279/regex-2026.4.4-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:07edca1ba687998968f7db5bc355288d0c6505caa7374f013d27356d93976d13", size = 912287, upload-time = "2026-04-03T20:53:49.422Z" }, + { url = "https://files.pythonhosted.org/packages/11/0e/a9f6f81013e0deaf559b25711623864970fe6a098314e374ccb1540a4152/regex-2026.4.4-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:993f657a7c1c6ec51b5e0ba97c9817d06b84ea5fa8d82e43b9405de0defdc2b9", size = 801126, upload-time = "2026-04-03T20:53:51.096Z" }, + { url = "https://files.pythonhosted.org/packages/71/61/3a0cc8af2dc0c8deb48e644dd2521f173f7e6513c6e195aad9aa8dd77ac5/regex-2026.4.4-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:2b69102a743e7569ebee67e634a69c4cb7e59d6fa2e1aa7d3bdbf3f61435f62d", size = 776788, upload-time = "2026-04-03T20:53:52.889Z" }, + { url = "https://files.pythonhosted.org/packages/64/0b/8bb9cbf21ef7dee58e49b0fdb066a7aded146c823202e16494a36777594f/regex-2026.4.4-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:6dac006c8b6dda72d86ea3d1333d45147de79a3a3f26f10c1cf9287ca4ca0ac3", size = 785184, upload-time = "2026-04-03T20:53:55.627Z" }, + { url = "https://files.pythonhosted.org/packages/99/c2/d3e80e8137b25ee06c92627de4e4d98b94830e02b3e6f81f3d2e3f504cf5/regex-2026.4.4-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:50a766ee2010d504554bfb5f578ed2e066898aa26411d57e6296230627cdefa0", size = 859913, upload-time = "2026-04-03T20:53:57.249Z" }, + { url = "https://files.pythonhosted.org/packages/bc/e6/9d5d876157d969c804622456ef250017ac7a8f83e0e14f903b9e6df5ce95/regex-2026.4.4-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:9e2f5217648f68e3028c823df58663587c1507a5ba8419f4fdfc8a461be76043", size = 765732, upload-time = "2026-04-03T20:53:59.428Z" }, + { url = "https://files.pythonhosted.org/packages/82/80/b568935b4421388561c8ed42aff77247285d3ae3bb2a6ca22af63bae805e/regex-2026.4.4-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:39d8de85a08e32632974151ba59c6e9140646dcc36c80423962b1c5c0a92e244", size = 852152, upload-time = "2026-04-03T20:54:01.505Z" }, + { url = "https://files.pythonhosted.org/packages/39/29/f0f81217e21cd998245da047405366385d5c6072048038a3d33b37a79dc0/regex-2026.4.4-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:55d9304e0e7178dfb1e106c33edf834097ddf4a890e2f676f6c5118f84390f73", size = 789076, upload-time = "2026-04-03T20:54:03.323Z" }, + { url = "https://files.pythonhosted.org/packages/49/1d/1d957a61976ab9d4e767dd4f9d04b66cc0c41c5e36cf40e2d43688b5ae6f/regex-2026.4.4-cp312-cp312-win32.whl", hash = "sha256:04bb679bc0bde8a7bfb71e991493d47314e7b98380b083df2447cda4b6edb60f", size = 266700, upload-time = "2026-04-03T20:54:05.639Z" }, + { url = "https://files.pythonhosted.org/packages/c5/5c/bf575d396aeb58ea13b06ef2adf624f65b70fafef6950a80fc3da9cae3bc/regex-2026.4.4-cp312-cp312-win_amd64.whl", hash = "sha256:db0ac18435a40a2543dbb3d21e161a6c78e33e8159bd2e009343d224bb03bb1b", size = 277768, upload-time = "2026-04-03T20:54:07.312Z" }, + { url = "https://files.pythonhosted.org/packages/c9/27/049df16ec6a6828ccd72add3c7f54b4df029669bea8e9817df6fff58be90/regex-2026.4.4-cp312-cp312-win_arm64.whl", hash = "sha256:4ce255cc05c1947a12989c6db801c96461947adb7a59990f1360b5983fab4983", size = 270568, upload-time = "2026-04-03T20:54:09.484Z" }, + { url = "https://files.pythonhosted.org/packages/9d/83/c4373bc5f31f2cf4b66f9b7c31005bd87fe66f0dce17701f7db4ee79ee29/regex-2026.4.4-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:62f5519042c101762509b1d717b45a69c0139d60414b3c604b81328c01bd1943", size = 490273, upload-time = "2026-04-03T20:54:11.202Z" }, + { url = "https://files.pythonhosted.org/packages/46/f8/fe62afbcc3cf4ad4ac9adeaafd98aa747869ae12d3e8e2ac293d0593c435/regex-2026.4.4-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:3790ba9fb5dd76715a7afe34dbe603ba03f8820764b1dc929dd08106214ed031", size = 291954, upload-time = "2026-04-03T20:54:13.412Z" }, + { url = "https://files.pythonhosted.org/packages/5a/92/4712b9fe6a33d232eeb1c189484b80c6c4b8422b90e766e1195d6e758207/regex-2026.4.4-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:8fae3c6e795d7678963f2170152b0d892cf6aee9ee8afc8c45e6be38d5107fe7", size = 289487, upload-time = "2026-04-03T20:54:15.824Z" }, + { url = "https://files.pythonhosted.org/packages/88/2c/f83b93f85e01168f1070f045a42d4c937b69fdb8dd7ae82d307253f7e36e/regex-2026.4.4-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:298c3ec2d53225b3bf91142eb9691025bab610e0c0c51592dde149db679b3d17", size = 796646, upload-time = "2026-04-03T20:54:18.229Z" }, + { url = "https://files.pythonhosted.org/packages/df/55/61a2e17bf0c4dc57e11caf8dd11771280d8aaa361785f9e3bc40d653f4a7/regex-2026.4.4-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:e9638791082eaf5b3ac112c587518ee78e083a11c4b28012d8fe2a0f536dfb17", size = 865904, upload-time = "2026-04-03T20:54:20.019Z" }, + { url = "https://files.pythonhosted.org/packages/45/32/1ac8ed1b5a346b5993a3d256abe0a0f03b0b73c8cc88d928537368ac65b6/regex-2026.4.4-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:ae3e764bd4c5ff55035dc82a8d49acceb42a5298edf6eb2fc4d328ee5dd7afae", size = 912304, upload-time = "2026-04-03T20:54:22.403Z" }, + { url = "https://files.pythonhosted.org/packages/26/47/2ee5c613ab546f0eddebf9905d23e07beb933416b1246c2d8791d01979b4/regex-2026.4.4-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ffa81f81b80047ba89a3c69ae6a0f78d06f4a42ce5126b0eb2a0a10ad44e0b2e", size = 801126, upload-time = "2026-04-03T20:54:24.308Z" }, + { url = "https://files.pythonhosted.org/packages/75/cd/41dacd129ca9fd20bd7d02f83e0fad83e034ac8a084ec369c90f55ef37e2/regex-2026.4.4-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:f56ebf9d70305307a707911b88469213630aba821e77de7d603f9d2f0730687d", size = 776772, upload-time = "2026-04-03T20:54:26.319Z" }, + { url = "https://files.pythonhosted.org/packages/89/6d/5af0b588174cb5f46041fa7dd64d3fd5cd2fe51f18766703d1edc387f324/regex-2026.4.4-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:773d1dfd652bbffb09336abf890bfd64785c7463716bf766d0eb3bc19c8b7f27", size = 785228, upload-time = "2026-04-03T20:54:28.387Z" }, + { url = "https://files.pythonhosted.org/packages/b7/3b/f5a72b7045bd59575fc33bf1345f156fcfd5a8484aea6ad84b12c5a82114/regex-2026.4.4-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:d51d20befd5275d092cdffba57ded05f3c436317ee56466c8928ac32d960edaf", size = 860032, upload-time = "2026-04-03T20:54:30.641Z" }, + { url = "https://files.pythonhosted.org/packages/39/a4/72a317003d6fcd7a573584a85f59f525dfe8f67e355ca74eb6b53d66a5e2/regex-2026.4.4-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:0a51cdb3c1e9161154f976cb2bef9894bc063ac82f31b733087ffb8e880137d0", size = 765714, upload-time = "2026-04-03T20:54:32.789Z" }, + { url = "https://files.pythonhosted.org/packages/25/1e/5672e16f34dbbcb2560cc7e6a2fbb26dfa8b270711e730101da4423d3973/regex-2026.4.4-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:ae5266a82596114e41fb5302140e9630204c1b5f325c770bec654b95dd54b0aa", size = 852078, upload-time = "2026-04-03T20:54:34.546Z" }, + { url = "https://files.pythonhosted.org/packages/f7/0d/c813f0af7c6cc7ed7b9558bac2e5120b60ad0fa48f813e4d4bd55446f214/regex-2026.4.4-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:c882cd92ec68585e9c1cf36c447ec846c0d94edd706fe59e0c198e65822fd23b", size = 789181, upload-time = "2026-04-03T20:54:36.642Z" }, + { url = "https://files.pythonhosted.org/packages/ea/6d/a344608d1adbd2a95090ddd906cec09a11be0e6517e878d02a5123e0917f/regex-2026.4.4-cp313-cp313-win32.whl", hash = "sha256:05568c4fbf3cb4fa9e28e3af198c40d3237cf6041608a9022285fe567ec3ad62", size = 266690, upload-time = "2026-04-03T20:54:38.343Z" }, + { url = "https://files.pythonhosted.org/packages/31/07/54049f89b46235ca6f45cd6c88668a7050e77d4a15555e47dd40fde75263/regex-2026.4.4-cp313-cp313-win_amd64.whl", hash = "sha256:3384df51ed52db0bea967e21458ab0a414f67cdddfd94401688274e55147bb81", size = 277733, upload-time = "2026-04-03T20:54:40.11Z" }, + { url = "https://files.pythonhosted.org/packages/0e/21/61366a8e20f4d43fb597708cac7f0e2baadb491ecc9549b4980b2be27d16/regex-2026.4.4-cp313-cp313-win_arm64.whl", hash = "sha256:acd38177bd2c8e69a411d6521760806042e244d0ef94e2dd03ecdaa8a3c99427", size = 270565, upload-time = "2026-04-03T20:54:41.883Z" }, + { url = "https://files.pythonhosted.org/packages/f1/1e/3a2b9672433bef02f5d39aa1143ca2c08f311c1d041c464a42be9ae648dc/regex-2026.4.4-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:f94a11a9d05afcfcfa640e096319720a19cc0c9f7768e1a61fceee6a3afc6c7c", size = 494126, upload-time = "2026-04-03T20:54:43.602Z" }, + { url = "https://files.pythonhosted.org/packages/4e/4b/c132a4f4fe18ad3340d89fcb56235132b69559136036b845be3c073142ed/regex-2026.4.4-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:36bcb9d6d1307ab629edc553775baada2aefa5c50ccc0215fbfd2afcfff43141", size = 293882, upload-time = "2026-04-03T20:54:45.41Z" }, + { url = "https://files.pythonhosted.org/packages/f4/5f/eaa38092ce7a023656280f2341dbbd4ad5f05d780a70abba7bb4f4bea54c/regex-2026.4.4-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:261c015b3e2ed0919157046d768774ecde57f03d8fa4ba78d29793447f70e717", size = 292334, upload-time = "2026-04-03T20:54:47.051Z" }, + { url = "https://files.pythonhosted.org/packages/5f/f6/dd38146af1392dac33db7074ab331cec23cced3759167735c42c5460a243/regex-2026.4.4-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c228cf65b4a54583763645dcd73819b3b381ca8b4bb1b349dee1c135f4112c07", size = 811691, upload-time = "2026-04-03T20:54:49.074Z" }, + { url = "https://files.pythonhosted.org/packages/7a/f0/dc54c2e69f5eeec50601054998ec3690d5344277e782bd717e49867c1d29/regex-2026.4.4-cp313-cp313t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:dd2630faeb6876fb0c287f664d93ddce4d50cd46c6e88e60378c05c9047e08ca", size = 871227, upload-time = "2026-04-03T20:54:51.035Z" }, + { url = "https://files.pythonhosted.org/packages/a1/af/cb16bd5dc61621e27df919a4449bbb7e5a1034c34d307e0a706e9cc0f3e3/regex-2026.4.4-cp313-cp313t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:6a50ab11b7779b849472337191f3a043e27e17f71555f98d0092fa6d73364520", size = 917435, upload-time = "2026-04-03T20:54:52.994Z" }, + { url = "https://files.pythonhosted.org/packages/5c/71/8b260897f22996b666edd9402861668f45a2ca259f665ac029e6104a2d7d/regex-2026.4.4-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0734f63afe785138549fbe822a8cfeaccd1bae814c5057cc0ed5b9f2de4fc883", size = 816358, upload-time = "2026-04-03T20:54:54.884Z" }, + { url = "https://files.pythonhosted.org/packages/1c/60/775f7f72a510ef238254906c2f3d737fc80b16ca85f07d20e318d2eea894/regex-2026.4.4-cp313-cp313t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:c4ee50606cb1967db7e523224e05f32089101945f859928e65657a2cbb3d278b", size = 785549, upload-time = "2026-04-03T20:54:57.01Z" }, + { url = "https://files.pythonhosted.org/packages/58/42/34d289b3627c03cf381e44da534a0021664188fa49ba41513da0b4ec6776/regex-2026.4.4-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:6c1818f37be3ca02dcb76d63f2c7aaba4b0dc171b579796c6fbe00148dfec6b1", size = 801364, upload-time = "2026-04-03T20:54:58.981Z" }, + { url = "https://files.pythonhosted.org/packages/fc/20/f6ecf319b382a8f1ab529e898b222c3f30600fcede7834733c26279e7465/regex-2026.4.4-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:f5bfc2741d150d0be3e4a0401a5c22b06e60acb9aa4daa46d9e79a6dcd0f135b", size = 866221, upload-time = "2026-04-03T20:55:00.88Z" }, + { url = "https://files.pythonhosted.org/packages/92/6a/9f16d3609d549bd96d7a0b2aee1625d7512ba6a03efc01652149ef88e74d/regex-2026.4.4-cp313-cp313t-musllinux_1_2_riscv64.whl", hash = "sha256:504ffa8a03609a087cad81277a629b6ce884b51a24bd388a7980ad61748618ff", size = 772530, upload-time = "2026-04-03T20:55:03.213Z" }, + { url = "https://files.pythonhosted.org/packages/fa/f6/aa9768bc96a4c361ac96419fbaf2dcdc33970bb813df3ba9b09d5d7b6d96/regex-2026.4.4-cp313-cp313t-musllinux_1_2_s390x.whl", hash = "sha256:70aadc6ff12e4b444586e57fc30771f86253f9f0045b29016b9605b4be5f7dfb", size = 856989, upload-time = "2026-04-03T20:55:05.087Z" }, + { url = "https://files.pythonhosted.org/packages/4d/b4/c671db3556be2473ae3e4bb7a297c518d281452871501221251ea4ecba57/regex-2026.4.4-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:f4f83781191007b6ef43b03debc35435f10cad9b96e16d147efe84a1d48bdde4", size = 803241, upload-time = "2026-04-03T20:55:07.162Z" }, + { url = "https://files.pythonhosted.org/packages/2a/5c/83e3b1d89fa4f6e5a1bc97b4abd4a9a97b3c1ac7854164f694f5f0ba98a0/regex-2026.4.4-cp313-cp313t-win32.whl", hash = "sha256:e014a797de43d1847df957c0a2a8e861d1c17547ee08467d1db2c370b7568baa", size = 269921, upload-time = "2026-04-03T20:55:09.62Z" }, + { url = "https://files.pythonhosted.org/packages/28/07/077c387121f42cdb4d92b1301133c0d93b5709d096d1669ab847dda9fe2e/regex-2026.4.4-cp313-cp313t-win_amd64.whl", hash = "sha256:b15b88b0d52b179712632832c1d6e58e5774f93717849a41096880442da41ab0", size = 281240, upload-time = "2026-04-03T20:55:11.521Z" }, + { url = "https://files.pythonhosted.org/packages/9d/22/ead4a4abc7c59a4d882662aa292ca02c8b617f30b6e163bc1728879e9353/regex-2026.4.4-cp313-cp313t-win_arm64.whl", hash = "sha256:586b89cdadf7d67bf86ae3342a4dcd2b8d70a832d90c18a0ae955105caf34dbe", size = 272440, upload-time = "2026-04-03T20:55:13.365Z" }, + { url = "https://files.pythonhosted.org/packages/f0/f5/ed97c2dc47b5fbd4b73c0d7d75f9ebc8eca139f2bbef476bba35f28c0a77/regex-2026.4.4-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:2da82d643fa698e5e5210e54af90181603d5853cf469f5eedf9bfc8f59b4b8c7", size = 490343, upload-time = "2026-04-03T20:55:15.241Z" }, + { url = "https://files.pythonhosted.org/packages/80/e9/de4828a7385ec166d673a5790ad06ac48cdaa98bc0960108dd4b9cc1aef7/regex-2026.4.4-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:54a1189ad9d9357760557c91103d5e421f0a2dabe68a5cdf9103d0dcf4e00752", size = 291909, upload-time = "2026-04-03T20:55:17.558Z" }, + { url = "https://files.pythonhosted.org/packages/b4/d6/5cfbfc97f3201a4d24b596a77957e092030dcc4205894bc035cedcfce62f/regex-2026.4.4-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:76d67d5afb1fe402d10a6403bae668d000441e2ab115191a804287d53b772951", size = 289692, upload-time = "2026-04-03T20:55:20.561Z" }, + { url = "https://files.pythonhosted.org/packages/8e/ac/f2212d9fd56fe897e36d0110ba30ba2d247bd6410c5bd98499c7e5a1e1f2/regex-2026.4.4-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e7cd3e4ee8d80447a83bbc9ab0c8459781fa77087f856c3e740d7763be0df27f", size = 796979, upload-time = "2026-04-03T20:55:22.56Z" }, + { url = "https://files.pythonhosted.org/packages/c9/e3/a016c12675fbac988a60c7e1c16e67823ff0bc016beb27bd7a001dbdabc6/regex-2026.4.4-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:2e19e18c568d2866d8b6a6dfad823db86193503f90823a8f66689315ba28fbe8", size = 866744, upload-time = "2026-04-03T20:55:24.646Z" }, + { url = "https://files.pythonhosted.org/packages/af/a4/0b90ca4cf17adc3cb43de80ec71018c37c88ad64987e8d0d481a95ca60b5/regex-2026.4.4-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:7698a6f38730fd1385d390d1ed07bb13dce39aa616aca6a6d89bea178464b9a4", size = 911613, upload-time = "2026-04-03T20:55:27.033Z" }, + { url = "https://files.pythonhosted.org/packages/8e/3b/2b3dac0b82d41ab43aa87c6ecde63d71189d03fe8854b8ca455a315edac3/regex-2026.4.4-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:173a66f3651cdb761018078e2d9487f4cf971232c990035ec0eb1cdc6bf929a9", size = 800551, upload-time = "2026-04-03T20:55:29.532Z" }, + { url = "https://files.pythonhosted.org/packages/25/fe/5365eb7aa0e753c4b5957815c321519ecab033c279c60e1b1ae2367fa810/regex-2026.4.4-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:fa7922bbb2cc84fa062d37723f199d4c0cd200245ce269c05db82d904db66b83", size = 776911, upload-time = "2026-04-03T20:55:31.526Z" }, + { url = "https://files.pythonhosted.org/packages/aa/b3/7fb0072156bba065e3b778a7bc7b0a6328212be5dd6a86fd207e0c4f2dab/regex-2026.4.4-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:59f67cd0a0acaf0e564c20bbd7f767286f23e91e2572c5703bf3e56ea7557edb", size = 785751, upload-time = "2026-04-03T20:55:33.797Z" }, + { url = "https://files.pythonhosted.org/packages/02/1a/9f83677eb699273e56e858f7bd95acdbee376d42f59e8bfca2fd80d79df3/regex-2026.4.4-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:475e50f3f73f73614f7cba5524d6de49dee269df00272a1b85e3d19f6d498465", size = 860484, upload-time = "2026-04-03T20:55:35.745Z" }, + { url = "https://files.pythonhosted.org/packages/3b/7a/93937507b61cfcff8b4c5857f1b452852b09f741daa9acae15c971d8554e/regex-2026.4.4-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:a1c0c7d67b64d85ac2e1879923bad2f08a08f3004055f2f406ef73c850114bd4", size = 765939, upload-time = "2026-04-03T20:55:37.972Z" }, + { url = "https://files.pythonhosted.org/packages/86/ea/81a7f968a351c6552b1670ead861e2a385be730ee28402233020c67f9e0f/regex-2026.4.4-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:1371c2ccbb744d66ee63631cc9ca12aa233d5749972626b68fe1a649dd98e566", size = 851417, upload-time = "2026-04-03T20:55:39.92Z" }, + { url = "https://files.pythonhosted.org/packages/4c/7e/323c18ce4b5b8f44517a36342961a0306e931e499febbd876bb149d900f0/regex-2026.4.4-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:59968142787042db793348a3f5b918cf24ced1f23247328530e063f89c128a95", size = 789056, upload-time = "2026-04-03T20:55:42.303Z" }, + { url = "https://files.pythonhosted.org/packages/c0/af/e7510f9b11b1913b0cd44eddb784b2d650b2af6515bfce4cffcc5bfd1d38/regex-2026.4.4-cp314-cp314-win32.whl", hash = "sha256:59efe72d37fd5a91e373e5146f187f921f365f4abc1249a5ab446a60f30dd5f8", size = 272130, upload-time = "2026-04-03T20:55:44.995Z" }, + { url = "https://files.pythonhosted.org/packages/9a/51/57dae534c915e2d3a21490e88836fa2ae79dde3b66255ecc0c0a155d2c10/regex-2026.4.4-cp314-cp314-win_amd64.whl", hash = "sha256:e0aab3ff447845049d676827d2ff714aab4f73f340e155b7de7458cf53baa5a4", size = 280992, upload-time = "2026-04-03T20:55:47.316Z" }, + { url = "https://files.pythonhosted.org/packages/0a/5e/abaf9f4c3792e34edb1434f06717fae2b07888d85cb5cec29f9204931bf8/regex-2026.4.4-cp314-cp314-win_arm64.whl", hash = "sha256:a7a5bb6aa0cf62208bb4fa079b0c756734f8ad0e333b425732e8609bd51ee22f", size = 273563, upload-time = "2026-04-03T20:55:49.273Z" }, + { url = "https://files.pythonhosted.org/packages/ff/06/35da85f9f217b9538b99cbb170738993bcc3b23784322decb77619f11502/regex-2026.4.4-cp314-cp314t-macosx_10_13_universal2.whl", hash = "sha256:97850d0638391bdc7d35dc1c1039974dcb921eaafa8cc935ae4d7f272b1d60b3", size = 494191, upload-time = "2026-04-03T20:55:51.258Z" }, + { url = "https://files.pythonhosted.org/packages/54/5b/1bc35f479eef8285c4baf88d8c002023efdeebb7b44a8735b36195486ae7/regex-2026.4.4-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:ee7337f88f2a580679f7bbfe69dc86c043954f9f9c541012f49abc554a962f2e", size = 293877, upload-time = "2026-04-03T20:55:53.214Z" }, + { url = "https://files.pythonhosted.org/packages/39/5b/f53b9ad17480b3ddd14c90da04bfb55ac6894b129e5dea87bcaf7d00e336/regex-2026.4.4-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:7429f4e6192c11d659900c0648ba8776243bf396ab95558b8c51a345afeddde6", size = 292410, upload-time = "2026-04-03T20:55:55.736Z" }, + { url = "https://files.pythonhosted.org/packages/bb/56/52377f59f60a7c51aa4161eecf0b6032c20b461805aca051250da435ffc9/regex-2026.4.4-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:dc4f10fbd5dd13dcf4265b4cc07d69ca70280742870c97ae10093e3d66000359", size = 811831, upload-time = "2026-04-03T20:55:57.802Z" }, + { url = "https://files.pythonhosted.org/packages/dd/63/8026310bf066f702a9c361f83a8c9658f3fe4edb349f9c1e5d5273b7c40c/regex-2026.4.4-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:a152560af4f9742b96f3827090f866eeec5becd4765c8e0d3473d9d280e76a5a", size = 871199, upload-time = "2026-04-03T20:56:00.333Z" }, + { url = "https://files.pythonhosted.org/packages/20/9f/a514bbb00a466dbb506d43f187a04047f7be1505f10a9a15615ead5080ee/regex-2026.4.4-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:54170b3e95339f415d54651f97df3bff7434a663912f9358237941bbf9143f55", size = 917649, upload-time = "2026-04-03T20:56:02.445Z" }, + { url = "https://files.pythonhosted.org/packages/cb/6b/8399f68dd41a2030218839b9b18360d79b86d22b9fab5ef477c7f23ca67c/regex-2026.4.4-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:07f190d65f5a72dcb9cf7106bfc3d21e7a49dd2879eda2207b683f32165e4d99", size = 816388, upload-time = "2026-04-03T20:56:04.595Z" }, + { url = "https://files.pythonhosted.org/packages/1e/9c/103963f47c24339a483b05edd568594c2be486188f688c0170fd504b2948/regex-2026.4.4-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:9a2741ce5a29d3c84b0b94261ba630ab459a1b847a0d6beca7d62d188175c790", size = 785746, upload-time = "2026-04-03T20:56:07.13Z" }, + { url = "https://files.pythonhosted.org/packages/fa/ee/7f6054c0dec0cee3463c304405e4ff42e27cff05bf36fcb34be549ab17bd/regex-2026.4.4-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:b26c30df3a28fd9793113dac7385a4deb7294a06c0f760dd2b008bd49a9139bc", size = 801483, upload-time = "2026-04-03T20:56:09.365Z" }, + { url = "https://files.pythonhosted.org/packages/30/c2/51d3d941cf6070dc00c3338ecf138615fc3cce0421c3df6abe97a08af61a/regex-2026.4.4-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:421439d1bee44b19f4583ccf42670ca464ffb90e9fdc38d37f39d1ddd1e44f1f", size = 866331, upload-time = "2026-04-03T20:56:12.039Z" }, + { url = "https://files.pythonhosted.org/packages/16/e8/76d50dcc122ac33927d939f350eebcfe3dbcbda96913e03433fc36de5e63/regex-2026.4.4-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:b40379b53ecbc747fd9bdf4a0ea14eb8188ca1bd0f54f78893a39024b28f4863", size = 772673, upload-time = "2026-04-03T20:56:14.558Z" }, + { url = "https://files.pythonhosted.org/packages/a5/6e/5f6bf75e20ea6873d05ba4ec78378c375cbe08cdec571c83fbb01606e563/regex-2026.4.4-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:08c55c13d2eef54f73eeadc33146fb0baaa49e7335eb1aff6ae1324bf0ddbe4a", size = 857146, upload-time = "2026-04-03T20:56:16.663Z" }, + { url = "https://files.pythonhosted.org/packages/0b/33/3c76d9962949e487ebba353a18e89399f292287204ac8f2f4cfc3a51c233/regex-2026.4.4-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:9776b85f510062f5a75ef112afe5f494ef1635607bf1cc220c1391e9ac2f5e81", size = 803463, upload-time = "2026-04-03T20:56:18.923Z" }, + { url = "https://files.pythonhosted.org/packages/19/eb/ef32dcd2cb69b69bc0c3e55205bce94a7def48d495358946bc42186dcccc/regex-2026.4.4-cp314-cp314t-win32.whl", hash = "sha256:385edaebde5db5be103577afc8699fea73a0e36a734ba24870be7ffa61119d74", size = 275709, upload-time = "2026-04-03T20:56:20.996Z" }, + { url = "https://files.pythonhosted.org/packages/a0/86/c291bf740945acbf35ed7dbebf8e2eea2f3f78041f6bd7cdab80cb274dc0/regex-2026.4.4-cp314-cp314t-win_amd64.whl", hash = "sha256:5d354b18839328927832e2fa5f7c95b7a3ccc39e7a681529e1685898e6436d45", size = 285622, upload-time = "2026-04-03T20:56:23.641Z" }, + { url = "https://files.pythonhosted.org/packages/d5/e7/ec846d560ae6a597115153c02ca6138a7877a1748b2072d9521c10a93e58/regex-2026.4.4-cp314-cp314t-win_arm64.whl", hash = "sha256:af0384cb01a33600c49505c27c6c57ab0b27bf84a74e28524c92ca897ebdac9d", size = 275773, upload-time = "2026-04-03T20:56:26.07Z" }, ] [[package]] name = "requests" -version = "2.32.5" +version = "2.33.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "certifi" }, @@ -4412,9 +4507,9 @@ dependencies = [ { name = "idna" }, { name = "urllib3" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/c9/74/b3ff8e6c8446842c3f5c837e9c3dfcfe2018ea6ecef224c710c85ef728f4/requests-2.32.5.tar.gz", hash = "sha256:dbba0bac56e100853db0ea71b82b4dfd5fe2bf6d3754a8893c3af500cec7d7cf", size = 134517, upload-time = "2025-08-18T20:46:02.573Z" } +sdist = { url = "https://files.pythonhosted.org/packages/5f/a4/98b9c7c6428a668bf7e42ebb7c79d576a1c3c1e3ae2d47e674b468388871/requests-2.33.1.tar.gz", hash = "sha256:18817f8c57c6263968bc123d237e3b8b08ac046f5456bd1e307ee8f4250d3517", size = 134120, upload-time = "2026-03-30T16:09:15.531Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/1e/db/4254e3eabe8020b458f1a747140d32277ec7a271daf1d235b70dc0b4e6e3/requests-2.32.5-py3-none-any.whl", hash = "sha256:2462f94637a34fd532264295e186976db0f5d453d1cdd31473c85a6a161affb6", size = 64738, upload-time = "2025-08-18T20:46:00.542Z" }, + { url = "https://files.pythonhosted.org/packages/d7/8e/7540e8a2036f79a125c1d2ebadf69ed7901608859186c856fa0388ef4197/requests-2.33.1-py3-none-any.whl", hash = "sha256:4e6d1ef462f3626a1f0a0a9c42dd93c63bad33f9f1c1937509b8c5c8718ab56a", size = 64947, upload-time = "2026-03-30T16:09:13.83Z" }, ] [[package]] @@ -4466,162 +4561,137 @@ wheels = [ [[package]] name = "rich" -version = "14.2.0" +version = "14.3.3" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "markdown-it-py" }, { name = "pygments" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/fb/d2/8920e102050a0de7bfabeb4c4614a49248cf8d5d7a8d01885fbb24dc767a/rich-14.2.0.tar.gz", hash = "sha256:73ff50c7c0c1c77c8243079283f4edb376f0f6442433aecb8ce7e6d0b92d1fe4", size = 219990, upload-time = "2025-10-09T14:16:53.064Z" } +sdist = { url = "https://files.pythonhosted.org/packages/b3/c6/f3b320c27991c46f43ee9d856302c70dc2d0fb2dba4842ff739d5f46b393/rich-14.3.3.tar.gz", hash = "sha256:b8daa0b9e4eef54dd8cf7c86c03713f53241884e814f4e2f5fb342fe520f639b", size = 230582, upload-time = "2026-02-19T17:23:12.474Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/25/7a/b0178788f8dc6cafce37a212c99565fa1fe7872c70c6c9c1e1a372d9d88f/rich-14.2.0-py3-none-any.whl", hash = "sha256:76bc51fe2e57d2b1be1f96c524b890b816e334ab4c1e45888799bfaab0021edd", size = 243393, upload-time = "2025-10-09T14:16:51.245Z" }, + { url = "https://files.pythonhosted.org/packages/14/25/b208c5683343959b670dc001595f2f3737e051da617f66c31f7c4fa93abc/rich-14.3.3-py3-none-any.whl", hash = "sha256:793431c1f8619afa7d3b52b2cdec859562b950ea0d4b6b505397612db8d5362d", size = 310458, upload-time = "2026-02-19T17:23:13.732Z" }, ] [[package]] name = "rpds-py" -version = "0.27.1" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/e9/dd/2c0cbe774744272b0ae725f44032c77bdcab6e8bcf544bffa3b6e70c8dba/rpds_py-0.27.1.tar.gz", hash = "sha256:26a1c73171d10b7acccbded82bf6a586ab8203601e565badc74bbbf8bc5a10f8", size = 27479, upload-time = "2025-08-27T12:16:36.024Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/a5/ed/3aef893e2dd30e77e35d20d4ddb45ca459db59cead748cad9796ad479411/rpds_py-0.27.1-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:68afeec26d42ab3b47e541b272166a0b4400313946871cba3ed3a4fc0cab1cef", size = 371606, upload-time = "2025-08-27T12:12:25.189Z" }, - { url = "https://files.pythonhosted.org/packages/6d/82/9818b443e5d3eb4c83c3994561387f116aae9833b35c484474769c4a8faf/rpds_py-0.27.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:74e5b2f7bb6fa38b1b10546d27acbacf2a022a8b5543efb06cfebc72a59c85be", size = 353452, upload-time = "2025-08-27T12:12:27.433Z" }, - { url = "https://files.pythonhosted.org/packages/99/c7/d2a110ffaaa397fc6793a83c7bd3545d9ab22658b7cdff05a24a4535cc45/rpds_py-0.27.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9024de74731df54546fab0bfbcdb49fae19159ecaecfc8f37c18d2c7e2c0bd61", size = 381519, upload-time = "2025-08-27T12:12:28.719Z" }, - { url = "https://files.pythonhosted.org/packages/5a/bc/e89581d1f9d1be7d0247eaef602566869fdc0d084008ba139e27e775366c/rpds_py-0.27.1-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:31d3ebadefcd73b73928ed0b2fd696f7fefda8629229f81929ac9c1854d0cffb", size = 394424, upload-time = "2025-08-27T12:12:30.207Z" }, - { url = "https://files.pythonhosted.org/packages/ac/2e/36a6861f797530e74bb6ed53495f8741f1ef95939eed01d761e73d559067/rpds_py-0.27.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b2e7f8f169d775dd9092a1743768d771f1d1300453ddfe6325ae3ab5332b4657", size = 523467, upload-time = "2025-08-27T12:12:31.808Z" }, - { url = "https://files.pythonhosted.org/packages/c4/59/c1bc2be32564fa499f988f0a5c6505c2f4746ef96e58e4d7de5cf923d77e/rpds_py-0.27.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3d905d16f77eb6ab2e324e09bfa277b4c8e5e6b8a78a3e7ff8f3cdf773b4c013", size = 402660, upload-time = "2025-08-27T12:12:33.444Z" }, - { url = "https://files.pythonhosted.org/packages/0a/ec/ef8bf895f0628dd0a59e54d81caed6891663cb9c54a0f4bb7da918cb88cf/rpds_py-0.27.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:50c946f048209e6362e22576baea09193809f87687a95a8db24e5fbdb307b93a", size = 384062, upload-time = "2025-08-27T12:12:34.857Z" }, - { url = "https://files.pythonhosted.org/packages/69/f7/f47ff154be8d9a5e691c083a920bba89cef88d5247c241c10b9898f595a1/rpds_py-0.27.1-cp310-cp310-manylinux_2_31_riscv64.whl", hash = "sha256:3deab27804d65cd8289eb814c2c0e807c4b9d9916c9225e363cb0cf875eb67c1", size = 401289, upload-time = "2025-08-27T12:12:36.085Z" }, - { url = "https://files.pythonhosted.org/packages/3b/d9/ca410363efd0615814ae579f6829cafb39225cd63e5ea5ed1404cb345293/rpds_py-0.27.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:8b61097f7488de4be8244c89915da8ed212832ccf1e7c7753a25a394bf9b1f10", size = 417718, upload-time = "2025-08-27T12:12:37.401Z" }, - { url = "https://files.pythonhosted.org/packages/e3/a0/8cb5c2ff38340f221cc067cc093d1270e10658ba4e8d263df923daa18e86/rpds_py-0.27.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:8a3f29aba6e2d7d90528d3c792555a93497fe6538aa65eb675b44505be747808", size = 558333, upload-time = "2025-08-27T12:12:38.672Z" }, - { url = "https://files.pythonhosted.org/packages/6f/8c/1b0de79177c5d5103843774ce12b84caa7164dfc6cd66378768d37db11bf/rpds_py-0.27.1-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:dd6cd0485b7d347304067153a6dc1d73f7d4fd995a396ef32a24d24b8ac63ac8", size = 589127, upload-time = "2025-08-27T12:12:41.48Z" }, - { url = "https://files.pythonhosted.org/packages/c8/5e/26abb098d5e01266b0f3a2488d299d19ccc26849735d9d2b95c39397e945/rpds_py-0.27.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:6f4461bf931108c9fa226ffb0e257c1b18dc2d44cd72b125bec50ee0ab1248a9", size = 554899, upload-time = "2025-08-27T12:12:42.925Z" }, - { url = "https://files.pythonhosted.org/packages/de/41/905cc90ced13550db017f8f20c6d8e8470066c5738ba480d7ba63e3d136b/rpds_py-0.27.1-cp310-cp310-win32.whl", hash = "sha256:ee5422d7fb21f6a00c1901bf6559c49fee13a5159d0288320737bbf6585bd3e4", size = 217450, upload-time = "2025-08-27T12:12:44.813Z" }, - { url = "https://files.pythonhosted.org/packages/75/3d/6bef47b0e253616ccdf67c283e25f2d16e18ccddd38f92af81d5a3420206/rpds_py-0.27.1-cp310-cp310-win_amd64.whl", hash = "sha256:3e039aabf6d5f83c745d5f9a0a381d031e9ed871967c0a5c38d201aca41f3ba1", size = 228447, upload-time = "2025-08-27T12:12:46.204Z" }, - { url = "https://files.pythonhosted.org/packages/b5/c1/7907329fbef97cbd49db6f7303893bd1dd5a4a3eae415839ffdfb0762cae/rpds_py-0.27.1-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:be898f271f851f68b318872ce6ebebbc62f303b654e43bf72683dbdc25b7c881", size = 371063, upload-time = "2025-08-27T12:12:47.856Z" }, - { url = "https://files.pythonhosted.org/packages/11/94/2aab4bc86228bcf7c48760990273653a4900de89c7537ffe1b0d6097ed39/rpds_py-0.27.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:62ac3d4e3e07b58ee0ddecd71d6ce3b1637de2d373501412df395a0ec5f9beb5", size = 353210, upload-time = "2025-08-27T12:12:49.187Z" }, - { url = "https://files.pythonhosted.org/packages/3a/57/f5eb3ecf434342f4f1a46009530e93fd201a0b5b83379034ebdb1d7c1a58/rpds_py-0.27.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4708c5c0ceb2d034f9991623631d3d23cb16e65c83736ea020cdbe28d57c0a0e", size = 381636, upload-time = "2025-08-27T12:12:50.492Z" }, - { url = "https://files.pythonhosted.org/packages/ae/f4/ef95c5945e2ceb5119571b184dd5a1cc4b8541bbdf67461998cfeac9cb1e/rpds_py-0.27.1-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:abfa1171a9952d2e0002aba2ad3780820b00cc3d9c98c6630f2e93271501f66c", size = 394341, upload-time = "2025-08-27T12:12:52.024Z" }, - { url = "https://files.pythonhosted.org/packages/5a/7e/4bd610754bf492d398b61725eb9598ddd5eb86b07d7d9483dbcd810e20bc/rpds_py-0.27.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4b507d19f817ebaca79574b16eb2ae412e5c0835542c93fe9983f1e432aca195", size = 523428, upload-time = "2025-08-27T12:12:53.779Z" }, - { url = "https://files.pythonhosted.org/packages/9f/e5/059b9f65a8c9149361a8b75094864ab83b94718344db511fd6117936ed2a/rpds_py-0.27.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:168b025f8fd8d8d10957405f3fdcef3dc20f5982d398f90851f4abc58c566c52", size = 402923, upload-time = "2025-08-27T12:12:55.15Z" }, - { url = "https://files.pythonhosted.org/packages/f5/48/64cabb7daced2968dd08e8a1b7988bf358d7bd5bcd5dc89a652f4668543c/rpds_py-0.27.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cb56c6210ef77caa58e16e8c17d35c63fe3f5b60fd9ba9d424470c3400bcf9ed", size = 384094, upload-time = "2025-08-27T12:12:57.194Z" }, - { url = "https://files.pythonhosted.org/packages/ae/e1/dc9094d6ff566bff87add8a510c89b9e158ad2ecd97ee26e677da29a9e1b/rpds_py-0.27.1-cp311-cp311-manylinux_2_31_riscv64.whl", hash = "sha256:d252f2d8ca0195faa707f8eb9368955760880b2b42a8ee16d382bf5dd807f89a", size = 401093, upload-time = "2025-08-27T12:12:58.985Z" }, - { url = "https://files.pythonhosted.org/packages/37/8e/ac8577e3ecdd5593e283d46907d7011618994e1d7ab992711ae0f78b9937/rpds_py-0.27.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:6e5e54da1e74b91dbc7996b56640f79b195d5925c2b78efaa8c5d53e1d88edde", size = 417969, upload-time = "2025-08-27T12:13:00.367Z" }, - { url = "https://files.pythonhosted.org/packages/66/6d/87507430a8f74a93556fe55c6485ba9c259949a853ce407b1e23fea5ba31/rpds_py-0.27.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:ffce0481cc6e95e5b3f0a47ee17ffbd234399e6d532f394c8dce320c3b089c21", size = 558302, upload-time = "2025-08-27T12:13:01.737Z" }, - { url = "https://files.pythonhosted.org/packages/3a/bb/1db4781ce1dda3eecc735e3152659a27b90a02ca62bfeea17aee45cc0fbc/rpds_py-0.27.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:a205fdfe55c90c2cd8e540ca9ceba65cbe6629b443bc05db1f590a3db8189ff9", size = 589259, upload-time = "2025-08-27T12:13:03.127Z" }, - { url = "https://files.pythonhosted.org/packages/7b/0e/ae1c8943d11a814d01b482e1f8da903f88047a962dff9bbdadf3bd6e6fd1/rpds_py-0.27.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:689fb5200a749db0415b092972e8eba85847c23885c8543a8b0f5c009b1a5948", size = 554983, upload-time = "2025-08-27T12:13:04.516Z" }, - { url = "https://files.pythonhosted.org/packages/b2/d5/0b2a55415931db4f112bdab072443ff76131b5ac4f4dc98d10d2d357eb03/rpds_py-0.27.1-cp311-cp311-win32.whl", hash = "sha256:3182af66048c00a075010bc7f4860f33913528a4b6fc09094a6e7598e462fe39", size = 217154, upload-time = "2025-08-27T12:13:06.278Z" }, - { url = "https://files.pythonhosted.org/packages/24/75/3b7ffe0d50dc86a6a964af0d1cc3a4a2cdf437cb7b099a4747bbb96d1819/rpds_py-0.27.1-cp311-cp311-win_amd64.whl", hash = "sha256:b4938466c6b257b2f5c4ff98acd8128ec36b5059e5c8f8372d79316b1c36bb15", size = 228627, upload-time = "2025-08-27T12:13:07.625Z" }, - { url = "https://files.pythonhosted.org/packages/8d/3f/4fd04c32abc02c710f09a72a30c9a55ea3cc154ef8099078fd50a0596f8e/rpds_py-0.27.1-cp311-cp311-win_arm64.whl", hash = "sha256:2f57af9b4d0793e53266ee4325535a31ba48e2f875da81a9177c9926dfa60746", size = 220998, upload-time = "2025-08-27T12:13:08.972Z" }, - { url = "https://files.pythonhosted.org/packages/bd/fe/38de28dee5df58b8198c743fe2bea0c785c6d40941b9950bac4cdb71a014/rpds_py-0.27.1-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:ae2775c1973e3c30316892737b91f9283f9908e3cc7625b9331271eaaed7dc90", size = 361887, upload-time = "2025-08-27T12:13:10.233Z" }, - { url = "https://files.pythonhosted.org/packages/7c/9a/4b6c7eedc7dd90986bf0fab6ea2a091ec11c01b15f8ba0a14d3f80450468/rpds_py-0.27.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2643400120f55c8a96f7c9d858f7be0c88d383cd4653ae2cf0d0c88f668073e5", size = 345795, upload-time = "2025-08-27T12:13:11.65Z" }, - { url = "https://files.pythonhosted.org/packages/6f/0e/e650e1b81922847a09cca820237b0edee69416a01268b7754d506ade11ad/rpds_py-0.27.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:16323f674c089b0360674a4abd28d5042947d54ba620f72514d69be4ff64845e", size = 385121, upload-time = "2025-08-27T12:13:13.008Z" }, - { url = "https://files.pythonhosted.org/packages/1b/ea/b306067a712988e2bff00dcc7c8f31d26c29b6d5931b461aa4b60a013e33/rpds_py-0.27.1-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:9a1f4814b65eacac94a00fc9a526e3fdafd78e439469644032032d0d63de4881", size = 398976, upload-time = "2025-08-27T12:13:14.368Z" }, - { url = "https://files.pythonhosted.org/packages/2c/0a/26dc43c8840cb8fe239fe12dbc8d8de40f2365e838f3d395835dde72f0e5/rpds_py-0.27.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7ba32c16b064267b22f1850a34051121d423b6f7338a12b9459550eb2096e7ec", size = 525953, upload-time = "2025-08-27T12:13:15.774Z" }, - { url = "https://files.pythonhosted.org/packages/22/14/c85e8127b573aaf3a0cbd7fbb8c9c99e735a4a02180c84da2a463b766e9e/rpds_py-0.27.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e5c20f33fd10485b80f65e800bbe5f6785af510b9f4056c5a3c612ebc83ba6cb", size = 407915, upload-time = "2025-08-27T12:13:17.379Z" }, - { url = "https://files.pythonhosted.org/packages/ed/7b/8f4fee9ba1fb5ec856eb22d725a4efa3deb47f769597c809e03578b0f9d9/rpds_py-0.27.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:466bfe65bd932da36ff279ddd92de56b042f2266d752719beb97b08526268ec5", size = 386883, upload-time = "2025-08-27T12:13:18.704Z" }, - { url = "https://files.pythonhosted.org/packages/86/47/28fa6d60f8b74fcdceba81b272f8d9836ac0340570f68f5df6b41838547b/rpds_py-0.27.1-cp312-cp312-manylinux_2_31_riscv64.whl", hash = "sha256:41e532bbdcb57c92ba3be62c42e9f096431b4cf478da9bc3bc6ce5c38ab7ba7a", size = 405699, upload-time = "2025-08-27T12:13:20.089Z" }, - { url = "https://files.pythonhosted.org/packages/d0/fd/c5987b5e054548df56953a21fe2ebed51fc1ec7c8f24fd41c067b68c4a0a/rpds_py-0.27.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:f149826d742b406579466283769a8ea448eed82a789af0ed17b0cd5770433444", size = 423713, upload-time = "2025-08-27T12:13:21.436Z" }, - { url = "https://files.pythonhosted.org/packages/ac/ba/3c4978b54a73ed19a7d74531be37a8bcc542d917c770e14d372b8daea186/rpds_py-0.27.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:80c60cfb5310677bd67cb1e85a1e8eb52e12529545441b43e6f14d90b878775a", size = 562324, upload-time = "2025-08-27T12:13:22.789Z" }, - { url = "https://files.pythonhosted.org/packages/b5/6c/6943a91768fec16db09a42b08644b960cff540c66aab89b74be6d4a144ba/rpds_py-0.27.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:7ee6521b9baf06085f62ba9c7a3e5becffbc32480d2f1b351559c001c38ce4c1", size = 593646, upload-time = "2025-08-27T12:13:24.122Z" }, - { url = "https://files.pythonhosted.org/packages/11/73/9d7a8f4be5f4396f011a6bb7a19fe26303a0dac9064462f5651ced2f572f/rpds_py-0.27.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:a512c8263249a9d68cac08b05dd59d2b3f2061d99b322813cbcc14c3c7421998", size = 558137, upload-time = "2025-08-27T12:13:25.557Z" }, - { url = "https://files.pythonhosted.org/packages/6e/96/6772cbfa0e2485bcceef8071de7821f81aeac8bb45fbfd5542a3e8108165/rpds_py-0.27.1-cp312-cp312-win32.whl", hash = "sha256:819064fa048ba01b6dadc5116f3ac48610435ac9a0058bbde98e569f9e785c39", size = 221343, upload-time = "2025-08-27T12:13:26.967Z" }, - { url = "https://files.pythonhosted.org/packages/67/b6/c82f0faa9af1c6a64669f73a17ee0eeef25aff30bb9a1c318509efe45d84/rpds_py-0.27.1-cp312-cp312-win_amd64.whl", hash = "sha256:d9199717881f13c32c4046a15f024971a3b78ad4ea029e8da6b86e5aa9cf4594", size = 232497, upload-time = "2025-08-27T12:13:28.326Z" }, - { url = "https://files.pythonhosted.org/packages/e1/96/2817b44bd2ed11aebacc9251da03689d56109b9aba5e311297b6902136e2/rpds_py-0.27.1-cp312-cp312-win_arm64.whl", hash = "sha256:33aa65b97826a0e885ef6e278fbd934e98cdcfed80b63946025f01e2f5b29502", size = 222790, upload-time = "2025-08-27T12:13:29.71Z" }, - { url = "https://files.pythonhosted.org/packages/cc/77/610aeee8d41e39080c7e14afa5387138e3c9fa9756ab893d09d99e7d8e98/rpds_py-0.27.1-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:e4b9fcfbc021633863a37e92571d6f91851fa656f0180246e84cbd8b3f6b329b", size = 361741, upload-time = "2025-08-27T12:13:31.039Z" }, - { url = "https://files.pythonhosted.org/packages/3a/fc/c43765f201c6a1c60be2043cbdb664013def52460a4c7adace89d6682bf4/rpds_py-0.27.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:1441811a96eadca93c517d08df75de45e5ffe68aa3089924f963c782c4b898cf", size = 345574, upload-time = "2025-08-27T12:13:32.902Z" }, - { url = "https://files.pythonhosted.org/packages/20/42/ee2b2ca114294cd9847d0ef9c26d2b0851b2e7e00bf14cc4c0b581df0fc3/rpds_py-0.27.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:55266dafa22e672f5a4f65019015f90336ed31c6383bd53f5e7826d21a0e0b83", size = 385051, upload-time = "2025-08-27T12:13:34.228Z" }, - { url = "https://files.pythonhosted.org/packages/fd/e8/1e430fe311e4799e02e2d1af7c765f024e95e17d651612425b226705f910/rpds_py-0.27.1-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d78827d7ac08627ea2c8e02c9e5b41180ea5ea1f747e9db0915e3adf36b62dcf", size = 398395, upload-time = "2025-08-27T12:13:36.132Z" }, - { url = "https://files.pythonhosted.org/packages/82/95/9dc227d441ff2670651c27a739acb2535ccaf8b351a88d78c088965e5996/rpds_py-0.27.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ae92443798a40a92dc5f0b01d8a7c93adde0c4dc965310a29ae7c64d72b9fad2", size = 524334, upload-time = "2025-08-27T12:13:37.562Z" }, - { url = "https://files.pythonhosted.org/packages/87/01/a670c232f401d9ad461d9a332aa4080cd3cb1d1df18213dbd0d2a6a7ab51/rpds_py-0.27.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c46c9dd2403b66a2a3b9720ec4b74d4ab49d4fabf9f03dfdce2d42af913fe8d0", size = 407691, upload-time = "2025-08-27T12:13:38.94Z" }, - { url = "https://files.pythonhosted.org/packages/03/36/0a14aebbaa26fe7fab4780c76f2239e76cc95a0090bdb25e31d95c492fcd/rpds_py-0.27.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2efe4eb1d01b7f5f1939f4ef30ecea6c6b3521eec451fb93191bf84b2a522418", size = 386868, upload-time = "2025-08-27T12:13:40.192Z" }, - { url = "https://files.pythonhosted.org/packages/3b/03/8c897fb8b5347ff6c1cc31239b9611c5bf79d78c984430887a353e1409a1/rpds_py-0.27.1-cp313-cp313-manylinux_2_31_riscv64.whl", hash = "sha256:15d3b4d83582d10c601f481eca29c3f138d44c92187d197aff663a269197c02d", size = 405469, upload-time = "2025-08-27T12:13:41.496Z" }, - { url = "https://files.pythonhosted.org/packages/da/07/88c60edc2df74850d496d78a1fdcdc7b54360a7f610a4d50008309d41b94/rpds_py-0.27.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:4ed2e16abbc982a169d30d1a420274a709949e2cbdef119fe2ec9d870b42f274", size = 422125, upload-time = "2025-08-27T12:13:42.802Z" }, - { url = "https://files.pythonhosted.org/packages/6b/86/5f4c707603e41b05f191a749984f390dabcbc467cf833769b47bf14ba04f/rpds_py-0.27.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:a75f305c9b013289121ec0f1181931975df78738cdf650093e6b86d74aa7d8dd", size = 562341, upload-time = "2025-08-27T12:13:44.472Z" }, - { url = "https://files.pythonhosted.org/packages/b2/92/3c0cb2492094e3cd9baf9e49bbb7befeceb584ea0c1a8b5939dca4da12e5/rpds_py-0.27.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:67ce7620704745881a3d4b0ada80ab4d99df390838839921f99e63c474f82cf2", size = 592511, upload-time = "2025-08-27T12:13:45.898Z" }, - { url = "https://files.pythonhosted.org/packages/10/bb/82e64fbb0047c46a168faa28d0d45a7851cd0582f850b966811d30f67ad8/rpds_py-0.27.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:9d992ac10eb86d9b6f369647b6a3f412fc0075cfd5d799530e84d335e440a002", size = 557736, upload-time = "2025-08-27T12:13:47.408Z" }, - { url = "https://files.pythonhosted.org/packages/00/95/3c863973d409210da7fb41958172c6b7dbe7fc34e04d3cc1f10bb85e979f/rpds_py-0.27.1-cp313-cp313-win32.whl", hash = "sha256:4f75e4bd8ab8db624e02c8e2fc4063021b58becdbe6df793a8111d9343aec1e3", size = 221462, upload-time = "2025-08-27T12:13:48.742Z" }, - { url = "https://files.pythonhosted.org/packages/ce/2c/5867b14a81dc217b56d95a9f2a40fdbc56a1ab0181b80132beeecbd4b2d6/rpds_py-0.27.1-cp313-cp313-win_amd64.whl", hash = "sha256:f9025faafc62ed0b75a53e541895ca272815bec18abe2249ff6501c8f2e12b83", size = 232034, upload-time = "2025-08-27T12:13:50.11Z" }, - { url = "https://files.pythonhosted.org/packages/c7/78/3958f3f018c01923823f1e47f1cc338e398814b92d83cd278364446fac66/rpds_py-0.27.1-cp313-cp313-win_arm64.whl", hash = "sha256:ed10dc32829e7d222b7d3b93136d25a406ba9788f6a7ebf6809092da1f4d279d", size = 222392, upload-time = "2025-08-27T12:13:52.587Z" }, - { url = "https://files.pythonhosted.org/packages/01/76/1cdf1f91aed5c3a7bf2eba1f1c4e4d6f57832d73003919a20118870ea659/rpds_py-0.27.1-cp313-cp313t-macosx_10_12_x86_64.whl", hash = "sha256:92022bbbad0d4426e616815b16bc4127f83c9a74940e1ccf3cfe0b387aba0228", size = 358355, upload-time = "2025-08-27T12:13:54.012Z" }, - { url = "https://files.pythonhosted.org/packages/c3/6f/bf142541229374287604caf3bb2a4ae17f0a580798fd72d3b009b532db4e/rpds_py-0.27.1-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:47162fdab9407ec3f160805ac3e154df042e577dd53341745fc7fb3f625e6d92", size = 342138, upload-time = "2025-08-27T12:13:55.791Z" }, - { url = "https://files.pythonhosted.org/packages/1a/77/355b1c041d6be40886c44ff5e798b4e2769e497b790f0f7fd1e78d17e9a8/rpds_py-0.27.1-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fb89bec23fddc489e5d78b550a7b773557c9ab58b7946154a10a6f7a214a48b2", size = 380247, upload-time = "2025-08-27T12:13:57.683Z" }, - { url = "https://files.pythonhosted.org/packages/d6/a4/d9cef5c3946ea271ce2243c51481971cd6e34f21925af2783dd17b26e815/rpds_py-0.27.1-cp313-cp313t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e48af21883ded2b3e9eb48cb7880ad8598b31ab752ff3be6457001d78f416723", size = 390699, upload-time = "2025-08-27T12:13:59.137Z" }, - { url = "https://files.pythonhosted.org/packages/3a/06/005106a7b8c6c1a7e91b73169e49870f4af5256119d34a361ae5240a0c1d/rpds_py-0.27.1-cp313-cp313t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6f5b7bd8e219ed50299e58551a410b64daafb5017d54bbe822e003856f06a802", size = 521852, upload-time = "2025-08-27T12:14:00.583Z" }, - { url = "https://files.pythonhosted.org/packages/e5/3e/50fb1dac0948e17a02eb05c24510a8fe12d5ce8561c6b7b7d1339ab7ab9c/rpds_py-0.27.1-cp313-cp313t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:08f1e20bccf73b08d12d804d6e1c22ca5530e71659e6673bce31a6bb71c1e73f", size = 402582, upload-time = "2025-08-27T12:14:02.034Z" }, - { url = "https://files.pythonhosted.org/packages/cb/b0/f4e224090dc5b0ec15f31a02d746ab24101dd430847c4d99123798661bfc/rpds_py-0.27.1-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0dc5dceeaefcc96dc192e3a80bbe1d6c410c469e97bdd47494a7d930987f18b2", size = 384126, upload-time = "2025-08-27T12:14:03.437Z" }, - { url = "https://files.pythonhosted.org/packages/54/77/ac339d5f82b6afff1df8f0fe0d2145cc827992cb5f8eeb90fc9f31ef7a63/rpds_py-0.27.1-cp313-cp313t-manylinux_2_31_riscv64.whl", hash = "sha256:d76f9cc8665acdc0c9177043746775aa7babbf479b5520b78ae4002d889f5c21", size = 399486, upload-time = "2025-08-27T12:14:05.443Z" }, - { url = "https://files.pythonhosted.org/packages/d6/29/3e1c255eee6ac358c056a57d6d6869baa00a62fa32eea5ee0632039c50a3/rpds_py-0.27.1-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:134fae0e36022edad8290a6661edf40c023562964efea0cc0ec7f5d392d2aaef", size = 414832, upload-time = "2025-08-27T12:14:06.902Z" }, - { url = "https://files.pythonhosted.org/packages/3f/db/6d498b844342deb3fa1d030598db93937a9964fcf5cb4da4feb5f17be34b/rpds_py-0.27.1-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:eb11a4f1b2b63337cfd3b4d110af778a59aae51c81d195768e353d8b52f88081", size = 557249, upload-time = "2025-08-27T12:14:08.37Z" }, - { url = "https://files.pythonhosted.org/packages/60/f3/690dd38e2310b6f68858a331399b4d6dbb9132c3e8ef8b4333b96caf403d/rpds_py-0.27.1-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:13e608ac9f50a0ed4faec0e90ece76ae33b34c0e8656e3dceb9a7db994c692cd", size = 587356, upload-time = "2025-08-27T12:14:10.034Z" }, - { url = "https://files.pythonhosted.org/packages/86/e3/84507781cccd0145f35b1dc32c72675200c5ce8d5b30f813e49424ef68fc/rpds_py-0.27.1-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:dd2135527aa40f061350c3f8f89da2644de26cd73e4de458e79606384f4f68e7", size = 555300, upload-time = "2025-08-27T12:14:11.783Z" }, - { url = "https://files.pythonhosted.org/packages/e5/ee/375469849e6b429b3516206b4580a79e9ef3eb12920ddbd4492b56eaacbe/rpds_py-0.27.1-cp313-cp313t-win32.whl", hash = "sha256:3020724ade63fe320a972e2ffd93b5623227e684315adce194941167fee02688", size = 216714, upload-time = "2025-08-27T12:14:13.629Z" }, - { url = "https://files.pythonhosted.org/packages/21/87/3fc94e47c9bd0742660e84706c311a860dcae4374cf4a03c477e23ce605a/rpds_py-0.27.1-cp313-cp313t-win_amd64.whl", hash = "sha256:8ee50c3e41739886606388ba3ab3ee2aae9f35fb23f833091833255a31740797", size = 228943, upload-time = "2025-08-27T12:14:14.937Z" }, - { url = "https://files.pythonhosted.org/packages/70/36/b6e6066520a07cf029d385de869729a895917b411e777ab1cde878100a1d/rpds_py-0.27.1-cp314-cp314-macosx_10_12_x86_64.whl", hash = "sha256:acb9aafccaae278f449d9c713b64a9e68662e7799dbd5859e2c6b3c67b56d334", size = 362472, upload-time = "2025-08-27T12:14:16.333Z" }, - { url = "https://files.pythonhosted.org/packages/af/07/b4646032e0dcec0df9c73a3bd52f63bc6c5f9cda992f06bd0e73fe3fbebd/rpds_py-0.27.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:b7fb801aa7f845ddf601c49630deeeccde7ce10065561d92729bfe81bd21fb33", size = 345676, upload-time = "2025-08-27T12:14:17.764Z" }, - { url = "https://files.pythonhosted.org/packages/b0/16/2f1003ee5d0af4bcb13c0cf894957984c32a6751ed7206db2aee7379a55e/rpds_py-0.27.1-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fe0dd05afb46597b9a2e11c351e5e4283c741237e7f617ffb3252780cca9336a", size = 385313, upload-time = "2025-08-27T12:14:19.829Z" }, - { url = "https://files.pythonhosted.org/packages/05/cd/7eb6dd7b232e7f2654d03fa07f1414d7dfc980e82ba71e40a7c46fd95484/rpds_py-0.27.1-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:b6dfb0e058adb12d8b1d1b25f686e94ffa65d9995a5157afe99743bf7369d62b", size = 399080, upload-time = "2025-08-27T12:14:21.531Z" }, - { url = "https://files.pythonhosted.org/packages/20/51/5829afd5000ec1cb60f304711f02572d619040aa3ec033d8226817d1e571/rpds_py-0.27.1-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ed090ccd235f6fa8bb5861684567f0a83e04f52dfc2e5c05f2e4b1309fcf85e7", size = 523868, upload-time = "2025-08-27T12:14:23.485Z" }, - { url = "https://files.pythonhosted.org/packages/05/2c/30eebca20d5db95720ab4d2faec1b5e4c1025c473f703738c371241476a2/rpds_py-0.27.1-cp314-cp314-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:bf876e79763eecf3e7356f157540d6a093cef395b65514f17a356f62af6cc136", size = 408750, upload-time = "2025-08-27T12:14:24.924Z" }, - { url = "https://files.pythonhosted.org/packages/90/1a/cdb5083f043597c4d4276eae4e4c70c55ab5accec078da8611f24575a367/rpds_py-0.27.1-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:12ed005216a51b1d6e2b02a7bd31885fe317e45897de81d86dcce7d74618ffff", size = 387688, upload-time = "2025-08-27T12:14:27.537Z" }, - { url = "https://files.pythonhosted.org/packages/7c/92/cf786a15320e173f945d205ab31585cc43969743bb1a48b6888f7a2b0a2d/rpds_py-0.27.1-cp314-cp314-manylinux_2_31_riscv64.whl", hash = "sha256:ee4308f409a40e50593c7e3bb8cbe0b4d4c66d1674a316324f0c2f5383b486f9", size = 407225, upload-time = "2025-08-27T12:14:28.981Z" }, - { url = "https://files.pythonhosted.org/packages/33/5c/85ee16df5b65063ef26017bef33096557a4c83fbe56218ac7cd8c235f16d/rpds_py-0.27.1-cp314-cp314-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:0b08d152555acf1f455154d498ca855618c1378ec810646fcd7c76416ac6dc60", size = 423361, upload-time = "2025-08-27T12:14:30.469Z" }, - { url = "https://files.pythonhosted.org/packages/4b/8e/1c2741307fcabd1a334ecf008e92c4f47bb6f848712cf15c923becfe82bb/rpds_py-0.27.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:dce51c828941973a5684d458214d3a36fcd28da3e1875d659388f4f9f12cc33e", size = 562493, upload-time = "2025-08-27T12:14:31.987Z" }, - { url = "https://files.pythonhosted.org/packages/04/03/5159321baae9b2222442a70c1f988cbbd66b9be0675dd3936461269be360/rpds_py-0.27.1-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:c1476d6f29eb81aa4151c9a31219b03f1f798dc43d8af1250a870735516a1212", size = 592623, upload-time = "2025-08-27T12:14:33.543Z" }, - { url = "https://files.pythonhosted.org/packages/ff/39/c09fd1ad28b85bc1d4554a8710233c9f4cefd03d7717a1b8fbfd171d1167/rpds_py-0.27.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:3ce0cac322b0d69b63c9cdb895ee1b65805ec9ffad37639f291dd79467bee675", size = 558800, upload-time = "2025-08-27T12:14:35.436Z" }, - { url = "https://files.pythonhosted.org/packages/c5/d6/99228e6bbcf4baa764b18258f519a9035131d91b538d4e0e294313462a98/rpds_py-0.27.1-cp314-cp314-win32.whl", hash = "sha256:dfbfac137d2a3d0725758cd141f878bf4329ba25e34979797c89474a89a8a3a3", size = 221943, upload-time = "2025-08-27T12:14:36.898Z" }, - { url = "https://files.pythonhosted.org/packages/be/07/c802bc6b8e95be83b79bdf23d1aa61d68324cb1006e245d6c58e959e314d/rpds_py-0.27.1-cp314-cp314-win_amd64.whl", hash = "sha256:a6e57b0abfe7cc513450fcf529eb486b6e4d3f8aee83e92eb5f1ef848218d456", size = 233739, upload-time = "2025-08-27T12:14:38.386Z" }, - { url = "https://files.pythonhosted.org/packages/c8/89/3e1b1c16d4c2d547c5717377a8df99aee8099ff050f87c45cb4d5fa70891/rpds_py-0.27.1-cp314-cp314-win_arm64.whl", hash = "sha256:faf8d146f3d476abfee026c4ae3bdd9ca14236ae4e4c310cbd1cf75ba33d24a3", size = 223120, upload-time = "2025-08-27T12:14:39.82Z" }, - { url = "https://files.pythonhosted.org/packages/62/7e/dc7931dc2fa4a6e46b2a4fa744a9fe5c548efd70e0ba74f40b39fa4a8c10/rpds_py-0.27.1-cp314-cp314t-macosx_10_12_x86_64.whl", hash = "sha256:ba81d2b56b6d4911ce735aad0a1d4495e808b8ee4dc58715998741a26874e7c2", size = 358944, upload-time = "2025-08-27T12:14:41.199Z" }, - { url = "https://files.pythonhosted.org/packages/e6/22/4af76ac4e9f336bfb1a5f240d18a33c6b2fcaadb7472ac7680576512b49a/rpds_py-0.27.1-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:84f7d509870098de0e864cad0102711c1e24e9b1a50ee713b65928adb22269e4", size = 342283, upload-time = "2025-08-27T12:14:42.699Z" }, - { url = "https://files.pythonhosted.org/packages/1c/15/2a7c619b3c2272ea9feb9ade67a45c40b3eeb500d503ad4c28c395dc51b4/rpds_py-0.27.1-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a9e960fc78fecd1100539f14132425e1d5fe44ecb9239f8f27f079962021523e", size = 380320, upload-time = "2025-08-27T12:14:44.157Z" }, - { url = "https://files.pythonhosted.org/packages/a2/7d/4c6d243ba4a3057e994bb5bedd01b5c963c12fe38dde707a52acdb3849e7/rpds_py-0.27.1-cp314-cp314t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:62f85b665cedab1a503747617393573995dac4600ff51869d69ad2f39eb5e817", size = 391760, upload-time = "2025-08-27T12:14:45.845Z" }, - { url = "https://files.pythonhosted.org/packages/b4/71/b19401a909b83bcd67f90221330bc1ef11bc486fe4e04c24388d28a618ae/rpds_py-0.27.1-cp314-cp314t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:fed467af29776f6556250c9ed85ea5a4dd121ab56a5f8b206e3e7a4c551e48ec", size = 522476, upload-time = "2025-08-27T12:14:47.364Z" }, - { url = "https://files.pythonhosted.org/packages/e4/44/1a3b9715c0455d2e2f0f6df5ee6d6f5afdc423d0773a8a682ed2b43c566c/rpds_py-0.27.1-cp314-cp314t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f2729615f9d430af0ae6b36cf042cb55c0936408d543fb691e1a9e36648fd35a", size = 403418, upload-time = "2025-08-27T12:14:49.991Z" }, - { url = "https://files.pythonhosted.org/packages/1c/4b/fb6c4f14984eb56673bc868a66536f53417ddb13ed44b391998100a06a96/rpds_py-0.27.1-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1b207d881a9aef7ba753d69c123a35d96ca7cb808056998f6b9e8747321f03b8", size = 384771, upload-time = "2025-08-27T12:14:52.159Z" }, - { url = "https://files.pythonhosted.org/packages/c0/56/d5265d2d28b7420d7b4d4d85cad8ef891760f5135102e60d5c970b976e41/rpds_py-0.27.1-cp314-cp314t-manylinux_2_31_riscv64.whl", hash = "sha256:639fd5efec029f99b79ae47e5d7e00ad8a773da899b6309f6786ecaf22948c48", size = 400022, upload-time = "2025-08-27T12:14:53.859Z" }, - { url = "https://files.pythonhosted.org/packages/8f/e9/9f5fc70164a569bdd6ed9046486c3568d6926e3a49bdefeeccfb18655875/rpds_py-0.27.1-cp314-cp314t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:fecc80cb2a90e28af8a9b366edacf33d7a91cbfe4c2c4544ea1246e949cfebeb", size = 416787, upload-time = "2025-08-27T12:14:55.673Z" }, - { url = "https://files.pythonhosted.org/packages/d4/64/56dd03430ba491db943a81dcdef115a985aac5f44f565cd39a00c766d45c/rpds_py-0.27.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:42a89282d711711d0a62d6f57d81aa43a1368686c45bc1c46b7f079d55692734", size = 557538, upload-time = "2025-08-27T12:14:57.245Z" }, - { url = "https://files.pythonhosted.org/packages/3f/36/92cc885a3129993b1d963a2a42ecf64e6a8e129d2c7cc980dbeba84e55fb/rpds_py-0.27.1-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:cf9931f14223de59551ab9d38ed18d92f14f055a5f78c1d8ad6493f735021bbb", size = 588512, upload-time = "2025-08-27T12:14:58.728Z" }, - { url = "https://files.pythonhosted.org/packages/dd/10/6b283707780a81919f71625351182b4f98932ac89a09023cb61865136244/rpds_py-0.27.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:f39f58a27cc6e59f432b568ed8429c7e1641324fbe38131de852cd77b2d534b0", size = 555813, upload-time = "2025-08-27T12:15:00.334Z" }, - { url = "https://files.pythonhosted.org/packages/04/2e/30b5ea18c01379da6272a92825dd7e53dc9d15c88a19e97932d35d430ef7/rpds_py-0.27.1-cp314-cp314t-win32.whl", hash = "sha256:d5fa0ee122dc09e23607a28e6d7b150da16c662e66409bbe85230e4c85bb528a", size = 217385, upload-time = "2025-08-27T12:15:01.937Z" }, - { url = "https://files.pythonhosted.org/packages/32/7d/97119da51cb1dd3f2f3c0805f155a3aa4a95fa44fe7d78ae15e69edf4f34/rpds_py-0.27.1-cp314-cp314t-win_amd64.whl", hash = "sha256:6567d2bb951e21232c2f660c24cf3470bb96de56cdcb3f071a83feeaff8a2772", size = 230097, upload-time = "2025-08-27T12:15:03.961Z" }, - { url = "https://files.pythonhosted.org/packages/d5/63/b7cc415c345625d5e62f694ea356c58fb964861409008118f1245f8c3347/rpds_py-0.27.1-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:7ba22cb9693df986033b91ae1d7a979bc399237d45fccf875b76f62bb9e52ddf", size = 371360, upload-time = "2025-08-27T12:15:29.218Z" }, - { url = "https://files.pythonhosted.org/packages/e5/8c/12e1b24b560cf378b8ffbdb9dc73abd529e1adcfcf82727dfd29c4a7b88d/rpds_py-0.27.1-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:5b640501be9288c77738b5492b3fd3abc4ba95c50c2e41273c8a1459f08298d3", size = 353933, upload-time = "2025-08-27T12:15:30.837Z" }, - { url = "https://files.pythonhosted.org/packages/9b/85/1bb2210c1f7a1b99e91fea486b9f0f894aa5da3a5ec7097cbad7dec6d40f/rpds_py-0.27.1-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fb08b65b93e0c6dd70aac7f7890a9c0938d5ec71d5cb32d45cf844fb8ae47636", size = 382962, upload-time = "2025-08-27T12:15:32.348Z" }, - { url = "https://files.pythonhosted.org/packages/cc/c9/a839b9f219cf80ed65f27a7f5ddbb2809c1b85c966020ae2dff490e0b18e/rpds_py-0.27.1-pp310-pypy310_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d7ff07d696a7a38152ebdb8212ca9e5baab56656749f3d6004b34ab726b550b8", size = 394412, upload-time = "2025-08-27T12:15:33.839Z" }, - { url = "https://files.pythonhosted.org/packages/02/2d/b1d7f928b0b1f4fc2e0133e8051d199b01d7384875adc63b6ddadf3de7e5/rpds_py-0.27.1-pp310-pypy310_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:fb7c72262deae25366e3b6c0c0ba46007967aea15d1eea746e44ddba8ec58dcc", size = 523972, upload-time = "2025-08-27T12:15:35.377Z" }, - { url = "https://files.pythonhosted.org/packages/a9/af/2cbf56edd2d07716df1aec8a726b3159deb47cb5c27e1e42b71d705a7c2f/rpds_py-0.27.1-pp310-pypy310_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7b002cab05d6339716b03a4a3a2ce26737f6231d7b523f339fa061d53368c9d8", size = 403273, upload-time = "2025-08-27T12:15:37.051Z" }, - { url = "https://files.pythonhosted.org/packages/c0/93/425e32200158d44ff01da5d9612c3b6711fe69f606f06e3895511f17473b/rpds_py-0.27.1-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:23f6b69d1c26c4704fec01311963a41d7de3ee0570a84ebde4d544e5a1859ffc", size = 385278, upload-time = "2025-08-27T12:15:38.571Z" }, - { url = "https://files.pythonhosted.org/packages/eb/1a/1a04a915ecd0551bfa9e77b7672d1937b4b72a0fc204a17deef76001cfb2/rpds_py-0.27.1-pp310-pypy310_pp73-manylinux_2_31_riscv64.whl", hash = "sha256:530064db9146b247351f2a0250b8f00b289accea4596a033e94be2389977de71", size = 402084, upload-time = "2025-08-27T12:15:40.529Z" }, - { url = "https://files.pythonhosted.org/packages/51/f7/66585c0fe5714368b62951d2513b684e5215beaceab2c6629549ddb15036/rpds_py-0.27.1-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:7b90b0496570bd6b0321724a330d8b545827c4df2034b6ddfc5f5275f55da2ad", size = 419041, upload-time = "2025-08-27T12:15:42.191Z" }, - { url = "https://files.pythonhosted.org/packages/8e/7e/83a508f6b8e219bba2d4af077c35ba0e0cdd35a751a3be6a7cba5a55ad71/rpds_py-0.27.1-pp310-pypy310_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:879b0e14a2da6a1102a3fc8af580fc1ead37e6d6692a781bd8c83da37429b5ab", size = 560084, upload-time = "2025-08-27T12:15:43.839Z" }, - { url = "https://files.pythonhosted.org/packages/66/66/bb945683b958a1b19eb0fe715594630d0f36396ebdef4d9b89c2fa09aa56/rpds_py-0.27.1-pp310-pypy310_pp73-musllinux_1_2_i686.whl", hash = "sha256:0d807710df3b5faa66c731afa162ea29717ab3be17bdc15f90f2d9f183da4059", size = 590115, upload-time = "2025-08-27T12:15:46.647Z" }, - { url = "https://files.pythonhosted.org/packages/12/00/ccfaafaf7db7e7adace915e5c2f2c2410e16402561801e9c7f96683002d3/rpds_py-0.27.1-pp310-pypy310_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:3adc388fc3afb6540aec081fa59e6e0d3908722771aa1e37ffe22b220a436f0b", size = 556561, upload-time = "2025-08-27T12:15:48.219Z" }, - { url = "https://files.pythonhosted.org/packages/e1/b7/92b6ed9aad103bfe1c45df98453dfae40969eef2cb6c6239c58d7e96f1b3/rpds_py-0.27.1-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:c796c0c1cc68cb08b0284db4229f5af76168172670c74908fdbd4b7d7f515819", size = 229125, upload-time = "2025-08-27T12:15:49.956Z" }, - { url = "https://files.pythonhosted.org/packages/0c/ed/e1fba02de17f4f76318b834425257c8ea297e415e12c68b4361f63e8ae92/rpds_py-0.27.1-pp311-pypy311_pp73-macosx_10_12_x86_64.whl", hash = "sha256:cdfe4bb2f9fe7458b7453ad3c33e726d6d1c7c0a72960bcc23800d77384e42df", size = 371402, upload-time = "2025-08-27T12:15:51.561Z" }, - { url = "https://files.pythonhosted.org/packages/af/7c/e16b959b316048b55585a697e94add55a4ae0d984434d279ea83442e460d/rpds_py-0.27.1-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:8fabb8fd848a5f75a2324e4a84501ee3a5e3c78d8603f83475441866e60b94a3", size = 354084, upload-time = "2025-08-27T12:15:53.219Z" }, - { url = "https://files.pythonhosted.org/packages/de/c1/ade645f55de76799fdd08682d51ae6724cb46f318573f18be49b1e040428/rpds_py-0.27.1-pp311-pypy311_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:eda8719d598f2f7f3e0f885cba8646644b55a187762bec091fa14a2b819746a9", size = 383090, upload-time = "2025-08-27T12:15:55.158Z" }, - { url = "https://files.pythonhosted.org/packages/1f/27/89070ca9b856e52960da1472efcb6c20ba27cfe902f4f23ed095b9cfc61d/rpds_py-0.27.1-pp311-pypy311_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:3c64d07e95606ec402a0a1c511fe003873fa6af630bda59bac77fac8b4318ebc", size = 394519, upload-time = "2025-08-27T12:15:57.238Z" }, - { url = "https://files.pythonhosted.org/packages/b3/28/be120586874ef906aa5aeeae95ae8df4184bc757e5b6bd1c729ccff45ed5/rpds_py-0.27.1-pp311-pypy311_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:93a2ed40de81bcff59aabebb626562d48332f3d028ca2036f1d23cbb52750be4", size = 523817, upload-time = "2025-08-27T12:15:59.237Z" }, - { url = "https://files.pythonhosted.org/packages/a8/ef/70cc197bc11cfcde02a86f36ac1eed15c56667c2ebddbdb76a47e90306da/rpds_py-0.27.1-pp311-pypy311_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:387ce8c44ae94e0ec50532d9cb0edce17311024c9794eb196b90e1058aadeb66", size = 403240, upload-time = "2025-08-27T12:16:00.923Z" }, - { url = "https://files.pythonhosted.org/packages/cf/35/46936cca449f7f518f2f4996e0e8344db4b57e2081e752441154089d2a5f/rpds_py-0.27.1-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:aaf94f812c95b5e60ebaf8bfb1898a7d7cb9c1af5744d4a67fa47796e0465d4e", size = 385194, upload-time = "2025-08-27T12:16:02.802Z" }, - { url = "https://files.pythonhosted.org/packages/e1/62/29c0d3e5125c3270b51415af7cbff1ec587379c84f55a5761cc9efa8cd06/rpds_py-0.27.1-pp311-pypy311_pp73-manylinux_2_31_riscv64.whl", hash = "sha256:4848ca84d6ded9b58e474dfdbad4b8bfb450344c0551ddc8d958bf4b36aa837c", size = 402086, upload-time = "2025-08-27T12:16:04.806Z" }, - { url = "https://files.pythonhosted.org/packages/8f/66/03e1087679227785474466fdd04157fb793b3b76e3fcf01cbf4c693c1949/rpds_py-0.27.1-pp311-pypy311_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2bde09cbcf2248b73c7c323be49b280180ff39fadcfe04e7b6f54a678d02a7cf", size = 419272, upload-time = "2025-08-27T12:16:06.471Z" }, - { url = "https://files.pythonhosted.org/packages/6a/24/e3e72d265121e00b063aef3e3501e5b2473cf1b23511d56e529531acf01e/rpds_py-0.27.1-pp311-pypy311_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:94c44ee01fd21c9058f124d2d4f0c9dc7634bec93cd4b38eefc385dabe71acbf", size = 560003, upload-time = "2025-08-27T12:16:08.06Z" }, - { url = "https://files.pythonhosted.org/packages/26/ca/f5a344c534214cc2d41118c0699fffbdc2c1bc7046f2a2b9609765ab9c92/rpds_py-0.27.1-pp311-pypy311_pp73-musllinux_1_2_i686.whl", hash = "sha256:df8b74962e35c9249425d90144e721eed198e6555a0e22a563d29fe4486b51f6", size = 590482, upload-time = "2025-08-27T12:16:10.137Z" }, - { url = "https://files.pythonhosted.org/packages/ce/08/4349bdd5c64d9d193c360aa9db89adeee6f6682ab8825dca0a3f535f434f/rpds_py-0.27.1-pp311-pypy311_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:dc23e6820e3b40847e2f4a7726462ba0cf53089512abe9ee16318c366494c17a", size = 556523, upload-time = "2025-08-27T12:16:12.188Z" }, -] - -[[package]] -name = "rsa" -version = "4.9.1" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "pyasn1" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/da/8a/22b7beea3ee0d44b1916c0c1cb0ee3af23b700b6da9f04991899d0c555d4/rsa-4.9.1.tar.gz", hash = "sha256:e7bdbfdb5497da4c07dfd35530e1a902659db6ff241e39d9953cad06ebd0ae75", size = 29034, upload-time = "2025-04-16T09:51:18.218Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/64/8d/0133e4eb4beed9e425d9a98ed6e081a55d195481b7632472be1af08d2f6b/rsa-4.9.1-py3-none-any.whl", hash = "sha256:68635866661c6836b8d39430f97a996acbd61bfa49406748ea243539fe239762", size = 34696, upload-time = "2025-04-16T09:51:17.142Z" }, +version = "0.30.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/20/af/3f2f423103f1113b36230496629986e0ef7e199d2aa8392452b484b38ced/rpds_py-0.30.0.tar.gz", hash = "sha256:dd8ff7cf90014af0c0f787eea34794ebf6415242ee1d6fa91eaba725cc441e84", size = 69469, upload-time = "2025-11-30T20:24:38.837Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/06/0c/0c411a0ec64ccb6d104dcabe0e713e05e153a9a2c3c2bd2b32ce412166fe/rpds_py-0.30.0-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:679ae98e00c0e8d68a7fda324e16b90fd5260945b45d3b824c892cec9eea3288", size = 370490, upload-time = "2025-11-30T20:21:33.256Z" }, + { url = "https://files.pythonhosted.org/packages/19/6a/4ba3d0fb7297ebae71171822554abe48d7cab29c28b8f9f2c04b79988c05/rpds_py-0.30.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:4cc2206b76b4f576934f0ed374b10d7ca5f457858b157ca52064bdfc26b9fc00", size = 359751, upload-time = "2025-11-30T20:21:34.591Z" }, + { url = "https://files.pythonhosted.org/packages/cd/7c/e4933565ef7f7a0818985d87c15d9d273f1a649afa6a52ea35ad011195ea/rpds_py-0.30.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:389a2d49eded1896c3d48b0136ead37c48e221b391c052fba3f4055c367f60a6", size = 389696, upload-time = "2025-11-30T20:21:36.122Z" }, + { url = "https://files.pythonhosted.org/packages/5e/01/6271a2511ad0815f00f7ed4390cf2567bec1d4b1da39e2c27a41e6e3b4de/rpds_py-0.30.0-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:32c8528634e1bf7121f3de08fa85b138f4e0dc47657866630611b03967f041d7", size = 403136, upload-time = "2025-11-30T20:21:37.728Z" }, + { url = "https://files.pythonhosted.org/packages/55/64/c857eb7cd7541e9b4eee9d49c196e833128a55b89a9850a9c9ac33ccf897/rpds_py-0.30.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f207f69853edd6f6700b86efb84999651baf3789e78a466431df1331608e5324", size = 524699, upload-time = "2025-11-30T20:21:38.92Z" }, + { url = "https://files.pythonhosted.org/packages/9c/ed/94816543404078af9ab26159c44f9e98e20fe47e2126d5d32c9d9948d10a/rpds_py-0.30.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:67b02ec25ba7a9e8fa74c63b6ca44cf5707f2fbfadae3ee8e7494297d56aa9df", size = 412022, upload-time = "2025-11-30T20:21:40.407Z" }, + { url = "https://files.pythonhosted.org/packages/61/b5/707f6cf0066a6412aacc11d17920ea2e19e5b2f04081c64526eb35b5c6e7/rpds_py-0.30.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0c0e95f6819a19965ff420f65578bacb0b00f251fefe2c8b23347c37174271f3", size = 390522, upload-time = "2025-11-30T20:21:42.17Z" }, + { url = "https://files.pythonhosted.org/packages/13/4e/57a85fda37a229ff4226f8cbcf09f2a455d1ed20e802ce5b2b4a7f5ed053/rpds_py-0.30.0-cp310-cp310-manylinux_2_31_riscv64.whl", hash = "sha256:a452763cc5198f2f98898eb98f7569649fe5da666c2dc6b5ddb10fde5a574221", size = 404579, upload-time = "2025-11-30T20:21:43.769Z" }, + { url = "https://files.pythonhosted.org/packages/f9/da/c9339293513ec680a721e0e16bf2bac3db6e5d7e922488de471308349bba/rpds_py-0.30.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:e0b65193a413ccc930671c55153a03ee57cecb49e6227204b04fae512eb657a7", size = 421305, upload-time = "2025-11-30T20:21:44.994Z" }, + { url = "https://files.pythonhosted.org/packages/f9/be/522cb84751114f4ad9d822ff5a1aa3c98006341895d5f084779b99596e5c/rpds_py-0.30.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:858738e9c32147f78b3ac24dc0edb6610000e56dc0f700fd5f651d0a0f0eb9ff", size = 572503, upload-time = "2025-11-30T20:21:46.91Z" }, + { url = "https://files.pythonhosted.org/packages/a2/9b/de879f7e7ceddc973ea6e4629e9b380213a6938a249e94b0cdbcc325bb66/rpds_py-0.30.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:da279aa314f00acbb803da1e76fa18666778e8a8f83484fba94526da5de2cba7", size = 598322, upload-time = "2025-11-30T20:21:48.709Z" }, + { url = "https://files.pythonhosted.org/packages/48/ac/f01fc22efec3f37d8a914fc1b2fb9bcafd56a299edbe96406f3053edea5a/rpds_py-0.30.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:7c64d38fb49b6cdeda16ab49e35fe0da2e1e9b34bc38bd78386530f218b37139", size = 560792, upload-time = "2025-11-30T20:21:50.024Z" }, + { url = "https://files.pythonhosted.org/packages/e2/da/4e2b19d0f131f35b6146425f846563d0ce036763e38913d917187307a671/rpds_py-0.30.0-cp310-cp310-win32.whl", hash = "sha256:6de2a32a1665b93233cde140ff8b3467bdb9e2af2b91079f0333a0974d12d464", size = 221901, upload-time = "2025-11-30T20:21:51.32Z" }, + { url = "https://files.pythonhosted.org/packages/96/cb/156d7a5cf4f78a7cc571465d8aec7a3c447c94f6749c5123f08438bcf7bc/rpds_py-0.30.0-cp310-cp310-win_amd64.whl", hash = "sha256:1726859cd0de969f88dc8673bdd954185b9104e05806be64bcd87badbe313169", size = 235823, upload-time = "2025-11-30T20:21:52.505Z" }, + { url = "https://files.pythonhosted.org/packages/4d/6e/f964e88b3d2abee2a82c1ac8366da848fce1c6d834dc2132c3fda3970290/rpds_py-0.30.0-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:a2bffea6a4ca9f01b3f8e548302470306689684e61602aa3d141e34da06cf425", size = 370157, upload-time = "2025-11-30T20:21:53.789Z" }, + { url = "https://files.pythonhosted.org/packages/94/ba/24e5ebb7c1c82e74c4e4f33b2112a5573ddc703915b13a073737b59b86e0/rpds_py-0.30.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:dc4f992dfe1e2bc3ebc7444f6c7051b4bc13cd8e33e43511e8ffd13bf407010d", size = 359676, upload-time = "2025-11-30T20:21:55.475Z" }, + { url = "https://files.pythonhosted.org/packages/84/86/04dbba1b087227747d64d80c3b74df946b986c57af0a9f0c98726d4d7a3b/rpds_py-0.30.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:422c3cb9856d80b09d30d2eb255d0754b23e090034e1deb4083f8004bd0761e4", size = 389938, upload-time = "2025-11-30T20:21:57.079Z" }, + { url = "https://files.pythonhosted.org/packages/42/bb/1463f0b1722b7f45431bdd468301991d1328b16cffe0b1c2918eba2c4eee/rpds_py-0.30.0-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:07ae8a593e1c3c6b82ca3292efbe73c30b61332fd612e05abee07c79359f292f", size = 402932, upload-time = "2025-11-30T20:21:58.47Z" }, + { url = "https://files.pythonhosted.org/packages/99/ee/2520700a5c1f2d76631f948b0736cdf9b0acb25abd0ca8e889b5c62ac2e3/rpds_py-0.30.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:12f90dd7557b6bd57f40abe7747e81e0c0b119bef015ea7726e69fe550e394a4", size = 525830, upload-time = "2025-11-30T20:21:59.699Z" }, + { url = "https://files.pythonhosted.org/packages/e0/ad/bd0331f740f5705cc555a5e17fdf334671262160270962e69a2bdef3bf76/rpds_py-0.30.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:99b47d6ad9a6da00bec6aabe5a6279ecd3c06a329d4aa4771034a21e335c3a97", size = 412033, upload-time = "2025-11-30T20:22:00.991Z" }, + { url = "https://files.pythonhosted.org/packages/f8/1e/372195d326549bb51f0ba0f2ecb9874579906b97e08880e7a65c3bef1a99/rpds_py-0.30.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:33f559f3104504506a44bb666b93a33f5d33133765b0c216a5bf2f1e1503af89", size = 390828, upload-time = "2025-11-30T20:22:02.723Z" }, + { url = "https://files.pythonhosted.org/packages/ab/2b/d88bb33294e3e0c76bc8f351a3721212713629ffca1700fa94979cb3eae8/rpds_py-0.30.0-cp311-cp311-manylinux_2_31_riscv64.whl", hash = "sha256:946fe926af6e44f3697abbc305ea168c2c31d3e3ef1058cf68f379bf0335a78d", size = 404683, upload-time = "2025-11-30T20:22:04.367Z" }, + { url = "https://files.pythonhosted.org/packages/50/32/c759a8d42bcb5289c1fac697cd92f6fe01a018dd937e62ae77e0e7f15702/rpds_py-0.30.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:495aeca4b93d465efde585977365187149e75383ad2684f81519f504f5c13038", size = 421583, upload-time = "2025-11-30T20:22:05.814Z" }, + { url = "https://files.pythonhosted.org/packages/2b/81/e729761dbd55ddf5d84ec4ff1f47857f4374b0f19bdabfcf929164da3e24/rpds_py-0.30.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:d9a0ca5da0386dee0655b4ccdf46119df60e0f10da268d04fe7cc87886872ba7", size = 572496, upload-time = "2025-11-30T20:22:07.713Z" }, + { url = "https://files.pythonhosted.org/packages/14/f6/69066a924c3557c9c30baa6ec3a0aa07526305684c6f86c696b08860726c/rpds_py-0.30.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:8d6d1cc13664ec13c1b84241204ff3b12f9bb82464b8ad6e7a5d3486975c2eed", size = 598669, upload-time = "2025-11-30T20:22:09.312Z" }, + { url = "https://files.pythonhosted.org/packages/5f/48/905896b1eb8a05630d20333d1d8ffd162394127b74ce0b0784ae04498d32/rpds_py-0.30.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:3896fa1be39912cf0757753826bc8bdc8ca331a28a7c4ae46b7a21280b06bb85", size = 561011, upload-time = "2025-11-30T20:22:11.309Z" }, + { url = "https://files.pythonhosted.org/packages/22/16/cd3027c7e279d22e5eb431dd3c0fbc677bed58797fe7581e148f3f68818b/rpds_py-0.30.0-cp311-cp311-win32.whl", hash = "sha256:55f66022632205940f1827effeff17c4fa7ae1953d2b74a8581baaefb7d16f8c", size = 221406, upload-time = "2025-11-30T20:22:13.101Z" }, + { url = "https://files.pythonhosted.org/packages/fa/5b/e7b7aa136f28462b344e652ee010d4de26ee9fd16f1bfd5811f5153ccf89/rpds_py-0.30.0-cp311-cp311-win_amd64.whl", hash = "sha256:a51033ff701fca756439d641c0ad09a41d9242fa69121c7d8769604a0a629825", size = 236024, upload-time = "2025-11-30T20:22:14.853Z" }, + { url = "https://files.pythonhosted.org/packages/14/a6/364bba985e4c13658edb156640608f2c9e1d3ea3c81b27aa9d889fff0e31/rpds_py-0.30.0-cp311-cp311-win_arm64.whl", hash = "sha256:47b0ef6231c58f506ef0b74d44e330405caa8428e770fec25329ed2cb971a229", size = 229069, upload-time = "2025-11-30T20:22:16.577Z" }, + { url = "https://files.pythonhosted.org/packages/03/e7/98a2f4ac921d82f33e03f3835f5bf3a4a40aa1bfdc57975e74a97b2b4bdd/rpds_py-0.30.0-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:a161f20d9a43006833cd7068375a94d035714d73a172b681d8881820600abfad", size = 375086, upload-time = "2025-11-30T20:22:17.93Z" }, + { url = "https://files.pythonhosted.org/packages/4d/a1/bca7fd3d452b272e13335db8d6b0b3ecde0f90ad6f16f3328c6fb150c889/rpds_py-0.30.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:6abc8880d9d036ecaafe709079969f56e876fcf107f7a8e9920ba6d5a3878d05", size = 359053, upload-time = "2025-11-30T20:22:19.297Z" }, + { url = "https://files.pythonhosted.org/packages/65/1c/ae157e83a6357eceff62ba7e52113e3ec4834a84cfe07fa4b0757a7d105f/rpds_py-0.30.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ca28829ae5f5d569bb62a79512c842a03a12576375d5ece7d2cadf8abe96ec28", size = 390763, upload-time = "2025-11-30T20:22:21.661Z" }, + { url = "https://files.pythonhosted.org/packages/d4/36/eb2eb8515e2ad24c0bd43c3ee9cd74c33f7ca6430755ccdb240fd3144c44/rpds_py-0.30.0-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:a1010ed9524c73b94d15919ca4d41d8780980e1765babf85f9a2f90d247153dd", size = 408951, upload-time = "2025-11-30T20:22:23.408Z" }, + { url = "https://files.pythonhosted.org/packages/d6/65/ad8dc1784a331fabbd740ef6f71ce2198c7ed0890dab595adb9ea2d775a1/rpds_py-0.30.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f8d1736cfb49381ba528cd5baa46f82fdc65c06e843dab24dd70b63d09121b3f", size = 514622, upload-time = "2025-11-30T20:22:25.16Z" }, + { url = "https://files.pythonhosted.org/packages/63/8e/0cfa7ae158e15e143fe03993b5bcd743a59f541f5952e1546b1ac1b5fd45/rpds_py-0.30.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d948b135c4693daff7bc2dcfc4ec57237a29bd37e60c2fabf5aff2bbacf3e2f1", size = 414492, upload-time = "2025-11-30T20:22:26.505Z" }, + { url = "https://files.pythonhosted.org/packages/60/1b/6f8f29f3f995c7ffdde46a626ddccd7c63aefc0efae881dc13b6e5d5bb16/rpds_py-0.30.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:47f236970bccb2233267d89173d3ad2703cd36a0e2a6e92d0560d333871a3d23", size = 394080, upload-time = "2025-11-30T20:22:27.934Z" }, + { url = "https://files.pythonhosted.org/packages/6d/d5/a266341051a7a3ca2f4b750a3aa4abc986378431fc2da508c5034d081b70/rpds_py-0.30.0-cp312-cp312-manylinux_2_31_riscv64.whl", hash = "sha256:2e6ecb5a5bcacf59c3f912155044479af1d0b6681280048b338b28e364aca1f6", size = 408680, upload-time = "2025-11-30T20:22:29.341Z" }, + { url = "https://files.pythonhosted.org/packages/10/3b/71b725851df9ab7a7a4e33cf36d241933da66040d195a84781f49c50490c/rpds_py-0.30.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:a8fa71a2e078c527c3e9dc9fc5a98c9db40bcc8a92b4e8858e36d329f8684b51", size = 423589, upload-time = "2025-11-30T20:22:31.469Z" }, + { url = "https://files.pythonhosted.org/packages/00/2b/e59e58c544dc9bd8bd8384ecdb8ea91f6727f0e37a7131baeff8d6f51661/rpds_py-0.30.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:73c67f2db7bc334e518d097c6d1e6fed021bbc9b7d678d6cc433478365d1d5f5", size = 573289, upload-time = "2025-11-30T20:22:32.997Z" }, + { url = "https://files.pythonhosted.org/packages/da/3e/a18e6f5b460893172a7d6a680e86d3b6bc87a54c1f0b03446a3c8c7b588f/rpds_py-0.30.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:5ba103fb455be00f3b1c2076c9d4264bfcb037c976167a6047ed82f23153f02e", size = 599737, upload-time = "2025-11-30T20:22:34.419Z" }, + { url = "https://files.pythonhosted.org/packages/5c/e2/714694e4b87b85a18e2c243614974413c60aa107fd815b8cbc42b873d1d7/rpds_py-0.30.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:7cee9c752c0364588353e627da8a7e808a66873672bcb5f52890c33fd965b394", size = 563120, upload-time = "2025-11-30T20:22:35.903Z" }, + { url = "https://files.pythonhosted.org/packages/6f/ab/d5d5e3bcedb0a77f4f613706b750e50a5a3ba1c15ccd3665ecc636c968fd/rpds_py-0.30.0-cp312-cp312-win32.whl", hash = "sha256:1ab5b83dbcf55acc8b08fc62b796ef672c457b17dbd7820a11d6c52c06839bdf", size = 223782, upload-time = "2025-11-30T20:22:37.271Z" }, + { url = "https://files.pythonhosted.org/packages/39/3b/f786af9957306fdc38a74cef405b7b93180f481fb48453a114bb6465744a/rpds_py-0.30.0-cp312-cp312-win_amd64.whl", hash = "sha256:a090322ca841abd453d43456ac34db46e8b05fd9b3b4ac0c78bcde8b089f959b", size = 240463, upload-time = "2025-11-30T20:22:39.021Z" }, + { url = "https://files.pythonhosted.org/packages/f3/d2/b91dc748126c1559042cfe41990deb92c4ee3e2b415f6b5234969ffaf0cc/rpds_py-0.30.0-cp312-cp312-win_arm64.whl", hash = "sha256:669b1805bd639dd2989b281be2cfd951c6121b65e729d9b843e9639ef1fd555e", size = 230868, upload-time = "2025-11-30T20:22:40.493Z" }, + { url = "https://files.pythonhosted.org/packages/ed/dc/d61221eb88ff410de3c49143407f6f3147acf2538c86f2ab7ce65ae7d5f9/rpds_py-0.30.0-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:f83424d738204d9770830d35290ff3273fbb02b41f919870479fab14b9d303b2", size = 374887, upload-time = "2025-11-30T20:22:41.812Z" }, + { url = "https://files.pythonhosted.org/packages/fd/32/55fb50ae104061dbc564ef15cc43c013dc4a9f4527a1f4d99baddf56fe5f/rpds_py-0.30.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:e7536cd91353c5273434b4e003cbda89034d67e7710eab8761fd918ec6c69cf8", size = 358904, upload-time = "2025-11-30T20:22:43.479Z" }, + { url = "https://files.pythonhosted.org/packages/58/70/faed8186300e3b9bdd138d0273109784eea2396c68458ed580f885dfe7ad/rpds_py-0.30.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2771c6c15973347f50fece41fc447c054b7ac2ae0502388ce3b6738cd366e3d4", size = 389945, upload-time = "2025-11-30T20:22:44.819Z" }, + { url = "https://files.pythonhosted.org/packages/bd/a8/073cac3ed2c6387df38f71296d002ab43496a96b92c823e76f46b8af0543/rpds_py-0.30.0-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:0a59119fc6e3f460315fe9d08149f8102aa322299deaa5cab5b40092345c2136", size = 407783, upload-time = "2025-11-30T20:22:46.103Z" }, + { url = "https://files.pythonhosted.org/packages/77/57/5999eb8c58671f1c11eba084115e77a8899d6e694d2a18f69f0ba471ec8b/rpds_py-0.30.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:76fec018282b4ead0364022e3c54b60bf368b9d926877957a8624b58419169b7", size = 515021, upload-time = "2025-11-30T20:22:47.458Z" }, + { url = "https://files.pythonhosted.org/packages/e0/af/5ab4833eadc36c0a8ed2bc5c0de0493c04f6c06de223170bd0798ff98ced/rpds_py-0.30.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:692bef75a5525db97318e8cd061542b5a79812d711ea03dbc1f6f8dbb0c5f0d2", size = 414589, upload-time = "2025-11-30T20:22:48.872Z" }, + { url = "https://files.pythonhosted.org/packages/b7/de/f7192e12b21b9e9a68a6d0f249b4af3fdcdff8418be0767a627564afa1f1/rpds_py-0.30.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9027da1ce107104c50c81383cae773ef5c24d296dd11c99e2629dbd7967a20c6", size = 394025, upload-time = "2025-11-30T20:22:50.196Z" }, + { url = "https://files.pythonhosted.org/packages/91/c4/fc70cd0249496493500e7cc2de87504f5aa6509de1e88623431fec76d4b6/rpds_py-0.30.0-cp313-cp313-manylinux_2_31_riscv64.whl", hash = "sha256:9cf69cdda1f5968a30a359aba2f7f9aa648a9ce4b580d6826437f2b291cfc86e", size = 408895, upload-time = "2025-11-30T20:22:51.87Z" }, + { url = "https://files.pythonhosted.org/packages/58/95/d9275b05ab96556fefff73a385813eb66032e4c99f411d0795372d9abcea/rpds_py-0.30.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:a4796a717bf12b9da9d3ad002519a86063dcac8988b030e405704ef7d74d2d9d", size = 422799, upload-time = "2025-11-30T20:22:53.341Z" }, + { url = "https://files.pythonhosted.org/packages/06/c1/3088fc04b6624eb12a57eb814f0d4997a44b0d208d6cace713033ff1a6ba/rpds_py-0.30.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:5d4c2aa7c50ad4728a094ebd5eb46c452e9cb7edbfdb18f9e1221f597a73e1e7", size = 572731, upload-time = "2025-11-30T20:22:54.778Z" }, + { url = "https://files.pythonhosted.org/packages/d8/42/c612a833183b39774e8ac8fecae81263a68b9583ee343db33ab571a7ce55/rpds_py-0.30.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:ba81a9203d07805435eb06f536d95a266c21e5b2dfbf6517748ca40c98d19e31", size = 599027, upload-time = "2025-11-30T20:22:56.212Z" }, + { url = "https://files.pythonhosted.org/packages/5f/60/525a50f45b01d70005403ae0e25f43c0384369ad24ffe46e8d9068b50086/rpds_py-0.30.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:945dccface01af02675628334f7cf49c2af4c1c904748efc5cf7bbdf0b579f95", size = 563020, upload-time = "2025-11-30T20:22:58.2Z" }, + { url = "https://files.pythonhosted.org/packages/0b/5d/47c4655e9bcd5ca907148535c10e7d489044243cc9941c16ed7cd53be91d/rpds_py-0.30.0-cp313-cp313-win32.whl", hash = "sha256:b40fb160a2db369a194cb27943582b38f79fc4887291417685f3ad693c5a1d5d", size = 223139, upload-time = "2025-11-30T20:23:00.209Z" }, + { url = "https://files.pythonhosted.org/packages/f2/e1/485132437d20aa4d3e1d8b3fb5a5e65aa8139f1e097080c2a8443201742c/rpds_py-0.30.0-cp313-cp313-win_amd64.whl", hash = "sha256:806f36b1b605e2d6a72716f321f20036b9489d29c51c91f4dd29a3e3afb73b15", size = 240224, upload-time = "2025-11-30T20:23:02.008Z" }, + { url = "https://files.pythonhosted.org/packages/24/95/ffd128ed1146a153d928617b0ef673960130be0009c77d8fbf0abe306713/rpds_py-0.30.0-cp313-cp313-win_arm64.whl", hash = "sha256:d96c2086587c7c30d44f31f42eae4eac89b60dabbac18c7669be3700f13c3ce1", size = 230645, upload-time = "2025-11-30T20:23:03.43Z" }, + { url = "https://files.pythonhosted.org/packages/ff/1b/b10de890a0def2a319a2626334a7f0ae388215eb60914dbac8a3bae54435/rpds_py-0.30.0-cp313-cp313t-macosx_10_12_x86_64.whl", hash = "sha256:eb0b93f2e5c2189ee831ee43f156ed34e2a89a78a66b98cadad955972548be5a", size = 364443, upload-time = "2025-11-30T20:23:04.878Z" }, + { url = "https://files.pythonhosted.org/packages/0d/bf/27e39f5971dc4f305a4fb9c672ca06f290f7c4e261c568f3dea16a410d47/rpds_py-0.30.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:922e10f31f303c7c920da8981051ff6d8c1a56207dbdf330d9047f6d30b70e5e", size = 353375, upload-time = "2025-11-30T20:23:06.342Z" }, + { url = "https://files.pythonhosted.org/packages/40/58/442ada3bba6e8e6615fc00483135c14a7538d2ffac30e2d933ccf6852232/rpds_py-0.30.0-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cdc62c8286ba9bf7f47befdcea13ea0e26bf294bda99758fd90535cbaf408000", size = 383850, upload-time = "2025-11-30T20:23:07.825Z" }, + { url = "https://files.pythonhosted.org/packages/14/14/f59b0127409a33c6ef6f5c1ebd5ad8e32d7861c9c7adfa9a624fc3889f6c/rpds_py-0.30.0-cp313-cp313t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:47f9a91efc418b54fb8190a6b4aa7813a23fb79c51f4bb84e418f5476c38b8db", size = 392812, upload-time = "2025-11-30T20:23:09.228Z" }, + { url = "https://files.pythonhosted.org/packages/b3/66/e0be3e162ac299b3a22527e8913767d869e6cc75c46bd844aa43fb81ab62/rpds_py-0.30.0-cp313-cp313t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1f3587eb9b17f3789ad50824084fa6f81921bbf9a795826570bda82cb3ed91f2", size = 517841, upload-time = "2025-11-30T20:23:11.186Z" }, + { url = "https://files.pythonhosted.org/packages/3d/55/fa3b9cf31d0c963ecf1ba777f7cf4b2a2c976795ac430d24a1f43d25a6ba/rpds_py-0.30.0-cp313-cp313t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:39c02563fc592411c2c61d26b6c5fe1e51eaa44a75aa2c8735ca88b0d9599daa", size = 408149, upload-time = "2025-11-30T20:23:12.864Z" }, + { url = "https://files.pythonhosted.org/packages/60/ca/780cf3b1a32b18c0f05c441958d3758f02544f1d613abf9488cd78876378/rpds_py-0.30.0-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:51a1234d8febafdfd33a42d97da7a43f5dcb120c1060e352a3fbc0c6d36e2083", size = 383843, upload-time = "2025-11-30T20:23:14.638Z" }, + { url = "https://files.pythonhosted.org/packages/82/86/d5f2e04f2aa6247c613da0c1dd87fcd08fa17107e858193566048a1e2f0a/rpds_py-0.30.0-cp313-cp313t-manylinux_2_31_riscv64.whl", hash = "sha256:eb2c4071ab598733724c08221091e8d80e89064cd472819285a9ab0f24bcedb9", size = 396507, upload-time = "2025-11-30T20:23:16.105Z" }, + { url = "https://files.pythonhosted.org/packages/4b/9a/453255d2f769fe44e07ea9785c8347edaf867f7026872e76c1ad9f7bed92/rpds_py-0.30.0-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:6bdfdb946967d816e6adf9a3d8201bfad269c67efe6cefd7093ef959683c8de0", size = 414949, upload-time = "2025-11-30T20:23:17.539Z" }, + { url = "https://files.pythonhosted.org/packages/a3/31/622a86cdc0c45d6df0e9ccb6becdba5074735e7033c20e401a6d9d0e2ca0/rpds_py-0.30.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:c77afbd5f5250bf27bf516c7c4a016813eb2d3e116139aed0096940c5982da94", size = 565790, upload-time = "2025-11-30T20:23:19.029Z" }, + { url = "https://files.pythonhosted.org/packages/1c/5d/15bbf0fb4a3f58a3b1c67855ec1efcc4ceaef4e86644665fff03e1b66d8d/rpds_py-0.30.0-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:61046904275472a76c8c90c9ccee9013d70a6d0f73eecefd38c1ae7c39045a08", size = 590217, upload-time = "2025-11-30T20:23:20.885Z" }, + { url = "https://files.pythonhosted.org/packages/6d/61/21b8c41f68e60c8cc3b2e25644f0e3681926020f11d06ab0b78e3c6bbff1/rpds_py-0.30.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:4c5f36a861bc4b7da6516dbdf302c55313afa09b81931e8280361a4f6c9a2d27", size = 555806, upload-time = "2025-11-30T20:23:22.488Z" }, + { url = "https://files.pythonhosted.org/packages/f9/39/7e067bb06c31de48de3eb200f9fc7c58982a4d3db44b07e73963e10d3be9/rpds_py-0.30.0-cp313-cp313t-win32.whl", hash = "sha256:3d4a69de7a3e50ffc214ae16d79d8fbb0922972da0356dcf4d0fdca2878559c6", size = 211341, upload-time = "2025-11-30T20:23:24.449Z" }, + { url = "https://files.pythonhosted.org/packages/0a/4d/222ef0b46443cf4cf46764d9c630f3fe4abaa7245be9417e56e9f52b8f65/rpds_py-0.30.0-cp313-cp313t-win_amd64.whl", hash = "sha256:f14fc5df50a716f7ece6a80b6c78bb35ea2ca47c499e422aa4463455dd96d56d", size = 225768, upload-time = "2025-11-30T20:23:25.908Z" }, + { url = "https://files.pythonhosted.org/packages/86/81/dad16382ebbd3d0e0328776d8fd7ca94220e4fa0798d1dc5e7da48cb3201/rpds_py-0.30.0-cp314-cp314-macosx_10_12_x86_64.whl", hash = "sha256:68f19c879420aa08f61203801423f6cd5ac5f0ac4ac82a2368a9fcd6a9a075e0", size = 362099, upload-time = "2025-11-30T20:23:27.316Z" }, + { url = "https://files.pythonhosted.org/packages/2b/60/19f7884db5d5603edf3c6bce35408f45ad3e97e10007df0e17dd57af18f8/rpds_py-0.30.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:ec7c4490c672c1a0389d319b3a9cfcd098dcdc4783991553c332a15acf7249be", size = 353192, upload-time = "2025-11-30T20:23:29.151Z" }, + { url = "https://files.pythonhosted.org/packages/bf/c4/76eb0e1e72d1a9c4703c69607cec123c29028bff28ce41588792417098ac/rpds_py-0.30.0-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f251c812357a3fed308d684a5079ddfb9d933860fc6de89f2b7ab00da481e65f", size = 384080, upload-time = "2025-11-30T20:23:30.785Z" }, + { url = "https://files.pythonhosted.org/packages/72/87/87ea665e92f3298d1b26d78814721dc39ed8d2c74b86e83348d6b48a6f31/rpds_py-0.30.0-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ac98b175585ecf4c0348fd7b29c3864bda53b805c773cbf7bfdaffc8070c976f", size = 394841, upload-time = "2025-11-30T20:23:32.209Z" }, + { url = "https://files.pythonhosted.org/packages/77/ad/7783a89ca0587c15dcbf139b4a8364a872a25f861bdb88ed99f9b0dec985/rpds_py-0.30.0-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3e62880792319dbeb7eb866547f2e35973289e7d5696c6e295476448f5b63c87", size = 516670, upload-time = "2025-11-30T20:23:33.742Z" }, + { url = "https://files.pythonhosted.org/packages/5b/3c/2882bdac942bd2172f3da574eab16f309ae10a3925644e969536553cb4ee/rpds_py-0.30.0-cp314-cp314-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4e7fc54e0900ab35d041b0601431b0a0eb495f0851a0639b6ef90f7741b39a18", size = 408005, upload-time = "2025-11-30T20:23:35.253Z" }, + { url = "https://files.pythonhosted.org/packages/ce/81/9a91c0111ce1758c92516a3e44776920b579d9a7c09b2b06b642d4de3f0f/rpds_py-0.30.0-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:47e77dc9822d3ad616c3d5759ea5631a75e5809d5a28707744ef79d7a1bcfcad", size = 382112, upload-time = "2025-11-30T20:23:36.842Z" }, + { url = "https://files.pythonhosted.org/packages/cf/8e/1da49d4a107027e5fbc64daeab96a0706361a2918da10cb41769244b805d/rpds_py-0.30.0-cp314-cp314-manylinux_2_31_riscv64.whl", hash = "sha256:b4dc1a6ff022ff85ecafef7979a2c6eb423430e05f1165d6688234e62ba99a07", size = 399049, upload-time = "2025-11-30T20:23:38.343Z" }, + { url = "https://files.pythonhosted.org/packages/df/5a/7ee239b1aa48a127570ec03becbb29c9d5a9eb092febbd1699d567cae859/rpds_py-0.30.0-cp314-cp314-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:4559c972db3a360808309e06a74628b95eaccbf961c335c8fe0d590cf587456f", size = 415661, upload-time = "2025-11-30T20:23:40.263Z" }, + { url = "https://files.pythonhosted.org/packages/70/ea/caa143cf6b772f823bc7929a45da1fa83569ee49b11d18d0ada7f5ee6fd6/rpds_py-0.30.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:0ed177ed9bded28f8deb6ab40c183cd1192aa0de40c12f38be4d59cd33cb5c65", size = 565606, upload-time = "2025-11-30T20:23:42.186Z" }, + { url = "https://files.pythonhosted.org/packages/64/91/ac20ba2d69303f961ad8cf55bf7dbdb4763f627291ba3d0d7d67333cced9/rpds_py-0.30.0-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:ad1fa8db769b76ea911cb4e10f049d80bf518c104f15b3edb2371cc65375c46f", size = 591126, upload-time = "2025-11-30T20:23:44.086Z" }, + { url = "https://files.pythonhosted.org/packages/21/20/7ff5f3c8b00c8a95f75985128c26ba44503fb35b8e0259d812766ea966c7/rpds_py-0.30.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:46e83c697b1f1c72b50e5ee5adb4353eef7406fb3f2043d64c33f20ad1c2fc53", size = 553371, upload-time = "2025-11-30T20:23:46.004Z" }, + { url = "https://files.pythonhosted.org/packages/72/c7/81dadd7b27c8ee391c132a6b192111ca58d866577ce2d9b0ca157552cce0/rpds_py-0.30.0-cp314-cp314-win32.whl", hash = "sha256:ee454b2a007d57363c2dfd5b6ca4a5d7e2c518938f8ed3b706e37e5d470801ed", size = 215298, upload-time = "2025-11-30T20:23:47.696Z" }, + { url = "https://files.pythonhosted.org/packages/3e/d2/1aaac33287e8cfb07aab2e6b8ac1deca62f6f65411344f1433c55e6f3eb8/rpds_py-0.30.0-cp314-cp314-win_amd64.whl", hash = "sha256:95f0802447ac2d10bcc69f6dc28fe95fdf17940367b21d34e34c737870758950", size = 228604, upload-time = "2025-11-30T20:23:49.501Z" }, + { url = "https://files.pythonhosted.org/packages/e8/95/ab005315818cc519ad074cb7784dae60d939163108bd2b394e60dc7b5461/rpds_py-0.30.0-cp314-cp314-win_arm64.whl", hash = "sha256:613aa4771c99f03346e54c3f038e4cc574ac09a3ddfb0e8878487335e96dead6", size = 222391, upload-time = "2025-11-30T20:23:50.96Z" }, + { url = "https://files.pythonhosted.org/packages/9e/68/154fe0194d83b973cdedcdcc88947a2752411165930182ae41d983dcefa6/rpds_py-0.30.0-cp314-cp314t-macosx_10_12_x86_64.whl", hash = "sha256:7e6ecfcb62edfd632e56983964e6884851786443739dbfe3582947e87274f7cb", size = 364868, upload-time = "2025-11-30T20:23:52.494Z" }, + { url = "https://files.pythonhosted.org/packages/83/69/8bbc8b07ec854d92a8b75668c24d2abcb1719ebf890f5604c61c9369a16f/rpds_py-0.30.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:a1d0bc22a7cdc173fedebb73ef81e07faef93692b8c1ad3733b67e31e1b6e1b8", size = 353747, upload-time = "2025-11-30T20:23:54.036Z" }, + { url = "https://files.pythonhosted.org/packages/ab/00/ba2e50183dbd9abcce9497fa5149c62b4ff3e22d338a30d690f9af970561/rpds_py-0.30.0-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0d08f00679177226c4cb8c5265012eea897c8ca3b93f429e546600c971bcbae7", size = 383795, upload-time = "2025-11-30T20:23:55.556Z" }, + { url = "https://files.pythonhosted.org/packages/05/6f/86f0272b84926bcb0e4c972262f54223e8ecc556b3224d281e6598fc9268/rpds_py-0.30.0-cp314-cp314t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5965af57d5848192c13534f90f9dd16464f3c37aaf166cc1da1cae1fd5a34898", size = 393330, upload-time = "2025-11-30T20:23:57.033Z" }, + { url = "https://files.pythonhosted.org/packages/cb/e9/0e02bb2e6dc63d212641da45df2b0bf29699d01715913e0d0f017ee29438/rpds_py-0.30.0-cp314-cp314t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9a4e86e34e9ab6b667c27f3211ca48f73dba7cd3d90f8d5b11be56e5dbc3fb4e", size = 518194, upload-time = "2025-11-30T20:23:58.637Z" }, + { url = "https://files.pythonhosted.org/packages/ee/ca/be7bca14cf21513bdf9c0606aba17d1f389ea2b6987035eb4f62bd923f25/rpds_py-0.30.0-cp314-cp314t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e5d3e6b26f2c785d65cc25ef1e5267ccbe1b069c5c21b8cc724efee290554419", size = 408340, upload-time = "2025-11-30T20:24:00.2Z" }, + { url = "https://files.pythonhosted.org/packages/c2/c7/736e00ebf39ed81d75544c0da6ef7b0998f8201b369acf842f9a90dc8fce/rpds_py-0.30.0-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:626a7433c34566535b6e56a1b39a7b17ba961e97ce3b80ec62e6f1312c025551", size = 383765, upload-time = "2025-11-30T20:24:01.759Z" }, + { url = "https://files.pythonhosted.org/packages/4a/3f/da50dfde9956aaf365c4adc9533b100008ed31aea635f2b8d7b627e25b49/rpds_py-0.30.0-cp314-cp314t-manylinux_2_31_riscv64.whl", hash = "sha256:acd7eb3f4471577b9b5a41baf02a978e8bdeb08b4b355273994f8b87032000a8", size = 396834, upload-time = "2025-11-30T20:24:03.687Z" }, + { url = "https://files.pythonhosted.org/packages/4e/00/34bcc2565b6020eab2623349efbdec810676ad571995911f1abdae62a3a0/rpds_py-0.30.0-cp314-cp314t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:fe5fa731a1fa8a0a56b0977413f8cacac1768dad38d16b3a296712709476fbd5", size = 415470, upload-time = "2025-11-30T20:24:05.232Z" }, + { url = "https://files.pythonhosted.org/packages/8c/28/882e72b5b3e6f718d5453bd4d0d9cf8df36fddeb4ddbbab17869d5868616/rpds_py-0.30.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:74a3243a411126362712ee1524dfc90c650a503502f135d54d1b352bd01f2404", size = 565630, upload-time = "2025-11-30T20:24:06.878Z" }, + { url = "https://files.pythonhosted.org/packages/3b/97/04a65539c17692de5b85c6e293520fd01317fd878ea1995f0367d4532fb1/rpds_py-0.30.0-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:3e8eeb0544f2eb0d2581774be4c3410356eba189529a6b3e36bbbf9696175856", size = 591148, upload-time = "2025-11-30T20:24:08.445Z" }, + { url = "https://files.pythonhosted.org/packages/85/70/92482ccffb96f5441aab93e26c4d66489eb599efdcf96fad90c14bbfb976/rpds_py-0.30.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:dbd936cde57abfee19ab3213cf9c26be06d60750e60a8e4dd85d1ab12c8b1f40", size = 556030, upload-time = "2025-11-30T20:24:10.956Z" }, + { url = "https://files.pythonhosted.org/packages/20/53/7c7e784abfa500a2b6b583b147ee4bb5a2b3747a9166bab52fec4b5b5e7d/rpds_py-0.30.0-cp314-cp314t-win32.whl", hash = "sha256:dc824125c72246d924f7f796b4f63c1e9dc810c7d9e2355864b3c3a73d59ade0", size = 211570, upload-time = "2025-11-30T20:24:12.735Z" }, + { url = "https://files.pythonhosted.org/packages/d0/02/fa464cdfbe6b26e0600b62c528b72d8608f5cc49f96b8d6e38c95d60c676/rpds_py-0.30.0-cp314-cp314t-win_amd64.whl", hash = "sha256:27f4b0e92de5bfbc6f86e43959e6edd1425c33b5e69aab0984a72047f2bcf1e3", size = 226532, upload-time = "2025-11-30T20:24:14.634Z" }, + { url = "https://files.pythonhosted.org/packages/69/71/3f34339ee70521864411f8b6992e7ab13ac30d8e4e3309e07c7361767d91/rpds_py-0.30.0-pp311-pypy311_pp73-macosx_10_12_x86_64.whl", hash = "sha256:c2262bdba0ad4fc6fb5545660673925c2d2a5d9e2e0fb603aad545427be0fc58", size = 372292, upload-time = "2025-11-30T20:24:16.537Z" }, + { url = "https://files.pythonhosted.org/packages/57/09/f183df9b8f2d66720d2ef71075c59f7e1b336bec7ee4c48f0a2b06857653/rpds_py-0.30.0-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:ee6af14263f25eedc3bb918a3c04245106a42dfd4f5c2285ea6f997b1fc3f89a", size = 362128, upload-time = "2025-11-30T20:24:18.086Z" }, + { url = "https://files.pythonhosted.org/packages/7a/68/5c2594e937253457342e078f0cc1ded3dd7b2ad59afdbf2d354869110a02/rpds_py-0.30.0-pp311-pypy311_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3adbb8179ce342d235c31ab8ec511e66c73faa27a47e076ccc92421add53e2bb", size = 391542, upload-time = "2025-11-30T20:24:20.092Z" }, + { url = "https://files.pythonhosted.org/packages/49/5c/31ef1afd70b4b4fbdb2800249f34c57c64beb687495b10aec0365f53dfc4/rpds_py-0.30.0-pp311-pypy311_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:250fa00e9543ac9b97ac258bd37367ff5256666122c2d0f2bc97577c60a1818c", size = 404004, upload-time = "2025-11-30T20:24:22.231Z" }, + { url = "https://files.pythonhosted.org/packages/e3/63/0cfbea38d05756f3440ce6534d51a491d26176ac045e2707adc99bb6e60a/rpds_py-0.30.0-pp311-pypy311_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9854cf4f488b3d57b9aaeb105f06d78e5529d3145b1e4a41750167e8c213c6d3", size = 527063, upload-time = "2025-11-30T20:24:24.302Z" }, + { url = "https://files.pythonhosted.org/packages/42/e6/01e1f72a2456678b0f618fc9a1a13f882061690893c192fcad9f2926553a/rpds_py-0.30.0-pp311-pypy311_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:993914b8e560023bc0a8bf742c5f303551992dcb85e247b1e5c7f4a7d145bda5", size = 413099, upload-time = "2025-11-30T20:24:25.916Z" }, + { url = "https://files.pythonhosted.org/packages/b8/25/8df56677f209003dcbb180765520c544525e3ef21ea72279c98b9aa7c7fb/rpds_py-0.30.0-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:58edca431fb9b29950807e301826586e5bbf24163677732429770a697ffe6738", size = 392177, upload-time = "2025-11-30T20:24:27.834Z" }, + { url = "https://files.pythonhosted.org/packages/4a/b4/0a771378c5f16f8115f796d1f437950158679bcd2a7c68cf251cfb00ed5b/rpds_py-0.30.0-pp311-pypy311_pp73-manylinux_2_31_riscv64.whl", hash = "sha256:dea5b552272a944763b34394d04577cf0f9bd013207bc32323b5a89a53cf9c2f", size = 406015, upload-time = "2025-11-30T20:24:29.457Z" }, + { url = "https://files.pythonhosted.org/packages/36/d8/456dbba0af75049dc6f63ff295a2f92766b9d521fa00de67a2bd6427d57a/rpds_py-0.30.0-pp311-pypy311_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:ba3af48635eb83d03f6c9735dfb21785303e73d22ad03d489e88adae6eab8877", size = 423736, upload-time = "2025-11-30T20:24:31.22Z" }, + { url = "https://files.pythonhosted.org/packages/13/64/b4d76f227d5c45a7e0b796c674fd81b0a6c4fbd48dc29271857d8219571c/rpds_py-0.30.0-pp311-pypy311_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:dff13836529b921e22f15cb099751209a60009731a68519630a24d61f0b1b30a", size = 573981, upload-time = "2025-11-30T20:24:32.934Z" }, + { url = "https://files.pythonhosted.org/packages/20/91/092bacadeda3edf92bf743cc96a7be133e13a39cdbfd7b5082e7ab638406/rpds_py-0.30.0-pp311-pypy311_pp73-musllinux_1_2_i686.whl", hash = "sha256:1b151685b23929ab7beec71080a8889d4d6d9fa9a983d213f07121205d48e2c4", size = 599782, upload-time = "2025-11-30T20:24:35.169Z" }, + { url = "https://files.pythonhosted.org/packages/d1/b7/b95708304cd49b7b6f82fdd039f1748b66ec2b21d6a45180910802f1abf1/rpds_py-0.30.0-pp311-pypy311_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:ac37f9f516c51e5753f27dfdef11a88330f04de2d564be3991384b2f3535d02e", size = 562191, upload-time = "2025-11-30T20:24:36.853Z" }, ] [[package]] @@ -4663,24 +4733,33 @@ wheels = [ [[package]] name = "secretstorage" -version = "3.4.0" +version = "3.5.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "cryptography" }, { name = "jeepney" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/31/9f/11ef35cf1027c1339552ea7bfe6aaa74a8516d8b5caf6e7d338daf54fd80/secretstorage-3.4.0.tar.gz", hash = "sha256:c46e216d6815aff8a8a18706a2fbfd8d53fcbb0dce99301881687a1b0289ef7c", size = 19748, upload-time = "2025-09-09T16:42:13.859Z" } +sdist = { url = "https://files.pythonhosted.org/packages/1c/03/e834bcd866f2f8a49a85eaff47340affa3bfa391ee9912a952a1faa68c7b/secretstorage-3.5.0.tar.gz", hash = "sha256:f04b8e4689cbce351744d5537bf6b1329c6fc68f91fa666f60a380edddcd11be", size = 19884, upload-time = "2025-11-23T19:02:53.191Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/91/ff/2e2eed29e02c14a5cb6c57f09b2d5b40e65d6cc71f45b52e0be295ccbc2f/secretstorage-3.4.0-py3-none-any.whl", hash = "sha256:0e3b6265c2c63509fb7415717607e4b2c9ab767b7f344a57473b779ca13bd02e", size = 15272, upload-time = "2025-09-09T16:42:12.744Z" }, + { url = "https://files.pythonhosted.org/packages/b7/46/f5af3402b579fd5e11573ce652019a67074317e18c1935cc0b4ba9b35552/secretstorage-3.5.0-py3-none-any.whl", hash = "sha256:0ce65888c0725fcb2c5bc0fdb8e5438eece02c523557ea40ce0703c266248137", size = 15554, upload-time = "2025-11-23T19:02:51.545Z" }, ] [[package]] name = "setuptools" -version = "80.9.0" +version = "81.0.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/0d/1c/73e719955c59b8e424d015ab450f51c0af856ae46ea2da83eba51cc88de1/setuptools-81.0.0.tar.gz", hash = "sha256:487b53915f52501f0a79ccfd0c02c165ffe06631443a886740b91af4b7a5845a", size = 1198299, upload-time = "2026-02-06T21:10:39.601Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e1/e3/c164c88b2e5ce7b24d667b9bd83589cf4f3520d97cad01534cd3c4f55fdb/setuptools-81.0.0-py3-none-any.whl", hash = "sha256:fdd925d5c5d9f62e4b74b30d6dd7828ce236fd6ed998a08d81de62ce5a6310d6", size = 1062021, upload-time = "2026-02-06T21:10:37.175Z" }, +] + +[[package]] +name = "shellingham" +version = "1.5.4" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/18/5d/3bf57dcd21979b887f014ea83c24ae194cfcd12b9e0fda66b957c69d1fca/setuptools-80.9.0.tar.gz", hash = "sha256:f36b47402ecde768dbfafc46e8e4207b4360c654f1f3bb84475f0a28628fb19c", size = 1319958, upload-time = "2025-05-27T00:56:51.443Z" } +sdist = { url = "https://files.pythonhosted.org/packages/58/15/8b3609fd3830ef7b27b655beb4b4e9c62313a4e8da8c676e142cc210d58e/shellingham-1.5.4.tar.gz", hash = "sha256:8dbca0739d487e5bd35ab3ca4b36e11c4078f3a234bfce294b0a0291363404de", size = 10310, upload-time = "2023-10-24T04:13:40.426Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/a3/dc/17031897dae0efacfea57dfd3a82fdd2a2aeb58e0ff71b77b87e44edc772/setuptools-80.9.0-py3-none-any.whl", hash = "sha256:062d34222ad13e0cc312a4c02d73f059e86a4acbfbdea8f8f76b28c99f306922", size = 1201486, upload-time = "2025-05-27T00:56:49.664Z" }, + { url = "https://files.pythonhosted.org/packages/e0/f9/0595336914c5619e5f28a1fb793285925a8cd4b432c9da0a987836c7f822/shellingham-1.5.4-py2.py3-none-any.whl", hash = "sha256:7ecfff8f2fd72616f7481040475a65b2bf8af90a56c89140852d1120324e8686", size = 9755, upload-time = "2023-10-24T04:13:38.866Z" }, ] [[package]] @@ -4712,76 +4791,76 @@ wheels = [ [[package]] name = "sqlalchemy" -version = "2.0.48" +version = "2.0.49" 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/1f/73/b4a9737255583b5fa858e0bb8e116eb94b88c910164ed2ed719147bde3de/sqlalchemy-2.0.48.tar.gz", hash = "sha256:5ca74f37f3369b45e1f6b7b06afb182af1fd5dde009e4ffd831830d98cbe5fe7", size = 9886075, upload-time = "2026-03-02T15:28:51.474Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/9a/67/1235676e93dd3b742a4a8eddfae49eea46c85e3eed29f0da446a8dd57500/sqlalchemy-2.0.48-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:7001dc9d5f6bb4deb756d5928eaefe1930f6f4179da3924cbd95ee0e9f4dce89", size = 2157384, upload-time = "2026-03-02T15:38:26.781Z" }, - { url = "https://files.pythonhosted.org/packages/4d/d7/fa728b856daa18c10e1390e76f26f64ac890c947008284387451d56ca3d0/sqlalchemy-2.0.48-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1a89ce07ad2d4b8cfc30bd5889ec40613e028ed80ef47da7d9dd2ce969ad30e0", size = 3236981, upload-time = "2026-03-02T15:58:53.53Z" }, - { url = "https://files.pythonhosted.org/packages/5c/ad/6c4395649a212a6c603a72c5b9ab5dce3135a1546cfdffa3c427e71fd535/sqlalchemy-2.0.48-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:10853a53a4a00417a00913d270dddda75815fcb80675874285f41051c094d7dd", size = 3235232, upload-time = "2026-03-02T15:52:25.654Z" }, - { url = "https://files.pythonhosted.org/packages/01/f4/58f845e511ac0509765a6f85eb24924c1ef0d54fb50de9d15b28c3601458/sqlalchemy-2.0.48-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:fac0fa4e4f55f118fd87177dacb1c6522fe39c28d498d259014020fec9164c29", size = 3188106, upload-time = "2026-03-02T15:58:55.193Z" }, - { url = "https://files.pythonhosted.org/packages/3f/f9/6dcc7bfa5f5794c3a095e78cd1de8269dfb5584dfd4c2c00a50d3c1ade44/sqlalchemy-2.0.48-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:3713e21ea67bca727eecd4a24bf68bcd414c403faae4989442be60994301ded0", size = 3209522, upload-time = "2026-03-02T15:52:27.407Z" }, - { url = "https://files.pythonhosted.org/packages/d7/5a/b632875ab35874d42657f079529f0745410604645c269a8c21fb4272ff7a/sqlalchemy-2.0.48-cp310-cp310-win32.whl", hash = "sha256:d404dc897ce10e565d647795861762aa2d06ca3f4a728c5e9a835096c7059018", size = 2117695, upload-time = "2026-03-02T15:46:51.389Z" }, - { url = "https://files.pythonhosted.org/packages/de/03/9752eb2a41afdd8568e41ac3c3128e32a0a73eada5ab80483083604a56d1/sqlalchemy-2.0.48-cp310-cp310-win_amd64.whl", hash = "sha256:841a94c66577661c1f088ac958cd767d7c9bf507698f45afffe7a4017049de76", size = 2140928, upload-time = "2026-03-02T15:46:52.992Z" }, - { url = "https://files.pythonhosted.org/packages/d7/6d/b8b78b5b80f3c3ab3f7fa90faa195ec3401f6d884b60221260fd4d51864c/sqlalchemy-2.0.48-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:1b4c575df7368b3b13e0cebf01d4679f9a28ed2ae6c1cd0b1d5beffb6b2007dc", size = 2157184, upload-time = "2026-03-02T15:38:28.161Z" }, - { url = "https://files.pythonhosted.org/packages/21/4b/4f3d4a43743ab58b95b9ddf5580a265b593d017693df9e08bd55780af5bb/sqlalchemy-2.0.48-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e83e3f959aaa1c9df95c22c528096d94848a1bc819f5d0ebf7ee3df0ca63db6c", size = 3313555, upload-time = "2026-03-02T15:58:57.21Z" }, - { url = "https://files.pythonhosted.org/packages/21/dd/3b7c53f1dbbf736fd27041aee68f8ac52226b610f914085b1652c2323442/sqlalchemy-2.0.48-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6f7b7243850edd0b8b97043f04748f31de50cf426e939def5c16bedb540698f7", size = 3313057, upload-time = "2026-03-02T15:52:29.366Z" }, - { url = "https://files.pythonhosted.org/packages/d9/cc/3e600a90ae64047f33313d7d32e5ad025417f09d2ded487e8284b5e21a15/sqlalchemy-2.0.48-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:82745b03b4043e04600a6b665cb98697c4339b24e34d74b0a2ac0a2488b6f94d", size = 3265431, upload-time = "2026-03-02T15:58:59.096Z" }, - { url = "https://files.pythonhosted.org/packages/8b/19/780138dacfe3f5024f4cf96e4005e91edf6653d53d3673be4844578faf1d/sqlalchemy-2.0.48-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:e5e088bf43f6ee6fec7dbf1ef7ff7774a616c236b5c0cb3e00662dd71a56b571", size = 3287646, upload-time = "2026-03-02T15:52:31.569Z" }, - { url = "https://files.pythonhosted.org/packages/40/fd/f32ced124f01a23151f4777e4c705f3a470adc7bd241d9f36a7c941a33bf/sqlalchemy-2.0.48-cp311-cp311-win32.whl", hash = "sha256:9c7d0a77e36b5f4b01ca398482230ab792061d243d715299b44a0b55c89fe617", size = 2116956, upload-time = "2026-03-02T15:46:54.535Z" }, - { url = "https://files.pythonhosted.org/packages/58/d5/dd767277f6feef12d05651538f280277e661698f617fa4d086cce6055416/sqlalchemy-2.0.48-cp311-cp311-win_amd64.whl", hash = "sha256:583849c743e0e3c9bb7446f5b5addeacedc168d657a69b418063dfdb2d90081c", size = 2141627, upload-time = "2026-03-02T15:46:55.849Z" }, - { url = "https://files.pythonhosted.org/packages/ef/91/a42ae716f8925e9659df2da21ba941f158686856107a61cc97a95e7647a3/sqlalchemy-2.0.48-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:348174f228b99f33ca1f773e85510e08927620caa59ffe7803b37170df30332b", size = 2155737, upload-time = "2026-03-02T15:49:13.207Z" }, - { url = "https://files.pythonhosted.org/packages/b9/52/f75f516a1f3888f027c1cfb5d22d4376f4b46236f2e8669dcb0cddc60275/sqlalchemy-2.0.48-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:53667b5f668991e279d21f94ccfa6e45b4e3f4500e7591ae59a8012d0f010dcb", size = 3337020, upload-time = "2026-03-02T15:50:34.547Z" }, - { url = "https://files.pythonhosted.org/packages/37/9a/0c28b6371e0cdcb14f8f1930778cb3123acfcbd2c95bb9cf6b4a2ba0cce3/sqlalchemy-2.0.48-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:34634e196f620c7a61d18d5cf7dc841ca6daa7961aed75d532b7e58b309ac894", size = 3349983, upload-time = "2026-03-02T15:53:25.542Z" }, - { url = "https://files.pythonhosted.org/packages/1c/46/0aee8f3ff20b1dcbceb46ca2d87fcc3d48b407925a383ff668218509d132/sqlalchemy-2.0.48-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:546572a1793cc35857a2ffa1fe0e58571af1779bcc1ffa7c9fb0839885ed69a9", size = 3279690, upload-time = "2026-03-02T15:50:36.277Z" }, - { url = "https://files.pythonhosted.org/packages/ce/8c/a957bc91293b49181350bfd55e6dfc6e30b7f7d83dc6792d72043274a390/sqlalchemy-2.0.48-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:07edba08061bc277bfdc772dd2a1a43978f5a45994dd3ede26391b405c15221e", size = 3314738, upload-time = "2026-03-02T15:53:27.519Z" }, - { url = "https://files.pythonhosted.org/packages/4b/44/1d257d9f9556661e7bdc83667cc414ba210acfc110c82938cb3611eea58f/sqlalchemy-2.0.48-cp312-cp312-win32.whl", hash = "sha256:908a3fa6908716f803b86896a09a2c4dde5f5ce2bb07aacc71ffebb57986ce99", size = 2115546, upload-time = "2026-03-02T15:54:31.591Z" }, - { url = "https://files.pythonhosted.org/packages/f2/af/c3c7e1f3a2b383155a16454df62ae8c62a30dd238e42e68c24cebebbfae6/sqlalchemy-2.0.48-cp312-cp312-win_amd64.whl", hash = "sha256:68549c403f79a8e25984376480959975212a670405e3913830614432b5daa07a", size = 2142484, upload-time = "2026-03-02T15:54:34.072Z" }, - { url = "https://files.pythonhosted.org/packages/d1/c6/569dc8bf3cd375abc5907e82235923e986799f301cd79a903f784b996fca/sqlalchemy-2.0.48-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:e3070c03701037aa418b55d36532ecb8f8446ed0135acb71c678dbdf12f5b6e4", size = 2152599, upload-time = "2026-03-02T15:49:14.41Z" }, - { url = "https://files.pythonhosted.org/packages/6d/ff/f4e04a4bd5a24304f38cb0d4aa2ad4c0fb34999f8b884c656535e1b2b74c/sqlalchemy-2.0.48-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:2645b7d8a738763b664a12a1542c89c940daa55196e8d73e55b169cc5c99f65f", size = 3278825, upload-time = "2026-03-02T15:50:38.269Z" }, - { url = "https://files.pythonhosted.org/packages/fe/88/cb59509e4668d8001818d7355d9995be90c321313078c912420603a7cb95/sqlalchemy-2.0.48-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b19151e76620a412c2ac1c6f977ab1b9fa7ad43140178345136456d5265b32ed", size = 3295200, upload-time = "2026-03-02T15:53:29.366Z" }, - { url = "https://files.pythonhosted.org/packages/87/dc/1609a4442aefd750ea2f32629559394ec92e89ac1d621a7f462b70f736ff/sqlalchemy-2.0.48-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:5b193a7e29fd9fa56e502920dca47dffe60f97c863494946bd698c6058a55658", size = 3226876, upload-time = "2026-03-02T15:50:39.802Z" }, - { url = "https://files.pythonhosted.org/packages/37/c3/6ae2ab5ea2fa989fbac4e674de01224b7a9d744becaf59bb967d62e99bed/sqlalchemy-2.0.48-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:36ac4ddc3d33e852da9cb00ffb08cea62ca05c39711dc67062ca2bb1fae35fd8", size = 3265045, upload-time = "2026-03-02T15:53:31.421Z" }, - { url = "https://files.pythonhosted.org/packages/6f/82/ea4665d1bb98c50c19666e672f21b81356bd6077c4574e3d2bbb84541f53/sqlalchemy-2.0.48-cp313-cp313-win32.whl", hash = "sha256:389b984139278f97757ea9b08993e7b9d1142912e046ab7d82b3fbaeb0209131", size = 2113700, upload-time = "2026-03-02T15:54:35.825Z" }, - { url = "https://files.pythonhosted.org/packages/b7/2b/b9040bec58c58225f073f5b0c1870defe1940835549dafec680cbd58c3c3/sqlalchemy-2.0.48-cp313-cp313-win_amd64.whl", hash = "sha256:d612c976cbc2d17edfcc4c006874b764e85e990c29ce9bd411f926bbfb02b9a2", size = 2139487, upload-time = "2026-03-02T15:54:37.079Z" }, - { url = "https://files.pythonhosted.org/packages/f4/f4/7b17bd50244b78a49d22cc63c969d71dc4de54567dc152a9b46f6fae40ce/sqlalchemy-2.0.48-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:69f5bc24904d3bc3640961cddd2523e361257ef68585d6e364166dfbe8c78fae", size = 3558851, upload-time = "2026-03-02T15:57:48.607Z" }, - { url = "https://files.pythonhosted.org/packages/20/0d/213668e9aca61d370f7d2a6449ea4ec699747fac67d4bda1bb3d129025be/sqlalchemy-2.0.48-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:fd08b90d211c086181caed76931ecfa2bdfc83eea3cfccdb0f82abc6c4b876cb", size = 3525525, upload-time = "2026-03-02T16:04:38.058Z" }, - { url = "https://files.pythonhosted.org/packages/85/d7/a84edf412979e7d59c69b89a5871f90a49228360594680e667cb2c46a828/sqlalchemy-2.0.48-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:1ccd42229aaac2df431562117ac7e667d702e8e44afdb6cf0e50fa3f18160f0b", size = 3466611, upload-time = "2026-03-02T15:57:50.759Z" }, - { url = "https://files.pythonhosted.org/packages/86/55/42404ce5770f6be26a2b0607e7866c31b9a4176c819e9a7a5e0a055770be/sqlalchemy-2.0.48-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:f0dcbc588cd5b725162c076eb9119342f6579c7f7f55057bb7e3c6ff27e13121", size = 3475812, upload-time = "2026-03-02T16:04:40.092Z" }, - { url = "https://files.pythonhosted.org/packages/ae/ae/29b87775fadc43e627cf582fe3bda4d02e300f6b8f2747c764950d13784c/sqlalchemy-2.0.48-cp313-cp313t-win32.whl", hash = "sha256:9764014ef5e58aab76220c5664abb5d47d5bc858d9debf821e55cfdd0f128485", size = 2141335, upload-time = "2026-03-02T15:52:51.518Z" }, - { url = "https://files.pythonhosted.org/packages/91/44/f39d063c90f2443e5b46ec4819abd3d8de653893aae92df42a5c4f5843de/sqlalchemy-2.0.48-cp313-cp313t-win_amd64.whl", hash = "sha256:e2f35b4cccd9ed286ad62e0a3c3ac21e06c02abc60e20aa51a3e305a30f5fa79", size = 2173095, upload-time = "2026-03-02T15:52:52.79Z" }, - { url = "https://files.pythonhosted.org/packages/f7/b3/f437eaa1cf028bb3c927172c7272366393e73ccd104dcf5b6963f4ab5318/sqlalchemy-2.0.48-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:e2d0d88686e3d35a76f3e15a34e8c12d73fc94c1dea1cd55782e695cc14086dd", size = 2154401, upload-time = "2026-03-02T15:49:17.24Z" }, - { url = "https://files.pythonhosted.org/packages/6c/1c/b3abdf0f402aa3f60f0df6ea53d92a162b458fca2321d8f1f00278506402/sqlalchemy-2.0.48-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:49b7bddc1eebf011ea5ab722fdbe67a401caa34a350d278cc7733c0e88fecb1f", size = 3274528, upload-time = "2026-03-02T15:50:41.489Z" }, - { url = "https://files.pythonhosted.org/packages/f2/5e/327428a034407651a048f5e624361adf3f9fbac9d0fa98e981e9c6ff2f5e/sqlalchemy-2.0.48-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:426c5ca86415d9b8945c7073597e10de9644802e2ff502b8e1f11a7a2642856b", size = 3279523, upload-time = "2026-03-02T15:53:32.962Z" }, - { url = "https://files.pythonhosted.org/packages/2a/ca/ece73c81a918add0965b76b868b7b5359e068380b90ef1656ee995940c02/sqlalchemy-2.0.48-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:288937433bd44e3990e7da2402fabc44a3c6c25d3704da066b85b89a85474ae0", size = 3224312, upload-time = "2026-03-02T15:50:42.996Z" }, - { url = "https://files.pythonhosted.org/packages/88/11/fbaf1ae91fa4ee43f4fe79661cead6358644824419c26adb004941bdce7c/sqlalchemy-2.0.48-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:8183dc57ae7d9edc1346e007e840a9f3d6aa7b7f165203a99e16f447150140d2", size = 3246304, upload-time = "2026-03-02T15:53:34.937Z" }, - { url = "https://files.pythonhosted.org/packages/fa/a8/5fb0deb13930b4f2f698c5541ae076c18981173e27dd00376dbaea7a9c82/sqlalchemy-2.0.48-cp314-cp314-win32.whl", hash = "sha256:1182437cb2d97988cfea04cf6cdc0b0bb9c74f4d56ec3d08b81e23d621a28cc6", size = 2116565, upload-time = "2026-03-02T15:54:38.321Z" }, - { url = "https://files.pythonhosted.org/packages/95/7e/e83615cb63f80047f18e61e31e8e32257d39458426c23006deeaf48f463b/sqlalchemy-2.0.48-cp314-cp314-win_amd64.whl", hash = "sha256:144921da96c08feb9e2b052c5c5c1d0d151a292c6135623c6b2c041f2a45f9e0", size = 2142205, upload-time = "2026-03-02T15:54:39.831Z" }, - { url = "https://files.pythonhosted.org/packages/83/e3/69d8711b3f2c5135e9cde5f063bc1605860f0b2c53086d40c04017eb1f77/sqlalchemy-2.0.48-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5aee45fd2c6c0f2b9cdddf48c48535e7471e42d6fb81adfde801da0bd5b93241", size = 3563519, upload-time = "2026-03-02T15:57:52.387Z" }, - { url = "https://files.pythonhosted.org/packages/f8/4f/a7cce98facca73c149ea4578981594aaa5fd841e956834931de503359336/sqlalchemy-2.0.48-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:7cddca31edf8b0653090cbb54562ca027c421c58ddde2c0685f49ff56a1690e0", size = 3528611, upload-time = "2026-03-02T16:04:42.097Z" }, - { url = "https://files.pythonhosted.org/packages/cd/7d/5936c7a03a0b0cb0fa0cc425998821c6029756b0855a8f7ee70fba1de955/sqlalchemy-2.0.48-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:7a936f1bb23d370b7c8cc079d5fce4c7d18da87a33c6744e51a93b0f9e97e9b3", size = 3472326, upload-time = "2026-03-02T15:57:54.423Z" }, - { url = "https://files.pythonhosted.org/packages/f4/33/cea7dfc31b52904efe3dcdc169eb4514078887dff1f5ae28a7f4c5d54b3c/sqlalchemy-2.0.48-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:e004aa9248e8cb0a5f9b96d003ca7c1c0a5da8decd1066e7b53f59eb8ce7c62b", size = 3478453, upload-time = "2026-03-02T16:04:44.584Z" }, - { url = "https://files.pythonhosted.org/packages/c8/95/32107c4d13be077a9cae61e9ae49966a35dc4bf442a8852dd871db31f62e/sqlalchemy-2.0.48-cp314-cp314t-win32.whl", hash = "sha256:b8438ec5594980d405251451c5b7ea9aa58dda38eb7ac35fb7e4c696712ee24f", size = 2147209, upload-time = "2026-03-02T15:52:54.274Z" }, - { url = "https://files.pythonhosted.org/packages/d2/d7/1e073da7a4bc645eb83c76067284a0374e643bc4be57f14cc6414656f92c/sqlalchemy-2.0.48-cp314-cp314t-win_amd64.whl", hash = "sha256:d854b3970067297f3a7fbd7a4683587134aa9b3877ee15aa29eea478dc68f933", size = 2182198, upload-time = "2026-03-02T15:52:55.606Z" }, - { url = "https://files.pythonhosted.org/packages/46/2c/9664130905f03db57961b8980b05cab624afd114bf2be2576628a9f22da4/sqlalchemy-2.0.48-py3-none-any.whl", hash = "sha256:a66fe406437dd65cacd96a72689a3aaaecaebbcd62d81c5ac1c0fdbeac835096", size = 1940202, upload-time = "2026-03-02T15:52:43.285Z" }, +sdist = { url = "https://files.pythonhosted.org/packages/09/45/461788f35e0364a8da7bda51a1fe1b09762d0c32f12f63727998d85a873b/sqlalchemy-2.0.49.tar.gz", hash = "sha256:d15950a57a210e36dd4cec1aac22787e2a4d57ba9318233e2ef8b2daf9ff2d5f", size = 9898221, upload-time = "2026-04-03T16:38:11.704Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/96/76/f908955139842c362aa877848f42f9249642d5b69e06cee9eae5111da1bd/sqlalchemy-2.0.49-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:42e8804962f9e6f4be2cbaedc0c3718f08f60a16910fa3d86da5a1e3b1bfe60f", size = 2159321, upload-time = "2026-04-03T16:50:11.8Z" }, + { url = "https://files.pythonhosted.org/packages/24/e2/17ba0b7bfbd8de67196889b6d951de269e8a46057d92baca162889beb16d/sqlalchemy-2.0.49-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:cc992c6ed024c8c3c592c5fc9846a03dd68a425674900c70122c77ea16c5fb0b", size = 3238937, upload-time = "2026-04-03T16:54:45.731Z" }, + { url = "https://files.pythonhosted.org/packages/90/1e/410dd499c039deacff395eec01a9da057125fcd0c97e3badc252c6a2d6a7/sqlalchemy-2.0.49-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6eb188b84269f357669b62cb576b5b918de10fb7c728a005fa0ebb0b758adce1", size = 3237188, upload-time = "2026-04-03T16:56:53.217Z" }, + { url = "https://files.pythonhosted.org/packages/ab/06/e797a8b98a3993ac4bc785309b9b6d005457fc70238ee6cefa7c8867a92e/sqlalchemy-2.0.49-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:62557958002b69699bdb7f5137c6714ca1133f045f97b3903964f47db97ea339", size = 3190061, upload-time = "2026-04-03T16:54:47.489Z" }, + { url = "https://files.pythonhosted.org/packages/44/d3/5a9f7ef580af1031184b38235da6ac58c3b571df01c9ec061c44b2b0c5a6/sqlalchemy-2.0.49-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:da9b91bca419dc9b9267ffadde24eae9b1a6bffcd09d0a207e5e3af99a03ce0d", size = 3211477, upload-time = "2026-04-03T16:56:55.056Z" }, + { url = "https://files.pythonhosted.org/packages/69/ec/7be8c8cb35f038e963a203e4fe5a028989167cc7299927b7cf297c271e37/sqlalchemy-2.0.49-cp310-cp310-win32.whl", hash = "sha256:5e61abbec255be7b122aa461021daa7c3f310f3e743411a67079f9b3cc91ece3", size = 2119965, upload-time = "2026-04-03T17:00:50.009Z" }, + { url = "https://files.pythonhosted.org/packages/b5/31/0defb93e3a10b0cf7d1271aedd87251a08c3a597ee4f353281769b547b5a/sqlalchemy-2.0.49-cp310-cp310-win_amd64.whl", hash = "sha256:0c98c59075b890df8abfcc6ad632879540f5791c68baebacb4f833713b510e75", size = 2142935, upload-time = "2026-04-03T17:00:51.675Z" }, + { url = "https://files.pythonhosted.org/packages/60/b5/e3617cc67420f8f403efebd7b043128f94775e57e5b84e7255203390ceae/sqlalchemy-2.0.49-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:c5070135e1b7409c4161133aa525419b0062088ed77c92b1da95366ec5cbebbe", size = 2159126, upload-time = "2026-04-03T16:50:13.242Z" }, + { url = "https://files.pythonhosted.org/packages/20/9b/91ca80403b17cd389622a642699e5f6564096b698e7cdcbcbb6409898bc4/sqlalchemy-2.0.49-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:9ac7a3e245fd0310fd31495eb61af772e637bdf7d88ee81e7f10a3f271bff014", size = 3315509, upload-time = "2026-04-03T16:54:49.332Z" }, + { url = "https://files.pythonhosted.org/packages/b1/61/0722511d98c54de95acb327824cb759e8653789af2b1944ab1cc69d32565/sqlalchemy-2.0.49-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4d4e5a0ceba319942fa6b585cf82539288a61e314ef006c1209f734551ab9536", size = 3315014, upload-time = "2026-04-03T16:56:56.376Z" }, + { url = "https://files.pythonhosted.org/packages/46/55/d514a653ffeb4cebf4b54c47bec32ee28ad89d39fafba16eeed1d81dccd5/sqlalchemy-2.0.49-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:3ddcb27fb39171de36e207600116ac9dfd4ae46f86c82a9bf3934043e80ebb88", size = 3267388, upload-time = "2026-04-03T16:54:51.272Z" }, + { url = "https://files.pythonhosted.org/packages/2f/16/0dcc56cb6d3335c1671a2258f5d2cb8267c9a2260e27fde53cbfb1b3540a/sqlalchemy-2.0.49-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:32fe6a41ad97302db2931f05bb91abbcc65b5ce4c675cd44b972428dd2947700", size = 3289602, upload-time = "2026-04-03T16:56:57.63Z" }, + { url = "https://files.pythonhosted.org/packages/51/6c/f8ab6fb04470a133cd80608db40aa292e6bae5f162c3a3d4ab19544a67af/sqlalchemy-2.0.49-cp311-cp311-win32.whl", hash = "sha256:46d51518d53edfbe0563662c96954dc8fcace9832332b914375f45a99b77cc9a", size = 2119044, upload-time = "2026-04-03T17:00:53.455Z" }, + { url = "https://files.pythonhosted.org/packages/c4/59/55a6d627d04b6ebb290693681d7683c7da001eddf90b60cfcc41ee907978/sqlalchemy-2.0.49-cp311-cp311-win_amd64.whl", hash = "sha256:951d4a210744813be63019f3df343bf233b7432aadf0db54c75802247330d3af", size = 2143642, upload-time = "2026-04-03T17:00:54.769Z" }, + { url = "https://files.pythonhosted.org/packages/49/b3/2de412451330756aaaa72d27131db6dde23995efe62c941184e15242a5fa/sqlalchemy-2.0.49-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:4bbccb45260e4ff1b7db0be80a9025bb1e6698bdb808b83fff0000f7a90b2c0b", size = 2157681, upload-time = "2026-04-03T16:53:07.132Z" }, + { url = "https://files.pythonhosted.org/packages/50/84/b2a56e2105bd11ebf9f0b93abddd748e1a78d592819099359aa98134a8bf/sqlalchemy-2.0.49-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:fb37f15714ec2652d574f021d479e78cd4eb9d04396dca36568fdfffb3487982", size = 3338976, upload-time = "2026-04-03T17:07:40Z" }, + { url = "https://files.pythonhosted.org/packages/2c/fa/65fcae2ed62f84ab72cf89536c7c3217a156e71a2c111b1305ab6f0690e2/sqlalchemy-2.0.49-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:3bb9ec6436a820a4c006aad1ac351f12de2f2dbdaad171692ee457a02429b672", size = 3351937, upload-time = "2026-04-03T17:12:23.374Z" }, + { url = "https://files.pythonhosted.org/packages/f8/2f/6fd118563572a7fe475925742eb6b3443b2250e346a0cc27d8d408e73773/sqlalchemy-2.0.49-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:8d6efc136f44a7e8bc8088507eaabbb8c2b55b3dbb63fe102c690da0ddebe55e", size = 3281646, upload-time = "2026-04-03T17:07:41.949Z" }, + { url = "https://files.pythonhosted.org/packages/c5/d7/410f4a007c65275b9cf82354adb4bb8ba587b176d0a6ee99caa16fe638f8/sqlalchemy-2.0.49-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:e06e617e3d4fd9e51d385dfe45b077a41e9d1b033a7702551e3278ac597dc750", size = 3316695, upload-time = "2026-04-03T17:12:25.642Z" }, + { url = "https://files.pythonhosted.org/packages/d9/95/81f594aa60ded13273a844539041ccf1e66c5a7bed0a8e27810a3b52d522/sqlalchemy-2.0.49-cp312-cp312-win32.whl", hash = "sha256:83101a6930332b87653886c01d1ee7e294b1fe46a07dd9a2d2b4f91bcc88eec0", size = 2117483, upload-time = "2026-04-03T17:05:40.896Z" }, + { url = "https://files.pythonhosted.org/packages/47/9e/fd90114059175cac64e4fafa9bf3ac20584384d66de40793ae2e2f26f3bb/sqlalchemy-2.0.49-cp312-cp312-win_amd64.whl", hash = "sha256:618a308215b6cececb6240b9abde545e3acdabac7ae3e1d4e666896bf5ba44b4", size = 2144494, upload-time = "2026-04-03T17:05:42.282Z" }, + { url = "https://files.pythonhosted.org/packages/ae/81/81755f50eb2478eaf2049728491d4ea4f416c1eb013338682173259efa09/sqlalchemy-2.0.49-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:df2d441bacf97022e81ad047e1597552eb3f83ca8a8f1a1fdd43cd7fe3898120", size = 2154547, upload-time = "2026-04-03T16:53:08.64Z" }, + { url = "https://files.pythonhosted.org/packages/a2/bc/3494270da80811d08bcfa247404292428c4fe16294932bce5593f215cad9/sqlalchemy-2.0.49-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8e20e511dc15265fb433571391ba313e10dd8ea7e509d51686a51313b4ac01a2", size = 3280782, upload-time = "2026-04-03T17:07:43.508Z" }, + { url = "https://files.pythonhosted.org/packages/cd/f5/038741f5e747a5f6ea3e72487211579d8cbea5eb9827a9cbd61d0108c4bd/sqlalchemy-2.0.49-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:47604cb2159f8bbd5a1ab48a714557156320f20871ee64d550d8bf2683d980d3", size = 3297156, upload-time = "2026-04-03T17:12:27.697Z" }, + { url = "https://files.pythonhosted.org/packages/88/50/a6af0ff9dc954b43a65ca9b5367334e45d99684c90a3d3413fc19a02d43c/sqlalchemy-2.0.49-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:22d8798819f86720bc646ab015baff5ea4c971d68121cb36e2ebc2ee43ead2b7", size = 3228832, upload-time = "2026-04-03T17:07:45.38Z" }, + { url = "https://files.pythonhosted.org/packages/bc/d1/5f6bdad8de0bf546fc74370939621396515e0cdb9067402d6ba1b8afbe9a/sqlalchemy-2.0.49-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:9b1c058c171b739e7c330760044803099c7fff11511e3ab3573e5327116a9c33", size = 3267000, upload-time = "2026-04-03T17:12:29.657Z" }, + { url = "https://files.pythonhosted.org/packages/f7/30/ad62227b4a9819a5e1c6abff77c0f614fa7c9326e5a3bdbee90f7139382b/sqlalchemy-2.0.49-cp313-cp313-win32.whl", hash = "sha256:a143af2ea6672f2af3f44ed8f9cd020e9cc34c56f0e8db12019d5d9ecf41cb3b", size = 2115641, upload-time = "2026-04-03T17:05:43.989Z" }, + { url = "https://files.pythonhosted.org/packages/17/3a/7215b1b7d6d49dc9a87211be44562077f5f04f9bb5a59552c1c8e2d98173/sqlalchemy-2.0.49-cp313-cp313-win_amd64.whl", hash = "sha256:12b04d1db2663b421fe072d638a138460a51d5a862403295671c4f3987fb9148", size = 2141498, upload-time = "2026-04-03T17:05:45.7Z" }, + { url = "https://files.pythonhosted.org/packages/28/4b/52a0cb2687a9cd1648252bb257be5a1ba2c2ded20ba695c65756a55a15a4/sqlalchemy-2.0.49-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:24bd94bb301ec672d8f0623eba9226cc90d775d25a0c92b5f8e4965d7f3a1518", size = 3560807, upload-time = "2026-04-03T16:58:31.666Z" }, + { url = "https://files.pythonhosted.org/packages/8c/d8/fda95459204877eed0458550d6c7c64c98cc50c2d8d618026737de9ed41a/sqlalchemy-2.0.49-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a51d3db74ba489266ef55c7a4534eb0b8db9a326553df481c11e5d7660c8364d", size = 3527481, upload-time = "2026-04-03T17:06:00.155Z" }, + { url = "https://files.pythonhosted.org/packages/ff/0a/2aac8b78ac6487240cf7afef8f203ca783e8796002dc0cf65c4ee99ff8bb/sqlalchemy-2.0.49-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:55250fe61d6ebfd6934a272ee16ef1244e0f16b7af6cd18ab5b1fc9f08631db0", size = 3468565, upload-time = "2026-04-03T16:58:33.414Z" }, + { url = "https://files.pythonhosted.org/packages/a5/3d/ce71cfa82c50a373fd2148b3c870be05027155ce791dc9a5dcf439790b8b/sqlalchemy-2.0.49-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:46796877b47034b559a593d7e4b549aba151dae73f9e78212a3478161c12ab08", size = 3477769, upload-time = "2026-04-03T17:06:02.787Z" }, + { url = "https://files.pythonhosted.org/packages/d5/e8/0a9f5c1f7c6f9ca480319bf57c2d7423f08d31445974167a27d14483c948/sqlalchemy-2.0.49-cp313-cp313t-win32.whl", hash = "sha256:9c4969a86e41454f2858256c39bdfb966a20961e9b58bf8749b65abf447e9a8d", size = 2143319, upload-time = "2026-04-03T17:02:04.328Z" }, + { url = "https://files.pythonhosted.org/packages/0e/51/fb5240729fbec73006e137c4f7a7918ffd583ab08921e6ff81a999d6517a/sqlalchemy-2.0.49-cp313-cp313t-win_amd64.whl", hash = "sha256:b9870d15ef00e4d0559ae10ee5bc71b654d1f20076dbe8bc7ed19b4c0625ceba", size = 2175104, upload-time = "2026-04-03T17:02:05.989Z" }, + { url = "https://files.pythonhosted.org/packages/55/33/bf28f618c0a9597d14e0b9ee7d1e0622faff738d44fe986ee287cdf1b8d0/sqlalchemy-2.0.49-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:233088b4b99ebcbc5258c755a097aa52fbf90727a03a5a80781c4b9c54347a2e", size = 2156356, upload-time = "2026-04-03T16:53:09.914Z" }, + { url = "https://files.pythonhosted.org/packages/d1/a7/5f476227576cb8644650eff68cc35fa837d3802b997465c96b8340ced1e2/sqlalchemy-2.0.49-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:57ca426a48eb2c682dae8204cd89ea8ab7031e2675120a47924fabc7caacbc2a", size = 3276486, upload-time = "2026-04-03T17:07:46.9Z" }, + { url = "https://files.pythonhosted.org/packages/2e/84/efc7c0bf3a1c5eef81d397f6fddac855becdbb11cb38ff957888603014a7/sqlalchemy-2.0.49-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:685e93e9c8f399b0c96a624799820176312f5ceef958c0f88215af4013d29066", size = 3281479, upload-time = "2026-04-03T17:12:32.226Z" }, + { url = "https://files.pythonhosted.org/packages/91/68/bb406fa4257099c67bd75f3f2261b129c63204b9155de0d450b37f004698/sqlalchemy-2.0.49-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:9e0400fa22f79acc334d9a6b185dc00a44a8e6578aa7e12d0ddcd8434152b187", size = 3226269, upload-time = "2026-04-03T17:07:48.678Z" }, + { url = "https://files.pythonhosted.org/packages/67/84/acb56c00cca9f251f437cb49e718e14f7687505749ea9255d7bd8158a6df/sqlalchemy-2.0.49-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:a05977bffe9bffd2229f477fa75eabe3192b1b05f408961d1bebff8d1cd4d401", size = 3248260, upload-time = "2026-04-03T17:12:34.381Z" }, + { url = "https://files.pythonhosted.org/packages/56/19/6a20ea25606d1efd7bd1862149bb2a22d1451c3f851d23d887969201633f/sqlalchemy-2.0.49-cp314-cp314-win32.whl", hash = "sha256:0f2fa354ba106eafff2c14b0cc51f22801d1e8b2e4149342023bd6f0955de5f5", size = 2118463, upload-time = "2026-04-03T17:05:47.093Z" }, + { url = "https://files.pythonhosted.org/packages/cf/4f/8297e4ed88e80baa1f5aa3c484a0ee29ef3c69c7582f206c916973b75057/sqlalchemy-2.0.49-cp314-cp314-win_amd64.whl", hash = "sha256:77641d299179c37b89cf2343ca9972c88bb6eef0d5fc504a2f86afd15cd5adf5", size = 2144204, upload-time = "2026-04-03T17:05:48.694Z" }, + { url = "https://files.pythonhosted.org/packages/1f/33/95e7216df810c706e0cd3655a778604bbd319ed4f43333127d465a46862d/sqlalchemy-2.0.49-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c1dc3368794d522f43914e03312202523cc89692f5389c32bea0233924f8d977", size = 3565474, upload-time = "2026-04-03T16:58:35.128Z" }, + { url = "https://files.pythonhosted.org/packages/0c/a4/ed7b18d8ccf7f954a83af6bb73866f5bc6f5636f44c7731fbb741f72cc4f/sqlalchemy-2.0.49-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:7c821c47ecfe05cc32140dcf8dc6fd5d21971c86dbd56eabfe5ba07a64910c01", size = 3530567, upload-time = "2026-04-03T17:06:04.587Z" }, + { url = "https://files.pythonhosted.org/packages/73/a3/20faa869c7e21a827c4a2a42b41353a54b0f9f5e96df5087629c306df71e/sqlalchemy-2.0.49-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:9c04bff9a5335eb95c6ecf1c117576a0aa560def274876fd156cfe5510fccc61", size = 3474282, upload-time = "2026-04-03T16:58:37.131Z" }, + { url = "https://files.pythonhosted.org/packages/b7/50/276b9a007aa0764304ad467eceb70b04822dc32092492ee5f322d559a4dc/sqlalchemy-2.0.49-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:7f605a456948c35260e7b2a39f8952a26f077fd25653c37740ed186b90aaa68a", size = 3480406, upload-time = "2026-04-03T17:06:07.176Z" }, + { url = "https://files.pythonhosted.org/packages/e5/c3/c80fcdb41905a2df650c2a3e0337198b6848876e63d66fe9188ef9003d24/sqlalchemy-2.0.49-cp314-cp314t-win32.whl", hash = "sha256:6270d717b11c5476b0cbb21eedc8d4dbb7d1a956fd6c15a23e96f197a6193158", size = 2149151, upload-time = "2026-04-03T17:02:07.281Z" }, + { url = "https://files.pythonhosted.org/packages/05/52/9f1a62feab6ed368aff068524ff414f26a6daebc7361861035ae00b05530/sqlalchemy-2.0.49-cp314-cp314t-win_amd64.whl", hash = "sha256:275424295f4256fd301744b8f335cff367825d270f155d522b30c7bf49903ee7", size = 2184178, upload-time = "2026-04-03T17:02:08.623Z" }, + { url = "https://files.pythonhosted.org/packages/e5/30/8519fdde58a7bdf155b714359791ad1dc018b47d60269d5d160d311fdc36/sqlalchemy-2.0.49-py3-none-any.whl", hash = "sha256:ec44cfa7ef1a728e88ad41674de50f6db8cfdb3e2af84af86e0041aaf02d43d0", size = 1942158, upload-time = "2026-04-03T16:53:44.135Z" }, ] [[package]] name = "sqlalchemy-spanner" -version = "1.17.2" +version = "1.17.3" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "alembic" }, { name = "google-cloud-spanner" }, { name = "sqlalchemy" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/8e/29/21698bb83e542f32e3581886671f39d94b1f7e8b190c24a8bfa994e62fd6/sqlalchemy_spanner-1.17.2.tar.gz", hash = "sha256:56ce4da7168a27442d80ffd71c29ed639b5056d7e69b1e69bb9c1e10190b67c4", size = 82745, upload-time = "2025-12-15T23:30:08.622Z" } +sdist = { url = "https://files.pythonhosted.org/packages/6b/1c/c7d28d88e8dd9a67be006a40135f05cbdf5a0f5f79bc51bb692f54432cf1/sqlalchemy_spanner-1.17.3.tar.gz", hash = "sha256:ea829d8223c404f19f854c4c2dbf6bf2ee48fb1347caa258f03e88071f3afa22", size = 82842, upload-time = "2026-03-23T22:44:01.25Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/7f/87/05be45a086116cea32cfa00fa0059d31b5345360dba7902ee640a1db793b/sqlalchemy_spanner-1.17.2-py3-none-any.whl", hash = "sha256:18713d4d78e0bf048eda0f7a5c80733e08a7b678b34349496415f37652efb12f", size = 31917, upload-time = "2025-12-15T23:30:07.356Z" }, + { url = "https://files.pythonhosted.org/packages/f3/43/cf21f3e70a8aa9e721fb557bd1459528906f0d9726b2ce642cd757fe592b/sqlalchemy_spanner-1.17.3-py3-none-any.whl", hash = "sha256:b0a13d2cae3bb0ee5aac898c44d22f56ec3edfc7780dd7d165d51f676590daf3", size = 31925, upload-time = "2026-03-23T22:43:33.214Z" }, ] [[package]] @@ -4795,27 +4874,28 @@ wheels = [ [[package]] name = "sse-starlette" -version = "3.0.2" +version = "3.3.4" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "anyio" }, + { name = "starlette" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/42/6f/22ed6e33f8a9e76ca0a412405f31abb844b779d52c5f96660766edcd737c/sse_starlette-3.0.2.tar.gz", hash = "sha256:ccd60b5765ebb3584d0de2d7a6e4f745672581de4f5005ab31c3a25d10b52b3a", size = 20985, upload-time = "2025-07-27T09:07:44.565Z" } +sdist = { url = "https://files.pythonhosted.org/packages/26/8c/f9290339ef6d79badbc010f067cd769d6601ec11a57d78569c683fb4dd87/sse_starlette-3.3.4.tar.gz", hash = "sha256:aaf92fc067af8a5427192895ac028e947b484ac01edbc3caf00e7e7137c7bef1", size = 32427, upload-time = "2026-03-29T09:00:23.307Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/ef/10/c78f463b4ef22eef8491f218f692be838282cd65480f6e423d7730dfd1fb/sse_starlette-3.0.2-py3-none-any.whl", hash = "sha256:16b7cbfddbcd4eaca11f7b586f3b8a080f1afe952c15813455b162edea619e5a", size = 11297, upload-time = "2025-07-27T09:07:43.268Z" }, + { url = "https://files.pythonhosted.org/packages/f8/7f/3de5402f39890ac5660b86bcf5c03f9d855dad5c4ed764866d7b592b46fd/sse_starlette-3.3.4-py3-none-any.whl", hash = "sha256:84bb06e58939a8b38d8341f1bc9792f06c2b53f48c608dd207582b664fc8f3c1", size = 14330, upload-time = "2026-03-29T09:00:21.846Z" }, ] [[package]] name = "starlette" -version = "0.49.1" +version = "0.52.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/1b/3f/507c21db33b66fb027a332f2cb3abbbe924cc3a79ced12f01ed8645955c9/starlette-0.49.1.tar.gz", hash = "sha256:481a43b71e24ed8c43b11ea02f5353d77840e01480881b8cb5a26b8cae64a8cb", size = 2654703, upload-time = "2025-10-28T17:34:10.928Z" } +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" } wheels = [ - { url = "https://files.pythonhosted.org/packages/51/da/545b75d420bb23b5d494b0517757b351963e974e79933f01e05c929f20a6/starlette-0.49.1-py3-none-any.whl", hash = "sha256:d92ce9f07e4a3caa3ac13a79523bd18e3bc0042bb8ff2d759a8e7dd0e1859875", size = 74175, upload-time = "2025-10-28T17:34:09.13Z" }, + { 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" }, ] [[package]] @@ -4902,6 +4982,7 @@ dev = [ { name = "pytest-timeout" }, { name = "pytest-xdist" }, { name = "ruff" }, + { name = "setuptools" }, { name = "toml" }, { name = "twine" }, ] @@ -4960,6 +5041,7 @@ dev = [ { name = "pytest-timeout", specifier = "~=2.2" }, { name = "pytest-xdist", specifier = ">=3.6,<4" }, { name = "ruff", specifier = ">=0.5.0,<0.6" }, + { name = "setuptools", specifier = "<82" }, { name = "toml", specifier = ">=0.10.2,<0.11" }, { name = "twine", specifier = ">=4.0.1,<5" }, ] @@ -5036,27 +5118,32 @@ wheels = [ [[package]] name = "tokenizers" -version = "0.22.1" +version = "0.22.2" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "huggingface-hub", marker = "python_full_version < '3.14'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/1c/46/fb6854cec3278fbfa4a75b50232c77622bc517ac886156e6afbfa4d8fc6e/tokenizers-0.22.1.tar.gz", hash = "sha256:61de6522785310a309b3407bac22d99c4db5dba349935e99e4d15ea2226af2d9", size = 363123, upload-time = "2025-09-19T09:49:23.424Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/bf/33/f4b2d94ada7ab297328fc671fed209368ddb82f965ec2224eb1892674c3a/tokenizers-0.22.1-cp39-abi3-macosx_10_12_x86_64.whl", hash = "sha256:59fdb013df17455e5f950b4b834a7b3ee2e0271e6378ccb33aa74d178b513c73", size = 3069318, upload-time = "2025-09-19T09:49:11.848Z" }, - { url = "https://files.pythonhosted.org/packages/1c/58/2aa8c874d02b974990e89ff95826a4852a8b2a273c7d1b4411cdd45a4565/tokenizers-0.22.1-cp39-abi3-macosx_11_0_arm64.whl", hash = "sha256:8d4e484f7b0827021ac5f9f71d4794aaef62b979ab7608593da22b1d2e3c4edc", size = 2926478, upload-time = "2025-09-19T09:49:09.759Z" }, - { url = "https://files.pythonhosted.org/packages/1e/3b/55e64befa1e7bfea963cf4b787b2cea1011362c4193f5477047532ce127e/tokenizers-0.22.1-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:19d2962dd28bc67c1f205ab180578a78eef89ac60ca7ef7cbe9635a46a56422a", size = 3256994, upload-time = "2025-09-19T09:48:56.701Z" }, - { url = "https://files.pythonhosted.org/packages/71/0b/fbfecf42f67d9b7b80fde4aabb2b3110a97fac6585c9470b5bff103a80cb/tokenizers-0.22.1-cp39-abi3-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:38201f15cdb1f8a6843e6563e6e79f4abd053394992b9bbdf5213ea3469b4ae7", size = 3153141, upload-time = "2025-09-19T09:48:59.749Z" }, - { url = "https://files.pythonhosted.org/packages/17/a9/b38f4e74e0817af8f8ef925507c63c6ae8171e3c4cb2d5d4624bf58fca69/tokenizers-0.22.1-cp39-abi3-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d1cbe5454c9a15df1b3443c726063d930c16f047a3cc724b9e6e1a91140e5a21", size = 3508049, upload-time = "2025-09-19T09:49:05.868Z" }, - { url = "https://files.pythonhosted.org/packages/d2/48/dd2b3dac46bb9134a88e35d72e1aa4869579eacc1a27238f1577270773ff/tokenizers-0.22.1-cp39-abi3-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e7d094ae6312d69cc2a872b54b91b309f4f6fbce871ef28eb27b52a98e4d0214", size = 3710730, upload-time = "2025-09-19T09:49:01.832Z" }, - { url = "https://files.pythonhosted.org/packages/93/0e/ccabc8d16ae4ba84a55d41345207c1e2ea88784651a5a487547d80851398/tokenizers-0.22.1-cp39-abi3-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:afd7594a56656ace95cdd6df4cca2e4059d294c5cfb1679c57824b605556cb2f", size = 3412560, upload-time = "2025-09-19T09:49:03.867Z" }, - { url = "https://files.pythonhosted.org/packages/d0/c6/dc3a0db5a6766416c32c034286d7c2d406da1f498e4de04ab1b8959edd00/tokenizers-0.22.1-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e2ef6063d7a84994129732b47e7915e8710f27f99f3a3260b8a38fc7ccd083f4", size = 3250221, upload-time = "2025-09-19T09:49:07.664Z" }, - { url = "https://files.pythonhosted.org/packages/d7/a6/2c8486eef79671601ff57b093889a345dd3d576713ef047776015dc66de7/tokenizers-0.22.1-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:ba0a64f450b9ef412c98f6bcd2a50c6df6e2443b560024a09fa6a03189726879", size = 9345569, upload-time = "2025-09-19T09:49:14.214Z" }, - { url = "https://files.pythonhosted.org/packages/6b/16/32ce667f14c35537f5f605fe9bea3e415ea1b0a646389d2295ec348d5657/tokenizers-0.22.1-cp39-abi3-musllinux_1_2_armv7l.whl", hash = "sha256:331d6d149fa9c7d632cde4490fb8bbb12337fa3a0232e77892be656464f4b446", size = 9271599, upload-time = "2025-09-19T09:49:16.639Z" }, - { url = "https://files.pythonhosted.org/packages/51/7c/a5f7898a3f6baa3fc2685c705e04c98c1094c523051c805cdd9306b8f87e/tokenizers-0.22.1-cp39-abi3-musllinux_1_2_i686.whl", hash = "sha256:607989f2ea68a46cb1dfbaf3e3aabdf3f21d8748312dbeb6263d1b3b66c5010a", size = 9533862, upload-time = "2025-09-19T09:49:19.146Z" }, - { url = "https://files.pythonhosted.org/packages/36/65/7e75caea90bc73c1dd8d40438adf1a7bc26af3b8d0a6705ea190462506e1/tokenizers-0.22.1-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:a0f307d490295717726598ef6fa4f24af9d484809223bbc253b201c740a06390", size = 9681250, upload-time = "2025-09-19T09:49:21.501Z" }, - { url = "https://files.pythonhosted.org/packages/30/2c/959dddef581b46e6209da82df3b78471e96260e2bc463f89d23b1bf0e52a/tokenizers-0.22.1-cp39-abi3-win32.whl", hash = "sha256:b5120eed1442765cd90b903bb6cfef781fd8fe64e34ccaecbae4c619b7b12a82", size = 2472003, upload-time = "2025-09-19T09:49:27.089Z" }, - { url = "https://files.pythonhosted.org/packages/b3/46/e33a8c93907b631a99377ef4c5f817ab453d0b34f93529421f42ff559671/tokenizers-0.22.1-cp39-abi3-win_amd64.whl", hash = "sha256:65fd6e3fb11ca1e78a6a93602490f134d1fdeb13bcef99389d5102ea318ed138", size = 2674684, upload-time = "2025-09-19T09:49:24.953Z" }, +sdist = { url = "https://files.pythonhosted.org/packages/73/6f/f80cfef4a312e1fb34baf7d85c72d4411afde10978d4657f8cdd811d3ccc/tokenizers-0.22.2.tar.gz", hash = "sha256:473b83b915e547aa366d1eee11806deaf419e17be16310ac0a14077f1e28f917", size = 372115, upload-time = "2026-01-05T10:45:15.988Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/92/97/5dbfabf04c7e348e655e907ed27913e03db0923abb5dfdd120d7b25630e1/tokenizers-0.22.2-cp39-abi3-macosx_10_12_x86_64.whl", hash = "sha256:544dd704ae7238755d790de45ba8da072e9af3eea688f698b137915ae959281c", size = 3100275, upload-time = "2026-01-05T10:41:02.158Z" }, + { url = "https://files.pythonhosted.org/packages/2e/47/174dca0502ef88b28f1c9e06b73ce33500eedfac7a7692108aec220464e7/tokenizers-0.22.2-cp39-abi3-macosx_11_0_arm64.whl", hash = "sha256:1e418a55456beedca4621dbab65a318981467a2b188e982a23e117f115ce5001", size = 2981472, upload-time = "2026-01-05T10:41:00.276Z" }, + { url = "https://files.pythonhosted.org/packages/d6/84/7990e799f1309a8b87af6b948f31edaa12a3ed22d11b352eaf4f4b2e5753/tokenizers-0.22.2-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2249487018adec45d6e3554c71d46eb39fa8ea67156c640f7513eb26f318cec7", size = 3290736, upload-time = "2026-01-05T10:40:32.165Z" }, + { url = "https://files.pythonhosted.org/packages/78/59/09d0d9ba94dcd5f4f1368d4858d24546b4bdc0231c2354aa31d6199f0399/tokenizers-0.22.2-cp39-abi3-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:25b85325d0815e86e0bac263506dd114578953b7b53d7de09a6485e4a160a7dd", size = 3168835, upload-time = "2026-01-05T10:40:38.847Z" }, + { url = "https://files.pythonhosted.org/packages/47/50/b3ebb4243e7160bda8d34b731e54dd8ab8b133e50775872e7a434e524c28/tokenizers-0.22.2-cp39-abi3-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bfb88f22a209ff7b40a576d5324bf8286b519d7358663db21d6246fb17eea2d5", size = 3521673, upload-time = "2026-01-05T10:40:56.614Z" }, + { url = "https://files.pythonhosted.org/packages/e0/fa/89f4cb9e08df770b57adb96f8cbb7e22695a4cb6c2bd5f0c4f0ebcf33b66/tokenizers-0.22.2-cp39-abi3-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1c774b1276f71e1ef716e5486f21e76333464f47bece56bbd554485982a9e03e", size = 3724818, upload-time = "2026-01-05T10:40:44.507Z" }, + { url = "https://files.pythonhosted.org/packages/64/04/ca2363f0bfbe3b3d36e95bf67e56a4c88c8e3362b658e616d1ac185d47f2/tokenizers-0.22.2-cp39-abi3-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:df6c4265b289083bf710dff49bc51ef252f9d5be33a45ee2bed151114a56207b", size = 3379195, upload-time = "2026-01-05T10:40:51.139Z" }, + { url = "https://files.pythonhosted.org/packages/2e/76/932be4b50ef6ccedf9d3c6639b056a967a86258c6d9200643f01269211ca/tokenizers-0.22.2-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:369cc9fc8cc10cb24143873a0d95438bb8ee257bb80c71989e3ee290e8d72c67", size = 3274982, upload-time = "2026-01-05T10:40:58.331Z" }, + { url = "https://files.pythonhosted.org/packages/1d/28/5f9f5a4cc211b69e89420980e483831bcc29dade307955cc9dc858a40f01/tokenizers-0.22.2-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:29c30b83d8dcd061078b05ae0cb94d3c710555fbb44861139f9f83dcca3dc3e4", size = 9478245, upload-time = "2026-01-05T10:41:04.053Z" }, + { url = "https://files.pythonhosted.org/packages/6c/fb/66e2da4704d6aadebf8cb39f1d6d1957df667ab24cff2326b77cda0dcb85/tokenizers-0.22.2-cp39-abi3-musllinux_1_2_armv7l.whl", hash = "sha256:37ae80a28c1d3265bb1f22464c856bd23c02a05bb211e56d0c5301a435be6c1a", size = 9560069, upload-time = "2026-01-05T10:45:10.673Z" }, + { url = "https://files.pythonhosted.org/packages/16/04/fed398b05caa87ce9b1a1bb5166645e38196081b225059a6edaff6440fac/tokenizers-0.22.2-cp39-abi3-musllinux_1_2_i686.whl", hash = "sha256:791135ee325f2336f498590eb2f11dc5c295232f288e75c99a36c5dbce63088a", size = 9899263, upload-time = "2026-01-05T10:45:12.559Z" }, + { url = "https://files.pythonhosted.org/packages/05/a1/d62dfe7376beaaf1394917e0f8e93ee5f67fea8fcf4107501db35996586b/tokenizers-0.22.2-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:38337540fbbddff8e999d59970f3c6f35a82de10053206a7562f1ea02d046fa5", size = 10033429, upload-time = "2026-01-05T10:45:14.333Z" }, + { url = "https://files.pythonhosted.org/packages/fd/18/a545c4ea42af3df6effd7d13d250ba77a0a86fb20393143bbb9a92e434d4/tokenizers-0.22.2-cp39-abi3-win32.whl", hash = "sha256:a6bf3f88c554a2b653af81f3204491c818ae2ac6fbc09e76ef4773351292bc92", size = 2502363, upload-time = "2026-01-05T10:45:20.593Z" }, + { url = "https://files.pythonhosted.org/packages/65/71/0670843133a43d43070abeb1949abfdef12a86d490bea9cd9e18e37c5ff7/tokenizers-0.22.2-cp39-abi3-win_amd64.whl", hash = "sha256:c9ea31edff2968b44a88f97d784c2f16dc0729b8b143ed004699ebca91f05c48", size = 2747786, upload-time = "2026-01-05T10:45:18.411Z" }, + { url = "https://files.pythonhosted.org/packages/72/f4/0de46cfa12cdcbcd464cc59fde36912af405696f687e53a091fb432f694c/tokenizers-0.22.2-cp39-abi3-win_arm64.whl", hash = "sha256:9ce725d22864a1e965217204946f830c37876eee3b2ba6fc6255e8e903d5fcbc", size = 2612133, upload-time = "2026-01-05T10:45:17.232Z" }, + { url = "https://files.pythonhosted.org/packages/84/04/655b79dbcc9b3ac5f1479f18e931a344af67e5b7d3b251d2dcdcd7558592/tokenizers-0.22.2-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:753d47ebd4542742ef9261d9da92cd545b2cacbb48349a1225466745bb866ec4", size = 3282301, upload-time = "2026-01-05T10:40:34.858Z" }, + { url = "https://files.pythonhosted.org/packages/46/cd/e4851401f3d8f6f45d8480262ab6a5c8cb9c4302a790a35aa14eeed6d2fd/tokenizers-0.22.2-pp310-pypy310_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e10bf9113d209be7cd046d40fbabbaf3278ff6d18eb4da4c500443185dc1896c", size = 3161308, upload-time = "2026-01-05T10:40:40.737Z" }, + { url = "https://files.pythonhosted.org/packages/6f/6e/55553992a89982cd12d4a66dddb5e02126c58677ea3931efcbe601d419db/tokenizers-0.22.2-pp310-pypy310_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:64d94e84f6660764e64e7e0b22baa72f6cd942279fdbb21d46abd70d179f0195", size = 3718964, upload-time = "2026-01-05T10:40:46.56Z" }, + { url = "https://files.pythonhosted.org/packages/59/8c/b1c87148aa15e099243ec9f0cf9d0e970cc2234c3257d558c25a2c5304e6/tokenizers-0.22.2-pp310-pypy310_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f01a9c019878532f98927d2bacb79bbb404b43d3437455522a00a30718cdedb5", size = 3373542, upload-time = "2026-01-05T10:40:52.803Z" }, ] [[package]] @@ -5070,63 +5157,68 @@ wheels = [ [[package]] name = "tomli" -version = "2.3.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/52/ed/3f73f72945444548f33eba9a87fc7a6e969915e7b1acc8260b30e1f76a2f/tomli-2.3.0.tar.gz", hash = "sha256:64be704a875d2a59753d80ee8a533c3fe183e3f06807ff7dc2232938ccb01549", size = 17392, upload-time = "2025-10-08T22:01:47.119Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/b3/2e/299f62b401438d5fe1624119c723f5d877acc86a4c2492da405626665f12/tomli-2.3.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:88bd15eb972f3664f5ed4b57c1634a97153b4bac4479dcb6a495f41921eb7f45", size = 153236, upload-time = "2025-10-08T22:01:00.137Z" }, - { url = "https://files.pythonhosted.org/packages/86/7f/d8fffe6a7aefdb61bced88fcb5e280cfd71e08939da5894161bd71bea022/tomli-2.3.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:883b1c0d6398a6a9d29b508c331fa56adbcdff647f6ace4dfca0f50e90dfd0ba", size = 148084, upload-time = "2025-10-08T22:01:01.63Z" }, - { url = "https://files.pythonhosted.org/packages/47/5c/24935fb6a2ee63e86d80e4d3b58b222dafaf438c416752c8b58537c8b89a/tomli-2.3.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d1381caf13ab9f300e30dd8feadb3de072aeb86f1d34a8569453ff32a7dea4bf", size = 234832, upload-time = "2025-10-08T22:01:02.543Z" }, - { url = "https://files.pythonhosted.org/packages/89/da/75dfd804fc11e6612846758a23f13271b76d577e299592b4371a4ca4cd09/tomli-2.3.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a0e285d2649b78c0d9027570d4da3425bdb49830a6156121360b3f8511ea3441", size = 242052, upload-time = "2025-10-08T22:01:03.836Z" }, - { url = "https://files.pythonhosted.org/packages/70/8c/f48ac899f7b3ca7eb13af73bacbc93aec37f9c954df3c08ad96991c8c373/tomli-2.3.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:0a154a9ae14bfcf5d8917a59b51ffd5a3ac1fd149b71b47a3a104ca4edcfa845", size = 239555, upload-time = "2025-10-08T22:01:04.834Z" }, - { url = "https://files.pythonhosted.org/packages/ba/28/72f8afd73f1d0e7829bfc093f4cb98ce0a40ffc0cc997009ee1ed94ba705/tomli-2.3.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:74bf8464ff93e413514fefd2be591c3b0b23231a77f901db1eb30d6f712fc42c", size = 245128, upload-time = "2025-10-08T22:01:05.84Z" }, - { url = "https://files.pythonhosted.org/packages/b6/eb/a7679c8ac85208706d27436e8d421dfa39d4c914dcf5fa8083a9305f58d9/tomli-2.3.0-cp311-cp311-win32.whl", hash = "sha256:00b5f5d95bbfc7d12f91ad8c593a1659b6387b43f054104cda404be6bda62456", size = 96445, upload-time = "2025-10-08T22:01:06.896Z" }, - { url = "https://files.pythonhosted.org/packages/0a/fe/3d3420c4cb1ad9cb462fb52967080575f15898da97e21cb6f1361d505383/tomli-2.3.0-cp311-cp311-win_amd64.whl", hash = "sha256:4dc4ce8483a5d429ab602f111a93a6ab1ed425eae3122032db7e9acf449451be", size = 107165, upload-time = "2025-10-08T22:01:08.107Z" }, - { url = "https://files.pythonhosted.org/packages/ff/b7/40f36368fcabc518bb11c8f06379a0fd631985046c038aca08c6d6a43c6e/tomli-2.3.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:d7d86942e56ded512a594786a5ba0a5e521d02529b3826e7761a05138341a2ac", size = 154891, upload-time = "2025-10-08T22:01:09.082Z" }, - { url = "https://files.pythonhosted.org/packages/f9/3f/d9dd692199e3b3aab2e4e4dd948abd0f790d9ded8cd10cbaae276a898434/tomli-2.3.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:73ee0b47d4dad1c5e996e3cd33b8a76a50167ae5f96a2607cbe8cc773506ab22", size = 148796, upload-time = "2025-10-08T22:01:10.266Z" }, - { url = "https://files.pythonhosted.org/packages/60/83/59bff4996c2cf9f9387a0f5a3394629c7efa5ef16142076a23a90f1955fa/tomli-2.3.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:792262b94d5d0a466afb5bc63c7daa9d75520110971ee269152083270998316f", size = 242121, upload-time = "2025-10-08T22:01:11.332Z" }, - { url = "https://files.pythonhosted.org/packages/45/e5/7c5119ff39de8693d6baab6c0b6dcb556d192c165596e9fc231ea1052041/tomli-2.3.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4f195fe57ecceac95a66a75ac24d9d5fbc98ef0962e09b2eddec5d39375aae52", size = 250070, upload-time = "2025-10-08T22:01:12.498Z" }, - { url = "https://files.pythonhosted.org/packages/45/12/ad5126d3a278f27e6701abde51d342aa78d06e27ce2bb596a01f7709a5a2/tomli-2.3.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:e31d432427dcbf4d86958c184b9bfd1e96b5b71f8eb17e6d02531f434fd335b8", size = 245859, upload-time = "2025-10-08T22:01:13.551Z" }, - { url = "https://files.pythonhosted.org/packages/fb/a1/4d6865da6a71c603cfe6ad0e6556c73c76548557a8d658f9e3b142df245f/tomli-2.3.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:7b0882799624980785240ab732537fcfc372601015c00f7fc367c55308c186f6", size = 250296, upload-time = "2025-10-08T22:01:14.614Z" }, - { url = "https://files.pythonhosted.org/packages/a0/b7/a7a7042715d55c9ba6e8b196d65d2cb662578b4d8cd17d882d45322b0d78/tomli-2.3.0-cp312-cp312-win32.whl", hash = "sha256:ff72b71b5d10d22ecb084d345fc26f42b5143c5533db5e2eaba7d2d335358876", size = 97124, upload-time = "2025-10-08T22:01:15.629Z" }, - { url = "https://files.pythonhosted.org/packages/06/1e/f22f100db15a68b520664eb3328fb0ae4e90530887928558112c8d1f4515/tomli-2.3.0-cp312-cp312-win_amd64.whl", hash = "sha256:1cb4ed918939151a03f33d4242ccd0aa5f11b3547d0cf30f7c74a408a5b99878", size = 107698, upload-time = "2025-10-08T22:01:16.51Z" }, - { url = "https://files.pythonhosted.org/packages/89/48/06ee6eabe4fdd9ecd48bf488f4ac783844fd777f547b8d1b61c11939974e/tomli-2.3.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:5192f562738228945d7b13d4930baffda67b69425a7f0da96d360b0a3888136b", size = 154819, upload-time = "2025-10-08T22:01:17.964Z" }, - { url = "https://files.pythonhosted.org/packages/f1/01/88793757d54d8937015c75dcdfb673c65471945f6be98e6a0410fba167ed/tomli-2.3.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:be71c93a63d738597996be9528f4abe628d1adf5e6eb11607bc8fe1a510b5dae", size = 148766, upload-time = "2025-10-08T22:01:18.959Z" }, - { url = "https://files.pythonhosted.org/packages/42/17/5e2c956f0144b812e7e107f94f1cc54af734eb17b5191c0bbfb72de5e93e/tomli-2.3.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c4665508bcbac83a31ff8ab08f424b665200c0e1e645d2bd9ab3d3e557b6185b", size = 240771, upload-time = "2025-10-08T22:01:20.106Z" }, - { url = "https://files.pythonhosted.org/packages/d5/f4/0fbd014909748706c01d16824eadb0307115f9562a15cbb012cd9b3512c5/tomli-2.3.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4021923f97266babc6ccab9f5068642a0095faa0a51a246a6a02fccbb3514eaf", size = 248586, upload-time = "2025-10-08T22:01:21.164Z" }, - { url = "https://files.pythonhosted.org/packages/30/77/fed85e114bde5e81ecf9bc5da0cc69f2914b38f4708c80ae67d0c10180c5/tomli-2.3.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:a4ea38c40145a357d513bffad0ed869f13c1773716cf71ccaa83b0fa0cc4e42f", size = 244792, upload-time = "2025-10-08T22:01:22.417Z" }, - { url = "https://files.pythonhosted.org/packages/55/92/afed3d497f7c186dc71e6ee6d4fcb0acfa5f7d0a1a2878f8beae379ae0cc/tomli-2.3.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:ad805ea85eda330dbad64c7ea7a4556259665bdf9d2672f5dccc740eb9d3ca05", size = 248909, upload-time = "2025-10-08T22:01:23.859Z" }, - { url = "https://files.pythonhosted.org/packages/f8/84/ef50c51b5a9472e7265ce1ffc7f24cd4023d289e109f669bdb1553f6a7c2/tomli-2.3.0-cp313-cp313-win32.whl", hash = "sha256:97d5eec30149fd3294270e889b4234023f2c69747e555a27bd708828353ab606", size = 96946, upload-time = "2025-10-08T22:01:24.893Z" }, - { url = "https://files.pythonhosted.org/packages/b2/b7/718cd1da0884f281f95ccfa3a6cc572d30053cba64603f79d431d3c9b61b/tomli-2.3.0-cp313-cp313-win_amd64.whl", hash = "sha256:0c95ca56fbe89e065c6ead5b593ee64b84a26fca063b5d71a1122bf26e533999", size = 107705, upload-time = "2025-10-08T22:01:26.153Z" }, - { url = "https://files.pythonhosted.org/packages/19/94/aeafa14a52e16163008060506fcb6aa1949d13548d13752171a755c65611/tomli-2.3.0-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:cebc6fe843e0733ee827a282aca4999b596241195f43b4cc371d64fc6639da9e", size = 154244, upload-time = "2025-10-08T22:01:27.06Z" }, - { url = "https://files.pythonhosted.org/packages/db/e4/1e58409aa78eefa47ccd19779fc6f36787edbe7d4cd330eeeedb33a4515b/tomli-2.3.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:4c2ef0244c75aba9355561272009d934953817c49f47d768070c3c94355c2aa3", size = 148637, upload-time = "2025-10-08T22:01:28.059Z" }, - { url = "https://files.pythonhosted.org/packages/26/b6/d1eccb62f665e44359226811064596dd6a366ea1f985839c566cd61525ae/tomli-2.3.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c22a8bf253bacc0cf11f35ad9808b6cb75ada2631c2d97c971122583b129afbc", size = 241925, upload-time = "2025-10-08T22:01:29.066Z" }, - { url = "https://files.pythonhosted.org/packages/70/91/7cdab9a03e6d3d2bb11beae108da5bdc1c34bdeb06e21163482544ddcc90/tomli-2.3.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0eea8cc5c5e9f89c9b90c4896a8deefc74f518db5927d0e0e8d4a80953d774d0", size = 249045, upload-time = "2025-10-08T22:01:31.98Z" }, - { url = "https://files.pythonhosted.org/packages/15/1b/8c26874ed1f6e4f1fcfeb868db8a794cbe9f227299402db58cfcc858766c/tomli-2.3.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:b74a0e59ec5d15127acdabd75ea17726ac4c5178ae51b85bfe39c4f8a278e879", size = 245835, upload-time = "2025-10-08T22:01:32.989Z" }, - { url = "https://files.pythonhosted.org/packages/fd/42/8e3c6a9a4b1a1360c1a2a39f0b972cef2cc9ebd56025168c4137192a9321/tomli-2.3.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:b5870b50c9db823c595983571d1296a6ff3e1b88f734a4c8f6fc6188397de005", size = 253109, upload-time = "2025-10-08T22:01:34.052Z" }, - { url = "https://files.pythonhosted.org/packages/22/0c/b4da635000a71b5f80130937eeac12e686eefb376b8dee113b4a582bba42/tomli-2.3.0-cp314-cp314-win32.whl", hash = "sha256:feb0dacc61170ed7ab602d3d972a58f14ee3ee60494292d384649a3dc38ef463", size = 97930, upload-time = "2025-10-08T22:01:35.082Z" }, - { url = "https://files.pythonhosted.org/packages/b9/74/cb1abc870a418ae99cd5c9547d6bce30701a954e0e721821df483ef7223c/tomli-2.3.0-cp314-cp314-win_amd64.whl", hash = "sha256:b273fcbd7fc64dc3600c098e39136522650c49bca95df2d11cf3b626422392c8", size = 107964, upload-time = "2025-10-08T22:01:36.057Z" }, - { url = "https://files.pythonhosted.org/packages/54/78/5c46fff6432a712af9f792944f4fcd7067d8823157949f4e40c56b8b3c83/tomli-2.3.0-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:940d56ee0410fa17ee1f12b817b37a4d4e4dc4d27340863cc67236c74f582e77", size = 163065, upload-time = "2025-10-08T22:01:37.27Z" }, - { url = "https://files.pythonhosted.org/packages/39/67/f85d9bd23182f45eca8939cd2bc7050e1f90c41f4a2ecbbd5963a1d1c486/tomli-2.3.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:f85209946d1fe94416debbb88d00eb92ce9cd5266775424ff81bc959e001acaf", size = 159088, upload-time = "2025-10-08T22:01:38.235Z" }, - { url = "https://files.pythonhosted.org/packages/26/5a/4b546a0405b9cc0659b399f12b6adb750757baf04250b148d3c5059fc4eb/tomli-2.3.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a56212bdcce682e56b0aaf79e869ba5d15a6163f88d5451cbde388d48b13f530", size = 268193, upload-time = "2025-10-08T22:01:39.712Z" }, - { url = "https://files.pythonhosted.org/packages/42/4f/2c12a72ae22cf7b59a7fe75b3465b7aba40ea9145d026ba41cb382075b0e/tomli-2.3.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c5f3ffd1e098dfc032d4d3af5c0ac64f6d286d98bc148698356847b80fa4de1b", size = 275488, upload-time = "2025-10-08T22:01:40.773Z" }, - { url = "https://files.pythonhosted.org/packages/92/04/a038d65dbe160c3aa5a624e93ad98111090f6804027d474ba9c37c8ae186/tomli-2.3.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:5e01decd096b1530d97d5d85cb4dff4af2d8347bd35686654a004f8dea20fc67", size = 272669, upload-time = "2025-10-08T22:01:41.824Z" }, - { url = "https://files.pythonhosted.org/packages/be/2f/8b7c60a9d1612a7cbc39ffcca4f21a73bf368a80fc25bccf8253e2563267/tomli-2.3.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:8a35dd0e643bb2610f156cca8db95d213a90015c11fee76c946aa62b7ae7e02f", size = 279709, upload-time = "2025-10-08T22:01:43.177Z" }, - { url = "https://files.pythonhosted.org/packages/7e/46/cc36c679f09f27ded940281c38607716c86cf8ba4a518d524e349c8b4874/tomli-2.3.0-cp314-cp314t-win32.whl", hash = "sha256:a1f7f282fe248311650081faafa5f4732bdbfef5d45fe3f2e702fbc6f2d496e0", size = 107563, upload-time = "2025-10-08T22:01:44.233Z" }, - { url = "https://files.pythonhosted.org/packages/84/ff/426ca8683cf7b753614480484f6437f568fd2fda2edbdf57a2d3d8b27a0b/tomli-2.3.0-cp314-cp314t-win_amd64.whl", hash = "sha256:70a251f8d4ba2d9ac2542eecf008b3c8a9fc5c3f9f02c56a9d7952612be2fdba", size = 119756, upload-time = "2025-10-08T22:01:45.234Z" }, - { url = "https://files.pythonhosted.org/packages/77/b8/0135fadc89e73be292b473cb820b4f5a08197779206b33191e801feeae40/tomli-2.3.0-py3-none-any.whl", hash = "sha256:e95b1af3c5b07d9e643909b5abbec77cd9f1217e6d0bca72b0234736b9fb1f1b", size = 14408, upload-time = "2025-10-08T22:01:46.04Z" }, +version = "2.4.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/22/de/48c59722572767841493b26183a0d1cc411d54fd759c5607c4590b6563a6/tomli-2.4.1.tar.gz", hash = "sha256:7c7e1a961a0b2f2472c1ac5b69affa0ae1132c39adcb67aba98568702b9cc23f", size = 17543, upload-time = "2026-03-25T20:22:03.828Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/f4/11/db3d5885d8528263d8adc260bb2d28ebf1270b96e98f0e0268d32b8d9900/tomli-2.4.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:f8f0fc26ec2cc2b965b7a3b87cd19c5c6b8c5e5f436b984e85f486d652285c30", size = 154704, upload-time = "2026-03-25T20:21:10.473Z" }, + { url = "https://files.pythonhosted.org/packages/6d/f7/675db52c7e46064a9aa928885a9b20f4124ecb9bc2e1ce74c9106648d202/tomli-2.4.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:4ab97e64ccda8756376892c53a72bd1f964e519c77236368527f758fbc36a53a", size = 149454, upload-time = "2026-03-25T20:21:12.036Z" }, + { url = "https://files.pythonhosted.org/packages/61/71/81c50943cf953efa35bce7646caab3cf457a7d8c030b27cfb40d7235f9ee/tomli-2.4.1-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:96481a5786729fd470164b47cdb3e0e58062a496f455ee41b4403be77cb5a076", size = 237561, upload-time = "2026-03-25T20:21:13.098Z" }, + { url = "https://files.pythonhosted.org/packages/48/c1/f41d9cb618acccca7df82aaf682f9b49013c9397212cb9f53219e3abac37/tomli-2.4.1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5a881ab208c0baf688221f8cecc5401bd291d67e38a1ac884d6736cbcd8247e9", size = 243824, upload-time = "2026-03-25T20:21:14.569Z" }, + { url = "https://files.pythonhosted.org/packages/22/e4/5a816ecdd1f8ca51fb756ef684b90f2780afc52fc67f987e3c61d800a46d/tomli-2.4.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:47149d5bd38761ac8be13a84864bf0b7b70bc051806bc3669ab1cbc56216b23c", size = 242227, upload-time = "2026-03-25T20:21:15.712Z" }, + { url = "https://files.pythonhosted.org/packages/6b/49/2b2a0ef529aa6eec245d25f0c703e020a73955ad7edf73e7f54ddc608aa5/tomli-2.4.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:ec9bfaf3ad2df51ace80688143a6a4ebc09a248f6ff781a9945e51937008fcbc", size = 247859, upload-time = "2026-03-25T20:21:17.001Z" }, + { url = "https://files.pythonhosted.org/packages/83/bd/6c1a630eaca337e1e78c5903104f831bda934c426f9231429396ce3c3467/tomli-2.4.1-cp311-cp311-win32.whl", hash = "sha256:ff2983983d34813c1aeb0fa89091e76c3a22889ee83ab27c5eeb45100560c049", size = 97204, upload-time = "2026-03-25T20:21:18.079Z" }, + { url = "https://files.pythonhosted.org/packages/42/59/71461df1a885647e10b6bb7802d0b8e66480c61f3f43079e0dcd315b3954/tomli-2.4.1-cp311-cp311-win_amd64.whl", hash = "sha256:5ee18d9ebdb417e384b58fe414e8d6af9f4e7a0ae761519fb50f721de398dd4e", size = 108084, upload-time = "2026-03-25T20:21:18.978Z" }, + { url = "https://files.pythonhosted.org/packages/b8/83/dceca96142499c069475b790e7913b1044c1a4337e700751f48ed723f883/tomli-2.4.1-cp311-cp311-win_arm64.whl", hash = "sha256:c2541745709bad0264b7d4705ad453b76ccd191e64aa6f0fc66b69a293a45ece", size = 95285, upload-time = "2026-03-25T20:21:20.309Z" }, + { url = "https://files.pythonhosted.org/packages/c1/ba/42f134a3fe2b370f555f44b1d72feebb94debcab01676bf918d0cb70e9aa/tomli-2.4.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:c742f741d58a28940ce01d58f0ab2ea3ced8b12402f162f4d534dfe18ba1cd6a", size = 155924, upload-time = "2026-03-25T20:21:21.626Z" }, + { url = "https://files.pythonhosted.org/packages/dc/c7/62d7a17c26487ade21c5422b646110f2162f1fcc95980ef7f63e73c68f14/tomli-2.4.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:7f86fd587c4ed9dd76f318225e7d9b29cfc5a9d43de44e5754db8d1128487085", size = 150018, upload-time = "2026-03-25T20:21:23.002Z" }, + { url = "https://files.pythonhosted.org/packages/5c/05/79d13d7c15f13bdef410bdd49a6485b1c37d28968314eabee452c22a7fda/tomli-2.4.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ff18e6a727ee0ab0388507b89d1bc6a22b138d1e2fa56d1ad494586d61d2eae9", size = 244948, upload-time = "2026-03-25T20:21:24.04Z" }, + { url = "https://files.pythonhosted.org/packages/10/90/d62ce007a1c80d0b2c93e02cab211224756240884751b94ca72df8a875ca/tomli-2.4.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:136443dbd7e1dee43c68ac2694fde36b2849865fa258d39bf822c10e8068eac5", size = 253341, upload-time = "2026-03-25T20:21:25.177Z" }, + { url = "https://files.pythonhosted.org/packages/1a/7e/caf6496d60152ad4ed09282c1885cca4eea150bfd007da84aea07bcc0a3e/tomli-2.4.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:5e262d41726bc187e69af7825504c933b6794dc3fbd5945e41a79bb14c31f585", size = 248159, upload-time = "2026-03-25T20:21:26.364Z" }, + { url = "https://files.pythonhosted.org/packages/99/e7/c6f69c3120de34bbd882c6fba7975f3d7a746e9218e56ab46a1bc4b42552/tomli-2.4.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:5cb41aa38891e073ee49d55fbc7839cfdb2bc0e600add13874d048c94aadddd1", size = 253290, upload-time = "2026-03-25T20:21:27.46Z" }, + { url = "https://files.pythonhosted.org/packages/d6/2f/4a3c322f22c5c66c4b836ec58211641a4067364f5dcdd7b974b4c5da300c/tomli-2.4.1-cp312-cp312-win32.whl", hash = "sha256:da25dc3563bff5965356133435b757a795a17b17d01dbc0f42fb32447ddfd917", size = 98141, upload-time = "2026-03-25T20:21:28.492Z" }, + { url = "https://files.pythonhosted.org/packages/24/22/4daacd05391b92c55759d55eaee21e1dfaea86ce5c571f10083360adf534/tomli-2.4.1-cp312-cp312-win_amd64.whl", hash = "sha256:52c8ef851d9a240f11a88c003eacb03c31fc1c9c4ec64a99a0f922b93874fda9", size = 108847, upload-time = "2026-03-25T20:21:29.386Z" }, + { url = "https://files.pythonhosted.org/packages/68/fd/70e768887666ddd9e9f5d85129e84910f2db2796f9096aa02b721a53098d/tomli-2.4.1-cp312-cp312-win_arm64.whl", hash = "sha256:f758f1b9299d059cc3f6546ae2af89670cb1c4d48ea29c3cacc4fe7de3058257", size = 95088, upload-time = "2026-03-25T20:21:30.677Z" }, + { url = "https://files.pythonhosted.org/packages/07/06/b823a7e818c756d9a7123ba2cda7d07bc2dd32835648d1a7b7b7a05d848d/tomli-2.4.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:36d2bd2ad5fb9eaddba5226aa02c8ec3fa4f192631e347b3ed28186d43be6b54", size = 155866, upload-time = "2026-03-25T20:21:31.65Z" }, + { url = "https://files.pythonhosted.org/packages/14/6f/12645cf7f08e1a20c7eb8c297c6f11d31c1b50f316a7e7e1e1de6e2e7b7e/tomli-2.4.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:eb0dc4e38e6a1fd579e5d50369aa2e10acfc9cace504579b2faabb478e76941a", size = 149887, upload-time = "2026-03-25T20:21:33.028Z" }, + { url = "https://files.pythonhosted.org/packages/5c/e0/90637574e5e7212c09099c67ad349b04ec4d6020324539297b634a0192b0/tomli-2.4.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c7f2c7f2b9ca6bdeef8f0fa897f8e05085923eb091721675170254cbc5b02897", size = 243704, upload-time = "2026-03-25T20:21:34.51Z" }, + { url = "https://files.pythonhosted.org/packages/10/8f/d3ddb16c5a4befdf31a23307f72828686ab2096f068eaf56631e136c1fdd/tomli-2.4.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f3c6818a1a86dd6dca7ddcaaf76947d5ba31aecc28cb1b67009a5877c9a64f3f", size = 251628, upload-time = "2026-03-25T20:21:36.012Z" }, + { url = "https://files.pythonhosted.org/packages/e3/f1/dbeeb9116715abee2485bf0a12d07a8f31af94d71608c171c45f64c0469d/tomli-2.4.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:d312ef37c91508b0ab2cee7da26ec0b3ed2f03ce12bd87a588d771ae15dcf82d", size = 247180, upload-time = "2026-03-25T20:21:37.136Z" }, + { url = "https://files.pythonhosted.org/packages/d3/74/16336ffd19ed4da28a70959f92f506233bd7cfc2332b20bdb01591e8b1d1/tomli-2.4.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:51529d40e3ca50046d7606fa99ce3956a617f9b36380da3b7f0dd3dd28e68cb5", size = 251674, upload-time = "2026-03-25T20:21:38.298Z" }, + { url = "https://files.pythonhosted.org/packages/16/f9/229fa3434c590ddf6c0aa9af64d3af4b752540686cace29e6281e3458469/tomli-2.4.1-cp313-cp313-win32.whl", hash = "sha256:2190f2e9dd7508d2a90ded5ed369255980a1bcdd58e52f7fe24b8162bf9fedbd", size = 97976, upload-time = "2026-03-25T20:21:39.316Z" }, + { url = "https://files.pythonhosted.org/packages/6a/1e/71dfd96bcc1c775420cb8befe7a9d35f2e5b1309798f009dca17b7708c1e/tomli-2.4.1-cp313-cp313-win_amd64.whl", hash = "sha256:8d65a2fbf9d2f8352685bc1364177ee3923d6baf5e7f43ea4959d7d8bc326a36", size = 108755, upload-time = "2026-03-25T20:21:40.248Z" }, + { url = "https://files.pythonhosted.org/packages/83/7a/d34f422a021d62420b78f5c538e5b102f62bea616d1d75a13f0a88acb04a/tomli-2.4.1-cp313-cp313-win_arm64.whl", hash = "sha256:4b605484e43cdc43f0954ddae319fb75f04cc10dd80d830540060ee7cd0243cd", size = 95265, upload-time = "2026-03-25T20:21:41.219Z" }, + { url = "https://files.pythonhosted.org/packages/3c/fb/9a5c8d27dbab540869f7c1f8eb0abb3244189ce780ba9cd73f3770662072/tomli-2.4.1-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:fd0409a3653af6c147209d267a0e4243f0ae46b011aa978b1080359fddc9b6cf", size = 155726, upload-time = "2026-03-25T20:21:42.23Z" }, + { url = "https://files.pythonhosted.org/packages/62/05/d2f816630cc771ad836af54f5001f47a6f611d2d39535364f148b6a92d6b/tomli-2.4.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:a120733b01c45e9a0c34aeef92bf0cf1d56cfe81ed9d47d562f9ed591a9828ac", size = 149859, upload-time = "2026-03-25T20:21:43.386Z" }, + { url = "https://files.pythonhosted.org/packages/ce/48/66341bdb858ad9bd0ceab5a86f90eddab127cf8b046418009f2125630ecb/tomli-2.4.1-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:559db847dc486944896521f68d8190be1c9e719fced785720d2216fe7022b662", size = 244713, upload-time = "2026-03-25T20:21:44.474Z" }, + { url = "https://files.pythonhosted.org/packages/df/6d/c5fad00d82b3c7a3ab6189bd4b10e60466f22cfe8a08a9394185c8a8111c/tomli-2.4.1-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:01f520d4f53ef97964a240a035ec2a869fe1a37dde002b57ebc4417a27ccd853", size = 252084, upload-time = "2026-03-25T20:21:45.62Z" }, + { url = "https://files.pythonhosted.org/packages/00/71/3a69e86f3eafe8c7a59d008d245888051005bd657760e96d5fbfb0b740c2/tomli-2.4.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:7f94b27a62cfad8496c8d2513e1a222dd446f095fca8987fceef261225538a15", size = 247973, upload-time = "2026-03-25T20:21:46.937Z" }, + { url = "https://files.pythonhosted.org/packages/67/50/361e986652847fec4bd5e4a0208752fbe64689c603c7ae5ea7cb16b1c0ca/tomli-2.4.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:ede3e6487c5ef5d28634ba3f31f989030ad6af71edfb0055cbbd14189ff240ba", size = 256223, upload-time = "2026-03-25T20:21:48.467Z" }, + { url = "https://files.pythonhosted.org/packages/8c/9a/b4173689a9203472e5467217e0154b00e260621caa227b6fa01feab16998/tomli-2.4.1-cp314-cp314-win32.whl", hash = "sha256:3d48a93ee1c9b79c04bb38772ee1b64dcf18ff43085896ea460ca8dec96f35f6", size = 98973, upload-time = "2026-03-25T20:21:49.526Z" }, + { url = "https://files.pythonhosted.org/packages/14/58/640ac93bf230cd27d002462c9af0d837779f8773bc03dee06b5835208214/tomli-2.4.1-cp314-cp314-win_amd64.whl", hash = "sha256:88dceee75c2c63af144e456745e10101eb67361050196b0b6af5d717254dddf7", size = 109082, upload-time = "2026-03-25T20:21:50.506Z" }, + { url = "https://files.pythonhosted.org/packages/d5/2f/702d5e05b227401c1068f0d386d79a589bb12bf64c3d2c72ce0631e3bc49/tomli-2.4.1-cp314-cp314-win_arm64.whl", hash = "sha256:b8c198f8c1805dc42708689ed6864951fd2494f924149d3e4bce7710f8eb5232", size = 96490, upload-time = "2026-03-25T20:21:51.474Z" }, + { url = "https://files.pythonhosted.org/packages/45/4b/b877b05c8ba62927d9865dd980e34a755de541eb65fffba52b4cc495d4d2/tomli-2.4.1-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:d4d8fe59808a54658fcc0160ecfb1b30f9089906c50b23bcb4c69eddc19ec2b4", size = 164263, upload-time = "2026-03-25T20:21:52.543Z" }, + { url = "https://files.pythonhosted.org/packages/24/79/6ab420d37a270b89f7195dec5448f79400d9e9c1826df982f3f8e97b24fd/tomli-2.4.1-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:7008df2e7655c495dd12d2a4ad038ff878d4ca4b81fccaf82b714e07eae4402c", size = 160736, upload-time = "2026-03-25T20:21:53.674Z" }, + { url = "https://files.pythonhosted.org/packages/02/e0/3630057d8eb170310785723ed5adcdfb7d50cb7e6455f85ba8a3deed642b/tomli-2.4.1-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1d8591993e228b0c930c4bb0db464bdad97b3289fb981255d6c9a41aedc84b2d", size = 270717, upload-time = "2026-03-25T20:21:55.129Z" }, + { url = "https://files.pythonhosted.org/packages/7a/b4/1613716072e544d1a7891f548d8f9ec6ce2faf42ca65acae01d76ea06bb0/tomli-2.4.1-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:734e20b57ba95624ecf1841e72b53f6e186355e216e5412de414e3c51e5e3c41", size = 278461, upload-time = "2026-03-25T20:21:56.228Z" }, + { url = "https://files.pythonhosted.org/packages/05/38/30f541baf6a3f6df77b3df16b01ba319221389e2da59427e221ef417ac0c/tomli-2.4.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:8a650c2dbafa08d42e51ba0b62740dae4ecb9338eefa093aa5c78ceb546fcd5c", size = 274855, upload-time = "2026-03-25T20:21:57.653Z" }, + { url = "https://files.pythonhosted.org/packages/77/a3/ec9dd4fd2c38e98de34223b995a3b34813e6bdadf86c75314c928350ed14/tomli-2.4.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:504aa796fe0569bb43171066009ead363de03675276d2d121ac1a4572397870f", size = 283144, upload-time = "2026-03-25T20:21:59.089Z" }, + { url = "https://files.pythonhosted.org/packages/ef/be/605a6261cac79fba2ec0c9827e986e00323a1945700969b8ee0b30d85453/tomli-2.4.1-cp314-cp314t-win32.whl", hash = "sha256:b1d22e6e9387bf4739fbe23bfa80e93f6b0373a7f1b96c6227c32bef95a4d7a8", size = 108683, upload-time = "2026-03-25T20:22:00.214Z" }, + { url = "https://files.pythonhosted.org/packages/12/64/da524626d3b9cc40c168a13da8335fe1c51be12c0a63685cc6db7308daae/tomli-2.4.1-cp314-cp314t-win_amd64.whl", hash = "sha256:2c1c351919aca02858f740c6d33adea0c5deea37f9ecca1cc1ef9e884a619d26", size = 121196, upload-time = "2026-03-25T20:22:01.169Z" }, + { url = "https://files.pythonhosted.org/packages/5a/cd/e80b62269fc78fc36c9af5a6b89c835baa8af28ff5ad28c7028d60860320/tomli-2.4.1-cp314-cp314t-win_arm64.whl", hash = "sha256:eab21f45c7f66c13f2a9e0e1535309cee140182a9cdae1e041d02e47291e8396", size = 100393, upload-time = "2026-03-25T20:22:02.137Z" }, + { url = "https://files.pythonhosted.org/packages/7b/61/cceae43728b7de99d9b847560c262873a1f6c98202171fd5ed62640b494b/tomli-2.4.1-py3-none-any.whl", hash = "sha256:0d85819802132122da43cb86656f8d1f8c6587d54ae7dcaf30e90533028b49fe", size = 14583, upload-time = "2026-03-25T20:22:03.012Z" }, ] [[package]] name = "tqdm" -version = "4.67.1" +version = "4.67.3" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "colorama", marker = "sys_platform == 'win32'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/a8/4b/29b4ef32e036bb34e4ab51796dd745cdba7ed47ad142a9f4a1eb8e0c744d/tqdm-4.67.1.tar.gz", hash = "sha256:f8aef9c52c08c13a65f30ea34f4e5aac3fd1a34959879d7e59e63027286627f2", size = 169737, upload-time = "2024-11-24T20:12:22.481Z" } +sdist = { url = "https://files.pythonhosted.org/packages/09/a9/6ba95a270c6f1fbcd8dac228323f2777d886cb206987444e4bce66338dd4/tqdm-4.67.3.tar.gz", hash = "sha256:7d825f03f89244ef73f1d4ce193cb1774a8179fd96f31d7e1dcde62092b960bb", size = 169598, upload-time = "2026-02-03T17:35:53.048Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/d0/30/dc54f88dd4a2b5dc8a0279bdd7270e735851848b762aeb1c1184ed1f6b14/tqdm-4.67.1-py3-none-any.whl", hash = "sha256:26445eca388f82e72884e0d580d5464cd801a3ea01e63e5601bdff9ba6a48de2", size = 78540, upload-time = "2024-11-24T20:12:19.698Z" }, + { url = "https://files.pythonhosted.org/packages/16/e1/3079a9ff9b8e11b846c6ac5c8b5bfb7ff225eee721825310c91b3b50304f/tqdm-4.67.3-py3-none-any.whl", hash = "sha256:ee1e4c0e59148062281c49d80b25b67771a127c85fc9676d3be5f243206826bf", size = 78374, upload-time = "2026-02-03T17:35:50.982Z" }, ] [[package]] @@ -5167,6 +5259,21 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/eb/66/ab7efd8941f0bc7b2bd555b0f0471bff77df4c88e0cc31120c82737fec77/twisted-25.5.0-py3-none-any.whl", hash = "sha256:8559f654d01a54a8c3efe66d533d43f383531ebf8d81d9f9ab4769d91ca15df7", size = 3204767, upload-time = "2025-06-07T09:52:21.428Z" }, ] +[[package]] +name = "typer" +version = "0.24.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "annotated-doc", marker = "python_full_version < '3.14'" }, + { name = "click", marker = "python_full_version < '3.14'" }, + { name = "rich", marker = "python_full_version < '3.14'" }, + { name = "shellingham", marker = "python_full_version < '3.14'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/f5/24/cb09efec5cc954f7f9b930bf8279447d24618bb6758d4f6adf2574c41780/typer-0.24.1.tar.gz", hash = "sha256:e39b4732d65fbdcde189ae76cf7cd48aeae72919dea1fdfc16593be016256b45", size = 118613, upload-time = "2026-02-21T16:54:40.609Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/4a/91/48db081e7a63bb37284f9fbcefda7c44c277b18b0e13fbc36ea2335b71e6/typer-0.24.1-py3-none-any.whl", hash = "sha256:112c1f0ce578bfb4cab9ffdabc68f031416ebcc216536611ba21f04e9aa84c9e", size = 56085, upload-time = "2026-02-21T16:54:41.616Z" }, +] + [[package]] name = "types-aioboto3" version = "15.5.0" @@ -5189,15 +5296,15 @@ s3 = [ [[package]] name = "types-aiobotocore" -version = "2.26.0.post2" +version = "3.3.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "botocore-stubs" }, { name = "typing-extensions", marker = "python_full_version < '3.12'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/3e/27/c60789f312a3630cbc82181e4d6e809bd8801b471de99f14ceb11f4c5c26/types_aiobotocore-2.26.0.post2.tar.gz", hash = "sha256:68ebe5e9de3201442e56359af182493e2e642e855a9133a5918352cbf5ac4e2d", size = 86472, upload-time = "2025-12-02T16:52:55.101Z" } +sdist = { url = "https://files.pythonhosted.org/packages/e7/93/e22753dc6b941093f19f0bfe87af5424e00310eaf52dd7d0d8306a6fe094/types_aiobotocore-3.3.0.tar.gz", hash = "sha256:c754c2888631d56c370cab4d2108da2bfd3afe80049303fb7132004ead3b21d6", size = 86908, upload-time = "2026-03-19T02:35:49.176Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/3d/47/e080e365376619d4062da8989747ecf7c8404bd94b2de10904239a3104f0/types_aiobotocore-2.26.0.post2-py3-none-any.whl", hash = "sha256:0e19caffd6ce6b1c3e7ba5b085d1d03357672e1aa65e5bcdfd9efb026a1041f7", size = 54207, upload-time = "2025-12-02T16:52:48.246Z" }, + { url = "https://files.pythonhosted.org/packages/97/c7/53a786a82bde6307fd79059357c1d2f510667019d78dd71d8787c49bec7f/types_aiobotocore-3.3.0-py3-none-any.whl", hash = "sha256:017e9666d5cba2c26134256ad5e4efb320a68352358b9f3257b4e2aae3fb4c18", size = 54364, upload-time = "2026-03-19T02:35:45.567Z" }, ] [[package]] @@ -5223,23 +5330,23 @@ wheels = [ [[package]] name = "types-protobuf" -version = "6.32.1.20250918" +version = "6.32.1.20260221" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/69/5a/bd06c2dbb77ebd4ea764473c9c4c014c7ba94432192cb965a274f8544b9d/types_protobuf-6.32.1.20250918.tar.gz", hash = "sha256:44ce0ae98475909ca72379946ab61a4435eec2a41090821e713c17e8faf5b88f", size = 63780, upload-time = "2025-09-18T02:50:39.391Z" } +sdist = { url = "https://files.pythonhosted.org/packages/5f/e2/9aa4a3b2469508bd7b4e2ae11cbedaf419222a09a1b94daffcd5efca4023/types_protobuf-6.32.1.20260221.tar.gz", hash = "sha256:6d5fb060a616bfb076cbb61b4b3c3969f5fc8bec5810f9a2f7e648ee5cbcbf6e", size = 64408, upload-time = "2026-02-21T03:55:13.916Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/37/5a/8d93d4f4af5dc3dd62aa4f020deae746b34b1d94fb5bee1f776c6b7e9d6c/types_protobuf-6.32.1.20250918-py3-none-any.whl", hash = "sha256:22ba6133d142d11cc34d3788ad6dead2732368ebb0406eaa7790ea6ae46c8d0b", size = 77885, upload-time = "2025-09-18T02:50:38.028Z" }, + { url = "https://files.pythonhosted.org/packages/2e/e8/1fd38926f9cf031188fbc5a96694203ea6f24b0e34bd64a225ec6f6291ba/types_protobuf-6.32.1.20260221-py3-none-any.whl", hash = "sha256:da7cdd947975964a93c30bfbcc2c6841ee646b318d3816b033adc2c4eb6448e4", size = 77956, upload-time = "2026-02-21T03:55:12.894Z" }, ] [[package]] name = "types-requests" -version = "2.32.4.20250913" +version = "2.33.0.20260402" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "urllib3" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/36/27/489922f4505975b11de2b5ad07b4fe1dca0bca9be81a703f26c5f3acfce5/types_requests-2.32.4.20250913.tar.gz", hash = "sha256:abd6d4f9ce3a9383f269775a9835a4c24e5cd6b9f647d64f88aa4613c33def5d", size = 23113, upload-time = "2025-09-13T02:40:02.309Z" } +sdist = { url = "https://files.pythonhosted.org/packages/c1/7b/a06527d20af1441d813360b8e0ce152a75b7d8e4aab7c7d0a156f405d7ec/types_requests-2.33.0.20260402.tar.gz", hash = "sha256:1bdd3ada9b869741c5c4b887d2c8b4e38284a1449751823b5ebbccba3eefd9da", size = 23851, upload-time = "2026-04-02T04:19:55.942Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/2a/20/9a227ea57c1285986c4cf78400d0a91615d25b24e257fd9e2969606bdfae/types_requests-2.32.4.20250913-py3-none-any.whl", hash = "sha256:78c9c1fffebbe0fa487a418e0fa5252017e9c60d1a2da394077f1780f655d7e1", size = 20658, upload-time = "2025-09-13T02:40:01.115Z" }, + { url = "https://files.pythonhosted.org/packages/51/65/3853bb6bac5ae789dc7e28781154705c27859eccc8e46282c3f36780f5f5/types_requests-2.33.0.20260402-py3-none-any.whl", hash = "sha256:c98372d7124dd5d10af815ee25c013897592ff92af27b27e22c98984102c3254", size = 20739, upload-time = "2026-04-02T04:19:54.955Z" }, ] [[package]] @@ -5274,11 +5381,11 @@ wheels = [ [[package]] name = "tzdata" -version = "2025.3" +version = "2026.1" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/5e/a7/c202b344c5ca7daf398f3b8a477eeb205cf3b6f32e7ec3a6bac0629ca975/tzdata-2025.3.tar.gz", hash = "sha256:de39c2ca5dc7b0344f2eba86f49d614019d29f060fc4ebc8a417896a620b56a7", size = 196772, upload-time = "2025-12-13T17:45:35.667Z" } +sdist = { url = "https://files.pythonhosted.org/packages/19/f5/cd531b2d15a671a40c0f66cf06bc3570a12cd56eef98960068ebbad1bf5a/tzdata-2026.1.tar.gz", hash = "sha256:67658a1903c75917309e753fdc349ac0efd8c27db7a0cb406a25be4840f87f98", size = 197639, upload-time = "2026-04-03T11:25:22.002Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/c7/b0/003792df09decd6849a5e39c28b513c06e84436a54440380862b5aeff25d/tzdata-2025.3-py2.py3-none-any.whl", hash = "sha256:06a47e5700f3081aab02b2e513160914ff0694bce9947d6b76ebd6bf57cfc5d1", size = 348521, upload-time = "2025-12-13T17:45:33.889Z" }, + { url = "https://files.pythonhosted.org/packages/b0/70/d460bd685a170790ec89317e9bd33047988e4bce507b831f5db771e142de/tzdata-2026.1-py2.py3-none-any.whl", hash = "sha256:4b1d2be7ac37ceafd7327b961aa3a54e467efbdb563a23655fbfe0d39cfc42a9", size = 348952, upload-time = "2026-04-03T11:25:20.313Z" }, ] [[package]] @@ -5313,16 +5420,16 @@ wheels = [ [[package]] name = "uvicorn" -version = "0.37.0" +version = "0.44.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "click" }, { name = "h11" }, { name = "typing-extensions", marker = "python_full_version < '3.11'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/71/57/1616c8274c3442d802621abf5deb230771c7a0fec9414cb6763900eb3868/uvicorn-0.37.0.tar.gz", hash = "sha256:4115c8add6d3fd536c8ee77f0e14a7fd2ebba939fed9b02583a97f80648f9e13", size = 80367, upload-time = "2025-09-23T13:33:47.486Z" } +sdist = { url = "https://files.pythonhosted.org/packages/5e/da/6eee1ff8b6cbeed47eeb5229749168e81eb4b7b999a1a15a7176e51410c9/uvicorn-0.44.0.tar.gz", hash = "sha256:6c942071b68f07e178264b9152f1f16dfac5da85880c4ce06366a96d70d4f31e", size = 86947, upload-time = "2026-04-06T09:23:22.826Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/85/cd/584a2ceb5532af99dd09e50919e3615ba99aa127e9850eafe5f31ddfdb9a/uvicorn-0.37.0-py3-none-any.whl", hash = "sha256:913b2b88672343739927ce381ff9e2ad62541f9f8289664fa1d1d3803fa2ce6c", size = 67976, upload-time = "2025-09-23T13:33:45.842Z" }, + { url = "https://files.pythonhosted.org/packages/b7/23/a5bbd9600dd607411fa644c06ff4951bec3a4d82c4b852374024359c19c0/uvicorn-0.44.0-py3-none-any.whl", hash = "sha256:ce937c99a2cc70279556967274414c087888e8cec9f9c94644dfca11bd3ced89", size = 69425, upload-time = "2026-04-06T09:23:21.524Z" }, ] [[package]] @@ -5418,14 +5525,14 @@ wheels = [ [[package]] name = "werkzeug" -version = "3.1.6" +version = "3.1.8" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "markupsafe" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/61/f1/ee81806690a87dab5f5653c1f146c92bc066d7f4cebc603ef88eb9e13957/werkzeug-3.1.6.tar.gz", hash = "sha256:210c6bede5a420a913956b4791a7f4d6843a43b6fcee4dfa08a65e93007d0d25", size = 864736, upload-time = "2026-02-19T15:17:18.884Z" } +sdist = { url = "https://files.pythonhosted.org/packages/dd/b2/381be8cfdee792dd117872481b6e378f85c957dd7c5bca38897b08f765fd/werkzeug-3.1.8.tar.gz", hash = "sha256:9bad61a4268dac112f1c5cd4630a56ede601b6ed420300677a869083d70a4c44", size = 875852, upload-time = "2026-04-02T18:49:14.268Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/4d/ec/d58832f89ede95652fd01f4f24236af7d32b70cab2196dfcc2d2fd13c5c2/werkzeug-3.1.6-py3-none-any.whl", hash = "sha256:7ddf3357bb9564e407607f988f683d72038551200c704012bb9a4c523d42f131", size = 225166, upload-time = "2026-02-19T15:17:17.475Z" }, + { url = "https://files.pythonhosted.org/packages/93/8c/2e650f2afeb7ee576912636c23ddb621c91ac6a98e66dc8d29c3c69446e1/werkzeug-3.1.8-py3-none-any.whl", hash = "sha256:63a77fb8892bf28ebc3178683445222aa500e48ebad5ec77b0ad80f8726b1f50", size = 226459, upload-time = "2026-04-02T18:49:12.72Z" }, ] [[package]] @@ -5508,128 +5615,142 @@ wheels = [ [[package]] name = "yarl" -version = "1.22.0" +version = "1.23.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "idna" }, { name = "multidict" }, { name = "propcache" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/57/63/0c6ebca57330cd313f6102b16dd57ffaf3ec4c83403dcb45dbd15c6f3ea1/yarl-1.22.0.tar.gz", hash = "sha256:bebf8557577d4401ba8bd9ff33906f1376c877aa78d1fe216ad01b4d6745af71", size = 187169, upload-time = "2025-10-06T14:12:55.963Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/d1/43/a2204825342f37c337f5edb6637040fa14e365b2fcc2346960201d457579/yarl-1.22.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:c7bd6683587567e5a49ee6e336e0612bec8329be1b7d4c8af5687dcdeb67ee1e", size = 140517, upload-time = "2025-10-06T14:08:42.494Z" }, - { url = "https://files.pythonhosted.org/packages/44/6f/674f3e6f02266428c56f704cd2501c22f78e8b2eeb23f153117cc86fb28a/yarl-1.22.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:5cdac20da754f3a723cceea5b3448e1a2074866406adeb4ef35b469d089adb8f", size = 93495, upload-time = "2025-10-06T14:08:46.2Z" }, - { url = "https://files.pythonhosted.org/packages/b8/12/5b274d8a0f30c07b91b2f02cba69152600b47830fcfb465c108880fcee9c/yarl-1.22.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:07a524d84df0c10f41e3ee918846e1974aba4ec017f990dc735aad487a0bdfdf", size = 94400, upload-time = "2025-10-06T14:08:47.855Z" }, - { url = "https://files.pythonhosted.org/packages/e2/7f/df1b6949b1fa1aa9ff6de6e2631876ad4b73c4437822026e85d8acb56bb1/yarl-1.22.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e1b329cb8146d7b736677a2440e422eadd775d1806a81db2d4cded80a48efc1a", size = 347545, upload-time = "2025-10-06T14:08:49.683Z" }, - { url = "https://files.pythonhosted.org/packages/84/09/f92ed93bd6cd77872ab6c3462df45ca45cd058d8f1d0c9b4f54c1704429f/yarl-1.22.0-cp310-cp310-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:75976c6945d85dbb9ee6308cd7ff7b1fb9409380c82d6119bd778d8fcfe2931c", size = 319598, upload-time = "2025-10-06T14:08:51.215Z" }, - { url = "https://files.pythonhosted.org/packages/c3/97/ac3f3feae7d522cf7ccec3d340bb0b2b61c56cb9767923df62a135092c6b/yarl-1.22.0-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:80ddf7a5f8c86cb3eb4bc9028b07bbbf1f08a96c5c0bc1244be5e8fefcb94147", size = 363893, upload-time = "2025-10-06T14:08:53.144Z" }, - { url = "https://files.pythonhosted.org/packages/06/49/f3219097403b9c84a4d079b1d7bda62dd9b86d0d6e4428c02d46ab2c77fc/yarl-1.22.0-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:d332fc2e3c94dad927f2112395772a4e4fedbcf8f80efc21ed7cdfae4d574fdb", size = 371240, upload-time = "2025-10-06T14:08:55.036Z" }, - { url = "https://files.pythonhosted.org/packages/35/9f/06b765d45c0e44e8ecf0fe15c9eacbbde342bb5b7561c46944f107bfb6c3/yarl-1.22.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0cf71bf877efeac18b38d3930594c0948c82b64547c1cf420ba48722fe5509f6", size = 346965, upload-time = "2025-10-06T14:08:56.722Z" }, - { url = "https://files.pythonhosted.org/packages/c5/69/599e7cea8d0fcb1694323b0db0dda317fa3162f7b90166faddecf532166f/yarl-1.22.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:663e1cadaddae26be034a6ab6072449a8426ddb03d500f43daf952b74553bba0", size = 342026, upload-time = "2025-10-06T14:08:58.563Z" }, - { url = "https://files.pythonhosted.org/packages/95/6f/9dfd12c8bc90fea9eab39832ee32ea48f8e53d1256252a77b710c065c89f/yarl-1.22.0-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:6dcbb0829c671f305be48a7227918cfcd11276c2d637a8033a99a02b67bf9eda", size = 335637, upload-time = "2025-10-06T14:09:00.506Z" }, - { url = "https://files.pythonhosted.org/packages/57/2e/34c5b4eb9b07e16e873db5b182c71e5f06f9b5af388cdaa97736d79dd9a6/yarl-1.22.0-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:f0d97c18dfd9a9af4490631905a3f131a8e4c9e80a39353919e2cfed8f00aedc", size = 359082, upload-time = "2025-10-06T14:09:01.936Z" }, - { url = "https://files.pythonhosted.org/packages/31/71/fa7e10fb772d273aa1f096ecb8ab8594117822f683bab7d2c5a89914c92a/yarl-1.22.0-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:437840083abe022c978470b942ff832c3940b2ad3734d424b7eaffcd07f76737", size = 357811, upload-time = "2025-10-06T14:09:03.445Z" }, - { url = "https://files.pythonhosted.org/packages/26/da/11374c04e8e1184a6a03cf9c8f5688d3e5cec83ed6f31ad3481b3207f709/yarl-1.22.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:a899cbd98dce6f5d8de1aad31cb712ec0a530abc0a86bd6edaa47c1090138467", size = 351223, upload-time = "2025-10-06T14:09:05.401Z" }, - { url = "https://files.pythonhosted.org/packages/82/8f/e2d01f161b0c034a30410e375e191a5d27608c1f8693bab1a08b089ca096/yarl-1.22.0-cp310-cp310-win32.whl", hash = "sha256:595697f68bd1f0c1c159fcb97b661fc9c3f5db46498043555d04805430e79bea", size = 82118, upload-time = "2025-10-06T14:09:11.148Z" }, - { url = "https://files.pythonhosted.org/packages/62/46/94c76196642dbeae634c7a61ba3da88cd77bed875bf6e4a8bed037505aa6/yarl-1.22.0-cp310-cp310-win_amd64.whl", hash = "sha256:cb95a9b1adaa48e41815a55ae740cfda005758104049a640a398120bf02515ca", size = 86852, upload-time = "2025-10-06T14:09:12.958Z" }, - { url = "https://files.pythonhosted.org/packages/af/af/7df4f179d3b1a6dcb9a4bd2ffbc67642746fcafdb62580e66876ce83fff4/yarl-1.22.0-cp310-cp310-win_arm64.whl", hash = "sha256:b85b982afde6df99ecc996990d4ad7ccbdbb70e2a4ba4de0aecde5922ba98a0b", size = 82012, upload-time = "2025-10-06T14:09:14.664Z" }, - { url = "https://files.pythonhosted.org/packages/4d/27/5ab13fc84c76a0250afd3d26d5936349a35be56ce5785447d6c423b26d92/yarl-1.22.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:1ab72135b1f2db3fed3997d7e7dc1b80573c67138023852b6efb336a5eae6511", size = 141607, upload-time = "2025-10-06T14:09:16.298Z" }, - { url = "https://files.pythonhosted.org/packages/6a/a1/d065d51d02dc02ce81501d476b9ed2229d9a990818332242a882d5d60340/yarl-1.22.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:669930400e375570189492dc8d8341301578e8493aec04aebc20d4717f899dd6", size = 94027, upload-time = "2025-10-06T14:09:17.786Z" }, - { url = "https://files.pythonhosted.org/packages/c1/da/8da9f6a53f67b5106ffe902c6fa0164e10398d4e150d85838b82f424072a/yarl-1.22.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:792a2af6d58177ef7c19cbf0097aba92ca1b9cb3ffdd9c7470e156c8f9b5e028", size = 94963, upload-time = "2025-10-06T14:09:19.662Z" }, - { url = "https://files.pythonhosted.org/packages/68/fe/2c1f674960c376e29cb0bec1249b117d11738db92a6ccc4a530b972648db/yarl-1.22.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3ea66b1c11c9150f1372f69afb6b8116f2dd7286f38e14ea71a44eee9ec51b9d", size = 368406, upload-time = "2025-10-06T14:09:21.402Z" }, - { url = "https://files.pythonhosted.org/packages/95/26/812a540e1c3c6418fec60e9bbd38e871eaba9545e94fa5eff8f4a8e28e1e/yarl-1.22.0-cp311-cp311-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:3e2daa88dc91870215961e96a039ec73e4937da13cf77ce17f9cad0c18df3503", size = 336581, upload-time = "2025-10-06T14:09:22.98Z" }, - { url = "https://files.pythonhosted.org/packages/0b/f5/5777b19e26fdf98563985e481f8be3d8a39f8734147a6ebf459d0dab5a6b/yarl-1.22.0-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:ba440ae430c00eee41509353628600212112cd5018d5def7e9b05ea7ac34eb65", size = 388924, upload-time = "2025-10-06T14:09:24.655Z" }, - { url = "https://files.pythonhosted.org/packages/86/08/24bd2477bd59c0bbd994fe1d93b126e0472e4e3df5a96a277b0a55309e89/yarl-1.22.0-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:e6438cc8f23a9c1478633d216b16104a586b9761db62bfacb6425bac0a36679e", size = 392890, upload-time = "2025-10-06T14:09:26.617Z" }, - { url = "https://files.pythonhosted.org/packages/46/00/71b90ed48e895667ecfb1eaab27c1523ee2fa217433ed77a73b13205ca4b/yarl-1.22.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4c52a6e78aef5cf47a98ef8e934755abf53953379b7d53e68b15ff4420e6683d", size = 365819, upload-time = "2025-10-06T14:09:28.544Z" }, - { url = "https://files.pythonhosted.org/packages/30/2d/f715501cae832651d3282387c6a9236cd26bd00d0ff1e404b3dc52447884/yarl-1.22.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:3b06bcadaac49c70f4c88af4ffcfbe3dc155aab3163e75777818092478bcbbe7", size = 363601, upload-time = "2025-10-06T14:09:30.568Z" }, - { url = "https://files.pythonhosted.org/packages/f8/f9/a678c992d78e394e7126ee0b0e4e71bd2775e4334d00a9278c06a6cce96a/yarl-1.22.0-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:6944b2dc72c4d7f7052683487e3677456050ff77fcf5e6204e98caf785ad1967", size = 358072, upload-time = "2025-10-06T14:09:32.528Z" }, - { url = "https://files.pythonhosted.org/packages/2c/d1/b49454411a60edb6fefdcad4f8e6dbba7d8019e3a508a1c5836cba6d0781/yarl-1.22.0-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:d5372ca1df0f91a86b047d1277c2aaf1edb32d78bbcefffc81b40ffd18f027ed", size = 385311, upload-time = "2025-10-06T14:09:34.634Z" }, - { url = "https://files.pythonhosted.org/packages/87/e5/40d7a94debb8448c7771a916d1861d6609dddf7958dc381117e7ba36d9e8/yarl-1.22.0-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:51af598701f5299012b8416486b40fceef8c26fc87dc6d7d1f6fc30609ea0aa6", size = 381094, upload-time = "2025-10-06T14:09:36.268Z" }, - { url = "https://files.pythonhosted.org/packages/35/d8/611cc282502381ad855448643e1ad0538957fc82ae83dfe7762c14069e14/yarl-1.22.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:b266bd01fedeffeeac01a79ae181719ff848a5a13ce10075adbefc8f1daee70e", size = 370944, upload-time = "2025-10-06T14:09:37.872Z" }, - { url = "https://files.pythonhosted.org/packages/2d/df/fadd00fb1c90e1a5a8bd731fa3d3de2e165e5a3666a095b04e31b04d9cb6/yarl-1.22.0-cp311-cp311-win32.whl", hash = "sha256:a9b1ba5610a4e20f655258d5a1fdc7ebe3d837bb0e45b581398b99eb98b1f5ca", size = 81804, upload-time = "2025-10-06T14:09:39.359Z" }, - { url = "https://files.pythonhosted.org/packages/b5/f7/149bb6f45f267cb5c074ac40c01c6b3ea6d8a620d34b337f6321928a1b4d/yarl-1.22.0-cp311-cp311-win_amd64.whl", hash = "sha256:078278b9b0b11568937d9509b589ee83ef98ed6d561dfe2020e24a9fd08eaa2b", size = 86858, upload-time = "2025-10-06T14:09:41.068Z" }, - { url = "https://files.pythonhosted.org/packages/2b/13/88b78b93ad3f2f0b78e13bfaaa24d11cbc746e93fe76d8c06bf139615646/yarl-1.22.0-cp311-cp311-win_arm64.whl", hash = "sha256:b6a6f620cfe13ccec221fa312139135166e47ae169f8253f72a0abc0dae94376", size = 81637, upload-time = "2025-10-06T14:09:42.712Z" }, - { url = "https://files.pythonhosted.org/packages/75/ff/46736024fee3429b80a165a732e38e5d5a238721e634ab41b040d49f8738/yarl-1.22.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:e340382d1afa5d32b892b3ff062436d592ec3d692aeea3bef3a5cfe11bbf8c6f", size = 142000, upload-time = "2025-10-06T14:09:44.631Z" }, - { url = "https://files.pythonhosted.org/packages/5a/9a/b312ed670df903145598914770eb12de1bac44599549b3360acc96878df8/yarl-1.22.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:f1e09112a2c31ffe8d80be1b0988fa6a18c5d5cad92a9ffbb1c04c91bfe52ad2", size = 94338, upload-time = "2025-10-06T14:09:46.372Z" }, - { url = "https://files.pythonhosted.org/packages/ba/f5/0601483296f09c3c65e303d60c070a5c19fcdbc72daa061e96170785bc7d/yarl-1.22.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:939fe60db294c786f6b7c2d2e121576628468f65453d86b0fe36cb52f987bd74", size = 94909, upload-time = "2025-10-06T14:09:48.648Z" }, - { url = "https://files.pythonhosted.org/packages/60/41/9a1fe0b73dbcefce72e46cf149b0e0a67612d60bfc90fb59c2b2efdfbd86/yarl-1.22.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e1651bf8e0398574646744c1885a41198eba53dc8a9312b954073f845c90a8df", size = 372940, upload-time = "2025-10-06T14:09:50.089Z" }, - { url = "https://files.pythonhosted.org/packages/17/7a/795cb6dfee561961c30b800f0ed616b923a2ec6258b5def2a00bf8231334/yarl-1.22.0-cp312-cp312-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:b8a0588521a26bf92a57a1705b77b8b59044cdceccac7151bd8d229e66b8dedb", size = 345825, upload-time = "2025-10-06T14:09:52.142Z" }, - { url = "https://files.pythonhosted.org/packages/d7/93/a58f4d596d2be2ae7bab1a5846c4d270b894958845753b2c606d666744d3/yarl-1.22.0-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:42188e6a615c1a75bcaa6e150c3fe8f3e8680471a6b10150c5f7e83f47cc34d2", size = 386705, upload-time = "2025-10-06T14:09:54.128Z" }, - { url = "https://files.pythonhosted.org/packages/61/92/682279d0e099d0e14d7fd2e176bd04f48de1484f56546a3e1313cd6c8e7c/yarl-1.22.0-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:f6d2cb59377d99718913ad9a151030d6f83ef420a2b8f521d94609ecc106ee82", size = 396518, upload-time = "2025-10-06T14:09:55.762Z" }, - { url = "https://files.pythonhosted.org/packages/db/0f/0d52c98b8a885aeda831224b78f3be7ec2e1aa4a62091f9f9188c3c65b56/yarl-1.22.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:50678a3b71c751d58d7908edc96d332af328839eea883bb554a43f539101277a", size = 377267, upload-time = "2025-10-06T14:09:57.958Z" }, - { url = "https://files.pythonhosted.org/packages/22/42/d2685e35908cbeaa6532c1fc73e89e7f2efb5d8a7df3959ea8e37177c5a3/yarl-1.22.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:1e8fbaa7cec507aa24ea27a01456e8dd4b6fab829059b69844bd348f2d467124", size = 365797, upload-time = "2025-10-06T14:09:59.527Z" }, - { url = "https://files.pythonhosted.org/packages/a2/83/cf8c7bcc6355631762f7d8bdab920ad09b82efa6b722999dfb05afa6cfac/yarl-1.22.0-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:433885ab5431bc3d3d4f2f9bd15bfa1614c522b0f1405d62c4f926ccd69d04fa", size = 365535, upload-time = "2025-10-06T14:10:01.139Z" }, - { url = "https://files.pythonhosted.org/packages/25/e1/5302ff9b28f0c59cac913b91fe3f16c59a033887e57ce9ca5d41a3a94737/yarl-1.22.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:b790b39c7e9a4192dc2e201a282109ed2985a1ddbd5ac08dc56d0e121400a8f7", size = 382324, upload-time = "2025-10-06T14:10:02.756Z" }, - { url = "https://files.pythonhosted.org/packages/bf/cd/4617eb60f032f19ae3a688dc990d8f0d89ee0ea378b61cac81ede3e52fae/yarl-1.22.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:31f0b53913220599446872d757257be5898019c85e7971599065bc55065dc99d", size = 383803, upload-time = "2025-10-06T14:10:04.552Z" }, - { url = "https://files.pythonhosted.org/packages/59/65/afc6e62bb506a319ea67b694551dab4a7e6fb7bf604e9bd9f3e11d575fec/yarl-1.22.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:a49370e8f711daec68d09b821a34e1167792ee2d24d405cbc2387be4f158b520", size = 374220, upload-time = "2025-10-06T14:10:06.489Z" }, - { url = "https://files.pythonhosted.org/packages/e7/3d/68bf18d50dc674b942daec86a9ba922d3113d8399b0e52b9897530442da2/yarl-1.22.0-cp312-cp312-win32.whl", hash = "sha256:70dfd4f241c04bd9239d53b17f11e6ab672b9f1420364af63e8531198e3f5fe8", size = 81589, upload-time = "2025-10-06T14:10:09.254Z" }, - { url = "https://files.pythonhosted.org/packages/c8/9a/6ad1a9b37c2f72874f93e691b2e7ecb6137fb2b899983125db4204e47575/yarl-1.22.0-cp312-cp312-win_amd64.whl", hash = "sha256:8884d8b332a5e9b88e23f60bb166890009429391864c685e17bd73a9eda9105c", size = 87213, upload-time = "2025-10-06T14:10:11.369Z" }, - { url = "https://files.pythonhosted.org/packages/44/c5/c21b562d1680a77634d748e30c653c3ca918beb35555cff24986fff54598/yarl-1.22.0-cp312-cp312-win_arm64.whl", hash = "sha256:ea70f61a47f3cc93bdf8b2f368ed359ef02a01ca6393916bc8ff877427181e74", size = 81330, upload-time = "2025-10-06T14:10:13.112Z" }, - { url = "https://files.pythonhosted.org/packages/ea/f3/d67de7260456ee105dc1d162d43a019ecad6b91e2f51809d6cddaa56690e/yarl-1.22.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:8dee9c25c74997f6a750cd317b8ca63545169c098faee42c84aa5e506c819b53", size = 139980, upload-time = "2025-10-06T14:10:14.601Z" }, - { url = "https://files.pythonhosted.org/packages/01/88/04d98af0b47e0ef42597b9b28863b9060bb515524da0a65d5f4db160b2d5/yarl-1.22.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:01e73b85a5434f89fc4fe27dcda2aff08ddf35e4d47bbbea3bdcd25321af538a", size = 93424, upload-time = "2025-10-06T14:10:16.115Z" }, - { url = "https://files.pythonhosted.org/packages/18/91/3274b215fd8442a03975ce6bee5fe6aa57a8326b29b9d3d56234a1dca244/yarl-1.22.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:22965c2af250d20c873cdbee8ff958fb809940aeb2e74ba5f20aaf6b7ac8c70c", size = 93821, upload-time = "2025-10-06T14:10:17.993Z" }, - { url = "https://files.pythonhosted.org/packages/61/3a/caf4e25036db0f2da4ca22a353dfeb3c9d3c95d2761ebe9b14df8fc16eb0/yarl-1.22.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b4f15793aa49793ec8d1c708ab7f9eded1aa72edc5174cae703651555ed1b601", size = 373243, upload-time = "2025-10-06T14:10:19.44Z" }, - { url = "https://files.pythonhosted.org/packages/6e/9e/51a77ac7516e8e7803b06e01f74e78649c24ee1021eca3d6a739cb6ea49c/yarl-1.22.0-cp313-cp313-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:e5542339dcf2747135c5c85f68680353d5cb9ffd741c0f2e8d832d054d41f35a", size = 342361, upload-time = "2025-10-06T14:10:21.124Z" }, - { url = "https://files.pythonhosted.org/packages/d4/f8/33b92454789dde8407f156c00303e9a891f1f51a0330b0fad7c909f87692/yarl-1.22.0-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:5c401e05ad47a75869c3ab3e35137f8468b846770587e70d71e11de797d113df", size = 387036, upload-time = "2025-10-06T14:10:22.902Z" }, - { url = "https://files.pythonhosted.org/packages/d9/9a/c5db84ea024f76838220280f732970aa4ee154015d7f5c1bfb60a267af6f/yarl-1.22.0-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:243dda95d901c733f5b59214d28b0120893d91777cb8aa043e6ef059d3cddfe2", size = 397671, upload-time = "2025-10-06T14:10:24.523Z" }, - { url = "https://files.pythonhosted.org/packages/11/c9/cd8538dc2e7727095e0c1d867bad1e40c98f37763e6d995c1939f5fdc7b1/yarl-1.22.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:bec03d0d388060058f5d291a813f21c011041938a441c593374da6077fe21b1b", size = 377059, upload-time = "2025-10-06T14:10:26.406Z" }, - { url = "https://files.pythonhosted.org/packages/a1/b9/ab437b261702ced75122ed78a876a6dec0a1b0f5e17a4ac7a9a2482d8abe/yarl-1.22.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:b0748275abb8c1e1e09301ee3cf90c8a99678a4e92e4373705f2a2570d581273", size = 365356, upload-time = "2025-10-06T14:10:28.461Z" }, - { url = "https://files.pythonhosted.org/packages/b2/9d/8e1ae6d1d008a9567877b08f0ce4077a29974c04c062dabdb923ed98e6fe/yarl-1.22.0-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:47fdb18187e2a4e18fda2c25c05d8251a9e4a521edaed757fef033e7d8498d9a", size = 361331, upload-time = "2025-10-06T14:10:30.541Z" }, - { url = "https://files.pythonhosted.org/packages/ca/5a/09b7be3905962f145b73beb468cdd53db8aa171cf18c80400a54c5b82846/yarl-1.22.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:c7044802eec4524fde550afc28edda0dd5784c4c45f0be151a2d3ba017daca7d", size = 382590, upload-time = "2025-10-06T14:10:33.352Z" }, - { url = "https://files.pythonhosted.org/packages/aa/7f/59ec509abf90eda5048b0bc3e2d7b5099dffdb3e6b127019895ab9d5ef44/yarl-1.22.0-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:139718f35149ff544caba20fce6e8a2f71f1e39b92c700d8438a0b1d2a631a02", size = 385316, upload-time = "2025-10-06T14:10:35.034Z" }, - { url = "https://files.pythonhosted.org/packages/e5/84/891158426bc8036bfdfd862fabd0e0fa25df4176ec793e447f4b85cf1be4/yarl-1.22.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:e1b51bebd221006d3d2f95fbe124b22b247136647ae5dcc8c7acafba66e5ee67", size = 374431, upload-time = "2025-10-06T14:10:37.76Z" }, - { url = "https://files.pythonhosted.org/packages/bb/49/03da1580665baa8bef5e8ed34c6df2c2aca0a2f28bf397ed238cc1bbc6f2/yarl-1.22.0-cp313-cp313-win32.whl", hash = "sha256:d3e32536234a95f513bd374e93d717cf6b2231a791758de6c509e3653f234c95", size = 81555, upload-time = "2025-10-06T14:10:39.649Z" }, - { url = "https://files.pythonhosted.org/packages/9a/ee/450914ae11b419eadd067c6183ae08381cfdfcb9798b90b2b713bbebddda/yarl-1.22.0-cp313-cp313-win_amd64.whl", hash = "sha256:47743b82b76d89a1d20b83e60d5c20314cbd5ba2befc9cda8f28300c4a08ed4d", size = 86965, upload-time = "2025-10-06T14:10:41.313Z" }, - { url = "https://files.pythonhosted.org/packages/98/4d/264a01eae03b6cf629ad69bae94e3b0e5344741e929073678e84bf7a3e3b/yarl-1.22.0-cp313-cp313-win_arm64.whl", hash = "sha256:5d0fcda9608875f7d052eff120c7a5da474a6796fe4d83e152e0e4d42f6d1a9b", size = 81205, upload-time = "2025-10-06T14:10:43.167Z" }, - { url = "https://files.pythonhosted.org/packages/88/fc/6908f062a2f77b5f9f6d69cecb1747260831ff206adcbc5b510aff88df91/yarl-1.22.0-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:719ae08b6972befcba4310e49edb1161a88cdd331e3a694b84466bd938a6ab10", size = 146209, upload-time = "2025-10-06T14:10:44.643Z" }, - { url = "https://files.pythonhosted.org/packages/65/47/76594ae8eab26210b4867be6f49129861ad33da1f1ebdf7051e98492bf62/yarl-1.22.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:47d8a5c446df1c4db9d21b49619ffdba90e77c89ec6e283f453856c74b50b9e3", size = 95966, upload-time = "2025-10-06T14:10:46.554Z" }, - { url = "https://files.pythonhosted.org/packages/ab/ce/05e9828a49271ba6b5b038b15b3934e996980dd78abdfeb52a04cfb9467e/yarl-1.22.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:cfebc0ac8333520d2d0423cbbe43ae43c8838862ddb898f5ca68565e395516e9", size = 97312, upload-time = "2025-10-06T14:10:48.007Z" }, - { url = "https://files.pythonhosted.org/packages/d1/c5/7dffad5e4f2265b29c9d7ec869c369e4223166e4f9206fc2243ee9eea727/yarl-1.22.0-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4398557cbf484207df000309235979c79c4356518fd5c99158c7d38203c4da4f", size = 361967, upload-time = "2025-10-06T14:10:49.997Z" }, - { url = "https://files.pythonhosted.org/packages/50/b2/375b933c93a54bff7fc041e1a6ad2c0f6f733ffb0c6e642ce56ee3b39970/yarl-1.22.0-cp313-cp313t-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:2ca6fd72a8cd803be290d42f2dec5cdcd5299eeb93c2d929bf060ad9efaf5de0", size = 323949, upload-time = "2025-10-06T14:10:52.004Z" }, - { url = "https://files.pythonhosted.org/packages/66/50/bfc2a29a1d78644c5a7220ce2f304f38248dc94124a326794e677634b6cf/yarl-1.22.0-cp313-cp313t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:ca1f59c4e1ab6e72f0a23c13fca5430f889634166be85dbf1013683e49e3278e", size = 361818, upload-time = "2025-10-06T14:10:54.078Z" }, - { url = "https://files.pythonhosted.org/packages/46/96/f3941a46af7d5d0f0498f86d71275696800ddcdd20426298e572b19b91ff/yarl-1.22.0-cp313-cp313t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:6c5010a52015e7c70f86eb967db0f37f3c8bd503a695a49f8d45700144667708", size = 372626, upload-time = "2025-10-06T14:10:55.767Z" }, - { url = "https://files.pythonhosted.org/packages/c1/42/8b27c83bb875cd89448e42cd627e0fb971fa1675c9ec546393d18826cb50/yarl-1.22.0-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9d7672ecf7557476642c88497c2f8d8542f8e36596e928e9bcba0e42e1e7d71f", size = 341129, upload-time = "2025-10-06T14:10:57.985Z" }, - { url = "https://files.pythonhosted.org/packages/49/36/99ca3122201b382a3cf7cc937b95235b0ac944f7e9f2d5331d50821ed352/yarl-1.22.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:3b7c88eeef021579d600e50363e0b6ee4f7f6f728cd3486b9d0f3ee7b946398d", size = 346776, upload-time = "2025-10-06T14:10:59.633Z" }, - { url = "https://files.pythonhosted.org/packages/85/b4/47328bf996acd01a4c16ef9dcd2f59c969f495073616586f78cd5f2efb99/yarl-1.22.0-cp313-cp313t-musllinux_1_2_armv7l.whl", hash = "sha256:f4afb5c34f2c6fecdcc182dfcfc6af6cccf1aa923eed4d6a12e9d96904e1a0d8", size = 334879, upload-time = "2025-10-06T14:11:01.454Z" }, - { url = "https://files.pythonhosted.org/packages/c2/ad/b77d7b3f14a4283bffb8e92c6026496f6de49751c2f97d4352242bba3990/yarl-1.22.0-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:59c189e3e99a59cf8d83cbb31d4db02d66cda5a1a4374e8a012b51255341abf5", size = 350996, upload-time = "2025-10-06T14:11:03.452Z" }, - { url = "https://files.pythonhosted.org/packages/81/c8/06e1d69295792ba54d556f06686cbd6a7ce39c22307100e3fb4a2c0b0a1d/yarl-1.22.0-cp313-cp313t-musllinux_1_2_s390x.whl", hash = "sha256:5a3bf7f62a289fa90f1990422dc8dff5a458469ea71d1624585ec3a4c8d6960f", size = 356047, upload-time = "2025-10-06T14:11:05.115Z" }, - { url = "https://files.pythonhosted.org/packages/4b/b8/4c0e9e9f597074b208d18cef227d83aac36184bfbc6eab204ea55783dbc5/yarl-1.22.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:de6b9a04c606978fdfe72666fa216ffcf2d1a9f6a381058d4378f8d7b1e5de62", size = 342947, upload-time = "2025-10-06T14:11:08.137Z" }, - { url = "https://files.pythonhosted.org/packages/e0/e5/11f140a58bf4c6ad7aca69a892bff0ee638c31bea4206748fc0df4ebcb3a/yarl-1.22.0-cp313-cp313t-win32.whl", hash = "sha256:1834bb90991cc2999f10f97f5f01317f99b143284766d197e43cd5b45eb18d03", size = 86943, upload-time = "2025-10-06T14:11:10.284Z" }, - { url = "https://files.pythonhosted.org/packages/31/74/8b74bae38ed7fe6793d0c15a0c8207bbb819cf287788459e5ed230996cdd/yarl-1.22.0-cp313-cp313t-win_amd64.whl", hash = "sha256:ff86011bd159a9d2dfc89c34cfd8aff12875980e3bd6a39ff097887520e60249", size = 93715, upload-time = "2025-10-06T14:11:11.739Z" }, - { url = "https://files.pythonhosted.org/packages/69/66/991858aa4b5892d57aef7ee1ba6b4d01ec3b7eb3060795d34090a3ca3278/yarl-1.22.0-cp313-cp313t-win_arm64.whl", hash = "sha256:7861058d0582b847bc4e3a4a4c46828a410bca738673f35a29ba3ca5db0b473b", size = 83857, upload-time = "2025-10-06T14:11:13.586Z" }, - { url = "https://files.pythonhosted.org/packages/46/b3/e20ef504049f1a1c54a814b4b9bed96d1ac0e0610c3b4da178f87209db05/yarl-1.22.0-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:34b36c2c57124530884d89d50ed2c1478697ad7473efd59cfd479945c95650e4", size = 140520, upload-time = "2025-10-06T14:11:15.465Z" }, - { url = "https://files.pythonhosted.org/packages/e4/04/3532d990fdbab02e5ede063676b5c4260e7f3abea2151099c2aa745acc4c/yarl-1.22.0-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:0dd9a702591ca2e543631c2a017e4a547e38a5c0f29eece37d9097e04a7ac683", size = 93504, upload-time = "2025-10-06T14:11:17.106Z" }, - { url = "https://files.pythonhosted.org/packages/11/63/ff458113c5c2dac9a9719ac68ee7c947cb621432bcf28c9972b1c0e83938/yarl-1.22.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:594fcab1032e2d2cc3321bb2e51271e7cd2b516c7d9aee780ece81b07ff8244b", size = 94282, upload-time = "2025-10-06T14:11:19.064Z" }, - { url = "https://files.pythonhosted.org/packages/a7/bc/315a56aca762d44a6aaaf7ad253f04d996cb6b27bad34410f82d76ea8038/yarl-1.22.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f3d7a87a78d46a2e3d5b72587ac14b4c16952dd0887dbb051451eceac774411e", size = 372080, upload-time = "2025-10-06T14:11:20.996Z" }, - { url = "https://files.pythonhosted.org/packages/3f/3f/08e9b826ec2e099ea6e7c69a61272f4f6da62cb5b1b63590bb80ca2e4a40/yarl-1.22.0-cp314-cp314-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:852863707010316c973162e703bddabec35e8757e67fcb8ad58829de1ebc8590", size = 338696, upload-time = "2025-10-06T14:11:22.847Z" }, - { url = "https://files.pythonhosted.org/packages/e3/9f/90360108e3b32bd76789088e99538febfea24a102380ae73827f62073543/yarl-1.22.0-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:131a085a53bfe839a477c0845acf21efc77457ba2bcf5899618136d64f3303a2", size = 387121, upload-time = "2025-10-06T14:11:24.889Z" }, - { url = "https://files.pythonhosted.org/packages/98/92/ab8d4657bd5b46a38094cfaea498f18bb70ce6b63508fd7e909bd1f93066/yarl-1.22.0-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:078a8aefd263f4d4f923a9677b942b445a2be970ca24548a8102689a3a8ab8da", size = 394080, upload-time = "2025-10-06T14:11:27.307Z" }, - { url = "https://files.pythonhosted.org/packages/f5/e7/d8c5a7752fef68205296201f8ec2bf718f5c805a7a7e9880576c67600658/yarl-1.22.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:bca03b91c323036913993ff5c738d0842fc9c60c4648e5c8d98331526df89784", size = 372661, upload-time = "2025-10-06T14:11:29.387Z" }, - { url = "https://files.pythonhosted.org/packages/b6/2e/f4d26183c8db0bb82d491b072f3127fb8c381a6206a3a56332714b79b751/yarl-1.22.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:68986a61557d37bb90d3051a45b91fa3d5c516d177dfc6dd6f2f436a07ff2b6b", size = 364645, upload-time = "2025-10-06T14:11:31.423Z" }, - { url = "https://files.pythonhosted.org/packages/80/7c/428e5812e6b87cd00ee8e898328a62c95825bf37c7fa87f0b6bb2ad31304/yarl-1.22.0-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:4792b262d585ff0dff6bcb787f8492e40698443ec982a3568c2096433660c694", size = 355361, upload-time = "2025-10-06T14:11:33.055Z" }, - { url = "https://files.pythonhosted.org/packages/ec/2a/249405fd26776f8b13c067378ef4d7dd49c9098d1b6457cdd152a99e96a9/yarl-1.22.0-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:ebd4549b108d732dba1d4ace67614b9545b21ece30937a63a65dd34efa19732d", size = 381451, upload-time = "2025-10-06T14:11:35.136Z" }, - { url = "https://files.pythonhosted.org/packages/67/a8/fb6b1adbe98cf1e2dd9fad71003d3a63a1bc22459c6e15f5714eb9323b93/yarl-1.22.0-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:f87ac53513d22240c7d59203f25cc3beac1e574c6cd681bbfd321987b69f95fd", size = 383814, upload-time = "2025-10-06T14:11:37.094Z" }, - { url = "https://files.pythonhosted.org/packages/d9/f9/3aa2c0e480fb73e872ae2814c43bc1e734740bb0d54e8cb2a95925f98131/yarl-1.22.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:22b029f2881599e2f1b06f8f1db2ee63bd309e2293ba2d566e008ba12778b8da", size = 370799, upload-time = "2025-10-06T14:11:38.83Z" }, - { url = "https://files.pythonhosted.org/packages/50/3c/af9dba3b8b5eeb302f36f16f92791f3ea62e3f47763406abf6d5a4a3333b/yarl-1.22.0-cp314-cp314-win32.whl", hash = "sha256:6a635ea45ba4ea8238463b4f7d0e721bad669f80878b7bfd1f89266e2ae63da2", size = 82990, upload-time = "2025-10-06T14:11:40.624Z" }, - { url = "https://files.pythonhosted.org/packages/ac/30/ac3a0c5bdc1d6efd1b41fa24d4897a4329b3b1e98de9449679dd327af4f0/yarl-1.22.0-cp314-cp314-win_amd64.whl", hash = "sha256:0d6e6885777af0f110b0e5d7e5dda8b704efed3894da26220b7f3d887b839a79", size = 88292, upload-time = "2025-10-06T14:11:42.578Z" }, - { url = "https://files.pythonhosted.org/packages/df/0a/227ab4ff5b998a1b7410abc7b46c9b7a26b0ca9e86c34ba4b8d8bc7c63d5/yarl-1.22.0-cp314-cp314-win_arm64.whl", hash = "sha256:8218f4e98d3c10d683584cb40f0424f4b9fd6e95610232dd75e13743b070ee33", size = 82888, upload-time = "2025-10-06T14:11:44.863Z" }, - { url = "https://files.pythonhosted.org/packages/06/5e/a15eb13db90abd87dfbefb9760c0f3f257ac42a5cac7e75dbc23bed97a9f/yarl-1.22.0-cp314-cp314t-macosx_10_13_universal2.whl", hash = "sha256:45c2842ff0e0d1b35a6bf1cd6c690939dacb617a70827f715232b2e0494d55d1", size = 146223, upload-time = "2025-10-06T14:11:46.796Z" }, - { url = "https://files.pythonhosted.org/packages/18/82/9665c61910d4d84f41a5bf6837597c89e665fa88aa4941080704645932a9/yarl-1.22.0-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:d947071e6ebcf2e2bee8fce76e10faca8f7a14808ca36a910263acaacef08eca", size = 95981, upload-time = "2025-10-06T14:11:48.845Z" }, - { url = "https://files.pythonhosted.org/packages/5d/9a/2f65743589809af4d0a6d3aa749343c4b5f4c380cc24a8e94a3c6625a808/yarl-1.22.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:334b8721303e61b00019474cc103bdac3d7b1f65e91f0bfedeec2d56dfe74b53", size = 97303, upload-time = "2025-10-06T14:11:50.897Z" }, - { url = "https://files.pythonhosted.org/packages/b0/ab/5b13d3e157505c43c3b43b5a776cbf7b24a02bc4cccc40314771197e3508/yarl-1.22.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1e7ce67c34138a058fd092f67d07a72b8e31ff0c9236e751957465a24b28910c", size = 361820, upload-time = "2025-10-06T14:11:52.549Z" }, - { url = "https://files.pythonhosted.org/packages/fb/76/242a5ef4677615cf95330cfc1b4610e78184400699bdda0acb897ef5e49a/yarl-1.22.0-cp314-cp314t-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:d77e1b2c6d04711478cb1c4ab90db07f1609ccf06a287d5607fcd90dc9863acf", size = 323203, upload-time = "2025-10-06T14:11:54.225Z" }, - { url = "https://files.pythonhosted.org/packages/8c/96/475509110d3f0153b43d06164cf4195c64d16999e0c7e2d8a099adcd6907/yarl-1.22.0-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:c4647674b6150d2cae088fc07de2738a84b8bcedebef29802cf0b0a82ab6face", size = 363173, upload-time = "2025-10-06T14:11:56.069Z" }, - { url = "https://files.pythonhosted.org/packages/c9/66/59db471aecfbd559a1fd48aedd954435558cd98c7d0da8b03cc6c140a32c/yarl-1.22.0-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:efb07073be061c8f79d03d04139a80ba33cbd390ca8f0297aae9cce6411e4c6b", size = 373562, upload-time = "2025-10-06T14:11:58.783Z" }, - { url = "https://files.pythonhosted.org/packages/03/1f/c5d94abc91557384719da10ff166b916107c1b45e4d0423a88457071dd88/yarl-1.22.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e51ac5435758ba97ad69617e13233da53908beccc6cfcd6c34bbed8dcbede486", size = 339828, upload-time = "2025-10-06T14:12:00.686Z" }, - { url = "https://files.pythonhosted.org/packages/5f/97/aa6a143d3afba17b6465733681c70cf175af89f76ec8d9286e08437a7454/yarl-1.22.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:33e32a0dd0c8205efa8e83d04fc9f19313772b78522d1bdc7d9aed706bfd6138", size = 347551, upload-time = "2025-10-06T14:12:02.628Z" }, - { url = "https://files.pythonhosted.org/packages/43/3c/45a2b6d80195959239a7b2a8810506d4eea5487dce61c2a3393e7fc3c52e/yarl-1.22.0-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:bf4a21e58b9cde0e401e683ebd00f6ed30a06d14e93f7c8fd059f8b6e8f87b6a", size = 334512, upload-time = "2025-10-06T14:12:04.871Z" }, - { url = "https://files.pythonhosted.org/packages/86/a0/c2ab48d74599c7c84cb104ebd799c5813de252bea0f360ffc29d270c2caa/yarl-1.22.0-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:e4b582bab49ac33c8deb97e058cd67c2c50dac0dd134874106d9c774fd272529", size = 352400, upload-time = "2025-10-06T14:12:06.624Z" }, - { url = "https://files.pythonhosted.org/packages/32/75/f8919b2eafc929567d3d8411f72bdb1a2109c01caaab4ebfa5f8ffadc15b/yarl-1.22.0-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:0b5bcc1a9c4839e7e30b7b30dd47fe5e7e44fb7054ec29b5bb8d526aa1041093", size = 357140, upload-time = "2025-10-06T14:12:08.362Z" }, - { url = "https://files.pythonhosted.org/packages/cf/72/6a85bba382f22cf78add705d8c3731748397d986e197e53ecc7835e76de7/yarl-1.22.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:c0232bce2170103ec23c454e54a57008a9a72b5d1c3105dc2496750da8cfa47c", size = 341473, upload-time = "2025-10-06T14:12:10.994Z" }, - { url = "https://files.pythonhosted.org/packages/35/18/55e6011f7c044dc80b98893060773cefcfdbf60dfefb8cb2f58b9bacbd83/yarl-1.22.0-cp314-cp314t-win32.whl", hash = "sha256:8009b3173bcd637be650922ac455946197d858b3630b6d8787aa9e5c4564533e", size = 89056, upload-time = "2025-10-06T14:12:13.317Z" }, - { url = "https://files.pythonhosted.org/packages/f9/86/0f0dccb6e59a9e7f122c5afd43568b1d31b8ab7dda5f1b01fb5c7025c9a9/yarl-1.22.0-cp314-cp314t-win_amd64.whl", hash = "sha256:9fb17ea16e972c63d25d4a97f016d235c78dd2344820eb35bc034bc32012ee27", size = 96292, upload-time = "2025-10-06T14:12:15.398Z" }, - { url = "https://files.pythonhosted.org/packages/48/b7/503c98092fb3b344a179579f55814b613c1fbb1c23b3ec14a7b008a66a6e/yarl-1.22.0-cp314-cp314t-win_arm64.whl", hash = "sha256:9f6d73c1436b934e3f01df1e1b21ff765cd1d28c77dfb9ace207f746d4610ee1", size = 85171, upload-time = "2025-10-06T14:12:16.935Z" }, - { url = "https://files.pythonhosted.org/packages/73/ae/b48f95715333080afb75a4504487cbe142cae1268afc482d06692d605ae6/yarl-1.22.0-py3-none-any.whl", hash = "sha256:1380560bdba02b6b6c90de54133c81c9f2a453dee9912fe58c1dcced1edb7cff", size = 46814, upload-time = "2025-10-06T14:12:53.872Z" }, +sdist = { url = "https://files.pythonhosted.org/packages/23/6e/beb1beec874a72f23815c1434518bfc4ed2175065173fb138c3705f658d4/yarl-1.23.0.tar.gz", hash = "sha256:53b1ea6ca88ebd4420379c330aea57e258408dd0df9af0992e5de2078dc9f5d5", size = 194676, upload-time = "2026-03-01T22:07:53.373Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/8b/0d/9cc638702f6fc3c7a3685bcc8cf2a9ed7d6206e932a49f5242658047ef51/yarl-1.23.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:cff6d44cb13d39db2663a22b22305d10855efa0fa8015ddeacc40bc59b9d8107", size = 123764, upload-time = "2026-03-01T22:04:09.7Z" }, + { url = "https://files.pythonhosted.org/packages/7a/35/5a553687c5793df5429cd1db45909d4f3af7eee90014888c208d086a44f0/yarl-1.23.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e4c53f8347cd4200f0d70a48ad059cabaf24f5adc6ba08622a23423bc7efa10d", size = 86282, upload-time = "2026-03-01T22:04:11.892Z" }, + { url = "https://files.pythonhosted.org/packages/68/2e/c5a2234238f8ce37a8312b52801ee74117f576b1539eec8404a480434acc/yarl-1.23.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:2a6940a074fb3c48356ed0158a3ca5699c955ee4185b4d7d619be3c327143e05", size = 86053, upload-time = "2026-03-01T22:04:13.292Z" }, + { url = "https://files.pythonhosted.org/packages/74/3f/bbd8ff36fb038622797ffbaf7db314918bb4d76f1cc8a4f9ca7a55fe5195/yarl-1.23.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ed5f69ce7be7902e5c70ea19eb72d20abf7d725ab5d49777d696e32d4fc1811d", size = 99395, upload-time = "2026-03-01T22:04:15.133Z" }, + { url = "https://files.pythonhosted.org/packages/77/04/9516bc4e269d2a3ec9c6779fcdeac51ce5b3a9b0156f06ac7152e5bba864/yarl-1.23.0-cp310-cp310-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:389871e65468400d6283c0308e791a640b5ab5c83bcee02a2f51295f95e09748", size = 92143, upload-time = "2026-03-01T22:04:16.829Z" }, + { url = "https://files.pythonhosted.org/packages/c7/63/88802d1f6b1cb1fc67d67a58cd0cf8a1790de4ce7946e434240f1d60ab4a/yarl-1.23.0-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:dda608c88cf709b1d406bdfcd84d8d63cff7c9e577a403c6108ce8ce9dcc8764", size = 107643, upload-time = "2026-03-01T22:04:18.519Z" }, + { url = "https://files.pythonhosted.org/packages/8e/db/4f9b838f4d8bdd6f0f385aed8bbf21c71ed11a0b9983305c302cbd557815/yarl-1.23.0-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:8c4fe09e0780c6c3bf2b7d4af02ee2394439d11a523bbcf095cf4747c2932007", size = 108700, upload-time = "2026-03-01T22:04:20.373Z" }, + { url = "https://files.pythonhosted.org/packages/50/12/95a1d33f04a79c402664070d43b8b9f72dc18914e135b345b611b0b1f8cc/yarl-1.23.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:31c9921eb8bd12633b41ad27686bbb0b1a2a9b8452bfdf221e34f311e9942ed4", size = 102769, upload-time = "2026-03-01T22:04:23.055Z" }, + { url = "https://files.pythonhosted.org/packages/86/65/91a0285f51321369fd1a8308aa19207520c5f0587772cfc2e03fc2467e90/yarl-1.23.0-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:5f10fd85e4b75967468af655228fbfd212bdf66db1c0d135065ce288982eda26", size = 101114, upload-time = "2026-03-01T22:04:25.031Z" }, + { url = "https://files.pythonhosted.org/packages/58/80/c7c8244fc3e5bc483dc71a09560f43b619fab29301a0f0a8f936e42865c7/yarl-1.23.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:dbf507e9ef5688bada447a24d68b4b58dd389ba93b7afc065a2ba892bea54769", size = 98883, upload-time = "2026-03-01T22:04:27.281Z" }, + { url = "https://files.pythonhosted.org/packages/86/e7/71ca9cc9ca79c0b7d491216177d1aed559d632947b8ffb0ee60f7d8b23e3/yarl-1.23.0-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:85e9beda1f591bc73e77ea1c51965c68e98dafd0fec72cdd745f77d727466716", size = 94172, upload-time = "2026-03-01T22:04:28.554Z" }, + { url = "https://files.pythonhosted.org/packages/6a/3f/6c6c8a0fe29c26fb2db2e8d32195bb84ec1bfb8f1d32e7f73b787fcf349b/yarl-1.23.0-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:0e1fdaa14ef51366d7757b45bde294e95f6c8c049194e793eedb8387c86d5993", size = 107010, upload-time = "2026-03-01T22:04:30.385Z" }, + { url = "https://files.pythonhosted.org/packages/56/38/12730c05e5ad40a76374d440ed8b0899729a96c250516d91c620a6e38fc2/yarl-1.23.0-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:75e3026ab649bf48f9a10c0134512638725b521340293f202a69b567518d94e0", size = 100285, upload-time = "2026-03-01T22:04:31.752Z" }, + { url = "https://files.pythonhosted.org/packages/34/92/6a7be9239f2347234e027284e7a5f74b1140cc86575e7b469d13fba1ebfe/yarl-1.23.0-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:80e6d33a3d42a7549b409f199857b4fb54e2103fc44fb87605b6663b7a7ff750", size = 108230, upload-time = "2026-03-01T22:04:33.844Z" }, + { url = "https://files.pythonhosted.org/packages/5e/81/4aebccfa9376bd98b9d8bfad20621a57d3e8cfc5b8631c1fa5f62cdd03f4/yarl-1.23.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:5ec2f42d41ccbd5df0270d7df31618a8ee267bfa50997f5d720ddba86c4a83a6", size = 103008, upload-time = "2026-03-01T22:04:35.856Z" }, + { url = "https://files.pythonhosted.org/packages/38/0f/0b4e3edcec794a86b853b0c6396c0a888d72dfce19b2d88c02ac289fb6c1/yarl-1.23.0-cp310-cp310-win32.whl", hash = "sha256:debe9c4f41c32990771be5c22b56f810659f9ddf3d63f67abfdcaa2c6c9c5c1d", size = 83073, upload-time = "2026-03-01T22:04:38.268Z" }, + { url = "https://files.pythonhosted.org/packages/a0/71/ad95c33da18897e4c636528bbc24a1dd23fe16797de8bc4ec667b8db0ba4/yarl-1.23.0-cp310-cp310-win_amd64.whl", hash = "sha256:ab5f043cb8a2d71c981c09c510da013bc79fd661f5c60139f00dd3c3cc4f2ffb", size = 87328, upload-time = "2026-03-01T22:04:39.558Z" }, + { url = "https://files.pythonhosted.org/packages/e2/14/dfa369523c79bccf9c9c746b0a63eb31f65db9418ac01275f7950962e504/yarl-1.23.0-cp310-cp310-win_arm64.whl", hash = "sha256:263cd4f47159c09b8b685890af949195b51d1aa82ba451c5847ca9bc6413c220", size = 82463, upload-time = "2026-03-01T22:04:41.454Z" }, + { url = "https://files.pythonhosted.org/packages/a2/aa/60da938b8f0997ba3a911263c40d82b6f645a67902a490b46f3355e10fae/yarl-1.23.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:b35d13d549077713e4414f927cdc388d62e543987c572baee613bf82f11a4b99", size = 123641, upload-time = "2026-03-01T22:04:42.841Z" }, + { url = "https://files.pythonhosted.org/packages/24/84/e237607faf4e099dbb8a4f511cfd5efcb5f75918baad200ff7380635631b/yarl-1.23.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:cbb0fef01f0c6b38cb0f39b1f78fc90b807e0e3c86a7ff3ce74ad77ce5c7880c", size = 86248, upload-time = "2026-03-01T22:04:44.757Z" }, + { url = "https://files.pythonhosted.org/packages/b2/0d/71ceabc14c146ba8ee3804ca7b3d42b1664c8440439de5214d366fec7d3a/yarl-1.23.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:dc52310451fc7c629e13c4e061cbe2dd01684d91f2f8ee2821b083c58bd72432", size = 85988, upload-time = "2026-03-01T22:04:46.365Z" }, + { url = "https://files.pythonhosted.org/packages/8c/6c/4a90d59c572e46b270ca132aca66954f1175abd691f74c1ef4c6711828e2/yarl-1.23.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b2c6b50c7b0464165472b56b42d4c76a7b864597007d9c085e8b63e185cf4a7a", size = 100566, upload-time = "2026-03-01T22:04:47.639Z" }, + { url = "https://files.pythonhosted.org/packages/49/fb/c438fb5108047e629f6282a371e6e91cf3f97ee087c4fb748a1f32ceef55/yarl-1.23.0-cp311-cp311-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:aafe5dcfda86c8af00386d7781d4c2181b5011b7be3f2add5e99899ea925df05", size = 92079, upload-time = "2026-03-01T22:04:48.925Z" }, + { url = "https://files.pythonhosted.org/packages/d9/13/d269aa1aed3e4f50a5a103f96327210cc5fa5dd2d50882778f13c7a14606/yarl-1.23.0-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:9ee33b875f0b390564c1fb7bc528abf18c8ee6073b201c6ae8524aca778e2d83", size = 108741, upload-time = "2026-03-01T22:04:50.838Z" }, + { url = "https://files.pythonhosted.org/packages/85/fb/115b16f22c37ea4437d323e472945bea97301c8ec6089868fa560abab590/yarl-1.23.0-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:4c41e021bc6d7affb3364dc1e1e5fa9582b470f283748784bd6ea0558f87f42c", size = 108099, upload-time = "2026-03-01T22:04:52.499Z" }, + { url = "https://files.pythonhosted.org/packages/9a/64/c53487d9f4968045b8afa51aed7ca44f58b2589e772f32745f3744476c82/yarl-1.23.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:99c8a9ed30f4164bc4c14b37a90208836cbf50d4ce2a57c71d0f52c7fb4f7598", size = 102678, upload-time = "2026-03-01T22:04:55.176Z" }, + { url = "https://files.pythonhosted.org/packages/85/59/cd98e556fbb2bf8fab29c1a722f67ad45c5f3447cac798ab85620d1e70af/yarl-1.23.0-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:f2af5c81a1f124609d5f33507082fc3f739959d4719b56877ab1ee7e7b3d602b", size = 100803, upload-time = "2026-03-01T22:04:56.588Z" }, + { url = "https://files.pythonhosted.org/packages/9e/c0/b39770b56d4a9f0bb5f77e2f1763cd2d75cc2f6c0131e3b4c360348fcd65/yarl-1.23.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:6b41389c19b07c760c7e427a3462e8ab83c4bb087d127f0e854c706ce1b9215c", size = 100163, upload-time = "2026-03-01T22:04:58.492Z" }, + { url = "https://files.pythonhosted.org/packages/e7/64/6980f99ab00e1f0ff67cb84766c93d595b067eed07439cfccfc8fb28c1a6/yarl-1.23.0-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:1dc702e42d0684f42d6519c8d581e49c96cefaaab16691f03566d30658ee8788", size = 93859, upload-time = "2026-03-01T22:05:00.268Z" }, + { url = "https://files.pythonhosted.org/packages/38/69/912e6c5e146793e5d4b5fe39ff5b00f4d22463dfd5a162bec565ac757673/yarl-1.23.0-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:0e40111274f340d32ebcc0a5668d54d2b552a6cca84c9475859d364b380e3222", size = 108202, upload-time = "2026-03-01T22:05:02.273Z" }, + { url = "https://files.pythonhosted.org/packages/59/97/35ca6767524687ad64e5f5c31ad54bc76d585585a9fcb40f649e7e82ffed/yarl-1.23.0-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:4764a6a7588561a9aef92f65bda2c4fb58fe7c675c0883862e6df97559de0bfb", size = 99866, upload-time = "2026-03-01T22:05:03.597Z" }, + { url = "https://files.pythonhosted.org/packages/d3/1c/1a3387ee6d73589f6f2a220ae06f2984f6c20b40c734989b0a44f5987308/yarl-1.23.0-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:03214408cfa590df47728b84c679ae4ef00be2428e11630277be0727eba2d7cc", size = 107852, upload-time = "2026-03-01T22:05:04.986Z" }, + { url = "https://files.pythonhosted.org/packages/a4/b8/35c0750fcd5a3f781058bfd954515dd4b1eab45e218cbb85cf11132215f1/yarl-1.23.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:170e26584b060879e29fac213e4228ef063f39128723807a312e5c7fec28eff2", size = 102919, upload-time = "2026-03-01T22:05:06.397Z" }, + { url = "https://files.pythonhosted.org/packages/e5/1c/9a1979aec4a81896d597bcb2177827f2dbee3f5b7cc48b2d0dadb644b41d/yarl-1.23.0-cp311-cp311-win32.whl", hash = "sha256:51430653db848d258336cfa0244427b17d12db63d42603a55f0d4546f50f25b5", size = 82602, upload-time = "2026-03-01T22:05:08.444Z" }, + { url = "https://files.pythonhosted.org/packages/93/22/b85eca6fa2ad9491af48c973e4c8cf6b103a73dbb271fe3346949449fca0/yarl-1.23.0-cp311-cp311-win_amd64.whl", hash = "sha256:bf49a3ae946a87083ef3a34c8f677ae4243f5b824bfc4c69672e72b3d6719d46", size = 87461, upload-time = "2026-03-01T22:05:10.145Z" }, + { url = "https://files.pythonhosted.org/packages/93/95/07e3553fe6f113e6864a20bdc53a78113cda3b9ced8784ee52a52c9f80d8/yarl-1.23.0-cp311-cp311-win_arm64.whl", hash = "sha256:b39cb32a6582750b6cc77bfb3c49c0f8760dc18dc96ec9fb55fbb0f04e08b928", size = 82336, upload-time = "2026-03-01T22:05:11.554Z" }, + { url = "https://files.pythonhosted.org/packages/88/8a/94615bc31022f711add374097ad4144d569e95ff3c38d39215d07ac153a0/yarl-1.23.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:1932b6b8bba8d0160a9d1078aae5838a66039e8832d41d2992daa9a3a08f7860", size = 124737, upload-time = "2026-03-01T22:05:12.897Z" }, + { url = "https://files.pythonhosted.org/packages/e3/6f/c6554045d59d64052698add01226bc867b52fe4a12373415d7991fdca95d/yarl-1.23.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:411225bae281f114067578891bc75534cfb3d92a3b4dfef7a6ca78ba354e6069", size = 87029, upload-time = "2026-03-01T22:05:14.376Z" }, + { url = "https://files.pythonhosted.org/packages/19/2a/725ecc166d53438bc88f76822ed4b1e3b10756e790bafd7b523fe97c322d/yarl-1.23.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:13a563739ae600a631c36ce096615fe307f131344588b0bc0daec108cdb47b25", size = 86310, upload-time = "2026-03-01T22:05:15.71Z" }, + { url = "https://files.pythonhosted.org/packages/99/30/58260ed98e6ff7f90ba84442c1ddd758c9170d70327394a6227b310cd60f/yarl-1.23.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:9cbf44c5cb4a7633d078788e1b56387e3d3cf2b8139a3be38040b22d6c3221c8", size = 97587, upload-time = "2026-03-01T22:05:17.384Z" }, + { url = "https://files.pythonhosted.org/packages/76/0a/8b08aac08b50682e65759f7f8dde98ae8168f72487e7357a5d684c581ef9/yarl-1.23.0-cp312-cp312-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:53ad387048f6f09a8969631e4de3f1bf70c50e93545d64af4f751b2498755072", size = 92528, upload-time = "2026-03-01T22:05:18.804Z" }, + { url = "https://files.pythonhosted.org/packages/52/07/0b7179101fe5f8385ec6c6bb5d0cb9f76bd9fb4a769591ab6fb5cdbfc69a/yarl-1.23.0-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:4a59ba56f340334766f3a4442e0efd0af895fae9e2b204741ef885c446b3a1a8", size = 105339, upload-time = "2026-03-01T22:05:20.235Z" }, + { url = "https://files.pythonhosted.org/packages/d3/8a/36d82869ab5ec829ca8574dfcb92b51286fcfb1e9c7a73659616362dc880/yarl-1.23.0-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:803a3c3ce4acc62eaf01eaca1208dcf0783025ef27572c3336502b9c232005e7", size = 105061, upload-time = "2026-03-01T22:05:22.268Z" }, + { url = "https://files.pythonhosted.org/packages/66/3e/868e5c3364b6cee19ff3e1a122194fa4ce51def02c61023970442162859e/yarl-1.23.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a3d2bff8f37f8d0f96c7ec554d16945050d54462d6e95414babaa18bfafc7f51", size = 100132, upload-time = "2026-03-01T22:05:23.638Z" }, + { url = "https://files.pythonhosted.org/packages/cf/26/9c89acf82f08a52cb52d6d39454f8d18af15f9d386a23795389d1d423823/yarl-1.23.0-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:c75eb09e8d55bceb4367e83496ff8ef2bc7ea6960efb38e978e8073ea59ecb67", size = 99289, upload-time = "2026-03-01T22:05:25.749Z" }, + { url = "https://files.pythonhosted.org/packages/6f/54/5b0db00d2cb056922356104468019c0a132e89c8d3ab67d8ede9f4483d2a/yarl-1.23.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:877b0738624280e34c55680d6054a307aa94f7d52fa0e3034a9cc6e790871da7", size = 96950, upload-time = "2026-03-01T22:05:27.318Z" }, + { url = "https://files.pythonhosted.org/packages/f6/40/10fa93811fd439341fad7e0718a86aca0de9548023bbb403668d6555acab/yarl-1.23.0-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:b5405bb8f0e783a988172993cfc627e4d9d00432d6bbac65a923041edacf997d", size = 93960, upload-time = "2026-03-01T22:05:28.738Z" }, + { url = "https://files.pythonhosted.org/packages/bc/d2/8ae2e6cd77d0805f4526e30ec43b6f9a3dfc542d401ac4990d178e4bf0cf/yarl-1.23.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:1c3a3598a832590c5a3ce56ab5576361b5688c12cb1d39429cf5dba30b510760", size = 104703, upload-time = "2026-03-01T22:05:30.438Z" }, + { url = "https://files.pythonhosted.org/packages/2f/0c/b3ceacf82c3fe21183ce35fa2acf5320af003d52bc1fcf5915077681142e/yarl-1.23.0-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:8419ebd326430d1cbb7efb5292330a2cf39114e82df5cc3d83c9a0d5ebeaf2f2", size = 98325, upload-time = "2026-03-01T22:05:31.835Z" }, + { url = "https://files.pythonhosted.org/packages/9d/e0/12900edd28bdab91a69bd2554b85ad7b151f64e8b521fe16f9ad2f56477a/yarl-1.23.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:be61f6fff406ca40e3b1d84716fde398fc08bc63dd96d15f3a14230a0973ed86", size = 105067, upload-time = "2026-03-01T22:05:33.358Z" }, + { url = "https://files.pythonhosted.org/packages/15/61/74bb1182cf79c9bbe4eb6b1f14a57a22d7a0be5e9cedf8e2d5c2086474c3/yarl-1.23.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:3ceb13c5c858d01321b5d9bb65e4cf37a92169ea470b70fec6f236b2c9dd7e34", size = 100285, upload-time = "2026-03-01T22:05:35.4Z" }, + { url = "https://files.pythonhosted.org/packages/69/7f/cd5ef733f2550de6241bd8bd8c3febc78158b9d75f197d9c7baa113436af/yarl-1.23.0-cp312-cp312-win32.whl", hash = "sha256:fffc45637bcd6538de8b85f51e3df3223e4ad89bccbfca0481c08c7fc8b7ed7d", size = 82359, upload-time = "2026-03-01T22:05:36.811Z" }, + { url = "https://files.pythonhosted.org/packages/f5/be/25216a49daeeb7af2bec0db22d5e7df08ed1d7c9f65d78b14f3b74fd72fc/yarl-1.23.0-cp312-cp312-win_amd64.whl", hash = "sha256:f69f57305656a4852f2a7203efc661d8c042e6cc67f7acd97d8667fb448a426e", size = 87674, upload-time = "2026-03-01T22:05:38.171Z" }, + { url = "https://files.pythonhosted.org/packages/d2/35/aeab955d6c425b227d5b7247eafb24f2653fedc32f95373a001af5dfeb9e/yarl-1.23.0-cp312-cp312-win_arm64.whl", hash = "sha256:6e87a6e8735b44816e7db0b2fbc9686932df473c826b0d9743148432e10bb9b9", size = 81879, upload-time = "2026-03-01T22:05:40.006Z" }, + { url = "https://files.pythonhosted.org/packages/9a/4b/a0a6e5d0ee8a2f3a373ddef8a4097d74ac901ac363eea1440464ccbe0898/yarl-1.23.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:16c6994ac35c3e74fb0ae93323bf8b9c2a9088d55946109489667c510a7d010e", size = 123796, upload-time = "2026-03-01T22:05:41.412Z" }, + { url = "https://files.pythonhosted.org/packages/67/b6/8925d68af039b835ae876db5838e82e76ec87b9782ecc97e192b809c4831/yarl-1.23.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:4a42e651629dafb64fd5b0286a3580613702b5809ad3f24934ea87595804f2c5", size = 86547, upload-time = "2026-03-01T22:05:42.841Z" }, + { url = "https://files.pythonhosted.org/packages/ae/50/06d511cc4b8e0360d3c94af051a768e84b755c5eb031b12adaaab6dec6e5/yarl-1.23.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:7c6b9461a2a8b47c65eef63bb1c76a4f1c119618ffa99ea79bc5bb1e46c5821b", size = 85854, upload-time = "2026-03-01T22:05:44.85Z" }, + { url = "https://files.pythonhosted.org/packages/c4/f4/4e30b250927ffdab4db70da08b9b8d2194d7c7b400167b8fbeca1e4701ca/yarl-1.23.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:2569b67d616eab450d262ca7cb9f9e19d2f718c70a8b88712859359d0ab17035", size = 98351, upload-time = "2026-03-01T22:05:46.836Z" }, + { url = "https://files.pythonhosted.org/packages/86/fc/4118c5671ea948208bdb1492d8b76bdf1453d3e73df051f939f563e7dcc5/yarl-1.23.0-cp313-cp313-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:e9d9a4d06d3481eab79803beb4d9bd6f6a8e781ec078ac70d7ef2dcc29d1bea5", size = 92711, upload-time = "2026-03-01T22:05:48.316Z" }, + { url = "https://files.pythonhosted.org/packages/56/11/1ed91d42bd9e73c13dc9e7eb0dd92298d75e7ac4dd7f046ad0c472e231cd/yarl-1.23.0-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:f514f6474e04179d3d33175ed3f3e31434d3130d42ec153540d5b157deefd735", size = 106014, upload-time = "2026-03-01T22:05:50.028Z" }, + { url = "https://files.pythonhosted.org/packages/ce/c9/74e44e056a23fbc33aca71779ef450ca648a5bc472bdad7a82339918f818/yarl-1.23.0-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:fda207c815b253e34f7e1909840fd14299567b1c0eb4908f8c2ce01a41265401", size = 105557, upload-time = "2026-03-01T22:05:51.416Z" }, + { url = "https://files.pythonhosted.org/packages/66/fe/b1e10b08d287f518994f1e2ff9b6d26f0adeecd8dd7d533b01bab29a3eda/yarl-1.23.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:34b6cf500e61c90f305094911f9acc9c86da1a05a7a3f5be9f68817043f486e4", size = 101559, upload-time = "2026-03-01T22:05:52.872Z" }, + { url = "https://files.pythonhosted.org/packages/72/59/c5b8d94b14e3d3c2a9c20cb100119fd534ab5a14b93673ab4cc4a4141ea5/yarl-1.23.0-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:d7504f2b476d21653e4d143f44a175f7f751cd41233525312696c76aa3dbb23f", size = 100502, upload-time = "2026-03-01T22:05:54.954Z" }, + { url = "https://files.pythonhosted.org/packages/77/4f/96976cb54cbfc5c9fd73ed4c51804f92f209481d1fb190981c0f8a07a1d7/yarl-1.23.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:578110dd426f0d209d1509244e6d4a3f1a3e9077655d98c5f22583d63252a08a", size = 98027, upload-time = "2026-03-01T22:05:56.409Z" }, + { url = "https://files.pythonhosted.org/packages/63/6e/904c4f476471afdbad6b7e5b70362fb5810e35cd7466529a97322b6f5556/yarl-1.23.0-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:609d3614d78d74ebe35f54953c5bbd2ac647a7ddb9c30a5d877580f5e86b22f2", size = 95369, upload-time = "2026-03-01T22:05:58.141Z" }, + { url = "https://files.pythonhosted.org/packages/9d/40/acfcdb3b5f9d68ef499e39e04d25e141fe90661f9d54114556cf83be8353/yarl-1.23.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:4966242ec68afc74c122f8459abd597afd7d8a60dc93d695c1334c5fd25f762f", size = 105565, upload-time = "2026-03-01T22:06:00.286Z" }, + { url = "https://files.pythonhosted.org/packages/5e/c6/31e28f3a6ba2869c43d124f37ea5260cac9c9281df803c354b31f4dd1f3c/yarl-1.23.0-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:e0fd068364a6759bc794459f0a735ab151d11304346332489c7972bacbe9e72b", size = 99813, upload-time = "2026-03-01T22:06:01.712Z" }, + { url = "https://files.pythonhosted.org/packages/08/1f/6f65f59e72d54aa467119b63fc0b0b1762eff0232db1f4720cd89e2f4a17/yarl-1.23.0-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:39004f0ad156da43e86aa71f44e033de68a44e5a31fc53507b36dd253970054a", size = 105632, upload-time = "2026-03-01T22:06:03.188Z" }, + { url = "https://files.pythonhosted.org/packages/a3/c4/18b178a69935f9e7a338127d5b77d868fdc0f0e49becd286d51b3a18c61d/yarl-1.23.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:e5723c01a56c5028c807c701aa66722916d2747ad737a046853f6c46f4875543", size = 101895, upload-time = "2026-03-01T22:06:04.651Z" }, + { url = "https://files.pythonhosted.org/packages/8f/54/f5b870b5505663911dba950a8e4776a0dbd51c9c54c0ae88e823e4b874a0/yarl-1.23.0-cp313-cp313-win32.whl", hash = "sha256:1b6b572edd95b4fa8df75de10b04bc81acc87c1c7d16bcdd2035b09d30acc957", size = 82356, upload-time = "2026-03-01T22:06:06.04Z" }, + { url = "https://files.pythonhosted.org/packages/7a/84/266e8da36879c6edcd37b02b547e2d9ecdfea776be49598e75696e3316e1/yarl-1.23.0-cp313-cp313-win_amd64.whl", hash = "sha256:baaf55442359053c7d62f6f8413a62adba3205119bcb6f49594894d8be47e5e3", size = 87515, upload-time = "2026-03-01T22:06:08.107Z" }, + { url = "https://files.pythonhosted.org/packages/00/fd/7e1c66efad35e1649114fa13f17485f62881ad58edeeb7f49f8c5e748bf9/yarl-1.23.0-cp313-cp313-win_arm64.whl", hash = "sha256:fb4948814a2a98e3912505f09c9e7493b1506226afb1f881825368d6fb776ee3", size = 81785, upload-time = "2026-03-01T22:06:10.181Z" }, + { url = "https://files.pythonhosted.org/packages/9c/fc/119dd07004f17ea43bb91e3ece6587759edd7519d6b086d16bfbd3319982/yarl-1.23.0-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:aecfed0b41aa72b7881712c65cf764e39ce2ec352324f5e0837c7048d9e6daaa", size = 130719, upload-time = "2026-03-01T22:06:11.708Z" }, + { url = "https://files.pythonhosted.org/packages/e6/0d/9f2348502fbb3af409e8f47730282cd6bc80dec6630c1e06374d882d6eb2/yarl-1.23.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:a41bcf68efd19073376eb8cf948b8d9be0af26256403e512bb18f3966f1f9120", size = 89690, upload-time = "2026-03-01T22:06:13.429Z" }, + { url = "https://files.pythonhosted.org/packages/50/93/e88f3c80971b42cfc83f50a51b9d165a1dbf154b97005f2994a79f212a07/yarl-1.23.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:cde9a2ecd91668bcb7f077c4966d8ceddb60af01b52e6e3e2680e4cf00ad1a59", size = 89851, upload-time = "2026-03-01T22:06:15.53Z" }, + { url = "https://files.pythonhosted.org/packages/1c/07/61c9dd8ba8f86473263b4036f70fb594c09e99c0d9737a799dfd8bc85651/yarl-1.23.0-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5023346c4ee7992febc0068e7593de5fa2bf611848c08404b35ebbb76b1b0512", size = 95874, upload-time = "2026-03-01T22:06:17.553Z" }, + { url = "https://files.pythonhosted.org/packages/9e/e9/f9ff8ceefba599eac6abddcfb0b3bee9b9e636e96dbf54342a8577252379/yarl-1.23.0-cp313-cp313t-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:d1009abedb49ae95b136a8904a3f71b342f849ffeced2d3747bf29caeda218c4", size = 88710, upload-time = "2026-03-01T22:06:19.004Z" }, + { url = "https://files.pythonhosted.org/packages/eb/78/0231bfcc5d4c8eec220bc2f9ef82cb4566192ea867a7c5b4148f44f6cbcd/yarl-1.23.0-cp313-cp313t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:a8d00f29b42f534cc8aa3931cfe773b13b23e561e10d2b26f27a8d309b0e82a1", size = 101033, upload-time = "2026-03-01T22:06:21.203Z" }, + { url = "https://files.pythonhosted.org/packages/cd/9b/30ea5239a61786f18fd25797151a17fbb3be176977187a48d541b5447dd4/yarl-1.23.0-cp313-cp313t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:95451e6ce06c3e104556d73b559f5da6c34a069b6b62946d3ad66afcd51642ea", size = 100817, upload-time = "2026-03-01T22:06:22.738Z" }, + { url = "https://files.pythonhosted.org/packages/62/e2/a4980481071791bc83bce2b7a1a1f7adcabfa366007518b4b845e92eeee3/yarl-1.23.0-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:531ef597132086b6cf96faa7c6c1dcd0361dd5f1694e5cc30375907b9b7d3ea9", size = 97482, upload-time = "2026-03-01T22:06:24.21Z" }, + { url = "https://files.pythonhosted.org/packages/e5/1e/304a00cf5f6100414c4b5a01fc7ff9ee724b62158a08df2f8170dfc72a2d/yarl-1.23.0-cp313-cp313t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:88f9fb0116fbfcefcab70f85cf4b74a2b6ce5d199c41345296f49d974ddb4123", size = 95949, upload-time = "2026-03-01T22:06:25.697Z" }, + { url = "https://files.pythonhosted.org/packages/68/03/093f4055ed4cae649ac53bca3d180bd37102e9e11d048588e9ab0c0108d0/yarl-1.23.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:e7b0460976dc75cb87ad9cc1f9899a4b97751e7d4e77ab840fc9b6d377b8fd24", size = 95839, upload-time = "2026-03-01T22:06:27.309Z" }, + { url = "https://files.pythonhosted.org/packages/b9/28/4c75ebb108f322aa8f917ae10a8ffa4f07cae10a8a627b64e578617df6a0/yarl-1.23.0-cp313-cp313t-musllinux_1_2_armv7l.whl", hash = "sha256:115136c4a426f9da976187d238e84139ff6b51a20839aa6e3720cd1026d768de", size = 90696, upload-time = "2026-03-01T22:06:29.048Z" }, + { url = "https://files.pythonhosted.org/packages/23/9c/42c2e2dd91c1a570402f51bdf066bfdb1241c2240ba001967bad778e77b7/yarl-1.23.0-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:ead11956716a940c1abc816b7df3fa2b84d06eaed8832ca32f5c5e058c65506b", size = 100865, upload-time = "2026-03-01T22:06:30.525Z" }, + { url = "https://files.pythonhosted.org/packages/74/05/1bcd60a8a0a914d462c305137246b6f9d167628d73568505fce3f1cb2e65/yarl-1.23.0-cp313-cp313t-musllinux_1_2_riscv64.whl", hash = "sha256:fe8f8f5e70e6dbdfca9882cd9deaac058729bcf323cf7a58660901e55c9c94f6", size = 96234, upload-time = "2026-03-01T22:06:32.692Z" }, + { url = "https://files.pythonhosted.org/packages/90/b2/f52381aac396d6778ce516b7bc149c79e65bfc068b5de2857ab69eeea3b7/yarl-1.23.0-cp313-cp313t-musllinux_1_2_s390x.whl", hash = "sha256:a0e317df055958a0c1e79e5d2aa5a5eaa4a6d05a20d4b0c9c3f48918139c9fc6", size = 100295, upload-time = "2026-03-01T22:06:34.268Z" }, + { url = "https://files.pythonhosted.org/packages/e5/e8/638bae5bbf1113a659b2435d8895474598afe38b4a837103764f603aba56/yarl-1.23.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:6f0fd84de0c957b2d280143522c4f91a73aada1923caee763e24a2b3fda9f8a5", size = 97784, upload-time = "2026-03-01T22:06:35.864Z" }, + { url = "https://files.pythonhosted.org/packages/80/25/a3892b46182c586c202629fc2159aa13975d3741d52ebd7347fd501d48d5/yarl-1.23.0-cp313-cp313t-win32.whl", hash = "sha256:93a784271881035ab4406a172edb0faecb6e7d00f4b53dc2f55919d6c9688595", size = 88313, upload-time = "2026-03-01T22:06:37.39Z" }, + { url = "https://files.pythonhosted.org/packages/43/68/8c5b36aa5178900b37387937bc2c2fe0e9505537f713495472dcf6f6fccc/yarl-1.23.0-cp313-cp313t-win_amd64.whl", hash = "sha256:dd00607bffbf30250fe108065f07453ec124dbf223420f57f5e749b04295e090", size = 94932, upload-time = "2026-03-01T22:06:39.579Z" }, + { url = "https://files.pythonhosted.org/packages/c6/cc/d79ba8292f51f81f4dc533a8ccfb9fc6992cabf0998ed3245de7589dc07c/yarl-1.23.0-cp313-cp313t-win_arm64.whl", hash = "sha256:ac09d42f48f80c9ee1635b2fcaa819496a44502737660d3c0f2ade7526d29144", size = 84786, upload-time = "2026-03-01T22:06:41.988Z" }, + { url = "https://files.pythonhosted.org/packages/90/98/b85a038d65d1b92c3903ab89444f48d3cee490a883477b716d7a24b1a78c/yarl-1.23.0-cp314-cp314-macosx_10_15_universal2.whl", hash = "sha256:21d1b7305a71a15b4794b5ff22e8eef96ff4a6d7f9657155e5aa419444b28912", size = 124455, upload-time = "2026-03-01T22:06:43.615Z" }, + { url = "https://files.pythonhosted.org/packages/39/54/bc2b45559f86543d163b6e294417a107bb87557609007c007ad889afec18/yarl-1.23.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:85610b4f27f69984932a7abbe52703688de3724d9f72bceb1cca667deff27474", size = 86752, upload-time = "2026-03-01T22:06:45.425Z" }, + { url = "https://files.pythonhosted.org/packages/24/f9/e8242b68362bffe6fb536c8db5076861466fc780f0f1b479fc4ffbebb128/yarl-1.23.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:23f371bd662cf44a7630d4d113101eafc0cfa7518a2760d20760b26021454719", size = 86291, upload-time = "2026-03-01T22:06:46.974Z" }, + { url = "https://files.pythonhosted.org/packages/ea/d8/d1cb2378c81dd729e98c716582b1ccb08357e8488e4c24714658cc6630e8/yarl-1.23.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c4a80f77dc1acaaa61f0934176fccca7096d9b1ff08c8ba9cddf5ae034a24319", size = 99026, upload-time = "2026-03-01T22:06:48.459Z" }, + { url = "https://files.pythonhosted.org/packages/0a/ff/7196790538f31debe3341283b5b0707e7feb947620fc5e8236ef28d44f72/yarl-1.23.0-cp314-cp314-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:bd654fad46d8d9e823afbb4f87c79160b5a374ed1ff5bde24e542e6ba8f41434", size = 92355, upload-time = "2026-03-01T22:06:50.306Z" }, + { url = "https://files.pythonhosted.org/packages/c1/56/25d58c3eddde825890a5fe6aa1866228377354a3c39262235234ab5f616b/yarl-1.23.0-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:682bae25f0a0dd23a056739f23a134db9f52a63e2afd6bfb37ddc76292bbd723", size = 106417, upload-time = "2026-03-01T22:06:52.1Z" }, + { url = "https://files.pythonhosted.org/packages/51/8a/882c0e7bc8277eb895b31bce0138f51a1ba551fc2e1ec6753ffc1e7c1377/yarl-1.23.0-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:a82836cab5f197a0514235aaf7ffccdc886ccdaa2324bc0aafdd4ae898103039", size = 106422, upload-time = "2026-03-01T22:06:54.424Z" }, + { url = "https://files.pythonhosted.org/packages/42/2b/fef67d616931055bf3d6764885990a3ac647d68734a2d6a9e1d13de437a2/yarl-1.23.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1c57676bdedc94cd3bc37724cf6f8cd2779f02f6aba48de45feca073e714fe52", size = 101915, upload-time = "2026-03-01T22:06:55.895Z" }, + { url = "https://files.pythonhosted.org/packages/18/6a/530e16aebce27c5937920f3431c628a29a4b6b430fab3fd1c117b26ff3f6/yarl-1.23.0-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:c7f8dc16c498ff06497c015642333219871effba93e4a2e8604a06264aca5c5c", size = 100690, upload-time = "2026-03-01T22:06:58.21Z" }, + { url = "https://files.pythonhosted.org/packages/88/08/93749219179a45e27b036e03260fda05190b911de8e18225c294ac95bbc9/yarl-1.23.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:5ee586fb17ff8f90c91cf73c6108a434b02d69925f44f5f8e0d7f2f260607eae", size = 98750, upload-time = "2026-03-01T22:06:59.794Z" }, + { url = "https://files.pythonhosted.org/packages/d9/cf/ea424a004969f5d81a362110a6ac1496d79efdc6d50c2c4b2e3ea0fc2519/yarl-1.23.0-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:17235362f580149742739cc3828b80e24029d08cbb9c4bda0242c7b5bc610a8e", size = 94685, upload-time = "2026-03-01T22:07:01.375Z" }, + { url = "https://files.pythonhosted.org/packages/e2/b7/14341481fe568e2b0408bcf1484c652accafe06a0ade9387b5d3fd9df446/yarl-1.23.0-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:0793e2bd0cf14234983bbb371591e6bea9e876ddf6896cdcc93450996b0b5c85", size = 106009, upload-time = "2026-03-01T22:07:03.151Z" }, + { url = "https://files.pythonhosted.org/packages/0a/e6/5c744a9b54f4e8007ad35bce96fbc9218338e84812d36f3390cea616881a/yarl-1.23.0-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:3650dc2480f94f7116c364096bc84b1d602f44224ef7d5c7208425915c0475dd", size = 100033, upload-time = "2026-03-01T22:07:04.701Z" }, + { url = "https://files.pythonhosted.org/packages/0c/23/e3bfc188d0b400f025bc49d99793d02c9abe15752138dcc27e4eaf0c4a9e/yarl-1.23.0-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:f40e782d49630ad384db66d4d8b73ff4f1b8955dc12e26b09a3e3af064b3b9d6", size = 106483, upload-time = "2026-03-01T22:07:06.231Z" }, + { url = "https://files.pythonhosted.org/packages/72/42/f0505f949a90b3f8b7a363d6cbdf398f6e6c58946d85c6d3a3bc70595b26/yarl-1.23.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:94f8575fbdf81749008d980c17796097e645574a3b8c28ee313931068dad14fe", size = 102175, upload-time = "2026-03-01T22:07:08.4Z" }, + { url = "https://files.pythonhosted.org/packages/aa/65/b39290f1d892a9dd671d1c722014ca062a9c35d60885d57e5375db0404b5/yarl-1.23.0-cp314-cp314-win32.whl", hash = "sha256:c8aa34a5c864db1087d911a0b902d60d203ea3607d91f615acd3f3108ac32169", size = 83871, upload-time = "2026-03-01T22:07:09.968Z" }, + { url = "https://files.pythonhosted.org/packages/a9/5b/9b92f54c784c26e2a422e55a8d2607ab15b7ea3349e28359282f84f01d43/yarl-1.23.0-cp314-cp314-win_amd64.whl", hash = "sha256:63e92247f383c85ab00dd0091e8c3fa331a96e865459f5ee80353c70a4a42d70", size = 89093, upload-time = "2026-03-01T22:07:11.501Z" }, + { url = "https://files.pythonhosted.org/packages/e0/7d/8a84dc9381fd4412d5e7ff04926f9865f6372b4c2fd91e10092e65d29eb8/yarl-1.23.0-cp314-cp314-win_arm64.whl", hash = "sha256:70efd20be968c76ece7baa8dafe04c5be06abc57f754d6f36f3741f7aa7a208e", size = 83384, upload-time = "2026-03-01T22:07:13.069Z" }, + { url = "https://files.pythonhosted.org/packages/dd/8d/d2fad34b1c08aa161b74394183daa7d800141aaaee207317e82c790b418d/yarl-1.23.0-cp314-cp314t-macosx_10_15_universal2.whl", hash = "sha256:9a18d6f9359e45722c064c97464ec883eb0e0366d33eda61cb19a244bf222679", size = 131019, upload-time = "2026-03-01T22:07:14.903Z" }, + { url = "https://files.pythonhosted.org/packages/19/ff/33009a39d3ccf4b94d7d7880dfe17fb5816c5a4fe0096d9b56abceea9ac7/yarl-1.23.0-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:2803ed8b21ca47a43da80a6fd1ed3019d30061f7061daa35ac54f63933409412", size = 89894, upload-time = "2026-03-01T22:07:17.372Z" }, + { url = "https://files.pythonhosted.org/packages/0c/f1/dab7ac5e7306fb79c0190766a3c00b4cb8d09a1f390ded68c85a5934faf5/yarl-1.23.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:394906945aa8b19fc14a61cf69743a868bb8c465efe85eee687109cc540b98f4", size = 89979, upload-time = "2026-03-01T22:07:19.361Z" }, + { url = "https://files.pythonhosted.org/packages/aa/b1/08e95f3caee1fad6e65017b9f26c1d79877b502622d60e517de01e72f95d/yarl-1.23.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:71d006bee8397a4a89f469b8deb22469fe7508132d3c17fa6ed871e79832691c", size = 95943, upload-time = "2026-03-01T22:07:21.266Z" }, + { url = "https://files.pythonhosted.org/packages/c0/cc/6409f9018864a6aa186c61175b977131f373f1988e198e031236916e87e4/yarl-1.23.0-cp314-cp314t-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:62694e275c93d54f7ccedcfef57d42761b2aad5234b6be1f3e3026cae4001cd4", size = 88786, upload-time = "2026-03-01T22:07:23.129Z" }, + { url = "https://files.pythonhosted.org/packages/76/40/cc22d1d7714b717fde2006fad2ced5efe5580606cb059ae42117542122f3/yarl-1.23.0-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:a31de1613658308efdb21ada98cbc86a97c181aa050ba22a808120bb5be3ab94", size = 101307, upload-time = "2026-03-01T22:07:24.689Z" }, + { url = "https://files.pythonhosted.org/packages/8f/0d/476c38e85ddb4c6ec6b20b815bdd779aa386a013f3d8b85516feee55c8dc/yarl-1.23.0-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:fb1e8b8d66c278b21d13b0a7ca22c41dd757a7c209c6b12c313e445c31dd3b28", size = 100904, upload-time = "2026-03-01T22:07:26.287Z" }, + { url = "https://files.pythonhosted.org/packages/72/32/0abe4a76d59adf2081dcb0397168553ece4616ada1c54d1c49d8936c74f8/yarl-1.23.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:50f9d8d531dfb767c565f348f33dd5139a6c43f5cbdf3f67da40d54241df93f6", size = 97728, upload-time = "2026-03-01T22:07:27.906Z" }, + { url = "https://files.pythonhosted.org/packages/b7/35/7b30f4810fba112f60f5a43237545867504e15b1c7647a785fbaf588fac2/yarl-1.23.0-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:575aa4405a656e61a540f4a80eaa5260f2a38fff7bfdc4b5f611840d76e9e277", size = 95964, upload-time = "2026-03-01T22:07:30.198Z" }, + { url = "https://files.pythonhosted.org/packages/2d/86/ed7a73ab85ef00e8bb70b0cb5421d8a2a625b81a333941a469a6f4022828/yarl-1.23.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:041b1a4cefacf65840b4e295c6985f334ba83c30607441ae3cf206a0eed1a2e4", size = 95882, upload-time = "2026-03-01T22:07:32.132Z" }, + { url = "https://files.pythonhosted.org/packages/19/90/d56967f61a29d8498efb7afb651e0b2b422a1e9b47b0ab5f4e40a19b699b/yarl-1.23.0-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:d38c1e8231722c4ce40d7593f28d92b5fc72f3e9774fe73d7e800ec32299f63a", size = 90797, upload-time = "2026-03-01T22:07:34.404Z" }, + { url = "https://files.pythonhosted.org/packages/72/00/8b8f76909259f56647adb1011d7ed8b321bcf97e464515c65016a47ecdf0/yarl-1.23.0-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:d53834e23c015ee83a99377db6e5e37d8484f333edb03bd15b4bc312cc7254fb", size = 101023, upload-time = "2026-03-01T22:07:35.953Z" }, + { url = "https://files.pythonhosted.org/packages/ac/e2/cab11b126fb7d440281b7df8e9ddbe4851e70a4dde47a202b6642586b8d9/yarl-1.23.0-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:2e27c8841126e017dd2a054a95771569e6070b9ee1b133366d8b31beb5018a41", size = 96227, upload-time = "2026-03-01T22:07:37.594Z" }, + { url = "https://files.pythonhosted.org/packages/c2/9b/2c893e16bfc50e6b2edf76c1a9eb6cb0c744346197e74c65e99ad8d634d0/yarl-1.23.0-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:76855800ac56f878847a09ce6dba727c93ca2d89c9e9d63002d26b916810b0a2", size = 100302, upload-time = "2026-03-01T22:07:39.334Z" }, + { url = "https://files.pythonhosted.org/packages/28/ec/5498c4e3a6d5f1003beb23405671c2eb9cdbf3067d1c80f15eeafe301010/yarl-1.23.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:e09fd068c2e169a7070d83d3bde728a4d48de0549f975290be3c108c02e499b4", size = 98202, upload-time = "2026-03-01T22:07:41.717Z" }, + { url = "https://files.pythonhosted.org/packages/fe/c3/cd737e2d45e70717907f83e146f6949f20cc23cd4bf7b2688727763aa458/yarl-1.23.0-cp314-cp314t-win32.whl", hash = "sha256:73309162a6a571d4cbd3b6a1dcc703c7311843ae0d1578df6f09be4e98df38d4", size = 90558, upload-time = "2026-03-01T22:07:43.433Z" }, + { url = "https://files.pythonhosted.org/packages/e1/19/3774d162f6732d1cfb0b47b4140a942a35ca82bb19b6db1f80e9e7bdc8f8/yarl-1.23.0-cp314-cp314t-win_amd64.whl", hash = "sha256:4503053d296bc6e4cbd1fad61cf3b6e33b939886c4f249ba7c78b602214fabe2", size = 97610, upload-time = "2026-03-01T22:07:45.773Z" }, + { url = "https://files.pythonhosted.org/packages/51/47/3fa2286c3cb162c71cdb34c4224d5745a1ceceb391b2bd9b19b668a8d724/yarl-1.23.0-cp314-cp314t-win_arm64.whl", hash = "sha256:44bb7bef4ea409384e3f8bc36c063d77ea1b8d4a5b2706956c0d6695f07dcc25", size = 86041, upload-time = "2026-03-01T22:07:49.026Z" }, + { url = "https://files.pythonhosted.org/packages/69/68/c8739671f5699c7dc470580a4f821ef37c32c4cb0b047ce223a7f115757f/yarl-1.23.0-py3-none-any.whl", hash = "sha256:a2df6afe50dea8ae15fa34c9f824a3ee958d785fd5d089063d960bae1daa0a3f", size = 48288, upload-time = "2026-03-01T22:07:51.388Z" }, ] [[package]] @@ -5643,32 +5764,38 @@ wheels = [ [[package]] name = "zope-interface" -version = "8.0.1" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/88/3a/7fcf02178b8fad0a51e67e32765cd039ae505d054d744d76b8c2bbcba5ba/zope_interface-8.0.1.tar.gz", hash = "sha256:eba5610d042c3704a48222f7f7c6ab5b243ed26f917e2bc69379456b115e02d1", size = 253746, upload-time = "2025-09-25T05:55:51.285Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/75/e5/ffef169d17b92c6236b3b18b890c0ce73502f3cbd5b6532ff20d412d94a3/zope_interface-8.0.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:fd7195081b8637eeed8d73e4d183b07199a1dc738fb28b3de6666b1b55662570", size = 207364, upload-time = "2025-09-25T05:58:50.262Z" }, - { url = "https://files.pythonhosted.org/packages/35/b6/87aca626c09af829d3a32011599d6e18864bc8daa0ad3a7e258f3d7f8bcf/zope_interface-8.0.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:f7c4bc4021108847bce763673ce70d0716b08dfc2ba9889e7bad46ac2b3bb924", size = 207901, upload-time = "2025-09-25T05:58:51.74Z" }, - { url = "https://files.pythonhosted.org/packages/d8/c1/eec33cc9f847ebeb0bc6234d7d45fe3fc0a6fe8fc5b5e6be0442bd2c684d/zope_interface-8.0.1-cp310-cp310-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:758803806b962f32c87b31bb18c298b022965ba34fe532163831cc39118c24ab", size = 249358, upload-time = "2025-09-25T05:58:16.979Z" }, - { url = "https://files.pythonhosted.org/packages/58/7d/1e3476a1ef0175559bd8492dc7bb921ad0df5b73861d764b1f824ad5484a/zope_interface-8.0.1-cp310-cp310-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:f8e88f35f86bbe8243cad4b2972deef0fdfca0a0723455abbebdc83bbab96b69", size = 254475, upload-time = "2025-09-25T05:58:10.032Z" }, - { url = "https://files.pythonhosted.org/packages/bc/67/ba5ea98ff23f723c5cbe7db7409f2e43c9fe2df1ced67881443c01e64478/zope_interface-8.0.1-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:7844765695937d9b0d83211220b72e2cf6ac81a08608ad2b58f2c094af498d83", size = 254913, upload-time = "2025-09-25T06:26:22.263Z" }, - { url = "https://files.pythonhosted.org/packages/2b/a7/b1b8b6c13fba955c043cdee409953ee85f652b106493e2e931a84f95c1aa/zope_interface-8.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:64fa7b206dd9669f29d5c1241a768bebe8ab1e8a4b63ee16491f041e058c09d0", size = 211753, upload-time = "2025-09-25T05:59:00.561Z" }, - { url = "https://files.pythonhosted.org/packages/f2/2f/c10c739bcb9b072090c97c2e08533777497190daa19d190d72b4cce9c7cb/zope_interface-8.0.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:4bd01022d2e1bce4a4a4ed9549edb25393c92e607d7daa6deff843f1f68b479d", size = 207903, upload-time = "2025-09-25T05:58:21.671Z" }, - { url = "https://files.pythonhosted.org/packages/b5/e1/9845ac3697f108d9a1af6912170c59a23732090bbfb35955fe77e5544955/zope_interface-8.0.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:29be8db8b712d94f1c05e24ea230a879271d787205ba1c9a6100d1d81f06c69a", size = 208345, upload-time = "2025-09-25T05:58:24.217Z" }, - { url = "https://files.pythonhosted.org/packages/f2/49/6573bc8b841cfab18e80c8e8259f1abdbbf716140011370de30231be79ad/zope_interface-8.0.1-cp311-cp311-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:51ae1b856565b30455b7879fdf0a56a88763b401d3f814fa9f9542d7410dbd7e", size = 255027, upload-time = "2025-09-25T05:58:19.975Z" }, - { url = "https://files.pythonhosted.org/packages/e2/fd/908b0fd4b1ab6e412dfac9bd2b606f2893ef9ba3dd36d643f5e5b94c57b3/zope_interface-8.0.1-cp311-cp311-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:d2e7596149cb1acd1d4d41b9f8fe2ffc0e9e29e2e91d026311814181d0d9efaf", size = 259800, upload-time = "2025-09-25T05:58:11.487Z" }, - { url = "https://files.pythonhosted.org/packages/dc/78/8419a2b4e88410520ed4b7f93bbd25a6d4ae66c4e2b131320f2b90f43077/zope_interface-8.0.1-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:b2737c11c34fb9128816759864752d007ec4f987b571c934c30723ed881a7a4f", size = 260978, upload-time = "2025-09-25T06:26:24.483Z" }, - { url = "https://files.pythonhosted.org/packages/e5/90/caf68152c292f1810e2bd3acd2177badf08a740aa8a348714617d6c9ad0b/zope_interface-8.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:cf66e4bf731aa7e0ced855bb3670e8cda772f6515a475c6a107bad5cb6604103", size = 212155, upload-time = "2025-09-25T05:59:40.318Z" }, - { url = "https://files.pythonhosted.org/packages/dc/a6/0f08713ddda834c428ebf97b2a7fd8dea50c0100065a8955924dbd94dae8/zope_interface-8.0.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:115f27c1cc95ce7a517d960ef381beedb0a7ce9489645e80b9ab3cbf8a78799c", size = 208609, upload-time = "2025-09-25T05:58:53.698Z" }, - { url = "https://files.pythonhosted.org/packages/e9/5e/d423045f54dc81e0991ec655041e7a0eccf6b2642535839dd364b35f4d7f/zope_interface-8.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:af655c573b84e3cb6a4f6fd3fbe04e4dc91c63c6b6f99019b3713ef964e589bc", size = 208797, upload-time = "2025-09-25T05:58:56.258Z" }, - { url = "https://files.pythonhosted.org/packages/c6/43/39d4bb3f7a80ebd261446792493cfa4e198badd47107224f5b6fe1997ad9/zope_interface-8.0.1-cp312-cp312-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:23f82ef9b2d5370750cc1bf883c3b94c33d098ce08557922a3fbc7ff3b63dfe1", size = 259242, upload-time = "2025-09-25T05:58:21.602Z" }, - { url = "https://files.pythonhosted.org/packages/da/29/49effcff64ef30731e35520a152a9dfcafec86cf114b4c2aff942e8264ba/zope_interface-8.0.1-cp312-cp312-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:35a1565d5244997f2e629c5c68715b3d9d9036e8df23c4068b08d9316dcb2822", size = 264696, upload-time = "2025-09-25T05:58:13.351Z" }, - { url = "https://files.pythonhosted.org/packages/c7/39/b947673ec9a258eeaa20208dd2f6127d9fbb3e5071272a674ebe02063a78/zope_interface-8.0.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:029ea1db7e855a475bf88d9910baab4e94d007a054810e9007ac037a91c67c6f", size = 264229, upload-time = "2025-09-25T06:26:26.226Z" }, - { url = "https://files.pythonhosted.org/packages/8f/ee/eed6efd1fc3788d1bef7a814e0592d8173b7fe601c699b935009df035fc2/zope_interface-8.0.1-cp312-cp312-win_amd64.whl", hash = "sha256:0beb3e7f7dc153944076fcaf717a935f68d39efa9fce96ec97bafcc0c2ea6cab", size = 212270, upload-time = "2025-09-25T05:58:53.584Z" }, - { url = "https://files.pythonhosted.org/packages/5f/dc/3c12fca01c910c793d636ffe9c0984e0646abaf804e44552070228ed0ede/zope_interface-8.0.1-cp313-cp313-macosx_10_9_x86_64.whl", hash = "sha256:c7cc027fc5c61c5d69e5080c30b66382f454f43dc379c463a38e78a9c6bab71a", size = 208992, upload-time = "2025-09-25T05:58:40.712Z" }, - { url = "https://files.pythonhosted.org/packages/46/71/6127b7282a3e380ca927ab2b40778a9c97935a4a57a2656dadc312db5f30/zope_interface-8.0.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:fcf9097ff3003b7662299f1c25145e15260ec2a27f9a9e69461a585d79ca8552", size = 209051, upload-time = "2025-09-25T05:58:42.182Z" }, - { url = "https://files.pythonhosted.org/packages/56/86/4387a9f951ee18b0e41fda77da77d59c33e59f04660578e2bad688703e64/zope_interface-8.0.1-cp313-cp313-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:6d965347dd1fb9e9a53aa852d4ded46b41ca670d517fd54e733a6b6a4d0561c2", size = 259223, upload-time = "2025-09-25T05:58:23.191Z" }, - { url = "https://files.pythonhosted.org/packages/61/08/ce60a114466abc067c68ed41e2550c655f551468ae17b4b17ea360090146/zope_interface-8.0.1-cp313-cp313-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:9a3b8bb77a4b89427a87d1e9eb969ab05e38e6b4a338a9de10f6df23c33ec3c2", size = 264690, upload-time = "2025-09-25T05:58:15.052Z" }, - { url = "https://files.pythonhosted.org/packages/36/9a/62a9ba3a919594605a07c34eee3068659bbd648e2fa0c4a86d876810b674/zope_interface-8.0.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:87e6b089002c43231fb9afec89268391bcc7a3b66e76e269ffde19a8112fb8d5", size = 264201, upload-time = "2025-09-25T06:26:27.797Z" }, - { url = "https://files.pythonhosted.org/packages/da/06/8fe88bd7edef60566d21ef5caca1034e10f6b87441ea85de4bbf9ea74768/zope_interface-8.0.1-cp313-cp313-win_amd64.whl", hash = "sha256:64a43f5280aa770cbafd0307cb3d1ff430e2a1001774e8ceb40787abe4bb6658", size = 212273, upload-time = "2025-09-25T06:00:25.398Z" }, +version = "8.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/86/a4/77daa5ba398996d16bb43fc721599d27d03eae68fe3c799de1963c72e228/zope_interface-8.2.tar.gz", hash = "sha256:afb20c371a601d261b4f6edb53c3c418c249db1a9717b0baafc9a9bb39ba1224", size = 254019, upload-time = "2026-01-09T07:51:07.253Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b1/fa/6d9eb3a33998a3019d7eb4fa1802d01d6602fad90e0aea443e6e0fe8e49a/zope_interface-8.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:788c293f3165964ec6527b2d861072c68eef53425213f36d3893ebee89a89623", size = 207541, upload-time = "2026-01-09T08:04:55.378Z" }, + { url = "https://files.pythonhosted.org/packages/19/8c/ad23c96fdee84cb1f768f6695dac187cc26e9038e01c69713ba0f7dc46ab/zope_interface-8.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9a4e785097e741a1c953b3970ce28f2823bd63c00adc5d276f2981dd66c96c15", size = 208075, upload-time = "2026-01-09T08:04:57.118Z" }, + { url = "https://files.pythonhosted.org/packages/dd/35/1bfd5fec31a307f0cf4065ee74ade63858ded3e2a71e248f1508118fcc95/zope_interface-8.2-cp310-cp310-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:16c69da19a06566664ddd4785f37cad5693a51d48df1515d264c20d005d322e2", size = 249528, upload-time = "2026-01-09T08:04:59.074Z" }, + { url = "https://files.pythonhosted.org/packages/c6/3a/5d50b5fdb0f8226a2edff6adb7efdd3762ec95dff827dbab1761cb9a9e85/zope_interface-8.2-cp310-cp310-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:c31acfa3d7cde48bec45701b0e1f4698daffc378f559bfb296837d8c834732f6", size = 254646, upload-time = "2026-01-09T08:05:00.964Z" }, + { url = "https://files.pythonhosted.org/packages/2f/2a/ee7d675e151578eaf77828b8faac2b7ed9a69fead350bf5cf0e4afe7c73d/zope_interface-8.2-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:0723507127f8269b8f3f22663168f717e9c9742107d1b6c9f419df561b71aa6d", size = 255083, upload-time = "2026-01-09T08:05:02.857Z" }, + { url = "https://files.pythonhosted.org/packages/5d/07/99e2342f976c3700e142eddc01524e375a9e9078869a6885d9c72f3a3659/zope_interface-8.2-cp310-cp310-win_amd64.whl", hash = "sha256:3bf73a910bb27344def2d301a03329c559a79b308e1e584686b74171d736be4e", size = 211924, upload-time = "2026-01-09T08:05:04.702Z" }, + { url = "https://files.pythonhosted.org/packages/98/97/9c2aa8caae79915ed64eb114e18816f178984c917aa9adf2a18345e4f2e5/zope_interface-8.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c65ade7ea85516e428651048489f5e689e695c79188761de8c622594d1e13322", size = 208081, upload-time = "2026-01-09T08:05:06.623Z" }, + { url = "https://files.pythonhosted.org/packages/34/86/4e2fcb01a8f6780ac84923748e450af0805531f47c0956b83065c99ab543/zope_interface-8.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:a1ef4b43659e1348f35f38e7d1a6bbc1682efde239761f335ffc7e31e798b65b", size = 208522, upload-time = "2026-01-09T08:05:07.986Z" }, + { url = "https://files.pythonhosted.org/packages/f6/eb/08e277da32ddcd4014922854096cf6dcb7081fad415892c2da1bedefbf02/zope_interface-8.2-cp311-cp311-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:dfc4f44e8de2ff4eba20af4f0a3ca42d3c43ab24a08e49ccd8558b7a4185b466", size = 255198, upload-time = "2026-01-09T08:05:09.532Z" }, + { url = "https://files.pythonhosted.org/packages/ea/a1/b32484f3281a5dc83bc713ad61eca52c543735cdf204543172087a074a74/zope_interface-8.2-cp311-cp311-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:8f094bfb49179ec5dc9981cb769af1275702bd64720ef94874d9e34da1390d4c", size = 259970, upload-time = "2026-01-09T08:05:11.477Z" }, + { url = "https://files.pythonhosted.org/packages/f6/81/bca0e8ae1e487d4093a8a7cfed2118aa2d4758c8cfd66e59d2af09d71f1c/zope_interface-8.2-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:d2bb8e7364e18f083bf6744ccf30433b2a5f236c39c95df8514e3c13007098ce", size = 261153, upload-time = "2026-01-09T08:05:13.402Z" }, + { url = "https://files.pythonhosted.org/packages/40/1e/e3ff2a708011e56b10b271b038d4cb650a8ad5b7d24352fe2edf6d6b187a/zope_interface-8.2-cp311-cp311-win_amd64.whl", hash = "sha256:6f4b4dfcfdfaa9177a600bb31cebf711fdb8c8e9ed84f14c61c420c6aa398489", size = 212330, upload-time = "2026-01-09T08:05:15.267Z" }, + { url = "https://files.pythonhosted.org/packages/e0/a0/1e1fabbd2e9c53ef92b69df6d14f4adc94ec25583b1380336905dc37e9a0/zope_interface-8.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:624b6787fc7c3e45fa401984f6add2c736b70a7506518c3b537ffaacc4b29d4c", size = 208785, upload-time = "2026-01-09T08:05:17.348Z" }, + { url = "https://files.pythonhosted.org/packages/c3/2a/88d098a06975c722a192ef1fb7d623d1b57c6a6997cf01a7aabb45ab1970/zope_interface-8.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:bc9ded9e97a0ed17731d479596ed1071e53b18e6fdb2fc33af1e43f5fd2d3aaa", size = 208976, upload-time = "2026-01-09T08:05:18.792Z" }, + { url = "https://files.pythonhosted.org/packages/e9/e8/757398549fdfd2f8c89f32c82ae4d2f0537ae2a5d2f21f4a2f711f5a059f/zope_interface-8.2-cp312-cp312-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:532367553e4420c80c0fc0cabcc2c74080d495573706f66723edee6eae53361d", size = 259411, upload-time = "2026-01-09T08:05:20.567Z" }, + { url = "https://files.pythonhosted.org/packages/91/af/502601f0395ce84dff622f63cab47488657a04d0065547df42bee3a680ff/zope_interface-8.2-cp312-cp312-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:2bf9cf275468bafa3c72688aad8cfcbe3d28ee792baf0b228a1b2d93bd1d541a", size = 264859, upload-time = "2026-01-09T08:05:22.234Z" }, + { url = "https://files.pythonhosted.org/packages/89/0c/d2f765b9b4814a368a7c1b0ac23b68823c6789a732112668072fe596945d/zope_interface-8.2-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:0009d2d3c02ea783045d7804da4fd016245e5c5de31a86cebba66dd6914d59a2", size = 264398, upload-time = "2026-01-09T08:05:23.853Z" }, + { url = "https://files.pythonhosted.org/packages/4a/81/2f171fbc4222066957e6b9220c4fb9146792540102c37e6d94e5d14aad97/zope_interface-8.2-cp312-cp312-win_amd64.whl", hash = "sha256:845d14e580220ae4544bd4d7eb800f0b6034fe5585fc2536806e0a26c2ee6640", size = 212444, upload-time = "2026-01-09T08:05:25.148Z" }, + { url = "https://files.pythonhosted.org/packages/66/47/45188fb101fa060b20e6090e500682398ab415e516a0c228fbb22bc7def2/zope_interface-8.2-cp313-cp313-macosx_10_9_x86_64.whl", hash = "sha256:6068322004a0158c80dfd4708dfb103a899635408c67c3b10e9acec4dbacefec", size = 209170, upload-time = "2026-01-09T08:05:26.616Z" }, + { url = "https://files.pythonhosted.org/packages/09/03/f6b9336c03c2b48403c4eb73a1ec961d94dc2fb5354c583dfb5fa05fd41f/zope_interface-8.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:2499de92e8275d0dd68f84425b3e19e9268cd1fa8507997900fa4175f157733c", size = 209229, upload-time = "2026-01-09T08:05:28.521Z" }, + { url = "https://files.pythonhosted.org/packages/07/b1/65fe1dca708569f302ade02e6cdca309eab6752bc9f80105514f5b708651/zope_interface-8.2-cp313-cp313-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:f777e68c76208503609c83ca021a6864902b646530a1a39abb9ed310d1100664", size = 259393, upload-time = "2026-01-09T08:05:29.897Z" }, + { url = "https://files.pythonhosted.org/packages/eb/a5/97b49cfceb6ed53d3dcfb3f3ebf24d83b5553194f0337fbbb3a9fec6cf78/zope_interface-8.2-cp313-cp313-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:9b05a919fdb0ed6ea942e5a7800e09a8b6cdae6f98fee1bef1c9d1a3fc43aaa0", size = 264863, upload-time = "2026-01-09T08:05:31.501Z" }, + { url = "https://files.pythonhosted.org/packages/cb/02/0b7a77292810efe3a0586a505b077ebafd5114e10c6e6e659f0c8e387e1f/zope_interface-8.2-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:ccc62b5712dd7bd64cfba3ee63089fb11e840f5914b990033beeae3b2180b6cb", size = 264369, upload-time = "2026-01-09T08:05:32.941Z" }, + { url = "https://files.pythonhosted.org/packages/fb/1d/0d1ff3846302ed1b5bbf659316d8084b30106770a5f346b7ff4e9f540f80/zope_interface-8.2-cp313-cp313-win_amd64.whl", hash = "sha256:34f877d1d3bb7565c494ed93828fa6417641ca26faf6e8f044e0d0d500807028", size = 212447, upload-time = "2026-01-09T08:05:35.064Z" }, + { url = "https://files.pythonhosted.org/packages/1a/da/3c89de3917751446728b8898b4d53318bc2f8f6bf8196e150a063c59905e/zope_interface-8.2-cp314-cp314-macosx_10_9_x86_64.whl", hash = "sha256:46c7e4e8cbc698398a67e56ca985d19cb92365b4aafbeb6a712e8c101090f4cb", size = 209223, upload-time = "2026-01-09T08:05:36.449Z" }, + { url = "https://files.pythonhosted.org/packages/00/7f/62d00ec53f0a6e5df0c984781e6f3999ed265129c4c3413df8128d1e0207/zope_interface-8.2-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:a87fc7517f825a97ff4a4ca4c8a950593c59e0f8e7bfe1b6f898a38d5ba9f9cf", size = 209366, upload-time = "2026-01-09T08:05:38.197Z" }, + { url = "https://files.pythonhosted.org/packages/ef/a2/f241986315174be8e00aabecfc2153cf8029c1327cab8ed53a9d979d7e08/zope_interface-8.2-cp314-cp314-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:ccf52f7d44d669203c2096c1a0c2c15d52e36b2e7a9413df50f48392c7d4d080", size = 261037, upload-time = "2026-01-09T08:05:39.568Z" }, + { url = "https://files.pythonhosted.org/packages/02/cc/b321c51d6936ede296a1b8860cf173bee2928357fe1fff7f97234899173f/zope_interface-8.2-cp314-cp314-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:aae807efc7bd26302eb2fea05cd6de7d59269ed6ae23a6de1ee47add6de99b8c", size = 264219, upload-time = "2026-01-09T08:05:41.624Z" }, + { url = "https://files.pythonhosted.org/packages/ab/fb/5f5e7b40a2f4efd873fe173624795ca47eaa22e29051270c981361b45209/zope_interface-8.2-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:05a0e42d6d830f547e114de2e7cd15750dc6c0c78f8138e6c5035e51ddfff37c", size = 264390, upload-time = "2026-01-09T08:05:42.936Z" }, + { url = "https://files.pythonhosted.org/packages/f9/82/3f2bc594370bc3abd58e5f9085d263bf682a222f059ed46275cde0570810/zope_interface-8.2-cp314-cp314-win_amd64.whl", hash = "sha256:561ce42390bee90bae51cf1c012902a8033b2aaefbd0deed81e877562a116d48", size = 212585, upload-time = "2026-01-09T08:05:44.419Z" }, ] From 6d3351ac13fbae5e49b4bd49759e9354f67e3664 Mon Sep 17 00:00:00 2001 From: tconley1428 Date: Tue, 7 Apr 2026 13:44:23 -0700 Subject: [PATCH 033/226] Support running ADK agents outside Temporal workflows (#1400) * Support running ADK agents outside Temporal workflows Add fallback paths in TemporalModel, activity_tool, and TemporalMcpToolSet that detect when code is running outside a workflow (via in_workflow()) and execute directly instead of scheduling activities. This enables local ADK development without a Temporal worker. Includes tests for all three paths plus the error case when no local MCP toolset is provided. Co-Authored-By: Claude Opus 4.6 (1M context) * Linting * Skip MCP in CI * Update error message, reuse agents * Unify lambda and toolset call * Rename local_toolset for non-workflow MCP use * Document local ADK runs for MCP agents * Format MCP rename changes * Clarify shared MCP toolset README example * Clarify shared MCP toolset README example --------- Co-authored-by: Claude Opus 4.6 (1M context) --- .../contrib/google_adk_agents/README.md | 72 ++++-- temporalio/contrib/google_adk_agents/_mcp.py | 23 +- .../contrib/google_adk_agents/_model.py | 9 + .../contrib/google_adk_agents/workflow.py | 9 + .../test_google_adk_agents.py | 210 +++++++++++++----- 5 files changed, 246 insertions(+), 77 deletions(-) diff --git a/temporalio/contrib/google_adk_agents/README.md b/temporalio/contrib/google_adk_agents/README.md index 4fe8440d8..40ebb9aee 100644 --- a/temporalio/contrib/google_adk_agents/README.md +++ b/temporalio/contrib/google_adk_agents/README.md @@ -118,35 +118,44 @@ from temporalio.worker import Worker from temporalio.contrib.google_adk_agents import ( GoogleAdkPlugin, TemporalMcpToolSetProvider, - TemporalMcpToolSet + TemporalMcpToolSet, ) -# Create toolset provider -provider = TemporalMcpToolSetProvider("my-tools", - lambda _: McpToolset( - connection_params=StdioConnectionParams( - server_params=StdioServerParameters( - command="npx", - args=[ - "-y", - "@modelcontextprotocol/server-filesystem", - os.path.dirname(os.path.abspath(__file__)), - ], - ), - ), - )) + +def toolset_factory(_): + return McpToolset( + connection_params=StdioConnectionParams( + server_params=StdioServerParameters( + command="npx", + args=[ + "-y", + "@modelcontextprotocol/server-filesystem", + os.path.dirname(os.path.abspath(__file__)), + ], + ), + ), + ) # Use in agent workflow agent = Agent( name="test_agent", model="gemini-2.5-pro", - tools=[TemporalMcpToolSet("my-tools")] + tools=[ + TemporalMcpToolSet( + "my-tools", + not_in_workflow_toolset=toolset_factory, + ) + ], ) client = await Client.connect( "localhost:7233", plugins=[ - GoogleAdkPlugin(toolset_providers=[provider]), + GoogleAdkPlugin( + toolset_providers=[ + TemporalMcpToolSetProvider("my-tools", toolset_factory), + ], + ), ], ) @@ -157,6 +166,35 @@ worker = Worker( ) ``` +### Local ADK Runs + +The same agent definitions can also be exercised outside Temporal with +`adk run` or `adk web`. + +- `TemporalModel` and `activity_tool(...)` work in local ADK runs without + additional configuration. +- If the agent uses `TemporalMcpToolSet`, define a shared toolset factory, + register it with `TemporalMcpToolSetProvider(...)` for workflow runs, and + reuse the same function for `not_in_workflow_toolset=...` so the agent can + fall back to the underlying `McpToolset` when it is not running inside + `workflow.in_workflow()`. + +Example: + +```python +# Reuse the same toolset_factory registered in GoogleAdkPlugin above. +agent = Agent( + name="test_agent", + model=TemporalModel("gemini-2.5-pro"), + tools=[ + TemporalMcpToolSet( + "my-tools", + not_in_workflow_toolset=toolset_factory, + ) + ], +) +``` + ## Integration Points This integration provides comprehensive support for running Google ADK Agents within Temporal workflows while maintaining: diff --git a/temporalio/contrib/google_adk_agents/_mcp.py b/temporalio/contrib/google_adk_agents/_mcp.py index 6c6123806..92bf994dd 100644 --- a/temporalio/contrib/google_adk_agents/_mcp.py +++ b/temporalio/contrib/google_adk_agents/_mcp.py @@ -90,7 +90,9 @@ class TemporalMcpToolSetProvider: within Temporal workflows. """ - def __init__(self, name: str, toolset_factory: Callable[[Any | None], McpToolset]): + def __init__( + self, name: str, toolset_factory: Callable[[Any | None], McpToolset] + ) -> None: """Initializes the toolset provider. Args: @@ -215,6 +217,7 @@ def __init__( name: str, config: ActivityConfig | None = None, factory_argument: Any | None = None, + not_in_workflow_toolset: Callable[[Any | None], McpToolset] | None = None, ): """Initializes the Temporal MCP toolset. @@ -222,6 +225,12 @@ def __init__( name: Name of the toolset (used for activity naming). config: Optional activity configuration. factory_argument: Optional argument passed to toolset factory. + not_in_workflow_toolset: Optional factory that returns the + underlying ``McpToolset`` to use when this wrapper executes + outside ``workflow.in_workflow()``, such as local ADK runs. + This is not needed during normal workflow execution, but + ``get_tools()`` raises ``ValueError`` outside a workflow if it + is omitted. """ super().__init__() self._name = name @@ -229,6 +238,7 @@ def __init__( self._config = config or ActivityConfig( start_to_close_timeout=timedelta(minutes=1) ) + self._not_in_workflow_toolset = not_in_workflow_toolset async def get_tools( self, readonly_context: ReadonlyContext | None = None @@ -241,6 +251,17 @@ async def get_tools( Returns: List of available tools wrapped as Temporal activities. """ + # If executed outside a workflow, like when doing local adk runs, use the mcp server directly + if not workflow.in_workflow(): + if self._not_in_workflow_toolset is None: + raise ValueError( + "Attempted to use TemporalMcpToolSet outside a workflow, but " + "no not_in_workflow_toolset was provided. Either use " + "McpToolSet directly or pass a factory that returns the " + "underlying McpToolset for non-workflow execution." + ) + return await self._not_in_workflow_toolset(None).get_tools(readonly_context) + tool_results: list[_ToolResult] = await workflow.execute_activity( self._name + "-list-tools", _GetToolsArguments(self._factory_argument), diff --git a/temporalio/contrib/google_adk_agents/_model.py b/temporalio/contrib/google_adk_agents/_model.py index 80079433c..6d1e7ffa9 100644 --- a/temporalio/contrib/google_adk_agents/_model.py +++ b/temporalio/contrib/google_adk_agents/_model.py @@ -5,6 +5,7 @@ from google.adk.models.llm_request import LlmRequest from google.adk.models.llm_response import LlmResponse +import temporalio.workflow from temporalio import activity, workflow from temporalio.workflow import ActivityConfig @@ -67,6 +68,14 @@ async def generate_content_async( Yields: The responses from the model. """ + # If executed outside a workflow, like when doing local adk runs, use the model directly + if not temporalio.workflow.in_workflow(): + async for response in LLMRegistry.new_llm( + self._model_name + ).generate_content_async(llm_request, stream=stream): + yield response + return + responses = await workflow.execute_activity( invoke_model, args=[llm_request], diff --git a/temporalio/contrib/google_adk_agents/workflow.py b/temporalio/contrib/google_adk_agents/workflow.py index 42ff7246f..93815aaba 100644 --- a/temporalio/contrib/google_adk_agents/workflow.py +++ b/temporalio/contrib/google_adk_agents/workflow.py @@ -3,6 +3,7 @@ import inspect from typing import Any, Callable +import temporalio.workflow from temporalio import workflow @@ -29,6 +30,14 @@ async def wrapper(*args: Any, **kw: Any): # Decorator kwargs are defaults. options = kwargs.copy() + if not temporalio.workflow.in_workflow(): + # If executed outside a workflow, like when doing local adk runs, use the function directly + result = activity_def(*args, **kw) + if inspect.isawaitable(result): + return await result + else: + return result + return await workflow.execute_activity(activity_def, *activity_args, **options) # Copy metadata diff --git a/tests/contrib/google_adk_agents/test_google_adk_agents.py b/tests/contrib/google_adk_agents/test_google_adk_agents.py index 22e6be4d8..59ecf8ee4 100644 --- a/tests/contrib/google_adk_agents/test_google_adk_agents.py +++ b/tests/contrib/google_adk_agents/test_google_adk_agents.py @@ -18,8 +18,9 @@ import os import uuid from abc import ABC, abstractmethod -from collections.abc import AsyncGenerator, Iterator +from collections.abc import AsyncGenerator from datetime import timedelta +from typing import Any import pytest from google.adk import Agent, Runner @@ -64,6 +65,19 @@ async def get_weather(city: str) -> str: # type: ignore[reportUnusedParameter] return "Warm and sunny. 17 degrees." +def weather_agent(model_name: str) -> Agent: + # Wraps 'get_weather' activity as a Tool + weather_tool = temporalio.contrib.google_adk_agents.workflow.activity_tool( + get_weather, start_to_close_timeout=timedelta(seconds=60) + ) + + return Agent( + name="test_agent", + model=TemporalModel(model_name), + tools=[weather_tool], + ) + + @workflow.defn class WeatherAgent: @workflow.run @@ -73,17 +87,7 @@ async def run(self, prompt: str, model_name: str) -> Event | None: # 1. Define Agent using Temporal Helpers # Note: AgentPlugin in the Runner automatically handles Runtime setup # and Model Activity interception. We use standard ADK models now. - - # Wraps 'get_weather' activity as a Tool - weather_tool = temporalio.contrib.google_adk_agents.workflow.activity_tool( - get_weather, start_to_close_timeout=timedelta(seconds=60) - ) - - agent = Agent( - name="test_agent", - model=TemporalModel(model_name), - tools=[weather_tool], - ) + agent = weather_agent(model_name) # 2. Create runner runner = InMemoryRunner( @@ -357,6 +361,30 @@ async def test_multi_agent(client: Client, use_local_model: bool): assert result == "haiku" +def example_toolset(_: Any | None) -> McpToolset: + return McpToolset( + connection_params=StdioConnectionParams( + server_params=StdioServerParameters( + command="npx", + args=[ + "-y", + "@modelcontextprotocol/server-filesystem", + os.path.dirname(os.path.abspath(__file__)), + ], + ), + ), + ) + + +def mcp_agent(model_name: str) -> Agent: + return Agent( + name="test_agent", + # instruction="Always use your tools to answer questions.", + model=TemporalModel(model_name), + tools=[TemporalMcpToolSet("test_set", not_in_workflow_toolset=example_toolset)], + ) + + @workflow.defn class McpAgent: @workflow.run @@ -364,14 +392,7 @@ async def run(self, prompt: str, model_name: str) -> str: logger.info("Workflow started.") # 1. Define Agent using Temporal Helpers - # Note: AgentPlugin in the Runner automatically handles Runtime setup - # and Model Activity interception. We use standard ADK models now. - agent = Agent( - name="test_agent", - # instruction="Always use your tools to answer questions.", - model=TemporalModel(model_name), - tools=[TemporalMcpToolSet("test_set")], - ) + agent = mcp_agent(model_name) # 2. Create Session (uses runtime.new_uuid() -> workflow.uuid4()) session_service = InMemorySessionService() @@ -408,39 +429,36 @@ async def run(self, prompt: str, model_name: str) -> str: return last_event.content.parts[0].text -class McpModel(BaseLlm): - responses: list[LlmResponse] = [ - LlmResponse( - content=Content( - role="model", - parts=[ - Part( - function_call=FunctionCall( - args={"path": os.path.dirname(os.path.abspath(__file__))}, - name="list_directory", +class McpModel(TestModel): + def responses(self) -> list[LlmResponse]: + return [ + LlmResponse( + content=Content( + role="model", + parts=[ + Part( + function_call=FunctionCall( + args={ + "path": os.path.dirname(os.path.abspath(__file__)) + }, + name="list_directory", + ) ) - ) - ], - ) - ), - LlmResponse( - content=Content( - role="model", - parts=[Part(text="Some files.")], - ) - ), - ] - response_iter: Iterator[LlmResponse] = iter(responses) + ], + ) + ), + LlmResponse( + content=Content( + role="model", + parts=[Part(text="Some files.")], + ) + ), + ] @classmethod def supported_models(cls) -> list[str]: return ["mcp_model"] - async def generate_content_async( - self, llm_request: LlmRequest, stream: bool = False - ) -> AsyncGenerator[LlmResponse, None]: - yield next(self.response_iter) - @pytest.mark.parametrize("use_local_model", [True, False]) @pytest.mark.asyncio @@ -455,18 +473,7 @@ async def test_mcp_agent(client: Client, use_local_model: bool): toolset_providers=[ TemporalMcpToolSetProvider( "test_set", - lambda _: McpToolset( - connection_params=StdioConnectionParams( - server_params=StdioServerParameters( - command="npx", - args=[ - "-y", - "@modelcontextprotocol/server-filesystem", - os.path.dirname(os.path.abspath(__file__)), - ], - ), - ), - ), + example_toolset, ) ], ) @@ -570,3 +577,88 @@ async def test_single_agent_telemetry( async def test_unsetting_timeout(): model = TemporalModel("", ActivityConfig(start_to_close_timeout=None)) assert model._activity_config.get("start_to_close_timeout", None) is None + + +@pytest.mark.asyncio +async def test_agent_outside_workflow(): + """Test that an agent using TemporalModel and activity_tool works outside a Temporal workflow.""" + LLMRegistry.register(WeatherModel) + + agent = weather_agent("weather_model") + + runner = InMemoryRunner( + agent=agent, + app_name="test_app_local", + ) + + session = await runner.session_service.create_session( + app_name="test_app_local", user_id="test" + ) + + last_event = None + async with Aclosing( + runner.run_async( + user_id="test", + session_id=session.id, + new_message=types.Content( + role="user", parts=[types.Part(text="What is the weather in New York?")] + ), + ) + ) as agen: + async for event in agen: + last_event = event + + assert last_event is not None + assert last_event.content is not None + assert last_event.content.parts is not None + assert last_event.content.parts[0].text == "warm and sunny" + + +@pytest.mark.asyncio +@pytest.mark.skip # Doesn't work well in CI currently +async def test_mcp_agent_outside_workflow(): + """Test that an agent using TemporalMcpToolSet works outside a Temporal workflow.""" + LLMRegistry.register(McpModel) + + agent = mcp_agent("mcp_model") + + session_service = InMemorySessionService() + session = await session_service.create_session( + app_name="test_app_local", user_id="test" + ) + + runner = Runner( + agent=agent, + app_name="test_app_local", + session_service=session_service, + ) + + last_event = None + async with Aclosing( + runner.run_async( + user_id="test", + session_id=session.id, + new_message=types.Content( + role="user", + parts=[types.Part(text="What files are in the current directory?")], + ), + ) + ) as agen: + async for event in agen: + last_event = event + + assert last_event is not None + assert last_event.content is not None + assert last_event.content.parts is not None + assert last_event.content.parts[0].text == "Some files." + + +@pytest.mark.asyncio +async def test_mcp_toolset_outside_workflow_no_not_in_workflow_toolset(): + """Test that TemporalMcpToolSet raises ValueError outside a workflow with no not_in_workflow_toolset.""" + toolset = TemporalMcpToolSet("test_set_no_local") + with pytest.raises( + ValueError, + match="not_in_workflow_toolset", + ): + await toolset.get_tools() From 1bd9641738684bebf65e140ca7b596520e664c25 Mon Sep 17 00:00:00 2001 From: tconley1428 Date: Tue, 7 Apr 2026 16:14:06 -0700 Subject: [PATCH 034/226] Fix Google ADK activity tool argument dispatch (#1421) * Fix Google ADK activity tool argument dispatch * Format Google ADK activity tool tests --- .../contrib/google_adk_agents/workflow.py | 10 +- .../test_google_adk_agents.py | 193 ++++++++++++++++++ 2 files changed, 202 insertions(+), 1 deletion(-) diff --git a/temporalio/contrib/google_adk_agents/workflow.py b/temporalio/contrib/google_adk_agents/workflow.py index 93815aaba..274dde807 100644 --- a/temporalio/contrib/google_adk_agents/workflow.py +++ b/temporalio/contrib/google_adk_agents/workflow.py @@ -38,7 +38,15 @@ async def wrapper(*args: Any, **kw: Any): else: return result - return await workflow.execute_activity(activity_def, *activity_args, **options) + if not activity_args: + return await workflow.execute_activity(activity_def, **options) + if len(activity_args) == 1: + return await workflow.execute_activity( + activity_def, activity_args[0], **options + ) + return await workflow.execute_activity( + activity_def, args=activity_args, **options + ) # Copy metadata wrapper.__name__ = activity_def.__name__ diff --git a/tests/contrib/google_adk_agents/test_google_adk_agents.py b/tests/contrib/google_adk_agents/test_google_adk_agents.py index 59ecf8ee4..d7ccd4699 100644 --- a/tests/contrib/google_adk_agents/test_google_adk_agents.py +++ b/tests/contrib/google_adk_agents/test_google_adk_agents.py @@ -662,3 +662,196 @@ async def test_mcp_toolset_outside_workflow_no_not_in_workflow_toolset(): match="not_in_workflow_toolset", ): await toolset.get_tools() + + +complex_activity_inputs_seen: dict[str, object] = {} + + +@activity.defn +async def book_trip(origin: str, destination: str, passengers: int) -> str: + """Activity that formats multiple discrete arguments.""" + complex_activity_inputs_seen["book_trip"] = (origin, destination, passengers) + return f"{origin}->{destination}:{passengers}" + + +@activity.defn +async def summarize_payload( + name: str, metadata: dict[str, str | int | list[str]] +) -> str: + """Activity that formats compound map input.""" + complex_activity_inputs_seen["summarize_payload"] = (name, metadata) + tags = metadata.get("tags", []) + assert isinstance(tags, list) + return f"{name}:{metadata['count']}:{metadata['owner']}:" + ",".join( + str(tag) for tag in tags + ) + + +class ComplexActivityMethodHolder: + def __init__(self, prefix: str) -> None: + self.prefix = prefix + + @activity.defn + async def annotate_trip(self, trip: str) -> str: + complex_activity_inputs_seen["annotate_trip"] = trip + return f"{self.prefix}:{trip}" + + +@workflow.defn +class ComplexActivityInputAgent: + @workflow.run + async def run(self, prompt: str, model_name: str) -> str: + logger.info("Workflow started.") + method_holder = ComplexActivityMethodHolder("method") + + agent = Agent( + name="complex_input_agent", + model=TemporalModel(model_name), + tools=[ + temporalio.contrib.google_adk_agents.workflow.activity_tool( + book_trip, start_to_close_timeout=timedelta(seconds=60) + ), + temporalio.contrib.google_adk_agents.workflow.activity_tool( + summarize_payload, start_to_close_timeout=timedelta(seconds=60) + ), + temporalio.contrib.google_adk_agents.workflow.activity_tool( + method_holder.annotate_trip, + start_to_close_timeout=timedelta(seconds=60), + ), + ], + ) + + runner = InMemoryRunner( + agent=agent, + app_name="complex_input_app", + ) + + session = await runner.session_service.create_session( + app_name="complex_input_app", user_id="test" + ) + + final_text = "" + async with Aclosing( + runner.run_async( + user_id="test", + session_id=session.id, + new_message=types.Content(role="user", parts=[types.Part(text=prompt)]), + ) + ) as agen: + async for event in agen: + logger.info(f"Event: {event}") + if event.content and event.content.parts: + for part in event.content.parts: + if part.text is not None: + final_text = part.text + + return final_text + + +class ComplexActivityInputModel(TestModel): + def responses(self) -> list[LlmResponse]: + return [ + LlmResponse( + content=Content( + role="model", + parts=[ + Part( + function_call=FunctionCall( + name="book_trip", + args={ + "origin": "SFO", + "destination": "LAX", + "passengers": 3, + }, + ) + ) + ], + ) + ), + LlmResponse( + content=Content( + role="model", + parts=[ + Part( + function_call=FunctionCall( + name="summarize_payload", + args={ + "name": "fixture", + "metadata": { + "count": 2, + "owner": "team-a", + "tags": ["alpha", "beta"], + }, + }, + ) + ) + ], + ) + ), + LlmResponse( + content=Content( + role="model", + parts=[ + Part( + function_call=FunctionCall( + name="annotate_trip", + args={"trip": "SFO->LAX:3"}, + ) + ) + ], + ) + ), + LlmResponse( + content=Content( + role="model", + parts=[Part(text="completed complex input tool calls")], + ) + ), + ] + + @classmethod + def supported_models(cls) -> list[str]: + return ["complex_activity_input_model"] + + +@pytest.mark.asyncio +async def test_activity_tool_supports_complex_inputs_via_adk(client: Client): + new_config = client.config() + new_config["plugins"] = [GoogleAdkPlugin()] + client = Client(**new_config) + complex_activity_inputs_seen.clear() + method_holder = ComplexActivityMethodHolder("method") + + async with Worker( + client, + task_queue="adk-task-queue-complex-inputs", + activities=[ + book_trip, + summarize_payload, + method_holder.annotate_trip, + ], + workflows=[ComplexActivityInputAgent], + max_cached_workflows=0, + ): + LLMRegistry.register(ComplexActivityInputModel) + + handle = await client.start_workflow( + ComplexActivityInputAgent.run, + args=[ + "Run every registered tool using structured inputs.", + "complex_activity_input_model", + ], + id=f"complex-activity-input-workflow-{uuid.uuid4()}", + task_queue="adk-task-queue-complex-inputs", + execution_timeout=timedelta(seconds=60), + ) + result = await handle.result() + assert result == "completed complex input tool calls" + assert complex_activity_inputs_seen == { + "book_trip": ("SFO", "LAX", 3), + "summarize_payload": ( + "fixture", + {"count": 2, "owner": "team-a", "tags": ["alpha", "beta"]}, + ), + "annotate_trip": "SFO->LAX:3", + } From 01359357e3a51083aa82d9f2d7084e9138ed9d1f Mon Sep 17 00:00:00 2001 From: Anthony James Padavano Date: Tue, 7 Apr 2026 19:14:27 -0400 Subject: [PATCH 035/226] docs: document OpenTelemetryConfig and PrometheusConfig fields (#1385) * docs: document OpenTelemetryConfig and PrometheusConfig fields Add comprehensive docstrings with Attributes sections to both telemetry config dataclasses. Documents each field's purpose, default behavior, and includes example values. Addresses #1121 Co-Authored-By: Claude Opus 4.6 (1M context) * fix: metric_periodicity defaults to 1s per sdk-core Co-Authored-By: Claude Opus 4.6 (1M context) --------- Co-authored-by: Claude Opus 4.6 (1M context) Co-authored-by: tconley1428 --- temporalio/runtime.py | 44 +++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 42 insertions(+), 2 deletions(-) diff --git a/temporalio/runtime.py b/temporalio/runtime.py index b151f96f0..8fab68e9e 100644 --- a/temporalio/runtime.py +++ b/temporalio/runtime.py @@ -316,7 +316,26 @@ class OpenTelemetryMetricTemporality(Enum): @dataclass(frozen=True) class OpenTelemetryConfig: - """Configuration for OpenTelemetry collector.""" + """Configuration for OpenTelemetry collector. + + Attributes: + url: URL of the OpenTelemetry collector endpoint (e.g. + ``"http://localhost:4317"`` for gRPC or + ``"http://localhost:4318/v1/metrics"`` for HTTP). + headers: Optional headers to include with each export request. + Useful for authentication tokens or routing metadata. + metric_periodicity: How often metrics are exported to the collector. + Defaults to 1s (set by sdk-core) when ``None``. + metric_temporality: Whether metrics are exported as cumulative + or delta values. Defaults to ``CUMULATIVE``. + durations_as_seconds: If ``True``, export duration metrics as + floating-point seconds instead of integer milliseconds. + Defaults to ``False``. + http: If ``True``, use HTTP/protobuf transport instead of gRPC. + When enabled, the ``url`` should point to the HTTP endpoint + (e.g. ``"http://localhost:4318/v1/metrics"``). + Defaults to ``False`` (gRPC). + """ url: str headers: Mapping[str, str] | None = None @@ -346,7 +365,28 @@ def _to_bridge_config(self) -> temporalio.bridge.runtime.OpenTelemetryConfig: @dataclass(frozen=True) class PrometheusConfig: - """Configuration for Prometheus metrics endpoint.""" + """Configuration for Prometheus metrics endpoint. + + Starts an HTTP server on the given address that exposes a ``/metrics`` + endpoint for Prometheus scraping. + + Attributes: + bind_address: Address to bind the metrics HTTP server to (e.g. + ``"0.0.0.0:9000"`` or ``"127.0.0.1:9090"``). Prometheus + will scrape ``http:///metrics``. + counters_total_suffix: If ``True``, append ``_total`` suffix to + counter metric names, following the OpenMetrics convention. + Defaults to ``False``. + unit_suffix: If ``True``, append unit suffixes (e.g. ``_seconds``, + ``_bytes``) to metric names. Defaults to ``False``. + durations_as_seconds: If ``True``, report duration metrics as + floating-point seconds instead of integer milliseconds. + Defaults to ``False``. + histogram_bucket_overrides: Override the default histogram bucket + boundaries for specific metrics. Keys are metric names and + values are sequences of bucket boundaries (e.g. + ``{"workflow_task_schedule_to_start_latency": [0.01, 0.05, 0.1, 0.5, 1.0, 5.0]}``). + """ bind_address: str counters_total_suffix: bool = False From 66e49d4c3caef3b3d32f7c28378b5dabc591684e Mon Sep 17 00:00:00 2001 From: Edward Amsden Date: Tue, 7 Apr 2026 18:49:19 -0500 Subject: [PATCH 036/226] A couple of errata for the README regarding external storage (#1424) --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index c65216160..967c7147a 100644 --- a/README.md +++ b/README.md @@ -578,7 +578,7 @@ class MyDriver(StorageDriver): claims = [] for payload in payloads: key = await my_storage.put(payload.SerializeToString()) - claims.append(StorageDriverClaim(data={"key": key})) + claims.append(StorageDriverClaim(claim_data={"key": key})) return claims async def retrieve( @@ -586,7 +586,7 @@ class MyDriver(StorageDriver): ) -> list[Payload]: payloads = [] for claim in claims: - data = await my_storage.get(claim.data["key"]) + data = await my_storage.get(claim.claim_data["key"]) p = Payload() p.ParseFromString(data) payloads.append(p) @@ -597,7 +597,7 @@ Some things to note about implementing a custom driver: * `StorageDriver.name()` must return a string that is unique among all drivers in `ExternalStorage.drivers`. This name is embedded in the reference payload stored in workflow history and used to look up the correct driver during retrieval — changing it after payloads have been stored will break retrieval. * `StorageDriver.type()` is automatically implemented to return the name of the class. This can be overridden in subclasses but must remain consistent across all instances of the subclass. -* Implement `temporalio.converter.WithSerializationContext` on your driver to receive workflow or activity context (namespace, workflow ID, activity ID, etc.) at serialization time. +* Use `StorageDriverStoreContext.target` inside `store()` when you need workflow or activity identity (namespace, workflow ID, activity ID, etc.) to choose where or how to store payloads. ### Workers From 8d4070247b4bb8a2611c963d4c6dd31ae4a450ab Mon Sep 17 00:00:00 2001 From: Donald Pinckney Date: Wed, 8 Apr 2026 11:47:16 -0400 Subject: [PATCH 037/226] Update README to remove local activities experimental warning (#1334) Remove experimental warning for local activities in README. Co-authored-by: tconley1428 --- README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/README.md b/README.md index 967c7147a..65a16bcfc 100644 --- a/README.md +++ b/README.md @@ -828,7 +828,6 @@ Some things to note about the above code: capabilities are needed. * Local activities work very similarly except the functions are `workflow.start_local_activity()` and `workflow.execute_local_activity()` - * ⚠️Local activities are currently experimental * Activities can be methods of a class. Invokers should use `workflow.start_activity_method()`, `workflow.execute_activity_method()`, `workflow.start_local_activity_method()`, and `workflow.execute_local_activity_method()` instead. From f93a8b5c6580e0f26f478ed1544edc3be6e7cb88 Mon Sep 17 00:00:00 2001 From: tconley1428 Date: Wed, 8 Apr 2026 10:03:25 -0700 Subject: [PATCH 038/226] Update version to 1.25.0 (#1425) --- pyproject.toml | 2 +- temporalio/service.py | 2 +- uv.lock | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 8cf2fee1d..5e2ec6f1c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "temporalio" -version = "1.24.0" +version = "1.25.0" description = "Temporal.io Python SDK" authors = [{ name = "Temporal Technologies Inc", email = "sdk@temporal.io" }] requires-python = ">=3.10" diff --git a/temporalio/service.py b/temporalio/service.py index 85165356c..776f4332d 100644 --- a/temporalio/service.py +++ b/temporalio/service.py @@ -24,7 +24,7 @@ import temporalio.runtime from temporalio.bridge.client import RPCError as BridgeRPCError -__version__ = "1.24.0" +__version__ = "1.25.0" ServiceRequest = TypeVar("ServiceRequest", bound=google.protobuf.message.Message) ServiceResponse = TypeVar("ServiceResponse", bound=google.protobuf.message.Message) diff --git a/uv.lock b/uv.lock index f5b8b962d..619c740b2 100644 --- a/uv.lock +++ b/uv.lock @@ -962,7 +962,7 @@ name = "exceptiongroup" version = "1.3.1" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "typing-extensions", marker = "python_full_version < '3.13'" }, + { name = "typing-extensions", marker = "python_full_version < '3.11'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/50/79/66800aadf48771f6b62f7eb014e352e5d06856655206165d775e675a02c9/exceptiongroup-1.3.1.tar.gz", hash = "sha256:8b412432c6055b0b7d14c310000ae93352ed6754f70fa8f7c34141f91c4e3219", size = 30371, upload-time = "2025-11-21T23:01:54.787Z" } wheels = [ @@ -4912,7 +4912,7 @@ wheels = [ [[package]] name = "temporalio" -version = "1.24.0" +version = "1.25.0" source = { virtual = "." } dependencies = [ { name = "nexus-rpc" }, From 4f3e320629e5fc63c3490a776fc64dab30debdd4 Mon Sep 17 00:00:00 2001 From: tconley1428 Date: Wed, 8 Apr 2026 11:32:08 -0700 Subject: [PATCH 039/226] Otel is now needed for conftest.py (#1426) * Otel is now needed for conftest.py * Add branch for testing --- .github/workflows/build-binaries.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build-binaries.yml b/.github/workflows/build-binaries.yml index a16a61365..ab0c3ed69 100644 --- a/.github/workflows/build-binaries.yml +++ b/.github/workflows/build-binaries.yml @@ -4,6 +4,7 @@ on: branches: - main - "releases/*" + - build_binaries_otel permissions: contents: read @@ -67,7 +68,7 @@ jobs: if [ "$RUNNER_OS" = "Windows" ]; then bindir=Scripts fi - ./.venv/$bindir/pip install pytest pytest_asyncio grpcio pydantic + ./.venv/$bindir/pip install pytest pytest_asyncio grpcio pydantic opentelemetry-api opentelemetry-sdk ./.venv/$bindir/pip install --prefer-binary ../dist/*.whl ./.venv/$bindir/python -m pytest -s tests/worker/test_workflow.py -k test_workflow_hello From 9bb9776e3932915d0174043ce4cce841dac65732 Mon Sep 17 00:00:00 2001 From: xumaple <45406854+xumaple@users.noreply.github.com> Date: Wed, 8 Apr 2026 16:10:34 -0400 Subject: [PATCH 040/226] Add LangSmith tracing plugin for Temporal workflows (#1369) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Add LangSmith tracing plugin for Temporal workflows Implements a LangSmith contrib plugin that creates trace hierarchies for Temporal operations (workflows, activities, signals, queries, updates, child workflows, Nexus). Supports ambient @traceable context propagation, replay-safe tracing, and an add_temporal_runs toggle for lightweight context-only mode. Co-Authored-By: Claude Opus 4.6 * Refactor LangSmith interceptor: add ReplaySafeRunTree, reduce boilerplate - Add ReplaySafeRunTree wrapper that handles replay skipping and sandbox safety (post/end/patch no-op during replay, sandbox_unrestricted in workflow context), inspired by OTel plugin's _ReplaySafeSpan pattern - Add config.maybe_run() to eliminate repeated config kwargs at every call site - Add _traced_call (client outbound) and _traced_outbound (workflow outbound) helpers to reduce interceptor methods to one-liners - Fold _extract_context into _workflow_maybe_run for workflow inbound - Remove _safe_post, _safe_patch helpers (internalized in wrapper) - Remove in_workflow parameter from _maybe_run (wrapper detects it) - Establish consistent wrapping invariant: all run references are ReplaySafeRunTree, unwrapping is unconditional ._run at RunTree constructor boundary - Parametrize redundant unit tests (client outbound, workflow inbound/outbound) and remove duplicate test - Remove _make_interceptor test helper, use LangSmithInterceptor directly - Collapse plugin constructor tests into one, add comprehensive plugin integration test, remove redundant sandbox tests Co-Authored-By: Claude Opus 4.6 * Fix import sorting and extract _get_current_run_safe helper Fix ruff I001 import sorting violations in _interceptor.py and test_integration.py. Extract _get_current_run_safe() helper for reading ambient LangSmith context with replay safety. Co-Authored-By: Claude Opus 4.6 * Add Nexus integration test coverage Co-Authored-By: Claude Opus 4.6 * Apply ruff formatting to all langsmith files Co-Authored-By: Claude Opus 4.6 * Fix pydocstyle, pyright, and mypy lint errors Co-Authored-By: Claude Opus 4.6 * Fix basedpyright errors and add CLAUDE.md with CI lint docs Co-Authored-By: Claude Opus 4.6 * Fix all basedpyright warnings (deprecated imports, unused params) Co-Authored-By: Claude Opus 4.6 * Clean up unused env params: use type:ignore consistently Co-Authored-By: Claude Opus 4.6 * Address PR review feedback: defaults, naming, and header key - Change add_temporal_runs default to False in both plugin and interceptor (reviewer preference for opt-in behavior) - Rename plugin to langchain.LangSmithPlugin per organization.PluginName convention - Prefix header key with _temporal- to avoid collisions - Update all tests to explicitly pass add_temporal_runs=True Co-Authored-By: Claude Opus 4.6 * Add replay safety and worker restart tests for LangSmith plugin - Add @traceable call (outer_chain) directly in ComprehensiveWorkflow to test non-deterministic tracing alongside deterministic replay - Set max_cached_workflows=0 on all test workers to force replay on every workflow task, exposing header non-determinism - Restructure comprehensive tests with mid-workflow worker restart: one shared collector across two worker lifetimes proves context propagates via headers, not cached plugin state - Add is_waiting_for_signal query and poll helper for deterministic sync (no arbitrary sleeps) - Consolidate make_mock_ls_client in conftest.py, remove unused fixtures, use raw client for polling to avoid trace contamination - Tests are expected to fail (TDD): sandbox blocks @traceable in workflows, max_cached_workflows=0 exposes outputs=None on eviction Co-Authored-By: Claude Opus 4.6 * Implement background thread I/O for LangSmith workflow tracing Move RunTree.post()/patch() I/O off the workflow task thread to a single-worker ThreadPoolExecutor, preventing deadlocks from compressed_traces.lock contention with the LangSmith drain thread. Key changes: - _ReplaySafeRunTree.create_child() override propagates replay safety and deterministic IDs to nested @langsmith.traceable calls - Executor-backed post()/patch() with FIFO ordering and fire-and-forget error logging via Future.add_done_callback - _ContextBridgeRunTree for add_temporal_runs=False without external context — invisible parent that produces root @traceable runs - aio_to_thread patch simplified: removed harmful replay-time tracing disable, added error gate for async @traceable without plugin - Plugin shutdown via SimplePlugin.run_context instead of dead method - Fix misleading comments referencing test artifacts instead of production reasons, remove OTel cross-references - Strict dump_runs catches dangling parent_run_id references - Add **/CLAUDE.md to .gitignore Co-Authored-By: Claude Opus 4.6 (1M context) * Replace unnecessary Any type annotations with specific types Replace ~35 Any annotations across _plugin.py and _interceptor.py with precise types (langsmith.Client, RunTree, _ReplaySafeRunTree, specific SDK interceptor input types, etc.). Add _InputWithHeaders Protocol for private helpers matching the OTel interceptor pattern. Narrow return types to match base class signatures exactly. Co-Authored-By: Claude Opus 4.6 (1M context) * Fix basedpyright warnings in test files Prefix unused mock parameters with underscore (_args, _kwargs) and rename unused variable (_collector) to satisfy basedpyright's reportUnusedParameter and reportUnusedVariable checks. Co-Authored-By: Claude Opus 4.6 (1M context) * Clean up types, dead code, and test assertions - Remove useless _get_current_run_safe wrapper (inline get_current_run_tree) - Restore generic type params on interceptor return types (ActivityHandle[Any], ChildWorkflowHandle[Any, Any]) to match base class exactly - Fix _make_bridge return type (Any → _ContextBridgeRunTree) - Fix _poll_query helper types (Any → WorkflowHandle, Callable) - Strengthen weak assertions in mixed sync/async integration tests - Add _InputWithHeaders Protocol for private helper input params Co-Authored-By: Claude Opus 4.6 (1M context) * Fix formatting in test_integration.py Co-Authored-By: Claude Opus 4.6 (1M context) * Add @traceable to all activity definitions in integration tests Wrap all 5 activity definitions with @traceable as outer decorator to test LangSmith tracing through the full activity execution path. Update all 9 expected trace hierarchies to account for the additional @traceable run nested under each RunActivity. Fix outputs assertion to only check interceptor runs (colon-prefixed names) since @traceable captures actual return values rather than the interceptor's {'status': 'ok'}. Co-Authored-By: Claude Opus 4.6 (1M context) * tests * Fix context propagation bugs and remove handler suppression Bug 1: Replace stale _current_run snapshot with ambient context in outbound interceptor. Add _get_current_run_for_propagation() helper that filters _ContextBridgeRunTree from ambient context. Outbound methods now read get_current_run_tree() for @traceable nesting instead of a frozen reference from workflow entry. Bug 2: Add tracing_context() to Nexus inbound interceptor for both execute_nexus_operation_start and execute_nexus_operation_cancel, matching the activity inbound pattern. Ensures @traceable functions in Nexus handlers have a LangSmith client even with add_temporal_runs=False. Remove handler suppression (is_handler check, _workflow_is_active flag) to align with OTel interceptor which creates spans for all handlers unconditionally. Add dump_traces() to test infrastructure for per-root-trace assertions. Restructure comprehensive tests so user_pipeline only wraps start_workflow, with polling/signals/queries as independent root traces. Co-Authored-By: Claude Opus 4.6 (1M context) * Skip LangSmith tracing for built-in Temporal queries Built-in queries like __temporal_workflow_metadata, __stack_trace, and __enhanced_stack_trace are fired automatically by infrastructure (e.g. the Temporal Web UI) and are not user-facing. Filter them out of LangSmith traces when add_temporal_runs=True to reduce noise. Co-Authored-By: Claude Opus 4.6 (1M context) * Remove dead error gate from _safe_aio_to_thread The isinstance check that raised RuntimeError("Use the LangSmith plugin...") was unreachable — when the plugin is active, _workflow_maybe_run always provides a _ReplaySafeRunTree parent, so _setup_run always returns a _ReplaySafeRunTree child. Co-Authored-By: Claude Opus 4.6 (1M context) * Fix pydoctor cross-refs and mock collector trace duplication - Replace :class:`RunTree` cross-references with backtick literals in docstrings to fix pydoctor build failure (exit status 3). - Add run ID dedup to InMemoryRunCollector.record_create to match real LangSmith API upsert semantics. Fixes flaky Windows CI failure where combined replay+new-event activations caused duplicate trace records with deterministic IDs. Co-Authored-By: Claude Opus 4.6 (1M context) * Address PR review feedback: comments, end() determinism, yield simplification - Reword sandbox/event loop terminology to use each in correct context - Make _safe_aio_to_thread docstring prescriptive (must not block) - Fix end() to use workflow.now() instead of datetime.now(), remove sandbox_unrestricted() from end() - Remove dead uuid4 try/except in read-only context - Remove redundant lazy import langsmith in __init__ - Improve _ContextBridgeRunTree, ls_client, _traced_outbound docs - Change get_current_run_tree → _get_current_run_for_propagation at call sites that propagate context - Simplify _maybe_run to yield None; callers use ambient context via _get_current_run_for_propagation() instead of the yielded value - Full comment audit: fix stale refs, move misplaced comments Co-Authored-By: Claude Opus 4.6 (1M context) * Create per-worker LangSmith interceptors instead of sharing one across workers Previously, all workers sharing a LangSmithPlugin used the same LangSmithInterceptor (and its ThreadPoolExecutor). Now each worker gets its own interceptor via a factory in configure_worker, while client interception uses a shared wrapper that only implements client.Interceptor to avoid being pulled into workers by _init_from_config. Also removes the sync fallback from _submit (formerly _submit_or_fallback) so executor-after-shutdown errors surface immediately instead of silently degrading. Co-Authored-By: Claude Opus 4.6 (1M context) * Remove unnecessary sandbox_unrestricted from post/patch in _ReplaySafeRunTree executor.submit() is not blocked by the workflow sandbox, so the sandbox_unrestricted context manager around _submit calls in post() and patch() was unnecessary. Removes the wrappers and corresponding unit test assertions. Co-Authored-By: Claude Opus 4.6 (1M context) * Rename _ContextBridgeRunTree to _RootReplaySafeRunTreeFactory The old name was misleading — it doesn't bridge contexts. It's a factory that sits in the LangSmith tracing context as a placeholder parent so @traceable can call create_child(), producing independent root _ReplaySafeRunTree instances with no parent link. Also removes unnecessary sandbox_unrestricted from post/patch since executor.submit() is not blocked by the workflow sandbox. Co-Authored-By: Claude Opus 4.6 (1M context) * Rename overloaded kwargs/ctx_kwargs variables in LangSmith interceptor Rename manually constructed dicts to more descriptive names: - kwargs → run_tree_args (used to build RunTree instances) - ctx_kwargs → tracing_args (used to build tracing_context calls) Co-Authored-By: Claude Opus 4.6 (1M context) * Clean up parent post-processing in LangSmith interceptor - _extract_context / _extract_nexus_context now accept ls_client and return fully-formed parents, eliminating 4 call-site fix-ups - Remove unnecessary _ReplaySafeRunTree unwrap in _make_run — RunTree only accesses .id/.dotted_order/.trace_id which delegate transparently - Simplify tracing_args construction by always including project_name and parent (tracing_context treats None same as absent) - Clean up _workflow_maybe_run: eliminate intermediate factory/ tracing_parent variables with single conditional expression Co-Authored-By: Claude Opus 4.6 (1M context) * Make StartFoo and RunFoo siblings instead of parent-child in LangSmith traces StartFoo completes instantly while RunFoo runs for the operation's lifetime, making the parent-child timing misleading in the UI. Now headers carry the ambient parent's context instead of StartFoo's, so RunFoo nests under the same parent as StartFoo. Adds _traced_start for client outbound start operations (separate from _traced_call used by query/signal/update which keep parent-child). Workflow outbound _traced_outbound captures ambient context before maybe_run for all operations. Co-Authored-By: Claude Opus 4.6 (1M context) * Add README for LangSmith plugin Covers quick start, example chatbot, add_temporal_runs toggle, where @traceable works, migration guide, replay safety, and context propagation. Co-Authored-By: Claude Opus 4.6 (1M context) * Share one langsmith.Client across all interceptors Previously, when client=None, each make_interceptor() call created a new langsmith.Client. This meant per-worker clients were never flushed. Now a single client is created eagerly in __init__ and shared via the make_interceptor closure. Also fix WorkerConfig import path for basedpyright. Co-Authored-By: Claude Opus 4.6 (1M context) * Add langsmith optional dependency and install instructions Add langsmith>=0.7.0 to [project.optional-dependencies] so users can install via pip install temporalio[langsmith]. Add Installation section to the LangSmith plugin README. Co-Authored-By: Claude Opus 4.6 (1M context) * Delete duplicate test_constructor_requires_executor test test_constructor_requires_executor and test_constructor_stores_executor were identical. Remove the duplicate. Co-Authored-By: Claude Opus 4.6 (1M context) * Revert to single shared LangSmithInterceptor Remove per-worker interceptor creation and the _ClientOnlyLangSmithInterceptor wrapper. The plugin now creates one LangSmithInterceptor shared across client and all workers, simplifying the design. run_context flushes the client on shutdown. Co-Authored-By: Claude Opus 4.6 (1M context) * Pin langsmith dependency to 0.7.x Add upper bound <0.8 since we monkey-patch langsmith internals (aio_to_thread). This controls upgrades so internal changes in a new minor don't silently break the plugin. Co-Authored-By: Claude Opus 4.6 (1M context) * Improve README and rename plugin params to match interceptor API - Simplify README first sentence, capitalize Temporal abstractions, use @traceable consistently, update StartFoo/RunFoo explanation, add signals/updates to @traceable table, add LangSmith docs link - Rename plugin params metadata/tags to default_metadata/default_tags to match LangSmithInterceptor API - Rename _session to _run_with_trace in README example Co-Authored-By: Claude Opus 4.6 (1M context) * Improve README and rename plugin params to match interceptor API - Simplify README: merge install into Quick Start, capitalize Temporal abstractions, use @traceable consistently, update StartFoo/RunFoo explanation, add signals/updates to @traceable table, add LangSmith docs link, rename _session to _run_with_trace - Rename plugin params metadata/tags to default_metadata/default_tags to match LangSmithInterceptor API Co-Authored-By: Claude Opus 4.6 (1M context) * Consolidate SimpleNexusWorkflow into TraceableActivityWorkflow SimpleNexusWorkflow was nearly identical to TraceableActivityWorkflow. Merge them by adding an optional _input param to TraceableActivityWorkflow and updating NexusService to use it. Co-Authored-By: Claude Opus 4.6 (1M context) * Consolidate test workflows and verify ValidateUpdate elision Merge SimpleNexusWorkflow into TraceableActivityWorkflow to remove duplication. Add my_unvalidated_update handler to ComprehensiveWorkflow and verify that ValidateUpdate traces are only created when a validator is defined. Co-Authored-By: Claude Opus 4.6 (1M context) * Extract find_traces helper for test trace filtering Replace 14 repeated list comprehensions filtering traces by root name with a shared find_traces() helper in conftest.py. Co-Authored-By: Claude Opus 4.6 (1M context) * Add screenshots and polish README examples Replace screenshot placeholders with actual LangSmith and Temporal UI images. Update trace example labels (Request -> Query) and improve Worker crash example description. Co-Authored-By: Claude Opus 4.6 (1M context) * Use uv add in README install instructions Co-Authored-By: Claude Opus 4.6 (1M context) * Simplify _poll_query to rely on pytest timeout Remove redundant timeout from _poll_query — pytest's 60s test timeout is the backstop. Use 1s poll interval. Co-Authored-By: Claude Opus 4.6 (1M context) --------- Co-authored-by: Claude Opus 4.6 --- .gitignore | 1 + pyproject.toml | 2 + temporalio/contrib/langsmith/README.md | 244 ++++ temporalio/contrib/langsmith/__init__.py | 14 + temporalio/contrib/langsmith/_interceptor.py | 976 +++++++++++++ temporalio/contrib/langsmith/_plugin.py | 78 + .../images/langsmith-no-temporal.png | Bin 0 -> 33009 bytes .../langsmith-with-crash-no-temporal.png | Bin 0 -> 60485 bytes .../images/langsmith-with-temporal.png | Bin 0 -> 58344 bytes .../contrib/langsmith/images/temporal-ui.png | Bin 0 -> 46549 bytes tests/contrib/langsmith/__init__.py | 0 tests/contrib/langsmith/conftest.py | 118 ++ tests/contrib/langsmith/test_background_io.py | 651 +++++++++ tests/contrib/langsmith/test_integration.py | 1285 +++++++++++++++++ tests/contrib/langsmith/test_interceptor.py | 1150 +++++++++++++++ tests/contrib/langsmith/test_plugin.py | 222 +++ uv.lock | 352 ++++- 17 files changed, 5086 insertions(+), 7 deletions(-) create mode 100644 temporalio/contrib/langsmith/README.md create mode 100644 temporalio/contrib/langsmith/__init__.py create mode 100644 temporalio/contrib/langsmith/_interceptor.py create mode 100644 temporalio/contrib/langsmith/_plugin.py create mode 100644 temporalio/contrib/langsmith/images/langsmith-no-temporal.png create mode 100644 temporalio/contrib/langsmith/images/langsmith-with-crash-no-temporal.png create mode 100644 temporalio/contrib/langsmith/images/langsmith-with-temporal.png create mode 100644 temporalio/contrib/langsmith/images/temporal-ui.png create mode 100644 tests/contrib/langsmith/__init__.py create mode 100644 tests/contrib/langsmith/conftest.py create mode 100644 tests/contrib/langsmith/test_background_io.py create mode 100644 tests/contrib/langsmith/test_integration.py create mode 100644 tests/contrib/langsmith/test_interceptor.py create mode 100644 tests/contrib/langsmith/test_plugin.py diff --git a/.gitignore b/.gitignore index c35cd4447..923875d32 100644 --- a/.gitignore +++ b/.gitignore @@ -8,6 +8,7 @@ temporalio/bridge/temporal_sdk_bridge* /tests/helpers/golangworker/golangworker /.idea /sdk-python.iml +**/CLAUDE.md /.zed *.DS_Store tags diff --git a/pyproject.toml b/pyproject.toml index 5e2ec6f1c..8e74bd6e1 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -30,6 +30,7 @@ opentelemetry = ["opentelemetry-api>=1.11.1,<2", "opentelemetry-sdk>=1.11.1,<2"] pydantic = ["pydantic>=2.0.0,<3"] openai-agents = ["openai-agents>=0.3,<0.7", "mcp>=1.9.4, <2"] google-adk = ["google-adk>=1.27.0,<2"] +langsmith = ["langsmith>=0.7.0,<0.8"] lambda-worker-otel = [ "opentelemetry-api>=1.11.1,<2", "opentelemetry-sdk>=1.11.1,<2", @@ -77,6 +78,7 @@ dev = [ "pytest-rerunfailures>=16.1", "pytest-xdist>=3.6,<4", "moto[s3,server]>=5", + "langsmith>=0.7.0,<0.8", "setuptools<82", "opentelemetry-exporter-otlp-proto-grpc>=1.11.1,<2", "opentelemetry-semantic-conventions>=0.40b0,<1", diff --git a/temporalio/contrib/langsmith/README.md b/temporalio/contrib/langsmith/README.md new file mode 100644 index 000000000..7002f5538 --- /dev/null +++ b/temporalio/contrib/langsmith/README.md @@ -0,0 +1,244 @@ +# LangSmith Plugin for Temporal Python SDK + +This Temporal [Plugin](https://docs.temporal.io/develop/plugins-guide) allows your [LangSmith](https://smith.langchain.com/) traces to work within Temporal Workflows. It propagates trace context across Worker boundaries so that `@traceable` calls, LLM invocations, and Temporal operations show up in a single connected trace, and ensures that replaying does not generate duplicate traces. + +## Quick Start + +Install Temporal with the LangSmith feature enabled: + +```bash +uv add temporalio[langsmith] +``` + +Register the Plugin on your Temporal Client. You need it on both the Client (starter) side and the Workers: + +```python +from temporalio.client import Client +from temporalio.contrib.langsmith import LangSmithPlugin + +client = await Client.connect( + "localhost:7233", + plugins=[LangSmithPlugin(project_name="my-project")], +) +``` + +Once that's set up, any `@traceable` function inside your Workflows and Activities will show up in LangSmith with correct parent-child relationships, even across Worker boundaries. + +## Example: AI Chatbot + +A conversational chatbot using OpenAI, orchestrated by a Temporal Workflow. The Workflow stays alive waiting for user messages via Signals, and dispatches each message to an Activity that calls the LLM. + +### Activity (Wraps the LLM Call) + +```python +from langsmith import traceable + +@traceable(name="Call OpenAI", run_type="chain") +@activity.defn +async def call_openai(request: OpenAIRequest) -> Response: + client = wrap_openai(AsyncOpenAI()) # This is a traced langsmith function + return await client.responses.create( + model=request.model, + input=request.input, + instructions=request.instructions, + ) +``` + +### Workflow (Orchestrates the Conversation) + +```python +@workflow.defn +class ChatbotWorkflow: + @workflow.run + async def run(self) -> str: + # @traceable works inside Workflows — fully replay-safe + now = workflow.now().strftime("%b %d %H:%M") + return await traceable( + name=f"Session {now}", run_type="chain", + )(self._run_with_trace)() + + async def _run_with_trace(self) -> str: + while not self._done: + await workflow.wait_condition( + lambda: self._pending_message is not None or self._done + ) + if self._done: + break + + message = self._pending_message + self._pending_message = None + + @traceable(name=f"Query: {message[:60]}", run_type="chain") + async def _query(msg: str) -> str: + response = await workflow.execute_activity( + call_openai, + OpenAIRequest(model="gpt-4o-mini", input=msg), + start_to_close_timeout=timedelta(seconds=60), + ) + return response.output_text + + self._last_response = await _query(message) + + return "Session ended." +``` + +### Worker + +```python +client = await Client.connect( + "localhost:7233", + plugins=[LangSmithPlugin(project_name="chatbot")], +) + +worker = Worker( + client, + task_queue="chatbot", + workflows=[ChatbotWorkflow], + activities=[call_openai], +) +await worker.run() +``` + +### What you see in LangSmith + +With the default configuration (`add_temporal_runs=False`), the trace contains only your application logic: + +``` +Session Apr 03 14:30 + Query: "What's the weather in NYC?" + Call OpenAI + openai.responses.create (auto-traced by wrap_openai) +``` + +An actual look at the LangSmith UI: + +![Screenshot: LangSmith trace tree with add_temporal_runs=False showing clean application-only hierarchy](images/langsmith-no-temporal.png) + +## `add_temporal_runs` — Temporal Operation Visibility + +By default, `add_temporal_runs` is `False` and only your `@traceable` application logic appears in traces. Setting it to `True` also adds Temporal operations (StartWorkflow, RunWorkflow, StartActivity, RunActivity, etc.): + +```python +plugins=[LangSmithPlugin(project_name="my-project", add_temporal_runs=True)] +``` + +This adds Temporal operation nodes to the trace tree so that the orchestration layer is visible alongside your application logic. If the caller wraps `start_workflow` in a `@traceable` function, the full trace looks like: + +``` +Ask Chatbot # @traceable wrapper around client.start_workflow + StartWorkflow:ChatbotWorkflow + RunWorkflow:ChatbotWorkflow + Session Apr 03 14:30 + Query: "What's the weather in NYC?" + StartActivity:call_openai + RunActivity:call_openai + Call OpenAI + openai.responses.create +``` + +Note: `StartFoo` and `RunFoo` appear as siblings. The start is the short-lived outbound RPC that enqueues work on a task queue and completes immediately, and the run is the actual execution which may be delayed and may take much longer. + +An actual look at the LangSmith UI: + +![Screenshot: LangSmith trace tree with add_temporal_runs=True showing Temporal operation nodes](images/langsmith-with-temporal.png) + +And here is a waterfall view of the Workflow in Temporal UI: + +![Screenshot: Temporal UI showing the corresponding Workflow execution](images/temporal-ui.png) + +## Migrating Existing LangSmith Code to Temporal + +If you already have code with LangSmith tracing, you should be able to move it into a Temporal Workflow and keep the same trace hierarchy. The Plugin handles sandbox restrictions and context propagation behind the scenes, so anything that was traceable before should remain traceable after the move. More details below: + +### Where `@traceable` Works + +The Plugin allows `@traceable` to work inside Temporal's deterministic Workflow sandbox, where it normally can't run. Note that `@traceable` on an Activity fires on each retry. + +| Location | Works? | Notes | +|-------------------------------|--------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| Inside Workflow methods | Yes | Traces called from inside `@workflow.run`, `@workflow.signal`, etc.; can trace sync and async methods | +| Inside Activity methods | Yes | Traces called from inside `@activity.defn`; can trace sync and async methods | +| On `@activity.defn` functions | Yes | Must stack `@traceable` decorator on top of `@activity.defn` decorator for correct functionality. *Note*: This trace fires on every retry; see [Wrapping Retriable Steps section](#example-wrapping-retriable-steps-in-a-trace) for more info | +| On `@workflow.defn` classes | No | Use `@traceable` inside `@workflow.run` instead. Decorating the workflow class or the `@workflow.run` function is not supported. | + +## Replay Safety + +Temporal Workflows are deterministic and get replayed from event history on recovery. The Plugin accounts for this by injecting replay-safe data into your traceable runs: + +- **No duplicate traces on replay.** Run IDs are derived deterministically from the Workflow's random seed, so replayed operations produce the same IDs and LangSmith deduplicates them. +- **No non-deterministic calls.** The Plugin injects metadata using `workflow.now()` for timestamps and `workflow.random()` for UUIDs instead of `datetime.now()` and `uuid4()`. +- **Background I/O stays outside the sandbox.** LangSmith HTTP calls to the server are submitted to a background thread pool that doesn't interfere with the deterministic Workflow execution. + +You don't need to do anything special for this. Your `@traceable` functions behave the same whether it's a fresh execution or a replay. + +### Example: Worker Crash Mid-Workflow + +``` +1. Workflow starts, executes Activity A -> trace appears in LangSmith +2. Worker crashes during Activity B +3. New Worker picks up the Workflow +4. Workflow replays Activity A (skips execution) -> NO duplicate trace +5. Workflow executes Activity B (new work) -> new trace appears +``` + +As you can see in the UI example below, a crash in the `Call OpenAI` activity didn't cause earlier traces to be duplicated: + +![Screenshot: LangSmith showing a Workflow trace that survived a Worker restart with no duplicate runs](images/langsmith-with-crash-no-temporal.png) + +### Example: Wrapping Retriable Steps in a Trace + +Since Temporal retries failed Activities, you can use an outer `@traceable` to group the attempts together: + +```python +@traceable(name="Call OpenAI", run_type="llm") +@activity.defn +async def call_openai(...): + ... + +@traceable(name="my_step", run_type="chain") +async def my_step(message: str) -> str: + return await workflow.execute_activity( + call_openai, + ... + ) +``` + +This groups everything under one run: +``` +my_step + Call OpenAI # first attempt + openai.responses.create + Call OpenAI # retry + openai.responses.create +``` + +## Context Propagation + +The Plugin propagates trace context across process boundaries (Client -> Workflow -> Activity -> Child Workflow -> Nexus) via Temporal headers. You don't need to pass any context manually. + +``` +Client Process Worker Process (Workflow) Worker Process (Activity) +───────────── ────────────────────────── ───────────────────────── +@traceable("my workflow") + start_workflow ──headers──> RunWorkflow + @traceable("session") + execute_activity ──headers──> RunActivity + @traceable("Call OpenAI") + openai.create(...) +``` + +## API Reference + +### `LangSmithPlugin` + +```python +LangSmithPlugin( + client=None, # langsmith.Client instance (auto-created if None) + project_name=None, # LangSmith project name + add_temporal_runs=False, # Show Temporal operation nodes in traces + default_metadata=None, # Custom metadata attached to all LangSmith traces (https://docs.smith.langchain.com/observability/how_to_guides/add_metadata_tags) + default_tags=None, # Custom tags attached to all LangSmith traces (see link above) +) +``` + +We recommend registering the Plugin on both the Client and all Workers. Strictly speaking, you only need it on the sides that produce traces, but adding it everywhere avoids surprises with context propagation. The Client and Worker don't need to share the same configuration — for example, they can use different `add_temporal_runs` settings. diff --git a/temporalio/contrib/langsmith/__init__.py b/temporalio/contrib/langsmith/__init__.py new file mode 100644 index 000000000..465e36c19 --- /dev/null +++ b/temporalio/contrib/langsmith/__init__.py @@ -0,0 +1,14 @@ +"""LangSmith integration for Temporal SDK. + +This package provides LangSmith tracing integration for Temporal workflows, +activities, and other operations. It includes automatic run creation and +context propagation for distributed tracing in LangSmith. +""" + +from temporalio.contrib.langsmith._interceptor import LangSmithInterceptor +from temporalio.contrib.langsmith._plugin import LangSmithPlugin + +__all__ = [ + "LangSmithInterceptor", + "LangSmithPlugin", +] diff --git a/temporalio/contrib/langsmith/_interceptor.py b/temporalio/contrib/langsmith/_interceptor.py new file mode 100644 index 000000000..5e020eb4d --- /dev/null +++ b/temporalio/contrib/langsmith/_interceptor.py @@ -0,0 +1,976 @@ +"""LangSmith interceptor implementation for Temporal SDK.""" + +from __future__ import annotations + +import json +import logging +import random +import uuid +from collections.abc import Callable, Iterator, Mapping, Sequence +from concurrent.futures import Future, ThreadPoolExecutor +from contextlib import contextmanager +from typing import Any, ClassVar, NoReturn, Protocol + +import langsmith +import nexusrpc.handler +from langsmith import tracing_context +from langsmith.run_helpers import get_current_run_tree +from langsmith.run_trees import RunTree, WriteReplica + +import temporalio.activity +import temporalio.client +import temporalio.converter +import temporalio.worker +import temporalio.workflow +from temporalio.api.common.v1 import Payload +from temporalio.exceptions import ApplicationError, ApplicationErrorCategory + +# This logger is only used in _log_future_exception, which runs on the +# executor thread (not the workflow thread). Never log directly from +# workflow interceptor code — the sandbox blocks logging I/O. +logger = logging.getLogger(__name__) + +# --------------------------------------------------------------------------- +# Constants +# --------------------------------------------------------------------------- + +HEADER_KEY = "_temporal-langsmith-context" + +_BUILTIN_QUERIES: frozenset[str] = frozenset( + { + "__stack_trace", + "__enhanced_stack_trace", + } +) + +# --------------------------------------------------------------------------- +# Context helpers +# --------------------------------------------------------------------------- + +_payload_converter = temporalio.converter.PayloadConverter.default + + +class _InputWithHeaders(Protocol): + headers: Mapping[str, Payload] + + +def _inject_context( + headers: Mapping[str, Payload], + run_tree: RunTree, +) -> dict[str, Payload]: + """Inject LangSmith context into Temporal payload headers. + + Serializes the run's trace context (trace ID, parent run ID, dotted order) + into a Temporal header under ``_temporal-langsmith-context``, enabling parent-child + trace nesting across process boundaries (client → worker, workflow → activity). + """ + ls_headers = run_tree.to_headers() + return { + **headers, + HEADER_KEY: _payload_converter.to_payloads([ls_headers])[0], + } + + +def _inject_current_context( + headers: Mapping[str, Payload], +) -> Mapping[str, Payload]: + """Inject the current ambient LangSmith context into Temporal payload headers. + + Reads ``_get_current_run_for_propagation()`` and injects if present. Returns + headers unchanged if no context is active. Called unconditionally so that + context propagation is independent of the ``add_temporal_runs`` toggle. + """ + current = _get_current_run_for_propagation() + if current is not None: + return _inject_context(headers, current) + return headers + + +def _extract_context( + headers: Mapping[str, Payload], + executor: ThreadPoolExecutor, + ls_client: langsmith.Client, +) -> _ReplaySafeRunTree | None: + """Extract LangSmith context from Temporal payload headers. + + Reconstructs a ``RunTree`` from the ``_temporal-langsmith-context`` header on + the receiving side, wrapped in a :class:`_ReplaySafeRunTree` so inbound + interceptors can establish a parent-child relationship with the sender's + run. Returns ``None`` if no header is present. + """ + header = headers.get(HEADER_KEY) + if not header: + return None + ls_headers = _payload_converter.from_payloads([header])[0] + run = RunTree.from_headers(ls_headers) + if run is None: + return None + run.ls_client = ls_client + return _ReplaySafeRunTree(run, executor=executor) + + +def _inject_nexus_context( + headers: Mapping[str, str], + run_tree: RunTree, +) -> dict[str, str]: + """Inject LangSmith context into Nexus string headers.""" + ls_headers = run_tree.to_headers() + return { + **headers, + HEADER_KEY: json.dumps(ls_headers), + } + + +def _extract_nexus_context( + headers: Mapping[str, str], + executor: ThreadPoolExecutor, + ls_client: langsmith.Client, +) -> _ReplaySafeRunTree | None: + """Extract LangSmith context from Nexus string headers.""" + raw = headers.get(HEADER_KEY) + if not raw: + return None + ls_headers = json.loads(raw) + run = RunTree.from_headers(ls_headers) + if run is None: + return None + run.ls_client = ls_client + return _ReplaySafeRunTree(run, executor=executor) + + +def _get_current_run_for_propagation() -> RunTree | None: + """Get the current ambient run for context propagation. + + Filters out ``_RootReplaySafeRunTreeFactory``, which is internal + scaffolding that should never be serialized into headers or used as + parent runs. + """ + run = get_current_run_tree() + if isinstance(run, _RootReplaySafeRunTreeFactory): + return None + return run + + +# --------------------------------------------------------------------------- +# Workflow event loop safety: patch @traceable's aio_to_thread +# --------------------------------------------------------------------------- + +_aio_to_thread_patched = False + + +def _patch_aio_to_thread() -> None: + """Patch langsmith's ``aio_to_thread`` to run synchronously in workflows. + + The ``@traceable`` decorator on async functions uses ``aio_to_thread()`` → + ``loop.run_in_executor()`` for run setup/teardown. The Temporal workflow + event loop does not support ``run_in_executor``. This patch runs those + functions synchronously on the workflow thread when inside a workflow. + Functions passed here must not perform blocking I/O. + + """ + global _aio_to_thread_patched # noqa: PLW0603 + if _aio_to_thread_patched: + return + + import langsmith._internal._aiter as _aiter + + _original = _aiter.aio_to_thread + + import contextvars + + async def _safe_aio_to_thread( + func: Callable[..., Any], + /, + *args: Any, + __ctx: contextvars.Context | None = None, + **kwargs: Any, + ) -> Any: + if not temporalio.workflow.in_workflow(): + return await _original(func, *args, __ctx=__ctx, **kwargs) + with temporalio.workflow.unsafe.sandbox_unrestricted(): + # Run without ctx.run() so context var changes propagate + # to the caller. Safe because workflows are single-threaded. + return func(*args, **kwargs) + + _aiter.aio_to_thread = _safe_aio_to_thread # type: ignore[assignment] + _aio_to_thread_patched = True + + +# --------------------------------------------------------------------------- +# Replay safety +# --------------------------------------------------------------------------- + + +def _is_replaying() -> bool: + """Check if we're currently replaying workflow history.""" + return ( + temporalio.workflow.in_workflow() + and temporalio.workflow.unsafe.is_replaying_history_events() + ) + + +def _get_workflow_random() -> random.Random | None: + """Get a deterministic random generator for the current workflow. + + Creates a workflow-safe random generator once via + ``workflow.new_random()`` and stores it on the workflow instance so + subsequent calls return the same generator. The generator is seeded + from the workflow's deterministic seed, so it produces identical UUIDs + across replays and worker restarts. + + Returns ``None`` outside a workflow, in read-only (query) contexts, or + when workflow APIs are mocked (unit tests). + """ + try: + if not temporalio.workflow.in_workflow(): + return None + if temporalio.workflow.unsafe.is_read_only(): + return None + inst = temporalio.workflow.instance() + rng = getattr(inst, "__temporal_langsmith_random", None) + if rng is None: + rng = temporalio.workflow.new_random() + setattr(inst, "__temporal_langsmith_random", rng) + return rng + except Exception: + return None + + +def _uuid_from_random(rng: random.Random) -> uuid.UUID: + """Generate a deterministic UUID4 from a workflow-bound random generator.""" + return uuid.UUID(int=rng.getrandbits(128), version=4) + + +# --------------------------------------------------------------------------- +# _ReplaySafeRunTree wrapper +# --------------------------------------------------------------------------- + + +class _ReplaySafeRunTree(RunTree): + """Wrapper around a ``RunTree`` with replay-safe ``post``, ``end``, and ``patch``. + + Inherits from ``RunTree`` so ``isinstance`` checks pass, but does + **not** call ``super().__init__()``—the wrapped ``_run`` is the real + RunTree. Attribute access is delegated via ``__getattr__``/``__setattr__``. + + During replay, ``post()``, ``end()``, and ``patch()`` become no-ops + (I/O suppression), but ``create_child()`` still runs to maintain + parent-child linkage so ``@traceable``'s ``_setup_run`` can build the + run tree across the replay boundary. In workflow context, ``post()`` + and ``patch()`` submit to a single-worker ``ThreadPoolExecutor`` for + FIFO ordering, avoiding blocking on the workflow task thread. + """ + + def __init__( # pyright: ignore[reportMissingSuperCall] + self, + run_tree: RunTree, + *, + executor: ThreadPoolExecutor, + ) -> None: + """Wrap an existing RunTree with replay-safe overrides.""" + object.__setattr__(self, "_run", run_tree) + object.__setattr__(self, "_executor", executor) + + def __getattr__(self, name: str) -> Any: + """Delegate attribute access to the wrapped RunTree.""" + return getattr(self._run, name) + + def __setattr__(self, name: str, value: Any) -> None: + """Delegate attribute setting to the wrapped RunTree.""" + setattr(self._run, name, value) + + def to_headers(self) -> dict[str, str]: + """Delegate to the wrapped RunTree's to_headers.""" + return self._run.to_headers() + + def _inject_deterministic_ids(self, kwargs: dict[str, Any]) -> None: + """Inject deterministic run_id and start_time in workflow context.""" + if temporalio.workflow.in_workflow(): + if kwargs.get("run_id") is None: + rng = _get_workflow_random() + if rng is not None: + kwargs["run_id"] = _uuid_from_random(rng) + if kwargs.get("start_time") is None: + kwargs["start_time"] = temporalio.workflow.now() + + def create_child(self, *args: Any, **kwargs: Any) -> _ReplaySafeRunTree: + """Create a child run, returning another _ReplaySafeRunTree. + + In workflow context, injects deterministic ``run_id`` and ``start_time`` + unless they are passed in manually via ``kwargs``. + """ + self._inject_deterministic_ids(kwargs) + child_run = self._run.create_child(*args, **kwargs) + return _ReplaySafeRunTree(child_run, executor=self._executor) + + def _submit(self, fn: Callable[..., object], *args: Any, **kwargs: Any) -> None: + """Submit work to the background executor.""" + + def _log_future_exception(future: Future[None]) -> None: + exc = future.exception() + if exc is not None: + logger.error("LangSmith background I/O error: %s", exc) + + future = self._executor.submit(fn, *args, **kwargs) + future.add_done_callback(_log_future_exception) + + def post(self, exclude_child_runs: bool = True) -> None: + """Post the run to LangSmith, skipping during replay.""" + if temporalio.workflow.in_workflow(): + if _is_replaying(): + return + self._submit(self._run.post, exclude_child_runs=exclude_child_runs) + else: + self._run.post(exclude_child_runs=exclude_child_runs) + + def end(self, **kwargs: Any) -> None: + """End the run, skipping during replay. + + Pre-computes ``end_time`` via ``workflow.now()`` in workflow context + so ``RunTree.end()`` doesn't call ``datetime.now()`` (non-deterministic + and sandbox-restricted). + """ + if _is_replaying(): + return + if temporalio.workflow.in_workflow(): + kwargs.setdefault("end_time", temporalio.workflow.now()) + self._run.end(**kwargs) + + def patch(self, *, exclude_inputs: bool = False) -> None: + """Patch the run to LangSmith, skipping during replay.""" + if temporalio.workflow.in_workflow(): + if _is_replaying(): + return + self._submit(self._run.patch, exclude_inputs=exclude_inputs) + else: + self._run.patch(exclude_inputs=exclude_inputs) + + +class _RootReplaySafeRunTreeFactory(_ReplaySafeRunTree): + """Factory that produces independent root ``_ReplaySafeRunTree`` instances with no parent link. + + When ``add_temporal_runs=False`` and no parent was propagated via headers, + ``@traceable`` functions still need *something* in the LangSmith + ``tracing_context`` to call ``create_child()`` on — otherwise they + cannot create ``_ReplaySafeRunTree`` children at all and instead default to + creating generic ``RunTree``s, which are not replay safe. This class fills + that role: it sits in the context as the nominal parent so + ``@traceable`` has a ``create_child()`` target. + + However, ``create_child()`` deliberately creates fresh ``RunTree`` + instances with **no** ``parent_run_id``. This means every child appears + as an independent root run in LangSmith rather than being nested under + a phantom parent that was never meant to be visible. + + ``post()``, ``patch()``, and ``end()`` all raise ``RuntimeError`` + because this object is purely internal scaffolding — it must never + appear in LangSmith. If any of these methods are called, it indicates + a programming error. + """ + + def __init__( # pyright: ignore[reportMissingSuperCall] + self, + *, + ls_client: langsmith.Client, + executor: ThreadPoolExecutor, + session_name: str | None = None, + replicas: Sequence[WriteReplica] | None = None, + ) -> None: + """Create a root factory with the given LangSmith client.""" + # Create a minimal RunTree for the factory — it will never be posted + factory_run = RunTree( + name="__root_factory__", + run_type="chain", + ls_client=ls_client, + ) + if session_name is not None: + factory_run.session_name = session_name + if replicas is not None: + factory_run.replicas = replicas + object.__setattr__(self, "_run", factory_run) + object.__setattr__(self, "_executor", executor) + + def post(self, exclude_child_runs: bool = True) -> NoReturn: + """Factory must never be posted.""" + raise RuntimeError("_RootReplaySafeRunTreeFactory must never be posted") + + def patch(self, *, exclude_inputs: bool = False) -> NoReturn: + """Factory must never be patched.""" + raise RuntimeError("_RootReplaySafeRunTreeFactory must never be patched") + + def end(self, **kwargs: Any) -> NoReturn: + """Factory must never be ended.""" + raise RuntimeError("_RootReplaySafeRunTreeFactory must never be ended") + + def create_child(self, *args: Any, **kwargs: Any) -> _ReplaySafeRunTree: + """Create a root _ReplaySafeRunTree (no parent_run_id). + + Creates a fresh ``RunTree(...)`` directly (bypassing + ``self._run.create_child``) so children are independent root runs + with no link back to the factory. + """ + self._inject_deterministic_ids(kwargs) + + # RunTree expects "id", but callers pass "run_id". RunTree.create_child + # also does the same mapping internally. + if "run_id" in kwargs: + kwargs["id"] = kwargs.pop("run_id") + + # Inherit ls_client and session_name from factory. + # session_name must be passed at construction time. + kwargs.setdefault("ls_client", self._run.ls_client) + kwargs.setdefault("session_name", self._run.session_name) + + child_run = RunTree(*args, **kwargs) + # Replicas must be set post-construction + if self._run.replicas is not None: + child_run.replicas = self._run.replicas + return _ReplaySafeRunTree(child_run, executor=self._executor) + + +# --------------------------------------------------------------------------- +# _maybe_run context manager +# --------------------------------------------------------------------------- + + +def _is_benign_error(exc: Exception) -> bool: + """Check if an exception is a benign ApplicationError.""" + return ( + isinstance(exc, ApplicationError) + and getattr(exc, "category", None) == ApplicationErrorCategory.BENIGN + ) + + +@contextmanager +def _maybe_run( + client: langsmith.Client, + name: str, + *, + add_temporal_runs: bool, + run_type: str = "chain", + inputs: dict[str, Any] | None = None, + metadata: dict[str, Any] | None = None, + tags: list[str] | None = None, + parent: RunTree | None = None, + project_name: str | None = None, + executor: ThreadPoolExecutor, +) -> Iterator[None]: + """Create a LangSmith run, handling errors. + + - If add_temporal_runs is False, yields None (no run created). + Context propagation is handled unconditionally by callers. + - When a run IS created, uses :class:`_ReplaySafeRunTree` for + replay and event loop safety, then sets it as ambient context via + ``tracing_context(parent=run_tree)`` so ``get_current_run_tree()`` + returns it and ``_inject_current_context()`` can inject it. + - On exception: marks run as errored (unless benign ApplicationError), re-raises. + + Args: + client: LangSmith client instance. + name: Display name for the run. + add_temporal_runs: Whether to create Temporal-level trace runs. + run_type: LangSmith run type (default ``"chain"``). + inputs: Input data to record on the run. + metadata: Extra metadata to attach to the run. + tags: Tags to attach to the run. + parent: Parent run for nesting. + project_name: LangSmith project name override. + executor: ThreadPoolExecutor for background I/O. + """ + if not add_temporal_runs: + yield None + return + + # If no explicit parent, inherit from ambient @traceable context + if parent is None: + parent = _get_current_run_for_propagation() + + run_tree_args: dict[str, Any] = dict( + name=name, + run_type=run_type, + inputs=inputs or {}, + ls_client=client, + ) + # Deterministic IDs so replayed workflows produce identical runs + # instead of duplicates (see _get_workflow_random for details). + rng = _get_workflow_random() + # In read-only contexts (queries, update validators), _get_workflow_random() + # returns None. Deterministic IDs aren't needed — these aren't replayed. + # LangSmith will auto-generate a random UUID. + if rng is not None: + run_tree_args["id"] = _uuid_from_random(rng) + run_tree_args["start_time"] = temporalio.workflow.now() + if project_name is not None: + run_tree_args["project_name"] = project_name + if parent is not None: + run_tree_args["parent_run"] = parent + if metadata: + run_tree_args["extra"] = {"metadata": metadata} + if tags: + run_tree_args["tags"] = tags + run_tree = _ReplaySafeRunTree(RunTree(**run_tree_args), executor=executor) + run_tree.post() + try: + with tracing_context(parent=run_tree, client=client): + yield None + except Exception as exc: + if not _is_benign_error(exc): + run_tree.end(error=f"{type(exc).__name__}: {exc}") + run_tree.patch() + raise + else: + run_tree.end(outputs={"status": "ok"}) + run_tree.patch() + + +# --------------------------------------------------------------------------- +# LangSmithInterceptor +# --------------------------------------------------------------------------- + + +class LangSmithInterceptor( + temporalio.client.Interceptor, temporalio.worker.Interceptor +): + """Interceptor that supports client and worker LangSmith run creation + and context propagation. + """ + + def __init__( + self, + *, + client: langsmith.Client | None = None, + project_name: str | None = None, + add_temporal_runs: bool = False, + default_metadata: dict[str, Any] | None = None, + default_tags: list[str] | None = None, + ) -> None: + """Initialize the LangSmith interceptor with tracing configuration.""" + super().__init__() + if client is None: + client = langsmith.Client() + self._client = client + self._project_name = project_name + self._add_temporal_runs = add_temporal_runs + self._default_metadata = default_metadata or {} + self._default_tags = default_tags or [] + self._executor = ThreadPoolExecutor(max_workers=1) + + @contextmanager + def maybe_run( + self, + name: str, + *, + run_type: str = "chain", + parent: RunTree | None = None, + extra_metadata: dict[str, Any] | None = None, + ) -> Iterator[None]: + """Create a LangSmith run with this interceptor's config already applied.""" + metadata = {**self._default_metadata, **(extra_metadata or {})} + with _maybe_run( + self._client, + name, + add_temporal_runs=self._add_temporal_runs, + run_type=run_type, + metadata=metadata, + tags=list(self._default_tags), + parent=parent, + executor=self._executor, + project_name=self._project_name, + ) as run: + yield run + + def intercept_client( + self, next: temporalio.client.OutboundInterceptor + ) -> temporalio.client.OutboundInterceptor: + """Create a client outbound interceptor for LangSmith tracing.""" + return _LangSmithClientOutboundInterceptor(next, self) + + def intercept_activity( + self, next: temporalio.worker.ActivityInboundInterceptor + ) -> temporalio.worker.ActivityInboundInterceptor: + """Create an activity inbound interceptor for LangSmith tracing.""" + return _LangSmithActivityInboundInterceptor(next, self) + + def workflow_interceptor_class( + self, input: temporalio.worker.WorkflowInterceptorClassInput + ) -> type[_LangSmithWorkflowInboundInterceptor]: + """Return the workflow interceptor class with config bound.""" + _patch_aio_to_thread() + config = self + + class InterceptorWithConfig(_LangSmithWorkflowInboundInterceptor): + _config = config + + return InterceptorWithConfig + + def intercept_nexus_operation( + self, next: temporalio.worker.NexusOperationInboundInterceptor + ) -> temporalio.worker.NexusOperationInboundInterceptor: + """Create a Nexus operation inbound interceptor for LangSmith tracing.""" + return _LangSmithNexusOperationInboundInterceptor(next, self) + + +# --------------------------------------------------------------------------- +# Client Outbound Interceptor +# --------------------------------------------------------------------------- + + +class _LangSmithClientOutboundInterceptor(temporalio.client.OutboundInterceptor): + """Instruments all client-side calls with LangSmith runs.""" + + def __init__( + self, + next: temporalio.client.OutboundInterceptor, + config: LangSmithInterceptor, + ) -> None: + super().__init__(next) + self._config = config + + @contextmanager + def _traced_call(self, name: str, input: _InputWithHeaders) -> Iterator[None]: + """Wrap a client call with a LangSmith run and inject context into headers.""" + with self._config.maybe_run(name): + input.headers = _inject_current_context(input.headers) + yield + + @contextmanager + def _traced_start(self, name: str, input: _InputWithHeaders) -> Iterator[None]: + """Wrap a start operation, injecting ambient parent context before creating the run. + + Unlike ``_traced_call``, this injects headers *before* ``maybe_run`` + so the downstream ``RunFoo`` becomes a sibling of ``StartFoo`` rather + than a child. + """ + input.headers = _inject_current_context(input.headers) + with self._config.maybe_run(name): + yield + + async def start_workflow( + self, input: temporalio.client.StartWorkflowInput + ) -> temporalio.client.WorkflowHandle[Any, Any]: + prefix = "SignalWithStartWorkflow" if input.start_signal else "StartWorkflow" + with self._traced_start(f"{prefix}:{input.workflow}", input): + return await super().start_workflow(input) + + async def query_workflow(self, input: temporalio.client.QueryWorkflowInput) -> Any: + with self._traced_call(f"QueryWorkflow:{input.query}", input): + return await super().query_workflow(input) + + async def signal_workflow( + self, input: temporalio.client.SignalWorkflowInput + ) -> None: + with self._traced_call(f"SignalWorkflow:{input.signal}", input): + return await super().signal_workflow(input) + + async def start_workflow_update( + self, input: temporalio.client.StartWorkflowUpdateInput + ) -> temporalio.client.WorkflowUpdateHandle[Any]: + with self._traced_call(f"StartWorkflowUpdate:{input.update}", input): + return await super().start_workflow_update(input) + + async def start_update_with_start_workflow( + self, input: temporalio.client.StartWorkflowUpdateWithStartInput + ) -> temporalio.client.WorkflowUpdateHandle[Any]: + input.start_workflow_input.headers = _inject_current_context( + input.start_workflow_input.headers + ) + input.update_workflow_input.headers = _inject_current_context( + input.update_workflow_input.headers + ) + with self._config.maybe_run( + f"StartUpdateWithStartWorkflow:{input.start_workflow_input.workflow}", + ): + return await super().start_update_with_start_workflow(input) + + +# --------------------------------------------------------------------------- +# Activity Inbound Interceptor +# --------------------------------------------------------------------------- + + +class _LangSmithActivityInboundInterceptor( + temporalio.worker.ActivityInboundInterceptor +): + """Instruments activity execution with LangSmith runs.""" + + def __init__( + self, + next: temporalio.worker.ActivityInboundInterceptor, + config: LangSmithInterceptor, + ) -> None: + super().__init__(next) + self._config = config + + async def execute_activity( + self, input: temporalio.worker.ExecuteActivityInput + ) -> Any: + parent = _extract_context( + input.headers, self._config._executor, self._config._client + ) + info = temporalio.activity.info() + extra_metadata = { + "temporalWorkflowID": info.workflow_id or "", + "temporalRunID": info.workflow_run_id or "", + "temporalActivityID": info.activity_id or "", + } + # Unconditionally set tracing context so @traceable functions inside + # activities inherit the plugin's client and parent, regardless of + # the add_temporal_runs toggle. + tracing_args: dict[str, Any] = { + "client": self._config._client, + "enabled": True, + "project_name": self._config._project_name, + "parent": parent, + } + with tracing_context(**tracing_args): + with self._config.maybe_run( + f"RunActivity:{info.activity_type}", + run_type="tool", + parent=parent, + extra_metadata=extra_metadata, + ): + return await super().execute_activity(input) + + +# --------------------------------------------------------------------------- +# Workflow Inbound Interceptor +# --------------------------------------------------------------------------- + + +class _LangSmithWorkflowInboundInterceptor( + temporalio.worker.WorkflowInboundInterceptor +): + """Instruments workflow execution with LangSmith runs.""" + + _config: ClassVar[LangSmithInterceptor] + + def init(self, outbound: temporalio.worker.WorkflowOutboundInterceptor) -> None: + super().init(_LangSmithWorkflowOutboundInterceptor(outbound, self._config)) + + @contextmanager + def _workflow_maybe_run( + self, + name: str, + headers: Mapping[str, Payload] | None = None, + ) -> Iterator[None]: + """Workflow-specific run creation with metadata. + + Extracts parent from headers (if provided) and sets up + ``tracing_context`` so ``@traceable`` functions called from workflow + code can discover the parent and LangSmith client, independent of the + ``add_temporal_runs`` toggle. + """ + parent = ( + _extract_context(headers, self._config._executor, self._config._client) + if headers + else None + ) + # When add_temporal_runs=False and no external parent, create a + # _RootReplaySafeRunTreeFactory so @traceable calls get a + # _ReplaySafeRunTree parent via create_child. The factory is + # invisible in LangSmith. + # tracing_parent can be None when add_temporal_runs=True but no parent was + # propagated via headers — maybe_run will later create a root run in that case. + tracing_parent: _ReplaySafeRunTree | _RootReplaySafeRunTreeFactory | None = ( + parent + if parent is not None or self._config._add_temporal_runs + else _RootReplaySafeRunTreeFactory( + ls_client=self._config._client, + executor=self._config._executor, + session_name=self._config._project_name, + ) + ) + tracing_args: dict[str, Any] = { + "client": self._config._client, + "enabled": True, + "project_name": self._config._project_name, + "parent": tracing_parent, + } + info = temporalio.workflow.info() + extra_metadata = { + "temporalWorkflowID": info.workflow_id, + "temporalRunID": info.run_id, + } + with tracing_context(**tracing_args): + with self._config.maybe_run( + name, + parent=parent, + extra_metadata=extra_metadata, + ) as run: + yield run + + async def execute_workflow( + self, input: temporalio.worker.ExecuteWorkflowInput + ) -> Any: + wf_type = temporalio.workflow.info().workflow_type + with self._workflow_maybe_run( + f"RunWorkflow:{wf_type}", + input.headers, + ): + return await super().execute_workflow(input) + + async def handle_signal(self, input: temporalio.worker.HandleSignalInput) -> None: + with self._workflow_maybe_run(f"HandleSignal:{input.signal}", input.headers): + return await super().handle_signal(input) + + async def handle_query(self, input: temporalio.worker.HandleQueryInput) -> Any: + if input.query.startswith("__temporal") or input.query in _BUILTIN_QUERIES: + return await super().handle_query(input) + with self._workflow_maybe_run(f"HandleQuery:{input.query}", input.headers): + return await super().handle_query(input) + + def handle_update_validator( + self, input: temporalio.worker.HandleUpdateInput + ) -> None: + with self._workflow_maybe_run(f"ValidateUpdate:{input.update}", input.headers): + return super().handle_update_validator(input) + + async def handle_update_handler( + self, input: temporalio.worker.HandleUpdateInput + ) -> Any: + with self._workflow_maybe_run(f"HandleUpdate:{input.update}", input.headers): + return await super().handle_update_handler(input) + + +# --------------------------------------------------------------------------- +# Workflow Outbound Interceptor +# --------------------------------------------------------------------------- + + +class _LangSmithWorkflowOutboundInterceptor( + temporalio.worker.WorkflowOutboundInterceptor +): + """Instruments all outbound calls from workflow code.""" + + def __init__( + self, + next: temporalio.worker.WorkflowOutboundInterceptor, + config: LangSmithInterceptor, + ) -> None: + super().__init__(next) + self._config = config + + @contextmanager + def _traced_outbound(self, name: str, input: _InputWithHeaders) -> Iterator[None]: + """Outbound workflow run creation with context injection into input.headers. + + Uses ambient context so ``@traceable`` step functions that wrap + outbound calls correctly parent the outbound run under themselves. + """ + context_source = _get_current_run_for_propagation() + with self._config.maybe_run(name): + if context_source: + input.headers = _inject_context(input.headers, context_source) + yield None + + def start_activity( + self, input: temporalio.worker.StartActivityInput + ) -> temporalio.workflow.ActivityHandle[Any]: + with self._traced_outbound(f"StartActivity:{input.activity}", input): + return super().start_activity(input) + + def start_local_activity( + self, input: temporalio.worker.StartLocalActivityInput + ) -> temporalio.workflow.ActivityHandle[Any]: + with self._traced_outbound(f"StartActivity:{input.activity}", input): + return super().start_local_activity(input) + + async def start_child_workflow( + self, input: temporalio.worker.StartChildWorkflowInput + ) -> temporalio.workflow.ChildWorkflowHandle[Any, Any]: + with self._traced_outbound(f"StartChildWorkflow:{input.workflow}", input): + return await super().start_child_workflow(input) + + async def signal_child_workflow( + self, input: temporalio.worker.SignalChildWorkflowInput + ) -> None: + with self._traced_outbound(f"SignalChildWorkflow:{input.signal}", input): + return await super().signal_child_workflow(input) + + async def signal_external_workflow( + self, input: temporalio.worker.SignalExternalWorkflowInput + ) -> None: + with self._traced_outbound(f"SignalExternalWorkflow:{input.signal}", input): + return await super().signal_external_workflow(input) + + def continue_as_new(self, input: temporalio.worker.ContinueAsNewInput) -> NoReturn: + # No trace created, but inject context from ambient run + current_run = _get_current_run_for_propagation() + if current_run: + input.headers = _inject_context(input.headers, current_run) + super().continue_as_new(input) + + async def start_nexus_operation( + self, input: temporalio.worker.StartNexusOperationInput[Any, Any] + ) -> temporalio.workflow.NexusOperationHandle[Any]: + context_source = _get_current_run_for_propagation() + with self._config.maybe_run( + f"StartNexusOperation:{input.service}/{input.operation_name}", + ): + if context_source: + input.headers = _inject_nexus_context( + input.headers or {}, context_source + ) + return await super().start_nexus_operation(input) + + +# --------------------------------------------------------------------------- +# Nexus Operation Inbound Interceptor +# --------------------------------------------------------------------------- + + +class _LangSmithNexusOperationInboundInterceptor( + temporalio.worker.NexusOperationInboundInterceptor +): + """Instruments Nexus operations with LangSmith runs.""" + + def __init__( + self, + next: temporalio.worker.NexusOperationInboundInterceptor, + config: LangSmithInterceptor, + ) -> None: + super().__init__(next) + self._config = config + + async def execute_nexus_operation_start( + self, input: temporalio.worker.ExecuteNexusOperationStartInput + ) -> ( + nexusrpc.handler.StartOperationResultSync[Any] + | nexusrpc.handler.StartOperationResultAsync + ): + parent = _extract_nexus_context( + input.ctx.headers, self._config._executor, self._config._client + ) + tracing_args: dict[str, Any] = { + "client": self._config._client, + "enabled": True, + "project_name": self._config._project_name, + "parent": parent, + } + with tracing_context(**tracing_args): + with self._config.maybe_run( + f"RunStartNexusOperationHandler:{input.ctx.service}/{input.ctx.operation}", + run_type="tool", + parent=parent, + ): + return await self.next.execute_nexus_operation_start(input) + + async def execute_nexus_operation_cancel( + self, input: temporalio.worker.ExecuteNexusOperationCancelInput + ) -> None: + parent = _extract_nexus_context( + input.ctx.headers, self._config._executor, self._config._client + ) + tracing_args: dict[str, Any] = { + "client": self._config._client, + "enabled": True, + "project_name": self._config._project_name, + "parent": parent, + } + with tracing_context(**tracing_args): + with self._config.maybe_run( + f"RunCancelNexusOperationHandler:{input.ctx.service}/{input.ctx.operation}", + run_type="tool", + parent=parent, + ): + return await self.next.execute_nexus_operation_cancel(input) diff --git a/temporalio/contrib/langsmith/_plugin.py b/temporalio/contrib/langsmith/_plugin.py new file mode 100644 index 000000000..d7a45a130 --- /dev/null +++ b/temporalio/contrib/langsmith/_plugin.py @@ -0,0 +1,78 @@ +"""LangSmith plugin for Temporal SDK.""" + +from __future__ import annotations + +import dataclasses +from collections.abc import AsyncIterator +from contextlib import asynccontextmanager +from typing import Any + +import langsmith + +from temporalio.contrib.langsmith._interceptor import LangSmithInterceptor +from temporalio.plugin import SimplePlugin +from temporalio.worker import WorkflowRunner +from temporalio.worker.workflow_sandbox import SandboxedWorkflowRunner + + +class LangSmithPlugin(SimplePlugin): + """LangSmith tracing plugin for Temporal SDK. + + Provides automatic LangSmith run creation for workflows, activities, + and other Temporal operations with context propagation. + """ + + def __init__( + self, + *, + client: langsmith.Client | None = None, + project_name: str | None = None, + add_temporal_runs: bool = False, + default_metadata: dict[str, Any] | None = None, + default_tags: list[str] | None = None, + ) -> None: + """Initialize the LangSmith plugin. + + Args: + client: A langsmith.Client instance. If None, one will be created + automatically (using LANGSMITH_API_KEY env var). + project_name: LangSmith project name for traces. + add_temporal_runs: Whether to create LangSmith runs for Temporal + operations. Defaults to False. + default_metadata: Default metadata to attach to all runs. + default_tags: Default tags to attach to all runs. + """ + interceptor = LangSmithInterceptor( + client=client, + project_name=project_name, + add_temporal_runs=add_temporal_runs, + default_metadata=default_metadata, + default_tags=default_tags, + ) + interceptors = [interceptor] + + def workflow_runner(runner: WorkflowRunner | None) -> WorkflowRunner: + if not runner: + raise ValueError("No WorkflowRunner provided to the LangSmith plugin.") + if isinstance(runner, SandboxedWorkflowRunner): + return dataclasses.replace( + runner, + restrictions=runner.restrictions.with_passthrough_modules( + "langsmith" + ), + ) + return runner + + @asynccontextmanager + async def run_context() -> AsyncIterator[None]: + try: + yield + finally: + interceptor._client.flush() + + super().__init__( + "langchain.LangSmithPlugin", + interceptors=interceptors, + workflow_runner=workflow_runner, + run_context=run_context, + ) diff --git a/temporalio/contrib/langsmith/images/langsmith-no-temporal.png b/temporalio/contrib/langsmith/images/langsmith-no-temporal.png new file mode 100644 index 0000000000000000000000000000000000000000..037e0d9ba05ce7f330463b608c3a74b70c9c98c7 GIT binary patch literal 33009 zcmX_{18^j7)b3;3#>V!>*2K2GaVEB%jW+hiw(Vp$wrx#pY;OMF{q8+gJyp{^)jj?8 z+kMXSJ5NU`D@r3H5Fmhofg#HPBviq`z`qu-S2&oj&pXic3K&=*n2dy|x~Jhqj+-&I z%+hd(97g0m!3O4r1&jxwv6IJFr1fw9Pnh6s)^C1Hc})Ac9vw=;p;;!r?)S;bxw*M5 z)=qUVdI6)+2eD@h`6+ZNvah4FAg1c~`l#IXDZZj`hO)}_PW~s<-}fDJ5gT)J^LrF_ zGA?#@c5kIHIMqB#C-<9VNZ+6Tg;-K0?uGycU*N(rX^qA)g;b5AlY$;}&1nVxe-T!6 zzqp&*!H7Zm*A8~>Kxb#;meDjh9YX8#$Z2wE|k0qcM8>z!2)rU1rv#y0JPc4szABi%kO0{blZPuk!~HSK8_*Bgwt&a{4!q2$Wl;n zs?X>p%01B7@RoH-Ji;Xql_B=XtnT-=qr--4Q- z?mxM^_i2qvnZ_y@qa?4ROKv%=8#&j4RfD#82y8 zVo5(hu3J(Pnfo$%+*JuTb715VqO|o$3MIvu_t3hj^gNhpF^V=kW@%fAr(=icGv&_& zvBs7l_Cv0kf&#g`(2rMl>D(TRhIrJa`do67_U%xBWY7$BwVbie-q72W(2xbaN?O&> zB=wVEaX1!7c}KE3hvr=}0in!Hv!ZwzQ56=p{!&wKwKZcO*kYCiE8yX$=x#5oGp+bE z4zwd2Wv6ZF-RG*lG3m{-zw)eEqWGOF`h?GWG8lMYcfa5lu!?2qwA{GKG!Ls)g*)1A@hHlV}-7KoxkP!%EM>nAMq{(_Qd;L2{&$iX7d3 zps^WHB-^l)WIY-Ttr;8}o-=A*@q|PndJOU_@mFV=@!lV+jBTZd!Y34a0sWECYzME26E%wba6$hYNgb1Uw{j)lP z*(_(FRHfDnW3dSVU5q}s>Gdsy(|J-~v<3PPg!S-@=$Ll{@vFRcM7wRg@#C3zdiN1) z3Cngo(%~!AY2JH=J&*I_cg9s;h<)4(vD`CpESrsKccxWO#uBE@(ziE7-FR~&H{?0t zXFG&N{HP2D)U_JA%qCCN9uN;?eS`C@UHCUQ=~JHa4ew}@PmdhEF{pLf+)a8x8p--g z(J^l4nFyG2xg||NR;$3-0#jJC+@0BOZq-S%00+BPC3#K=}=H)gdLV~LpG%(9|M?{y>N(H+U5S~xY2CDEsTWh^7BK{ zvKaV&Mk8{ngHTiqckb`~NbD1Gk#6QgrhYlCc}B65HZ3rFG~ zjP-sMt$A^RqqTIj49%H8mqKuCSKoyT1Y&GJrMm-@qX_1YR%y%UXczqWV~_p2jjh1z zdj)g)Wp23ZSfcxU(J}i=ovd%E0pbTg5)jQiUQONxeYL&o;bh&)s8DH>1q|>+Wr=zG z5D}M1L)6Y-BC~tgvJd;?a~mN)%tu=K1~ZxyMamcZhW}{TJBb{VCH%q#g|8V{6-@3> z(NYH1!SFv>RC9tUyiG~Z3n3MS)`ykUQvKm6p{Luk)=FzJS?`xQG%u5m;1Yuc+exc9j}uLIbi{VA8GWxGG) zCuD?}zQ5<3-7j4U#e*VhPr9#jJxRuST#vrHlXixG&^X#W=Zf@MC?MV3dh`uvDX}`8 zQ4?#2GPKsN`ziL@BRiyuKk?Z-x)b$!D(xPp#}u9yX~V$M!`@ZHZZrJB_viRLOPpU) z%$|W0Z(+y-2RC+EP%uQjw>(qEtrCu|hGn+?k)b{&o-0}v$ zhO2G@Rc?0TAlkIEfl^lQLutxI$2c15`dpXnkaEJx zWPJ$sA)T_yOF}HIvZzqO46DT@TXOh#ZH|XTh z9X@dR(p`oH_%lWZNQc9gd2QyLkT|AbS3vk@+ORbh{en)A+tUr|*>$$+LejPEucKcp zvuXCcRKzb0CvgmzJ?@!1S5hhOdP8v|61}SL$DBsv}jo9;mMC&Y`Gt#*;N{B7=>c1zH1H*m;n`VoJWir;hoEnJ^Q?#2I%RZr$^ zhM2d7AC{OHclf)pP#R_!s!KUS*wO1Mgf$ejy1)o`sjAteU+3InC;u)KJ^O0`*wOZr6$2HTM!p^cbt_)8dKaw7^ z$-VJL5?Yh%{0#!lKtefWs?3v0$%}-5=WF3nyEe6`q%mvWINIbtAs%D6gRioULg8=j z*_fssf0zNgG2Z2^FG^8JspF~0!3|Pl2E-1OSgFg&z5P!tn$zSCli$PnB4i*^yrLxR zA}zQ4h`sujW2xp zfMYipr!YK7?faP!#3MgYK9u&Z(Cp}hgpBV0jQixIFpLw4Vk=WQ` z5(hSK^h%khr4n>I$3){wUS{~Ty0(m;&pKBZAay~bu_izJs9U#7izA!2)^;VJ3F3*h zV^4HZr3M_=@)soS+*Z@5w5~Hs$gacfA6paQW-xC@rC~0S8gd5Eo2C3*ap!Fyv^r`as z_#p;$!o!HJiR#RbFBhD``(m8O#<>$w*R(pT`e z{GpW4lBUenn=QBEOdg1q54V5*Wcb6Xq_TrTS;3$oEjaXHqv7+{ktj&C;$>m3dm(5x zk^TKxZ2Bt+xXwl~Q~g2$g9szD%#|}TNelwOPAotUvWvM#wrNTO^c*4e6I$>%?Hiez zo?6A;?)YY}Ibgq^PeYdPu{Uv?Yw62!9;kCZI}JTg`sgq}&tPPQ_jCmk#Urw@bOv8<=Ri+u(4&JFMLAqHqj;W`t1oCwQEF6r zc?3V>g^5q5H2I-v{*vEI%?Q>sT_VAqpdR9H?^#9V1?+nuL82wyHK$cIv{BBlf8SbGegc+XB&c=4krb-mDzYlWrux9*xZ&YyD6 zI}@SmnpcLhZMEQ=8EMArVqz4KYVpN165~D(4q5iT`@jaew(`i45TqhPtgU?+5%v$kifiUBxPh)5GYmrf|ts1Y+aG4sgDs7y3sHrvXQ?5 zF$#}+{vDsidP*nLp%*jwS-`_7HT6{5=vwKU*cd;WnsfdUm?Fm+VR+SPJB37MC5@tK z18{t2Es2pXszgpDN$|*tKkWp+B`Uv_EmeNoaK6@J(a~HH83P|)Hc5Zlr|05l!eyZ! z52QA4&x7oh8ohFL%Y4HhX$*1db5Wjyc4{eABcgVQYgfLc&<}@eYoqTmoU#}_y2<5T zH!Vo+uiHi_*Oj9w<*H_@5K5u{<|er&q`nG19|#d=1V&*q8< zL7qR^dfuYJ4dl7z@#NvPTX8Ww*C>C$5{!$nHah}I3>w}+q?oX5;leT+;Zn4%;^3Rl zIPt?$YQsNYPI9}{ zM=i_gx5XR@^U|SRY+7LK2?=ovHQuwo{7i30COlYm>aVMA5_XB3px|3#5czs?M)S_2 z8Mz?HeASJ^Z#(Oh6qfdb1q!3)zt(FU;;;Aa&e)xy&ph&~{X+UoDaFkCxbf0Uk7Di^ z#nlwP^%#z%_&?GGFL+Z;-(>oZ=<64d!__ECQbwP!dl&zkxWo6WkIUY9=2*so(^^M- z$!}_%6-J!X*0C_Qu&=sG@wTvsyQ)Io+1&qH*
  • &L<|R~m4|I=^VDL(!glIlL*VEq2-kwh#bD`MP&Lx}Lz}EaH_eZf{)E*n z(XY{iSdLGE9d{+d!a5&g_e8m~^`#0w9G)=su^8@Qw2v?ztHXV|BVxunWdOLxh2-hP zqY-c0vgsG?TXsWG3iBJTchI!N?ALnfg2rtdnCy4YwwD*bAGa{J7-g9ofN*Dm7xjYg zbMA4-iai4~KX?4JPf^dU-iE3DTV7Gs$R0t~#b7Jb)&7LP^qQQf>raI1Hvz&P zl}f$kqQ?aSJ|$KK)(_{hoQi5G)>;FmFQ_E7O4 zI7nwvCW?INAug$`>p$%IDdEp9ifbKO28t%P8AS6Rz7xbQRxy;Y)q|*kE{@N-qU8GG zv7cOPZ;-^HcryW!kv*|iCYO*qsj{! z+|Zg8=p;_B-P#y*E9ac(G_>-G57wlNatDZuk^`sPMT{iMJC%s3?y?;z!tVrFq*irC zq6oS>;o1e}a1pr?JWgBp2_p$~zL<0IiCD4IF~o;!J*{PaFSY^Jab+$*t)SY!Wn0=> zky9&eS@E7&4N^*KA>y@Dfm+zwycQKkRRfVw8D4__RPLVFhTL|Gy#+Uv_z|`UA~@OV zKT3~&HWNocy_Xzytqlsa2 zbKw&O+?ayX^TX^{FkXZV(X|(x+wU$XI!_Z{Ety! zr^mai_fMtZ``6z6hw6{_JU1XC1!F@{lP8`?=59z}@=gpM8{aqSxbn~S5LQ_%D~V_< z3K4;k8(+E5vQ8hOp{OK)F#jd0g22{aItUwIJyb( z;q@z*F0E1LwoSh68-0>-mlf)`Wpz40HxfV?*AJeIYRLJBAy(q=N8)!if4fyL?N4^A zFnZ)&bQ)v??8@Mw9v$&e%Knui3+@S>CY;r~WTZWFFGJI9yB}LEG)GK25%o#O1tN*j z-nnicL|$?xJ9RSYTmf8sPk7Os_;=ly@}Fs6Fvr&yqrkS+Fum6pp3mbH-0=zuf#|YQ zwHc;FF()W0snldH86S_!TcE3JPbLomVGNL1P-s=_e=<`~_)Q{`z`VB`P6`pA`9r^5 z){ThQ9pep^L^L+jZTI5h-`ehoSe3TnkNFzRR7QiS{6Q&-uS&Kbf=Slg3X4ILpz(NO zv}*NEx#`Dg;J&AlgTvO3?RZEfAu+eK&;DG5u zaLUXj9#nK9(2${&P~hZ@dHl5#?`B0h~E@{o4>4`aC-{46Z1qhrd=8jEI`v5 zg!;7oAKGve(^<@({hxYOJ2nuNX@bs3mT1pa-|m#mA#gT zL{k{;=#5OLfzu2qkNtDB;&);KMh$VIeuT(C# zHF+XFXZ+7GD$47q>QMnzr#Xp0@XF3#MH#+=`h@1_qd;k2&s;$fQ zI307lSZUTezgmHTDay+b@<_ml^FmA+-APmf?yNvh=++@%SA3V)HPx66IFTSqw#O`G zlBl2K3eJ}MO(mZSJ-+NPx;E(pyd2vkBcm$2!=b17?H8U3@*Z5I;QduPmA{iMU{?Q6 zzg5LYzvl(8>GV@ON~OY=*lno&Hf^>6qx4U-qs@2e<*h-LMnhXl^uF)|%|XN>SItoU zLwYVKdA}jzM-8ylT4jyRWV12?Hd9Vu_O|JE(4cosQc_YMozMtk69%<>O7U8uZ%p-_mo|J5Rg-TMM@X`!fl4>Rofr zzuV2ejc4;_r6$p-ecvSIZ{b$V>keFVBRHFO&7ZfLNS#i+-$<=qW9TZBa+6{J=F9Uh z)NVuRwSYLuJ}~avLy}qLQ|b9zE`@@Zh+n^@ma;e>u`u=7K;k|f{9z$~j%r*Uu3kde z<2*%!AElsSDfG;61U}w^$jA;0G(MJ41f5Fj{ix8ouceAn=>$`QBXadMYQD}niFSiC;zpO+0EMEBD~JmT zG1VS!kMqL?XYdq}dsxL?q@+sHX?LyrYg%*iyAuA~hZtMHzpY5R|CyzkKY1-=UjpHc zw0Q)IU;*B4xCLEehS8H}vl}=7D^X`1uc6#3b)2yzU+9q&w81VsS$4ry_2Oo+87Pq) zXB(<>e176xx4ULU^SE4o^EK?0)VrM3$oJWu)0o6ZA^r|w#iBoO!iKpJHjK$?j}gJ` z@$VZF#vc-XAOYcb2MyR$ICL@F+hqLA09WT%eqjQ^4rFKXh}eN~E#Z8(bCfe$cp1b$ z-&@m(&xd)1{2n1-QHh6Jxz76~<6{`fy-6AM>R%uHFalL(HCmXA>Zy$h$4$4AP5h#< zPVcQYQw5qGp_9%5$N^F3g;dP|FYnS_K4xab=z&}7FAvYVd zK~G%8_JaDdO@NaoL*!|r&x;c8}vKh~`Z8a{MR;`LOae+oSG}k`?rx_>sx7PjV zzm4ev5B%WT>TZkYOO7akxVy5)9iFGrB1vLs8|x3B3aza?PAuSM2gyh#lU;S`LF3KR{NO%kH_m@ z(xC(q4W`#+%3(QaR4k0kq(Pk3LMl;l|6N+<8Hd>r`ziN5kk}{QZ0py;>euPmzo0B+)&trLm#N>dy zZ=arLnu5r3TIY9u^+N}Gzs&LL;xZLi^5cU-q4KT}Nv|bHYO)i9e(9ka&3n2hq=TNs z&R=~8Ykn13qtZWynEz>SW_N#&@BFMjHy4=5rRNZ49is{2l+I+-u@UgRSKkG2EBtBq z8JgYq+87ufe<0C8W%&7Y|Fd*7g-(yoII+4*p3*hNE>AY4Vt=UI1p%0fDVhyp2R6&= zu@d*ca@%a^k6UG|HXipYWT>aJEbSu$dKtg!uxgc3s+KFk60n#wTD8FS@yyD$V8>(; z_p^y&1StoazP7n79es;w|H2t@PT(5EhTl5^$8ohp&j5A;vkSNaevy2dG*~w5=#;+7 zjOmC`JsfxU@a58t~{D5)Su*EyB&`#q(B9tubf3k?nwcsFzz@@OiRs?d~ygk>ah{F%XSB`yg3 z?Mu^SS^bJ2hT=V{;lnUQ%;%aMY||Th;k7hF5`kxw*5OQIRM&&63NO_5m%>tj=LlNp+-5s;>g+KYPHl2v}r~5 zEhgsRt+-S%PkP$$13NAXv9@PatGc&*S9#QpTZrqR;+^_ThDNB`t)k+X%)M z2d>ZU1g{@<%vGav{$E)Qyaa!f*9}qGRYMi}+T9mwl_wzzSGFJdeW01Bn6m9AwS;X6 zXZ5clHK9{PXVPm#Zh{-!`NUC*N+ywOhXDT_p}dh%zX}0^`VJ9p@{|!?VJYaUiM_ec zZ)r>*r4|4k#%2`N@W{Iqgus%Zo3Pi{x<%gXA4Bu!cPoEx!mcT5(75v2KVs$76nZxp zte1+=4xxW`MmXTftS0Q)LN10{?IC)zs4|a-XwF}=so#U+_-sHun+G0pF(fbPtwb~m z!y<8*1@@UB#m)b00pD$StHYxQLaKFaxqM^84`MOuur8NMHg$eEzp4rP>88<^QR!e@ zOG1s%b>Q*EkVLvPmtEtP?5TjA?4#?RDsTa&<0pX>x6PL1HsPTo85_-Ct<5 z54zoB@3*sO4oPF(UXn97v2)MMW8mW(=xKEd+1pQU7k`T3|_|bgg64tleH`SH0;A93X};!5`&I>w9!1=aB#o zVY=qD<_O_p7(SXTI)(icxvuyDdgfFBy?#Mk%p!mh6bT7@Fp_a$y!g}<2?m$Bgjlc5 zZ+s`;IH|n!3sHh~!GEQ&sw!1gle;-BNP9GmOz*xmd#(FE#kD`Vkp%`8MtezoIZ^{1 zGrOcn^Hqx&B8PP7&y6^oeEq+)`PU98V2pq-_aZisatt4sMD>lF&vw}3wK9>43o4;> zu;meLYK8GimpauzY?6=dlYp8&vXA7?Xj%)%vty=F9~1+qirLXp53f`y(t0751Oj|~ z{14RswK4vG-Vp{jXE_R8v=3dRa3IoijN|W|iuj4Fs!4gm_Mew9?`K0Z0!$H|OCN`% z5YJmtSWH?itz;X0iL^7NY%c!4RfH3((U1T6WwLT}MO3Sfr zD4OCHUTfI(My!Ccd?$~q*57@@@jpf*BcpwKlt_!0Frol%CC2H#;iM(6MG9_hLkKu* z-1q;_eyJooAj>^H^uJEWDkaRKs^#^udZhohInB{PsvePN3-0dWpfX>=OWbTLPCT)b zo@>|q2YBAjlEBJESW`XNJvGn4uk!hKx&HBVjSwStjt~WFWt}?7Woa2-pf~ycx38yJ zX;f8ULCu!T?xqELmzFQ;Rq^yr_rdA9+|)ycH;O|>FNW0_{ypD+Cwf)!i4DLE$1d6< z6J&5}5_R1jW-_`6<=rP2Et8KvZk--{f5d zaqiOki7?4`9l^fq3a10)mRb}9YUMZM`T1dy7;vaNPOMNnY^{pvI;zYhtg)JJxhdU9e>>chFPa&zMU7AE>#XkEHr_4@K9)IT1Vza*;hm|V*3OpY9OnSAP@g7ZmY!Rlh&~~`DsTKjOdS7~Zn2HS33tkV zB(isKx?OG{j+vhixoTs}}Jsh~effw!@CNL;u?bSnG-OcZMit zQlcU(LiVq0{f8EHCzg!3fkHi@BkJ6)>B{H*=IV2B2vL~gu7U>8xyL4z_a+mR>9MKS zHr=X!Y6foI!yTMVOr8X0@^?(3&Fd52VKX3z@F~~iC6noTJXQF2p)b-N7_&+TLd~XE zuniX>c{C5U5WiN?zddY1Am|bk>$T$N(kg-cmyGN`z`s+e(C5-`b4T^M#r8Y*F@3S1 zUl7@?9k*$B1vH;=jee!*L~6g5R%cS9w6Z`9iwc-`0hcXj>$g}wT48fxB$oQz;xWIF z0m<=GKbK%r!lyHC0kE1~suq_*OVG_lgmBR&Jxpex80LAumD|UZn%%k|9(+;}yr&dn zqstRGkK1mz81SIYdX1&wkP&N!#nXSP%V>Wt78Xy)GWwB2%lKDt?ELC^6{DbtsCOoBtjS^*~4bgM#7%?!wpfYo-@lAFQ$ z`843}nE|KcrX&nNhtqx*-HLg0Z|g#Clax1hxr!PxKlvJTa+g*mSyWb! zt}<4uQ;UBo06;FmUk^ zm<`hNjm}TFpk0@ulpck2jOedFJ$tTW-|0CFqmPZ}Tws1*|JEmy)3@$^7W<7oYQc7a zV02o)e|5aI`STF#xBusOFPrxOl3QW*y2tWA?N-roRwb~jiUd`>)D^|4{EGmF;RZ-+ zu@@Q>cKC93tk<2d?n)9oW~oH3fMf!tb!H$e&PhjpVDif}r5s8ApKvSMh8z4YoSB?8 z5N?@6&l91g(FZp3S69ouCclt+cWa+Cp>@Z$Z|GVg6i~xAkAZc8cj1d&xg?quC%8+_ zQKj+JfvlIWa`$+qs;#+11pTG=@qXs96Fy`$&5HI#qzgz&xtverH8q z`Vy;K+GmdkZvp+nKH$mBM#LT@e(?pW?nyYrtnPF24pPcH4vtJD-PYT z=VWF&-LNY#TeE6uSa|Xj>aQhn9hl)!0?Rc1&I^tkFlN;L5&uG@DdNHSI}H3YpJrRk zSh72PrHN-)fefq8*dtxTwskfi?&fLJ;>89qD8v!I&~mi*o+Rt>Z?AeFddL;IwMGA( z>+}X}+uv5bCJ5hKs6MY219--?D$4tg?sm=Rtoi`RNnVBzYq4w&bBss?LL|_`fAuh7 zKdm<5h*~7yrn(oNb!SVwyeFB`tUG4)UEX~JssI@>RI`fxZt;Ecn~IXb9f@tgt5nlU@O zpinw5-}C)eD>mFyV0`!U;;NOjXTg1%D(O+=l(5Pw^iRzksqdlAw&v)#%w~n2XUs=n zB8ABnkC#f7ZSMQ<7Cje6#aHblEJHn{^b4JC9`{{ZMD~VYBFS=E1x)AN8BtpeQ3As{ zLiMi#46G`j(vie;?=z-Hz$-V&$1SP;$1Y3q`lEght%1$WQC1&#V3gz8cR z@3#&W6mt~)H+N$iBj!H7Z`WjKqe>YeN$j3`W03oOJK{RsCNwP|-hw>%zju2!PsBp8 z&~nSC7u~Ll)X;FSgVhl%bp~;QzPH~>rgSMG9g{=tdJ*elpm<_n6xPnF6yY>#7vbU! z--GEF&!C;UPdUDHmXn_MG8B9vy(YI543!_A_SisxOvpaK1phvd0(%U&zOoSWXG z@nDPJ8N#V1oRnc!PHZ5L>mEdj+y@-2za@(OUXvFe?R4~AX6KJ)KK$T_e1mML9t1qT z%yDkgz0UUWCOee6ygkmOs)G?@f1#$5f z;&rNq4L!pk`u@(R8EeL5my;1(mhIouQv`Tb0mMKdqIV-~78cC>m=aX~chF~@*Qn@_ zbK~JN&R;K@X`_e;57T>m9@XHPRjoBk*rvDu^dU0cE3aG6r;LbtSL47VN`chEwH`Y?F-bw*a>-ZprcEQQ zS?B0daP+W>%Vafq-2ZR*H2@$z_R5_I=RBNQ4M?C=`0Z}|=6`1oS+(9p7-cTM()r=B z^hr>JRXZq}CeNq6WcQN5^GmkoFyM1J)i9N|l*}E%_5v`#BhTCrmN^RbjNh zvq|N=!Si2!ps)Zd%C!WR>ipL~ws)8mQyjP$$t()luLea0?e5KyBS24g;HSozfpspi zMEnZ;-W#EGkRlzfi{B=zZ(Xq3!ecO zwzZe=+_(B2iUXEneCGu*ty*i;OnAP*kf@8ucS7yfDm>FwjMo`=_7#UkLkG71G=`ha z?MMtfhGQ&>gQ86u5w7aEIswgTwj22EH{zlB@c|aNKReH*;0ri%RWWKJQ#U|5pd9cyzFBH4GNUBobGt$v=t~MTPnWe)Yci(_!+E1$FVHTR^$u`-AS#0z-;k_C z(*f&uj?e9=!qgmV^4Be;-#f{b)#Fh8EpFB{qqo6kKvcV|+&6kY|1g&$^m(cjtGZ!G zh~LrRz6nr&>v?;|9b0z7 z3KF#`W{w^cyydOhZqQnWPlu$&jdHmC3Eh!y9zYy@toJbw!9;WaRdC?63ajmY z@Q=v$>z&z# z^?ql4{qX@8Gf2ZimyGYs{`0W0Sw#BAQ^*Ce2;rwT(5>OO+VM1F%<(Kb+rbgojv#B7 zB|#Wytx3bmepzL|1eV9GlG!z_^1y2*h~rAuct%D8L;H|HU2J!Fm?wPqDet|k?$}hZ zd!+h-m(BN(a`-w`vhZmJ8@kUT`HO`M6%-vDD}vgw)TB3gJ61ZL;PT-Z%=|F6}%oQl;KcWWVCr zYT%xyqG!xQJjSFTScxxnHYNNlqs|@lS;SR!JbY1V6?plt2$P^>mK7SkS2*0>Pej|x zcSN@1HJlXZ8oywa>S-VfMw3t@7bJPu?;fR_R?h$^&LttoI=pDup{ z-@ZK*(Uov(Z%!&cFCUQ^ctEZbXm--$yy>2Ev$~2(!e4vrL^xPW)zDkr1_u%3MUO(s zFtPhdB!OyiG?nqhKwRfqRz9@2(#bRGt+t`W-ERHn4}Ids8y{oJn6#c&wGt@>AtM%v zMnlP;2z_AtnGp#hU4k1{6lyj0Kr>4KXWb<>u3s zan1N;wt$AMG>W)nQjh`E}IV&zefg(YoMyRcQ74v z_~3Ev#_WvO-)Q7?9=94rp62uB8J}j6v6h|Rhs`jkq@-Y^9cE%#JGE-P?YZMvXljyO zIB#%oioC#>l*+}$M^nC0boKtA`>{!B0Nr%V^6r7s^OwbQyg#VPCKkpi`lJApc^-Y< zlKG2J(-=LvAO?5gY)|YQ{QbKSEzqVs(S$y@zmqGto;j7d?q$F%Mk45^^R^!`5z99Q zqsAQ-{rUrI&{g5+I-K@_EtoSw|DU0qX>Q}e(y=FXqx+?s(nB-NKw=!n>@VrEh7ag9 zQtz-|S$WnxSG&(y3MOE5!?4rYSg;H(KvxF^UH73NvtumfP*Q$+7YBVPUYd{?#W3P@ z`;leClfbVoSDo~B{+Z>%?8v>CFR)f1&Wkd2SU(k7HN2WAbadKqku@38Zt49HJR~Y- z<(FCaD(}fmdQ!HK4}8m?zLF%f?vqHRD7~Ck&t?=b6sYy!FaCxUODrlIF^C0y_hac} zHp&Ui1J^??fxRh@?x7JT-Ota{{s>ZsSs2qe%~3!(qU`C_yMYn_k7ldP-b4e);CF>O zg$lwIckbW{U$xU3{}@Vgche6w^YUkRO8+t*C6UY%hjJ0q%u|I@Q^1r)PVwOY=2;!7*@^(=bgm#sS4GmZ6F`N#kfKhx2miWG`jfb6^Np(Sde z>E1}|!B2hDi?&>v2@RiN*hS@YE7a?C!O0H`Li4|=9OOcW|Av6fQB`vXIl*Y~dg!el z)N+>#uUNZb69Ssl{EYLu!f*)%U z=It(CeM&Nemp>E;;^wkfc?a|P7}5)P5d~;)!buFmsk%#{P&4zeF&@%$xbm8cMF%HDIkJIfjE{OdvRcY)}~N~ zy#+mA)zA`zyr*V_D*0G?;QN*hp83YLf%f{(-&{TattoUaw>$H|DMrS`)g>ke{#Ak3hw)2@Ol65|k zYAyfq+0DXq!Ks;RDKpqkO*<@-KA!SmN-CZRRXYv|PUf{MvDPnkm@skvX1X%o@?|9P zi?g4c$tsVY5s{twdZ&k@6_zd!ljeCx!jZGGCHjDQa{18u(NXVl3gm>1%=)-TuQ)VP)sp7We!-MnGv2cD8S zOfF46N&c`Rz?0Q+^kYITHjhtQY!f?^qIiDKUo7}C=&A_Aa$l(nhU$Gm5bq^Rq= zQDXN!NYwI&E)4lyr=4^QEb&8TY$rsJ>-r_d9>5;0L_C|?5_0tSI;6xf3G#>5nt-YW)YVb%Rh9|2D2AoHytZGY9H9BSzfL=SUrY&8W?t zlxE6cFd;FCv-A&_MNY&rT5Y;nQT+M1R(|+Y5ChU2_>QCjNTZtgsdL{WIg`NS*EhT&uoUQ~4w~ zv&CY9O@^8YQ{D6CZ+P9yz9AL1X`HuE_&BWV(P+Ne{?i#VR$ROB7ee&IAZvcZRtdlJ zg38u{&PEOR;GXJvMq~+iV_DjK!BypBW`r(f4Nl&Jq(NHMc|NzFz@NKu8nKWzuZalB z9(7W__LK9s#G43%*5Y2D0G*L2<;ySspU&PgD2}-M5=KK3AOsH%gL@zl+--1|5L|)< zg1ZC>?(RCcyK9i(?he7-VPIf8&-?uAt=ifTTl;Zfy8F)0uAFmECvDYRRb9%BC}YNJ zd<6zpO6Q=yhqCmy1KIdymkXL9^Tmhf{Ee7%02^t_aRHuU;}5(t~SNH?$DV=0@@`(2yfV(cZ>Le^rPIPkf_r^54F z8`tBkx6PhI!DBrNQ=jwpjhCv~9Q(<*A&HxUZD&O9?bc_7$Z#3%cgH>w9N8WA?eP{h zNG0QD`C4QG;PwqpTZioVtkv{&t~t4JH*HC=niVi&i_;k<_HiSK_dr{ z8U>mz%dBtrzTEvdsYOYIwe!vOE&cH6*!CW<*J>E5csJ+$coaBO(M{j<=;*0%yIcMgFJ&5FKRN5J?wIo);9XevuNP>lIWg_ba&sDZe0{Jc%9yl#LmcFllVRK`RJUh9 zvfTu$RW6GnfsB!!mk7LHW7I=N0Cf)%)9bfkaMD_`di&4(@d~EC+ufSzUYDE`c3FAu z*!n4x#@5PW$;M=|@bo261i)a@1l^-AmoKpMgT|{?8_uY7pR_vPot4)gBYW8B<*>vBO+|uMaWIqpue&;x3VX&sF6!!gIt`q63*+smO#1TdC%5VKt;PF)( z%8wwAjvs=S!P-!z$a#PXi+B(RN58X$toghc6JW8)a8sA$kc$S6rx#+!rOV4Axof2v zGkDZ^QiRL>hYMv35=5(%VPp`#fQmAVLXG9qxpALr{!WcYKB|)~w|^iY@DhYVgbDpV zytd_Fu97Xz|v$ zjEp1hu(<3RWweWi5)pVQ0}!U`P8tm>Ak#sv&7s*FjCqu&T4&Az011d#RHGoTohu6$ z%Dl!zcni8v-0Sg?rLae0+$pxm<#noE3024_#=O>AFloj{D9Nc&b9aKZHHL*xmmR`= z)0-)B<;yatx=rMrfys5>pPwAAU)D?iu-48B{lObydy3T==azm+B)0OhD|Zs?{E)2Q zL$uJy$Ra%`!_WHY)Jp3g>nhbo5-2z}@c|Kun#YI3EpyS)Cu z=1tRZD)h@w{{^PWO0P#5^5YegRz2=f16lte^JBI1GR4T38d9KyKWiM9|0f^@`S$4tPZ$Y9T0C>~;fCdR-*ch8r;IUS-MbuA6JZED5 zFqIuEBGpkzIJL=GBH1$!DrK#Y;Q6EYm!LPF@QUy8Sz!)1v6r{G zP6KQ3K39RJT0RqzFMJJ7S|T!L(r`4giG+(ad%m4M3RH5*#A9QpBIyNAp1=^EuWN?=fA3l0wS#p}^uUjfg$-Y*| zY{n6I6+UGvs66GE%;tl;-Ff?~W^m9OvT<)7<_>r=6x?I*m3ojY_?sQvqmE#d;g1 zDcWRPi80B)Gw0t1bN%&7C6w{uDJ%=^ic;KuQYoX0Nv*E!)Yv=T!1P_hMtY~`CtwRb zxl=Gu;#ID(R5)_+I+6vnAL$;=98*X8`Lj*J`#Tk&Gmb zYQDnD5gV{U_*3NmP8EK{SJ3AH@sP`$@cq&!vKFsBJ?^k8s*eOiwVtPW%kA#4M8Bn5 z!BU_{LHRvF^s7oB{Iu3c)AD&-hNifU_gOVq1!pxXNjs(MbVo7e@Qb8X+FBfQyS^J# z`8IdH_M7$%!@PNLj&b3UpT+>GKSKAlJUR7DQ&FAMBg<%n_t#pMp~O>vA256;Y z+5Zf+1J+Gi0oJifMNhf8OPi0Kr$0;wj`HQ+Wmh9;rBTYq%#pQ5=?Ldk4(C)gP3Z=W z|K?K1(+$`%nx3a-G=2$TM3|BTr?Ca`Y8Jj`<4mtmE+qJT%KtXYbrA9Jg(h0tz+|k} z8%Fa%$c{mya`h*2SfbI~@q_tfE^}KuHqx8HhpQqs?5c08G`$gNA1<(|`U2&@ve{j7 z=<1ZHHc~{A3jKCF=XmpDP5hFJ|5nq@yHx*2~7eaZ!9mx z>&sapZiiC3(mmX681nT=zqmrtRT~+xOK5)PpIr$-1A$|Iu~&?`G2Bwp?mq zWPjN6XzxyHBUCrzYkC4K)FE<9!a^pp*h|AAuwCCOzbZuFVRVXtyH6P z^K%C7ZaM})hM{J>UAoz@&pcBbz1vJYr?pAAxrGWDm>nG!2-cLI#Sm##X{{_}{3<{H zBE9i{O))fxQxmv6+TXqML$dNh((3dbLpP7}D@EkOw$)S zhq}Vh&qgT$v^!ef=8p&@X8+ExIQWBsVhr@D^XUJs74J5gRCW~4t^AqF(!AFdQBnHs^E3O~S-(BWS(@qHicWnCqBZ~j9Hs}#m z{zLVM2Tc0c0L1Vf9QRGq50diV?@8X0-$V{~x*n8vDsR(g{d2zI;XOc;P5&kH+xfo| zG5li6u6>-5|JsJ=Ky(XfS!_x%hzQ#CV$W5^X3e{bGLRB?gl2?`9qM=U<)_+V z%11kfd$Um@6aDwiuD?rSs07Jh-#ExL)^ zK^%|q*lhp%<-P6Fu=TSTMEmwb-uQEXEbB|p&e=;(6F{ptm>RHc3@ZM^sjiU5=+vh1 z@uu!sFzz{r-)_7c)?N^O{h54cJ$P$9)jsa%W76ufMGlq??sMiA-QRhkL`dGPi6Qtn!!Zb9 zXPYvp4U|1FUh`UgJ{29P@WSL0c`NSnu03;;evVRI+h;_t3SrueRV0_n0^u~ypi(RU z^DeWVKh@xLkoyau($+3W8%+aF#^Q0n^=pM=>}?5xhg4Gska?Wa9(z2Y#4>v!?KNY( z_Zssu(R%p6>hr>ydhAh5;R6Io;0a$WnsJ|d#G}UJ?mu?ZRd&mQ{EwS1;i(_Rbo12B z5Q2S7<7-?pzdDol9HR66vzUJTWTsq*wDSq~AGySwKCR39`U(Gg^bxf}qC%8m#%uM= z;TN~^4TAzFOcyH>E9<@Sl>ux1c{`!L&Z>Vkbbi-o>`c!W)*0&wnMOPPUb^ZD0PW>} zxln`*Mhk4P))Nx^N+N#D%Ui2^DZg(18ECw< z61imAljvjfsKn0}Soc}7`vd+jD=m?skF6qL0y2EI@g?@Q70dGUivtgUZnL>2XhDG8Q)mOkR59uKOc%FOBz8XhKQ&cXp9U z9tWcFi(x&u;%QU$B;E5;_CJ}euZ@=Ld5(IwxonoB9%SbX5`=vgOGbf~si_7M59thV z$;0bK;1KE2poa6l;Lbe)FWh>Z~=$54IIhNUd?{4@?Wx|}UE z5VqVA9|*=4xZlS}cZH%zX1#nNp@)~vF2I+9o+tU_&0ml?ZqhT6@6@mIV;SA~VlT8D zRm~0fy?VI|Nh0=o6)B!y;`CmZT(U~9^g3QC%-t@_8Nn+;?I-6mfZ(@y1N ztRaA2^xL#}IG+f^4tA=_^rab7TGeERo$HL7?x#)|Pnd>9%0GrX52|JlpG^&1QYy0< z#frz%+xnwM;pxN-+r7yxS|fb%WDw3H>!W6&4eYvBVEDeaG8wlZy{G)lOM$$; z*PZsg)_vIY5Jd%}aRD)y7Cn)|*qI8q38=VYzlKyJ$EIkq(L(WA+MZBPqS{1{epg=a z;c~qoD=sS9vb0>VuDm>~zt!mh(9j*R+($~B0r}KlU}a;JVn#A1iJ(TWaZJY}PA$VE zbsB%!c`}2t^nvJPdf#ZEzz5>HCG9IXL7Aan5)#sDw7Yuedb@r0CuNTjV2pfNABI$! zKfJmRYaP*ViZ4J=$msOtzVK4c23xGOy%4vfgp0HLnr-Ip*y?Qv?zAGiljv>V{!TJy zd6$+^?GWYb3O(eSDO*NUhEyQA6rRFxGwG-AyY)|ZHm|ZKI~>T`@ex(>Fz5+sch@w_ zR!g=AwP$v?jeWkQmbx9WY&L#7=kbfL5&hGIfXq9M!;Y9Q6NemvRp>Wx4&;j+8}RHE z?%|A;&r|8F}%wzSSQFq=!HXte^Qwa}Ua7n6M z^gA^oUSR#l6ZBqglgB@a+w5-|$Au)iVj!u5bJ~-H?N?8HHV>m-BzveEe&zRj=x+@O zJ%^oDJo#nPdiPSmA5ZJQ_+Kt({-!2}U=V?wzFo^l$#Rhy0R*(eUg9IEeXWPoxsz7o zqf<(5?_GvS0O^IJ0Uvx^M^f=i&M>*_j!XSoKaN>DU3V~{ir@HDvok&MTr(3gmNZa3 z%{DHbv{<6+GHSKv1Eo~R?2L@tt6)?c*X_uw;E2;F{f&{pFcVZSes_el|FtWqIr#qK-9p*78C`qkm7ZIM457n`?+j-{-7T@6Gov zt0~*CHla3zL19djm`v;z8nGNqSys8pW~La}!=G5C)9G|Z1ZdDPHM+cD5{h1V^2(o1 ztGi>G?P8l%mb4x({z%^CJm6kjT&V6~(G$Uk9CDcZ5;!DoETk}ME4;Fs2{2niTjZ20 zd|c_+qXS$R37kqLw=^y!uU}phd`reIxlX)cgx#kU%44)fmQfC%^T6Wv5yzA3OlxF% z$|%ZbC4lJURJLs+X9h3J)o!t^>@9EnaS?x`9(b!$zIWKZEqnh1Q3avmdmka;XT`L7 zEquRy;WunO`@TP;Y@*NH?Q`f1V>u8~_kpAVg+;G3ij&AC@C`(c($+9k!68kUF^pSL zk2bSuEYmCK;47kIJ|jBHa|Zhk%ie`va>WKu`SRUIV7jDC%GbVHa16lC%K!bA zk3&>&UJuJY6VM4p@eD6A0ATe-k2i#c6#9@~U@ez;Dg6v2fqd57|D}P|u-};HuT4ZI->X42Rg?u*1HisD#$C zZn~Tfk*s)KzD0@38jye|);+9Jj>ECnLEB10Xq$Tl&pym+dz~H#6M&-4vcK*MQQbQ< z!ocz!&AGx~Z<|_-QyLPFvoZD{Dnj$9L=p| zr^8>qzxyqcVi^4tOpYx(RYvX=F^_gc1-eEBfiJ~tB3)nvv@ zb^NAt&>;G40H&PVjMA1q{!+gFYU|}`@xs9t6#qr=s)|4Hyzcf3xhdV)3g+s^Vf&|c zAMXN>or_3QBo`Q1+31L^jBB_qsEFETTafg($KKv}O%{RI7wDESL)X<|9o*UzsR|!C zyZ#XFlWW*_mf4}Cz!GZ3%})Jx(>ydXTo z-Db}M$T~v!)eV4(WNG@Ct}CbaUZL7qSq7gKJbT*=fEfAyUke>CLIAR%NFuKoPzdjWpfix z4qp9|k}r@BaJ0&noN?iwcXzS!n;JO+D?^Q_O2_urF&oRI;7QwTK%b#-Aki9~t8>fN z^f9?=0Z3HBkm>tehK-P5jJa&NE#zPPOwNZl3jfuP&sn2*eY7{*fCL3)1|NOuJ*4u0 zN;c@_#~FWDZcD>+xsix_4&*}pSf(Vq}vt1B$RlEk!8EU>)u&ApP>}~|NVDnnu~btnRD|PPp!@tJ)l&I z`W{)Tdy;x1qy09(C^UE`xltJs|Cz7lRTozk-pI&z1MM+U!!HoJ!X=YJ7D;_-)f1?? zpAyr1;8_i!GqazNNY`?h$}V@x!>D$5ozE-PFfCs}Q%%mGDKhYZ} zY_D!u_#D*CeWbVQyTi;MSeZ+7n}i8E%ijkh4i?((Emj7H+N6||#(ruaS> z<5^F|YL+pqpV`*dcDP#be+GnCLPpk$!)Ef$u+VCx3>i*EzKhek8J<3Rg`TF{YsA%gAf#1nvoH8}j z+Z&?BUyb?+$2IC$5urA|_cIPfgnCJ2M;zw)VZuR?nc+y(2N8VRF`irOucFf9%TL@e z>7{3;r^$vBD@EP=>C0f>1-^|xAQ7n{HCxT^EmS+O=H}+|h|ZFVdF7(wvGf51(Rgmy zM1wVLhNE<@^KFGpjmu=dtYV$bD*WbVy+eeJ1Vpr2LfmrX2!~!Ii*i;>7H^MAB@~Pj zksPe5dCHhlupvA}Pb}ntsOy2TRhLBtmi7C-oD?jGDA_&KFE0T}(t7fOGYPc_q(7REGy(YvrQWv?}>ItCLprjfjDbdP^8q2e@DtMDYozXJoY86hP z-pxRemg8*V#Sc6D%JF@H>8lANU@RxFpVsQYZ?KG{aphHbpsPIcV4-+>!i<(XDTDk& zZs$V=plRWa;`-3*HxZ&kgRB!Qy8`Nk81w4o?z$uTE$=P{#)Cl7fB=) z6~$*~JdFw{4xh`3n5QV{9hvlBaDwFDC>m1#yga@nF3wp;l;c&G_rscHn}SM9Ha0e4 zR$MlDcH4L@9GM_(cPh93QipJoyBr4nxgrvfN{$u?#JMXU5>NkQV9$KEgDc)CNeT|x8+r!JOw)M5%OV6#&kDipFPnE zpQw~#EyTr1_}!rB7+P)~C>vLZ7w4C6H@pD-6XNy;^Tjdq4H)OPg{4s&TKv=)qU2yHdHQD4Q6)9XesypVDf68FpSY6t6;DKBjYI}#K;fE%5 zm||tV*nu*y+pJA>OPeWPJEyy`iy52=ldK95nDLls5Ml+*4$X{Lg4WK2J^A5h}15!Qrocp@?NNHN4TV8`J3flo5ps@xP24!JCU=bfV_Rt_Bhvf{Rc zsAcxbTtbxZBKR2a49(tV2wPP3+j*8A# zv>Tf4L?7YM{X0!3@r&ylTYk15c30XPb2r_Gfc5jh^%ER)C+IwM=(PJhUUO9PUr`j* z&MW?yqV4(ZYG9CAeH+KDOwxZnFYR=YG#&-kN5-NYOd>xxJfqA}!G}A^8%PH!Gyhvt zxvVOvs2-<#m*{2X;)kptW~7)yp8}}A2y}TrJ#ZO)(BdU5lKFc~2a7mx9*OHiID!o< zE#b4ev_Vs%SO@FBg4N!?jX4J8bBw5nLp4HY2yVwZ&QU`H@~Ll>wQ+d%Ga(8r-iOdq zbX214JMz~Oc>ltKJm6dqT;(sVk`tK0*PA)NEQQyf{mdstHoN9>wS*l?|8GBP#8}z} zX2h}T@H61^q^~meES)}#Ya{0@kOTYR1h3dRTDH~FY_g}S{C|9YnA-b*`S9SG517T| zuOCFkEyDrp0z4@|oRZ=UuSGk6z~KKTdI3$jVEiU~_1bM`)iD6`pR1LC?1r-AvCvuU zmI(fNQdUu3(#e<~YSPO&&v|T|5_sMAL>b^IDs;s8#J?^LtpC575GvtMjGB&bUHYLF z8Vjq1{LXiuhl#vKs>%zI17{op{M#Ajm?Mtx-(tuTaRF(4*EB6oB#ZZ3ABre$`ZkzV z$vDf%zJu2uU~(K;j0%;d;Ylbi$;r77s{BuCYW;}5{Ak_5xD|cqYsT%>awU zF3UCu0?yBQB_Gjp>YhhzQK_e5`;F2|A!XrRL0CAw_?( zMdaqh=YEgK51wl4z(O&RQ;#jrjVaHRdvVdDSG%wui33aH)Rom{7Jk)ED z*KucNkiRcr76# zIOI-9XbYZ!@)NWK1Ym4-Q&O+d%F>TQ%PSGF_?hDb-0YdO8&9KKscMJhAIu50>%J!$ z^I%%wfu_=P?nv?QkUM`eu*M^WTyKgC#Eh{Phj0kppmcO19Dhd|8HqjA-1B9fP7oK; zVAsWXdgin(GW(qJ9ED{8CKZ<{4QNq&-6b`>w|!qM+vEv@kB!ReE~+NGs2Qi4v1G^< zbiC%)t~=-%79yIvVE23~?Goaaqos^xn1yxsY7q}}M*%G<8~1~yeU1eI>lxaDeNiR|_t?BvgN=Ii~s9Gyky|bHTxe}PeR3`1{HZ3{% zAXjNg(CXHc!)i@ZBE>ZPaD;}^35}%Fa9d-dGdY=*7}@eJPOW~==S%#sHN#b#{B?T6 zG-Z21OPyajn*$541RGsyXbFAS_75X@n=-`>i=GgGk&cgs*S zcp{V+1I91fE8K&Bfs)=IM9Mr^$8!iFd$*w<+vKZw;2Wqi%e!~B7l$hSfG_2DwD8sw zm$9}}#}aVlAX$f9(#~10`G=@}Gd!yBzu#>1p|qK{VZr{=NZ;{rpua!sLMM~hVA7oU zsdoIfeac};@)6vyq?VFd3ACI@#eQ-!rR!O)i5t5h^Q?HI`VFLz@Nl~)WJ^wgK4#;c z8o$1x>_S=+boe>G?AZ-{S-i5Ce^ybg%X2kytH52rSTJv`$I$_LTJ4#1p zynt2ubhB2aDyx-Si2*aZRbB5SxlO~Y+^9#nu)s^f--gG;d}3&|7jBuuX=t|RCmErg z?d^!IrL|BUZvL21%2nmKD1(Ij>%(j*hIB1}i8r}EFpy2xfBlgGmSv>y@IbNu`vG_M zXJ6viL&YrzTU)VNOU{km-H2NmZwd;-HhyO;T=c4|E%2=wpvF?10_0;+TXl{;!U$yc}V;i*#WAj z3kmnZ_dRSq z_~1ft7(84x8FxPJ^Fqe!aujr)dULVE)tN0D^<1PzjUcd2~k20A7+*{{tmIKD5vJ1At`4h`i6n&!GPJo&T}c zfBz<~xx(I*lX7**JZem&#@@c-XYC%Vo#ThB=m1iI$3rM}UP5~1YLov+oSE&>tyh^I z_CQU+cD<8D&ZW~4XRp7M;`w4r#GgO>zlJp{t{$RjNPagv;3t$-b_-==&1WUY2Ero- z+360bd^&&dbv+jPP-)_g{U(H-Nh4H2Rb~3(`Df0GkJUXv2)OorOveW(#u=Gb0;Q@? z!r>B+>$!7eTTO2XriHY;_KUc*!&hB{AF>JkS#WaW-#-NR1t>&5B28(71Q6f1yxz7#52}GTz~*j80ed zOz%4)7ioUzA?@*+4~`9~ug+bFgXV?X6B{vqY~Ybg)<&!TOYie<`W3xMm4x0jIuV~d z&}5=@i@|ZPh3n->Wsw@E-}?L!7JZ2Sls;BSLFd!j%1&TP6~l>n z5{EU4HimmnW*@z7S~##G3pQZS{trBZ(6Uo7Y!TMbZ@3fDgD!TpmI>Wzq|t1oxvP3ddH}npMDp&N|{y zc5w)6(DM~gIYx%G_7B)xoC?w;Xhs^H8cwv3f{i?G1+t?;x^ODE#_EOJ5v3f#J$ zxVqWQimki?OdwZ)r@+YEBBz!gIwB zX(2P2CJCu-q=pQYN`4t>fu za7T8e1539X2yYsv9_U7&wL_AICa>0Cpg+oa|AuFZnPO6j-2>8CbI?>(>iy-xysg8XAwf(N9*cIMda2O1 zBlORt2{i+60}d#D0UT>F@X7A-uSNKSfnTiQmzmP_4`ynR{o~_qdpQ+lqrGI(!(^;O zXlNI}r86`;8^WZm_kHCJWUmEdW|7FKNhRPLj!3ig-tOOT(i@~^Eq)R;p4s8U4Z6^cp>*Nd2R2v91O0@JR3?#@E z1?T#p7SQ;^^i;|#8<$=pA!(b#3nEMWlZY=~PMr$6kt`WMja!Hh&*g%E5$F56J>Jou z69!>ScZ;+DTxId68}vv5p@d%+T7kVH_LMQPa)G6eoj{T1l-7E^7+-_e;xu2VZWL9PFxZ?5BUpK<(@GyfA-#PFR(4RxV!YmM;$1nTFSEQ48&kVc z(WNpDbuG@ImPx(f!BSPEWIN%AnoIgv?J5tdm&}cgpefiIR*I!MQ<$c3^ z%W(0FF=VcYG~}zx>F=Q--(|6zaFRy~Kum35tKeA?%gjWLBP{jrmr6ZK0R2g#G{9O< z#-OPIbLO%}lrK9|I4?0##;DAT9DOEvz<|rx+t|!w^1!qp#f;g-IQ>dhM_PFx9FQ!anrtqQGMk{02q)4b?S7!%&BpQ+eGh9X4BpNTwU7rMhWS~jzF{{HZ?XaC{{`GbGP%Ikd z5$9fuRMg7{ps9G~DG1gKM0OIw(6=Z@ zFYE|JDix$UMg1}r1;}{xBBCjLKPXfp^BoSqfBP2Uc7?w=kmWO- zfBW*Z&D!gD@FtXeIH~Z@DMDaWwptrUZ0z($+lh~BQZ=Av%N&lhsmDRGKBJuyMV`?7 zXZ4cDfKYa#&zA2za6{IVRH(X@NlevnQqxl-0W}0$4q2!DdFkBBO3;cXu0>iyhB%}$ zG`P;dgy_3bjD{-auJuMtD0e3>I`Q$FV++KmM-1GMQ~1+f#=*!r@dC5G(o1#UA1ozx z>w=1y^djrS9b$t`jwc(5)bT@LV|7^Hbb-w$Vh6e&Qgmt4#?#kp+! z{{ef|SlTGmG+4>ySTr|56_LyRPE&vQB_JGd;_N!55RbFrvnGs$F^N5hJ=JMxBbkFH zoJ3RYo)wkkBz-&0V&l<*szi^^WtXZ+ohQT+Wzfvq!Gn&+7mS%>0kxmD3A&k zwS+rPacnpkvh+G>*Je&-{2<*CsNWa2W?Kv^$T;F9=Ziz5Uhc^vlSyE= zwjhF9B|&S5A+Z51fLocgT=fzhAP+iD%8Yz>erv`uenK!a=_5c1iPb&Ai9zY;DE3b5hYwy%r*# zoRn`Cn5mR0_A%E&5-OzE?e128SlAt1KIdR8@sG@NP??8Mu$rpF_46zJOZVeHLA#$J zM^rpinzc9{<_)R}$Q`jioRpTx$@`ggM(0}+?_I&*@)9g_Kn5pm`RIu~TA6c6r{ec2 zXzfS{p^?lp;)gdBk?TyzI7L^D-lo)9x0$tC0k+G(S9{hK!yBVQcEI`q^)W9JmzfTy z>l5_4;02CrdQ8(xD=fO3;@kaC$w!d*4yi1WmAeJO0@tuMxh|i=LYmI|biEb43OKw%mkjp)_BrTgdEK?z7`r^gsRADeyc`L2AGABK(TR*747~Pv!f#skgIZXWXo&2_s6ZBKO!gy?`tT>eNSczist@G%{t4>$4YXW<6os|T{6&!eOa$wN7hkESe zo1-bYvc^pZi~R4dYkQA1NuR|3)gkH(K7_;<2s2kB+ngbGXwW~xkTx34Qt1-Bv1AYx zTECh@<&*eKBj$u&GQ9O9WTNZnMo%x+48orbYC`GOw}Tb=d^11-q3r$)>hm`TQSoHy?hT&sdZ&Qviv=Pg zvjjch0r}Qlo;+U>3ML4kMF~hT!&c^tGw`7m6rfR2aqW*BAm%h!<8Azws?Pz`vMWEnI{jNfP zzjJiwBt*c;q^g#Ev^>fAv(g2qo>C*D;)y9tm^|1s-0bL66MW}ldaMvWTV3kM_3l=# zaymCk`QY7uh6bAQQ=aQVmKRIE*h{Zr5~bwXrJ7AYm6o|u!cXXd(A<`ct(}F$%DO+B?0P7c(l^=(4#r1{^`tdnOD`SHw3No)1PP;_~v%zZon;?*v zu9C^&(QfG2=DU6MVM)U@vzGZfv7#u(A$p25{OS0PCb4hI8eCzxiB1l})x&KOJkIdi+|gIn z{Zt=DJj3E)Ce$4Ht4B(lq3x}sHFpcr`B_rgiDB+HF>H zDHF@q{BD*pjCvQMoJ!rN?qpnY&sKe?1XtTIhJ}_R6YCn<*G3ccB@IL4d$qcMt-kYECY@4JV6I?nb$!*vOH7i~EPs7X6YA3dAr@Qo2w$U^kzmigdl6*IPH zdFIO^ww?a2p9uwM?v@c_1^(!K37J>W?l3~1^KN;!+HyCT51_>7fxsBEg1^gu?K3z$ z&Og5eUJP&@CJCZ`6ZwG;R{;8MTV23nvgNRzaN~Y4?feo|S-&X=%L*$ut!~GQS|-Kt zZ2GeYucdWzCr(% zL&!2KlAFP4CfH!TJ}L`8?S87;dfRizX-B8pAD%akT{vbRAoFOxxV3`!4Lj!T4>U}R z3%@-ZUiWGy3wg+2Y|U_SnF;TX?wTb9#!%L%6vQe)!E?qUOHLO_?=X2 z&^GqPpdWQrt;=S-uEWWfi_r7~g2IUoFEs7?(`?XW_xTN~hUnaN*i>vUkiop4&PREL zP8v9rAeJAccK?VOgD14_L18WrSrIQ`p08bheTpKGZvX0ruwhOjaY;};)V5T;GALeE z-&UXw&A|-!7pV--a1XO`4S#CgaR8omtLagYR|=SZ>H9(zk5p7eh2EFRJZU`Yf3?SL z0@`@Aprb?#nhRbY^?wO%baZl0F)Zizn;4xAF%$+)7;R7T? zwah$BAlx->(A1W+o;ZMDgaaU@A+!y5p@9`M&Pd3&+&}2lBj4D3@Gqh?Eg*%)vC5E9 zf5;&LeMn2LH{c}vY&E`@Q>5N`niLX0=T_(qh|HdDZx?@>s8V(a2ne8LVnT>fo=oQ8 z(Ku-hvfHM0_)-pDU1_^m7JBXqO|aq_Eu8ThlA4Z5O&m0(GsgkiIzJ_8|Gyn%&L3Ue;$!k&F*f4PNE4Ro(3ugnZU0wRM^KZ+rN5% zWfcD`OBdH(>+v-;GuDSUrXAN{|L&(^%H)!Zapo5ZNF?SI#7a}>eTxC%z)2*te#v4aD0|cO&n7bT6 zc=UD9iCWQN3ZEREcry4YFygCQ2b~1uli9eGicBh2A$@;jTEMK;b`5AsCHeBg5dtar zz0#urQrSEc6W8XS486WzBw~P_b}8@1AB26h_hdq~TUy!Sj&**=yzC@p(!QI%Mke1G zoGmlkeCDvYWDOQ_!9L-=6N$sim}ryN1Tra^$-J@dk;uC38e(PP%OSrQxxS@M zys*bun#%N)>IuYBPM8jB8t<05eYomInkm9e*yfM z`J@!XQ@H*2icceiA{SBTyN0=_^!??b(Q@=&^JA3xdpu!h&2q(Lb^qQxGFi*2m@pMN zGMxuR^DWLt5qg%LS^5$L_4v=;z+4ky72SG(CM`^*mg!_TYwi8&Gdwi1iVLFRZYS*u zWSR+1=0H(YaSn~wwxE~d{y|Qp90TB-s=&8&>}O^ z;NalOq{T(lR5sPKt$q(OzxH-4{3u1Xu%ND_!py7WL7d*UiLXU8cG_*vjQT4qSdH#= zWQA|Gseq^d5nXQRd#5H{M;A|2#%*WR9xDle4uE7WWU1U=HR^Z1RE-5N#>jEd{-Lv? n@c-yz?rCgGqsjfPjGWUHY3M0s^AN>u=!=+Upahx5x;*yKF_GxzpfxjLy~XIx5K z5;gn#j>EfH&L(nrIGOtr%HzKCL7!eKGANtLv6C6(@a-}fr*6+a{68j~8_;9_Hd`FK ztoxon9I+-QCPv|nQZ(!u6mDjd?l2~`Wo`6o|0=dl-orqa$Tej&OGP76@mktz>A9Fo zlPbJiuXeBYLzU3pJ)|* z%m$34@IxlRJ%PjyzR=tMYI}xEngWPmI%Eq528Jwr=KqbQc$fz)tS`PAd>fnBpZ_zF zFs~<>d>u)Dtz^7n9Kqien*d9XH|rFry6cqG-?j>w*Awy*kr#X?c)2ix9>1wCc=2(1 zx~EG@(tM>snL^r^Mp`(Fz{M=iqx~^XkQvjVS}`8{%M;Ma%O7NR_wdsVZAS9+qX?q; zNkXt<)d%{T{9x&k)vR|d`8<~9_bE|AwhUP}B{#Sh_U#I-X_?W^@Noq%+tR+JZ{uA2 zUTC?Sdum97_ph77!~GOTRe~p)k?5!Vw5PTBcPW#S;nQn_r&vnX zc1Ro1@$2+j!sK&@tqE$hJiqO!kr5p3kZj)}3`V?xVlrsVqowG=xX8#`XcyPi+j2%QHUHW3|Iw3^2z5^I1PYQt3^tLZrzxX*CjN z?ztUu>sBvaBt#jR7LbJ@Krj3`PETQfVK_P&wi<6SyO#;I0+&GAUu73(ROLiLn`uZl zcG=|Lv<$k!NqbWX2)L~(t!%rBTbsJ-qB4&_I(d=qM-32{S5|&@=<-=Yeo|Srpy&?u zlYiVTcCqEpm~S3758#f58HGI78ez5BV!~@qcVPTgq;B5y*AWSy%jQ*yhi&lnVT5p| zFm^s3gGCI%J%5U>X7->eW!ybUUx9Vc`4&k1*MWu#MP!)!@!NKE(kUzXKMSCaP8_L< z%`@X+ZFjPq)TqSX$DN1g$TvB+s7-pS=azfiUaa)lw$ytm-t^ABa}WXjg~}(j>UFYM z;?p}F0c-)&7__W%r%Q|@Aur;|L>kfFizk9F)=KeKT)33i>0K$%)jP}WYo(-myE^P2 z(0}vLNhX&4VQt4Zi+I|-*%IzC4I2okSYmIvr39P+6>ll8(k z)Pq4=G@cA!umE^pcv!;|ze)u#RXgvp0sIDEVMBNavChTR9jbY_0v>AAR_x6$S}eO8 zS%&56j`TfVNpWZ%v}pA0FX*IAu7iu~=q7muCSpAD*jJ;d4OQsOE2uG#=k9>|x5Fi5 zEVJE%)4~WxkXEy-@f4T9FLC}<*%8kYo@Vk*#@1og5N4QI*Th`8pa{w7NRaRlH=SY4 z!o*+XFH@qJAM)qRHU4S(Xx_B-4gWzO_x$(CcgTFn^AY&~oDmpYrbV_ch9H04+Xpg$ zW*K5cw`y5JtJ>w>@a*wZ-W_1yxWqi}fASp4(GWQvon%XApERJiS@HHohkJc>gnZfU z@G;iAA2oJHO;1h9@Gd85)UH-!S4_snL~$WJwoU%lU*jKF>Sh z^yXV-Uwk%eZqHR2f4dMmaQ*R`1UXCT-_`D`6qH2HZD%8+_ZfbTHq_suA2ysmMMz&=q6wGHqTo%jFyeI2_>;<4O*;Lu7QvZD zE$yLCq>!yBM9Wg5FRqP^!JvY?HHlXchGw)2X9YoYek)(37Z8WTH)29d|{< z<{7k9|3YPr&JJ|{>QhDEn5=y|KXUBfn< zI^aSsL1&SC1~O1_3@m5}NbQ8`W(}xbe!Glm)e@0q4yym_z{=QJHh~cME-Ht4kyQ3! zboO7B3i-#o+KFl3i5L8tP$xvWDJZtfyMb=I2&|x+a?&byuTT z-<80e;Zyr7uHuY!1xwZqE-r3g#3C}ZMrUW(H>?2WxR{{`GVvt+s8^x}91_0;5W{*0 zX4MahI4gs(TA$Y5yM^mSl$)pAcV%S6CGG`=@n*m-gNfaSKN-HeTat*hez>L=bOehg zP02=Uq+j;7kmgTA&@g8x3-m^4Z7!;P(ocOOp;sil-lpK5l?H(W+A*(w#enZxszaTE z>g)mH7?55~#nKI=LXLrh!-nU$FM4y~CC|~01>Q&&zD{!*{PKDrsd(*W)ksu(Zw@hl zm{Y3QTx1+ZbxuR}P*$AulRbv! z#AAk*>XDizqoAt8>RfA40Fn_pI9pm_RUm)4M_FoQ0+(sfD?}Kp%HXbHW6q@FkAM!Sq&9*ozs03IuMfn*en;|mC?`%) zeel(e4kcdu?HMJ+9U>tqQ>TaZpDasu!y*w%q^AsFqAR$T3A_q1Cn?SkbVJn)E0BNw zg0rH>@;o4j^!6gj}C|gP0Dc`_e z*Gt}PlQ{cw3ZdWavT;5Fi~@d z_}C0rROnd6ai6+Z~`2bki` zo(j)4R(JVqRB^~62{!UA-5o~iMPcJR9SDMEkKUKgBVCa)Q63ft9=>V*U>Nv(ftzkt zA7Foe$|lktco@}#8ad;3Ytn=G8di`suXW{jM}4Eg=}kN3qR3hZsK`?>lv{zSO|gig z#nI{SqgU9YZ4^+}Eq1Y;R-61%?2bgtTiVakI-{zRJsHdPi~SLd-1nKRKdMI10r@{-Q$A3$1hzP62x2Cdw{HOL_@*0-AeNG7L0@tzg<3AAjWP1Ywn{e{QLyusQ1k7w6ai*T|$dtD( ze_A*%J`V>MF2}-NU;%T@w8EgWsIYCN33~JA+=&M3a@-I3OkW(njHXN=lCklzm&W+$ ziD$cKG3(TB2lOf~e)p#lGDX*U{6`}MFSydSFDdHr&8=_2-EEwMduXg29Y`l zWDU*mM@I6M`kkSe+lcaXVa-_M581IOGp68oPwkB-2bOPaOy+nTtyLHy@Y@{(HQF>n zb^#1W!(x6K!1tR_nYe93eyP!g(oqp#pu?C zOZ*S3e~hDrWk5-?II)#<8*+ZZH!jCB)^Vj-#XU80_ML~_OEsH$4Z|_ZuuBc8+X98t zhB>d>*q~31ks3_?(?Supzm1z>c4-8>^J-;xtuu=?dtvj`GspZ{VSYok>Cx&l#`a@B zoe**m)flAD>k%wO0bl>mdkc&1bR0F{y77#T*;Mx-JbFzWG%0)ER3>`#&5u8pF6 zIr_dq+c&)ID_9eR;hLHy{iJ}|)U`24ey_*!i?S^rRF|wqf3h9UCme)R-!48YBkw|B zIx11)9_2mt`3+TPLV26>ZnBQ1hUmzd1V!@9WC54y}{;YlbrCd_=*q7OTFj;6Wk(hZKd7JGwKVB~yT#?1GGLtr`z0a!kq;64ckIw?}mk zYtncR?pehkI{BqX=D$wbt9}eFz4`7oo;|FEVgx0&6;y$iJ9;_GYlel)JhAu_KjdC+ zin_^a39d4(5~9De?CT=sI&&hjvm1-(;;SP}L)v47WqPrEY}?P4%iMh+#|J1Bz*;7T*{9cs~C&qI0#}R*Kowxze1%&cH?#MTOOdh;S;6& zZ~S?&Cpr>B=ypO5;4LXr_*Yp^g=S-}c=p{$PU0>@b2>buVJ)l}s6GH&eiASiXtm&? zBVf;Gu7|<{#mbv=$_&X?sO;iqqx=9t#mHN0S7vJLsccI-|1xG0%fu}V>Bue#5dLi{W{Ct zM%rMOcl;dymlek3Ji#u<~Bfmc|5Cdyh%B<~x*x`~GQSn`&%|Ji*l z!=S)_in4u{8lwUlN3dEFLUL7OYX0m|a?-q_&99WJivg%jU>}2zfnjyLIa>S1W4B*P z*EIBY25ot|xBsN-VQR4{bBM|Y7X2aQ)Fc(xwjb|so;bxku(BT0?^i_ql#y{75a#mrh(H*>k#6voYVO)FHaS@pib~#FCoqp=q+v5Wa*jq)bai4LPRx7V;XXnNIJQPT@ zjrk+%Q>4k=+bmrui?mkg|| zi|V4tk^Uq4^JxG1+LHB8~G=j0uM?9(msD>R&pL!i<4CvRF z+?ObpL9;HMZp%0w9PO^YxRipVq10`+sQX5uueFVY1kxmV?va%yu2#2mGDf}e`cXTg ztnJf&2IUzenaW!$JZ` z&_j%R+-M_Z%E(Dg1))AE^>$Gw7i;wF8L7w^9p5-ys9UwrzX+SQoK!uz$kzXQO)&z? zpjaoeSRF0u`cGCOG}*6SN*KM4@PyCf`yzl8gM2X4aa&YscPNS5RC^tzxul2ZGP!|v zDA1@iOKkGXJ^ZAXeJ;m6e?PXt+Ocjp(-nGogUTXrE8>Kx`-O(|O|_uhW#x7|1bl@e zJgZHnvTpFcYz0&c|`{Y4I(J)}*r@2L7U$U~R@`^pclnm?Bf zlz*KbI`il2GWoup$eR&b$yX6fDmzFau1k=%7){zos8)5H3nKR7jz%M|a~Sp@zCek> zpPZwagh`8?2R=IvFF~aT0;TQkPzFER=b-9nD({j09 z${1~bNfS(=W^=R5dvsP*J{Jl)^v-QFu0O%eHqRvmm`aiYW9wsMR>W$k034ai>hbGG-g2Up&Ei0=u^)Z`n zv9(dsi(JwPUNa90FLQ}%^}z|97385#OM~qr7+caJWmi}gLou1Z=~Ajq?BdJbGkLCo zRU@cQ9kDhv=i~g(W$ME}0uFCDdTo!lF<>qTJUv2_@lUsu#4_@lY>8-kqbdFr%sa5I z9<$o-y|Ea&Z1)wy^*C|Xp;#f|JuVcrGK(pOvq22k!|bJJRK6o6NuyXHDS29ynrQsE zd;FHzxMw4hhk~ZR)3%Kg=80AX7XO{8Yl0Ehnl{}{`5O!e{{NOm6_>0h*N__+TjQP< zN36%y#CX{Fks?SB#F7D++TV`-5=%tvQ64{PD4UR z5BCl3-eU#H7Wdj(tJ5RQyFxOEDQn~|?*z&=|D|V?9KO*=% z1I+n4-!Agx_P71c43jUb?Ngsc`x8{Wif6UZW|+&U<{b8i!pPGT5%ihhHpn za=`Dd2JY8PaiH~s+(nx!wCEa#&EEV-wWfm=D{t-aIqs$J@nN{Dd-$0ofc>|nkGYxJ zh@%28^U~(u)`_OXwQ`B$S5U~l^utEm?zGy=_R-$=flDV{X$*GBMZEKdF{zqF$wY8L z4So~9Sq__|4_A85XLkXsD^)ZuOn!|&0I2)usNmmz!5RfCnqtSrE(NE&EwgpgiQ|m9 zc!&qm(<((v+}x5Bk3r-d0DC7?bb61;O}n9G@ntZ~QdoQ(kvL!AYhLpbjy|vm%Q(i3 zX^DtHAmLkgFNENheYFLhXCO>Ew$)wCCeHC3fba@g3tk~BVxi`WFp^qB+Y!rN8!(S@ zCxZ#6R%1WoO9btxpu-*HbSqZ`-Tam|n5k@>nKNFcRG7Y&{S|*%!<*; zuSiOsYMuh7;(e6G7S9k~NpB&iWm7ADpt;ApG5eoR6EV!g+@OWM(=hyzMWpf2FOX9Q z_~eA>!rtm6IwFsRXFdr+esUI?Gbu~>*~Prq3c)8%(84SB zmcG&#JJuk0T=?r&3Y=5P=j(hx_3l~v4-l`4{~wM|{NJcbEB`X-O@)t5E>B5LPTt~w z1iKDNe9NS`ef#jjM@z;9`|`@--O%U7jtQ6%J(P^F0wWtsgu|a7wX)%sW$3e&-qx!h zw+5e2!o!h#frY8Ou}^U?XK%4vyyfd8hQqJ$1&j&0zo*N^zYwYlcY_oV()Wux8IrsO zI{V7#VvP$BR)>uxw!^=s4IVt4pIhSZEt8X@qSZ9X?IG0&iVn+w2}HiDbjzikSH-C= zTqvT8HE{r|=O*qvm9~8oRq4Bf2}n5&C<6Hg+|Mt5d^}~UYc9L*Ri{La2TT#r_kB~; zZ5u3*LdtB;&K2JG&aK)7;=S8a|kO@>i?api_Lu`z`Y5JY;aWr(*1V zYev#Vx(D~484(OC?`>b zxHBamcam@L&KJ);im9Ws0q%r=rY6SBH`tlqLa09xGsPlzUvG8@(Ezs)c_DHG+(f*v zFPI+%@^7dFLw+bzGI(r?|9vxcclJe|aL}I6_}icpM83rN=aj`53IFAval;D2Y*nA8 z#y$ZZ4TVP4A4Rj8yPg|)-eBPp4-o0z^XzOx%F=?Qy^f|ibv?9 zmvj=JE04M2^M0E<+IL(z+7z3pD(LEZMvg?ynAQ~#;`7B?ppzFuaYx0}4$0lu3WDj4 zZjR1M1mm-|LmsN;Che*4R$9bF7{!i_MXia{oaJx!MX+lQYl!7(9*sn0*Y3Ajd{Mqv z(aQEB%{4v*KYMo#@}$tI9R2Fo%tw0r;SvkMaz!ae#W9?Wmyki?k>8?|Ws6-=0Zwr8 zesC(mk(hYGbdV8$2Hak?uUG{Gs zem&r^HHZ!+BZ&Urz5v2yHa4q9jndqr*!~-V`Ye^>`y_4`x}YdB|9GZJbZJJhPNTh9 z+vu$dvJuVdaq`eVxEVEC4TDMimZid~xx@2Mr`rwPAxbdSQ?FZ-9ja=ZNwEVuXBZcs z(d(K99Km#2otZ6W%%28)77%+H=PFKJCJa~`hj?lJLQ-`oRMwvY zoHn-RISh_u(&Cz_TW*N~O*o=XWkmU(BA+itey6PPI;w7jE-hv&yMSk#6SwuufXU1GM3)GS|8{GKcxiZlcS+jujQpE` zAtEcBzuxQU%e~>xIkcNy0&(HnZ#j@IM~lE zu-eDblM6r}_dav|7ED2NQV~lRniNtsU2v)MHRWz+P!|^~ z(fZr>fy3M6qP;ONg28=u_m(XQ)6!kCd1MAq_p*}8H6g8MyjT{m+G>@O{~}?=@Osy6 z752eyB6}dXS5`CAvQ7uHG^OT%!E#3H;8}}b6zj{7N^$SRc9GrI-1qK~RB3U7n#0fS z6@+=jrTU!##6FDeE~f0TUj-Kz?%!T~X=Rc)Fgg4$vZ5Q3FhYB3jZXEYE?$ZNYQzBA1K*hT2UmT){+ zlloEjZ=p_~W7GA~tXM!Buh|@S9z1Q99MKz|E>xBq2fBzNVa@fqtrkXxbFStLsTyu% zn=9rKL^I0K0fMRMQp%;FK!02_jJNL`74p!gB*pr14+d6;C$(u5G=tK$X>5^dy5>!K zcA)6vB{v*_7BgD!6dfwnQR({>k2VDRE-#m2W*b^F^biEt7Gmt!83<$G-L+NGSw zzsa1I1ld0_RNJB7shlZf-rkljR?1yg#lMqqmSwDX6a+s5fx%h1KSz^lJ}TyJwvb=l zm{%q0Uj;26(TL1@|uURE;?KA`A71U`T<#hF8fR%=QzKFn{jf&UYR(Ks*CqV z@bsqOAAbsqu$)1w6mJsPG~ch;=KF_$BTJJw_bKa6{u&=%Yn(XkKfOC%IX7k zFG0e#9KXFF`i!=kSIua!J&!sNvuS-zyT!q&D3@W;tvm57_v$hk;HEc$tNT=JepnCV zh;(|h>xqsV5@!?s?z_@~UJQ%+Csx8sV|6@$aB1WUQ1VtOBDH#q+=rMR^Og-eKf*5> zFePjsM`vC+RwHyO3p4qcsc^}*;f%-pdEX$lZa*Z)vbG>Khv8(}mWYI9agD}}Run_O zaS8eWGMn36tGMK&E9GKYbOQnN997QOvwn}!fA`mU0v^4KIbHk zbsij~aM4xPlRwdw{$XQAX{pEvmzBR+)Ph2hZZ{cQyKY1t-+`RpV-m6C_F=3+E=eDD z`>G)xJ%u%U^Gz8qdL5NBh06#J*EEXd7eMOGa3B59{BZ-ls|B2k$CfMVbW?u5H#Mho zIP;a;9X&s1Q7-KNQC+frJic${g8=QM++v6hOySz{`IpU}>(j47g)G`v)>i+9`tKnY zyDcJ*_C@`GDmXDHWpn{$~u5(Efj96|#5CGO-l4R*)rK+lyS?ROGw#lCT- zWt;8eRgKaEmVQD1M9_Kk)r(Y+wd!4o4ZD3+%5>20E=b2+?UT9wa2V}LrxCROJ6K+& zu_4mu@w~Ufrsn$Ud$OB|#R!5b=$%vf_5@ZC1LU1vY}C9s7#x=IFxesdM&;LjoNc&4!?r1Z@}0Qt{a(Gkx<6c%x& zQCO);%NJZ4{`FG_b;dO1qZLQdL#ypVa9Jm9q|--S9qR?>uRFu@@8O!jeu>DfzX)s! znc>2uLp_bb_;jBd+OPs@P*BQ+; z;9s|$4OVPwP6=pJ4cWj$$+2sx=!heBODd}W?P-SsZ6&mB-@%M?SEc` zv}{!>L~)v+Vt-u@Z3;|L+gB?j1tvvX|NhZIKquXAds-ilQV3ABQ+Dy2ZgUh{hzjV1 z*wRK_QqHDUj5(^^5LVg}RM^F)mH7#j(dJ8jsbY~7aFV+5G%&f9Ah?KOhh?cV3fpN3 z=l5px$q;r=23~(A2i#OzfhlVGVC!*UQT3F_|ub;hrGdBV@zYBAM>8f>K zIvlk5-oVJ62a8N=6tK#i}E#S;dyFFTYkCAQeQ zul=7$Ol8W=?qth@LUOnAlg$l)_HpvhI{UqDRMf-byQ1|}U}Cx^Q{>}znfLlugC*bf zGBN7;bxR*g{hgEV#d92uLYukiNEl4mai0X}Oqt)V-DDoM^x(~BKht;o zJ&}jBRlpIE)39eoje~TlH-uqVrRHgsdImsaJfxy1O(>83-fFdBRwQ1Joe;5Kn`%j6 zT~L}YF_|_mwasZe1?g^M+wwrAVbbreoJ#i!5RB#Eaaaq$><3;^>?7$@KuV?L(z9fe zLorQ*+(w~oEXE7|+=?^mRl5(Te@xW*qV3T`{(wd_uKw|p&8$@sj=En{k9CAB-jZR4 zka4E;9yQRqZ%nCcI~hwGjja&?<>xZyeHK1S&x=Suq}}pd+E-{WakL+sCc0H=PHN%~O)L$GHMTrd5h*k)pg34y z0@?sAEny$knnQtBjaThAGs=l04`lcKYpN*Iht*Rp3+CL!9$k@9H^>&Id=755h;!3* zM_M6cTag$*P-k2pOZm=lGT!!}@;F(^WxCZ#3+Ub=FF;7>$7c72WMY{{QM)6mAf95Zg3LD{cmP^AH~g{J|m7B+-0u?TuX87nIHIChR;b(9Lc1mQI8wL{Wv7B$SOCmdN2 z(1_sYz=tbAQ?X~+o7U0E^J(xy9RT_8$@e~^-w#@3Sn2~`Jzo8a?JE4~ho?HVZbB(c zANv8aE12XpZjdtt;r?PRa$1NT!ytfgh%Ix7#o{#R9F6uT^1WsBW=rXkcfDPt`!NLV z6`LsFSNgl%CNX_f%ciI25xDs7n?nB)L$o)C{N7Hd8>NnI=wz9W;ZSItb&rX7&FyqYkk!y!fm z4&;HKU#ZETn>aql_YhrHS9+UMMY&V)kIj*d>ilS`XUjKVkG1chlOJI?JqR#s>jzF2#AV z5#`;n-TeRREcNHb0Q|9(u|b8}G?K5DQU3~!96lq0P5w`t8J$ThwtP>N8K1@ivtc5w z@hl6Ct`V}>Dhval)Ogfp{8t(3pm=@FCJLoTH^^ZNGPCFI7-9VL@ycD9sO*>Yb}Fi| z1OM)&y5qu$BbU~{0jPiNI80;DEf_F~dqkFD2Wi~?SygK9i<9W)w{{O_W zO}rcLq?uu$a35G?9M$-ikLEwVQ|+Z9D6PV$TY{W%Uv)!Jj|>H4y5 ziH}GtL%ace==B3WzB@4V0fx5ogE!(orWGM98Fb?~3HvNHuT8r|bbVj!uq0fklJX*1 zd?f0TI42Q^ywhcX-6XqUQ8PKVC^Z8^Q+eqnuBI}s9qA-IR9P~fp!T#*$~K3t@;6V~ zEoJ}ITJzZk0V&;Xu0;fQsRoU&EY4%st#&1<$YFjlpvYOg0eDj@+*!>q1W~=CKozG! zo+4N_%(64konrq*RbjvgaTG@S1^+7mSjQr@tKAZQ5gxSi3=)re4$EtM3M75GqiJQdZraz$yUom?$6DOwcXx2-n;@M;4j^3C; zr2F3wGMMn@dzpgm>tJ&B_N$QCT#1P-@-+Y>Q*7Q~xY|m{$|JR(eD}wSYJZLW`)=9X zyPhpoZEY=@_$0K+N-w#jcQ|huf0FJsMzicT+L0p1vPejlytFBm*}m29Yb;R9VcYm1 zO>p!N0$6p#G-qT<B`t17xAtmqHwYU`pJ% znP7^un`d_AiK^}ST!f|mp83MY)$iz#+ORiA_iS&rE!y$euv_c);QoCS%GBK|rp1@s z_=&w-xK4Q3?8*B5a$ddblduW9nr}6^!>vnyG%R?d_=kr&xheaqT2=b zkp0OZV2fQ#W5^0TQ__TMaPjZ%qk8TqP+Ci<;9XeTB{zX&VCWz56OSIA<+B(Am?Sip z@3n@W$c9sAH#y`i-Tj1##&A8i$;DQ(sx{({8}_{D9iMrIf;%pDV|Ml2KP1(j2nPs1 z{cdw?X_YPBeZ@WN54z8tiQ9#DZKri1+x<$gccWU3fjF8s^g5ZdL9qvDj!@F+X^UZ6w3W`ZRx@r%h-jKt6^!_O~$o-%DJ zEhc;p7xZka9{JY)4m%8y$T73(Uh%@KoSjxVi2f}6_@U!dEUYwzkNkQI9wNh!*}s=g zZ>H9UIu$P76k=%ebbLeRwZr%=<1|=KDIIB-S>!Rqm(lxIA3#fb3f%xltY4DMp1T*9F6pLb1{qW1oyLdwYz9sq1S^1=1Kz&Z=I}jS__c%C z;%s&<7{#jIK(KgCZ>cc94cfjL8t$Kr|Tz1{4zl@sic(*)%zAxa^7_^V7 ztmB?ujJzU6F#J>1dg8)uKqdxxCYV#H!<+0_%Vl(*)00`qTB>ZY{aLRDC*6gO{W9}m zM0fA!NS}qj3SYMfYo14OGhex|>vdIah?l?Qoo?SvpR?D)`i*o3KQCACs}MJ`Axxzp zthSSWbyz)AAWDbcGSUyYR<>G+?n3k8gDBox*kwCgP=|}cXnb}fn~XvJbg_1R(^k+i zkWds|`zok;CcUDp8?Rg#BGc%0X?L~|vH318bn3V>;&Ot05HRo<&E@$Q5BI?0yGI3& z`v=znA{M!Hdg(KZP_mD3UY`_>$fjFFhhW28OOs%RUccGhyNBMzmkvSud7Dc=Jc}m1dEoim(Ys+K|D>TsO=$+hkL&{ghI@7p%smT|FqLs@Wv=6NmR(?86?L z0QmH`Z&z=YMv3IXhugRNk_%3I1t(dGHTQe(0fC?bg{tf4NPl)g{f#NJ)rKf%uIKb$ zxl>Md&&FPVP7fjkDlA{@p^cSR#-FCTrx&A$eTGzQXDnTt#o}sR@4HU>|I{VLw^5w@ z=wsH%L@J!Mp$FJte^RyeAuCH`8A@g`maI0LBo^;6t~nVK7odfMqq#Vr#QWgp=v$Y+ zqDOz2_V}{JE)DJGv%qJ(&&-@oR&+C_8xX4^DPD=`NrX+2%Zq;hJEg7HtuZ{#T|PKz zydi(*KZua5LHe&PaqK&kjS>hx3=`|>vz*7k-9^lpC1KG(12lT%;3n?Asda|BXT=Y{ zyA_yR7dW0Oq1j;kk;CyxyEVw~H$0xfh2TZ-jyqyF_f6K{tPg+9ha!X7PlHY~Wgn=4 zAE`wgQJ3BD0y2EUPn@EgFOM3q4lnC0R<*m#M)%JFXUPvZR0aOI%Ddz}4VBhstEjpNpsqxZu|BOcB&n7e(PC~ZtVcN^Ms4B%nnsVyTsT1y6?|bQiW<2BJ8B@64 z-_bNi_j91bN#|~f+8)ne#&*_*X6+B^d{W@UxN^6}tCgw(RgOYuJ;fSr$iL-u#y}!E zR4h=XB~@tJ#vSw_a^Lgyj#%sp+3yrK;yDNKW2su?WijjL&DUFJe9-}s{|-<42wfMU zAT-r+G6hpqw-4#Qd|ltzRw%F#(rSA6<_&E6;2ax?MClyuMDF-n7fa1w9%Jm=J=w1> z2pvx~n_lo<+TVBLKt{VUFBkDz`v$>_Sc**%RC7OOQ8Kj3Akl#{Zm zD`Z6Mk}r@6*ymEWeV8ptWa5XzlbW#m+M4`i7xD6yS{x2zf?y6itf6N}#C`{R`#&{o z55JtwxIx>DB7D}s#mfYt=9%S8ikX6)p_`_FN;clp#~IG(AN)HkY6VIzt#DlJwpdfQ z5Z2f5mJy%mkK4sxEQf27Xd~FJfXH#^SH-+Da(gtD99E5;xczv5BOw3nV*QEgU0v8M zwo|3R4Pg4Fy|Ut@Y#G8*6+4--dMveyRW7wZoac7jd+>`qbFFDZzz}k0<-v~4DCl<1 z?6AXB=+C!`Z2JDS!xMMyOf1*kGh;giM37DcfR}?xwuAr^wS67&@Lg<+osO$8A#{** z6W?F|xgEgjM*BE7CSBcL#rFJ-nMnEI_G;9YBVzL3?Km-?CtrV`=Xlc{(dVN)k+DMU z8~MY0aP24m4GK=lX`|?kOa2VQRFhRR_MrCZ;T_w3Lw{hJ$Ieu!9f%IZ>K=*IpTJ7v z&=1$*l8{RU5*pwxkRVJ2*iA#>=a=5Pec9Y4_TAYxD=&bRjcP)6_ux(V^H`6>35q`1 zJ3g3+gyVvj0&pn_gBz(CC6rjs#p!2mpi>G%FKD`#Le&I?BtNlu=^a3?t?_rn;*F*0 z&Mt?3CM=r|;M~4&m0F}})JGdm)=1lop-!DOR7t`2w|sXoF4kKM5risRr5D462&5ZQ zmZ$w*Cs$rYSk3^tGx2S#)x^`;JMw{0y_{5nB)WoJ#OFh6rieL7;E16qRd&RqI*k!? z=N>gx5z+I=`a~aO`0Rg6R6ojg%W}!#qM*E6=0@jPk;6ZC3}R^jukEc^!j>p?;8!ub zpHvEC+lq`Rvq;M3*6`$3e!5<)aBbKCMyu*~1nlPcmW9go4~4CW)UPzEjZj-!?Za>} z#SXPUd{5UwM+ho;^%(&xPeFrK%ZfLt^s*!^FaPc+$$$>Aoq_FHU8ZEe?;K!s9~;c1 z@`PNwQA$W>P)!-|jAxW<4P+Z;l*D>>*E|E3#K@1}TFu)cVfor^fipa&EZEw1Xq*<0 zPC`<3^BP)r0Ei^+#P+A@8B6ja)0KdNtI|6g42M>wpo%vwq+Ipaj}~t-F+>U9eb3@% zE)`b;4`<-YCn__vtK%*ri*W1CL~!S;f7rRq5o8btyhikyMke-c`l(Hf`Y5Q0fJVWU z)v46*5M-y@lH!YXk@>J@Gg`&=ojgxy{6}%=yZNteo47o$uf6a zY#a>O4(Cn}XlntDo(58H+NVOPGSavH7#5{wll(Z8Lh4Hq$WvBMf>L}}C%iJ0X|{u} z0$jI}_GI}cuiXN+1?7A#DJfmh`2Iw%Tylw09;Hjheswb754hczjdwWZjZcsHY11jNbHTHn5T&8~_8vHMk2 z*ezovoJQh$1Sb%zgkPou!1V@UUA);tmk@u3e03YFMin6r$d*sHAfOiHV(aA#^!|-ezMBTaTauZqiJT?FEf8p2IKG z1%l9$ZG+(wXCTuazTAc|_i`$Les9=114tgKRpbwdVDeM@I^kMa&puJAXu6+ARaPB5x_p0<0YE3-Uxb*$D zX}!Vy(R&SBY*Wt9+t?P?Q4a6`Cdad(jIsOL6>Gol0{e|4Vkizj^8DK<^}f5fb8}(5 zS@}2I?hiN-1`lwS+}QG+hs}!Q31O+Qj|By6=}qps$$&Sw=fM@E;Fe9A00^e z30Z*pv2--W{s4(GV{InNd*cGn+aQt3n?-5y3C~+q8huXcRjtY`*GShHxQhdV~lv5006WXM#v{Eo6G-;0P?n7aW9>!$u zcqQMc1&$D)5dwcVm3h?%D9(McSkS41sl!Yl7#6j3Y#%Ch)J3QS$xSSlTboAn_j<{H ztYtD?8a`b>$V!>mkp&LJ1il|lnySJ~_CA6aic|19Mm;br61s@<_fIgKS`Bsj#xTWX zmDZXgVWk@BsaJ}Be*mm$JX*=pF?h79^cP!2MGd_6jcfY>^ePnC({?0r1MIf>IFR~S zh=vBja&#ieI`Qf_pt+p`wnG1T+Y-Z-+{meHe9X51~=8 zoORST3OE1l^s2tC5S#onkyFkv2C3veB1s&=b^4z6X&Kcp-T!ygY{6%-5y@dRkgGji zctk8thGz8~WN%L`FOBI;g6nzcQdZOX0-YzSPd4c*)frC&;Uv^iubk=)yvn1L0*Ml5 z`Ah;4p1pthc}E7lznL=RXI9aN@_m^SR4J?}2^5`YSb`-+O!Y>-YVmR|r@6CPBlAg{ zadI04hoS)0<=QBMS8ZYl{HHv}GT*rp?A!hzh2>7?2e_s`r^qEa`NaCE!mT%it!lldc?OZL*UJw!f>MQl1MOz`#YPa5%n6ET^h6wvszqTolYf8X zZa5uiS(bNNj$TPfdH*cUamQoJpUfV*2Ej~PJ#Z;db9-Fu_V1q%U?wX|odcB)*9L)q zZZDaWl`EiQSC>L(8qYEeSDiKC9Sk2V(i86fTDq*jUkZXx{lnUhoBoZvn4O}ZO8mu~ zLRv9M&Dc*=uPk%Nv3UNc{rra5S&)=Zpp)U5)4a(K(c+6DaIT8f_Tb;2bxa^-@75gW z{?=a5zVv>0Jzvisuf|~9i^@GC@|Vj2 z9d^3TBx+J3stxnSN3>DmOj*WmlRWSHLFqECp=9OWHWD2D|1J@`}i=4#4%!RjVKCVM8t z0cE0q9_V6g!XCfhZ+WA=*JHoSs#5|NGVc8van7|e;=nmGimEp%nby(!FB$Ex$I}U+ zOcGEP&h7E_w^X~ijKd8I0-A7g>rGA4bdW6n+vHrx&Dom;D-ILviADw_rnt3^`3Z zPN|&TkT8`)h-K(dk3YJc_e}5izCL{9j&|I3CLSoJ0I`c4{&3Zn+e#mSD?pc~H%K$b9|$cZ$z8{xn`s8NFo3O43+Ajy}Ft0LXs|XJ;)RqfX;CMV|g*eHR4r z8%&9yBJcnEC3YT%K5o-V@X+P_Y2Gfa6iul+tpf;AS#4*37$>n(udh_<#}+%;Hm z2n2U`2@oK7g1fuByF-AG;F@5AySuv&?(Xh>oAaIjzg4&DyHrtAH89<~_iS0c-e|76>^(%;GjWL54UOh2vNB=k(ntr$|z<+#9g2n35 zS0(c|G!33HwR~E!0VR`uC?cW68sf0S&8$&tVpK#l4u8<&Sa%YE;ks-6b&BIrbnqRE zTwi2637cxU$;j_!g+M6IZVKzzVDfHmqGX`r2QpAk$N|>!v`}X8o8OoZ z(1=?n#KjyKzc7%DAniFv4a)qB1!INh(T*UHhSarS?_ zQ5!(q{il_=3CzNuf&U_9-0DYJ6rIIYT- z+4R*Zb~-1pCEp@h$!@zGHCnD7vTC5Q(z$wchkWy*WfG~9O;5da`x2v7=`Ng=;nGo# zh1IoeH)6KKG5+YuDlt)MH08o4HpMqSrd{_%?&UUzv$j4dZ7%Oy8cuJo2dnT|7==TeR^^eQ`~rPTbgxr+lObi>lp@Xr;Bc9}!OjUW(VON3;P( zR}^vyir>zVnk+mf6IEqfiP?^9Ndp-6DD0-IrsVl!A~_7A_3PL*58=9Xv1|yzV+(`u z^oE13Rl?kZ$9=O)rcJnB{T|A=$C=>OPW8f@GsLu!4(uaRzmr@tU@}O=S7vPP-}O+Vlfb4UJ5VjJvlKT$y|kJ0GXu%QqCPBKyaWt;b>}Gecj5 z_RzY&j<8_kS~)GULpobC(8 zkMuI?g^P7&U1XPZ!)879ybobXwsfHA_|1NFV1Fjw-&})5g2K{C<1% zurM^Nl7@Jgl0M$t#04^QQZbb&TkKytbr5>XcRMbM{(43h8;5piUb#MF-ta1DVYc4q zd6S3h>$AKyGuI0(wm=ooIzHch9-h{9k)?O+0sEtjZ~ZBb6M<#9Geo#A@}%P3tpf#T zQ}pEY=e{(1x7o5mz|CFfV;Y!ALTb3R@*5Xw<=alk&8UUhP>pYs!b}3i|M`R*qIyoj z5bW71{RaD8e#hf4==si>uBUSnFNDf(9EcY{fR2RYjnHpvY>fR4hfYMU(W6t)RKT5b z94(f^W8>Fj?eh1XuYu`#ac%CXFUQ_v4mKq2J<=CL((vrU@1`Gd{}iDuBX>6ZO#jlm zeg}hCf6*8?-kS{l%{tk;$@Ihc{f;+3f{;|Q(Y|Oa$^W6`th(QEXxy|03`($z0NVBa zwd;R>CBD4=d-(D)(EC=)0UW4;EgQ|?G8{U~y)ceJh2%be5O4DxDeJlRe9;pFoJL+@ zff`w&$~NM-F;sng!mx@z_BQMB`!H0dZeFduyX*=coUm9p5L%vCIZ0T zZWMCieBppjxMPC0oHOKm-jeDphc1xdLhoO*Mtf~dWKisXCCf%56{713iQ2r!=ZbuD z*zGkMi~KmrIPv0H8pxLbVB(YQw9tngn|ftiexDB5^*K~+7o)sGWZ)lv=NRRWbVvU5 zsxUr5o7tRMsx)4aHy+nfexs1tA^2JG<@5yXr0@UcdSTj12=YJ;_||&j*~Kk6=AF#p zL9olL9!F21iX$5$!QVsz3FN9(6GWjm#q^EC`yK7pc-_44NY~9iWs-4_E+Uh>SY3=uci=bP2G^r{8m&TkGDWSox^N`IRbuE+xt@J# zr)xj(%|1VrbiA3!o^B9}!Q&TLPI!OigQ~yM#Z2aFwOI|aCDGQ0Dj{681@##&z5W0x=lo(^;SNeQh!l^AH|ig2HJ_+R@pZjB z7cWtFz~Htu#KyWO5pYJCDVkI5w}IsUibCq`b_?|_fi7%J$5Vej`|n}JK|bOh8gcXH ze8luVxRD>=sDJ+JZ39DgX14#Q2jd}Ytu7WG^fK1qETMen=j~uRoL=xqX-Vouh^b_a zIm~B8MOqbNv0^l;@Wku1B``QU{2V>lLG1vkOs7&7fQ(oEPruX9-tA6#PX@%cnl98z zdV3-q{ zP$e?xM34x!eSnYzdm&sX7qYD{M3I77wf>^>9i8ysky(QGksd%wM*D&Sb7eYaL_(fl zGI++{wPzn=e8uKOdPObUg{Dvz5>{WTuX5=p{xv7*u$Fxw#GUQJ>TH|6w&YrK#yUSQ z0?tFO`V%Uks~VdrET;Z!`l9PE-w%RRThZuLiefHtin2X_Hto+BrhQ5Ki%j1qJMnnm zqb4bbCqIuh&@1yt>7$otpTuU*;7%$`s*o7fJHlOfHbyR=E`B(G3h4YoRVW~xVH}X4 zVQ-k^$o=bI)OI3RVp~41PLZX%bWvgE~heFJ-F^Q7?aOM)i?bpVK>P4tGI)KxPM=OQNzpO@AeNJw-Y1xOut=(3xov_(_ji+LUq*s^`A?-|9uBxNCL4?|Yl zHo%Va?R|5enGGZ_-%HX#aH0FM{gLVLZbkHk>C;4MdH50@;+pfA#(##rC>;2$OuayK z&dU5D=N%*a`c{Mj5=)HFA3?M$e3H^0Fp{Fkm4=HG2g*Tg|6Q~A?ScpP_2MC21~8A7 zrm0h24PF}%r)Vl#wjPy|V zZ6{;ob9LEm6;P$*Lk8@70=%2^LIlvWS>&>}mju9@`u~T*_}^Y(pvt06vq2sTjQlu5(wJ&hBfM)Y5wFmk}Hbf2naH=)Jod zsMc*@ABCwv&!kB5-taS-EMm}#0A_c2uKz7nOOjy7-9LCg1sM{=3cZf%T{S8cL*U#7 zH--LuqW_f7hg0z;S8w;YR{*TTf~y6#Dq!8}cfo+stB*UAceZ2FxbD~-gAY{JV8O;O zvQi3^|6xP+efEDqa1I|3^CMR6(f9+oomFkyfTq3hRy&tzR@jjXJYkWvpf#hpm$gbQ z@W#1JkH#}bB`#dcte}c5F$C0(Nz$LFH>Y23GQWb5h2fu>x9t*d-f&N{bfn+(a&n1h zM)zjk%%dN6Js(62GZ~Og#MW7dq&Uc!s~@2ulj{5XMZDi`{UCFhjrvD{nqoln$wn&N8zoLFD> zTJ~f(mT==+^9I@XTz3x?VovFDk1YUXdRzv2buseC9)^fSEDrO26+AR}a&N7_$4Pi& zG4>66;_=tiAVfC7e>>5fJYqQ{iL0ES@xmJJtjC-W#jC}Pu_ zYsAoizP5vo={ML7A>x|mM%qmJ9Akm!CtBmt3D3D=^pj8S{JB7w#kfbjCuT3o{5u!v z1Fz*WN6Y<#!XGBRZei?A9DYPLCLDd1f28Ld}2fAwMQocpmQVStHP@uZ{o9}=K z*5T^ai9xR#cJR9~*vWZHF4e7Ln$$O`)9}wOCbuZkef~(U1$7)GQ_eQtF#oT7gM>7H zs(JQ@op)sCIbft|=j;M2@4I?|be7Il6*?DqN+qqrbW7ekK{WJKXsFm8RdfYNmlA`f zOb6Z(yTfg3)nmgo1K~>2x1~q0h#UlrT8>Q(OU+L_;+$n@wOBZMeQCkgiKB>5TcA7nWjur_4pbJ?!N0wit6G&Sp|_Q>H6 zkr!A6T>vsO3DWQq$AH(Ywq++0aK*(dTfvg_CcVNf{rX|;`f>9;u5q6@zi7C-m&_gh zBSXwMZo!~FHk#QEwO778i6LHa`cmPvrc`qVCZrzM=>}+$3LsCsJ)|{)xfVl&+$*Ef zRsTJ4n44t%d8YYY#z12miDC}~DrEY@D}OjhkLk5NV023=h(@blyy);ij)>;CJdv2s z6(%)3|0%3Chkma>EH%`UBR_E;7>FRKbK>GwZU~>8Nv{3fW+Hr7e?uFPT9vNN7N8YF z1nW#KH3Uw%anoxO2~aNC@PhK^%jemrgxVm!^X=~jNF8N|ksspdelN)EOs@=aZRH!W zlY72>=pXg|X(DnCFl#ki5U#{LWzd0F=A`nMHj{PqnJ@S7RXcRiBtCG3-D_1_T7Sy5wFp#y zq&GSv!^iNzVKtd|r36W3K7Up$SF#FWG8kzA_)dR79@IZSN2F0MA?lM&EsSZ^EbSv$ zU3X%O@qIf`7)a*jb{v8@UtbtEpDAk=iUL?q^Mu}BU7s++oyU{#B$hnkxP`i6uz9%7 zQ*0-*R{%HDefw`APDQOxx&NY?w>AywAYDSEd3!AOLd)%%AhPSyFIVB)w-#glK3yI5 z4>aDgvLQz!Zp(-1eoFLj*}EV;KgxO&n|@)23Km<1vup!hZ`zix`bKB^gzZPw=otkh zRzrqj-G4%0@?G^hr<}E2%)`)awzwk{9o-Z3-W0%P)H_QS!T0gf?GK$6Ds*Vf4|{5n{Zgc$E%I zzQ;oLP?LEh!M5r5wAc8Er_9@KiAi(T@hLE!qa3c`L1x++d&vdwJ%aOuyX4}=DxeJ? znM9L!`T9tG*^k@U>%zdrc&GWGG0r0YY2NEj_v;dw_Vok5*DsGVu^1kw zg3g#c!cQm6&VsklMJK)ipXYqL$AKl1vHgX_mP@J~6%2#1)rf-5A|wam%`zj_8cWJL z__xQT{n=kA#HfII>o(}DQZ-vPyc|=%9T5yeh6iNU^;;Gel&U8=>{c}JZU8ksl0*+x zwSr3ac-}!Y&J?deE@_0Nmx#7|rC-?mW9SBYsLhymOW_{=_$q_E_ePb=s{`Mz+wGK1 zbd~_2LDyG_y7Z81U#?9)R80_tS;O{ePSW}B6g0xx_sdU&wHlLe#GTHSkUXCE+I|sB zeFTdVOP!YEVc}m6)Ndf_zP=`X;VGJiGGKO?pw4>5!^?aNuyK0}a$L$R{Ec=VlBDmS z`bmTvS;UQ$Cni}J5&Ae}x5nadL;|E!&igH~uxLG1$clAHtt?00`ysWIV9l2h^zgf4 zM_=S)egb}QZFk@vemfwtHu4$vfxK=A0|6hj!%t+xomUUYJ`r9DzT(q~87xkxZ0US{ z#3uB!;t^9SHP#_fNs_BjpIyiuj{xek{W^&^WNgt$7ypJk=ZcQYjUs%K0dO)=hD zuIDaYbxke+yFZBs<2uy|%c)1H^Vz6t`G+hBQ}&tH8f+}^_J9tI&kuZe`>{uES#(lB z#c?*W8_aTOsaFu{AyH%0`fc|a>_5Ud8Vk)g9RdK|>de7wH&~x=AaLDZ@%!j|f8u98 z{g=8+GP=x!avO1sVc~N4f@CvXujmO4iwdbL*h!2wz-5L2HID(Y(xu)?F*bwe$CdFw zD2rKg@VHo|z>+KJ>;e>g*lav-cdlfP_e8o>uCQ!;#!O{12f!793wAd~4&XPjj8Rhwb*53T+fZ5x4$09vc=RgL z-LO$fb|T|#Vw~0;y*&UPNe4O@;zp`T!HvaSA3OLF?9!cY;~=Sh(@5`DVR)iSd_XGQ z7OjKz3geVj9!5WbZxO{aE|zJtM$oWNEUZlLz?Cn*zYzCt|M=KhMAnQ(6xJ@< z&(HMShPy2$prwk0P@RU@l+(sDe@q^yi^NbiggKL9?i{1~wx+POoysmY7`_btI}vWn zMR`2*6ovX#=*c1*?l(s#vW+jF+QC2s7csp{{&SR;eH469ZP4|HmqzPve(3kUVKcrH z^u>Xn(O;T{WE5kU_s}iN)yPg6HThf2ayXu`+y# zVoGi2pR2AF`?A${xv+TH=k$DVSWSN*k1Cy|Z%Q!cchn7a6Hcw`eNF%m8)<0ikUR=eose(hJWGs1K^d~Dy0R_rhT zW})TP=lZX!&SOAGrZ-^*e`uZ=uF}BdohYOJ>y*9IiDI)=o zrW}K=X|bz!_<$P@|L|V%YytSJ;6XJsXYaY>X!&~e`CGLc?z#%m30}Wofcuwa1WYn@ zd$$59+CR8RjHisM%PXY~%`*0GZUqgApIjauecrCJu2!u*oz7t6am~L_k2_^9H}mte z^EW@GRiBNlv{InIxoNzDH7y&jrtnI=kmf$eZv0DcY?Z8|d|O>YJRI^w>Z-^R*nUq%Hhi0Bp)@_#rfsjV3S&Qa=y2^L6%Arnm= z9K*MmHvRU;QOV^RotB1~zhe3QB&9%;ZfpY=Rl1O!%V7*3uT!w{*i4$#OYT^pdHUmfTOBQm_4lg!x>bqQ@%7|H|*v`>n!(eiV#_W7AGi z$fY(sIC%{HIrv3q0yq7pj9*g6nG0OEiP-xktz>gSq?hYkfS*9T&p}R_JHuxw#DYqH z51-5@%LwUIio-_aGb<17YnsCcy3A+uk%g>g@OiJWr7=p@C_&SC)p#Ezw+Dj0B@}n} zb4z7gmyDC7VtxMh2Pc6+0}U1lTOwaJM)g6F0IaFW_1*<@0Bc}i8dhRHwdrKN>O)je zwk-KT=Yr!-yp_9ATmpxZ6>M_kYB;c8s9x*992%WMHH>&*m{+WSm5G&Hsn1C@rXDDF z=#-F(nhVV`9yXp@=d%0($+9bHjK{^YFXm*s*@Qq$`^{v$jmK?+&GmSd{>=&u%F)jt z!Dln>ESfoTxV+Y|UTuQrcRlR|XwmikeWoRi-S>g;KOK^hO(i9hSR5l!Tt_#r+S^nL zpI{Y(Y?)uEQI9!m%?rWYu1G19h(^BgP-%MQi%qK`z20m*>gs$bgkkZSBOV`>p#DR0 zvlm=3UsHIq>lMlu*V>GnsMv(17-kUSIPisZuCC%6Z2St39*OPfP@Fe&O^k!hsP^y- zWgAihMFJSdr%#{Ir*cRA6H6Bj)&jZ*;(Jvtc^wWJhLXxZ9aQr)bcqgDX#>NxG)XE5 zK!dQr%d6C6+Pc`ocwpOk-+3gkEW5*_q4!itjyD?GD1`wAo|_*J&Hm-nEwmX%VzqyR zRsP0OPyI1}#1zizZ#R0b#}Z;yyT!0PD>wax$BZH;5GMTW1tcf=$@+fitPP*x(XEbp zn;~cZcybU9{ha>A6wXHhW6Hpw?yZj0^UUWN=WE57#nn~Bjg3YFvpoa_1wV)BOx@Q8 z?;AeHy@)R{L>}wM=_-6s!&RKX%+vk!KF8!02_GhL_!}P=VK^b>JABKCu8w<;Dr}d? zOXe#GP3UIhJ0(fq>|qb5L8{H<@p%K`+qCS1T7BqQtpSUq9GG{l9%s_nbgGasMbUku zeA!Op2UK5=eX=(Xe^oVT|#(N8;c!D#OBt** zLe!kmS)~j}wfL{&B5dW;04&F2O@{R_cdS+$ly zA~lVhg>27j6AK-7z|JefL+K^%i=T`#k|;wq((-W*4RM^hT5`6?<#ec!@Wu}ZMEj-A zCv0rK`i^X|<|O>iaz<>%^6c-onN;(IB0(yJlo(O5P~`NV8f43+&%v~S1xqHBBT}9* zje13LPu@Y7)Am3V;5stI1=H9ZhR&q(KoEk2Q;+{T@qdSaw4&r0&!=qp3?^hc)#5ND z6|mV(B5;wB<~yN)%M2>K8L9WV12UqI{V4}LEC3Eh0GcB^dMJ1Pm`*^O7!{d`r584n zF60kWW-E)>p$IJn21TUPw;JqWS}(iEZjL{5QV?^( zqnI&iQ#c&oETI|o+^1|NBRag23R=WKyDjeA zP5v-8IC>bL(s<|T3;At)@Se)$WiuZ6z>k*({aY;TC+@l1>1E!w1-($|d%K`C0vClE z*r1&LsAZ#pvweSN=OY-6t*;B1)s==hwm7#w%Q|4Nkn!NXbNE+-@7ZW6}?(tK@*M!$w9WUKe$U@HfK1 zjAvvdtb%djbHRKv15D>%LPcH_q=PhN=n;p3P577tw5FuU-waP7Laf!7zCd1Jq)zcG zd;`OkEJl76VLXKbJoHm{CRc7AWDtIvEMPkRA5QE!C&XEinPCGSB3Q&4KW1{D!l z*1D?T!`ef3-c78``{(%HL!0>I|1Gq!0Op&;XF3Z-Eg9e%WayRNPxihyYeswn+BXFZ z@u_dh|KDio%_p7|auD6N=0kpu+e_PT;P10~ur7T3Zn*>N0ow;yG_`W6vPigGmtaqR z#|wneFa@+yn4v*Nky^dY=Fl}>;C%Fdv#Io_jW0!V+u=2F+{E|TZoj2$mB!>%XFDg; z&8>Uz&FdEJ933F+ zj{R-K-;29<ex17rM4;kc^@9`)G2QYGUz_&d+1(n+nooDP0)mvrX z#8b+DM4*Db$BiSg56-LHzO~6$GPE5{IX33$CdvmrGQNLVjxxumVb2dyr<|DBD@YU;D*_BD~9>zzuo0aOc0z!)G(~6n>GG4 zN##bgY|D6&u+yr?1_FciP&$>hpn`%o!Vu2kf0p2qsAnY!T?B(I*j~;xFH*o4x41wQ-7%ttG@CKQwb>Fw%p6{@v{>bCKE?z_g6uoFfeMP}MNZzVSPMRI$NcI#>4B zDxI**XPHD?L9d(sH%QRaYuM$Ax}<(;(i6t~rwH;2`#=9ETKp6H7zFkZA;8hpSKBr4f3Z2YD^7Fs=!oWz%h=s3aS&@7K_K{0x|^sS<8?XHRK$Qe%knZQU9rSjYJLVfd~4#RZKOSNEmfZ;0>qwHml

    E6qGSzO21f(^OFMl@=;fyt*&c!j$iu+M}%bzk}rtw+0ml@vLtF)2#hR?M7Tjo3Go9LwyxPb6~ zLFw>ve}UP(-4{!v&xQ8;QqENp^!a`B8pc09`r&8PUU)EE!}E*S`Ux>jmY{%l9BU3V zn~5V}cvsJGb%h)ntDwk0w6fe%X*KQ(5E7&sRSoJpR!mSVey^W+d~Tu2blM}}NV#HQ zIj@X(fpBQE=D-)Vz)Hr|RldlYxlm7CovES8Q+mIvw-@X0U*6Bm&^?)%zV^Aih|jBb};tSB-{9XUa3@f;vMhEqTBm}fSS6v9FvDh{$`mzx9Z`XK81y7^A3 z8|3fqfTgei4GDh>4}UE70IjEh)*$~4{D9&#f1Ddb9T#sAx&HZF4Sw&Z?z8n4JUE-SHrrQlp?#A-nA zFt`3zolkPLy~(jJCYV?y1HjJF7QnvGDvE^q1VWA|OnR*`6#eq=FbI$RIgLQ;Gi)&6 zQPDH8kz;>+Z=v1h3a!(8_oYbrfK`8j<@xfcyuo)1_wk05=tvPYB}r7IY^?#-X33=s zm^SB={c^D2U`KsL8ZMjF7$BdGs=|L1h~(d>EeHuR&VLAc>rK=(%>Lk9UQ-Y|ew z$hNH23}3Cm*<;r3TD&1tk=!a?&%nLHW$2@pOO@e$XIGLdu}ofojh)qF$k}-8m?2{z zP-1vu|F@}Broc}XLSX0q4E(AuzcC<*^E!SlM9%(L!C%RJKbRnmTE##xhfYC6tS$LodwUyunRzd4+pJVH^#{Ybjk!=OyLz8qEh+9?CH?SAE3-hl5N*Ei*t27zzP5 zI-(cf6MB6z)z(d9>-B$C@i^QP2%Rm$zl!oIs&yvY+pe^w@hk$utHIkZ_94uquOfBn zP_r6WNm>E1Ca45lB=w{MNiqNK{4w1xU(Tw03ae%mTW7;~98Ob%P4|zBXF;)qcbV(M zLSj9=+%~I_ZaB*P-jgzmsT0)8%{N3ew!VPy_F)xJ04jr>_ZRtH4;Ztl!jW<4W1rSu zKOXJt;eie~lFHR7Dn3^r0Hh1j#_bCH2RKBv^WDAdbry%r;5FboV);s|QKhV2Ybuz^ zX-6^av^^39kYJHfI#tHJLN6tszZX4MnIQLX>jV-ONYUC+Iyr(MwYqR)F5BV%s zcxX7Z1in%YywcfvNz2+8H@F)ibDE`!EA?tFf($;F1RG!kMDH>#Stz~%@nlREf=H+^ z!Y&zXDT|92$=~$4EU3l2aid+uX{9W^!j2`hWDvy54cGd-T1T%76~>*?BD;9!qrb&U zi(!X$9=~LOQVbG!P#182<6*N?g0!cGRhLoxAz%v!LaZ)BavzK@M&^|G3ifROB~mJN zfds`8%95P<7j@TbXID%%nN4zPEV&w63!5XQAW6^FVOva6?gK_@Qqp%H>ScUps*m^- zdwbrn-@a+?-Y9J)R+U)(^i;3$hW=N78uUAjl&!yEe*sxlKdnj3-r=r)RwoRzln;AQ z>qJlW%(|-G2QEhZQrY#pTGJhn<{oxyy0&SK)pxl@TL>L~Wdfo0%Y-d~F3g~41Nmua zQ0DBGG2OocDYas~wLkYv8H}P!Ic9p0Y{0`sM&TT`wNFp5!ea@2BKxwuL-Vt^Bmt+I zUsQ5%unT$LzaFsRBm|ZI{9y)cMEe)#Dsz%TGqmZk0Zd0?{#Lg3U(KqadLfL`rY10EUmPnZo0; zrm9>fu}plfOpp_V6~zI3SO)AGKSrg!*< zZ5G0kuGHpeGhcYkxai!M`jg+`zDEMlYC=gNolhbCV8mk>hXWn)W5$ZNgFNpcP`^0k#O{Fr?UxGWZj8XwkGjL+a6z%V7YqS1jT+dRBu!MbSt%HS;%wV3%`M zHzvT^K*@wT>ZcagDqi_Y_xa=x<*?r*65oKTchj9F8}rpi0LD z;3l=n0gEciNG>Bah9klMF0FrDHil2&Lu{51-oOWQD!f)mLC>4t<43c0-^UsgN+@U! z257tD&;*=t@w_=*aJg(3LvN5m)9Q~q+=QQ_ht;P~scafb-n60?oo&hw-22uyJx2Ui{O1<|cE;D5gNPXZN+>$bhCy1&mr{W6;{jPM&A&0sv7`5!YCPKdz@SVrn^Azj=j=1i zCP)L$fZOhZAYI_CHkeyI5tG^U*c~veny-2B?TWTF!=Jxp~UHCX*aA zmZEPm5a?hPNsh+nX|_{^=t$A?MbU{YKAVKgvMSJ?@A^mmQ)@=EJ2joQk`HD%X^-(RiY@H`&O6ES$0`JFc z-D0xU97#RtdY32L8rwPPpvSB~a5rme3?SZKTSu<-Q-_`Wmw-||h&y?xxjG0dLg=j) zf8--s)`M0t|LH6LVM2e3E&qUgJ+3w+Fm^Wqs*q)Yp9w>fe6|eXp<0 zu<2DaOl4aTz%YB;2UnF(9f$$sX80`1oi0Q@Mgs3JX2s00p{>D7wqJrtfT%YyyY zsmK@ICTIj+Pu*1H=@FeUz~g?8%!{tiA1rvL#WEy~s7K>lC>(MAXi!AEh3$mLU&GLv zRVw?H2Z&_-c(o4j+#iUTlAeqx*KF5GugfVe?`b_)c&+lJr*UcY+9Gqebi^w^ zn3y!0qyR}TX#%jHp2MC}0nAuAi`@8@La!u!zrffuc2rv{dc(gCfg#bxlaL`3VfYvY z=&zeK5h5*b_mb&t_RvT5$DIqq_1m}YwT?s4gzU@b=Y!)&fhR_yI<=-g zklqKEoW}kanTwe}mO^7w0s$ME$Zk{XR0x}uw&Dix454eb;S8Tt-uft{FjQQ%_^jP3 z1zMUxxNlJZKs0vZq}{o>x6e~$Pij)xBISj-{2C#Lb-FW~(2&KnPj%ZC)p%bOXWD1< zP?iQe_?V1tz_Df1|8e)l>?5D$KUx0g4eo4}=CUb|j|McZ3@F9kcl5>+H91f>ze!)O z>UWi}G((V*MCwml<9Ms1{3|k`7BhX|VOw~ecDhYqZOUZI`1qQXx+aOzo&VD6La1u} zL*{ZDhAH{Q{I=vcwado4C!A4UnQ`EiIFErSoHjRCwJbc>D`!TFdRR}1df3ifOxhxg z#1X>IBnkZlN6%viL!twr+KPU?^$2nELd3!zJHsx#2^3oNheFWh`13o1jb+nX)gh#L z2!%gv5Sezh*jHXwMGvJkv%sO?(~l)u2$|of^aQo1R$_b}R!$J@gd^onnt+2RKpe++ zN*WqL{lZf^6!d^f#3#>d>q02#$u^`~f{!d4*zgv|%9ciHr!2j5-!JnjmsX!7Di)#9 zA8gL^)9&=&%#h8vcrTqxt`Jd$&7FrrL@_(#-S3zb=sz>7#pOeu3YW&op+`S&*Xx2W z*DD};m4>oHy=tbm!R)h_sgah7~8|Rb1dED=ldvft9Vg`O`?JD#0 zddxcym;bQiduylrzkOrogE33NPRrs4aeRoXt&SwXgKqr>HP4UX4kBwUQyTfx(tz&t z*zO*8#&wc z_;?WgwmXi;D&n&{CFjt^kah6A;OCP728HXW_e0ha{?W*he)t0m>XqS(P3PP^_q4Xn zkEW!I?s6#3&*O&!aT>nv@q%9R9wcEKO!&GizLRE+EA0~hoh}LoIEwY$)j#y>+&xKj z*jB18a$9z4{a=Q3NIyc2Fk$aKkW><660Kc-i}EkYukTe)Ou(jeDhiAJJrT}&)Xny@ zaTUyqONz;0oB8(~d5C&~yu^mKG>~(TfcPt+zfdqdrDF9Z-_QSn-LzLJV;y|Ws5RkElvdDkF6RJ zO#8xl{RbC5*&Pyj`ds?k=?mS{HhP)Pee)MkrrsmfhFJA&w5}cf( zhqIOaE>M{VFZ__MhlR&b@XTUigroQ>BMjiTAf=^6)1^0eaggj>kjoQT8a<7xEfq?+ z$$(asMmA(tnbEJQX(tEda{W{Ugav$@$jEZDpB0oZ2O;g= zq+m<|TM;!sbFKZ<2F+V4#mDMB@|hbc#nPjUi3FE+7StUstRGS~TS+ z8AY=yHx;zP3gB!qz4zr|j-|T3jWFSfvF)-9L&<}Pq6WSCXX_TV=$e|+UuUyj=d$HL zv1P)){F98hyuWB1>toMjjHRxZ$zYN>zRG5tYnQbn0OzYon#6I(53v6ooxPBw^p=VE zi`VKC3}l`?sf`gWi65n&Hyy}xfh<6zLaLj%fA5k!jga`-;0${0p-&(XC}o?je7&4k zq97)n&zj+fK_#eFK6=Xel5n>}>v$o!Yxe+n?jLlxJ;9-f0j{cJO zZAPik5mmYDI~Gu=kdV}~=!qN&TpK?*z2Z@4k2oU<7Catl&Dj)Q+Fg1_gp8X~(-*m7 z?q;6G2ZQU}M)e9qc2CrgKX(XS4Yqq0E-%%;EDkecSL2rUUc(kodQE&RS@T5zEX035 z|J)k$o*E_`D<$^&B0B2!Fp2oXd7v))8~$(@D(TPaJ?6o*DrP`es>P`|$b3*u02ZpP z`HLU(7_Abs3K?87t6Jvt3aFN)Zou%7mO(N2Q>;x`jaM$F{I_bp;-v!W#>+uubk1@{ zP2L00YwcaHlDMPc&BlKM!udb_$;->lr5K$jgTrNKp3R0qs z)=GytR(i!B)4QeOFR@xh&__SRmqU6Drsb~q#mMNnPk&8BXw8ZQ@6o})Q`TsU_%ieA9-H683#KDzqmCfsO$c|u0AF}bwOZCQ3E#W|MwqCYAtGnl8e~Zde zllOb~eg(Q$A((ULkVGHWl7zj>UEYgt4v^@17=4-u4o2FuaOau)8TCf7?Tv z!OvA6IK#EqZlq25505meB^*G$)mR4z108@8xSblY64Nk1*KK8=%9c;{#0TMz&HJ9C z5O5#)Zxn$3`zY&5Dz)B9O64W0lwYv| z*@1Am=2(N>Ku((PRaHHuZwzlU*}D*=E35$mew`l}G@3pD2F%?}H)$+(uZF;5I27Sv z@XNVGe< z_q_baReW~SF^SkrpRJCJrRX#kjZN@ie4g^RP&N~~jmN)lg_%+y3rbtnVVB6;S!u^4 zoOd5ilLP|78bVrJRGAtG+5(fxk{otcTj9ftbsH^-^GB133DL-tM+;^!>i}opo`Y&U z2m573R!b|>d63>%6I?q ziNT4=Y0TCu5JalUpHgLNK!6_ENMq1AOz!+b4cz23)e*5sxQB&E8Ul}XNxqyxNfEON z{@U;}RsqBF4&VQPeK*@9imRfUd&eRL9YB6=hE!+fD$4*~Abgi3x z^YsBOv%#bD>YJl!KCsG+Xdg@v!S+ZOj2mm(A^9{6GLukzLYB_-b0Mj1j7}l0OE1rp zwO61plwI^D)@iC_0&*qHqYCefVjQq2CStNDjDfUnI6f55UOh$4rp!_kf!~7v zI|8j|cm51+r#g(*!xs;Bw zg&b<+i}aG?7}}?ayS<1FF0ffL>U#<~#OHlTBd0uMh!pM95sr@nDi!PF+%$)CJS z$~7N;Gl&us=@Kn;MGg|?zjHjmdjY_E@zoqvdkk36mQMe}pC`CeHFx z^ltKGQ{~cfk1O(kLSmSF%XRS6y(h_Nu(gnPB|HoM`+v=puOE1rKu&*RAUUz_+g(lU zFWI4Q(rCqGWMqzX;&DJ?FyMv%o-x8Yh_Cpa)meTE(XxC`9quOiSVlzdNbeU|tz#KwqC;B4K zEzE6v-xNc&dOvPKJ=$S3(%4O4m66upmVs^SR-qW8mi5Jo_P}eb28M>aZ@gpe@Xd{G z63;|tFH`;Ygl+Khx(4}*ktP~|_^uhDY)1@srCXb7Tc{|I^1W|>2X&QB_Y6%EGC^~7 znG71y)1(b+&{hXJ&0oTsH^0#?lDdbc)02{2wKO|SHIB7IQ`h>%#9TzFRihqPoo57l z8|ULyQ5tqE@!w17FeVW`#Vt(sTdp+Ic){EK+PR#g&4jm}#?ztDP7?avj|_xn0&{GO z?T=+=DlYCin;u!6r{yP6vq#ff@U=nl1zHejc%!jHujB*wRgT!8jId+H?AJb|vE5H` zhZvm3RZ+NA5!a*E=b|rNz+2H7%%lgu;Ub=tkg>;wS zp@&_{#bAupV*){-v8extueS_};|srag9UejyF0-hg1bX-5ANWe)oGgb9hdl$EBYqV@J3mY|bW7cn^;x=oZ25 z(;mbGr?dG0woyJFuRTcrw_9P)r`5QJ!})cmv))hY)r(*B!V^=(Q3fJVF^H956r3^&lz>uWeNjAkNPeWFcX*ymgPq4Ux;(eUgT-r)dQ`rtaRy? zojWT93{rA-`9{r}=J0N{a5|9zq<>hHu2Gg-Q&Xd!xm?O_z1R`Bl{;JD9l|SL7XB~L z$*9lxY(`Bi=uhq7$$d`9bj_B6_rBUG>iDo=WxLoVb=NOYX@(b*(U5YT2x6a*8uevr zu5J9=VH=*tuX}BVH|zGJ$OV5T??M<{UHH&T;wC9YTzuX{jZoCA%o(Lu6zG7R9Va`t%jrk<7f7=o{V)8@ zn?9H<`mM1CWBgPOrhe2u%ez{#OColCc0~G+-w5`MLo?s>?k&8V3c;F{qq$e+d`+7J zO#HR)8<$$j1jZy5x1i;#b|=k0e4UK)CX0$M^2z~gji_DkmpI~k3{^{Deb9tJQ_;l- z2^tU+N4GE6kwX^CbP?+&-nBRGGR6;qumM(cf|vAhb&?{7l?LR0Ngc_|now5L?E_hc z#I<%g{d8xw98AyGzMOtsjjVC3%j3>?GhUBj6tq4D{L4V+9W4fNeLluTwS->(5nk9eIC^ZP4SulBF^zvHF&;90C~vyZM%@ zT@2KU=}ctk+vF#+4!B_`B&ZhmUz{j8tvUaU%uX$I9e;SiIO|GiThuqQ=Z_g4a;_m;q)x;f_){k#h44KVX>YngOH+y4!2b2VO^E`5T#$SEAuC1 z$l-ArKY(s^>9{ehPU9(LahkxR-+GWKq_yZzqSK?ssS@?ZY{F6JPd3Jvb({;e&!p6) zO|j}k>6KBD@#g%OEj1u&`qaM-rPF+fC5I*D<)-|8bC9-+O$2^Vs5oEh|0?Oa#=HEm znTfJO<<2!ENU4FsxIx-XN=jh2CA5;otgFWGj6?*-;*?MCTeQU)WuYC-1X+LWhj zO=2F=nH)qKHejinqDsr93PGKw)96~v7_;TcoqBi6sXavbbS`d1>C<(_CbKV1D`heG zL#>vJ)b2-o5knf#vuifE%T`?|uco<0JT+;3>~O~jd;M$VkCRjako|sQ@k}u z!U{uL{ExF&{Flrkj+@{Z02{{X^HK0nP=^QMJfn>SQ=Yj{=%_)$Qd2jmAdQsC2WyaS_Z zA>g2;?E+_`r(lrB`Gvz5%7q?xtoQodUsSnC0DLGFGQ>1s=)X7)cw-<#vX=vVeg0Bz@#_=;J#1wZ2!rsmVIJqgy+f=?wMLh+FGbV! zpat`(O!-`DU-;JZfCrh?E*4C6wi3ZvOn64A}nf7 zvZ=@Gp1yA-R@q&pUop$&3`_U0(;n!rq#I37H+ortT>5|vUto^^Yg~gczxbSAh%CF$ z8OE&Qy3FIU#(uxI6Un=h-Ezn5zB6H~!%0>P%g^$8OjF0L8yJo7L!N-c3~-KzFNyyO z;rjaxqGERI4>N}OaulN^uyG1~2Rs8^-|kw7H{Nyg_vFk?#)C2mZu$|94bC z-yD7rv#eZyCsp^RS#QRH=YqpH$h|HUQhwyR_7M}K-Sf;@&uDlg=AmxlGb@K=`$fkl z2pm@VJXvDJpZRg4`iKOE(~JbOpb8T=vR}okrczlbi#dg4UJm;&^98>Cx7ajIa*lRAD_?TYhFAb9@2N@EcSMeSaKKY&uexR!i9~e<>C9&*5|IS z1>8hl_v7AWXhd`My1kU%*4v)Z%DPqUZ8~^5GOb^~&caWTO&O=s>T3kbHXF7+!9MIZ z3-9EcW&5BK_QSx0zgh=)2G3Q^Yv~WY|7`yd#;L_Mk;JGd#8djA-g!)NaXxTkrRDvC zb*?-LkOo!K7u$Znzc_YyPjHSFk%9uFk_h*sxD6WfcnwI*R^@(6x0X(yli8{vWUySW zZ9jopH9YgBQqMF`?9iG3jgYxKBO`$M-A_~P&V)QE&lcf)2nC!)^_W;l?d6)i-Zz^e zwF(rS$;uQT22OpZ6&d5=w~bDZ+%h%7wPj`t2;Pd9ZmyaAej(#AFVr~kSNZzMjgz@U zx~@QTjs{fmeQR?P?a*jvh6JEwTT#x(Fw3=Mzf8c#?EFu2y;6uI7Vy$+)&z)@~gN!Z%gu5dS>pmqScGSeCYpoSp%?dr6BaTO8uJaS(J5xvYRy!n?t{m^Vuuxw{=gV#t^7GlxJ1Z@Fo(I-<)S> zDTd!U0p~08)1aZhln+eF&4@mGK$zNJGKEWiSjKf8~@97b+_q8 zJS(k1S!7^~!n3_<5qw=2Brha64@Zu3*}Bog5d1XyYTNY}`viybcci$Bxr|NZfX42< zsddYOHg{Y&wgHsG!sF zw$Icn9={!fh&C5%R1lrOu1QMZyKwbac<#B)Y{(msPn$L za%{NsNL-GU18MjEfxc&1Q~rH49*U=9=CD(rF|>AI^Z4F z-0%_p&?3_xjM4T2;lBF(Y5nEJP|xoTmbm=gQ2#-M^wj9FAXPIk}#(yn9Llpw9QdkJxt(RNL= z9VPCBC1aF=$l~?TK10%)hY*uAUC%S!5`ZV-Q(P0t67qo;e!0m62gS2p89gHPzjz7k zL&HZMN)cu-_nWiDp#@2BkutcG-+N9T&X`gXE_uWW zt~1TN=~K}w>kcDMJ%n-L+S8#0kBB1aglAeF{W@*TtqF=&F)UDoz6F5O zl!_znLj)SCJqN&oA=AN)i`R$FxqT^~Bazi>FH(?Q7K7cz~+ z5c4~I&Fx#@5*gQeD5`8XyHo6fEc}Jp27F)$VJzn&9CzQY$A@NUI23gycjy`8Ez%;M zClq4_3)S`w$_i*hQ4DXel-UWdsK1O&!rs4bax2wX9$L3%nq<0=ES0u1oIOkBG+-!e zDx<7ofCUD1nvcu$-m7W9=GUFDOyrG~37!f1GM-k6yn6rHp5Q;CC)9JTA=dNNmu1V{ zi;gup?&_&Gd=F0~=t{8i3UwOb^-%ftN^!$?N2K>Ddd$LKi;g&V{A4HOi(A5sm(ypf zinaqCT5hlFJE#bzY*ob=<|LebSmcZmw%&a)HwGbHUJjJEi@UX+e$+lmMP;0uiG!ui z?ogs9RD3$tBfeW95ux2QT+z)JQL1V7m5-}U?Jqm|xnyEX8h2GN9B0{&YZW%Pp< zXV&nkRHJi4M)^$2E|bnXX>`s#bxE6Fw3OUz^g8##*$_7$?}Z~n_WQ?m&Bh`2xU$Me zA%=iB-_Z?RhoA7Q*OO6B*=Ui?XDd=6aT$m&Gy$Bj!f!WGe=SQc4aD$5{jN^<)7^~W zt;b;jo8F0*@;w2M=m<9~=OE01ukcGr`k!jNu3-WVS(66gQn&E9Y>a~;+@2s)Hq)?e zWK?kFoB!;l6Vc#DxM7G8sXWiaG7S8!u4emr2|ml~yKh6{c2>FA(AIp%PrAz`dp!z$?A9H((YjfAy-+zP}!VUEeDjIhl z*|w~AYAklYy$PpF{NZz~(LCj|p0}eE7T@eruh65x1|ua2yuVrShJBCx8vl9u4)jbV z|L3*!d4r%8)41JbBOWSgFV~#LU5UulMR`KMMXzZl*T2@Y^AcB!IRNx;00fc-4Aot) zRWH16aPR0nqOC=p7u?MawiN5#J!N*29*fRYpfP-*`2faZ5eg$Xus%#X^gX2RR*PS4 za>>!t6X1Cfc09m^z+FX!E#x`svKnR99(>p?aZ-c!CH&m(b{{0aZDJWtaZh+*Q_2Tn zN*c8#j|sWq1LG7%!4nc<#){0+622}l@LU%1S(p_Ld+ujFH_yd46zjDo=K)9yh>KpA z+o7-s!?8q^@3s29ok7|^f}zrYT&|}9eJiMxKHN)WH>sYQ;9XQ!dAGYnJcQIL-^wdL z=G$!{#Y|Si6}Hh<=hKfz^f*>s)qlg)(0Q*-LfiOdijBlP(a$RC4L5RFt=%C(pR}}r z__YTL;wFB6nKd`Z4+)c->H`M~{DrUZEMY>#0nb=|$#ND3wgD)vS80Z{?BYZGH;rvE=b92 zWH#P+anVCvF=sFa#GZPo8Ov?I{3ExaWv{HxG!A($hY?l+uf{|Bh`HN>*&(V~-vQZ|7l+-P2s3mO`ixT;tUizM^&f8gLa$mUynwSz?y}@y%h2Dwfda)D zt#qWgW^BS?C_Dv0&2uk!b?6j@aCCg;qiw3L4h9H3@}^x`>)I&CX5fe|U;A<5O@D1g zF^*F)tt{`UM|_+{vqdZ-#%3~gZJaaiQL+Q<9b}cE&W8 z?V8prtW>wqG8MydR&G?Y&y}f5DRvHoEaS4qpqFG*?!7GCx#14bmE_OJ((c1SNy*pf zMamZqlH&=p7yGw#JL9#K=u?NjUq-I@Z8vcEDTxCOZ% zO%nink{-}=TtzREq`}_0-L4tks2en5kVUy-({#6GdSOfUE$2E-L0`Sbc+^$Xi+$_g zp?TU-XV7jFAsmO{UH-OlY0GJH&C}wO?T`S=C`Z$b?tH2h+&a##X%~}Og^xDxrGC-v z9Z;%2-GHBe>fEe*u_8PenYr3aC$_NWtlyTJ@`US?_7Vq?yaPVY)X0mH$=OD$F(=vf@nUxs9u*v2~TR**UF5a|3(X0@ReLYN5A zkccAfe6np_n_>sw{Lc17BDDrU22_$%$jSsJAjagLDV&&)I#W}1;$LbxO!HBC7@J*| zz%%;QWDvnze^Ph3P*5aXgF3GCY({VYbr@vy|Fik&L;xUz|2hu;hesKC0p=Hx=z1T= z>7?bHiDm$(5ZTR9k`(VL?`aEJk0Yt9RZB^?o=eNqFYs3yxO{)07s+;osfnM~`NO#g zVkmx!%!)4LpW7!GXdJ;Dzi{0t0X-ZE;A!MrmlroR3xMJx9 zl)Jm}p{zv-p-d=#jS-}))t)KjQdP4r85}HCIY3kCYj2^59oZRok4~YvnCme+WWu9t z2C;v2ii9|Jf9k8G@t@E|&u(Kxp0-Mt>b$S~iVn_y@>SyEb}Rq4-o5fk1LaG@gS zddP|N*3)YE_`#>Z03POcl(2@WQ2qB9;DV5f&Hhp_kV8*e90RY(lkYMQ*u>rV0Rk&P z_k12p8Zj32+^6xai@5VCYeZRh- z{w`;@AoI`VO$CfMa}%C?*Y8VdY!)!&*QvcnW6v;P-(i|Oe!DgLAj=HbaiGml-$cR_ zvZ7LGDl*FD;*Q!Ic_3)Hm{9E^Bc&6WAz#LmCs})P%EAg1vD5cWv<_GAUVA18XhXV zZ2p-{T=rQc&%2;t!1B6{I!rrby3&41r2t*I%XN|dmX}vHnK8WU^`lIyUJkzp1h74U zASUkOGX4K7jF*u7?FnO7GS!l&$6E8io(w-2uYKL&v_DX{agF+rw99(qG3X{5B6z3Yb zis@{EWg68nOu8QVGyAL1e-l~@l)FSVd>3k1=NuNI^ZKN;k+CuAf`amRs`OmcgUA7Z za>nn}+&%9$>$b}Z?N{X%X?URUthRd}!8j35CTD8^=nX`Vxrn}XqT|%|3 ziPdk3k<4*RZum>VXkiS&32HY~{^iT8eFgyADqP)s-*z{69A5oDl^_=rc3LqkH62rq z&r>EL7SXF$P#Yt#R12F9Nm_mzsA$FI_!io-V>M$@5XW<*UTX!nMkS}YbvRQDsH0%2 zsO%nkl8kNZ%)UO=39ElER)tO{G2oPohO&md?bNw-1S%xjis66l;7`G&?9%w- zM*zCY`Ra=_ptl>(2$zUT9c(-NhhPy9;2zIv|FJi=4A;PPT>Q`cJ`a4=i0uIp_U-5$ zSklcWf)Udrcm!&vaLWKKqQG<>qBalJbh!afPo?VW8CSp?-x~=xq=fuajc=d5_Q2_w zh+U}A6%IX3Nc3?N$w0=~GXNB%8D{8;%`ky8y-GezV|8K1_g%mp({1SAH+20J{(3p6 zFjc4FgU9IV>KYY8a{Vp}vwF;J55I%g^l*3R(el25-gU5|f5oWT75OI%{`T9jYOYb< zR*UPS4g7aXrEC=cw?)T`3s%>|C9z5+ie;@i1;9goTn+fn!~Tkl^@s<%p4G)Xp6_@@BrPj%#Q}x5>pR752qL5D?H8x zb5q7bQau8{EUz1$MuCzvUjLy1-ZD5!?1nyY!rt=)N{8zei?E;YdZX`_gT=l$+DB)7 zhLxK;L#uiExRY$6~^$62yZaPWi?i8Kc2x*=CQ+e zRZ+cS?Spn_pR(pp3D^mUK}Od4e?n-eIl>(mM@NYuNC}lzXXKqYdh!ou(!D9myKHS{ zNv4V+=mi7$rp3%#+3AML%DC8c$~gjl28UUJnWMPx_75tU0&jP^S-b%yJOW&JnM{E z)h%CR7TUf%1_~EjKyZfI1un{P>D9*l-f35II#m`%i}SWYNAZ>HK?SM{tGn%ow0Ap^ zYl$ruv@s&q=0e2#p(6&A3@?I5R!~7f`wv!IvAu3v4q%S@ZyJ5YK(88SjobO=^BHOL z6o>2@#A`O;Tg5JhljS}*0nOO&HM91{O9|SoMophv7#PZAmjrOKl)Lz3sA9m3xt>tj zI`^WerK@<#uH?WxDuDctT<~uWVM(au+F;wZ*hm>=npu*)ud}0c7;Ncwz-u- z`j)6d5zx-JB`Fk9Y6-mC`Tu9J^q(%K_1}mB^fCXxM}rSX@e3q2lka;!~a(9{O`vn?hw8L)v#__dz~(#`AL=!6LyhFc2t zn`cBHl`;)|%bp9D$g;B_S(YRxv_9Xemo-(Jqwe9spJIAVqNANySFWqNLL~Pp>7+IE z(rNRA_ZR#0Jqg*&9{58x9$mkt!f1NKB4ggt8D3I9YMgQo2QfSiU1woBe=fs8zD1ok zHnSQRFXK!n-s|Yh90Ilyv!dOm=9y{P8*iL1AOrnekuEYG%_`gx&nE;urWsuFlH#XU zielszj7b!20p&6753jwVtc>JH$dJKkJ6qoytU+LQ( zPEWG_8}6IaRpe^e#a`Xy4_Y_HXIWr9Y;8s5-HDjH*MCsPyoR?sVq(^nH3Fe4#>rJV zt%(3`W!#W$!5Kb^TK#@y6h1vfxQR{}QDJP32kae+_Ed!e&WVsWdXhO)45A;*Iyn`+F(8CqaJpb5zs5-gh!Dlg zU2=vMtKJ`un@M_KK4r#NE8{U}Etj?bBf!1#Lt3+RpU`G^UVt%uHR32*YzO6PTTvduk}F`-4PnSdDj9e6tG$>_bdxz`JmSlK75$zss}3daD(u5EC7Gr2G<0#JV|@r18PfZ-#}A7oQMK7QF(}lX)(qFaF|Wh` z!56&$kY0|7+H`?Ev;U+ zy*0m_7JL~)tgC6~9>*SydqZfkkJW~0LDKyd^^>y%etQhzBBWOgW?Y`6>bL&dvSHI^ zU6~LBPxTeD(J-nVcP=L2+u zhS_Z8Iy7M7OuTJebHFeakfYuGg)lLZKcY-DZGBi zdJQk2RKB4p(Xdbk3hqF9$XC!%&qC8X#}zg$m75;m2lyumPNY&|Ap+!0Whx~0Whf_E z2OY36PY6lo%pyQgFJ(o(aph0iTjn4>kL+IQO6G?T7D|kxsfe(VI}$7~Cu|1(Bdk7T zE3=3~)~i_T%7B2UYHh)ghb1_x6MBbG`i0{&oJ|3Fe|kMqnB?C6aKzk*M&{seLm2D1 z7^lPfko({$(s zc*+|ooS#u#c}gC7Vy`0RI?Zh6xv83u+c1q}Rc9i=207@w#A zK*H|=V_4R3Vu>sJ2naW49H!WNF$|?(iivkk8`{x?gK`ja(6G|hxgBsCLXP)I^W zPO1a#SG%Ps#Z}l`lSc0}HXk5JYrDTwHw9QN#~tfKaSG2|V*LK}lOnrt1E1(80Zrsy z-_NZ_R%#2Lfrpm<;Ec)2&Eq)B-ICLv+li$f)_A7Va-U9sBEZfRlaIUn@F%k4m^$D; z$M@H9H?exn_lFRaBza+Qj2XUD4L#AS?bs6XY!|IX4kMK+!-CzipSaNwhwB0h6sH*0 zb6mE@85f^>x=L7}nn+>|W5LF)#J#`g-F3iJiIvSSWkn&44917Ld$b@o^}K1zQ z&wYM`9;k+6Z}gN!Raf2NBMny)<5vR%c;{9>xP9v~`4{B3B&Z()$B ziH8o>rE5@bkal7^`x9<+%>Vv<*Cr|>KydLuvKBWoLzM)J=v>G*WqqdglC|y8 zcqY35sJ39#X)X1r>XU9qrieu~t=2l5k{3%IoZEUrph4G@Qv7&ot-C7%MPPX;P2|AJ znOt3hVxV{HuG^oF_%JmDYA8>xhf z+Kz%9vwkD|;Dp|QR1SFW2@YS_|LR18QEd=JmC0m?_SRa`nRYRxb=!RDr3hyIE*IiF z#SZwIs^2JXc`vOSGmLbnWfWN@_M)Wv_K38$l9%!lD11;07 zlBUt6P?KL9uhSE`hC2XAKkcu4-J@RxC<6EzBKbw*owLWyE+EQtjp1`-3fGZF)w1BQ ztuYy`aiWA|g5oJ0ARb^_g*rK@2yw8lxZ6Z(3!TG$EjBJZ-{6SyS5rw}f~1u)0f|QG znAmGu%gKIM>|4~k&w6RAp0r)wtvmp*cYtt!5=YIQ6{90&|5kycwinnV{%@dm!8 zY|n?2W{!w9Ac97#%bz>P#y0|i$MuPCB)NLz(f2)9K$_1#;(Efh7O;E}xDyXFw2rd+ zANigLIN~=RABWL|N%fn|oKd84*uZxY^58RYQ(avMKGA%(*F<}B69@Cr?r!d$L=?hY zZ%WtV5?_i?NVyM6nWhFy#^TClNXL}G%Zg2w#2Qo3)O?^5blL%kT5Wr!l!^&Nt9jfe zf3c`$b$Q(0_z?Z3fiS}`QZH4hm77JxRw4ZFB33Bg4q4@ezO2YI1+fy5kuuZC4C6TZ z>H+*7>p>JPG1!&-6o(ghiY@?jEM|1F)_J_m)5~_PHU~yt3~v9g;kXB;st>%}yh(3z ztG9}px5aT)$ib`yE$U){3!_HWl}mx%f#2mciPJBIZqkE!=t6JW@Em*W zMKOtIpfsr0Es!4)n=nqHuFsLtd>V@aOoGzGkx%OIonfUeR#Q!|eE0aF zapnFWVGBB%Nz;(=RKP54-?PYVycOYAUsU^q;S_>{ReDEJ@91R}WTve;zw3>{Bq^6* z#_dRsX8bx>sB~$o^Lz;=_ev-K_PnE;-^}$22nJVe1fl=8;WSB&Su<+jhz2bN0Th_COqHa5U{v^{asLpP$Y%Ma%FMRE(WfbNO2-iq&E57*z-^$Nt?9VSn105|Ycze~CR0JhWy4Rc65cpS z8lbgFFqd_k<22PaC9Zw#7b8;|{O)OybVfbgtA!p^JsiKXir%`k_ ztgr+NReB}^mNu958p=AOUMcxeyyn{&w8%s1uw{Oc^up{EQJ=c{s^M^3U=%;3hB#rC zY%rGb_?hKaVJ1)DoszcO{rj?XoZqcE8BX z9Y+LhjSsjr9dVt^7)@$CztEp|US|?hv4JxUep6Q=F!9_sv1YCMcd$ybeBjTYUBtn` zq;Tf3KXlNbd;X%UAO@4B@seAMph2@si8H|k8}0olfe}IbONib`3KyJC@jqXrSXXii z@=H+TRs8Rn_OvSPUQ)luXfRp@`Xv54tdz6(=@H(?V!fdM4p}cYsv>s;oV`arVO;!w zoa39NN;zgzt=spQ7`Y`Gng9aejX<$gl>D@{BN8y$&mn2*skNdgA+^fC>9>kY4c~!vA_jiP!BuiH@STm zM8+ri2{#XjxZF1VT9{ihxvtM3tGkvoF38 z(nGpi@u|{SnL-o?0!pfybdT`7`w2V4vTuTH=wL7N8?`ezKGOQAfq@C7ma{Y9780_)m-nJaF3+ z63@E0)i}^SKkh}qp`Zeqtu5K#GYk*A?+>y@;}rKD>R?Kf{m^z?_bpg~r(2dR-z!+f zfP0#*=hOGe>kIY;Jc+p`gUE&m2KCs%z@ zmKyk|2DP`r=86_7O%;hLfgM)xTMJCQUgh4o9B{2ic~eP*N)1qfz_{-r_03&=iLT$) zL`ziK(Ve}ZyJogALR|-+$*m(v#YC^2vzI)VUE)imPW($tPBkb6#U&=YU+)7f8=m=F zsFe|RP;^dSiG^P;10F1AC}Nvt$gLB


    QcU7c{Qbi4yx*fsTPCE&Z3N?jF$J%tk# zm)CLd+BW7>W4+2{V9@Nv{gt|#n^EfY4>ofQFp+GYZRcE^7V5TmKeJY?c!#3scY){2 z^G@IER=O^0EuV4E96CU`maQhcI=+PB+HOu$|F)I02gJ_0hj|3f07-K=Le{li>Hw1<>YjCL*Uq34Ozd#{pHtq6RS>{)k<;2F^ z72HLuvEF3Q@wPrW6NFhItQm?NpMW}UmfwXOxT}16!L1AR?>s0u9f7r&=D*omks{jk zi&-4chbPFb$yPcHPJymG`reRIgIV5K+F?{Z`Ud-It$Z7jeA8()*R^-7sdC~2el$*Pn$>qA%&u2Dg?wuGG5wn0f`i;i-ysvLiDT)n zURO8+=v1|et54)=Uv+mhRY4qn#O{>DJw>O_JV(EhAwYxW;tKgE3zewEg0H9}B?p{p z*aV%nhYq#=qr@ltu91Z+xmE=7=?Q_(BwzctJ`t$xSW|PlnMaGDuS*%(Z;D8K?8Wdx6;nJhnp1Af@NJY2ZCZU z;DYvFBuTbVo?iG59qH=H`&7t$zT3>>RODv0Zsi7q4(mCqm%Xm}^Q02^MC=GAhc3~q zdX!Q957}#Ej&9c$S;;lg5(J0 z>3DxRkyS_93cMnt!fG|Bz=HSO<^d+31vTP!s{Wl+DTo{hA!$k6VOi)r#|;B4BLLaD zmID*Jdh^QlZ>9&OldIzMRDZ}c4%4#hF3b9yKCF|XjOWzV?L+?hXT`=9?+c{DQH`*| zM1e-lG~b_>-tqmK3$8v5 zG_8g!pU#9iFqiqSiz`@eIcr`;MMsJRL0@1;Eb(d`ksVxrZ zWeIpgMfL~?pDeuJY`tK{KYv8IW`03}{bZ%7?(F~c{BHb`PQoi}$8)u9mR|&y#5cyg z?iuJGB1sm7k?e%`6fdKGX3$e|;iS-2qowt2m!rp>>PsTaPi=r7EhnL%;xe7UuJw!j zo0u2o4NRFqIoW7kMPz=vA1j(tz@wbRFcWVgjg$Mk2^z8gI{^aD^9NAdeSiP)JOwMfbE+N6!rV+?ZSlY7_vPJSsFHjBCnEo_KGXoI1UFRl)-8yoGoO*fY^OJi7Rm#1$G(Q) zQE>$lBg->Oy%u*=KiC)!bWS2eE{4?$-nOS{rLwQ5ZKhidURtg8{Pru)*@g0Tx{bzz zz`uj{6woz0N)@EsO)cfIsDunu^5!!el#zS;^5V|h3vbdI$i@A^VVUr{0S;k2utL@H ziVa1yd>~ z;!3oQeswS=v%x{d&cblK{t8lQ^8F+}_;W|Vek&*mz!8xH0)xO9-FuVO6v1jN&d$UW z=@M6!+?Sfo1*^8UI9&Ghev(|~kA^oyBjmT26O|J(IP|J1&CREim@b%K|H~@luqAv# zCjR~=CRvcW6z;r%W#+Jy9SS2icO;?EccGZm9pr>*QF^e9prGTrF+N(}OkAG@kMAdn z6Nzot<`~MHk3G#lcN7p!er#2bv-Qxdsa)(I#m!GNTuO1=BTS+TH+ zlK%HnvCAb84WWjv*0+5&-PsA+BWU@Ul2Z0s)t`KxFMa1LK~h&^iDTI_NKTh#JU>Ms z$BTX`@E)B9ykU}*Uty;^f393|w@6UUZq12&W1-)Ceh9DkWMZs9M<{WuG7wr#90Mn5xHl+Z~u`1{&#=6NtP%ezX14ta7Fd=ID9rNv0UU% zP2!@ah|1uDj;i+gLE`@|oV@n%BYZcZ!lh(hDf#zc&Lh0N?4MXV@hK~G&WPx%Hk+S% zrDCy?y2>b?BY$B!vT9tJEO~TKy~i#$o(-p3eT0)4b!8-et2ypZ#d)h#uXYfW&pYh% zS*@1s+-H*BK7ew4gi4psblEyTDDIS=Tm@{{776}3~n zX?I#SP|Tb}W>e1&L!DNjyCrDs9d?=j>@Y>YrU(iLGLk$M!TZeXJ!#bzq|F%TepDMk zq>^)_SUdX^c@**!D)HEU8ov^wPWcds87Wy7SSlalJ+1rLBvP~00nC4QP209x0!4vG zD5^PO*>RbGI1AY|7nV1q=I@ft(Z#=k8BQ5LSW;E_mn;Q8Fp6UR!j)XA7RDITn)%xw zO*d+4c`i>i-tahm!IaVIpF^(yP!0~WV}7<;;?`RSYa@Cd5O#9^?Mvb~B@&#j7F3)E+CTux#Qn?L_>u&T)}1rHCsf(>^P22sF(qrDV8; zh_stp+R01LMnh+lUz8JY+)SCTTOB08c$muv7+ZzC&qn3ku<0(z?nqv-Z<7H#F-&2o zC2lUTJunaj*4sTyJ6KHN%5N7rnw|+dCC1OMOAPqU@f8GCfe1tkrjOdnMh&8koPPbJzeGwToZf4s20ZW)wV$Hn(Cb=bAW_nwI58i$owb!)Q*x#XL z%q*IopADV4lBQRv;Y1fyhIf!j>r^~u>gCu zi@4#Me1G^-3}CC)+b$|@7x`~jSO0(iVdRnO8y)8PNMj#KE~2BG!BymMllmgXl&5r z)@o}wDoMYH^n67U-JS1(8XG~qLi!05#S|UB6q^L z!9;CENEq5Te>GPp$Em}(JD=p%y-4Krp!Gn&$< z*@~iU2ZKtIV`m4{#zwpxi@r`ORTSrnpzr49;o!Lys0o!x&5LB6)F6jRS24+(QyeTB zCM9k+l8MDB_}uDviCSxYEmX0V7^*9{Z@D)F` zT2HEeuQGuy=~LAF;v!VRfN#ud#B+QLH@xY9Vqif*rol+#F~{#%{fLEn4`FN;{fNm) z>Da26W19bQk;c{JMoKx#17ZoI>~NSC%)LPU`nD7)gK%z!J9>1o??tS)Kzl{QhEsA8 zwcNC?s_&sgjKx-ouRozF1)pqq#y66~CMvHZqTvUh%^YD(O-*P_Wm2T8zBafai>m$> zu~1>UvEHR;uaf_ATd6yD9_JM-w5YWP#Buzwr`mjZG*uyOLj$tUlRE_2O-v#;u4V}y z8ommKhKd_qCF5yzIV0EU7W)RFsUYJ0cl&g}(6eIS)J$SxnIi0DXcD;FS`4ZvZ7Sul z<$O47*C0mcPEFtkvFQ7((1H3N;}I>Dbr}t?PR8Xm<}zo|3z@>)CslHt+P_)@wrB9% zUD7i0ATGqHRK~#-FU0s7BUZ`sA1#t&Z8eQ<{>*lHBIM^&*K&;dT?j6F)VWIQL5$W* zU+ciIaL7@rquN;5xIC6T*o=B*YZj{Lo_G!ClT?pe@yIZU*aO2e7Mpu}NhbWjlBkaY z81HsJbVB|Jm{02=5wIhF<&~!)%Dtn_H)ucoAXGUY{9XQ-)&wOgdNUb*x6~?lh04Y~ zSNA-RR;P~q37Kd@g>SdIQC-?v97HAO4tAJ?Cg8G@czsgPfF=yj&2{`UfGyG=sZnG5 zXf2+?n>FyBN1&IZgr8`7Qx?8#%MY^OL=~lW~y1QGX5qO6Ce!jlv zJ@3mW4rkAqVP+wd+T7VU5# zmDg}%+xqkpOV$73PJo4_RC5_fYnS+}3yZFdih%)W(=qjaqMJ@m{#;wHVsc1!Zh=GK z=a%&Ovs0`!#m*GxRM3skzt#%B!dfyQ8}+`5?vKDW>(UpX&YgyX)&SrWQWSv1>*&Bh zI-u(wSvrz9!l+Zm2q>CoSphmJO?Jv#Pft%LB2seJ>7hDntJx-}SJ+#L$a&&GDiR7Q zsZ6;>M4{uR-KsZ`<&>YZ9VOS)bmRnM)Gp;=(`^bT;XOF5{_`iS5Si-j(;G)>5+B-2 zz*+$IOmQ64W-xZC)sIL4G1*Kvk$x**K$8hDPvOAl-71tl=OLlxag|W5n84@8RX5t| z0lVD>?wJCY6ED%9nBOKI_l#?@WQO=PDX&z-H|wzmKx}P0mgqQ!hViXqc{vDD2AMzu zGMGNxan+s71}ufiy4`k;x?P`gHo2Y*`c>7!hihTj{5Z{ z!ECJ19zz+01~LK469pi_Rkj?(uzD)X@cdpSXh$pzu30_*A!fHhg~c?UISN&)edCQK zhjtGrV|*j^%e` zvSXF~1|J~dlZSM*(WiU)`K|ROu@fSrcNNVL10qqp3A2&4YFbO&n_%d|pup_{5+s;SM%Ns@axt(= z;MHu|)9DRvMBQ?}kwbHbV{KOAEIRF}!st=G(g|K5{??Og2zZ+{QkTN-gJ#>?2z6_d zn+jzFPwO~iT#XaGWp#dE67AazVRm#PwqF}5db%PKG{TW|(AY>234^)7au!u5V*PJj z+Dct@O;Ek-GkT?TKPj2$jVyl^N~aC^dEFax(%T(LSokXs^9`1>pbyT6cTQ3 z%lN%25rsjRF`@H`{H&J60o2R!TTG-MCZql$Cg1LEzwI)WODu}?LVl#EHVbtLF}ab; zbZ}>qx|=Cnz|5>a2|J_o9q{KDS)L4^*X&3P&eC9Jp4h#F5XYcr--DE(8>L5wdJ4x1 zJPNtQCsvW6+I^>?g;4hiU^Zi%w+&wVuLJWIqy3`|rZxTcIO?yqj! z2MhEjZBsO41$aaM_Y~`?_I+PCzPU*KA|3wpwt*6m;K1l(q_PU69#Tt~O%$No6D=a&YWWNp!N za1W$rY(ahA8Cdh)_h;6rTSF5{MCl42@L!KJS;jkM8@e7^m;{K2m;%YaDjyX^4NQM^ zQ%sxdcYUS#ym1>;|DwOUf673XAtQ6r%o>VEhFV15OrDnJtu>1^GOE+@Re1W3N{83|b- zWF%~*Z-37hI~Iuzb4~{H%07CxSz$Fadi(&HL3`yBR`Q)-+0GS0A-=x{=e?4Y??B`) z(jDavGMRJh?p}gBJB90UYxiEZosgt3`q5+LYiwBCzOZD@3yX+y*Am37wKe1s59iCh zT~7yYbkIZpl4!siJUHfM(RZ~?T@7YBEfd)UH^*lTJI}8apUu?0aE*SZBaFnI^F_Ap z)$a$-_D8J2aFK^b0Tq6mUSeFj;p7k8@pmYYqS2w4Bwh(bBxB9+@=Yex2y#KHR3q;U zCuOsFIK>_b(A_@)52{YPJ=VYWR^(Y@Cy!X`4qcuAw>urzVX-UHwOYfh5?+#4_)^J@ zAt4!6*1NhNROjDHN#(BYZ9Ph&9SjB)Ib=NS+kW&=px$>4q_>pgEIKI*6?z-5tE-FV z=GNMjyQ$(jxC4QnkrxW^K{(Z{9VcaPxwUKAVLIIkkfnh0;_KNk4Y#Vc!0&pqrPpEo(`LKDZZp6HJt81A-Pn!K=H*Q5W`97t4ol~ zZRTs!Y=6(*z4|@!U`!ua5IcZMma$r$3jBp}eT%jMfMLvXOroIQLdCfdmK5xR-bXEY z=L!td<|qa~Gy-HmKGVHDLV1#Q^R2tzgxtWW&9jZfA3FpnHpj?prAXU^uX-8^LxtXd z)k4)>%({f*+}P=n(DLTcQ@P&+8sATY7v0Zk=oOM9T+-V*fIadPoc+DsjW>x|^#_ZM zs9W$W=zIrtM3haB1KsD1-Gph2pUGC$xm#}?2~GY+)9Tl$m;(BYO2AIN_;^gDps_IT zvL6JrPp@qU6wKC$qUrk>{d1l8q+4*My+o_t>F8Fzv{^mR$0YA;-cHQ&Q#cuXNV@^} z$v5_odV#(b6d)KNY6emFwAR$lycfBC&mP^A*6ctLt% z8#>MRb)w?3Cb`8Aq*b?wJF-hkS+0frMBEeDF3ZQ@-e6Oi{44oqftiHZk+^*1a?USxxabIX<)9$h)iU~c65E2N!s!zxin!HI^&~TXrWpO1yC~jg5Q<$C329- z_~xGZSQd!SW;wWQ!F3}yrkFY*h|a?YL8O#<|HXDRL*|O2^#W!i7mHt@kQ(*}kKU0K zs9iCEO>_ets|20FQNPPYJsYF2#Y+QOlHuQY`}w$vpV32;{nX2Z43*Z!6w-L0kPDpe zLf(A1SM)|59ofL9;}htLl!N#ylg7?{Fea%VFn=2F*J#Z)Su>>6o0qiYB3ni zs9sEsPRJC5F>`Dm*m^YvQj8Jtx}?M;7J4;jt*hx1q4Bwcm(EenG_Bo(NEkQfooj}G zLb4#Bvh@ZE)!RF>H+GcE)TK%R=uY^G+_cdOr;`4kX-WNRtPuS?-*w3!0mrphpGFNv zatb_(D8dgxmJDxW9z29*d{=kt8@&EfsoO51iPL?WmnK5BjF=`D_D*JhPFhFn-~ovk zm;ZME-506~Co0Zo6*^@P*`38@`O8mdi3{%z&s<&KvXaxaKJ91Vtu)#o^m;sG0PGl5 z_`d&c_*wLuo)d@{`vZ8{Q(shQ7|6d+1lewL);{vBFj6DUS=BjX%G5iUWqdv#7KPX= zps=V^9xE`-Hk@8!FF{xRt|LbNh)NhS07RTeWo{M%lYCf%^B^M|K`@9cpCeg0> z9I)U@nWb4Z{?E#Auuji>qWq^v=J2L1ZH|x3E`&8b3?xaNv&+t;RH`@|hrE{Svko_- zksx;?YNm@x&!6nw_}PIkPPZY~Q42PdL_NKCCIDofbm38po$+JJ!vA{=jLW>v_93hg%E8f;LPu_3phsx{Vj8 zKuXw71TN$hJM*E3=w0-tnrA?8Om7}3w&t=s2EGx<7vV~5>kH4JzZp(#Ck_bl%A+;S z?u$Iz67Ok6iMhz}Io%be+jd))K1xNv(ph^c=X)p zME@$N?d;&tdE7;-S|M>(vsu`ve^0NQnQ6cg!K;+vZz+f|BZW8v3c+q>ftJBRgwR&< zLhT8rhKAAwIcxBshHb~(T)?2~;Vd-Fg(0b6OVAOI!>~hHY?}9g&%u(OG|c1C2yl6a z55`{CGYP`eYg%kN3B8t^0zz+Bz~Fn!T^ot;a>t^~vqqYnI3-zjzB&Q)qReZfHDtRs zEA{k3(5M$2(kEZ?%n=>QHTt<#D$m)JXeGEu3Y#_3sIchBgKeIGIWr&e-Lvf>&N zSY+cp=%cY}m?cTb$G{N3EVY2GfZ7IIjwpl30%P(mH zHgElL!cjwj>P*lTr_Nh7o5FTSc5KzTG1Y^djD15yrT26b2M4O15k*0xj@tQ!(6Dc?SO9ZJO z^vF*t;Y+UEywuOaBaJU_8{N;J_-~v-+xIUE@T6lhZK$C_^x@xRKiSLqKhboFFVK>+ z{;}tw4HPk^s$G9skmzyG=49z zXr)r2NKdXTt<@^w;u9Ws)%z2H}On$T$}VxkS86t6YMbkRfbm z!QElGK7%_XQgIZD3}hS1=NZf6&Mfpk$Yc}+o2B6UReTQK*el| zp}J0SWOzKbmWF{Hi0orqO#YCQk0l751S-glVQ?^1GVdP;WG-EEG*-4rn zMI`60Ry0_`^}yGXKA7W)*!@>09iz_tGQdTNCeK67C7yAAj!}SjwiDA?P`h7L%@1pG za{sozPRGpQy{&tF`zm!3s@z3EOx$w;W;)x7=tgW5jNJ_)**Oj6ZQ4Y*|0Oa)tZ#X7 z7Ul!5Yodx>A$&OTy~G(iP*23B+m=t{e21l1>2W08TG*akA1lltJL$xhm`e{kS#phq zgHj4L%C$q-+je_%mTOE=v`cpN!1wIbIX>R!Ior)|{xVTfBBC}0>M z2q2?Kb=}4L>*@+!yoCTBc_;(P*{F{1zdpbKU2$1+e zCfUzLN%Ou|wg^K`c+uyYX23@iIk|c^>oFGLc6ne>{4jTVjs~&Qd@_dM5tT1(8N5iO zZ*)Ha6{}YC5}^RrrV($~*?^gy>Pj(AhXZvzK*3~ylVV!koC`5~NJ&uk8n)u$$w&Lw~AUn6l$ zt3k%_oZ>FdKhPaobl8eN}lxPq0Wy8Ti8SHK3R7U z5qr#?rA`7NIexTbB52c}px|fYoN+uB-l?Y_rLC3I`PE)7{(yLjy=sET3z2}B@>{qd z8wKo(s}ZQ_I)MH|WOGD$GBKVC=Br(R=JRj#QGjcv2Z}cjWfOlu@j}|2tp&_W*S%Iz zx%7U3&|G4Vi&An%%lsG4W!Qw7`>gJ=7qb1sy4vhqqXR|qG2^7Pqxm|m#5mtZlflbc z3r45;%>ALQ{qD|veOimx)(SOi55a@qzSXrTS`D7I8a4MU=sR8Igx-=<0nfXFjhmJ- z*7aI>cuL5#2&QK`&3iVK;zBsYJ4l$LDQP4Y$dUHr*u(OGwk)1H%C=m;1V_7Oe+Yz0 z;!vfL->&7`a~?ajXEAu}U{o#A$~-9OOBF)dYjB+1?XgWb-;+*n zdaeDAw)7cgOj#~Nfhjr>bHQj3JW;RetiY?({jAq+Aj0@*rb+{TeaWmeL1b zye9|%e1EHZ9QT`b(-D22dKai&E|~e!%;0y^t?E=p>*LOCXIEqMfnuw+_8$KczA2wq zh-Mua63o|@oOOk7K_Z4_inYh%eV8r58-_o|86W9xl5LQ5wxH{BH9(`=29l1#pNo zB4^@w0DM=u*vWl%Rv`H>2{x9I!I0xK7+Po$ljd?PFfPU*elw!nKt_j0yTR%5ejIgm z;L}oPa-GZc>lyhrYu(Y%p=URz7nOm>U#4Ss}wm ziha&@l6GdI$jfLsosn1|x;?2m9$0Jw=hjiPy-nW>de8z*Nt*lsnHse$EoNbq71&Z_ z6m^LUsDGfLwQ#Mli#uPC2H$&(iG;C@P-sr|=`$Q4lARFF+HX_Qh?;iZKRk2Q%$qRR z4j9MkDZ+3Jrrp@x$JQ9-po%*E$p9X=r398!DGT%_(|R2(qC*?&026Xn0`;P8WlyWf zqWwTS%J4Dh0nxHpQ?&g4dxG)c54Qkz=fkc15t=YD9?6c6Q}BAJt8R}M;HZD=NdMnd z#efvqO;p8A+EwV+xh|j-uEK+1JidufZ~cj#w&XufuDE|^E${jzyfWzgOQ`lWL+t9J zNar=-dPn8;ImBFql7H#B^~vVzTQx&3AAdu20Isf)jCWBn_?}fsZD)5rDH_Yztk>lK zN#oC1)VholNoMA|@8mr>SYa$-v3RRf8&F+a0dAgKYc4(38J%dHSYDB02+ueM%SU4 zq@tEQ)JjxCI!#Yx>+gZ6u~}=66xca~ zuj~1V1@!Js5aIKVYFCnYheU3e%9v3qWYoUQWf(CHn-F8OL5fUg(y5TuDP3yH%yrI) zmX|P9@u+jMgp{FGn2ZKqiJj2-1KX9=Lit_EW;ZFjm#hDWw zFrzP+6PQj6t=1^~^she|gG|+GL00F~JQ3!=PDy6j2`B5r9nfcU8@kXyj#C?JGZrzQ zv~ydNm90*_fBpi^bs#Nom)jgu30?lcTxA9*uB zHwsb`zgOT-GIB@>8bFYR(EcG8#*2ePb^x+_kK{u9V4EDt^}<)Cf@S|1j&swOA38Y- zbf4vg`Wwv-HWwZ04zbLa^GT!ATEpz&JGql6YRW%txIfE^M1QmPJPpNWlF4MxQ&j&v z8z9XpL{*X}x|kSS&yc>po6?mgSi(9=Z!;^KOafb2Xnxx0Jgt?(DfQC7{Qs~l&o&qr z>gQs8W6=xC?N$0UJS@X*IUhqSvXhFuD{jY#;k{Y-=evLfN&C#e81XK`q^)PlYNpcm zkxDUucsm}{xENEEZ>jBVJ3 zFqXZ{2EhKtir0Yw)?7q-t_Q7T=JWf^wg3*pRSrd07WHxcN;^<6=3BpStP95X!K`F3 zD+C*)v(|E|vxs{~wTtY9t*!5}?eaf}os0bjm)6f+YD+oO*}3K{vx+tWw@qR)G6#E6 ze68NDu8qZ@!NQd+ko>~+HK0&wqRE?-d2ddIQ=2S>aO!u+wBsSir5Hx=cGwRz zXKFnuZI&8iJg+E?`^Ip{WM_&N-rW4{wcnx6lalPrvHN=|dVPajVk#fFGZG;sGszw@ zx?qp5xbA~M#ryA9M0+KfF-H-5%#7RQLGGM_BiwPKCT)-gwOh^`6UB`38d=&XAUxb^ z%Bp{XJh2jZoMWmIcB<@tg6w^#3whOTIYaXa#E@{9Bq@VBV!hIK06!O34EvvKiGj^2 zKrSljV*dvm6rP!NmGpwcW9X&R(F3wr$;@t0u9%3({TmXJe)8alhioz^yLJm%dHFHR zV}*3&uPVF(*l|GklWyS~i%!rM^Gu<)wL5-a7<|R}s0qrb4(wgT2NFw8bv++c05oVmpSw)`?GP;E+Xd9T>j$8&!NMf(MHSFQA`fY5#1&A zRDhykd8Jc0af0-9N}VTLNucN3kF3lYxBCX&mX7 zh%MzH=H$LTrnP7IT6j*`yJOkRK)X{ng4^2BZm4^s*!3jOeiG%+MIh+(3|;v`yBI^# z^ibRlzxk5Z$ab9SaKZQcV0RCpETOBP!NQWWb*bh@RD>4vZv)5&r6dB(haIjue>wSE7A z`TgH&URJ9X=)!2jP&59;pj+G*c*N7f`!t~Bgb9g?i;m9ED~4$UbLS5{;PKbaJ_!QS zSj1!INBn|k5Pu6Na2Bh~QIt+luaUdIr#($A)Rt?R9qu+Kiz0CJsAeUlvGjUBqoAof zNjtkUzoAp=@1jqikX*qg`2rZb<3~_~B2tfSH!qXqx~rwn_wq9ViY>~Uh= z0ss(z!bi!^UWO;x?!E*=GyOqI`e-=RE$xV&|NBA*g8tWg@lCAp^>4>zD(Cj}G!mSeHBYsX=8AF#VLra!0Y!^41Mz-;iOh2wRa%DmZ1og3XCU=|s~9(;_Zu4; z8af%47H^&+O^I_q{?pNo_iOsM#k^ui$tXE4i!rKrwdQ50q@;B0lb}+`LpV6kBD~~X zY*vJ=-4~M>(~)3N0$M^J_T2GiWo4~8SK#yT7&o^%m-WB`g6^EY*a>T2DaK{hn~$;n z-ySCTZF)h&&IkKSF)bl5U9OXS!q&#d#!qb;Iy*f*U9UlwrVG2Yn783(Xt0)++TslC zh-a+8KaNkx_N$0g)XGcg}vsp+OQ~7!0^YKgx7{bh-GDCY1=!@-=lXtjo`vU;h_chb`ud8oT z8;EIwE(AE*D_&w@i)3!cJC5+hxDaHxq_apWjWc&OChQSk@AkL zz-G&B>Y(--^0$wIj0m|Vf)1ktWO*;rdZlrmH()jb*5Y5QPpQ+P&7hT4uZ=C8)VJvn z8m7WFzp}Tefhu+RJrctAO%*p(VpR$?w;MNefu!P+?}l@`1X>3!vHT`E7WG5VsqgkC zzQavx{6nYul!rNC{qz!hbJAmUbJg5+xS6Q-*?5QBWz+RX~yE;1E;{ocbH*OuvZBgt%?AiGsFViJclnaeM0Y~S*o`v#G-qxdj9It7;7 zUzjxKlLWCV>)ihJ#sgp0W5zE_!9$9(9qz=#S*%oj;i)&j4tq2i$xpYobK*2gMpP9v zEfbIkPou8yfw{!G*wwL@y0*ccQihCj%W*4YFGqv+*2=cgpZz#_gS$=?}3$sQcMv*DWkG4m+w4SEWcgj{CT`cwisx{)T zDiw}zigbM9B~lo}7X0FqYeuhyqi|}27IpPpQ~|hYU!`~*)&u`hh{zDvtd(dIJ4}A3 zgX4;y(jf_c@aCXb$f3D;43KT1SD$wK+~S24NYi<~9FX;hP5M3&$A&{9qv`15e$9GO zihaBKEQzWM1w#4TCT9XLku4>8ZzqQ%aGzaA2ESws{}VY1$JN=AC!?tUL*Te!n@r5C544V zjY4Ciho&p-BT}=CcO1H%4h#>ERYlttf@wv@oR^R6$S%jliKR|Y? zS7J;~8;D4kEXTYV*nv~J{IMzdc=p4epM;+CrnJ;*7J1uQ(JG+8Dch!y#5%ek3Jn(f zG|NLch$NH1$@(wkhim5_m9#4Pse;^H4(^e3yDVarRg+5+EcEilzRJjw)=oE_3QCP2 z@MQ*)vRr&C?DJmThwqx(J;{+k<~rJKb_pU)gDA=Ghq`?>A_XfMxSX^2FGf=U5zTkAjQl!P@pO!jhM-cW7wa{DD8C9-;BN}~Kg$z}I z>R^dS&wRu2g?G7b1zK|Tr^xwp0jbk=Oq}B>F4m*9)_t7imSe``Z8ykXOpsNXP(b-( zRF*(!O3j+2jMt^zYWc5Sy;`uhYXG2p$}I2g`*^!!Q4N-IF9)~PxC$CxQK3GDDw4{M zF(zgjvt_!;oLT(oGfMqZ!8k&~@%gjtb&Vf&JJLJ?{_SGtT^K|L(^t7g%1#BbazoOB zWj-HHx_|nm#F6yFaoM+1dM*;qJf)N}MFStqe2?sJ>cy4b7Lcu+VeRVo`^I_O`q?3@ zHpMkmqTaVGddX&eSBKMP08y{UNGM4V9@|~rjJEa4*?YIEXZLgf2{e6CrLzbB*Bt~G z-WDuyOV(&P;*>UvRKYonr0guB7MPGUSMqZ=msv$?xy8N<4HAe?>sPElo3El>u2Vzm zekv$W?+1N6o&Bkxr#N&7cO^42pTQt}6zD4YgjrC|OCH`A;=!!l%E!)zS)~7*omS-t z9@KFm;Aobv(?~95)AImuR=N>;C^**$dSR^kJckr3=d$O$gNnXW^KaQiiOnskYR6J| z3>p}pIk@CzwEsqRv{;o3{u-W8$i0v4+03C+kgmj2;FI`4O%7Re=2;JXD9aKLl?m++xvc1 zd?ktt7Na`)FMB>H5-d(eW}};YVmQyq2V*W zhdk`xNeTvuU%vc!!rbGvn^x^7T_(Q^_wT!xe4{Z4Dz>*+EjV{(UH)acX8GrDl=Ewg z4}Bg)<*8IXQk5WlAM10em&|hg-3M<5l{f6d2X2L{sD>9PDf5s$6;pZkXrmCu%9qT4 zibm#tUzc2OXf4JKC5W2jD;@koXHI@p?0$oYiA@A5&XH@p6ra+G#*iN0^1|{6rdYxy z?@#crXNkY4i&Rphg<0x)CubpzjqaGZX>YxtfC4?o*TT^A*TR=rarO0EwIT1iq2bZS zGp64!H~jAA$1@ZI4e)6Ph~jUzZhL>T953i{0s*A7B%+wiB0K1tedN-miCjiD18;k+lE{ij>2dg)Vh}RVs0lcg_>LO;k9>@ODnNo+rYx{Ac2cS7)N$BW(T<373OG1-GX^N^s1`yp@i8F*d7(OVh~X zA|}`r!VDa;%5Lb*_?1+%2zS``=4Q2ex*TbRORhwCEL008qHelJzka~AonMf`5p*Ju zHHlRBt7g#IL;4)3?xx0`Cd%x7WSks%#=Z8^dfv>^)fr|soqT}m|Luy8x!?o`f}u`S z!y5K;)$QQCg9*)j$I0k+H6+sm76`?Q=VLc!hL9}{ol>&Sl{6R$8eHTZT_q2SV-Qq1 z#uD`k{IzqbDSt+|XI43OWx#y9?0S%NbKTifg5*|Poq}SQAmjR!Q{Z;^=*QMB6!fhe zfNy^`evK4)uK-kX_r~q-cF8^t`$i$~EoAuOcWkCe=CPONbo;jtNpTpDn0qv9s%L5q zR8j;J8~*vCyC zPE@`6(UqvCcq;KPm#^BdIin3bKYw&TVdLe@Rb^sW#>eb#=`n@=Y2MD8N$;QUmFSmY zj9n3PTiA@I6g7(!Xm`D+*gCu^%J7R8tp1lSiA|oNP%Rz#N?fLh6~3s6O%3hmGInlA zyI@LV;M4n6`}QGzxbv>Bv`lk5na^cy@32h8OC$+WF^v=vG$vHGJVs4%2WP5wZ}~JT9{JW0YXgsMjhzU^TeRl}V!zJX`VRB=jeUTTty| z@24jW5+-Qx!wj)w-IpBwO7a$~+Mg$sI~qgvbBH9;aw;i4e>VGfnY*=!K`6by0d8Ra zb$u%dYyje}lM$L%QAmY=-Ry^7$%ywL{U+H*o1qAIx3eosIC8B3@HklD+YKf2rHHaG zc#~e+DZT+0q^qn2t}i7AQRzqWkq#wN*>nB~bbTE*xGqGSrfQ=1Bq09~#$?ob8+Jv^ zHg@Y*HavF&<`wVln+mC%K)~gr zXrNOA$vD>;PWhiS_s!?ce6{q}Pt!fRXTsJ=v!q%aR}=jq!%Ird7LvUJ?cV2t?nmoJ zQbY!A*l{vc=RxKI^kq|_HtGvU(+g8*$lU_984oIz2CDU zyR3y&A*MO~iDy6_&M&gH-hajCYMFOjVqp=2L}4<3EdfAKW-GcD>h7md^_}8K@}Pe` zfE$Aob}bftcjY8f*VMs}(L)br8t}#|9#lk1m|9<^lSuc3^r=!;D4-NPz8$+|5W(0g zyj5}txAmd`8WN)|V4fKyer|qvFj}OyePtR1cS`}CC+bEU^5zV-h~oRWvgME4EzuR3 z%o~sn&Shq^qF|TDw*Etx+jAGwMI(V&w|n**B~xF#Qw?PJ!z)nYse8D$J5#95Rm ze7$23E}{0DFV!ONEIIN6JUMbAhhpEf*fFNeSP*jRK68#46yb>DHXr^ zBMP5JytI6?R~P7Z!BhK_8uO9(p$hz4XBqPp&Nv@?vbmO7yKH^&S3+hKRZ-3X_NdZ;Jn9DGGi`f`kPkOX{z#+2$i@!l#`9lI0hY(c(BPF$ll^!J zV=NxPj0&XHVnabOo}PSxMf_C2Eu~*MUCx4KF1`u7%HK$OgCb4QQkw$6+p_C`(R*(v z2(%oz1fX98R~SUGj>?_C6>75km+*S}7d)Nhm{GLEJUcxXgmTXBFzs(2`ZWQAR^e^hGcKMjGTR7hkre83ct0n&oxl;ehqA!sZZT6FZ*BOYs`ds{+) zr`5fc-M@!p)rYjD37Yxrr&VGXwzaAZB=h3>d{ocSU2|b#$_nY_;%O6+U;Sy35bo*jlR_#jcMj^n@$l-~q1-~A?J{2~w=~WVfE!J= zZ5rHomqro^o&>0Zr-lt=yh+Rk8Qx2mvThJ}D<9bQ>fj=0v^)KCd0S&g@7yb?`l?|ZHk=w~*;RbdQx3{%9pEo75zqmEaJO3uO`BS@ZI50I7KvQBuwEdGP>`*-uY9l=b9X{e8S@c3HnAWUV`7PGX)T3@G^eMq=jE94qTksrw2 zkPgeHTklt%i0zONm7duV!iR-jn_hk-Ct}tbr+^>Kc;A&Z5Q15)eG6ARpqfQ@`l-sp ztQBiu>uc<8Q~S5$x|YqB0hN_IB@Cidnw_ZQsDTh1bk(ujUNgloN!X7=r|y?n|4!G3 zE-45WnKH~ppqC(JFvJVbd#{W;Gr#s3c(-#grTIZC=2d19jV9JVNG_5$whrT`Y1B_D zt?DH*X3!jk)KkrReJ)w!0Z6M(g+Py4vy9K)Y>-YhC2&(~MAVgBUO#IKoNtF&ruIQ~ zrBa1o_qTVK7tLbrs?SM+-J`K4YGxoph)VuaB>e8<2VYUX7!J9uX!k?WDAuLl30-v# zMoPH&X?Cnc8_!vW&;L@vu_;jH+7nztldx@J)2zQ~Me0TXdNNWLae97atZnC7Hg2m4 z_CGFQ;ziUyJtrg$X#h5ik6?;45kV5KmJ$t%3N(EXtMYpe+gTgh6shD4Obg>~x}cT% zNCTIo=R@6Pbc_a}^$(2>1D?!pZHSu`kp+g66i1ZM zAfo}INVsL_vs{Lvp&v2u@$Ja;;%c3glB#LqeVZ2xz2YaAhmf{+Rw)L1|prvKE-KH9R zT@}t*`P{xziq5Apc?LKv*mq(gmtW!8k-U0oUL7bYTh;H0y{4>(Yb)QgeJjZcvdFsM zWu>36DjrMId_7yXBGC&OC{^xT{#@XIzC>7~(^a&DN6EdEno_f*AhRfBzuZQCD(tW0 zvF02w_mwxfR<{9wO8O8*NK!FHUHOTRb(JC2Qn#$45L>6A!5b@xR{265|fjh zEhEx}>iNzI{L3cwM71I?Rs>)Qwj_ZrTFB@D=)LR^+ed0OE;?wA5Cvj#jD=#ZNd^ZI zoH-CrE(P#FOaLo91SB=GpZeemFNX;{*y7s;YXGqa{exs@&_gstLsC(K$g3Y~rxM4Y zt9|aljZs2?Pb1p)2_EWuCIv|37=zdr#z6=Vf8f7cqzHI_gTsav0lmNbcqDIiIgB{W z{3@(d8JH~gx zq+H1Ved&hqQz(iURU|aL&ytp1sI~zPOJsSr+LdaE%1^yY%S?xwZNrONiv*h3^@%in za1bATVkh<70#_pk3AAvxs$TmFB9@2#eW4QQl;b;aqUbKhJ0o<5p7C}II`OK%Ud?4% zz%?S$KjObcT*b5VW#@Fg7*u}qVNhEhyo*+$LK;1EO&KK7lK64=-Cz1GPrp}qOXsI( z{Kh6O{^879e3U!bl|+tYrv=#rb#FYB-rcd0ydfV}+Ke}XYJHumF6nJ@7Om`K`t@Qi z`DcT%z~aepxA|Md@b{cy${>ltJmMX^M=cH$D7TyT(|8dhT(oK1|ZWrd(I*or7`cZ!I`z?M|@xDv2u-#G$xNpK<{$$>Wjv@`OzKk&ymx5yWu<8a$+ zB9KMQmu-QZU%|ZQ-fx4%oXp9{ds{w49_}pKHSE<~Ii83D1SckcN`^MgI%SVWh{Qp9 zH|ZtXT;5Trv6fq$R1$dYOMk7TTQNs|*@lggH@tr&#>Wci8I#TaEIRvAY{r7RU;f#V z`k^n(zFyy{CT)_S%nhMFe_h(&t$<-e#`GI)g#YfS}9Is(XR%U_NY`0m3MpBT~ z4a4IXNrC~tD}p_d2qmANR9m_gd@}d)Ir*p*M%IzOtKy82iT`iK(f6GM&(Vq5HK)<~&J_0^&WH14@SDhj&C>dP^-~}CAZC0qSEk=`3QLEafoPAK(6VOg$My7Y?Qi&c67x=2T=cF=#f;=@OQz z@%Gr3lA_hZv<*mPRUX(~8ZsMZaxr?CF5l?IP#?)jKpAPYBcEYmiQ2P<@xd1*846=5 z41p3iq#?fx`YW*S#BNTgBoKzK24*#Pb*l}2T0C@duE3C{zp@O-SgNVo{5&O&V&*SH z=xE;%O=7ata+J&vjihd(#e;Z+Gpx;*mIyCsFhIDYcl2IX-nP&z1qSns6kuESe^d|m z)BgsMiU^u80y?5-WBe7?4;>~Qp+ z#>Gy%vOQ+I(r5^vd#O17U)@4a!w~WzW_Mv)30ZwaiaQRY+!gX|PhOUEkZz9C+nL%; z`w)qi)&KlocV2^Nu{f6M5kYIqV;`_PEIs?KjU9h9D8AMVnQg1PC?>C%JClt}{YOVr zAL*f^8NBDIfkQ-jw&{FYU5TsFdkqJHs2f39cL6eIeh7o>f}Q?8h5yagVJ3h(R1L1) zGlKlY7pIQ*pg#_OWExc>h=Mf1`To~rzt!ioy+bP@OVu9eE!ZiOB4PhNKRH~ezuuMq zIMNt9NNRW@1rE6E>`Qk2kPw&3DXv5_aZsnvsHo*bNuIH3g1LWuIr zOYFW9bo}B4FR@}%zl`4UQ(8GjsT~cvUx@YCbizIm7GgeroKZ(su^&!UW z2)N@-$8cVF`1-{l4uv{@b8GjA&i?FQQ5{i4oDs&E&n$y_LPHW{W#~#ICi9V3CT{1z z@us3grc3vIVINpN3-o)}LnwD;a~Y3y!ctb9TOMGu2G8UaU2HK+Q@mp)^$bXx?#>akqnh{(@iXG60G|s#A`Qp&&7$m-j22}-#U{#8 zBRYdz|M|LYukv2$wdPP{?W7a`nBFU&ffcjLOq1J8n1#P$FnnEVB0m*(ktI?t*bD23 zgdtG=GtnLA>ojEST#2e>&r}cP(K~zCAiLkf2Kl?o9$T-2w|^ad6#jB0I{@EVQMieE zh0<5WZ2ULAS2t$pDoMh^`l}>@S_dII4+yGX_YFPUQhwfXHsb4?t*q!H7JjWUfZ;;b z-s1;|fx9{qIAcyXc1LVe%4~uFd%sL1jETL{^~GFELK0c%L-Pk4#!(lC(0u3dLBoI z;wvVzwd;rONXx1gKB;YJd;@u95j~VY>aNFzkpVMsSy+nxQ>5ETthwo;b(28WTV-+dYjWJ(84ql zHHgfPNvL zrtk=Djw*k^O91d6Ot#$*rc=py?Bxu6uo8x%uVEaIaBwuEIjPB&5`d~q-Esp%%mshm z(|_V_lKq`noa_rD{ZeBqZiGraL>t1ZpIUy%-1~E+bK+bRGppDO-hR45o2s|k7sz_j`V6!*%mxHO&`$YXR(W8A>H93{0{|#^O~k7PpA`7-Y}$+( zlY%dX`AZeUL(%5*fN~ZSG`LYab43WHy~-2#JHdk;+yJ_z5()XUs&J+ziJ0q+o|JEh zkqwhAs9z=|7lOboYfl)-$IT}qj9OIPBmk!hk2Q0Ldm0|OI#nWJb)~JN$d@lRucQpIE3mj{W&>#%5f{?x} zRBJje`(1o6=zNH4y9FwHze|b}>)Qa(U&*|Eu38F1#-e2Ki<(3s%B5(1rxf7*>nWx_ zzS@6>kIR1+93nT9r$hzZUm8Wq4A`<5+1)!2)lAvr~0VzAt9`hU?xSVgGS7qo%2!+rC0<52tLGap;C1cR?ZNM zmDG!>-tc4gJ~hLJvk&%I8)WMuX7`#Rp@ke$b}sZVuq$SuO!&w5Vb9+kVG19>bQ9D3 zFwKT~KgfG=Mu3G#@CftxZT8`Kw*3utdGr&dsDB#-t!_jQ+i((q%tJI>{To@K6NW+) zaNznS_P*X)U>HlbJl!X+q7VOp)guAa+hf;659l~>d|na_AeQ&NO-}*1gRfX;B>`;;b|d&URvt_j2y14gaUogI-&- zfAJgD@FTe)!K9o6a9#2YE|OG=&zAp`D2V>U&yX)07-{#wOa@YD(syAYpP1*Q=qgIz z$6b(onWn{ueHy(W06s@$!;9d{)eyn2(dJhs3lnsF&XF~2u>@hg9JCbCd^3#69yKv_ z{jShmvVM}kTsb6Z1htDe@+c(4_f;u@Nb)p;Si~49>F|~)9&;RM0EQO(8u4ekAmBXG z71TU9GMdZdM3f$Y$O8*JEY-x7?8+@Vok~nDNsI7n?HKaP9k6(Fwd+Nf@_reFpBlNi zn6PJSagEBkz)<5~)P|v0S}(S95y10Fg5}+vko`Yem+PC9C#qg85o3fJ01?;rU}>Vu zK3)G9j+9dr1Wp*!9NNee$hgYbDXs_dG%SA6SWY_rrtb4{*Brg@KXEN3xbD zdf}DaPt$liEyC5LcKh%41*CgCpIpsO34JEsMCUu}NHfMr8S#c@A%Q};ruHf&cYg`Pm! zaOhd#|1pQ~IG3|iiumVbdBguB7s+54kq#WW5md59Xm@bZd8*@eN&ACfi{Z2eTSdO& z-e+V8!jNm{1dndSLl|ZR5LSFxbyS82yOEGgDmRhDX18`D1eAaa7tXUEWK+;I;%y%&H*FSLxsQLfqb10;3_ z?8-Z_ll%jZNDU{0qzq0vpwbV0?R)82mKAS4T-4k|C8kQDIfC%X0Bgx84LS}!=*7V+ zSCdcAny^sbp|X(IwnK?H9?Otp(ZRolG%QRHVp4zf1jWXZ@f-AG_ak4)0WZKf8G$RS z2?q92lwh}m_cxAK|G*ZRdM*XwJ53S`$ty-2xiOJ?}X1NL? zd}rOWjl39})du>MF62rxmeUo*SGzD(?do`FbfXTFC={~wKV1Hnk1ojzocx&EV;iKM z&@3@T4IB@c<3}mRqyHIU5n*RA2JNL+{a%E9h^QCS4)iBb!gn71e)4VOWlyc`{tIst&xHP2~{s{6l2%Ju=_909&F<2ff8%xk$If>U1#+f+b7e;0&w#;{B{zy2y=+#hD~ z4H+N0+IC#qI~4~cqBSjH#Ky-mhFYS4(%3{%-hBjM%yJW}N%d00k@PA!V_ec4Za_Pu z@W$fT9#rAkd#6DBq_u)XsWk6WaqTgn6ymO5s0;fCVG77T4Pr5Pwo*am_Nv#~{A^qRMt=;3=p)L*%b!3bX3;{F35rH<}r7{0aissLIm8b^c!pB)v?3;GFB1?_Wg<>xDE9o` zHS9qAom?dV;rk+~T3?Dq#Y>I#Vp;QN&js{|^E>$%lt2p-NO&NYm$B*6VlUpvl_0hu zfWWxob5%}@o6`UQAA-R`ikt^ePcMPzQ9{TuppwA~?KS^MCV}KYO>cRr@x>g^*nQya zV)yX+aCl5^TWs@DdVqbBxk-RihZFFLo}POcA`|Aj>7WCT^8sLg7+F#c1hO%4wu zIUr>_Hk#LF^Sy66sBu7iJT{6|m!v?+&~sEmYWgq_ct%*h!KAgRoHN>@YCpLtoFs^2 ziC;XLJQVw!+^>@JK7~g@*z|;_x~GvECfsR^pn-6p8S^Gp>541|y#^kmMPesXXo(M( z>NJ;SX%f*x0FZppD#GfLAbN_XG&0e++046_Fn{@;$v>Q6Z|e$}ymz`5ii2>3P=Sw+ zqxBY_m}-ts@8X8y;uOw6bQjg?KV2i>V1_Tfe0Wx{P_GmAtgc$-GN+OmMrf-L2Ip7C zr}GJG7@1KixoTW%6TVfv<)!p(AA*KHlSzDtqy%5sWw5GD?p52cQcoBCd~rfw=__nnW)&s_p;X5E#Uxm5NP+uP+)i{+G>Xiu?O+YNQ`JDKmwl{o+26={N7WlsdGcO>I1+>Cjw0q*wn|FQU657%%ncMyKPr9|Al7U?R>IqWLAN5 z8W(CHZg+270<@W8xIq0>V&9G(=^5zLYifo_Z<=OpbYf|SD;;1`X{_F7sV5Kpyn{XA zmyd~q-*;V#6q$k_NpS~xeE*D4YWVkgp)NU^FJvEr$z=E8cK>*`;EVWo4wTx-&Cclk zZfRV+G|11pdO5d;IjV-uWfbQrxB-j`;LKJ@?g3BxQTY9{l?f@bakYN?7vms>7@=;m za&Ti#i@d=SrOeLViLf&D_i#93REI*Bp*ott^Ay;0xF=PSsR5sz)V8*{o@{X2CFKi* z2ss-!UTMQ|nZvrjlZ$mVo=C?!=ip_(g_)qkW zAOaDEx$zHY*tPxr#MME15puSGxF@v$+!3?|>Q1x@WP8X3Qa5!9v{xLf(ySB?Cnz+w zL>NP**Sc;9UJ3j13v|KU;AyId_}mLlfWB7Z0bDyN3z;-C^t}KG9euyL0Amp`w%nGY zpOMDK4t>~pg1$GmMgT{HNsMVyKzd&~FhJi+86L6YnAGVnyfzczjs%EWSul8#uptQk zwPAHiF-Y%r`tZ^gZxZ)89!MUsIn_V}2MmRhxd=D!(!8|pk0@tc)9MGW?%|(}-A%Jh zqfG0dFPpxJM3jd;R3Fe|uRdIO&5n2m4F09%Yl(7|W- zN&pzQR`s(85dvunla`l$?2S_@XV}~ueZ`Jg;J~Fst58fEG`n1*fM#!J=>3EwvSFwf zNltdpuKMklfs<^NH}CH|rQ(&0g(J{;{OMBHw6sI+%rnwG8caUaau;tvM1ifZtM_!M zUA*z#>Q$HX<}!`Zhz9~AuJ-5C3JAIq4!Lw%R#;{^Caq0HQu^ra=LMSc22z)d5e@sm zE1bVjgd;%G73!qy50Vs93*;Q746Xu^Y1paz>7ya%(pTABnh^a?4g0d#dfCt3OD(53 zwCdzq)&advoLZkLLe;?SJ;ne0fNWOJscvH998xK+T&XO!Gk$W6mv9!CsZT06zmIC6-kJXULFo4|~zhK)~8d)sxC74idOt_)Md| z^>xl2=D2eD(hEo53vpFU4qbgh8a&t8W>{WL6~kigk|2$h2GHxJz$-maDxW&QXvdFS zS|Sb_VeN+^w@?DH-8jAgoTZ|1B}2gxjW)c--S*24>5L9~eu|W$n6dvp{)-mKK?7A? z2ON@ptTPkT>_!}7QtGGp&k)Av)vXZ&gB@BV1e}2nq%^U?>t#%?DXUuvx&Pe-7yiGY z5nTD=0L{p>Sm`{6$Blyqe-9gDSpq??1i21^BmoOH#S9_GV9or(rJ*HOyPEE~>Bp(U zKvFnFRPSCT1qF@2AGAXf3N%+y8PuwcG(uVnDzs}KZEapa)6ght#RM*X!FKweB%CLV zmdc^146`FF>c|lT_3rm|%Z5rLx;Dlk>P>mQByUyi5gWG3DMD0B!Y$}orhP6^P7$O% zIU+kHg@_9E!xKM9&n1HW@r zhHpyeb=ju4W}yZs0jkumRb3qV9t~z&?>>n+ek+1E4qwoWA`ws2vR{_#^tUbh{6qJT zKY;+x55hEge9<<_k=Mw>_-fO=BOcFnsSFW!p@-d3s}Rcu>!u|30Ne~NcjU1g;aKL+ zrOb!X-ty`Hu`F?R4(Hz;=WU+}nYG%=OO2Eo=g_jwo9&&l8c*Vh)q?d}aPp zy_7~P)0o(NPspYo56^dw&w_uRn=Tem)N#z9tIXi7Fn6HfT4wd8Ufj%7Uv!w*OwxEX z8JW>^1{;dW2IMq|#d1TsO?PiugZ+R*Mwb&BtHEEj5$)+}(m~h{9typl_tv5xf2!-*#c{MC$ zr9Y3hE3H(lx~)2uN+Zvg8ceqdY#k(>SbFjPaC&`hZcZ`mXTswOCo_K%eN(Fo{@S;r z>yK!a_sk#Sk_q_YMdvm__&DM&zq2b@`=g~fCF0X7%dU8y7BzkTW*y*%!;_PTV z--nmE9lmqBxZo@Ym$fZTN0HI-5i)*?`bR0C?0rR;4~Gz{QKGuW)TwP6V#cGeGrS<| zB*ut8ARC)5(RocAZt=A;=s#qMT#S0zAFMDv{r5LRsoM`-c(svh4XvNN8MN*&i^>zp zm+~pbFv18ma2jTY$4_28?7{Zjc>gPq_z}MyJOWdBM?E18pjU+T_>In3Hi96iT&qfE zpWQGIX4y)ps`>@Mt!}9oxuX>L7!(@C)q}I}xlAL`VXae1*yFS)zF?s4wk0qoTR>$f zv4jwHAj~8pkk)?6wCM0^j(oLA>?AA9F=4W)QYF2n z)57!<|EGtl!XJ?-(~57r4R#OA8DeHwtVXyJ2JN?|#m%qOp*_Zx9v4MLA3iwhgBA{^b;E?0rqEQrfZo zbXk4esx&{H#&nHXp0c--@%&@t9cVMiyMnRW8taU%`B@RXVrnTqCcK$H%f zJah0Q1G|9EpM|7*iq3xc^Wovm5;|U2lsW$U-Yee!#_#bk5bd~LI##kc+Zj3aF&>RU zoBiRVpsE9!_3G>ckHa#&Adz6kZwYmKGK)(ldD~{nd}dzqM3q7?0c(inrfa4%liXQ8 z!2(Mw*jGN5(qjoH;>^0bClylmGhM)0@o1@nYAmxWZN73vUMZ!Ty32yaX7i`XiDe1e zw&Fn87IpifTugQ$pS|!q3FnvaM5|Jn5f41ti+`$rs-JO>W*p2J6M7p@>M}L1`Y1oFg zpMq?OsJ;zLB>u(+o7T>u2*?QZHIxJ^aA~e0+9}&ePSwDN72LB+0S`lQDmo6J6Bwyxq*As&3;4}5-XtHXfhYPoXaY#gWhLrkvD$m^^wMz2w;sUpvw zx{tvoPv7+`?o4fObMG$xlco4RodXPh1lP=MXpnXdbRkOauwdF&Wnx3A^?MVej-zecb-LVI;Fa=Q?Hjf>X21u1}ZiQmX1a z07s(L`j9Mx(+X{gTR{5zU;yq>He{v!ZF6cC=2eKmXSZod3GDdK_%la_xd)tdfO(aZ zpWvg8`0NyR=*NoVcZ$Ph>q264q+XDti$5w%Bim>LK=#N~N9#VQV>-22ZI@OV7=oit zh>Kj7L(&MLF$H2Ta)T8K;-2iq-@G*za)PXfqmW!EkAij}Ug2C{3dOknUP^T;RCf=P z^<&7dryiYe*5L3T04ahlyQxNiw^ie2-R*0h_pI;dIsdX)Vd$x@uDbi)``X3(8fE=-L1UzS z8K6Jz^M!S1wdjd3bCS99RrcDs{r&Bd21uW6n@%D2&4Gbev7BdA$~DzNX|gvNe#>Fl z+e?OU-1E;qM!A~l+C+Ir!U!3%7-b8l3%X6YIRLF8=mW2?=@PU&!`wL zS50BgOfIG$Uao-=>xPpVR}l@0;Dvu*E$S;}3jWC|4aGhmHn3HH^cz2->hm$KK(-); z@Kjy+>5#MEHMm!>Vq?gA<49R5g}PM68OSjB7hGNg_)KEtGjrLBS-Z3aF%|hTk3!=L zxS{^SbsN&LD+2U%?+h0#`TK9=89k5Vn>B%X3y1?))N+(6iUL9v3=DOuvDo;dD*CBc zyuI!mB67$B3fy3y>mcH~z^;0bq;IoUdUO&Qyc^;Q;)T?}^RJlDVJsu6ZMNSSPzeG~ z#t!O#RByBb_gO(f{1;=$-Mym)V45-IApyL>S{?lxR9CZA~!`1BTPW8gH2 z)^Q?ukv3OcPgeI@;S1U22P0DKrB*Tp$n69g+Rf}m8*Wa>VW!!Po39oSFFNn(Iago9 z1Yivkd9qyZDO;W%FbKR480Uk#x&v;A_#_u^i9Ucp_Fb3`&eC7Z@F}W<&RkwZ3e3j4 z;vDaHL|bgHnPijsRI{=CX{-($=kevz_5?@=zOB}6LTwvPYzXf9E{6Gz?l@Fg+ix*3 z#5vPxad=t^&7tuc&sG2JNPe);Zj{UcawWv5-$2p5=cUnhN#E z3}h_E78r`Hg7-H#-=LvN`rYaeHSIPDdtv<1IxcxzmjiH`PsU;ROh$yCeoVxm#np@l z+)8=eSuceQrCBkxef{G}zM*3lv&BhGwia^)r9&A=P`R5dp|(O+-%0JTlBx)kDnWE5 zBNZnAjb*yD#cRKk#F)QnQlUVe*;Z8n)knvUr(k(@==rw@oJO9NBNg4e`OBoV>5|Py^sF4^ z!-l}7p#m=bGvY)YXzNlB`IW)^?)J483UQ}wa!Q(aESr}i@N?}OtStIRKY1~b@aS~D zR+MU$3u%G_;aBtp5vIe|hj|gGnMiAAE;Ur4^nfZ9Pv^iSH9S!VM_ndv?(@%bwUq2!+QPTEEFB?oF(d(5qRZ)0 zvpTcp9vges3OrHm7^?lJSe&#Tc2m$2M0$_`GK{WlBh; zMllXYB`}%NDiwGZ`%4M@bzo*+#OOFRTb@p@Q^jf+=z`iLoA7Y7s_Z9J)NcN09Yy*E zGDcOiC5(!|`VfnmsLL_00n^cb?O1Ae8N8tJPwp27st9^|L*vx3GrTyU;&xb?Zf9HdQB`ufmjCy#_&!;}&t=9Wt!SKoNevMTi)Bb?8S=!ws z%4P#Xs6tIVzS&7Pj$`!Kme)P?NueOhB{eV(;m7SckyhJl679~*_=a;RUz}tfH-w=^ zsnH-y{1vPuJpVi({{xf1R}eNie9l}f1+dY?XuAi%DKLX!TbrTGHn#TrQVIFZ64Qgz ze%(=k(QP$b;;I^I*!J|y$^n^xOXkfp2^cIt_=1eYNqWA^C-QmpN>ey}bp!lVu^uJL zmCa3CgFSbKunQ>L@)^wvWa!D80#QA&0?s?18)v0{@Clua4WQem-8*QD)G#p~W&|u+ zax*iTZW?;}gb{i%`FKIO`)V|ZQ$Hi0Hss%FJxZC*>BKeBLyX=*>~45>n!yPm%< zy|3<*Iyy*T(2RWZAc;x;#704^R!bXnuCY_flf$wr_`vVqisnnE5)?_)Ye6lWM#EoA z2vh#u6DIj1M^mBd>pG0}KQyP5Zfj=eaMmtp8G*t)-%#04P*|;#iC{RQmMbD!+<)h_ zs@o57N7R(m4@aZo2sa81)CS?wQHRy%0Z%NhcJd+8D#a_lfN7EfEYs`69R(ZjM{EK{ zP~lua?WTa1xF+V2n)4CMD_*39NhZqz$a*1@Vw74*QF~9ME3CT-6r~TWRvic?NzZ| z+q3F3HaNgSJCISLm+?o1Cj%ir6j}C1hZk5tzzxByZ9N&zcGSXNssTD)O~Oa62JFUe zU}`()Nj+BmW+lK$XC#`f1ys`e(6Mdz(nvDUUEO`dKa?9tmN%&r>q21l4Z8cOgDmC# zpnYg+*yhD>LXRVXm``D+diSEoJ)?01e&9;_GTW1ixq2~?FG3U`{mN<-Unz#jOLC* zV_Cte65sNe&bj(wAP6xW4loN1en<5U%{YHcD|zSar~Dk@eM9t$pZ(T(8ahn=YKu7RFejOad|>Wt2d$Tk;ySSEKz(qrUd}0M?x;Gd zWHa@`yH6`OGSzD9_V~SBh$)`f;#W-xM!BGWA*>GGBa_LkRJ5l z?u;Rl4p|hN1ur2GnqXPCUX5fl996mOr87TkAu|5)tsNS^* zBFanhfj9SxrQ;KG!t1KOoRc-cP&4R5m5%%VHU?2-=@)#STm<$ul=qO&QzA_jfS2~_ zO_Gx>coFTF$mG8zE&@z^NdG_yQR@%l8}KP?&{>_>PxQmz>320GBcI&{mE@-anJf}kdHsAx-Lv%Z-Z-1Jgv4e2~M|R zHxu&<3S2gvGI8ky??RCRk4R45%VOqbnLq_-d8JD#o@WtQ%I z<{#C-@=z~Pra2Bbij#A>pEGMj#RoxtC|rWuNjkAmbo*yJWK0 z?DEsr`>8MAiL06e(1@G5noa?Gw4L^*bhE8X>%}wlo&=r}2~SWYs{lzLA0^W}`VYSn zc=Z4Nw0CB=dIIH@0Et5!-WNpHi@o~l`g(NA4H{Llgz;HI26Cx`R>^`UKt^6{&VwG9XLBGSddWI?JeI9MK&$={FQ-H7x0fa^iuuEwsgP%`wQb& zD3nQi{qUK-fr!KpFDi)z+jd9;w&>lPJVne)@nYms*)t_4$W@|3zj?JKvTMs=E55eJ ztklSoJwO*0_f)e9*?!#j8_*VQx8prRQLK~l4pnezHIG;2~u84q8cpbMP9mijH z$#dI$Y0ng}Nxtvk7LWv$skm7*!o*ukMA1o z52f%dK8{x|MfEzn1#wT^FIv7bM5jQ_Af*uVnF#z8p+F-b6Zt9_9dbQAH5H}?utaZ} zh;NaI|FK9afRywGBmKuBz0pVjjP#e3D7gXsZagi7_Ib+>a!UjJ1UnfDbEO2I#{2Vy zOiWY)m&g!f)V`pMhQ?|f2aAsaXd}rjHvg~W%218suig~36v}u7Zst>&u7mOdoZkh0 z_x>>KAN;4-y`|ptF#X=DaNC-Cr<~p)hZv8gtp&l^2kU&ldsrAO;o?LFS)rOnmm;;h z=t8xq4{}g$T9yB{5l`2bng{Ai%g#;HE6$E zPM;cXG&1yPG*$wAQ&u8csdzPPPIJpJvq4gyO`b8rarjYDX!dY~LWm0`+Fx53YN!xy z97xG(m^r7Z(My?PBRmeHvX~B9&I^rTVL3gOd`92_hq)+Ps#CUOihYVto60k~aYwh& zAG5=XpE(*{Ku1VD**pEl0)}0KL(|^wI=?$mS^+()&7J|F2P13p{PoV6DV|3D>u0s9 zkG#BY67B{hK=TuFOZ(qnCrhRh|C-9@!Yg}ebiTVa?_K9MZg;U-6`a0|C52yov_uOu z$?KdCzow4uQ;%wh5V{cOZ4{IaGrLgAK3cR^*Glh&3|cKB3` z>A_R`BF=ryQ4jRhZE;jLeeI%jT$}j7=WqhUsJ3TwK~zt=V{5 zXgH)K-O=9$s3RTXfTD@TLar861t-=}m^3hcsVPp}g2vH_39}6q>jl*Bvjl6`$fJul z*@5(2QV;QFHIqQ-8hiDYNHKXwg6!2cdd3jFY+zya~nXiW(Wx}pq!;Xw{Dc<^)0baVfZlWs+OIVnk{pmvC&$2G zmikRW?B-7WN!59LvtO2$e--{6b^=F;?!w%+!l;av>5`d4_`m&cy2*bd%MQF>i*BBq zP7aU$tFZ8yU#b?U)M2S4;~sT^zb4^OS>XxY{G5rb25?Bx4JZ6!LT+J_LZSmQMU!z} z@D*n4+qt3axQaVR@V_jHyZ}A#_m4sud5;^C{C7B|vB9lLM2(FuMo|4YXT*G->43IL ze%8aQmY#5b3UnJ|PoMfcUp{7Z+6F#ge5AlFUO0kQ`|Xp?qvN=>Ct0$ZU94sCrsDlK zK`WvD?pbOl7OSO|k6;-$&L@8_6Gt%E)e$xAdsqg7Iq4e2_@LfHc7WiWKL*iVvAFku zysY^pT}YY)nsO>|hN`hT^lSYg2lg5col>lpmcS?zx7NN^Gs?u|CQY$TXIDCx`x@tD zvG+6e)#AWvvB!AF)(%Our~OVIz)C5WYg~^iz%f`^WtiQEK>@02D1Ko-pDD=PD|!ly zY661MnfowcEW0@7<*%M36=KF^HWSEoEF=enQ=wjjsrr66rO0Y@B#unw8AxZ2qLEDr zeamM71Zg8~Z_;|pRcWsH?u}U3WTykJTr|SQsrX`cvwb!n=%odxv^gqWX`pR~b=&3@ zT!Bp&OZO5Y?|Xi5t+{nXBwi-jv`i@;S;XsrcX4Y9BW~LNx4F*kP|n`@0?DpN9MCd6 z5`a|-77Jq3JnUpPow>Qyhf8r0$dFak>yR>Y$bp5z;ZZ?>Iq-A$EVPkXF10zia7&z~hCj0;Y8ZI(#t9RWwuV7T5`YFV+?TcYftAI1ui1Wv`CfuDc2 z$cUAw*OFWx%&0oII&2Tycrzen&3%Mn`B5}RmL^cem&B+m)*~LVeyT_{8k0k5Hl0Yk zv9dTfm+WT&;HCdthTy0{2w*+cR;MB%4k2xr z1-N(w6)rCnM*D;Fn(^$q$bJVUkskYl&6;)Ak9uwhSl0Is#KHHeKhqnCGMXHtor(Bp z2DnayzAs{A=6ua7lz7?JYrm+*Idne1r{wT{5DBwz{XR_q60yzFqtZ7(OcRWXI)UNp zr4+R<0AO#6*$x!VYzxz+yPpJUYznzCMnpL-Ov##8Nx;YzOG-9q)BBCW= zQT0Xw7F9|XXi+dqRb2!fMd5x1L;F$srVW5>(n*Fz#78hnNUyh*1~;aQmMIYr_`p-0 z$x+UB*TAWHUEt<%;M)&#_RCUP_?ZQeXB)$%De^>rG|iV_rLs1=&l0fhw6e_oh|Q=* z5*z)txxH;KaMW-L1eZ#LTn9EsL20D6jWI?Vc?_4mF1}a;k^EZ|ozOdtfLQ;(Nq}Jd z?M;+}%>G8$!9bGXr;(RR?+#wt{Pg=344qDqs^91M=`>%RPR=uc**m*o_8|w@)hS`( zmK{~2KgBaBTZbi)G4_R~{o3daR|7m*C~h<(Oc2{Q7mb*L8R#Vh?8wn4lCg|gJ(3oR zNj-|YzLi228B_pq`CobQJ{#F(79s>A)w-^+ngi4nptouyu#$u2O>X`VhJMow|D&P* zpB0SEe{$X%PyJ>adIPFo(OAxZSXQSGG8Mv(uv*qU?=A}h4D@Oe2TKp!Umh5N0mJ#B zWc?m zT3(g1)4+ID-KyRrY39V2b-ug4e((LH3Ye`nq+q8tKs84D>7|%%4BlT(00jLpHdr@a zGy50Otp`JuQ~7)nblI}QThKM2_hWsMl1!=Hda0>5Ih8vROpJXT#_Ix`#vg73Z&jT^ zyPdfVW_BV%)4Ifx4YMnD?fug7vUYf4;s*Br;=nOZ zPEN3CPZSPL7jJK$#vHmC(x{LnTg`qn`3Ph!XYe~%?RcN^?v9PEo#m}gD0k4PT|iai zsXqz^BsJ}v(Aobc0gR#!OyKo!3(_^3N3&?m#>zw_hKZXn>6whepz=_pp zN2E-nlNhUTOsrX|-ciA`Y|N(!={&dKv))rY?_fG(XLrn^`YVu=3j$c1Gs)kRm188H zU_1RQQUQcf4QCNQ3L{qYC&zr5IAvYT-Q?Q=>_z%eId>Jo&#I5_^7>_8*Km4Cu@14P zr)KtR74iF8Pm=1l!~<`9p_C|N{ms6628$=emqbuAwL!*twqxkgnpTp!C~rm;2n16ya~Kpi&T z?MLynktkqMiV;wz)+AVT*oMFY$o4xk_MLzBnsvuvBiyGJ{ETP4^6~F@sdR7RIC<5a zOgfD)OYhdsFX!5xeH-E+^E=0n^^8k2(l;;?NpwlT$X=Ijjb7wRbS~Ty-kRtZj>IoE zL_+AJ^?Wq%&%G{}`Y*u`HBUfJ5ao00=8<0SxFf!UnXau;)oJ*TsaJZ)gOsk3IDy$= z0paZg0F~Ass1E>4^`k#aCsy6OJx<~a^Pg39q3L-OhO9WmoMiO}Fke)bz-sZ7@$6Nv zQZ!&0HrG_MhNK5_RQf_4%bYLG`!DG*r0thw87yS|hBij+#3H417BR$?m=KhYp)GK( zaUw6>^7sO-i&nR8duDG~d4?yB?hyG^;7u0Uz9%$Q<{7{*{Djvo*9L*l20{NA4#(&J z;Cw9XckB^u{#=HimX!(9{A0KB5FB!{Q*Og59w4* z-n$x&%WL=JaUK@q#8xVpr6+!c0OkN9eh0CUbY7e0Zc0DYk2~Un%6~4Xte3og zT_jl0{~VA@E%1kUe>r>H!bkZhODT}-Gn)x(r&hKR`eRpb)(>j|w>y>TE+Gx0&bq$S zIyX@vdPUS02i(sTB<8y5 zo$iRTX)X$PC%mr15QH0p<}l9s_Y*RvhFr}C|An{BO_hl$C`2RGkG3DQg5Zc2? zuA`WKhgzPz9pWGi+PWvTeH{>Hxx9!Dq1w0BR~&1(p(J^|LYxXsJ83+-v;$pi6=GV1 zt!0Nx+(KBrZhqnLRhhxR4+7ZE8^ph|i#G<_E#(g$>EOsJ5JS95FOX{PbT(0vn_z!C zNl(P@1s|E_q(GmqQSR<~bwT5)xJj56E;E?k>?&Ozq;lM{xgGtg%=6wGJ zM|GR(NE)4|nf@l%{=*2H$^Tn! zGa5kr*UIYZZ&V|3h}wJm@<+74fnzDW%9Y4e|_2mjI@OtGErkP=$8{1 zVlPK6mlo`xYMp0)U3u*)#{nchPYN|;5BX`zl$iz*mCTl4;3d)SO%z~cwmsnkiDEM^ z`J7%qAF{k;=u>u`qUvZoPP&!G7n;a+t)tW?>U8)W_rtMFDsy802{&tHQ4YvX4^i`1 zYVL<`npEn~AB=8rZYhSJ{tG1JljN|Nk)+O6QfqR|$UN23kF2R|IO5692?kUL%1)U~ zO&3y#_gX&K+lM+6mGL-Lmvc(30G>(*Z&bqxV!=@^livOi4W8!i)Q3Fb(EhATcNMp? zlYg*2>Q&FdUESgV&8HQhtu`E$&5|~1;_^iz$f=BNL_-()tI0bt=daNHF!_$q?8-j0 zMk!&i2t8dxBro`^ZID>3A|SFJDgWEz*+Bd5-uV^9HSC&K1nQyZ^i{N6d;EiF`N$e{ zoPQ*2Os%7dU6ER%?KHp=Yq=#r9W@#4zVgj5f53s#$P4Lm&DfjVol+t_wT2b?33IltxR;!;=I6Wwgt=` zQvez6Nf1{!KC8wwz6hTpV@h88(iUZp6o5ZgOil8AK8&-DbVTKkpXq7YvC?)4@?Rgt zK_BhT=FFs6qfTFGS5==x_Qxa?{WAKTKB0A|L@{cV#L=3>@`Z?HMEQr>r*y_ldO4yx zV_v$mhicGJQv>@cEh`xH+s#Rn6Zw4WmK|IWJrJ>8;r!0esLt(nQcUZ7xAVzQsAwg7 z{UvFR;pDzl_cgfExzjfdEwKxh8c}_?P8}!2afac&Dbe&ObGDGpxw%uLtDQ_*`xY$7 z`fNEoa0HSUfrAQDdhU1qAl|4^yV4w&$W{QF&sm1mRD~{&4zCsIGe7CQ|_?;9P9N%Yjzh?vxCi|0emDw>G)D z7!fYp_22T4HHNiHpoHP#;&l*k+f?4$F9MysZGL&T2-WjImdpaEy)XtSllAz2DYZtx;f?$&8plN-#ik55kFe~?xaG@K! z@inM8niRa(20?Mdn2alw%#l7h)wkk&t9W!rqf9xILlcE1(!v;W4U9 zBHUO+if)hTYH2g03v`E~K*4YGm**~Q;A(=m)78ehrASs3baSV*{UaxJK!I|?@4cbw8` z^V64!Dj6V9^}~EHB11JJLz;hT^(g#CtdPfLn%c>;)%z+$>goAlE>OiB2$q^AdJ_gm zqx6XTR{iPGz*R4FO8Fn3 zaR+MJdkuk83$Bxi&>FpIE&@JKS;B;Y%mNJc=AdOQ{NK#ypn2aRF`^UQ-L%33dtuiH zmGYm7Io59LQws=ky+FAKxln>9%m0oe90OPl9sBT1DxX6nh zz5qz64Qdb5&K84+OHOs*5|7FMa`pt&>KpG{%wYX-Srr`#Cg5CLhc-ft)vFrS8KJ}M ztF6KXkgeU9FcY;A#opg1Mk)@v5V@>Xx&`&Ml=Hm@d|bKy3ge|}o{q~KNM}UMQcUJQ zKg?e2EEf?J<$DY^*z#+SS*!|91qMh?N)j>iR@PM%;(n9f*9*` zkw_EeM@&n6gBrh`t9&eFvSi+LN2RJNXJY!znQnV>Vf8n;^)D5PUjhXwOFnS>bGMeu z>?26xu*Nn;6@6v--x z=7oW|%ob%lY13&R6(1Dz1((GD`J+RHR|L0X!+wu6t@P0H)q#+O4xI;mil)-%L(*Bpu`{-{NyN!0^OqR{ zr@rHJn;F)C-&zRJh*OKJWVRN?1GF3~R@P~64ZGJ zymfp*{4$M8j2)2P^pVi`DYg-=T8QYZ?me&iL_r1}h~^(p7YlO`pBi-!-E?2=T>WWN zdibj-V>PHp+_A@SK6(}fFH-7V%tyq+0vqVK=bq;@j#IKP&SI@&?dQ*VvjnQ!=6r`e zFWbO<$0g=u*0_d-t~FY;)^J&2<5Xxv)bU59R|9J`S!U=o3N$1fJ#L;(z>ED#iF+;0 zdYK61I7#DC=c`V)DK^=%R+W>$(WuIQd-xtd8e3KqiD$h+GkZV7!pe1iz4SjdNW8x3 zsCpzc{PK>3g)Y+--5p_hzklq*NIj}Q7*F7G z9h74sWVhhi9>VKuigT80LQ)4}JRJL+hR0jZrs4g=gy{mWHGiZZy1S3kLt5&PA=jzD z?|sV-9OJlf^mXU*cnzo{!e~l+*5{$=vH9_ddz!2mj}f!wL@Qoj;CCbCs*I92{~*GeUTT3dd=y;h5f#c7{cf)Pv+%gy*FXtm**FyO>H zoS}^-kyVXkT={Tg15-YgOJ4gP$f-5+LD*8!up;=ZVBBd>s-dIxXK%$M#0om{zJ{pV zv_l3efcjJb#21}20Di_VGDzD~e$NNTG)_}46@+X&rd`-bW48*t0h)DK=5a!^=7XAh zwXS#b*;R)PglkEYfe?ryz-F;PE&X^?#dMSh{QJ*0 zDQ|yf4@3A^>xk{=#;gX;=TT#vO~4~y#1aW8-6bl6tQivA<}^j#7O2zLtMDO0Pd7z# zLb+P+Me%BUdn%(>p<&cmIWSN+z>YQ|`I@0xSX&YGIDzA|G*+XI_-Iwe+^CK#+B@j| z`m_3_S_EbMSCleo!?+zt^WLJf?T}L3VhD32n(SWlx%b7uO@;5UYxDT=*97VxU0BR$ zgT>=pJ$%dXcIEuzgkuQrrVD+BlOd_b^(M__-Gj*DSp{>McTHzX=DphEAs0rc7#(D^ zC8+EYM11Os&R8v6-g4?0%R`VP81_OakI1)-4T z`ssyTZ;ZZZTqux!I+{1_@Hud{cHF-0|+R%IoOc%maj?v1;%N;h(xCvC)lPe~~ZEVkd^ zg4F^&ndOfvAIViV6+>oB^JQ5HqrUu7!CIfzYw>QB51&!{=|iiJR|0>Vj4W~#Mu?C9 ze8~oWV#hRXInX4#hYa3^;m)HCVbO>~uGFtu4O*nM9;1bpmj?%FWrm@qL-h&c3I=@{ z)Gxhpk2(Ll-u-X*AOd`^1vao_E-Fi8gpd_Jh))qA`TO^*22_>|T38v%Jb6uoWVwI4 zFfuDi`v+aGLBWE7eZnvwz4+dKNeB<*-Y*>pC&?bn+b5k4&ARa^sCjaQw$9LZ|C<*& zSY|5@XXwYSmcf_Yvv?mLHkZv(6$z3{Y&8^u82{bqcrkc(c z05GFjX|(C)xy)v(X-C;CjI4&UB5Nmer&*MmvyB|8R1WgrKZ=6yd27Ty??2yw_PasKn4=ZWi(mY;IRc1xiPh0zp-{ff8+1> zctP=yT*jnMzRUqe3RQTq7hHaTwdu^Ek# z4}AZg@R`$gYff^M(ryF$-Gt|TIGM;D?StEKzl#LmDS?{c0CT+4ew(;s2-Mre!htOd zb(r_>Ak5~R;6iQjzCOAA%7|n;O!{y5jfN4i)nh3rkZg}mMSCsme^&np9Fi<2xF0@L zcorw)U>FJMa+-#s@uM5ew`9yUUH(bj6h?Tk17U*fHmOCTNxZ5}PQNl}cf6Z6`P)^( zd03^ttr0=O4h@(dE)ZL6*KAeBV}&~>qa@tnkM1P&M=;q0^y z>&h$CUua7JNQH2wv%39%c#l!KT>yqqZ8VNtw(5-}Cat3Ko<=?chaV$L)Gv1%J0hWE z2FJyVLw`>b^?4WrorO{?ENU{32K2Wn6rd@utkdYVv<=9ek6ibJZE3lz<_kObbAQxH z?2hV2%vf-P9>)ZEJhy1aGCKou`=pAmhrB4hg%oDN`Mg4lR@qIfXp#Wygiq1i<2eCE zErwDneX6Hc?^fAQ1*EOwlCeB%U3w;Scod7+-QA^_E82TNv;t?$w@zI*>|OQ+e{SZ4 zdQNrIh*2L2II1k&`aLXY?QGxebVNhPo#h6)9^IKmeB{Jcui1)S)j2ym`*%#IRM>O& z!GHr{e>>sJ*C7KWp;aq>yX^(pdV=L8{am;31|FC5FpU&kY;7%yJnQA4CfEJcmXm;D z17cul6M0+3;%ogR4`Xr3E|sLGDM>zuT{k}Ni5U*Ys^XcJc_Ax^$i40|c5b@T^d%2n zvY0`XWE*|98KH+ASKDb6a}HDwx|7}`jceEFG%{-KhqK{4tr$FaFm=K1;I0yX)a zWmfmwriXw=TO!RrFlp7H!XktOHoK*1q~WsA6-E=V>tuhFTXx#%Nj6?-3&f5HFzS<< zu|4j$!e&-fS#}+`Kx2t~LH}Jg}ZY1`nLi8GY0ozObS^%Kh~r3`e8>yB9q3$n+%@ zE{%;eMSR?+agfEpfUo2SYpqEk+p|9vhN`7HguwA`UjxIGogUMhQ6}?DbbTr~)@Msy zd@Sd-=qp@)`sIbM@Hrmd+)AXdwRhJjtYZQ#Mi{At&z1X3OdnuFbO}HNfgNuNICnn5jJ06o1e>@&<4rkDKD7%YcG z%lGsSLKG;U((3o4(Dx3+*3*)GkG2AJed&$y;zv477r5sfJESdaM_ zA6UvC=`OeE0=%CQ4JKo^)oPt7jmI*BSq*3?G#i#0n)01cZ{?F&@S{lhi&adE#+GNw zNvTgf@+Br?sI904JfBd-qq9V2PueFNS3y?^ZKJu-lfvY%GBm>}V1VSuw5`Q0?=!B( z=04^NqOx$wmI##!c|Sx9gkpBRV5!DX%ClB~F*uCeKWreLdj7Kxqp|WipQ%Z$)C(bc zc8=O0iJtr9J0KCw*l)k{IQ?o+Ew*$%lXkmr?sm;g7&u7Pi1&4815>hV?}S8r*@kJ! z6RGL;@scZNy=MRfIl6bppjI73R@F$;5+h}I#-x_bi~^3q1zp6a3}zI8pzLJc*64)) zt%K^k5*V~^hKeLW8XX2AvD*z#VKO-CWMq0boX|T zEB?>pZq$cocFy|}Iay6q=pbzEvNXFOobCBk0IzT>4EwiJ7g!o{=z)R!T<43A`wi4D zpAIbv&1I&uh=jGDFql4oo-1a@>RC9>&ezJVBH%|CU_6D5aRQS{#Q((%Sahy z!F=jR>dC}}`Y#(HBIf?4E_IWnt15K-;+g*Z?_w2dT?+0ZM!q_H8Z?2 zd#fhcz#ME3bw)rL^M5Uo{s?2pba;0^$`3!)_6_cx#sVL5UF5reLUj@3v4m|Kouv`~ zIXTvAvmk)~()Q9ryW;n6#l5#`>>VA8w)Q63_nNXZb74ZAALBg^H%_i&Ew}DWnZ`4LPB^LO&uTnD-^X8%B|PCoQ}C%eUb8)d zDk7atg$C;1zkiqe4P1U7*TbiAU%<@evy~EIw~k8>-S(X{V77*a6g;VuNrB;Kn8+DD zd2&WyCvb;prYb0cI&ZvaGbHLd-VA;F3IAC?mo$D?7xL&sAs$)I{PmH4Jo5U*@e!}= z8J{&;LQ&tlYFW{eaCPWKb>y*BUvO^rX{<$U^)+&%H1(cZY2Y}^|Lrz4u$t94(gKGr zw{1|PZOli&8H>2e@qGBif;^(8FMA_&P7v+=1lzdsgm~-yR9SM8iDz!50lrH0!8?(x z^~6rbJ3@&CFaZ1M)(M_%#F|U_{_#WivIoW_x0=S|Wt_@wYy#o=#lS1*psX*|=gU2BVvm4yQf0+;*m1(Q z=rmRrI=S@rl2b#BqlFFM&k9YbCqnLlL9z>Esik-tji-L^5-b*}1AK=u%sp(Uh!5o@ z8V~;ws#>qi-i}}p3gYiF`4rilpnlF;i#IAjte5{{cC!d0)hJ&(buYPQv(y4KS^d3W zF~^l_;!`F7nfKX39kbVCeAm&T*1ZyYwofX4Kp344w<_rn)z07`K+I`G3mY3O8X-= zV1SI*9q*>LTJBlS{c}ppz`ZHt#B>#qx?a!tF{#fzX!ve7O#m6&cK_jauF42wOt;-1 zySVnQ*3eDh(%3s*xe(AJPzi)c-rN*T`e^LTzu1OaRgpEFs%$FjBmLRkO8%OUeppMg zUg}8>WuFnLUS$Rwtj;WULdipcOC)!t$j>R9n@+9u5hE;l^L`^1L z_FS)sSTs6SOH@=3`>&MP%uWnjz%{dA)>Iv!9C{h|i#NLtHt!0MN!vHTENQi-@6Afp2{~>xxKCwNYjMW{uvt_WXl<;a*WPA}yO(o|vP3>l#abcY zeXrceByPwI^0ZA0gp*mFu~!0mE=qDCWn7)rMx7h2YH^}k!APAB&A9FWN44#Ul%Vln z%^*ypk`6*gZ(CC;FIM+%)ZQBzhD2xR{PB3rOR99GqVcHpydu*@W9eq#nCX88v?6T) zpQG`baM+M*6`UDD8DmU}l?;fkDxj#3{5W_<8%Xbx8R)h90e+!A%~`MTUoGGsY2b1` zg6Li{=(MoyFsu6)lyc>HZ$cUzMmO1wMuV&4Of0l%WHQ3j-NN_Jkui(YyG&Zz2e~|8UxP>Mqo)%~ne2nhSRqo)^ zYYvEJa-wCL;HNRdsg;HL%UyVN9m}~mSwGGakR&-v^@|X&mxgn~Xv*)?Xf#OAo_yKO z6m?WWr`bpAu!^41yczzM{FlowKgNA`Se57;vk(>Ma2nVMYkY?m!*Ykk#KWn@$9@fx zAJg!(Z%|ERk+RE)^oGRU!Gg^H+OIz*Zzm+ZcDdMmtbGz?lr0p)`oe{Cn{Mr{zFHL0 zJQ1dcfF=`$x6?*dYPY*C&0!7EK}2T+>G(1MxldFc(8Qj%SufeJ1u0OBvOz>V-aGH2 zLfvmkb4~=NExcyb5FwfVMYih;+DCl0B1=bNdw@3EVhJ~$zkhiyh9->Scf3;n+SDBY zT53K`hM9vQI^?$eXDDb5m;~&PVBog`iZ2yPxCk$XS&cwgIKvEaC#7l+~In z+jn~S`sCxK7@LOJaVb1bD9l-X7HhB`P(SA6ga8;=w|XU{F7nhd;(73ID1SRwbjBXLha_e^Xzy?0+~xs}mA`E5{S=7l)& z4NC`snCJv%nQm0=1x`&_MentE}GRqGD@Yee?Xx_PKc)(rMpOOsSxB(pH|oXTicL-2sOROQ24z*Zzdacw|K#N&)^ zl7H-l5cN~-GTmposz7ASWtZG?pAUg88@X5<`H)gUmUh zL{(DDTHOd=)6oEc^?gDiM@-{v=zV`2V~WD+-HS0W*K{mUA5WNUeEUe1E0e6X{IgZr zlQw)4RvipYFNj=9R5qMVN?8=x#R&Tmui)$U#!h9e5lKbV?rQ|MeXRfK7ji7>;|>_I zvte-`-P|9;=QS-3NHLn4B%vhwLnFe7hT2FqT>el}!yIYMR&5_H85k|zTtX57+RPh2 z3=V$}g5M1g=Vrt)zJ58Y!93F$8WTScIK0kuIoXANhz286Xiy-^h(J@^Ed!h~nWHq& zqKT}|TX7Owy&bylK+t~L3m=GHt5*DP_Kn7`V?%5VP)d>_1$eYM`j6P41WSF&{;%tv z#sgN%oYAfbbnd#d?dJ2`4vw->_1xYzy(c{womZ0G3ZrxJp5!{U!y1yqtz?XIl3+fk zCts%bys`Y*=VAoh`U8AJg13nGm7%EalFdHlD!TRpgFdBCuz%p7s$ue|4Qrk1H0^BYl&uQ>sO<3q=0&&*rBmQVx8o;?*bi^FV@0L zN_cICW(6^Zx!2;v`7K)GL@SI3^q5b!!7T2dT_M)dDqL(DtrGt*|8)O)s{(CADHJK~ zijiRISuQ%+&Nz;*jqxdWfUxR{ng?0BbbCUNdFZKrGayzY7| z6C!!isHdv;Yra#Xe&pY}!QxCMQ4758kME%{$G?2L;^tU8#s0yH$e^HRXVZMF(HXCpP|yHyT;ruRDg~(Y{vO zjelV7c4q01=9n};_j88Ie0YJ4?mG#jb`n_nrc6GJNC%2981j>Djv~pFN{ZmO=k#T_ z?J-2gW#8onk(Vhp9+_iaMtwvIG0(PM3FFaNJvW=7H#w)0(H&${_Kw z4ENK=XzxcTR_!;@Y0=ClemyhV*8pfRG%P)%*M6^Iqj=3NVe36kV7Lk&kVa?OLB@9p z|MTFHklRyj+Y5Td_s{;!QiYE=>nbEb)o1^5xOB$rrrbH=JH$pI9BzDk)@{yzi#Z>C zMpH&wa?X~e+Mne!$lq(<7$fAINw>R;cjv^oVHdFs11m+?KWH$0`@#WX`{QouRP^Ah zby;miujc|w-DVb_<(OaMD_`e}YJY&dO&=~o*8?Pn%!dd}4P9ge(4vT+)zC;F3&2-l zwqDbI`fAfD4>{trK>M>M%7pt!46oh$8uy1eYX=Ywe?tcu1fmG59r`y=h`@9$1Jx(u zN(e-c=xdw|#;`|c5UD3!d%VAmFmJz|h0Mx}QlEBRQTe~MhOS$N^RvmlRd@jCIRo)=&S!O=vf_}|Q z2>gi;UpK;&R-=~vr*7TxiiR(aEG&=zT?=^#lDH-fkb|C-prXQKVF0*?;NlIZx3jes z&r2Qi-G%joh}6Ar0Bw&4t?m?uQ7Vj-K=7QBg55d-aaXGDRv1@3C*&2tC6kXHT*BHL z_U!|8Hd5C+5eIgRfXV-k>d(28!xU?JYBkx%)A68Xppn}U4!f)2sO)%VJH`$x6;rvo z7vhb~y4-4s`Ix;JBR|A6%v2f*R8V|WFN^rg$R&WJAcz3@1m*GCt$X9d;-;HaKSN|5b8(%U@zSs9{;7u$dvPZHo)%If0Tky zt#2c})|^n^GvtF;E`N=rgI3p;0;Ka5N}899m==d^mJa+Ezu?9DzAxHn+@%W?UH-82 z)KTS=U`@lyyAef$DQmdVG}38*iK$~fsQkkCjvsnsff=CvFzb1`sqN~kLzE6HJ5a+~ z5(}^A3J%;(YS-e;$`ZV@-n)vUjG-Jng?KpWT-ac(lOz1Qys3iUnYKtXK~pVHL$scy z1epuPvFmS;YMQ1rWdmD9Qt3ir#||VS?RO+_%K`#B9iJ^k2x~FZnCOCv3pR`ulpY16Lv?5|hs~W2Z~}Xiq;^$+?3@0}b$9T3`vt?HPHrB%$Lu zs>Z+MGNRG$CL_kMfjCpulcu16FC=R-2RGaCB3*Lq3&pDXaUDtig-6A@YDOzORMRY% zY>Q6fg`#@UNG28!ME3%dL0e74uu^GJJjV2X$kPejy-F+8{fF8*L-uO+n7gk z^x?>_CI=ma;1eD7B4pVW?@Op77Srr_(Q&VCW*hab6KpzA*>cPApAN${%o49isDkqB z2C46MpYta){N`*pq0jHBYTh_+zC>s~NPdTQecN3sgS#$|*s+&s_|D_8BE@ZU;!W6W zJnWS#lc``ZHavgcHNh}_lS-{thl^EqJKGjb`?A_(Kt!`%q0!A46+fl(4%FP3_~M9W z?N^@=k8wQ_{62s6V=f^)EE8HkarMQ9oD>FDJ*;U+f~Y7W2KS zTOE1sqrKSFZG#I~Du#_&-NHG5VOq&!i}kMzd&VFN8ETg=CZ;$G--FR*$m39nX2?zfg&o zgpZsD_Ts9~{`ATA6Nnci3YmU_2591QZlCWXY^LmaJU8>zT_WZgZNjLJY`h+L75{4K z_>OV0XB`Fs5d|_&fy<5h-Vz-nue$4##Rem>Pj^SGn%xl4pI0v?KN}b0jdNUL6>V>k zP+p1`*zuQ(Is8b~Lvm-xjrnGVYlT{7En{3mwn*d&7g?3wpI5?a@uWtv+%@Zc%gzmv zUoCxuTRXLFmU#K9LPw@%L@23KI94<48wPZz;@q29= z(3igzwqV`79(r`A6!Qfj8%g&5*{U5{i3h|)20B+&bTbf(b?-i9WH~B%Tk?@ODNVAG%%9i+q~FZBy~g$Av~*fJsk~_TTKAl zed#Y-nA9z(aD)#{eJe7Bs&;acTtT2*a_|6USrXf5bR#b#5M|gf zT8w?QyAKRxM zSbMoc;tyj~k_jfFwQFin_GV09Z;YJ79X41Dpo%t71K>Oc-Zh=2d;{6YWpu?Pc+sXU z$L0r<4?#Z|jjnXCYAr{xoEpm*%?6ol+(RnMFVOR5nkZzFWTFi??hLe43w$02Q=bnI zrY^MZvFdogR}8jCpY93Q-!&M zOeBe#oDAFd^!;k@i19+-2803z698bIV(aqM`bO7dlB+&`n04k6ora>1m0Y>{a=vnf z`t=YM9KFH)#If=j?rjsVR7Y|C&VSX8=oqr*c0bVKBblVKI$ys=zv=^AjVxb3XVPwi z4WCnmENbC8!Ch?!KXtik(Gc#mVOo4RcNBF=RKI$^0|-_zDY4#wfS_GNS?l3@?GG;9 z&`Pa7AzCrcBqJ-0Mz7y%N875#d^eR*^|Gj?TDMNfhwP{lzOxKj>vOgHV63$3jv>2u z@EU+Z7djlnp~gi>pECl@;CNpO#s%8@8(?q&_6O1VoJpBF?Oq~gC${fm$(wCtB4a+@ z1c{Vs7}T=*b;aT8dB>4nr};vmxLb6wLDPS+XEabR`n6aZ#M&+DC+){?0d6OEA2tuM zKanahG&H`x$l5&Ahtqvq9qpj$tN0#7sp{N+`d>g_r~{+1$+e4AT*SqT6Gi*8OqWBS zk&8?_2G?i<^j|8I%~?A_{akuOZMh4|8s-!X7t6aU`|z}`n^NG3h`1_~K0l1B1NU(wQgTZfOv?=ZW! zIB;ExA-+^uS7IrMlTC91J!)1PRaxAcdvFR>HUW)RXij`uE;}P6uAa}HJMZ6+{?9jj z4zaKa2j#yG753SxO@E{t<_PBq{AoXOR37qe<9a~Y)GJqt6sW0?{SQE@?UN$g21lUb zh^@lq7LRDFwoE`L$>}LXuvyjMFGe#=PQWXLZ7M>bib`1d84S*kmHYNyo7i&C`Ai{^ zcj^?4^XBj99fnC1+xH`IIE;=6azZ;R5&uve&y_29j(C57w^WF_V084R?g3_ zHj03(>;|91`b`rkav1hT#KXH@V);6^7$W}ccl-?v-lY72gbNN|%HD_yWqUYb(SE+f zvhjX{VO{6)oloUKly}!{qB;4XlDWeV8UJZqrI2|@snkpX5chr3`AUTA&(WTsR44F} zOe~EK}PjMw{Q3QSrhC`p?$WdbRZjoQXEvVd+Gi{qmJQz@0P4DVWf_i0y129DK8w zC632zxg_G<+%M&$gjZ*9nx7tm!zt%8k9PORXtBi!TeJP@3;Pv@aGc@cgv~!w7%WQv zjw9TKTi*DwaZ_t;aJ%8hUniXT?PceLmFUnZ(FWR4%e-~6Kh2{0IrHHhxt>x!AFg#5 zFgVR^wR>(MlmHKMl}qR3&`5d#D2_rh+SIp}^GnBdt23bnp>|L~!)CG$cgIZ0Q}2;w zcx>{ojWJYNGzTU6cCazLPow9!-2EAwkCfUK@t?v7RiEbD%#Oz4`q%}^bQG8V`x2B~ z=jBpS3Pfr!>d12 zDv5aNl?I~&`n-wlhUk~t9EsU?Z*YsAXDqQX0d-4@?+B z8)Py38T8(ExnhZfEUINlI`nPPADD7fV_9Lsq@!qpf<4+V_864c*aIt*e{H=+(_h^3 zw&!fj*?A%H6GQJ6J1t*BZU^oGVve>#HPrWVLY%%)(svbUIM2Lj-7)|In+Jp1^^$OIMIi%w@d9P_yDI~%aQM0ADG#j?FmA#uWr08r)M zb?5y+r0&nBV+zC;xowk;zEw(ds`7;G!#U?ehEITzu3)YDO|3Of_0FvCsJ*^Bd1pY8 z!(@(?NA@@nZb$6j zwTl@&cz||)8aJ)Km_hJ4jX!NFQN(2dyMZm@v5cz zE)dm5`Cicx=AI1)UEos3*!aopeQ`u_zWt5MA2R#H!Ft26D9IZyWy8g{p69c z_bI2n$S}1|5f+J<7Pa>UrZvD$_f;k!e4pcY`#X z38oM#Y%4D>p8{{~0D)9qX8rbDtI0rodqCY45dH*a;XG;Dsfj@7v2u?ZAd6Wy28g+? zbZnFMm$ylk`^c~WGc%_YB2H{2bp$f@gdLGYb}eUsK1m`Kd2y4GCr0T~_%z1s%C_bC zhIT1k^<(k_EoSOu?^Hy6F{MaoqN|doqqE(t;1MAB=VQ0M#{aHZsBTTQPibw;zwRzwP09BR#mUfH6k<6`i zdK*L?$Y>7HuBq`r$!y5_4DWq+z^Mr5(Me*2CIic*b$QkrJkYy}Ew{>5={Rc)lfEla zw%G8QdfrBXItI$Ef9;QXBqKd!)P-u(iFB&-PjJC!3sQ$95A(&j(&?WRfrU$OHDeym zgz_#Is$JV#H|McGKM>OEAzmM`;s-*Po)iFTs_!)H6RM)>-y(JsX%v+B1xkQS5%yrZ z&DmX@Mla5~GoI3$yhJQ~U3(q+!MCjI7ufaIRQju&T1Rn;_`zxHZy0 zK&?%c+^A|5z}Gu-&8}uNbUmkx2Z}yetu-;p5A=xYqPx+Iled((K?5O+lL#T74Q`fh zHYq#-DtFF)I-k{iQT^>jr@=l*?h>V>BbQ|8M}J@uQ0*w%9dVF!ia9nr&DX*;w^x4o z2zrARzWe9U&A!2I`_0)`!3Qh9gK;}w@Ba1FL8_$+J2u&oFa5<~;&Q>BnXTc&uyrPS z%&U*ba^GX)HWvkS$4(9^+$U_0@^!CVWlY~>aT@mIf0L6^uxdX$@YyU|y!QD35dAnU zklN~#0p8&)5D$)J)*}!`50!yMOxr!RTXGyY91g}pxif10w%5yStwC3j%W2&UhalDE z`@w3Wp;kS%@d|VP5_{r1c`njg=5!g68K7=sZo77I$Y}?aHU*^Ec+@A;odq*M&ri`8 zKJ0mSLH+U1ghZavYL*#Z`p80X&5-Ly#nQ_>fu#K+qh{+boOVg7sm=d{D0+CHM80>t zeeB3xU=eTtGP+Nu0gK&3rzA05Ga~m_VEOP|fbkP~8g|$O?BSI8O6aABr~PsXW!>f) z(ahV{5yV*#>p5KbXyYkEL`oo-#9lnpqU=w=J zg32Em3VV`(yvK;$(F%cfk3ZyRgm~NIAu7QLR}kNBN6k^MY?seZBt-BEYbY|X%sR_f zsQ3D&TwDbibH)Vc^|QlJ1JL{zeimMi;{IVgU=W^AYO1kQp$nF4fq=}wN`+xa8s#5! zn}Xa4=&0ySz(JbG7ep<^PQHy%og{`a20Xi&bNRB=j4IQLs_2?u2IlA^9T=&w(~<`zgLf5rd8QTQaE(kLxslI<>>wIgU)*?!d4-5Z zRCC2wl($vLdYvJprG_bo<~;vtk!F||Lh4DF2r@1lA!57Ma#~5V>RVIC)xX~8f%NtO zfe@%bx*u@#WyJv0y$;wU&U7wFZS+E@)#-n%1z70@gf&wAA+?UD&7%L%=Hp^E0<{~L z<_pQOn}cU2A@hwM)H=u<;Y$bg*%@Fteoa}{9vvJ7Cv)NZic8kasYKQglu~YMIZCtM zpG^j0lxs6Z^)n}Rd)yD!r8nEdIRHZ5TzF0OYTBh=!dR6(K+;Nn#c1lEtV}!_^(OQ9 zhEZ%mXek1sv=7!i9n5xjYBJD=sB`{VQ~a6Cv@$v^c}R>Szh5u~FPGZ(L-r)I>;;Z^ zT_Q4gGZb#oR_*5&A&px_XkQ@Wv6uxJ0mkzrLV}aQ0ZFK=o74Ui%JUsW{MN&eN@0S` z{aDcdbuS^na!Jmei`aJ{{uSFbjvcsRm4QP}3Gb&)2A_7}pif``&+b=;h^e(7w*o@O zJ6$25u??yW>9hE~QGU|pPE=(dn?pGK3khwoy(#C_9n)x0zuNV52hi=$=mXF`>s|7W zFjwLAZ)mJ_l}%C+oaLC*)qV|uk-bW7)PUv@2V7%HDgFCzJz1s4TELh)2tgVN49&1@ zSxQMOJ-oYTPRHN(Pr%;yVm0_LhH8z_&D>Y^q@-Qvy9{cKQkbuEKLq!<%*{SGK}#a} zl9cW6cT*mivtu`8v_2?dtAAH6`(x(#WSZxE%&p2lT34-uO{Y=dT501#*?A^daER|2~_i^^o<#I03{3~u}JoJGa0 zD3CuYS7@rHb>B$(BL3CBHtj{b-HsX$pO13_XJW_6n+-fb9`fL0}@ zY=KH;JB4V~$)Ylpx-?A;{?4F){`fmr{j~kI`H!o;9R|4%ymm)imMcxNPfjg9k>ScG zcx#tJ;VGy4km0THOzPm3=m`T}&DNWr!^MDN|CEwWb%NZaG%<*iCIyPClR?L5Uda6;H_ob2R!?aC_cc7O|2~)GQ&`b6qYMHHlvsU{< z<6k+n2E1MVnc7uzOVuw~>!{oocxsh7^gpUu)gBGW683w-+pf{-ren{gJgM)`a@;y3 zL+tUA-GMJYxjGuWh4X}SejR<}4{7tOln7=s`l-H#gSJ-_s1X;<>*4P|K*;E8Ro|ie z#+mhkU(cQoQfd(Z3nSy)V})4dX)tq*re|}g`WR3o~UnuMqXi1wyoBm zHC1YG`qXjZUZ)u-C!lGmK9_XQX|kqIv|~bG0ldiWeX_S_!s?c`Rg-<9>UZv!?eN-{ zGlPAO&Rw4OzXQD^=F#%o!rz{VXDu?E!?*W4)bx>c$lMdP%LK>P^fJ`9a|bLqF52S7 zE0w}#AT#98&u}{!3UzDfnm>N_PVB~Cu#NGP-YyZ$b^f%A!h+utdH{G2j3Ea%??0S+ z=9QGM8b+Md!8kR8^-nBQM#uSrpIwAS&Dz+sG$SbAlmHH65A^u-{!)?nupc`CR~|V; zdfAW<&ss~~C2h7Ti&juCkc(5syD;WSDq{&dU#HVSDvf(pbEA8(ex&`1cl=y5^x-NK zSOYkYuin>Ov%O++D|3-a#>3!L?+P+MoPoy-R&c7Blk#FG*GZs8DoFYW2{5$yz+A!< zhC^v^lkmMCZXdo90oc_~K;-oW>nVa&ml`Df21uN?89R`>-`Ti`8vk#f9$S0{HB7p4 z@Q=-|*@r(cAs=6T$R|qB@7eTDdT76>Aiw)SIBb0VF!cT}hY$IpBLQM*G z9}|@pI4u`kp_x76hB+S+bN2%hqk-7fPgHT#Ev=u6EC`4Nm^EP0Qu3w1?0!t6>}zcXyqbf%OPHaaydk~8`UsqcR0+)=*3 zNdr|Mppq1>*AN)fY5FgQ&p)_ZL2rt8EVavYYInj===HIZpu3cpS33R|I=gt42Dhu;M*@8zc`9#&3$aqRyNS-aEoWHLuxfpLw=-;{EC8a zC}l@N0;wFjYu^)E`q}jP%^oZmRPa&a0SdeEW+w(e^e`4{>Li@DMt=wtxVsPyH~ zJQ?f$l-EUQQ`~vEmz?CgN|CQ(5#vGKS}WXFo3<`QS!`_V(R!UX;>YDmkN@owlI~~h z{3La}@#r{kJ(dYeSkJ3lKa4I#(+_MZw3(4#YArsux{R^_(jt}Z#5u{@97HjMbw#sk zgYn7mZ$E3&@&Ots_B$afjr_RMY@PubpB={|CFzaP50-*<`2HeZ_a%t-3t;pLEUdz= zajHmc)&#yOH9-bNfAL>+NBL^CG{Rzv?$!z&a)m`Ba!2S{vFQ9;fW@fz+B}vqW6*;N zsgF`7UHImx7AnFB7`cF^j|rKY*+*RW5UCTlw(s9Xb%o`N%nq&MqdyEmSjCP8Jf|a3 zNTVdH>Buyvmp$IKsnZ_4CJG?F=)JsYo+y=OEvim#GmH83TI?m+0H|axXVfN&_CK}P z|6HowHs~PRNc~~sf694xu!UU4kDUykWBbUheA2*Xe*&HAwJf3K$g3;TQ#kqg-^l|~ z1TGT<5QW({V^(eZyn{m~leV(gr7@AlWb+;_T(k@s7Wu!Q^CXAmTs~+1n3nG@-mmPv zd1*|?s3$b=A>*#do8IS2mm6h(dMma5KrlLrS`KYIDX#=FzT_G$IFGqNRLqx-Z^0g9 zARkszsn4K3jGFHN^g8gr4i==#28^hc4R#7I^ncv;cJOz@gl%Iw21n!fv)umO~Z;Qv01PQB~C!|E}_ z|85DJ1Edy_zNV%p4xT$MyGE?%M6$w0g8dGWl%HBj*wih#Gh7*r2Qe=b@$Rw!Ls58o zI*+LxoXN6t+tQ^PIE~vhK7ej8dx;z>Ip$*6XrEYVvQErwGb!RT|DkNzk*{QqV4^`B zX{J;S4v*zA$8gZT%Epm9h|hAlyjndkmb8)Ti>v!&RJ!|QgPlX5ZNopgiCPVMe0Dc< z@%Y>+E91nKZ*1@LzdZ%WRo3WT98~JWN+zBG5epL(KxmNMjFKsu5>|V?CS~E?CScT) zXPv!42EsWny)`0@l)U`)hu(ZnG?Y>2D^PoAk_G78O<6q}F*%KH#M(KEsn`%|Sz_$? zY)+T}^+mZs-RbcQ=*4F@Dz&z)FD%ib(xVr5B)uM9A%CnVwHA-TWXuDDUb`=oT3V6; z5GArXZ!#{`pZn#CE99hmXt%k2E|ND9a`82~!m_fvdnL7-Z|A$jIE>*DWFZreyY#OD zgkJbYJ~%5C)$Zs^9=#Ty7REARCm=9Sl>~@ebD#rON`OgEMhEkaFF|1TkWl z-|2K$?G9)zF~056E92tp%DX+q_)PaxCPFegpZSTUbNE|Vw-c|Tmks3zOX|J(lCsfn ztTeh4NhD-p;(n~uckOmQmeFi?#VZ)s?r02GvAubeMkZoVzH*2#_@5y^oYFD#-1AX3 z<2#Z_L}uU(}bey2T4{7A? z-z5~8)=7tcR8pxs%XYu)_jZFL2IbUdcl^ZQ-~wrD>q_2%?!WH>sk{G-85R%~lBxDZ z9I>?@#`#vtc^S`>hIdZW<4XypSI&(2kEL}V>t2>dUX}L7OKThMOVxaG>DbA0)mOm- zdPt^R#FO@&x%R-5U6)ew|Cvz(VL`NLE>T#SwX1e`$7mD3EWEkvA#yd$dLS*!9!{hw64xV-5H#vZKoI@-3^Wb`8c)k!pwY{@)iNvOQ)BEU zFdNDATr$gQuwMRm(IM5`U^a5EC(8gCb%X1f@qQkUn(yi+8^C7o3sAR;m0O7WKlW)Z z6PDsFWowUo%Yjhv+m#Oj=^wuL0sbz9!h$=iMDHSXWoalFg1Ji|{uzdEdnX0SI)C>! z7R1QtM*qH^ih-O~;=^WAU~sw7f;)Gu->ALkX~9}W$~RnpaNhV~$f>_uR_w~YXJdHX z_@5U8P=|KrFm8hUmtl{hO|8>mF(?SJ=N}W=U+RK#-dO*MTGj|ys*%FIzrZWUMBB5{Ix z`@_hk($t@#&qwT}>O+5qr^9D_mg%rK+(!Li_LnUjei-gs+XGclx~snz<@(q8$NmuF zjha(YNkGcgKq*D}6=ltJ+uiS;@G3-3{|ISDz`pH|P`H6RQOwJoPmf0m@35XL&AeS^ zyWr&Nw)sP8xB>1l(ZsJm-tEBr+;C4)+2R^@AUO=_Nk>}WFOED;W#R{Ij4#JEIU{Lv zv6cL`IWxU(cev~Q?P2*^;8%Uha%ysU4p))vWr??5_~2FJtdaE%PO@-ts#9wczQ zEF8kf!d8&%XVtdXQ}28Ieg~JZT5;!=;mY}@vW`c}5b~#ch%04)l*u<^vx1mx!_#pJ zM{m1%M6lw12^%b<$yX_#$Xik4LZJF-)5P*G8Jq11zVWC|_TRJJyG11Bd$p8b6?#16 z!^*vYSt7G{Quig@dP}t1M~$UY`8~5tZ{7Ly#65Us@BU`E=YJdUu?AV2^;Q?xH#YC` zAHzYp2^RK%@Pnwzc;ijL`R7sQwquC((HYps=zLXAX}rP^soKGT#NPoJKb|91HRlQ# zOV^43nS+worsWm235m_g9poz>lK58>>AiT_K88{fLqJ3^XAHV@zfuwu~&zbgVui&HrTL8eN*6yw|{+n`BSW-Nb4FipO z8^n8|uL{$`+!I{itXlRw=9QCZl4vyh+et42Fd#KwJ;{~{PtN3`$TuO;fbWo~_h~YJ zVF4)kL_q$daDVxWqj&yi@E^*Nj+^CZ0Qsg++n=`M>~+|6d3|?YdV|q#q0#ok82J77 zn|#4wj{g#5LD)J@H}VIt@<`RfUcrImJ?0X=Td0%;VJP{-nzU@q2{B#kJ?dkI2UPt7 zV171i#LaSl*0~vvjV7x(BPRE(9~L0e=9g!CJ4IW|(>;9Na_J7}We{7Wm+$_FU!kPR z+5#)NNL*HecLbXTSZR2Wp=yjI>{dMkY8ErV6Z||H&7dG#ewG8^QDOrn=^*WwU<u><0q-nRZd_(F|GBNp^A&G=>N#uSz@b_zEV8>{Fgg7h zmq%!j^s;{bN&DS|+3zPSpNG4!c?dy1fD>IOt)4_fpW_ujhudT)(y|QnH%Z3x0^_%8 zH@L!Pe7L8Vb-3p~$)iq)^P!`?Xsy(lC zn%85tnv}cE3=JOl7Fva+ta<*wp_d-mCYa-piD9;MsECM(It)tGGj+i zy88PPlKdah1((1xIqHNm&1ez!I>}?pQ(^T!jMww{TlRS9JW4nZKU6%n`5Gko?2*N6 zd9z=S9Z`mZU*g7wK8o+o7CL{Y%ht*dsmy9cEz_oRUx;|u9?av%sYrLkoWjYMW^J1K zNT2ANtV9N{A{7&JWtq(AxLB&X|DCwPE5Fb$DHv-?)>yk;k-Ww8v4q~vx^AjHoP15JIq zW>A6WPG8x-7O8*UnnR-B@26U!D^xjes*i3E5z4?ox!baz=5be_VY0x6{8doMf8=rd zk)fJ%Z12)*PQ6+MRBs@YSuKWmMdWwpyJy8gvMa^m+%UPH8@F4qP{|p3PPEM>aqCAC z_&}Hw!eoKdI%nEV_AuJ|h)(}@PCp~<2J8QEU3arKneE{;v#{#UT~W+q$SUdWaa;%N zxl3MeC$CXZ*F}~co7IMHX1y`Nz#bqzFZ#AT{fkUR;*X$61U7;#Uh+kBW@}G=gAkn& z755&wl(}_<^JO2V+}hv82Bs1!0d~}M=l9w!jXX)>kfe%L->imC#XnQd@6+mG*J4yv zT2iPdk{p9pB_*tu`xJhd7WG@z)Xui&!{-|+EEw2-S9$@((tRrC;`BM2<&Mz7;qR|p z#dHM*=w!9yuz^B|t{Lcq*MzL7F@|}db#6zZ8q?L-c;kTkXphoD6bv<7GX`}*ja*PT z6mD0|%Hx+=6pv^fp(=cb3lq6tynB~irgzR_Xk8wU%WwYEC)oYOq(BWUSKF ztTNT%<9TGUFBaEY-hK=R?-Yha2nojhAr^`Kft&Sf)wtma2o8!b7*+4E@-7(HLCc$3 zdk&<^!bo-5VB;BX_=v|DUFt4Q)m#@A7w$G%lpY7|^3b=RW{j!FVu9J+6>&HtNj9jc z+2lp^xnLA?q#K|g0MuhgAVu%<&1wa zJ8AlaTT6O)h;z|)sB&&bF13_oD3vbc*aFyt|8wU+P5%por;%v2^^C|S|EmHlw-H@m zkkCjFjuO9hhuS=z1k#Me49z}pVGHNvIsk`pFsGrGa9a2IMC?jr-3{;=LBSqe88B(7 zzY>>uEks!PZK0zC@a^|Eq;FE_h_##PZ1H3AYBe6*sFjNq zPOPXu)a%@skcGRBd0jA^Bd&4&F#vq)Q1TL%3pa@%vXN@+zXpJp91R0*d!yHIxn)mFfHPr*M+cnP6sp>k<6DD3gx&0I6 z&D!+8+=c*u)5W^#hJ3U%Eb(VD$L}xup#g<-Qje&56BTxaRL~F4^KUupS#mV$kK1Ho zD~fBp&yP6u{&Ar8`#n*r5pVb==e4=^W(;FHK0)xz=62f)!c@j9UP0z_=m6B;B^vLi z@we{hV|v#Kw`8P9l*v&2n!|nMw;CLUSPk#To0O4DAE(jF*TstW$5L_+Em*A^5V5URz8L3l2lC*z-pm zhn-j)RrFhrtoLi6N&6dW^vn{CIGA0ih;Afu3Hbll%9zs9lND7^O+;MsWy-WHI&vPp zC0!Hji;e6=K-!@zrl?Xb0 zcBsHKYVwQh(3^x|qkWCgDfzo?wVxJXHQoriEB&A_-9^w&5sLu_oEYBqxm49~9)8|< z$NXPN?=r?aDtdgyr_|O5K}52+tq_cSl-PCYz>)8 zia-ESfy9+57vuy_B^A0e`rgP<9L#Lm`Yp#bJ?;+ay$N&^^$QHenXv33YP`HLG7_8d4 zu%M|c7XS*bjl>I|o>IOMav42N#<2QNOFAhB3+(%(k}*^g2FCB^Rf>A1s<3Bk*|v_f zlmTkbJpNlzz?EFo1&Du6oV=ool)CaR&%Hd6TGD3Hn{?l1EEb=h$* z&!1x#Qu-1T@DX_k{xAj8G@XM?iuLa&wni9ny|!R6y`xVyf?zTpw_8K8#MDB3w2z#W z=Un^p#Ar?K$)YZb+|aOr-6H}{(lt?DaV}6pO8i2#kHB?~u}BB9v`FhE(OC`2J38M5 zHU`p4Br%Vvi{|9slv}S=)H;cTqW8H{Xi|;b;l1CZia>EH5Qq)(c?WYzk4nn*b?2a zpx{0ZUxDSp=dAKz4k0~61+@7pCr*&brg;Wx@ZL_!?IC07QbLRsoV8s}M|&(VAQ2V7(4%$=t-n5J zoP_T!Wv5{Lt~vQSwGFet;bw&3J0_XuVmKO4mu2oTWu!N(E3cY5l7gD59m!i#nLKh9;|2!d* zk{YZus+9=X<=j0{t^LBO$V0W;!5p3>#q;}hV-d~K3_>B}JtK4_js=D|(`D`7R&6#k z`#gbtI#%9CT0P3CqfLe6iL&{hYa%*i@~nUD)vDRP?@&siuT*UQv1NXMwzNzOK)!*= zgC=LgX@XzW8fyrO<~iy%lOrFISFLiy%;5F*4UI4OV_at1L#OIDtWw@RI!alhl4fXW zZXUSme(Rt?HRom!VC{~Mhm zaj6+4t*0ZJ(r^?)hOOb=9@R}M*^ABo5#2l_u00{fxZn(`=V>@(*#UXGU{v&H?*L@- z4q4}<0ma6@NesH*$uw%ADNOtNn>j|RZTcVUELVLMV?hQSjz*2&yEH593F`Ia;}k<@ z@J+_F`GQeaT{z@ufJ1PIH1_8&T=w{_k;3CYgG-%=$H9ojRS7Oya1tNa-(3 z^2Q9m;Jy>q9YmghaD)Uei!G3sIZc7oOPtXL zah%1pa{8xcOVZ(Zw}aWdluS^OP`*6-jTA2IM_js|1sEVgPc%BibF$3c#_?!{0H6@^ z*P2giYESb#KEi(CkV=#g2a`*DvE!s5_@hv8M)PwiY3OEWyFhn%u(n1D+>7x(n}Grc z(H*b)*GNq!>jY&Jm@9OTm@OljlFu(1q|E=8;>-OGhOK?f!b7FZxk#KDG|=Dcu!=k0 zzIFI}A8>e8srz6IR^zyEi#u*J*q?Ns__7e9$l-C~C{vkmU#JzIi@%zMS?~URJ|PpN z)Ws-RZCqCAI{fP-LUsow^M?hi{&|}qi5;D&s%oue)t`B5>$L{^Q;I%MMjU>AVlayp zOM3xBN}dGH)n&hIo9M7I(bpPzB_WYHzfA83&0s8G=3jpw*MU@0JQ<$|5{E<;m@3Q- zAd_rDM5hKFuL(h^?wvqjir;X3`zEn)9g4PUgFRAowPuYubsYu1NLQyqA%->{tVmMf zC-q24$M5^tp{KWm+`%x^brtwUWpPs!gRaIW5+@7JX~9f#%lVHDQdR-tKP7T&4i9#s zLPBs?dOhBwe2P49NQ;wSuTWMWNtsKNRE_%?ooa4B0Uc(rOjgC3bma{%1DU0e=_!HRC1z z^LJiV+L-9}_e2aa-Xbl9Mdd3Xl!$4bsyi{ksfC_)+(0KMtLvF_hg`ra_P;}ZEeRBk z_%}d2`qwa3NsbT3-cuy-UY9!wG}|3PMPaG89rzv|PH6n>W8l930eFXgdLMNSNby6z zB&@Z)HlMS!kt8Wq;X|Mc*J$Lrswh>SB0i%GSwo1BGn#%1oduhut%6<#~e~S~fnrXnfm1?-UY_ z(&n|O@h{6ahs+Xsg*_!_+gsmyu}$Vdb!`W@mp?5=dfz{Ho6(IU2@*@DS}%-^k@q)s z1r3?0sMtV5Ltj{o-W)AY&J4W1Hrh}IQcdDY;;AT>spI`ZSu7}25=GlX{VZvOO%ZC_ zv@s{MaUw-5Y*48wb~6UC;q46}%czLnT8E~pTNY=L5Ase|{$GWCWmHsc*tG&8qlAQX zNDV2Ww1ASs08#_eF(62HBOoOW&M?3bLr8~ogMfgHbeDi2Dcwl(9iR2B_vic0pYvnZ znmOy7`?}73_P+MsWR7vC=MNIB5XT^bZvZmq!n`a}Hh)gWRYWCdJuRj;+gROYJLT{( zhhvbnSTUqjpQASH=WVZU#H*PsZv8%`j9rseLAzgC>FRAkTV71eCmlL~8kp`>wx10) zuzY1fp@D7$v6i2FWJ&b#InVKQ4|)HWRjD*6=&|$P8{CW%V^~dZ4Snk6SKUq>|96$E=4}suXZ(7!|n3 z)q>60i)6o(K_i@aDJ|MP1%GZD+H82`wog7w5M&Zh-jVBnQcDR2d}@C@JLwRX zJiDN=!t!;tXIoU*7_wx1J;QyNTxKaFVmEOYfVSkXyB)GjM`PHP`zD+MF6L1*+#3a2 z9ckzp`0ek6=@x(W$pE4Gy%BO7@8kK0{iaovxF2J>dp%sd50{-HW2y&H!qUP^%6WJSJAyK%Ik{~{1*R^D*4Z?(%}Noq_mt5OiVZ=akzhx zq13oR1)@P+)Ml+uoqeMo6)0t-*+%*k>OkF$AM2#$Q+DLqWwAjzE;f7A3pJYsm1!eh z(#uWMG+AJW+M^e4!v9 zs?`dUUpQ6qnBLg`KqfqXIA`b)o=&O3BI;7nnpu@hb+s2U9k?$Lmnjwt?}Wfl)Ahzn zrqEMEq~*i3?pcY@mKFUuQ$+N8vOAzvFbjQD2>x^Tlr zFYQV%Ba@vDR>!D)uWP{UA0Jb-B{To5i~Yv2%n?16Hxk&cL3ryel&_WWKCD5c} z)H+^4X%3@5gv#`o(!5loh?Z8^A$+Lqf-!CBbnz-L%}6%z@0BRutj){7gBJ{>?3dRN zb(h0!%l9{b{I9ewp2^j%Zxf!&=>0k3R-J{GbcO^UB%6^sn~a&>p)MC0gtky|nX z^*(9Ai2^DbTlZQll#toD3BT!A{!{7qUZedGG^%TE?!EJQuLpC_xh#^X()!@R)hRa9 z`WF6_T^qPZ*S#_|$4JH9Dq5R3k^xIEf@r;`Uli(6Pug6wYV6y zCAvo-*bTHB<5Imw%6i8IED!>HcKti2N3X&<r#VjL}&y)h$0nlj2VzV(K3{^e#Y zK2h55)A=DEDF;!jIXu3e2^dgAD^7BvQHhUa!=gwDNXmOGo6^oo=`sEd%bf!=Phn_T z?}z;#s7T~{9C&kQR3@w%S@a?fxtuMfoXv&yHQ0u(=Y#U3UqyM}?kxm0C>lIW2qkCK zfuO$Kc0^Rd#5Rh`3ogTv;HMlih$qWSB<-_pEOTG`Sm6tra{%^izb&Ovu4%{IEk_U? zqZp~RR!BM@TEF+x;*R=vm7UB3KjO~b$;Xy`y1(7U9hZ33s%Of2rWH|Zv(A5ilTV9# zn@@b)0j#M41p*G~9cN29S6)MfcMe}qzbGLqUE9<7v%;!MMwy32CA`y9^YzUO{WRx% z`z=|&gDr@NPCE6w?9#?`5#3;V^AnR~MLOn&Wv&8o83VoPY~8(^^j9F?*X++Q78|2F zdKJ!GOcuT4`g+V{`K=kunMZnuAOvOjTZT4;KF55(~-JmMo{M9KyYggX?ov zQa&|gPK_LJv8%w99}ux?N{IQD{1lceX5lRbcd**BHW&$H#1#LRexlDfAF*!(cddepj z$jmU}L0hE<&06gXcP-jmS_=Ef0@4aLYO;R}7_^5MBZSW-*T+U1t0VE4$jH8FdAa?C zM+OeJl4}hihlRr$(^Y&VNJgr4U(!pY^M-NxG;=QXzd_p7!L`J1Cd8T5-OQ3XYXg0= zY&+S+`GBk()qAHA$g2yr#bdlm4A=gVt~o|Z0K#tyM-t+Obm*fqBWiTDl+@kmm=Itt z84*&@(MUpO!_x#d1+weHzmFWJ2uVBGfD>$Szh+FHy&s=nWrkHl_k4cg&iiF<$v zQD?XWnzDR4i@W6c?T0fGsL|H$HTF}$2_whYi6NQu8#ZO%*IO#lZlZlCuV@jB*j+ml zx9o&?0VqAD`Pl5+Ctm0?w&HNp0L)W3F|}CCciD|nhh}1>X6MMid1{#`@*;f(nK^Oo z4!su9wW$l)AJtYvo$Dm6iz3QP8`bM)*8uvC%;VAfR8wkKZ<2!LkMuoBTLgyK1fEy- zZ08DEAx6}F)j{Y`D3Tri@uQ-1LU409|HFi`%j1+9qcCxPPt7C&zrQpeLZDaxX5CAo z$4HO6RM$P*$MUx)sI<#yCh?y>;&Kfw#-{(|F(nWOd*bnZxu+KQnB}qM)pO?Yut@_@ zf};_wE_4S_3Sr-%+Lif*@|3u%%ja)!1`ItGr`Y;|Og}47H6%0pZ0R7LfT$$MBW(%c za&*^gbXvmO_qWf?rMw9L+)`7MdT@4U9Cfq$7i!CApx{V>;J#FfmmLTS$Q{Soe3 zGz!``RzO^pj&942LqFDiFx#|Uo7_M)g+b8JB~7;G1G%q@}1m>=}~8pxXZ zGKCJ)FVfO+96R36MYaf;OSrEtgqOw3H~7UDZ<{o|7Y3$YQ`!4lukZi1K7^V;ECb(n zWEc%`g>i9dyFOmaPi29d+^L(umsZDN#Nd}X+#A)!v6Bs=i)_DPT)L*!iTCN2Sd8+P zlGB-7=THrnmxadmuE)-L<|xZMoZ)H9FIzD^x&A3-)bRe{pySPzG(Y@JT;cZ(WUdnK zuMHCO#R`|R4b$7zQ0VNQ6e@VRi0b!mbvd(1{}wDn_#@#v1FD zIz!y9b`5~_4MO78-VUHoxau6@*O5uS8AZ=OPQvI`SBjoj?!7`jS{GKc(T;=Bs3DD5 zdRL#Xk7_h3zm2O*j9THO;daRNza&~?+#tIs)>g*SNLk^i2wWfP>?%EbYLO_{+FNPw zpy0bu@fiMlBJ_+fG=|4~s}94vM#fIqDEAJa@LI}X>$_-SjyElQVWg~B_;iKl)g{^Z zjdD@Kq{qh3guvUmGSdezt-_T@Yxe$TK}7pImQTu<1zr=lLtxA!oMw^HoSk7}ZLjYq z`P{7!6AQeAPJp^hQ^o`6!SgNM`JR86d$(pu7~NcROss7!Bt4%I!F6)P9jdfVuYwe1 z)1!crx}{zKjc7qs(@u@`GuB6)7Q1FtfM_Jn){EVHVD-%VU&+9d;}H_cWl>$q*er{H z=_0DOf>kd@X}Aq6-a7pY{4_CMT9_*(veLwNXIuwt`{gnB!AK&&N zAOzxa!AnIS_wMCwPY<|%>5vp}f`-hs%l!qt0v`%~AdYt*Z z*fiwA`N>JSTybV}Kyjw7KW0t1i1oi^O8}#3$QZ^yTLn3rw8>%&8$ zi{-$Q#bunykZieRY3CEp=q4fq*TbA#$iith9u!MV_#i}cO;>Qk4n2+-FIf;^q*u2P zvJt=591#??pC4F|a6KUSK_4zo0qBKYZTRc5-C&o+c55D*hVO6@d_}Jle~pQ_8~36$ z2Nn!@4oSh09lw6*pngDHHjnk~f02c&(CAir&V$jZ29@oFkQSdKk#Yu&jH$!mS6I%N zWeO2szbwnXRf0$u5A9iCoq`dWshi%Nd&#zPp2#^cRK(a$x}epfc26zfvvL;g0{iWh z`%W12Q)uC}y3F-W_7sYHBKg4U+xKUyBp+6aTg!b7SsZfMU?=5L+zT92k_9ZPwBb+- z(E(nJkLkcEG;cubx(Vf8+)}XRnGUcsWf-op;puY!6YP7E>RiQ^ zf)rw9wd#!EXsZ^Pk=oP02~xiwj_#lmeNyNuTxP%AX>GWAH)q61m4c_ z&eUSl&tWLq%Lofej2QukALL7zK1w6B(YKS>k+!13^XWd50bCX|)7Mt4G%uZ=6mw=M zG?Tq&0E-u?71V;nWHbBM4#%)VcY=${mDlFV8|2zv3JW**g>}qGHMD2uP~@}e684EP z*X1R0R=fF8T7lUhs|d#^C1FcwgoXX)lbd&>Qai+?LktWm!fcbn9>gFo8%OAu5vB{D@JkD*J#QZTpQVx;%aeKdoan zrF98?B)Lb9dbUuQ&L^*wy7q>z!s9Rmlh7uwvW>wtTVBMR@99;zLjmmUuuF+xaAXif zPCNaiwhc5IPE9~q+jVChA8qCfvuk*vWj^5Zz9&s?Nl3VWm_728!U**MSO8P94sk+E zBm+3mQ67RCk{zCRaVQEZ;PFWoDX;Q>9iD0sEpYi>VJbtBZSnuWI$9;=;{irGKc{K2 zGYavWjdGh!S^&F)W(>DLcJ~kCKX}b3-Q3i9k#-i?Q*2|d@`M&h|6zM}`^OK%b5v&f z3+9G#>9yl|c^*(dEG;$GOFhP8Rj)nee_UtSIWa)ZQgA8R6Z5qeGR{*7ZwZAYlmwPlv5Jo# zR(<B>DZ?l(nf>1J=54I15%g1szN&D3w21nz+9LrKbyaedIVeOtUzK(x9? zCl%l(DY;akh!436AeVtP`S;I+lM2kUET3EGn)jqS=+6$TliBILHKu>*MMOG5*WUi) z!QIu8CmU}i3~F|8u95lH!`ryICQZ@%wkH~+?KmE^b={FQbcI^NseSHEOg0jrRCLT> zn%kz~PAHTtr_rT1=}UX{v(v4Y1X6w{%PGWP{d=p#CKMp$Hcb(oSShY;s5WyvG+`rWVRlBw&-9q;RbwI4+paSnz|o@ zmtXKMCT{-1!fVuqGL1zwRV5uPTcT0q`-TqODyAB>{ww>s zP|E%Lg?9|KXvjTfw`g^A-5o=DiM;EkW7^UKwv($c=wXhyYra}qSZ*h_(*E3*kY0!| z0j!R_x~HP&TQfK}C!&(7Z32Oawx8Fyqp1x$Iy&O=Xbre!tYM8cBHw? zXlcAkQdw7Un2Har;eg$z|9|cjz2pOZIuWlh_+Kh))@9tcqy8ddqyjh0D2 z>X5`EL4bv489_+90YEPH_m93&)3xvg$#v-7b2>kgZ3%Cj0R_1XOu7!kz`=T)K14k})kbiCxV zpQBF}KYg|?{6BSd!cX86fH!z zJPc=<>5kM2T+!o8t9P7@WH^Y_tFsqwa^DE*lDhBRWXR5d6ySKB8W+POdM5R>z;gVq zko}ppT8dDA#ONy0vc!4&45~LPwl)*Q7IyB402&cUDG7BLEc>}3_stqXL0xwOl@oK7 zqFg|E%)s$!`HxRRHilACtjDwhNEN$H0Rw<31FL4<78Aixdw@6PTN_$x!|b;4aymVIuF@ZZbGrK?6hxl?`Ca+VpUJOO0BpoF`diI$ zsHWDVm(~s%Y(Fc4PowLUrAouSOeE&d_*yzhCgi1+PZFn1Xb;SaW%Vuh_I7$>moBmZ z{68&a?{R$9zcB{$rjuo@)Rk#~u}p9BHq0I1c6L32#Qp*E{!jz7i}6Y*=^JJvM;J|; zxtt_r*<8%1Eb{43k8d`WrW)21$I9r>R`Y9OX)f{KRW3OiR>-+)VAySvwp6<9pwsXPpJe#RG2hvcqo za;g!L{BWgEtIu7GAC3)8DcJ zZiGbGo-|a4hl5i}Cc_mbWmKmEtmjzp2U)(-CTs5LaiawuMm-zG_)cwbeAS&qytkq8 zzYNcss$%1({rA80s5>_H?Ad&RP2q*Ay1z=gbw|Cve`$!-I%0%%n-=%_O*pfAp!_!^ zQ!iT`;M^-ov=4(R)|wT7nWvsaFV=q1)kJ~Sv8Z47{@Vp)t-~e6E|01?VhJ~V(15p? zRMMNlD@j!zLlPY~Ili`#-2H!JQ-@ta3SH_(B!v(7+ag%*_l$lMf7N@)@E>o8PliZQ za;YPhuJAbKF+b}V?S2h>1#Alt)_0*roXG20D6$@4Jmpys){+0qq38DgHV58TR(Hg~ P9pD31P?Il{H4FZKf%)ad literal 0 HcmV?d00001 diff --git a/temporalio/contrib/langsmith/images/temporal-ui.png b/temporalio/contrib/langsmith/images/temporal-ui.png new file mode 100644 index 0000000000000000000000000000000000000000..55ee90970a2dd2e6cac94ffa6236986ddc7fe700 GIT binary patch literal 46549 zcmb5WWmuG58#OEnXLkuts z-yXf6`|&y6@BQ)qfjMRdu6^x&?sKnmt#w`@s>*WsxKy}Tu3W)ake61!as?9#UXS5m zgP+Dv#2#F^^6H9$^kYp=!|k-|o}@D5fsF5Ny?#rK!}2j8Q*)!?gi2l#ufZd3PAxRz zPUf2j8!s@RkJVzBWTNL%NFICd_3zC)NSaJMmE7%bSh*4l^U7FBpY_=@a~~WyeYw`x zrj#Zs@PH~pHfzWd{R?h=d(igB@0Y*d=`Rc-gZ}j~Rc3p}f4-YFRF7?Wko)Hk(cdn? zc#gFC_n-CKJnC!9NMx)3_nin?W@2l>ut@#`{ew<|U%duolelBhjjrdJboW<_UO(|d zwL*;SdcB+;CtP)l5iz0-Gq|dYHx_WIcYm`x{BDX9zL#BpCrh)<-AY^CU*lRyJH#*2 zLXLv2s_cDx^Q)M%m*q4)R$p+3;F#!{U_L5y`uh0~)C>Ce)7M*cl&vQ{pHkwb>^NbR z7)uvD+F=;g&bTg+Li{?$QZ%K_=-G1XL;m^@7P<|iyI)thUd1=rc2v!FmYR1O+Y0$t zZ%lML8|v@NHZJ9j=jF8XU_^~Hu1^#-we!4QNv9n8>Zg*exa=Tu=k=?FsxFkQF&O!3 z;fP$fvjDgIjnaXuDQ=|`tP87YSVdDOl3z6?5=@<*;_@0jaG339H+|O2cjJLzvDF$4 z7MJ^tALQ9*m|Nj)7F9|Nl};rG>B|ik5@h2)VzB_9@va{W5t=BkoPJHjA20 zTURN)D#I})?zppNO8kPWGiks!@zF&Gw-%ReRVUU6_6W`h?#RuNTO)*P@NB6f+5R<# z18ss34NqpndQV?3Lx`V8Dr6d*yLTmU7lM0F7O=^bY{w<5yY`jZZ7g4d4cvG4`#Wlb_=$)yQ>Tc! zI!^DC`){p&W+#{uuUqPCNCfq}-_U&E`}+6VmF@Pq-(XQm(42LtKk4gSqB>*uiKCuw?o85q4k{d7KPxbUMo&rnAfJ%^ zbIW!D;I?$$@`Xr48NyfFI+U!23v?!IqwwokvUHPsf~G+iqbr8$jAC~mDAIP2J^@lr2n%frMc-RG<)Lk zvYJ2%MWdX-F%Tgyrke#@Y!k0cYgQG3uTq5FyJKu? z0wS!#SzWAGuiC!I#JF6X=f|J9rKbR)3PQhmPJ^EQLqn{wh%&L9F%GO$seeQM!+lnD zoPHxaErS;8R7Tlvq5YC*;s zAaI!c8V_C^uVZ6f52Jm$P(fKH0&Ne=dht;b%t_L9jcR*w5E$DZZr-wAs(@+QW|jzA zkLcJA7||{#EB2pqnjx<8{Z1OQ=$RRy-xCS(l0H;BD~KDq#_!vq(0^+B?{wvBs8fQ; ziV>aa(^39Z@_uu)FiZi@@iSui!Qox4LMEGMFbDWA_28zxgc8;Gi`Jg_u0-C9RZrU( zF4PJP83AH1(*?CH2SZMRnQ5A9IA2eNi2V?O9)C}T%(;ld2Hjl;GW@`s=f+%YmE}mc z?o&?H%q!thZSjTUKdOzOEN)AU^}Iodb9*fR=NEVhT)Lr!cc_*5!CK7{&U~(kx zjbH_@=;+_Bb%=-pJNO3;n?p?2y|*qCIcu(-_h5ssQLFMSFjx6Or=>Y#;&&VhrurKB zudn+(E`aaPa(RITdprD}ZK`0%{Q93Qn%$uk{yN8XMN9+fq_u%Z&bz!E z)w#Tq-&E$dB^bx4J>ZjwqeD|913Dc3-1E0@f#@_5Cu? z8gl59o3UD7^GX~;om?v>9X?)d1SyN~sXN|jUqd>@>dPVG`3ckDiCmOtM_asKod^a` zmF~ElF~P@ZhF*zcc8fs2@Tb8o#6Vo%^&10c#ZMPhwte=1V7y%+I7&L0!WBT^?NnHg zDn1#YuY8OK1L%}HNam^X#h{ul3co>0&Ff??K()cNSySkiYmwe%-Kt;N;|j#`oT5YH z5t*RvL@??6C4twxFC6l#F+?b0zKTV3-(MeCs4pfW@!9Gvw5hPrFY_ zT-&on#K!Udj?}LeZy-!Xr7Wlnk{X+BV zo&9?u_)P8ei6Z^6Fi8C1c-aoAyTVJHCVz862XDW&^Do7Z8*nH}*hcT=q3AWNKMe38 zKG7{jm0(1P?8F#fSY{iE^=x=v3KCmEX^jEUIImWdhxa;$8Q_99ihC@0Nz_-Q59tS~3n4 z_AQ#X)Its>=aB|U2dhs;inIy7xxgYv?<&}jy5xn$II1aSiyhwhnSmtPP-#oOiA~pZ zBvYU7w%C}>>g(W(b$PC|0Cgz)7bbh@@|k#d9PcVgYJM3^$|!5nC6EsL$eqWRClGff z`#4xSmaurU&SM@URl<+TX6%dBwAj5tUN>u46k!+%G+*88lXS>?3JDVyf1Pi*&LeSTWBWto*_QibKod-S%n${0zUq?lsrZZ02b5}%6hb?%RN)U5dzV?i@ z`F>u~-J_iH-$98OKN*}z=aVq?Gv_yfhS7Q68lf1W8lh42k^ZC*#}h(NKUoe_9e!xh zpB@0ILWOJz*)NW4@at4BdfcQIysB0BEFdasxmxo!2dXbyDe;y}D9PhX49rsB_RIb8 z5RHO2$J>)ZuLH342BP9TlnU_{{e0g$@$KBUtIxZUSRq>T_OqQISt8LIsxvf_yLRd0x#QdF?mV;rM$<%AKWu z%lxZUDIwt_f+}*V((7lGJdmn!zXy%{C=iFpI=;6>MBSClO??$JpwxLZ%9HtoI$`;k z={eH8CyryPLEPVyGq@%u9F-1#J%>Jiv z@?d9`k>{1x`6R;S;)20sP)0^>r=ux>aGIlZ^8rrn?#b#)2J4aVMSuR75QtRS`8I+= zK?x?CY(*Qr(QKCeVFEiHlZr_ui&!3Rr6+ZT=VI@T^?xBpy}C3T3Q5l!FuwnYr9_)V zf_g4!u=Zp@q=HY~tt4b6(6Gz%g?i1E3N57Cq21K4>w9vBC^)N+lnIQwt9m$;?QkJ@m)19}^&$cUm%e|-R`_dPaUTP)ho;1By z!}xFvWY8lbln*BbmH*%R7j8`ykI2H_-`2#pYT69xyYvqjX$^>5S2C=|sSm_z$uh_C zyp|X^_?geTw2SV5T(pxF+QJjS*jaTL2)8C}wU4_*_xH zk}i57L?`YYUNBmqHxNb=i!d$D7_1_Q@qej}_(F+MBH$Oaxq_a?J&rHO8K>Trn?7n_zU8N)c3zo;ACh8#P7p}w)5qL0xV$G`<4b68y2q5 zlHW`*2`=%5tLG@1o`&v?4q#ghpaSfmjo8dkP}s=1rqHNgyG8eqf>XO#UE%%Oa*PSx z=`vOhPJJCkcLC`u?WknM!<_p(W<9sGV!m2YW*c2fAnBnO^AR8ankYr09K>=Nn^Eie z`D1xQR*1SFXP72!0fWqiiM)6P-$Tis*2^Jv#JdQR4pk)IIIm5@7whlj@UnY~i5vm# zN(oELDjj-}?btC(Q9dVWA}-iA<3-xcep-cE8gB-D)1OM;L3zgP@<^W1V>8S2OUjGi z$1%LvY%R3GXT5r1{~^KQfA^j;k}ol8TFmn}@15q(UCyCIZ`CUgH_6|fguec$Cn1eY zr3i-X8aMi#E7J&j;=tE<9}TbdtL3R0*VKN~9dLU94!n1Uj~+2U$v9xGvYjjl6j!@oV8nNdV`tIBEAqcsu%A=8VkwHE z#BXp=lZw%NoXXl*zL-`L-}n?gf=EQe>6o7N(^!C`B5$*)EKeP!Oh6Y16L`+4Kw%|Y zX3`$R@c3%4k7=0v0Xfk#WiS-gI(OP9X~&d;$VMXVlG)}D<*?G7LC8?PhDEOr6D!q0 zF3;F(``!FlJu$?*k;!C*T3XiM>ja1yIeTtZD#jB13 z)YK7^)j7H_{;^fAZ0Y<`rf%b`le$yxKaOM zf0DJsC_aR!4S%wraP4iap4R81$CQ2P4%H=puf z6JVOGEw(6`%hRh)Z>Q6f4ucdJpd7yq$8l%`PQzDwqojgv8Sl;c$)C6mpTHKUzFb-I zQzPisJ_+0#En!LNX*1BLF#~P3-1>&|%Dx@V@;)t$3%__V{D(OUV1)+}@Y;?|bjicDwy~CCiei zlGrcdI*DU?PSSLwRVHETUw$h%#4xiXb1ZW$6MfS0lR))noL39zN8j+$in)2Oc}`dD zXrhdMt#otmRgw=amH3_CLb&xmM;{I9%P3)smr>7Tp$v`dt$S8V~;0ym)+9c2GxOXlE zK9MKsr#kvl^f@IzEzs!Mf+oWaAj|)hI#132|0y*oX6%=MQWL{s2B>oH*(E+Hod39b z{k3JKByA4Ba(Nf~Ir`$lT6nKl z8SljpPk1d}JEm;X!{0pU6Jhc1kxm$N5xikA8+}(77fj><{!j1ERTDYUcXD#?W`S~N zaD`5u5V9E|zWjbAnlXwj($S$H}9A^bv^43ktOYX-VDgq`ZkKBveL<2Tg^U) zpBR6Wj)Rt1Ql_dlNf6$<>?rr0xd88@t-|rgkH6QrUtlNjUK-{!Ing&?UX0aFa0o@Kgc2HwlCzym}X!sYzdNYUkd3lFPOd`t4Ye`|ZM_J|-F z*H``7iF9;y`$tEW6SrBF!=*!Lgm62Hm}^3ivC!Ao38YHa>-LT-Q_0EA`jfSGoX}NC z11YVjE8sYqm0w3EaMOBc2){qWr()1xIjOp)7|#>IBohi4!v%PzT9z!B@d=U9pEWR= zA;wk9iJAv?Q+@2q<(zCvjLkKlDensx?>MsjDc*ip;tO|Y>tUXIAEMd?{w-pCJ7mbt z73mcig{FKJq{Dv_&0 z;HL;~cHtXZQgIbG?f*FBi6S$ zRv4t5CTe<^RCc$$==ss6a)_x+7(}$YhCrgN!RJJ(Q#&Fm zWSVn9XNl|jjFUuzN)|wcaC#g3hpd0{6|$cmdv^14iQ@6~{2ffcKdki_$Ce}HnVN|~o5W10%OqN$WiOQ|l6r48){CHi)}-nu zn=#uQZxb@qXdD?>?*(UqzP>uKe}3l)$`u!vjO*==nER5&at*VXyi8aVx*((1zC?!G zouvC&&IqesG+4pO1Rhv}{RyrNlActWs2iGiN-Q$%v^ZgokWXsPUE45|iPbHg^SJC3%Z@ZGgSqdQt#!#J#;IB8SZt z$yDKI$?7hhIIj6$cJ-gB4wuPZdwUzqwp_~ASWzLMc4uR<-IRisbt5@3JQ(}UX%r60 zBd3~U-a;2kvU43f_lk*MW&I5Q>MN&dHjql0SfcOq@?Kbg(fJ9zCNz;P|P2K1(X z!Fb+Bz<@pi3~1EAX*mHPrRdS`|0jon&w|Qk!jhj`aq=?3_I9KlI2S$UFENh4(X`DW zs><2sFjAi!R}({R_=_sR03Dxm9z7W}Y-q7#mTL$ys5{QfubJ6hEV-TAQW?z*sxbEB z0h9~fIRQMy|5yUgO37@o~rHvtsp5Uq938w!46xop4lN2V@>jTI;SkI8M1b z6@JmUhlnq|6+c$@Y16d;6m_d}D%fg22-H8vrNG%H>9b)-h2!gUF6tTI-@ClXImevF z0jC4tm%N|+mewdRr>8?!V6Y&`cer}nFGE@HewLm#X!23)+HnyvNT(eX^V!U2=WWJK0qXPrR!|wRgO;wLicBDhijLZ-f1Mr@!72#E6y4Nq$9S zO|1G_fZN*+acZm3v&eK7eO^hN0w2G}aHY||jK0zx+gDhz-^qm6P-mdz!36VMftF3o zu*9UJV;Bt}M=F!9TLrBO}5TxW&ky^l%qe65p5V z*rGEqHzZ(jJ0%seHsl1AxkZ%&SQYJJLpfE)Qox52LQ~!82!G(j-_;6?ii%pT;V0ri zO;y)S?AAG*?fIsR)EQE$adL z45wr4x&c||0s6o6lp(+&4}X%uTj`3CvWp+;_;G!&2}1QWMG!y3U%$16-bPM`g0IfW zo>R&aj`ThKm8Jjfm$m4<>YzHGJ&c!w9|ExPsU(J<$+4ks)zS#~(|7n|mM?@^mTMt% z6jI3M{i|sbi}l;VY}|XfE!-SY;z@6j(6JEAx#tfuT2HSZm zuy!9slsVEwO=zfvgA7cfgpD0)G>7^`m0~1cD$7|$#?FX;))7RDHJ{Z3n9km4LSLjQ zoLtWze6fK7^k^opJS`u-9sNpi48tTn%iiNIilkvdC?I=0cIR5@^{N*EW=|4vsUrR| zas#;-xL$u9Wadaa=&tI?MxSo^C=W&|>%sJt8_3y2k#r)Vyq^a>J32oRLxc1qjjN^~ z`Yxha-RpL>OHS%&zEf2nt?wM)a$`&4>1sC$MAM zO^1%Nafcc8VTb+<`gnxcwlhuZ?T8lnlaqT>eq8?U=lJurMUTj~UI_ z-NTw{B*U6KzqT7$4j7?TC7Sr{nQvhrX5xp3YAYvFo34Bpfu=GWRp{`6Pq!KIZr%it zyxFj0tY|to^|+f(*`AUaWbiVlr$(*=QcpNu{w+Q&#BqVRk}F-$I@HQ%)&bg68g_pb z6?ACd*Up%Pic>xfOqYQS`{XbTm@oyX|SwxF^;PA-Hx6qK$qsGZ%S4~wuyb( zLXfGD4+I3vaZO;g3r}tS`jAQ>uoawUKlOz99SZL>f_HZHLf5H-g z$ffN`7h&HO_Krx}png46Gsr425U79U4?L*wr%uuby!!RwdyRU?gd$Ev7QF7dkWxy0#AAB5KV#B((yCctCR82UxGeCd1-+B{mQ4XOk+8d2A4pzg+1L51VLZ>P`oA1TzHH%YuA z$6DvQVO^&5Xw|jCidhI&qQ(r;wRvv>Y07e&mHp$#W8&T{&2#&p`UnL9jLpK5ode?h z(Q@);DrDL??YCQ@G${QfwT*}ioe(#1$TFPNb07bs8mfvwc^%uO^?s{lCg+bp#H4CiwHbD6;^4ZTGw_}WLbs}k1moAR-#+J1|nV<;`<}> zJNgA}f%e{NFn74$OzK57lJPkVo3 zFVn%dBiMKUWPdI_-0$!$5x2>wFF@{RW_4@RbXJzriHrp&;wk}$dT_tfl0ZBa$B-HaV}+_4p*KCSfs<7@FY&MPDqlW)|>%*f()ztKOuk&-^s$ zrPqsRAh>1!rU)9y^L&{dT<;Eq?xCm7jdFVE8KriKVQcdISb?#chmg?rT=`x+Idrnz zLK~je?|#EEuhwSV9$k_$&waMjD-%DCpb`qqaGD2}fQ8Tb?V;q=XwD=aAaI)8D!b{B z)MLs7IJr~K1BLzHCIb6^@;J~L-@BmJfy(%LP!vRqE%hIZ%U|hR-9q?YLaeY%%Dq3- z$$P}XlIfFVKE)bFw*7ls%n$pBDG8Vv4=0vwRYuNB%$ov*ZZ}$;My{_9WwGr-JcH+j z?C(p@3(kD=At;)z(CS1yM3`=6B%HKi4=qLQV|2y)t@UR_8Mg*9K23hmqb!ihYvdpF zL@bUA^&f8m04K+26#mzS75& z)IN(+d-`oDFrpXG=otyZ-y!E8!;e$1-!SsvM;FDc`AtV`PtRX`=}3Ge93~RiqpwKY zyOMBY_rOSB#5BP3pfjd%P~x0Mt3VUKTHq#5bDKge?VX2UQ2&twWN%j=Zk$K{#34wh zSQgOq^?ZyLf+ZJGCiE(k`cZ%n|8}vg@zi-s#`zo zC4{N~CEfP0rPHfB-Ow-rz71-#<%h7(Pg8);Xu*v_*fAOneqVqT%D)Ggm8t=ND>Rd3m@Kq#sKM2jka$h>%46qeKYLamhniiu&E`qP_gGo4R`Ou5 zsAH5{Xvf_zv+fZfOb_~U6@QHSsl8FYX6nAUX+pm?=!Ki%gtoi0foD~AVg&P-wE;_rVan#XytRM!>`R-QraJ(}g4i3l=vUfYy*-hS6|=ISAZ zyk`Hg316SMmie7_frYKfy`H!k{`k9Dt4UYh=P2H&Zo2_$br!{RO|-r1ANcPRagwSD z%`EBYp(n0s70{-tapwv2+|#OxIN@YQbtyX9XyFu77Hx1U#P$I9kPnlaEdEv>%|j(d zuDvPrKA@Q(PlJ=w4v;{thCjD2FiK_UZnx{!lPpD1H^5;l`NP(%Y}(|V%7yQ_P{Eo( zEP%o$iv3!~Xj&4Ln45c`Dj(!Jw}D@88th~*>TqPptHO(j^TtCxUR{{4*>*Xw(Ue7x zcJ&uNyIon6>ecXCD-BZ0YQJk40kMnaP<3I-V`a~^N*3uvJNjP1AwX*d`rRgdS$9)M z@cX#dFLCm)ujUUQU>QP=0(!Hb2cO7@w_Se1SWhxX7*W7HcN>n`L{ zjuK)cchqyM$oJnc1mzB}319V}9{Mr7424 z}S)^4UAvZxW{VKOt+~8(;$F-C9Qv zB439Axi=-#40E}ai)B^3_fh<`60nyP`yNm34T!@<-lKku623lK9IO4oKZv^XG+C4@ z)Ad2SQXF9&X*9@59W3f{t~vI-l2n4Wi03OvQZ5}r7_Yu$7#VjNkicuak3`RocVKac zIf;@;zmr+qCn?9@&Zfu53BnS&zC&OGS%YGGOiu4v65w`V*A0X8dvJFJ=`?l6&t^Z! zXc3;H$7jBHCnc%YlK)PhZorpGm+!;-gIupyqx%VYC!cFYkm~9^d+h+n-4rr{@AWap zbHf^Ln(?86p7i$wUGnm^5Drax15Yr7f6>DR18Ltk4vfcmLgWm~r}6p*219_Xciox7*Q>tB z=XrGciiXfEb7Gcf6qca-!-4kZ3+DFo!Pcz1GRFO`Fu|&5MU-W!>n)DDF z@Qwpdh>D5#m+8kZa*_I8iyI$sb*VZHk!mcfdz$q99SvbZVk2r*%_lw|T{B(=Mtgs| z#&DS^X+ZU9hbgydRejR;WMxO{Oabi35E9j2{s!*?*PB~RLB&B+HVJad8jrAjG!~>-|_GW#KjrSV; z*q>J<{jsJgWEc&mjM>J%S@8~2m~3gA-@g&YObV@tNUypo1-SaZ3LQ9xjwdu{j|XX3rnx{`(A>@Tan-KF&xFMYF-4Wn|HBRHQ=Q{{mZHp|N| zBp*>%hx5VR|LXkmu%t}pX$>)S7+itRihc=qgD-?9#ZNwJHG3qDzm5Lg&ikC+{lRZ8 zo{04u%4rg&>uIKndqCc$I6vO$O#KE2VjEax`jaJN6(G|anNC?`6q1%AM42KdG?cy~ zdSjS_lJ{&us)4uGdF%l}>d`8)(t)=s=>9$S^=~53p^zpOa$8LeQI}Oe>J7j9rYqUz z*2%d=OS~@ftcVBPxo-*DRTFTAg)a0o)vJO#*-?@b+fkh=>6sl1$BIaUdVkX4Mk5O5 z1K9W{ru$U$u+G5;{w`CjJIK`1JzTMYc_O)G;ja`26uorr;Ti2;hjyp?&J6ua&L9yk zh?Gu*7pph6=|Z21YN=Ad{?~`(zat|N$jDIKCd}Aq2AAh7MQVipSjd2TChhgya0B(d(-m%tiBT!}b0xY5wU zdN)gFlFIVO7wY>KgJDq?s4vbJCU;Tn6+MSmkpu~S&D*2%CS9o^o^^W6tOe`|Jx$ba z_`)PQw=){Q|M(UgZi>{xD6)|%K2Vfhc{KFsX3{C&%Zo#SGw3PbFZaBxYqXH2u^-9^%gHCcr_1-2QMW zBkX=mvMXK_wIg>-`DT~sIOAccZy*DwP4Fj9 zq2k43V3cw*#EuY?2EliKQc_-{?fD?O>=q-S{=2`hl z$T9s)vcRx%5$eH*Ebe6!ivFpJbNfjjjC0n*!Ft=57Wcp#9EnS`TbRrqxCBY248gNnQIOF&VyvH5pAGE>v zSg&!ALG(qX{47>cMMM5e_l`U|6{ZQ*9 zd4Ky<6XBE%TxsMl8D%0Q<>3m2m%lDQ5&g-x3a8pHUF*#tKYQ=2rn@8{w#FK+(@A)T z`(Iqo8y^uxWy)roJ@wA9iZzBp!vTNe6M)L`@?F6!Jm8l_57tamCA!3j=A~%wPGOP&WDnQ z0{MdELmq*Ou+)AwaDSZIe?B<9!CP<6f)kKwFcFtlZBXo|o)Nj1D@u6}(2EIf_n)TJ zI^OQlvU%$~O3iU_GWioiI8()oOTu09`L*+T5bWtWOVD7ds!6a(NC}5Odru9!Vq!P* z2uUyZbr0i#!TJ1+4?uS=Q$bR~R;=|f6WI@MzFxBn7MuE7T|jmh2dZ0K^}NP7xar1x zpW3Q%q*080L>vQ6!vcS}kzntB|8<=T_naPb79$Fi;?9wwuF21}2b0>t1R&u9Gh5S<4rB8lv`9R11EN4VZTSk`O3TvSI;58?<= zby;QJ-P>zIXYLI^3;)APzd}P~XZ2h-APEn_lq$h?ik>03v}!B7(48Nvt4u)x|g3YWsPC)H>3u0dJgk&hUf!-oSSA~L_e5sNyeN#1MZ#`deRS=jhu=TV`!|p3jmI=;h_e)G<1oXXs`(oyB7E*%`5;!a zx1z>+c%Nc^ybnQx+t)Y@QPsG|aact&QzUzXV*$GlDeY%b#7H|rqJ|owox|dwCVSlR zd3DIGhy7apxRhUK4s}dO)46r%Mq{j8>DB}WtF;CeiB?#nYS(XTsqG!n1G!zEz`gFl zm~46XY`qEU^b2YRuhylHolFwE|H&ADnE|eW$V7_Rq#gC>dfAr3batL_WDT_i!$KgK%J9QezXvl78cahe{#~w1{9A_5 zq2MNTrTT6qN!ocb`1eni(*S^htww72?C0v=xxjcA1{%)M-Ve}M!w-yHVR+;`pS+K# z{vp;JA1B_T6*Jk7X58;iQkz5~k z@JR%-==Ids4I)sY54E2Bfxh)u#DjdT$M5XTke3XU@&xXm-`H}${P@|!*@=`Vv&AZz zM76N`GSWc^74FeQ5wua5P+%2DdS0nMEEINvqrS8^Op5oz9Z9%iucxt-NKT0*IcUYO3ks%RaC$Q8)yaa$!giyZY8~~B>J7;+)>MoN zPyDM7$SW?)9M_)_*cF&=p5TovaqD*lUW?oXCHDFJwhp=1^tc*ct7?~Xt!2hwr*TJt zxuUD{)(vH>Rd$Bl`sZ&A&Cq?W^^I+hkR0q+vqK!c__81JLLIjimT!iFopoIUiXhh${5H*uis=e|X# z;eBo{RC6-NahcGKfZP}KIcus| zx>Q%V;N_cJj{0XBG?7H167b-EaIO8UENC(N@YP&x)r#l+1I>Yq0BspplHZ+yq)<^9 z?@M6~q)cGB?8El3CZN@zYl$DsEjYuai_Aa+Vyq;6d+O^G&4of_MvHp0O2Bv(h;v1h zZ5IXn<{sdMLe9p1sF0aVy@#Z)owd{OAn$J!x^<<)@jbm|cu*~wg!iWO?HQWE0d{5^e!w1VBwK{GHf_otRmxTHVv9|28!ie*DmnUz&w|W z^1F*LbDXa595|zmJgJ$$wFP+B(AVV0T4A#v%=o%yzFhtKpwLo;j3}~p)z)Cv1p4uT zK+i;uATsi4z}`FEeQ_cFICy#V(XaYTLpxen9>fWB5t zxC?L*Ct&FQ7NY;Di$y>6g7Y8UaJ=vY$nsts?MBPZkHV>i28>Vjf5W5e*L!`FocukT z{4W5TnwQ$NJ4@>xC7evg*LBML#Z>vyY=BO?sgkr&n>#jD7(-v-6HMddbJ932qcK2E zCg_X&s4x$1N3|%tCoIm_Xcp*)vYaSI9bfpg&Werl1AewAnyP4i!#<8L0CdDAyKY^X zM}7lWius|prg zyIX&uoSsvD6XN`(sIpXG*SZs!35|C_3BRW!AqfZm4c$lq%Lzi@L#diD?N#DHA;Uva z=Y6_2X$AY7`{;n?aLYrATH`LF?HR{kEL*Bsglz+veA} zp)Wu$bB*J{ee3b!+x}c?OKsMLb$;grq80E*6`-SI8Yte5sFrpMVGq=&g8g!f!B3hS zKmQaxon8YGR08PEY3eGEJqf_80Awg&HFXGhCMTKpP*N?!ARs)feZNN!w5BWCN?RlO zZ_{|y{ywBSH{>O5c+M#k53s}WVoL1IdxKx zRzY69G{5KmU3b0?5n1Zy+8HdmB$gi-ER{sJCaJar*Cl%5_j}bCSMqfbRFP^hGg0Nj~HN z)nl3c1-321FIGx!23Q$kYPre=2n0fB8{Je}7V~~H`X{WkJhz`H4Rc_@%Vh$O?QVFE zM6V;yw1|F>d-ollmvzCF{#&Y$Q|NTo#8oi^ARyfU4kG4$=~{^JS7R3zAd9+z_C$&7 zb1ByyDSf6%de`$85J0*{uMi9nLxDj-_5vHf#V!If!0~XMZ>G_O{5k=hBzSViAGzD; zqvSg+b7?Y?{g=Y72zJohZzu8+U4mVD?g8x0UN`s7;^cR?IIT|?wT zVFo>$CUbuGv!(UeP*uXr;O#@p{?dVLBkl61xF5~Kkm+GIpWs0?fhY#n{d>&7-IN$1 z&zk}aP}3l$B|uDjbCG|z6^xh4h?1ZDx*E+hTh4juOhh+D%;t`42?do*qHu%9CB|5h zUX=A{0mS8i163ocd_*O{{fGUAr;5x^f~YKcy^`9boF*2wV`XY6sVPG1GCZi&vR6C! zlt$T;=K5^pQf8fsSt_fPuBF{xe-@?8xnzCT?87gkd6BYZ2^61bd=h3?`ICY zBZ%HF9Eg7+2HT-zP~S(1T)M>b+(xefk-Io9V516pQTFM|#vdb{()mv=(T~-*E;HYF z0e~$C;YvNBvSIZUxfnP(#L$ydMCXrm`$0Q=kBv85g^lD3c@-0o0@AO%& z^4@va_lr=)S>mzaiEYAO$Svi|=&45=G;HU_4dA&IV4#OsI|Nm&K2NPd6>5bNc81jOtQ?oaHRly39uqg zRzN0#j<27G6!=BIGK2m&cz+?!lfnW;KZjs_EvHvIMnGxZwg^0j!~`Vqi3%@%#RON| z&DWL(og9?FxuCnpm`F{>|MH8}XIbD${wM-P)6|{@XNO*$z!F4HmR9FVG@UY9q04XP zzqvrya(_OL1lT zW@S~^Ky84|wzzr{oshKqSV9i7-+_)hIz}z-bKHVBxV>L;AP!`vf4VKH1aGRw>(_fa z_41*ej|zjQvFa)>5w8H#IsV1VC8d2HBawMx*?WPqOl}&u&BzwX(-53Sjc*PzttjVk zaunkgSDW67>jR5)5U<5R3owfr1O9#=4#$I*1j#8@LdFvLElei%i5Am%w;wx9SJ7Uj z5|9PfV|0&7C3)`YC0+o&anLQ=(a)cOdsA>ABkx#!*&~AHl{FeH_2q zORk>mKe6bs;6ws-^@rotqXNAVnZl7wdhq*!c;;$1J(={d*1MYr(dgDvcK&=*NbehJ zsgQ>O^*RLCY58)o*?C!oKOa0hybgO5YPWvXmbpOi@gD~J!*Q>xT+wBAxfG@+*jDIN zZzTZ`_OC|eKVVMx@&ob!9a}8lTqeqe|Ir$?oq8>;x%Ct^8U z|0MDk@gJ~!L8^uCbCa+VjQ$59X{4+X0FxBg@75ZzeBPjTBi9Y@z)0hbX7?J=?iQaK zRxYr@c&XN`2PVxxJ(s9w9*L#rI{52ZAU5d);v5|K<;d{U8_1^YZG$_t$CU{h5x(AJp&hn;NXOnaEP2Nc zi%~P{))BZUie&aaHaYKdejZ5*1# zQ#nsYHT~CSUCrz{^yMNe94a1uuiE=byd*gwoXBV@TyV9kUzr;|^PDm*moshM4%m49IHA1pChVjnAUSfqmZ<79*90fI$cK`Fb-vq)DT4EC}bxY{L6Xtvn%*?P#^W94*sqz9eM48J7^?0GQAk1zT!pU+m>sn^0q6rmd$5VbDkpxLY^wGydE8h5@e}cIa-G8c41e}Z zkitZ~q(7=xA;FJ-iE22?rM`~h!h09veYAKLoWN|5^+hi>1@bmlP~wA2SoEZ;96)H( z(dUUR16o(MK1?bCfhZXdRirkjBz%S8xR=|91=ke2B@j9;O$x7Xf8qI(h&ROl@#8p1 z<%48K!BJoTK`FCTa@c%Y24*XDM(APSpkBg;0QMopR={+b)lurrg~loz;kp66-Sr@w zg>zMWhrqQV zvUQtsIX07SQCK>+Gaj+~ZP11%aNr1{P|1;QSP0C@rwaI7EEAue*}F|4aN6&%bGYv{ z+Z?Qt_l6wm`T>oY68VqY%oTdYsvJ^8rs7dZpf)g`Oqu$I-ts#gJz8+wQ&Q#w)WREG z|HTHo;=*DeRZzX(^$7_7lPk?d>3u~Ykq&P&{RBoi6KRn0qgnSgyY=SgzElPF0bmDX zQgY<(80cTM3_3^5N|f^5ZSktW)|L7vr7aF@CR=sQPzvPO6Fa!(&(!n&ls2hYdSGXH z&=GfP$nEqQD=7S-=iiUMK;)~#l}-rf2?ojuM!n+}j10!k3WLt6tw%m`VQLAZzW`~w z2OxF5_%a>6#1uif)5Vp>=Y)TGA?n}(+o?j((ylcq-gR)>f2F)-d19Q zvLAVTAJS90;P|J;f=i`HE;yJEK*i;Ey?8u91edDU z*YGs{?lT23k;Y4iM5)R#HR$v0sd%6O+08DO#`GKqI)-4uf7`vE58ulhFO33@Gky!J zgqR3yGU%cl_ok$nO$exaLI>`U)k?1wDaC9lS;SF~rLjE6^I0U^HC_dM6vt8gr*31s zJFEI@j|~h6-4|uWN4X0O9E9KN20bWWlB2W%&Jm1ms{>OOs~xoUl5gH~`pSYx9W=eZ zl03e=(N{aY92V0`K+HGe>+D2H#=x^!^2zQ&m4C-H`h4hFsit0v0CxF>$Erg!;D@d zHdRlj1fI1(oyyHTE70S>yt*$D9uLHa>l*KhoM_(x=|}K0u%26@$wY(6ENU$!l7@H) zYk}4l-}!`wW2l=1K6{;y5p%BmqWv3^5VFrLttn#KCSc~UJkQCmyhyJ;;!kxl@E&7R zJ?iubcrKt-=R%`aQmG&y$)T@UI&<0{yiV5Dges=%1vn@{SCx@SV z$>+RdJ(R>D-mLv}D+`_)GO)2}|pHi1VLxcNL;5XKkSUiT86FcdEl97!~ z?yDL}V^a@hww2-)$G_Usw{BT?m9woV?oN0Aa%?IH+)u%RHxWckz!}wFsjYIXqzy_c zm@RBW2>Il?KWZOGrw%{Z$1I3ZiCH>Uf6W4CEAWV}fUGC63>W!Ql)guynC>TM%jUF` z(fM-xY$ygypsh$dHzO{euaUwvA%K5U&HyggPW*fhP zoc$(D-OOSfOXgpb?VWPFZ$rWb)fR-m6;X>)xGv0ouzQSiO=O37#Xp=>*A8-?I>bey zshm=l^KI9b*w`O3`3Tg)|ik7mr7+o&Hb^WR@{k_^VVXFpMdTlHXg#etQW ziS1TNtOdRVY<1~a;HkIzly z2IMV9(64(7b;SHG=R&|hxiVQep>cQ0G{zY=&gC4>06+6)`sdQ(GZ_)HYPH0Yv+Z9r-3wyS5;Y zMd6kZjE+HV{}~;z6ffSNH{y7Y!I+6m+ zm9~T_qb~Tvu{Y3%-mD8Lo8I%3pWG#g~V?a9cHBSjQFv%^IO2FT#^w# z^8LOtnAR|v0R$oO6-@ZDQG(pUw=Ai?m0~qJQ=L|O>jF+k71wRjv2=cR+Px&%5MGIH zAR!m9eM@RJ|J_{C4|LZ>qBKiR5Ht>?VGMNA2UVM9zZ|Wzk;1v5q}5{f;C4d10Z{~g z{ej(^fY$`QkL$>}w>&1PM)F&85ZAqio)ZDq7fF+8$|qIV z!rIxO=>wx(I2i3fY?EM=5s$7iE#bG3SDwamGs|n2$8E20-j?_-FZV!45>I1yB$n%} z)8{wobl>;#mxJdh#D9SQ`(@ycGc--h;N~v%y}c$Qvdu$DWYiit5zu&u+H4~^=X5U+4k7@$<=7KZ7dyKc_%uo03ESR`~A3OYtvo|bV!CAm9 zm0Dgmh1pjh7&t&QB_08f3&E7dWc9xw+4_E%GiYd0_il9%G=|)u2f;)dQg$TZR2y; zRWoH-^^WM6Ys7dS{_8SG=^=p`e54pHkJskZok)<`l{|P>PwAvY_+)nCSh zTI6EsVh0e;&K(wom<&KA0CVN!k^!Yu%#VP8r%Cvj9hCA7uStpLZ_bHDLX&F#Rb$G# zjHCk;q@xO~+BXz3G@AyW{X>6DBFETM)i_37Bmomu3Z$zFARgf6!0Z1H*nx>c2bJIA zr*3hN(5{^!g_f%pPdfpiuD+c4f@L$U7evtXg0|ddwL?^;RCDTI%c_mvs9!J^WaO`_ z`LE8K#oe{&;~lXTgsr-oUByg8(SMyPz$H9WXDtX^bIpPP1*#+`msVR)TXj>E7`YlW zpTs4O0x&rD@B?<5FPGYJAr>Ph{r~eI9X;Sim8Yx>Q28RkBivro2X6srfh?8h9?+wQ z^$x`4ro#_otz7W1R&7zsty4PtOH`%hhs+kz!(?ki_^qEt+p1%LgBqBweEDS-w-V)) z%d~mAg723rDI}w~DgFROw$Q)U>=hqxe2<5eL4>$uf9d^U^YLn0R?`v7e^ijM*Vb&` zB`ZcWt0NL2UH?FK-0O+!UvPfZSHs^$p3|Xu^@W@;-R^vWhzilgPL5=uDw`n_)m51T6b`3Lwe?P~UcE0iK!0xk-8XVtBhiqcSVWK_9RTJcPr^gO-blf?fLR zMVCNFIs=G^2lIo5X$c71wR;AAIR zYfnLyDVAc?X;dk_|c56d%maAmi=t>+dgxWc{nopzfI zelQl3;+i$sfmT*K#S3)u!~QE}?i|5XA9kRXNb4NY{ZJVC*7g1&Rg`deqlL;oi6!y? zT?s)7z(D`4W;wO!AkTwbq|v>C7!=aGRRC?cj)9tm@%;Jo-~P*7er=nf6&5o@lLZ)! zZ_O-0la?QRP1&Ck%KVp^vW%SXO0sGafjDPZRGdKfj;01&Qq(e|i zXfB3lN-yZ14vv-#&XouRY==mLA^7yYlGKY<>vx8DCUb^nEeL7yw!)$5C6?= zp2nu7B1OyaUjT^QXrs|ClmB}I2m%# z@)X2twQXo?(Q02>EjGGihZ6<-Yzutvb|&%$Eoyh`w{Wp6iqas}m5cxJN~HF3jOM!z z7q$h8jP#mHVcR>&7HHrsF9h~h+uES7R1o~%Dp2@bq&iB_9~@FB*zYXIz-@hcO|M?s z0bKMz1%E2F3xutNpqI?Ax8KDAQ~Fe9AqG<@7`2x}m`vB;J^_HbtWrD*g!kRu9SpM2=F_){@fqr<+x`BX6Wu5Zhi@8(}< z)auYxq%1?hZ*y|LpNdqk+I<~RZeOnNTK+uC@M&hw6R809K=vr9{Fv{KQjXvc`QN|J zTXImrL&w>G;XU%1o2N4j`Xi^!=&t4byEY9Mnrx?2hYR`d^cv_$wF5d=zi|`11m6Nt zEs-q)ZWzVbte2ilUg$J_ZxTK_@mR5dg!hEy82P7i7ls9-s)&dC6#^!>h+I6p zn9X#w7}!aQR4y`~y%uJbjH1}tEnl_x-|Jq!i3;5Rfo3p|c_EZowJ`}YUsT%QccK(q z^RV3_x2vC|kOL$=e9!XM>msQ{)>x?|hD50p?#jTHGh${1o%-*ebXwg+Ws?PTx}6?T zsu4ci>p!vm9qqz_o0k_6IpA3iPEcbe|>u>PNVJSSKUO*9I zRP-&9Z2Uzh0pvgLF!+X!_nnnSt1QKQA}`c@y4lbCPer78Vd!rFcLk$$El-+F2#+*j zyII|i{bBy-?OP-q5VrFtlid6wjlak_7;6WNtuJwR|BvgD$qU|94}je2Bp!=eUYE0k zBvzB6>(zk8ohxWMI<70z<^1IfRVx3BH2@ChU<)5c&<%9#EzV!2GT4|nadS;$XYFE|bjp)a@+AmnkvOnL_ zo{`0qtl_}W)7{S-e&TVM_c<}G&MPE`VKaGjv6Ssk$P2zXEa6#_PIEhX9{Wy*7j^}$ zBnvx!?{=PeXMvD5Cl;DqfPzVPx#r>>bUnmY1k$IAv>R+&?TDh`u@sU@FtrdII{!`g z7E++@Z*+mx%oxKVcBcg8D@&&Df{6GVU2gX4U^OkoHddort(<{*<+}^k(Syyu7YFUf zsjoLY@3juZ?V98Ng!Ae&o)vu_)-&O^nk|UDmOG418@tHjnMOX`UOs`QOBeNAH+)&j z%B53pZFV_qxe)G|Tk$~`RH2lPi!zO~px3Hhbhj@0il0^r3S_YCM83Qr>>A(NH>6=1 ztN`JoTp;Tza@cRg04S$8ATV`QuX2lubX)w>e3zc{92$^-y=ysULSYM=_$@qwK>9HN_>Ml)TFFSVSa#Ih z^4zOLt2C!INt@=O!OM``RlD@2qfQ9knCYe_U89q!gOC3nS@48QDOqk z_>~L(ggX-C%UuB$vPgB8b2_9Xu2i!)*oCM+{&3``)#>>4_58bHkQk!T#95%6U)Jch z@sm!oM5Bu(#80(&rf7p+ZD)94x$T+Qh*8l;AOF?1-EcqhuwRvn6*j*#EA%5dj#)g) zr>*AuT4MQK!vZ0r0v9Rs%_hl7Y>sKV;rE2LY4OdsCxcO$cEAn?yD8$Jlbx?7HM0DD z=&-g<>uxnOHL$Gi$E{)I^()g3T6WU3CSyKd($HuND;lzXicYA==dh>JU_1AToO!R& z@v!jSjzxCeCky_3ov~3y43sjfrq7apK(}O`N;8k zXts&B^j@w$4e15;_TfQQ+HP4t^8HF?=MD&@Fz@sa-5F$p_@zKFhbTdef@1z?ilXTm z?8xz$wQbj6&eJfb>M8T+>65aD0I}=F5h*=u_&e=ph8YKVhp4Lh0&*?k%ZunUT-E~M zQYh#Q2rmFrp0sN~ye|Ca2|swUiBylClxVem6lz~w1W#>Lk$Rh#Q`M5oE+fFywG|Oq z!NoZjL274Yfc2d}T9N*5?;XAS#{IccmBOkd0i(}-&bq%v2FYS5EvEVUB3Ai0oCnzL z-|zXlg>O3RzGC|<6U#5YKEvtW!(hL@Wn+=7gVn=sHc?nISG8MAe>iuOb3+ym23sRdLEVA`Ool+6fSuSLf-ix9Ua&{zP_#8V*$j?&CrK)WVs0VV7 z{2Fw00){`>ac{bB3KR*)GvG`NlGEz1lq)Sx0G+p8@1yM%yj<~#IBi~uRo9(D?syI} zS|zJG2L4Y+leA9h`+n;5B1Wyc!p|-UmT6F=@;10XH^B)u4av;;m^g7^qy6rnHa4{! zffAqE&0DjLG=dE?n@q z-Z&rAfe<1Gy5qz3QAUNIJ z=c?#B*Ic!sc0kob@#f4@CI@7-YBhtq9+`ata)I&SYowab!7dJ})G3V6#OSzpfE?{3_% zl!tedFfhn)N`Sllaa^axv?Lit73&(D;&jl~4)v=!{=nX&W-k8_4|*uzt_mW$Cc%*n zlu4MkJjpq?NGSeb5ly0fKO9ru7}WbvHq5?qu`gI)3+;bnn}+R{{Jz0y6X8??L}*VH zPMDITEEKDizH6&P%TD|9N-?zEAA|ZCvifAf>WtL&SizVPD0AKnpMC`yz+yPhox(9Z z8TO33YHG(WAV5D1e)t+y@qiH(VTt;W|FE~;iz!g&)?KXfgv5jJR5z>H%{sCpgI-gs zJ&bnvTvo54@u4?pvzFF#wRd4gw_z}R_Lv#tMU_%D{`L1v`UtHC6PtWtq@wp0rSm5) zC+mgNA%a`RkdGfRZa#K z{!XXKFXe)yBSqNk#da;_8Btt;UTPzZ0>NLf>MgJR0fFsO%SwnK@yXt=QK=Y&aPC94 z&jS=(k2v1uwAgRWDl%%81S& z{|j&DH0+9g*lrEWRrC40#cO9&ZS?ZxW*DBX+i~~9gZb*J^LYnH2)>}A61l`G<(+f) z&*drL+b^}6XNF&25Yv<^Zah4Bc~R#( zT1#B*CGQ*f);NUW^gUC?2-Ds=ZK1^)|L&7WXHInOg)Grv)fZMNNl@o*bim}k(`hW4 zFddO(_m?F|mf>W|u`*a`y98V|)cNC5^OefX*S{OB#QdKveM?+S-CN?{>8bYCV7Rxb z!r*k=b(bT7ua48MUQ&M}F%0)oEp-Wf`2C%KzO}V_{)Q^*;ytl=IH5YQ#z$OC*OS=I-~5v)xvRoOSixP%gNkv_D`xSj&Jk`te+6gyAF zc~{y$3R6r4o+TE~SQk8rBYW&)TSRS+@Sf?S^DJcO>FaS59z;dc2v z!AFexf;_njG{GuMcA=KdbM1=am1d`En0#_6;JsMmvH~=Rri41_aDWA0d3peqY_itP zyP)Zpcx&$#s1-$0eMWlN$VA`@ej)`>p-4%e5;o@&x~4@2?hWhn-6rpZ#@+ zR2+j!NzaQ}?Ft<78h*odng&kJ_?&(v`L}t?y}_PZ&w8Y17v+*Ug{zRnLh-WO+KwzB zH-^L9d0ZPdZ57dfAK|FDo*yWKQ$|#tz9fvh36;Sl69;F(ycw&7GT>_DDD2PG3Es}X zMAk`OGA>n|N{_mj%^&4*r( z!DQz|+Q%;z`|_ycNx9_I$}eb|>$~;lfXAHmK*u#5eEVH;s)OyrJLaD<{n7c)a1XH+ zXl_7nD;(yE6q#9R)LRJL+tP?N)@^WekdYWwYZ3;-`{_u%h4j`MKRF%brxk);CTJ%f zG|Nttc{{R{Z(c6lY|zI^w}kDRhM2D2Xg3Ir^9tS`2}_Rta(Aau^?<3?*9knr=NZRw z{ycoF+d+^>qqxQwcFdnA6FY!?r=&N%i+s8u)3W{UctYMbxxLn{T4ph!+eltUk{LDiWI^xhgYLSC5z zwy@|Ruc~66rQ@07nq&0}1=4=|?p+io?PE)_c`wJyYuIk9;?8xG(@B56h`}4CzF?;L zREkHP8HU|bYc;Hb*?El3Op;s9x{5hpSU`ivlK6*444uzLiHhBJ&nl=8@p2oQE{a33 z>3SH{FModgp`dg*J_2NhI) zu|+2{yYG16Fs?xE6Z+``9)99Ey5KF1aR_5UcurWtjFYStuPGV%tW#a7lG)mV#l$GW zNNKyPp3VZJM!BU`{XIVS^E)Ri5kko}^yYk3FUDA@Xj2%TO>fO72IWB1c{#+gfaMwa zQN&%f46&K;SC}>XmzQi38(@#&?*r3Q_Ew|{YR8DiZ8gsa+cdJd%jd5pbST@aLGzSvHKH&VAE~X&YeSIi|-h-2!%jb6mij1ZhDQZLp(RH5n;+O(jK9H3zcP zFooyU8ciQHXG2Hy6t*W!BLeYkm*QbHQ>9v?*vWcIh>{5F9J)sp6>pT<%!&`_aMI*4 z%Ey=AaD3;E>Z5qZ*=XtY=l5(SWP_vXMjNC?x#t9=@=ROI`jR)?`{@$vI>S^GFC->} zhNlR2Ik-PdKqzgcnHbB0cVDQzszp+41C70O3v==@*p3R5x$ghmq_OPa4qgz5(K3nz zc6>{vF}1TA8mzssc~Udo8=f9x8L`J>JCGu-;{@^}K}(F5ND8D*(XD}cZpVH}ZTeo- zX%(s#gs3+%o3A%lAMhV|U9PUFy2Pg6KJ0P6csLP%F1we7fxzbc6Z^a{*Up(9;(<^a zbfhJ_=&)pNN!^KchdX~+x=u!p$^bN%TkRGHVMO!@lvZ0<67V_rOd>`I%3bF>hhgjA zDpFT|-)2qJ4(dS^=!`I%YOK+${}RLzPT~yDIWr!K5*7KZf0yRjFYvnvLIaor#>phCnf0 zKi)$c=lMJqQXR4&&m**+91hXzQzt3m@=0L^klBJBbhj+<(TXVC;D`SmyL@zW@%m&LB&4+}n8v1%Up$EW!yVcmkA46Y68Zq~P%B)CrD z@n6RoDf?*@)6_s?>`W8dwl%gKMMLbo=4G@#XM}i?WN3hrAUVZ0de`)u3( zmOMJ!dn>QeZAD+9=+gHNN{VV<5O(Kb_)2X(zQIpulcg3EaXi#fmCLNwa%fMOl;8spK-CvR1Cnw=CmR|}PLmA1$8TjAtDG+_G6UX6-0HD_$DJ1Qk5&*jV9YH7vubS+ zf#f!Q179IZZ>9pZ=(%=lD`^>|ZzBwv%_=I0LAHN-{IO_k*1BRj2L17jnT^j#jyiU~ z{&gvsv)k;qh+((-S@Qpg8ZZIkbx-jzN_UtkR>VQr%y2F>Hl=UAV8Q zziP8+m>uieS#5a4lZg5s=A?LA7#)f<1%xKo`G#EJZR)V*IECsHi?Nr-zteix)&PLD zEo;egF5b`AVL6B`_#lzH0PfE>`^Q9h2?1<2;xNc#&=7;ctl)khux2QQLehLb}7 zz5swk;8&YB$V+u!C)CjJSXFdS+sVDIb$Vn-q5NAFbKSr2BToD~M1S@n_F8amI4vre zvp#&rmkWhlL}w$b?qKy#0WL>nx7JEj41bD7>#qDs1grnd))iDQ;^J9pf|2FNJE|G1 z0?Lz#n#Xir68)!1e!Cv7$#B7lCw>?|FUMBN#Z`jiN{u@mfSLiLo*A6j6`3VUi6ZCA z$gmf~O%nL%>ui0$%TJP*>`Be?Nvxt2-Fg$q#3wfvXBTFCI?^us+ZM&DO|?V#P6syZ zE0Daee+0X(tJcka-T~KDfs|vz3Oy4s<+ zPC~|=h&I$hCckg96-cX>NyI#?nj9LX>@Xu_BniX_=GrgeAG<(r!eN<$Z7%G^laTQ! z@~>!coJ7|!!7e4YaGn{YMd#+cNbYar+9T(y-1v1D8<7M^3zf-$N>w~Xl~^8%>sJv> zn@3Nt_2<<>0YYq?;5uEVQ|KhGzFogcgu)(-TGTml8S}4JVEq9=9TMsET}*RyQvbnH3bXd*8zB zImtfZFr9h*F2>^aH+YDCj9kiP3L#cOBt*v!YP*(V{M4ud!V^VPh$N#aC-6__r`MZ& zet+m;5k;^-MMxV29I>W+@?+HIbC<`ze*o>uJQ?lA=aw=?I@O{qXlS(g?)g61cvoJE z#GT#fr?RUF|0g||Gyd3En2_`{GMS>d;Vn%4E(PL#wc|?}B>3rc`9xBM`;54@Ee4*pTi;897d_U5ZwRAZtc$evG-$u%)|A6|R z#9AmF1{}S(KXejw*n!wUdeC@!UugIqVI`hiTL#t(*fn<^7pw%x{z+ejTDb1l%ybua zSu7-Lzfm$mSYz{O;#69E5^2(=vkqYR8mQHNnMRDyw8h#$_=hu>NxESI5qPw`vj zF^D1G^*kxRbFk75*Nah<4cr;e3YpQ)CPplM@{KZ4jRe-+yoA0Nr?#-D+B<>a~+Rl};J4t@vKcYihU@hxsD=zdRGMA=2C9 zq+Tzk7u|yaiu5bnpUPVbJf{q6s3KE}3AtjQ zf52s}>X83SJuTvc8eL^Nni)oj9;^~|3!>Lz;1o2}N$LDs`m?Qf=X~Q8F)qH34qNV9 zE&CJ=vz{%!AAPaK;)k*Xm^8A(E5a|&!d?>{+HKzImTI+)X;w0KF9AP7l;^g1S4|eT zdbx+YVn((jc1Zk9MoA2RI$@mVQA|yfIj6E}-kx(B^;R*hU$yY1#oA#&0 zs&9U*i~&fph)$)1CXuCh~FoQ{!OA0#bft**)80<6<7A$@)=1> zQM%SbmfB+tE&!l1?wmZ1j5md)46zx8xks!nSuSPyC2?96(M%@Er1Glz&JX=tU2Py9 znPoa{w1r`trfwKGo*wkmt;9zwr5eXgxAz$K&%a6eWZDBD5kl?D)pUVJ#Jm18(s`3V z84Vus+4R?Rv$OQ}@JZJj2P#eDD)G?9zvkXFDL!F=ROPeq6^u{u} zIzyi-L36MzO=&&9CSYTFedt+#Zc7R(kVKb2>!Z%J*pu+N%hmKBnF zP+N3u`XZbaGlfL27`OfUYlf2nY+b}jdrl5(4vulJFbKCZ28Vr((=5L4r3WGdvOCIQ z$PZqoQM%6_dev{4LqcIZfI ze&hH3yhi&&jK_!AjJgc2BB%c_&cs|)!yvl!jb4qW{dSY@YG-=s*32@RE<+Y_-vYH% z3^!t!=jE6nHMt6`sNje;A*KCVLjFQF@^8^wKj6m>m!~37Va# z)SSdgy~ZDExj8RJU7jm^V?utD3b!^Qco4GWN<=DUvF2p4W|ErSMpByXB(NC$Y*fjp zqln&nFm7F+t=dkqN9R2*3GL@B(*2XT)!^R?T%Fgm*vzA+qv1EhO z_vP)YALy(4>AJg)v^glDeQmtQlg^N&=Db#+4G zLU7p%0o7at&Ks0kpL;(lJ^uw_eH>*{WI1QM=BAMa#X2Y7m|k>pkLi)CtEAQ-CdGS^gHyFxRSctC1a<%L~`gy;p^K{En*B6 zmMfqQ2#=emj_6R5#dm+-oOAS8_Wh@j;mViR`ZmVDWQQry4JQjm3jhPAY0X_UIBY>5 z^{7xeKeD?;5z;g6vsJ*U#BvEtl37^0XxC}{uDJqZpt4JW%rma0UK1hmHLrXkbgW1f zPC^k(ftFZ-T@D5T>9}|5pc<%9dR%`3#-XO_x0!<2FpqdxPqwx*UrWWS^iQ>xev_nz z^@zXh7aVGgdc$tgULUKkx+e2kx0;U?sdll%IA2+ri99e@l5Yp&jsu=4gVba4rO^Z) zY5VPgoJ{;yW+s}86 zHvXkfIAD35LoNUeLZ58>Bm6@Z+bvxF5=~ne0$Tw7cLG~Z&X`-Z_vktF1Flx_Q$=?3&$OF7TKXWTuD`e{ z&2B@}nHB%m+bHWaf8TgHlG;`PSCE>nq-M-rhJ5Jm$8rlN?*pJJR3(W}9U%;LyF>5ALyAA($XABMI)VlZA`kB%nLnCwIF zz!9Z6YG=0|Q)-R|?!nhz;s%9ar=yg@J$zp~g(ou%gaMkT_$g-g`=6~?*+T#~cP)HQ zgJ9<5hV{n|5HEQVWtaL2hEQft{3w(YUI>jjMPj%*nf_SrA# zobLXdaNdF4CHHGdJSF3c^<^|%1WN+tT)9$Rw^dP=j0ff^T`{}fssFVk<^!|ciq2_L zV?GskvFOMx2!b`34htu0%x;k$;Le=5uenR#Qu!Tq?WdNpBad{NE;QKSfKn#Kn0S`E zL7f(3N}_)YINFcPj_$%Er%zH?0nws%3T29D2!lO>$~d=tOmEZAG}eo$NH~6jN{Pzv z3L78oL%M=%)|rtfa@2+ho)_NMeyTElfK%S|D*dpWs|pVDDTNgS0nwTY8cnA1^e-(z zgvSu{-cUwJ`IkyVb4cDW#vyPI(TtpYkk^pPu75gwN~Dq}m;7#Y+~~gkRCi@5AwQk( z+<24cq65L`Hc=$#q*~+=u~?0Kh#;2rSO1{syf0MJFF8HY@Yqps0Ybx!lV!I#q{#Mp z=yf&<)9ECwG9Zjpg?kpfCHHuO8_paN&?&byH*MNhOao9ZhKc0p`7g*y~2`s zD2dO(ah(y>d{kCS9)Wqt=Cm#TNwS=E3~R}CmXX7M`V@^Qc*D3F?c%>q6TE!JqR>h3 zO2K(!N_{FYlAN+7^qQA*?Vnj=^u;XAJDpmg{lyybof|-=Fczj+PX64M?H?A53Dg1w z{xR}Y1gUWD%g-wrzm@Qvcg}DnDXHzB<7Xgt*GW(*V&BiDsBlGyqE z4KLD=0XB5a@y!xIhSx9$KuEVnoLZhFdLTaxx7!)opkvf&^G;X;NJcm5UrE8@+a~K} z4_bs(yQKv>$Q6L+a`U_A~g>2X*H~AH1H-C)8TJikeod z({0gmzK6oPJmq#Uz6t!{8Us)OH~y=`OfCS9^$Q97!XQOyhoO#(J$adnW8JMFFCIju z*oKPBs)1?Q?h~v&r;;z?7c=>O0VRONu(=eNC`r?7d~t1;i|VrS&^miIt)*n&aPUn2 z!I+u_RNrJG&=~Y;#_)WYG|eg!xVx5o`vQT;Pr^J9`<*6*82y;wDS_aJ!xdoP`{Yg~ zaI5Kf3P{ zP19o~o~~e0pv8Pi=9xx6+nW-1xlio1@+xQt$6QYZMN`*gPAR?J8e*x<2n!PM1wQsy zeynXyzYAeaPTNtu-?sua!9>}1k2~b&{K*kJwi`PfvGY+Hzn7l}10Sez4lR$a&bSsW zqWDNMeg{CJ7JY%tGwCPRzFO*h@|ZD80_nm$8JhUhY5R3iOT{kO;*(z#jRjMox5OaP+7 z==Db@F63QO^4?p@Ru|Dpb}qwy^;<~cS&dc-yBCD!`!T9A)BtQ?I4ae4A8-?g#Q+J} z9sP6bl|5pPT_V)!IYy@a?u;~I1U%4Urc5~+rY+PJdQBxLVh_e9F>pqBsaW~!59;RN z+iT#*6SR$T&@r=p0mt&-{-Dj|=p3J8U{YjstCt4mB3 z*%b%ghjJ~wVq^y)~G|`o&)PzGdC%l1T4Qr4IKH z+Z^oS`jgdR5%?i$iPLsnA}C2|p^K{7bW~UA)HhP9CBQjN_M68lVj`DkCWpOn$fFce zkOCF1^4W8?0;5O~LIuj`lYl*-kfcqbk5GuHX;nVF>V3xO(h$pWVM&Y3z0@-Bjz>LRm zG6F|kY%yPjVq_VleT-dvKSR$P^@;p7#WTlwg|hGWo*<>i0!~+;SP{L zn_vBmRnqibtuyXtbymY>`sC8v2te4dSBKegX|K`YfoW^inePb1YZwE{XV!<4^#C6K zZvC?5s2$JqS*t#($-o}d=+Uy|f&<~?tj!ytFxThXMj{il?_baT0NS@;Qn_R#yXKi! zjGx>vSf@KxM=Zvc!{|s0(guN8IDUK?1!9)<olTBN&RJ ztC)(!r)*3lH{Pbz^2;8tVK3WR2wvVQMt=dKKM~8s-p@lRv>X+BZZ=KgWOf9nGT)?e znKIw|!)PO}MjI5+WedDU9y0=#m&rN@S#f#0Y6=L2Fg_J?gpm-f`Uj!sBnqaSV=qc3r&VJYOf*4{1x5(6B=k%Y00S@NvS7=YZQ# z)Rxh=ZD~yp&XcYaDfnbh6wj8dulU}V4>48X0uBQD#uV95Mg>pzCG=n^MnpD{xqkBQ zIdvc?c+1hEJGV*HmR#0GL?8`o?k#dH9??nUifg26-znc1N@alhm{r5w1R1rP=bOD5 z7jSz<`QntK0LkL6fVeU$=4)o2agx=2b5MnHz_u3( zcjOnL+!F2SrQ(u>KKlWo;oCqSje5j$0x9?|b7S?b%Lf|)YQ+ytx&8_SisT@uDlw37 zz2C_4hEk2zMbXoqC`?^yv0gQ9uOa`_BU_A02Z>+{|7e9(s$zlv%zsWWl?0*!?S?Aa z&b7wQ54~|K$a9h(>W-rMkY+7cb(>&lhnm#xw_QT5dLnxRuk*CR##J#b;Rh8o-cwZ2 zM0Tq*PKcWAjtF4c-7ZR0e&*~&zEYTBosQJ}l+8aAkb?_qmbCgFUnpIENgJ ztx?JMToqB;IkD;1#_w#o8aypWyM*RsFmuesPHPxO$q0+$Di$^ zgPdr;1Zb7rZOZlH{1tBBLga0ift=@7lFT6F z+J|z={g*5LR6_p>K~^@R2kCzesl%^PMqw`;VH~r$)S73@SF6IT9se@-r;D znIGF*ei~dY7r2oN*0iZ%zWDp?sU8V_Py;&nbtBRFTf;x=lKJ(`A7D*-j0t$r#IomI zivZbSmntp2$8Ko(xAbtX=(@%8QVyVi&KBFbKW8!iZ%64ms8tA_>xWJ zteo4(N7&TSHqB3IuORRus?y+SUn9v%|M2y8yzyBweIR8 zL_y_;dH@xYmO@t%>CD)M z5d;X5{G@dNT1Y-xd>R{Z(C;;x_VCxz6!VMl(otC3364sI=rvg0`Q2h2w-=;ncL znaIQ#LV8U)DIfCTyKcraTqL6n9U)UeKN(LZ*b=0Sfo%GR@X6W?=M1?RAfPXS#?VB@ z@25Pf=Gw~U!rZXjv`B~LgwKZ*v)_I!n0e2dxzyCp89XxVlM=tegoM||U^-^|Hs4Mh*M6dQFV%3=WoN`Ly43*iID=>UF=Br%KhIMoBmb;mY zFFS#THNvd9VZv5B>uzD}O^G4|(KxGdt}bB(5I~4+f#7Gs1zx?=-_E~MG;q+Tb^`Sxir^FkN!uGG zNB28duVFtsofhimTjQk0Y;FJ9k&y=aCGTix-AYPXl0;}d`gml8`aD`bD**ZPQ#U~%`fOb?q8ifD$ZZ;j!#u@<_E7IC#0D$X&?fNUHSD^ zw3XA50X##(;5S;rRu$0vBn_-Qk}&YHVEe7UTuIHd z_i3o$mEoLOkT_MMpChd+@=iqEp}EBKxQ9MV6db}^uxQlnelV`JY6?*!iELCKdF|p#49z;+RDK6sW)6yPAj{5aj`F@Z?i&xWjquuh`$Xsu>)w&t zH%4y5r6O>7g#NnnZtl49pfK`4WPns~^>cDL@xLoBg^uipvA?n;;@&Y=dfnB_k+N#6 zl=WFDt-??AZ6`D(NSp_e#ep!FdG8)&hCAF*oUV+3SNqU(ug?SMr3%DOsMyI3kK^fe z+g%!u7Ia+;((9JTov> zZZ=K)u~6G>+7*~*SkQ0ce0aKR5A|CelDzyLnq1yr2PRG2=^0QBgf!MZZ$T}ku?Oy zM-xh>m~fxF7`01NE$6j>!VOisp~k7Kn>_-y2JGJOxz!*Yf}$PijXJfTv-Xi#tPTV@ z)AH-3`8$q$93R@0KJtO01e7m_v?FIA5WaUecIM}NTPJisoq_##k>Mlf{@m(=k4o1s zuRuU4(pjIV*5zj33vZj$b$q`hat&^=WwALFB}kq>Tslf!sKk8-HUFAT9*FQpPfvZc zv$`ImLnp4C1EmeyYWOB!SAO*BPvnHKR3jkg(Y1wUYY#a+Sz7!V$KjnP0_qiAI?M-b z=j?!8?c_}arQi$TSQ^4P4i@kg{L`T1hSW*~v~`@hzr+$4>f0sI;Hx)Nk_!BqOdH3Bz3+QL9t_6lMTlyR29p;s{c4 zgmE26bjVgqG}oW=X(Q9upNzim(5osDOD%l7nXGQw5ITD!EDi|Yb+F`*cVl!WdSGNm zAOrh*UUOi(_1_#8#BAkkD3a_orRPqOZiYeblb>-Hyl@GDuPVs6>(RiUX5l3>m&989 zy6l*OAr?WEW$Ebg-uoA;nxUz=%h*hgC&n;S#u%(Ep6I`o(hoj?d&?@lJXdw=n60da zmF=@gb+e`bP|TAuA~)g$*4$<(Qzwq+pzJc$BIXpi(rpifv`-v)&atKkFd8Dx-Ct2T z=N^}P)MRS!iLX}+pN)qHKo!1WHJp0$td_g7Oeq0H3il~f4Co2Nh4}o>gFFO8ts4UL zK^&%4hz)lG({W8&^#&;g6E~NWW3TQv()!uoMVKU|fHm7Q4Oc2^>54DUo^3Os_f~VzZd5!H%nY4eV;V7y3I`{}5w@54n;9!6i6X$Gwvw`jRmD zytDaFq6Q8XSYh6v5f8KnmCb?@Fswke@8k{bmp!z+j2I2tE6`n53lwJS?F?GPs2G#? z0F-B6M{r^3Vo+Xf_@W}q2JpIRo+hB+(Pew%#Ubc$TFqf^2z zh5Ow^b_&z{C#4+ZD=}a%g1m}@hiP=`xgdf;0UZA4GjREqYV_Ig6;Nn>xiG25u}QKg z7#Tg}-A~Bo8cGPUsn+1uU@`~D7-KM$y9V~rTOCxaGGYsgtBz3V$5SyV6CdX`o*PVi zSaF^Jm0;eS-q<%nC2aD3z15$`UY=?r`brin!&0LjQdQj*Q{IgQnhhCL!Ftd&q>+(o;!gU8JkC{?{w|om0uSCTj;I?Yt`jB^X8GE$7 z7@f))#)MBEuJXUKnvdOe?n~Ea^CQuR{^;mn(qlNScwMws`uJiIywz$~4!NVu{*Be%e@&Oj;>rm|bn_E`A85{U zF$h;gBdG<2RvuS!;br_bf?N$6?|Tdos6{CciGl;6YK8_=Cwp72uT;SFX$B@Q)Hg$X z>P2X78Qj)T9Q3@tdi%+j(oBZHQ^G-y-_&z6YFT@An~h)d3_7CX^^Jksmpje4J3#A= zknd3|ZMUrT7JkhGeg9Q78ff#h%;pairA^u)mnUy9e&Nr{^Ie@TIroHW!v6avlUnK^ z@#-50)2)R{L${s|Ioeb`eP59lPndSS#O5pCH^{HL%?`8Rll@0$S8t>>I;j*9CnTv@ zebcA*Ymr3~J;Pz=tL>m9-H0vSz$>`}hMJ${i?fpMH_I8u-CnWYc-d6lg_l5LC;y3e z;~T-+#cSYGG{q^KY=B-k)e5511{7uq(d000?Lh8Bo9qF%OZ~;d^_n3iBF^*sF!EJ_ z=7){1|Ev{7#op&HJ1$lHXR{=rgS@Ij{&dG4O{kex!A)y)@0D7Nd-i<9W zEnAv+Oprzb*N6(u7BeS!|6F%^30SYIKP#vM(BeRL=I|>bNF$IN#Hz|Q!K1FI{k2%*|L^llt<))-m*w<3S))eE&)4z3+B|BObFGEF3x%kMdi)rz{_R-Y zuv_T|&BT}=thNI0#Oj`pdy5kRsdu;*aRQY|;8I zJd&21s#TH5I}pjgGY!RZ>@QS<&#KS*?qo4CJx2F(^BG2Dy*`qj4RV-9u1*z}$psyK zLTV0N>;rD^7l;i|>{stO(>7UZilGC4&%`MCo>DkomWG;zdT-=F5s=i#ep;6&7tBA^ zoDG|8ZWU*$-zWxr=?F7)r&MPEWzUC#=CV=Zm6~PYmyE@-f^V+TPOKZBO!;7REtm?5 zf};N|+jj&R9{3qrFm(Ad{ntCVDFS=uE`_l9G>{0G0sLPE?{(tCYG-1(h{!lXTxv&1 z7Qb2?veV3~j8pULW%72!ukVqEm{w3ZTp2q}NtgCG57JJ(+ZjmdTHiI{Jdk7AmCF|= zko-mVOZh@akqAf{8`>a=Wf0*HE=K=(*HQ`kjH72jS9Z%629)u-WvKwnp_{MhQ=j39 z@yfq4>x0D^ebqQ2@~P*@l=ldMQqbjaZqR&&%+}e!WRKgrBf~#|m&nxA+UEUo(o`QaCNwZ~=rrW7yYbw$DSl=Z9K63Y3*bbmJV zZ4naZtW@+^4L}9g#vZwB^|%EX401$Wx!f9&)pOd|G^(nL8;$=>=|SB7 z7je4+oFqHbh{NYQX|6*Cgw%J&{pM_;VLwC!(rs#jA_WS#NyDEjkV?!&ZQO?;KAM6{{uLjrSX z+BC={x5Pyg^BU%<=3P_XyQaRH-Uve}?*8L02v3c=O*EO@)CHbS*|`;!g<&MWMWld? zuK`p6p%3E>o->NN*EzY8e{nry^6*uUpX1!o^7m@E3=h<_#CsX(%MrQhyC#j!`uZm# zexDd+#{Jh}BsP#Tkfxw;y9yF(FJ!EfR$2?6wbK_lvTMD(&0=fdle&Acqo^x4*rY6n zM8=Vm&&bSCF2>dVyH2jg%}a*Lx6X0c5|+CoqVa6f=M{?o>O;vO$LD+aWV2ch?>Mhe z8Oq4r6+~r=k%|lFxb$qSX38kmfHSjg=r`rl{=)k#H23VG|1?0; zy1KTxU01>V1UEzLSNyYInL~}F)Wz?!U13)f?)hyD^?b!Zin>}5 z;F7RU4Cub8>N5%(l2t#+C@50#lG*9MEn=IpmC%|WL2LFSi-)r#pN0(E*TP^z#{<6_9k#+?=YJfKY(_7=EhFo$+8LJ_073u$i-Cww7I z!ch#>0N#b7yy=$1XcKgQe{~YWxF$quT{Z$Y12S9Gy208A9L&;tFGq(THCv6<`0RD0 zh^b`@okfIN?-fdS%K!I!dIT04KUw@2+OI)sZE0m4_^r#cgmkcIu0{B(Q;FbFcVV|d zoZZMr*?`}lwM7fohO;HtmQK{NZX3?j1N##R&rLoB7(}Z$0z?LMIWb}yz!TRpw0j>5 zS%hE0R!nkdP_7cj>wzmb>+IDAX9IMzlRpGR7jOk92ORtpDJ`jyUO;$#Z)BPvyB_2R z)t7!Y!7Ug5AqyTa%;p(7y2&9MJK(L7jU@bAE!Ick0P~a$eYxH8J|M_u-LA z3A5PVEyFBkFq%(0TD_%hb1(6PkYq>8xA;opaaKkWuHN;xlUD*U=~=bgC^T}sW^u=^ z`SL{Hka7i!9$K}eLwCd(^^+3=!=frdCIv^diVltx?r!X1Ux%TCfWV6oGvzZ&6Xr0U zoz_5;K;Su2gD9IEK+Cm!>pWLu?>X~Z35PvZ|DwF;0GCNJcdbj8xSMpS#QvfOuXyMT z%<%WQH9#fHRZY3CXJ+wg^ZT&dh`9%e!TR0R&&ubIAJY#RO=8i;wAy?;sm-jLSJA%K zRbwGbqIZwZ#c=RiM#2@l083Jm=FAiKIF0Go0J?%d$P)%5wTaJeiTl~gIIIgJ?c+oL zU>sJ^mCz0pM+JdQn=QP$>3VOKe5{wdk|iAL;YQT_7Q6<)u=wAH&=Wzj^AF+GU7io< zMVAXg+-PM}mr9NU95SVRRb5{hF}BsU%QhH)(~bg%L!KTNDw0x|Ouks>g%<(ON-2PD zbLYP{_Ly`??4l;mw-@-Ue}_e~eja7s=yE)9v?=XArUla>o@Hz0+#4!0dJl94qAk>9 zhGlx(hpcdNt&(`$tAB(h)gzU&0;``P?$bp92e=Q`L4z9}c;}_Q48tKt_~ z8Wq2vUDTJYd!cbR$*I4f@mUcJ#21R@dhDt5?jqd<=a&Sv8*Hj!uSMB1WK<8&zwH zW~LY$WWQtnns&O8*f!#E!ZuiGNH^zG24X+}aSoEs_rw4VrGC2<0dd^-2z}YnOIs?i zV*|r?02*v;bgk?&?pQsDp;11r>A;E_?cQ3ZyJe_(s(UeD*QVL!W1n!yY@W+`L~~@d z`aZg?w`Ny_VBMbRura@2))D&jSDJR(pfTUFZ%ncuZ8mUm;VJmT^q_4nBIypZ7t!!-@>cKwJE4M8=(IXcExH z_Ll-WQKMEvv~zy&omShBsW0OAcg?$@N7q$h9Km~^?@b=O8f3hlT&gn7-*A39r$RIW zm@Lw|sorF9 z*AsE+{~Ve!diHc1l}9_QQy-2ZJNP>Y&f;iNNGwtZzqk6c>(cnje9z?*G9uHVAqp>6 zAp$h*DPP7KgRe^3HmkTY+9p)rU%mTu`Fz1z*rX~mTi&k%HuWuL-vxlvyr5i6+9zrF zI<-|XK%N*9tpeJ2a1tV3iwrWhtBh^!Femd@h(Cax3_2lp`&=OXqy=Q6N465z?p4fu zbNza%t8*{e$)qZk*9#YR@tRfErxXC=d)>Y;1B-zECDh9?m-35KZxKi|xfA7D1e*EB zW7k|un!maw?9;4Brb)ykEkG}wxtHX#Y`Nec*-Nja=p1c6)qsRsvxe;s7QDPXr@O3gJX_)pXBh&ZxnPz#TtxjGGct~Vgj z>byhO17S*Xso4>K^VVPhkaigH z`2Ry>-g{c4lo2%u;5f$Pd!*Cg3LpcOleq3ia7gc!fK+)H)}Q+O?~JdZvV}X4;LOI1EkQgF%@MZM=VZL0Fn-&64@&a)j_&n0x|&lT(@T zUjxqdlQ`cq^`Rf+07sx-UOfy@@>52vmosdz71M#s6Ef+5{{(*F@b}UIdrZS0{VB3$ z@vF1XI}_N3V4W}UM{S{?&cBgpyW8M?OrB*X&XDP-J#PQ|_{I9pvT&(MVb2iF9563&%Rfsv%m#yq(t~yR9=Aq$*sY7* z{73D!uNnHD4W4d6cmU)Kz9gAL9q$}LdiqXG_oZCyp}&49=O|Rs;?Er`z6S%B1#c9R zI(b98=@amh>O7wZF5r>C=u09Ji>ao1jNd`7f2k(M8VC034AI2>S3yU$b>f8~WbtY* z2eH#-6Mla=5A*v1ZpGLA#2=z=aSKJ?suE9~uZu63iOv3G^Sj_orNUAfEizft>xR!r zDOXJ=Bd@3#RuZSl^mA3)25dAP(N@vLpQ(R{#d&jJ`KPtF^s+w!w@mS+3R#05A~{s$ z{{q}XYNaxTZ1qLsf$w~2FgPmZr5ixA>-xJ0jKuSkZ*v^*J7eBH60xYJ=~Uz9h*?rZ z|JRkt{pcS3N}|FGkUbBdDR|?d@C4C*_U#(CVxj(IO-fYHelSot3jyFH*P?r<`7)4q z^DW%Ru_^9MhZpG}`-nq~E@F&;3VL-GU0w;sa_ zm^{d);~lNC^0*Dx%n93sfsCNiOHSIyBCx4~*>jvkH}vt^wqHUM&$gpe9@4o-xP;aR zcN(l_xqusrRdSc{HqCwhJktVo*FFA(AKcs};9UadG|rwpN@l4P=eY-GL0}DK2+ejs zJl>VKG$f#@4RoN*a?eloO?qnG$8mAyzr%>H#ucn|8GnFI#Rjy4ILyEMz8U~P$c1kR z#8~@oOv&y8<{!9m4EU7q2^HTGS^a|YxBl*}&pI?*HhMXh{W=qv*|7nP87ZS+SeEi9 zeH8k_C*&fy3(`E(f;S z`9Rfc+1b9p8U1@#rvbk|JkxLz{GRk|)j2=res$pCvrC8;P+*Dp)JB z)rj`Mr`u$~v)L_QVEYlU!-j@J-*sg7ZJ08c8guX(eHXE542rO$w!rW}6MlKs*xvbU zRWSGMCD;`|*k6}cnP@liIs4~>DR~H=IBG4yivfnze*r)bDPeDs3|XB32)g)^aM&I8 z$^Wd%^rYV7@{|8RHbohBLeT5|?^mpe1pP<<2kWUx;C%W&j!V`Xojm`!oc@O|x(ERk z`u{ None: + self.runs: list[_RunRecord] = [] + self._by_id: dict[str, _RunRecord] = {} + + def record_create(self, **kwargs: Any) -> None: + run_id = str(kwargs.get("id", kwargs.get("run_id", ""))) + if run_id in self._by_id: + return + rec = _RunRecord( + id=run_id, + parent_run_id=( + str(kwargs["parent_run_id"]) if kwargs.get("parent_run_id") else None + ), + name=kwargs.get("name", ""), + run_type=kwargs.get("run_type", "chain"), + inputs=kwargs.get("inputs", {}), + ) + self.runs.append(rec) + self._by_id[rec.id] = rec + + def record_update(self, run_id: str, **kwargs: Any) -> None: + run_id_str = str(run_id) + rec = self._by_id.get(run_id_str) + if rec is None: + return + if "outputs" in kwargs: + rec.outputs = kwargs["outputs"] + if "error" in kwargs: + rec.error = kwargs["error"] + + def clear(self) -> None: + self.runs.clear() + self._by_id.clear() + + +def dump_traces(collector: InMemoryRunCollector) -> list[list[str]]: + """Reconstruct parent-child hierarchy grouped by root trace. + + Returns a list of traces, where each trace is a list of indented + strings (same format as dump_runs). Each trace starts from a + different root run. + """ + runs = collector.runs + children: dict[str | None, list[_RunRecord]] = {} + for r in runs: + children.setdefault(r.parent_run_id, []).append(r) + + # Strict: reject dangling parent references + known_ids = {r.id for r in runs} + for r in runs: + if r.parent_run_id is not None and r.parent_run_id not in known_ids: + raise AssertionError( + f"Run {r.name!r} (id={r.id}) has parent_run_id={r.parent_run_id} " + f"which is not in the collected runs — dangling parent reference" + ) + + traces: list[list[str]] = [] + for root in children.get(None, []): + trace: list[str] = [] + + def _walk(parent_id: str | None, depth: int) -> None: + for child in children.get(parent_id, []): + trace.append(" " * depth + child.name) + _walk(child.id, depth + 1) + + trace.append(root.name) + _walk(root.id, 1) + traces.append(trace) + + return traces + + +def dump_runs(collector: InMemoryRunCollector) -> list[str]: + """Flat list of all runs across all traces.""" + return [run for trace in dump_traces(collector) for run in trace] + + +def find_traces(traces: list[list[str]], root_name: str) -> list[list[str]]: + """Filter traces by exact root name match.""" + return [t for t in traces if t[0] == root_name] + + +def make_mock_ls_client(collector: InMemoryRunCollector) -> MagicMock: + """Create a mock langsmith.Client wired to a collector.""" + client = MagicMock() + client.create_run.side_effect = collector.record_create + client.update_run.side_effect = collector.record_update + client.session = MagicMock() + client.tracing_queue = MagicMock() + return client diff --git a/tests/contrib/langsmith/test_background_io.py b/tests/contrib/langsmith/test_background_io.py new file mode 100644 index 000000000..79c48eeef --- /dev/null +++ b/tests/contrib/langsmith/test_background_io.py @@ -0,0 +1,651 @@ +"""Unit tests for _ReplaySafeRunTree and _RootReplaySafeRunTreeFactory. + +Covers create_child propagation, executor-backed post/patch, +replay suppression, and post-shutdown fallback. +""" + +from __future__ import annotations + +import logging +import threading +import uuid +from concurrent.futures import ThreadPoolExecutor +from datetime import datetime, timezone +from typing import Any +from unittest.mock import MagicMock, patch + +import pytest +from langsmith.run_trees import RunTree + +from temporalio.contrib.langsmith._interceptor import ( + _ReplaySafeRunTree, + _RootReplaySafeRunTreeFactory, + _uuid_from_random, +) + +# Common patch targets +_MOD = "temporalio.contrib.langsmith._interceptor" +_PATCH_IN_WORKFLOW = f"{_MOD}.temporalio.workflow.in_workflow" +_PATCH_IS_REPLAYING = f"{_MOD}.temporalio.workflow.unsafe.is_replaying_history_events" +_PATCH_WF_NOW = f"{_MOD}.temporalio.workflow.now" +_PATCH_GET_WF_RANDOM = f"{_MOD}._get_workflow_random" + + +def _make_executor() -> ThreadPoolExecutor: + """Create a single-worker executor for tests.""" + return ThreadPoolExecutor(max_workers=1) + + +def _make_mock_run(**kwargs: Any) -> MagicMock: + """Create a mock RunTree.""" + mock = MagicMock(spec=RunTree) + mock.to_headers.return_value = {"langsmith-trace": "test"} + mock.ls_client = kwargs.get("ls_client", MagicMock()) + mock.session_name = kwargs.get("session_name", "test-session") + mock.replicas = kwargs.get("replicas", []) + mock.id = kwargs.get("id", uuid.uuid4()) + mock.name = kwargs.get("name", "test-run") + # create_child returns another mock RunTree by default + child_mock = MagicMock(spec=RunTree) + child_mock.id = uuid.uuid4() + child_mock.ls_client = mock.ls_client + child_mock.session_name = mock.session_name + child_mock.replicas = mock.replicas + mock.create_child.return_value = child_mock + return mock + + +# =================================================================== +# TestCreateChildPropagation +# =================================================================== + + +class TestCreateChildPropagation: + """Tests for _ReplaySafeRunTree.create_child() override.""" + + def test_create_child_returns_replay_safe_run_tree(self) -> None: + """create_child() must return a _ReplaySafeRunTree wrapping the child.""" + executor = _make_executor() + mock_run = _make_mock_run() + parent = _ReplaySafeRunTree(mock_run, executor=executor) + + child = parent.create_child(name="child-op", run_type="chain") + + assert isinstance(child, _ReplaySafeRunTree) + # The wrapped child should be the result of the inner run's create_child + mock_run.create_child.assert_called_once() + + @patch(_PATCH_GET_WF_RANDOM) + @patch(_PATCH_WF_NOW) + @patch(_PATCH_IN_WORKFLOW, return_value=True) + def test_create_child_injects_deterministic_ids_in_workflow( + self, + _mock_in_wf: Any, + mock_now: Any, + mock_get_random: Any, + ) -> None: + """In workflow context, create_child injects deterministic run_id and start_time.""" + import random as stdlib_random + + rng = stdlib_random.Random(42) + mock_get_random.return_value = rng + fake_now = datetime(2025, 1, 1, tzinfo=timezone.utc) + mock_now.return_value = fake_now + + expected_id = _uuid_from_random(stdlib_random.Random(42)) # same seed + + executor = _make_executor() + mock_run = _make_mock_run() + parent = _ReplaySafeRunTree(mock_run, executor=executor) + + # Simulate what _setup_run does: passes run_id=None explicitly + child = parent.create_child(name="child-op", run_type="chain", run_id=None) + + assert isinstance(child, _ReplaySafeRunTree) + # Verify the kwargs passed to inner create_child had deterministic values + call_kwargs = mock_run.create_child.call_args.kwargs + assert call_kwargs["run_id"] == expected_id + assert call_kwargs["start_time"] == fake_now + + def test_create_child_passes_through_kwargs(self) -> None: + """create_child passes through all kwargs to the inner run's create_child.""" + executor = _make_executor() + mock_run = _make_mock_run() + parent = _ReplaySafeRunTree(mock_run, executor=executor) + + child = parent.create_child( + name="child-op", + run_type="llm", + inputs={"prompt": "hello"}, + tags=["test"], + extra_kwarg="future-proof", + ) + + assert isinstance(child, _ReplaySafeRunTree) + call_kwargs = mock_run.create_child.call_args.kwargs + assert call_kwargs["name"] == "child-op" + assert call_kwargs["run_type"] == "llm" + assert call_kwargs["inputs"] == {"prompt": "hello"} + assert call_kwargs["tags"] == ["test"] + assert call_kwargs["extra_kwarg"] == "future-proof" + + def test_create_child_propagates_executor_to_child(self) -> None: + """The child _ReplaySafeRunTree must receive the same executor reference.""" + executor = _make_executor() + mock_run = _make_mock_run() + parent = _ReplaySafeRunTree(mock_run, executor=executor) + + child = parent.create_child(name="child-op", run_type="chain") + + assert isinstance(child, _ReplaySafeRunTree) + # Child should have the same executor + assert child._executor is executor + + @patch(_PATCH_IN_WORKFLOW, return_value=False) + def test_create_child_no_deterministic_ids_outside_workflow( + self, _mock_in_wf: Any + ) -> None: + """Outside workflow context, create_child does NOT inject deterministic IDs.""" + executor = _make_executor() + mock_run = _make_mock_run() + parent = _ReplaySafeRunTree(mock_run, executor=executor) + + child = parent.create_child(name="child-op", run_type="chain", run_id=None) + + assert isinstance(child, _ReplaySafeRunTree) + # run_id should remain None (not overridden) + call_kwargs = mock_run.create_child.call_args.kwargs + assert call_kwargs.get("run_id") is None + + @patch(_PATCH_GET_WF_RANDOM) + @patch(_PATCH_WF_NOW) + @patch(_PATCH_IN_WORKFLOW, return_value=True) + def test_create_child_respects_explicit_run_id( + self, + _mock_in_wf: Any, + mock_now: Any, + mock_get_random: Any, + ) -> None: + """If run_id is explicitly provided (not None), create_child preserves it.""" + import random as stdlib_random + + mock_get_random.return_value = stdlib_random.Random(42) + mock_now.return_value = datetime(2025, 1, 1, tzinfo=timezone.utc) + + executor = _make_executor() + mock_run = _make_mock_run() + parent = _ReplaySafeRunTree(mock_run, executor=executor) + + explicit_id = uuid.uuid4() + child = parent.create_child( + name="child-op", run_type="chain", run_id=explicit_id + ) + + assert isinstance(child, _ReplaySafeRunTree) + call_kwargs = mock_run.create_child.call_args.kwargs + assert call_kwargs["run_id"] == explicit_id + + +# =================================================================== +# TestExecutorBackedPostPatch +# =================================================================== + + +class TestExecutorBackedPostPatch: + """Tests for executor-backed post()/patch() in _ReplaySafeRunTree.""" + + @patch(_PATCH_IS_REPLAYING, return_value=False) + @patch(_PATCH_IN_WORKFLOW, return_value=True) + def test_post_submits_to_executor_in_workflow( + self, _mock_in_wf: Any, _mock_replaying: Any + ) -> None: + """In workflow context, post() submits to executor, not inline.""" + executor = _make_executor() + mock_run = _make_mock_run() + calling_thread = threading.current_thread() + post_thread: list[threading.Thread] = [] + + def record_thread(*_args: Any, **_kwargs: Any) -> None: + post_thread.append(threading.current_thread()) + + mock_run.post.side_effect = record_thread + tree = _ReplaySafeRunTree(mock_run, executor=executor) + + tree.post() + + # Wait for executor to finish + executor.shutdown(wait=True) + + # post should have been called on the inner run via executor + mock_run.post.assert_called_once() + # Verify it ran on the executor thread, not the calling thread + assert len(post_thread) == 1 + assert post_thread[0] is not calling_thread + + @patch(_PATCH_IS_REPLAYING, return_value=False) + @patch(_PATCH_IN_WORKFLOW, return_value=True) + def test_patch_submits_to_executor_in_workflow( + self, _mock_in_wf: Any, _mock_replaying: Any + ) -> None: + """In workflow context, patch() submits to executor, not inline.""" + executor = _make_executor() + mock_run = _make_mock_run() + tree = _ReplaySafeRunTree(mock_run, executor=executor) + + tree.patch() + + executor.shutdown(wait=True) + mock_run.patch.assert_called_once() + + @patch(_PATCH_IN_WORKFLOW, return_value=False) + def test_post_delegates_directly_outside_workflow(self, _mock_in_wf: Any) -> None: + """Outside workflow, post() delegates directly to the inner run.""" + executor = _make_executor() + mock_run = _make_mock_run() + tree = _ReplaySafeRunTree(mock_run, executor=executor) + + tree.post() + + mock_run.post.assert_called_once() + + @patch(_PATCH_IN_WORKFLOW, return_value=False) + def test_patch_delegates_directly_outside_workflow(self, _mock_in_wf: Any) -> None: + """Outside workflow, patch() delegates directly to the inner run.""" + executor = _make_executor() + mock_run = _make_mock_run() + tree = _ReplaySafeRunTree(mock_run, executor=executor) + + tree.patch(exclude_inputs=True) + + mock_run.patch.assert_called_once_with(exclude_inputs=True) + + @patch(_PATCH_IS_REPLAYING, return_value=False) + @patch(_PATCH_IN_WORKFLOW, return_value=True) + def test_post_error_logged_via_done_callback( + self, + _mock_in_wf: Any, + _mock_replaying: Any, + caplog: pytest.LogCaptureFixture, + ) -> None: + """Errors from fire-and-forget post() are logged via Future.add_done_callback.""" + executor = _make_executor() + mock_run = _make_mock_run() + mock_run.post.side_effect = RuntimeError("LangSmith API error") + tree = _ReplaySafeRunTree(mock_run, executor=executor) + + with caplog.at_level(logging.ERROR): + tree.post() + executor.shutdown(wait=True) + + # The error should have been logged + assert any("LangSmith API error" in record.message for record in caplog.records) + + @patch(_PATCH_IS_REPLAYING, return_value=False) + @patch(_PATCH_IN_WORKFLOW, return_value=True) + def test_patch_error_logged_via_done_callback( + self, + _mock_in_wf: Any, + _mock_replaying: Any, + caplog: pytest.LogCaptureFixture, + ) -> None: + """Errors from fire-and-forget patch() are logged via Future.add_done_callback.""" + executor = _make_executor() + mock_run = _make_mock_run() + mock_run.patch.side_effect = RuntimeError("LangSmith patch error") + tree = _ReplaySafeRunTree(mock_run, executor=executor) + + with caplog.at_level(logging.ERROR): + tree.patch() + executor.shutdown(wait=True) + + # The error should have been logged + assert any( + "LangSmith patch error" in record.message for record in caplog.records + ) + + +# =================================================================== +# TestReplaySuppression +# =================================================================== + + +class TestReplaySuppression: + """Tests for _is_replaying() check before executor submission.""" + + @patch(_PATCH_IS_REPLAYING, return_value=True) + @patch(_PATCH_IN_WORKFLOW, return_value=True) + def test_post_noop_during_replay( + self, _mock_in_wf: Any, _mock_replaying: Any + ) -> None: + """post() is a no-op during replay — no executor submission.""" + executor = _make_executor() + mock_run = _make_mock_run() + tree = _ReplaySafeRunTree(mock_run, executor=executor) + + tree.post() + + executor.shutdown(wait=True) + mock_run.post.assert_not_called() + + @patch(_PATCH_IS_REPLAYING, return_value=True) + @patch(_PATCH_IN_WORKFLOW, return_value=True) + def test_patch_noop_during_replay( + self, _mock_in_wf: Any, _mock_replaying: Any + ) -> None: + """patch() is a no-op during replay.""" + executor = _make_executor() + mock_run = _make_mock_run() + tree = _ReplaySafeRunTree(mock_run, executor=executor) + + tree.patch() + + executor.shutdown(wait=True) + mock_run.patch.assert_not_called() + + @patch(_PATCH_IS_REPLAYING, return_value=True) + @patch(_PATCH_IN_WORKFLOW, return_value=True) + def test_end_noop_during_replay( + self, _mock_in_wf: Any, _mock_replaying: Any + ) -> None: + """end() is a no-op during replay.""" + executor = _make_executor() + mock_run = _make_mock_run() + tree = _ReplaySafeRunTree(mock_run, executor=executor) + + tree.end(outputs={"result": "done"}) + + mock_run.end.assert_not_called() + + @patch(_PATCH_WF_NOW, return_value=datetime.now(timezone.utc)) + @patch(_PATCH_IS_REPLAYING, return_value=False) + @patch(_PATCH_IN_WORKFLOW, return_value=True) + def test_end_delegates_during_normal_execution( + self, _mock_in_wf: Any, _mock_replaying: Any, _mock_now: Any + ) -> None: + """end() delegates to self._run.end() during normal (non-replay) execution.""" + executor = _make_executor() + mock_run = _make_mock_run() + tree = _ReplaySafeRunTree(mock_run, executor=executor) + + tree.end(outputs={"result": "done"}, error="some error") + + mock_run.end.assert_called_once() + call_kwargs = mock_run.end.call_args.kwargs + assert call_kwargs["outputs"] == {"result": "done"} + assert call_kwargs["error"] == "some error" + assert "end_time" in call_kwargs + + +# =================================================================== +# TestRootReplaySafeRunTreeFactory +# =================================================================== + + +class TestRootReplaySafeRunTreeFactory: + """Tests for _RootReplaySafeRunTreeFactory subclass.""" + + def _make_factory(self, **kwargs: Any) -> _RootReplaySafeRunTreeFactory: + """Create a _RootReplaySafeRunTreeFactory for testing.""" + from temporalio.contrib.langsmith._interceptor import ( + _RootReplaySafeRunTreeFactory, + ) + + executor = kwargs.pop("executor", _make_executor()) + mock_client = kwargs.pop("ls_client", MagicMock()) + return _RootReplaySafeRunTreeFactory( + ls_client=mock_client, executor=executor, **kwargs + ) + + def test_post_raises_runtime_error(self) -> None: + """Factory's post() raises RuntimeError — factory must never be posted.""" + factory = self._make_factory() + with pytest.raises(RuntimeError, match="must never be posted"): + factory.post() + + def test_patch_raises_runtime_error(self) -> None: + """Factory's patch() raises RuntimeError — factory must never be patched.""" + factory = self._make_factory() + with pytest.raises(RuntimeError, match="must never be patched"): + factory.patch() + + def test_end_raises_runtime_error(self) -> None: + """Factory's end() raises RuntimeError — factory must never be ended.""" + factory = self._make_factory() + with pytest.raises(RuntimeError, match="must never be ended"): + factory.end(outputs={"status": "ok"}) + + @patch(_PATCH_GET_WF_RANDOM) + @patch(_PATCH_WF_NOW) + @patch(_PATCH_IN_WORKFLOW, return_value=True) + def test_create_child_returns_root_replay_safe_run_tree( + self, + _mock_in_wf: Any, + mock_now: Any, + mock_get_random: Any, + ) -> None: + """Factory's create_child creates a root _ReplaySafeRunTree (no parent_run_id).""" + import random as stdlib_random + + mock_get_random.return_value = stdlib_random.Random(42) + mock_now.return_value = datetime(2025, 1, 1, tzinfo=timezone.utc) + + executor = _make_executor() + mock_client = MagicMock() + factory = self._make_factory(ls_client=mock_client, executor=executor) + + child = factory.create_child(name="traceable-fn", run_type="chain") + + assert isinstance(child, _ReplaySafeRunTree) + # Child should be a root run — no parent_run_id + assert child._run.parent_run_id is None + + def test_create_child_inherits_client_session_and_replicas(self) -> None: + """Factory's children inherit ls_client, session_name, replicas.""" + executor = _make_executor() + mock_client = MagicMock() + mock_replicas = [MagicMock(), MagicMock()] + factory = self._make_factory( + ls_client=mock_client, + executor=executor, + session_name="my-project", + replicas=mock_replicas, + ) + + with patch(_PATCH_IN_WORKFLOW, return_value=False): + child = factory.create_child(name="traceable-fn", run_type="chain") + + assert isinstance(child, _ReplaySafeRunTree) + # Child should have the factory's ls_client, session_name, and replicas + assert child.ls_client is mock_client + assert child.session_name == "my-project" + assert child.replicas is mock_replicas + + def test_create_child_propagates_executor(self) -> None: + """Factory propagates executor to children.""" + executor = _make_executor() + factory = self._make_factory(executor=executor) + + with patch(_PATCH_IN_WORKFLOW, return_value=False): + child = factory.create_child(name="traceable-fn", run_type="chain") + + assert isinstance(child, _ReplaySafeRunTree) + assert child._executor is executor + + def test_create_child_maps_run_id_to_id(self) -> None: + """Factory's create_child maps run_id kwarg to id on the resulting RunTree. + + The run_id kwarg is mapped to id, matching LangSmith's + RunTree.create_child convention (run_trees.py:545). + """ + executor = _make_executor() + factory = self._make_factory(executor=executor) + explicit_id = uuid.uuid4() + + with patch(_PATCH_IN_WORKFLOW, return_value=False): + child = factory.create_child( + name="traceable-fn", run_type="chain", run_id=explicit_id + ) + + assert isinstance(child, _ReplaySafeRunTree) + # The underlying RunTree should have id set to the passed run_id + assert child._run.id == explicit_id + + def test_factory_not_in_collected_runs(self) -> None: + """Factory's post/patch/end raise RuntimeError — factory is never traced.""" + factory = self._make_factory() + + with pytest.raises(RuntimeError): + factory.post() + with pytest.raises(RuntimeError): + factory.patch() + with pytest.raises(RuntimeError): + factory.end() + + +# =================================================================== +# TestPostTimingDelayedExecution +# =================================================================== + + +class TestPostTimingDelayedExecution: + """Tests for post() timing when executor is busy. + + When post() is delayed (executor busy), create_run includes finalized data + (outputs/end_time), and the subsequent update_run from patch() is idempotent. + """ + + @patch(_PATCH_IS_REPLAYING, return_value=False) + @patch(_PATCH_IN_WORKFLOW, return_value=True) + def test_post_patch_fifo_ordering( + self, _mock_in_wf: Any, _mock_replaying: Any + ) -> None: + """post() always completes before patch() starts (FIFO via single-worker executor).""" + executor = _make_executor() + mock_run = _make_mock_run() + call_order: list[str] = [] + + def record_post(*_args: Any, **_kwargs: Any) -> None: + call_order.append("post") + + def record_patch(*_args: Any, **_kwargs: Any) -> None: + call_order.append("patch") + + mock_run.post.side_effect = record_post + mock_run.patch.side_effect = record_patch + + tree = _ReplaySafeRunTree(mock_run, executor=executor) + + tree.post() + tree.patch() + + executor.shutdown(wait=True) + + assert call_order == ["post", "patch"] + + @patch(_PATCH_IS_REPLAYING, return_value=False) + @patch(_PATCH_IN_WORKFLOW, return_value=True) + def test_delayed_post_reads_finalized_fields( + self, _mock_in_wf: Any, _mock_replaying: Any + ) -> None: + """When post() is delayed, create_run sees finalized outputs/end_time. + + Simulates: block executor → submit post() (queued) → call end() on + "workflow thread" to set outputs/end_time → release blocker → verify + post() saw the finalized fields via _get_dicts_safe(). + """ + executor = _make_executor() + mock_run = _make_mock_run() + + # Barrier to block executor so post() is delayed + blocker = threading.Event() + post_saw_outputs: list[Any] = [] + post_saw_end_time: list[Any] = [] + + # Block the executor with a dummy task + def blocking_task() -> None: + blocker.wait(timeout=5.0) + + executor.submit(blocking_task) + + # Record what fields post() sees when it finally runs + def capturing_post(*_args: Any, **_kwargs: Any) -> None: + post_saw_outputs.append(getattr(mock_run, "outputs", None)) + post_saw_end_time.append(getattr(mock_run, "end_time", None)) + + mock_run.post.side_effect = capturing_post + + tree = _ReplaySafeRunTree(mock_run, executor=executor) + + # Submit post() — it's queued behind the blocker + tree.post() + + # Simulate end() on the "workflow thread" while post() is still queued + finalized_outputs = {"result": "done"} + finalized_end_time = datetime(2025, 6, 1, tzinfo=timezone.utc) + mock_run.outputs = finalized_outputs + mock_run.end_time = finalized_end_time + + # Release the blocker — post() now runs and reads finalized fields + blocker.set() + executor.shutdown(wait=True) + + # post() should have seen the finalized outputs and end_time + assert len(post_saw_outputs) == 1 + assert post_saw_outputs[0] == finalized_outputs + assert len(post_saw_end_time) == 1 + assert post_saw_end_time[0] == finalized_end_time + + +# =================================================================== +# TestPostShutdownRaises +# =================================================================== + + +class TestPostShutdownRaises: + """Tests that post/patch raise after executor shutdown.""" + + @patch(_PATCH_IS_REPLAYING, return_value=False) + @patch(_PATCH_IN_WORKFLOW, return_value=True) + def test_post_raises_after_shutdown( + self, _mock_in_wf: Any, _mock_replaying: Any + ) -> None: + """After executor.shutdown(), post() raises RuntimeError.""" + executor = _make_executor() + executor.shutdown(wait=True) + + mock_run = _make_mock_run() + tree = _ReplaySafeRunTree(mock_run, executor=executor) + + with pytest.raises(RuntimeError): + tree.post() + + @patch(_PATCH_IS_REPLAYING, return_value=False) + @patch(_PATCH_IN_WORKFLOW, return_value=True) + def test_patch_raises_after_shutdown( + self, _mock_in_wf: Any, _mock_replaying: Any + ) -> None: + """After executor.shutdown(), patch() raises RuntimeError.""" + executor = _make_executor() + executor.shutdown(wait=True) + + mock_run = _make_mock_run() + tree = _ReplaySafeRunTree(mock_run, executor=executor) + + with pytest.raises(RuntimeError): + tree.patch() + + +# =================================================================== +# Test_ReplaySafeRunTreeConstructor +# =================================================================== + + +class Test_ReplaySafeRunTreeConstructor: + """Tests for _ReplaySafeRunTree accepting executor parameter.""" + + def test_constructor_stores_executor(self) -> None: + """The executor is stored and accessible.""" + executor = _make_executor() + mock_run = _make_mock_run() + tree = _ReplaySafeRunTree(mock_run, executor=executor) + assert tree._executor is executor diff --git a/tests/contrib/langsmith/test_integration.py b/tests/contrib/langsmith/test_integration.py new file mode 100644 index 000000000..78d48c71e --- /dev/null +++ b/tests/contrib/langsmith/test_integration.py @@ -0,0 +1,1285 @@ +"""Integration tests for LangSmith plugin with real Temporal worker.""" + +from __future__ import annotations + +import asyncio +import uuid +from collections.abc import Callable +from datetime import timedelta +from typing import Any +from unittest.mock import MagicMock + +import nexusrpc.handler +import pytest +from langsmith import traceable, tracing_context + +from temporalio import activity, common, nexus, workflow +from temporalio.client import ( + Client, + WorkflowFailureError, + WorkflowHandle, + WorkflowQueryFailedError, +) +from temporalio.contrib.langsmith import LangSmithPlugin +from temporalio.exceptions import ApplicationError +from temporalio.service import RPCError +from temporalio.testing import WorkflowEnvironment +from tests.contrib.langsmith.conftest import ( + InMemoryRunCollector, + dump_runs, + dump_traces, + find_traces, + make_mock_ls_client, +) +from tests.helpers import new_worker +from tests.helpers.nexus import make_nexus_endpoint_name + +# --------------------------------------------------------------------------- +# Shared @traceable functions and activities +# --------------------------------------------------------------------------- + + +@traceable(name="inner_llm_call") +async def _inner_llm_call(prompt: str) -> str: + """Simulates an LLM call decorated with @traceable.""" + return f"response to: {prompt}" + + +@traceable(name="outer_chain") +async def _outer_chain(prompt: str) -> str: + """A @traceable that calls another @traceable.""" + return await _inner_llm_call(prompt) + + +@traceable +@activity.defn +async def traceable_activity() -> str: + """Activity that calls a @traceable function.""" + result = await _inner_llm_call("hello") + return result + + +@traceable +@activity.defn +async def nested_traceable_activity() -> str: + """Activity with two levels of @traceable nesting.""" + result = await _outer_chain("hello") + return result + + +# --------------------------------------------------------------------------- +# Shared workflows +# --------------------------------------------------------------------------- + + +@workflow.defn +class TraceableActivityWorkflow: + @workflow.run + async def run(self, _input: str = "") -> str: + return await workflow.execute_activity( + traceable_activity, + start_to_close_timeout=timedelta(seconds=10), + ) + + +@nexusrpc.handler.service_handler +class NexusService: + @nexus.workflow_run_operation + async def run_operation( + self, ctx: nexus.WorkflowRunOperationContext, input: str + ) -> nexus.WorkflowHandle[str]: + return await ctx.start_workflow( + TraceableActivityWorkflow.run, + input, + id=f"nexus-wf-{ctx.request_id}", + ) + + +# --------------------------------------------------------------------------- +# Simple/basic workflows and activities +# --------------------------------------------------------------------------- + + +@traceable +@activity.defn +async def simple_activity() -> str: + return "activity-done" + + +@workflow.defn +class SimpleWorkflow: + @workflow.run + async def run(self) -> str: + result = await workflow.execute_activity( + simple_activity, + start_to_close_timeout=timedelta(seconds=10), + ) + return result + + +# --------------------------------------------------------------------------- +# Signal/query/update workflows +# --------------------------------------------------------------------------- + + +@traceable(name="step_with_activity") +async def _step_with_activity() -> str: + """A @traceable step that wraps an activity call.""" + return await workflow.execute_activity( + nested_traceable_activity, + start_to_close_timeout=timedelta(seconds=10), + ) + + +@traceable(name="step_with_child_workflow") +async def _step_with_child_workflow() -> str: + """A @traceable step that wraps a child workflow call.""" + return await workflow.execute_child_workflow( + TraceableActivityWorkflow.run, + id=f"step-child-{workflow.info().workflow_id}", + ) + + +@traceable(name="step_with_nexus") +async def _step_with_nexus() -> str: + """A @traceable step that wraps a nexus operation.""" + nexus_client = workflow.create_nexus_client( + endpoint=make_nexus_endpoint_name(workflow.info().task_queue), + service=NexusService, + ) + nexus_handle = await nexus_client.start_operation( + operation=NexusService.run_operation, + input="test-input", + ) + return await nexus_handle + + +@workflow.defn +class ComprehensiveWorkflow: + def __init__(self) -> None: + self._signal_received = False + self._waiting_for_signal = False + self._complete = False + + @workflow.run + async def run(self) -> str: + await workflow.execute_activity( + nested_traceable_activity, + start_to_close_timeout=timedelta(seconds=10), + ) + await _step_with_activity() + await workflow.execute_local_activity( + nested_traceable_activity, + start_to_close_timeout=timedelta(seconds=10), + ) + await _outer_chain("from-workflow") + await workflow.execute_child_workflow( + TraceableActivityWorkflow.run, + id=f"child-{workflow.info().workflow_id}", + ) + await _step_with_child_workflow() + nexus_client = workflow.create_nexus_client( + endpoint=make_nexus_endpoint_name(workflow.info().task_queue), + service=NexusService, + ) + nexus_handle = await nexus_client.start_operation( + operation=NexusService.run_operation, + input="test-input", + ) + await nexus_handle + await _step_with_nexus() + + self._waiting_for_signal = True + await workflow.wait_condition(lambda: self._signal_received) + await workflow.execute_activity( + nested_traceable_activity, + start_to_close_timeout=timedelta(seconds=10), + ) + await workflow.wait_condition(lambda: self._complete) + return "comprehensive-done" + + @workflow.signal + def my_signal(self, _value: str) -> None: + self._signal_received = True + + @workflow.query + def my_query(self) -> bool: + return self._signal_received + + @workflow.query + def is_waiting_for_signal(self) -> bool: + return self._waiting_for_signal + + @workflow.update + def my_update(self, value: str) -> str: + self._complete = True + return f"updated-{value}" + + @my_update.validator + def validate_my_update(self, value: str) -> None: + if not value: + raise ValueError("empty") + + @workflow.update + def my_unvalidated_update(self, value: str) -> str: + return f"unvalidated-{value}" + + +# --------------------------------------------------------------------------- +# Error workflows and activities +# --------------------------------------------------------------------------- + + +@traceable +@activity.defn +async def failing_activity() -> str: + raise ApplicationError("activity-failed", non_retryable=True) + + +@traceable +@activity.defn +async def benign_failing_activity() -> str: + from temporalio.exceptions import ApplicationErrorCategory + + raise ApplicationError( + "benign-fail", + non_retryable=True, + category=ApplicationErrorCategory.BENIGN, + ) + + +@workflow.defn +class FailingWorkflow: + @workflow.run + async def run(self) -> str: + raise ApplicationError("workflow-failed", non_retryable=True) + + +@workflow.defn +class ActivityFailureWorkflow: + @workflow.run + async def run(self) -> str: + return await workflow.execute_activity( + failing_activity, + start_to_close_timeout=timedelta(seconds=10), + retry_policy=common.RetryPolicy(maximum_attempts=1), + ) + + +@workflow.defn +class BenignErrorWorkflow: + @workflow.run + async def run(self) -> str: + return await workflow.execute_activity( + benign_failing_activity, + start_to_close_timeout=timedelta(seconds=10), + retry_policy=common.RetryPolicy(maximum_attempts=1), + ) + + +# --------------------------------------------------------------------------- +# Helpers +# --------------------------------------------------------------------------- + + +def _make_plugin_and_collector( + **kwargs: Any, +) -> tuple[LangSmithPlugin, InMemoryRunCollector, MagicMock]: + """Create a LangSmithPlugin wired to an InMemoryRunCollector via mock client.""" + collector = InMemoryRunCollector() + mock_ls_client = make_mock_ls_client(collector) + plugin = LangSmithPlugin(client=mock_ls_client, **kwargs) + return plugin, collector, mock_ls_client + + +def _make_client_and_collector( + client: Client, **kwargs: Any +) -> tuple[Client, InMemoryRunCollector, MagicMock]: + """Create a Temporal Client with LangSmith plugin and an InMemoryRunCollector.""" + plugin, collector, mock_ls_client = _make_plugin_and_collector(**kwargs) + config = client.config() + config["plugins"] = [plugin] + return Client(**config), collector, mock_ls_client + + +def _make_temporal_client( + client: Client, mock_ls_client: MagicMock, **kwargs: Any +) -> Client: + """Create a Temporal Client with a fresh LangSmith plugin.""" + plugin = LangSmithPlugin(client=mock_ls_client, **kwargs) + config = client.config() + config["plugins"] = [plugin] + return Client(**config) + + +@traceable(name="poll_query") +async def _poll_query( + handle: WorkflowHandle[Any, Any], + query: Callable[..., Any], + *, + expected: Any = True, +) -> bool: + """Poll a workflow query until it returns the expected value.""" + while True: + try: + result = await handle.query(query) + if result == expected: + return True + except (WorkflowQueryFailedError, RPCError): + pass # Query not yet available (workflow hasn't started) + await asyncio.sleep(1) + + +# --------------------------------------------------------------------------- +# TestBasicTracing +# --------------------------------------------------------------------------- + + +class TestBasicTracing: + async def test_workflow_activity_trace_hierarchy( + self, + client: Client, + env: WorkflowEnvironment, # type:ignore[reportUnusedParameter] + ) -> None: + """StartWorkflow → RunWorkflow → StartActivity → RunActivity hierarchy.""" + temporal_client, collector, _ = _make_client_and_collector( + client, add_temporal_runs=True + ) + + async with new_worker( + temporal_client, + SimpleWorkflow, + activities=[simple_activity], + max_cached_workflows=0, + ) as worker: + result = await temporal_client.start_workflow( + SimpleWorkflow.run, + id=f"basic-trace-{uuid.uuid4()}", + task_queue=worker.task_queue, + ) + assert await result.result() == "activity-done" + + hierarchy = dump_runs(collector) + expected = [ + "StartWorkflow:SimpleWorkflow", + "RunWorkflow:SimpleWorkflow", + " StartActivity:simple_activity", + " RunActivity:simple_activity", + " simple_activity", + ] + assert ( + hierarchy == expected + ), f"Hierarchy mismatch.\nExpected:\n{expected}\nActual:\n{hierarchy}" + + # Verify run_type: RunActivity is "tool", others are "chain" + for run in collector.runs: + if run.name == "RunActivity:simple_activity": + assert ( + run.run_type == "tool" + ), f"Expected RunActivity run_type='tool', got '{run.run_type}'" + else: + assert ( + run.run_type == "chain" + ), f"Expected {run.name} run_type='chain', got '{run.run_type}'" + + # Verify successful runs have outputs == {"status": "ok"} + for run in collector.runs: + if ":" in run.name: # Interceptor runs use "Type:Name" format + assert run.outputs == { + "status": "ok" + }, f"Expected {run.name} outputs={{'status': 'ok'}}, got {run.outputs}" + + +# --------------------------------------------------------------------------- +# TestReplay +# --------------------------------------------------------------------------- + + +class TestReplay: + async def test_no_duplicate_traces_on_replay( + self, + client: Client, + env: WorkflowEnvironment, # type:ignore[reportUnusedParameter] + ) -> None: + """With max_cached_workflows=0 (forcing replay), no duplicate runs appear.""" + temporal_client, collector, _ = _make_client_and_collector( + client, add_temporal_runs=True + ) + + async with new_worker( + temporal_client, + TraceableActivityWorkflow, + activities=[traceable_activity], + max_cached_workflows=0, + ) as worker: + handle = await temporal_client.start_workflow( + TraceableActivityWorkflow.run, + id=f"replay-test-{uuid.uuid4()}", + task_queue=worker.task_queue, + ) + await handle.result() + + # Workflow→activity→@traceable flow should produce exactly these runs + # with no duplicates from replay: + hierarchy = dump_runs(collector) + expected = [ + "StartWorkflow:TraceableActivityWorkflow", + "RunWorkflow:TraceableActivityWorkflow", + " StartActivity:traceable_activity", + " RunActivity:traceable_activity", + " traceable_activity", + " inner_llm_call", + ] + assert hierarchy == expected, ( + f"Hierarchy mismatch (possible replay duplicates).\n" + f"Expected:\n{expected}\nActual:\n{hierarchy}" + ) + + +# --------------------------------------------------------------------------- +# TestErrorTracing +# --------------------------------------------------------------------------- + + +class TestErrorTracing: + async def test_activity_failure_marked( + self, + client: Client, + env: WorkflowEnvironment, # type:ignore[reportUnusedParameter] + ) -> None: + """A failing activity run is marked with an error.""" + temporal_client, collector, _ = _make_client_and_collector( + client, add_temporal_runs=True + ) + + async with new_worker( + temporal_client, + ActivityFailureWorkflow, + activities=[failing_activity], + workflow_failure_exception_types=[ApplicationError], + max_cached_workflows=0, + ) as worker: + handle = await temporal_client.start_workflow( + ActivityFailureWorkflow.run, + id=f"act-fail-{uuid.uuid4()}", + task_queue=worker.task_queue, + ) + with pytest.raises(WorkflowFailureError): + await handle.result() + + hierarchy = dump_runs(collector) + expected = [ + "StartWorkflow:ActivityFailureWorkflow", + "RunWorkflow:ActivityFailureWorkflow", + " StartActivity:failing_activity", + " RunActivity:failing_activity", + " failing_activity", + ] + assert ( + hierarchy == expected + ), f"Hierarchy mismatch.\nExpected:\n{expected}\nActual:\n{hierarchy}" + # Verify the RunActivity run has an error + activity_runs = [ + r for r in collector.runs if r.name == "RunActivity:failing_activity" + ] + assert len(activity_runs) == 1 + assert activity_runs[0].error == "ApplicationError: activity-failed" + + async def test_workflow_failure_marked( + self, + client: Client, + env: WorkflowEnvironment, # type:ignore[reportUnusedParameter] + ) -> None: + """A failing workflow run is marked with an error.""" + temporal_client, collector, _ = _make_client_and_collector( + client, add_temporal_runs=True + ) + + async with new_worker( + temporal_client, + FailingWorkflow, + workflow_failure_exception_types=[ApplicationError], + max_cached_workflows=0, + ) as worker: + handle = await temporal_client.start_workflow( + FailingWorkflow.run, + id=f"wf-fail-{uuid.uuid4()}", + task_queue=worker.task_queue, + ) + with pytest.raises(WorkflowFailureError): + await handle.result() + + hierarchy = dump_runs(collector) + expected = [ + "StartWorkflow:FailingWorkflow", + "RunWorkflow:FailingWorkflow", + ] + assert ( + hierarchy == expected + ), f"Hierarchy mismatch.\nExpected:\n{expected}\nActual:\n{hierarchy}" + # Verify the RunWorkflow run has an error + wf_runs = [r for r in collector.runs if r.name == "RunWorkflow:FailingWorkflow"] + assert len(wf_runs) == 1 + assert wf_runs[0].error == "ApplicationError: workflow-failed" + + async def test_benign_error_not_marked( + self, + client: Client, + env: WorkflowEnvironment, # type:ignore[reportUnusedParameter] + ) -> None: + """A benign ApplicationError does NOT mark the run as errored.""" + temporal_client, collector, _ = _make_client_and_collector( + client, add_temporal_runs=True + ) + + async with new_worker( + temporal_client, + BenignErrorWorkflow, + activities=[benign_failing_activity], + workflow_failure_exception_types=[ApplicationError], + max_cached_workflows=0, + ) as worker: + handle = await temporal_client.start_workflow( + BenignErrorWorkflow.run, + id=f"benign-{uuid.uuid4()}", + task_queue=worker.task_queue, + ) + with pytest.raises(WorkflowFailureError): + await handle.result() + + hierarchy = dump_runs(collector) + expected = [ + "StartWorkflow:BenignErrorWorkflow", + "RunWorkflow:BenignErrorWorkflow", + " StartActivity:benign_failing_activity", + " RunActivity:benign_failing_activity", + " benign_failing_activity", + ] + assert ( + hierarchy == expected + ), f"Hierarchy mismatch.\nExpected:\n{expected}\nActual:\n{hierarchy}" + # The RunActivity run for benign error should NOT have error set + activity_runs = [ + r for r in collector.runs if r.name == "RunActivity:benign_failing_activity" + ] + assert len(activity_runs) == 1 + assert activity_runs[0].error is None + + +# --------------------------------------------------------------------------- +# TestComprehensiveTracing +# --------------------------------------------------------------------------- + + +class TestComprehensiveTracing: + async def test_comprehensive_with_temporal_runs( + self, client: Client, env: WorkflowEnvironment + ) -> None: + """Full trace hierarchy with worker restart mid-workflow. + + user_pipeline only wraps start_workflow (completing before the worker + starts), so poll/signal/query traces are naturally separate root traces. + """ + if env.supports_time_skipping: + pytest.skip("Time-skipping server doesn't persist headers.") + + task_queue = f"comprehensive-{uuid.uuid4()}" + workflow_id = f"comprehensive-{uuid.uuid4()}" + collector = InMemoryRunCollector() + mock_ls = make_mock_ls_client(collector) + temporal_client_1 = _make_temporal_client( + client, mock_ls, add_temporal_runs=True + ) + + @traceable(name="user_pipeline") + async def user_pipeline() -> WorkflowHandle[Any, Any]: + return await temporal_client_1.start_workflow( + ComprehensiveWorkflow.run, + id=workflow_id, + task_queue=task_queue, + ) + + with tracing_context(client=mock_ls, enabled=True): + # Start workflow — no worker yet, just a server RPC + handle = await user_pipeline() + + # Phase 1: worker picks up workflow, poll until signal wait + async with new_worker( + temporal_client_1, + ComprehensiveWorkflow, + TraceableActivityWorkflow, + activities=[nested_traceable_activity, traceable_activity], + nexus_service_handlers=[NexusService()], + task_queue=task_queue, + max_cached_workflows=0, + ) as worker: + await env.create_nexus_endpoint( + make_nexus_endpoint_name(worker.task_queue), + worker.task_queue, + ) + assert await _poll_query( + handle, + ComprehensiveWorkflow.is_waiting_for_signal, + expected=True, + ), "Workflow never reached signal wait point" + # Raw-client query (no LangSmith interceptor) — root-level trace + raw_handle = client.get_workflow_handle(workflow_id) + await raw_handle.query(ComprehensiveWorkflow.is_waiting_for_signal) + + # Phase 2: fresh worker, signal to resume, complete + temporal_client_2 = _make_temporal_client( + client, mock_ls, add_temporal_runs=True + ) + async with new_worker( + temporal_client_2, + ComprehensiveWorkflow, + TraceableActivityWorkflow, + activities=[nested_traceable_activity, traceable_activity], + nexus_service_handlers=[NexusService()], + task_queue=task_queue, + max_cached_workflows=0, + ): + handle_2 = temporal_client_2.get_workflow_handle(workflow_id) + await handle_2.query(ComprehensiveWorkflow.my_query) + await handle_2.signal(ComprehensiveWorkflow.my_signal, "hello") + await handle_2.execute_update( + ComprehensiveWorkflow.my_unvalidated_update, "test" + ) + await handle_2.execute_update(ComprehensiveWorkflow.my_update, "finish") + result = await handle_2.result() + + assert result == "comprehensive-done" + + traces = dump_traces(collector) + + # user_pipeline trace: StartWorkflow + full workflow execution tree + workflow_traces = find_traces(traces, "user_pipeline") + assert len(workflow_traces) == 1 + assert workflow_traces[0] == [ + "user_pipeline", + " StartWorkflow:ComprehensiveWorkflow", + " RunWorkflow:ComprehensiveWorkflow", + " StartActivity:nested_traceable_activity", + " RunActivity:nested_traceable_activity", + " nested_traceable_activity", + " outer_chain", + " inner_llm_call", + # step-wrapped activity + " step_with_activity", + " StartActivity:nested_traceable_activity", + " RunActivity:nested_traceable_activity", + " nested_traceable_activity", + " outer_chain", + " inner_llm_call", + " StartActivity:nested_traceable_activity", + " RunActivity:nested_traceable_activity", + " nested_traceable_activity", + " outer_chain", + " inner_llm_call", + " outer_chain", + " inner_llm_call", + " StartChildWorkflow:TraceableActivityWorkflow", + " RunWorkflow:TraceableActivityWorkflow", + " StartActivity:traceable_activity", + " RunActivity:traceable_activity", + " traceable_activity", + " inner_llm_call", + # step-wrapped child workflow + " step_with_child_workflow", + " StartChildWorkflow:TraceableActivityWorkflow", + " RunWorkflow:TraceableActivityWorkflow", + " StartActivity:traceable_activity", + " RunActivity:traceable_activity", + " traceable_activity", + " inner_llm_call", + " StartNexusOperation:NexusService/run_operation", + " RunStartNexusOperationHandler:NexusService/run_operation", + " StartWorkflow:TraceableActivityWorkflow", + " RunWorkflow:TraceableActivityWorkflow", + " StartActivity:traceable_activity", + " RunActivity:traceable_activity", + " traceable_activity", + " inner_llm_call", + # step-wrapped nexus operation + " step_with_nexus", + " StartNexusOperation:NexusService/run_operation", + " RunStartNexusOperationHandler:NexusService/run_operation", + " StartWorkflow:TraceableActivityWorkflow", + " RunWorkflow:TraceableActivityWorkflow", + " StartActivity:traceable_activity", + " RunActivity:traceable_activity", + " traceable_activity", + " inner_llm_call", + # post-signal + " StartActivity:nested_traceable_activity", + " RunActivity:nested_traceable_activity", + " nested_traceable_activity", + " outer_chain", + " inner_llm_call", + ] + + # poll_query trace (separate root, variable number of iterations) + poll_traces = find_traces(traces, "poll_query") + assert len(poll_traces) == 1 + poll = poll_traces[0] + assert poll[0] == "poll_query" + poll_children = poll[1:] + for i in range(0, len(poll_children), 2): + assert poll_children[i] == " QueryWorkflow:is_waiting_for_signal" + assert poll_children[i + 1] == " HandleQuery:is_waiting_for_signal" + + # Raw-client query — no parent context, appears as root + raw_query_traces = [t for t in traces if t[0].startswith("HandleQuery:")] + assert len(raw_query_traces) == 1 + + # Phase 2: each operation is its own root trace + query_traces = find_traces(traces, "QueryWorkflow:my_query") + assert len(query_traces) == 1 + assert query_traces[0] == [ + "QueryWorkflow:my_query", + " HandleQuery:my_query", + ] + + signal_traces = find_traces(traces, "SignalWorkflow:my_signal") + assert len(signal_traces) == 1 + assert signal_traces[0] == [ + "SignalWorkflow:my_signal", + " HandleSignal:my_signal", + ] + + update_traces = find_traces(traces, "StartWorkflowUpdate:my_update") + assert len(update_traces) == 1 + assert update_traces[0] == [ + "StartWorkflowUpdate:my_update", + " ValidateUpdate:my_update", + " HandleUpdate:my_update", + ] + + # Update without a validator — no ValidateUpdate trace + unvalidated_traces = find_traces( + traces, "StartWorkflowUpdate:my_unvalidated_update" + ) + assert len(unvalidated_traces) == 1 + assert unvalidated_traces[0] == [ + "StartWorkflowUpdate:my_unvalidated_update", + " HandleUpdate:my_unvalidated_update", + ] + + async def test_comprehensive_without_temporal_runs( + self, client: Client, env: WorkflowEnvironment + ) -> None: + """Same workflow with add_temporal_runs=False and worker restart. + + Only @traceable runs appear. Context propagation via headers still works. + user_pipeline only wraps start_workflow, so poll traces are separate roots. + """ + if env.supports_time_skipping: + pytest.skip("Time-skipping server doesn't persist headers.") + + task_queue = f"comprehensive-no-runs-{uuid.uuid4()}" + workflow_id = f"comprehensive-no-runs-{uuid.uuid4()}" + collector = InMemoryRunCollector() + mock_ls = make_mock_ls_client(collector) + temporal_client_1 = _make_temporal_client( + client, mock_ls, add_temporal_runs=False + ) + + @traceable(name="user_pipeline") + async def user_pipeline() -> WorkflowHandle[Any, Any]: + return await temporal_client_1.start_workflow( + ComprehensiveWorkflow.run, + id=workflow_id, + task_queue=task_queue, + ) + + with tracing_context(client=mock_ls, enabled=True): + handle = await user_pipeline() + + # Phase 1: worker picks up workflow, poll until signal wait + async with new_worker( + temporal_client_1, + ComprehensiveWorkflow, + TraceableActivityWorkflow, + activities=[nested_traceable_activity, traceable_activity], + nexus_service_handlers=[NexusService()], + task_queue=task_queue, + max_cached_workflows=0, + ) as worker: + await env.create_nexus_endpoint( + make_nexus_endpoint_name(worker.task_queue), + worker.task_queue, + ) + # Raw-client query — no interceptor, produces nothing + raw_handle = client.get_workflow_handle(workflow_id) + await raw_handle.query(ComprehensiveWorkflow.is_waiting_for_signal) + assert await _poll_query( + handle, + ComprehensiveWorkflow.is_waiting_for_signal, + expected=True, + ), "Workflow never reached signal wait point" + + # Phase 2: fresh worker, signal to resume, complete + temporal_client_2 = _make_temporal_client( + client, mock_ls, add_temporal_runs=False + ) + async with new_worker( + temporal_client_2, + ComprehensiveWorkflow, + TraceableActivityWorkflow, + activities=[nested_traceable_activity, traceable_activity], + nexus_service_handlers=[NexusService()], + task_queue=task_queue, + max_cached_workflows=0, + ): + handle_2 = temporal_client_2.get_workflow_handle(workflow_id) + await handle_2.signal(ComprehensiveWorkflow.my_signal, "hello") + await handle_2.execute_update( + ComprehensiveWorkflow.my_unvalidated_update, "test" + ) + await handle_2.execute_update(ComprehensiveWorkflow.my_update, "finish") + result = await handle_2.result() + + assert result == "comprehensive-done" + + traces = dump_traces(collector) + + # Main workflow trace (only @traceable runs, nested under user_pipeline) + workflow_traces = find_traces(traces, "user_pipeline") + assert len(workflow_traces) == 1 + expected_workflow = [ + "user_pipeline", + " nested_traceable_activity", + " outer_chain", + " inner_llm_call", + " step_with_activity", + " nested_traceable_activity", + " outer_chain", + " inner_llm_call", + " nested_traceable_activity", + " outer_chain", + " inner_llm_call", + " outer_chain", + " inner_llm_call", + " traceable_activity", + " inner_llm_call", + " step_with_child_workflow", + " traceable_activity", + " inner_llm_call", + " traceable_activity", + " inner_llm_call", + " step_with_nexus", + " traceable_activity", + " inner_llm_call", + # post-signal + " nested_traceable_activity", + " outer_chain", + " inner_llm_call", + ] + assert workflow_traces[0] == expected_workflow, ( + f"Workflow trace mismatch.\n" + f"Expected:\n{expected_workflow}\nActual:\n{workflow_traces[0]}" + ) + + # Poll query — separate root, just the @traceable wrapper, no Temporal children + poll_traces = find_traces(traces, "poll_query") + assert len(poll_traces) == 1 + assert poll_traces[0] == ["poll_query"] + + +# --------------------------------------------------------------------------- +# TestBackgroundIOIntegration — _RootReplaySafeRunTreeFactory + sync @traceable +# --------------------------------------------------------------------------- + + +@traceable(name="sync_inner_llm_call") +def _sync_inner_llm_call(prompt: str) -> str: + """Sync @traceable simulating an LLM call.""" + return f"sync-response to: {prompt}" + + +@traceable(name="sync_outer_chain") +def _sync_outer_chain(prompt: str) -> str: + """Sync @traceable that calls another sync @traceable.""" + return _sync_inner_llm_call(prompt) + + +@traceable(name="async_calls_sync") +async def _async_calls_sync(prompt: str) -> str: + """Async @traceable that calls a sync @traceable — the interesting mixed case.""" + return _sync_inner_llm_call(prompt) + + +@workflow.defn +class FactoryTraceableWorkflow: + """Workflow exercising _RootReplaySafeRunTreeFactory with async, sync, and mixed @traceable. + + Covers three code paths through create_child: + - async→async nesting + - sync→sync nesting (sync @traceable entry to factory) + - async→sync nesting (cross-boundary case) + """ + + @workflow.run + async def run(self) -> str: + r1 = await _outer_chain("async") + r2 = _sync_outer_chain("sync") + r3 = await _async_calls_sync("mixed") + # Activity with nested @traceable + await workflow.execute_activity( + nested_traceable_activity, + start_to_close_timeout=timedelta(seconds=10), + ) + return f"{r1}|{r2}|{r3}" + + +class TestBackgroundIOIntegration: + """Integration tests for workflows using add_temporal_runs=False without external context. + + Exercises the _RootReplaySafeRunTreeFactory path with sync, async, and mixed @traceable + nesting. Verifies root-run creation, correct nesting hierarchy, and replay safety. + """ + + async def test_factory_traceable_no_external_context( + self, + client: Client, + env: WorkflowEnvironment, # type:ignore[reportUnusedParameter] + ) -> None: + """Exercises _RootReplaySafeRunTreeFactory: add_temporal_runs=False, no external context. + + Uses a workflow with async→async, sync→sync, and async→sync @traceable + nesting, plus an activity with nested @traceable. Verifies: + - Each top-level @traceable becomes a root run (factory creates root children) + - Nested @traceable calls nest correctly under their parent + - Activity @traceable also produces correct hierarchy + - No phantom factory run appears in collected runs + - No duplicate run IDs after replay (max_cached_workflows=0) + """ + temporal_client, collector, _ = _make_client_and_collector( + client, add_temporal_runs=False + ) + + async with new_worker( + temporal_client, + FactoryTraceableWorkflow, + activities=[nested_traceable_activity], + max_cached_workflows=0, + ) as worker: + handle = await temporal_client.start_workflow( + FactoryTraceableWorkflow.run, + id=f"factory-{uuid.uuid4()}", + task_queue=worker.task_queue, + ) + result = await handle.result() + + assert ( + result + == "response to: async|sync-response to: sync|sync-response to: mixed" + ) + + hierarchy = dump_runs(collector) + expected = [ + "outer_chain", + " inner_llm_call", + "sync_outer_chain", + " sync_inner_llm_call", + "async_calls_sync", + " sync_inner_llm_call", + "nested_traceable_activity", + " outer_chain", + " inner_llm_call", + ] + assert ( + hierarchy == expected + ), f"Hierarchy mismatch.\nExpected:\n{expected}\nActual:\n{hierarchy}" + + # Verify no duplicate run IDs (replay safety with max_cached_workflows=0) + run_ids = [r.id for r in collector.runs] + assert len(run_ids) == len( + set(run_ids) + ), f"Duplicate run IDs found (replay issue): {run_ids}" + + async def test_factory_passes_project_name_to_children( + self, + client: Client, + env: WorkflowEnvironment, # type:ignore[reportUnusedParameter] + ) -> None: + """Factory children inherit project_name (session_name) from plugin config.""" + temporal_client, _collector, mock_ls_client = _make_client_and_collector( + client, add_temporal_runs=False, project_name="my-ls-project" + ) + + async with new_worker( + temporal_client, + FactoryTraceableWorkflow, + activities=[nested_traceable_activity], + max_cached_workflows=0, + ) as worker: + handle = await temporal_client.start_workflow( + FactoryTraceableWorkflow.run, + id=f"factory-proj-{uuid.uuid4()}", + task_queue=worker.task_queue, + ) + await handle.result() + + # Verify create_run calls include session_name from project_name + for call in mock_ls_client.create_run.call_args_list: + session = call.kwargs.get("session_name") + assert session == "my-ls-project", ( + f"Expected session_name='my-ls-project', got {session!r} " + f"in create_run call: {call.kwargs.get('name')}" + ) + + async def test_mixed_sync_async_traceable_with_temporal_runs( + self, + client: Client, + env: WorkflowEnvironment, # type:ignore[reportUnusedParameter] + ) -> None: + """Exercises _ReplaySafeRunTree.create_child with mixed sync/async @traceable. + + With add_temporal_runs=True, the interceptor creates a real + _ReplaySafeRunTree as parent. This test verifies create_child + propagation works at every level regardless of sync/async, with + correct parent-child hierarchy and no duplicate run IDs after replay. + """ + temporal_client, collector, _ = _make_client_and_collector( + client, add_temporal_runs=True + ) + + async with new_worker( + temporal_client, + FactoryTraceableWorkflow, + activities=[nested_traceable_activity], + max_cached_workflows=0, + ) as worker: + handle = await temporal_client.start_workflow( + FactoryTraceableWorkflow.run, + id=f"mixed-temporal-{uuid.uuid4()}", + task_queue=worker.task_queue, + ) + result = await handle.result() + + assert ( + result + == "response to: async|sync-response to: sync|sync-response to: mixed" + ) + + hierarchy = dump_runs(collector) + # With add_temporal_runs=True, Temporal operations get their own runs. + # @traceable calls nest under the RunWorkflow run. + expected = [ + "StartWorkflow:FactoryTraceableWorkflow", + "RunWorkflow:FactoryTraceableWorkflow", + " outer_chain", + " inner_llm_call", + " sync_outer_chain", + " sync_inner_llm_call", + " async_calls_sync", + " sync_inner_llm_call", + " StartActivity:nested_traceable_activity", + " RunActivity:nested_traceable_activity", + " nested_traceable_activity", + " outer_chain", + " inner_llm_call", + ] + assert ( + hierarchy == expected + ), f"Hierarchy mismatch.\nExpected:\n{expected}\nActual:\n{hierarchy}" + + # Verify no duplicate run IDs (replay safety with max_cached_workflows=0) + run_ids = [r.id for r in collector.runs] + assert len(run_ids) == len( + set(run_ids) + ), f"Duplicate run IDs found (replay issue): {run_ids}" + + +# --- Nexus service with direct @traceable call in handler --- + + +@traceable(name="nexus_direct_traceable") +async def _nexus_direct_traceable(input: str) -> str: + """A @traceable function called directly from a nexus handler.""" + return await _inner_llm_call(input) + + +@nexusrpc.handler.service_handler +class DirectTraceableNexusService: + """Nexus service that calls @traceable directly (not via activity).""" + + @nexusrpc.handler.sync_operation + async def direct_traceable_op( + self, + ctx: nexusrpc.handler.StartOperationContext, # type:ignore[reportUnusedParameter] + input: str, + ) -> str: + return await _nexus_direct_traceable(input) + + +@workflow.defn +class NexusDirectTraceableWorkflow: + """Workflow that calls a nexus operation whose handler uses @traceable directly.""" + + @workflow.run + async def run(self) -> str: + nexus_client = workflow.create_nexus_client( + endpoint=make_nexus_endpoint_name(workflow.info().task_queue), + service=DirectTraceableNexusService, + ) + return await nexus_client.execute_operation( + operation=DirectTraceableNexusService.direct_traceable_op, + input="nexus-input", + ) + + +# --------------------------------------------------------------------------- +# TestNexusInboundTracing +# --------------------------------------------------------------------------- + + +class TestNexusInboundTracing: + """Verifies nexus handlers receive tracing_context for @traceable collection.""" + + async def test_nexus_direct_traceable_without_temporal_runs( + self, + client: Client, + env: WorkflowEnvironment, + ) -> None: + """@traceable in nexus handler works with add_temporal_runs=False. + + The worker must be started OUTSIDE tracing_context so that nexus handler + tasks inherit a clean contextvars state. Only the client call gets + tracing_context — the interceptor's tracing_context setup (or lack + thereof) is the only thing that should provide context to the handler. + """ + if env.supports_time_skipping: + pytest.skip("Time-skipping server doesn't persist headers.") + + task_queue = f"nexus-direct-{uuid.uuid4()}" + collector = InMemoryRunCollector() + mock_ls = make_mock_ls_client(collector) + temporal_client = _make_temporal_client( + client, mock_ls, add_temporal_runs=False + ) + + # Worker starts OUTSIDE tracing_context — nexus handler tasks get clean context + async with new_worker( + temporal_client, + NexusDirectTraceableWorkflow, + nexus_service_handlers=[DirectTraceableNexusService()], + task_queue=task_queue, + max_cached_workflows=0, + ) as worker: + await env.create_nexus_endpoint( + make_nexus_endpoint_name(worker.task_queue), + worker.task_queue, + ) + # Only the client call gets tracing context, not the worker + with tracing_context(client=mock_ls, enabled=True): + handle = await temporal_client.start_workflow( + NexusDirectTraceableWorkflow.run, + id=f"nexus-direct-{uuid.uuid4()}", + task_queue=worker.task_queue, + ) + result = await handle.result() + + assert result == "response to: nexus-input" + + hierarchy = dump_runs(collector) + # @traceable runs from inside the nexus handler should be collected + # via the interceptor's tracing_context setup. + expected = [ + "nexus_direct_traceable", + " inner_llm_call", + ] + assert ( + hierarchy == expected + ), f"Hierarchy mismatch.\nExpected:\n{expected}\nActual:\n{hierarchy}" + + +# --------------------------------------------------------------------------- +# TestBuiltinQueryFiltering +# --------------------------------------------------------------------------- + + +@workflow.defn +class QueryFilteringWorkflow: + """Workflow with a user query and a signal to complete.""" + + def __init__(self) -> None: + self._complete = False + + @workflow.run + async def run(self) -> str: + await workflow.wait_condition(lambda: self._complete) + return "done" + + @workflow.signal + def complete(self) -> None: + self._complete = True + + @workflow.query + def my_query(self) -> str: + return "query-result" + + +class TestBuiltinQueryFiltering: + """Verifies __temporal_ prefixed queries are not traced.""" + + async def test_temporal_prefixed_query_not_traced( + self, + client: Client, + ) -> None: + """__temporal_workflow_metadata query should not produce a trace, + but user-defined queries should still be traced. + + Uses add_temporal_runs=False on the query client to suppress + client-side QueryWorkflow traces, isolating the test to + worker-side HandleQuery traces only. + """ + + task_queue = f"query-filter-{uuid.uuid4()}" + collector = InMemoryRunCollector() + mock_ls = make_mock_ls_client(collector) + + # Worker client: add_temporal_runs=True so HandleQuery traces are created + worker_client = _make_temporal_client(client, mock_ls, add_temporal_runs=True) + # Query client: add_temporal_runs=False to suppress client-side traces + query_client = _make_temporal_client(client, mock_ls, add_temporal_runs=False) + + async with new_worker( + worker_client, + QueryFilteringWorkflow, + task_queue=task_queue, + max_cached_workflows=0, + ) as worker: + handle = await query_client.start_workflow( + QueryFilteringWorkflow.run, + id=f"query-filter-{uuid.uuid4()}", + task_queue=worker.task_queue, + ) + + # Wait for workflow to start by polling the user query + assert await _poll_query( + handle, + QueryFilteringWorkflow.my_query, + expected="query-result", + ), "Workflow never started" + + collector.clear() + + # Built-in queries — should NOT be traced + await handle.query("__temporal_workflow_metadata") + await handle.query("__stack_trace") + await handle.query("__enhanced_stack_trace") + + # User query — should be traced + await handle.query(QueryFilteringWorkflow.my_query) + + await handle.signal(QueryFilteringWorkflow.complete) + assert await handle.result() == "done" + + # Built-in queries should be absent; only user query and signal remain. + traces = dump_traces(collector) + assert traces == [ + ["HandleQuery:my_query"], + ["HandleSignal:complete"], + ], f"Unexpected traces: {traces}" diff --git a/tests/contrib/langsmith/test_interceptor.py b/tests/contrib/langsmith/test_interceptor.py new file mode 100644 index 000000000..96fdc1170 --- /dev/null +++ b/tests/contrib/langsmith/test_interceptor.py @@ -0,0 +1,1150 @@ +"""Tests for LangSmith interceptor points and helper functions.""" + +from __future__ import annotations + +import asyncio +from concurrent.futures import ThreadPoolExecutor +from datetime import datetime, timezone +from typing import Any +from unittest.mock import AsyncMock, MagicMock, patch + +import pytest + +from temporalio.api.common.v1 import Payload +from temporalio.contrib.langsmith import LangSmithInterceptor +from temporalio.contrib.langsmith._interceptor import ( + HEADER_KEY, + _extract_context, + _inject_context, + _maybe_run, + _ReplaySafeRunTree, +) + +# --------------------------------------------------------------------------- +# Helpers +# --------------------------------------------------------------------------- + +# Common patch targets (interceptor module) +_MOD = "temporalio.contrib.langsmith._interceptor" +_PATCH_RUNTREE = f"{_MOD}.RunTree" +_PATCH_IN_WORKFLOW = f"{_MOD}.temporalio.workflow.in_workflow" +_PATCH_IS_REPLAYING = f"{_MOD}.temporalio.workflow.unsafe.is_replaying_history_events" +_PATCH_WF_NOW = f"{_MOD}.temporalio.workflow.now" +_PATCH_WF_INFO = f"{_MOD}.temporalio.workflow.info" +_PATCH_TRACING_CTX = f"{_MOD}.tracing_context" +_PATCH_EXTRACT_NEXUS = f"{_MOD}._extract_nexus_context" +_PATCH_INJECT_NEXUS = f"{_MOD}._inject_nexus_context" +_PATCH_GET_CURRENT_RUN = f"{_MOD}.get_current_run_tree" + + +def _make_mock_run() -> MagicMock: + """Create a mock RunTree with working to_headers() for _inject_context.""" + mock_run = MagicMock() + mock_run.to_headers.return_value = {"langsmith-trace": "test-trace-id"} + return mock_run + + +def _mock_workflow_info(**overrides: Any) -> MagicMock: + """Create a mock workflow Info object.""" + info = MagicMock() + info.workflow_id = overrides.get("workflow_id", "test-wf-id") + info.run_id = overrides.get("run_id", "test-run-id") + info.workflow_type = overrides.get("workflow_type", "TestWorkflow") + return info + + +def _mock_activity_info(**overrides: Any) -> MagicMock: + """Create a mock activity Info object.""" + info = MagicMock() + info.workflow_id = overrides.get("workflow_id", "test-wf-id") + info.workflow_run_id = overrides.get("workflow_run_id", "test-run-id") + info.activity_id = overrides.get("activity_id", "test-activity-id") + info.activity_type = overrides.get("activity_type", "test_activity") + return info + + +def _make_executor() -> ThreadPoolExecutor: + """Create a single-worker executor for tests.""" + return ThreadPoolExecutor(max_workers=1) + + +def _get_runtree_name(MockRunTree: MagicMock) -> str: + """Extract the 'name' kwarg from RunTree constructor call.""" + MockRunTree.assert_called_once() + return MockRunTree.call_args.kwargs["name"] + + +def _get_runtree_metadata(MockRunTree: MagicMock) -> dict[str, Any]: + """Extract metadata from RunTree constructor kwargs. + + The design stores metadata in the 'extra' kwarg as {"metadata": {...}}. + """ + MockRunTree.assert_called_once() + kwargs = MockRunTree.call_args.kwargs + extra = kwargs.get("extra", {}) + if extra and "metadata" in extra: + return extra["metadata"] + # Alternatively, metadata might be passed directly + return kwargs.get("metadata", {}) + + +# =================================================================== +# TestContextPropagation +# =================================================================== + + +class TestContextPropagation: + """Tests for _inject_context / _extract_context roundtrip.""" + + @patch(_PATCH_RUNTREE) + def test_inject_extract_roundtrip(self, MockRunTree: Any) -> None: + """Inject a mock run tree's headers, then extract. Verify roundtrip.""" + mock_run = MagicMock() + mock_run.to_headers.return_value = { + "langsmith-trace": "test-trace-id", + "parent": "abc-123", + } + + headers: dict[str, Payload] = {} + result = _inject_context(headers, mock_run) + + assert HEADER_KEY in result + + # Mock from_headers for extraction (real one needs valid LangSmith header format) + mock_extracted = MagicMock() + MockRunTree.from_headers.return_value = mock_extracted + + extracted = _extract_context(result, _make_executor(), MagicMock()) + # extracted should be a _ReplaySafeRunTree wrapping the reconstructed run + assert isinstance(extracted, _ReplaySafeRunTree) + assert extracted._run is mock_extracted + MockRunTree.from_headers.assert_called_once() + + def test_extract_missing_header(self) -> None: + """When the _temporal-langsmith-context header is absent, returns None.""" + headers: dict[str, Payload] = {} + result = _extract_context(headers, _make_executor(), MagicMock()) + assert result is None + + def test_inject_preserves_existing_headers(self) -> None: + """Injecting LangSmith context does not overwrite other existing headers.""" + mock_run = MagicMock() + mock_run.to_headers.return_value = {"langsmith-trace": "val"} + + existing_payload = Payload(data=b"existing") + headers: dict[str, Payload] = {"my-header": existing_payload} + result = _inject_context(headers, mock_run) + + assert "my-header" in result + assert result["my-header"] is existing_payload + assert HEADER_KEY in result + + +# =================================================================== +# TestReplaySafety +# =================================================================== + + +class TestReplaySafety: + """Tests for replay-safe tracing behavior.""" + + @patch(_PATCH_RUNTREE) + @patch(_PATCH_IS_REPLAYING, return_value=True) + @patch(_PATCH_IN_WORKFLOW, return_value=True) + def test_replay_noop_post_end_patch( + self, _mock_in_wf: Any, _mock_replaying: Any, MockRunTree: Any + ) -> None: + """During replay, RunTree is created but post/end/patch are no-ops.""" + mock_run = _make_mock_run() + MockRunTree.return_value = mock_run + mock_client = MagicMock() + with _maybe_run( + mock_client, + "TestRun", + add_temporal_runs=True, + executor=_make_executor(), + ): + pass + # RunTree IS created (wrapped in _ReplaySafeRunTree) + MockRunTree.assert_called_once() + # But post/end/patch are no-ops during replay + mock_run.post.assert_not_called() + mock_run.end.assert_not_called() + mock_run.patch.assert_not_called() + + @patch(_PATCH_WF_NOW, return_value=datetime.now(timezone.utc)) + @patch(_PATCH_RUNTREE) + @patch(_PATCH_IS_REPLAYING, return_value=False) + @patch(_PATCH_IN_WORKFLOW, return_value=True) + def test_create_trace_when_not_replaying( + self, _mock_in_wf: Any, _mock_replaying: Any, MockRunTree: Any, _mock_now: Any + ) -> None: + """When not replaying (but in workflow), _maybe_run creates a _ReplaySafeRunTree.""" + mock_run = _make_mock_run() + MockRunTree.return_value = mock_run + mock_client = MagicMock() + with _maybe_run( + mock_client, + "TestRun", + add_temporal_runs=True, + executor=_make_executor(), + ): + pass + MockRunTree.assert_called_once() + assert MockRunTree.call_args.kwargs["name"] == "TestRun" + + @patch(_PATCH_RUNTREE) + @patch(_PATCH_IN_WORKFLOW, return_value=False) + def test_create_trace_outside_workflow( + self, _mock_in_wf: Any, MockRunTree: Any + ) -> None: + """Outside workflow (client/activity), RunTree IS created.""" + mock_run = _make_mock_run() + MockRunTree.return_value = mock_run + mock_client = MagicMock() + with _maybe_run( + mock_client, + "TestRun", + add_temporal_runs=True, + executor=_make_executor(), + ): + pass + MockRunTree.assert_called_once() + + +# =================================================================== +# TestErrorHandling +# =================================================================== + + +class TestErrorHandling: + """Tests for _maybe_run error handling.""" + + @patch(_PATCH_RUNTREE) + @patch(_PATCH_IN_WORKFLOW, return_value=False) + def test_exception_marks_run_errored( + self, _mock_in_wf: Any, MockRunTree: Any + ) -> None: + """RuntimeError marks the run as errored and re-raises.""" + mock_run = _make_mock_run() + MockRunTree.return_value = mock_run + mock_client = MagicMock() + with pytest.raises(RuntimeError, match="boom"): + with _maybe_run( + mock_client, + "TestRun", + add_temporal_runs=True, + executor=_make_executor(), + ): + raise RuntimeError("boom") + # run.end should have been called with error containing "boom" + mock_run.end.assert_called() + end_kwargs = mock_run.end.call_args.kwargs + assert end_kwargs["error"] == "RuntimeError: boom" + mock_run.patch.assert_called() + + @patch(_PATCH_RUNTREE) + @patch(_PATCH_IN_WORKFLOW, return_value=False) + def test_benign_application_error_not_marked( + self, _mock_in_wf: Any, MockRunTree: Any + ) -> None: + """Benign ApplicationError does not mark the run as errored.""" + from temporalio.exceptions import ApplicationError, ApplicationErrorCategory + + mock_run = _make_mock_run() + MockRunTree.return_value = mock_run + mock_client = MagicMock() + with pytest.raises(ApplicationError): + with _maybe_run( + mock_client, + "TestRun", + add_temporal_runs=True, + executor=_make_executor(), + ): + raise ApplicationError( + "benign", + category=ApplicationErrorCategory.BENIGN, + ) + # run.end should NOT have been called with error= + end_calls = mock_run.end.call_args_list + for c in end_calls: + assert "error" not in (c.kwargs or {}) + + @patch(_PATCH_RUNTREE) + @patch(_PATCH_IN_WORKFLOW, return_value=False) + def test_non_benign_application_error_marked( + self, _mock_in_wf: Any, MockRunTree: Any + ) -> None: + """Non-benign ApplicationError marks the run as errored.""" + from temporalio.exceptions import ApplicationError + + mock_run = _make_mock_run() + MockRunTree.return_value = mock_run + mock_client = MagicMock() + with pytest.raises(ApplicationError): + with _maybe_run( + mock_client, + "TestRun", + add_temporal_runs=True, + executor=_make_executor(), + ): + raise ApplicationError("bad", non_retryable=True) + mock_run.end.assert_called() + end_kwargs = mock_run.end.call_args.kwargs + assert end_kwargs["error"] == "ApplicationError: bad" + mock_run.patch.assert_called() + + @patch(_PATCH_RUNTREE) + @patch(_PATCH_IN_WORKFLOW, return_value=False) + def test_success_completes_normally( + self, _mock_in_wf: Any, MockRunTree: Any + ) -> None: + """On success, run.end(outputs={"status": "ok"}) and run.patch() are called.""" + mock_run = _make_mock_run() + MockRunTree.return_value = mock_run + mock_client = MagicMock() + with _maybe_run( + mock_client, + "TestRun", + add_temporal_runs=True, + executor=_make_executor(), + ): + pass + mock_run.end.assert_called_once() + end_kwargs = mock_run.end.call_args.kwargs + assert end_kwargs.get("outputs") == {"status": "ok"} + mock_run.patch.assert_called() + + @patch(_PATCH_RUNTREE) + @patch(_PATCH_IN_WORKFLOW, return_value=False) + def test_cancelled_error_propagates_without_marking_run( + self, _mock_in_wf: Any, MockRunTree: Any + ) -> None: + """CancelledError (BaseException) propagates without marking run as errored. + + _maybe_run catches Exception only, so CancelledError bypasses error marking. + """ + mock_run = _make_mock_run() + MockRunTree.return_value = mock_run + mock_client = MagicMock() + with pytest.raises(asyncio.CancelledError): + with _maybe_run( + mock_client, + "TestRun", + add_temporal_runs=True, + executor=_make_executor(), + ): + raise asyncio.CancelledError() + # run.end should NOT have been called with error= + end_calls = mock_run.end.call_args_list + for c in end_calls: + assert "error" not in (c.kwargs or {}) + + +# =================================================================== +# TestClientOutboundInterceptor +# =================================================================== + + +class TestClientOutboundInterceptor: + """Tests for _LangSmithClientOutboundInterceptor.""" + + def _make_client_interceptor( + self, *, add_temporal_runs: bool = True + ) -> tuple[Any, MagicMock]: + """Create a client outbound interceptor with a mock next.""" + config = LangSmithInterceptor( + client=MagicMock(), add_temporal_runs=add_temporal_runs + ) + mock_next = MagicMock() + mock_next.start_workflow = AsyncMock() + mock_next.query_workflow = AsyncMock() + mock_next.signal_workflow = AsyncMock() + mock_next.start_workflow_update = AsyncMock() + mock_next.start_update_with_start_workflow = AsyncMock() + interceptor = config.intercept_client(mock_next) + return interceptor, mock_next + + @pytest.mark.parametrize( + "method,input_attrs,expected_name", + [ + ( + "start_workflow", + {"workflow": "MyWorkflow", "start_signal": None}, + "StartWorkflow:MyWorkflow", + ), + ( + "start_workflow", + {"workflow": "MyWorkflow", "start_signal": "my_signal"}, + "SignalWithStartWorkflow:MyWorkflow", + ), + ("query_workflow", {"query": "get_status"}, "QueryWorkflow:get_status"), + ("signal_workflow", {"signal": "my_signal"}, "SignalWorkflow:my_signal"), + ( + "start_workflow_update", + {"update": "my_update"}, + "StartWorkflowUpdate:my_update", + ), + ], + ids=["start_workflow", "signal_with_start", "query", "signal", "update"], + ) + @pytest.mark.asyncio + @patch(_PATCH_RUNTREE) + async def test_creates_trace_and_injects_headers( + self, + MockRunTree: Any, + method: str, + input_attrs: dict[str, Any], + expected_name: str, + ) -> None: + """Each client method creates the correct trace and injects headers.""" + mock_run = _make_mock_run() + MockRunTree.return_value = mock_run + interceptor, mock_next = self._make_client_interceptor() + mock_input = MagicMock() + for k, v in input_attrs.items(): + setattr(mock_input, k, v) + mock_input.headers = {} + + with patch(_PATCH_GET_CURRENT_RUN, return_value=mock_run): + await getattr(interceptor, method)(mock_input) + + assert _get_runtree_name(MockRunTree) == expected_name + assert HEADER_KEY in mock_input.headers + getattr(mock_next, method).assert_called_once() + + @pytest.mark.asyncio + @patch(_PATCH_RUNTREE) + async def test_start_update_with_start_workflow(self, MockRunTree: Any) -> None: + """start_update_with_start_workflow injects headers into BOTH start and update inputs.""" + mock_run = _make_mock_run() + MockRunTree.return_value = mock_run + interceptor, mock_next = self._make_client_interceptor() + mock_input = MagicMock() + mock_input.start_workflow_input = MagicMock() + mock_input.start_workflow_input.workflow = "MyWorkflow" + mock_input.start_workflow_input.headers = {} + mock_input.update_workflow_input = MagicMock() + mock_input.update_workflow_input.headers = {} + + with patch(_PATCH_GET_CURRENT_RUN, return_value=mock_run): + await interceptor.start_update_with_start_workflow(mock_input) + + assert ( + _get_runtree_name(MockRunTree) == "StartUpdateWithStartWorkflow:MyWorkflow" + ) + assert HEADER_KEY in mock_input.start_workflow_input.headers + assert HEADER_KEY in mock_input.update_workflow_input.headers + mock_next.start_update_with_start_workflow.assert_called_once() + + @pytest.mark.asyncio + @patch(_PATCH_GET_CURRENT_RUN, return_value=None) + @patch(_PATCH_RUNTREE) + async def test_add_temporal_runs_false_skips_trace( + self, MockRunTree: Any, mock_get_current: Any + ) -> None: + """With add_temporal_runs=False and no ambient context, no run is created + and no headers are injected. + + _inject_current_context() is called unconditionally, but + _get_current_run_for_propagation() returns None so headers are unchanged. + """ + interceptor, mock_next = self._make_client_interceptor(add_temporal_runs=False) + mock_input = MagicMock() + mock_input.workflow = "MyWorkflow" + mock_input.start_signal = None + mock_input.headers = {} + + await interceptor.start_workflow(mock_input) + + # RunTree should NOT be created + MockRunTree.assert_not_called() + # _inject_current_context was called but found no ambient context + mock_get_current.assert_called_once() + # Headers should NOT have been modified (no ambient context) + assert HEADER_KEY not in mock_input.headers + # super() should still be called + mock_next.start_workflow.assert_called_once() + + @pytest.mark.asyncio + @patch(_PATCH_RUNTREE) + async def test_add_temporal_runs_false_with_ambient_context( + self, MockRunTree: Any + ) -> None: + """With add_temporal_runs=False but user-provided ambient context, + no run is created but the ambient context IS injected into headers. + + This verifies that context propagation works even without plugin-created + runs — if the user wraps the call in langsmith.trace(), that context + gets propagated through Temporal headers. + """ + mock_ambient_run = _make_mock_run() + interceptor, mock_next = self._make_client_interceptor(add_temporal_runs=False) + mock_input = MagicMock() + mock_input.workflow = "MyWorkflow" + mock_input.start_signal = None + mock_input.headers = {} + + with patch(_PATCH_GET_CURRENT_RUN, return_value=mock_ambient_run): + await interceptor.start_workflow(mock_input) + + # RunTree should NOT be created (no Temporal run) + MockRunTree.assert_not_called() + # But headers SHOULD be injected from the ambient context + assert HEADER_KEY in mock_input.headers + mock_next.start_workflow.assert_called_once() + + +# =================================================================== +# TestActivityInboundInterceptor +# =================================================================== + + +class TestActivityInboundInterceptor: + """Tests for _LangSmithActivityInboundInterceptor.""" + + def _make_activity_interceptor( + self, *, add_temporal_runs: bool = True + ) -> tuple[Any, MagicMock]: + config = LangSmithInterceptor( + client=MagicMock(), add_temporal_runs=add_temporal_runs + ) + mock_next = MagicMock() + mock_next.execute_activity = AsyncMock(return_value="activity_result") + interceptor = config.intercept_activity(mock_next) + return interceptor, mock_next + + @pytest.mark.asyncio + @patch(_PATCH_TRACING_CTX) + @patch(_PATCH_RUNTREE) + @patch("temporalio.activity.info") + async def test_execute_activity_creates_run_with_context_and_metadata( + self, mock_info_fn: Any, MockRunTree: Any, mock_tracing_ctx: Any + ) -> None: + """Activity execution creates a correctly named run with metadata and parent context.""" + mock_info_fn.return_value = _mock_activity_info( + activity_type="do_thing", + workflow_id="wf-123", + workflow_run_id="run-456", + activity_id="act-789", + ) + mock_run = _make_mock_run() + MockRunTree.return_value = mock_run + interceptor, mock_next = self._make_activity_interceptor() + + mock_input = MagicMock() + mock_input.headers = {} + + result = await interceptor.execute_activity(mock_input) + + # Verify trace name and run_type + assert _get_runtree_name(MockRunTree) == "RunActivity:do_thing" + assert MockRunTree.call_args.kwargs.get("run_type") == "tool" + # Verify metadata + metadata = _get_runtree_metadata(MockRunTree) + assert metadata["temporalWorkflowID"] == "wf-123" + assert metadata["temporalRunID"] == "run-456" + assert metadata["temporalActivityID"] == "act-789" + # Verify tracing_context sets parent (wrapped in _ReplaySafeRunTree) + mock_tracing_ctx.assert_called() + ctx_kwargs = mock_tracing_ctx.call_args.kwargs + parent = ctx_kwargs.get("parent") + assert isinstance(parent, _ReplaySafeRunTree) + assert parent._run is mock_run + # Verify super() called and result passed through + mock_next.execute_activity.assert_called_once() + assert result == "activity_result" + + @pytest.mark.asyncio + @patch(_PATCH_RUNTREE) + @patch("temporalio.activity.info") + async def test_execute_activity_no_header( + self, mock_info_fn: Any, MockRunTree: Any + ) -> None: + """When no LangSmith header is present, activity still executes (no parent, no crash).""" + mock_info_fn.return_value = _mock_activity_info() + mock_run = _make_mock_run() + MockRunTree.return_value = mock_run + interceptor, _mock_next = self._make_activity_interceptor() + + mock_input = MagicMock() + mock_input.headers = {} # No LangSmith header + + result = await interceptor.execute_activity(mock_input) + + # Should still create a run (just without a parent) + MockRunTree.assert_called_once() + assert MockRunTree.call_args.kwargs.get("parent_run") is None + assert result == "activity_result" + + +# =================================================================== +# TestWorkflowInboundInterceptor +# =================================================================== + + +class TestWorkflowInboundInterceptor: + """Tests for _LangSmithWorkflowInboundInterceptor.""" + + def _make_workflow_interceptors( + self, *, add_temporal_runs: bool = True + ) -> tuple[Any, MagicMock]: + """Create workflow inbound interceptor and a mock next.""" + config = LangSmithInterceptor( + client=MagicMock(), add_temporal_runs=add_temporal_runs + ) + mock_next = MagicMock() + mock_next.execute_workflow = AsyncMock(return_value="wf_result") + mock_next.handle_signal = AsyncMock() + mock_next.handle_query = AsyncMock(return_value="query_result") + mock_next.handle_update_validator = MagicMock() + mock_next.handle_update_handler = AsyncMock(return_value="update_result") + + # Get the workflow interceptor class + wf_class_input = MagicMock() + wf_interceptor_cls = config.workflow_interceptor_class(wf_class_input) + assert wf_interceptor_cls is not None + + # Instantiate with mock next + wf_interceptor = wf_interceptor_cls(mock_next) + + # Initialize with mock outbound + mock_outbound = MagicMock() + wf_interceptor.init(mock_outbound) + + return wf_interceptor, mock_next + + @pytest.mark.asyncio + @patch(_PATCH_WF_NOW, return_value=datetime.now(timezone.utc)) + @patch(_PATCH_RUNTREE) + @patch(_PATCH_IS_REPLAYING, return_value=False) + @patch(_PATCH_IN_WORKFLOW, return_value=True) + @patch(_PATCH_WF_INFO) + async def test_execute_workflow( + self, + mock_wf_info: Any, + _mock_in_wf: Any, + _mock_replaying: Any, + MockRunTree: Any, + _mock_now: Any, + ) -> None: + """execute_workflow creates a run named RunWorkflow:{workflow_type}.""" + mock_wf_info.return_value = _mock_workflow_info(workflow_type="MyWorkflow") + mock_run = _make_mock_run() + MockRunTree.return_value = mock_run + interceptor, mock_next = self._make_workflow_interceptors() + + mock_input = MagicMock() + mock_input.headers = {} + + result = await interceptor.execute_workflow(mock_input) + + # Verify trace name + assert _get_runtree_name(MockRunTree) == "RunWorkflow:MyWorkflow" + # Verify metadata includes workflow ID and run ID + metadata = _get_runtree_metadata(MockRunTree) + assert metadata == { + "temporalWorkflowID": "test-wf-id", + "temporalRunID": "test-run-id", + } + # Verify super() called and result passed through + mock_next.execute_workflow.assert_called_once() + assert result == "wf_result" + + @pytest.mark.parametrize( + "method,input_attr,input_val,expected_name", + [ + ("handle_signal", "signal", "my_signal", "HandleSignal:my_signal"), + ("handle_query", "query", "get_status", "HandleQuery:get_status"), + ( + "handle_update_validator", + "update", + "my_update", + "ValidateUpdate:my_update", + ), + ("handle_update_handler", "update", "my_update", "HandleUpdate:my_update"), + ], + ids=["signal", "query", "validator", "update_handler"], + ) + @pytest.mark.asyncio + @patch(_PATCH_WF_NOW, return_value=datetime.now(timezone.utc)) + @patch(_PATCH_RUNTREE) + @patch(_PATCH_IS_REPLAYING, return_value=False) + @patch(_PATCH_IN_WORKFLOW, return_value=True) + @patch(_PATCH_WF_INFO) + async def test_handler_creates_trace( + self, + mock_wf_info: Any, + _mock_in_wf: Any, + _mock_replaying: Any, + MockRunTree: Any, + _mock_now: Any, + method: str, + input_attr: str, + input_val: str, + expected_name: str, + ) -> None: + """Each workflow handler creates the correct trace name.""" + mock_wf_info.return_value = _mock_workflow_info() + mock_run = _make_mock_run() + MockRunTree.return_value = mock_run + interceptor, mock_next = self._make_workflow_interceptors() + + mock_input = MagicMock() + setattr(mock_input, input_attr, input_val) + mock_input.headers = {} + + result = getattr(interceptor, method)(mock_input) + if asyncio.iscoroutine(result): + await result + + assert _get_runtree_name(MockRunTree) == expected_name + getattr(mock_next, method).assert_called_once() + + +# =================================================================== +# TestWorkflowOutboundInterceptor +# =================================================================== + + +class TestWorkflowOutboundInterceptor: + """Tests for _LangSmithWorkflowOutboundInterceptor.""" + + def _make_outbound_interceptor( + self, *, add_temporal_runs: bool = True + ) -> tuple[Any, MagicMock, Any]: + """Create outbound interceptor with mock next and ambient run. + + Returns (outbound_interceptor, mock_next, mock_current_run). + """ + config = LangSmithInterceptor( + client=MagicMock(), add_temporal_runs=add_temporal_runs + ) + + # Create mock next for inbound + mock_inbound_next = MagicMock() + mock_inbound_next.execute_workflow = AsyncMock() + mock_inbound_next.handle_signal = AsyncMock() + mock_inbound_next.handle_query = AsyncMock() + mock_inbound_next.handle_update_validator = MagicMock() + mock_inbound_next.handle_update_handler = AsyncMock() + + # Create inbound interceptor + wf_class_input = MagicMock() + wf_interceptor_cls = config.workflow_interceptor_class(wf_class_input) + inbound = wf_interceptor_cls(mock_inbound_next) + + # Create mock outbound next + mock_outbound_next = MagicMock() + mock_outbound_next.start_activity = MagicMock() + mock_outbound_next.start_local_activity = MagicMock() + mock_outbound_next.start_child_workflow = AsyncMock() + mock_outbound_next.signal_child_workflow = AsyncMock() + mock_outbound_next.signal_external_workflow = AsyncMock() + mock_outbound_next.continue_as_new = MagicMock() + mock_outbound_next.start_nexus_operation = AsyncMock() + + # Initialize inbound (which should create the outbound) + inbound.init(mock_outbound_next) + + # Create the outbound directly for unit testing + from temporalio.contrib.langsmith._interceptor import ( + _LangSmithWorkflowOutboundInterceptor, + ) + + outbound = _LangSmithWorkflowOutboundInterceptor(mock_outbound_next, config) + + # Simulate active workflow execution via ambient context + mock_current_run = _make_mock_run() + + return outbound, mock_outbound_next, mock_current_run + + @pytest.mark.parametrize( + "method,input_attr,input_val,expected_name", + [ + ("start_activity", "activity", "do_thing", "StartActivity:do_thing"), + ( + "start_local_activity", + "activity", + "local_thing", + "StartActivity:local_thing", + ), + ( + "start_child_workflow", + "workflow", + "ChildWorkflow", + "StartChildWorkflow:ChildWorkflow", + ), + ( + "signal_child_workflow", + "signal", + "child_signal", + "SignalChildWorkflow:child_signal", + ), + ( + "signal_external_workflow", + "signal", + "ext_signal", + "SignalExternalWorkflow:ext_signal", + ), + ], + ids=[ + "activity", + "local_activity", + "child_workflow", + "signal_child", + "signal_external", + ], + ) + @pytest.mark.asyncio + @patch(_PATCH_WF_NOW, return_value=datetime.now(timezone.utc)) + @patch(_PATCH_RUNTREE) + @patch(_PATCH_IS_REPLAYING, return_value=False) + @patch(_PATCH_IN_WORKFLOW, return_value=True) + async def test_creates_trace_and_injects_headers( + self, + _mock_in_wf: Any, + _mock_replaying: Any, + MockRunTree: Any, + _mock_now: Any, + method: str, + input_attr: str, + input_val: str, + expected_name: str, + ) -> None: + """Each outbound method creates the correct trace and injects headers.""" + mock_run = _make_mock_run() + MockRunTree.return_value = mock_run + outbound, mock_next, mock_current_run = self._make_outbound_interceptor() + + mock_input = MagicMock() + setattr(mock_input, input_attr, input_val) + mock_input.headers = {} + + with patch(_PATCH_GET_CURRENT_RUN, return_value=mock_current_run): + result = getattr(outbound, method)(mock_input) + if asyncio.iscoroutine(result): + await result + + assert _get_runtree_name(MockRunTree) == expected_name + assert HEADER_KEY in mock_input.headers + getattr(mock_next, method).assert_called_once() + + @patch(_PATCH_RUNTREE) + @patch(_PATCH_IS_REPLAYING, return_value=False) + @patch(_PATCH_IN_WORKFLOW, return_value=True) + def test_continue_as_new( + self, _mock_in_wf: Any, _mock_replaying: Any, MockRunTree: Any + ) -> None: + """continue_as_new does NOT create a new trace, but injects context from ambient run.""" + outbound, mock_next, mock_current_run = self._make_outbound_interceptor() + + mock_input = MagicMock() + mock_input.headers = {} + + with patch(_PATCH_GET_CURRENT_RUN, return_value=mock_current_run): + outbound.continue_as_new(mock_input) + + # No new RunTree should be created for continue_as_new + MockRunTree.assert_not_called() + # But headers SHOULD be modified (context from ambient run) + assert HEADER_KEY in mock_input.headers + mock_next.continue_as_new.assert_called_once() + + @pytest.mark.asyncio + @patch(_PATCH_WF_NOW, return_value=datetime.now(timezone.utc)) + @patch(_PATCH_RUNTREE) + @patch(_PATCH_IS_REPLAYING, return_value=False) + @patch(_PATCH_IN_WORKFLOW, return_value=True) + async def test_start_nexus_operation( + self, + _mock_in_wf: Any, + _mock_replaying: Any, + MockRunTree: Any, + _mock_now: Any, + ) -> None: + """start_nexus_operation creates a trace named StartNexusOperation:{service}/{operation}.""" + mock_run = _make_mock_run() + MockRunTree.return_value = mock_run + outbound, mock_next, mock_current_run = self._make_outbound_interceptor() + + mock_input = MagicMock() + mock_input.service = "MyService" + mock_input.operation_name = "do_op" + mock_input.headers = {} + + with patch(_PATCH_GET_CURRENT_RUN, return_value=mock_current_run): + await outbound.start_nexus_operation(mock_input) + + assert _get_runtree_name(MockRunTree) == "StartNexusOperation:MyService/do_op" + # Nexus uses string headers, so context injection uses _inject_nexus_context + # The headers dict should be modified + mock_next.start_nexus_operation.assert_called_once() + + +# =================================================================== +# TestNexusInboundInterceptor +# =================================================================== + + +class TestNexusInboundInterceptor: + """Tests for _LangSmithNexusOperationInboundInterceptor.""" + + def _make_nexus_interceptor( + self, *, add_temporal_runs: bool = True + ) -> tuple[Any, MagicMock]: + config = LangSmithInterceptor( + client=MagicMock(), add_temporal_runs=add_temporal_runs + ) + mock_next = MagicMock() + mock_next.execute_nexus_operation_start = AsyncMock() + mock_next.execute_nexus_operation_cancel = AsyncMock() + interceptor = config.intercept_nexus_operation(mock_next) + return interceptor, mock_next + + @pytest.mark.asyncio + @patch(_PATCH_RUNTREE) + @patch(_PATCH_EXTRACT_NEXUS) + async def test_execute_nexus_operation_start( + self, mock_extract_nexus: Any, MockRunTree: Any + ) -> None: + """Creates a run named RunStartNexusOperationHandler:{service}/{operation}. + + Uses _extract_nexus_context (not _extract_context) for Nexus string headers. + """ + mock_extract_nexus.return_value = None # no parent + mock_run = _make_mock_run() + MockRunTree.return_value = mock_run + interceptor, mock_next = self._make_nexus_interceptor() + + mock_input = MagicMock() + mock_input.ctx = MagicMock() + mock_input.ctx.service = "MyService" + mock_input.ctx.operation = "start_op" + mock_input.ctx.headers = {} + + await interceptor.execute_nexus_operation_start(mock_input) + + # Verify _extract_nexus_context was called (not _extract_context) + mock_extract_nexus.assert_called_once() + assert mock_extract_nexus.call_args[0][0] is mock_input.ctx.headers + # Verify trace name + assert ( + _get_runtree_name(MockRunTree) + == "RunStartNexusOperationHandler:MyService/start_op" + ) + # Verify run_type is "tool" for Nexus operations + assert MockRunTree.call_args.kwargs.get("run_type") == "tool" + mock_next.execute_nexus_operation_start.assert_called_once() + + @pytest.mark.asyncio + @patch(_PATCH_RUNTREE) + @patch(_PATCH_EXTRACT_NEXUS) + async def test_execute_nexus_operation_cancel( + self, mock_extract_nexus: Any, MockRunTree: Any + ) -> None: + """Creates a run named RunCancelNexusOperationHandler:{service}/{operation}. + + Uses _extract_nexus_context for context extraction. + """ + mock_extract_nexus.return_value = None + mock_run = _make_mock_run() + MockRunTree.return_value = mock_run + interceptor, mock_next = self._make_nexus_interceptor() + + mock_input = MagicMock() + mock_input.ctx = MagicMock() + mock_input.ctx.service = "MyService" + mock_input.ctx.operation = "cancel_op" + mock_input.ctx.headers = {} + + await interceptor.execute_nexus_operation_cancel(mock_input) + + mock_extract_nexus.assert_called_once() + assert mock_extract_nexus.call_args[0][0] is mock_input.ctx.headers + assert ( + _get_runtree_name(MockRunTree) + == "RunCancelNexusOperationHandler:MyService/cancel_op" + ) + assert MockRunTree.call_args.kwargs.get("run_type") == "tool" + mock_next.execute_nexus_operation_cancel.assert_called_once() + + +# =================================================================== +# TestLazyClientPrevention +# =================================================================== + + +class TestLazyClientPrevention: + """Tests that RunTree always receives ls_client= to prevent lazy Client creation.""" + + @patch(_PATCH_IN_WORKFLOW, return_value=False) + @patch(_PATCH_RUNTREE) + def test_runtree_always_receives_ls_client( + self, MockRunTree: Any, _mock_in_wf: Any + ) -> None: + """Every RunTree() created by _maybe_run receives ls_client= (pre-created client).""" + mock_client = MagicMock() + mock_run = _make_mock_run() + MockRunTree.return_value = mock_run + + with _maybe_run( + mock_client, + "TestRun", + add_temporal_runs=True, + executor=_make_executor(), + ): + pass + + MockRunTree.assert_called_once() + call_kwargs = MockRunTree.call_args.kwargs + assert "ls_client" in call_kwargs + assert call_kwargs["ls_client"] is mock_client + + +# =================================================================== +# TestAddTemporalRunsToggle +# =================================================================== + + +class TestAddTemporalRunsToggle: + """Tests for the add_temporal_runs toggle.""" + + @patch(_PATCH_RUNTREE) + @patch(_PATCH_IN_WORKFLOW, return_value=False) + def test_false_skips_traces(self, _mock_in_wf: Any, MockRunTree: Any) -> None: + """With add_temporal_runs=False, _maybe_run yields None (no run created). + + Callers are responsible for propagating context even when the run is None. + See test_false_still_propagates_context for the full behavior. + """ + mock_client = MagicMock() + with _maybe_run( + mock_client, + "TestRun", + add_temporal_runs=False, + executor=_make_executor(), + ) as run: + assert run is None + MockRunTree.assert_not_called() + + @pytest.mark.asyncio + @patch(_PATCH_TRACING_CTX) + @patch(_PATCH_RUNTREE) + @patch(_PATCH_IS_REPLAYING, return_value=False) + @patch(_PATCH_IN_WORKFLOW, return_value=True) + @patch(_PATCH_WF_INFO) + @patch(f"{_MOD}.temporalio.activity.info") + async def test_false_still_propagates_context( + self, + mock_act_info: Any, + mock_wf_info: Any, + _mock_in_wf: Any, + _mock_replaying: Any, + MockRunTree: Any, + mock_tracing_ctx: Any, + ) -> None: + """With add_temporal_runs=False, no runs are created but context still propagates. + + 1. Workflow outbound: injects the ambient run's context into headers even + though no StartActivity run is created. + 2. Activity inbound: sets tracing_context(parent=extracted_parent) + unconditionally (before _maybe_run), so @traceable code nests correctly + even without a RunActivity run. + """ + from temporalio.contrib.langsmith._interceptor import ( + _LangSmithWorkflowOutboundInterceptor, + ) + + mock_wf_info.return_value = _mock_workflow_info() + mock_act_info.return_value = _mock_activity_info() + + # --- Workflow outbound: context propagation without run creation --- + config = LangSmithInterceptor(client=MagicMock(), add_temporal_runs=False) + + # Create inbound interceptor + wf_class_input = MagicMock() + wf_interceptor_cls = config.workflow_interceptor_class(wf_class_input) + mock_inbound_next = MagicMock() + mock_inbound_next.execute_workflow = AsyncMock() + inbound = wf_interceptor_cls(mock_inbound_next) + + # Create outbound interceptor + mock_outbound_next = MagicMock() + mock_outbound_next.start_activity = MagicMock() + inbound.init(mock_outbound_next) + outbound = _LangSmithWorkflowOutboundInterceptor(mock_outbound_next, config) + + # Simulate an ambient parent context (as if from active workflow execution) + mock_parent = _make_mock_run() + + mock_input = MagicMock() + mock_input.activity = "do_thing" + mock_input.headers = {} + + with patch(_PATCH_GET_CURRENT_RUN, return_value=mock_parent): + outbound.start_activity(mock_input) + + # No RunTree should be created (add_temporal_runs=False) + MockRunTree.assert_not_called() + # But headers SHOULD be injected from the inbound's parent context + assert HEADER_KEY in mock_input.headers + mock_outbound_next.start_activity.assert_called_once() + + # --- Activity inbound: tracing_context with extracted parent --- + MockRunTree.reset_mock() + mock_tracing_ctx.reset_mock() + + mock_act_next = MagicMock() + mock_act_next.execute_activity = AsyncMock(return_value="result") + act_interceptor = config.intercept_activity(mock_act_next) + + mock_act_input = MagicMock() + mock_extracted_parent = _make_mock_run() + + with patch(f"{_MOD}._extract_context", return_value=mock_extracted_parent): + await act_interceptor.execute_activity(mock_act_input) + + # No RunTree should be created (add_temporal_runs=False) + MockRunTree.assert_not_called() + # tracing_context SHOULD be called with the client and extracted parent + # (unconditionally, before _maybe_run) + mock_tracing_ctx.assert_called_once_with( + client=config._client, + enabled=True, + project_name=None, + parent=mock_extracted_parent, + ) + mock_act_next.execute_activity.assert_called_once() + + @pytest.mark.asyncio + @patch(_PATCH_TRACING_CTX) + @patch(_PATCH_RUNTREE) + @patch(f"{_MOD}.temporalio.activity.info") + async def test_false_activity_no_parent_no_context( + self, + mock_act_info: Any, + MockRunTree: Any, + mock_tracing_ctx: Any, + ) -> None: + """With add_temporal_runs=False and no parent in headers, tracing_context + is still called with the client (so @traceable can use it), but no parent. + """ + mock_act_info.return_value = _mock_activity_info() + config = LangSmithInterceptor(client=MagicMock(), add_temporal_runs=False) + + mock_act_next = MagicMock() + mock_act_next.execute_activity = AsyncMock(return_value="result") + act_interceptor = config.intercept_activity(mock_act_next) + + mock_act_input = MagicMock() + + with patch(f"{_MOD}._extract_context", return_value=None): + await act_interceptor.execute_activity(mock_act_input) + + MockRunTree.assert_not_called() + # tracing_context called with client and enabled (no parent) + mock_tracing_ctx.assert_called_once_with( + client=config._client, enabled=True, project_name=None, parent=None + ) + mock_act_next.execute_activity.assert_called_once() diff --git a/tests/contrib/langsmith/test_plugin.py b/tests/contrib/langsmith/test_plugin.py new file mode 100644 index 000000000..17c21cb7c --- /dev/null +++ b/tests/contrib/langsmith/test_plugin.py @@ -0,0 +1,222 @@ +"""Tests for LangSmithPlugin construction, configuration, and end-to-end usage.""" + +from __future__ import annotations + +import uuid +from typing import Any +from unittest.mock import MagicMock + +import pytest +from langsmith import traceable, tracing_context + +from temporalio.client import Client, WorkflowHandle +from temporalio.contrib.langsmith import LangSmithInterceptor, LangSmithPlugin +from temporalio.testing import WorkflowEnvironment +from tests.contrib.langsmith.conftest import dump_traces, find_traces +from tests.contrib.langsmith.test_integration import ( + ComprehensiveWorkflow, + NexusService, + TraceableActivityWorkflow, + _make_client_and_collector, + _poll_query, + nested_traceable_activity, + traceable_activity, +) +from tests.helpers import new_worker +from tests.helpers.nexus import make_nexus_endpoint_name + + +class TestPluginConstruction: + """Tests for LangSmithPlugin construction.""" + + def test_construction_stores_all_config(self) -> None: + """All constructor kwargs are stored on the interceptor.""" + mock_client = MagicMock() + plugin = LangSmithPlugin( + client=mock_client, + project_name="my-project", + add_temporal_runs=False, + default_metadata={"env": "prod"}, + default_tags=["v1"], + ) + assert plugin.interceptors is not None + assert len(plugin.interceptors) > 0 + interceptor = plugin.interceptors[0] + assert isinstance(interceptor, LangSmithInterceptor) + assert interceptor._client is mock_client + assert interceptor._project_name == "my-project" + assert interceptor._add_temporal_runs is False + assert interceptor._default_metadata == {"env": "prod"} + assert interceptor._default_tags == ["v1"] + + +class TestPluginIntegration: + """End-to-end test using LangSmithPlugin as a Temporal client plugin.""" + + async def test_comprehensive_plugin_trace_hierarchy( + self, client: Client, env: WorkflowEnvironment + ) -> None: + """Plugin wired to a real Temporal worker produces the full trace hierarchy. + + user_pipeline only wraps start_workflow, so poll/query/signal/update + traces are naturally separate root traces. + """ + if env.supports_time_skipping: + pytest.skip("Time-skipping server doesn't persist headers.") + + temporal_client, collector, mock_ls_client = _make_client_and_collector( + client, add_temporal_runs=True + ) + + task_queue = f"plugin-comprehensive-{uuid.uuid4()}" + workflow_id = f"plugin-comprehensive-{uuid.uuid4()}" + + @traceable(name="user_pipeline") + async def user_pipeline() -> WorkflowHandle[Any, Any]: + return await temporal_client.start_workflow( + ComprehensiveWorkflow.run, + id=workflow_id, + task_queue=task_queue, + ) + + with tracing_context(client=mock_ls_client, enabled=True): + handle = await user_pipeline() + + async with new_worker( + temporal_client, + ComprehensiveWorkflow, + TraceableActivityWorkflow, + activities=[nested_traceable_activity, traceable_activity], + nexus_service_handlers=[NexusService()], + task_queue=task_queue, + max_cached_workflows=0, + ) as worker: + await env.create_nexus_endpoint( + make_nexus_endpoint_name(worker.task_queue), + worker.task_queue, + ) + assert await _poll_query( + handle, + ComprehensiveWorkflow.is_waiting_for_signal, + expected=True, + ), "Workflow never reached signal wait point" + await handle.query(ComprehensiveWorkflow.my_query) + await handle.signal(ComprehensiveWorkflow.my_signal, "hello") + await handle.execute_update( + ComprehensiveWorkflow.my_unvalidated_update, "test" + ) + await handle.execute_update(ComprehensiveWorkflow.my_update, "finish") + result = await handle.result() + + assert result == "comprehensive-done" + + traces = dump_traces(collector) + + # user_pipeline trace: StartWorkflow + full workflow execution tree + workflow_traces = find_traces(traces, "user_pipeline") + assert len(workflow_traces) == 1 + assert workflow_traces[0] == [ + "user_pipeline", + " StartWorkflow:ComprehensiveWorkflow", + " RunWorkflow:ComprehensiveWorkflow", + " StartActivity:nested_traceable_activity", + " RunActivity:nested_traceable_activity", + " nested_traceable_activity", + " outer_chain", + " inner_llm_call", + # step-wrapped activity + " step_with_activity", + " StartActivity:nested_traceable_activity", + " RunActivity:nested_traceable_activity", + " nested_traceable_activity", + " outer_chain", + " inner_llm_call", + " StartActivity:nested_traceable_activity", + " RunActivity:nested_traceable_activity", + " nested_traceable_activity", + " outer_chain", + " inner_llm_call", + " outer_chain", + " inner_llm_call", + " StartChildWorkflow:TraceableActivityWorkflow", + " RunWorkflow:TraceableActivityWorkflow", + " StartActivity:traceable_activity", + " RunActivity:traceable_activity", + " traceable_activity", + " inner_llm_call", + # step-wrapped child workflow + " step_with_child_workflow", + " StartChildWorkflow:TraceableActivityWorkflow", + " RunWorkflow:TraceableActivityWorkflow", + " StartActivity:traceable_activity", + " RunActivity:traceable_activity", + " traceable_activity", + " inner_llm_call", + " StartNexusOperation:NexusService/run_operation", + " RunStartNexusOperationHandler:NexusService/run_operation", + " StartWorkflow:TraceableActivityWorkflow", + " RunWorkflow:TraceableActivityWorkflow", + " StartActivity:traceable_activity", + " RunActivity:traceable_activity", + " traceable_activity", + " inner_llm_call", + # step-wrapped nexus operation + " step_with_nexus", + " StartNexusOperation:NexusService/run_operation", + " RunStartNexusOperationHandler:NexusService/run_operation", + " StartWorkflow:TraceableActivityWorkflow", + " RunWorkflow:TraceableActivityWorkflow", + " StartActivity:traceable_activity", + " RunActivity:traceable_activity", + " traceable_activity", + " inner_llm_call", + # post-signal + " StartActivity:nested_traceable_activity", + " RunActivity:nested_traceable_activity", + " nested_traceable_activity", + " outer_chain", + " inner_llm_call", + ] + + # poll_query trace (separate root, variable number of iterations) + poll_traces = find_traces(traces, "poll_query") + assert len(poll_traces) == 1 + poll = poll_traces[0] + assert poll[0] == "poll_query" + poll_children = poll[1:] + for i in range(0, len(poll_children), 2): + assert poll_children[i] == " QueryWorkflow:is_waiting_for_signal" + assert poll_children[i + 1] == " HandleQuery:is_waiting_for_signal" + + # Each remaining operation is its own root trace + query_traces = find_traces(traces, "QueryWorkflow:my_query") + assert len(query_traces) == 1 + assert query_traces[0] == [ + "QueryWorkflow:my_query", + " HandleQuery:my_query", + ] + + signal_traces = find_traces(traces, "SignalWorkflow:my_signal") + assert len(signal_traces) == 1 + assert signal_traces[0] == [ + "SignalWorkflow:my_signal", + " HandleSignal:my_signal", + ] + + update_traces = find_traces(traces, "StartWorkflowUpdate:my_update") + assert len(update_traces) == 1 + assert update_traces[0] == [ + "StartWorkflowUpdate:my_update", + " ValidateUpdate:my_update", + " HandleUpdate:my_update", + ] + + # Update without a validator — no ValidateUpdate trace + unvalidated_traces = find_traces( + traces, "StartWorkflowUpdate:my_unvalidated_update" + ) + assert len(unvalidated_traces) == 1 + assert unvalidated_traces[0] == [ + "StartWorkflowUpdate:my_unvalidated_update", + " HandleUpdate:my_unvalidated_update", + ] diff --git a/uv.lock b/uv.lock index 619c740b2..c45409833 100644 --- a/uv.lock +++ b/uv.lock @@ -1812,7 +1812,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/38/3f/9859f655d11901e7b2996c6e3d33e0caa9a1d4572c3bc61ed0faa64b2f4c/greenlet-3.3.2-cp310-cp310-macosx_11_0_universal2.whl", hash = "sha256:9bc885b89709d901859cf95179ec9f6bb67a3d2bb1f0e88456461bd4b7f8fd0d", size = 277747, upload-time = "2026-02-20T20:16:21.325Z" }, { url = "https://files.pythonhosted.org/packages/fb/07/cb284a8b5c6498dbd7cba35d31380bb123d7dceaa7907f606c8ff5993cbf/greenlet-3.3.2-cp310-cp310-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b568183cf65b94919be4438dc28416b234b678c608cafac8874dfeeb2a9bbe13", size = 579202, upload-time = "2026-02-20T20:47:28.955Z" }, { url = "https://files.pythonhosted.org/packages/ed/45/67922992b3a152f726163b19f890a85129a992f39607a2a53155de3448b8/greenlet-3.3.2-cp310-cp310-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:527fec58dc9f90efd594b9b700662ed3fb2493c2122067ac9c740d98080a620e", size = 590620, upload-time = "2026-02-20T20:55:55.581Z" }, - { url = "https://files.pythonhosted.org/packages/03/5f/6e2a7d80c353587751ef3d44bb947f0565ec008a2e0927821c007e96d3a7/greenlet-3.3.2-cp310-cp310-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:508c7f01f1791fbc8e011bd508f6794cb95397fdb198a46cb6635eb5b78d85a7", size = 602132, upload-time = "2026-02-20T21:02:43.261Z" }, { url = "https://files.pythonhosted.org/packages/ad/55/9f1ebb5a825215fadcc0f7d5073f6e79e3007e3282b14b22d6aba7ca6cb8/greenlet-3.3.2-cp310-cp310-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ad0c8917dd42a819fe77e6bdfcb84e3379c0de956469301d9fd36427a1ca501f", size = 591729, upload-time = "2026-02-20T20:20:58.395Z" }, { url = "https://files.pythonhosted.org/packages/24/b4/21f5455773d37f94b866eb3cf5caed88d6cea6dd2c6e1f9c34f463cba3ec/greenlet-3.3.2-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:97245cc10e5515dbc8c3104b2928f7f02b6813002770cfaffaf9a6e0fc2b94ef", size = 1551946, upload-time = "2026-02-20T20:49:31.102Z" }, { url = "https://files.pythonhosted.org/packages/00/68/91f061a926abead128fe1a87f0b453ccf07368666bd59ffa46016627a930/greenlet-3.3.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:8c1fdd7d1b309ff0da81d60a9688a8bd044ac4e18b250320a96fc68d31c209ca", size = 1618494, upload-time = "2026-02-20T20:21:06.541Z" }, @@ -1820,7 +1819,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/f3/47/16400cb42d18d7a6bb46f0626852c1718612e35dcb0dffa16bbaffdf5dd2/greenlet-3.3.2-cp311-cp311-macosx_11_0_universal2.whl", hash = "sha256:c56692189a7d1c7606cb794be0a8381470d95c57ce5be03fb3d0ef57c7853b86", size = 278890, upload-time = "2026-02-20T20:19:39.263Z" }, { url = "https://files.pythonhosted.org/packages/a3/90/42762b77a5b6aa96cd8c0e80612663d39211e8ae8a6cd47c7f1249a66262/greenlet-3.3.2-cp311-cp311-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1ebd458fa8285960f382841da585e02201b53a5ec2bac6b156fc623b5ce4499f", size = 581120, upload-time = "2026-02-20T20:47:30.161Z" }, { url = "https://files.pythonhosted.org/packages/bf/6f/f3d64f4fa0a9c7b5c5b3c810ff1df614540d5aa7d519261b53fba55d4df9/greenlet-3.3.2-cp311-cp311-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:a443358b33c4ec7b05b79a7c8b466f5d275025e750298be7340f8fc63dff2a55", size = 594363, upload-time = "2026-02-20T20:55:56.965Z" }, - { url = "https://files.pythonhosted.org/packages/9c/8b/1430a04657735a3f23116c2e0d5eb10220928846e4537a938a41b350bed6/greenlet-3.3.2-cp311-cp311-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:4375a58e49522698d3e70cc0b801c19433021b5c37686f7ce9c65b0d5c8677d2", size = 605046, upload-time = "2026-02-20T21:02:45.234Z" }, { url = "https://files.pythonhosted.org/packages/72/83/3e06a52aca8128bdd4dcd67e932b809e76a96ab8c232a8b025b2850264c5/greenlet-3.3.2-cp311-cp311-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8e2cd90d413acbf5e77ae41e5d3c9b3ac1d011a756d7284d7f3f2b806bbd6358", size = 594156, upload-time = "2026-02-20T20:20:59.955Z" }, { url = "https://files.pythonhosted.org/packages/70/79/0de5e62b873e08fe3cef7dbe84e5c4bc0e8ed0c7ff131bccb8405cd107c8/greenlet-3.3.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:442b6057453c8cb29b4fb36a2ac689382fc71112273726e2423f7f17dc73bf99", size = 1554649, upload-time = "2026-02-20T20:49:32.293Z" }, { url = "https://files.pythonhosted.org/packages/5a/00/32d30dee8389dc36d42170a9c66217757289e2afb0de59a3565260f38373/greenlet-3.3.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:45abe8eb6339518180d5a7fa47fa01945414d7cca5ecb745346fc6a87d2750be", size = 1619472, upload-time = "2026-02-20T20:21:07.966Z" }, @@ -1829,7 +1827,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/ea/ab/1608e5a7578e62113506740b88066bf09888322a311cff602105e619bd87/greenlet-3.3.2-cp312-cp312-macosx_11_0_universal2.whl", hash = "sha256:ac8d61d4343b799d1e526db579833d72f23759c71e07181c2d2944e429eb09cd", size = 280358, upload-time = "2026-02-20T20:17:43.971Z" }, { url = "https://files.pythonhosted.org/packages/a5/23/0eae412a4ade4e6623ff7626e38998cb9b11e9ff1ebacaa021e4e108ec15/greenlet-3.3.2-cp312-cp312-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3ceec72030dae6ac0c8ed7591b96b70410a8be370b6a477b1dbc072856ad02bd", size = 601217, upload-time = "2026-02-20T20:47:31.462Z" }, { url = "https://files.pythonhosted.org/packages/f8/16/5b1678a9c07098ecb9ab2dd159fafaf12e963293e61ee8d10ecb55273e5e/greenlet-3.3.2-cp312-cp312-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:a2a5be83a45ce6188c045bcc44b0ee037d6a518978de9a5d97438548b953a1ac", size = 611792, upload-time = "2026-02-20T20:55:58.423Z" }, - { url = "https://files.pythonhosted.org/packages/5c/c5/cc09412a29e43406eba18d61c70baa936e299bc27e074e2be3806ed29098/greenlet-3.3.2-cp312-cp312-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:ae9e21c84035c490506c17002f5c8ab25f980205c3e61ddb3a2a2a2e6c411fcb", size = 626250, upload-time = "2026-02-20T21:02:46.596Z" }, { url = "https://files.pythonhosted.org/packages/50/1f/5155f55bd71cabd03765a4aac9ac446be129895271f73872c36ebd4b04b6/greenlet-3.3.2-cp312-cp312-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:43e99d1749147ac21dde49b99c9abffcbc1e2d55c67501465ef0930d6e78e070", size = 613875, upload-time = "2026-02-20T20:21:01.102Z" }, { url = "https://files.pythonhosted.org/packages/fc/dd/845f249c3fcd69e32df80cdab059b4be8b766ef5830a3d0aa9d6cad55beb/greenlet-3.3.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:4c956a19350e2c37f2c48b336a3afb4bff120b36076d9d7fb68cb44e05d95b79", size = 1571467, upload-time = "2026-02-20T20:49:33.495Z" }, { url = "https://files.pythonhosted.org/packages/2a/50/2649fe21fcc2b56659a452868e695634722a6655ba245d9f77f5656010bf/greenlet-3.3.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:6c6f8ba97d17a1e7d664151284cb3315fc5f8353e75221ed4324f84eb162b395", size = 1640001, upload-time = "2026-02-20T20:21:09.154Z" }, @@ -1838,7 +1835,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/ac/48/f8b875fa7dea7dd9b33245e37f065af59df6a25af2f9561efa8d822fde51/greenlet-3.3.2-cp313-cp313-macosx_11_0_universal2.whl", hash = "sha256:aa6ac98bdfd716a749b84d4034486863fd81c3abde9aa3cf8eff9127981a4ae4", size = 279120, upload-time = "2026-02-20T20:19:01.9Z" }, { url = "https://files.pythonhosted.org/packages/49/8d/9771d03e7a8b1ee456511961e1b97a6d77ae1dea4a34a5b98eee706689d3/greenlet-3.3.2-cp313-cp313-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ab0c7e7901a00bc0a7284907273dc165b32e0d109a6713babd04471327ff7986", size = 603238, upload-time = "2026-02-20T20:47:32.873Z" }, { url = "https://files.pythonhosted.org/packages/59/0e/4223c2bbb63cd5c97f28ffb2a8aee71bdfb30b323c35d409450f51b91e3e/greenlet-3.3.2-cp313-cp313-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:d248d8c23c67d2291ffd47af766e2a3aa9fa1c6703155c099feb11f526c63a92", size = 614219, upload-time = "2026-02-20T20:55:59.817Z" }, - { url = "https://files.pythonhosted.org/packages/94/2b/4d012a69759ac9d77210b8bfb128bc621125f5b20fc398bce3940d036b1c/greenlet-3.3.2-cp313-cp313-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:ccd21bb86944ca9be6d967cf7691e658e43417782bce90b5d2faeda0ff78a7dd", size = 628268, upload-time = "2026-02-20T21:02:48.024Z" }, { url = "https://files.pythonhosted.org/packages/7a/34/259b28ea7a2a0c904b11cd36c79b8cef8019b26ee5dbe24e73b469dea347/greenlet-3.3.2-cp313-cp313-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b6997d360a4e6a4e936c0f9625b1c20416b8a0ea18a8e19cabbefc712e7397ab", size = 616774, upload-time = "2026-02-20T20:21:02.454Z" }, { url = "https://files.pythonhosted.org/packages/0a/03/996c2d1689d486a6e199cb0f1cf9e4aa940c500e01bdf201299d7d61fa69/greenlet-3.3.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:64970c33a50551c7c50491671265d8954046cb6e8e2999aacdd60e439b70418a", size = 1571277, upload-time = "2026-02-20T20:49:34.795Z" }, { url = "https://files.pythonhosted.org/packages/d9/c4/2570fc07f34a39f2caf0bf9f24b0a1a0a47bc2e8e465b2c2424821389dfc/greenlet-3.3.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:1a9172f5bf6bd88e6ba5a84e0a68afeac9dc7b6b412b245dd64f52d83c81e55b", size = 1640455, upload-time = "2026-02-20T20:21:10.261Z" }, @@ -1847,7 +1843,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/3f/ae/8bffcbd373b57a5992cd077cbe8858fff39110480a9d50697091faea6f39/greenlet-3.3.2-cp314-cp314-macosx_11_0_universal2.whl", hash = "sha256:8d1658d7291f9859beed69a776c10822a0a799bc4bfe1bd4272bb60e62507dab", size = 279650, upload-time = "2026-02-20T20:18:00.783Z" }, { url = "https://files.pythonhosted.org/packages/d1/c0/45f93f348fa49abf32ac8439938726c480bd96b2a3c6f4d949ec0124b69f/greenlet-3.3.2-cp314-cp314-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:18cb1b7337bca281915b3c5d5ae19f4e76d35e1df80f4ad3c1a7be91fadf1082", size = 650295, upload-time = "2026-02-20T20:47:34.036Z" }, { url = "https://files.pythonhosted.org/packages/b3/de/dd7589b3f2b8372069ab3e4763ea5329940fc7ad9dcd3e272a37516d7c9b/greenlet-3.3.2-cp314-cp314-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:c2e47408e8ce1c6f1ceea0dffcdf6ebb85cc09e55c7af407c99f1112016e45e9", size = 662163, upload-time = "2026-02-20T20:56:01.295Z" }, - { url = "https://files.pythonhosted.org/packages/cd/ac/85804f74f1ccea31ba518dcc8ee6f14c79f73fe36fa1beba38930806df09/greenlet-3.3.2-cp314-cp314-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:e3cb43ce200f59483eb82949bf1835a99cf43d7571e900d7c8d5c62cdf25d2f9", size = 675371, upload-time = "2026-02-20T21:02:49.664Z" }, { url = "https://files.pythonhosted.org/packages/d2/d8/09bfa816572a4d83bccd6750df1926f79158b1c36c5f73786e26dbe4ee38/greenlet-3.3.2-cp314-cp314-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:63d10328839d1973e5ba35e98cccbca71b232b14051fd957b6f8b6e8e80d0506", size = 664160, upload-time = "2026-02-20T20:21:04.015Z" }, { url = "https://files.pythonhosted.org/packages/48/cf/56832f0c8255d27f6c35d41b5ec91168d74ec721d85f01a12131eec6b93c/greenlet-3.3.2-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:8e4ab3cfb02993c8cc248ea73d7dae6cec0253e9afa311c9b37e603ca9fad2ce", size = 1619181, upload-time = "2026-02-20T20:49:36.052Z" }, { url = "https://files.pythonhosted.org/packages/0a/23/b90b60a4aabb4cec0796e55f25ffbfb579a907c3898cd2905c8918acaa16/greenlet-3.3.2-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:94ad81f0fd3c0c0681a018a976e5c2bd2ca2d9d94895f23e7bb1af4e8af4e2d5", size = 1687713, upload-time = "2026-02-20T20:21:11.684Z" }, @@ -1856,7 +1851,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/98/6d/8f2ef704e614bcf58ed43cfb8d87afa1c285e98194ab2cfad351bf04f81e/greenlet-3.3.2-cp314-cp314t-macosx_11_0_universal2.whl", hash = "sha256:e26e72bec7ab387ac80caa7496e0f908ff954f31065b0ffc1f8ecb1338b11b54", size = 286617, upload-time = "2026-02-20T20:19:29.856Z" }, { url = "https://files.pythonhosted.org/packages/5e/0d/93894161d307c6ea237a43988f27eba0947b360b99ac5239ad3fe09f0b47/greenlet-3.3.2-cp314-cp314t-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8b466dff7a4ffda6ca975979bab80bdadde979e29fc947ac3be4451428d8b0e4", size = 655189, upload-time = "2026-02-20T20:47:35.742Z" }, { url = "https://files.pythonhosted.org/packages/f5/2c/d2d506ebd8abcb57386ec4f7ba20f4030cbe56eae541bc6fd6ef399c0b41/greenlet-3.3.2-cp314-cp314t-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:b8bddc5b73c9720bea487b3bffdb1840fe4e3656fba3bd40aa1489e9f37877ff", size = 658225, upload-time = "2026-02-20T20:56:02.527Z" }, - { url = "https://files.pythonhosted.org/packages/d1/67/8197b7e7e602150938049d8e7f30de1660cfb87e4c8ee349b42b67bdb2e1/greenlet-3.3.2-cp314-cp314t-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:59b3e2c40f6706b05a9cd299c836c6aa2378cabe25d021acd80f13abf81181cf", size = 666581, upload-time = "2026-02-20T21:02:51.526Z" }, { url = "https://files.pythonhosted.org/packages/8e/30/3a09155fbf728673a1dea713572d2d31159f824a37c22da82127056c44e4/greenlet-3.3.2-cp314-cp314t-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b26b0f4428b871a751968285a1ac9648944cea09807177ac639b030bddebcea4", size = 657907, upload-time = "2026-02-20T20:21:05.259Z" }, { url = "https://files.pythonhosted.org/packages/f3/fd/d05a4b7acd0154ed758797f0a43b4c0962a843bedfe980115e842c5b2d08/greenlet-3.3.2-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:1fb39a11ee2e4d94be9a76671482be9398560955c9e568550de0224e41104727", size = 1618857, upload-time = "2026-02-20T20:49:37.309Z" }, { url = "https://files.pythonhosted.org/packages/6f/e1/50ee92a5db521de8f35075b5eff060dd43d39ebd46c2181a2042f7070385/greenlet-3.3.2-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:20154044d9085151bc309e7689d6f7ba10027f8f5a8c0676ad398b951913d89e", size = 1680010, upload-time = "2026-02-20T20:21:13.427Z" }, @@ -2477,6 +2471,26 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/81/db/e655086b7f3a705df045bf0933bdd9c2f79bb3c97bfef1384598bb79a217/keyring-25.7.0-py3-none-any.whl", hash = "sha256:be4a0b195f149690c166e850609a477c532ddbfbaed96a404d4e43f8d5e2689f", size = 39160, upload-time = "2025-11-16T16:26:08.402Z" }, ] +[[package]] +name = "langsmith" +version = "0.7.26" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "httpx" }, + { name = "orjson", marker = "platform_python_implementation != 'PyPy'" }, + { name = "packaging" }, + { name = "pydantic" }, + { name = "requests" }, + { name = "requests-toolbelt" }, + { name = "uuid-utils" }, + { name = "xxhash" }, + { name = "zstandard" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/76/86/6de4f6f0451a9658f26f633e0bb090552a4dafd7df3f1ae7f0d40558e67e/langsmith-0.7.26.tar.gz", hash = "sha256:a3e06f3d689ce7195717aa6b8f91082319819ec7ea9b9a62cdcd3d9dc25bfc7b", size = 1146118, upload-time = "2026-04-06T15:01:03.336Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/81/8e/7eb7d65ce62e98e74b9f18f193ea7ac3996d4fbd71fffcc67d0f7ba3103e/langsmith-0.7.26-py3-none-any.whl", hash = "sha256:fe5c877972cea450c1c48251c8fae0f18543c8d19dfdb9ff9a9c4263763dde4e", size = 360160, upload-time = "2026-04-06T15:01:01.516Z" }, +] + [[package]] name = "lazy-object-proxy" version = "1.12.0" @@ -3583,6 +3597,87 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/24/7d/c88d7b15ba8fe5c6b8f93be50fc11795e9fc05386c44afaf6b76fe191f9b/opentelemetry_semantic_conventions-0.59b0-py3-none-any.whl", hash = "sha256:35d3b8833ef97d614136e253c1da9342b4c3c083bbaf29ce31d572a1c3825eed", size = 207954, upload-time = "2025-10-16T08:35:48.054Z" }, ] +[[package]] +name = "orjson" +version = "3.11.8" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/9d/1b/2024d06792d0779f9dbc51531b61c24f76c75b9f4ce05e6f3377a1814cea/orjson-3.11.8.tar.gz", hash = "sha256:96163d9cdc5a202703e9ad1b9ae757d5f0ca62f4fa0cc93d1f27b0e180cc404e", size = 5603832, upload-time = "2026-03-31T16:16:27.878Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/2f/90/5d81f61fe3e4270da80c71442864c091cee3003cc8984c75f413fe742a07/orjson-3.11.8-cp310-cp310-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:e6693ff90018600c72fd18d3d22fa438be26076cd3c823da5f63f7bab28c11cb", size = 229663, upload-time = "2026-03-31T16:14:30.708Z" }, + { url = "https://files.pythonhosted.org/packages/6c/ef/85e06b0eb11de6fb424120fd5788a07035bd4c5e6bb7841ae9972a0526d1/orjson-3.11.8-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:93de06bc920854552493c81f1f729fab7213b7db4b8195355db5fda02c7d1363", size = 132321, upload-time = "2026-03-31T16:14:32.317Z" }, + { url = "https://files.pythonhosted.org/packages/86/71/089338ee51b3132f050db0864a7df9bdd5e94c2a03820ab8a91e8f655618/orjson-3.11.8-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:fe0b8c83e0f36247fc9431ce5425a5d95f9b3a689133d494831bdbd6f0bceb13", size = 130658, upload-time = "2026-03-31T16:14:33.935Z" }, + { url = "https://files.pythonhosted.org/packages/10/0d/f39d8802345d0ad65f7fd4374b29b9b59f98656dc30f21ca5c773265b2f0/orjson-3.11.8-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:97d823831105c01f6c8029faf297633dbeb30271892bd430e9c24ceae3734744", size = 135708, upload-time = "2026-03-31T16:14:35.224Z" }, + { url = "https://files.pythonhosted.org/packages/ff/b5/40aae576b3473511696dcffea84fde638b2b64774eb4dcb8b2c262729f8a/orjson-3.11.8-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c60c0423f15abb6cf78f56dff00168a1b582f7a1c23f114036e2bfc697814d5f", size = 147047, upload-time = "2026-03-31T16:14:36.489Z" }, + { url = "https://files.pythonhosted.org/packages/7b/f0/778a84458d1fdaa634b2e572e51ce0b354232f580b2327e1f00a8d88c38c/orjson-3.11.8-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:01928d0476b216ad2201823b0a74000440360cef4fed1912d297b8d84718f277", size = 133072, upload-time = "2026-03-31T16:14:37.715Z" }, + { url = "https://files.pythonhosted.org/packages/bf/d3/1bbf2fc3ffcc4b829ade554b574af68cec898c9b5ad6420a923c75a073d3/orjson-3.11.8-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6a4a639049c44d36a6d1ae0f4a94b271605c745aee5647fa8ffaabcdc01b69a6", size = 133867, upload-time = "2026-03-31T16:14:39.356Z" }, + { url = "https://files.pythonhosted.org/packages/08/94/6413da22edc99a69a8d0c2e83bf42973b8aa94d83ef52a6d39ac85da00bc/orjson-3.11.8-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:3222adff1e1ff0dce93c16146b93063a7793de6c43d52309ae321234cdaf0f4d", size = 142268, upload-time = "2026-03-31T16:14:40.972Z" }, + { url = "https://files.pythonhosted.org/packages/4a/5f/aa5dbaa6136d7ba55f5461ac2e885efc6e6349424a428927fd46d68f4396/orjson-3.11.8-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:3223665349bbfb68da234acd9846955b1a0808cbe5520ff634bf253a4407009b", size = 424008, upload-time = "2026-03-31T16:14:42.637Z" }, + { url = "https://files.pythonhosted.org/packages/fa/aa/2c1962d108c7fe5e27aa03a354b378caf56d8eafdef15fd83dec081ce45a/orjson-3.11.8-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:61c9d357a59465736022d5d9ba06687afb7611dfb581a9d2129b77a6fcf78e59", size = 147942, upload-time = "2026-03-31T16:14:44.256Z" }, + { url = "https://files.pythonhosted.org/packages/47/d1/65f404f4c47eb1b0b4476f03ec838cac0c4aa933920ff81e5dda4dee14e7/orjson-3.11.8-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:58fb9b17b4472c7b1dcf1a54583629e62e23779b2331052f09a9249edf81675b", size = 136640, upload-time = "2026-03-31T16:14:45.884Z" }, + { url = "https://files.pythonhosted.org/packages/90/5f/7b784aea98bdb125a2f2da7c27d6c2d2f6d943d96ef0278bae596d563f85/orjson-3.11.8-cp310-cp310-win32.whl", hash = "sha256:b43dc2a391981d36c42fa57747a49dae793ef1d2e43898b197925b5534abd10a", size = 132066, upload-time = "2026-03-31T16:14:47.397Z" }, + { url = "https://files.pythonhosted.org/packages/92/ec/2e284af8d6c9478df5ef938917743f61d68f4c70d17f1b6e82f7e3b8dba1/orjson-3.11.8-cp310-cp310-win_amd64.whl", hash = "sha256:c98121237fea2f679480765abd566f7713185897f35c9e6c2add7e3a9900eb61", size = 127609, upload-time = "2026-03-31T16:14:48.78Z" }, + { url = "https://files.pythonhosted.org/packages/67/41/5aa7fa3b0f4dc6b47dcafc3cea909299c37e40e9972feabc8b6a74e2730d/orjson-3.11.8-cp311-cp311-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:003646067cc48b7fcab2ae0c562491c9b5d2cbd43f1e5f16d98fd118c5522d34", size = 229229, upload-time = "2026-03-31T16:14:50.424Z" }, + { url = "https://files.pythonhosted.org/packages/0a/d7/57e7f2458e0a2c41694f39fc830030a13053a84f837a5b73423dca1f0938/orjson-3.11.8-cp311-cp311-macosx_15_0_arm64.whl", hash = "sha256:ed193ce51d77a3830cad399a529cd4ef029968761f43ddc549e1bc62b40d88f8", size = 128871, upload-time = "2026-03-31T16:14:51.888Z" }, + { url = "https://files.pythonhosted.org/packages/53/4a/e0fdb9430983e6c46e0299559275025075568aad5d21dd606faee3703924/orjson-3.11.8-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f30491bc4f862aa15744b9738517454f1e46e56c972a2be87d70d727d5b2a8f8", size = 132104, upload-time = "2026-03-31T16:14:53.142Z" }, + { url = "https://files.pythonhosted.org/packages/08/4a/2025a60ff3f5c8522060cda46612d9b1efa653de66ed2908591d8d82f22d/orjson-3.11.8-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:6eda5b8b6be91d3f26efb7dc6e5e68ee805bc5617f65a328587b35255f138bf4", size = 130483, upload-time = "2026-03-31T16:14:54.605Z" }, + { url = "https://files.pythonhosted.org/packages/2d/3c/b9cde05bdc7b2385c66014e0620627da638d3d04e4954416ab48c31196c5/orjson-3.11.8-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ee8db7bfb6fe03581bbab54d7c4124a6dd6a7f4273a38f7267197890f094675f", size = 135481, upload-time = "2026-03-31T16:14:55.901Z" }, + { url = "https://files.pythonhosted.org/packages/ff/f2/a8238e7734de7cb589fed319857a8025d509c89dc52fdcc88f39c6d03d5a/orjson-3.11.8-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5d8b5231de76c528a46b57010bbd83fb51e056aa0220a372fd5065e978406f1c", size = 146819, upload-time = "2026-03-31T16:14:57.548Z" }, + { url = "https://files.pythonhosted.org/packages/db/10/dbf1e2a3cafea673b1b4350e371877b759060d6018a998643b7040e5de48/orjson-3.11.8-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:58a4a208a6fbfdb7a7327b8f201c6014f189f721fd55d047cafc4157af1bc62a", size = 132846, upload-time = "2026-03-31T16:14:58.91Z" }, + { url = "https://files.pythonhosted.org/packages/f8/fc/55e667ec9c85694038fcff00573d221b085d50777368ee3d77f38668bf3c/orjson-3.11.8-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5f8952d6d2505c003e8f0224ff7858d341fa4e33fef82b91c4ff0ef070f2393c", size = 133580, upload-time = "2026-03-31T16:15:00.519Z" }, + { url = "https://files.pythonhosted.org/packages/7e/a6/c08c589a9aad0cb46c4831d17de212a2b6901f9d976814321ff8e69e8785/orjson-3.11.8-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:0022bb50f90da04b009ce32c512dc1885910daa7cb10b7b0cba4505b16db82a8", size = 142042, upload-time = "2026-03-31T16:15:01.906Z" }, + { url = "https://files.pythonhosted.org/packages/5c/cc/2f78ea241d52b717d2efc38878615fe80425bf2beb6e68c984dde257a766/orjson-3.11.8-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:ff51f9d657d1afb6f410cb435792ce4e1fe427aab23d2fcd727a2876e21d4cb6", size = 423845, upload-time = "2026-03-31T16:15:03.703Z" }, + { url = "https://files.pythonhosted.org/packages/70/07/c17dcf05dd8045457538428a983bf1f1127928df5bf328cb24d2b7cddacb/orjson-3.11.8-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:6dbe9a97bdb4d8d9d5367b52a7c32549bba70b2739c58ef74a6964a6d05ae054", size = 147729, upload-time = "2026-03-31T16:15:05.203Z" }, + { url = "https://files.pythonhosted.org/packages/90/6c/0fb6e8a24e682e0958d71711ae6f39110e4b9cd8cab1357e2a89cb8e1951/orjson-3.11.8-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:a5c370674ebabe16c6ccac33ff80c62bf8a6e59439f5e9d40c1f5ab8fd2215b7", size = 136425, upload-time = "2026-03-31T16:15:07.052Z" }, + { url = "https://files.pythonhosted.org/packages/b2/35/4d3cc3a3d616035beb51b24a09bb872942dc452cf2df0c1d11ab35046d9f/orjson-3.11.8-cp311-cp311-win32.whl", hash = "sha256:0e32f7154299f42ae66f13488963269e5eccb8d588a65bc839ed986919fc9fac", size = 131870, upload-time = "2026-03-31T16:15:08.678Z" }, + { url = "https://files.pythonhosted.org/packages/13/26/9fe70f81d16b702f8c3a775e8731b50ad91d22dacd14c7599b60a0941cd1/orjson-3.11.8-cp311-cp311-win_amd64.whl", hash = "sha256:25e0c672a2e32348d2eb33057b41e754091f2835f87222e4675b796b92264f06", size = 127440, upload-time = "2026-03-31T16:15:09.994Z" }, + { url = "https://files.pythonhosted.org/packages/e8/c6/b038339f4145efd2859c1ca53097a52c0bb9cbdd24f947ebe146da1ad067/orjson-3.11.8-cp311-cp311-win_arm64.whl", hash = "sha256:9185589c1f2a944c17e26c9925dcdbc2df061cc4a145395c57f0c51f9b5dbfcd", size = 127399, upload-time = "2026-03-31T16:15:11.412Z" }, + { url = "https://files.pythonhosted.org/packages/01/f6/8d58b32ab32d9215973a1688aebd098252ee8af1766c0e4e36e7831f0295/orjson-3.11.8-cp312-cp312-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:1cd0b77e77c95758f8e1100139844e99f3ccc87e71e6fc8e1c027e55807c549f", size = 229233, upload-time = "2026-03-31T16:15:12.762Z" }, + { url = "https://files.pythonhosted.org/packages/a9/8b/2ffe35e71f6b92622e8ea4607bf33ecf7dfb51b3619dcfabfd36cbe2d0a5/orjson-3.11.8-cp312-cp312-macosx_15_0_arm64.whl", hash = "sha256:6a3d159d5ffa0e3961f353c4b036540996bf8b9697ccc38261c0eac1fd3347a6", size = 128772, upload-time = "2026-03-31T16:15:14.237Z" }, + { url = "https://files.pythonhosted.org/packages/27/d2/1f8682ae50d5c6897a563cb96bc106da8c9cb5b7b6e81a52e4cc086679b9/orjson-3.11.8-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:76070a76e9c5ae661e2d9848f216980d8d533e0f8143e6ed462807b242e3c5e8", size = 131946, upload-time = "2026-03-31T16:15:15.607Z" }, + { url = "https://files.pythonhosted.org/packages/52/4b/5500f76f0eece84226e0689cb48dcde081104c2fa6e2483d17ca13685ffb/orjson-3.11.8-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:54153d21520a71a4c82a0dbb4523e468941d549d221dc173de0f019678cf3813", size = 130368, upload-time = "2026-03-31T16:15:17.066Z" }, + { url = "https://files.pythonhosted.org/packages/da/4e/58b927e08fbe9840e6c920d9e299b051ea667463b1f39a56e668669f8508/orjson-3.11.8-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:469ac2125611b7c5741a0b3798cd9e5786cbad6345f9f400c77212be89563bec", size = 135540, upload-time = "2026-03-31T16:15:18.404Z" }, + { url = "https://files.pythonhosted.org/packages/56/7c/ba7cb871cba1bcd5cd02ee34f98d894c6cea96353ad87466e5aef2429c60/orjson-3.11.8-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:14778ffd0f6896aa613951a7fbf4690229aa7a543cb2bfbe9f358e08aafa9546", size = 146877, upload-time = "2026-03-31T16:15:19.833Z" }, + { url = "https://files.pythonhosted.org/packages/0b/5d/eb9c25fc1386696c6a342cd361c306452c75e0b55e86ad602dd4827a7fd7/orjson-3.11.8-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ea56a955056a6d6c550cf18b3348656a9d9a4f02e2d0c02cabf3c73f1055d506", size = 132837, upload-time = "2026-03-31T16:15:21.282Z" }, + { url = "https://files.pythonhosted.org/packages/37/87/5ddeb7fc1fbd9004aeccab08426f34c81a5b4c25c7061281862b015fce2b/orjson-3.11.8-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:53a0f57e59a530d18a142f4d4ba6dfc708dc5fdedce45e98ff06b44930a2a48f", size = 133624, upload-time = "2026-03-31T16:15:22.641Z" }, + { url = "https://files.pythonhosted.org/packages/22/09/90048793db94ee4b2fcec4ac8e5ddb077367637d6650be896b3494b79bb7/orjson-3.11.8-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:9b48e274f8824567d74e2158199e269597edf00823a1b12b63d48462bbf5123e", size = 141904, upload-time = "2026-03-31T16:15:24.435Z" }, + { url = "https://files.pythonhosted.org/packages/c0/cf/eb284847487821a5d415e54149a6449ba9bfc5872ce63ab7be41b8ec401c/orjson-3.11.8-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:3f262401086a3960586af06c054609365e98407151f5ea24a62893a40d80dbbb", size = 423742, upload-time = "2026-03-31T16:15:26.155Z" }, + { url = "https://files.pythonhosted.org/packages/44/09/e12423d327071c851c13e76936f144a96adacfc037394dec35ac3fc8d1e8/orjson-3.11.8-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:8e8c6218b614badf8e229b697865df4301afa74b791b6c9ade01d19a9953a942", size = 147806, upload-time = "2026-03-31T16:15:27.909Z" }, + { url = "https://files.pythonhosted.org/packages/b3/6d/37c2589ba864e582ffe7611643314785c6afb1f83c701654ef05daa8fcc7/orjson-3.11.8-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:093d489fa039ddade2db541097dbb484999fcc65fc2b0ff9819141e2ab364f25", size = 136485, upload-time = "2026-03-31T16:15:29.749Z" }, + { url = "https://files.pythonhosted.org/packages/be/c9/135194a02ab76b04ed9a10f68624b7ebd238bbe55548878b11ff15a0f352/orjson-3.11.8-cp312-cp312-win32.whl", hash = "sha256:e0950ed1bcb9893f4293fd5c5a7ee10934fbf82c4101c70be360db23ce24b7d2", size = 131966, upload-time = "2026-03-31T16:15:31.687Z" }, + { url = "https://files.pythonhosted.org/packages/ed/9a/9796f8fbe3cf30ce9cb696748dbb535e5c87be4bf4fe2e9ca498ef1fa8cf/orjson-3.11.8-cp312-cp312-win_amd64.whl", hash = "sha256:3cf17c141617b88ced4536b2135c552490f07799f6ad565948ea07bef0dcb9a6", size = 127441, upload-time = "2026-03-31T16:15:33.333Z" }, + { url = "https://files.pythonhosted.org/packages/cc/47/5aaf54524a7a4a0dd09dd778f3fa65dd2108290615b652e23d944152bc8e/orjson-3.11.8-cp312-cp312-win_arm64.whl", hash = "sha256:48854463b0572cc87dac7d981aa72ed8bf6deedc0511853dc76b8bbd5482d36d", size = 127364, upload-time = "2026-03-31T16:15:34.748Z" }, + { url = "https://files.pythonhosted.org/packages/66/7f/95fba509bb2305fab0073558f1e8c3a2ec4b2afe58ed9fcb7d3b8beafe94/orjson-3.11.8-cp313-cp313-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:3f23426851d98478c8970da5991f84784a76682213cd50eb73a1da56b95239dc", size = 229180, upload-time = "2026-03-31T16:15:36.426Z" }, + { url = "https://files.pythonhosted.org/packages/f6/9d/b237215c743ca073697d759b5503abd2cb8a0d7b9c9e21f524bcf176ab66/orjson-3.11.8-cp313-cp313-macosx_15_0_arm64.whl", hash = "sha256:ebaed4cef74a045b83e23537b52ef19a367c7e3f536751e355a2a394f8648559", size = 128754, upload-time = "2026-03-31T16:15:38.049Z" }, + { url = "https://files.pythonhosted.org/packages/42/3d/27d65b6d11e63f133781425f132807aef793ed25075fec686fc8e46dd528/orjson-3.11.8-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:97c8f5d3b62380b70c36ffacb2a356b7c6becec86099b177f73851ba095ef623", size = 131877, upload-time = "2026-03-31T16:15:39.484Z" }, + { url = "https://files.pythonhosted.org/packages/dd/cc/faee30cd8f00421999e40ef0eba7332e3a625ce91a58200a2f52c7fef235/orjson-3.11.8-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:436c4922968a619fb7fef1ccd4b8b3a76c13b67d607073914d675026e911a65c", size = 130361, upload-time = "2026-03-31T16:15:41.274Z" }, + { url = "https://files.pythonhosted.org/packages/5c/bb/a6c55896197f97b6d4b4e7c7fd77e7235517c34f5d6ad5aadd43c54c6d7c/orjson-3.11.8-cp313-cp313-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1ab359aff0436d80bfe8a23b46b5fea69f1e18aaf1760a709b4787f1318b317f", size = 135521, upload-time = "2026-03-31T16:15:42.758Z" }, + { url = "https://files.pythonhosted.org/packages/9c/7c/ca3a3525aa32ff636ebb1778e77e3587b016ab2edb1b618b36ba96f8f2c0/orjson-3.11.8-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f89b6d0b3a8d81e1929d3ab3d92bbc225688bd80a770c49432543928fe09ac55", size = 146862, upload-time = "2026-03-31T16:15:44.341Z" }, + { url = "https://files.pythonhosted.org/packages/3c/0c/18a9d7f18b5edd37344d1fd5be17e94dc652c67826ab749c6e5948a78112/orjson-3.11.8-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:29c009e7a2ca9ad0ed1376ce20dd692146a5d9fe4310848904b6b4fee5c5c137", size = 132847, upload-time = "2026-03-31T16:15:46.368Z" }, + { url = "https://files.pythonhosted.org/packages/23/91/7e722f352ad67ca573cee44de2a58fb810d0f4eb4e33276c6a557979fd8a/orjson-3.11.8-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:705b895b781b3e395c067129d8551655642dfe9437273211d5404e87ac752b53", size = 133637, upload-time = "2026-03-31T16:15:48.123Z" }, + { url = "https://files.pythonhosted.org/packages/af/04/32845ce13ac5bd1046ddb02ac9432ba856cc35f6d74dde95864fe0ad5523/orjson-3.11.8-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:88006eda83858a9fdf73985ce3804e885c2befb2f506c9a3723cdeb5a2880e3e", size = 141906, upload-time = "2026-03-31T16:15:49.626Z" }, + { url = "https://files.pythonhosted.org/packages/02/5e/c551387ddf2d7106d9039369862245c85738b828844d13b99ccb8d61fd06/orjson-3.11.8-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:55120759e61309af7fcf9e961c6f6af3dde5921cdb3ee863ef63fd9db126cae6", size = 423722, upload-time = "2026-03-31T16:15:51.176Z" }, + { url = "https://files.pythonhosted.org/packages/00/a3/ecfe62434096f8a794d4976728cb59bcfc4a643977f21c2040545d37eb4c/orjson-3.11.8-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:98bdc6cb889d19bed01de46e67574a2eab61f5cc6b768ed50e8ac68e9d6ffab6", size = 147801, upload-time = "2026-03-31T16:15:52.939Z" }, + { url = "https://files.pythonhosted.org/packages/18/6d/0dce10b9f6643fdc59d99333871a38fa5a769d8e2fc34a18e5d2bfdee900/orjson-3.11.8-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:708c95f925a43ab9f34625e45dcdadf09ec8a6e7b664a938f2f8d5650f6c090b", size = 136460, upload-time = "2026-03-31T16:15:54.431Z" }, + { url = "https://files.pythonhosted.org/packages/01/d6/6dde4f31842d87099238f1f07b459d24edc1a774d20687187443ab044191/orjson-3.11.8-cp313-cp313-win32.whl", hash = "sha256:01c4e5a6695dc09098f2e6468a251bc4671c50922d4d745aff1a0a33a0cf5b8d", size = 131956, upload-time = "2026-03-31T16:15:56.081Z" }, + { url = "https://files.pythonhosted.org/packages/c1/f9/4e494a56e013db957fb77186b818b916d4695b8fa2aa612364974160e91b/orjson-3.11.8-cp313-cp313-win_amd64.whl", hash = "sha256:c154a35dd1330707450bb4d4e7dd1f17fa6f42267a40c1e8a1daa5e13719b4b8", size = 127410, upload-time = "2026-03-31T16:15:57.54Z" }, + { url = "https://files.pythonhosted.org/packages/57/7f/803203d00d6edb6e9e7eef421d4e1adbb5ea973e40b3533f3cfd9aeb374e/orjson-3.11.8-cp313-cp313-win_arm64.whl", hash = "sha256:4861bde57f4d253ab041e374f44023460e60e71efaa121f3c5f0ed457c3a701e", size = 127338, upload-time = "2026-03-31T16:15:59.106Z" }, + { url = "https://files.pythonhosted.org/packages/6d/35/b01910c3d6b85dc882442afe5060cbf719c7d1fc85749294beda23d17873/orjson-3.11.8-cp314-cp314-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:ec795530a73c269a55130498842aaa762e4a939f6ce481a7e986eeaa790e9da4", size = 229171, upload-time = "2026-03-31T16:16:00.651Z" }, + { url = "https://files.pythonhosted.org/packages/c2/56/c9ec97bd11240abef39b9e5d99a15462809c45f677420fd148a6c5e6295e/orjson-3.11.8-cp314-cp314-macosx_15_0_arm64.whl", hash = "sha256:c492a0e011c0f9066e9ceaa896fbc5b068c54d365fea5f3444b697ee01bc8625", size = 128746, upload-time = "2026-03-31T16:16:02.673Z" }, + { url = "https://files.pythonhosted.org/packages/3b/e4/66d4f30a90de45e2f0cbd9623588e8ae71eef7679dbe2ae954ed6d66a41f/orjson-3.11.8-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:883206d55b1bd5f5679ad5e6ddd3d1a5e3cac5190482927fdb8c78fb699193b5", size = 131867, upload-time = "2026-03-31T16:16:04.342Z" }, + { url = "https://files.pythonhosted.org/packages/19/30/2a645fc9286b928675e43fa2a3a16fb7b6764aa78cc719dc82141e00f30b/orjson-3.11.8-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5774c1fdcc98b2259800b683b19599c133baeb11d60033e2095fd9d4667b82db", size = 124664, upload-time = "2026-03-31T16:16:05.837Z" }, + { url = "https://files.pythonhosted.org/packages/db/44/77b9a86d84a28d52ba3316d77737f6514e17118119ade3f91b639e859029/orjson-3.11.8-cp314-cp314-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8ac7381c83dd3d4a6347e6635950aa448f54e7b8406a27c7ecb4a37e9f1ae08b", size = 129701, upload-time = "2026-03-31T16:16:07.407Z" }, + { url = "https://files.pythonhosted.org/packages/b3/ea/eff3d9bfe47e9bc6969c9181c58d9f71237f923f9c86a2d2f490cd898c82/orjson-3.11.8-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:14439063aebcb92401c11afc68ee4e407258d2752e62d748b6942dad20d2a70d", size = 141202, upload-time = "2026-03-31T16:16:09.48Z" }, + { url = "https://files.pythonhosted.org/packages/52/c8/90d4b4c60c84d62068d0cf9e4d8f0a4e05e76971d133ac0c60d818d4db20/orjson-3.11.8-cp314-cp314-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:fa72e71977bff96567b0f500fc5bfd2fdf915f34052c782a4c6ebbdaa97aa858", size = 127194, upload-time = "2026-03-31T16:16:11.02Z" }, + { url = "https://files.pythonhosted.org/packages/8d/c7/ea9e08d1f0ba981adffb629811148b44774d935171e7b3d780ae43c4c254/orjson-3.11.8-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7679bc2f01bb0d219758f1a5f87bb7c8a81c0a186824a393b366876b4948e14f", size = 133639, upload-time = "2026-03-31T16:16:13.434Z" }, + { url = "https://files.pythonhosted.org/packages/6c/8c/ddbbfd6ba59453c8fc7fe1d0e5983895864e264c37481b2a791db635f046/orjson-3.11.8-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:14f7b8fcb35ef403b42fa5ecfa4ed032332a91f3dc7368fbce4184d59e1eae0d", size = 141914, upload-time = "2026-03-31T16:16:14.955Z" }, + { url = "https://files.pythonhosted.org/packages/4e/31/dbfbefec9df060d34ef4962cd0afcb6fa7a9ec65884cb78f04a7859526c3/orjson-3.11.8-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:c2bdf7b2facc80b5e34f48a2d557727d5c5c57a8a450de122ae81fa26a81c1bc", size = 423800, upload-time = "2026-03-31T16:16:16.594Z" }, + { url = "https://files.pythonhosted.org/packages/87/cf/f74e9ae9803d4ab46b163494adba636c6d7ea955af5cc23b8aaa94cfd528/orjson-3.11.8-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:ccd7ba1b0605813a0715171d39ec4c314cb97a9c85893c2c5c0c3a3729df38bf", size = 147837, upload-time = "2026-03-31T16:16:18.585Z" }, + { url = "https://files.pythonhosted.org/packages/64/e6/9214f017b5db85e84e68602792f742e5dc5249e963503d1b356bee611e01/orjson-3.11.8-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:cdbc8c9c02463fef4d3c53a9ba3336d05496ec8e1f1c53326a1e4acc11f5c600", size = 136441, upload-time = "2026-03-31T16:16:20.151Z" }, + { url = "https://files.pythonhosted.org/packages/24/dd/3590348818f58f837a75fb969b04cdf187ae197e14d60b5e5a794a38b79d/orjson-3.11.8-cp314-cp314-win32.whl", hash = "sha256:0b57f67710a8cd459e4e54eb96d5f77f3624eba0c661ba19a525807e42eccade", size = 131983, upload-time = "2026-03-31T16:16:21.823Z" }, + { url = "https://files.pythonhosted.org/packages/3f/0f/b6cb692116e05d058f31ceee819c70f097fa9167c82f67fabe7516289abc/orjson-3.11.8-cp314-cp314-win_amd64.whl", hash = "sha256:735e2262363dcbe05c35e3a8869898022af78f89dde9e256924dc02e99fe69ca", size = 127396, upload-time = "2026-03-31T16:16:23.685Z" }, + { url = "https://files.pythonhosted.org/packages/c0/d1/facb5b5051fabb0ef9d26c6544d87ef19a939a9a001198655d0d891062dd/orjson-3.11.8-cp314-cp314-win_arm64.whl", hash = "sha256:6ccdea2c213cf9f3d9490cbd5d427693c870753df41e6cb375bd79bcbafc8817", size = 127330, upload-time = "2026-03-31T16:16:25.496Z" }, +] + [[package]] name = "packaging" version = "26.0" @@ -4940,6 +5035,9 @@ lambda-worker-otel = [ { name = "opentelemetry-sdk-extension-aws" }, { name = "opentelemetry-semantic-conventions" }, ] +langsmith = [ + { name = "langsmith" }, +] openai-agents = [ { name = "mcp" }, { name = "openai-agents" }, @@ -4959,6 +5057,7 @@ dev = [ { name = "googleapis-common-protos" }, { name = "grpcio-tools" }, { name = "httpx" }, + { name = "langsmith" }, { name = "maturin" }, { name = "moto", extra = ["s3", "server"] }, { name = "mypy" }, @@ -4992,6 +5091,7 @@ requires-dist = [ { name = "aioboto3", marker = "extra == 'aioboto3'", specifier = ">=10.4.0" }, { name = "google-adk", marker = "extra == 'google-adk'", specifier = ">=1.27.0,<2" }, { name = "grpcio", marker = "extra == 'grpc'", specifier = ">=1.48.2,<2" }, + { name = "langsmith", marker = "extra == 'langsmith'", specifier = ">=0.7.0,<0.8" }, { name = "mcp", marker = "extra == 'openai-agents'", specifier = ">=1.9.4,<2" }, { name = "nexus-rpc", specifier = "==1.4.0" }, { name = "openai-agents", marker = "extra == 'openai-agents'", specifier = ">=0.3,<0.7" }, @@ -5009,7 +5109,7 @@ requires-dist = [ { name = "types-protobuf", specifier = ">=3.20,<7.0.0" }, { name = "typing-extensions", specifier = ">=4.2.0,<5" }, ] -provides-extras = ["grpc", "opentelemetry", "pydantic", "openai-agents", "google-adk", "lambda-worker-otel", "aioboto3"] +provides-extras = ["grpc", "opentelemetry", "pydantic", "openai-agents", "google-adk", "langsmith", "lambda-worker-otel", "aioboto3"] [package.metadata.requires-dev] dev = [ @@ -5018,6 +5118,7 @@ dev = [ { name = "googleapis-common-protos", specifier = "==1.70.0" }, { name = "grpcio-tools", specifier = ">=1.48.2,<2" }, { name = "httpx", specifier = ">=0.28.1" }, + { name = "langsmith", specifier = ">=0.7.0,<0.8" }, { name = "maturin", specifier = ">=1.8.2" }, { name = "moto", extras = ["s3", "server"], specifier = ">=5" }, { name = "mypy", specifier = "==1.18.2" }, @@ -5418,6 +5519,35 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/39/08/aaaad47bc4e9dc8c725e68f9d04865dbcb2052843ff09c97b08904852d84/urllib3-2.6.3-py3-none-any.whl", hash = "sha256:bf272323e553dfb2e87d9bfd225ca7b0f467b919d7bbd355436d3fd37cb0acd4", size = 131584, upload-time = "2026-01-07T16:24:42.685Z" }, ] +[[package]] +name = "uuid-utils" +version = "0.14.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/7b/d1/38a573f0c631c062cf42fa1f5d021d4dd3c31fb23e4376e4b56b0c9fbbed/uuid_utils-0.14.1.tar.gz", hash = "sha256:9bfc95f64af80ccf129c604fb6b8ca66c6f256451e32bc4570f760e4309c9b69", size = 22195, upload-time = "2026-02-20T22:50:38.833Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/43/b7/add4363039a34506a58457d96d4aa2126061df3a143eb4d042aedd6a2e76/uuid_utils-0.14.1-cp39-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:93a3b5dc798a54a1feb693f2d1cb4cf08258c32ff05ae4929b5f0a2ca624a4f0", size = 604679, upload-time = "2026-02-20T22:50:27.469Z" }, + { url = "https://files.pythonhosted.org/packages/dd/84/d1d0bef50d9e66d31b2019997c741b42274d53dde2e001b7a83e9511c339/uuid_utils-0.14.1-cp39-abi3-macosx_10_12_x86_64.whl", hash = "sha256:ccd65a4b8e83af23eae5e56d88034b2fe7264f465d3e830845f10d1591b81741", size = 309346, upload-time = "2026-02-20T22:50:31.857Z" }, + { url = "https://files.pythonhosted.org/packages/ef/ed/b6d6fd52a6636d7c3eddf97d68da50910bf17cd5ac221992506fb56cf12e/uuid_utils-0.14.1-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b56b0cacd81583834820588378e432b0696186683b813058b707aedc1e16c4b1", size = 344714, upload-time = "2026-02-20T22:50:42.642Z" }, + { url = "https://files.pythonhosted.org/packages/a8/a7/a19a1719fb626fe0b31882db36056d44fe904dc0cf15b06fdf56b2679cf7/uuid_utils-0.14.1-cp39-abi3-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:bb3cf14de789097320a3c56bfdfdd51b1225d11d67298afbedee7e84e3837c96", size = 350914, upload-time = "2026-02-20T22:50:36.487Z" }, + { url = "https://files.pythonhosted.org/packages/1d/fc/f6690e667fdc3bb1a73f57951f97497771c56fe23e3d302d7404be394d4f/uuid_utils-0.14.1-cp39-abi3-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:60e0854a90d67f4b0cc6e54773deb8be618f4c9bad98d3326f081423b5d14fae", size = 482609, upload-time = "2026-02-20T22:50:37.511Z" }, + { url = "https://files.pythonhosted.org/packages/54/6e/dcd3fa031320921a12ec7b4672dea3bd1dd90ddffa363a91831ba834d559/uuid_utils-0.14.1-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ce6743ba194de3910b5feb1a62590cd2587e33a73ab6af8a01b642ceb5055862", size = 345699, upload-time = "2026-02-20T22:50:46.87Z" }, + { url = "https://files.pythonhosted.org/packages/04/28/e5220204b58b44ac0047226a9d016a113fde039280cc8732d9e6da43b39f/uuid_utils-0.14.1-cp39-abi3-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:043fb58fde6cf1620a6c066382f04f87a8e74feb0f95a585e4ed46f5d44af57b", size = 372205, upload-time = "2026-02-20T22:50:28.438Z" }, + { url = "https://files.pythonhosted.org/packages/c7/d9/3d2eb98af94b8dfffc82b6a33b4dfc87b0a5de2c68a28f6dde0db1f8681b/uuid_utils-0.14.1-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:c915d53f22945e55fe0d3d3b0b87fd965a57f5fd15666fd92d6593a73b1dd297", size = 521836, upload-time = "2026-02-20T22:50:23.057Z" }, + { url = "https://files.pythonhosted.org/packages/a8/15/0eb106cc6fe182f7577bc0ab6e2f0a40be247f35c5e297dbf7bbc460bd02/uuid_utils-0.14.1-cp39-abi3-musllinux_1_2_armv7l.whl", hash = "sha256:0972488e3f9b449e83f006ead5a0e0a33ad4a13e4462e865b7c286ab7d7566a3", size = 625260, upload-time = "2026-02-20T22:50:25.949Z" }, + { url = "https://files.pythonhosted.org/packages/3c/17/f539507091334b109e7496830af2f093d9fc8082411eafd3ece58af1f8ba/uuid_utils-0.14.1-cp39-abi3-musllinux_1_2_i686.whl", hash = "sha256:1c238812ae0c8ffe77d8d447a32c6dfd058ea4631246b08b5a71df586ff08531", size = 587824, upload-time = "2026-02-20T22:50:35.225Z" }, + { url = "https://files.pythonhosted.org/packages/2e/c2/d37a7b2e41f153519367d4db01f0526e0d4b06f1a4a87f1c5dfca5d70a8b/uuid_utils-0.14.1-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:bec8f8ef627af86abf8298e7ec50926627e29b34fa907fcfbedb45aaa72bca43", size = 551407, upload-time = "2026-02-20T22:50:44.915Z" }, + { url = "https://files.pythonhosted.org/packages/65/36/2d24b2cbe78547c6532da33fb8613debd3126eccc33a6374ab788f5e46e9/uuid_utils-0.14.1-cp39-abi3-win32.whl", hash = "sha256:b54d6aa6252d96bac1fdbc80d26ba71bad9f220b2724d692ad2f2310c22ef523", size = 183476, upload-time = "2026-02-20T22:50:32.745Z" }, + { url = "https://files.pythonhosted.org/packages/83/92/2d7e90df8b1a69ec4cff33243ce02b7a62f926ef9e2f0eca5a026889cd73/uuid_utils-0.14.1-cp39-abi3-win_amd64.whl", hash = "sha256:fc27638c2ce267a0ce3e06828aff786f91367f093c80625ee21dad0208e0f5ba", size = 187147, upload-time = "2026-02-20T22:50:45.807Z" }, + { url = "https://files.pythonhosted.org/packages/d9/26/529f4beee17e5248e37e0bc17a2761d34c0fa3b1e5729c88adb2065bae6e/uuid_utils-0.14.1-cp39-abi3-win_arm64.whl", hash = "sha256:b04cb49b42afbc4ff8dbc60cf054930afc479d6f4dd7f1ec3bbe5dbfdde06b7a", size = 188132, upload-time = "2026-02-20T22:50:41.718Z" }, + { url = "https://files.pythonhosted.org/packages/91/f9/6c64bdbf71f58ccde7919e00491812556f446a5291573af92c49a5e9aaef/uuid_utils-0.14.1-pp311-pypy311_pp73-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:b197cd5424cf89fb019ca7f53641d05bfe34b1879614bed111c9c313b5574cd8", size = 591617, upload-time = "2026-02-20T22:50:24.532Z" }, + { url = "https://files.pythonhosted.org/packages/d0/f0/758c3b0fb0c4871c7704fef26a5bc861de4f8a68e4831669883bebe07b0f/uuid_utils-0.14.1-pp311-pypy311_pp73-macosx_10_12_x86_64.whl", hash = "sha256:12c65020ba6cb6abe1d57fcbfc2d0ea0506c67049ee031714057f5caf0f9bc9c", size = 303702, upload-time = "2026-02-20T22:50:40.687Z" }, + { url = "https://files.pythonhosted.org/packages/85/89/d91862b544c695cd58855efe3201f83894ed82fffe34500774238ab8eba7/uuid_utils-0.14.1-pp311-pypy311_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0b5d2ad28063d422ccc2c28d46471d47b61a58de885d35113a8f18cb547e25bf", size = 337678, upload-time = "2026-02-20T22:50:39.768Z" }, + { url = "https://files.pythonhosted.org/packages/ee/6b/cf342ba8a898f1de024be0243fac67c025cad530c79ea7f89c4ce718891a/uuid_utils-0.14.1-pp311-pypy311_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:da2234387b45fde40b0fedfee64a0ba591caeea9c48c7698ab6e2d85c7991533", size = 343711, upload-time = "2026-02-20T22:50:43.965Z" }, + { url = "https://files.pythonhosted.org/packages/b3/20/049418d094d396dfa6606b30af925cc68a6670c3b9103b23e6990f84b589/uuid_utils-0.14.1-pp311-pypy311_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:50fffc2827348c1e48972eed3d1c698959e63f9d030aa5dd82ba451113158a62", size = 476731, upload-time = "2026-02-20T22:50:30.589Z" }, + { url = "https://files.pythonhosted.org/packages/77/a1/0857f64d53a90321e6a46a3d4cc394f50e1366132dcd2ae147f9326ca98b/uuid_utils-0.14.1-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c1dbe718765f70f5b7f9b7f66b6a937802941b1cc56bcf642ce0274169741e01", size = 338902, upload-time = "2026-02-20T22:50:33.927Z" }, + { url = "https://files.pythonhosted.org/packages/ed/d0/5bf7cbf1ac138c92b9ac21066d18faf4d7e7f651047b700eb192ca4b9fdb/uuid_utils-0.14.1-pp311-pypy311_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:258186964039a8e36db10810c1ece879d229b01331e09e9030bc5dcabe231bd2", size = 364700, upload-time = "2026-02-20T22:50:21.732Z" }, +] + [[package]] name = "uvicorn" version = "0.44.0" @@ -5613,6 +5743,124 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/38/34/98a2f52245f4d47be93b580dae5f9861ef58977d73a79eb47c58f1ad1f3a/xmltodict-1.0.4-py3-none-any.whl", hash = "sha256:a4a00d300b0e1c59fc2bfccb53d7b2e88c32f200df138a0dd2229f842497026a", size = 13580, upload-time = "2026-02-22T02:21:21.039Z" }, ] +[[package]] +name = "xxhash" +version = "3.6.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/02/84/30869e01909fb37a6cc7e18688ee8bf1e42d57e7e0777636bd47524c43c7/xxhash-3.6.0.tar.gz", hash = "sha256:f0162a78b13a0d7617b2845b90c763339d1f1d82bb04a4b07f4ab535cc5e05d6", size = 85160, upload-time = "2025-10-02T14:37:08.097Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/34/ee/f9f1d656ad168681bb0f6b092372c1e533c4416b8069b1896a175c46e484/xxhash-3.6.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:87ff03d7e35c61435976554477a7f4cd1704c3596a89a8300d5ce7fc83874a71", size = 32845, upload-time = "2025-10-02T14:33:51.573Z" }, + { url = "https://files.pythonhosted.org/packages/a3/b1/93508d9460b292c74a09b83d16750c52a0ead89c51eea9951cb97a60d959/xxhash-3.6.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:f572dfd3d0e2eb1a57511831cf6341242f5a9f8298a45862d085f5b93394a27d", size = 30807, upload-time = "2025-10-02T14:33:52.964Z" }, + { url = "https://files.pythonhosted.org/packages/07/55/28c93a3662f2d200c70704efe74aab9640e824f8ce330d8d3943bf7c9b3c/xxhash-3.6.0-cp310-cp310-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:89952ea539566b9fed2bbd94e589672794b4286f342254fad28b149f9615fef8", size = 193786, upload-time = "2025-10-02T14:33:54.272Z" }, + { url = "https://files.pythonhosted.org/packages/c1/96/fec0be9bb4b8f5d9c57d76380a366f31a1781fb802f76fc7cda6c84893c7/xxhash-3.6.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:48e6f2ffb07a50b52465a1032c3cf1f4a5683f944acaca8a134a2f23674c2058", size = 212830, upload-time = "2025-10-02T14:33:55.706Z" }, + { url = "https://files.pythonhosted.org/packages/c4/a0/c706845ba77b9611f81fd2e93fad9859346b026e8445e76f8c6fd057cc6d/xxhash-3.6.0-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:b5b848ad6c16d308c3ac7ad4ba6bede80ed5df2ba8ed382f8932df63158dd4b2", size = 211606, upload-time = "2025-10-02T14:33:57.133Z" }, + { url = "https://files.pythonhosted.org/packages/67/1e/164126a2999e5045f04a69257eea946c0dc3e86541b400d4385d646b53d7/xxhash-3.6.0-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:a034590a727b44dd8ac5914236a7b8504144447a9682586c3327e935f33ec8cc", size = 444872, upload-time = "2025-10-02T14:33:58.446Z" }, + { url = "https://files.pythonhosted.org/packages/2d/4b/55ab404c56cd70a2cf5ecfe484838865d0fea5627365c6c8ca156bd09c8f/xxhash-3.6.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8a8f1972e75ebdd161d7896743122834fe87378160c20e97f8b09166213bf8cc", size = 193217, upload-time = "2025-10-02T14:33:59.724Z" }, + { url = "https://files.pythonhosted.org/packages/45/e6/52abf06bac316db33aa269091ae7311bd53cfc6f4b120ae77bac1b348091/xxhash-3.6.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:ee34327b187f002a596d7b167ebc59a1b729e963ce645964bbc050d2f1b73d07", size = 210139, upload-time = "2025-10-02T14:34:02.041Z" }, + { url = "https://files.pythonhosted.org/packages/34/37/db94d490b8691236d356bc249c08819cbcef9273a1a30acf1254ff9ce157/xxhash-3.6.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:339f518c3c7a850dd033ab416ea25a692759dc7478a71131fe8869010d2b75e4", size = 197669, upload-time = "2025-10-02T14:34:03.664Z" }, + { url = "https://files.pythonhosted.org/packages/b7/36/c4f219ef4a17a4f7a64ed3569bc2b5a9c8311abdb22249ac96093625b1a4/xxhash-3.6.0-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:bf48889c9630542d4709192578aebbd836177c9f7a4a2778a7d6340107c65f06", size = 210018, upload-time = "2025-10-02T14:34:05.325Z" }, + { url = "https://files.pythonhosted.org/packages/fd/06/bfac889a374fc2fc439a69223d1750eed2e18a7db8514737ab630534fa08/xxhash-3.6.0-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:5576b002a56207f640636056b4160a378fe36a58db73ae5c27a7ec8db35f71d4", size = 413058, upload-time = "2025-10-02T14:34:06.925Z" }, + { url = "https://files.pythonhosted.org/packages/c9/d1/555d8447e0dd32ad0930a249a522bb2e289f0d08b6b16204cfa42c1f5a0c/xxhash-3.6.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:af1f3278bd02814d6dedc5dec397993b549d6f16c19379721e5a1d31e132c49b", size = 190628, upload-time = "2025-10-02T14:34:08.669Z" }, + { url = "https://files.pythonhosted.org/packages/d1/15/8751330b5186cedc4ed4b597989882ea05e0408b53fa47bcb46a6125bfc6/xxhash-3.6.0-cp310-cp310-win32.whl", hash = "sha256:aed058764db109dc9052720da65fafe84873b05eb8b07e5e653597951af57c3b", size = 30577, upload-time = "2025-10-02T14:34:10.234Z" }, + { url = "https://files.pythonhosted.org/packages/bb/cc/53f87e8b5871a6eb2ff7e89c48c66093bda2be52315a8161ddc54ea550c4/xxhash-3.6.0-cp310-cp310-win_amd64.whl", hash = "sha256:e82da5670f2d0d98950317f82a0e4a0197150ff19a6df2ba40399c2a3b9ae5fb", size = 31487, upload-time = "2025-10-02T14:34:11.618Z" }, + { url = "https://files.pythonhosted.org/packages/9f/00/60f9ea3bb697667a14314d7269956f58bf56bb73864f8f8d52a3c2535e9a/xxhash-3.6.0-cp310-cp310-win_arm64.whl", hash = "sha256:4a082ffff8c6ac07707fb6b671caf7c6e020c75226c561830b73d862060f281d", size = 27863, upload-time = "2025-10-02T14:34:12.619Z" }, + { url = "https://files.pythonhosted.org/packages/17/d4/cc2f0400e9154df4b9964249da78ebd72f318e35ccc425e9f403c392f22a/xxhash-3.6.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:b47bbd8cf2d72797f3c2772eaaac0ded3d3af26481a26d7d7d41dc2d3c46b04a", size = 32844, upload-time = "2025-10-02T14:34:14.037Z" }, + { url = "https://files.pythonhosted.org/packages/5e/ec/1cc11cd13e26ea8bc3cb4af4eaadd8d46d5014aebb67be3f71fb0b68802a/xxhash-3.6.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:2b6821e94346f96db75abaa6e255706fb06ebd530899ed76d32cd99f20dc52fa", size = 30809, upload-time = "2025-10-02T14:34:15.484Z" }, + { url = "https://files.pythonhosted.org/packages/04/5f/19fe357ea348d98ca22f456f75a30ac0916b51c753e1f8b2e0e6fb884cce/xxhash-3.6.0-cp311-cp311-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:d0a9751f71a1a65ce3584e9cae4467651c7e70c9d31017fa57574583a4540248", size = 194665, upload-time = "2025-10-02T14:34:16.541Z" }, + { url = "https://files.pythonhosted.org/packages/90/3b/d1f1a8f5442a5fd8beedae110c5af7604dc37349a8e16519c13c19a9a2de/xxhash-3.6.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8b29ee68625ab37b04c0b40c3fafdf24d2f75ccd778333cfb698f65f6c463f62", size = 213550, upload-time = "2025-10-02T14:34:17.878Z" }, + { url = "https://files.pythonhosted.org/packages/c4/ef/3a9b05eb527457d5db13a135a2ae1a26c80fecd624d20f3e8dcc4cb170f3/xxhash-3.6.0-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:6812c25fe0d6c36a46ccb002f40f27ac903bf18af9f6dd8f9669cb4d176ab18f", size = 212384, upload-time = "2025-10-02T14:34:19.182Z" }, + { url = "https://files.pythonhosted.org/packages/0f/18/ccc194ee698c6c623acbf0f8c2969811a8a4b6185af5e824cd27b9e4fd3e/xxhash-3.6.0-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:4ccbff013972390b51a18ef1255ef5ac125c92dc9143b2d1909f59abc765540e", size = 445749, upload-time = "2025-10-02T14:34:20.659Z" }, + { url = "https://files.pythonhosted.org/packages/a5/86/cf2c0321dc3940a7aa73076f4fd677a0fb3e405cb297ead7d864fd90847e/xxhash-3.6.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:297b7fbf86c82c550e12e8fb71968b3f033d27b874276ba3624ea868c11165a8", size = 193880, upload-time = "2025-10-02T14:34:22.431Z" }, + { url = "https://files.pythonhosted.org/packages/82/fb/96213c8560e6f948a1ecc9a7613f8032b19ee45f747f4fca4eb31bb6d6ed/xxhash-3.6.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:dea26ae1eb293db089798d3973a5fc928a18fdd97cc8801226fae705b02b14b0", size = 210912, upload-time = "2025-10-02T14:34:23.937Z" }, + { url = "https://files.pythonhosted.org/packages/40/aa/4395e669b0606a096d6788f40dbdf2b819d6773aa290c19e6e83cbfc312f/xxhash-3.6.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:7a0b169aafb98f4284f73635a8e93f0735f9cbde17bd5ec332480484241aaa77", size = 198654, upload-time = "2025-10-02T14:34:25.644Z" }, + { url = "https://files.pythonhosted.org/packages/67/74/b044fcd6b3d89e9b1b665924d85d3f400636c23590226feb1eb09e1176ce/xxhash-3.6.0-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:08d45aef063a4531b785cd72de4887766d01dc8f362a515693df349fdb825e0c", size = 210867, upload-time = "2025-10-02T14:34:27.203Z" }, + { url = "https://files.pythonhosted.org/packages/bc/fd/3ce73bf753b08cb19daee1eb14aa0d7fe331f8da9c02dd95316ddfe5275e/xxhash-3.6.0-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:929142361a48ee07f09121fe9e96a84950e8d4df3bb298ca5d88061969f34d7b", size = 414012, upload-time = "2025-10-02T14:34:28.409Z" }, + { url = "https://files.pythonhosted.org/packages/ba/b3/5a4241309217c5c876f156b10778f3ab3af7ba7e3259e6d5f5c7d0129eb2/xxhash-3.6.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:51312c768403d8540487dbbfb557454cfc55589bbde6424456951f7fcd4facb3", size = 191409, upload-time = "2025-10-02T14:34:29.696Z" }, + { url = "https://files.pythonhosted.org/packages/c0/01/99bfbc15fb9abb9a72b088c1d95219fc4782b7d01fc835bd5744d66dd0b8/xxhash-3.6.0-cp311-cp311-win32.whl", hash = "sha256:d1927a69feddc24c987b337ce81ac15c4720955b667fe9b588e02254b80446fd", size = 30574, upload-time = "2025-10-02T14:34:31.028Z" }, + { url = "https://files.pythonhosted.org/packages/65/79/9d24d7f53819fe301b231044ea362ce64e86c74f6e8c8e51320de248b3e5/xxhash-3.6.0-cp311-cp311-win_amd64.whl", hash = "sha256:26734cdc2d4ffe449b41d186bbeac416f704a482ed835d375a5c0cb02bc63fef", size = 31481, upload-time = "2025-10-02T14:34:32.062Z" }, + { url = "https://files.pythonhosted.org/packages/30/4e/15cd0e3e8772071344eab2961ce83f6e485111fed8beb491a3f1ce100270/xxhash-3.6.0-cp311-cp311-win_arm64.whl", hash = "sha256:d72f67ef8bf36e05f5b6c65e8524f265bd61071471cd4cf1d36743ebeeeb06b7", size = 27861, upload-time = "2025-10-02T14:34:33.555Z" }, + { url = "https://files.pythonhosted.org/packages/9a/07/d9412f3d7d462347e4511181dea65e47e0d0e16e26fbee2ea86a2aefb657/xxhash-3.6.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:01362c4331775398e7bb34e3ab403bc9ee9f7c497bc7dee6272114055277dd3c", size = 32744, upload-time = "2025-10-02T14:34:34.622Z" }, + { url = "https://files.pythonhosted.org/packages/79/35/0429ee11d035fc33abe32dca1b2b69e8c18d236547b9a9b72c1929189b9a/xxhash-3.6.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:b7b2df81a23f8cb99656378e72501b2cb41b1827c0f5a86f87d6b06b69f9f204", size = 30816, upload-time = "2025-10-02T14:34:36.043Z" }, + { url = "https://files.pythonhosted.org/packages/b7/f2/57eb99aa0f7d98624c0932c5b9a170e1806406cdbcdb510546634a1359e0/xxhash-3.6.0-cp312-cp312-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:dc94790144e66b14f67b10ac8ed75b39ca47536bf8800eb7c24b50271ea0c490", size = 194035, upload-time = "2025-10-02T14:34:37.354Z" }, + { url = "https://files.pythonhosted.org/packages/4c/ed/6224ba353690d73af7a3f1c7cdb1fc1b002e38f783cb991ae338e1eb3d79/xxhash-3.6.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:93f107c673bccf0d592cdba077dedaf52fe7f42dcd7676eba1f6d6f0c3efffd2", size = 212914, upload-time = "2025-10-02T14:34:38.6Z" }, + { url = "https://files.pythonhosted.org/packages/38/86/fb6b6130d8dd6b8942cc17ab4d90e223653a89aa32ad2776f8af7064ed13/xxhash-3.6.0-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:2aa5ee3444c25b69813663c9f8067dcfaa2e126dc55e8dddf40f4d1c25d7effa", size = 212163, upload-time = "2025-10-02T14:34:39.872Z" }, + { url = "https://files.pythonhosted.org/packages/ee/dc/e84875682b0593e884ad73b2d40767b5790d417bde603cceb6878901d647/xxhash-3.6.0-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:f7f99123f0e1194fa59cc69ad46dbae2e07becec5df50a0509a808f90a0f03f0", size = 445411, upload-time = "2025-10-02T14:34:41.569Z" }, + { url = "https://files.pythonhosted.org/packages/11/4f/426f91b96701ec2f37bb2b8cec664eff4f658a11f3fa9d94f0a887ea6d2b/xxhash-3.6.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:49e03e6fe2cac4a1bc64952dd250cf0dbc5ef4ebb7b8d96bce82e2de163c82a2", size = 193883, upload-time = "2025-10-02T14:34:43.249Z" }, + { url = "https://files.pythonhosted.org/packages/53/5a/ddbb83eee8e28b778eacfc5a85c969673e4023cdeedcfcef61f36731610b/xxhash-3.6.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:bd17fede52a17a4f9a7bc4472a5867cb0b160deeb431795c0e4abe158bc784e9", size = 210392, upload-time = "2025-10-02T14:34:45.042Z" }, + { url = "https://files.pythonhosted.org/packages/1e/c2/ff69efd07c8c074ccdf0a4f36fcdd3d27363665bcdf4ba399abebe643465/xxhash-3.6.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:6fb5f5476bef678f69db04f2bd1efbed3030d2aba305b0fc1773645f187d6a4e", size = 197898, upload-time = "2025-10-02T14:34:46.302Z" }, + { url = "https://files.pythonhosted.org/packages/58/ca/faa05ac19b3b622c7c9317ac3e23954187516298a091eb02c976d0d3dd45/xxhash-3.6.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:843b52f6d88071f87eba1631b684fcb4b2068cd2180a0224122fe4ef011a9374", size = 210655, upload-time = "2025-10-02T14:34:47.571Z" }, + { url = "https://files.pythonhosted.org/packages/d4/7a/06aa7482345480cc0cb597f5c875b11a82c3953f534394f620b0be2f700c/xxhash-3.6.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:7d14a6cfaf03b1b6f5f9790f76880601ccc7896aff7ab9cd8978a939c1eb7e0d", size = 414001, upload-time = "2025-10-02T14:34:49.273Z" }, + { url = "https://files.pythonhosted.org/packages/23/07/63ffb386cd47029aa2916b3d2f454e6cc5b9f5c5ada3790377d5430084e7/xxhash-3.6.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:418daf3db71e1413cfe211c2f9a528456936645c17f46b5204705581a45390ae", size = 191431, upload-time = "2025-10-02T14:34:50.798Z" }, + { url = "https://files.pythonhosted.org/packages/0f/93/14fde614cadb4ddf5e7cebf8918b7e8fac5ae7861c1875964f17e678205c/xxhash-3.6.0-cp312-cp312-win32.whl", hash = "sha256:50fc255f39428a27299c20e280d6193d8b63b8ef8028995323bf834a026b4fbb", size = 30617, upload-time = "2025-10-02T14:34:51.954Z" }, + { url = "https://files.pythonhosted.org/packages/13/5d/0d125536cbe7565a83d06e43783389ecae0c0f2ed037b48ede185de477c0/xxhash-3.6.0-cp312-cp312-win_amd64.whl", hash = "sha256:c0f2ab8c715630565ab8991b536ecded9416d615538be8ecddce43ccf26cbc7c", size = 31534, upload-time = "2025-10-02T14:34:53.276Z" }, + { url = "https://files.pythonhosted.org/packages/54/85/6ec269b0952ec7e36ba019125982cf11d91256a778c7c3f98a4c5043d283/xxhash-3.6.0-cp312-cp312-win_arm64.whl", hash = "sha256:eae5c13f3bc455a3bbb68bdc513912dc7356de7e2280363ea235f71f54064829", size = 27876, upload-time = "2025-10-02T14:34:54.371Z" }, + { url = "https://files.pythonhosted.org/packages/33/76/35d05267ac82f53ae9b0e554da7c5e281ee61f3cad44c743f0fcd354f211/xxhash-3.6.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:599e64ba7f67472481ceb6ee80fa3bd828fd61ba59fb11475572cc5ee52b89ec", size = 32738, upload-time = "2025-10-02T14:34:55.839Z" }, + { url = "https://files.pythonhosted.org/packages/31/a8/3fbce1cd96534a95e35d5120637bf29b0d7f5d8fa2f6374e31b4156dd419/xxhash-3.6.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:7d8b8aaa30fca4f16f0c84a5c8d7ddee0e25250ec2796c973775373257dde8f1", size = 30821, upload-time = "2025-10-02T14:34:57.219Z" }, + { url = "https://files.pythonhosted.org/packages/0c/ea/d387530ca7ecfa183cb358027f1833297c6ac6098223fd14f9782cd0015c/xxhash-3.6.0-cp313-cp313-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:d597acf8506d6e7101a4a44a5e428977a51c0fadbbfd3c39650cca9253f6e5a6", size = 194127, upload-time = "2025-10-02T14:34:59.21Z" }, + { url = "https://files.pythonhosted.org/packages/ba/0c/71435dcb99874b09a43b8d7c54071e600a7481e42b3e3ce1eb5226a5711a/xxhash-3.6.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:858dc935963a33bc33490128edc1c12b0c14d9c7ebaa4e387a7869ecc4f3e263", size = 212975, upload-time = "2025-10-02T14:35:00.816Z" }, + { url = "https://files.pythonhosted.org/packages/84/7a/c2b3d071e4bb4a90b7057228a99b10d51744878f4a8a6dd643c8bd897620/xxhash-3.6.0-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:ba284920194615cb8edf73bf52236ce2e1664ccd4a38fdb543506413529cc546", size = 212241, upload-time = "2025-10-02T14:35:02.207Z" }, + { url = "https://files.pythonhosted.org/packages/81/5f/640b6eac0128e215f177df99eadcd0f1b7c42c274ab6a394a05059694c5a/xxhash-3.6.0-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:4b54219177f6c6674d5378bd862c6aedf64725f70dd29c472eaae154df1a2e89", size = 445471, upload-time = "2025-10-02T14:35:03.61Z" }, + { url = "https://files.pythonhosted.org/packages/5e/1e/3c3d3ef071b051cc3abbe3721ffb8365033a172613c04af2da89d5548a87/xxhash-3.6.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:42c36dd7dbad2f5238950c377fcbf6811b1cdb1c444fab447960030cea60504d", size = 193936, upload-time = "2025-10-02T14:35:05.013Z" }, + { url = "https://files.pythonhosted.org/packages/2c/bd/4a5f68381939219abfe1c22a9e3a5854a4f6f6f3c4983a87d255f21f2e5d/xxhash-3.6.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:f22927652cba98c44639ffdc7aaf35828dccf679b10b31c4ad72a5b530a18eb7", size = 210440, upload-time = "2025-10-02T14:35:06.239Z" }, + { url = "https://files.pythonhosted.org/packages/eb/37/b80fe3d5cfb9faff01a02121a0f4d565eb7237e9e5fc66e73017e74dcd36/xxhash-3.6.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:b45fad44d9c5c119e9c6fbf2e1c656a46dc68e280275007bbfd3d572b21426db", size = 197990, upload-time = "2025-10-02T14:35:07.735Z" }, + { url = "https://files.pythonhosted.org/packages/d7/fd/2c0a00c97b9e18f72e1f240ad4e8f8a90fd9d408289ba9c7c495ed7dc05c/xxhash-3.6.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:6f2580ffab1a8b68ef2b901cde7e55fa8da5e4be0977c68f78fc80f3c143de42", size = 210689, upload-time = "2025-10-02T14:35:09.438Z" }, + { url = "https://files.pythonhosted.org/packages/93/86/5dd8076a926b9a95db3206aba20d89a7fc14dd5aac16e5c4de4b56033140/xxhash-3.6.0-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:40c391dd3cd041ebc3ffe6f2c862f402e306eb571422e0aa918d8070ba31da11", size = 414068, upload-time = "2025-10-02T14:35:11.162Z" }, + { url = "https://files.pythonhosted.org/packages/af/3c/0bb129170ee8f3650f08e993baee550a09593462a5cddd8e44d0011102b1/xxhash-3.6.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:f205badabde7aafd1a31e8ca2a3e5a763107a71c397c4481d6a804eb5063d8bd", size = 191495, upload-time = "2025-10-02T14:35:12.971Z" }, + { url = "https://files.pythonhosted.org/packages/e9/3a/6797e0114c21d1725e2577508e24006fd7ff1d8c0c502d3b52e45c1771d8/xxhash-3.6.0-cp313-cp313-win32.whl", hash = "sha256:2577b276e060b73b73a53042ea5bd5203d3e6347ce0d09f98500f418a9fcf799", size = 30620, upload-time = "2025-10-02T14:35:14.129Z" }, + { url = "https://files.pythonhosted.org/packages/86/15/9bc32671e9a38b413a76d24722a2bf8784a132c043063a8f5152d390b0f9/xxhash-3.6.0-cp313-cp313-win_amd64.whl", hash = "sha256:757320d45d2fbcce8f30c42a6b2f47862967aea7bf458b9625b4bbe7ee390392", size = 31542, upload-time = "2025-10-02T14:35:15.21Z" }, + { url = "https://files.pythonhosted.org/packages/39/c5/cc01e4f6188656e56112d6a8e0dfe298a16934b8c47a247236549a3f7695/xxhash-3.6.0-cp313-cp313-win_arm64.whl", hash = "sha256:457b8f85dec5825eed7b69c11ae86834a018b8e3df5e77783c999663da2f96d6", size = 27880, upload-time = "2025-10-02T14:35:16.315Z" }, + { url = "https://files.pythonhosted.org/packages/f3/30/25e5321c8732759e930c555176d37e24ab84365482d257c3b16362235212/xxhash-3.6.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:a42e633d75cdad6d625434e3468126c73f13f7584545a9cf34e883aa1710e702", size = 32956, upload-time = "2025-10-02T14:35:17.413Z" }, + { url = "https://files.pythonhosted.org/packages/9f/3c/0573299560d7d9f8ab1838f1efc021a280b5ae5ae2e849034ef3dee18810/xxhash-3.6.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:568a6d743219e717b07b4e03b0a828ce593833e498c3b64752e0f5df6bfe84db", size = 31072, upload-time = "2025-10-02T14:35:18.844Z" }, + { url = "https://files.pythonhosted.org/packages/7a/1c/52d83a06e417cd9d4137722693424885cc9878249beb3a7c829e74bf7ce9/xxhash-3.6.0-cp313-cp313t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:bec91b562d8012dae276af8025a55811b875baace6af510412a5e58e3121bc54", size = 196409, upload-time = "2025-10-02T14:35:20.31Z" }, + { url = "https://files.pythonhosted.org/packages/e3/8e/c6d158d12a79bbd0b878f8355432075fc82759e356ab5a111463422a239b/xxhash-3.6.0-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:78e7f2f4c521c30ad5e786fdd6bae89d47a32672a80195467b5de0480aa97b1f", size = 215736, upload-time = "2025-10-02T14:35:21.616Z" }, + { url = "https://files.pythonhosted.org/packages/bc/68/c4c80614716345d55071a396cf03d06e34b5f4917a467faf43083c995155/xxhash-3.6.0-cp313-cp313t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:3ed0df1b11a79856df5ffcab572cbd6b9627034c1c748c5566fa79df9048a7c5", size = 214833, upload-time = "2025-10-02T14:35:23.32Z" }, + { url = "https://files.pythonhosted.org/packages/7e/e9/ae27c8ffec8b953efa84c7c4a6c6802c263d587b9fc0d6e7cea64e08c3af/xxhash-3.6.0-cp313-cp313t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:0e4edbfc7d420925b0dd5e792478ed393d6e75ff8fc219a6546fb446b6a417b1", size = 448348, upload-time = "2025-10-02T14:35:25.111Z" }, + { url = "https://files.pythonhosted.org/packages/d7/6b/33e21afb1b5b3f46b74b6bd1913639066af218d704cc0941404ca717fc57/xxhash-3.6.0-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:fba27a198363a7ef87f8c0f6b171ec36b674fe9053742c58dd7e3201c1ab30ee", size = 196070, upload-time = "2025-10-02T14:35:26.586Z" }, + { url = "https://files.pythonhosted.org/packages/96/b6/fcabd337bc5fa624e7203aa0fa7d0c49eed22f72e93229431752bddc83d9/xxhash-3.6.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:794fe9145fe60191c6532fa95063765529770edcdd67b3d537793e8004cabbfd", size = 212907, upload-time = "2025-10-02T14:35:28.087Z" }, + { url = "https://files.pythonhosted.org/packages/4b/d3/9ee6160e644d660fcf176c5825e61411c7f62648728f69c79ba237250143/xxhash-3.6.0-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:6105ef7e62b5ac73a837778efc331a591d8442f8ef5c7e102376506cb4ae2729", size = 200839, upload-time = "2025-10-02T14:35:29.857Z" }, + { url = "https://files.pythonhosted.org/packages/0d/98/e8de5baa5109394baf5118f5e72ab21a86387c4f89b0e77ef3e2f6b0327b/xxhash-3.6.0-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:f01375c0e55395b814a679b3eea205db7919ac2af213f4a6682e01220e5fe292", size = 213304, upload-time = "2025-10-02T14:35:31.222Z" }, + { url = "https://files.pythonhosted.org/packages/7b/1d/71056535dec5c3177eeb53e38e3d367dd1d16e024e63b1cee208d572a033/xxhash-3.6.0-cp313-cp313t-musllinux_1_2_s390x.whl", hash = "sha256:d706dca2d24d834a4661619dcacf51a75c16d65985718d6a7d73c1eeeb903ddf", size = 416930, upload-time = "2025-10-02T14:35:32.517Z" }, + { url = "https://files.pythonhosted.org/packages/dc/6c/5cbde9de2cd967c322e651c65c543700b19e7ae3e0aae8ece3469bf9683d/xxhash-3.6.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:5f059d9faeacd49c0215d66f4056e1326c80503f51a1532ca336a385edadd033", size = 193787, upload-time = "2025-10-02T14:35:33.827Z" }, + { url = "https://files.pythonhosted.org/packages/19/fa/0172e350361d61febcea941b0cc541d6e6c8d65d153e85f850a7b256ff8a/xxhash-3.6.0-cp313-cp313t-win32.whl", hash = "sha256:1244460adc3a9be84731d72b8e80625788e5815b68da3da8b83f78115a40a7ec", size = 30916, upload-time = "2025-10-02T14:35:35.107Z" }, + { url = "https://files.pythonhosted.org/packages/ad/e6/e8cf858a2b19d6d45820f072eff1bea413910592ff17157cabc5f1227a16/xxhash-3.6.0-cp313-cp313t-win_amd64.whl", hash = "sha256:b1e420ef35c503869c4064f4a2f2b08ad6431ab7b229a05cce39d74268bca6b8", size = 31799, upload-time = "2025-10-02T14:35:36.165Z" }, + { url = "https://files.pythonhosted.org/packages/56/15/064b197e855bfb7b343210e82490ae672f8bc7cdf3ddb02e92f64304ee8a/xxhash-3.6.0-cp313-cp313t-win_arm64.whl", hash = "sha256:ec44b73a4220623235f67a996c862049f375df3b1052d9899f40a6382c32d746", size = 28044, upload-time = "2025-10-02T14:35:37.195Z" }, + { url = "https://files.pythonhosted.org/packages/7e/5e/0138bc4484ea9b897864d59fce9be9086030825bc778b76cb5a33a906d37/xxhash-3.6.0-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:a40a3d35b204b7cc7643cbcf8c9976d818cb47befcfac8bbefec8038ac363f3e", size = 32754, upload-time = "2025-10-02T14:35:38.245Z" }, + { url = "https://files.pythonhosted.org/packages/18/d7/5dac2eb2ec75fd771957a13e5dda560efb2176d5203f39502a5fc571f899/xxhash-3.6.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:a54844be970d3fc22630b32d515e79a90d0a3ddb2644d8d7402e3c4c8da61405", size = 30846, upload-time = "2025-10-02T14:35:39.6Z" }, + { url = "https://files.pythonhosted.org/packages/fe/71/8bc5be2bb00deb5682e92e8da955ebe5fa982da13a69da5a40a4c8db12fb/xxhash-3.6.0-cp314-cp314-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:016e9190af8f0a4e3741343777710e3d5717427f175adfdc3e72508f59e2a7f3", size = 194343, upload-time = "2025-10-02T14:35:40.69Z" }, + { url = "https://files.pythonhosted.org/packages/e7/3b/52badfb2aecec2c377ddf1ae75f55db3ba2d321c5e164f14461c90837ef3/xxhash-3.6.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4f6f72232f849eb9d0141e2ebe2677ece15adfd0fa599bc058aad83c714bb2c6", size = 213074, upload-time = "2025-10-02T14:35:42.29Z" }, + { url = "https://files.pythonhosted.org/packages/a2/2b/ae46b4e9b92e537fa30d03dbc19cdae57ed407e9c26d163895e968e3de85/xxhash-3.6.0-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:63275a8aba7865e44b1813d2177e0f5ea7eadad3dd063a21f7cf9afdc7054063", size = 212388, upload-time = "2025-10-02T14:35:43.929Z" }, + { url = "https://files.pythonhosted.org/packages/f5/80/49f88d3afc724b4ac7fbd664c8452d6db51b49915be48c6982659e0e7942/xxhash-3.6.0-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:3cd01fa2aa00d8b017c97eb46b9a794fbdca53fc14f845f5a328c71254b0abb7", size = 445614, upload-time = "2025-10-02T14:35:45.216Z" }, + { url = "https://files.pythonhosted.org/packages/ed/ba/603ce3961e339413543d8cd44f21f2c80e2a7c5cfe692a7b1f2cccf58f3c/xxhash-3.6.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0226aa89035b62b6a86d3c68df4d7c1f47a342b8683da2b60cedcddb46c4d95b", size = 194024, upload-time = "2025-10-02T14:35:46.959Z" }, + { url = "https://files.pythonhosted.org/packages/78/d1/8e225ff7113bf81545cfdcd79eef124a7b7064a0bba53605ff39590b95c2/xxhash-3.6.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:c6e193e9f56e4ca4923c61238cdaced324f0feac782544eb4c6d55ad5cc99ddd", size = 210541, upload-time = "2025-10-02T14:35:48.301Z" }, + { url = "https://files.pythonhosted.org/packages/6f/58/0f89d149f0bad89def1a8dd38feb50ccdeb643d9797ec84707091d4cb494/xxhash-3.6.0-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:9176dcaddf4ca963d4deb93866d739a343c01c969231dbe21680e13a5d1a5bf0", size = 198305, upload-time = "2025-10-02T14:35:49.584Z" }, + { url = "https://files.pythonhosted.org/packages/11/38/5eab81580703c4df93feb5f32ff8fa7fe1e2c51c1f183ee4e48d4bb9d3d7/xxhash-3.6.0-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:c1ce4009c97a752e682b897aa99aef84191077a9433eb237774689f14f8ec152", size = 210848, upload-time = "2025-10-02T14:35:50.877Z" }, + { url = "https://files.pythonhosted.org/packages/5e/6b/953dc4b05c3ce678abca756416e4c130d2382f877a9c30a20d08ee6a77c0/xxhash-3.6.0-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:8cb2f4f679b01513b7adbb9b1b2f0f9cdc31b70007eaf9d59d0878809f385b11", size = 414142, upload-time = "2025-10-02T14:35:52.15Z" }, + { url = "https://files.pythonhosted.org/packages/08/a9/238ec0d4e81a10eb5026d4a6972677cbc898ba6c8b9dbaec12ae001b1b35/xxhash-3.6.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:653a91d7c2ab54a92c19ccf43508b6a555440b9be1bc8be553376778be7f20b5", size = 191547, upload-time = "2025-10-02T14:35:53.547Z" }, + { url = "https://files.pythonhosted.org/packages/f1/ee/3cf8589e06c2164ac77c3bf0aa127012801128f1feebf2a079272da5737c/xxhash-3.6.0-cp314-cp314-win32.whl", hash = "sha256:a756fe893389483ee8c394d06b5ab765d96e68fbbfe6fde7aa17e11f5720559f", size = 31214, upload-time = "2025-10-02T14:35:54.746Z" }, + { url = "https://files.pythonhosted.org/packages/02/5d/a19552fbc6ad4cb54ff953c3908bbc095f4a921bc569433d791f755186f1/xxhash-3.6.0-cp314-cp314-win_amd64.whl", hash = "sha256:39be8e4e142550ef69629c9cd71b88c90e9a5db703fecbcf265546d9536ca4ad", size = 32290, upload-time = "2025-10-02T14:35:55.791Z" }, + { url = "https://files.pythonhosted.org/packages/b1/11/dafa0643bc30442c887b55baf8e73353a344ee89c1901b5a5c54a6c17d39/xxhash-3.6.0-cp314-cp314-win_arm64.whl", hash = "sha256:25915e6000338999236f1eb68a02a32c3275ac338628a7eaa5a269c401995679", size = 28795, upload-time = "2025-10-02T14:35:57.162Z" }, + { url = "https://files.pythonhosted.org/packages/2c/db/0e99732ed7f64182aef4a6fb145e1a295558deec2a746265dcdec12d191e/xxhash-3.6.0-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:c5294f596a9017ca5a3e3f8884c00b91ab2ad2933cf288f4923c3fd4346cf3d4", size = 32955, upload-time = "2025-10-02T14:35:58.267Z" }, + { url = "https://files.pythonhosted.org/packages/55/f4/2a7c3c68e564a099becfa44bb3d398810cc0ff6749b0d3cb8ccb93f23c14/xxhash-3.6.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:1cf9dcc4ab9cff01dfbba78544297a3a01dafd60f3bde4e2bfd016cf7e4ddc67", size = 31072, upload-time = "2025-10-02T14:35:59.382Z" }, + { url = "https://files.pythonhosted.org/packages/c6/d9/72a29cddc7250e8a5819dad5d466facb5dc4c802ce120645630149127e73/xxhash-3.6.0-cp314-cp314t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:01262da8798422d0685f7cef03b2bd3f4f46511b02830861df548d7def4402ad", size = 196579, upload-time = "2025-10-02T14:36:00.838Z" }, + { url = "https://files.pythonhosted.org/packages/63/93/b21590e1e381040e2ca305a884d89e1c345b347404f7780f07f2cdd47ef4/xxhash-3.6.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:51a73fb7cb3a3ead9f7a8b583ffd9b8038e277cdb8cb87cf890e88b3456afa0b", size = 215854, upload-time = "2025-10-02T14:36:02.207Z" }, + { url = "https://files.pythonhosted.org/packages/ce/b8/edab8a7d4fa14e924b29be877d54155dcbd8b80be85ea00d2be3413a9ed4/xxhash-3.6.0-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:b9c6df83594f7df8f7f708ce5ebeacfc69f72c9fbaaababf6cf4758eaada0c9b", size = 214965, upload-time = "2025-10-02T14:36:03.507Z" }, + { url = "https://files.pythonhosted.org/packages/27/67/dfa980ac7f0d509d54ea0d5a486d2bb4b80c3f1bb22b66e6a05d3efaf6c0/xxhash-3.6.0-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:627f0af069b0ea56f312fd5189001c24578868643203bca1abbc2c52d3a6f3ca", size = 448484, upload-time = "2025-10-02T14:36:04.828Z" }, + { url = "https://files.pythonhosted.org/packages/8c/63/8ffc2cc97e811c0ca5d00ab36604b3ea6f4254f20b7bc658ca825ce6c954/xxhash-3.6.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:aa912c62f842dfd013c5f21a642c9c10cd9f4c4e943e0af83618b4a404d9091a", size = 196162, upload-time = "2025-10-02T14:36:06.182Z" }, + { url = "https://files.pythonhosted.org/packages/4b/77/07f0e7a3edd11a6097e990f6e5b815b6592459cb16dae990d967693e6ea9/xxhash-3.6.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:b465afd7909db30168ab62afe40b2fcf79eedc0b89a6c0ab3123515dc0df8b99", size = 213007, upload-time = "2025-10-02T14:36:07.733Z" }, + { url = "https://files.pythonhosted.org/packages/ae/d8/bc5fa0d152837117eb0bef6f83f956c509332ce133c91c63ce07ee7c4873/xxhash-3.6.0-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:a881851cf38b0a70e7c4d3ce81fc7afd86fbc2a024f4cfb2a97cf49ce04b75d3", size = 200956, upload-time = "2025-10-02T14:36:09.106Z" }, + { url = "https://files.pythonhosted.org/packages/26/a5/d749334130de9411783873e9b98ecc46688dad5db64ca6e04b02acc8b473/xxhash-3.6.0-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:9b3222c686a919a0f3253cfc12bb118b8b103506612253b5baeaac10d8027cf6", size = 213401, upload-time = "2025-10-02T14:36:10.585Z" }, + { url = "https://files.pythonhosted.org/packages/89/72/abed959c956a4bfc72b58c0384bb7940663c678127538634d896b1195c10/xxhash-3.6.0-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:c5aa639bc113e9286137cec8fadc20e9cd732b2cc385c0b7fa673b84fc1f2a93", size = 417083, upload-time = "2025-10-02T14:36:12.276Z" }, + { url = "https://files.pythonhosted.org/packages/0c/b3/62fd2b586283b7d7d665fb98e266decadf31f058f1cf6c478741f68af0cb/xxhash-3.6.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:5c1343d49ac102799905e115aee590183c3921d475356cb24b4de29a4bc56518", size = 193913, upload-time = "2025-10-02T14:36:14.025Z" }, + { url = "https://files.pythonhosted.org/packages/9a/9a/c19c42c5b3f5a4aad748a6d5b4f23df3bed7ee5445accc65a0fb3ff03953/xxhash-3.6.0-cp314-cp314t-win32.whl", hash = "sha256:5851f033c3030dd95c086b4a36a2683c2ff4a799b23af60977188b057e467119", size = 31586, upload-time = "2025-10-02T14:36:15.603Z" }, + { url = "https://files.pythonhosted.org/packages/03/d6/4cc450345be9924fd5dc8c590ceda1db5b43a0a889587b0ae81a95511360/xxhash-3.6.0-cp314-cp314t-win_amd64.whl", hash = "sha256:0444e7967dac37569052d2409b00a8860c2135cff05502df4da80267d384849f", size = 32526, upload-time = "2025-10-02T14:36:16.708Z" }, + { url = "https://files.pythonhosted.org/packages/0f/c9/7243eb3f9eaabd1a88a5a5acadf06df2d83b100c62684b7425c6a11bcaa8/xxhash-3.6.0-cp314-cp314t-win_arm64.whl", hash = "sha256:bb79b1e63f6fd84ec778a4b1916dfe0a7c3fdb986c06addd5db3a0d413819d95", size = 28898, upload-time = "2025-10-02T14:36:17.843Z" }, + { url = "https://files.pythonhosted.org/packages/93/1e/8aec23647a34a249f62e2398c42955acd9b4c6ed5cf08cbea94dc46f78d2/xxhash-3.6.0-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:0f7b7e2ec26c1666ad5fc9dbfa426a6a3367ceaf79db5dd76264659d509d73b0", size = 30662, upload-time = "2025-10-02T14:37:01.743Z" }, + { url = "https://files.pythonhosted.org/packages/b8/0b/b14510b38ba91caf43006209db846a696ceea6a847a0c9ba0a5b1adc53d6/xxhash-3.6.0-pp311-pypy311_pp73-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:5dc1e14d14fa0f5789ec29a7062004b5933964bb9b02aae6622b8f530dc40296", size = 41056, upload-time = "2025-10-02T14:37:02.879Z" }, + { url = "https://files.pythonhosted.org/packages/50/55/15a7b8a56590e66ccd374bbfa3f9ffc45b810886c8c3b614e3f90bd2367c/xxhash-3.6.0-pp311-pypy311_pp73-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:881b47fc47e051b37d94d13e7455131054b56749b91b508b0907eb07900d1c13", size = 36251, upload-time = "2025-10-02T14:37:04.44Z" }, + { url = "https://files.pythonhosted.org/packages/62/b2/5ac99a041a29e58e95f907876b04f7067a0242cb85b5f39e726153981503/xxhash-3.6.0-pp311-pypy311_pp73-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c6dc31591899f5e5666f04cc2e529e69b4072827085c1ef15294d91a004bc1bd", size = 32481, upload-time = "2025-10-02T14:37:05.869Z" }, + { url = "https://files.pythonhosted.org/packages/7b/d9/8d95e906764a386a3d3b596f3c68bb63687dfca806373509f51ce8eea81f/xxhash-3.6.0-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:15e0dac10eb9309508bfc41f7f9deaa7755c69e35af835db9cb10751adebc35d", size = 31565, upload-time = "2025-10-02T14:37:06.966Z" }, +] + [[package]] name = "yarl" version = "1.23.0" @@ -5799,3 +6047,93 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/ab/fb/5f5e7b40a2f4efd873fe173624795ca47eaa22e29051270c981361b45209/zope_interface-8.2-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:05a0e42d6d830f547e114de2e7cd15750dc6c0c78f8138e6c5035e51ddfff37c", size = 264390, upload-time = "2026-01-09T08:05:42.936Z" }, { url = "https://files.pythonhosted.org/packages/f9/82/3f2bc594370bc3abd58e5f9085d263bf682a222f059ed46275cde0570810/zope_interface-8.2-cp314-cp314-win_amd64.whl", hash = "sha256:561ce42390bee90bae51cf1c012902a8033b2aaefbd0deed81e877562a116d48", size = 212585, upload-time = "2026-01-09T08:05:44.419Z" }, ] + +[[package]] +name = "zstandard" +version = "0.25.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/fd/aa/3e0508d5a5dd96529cdc5a97011299056e14c6505b678fd58938792794b1/zstandard-0.25.0.tar.gz", hash = "sha256:7713e1179d162cf5c7906da876ec2ccb9c3a9dcbdffef0cc7f70c3667a205f0b", size = 711513, upload-time = "2025-09-14T22:15:54.002Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/56/7a/28efd1d371f1acd037ac64ed1c5e2b41514a6cc937dd6ab6a13ab9f0702f/zstandard-0.25.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e59fdc271772f6686e01e1b3b74537259800f57e24280be3f29c8a0deb1904dd", size = 795256, upload-time = "2025-09-14T22:15:56.415Z" }, + { url = "https://files.pythonhosted.org/packages/96/34/ef34ef77f1ee38fc8e4f9775217a613b452916e633c4f1d98f31db52c4a5/zstandard-0.25.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:4d441506e9b372386a5271c64125f72d5df6d2a8e8a2a45a0ae09b03cb781ef7", size = 640565, upload-time = "2025-09-14T22:15:58.177Z" }, + { url = "https://files.pythonhosted.org/packages/9d/1b/4fdb2c12eb58f31f28c4d28e8dc36611dd7205df8452e63f52fb6261d13e/zstandard-0.25.0-cp310-cp310-manylinux2010_i686.manylinux2014_i686.manylinux_2_12_i686.manylinux_2_17_i686.whl", hash = "sha256:ab85470ab54c2cb96e176f40342d9ed41e58ca5733be6a893b730e7af9c40550", size = 5345306, upload-time = "2025-09-14T22:16:00.165Z" }, + { url = "https://files.pythonhosted.org/packages/73/28/a44bdece01bca027b079f0e00be3b6bd89a4df180071da59a3dd7381665b/zstandard-0.25.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:e05ab82ea7753354bb054b92e2f288afb750e6b439ff6ca78af52939ebbc476d", size = 5055561, upload-time = "2025-09-14T22:16:02.22Z" }, + { url = "https://files.pythonhosted.org/packages/e9/74/68341185a4f32b274e0fc3410d5ad0750497e1acc20bd0f5b5f64ce17785/zstandard-0.25.0-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:78228d8a6a1c177a96b94f7e2e8d012c55f9c760761980da16ae7546a15a8e9b", size = 5402214, upload-time = "2025-09-14T22:16:04.109Z" }, + { url = "https://files.pythonhosted.org/packages/8b/67/f92e64e748fd6aaffe01e2b75a083c0c4fd27abe1c8747fee4555fcee7dd/zstandard-0.25.0-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:2b6bd67528ee8b5c5f10255735abc21aa106931f0dbaf297c7be0c886353c3d0", size = 5449703, upload-time = "2025-09-14T22:16:06.312Z" }, + { url = "https://files.pythonhosted.org/packages/fd/e5/6d36f92a197c3c17729a2125e29c169f460538a7d939a27eaaa6dcfcba8e/zstandard-0.25.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:4b6d83057e713ff235a12e73916b6d356e3084fd3d14ced499d84240f3eecee0", size = 5556583, upload-time = "2025-09-14T22:16:08.457Z" }, + { url = "https://files.pythonhosted.org/packages/d7/83/41939e60d8d7ebfe2b747be022d0806953799140a702b90ffe214d557638/zstandard-0.25.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:9174f4ed06f790a6869b41cba05b43eeb9a35f8993c4422ab853b705e8112bbd", size = 5045332, upload-time = "2025-09-14T22:16:10.444Z" }, + { url = "https://files.pythonhosted.org/packages/b3/87/d3ee185e3d1aa0133399893697ae91f221fda79deb61adbe998a7235c43f/zstandard-0.25.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:25f8f3cd45087d089aef5ba3848cd9efe3ad41163d3400862fb42f81a3a46701", size = 5572283, upload-time = "2025-09-14T22:16:12.128Z" }, + { url = "https://files.pythonhosted.org/packages/0a/1d/58635ae6104df96671076ac7d4ae7816838ce7debd94aecf83e30b7121b0/zstandard-0.25.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:3756b3e9da9b83da1796f8809dd57cb024f838b9eeafde28f3cb472012797ac1", size = 4959754, upload-time = "2025-09-14T22:16:14.225Z" }, + { url = "https://files.pythonhosted.org/packages/75/d6/57e9cb0a9983e9a229dd8fd2e6e96593ef2aa82a3907188436f22b111ccd/zstandard-0.25.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:81dad8d145d8fd981b2962b686b2241d3a1ea07733e76a2f15435dfb7fb60150", size = 5266477, upload-time = "2025-09-14T22:16:16.343Z" }, + { url = "https://files.pythonhosted.org/packages/d1/a9/ee891e5edf33a6ebce0a028726f0bbd8567effe20fe3d5808c42323e8542/zstandard-0.25.0-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:a5a419712cf88862a45a23def0ae063686db3d324cec7edbe40509d1a79a0aab", size = 5440914, upload-time = "2025-09-14T22:16:18.453Z" }, + { url = "https://files.pythonhosted.org/packages/58/08/a8522c28c08031a9521f27abc6f78dbdee7312a7463dd2cfc658b813323b/zstandard-0.25.0-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:e7360eae90809efd19b886e59a09dad07da4ca9ba096752e61a2e03c8aca188e", size = 5819847, upload-time = "2025-09-14T22:16:20.559Z" }, + { url = "https://files.pythonhosted.org/packages/6f/11/4c91411805c3f7b6f31c60e78ce347ca48f6f16d552fc659af6ec3b73202/zstandard-0.25.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:75ffc32a569fb049499e63ce68c743155477610532da1eb38e7f24bf7cd29e74", size = 5363131, upload-time = "2025-09-14T22:16:22.206Z" }, + { url = "https://files.pythonhosted.org/packages/ef/d6/8c4bd38a3b24c4c7676a7a3d8de85d6ee7a983602a734b9f9cdefb04a5d6/zstandard-0.25.0-cp310-cp310-win32.whl", hash = "sha256:106281ae350e494f4ac8a80470e66d1fe27e497052c8d9c3b95dc4cf1ade81aa", size = 436469, upload-time = "2025-09-14T22:16:25.002Z" }, + { url = "https://files.pythonhosted.org/packages/93/90/96d50ad417a8ace5f841b3228e93d1bb13e6ad356737f42e2dde30d8bd68/zstandard-0.25.0-cp310-cp310-win_amd64.whl", hash = "sha256:ea9d54cc3d8064260114a0bbf3479fc4a98b21dffc89b3459edd506b69262f6e", size = 506100, upload-time = "2025-09-14T22:16:23.569Z" }, + { url = "https://files.pythonhosted.org/packages/2a/83/c3ca27c363d104980f1c9cee1101cc8ba724ac8c28a033ede6aab89585b1/zstandard-0.25.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:933b65d7680ea337180733cf9e87293cc5500cc0eb3fc8769f4d3c88d724ec5c", size = 795254, upload-time = "2025-09-14T22:16:26.137Z" }, + { url = "https://files.pythonhosted.org/packages/ac/4d/e66465c5411a7cf4866aeadc7d108081d8ceba9bc7abe6b14aa21c671ec3/zstandard-0.25.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:a3f79487c687b1fc69f19e487cd949bf3aae653d181dfb5fde3bf6d18894706f", size = 640559, upload-time = "2025-09-14T22:16:27.973Z" }, + { url = "https://files.pythonhosted.org/packages/12/56/354fe655905f290d3b147b33fe946b0f27e791e4b50a5f004c802cb3eb7b/zstandard-0.25.0-cp311-cp311-manylinux2010_i686.manylinux2014_i686.manylinux_2_12_i686.manylinux_2_17_i686.whl", hash = "sha256:0bbc9a0c65ce0eea3c34a691e3c4b6889f5f3909ba4822ab385fab9057099431", size = 5348020, upload-time = "2025-09-14T22:16:29.523Z" }, + { url = "https://files.pythonhosted.org/packages/3b/13/2b7ed68bd85e69a2069bcc72141d378f22cae5a0f3b353a2c8f50ef30c1b/zstandard-0.25.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:01582723b3ccd6939ab7b3a78622c573799d5d8737b534b86d0e06ac18dbde4a", size = 5058126, upload-time = "2025-09-14T22:16:31.811Z" }, + { url = "https://files.pythonhosted.org/packages/c9/dd/fdaf0674f4b10d92cb120ccff58bbb6626bf8368f00ebfd2a41ba4a0dc99/zstandard-0.25.0-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:5f1ad7bf88535edcf30038f6919abe087f606f62c00a87d7e33e7fc57cb69fcc", size = 5405390, upload-time = "2025-09-14T22:16:33.486Z" }, + { url = "https://files.pythonhosted.org/packages/0f/67/354d1555575bc2490435f90d67ca4dd65238ff2f119f30f72d5cde09c2ad/zstandard-0.25.0-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:06acb75eebeedb77b69048031282737717a63e71e4ae3f77cc0c3b9508320df6", size = 5452914, upload-time = "2025-09-14T22:16:35.277Z" }, + { url = "https://files.pythonhosted.org/packages/bb/1f/e9cfd801a3f9190bf3e759c422bbfd2247db9d7f3d54a56ecde70137791a/zstandard-0.25.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:9300d02ea7c6506f00e627e287e0492a5eb0371ec1670ae852fefffa6164b072", size = 5559635, upload-time = "2025-09-14T22:16:37.141Z" }, + { url = "https://files.pythonhosted.org/packages/21/88/5ba550f797ca953a52d708c8e4f380959e7e3280af029e38fbf47b55916e/zstandard-0.25.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:bfd06b1c5584b657a2892a6014c2f4c20e0db0208c159148fa78c65f7e0b0277", size = 5048277, upload-time = "2025-09-14T22:16:38.807Z" }, + { url = "https://files.pythonhosted.org/packages/46/c0/ca3e533b4fa03112facbe7fbe7779cb1ebec215688e5df576fe5429172e0/zstandard-0.25.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:f373da2c1757bb7f1acaf09369cdc1d51d84131e50d5fa9863982fd626466313", size = 5574377, upload-time = "2025-09-14T22:16:40.523Z" }, + { url = "https://files.pythonhosted.org/packages/12/9b/3fb626390113f272abd0799fd677ea33d5fc3ec185e62e6be534493c4b60/zstandard-0.25.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:6c0e5a65158a7946e7a7affa6418878ef97ab66636f13353b8502d7ea03c8097", size = 4961493, upload-time = "2025-09-14T22:16:43.3Z" }, + { url = "https://files.pythonhosted.org/packages/cb/d3/23094a6b6a4b1343b27ae68249daa17ae0651fcfec9ed4de09d14b940285/zstandard-0.25.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:c8e167d5adf59476fa3e37bee730890e389410c354771a62e3c076c86f9f7778", size = 5269018, upload-time = "2025-09-14T22:16:45.292Z" }, + { url = "https://files.pythonhosted.org/packages/8c/a7/bb5a0c1c0f3f4b5e9d5b55198e39de91e04ba7c205cc46fcb0f95f0383c1/zstandard-0.25.0-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:98750a309eb2f020da61e727de7d7ba3c57c97cf6213f6f6277bb7fb42a8e065", size = 5443672, upload-time = "2025-09-14T22:16:47.076Z" }, + { url = "https://files.pythonhosted.org/packages/27/22/503347aa08d073993f25109c36c8d9f029c7d5949198050962cb568dfa5e/zstandard-0.25.0-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:22a086cff1b6ceca18a8dd6096ec631e430e93a8e70a9ca5efa7561a00f826fa", size = 5822753, upload-time = "2025-09-14T22:16:49.316Z" }, + { url = "https://files.pythonhosted.org/packages/e2/be/94267dc6ee64f0f8ba2b2ae7c7a2df934a816baaa7291db9e1aa77394c3c/zstandard-0.25.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:72d35d7aa0bba323965da807a462b0966c91608ef3a48ba761678cb20ce5d8b7", size = 5366047, upload-time = "2025-09-14T22:16:51.328Z" }, + { url = "https://files.pythonhosted.org/packages/7b/a3/732893eab0a3a7aecff8b99052fecf9f605cf0fb5fb6d0290e36beee47a4/zstandard-0.25.0-cp311-cp311-win32.whl", hash = "sha256:f5aeea11ded7320a84dcdd62a3d95b5186834224a9e55b92ccae35d21a8b63d4", size = 436484, upload-time = "2025-09-14T22:16:55.005Z" }, + { url = "https://files.pythonhosted.org/packages/43/a3/c6155f5c1cce691cb80dfd38627046e50af3ee9ddc5d0b45b9b063bfb8c9/zstandard-0.25.0-cp311-cp311-win_amd64.whl", hash = "sha256:daab68faadb847063d0c56f361a289c4f268706b598afbf9ad113cbe5c38b6b2", size = 506183, upload-time = "2025-09-14T22:16:52.753Z" }, + { url = "https://files.pythonhosted.org/packages/8c/3e/8945ab86a0820cc0e0cdbf38086a92868a9172020fdab8a03ac19662b0e5/zstandard-0.25.0-cp311-cp311-win_arm64.whl", hash = "sha256:22a06c5df3751bb7dc67406f5374734ccee8ed37fc5981bf1ad7041831fa1137", size = 462533, upload-time = "2025-09-14T22:16:53.878Z" }, + { url = "https://files.pythonhosted.org/packages/82/fc/f26eb6ef91ae723a03e16eddb198abcfce2bc5a42e224d44cc8b6765e57e/zstandard-0.25.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:7b3c3a3ab9daa3eed242d6ecceead93aebbb8f5f84318d82cee643e019c4b73b", size = 795738, upload-time = "2025-09-14T22:16:56.237Z" }, + { url = "https://files.pythonhosted.org/packages/aa/1c/d920d64b22f8dd028a8b90e2d756e431a5d86194caa78e3819c7bf53b4b3/zstandard-0.25.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:913cbd31a400febff93b564a23e17c3ed2d56c064006f54efec210d586171c00", size = 640436, upload-time = "2025-09-14T22:16:57.774Z" }, + { url = "https://files.pythonhosted.org/packages/53/6c/288c3f0bd9fcfe9ca41e2c2fbfd17b2097f6af57b62a81161941f09afa76/zstandard-0.25.0-cp312-cp312-manylinux2010_i686.manylinux2014_i686.manylinux_2_12_i686.manylinux_2_17_i686.whl", hash = "sha256:011d388c76b11a0c165374ce660ce2c8efa8e5d87f34996aa80f9c0816698b64", size = 5343019, upload-time = "2025-09-14T22:16:59.302Z" }, + { url = "https://files.pythonhosted.org/packages/1e/15/efef5a2f204a64bdb5571e6161d49f7ef0fffdbca953a615efbec045f60f/zstandard-0.25.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:6dffecc361d079bb48d7caef5d673c88c8988d3d33fb74ab95b7ee6da42652ea", size = 5063012, upload-time = "2025-09-14T22:17:01.156Z" }, + { url = "https://files.pythonhosted.org/packages/b7/37/a6ce629ffdb43959e92e87ebdaeebb5ac81c944b6a75c9c47e300f85abdf/zstandard-0.25.0-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:7149623bba7fdf7e7f24312953bcf73cae103db8cae49f8154dd1eadc8a29ecb", size = 5394148, upload-time = "2025-09-14T22:17:03.091Z" }, + { url = "https://files.pythonhosted.org/packages/e3/79/2bf870b3abeb5c070fe2d670a5a8d1057a8270f125ef7676d29ea900f496/zstandard-0.25.0-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:6a573a35693e03cf1d67799fd01b50ff578515a8aeadd4595d2a7fa9f3ec002a", size = 5451652, upload-time = "2025-09-14T22:17:04.979Z" }, + { url = "https://files.pythonhosted.org/packages/53/60/7be26e610767316c028a2cbedb9a3beabdbe33e2182c373f71a1c0b88f36/zstandard-0.25.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:5a56ba0db2d244117ed744dfa8f6f5b366e14148e00de44723413b2f3938a902", size = 5546993, upload-time = "2025-09-14T22:17:06.781Z" }, + { url = "https://files.pythonhosted.org/packages/85/c7/3483ad9ff0662623f3648479b0380d2de5510abf00990468c286c6b04017/zstandard-0.25.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:10ef2a79ab8e2974e2075fb984e5b9806c64134810fac21576f0668e7ea19f8f", size = 5046806, upload-time = "2025-09-14T22:17:08.415Z" }, + { url = "https://files.pythonhosted.org/packages/08/b3/206883dd25b8d1591a1caa44b54c2aad84badccf2f1de9e2d60a446f9a25/zstandard-0.25.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:aaf21ba8fb76d102b696781bddaa0954b782536446083ae3fdaa6f16b25a1c4b", size = 5576659, upload-time = "2025-09-14T22:17:10.164Z" }, + { url = "https://files.pythonhosted.org/packages/9d/31/76c0779101453e6c117b0ff22565865c54f48f8bd807df2b00c2c404b8e0/zstandard-0.25.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:1869da9571d5e94a85a5e8d57e4e8807b175c9e4a6294e3b66fa4efb074d90f6", size = 4953933, upload-time = "2025-09-14T22:17:11.857Z" }, + { url = "https://files.pythonhosted.org/packages/18/e1/97680c664a1bf9a247a280a053d98e251424af51f1b196c6d52f117c9720/zstandard-0.25.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:809c5bcb2c67cd0ed81e9229d227d4ca28f82d0f778fc5fea624a9def3963f91", size = 5268008, upload-time = "2025-09-14T22:17:13.627Z" }, + { url = "https://files.pythonhosted.org/packages/1e/73/316e4010de585ac798e154e88fd81bb16afc5c5cb1a72eeb16dd37e8024a/zstandard-0.25.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:f27662e4f7dbf9f9c12391cb37b4c4c3cb90ffbd3b1fb9284dadbbb8935fa708", size = 5433517, upload-time = "2025-09-14T22:17:16.103Z" }, + { url = "https://files.pythonhosted.org/packages/5b/60/dd0f8cfa8129c5a0ce3ea6b7f70be5b33d2618013a161e1ff26c2b39787c/zstandard-0.25.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:99c0c846e6e61718715a3c9437ccc625de26593fea60189567f0118dc9db7512", size = 5814292, upload-time = "2025-09-14T22:17:17.827Z" }, + { url = "https://files.pythonhosted.org/packages/fc/5f/75aafd4b9d11b5407b641b8e41a57864097663699f23e9ad4dbb91dc6bfe/zstandard-0.25.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:474d2596a2dbc241a556e965fb76002c1ce655445e4e3bf38e5477d413165ffa", size = 5360237, upload-time = "2025-09-14T22:17:19.954Z" }, + { url = "https://files.pythonhosted.org/packages/ff/8d/0309daffea4fcac7981021dbf21cdb2e3427a9e76bafbcdbdf5392ff99a4/zstandard-0.25.0-cp312-cp312-win32.whl", hash = "sha256:23ebc8f17a03133b4426bcc04aabd68f8236eb78c3760f12783385171b0fd8bd", size = 436922, upload-time = "2025-09-14T22:17:24.398Z" }, + { url = "https://files.pythonhosted.org/packages/79/3b/fa54d9015f945330510cb5d0b0501e8253c127cca7ebe8ba46a965df18c5/zstandard-0.25.0-cp312-cp312-win_amd64.whl", hash = "sha256:ffef5a74088f1e09947aecf91011136665152e0b4b359c42be3373897fb39b01", size = 506276, upload-time = "2025-09-14T22:17:21.429Z" }, + { url = "https://files.pythonhosted.org/packages/ea/6b/8b51697e5319b1f9ac71087b0af9a40d8a6288ff8025c36486e0c12abcc4/zstandard-0.25.0-cp312-cp312-win_arm64.whl", hash = "sha256:181eb40e0b6a29b3cd2849f825e0fa34397f649170673d385f3598ae17cca2e9", size = 462679, upload-time = "2025-09-14T22:17:23.147Z" }, + { url = "https://files.pythonhosted.org/packages/35/0b/8df9c4ad06af91d39e94fa96cc010a24ac4ef1378d3efab9223cc8593d40/zstandard-0.25.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:ec996f12524f88e151c339688c3897194821d7f03081ab35d31d1e12ec975e94", size = 795735, upload-time = "2025-09-14T22:17:26.042Z" }, + { url = "https://files.pythonhosted.org/packages/3f/06/9ae96a3e5dcfd119377ba33d4c42a7d89da1efabd5cb3e366b156c45ff4d/zstandard-0.25.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:a1a4ae2dec3993a32247995bdfe367fc3266da832d82f8438c8570f989753de1", size = 640440, upload-time = "2025-09-14T22:17:27.366Z" }, + { url = "https://files.pythonhosted.org/packages/d9/14/933d27204c2bd404229c69f445862454dcc101cd69ef8c6068f15aaec12c/zstandard-0.25.0-cp313-cp313-manylinux2010_i686.manylinux2014_i686.manylinux_2_12_i686.manylinux_2_17_i686.whl", hash = "sha256:e96594a5537722fdfb79951672a2a63aec5ebfb823e7560586f7484819f2a08f", size = 5343070, upload-time = "2025-09-14T22:17:28.896Z" }, + { url = "https://files.pythonhosted.org/packages/6d/db/ddb11011826ed7db9d0e485d13df79b58586bfdec56e5c84a928a9a78c1c/zstandard-0.25.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:bfc4e20784722098822e3eee42b8e576b379ed72cca4a7cb856ae733e62192ea", size = 5063001, upload-time = "2025-09-14T22:17:31.044Z" }, + { url = "https://files.pythonhosted.org/packages/db/00/87466ea3f99599d02a5238498b87bf84a6348290c19571051839ca943777/zstandard-0.25.0-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:457ed498fc58cdc12fc48f7950e02740d4f7ae9493dd4ab2168a47c93c31298e", size = 5394120, upload-time = "2025-09-14T22:17:32.711Z" }, + { url = "https://files.pythonhosted.org/packages/2b/95/fc5531d9c618a679a20ff6c29e2b3ef1d1f4ad66c5e161ae6ff847d102a9/zstandard-0.25.0-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:fd7a5004eb1980d3cefe26b2685bcb0b17989901a70a1040d1ac86f1d898c551", size = 5451230, upload-time = "2025-09-14T22:17:34.41Z" }, + { url = "https://files.pythonhosted.org/packages/63/4b/e3678b4e776db00f9f7b2fe58e547e8928ef32727d7a1ff01dea010f3f13/zstandard-0.25.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:8e735494da3db08694d26480f1493ad2cf86e99bdd53e8e9771b2752a5c0246a", size = 5547173, upload-time = "2025-09-14T22:17:36.084Z" }, + { url = "https://files.pythonhosted.org/packages/4e/d5/ba05ed95c6b8ec30bd468dfeab20589f2cf709b5c940483e31d991f2ca58/zstandard-0.25.0-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:3a39c94ad7866160a4a46d772e43311a743c316942037671beb264e395bdd611", size = 5046736, upload-time = "2025-09-14T22:17:37.891Z" }, + { url = "https://files.pythonhosted.org/packages/50/d5/870aa06b3a76c73eced65c044b92286a3c4e00554005ff51962deef28e28/zstandard-0.25.0-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:172de1f06947577d3a3005416977cce6168f2261284c02080e7ad0185faeced3", size = 5576368, upload-time = "2025-09-14T22:17:40.206Z" }, + { url = "https://files.pythonhosted.org/packages/5d/35/398dc2ffc89d304d59bc12f0fdd931b4ce455bddf7038a0a67733a25f550/zstandard-0.25.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:3c83b0188c852a47cd13ef3bf9209fb0a77fa5374958b8c53aaa699398c6bd7b", size = 4954022, upload-time = "2025-09-14T22:17:41.879Z" }, + { url = "https://files.pythonhosted.org/packages/9a/5c/36ba1e5507d56d2213202ec2b05e8541734af5f2ce378c5d1ceaf4d88dc4/zstandard-0.25.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:1673b7199bbe763365b81a4f3252b8e80f44c9e323fc42940dc8843bfeaf9851", size = 5267889, upload-time = "2025-09-14T22:17:43.577Z" }, + { url = "https://files.pythonhosted.org/packages/70/e8/2ec6b6fb7358b2ec0113ae202647ca7c0e9d15b61c005ae5225ad0995df5/zstandard-0.25.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:0be7622c37c183406f3dbf0cba104118eb16a4ea7359eeb5752f0794882fc250", size = 5433952, upload-time = "2025-09-14T22:17:45.271Z" }, + { url = "https://files.pythonhosted.org/packages/7b/01/b5f4d4dbc59ef193e870495c6f1275f5b2928e01ff5a81fecb22a06e22fb/zstandard-0.25.0-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:5f5e4c2a23ca271c218ac025bd7d635597048b366d6f31f420aaeb715239fc98", size = 5814054, upload-time = "2025-09-14T22:17:47.08Z" }, + { url = "https://files.pythonhosted.org/packages/b2/e5/fbd822d5c6f427cf158316d012c5a12f233473c2f9c5fe5ab1ae5d21f3d8/zstandard-0.25.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:4f187a0bb61b35119d1926aee039524d1f93aaf38a9916b8c4b78ac8514a0aaf", size = 5360113, upload-time = "2025-09-14T22:17:48.893Z" }, + { url = "https://files.pythonhosted.org/packages/8e/e0/69a553d2047f9a2c7347caa225bb3a63b6d7704ad74610cb7823baa08ed7/zstandard-0.25.0-cp313-cp313-win32.whl", hash = "sha256:7030defa83eef3e51ff26f0b7bfb229f0204b66fe18e04359ce3474ac33cbc09", size = 436936, upload-time = "2025-09-14T22:17:52.658Z" }, + { url = "https://files.pythonhosted.org/packages/d9/82/b9c06c870f3bd8767c201f1edbdf9e8dc34be5b0fbc5682c4f80fe948475/zstandard-0.25.0-cp313-cp313-win_amd64.whl", hash = "sha256:1f830a0dac88719af0ae43b8b2d6aef487d437036468ef3c2ea59c51f9d55fd5", size = 506232, upload-time = "2025-09-14T22:17:50.402Z" }, + { url = "https://files.pythonhosted.org/packages/d4/57/60c3c01243bb81d381c9916e2a6d9e149ab8627c0c7d7abb2d73384b3c0c/zstandard-0.25.0-cp313-cp313-win_arm64.whl", hash = "sha256:85304a43f4d513f5464ceb938aa02c1e78c2943b29f44a750b48b25ac999a049", size = 462671, upload-time = "2025-09-14T22:17:51.533Z" }, + { url = "https://files.pythonhosted.org/packages/3d/5c/f8923b595b55fe49e30612987ad8bf053aef555c14f05bb659dd5dbe3e8a/zstandard-0.25.0-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:e29f0cf06974c899b2c188ef7f783607dbef36da4c242eb6c82dcd8b512855e3", size = 795887, upload-time = "2025-09-14T22:17:54.198Z" }, + { url = "https://files.pythonhosted.org/packages/8d/09/d0a2a14fc3439c5f874042dca72a79c70a532090b7ba0003be73fee37ae2/zstandard-0.25.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:05df5136bc5a011f33cd25bc9f506e7426c0c9b3f9954f056831ce68f3b6689f", size = 640658, upload-time = "2025-09-14T22:17:55.423Z" }, + { url = "https://files.pythonhosted.org/packages/5d/7c/8b6b71b1ddd517f68ffb55e10834388d4f793c49c6b83effaaa05785b0b4/zstandard-0.25.0-cp314-cp314-manylinux2010_i686.manylinux_2_12_i686.manylinux_2_28_i686.whl", hash = "sha256:f604efd28f239cc21b3adb53eb061e2a205dc164be408e553b41ba2ffe0ca15c", size = 5379849, upload-time = "2025-09-14T22:17:57.372Z" }, + { url = "https://files.pythonhosted.org/packages/a4/86/a48e56320d0a17189ab7a42645387334fba2200e904ee47fc5a26c1fd8ca/zstandard-0.25.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:223415140608d0f0da010499eaa8ccdb9af210a543fac54bce15babbcfc78439", size = 5058095, upload-time = "2025-09-14T22:17:59.498Z" }, + { url = "https://files.pythonhosted.org/packages/f8/ad/eb659984ee2c0a779f9d06dbfe45e2dc39d99ff40a319895df2d3d9a48e5/zstandard-0.25.0-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:2e54296a283f3ab5a26fc9b8b5d4978ea0532f37b231644f367aa588930aa043", size = 5551751, upload-time = "2025-09-14T22:18:01.618Z" }, + { url = "https://files.pythonhosted.org/packages/61/b3/b637faea43677eb7bd42ab204dfb7053bd5c4582bfe6b1baefa80ac0c47b/zstandard-0.25.0-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:ca54090275939dc8ec5dea2d2afb400e0f83444b2fc24e07df7fdef677110859", size = 6364818, upload-time = "2025-09-14T22:18:03.769Z" }, + { url = "https://files.pythonhosted.org/packages/31/dc/cc50210e11e465c975462439a492516a73300ab8caa8f5e0902544fd748b/zstandard-0.25.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e09bb6252b6476d8d56100e8147b803befa9a12cea144bbe629dd508800d1ad0", size = 5560402, upload-time = "2025-09-14T22:18:05.954Z" }, + { url = "https://files.pythonhosted.org/packages/c9/ae/56523ae9c142f0c08efd5e868a6da613ae76614eca1305259c3bf6a0ed43/zstandard-0.25.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:a9ec8c642d1ec73287ae3e726792dd86c96f5681eb8df274a757bf62b750eae7", size = 4955108, upload-time = "2025-09-14T22:18:07.68Z" }, + { url = "https://files.pythonhosted.org/packages/98/cf/c899f2d6df0840d5e384cf4c4121458c72802e8bda19691f3b16619f51e9/zstandard-0.25.0-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:a4089a10e598eae6393756b036e0f419e8c1d60f44a831520f9af41c14216cf2", size = 5269248, upload-time = "2025-09-14T22:18:09.753Z" }, + { url = "https://files.pythonhosted.org/packages/1b/c0/59e912a531d91e1c192d3085fc0f6fb2852753c301a812d856d857ea03c6/zstandard-0.25.0-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:f67e8f1a324a900e75b5e28ffb152bcac9fbed1cc7b43f99cd90f395c4375344", size = 5430330, upload-time = "2025-09-14T22:18:11.966Z" }, + { url = "https://files.pythonhosted.org/packages/a0/1d/7e31db1240de2df22a58e2ea9a93fc6e38cc29353e660c0272b6735d6669/zstandard-0.25.0-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:9654dbc012d8b06fc3d19cc825af3f7bf8ae242226df5f83936cb39f5fdc846c", size = 5811123, upload-time = "2025-09-14T22:18:13.907Z" }, + { url = "https://files.pythonhosted.org/packages/f6/49/fac46df5ad353d50535e118d6983069df68ca5908d4d65b8c466150a4ff1/zstandard-0.25.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:4203ce3b31aec23012d3a4cf4a2ed64d12fea5269c49aed5e4c3611b938e4088", size = 5359591, upload-time = "2025-09-14T22:18:16.465Z" }, + { url = "https://files.pythonhosted.org/packages/c2/38/f249a2050ad1eea0bb364046153942e34abba95dd5520af199aed86fbb49/zstandard-0.25.0-cp314-cp314-win32.whl", hash = "sha256:da469dc041701583e34de852d8634703550348d5822e66a0c827d39b05365b12", size = 444513, upload-time = "2025-09-14T22:18:20.61Z" }, + { url = "https://files.pythonhosted.org/packages/3a/43/241f9615bcf8ba8903b3f0432da069e857fc4fd1783bd26183db53c4804b/zstandard-0.25.0-cp314-cp314-win_amd64.whl", hash = "sha256:c19bcdd826e95671065f8692b5a4aa95c52dc7a02a4c5a0cac46deb879a017a2", size = 516118, upload-time = "2025-09-14T22:18:17.849Z" }, + { url = "https://files.pythonhosted.org/packages/f0/ef/da163ce2450ed4febf6467d77ccb4cd52c4c30ab45624bad26ca0a27260c/zstandard-0.25.0-cp314-cp314-win_arm64.whl", hash = "sha256:d7541afd73985c630bafcd6338d2518ae96060075f9463d7dc14cfb33514383d", size = 476940, upload-time = "2025-09-14T22:18:19.088Z" }, +] From c75b9a0c8d39c91a149f6a0e08f26629a58c182e Mon Sep 17 00:00:00 2001 From: Quinn Klassen Date: Wed, 8 Apr 2026 22:09:55 -0700 Subject: [PATCH 041/226] Add namespace to Nexus operation info (#1416) Add namespace to Nexus operation info --- temporalio/nexus/_operation_context.py | 3 ++ temporalio/worker/_nexus.py | 6 ++-- temporalio/worker/_worker.py | 1 + tests/nexus/test_workflow_caller.py | 41 ++++++++++++++++++++++++++ 4 files changed, 49 insertions(+), 2 deletions(-) diff --git a/temporalio/nexus/_operation_context.py b/temporalio/nexus/_operation_context.py index 66e675d27..ae310f070 100644 --- a/temporalio/nexus/_operation_context.py +++ b/temporalio/nexus/_operation_context.py @@ -79,6 +79,9 @@ class Info: Retrieved inside a Nexus operation handler via :py:func:`info`. """ + namespace: str + """The namespace of the worker handling this Nexus operation.""" + task_queue: str """The task queue of the worker handling this Nexus operation.""" diff --git a/temporalio/worker/_nexus.py b/temporalio/worker/_nexus.py index 278337746..d324a0c4c 100644 --- a/temporalio/worker/_nexus.py +++ b/temporalio/worker/_nexus.py @@ -67,6 +67,7 @@ def __init__( *, bridge_worker: Callable[[], temporalio.bridge.worker.Worker], client: temporalio.client.Client, + namespace: str, task_queue: str, service_handlers: Sequence[Any], data_converter: temporalio.converter.DataConverter, @@ -76,6 +77,7 @@ def __init__( ) -> None: self._bridge_worker = bridge_worker self._client = client + self._namespace = namespace self._task_queue = task_queue self._metric_meter = metric_meter @@ -242,7 +244,7 @@ async def _handle_cancel_operation_task( request_deadline=request_deadline, ) temporalio.nexus._operation_context._TemporalCancelOperationContext( - info=lambda: Info(task_queue=self._task_queue), + info=lambda: Info(namespace=self._namespace, task_queue=self._task_queue), nexus_context=ctx, client=self._client, _runtime_metric_meter=self._metric_meter, @@ -373,7 +375,7 @@ async def _start_operation( temporalio.nexus._operation_context._TemporalStartOperationContext( nexus_context=ctx, client=self._client, - info=lambda: Info(task_queue=self._task_queue), + info=lambda: Info(namespace=self._namespace, task_queue=self._task_queue), _runtime_metric_meter=self._metric_meter, _worker_shutdown_event=self._worker_shutdown_event, ).set() diff --git a/temporalio/worker/_worker.py b/temporalio/worker/_worker.py index 332e2ead7..2ad1d42c6 100644 --- a/temporalio/worker/_worker.py +++ b/temporalio/worker/_worker.py @@ -485,6 +485,7 @@ def _init_from_config(self, client: temporalio.client.Client, config: WorkerConf self._nexus_worker = _NexusWorker( bridge_worker=lambda: self._bridge_worker, client=config["client"], # type: ignore[reportTypedDictNotRequiredAccess] + namespace=client_config["namespace"], task_queue=config["task_queue"], # type: ignore[reportTypedDictNotRequiredAccess] service_handlers=nexus_service_handlers, data_converter=client_config["data_converter"], diff --git a/tests/nexus/test_workflow_caller.py b/tests/nexus/test_workflow_caller.py index ca9e2e145..2b9699089 100644 --- a/tests/nexus/test_workflow_caller.py +++ b/tests/nexus/test_workflow_caller.py @@ -696,6 +696,47 @@ async def test_sync_operation_happy_path(client: Client, env: WorkflowEnvironmen assert wf_output.op_output.value == "sync response" +@service_handler +class NexusInfoService: + @sync_operation + async def get_info( + self, _ctx: StartOperationContext, _input: None + ) -> dict[str, str]: + info = nexus.info() + return {"namespace": info.namespace, "task_queue": info.task_queue} + + +@workflow.defn +class NexusInfoCallerWorkflow: + @workflow.run + async def run(self, task_queue: str) -> dict[str, str]: + nexus_client = workflow.create_nexus_client( + service=NexusInfoService, + endpoint=make_nexus_endpoint_name(task_queue), + ) + return await nexus_client.execute_operation(NexusInfoService.get_info, None) + + +async def test_nexus_info_includes_namespace(client: Client, env: WorkflowEnvironment): + task_queue = str(uuid.uuid4()) + async with Worker( + client, + nexus_service_handlers=[NexusInfoService()], + workflows=[NexusInfoCallerWorkflow], + task_queue=task_queue, + ): + endpoint_name = make_nexus_endpoint_name(task_queue) + await env.create_nexus_endpoint(endpoint_name, task_queue) + result = await client.execute_workflow( + NexusInfoCallerWorkflow.run, + task_queue, + id=str(uuid.uuid4()), + task_queue=task_queue, + ) + assert result["namespace"] == client.namespace + assert result["task_queue"] == task_queue + + async def test_workflow_run_operation_happy_path( client: Client, env: WorkflowEnvironment ): From 79a140b0ec4cad90c0579bf38b7d0382dcb39ca5 Mon Sep 17 00:00:00 2001 From: xumaple <45406854+xumaple@users.noreply.github.com> Date: Fri, 10 Apr 2026 12:30:03 -0400 Subject: [PATCH 042/226] Add LiteLlm + TemporalModel integration test (#1431) * Add LiteLlm + TemporalModel integration test and sandbox fix Add litellm and httpx to the GoogleAdkPlugin sandbox passthrough modules. Without this, any LiteLlm-backed model crashes inside the workflow sandbox because litellm transitively imports httpx which fails sandbox restrictions. Add an integration test proving LiteLlm works with TemporalModel through the full Temporal workflow path, using a fake litellm custom provider that requires no API key. Co-Authored-By: Claude Opus 4.6 (1M context) * small refactor * update dependency * Use exact model string in FakeLiteLlm test instead of wildcard regex Co-Authored-By: Claude Opus 4.6 (1M context) --------- Co-authored-by: Claude Opus 4.6 (1M context) --- pyproject.toml | 1 + .../test_google_adk_agents.py | 108 ++++++++++++++++++ uv.lock | 58 +++++----- 3 files changed, 139 insertions(+), 28 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 8e74bd6e1..6ea339047 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -73,6 +73,7 @@ dev = [ "pytest-pretty>=1.3.0", "openai-agents>=0.3,<0.7; python_version >= '3.14'", "openai-agents[litellm]>=0.3,<0.7; python_version < '3.14'", + "litellm>=1.83.0", "openinference-instrumentation-google-adk>=0.1.8", "googleapis-common-protos==1.70.0", "pytest-rerunfailures>=16.1", diff --git a/tests/contrib/google_adk_agents/test_google_adk_agents.py b/tests/contrib/google_adk_agents/test_google_adk_agents.py index d7ccd4699..a02e98b3f 100644 --- a/tests/contrib/google_adk_agents/test_google_adk_agents.py +++ b/tests/contrib/google_adk_agents/test_google_adk_agents.py @@ -855,3 +855,111 @@ async def test_activity_tool_supports_complex_inputs_via_adk(client: Client): ), "annotate_trip": "SFO->LAX:3", } + + +def litellm_agent(model_name: str) -> Agent: + return Agent( + name="litellm_test_agent", + model=TemporalModel(model_name), + ) + + +@workflow.defn +class LiteLlmWorkflow: + @workflow.run + async def run(self, prompt: str, model_name: str) -> Event | None: + agent = litellm_agent(model_name) + + runner = InMemoryRunner( + agent=agent, + app_name="litellm_test_app", + ) + + session = await runner.session_service.create_session( + app_name="litellm_test_app", user_id="test" + ) + + last_event = None + async with Aclosing( + runner.run_async( + user_id="test", + session_id=session.id, + new_message=types.Content(role="user", parts=[types.Part(text=prompt)]), + ) + ) as agen: + async for event in agen: + last_event = event + + return last_event + + +@pytest.mark.asyncio +async def test_litellm_model(client: Client): + """Test that a litellm-backed model works with TemporalModel through a full Temporal workflow.""" + import litellm as litellm_module + from google.adk.models.lite_llm import LiteLlm + from litellm import ModelResponse + from litellm.llms.custom_llm import CustomLLM + + class FakeLiteLlmProvider(CustomLLM): + """A fake litellm provider that returns canned responses locally.""" + + def _make_response(self, model: str) -> ModelResponse: + return ModelResponse( + choices=[ + { + "message": { + "content": "hello from litellm", + "role": "assistant", + }, + "index": 0, + "finish_reason": "stop", + } + ], + model=model, + ) + + def completion(self, *args: Any, **kwargs: Any) -> ModelResponse: + model = args[0] if args else kwargs.get("model", "unknown") + return self._make_response(model) + + async def acompletion(self, *args: Any, **kwargs: Any) -> ModelResponse: + return self.completion(*args, **kwargs) + + class FakeLiteLlm(LiteLlm): + """LiteLlm subclass that supports the fake/test-model name for testing.""" + + @classmethod + def supported_models(cls) -> list[str]: + return ["fake/test-model"] + + # Register our fake provider with litellm + litellm_module.custom_provider_map = [ + {"provider": "fake", "custom_handler": FakeLiteLlmProvider()} + ] + + LLMRegistry.register(FakeLiteLlm) + + new_config = client.config() + new_config["plugins"] = [GoogleAdkPlugin()] + client = Client(**new_config) + + async with Worker( + client, + task_queue="adk-task-queue-litellm", + workflows=[LiteLlmWorkflow], + max_cached_workflows=0, + ): + handle = await client.start_workflow( + LiteLlmWorkflow.run, + args=["Say hello", "fake/test-model"], + id=f"litellm-agent-workflow-{uuid.uuid4()}", + task_queue="adk-task-queue-litellm", + execution_timeout=timedelta(seconds=60), + ) + result = await handle.result() + + assert result is not None + assert result.content is not None + assert result.content.parts is not None + assert result.content.parts[0].text == "hello from litellm" diff --git a/uv.lock b/uv.lock index c45409833..6d824cf92 100644 --- a/uv.lock +++ b/uv.lock @@ -2128,15 +2128,15 @@ name = "huggingface-hub" version = "1.9.1" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "filelock", marker = "python_full_version < '3.14'" }, - { name = "fsspec", marker = "python_full_version < '3.14'" }, - { name = "hf-xet", marker = "(python_full_version < '3.14' and platform_machine == 'AMD64') or (python_full_version < '3.14' and platform_machine == 'aarch64') or (python_full_version < '3.14' and platform_machine == 'amd64') or (python_full_version < '3.14' and platform_machine == 'arm64') or (python_full_version < '3.14' and platform_machine == 'x86_64')" }, - { name = "httpx", marker = "python_full_version < '3.14'" }, - { name = "packaging", marker = "python_full_version < '3.14'" }, - { name = "pyyaml", marker = "python_full_version < '3.14'" }, - { name = "tqdm", marker = "python_full_version < '3.14'" }, - { name = "typer", marker = "python_full_version < '3.14'" }, - { name = "typing-extensions", marker = "python_full_version < '3.14'" }, + { name = "filelock" }, + { name = "fsspec" }, + { name = "hf-xet", marker = "platform_machine == 'AMD64' or platform_machine == 'aarch64' or platform_machine == 'amd64' or platform_machine == 'arm64' or platform_machine == 'x86_64'" }, + { name = "httpx" }, + { name = "packaging" }, + { name = "pyyaml" }, + { name = "tqdm" }, + { name = "typer" }, + { name = "typing-extensions" }, ] sdist = { url = "https://files.pythonhosted.org/packages/44/40/68d9b286b125d9318ae95c8f8b206e8672e7244b0eea61ebb4a88037638c/huggingface_hub-1.9.1.tar.gz", hash = "sha256:442af372207cc24dcb089caf507fcd7dbc1217c11d6059a06f6b90afe64e8bd2", size = 750355, upload-time = "2026-04-07T13:47:59.167Z" } wheels = [ @@ -2541,18 +2541,18 @@ name = "litellm" version = "1.83.0" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "aiohttp", marker = "python_full_version < '3.14'" }, - { name = "click", marker = "python_full_version < '3.14'" }, - { name = "fastuuid", marker = "python_full_version < '3.14'" }, - { name = "httpx", marker = "python_full_version < '3.14'" }, - { name = "importlib-metadata", marker = "python_full_version < '3.14'" }, - { name = "jinja2", marker = "python_full_version < '3.14'" }, - { name = "jsonschema", marker = "python_full_version < '3.14'" }, - { name = "openai", marker = "python_full_version < '3.14'" }, - { name = "pydantic", marker = "python_full_version < '3.14'" }, - { name = "python-dotenv", marker = "python_full_version < '3.14'" }, - { name = "tiktoken", marker = "python_full_version < '3.14'" }, - { name = "tokenizers", marker = "python_full_version < '3.14'" }, + { name = "aiohttp" }, + { name = "click" }, + { name = "fastuuid" }, + { name = "httpx" }, + { name = "importlib-metadata" }, + { name = "jinja2" }, + { name = "jsonschema" }, + { name = "openai" }, + { name = "pydantic" }, + { name = "python-dotenv" }, + { name = "tiktoken" }, + { name = "tokenizers" }, ] sdist = { url = "https://files.pythonhosted.org/packages/22/92/6ce9737554994ca8e536e5f4f6a87cc7c4774b656c9eb9add071caf7d54b/litellm-1.83.0.tar.gz", hash = "sha256:860bebc76c4bb27b4cf90b4a77acd66dba25aced37e3db98750de8a1766bfb7a", size = 17333062, upload-time = "2026-03-31T05:08:25.331Z" } wheels = [ @@ -5058,6 +5058,7 @@ dev = [ { name = "grpcio-tools" }, { name = "httpx" }, { name = "langsmith" }, + { name = "litellm" }, { name = "maturin" }, { name = "moto", extra = ["s3", "server"] }, { name = "mypy" }, @@ -5119,6 +5120,7 @@ dev = [ { name = "grpcio-tools", specifier = ">=1.48.2,<2" }, { name = "httpx", specifier = ">=0.28.1" }, { name = "langsmith", specifier = ">=0.7.0,<0.8" }, + { name = "litellm", specifier = ">=1.83.0" }, { name = "maturin", specifier = ">=1.8.2" }, { name = "moto", extras = ["s3", "server"], specifier = ">=5" }, { name = "mypy", specifier = "==1.18.2" }, @@ -5161,8 +5163,8 @@ name = "tiktoken" version = "0.12.0" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "regex", marker = "python_full_version < '3.14'" }, - { name = "requests", marker = "python_full_version < '3.14'" }, + { name = "regex" }, + { name = "requests" }, ] sdist = { url = "https://files.pythonhosted.org/packages/7d/ab/4d017d0f76ec3171d469d80fc03dfbb4e48a4bcaddaa831b31d526f05edc/tiktoken-0.12.0.tar.gz", hash = "sha256:b18ba7ee2b093863978fcb14f74b3707cdc8d4d4d3836853ce7ec60772139931", size = 37806, upload-time = "2025-10-06T20:22:45.419Z" } wheels = [ @@ -5222,7 +5224,7 @@ name = "tokenizers" version = "0.22.2" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "huggingface-hub", marker = "python_full_version < '3.14'" }, + { name = "huggingface-hub" }, ] sdist = { url = "https://files.pythonhosted.org/packages/73/6f/f80cfef4a312e1fb34baf7d85c72d4411afde10978d4657f8cdd811d3ccc/tokenizers-0.22.2.tar.gz", hash = "sha256:473b83b915e547aa366d1eee11806deaf419e17be16310ac0a14077f1e28f917", size = 372115, upload-time = "2026-01-05T10:45:15.988Z" } wheels = [ @@ -5365,10 +5367,10 @@ name = "typer" version = "0.24.1" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "annotated-doc", marker = "python_full_version < '3.14'" }, - { name = "click", marker = "python_full_version < '3.14'" }, - { name = "rich", marker = "python_full_version < '3.14'" }, - { name = "shellingham", marker = "python_full_version < '3.14'" }, + { name = "annotated-doc" }, + { name = "click" }, + { name = "rich" }, + { name = "shellingham" }, ] sdist = { url = "https://files.pythonhosted.org/packages/f5/24/cb09efec5cc954f7f9b930bf8279447d24618bb6758d4f6adf2574c41780/typer-0.24.1.tar.gz", hash = "sha256:e39b4732d65fbdcde189ae76cf7cd48aeae72919dea1fdfc16593be016256b45", size = 118613, upload-time = "2026-02-21T16:54:40.609Z" } wheels = [ From 18cebd42a5dc0ecb87f368245f59f20b870fb608 Mon Sep 17 00:00:00 2001 From: xumaple <45406854+xumaple@users.noreply.github.com> Date: Mon, 13 Apr 2026 16:33:13 -0400 Subject: [PATCH 043/226] AI-59: Mark LangSmith plugin as experimental (#1441) Add experimental warnings to the LangSmith plugin, consistent with the pattern used by OpenTelemetry, Google ADK, and AWS S3 contrib plugins. Adds RST `.. warning::` blocks to public API class docstrings and an experimental banner to the README. --- temporalio/contrib/langsmith/README.md | 2 ++ temporalio/contrib/langsmith/__init__.py | 4 ++++ temporalio/contrib/langsmith/_interceptor.py | 4 ++++ temporalio/contrib/langsmith/_plugin.py | 4 ++++ 4 files changed, 14 insertions(+) diff --git a/temporalio/contrib/langsmith/README.md b/temporalio/contrib/langsmith/README.md index 7002f5538..421a76c02 100644 --- a/temporalio/contrib/langsmith/README.md +++ b/temporalio/contrib/langsmith/README.md @@ -1,5 +1,7 @@ # LangSmith Plugin for Temporal Python SDK +> ⚠️ **This package is currently at an experimental release stage.** ⚠️ + This Temporal [Plugin](https://docs.temporal.io/develop/plugins-guide) allows your [LangSmith](https://smith.langchain.com/) traces to work within Temporal Workflows. It propagates trace context across Worker boundaries so that `@traceable` calls, LLM invocations, and Temporal operations show up in a single connected trace, and ensures that replaying does not generate duplicate traces. ## Quick Start diff --git a/temporalio/contrib/langsmith/__init__.py b/temporalio/contrib/langsmith/__init__.py index 465e36c19..c174fe92b 100644 --- a/temporalio/contrib/langsmith/__init__.py +++ b/temporalio/contrib/langsmith/__init__.py @@ -1,5 +1,9 @@ """LangSmith integration for Temporal SDK. +.. warning:: + This package is experimental and may change in future versions. + Use with caution in production environments. + This package provides LangSmith tracing integration for Temporal workflows, activities, and other operations. It includes automatic run creation and context propagation for distributed tracing in LangSmith. diff --git a/temporalio/contrib/langsmith/_interceptor.py b/temporalio/contrib/langsmith/_interceptor.py index 5e020eb4d..6789ddea4 100644 --- a/temporalio/contrib/langsmith/_interceptor.py +++ b/temporalio/contrib/langsmith/_interceptor.py @@ -533,6 +533,10 @@ class LangSmithInterceptor( ): """Interceptor that supports client and worker LangSmith run creation and context propagation. + + .. warning:: + This class is experimental and may change in future versions. + Use with caution in production environments. """ def __init__( diff --git a/temporalio/contrib/langsmith/_plugin.py b/temporalio/contrib/langsmith/_plugin.py index d7a45a130..6e9fba0ee 100644 --- a/temporalio/contrib/langsmith/_plugin.py +++ b/temporalio/contrib/langsmith/_plugin.py @@ -18,6 +18,10 @@ class LangSmithPlugin(SimplePlugin): """LangSmith tracing plugin for Temporal SDK. + .. warning:: + This class is experimental and may change in future versions. + Use with caution in production environments. + Provides automatic LangSmith run creation for workflows, activities, and other Temporal operations with context propagation. """ From 160bfce493f38f8bc072e07617fcf037fe72c033 Mon Sep 17 00:00:00 2001 From: xumaple <45406854+xumaple@users.noreply.github.com> Date: Mon, 13 Apr 2026 17:50:37 -0400 Subject: [PATCH 044/226] AI-61: Strip unset None fields from ADK plugin payloads (#1442) Use ToJsonOptions(exclude_unset=True) in the ADK plugin's payload converter, matching the OpenAI plugin's pattern. This reduces LlmRequest payloads from 4-8KB of mostly nulls to just the fields that were set. --- .../contrib/google_adk_agents/_plugin.py | 16 +++++--- .../test_google_adk_agents.py | 39 +++++++++++++++++++ 2 files changed, 50 insertions(+), 5 deletions(-) diff --git a/temporalio/contrib/google_adk_agents/_plugin.py b/temporalio/contrib/google_adk_agents/_plugin.py index 03cb78998..9be321398 100644 --- a/temporalio/contrib/google_adk_agents/_plugin.py +++ b/temporalio/contrib/google_adk_agents/_plugin.py @@ -10,7 +10,8 @@ from temporalio.contrib.google_adk_agents._mcp import TemporalMcpToolSetProvider from temporalio.contrib.google_adk_agents._model import invoke_model from temporalio.contrib.pydantic import ( - PydanticPayloadConverter as _DefaultPydanticPayloadConverter, + PydanticPayloadConverter, + ToJsonOptions, ) from temporalio.converter import DataConverter, DefaultPayloadConverter from temporalio.plugin import SimplePlugin @@ -111,11 +112,16 @@ def _configure_data_converter( self, converter: DataConverter | None ) -> DataConverter: if converter is None: - return DataConverter( - payload_converter_class=_DefaultPydanticPayloadConverter - ) + return DataConverter(payload_converter_class=_AdkPayloadConverter) elif converter.payload_converter_class is DefaultPayloadConverter: return dataclasses.replace( - converter, payload_converter_class=_DefaultPydanticPayloadConverter + converter, payload_converter_class=_AdkPayloadConverter ) return converter + + +class _AdkPayloadConverter(PydanticPayloadConverter): + """PayloadConverter for Google ADK that strips unset None fields.""" + + def __init__(self) -> None: + super().__init__(ToJsonOptions(exclude_unset=True)) diff --git a/tests/contrib/google_adk_agents/test_google_adk_agents.py b/tests/contrib/google_adk_agents/test_google_adk_agents.py index a02e98b3f..e35d58ea6 100644 --- a/tests/contrib/google_adk_agents/test_google_adk_agents.py +++ b/tests/contrib/google_adk_agents/test_google_adk_agents.py @@ -14,6 +14,7 @@ """Integration tests for ADK Temporal support.""" +import json import logging import os import uuid @@ -963,3 +964,41 @@ def supported_models(cls) -> list[str]: assert result.content is not None assert result.content.parts is not None assert result.content.parts[0].text == "hello from litellm" + + +def test_unset_none_fields_stripped() -> None: + """ADK plugin converter strips unset None fields from Pydantic payloads.""" + plugin = GoogleAdkPlugin() + converter = plugin._configure_data_converter(None) + request = LlmRequest( + model="gemini-2.0-flash", + contents=[Content(parts=[Part(text="hello")])], + ) + payloads = converter.payload_converter.to_payloads([request]) + serialized = json.loads(payloads[0].data) + + assert serialized["model"] == "gemini-2.0-flash" + assert "contents" in serialized + for field in ( + "cache_config", + "cache_metadata", + "cacheable_contents_token_count", + "previous_interaction_id", + ): + assert field not in serialized, f"Unset field {field!r} should be stripped" + + +def test_explicitly_set_none_preserved() -> None: + """Explicitly-set None is preserved (exclude_unset, not exclude_none).""" + plugin = GoogleAdkPlugin() + converter = plugin._configure_data_converter(None) + request = LlmRequest( + model="gemini-2.0-flash", + contents=[Content(parts=[Part(text="hello")])], + cache_config=None, + ) + payloads = converter.payload_converter.to_payloads([request]) + serialized = json.loads(payloads[0].data) + + assert "cache_config" in serialized, "Explicitly-set None should be preserved" + assert serialized["cache_config"] is None From 0916177627cb202e917ee6aa2c05211e07346ba6 Mon Sep 17 00:00:00 2001 From: Justin Anderson <44687433+jmaeagle99@users.noreply.github.com> Date: Mon, 13 Apr 2026 18:33:47 -0700 Subject: [PATCH 045/226] S3 Driver requires hash algorithm and value on claim payloads (#1443) --- temporalio/contrib/aws/s3driver/_driver.py | 37 ++++++++++++--------- tests/contrib/aws/s3driver/test_s3driver.py | 11 +++--- 2 files changed, 27 insertions(+), 21 deletions(-) diff --git a/temporalio/contrib/aws/s3driver/_driver.py b/temporalio/contrib/aws/s3driver/_driver.py index 9e68697ac..f784e67d1 100644 --- a/temporalio/contrib/aws/s3driver/_driver.py +++ b/temporalio/contrib/aws/s3driver/_driver.py @@ -188,23 +188,28 @@ async def _download(claim: StorageDriverClaim) -> Payload: f"S3StorageDriver retrieve failed [bucket={bucket}, key={key}]" ) from e - expected_hash = claim.claim_data.get("hash_value") hash_algorithm = claim.claim_data.get("hash_algorithm") - if expected_hash and hash_algorithm: - if hash_algorithm != "sha256": - raise ValueError( - f"S3StorageDriver unsupported hash algorithm " - f"[bucket={bucket}, key={key}]: " - f"expected sha256, got {hash_algorithm}" - ) - actual_hash = hashlib.sha256(payload_bytes).hexdigest().lower() - if actual_hash != expected_hash: - raise ValueError( - f"S3StorageDriver integrity check failed " - f"[bucket={bucket}, key={key}]: " - f"expected {hash_algorithm}:{expected_hash}, " - f"got {hash_algorithm}:{actual_hash}" - ) + expected_hash = claim.claim_data.get("hash_value") + if not hash_algorithm or not expected_hash: + raise ValueError( + f"S3StorageDriver claim is missing required content hash information " + f"[bucket={bucket}, key={key}]: " + f"claim_data must contain 'hash_algorithm' and 'hash_value'" + ) + if hash_algorithm != "sha256": + raise ValueError( + f"S3StorageDriver unsupported hash algorithm " + f"[bucket={bucket}, key={key}]: " + f"expected sha256, got {hash_algorithm}" + ) + actual_hash = hashlib.sha256(payload_bytes).hexdigest().lower() + if actual_hash != expected_hash: + raise ValueError( + f"S3StorageDriver integrity check failed " + f"[bucket={bucket}, key={key}]: " + f"expected {hash_algorithm}:{expected_hash}, " + f"got {hash_algorithm}:{actual_hash}" + ) payload = Payload() payload.ParseFromString(payload_bytes) diff --git a/tests/contrib/aws/s3driver/test_s3driver.py b/tests/contrib/aws/s3driver/test_s3driver.py index c389fe07c..ac11158fa 100644 --- a/tests/contrib/aws/s3driver/test_s3driver.py +++ b/tests/contrib/aws/s3driver/test_s3driver.py @@ -489,7 +489,7 @@ async def test_retrieve_rejects_unsupported_hash_algorithm( async def test_retrieve_without_hash_in_claim( self, driver_client: S3StorageDriverClient ) -> None: - """Claims without hash fields still retrieve successfully (backward compat).""" + """Claims missing content hash fields raise ValueError on retrieve.""" driver = S3StorageDriver(client=driver_client, bucket=BUCKET) payload = make_payload("no-hash-claim") [claim] = await driver.store(make_store_context(), [payload]) @@ -500,10 +500,11 @@ async def test_retrieve_without_hash_in_claim( "key": claim.claim_data["key"], }, ) - [retrieved] = await driver.retrieve( - StorageDriverRetrieveContext(), [legacy_claim] - ) - assert retrieved == payload + with pytest.raises( + ValueError, + match=r"S3StorageDriver claim is missing required content hash information", + ): + await driver.retrieve(StorageDriverRetrieveContext(), [legacy_claim]) # --------------------------------------------------------------------------- From 40e75f660df41f943bc9367b7cdc7a87f4221d19 Mon Sep 17 00:00:00 2001 From: Quinn Klassen Date: Tue, 14 Apr 2026 10:22:26 -0700 Subject: [PATCH 046/226] Expose Nexus Endpoint in a Nexus Operation Handler (#1437) Expose Nexus Endpoint in a Nexus Operation Handler --- temporalio/bridge/proto/nexus/nexus_pb2.py | 16 +++++++------- temporalio/bridge/proto/nexus/nexus_pb2.pyi | 8 +++++++ temporalio/bridge/sdk-core | 2 +- temporalio/nexus/_operation_context.py | 3 +++ temporalio/worker/_nexus.py | 23 ++++++++++++++++++--- tests/nexus/test_workflow_caller.py | 9 +++++++- 6 files changed, 48 insertions(+), 13 deletions(-) diff --git a/temporalio/bridge/proto/nexus/nexus_pb2.py b/temporalio/bridge/proto/nexus/nexus_pb2.py index 2a1d8b786..d932c3571 100644 --- a/temporalio/bridge/proto/nexus/nexus_pb2.py +++ b/temporalio/bridge/proto/nexus/nexus_pb2.py @@ -34,7 +34,7 @@ ) DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile( - b'\n#temporal/sdk/core/nexus/nexus.proto\x12\rcoresdk.nexus\x1a\x1fgoogle/protobuf/timestamp.proto\x1a$temporal/api/common/v1/message.proto\x1a%temporal/api/failure/v1/message.proto\x1a#temporal/api/nexus/v1/message.proto\x1a\x36temporal/api/workflowservice/v1/request_response.proto\x1a%temporal/sdk/core/common/common.proto"\xf8\x01\n\x14NexusOperationResult\x12\x34\n\tcompleted\x18\x01 \x01(\x0b\x32\x1f.temporal.api.common.v1.PayloadH\x00\x12\x32\n\x06\x66\x61iled\x18\x02 \x01(\x0b\x32 .temporal.api.failure.v1.FailureH\x00\x12\x35\n\tcancelled\x18\x03 \x01(\x0b\x32 .temporal.api.failure.v1.FailureH\x00\x12\x35\n\ttimed_out\x18\x04 \x01(\x0b\x32 .temporal.api.failure.v1.FailureH\x00\x42\x08\n\x06status"\xee\x01\n\x13NexusTaskCompletion\x12\x12\n\ntask_token\x18\x01 \x01(\x0c\x12\x34\n\tcompleted\x18\x02 \x01(\x0b\x32\x1f.temporal.api.nexus.v1.ResponseH\x00\x12\x38\n\x05\x65rror\x18\x03 \x01(\x0b\x32#.temporal.api.nexus.v1.HandlerErrorB\x02\x18\x01H\x00\x12\x14\n\nack_cancel\x18\x04 \x01(\x08H\x00\x12\x33\n\x07\x66\x61ilure\x18\x05 \x01(\x0b\x32 .temporal.api.failure.v1.FailureH\x00\x42\x08\n\x06status"\xd0\x01\n\tNexusTask\x12K\n\x04task\x18\x01 \x01(\x0b\x32;.temporal.api.workflowservice.v1.PollNexusTaskQueueResponseH\x00\x12\x35\n\x0b\x63\x61ncel_task\x18\x02 \x01(\x0b\x32\x1e.coresdk.nexus.CancelNexusTaskH\x00\x12\x34\n\x10request_deadline\x18\x03 \x01(\x0b\x32\x1a.google.protobuf.TimestampB\t\n\x07variant"[\n\x0f\x43\x61ncelNexusTask\x12\x12\n\ntask_token\x18\x01 \x01(\x0c\x12\x34\n\x06reason\x18\x02 \x01(\x0e\x32$.coresdk.nexus.NexusTaskCancelReason*;\n\x15NexusTaskCancelReason\x12\r\n\tTIMED_OUT\x10\x00\x12\x13\n\x0fWORKER_SHUTDOWN\x10\x01*\x7f\n\x1eNexusOperationCancellationType\x12\x1f\n\x1bWAIT_CANCELLATION_COMPLETED\x10\x00\x12\x0b\n\x07\x41\x42\x41NDON\x10\x01\x12\x0e\n\nTRY_CANCEL\x10\x02\x12\x1f\n\x1bWAIT_CANCELLATION_REQUESTED\x10\x03\x42+\xea\x02(Temporalio::Internal::Bridge::Api::Nexusb\x06proto3' + b'\n#temporal/sdk/core/nexus/nexus.proto\x12\rcoresdk.nexus\x1a\x1fgoogle/protobuf/timestamp.proto\x1a$temporal/api/common/v1/message.proto\x1a%temporal/api/failure/v1/message.proto\x1a#temporal/api/nexus/v1/message.proto\x1a\x36temporal/api/workflowservice/v1/request_response.proto\x1a%temporal/sdk/core/common/common.proto"\xf8\x01\n\x14NexusOperationResult\x12\x34\n\tcompleted\x18\x01 \x01(\x0b\x32\x1f.temporal.api.common.v1.PayloadH\x00\x12\x32\n\x06\x66\x61iled\x18\x02 \x01(\x0b\x32 .temporal.api.failure.v1.FailureH\x00\x12\x35\n\tcancelled\x18\x03 \x01(\x0b\x32 .temporal.api.failure.v1.FailureH\x00\x12\x35\n\ttimed_out\x18\x04 \x01(\x0b\x32 .temporal.api.failure.v1.FailureH\x00\x42\x08\n\x06status"\xee\x01\n\x13NexusTaskCompletion\x12\x12\n\ntask_token\x18\x01 \x01(\x0c\x12\x34\n\tcompleted\x18\x02 \x01(\x0b\x32\x1f.temporal.api.nexus.v1.ResponseH\x00\x12\x38\n\x05\x65rror\x18\x03 \x01(\x0b\x32#.temporal.api.nexus.v1.HandlerErrorB\x02\x18\x01H\x00\x12\x14\n\nack_cancel\x18\x04 \x01(\x08H\x00\x12\x33\n\x07\x66\x61ilure\x18\x05 \x01(\x0b\x32 .temporal.api.failure.v1.FailureH\x00\x42\x08\n\x06status"\xe2\x01\n\tNexusTask\x12K\n\x04task\x18\x01 \x01(\x0b\x32;.temporal.api.workflowservice.v1.PollNexusTaskQueueResponseH\x00\x12\x35\n\x0b\x63\x61ncel_task\x18\x02 \x01(\x0b\x32\x1e.coresdk.nexus.CancelNexusTaskH\x00\x12\x34\n\x10request_deadline\x18\x03 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x10\n\x08\x65ndpoint\x18\x04 \x01(\tB\t\n\x07variant"[\n\x0f\x43\x61ncelNexusTask\x12\x12\n\ntask_token\x18\x01 \x01(\x0c\x12\x34\n\x06reason\x18\x02 \x01(\x0e\x32$.coresdk.nexus.NexusTaskCancelReason*;\n\x15NexusTaskCancelReason\x12\r\n\tTIMED_OUT\x10\x00\x12\x13\n\x0fWORKER_SHUTDOWN\x10\x01*\x7f\n\x1eNexusOperationCancellationType\x12\x1f\n\x1bWAIT_CANCELLATION_COMPLETED\x10\x00\x12\x0b\n\x07\x41\x42\x41NDON\x10\x01\x12\x0e\n\nTRY_CANCEL\x10\x02\x12\x1f\n\x1bWAIT_CANCELLATION_REQUESTED\x10\x03\x42+\xea\x02(Temporalio::Internal::Bridge::Api::Nexusb\x06proto3' ) _NEXUSTASKCANCELREASON = DESCRIPTOR.enum_types_by_name["NexusTaskCancelReason"] @@ -108,16 +108,16 @@ ) _NEXUSTASKCOMPLETION.fields_by_name["error"]._options = None _NEXUSTASKCOMPLETION.fields_by_name["error"]._serialized_options = b"\030\001" - _NEXUSTASKCANCELREASON._serialized_start = 1092 - _NEXUSTASKCANCELREASON._serialized_end = 1151 - _NEXUSOPERATIONCANCELLATIONTYPE._serialized_start = 1153 - _NEXUSOPERATIONCANCELLATIONTYPE._serialized_end = 1280 + _NEXUSTASKCANCELREASON._serialized_start = 1110 + _NEXUSTASKCANCELREASON._serialized_end = 1169 + _NEXUSOPERATIONCANCELLATIONTYPE._serialized_start = 1171 + _NEXUSOPERATIONCANCELLATIONTYPE._serialized_end = 1298 _NEXUSOPERATIONRESULT._serialized_start = 297 _NEXUSOPERATIONRESULT._serialized_end = 545 _NEXUSTASKCOMPLETION._serialized_start = 548 _NEXUSTASKCOMPLETION._serialized_end = 786 _NEXUSTASK._serialized_start = 789 - _NEXUSTASK._serialized_end = 997 - _CANCELNEXUSTASK._serialized_start = 999 - _CANCELNEXUSTASK._serialized_end = 1090 + _NEXUSTASK._serialized_end = 1015 + _CANCELNEXUSTASK._serialized_start = 1017 + _CANCELNEXUSTASK._serialized_end = 1108 # @@protoc_insertion_point(module_scope) diff --git a/temporalio/bridge/proto/nexus/nexus_pb2.pyi b/temporalio/bridge/proto/nexus/nexus_pb2.pyi index 94f390595..3cfafac26 100644 --- a/temporalio/bridge/proto/nexus/nexus_pb2.pyi +++ b/temporalio/bridge/proto/nexus/nexus_pb2.pyi @@ -240,6 +240,7 @@ class NexusTask(google.protobuf.message.Message): TASK_FIELD_NUMBER: builtins.int CANCEL_TASK_FIELD_NUMBER: builtins.int REQUEST_DEADLINE_FIELD_NUMBER: builtins.int + ENDPOINT_FIELD_NUMBER: builtins.int @property def task( self, @@ -265,6 +266,10 @@ class NexusTask(google.protobuf.message.Message): Only set when variant is `task` and the header was present with a valid value. Represented as an absolute timestamp. """ + endpoint: builtins.str + """The endpoint this request was addressed to. Extracted from the request for convenient access. + Only set when variant is `task`. + """ def __init__( self, *, @@ -272,6 +277,7 @@ class NexusTask(google.protobuf.message.Message): | None = ..., cancel_task: global___CancelNexusTask | None = ..., request_deadline: google.protobuf.timestamp_pb2.Timestamp | None = ..., + endpoint: builtins.str = ..., ) -> None: ... def HasField( self, @@ -291,6 +297,8 @@ class NexusTask(google.protobuf.message.Message): field_name: typing_extensions.Literal[ "cancel_task", b"cancel_task", + "endpoint", + b"endpoint", "request_deadline", b"request_deadline", "task", diff --git a/temporalio/bridge/sdk-core b/temporalio/bridge/sdk-core index 71a5caa57..b544f95da 160000 --- a/temporalio/bridge/sdk-core +++ b/temporalio/bridge/sdk-core @@ -1 +1 @@ -Subproject commit 71a5caa57118848bd60843dd7fa867ed73704108 +Subproject commit b544f95da46b21e8a642229b8d7f1b017c88e84e diff --git a/temporalio/nexus/_operation_context.py b/temporalio/nexus/_operation_context.py index ae310f070..04462c900 100644 --- a/temporalio/nexus/_operation_context.py +++ b/temporalio/nexus/_operation_context.py @@ -79,6 +79,9 @@ class Info: Retrieved inside a Nexus operation handler via :py:func:`info`. """ + endpoint: str + """The endpoint this Nexus request was addressed to.""" + namespace: str """The namespace of the worker handling this Nexus operation.""" diff --git a/temporalio/worker/_nexus.py b/temporalio/worker/_nexus.py index d324a0c4c..a189278b8 100644 --- a/temporalio/worker/_nexus.py +++ b/temporalio/worker/_nexus.py @@ -140,6 +140,7 @@ async def raise_from_exception_queue() -> NoReturn: headers=dict(task.request.header), task_cancellation=task_cancellation, request_deadline=request_deadline, + endpoint=nexus_task.endpoint, ) ) self._running_tasks[task.task_token] = _RunningNexusTask( @@ -154,6 +155,7 @@ async def raise_from_exception_queue() -> NoReturn: headers=dict(task.request.header), task_cancellation=task_cancellation, request_deadline=request_deadline, + endpoint=nexus_task.endpoint, ) ) self._running_tasks[task.task_token] = _RunningNexusTask( @@ -224,6 +226,7 @@ async def _handle_cancel_operation_task( headers: Mapping[str, str], task_cancellation: nexusrpc.handler.OperationTaskCancellation, request_deadline: datetime | None, + endpoint: str, ) -> None: """Handle a cancel operation task. @@ -244,7 +247,11 @@ async def _handle_cancel_operation_task( request_deadline=request_deadline, ) temporalio.nexus._operation_context._TemporalCancelOperationContext( - info=lambda: Info(namespace=self._namespace, task_queue=self._task_queue), + info=lambda: Info( + endpoint=endpoint, + namespace=self._namespace, + task_queue=self._task_queue, + ), nexus_context=ctx, client=self._client, _runtime_metric_meter=self._metric_meter, @@ -293,6 +300,7 @@ async def _handle_start_operation_task( headers: Mapping[str, str], task_cancellation: nexusrpc.handler.OperationTaskCancellation, request_deadline: datetime | None, + endpoint: str, ) -> None: """Handle a start operation task. @@ -302,7 +310,11 @@ async def _handle_start_operation_task( try: try: start_response = await self._start_operation( - start_request, headers, task_cancellation, request_deadline + start_request, + headers, + task_cancellation, + request_deadline, + endpoint, ) except asyncio.CancelledError: completion = temporalio.bridge.proto.nexus.NexusTaskCompletion( @@ -346,6 +358,7 @@ async def _start_operation( headers: Mapping[str, str], cancellation: nexusrpc.handler.OperationTaskCancellation, request_deadline: datetime | None, + endpoint: str, ) -> temporalio.api.nexus.v1.StartOperationResponse: """Invoke the Nexus handler's start_operation method and construct the StartOperationResponse. @@ -375,7 +388,11 @@ async def _start_operation( temporalio.nexus._operation_context._TemporalStartOperationContext( nexus_context=ctx, client=self._client, - info=lambda: Info(namespace=self._namespace, task_queue=self._task_queue), + info=lambda: Info( + endpoint=endpoint, + namespace=self._namespace, + task_queue=self._task_queue, + ), _runtime_metric_meter=self._metric_meter, _worker_shutdown_event=self._worker_shutdown_event, ).set() diff --git a/tests/nexus/test_workflow_caller.py b/tests/nexus/test_workflow_caller.py index 2b9699089..18cfb40c0 100644 --- a/tests/nexus/test_workflow_caller.py +++ b/tests/nexus/test_workflow_caller.py @@ -703,7 +703,11 @@ async def get_info( self, _ctx: StartOperationContext, _input: None ) -> dict[str, str]: info = nexus.info() - return {"namespace": info.namespace, "task_queue": info.task_queue} + return { + "endpoint": info.endpoint, + "namespace": info.namespace, + "task_queue": info.task_queue, + } @workflow.defn @@ -733,6 +737,9 @@ async def test_nexus_info_includes_namespace(client: Client, env: WorkflowEnviro id=str(uuid.uuid4()), task_queue=task_queue, ) + if not env.supports_time_skipping: + # Time-skipping server doesn't send the endpoint yet. + assert result["endpoint"] == endpoint_name assert result["namespace"] == client.namespace assert result["task_queue"] == task_queue From b93b5c0137bcb6171b332d2bcf2164c9621e2ba5 Mon Sep 17 00:00:00 2001 From: tconley1428 Date: Wed, 15 Apr 2026 12:31:12 -0700 Subject: [PATCH 047/226] Bump version to 1.26.0 (#1453) --- pyproject.toml | 2 +- temporalio/service.py | 2 +- uv.lock | 8 +++++++- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 6ea339047..43444c666 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "temporalio" -version = "1.25.0" +version = "1.26.0" description = "Temporal.io Python SDK" authors = [{ name = "Temporal Technologies Inc", email = "sdk@temporal.io" }] requires-python = ">=3.10" diff --git a/temporalio/service.py b/temporalio/service.py index 776f4332d..cbb3dc9be 100644 --- a/temporalio/service.py +++ b/temporalio/service.py @@ -24,7 +24,7 @@ import temporalio.runtime from temporalio.bridge.client import RPCError as BridgeRPCError -__version__ = "1.25.0" +__version__ = "1.26.0" ServiceRequest = TypeVar("ServiceRequest", bound=google.protobuf.message.Message) ServiceResponse = TypeVar("ServiceResponse", bound=google.protobuf.message.Message) diff --git a/uv.lock b/uv.lock index 6d824cf92..29a90e6f1 100644 --- a/uv.lock +++ b/uv.lock @@ -1812,6 +1812,7 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/38/3f/9859f655d11901e7b2996c6e3d33e0caa9a1d4572c3bc61ed0faa64b2f4c/greenlet-3.3.2-cp310-cp310-macosx_11_0_universal2.whl", hash = "sha256:9bc885b89709d901859cf95179ec9f6bb67a3d2bb1f0e88456461bd4b7f8fd0d", size = 277747, upload-time = "2026-02-20T20:16:21.325Z" }, { url = "https://files.pythonhosted.org/packages/fb/07/cb284a8b5c6498dbd7cba35d31380bb123d7dceaa7907f606c8ff5993cbf/greenlet-3.3.2-cp310-cp310-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b568183cf65b94919be4438dc28416b234b678c608cafac8874dfeeb2a9bbe13", size = 579202, upload-time = "2026-02-20T20:47:28.955Z" }, { url = "https://files.pythonhosted.org/packages/ed/45/67922992b3a152f726163b19f890a85129a992f39607a2a53155de3448b8/greenlet-3.3.2-cp310-cp310-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:527fec58dc9f90efd594b9b700662ed3fb2493c2122067ac9c740d98080a620e", size = 590620, upload-time = "2026-02-20T20:55:55.581Z" }, + { url = "https://files.pythonhosted.org/packages/03/5f/6e2a7d80c353587751ef3d44bb947f0565ec008a2e0927821c007e96d3a7/greenlet-3.3.2-cp310-cp310-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:508c7f01f1791fbc8e011bd508f6794cb95397fdb198a46cb6635eb5b78d85a7", size = 602132, upload-time = "2026-02-20T21:02:43.261Z" }, { url = "https://files.pythonhosted.org/packages/ad/55/9f1ebb5a825215fadcc0f7d5073f6e79e3007e3282b14b22d6aba7ca6cb8/greenlet-3.3.2-cp310-cp310-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ad0c8917dd42a819fe77e6bdfcb84e3379c0de956469301d9fd36427a1ca501f", size = 591729, upload-time = "2026-02-20T20:20:58.395Z" }, { url = "https://files.pythonhosted.org/packages/24/b4/21f5455773d37f94b866eb3cf5caed88d6cea6dd2c6e1f9c34f463cba3ec/greenlet-3.3.2-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:97245cc10e5515dbc8c3104b2928f7f02b6813002770cfaffaf9a6e0fc2b94ef", size = 1551946, upload-time = "2026-02-20T20:49:31.102Z" }, { url = "https://files.pythonhosted.org/packages/00/68/91f061a926abead128fe1a87f0b453ccf07368666bd59ffa46016627a930/greenlet-3.3.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:8c1fdd7d1b309ff0da81d60a9688a8bd044ac4e18b250320a96fc68d31c209ca", size = 1618494, upload-time = "2026-02-20T20:21:06.541Z" }, @@ -1819,6 +1820,7 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/f3/47/16400cb42d18d7a6bb46f0626852c1718612e35dcb0dffa16bbaffdf5dd2/greenlet-3.3.2-cp311-cp311-macosx_11_0_universal2.whl", hash = "sha256:c56692189a7d1c7606cb794be0a8381470d95c57ce5be03fb3d0ef57c7853b86", size = 278890, upload-time = "2026-02-20T20:19:39.263Z" }, { url = "https://files.pythonhosted.org/packages/a3/90/42762b77a5b6aa96cd8c0e80612663d39211e8ae8a6cd47c7f1249a66262/greenlet-3.3.2-cp311-cp311-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1ebd458fa8285960f382841da585e02201b53a5ec2bac6b156fc623b5ce4499f", size = 581120, upload-time = "2026-02-20T20:47:30.161Z" }, { url = "https://files.pythonhosted.org/packages/bf/6f/f3d64f4fa0a9c7b5c5b3c810ff1df614540d5aa7d519261b53fba55d4df9/greenlet-3.3.2-cp311-cp311-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:a443358b33c4ec7b05b79a7c8b466f5d275025e750298be7340f8fc63dff2a55", size = 594363, upload-time = "2026-02-20T20:55:56.965Z" }, + { url = "https://files.pythonhosted.org/packages/9c/8b/1430a04657735a3f23116c2e0d5eb10220928846e4537a938a41b350bed6/greenlet-3.3.2-cp311-cp311-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:4375a58e49522698d3e70cc0b801c19433021b5c37686f7ce9c65b0d5c8677d2", size = 605046, upload-time = "2026-02-20T21:02:45.234Z" }, { url = "https://files.pythonhosted.org/packages/72/83/3e06a52aca8128bdd4dcd67e932b809e76a96ab8c232a8b025b2850264c5/greenlet-3.3.2-cp311-cp311-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8e2cd90d413acbf5e77ae41e5d3c9b3ac1d011a756d7284d7f3f2b806bbd6358", size = 594156, upload-time = "2026-02-20T20:20:59.955Z" }, { url = "https://files.pythonhosted.org/packages/70/79/0de5e62b873e08fe3cef7dbe84e5c4bc0e8ed0c7ff131bccb8405cd107c8/greenlet-3.3.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:442b6057453c8cb29b4fb36a2ac689382fc71112273726e2423f7f17dc73bf99", size = 1554649, upload-time = "2026-02-20T20:49:32.293Z" }, { url = "https://files.pythonhosted.org/packages/5a/00/32d30dee8389dc36d42170a9c66217757289e2afb0de59a3565260f38373/greenlet-3.3.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:45abe8eb6339518180d5a7fa47fa01945414d7cca5ecb745346fc6a87d2750be", size = 1619472, upload-time = "2026-02-20T20:21:07.966Z" }, @@ -1827,6 +1829,7 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/ea/ab/1608e5a7578e62113506740b88066bf09888322a311cff602105e619bd87/greenlet-3.3.2-cp312-cp312-macosx_11_0_universal2.whl", hash = "sha256:ac8d61d4343b799d1e526db579833d72f23759c71e07181c2d2944e429eb09cd", size = 280358, upload-time = "2026-02-20T20:17:43.971Z" }, { url = "https://files.pythonhosted.org/packages/a5/23/0eae412a4ade4e6623ff7626e38998cb9b11e9ff1ebacaa021e4e108ec15/greenlet-3.3.2-cp312-cp312-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3ceec72030dae6ac0c8ed7591b96b70410a8be370b6a477b1dbc072856ad02bd", size = 601217, upload-time = "2026-02-20T20:47:31.462Z" }, { url = "https://files.pythonhosted.org/packages/f8/16/5b1678a9c07098ecb9ab2dd159fafaf12e963293e61ee8d10ecb55273e5e/greenlet-3.3.2-cp312-cp312-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:a2a5be83a45ce6188c045bcc44b0ee037d6a518978de9a5d97438548b953a1ac", size = 611792, upload-time = "2026-02-20T20:55:58.423Z" }, + { url = "https://files.pythonhosted.org/packages/5c/c5/cc09412a29e43406eba18d61c70baa936e299bc27e074e2be3806ed29098/greenlet-3.3.2-cp312-cp312-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:ae9e21c84035c490506c17002f5c8ab25f980205c3e61ddb3a2a2a2e6c411fcb", size = 626250, upload-time = "2026-02-20T21:02:46.596Z" }, { url = "https://files.pythonhosted.org/packages/50/1f/5155f55bd71cabd03765a4aac9ac446be129895271f73872c36ebd4b04b6/greenlet-3.3.2-cp312-cp312-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:43e99d1749147ac21dde49b99c9abffcbc1e2d55c67501465ef0930d6e78e070", size = 613875, upload-time = "2026-02-20T20:21:01.102Z" }, { url = "https://files.pythonhosted.org/packages/fc/dd/845f249c3fcd69e32df80cdab059b4be8b766ef5830a3d0aa9d6cad55beb/greenlet-3.3.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:4c956a19350e2c37f2c48b336a3afb4bff120b36076d9d7fb68cb44e05d95b79", size = 1571467, upload-time = "2026-02-20T20:49:33.495Z" }, { url = "https://files.pythonhosted.org/packages/2a/50/2649fe21fcc2b56659a452868e695634722a6655ba245d9f77f5656010bf/greenlet-3.3.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:6c6f8ba97d17a1e7d664151284cb3315fc5f8353e75221ed4324f84eb162b395", size = 1640001, upload-time = "2026-02-20T20:21:09.154Z" }, @@ -1835,6 +1838,7 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/ac/48/f8b875fa7dea7dd9b33245e37f065af59df6a25af2f9561efa8d822fde51/greenlet-3.3.2-cp313-cp313-macosx_11_0_universal2.whl", hash = "sha256:aa6ac98bdfd716a749b84d4034486863fd81c3abde9aa3cf8eff9127981a4ae4", size = 279120, upload-time = "2026-02-20T20:19:01.9Z" }, { url = "https://files.pythonhosted.org/packages/49/8d/9771d03e7a8b1ee456511961e1b97a6d77ae1dea4a34a5b98eee706689d3/greenlet-3.3.2-cp313-cp313-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ab0c7e7901a00bc0a7284907273dc165b32e0d109a6713babd04471327ff7986", size = 603238, upload-time = "2026-02-20T20:47:32.873Z" }, { url = "https://files.pythonhosted.org/packages/59/0e/4223c2bbb63cd5c97f28ffb2a8aee71bdfb30b323c35d409450f51b91e3e/greenlet-3.3.2-cp313-cp313-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:d248d8c23c67d2291ffd47af766e2a3aa9fa1c6703155c099feb11f526c63a92", size = 614219, upload-time = "2026-02-20T20:55:59.817Z" }, + { url = "https://files.pythonhosted.org/packages/94/2b/4d012a69759ac9d77210b8bfb128bc621125f5b20fc398bce3940d036b1c/greenlet-3.3.2-cp313-cp313-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:ccd21bb86944ca9be6d967cf7691e658e43417782bce90b5d2faeda0ff78a7dd", size = 628268, upload-time = "2026-02-20T21:02:48.024Z" }, { url = "https://files.pythonhosted.org/packages/7a/34/259b28ea7a2a0c904b11cd36c79b8cef8019b26ee5dbe24e73b469dea347/greenlet-3.3.2-cp313-cp313-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b6997d360a4e6a4e936c0f9625b1c20416b8a0ea18a8e19cabbefc712e7397ab", size = 616774, upload-time = "2026-02-20T20:21:02.454Z" }, { url = "https://files.pythonhosted.org/packages/0a/03/996c2d1689d486a6e199cb0f1cf9e4aa940c500e01bdf201299d7d61fa69/greenlet-3.3.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:64970c33a50551c7c50491671265d8954046cb6e8e2999aacdd60e439b70418a", size = 1571277, upload-time = "2026-02-20T20:49:34.795Z" }, { url = "https://files.pythonhosted.org/packages/d9/c4/2570fc07f34a39f2caf0bf9f24b0a1a0a47bc2e8e465b2c2424821389dfc/greenlet-3.3.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:1a9172f5bf6bd88e6ba5a84e0a68afeac9dc7b6b412b245dd64f52d83c81e55b", size = 1640455, upload-time = "2026-02-20T20:21:10.261Z" }, @@ -1843,6 +1847,7 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/3f/ae/8bffcbd373b57a5992cd077cbe8858fff39110480a9d50697091faea6f39/greenlet-3.3.2-cp314-cp314-macosx_11_0_universal2.whl", hash = "sha256:8d1658d7291f9859beed69a776c10822a0a799bc4bfe1bd4272bb60e62507dab", size = 279650, upload-time = "2026-02-20T20:18:00.783Z" }, { url = "https://files.pythonhosted.org/packages/d1/c0/45f93f348fa49abf32ac8439938726c480bd96b2a3c6f4d949ec0124b69f/greenlet-3.3.2-cp314-cp314-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:18cb1b7337bca281915b3c5d5ae19f4e76d35e1df80f4ad3c1a7be91fadf1082", size = 650295, upload-time = "2026-02-20T20:47:34.036Z" }, { url = "https://files.pythonhosted.org/packages/b3/de/dd7589b3f2b8372069ab3e4763ea5329940fc7ad9dcd3e272a37516d7c9b/greenlet-3.3.2-cp314-cp314-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:c2e47408e8ce1c6f1ceea0dffcdf6ebb85cc09e55c7af407c99f1112016e45e9", size = 662163, upload-time = "2026-02-20T20:56:01.295Z" }, + { url = "https://files.pythonhosted.org/packages/cd/ac/85804f74f1ccea31ba518dcc8ee6f14c79f73fe36fa1beba38930806df09/greenlet-3.3.2-cp314-cp314-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:e3cb43ce200f59483eb82949bf1835a99cf43d7571e900d7c8d5c62cdf25d2f9", size = 675371, upload-time = "2026-02-20T21:02:49.664Z" }, { url = "https://files.pythonhosted.org/packages/d2/d8/09bfa816572a4d83bccd6750df1926f79158b1c36c5f73786e26dbe4ee38/greenlet-3.3.2-cp314-cp314-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:63d10328839d1973e5ba35e98cccbca71b232b14051fd957b6f8b6e8e80d0506", size = 664160, upload-time = "2026-02-20T20:21:04.015Z" }, { url = "https://files.pythonhosted.org/packages/48/cf/56832f0c8255d27f6c35d41b5ec91168d74ec721d85f01a12131eec6b93c/greenlet-3.3.2-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:8e4ab3cfb02993c8cc248ea73d7dae6cec0253e9afa311c9b37e603ca9fad2ce", size = 1619181, upload-time = "2026-02-20T20:49:36.052Z" }, { url = "https://files.pythonhosted.org/packages/0a/23/b90b60a4aabb4cec0796e55f25ffbfb579a907c3898cd2905c8918acaa16/greenlet-3.3.2-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:94ad81f0fd3c0c0681a018a976e5c2bd2ca2d9d94895f23e7bb1af4e8af4e2d5", size = 1687713, upload-time = "2026-02-20T20:21:11.684Z" }, @@ -1851,6 +1856,7 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/98/6d/8f2ef704e614bcf58ed43cfb8d87afa1c285e98194ab2cfad351bf04f81e/greenlet-3.3.2-cp314-cp314t-macosx_11_0_universal2.whl", hash = "sha256:e26e72bec7ab387ac80caa7496e0f908ff954f31065b0ffc1f8ecb1338b11b54", size = 286617, upload-time = "2026-02-20T20:19:29.856Z" }, { url = "https://files.pythonhosted.org/packages/5e/0d/93894161d307c6ea237a43988f27eba0947b360b99ac5239ad3fe09f0b47/greenlet-3.3.2-cp314-cp314t-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8b466dff7a4ffda6ca975979bab80bdadde979e29fc947ac3be4451428d8b0e4", size = 655189, upload-time = "2026-02-20T20:47:35.742Z" }, { url = "https://files.pythonhosted.org/packages/f5/2c/d2d506ebd8abcb57386ec4f7ba20f4030cbe56eae541bc6fd6ef399c0b41/greenlet-3.3.2-cp314-cp314t-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:b8bddc5b73c9720bea487b3bffdb1840fe4e3656fba3bd40aa1489e9f37877ff", size = 658225, upload-time = "2026-02-20T20:56:02.527Z" }, + { url = "https://files.pythonhosted.org/packages/d1/67/8197b7e7e602150938049d8e7f30de1660cfb87e4c8ee349b42b67bdb2e1/greenlet-3.3.2-cp314-cp314t-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:59b3e2c40f6706b05a9cd299c836c6aa2378cabe25d021acd80f13abf81181cf", size = 666581, upload-time = "2026-02-20T21:02:51.526Z" }, { url = "https://files.pythonhosted.org/packages/8e/30/3a09155fbf728673a1dea713572d2d31159f824a37c22da82127056c44e4/greenlet-3.3.2-cp314-cp314t-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b26b0f4428b871a751968285a1ac9648944cea09807177ac639b030bddebcea4", size = 657907, upload-time = "2026-02-20T20:21:05.259Z" }, { url = "https://files.pythonhosted.org/packages/f3/fd/d05a4b7acd0154ed758797f0a43b4c0962a843bedfe980115e842c5b2d08/greenlet-3.3.2-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:1fb39a11ee2e4d94be9a76671482be9398560955c9e568550de0224e41104727", size = 1618857, upload-time = "2026-02-20T20:49:37.309Z" }, { url = "https://files.pythonhosted.org/packages/6f/e1/50ee92a5db521de8f35075b5eff060dd43d39ebd46c2181a2042f7070385/greenlet-3.3.2-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:20154044d9085151bc309e7689d6f7ba10027f8f5a8c0676ad398b951913d89e", size = 1680010, upload-time = "2026-02-20T20:21:13.427Z" }, @@ -5007,7 +5013,7 @@ wheels = [ [[package]] name = "temporalio" -version = "1.25.0" +version = "1.26.0" source = { virtual = "." } dependencies = [ { name = "nexus-rpc" }, From 447472e51f8c39c3a4e5cee08c524d72d09a774c Mon Sep 17 00:00:00 2001 From: Jason Steving <32336750+JasonSteving99@users.noreply.github.com> Date: Wed, 15 Apr 2026 16:01:01 -0700 Subject: [PATCH 048/226] Feat/OpenAI agents plugin sandbox support (#1452) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add SandboxAgent support to Temporal OpenAI Agents plugin Enable workflows to use the OpenAI Agents SDK's SandboxAgent by routing all sandbox lifecycle and I/O operations through Temporal activities. The user passes a real sandbox client (e.g. DaytonaSandboxClient) to OpenAIAgentsPlugin(sandbox_client=...) and the plugin handles the rest — no direct imports from the sandbox subpackage are needed. Key changes: Add sandbox/ subpackage with internal modules for: - TemporalSandboxClient: workflow-side client that dispatches create/resume/delete as activities - TemporalSandboxSession: workflow-side session that routes exec, read, write, and other I/O through activities - TemporalSandboxActivities: worker-side activity implementations that delegate to the real BaseSandboxClient/BaseSandboxSession - Pydantic activity arg/result models for serialization Update TemporalOpenAIRunner to detect SandboxAgent in the agent graph and automatically inject TemporalSandboxClient when run_config.sandbox is configured Update OpenAIAgentsPlugin to accept sandbox_client and register sandbox activities on the worker Add tests covering: - SandboxAgent detection in agent graphs (direct, handoff, circular) - Validation errors (missing config, wrong client type) - Activity delegation (each activity correctly calls the real client/session) - Session caching and eviction in TemporalSandboxActivities - End-to-end integration test running sandbox activities through a real Temporal workflow --- pyproject.toml | 6 +- temporalio/contrib/openai_agents/README.md | 126 +++ temporalio/contrib/openai_agents/__init__.py | 4 + .../openai_agents/_invoke_model_activity.py | 58 ++ temporalio/contrib/openai_agents/_mcp.py | 22 +- .../contrib/openai_agents/_openai_runner.py | 60 +- .../openai_agents/_temporal_model_stub.py | 12 + .../openai_agents/_temporal_openai_agents.py | 25 +- .../contrib/openai_agents/sandbox/__init__.py | 1 + .../sandbox/_sandbox_client_provider.py | 245 ++++++ .../sandbox/_temporal_activity_models.py | 218 +++++ .../sandbox/_temporal_sandbox_client.py | 124 +++ .../sandbox/_temporal_sandbox_session.py | 239 ++++++ temporalio/contrib/openai_agents/workflow.py | 35 + tests/contrib/openai_agents/test_openai.py | 5 +- .../openai_agents/test_openai_sandbox.py | 792 ++++++++++++++++++ .../openai_agents/test_openai_tracing.py | 96 ++- uv.lock | 26 +- 18 files changed, 2031 insertions(+), 63 deletions(-) create mode 100644 temporalio/contrib/openai_agents/sandbox/__init__.py create mode 100644 temporalio/contrib/openai_agents/sandbox/_sandbox_client_provider.py create mode 100644 temporalio/contrib/openai_agents/sandbox/_temporal_activity_models.py create mode 100644 temporalio/contrib/openai_agents/sandbox/_temporal_sandbox_client.py create mode 100644 temporalio/contrib/openai_agents/sandbox/_temporal_sandbox_session.py create mode 100644 tests/contrib/openai_agents/test_openai_sandbox.py diff --git a/pyproject.toml b/pyproject.toml index 43444c666..bd2409f6e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -28,7 +28,7 @@ classifiers = [ grpc = ["grpcio>=1.48.2,<2"] opentelemetry = ["opentelemetry-api>=1.11.1,<2", "opentelemetry-sdk>=1.11.1,<2"] pydantic = ["pydantic>=2.0.0,<3"] -openai-agents = ["openai-agents>=0.3,<0.7", "mcp>=1.9.4, <2"] +openai-agents = ["openai-agents>=0.14.0", "mcp>=1.9.4, <2"] google-adk = ["google-adk>=1.27.0,<2"] langsmith = ["langsmith>=0.7.0,<0.8"] lambda-worker-otel = [ @@ -71,8 +71,8 @@ dev = [ "pytest-cov>=6.1.1", "httpx>=0.28.1", "pytest-pretty>=1.3.0", - "openai-agents>=0.3,<0.7; python_version >= '3.14'", - "openai-agents[litellm]>=0.3,<0.7; python_version < '3.14'", + "openai-agents>=0.14.0; python_version >= '3.14'", + "openai-agents[litellm]>=0.14.0; python_version < '3.14'", "litellm>=1.83.0", "openinference-instrumentation-google-adk>=0.1.8", "googleapis-common-protos==1.70.0", diff --git a/temporalio/contrib/openai_agents/README.md b/temporalio/contrib/openai_agents/README.md index 888490379..ae1243dcb 100644 --- a/temporalio/contrib/openai_agents/README.md +++ b/temporalio/contrib/openai_agents/README.md @@ -17,6 +17,7 @@ This document is organized as follows: - **[Background Concepts](#core-concepts).** Background on durable execution and AI agents. - **[Full Example](#full-example)** Running the Hello World Durable Agent example. - **[Tool Calling](#tool-calling).** Calling agent Tools in Temporal. +- **[Sandbox Support](#sandbox-support).** Running sandbox agents in Temporal. - **[Feature Support](#feature-support).** Compatibility matrix. The [samples repository](https://github.com/temporalio/samples-python/tree/main/openai_agents) contains examples including basic usage, common agent patterns, and more complete samples. @@ -450,6 +451,131 @@ To recover from such failures, you need to implement your own application-level For network-accessible MCP servers, you can also use `HostedMCPTool` from the OpenAI Agents SDK, which uses an MCP client hosted by OpenAI. +## Sandbox Support + +⚠️ **Pre-release** - This functionality is subject to change prior to General Availability. + +The sandbox integration lets `SandboxAgent` from the OpenAI Agents SDK execute inside a remote or local sandbox (Daytona, Docker, E2B, local Unix, etc.) while keeping all coordination durable in Temporal. + +Every sandbox operation — creating a session, running commands, reading/writing files, PTY interactions — is dispatched as a Temporal activity. This means sandbox work is fully observable, retryable, and recoverable like any other activity, and sandbox session state is serialized with the workflow so it survives worker restarts. + +### Architecture + +```text +Workflow Code + ↓ +temporal_sandbox_client("daytona") [returns TemporalSandboxClient] + ↓ +SandboxAgent.run(run_config=RunConfig(sandbox=SandboxRunConfig(client=...))) + ↓ +sandbox agent calls session.exec / session.read / session.write / … + ↓ +TemporalSandboxSession routes each call as a Temporal activity +("daytona-sandbox_session_exec", "daytona-sandbox_session_read", …) + ↓ +SandboxClientProvider activities on the worker call the real sandbox client + ↓ +Actual sandbox backend (Daytona, Docker, local, …) +``` + +### Worker Configuration + +Register one or more `SandboxClientProvider` instances with the plugin. Each provider pairs a unique name with a real `BaseSandboxClient` implementation. The plugin automatically registers all required activities on the worker. + +```python +import asyncio +import docker +from temporalio.client import Client +from temporalio.worker import Worker +from temporalio.contrib.openai_agents import OpenAIAgentsPlugin, SandboxClientProvider, ModelActivityParameters +from agents.extensions.sandbox.daytona import DaytonaSandboxClient +from agents.extensions.sandbox.unix_local import UnixLocalSandboxClient + +async def main(): + client = await Client.connect( + "localhost:7233", + plugins=[ + OpenAIAgentsPlugin( + model_params=ModelActivityParameters( + start_to_close_timeout=timedelta(seconds=30) + ), + sandbox_clients=[ + SandboxClientProvider("daytona", DaytonaSandboxClient()), + SandboxClientProvider("local", UnixLocalSandboxClient()), + ], + ), + ], + ) + + worker = Worker( + client, + task_queue="my-task-queue", + workflows=[MyWorkflow], + ) + await worker.run() +``` + +Provider names must be unique. Each name becomes the prefix for that backend's activities, allowing multiple backends to coexist on a single worker. + +### Workflow Usage + +In the workflow, use `temporal_sandbox_client()` to create a reference to a registered backend by name. Pass it to `SandboxRunConfig` inside `RunConfig`: + +```python +from temporalio import workflow +from temporalio.contrib.openai_agents.workflow import temporal_sandbox_client +from agents import Runner +from agents.sandbox import SandboxAgent, SandboxRunConfig +from agents.run import RunConfig + +@workflow.defn +class MyWorkflow: + @workflow.run + async def run(self, prompt: str) -> str: + agent = SandboxAgent( + name="Coding Assistant", + instructions="You are a helpful coding assistant with access to a sandbox.", + ) + + result = await Runner.run( + agent, + prompt, + run_config=RunConfig( + sandbox=SandboxRunConfig( + client=temporal_sandbox_client("daytona"), + options=DaytonaSandboxClientOptions(pause_on_exit=False), + ), + ), + ) + return result.final_output +``` + +The name passed to `temporal_sandbox_client()` must exactly match the name used in `SandboxClientProvider` on the worker. + +### Multiple Backends + +A single workflow can target different backends by name. Register all backends on the worker and reference each by name in the workflow: + +```python +# Run a task on the "daytona" backend +result = await Runner.run( + agent, prompt, + run_config=RunConfig(sandbox=SandboxRunConfig( + client=temporal_sandbox_client("daytona"), + options=DaytonaSandboxClientOptions(pause_on_exit=False), + )), +) + +# Run a different task on the "local" backend +result = await Runner.run( + agent, prompt, + run_config=RunConfig(sandbox=SandboxRunConfig( + client=temporal_sandbox_client("local"), + options=UnixLocalSandboxClientOptions(), + )), +) +``` + ## Feature Support This integration is presently subject to certain limitations. diff --git a/temporalio/contrib/openai_agents/__init__.py b/temporalio/contrib/openai_agents/__init__.py index 6d64b0b07..3976f633c 100644 --- a/temporalio/contrib/openai_agents/__init__.py +++ b/temporalio/contrib/openai_agents/__init__.py @@ -13,6 +13,9 @@ OpenAIAgentsPlugin, OpenAIPayloadConverter, ) +from temporalio.contrib.openai_agents.sandbox._sandbox_client_provider import ( + SandboxClientProvider, +) from temporalio.contrib.openai_agents.workflow import AgentsWorkflowError from . import testing, workflow @@ -22,6 +25,7 @@ "ModelActivityParameters", "OpenAIAgentsPlugin", "OpenAIPayloadConverter", + "SandboxClientProvider", "StatelessMCPServerProvider", "StatefulMCPServerProvider", "testing", diff --git a/temporalio/contrib/openai_agents/_invoke_model_activity.py b/temporalio/contrib/openai_agents/_invoke_model_activity.py index 945a05ec6..cffd8855e 100644 --- a/temporalio/contrib/openai_agents/_invoke_model_activity.py +++ b/temporalio/contrib/openai_agents/_invoke_model_activity.py @@ -27,6 +27,13 @@ UserError, WebSearchTool, ) +from agents.tool import ( + ApplyPatchTool, + LocalShellTool, + ShellTool, + ShellToolEnvironment, + ToolSearchTool, +) from openai import ( APIStatusError, AsyncOpenAI, @@ -73,6 +80,36 @@ class HostedMCPToolInput: tool_config: Mcp +@dataclass +class ShellToolInput: + """Data conversion friendly representation of a ShellTool. Contains only the fields which are needed by the model + execution to determine what tool to call, not the actual tool invocation, which remains in the workflow context. + """ + + name: str = "shell" + environment: ShellToolEnvironment | None = None + + +class _NoopApplyPatchEditor: + """Satisfies the ApplyPatchEditor protocol for tool reconstruction during model calls.""" + + def create_file(self, operation: Any) -> None: # type: ignore[reportUnusedParameter] + return None + + def update_file(self, operation: Any) -> None: # type: ignore[reportUnusedParameter] + return None + + def delete_file(self, operation: Any) -> None: # type: ignore[reportUnusedParameter] + return None + + +@dataclass +class ApplyPatchToolInput: + """Data conversion friendly representation of an ApplyPatchTool.""" + + name: str = "apply_patch" + + ToolInput = ( FunctionToolInput | FileSearchTool @@ -80,6 +117,10 @@ class HostedMCPToolInput: | ImageGenerationTool | CodeInterpreterTool | HostedMCPToolInput + | ShellToolInput + | LocalShellTool + | ApplyPatchToolInput + | ToolSearchTool ) @@ -181,9 +222,26 @@ def make_tool(tool: ToolInput) -> Tool: WebSearchTool, ImageGenerationTool, CodeInterpreterTool, + LocalShellTool, + ToolSearchTool, ), ): return tool + elif isinstance(tool, ShellToolInput): + + async def _noop_executor(*a: Any, **kw: Any) -> str: # type: ignore[reportUnusedParameter] + return "" + + return ShellTool( + name=tool.name, + environment=tool.environment, + executor=_noop_executor, + ) + elif isinstance(tool, ApplyPatchToolInput): + return ApplyPatchTool( + name=tool.name, + editor=_NoopApplyPatchEditor(), + ) elif isinstance(tool, HostedMCPToolInput): return HostedMCPTool( tool_config=tool.tool_config, diff --git a/temporalio/contrib/openai_agents/_mcp.py b/temporalio/contrib/openai_agents/_mcp.py index 8d6a9464a..78ac5daa0 100644 --- a/temporalio/contrib/openai_agents/_mcp.py +++ b/temporalio/contrib/openai_agents/_mcp.py @@ -41,6 +41,7 @@ class _StatelessCallToolsArguments: tool_name: str arguments: dict[str, Any] | None factory_argument: Any | None + meta: dict[str, Any] | None = None @dataclasses.dataclass @@ -100,11 +101,16 @@ async def list_tools( return tools async def call_tool( - self, tool_name: str, arguments: dict[str, Any] | None + self, + tool_name: str, + arguments: dict[str, Any] | None, + meta: dict[str, Any] | None = None, ) -> CallToolResult: return await workflow.execute_activity( self.name + "-call-tool-v2", - _StatelessCallToolsArguments(tool_name, arguments, self._factory_argument), + _StatelessCallToolsArguments( + tool_name, arguments, self._factory_argument, meta + ), result_type=CallToolResult, **self._config, ) @@ -190,7 +196,7 @@ async def call_tool(args: _StatelessCallToolsArguments) -> CallToolResult: server = self._create_server(args.factory_argument) try: await server.connect() - return await server.call_tool(args.tool_name, args.arguments) + return await server.call_tool(args.tool_name, args.arguments, args.meta) finally: await server.cleanup() @@ -275,6 +281,7 @@ async def wrapper(*args: Any, **kwargs: Any): class _StatefulCallToolsArguments: tool_name: str arguments: dict[str, Any] | None + meta: dict[str, Any] | None = None @dataclasses.dataclass @@ -362,7 +369,10 @@ async def list_tools( @_handle_worker_failure async def call_tool( - self, tool_name: str, arguments: dict[str, Any] | None + self, + tool_name: str, + arguments: dict[str, Any] | None, + meta: dict[str, Any] | None = None, ) -> CallToolResult: if not self._connect_handle: raise ApplicationError( @@ -370,7 +380,7 @@ async def call_tool( ) return await workflow.execute_activity( self.name + "-call-tool-v2", - _StatefulCallToolsArguments(tool_name, arguments), + _StatefulCallToolsArguments(tool_name, arguments, meta), result_type=CallToolResult, **self._config, ) @@ -460,7 +470,7 @@ async def call_tool_deprecated( @activity.defn(name=self.name + "-call-tool-v2") async def call_tool(args: _StatefulCallToolsArguments) -> CallToolResult: return await self._servers[_server_id()].call_tool( - args.tool_name, args.arguments + args.tool_name, args.arguments, args.meta ) @activity.defn(name=self.name + "-list-prompts") diff --git a/temporalio/contrib/openai_agents/_openai_runner.py b/temporalio/contrib/openai_agents/_openai_runner.py index 30e27f061..1884ff8a6 100644 --- a/temporalio/contrib/openai_agents/_openai_runner.py +++ b/temporalio/contrib/openai_agents/_openai_runner.py @@ -10,15 +10,21 @@ RunContextWrapper, RunResult, RunResultStreaming, + RunState, SQLiteSession, TContext, TResponseInputItem, ) -from agents.run import DEFAULT_AGENT_RUNNER, DEFAULT_MAX_TURNS, AgentRunner +from agents.run import DEFAULT_AGENT_RUNNER, DEFAULT_MAX_TURNS, AgentRunner, RunOptions +from agents.sandbox import SandboxAgent +from typing_extensions import Unpack from temporalio import workflow from temporalio.contrib.openai_agents._model_parameters import ModelActivityParameters from temporalio.contrib.openai_agents._temporal_model_stub import _TemporalModelStub +from temporalio.contrib.openai_agents.sandbox._temporal_sandbox_client import ( + TemporalSandboxClient, +) from temporalio.contrib.openai_agents.workflow import AgentsWorkflowError @@ -78,6 +84,21 @@ async def on_invoke( return new_agent +def _has_sandbox_agent(agent: Agent[Any], seen: set[int] | None = None) -> bool: + """Check if any agent in the graph (following direct Agent handoffs) is a SandboxAgent.""" + if seen is None: + seen = set() + if id(agent) in seen: + return False + seen.add(id(agent)) + if isinstance(agent, SandboxAgent): + return True + for handoff in agent.handoffs: + if isinstance(handoff, Agent) and _has_sandbox_agent(handoff, seen): + return True + return False + + class TemporalOpenAIRunner(AgentRunner): """Temporal Runner for OpenAI agents. @@ -85,7 +106,10 @@ class TemporalOpenAIRunner(AgentRunner): """ - def __init__(self, model_params: ModelActivityParameters) -> None: + def __init__( + self, + model_params: ModelActivityParameters, + ) -> None: """Initialize the Temporal OpenAI Runner.""" self._runner = DEFAULT_AGENT_RUNNER or AgentRunner() self.model_params = model_params @@ -93,8 +117,8 @@ def __init__(self, model_params: ModelActivityParameters) -> None: async def run( self, starting_agent: Agent[TContext], - input: str | list[TResponseInputItem], - **kwargs: Any, + input: str | list[TResponseInputItem] | RunState[TContext], + **kwargs: Unpack[RunOptions[TContext]], ) -> RunResult: """Run the agent in a Temporal workflow.""" if not workflow.in_workflow(): @@ -141,7 +165,7 @@ async def run( if run_config is None: run_config = RunConfig() - if run_config.model: + if run_config.model and not isinstance(run_config.model, _TemporalModelStub): if not isinstance(run_config.model, str): raise ValueError( "Temporal workflows require a model name to be a string in the run config." @@ -152,6 +176,28 @@ async def run( run_config.model, model_params=self.model_params, agent=None ), ) + # run_config.sandbox is global for the entire run — configure it if any agent needs it. + if _has_sandbox_agent(starting_agent) or run_config.sandbox: + if run_config.sandbox is None: + raise ValueError( + "A SandboxAgent was provided but run_config.sandbox is not configured. " + "You must set run_config.sandbox to a SandboxRunConfig. " + "For example:\n" + " from temporalio.contrib.openai_agents.workflow import temporal_sandbox_client\n" + " run_config = RunConfig(sandbox=SandboxRunConfig(client=temporal_sandbox_client('my-backend')))" + ) + elif run_config.sandbox.client is None: + raise ValueError( + "run_config.sandbox.client must be set to a temporal sandbox client. " + "Use temporalio.contrib.openai_agents.workflow.temporal_sandbox_client(name) " + "to create one, where name matches a SandboxClientProvider registered on the plugin." + ) + elif not isinstance(run_config.sandbox.client, TemporalSandboxClient): + raise ValueError( + "run_config.sandbox.client must be created via " + "temporalio.contrib.openai_agents.workflow.temporal_sandbox_client(name). " + "Do not pass a raw sandbox client directly." + ) try: return await self._runner.run( @@ -179,7 +225,7 @@ async def run( def run_sync( self, starting_agent: Agent[TContext], - input: str | list[TResponseInputItem], + input: str | list[TResponseInputItem] | RunState[TContext], **kwargs: Any, ) -> RunResult: """Run the agent synchronously (not supported in Temporal workflows).""" @@ -194,7 +240,7 @@ def run_sync( def run_streamed( self, starting_agent: Agent[TContext], - input: str | list[TResponseInputItem], + input: str | list[TResponseInputItem] | RunState[TContext], **kwargs: Any, ) -> RunResultStreaming: """Run the agent with streaming responses (not supported in Temporal workflows).""" diff --git a/temporalio/contrib/openai_agents/_temporal_model_stub.py b/temporalio/contrib/openai_agents/_temporal_model_stub.py index f55821309..03e689f17 100644 --- a/temporalio/contrib/openai_agents/_temporal_model_stub.py +++ b/temporalio/contrib/openai_agents/_temporal_model_stub.py @@ -29,16 +29,19 @@ WebSearchTool, ) from agents.items import TResponseStreamEvent +from agents.tool import ApplyPatchTool, LocalShellTool, ShellTool, ToolSearchTool from openai.types.responses.response_prompt_param import ResponsePromptParam from temporalio.contrib.openai_agents._invoke_model_activity import ( ActivityModelInput, AgentOutputSchemaInput, + ApplyPatchToolInput, FunctionToolInput, HandoffInput, HostedMCPToolInput, ModelActivity, ModelTracingInput, + ShellToolInput, ToolInput, ) @@ -79,9 +82,18 @@ def make_tool_info(tool: Tool) -> ToolInput: WebSearchTool, ImageGenerationTool, CodeInterpreterTool, + LocalShellTool, + ToolSearchTool, ), ): return tool + elif isinstance(tool, ShellTool): + return ShellToolInput( + name=tool.name, + environment=tool.environment, + ) + elif isinstance(tool, ApplyPatchTool): + return ApplyPatchToolInput(name=tool.name) elif isinstance(tool, HostedMCPTool): return HostedMCPToolInput(tool_config=tool.tool_config) elif isinstance(tool, FunctionTool): diff --git a/temporalio/contrib/openai_agents/_temporal_openai_agents.py b/temporalio/contrib/openai_agents/_temporal_openai_agents.py index 39168d0fd..f7757723c 100644 --- a/temporalio/contrib/openai_agents/_temporal_openai_agents.py +++ b/temporalio/contrib/openai_agents/_temporal_openai_agents.py @@ -38,6 +38,7 @@ if typing.TYPE_CHECKING: from temporalio.contrib.openai_agents import ( + SandboxClientProvider, StatefulMCPServerProvider, StatelessMCPServerProvider, ) @@ -144,6 +145,7 @@ def __init__( mcp_server_providers: Sequence[ "StatelessMCPServerProvider | StatefulMCPServerProvider" ] = (), + sandbox_clients: Sequence["SandboxClientProvider"] = (), register_activities: bool = True, add_temporal_spans: bool = True, use_otel_instrumentation: bool = False, @@ -159,6 +161,14 @@ def __init__( Each server will be wrapped in a TemporalMCPServer if not already wrapped, and their activities will be automatically registered with the worker. The plugin manages the connection lifecycle of these servers. + sandbox_clients: Sequence of named sandbox client providers to register + on the worker. Each provider pairs a unique name with a real + ``BaseSandboxClient`` (e.g. ``DaytonaSandboxClient``, + ``UnixLocalSandboxClient``). On the workflow side, use + ``temporal_sandbox_client`` + with the matching name to target the correct backend. + Warning: sandbox_clients is experimental and behavior may change in future versions. + Use with caution in production environments. register_activities: Whether to register activities during the worker execution. This can be disabled on some workers to allow a separation of workflows and activities but should not be disabled on all workers, or agents will not be able to progress. @@ -200,11 +210,21 @@ def add_activities( server_names = [server.name for server in mcp_server_providers] if len(server_names) != len(set(server_names)): raise ValueError( - f"More than one mcp server registered with the same name. Please provide unique names." + "More than one mcp server registered with the same name. Please provide unique names." ) for mcp_server in mcp_server_providers: new_activities.extend(mcp_server._get_activities()) + + sandbox_names = [sc.name for sc in sandbox_clients] + if len(sandbox_names) != len(set(sandbox_names)): + raise ValueError( + "More than one sandbox client registered with the same name. Please provide unique names." + ) + + for sandbox_provider in sandbox_clients: + new_activities.extend(sandbox_provider._get_activities()) + return list(activities or []) + new_activities def workflow_runner(runner: WorkflowRunner | None) -> WorkflowRunner: @@ -247,7 +267,8 @@ def workflow_runner(runner: WorkflowRunner | None) -> WorkflowRunner: async def run_context() -> AsyncIterator[None]: with self.tracing_context(): with _set_open_ai_agent_temporal_overrides( - model_params, start_spans_in_replay=use_otel_instrumentation + model_params, + start_spans_in_replay=use_otel_instrumentation, ): yield diff --git a/temporalio/contrib/openai_agents/sandbox/__init__.py b/temporalio/contrib/openai_agents/sandbox/__init__.py new file mode 100644 index 000000000..632b264cd --- /dev/null +++ b/temporalio/contrib/openai_agents/sandbox/__init__.py @@ -0,0 +1 @@ +"""Sandbox support for Temporal OpenAI Agents plugin.""" diff --git a/temporalio/contrib/openai_agents/sandbox/_sandbox_client_provider.py b/temporalio/contrib/openai_agents/sandbox/_sandbox_client_provider.py new file mode 100644 index 000000000..9e4d67644 --- /dev/null +++ b/temporalio/contrib/openai_agents/sandbox/_sandbox_client_provider.py @@ -0,0 +1,245 @@ +"""Public-facing provider that pairs a name with a real sandbox client.""" + +from __future__ import annotations + +import io +from collections.abc import Callable, Sequence +from pathlib import Path +from typing import Any + +from agents.sandbox.session.sandbox_client import BaseSandboxClient +from agents.sandbox.session.sandbox_session import SandboxSession + +from temporalio import activity +from temporalio.contrib.openai_agents.sandbox._temporal_activity_models import ( + CreateSessionArgs, + ExecArgs, + HydrateWorkspaceArgs, + PersistWorkspaceArgs, + PersistWorkspaceResult, + PtyExecStartArgs, + PtyExecUpdateResult, + PtyWriteStdinArgs, + ReadArgs, + ReadResult, + ResumeSessionArgs, + RunningArgs, + RunningResult, + SessionResult, + StartArgs, + StopArgs, + WriteArgs, + _HasState, +) +from temporalio.contrib.openai_agents.sandbox._temporal_activity_models import ( + ExecResult as ExecResultModel, +) + + +class SandboxClientProvider: + """A named sandbox client provider for Temporal workflows. + + .. warning:: + This class is experimental and may change in future versions. + Use with caution in production environments. + + Wraps a ``BaseSandboxClient`` with a unique name so that multiple + sandbox backends can be registered on a single Temporal worker. Each + provider gets its own set of Temporal activities whose names are prefixed + with the provider name, allowing them to coexist on the same task queue. + + On the **worker side**, pass one or more providers to the plugin:: + + plugin = OpenAIAgentsPlugin( + sandbox_clients=[ + SandboxClientProvider("daytona", DaytonaSandboxClient()), + SandboxClientProvider("local", UnixLocalSandboxClient()), + ], + ) + + On the **workflow side**, reference a provider by name via + :func:`temporalio.contrib.openai_agents.workflow.temporal_sandbox_client`:: + + run_config = RunConfig( + sandbox=SandboxRunConfig( + client=temporal_sandbox_client("daytona"), + ... + ), + ) + + Args: + name: A unique name for this sandbox backend (e.g. ``"daytona"``, + ``"local"``). Must match the name used on the workflow side. + client: The real ``BaseSandboxClient`` that performs sandbox + lifecycle and I/O operations on the worker. + """ + + def __init__(self, name: str, client: BaseSandboxClient[Any]) -> None: + """Initialize the provider.""" + self._name = name + self._client = client + self._sessions: dict[str, SandboxSession] = {} + + @property + def name(self) -> str: + """The provider name used as an activity-name prefix.""" + return self._name + + async def _session(self, args: _HasState) -> SandboxSession: + key = str(args.state.session_id) + if key not in self._sessions: + self._sessions[key] = await self._client.resume(args.state) + return self._sessions[key] + + def _get_activities(self) -> Sequence[Callable[..., Any]]: + """Return all activity callables for registration with a Temporal Worker.""" + prefix = self._name + + # -- Client-level operations (lifecycle) -- + + @activity.defn(name=f"{prefix}-sandbox_client_create") + async def create_session(args: CreateSessionArgs) -> SessionResult: + session = await self._client.create( + snapshot=args.snapshot_spec, + manifest=args.manifest, + options=args.client_options, + ) + self._sessions[str(session.state.session_id)] = session + return SessionResult( + state=session.state, supports_pty=session.supports_pty() + ) + + @activity.defn(name=f"{prefix}-sandbox_client_resume") + async def resume_session(args: ResumeSessionArgs) -> SessionResult: + session = await self._client.resume(args.state) + self._sessions[str(session.state.session_id)] = session + return SessionResult( + state=session.state, supports_pty=session.supports_pty() + ) + + @activity.defn(name=f"{prefix}-sandbox_client_delete") + async def delete_session(args: StopArgs) -> None: + session = await self._session(args) + await self._client.delete(session) + return None + + # -- Session-level operations (I/O and lifecycle) -- + + @activity.defn(name=f"{prefix}-sandbox_session_exec") + async def exec_(args: ExecArgs) -> ExecResultModel: + session = await self._session(args) + result = await session.exec( + *args.command, + timeout=args.timeout, + shell=args.shell, + user=args.user, + ) + return ExecResultModel( + stdout=result.stdout, + stderr=result.stderr, + exit_code=result.exit_code, + ) + + @activity.defn(name=f"{prefix}-sandbox_session_read") + async def read(args: ReadArgs) -> ReadResult: + session = await self._session(args) + handle = await session.read(Path(args.path)) + return ReadResult(data=handle.read()) + + @activity.defn(name=f"{prefix}-sandbox_session_write") + async def write(args: WriteArgs) -> None: + session = await self._session(args) + await session.write(Path(args.path), io.BytesIO(args.data)) + return None + + @activity.defn(name=f"{prefix}-sandbox_session_running") + async def running(args: RunningArgs) -> RunningResult: + session = await self._session(args) + return RunningResult(is_running=await session.running()) + + @activity.defn(name=f"{prefix}-sandbox_session_persist_workspace") + async def persist_workspace( + args: PersistWorkspaceArgs, + ) -> PersistWorkspaceResult: + session = await self._session(args) + stream = await session.persist_workspace() + return PersistWorkspaceResult(data=stream.read()) + + @activity.defn(name=f"{prefix}-sandbox_session_hydrate_workspace") + async def hydrate_workspace(args: HydrateWorkspaceArgs) -> None: + session = await self._session(args) + await session.hydrate_workspace(io.BytesIO(args.data)) + return None + + @activity.defn(name=f"{prefix}-sandbox_session_pty_exec_start") + async def pty_exec_start(args: PtyExecStartArgs) -> PtyExecUpdateResult: + session = await self._session(args) + update = await session.pty_exec_start( + *args.command, + timeout=args.timeout, + shell=args.shell, + user=args.user, + tty=args.tty, + yield_time_s=args.yield_time_s, + max_output_tokens=args.max_output_tokens, + ) + return PtyExecUpdateResult( + process_id=update.process_id, + output=update.output, + exit_code=update.exit_code, + original_token_count=update.original_token_count, + ) + + @activity.defn(name=f"{prefix}-sandbox_session_pty_write_stdin") + async def pty_write_stdin(args: PtyWriteStdinArgs) -> PtyExecUpdateResult: + session = await self._session(args) + update = await session.pty_write_stdin( + session_id=args.session_id, + chars=args.chars, + yield_time_s=args.yield_time_s, + max_output_tokens=args.max_output_tokens, + ) + return PtyExecUpdateResult( + process_id=update.process_id, + output=update.output, + exit_code=update.exit_code, + original_token_count=update.original_token_count, + ) + + @activity.defn(name=f"{prefix}-sandbox_session_start") + async def start(args: StartArgs) -> None: + session = await self._session(args) + await session.start() + return None + + @activity.defn(name=f"{prefix}-sandbox_session_stop") + async def session_stop(args: StopArgs) -> None: + session = await self._session(args) + await session.stop() + return None + + @activity.defn(name=f"{prefix}-sandbox_session_shutdown") + async def session_shutdown(args: StopArgs) -> None: + key = str(args.state.session_id) + session = self._sessions.get(key) + if session is not None: + await session.shutdown() + del self._sessions[key] + return None + + return [ + create_session, + resume_session, + delete_session, + exec_, + read, + write, + running, + persist_workspace, + hydrate_workspace, + pty_exec_start, + pty_write_stdin, + start, + session_stop, + session_shutdown, + ] diff --git a/temporalio/contrib/openai_agents/sandbox/_temporal_activity_models.py b/temporalio/contrib/openai_agents/sandbox/_temporal_activity_models.py new file mode 100644 index 000000000..5cdc0ccba --- /dev/null +++ b/temporalio/contrib/openai_agents/sandbox/_temporal_activity_models.py @@ -0,0 +1,218 @@ +"""Pydantic models for Temporal sandbox activity arguments and results. + +Using ``pydantic_data_converter`` on the Temporal client means these models are +serialized/deserialized automatically. Each activity receives a single typed +model instance rather than a positional arg list. +""" + +from __future__ import annotations + +from base64 import b64decode, b64encode +from typing import Annotated, Any, cast + +from agents.sandbox import Manifest +from agents.sandbox.session.sandbox_client import BaseSandboxClientOptions +from agents.sandbox.session.sandbox_session_state import SandboxSessionState +from agents.sandbox.snapshot import SnapshotBase, SnapshotSpecUnion +from agents.sandbox.types import User +from pydantic import ( + BaseModel, + BeforeValidator, + PlainSerializer, + SerializeAsAny, + field_validator, +) + + +def _coerce_bytes(v: Any) -> bytes: + if isinstance(v, bytes): + return v + if isinstance(v, str): + return b64decode(v) + raise ValueError(f"Expected bytes or base64 string, got {type(v)}") + + +# Bytes type that is stored as raw bytes in Python but base64-encoded in JSON, +# ensuring lossless serialization of arbitrary binary data through pydantic. +JsonSafeBytes = Annotated[ + bytes, + BeforeValidator(_coerce_bytes), + PlainSerializer(lambda v: b64encode(v).decode("ascii"), return_type=str), +] + +# --------------------------------------------------------------------------- +# Shared base for all argument models that carry a session state field. +# --------------------------------------------------------------------------- + + +class _HasState(BaseModel): + state: SerializeAsAny[SandboxSessionState] + + @field_validator("state", mode="before") + @classmethod + def _coerce_state(cls, value: object) -> SandboxSessionState: + return SandboxSessionState.parse(value) + + +# --------------------------------------------------------------------------- +# Argument models (workflow -> activity) +# --------------------------------------------------------------------------- + + +class ExecArgs(_HasState): + """Arguments for exec activity.""" + + command: list[str] + timeout: float | None = None + shell: bool | list[str] = True + user: str | User | None = None + + +class ReadArgs(_HasState): + """Arguments for read activity.""" + + path: str + + +class WriteArgs(_HasState): + """Arguments for write activity.""" + + path: str + data: JsonSafeBytes + + +class RunningArgs(_HasState): + """Arguments for running check activity.""" + + pass + + +class PersistWorkspaceArgs(_HasState): + """Arguments for persist workspace activity.""" + + pass + + +class HydrateWorkspaceArgs(_HasState): + """Arguments for hydrate workspace activity.""" + + data: JsonSafeBytes + + +class PtyExecStartArgs(_HasState): + """Arguments for PTY exec start activity.""" + + command: list[str] + timeout: float | None = None + shell: bool | list[str] = True + user: str | User | None = None + tty: bool = False + yield_time_s: float | None = None + max_output_tokens: int | None = None + + +class PtyWriteStdinArgs(_HasState): + """Arguments for PTY write stdin activity.""" + + session_id: int + chars: str + yield_time_s: float | None = None + max_output_tokens: int | None = None + + +class StartArgs(_HasState): + """Arguments for start activity.""" + + pass + + +class StopArgs(_HasState): + """Arguments for stop activity.""" + + pass + + +# --------------------------------------------------------------------------- +# Result models (activity -> workflow) +# --------------------------------------------------------------------------- + + +class ExecResult(BaseModel): + """Result of an exec activity.""" + + stdout: JsonSafeBytes + stderr: JsonSafeBytes + exit_code: int + + +class PtyExecUpdateResult(BaseModel): + """Result of a PTY exec activity.""" + + process_id: int | None + output: JsonSafeBytes + exit_code: int | None + original_token_count: int | None + + +class ReadResult(BaseModel): + """Result of a read activity.""" + + data: JsonSafeBytes + + +class RunningResult(BaseModel): + """Result of a running check activity.""" + + is_running: bool + + +class PersistWorkspaceResult(BaseModel): + """Result of a persist workspace activity.""" + + data: JsonSafeBytes + + +# --------------------------------------------------------------------------- +# Session lifecycle models (create / resume) +# --------------------------------------------------------------------------- + + +class CreateSessionArgs(BaseModel): + """Arguments for create session activity.""" + + snapshot_spec: SnapshotSpecUnion | SerializeAsAny[SnapshotBase] | None = None + manifest: Manifest | None = None + client_options: SerializeAsAny[BaseSandboxClientOptions] | None = None + + @field_validator("snapshot_spec", mode="before") + @classmethod + def _coerce_snapshot_spec( + cls, value: object + ) -> SnapshotSpecUnion | SnapshotBase | None: + if value is None or isinstance(value, SnapshotBase): + return value + # SnapshotBase subclasses always carry an `id` field; + # SnapshotSpec subclasses do not. Use that to distinguish + # serialized SnapshotBase dicts from SnapshotSpecUnion dicts. + if isinstance(value, dict) and "id" in value: + return SnapshotBase.parse(value) + return cast(SnapshotSpecUnion | None, value) + + @field_validator("client_options", mode="before") + @classmethod + def _coerce_client_options(cls, value: object) -> BaseSandboxClientOptions | None: + if value is None: + return None + return BaseSandboxClientOptions.parse(value) + + +class ResumeSessionArgs(_HasState): + """Arguments for resume session activity.""" + + pass + + +class SessionResult(_HasState): + """Result of create/resume -- session state + capabilities.""" + + supports_pty: bool diff --git a/temporalio/contrib/openai_agents/sandbox/_temporal_sandbox_client.py b/temporalio/contrib/openai_agents/sandbox/_temporal_sandbox_client.py new file mode 100644 index 000000000..891c65f4b --- /dev/null +++ b/temporalio/contrib/openai_agents/sandbox/_temporal_sandbox_client.py @@ -0,0 +1,124 @@ +"""Temporal-aware sandbox client that dispatches lifecycle operations as activities.""" + +from __future__ import annotations + +from datetime import timedelta +from typing import Any + +from agents.sandbox import Manifest +from agents.sandbox.session.sandbox_client import ( + BaseSandboxClient, + BaseSandboxClientOptions, +) +from agents.sandbox.session.sandbox_session import SandboxSession +from agents.sandbox.session.sandbox_session_state import SandboxSessionState +from agents.sandbox.snapshot import SnapshotBase, SnapshotSpec, SnapshotSpecUnion +from pydantic.type_adapter import TypeAdapter + +from temporalio import workflow +from temporalio.contrib.openai_agents.sandbox._temporal_activity_models import ( + CreateSessionArgs, + ResumeSessionArgs, + SessionResult, + StopArgs, +) +from temporalio.contrib.openai_agents.sandbox._temporal_sandbox_session import ( + TemporalSandboxSession, +) +from temporalio.workflow import ActivityConfig + + +class TemporalSandboxClient(BaseSandboxClient[BaseSandboxClientOptions]): + """Stateless client that dispatches all lifecycle operations as Temporal activities. + + No inner client is needed -- session creation, resumption, and deletion are + all handled by activities whose names are prefixed with the provider + ``name`` (e.g. ``"daytona-sandbox_create_session"``). The real + ``BaseSandboxClient`` lives inside :class:`SandboxClientProvider` on the worker. + + Users should never need to instantiate this directly -- use + :func:`temporalio.contrib.openai_agents.workflow.temporal_sandbox_client` + instead. + + Args: + name: The name of the :class:`SandboxClientProvider` registered on the + worker. Used as an activity-name prefix so that the correct + sandbox backend is targeted. + config: Optional activity configuration for controlling timeouts, + retries, etc. Defaults to a 5-minute ``start_to_close_timeout``. + """ + + def __init__( + self, + name: str, + config: ActivityConfig | None = None, + ) -> None: + """Initialize the client.""" + self._name = name + self._config: ActivityConfig = config or ActivityConfig( + start_to_close_timeout=timedelta(minutes=5), + ) + self.backend_id = name + + async def create( + self, + *, + snapshot: SnapshotSpec | SnapshotBase | None = None, + manifest: Manifest | None = None, + options: BaseSandboxClientOptions, + ) -> SandboxSession: + """Create a new sandbox session via activity.""" + result: SessionResult = await workflow.execute_activity( + f"{self._name}-sandbox_client_create", + arg=CreateSessionArgs( + snapshot_spec=TypeAdapter(SnapshotSpecUnion).validate_python(snapshot) + if isinstance(snapshot, SnapshotSpec) + else snapshot, + manifest=manifest, + client_options=options, + ), + result_type=SessionResult, + **self._config, + ) + return self._wrap_session( + TemporalSandboxSession( + name=self._name, + config=self._config, + state=result.state, + supports_pty_flag=result.supports_pty, + ), + # Real instrumentation runs in the activity in the real client session. + instrumentation=None, + ) + + async def resume(self, state: SandboxSessionState) -> SandboxSession: + """Resume an existing sandbox session via activity.""" + result: SessionResult = await workflow.execute_activity( + f"{self._name}-sandbox_client_resume", + arg=ResumeSessionArgs(state=state), + result_type=SessionResult, + **self._config, + ) + return self._wrap_session( + TemporalSandboxSession( + name=self._name, + config=self._config, + state=result.state, + supports_pty_flag=result.supports_pty, + ), + # Real instrumentation runs in the activity in the real client session. + instrumentation=None, + ) + + async def delete(self, session: TemporalSandboxSession) -> TemporalSandboxSession: # type: ignore[override] + """Delete a sandbox session via activity.""" + await workflow.execute_activity( + f"{self._name}-sandbox_client_delete", + arg=StopArgs(state=session.state), + **self._config, + ) + return session + + def deserialize_session_state(self, payload: dict[str, Any]) -> SandboxSessionState: + """Deserialize a session state from a dict.""" + return SandboxSessionState.parse(payload) diff --git a/temporalio/contrib/openai_agents/sandbox/_temporal_sandbox_session.py b/temporalio/contrib/openai_agents/sandbox/_temporal_sandbox_session.py new file mode 100644 index 000000000..cccb72936 --- /dev/null +++ b/temporalio/contrib/openai_agents/sandbox/_temporal_sandbox_session.py @@ -0,0 +1,239 @@ +"""Temporal-aware sandbox session that routes all I/O through Temporal activities.""" + +from __future__ import annotations + +import io +from pathlib import Path + +from agents.sandbox.session.base_sandbox_session import BaseSandboxSession +from agents.sandbox.session.pty_types import PtyExecUpdate +from agents.sandbox.session.sandbox_session_state import SandboxSessionState +from agents.sandbox.types import ExecResult, User + +from temporalio import workflow +from temporalio.contrib.openai_agents.sandbox._temporal_activity_models import ( + ExecArgs, + HydrateWorkspaceArgs, + PersistWorkspaceArgs, + PersistWorkspaceResult, + PtyExecStartArgs, + PtyExecUpdateResult, + PtyWriteStdinArgs, + ReadArgs, + ReadResult, + RunningArgs, + RunningResult, + StartArgs, + StopArgs, + WriteArgs, +) +from temporalio.contrib.openai_agents.sandbox._temporal_activity_models import ( + ExecResult as ExecResultModel, +) +from temporalio.workflow import ActivityConfig + + +class TemporalSandboxSession(BaseSandboxSession): + """A BaseSandboxSession that routes all I/O through Temporal activities. + + This class is fully stateless with respect to the physical sandbox -- it + holds only the serializable ``SandboxSessionState`` and a ``supports_pty`` + flag (both provided by the worker-side ``SessionResult``). + + Activity names are prefixed with the provider ``name`` so that dispatches + reach the correct sandbox backend's activities on the worker. + + Each activity receives a single Pydantic model instance. Because the Temporal + client is configured with ``pydantic_data_converter``, all fields are + serialized and deserialized automatically. + """ + + def __init__( + self, + name: str, + config: ActivityConfig, + state: SandboxSessionState, + supports_pty_flag: bool = True, + ) -> None: + """Initialize the session.""" + self._name = name + self._config = config + self._state = state + self._supports_pty = supports_pty_flag + + @property + def state(self) -> SandboxSessionState: + """The current session state.""" + return self._state + + @state.setter + def state(self, value: SandboxSessionState) -> None: # type: ignore[reportIncompatibleVariableOverride] + self._state = value + + async def exec( + self, + *command: str | Path, + timeout: float | None = None, + shell: bool | list[str] = True, + user: str | User | None = None, + ) -> ExecResult: + """Execute a command in the sandbox via activity.""" + result: ExecResultModel = await workflow.execute_activity( + f"{self._name}-sandbox_session_exec", + arg=ExecArgs( + state=self.state, + command=[str(c) for c in command], + timeout=timeout, + shell=shell, + user=user, + ), + result_type=ExecResultModel, + **self._config, + ) + return ExecResult( + stdout=result.stdout, stderr=result.stderr, exit_code=result.exit_code + ) + + async def _exec_internal( + self, + *command: str | Path, + timeout: float | None = None, + ) -> ExecResult: + raise NotImplementedError("TemporalSandboxSession overrides exec() directly") + + async def read(self, path: Path, *, user: str | User | None = None) -> io.IOBase: + """Read a file from the sandbox via activity.""" + result: ReadResult = await workflow.execute_activity( + f"{self._name}-sandbox_session_read", + arg=ReadArgs(state=self.state, path=str(path)), + result_type=ReadResult, + **self._config, + ) + return io.BytesIO(result.data) + + async def write( + self, path: Path, data: io.IOBase, *, user: str | User | None = None + ) -> None: + """Write a file to the sandbox via activity.""" + await workflow.execute_activity( + f"{self._name}-sandbox_session_write", + arg=WriteArgs(state=self.state, path=str(path), data=data.read()), + **self._config, + ) + + async def running(self) -> bool: + """Check if the sandbox is running via activity.""" + result: RunningResult = await workflow.execute_activity( + f"{self._name}-sandbox_session_running", + arg=RunningArgs(state=self.state), + result_type=RunningResult, + **self._config, + ) + return result.is_running + + async def shutdown(self) -> None: + """Shut down the sandbox via activity.""" + await workflow.execute_activity( + f"{self._name}-sandbox_session_shutdown", + arg=StopArgs(state=self.state), + **self._config, + ) + + async def persist_workspace(self) -> io.IOBase: + """Persist the workspace via activity.""" + result: PersistWorkspaceResult = await workflow.execute_activity( + f"{self._name}-sandbox_session_persist_workspace", + arg=PersistWorkspaceArgs(state=self.state), + result_type=PersistWorkspaceResult, + **self._config, + ) + return io.BytesIO(result.data) + + async def hydrate_workspace(self, data: io.IOBase) -> None: + """Hydrate the workspace via activity.""" + await workflow.execute_activity( + f"{self._name}-sandbox_session_hydrate_workspace", + arg=HydrateWorkspaceArgs(state=self.state, data=data.read()), + **self._config, + ) + + def supports_pty(self) -> bool: + """Whether this session supports PTY operations.""" + return self._supports_pty + + async def pty_exec_start( + self, + *command: str | Path, + timeout: float | None = None, + shell: bool | list[str] = True, + user: str | User | None = None, + tty: bool = False, + yield_time_s: float | None = None, + max_output_tokens: int | None = None, + ) -> PtyExecUpdate: + """Start a PTY exec via activity.""" + result: PtyExecUpdateResult = await workflow.execute_activity( + f"{self._name}-sandbox_session_pty_exec_start", + arg=PtyExecStartArgs( + state=self.state, + command=[str(c) for c in command], + timeout=timeout, + shell=shell, + user=user, + tty=tty, + yield_time_s=yield_time_s, + max_output_tokens=max_output_tokens, + ), + result_type=PtyExecUpdateResult, + **self._config, + ) + return PtyExecUpdate( + process_id=result.process_id, + output=result.output, + exit_code=result.exit_code, + original_token_count=result.original_token_count, + ) + + async def pty_write_stdin( + self, + *, + session_id: int, + chars: str, + yield_time_s: float | None = None, + max_output_tokens: int | None = None, + ) -> PtyExecUpdate: + """Write to PTY stdin via activity.""" + result: PtyExecUpdateResult = await workflow.execute_activity( + f"{self._name}-sandbox_session_pty_write_stdin", + arg=PtyWriteStdinArgs( + state=self.state, + session_id=session_id, + chars=chars, + yield_time_s=yield_time_s, + max_output_tokens=max_output_tokens, + ), + result_type=PtyExecUpdateResult, + **self._config, + ) + return PtyExecUpdate( + process_id=result.process_id, + output=result.output, + exit_code=result.exit_code, + original_token_count=result.original_token_count, + ) + + async def start(self) -> None: + """Start the sandbox session via activity.""" + await workflow.execute_activity( + f"{self._name}-sandbox_session_start", + arg=StartArgs(state=self.state), + **self._config, + ) + + async def stop(self) -> None: + """Stop the sandbox session via activity.""" + await workflow.execute_activity( + f"{self._name}-sandbox_session_stop", + arg=StopArgs(state=self.state), + **self._config, + ) diff --git a/temporalio/contrib/openai_agents/workflow.py b/temporalio/contrib/openai_agents/workflow.py index cf9ddbc70..b37a82bdc 100644 --- a/temporalio/contrib/openai_agents/workflow.py +++ b/temporalio/contrib/openai_agents/workflow.py @@ -22,6 +22,9 @@ from temporalio import activity from temporalio import workflow as temporal_workflow from temporalio.common import Priority, RetryPolicy +from temporalio.contrib.openai_agents.sandbox._temporal_sandbox_client import ( + TemporalSandboxClient, +) from temporalio.exceptions import ApplicationError, TemporalError from temporalio.workflow import ( ActivityCancellationType, @@ -241,6 +244,38 @@ async def run_operation(_ctx: RunContextWrapper[Any], input: str) -> Any: ) +def temporal_sandbox_client( + name: str, + config: ActivityConfig | None = None, +) -> Any: + """Create a sandbox client reference for use in a Temporal workflow ``RunConfig``. + + .. warning:: + This is experimental and may change in future versions. + Use with caution in production environments. + + This returns a ``BaseSandboxClient`` that dispatches all sandbox operations + as Temporal activities, targeting the ``SandboxClientProvider`` registered + on the worker with the matching ``name``. + + Example:: + + run_config = RunConfig( + sandbox=SandboxRunConfig( + client=temporal_sandbox_client("daytona"), + options=DaytonaSandboxClientOptions(...), + ), + ) + + Args: + name: The name of the ``SandboxClientProvider`` registered on the + worker. Must match exactly. + config: Optional activity configuration for controlling timeouts, + retries, etc. Defaults to a 5-minute ``start_to_close_timeout``. + """ + return TemporalSandboxClient(name=name, config=config) + + def stateless_mcp_server( name: str, config: ActivityConfig | None = None, diff --git a/tests/contrib/openai_agents/test_openai.py b/tests/contrib/openai_agents/test_openai.py index 84aa5646f..578eb4d77 100644 --- a/tests/contrib/openai_agents/test_openai.py +++ b/tests/contrib/openai_agents/test_openai.py @@ -2286,7 +2286,10 @@ async def list_tools( ] async def call_tool( - self, tool_name: str, arguments: dict[str, Any] | None + self, + tool_name: str, + arguments: dict[str, Any] | None, + meta: dict[str, Any] | None = None, ) -> CallToolResult: self.calls.append("call_tool") name = (arguments or {}).get("name") or "John Doe" diff --git a/tests/contrib/openai_agents/test_openai_sandbox.py b/tests/contrib/openai_agents/test_openai_sandbox.py new file mode 100644 index 000000000..74ff80e85 --- /dev/null +++ b/tests/contrib/openai_agents/test_openai_sandbox.py @@ -0,0 +1,792 @@ +"""Tests for sandbox validation in TemporalOpenAIRunner.""" + +import io +import uuid +from datetime import timedelta +from pathlib import Path +from typing import Any, Literal + +import pytest +from agents import Agent, FunctionTool, RunConfig, Runner, Tool +from agents.sandbox import Capability, Manifest, SandboxAgent, SandboxRunConfig +from agents.sandbox.session.base_sandbox_session import BaseSandboxSession +from agents.sandbox.session.sandbox_client import ( + BaseSandboxClient, + BaseSandboxClientOptions, +) +from agents.sandbox.session.sandbox_session import SandboxSession +from agents.sandbox.session.sandbox_session_state import SandboxSessionState +from agents.sandbox.snapshot import NoopSnapshot +from agents.sandbox.types import ExecResult +from pydantic import TypeAdapter +from pydantic_core import to_json + +from temporalio import workflow +from temporalio.client import Client +from temporalio.contrib.openai_agents import ( + ModelActivityParameters, + OpenAIAgentsPlugin, + SandboxClientProvider, +) +from temporalio.contrib.openai_agents._openai_runner import _has_sandbox_agent +from temporalio.contrib.openai_agents.sandbox._temporal_activity_models import ( + CreateSessionArgs, + ExecArgs, + HydrateWorkspaceArgs, + PersistWorkspaceResult, + PtyExecUpdateResult, + ReadArgs, + ReadResult, + ResumeSessionArgs, + RunningArgs, + StopArgs, + WriteArgs, +) +from temporalio.contrib.openai_agents.sandbox._temporal_activity_models import ( + ExecResult as ExecResultModel, +) +from temporalio.contrib.openai_agents.sandbox._temporal_sandbox_client import ( + TemporalSandboxClient, +) +from temporalio.contrib.openai_agents.testing import ( + AgentEnvironment, + ResponseBuilders, + TestModel, + TestModelProvider, +) +from temporalio.contrib.openai_agents.workflow import temporal_sandbox_client +from temporalio.workflow import ActivityConfig +from tests.helpers import new_worker + +# ── _has_sandbox_agent unit tests ── + + +def test_has_sandbox_agent_regular_agent(): + assert _has_sandbox_agent(Agent[None](name="regular")) is False + + +def test_has_sandbox_agent_sandbox_starting(): + assert _has_sandbox_agent(SandboxAgent[None](name="sandbox")) is True + + +def test_has_sandbox_agent_sandbox_direct_handoff(): + sandbox = SandboxAgent[None](name="sandbox") + regular = Agent[None](name="regular", handoffs=[sandbox]) + assert _has_sandbox_agent(regular) is True + + +def test_has_sandbox_agent_sandbox_deep_handoff(): + sandbox = SandboxAgent[None](name="sandbox") + middle = Agent[None](name="middle", handoffs=[sandbox]) + top = Agent[None](name="top", handoffs=[middle]) + assert _has_sandbox_agent(top) is True + + +def test_has_sandbox_agent_no_sandbox_in_chain(): + c = Agent[None](name="c") + b = Agent[None](name="b", handoffs=[c]) + a = Agent[None](name="a", handoffs=[b]) + assert _has_sandbox_agent(a) is False + + +def test_has_sandbox_agent_circular_no_sandbox(): + a: Agent[Any] = Agent[None](name="a") + b: Agent[Any] = Agent[None](name="b", handoffs=[a]) + a.handoffs = [b] + assert _has_sandbox_agent(a) is False + + +def test_has_sandbox_agent_circular_with_sandbox(): + sandbox = SandboxAgent[None](name="sandbox") + a: Agent[Any] = Agent[None](name="a", handoffs=[sandbox]) + b: Agent[Any] = Agent[None](name="b", handoffs=[a]) + a.handoffs = [b, sandbox] + assert _has_sandbox_agent(b) is True + + +# ── temporal_sandbox_client helper tests ── + + +def test_temporal_sandbox_client_returns_temporal_client(): + client = temporal_sandbox_client("my-backend") + assert isinstance(client, TemporalSandboxClient) + assert client._name == "my-backend" + assert client.backend_id == "my-backend" + + +def test_temporal_sandbox_client_with_config(): + config = ActivityConfig(start_to_close_timeout=timedelta(minutes=10)) + client = temporal_sandbox_client("my-backend", config=config) + assert isinstance(client, TemporalSandboxClient) + assert client._config == config + + +# ── Workflow validation tests ── + + +def _mock_model(): + return TestModel.returning_responses([ResponseBuilders.output_message("test")]) + + +@workflow.defn +class SandboxValidationWorkflow: + """Single workflow that validates all sandbox configuration error cases.""" + + @workflow.run + async def run(self) -> str: + # Case 1: SandboxAgent without run_config.sandbox + try: + agent = SandboxAgent[None](name="sandbox") + await Runner.run(starting_agent=agent, input="hello") + return "FAIL: no-config should have raised" + except ValueError as e: + assert "run_config.sandbox is not configured" in str(e) + + # Case 2: SandboxAgent reachable via handoff without run_config.sandbox + try: + sandbox = SandboxAgent[None](name="sandbox_target") + router = Agent[None](name="router", handoffs=[sandbox]) + await Runner.run(starting_agent=router, input="hello") + return "FAIL: handoff-no-config should have raised" + except ValueError as e: + assert "run_config.sandbox is not configured" in str(e) + + # Case 3: SandboxRunConfig with client=None + try: + agent = SandboxAgent[None](name="sandbox") + await Runner.run( + starting_agent=agent, + input="hello", + run_config=RunConfig( + sandbox=SandboxRunConfig(client=None), # type: ignore[arg-type] + ), + ) + return "FAIL: null-client should have raised" + except ValueError as e: + assert "run_config.sandbox.client must be set" in str(e) + + # Case 4: Non-TemporalSandboxClient in run_config.sandbox.client + try: + agent = SandboxAgent[None](name="sandbox") + await Runner.run( + starting_agent=agent, + input="hello", + run_config=RunConfig( + sandbox=SandboxRunConfig(client=object()), # type: ignore[arg-type] + ), + ) + return "FAIL: wrong-client should have raised" + except ValueError as e: + assert "temporal_sandbox_client(name)" in str(e) + + return "OK" + + +async def test_sandbox_validation_errors(client: Client): + """All sandbox configuration errors should be caught immediately in the workflow.""" + async with AgentEnvironment(model=_mock_model()) as env: + client = env.applied_on_client(client) + async with new_worker( + client, + SandboxValidationWorkflow, + workflow_failure_exception_types=[ValueError, AssertionError], + ) as worker: + result = await client.execute_workflow( + SandboxValidationWorkflow.run, + id=f"sandbox-validation-{uuid.uuid4()}", + task_queue=worker.task_queue, + execution_timeout=timedelta(seconds=10), + ) + assert result == "OK" + + +# ── Mock sandbox infrastructure for delegation tests ── + + +class TestSessionState(SandboxSessionState): + """Concrete ``SandboxSessionState`` subclass for tests that don't need a real backend.""" + + __test__ = False + type: Literal["test"] = "test" # type: ignore + + +class _MockSandboxSession(BaseSandboxSession): + """Minimal mock session that tracks calls and returns canned results.""" + + def __init__(self, manifest: Manifest | None = None) -> None: + self.state = TestSessionState( + manifest=manifest or Manifest(), + snapshot=NoopSnapshot(id=str(uuid.uuid4())), + ) + self.exec_calls: list[tuple] = [] + self.read_calls: list[Path] = [] + self.write_calls: list[tuple[Path, bytes]] = [] + self.running_calls: int = 0 + self.start_calls: int = 0 + self.stop_calls: int = 0 + self.shutdown_calls: int = 0 + self.persist_workspace_calls: int = 0 + self.hydrate_workspace_calls: int = 0 + + async def start(self) -> None: + self.start_calls += 1 + + async def stop(self) -> None: + self.stop_calls += 1 + + async def shutdown(self) -> None: + self.shutdown_calls += 1 + + async def running(self) -> bool: + self.running_calls += 1 + return True + + async def _exec_internal( + self, + *command: str | Path, + timeout: float | None = None, + ) -> ExecResult: + self.exec_calls.append((command, timeout)) + return ExecResult(stdout=b"ok\n", stderr=b"", exit_code=0) + + async def read(self, path: Path, *, user: Any = None) -> io.IOBase: # type: ignore[reportUnusedParameter] + self.read_calls.append(path) + return io.BytesIO(b"file-content") + + async def write(self, path: Path, data: io.IOBase, *, user: Any = None) -> None: # type: ignore[reportUnusedParameter] + self.write_calls.append((path, data.read())) + + async def persist_workspace(self) -> io.IOBase: + self.persist_workspace_calls += 1 + return io.BytesIO(b"workspace-archive") + + async def hydrate_workspace(self, data: io.IOBase) -> None: + self.hydrate_workspace_calls += 1 + + def supports_pty(self) -> bool: + return False + + +class _MockSandboxClient(BaseSandboxClient[BaseSandboxClientOptions | None]): + """Mock client that tracks create/resume/delete calls and delegates to a mock session.""" + + backend_id = "mock" + supports_default_options = True + + def __init__(self, session: _MockSandboxSession | None = None) -> None: + self.inner_session = session or _MockSandboxSession() + self.session = self._wrap_session(self.inner_session) + self.create_calls: int = 0 + self.resume_calls: int = 0 + self.delete_calls: int = 0 + + async def create( + self, + *, + snapshot: Any = None, + manifest: Manifest | None = None, + options: BaseSandboxClientOptions | None = None, + ) -> SandboxSession: + self.create_calls += 1 + if manifest is not None: + self.inner_session.state.manifest = manifest + return self.session + + async def resume(self, state: SandboxSessionState) -> SandboxSession: + self.resume_calls += 1 + self.inner_session.state = state + return self.session + + async def delete(self, session: SandboxSession) -> SandboxSession: + self.delete_calls += 1 + return session + + def deserialize_session_state(self, payload: dict[str, Any]) -> SandboxSessionState: + return SandboxSessionState.model_validate(payload) + + +# ── SandboxClientProvider unit tests (delegation) ── + + +@pytest.fixture +def mock_client() -> _MockSandboxClient: + return _MockSandboxClient() + + +@pytest.fixture +def sandbox_activities(mock_client: _MockSandboxClient) -> SandboxClientProvider: + return SandboxClientProvider("mock", mock_client) + + +def _make_state(manifest: Manifest | None = None) -> TestSessionState: + return TestSessionState( + manifest=manifest or Manifest(), + snapshot=NoopSnapshot(id=str(uuid.uuid4())), + ) + + +def _activity_map( + sandbox_activities: SandboxClientProvider, +) -> dict[str, Any]: + """Build a short-name → callable dict from all() for easy test dispatch.""" + return { + act.__temporal_activity_definition.name: act # type: ignore[attr-defined, union-attr] + for act in sandbox_activities._get_activities() + } + + +async def test_activities_create_session_delegates( + sandbox_activities: SandboxClientProvider, + mock_client: _MockSandboxClient, +): + """create_session activity should delegate to the real client's create().""" + acts = _activity_map(sandbox_activities) + args = CreateSessionArgs( + snapshot_spec=None, + manifest=Manifest(), + client_options=None, + ) + result = await acts["mock-sandbox_client_create"](args) + assert mock_client.create_calls == 1 + assert result.state is not None + assert isinstance(result.supports_pty, bool) + + +async def test_activities_resume_session_delegates( + sandbox_activities: SandboxClientProvider, + mock_client: _MockSandboxClient, +): + """resume_session activity should delegate to the real client's resume().""" + acts = _activity_map(sandbox_activities) + state = _make_state() + args = ResumeSessionArgs(state=state) + result = await acts["mock-sandbox_client_resume"](args) + assert mock_client.resume_calls == 1 + assert result.state is not None + + +async def test_activities_exec_delegates( + sandbox_activities: SandboxClientProvider, + mock_client: _MockSandboxClient, +): + """exec activity should delegate to the real session's exec().""" + acts = _activity_map(sandbox_activities) + # First create a session so the activities cache is populated + await acts["mock-sandbox_client_create"]( + CreateSessionArgs(snapshot_spec=None, manifest=Manifest(), client_options=None) + ) + state = mock_client.inner_session.state + + args = ExecArgs(state=state, command=["echo", "hello"], timeout=10.0, shell=True) + result = await acts["mock-sandbox_session_exec"](args) + assert result.stdout == b"ok\n" + assert result.stderr == b"" + assert result.exit_code == 0 + assert len(mock_client.inner_session.exec_calls) == 1 + + +async def test_activities_read_delegates( + sandbox_activities: SandboxClientProvider, + mock_client: _MockSandboxClient, +): + """read activity should delegate to the real session's read().""" + acts = _activity_map(sandbox_activities) + await acts["mock-sandbox_client_create"]( + CreateSessionArgs(snapshot_spec=None, manifest=Manifest(), client_options=None) + ) + state = mock_client.inner_session.state + + args = ReadArgs(state=state, path="/tmp/test.txt") + result = await acts["mock-sandbox_session_read"](args) + assert result.data == b"file-content" + assert len(mock_client.inner_session.read_calls) == 1 + + +async def test_activities_write_delegates( + sandbox_activities: SandboxClientProvider, + mock_client: _MockSandboxClient, +): + """write activity should delegate to the real session's write().""" + acts = _activity_map(sandbox_activities) + await acts["mock-sandbox_client_create"]( + CreateSessionArgs(snapshot_spec=None, manifest=Manifest(), client_options=None) + ) + state = mock_client.inner_session.state + + args = WriteArgs(state=state, path="/tmp/out.txt", data=b"written-data") + await acts["mock-sandbox_session_write"](args) + assert len(mock_client.inner_session.write_calls) == 1 + assert mock_client.inner_session.write_calls[0][1] == b"written-data" + + +async def test_activities_running_delegates( + sandbox_activities: SandboxClientProvider, + mock_client: _MockSandboxClient, +): + """running activity should delegate to the real session's running().""" + acts = _activity_map(sandbox_activities) + await acts["mock-sandbox_client_create"]( + CreateSessionArgs(snapshot_spec=None, manifest=Manifest(), client_options=None) + ) + state = mock_client.inner_session.state + + args = RunningArgs(state=state) + result = await acts["mock-sandbox_session_running"](args) + assert result.is_running is True + assert mock_client.inner_session.running_calls == 1 + + +async def test_activities_client_delete_delegates( + sandbox_activities: SandboxClientProvider, + mock_client: _MockSandboxClient, +): + """client_delete activity should delegate to the real client's delete().""" + acts = _activity_map(sandbox_activities) + await acts["mock-sandbox_client_create"]( + CreateSessionArgs(snapshot_spec=None, manifest=Manifest(), client_options=None) + ) + state = mock_client.inner_session.state + + args = StopArgs(state=state) + await acts["mock-sandbox_client_delete"](args) + + assert mock_client.delete_calls == 1 + + +async def test_activities_session_shutdown_clears_cache( + sandbox_activities: SandboxClientProvider, + mock_client: _MockSandboxClient, +): + """session_shutdown activity should call session.shutdown() and evict from cache.""" + acts = _activity_map(sandbox_activities) + await acts["mock-sandbox_client_create"]( + CreateSessionArgs(snapshot_spec=None, manifest=Manifest(), client_options=None) + ) + state = mock_client.inner_session.state + session_key = str(state.session_id) + + # Session should be cached + assert session_key in sandbox_activities._sessions + + args = StopArgs(state=state) + await acts["mock-sandbox_session_shutdown"](args) + + assert mock_client.inner_session.shutdown_calls == 1 + # Session should be evicted from cache + assert session_key not in sandbox_activities._sessions + + +async def test_activities_session_shutdown_noop_for_unknown_session( + sandbox_activities: SandboxClientProvider, +): + """session_shutdown should be a no-op if the session isn't in the cache.""" + acts = _activity_map(sandbox_activities) + state = _make_state() + args = StopArgs(state=state) + # Should not raise + await acts["mock-sandbox_session_shutdown"](args) + + +async def test_activities_session_caching( + sandbox_activities: SandboxClientProvider, + mock_client: _MockSandboxClient, +): + """Multiple operations on the same session should reuse the cached session.""" + acts = _activity_map(sandbox_activities) + await acts["mock-sandbox_client_create"]( + CreateSessionArgs(snapshot_spec=None, manifest=Manifest(), client_options=None) + ) + state = mock_client.inner_session.state + + # Multiple exec calls should not trigger additional resume calls + await acts["mock-sandbox_session_exec"]( + ExecArgs(state=state, command=["cmd1"], shell=True) + ) + await acts["mock-sandbox_session_exec"]( + ExecArgs(state=state, command=["cmd2"], shell=True) + ) + assert mock_client.resume_calls == 0 + assert len(mock_client.inner_session.exec_calls) == 2 + + +async def test_activities_all_returns_all_activity_methods( + sandbox_activities: SandboxClientProvider, +): + """all() should return all 14 activity callables with prefixed names.""" + activities = sandbox_activities._get_activities() + assert len(activities) == 14 + # Verify they are all activity-decorated callables with prefixed names + activity_names = set() + for act in activities: + assert hasattr(act, "__temporal_activity_definition") + activity_names.add(act.__temporal_activity_definition.name) # type: ignore[union-attr] + expected = { + "mock-sandbox_client_create", + "mock-sandbox_client_resume", + "mock-sandbox_client_delete", + "mock-sandbox_session_exec", + "mock-sandbox_session_read", + "mock-sandbox_session_write", + "mock-sandbox_session_running", + "mock-sandbox_session_persist_workspace", + "mock-sandbox_session_hydrate_workspace", + "mock-sandbox_session_pty_exec_start", + "mock-sandbox_session_pty_write_stdin", + "mock-sandbox_session_start", + "mock-sandbox_session_stop", + "mock-sandbox_session_shutdown", + } + assert activity_names == expected + + +async def test_multiple_providers_register_distinct_activities(): + """Multiple SandboxClientProviders should produce distinct prefixed activity sets.""" + client1 = _MockSandboxClient() + client2 = _MockSandboxClient() + provider1 = SandboxClientProvider("daytona", client1) + provider2 = SandboxClientProvider("local", client2) + + activities1 = provider1._get_activities() + activities2 = provider2._get_activities() + + names1 = {a.__temporal_activity_definition.name for a in activities1} # type: ignore + names2 = {a.__temporal_activity_definition.name for a in activities2} # type: ignore + + # No overlap + assert names1.isdisjoint(names2) + # Both have 14 activities + assert len(names1) == 14 + assert len(names2) == 14 + # Verify prefixes + assert all( + n.startswith("daytona-sandbox_client_") + or n.startswith("daytona-sandbox_session_") + for n in names1 + ) + assert all( + n.startswith("local-sandbox_client_") or n.startswith("local-sandbox_session_") + for n in names2 + ) + + +# ── End-to-end test: Runner + SandboxAgent through Temporal activities ── + + +class _TestSandboxCapability(Capability): + """Minimal capability exposing exec, read, and write via FunctionTools.""" + + def __init__(self) -> None: + super().__init__(type="test_sandbox") + self._session: BaseSandboxSession | None = None + + def bind(self, session: BaseSandboxSession) -> None: + self._session = session + + def tools(self) -> list[Tool]: + session = self._session + + async def _run_cmd(ctx: Any, args: str) -> str: # type: ignore[reportUnusedParameter] + import json + + cmd = json.loads(args)["cmd"] + result = await session.exec(cmd, shell=True) # type: ignore[union-attr] + return result.stdout.decode() + + async def _read_file(ctx: Any, args: str) -> str: # type: ignore[reportUnusedParameter] + import json + + path = json.loads(args)["path"] + handle = await session.read(Path(path)) # type: ignore[union-attr] + return handle.read().decode() + + async def _write_file(ctx: Any, args: str) -> str: # type: ignore[reportUnusedParameter] + import json + + parsed = json.loads(args) + await session.write( # type: ignore[union-attr] + Path(parsed["path"]), io.BytesIO(parsed["data"].encode()) + ) + return "ok" + + return [ + FunctionTool( + name="run_command", + description="Run a shell command", + params_json_schema={ + "type": "object", + "properties": {"cmd": {"type": "string"}}, + "required": ["cmd"], + }, + on_invoke_tool=_run_cmd, + ), + FunctionTool( + name="read_file", + description="Read a file", + params_json_schema={ + "type": "object", + "properties": {"path": {"type": "string"}}, + "required": ["path"], + }, + on_invoke_tool=_read_file, + ), + FunctionTool( + name="write_file", + description="Write a file", + params_json_schema={ + "type": "object", + "properties": { + "path": {"type": "string"}, + "data": {"type": "string"}, + }, + "required": ["path", "data"], + }, + on_invoke_tool=_write_file, + ), + ] + + +class _TestSandboxClientOptions(BaseSandboxClientOptions): + type: str = "test" # type: ignore[reportIncompatibleVariableOverride] + + +@workflow.defn +class SandboxE2EWorkflow: + @workflow.run + async def run(self) -> str: + agent = SandboxAgent[None]( + name="sandbox-e2e", capabilities=[_TestSandboxCapability()] + ) + result = await Runner.run( + starting_agent=agent, + input="run a command", + run_config=RunConfig( + sandbox=SandboxRunConfig( + client=temporal_sandbox_client("mock"), + options=_TestSandboxClientOptions(), + ), + ), + ) + return result.final_output + + +async def test_sandbox_e2e_runner(client: Client): + """End-to-end: Runner.run() with SandboxAgent exercises the full sandbox + lifecycle (create, start, stop, shutdown, delete) through Temporal activities.""" + mock_session = _MockSandboxSession() + mock_sandbox_client = _MockSandboxClient(mock_session) + + mock_model = TestModel.returning_responses( + [ + ResponseBuilders.tool_call('{"cmd": "echo hello"}', "run_command"), + ResponseBuilders.tool_call('{"path": "/tmp/test.txt"}', "read_file"), + ResponseBuilders.tool_call( + '{"path": "/tmp/out.txt", "data": "hello"}', "write_file" + ), + ResponseBuilders.output_message("Done."), + ] + ) + + plugin = OpenAIAgentsPlugin( + model_params=ModelActivityParameters( + start_to_close_timeout=timedelta(seconds=30), + ), + model_provider=TestModelProvider(mock_model), + sandbox_clients=[SandboxClientProvider("mock", mock_sandbox_client)], + ) + + new_config = client.config() + new_config["plugins"] = [plugin] + test_client = Client(**new_config) + + async with new_worker( + test_client, + SandboxE2EWorkflow, + workflow_failure_exception_types=[Exception], + ) as worker: + result = await test_client.execute_workflow( + SandboxE2EWorkflow.run, + id=f"sandbox-e2e-{uuid.uuid4()}", + task_queue=worker.task_queue, + execution_timeout=timedelta(seconds=10), + ) + + assert result == "Done." + # Full sandbox lifecycle exercised through Temporal activities + assert mock_sandbox_client.create_calls == 1, "client.create() not called" + assert mock_session.start_calls == 1, "session.start() not called" + assert len(mock_session.exec_calls) >= 1, "session.exec() not called" + assert len(mock_session.read_calls) >= 1, "session.read() not called" + assert len(mock_session.write_calls) >= 1, "session.write() not called" + assert mock_session.stop_calls >= 1, "session.stop() not called" + assert mock_session.shutdown_calls >= 1, "session.shutdown() not called" + assert mock_sandbox_client.delete_calls == 1, "client.delete() not called" + + +# ── JsonSafeBytes lossless serialization tests ── + +# Payloads that exercise edge cases for bytes → JSON → bytes roundtrip. +_BYTE_PAYLOADS = [ + pytest.param(b"", id="empty"), + pytest.param(b"hello world", id="ascii"), + pytest.param(b"\xc3\xa9\xc3\xa0", id="valid-utf8"), # éà + pytest.param(bytes(range(256)), id="all-byte-values"), + pytest.param(b"\xff\xfe\x80\x90\x00\x01", id="non-utf8-binary"), + pytest.param(b"ok\nWarning: \xff\xfe binary \x80\x90\x00\x01", id="mixed"), + pytest.param(b"\x00\x00\x00", id="null-bytes"), +] + + +def _roundtrip(model_cls: Any, **kwargs: Any) -> Any: + """Serialize a model to JSON via pydantic_core and deserialize back.""" + json_bytes = to_json(model_cls(**kwargs)) + return TypeAdapter(model_cls).validate_json(json_bytes) + + +@pytest.mark.parametrize("payload", _BYTE_PAYLOADS) +def test_exec_result_bytes_roundtrip(payload: bytes): + """ExecResult.stdout/stderr must survive a JSON roundtrip unchanged.""" + restored = _roundtrip(ExecResultModel, stdout=payload, stderr=payload, exit_code=1) + assert restored.stdout == payload + assert restored.stderr == payload + assert restored.exit_code == 1 + + +@pytest.mark.parametrize("payload", _BYTE_PAYLOADS) +def test_pty_exec_update_result_bytes_roundtrip(payload: bytes): + """PtyExecUpdateResult.output must survive a JSON roundtrip unchanged.""" + restored = _roundtrip( + PtyExecUpdateResult, + process_id=1, + output=payload, + exit_code=0, + original_token_count=None, + ) + assert restored.output == payload + + +@pytest.mark.parametrize("payload", _BYTE_PAYLOADS) +def test_read_result_bytes_roundtrip(payload: bytes): + """ReadResult.data must survive a JSON roundtrip unchanged.""" + restored = _roundtrip(ReadResult, data=payload) + assert restored.data == payload + + +@pytest.mark.parametrize("payload", _BYTE_PAYLOADS) +def test_persist_workspace_result_bytes_roundtrip(payload: bytes): + """PersistWorkspaceResult.data must survive a JSON roundtrip unchanged.""" + restored = _roundtrip(PersistWorkspaceResult, data=payload) + assert restored.data == payload + + +@pytest.mark.parametrize("payload", _BYTE_PAYLOADS) +def test_write_args_bytes_roundtrip(payload: bytes): + """WriteArgs.data must survive a JSON roundtrip unchanged (workflow → activity).""" + restored = _roundtrip(WriteArgs, state=_make_state(), path="/tmp/f", data=payload) + assert restored.data == payload + + +@pytest.mark.parametrize("payload", _BYTE_PAYLOADS) +def test_hydrate_workspace_args_bytes_roundtrip(payload: bytes): + """HydrateWorkspaceArgs.data must survive a JSON roundtrip unchanged.""" + restored = _roundtrip(HydrateWorkspaceArgs, state=_make_state(), data=payload) + assert restored.data == payload diff --git a/tests/contrib/openai_agents/test_openai_tracing.py b/tests/contrib/openai_agents/test_openai_tracing.py index 5414f7916..7613ae49e 100644 --- a/tests/contrib/openai_agents/test_openai_tracing.py +++ b/tests/contrib/openai_agents/test_openai_tracing.py @@ -117,25 +117,31 @@ def paired_span(a: tuple[Span[Any], bool], b: tuple[Span[Any], bool]) -> None: == "Research manager" ) - # Initial planner spans - There are only 3 because we don't make an actual model call - paired_span(processor.span_events[4], processor.span_events[9]) + # Initial planner spans - task wraps agent, agent wraps turn, turn wraps activity + paired_span(processor.span_events[4], processor.span_events[13]) + assert processor.span_events[4][0].span_data.export().get("name") == "task" + + paired_span(processor.span_events[5], processor.span_events[12]) assert ( - processor.span_events[4][0].span_data.export().get("name") == "PlannerAgent" + processor.span_events[5][0].span_data.export().get("name") == "PlannerAgent" ) - paired_span(processor.span_events[5], processor.span_events[8]) + paired_span(processor.span_events[6], processor.span_events[11]) + assert processor.span_events[6][0].span_data.export().get("name") == "turn" + + paired_span(processor.span_events[7], processor.span_events[10]) assert ( - processor.span_events[5][0].span_data.export().get("name") + processor.span_events[7][0].span_data.export().get("name") == "temporal:startActivity" ) - paired_span(processor.span_events[6], processor.span_events[7]) + paired_span(processor.span_events[8], processor.span_events[9]) assert ( - processor.span_events[6][0].span_data.export().get("name") + processor.span_events[8][0].span_data.export().get("name") == "temporal:executeActivity" ) - for span, start in processor.span_events[10:-8]: + for span, start in processor.span_events[14:-12]: span_data = span.span_data.export() # All spans should be closed @@ -145,15 +151,26 @@ def paired_span(a: tuple[Span[Any], bool], b: tuple[Span[Any], bool]) -> None: for (s, s_start) in processor.span_events ) - # Start activity is always parented to an agent + # Start activity is always parented to a turn span, which is parented to an agent if span_data.get("name") == "temporal:startActivity": - parents = [ + turn_spans = [ s for (s, _) in processor.span_events if s.span_id == span.parent_id ] + assert len(turn_spans) == 2 assert ( - len(parents) == 2 - and parents[0].span_data.export()["type"] == "agent" + turn_spans[0] + .span_data.export() + .get("data", {}) + .get("sdk_span_type") + == "turn" ) + agent_spans = [ + s + for (s, _) in processor.span_events + if s.span_id == turn_spans[0].parent_id + ] + assert len(agent_spans) == 2 + assert agent_spans[0].span_data.export()["type"] == "agent" # Execute is parented to start if span_data.get("name") == "temporal:executeActivity": @@ -166,21 +183,28 @@ def paired_span(a: tuple[Span[Any], bool], b: tuple[Span[Any], bool]) -> None: == "temporal:startActivity" ) - # Final writer spans - There are only 3 because we don't make an actual model call - paired_span(processor.span_events[-8], processor.span_events[-3]) + # Final writer spans - task wraps agent, agent wraps turn, turn wraps activity + paired_span(processor.span_events[-12], processor.span_events[-3]) + assert processor.span_events[-12][0].span_data.export().get("name") == "task" + + paired_span(processor.span_events[-11], processor.span_events[-4]) assert ( - processor.span_events[-8][0].span_data.export().get("name") == "WriterAgent" + processor.span_events[-11][0].span_data.export().get("name") + == "WriterAgent" ) - paired_span(processor.span_events[-7], processor.span_events[-4]) + paired_span(processor.span_events[-10], processor.span_events[-5]) + assert processor.span_events[-10][0].span_data.export().get("name") == "turn" + + paired_span(processor.span_events[-9], processor.span_events[-6]) assert ( - processor.span_events[-7][0].span_data.export().get("name") + processor.span_events[-9][0].span_data.export().get("name") == "temporal:startActivity" ) - paired_span(processor.span_events[-6], processor.span_events[-5]) + paired_span(processor.span_events[-8], processor.span_events[-7]) assert ( - processor.span_events[-6][0].span_data.export().get("name") + processor.span_events[-8][0].span_data.export().get("name") == "temporal:executeActivity" ) @@ -702,31 +726,43 @@ async def test_otel_tracing_in_runner( search_span.parent.span_id == research_span.context.span_id ), "Expected 'Search the web' to be child of 'Research manager' span" - # All search agent spans should be children of "Search the web" + # All search agent spans should be descendants of "Search the web" + # (the SDK now inserts a "task" span between "Search the web" and the agent) + span_by_id = {span.context.span_id: span for span in spans if span.context} search_agent_spans = [span for span in spans if "Search agent" in span.name] + + def is_descendant_of(child: ReadableSpan, ancestor_span_id: int) -> bool: + """Check if child is a descendant of the span with ancestor_span_id.""" + current: ReadableSpan | None = child + while current and current.parent: + if current.parent.span_id == ancestor_span_id: + return True + current = span_by_id.get(current.parent.span_id) + return False + for search_agent_span in search_agent_spans: assert ( search_agent_span.parent is not None ), f"Search agent span '{search_agent_span.name}' should have a parent" - assert ( - search_agent_span.parent.span_id == search_span.context.span_id - ), f"Expected all 'Search agent' spans to be children of 'Search the web' span" + assert is_descendant_of( + search_agent_span, search_span.context.span_id + ), f"Expected all 'Search agent' spans to be descendants of 'Search the web' span" - # PlannerAgent and WriterAgent should be children of research manager + # PlannerAgent and WriterAgent should be descendants of research manager planner_spans = [span for span in spans if "PlannerAgent" in span.name] writer_spans = [span for span in spans if "WriterAgent" in span.name] for planner_span in planner_spans: assert planner_span.parent is not None, "PlannerAgent span should have a parent" - assert ( - planner_span.parent.span_id == research_span.context.span_id - ), "Expected 'PlannerAgent' to be child of 'Research manager' span" + assert is_descendant_of( + planner_span, research_span.context.span_id + ), "Expected 'PlannerAgent' to be descendant of 'Research manager' span" for writer_span in writer_spans: assert writer_span.parent is not None, "WriterAgent span should have a parent" - assert ( - writer_span.parent.span_id == research_span.context.span_id - ), "Expected 'WriterAgent' to be child of 'Research manager' span" + assert is_descendant_of( + writer_span, research_span.context.span_id + ), "Expected 'WriterAgent' to be descendant of 'Research manager' span" @workflow.defn diff --git a/uv.lock b/uv.lock index 29a90e6f1..bdc25a507 100644 --- a/uv.lock +++ b/uv.lock @@ -1864,15 +1864,12 @@ wheels = [ ] [[package]] -name = "griffe" -version = "1.15.0" +name = "griffelib" +version = "2.0.2" source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "colorama" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/0d/0c/3a471b6e31951dce2360477420d0a8d1e00dea6cf33b70f3e8c3ab6e28e1/griffe-1.15.0.tar.gz", hash = "sha256:7726e3afd6f298fbc3696e67958803e7ac843c1cfe59734b6251a40cdbfb5eea", size = 424112, upload-time = "2025-11-10T15:03:15.52Z" } +sdist = { url = "https://files.pythonhosted.org/packages/9d/82/74f4a3310cdabfbb10da554c3a672847f1ed33c6f61dd472681ce7f1fe67/griffelib-2.0.2.tar.gz", hash = "sha256:3cf20b3bc470e83763ffbf236e0076b1211bac1bc67de13daf494640f2de707e", size = 166461, upload-time = "2026-03-27T11:34:51.091Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/9c/83/3b1d03d36f224edded98e9affd0467630fc09d766c0e56fb1498cbb04a9b/griffe-1.15.0-py3-none-any.whl", hash = "sha256:6f6762661949411031f5fcda9593f586e6ce8340f0ba88921a0f2ef7a81eb9a3", size = 150705, upload-time = "2025-11-10T15:03:13.549Z" }, + { 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]] @@ -3301,20 +3298,21 @@ wheels = [ [[package]] name = "openai-agents" -version = "0.6.9" +version = "0.14.0" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "griffe" }, + { name = "griffelib" }, { name = "mcp" }, { name = "openai" }, { name = "pydantic" }, { name = "requests" }, { name = "types-requests" }, { name = "typing-extensions" }, + { name = "websockets" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/3a/e3/41f4d83df6b9080ccba444b79e150aa3b57182bcc0deeb6adabe08678407/openai_agents-0.6.9.tar.gz", hash = "sha256:e55623827b4a1b11d66ec0084bd2b9ea2c6d60f233e04547803af433967e2fdb", size = 2152399, upload-time = "2026-01-20T01:57:00.04Z" } +sdist = { url = "https://files.pythonhosted.org/packages/f2/3c/965968ab53d6afc1d6e4223b6b2e8cdfca15f39fdcc20cfe5dd526ea99f4/openai_agents-0.14.0.tar.gz", hash = "sha256:d82cbafbeea5b189712c243664552268df16082fa14f1778af40f706eb976692", size = 5192284, upload-time = "2026-04-15T17:12:10.191Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/a7/9f/1cb6d64487c185c8e775c66314e5c047ca307b3bcd6c5edb97af6c0b5d6e/openai_agents-0.6.9-py3-none-any.whl", hash = "sha256:9e05a96b7610a7a89d6fd9ba379ff840a1aebca150eebcc4d505743ee458f50b", size = 284423, upload-time = "2026-01-20T01:56:57.54Z" }, + { url = "https://files.pythonhosted.org/packages/8d/3e/0be9a884d3b770114572e0be101ab8adb04a7f1a99620261e7393b72a655/openai_agents-0.14.0-py3-none-any.whl", hash = "sha256:5a1dad74de95970efbf4a3f89dfd50d6a22202d9105b81d7abb25a0be3d493c7", size = 795734, upload-time = "2026-04-15T17:12:08.001Z" }, ] [package.optional-dependencies] @@ -5101,7 +5099,7 @@ requires-dist = [ { name = "langsmith", marker = "extra == 'langsmith'", specifier = ">=0.7.0,<0.8" }, { name = "mcp", marker = "extra == 'openai-agents'", specifier = ">=1.9.4,<2" }, { name = "nexus-rpc", specifier = "==1.4.0" }, - { name = "openai-agents", marker = "extra == 'openai-agents'", specifier = ">=0.3,<0.7" }, + { name = "openai-agents", marker = "extra == 'openai-agents'", specifier = ">=0.14.0" }, { name = "opentelemetry-api", marker = "extra == 'lambda-worker-otel'", specifier = ">=1.11.1,<2" }, { name = "opentelemetry-api", marker = "extra == 'opentelemetry'", specifier = ">=1.11.1,<2" }, { name = "opentelemetry-exporter-otlp-proto-grpc", marker = "extra == 'lambda-worker-otel'", specifier = ">=1.11.1,<2" }, @@ -5131,8 +5129,8 @@ dev = [ { name = "moto", extras = ["s3", "server"], specifier = ">=5" }, { name = "mypy", specifier = "==1.18.2" }, { name = "mypy-protobuf", specifier = ">=3.3.0,<4" }, - { name = "openai-agents", marker = "python_full_version >= '3.14'", specifier = ">=0.3,<0.7" }, - { name = "openai-agents", extras = ["litellm"], marker = "python_full_version < '3.14'", specifier = ">=0.3,<0.7" }, + { name = "openai-agents", marker = "python_full_version >= '3.14'", specifier = ">=0.14.0" }, + { name = "openai-agents", extras = ["litellm"], marker = "python_full_version < '3.14'", specifier = ">=0.14.0" }, { name = "openinference-instrumentation-google-adk", specifier = ">=0.1.8" }, { name = "openinference-instrumentation-openai-agents", specifier = ">=0.1.0" }, { name = "opentelemetry-exporter-otlp-proto-grpc", specifier = ">=1.11.1,<2" }, From e62a7f1db276db899d3ebdf4ebe3e1d35f2e090c Mon Sep 17 00:00:00 2001 From: tconley1428 Date: Thu, 16 Apr 2026 13:00:07 -0700 Subject: [PATCH 049/226] Harden flaky workflow tests (#1456) * Harden flaky workflow tests * Fix additional time-skipping test flakes * Fix linting --- tests/worker/test_workflow.py | 37 +++++++++++++++++++++++------------ 1 file changed, 25 insertions(+), 12 deletions(-) diff --git a/tests/worker/test_workflow.py b/tests/worker/test_workflow.py index 428ea3456..5d7e22857 100644 --- a/tests/worker/test_workflow.py +++ b/tests/worker/test_workflow.py @@ -3397,7 +3397,7 @@ def cancel_timer(self) -> None: async def test_workflow_cancel_signal_and_timer_fired_in_same_task( - client: Client, env: WorkflowEnvironment + env: WorkflowEnvironment, ): # This test only works when we support time skipping if not env.supports_time_skipping: @@ -3411,10 +3411,12 @@ async def test_workflow_cancel_signal_and_timer_fired_in_same_task( # Start worker for 30 mins. Need to disable workflow cache since we # restart the worker and don't want to pay the sticky queue penalty. async with new_worker( - client, CancelSignalAndTimerFiredInSameTaskWorkflow, max_cached_workflows=0 + env.client, + CancelSignalAndTimerFiredInSameTaskWorkflow, + max_cached_workflows=0, ) as worker: task_queue = worker.task_queue - handle = await client.start_workflow( + handle = await env.client.start_workflow( CancelSignalAndTimerFiredInSameTaskWorkflow.run, id=f"workflow-{uuid.uuid4()}", task_queue=task_queue, @@ -3432,7 +3434,7 @@ async def test_workflow_cancel_signal_and_timer_fired_in_same_task( # Start worker again and wait for workflow completion async with new_worker( - client, + env.client, CancelSignalAndTimerFiredInSameTaskWorkflow, task_queue=task_queue, max_cached_workflows=0, @@ -4905,11 +4907,12 @@ async def test_workflow_timeout_support(client: Client, approach: str): @workflow.defn class BuildIDInfoWorkflow: + do_continue = False do_finish = False @workflow.run async def run(self): - await asyncio.sleep(1) + await workflow.wait_condition(lambda: self.do_continue) if workflow.info().get_current_build_id() == "1.0": await workflow.execute_activity( say_hello, "yo", schedule_to_close_timeout=timedelta(seconds=5) @@ -4920,6 +4923,10 @@ async def run(self): def get_build_id(self) -> str: return workflow.info().get_current_build_id() + @workflow.signal + async def continue_run(self): + self.do_continue = True + @workflow.signal async def finish(self): self.do_finish = True @@ -4964,9 +4971,11 @@ async def test_workflow_current_build_id_appropriately_set( ) as worker: bid = await handle.query(BuildIDInfoWorkflow.get_build_id) assert bid == "1.0" + await handle.signal(BuildIDInfoWorkflow.continue_run) + await assert_eq_eventually( + "1.1", lambda: handle.query(BuildIDInfoWorkflow.get_build_id) + ) await handle.signal(BuildIDInfoWorkflow.finish) - bid = await handle.query(BuildIDInfoWorkflow.get_build_id) - assert bid == "1.1" await handle.result() bid = await handle.query(BuildIDInfoWorkflow.get_build_id) assert bid == "1.1" @@ -6505,19 +6514,23 @@ async def waiting() -> bool: @workflow.defn class WorkflowSleepWorkflow: @workflow.run - async def run(self) -> None: + async def run(self) -> float: + start_time = workflow.time() await workflow.sleep(1) + return workflow.time() - start_time -async def test_workflow_sleep(client: Client): +async def test_workflow_sleep(client: Client, env: WorkflowEnvironment): async with new_worker(client, WorkflowSleepWorkflow) as worker: start_time = datetime.now() - await client.execute_workflow( + workflow_elapsed = await client.execute_workflow( WorkflowSleepWorkflow.run, id=f"workflow-{uuid.uuid4()}", task_queue=worker.task_queue, ) - assert (datetime.now() - start_time) >= timedelta(seconds=1) + assert workflow_elapsed >= 1 + if not env.supports_time_skipping: + assert (datetime.now() - start_time) >= timedelta(seconds=1) @workflow.defn @@ -8558,7 +8571,7 @@ async def execute_with_new_worker(*, disable_sandbox: bool) -> None: DisableLoggerSandbox.run, id=f"workflow-{uuid.uuid4()}", task_queue=worker.task_queue, - run_timeout=timedelta(seconds=1), + run_timeout=timedelta(seconds=5), retry_policy=RetryPolicy(maximum_attempts=1), ) From 6948be180cb5abaf76c67dc048dbb20ba089ec82 Mon Sep 17 00:00:00 2001 From: tconley1428 Date: Fri, 17 Apr 2026 09:53:00 -0700 Subject: [PATCH 050/226] Pin GitHub Actions and cap uv deps (#1458) * Pin GitHub Actions and cap uv deps * Exclude reusable workflows from SHA pinning --- .github/workflows/build-binaries.yml | 12 ++-- .github/workflows/ci.yml | 56 +++++++++---------- .../workflows/nightly-throughput-stress.yml | 24 ++++---- .github/workflows/run-bench.yml | 12 ++-- pyproject.toml | 2 + 5 files changed, 54 insertions(+), 52 deletions(-) diff --git a/.github/workflows/build-binaries.yml b/.github/workflows/build-binaries.yml index ab0c3ed69..a28ae4258 100644 --- a/.github/workflows/build-binaries.yml +++ b/.github/workflows/build-binaries.yml @@ -30,10 +30,10 @@ jobs: package-suffix: windows-amd64 runs-on: ${{ matrix.runsOn || matrix.os }} steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 with: submodules: recursive - - uses: actions/setup-python@v5 + - uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5 with: python-version: "3.14" @@ -41,12 +41,12 @@ jobs: # command to build with cibuildwheel which uses rustup install defined # in pyproject.toml) - if: ${{ runner.os != 'Linux' }} - uses: dtolnay/rust-toolchain@stable + uses: dtolnay/rust-toolchain@29eef336d9b2848a0b548edc03f92a220660cdb8 # stable - if: ${{ runner.os != 'Linux' }} - uses: Swatinem/rust-cache@v2 + uses: Swatinem/rust-cache@42dc69e1aa15d09112580998cf2ef0119e2e91ae # v2 with: workspaces: temporalio/bridge -> target - - uses: astral-sh/setup-uv@v5 + - uses: astral-sh/setup-uv@e58605a9b6da7c637471fab8847a5e5a6b8df081 # v5 - run: uv sync --all-extras # Add the source dist only for Linux x64 for now @@ -73,7 +73,7 @@ jobs: ./.venv/$bindir/python -m pytest -s tests/worker/test_workflow.py -k test_workflow_hello # Upload dist - - uses: actions/upload-artifact@v4 + - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4 with: name: packages-${{ matrix.package-suffix }} path: dist diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4c07251ee..99a5f03f6 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -38,24 +38,24 @@ jobs: runsOn: macos-latest runs-on: ${{ matrix.runsOn || matrix.os }} steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 with: submodules: recursive - - uses: dtolnay/rust-toolchain@stable + - uses: dtolnay/rust-toolchain@29eef336d9b2848a0b548edc03f92a220660cdb8 # stable with: components: "clippy" - - uses: Swatinem/rust-cache@v2 + - uses: Swatinem/rust-cache@42dc69e1aa15d09112580998cf2ef0119e2e91ae # v2 with: workspaces: temporalio/bridge -> target - - uses: actions/setup-python@v5 + - uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5 with: python-version: ${{ matrix.pythonOverride || matrix.python }} - - uses: arduino/setup-protoc@v3 + - uses: arduino/setup-protoc@c65c819552d16ad3c9b72d9dfd5ba5237b9c906b # v3 with: # TODO(cretz): Can upgrade proto when https://github.com/arduino/setup-protoc/issues/99 fixed version: "23.x" repo-token: ${{ secrets.GITHUB_TOKEN }} - - uses: astral-sh/setup-uv@v5 + - uses: astral-sh/setup-uv@e58605a9b6da7c637471fab8847a5e5a6b8df081 # v5 - run: uv tool install poethepoet - run: uv sync --all-extras - run: poe bridge-lint @@ -75,7 +75,7 @@ jobs: env: OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} - name: "Upload junit-xml artifacts" - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4 if: always() with: name: junit-xml--${{github.run_id}}--${{github.run_attempt}}--${{ matrix.python }}--${{ matrix.os }} @@ -94,7 +94,7 @@ jobs: run: npx vercel deploy build/apidocs -t ${{ secrets.VERCEL_TOKEN }} --prod --yes # Confirm README ToC is generated properly - - uses: actions/setup-node@v4 + - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4 - name: Check generated README ToC if: ${{ matrix.docsTarget }} run: | @@ -105,22 +105,22 @@ jobs: timeout-minutes: 30 runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 with: submodules: recursive - - uses: dtolnay/rust-toolchain@stable - - uses: Swatinem/rust-cache@v2 + - uses: dtolnay/rust-toolchain@29eef336d9b2848a0b548edc03f92a220660cdb8 # stable + - uses: Swatinem/rust-cache@42dc69e1aa15d09112580998cf2ef0119e2e91ae # v2 with: workspaces: temporalio/bridge -> target - - uses: actions/setup-python@v5 + - uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5 with: python-version: "3.10" - - uses: arduino/setup-protoc@v3 + - uses: arduino/setup-protoc@c65c819552d16ad3c9b72d9dfd5ba5237b9c906b # v3 with: # TODO(cretz): Can upgrade proto when https://github.com/arduino/setup-protoc/issues/99 fixed version: "23.x" repo-token: ${{ secrets.GITHUB_TOKEN }} - - uses: astral-sh/setup-uv@v5 + - uses: astral-sh/setup-uv@e58605a9b6da7c637471fab8847a5e5a6b8df081 # v5 - run: uv tool install poethepoet - run: uv remove google-adk --optional google-adk - run: uv add --python 3.10 "protobuf<4" @@ -139,24 +139,24 @@ jobs: timeout-minutes: 30 runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 with: submodules: recursive - - uses: dtolnay/rust-toolchain@stable + - uses: dtolnay/rust-toolchain@29eef336d9b2848a0b548edc03f92a220660cdb8 # stable with: components: "clippy" - - uses: Swatinem/rust-cache@v2 + - uses: Swatinem/rust-cache@42dc69e1aa15d09112580998cf2ef0119e2e91ae # v2 with: workspaces: temporalio/bridge -> target - - uses: actions/setup-python@v5 + - uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5 with: python-version: "3.13" - - uses: arduino/setup-protoc@v3 + - uses: arduino/setup-protoc@c65c819552d16ad3c9b72d9dfd5ba5237b9c906b # v3 with: # TODO(cretz): Can upgrade proto when https://github.com/arduino/setup-protoc/issues/99 fixed version: "23.x" repo-token: ${{ secrets.GITHUB_TOKEN }} - - uses: astral-sh/setup-uv@v5 + - uses: astral-sh/setup-uv@e58605a9b6da7c637471fab8847a5e5a6b8df081 # v5 - run: uv tool install poethepoet - run: uv lock --upgrade - run: uv sync --all-extras @@ -166,7 +166,7 @@ jobs: - run: poe test -s --junit-xml=junit-xml/latest-deps.xml timeout-minutes: 15 - name: "Upload junit-xml artifacts" - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4 if: always() with: name: junit-xml--${{github.run_id}}--${{github.run_attempt}}--latest-deps--time-skipping @@ -179,22 +179,22 @@ jobs: timeout-minutes: 15 runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 with: submodules: recursive - - uses: dtolnay/rust-toolchain@stable - - uses: Swatinem/rust-cache@v2 + - uses: dtolnay/rust-toolchain@29eef336d9b2848a0b548edc03f92a220660cdb8 # stable + - uses: Swatinem/rust-cache@42dc69e1aa15d09112580998cf2ef0119e2e91ae # v2 with: workspaces: temporalio/bridge -> target - - uses: actions/setup-python@v5 + - uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5 with: python-version: "3.14" - - uses: arduino/setup-protoc@v3 + - uses: arduino/setup-protoc@c65c819552d16ad3c9b72d9dfd5ba5237b9c906b # v3 with: # TODO(cretz): Can upgrade proto when https://github.com/arduino/setup-protoc/issues/99 fixed version: "23.x" repo-token: ${{ secrets.GITHUB_TOKEN }} - - uses: astral-sh/setup-uv@v5 + - uses: astral-sh/setup-uv@e58605a9b6da7c637471fab8847a5e5a6b8df081 # v5 - run: uv tool install poethepoet - run: uv sync --all-extras - run: poe build-develop @@ -209,7 +209,7 @@ jobs: TEMPORAL_CLIENT_CERT: ${{ secrets.TEMPORAL_CLIENT_CERT }} TEMPORAL_CLIENT_KEY: ${{ secrets.TEMPORAL_CLIENT_KEY }} - name: "Upload junit-xml artifacts" - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4 if: always() with: name: junit-xml--${{github.run_id}}--${{github.run_attempt}}--cloud diff --git a/.github/workflows/nightly-throughput-stress.yml b/.github/workflows/nightly-throughput-stress.yml index b9a2314e0..78523f4f3 100644 --- a/.github/workflows/nightly-throughput-stress.yml +++ b/.github/workflows/nightly-throughput-stress.yml @@ -68,44 +68,44 @@ jobs: echo "==========================================" - name: Checkout SDK - uses: actions/checkout@v4 + uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 with: submodules: recursive - name: Checkout OMES - uses: actions/checkout@v4 + uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 with: repository: ${{ env.OMES_REPO }} ref: ${{ env.OMES_REF }} path: omes - name: Setup Go - uses: actions/setup-go@v5 + uses: actions/setup-go@40f1582b2485089dde7abd97c1529aa768e1baff # v5 with: go-version-file: omes/go.mod cache-dependency-path: omes/go.sum - name: Setup Rust - uses: dtolnay/rust-toolchain@stable + uses: dtolnay/rust-toolchain@29eef336d9b2848a0b548edc03f92a220660cdb8 # stable - name: Setup Rust cache - uses: Swatinem/rust-cache@v2 + uses: Swatinem/rust-cache@42dc69e1aa15d09112580998cf2ef0119e2e91ae # v2 with: workspaces: temporalio/bridge -> target - name: Setup Python - uses: actions/setup-python@v5 + uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5 with: python-version: "3.13" - name: Install protoc - uses: arduino/setup-protoc@v3 + uses: arduino/setup-protoc@c65c819552d16ad3c9b72d9dfd5ba5237b9c906b # v3 with: version: '23.x' repo-token: ${{ secrets.GITHUB_TOKEN }} - name: Setup uv - uses: astral-sh/setup-uv@v5 + uses: astral-sh/setup-uv@e58605a9b6da7c637471fab8847a5e5a6b8df081 # v5 - name: Install poethepoet run: uv tool install poethepoet @@ -117,7 +117,7 @@ jobs: run: poe build-develop - name: Install Temporal CLI - uses: temporalio/setup-temporal@v0 + uses: temporalio/setup-temporal@1059a504f87e7fa2f385e3fa40d1aa7e62f1c6ca # v0 - name: Install Prometheus run: | @@ -172,7 +172,7 @@ jobs: - name: Configure AWS credentials if: always() - uses: aws-actions/configure-aws-credentials@v4 + uses: aws-actions/configure-aws-credentials@ff717079ee2060e4bcee96c4779b553acc87447c # v4 with: role-to-assume: ${{ env.AWS_S3_METRICS_UPLOAD_ROLE_ARN }} aws-region: us-west-2 @@ -192,7 +192,7 @@ jobs: - name: Upload logs on failure if: failure() || cancelled() - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4 with: name: throughput-stress-logs path: ${{ env.WORKER_LOG_DIR }} @@ -200,7 +200,7 @@ jobs: - name: Notify Slack on failure if: failure() || cancelled() - uses: slackapi/slack-github-action@v2 + uses: slackapi/slack-github-action@91efab103c0de0a537f72a35f6b8cda0ee76bf0a # v2 with: webhook-type: incoming-webhook payload: | diff --git a/.github/workflows/run-bench.yml b/.github/workflows/run-bench.yml index 7f108e1db..f18ab5848 100644 --- a/.github/workflows/run-bench.yml +++ b/.github/workflows/run-bench.yml @@ -29,25 +29,25 @@ jobs: runs-on: ${{ matrix.os }} steps: # Prepare - - uses: actions/checkout@v4 + - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 with: submodules: recursive - - uses: dtolnay/rust-toolchain@stable + - uses: dtolnay/rust-toolchain@29eef336d9b2848a0b548edc03f92a220660cdb8 # stable with: toolchain: stable - - uses: Swatinem/rust-cache@v2 + - uses: Swatinem/rust-cache@42dc69e1aa15d09112580998cf2ef0119e2e91ae # v2 with: workspaces: temporalio/bridge -> target - - uses: actions/setup-python@v5 + - uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5 with: python-version: "3.13" - - uses: arduino/setup-protoc@v3 + - uses: arduino/setup-protoc@c65c819552d16ad3c9b72d9dfd5ba5237b9c906b # v3 with: # TODO(cretz): Can upgrade proto when https://github.com/arduino/setup-protoc/issues/99 fixed version: "23.x" repo-token: ${{ secrets.GITHUB_TOKEN }} - - uses: astral-sh/setup-uv@v5 + - uses: astral-sh/setup-uv@e58605a9b6da7c637471fab8847a5e5a6b8df081 # v5 # Build - run: uv tool install poethepoet - run: uv sync --all-extras diff --git a/pyproject.toml b/pyproject.toml index bd2409f6e..9e0987b6b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -252,3 +252,5 @@ exclude = ["temporalio/bridge/target/**/*"] [tool.uv] # Prevent uv commands from building the package by default package = false +exclude-newer = "1 week" +exclude-newer-package = { openai-agents = false } From e75147e81f9438b13797011bcb2a28522fe72c59 Mon Sep 17 00:00:00 2001 From: Brian Strauch Date: Fri, 17 Apr 2026 15:40:54 -0700 Subject: [PATCH 051/226] implement is_running for asyncio loop (#1463) --- temporalio/worker/_workflow_instance.py | 3 +++ tests/worker/test_workflow.py | 16 ++++++++++++++++ 2 files changed, 19 insertions(+) diff --git a/temporalio/worker/_workflow_instance.py b/temporalio/worker/_workflow_instance.py index 36c7d0007..47175ada3 100644 --- a/temporalio/worker/_workflow_instance.py +++ b/temporalio/worker/_workflow_instance.py @@ -2882,6 +2882,9 @@ def call_exception_handler(self, context: _Context) -> None: def get_debug(self) -> bool: return False + def is_running(self) -> bool: + return True + class _WorkflowInboundImpl(WorkflowInboundInterceptor): def __init__( # type: ignore diff --git a/tests/worker/test_workflow.py b/tests/worker/test_workflow.py index 5d7e22857..b239841b5 100644 --- a/tests/worker/test_workflow.py +++ b/tests/worker/test_workflow.py @@ -7207,6 +7207,22 @@ async def test_in_workflow_util(client: Client): ) +@workflow.defn +class LoopIsRunningWorkflow: + @workflow.run + async def run(self) -> bool: + return asyncio.get_running_loop().is_running() + + +async def test_workflow_loop_is_running(client: Client): + async with new_worker(client, LoopIsRunningWorkflow) as worker: + assert await client.execute_workflow( + LoopIsRunningWorkflow.run, + id=f"workflow-{uuid.uuid4()}", + task_queue=worker.task_queue, + ) + + deadlock_interruptible_completed = 0 From 0ada3b40661c506c8eefda9269ce21c508e8ba6a Mon Sep 17 00:00:00 2001 From: James Watkins-Harvey Date: Fri, 17 Apr 2026 20:48:34 -0400 Subject: [PATCH 052/226] Update and pin all GHA actions (#1464) --- .github/workflows/build-binaries.yml | 6 ++--- .github/workflows/ci.yml | 24 +++++++++---------- .../workflows/nightly-throughput-stress.yml | 10 ++++---- .github/workflows/run-bench.yml | 6 ++--- 4 files changed, 23 insertions(+), 23 deletions(-) diff --git a/.github/workflows/build-binaries.yml b/.github/workflows/build-binaries.yml index a28ae4258..1b1f2370d 100644 --- a/.github/workflows/build-binaries.yml +++ b/.github/workflows/build-binaries.yml @@ -30,7 +30,7 @@ jobs: package-suffix: windows-amd64 runs-on: ${{ matrix.runsOn || matrix.os }} steps: - - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 with: submodules: recursive - uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5 @@ -43,10 +43,10 @@ jobs: - if: ${{ runner.os != 'Linux' }} uses: dtolnay/rust-toolchain@29eef336d9b2848a0b548edc03f92a220660cdb8 # stable - if: ${{ runner.os != 'Linux' }} - uses: Swatinem/rust-cache@42dc69e1aa15d09112580998cf2ef0119e2e91ae # v2 + uses: Swatinem/rust-cache@e18b497796c12c097a38f9edb9d0641fb99eee32 # v2 with: workspaces: temporalio/bridge -> target - - uses: astral-sh/setup-uv@e58605a9b6da7c637471fab8847a5e5a6b8df081 # v5 + - uses: astral-sh/setup-uv@cec208311dfd045dd5311c1add060b2062131d57 # v8 - run: uv sync --all-extras # Add the source dist only for Linux x64 for now diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 99a5f03f6..6294f6d9a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -38,13 +38,13 @@ jobs: runsOn: macos-latest runs-on: ${{ matrix.runsOn || matrix.os }} steps: - - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 with: submodules: recursive - uses: dtolnay/rust-toolchain@29eef336d9b2848a0b548edc03f92a220660cdb8 # stable with: components: "clippy" - - uses: Swatinem/rust-cache@42dc69e1aa15d09112580998cf2ef0119e2e91ae # v2 + - uses: Swatinem/rust-cache@e18b497796c12c097a38f9edb9d0641fb99eee32 # v2 with: workspaces: temporalio/bridge -> target - uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5 @@ -55,7 +55,7 @@ jobs: # TODO(cretz): Can upgrade proto when https://github.com/arduino/setup-protoc/issues/99 fixed version: "23.x" repo-token: ${{ secrets.GITHUB_TOKEN }} - - uses: astral-sh/setup-uv@e58605a9b6da7c637471fab8847a5e5a6b8df081 # v5 + - uses: astral-sh/setup-uv@cec208311dfd045dd5311c1add060b2062131d57 # v8 - run: uv tool install poethepoet - run: uv sync --all-extras - run: poe bridge-lint @@ -105,11 +105,11 @@ jobs: timeout-minutes: 30 runs-on: ubuntu-latest steps: - - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 with: submodules: recursive - uses: dtolnay/rust-toolchain@29eef336d9b2848a0b548edc03f92a220660cdb8 # stable - - uses: Swatinem/rust-cache@42dc69e1aa15d09112580998cf2ef0119e2e91ae # v2 + - uses: Swatinem/rust-cache@e18b497796c12c097a38f9edb9d0641fb99eee32 # v2 with: workspaces: temporalio/bridge -> target - uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5 @@ -120,7 +120,7 @@ jobs: # TODO(cretz): Can upgrade proto when https://github.com/arduino/setup-protoc/issues/99 fixed version: "23.x" repo-token: ${{ secrets.GITHUB_TOKEN }} - - uses: astral-sh/setup-uv@e58605a9b6da7c637471fab8847a5e5a6b8df081 # v5 + - uses: astral-sh/setup-uv@cec208311dfd045dd5311c1add060b2062131d57 # v8 - run: uv tool install poethepoet - run: uv remove google-adk --optional google-adk - run: uv add --python 3.10 "protobuf<4" @@ -139,13 +139,13 @@ jobs: timeout-minutes: 30 runs-on: ubuntu-latest steps: - - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 with: submodules: recursive - uses: dtolnay/rust-toolchain@29eef336d9b2848a0b548edc03f92a220660cdb8 # stable with: components: "clippy" - - uses: Swatinem/rust-cache@42dc69e1aa15d09112580998cf2ef0119e2e91ae # v2 + - uses: Swatinem/rust-cache@e18b497796c12c097a38f9edb9d0641fb99eee32 # v2 with: workspaces: temporalio/bridge -> target - uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5 @@ -156,7 +156,7 @@ jobs: # TODO(cretz): Can upgrade proto when https://github.com/arduino/setup-protoc/issues/99 fixed version: "23.x" repo-token: ${{ secrets.GITHUB_TOKEN }} - - uses: astral-sh/setup-uv@e58605a9b6da7c637471fab8847a5e5a6b8df081 # v5 + - uses: astral-sh/setup-uv@cec208311dfd045dd5311c1add060b2062131d57 # v8 - run: uv tool install poethepoet - run: uv lock --upgrade - run: uv sync --all-extras @@ -179,11 +179,11 @@ jobs: timeout-minutes: 15 runs-on: ubuntu-latest steps: - - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 with: submodules: recursive - uses: dtolnay/rust-toolchain@29eef336d9b2848a0b548edc03f92a220660cdb8 # stable - - uses: Swatinem/rust-cache@42dc69e1aa15d09112580998cf2ef0119e2e91ae # v2 + - uses: Swatinem/rust-cache@e18b497796c12c097a38f9edb9d0641fb99eee32 # v2 with: workspaces: temporalio/bridge -> target - uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5 @@ -194,7 +194,7 @@ jobs: # TODO(cretz): Can upgrade proto when https://github.com/arduino/setup-protoc/issues/99 fixed version: "23.x" repo-token: ${{ secrets.GITHUB_TOKEN }} - - uses: astral-sh/setup-uv@e58605a9b6da7c637471fab8847a5e5a6b8df081 # v5 + - uses: astral-sh/setup-uv@cec208311dfd045dd5311c1add060b2062131d57 # v8 - run: uv tool install poethepoet - run: uv sync --all-extras - run: poe build-develop diff --git a/.github/workflows/nightly-throughput-stress.yml b/.github/workflows/nightly-throughput-stress.yml index 78523f4f3..65d71bf8d 100644 --- a/.github/workflows/nightly-throughput-stress.yml +++ b/.github/workflows/nightly-throughput-stress.yml @@ -68,12 +68,12 @@ jobs: echo "==========================================" - name: Checkout SDK - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 with: submodules: recursive - name: Checkout OMES - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 with: repository: ${{ env.OMES_REPO }} ref: ${{ env.OMES_REF }} @@ -89,7 +89,7 @@ jobs: uses: dtolnay/rust-toolchain@29eef336d9b2848a0b548edc03f92a220660cdb8 # stable - name: Setup Rust cache - uses: Swatinem/rust-cache@42dc69e1aa15d09112580998cf2ef0119e2e91ae # v2 + uses: Swatinem/rust-cache@e18b497796c12c097a38f9edb9d0641fb99eee32 # v2 with: workspaces: temporalio/bridge -> target @@ -105,7 +105,7 @@ jobs: repo-token: ${{ secrets.GITHUB_TOKEN }} - name: Setup uv - uses: astral-sh/setup-uv@e58605a9b6da7c637471fab8847a5e5a6b8df081 # v5 + uses: astral-sh/setup-uv@cec208311dfd045dd5311c1add060b2062131d57 # v8 - name: Install poethepoet run: uv tool install poethepoet @@ -200,7 +200,7 @@ jobs: - name: Notify Slack on failure if: failure() || cancelled() - uses: slackapi/slack-github-action@91efab103c0de0a537f72a35f6b8cda0ee76bf0a # v2 + uses: slackapi/slack-github-action@af78098f536edbc4de71162a307590698245be95 # v3 with: webhook-type: incoming-webhook payload: | diff --git a/.github/workflows/run-bench.yml b/.github/workflows/run-bench.yml index f18ab5848..a5a874a30 100644 --- a/.github/workflows/run-bench.yml +++ b/.github/workflows/run-bench.yml @@ -29,13 +29,13 @@ jobs: runs-on: ${{ matrix.os }} steps: # Prepare - - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 with: submodules: recursive - uses: dtolnay/rust-toolchain@29eef336d9b2848a0b548edc03f92a220660cdb8 # stable with: toolchain: stable - - uses: Swatinem/rust-cache@42dc69e1aa15d09112580998cf2ef0119e2e91ae # v2 + - uses: Swatinem/rust-cache@e18b497796c12c097a38f9edb9d0641fb99eee32 # v2 with: workspaces: temporalio/bridge -> target - uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5 @@ -47,7 +47,7 @@ jobs: version: "23.x" repo-token: ${{ secrets.GITHUB_TOKEN }} - - uses: astral-sh/setup-uv@e58605a9b6da7c637471fab8847a5e5a6b8df081 # v5 + - uses: astral-sh/setup-uv@cec208311dfd045dd5311c1add060b2062131d57 # v8 # Build - run: uv tool install poethepoet - run: uv sync --all-extras From 7e36940d5c740db71e74a6e32c3408e78298c461 Mon Sep 17 00:00:00 2001 From: David Hyde Date: Mon, 20 Apr 2026 12:29:10 -0500 Subject: [PATCH 053/226] Increase execution_timeout for OpenAI tests that call the real API (#1466) test_hello_world_agent[False] had a 5s execution timeout and test_input_guardrail[False] had a 10s timeout, but both use a 30s activity start_to_close_timeout. The workflow times out before the OpenAI API call can complete on slower CI runners. Bump both to 60s. --- tests/contrib/openai_agents/test_openai.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/contrib/openai_agents/test_openai.py b/tests/contrib/openai_agents/test_openai.py index 578eb4d77..c3895a72c 100644 --- a/tests/contrib/openai_agents/test_openai.py +++ b/tests/contrib/openai_agents/test_openai.py @@ -141,7 +141,7 @@ async def test_hello_world_agent(client: Client, use_local_model: bool): "Tell me about recursion in programming.", id=f"hello-workflow-{uuid.uuid4()}", task_queue=worker.task_queue, - execution_timeout=timedelta(seconds=5), + execution_timeout=timedelta(seconds=60), ) if use_local_model: assert result == "test" @@ -1243,7 +1243,7 @@ async def test_input_guardrail(client: Client, use_local_model: bool): ], id=f"input-guardrail-{uuid.uuid4()}", task_queue=worker.task_queue, - execution_timeout=timedelta(seconds=10), + execution_timeout=timedelta(seconds=60), ) result = await workflow_handle.result() From 4b69cd4b0fbd289e50de9d5069dc7e649422717d Mon Sep 17 00:00:00 2001 From: xumaple <45406854+xumaple@users.noreply.github.com> Date: Wed, 22 Apr 2026 12:55:43 -0400 Subject: [PATCH 054/226] AI-60: Add summary_fn parameter to TemporalModel for dynamic activity summaries (#1451) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * AI-60: Add AdkActivityConfig with summary_fn for dynamic activity summaries Introduce AdkActivityConfig extending ActivityConfig with a summary_fn field that accepts a callable for dynamic per-call summaries. When no summary_fn or static summary is set, falls back to reading adk_agent_name from LlmRequest labels for zero-config agent name display. Setting both summary and summary_fn raises ValueError to prevent ambiguity. Co-Authored-By: Claude Opus 4.6 (1M context) * AI-60: Address auditor findings — determinism note, summary_fn None test, label fallback test Co-Authored-By: Claude Opus 4.6 (1M context) * AI-60: Switch to summary_fn keyword param, address auditor findings Drop AdkActivityConfig in favor of a keyword-only summary_fn parameter on TemporalModel. Zero type: ignore comments needed. Auditor findings addressed: - Label fallback test rewritten as integration test - Exception propagation documented in summary_fn docstring - Empty string summary test added Co-Authored-By: Claude Opus 4.6 (1M context) * AI-60: Qualify 'summary' as ActivityConfig summary in error message and docstring Co-Authored-By: Claude Opus 4.6 (1M context) * AI-60: Consolidate summary tests into single workflow run Run all 4 summary_fn variants (dynamic, None, empty, label fallback) as sequential agent invocations within one workflow, reducing CI overhead. Co-Authored-By: Claude Opus 4.6 (1M context) --------- Co-authored-by: Claude Opus 4.6 (1M context) --- .../contrib/google_adk_agents/_model.py | 35 ++++++- .../test_google_adk_agents.py | 97 +++++++++++++++++++ 2 files changed, 128 insertions(+), 4 deletions(-) diff --git a/temporalio/contrib/google_adk_agents/_model.py b/temporalio/contrib/google_adk_agents/_model.py index 6d1e7ffa9..8b32a7432 100644 --- a/temporalio/contrib/google_adk_agents/_model.py +++ b/temporalio/contrib/google_adk_agents/_model.py @@ -1,4 +1,4 @@ -from collections.abc import AsyncGenerator +from collections.abc import AsyncGenerator, Callable from datetime import timedelta from google.adk.models import BaseLlm, LLMRegistry @@ -40,20 +40,37 @@ class TemporalModel(BaseLlm): """A Temporal-based LLM model that executes model invocations as activities.""" def __init__( - self, model_name: str, activity_config: ActivityConfig | None = None + self, + model_name: str, + activity_config: ActivityConfig | None = None, + *, + summary_fn: Callable[[LlmRequest], str | None] | None = None, ) -> None: """Initialize the TemporalModel. Args: model_name: The name of the model to use. activity_config: Configuration options for the activity execution. + summary_fn: Optional callable that receives the LlmRequest and + returns a summary string (or None) for the activity. Must be + deterministic as it is called during workflow execution. If + the callable raises, the exception will propagate and fail + the workflow task. + + Raises: + ValueError: If both ``ActivityConfig["summary"]`` and ``summary_fn`` are set. """ super().__init__(model=model_name) self._model_name = model_name + self._summary_fn = summary_fn self._activity_config = ActivityConfig( start_to_close_timeout=timedelta(seconds=60) ) - if activity_config: + if activity_config is not None: + if summary_fn is not None and activity_config.get("summary") is not None: + raise ValueError( + "Cannot specify both ActivityConfig 'summary' and 'summary_fn'" + ) self._activity_config.update(activity_config) async def generate_content_async( @@ -76,10 +93,20 @@ async def generate_content_async( yield response return + config = self._activity_config.copy() + if self._summary_fn is not None: + summary = self._summary_fn(llm_request) + if summary is not None: + config["summary"] = summary + elif "summary" not in config: + if llm_request.config and llm_request.config.labels: + agent_name = llm_request.config.labels.get("adk_agent_name") + if agent_name: + config["summary"] = agent_name responses = await workflow.execute_activity( invoke_model, args=[llm_request], - **self._activity_config, + **config, ) for response in responses: yield response diff --git a/tests/contrib/google_adk_agents/test_google_adk_agents.py b/tests/contrib/google_adk_agents/test_google_adk_agents.py index e35d58ea6..2bea29efd 100644 --- a/tests/contrib/google_adk_agents/test_google_adk_agents.py +++ b/tests/contrib/google_adk_agents/test_google_adk_agents.py @@ -580,6 +580,103 @@ async def test_unsetting_timeout(): assert model._activity_config.get("start_to_close_timeout", None) is None +class SummaryFnModel(TestModel): + """Returns a single text response for summary_fn testing.""" + + def responses(self) -> list[LlmResponse]: + return [ + LlmResponse(content=Content(role="model", parts=[Part(text="response")])), + ] + + @classmethod + def supported_models(cls) -> list[str]: + return ["summary_fn_model"] + + +@workflow.defn +class SummaryTestWorkflow: + @workflow.run + async def run(self, model_name: str) -> None: + modes = [ + ("dynamic", lambda req: f"Invoking {req.model}"), + ("none", lambda req: None), + ("empty", lambda req: ""), + ("label_fallback", None), + ] + for mode_name, summary_fn in modes: + agent = Agent( + name=f"summary_test_{mode_name}", + model=TemporalModel(model_name, summary_fn=summary_fn), + ) + runner = InMemoryRunner(agent=agent, app_name=f"summary_{mode_name}") + session = await runner.session_service.create_session( + app_name=f"summary_{mode_name}", user_id="test" + ) + async with Aclosing( + runner.run_async( + user_id="test", + session_id=session.id, + new_message=types.Content( + role="user", parts=[types.Part(text="hi")] + ), + ) + ) as agen: + async for _ in agen: + pass + + +@pytest.mark.asyncio +async def test_summary_fn_variants(client: Client): + """Test summary_fn with dynamic, None, empty string, and label fallback.""" + new_config = client.config() + new_config["plugins"] = [GoogleAdkPlugin()] + client = Client(**new_config) + LLMRegistry.register(SummaryFnModel) + + async with Worker( + client, + task_queue="adk-summary-test", + workflows=[SummaryTestWorkflow], + max_cached_workflows=0, + ): + handle = await client.start_workflow( + SummaryTestWorkflow.run, + "summary_fn_model", + id=f"summary-test-{uuid.uuid4()}", + task_queue="adk-summary-test", + execution_timeout=timedelta(seconds=60), + ) + await handle.result() + + summaries = [] + async for e in handle.fetch_history_events(): + if e.HasField("activity_task_scheduled_event_attributes"): + attrs = e.activity_task_scheduled_event_attributes + if attrs.activity_type.name == "invoke_model": + summaries.append(e.user_metadata.summary.data) + + assert len(summaries) == 4 + assert summaries[0] == b'"Invoking summary_fn_model"' # dynamic + assert summaries[1] == b"" # none + assert summaries[2] == b"" # empty + assert ( + summaries[3] == b'"summary_test_label_fallback"' + ) # label fallback agent name + + +def test_summary_and_summary_fn_raises(): + """Cannot specify both summary and summary_fn.""" + with pytest.raises( + ValueError, + match="Cannot specify both ActivityConfig 'summary' and 'summary_fn'", + ): + TemporalModel( + "m", + activity_config=ActivityConfig(summary="static"), + summary_fn=lambda req: "dynamic", + ) + + @pytest.mark.asyncio async def test_agent_outside_workflow(): """Test that an agent using TemporalModel and activity_tool works outside a Temporal workflow.""" From 5ff4e35c4e2e27a856b3b4c09df6a958173cc69a Mon Sep 17 00:00:00 2001 From: Christopher Constable Date: Wed, 22 Apr 2026 15:13:12 -0400 Subject: [PATCH 055/226] Add OTel tracing for standalone activities (#1471) * feat(otel): add otel tracing for standalone activities for both legacy and new interceptors. * docs: update README section on testing to reflect current implementation. * style: remove unnecessary comments in tests. --- .gitignore | 1 + README.md | 19 ++++-- .../contrib/opentelemetry/_interceptor.py | 54 ++++++++++++++++ .../opentelemetry/_otel_interceptor.py | 64 +++++++++++++++++++ .../opentelemetry/test_opentelemetry.py | 64 +++++++++++++++++++ .../test_opentelemetry_plugin.py | 63 ++++++++++++++++++ 6 files changed, 258 insertions(+), 7 deletions(-) diff --git a/.gitignore b/.gitignore index 923875d32..8cd439e05 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,7 @@ __pycache__ /build /dist +temporalio/bridge/libtemporal_sdk_bridge.dylib.dSYM/ temporalio/bridge/target/ temporalio/bridge/temporal_sdk_bridge* /tests/helpers/golangserver/golangserver diff --git a/README.md b/README.md index 65a16bcfc..5968b2072 100644 --- a/README.md +++ b/README.md @@ -2059,28 +2059,33 @@ The environment is now ready to develop in. #### Testing -To execute tests: +To execute tests (in parallel if possible): ```bash poe test ``` -`poe test` spreads tests across multiple worker processes by default. If you -need a serial run for debugging, invoke pytest directly: +To execute tests serially: ```bash uv run pytest ``` -This runs against [Temporalite](https://github.com/temporalio/temporalite). To run against the time-skipping test -server, pass `--workflow-environment time-skipping`. To run against the `default` namespace of an already-running -server, pass the `host:port` to `--workflow-environment`. Can also use regular pytest arguments. For example, here's how -to run a single test with debug logs on the console: +To execute a single test: ```bash poe test -s --log-cli-level=DEBUG -k test_sync_activity_thread_cancel_caught ``` +**Temporal Server** + +- Tests that use the workflow test environment run against the [Temporal CLI dev server](https://docs.temporal.io/cli#start-dev-server). +- By default, workflow-environment tests automatically start a local dev server. +- On first run, the dev server binary may be downloaded so network access is required if no server is currently running. +- To run workflow-environment tests against the time-skipping test server, pass `--workflow-environment time-skipping`. +- To run workflow-environment tests against the `default` namespace of an already-running server, pass the `host:port` to `--workflow-environment`. +- Unit tests that do not use the workflow environment do not start a dev server. + #### Proto Generation and Testing If you have docker available, run diff --git a/temporalio/contrib/opentelemetry/_interceptor.py b/temporalio/contrib/opentelemetry/_interceptor.py index 69a2cfb0c..2c6323707 100644 --- a/temporalio/contrib/opentelemetry/_interceptor.py +++ b/temporalio/contrib/opentelemetry/_interceptor.py @@ -341,6 +341,60 @@ async def start_update_with_start_workflow( return await super().start_update_with_start_workflow(input) + async def start_activity( + self, input: temporalio.client.StartActivityInput + ) -> temporalio.client.ActivityHandle[Any]: + with self.root._start_as_current_span( + f"StartActivity:{input.activity_type}", + attributes={ + "temporalActivityID": input.id, + "temporalActivityType": input.activity_type, + }, + input_with_headers=input, + kind=opentelemetry.trace.SpanKind.CLIENT, + ): + return await super().start_activity(input) + + async def cancel_activity( + self, input: temporalio.client.CancelActivityInput + ) -> None: + with self.root._start_as_current_span( + "CancelActivity", + attributes={"temporalActivityID": input.activity_id}, + kind=opentelemetry.trace.SpanKind.CLIENT, + ): + return await super().cancel_activity(input) + + async def terminate_activity( + self, input: temporalio.client.TerminateActivityInput + ) -> None: + with self.root._start_as_current_span( + "TerminateActivity", + attributes={"temporalActivityID": input.activity_id}, + kind=opentelemetry.trace.SpanKind.CLIENT, + ): + return await super().terminate_activity(input) + + async def describe_activity( + self, input: temporalio.client.DescribeActivityInput + ) -> temporalio.client.ActivityExecutionDescription: + with self.root._start_as_current_span( + "DescribeActivity", + attributes={"temporalActivityID": input.activity_id}, + kind=opentelemetry.trace.SpanKind.CLIENT, + ): + return await super().describe_activity(input) + + async def count_activities( + self, input: temporalio.client.CountActivitiesInput + ) -> temporalio.client.ActivityExecutionCount: + with self.root._start_as_current_span( + "CountActivities", + attributes={}, + kind=opentelemetry.trace.SpanKind.CLIENT, + ): + return await super().count_activities(input) + class _TracingActivityInboundInterceptor(temporalio.worker.ActivityInboundInterceptor): def __init__( diff --git a/temporalio/contrib/opentelemetry/_otel_interceptor.py b/temporalio/contrib/opentelemetry/_otel_interceptor.py index 1756f93e1..089e73da7 100644 --- a/temporalio/contrib/opentelemetry/_otel_interceptor.py +++ b/temporalio/contrib/opentelemetry/_otel_interceptor.py @@ -303,6 +303,70 @@ async def start_update_with_start_workflow( ) return await super().start_update_with_start_workflow(input) + async def start_activity( + self, input: temporalio.client.StartActivityInput + ) -> temporalio.client.ActivityHandle[Any]: + with _maybe_span( + get_tracer(__name__), + f"StartActivity:{input.activity_type}", + add_temporal_spans=self._add_temporal_spans, + attributes={ + "temporalActivityID": input.id, + "temporalActivityType": input.activity_type, + }, + kind=opentelemetry.trace.SpanKind.CLIENT, + ): + input.headers = _context_to_headers(input.headers) + return await super().start_activity(input) + + async def cancel_activity( + self, input: temporalio.client.CancelActivityInput + ) -> None: + with _maybe_span( + get_tracer(__name__), + "CancelActivity", + add_temporal_spans=self._add_temporal_spans, + attributes={"temporalActivityID": input.activity_id}, + kind=opentelemetry.trace.SpanKind.CLIENT, + ): + return await super().cancel_activity(input) + + async def terminate_activity( + self, input: temporalio.client.TerminateActivityInput + ) -> None: + with _maybe_span( + get_tracer(__name__), + "TerminateActivity", + add_temporal_spans=self._add_temporal_spans, + attributes={"temporalActivityID": input.activity_id}, + kind=opentelemetry.trace.SpanKind.CLIENT, + ): + return await super().terminate_activity(input) + + async def describe_activity( + self, input: temporalio.client.DescribeActivityInput + ) -> temporalio.client.ActivityExecutionDescription: + with _maybe_span( + get_tracer(__name__), + "DescribeActivity", + add_temporal_spans=self._add_temporal_spans, + attributes={"temporalActivityID": input.activity_id}, + kind=opentelemetry.trace.SpanKind.CLIENT, + ): + return await super().describe_activity(input) + + async def count_activities( + self, input: temporalio.client.CountActivitiesInput + ) -> temporalio.client.ActivityExecutionCount: + with _maybe_span( + get_tracer(__name__), + "CountActivities", + add_temporal_spans=self._add_temporal_spans, + attributes={}, + kind=opentelemetry.trace.SpanKind.CLIENT, + ): + return await super().count_activities(input) + class _TracingActivityInboundInterceptor(temporalio.worker.ActivityInboundInterceptor): def __init__( diff --git a/tests/contrib/opentelemetry/test_opentelemetry.py b/tests/contrib/opentelemetry/test_opentelemetry.py index 2c3293fd6..2dd17e303 100644 --- a/tests/contrib/opentelemetry/test_opentelemetry.py +++ b/tests/contrib/opentelemetry/test_opentelemetry.py @@ -944,6 +944,70 @@ async def test_opentelemetry_interceptor_works_if_no_context( # * signal failure and wft failure from signal +async def test_opentelemetry_standalone_activity_tracing( + client: Client, env: WorkflowEnvironment +): + if env.supports_time_skipping: + pytest.skip( + "Java test server: https://github.com/temporalio/sdk-java/issues/2741" + ) + exporter = InMemorySpanExporter() + provider = TracerProvider() + provider.add_span_processor(SimpleSpanProcessor(exporter)) + tracer = get_tracer(__name__, tracer_provider=provider) + client_config = client.config() + client_config["interceptors"] = [TracingInterceptor(tracer)] + client = Client(**client_config) + + task_queue = f"task_queue_{uuid.uuid4()}" + async with Worker( + client, + task_queue=task_queue, + activities=[tracing_activity], + ): + handle = await client.start_activity( + tracing_activity, + TracingActivityParam(heartbeat=False), + id=f"activity_{uuid.uuid4()}", + task_queue=task_queue, + schedule_to_close_timeout=timedelta(seconds=10), + ) + await handle.result() + + # Use a queue with no worker so activities stay in SCHEDULED state, + # allowing describe/cancel/terminate to be called without a race. + no_worker_queue = f"task_queue_{uuid.uuid4()}" + + cancel_handle = await client.start_activity( + tracing_activity, + TracingActivityParam(heartbeat=False), + id=f"activity_{uuid.uuid4()}", + task_queue=no_worker_queue, + schedule_to_close_timeout=timedelta(seconds=30), + ) + await cancel_handle.describe() + await cancel_handle.cancel() + + terminate_handle = await client.start_activity( + tracing_activity, + TracingActivityParam(heartbeat=False), + id=f"activity_{uuid.uuid4()}", + task_queue=no_worker_queue, + schedule_to_close_timeout=timedelta(seconds=30), + ) + await terminate_handle.terminate() + + assert dump_spans(exporter.get_finished_spans(), with_attributes=False) == [ + "StartActivity:tracing_activity", + " RunActivity:tracing_activity", + "StartActivity:tracing_activity", + "DescribeActivity", + "CancelActivity", + "StartActivity:tracing_activity", + "TerminateActivity", + ] + + def test_opentelemetry_safe_detach(): class _fake_self: def _load_workflow_context_carrier(*_args): diff --git a/tests/contrib/opentelemetry/test_opentelemetry_plugin.py b/tests/contrib/opentelemetry/test_opentelemetry_plugin.py index dd1b20024..29acf0b6a 100644 --- a/tests/contrib/opentelemetry/test_opentelemetry_plugin.py +++ b/tests/contrib/opentelemetry/test_opentelemetry_plugin.py @@ -567,6 +567,69 @@ async def test_otel_tracing_workflow_failure( ), f"Span hierarchy mismatch.\nExpected:\n{expected_hierarchy}\nActual:\n{actual_hierarchy}" +async def test_otel_standalone_activity_tracing( + client: Client, + env: WorkflowEnvironment, + reset_otel_tracer_provider: Any, # type: ignore[reportUnusedParameter] +): + if env.supports_time_skipping: + pytest.skip( + "Java test server: https://github.com/temporalio/sdk-java/issues/2741" + ) + exporter = InMemorySpanExporter() + provider = create_tracer_provider() + provider.add_span_processor(SimpleSpanProcessor(exporter)) + opentelemetry.trace.set_tracer_provider(provider) + + new_config = client.config() + new_config["plugins"] = [OpenTelemetryPlugin(add_temporal_spans=True)] + new_client = Client(**new_config) + + async with new_worker( + new_client, + activities=[simple_no_context_activity], + ) as worker: + handle = await new_client.start_activity( + simple_no_context_activity, + id=f"activity_{uuid.uuid4()}", + task_queue=worker.task_queue, + schedule_to_close_timeout=timedelta(seconds=10), + ) + await handle.result() + + # Use a queue with no worker so activities stay in SCHEDULED state, + # allowing describe/cancel/terminate to be called without a race. + no_worker_queue = f"task_queue_{uuid.uuid4()}" + + cancel_handle = await new_client.start_activity( + simple_no_context_activity, + id=f"activity_{uuid.uuid4()}", + task_queue=no_worker_queue, + schedule_to_close_timeout=timedelta(seconds=30), + ) + await cancel_handle.describe() + await cancel_handle.cancel() + + terminate_handle = await new_client.start_activity( + simple_no_context_activity, + id=f"activity_{uuid.uuid4()}", + task_queue=no_worker_queue, + schedule_to_close_timeout=timedelta(seconds=30), + ) + await terminate_handle.terminate() + + assert dump_spans(exporter.get_finished_spans(), with_attributes=False) == [ + "StartActivity:simple_no_context_activity", + " RunActivity:simple_no_context_activity", + " Activity", + "StartActivity:simple_no_context_activity", + "DescribeActivity", + "CancelActivity", + "StartActivity:simple_no_context_activity", + "TerminateActivity", + ] + + def test_replay_safe_span_delegates_extra_attributes(): """Test that _ReplaySafeSpan delegates attribute access to the underlying span. From b466009d5a2810da2a4c47f6b5cfc28acc3b1520 Mon Sep 17 00:00:00 2001 From: Justin Anderson <44687433+jmaeagle99@users.noreply.github.com> Date: Wed, 22 Apr 2026 15:20:13 -0700 Subject: [PATCH 056/226] More details for workflow task latency logging (#1469) --- temporalio/converter/_extstore.py | 35 ++++++++--- temporalio/worker/_workflow.py | 48 +++++++++------ temporalio/worker/_workflow_instance.py | 8 +++ temporalio/worker/workflow_sandbox/_runner.py | 3 + temporalio/workflow.py | 60 ++++++++++++++----- tests/worker/test_extstore.py | 48 +++++++-------- tests/worker/test_workflow.py | 3 + 7 files changed, 139 insertions(+), 66 deletions(-) diff --git a/temporalio/converter/_extstore.py b/temporalio/converter/_extstore.py index e787652a5..55b1686bf 100644 --- a/temporalio/converter/_extstore.py +++ b/temporalio/converter/_extstore.py @@ -38,11 +38,17 @@ class StorageOperationMetrics: total_duration: timedelta = dataclasses.field(default_factory=timedelta) """Wall-clock time spent on external storage operations.""" - def record_batch(self, count: int, size: int, duration: timedelta) -> None: + driver_names: set[str] = dataclasses.field(default_factory=set) + """Names of the drivers that participated in the operations.""" + + def record_batch( + self, count: int, size: int, duration: timedelta, driver_names: set[str] + ) -> None: """Record metrics from a batch of storage operations.""" self.payload_count += count self.total_size += size self.total_duration += duration + self.driver_names.update(driver_names) @contextlib.contextmanager def track(self) -> Generator[Self, None, None]: @@ -362,7 +368,7 @@ async def _store_payload(self, payload: Payload) -> Payload: ) reference_payload.external_payloads.add().size_bytes = external_size - ExternalStorage._record_metrics(1, external_size, start_time) + ExternalStorage._record_metrics(1, external_size, start_time, {driver.name()}) return reference_payload @@ -407,6 +413,7 @@ async def _store_payload_sequence( external_count = 0 external_size = 0 + driver_names: set[str] = set() for (driver, indexed_payloads), claims in zip(driver_group_list, all_claims): indices = [idx for idx, _ in indexed_payloads] sizes = [p.ByteSize() for _, p in indexed_payloads] @@ -428,8 +435,11 @@ async def _store_payload_sequence( external_size += sizes[i] external_count += len(claims) + driver_names.add(driver.name()) - ExternalStorage._record_metrics(external_count, external_size, start_time) + ExternalStorage._record_metrics( + external_count, external_size, start_time, driver_names + ) return results @@ -452,7 +462,9 @@ async def _retrieve_payload(self, payload: Payload) -> Payload: stored_payload = stored_payloads[0] - ExternalStorage._record_metrics(1, stored_payload.ByteSize(), start_time) + ExternalStorage._record_metrics( + 1, stored_payload.ByteSize(), start_time, {driver.name()} + ) return stored_payload @@ -501,6 +513,7 @@ async def _retrieve_payload_sequence( external_count = 0 external_size = 0 + driver_names: set[str] = set() for (driver, indexed_claims), stored_payloads in zip( driver_claim_list, all_stored ): @@ -517,6 +530,7 @@ async def _retrieve_payload_sequence( external_size += stored_payload.ByteSize() external_count += len(stored_payloads) + driver_names.add(driver.name()) retrieve_indices = sorted(stored_by_index.keys()) stored_list = [stored_by_index[idx] for idx in retrieve_indices] @@ -524,7 +538,9 @@ async def _retrieve_payload_sequence( for i, retrieved_payload in enumerate(stored_list): results[retrieve_indices[i]] = retrieved_payload - ExternalStorage._record_metrics(external_count, external_size, start_time) + ExternalStorage._record_metrics( + external_count, external_size, start_time, driver_names + ) return results @@ -545,9 +561,14 @@ def _validate_payload_length( ) @staticmethod - def _record_metrics(count: int, size: int, start_time: float): + def _record_metrics( + count: int, size: int, start_time: float, driver_names: set[str] + ): metrics = _current_storage_metrics.get() if metrics is not None: metrics.record_batch( - count, size, timedelta(seconds=time.monotonic() - start_time) + count, + size, + timedelta(seconds=time.monotonic() - start_time), + driver_names, ) diff --git a/temporalio/worker/_workflow.py b/temporalio/worker/_workflow.py index b699e421d..bb489329a 100644 --- a/temporalio/worker/_workflow.py +++ b/temporalio/worker/_workflow.py @@ -302,7 +302,7 @@ async def _handle_activation( id=workflow_id, run_id=act.run_id, type=( - workflow.workflow_type + workflow.get_info().workflow_type if workflow else (init_job.workflow_type if init_job else None) ), @@ -326,9 +326,7 @@ async def _handle_activation( if not workflow: assert init_job workflow = _RunningWorkflow( - self._create_workflow_instance(act, init_job), - workflow_id, - workflow_type=init_job.workflow_type, + self._create_workflow_instance(act, init_job), workflow_id ) self._running_workflows[act.run_id] = workflow @@ -461,8 +459,8 @@ async def _handle_activation( act, task_start_time, download_metrics, upload_metrics ) - @staticmethod def _log_workflow_task_duration( + self, act: temporalio.bridge.proto.workflow_activation.WorkflowActivation, task_start_time: float, download_metrics: temporalio.converter._extstore.StorageOperationMetrics, @@ -476,47 +474,60 @@ def _fmt_duration(td: timedelta) -> str: return f"{secs:.3f}s" return f"{secs * 1000:.3f}ms" - msg_details: dict[str, object] = { - "event_id": act.history_length, - "workflow_task_duration": _fmt_duration(task_duration), - } - extra: dict[str, object] = { - "event_id": act.history_length, - "workflow_task_duration": task_duration, - } + completed_event_id = act.history_length + 1 + _running = self._running_workflows.get(act.run_id) + _info = _running.get_info() if _running is not None else None + attempt = _info.attempt if _info is not None else "unknown" + log_id = f"{act.run_id}:{completed_event_id}:{attempt}" + msg_details, extra = temporalio.workflow._build_log_context( + _info._logger_details() if _info is not None else None, + full_workflow_info=_info, + ) + msg_details["event_id"] = completed_event_id + msg_details["workflow_task_duration"] = _fmt_duration(task_duration) + msg_details["workflow_history_size"] = act.history_size_bytes + extra["event_id"] = completed_event_id + extra["workflow_task_duration"] = task_duration + extra["workflow_history_size"] = act.history_size_bytes if download_metrics.payload_count > 0: msg_details["payload_download_count"] = download_metrics.payload_count msg_details["payload_download_size"] = download_metrics.total_size msg_details["payload_download_duration"] = _fmt_duration( download_metrics.total_duration ) + msg_details["payload_download_drivers"] = sorted( + download_metrics.driver_names + ) extra["payload_download_count"] = download_metrics.payload_count extra["payload_download_size"] = download_metrics.total_size extra["payload_download_duration"] = download_metrics.total_duration + extra["payload_download_drivers"] = sorted(download_metrics.driver_names) if upload_metrics.payload_count > 0: msg_details["payload_upload_count"] = upload_metrics.payload_count msg_details["payload_upload_size"] = upload_metrics.total_size msg_details["payload_upload_duration"] = _fmt_duration( upload_metrics.total_duration ) + msg_details["payload_upload_drivers"] = sorted(upload_metrics.driver_names) extra["payload_upload_count"] = upload_metrics.payload_count extra["payload_upload_size"] = upload_metrics.total_size extra["payload_upload_duration"] = upload_metrics.total_duration + extra["payload_upload_drivers"] = sorted(upload_metrics.driver_names) if task_duration.total_seconds() > 10: logger.warning( - "[TMPRL1104] Workflow task exceeded 10 seconds (%s)", + f"[TMPRL1104] {log_id} Workflow task exceeded 10 seconds (%s)", msg_details, extra=extra, ) elif task_duration.total_seconds() > 5: logger.info( - "[TMPRL1104] Workflow task exceeded 5 seconds (%s)", + f"[TMPRL1104] {log_id} Workflow task exceeded 5 seconds (%s)", msg_details, extra=extra, ) else: logger.debug( - "[TMPRL1104] Workflow task duration information (%s)", + f"[TMPRL1104] {log_id} Workflow task duration information (%s)", msg_details, extra=extra, ) @@ -822,15 +833,16 @@ def __init__( self, instance: WorkflowInstance, workflow_id: str, - workflow_type: str | None = None, ): self.instance = instance self.workflow_id = workflow_id - self.workflow_type = workflow_type self.deadlocked_activation_task: Awaitable | None = None self._deadlock_can_be_interrupted_lock = threading.Lock() self._deadlock_can_be_interrupted = False + def get_info(self) -> temporalio.workflow.Info: + return self.instance.get_info() + def activate( self, act: temporalio.bridge.proto.workflow_activation.WorkflowActivation ) -> temporalio.bridge.proto.workflow_completion.WorkflowActivationCompletion: diff --git a/temporalio/worker/_workflow_instance.py b/temporalio/worker/_workflow_instance.py index 47175ada3..fea97564b 100644 --- a/temporalio/worker/_workflow_instance.py +++ b/temporalio/worker/_workflow_instance.py @@ -198,6 +198,11 @@ def get_external_store_context( """ raise NotImplementedError + @abstractmethod + def get_info(self) -> temporalio.workflow.Info: + """Return the workflow info for this instance.""" + raise NotImplementedError + def get_thread_id(self) -> int | None: """Return the thread identifier that this workflow is running on. @@ -1202,6 +1207,9 @@ def workflow_get_current_deployment_version( deployment_name=self._deployment_version_for_current_task.deployment_name, ) + def get_info(self) -> temporalio.workflow.Info: + return self._info + def workflow_get_current_history_length(self) -> int: return self._current_history_length diff --git a/temporalio/worker/workflow_sandbox/_runner.py b/temporalio/worker/workflow_sandbox/_runner.py index 7605f3054..b11c9b8c4 100644 --- a/temporalio/worker/workflow_sandbox/_runner.py +++ b/temporalio/worker/workflow_sandbox/_runner.py @@ -187,6 +187,9 @@ def _run_code(self, code: str, **extra_globals: Any) -> None: for k, v in extra_globals.items(): self.globals_and_locals.pop(k, None) + def get_info(self) -> temporalio.workflow.Info: + return self.instance_details.info + def get_thread_id(self) -> int | None: return self._current_thread_id diff --git a/temporalio/workflow.py b/temporalio/workflow.py index dd8565f78..59a353286 100644 --- a/temporalio/workflow.py +++ b/temporalio/workflow.py @@ -1635,6 +1635,41 @@ def sandbox_import_notification_policy( _sandbox_import_notification_policy_override.value = original_policy +def _build_log_context( + workflow_details: Mapping[str, Any] | None, + update_details: Mapping[str, Any] | None = None, + *, + workflow_info_on_message: bool = True, + workflow_info_on_extra: bool = True, + full_workflow_info: Info | None = None, +) -> tuple[dict[str, Any], dict[str, Any]]: + """Build the msg_extra suffix and extra dict entries for a temporal log record. + + Returns: + (msg_extra, extra) where msg_extra should be appended to the log message + and extra should be merged into the log record's extra dict. + """ + msg_extra: dict[str, Any] = {} + extra: dict[str, Any] = {} + + if workflow_details is not None: + if workflow_info_on_message: + msg_extra.update(workflow_details) + if workflow_info_on_extra: + extra["temporal_workflow"] = dict(workflow_details) + + if update_details is not None: + if workflow_info_on_message: + msg_extra.update(update_details) + if workflow_info_on_extra: + extra.setdefault("temporal_workflow", {}).update(update_details) + + if full_workflow_info is not None: + extra["workflow_info"] = full_workflow_info + + return msg_extra, extra + + class LoggerAdapter(logging.LoggerAdapter): """Adapter that adds details to the log about the running workflow. @@ -1671,8 +1706,8 @@ def process( self, msg: Any, kwargs: MutableMapping[str, Any] ) -> tuple[Any, MutableMapping[str, Any]]: """Override to add workflow details.""" - extra: dict[str, Any] = {} msg_extra: dict[str, Any] = {} + extra: dict[str, Any] = {} if ( self.workflow_info_on_message @@ -1680,21 +1715,16 @@ def process( or self.full_workflow_info_on_extra ): runtime = _Runtime.maybe_current() - if runtime: - workflow_details = runtime.logger_details - if self.workflow_info_on_message: - msg_extra.update(workflow_details) - if self.workflow_info_on_extra: - extra["temporal_workflow"] = workflow_details - if self.full_workflow_info_on_extra: - extra["workflow_info"] = runtime.workflow_info() update_info = current_update_info() - if update_info: - update_details = update_info._logger_details - if self.workflow_info_on_message: - msg_extra.update(update_details) - if self.workflow_info_on_extra: - extra.setdefault("temporal_workflow", {}).update(update_details) + msg_extra, extra = _build_log_context( + runtime.logger_details if runtime else None, + update_info._logger_details if update_info else None, + workflow_info_on_message=self.workflow_info_on_message, + workflow_info_on_extra=self.workflow_info_on_extra, + full_workflow_info=runtime.workflow_info() + if runtime and self.full_workflow_info_on_extra + else None, + ) kwargs["extra"] = {**extra, **(kwargs.get("extra") or {})} if msg_extra: diff --git a/tests/worker/test_extstore.py b/tests/worker/test_extstore.py index 56ede59d0..5f55e0be2 100644 --- a/tests/worker/test_extstore.py +++ b/tests/worker/test_extstore.py @@ -1,5 +1,6 @@ import dataclasses import logging +import re import uuid from collections.abc import Sequence from dataclasses import dataclass @@ -665,8 +666,9 @@ async def test_tmprl1104_no_extstore(env: WorkflowEnvironment) -> None: records = _tmprl1104_records(capturer) assert len(records) == 1 record = records[0] - assert record.getMessage().startswith( - "[TMPRL1104] Workflow task duration information (" + assert re.match( + r"\[TMPRL1104\] [^:]+:\d+:\d+ Workflow task duration information \(", + record.getMessage(), ) assert hasattr(record, "workflow_task_duration") assert hasattr(record, "event_id") @@ -719,10 +721,9 @@ async def test_tmprl1104_with_extstore_download(env: WorkflowEnvironment) -> Non assert len(records) == 2 # WFT 1: retrieves the externalized workflow input - assert ( - records[0] - .getMessage() - .startswith("[TMPRL1104] Workflow task duration information (") + assert re.match( + r"\[TMPRL1104\] [^:]+:\d+:\d+ Workflow task duration information \(", + records[0].getMessage(), ) assert getattr(records[0], "payload_download_count") == 1 assert getattr(records[0], "payload_download_size") == expected_input_size @@ -730,10 +731,9 @@ async def test_tmprl1104_with_extstore_download(env: WorkflowEnvironment) -> Non assert not hasattr(records[0], "payload_upload_count") # WFT 2: activity result is small — no external storage - assert ( - records[1] - .getMessage() - .startswith("[TMPRL1104] Workflow task duration information (") + assert re.match( + r"\[TMPRL1104\] [^:]+:\d+:\d+ Workflow task duration information \(", + records[1].getMessage(), ) assert not hasattr(records[1], "payload_download_count") assert not hasattr(records[1], "payload_upload_count") @@ -779,19 +779,17 @@ async def test_tmprl1104_with_extstore_upload(env: WorkflowEnvironment) -> None: assert len(records) == 2 # WFT 1: small input — no external storage - assert ( - records[0] - .getMessage() - .startswith("[TMPRL1104] Workflow task duration information (") + assert re.match( + r"\[TMPRL1104\] [^:]+:\d+:\d+ Workflow task duration information \(", + records[0].getMessage(), ) assert not hasattr(records[0], "payload_download_count") assert not hasattr(records[0], "payload_upload_count") # WFT 2: workflow returns large result → uploaded - assert ( - records[1] - .getMessage() - .startswith("[TMPRL1104] Workflow task duration information (") + assert re.match( + r"\[TMPRL1104\] [^:]+:\d+:\d+ Workflow task duration information \(", + records[1].getMessage(), ) assert not hasattr(records[1], "payload_download_count") assert getattr(records[1], "payload_upload_count") == 1 @@ -843,10 +841,9 @@ async def test_tmprl1104_with_extstore_download_and_upload( assert len(records) == 2 # WFT 1: retrieves externalized workflow input - assert ( - records[0] - .getMessage() - .startswith("[TMPRL1104] Workflow task duration information (") + assert re.match( + r"\[TMPRL1104\] [^:]+:\d+:\d+ Workflow task duration information \(", + records[0].getMessage(), ) assert getattr(records[0], "payload_download_count") == 1 assert getattr(records[0], "payload_download_size") == expected_input_size @@ -854,10 +851,9 @@ async def test_tmprl1104_with_extstore_download_and_upload( assert not hasattr(records[0], "payload_upload_count") # WFT 2: uploads externalized workflow result - assert ( - records[1] - .getMessage() - .startswith("[TMPRL1104] Workflow task duration information (") + assert re.match( + r"\[TMPRL1104\] [^:]+:\d+:\d+ Workflow task duration information \(", + records[1].getMessage(), ) assert not hasattr(records[1], "payload_download_count") assert getattr(records[1], "payload_upload_count") == 1 diff --git a/tests/worker/test_workflow.py b/tests/worker/test_workflow.py index b239841b5..cf84db758 100644 --- a/tests/worker/test_workflow.py +++ b/tests/worker/test_workflow.py @@ -1637,6 +1637,9 @@ def get_external_store_context( ) -> temporalio.converter._extstore.StorageDriverStoreContext: return self._unsandboxed.get_external_store_context(command_info) + def get_info(self) -> temporalio.workflow.Info: + return self._unsandboxed.get_info() + async def test_workflow_with_custom_runner(client: Client): runner = CustomWorkflowRunner() From cfedf83430547a622bdbc6b3cdb8d6e34698029a Mon Sep 17 00:00:00 2001 From: Justin Anderson <44687433+jmaeagle99@users.noreply.github.com> Date: Thu, 23 Apr 2026 07:57:59 -0700 Subject: [PATCH 057/226] Fix external storage CaN test stability (#1454) --- tests/worker/test_extstore.py | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/tests/worker/test_extstore.py b/tests/worker/test_extstore.py index 5f55e0be2..2265ed8ee 100644 --- a/tests/worker/test_extstore.py +++ b/tests/worker/test_extstore.py @@ -1353,16 +1353,24 @@ async def test_store_metadata_standalone_activity(env: WorkflowEnvironment) -> N class ContinueAsNewExtStoreWorkflow: """Workflow that continues-as-new once with a large payload. - Run 1: called with large_payload, calls continue_as_new with same payload. + Run 1: called with large_payload, waits for signal, calls continue_as_new with same payload. Run 2: called with large_payload again (from CaN), returns immediately. """ + def __init__(self) -> None: + self._proceed = False + @workflow.run async def run(self, large_payload: str) -> str: if workflow.info().continued_run_id is None: + await workflow.wait_condition(lambda: self._proceed) workflow.continue_as_new(large_payload) return "done" + @workflow.signal + def proceed(self) -> None: + self._proceed = True + async def test_extstore_continue_as_new_result_stored_under_current_run( env: WorkflowEnvironment, @@ -1379,7 +1387,9 @@ async def test_extstore_continue_as_new_result_stored_under_current_run( id=f"workflow-{uuid.uuid4()}", task_queue=worker.task_queue, ) + # Capture the first run_id before signalling the workflow to proceed. first_run_id = (await handle.describe()).run_id + await handle.signal(ContinueAsNewExtStoreWorkflow.proceed) await handle.result() last_run_id = (await handle.describe()).run_id assert len(driver.store_contexts) == 3 From 53ff0651216efaa7c09d1cfa91d03bb9d5430e99 Mon Sep 17 00:00:00 2001 From: Brian Strauch Date: Thu, 23 Apr 2026 14:59:49 -0700 Subject: [PATCH 058/226] Fix race condition in test_update_payload_conversion (#1473) * fix race condition in test_update_payload_conversion * improve comment * trigger ci --- tests/test_serialization_context.py | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/tests/test_serialization_context.py b/tests/test_serialization_context.py index d3ce022f5..8e8fcf048 100644 --- a/tests/test_serialization_context.py +++ b/tests/test_serialization_context.py @@ -853,13 +853,13 @@ async def run(self, _pass_validation: bool) -> TraceData: @workflow.update def my_update(self, input: TraceData) -> TraceData: + self.input = input return input @my_update.validator def my_update_validator(self, input: TraceData) -> None: - self.input = input # for test purposes; update validators should not mutate workflow state if not self.pass_validation: - raise ValueError("Rejected") + raise ApplicationError("Rejected", input) @pytest.mark.parametrize("pass_validation", [True, False]) @@ -900,10 +900,12 @@ async def test_update_payload_conversion( UpdateSerializationContextTestWorkflow.my_update, TraceData() ) raise AssertionError("Expected WorkflowUpdateFailedError") - except WorkflowUpdateFailedError: - pass - - result = await wf_handle.result() + except WorkflowUpdateFailedError as e: + assert isinstance(e.cause, ApplicationError) + assert len(e.cause.details) == 1 + result = e.cause.details[0] + assert isinstance(result, TraceData) + await wf_handle.terminate() workflow_context = dataclasses.asdict( WorkflowSerializationContext( @@ -922,11 +924,11 @@ async def test_update_payload_conversion( ), TraceItem( method="to_payload", - context=workflow_context, # Outbound update/workflow result + context=workflow_context, # Outbound update result or error detail ), TraceItem( method="from_payload", - context=workflow_context, # Inbound update/workflow result + context=workflow_context, # Inbound update result or error detail ), ] From fb536f503a5c777e6737105b2f104e4dfcc362a2 Mon Sep 17 00:00:00 2001 From: Brian Strauch Date: Thu, 23 Apr 2026 14:59:59 -0700 Subject: [PATCH 059/226] Fix race condition in test_async_response (#1474) * fix race condition in test_async_response nexus test * revert uv.lock --- tests/nexus/test_workflow_caller.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/nexus/test_workflow_caller.py b/tests/nexus/test_workflow_caller.py index 18cfb40c0..38f51cd63 100644 --- a/tests/nexus/test_workflow_caller.py +++ b/tests/nexus/test_workflow_caller.py @@ -1191,10 +1191,10 @@ async def test_async_response( handler_wf_info = await handler_wf_handle.describe() assert handler_wf_info.status == WorkflowExecutionStatus.CANCELED else: - handler_wf_info = await handler_wf_handle.describe() - assert handler_wf_info.status == WorkflowExecutionStatus.COMPLETED result = await caller_wf_handle.result() assert result.op_output.value == "workflow result" + handler_wf_info = await handler_wf_handle.describe() + assert handler_wf_info.status == WorkflowExecutionStatus.COMPLETED async def _start_wf_and_nexus_op( From 8b5270dd427a84ed8111a3e4bcb9d675c3f5bde1 Mon Sep 17 00:00:00 2001 From: Brian Strauch Date: Thu, 23 Apr 2026 15:00:11 -0700 Subject: [PATCH 060/226] Fix race condition in test_cancellation_type for TRY_CANCEL (#1475) * fix race condition in test_cancellation_type for TRY_CANCEL * revert uv.lock --- ...w_caller_cancellation_types_when_cancel_handler_fails.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tests/nexus/test_workflow_caller_cancellation_types_when_cancel_handler_fails.py b/tests/nexus/test_workflow_caller_cancellation_types_when_cancel_handler_fails.py index 2e4ef401c..a344f1b5c 100644 --- a/tests/nexus/test_workflow_caller_cancellation_types_when_cancel_handler_fails.py +++ b/tests/nexus/test_workflow_caller_cancellation_types_when_cancel_handler_fails.py @@ -298,6 +298,12 @@ async def check_behavior_for_try_cancel( handler_wf: WorkflowHandle[Any, None], ) -> None: await handler_wf.result() + + cancel_request_failed = EventType.EVENT_TYPE_NEXUS_OPERATION_CANCEL_REQUEST_FAILED + async for event in caller_wf.fetch_history_events(wait_new_event=True): + if event.event_type == cancel_request_failed: + break + await caller_wf.signal(CallerWorkflow.release) result = await caller_wf.result() assert result.error_type == "NexusOperationError" From 58f2a686b6f94773d6939c6c3d77bae12cb1fb9b Mon Sep 17 00:00:00 2001 From: Brian Strauch Date: Thu, 23 Apr 2026 15:00:23 -0700 Subject: [PATCH 061/226] extend timeout for test_customer_service_workflow (#1476) --- tests/contrib/openai_agents/test_openai.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/contrib/openai_agents/test_openai.py b/tests/contrib/openai_agents/test_openai.py index c3895a72c..8824aac77 100644 --- a/tests/contrib/openai_agents/test_openai.py +++ b/tests/contrib/openai_agents/test_openai.py @@ -1016,7 +1016,7 @@ async def test_customer_service_workflow(client: Client, use_local_model: bool): CustomerServiceWorkflow.run, id=f"customer-service-{uuid.uuid4()}", task_queue=worker.task_queue, - execution_timeout=timedelta(seconds=30), + execution_timeout=timedelta(seconds=60), ) history: list[Any] = [] for q in questions: From d0ca632184565f1ea24fa34378f12cd8b87b122e Mon Sep 17 00:00:00 2001 From: Justin Anderson <44687433+jmaeagle99@users.noreply.github.com> Date: Mon, 27 Apr 2026 13:47:13 -0700 Subject: [PATCH 062/226] Update sdk-core submodule to latest (#1481) --- .gitmodules | 2 +- temporalio/api/activity/v1/__init__.py | 2 + temporalio/api/activity/v1/message_pb2.py | 61 +- temporalio/api/activity/v1/message_pb2.pyi | 87 + temporalio/api/callback/__init__.py | 0 temporalio/api/callback/v1/__init__.py | 5 + temporalio/api/callback/v1/message_pb2.py | 51 + temporalio/api/callback/v1/message_pb2.pyi | 112 ++ temporalio/api/command/v1/message_pb2.py | 70 +- temporalio/api/command/v1/message_pb2.pyi | 3 + temporalio/api/common/v1/__init__.py | 4 + temporalio/api/common/v1/message_pb2.py | 82 +- temporalio/api/common/v1/message_pb2.pyi | 145 +- temporalio/api/compute/__init__.py | 0 temporalio/api/compute/v1/__init__.py | 19 + temporalio/api/compute/v1/config_pb2.py | 147 ++ temporalio/api/compute/v1/config_pb2.pyi | 255 +++ temporalio/api/compute/v1/provider_pb2.py | 43 + temporalio/api/compute/v1/provider_pb2.pyi | 68 + temporalio/api/compute/v1/scaler_pb2.py | 43 + temporalio/api/compute/v1/scaler_pb2.pyi | 57 + temporalio/api/deployment/v1/message_pb2.py | 80 +- temporalio/api/deployment/v1/message_pb2.pyi | 64 +- temporalio/api/enums/v1/__init__.py | 12 +- temporalio/api/enums/v1/deployment_pb2.py | 5 +- temporalio/api/enums/v1/deployment_pb2.pyi | 13 +- temporalio/api/enums/v1/event_type_pb2.py | 5 +- temporalio/api/enums/v1/event_type_pb2.pyi | 4 + temporalio/api/enums/v1/nexus_pb2.py | 47 +- temporalio/api/enums/v1/nexus_pb2.pyi | 211 +++ temporalio/api/enums/v1/task_queue_pb2.py | 31 +- temporalio/api/enums/v1/task_queue_pb2.pyi | 12 + temporalio/api/enums/v1/workflow_pb2.py | 9 +- temporalio/api/enums/v1/workflow_pb2.pyi | 55 +- temporalio/api/errordetails/v1/__init__.py | 2 + temporalio/api/errordetails/v1/message_pb2.py | 18 +- .../api/errordetails/v1/message_pb2.pyi | 29 + temporalio/api/failure/v1/message_pb2.py | 40 +- temporalio/api/failure/v1/message_pb2.pyi | 17 +- temporalio/api/history/v1/__init__.py | 2 + temporalio/api/history/v1/message_pb2.py | 276 +-- temporalio/api/history/v1/message_pb2.pyi | 171 +- temporalio/api/nexus/v1/__init__.py | 6 + temporalio/api/nexus/v1/message_pb2.py | 158 +- temporalio/api/nexus/v1/message_pb2.pyi | 480 +++++ temporalio/api/nexusservices/__init__.py | 0 .../nexusservices/workerservice/__init__.py | 0 .../workerservice/v1/__init__.py | 6 + .../workerservice/v1/request_response_pb2.py | 57 + .../workerservice/v1/request_response_pb2.pyi | 80 + .../v1/request_response_pb2_grpc.py | 4 + .../v1/request_response_pb2_grpc.pyi | 4 + temporalio/api/sdk/v1/__init__.py | 2 + temporalio/api/sdk/v1/external_storage_pb2.py | 56 + .../api/sdk/v1/external_storage_pb2.pyi | 69 + temporalio/api/taskqueue/v1/__init__.py | 2 + temporalio/api/taskqueue/v1/message_pb2.py | 40 +- temporalio/api/taskqueue/v1/message_pb2.pyi | 21 +- temporalio/api/worker/v1/__init__.py | 8 + temporalio/api/worker/v1/message_pb2.py | 58 +- temporalio/api/worker/v1/message_pb2.pyi | 93 + temporalio/api/workflow/v1/__init__.py | 2 + temporalio/api/workflow/v1/message_pb2.py | 126 +- temporalio/api/workflow/v1/message_pb2.pyi | 123 +- temporalio/api/workflowservice/v1/__init__.py | 48 + .../v1/request_response_pb2.py | 1432 +++++++++----- .../v1/request_response_pb2.pyi | 1645 ++++++++++++++++- .../api/workflowservice/v1/service_pb2.py | 112 +- .../workflowservice/v1/service_pb2_grpc.py | 578 ++++++ .../workflowservice/v1/service_pb2_grpc.pyi | 220 +++ temporalio/bridge/Cargo.lock | 111 +- temporalio/bridge/Cargo.toml | 6 +- temporalio/bridge/sdk-core | 2 +- temporalio/bridge/services_generated.py | 216 +++ temporalio/bridge/src/client.rs | 8 +- temporalio/bridge/src/client_rpc_generated.rs | 108 ++ temporalio/bridge/src/worker.rs | 1 + 77 files changed, 7143 insertions(+), 1098 deletions(-) create mode 100644 temporalio/api/callback/__init__.py create mode 100644 temporalio/api/callback/v1/__init__.py create mode 100644 temporalio/api/callback/v1/message_pb2.py create mode 100644 temporalio/api/callback/v1/message_pb2.pyi create mode 100644 temporalio/api/compute/__init__.py create mode 100644 temporalio/api/compute/v1/__init__.py create mode 100644 temporalio/api/compute/v1/config_pb2.py create mode 100644 temporalio/api/compute/v1/config_pb2.pyi create mode 100644 temporalio/api/compute/v1/provider_pb2.py create mode 100644 temporalio/api/compute/v1/provider_pb2.pyi create mode 100644 temporalio/api/compute/v1/scaler_pb2.py create mode 100644 temporalio/api/compute/v1/scaler_pb2.pyi create mode 100644 temporalio/api/nexusservices/__init__.py create mode 100644 temporalio/api/nexusservices/workerservice/__init__.py create mode 100644 temporalio/api/nexusservices/workerservice/v1/__init__.py create mode 100644 temporalio/api/nexusservices/workerservice/v1/request_response_pb2.py create mode 100644 temporalio/api/nexusservices/workerservice/v1/request_response_pb2.pyi create mode 100644 temporalio/api/nexusservices/workerservice/v1/request_response_pb2_grpc.py create mode 100644 temporalio/api/nexusservices/workerservice/v1/request_response_pb2_grpc.pyi create mode 100644 temporalio/api/sdk/v1/external_storage_pb2.py create mode 100644 temporalio/api/sdk/v1/external_storage_pb2.pyi diff --git a/.gitmodules b/.gitmodules index ba2ba964a..a4c911631 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,3 @@ [submodule "sdk-core"] path = temporalio/bridge/sdk-core - url = https://github.com/temporalio/sdk-core.git + url = https://github.com/temporalio/sdk-rust.git diff --git a/temporalio/api/activity/v1/__init__.py b/temporalio/api/activity/v1/__init__.py index e86b0ef71..270022714 100644 --- a/temporalio/api/activity/v1/__init__.py +++ b/temporalio/api/activity/v1/__init__.py @@ -3,6 +3,7 @@ ActivityExecutionListInfo, ActivityExecutionOutcome, ActivityOptions, + CallbackInfo, ) __all__ = [ @@ -10,4 +11,5 @@ "ActivityExecutionListInfo", "ActivityExecutionOutcome", "ActivityOptions", + "CallbackInfo", ] diff --git a/temporalio/api/activity/v1/message_pb2.py b/temporalio/api/activity/v1/message_pb2.py index d67a8ca7b..4b039faff 100644 --- a/temporalio/api/activity/v1/message_pb2.py +++ b/temporalio/api/activity/v1/message_pb2.py @@ -17,6 +17,9 @@ from google.protobuf import duration_pb2 as google_dot_protobuf_dot_duration__pb2 from google.protobuf import timestamp_pb2 as google_dot_protobuf_dot_timestamp__pb2 +from temporalio.api.callback.v1 import ( + message_pb2 as temporal_dot_api_dot_callback_dot_v1_dot_message__pb2, +) from temporalio.api.common.v1 import ( message_pb2 as temporal_dot_api_dot_common_dot_v1_dot_message__pb2, ) @@ -40,7 +43,7 @@ ) DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile( - b'\n&temporal/api/activity/v1/message.proto\x12\x18temporal.api.activity.v1\x1a\x1egoogle/protobuf/duration.proto\x1a\x1fgoogle/protobuf/timestamp.proto\x1a$temporal/api/common/v1/message.proto\x1a(temporal/api/deployment/v1/message.proto\x1a$temporal/api/enums/v1/activity.proto\x1a$temporal/api/enums/v1/workflow.proto\x1a%temporal/api/failure/v1/message.proto\x1a\'temporal/api/taskqueue/v1/message.proto\x1a\'temporal/api/sdk/v1/user_metadata.proto"\x8c\x01\n\x18\x41\x63tivityExecutionOutcome\x12\x32\n\x06result\x18\x01 \x01(\x0b\x32 .temporal.api.common.v1.PayloadsH\x00\x12\x33\n\x07\x66\x61ilure\x18\x02 \x01(\x0b\x32 .temporal.api.failure.v1.FailureH\x00\x42\x07\n\x05value"\xa7\x03\n\x0f\x41\x63tivityOptions\x12\x38\n\ntask_queue\x18\x01 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12<\n\x19schedule_to_close_timeout\x18\x02 \x01(\x0b\x32\x19.google.protobuf.Duration\x12<\n\x19schedule_to_start_timeout\x18\x03 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x39\n\x16start_to_close_timeout\x18\x04 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x34\n\x11heartbeat_timeout\x18\x05 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x39\n\x0cretry_policy\x18\x06 \x01(\x0b\x32#.temporal.api.common.v1.RetryPolicy\x12\x32\n\x08priority\x18\x07 \x01(\x0b\x32 .temporal.api.common.v1.Priority"\xdf\x0c\n\x15\x41\x63tivityExecutionInfo\x12\x13\n\x0b\x61\x63tivity_id\x18\x01 \x01(\t\x12\x0e\n\x06run_id\x18\x02 \x01(\t\x12;\n\ractivity_type\x18\x03 \x01(\x0b\x32$.temporal.api.common.v1.ActivityType\x12>\n\x06status\x18\x04 \x01(\x0e\x32..temporal.api.enums.v1.ActivityExecutionStatus\x12>\n\trun_state\x18\x05 \x01(\x0e\x32+.temporal.api.enums.v1.PendingActivityState\x12\x12\n\ntask_queue\x18\x06 \x01(\t\x12<\n\x19schedule_to_close_timeout\x18\x07 \x01(\x0b\x32\x19.google.protobuf.Duration\x12<\n\x19schedule_to_start_timeout\x18\x08 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x39\n\x16start_to_close_timeout\x18\t \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x34\n\x11heartbeat_timeout\x18\n \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x39\n\x0cretry_policy\x18\x0b \x01(\x0b\x32#.temporal.api.common.v1.RetryPolicy\x12;\n\x11heartbeat_details\x18\x0c \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x37\n\x13last_heartbeat_time\x18\r \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x35\n\x11last_started_time\x18\x0e \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x0f\n\x07\x61ttempt\x18\x0f \x01(\x05\x12\x35\n\x12\x65xecution_duration\x18\x10 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x31\n\rschedule_time\x18\x11 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x33\n\x0f\x65xpiration_time\x18\x12 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12.\n\nclose_time\x18\x13 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x36\n\x0clast_failure\x18\x14 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12\x1c\n\x14last_worker_identity\x18\x15 \x01(\t\x12\x39\n\x16\x63urrent_retry_interval\x18\x16 \x01(\x0b\x32\x19.google.protobuf.Duration\x12>\n\x1alast_attempt_complete_time\x18\x17 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12>\n\x1anext_attempt_schedule_time\x18\x18 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12T\n\x17last_deployment_version\x18\x19 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersion\x12\x32\n\x08priority\x18\x1a \x01(\x0b\x32 .temporal.api.common.v1.Priority\x12\x1e\n\x16state_transition_count\x18\x1b \x01(\x03\x12\x18\n\x10state_size_bytes\x18\x1c \x01(\x03\x12\x43\n\x11search_attributes\x18\x1d \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes\x12.\n\x06header\x18\x1e \x01(\x0b\x32\x1e.temporal.api.common.v1.Header\x12\x38\n\ruser_metadata\x18\x1f \x01(\x0b\x32!.temporal.api.sdk.v1.UserMetadata\x12\x17\n\x0f\x63\x61nceled_reason\x18 \x01(\t"\xea\x03\n\x19\x41\x63tivityExecutionListInfo\x12\x13\n\x0b\x61\x63tivity_id\x18\x01 \x01(\t\x12\x0e\n\x06run_id\x18\x02 \x01(\t\x12;\n\ractivity_type\x18\x03 \x01(\x0b\x32$.temporal.api.common.v1.ActivityType\x12\x31\n\rschedule_time\x18\x04 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12.\n\nclose_time\x18\x05 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12>\n\x06status\x18\x06 \x01(\x0e\x32..temporal.api.enums.v1.ActivityExecutionStatus\x12\x43\n\x11search_attributes\x18\x07 \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes\x12\x12\n\ntask_queue\x18\x08 \x01(\t\x12\x1e\n\x16state_transition_count\x18\t \x01(\x03\x12\x18\n\x10state_size_bytes\x18\n \x01(\x03\x12\x35\n\x12\x65xecution_duration\x18\x0b \x01(\x0b\x32\x19.google.protobuf.DurationB\x93\x01\n\x1bio.temporal.api.activity.v1B\x0cMessageProtoP\x01Z\'go.temporal.io/api/activity/v1;activity\xaa\x02\x1aTemporalio.Api.Activity.V1\xea\x02\x1dTemporalio::Api::Activity::V1b\x06proto3' + b'\n&temporal/api/activity/v1/message.proto\x12\x18temporal.api.activity.v1\x1a\x1egoogle/protobuf/duration.proto\x1a\x1fgoogle/protobuf/timestamp.proto\x1a$temporal/api/common/v1/message.proto\x1a(temporal/api/deployment/v1/message.proto\x1a$temporal/api/enums/v1/activity.proto\x1a&temporal/api/callback/v1/message.proto\x1a$temporal/api/enums/v1/workflow.proto\x1a%temporal/api/failure/v1/message.proto\x1a\'temporal/api/taskqueue/v1/message.proto\x1a\'temporal/api/sdk/v1/user_metadata.proto"\x8c\x01\n\x18\x41\x63tivityExecutionOutcome\x12\x32\n\x06result\x18\x01 \x01(\x0b\x32 .temporal.api.common.v1.PayloadsH\x00\x12\x33\n\x07\x66\x61ilure\x18\x02 \x01(\x0b\x32 .temporal.api.failure.v1.FailureH\x00\x42\x07\n\x05value"\xa7\x03\n\x0f\x41\x63tivityOptions\x12\x38\n\ntask_queue\x18\x01 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12<\n\x19schedule_to_close_timeout\x18\x02 \x01(\x0b\x32\x19.google.protobuf.Duration\x12<\n\x19schedule_to_start_timeout\x18\x03 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x39\n\x16start_to_close_timeout\x18\x04 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x34\n\x11heartbeat_timeout\x18\x05 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x39\n\x0cretry_policy\x18\x06 \x01(\x0b\x32#.temporal.api.common.v1.RetryPolicy\x12\x32\n\x08priority\x18\x07 \x01(\x0b\x32 .temporal.api.common.v1.Priority"\xab\r\n\x15\x41\x63tivityExecutionInfo\x12\x13\n\x0b\x61\x63tivity_id\x18\x01 \x01(\t\x12\x0e\n\x06run_id\x18\x02 \x01(\t\x12;\n\ractivity_type\x18\x03 \x01(\x0b\x32$.temporal.api.common.v1.ActivityType\x12>\n\x06status\x18\x04 \x01(\x0e\x32..temporal.api.enums.v1.ActivityExecutionStatus\x12>\n\trun_state\x18\x05 \x01(\x0e\x32+.temporal.api.enums.v1.PendingActivityState\x12\x12\n\ntask_queue\x18\x06 \x01(\t\x12<\n\x19schedule_to_close_timeout\x18\x07 \x01(\x0b\x32\x19.google.protobuf.Duration\x12<\n\x19schedule_to_start_timeout\x18\x08 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x39\n\x16start_to_close_timeout\x18\t \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x34\n\x11heartbeat_timeout\x18\n \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x39\n\x0cretry_policy\x18\x0b \x01(\x0b\x32#.temporal.api.common.v1.RetryPolicy\x12;\n\x11heartbeat_details\x18\x0c \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x37\n\x13last_heartbeat_time\x18\r \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x35\n\x11last_started_time\x18\x0e \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x0f\n\x07\x61ttempt\x18\x0f \x01(\x05\x12\x35\n\x12\x65xecution_duration\x18\x10 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x31\n\rschedule_time\x18\x11 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x33\n\x0f\x65xpiration_time\x18\x12 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12.\n\nclose_time\x18\x13 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x36\n\x0clast_failure\x18\x14 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12\x1c\n\x14last_worker_identity\x18\x15 \x01(\t\x12\x39\n\x16\x63urrent_retry_interval\x18\x16 \x01(\x0b\x32\x19.google.protobuf.Duration\x12>\n\x1alast_attempt_complete_time\x18\x17 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12>\n\x1anext_attempt_schedule_time\x18\x18 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12T\n\x17last_deployment_version\x18\x19 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersion\x12\x32\n\x08priority\x18\x1a \x01(\x0b\x32 .temporal.api.common.v1.Priority\x12\x1e\n\x16state_transition_count\x18\x1b \x01(\x03\x12\x18\n\x10state_size_bytes\x18\x1c \x01(\x03\x12\x43\n\x11search_attributes\x18\x1d \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes\x12.\n\x06header\x18\x1e \x01(\x0b\x32\x1e.temporal.api.common.v1.Header\x12\x38\n\ruser_metadata\x18\x1f \x01(\x0b\x32!.temporal.api.sdk.v1.UserMetadata\x12\x17\n\x0f\x63\x61nceled_reason\x18 \x01(\t\x12+\n\x05links\x18! \x03(\x0b\x32\x1c.temporal.api.common.v1.Link\x12\x1d\n\x15total_heartbeat_count\x18" \x01(\x03"\xea\x03\n\x19\x41\x63tivityExecutionListInfo\x12\x13\n\x0b\x61\x63tivity_id\x18\x01 \x01(\t\x12\x0e\n\x06run_id\x18\x02 \x01(\t\x12;\n\ractivity_type\x18\x03 \x01(\x0b\x32$.temporal.api.common.v1.ActivityType\x12\x31\n\rschedule_time\x18\x04 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12.\n\nclose_time\x18\x05 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12>\n\x06status\x18\x06 \x01(\x0e\x32..temporal.api.enums.v1.ActivityExecutionStatus\x12\x43\n\x11search_attributes\x18\x07 \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes\x12\x12\n\ntask_queue\x18\x08 \x01(\t\x12\x1e\n\x16state_transition_count\x18\t \x01(\x03\x12\x18\n\x10state_size_bytes\x18\n \x01(\x03\x12\x35\n\x12\x65xecution_duration\x18\x0b \x01(\x0b\x32\x19.google.protobuf.Duration"\xff\x01\n\x0c\x43\x61llbackInfo\x12?\n\x07trigger\x18\x01 \x01(\x0b\x32..temporal.api.activity.v1.CallbackInfo.Trigger\x12\x34\n\x04info\x18\x02 \x01(\x0b\x32&.temporal.api.callback.v1.CallbackInfo\x1a\x10\n\x0e\x41\x63tivityClosed\x1a\x66\n\x07Trigger\x12P\n\x0f\x61\x63tivity_closed\x18\x01 \x01(\x0b\x32\x35.temporal.api.activity.v1.CallbackInfo.ActivityClosedH\x00\x42\t\n\x07variantB\x93\x01\n\x1bio.temporal.api.activity.v1B\x0cMessageProtoP\x01Z\'go.temporal.io/api/activity/v1;activity\xaa\x02\x1aTemporalio.Api.Activity.V1\xea\x02\x1dTemporalio::Api::Activity::V1b\x06proto3' ) @@ -50,6 +53,9 @@ _ACTIVITYEXECUTIONLISTINFO = DESCRIPTOR.message_types_by_name[ "ActivityExecutionListInfo" ] +_CALLBACKINFO = DESCRIPTOR.message_types_by_name["CallbackInfo"] +_CALLBACKINFO_ACTIVITYCLOSED = _CALLBACKINFO.nested_types_by_name["ActivityClosed"] +_CALLBACKINFO_TRIGGER = _CALLBACKINFO.nested_types_by_name["Trigger"] ActivityExecutionOutcome = _reflection.GeneratedProtocolMessageType( "ActivityExecutionOutcome", (_message.Message,), @@ -94,15 +100,52 @@ ) _sym_db.RegisterMessage(ActivityExecutionListInfo) +CallbackInfo = _reflection.GeneratedProtocolMessageType( + "CallbackInfo", + (_message.Message,), + { + "ActivityClosed": _reflection.GeneratedProtocolMessageType( + "ActivityClosed", + (_message.Message,), + { + "DESCRIPTOR": _CALLBACKINFO_ACTIVITYCLOSED, + "__module__": "temporalio.api.activity.v1.message_pb2", + # @@protoc_insertion_point(class_scope:temporal.api.activity.v1.CallbackInfo.ActivityClosed) + }, + ), + "Trigger": _reflection.GeneratedProtocolMessageType( + "Trigger", + (_message.Message,), + { + "DESCRIPTOR": _CALLBACKINFO_TRIGGER, + "__module__": "temporalio.api.activity.v1.message_pb2", + # @@protoc_insertion_point(class_scope:temporal.api.activity.v1.CallbackInfo.Trigger) + }, + ), + "DESCRIPTOR": _CALLBACKINFO, + "__module__": "temporalio.api.activity.v1.message_pb2", + # @@protoc_insertion_point(class_scope:temporal.api.activity.v1.CallbackInfo) + }, +) +_sym_db.RegisterMessage(CallbackInfo) +_sym_db.RegisterMessage(CallbackInfo.ActivityClosed) +_sym_db.RegisterMessage(CallbackInfo.Trigger) + if _descriptor._USE_C_DESCRIPTORS == False: DESCRIPTOR._options = None DESCRIPTOR._serialized_options = b"\n\033io.temporal.api.activity.v1B\014MessageProtoP\001Z'go.temporal.io/api/activity/v1;activity\252\002\032Temporalio.Api.Activity.V1\352\002\035Temporalio::Api::Activity::V1" - _ACTIVITYEXECUTIONOUTCOME._serialized_start = 411 - _ACTIVITYEXECUTIONOUTCOME._serialized_end = 551 - _ACTIVITYOPTIONS._serialized_start = 554 - _ACTIVITYOPTIONS._serialized_end = 977 - _ACTIVITYEXECUTIONINFO._serialized_start = 980 - _ACTIVITYEXECUTIONINFO._serialized_end = 2611 - _ACTIVITYEXECUTIONLISTINFO._serialized_start = 2614 - _ACTIVITYEXECUTIONLISTINFO._serialized_end = 3104 + _ACTIVITYEXECUTIONOUTCOME._serialized_start = 451 + _ACTIVITYEXECUTIONOUTCOME._serialized_end = 591 + _ACTIVITYOPTIONS._serialized_start = 594 + _ACTIVITYOPTIONS._serialized_end = 1017 + _ACTIVITYEXECUTIONINFO._serialized_start = 1020 + _ACTIVITYEXECUTIONINFO._serialized_end = 2727 + _ACTIVITYEXECUTIONLISTINFO._serialized_start = 2730 + _ACTIVITYEXECUTIONLISTINFO._serialized_end = 3220 + _CALLBACKINFO._serialized_start = 3223 + _CALLBACKINFO._serialized_end = 3478 + _CALLBACKINFO_ACTIVITYCLOSED._serialized_start = 3358 + _CALLBACKINFO_ACTIVITYCLOSED._serialized_end = 3374 + _CALLBACKINFO_TRIGGER._serialized_start = 3376 + _CALLBACKINFO_TRIGGER._serialized_end = 3478 # @@protoc_insertion_point(module_scope) diff --git a/temporalio/api/activity/v1/message_pb2.pyi b/temporalio/api/activity/v1/message_pb2.pyi index 080e479cd..a5770f03a 100644 --- a/temporalio/api/activity/v1/message_pb2.pyi +++ b/temporalio/api/activity/v1/message_pb2.pyi @@ -4,13 +4,16 @@ isort:skip_file """ import builtins +import collections.abc import sys import google.protobuf.descriptor import google.protobuf.duration_pb2 +import google.protobuf.internal.containers import google.protobuf.message import google.protobuf.timestamp_pb2 +import temporalio.api.callback.v1.message_pb2 import temporalio.api.common.v1.message_pb2 import temporalio.api.deployment.v1.message_pb2 import temporalio.api.enums.v1.activity_pb2 @@ -202,6 +205,8 @@ class ActivityExecutionInfo(google.protobuf.message.Message): HEADER_FIELD_NUMBER: builtins.int USER_METADATA_FIELD_NUMBER: builtins.int CANCELED_REASON_FIELD_NUMBER: builtins.int + LINKS_FIELD_NUMBER: builtins.int + TOTAL_HEARTBEAT_COUNT_FIELD_NUMBER: builtins.int activity_id: builtins.str """Unique identifier of this activity within its namespace along with run ID (below).""" run_id: builtins.str @@ -313,6 +318,15 @@ class ActivityExecutionInfo(google.protobuf.message.Message): """Metadata for use by user interfaces to display the fixed as-of-start summary and details of the activity.""" canceled_reason: builtins.str """Set if activity cancelation was requested.""" + @property + def links( + self, + ) -> google.protobuf.internal.containers.RepeatedCompositeFieldContainer[ + temporalio.api.common.v1.message_pb2.Link + ]: + """Links to related entities, such as the entity that started this activity.""" + total_heartbeat_count: builtins.int + """Total number of heartbeats recorded across all attempts of this activity, including retries.""" def __init__( self, *, @@ -353,6 +367,9 @@ class ActivityExecutionInfo(google.protobuf.message.Message): user_metadata: temporalio.api.sdk.v1.user_metadata_pb2.UserMetadata | None = ..., canceled_reason: builtins.str = ..., + links: collections.abc.Iterable[temporalio.api.common.v1.message_pb2.Link] + | None = ..., + total_heartbeat_count: builtins.int = ..., ) -> None: ... def HasField( self, @@ -440,6 +457,8 @@ class ActivityExecutionInfo(google.protobuf.message.Message): b"last_started_time", "last_worker_identity", b"last_worker_identity", + "links", + b"links", "next_attempt_schedule_time", b"next_attempt_schedule_time", "priority", @@ -468,6 +487,8 @@ class ActivityExecutionInfo(google.protobuf.message.Message): b"status", "task_queue", b"task_queue", + "total_heartbeat_count", + b"total_heartbeat_count", "user_metadata", b"user_metadata", ], @@ -587,3 +608,69 @@ class ActivityExecutionListInfo(google.protobuf.message.Message): ) -> None: ... global___ActivityExecutionListInfo = ActivityExecutionListInfo + +class CallbackInfo(google.protobuf.message.Message): + """CallbackInfo contains the state of an attached activity callback.""" + + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + class ActivityClosed(google.protobuf.message.Message): + """Trigger for when the activity is closed.""" + + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + def __init__( + self, + ) -> None: ... + + class Trigger(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + ACTIVITY_CLOSED_FIELD_NUMBER: builtins.int + @property + def activity_closed(self) -> global___CallbackInfo.ActivityClosed: ... + def __init__( + self, + *, + activity_closed: global___CallbackInfo.ActivityClosed | None = ..., + ) -> None: ... + def HasField( + self, + field_name: typing_extensions.Literal[ + "activity_closed", b"activity_closed", "variant", b"variant" + ], + ) -> builtins.bool: ... + def ClearField( + self, + field_name: typing_extensions.Literal[ + "activity_closed", b"activity_closed", "variant", b"variant" + ], + ) -> None: ... + def WhichOneof( + self, oneof_group: typing_extensions.Literal["variant", b"variant"] + ) -> typing_extensions.Literal["activity_closed"] | None: ... + + TRIGGER_FIELD_NUMBER: builtins.int + INFO_FIELD_NUMBER: builtins.int + @property + def trigger(self) -> global___CallbackInfo.Trigger: + """Trigger for this callback.""" + @property + def info(self) -> temporalio.api.callback.v1.message_pb2.CallbackInfo: + """Common callback info.""" + def __init__( + self, + *, + trigger: global___CallbackInfo.Trigger | None = ..., + info: temporalio.api.callback.v1.message_pb2.CallbackInfo | None = ..., + ) -> None: ... + def HasField( + self, + field_name: typing_extensions.Literal["info", b"info", "trigger", b"trigger"], + ) -> builtins.bool: ... + def ClearField( + self, + field_name: typing_extensions.Literal["info", b"info", "trigger", b"trigger"], + ) -> None: ... + +global___CallbackInfo = CallbackInfo diff --git a/temporalio/api/callback/__init__.py b/temporalio/api/callback/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/temporalio/api/callback/v1/__init__.py b/temporalio/api/callback/v1/__init__.py new file mode 100644 index 000000000..4e0d8fcc6 --- /dev/null +++ b/temporalio/api/callback/v1/__init__.py @@ -0,0 +1,5 @@ +from .message_pb2 import CallbackInfo + +__all__ = [ + "CallbackInfo", +] diff --git a/temporalio/api/callback/v1/message_pb2.py b/temporalio/api/callback/v1/message_pb2.py new file mode 100644 index 000000000..5d4ccb917 --- /dev/null +++ b/temporalio/api/callback/v1/message_pb2.py @@ -0,0 +1,51 @@ +# -*- coding: utf-8 -*- +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: temporal/api/callback/v1/message.proto +"""Generated protocol buffer code.""" + +from google.protobuf import descriptor as _descriptor +from google.protobuf import descriptor_pool as _descriptor_pool +from google.protobuf import message as _message +from google.protobuf import reflection as _reflection +from google.protobuf import symbol_database as _symbol_database + +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + +from google.protobuf import timestamp_pb2 as google_dot_protobuf_dot_timestamp__pb2 + +from temporalio.api.common.v1 import ( + message_pb2 as temporal_dot_api_dot_common_dot_v1_dot_message__pb2, +) +from temporalio.api.enums.v1 import ( + common_pb2 as temporal_dot_api_dot_enums_dot_v1_dot_common__pb2, +) +from temporalio.api.failure.v1 import ( + message_pb2 as temporal_dot_api_dot_failure_dot_v1_dot_message__pb2, +) + +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile( + b'\n&temporal/api/callback/v1/message.proto\x12\x18temporal.api.callback.v1\x1a\x1fgoogle/protobuf/timestamp.proto\x1a$temporal/api/common/v1/message.proto\x1a"temporal/api/enums/v1/common.proto\x1a%temporal/api/failure/v1/message.proto"\x97\x03\n\x0c\x43\x61llbackInfo\x12\x32\n\x08\x63\x61llback\x18\x01 \x01(\x0b\x32 .temporal.api.common.v1.Callback\x12\x35\n\x11registration_time\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x33\n\x05state\x18\x03 \x01(\x0e\x32$.temporal.api.enums.v1.CallbackState\x12\x0f\n\x07\x61ttempt\x18\x04 \x01(\x05\x12>\n\x1alast_attempt_complete_time\x18\x05 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12>\n\x14last_attempt_failure\x18\x06 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12>\n\x1anext_attempt_schedule_time\x18\x07 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x16\n\x0e\x62locked_reason\x18\x08 \x01(\tB\x93\x01\n\x1bio.temporal.api.callback.v1B\x0cMessageProtoP\x01Z\'go.temporal.io/api/callback/v1;callback\xaa\x02\x1aTemporalio.Api.Callback.V1\xea\x02\x1dTemporalio::Api::Callback::V1b\x06proto3' +) + + +_CALLBACKINFO = DESCRIPTOR.message_types_by_name["CallbackInfo"] +CallbackInfo = _reflection.GeneratedProtocolMessageType( + "CallbackInfo", + (_message.Message,), + { + "DESCRIPTOR": _CALLBACKINFO, + "__module__": "temporalio.api.callback.v1.message_pb2", + # @@protoc_insertion_point(class_scope:temporal.api.callback.v1.CallbackInfo) + }, +) +_sym_db.RegisterMessage(CallbackInfo) + +if _descriptor._USE_C_DESCRIPTORS == False: + DESCRIPTOR._options = None + DESCRIPTOR._serialized_options = b"\n\033io.temporal.api.callback.v1B\014MessageProtoP\001Z'go.temporal.io/api/callback/v1;callback\252\002\032Temporalio.Api.Callback.V1\352\002\035Temporalio::Api::Callback::V1" + _CALLBACKINFO._serialized_start = 215 + _CALLBACKINFO._serialized_end = 622 +# @@protoc_insertion_point(module_scope) diff --git a/temporalio/api/callback/v1/message_pb2.pyi b/temporalio/api/callback/v1/message_pb2.pyi new file mode 100644 index 000000000..ea7d6444b --- /dev/null +++ b/temporalio/api/callback/v1/message_pb2.pyi @@ -0,0 +1,112 @@ +""" +@generated by mypy-protobuf. Do not edit manually! +isort:skip_file +""" + +import builtins +import sys + +import google.protobuf.descriptor +import google.protobuf.message +import google.protobuf.timestamp_pb2 + +import temporalio.api.common.v1.message_pb2 +import temporalio.api.enums.v1.common_pb2 +import temporalio.api.failure.v1.message_pb2 + +if sys.version_info >= (3, 8): + import typing as typing_extensions +else: + import typing_extensions + +DESCRIPTOR: google.protobuf.descriptor.FileDescriptor + +class CallbackInfo(google.protobuf.message.Message): + """Common callback information. Specific CallbackInfo messages should embed this and may include additional fields.""" + + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + CALLBACK_FIELD_NUMBER: builtins.int + REGISTRATION_TIME_FIELD_NUMBER: builtins.int + STATE_FIELD_NUMBER: builtins.int + ATTEMPT_FIELD_NUMBER: builtins.int + LAST_ATTEMPT_COMPLETE_TIME_FIELD_NUMBER: builtins.int + LAST_ATTEMPT_FAILURE_FIELD_NUMBER: builtins.int + NEXT_ATTEMPT_SCHEDULE_TIME_FIELD_NUMBER: builtins.int + BLOCKED_REASON_FIELD_NUMBER: builtins.int + @property + def callback(self) -> temporalio.api.common.v1.message_pb2.Callback: + """Information on how this callback should be invoked (e.g. its URL and type).""" + @property + def registration_time(self) -> google.protobuf.timestamp_pb2.Timestamp: + """The time when the callback was registered.""" + state: temporalio.api.enums.v1.common_pb2.CallbackState.ValueType + """The current state of the callback.""" + attempt: builtins.int + """The number of attempts made to deliver the callback. + This number represents a minimum bound since the attempt is incremented after the callback request completes. + """ + @property + def last_attempt_complete_time(self) -> google.protobuf.timestamp_pb2.Timestamp: + """The time when the last attempt completed.""" + @property + def last_attempt_failure(self) -> temporalio.api.failure.v1.message_pb2.Failure: + """The last attempt's failure, if any.""" + @property + def next_attempt_schedule_time(self) -> google.protobuf.timestamp_pb2.Timestamp: + """The time when the next attempt is scheduled.""" + blocked_reason: builtins.str + """If the state is BLOCKED, blocked reason provides additional information.""" + def __init__( + self, + *, + callback: temporalio.api.common.v1.message_pb2.Callback | None = ..., + registration_time: google.protobuf.timestamp_pb2.Timestamp | None = ..., + state: temporalio.api.enums.v1.common_pb2.CallbackState.ValueType = ..., + attempt: builtins.int = ..., + last_attempt_complete_time: google.protobuf.timestamp_pb2.Timestamp + | None = ..., + last_attempt_failure: temporalio.api.failure.v1.message_pb2.Failure + | None = ..., + next_attempt_schedule_time: google.protobuf.timestamp_pb2.Timestamp + | None = ..., + blocked_reason: builtins.str = ..., + ) -> None: ... + def HasField( + self, + field_name: typing_extensions.Literal[ + "callback", + b"callback", + "last_attempt_complete_time", + b"last_attempt_complete_time", + "last_attempt_failure", + b"last_attempt_failure", + "next_attempt_schedule_time", + b"next_attempt_schedule_time", + "registration_time", + b"registration_time", + ], + ) -> builtins.bool: ... + def ClearField( + self, + field_name: typing_extensions.Literal[ + "attempt", + b"attempt", + "blocked_reason", + b"blocked_reason", + "callback", + b"callback", + "last_attempt_complete_time", + b"last_attempt_complete_time", + "last_attempt_failure", + b"last_attempt_failure", + "next_attempt_schedule_time", + b"next_attempt_schedule_time", + "registration_time", + b"registration_time", + "state", + b"state", + ], + ) -> None: ... + +global___CallbackInfo = CallbackInfo diff --git a/temporalio/api/command/v1/message_pb2.py b/temporalio/api/command/v1/message_pb2.py index 4ab0a2dcd..fe94363f5 100644 --- a/temporalio/api/command/v1/message_pb2.py +++ b/temporalio/api/command/v1/message_pb2.py @@ -36,7 +36,7 @@ ) DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile( - b'\n%temporal/api/command/v1/message.proto\x12\x17temporal.api.command.v1\x1a\x1egoogle/protobuf/duration.proto\x1a$temporal/api/enums/v1/workflow.proto\x1a(temporal/api/enums/v1/command_type.proto\x1a$temporal/api/common/v1/message.proto\x1a%temporal/api/failure/v1/message.proto\x1a\'temporal/api/taskqueue/v1/message.proto\x1a\'temporal/api/sdk/v1/user_metadata.proto"\xb6\x05\n%ScheduleActivityTaskCommandAttributes\x12\x13\n\x0b\x61\x63tivity_id\x18\x01 \x01(\t\x12;\n\ractivity_type\x18\x02 \x01(\x0b\x32$.temporal.api.common.v1.ActivityType\x12\x38\n\ntask_queue\x18\x04 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12.\n\x06header\x18\x05 \x01(\x0b\x32\x1e.temporal.api.common.v1.Header\x12/\n\x05input\x18\x06 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12<\n\x19schedule_to_close_timeout\x18\x07 \x01(\x0b\x32\x19.google.protobuf.Duration\x12<\n\x19schedule_to_start_timeout\x18\x08 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x39\n\x16start_to_close_timeout\x18\t \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x34\n\x11heartbeat_timeout\x18\n \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x39\n\x0cretry_policy\x18\x0b \x01(\x0b\x32#.temporal.api.common.v1.RetryPolicy\x12\x1f\n\x17request_eager_execution\x18\x0c \x01(\x08\x12\x1d\n\x15use_workflow_build_id\x18\r \x01(\x08\x12\x32\n\x08priority\x18\x0e \x01(\x0b\x32 .temporal.api.common.v1.PriorityJ\x04\x08\x03\x10\x04"H\n*RequestCancelActivityTaskCommandAttributes\x12\x1a\n\x12scheduled_event_id\x18\x01 \x01(\x03"i\n\x1bStartTimerCommandAttributes\x12\x10\n\x08timer_id\x18\x01 \x01(\t\x12\x38\n\x15start_to_fire_timeout\x18\x02 \x01(\x0b\x32\x19.google.protobuf.Duration"^\n*CompleteWorkflowExecutionCommandAttributes\x12\x30\n\x06result\x18\x01 \x01(\x0b\x32 .temporal.api.common.v1.Payloads"[\n&FailWorkflowExecutionCommandAttributes\x12\x31\n\x07\x66\x61ilure\x18\x01 \x01(\x0b\x32 .temporal.api.failure.v1.Failure"0\n\x1c\x43\x61ncelTimerCommandAttributes\x12\x10\n\x08timer_id\x18\x01 \x01(\t"]\n(CancelWorkflowExecutionCommandAttributes\x12\x31\n\x07\x64\x65tails\x18\x01 \x01(\x0b\x32 .temporal.api.common.v1.Payloads"\xb3\x01\n7RequestCancelExternalWorkflowExecutionCommandAttributes\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x12\x13\n\x07\x63ontrol\x18\x04 \x01(\tB\x02\x18\x01\x12\x1b\n\x13\x63hild_workflow_only\x18\x05 \x01(\x08\x12\x0e\n\x06reason\x18\x06 \x01(\t"\xab\x02\n0SignalExternalWorkflowExecutionCommandAttributes\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12<\n\texecution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x13\n\x0bsignal_name\x18\x03 \x01(\t\x12/\n\x05input\x18\x04 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x13\n\x07\x63ontrol\x18\x05 \x01(\tB\x02\x18\x01\x12\x1b\n\x13\x63hild_workflow_only\x18\x06 \x01(\x08\x12.\n\x06header\x18\x07 \x01(\x0b\x32\x1e.temporal.api.common.v1.Header"v\n/UpsertWorkflowSearchAttributesCommandAttributes\x12\x43\n\x11search_attributes\x18\x01 \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes"`\n)ModifyWorkflowPropertiesCommandAttributes\x12\x33\n\rupserted_memo\x18\x01 \x01(\x0b\x32\x1c.temporal.api.common.v1.Memo"\xbf\x02\n\x1dRecordMarkerCommandAttributes\x12\x13\n\x0bmarker_name\x18\x01 \x01(\t\x12T\n\x07\x64\x65tails\x18\x02 \x03(\x0b\x32\x43.temporal.api.command.v1.RecordMarkerCommandAttributes.DetailsEntry\x12.\n\x06header\x18\x03 \x01(\x0b\x32\x1e.temporal.api.common.v1.Header\x12\x31\n\x07\x66\x61ilure\x18\x04 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x1aP\n\x0c\x44\x65tailsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12/\n\x05value\x18\x02 \x01(\x0b\x32 .temporal.api.common.v1.Payloads:\x02\x38\x01"\xac\x07\n/ContinueAsNewWorkflowExecutionCommandAttributes\x12;\n\rworkflow_type\x18\x01 \x01(\x0b\x32$.temporal.api.common.v1.WorkflowType\x12\x38\n\ntask_queue\x18\x02 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12/\n\x05input\x18\x03 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x37\n\x14workflow_run_timeout\x18\x04 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x38\n\x15workflow_task_timeout\x18\x05 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x39\n\x16\x62\x61\x63koff_start_interval\x18\x06 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x39\n\x0cretry_policy\x18\x07 \x01(\x0b\x32#.temporal.api.common.v1.RetryPolicy\x12@\n\tinitiator\x18\x08 \x01(\x0e\x32-.temporal.api.enums.v1.ContinueAsNewInitiator\x12\x31\n\x07\x66\x61ilure\x18\t \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12@\n\x16last_completion_result\x18\n \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x15\n\rcron_schedule\x18\x0b \x01(\t\x12.\n\x06header\x18\x0c \x01(\x0b\x32\x1e.temporal.api.common.v1.Header\x12*\n\x04memo\x18\r \x01(\x0b\x32\x1c.temporal.api.common.v1.Memo\x12\x43\n\x11search_attributes\x18\x0e \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes\x12\x1c\n\x10inherit_build_id\x18\x0f \x01(\x08\x42\x02\x18\x01\x12[\n\x1binitial_versioning_behavior\x18\x10 \x01(\x0e\x32\x36.temporal.api.enums.v1.ContinueAsNewVersioningBehavior"\x9d\x07\n,StartChildWorkflowExecutionCommandAttributes\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12;\n\rworkflow_type\x18\x03 \x01(\x0b\x32$.temporal.api.common.v1.WorkflowType\x12\x38\n\ntask_queue\x18\x04 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12/\n\x05input\x18\x05 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12=\n\x1aworkflow_execution_timeout\x18\x06 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x37\n\x14workflow_run_timeout\x18\x07 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x38\n\x15workflow_task_timeout\x18\x08 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x45\n\x13parent_close_policy\x18\t \x01(\x0e\x32(.temporal.api.enums.v1.ParentClosePolicy\x12\x0f\n\x07\x63ontrol\x18\n \x01(\t\x12N\n\x18workflow_id_reuse_policy\x18\x0b \x01(\x0e\x32,.temporal.api.enums.v1.WorkflowIdReusePolicy\x12\x39\n\x0cretry_policy\x18\x0c \x01(\x0b\x32#.temporal.api.common.v1.RetryPolicy\x12\x15\n\rcron_schedule\x18\r \x01(\t\x12.\n\x06header\x18\x0e \x01(\x0b\x32\x1e.temporal.api.common.v1.Header\x12*\n\x04memo\x18\x0f \x01(\x0b\x32\x1c.temporal.api.common.v1.Memo\x12\x43\n\x11search_attributes\x18\x10 \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes\x12\x1c\n\x10inherit_build_id\x18\x11 \x01(\x08\x42\x02\x18\x01\x12\x32\n\x08priority\x18\x12 \x01(\x0b\x32 .temporal.api.common.v1.Priority"6\n ProtocolMessageCommandAttributes\x12\x12\n\nmessage_id\x18\x01 \x01(\t"\xe3\x03\n\'ScheduleNexusOperationCommandAttributes\x12\x10\n\x08\x65ndpoint\x18\x01 \x01(\t\x12\x0f\n\x07service\x18\x02 \x01(\t\x12\x11\n\toperation\x18\x03 \x01(\t\x12.\n\x05input\x18\x04 \x01(\x0b\x32\x1f.temporal.api.common.v1.Payload\x12<\n\x19schedule_to_close_timeout\x18\x05 \x01(\x0b\x32\x19.google.protobuf.Duration\x12g\n\x0cnexus_header\x18\x06 \x03(\x0b\x32Q.temporal.api.command.v1.ScheduleNexusOperationCommandAttributes.NexusHeaderEntry\x12<\n\x19schedule_to_start_timeout\x18\x07 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x39\n\x16start_to_close_timeout\x18\x08 \x01(\x0b\x32\x19.google.protobuf.Duration\x1a\x32\n\x10NexusHeaderEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01"J\n,RequestCancelNexusOperationCommandAttributes\x12\x1a\n\x12scheduled_event_id\x18\x01 \x01(\x03"\xc2\x11\n\x07\x43ommand\x12\x38\n\x0c\x63ommand_type\x18\x01 \x01(\x0e\x32".temporal.api.enums.v1.CommandType\x12\x39\n\ruser_metadata\x18\xad\x02 \x01(\x0b\x32!.temporal.api.sdk.v1.UserMetadata\x12s\n)schedule_activity_task_command_attributes\x18\x02 \x01(\x0b\x32>.temporal.api.command.v1.ScheduleActivityTaskCommandAttributesH\x00\x12^\n\x1estart_timer_command_attributes\x18\x03 \x01(\x0b\x32\x34.temporal.api.command.v1.StartTimerCommandAttributesH\x00\x12}\n.complete_workflow_execution_command_attributes\x18\x04 \x01(\x0b\x32\x43.temporal.api.command.v1.CompleteWorkflowExecutionCommandAttributesH\x00\x12u\n*fail_workflow_execution_command_attributes\x18\x05 \x01(\x0b\x32?.temporal.api.command.v1.FailWorkflowExecutionCommandAttributesH\x00\x12~\n/request_cancel_activity_task_command_attributes\x18\x06 \x01(\x0b\x32\x43.temporal.api.command.v1.RequestCancelActivityTaskCommandAttributesH\x00\x12`\n\x1f\x63\x61ncel_timer_command_attributes\x18\x07 \x01(\x0b\x32\x35.temporal.api.command.v1.CancelTimerCommandAttributesH\x00\x12y\n,cancel_workflow_execution_command_attributes\x18\x08 \x01(\x0b\x32\x41.temporal.api.command.v1.CancelWorkflowExecutionCommandAttributesH\x00\x12\x99\x01\n=request_cancel_external_workflow_execution_command_attributes\x18\t \x01(\x0b\x32P.temporal.api.command.v1.RequestCancelExternalWorkflowExecutionCommandAttributesH\x00\x12\x62\n record_marker_command_attributes\x18\n \x01(\x0b\x32\x36.temporal.api.command.v1.RecordMarkerCommandAttributesH\x00\x12\x89\x01\n5continue_as_new_workflow_execution_command_attributes\x18\x0b \x01(\x0b\x32H.temporal.api.command.v1.ContinueAsNewWorkflowExecutionCommandAttributesH\x00\x12\x82\x01\n1start_child_workflow_execution_command_attributes\x18\x0c \x01(\x0b\x32\x45.temporal.api.command.v1.StartChildWorkflowExecutionCommandAttributesH\x00\x12\x8a\x01\n5signal_external_workflow_execution_command_attributes\x18\r \x01(\x0b\x32I.temporal.api.command.v1.SignalExternalWorkflowExecutionCommandAttributesH\x00\x12\x88\x01\n4upsert_workflow_search_attributes_command_attributes\x18\x0e \x01(\x0b\x32H.temporal.api.command.v1.UpsertWorkflowSearchAttributesCommandAttributesH\x00\x12h\n#protocol_message_command_attributes\x18\x0f \x01(\x0b\x32\x39.temporal.api.command.v1.ProtocolMessageCommandAttributesH\x00\x12{\n-modify_workflow_properties_command_attributes\x18\x11 \x01(\x0b\x32\x42.temporal.api.command.v1.ModifyWorkflowPropertiesCommandAttributesH\x00\x12w\n+schedule_nexus_operation_command_attributes\x18\x12 \x01(\x0b\x32@.temporal.api.command.v1.ScheduleNexusOperationCommandAttributesH\x00\x12\x82\x01\n1request_cancel_nexus_operation_command_attributes\x18\x13 \x01(\x0b\x32\x45.temporal.api.command.v1.RequestCancelNexusOperationCommandAttributesH\x00\x42\x0c\n\nattributesB\x8e\x01\n\x1aio.temporal.api.command.v1B\x0cMessageProtoP\x01Z%go.temporal.io/api/command/v1;command\xaa\x02\x19Temporalio.Api.Command.V1\xea\x02\x1cTemporalio::Api::Command::V1b\x06proto3' + b'\n%temporal/api/command/v1/message.proto\x12\x17temporal.api.command.v1\x1a\x1egoogle/protobuf/duration.proto\x1a$temporal/api/enums/v1/workflow.proto\x1a(temporal/api/enums/v1/command_type.proto\x1a$temporal/api/common/v1/message.proto\x1a%temporal/api/failure/v1/message.proto\x1a\'temporal/api/taskqueue/v1/message.proto\x1a\'temporal/api/sdk/v1/user_metadata.proto"\xb6\x05\n%ScheduleActivityTaskCommandAttributes\x12\x13\n\x0b\x61\x63tivity_id\x18\x01 \x01(\t\x12;\n\ractivity_type\x18\x02 \x01(\x0b\x32$.temporal.api.common.v1.ActivityType\x12\x38\n\ntask_queue\x18\x04 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12.\n\x06header\x18\x05 \x01(\x0b\x32\x1e.temporal.api.common.v1.Header\x12/\n\x05input\x18\x06 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12<\n\x19schedule_to_close_timeout\x18\x07 \x01(\x0b\x32\x19.google.protobuf.Duration\x12<\n\x19schedule_to_start_timeout\x18\x08 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x39\n\x16start_to_close_timeout\x18\t \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x34\n\x11heartbeat_timeout\x18\n \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x39\n\x0cretry_policy\x18\x0b \x01(\x0b\x32#.temporal.api.common.v1.RetryPolicy\x12\x1f\n\x17request_eager_execution\x18\x0c \x01(\x08\x12\x1d\n\x15use_workflow_build_id\x18\r \x01(\x08\x12\x32\n\x08priority\x18\x0e \x01(\x0b\x32 .temporal.api.common.v1.PriorityJ\x04\x08\x03\x10\x04"H\n*RequestCancelActivityTaskCommandAttributes\x12\x1a\n\x12scheduled_event_id\x18\x01 \x01(\x03"i\n\x1bStartTimerCommandAttributes\x12\x10\n\x08timer_id\x18\x01 \x01(\t\x12\x38\n\x15start_to_fire_timeout\x18\x02 \x01(\x0b\x32\x19.google.protobuf.Duration"^\n*CompleteWorkflowExecutionCommandAttributes\x12\x30\n\x06result\x18\x01 \x01(\x0b\x32 .temporal.api.common.v1.Payloads"[\n&FailWorkflowExecutionCommandAttributes\x12\x31\n\x07\x66\x61ilure\x18\x01 \x01(\x0b\x32 .temporal.api.failure.v1.Failure"0\n\x1c\x43\x61ncelTimerCommandAttributes\x12\x10\n\x08timer_id\x18\x01 \x01(\t"]\n(CancelWorkflowExecutionCommandAttributes\x12\x31\n\x07\x64\x65tails\x18\x01 \x01(\x0b\x32 .temporal.api.common.v1.Payloads"\xb7\x01\n7RequestCancelExternalWorkflowExecutionCommandAttributes\x12\x15\n\tnamespace\x18\x01 \x01(\tB\x02\x18\x01\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x12\x13\n\x07\x63ontrol\x18\x04 \x01(\tB\x02\x18\x01\x12\x1b\n\x13\x63hild_workflow_only\x18\x05 \x01(\x08\x12\x0e\n\x06reason\x18\x06 \x01(\t"\xaf\x02\n0SignalExternalWorkflowExecutionCommandAttributes\x12\x15\n\tnamespace\x18\x01 \x01(\tB\x02\x18\x01\x12<\n\texecution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x13\n\x0bsignal_name\x18\x03 \x01(\t\x12/\n\x05input\x18\x04 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x13\n\x07\x63ontrol\x18\x05 \x01(\tB\x02\x18\x01\x12\x1b\n\x13\x63hild_workflow_only\x18\x06 \x01(\x08\x12.\n\x06header\x18\x07 \x01(\x0b\x32\x1e.temporal.api.common.v1.Header"v\n/UpsertWorkflowSearchAttributesCommandAttributes\x12\x43\n\x11search_attributes\x18\x01 \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes"`\n)ModifyWorkflowPropertiesCommandAttributes\x12\x33\n\rupserted_memo\x18\x01 \x01(\x0b\x32\x1c.temporal.api.common.v1.Memo"\xbf\x02\n\x1dRecordMarkerCommandAttributes\x12\x13\n\x0bmarker_name\x18\x01 \x01(\t\x12T\n\x07\x64\x65tails\x18\x02 \x03(\x0b\x32\x43.temporal.api.command.v1.RecordMarkerCommandAttributes.DetailsEntry\x12.\n\x06header\x18\x03 \x01(\x0b\x32\x1e.temporal.api.common.v1.Header\x12\x31\n\x07\x66\x61ilure\x18\x04 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x1aP\n\x0c\x44\x65tailsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12/\n\x05value\x18\x02 \x01(\x0b\x32 .temporal.api.common.v1.Payloads:\x02\x38\x01"\xac\x07\n/ContinueAsNewWorkflowExecutionCommandAttributes\x12;\n\rworkflow_type\x18\x01 \x01(\x0b\x32$.temporal.api.common.v1.WorkflowType\x12\x38\n\ntask_queue\x18\x02 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12/\n\x05input\x18\x03 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x37\n\x14workflow_run_timeout\x18\x04 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x38\n\x15workflow_task_timeout\x18\x05 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x39\n\x16\x62\x61\x63koff_start_interval\x18\x06 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x39\n\x0cretry_policy\x18\x07 \x01(\x0b\x32#.temporal.api.common.v1.RetryPolicy\x12@\n\tinitiator\x18\x08 \x01(\x0e\x32-.temporal.api.enums.v1.ContinueAsNewInitiator\x12\x31\n\x07\x66\x61ilure\x18\t \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12@\n\x16last_completion_result\x18\n \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x15\n\rcron_schedule\x18\x0b \x01(\t\x12.\n\x06header\x18\x0c \x01(\x0b\x32\x1e.temporal.api.common.v1.Header\x12*\n\x04memo\x18\r \x01(\x0b\x32\x1c.temporal.api.common.v1.Memo\x12\x43\n\x11search_attributes\x18\x0e \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes\x12\x1c\n\x10inherit_build_id\x18\x0f \x01(\x08\x42\x02\x18\x01\x12[\n\x1binitial_versioning_behavior\x18\x10 \x01(\x0e\x32\x36.temporal.api.enums.v1.ContinueAsNewVersioningBehavior"\xa1\x07\n,StartChildWorkflowExecutionCommandAttributes\x12\x15\n\tnamespace\x18\x01 \x01(\tB\x02\x18\x01\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12;\n\rworkflow_type\x18\x03 \x01(\x0b\x32$.temporal.api.common.v1.WorkflowType\x12\x38\n\ntask_queue\x18\x04 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12/\n\x05input\x18\x05 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12=\n\x1aworkflow_execution_timeout\x18\x06 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x37\n\x14workflow_run_timeout\x18\x07 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x38\n\x15workflow_task_timeout\x18\x08 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x45\n\x13parent_close_policy\x18\t \x01(\x0e\x32(.temporal.api.enums.v1.ParentClosePolicy\x12\x0f\n\x07\x63ontrol\x18\n \x01(\t\x12N\n\x18workflow_id_reuse_policy\x18\x0b \x01(\x0e\x32,.temporal.api.enums.v1.WorkflowIdReusePolicy\x12\x39\n\x0cretry_policy\x18\x0c \x01(\x0b\x32#.temporal.api.common.v1.RetryPolicy\x12\x15\n\rcron_schedule\x18\r \x01(\t\x12.\n\x06header\x18\x0e \x01(\x0b\x32\x1e.temporal.api.common.v1.Header\x12*\n\x04memo\x18\x0f \x01(\x0b\x32\x1c.temporal.api.common.v1.Memo\x12\x43\n\x11search_attributes\x18\x10 \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes\x12\x1c\n\x10inherit_build_id\x18\x11 \x01(\x08\x42\x02\x18\x01\x12\x32\n\x08priority\x18\x12 \x01(\x0b\x32 .temporal.api.common.v1.Priority"6\n ProtocolMessageCommandAttributes\x12\x12\n\nmessage_id\x18\x01 \x01(\t"\xe3\x03\n\'ScheduleNexusOperationCommandAttributes\x12\x10\n\x08\x65ndpoint\x18\x01 \x01(\t\x12\x0f\n\x07service\x18\x02 \x01(\t\x12\x11\n\toperation\x18\x03 \x01(\t\x12.\n\x05input\x18\x04 \x01(\x0b\x32\x1f.temporal.api.common.v1.Payload\x12<\n\x19schedule_to_close_timeout\x18\x05 \x01(\x0b\x32\x19.google.protobuf.Duration\x12g\n\x0cnexus_header\x18\x06 \x03(\x0b\x32Q.temporal.api.command.v1.ScheduleNexusOperationCommandAttributes.NexusHeaderEntry\x12<\n\x19schedule_to_start_timeout\x18\x07 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x39\n\x16start_to_close_timeout\x18\x08 \x01(\x0b\x32\x19.google.protobuf.Duration\x1a\x32\n\x10NexusHeaderEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01"J\n,RequestCancelNexusOperationCommandAttributes\x12\x1a\n\x12scheduled_event_id\x18\x01 \x01(\x03"\xc2\x11\n\x07\x43ommand\x12\x38\n\x0c\x63ommand_type\x18\x01 \x01(\x0e\x32".temporal.api.enums.v1.CommandType\x12\x39\n\ruser_metadata\x18\xad\x02 \x01(\x0b\x32!.temporal.api.sdk.v1.UserMetadata\x12s\n)schedule_activity_task_command_attributes\x18\x02 \x01(\x0b\x32>.temporal.api.command.v1.ScheduleActivityTaskCommandAttributesH\x00\x12^\n\x1estart_timer_command_attributes\x18\x03 \x01(\x0b\x32\x34.temporal.api.command.v1.StartTimerCommandAttributesH\x00\x12}\n.complete_workflow_execution_command_attributes\x18\x04 \x01(\x0b\x32\x43.temporal.api.command.v1.CompleteWorkflowExecutionCommandAttributesH\x00\x12u\n*fail_workflow_execution_command_attributes\x18\x05 \x01(\x0b\x32?.temporal.api.command.v1.FailWorkflowExecutionCommandAttributesH\x00\x12~\n/request_cancel_activity_task_command_attributes\x18\x06 \x01(\x0b\x32\x43.temporal.api.command.v1.RequestCancelActivityTaskCommandAttributesH\x00\x12`\n\x1f\x63\x61ncel_timer_command_attributes\x18\x07 \x01(\x0b\x32\x35.temporal.api.command.v1.CancelTimerCommandAttributesH\x00\x12y\n,cancel_workflow_execution_command_attributes\x18\x08 \x01(\x0b\x32\x41.temporal.api.command.v1.CancelWorkflowExecutionCommandAttributesH\x00\x12\x99\x01\n=request_cancel_external_workflow_execution_command_attributes\x18\t \x01(\x0b\x32P.temporal.api.command.v1.RequestCancelExternalWorkflowExecutionCommandAttributesH\x00\x12\x62\n record_marker_command_attributes\x18\n \x01(\x0b\x32\x36.temporal.api.command.v1.RecordMarkerCommandAttributesH\x00\x12\x89\x01\n5continue_as_new_workflow_execution_command_attributes\x18\x0b \x01(\x0b\x32H.temporal.api.command.v1.ContinueAsNewWorkflowExecutionCommandAttributesH\x00\x12\x82\x01\n1start_child_workflow_execution_command_attributes\x18\x0c \x01(\x0b\x32\x45.temporal.api.command.v1.StartChildWorkflowExecutionCommandAttributesH\x00\x12\x8a\x01\n5signal_external_workflow_execution_command_attributes\x18\r \x01(\x0b\x32I.temporal.api.command.v1.SignalExternalWorkflowExecutionCommandAttributesH\x00\x12\x88\x01\n4upsert_workflow_search_attributes_command_attributes\x18\x0e \x01(\x0b\x32H.temporal.api.command.v1.UpsertWorkflowSearchAttributesCommandAttributesH\x00\x12h\n#protocol_message_command_attributes\x18\x0f \x01(\x0b\x32\x39.temporal.api.command.v1.ProtocolMessageCommandAttributesH\x00\x12{\n-modify_workflow_properties_command_attributes\x18\x11 \x01(\x0b\x32\x42.temporal.api.command.v1.ModifyWorkflowPropertiesCommandAttributesH\x00\x12w\n+schedule_nexus_operation_command_attributes\x18\x12 \x01(\x0b\x32@.temporal.api.command.v1.ScheduleNexusOperationCommandAttributesH\x00\x12\x82\x01\n1request_cancel_nexus_operation_command_attributes\x18\x13 \x01(\x0b\x32\x45.temporal.api.command.v1.RequestCancelNexusOperationCommandAttributesH\x00\x42\x0c\n\nattributesB\x8e\x01\n\x1aio.temporal.api.command.v1B\x0cMessageProtoP\x01Z%go.temporal.io/api/command/v1;command\xaa\x02\x19Temporalio.Api.Command.V1\xea\x02\x1cTemporalio::Api::Command::V1b\x06proto3' ) @@ -329,12 +329,24 @@ if _descriptor._USE_C_DESCRIPTORS == False: DESCRIPTOR._options = None DESCRIPTOR._serialized_options = b"\n\032io.temporal.api.command.v1B\014MessageProtoP\001Z%go.temporal.io/api/command/v1;command\252\002\031Temporalio.Api.Command.V1\352\002\034Temporalio::Api::Command::V1" + _REQUESTCANCELEXTERNALWORKFLOWEXECUTIONCOMMANDATTRIBUTES.fields_by_name[ + "namespace" + ]._options = None + _REQUESTCANCELEXTERNALWORKFLOWEXECUTIONCOMMANDATTRIBUTES.fields_by_name[ + "namespace" + ]._serialized_options = b"\030\001" _REQUESTCANCELEXTERNALWORKFLOWEXECUTIONCOMMANDATTRIBUTES.fields_by_name[ "control" ]._options = None _REQUESTCANCELEXTERNALWORKFLOWEXECUTIONCOMMANDATTRIBUTES.fields_by_name[ "control" ]._serialized_options = b"\030\001" + _SIGNALEXTERNALWORKFLOWEXECUTIONCOMMANDATTRIBUTES.fields_by_name[ + "namespace" + ]._options = None + _SIGNALEXTERNALWORKFLOWEXECUTIONCOMMANDATTRIBUTES.fields_by_name[ + "namespace" + ]._serialized_options = b"\030\001" _SIGNALEXTERNALWORKFLOWEXECUTIONCOMMANDATTRIBUTES.fields_by_name[ "control" ]._options = None @@ -349,6 +361,12 @@ _CONTINUEASNEWWORKFLOWEXECUTIONCOMMANDATTRIBUTES.fields_by_name[ "inherit_build_id" ]._serialized_options = b"\030\001" + _STARTCHILDWORKFLOWEXECUTIONCOMMANDATTRIBUTES.fields_by_name[ + "namespace" + ]._options = None + _STARTCHILDWORKFLOWEXECUTIONCOMMANDATTRIBUTES.fields_by_name[ + "namespace" + ]._serialized_options = b"\030\001" _STARTCHILDWORKFLOWEXECUTIONCOMMANDATTRIBUTES.fields_by_name[ "inherit_build_id" ]._options = None @@ -374,29 +392,29 @@ _CANCELWORKFLOWEXECUTIONCOMMANDATTRIBUTES._serialized_start = 1454 _CANCELWORKFLOWEXECUTIONCOMMANDATTRIBUTES._serialized_end = 1547 _REQUESTCANCELEXTERNALWORKFLOWEXECUTIONCOMMANDATTRIBUTES._serialized_start = 1550 - _REQUESTCANCELEXTERNALWORKFLOWEXECUTIONCOMMANDATTRIBUTES._serialized_end = 1729 - _SIGNALEXTERNALWORKFLOWEXECUTIONCOMMANDATTRIBUTES._serialized_start = 1732 - _SIGNALEXTERNALWORKFLOWEXECUTIONCOMMANDATTRIBUTES._serialized_end = 2031 - _UPSERTWORKFLOWSEARCHATTRIBUTESCOMMANDATTRIBUTES._serialized_start = 2033 - _UPSERTWORKFLOWSEARCHATTRIBUTESCOMMANDATTRIBUTES._serialized_end = 2151 - _MODIFYWORKFLOWPROPERTIESCOMMANDATTRIBUTES._serialized_start = 2153 - _MODIFYWORKFLOWPROPERTIESCOMMANDATTRIBUTES._serialized_end = 2249 - _RECORDMARKERCOMMANDATTRIBUTES._serialized_start = 2252 - _RECORDMARKERCOMMANDATTRIBUTES._serialized_end = 2571 - _RECORDMARKERCOMMANDATTRIBUTES_DETAILSENTRY._serialized_start = 2491 - _RECORDMARKERCOMMANDATTRIBUTES_DETAILSENTRY._serialized_end = 2571 - _CONTINUEASNEWWORKFLOWEXECUTIONCOMMANDATTRIBUTES._serialized_start = 2574 - _CONTINUEASNEWWORKFLOWEXECUTIONCOMMANDATTRIBUTES._serialized_end = 3514 - _STARTCHILDWORKFLOWEXECUTIONCOMMANDATTRIBUTES._serialized_start = 3517 - _STARTCHILDWORKFLOWEXECUTIONCOMMANDATTRIBUTES._serialized_end = 4442 - _PROTOCOLMESSAGECOMMANDATTRIBUTES._serialized_start = 4444 - _PROTOCOLMESSAGECOMMANDATTRIBUTES._serialized_end = 4498 - _SCHEDULENEXUSOPERATIONCOMMANDATTRIBUTES._serialized_start = 4501 - _SCHEDULENEXUSOPERATIONCOMMANDATTRIBUTES._serialized_end = 4984 - _SCHEDULENEXUSOPERATIONCOMMANDATTRIBUTES_NEXUSHEADERENTRY._serialized_start = 4934 - _SCHEDULENEXUSOPERATIONCOMMANDATTRIBUTES_NEXUSHEADERENTRY._serialized_end = 4984 - _REQUESTCANCELNEXUSOPERATIONCOMMANDATTRIBUTES._serialized_start = 4986 - _REQUESTCANCELNEXUSOPERATIONCOMMANDATTRIBUTES._serialized_end = 5060 - _COMMAND._serialized_start = 5063 - _COMMAND._serialized_end = 7305 + _REQUESTCANCELEXTERNALWORKFLOWEXECUTIONCOMMANDATTRIBUTES._serialized_end = 1733 + _SIGNALEXTERNALWORKFLOWEXECUTIONCOMMANDATTRIBUTES._serialized_start = 1736 + _SIGNALEXTERNALWORKFLOWEXECUTIONCOMMANDATTRIBUTES._serialized_end = 2039 + _UPSERTWORKFLOWSEARCHATTRIBUTESCOMMANDATTRIBUTES._serialized_start = 2041 + _UPSERTWORKFLOWSEARCHATTRIBUTESCOMMANDATTRIBUTES._serialized_end = 2159 + _MODIFYWORKFLOWPROPERTIESCOMMANDATTRIBUTES._serialized_start = 2161 + _MODIFYWORKFLOWPROPERTIESCOMMANDATTRIBUTES._serialized_end = 2257 + _RECORDMARKERCOMMANDATTRIBUTES._serialized_start = 2260 + _RECORDMARKERCOMMANDATTRIBUTES._serialized_end = 2579 + _RECORDMARKERCOMMANDATTRIBUTES_DETAILSENTRY._serialized_start = 2499 + _RECORDMARKERCOMMANDATTRIBUTES_DETAILSENTRY._serialized_end = 2579 + _CONTINUEASNEWWORKFLOWEXECUTIONCOMMANDATTRIBUTES._serialized_start = 2582 + _CONTINUEASNEWWORKFLOWEXECUTIONCOMMANDATTRIBUTES._serialized_end = 3522 + _STARTCHILDWORKFLOWEXECUTIONCOMMANDATTRIBUTES._serialized_start = 3525 + _STARTCHILDWORKFLOWEXECUTIONCOMMANDATTRIBUTES._serialized_end = 4454 + _PROTOCOLMESSAGECOMMANDATTRIBUTES._serialized_start = 4456 + _PROTOCOLMESSAGECOMMANDATTRIBUTES._serialized_end = 4510 + _SCHEDULENEXUSOPERATIONCOMMANDATTRIBUTES._serialized_start = 4513 + _SCHEDULENEXUSOPERATIONCOMMANDATTRIBUTES._serialized_end = 4996 + _SCHEDULENEXUSOPERATIONCOMMANDATTRIBUTES_NEXUSHEADERENTRY._serialized_start = 4946 + _SCHEDULENEXUSOPERATIONCOMMANDATTRIBUTES_NEXUSHEADERENTRY._serialized_end = 4996 + _REQUESTCANCELNEXUSOPERATIONCOMMANDATTRIBUTES._serialized_start = 4998 + _REQUESTCANCELNEXUSOPERATIONCOMMANDATTRIBUTES._serialized_end = 5072 + _COMMAND._serialized_start = 5075 + _COMMAND._serialized_end = 7317 # @@protoc_insertion_point(module_scope) diff --git a/temporalio/api/command/v1/message_pb2.pyi b/temporalio/api/command/v1/message_pb2.pyi index ec7a900f9..1b6bb3404 100644 --- a/temporalio/api/command/v1/message_pb2.pyi +++ b/temporalio/api/command/v1/message_pb2.pyi @@ -332,6 +332,7 @@ class RequestCancelExternalWorkflowExecutionCommandAttributes( CHILD_WORKFLOW_ONLY_FIELD_NUMBER: builtins.int REASON_FIELD_NUMBER: builtins.int namespace: builtins.str + """Deprecated. Cross-namespace operations are disabled by default as of server 1.30.1.""" workflow_id: builtins.str run_id: builtins.str control: builtins.str @@ -386,6 +387,7 @@ class SignalExternalWorkflowExecutionCommandAttributes(google.protobuf.message.M CHILD_WORKFLOW_ONLY_FIELD_NUMBER: builtins.int HEADER_FIELD_NUMBER: builtins.int namespace: builtins.str + """Deprecated. Cross-namespace operations are disabled by default as of server 1.30.1.""" @property def execution(self) -> temporalio.api.common.v1.message_pb2.WorkflowExecution: ... signal_name: builtins.str @@ -757,6 +759,7 @@ class StartChildWorkflowExecutionCommandAttributes(google.protobuf.message.Messa INHERIT_BUILD_ID_FIELD_NUMBER: builtins.int PRIORITY_FIELD_NUMBER: builtins.int namespace: builtins.str + """Deprecated. Cross-namespace operations are disabled by default as of server 1.30.1.""" workflow_id: builtins.str @property def workflow_type(self) -> temporalio.api.common.v1.message_pb2.WorkflowType: ... diff --git a/temporalio/api/common/v1/__init__.py b/temporalio/api/common/v1/__init__.py index b3d074f41..112068861 100644 --- a/temporalio/api/common/v1/__init__.py +++ b/temporalio/api/common/v1/__init__.py @@ -7,8 +7,10 @@ Link, Memo, MeteringMetadata, + OnConflictOptions, Payload, Payloads, + Principal, Priority, ResetOptions, RetryPolicy, @@ -29,8 +31,10 @@ "Link", "Memo", "MeteringMetadata", + "OnConflictOptions", "Payload", "Payloads", + "Principal", "Priority", "ResetOptions", "RetryPolicy", diff --git a/temporalio/api/common/v1/message_pb2.py b/temporalio/api/common/v1/message_pb2.py index 0e27267a2..86a0c18fc 100644 --- a/temporalio/api/common/v1/message_pb2.py +++ b/temporalio/api/common/v1/message_pb2.py @@ -28,7 +28,7 @@ ) DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile( - b'\n$temporal/api/common/v1/message.proto\x12\x16temporal.api.common.v1\x1a\x1egoogle/protobuf/duration.proto\x1a\x1bgoogle/protobuf/empty.proto\x1a"temporal/api/enums/v1/common.proto\x1a&temporal/api/enums/v1/event_type.proto\x1a!temporal/api/enums/v1/reset.proto"T\n\x08\x44\x61taBlob\x12:\n\rencoding_type\x18\x01 \x01(\x0e\x32#.temporal.api.enums.v1.EncodingType\x12\x0c\n\x04\x64\x61ta\x18\x02 \x01(\x0c"=\n\x08Payloads\x12\x31\n\x08payloads\x18\x01 \x03(\x0b\x32\x1f.temporal.api.common.v1.Payload"\x8a\x02\n\x07Payload\x12?\n\x08metadata\x18\x01 \x03(\x0b\x32-.temporal.api.common.v1.Payload.MetadataEntry\x12\x0c\n\x04\x64\x61ta\x18\x02 \x01(\x0c\x12Q\n\x11\x65xternal_payloads\x18\x03 \x03(\x0b\x32\x36.temporal.api.common.v1.Payload.ExternalPayloadDetails\x1a/\n\rMetadataEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\x0c:\x02\x38\x01\x1a,\n\x16\x45xternalPayloadDetails\x12\x12\n\nsize_bytes\x18\x01 \x01(\x03"\xbe\x01\n\x10SearchAttributes\x12S\n\x0eindexed_fields\x18\x01 \x03(\x0b\x32;.temporal.api.common.v1.SearchAttributes.IndexedFieldsEntry\x1aU\n\x12IndexedFieldsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12.\n\x05value\x18\x02 \x01(\x0b\x32\x1f.temporal.api.common.v1.Payload:\x02\x38\x01"\x90\x01\n\x04Memo\x12\x38\n\x06\x66ields\x18\x01 \x03(\x0b\x32(.temporal.api.common.v1.Memo.FieldsEntry\x1aN\n\x0b\x46ieldsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12.\n\x05value\x18\x02 \x01(\x0b\x32\x1f.temporal.api.common.v1.Payload:\x02\x38\x01"\x94\x01\n\x06Header\x12:\n\x06\x66ields\x18\x01 \x03(\x0b\x32*.temporal.api.common.v1.Header.FieldsEntry\x1aN\n\x0b\x46ieldsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12.\n\x05value\x18\x02 \x01(\x0b\x32\x1f.temporal.api.common.v1.Payload:\x02\x38\x01"8\n\x11WorkflowExecution\x12\x13\n\x0bworkflow_id\x18\x01 \x01(\t\x12\x0e\n\x06run_id\x18\x02 \x01(\t"\x1c\n\x0cWorkflowType\x12\x0c\n\x04name\x18\x01 \x01(\t"\x1c\n\x0c\x41\x63tivityType\x12\x0c\n\x04name\x18\x01 \x01(\t"\xd1\x01\n\x0bRetryPolicy\x12\x33\n\x10initial_interval\x18\x01 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x1b\n\x13\x62\x61\x63koff_coefficient\x18\x02 \x01(\x01\x12\x33\n\x10maximum_interval\x18\x03 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x18\n\x10maximum_attempts\x18\x04 \x01(\x05\x12!\n\x19non_retryable_error_types\x18\x05 \x03(\t"F\n\x10MeteringMetadata\x12\x32\n*nonfirst_local_activity_execution_attempts\x18\r \x01(\r">\n\x12WorkerVersionStamp\x12\x10\n\x08\x62uild_id\x18\x01 \x01(\t\x12\x16\n\x0euse_versioning\x18\x03 \x01(\x08"e\n\x19WorkerVersionCapabilities\x12\x10\n\x08\x62uild_id\x18\x01 \x01(\t\x12\x16\n\x0euse_versioning\x18\x02 \x01(\x08\x12\x1e\n\x16\x64\x65ployment_series_name\x18\x04 \x01(\t"\xed\x02\n\x0cResetOptions\x12\x35\n\x13\x66irst_workflow_task\x18\x01 \x01(\x0b\x32\x16.google.protobuf.EmptyH\x00\x12\x34\n\x12last_workflow_task\x18\x02 \x01(\x0b\x32\x16.google.protobuf.EmptyH\x00\x12\x1a\n\x10workflow_task_id\x18\x03 \x01(\x03H\x00\x12\x12\n\x08\x62uild_id\x18\x04 \x01(\tH\x00\x12G\n\x12reset_reapply_type\x18\n \x01(\x0e\x32\'.temporal.api.enums.v1.ResetReapplyTypeB\x02\x18\x01\x12\x18\n\x10\x63urrent_run_only\x18\x0b \x01(\x08\x12S\n\x1breset_reapply_exclude_types\x18\x0c \x03(\x0e\x32..temporal.api.enums.v1.ResetReapplyExcludeTypeB\x08\n\x06target"\xe4\x02\n\x08\x43\x61llback\x12\x37\n\x05nexus\x18\x02 \x01(\x0b\x32&.temporal.api.common.v1.Callback.NexusH\x00\x12=\n\x08internal\x18\x03 \x01(\x0b\x32).temporal.api.common.v1.Callback.InternalH\x00\x12+\n\x05links\x18\x64 \x03(\x0b\x32\x1c.temporal.api.common.v1.Link\x1a\x87\x01\n\x05Nexus\x12\x0b\n\x03url\x18\x01 \x01(\t\x12\x42\n\x06header\x18\x02 \x03(\x0b\x32\x32.temporal.api.common.v1.Callback.Nexus.HeaderEntry\x1a-\n\x0bHeaderEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x1a\x18\n\x08Internal\x12\x0c\n\x04\x64\x61ta\x18\x01 \x01(\x0c\x42\t\n\x07variantJ\x04\x08\x01\x10\x02"\xe9\x04\n\x04Link\x12\x44\n\x0eworkflow_event\x18\x01 \x01(\x0b\x32*.temporal.api.common.v1.Link.WorkflowEventH\x00\x12:\n\tbatch_job\x18\x02 \x01(\x0b\x32%.temporal.api.common.v1.Link.BatchJobH\x00\x1a\xb7\x03\n\rWorkflowEvent\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x12N\n\tevent_ref\x18\x64 \x01(\x0b\x32\x39.temporal.api.common.v1.Link.WorkflowEvent.EventReferenceH\x00\x12W\n\x0erequest_id_ref\x18\x65 \x01(\x0b\x32=.temporal.api.common.v1.Link.WorkflowEvent.RequestIdReferenceH\x00\x1aX\n\x0e\x45ventReference\x12\x10\n\x08\x65vent_id\x18\x01 \x01(\x03\x12\x34\n\nevent_type\x18\x02 \x01(\x0e\x32 .temporal.api.enums.v1.EventType\x1a^\n\x12RequestIdReference\x12\x12\n\nrequest_id\x18\x01 \x01(\t\x12\x34\n\nevent_type\x18\x02 \x01(\x0e\x32 .temporal.api.enums.v1.EventTypeB\x0b\n\treference\x1a\x1a\n\x08\x42\x61tchJob\x12\x0e\n\x06job_id\x18\x01 \x01(\tB\t\n\x07variant"O\n\x08Priority\x12\x14\n\x0cpriority_key\x18\x01 \x01(\x05\x12\x14\n\x0c\x66\x61irness_key\x18\x02 \x01(\t\x12\x17\n\x0f\x66\x61irness_weight\x18\x03 \x01(\x02";\n\x0eWorkerSelector\x12\x1d\n\x13worker_instance_key\x18\x01 \x01(\tH\x00\x42\n\n\x08selectorB\x89\x01\n\x19io.temporal.api.common.v1B\x0cMessageProtoP\x01Z#go.temporal.io/api/common/v1;common\xaa\x02\x18Temporalio.Api.Common.V1\xea\x02\x1bTemporalio::Api::Common::V1b\x06proto3' + b'\n$temporal/api/common/v1/message.proto\x12\x16temporal.api.common.v1\x1a\x1egoogle/protobuf/duration.proto\x1a\x1bgoogle/protobuf/empty.proto\x1a"temporal/api/enums/v1/common.proto\x1a&temporal/api/enums/v1/event_type.proto\x1a!temporal/api/enums/v1/reset.proto"T\n\x08\x44\x61taBlob\x12:\n\rencoding_type\x18\x01 \x01(\x0e\x32#.temporal.api.enums.v1.EncodingType\x12\x0c\n\x04\x64\x61ta\x18\x02 \x01(\x0c"=\n\x08Payloads\x12\x31\n\x08payloads\x18\x01 \x03(\x0b\x32\x1f.temporal.api.common.v1.Payload"\x8a\x02\n\x07Payload\x12?\n\x08metadata\x18\x01 \x03(\x0b\x32-.temporal.api.common.v1.Payload.MetadataEntry\x12\x0c\n\x04\x64\x61ta\x18\x02 \x01(\x0c\x12Q\n\x11\x65xternal_payloads\x18\x03 \x03(\x0b\x32\x36.temporal.api.common.v1.Payload.ExternalPayloadDetails\x1a/\n\rMetadataEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\x0c:\x02\x38\x01\x1a,\n\x16\x45xternalPayloadDetails\x12\x12\n\nsize_bytes\x18\x01 \x01(\x03"\xbe\x01\n\x10SearchAttributes\x12S\n\x0eindexed_fields\x18\x01 \x03(\x0b\x32;.temporal.api.common.v1.SearchAttributes.IndexedFieldsEntry\x1aU\n\x12IndexedFieldsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12.\n\x05value\x18\x02 \x01(\x0b\x32\x1f.temporal.api.common.v1.Payload:\x02\x38\x01"\x90\x01\n\x04Memo\x12\x38\n\x06\x66ields\x18\x01 \x03(\x0b\x32(.temporal.api.common.v1.Memo.FieldsEntry\x1aN\n\x0b\x46ieldsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12.\n\x05value\x18\x02 \x01(\x0b\x32\x1f.temporal.api.common.v1.Payload:\x02\x38\x01"\x94\x01\n\x06Header\x12:\n\x06\x66ields\x18\x01 \x03(\x0b\x32*.temporal.api.common.v1.Header.FieldsEntry\x1aN\n\x0b\x46ieldsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12.\n\x05value\x18\x02 \x01(\x0b\x32\x1f.temporal.api.common.v1.Payload:\x02\x38\x01"8\n\x11WorkflowExecution\x12\x13\n\x0bworkflow_id\x18\x01 \x01(\t\x12\x0e\n\x06run_id\x18\x02 \x01(\t"\x1c\n\x0cWorkflowType\x12\x0c\n\x04name\x18\x01 \x01(\t"\x1c\n\x0c\x41\x63tivityType\x12\x0c\n\x04name\x18\x01 \x01(\t"\xd1\x01\n\x0bRetryPolicy\x12\x33\n\x10initial_interval\x18\x01 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x1b\n\x13\x62\x61\x63koff_coefficient\x18\x02 \x01(\x01\x12\x33\n\x10maximum_interval\x18\x03 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x18\n\x10maximum_attempts\x18\x04 \x01(\x05\x12!\n\x19non_retryable_error_types\x18\x05 \x03(\t"F\n\x10MeteringMetadata\x12\x32\n*nonfirst_local_activity_execution_attempts\x18\r \x01(\r">\n\x12WorkerVersionStamp\x12\x10\n\x08\x62uild_id\x18\x01 \x01(\t\x12\x16\n\x0euse_versioning\x18\x03 \x01(\x08"e\n\x19WorkerVersionCapabilities\x12\x10\n\x08\x62uild_id\x18\x01 \x01(\t\x12\x16\n\x0euse_versioning\x18\x02 \x01(\x08\x12\x1e\n\x16\x64\x65ployment_series_name\x18\x04 \x01(\t"\xed\x02\n\x0cResetOptions\x12\x35\n\x13\x66irst_workflow_task\x18\x01 \x01(\x0b\x32\x16.google.protobuf.EmptyH\x00\x12\x34\n\x12last_workflow_task\x18\x02 \x01(\x0b\x32\x16.google.protobuf.EmptyH\x00\x12\x1a\n\x10workflow_task_id\x18\x03 \x01(\x03H\x00\x12\x12\n\x08\x62uild_id\x18\x04 \x01(\tH\x00\x12G\n\x12reset_reapply_type\x18\n \x01(\x0e\x32\'.temporal.api.enums.v1.ResetReapplyTypeB\x02\x18\x01\x12\x18\n\x10\x63urrent_run_only\x18\x0b \x01(\x08\x12S\n\x1breset_reapply_exclude_types\x18\x0c \x03(\x0e\x32..temporal.api.enums.v1.ResetReapplyExcludeTypeB\x08\n\x06target"\xe4\x02\n\x08\x43\x61llback\x12\x37\n\x05nexus\x18\x02 \x01(\x0b\x32&.temporal.api.common.v1.Callback.NexusH\x00\x12=\n\x08internal\x18\x03 \x01(\x0b\x32).temporal.api.common.v1.Callback.InternalH\x00\x12+\n\x05links\x18\x64 \x03(\x0b\x32\x1c.temporal.api.common.v1.Link\x1a\x87\x01\n\x05Nexus\x12\x0b\n\x03url\x18\x01 \x01(\t\x12\x42\n\x06header\x18\x02 \x03(\x0b\x32\x32.temporal.api.common.v1.Callback.Nexus.HeaderEntry\x1a-\n\x0bHeaderEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x1a\x18\n\x08Internal\x12\x0c\n\x04\x64\x61ta\x18\x01 \x01(\x0c\x42\t\n\x07variantJ\x04\x08\x01\x10\x02"\xfb\x06\n\x04Link\x12\x44\n\x0eworkflow_event\x18\x01 \x01(\x0b\x32*.temporal.api.common.v1.Link.WorkflowEventH\x00\x12:\n\tbatch_job\x18\x02 \x01(\x0b\x32%.temporal.api.common.v1.Link.BatchJobH\x00\x12\x39\n\x08\x61\x63tivity\x18\x03 \x01(\x0b\x32%.temporal.api.common.v1.Link.ActivityH\x00\x12\x46\n\x0fnexus_operation\x18\x04 \x01(\x0b\x32+.temporal.api.common.v1.Link.NexusOperationH\x00\x1a\xb7\x03\n\rWorkflowEvent\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x12N\n\tevent_ref\x18\x64 \x01(\x0b\x32\x39.temporal.api.common.v1.Link.WorkflowEvent.EventReferenceH\x00\x12W\n\x0erequest_id_ref\x18\x65 \x01(\x0b\x32=.temporal.api.common.v1.Link.WorkflowEvent.RequestIdReferenceH\x00\x1aX\n\x0e\x45ventReference\x12\x10\n\x08\x65vent_id\x18\x01 \x01(\x03\x12\x34\n\nevent_type\x18\x02 \x01(\x0e\x32 .temporal.api.enums.v1.EventType\x1a^\n\x12RequestIdReference\x12\x12\n\nrequest_id\x18\x01 \x01(\t\x12\x34\n\nevent_type\x18\x02 \x01(\x0e\x32 .temporal.api.enums.v1.EventTypeB\x0b\n\treference\x1a\x1a\n\x08\x42\x61tchJob\x12\x0e\n\x06job_id\x18\x01 \x01(\t\x1a\x42\n\x08\x41\x63tivity\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0b\x61\x63tivity_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x1aI\n\x0eNexusOperation\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x14\n\x0coperation_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\tB\t\n\x07variant"\'\n\tPrincipal\x12\x0c\n\x04type\x18\x01 \x01(\t\x12\x0c\n\x04name\x18\x02 \x01(\t"O\n\x08Priority\x12\x14\n\x0cpriority_key\x18\x01 \x01(\x05\x12\x14\n\x0c\x66\x61irness_key\x18\x02 \x01(\t\x12\x17\n\x0f\x66\x61irness_weight\x18\x03 \x01(\x02";\n\x0eWorkerSelector\x12\x1d\n\x13worker_instance_key\x18\x01 \x01(\tH\x00\x42\n\n\x08selector"i\n\x11OnConflictOptions\x12\x19\n\x11\x61ttach_request_id\x18\x01 \x01(\x08\x12#\n\x1b\x61ttach_completion_callbacks\x18\x02 \x01(\x08\x12\x14\n\x0c\x61ttach_links\x18\x03 \x01(\x08\x42\x89\x01\n\x19io.temporal.api.common.v1B\x0cMessageProtoP\x01Z#go.temporal.io/api/common/v1;common\xaa\x02\x18Temporalio.Api.Common.V1\xea\x02\x1bTemporalio::Api::Common::V1b\x06proto3' ) @@ -70,8 +70,12 @@ "RequestIdReference" ] _LINK_BATCHJOB = _LINK.nested_types_by_name["BatchJob"] +_LINK_ACTIVITY = _LINK.nested_types_by_name["Activity"] +_LINK_NEXUSOPERATION = _LINK.nested_types_by_name["NexusOperation"] +_PRINCIPAL = DESCRIPTOR.message_types_by_name["Principal"] _PRIORITY = DESCRIPTOR.message_types_by_name["Priority"] _WORKERSELECTOR = DESCRIPTOR.message_types_by_name["WorkerSelector"] +_ONCONFLICTOPTIONS = DESCRIPTOR.message_types_by_name["OnConflictOptions"] DataBlob = _reflection.GeneratedProtocolMessageType( "DataBlob", (_message.Message,), @@ -357,6 +361,24 @@ # @@protoc_insertion_point(class_scope:temporal.api.common.v1.Link.BatchJob) }, ), + "Activity": _reflection.GeneratedProtocolMessageType( + "Activity", + (_message.Message,), + { + "DESCRIPTOR": _LINK_ACTIVITY, + "__module__": "temporalio.api.common.v1.message_pb2", + # @@protoc_insertion_point(class_scope:temporal.api.common.v1.Link.Activity) + }, + ), + "NexusOperation": _reflection.GeneratedProtocolMessageType( + "NexusOperation", + (_message.Message,), + { + "DESCRIPTOR": _LINK_NEXUSOPERATION, + "__module__": "temporalio.api.common.v1.message_pb2", + # @@protoc_insertion_point(class_scope:temporal.api.common.v1.Link.NexusOperation) + }, + ), "DESCRIPTOR": _LINK, "__module__": "temporalio.api.common.v1.message_pb2", # @@protoc_insertion_point(class_scope:temporal.api.common.v1.Link) @@ -367,6 +389,19 @@ _sym_db.RegisterMessage(Link.WorkflowEvent.EventReference) _sym_db.RegisterMessage(Link.WorkflowEvent.RequestIdReference) _sym_db.RegisterMessage(Link.BatchJob) +_sym_db.RegisterMessage(Link.Activity) +_sym_db.RegisterMessage(Link.NexusOperation) + +Principal = _reflection.GeneratedProtocolMessageType( + "Principal", + (_message.Message,), + { + "DESCRIPTOR": _PRINCIPAL, + "__module__": "temporalio.api.common.v1.message_pb2", + # @@protoc_insertion_point(class_scope:temporal.api.common.v1.Principal) + }, +) +_sym_db.RegisterMessage(Principal) Priority = _reflection.GeneratedProtocolMessageType( "Priority", @@ -390,6 +425,17 @@ ) _sym_db.RegisterMessage(WorkerSelector) +OnConflictOptions = _reflection.GeneratedProtocolMessageType( + "OnConflictOptions", + (_message.Message,), + { + "DESCRIPTOR": _ONCONFLICTOPTIONS, + "__module__": "temporalio.api.common.v1.message_pb2", + # @@protoc_insertion_point(class_scope:temporal.api.common.v1.OnConflictOptions) + }, +) +_sym_db.RegisterMessage(OnConflictOptions) + if _descriptor._USE_C_DESCRIPTORS == False: DESCRIPTOR._options = None DESCRIPTOR._serialized_options = b"\n\031io.temporal.api.common.v1B\014MessageProtoP\001Z#go.temporal.io/api/common/v1;common\252\002\030Temporalio.Api.Common.V1\352\002\033Temporalio::Api::Common::V1" @@ -452,17 +498,25 @@ _CALLBACK_INTERNAL._serialized_start = 2398 _CALLBACK_INTERNAL._serialized_end = 2422 _LINK._serialized_start = 2442 - _LINK._serialized_end = 3059 - _LINK_WORKFLOWEVENT._serialized_start = 2581 - _LINK_WORKFLOWEVENT._serialized_end = 3020 - _LINK_WORKFLOWEVENT_EVENTREFERENCE._serialized_start = 2823 - _LINK_WORKFLOWEVENT_EVENTREFERENCE._serialized_end = 2911 - _LINK_WORKFLOWEVENT_REQUESTIDREFERENCE._serialized_start = 2913 - _LINK_WORKFLOWEVENT_REQUESTIDREFERENCE._serialized_end = 3007 - _LINK_BATCHJOB._serialized_start = 3022 - _LINK_BATCHJOB._serialized_end = 3048 - _PRIORITY._serialized_start = 3061 - _PRIORITY._serialized_end = 3140 - _WORKERSELECTOR._serialized_start = 3142 - _WORKERSELECTOR._serialized_end = 3201 + _LINK._serialized_end = 3333 + _LINK_WORKFLOWEVENT._serialized_start = 2712 + _LINK_WORKFLOWEVENT._serialized_end = 3151 + _LINK_WORKFLOWEVENT_EVENTREFERENCE._serialized_start = 2954 + _LINK_WORKFLOWEVENT_EVENTREFERENCE._serialized_end = 3042 + _LINK_WORKFLOWEVENT_REQUESTIDREFERENCE._serialized_start = 3044 + _LINK_WORKFLOWEVENT_REQUESTIDREFERENCE._serialized_end = 3138 + _LINK_BATCHJOB._serialized_start = 3153 + _LINK_BATCHJOB._serialized_end = 3179 + _LINK_ACTIVITY._serialized_start = 3181 + _LINK_ACTIVITY._serialized_end = 3247 + _LINK_NEXUSOPERATION._serialized_start = 3249 + _LINK_NEXUSOPERATION._serialized_end = 3322 + _PRINCIPAL._serialized_start = 3335 + _PRINCIPAL._serialized_end = 3374 + _PRIORITY._serialized_start = 3376 + _PRIORITY._serialized_end = 3455 + _WORKERSELECTOR._serialized_start = 3457 + _WORKERSELECTOR._serialized_end = 3516 + _ONCONFLICTOPTIONS._serialized_start = 3518 + _ONCONFLICTOPTIONS._serialized_end = 3623 # @@protoc_insertion_point(module_scope) diff --git a/temporalio/api/common/v1/message_pb2.pyi b/temporalio/api/common/v1/message_pb2.pyi index 3cb11ce57..36685f976 100644 --- a/temporalio/api/common/v1/message_pb2.pyi +++ b/temporalio/api/common/v1/message_pb2.pyi @@ -883,23 +883,95 @@ class Link(google.protobuf.message.Message): self, field_name: typing_extensions.Literal["job_id", b"job_id"] ) -> None: ... + class Activity(google.protobuf.message.Message): + """A link to an activity.""" + + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + NAMESPACE_FIELD_NUMBER: builtins.int + ACTIVITY_ID_FIELD_NUMBER: builtins.int + RUN_ID_FIELD_NUMBER: builtins.int + namespace: builtins.str + activity_id: builtins.str + run_id: builtins.str + def __init__( + self, + *, + namespace: builtins.str = ..., + activity_id: builtins.str = ..., + run_id: builtins.str = ..., + ) -> None: ... + def ClearField( + self, + field_name: typing_extensions.Literal[ + "activity_id", + b"activity_id", + "namespace", + b"namespace", + "run_id", + b"run_id", + ], + ) -> None: ... + + class NexusOperation(google.protobuf.message.Message): + """A link to a standalone Nexus operation.""" + + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + NAMESPACE_FIELD_NUMBER: builtins.int + OPERATION_ID_FIELD_NUMBER: builtins.int + RUN_ID_FIELD_NUMBER: builtins.int + namespace: builtins.str + operation_id: builtins.str + run_id: builtins.str + def __init__( + self, + *, + namespace: builtins.str = ..., + operation_id: builtins.str = ..., + run_id: builtins.str = ..., + ) -> None: ... + def ClearField( + self, + field_name: typing_extensions.Literal[ + "namespace", + b"namespace", + "operation_id", + b"operation_id", + "run_id", + b"run_id", + ], + ) -> None: ... + WORKFLOW_EVENT_FIELD_NUMBER: builtins.int BATCH_JOB_FIELD_NUMBER: builtins.int + ACTIVITY_FIELD_NUMBER: builtins.int + NEXUS_OPERATION_FIELD_NUMBER: builtins.int @property def workflow_event(self) -> global___Link.WorkflowEvent: ... @property def batch_job(self) -> global___Link.BatchJob: ... + @property + def activity(self) -> global___Link.Activity: ... + @property + def nexus_operation(self) -> global___Link.NexusOperation: ... def __init__( self, *, workflow_event: global___Link.WorkflowEvent | None = ..., batch_job: global___Link.BatchJob | None = ..., + activity: global___Link.Activity | None = ..., + nexus_operation: global___Link.NexusOperation | None = ..., ) -> None: ... def HasField( self, field_name: typing_extensions.Literal[ + "activity", + b"activity", "batch_job", b"batch_job", + "nexus_operation", + b"nexus_operation", "variant", b"variant", "workflow_event", @@ -909,8 +981,12 @@ class Link(google.protobuf.message.Message): def ClearField( self, field_name: typing_extensions.Literal[ + "activity", + b"activity", "batch_job", b"batch_job", + "nexus_operation", + b"nexus_operation", "variant", b"variant", "workflow_event", @@ -919,10 +995,40 @@ class Link(google.protobuf.message.Message): ) -> None: ... def WhichOneof( self, oneof_group: typing_extensions.Literal["variant", b"variant"] - ) -> typing_extensions.Literal["workflow_event", "batch_job"] | None: ... + ) -> ( + typing_extensions.Literal[ + "workflow_event", "batch_job", "activity", "nexus_operation" + ] + | None + ): ... global___Link = Link +class Principal(google.protobuf.message.Message): + """Principal is an authenticated caller identity computed by the server from trusted + authentication context. + """ + + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + TYPE_FIELD_NUMBER: builtins.int + NAME_FIELD_NUMBER: builtins.int + type: builtins.str + """Low-cardinality category of the principal (e.g., "jwt", "users").""" + name: builtins.str + """Identifier within that category (e.g., sub JWT claim, email address).""" + def __init__( + self, + *, + type: builtins.str = ..., + name: builtins.str = ..., + ) -> None: ... + def ClearField( + self, field_name: typing_extensions.Literal["name", b"name", "type", b"type"] + ) -> None: ... + +global___Principal = Principal + class Priority(google.protobuf.message.Message): """Priority contains metadata that controls relative ordering of task processing when tasks are backed up in a queue. Initially, Priority will be used in @@ -1066,3 +1172,40 @@ class WorkerSelector(google.protobuf.message.Message): ) -> typing_extensions.Literal["worker_instance_key"] | None: ... global___WorkerSelector = WorkerSelector + +class OnConflictOptions(google.protobuf.message.Message): + """When starting an execution with a conflict policy that uses an existing execution and there is already an existing + running execution, OnConflictOptions defines actions to be taken on the existing running execution. + """ + + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + ATTACH_REQUEST_ID_FIELD_NUMBER: builtins.int + ATTACH_COMPLETION_CALLBACKS_FIELD_NUMBER: builtins.int + ATTACH_LINKS_FIELD_NUMBER: builtins.int + attach_request_id: builtins.bool + """Attaches the request ID to the running execution.""" + attach_completion_callbacks: builtins.bool + """Attaches the completion callbacks to the running execution.""" + attach_links: builtins.bool + """Attaches the links to the running execution.""" + def __init__( + self, + *, + attach_request_id: builtins.bool = ..., + attach_completion_callbacks: builtins.bool = ..., + attach_links: builtins.bool = ..., + ) -> None: ... + def ClearField( + self, + field_name: typing_extensions.Literal[ + "attach_completion_callbacks", + b"attach_completion_callbacks", + "attach_links", + b"attach_links", + "attach_request_id", + b"attach_request_id", + ], + ) -> None: ... + +global___OnConflictOptions = OnConflictOptions diff --git a/temporalio/api/compute/__init__.py b/temporalio/api/compute/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/temporalio/api/compute/v1/__init__.py b/temporalio/api/compute/v1/__init__.py new file mode 100644 index 000000000..816d11299 --- /dev/null +++ b/temporalio/api/compute/v1/__init__.py @@ -0,0 +1,19 @@ +from .config_pb2 import ( + ComputeConfig, + ComputeConfigScalingGroup, + ComputeConfigScalingGroupSummary, + ComputeConfigScalingGroupUpdate, + ComputeConfigSummary, +) +from .provider_pb2 import ComputeProvider +from .scaler_pb2 import ComputeScaler + +__all__ = [ + "ComputeConfig", + "ComputeConfigScalingGroup", + "ComputeConfigScalingGroupSummary", + "ComputeConfigScalingGroupUpdate", + "ComputeConfigSummary", + "ComputeProvider", + "ComputeScaler", +] diff --git a/temporalio/api/compute/v1/config_pb2.py b/temporalio/api/compute/v1/config_pb2.py new file mode 100644 index 000000000..ef3965397 --- /dev/null +++ b/temporalio/api/compute/v1/config_pb2.py @@ -0,0 +1,147 @@ +# -*- coding: utf-8 -*- +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: temporal/api/compute/v1/config.proto +"""Generated protocol buffer code.""" + +from google.protobuf import descriptor as _descriptor +from google.protobuf import descriptor_pool as _descriptor_pool +from google.protobuf import message as _message +from google.protobuf import reflection as _reflection +from google.protobuf import symbol_database as _symbol_database + +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + +from google.protobuf import field_mask_pb2 as google_dot_protobuf_dot_field__mask__pb2 + +from temporalio.api.compute.v1 import ( + provider_pb2 as temporal_dot_api_dot_compute_dot_v1_dot_provider__pb2, +) +from temporalio.api.compute.v1 import ( + scaler_pb2 as temporal_dot_api_dot_compute_dot_v1_dot_scaler__pb2, +) +from temporalio.api.enums.v1 import ( + task_queue_pb2 as temporal_dot_api_dot_enums_dot_v1_dot_task__queue__pb2, +) + +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile( + b'\n$temporal/api/compute/v1/config.proto\x12\x17temporal.api.compute.v1\x1a&temporal/api/compute/v1/provider.proto\x1a$temporal/api/compute/v1/scaler.proto\x1a&temporal/api/enums/v1/task_queue.proto\x1a google/protobuf/field_mask.proto"\xcf\x01\n\x19\x43omputeConfigScalingGroup\x12>\n\x10task_queue_types\x18\x01 \x03(\x0e\x32$.temporal.api.enums.v1.TaskQueueType\x12:\n\x08provider\x18\x03 \x01(\x0b\x32(.temporal.api.compute.v1.ComputeProvider\x12\x36\n\x06scaler\x18\x04 \x01(\x0b\x32&.temporal.api.compute.v1.ComputeScaler"\xcc\x01\n\rComputeConfig\x12Q\n\x0escaling_groups\x18\x01 \x03(\x0b\x32\x39.temporal.api.compute.v1.ComputeConfig.ScalingGroupsEntry\x1ah\n\x12ScalingGroupsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x41\n\x05value\x18\x02 \x01(\x0b\x32\x32.temporal.api.compute.v1.ComputeConfigScalingGroup:\x02\x38\x01"\x9d\x01\n\x1f\x43omputeConfigScalingGroupUpdate\x12I\n\rscaling_group\x18\x01 \x01(\x0b\x32\x32.temporal.api.compute.v1.ComputeConfigScalingGroup\x12/\n\x0bupdate_mask\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.FieldMask"\xe1\x01\n\x14\x43omputeConfigSummary\x12X\n\x0escaling_groups\x18\x01 \x03(\x0b\x32@.temporal.api.compute.v1.ComputeConfigSummary.ScalingGroupsEntry\x1ao\n\x12ScalingGroupsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12H\n\x05value\x18\x02 \x01(\x0b\x32\x39.temporal.api.compute.v1.ComputeConfigScalingGroupSummary:\x02\x38\x01"y\n ComputeConfigScalingGroupSummary\x12>\n\x10task_queue_types\x18\x01 \x03(\x0e\x32$.temporal.api.enums.v1.TaskQueueType\x12\x15\n\rprovider_type\x18\x02 \x01(\tB\x8d\x01\n\x1aio.temporal.api.compute.v1B\x0b\x43onfigProtoP\x01Z%go.temporal.io/api/compute/v1;compute\xaa\x02\x19Temporalio.Api.Compute.V1\xea\x02\x1cTemporalio::Api::Compute::V1b\x06proto3' +) + + +_COMPUTECONFIGSCALINGGROUP = DESCRIPTOR.message_types_by_name[ + "ComputeConfigScalingGroup" +] +_COMPUTECONFIG = DESCRIPTOR.message_types_by_name["ComputeConfig"] +_COMPUTECONFIG_SCALINGGROUPSENTRY = _COMPUTECONFIG.nested_types_by_name[ + "ScalingGroupsEntry" +] +_COMPUTECONFIGSCALINGGROUPUPDATE = DESCRIPTOR.message_types_by_name[ + "ComputeConfigScalingGroupUpdate" +] +_COMPUTECONFIGSUMMARY = DESCRIPTOR.message_types_by_name["ComputeConfigSummary"] +_COMPUTECONFIGSUMMARY_SCALINGGROUPSENTRY = _COMPUTECONFIGSUMMARY.nested_types_by_name[ + "ScalingGroupsEntry" +] +_COMPUTECONFIGSCALINGGROUPSUMMARY = DESCRIPTOR.message_types_by_name[ + "ComputeConfigScalingGroupSummary" +] +ComputeConfigScalingGroup = _reflection.GeneratedProtocolMessageType( + "ComputeConfigScalingGroup", + (_message.Message,), + { + "DESCRIPTOR": _COMPUTECONFIGSCALINGGROUP, + "__module__": "temporalio.api.compute.v1.config_pb2", + # @@protoc_insertion_point(class_scope:temporal.api.compute.v1.ComputeConfigScalingGroup) + }, +) +_sym_db.RegisterMessage(ComputeConfigScalingGroup) + +ComputeConfig = _reflection.GeneratedProtocolMessageType( + "ComputeConfig", + (_message.Message,), + { + "ScalingGroupsEntry": _reflection.GeneratedProtocolMessageType( + "ScalingGroupsEntry", + (_message.Message,), + { + "DESCRIPTOR": _COMPUTECONFIG_SCALINGGROUPSENTRY, + "__module__": "temporalio.api.compute.v1.config_pb2", + # @@protoc_insertion_point(class_scope:temporal.api.compute.v1.ComputeConfig.ScalingGroupsEntry) + }, + ), + "DESCRIPTOR": _COMPUTECONFIG, + "__module__": "temporalio.api.compute.v1.config_pb2", + # @@protoc_insertion_point(class_scope:temporal.api.compute.v1.ComputeConfig) + }, +) +_sym_db.RegisterMessage(ComputeConfig) +_sym_db.RegisterMessage(ComputeConfig.ScalingGroupsEntry) + +ComputeConfigScalingGroupUpdate = _reflection.GeneratedProtocolMessageType( + "ComputeConfigScalingGroupUpdate", + (_message.Message,), + { + "DESCRIPTOR": _COMPUTECONFIGSCALINGGROUPUPDATE, + "__module__": "temporalio.api.compute.v1.config_pb2", + # @@protoc_insertion_point(class_scope:temporal.api.compute.v1.ComputeConfigScalingGroupUpdate) + }, +) +_sym_db.RegisterMessage(ComputeConfigScalingGroupUpdate) + +ComputeConfigSummary = _reflection.GeneratedProtocolMessageType( + "ComputeConfigSummary", + (_message.Message,), + { + "ScalingGroupsEntry": _reflection.GeneratedProtocolMessageType( + "ScalingGroupsEntry", + (_message.Message,), + { + "DESCRIPTOR": _COMPUTECONFIGSUMMARY_SCALINGGROUPSENTRY, + "__module__": "temporalio.api.compute.v1.config_pb2", + # @@protoc_insertion_point(class_scope:temporal.api.compute.v1.ComputeConfigSummary.ScalingGroupsEntry) + }, + ), + "DESCRIPTOR": _COMPUTECONFIGSUMMARY, + "__module__": "temporalio.api.compute.v1.config_pb2", + # @@protoc_insertion_point(class_scope:temporal.api.compute.v1.ComputeConfigSummary) + }, +) +_sym_db.RegisterMessage(ComputeConfigSummary) +_sym_db.RegisterMessage(ComputeConfigSummary.ScalingGroupsEntry) + +ComputeConfigScalingGroupSummary = _reflection.GeneratedProtocolMessageType( + "ComputeConfigScalingGroupSummary", + (_message.Message,), + { + "DESCRIPTOR": _COMPUTECONFIGSCALINGGROUPSUMMARY, + "__module__": "temporalio.api.compute.v1.config_pb2", + # @@protoc_insertion_point(class_scope:temporal.api.compute.v1.ComputeConfigScalingGroupSummary) + }, +) +_sym_db.RegisterMessage(ComputeConfigScalingGroupSummary) + +if _descriptor._USE_C_DESCRIPTORS == False: + DESCRIPTOR._options = None + DESCRIPTOR._serialized_options = b"\n\032io.temporal.api.compute.v1B\013ConfigProtoP\001Z%go.temporal.io/api/compute/v1;compute\252\002\031Temporalio.Api.Compute.V1\352\002\034Temporalio::Api::Compute::V1" + _COMPUTECONFIG_SCALINGGROUPSENTRY._options = None + _COMPUTECONFIG_SCALINGGROUPSENTRY._serialized_options = b"8\001" + _COMPUTECONFIGSUMMARY_SCALINGGROUPSENTRY._options = None + _COMPUTECONFIGSUMMARY_SCALINGGROUPSENTRY._serialized_options = b"8\001" + _COMPUTECONFIGSCALINGGROUP._serialized_start = 218 + _COMPUTECONFIGSCALINGGROUP._serialized_end = 425 + _COMPUTECONFIG._serialized_start = 428 + _COMPUTECONFIG._serialized_end = 632 + _COMPUTECONFIG_SCALINGGROUPSENTRY._serialized_start = 528 + _COMPUTECONFIG_SCALINGGROUPSENTRY._serialized_end = 632 + _COMPUTECONFIGSCALINGGROUPUPDATE._serialized_start = 635 + _COMPUTECONFIGSCALINGGROUPUPDATE._serialized_end = 792 + _COMPUTECONFIGSUMMARY._serialized_start = 795 + _COMPUTECONFIGSUMMARY._serialized_end = 1020 + _COMPUTECONFIGSUMMARY_SCALINGGROUPSENTRY._serialized_start = 909 + _COMPUTECONFIGSUMMARY_SCALINGGROUPSENTRY._serialized_end = 1020 + _COMPUTECONFIGSCALINGGROUPSUMMARY._serialized_start = 1022 + _COMPUTECONFIGSCALINGGROUPSUMMARY._serialized_end = 1143 +# @@protoc_insertion_point(module_scope) diff --git a/temporalio/api/compute/v1/config_pb2.pyi b/temporalio/api/compute/v1/config_pb2.pyi new file mode 100644 index 000000000..7c0221f4c --- /dev/null +++ b/temporalio/api/compute/v1/config_pb2.pyi @@ -0,0 +1,255 @@ +""" +@generated by mypy-protobuf. Do not edit manually! +isort:skip_file +""" + +import builtins +import collections.abc +import sys + +import google.protobuf.descriptor +import google.protobuf.field_mask_pb2 +import google.protobuf.internal.containers +import google.protobuf.message + +import temporalio.api.compute.v1.provider_pb2 +import temporalio.api.compute.v1.scaler_pb2 +import temporalio.api.enums.v1.task_queue_pb2 + +if sys.version_info >= (3, 8): + import typing as typing_extensions +else: + import typing_extensions + +DESCRIPTOR: google.protobuf.descriptor.FileDescriptor + +class ComputeConfigScalingGroup(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + TASK_QUEUE_TYPES_FIELD_NUMBER: builtins.int + PROVIDER_FIELD_NUMBER: builtins.int + SCALER_FIELD_NUMBER: builtins.int + @property + def task_queue_types( + self, + ) -> google.protobuf.internal.containers.RepeatedScalarFieldContainer[ + temporalio.api.enums.v1.task_queue_pb2.TaskQueueType.ValueType + ]: + """Optional. The set of task queue types this scaling group serves. + If not provided, this scaling group serves all not otherwise defined + task types. + """ + @property + def provider(self) -> temporalio.api.compute.v1.provider_pb2.ComputeProvider: + """Stores instructions for a worker control plane controller how to respond + to worker lifeycle events. + """ + @property + def scaler(self) -> temporalio.api.compute.v1.scaler_pb2.ComputeScaler: + """Informs a worker lifecycle controller *when* and *how often* to perform + certain worker lifecycle actions like starting a serverless worker. + """ + def __init__( + self, + *, + task_queue_types: collections.abc.Iterable[ + temporalio.api.enums.v1.task_queue_pb2.TaskQueueType.ValueType + ] + | None = ..., + provider: temporalio.api.compute.v1.provider_pb2.ComputeProvider | None = ..., + scaler: temporalio.api.compute.v1.scaler_pb2.ComputeScaler | None = ..., + ) -> None: ... + def HasField( + self, + field_name: typing_extensions.Literal[ + "provider", b"provider", "scaler", b"scaler" + ], + ) -> builtins.bool: ... + def ClearField( + self, + field_name: typing_extensions.Literal[ + "provider", + b"provider", + "scaler", + b"scaler", + "task_queue_types", + b"task_queue_types", + ], + ) -> None: ... + +global___ComputeConfigScalingGroup = ComputeConfigScalingGroup + +class ComputeConfig(google.protobuf.message.Message): + """ComputeConfig stores configuration that helps a worker control plane + controller understand *when* and *how* to respond to worker lifecycle + events. + """ + + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + class ScalingGroupsEntry(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + KEY_FIELD_NUMBER: builtins.int + VALUE_FIELD_NUMBER: builtins.int + key: builtins.str + @property + def value(self) -> global___ComputeConfigScalingGroup: ... + def __init__( + self, + *, + key: builtins.str = ..., + value: global___ComputeConfigScalingGroup | None = ..., + ) -> None: ... + def HasField( + self, field_name: typing_extensions.Literal["value", b"value"] + ) -> builtins.bool: ... + def ClearField( + self, + field_name: typing_extensions.Literal["key", b"key", "value", b"value"], + ) -> None: ... + + SCALING_GROUPS_FIELD_NUMBER: builtins.int + @property + def scaling_groups( + self, + ) -> google.protobuf.internal.containers.MessageMap[ + builtins.str, global___ComputeConfigScalingGroup + ]: + """Each scaling group describes a compute config for a specific subset of the worker + deployment version: covering a specific set of task types and/or regions. + Having different configurations for different task types, allows independent + tuning of activity and workflow task processing (for example). + + The key of the map is the ID of the scaling group used to reference it in subsequent + update calls. + """ + def __init__( + self, + *, + scaling_groups: collections.abc.Mapping[ + builtins.str, global___ComputeConfigScalingGroup + ] + | None = ..., + ) -> None: ... + def ClearField( + self, field_name: typing_extensions.Literal["scaling_groups", b"scaling_groups"] + ) -> None: ... + +global___ComputeConfig = ComputeConfig + +class ComputeConfigScalingGroupUpdate(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + SCALING_GROUP_FIELD_NUMBER: builtins.int + UPDATE_MASK_FIELD_NUMBER: builtins.int + @property + def scaling_group(self) -> global___ComputeConfigScalingGroup: ... + @property + def update_mask(self) -> google.protobuf.field_mask_pb2.FieldMask: + """Controls which fields from `scaling_group` will be applied. Semantics: + - Mask is ignored for new scaling groups (only applicable when scaling group already exists). + - Empty mask for an existing scaling group is no-op: no change. + - Non-empty mask for an existing scaling group will update/unset only to the fields + mentioned in the mask. + - Accepted paths: "task_queue_types", "provider", "provider.type", "provider.details", + "provider.nexus_endpoint", "scaler", "scaler.type", "scaler.details" + """ + def __init__( + self, + *, + scaling_group: global___ComputeConfigScalingGroup | None = ..., + update_mask: google.protobuf.field_mask_pb2.FieldMask | None = ..., + ) -> None: ... + def HasField( + self, + field_name: typing_extensions.Literal[ + "scaling_group", b"scaling_group", "update_mask", b"update_mask" + ], + ) -> builtins.bool: ... + def ClearField( + self, + field_name: typing_extensions.Literal[ + "scaling_group", b"scaling_group", "update_mask", b"update_mask" + ], + ) -> None: ... + +global___ComputeConfigScalingGroupUpdate = ComputeConfigScalingGroupUpdate + +class ComputeConfigSummary(google.protobuf.message.Message): + """A subset of information in ComputeConfig optimized for list views.""" + + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + class ScalingGroupsEntry(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + KEY_FIELD_NUMBER: builtins.int + VALUE_FIELD_NUMBER: builtins.int + key: builtins.str + @property + def value(self) -> global___ComputeConfigScalingGroupSummary: ... + def __init__( + self, + *, + key: builtins.str = ..., + value: global___ComputeConfigScalingGroupSummary | None = ..., + ) -> None: ... + def HasField( + self, field_name: typing_extensions.Literal["value", b"value"] + ) -> builtins.bool: ... + def ClearField( + self, + field_name: typing_extensions.Literal["key", b"key", "value", b"value"], + ) -> None: ... + + SCALING_GROUPS_FIELD_NUMBER: builtins.int + @property + def scaling_groups( + self, + ) -> google.protobuf.internal.containers.MessageMap[ + builtins.str, global___ComputeConfigScalingGroupSummary + ]: ... + def __init__( + self, + *, + scaling_groups: collections.abc.Mapping[ + builtins.str, global___ComputeConfigScalingGroupSummary + ] + | None = ..., + ) -> None: ... + def ClearField( + self, field_name: typing_extensions.Literal["scaling_groups", b"scaling_groups"] + ) -> None: ... + +global___ComputeConfigSummary = ComputeConfigSummary + +class ComputeConfigScalingGroupSummary(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + TASK_QUEUE_TYPES_FIELD_NUMBER: builtins.int + PROVIDER_TYPE_FIELD_NUMBER: builtins.int + @property + def task_queue_types( + self, + ) -> google.protobuf.internal.containers.RepeatedScalarFieldContainer[ + temporalio.api.enums.v1.task_queue_pb2.TaskQueueType.ValueType + ]: ... + provider_type: builtins.str + def __init__( + self, + *, + task_queue_types: collections.abc.Iterable[ + temporalio.api.enums.v1.task_queue_pb2.TaskQueueType.ValueType + ] + | None = ..., + provider_type: builtins.str = ..., + ) -> None: ... + def ClearField( + self, + field_name: typing_extensions.Literal[ + "provider_type", b"provider_type", "task_queue_types", b"task_queue_types" + ], + ) -> None: ... + +global___ComputeConfigScalingGroupSummary = ComputeConfigScalingGroupSummary diff --git a/temporalio/api/compute/v1/provider_pb2.py b/temporalio/api/compute/v1/provider_pb2.py new file mode 100644 index 000000000..26d921e2b --- /dev/null +++ b/temporalio/api/compute/v1/provider_pb2.py @@ -0,0 +1,43 @@ +# -*- coding: utf-8 -*- +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: temporal/api/compute/v1/provider.proto +"""Generated protocol buffer code.""" + +from google.protobuf import descriptor as _descriptor +from google.protobuf import descriptor_pool as _descriptor_pool +from google.protobuf import message as _message +from google.protobuf import reflection as _reflection +from google.protobuf import symbol_database as _symbol_database + +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + +from temporalio.api.common.v1 import ( + message_pb2 as temporal_dot_api_dot_common_dot_v1_dot_message__pb2, +) + +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile( + b'\n&temporal/api/compute/v1/provider.proto\x12\x17temporal.api.compute.v1\x1a$temporal/api/common/v1/message.proto"i\n\x0f\x43omputeProvider\x12\x0c\n\x04type\x18\x01 \x01(\t\x12\x30\n\x07\x64\x65tails\x18\x02 \x01(\x0b\x32\x1f.temporal.api.common.v1.Payload\x12\x16\n\x0enexus_endpoint\x18\n \x01(\tB\x8f\x01\n\x1aio.temporal.api.compute.v1B\rProviderProtoP\x01Z%go.temporal.io/api/compute/v1;compute\xaa\x02\x19Temporalio.Api.Compute.V1\xea\x02\x1cTemporalio::Api::Compute::V1b\x06proto3' +) + + +_COMPUTEPROVIDER = DESCRIPTOR.message_types_by_name["ComputeProvider"] +ComputeProvider = _reflection.GeneratedProtocolMessageType( + "ComputeProvider", + (_message.Message,), + { + "DESCRIPTOR": _COMPUTEPROVIDER, + "__module__": "temporalio.api.compute.v1.provider_pb2", + # @@protoc_insertion_point(class_scope:temporal.api.compute.v1.ComputeProvider) + }, +) +_sym_db.RegisterMessage(ComputeProvider) + +if _descriptor._USE_C_DESCRIPTORS == False: + DESCRIPTOR._options = None + DESCRIPTOR._serialized_options = b"\n\032io.temporal.api.compute.v1B\rProviderProtoP\001Z%go.temporal.io/api/compute/v1;compute\252\002\031Temporalio.Api.Compute.V1\352\002\034Temporalio::Api::Compute::V1" + _COMPUTEPROVIDER._serialized_start = 105 + _COMPUTEPROVIDER._serialized_end = 210 +# @@protoc_insertion_point(module_scope) diff --git a/temporalio/api/compute/v1/provider_pb2.pyi b/temporalio/api/compute/v1/provider_pb2.pyi new file mode 100644 index 000000000..90f566aa4 --- /dev/null +++ b/temporalio/api/compute/v1/provider_pb2.pyi @@ -0,0 +1,68 @@ +""" +@generated by mypy-protobuf. Do not edit manually! +isort:skip_file +""" + +import builtins +import sys + +import google.protobuf.descriptor +import google.protobuf.message + +import temporalio.api.common.v1.message_pb2 + +if sys.version_info >= (3, 8): + import typing as typing_extensions +else: + import typing_extensions + +DESCRIPTOR: google.protobuf.descriptor.FileDescriptor + +class ComputeProvider(google.protobuf.message.Message): + """ComputeProvider stores information used by a worker control plane controller + to respond to worker lifecycle events. For example, when a Task is received + on a TaskQueue that has no active pollers, a serverless worker lifecycle + controller might need to invoke an AWS Lambda Function that itself ends up + calling the SDK's worker.New() function. + """ + + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + TYPE_FIELD_NUMBER: builtins.int + DETAILS_FIELD_NUMBER: builtins.int + NEXUS_ENDPOINT_FIELD_NUMBER: builtins.int + type: builtins.str + """Type of the compute provider. This string is implementation-specific and + can be used by implementations to understand how to interpret the + contents of the provider_details field. + """ + @property + def details(self) -> temporalio.api.common.v1.message_pb2.Payload: + """Contains provider-specific instructions and configuration. + For server-implemented providers, use the SDK's default content + converter to ensure the server can understand it. + For remote-implemented providers, you might use your own content + converters according to what the remote endpoints understand. + """ + nexus_endpoint: builtins.str + """Optional. If the compute provider is a Nexus service, this should point + there. + """ + def __init__( + self, + *, + type: builtins.str = ..., + details: temporalio.api.common.v1.message_pb2.Payload | None = ..., + nexus_endpoint: builtins.str = ..., + ) -> None: ... + def HasField( + self, field_name: typing_extensions.Literal["details", b"details"] + ) -> builtins.bool: ... + def ClearField( + self, + field_name: typing_extensions.Literal[ + "details", b"details", "nexus_endpoint", b"nexus_endpoint", "type", b"type" + ], + ) -> None: ... + +global___ComputeProvider = ComputeProvider diff --git a/temporalio/api/compute/v1/scaler_pb2.py b/temporalio/api/compute/v1/scaler_pb2.py new file mode 100644 index 000000000..84bfe7b24 --- /dev/null +++ b/temporalio/api/compute/v1/scaler_pb2.py @@ -0,0 +1,43 @@ +# -*- coding: utf-8 -*- +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: temporal/api/compute/v1/scaler.proto +"""Generated protocol buffer code.""" + +from google.protobuf import descriptor as _descriptor +from google.protobuf import descriptor_pool as _descriptor_pool +from google.protobuf import message as _message +from google.protobuf import reflection as _reflection +from google.protobuf import symbol_database as _symbol_database + +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + +from temporalio.api.common.v1 import ( + message_pb2 as temporal_dot_api_dot_common_dot_v1_dot_message__pb2, +) + +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile( + b'\n$temporal/api/compute/v1/scaler.proto\x12\x17temporal.api.compute.v1\x1a$temporal/api/common/v1/message.proto"O\n\rComputeScaler\x12\x0c\n\x04type\x18\x01 \x01(\t\x12\x30\n\x07\x64\x65tails\x18\x02 \x01(\x0b\x32\x1f.temporal.api.common.v1.PayloadB\x8d\x01\n\x1aio.temporal.api.compute.v1B\x0bScalerProtoP\x01Z%go.temporal.io/api/compute/v1;compute\xaa\x02\x19Temporalio.Api.Compute.V1\xea\x02\x1cTemporalio::Api::Compute::V1b\x06proto3' +) + + +_COMPUTESCALER = DESCRIPTOR.message_types_by_name["ComputeScaler"] +ComputeScaler = _reflection.GeneratedProtocolMessageType( + "ComputeScaler", + (_message.Message,), + { + "DESCRIPTOR": _COMPUTESCALER, + "__module__": "temporalio.api.compute.v1.scaler_pb2", + # @@protoc_insertion_point(class_scope:temporal.api.compute.v1.ComputeScaler) + }, +) +_sym_db.RegisterMessage(ComputeScaler) + +if _descriptor._USE_C_DESCRIPTORS == False: + DESCRIPTOR._options = None + DESCRIPTOR._serialized_options = b"\n\032io.temporal.api.compute.v1B\013ScalerProtoP\001Z%go.temporal.io/api/compute/v1;compute\252\002\031Temporalio.Api.Compute.V1\352\002\034Temporalio::Api::Compute::V1" + _COMPUTESCALER._serialized_start = 103 + _COMPUTESCALER._serialized_end = 182 +# @@protoc_insertion_point(module_scope) diff --git a/temporalio/api/compute/v1/scaler_pb2.pyi b/temporalio/api/compute/v1/scaler_pb2.pyi new file mode 100644 index 000000000..3ff933055 --- /dev/null +++ b/temporalio/api/compute/v1/scaler_pb2.pyi @@ -0,0 +1,57 @@ +""" +@generated by mypy-protobuf. Do not edit manually! +isort:skip_file +""" + +import builtins +import sys + +import google.protobuf.descriptor +import google.protobuf.message + +import temporalio.api.common.v1.message_pb2 + +if sys.version_info >= (3, 8): + import typing as typing_extensions +else: + import typing_extensions + +DESCRIPTOR: google.protobuf.descriptor.FileDescriptor + +class ComputeScaler(google.protobuf.message.Message): + """ComputeScaler instructs the Temporal Service when to scale up or down the number of + Workers that comprise a WorkerDeployment. + """ + + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + TYPE_FIELD_NUMBER: builtins.int + DETAILS_FIELD_NUMBER: builtins.int + type: builtins.str + """Type of the compute scaler. this string is implementation-specific and + can be used by implementations to understand how to interpret the + contents of the scaler_details field. + """ + @property + def details(self) -> temporalio.api.common.v1.message_pb2.Payload: + """Contains scaler-specific instructions and configuration. + For server-implemented scalers, use the SDK's default data + converter to ensure the server can understand it. + For remote-implemented scalers, you might use your own data + converters according to what the remote endpoints understand. + """ + def __init__( + self, + *, + type: builtins.str = ..., + details: temporalio.api.common.v1.message_pb2.Payload | None = ..., + ) -> None: ... + def HasField( + self, field_name: typing_extensions.Literal["details", b"details"] + ) -> builtins.bool: ... + def ClearField( + self, + field_name: typing_extensions.Literal["details", b"details", "type", b"type"], + ) -> None: ... + +global___ComputeScaler = ComputeScaler diff --git a/temporalio/api/deployment/v1/message_pb2.py b/temporalio/api/deployment/v1/message_pb2.py index b32b24a46..08914a31f 100644 --- a/temporalio/api/deployment/v1/message_pb2.py +++ b/temporalio/api/deployment/v1/message_pb2.py @@ -19,15 +19,21 @@ from temporalio.api.common.v1 import ( message_pb2 as temporal_dot_api_dot_common_dot_v1_dot_message__pb2, ) +from temporalio.api.compute.v1 import ( + config_pb2 as temporal_dot_api_dot_compute_dot_v1_dot_config__pb2, +) from temporalio.api.enums.v1 import ( deployment_pb2 as temporal_dot_api_dot_enums_dot_v1_dot_deployment__pb2, ) from temporalio.api.enums.v1 import ( task_queue_pb2 as temporal_dot_api_dot_enums_dot_v1_dot_task__queue__pb2, ) +from temporalio.api.enums.v1 import ( + workflow_pb2 as temporal_dot_api_dot_enums_dot_v1_dot_workflow__pb2, +) DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile( - b'\n(temporal/api/deployment/v1/message.proto\x12\x1atemporal.api.deployment.v1\x1a\x1fgoogle/protobuf/timestamp.proto\x1a&temporal/api/enums/v1/deployment.proto\x1a&temporal/api/enums/v1/task_queue.proto\x1a$temporal/api/common/v1/message.proto"\x91\x01\n\x17WorkerDeploymentOptions\x12\x17\n\x0f\x64\x65ployment_name\x18\x01 \x01(\t\x12\x10\n\x08\x62uild_id\x18\x02 \x01(\t\x12K\n\x16worker_versioning_mode\x18\x03 \x01(\x0e\x32+.temporal.api.enums.v1.WorkerVersioningMode"3\n\nDeployment\x12\x13\n\x0bseries_name\x18\x01 \x01(\t\x12\x10\n\x08\x62uild_id\x18\x02 \x01(\t"\x8e\x04\n\x0e\x44\x65ploymentInfo\x12:\n\ndeployment\x18\x01 \x01(\x0b\x32&.temporal.api.deployment.v1.Deployment\x12/\n\x0b\x63reate_time\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12R\n\x10task_queue_infos\x18\x03 \x03(\x0b\x32\x38.temporal.api.deployment.v1.DeploymentInfo.TaskQueueInfo\x12J\n\x08metadata\x18\x04 \x03(\x0b\x32\x38.temporal.api.deployment.v1.DeploymentInfo.MetadataEntry\x12\x12\n\nis_current\x18\x05 \x01(\x08\x1aP\n\rMetadataEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12.\n\x05value\x18\x02 \x01(\x0b\x32\x1f.temporal.api.common.v1.Payload:\x02\x38\x01\x1a\x88\x01\n\rTaskQueueInfo\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x32\n\x04type\x18\x02 \x01(\x0e\x32$.temporal.api.enums.v1.TaskQueueType\x12\x35\n\x11\x66irst_poller_time\x18\x03 \x01(\x0b\x32\x1a.google.protobuf.Timestamp"\xea\x01\n\x18UpdateDeploymentMetadata\x12_\n\x0eupsert_entries\x18\x01 \x03(\x0b\x32G.temporal.api.deployment.v1.UpdateDeploymentMetadata.UpsertEntriesEntry\x12\x16\n\x0eremove_entries\x18\x02 \x03(\t\x1aU\n\x12UpsertEntriesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12.\n\x05value\x18\x02 \x01(\x0b\x32\x1f.temporal.api.common.v1.Payload:\x02\x38\x01"\x95\x01\n\x12\x44\x65ploymentListInfo\x12:\n\ndeployment\x18\x01 \x01(\x0b\x32&.temporal.api.deployment.v1.Deployment\x12/\n\x0b\x63reate_time\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x12\n\nis_current\x18\x03 \x01(\x08"\xcd\x07\n\x1bWorkerDeploymentVersionInfo\x12\x13\n\x07version\x18\x01 \x01(\tB\x02\x18\x01\x12\x44\n\x06status\x18\x0e \x01(\x0e\x32\x34.temporal.api.enums.v1.WorkerDeploymentVersionStatus\x12O\n\x12\x64\x65ployment_version\x18\x0b \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersion\x12\x17\n\x0f\x64\x65ployment_name\x18\x02 \x01(\t\x12/\n\x0b\x63reate_time\x18\x03 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x38\n\x14routing_changed_time\x18\x04 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x36\n\x12\x63urrent_since_time\x18\x05 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x36\n\x12ramping_since_time\x18\x06 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x39\n\x15\x66irst_activation_time\x18\x0c \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x35\n\x11last_current_time\x18\x0f \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12:\n\x16last_deactivation_time\x18\r \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x17\n\x0framp_percentage\x18\x07 \x01(\x02\x12\x66\n\x10task_queue_infos\x18\x08 \x03(\x0b\x32L.temporal.api.deployment.v1.WorkerDeploymentVersionInfo.VersionTaskQueueInfo\x12\x46\n\rdrainage_info\x18\t \x01(\x0b\x32/.temporal.api.deployment.v1.VersionDrainageInfo\x12=\n\x08metadata\x18\n \x01(\x0b\x32+.temporal.api.deployment.v1.VersionMetadata\x1aX\n\x14VersionTaskQueueInfo\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x32\n\x04type\x18\x02 \x01(\x0e\x32$.temporal.api.enums.v1.TaskQueueType"\xc1\x01\n\x13VersionDrainageInfo\x12<\n\x06status\x18\x01 \x01(\x0e\x32,.temporal.api.enums.v1.VersionDrainageStatus\x12\x35\n\x11last_changed_time\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x35\n\x11last_checked_time\x18\x03 \x01(\x0b\x32\x1a.google.protobuf.Timestamp"\xfa\x08\n\x14WorkerDeploymentInfo\x12\x0c\n\x04name\x18\x01 \x01(\t\x12j\n\x11version_summaries\x18\x02 \x03(\x0b\x32O.temporal.api.deployment.v1.WorkerDeploymentInfo.WorkerDeploymentVersionSummary\x12/\n\x0b\x63reate_time\x18\x03 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x41\n\x0erouting_config\x18\x04 \x01(\x0b\x32).temporal.api.deployment.v1.RoutingConfig\x12\x1e\n\x16last_modifier_identity\x18\x05 \x01(\t\x12\x18\n\x10manager_identity\x18\x06 \x01(\t\x12T\n\x1brouting_config_update_state\x18\x07 \x01(\x0e\x32/.temporal.api.enums.v1.RoutingConfigUpdateState\x1a\xe3\x05\n\x1eWorkerDeploymentVersionSummary\x12\x13\n\x07version\x18\x01 \x01(\tB\x02\x18\x01\x12\x44\n\x06status\x18\x0b \x01(\x0e\x32\x34.temporal.api.enums.v1.WorkerDeploymentVersionStatus\x12O\n\x12\x64\x65ployment_version\x18\x04 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersion\x12/\n\x0b\x63reate_time\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x45\n\x0f\x64rainage_status\x18\x03 \x01(\x0e\x32,.temporal.api.enums.v1.VersionDrainageStatus\x12\x46\n\rdrainage_info\x18\x05 \x01(\x0b\x32/.temporal.api.deployment.v1.VersionDrainageInfo\x12\x36\n\x12\x63urrent_since_time\x18\x06 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x36\n\x12ramping_since_time\x18\x07 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x37\n\x13routing_update_time\x18\x08 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x39\n\x15\x66irst_activation_time\x18\t \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x35\n\x11last_current_time\x18\x0c \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12:\n\x16last_deactivation_time\x18\n \x01(\x0b\x32\x1a.google.protobuf.Timestamp"D\n\x17WorkerDeploymentVersion\x12\x10\n\x08\x62uild_id\x18\x01 \x01(\t\x12\x17\n\x0f\x64\x65ployment_name\x18\x02 \x01(\t"\xad\x01\n\x0fVersionMetadata\x12I\n\x07\x65ntries\x18\x01 \x03(\x0b\x32\x38.temporal.api.deployment.v1.VersionMetadata.EntriesEntry\x1aO\n\x0c\x45ntriesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12.\n\x05value\x18\x02 \x01(\x0b\x32\x1f.temporal.api.common.v1.Payload:\x02\x38\x01"\x89\x04\n\rRoutingConfig\x12W\n\x1a\x63urrent_deployment_version\x18\x07 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersion\x12\x1b\n\x0f\x63urrent_version\x18\x01 \x01(\tB\x02\x18\x01\x12W\n\x1aramping_deployment_version\x18\t \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersion\x12\x1b\n\x0framping_version\x18\x02 \x01(\tB\x02\x18\x01\x12"\n\x1aramping_version_percentage\x18\x03 \x01(\x02\x12@\n\x1c\x63urrent_version_changed_time\x18\x04 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12@\n\x1cramping_version_changed_time\x18\x05 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12K\n\'ramping_version_percentage_changed_time\x18\x06 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x17\n\x0frevision_number\x18\n \x01(\x03"\x9d\x01\n\x18InheritedAutoUpgradeInfo\x12V\n\x19source_deployment_version\x18\x01 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersion\x12)\n!source_deployment_revision_number\x18\x02 \x01(\x03\x42\x9d\x01\n\x1dio.temporal.api.deployment.v1B\x0cMessageProtoP\x01Z+go.temporal.io/api/deployment/v1;deployment\xaa\x02\x1cTemporalio.Api.Deployment.V1\xea\x02\x1fTemporalio::Api::Deployment::V1b\x06proto3' + b'\n(temporal/api/deployment/v1/message.proto\x12\x1atemporal.api.deployment.v1\x1a\x1fgoogle/protobuf/timestamp.proto\x1a$temporal/api/enums/v1/workflow.proto\x1a&temporal/api/enums/v1/deployment.proto\x1a&temporal/api/enums/v1/task_queue.proto\x1a$temporal/api/common/v1/message.proto\x1a$temporal/api/compute/v1/config.proto"\x91\x01\n\x17WorkerDeploymentOptions\x12\x17\n\x0f\x64\x65ployment_name\x18\x01 \x01(\t\x12\x10\n\x08\x62uild_id\x18\x02 \x01(\t\x12K\n\x16worker_versioning_mode\x18\x03 \x01(\x0e\x32+.temporal.api.enums.v1.WorkerVersioningMode"3\n\nDeployment\x12\x13\n\x0bseries_name\x18\x01 \x01(\t\x12\x10\n\x08\x62uild_id\x18\x02 \x01(\t"\x8e\x04\n\x0e\x44\x65ploymentInfo\x12:\n\ndeployment\x18\x01 \x01(\x0b\x32&.temporal.api.deployment.v1.Deployment\x12/\n\x0b\x63reate_time\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12R\n\x10task_queue_infos\x18\x03 \x03(\x0b\x32\x38.temporal.api.deployment.v1.DeploymentInfo.TaskQueueInfo\x12J\n\x08metadata\x18\x04 \x03(\x0b\x32\x38.temporal.api.deployment.v1.DeploymentInfo.MetadataEntry\x12\x12\n\nis_current\x18\x05 \x01(\x08\x1aP\n\rMetadataEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12.\n\x05value\x18\x02 \x01(\x0b\x32\x1f.temporal.api.common.v1.Payload:\x02\x38\x01\x1a\x88\x01\n\rTaskQueueInfo\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x32\n\x04type\x18\x02 \x01(\x0e\x32$.temporal.api.enums.v1.TaskQueueType\x12\x35\n\x11\x66irst_poller_time\x18\x03 \x01(\x0b\x32\x1a.google.protobuf.Timestamp"\xea\x01\n\x18UpdateDeploymentMetadata\x12_\n\x0eupsert_entries\x18\x01 \x03(\x0b\x32G.temporal.api.deployment.v1.UpdateDeploymentMetadata.UpsertEntriesEntry\x12\x16\n\x0eremove_entries\x18\x02 \x03(\t\x1aU\n\x12UpsertEntriesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12.\n\x05value\x18\x02 \x01(\x0b\x32\x1f.temporal.api.common.v1.Payload:\x02\x38\x01"\x95\x01\n\x12\x44\x65ploymentListInfo\x12:\n\ndeployment\x18\x01 \x01(\x0b\x32&.temporal.api.deployment.v1.Deployment\x12/\n\x0b\x63reate_time\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x12\n\nis_current\x18\x03 \x01(\x08"\xad\x08\n\x1bWorkerDeploymentVersionInfo\x12\x13\n\x07version\x18\x01 \x01(\tB\x02\x18\x01\x12\x44\n\x06status\x18\x0e \x01(\x0e\x32\x34.temporal.api.enums.v1.WorkerDeploymentVersionStatus\x12O\n\x12\x64\x65ployment_version\x18\x0b \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersion\x12\x17\n\x0f\x64\x65ployment_name\x18\x02 \x01(\t\x12/\n\x0b\x63reate_time\x18\x03 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x38\n\x14routing_changed_time\x18\x04 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x36\n\x12\x63urrent_since_time\x18\x05 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x36\n\x12ramping_since_time\x18\x06 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x39\n\x15\x66irst_activation_time\x18\x0c \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x35\n\x11last_current_time\x18\x0f \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12:\n\x16last_deactivation_time\x18\r \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x17\n\x0framp_percentage\x18\x07 \x01(\x02\x12\x66\n\x10task_queue_infos\x18\x08 \x03(\x0b\x32L.temporal.api.deployment.v1.WorkerDeploymentVersionInfo.VersionTaskQueueInfo\x12\x46\n\rdrainage_info\x18\t \x01(\x0b\x32/.temporal.api.deployment.v1.VersionDrainageInfo\x12=\n\x08metadata\x18\n \x01(\x0b\x32+.temporal.api.deployment.v1.VersionMetadata\x12>\n\x0e\x63ompute_config\x18\x10 \x01(\x0b\x32&.temporal.api.compute.v1.ComputeConfig\x12\x1e\n\x16last_modifier_identity\x18\x11 \x01(\t\x1aX\n\x14VersionTaskQueueInfo\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x32\n\x04type\x18\x02 \x01(\x0e\x32$.temporal.api.enums.v1.TaskQueueType"\xc1\x01\n\x13VersionDrainageInfo\x12<\n\x06status\x18\x01 \x01(\x0e\x32,.temporal.api.enums.v1.VersionDrainageStatus\x12\x35\n\x11last_changed_time\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x35\n\x11last_checked_time\x18\x03 \x01(\x0b\x32\x1a.google.protobuf.Timestamp"\xc1\t\n\x14WorkerDeploymentInfo\x12\x0c\n\x04name\x18\x01 \x01(\t\x12j\n\x11version_summaries\x18\x02 \x03(\x0b\x32O.temporal.api.deployment.v1.WorkerDeploymentInfo.WorkerDeploymentVersionSummary\x12/\n\x0b\x63reate_time\x18\x03 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x41\n\x0erouting_config\x18\x04 \x01(\x0b\x32).temporal.api.deployment.v1.RoutingConfig\x12\x1e\n\x16last_modifier_identity\x18\x05 \x01(\t\x12\x18\n\x10manager_identity\x18\x06 \x01(\t\x12T\n\x1brouting_config_update_state\x18\x07 \x01(\x0e\x32/.temporal.api.enums.v1.RoutingConfigUpdateState\x1a\xaa\x06\n\x1eWorkerDeploymentVersionSummary\x12\x13\n\x07version\x18\x01 \x01(\tB\x02\x18\x01\x12\x44\n\x06status\x18\x0b \x01(\x0e\x32\x34.temporal.api.enums.v1.WorkerDeploymentVersionStatus\x12O\n\x12\x64\x65ployment_version\x18\x04 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersion\x12/\n\x0b\x63reate_time\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x45\n\x0f\x64rainage_status\x18\x03 \x01(\x0e\x32,.temporal.api.enums.v1.VersionDrainageStatus\x12\x46\n\rdrainage_info\x18\x05 \x01(\x0b\x32/.temporal.api.deployment.v1.VersionDrainageInfo\x12\x36\n\x12\x63urrent_since_time\x18\x06 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x36\n\x12ramping_since_time\x18\x07 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x37\n\x13routing_update_time\x18\x08 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x39\n\x15\x66irst_activation_time\x18\t \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x35\n\x11last_current_time\x18\x0c \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12:\n\x16last_deactivation_time\x18\n \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x45\n\x0e\x63ompute_config\x18\r \x01(\x0b\x32-.temporal.api.compute.v1.ComputeConfigSummary"D\n\x17WorkerDeploymentVersion\x12\x10\n\x08\x62uild_id\x18\x01 \x01(\t\x12\x17\n\x0f\x64\x65ployment_name\x18\x02 \x01(\t"\xad\x01\n\x0fVersionMetadata\x12I\n\x07\x65ntries\x18\x01 \x03(\x0b\x32\x38.temporal.api.deployment.v1.VersionMetadata.EntriesEntry\x1aO\n\x0c\x45ntriesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12.\n\x05value\x18\x02 \x01(\x0b\x32\x1f.temporal.api.common.v1.Payload:\x02\x38\x01"\x89\x04\n\rRoutingConfig\x12W\n\x1a\x63urrent_deployment_version\x18\x07 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersion\x12\x1b\n\x0f\x63urrent_version\x18\x01 \x01(\tB\x02\x18\x01\x12W\n\x1aramping_deployment_version\x18\t \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersion\x12\x1b\n\x0framping_version\x18\x02 \x01(\tB\x02\x18\x01\x12"\n\x1aramping_version_percentage\x18\x03 \x01(\x02\x12@\n\x1c\x63urrent_version_changed_time\x18\x04 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12@\n\x1cramping_version_changed_time\x18\x05 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12K\n\'ramping_version_percentage_changed_time\x18\x06 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x17\n\x0frevision_number\x18\n \x01(\x03"\x8a\x02\n\x18InheritedAutoUpgradeInfo\x12V\n\x19source_deployment_version\x18\x01 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersion\x12)\n!source_deployment_revision_number\x18\x02 \x01(\x03\x12k\n+continue_as_new_initial_versioning_behavior\x18\x03 \x01(\x0e\x32\x36.temporal.api.enums.v1.ContinueAsNewVersioningBehaviorB\x9d\x01\n\x1dio.temporal.api.deployment.v1B\x0cMessageProtoP\x01Z+go.temporal.io/api/deployment/v1;deployment\xaa\x02\x1cTemporalio.Api.Deployment.V1\xea\x02\x1fTemporalio::Api::Deployment::V1b\x06proto3' ) @@ -272,40 +278,40 @@ _ROUTINGCONFIG.fields_by_name["current_version"]._serialized_options = b"\030\001" _ROUTINGCONFIG.fields_by_name["ramping_version"]._options = None _ROUTINGCONFIG.fields_by_name["ramping_version"]._serialized_options = b"\030\001" - _WORKERDEPLOYMENTOPTIONS._serialized_start = 224 - _WORKERDEPLOYMENTOPTIONS._serialized_end = 369 - _DEPLOYMENT._serialized_start = 371 - _DEPLOYMENT._serialized_end = 422 - _DEPLOYMENTINFO._serialized_start = 425 - _DEPLOYMENTINFO._serialized_end = 951 - _DEPLOYMENTINFO_METADATAENTRY._serialized_start = 732 - _DEPLOYMENTINFO_METADATAENTRY._serialized_end = 812 - _DEPLOYMENTINFO_TASKQUEUEINFO._serialized_start = 815 - _DEPLOYMENTINFO_TASKQUEUEINFO._serialized_end = 951 - _UPDATEDEPLOYMENTMETADATA._serialized_start = 954 - _UPDATEDEPLOYMENTMETADATA._serialized_end = 1188 - _UPDATEDEPLOYMENTMETADATA_UPSERTENTRIESENTRY._serialized_start = 1103 - _UPDATEDEPLOYMENTMETADATA_UPSERTENTRIESENTRY._serialized_end = 1188 - _DEPLOYMENTLISTINFO._serialized_start = 1191 - _DEPLOYMENTLISTINFO._serialized_end = 1340 - _WORKERDEPLOYMENTVERSIONINFO._serialized_start = 1343 - _WORKERDEPLOYMENTVERSIONINFO._serialized_end = 2316 - _WORKERDEPLOYMENTVERSIONINFO_VERSIONTASKQUEUEINFO._serialized_start = 2228 - _WORKERDEPLOYMENTVERSIONINFO_VERSIONTASKQUEUEINFO._serialized_end = 2316 - _VERSIONDRAINAGEINFO._serialized_start = 2319 - _VERSIONDRAINAGEINFO._serialized_end = 2512 - _WORKERDEPLOYMENTINFO._serialized_start = 2515 - _WORKERDEPLOYMENTINFO._serialized_end = 3661 - _WORKERDEPLOYMENTINFO_WORKERDEPLOYMENTVERSIONSUMMARY._serialized_start = 2922 - _WORKERDEPLOYMENTINFO_WORKERDEPLOYMENTVERSIONSUMMARY._serialized_end = 3661 - _WORKERDEPLOYMENTVERSION._serialized_start = 3663 - _WORKERDEPLOYMENTVERSION._serialized_end = 3731 - _VERSIONMETADATA._serialized_start = 3734 - _VERSIONMETADATA._serialized_end = 3907 - _VERSIONMETADATA_ENTRIESENTRY._serialized_start = 3828 - _VERSIONMETADATA_ENTRIESENTRY._serialized_end = 3907 - _ROUTINGCONFIG._serialized_start = 3910 - _ROUTINGCONFIG._serialized_end = 4431 - _INHERITEDAUTOUPGRADEINFO._serialized_start = 4434 - _INHERITEDAUTOUPGRADEINFO._serialized_end = 4591 + _WORKERDEPLOYMENTOPTIONS._serialized_start = 300 + _WORKERDEPLOYMENTOPTIONS._serialized_end = 445 + _DEPLOYMENT._serialized_start = 447 + _DEPLOYMENT._serialized_end = 498 + _DEPLOYMENTINFO._serialized_start = 501 + _DEPLOYMENTINFO._serialized_end = 1027 + _DEPLOYMENTINFO_METADATAENTRY._serialized_start = 808 + _DEPLOYMENTINFO_METADATAENTRY._serialized_end = 888 + _DEPLOYMENTINFO_TASKQUEUEINFO._serialized_start = 891 + _DEPLOYMENTINFO_TASKQUEUEINFO._serialized_end = 1027 + _UPDATEDEPLOYMENTMETADATA._serialized_start = 1030 + _UPDATEDEPLOYMENTMETADATA._serialized_end = 1264 + _UPDATEDEPLOYMENTMETADATA_UPSERTENTRIESENTRY._serialized_start = 1179 + _UPDATEDEPLOYMENTMETADATA_UPSERTENTRIESENTRY._serialized_end = 1264 + _DEPLOYMENTLISTINFO._serialized_start = 1267 + _DEPLOYMENTLISTINFO._serialized_end = 1416 + _WORKERDEPLOYMENTVERSIONINFO._serialized_start = 1419 + _WORKERDEPLOYMENTVERSIONINFO._serialized_end = 2488 + _WORKERDEPLOYMENTVERSIONINFO_VERSIONTASKQUEUEINFO._serialized_start = 2400 + _WORKERDEPLOYMENTVERSIONINFO_VERSIONTASKQUEUEINFO._serialized_end = 2488 + _VERSIONDRAINAGEINFO._serialized_start = 2491 + _VERSIONDRAINAGEINFO._serialized_end = 2684 + _WORKERDEPLOYMENTINFO._serialized_start = 2687 + _WORKERDEPLOYMENTINFO._serialized_end = 3904 + _WORKERDEPLOYMENTINFO_WORKERDEPLOYMENTVERSIONSUMMARY._serialized_start = 3094 + _WORKERDEPLOYMENTINFO_WORKERDEPLOYMENTVERSIONSUMMARY._serialized_end = 3904 + _WORKERDEPLOYMENTVERSION._serialized_start = 3906 + _WORKERDEPLOYMENTVERSION._serialized_end = 3974 + _VERSIONMETADATA._serialized_start = 3977 + _VERSIONMETADATA._serialized_end = 4150 + _VERSIONMETADATA_ENTRIESENTRY._serialized_start = 4071 + _VERSIONMETADATA_ENTRIESENTRY._serialized_end = 4150 + _ROUTINGCONFIG._serialized_start = 4153 + _ROUTINGCONFIG._serialized_end = 4674 + _INHERITEDAUTOUPGRADEINFO._serialized_start = 4677 + _INHERITEDAUTOUPGRADEINFO._serialized_end = 4943 # @@protoc_insertion_point(module_scope) diff --git a/temporalio/api/deployment/v1/message_pb2.pyi b/temporalio/api/deployment/v1/message_pb2.pyi index fe01ca1fe..1b97a8db1 100644 --- a/temporalio/api/deployment/v1/message_pb2.pyi +++ b/temporalio/api/deployment/v1/message_pb2.pyi @@ -13,8 +13,10 @@ import google.protobuf.message import google.protobuf.timestamp_pb2 import temporalio.api.common.v1.message_pb2 +import temporalio.api.compute.v1.config_pb2 import temporalio.api.enums.v1.deployment_pb2 import temporalio.api.enums.v1.task_queue_pb2 +import temporalio.api.enums.v1.workflow_pb2 if sys.version_info >= (3, 8): import typing as typing_extensions @@ -24,9 +26,7 @@ else: DESCRIPTOR: google.protobuf.descriptor.FileDescriptor class WorkerDeploymentOptions(google.protobuf.message.Message): - """Worker Deployment options set in SDK that need to be sent to server in every poll. - Experimental. Worker Deployments are experimental and might significantly change in the future. - """ + """Worker Deployment options set in SDK that need to be sent to server in every poll.""" DESCRIPTOR: google.protobuf.descriptor.Descriptor @@ -347,7 +347,6 @@ class WorkerDeploymentVersionInfo(google.protobuf.message.Message): non-determinism issues. Worker Deployment Versions are created in Temporal server automatically when their first poller arrives to the server. - Experimental. Worker Deployments are experimental and might significantly change in the future. """ DESCRIPTOR: google.protobuf.descriptor.Descriptor @@ -385,6 +384,8 @@ class WorkerDeploymentVersionInfo(google.protobuf.message.Message): TASK_QUEUE_INFOS_FIELD_NUMBER: builtins.int DRAINAGE_INFO_FIELD_NUMBER: builtins.int METADATA_FIELD_NUMBER: builtins.int + COMPUTE_CONFIG_FIELD_NUMBER: builtins.int + LAST_MODIFIER_IDENTITY_FIELD_NUMBER: builtins.int version: builtins.str """Deprecated. Use `deployment_version`.""" status: ( @@ -395,6 +396,7 @@ class WorkerDeploymentVersionInfo(google.protobuf.message.Message): def deployment_version(self) -> global___WorkerDeploymentVersion: """Required.""" deployment_name: builtins.str + """Deprecated. User deployment_version.deployment_name.""" @property def create_time(self) -> google.protobuf.timestamp_pb2.Timestamp: ... @property @@ -457,6 +459,18 @@ class WorkerDeploymentVersionInfo(google.protobuf.message.Message): @property def metadata(self) -> global___VersionMetadata: """Arbitrary user-provided metadata attached to this version.""" + @property + def compute_config(self) -> temporalio.api.compute.v1.config_pb2.ComputeConfig: + """Optional. Contains the new worker compute configuration for the Worker + Deployment. Used for worker scale management. + """ + last_modifier_identity: builtins.str + """Identity of the last client who modified the configuration of this Version. + As of now, this field only covers changes through the following APIs: + - `CreateWorkerDeploymentVersion` + - `UpdateWorkerDeploymentVersionComputeConfig` + - `UpdateWorkerDeploymentVersionMetadata` + """ def __init__( self, *, @@ -478,10 +492,14 @@ class WorkerDeploymentVersionInfo(google.protobuf.message.Message): | None = ..., drainage_info: global___VersionDrainageInfo | None = ..., metadata: global___VersionMetadata | None = ..., + compute_config: temporalio.api.compute.v1.config_pb2.ComputeConfig | None = ..., + last_modifier_identity: builtins.str = ..., ) -> None: ... def HasField( self, field_name: typing_extensions.Literal[ + "compute_config", + b"compute_config", "create_time", b"create_time", "current_since_time", @@ -507,6 +525,8 @@ class WorkerDeploymentVersionInfo(google.protobuf.message.Message): def ClearField( self, field_name: typing_extensions.Literal[ + "compute_config", + b"compute_config", "create_time", b"create_time", "current_since_time", @@ -523,6 +543,8 @@ class WorkerDeploymentVersionInfo(google.protobuf.message.Message): b"last_current_time", "last_deactivation_time", b"last_deactivation_time", + "last_modifier_identity", + b"last_modifier_identity", "metadata", b"metadata", "ramp_percentage", @@ -545,7 +567,6 @@ global___WorkerDeploymentVersionInfo = WorkerDeploymentVersionInfo class VersionDrainageInfo(google.protobuf.message.Message): """Information about workflow drainage to help the user determine when it is safe to decommission a Version. Not present while version is current or ramping. - Experimental. Worker Deployments are experimental and might significantly change in the future. """ DESCRIPTOR: google.protobuf.descriptor.Descriptor @@ -601,7 +622,6 @@ class WorkerDeploymentInfo(google.protobuf.message.Message): version of workers. (see documentation of WorkerDeploymentVersionInfo) Deployment records are created in Temporal server automatically when their first poller arrives to the server. - Experimental. Worker Deployments are experimental and might significantly change in the future. """ DESCRIPTOR: google.protobuf.descriptor.Descriptor @@ -621,6 +641,7 @@ class WorkerDeploymentInfo(google.protobuf.message.Message): FIRST_ACTIVATION_TIME_FIELD_NUMBER: builtins.int LAST_CURRENT_TIME_FIELD_NUMBER: builtins.int LAST_DEACTIVATION_TIME_FIELD_NUMBER: builtins.int + COMPUTE_CONFIG_FIELD_NUMBER: builtins.int version: builtins.str """Deprecated. Use `deployment_version`.""" status: temporalio.api.enums.v1.deployment_pb2.WorkerDeploymentVersionStatus.ValueType @@ -667,6 +688,10 @@ class WorkerDeploymentInfo(google.protobuf.message.Message): """Timestamp when this version last stopped being current or ramping. Cleared if the version becomes current or ramping again. """ + @property + def compute_config( + self, + ) -> temporalio.api.compute.v1.config_pb2.ComputeConfigSummary: ... def __init__( self, *, @@ -683,10 +708,14 @@ class WorkerDeploymentInfo(google.protobuf.message.Message): last_current_time: google.protobuf.timestamp_pb2.Timestamp | None = ..., last_deactivation_time: google.protobuf.timestamp_pb2.Timestamp | None = ..., + compute_config: temporalio.api.compute.v1.config_pb2.ComputeConfigSummary + | None = ..., ) -> None: ... def HasField( self, field_name: typing_extensions.Literal[ + "compute_config", + b"compute_config", "create_time", b"create_time", "current_since_time", @@ -710,6 +739,8 @@ class WorkerDeploymentInfo(google.protobuf.message.Message): def ClearField( self, field_name: typing_extensions.Literal[ + "compute_config", + b"compute_config", "create_time", b"create_time", "current_since_time", @@ -955,7 +986,7 @@ class RoutingConfig(google.protobuf.message.Message): If ramping version is changed, this is also updated, even if the percentage stays the same. """ revision_number: builtins.int - """Monotonically increasing value which is incremented on every mutation + """Monotonically increasing value which is incremented on every mutation to any field of this message to achieve eventual consistency between task queues and their partitions. """ def __init__( @@ -1018,22 +1049,39 @@ global___RoutingConfig = RoutingConfig class InheritedAutoUpgradeInfo(google.protobuf.message.Message): """Used as part of WorkflowExecutionStartedEventAttributes to pass down the AutoUpgrade behavior and source deployment version to a workflow execution whose parent/previous workflow has an AutoUpgrade behavior. + Also used for Upgrade-on-CaN behaviors AutoUpgrade and UseRampingVersion. """ DESCRIPTOR: google.protobuf.descriptor.Descriptor SOURCE_DEPLOYMENT_VERSION_FIELD_NUMBER: builtins.int SOURCE_DEPLOYMENT_REVISION_NUMBER_FIELD_NUMBER: builtins.int + CONTINUE_AS_NEW_INITIAL_VERSIONING_BEHAVIOR_FIELD_NUMBER: builtins.int @property def source_deployment_version(self) -> global___WorkerDeploymentVersion: """The source deployment version of the parent/previous workflow.""" source_deployment_revision_number: builtins.int """The revision number of the source deployment version of the parent/previous workflow.""" + continue_as_new_initial_versioning_behavior: ( + temporalio.api.enums.v1.workflow_pb2.ContinueAsNewVersioningBehavior.ValueType + ) + """Experimental. + If this workflow is the result of a continue-as-new, this field is set to the initial_versioning_behavior + specified in that command. + Only used for the initial task of this run and the initial task of any retries of this run. + Not passed to children or to future continue-as-new. + + Note: In the first release of Upgrade-on-CaN, when the only ContinueAsNewVersioningBehavior was AutoUpgrade, + a non-empty InheritedAutoUpgradeInfo meant that the workflow should start as AutoUpgrade. So for compatibility + with history events generated during that time, know that an UNSPECIFIED value here is equivalent to AutoUpgrade + value if the InheritedAutoUpgradeInfo is non-empty. + """ def __init__( self, *, source_deployment_version: global___WorkerDeploymentVersion | None = ..., source_deployment_revision_number: builtins.int = ..., + continue_as_new_initial_versioning_behavior: temporalio.api.enums.v1.workflow_pb2.ContinueAsNewVersioningBehavior.ValueType = ..., ) -> None: ... def HasField( self, @@ -1044,6 +1092,8 @@ class InheritedAutoUpgradeInfo(google.protobuf.message.Message): def ClearField( self, field_name: typing_extensions.Literal[ + "continue_as_new_initial_versioning_behavior", + b"continue_as_new_initial_versioning_behavior", "source_deployment_revision_number", b"source_deployment_revision_number", "source_deployment_version", diff --git a/temporalio/api/enums/v1/__init__.py b/temporalio/api/enums/v1/__init__.py index 18f3be0ff..82fef9b2c 100644 --- a/temporalio/api/enums/v1/__init__.py +++ b/temporalio/api/enums/v1/__init__.py @@ -32,7 +32,13 @@ WorkflowTaskFailedCause, ) from .namespace_pb2 import ArchivalState, NamespaceState, ReplicationState -from .nexus_pb2 import NexusHandlerErrorRetryBehavior +from .nexus_pb2 import ( + NexusHandlerErrorRetryBehavior, + NexusOperationExecutionStatus, + NexusOperationIdConflictPolicy, + NexusOperationIdReusePolicy, + NexusOperationWaitStage, +) from .query_pb2 import QueryRejectCondition, QueryResultType from .reset_pb2 import ResetReapplyExcludeType, ResetReapplyType, ResetType from .schedule_pb2 import ScheduleOverlapPolicy @@ -85,6 +91,10 @@ "NamespaceState", "NexusHandlerErrorRetryBehavior", "NexusOperationCancellationState", + "NexusOperationExecutionStatus", + "NexusOperationIdConflictPolicy", + "NexusOperationIdReusePolicy", + "NexusOperationWaitStage", "ParentClosePolicy", "PendingActivityState", "PendingNexusOperationState", diff --git a/temporalio/api/enums/v1/deployment_pb2.py b/temporalio/api/enums/v1/deployment_pb2.py index a4c5e00aa..aa05071ed 100644 --- a/temporalio/api/enums/v1/deployment_pb2.py +++ b/temporalio/api/enums/v1/deployment_pb2.py @@ -16,7 +16,7 @@ DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile( - b"\n&temporal/api/enums/v1/deployment.proto\x12\x15temporal.api.enums.v1*\xc4\x01\n\x16\x44\x65ploymentReachability\x12'\n#DEPLOYMENT_REACHABILITY_UNSPECIFIED\x10\x00\x12%\n!DEPLOYMENT_REACHABILITY_REACHABLE\x10\x01\x12\x31\n-DEPLOYMENT_REACHABILITY_CLOSED_WORKFLOWS_ONLY\x10\x02\x12'\n#DEPLOYMENT_REACHABILITY_UNREACHABLE\x10\x03*\x8b\x01\n\x15VersionDrainageStatus\x12'\n#VERSION_DRAINAGE_STATUS_UNSPECIFIED\x10\x00\x12$\n VERSION_DRAINAGE_STATUS_DRAINING\x10\x01\x12#\n\x1fVERSION_DRAINAGE_STATUS_DRAINED\x10\x02*\x8c\x01\n\x14WorkerVersioningMode\x12&\n\"WORKER_VERSIONING_MODE_UNSPECIFIED\x10\x00\x12&\n\"WORKER_VERSIONING_MODE_UNVERSIONED\x10\x01\x12$\n WORKER_VERSIONING_MODE_VERSIONED\x10\x02*\xb9\x02\n\x1dWorkerDeploymentVersionStatus\x12\x30\n,WORKER_DEPLOYMENT_VERSION_STATUS_UNSPECIFIED\x10\x00\x12-\n)WORKER_DEPLOYMENT_VERSION_STATUS_INACTIVE\x10\x01\x12,\n(WORKER_DEPLOYMENT_VERSION_STATUS_CURRENT\x10\x02\x12,\n(WORKER_DEPLOYMENT_VERSION_STATUS_RAMPING\x10\x03\x12-\n)WORKER_DEPLOYMENT_VERSION_STATUS_DRAINING\x10\x04\x12,\n(WORKER_DEPLOYMENT_VERSION_STATUS_DRAINED\x10\x05\x42\x87\x01\n\x18io.temporal.api.enums.v1B\x0f\x44\x65ploymentProtoP\x01Z!go.temporal.io/api/enums/v1;enums\xaa\x02\x17Temporalio.Api.Enums.V1\xea\x02\x1aTemporalio::Api::Enums::V1b\x06proto3" + b"\n&temporal/api/enums/v1/deployment.proto\x12\x15temporal.api.enums.v1*\xc4\x01\n\x16\x44\x65ploymentReachability\x12'\n#DEPLOYMENT_REACHABILITY_UNSPECIFIED\x10\x00\x12%\n!DEPLOYMENT_REACHABILITY_REACHABLE\x10\x01\x12\x31\n-DEPLOYMENT_REACHABILITY_CLOSED_WORKFLOWS_ONLY\x10\x02\x12'\n#DEPLOYMENT_REACHABILITY_UNREACHABLE\x10\x03*\x8b\x01\n\x15VersionDrainageStatus\x12'\n#VERSION_DRAINAGE_STATUS_UNSPECIFIED\x10\x00\x12$\n VERSION_DRAINAGE_STATUS_DRAINING\x10\x01\x12#\n\x1fVERSION_DRAINAGE_STATUS_DRAINED\x10\x02*\x8c\x01\n\x14WorkerVersioningMode\x12&\n\"WORKER_VERSIONING_MODE_UNSPECIFIED\x10\x00\x12&\n\"WORKER_VERSIONING_MODE_UNVERSIONED\x10\x01\x12$\n WORKER_VERSIONING_MODE_VERSIONED\x10\x02*\xe7\x02\n\x1dWorkerDeploymentVersionStatus\x12\x30\n,WORKER_DEPLOYMENT_VERSION_STATUS_UNSPECIFIED\x10\x00\x12-\n)WORKER_DEPLOYMENT_VERSION_STATUS_INACTIVE\x10\x01\x12,\n(WORKER_DEPLOYMENT_VERSION_STATUS_CURRENT\x10\x02\x12,\n(WORKER_DEPLOYMENT_VERSION_STATUS_RAMPING\x10\x03\x12-\n)WORKER_DEPLOYMENT_VERSION_STATUS_DRAINING\x10\x04\x12,\n(WORKER_DEPLOYMENT_VERSION_STATUS_DRAINED\x10\x05\x12,\n(WORKER_DEPLOYMENT_VERSION_STATUS_CREATED\x10\x06\x42\x87\x01\n\x18io.temporal.api.enums.v1B\x0f\x44\x65ploymentProtoP\x01Z!go.temporal.io/api/enums/v1;enums\xaa\x02\x17Temporalio.Api.Enums.V1\xea\x02\x1aTemporalio::Api::Enums::V1b\x06proto3" ) _DEPLOYMENTREACHABILITY = DESCRIPTOR.enum_types_by_name["DeploymentReachability"] @@ -47,6 +47,7 @@ WORKER_DEPLOYMENT_VERSION_STATUS_RAMPING = 3 WORKER_DEPLOYMENT_VERSION_STATUS_DRAINING = 4 WORKER_DEPLOYMENT_VERSION_STATUS_DRAINED = 5 +WORKER_DEPLOYMENT_VERSION_STATUS_CREATED = 6 if _descriptor._USE_C_DESCRIPTORS == False: @@ -59,5 +60,5 @@ _WORKERVERSIONINGMODE._serialized_start = 407 _WORKERVERSIONINGMODE._serialized_end = 547 _WORKERDEPLOYMENTVERSIONSTATUS._serialized_start = 550 - _WORKERDEPLOYMENTVERSIONSTATUS._serialized_end = 863 + _WORKERDEPLOYMENTVERSIONSTATUS._serialized_end = 909 # @@protoc_insertion_point(module_scope) diff --git a/temporalio/api/enums/v1/deployment_pb2.pyi b/temporalio/api/enums/v1/deployment_pb2.pyi index 92074757c..de3378e69 100644 --- a/temporalio/api/enums/v1/deployment_pb2.pyi +++ b/temporalio/api/enums/v1/deployment_pb2.pyi @@ -101,7 +101,6 @@ class VersionDrainageStatus( aip.dev/not-precedent: Call this status because it is . --) Specify the drainage status for a Worker Deployment Version so users can decide whether they can safely decommission the version. - Experimental. Worker Deployments are experimental and might significantly change in the future. """ VERSION_DRAINAGE_STATUS_UNSPECIFIED: VersionDrainageStatus.ValueType # 0 @@ -160,7 +159,6 @@ class WorkerVersioningMode( - Whether or not Temporal Server considers this worker's version (Build ID) when dispatching tasks to it. - Whether or not the workflows processed by this worker are versioned using the worker's version. - Experimental. Worker Deployments are experimental and might significantly change in the future. """ WORKER_VERSIONING_MODE_UNSPECIFIED: WorkerVersioningMode.ValueType # 0 @@ -234,6 +232,12 @@ class _WorkerDeploymentVersionStatusEnumTypeWrapper( not query closed workflows. If the user does query closed workflows for some time x after workflows are closed, they should decommission the version after it has been drained for that duration. """ + WORKER_DEPLOYMENT_VERSION_STATUS_CREATED: ( + _WorkerDeploymentVersionStatus.ValueType + ) # 6 + """The Worker Deployment Version is created by user (via `CreateWorkerDeploymentVersion` API) + but server has not seen any poller for it yet. + """ class WorkerDeploymentVersionStatus( _WorkerDeploymentVersionStatus, @@ -242,7 +246,6 @@ class WorkerDeploymentVersionStatus( """(-- api-linter: core::0216::synonyms=disabled aip.dev/not-precedent: Call this status because it is . --) Specify the status of a Worker Deployment Version. - Experimental. Worker Deployments are experimental and might significantly change in the future. """ WORKER_DEPLOYMENT_VERSION_STATUS_UNSPECIFIED: ( @@ -271,4 +274,8 @@ Queries sent to closed workflows. The version can be decommissioned safely if us not query closed workflows. If the user does query closed workflows for some time x after workflows are closed, they should decommission the version after it has been drained for that duration. """ +WORKER_DEPLOYMENT_VERSION_STATUS_CREATED: WorkerDeploymentVersionStatus.ValueType # 6 +"""The Worker Deployment Version is created by user (via `CreateWorkerDeploymentVersion` API) +but server has not seen any poller for it yet. +""" global___WorkerDeploymentVersionStatus = WorkerDeploymentVersionStatus diff --git a/temporalio/api/enums/v1/event_type_pb2.py b/temporalio/api/enums/v1/event_type_pb2.py index 6c1a49f4b..14ff7984d 100644 --- a/temporalio/api/enums/v1/event_type_pb2.py +++ b/temporalio/api/enums/v1/event_type_pb2.py @@ -16,7 +16,7 @@ DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile( - b'\n&temporal/api/enums/v1/event_type.proto\x12\x15temporal.api.enums.v1*\xe0\x15\n\tEventType\x12\x1a\n\x16\x45VENT_TYPE_UNSPECIFIED\x10\x00\x12)\n%EVENT_TYPE_WORKFLOW_EXECUTION_STARTED\x10\x01\x12+\n\'EVENT_TYPE_WORKFLOW_EXECUTION_COMPLETED\x10\x02\x12(\n$EVENT_TYPE_WORKFLOW_EXECUTION_FAILED\x10\x03\x12+\n\'EVENT_TYPE_WORKFLOW_EXECUTION_TIMED_OUT\x10\x04\x12&\n"EVENT_TYPE_WORKFLOW_TASK_SCHEDULED\x10\x05\x12$\n EVENT_TYPE_WORKFLOW_TASK_STARTED\x10\x06\x12&\n"EVENT_TYPE_WORKFLOW_TASK_COMPLETED\x10\x07\x12&\n"EVENT_TYPE_WORKFLOW_TASK_TIMED_OUT\x10\x08\x12#\n\x1f\x45VENT_TYPE_WORKFLOW_TASK_FAILED\x10\t\x12&\n"EVENT_TYPE_ACTIVITY_TASK_SCHEDULED\x10\n\x12$\n EVENT_TYPE_ACTIVITY_TASK_STARTED\x10\x0b\x12&\n"EVENT_TYPE_ACTIVITY_TASK_COMPLETED\x10\x0c\x12#\n\x1f\x45VENT_TYPE_ACTIVITY_TASK_FAILED\x10\r\x12&\n"EVENT_TYPE_ACTIVITY_TASK_TIMED_OUT\x10\x0e\x12-\n)EVENT_TYPE_ACTIVITY_TASK_CANCEL_REQUESTED\x10\x0f\x12%\n!EVENT_TYPE_ACTIVITY_TASK_CANCELED\x10\x10\x12\x1c\n\x18\x45VENT_TYPE_TIMER_STARTED\x10\x11\x12\x1a\n\x16\x45VENT_TYPE_TIMER_FIRED\x10\x12\x12\x1d\n\x19\x45VENT_TYPE_TIMER_CANCELED\x10\x13\x12\x32\n.EVENT_TYPE_WORKFLOW_EXECUTION_CANCEL_REQUESTED\x10\x14\x12*\n&EVENT_TYPE_WORKFLOW_EXECUTION_CANCELED\x10\x15\x12\x43\n?EVENT_TYPE_REQUEST_CANCEL_EXTERNAL_WORKFLOW_EXECUTION_INITIATED\x10\x16\x12@\n None: ... global___ActivityExecutionAlreadyStartedFailure = ActivityExecutionAlreadyStartedFailure + +class NexusOperationExecutionAlreadyStartedFailure(google.protobuf.message.Message): + """An error indicating that a Nexus operation failed to start. Returned when there is an existing operation with the + given operation ID, and the given ID reuse and conflict policies do not permit starting a new one or attaching to an + existing one. + """ + + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + START_REQUEST_ID_FIELD_NUMBER: builtins.int + RUN_ID_FIELD_NUMBER: builtins.int + start_request_id: builtins.str + run_id: builtins.str + def __init__( + self, + *, + start_request_id: builtins.str = ..., + run_id: builtins.str = ..., + ) -> None: ... + def ClearField( + self, + field_name: typing_extensions.Literal[ + "run_id", b"run_id", "start_request_id", b"start_request_id" + ], + ) -> None: ... + +global___NexusOperationExecutionAlreadyStartedFailure = ( + NexusOperationExecutionAlreadyStartedFailure +) diff --git a/temporalio/api/failure/v1/message_pb2.py b/temporalio/api/failure/v1/message_pb2.py index 6b6133112..db46b0717 100644 --- a/temporalio/api/failure/v1/message_pb2.py +++ b/temporalio/api/failure/v1/message_pb2.py @@ -30,7 +30,7 @@ ) DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile( - b'\n%temporal/api/failure/v1/message.proto\x12\x17temporal.api.failure.v1\x1a$temporal/api/common/v1/message.proto\x1a$temporal/api/enums/v1/workflow.proto\x1a!temporal/api/enums/v1/nexus.proto\x1a"temporal/api/enums/v1/common.proto\x1a\x1egoogle/protobuf/duration.proto"\xe8\x01\n\x16\x41pplicationFailureInfo\x12\x0c\n\x04type\x18\x01 \x01(\t\x12\x15\n\rnon_retryable\x18\x02 \x01(\x08\x12\x31\n\x07\x64\x65tails\x18\x03 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x33\n\x10next_retry_delay\x18\x04 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x41\n\x08\x63\x61tegory\x18\x05 \x01(\x0e\x32/.temporal.api.enums.v1.ApplicationErrorCategory"\x90\x01\n\x12TimeoutFailureInfo\x12\x38\n\x0ctimeout_type\x18\x01 \x01(\x0e\x32".temporal.api.enums.v1.TimeoutType\x12@\n\x16last_heartbeat_details\x18\x02 \x01(\x0b\x32 .temporal.api.common.v1.Payloads"H\n\x13\x43\x61nceledFailureInfo\x12\x31\n\x07\x64\x65tails\x18\x01 \x01(\x0b\x32 .temporal.api.common.v1.Payloads"\x17\n\x15TerminatedFailureInfo"*\n\x11ServerFailureInfo\x12\x15\n\rnon_retryable\x18\x01 \x01(\x08"\\\n\x18ResetWorkflowFailureInfo\x12@\n\x16last_heartbeat_details\x18\x01 \x01(\x0b\x32 .temporal.api.common.v1.Payloads"\xe7\x01\n\x13\x41\x63tivityFailureInfo\x12\x1a\n\x12scheduled_event_id\x18\x01 \x01(\x03\x12\x18\n\x10started_event_id\x18\x02 \x01(\x03\x12\x10\n\x08identity\x18\x03 \x01(\t\x12;\n\ractivity_type\x18\x04 \x01(\x0b\x32$.temporal.api.common.v1.ActivityType\x12\x13\n\x0b\x61\x63tivity_id\x18\x05 \x01(\t\x12\x36\n\x0bretry_state\x18\x06 \x01(\x0e\x32!.temporal.api.enums.v1.RetryState"\xa8\x02\n!ChildWorkflowExecutionFailureInfo\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x45\n\x12workflow_execution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12;\n\rworkflow_type\x18\x03 \x01(\x0b\x32$.temporal.api.common.v1.WorkflowType\x12\x1a\n\x12initiated_event_id\x18\x04 \x01(\x03\x12\x18\n\x10started_event_id\x18\x05 \x01(\x03\x12\x36\n\x0bretry_state\x18\x06 \x01(\x0e\x32!.temporal.api.enums.v1.RetryState"\xa0\x01\n\x19NexusOperationFailureInfo\x12\x1a\n\x12scheduled_event_id\x18\x01 \x01(\x03\x12\x10\n\x08\x65ndpoint\x18\x02 \x01(\t\x12\x0f\n\x07service\x18\x03 \x01(\t\x12\x11\n\toperation\x18\x04 \x01(\t\x12\x18\n\x0coperation_id\x18\x05 \x01(\tB\x02\x18\x01\x12\x17\n\x0foperation_token\x18\x06 \x01(\t"v\n\x17NexusHandlerFailureInfo\x12\x0c\n\x04type\x18\x01 \x01(\t\x12M\n\x0eretry_behavior\x18\x02 \x01(\x0e\x32\x35.temporal.api.enums.v1.NexusHandlerErrorRetryBehavior"\xa0\x08\n\x07\x46\x61ilure\x12\x0f\n\x07message\x18\x01 \x01(\t\x12\x0e\n\x06source\x18\x02 \x01(\t\x12\x13\n\x0bstack_trace\x18\x03 \x01(\t\x12;\n\x12\x65ncoded_attributes\x18\x14 \x01(\x0b\x32\x1f.temporal.api.common.v1.Payload\x12/\n\x05\x63\x61use\x18\x04 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12S\n\x18\x61pplication_failure_info\x18\x05 \x01(\x0b\x32/.temporal.api.failure.v1.ApplicationFailureInfoH\x00\x12K\n\x14timeout_failure_info\x18\x06 \x01(\x0b\x32+.temporal.api.failure.v1.TimeoutFailureInfoH\x00\x12M\n\x15\x63\x61nceled_failure_info\x18\x07 \x01(\x0b\x32,.temporal.api.failure.v1.CanceledFailureInfoH\x00\x12Q\n\x17terminated_failure_info\x18\x08 \x01(\x0b\x32..temporal.api.failure.v1.TerminatedFailureInfoH\x00\x12I\n\x13server_failure_info\x18\t \x01(\x0b\x32*.temporal.api.failure.v1.ServerFailureInfoH\x00\x12X\n\x1breset_workflow_failure_info\x18\n \x01(\x0b\x32\x31.temporal.api.failure.v1.ResetWorkflowFailureInfoH\x00\x12M\n\x15\x61\x63tivity_failure_info\x18\x0b \x01(\x0b\x32,.temporal.api.failure.v1.ActivityFailureInfoH\x00\x12k\n%child_workflow_execution_failure_info\x18\x0c \x01(\x0b\x32:.temporal.api.failure.v1.ChildWorkflowExecutionFailureInfoH\x00\x12\x64\n&nexus_operation_execution_failure_info\x18\r \x01(\x0b\x32\x32.temporal.api.failure.v1.NexusOperationFailureInfoH\x00\x12V\n\x1anexus_handler_failure_info\x18\x0e \x01(\x0b\x32\x30.temporal.api.failure.v1.NexusHandlerFailureInfoH\x00\x42\x0e\n\x0c\x66\x61ilure_info" \n\x1eMultiOperationExecutionAbortedB\x8e\x01\n\x1aio.temporal.api.failure.v1B\x0cMessageProtoP\x01Z%go.temporal.io/api/failure/v1;failure\xaa\x02\x19Temporalio.Api.Failure.V1\xea\x02\x1cTemporalio::Api::Failure::V1b\x06proto3' + b'\n%temporal/api/failure/v1/message.proto\x12\x17temporal.api.failure.v1\x1a$temporal/api/common/v1/message.proto\x1a$temporal/api/enums/v1/workflow.proto\x1a!temporal/api/enums/v1/nexus.proto\x1a"temporal/api/enums/v1/common.proto\x1a\x1egoogle/protobuf/duration.proto"\xe8\x01\n\x16\x41pplicationFailureInfo\x12\x0c\n\x04type\x18\x01 \x01(\t\x12\x15\n\rnon_retryable\x18\x02 \x01(\x08\x12\x31\n\x07\x64\x65tails\x18\x03 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x33\n\x10next_retry_delay\x18\x04 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x41\n\x08\x63\x61tegory\x18\x05 \x01(\x0e\x32/.temporal.api.enums.v1.ApplicationErrorCategory"\x90\x01\n\x12TimeoutFailureInfo\x12\x38\n\x0ctimeout_type\x18\x01 \x01(\x0e\x32".temporal.api.enums.v1.TimeoutType\x12@\n\x16last_heartbeat_details\x18\x02 \x01(\x0b\x32 .temporal.api.common.v1.Payloads"Z\n\x13\x43\x61nceledFailureInfo\x12\x31\n\x07\x64\x65tails\x18\x01 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x10\n\x08identity\x18\x02 \x01(\t")\n\x15TerminatedFailureInfo\x12\x10\n\x08identity\x18\x01 \x01(\t"*\n\x11ServerFailureInfo\x12\x15\n\rnon_retryable\x18\x01 \x01(\x08"\\\n\x18ResetWorkflowFailureInfo\x12@\n\x16last_heartbeat_details\x18\x01 \x01(\x0b\x32 .temporal.api.common.v1.Payloads"\xe7\x01\n\x13\x41\x63tivityFailureInfo\x12\x1a\n\x12scheduled_event_id\x18\x01 \x01(\x03\x12\x18\n\x10started_event_id\x18\x02 \x01(\x03\x12\x10\n\x08identity\x18\x03 \x01(\t\x12;\n\ractivity_type\x18\x04 \x01(\x0b\x32$.temporal.api.common.v1.ActivityType\x12\x13\n\x0b\x61\x63tivity_id\x18\x05 \x01(\t\x12\x36\n\x0bretry_state\x18\x06 \x01(\x0e\x32!.temporal.api.enums.v1.RetryState"\xa8\x02\n!ChildWorkflowExecutionFailureInfo\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x45\n\x12workflow_execution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12;\n\rworkflow_type\x18\x03 \x01(\x0b\x32$.temporal.api.common.v1.WorkflowType\x12\x1a\n\x12initiated_event_id\x18\x04 \x01(\x03\x12\x18\n\x10started_event_id\x18\x05 \x01(\x03\x12\x36\n\x0bretry_state\x18\x06 \x01(\x0e\x32!.temporal.api.enums.v1.RetryState"\xa0\x01\n\x19NexusOperationFailureInfo\x12\x1a\n\x12scheduled_event_id\x18\x01 \x01(\x03\x12\x10\n\x08\x65ndpoint\x18\x02 \x01(\t\x12\x0f\n\x07service\x18\x03 \x01(\t\x12\x11\n\toperation\x18\x04 \x01(\t\x12\x18\n\x0coperation_id\x18\x05 \x01(\tB\x02\x18\x01\x12\x17\n\x0foperation_token\x18\x06 \x01(\t"v\n\x17NexusHandlerFailureInfo\x12\x0c\n\x04type\x18\x01 \x01(\t\x12M\n\x0eretry_behavior\x18\x02 \x01(\x0e\x32\x35.temporal.api.enums.v1.NexusHandlerErrorRetryBehavior"\xa0\x08\n\x07\x46\x61ilure\x12\x0f\n\x07message\x18\x01 \x01(\t\x12\x0e\n\x06source\x18\x02 \x01(\t\x12\x13\n\x0bstack_trace\x18\x03 \x01(\t\x12;\n\x12\x65ncoded_attributes\x18\x14 \x01(\x0b\x32\x1f.temporal.api.common.v1.Payload\x12/\n\x05\x63\x61use\x18\x04 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12S\n\x18\x61pplication_failure_info\x18\x05 \x01(\x0b\x32/.temporal.api.failure.v1.ApplicationFailureInfoH\x00\x12K\n\x14timeout_failure_info\x18\x06 \x01(\x0b\x32+.temporal.api.failure.v1.TimeoutFailureInfoH\x00\x12M\n\x15\x63\x61nceled_failure_info\x18\x07 \x01(\x0b\x32,.temporal.api.failure.v1.CanceledFailureInfoH\x00\x12Q\n\x17terminated_failure_info\x18\x08 \x01(\x0b\x32..temporal.api.failure.v1.TerminatedFailureInfoH\x00\x12I\n\x13server_failure_info\x18\t \x01(\x0b\x32*.temporal.api.failure.v1.ServerFailureInfoH\x00\x12X\n\x1breset_workflow_failure_info\x18\n \x01(\x0b\x32\x31.temporal.api.failure.v1.ResetWorkflowFailureInfoH\x00\x12M\n\x15\x61\x63tivity_failure_info\x18\x0b \x01(\x0b\x32,.temporal.api.failure.v1.ActivityFailureInfoH\x00\x12k\n%child_workflow_execution_failure_info\x18\x0c \x01(\x0b\x32:.temporal.api.failure.v1.ChildWorkflowExecutionFailureInfoH\x00\x12\x64\n&nexus_operation_execution_failure_info\x18\r \x01(\x0b\x32\x32.temporal.api.failure.v1.NexusOperationFailureInfoH\x00\x12V\n\x1anexus_handler_failure_info\x18\x0e \x01(\x0b\x32\x30.temporal.api.failure.v1.NexusHandlerFailureInfoH\x00\x42\x0e\n\x0c\x66\x61ilure_info" \n\x1eMultiOperationExecutionAbortedB\x8e\x01\n\x1aio.temporal.api.failure.v1B\x0cMessageProtoP\x01Z%go.temporal.io/api/failure/v1;failure\xaa\x02\x19Temporalio.Api.Failure.V1\xea\x02\x1cTemporalio::Api::Failure::V1b\x06proto3' ) @@ -196,23 +196,23 @@ _TIMEOUTFAILUREINFO._serialized_start = 481 _TIMEOUTFAILUREINFO._serialized_end = 625 _CANCELEDFAILUREINFO._serialized_start = 627 - _CANCELEDFAILUREINFO._serialized_end = 699 - _TERMINATEDFAILUREINFO._serialized_start = 701 - _TERMINATEDFAILUREINFO._serialized_end = 724 - _SERVERFAILUREINFO._serialized_start = 726 - _SERVERFAILUREINFO._serialized_end = 768 - _RESETWORKFLOWFAILUREINFO._serialized_start = 770 - _RESETWORKFLOWFAILUREINFO._serialized_end = 862 - _ACTIVITYFAILUREINFO._serialized_start = 865 - _ACTIVITYFAILUREINFO._serialized_end = 1096 - _CHILDWORKFLOWEXECUTIONFAILUREINFO._serialized_start = 1099 - _CHILDWORKFLOWEXECUTIONFAILUREINFO._serialized_end = 1395 - _NEXUSOPERATIONFAILUREINFO._serialized_start = 1398 - _NEXUSOPERATIONFAILUREINFO._serialized_end = 1558 - _NEXUSHANDLERFAILUREINFO._serialized_start = 1560 - _NEXUSHANDLERFAILUREINFO._serialized_end = 1678 - _FAILURE._serialized_start = 1681 - _FAILURE._serialized_end = 2737 - _MULTIOPERATIONEXECUTIONABORTED._serialized_start = 2739 - _MULTIOPERATIONEXECUTIONABORTED._serialized_end = 2771 + _CANCELEDFAILUREINFO._serialized_end = 717 + _TERMINATEDFAILUREINFO._serialized_start = 719 + _TERMINATEDFAILUREINFO._serialized_end = 760 + _SERVERFAILUREINFO._serialized_start = 762 + _SERVERFAILUREINFO._serialized_end = 804 + _RESETWORKFLOWFAILUREINFO._serialized_start = 806 + _RESETWORKFLOWFAILUREINFO._serialized_end = 898 + _ACTIVITYFAILUREINFO._serialized_start = 901 + _ACTIVITYFAILUREINFO._serialized_end = 1132 + _CHILDWORKFLOWEXECUTIONFAILUREINFO._serialized_start = 1135 + _CHILDWORKFLOWEXECUTIONFAILUREINFO._serialized_end = 1431 + _NEXUSOPERATIONFAILUREINFO._serialized_start = 1434 + _NEXUSOPERATIONFAILUREINFO._serialized_end = 1594 + _NEXUSHANDLERFAILUREINFO._serialized_start = 1596 + _NEXUSHANDLERFAILUREINFO._serialized_end = 1714 + _FAILURE._serialized_start = 1717 + _FAILURE._serialized_end = 2773 + _MULTIOPERATIONEXECUTIONABORTED._serialized_start = 2775 + _MULTIOPERATIONEXECUTIONABORTED._serialized_end = 2807 # @@protoc_insertion_point(module_scope) diff --git a/temporalio/api/failure/v1/message_pb2.pyi b/temporalio/api/failure/v1/message_pb2.pyi index 131e67883..e0eecf7e7 100644 --- a/temporalio/api/failure/v1/message_pb2.pyi +++ b/temporalio/api/failure/v1/message_pb2.pyi @@ -114,18 +114,25 @@ class CanceledFailureInfo(google.protobuf.message.Message): DESCRIPTOR: google.protobuf.descriptor.Descriptor DETAILS_FIELD_NUMBER: builtins.int + IDENTITY_FIELD_NUMBER: builtins.int @property def details(self) -> temporalio.api.common.v1.message_pb2.Payloads: ... + identity: builtins.str + """The identity of the worker or client that requested the cancellation.""" def __init__( self, *, details: temporalio.api.common.v1.message_pb2.Payloads | None = ..., + identity: builtins.str = ..., ) -> None: ... def HasField( self, field_name: typing_extensions.Literal["details", b"details"] ) -> builtins.bool: ... def ClearField( - self, field_name: typing_extensions.Literal["details", b"details"] + self, + field_name: typing_extensions.Literal[ + "details", b"details", "identity", b"identity" + ], ) -> None: ... global___CanceledFailureInfo = CanceledFailureInfo @@ -133,8 +140,16 @@ global___CanceledFailureInfo = CanceledFailureInfo class TerminatedFailureInfo(google.protobuf.message.Message): DESCRIPTOR: google.protobuf.descriptor.Descriptor + IDENTITY_FIELD_NUMBER: builtins.int + identity: builtins.str + """The identity of the worker or client that requested the termination.""" def __init__( self, + *, + identity: builtins.str = ..., + ) -> None: ... + def ClearField( + self, field_name: typing_extensions.Literal["identity", b"identity"] ) -> None: ... global___TerminatedFailureInfo = TerminatedFailureInfo diff --git a/temporalio/api/history/v1/__init__.py b/temporalio/api/history/v1/__init__.py index 96160cf4f..ec7f65962 100644 --- a/temporalio/api/history/v1/__init__.py +++ b/temporalio/api/history/v1/__init__.py @@ -49,6 +49,7 @@ WorkflowExecutionStartedEventAttributes, WorkflowExecutionTerminatedEventAttributes, WorkflowExecutionTimedOutEventAttributes, + WorkflowExecutionTimeSkippingTransitionedEventAttributes, WorkflowExecutionUnpausedEventAttributes, WorkflowExecutionUpdateAcceptedEventAttributes, WorkflowExecutionUpdateAdmittedEventAttributes, @@ -113,6 +114,7 @@ "WorkflowExecutionSignaledEventAttributes", "WorkflowExecutionStartedEventAttributes", "WorkflowExecutionTerminatedEventAttributes", + "WorkflowExecutionTimeSkippingTransitionedEventAttributes", "WorkflowExecutionTimedOutEventAttributes", "WorkflowExecutionUnpausedEventAttributes", "WorkflowExecutionUpdateAcceptedEventAttributes", diff --git a/temporalio/api/history/v1/message_pb2.py b/temporalio/api/history/v1/message_pb2.py index 55a236cdb..0c22ff973 100644 --- a/temporalio/api/history/v1/message_pb2.py +++ b/temporalio/api/history/v1/message_pb2.py @@ -55,7 +55,7 @@ ) DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile( - b'\n%temporal/api/history/v1/message.proto\x12\x17temporal.api.history.v1\x1a\x1egoogle/protobuf/duration.proto\x1a\x1fgoogle/protobuf/timestamp.proto\x1a&temporal/api/enums/v1/event_type.proto\x1a(temporal/api/enums/v1/failed_cause.proto\x1a"temporal/api/enums/v1/update.proto\x1a$temporal/api/enums/v1/workflow.proto\x1a$temporal/api/common/v1/message.proto\x1a(temporal/api/deployment/v1/message.proto\x1a%temporal/api/failure/v1/message.proto\x1a\'temporal/api/taskqueue/v1/message.proto\x1a$temporal/api/update/v1/message.proto\x1a&temporal/api/workflow/v1/message.proto\x1a\x30temporal/api/sdk/v1/task_complete_metadata.proto\x1a\'temporal/api/sdk/v1/user_metadata.proto"\x91\x11\n\'WorkflowExecutionStartedEventAttributes\x12;\n\rworkflow_type\x18\x01 \x01(\x0b\x32$.temporal.api.common.v1.WorkflowType\x12!\n\x19parent_workflow_namespace\x18\x02 \x01(\t\x12$\n\x1cparent_workflow_namespace_id\x18\x1b \x01(\t\x12L\n\x19parent_workflow_execution\x18\x03 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12!\n\x19parent_initiated_event_id\x18\x04 \x01(\x03\x12\x38\n\ntask_queue\x18\x05 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12/\n\x05input\x18\x06 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12=\n\x1aworkflow_execution_timeout\x18\x07 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x37\n\x14workflow_run_timeout\x18\x08 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x38\n\x15workflow_task_timeout\x18\t \x01(\x0b\x32\x19.google.protobuf.Duration\x12"\n\x1a\x63ontinued_execution_run_id\x18\n \x01(\t\x12@\n\tinitiator\x18\x0b \x01(\x0e\x32-.temporal.api.enums.v1.ContinueAsNewInitiator\x12;\n\x11\x63ontinued_failure\x18\x0c \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12@\n\x16last_completion_result\x18\r \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12!\n\x19original_execution_run_id\x18\x0e \x01(\t\x12\x10\n\x08identity\x18\x0f \x01(\t\x12\x1e\n\x16\x66irst_execution_run_id\x18\x10 \x01(\t\x12\x39\n\x0cretry_policy\x18\x11 \x01(\x0b\x32#.temporal.api.common.v1.RetryPolicy\x12\x0f\n\x07\x61ttempt\x18\x12 \x01(\x05\x12\x46\n"workflow_execution_expiration_time\x18\x13 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x15\n\rcron_schedule\x18\x14 \x01(\t\x12>\n\x1b\x66irst_workflow_task_backoff\x18\x15 \x01(\x0b\x32\x19.google.protobuf.Duration\x12*\n\x04memo\x18\x16 \x01(\x0b\x32\x1c.temporal.api.common.v1.Memo\x12\x43\n\x11search_attributes\x18\x17 \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes\x12\x45\n\x16prev_auto_reset_points\x18\x18 \x01(\x0b\x32%.temporal.api.workflow.v1.ResetPoints\x12.\n\x06header\x18\x19 \x01(\x0b\x32\x1e.temporal.api.common.v1.Header\x12&\n\x1eparent_initiated_event_version\x18\x1a \x01(\x03\x12\x13\n\x0bworkflow_id\x18\x1c \x01(\t\x12L\n\x14source_version_stamp\x18\x1d \x01(\x0b\x32*.temporal.api.common.v1.WorkerVersionStampB\x02\x18\x01\x12>\n\x14\x63ompletion_callbacks\x18\x1e \x03(\x0b\x32 .temporal.api.common.v1.Callback\x12J\n\x17root_workflow_execution\x18\x1f \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x1e\n\x12inherited_build_id\x18 \x01(\tB\x02\x18\x01\x12I\n\x13versioning_override\x18! \x01(\x0b\x32,.temporal.api.workflow.v1.VersioningOverride\x12\x33\n\'parent_pinned_worker_deployment_version\x18" \x01(\tB\x02\x18\x01\x12\x32\n\x08priority\x18# \x01(\x0b\x32 .temporal.api.common.v1.Priority\x12U\n\x18inherited_pinned_version\x18% \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersion\x12Y\n\x1binherited_auto_upgrade_info\x18\' \x01(\x0b\x32\x34.temporal.api.deployment.v1.InheritedAutoUpgradeInfo\x12 \n\x18\x65\x61ger_execution_accepted\x18& \x01(\x08\x12^\n\x1f\x64\x65\x63lined_target_version_upgrade\x18( \x01(\x0b\x32\x35.temporal.api.history.v1.DeclinedTargetVersionUpgradeJ\x04\x08$\x10%R parent_pinned_deployment_version"o\n\x1c\x44\x65\x63linedTargetVersionUpgrade\x12O\n\x12\x64\x65ployment_version\x18\x01 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersion"\xa5\x01\n)WorkflowExecutionCompletedEventAttributes\x12\x30\n\x06result\x18\x01 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12(\n workflow_task_completed_event_id\x18\x02 \x01(\x03\x12\x1c\n\x14new_execution_run_id\x18\x03 \x01(\t"\xdb\x01\n&WorkflowExecutionFailedEventAttributes\x12\x31\n\x07\x66\x61ilure\x18\x01 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12\x36\n\x0bretry_state\x18\x02 \x01(\x0e\x32!.temporal.api.enums.v1.RetryState\x12(\n workflow_task_completed_event_id\x18\x03 \x01(\x03\x12\x1c\n\x14new_execution_run_id\x18\x04 \x01(\t"\x80\x01\n(WorkflowExecutionTimedOutEventAttributes\x12\x36\n\x0bretry_state\x18\x01 \x01(\x0e\x32!.temporal.api.enums.v1.RetryState\x12\x1c\n\x14new_execution_run_id\x18\x02 \x01(\t"\xa5\x07\n.WorkflowExecutionContinuedAsNewEventAttributes\x12\x1c\n\x14new_execution_run_id\x18\x01 \x01(\t\x12;\n\rworkflow_type\x18\x02 \x01(\x0b\x32$.temporal.api.common.v1.WorkflowType\x12\x38\n\ntask_queue\x18\x03 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12/\n\x05input\x18\x04 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x37\n\x14workflow_run_timeout\x18\x05 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x38\n\x15workflow_task_timeout\x18\x06 \x01(\x0b\x32\x19.google.protobuf.Duration\x12(\n workflow_task_completed_event_id\x18\x07 \x01(\x03\x12\x39\n\x16\x62\x61\x63koff_start_interval\x18\x08 \x01(\x0b\x32\x19.google.protobuf.Duration\x12@\n\tinitiator\x18\t \x01(\x0e\x32-.temporal.api.enums.v1.ContinueAsNewInitiator\x12\x35\n\x07\x66\x61ilure\x18\n \x01(\x0b\x32 .temporal.api.failure.v1.FailureB\x02\x18\x01\x12@\n\x16last_completion_result\x18\x0b \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12.\n\x06header\x18\x0c \x01(\x0b\x32\x1e.temporal.api.common.v1.Header\x12*\n\x04memo\x18\r \x01(\x0b\x32\x1c.temporal.api.common.v1.Memo\x12\x43\n\x11search_attributes\x18\x0e \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes\x12\x1c\n\x10inherit_build_id\x18\x0f \x01(\x08\x42\x02\x18\x01\x12[\n\x1binitial_versioning_behavior\x18\x10 \x01(\x0e\x32\x36.temporal.api.enums.v1.ContinueAsNewVersioningBehavior"\xac\x01\n$WorkflowTaskScheduledEventAttributes\x12\x38\n\ntask_queue\x18\x01 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12\x39\n\x16start_to_close_timeout\x18\x02 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x0f\n\x07\x61ttempt\x18\x03 \x01(\x05"\xa0\x03\n"WorkflowTaskStartedEventAttributes\x12\x1a\n\x12scheduled_event_id\x18\x01 \x01(\x03\x12\x10\n\x08identity\x18\x02 \x01(\t\x12\x12\n\nrequest_id\x18\x03 \x01(\t\x12\x1f\n\x17suggest_continue_as_new\x18\x04 \x01(\x08\x12Z\n\x1fsuggest_continue_as_new_reasons\x18\x08 \x03(\x0e\x32\x31.temporal.api.enums.v1.SuggestContinueAsNewReason\x12\x30\n(target_worker_deployment_version_changed\x18\t \x01(\x08\x12\x1a\n\x12history_size_bytes\x18\x05 \x01(\x03\x12\x46\n\x0eworker_version\x18\x06 \x01(\x0b\x32*.temporal.api.common.v1.WorkerVersionStampB\x02\x18\x01\x12%\n\x19\x62uild_id_redirect_counter\x18\x07 \x01(\x03\x42\x02\x18\x01"\x82\x05\n$WorkflowTaskCompletedEventAttributes\x12\x1a\n\x12scheduled_event_id\x18\x01 \x01(\x03\x12\x18\n\x10started_event_id\x18\x02 \x01(\x03\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x1b\n\x0f\x62inary_checksum\x18\x04 \x01(\tB\x02\x18\x01\x12\x46\n\x0eworker_version\x18\x05 \x01(\x0b\x32*.temporal.api.common.v1.WorkerVersionStampB\x02\x18\x01\x12H\n\x0csdk_metadata\x18\x06 \x01(\x0b\x32\x32.temporal.api.sdk.v1.WorkflowTaskCompletedMetadata\x12\x43\n\x11metering_metadata\x18\r \x01(\x0b\x32(.temporal.api.common.v1.MeteringMetadata\x12>\n\ndeployment\x18\x07 \x01(\x0b\x32&.temporal.api.deployment.v1.DeploymentB\x02\x18\x01\x12\x46\n\x13versioning_behavior\x18\x08 \x01(\x0e\x32).temporal.api.enums.v1.VersioningBehavior\x12%\n\x19worker_deployment_version\x18\t \x01(\tB\x02\x18\x01\x12\x1e\n\x16worker_deployment_name\x18\n \x01(\t\x12O\n\x12\x64\x65ployment_version\x18\x0b \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersion"\x95\x01\n#WorkflowTaskTimedOutEventAttributes\x12\x1a\n\x12scheduled_event_id\x18\x01 \x01(\x03\x12\x18\n\x10started_event_id\x18\x02 \x01(\x03\x12\x38\n\x0ctimeout_type\x18\x03 \x01(\x0e\x32".temporal.api.enums.v1.TimeoutType"\x87\x03\n!WorkflowTaskFailedEventAttributes\x12\x1a\n\x12scheduled_event_id\x18\x01 \x01(\x03\x12\x18\n\x10started_event_id\x18\x02 \x01(\x03\x12=\n\x05\x63\x61use\x18\x03 \x01(\x0e\x32..temporal.api.enums.v1.WorkflowTaskFailedCause\x12\x31\n\x07\x66\x61ilure\x18\x04 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12\x10\n\x08identity\x18\x05 \x01(\t\x12\x13\n\x0b\x62\x61se_run_id\x18\x06 \x01(\t\x12\x12\n\nnew_run_id\x18\x07 \x01(\t\x12\x1a\n\x12\x66ork_event_version\x18\x08 \x01(\x03\x12\x1b\n\x0f\x62inary_checksum\x18\t \x01(\tB\x02\x18\x01\x12\x46\n\x0eworker_version\x18\n \x01(\x0b\x32*.temporal.api.common.v1.WorkerVersionStampB\x02\x18\x01"\xc2\x05\n$ActivityTaskScheduledEventAttributes\x12\x13\n\x0b\x61\x63tivity_id\x18\x01 \x01(\t\x12;\n\ractivity_type\x18\x02 \x01(\x0b\x32$.temporal.api.common.v1.ActivityType\x12\x38\n\ntask_queue\x18\x04 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12.\n\x06header\x18\x05 \x01(\x0b\x32\x1e.temporal.api.common.v1.Header\x12/\n\x05input\x18\x06 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12<\n\x19schedule_to_close_timeout\x18\x07 \x01(\x0b\x32\x19.google.protobuf.Duration\x12<\n\x19schedule_to_start_timeout\x18\x08 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x39\n\x16start_to_close_timeout\x18\t \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x34\n\x11heartbeat_timeout\x18\n \x01(\x0b\x32\x19.google.protobuf.Duration\x12(\n workflow_task_completed_event_id\x18\x0b \x01(\x03\x12\x39\n\x0cretry_policy\x18\x0c \x01(\x0b\x32#.temporal.api.common.v1.RetryPolicy\x12!\n\x15use_workflow_build_id\x18\r \x01(\x08\x42\x02\x18\x01\x12\x32\n\x08priority\x18\x0e \x01(\x0b\x32 .temporal.api.common.v1.PriorityJ\x04\x08\x03\x10\x04"\x9e\x02\n"ActivityTaskStartedEventAttributes\x12\x1a\n\x12scheduled_event_id\x18\x01 \x01(\x03\x12\x10\n\x08identity\x18\x02 \x01(\t\x12\x12\n\nrequest_id\x18\x03 \x01(\t\x12\x0f\n\x07\x61ttempt\x18\x04 \x01(\x05\x12\x36\n\x0clast_failure\x18\x05 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12\x46\n\x0eworker_version\x18\x06 \x01(\x0b\x32*.temporal.api.common.v1.WorkerVersionStampB\x02\x18\x01\x12%\n\x19\x62uild_id_redirect_counter\x18\x07 \x01(\x03\x42\x02\x18\x01"\xe8\x01\n$ActivityTaskCompletedEventAttributes\x12\x30\n\x06result\x18\x01 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x1a\n\x12scheduled_event_id\x18\x02 \x01(\x03\x12\x18\n\x10started_event_id\x18\x03 \x01(\x03\x12\x10\n\x08identity\x18\x04 \x01(\t\x12\x46\n\x0eworker_version\x18\x05 \x01(\x0b\x32*.temporal.api.common.v1.WorkerVersionStampB\x02\x18\x01"\x9e\x02\n!ActivityTaskFailedEventAttributes\x12\x31\n\x07\x66\x61ilure\x18\x01 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12\x1a\n\x12scheduled_event_id\x18\x02 \x01(\x03\x12\x18\n\x10started_event_id\x18\x03 \x01(\x03\x12\x10\n\x08identity\x18\x04 \x01(\t\x12\x36\n\x0bretry_state\x18\x05 \x01(\x0e\x32!.temporal.api.enums.v1.RetryState\x12\x46\n\x0eworker_version\x18\x06 \x01(\x0b\x32*.temporal.api.common.v1.WorkerVersionStampB\x02\x18\x01"\xc6\x01\n#ActivityTaskTimedOutEventAttributes\x12\x31\n\x07\x66\x61ilure\x18\x01 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12\x1a\n\x12scheduled_event_id\x18\x02 \x01(\x03\x12\x18\n\x10started_event_id\x18\x03 \x01(\x03\x12\x36\n\x0bretry_state\x18\x04 \x01(\x0e\x32!.temporal.api.enums.v1.RetryState"r\n*ActivityTaskCancelRequestedEventAttributes\x12\x1a\n\x12scheduled_event_id\x18\x01 \x01(\x03\x12(\n workflow_task_completed_event_id\x18\x02 \x01(\x03"\x92\x02\n#ActivityTaskCanceledEventAttributes\x12\x31\n\x07\x64\x65tails\x18\x01 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12(\n latest_cancel_requested_event_id\x18\x02 \x01(\x03\x12\x1a\n\x12scheduled_event_id\x18\x03 \x01(\x03\x12\x18\n\x10started_event_id\x18\x04 \x01(\x03\x12\x10\n\x08identity\x18\x05 \x01(\t\x12\x46\n\x0eworker_version\x18\x06 \x01(\x0b\x32*.temporal.api.common.v1.WorkerVersionStampB\x02\x18\x01"\x93\x01\n\x1bTimerStartedEventAttributes\x12\x10\n\x08timer_id\x18\x01 \x01(\t\x12\x38\n\x15start_to_fire_timeout\x18\x02 \x01(\x0b\x32\x19.google.protobuf.Duration\x12(\n workflow_task_completed_event_id\x18\x03 \x01(\x03"G\n\x19TimerFiredEventAttributes\x12\x10\n\x08timer_id\x18\x01 \x01(\t\x12\x18\n\x10started_event_id\x18\x02 \x01(\x03"\x86\x01\n\x1cTimerCanceledEventAttributes\x12\x10\n\x08timer_id\x18\x01 \x01(\t\x12\x18\n\x10started_event_id\x18\x02 \x01(\x03\x12(\n workflow_task_completed_event_id\x18\x03 \x01(\x03\x12\x10\n\x08identity\x18\x04 \x01(\t"\xc7\x01\n/WorkflowExecutionCancelRequestedEventAttributes\x12\r\n\x05\x63\x61use\x18\x01 \x01(\t\x12#\n\x1b\x65xternal_initiated_event_id\x18\x02 \x01(\x03\x12N\n\x1b\x65xternal_workflow_execution\x18\x03 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x10\n\x08identity\x18\x04 \x01(\t"\x87\x01\n(WorkflowExecutionCanceledEventAttributes\x12(\n workflow_task_completed_event_id\x18\x01 \x01(\x03\x12\x31\n\x07\x64\x65tails\x18\x02 \x01(\x0b\x32 .temporal.api.common.v1.Payloads"\xe9\x02\n\x1dMarkerRecordedEventAttributes\x12\x13\n\x0bmarker_name\x18\x01 \x01(\t\x12T\n\x07\x64\x65tails\x18\x02 \x03(\x0b\x32\x43.temporal.api.history.v1.MarkerRecordedEventAttributes.DetailsEntry\x12(\n workflow_task_completed_event_id\x18\x03 \x01(\x03\x12.\n\x06header\x18\x04 \x01(\x0b\x32\x1e.temporal.api.common.v1.Header\x12\x31\n\x07\x66\x61ilure\x18\x05 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x1aP\n\x0c\x44\x65tailsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12/\n\x05value\x18\x02 \x01(\x0b\x32 .temporal.api.common.v1.Payloads:\x02\x38\x01"\xab\x02\n(WorkflowExecutionSignaledEventAttributes\x12\x13\n\x0bsignal_name\x18\x01 \x01(\t\x12/\n\x05input\x18\x02 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x10\n\x08identity\x18\x03 \x01(\t\x12.\n\x06header\x18\x04 \x01(\x0b\x32\x1e.temporal.api.common.v1.Header\x12\'\n\x1bskip_generate_workflow_task\x18\x05 \x01(\x08\x42\x02\x18\x01\x12N\n\x1b\x65xternal_workflow_execution\x18\x06 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution"\x81\x01\n*WorkflowExecutionTerminatedEventAttributes\x12\x0e\n\x06reason\x18\x01 \x01(\t\x12\x31\n\x07\x64\x65tails\x18\x02 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x10\n\x08identity\x18\x03 \x01(\t"\x9c\x02\n>RequestCancelExternalWorkflowExecutionInitiatedEventAttributes\x12(\n workflow_task_completed_event_id\x18\x01 \x01(\x03\x12\x11\n\tnamespace\x18\x02 \x01(\t\x12\x14\n\x0cnamespace_id\x18\x07 \x01(\t\x12\x45\n\x12workflow_execution\x18\x03 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x13\n\x07\x63ontrol\x18\x04 \x01(\tB\x02\x18\x01\x12\x1b\n\x13\x63hild_workflow_only\x18\x05 \x01(\x08\x12\x0e\n\x06reason\x18\x06 \x01(\t"\xda\x02\n;RequestCancelExternalWorkflowExecutionFailedEventAttributes\x12P\n\x05\x63\x61use\x18\x01 \x01(\x0e\x32\x41.temporal.api.enums.v1.CancelExternalWorkflowExecutionFailedCause\x12(\n workflow_task_completed_event_id\x18\x02 \x01(\x03\x12\x11\n\tnamespace\x18\x03 \x01(\t\x12\x14\n\x0cnamespace_id\x18\x07 \x01(\t\x12\x45\n\x12workflow_execution\x18\x04 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x1a\n\x12initiated_event_id\x18\x05 \x01(\x03\x12\x13\n\x07\x63ontrol\x18\x06 \x01(\tB\x02\x18\x01"\xc5\x01\n7ExternalWorkflowExecutionCancelRequestedEventAttributes\x12\x1a\n\x12initiated_event_id\x18\x01 \x01(\x03\x12\x11\n\tnamespace\x18\x02 \x01(\t\x12\x14\n\x0cnamespace_id\x18\x04 \x01(\t\x12\x45\n\x12workflow_execution\x18\x03 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution"\xfb\x02\n7SignalExternalWorkflowExecutionInitiatedEventAttributes\x12(\n workflow_task_completed_event_id\x18\x01 \x01(\x03\x12\x11\n\tnamespace\x18\x02 \x01(\t\x12\x14\n\x0cnamespace_id\x18\t \x01(\t\x12\x45\n\x12workflow_execution\x18\x03 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x13\n\x0bsignal_name\x18\x04 \x01(\t\x12/\n\x05input\x18\x05 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x13\n\x07\x63ontrol\x18\x06 \x01(\tB\x02\x18\x01\x12\x1b\n\x13\x63hild_workflow_only\x18\x07 \x01(\x08\x12.\n\x06header\x18\x08 \x01(\x0b\x32\x1e.temporal.api.common.v1.Header"\xd3\x02\n4SignalExternalWorkflowExecutionFailedEventAttributes\x12P\n\x05\x63\x61use\x18\x01 \x01(\x0e\x32\x41.temporal.api.enums.v1.SignalExternalWorkflowExecutionFailedCause\x12(\n workflow_task_completed_event_id\x18\x02 \x01(\x03\x12\x11\n\tnamespace\x18\x03 \x01(\t\x12\x14\n\x0cnamespace_id\x18\x07 \x01(\t\x12\x45\n\x12workflow_execution\x18\x04 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x1a\n\x12initiated_event_id\x18\x05 \x01(\x03\x12\x13\n\x07\x63ontrol\x18\x06 \x01(\tB\x02\x18\x01"\xd3\x01\n0ExternalWorkflowExecutionSignaledEventAttributes\x12\x1a\n\x12initiated_event_id\x18\x01 \x01(\x03\x12\x11\n\tnamespace\x18\x02 \x01(\t\x12\x14\n\x0cnamespace_id\x18\x05 \x01(\t\x12\x45\n\x12workflow_execution\x18\x03 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x13\n\x07\x63ontrol\x18\x04 \x01(\tB\x02\x18\x01"\x9e\x01\n-UpsertWorkflowSearchAttributesEventAttributes\x12(\n workflow_task_completed_event_id\x18\x01 \x01(\x03\x12\x43\n\x11search_attributes\x18\x02 \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes"\x8a\x01\n)WorkflowPropertiesModifiedEventAttributes\x12(\n workflow_task_completed_event_id\x18\x01 \x01(\x03\x12\x33\n\rupserted_memo\x18\x02 \x01(\x0b\x32\x1c.temporal.api.common.v1.Memo"\xe8\x07\n3StartChildWorkflowExecutionInitiatedEventAttributes\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x14\n\x0cnamespace_id\x18\x12 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12;\n\rworkflow_type\x18\x03 \x01(\x0b\x32$.temporal.api.common.v1.WorkflowType\x12\x38\n\ntask_queue\x18\x04 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12/\n\x05input\x18\x05 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12=\n\x1aworkflow_execution_timeout\x18\x06 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x37\n\x14workflow_run_timeout\x18\x07 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x38\n\x15workflow_task_timeout\x18\x08 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x45\n\x13parent_close_policy\x18\t \x01(\x0e\x32(.temporal.api.enums.v1.ParentClosePolicy\x12\x13\n\x07\x63ontrol\x18\n \x01(\tB\x02\x18\x01\x12(\n workflow_task_completed_event_id\x18\x0b \x01(\x03\x12N\n\x18workflow_id_reuse_policy\x18\x0c \x01(\x0e\x32,.temporal.api.enums.v1.WorkflowIdReusePolicy\x12\x39\n\x0cretry_policy\x18\r \x01(\x0b\x32#.temporal.api.common.v1.RetryPolicy\x12\x15\n\rcron_schedule\x18\x0e \x01(\t\x12.\n\x06header\x18\x0f \x01(\x0b\x32\x1e.temporal.api.common.v1.Header\x12*\n\x04memo\x18\x10 \x01(\x0b\x32\x1c.temporal.api.common.v1.Memo\x12\x43\n\x11search_attributes\x18\x11 \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes\x12\x1c\n\x10inherit_build_id\x18\x13 \x01(\x08\x42\x02\x18\x01\x12\x32\n\x08priority\x18\x14 \x01(\x0b\x32 .temporal.api.common.v1.Priority"\xd6\x02\n0StartChildWorkflowExecutionFailedEventAttributes\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x14\n\x0cnamespace_id\x18\x08 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12;\n\rworkflow_type\x18\x03 \x01(\x0b\x32$.temporal.api.common.v1.WorkflowType\x12L\n\x05\x63\x61use\x18\x04 \x01(\x0e\x32=.temporal.api.enums.v1.StartChildWorkflowExecutionFailedCause\x12\x13\n\x07\x63ontrol\x18\x05 \x01(\tB\x02\x18\x01\x12\x1a\n\x12initiated_event_id\x18\x06 \x01(\x03\x12(\n workflow_task_completed_event_id\x18\x07 \x01(\x03"\xa7\x02\n,ChildWorkflowExecutionStartedEventAttributes\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x14\n\x0cnamespace_id\x18\x06 \x01(\t\x12\x1a\n\x12initiated_event_id\x18\x02 \x01(\x03\x12\x45\n\x12workflow_execution\x18\x03 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12;\n\rworkflow_type\x18\x04 \x01(\x0b\x32$.temporal.api.common.v1.WorkflowType\x12.\n\x06header\x18\x05 \x01(\x0b\x32\x1e.temporal.api.common.v1.Header"\xc5\x02\n.ChildWorkflowExecutionCompletedEventAttributes\x12\x30\n\x06result\x18\x01 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x11\n\tnamespace\x18\x02 \x01(\t\x12\x14\n\x0cnamespace_id\x18\x07 \x01(\t\x12\x45\n\x12workflow_execution\x18\x03 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12;\n\rworkflow_type\x18\x04 \x01(\x0b\x32$.temporal.api.common.v1.WorkflowType\x12\x1a\n\x12initiated_event_id\x18\x05 \x01(\x03\x12\x18\n\x10started_event_id\x18\x06 \x01(\x03"\xfb\x02\n+ChildWorkflowExecutionFailedEventAttributes\x12\x31\n\x07\x66\x61ilure\x18\x01 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12\x11\n\tnamespace\x18\x02 \x01(\t\x12\x14\n\x0cnamespace_id\x18\x08 \x01(\t\x12\x45\n\x12workflow_execution\x18\x03 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12;\n\rworkflow_type\x18\x04 \x01(\x0b\x32$.temporal.api.common.v1.WorkflowType\x12\x1a\n\x12initiated_event_id\x18\x05 \x01(\x03\x12\x18\n\x10started_event_id\x18\x06 \x01(\x03\x12\x36\n\x0bretry_state\x18\x07 \x01(\x0e\x32!.temporal.api.enums.v1.RetryState"\xc5\x02\n-ChildWorkflowExecutionCanceledEventAttributes\x12\x31\n\x07\x64\x65tails\x18\x01 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x11\n\tnamespace\x18\x02 \x01(\t\x12\x14\n\x0cnamespace_id\x18\x07 \x01(\t\x12\x45\n\x12workflow_execution\x18\x03 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12;\n\rworkflow_type\x18\x04 \x01(\x0b\x32$.temporal.api.common.v1.WorkflowType\x12\x1a\n\x12initiated_event_id\x18\x05 \x01(\x03\x12\x18\n\x10started_event_id\x18\x06 \x01(\x03"\xca\x02\n-ChildWorkflowExecutionTimedOutEventAttributes\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x14\n\x0cnamespace_id\x18\x07 \x01(\t\x12\x45\n\x12workflow_execution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12;\n\rworkflow_type\x18\x03 \x01(\x0b\x32$.temporal.api.common.v1.WorkflowType\x12\x1a\n\x12initiated_event_id\x18\x04 \x01(\x03\x12\x18\n\x10started_event_id\x18\x05 \x01(\x03\x12\x36\n\x0bretry_state\x18\x06 \x01(\x0e\x32!.temporal.api.enums.v1.RetryState"\x94\x02\n/ChildWorkflowExecutionTerminatedEventAttributes\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x14\n\x0cnamespace_id\x18\x06 \x01(\t\x12\x45\n\x12workflow_execution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12;\n\rworkflow_type\x18\x03 \x01(\x0b\x32$.temporal.api.common.v1.WorkflowType\x12\x1a\n\x12initiated_event_id\x18\x04 \x01(\x03\x12\x18\n\x10started_event_id\x18\x05 \x01(\x03"\xca\x02\n.WorkflowExecutionOptionsUpdatedEventAttributes\x12I\n\x13versioning_override\x18\x01 \x01(\x0b\x32,.temporal.api.workflow.v1.VersioningOverride\x12!\n\x19unset_versioning_override\x18\x02 \x01(\x08\x12\x1b\n\x13\x61ttached_request_id\x18\x03 \x01(\t\x12G\n\x1d\x61ttached_completion_callbacks\x18\x04 \x03(\x0b\x32 .temporal.api.common.v1.Callback\x12\x10\n\x08identity\x18\x05 \x01(\t\x12\x32\n\x08priority\x18\x06 \x01(\x0b\x32 .temporal.api.common.v1.Priority"\xc0\x02\n3WorkflowPropertiesModifiedExternallyEventAttributes\x12\x16\n\x0enew_task_queue\x18\x01 \x01(\t\x12<\n\x19new_workflow_task_timeout\x18\x02 \x01(\x0b\x32\x19.google.protobuf.Duration\x12;\n\x18new_workflow_run_timeout\x18\x03 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x41\n\x1enew_workflow_execution_timeout\x18\x04 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x33\n\rupserted_memo\x18\x05 \x01(\x0b\x32\x1c.temporal.api.common.v1.Memo"\x90\x01\n3ActivityPropertiesModifiedExternallyEventAttributes\x12\x1a\n\x12scheduled_event_id\x18\x01 \x01(\x03\x12=\n\x10new_retry_policy\x18\x02 \x01(\x0b\x32#.temporal.api.common.v1.RetryPolicy"\xdc\x01\n.WorkflowExecutionUpdateAcceptedEventAttributes\x12\x1c\n\x14protocol_instance_id\x18\x01 \x01(\t\x12#\n\x1b\x61\x63\x63\x65pted_request_message_id\x18\x02 \x01(\t\x12,\n$accepted_request_sequencing_event_id\x18\x03 \x01(\x03\x12\x39\n\x10\x61\x63\x63\x65pted_request\x18\x04 \x01(\x0b\x32\x1f.temporal.api.update.v1.Request"\xaa\x01\n/WorkflowExecutionUpdateCompletedEventAttributes\x12*\n\x04meta\x18\x01 \x01(\x0b\x32\x1c.temporal.api.update.v1.Meta\x12\x19\n\x11\x61\x63\x63\x65pted_event_id\x18\x03 \x01(\x03\x12\x30\n\x07outcome\x18\x02 \x01(\x0b\x32\x1f.temporal.api.update.v1.Outcome"\x8f\x02\n.WorkflowExecutionUpdateRejectedEventAttributes\x12\x1c\n\x14protocol_instance_id\x18\x01 \x01(\t\x12#\n\x1brejected_request_message_id\x18\x02 \x01(\t\x12,\n$rejected_request_sequencing_event_id\x18\x03 \x01(\x03\x12\x39\n\x10rejected_request\x18\x04 \x01(\x0b\x32\x1f.temporal.api.update.v1.Request\x12\x31\n\x07\x66\x61ilure\x18\x05 \x01(\x0b\x32 .temporal.api.failure.v1.Failure"\xa4\x01\n.WorkflowExecutionUpdateAdmittedEventAttributes\x12\x30\n\x07request\x18\x01 \x01(\x0b\x32\x1f.temporal.api.update.v1.Request\x12@\n\x06origin\x18\x02 \x01(\x0e\x32\x30.temporal.api.enums.v1.UpdateAdmittedEventOrigin"^\n&WorkflowExecutionPausedEventAttributes\x12\x10\n\x08identity\x18\x01 \x01(\t\x12\x0e\n\x06reason\x18\x02 \x01(\t\x12\x12\n\nrequest_id\x18\x03 \x01(\t"`\n(WorkflowExecutionUnpausedEventAttributes\x12\x10\n\x08identity\x18\x01 \x01(\t\x12\x0e\n\x06reason\x18\x02 \x01(\t\x12\x12\n\nrequest_id\x18\x03 \x01(\t"\xb4\x04\n&NexusOperationScheduledEventAttributes\x12\x10\n\x08\x65ndpoint\x18\x01 \x01(\t\x12\x0f\n\x07service\x18\x02 \x01(\t\x12\x11\n\toperation\x18\x03 \x01(\t\x12.\n\x05input\x18\x04 \x01(\x0b\x32\x1f.temporal.api.common.v1.Payload\x12<\n\x19schedule_to_close_timeout\x18\x05 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x66\n\x0cnexus_header\x18\x06 \x03(\x0b\x32P.temporal.api.history.v1.NexusOperationScheduledEventAttributes.NexusHeaderEntry\x12(\n workflow_task_completed_event_id\x18\x07 \x01(\x03\x12\x12\n\nrequest_id\x18\x08 \x01(\t\x12\x13\n\x0b\x65ndpoint_id\x18\t \x01(\t\x12<\n\x19schedule_to_start_timeout\x18\n \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x39\n\x16start_to_close_timeout\x18\x0b \x01(\x0b\x32\x19.google.protobuf.Duration\x1a\x32\n\x10NexusHeaderEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01"\x89\x01\n$NexusOperationStartedEventAttributes\x12\x1a\n\x12scheduled_event_id\x18\x01 \x01(\x03\x12\x18\n\x0coperation_id\x18\x03 \x01(\tB\x02\x18\x01\x12\x12\n\nrequest_id\x18\x04 \x01(\t\x12\x17\n\x0foperation_token\x18\x05 \x01(\t"\x89\x01\n&NexusOperationCompletedEventAttributes\x12\x1a\n\x12scheduled_event_id\x18\x01 \x01(\x03\x12/\n\x06result\x18\x02 \x01(\x0b\x32\x1f.temporal.api.common.v1.Payload\x12\x12\n\nrequest_id\x18\x03 \x01(\t"\x88\x01\n#NexusOperationFailedEventAttributes\x12\x1a\n\x12scheduled_event_id\x18\x01 \x01(\x03\x12\x31\n\x07\x66\x61ilure\x18\x02 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12\x12\n\nrequest_id\x18\x03 \x01(\t"\x8a\x01\n%NexusOperationTimedOutEventAttributes\x12\x1a\n\x12scheduled_event_id\x18\x01 \x01(\x03\x12\x31\n\x07\x66\x61ilure\x18\x02 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12\x12\n\nrequest_id\x18\x03 \x01(\t"\x8a\x01\n%NexusOperationCanceledEventAttributes\x12\x1a\n\x12scheduled_event_id\x18\x01 \x01(\x03\x12\x31\n\x07\x66\x61ilure\x18\x02 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12\x12\n\nrequest_id\x18\x03 \x01(\t"t\n,NexusOperationCancelRequestedEventAttributes\x12\x1a\n\x12scheduled_event_id\x18\x01 \x01(\x03\x12(\n workflow_task_completed_event_id\x18\x02 \x01(\x03"\x97\x01\n3NexusOperationCancelRequestCompletedEventAttributes\x12\x1a\n\x12requested_event_id\x18\x01 \x01(\x03\x12(\n workflow_task_completed_event_id\x18\x02 \x01(\x03\x12\x1a\n\x12scheduled_event_id\x18\x03 \x01(\x03"\xc7\x01\n0NexusOperationCancelRequestFailedEventAttributes\x12\x1a\n\x12requested_event_id\x18\x01 \x01(\x03\x12(\n workflow_task_completed_event_id\x18\x02 \x01(\x03\x12\x31\n\x07\x66\x61ilure\x18\x03 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12\x1a\n\x12scheduled_event_id\x18\x04 \x01(\x03"\xb0=\n\x0cHistoryEvent\x12\x10\n\x08\x65vent_id\x18\x01 \x01(\x03\x12.\n\nevent_time\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x34\n\nevent_type\x18\x03 \x01(\x0e\x32 .temporal.api.enums.v1.EventType\x12\x0f\n\x07version\x18\x04 \x01(\x03\x12\x0f\n\x07task_id\x18\x05 \x01(\x03\x12\x1a\n\x11worker_may_ignore\x18\xac\x02 \x01(\x08\x12\x39\n\ruser_metadata\x18\xad\x02 \x01(\x0b\x32!.temporal.api.sdk.v1.UserMetadata\x12,\n\x05links\x18\xae\x02 \x03(\x0b\x32\x1c.temporal.api.common.v1.Link\x12w\n+workflow_execution_started_event_attributes\x18\x06 \x01(\x0b\x32@.temporal.api.history.v1.WorkflowExecutionStartedEventAttributesH\x00\x12{\n-workflow_execution_completed_event_attributes\x18\x07 \x01(\x0b\x32\x42.temporal.api.history.v1.WorkflowExecutionCompletedEventAttributesH\x00\x12u\n*workflow_execution_failed_event_attributes\x18\x08 \x01(\x0b\x32?.temporal.api.history.v1.WorkflowExecutionFailedEventAttributesH\x00\x12z\n-workflow_execution_timed_out_event_attributes\x18\t \x01(\x0b\x32\x41.temporal.api.history.v1.WorkflowExecutionTimedOutEventAttributesH\x00\x12q\n(workflow_task_scheduled_event_attributes\x18\n \x01(\x0b\x32=.temporal.api.history.v1.WorkflowTaskScheduledEventAttributesH\x00\x12m\n&workflow_task_started_event_attributes\x18\x0b \x01(\x0b\x32;.temporal.api.history.v1.WorkflowTaskStartedEventAttributesH\x00\x12q\n(workflow_task_completed_event_attributes\x18\x0c \x01(\x0b\x32=.temporal.api.history.v1.WorkflowTaskCompletedEventAttributesH\x00\x12p\n(workflow_task_timed_out_event_attributes\x18\r \x01(\x0b\x32<.temporal.api.history.v1.WorkflowTaskTimedOutEventAttributesH\x00\x12k\n%workflow_task_failed_event_attributes\x18\x0e \x01(\x0b\x32:.temporal.api.history.v1.WorkflowTaskFailedEventAttributesH\x00\x12q\n(activity_task_scheduled_event_attributes\x18\x0f \x01(\x0b\x32=.temporal.api.history.v1.ActivityTaskScheduledEventAttributesH\x00\x12m\n&activity_task_started_event_attributes\x18\x10 \x01(\x0b\x32;.temporal.api.history.v1.ActivityTaskStartedEventAttributesH\x00\x12q\n(activity_task_completed_event_attributes\x18\x11 \x01(\x0b\x32=.temporal.api.history.v1.ActivityTaskCompletedEventAttributesH\x00\x12k\n%activity_task_failed_event_attributes\x18\x12 \x01(\x0b\x32:.temporal.api.history.v1.ActivityTaskFailedEventAttributesH\x00\x12p\n(activity_task_timed_out_event_attributes\x18\x13 \x01(\x0b\x32<.temporal.api.history.v1.ActivityTaskTimedOutEventAttributesH\x00\x12^\n\x1etimer_started_event_attributes\x18\x14 \x01(\x0b\x32\x34.temporal.api.history.v1.TimerStartedEventAttributesH\x00\x12Z\n\x1ctimer_fired_event_attributes\x18\x15 \x01(\x0b\x32\x32.temporal.api.history.v1.TimerFiredEventAttributesH\x00\x12~\n/activity_task_cancel_requested_event_attributes\x18\x16 \x01(\x0b\x32\x43.temporal.api.history.v1.ActivityTaskCancelRequestedEventAttributesH\x00\x12o\n\'activity_task_canceled_event_attributes\x18\x17 \x01(\x0b\x32<.temporal.api.history.v1.ActivityTaskCanceledEventAttributesH\x00\x12`\n\x1ftimer_canceled_event_attributes\x18\x18 \x01(\x0b\x32\x35.temporal.api.history.v1.TimerCanceledEventAttributesH\x00\x12\x62\n marker_recorded_event_attributes\x18\x19 \x01(\x0b\x32\x36.temporal.api.history.v1.MarkerRecordedEventAttributesH\x00\x12y\n,workflow_execution_signaled_event_attributes\x18\x1a \x01(\x0b\x32\x41.temporal.api.history.v1.WorkflowExecutionSignaledEventAttributesH\x00\x12}\n.workflow_execution_terminated_event_attributes\x18\x1b \x01(\x0b\x32\x43.temporal.api.history.v1.WorkflowExecutionTerminatedEventAttributesH\x00\x12\x88\x01\n4workflow_execution_cancel_requested_event_attributes\x18\x1c \x01(\x0b\x32H.temporal.api.history.v1.WorkflowExecutionCancelRequestedEventAttributesH\x00\x12y\n,workflow_execution_canceled_event_attributes\x18\x1d \x01(\x0b\x32\x41.temporal.api.history.v1.WorkflowExecutionCanceledEventAttributesH\x00\x12\xa8\x01\nErequest_cancel_external_workflow_execution_initiated_event_attributes\x18\x1e \x01(\x0b\x32W.temporal.api.history.v1.RequestCancelExternalWorkflowExecutionInitiatedEventAttributesH\x00\x12\xa2\x01\nBrequest_cancel_external_workflow_execution_failed_event_attributes\x18\x1f \x01(\x0b\x32T.temporal.api.history.v1.RequestCancelExternalWorkflowExecutionFailedEventAttributesH\x00\x12\x99\x01\n=external_workflow_execution_cancel_requested_event_attributes\x18 \x01(\x0b\x32P.temporal.api.history.v1.ExternalWorkflowExecutionCancelRequestedEventAttributesH\x00\x12\x87\x01\n4workflow_execution_continued_as_new_event_attributes\x18! \x01(\x0b\x32G.temporal.api.history.v1.WorkflowExecutionContinuedAsNewEventAttributesH\x00\x12\x91\x01\n9start_child_workflow_execution_initiated_event_attributes\x18" \x01(\x0b\x32L.temporal.api.history.v1.StartChildWorkflowExecutionInitiatedEventAttributesH\x00\x12\x8b\x01\n6start_child_workflow_execution_failed_event_attributes\x18# \x01(\x0b\x32I.temporal.api.history.v1.StartChildWorkflowExecutionFailedEventAttributesH\x00\x12\x82\x01\n1child_workflow_execution_started_event_attributes\x18$ \x01(\x0b\x32\x45.temporal.api.history.v1.ChildWorkflowExecutionStartedEventAttributesH\x00\x12\x86\x01\n3child_workflow_execution_completed_event_attributes\x18% \x01(\x0b\x32G.temporal.api.history.v1.ChildWorkflowExecutionCompletedEventAttributesH\x00\x12\x80\x01\n0child_workflow_execution_failed_event_attributes\x18& \x01(\x0b\x32\x44.temporal.api.history.v1.ChildWorkflowExecutionFailedEventAttributesH\x00\x12\x84\x01\n2child_workflow_execution_canceled_event_attributes\x18\' \x01(\x0b\x32\x46.temporal.api.history.v1.ChildWorkflowExecutionCanceledEventAttributesH\x00\x12\x85\x01\n3child_workflow_execution_timed_out_event_attributes\x18( \x01(\x0b\x32\x46.temporal.api.history.v1.ChildWorkflowExecutionTimedOutEventAttributesH\x00\x12\x88\x01\n4child_workflow_execution_terminated_event_attributes\x18) \x01(\x0b\x32H.temporal.api.history.v1.ChildWorkflowExecutionTerminatedEventAttributesH\x00\x12\x99\x01\n=signal_external_workflow_execution_initiated_event_attributes\x18* \x01(\x0b\x32P.temporal.api.history.v1.SignalExternalWorkflowExecutionInitiatedEventAttributesH\x00\x12\x93\x01\n:signal_external_workflow_execution_failed_event_attributes\x18+ \x01(\x0b\x32M.temporal.api.history.v1.SignalExternalWorkflowExecutionFailedEventAttributesH\x00\x12\x8a\x01\n5external_workflow_execution_signaled_event_attributes\x18, \x01(\x0b\x32I.temporal.api.history.v1.ExternalWorkflowExecutionSignaledEventAttributesH\x00\x12\x84\x01\n2upsert_workflow_search_attributes_event_attributes\x18- \x01(\x0b\x32\x46.temporal.api.history.v1.UpsertWorkflowSearchAttributesEventAttributesH\x00\x12\x86\x01\n3workflow_execution_update_accepted_event_attributes\x18. \x01(\x0b\x32G.temporal.api.history.v1.WorkflowExecutionUpdateAcceptedEventAttributesH\x00\x12\x86\x01\n3workflow_execution_update_rejected_event_attributes\x18/ \x01(\x0b\x32G.temporal.api.history.v1.WorkflowExecutionUpdateRejectedEventAttributesH\x00\x12\x88\x01\n4workflow_execution_update_completed_event_attributes\x18\x30 \x01(\x0b\x32H.temporal.api.history.v1.WorkflowExecutionUpdateCompletedEventAttributesH\x00\x12\x90\x01\n8workflow_properties_modified_externally_event_attributes\x18\x31 \x01(\x0b\x32L.temporal.api.history.v1.WorkflowPropertiesModifiedExternallyEventAttributesH\x00\x12\x90\x01\n8activity_properties_modified_externally_event_attributes\x18\x32 \x01(\x0b\x32L.temporal.api.history.v1.ActivityPropertiesModifiedExternallyEventAttributesH\x00\x12{\n-workflow_properties_modified_event_attributes\x18\x33 \x01(\x0b\x32\x42.temporal.api.history.v1.WorkflowPropertiesModifiedEventAttributesH\x00\x12\x86\x01\n3workflow_execution_update_admitted_event_attributes\x18\x34 \x01(\x0b\x32G.temporal.api.history.v1.WorkflowExecutionUpdateAdmittedEventAttributesH\x00\x12u\n*nexus_operation_scheduled_event_attributes\x18\x35 \x01(\x0b\x32?.temporal.api.history.v1.NexusOperationScheduledEventAttributesH\x00\x12q\n(nexus_operation_started_event_attributes\x18\x36 \x01(\x0b\x32=.temporal.api.history.v1.NexusOperationStartedEventAttributesH\x00\x12u\n*nexus_operation_completed_event_attributes\x18\x37 \x01(\x0b\x32?.temporal.api.history.v1.NexusOperationCompletedEventAttributesH\x00\x12o\n\'nexus_operation_failed_event_attributes\x18\x38 \x01(\x0b\x32<.temporal.api.history.v1.NexusOperationFailedEventAttributesH\x00\x12s\n)nexus_operation_canceled_event_attributes\x18\x39 \x01(\x0b\x32>.temporal.api.history.v1.NexusOperationCanceledEventAttributesH\x00\x12t\n*nexus_operation_timed_out_event_attributes\x18: \x01(\x0b\x32>.temporal.api.history.v1.NexusOperationTimedOutEventAttributesH\x00\x12\x82\x01\n1nexus_operation_cancel_requested_event_attributes\x18; \x01(\x0b\x32\x45.temporal.api.history.v1.NexusOperationCancelRequestedEventAttributesH\x00\x12\x86\x01\n3workflow_execution_options_updated_event_attributes\x18< \x01(\x0b\x32G.temporal.api.history.v1.WorkflowExecutionOptionsUpdatedEventAttributesH\x00\x12\x91\x01\n9nexus_operation_cancel_request_completed_event_attributes\x18= \x01(\x0b\x32L.temporal.api.history.v1.NexusOperationCancelRequestCompletedEventAttributesH\x00\x12\x8b\x01\n6nexus_operation_cancel_request_failed_event_attributes\x18> \x01(\x0b\x32I.temporal.api.history.v1.NexusOperationCancelRequestFailedEventAttributesH\x00\x12u\n*workflow_execution_paused_event_attributes\x18? \x01(\x0b\x32?.temporal.api.history.v1.WorkflowExecutionPausedEventAttributesH\x00\x12y\n,workflow_execution_unpaused_event_attributes\x18@ \x01(\x0b\x32\x41.temporal.api.history.v1.WorkflowExecutionUnpausedEventAttributesH\x00\x42\x0c\n\nattributes"@\n\x07History\x12\x35\n\x06\x65vents\x18\x01 \x03(\x0b\x32%.temporal.api.history.v1.HistoryEventB\x8e\x01\n\x1aio.temporal.api.history.v1B\x0cMessageProtoP\x01Z%go.temporal.io/api/history/v1;history\xaa\x02\x19Temporalio.Api.History.V1\xea\x02\x1cTemporalio::Api::History::V1b\x06proto3' + b'\n%temporal/api/history/v1/message.proto\x12\x17temporal.api.history.v1\x1a\x1egoogle/protobuf/duration.proto\x1a\x1fgoogle/protobuf/timestamp.proto\x1a&temporal/api/enums/v1/event_type.proto\x1a(temporal/api/enums/v1/failed_cause.proto\x1a"temporal/api/enums/v1/update.proto\x1a$temporal/api/enums/v1/workflow.proto\x1a$temporal/api/common/v1/message.proto\x1a(temporal/api/deployment/v1/message.proto\x1a%temporal/api/failure/v1/message.proto\x1a\'temporal/api/taskqueue/v1/message.proto\x1a$temporal/api/update/v1/message.proto\x1a&temporal/api/workflow/v1/message.proto\x1a\x30temporal/api/sdk/v1/task_complete_metadata.proto\x1a\'temporal/api/sdk/v1/user_metadata.proto"\x9a\x12\n\'WorkflowExecutionStartedEventAttributes\x12;\n\rworkflow_type\x18\x01 \x01(\x0b\x32$.temporal.api.common.v1.WorkflowType\x12!\n\x19parent_workflow_namespace\x18\x02 \x01(\t\x12$\n\x1cparent_workflow_namespace_id\x18\x1b \x01(\t\x12L\n\x19parent_workflow_execution\x18\x03 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12!\n\x19parent_initiated_event_id\x18\x04 \x01(\x03\x12\x38\n\ntask_queue\x18\x05 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12/\n\x05input\x18\x06 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12=\n\x1aworkflow_execution_timeout\x18\x07 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x37\n\x14workflow_run_timeout\x18\x08 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x38\n\x15workflow_task_timeout\x18\t \x01(\x0b\x32\x19.google.protobuf.Duration\x12"\n\x1a\x63ontinued_execution_run_id\x18\n \x01(\t\x12@\n\tinitiator\x18\x0b \x01(\x0e\x32-.temporal.api.enums.v1.ContinueAsNewInitiator\x12;\n\x11\x63ontinued_failure\x18\x0c \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12@\n\x16last_completion_result\x18\r \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12!\n\x19original_execution_run_id\x18\x0e \x01(\t\x12\x10\n\x08identity\x18\x0f \x01(\t\x12\x1e\n\x16\x66irst_execution_run_id\x18\x10 \x01(\t\x12\x39\n\x0cretry_policy\x18\x11 \x01(\x0b\x32#.temporal.api.common.v1.RetryPolicy\x12\x0f\n\x07\x61ttempt\x18\x12 \x01(\x05\x12\x46\n"workflow_execution_expiration_time\x18\x13 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x15\n\rcron_schedule\x18\x14 \x01(\t\x12>\n\x1b\x66irst_workflow_task_backoff\x18\x15 \x01(\x0b\x32\x19.google.protobuf.Duration\x12*\n\x04memo\x18\x16 \x01(\x0b\x32\x1c.temporal.api.common.v1.Memo\x12\x43\n\x11search_attributes\x18\x17 \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes\x12\x45\n\x16prev_auto_reset_points\x18\x18 \x01(\x0b\x32%.temporal.api.workflow.v1.ResetPoints\x12.\n\x06header\x18\x19 \x01(\x0b\x32\x1e.temporal.api.common.v1.Header\x12&\n\x1eparent_initiated_event_version\x18\x1a \x01(\x03\x12\x13\n\x0bworkflow_id\x18\x1c \x01(\t\x12L\n\x14source_version_stamp\x18\x1d \x01(\x0b\x32*.temporal.api.common.v1.WorkerVersionStampB\x02\x18\x01\x12>\n\x14\x63ompletion_callbacks\x18\x1e \x03(\x0b\x32 .temporal.api.common.v1.Callback\x12J\n\x17root_workflow_execution\x18\x1f \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x1e\n\x12inherited_build_id\x18 \x01(\tB\x02\x18\x01\x12I\n\x13versioning_override\x18! \x01(\x0b\x32,.temporal.api.workflow.v1.VersioningOverride\x12\x33\n\'parent_pinned_worker_deployment_version\x18" \x01(\tB\x02\x18\x01\x12\x32\n\x08priority\x18# \x01(\x0b\x32 .temporal.api.common.v1.Priority\x12U\n\x18inherited_pinned_version\x18% \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersion\x12Y\n\x1binherited_auto_upgrade_info\x18\' \x01(\x0b\x32\x34.temporal.api.deployment.v1.InheritedAutoUpgradeInfo\x12 \n\x18\x65\x61ger_execution_accepted\x18& \x01(\x08\x12^\n\x1f\x64\x65\x63lined_target_version_upgrade\x18( \x01(\x0b\x32\x35.temporal.api.history.v1.DeclinedTargetVersionUpgrade\x12J\n\x14time_skipping_config\x18) \x01(\x0b\x32,.temporal.api.workflow.v1.TimeSkippingConfig\x12;\n\x18initial_skipped_duration\x18* \x01(\x0b\x32\x19.google.protobuf.DurationJ\x04\x08$\x10%R parent_pinned_deployment_version"\x88\x01\n\x1c\x44\x65\x63linedTargetVersionUpgrade\x12O\n\x12\x64\x65ployment_version\x18\x01 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersion\x12\x17\n\x0frevision_number\x18\x02 \x01(\x03"\xa5\x01\n)WorkflowExecutionCompletedEventAttributes\x12\x30\n\x06result\x18\x01 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12(\n workflow_task_completed_event_id\x18\x02 \x01(\x03\x12\x1c\n\x14new_execution_run_id\x18\x03 \x01(\t"\xdb\x01\n&WorkflowExecutionFailedEventAttributes\x12\x31\n\x07\x66\x61ilure\x18\x01 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12\x36\n\x0bretry_state\x18\x02 \x01(\x0e\x32!.temporal.api.enums.v1.RetryState\x12(\n workflow_task_completed_event_id\x18\x03 \x01(\x03\x12\x1c\n\x14new_execution_run_id\x18\x04 \x01(\t"\x80\x01\n(WorkflowExecutionTimedOutEventAttributes\x12\x36\n\x0bretry_state\x18\x01 \x01(\x0e\x32!.temporal.api.enums.v1.RetryState\x12\x1c\n\x14new_execution_run_id\x18\x02 \x01(\t"\xa5\x07\n.WorkflowExecutionContinuedAsNewEventAttributes\x12\x1c\n\x14new_execution_run_id\x18\x01 \x01(\t\x12;\n\rworkflow_type\x18\x02 \x01(\x0b\x32$.temporal.api.common.v1.WorkflowType\x12\x38\n\ntask_queue\x18\x03 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12/\n\x05input\x18\x04 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x37\n\x14workflow_run_timeout\x18\x05 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x38\n\x15workflow_task_timeout\x18\x06 \x01(\x0b\x32\x19.google.protobuf.Duration\x12(\n workflow_task_completed_event_id\x18\x07 \x01(\x03\x12\x39\n\x16\x62\x61\x63koff_start_interval\x18\x08 \x01(\x0b\x32\x19.google.protobuf.Duration\x12@\n\tinitiator\x18\t \x01(\x0e\x32-.temporal.api.enums.v1.ContinueAsNewInitiator\x12\x35\n\x07\x66\x61ilure\x18\n \x01(\x0b\x32 .temporal.api.failure.v1.FailureB\x02\x18\x01\x12@\n\x16last_completion_result\x18\x0b \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12.\n\x06header\x18\x0c \x01(\x0b\x32\x1e.temporal.api.common.v1.Header\x12*\n\x04memo\x18\r \x01(\x0b\x32\x1c.temporal.api.common.v1.Memo\x12\x43\n\x11search_attributes\x18\x0e \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes\x12\x1c\n\x10inherit_build_id\x18\x0f \x01(\x08\x42\x02\x18\x01\x12[\n\x1binitial_versioning_behavior\x18\x10 \x01(\x0e\x32\x36.temporal.api.enums.v1.ContinueAsNewVersioningBehavior"\xac\x01\n$WorkflowTaskScheduledEventAttributes\x12\x38\n\ntask_queue\x18\x01 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12\x39\n\x16start_to_close_timeout\x18\x02 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x0f\n\x07\x61ttempt\x18\x03 \x01(\x05"\xa0\x03\n"WorkflowTaskStartedEventAttributes\x12\x1a\n\x12scheduled_event_id\x18\x01 \x01(\x03\x12\x10\n\x08identity\x18\x02 \x01(\t\x12\x12\n\nrequest_id\x18\x03 \x01(\t\x12\x1f\n\x17suggest_continue_as_new\x18\x04 \x01(\x08\x12Z\n\x1fsuggest_continue_as_new_reasons\x18\x08 \x03(\x0e\x32\x31.temporal.api.enums.v1.SuggestContinueAsNewReason\x12\x30\n(target_worker_deployment_version_changed\x18\t \x01(\x08\x12\x1a\n\x12history_size_bytes\x18\x05 \x01(\x03\x12\x46\n\x0eworker_version\x18\x06 \x01(\x0b\x32*.temporal.api.common.v1.WorkerVersionStampB\x02\x18\x01\x12%\n\x19\x62uild_id_redirect_counter\x18\x07 \x01(\x03\x42\x02\x18\x01"\x82\x05\n$WorkflowTaskCompletedEventAttributes\x12\x1a\n\x12scheduled_event_id\x18\x01 \x01(\x03\x12\x18\n\x10started_event_id\x18\x02 \x01(\x03\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x1b\n\x0f\x62inary_checksum\x18\x04 \x01(\tB\x02\x18\x01\x12\x46\n\x0eworker_version\x18\x05 \x01(\x0b\x32*.temporal.api.common.v1.WorkerVersionStampB\x02\x18\x01\x12H\n\x0csdk_metadata\x18\x06 \x01(\x0b\x32\x32.temporal.api.sdk.v1.WorkflowTaskCompletedMetadata\x12\x43\n\x11metering_metadata\x18\r \x01(\x0b\x32(.temporal.api.common.v1.MeteringMetadata\x12>\n\ndeployment\x18\x07 \x01(\x0b\x32&.temporal.api.deployment.v1.DeploymentB\x02\x18\x01\x12\x46\n\x13versioning_behavior\x18\x08 \x01(\x0e\x32).temporal.api.enums.v1.VersioningBehavior\x12%\n\x19worker_deployment_version\x18\t \x01(\tB\x02\x18\x01\x12\x1e\n\x16worker_deployment_name\x18\n \x01(\t\x12O\n\x12\x64\x65ployment_version\x18\x0b \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersion"\x95\x01\n#WorkflowTaskTimedOutEventAttributes\x12\x1a\n\x12scheduled_event_id\x18\x01 \x01(\x03\x12\x18\n\x10started_event_id\x18\x02 \x01(\x03\x12\x38\n\x0ctimeout_type\x18\x03 \x01(\x0e\x32".temporal.api.enums.v1.TimeoutType"\x87\x03\n!WorkflowTaskFailedEventAttributes\x12\x1a\n\x12scheduled_event_id\x18\x01 \x01(\x03\x12\x18\n\x10started_event_id\x18\x02 \x01(\x03\x12=\n\x05\x63\x61use\x18\x03 \x01(\x0e\x32..temporal.api.enums.v1.WorkflowTaskFailedCause\x12\x31\n\x07\x66\x61ilure\x18\x04 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12\x10\n\x08identity\x18\x05 \x01(\t\x12\x13\n\x0b\x62\x61se_run_id\x18\x06 \x01(\t\x12\x12\n\nnew_run_id\x18\x07 \x01(\t\x12\x1a\n\x12\x66ork_event_version\x18\x08 \x01(\x03\x12\x1b\n\x0f\x62inary_checksum\x18\t \x01(\tB\x02\x18\x01\x12\x46\n\x0eworker_version\x18\n \x01(\x0b\x32*.temporal.api.common.v1.WorkerVersionStampB\x02\x18\x01"\xc2\x05\n$ActivityTaskScheduledEventAttributes\x12\x13\n\x0b\x61\x63tivity_id\x18\x01 \x01(\t\x12;\n\ractivity_type\x18\x02 \x01(\x0b\x32$.temporal.api.common.v1.ActivityType\x12\x38\n\ntask_queue\x18\x04 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12.\n\x06header\x18\x05 \x01(\x0b\x32\x1e.temporal.api.common.v1.Header\x12/\n\x05input\x18\x06 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12<\n\x19schedule_to_close_timeout\x18\x07 \x01(\x0b\x32\x19.google.protobuf.Duration\x12<\n\x19schedule_to_start_timeout\x18\x08 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x39\n\x16start_to_close_timeout\x18\t \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x34\n\x11heartbeat_timeout\x18\n \x01(\x0b\x32\x19.google.protobuf.Duration\x12(\n workflow_task_completed_event_id\x18\x0b \x01(\x03\x12\x39\n\x0cretry_policy\x18\x0c \x01(\x0b\x32#.temporal.api.common.v1.RetryPolicy\x12!\n\x15use_workflow_build_id\x18\r \x01(\x08\x42\x02\x18\x01\x12\x32\n\x08priority\x18\x0e \x01(\x0b\x32 .temporal.api.common.v1.PriorityJ\x04\x08\x03\x10\x04"\x9e\x02\n"ActivityTaskStartedEventAttributes\x12\x1a\n\x12scheduled_event_id\x18\x01 \x01(\x03\x12\x10\n\x08identity\x18\x02 \x01(\t\x12\x12\n\nrequest_id\x18\x03 \x01(\t\x12\x0f\n\x07\x61ttempt\x18\x04 \x01(\x05\x12\x36\n\x0clast_failure\x18\x05 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12\x46\n\x0eworker_version\x18\x06 \x01(\x0b\x32*.temporal.api.common.v1.WorkerVersionStampB\x02\x18\x01\x12%\n\x19\x62uild_id_redirect_counter\x18\x07 \x01(\x03\x42\x02\x18\x01"\xe8\x01\n$ActivityTaskCompletedEventAttributes\x12\x30\n\x06result\x18\x01 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x1a\n\x12scheduled_event_id\x18\x02 \x01(\x03\x12\x18\n\x10started_event_id\x18\x03 \x01(\x03\x12\x10\n\x08identity\x18\x04 \x01(\t\x12\x46\n\x0eworker_version\x18\x05 \x01(\x0b\x32*.temporal.api.common.v1.WorkerVersionStampB\x02\x18\x01"\x9e\x02\n!ActivityTaskFailedEventAttributes\x12\x31\n\x07\x66\x61ilure\x18\x01 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12\x1a\n\x12scheduled_event_id\x18\x02 \x01(\x03\x12\x18\n\x10started_event_id\x18\x03 \x01(\x03\x12\x10\n\x08identity\x18\x04 \x01(\t\x12\x36\n\x0bretry_state\x18\x05 \x01(\x0e\x32!.temporal.api.enums.v1.RetryState\x12\x46\n\x0eworker_version\x18\x06 \x01(\x0b\x32*.temporal.api.common.v1.WorkerVersionStampB\x02\x18\x01"\xc6\x01\n#ActivityTaskTimedOutEventAttributes\x12\x31\n\x07\x66\x61ilure\x18\x01 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12\x1a\n\x12scheduled_event_id\x18\x02 \x01(\x03\x12\x18\n\x10started_event_id\x18\x03 \x01(\x03\x12\x36\n\x0bretry_state\x18\x04 \x01(\x0e\x32!.temporal.api.enums.v1.RetryState"r\n*ActivityTaskCancelRequestedEventAttributes\x12\x1a\n\x12scheduled_event_id\x18\x01 \x01(\x03\x12(\n workflow_task_completed_event_id\x18\x02 \x01(\x03"\x92\x02\n#ActivityTaskCanceledEventAttributes\x12\x31\n\x07\x64\x65tails\x18\x01 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12(\n latest_cancel_requested_event_id\x18\x02 \x01(\x03\x12\x1a\n\x12scheduled_event_id\x18\x03 \x01(\x03\x12\x18\n\x10started_event_id\x18\x04 \x01(\x03\x12\x10\n\x08identity\x18\x05 \x01(\t\x12\x46\n\x0eworker_version\x18\x06 \x01(\x0b\x32*.temporal.api.common.v1.WorkerVersionStampB\x02\x18\x01"\x93\x01\n\x1bTimerStartedEventAttributes\x12\x10\n\x08timer_id\x18\x01 \x01(\t\x12\x38\n\x15start_to_fire_timeout\x18\x02 \x01(\x0b\x32\x19.google.protobuf.Duration\x12(\n workflow_task_completed_event_id\x18\x03 \x01(\x03"G\n\x19TimerFiredEventAttributes\x12\x10\n\x08timer_id\x18\x01 \x01(\t\x12\x18\n\x10started_event_id\x18\x02 \x01(\x03"\x86\x01\n\x1cTimerCanceledEventAttributes\x12\x10\n\x08timer_id\x18\x01 \x01(\t\x12\x18\n\x10started_event_id\x18\x02 \x01(\x03\x12(\n workflow_task_completed_event_id\x18\x03 \x01(\x03\x12\x10\n\x08identity\x18\x04 \x01(\t"\xc7\x01\n/WorkflowExecutionCancelRequestedEventAttributes\x12\r\n\x05\x63\x61use\x18\x01 \x01(\t\x12#\n\x1b\x65xternal_initiated_event_id\x18\x02 \x01(\x03\x12N\n\x1b\x65xternal_workflow_execution\x18\x03 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x10\n\x08identity\x18\x04 \x01(\t"\x87\x01\n(WorkflowExecutionCanceledEventAttributes\x12(\n workflow_task_completed_event_id\x18\x01 \x01(\x03\x12\x31\n\x07\x64\x65tails\x18\x02 \x01(\x0b\x32 .temporal.api.common.v1.Payloads"\xe9\x02\n\x1dMarkerRecordedEventAttributes\x12\x13\n\x0bmarker_name\x18\x01 \x01(\t\x12T\n\x07\x64\x65tails\x18\x02 \x03(\x0b\x32\x43.temporal.api.history.v1.MarkerRecordedEventAttributes.DetailsEntry\x12(\n workflow_task_completed_event_id\x18\x03 \x01(\x03\x12.\n\x06header\x18\x04 \x01(\x0b\x32\x1e.temporal.api.common.v1.Header\x12\x31\n\x07\x66\x61ilure\x18\x05 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x1aP\n\x0c\x44\x65tailsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12/\n\x05value\x18\x02 \x01(\x0b\x32 .temporal.api.common.v1.Payloads:\x02\x38\x01"\xbf\x02\n(WorkflowExecutionSignaledEventAttributes\x12\x13\n\x0bsignal_name\x18\x01 \x01(\t\x12/\n\x05input\x18\x02 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x10\n\x08identity\x18\x03 \x01(\t\x12.\n\x06header\x18\x04 \x01(\x0b\x32\x1e.temporal.api.common.v1.Header\x12\'\n\x1bskip_generate_workflow_task\x18\x05 \x01(\x08\x42\x02\x18\x01\x12N\n\x1b\x65xternal_workflow_execution\x18\x06 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x12\n\nrequest_id\x18\x07 \x01(\t"\x81\x01\n*WorkflowExecutionTerminatedEventAttributes\x12\x0e\n\x06reason\x18\x01 \x01(\t\x12\x31\n\x07\x64\x65tails\x18\x02 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x10\n\x08identity\x18\x03 \x01(\t"\x9c\x02\n>RequestCancelExternalWorkflowExecutionInitiatedEventAttributes\x12(\n workflow_task_completed_event_id\x18\x01 \x01(\x03\x12\x11\n\tnamespace\x18\x02 \x01(\t\x12\x14\n\x0cnamespace_id\x18\x07 \x01(\t\x12\x45\n\x12workflow_execution\x18\x03 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x13\n\x07\x63ontrol\x18\x04 \x01(\tB\x02\x18\x01\x12\x1b\n\x13\x63hild_workflow_only\x18\x05 \x01(\x08\x12\x0e\n\x06reason\x18\x06 \x01(\t"\xda\x02\n;RequestCancelExternalWorkflowExecutionFailedEventAttributes\x12P\n\x05\x63\x61use\x18\x01 \x01(\x0e\x32\x41.temporal.api.enums.v1.CancelExternalWorkflowExecutionFailedCause\x12(\n workflow_task_completed_event_id\x18\x02 \x01(\x03\x12\x11\n\tnamespace\x18\x03 \x01(\t\x12\x14\n\x0cnamespace_id\x18\x07 \x01(\t\x12\x45\n\x12workflow_execution\x18\x04 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x1a\n\x12initiated_event_id\x18\x05 \x01(\x03\x12\x13\n\x07\x63ontrol\x18\x06 \x01(\tB\x02\x18\x01"\xc5\x01\n7ExternalWorkflowExecutionCancelRequestedEventAttributes\x12\x1a\n\x12initiated_event_id\x18\x01 \x01(\x03\x12\x11\n\tnamespace\x18\x02 \x01(\t\x12\x14\n\x0cnamespace_id\x18\x04 \x01(\t\x12\x45\n\x12workflow_execution\x18\x03 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution"\xfb\x02\n7SignalExternalWorkflowExecutionInitiatedEventAttributes\x12(\n workflow_task_completed_event_id\x18\x01 \x01(\x03\x12\x11\n\tnamespace\x18\x02 \x01(\t\x12\x14\n\x0cnamespace_id\x18\t \x01(\t\x12\x45\n\x12workflow_execution\x18\x03 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x13\n\x0bsignal_name\x18\x04 \x01(\t\x12/\n\x05input\x18\x05 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x13\n\x07\x63ontrol\x18\x06 \x01(\tB\x02\x18\x01\x12\x1b\n\x13\x63hild_workflow_only\x18\x07 \x01(\x08\x12.\n\x06header\x18\x08 \x01(\x0b\x32\x1e.temporal.api.common.v1.Header"\xd3\x02\n4SignalExternalWorkflowExecutionFailedEventAttributes\x12P\n\x05\x63\x61use\x18\x01 \x01(\x0e\x32\x41.temporal.api.enums.v1.SignalExternalWorkflowExecutionFailedCause\x12(\n workflow_task_completed_event_id\x18\x02 \x01(\x03\x12\x11\n\tnamespace\x18\x03 \x01(\t\x12\x14\n\x0cnamespace_id\x18\x07 \x01(\t\x12\x45\n\x12workflow_execution\x18\x04 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x1a\n\x12initiated_event_id\x18\x05 \x01(\x03\x12\x13\n\x07\x63ontrol\x18\x06 \x01(\tB\x02\x18\x01"\xd3\x01\n0ExternalWorkflowExecutionSignaledEventAttributes\x12\x1a\n\x12initiated_event_id\x18\x01 \x01(\x03\x12\x11\n\tnamespace\x18\x02 \x01(\t\x12\x14\n\x0cnamespace_id\x18\x05 \x01(\t\x12\x45\n\x12workflow_execution\x18\x03 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x13\n\x07\x63ontrol\x18\x04 \x01(\tB\x02\x18\x01"\x9e\x01\n-UpsertWorkflowSearchAttributesEventAttributes\x12(\n workflow_task_completed_event_id\x18\x01 \x01(\x03\x12\x43\n\x11search_attributes\x18\x02 \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes"\x8a\x01\n)WorkflowPropertiesModifiedEventAttributes\x12(\n workflow_task_completed_event_id\x18\x01 \x01(\x03\x12\x33\n\rupserted_memo\x18\x02 \x01(\x0b\x32\x1c.temporal.api.common.v1.Memo"\xf1\x08\n3StartChildWorkflowExecutionInitiatedEventAttributes\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x14\n\x0cnamespace_id\x18\x12 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12;\n\rworkflow_type\x18\x03 \x01(\x0b\x32$.temporal.api.common.v1.WorkflowType\x12\x38\n\ntask_queue\x18\x04 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12/\n\x05input\x18\x05 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12=\n\x1aworkflow_execution_timeout\x18\x06 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x37\n\x14workflow_run_timeout\x18\x07 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x38\n\x15workflow_task_timeout\x18\x08 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x45\n\x13parent_close_policy\x18\t \x01(\x0e\x32(.temporal.api.enums.v1.ParentClosePolicy\x12\x13\n\x07\x63ontrol\x18\n \x01(\tB\x02\x18\x01\x12(\n workflow_task_completed_event_id\x18\x0b \x01(\x03\x12N\n\x18workflow_id_reuse_policy\x18\x0c \x01(\x0e\x32,.temporal.api.enums.v1.WorkflowIdReusePolicy\x12\x39\n\x0cretry_policy\x18\r \x01(\x0b\x32#.temporal.api.common.v1.RetryPolicy\x12\x15\n\rcron_schedule\x18\x0e \x01(\t\x12.\n\x06header\x18\x0f \x01(\x0b\x32\x1e.temporal.api.common.v1.Header\x12*\n\x04memo\x18\x10 \x01(\x0b\x32\x1c.temporal.api.common.v1.Memo\x12\x43\n\x11search_attributes\x18\x11 \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes\x12\x1c\n\x10inherit_build_id\x18\x13 \x01(\x08\x42\x02\x18\x01\x12\x32\n\x08priority\x18\x14 \x01(\x0b\x32 .temporal.api.common.v1.Priority\x12J\n\x14time_skipping_config\x18\x15 \x01(\x0b\x32,.temporal.api.workflow.v1.TimeSkippingConfig\x12;\n\x18initial_skipped_duration\x18\x1e \x01(\x0b\x32\x19.google.protobuf.Duration"\xd6\x02\n0StartChildWorkflowExecutionFailedEventAttributes\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x14\n\x0cnamespace_id\x18\x08 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12;\n\rworkflow_type\x18\x03 \x01(\x0b\x32$.temporal.api.common.v1.WorkflowType\x12L\n\x05\x63\x61use\x18\x04 \x01(\x0e\x32=.temporal.api.enums.v1.StartChildWorkflowExecutionFailedCause\x12\x13\n\x07\x63ontrol\x18\x05 \x01(\tB\x02\x18\x01\x12\x1a\n\x12initiated_event_id\x18\x06 \x01(\x03\x12(\n workflow_task_completed_event_id\x18\x07 \x01(\x03"\xa7\x02\n,ChildWorkflowExecutionStartedEventAttributes\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x14\n\x0cnamespace_id\x18\x06 \x01(\t\x12\x1a\n\x12initiated_event_id\x18\x02 \x01(\x03\x12\x45\n\x12workflow_execution\x18\x03 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12;\n\rworkflow_type\x18\x04 \x01(\x0b\x32$.temporal.api.common.v1.WorkflowType\x12.\n\x06header\x18\x05 \x01(\x0b\x32\x1e.temporal.api.common.v1.Header"\xc5\x02\n.ChildWorkflowExecutionCompletedEventAttributes\x12\x30\n\x06result\x18\x01 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x11\n\tnamespace\x18\x02 \x01(\t\x12\x14\n\x0cnamespace_id\x18\x07 \x01(\t\x12\x45\n\x12workflow_execution\x18\x03 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12;\n\rworkflow_type\x18\x04 \x01(\x0b\x32$.temporal.api.common.v1.WorkflowType\x12\x1a\n\x12initiated_event_id\x18\x05 \x01(\x03\x12\x18\n\x10started_event_id\x18\x06 \x01(\x03"\xfb\x02\n+ChildWorkflowExecutionFailedEventAttributes\x12\x31\n\x07\x66\x61ilure\x18\x01 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12\x11\n\tnamespace\x18\x02 \x01(\t\x12\x14\n\x0cnamespace_id\x18\x08 \x01(\t\x12\x45\n\x12workflow_execution\x18\x03 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12;\n\rworkflow_type\x18\x04 \x01(\x0b\x32$.temporal.api.common.v1.WorkflowType\x12\x1a\n\x12initiated_event_id\x18\x05 \x01(\x03\x12\x18\n\x10started_event_id\x18\x06 \x01(\x03\x12\x36\n\x0bretry_state\x18\x07 \x01(\x0e\x32!.temporal.api.enums.v1.RetryState"\xc5\x02\n-ChildWorkflowExecutionCanceledEventAttributes\x12\x31\n\x07\x64\x65tails\x18\x01 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x11\n\tnamespace\x18\x02 \x01(\t\x12\x14\n\x0cnamespace_id\x18\x07 \x01(\t\x12\x45\n\x12workflow_execution\x18\x03 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12;\n\rworkflow_type\x18\x04 \x01(\x0b\x32$.temporal.api.common.v1.WorkflowType\x12\x1a\n\x12initiated_event_id\x18\x05 \x01(\x03\x12\x18\n\x10started_event_id\x18\x06 \x01(\x03"\xca\x02\n-ChildWorkflowExecutionTimedOutEventAttributes\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x14\n\x0cnamespace_id\x18\x07 \x01(\t\x12\x45\n\x12workflow_execution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12;\n\rworkflow_type\x18\x03 \x01(\x0b\x32$.temporal.api.common.v1.WorkflowType\x12\x1a\n\x12initiated_event_id\x18\x04 \x01(\x03\x12\x18\n\x10started_event_id\x18\x05 \x01(\x03\x12\x36\n\x0bretry_state\x18\x06 \x01(\x0e\x32!.temporal.api.enums.v1.RetryState"\x94\x02\n/ChildWorkflowExecutionTerminatedEventAttributes\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x14\n\x0cnamespace_id\x18\x06 \x01(\t\x12\x45\n\x12workflow_execution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12;\n\rworkflow_type\x18\x03 \x01(\x0b\x32$.temporal.api.common.v1.WorkflowType\x12\x1a\n\x12initiated_event_id\x18\x04 \x01(\x03\x12\x18\n\x10started_event_id\x18\x05 \x01(\x03"\x96\x03\n.WorkflowExecutionOptionsUpdatedEventAttributes\x12I\n\x13versioning_override\x18\x01 \x01(\x0b\x32,.temporal.api.workflow.v1.VersioningOverride\x12!\n\x19unset_versioning_override\x18\x02 \x01(\x08\x12\x1b\n\x13\x61ttached_request_id\x18\x03 \x01(\t\x12G\n\x1d\x61ttached_completion_callbacks\x18\x04 \x03(\x0b\x32 .temporal.api.common.v1.Callback\x12\x10\n\x08identity\x18\x05 \x01(\t\x12\x32\n\x08priority\x18\x06 \x01(\x0b\x32 .temporal.api.common.v1.Priority\x12J\n\x14time_skipping_config\x18\x07 \x01(\x0b\x32,.temporal.api.workflow.v1.TimeSkippingConfig"\xc0\x02\n3WorkflowPropertiesModifiedExternallyEventAttributes\x12\x16\n\x0enew_task_queue\x18\x01 \x01(\t\x12<\n\x19new_workflow_task_timeout\x18\x02 \x01(\x0b\x32\x19.google.protobuf.Duration\x12;\n\x18new_workflow_run_timeout\x18\x03 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x41\n\x1enew_workflow_execution_timeout\x18\x04 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x33\n\rupserted_memo\x18\x05 \x01(\x0b\x32\x1c.temporal.api.common.v1.Memo"\x90\x01\n3ActivityPropertiesModifiedExternallyEventAttributes\x12\x1a\n\x12scheduled_event_id\x18\x01 \x01(\x03\x12=\n\x10new_retry_policy\x18\x02 \x01(\x0b\x32#.temporal.api.common.v1.RetryPolicy"\xdc\x01\n.WorkflowExecutionUpdateAcceptedEventAttributes\x12\x1c\n\x14protocol_instance_id\x18\x01 \x01(\t\x12#\n\x1b\x61\x63\x63\x65pted_request_message_id\x18\x02 \x01(\t\x12,\n$accepted_request_sequencing_event_id\x18\x03 \x01(\x03\x12\x39\n\x10\x61\x63\x63\x65pted_request\x18\x04 \x01(\x0b\x32\x1f.temporal.api.update.v1.Request"\xaa\x01\n/WorkflowExecutionUpdateCompletedEventAttributes\x12*\n\x04meta\x18\x01 \x01(\x0b\x32\x1c.temporal.api.update.v1.Meta\x12\x19\n\x11\x61\x63\x63\x65pted_event_id\x18\x03 \x01(\x03\x12\x30\n\x07outcome\x18\x02 \x01(\x0b\x32\x1f.temporal.api.update.v1.Outcome"\x8f\x02\n.WorkflowExecutionUpdateRejectedEventAttributes\x12\x1c\n\x14protocol_instance_id\x18\x01 \x01(\t\x12#\n\x1brejected_request_message_id\x18\x02 \x01(\t\x12,\n$rejected_request_sequencing_event_id\x18\x03 \x01(\x03\x12\x39\n\x10rejected_request\x18\x04 \x01(\x0b\x32\x1f.temporal.api.update.v1.Request\x12\x31\n\x07\x66\x61ilure\x18\x05 \x01(\x0b\x32 .temporal.api.failure.v1.Failure"\xa4\x01\n.WorkflowExecutionUpdateAdmittedEventAttributes\x12\x30\n\x07request\x18\x01 \x01(\x0b\x32\x1f.temporal.api.update.v1.Request\x12@\n\x06origin\x18\x02 \x01(\x0e\x32\x30.temporal.api.enums.v1.UpdateAdmittedEventOrigin"^\n&WorkflowExecutionPausedEventAttributes\x12\x10\n\x08identity\x18\x01 \x01(\t\x12\x0e\n\x06reason\x18\x02 \x01(\t\x12\x12\n\nrequest_id\x18\x03 \x01(\t"`\n(WorkflowExecutionUnpausedEventAttributes\x12\x10\n\x08identity\x18\x01 \x01(\t\x12\x0e\n\x06reason\x18\x02 \x01(\t\x12\x12\n\nrequest_id\x18\x03 \x01(\t"\xbe\x01\n8WorkflowExecutionTimeSkippingTransitionedEventAttributes\x12/\n\x0btarget_time\x18\x01 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x1c\n\x14\x64isabled_after_bound\x18\x02 \x01(\x08\x12\x33\n\x0fwall_clock_time\x18\x03 \x01(\x0b\x32\x1a.google.protobuf.Timestamp"\xb4\x04\n&NexusOperationScheduledEventAttributes\x12\x10\n\x08\x65ndpoint\x18\x01 \x01(\t\x12\x0f\n\x07service\x18\x02 \x01(\t\x12\x11\n\toperation\x18\x03 \x01(\t\x12.\n\x05input\x18\x04 \x01(\x0b\x32\x1f.temporal.api.common.v1.Payload\x12<\n\x19schedule_to_close_timeout\x18\x05 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x66\n\x0cnexus_header\x18\x06 \x03(\x0b\x32P.temporal.api.history.v1.NexusOperationScheduledEventAttributes.NexusHeaderEntry\x12(\n workflow_task_completed_event_id\x18\x07 \x01(\x03\x12\x12\n\nrequest_id\x18\x08 \x01(\t\x12\x13\n\x0b\x65ndpoint_id\x18\t \x01(\t\x12<\n\x19schedule_to_start_timeout\x18\n \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x39\n\x16start_to_close_timeout\x18\x0b \x01(\x0b\x32\x19.google.protobuf.Duration\x1a\x32\n\x10NexusHeaderEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01"\x89\x01\n$NexusOperationStartedEventAttributes\x12\x1a\n\x12scheduled_event_id\x18\x01 \x01(\x03\x12\x18\n\x0coperation_id\x18\x03 \x01(\tB\x02\x18\x01\x12\x12\n\nrequest_id\x18\x04 \x01(\t\x12\x17\n\x0foperation_token\x18\x05 \x01(\t"\x89\x01\n&NexusOperationCompletedEventAttributes\x12\x1a\n\x12scheduled_event_id\x18\x01 \x01(\x03\x12/\n\x06result\x18\x02 \x01(\x0b\x32\x1f.temporal.api.common.v1.Payload\x12\x12\n\nrequest_id\x18\x03 \x01(\t"\x88\x01\n#NexusOperationFailedEventAttributes\x12\x1a\n\x12scheduled_event_id\x18\x01 \x01(\x03\x12\x31\n\x07\x66\x61ilure\x18\x02 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12\x12\n\nrequest_id\x18\x03 \x01(\t"\x8a\x01\n%NexusOperationTimedOutEventAttributes\x12\x1a\n\x12scheduled_event_id\x18\x01 \x01(\x03\x12\x31\n\x07\x66\x61ilure\x18\x02 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12\x12\n\nrequest_id\x18\x03 \x01(\t"\x8a\x01\n%NexusOperationCanceledEventAttributes\x12\x1a\n\x12scheduled_event_id\x18\x01 \x01(\x03\x12\x31\n\x07\x66\x61ilure\x18\x02 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12\x12\n\nrequest_id\x18\x03 \x01(\t"t\n,NexusOperationCancelRequestedEventAttributes\x12\x1a\n\x12scheduled_event_id\x18\x01 \x01(\x03\x12(\n workflow_task_completed_event_id\x18\x02 \x01(\x03"\x97\x01\n3NexusOperationCancelRequestCompletedEventAttributes\x12\x1a\n\x12requested_event_id\x18\x01 \x01(\x03\x12(\n workflow_task_completed_event_id\x18\x02 \x01(\x03\x12\x1a\n\x12scheduled_event_id\x18\x03 \x01(\x03"\xc7\x01\n0NexusOperationCancelRequestFailedEventAttributes\x12\x1a\n\x12requested_event_id\x18\x01 \x01(\x03\x12(\n workflow_task_completed_event_id\x18\x02 \x01(\x03\x12\x31\n\x07\x66\x61ilure\x18\x03 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12\x1a\n\x12scheduled_event_id\x18\x04 \x01(\x03"\x85?\n\x0cHistoryEvent\x12\x10\n\x08\x65vent_id\x18\x01 \x01(\x03\x12.\n\nevent_time\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x34\n\nevent_type\x18\x03 \x01(\x0e\x32 .temporal.api.enums.v1.EventType\x12\x0f\n\x07version\x18\x04 \x01(\x03\x12\x0f\n\x07task_id\x18\x05 \x01(\x03\x12\x1a\n\x11worker_may_ignore\x18\xac\x02 \x01(\x08\x12\x39\n\ruser_metadata\x18\xad\x02 \x01(\x0b\x32!.temporal.api.sdk.v1.UserMetadata\x12,\n\x05links\x18\xae\x02 \x03(\x0b\x32\x1c.temporal.api.common.v1.Link\x12\x35\n\tprincipal\x18\xaf\x02 \x01(\x0b\x32!.temporal.api.common.v1.Principal\x12w\n+workflow_execution_started_event_attributes\x18\x06 \x01(\x0b\x32@.temporal.api.history.v1.WorkflowExecutionStartedEventAttributesH\x00\x12{\n-workflow_execution_completed_event_attributes\x18\x07 \x01(\x0b\x32\x42.temporal.api.history.v1.WorkflowExecutionCompletedEventAttributesH\x00\x12u\n*workflow_execution_failed_event_attributes\x18\x08 \x01(\x0b\x32?.temporal.api.history.v1.WorkflowExecutionFailedEventAttributesH\x00\x12z\n-workflow_execution_timed_out_event_attributes\x18\t \x01(\x0b\x32\x41.temporal.api.history.v1.WorkflowExecutionTimedOutEventAttributesH\x00\x12q\n(workflow_task_scheduled_event_attributes\x18\n \x01(\x0b\x32=.temporal.api.history.v1.WorkflowTaskScheduledEventAttributesH\x00\x12m\n&workflow_task_started_event_attributes\x18\x0b \x01(\x0b\x32;.temporal.api.history.v1.WorkflowTaskStartedEventAttributesH\x00\x12q\n(workflow_task_completed_event_attributes\x18\x0c \x01(\x0b\x32=.temporal.api.history.v1.WorkflowTaskCompletedEventAttributesH\x00\x12p\n(workflow_task_timed_out_event_attributes\x18\r \x01(\x0b\x32<.temporal.api.history.v1.WorkflowTaskTimedOutEventAttributesH\x00\x12k\n%workflow_task_failed_event_attributes\x18\x0e \x01(\x0b\x32:.temporal.api.history.v1.WorkflowTaskFailedEventAttributesH\x00\x12q\n(activity_task_scheduled_event_attributes\x18\x0f \x01(\x0b\x32=.temporal.api.history.v1.ActivityTaskScheduledEventAttributesH\x00\x12m\n&activity_task_started_event_attributes\x18\x10 \x01(\x0b\x32;.temporal.api.history.v1.ActivityTaskStartedEventAttributesH\x00\x12q\n(activity_task_completed_event_attributes\x18\x11 \x01(\x0b\x32=.temporal.api.history.v1.ActivityTaskCompletedEventAttributesH\x00\x12k\n%activity_task_failed_event_attributes\x18\x12 \x01(\x0b\x32:.temporal.api.history.v1.ActivityTaskFailedEventAttributesH\x00\x12p\n(activity_task_timed_out_event_attributes\x18\x13 \x01(\x0b\x32<.temporal.api.history.v1.ActivityTaskTimedOutEventAttributesH\x00\x12^\n\x1etimer_started_event_attributes\x18\x14 \x01(\x0b\x32\x34.temporal.api.history.v1.TimerStartedEventAttributesH\x00\x12Z\n\x1ctimer_fired_event_attributes\x18\x15 \x01(\x0b\x32\x32.temporal.api.history.v1.TimerFiredEventAttributesH\x00\x12~\n/activity_task_cancel_requested_event_attributes\x18\x16 \x01(\x0b\x32\x43.temporal.api.history.v1.ActivityTaskCancelRequestedEventAttributesH\x00\x12o\n\'activity_task_canceled_event_attributes\x18\x17 \x01(\x0b\x32<.temporal.api.history.v1.ActivityTaskCanceledEventAttributesH\x00\x12`\n\x1ftimer_canceled_event_attributes\x18\x18 \x01(\x0b\x32\x35.temporal.api.history.v1.TimerCanceledEventAttributesH\x00\x12\x62\n marker_recorded_event_attributes\x18\x19 \x01(\x0b\x32\x36.temporal.api.history.v1.MarkerRecordedEventAttributesH\x00\x12y\n,workflow_execution_signaled_event_attributes\x18\x1a \x01(\x0b\x32\x41.temporal.api.history.v1.WorkflowExecutionSignaledEventAttributesH\x00\x12}\n.workflow_execution_terminated_event_attributes\x18\x1b \x01(\x0b\x32\x43.temporal.api.history.v1.WorkflowExecutionTerminatedEventAttributesH\x00\x12\x88\x01\n4workflow_execution_cancel_requested_event_attributes\x18\x1c \x01(\x0b\x32H.temporal.api.history.v1.WorkflowExecutionCancelRequestedEventAttributesH\x00\x12y\n,workflow_execution_canceled_event_attributes\x18\x1d \x01(\x0b\x32\x41.temporal.api.history.v1.WorkflowExecutionCanceledEventAttributesH\x00\x12\xa8\x01\nErequest_cancel_external_workflow_execution_initiated_event_attributes\x18\x1e \x01(\x0b\x32W.temporal.api.history.v1.RequestCancelExternalWorkflowExecutionInitiatedEventAttributesH\x00\x12\xa2\x01\nBrequest_cancel_external_workflow_execution_failed_event_attributes\x18\x1f \x01(\x0b\x32T.temporal.api.history.v1.RequestCancelExternalWorkflowExecutionFailedEventAttributesH\x00\x12\x99\x01\n=external_workflow_execution_cancel_requested_event_attributes\x18 \x01(\x0b\x32P.temporal.api.history.v1.ExternalWorkflowExecutionCancelRequestedEventAttributesH\x00\x12\x87\x01\n4workflow_execution_continued_as_new_event_attributes\x18! \x01(\x0b\x32G.temporal.api.history.v1.WorkflowExecutionContinuedAsNewEventAttributesH\x00\x12\x91\x01\n9start_child_workflow_execution_initiated_event_attributes\x18" \x01(\x0b\x32L.temporal.api.history.v1.StartChildWorkflowExecutionInitiatedEventAttributesH\x00\x12\x8b\x01\n6start_child_workflow_execution_failed_event_attributes\x18# \x01(\x0b\x32I.temporal.api.history.v1.StartChildWorkflowExecutionFailedEventAttributesH\x00\x12\x82\x01\n1child_workflow_execution_started_event_attributes\x18$ \x01(\x0b\x32\x45.temporal.api.history.v1.ChildWorkflowExecutionStartedEventAttributesH\x00\x12\x86\x01\n3child_workflow_execution_completed_event_attributes\x18% \x01(\x0b\x32G.temporal.api.history.v1.ChildWorkflowExecutionCompletedEventAttributesH\x00\x12\x80\x01\n0child_workflow_execution_failed_event_attributes\x18& \x01(\x0b\x32\x44.temporal.api.history.v1.ChildWorkflowExecutionFailedEventAttributesH\x00\x12\x84\x01\n2child_workflow_execution_canceled_event_attributes\x18\' \x01(\x0b\x32\x46.temporal.api.history.v1.ChildWorkflowExecutionCanceledEventAttributesH\x00\x12\x85\x01\n3child_workflow_execution_timed_out_event_attributes\x18( \x01(\x0b\x32\x46.temporal.api.history.v1.ChildWorkflowExecutionTimedOutEventAttributesH\x00\x12\x88\x01\n4child_workflow_execution_terminated_event_attributes\x18) \x01(\x0b\x32H.temporal.api.history.v1.ChildWorkflowExecutionTerminatedEventAttributesH\x00\x12\x99\x01\n=signal_external_workflow_execution_initiated_event_attributes\x18* \x01(\x0b\x32P.temporal.api.history.v1.SignalExternalWorkflowExecutionInitiatedEventAttributesH\x00\x12\x93\x01\n:signal_external_workflow_execution_failed_event_attributes\x18+ \x01(\x0b\x32M.temporal.api.history.v1.SignalExternalWorkflowExecutionFailedEventAttributesH\x00\x12\x8a\x01\n5external_workflow_execution_signaled_event_attributes\x18, \x01(\x0b\x32I.temporal.api.history.v1.ExternalWorkflowExecutionSignaledEventAttributesH\x00\x12\x84\x01\n2upsert_workflow_search_attributes_event_attributes\x18- \x01(\x0b\x32\x46.temporal.api.history.v1.UpsertWorkflowSearchAttributesEventAttributesH\x00\x12\x86\x01\n3workflow_execution_update_accepted_event_attributes\x18. \x01(\x0b\x32G.temporal.api.history.v1.WorkflowExecutionUpdateAcceptedEventAttributesH\x00\x12\x86\x01\n3workflow_execution_update_rejected_event_attributes\x18/ \x01(\x0b\x32G.temporal.api.history.v1.WorkflowExecutionUpdateRejectedEventAttributesH\x00\x12\x88\x01\n4workflow_execution_update_completed_event_attributes\x18\x30 \x01(\x0b\x32H.temporal.api.history.v1.WorkflowExecutionUpdateCompletedEventAttributesH\x00\x12\x90\x01\n8workflow_properties_modified_externally_event_attributes\x18\x31 \x01(\x0b\x32L.temporal.api.history.v1.WorkflowPropertiesModifiedExternallyEventAttributesH\x00\x12\x90\x01\n8activity_properties_modified_externally_event_attributes\x18\x32 \x01(\x0b\x32L.temporal.api.history.v1.ActivityPropertiesModifiedExternallyEventAttributesH\x00\x12{\n-workflow_properties_modified_event_attributes\x18\x33 \x01(\x0b\x32\x42.temporal.api.history.v1.WorkflowPropertiesModifiedEventAttributesH\x00\x12\x86\x01\n3workflow_execution_update_admitted_event_attributes\x18\x34 \x01(\x0b\x32G.temporal.api.history.v1.WorkflowExecutionUpdateAdmittedEventAttributesH\x00\x12u\n*nexus_operation_scheduled_event_attributes\x18\x35 \x01(\x0b\x32?.temporal.api.history.v1.NexusOperationScheduledEventAttributesH\x00\x12q\n(nexus_operation_started_event_attributes\x18\x36 \x01(\x0b\x32=.temporal.api.history.v1.NexusOperationStartedEventAttributesH\x00\x12u\n*nexus_operation_completed_event_attributes\x18\x37 \x01(\x0b\x32?.temporal.api.history.v1.NexusOperationCompletedEventAttributesH\x00\x12o\n\'nexus_operation_failed_event_attributes\x18\x38 \x01(\x0b\x32<.temporal.api.history.v1.NexusOperationFailedEventAttributesH\x00\x12s\n)nexus_operation_canceled_event_attributes\x18\x39 \x01(\x0b\x32>.temporal.api.history.v1.NexusOperationCanceledEventAttributesH\x00\x12t\n*nexus_operation_timed_out_event_attributes\x18: \x01(\x0b\x32>.temporal.api.history.v1.NexusOperationTimedOutEventAttributesH\x00\x12\x82\x01\n1nexus_operation_cancel_requested_event_attributes\x18; \x01(\x0b\x32\x45.temporal.api.history.v1.NexusOperationCancelRequestedEventAttributesH\x00\x12\x86\x01\n3workflow_execution_options_updated_event_attributes\x18< \x01(\x0b\x32G.temporal.api.history.v1.WorkflowExecutionOptionsUpdatedEventAttributesH\x00\x12\x91\x01\n9nexus_operation_cancel_request_completed_event_attributes\x18= \x01(\x0b\x32L.temporal.api.history.v1.NexusOperationCancelRequestCompletedEventAttributesH\x00\x12\x8b\x01\n6nexus_operation_cancel_request_failed_event_attributes\x18> \x01(\x0b\x32I.temporal.api.history.v1.NexusOperationCancelRequestFailedEventAttributesH\x00\x12u\n*workflow_execution_paused_event_attributes\x18? \x01(\x0b\x32?.temporal.api.history.v1.WorkflowExecutionPausedEventAttributesH\x00\x12y\n,workflow_execution_unpaused_event_attributes\x18@ \x01(\x0b\x32\x41.temporal.api.history.v1.WorkflowExecutionUnpausedEventAttributesH\x00\x12\x9b\x01\n>workflow_execution_time_skipping_transitioned_event_attributes\x18\x41 \x01(\x0b\x32Q.temporal.api.history.v1.WorkflowExecutionTimeSkippingTransitionedEventAttributesH\x00\x42\x0c\n\nattributes"@\n\x07History\x12\x35\n\x06\x65vents\x18\x01 \x03(\x0b\x32%.temporal.api.history.v1.HistoryEventB\x8e\x01\n\x1aio.temporal.api.history.v1B\x0cMessageProtoP\x01Z%go.temporal.io/api/history/v1;history\xaa\x02\x19Temporalio.Api.History.V1\xea\x02\x1cTemporalio::Api::History::V1b\x06proto3' ) @@ -225,6 +225,11 @@ _WORKFLOWEXECUTIONUNPAUSEDEVENTATTRIBUTES = DESCRIPTOR.message_types_by_name[ "WorkflowExecutionUnpausedEventAttributes" ] +_WORKFLOWEXECUTIONTIMESKIPPINGTRANSITIONEDEVENTATTRIBUTES = ( + DESCRIPTOR.message_types_by_name[ + "WorkflowExecutionTimeSkippingTransitionedEventAttributes" + ] +) _NEXUSOPERATIONSCHEDULEDEVENTATTRIBUTES = DESCRIPTOR.message_types_by_name[ "NexusOperationScheduledEventAttributes" ] @@ -870,6 +875,19 @@ ) _sym_db.RegisterMessage(WorkflowExecutionUnpausedEventAttributes) +WorkflowExecutionTimeSkippingTransitionedEventAttributes = ( + _reflection.GeneratedProtocolMessageType( + "WorkflowExecutionTimeSkippingTransitionedEventAttributes", + (_message.Message,), + { + "DESCRIPTOR": _WORKFLOWEXECUTIONTIMESKIPPINGTRANSITIONEDEVENTATTRIBUTES, + "__module__": "temporalio.api.history.v1.message_pb2", + # @@protoc_insertion_point(class_scope:temporal.api.history.v1.WorkflowExecutionTimeSkippingTransitionedEventAttributes) + }, + ) +) +_sym_db.RegisterMessage(WorkflowExecutionTimeSkippingTransitionedEventAttributes) + NexusOperationScheduledEventAttributes = _reflection.GeneratedProtocolMessageType( "NexusOperationScheduledEventAttributes", (_message.Message,), @@ -1175,135 +1193,137 @@ "operation_id" ]._serialized_options = b"\030\001" _WORKFLOWEXECUTIONSTARTEDEVENTATTRIBUTES._serialized_start = 617 - _WORKFLOWEXECUTIONSTARTEDEVENTATTRIBUTES._serialized_end = 2810 - _DECLINEDTARGETVERSIONUPGRADE._serialized_start = 2812 - _DECLINEDTARGETVERSIONUPGRADE._serialized_end = 2923 - _WORKFLOWEXECUTIONCOMPLETEDEVENTATTRIBUTES._serialized_start = 2926 - _WORKFLOWEXECUTIONCOMPLETEDEVENTATTRIBUTES._serialized_end = 3091 - _WORKFLOWEXECUTIONFAILEDEVENTATTRIBUTES._serialized_start = 3094 - _WORKFLOWEXECUTIONFAILEDEVENTATTRIBUTES._serialized_end = 3313 - _WORKFLOWEXECUTIONTIMEDOUTEVENTATTRIBUTES._serialized_start = 3316 - _WORKFLOWEXECUTIONTIMEDOUTEVENTATTRIBUTES._serialized_end = 3444 - _WORKFLOWEXECUTIONCONTINUEDASNEWEVENTATTRIBUTES._serialized_start = 3447 - _WORKFLOWEXECUTIONCONTINUEDASNEWEVENTATTRIBUTES._serialized_end = 4380 - _WORKFLOWTASKSCHEDULEDEVENTATTRIBUTES._serialized_start = 4383 - _WORKFLOWTASKSCHEDULEDEVENTATTRIBUTES._serialized_end = 4555 - _WORKFLOWTASKSTARTEDEVENTATTRIBUTES._serialized_start = 4558 - _WORKFLOWTASKSTARTEDEVENTATTRIBUTES._serialized_end = 4974 - _WORKFLOWTASKCOMPLETEDEVENTATTRIBUTES._serialized_start = 4977 - _WORKFLOWTASKCOMPLETEDEVENTATTRIBUTES._serialized_end = 5619 - _WORKFLOWTASKTIMEDOUTEVENTATTRIBUTES._serialized_start = 5622 - _WORKFLOWTASKTIMEDOUTEVENTATTRIBUTES._serialized_end = 5771 - _WORKFLOWTASKFAILEDEVENTATTRIBUTES._serialized_start = 5774 - _WORKFLOWTASKFAILEDEVENTATTRIBUTES._serialized_end = 6165 - _ACTIVITYTASKSCHEDULEDEVENTATTRIBUTES._serialized_start = 6168 - _ACTIVITYTASKSCHEDULEDEVENTATTRIBUTES._serialized_end = 6874 - _ACTIVITYTASKSTARTEDEVENTATTRIBUTES._serialized_start = 6877 - _ACTIVITYTASKSTARTEDEVENTATTRIBUTES._serialized_end = 7163 - _ACTIVITYTASKCOMPLETEDEVENTATTRIBUTES._serialized_start = 7166 - _ACTIVITYTASKCOMPLETEDEVENTATTRIBUTES._serialized_end = 7398 - _ACTIVITYTASKFAILEDEVENTATTRIBUTES._serialized_start = 7401 - _ACTIVITYTASKFAILEDEVENTATTRIBUTES._serialized_end = 7687 - _ACTIVITYTASKTIMEDOUTEVENTATTRIBUTES._serialized_start = 7690 - _ACTIVITYTASKTIMEDOUTEVENTATTRIBUTES._serialized_end = 7888 - _ACTIVITYTASKCANCELREQUESTEDEVENTATTRIBUTES._serialized_start = 7890 - _ACTIVITYTASKCANCELREQUESTEDEVENTATTRIBUTES._serialized_end = 8004 - _ACTIVITYTASKCANCELEDEVENTATTRIBUTES._serialized_start = 8007 - _ACTIVITYTASKCANCELEDEVENTATTRIBUTES._serialized_end = 8281 - _TIMERSTARTEDEVENTATTRIBUTES._serialized_start = 8284 - _TIMERSTARTEDEVENTATTRIBUTES._serialized_end = 8431 - _TIMERFIREDEVENTATTRIBUTES._serialized_start = 8433 - _TIMERFIREDEVENTATTRIBUTES._serialized_end = 8504 - _TIMERCANCELEDEVENTATTRIBUTES._serialized_start = 8507 - _TIMERCANCELEDEVENTATTRIBUTES._serialized_end = 8641 - _WORKFLOWEXECUTIONCANCELREQUESTEDEVENTATTRIBUTES._serialized_start = 8644 - _WORKFLOWEXECUTIONCANCELREQUESTEDEVENTATTRIBUTES._serialized_end = 8843 - _WORKFLOWEXECUTIONCANCELEDEVENTATTRIBUTES._serialized_start = 8846 - _WORKFLOWEXECUTIONCANCELEDEVENTATTRIBUTES._serialized_end = 8981 - _MARKERRECORDEDEVENTATTRIBUTES._serialized_start = 8984 - _MARKERRECORDEDEVENTATTRIBUTES._serialized_end = 9345 - _MARKERRECORDEDEVENTATTRIBUTES_DETAILSENTRY._serialized_start = 9265 - _MARKERRECORDEDEVENTATTRIBUTES_DETAILSENTRY._serialized_end = 9345 - _WORKFLOWEXECUTIONSIGNALEDEVENTATTRIBUTES._serialized_start = 9348 - _WORKFLOWEXECUTIONSIGNALEDEVENTATTRIBUTES._serialized_end = 9647 - _WORKFLOWEXECUTIONTERMINATEDEVENTATTRIBUTES._serialized_start = 9650 - _WORKFLOWEXECUTIONTERMINATEDEVENTATTRIBUTES._serialized_end = 9779 - _REQUESTCANCELEXTERNALWORKFLOWEXECUTIONINITIATEDEVENTATTRIBUTES._serialized_start = 9782 + _WORKFLOWEXECUTIONSTARTEDEVENTATTRIBUTES._serialized_end = 2947 + _DECLINEDTARGETVERSIONUPGRADE._serialized_start = 2950 + _DECLINEDTARGETVERSIONUPGRADE._serialized_end = 3086 + _WORKFLOWEXECUTIONCOMPLETEDEVENTATTRIBUTES._serialized_start = 3089 + _WORKFLOWEXECUTIONCOMPLETEDEVENTATTRIBUTES._serialized_end = 3254 + _WORKFLOWEXECUTIONFAILEDEVENTATTRIBUTES._serialized_start = 3257 + _WORKFLOWEXECUTIONFAILEDEVENTATTRIBUTES._serialized_end = 3476 + _WORKFLOWEXECUTIONTIMEDOUTEVENTATTRIBUTES._serialized_start = 3479 + _WORKFLOWEXECUTIONTIMEDOUTEVENTATTRIBUTES._serialized_end = 3607 + _WORKFLOWEXECUTIONCONTINUEDASNEWEVENTATTRIBUTES._serialized_start = 3610 + _WORKFLOWEXECUTIONCONTINUEDASNEWEVENTATTRIBUTES._serialized_end = 4543 + _WORKFLOWTASKSCHEDULEDEVENTATTRIBUTES._serialized_start = 4546 + _WORKFLOWTASKSCHEDULEDEVENTATTRIBUTES._serialized_end = 4718 + _WORKFLOWTASKSTARTEDEVENTATTRIBUTES._serialized_start = 4721 + _WORKFLOWTASKSTARTEDEVENTATTRIBUTES._serialized_end = 5137 + _WORKFLOWTASKCOMPLETEDEVENTATTRIBUTES._serialized_start = 5140 + _WORKFLOWTASKCOMPLETEDEVENTATTRIBUTES._serialized_end = 5782 + _WORKFLOWTASKTIMEDOUTEVENTATTRIBUTES._serialized_start = 5785 + _WORKFLOWTASKTIMEDOUTEVENTATTRIBUTES._serialized_end = 5934 + _WORKFLOWTASKFAILEDEVENTATTRIBUTES._serialized_start = 5937 + _WORKFLOWTASKFAILEDEVENTATTRIBUTES._serialized_end = 6328 + _ACTIVITYTASKSCHEDULEDEVENTATTRIBUTES._serialized_start = 6331 + _ACTIVITYTASKSCHEDULEDEVENTATTRIBUTES._serialized_end = 7037 + _ACTIVITYTASKSTARTEDEVENTATTRIBUTES._serialized_start = 7040 + _ACTIVITYTASKSTARTEDEVENTATTRIBUTES._serialized_end = 7326 + _ACTIVITYTASKCOMPLETEDEVENTATTRIBUTES._serialized_start = 7329 + _ACTIVITYTASKCOMPLETEDEVENTATTRIBUTES._serialized_end = 7561 + _ACTIVITYTASKFAILEDEVENTATTRIBUTES._serialized_start = 7564 + _ACTIVITYTASKFAILEDEVENTATTRIBUTES._serialized_end = 7850 + _ACTIVITYTASKTIMEDOUTEVENTATTRIBUTES._serialized_start = 7853 + _ACTIVITYTASKTIMEDOUTEVENTATTRIBUTES._serialized_end = 8051 + _ACTIVITYTASKCANCELREQUESTEDEVENTATTRIBUTES._serialized_start = 8053 + _ACTIVITYTASKCANCELREQUESTEDEVENTATTRIBUTES._serialized_end = 8167 + _ACTIVITYTASKCANCELEDEVENTATTRIBUTES._serialized_start = 8170 + _ACTIVITYTASKCANCELEDEVENTATTRIBUTES._serialized_end = 8444 + _TIMERSTARTEDEVENTATTRIBUTES._serialized_start = 8447 + _TIMERSTARTEDEVENTATTRIBUTES._serialized_end = 8594 + _TIMERFIREDEVENTATTRIBUTES._serialized_start = 8596 + _TIMERFIREDEVENTATTRIBUTES._serialized_end = 8667 + _TIMERCANCELEDEVENTATTRIBUTES._serialized_start = 8670 + _TIMERCANCELEDEVENTATTRIBUTES._serialized_end = 8804 + _WORKFLOWEXECUTIONCANCELREQUESTEDEVENTATTRIBUTES._serialized_start = 8807 + _WORKFLOWEXECUTIONCANCELREQUESTEDEVENTATTRIBUTES._serialized_end = 9006 + _WORKFLOWEXECUTIONCANCELEDEVENTATTRIBUTES._serialized_start = 9009 + _WORKFLOWEXECUTIONCANCELEDEVENTATTRIBUTES._serialized_end = 9144 + _MARKERRECORDEDEVENTATTRIBUTES._serialized_start = 9147 + _MARKERRECORDEDEVENTATTRIBUTES._serialized_end = 9508 + _MARKERRECORDEDEVENTATTRIBUTES_DETAILSENTRY._serialized_start = 9428 + _MARKERRECORDEDEVENTATTRIBUTES_DETAILSENTRY._serialized_end = 9508 + _WORKFLOWEXECUTIONSIGNALEDEVENTATTRIBUTES._serialized_start = 9511 + _WORKFLOWEXECUTIONSIGNALEDEVENTATTRIBUTES._serialized_end = 9830 + _WORKFLOWEXECUTIONTERMINATEDEVENTATTRIBUTES._serialized_start = 9833 + _WORKFLOWEXECUTIONTERMINATEDEVENTATTRIBUTES._serialized_end = 9962 + _REQUESTCANCELEXTERNALWORKFLOWEXECUTIONINITIATEDEVENTATTRIBUTES._serialized_start = 9965 _REQUESTCANCELEXTERNALWORKFLOWEXECUTIONINITIATEDEVENTATTRIBUTES._serialized_end = ( - 10066 + 10249 ) _REQUESTCANCELEXTERNALWORKFLOWEXECUTIONFAILEDEVENTATTRIBUTES._serialized_start = ( - 10069 + 10252 ) - _REQUESTCANCELEXTERNALWORKFLOWEXECUTIONFAILEDEVENTATTRIBUTES._serialized_end = 10415 - _EXTERNALWORKFLOWEXECUTIONCANCELREQUESTEDEVENTATTRIBUTES._serialized_start = 10418 - _EXTERNALWORKFLOWEXECUTIONCANCELREQUESTEDEVENTATTRIBUTES._serialized_end = 10615 - _SIGNALEXTERNALWORKFLOWEXECUTIONINITIATEDEVENTATTRIBUTES._serialized_start = 10618 - _SIGNALEXTERNALWORKFLOWEXECUTIONINITIATEDEVENTATTRIBUTES._serialized_end = 10997 - _SIGNALEXTERNALWORKFLOWEXECUTIONFAILEDEVENTATTRIBUTES._serialized_start = 11000 - _SIGNALEXTERNALWORKFLOWEXECUTIONFAILEDEVENTATTRIBUTES._serialized_end = 11339 - _EXTERNALWORKFLOWEXECUTIONSIGNALEDEVENTATTRIBUTES._serialized_start = 11342 - _EXTERNALWORKFLOWEXECUTIONSIGNALEDEVENTATTRIBUTES._serialized_end = 11553 - _UPSERTWORKFLOWSEARCHATTRIBUTESEVENTATTRIBUTES._serialized_start = 11556 - _UPSERTWORKFLOWSEARCHATTRIBUTESEVENTATTRIBUTES._serialized_end = 11714 - _WORKFLOWPROPERTIESMODIFIEDEVENTATTRIBUTES._serialized_start = 11717 - _WORKFLOWPROPERTIESMODIFIEDEVENTATTRIBUTES._serialized_end = 11855 - _STARTCHILDWORKFLOWEXECUTIONINITIATEDEVENTATTRIBUTES._serialized_start = 11858 - _STARTCHILDWORKFLOWEXECUTIONINITIATEDEVENTATTRIBUTES._serialized_end = 12858 - _STARTCHILDWORKFLOWEXECUTIONFAILEDEVENTATTRIBUTES._serialized_start = 12861 - _STARTCHILDWORKFLOWEXECUTIONFAILEDEVENTATTRIBUTES._serialized_end = 13203 - _CHILDWORKFLOWEXECUTIONSTARTEDEVENTATTRIBUTES._serialized_start = 13206 - _CHILDWORKFLOWEXECUTIONSTARTEDEVENTATTRIBUTES._serialized_end = 13501 - _CHILDWORKFLOWEXECUTIONCOMPLETEDEVENTATTRIBUTES._serialized_start = 13504 - _CHILDWORKFLOWEXECUTIONCOMPLETEDEVENTATTRIBUTES._serialized_end = 13829 - _CHILDWORKFLOWEXECUTIONFAILEDEVENTATTRIBUTES._serialized_start = 13832 - _CHILDWORKFLOWEXECUTIONFAILEDEVENTATTRIBUTES._serialized_end = 14211 - _CHILDWORKFLOWEXECUTIONCANCELEDEVENTATTRIBUTES._serialized_start = 14214 - _CHILDWORKFLOWEXECUTIONCANCELEDEVENTATTRIBUTES._serialized_end = 14539 - _CHILDWORKFLOWEXECUTIONTIMEDOUTEVENTATTRIBUTES._serialized_start = 14542 - _CHILDWORKFLOWEXECUTIONTIMEDOUTEVENTATTRIBUTES._serialized_end = 14872 - _CHILDWORKFLOWEXECUTIONTERMINATEDEVENTATTRIBUTES._serialized_start = 14875 - _CHILDWORKFLOWEXECUTIONTERMINATEDEVENTATTRIBUTES._serialized_end = 15151 - _WORKFLOWEXECUTIONOPTIONSUPDATEDEVENTATTRIBUTES._serialized_start = 15154 - _WORKFLOWEXECUTIONOPTIONSUPDATEDEVENTATTRIBUTES._serialized_end = 15484 - _WORKFLOWPROPERTIESMODIFIEDEXTERNALLYEVENTATTRIBUTES._serialized_start = 15487 - _WORKFLOWPROPERTIESMODIFIEDEXTERNALLYEVENTATTRIBUTES._serialized_end = 15807 - _ACTIVITYPROPERTIESMODIFIEDEXTERNALLYEVENTATTRIBUTES._serialized_start = 15810 - _ACTIVITYPROPERTIESMODIFIEDEXTERNALLYEVENTATTRIBUTES._serialized_end = 15954 - _WORKFLOWEXECUTIONUPDATEACCEPTEDEVENTATTRIBUTES._serialized_start = 15957 - _WORKFLOWEXECUTIONUPDATEACCEPTEDEVENTATTRIBUTES._serialized_end = 16177 - _WORKFLOWEXECUTIONUPDATECOMPLETEDEVENTATTRIBUTES._serialized_start = 16180 - _WORKFLOWEXECUTIONUPDATECOMPLETEDEVENTATTRIBUTES._serialized_end = 16350 - _WORKFLOWEXECUTIONUPDATEREJECTEDEVENTATTRIBUTES._serialized_start = 16353 - _WORKFLOWEXECUTIONUPDATEREJECTEDEVENTATTRIBUTES._serialized_end = 16624 - _WORKFLOWEXECUTIONUPDATEADMITTEDEVENTATTRIBUTES._serialized_start = 16627 - _WORKFLOWEXECUTIONUPDATEADMITTEDEVENTATTRIBUTES._serialized_end = 16791 - _WORKFLOWEXECUTIONPAUSEDEVENTATTRIBUTES._serialized_start = 16793 - _WORKFLOWEXECUTIONPAUSEDEVENTATTRIBUTES._serialized_end = 16887 - _WORKFLOWEXECUTIONUNPAUSEDEVENTATTRIBUTES._serialized_start = 16889 - _WORKFLOWEXECUTIONUNPAUSEDEVENTATTRIBUTES._serialized_end = 16985 - _NEXUSOPERATIONSCHEDULEDEVENTATTRIBUTES._serialized_start = 16988 - _NEXUSOPERATIONSCHEDULEDEVENTATTRIBUTES._serialized_end = 17552 - _NEXUSOPERATIONSCHEDULEDEVENTATTRIBUTES_NEXUSHEADERENTRY._serialized_start = 17502 - _NEXUSOPERATIONSCHEDULEDEVENTATTRIBUTES_NEXUSHEADERENTRY._serialized_end = 17552 - _NEXUSOPERATIONSTARTEDEVENTATTRIBUTES._serialized_start = 17555 - _NEXUSOPERATIONSTARTEDEVENTATTRIBUTES._serialized_end = 17692 - _NEXUSOPERATIONCOMPLETEDEVENTATTRIBUTES._serialized_start = 17695 - _NEXUSOPERATIONCOMPLETEDEVENTATTRIBUTES._serialized_end = 17832 - _NEXUSOPERATIONFAILEDEVENTATTRIBUTES._serialized_start = 17835 - _NEXUSOPERATIONFAILEDEVENTATTRIBUTES._serialized_end = 17971 - _NEXUSOPERATIONTIMEDOUTEVENTATTRIBUTES._serialized_start = 17974 - _NEXUSOPERATIONTIMEDOUTEVENTATTRIBUTES._serialized_end = 18112 - _NEXUSOPERATIONCANCELEDEVENTATTRIBUTES._serialized_start = 18115 - _NEXUSOPERATIONCANCELEDEVENTATTRIBUTES._serialized_end = 18253 - _NEXUSOPERATIONCANCELREQUESTEDEVENTATTRIBUTES._serialized_start = 18255 - _NEXUSOPERATIONCANCELREQUESTEDEVENTATTRIBUTES._serialized_end = 18371 - _NEXUSOPERATIONCANCELREQUESTCOMPLETEDEVENTATTRIBUTES._serialized_start = 18374 - _NEXUSOPERATIONCANCELREQUESTCOMPLETEDEVENTATTRIBUTES._serialized_end = 18525 - _NEXUSOPERATIONCANCELREQUESTFAILEDEVENTATTRIBUTES._serialized_start = 18528 - _NEXUSOPERATIONCANCELREQUESTFAILEDEVENTATTRIBUTES._serialized_end = 18727 - _HISTORYEVENT._serialized_start = 18730 - _HISTORYEVENT._serialized_end = 26586 - _HISTORY._serialized_start = 26588 - _HISTORY._serialized_end = 26652 + _REQUESTCANCELEXTERNALWORKFLOWEXECUTIONFAILEDEVENTATTRIBUTES._serialized_end = 10598 + _EXTERNALWORKFLOWEXECUTIONCANCELREQUESTEDEVENTATTRIBUTES._serialized_start = 10601 + _EXTERNALWORKFLOWEXECUTIONCANCELREQUESTEDEVENTATTRIBUTES._serialized_end = 10798 + _SIGNALEXTERNALWORKFLOWEXECUTIONINITIATEDEVENTATTRIBUTES._serialized_start = 10801 + _SIGNALEXTERNALWORKFLOWEXECUTIONINITIATEDEVENTATTRIBUTES._serialized_end = 11180 + _SIGNALEXTERNALWORKFLOWEXECUTIONFAILEDEVENTATTRIBUTES._serialized_start = 11183 + _SIGNALEXTERNALWORKFLOWEXECUTIONFAILEDEVENTATTRIBUTES._serialized_end = 11522 + _EXTERNALWORKFLOWEXECUTIONSIGNALEDEVENTATTRIBUTES._serialized_start = 11525 + _EXTERNALWORKFLOWEXECUTIONSIGNALEDEVENTATTRIBUTES._serialized_end = 11736 + _UPSERTWORKFLOWSEARCHATTRIBUTESEVENTATTRIBUTES._serialized_start = 11739 + _UPSERTWORKFLOWSEARCHATTRIBUTESEVENTATTRIBUTES._serialized_end = 11897 + _WORKFLOWPROPERTIESMODIFIEDEVENTATTRIBUTES._serialized_start = 11900 + _WORKFLOWPROPERTIESMODIFIEDEVENTATTRIBUTES._serialized_end = 12038 + _STARTCHILDWORKFLOWEXECUTIONINITIATEDEVENTATTRIBUTES._serialized_start = 12041 + _STARTCHILDWORKFLOWEXECUTIONINITIATEDEVENTATTRIBUTES._serialized_end = 13178 + _STARTCHILDWORKFLOWEXECUTIONFAILEDEVENTATTRIBUTES._serialized_start = 13181 + _STARTCHILDWORKFLOWEXECUTIONFAILEDEVENTATTRIBUTES._serialized_end = 13523 + _CHILDWORKFLOWEXECUTIONSTARTEDEVENTATTRIBUTES._serialized_start = 13526 + _CHILDWORKFLOWEXECUTIONSTARTEDEVENTATTRIBUTES._serialized_end = 13821 + _CHILDWORKFLOWEXECUTIONCOMPLETEDEVENTATTRIBUTES._serialized_start = 13824 + _CHILDWORKFLOWEXECUTIONCOMPLETEDEVENTATTRIBUTES._serialized_end = 14149 + _CHILDWORKFLOWEXECUTIONFAILEDEVENTATTRIBUTES._serialized_start = 14152 + _CHILDWORKFLOWEXECUTIONFAILEDEVENTATTRIBUTES._serialized_end = 14531 + _CHILDWORKFLOWEXECUTIONCANCELEDEVENTATTRIBUTES._serialized_start = 14534 + _CHILDWORKFLOWEXECUTIONCANCELEDEVENTATTRIBUTES._serialized_end = 14859 + _CHILDWORKFLOWEXECUTIONTIMEDOUTEVENTATTRIBUTES._serialized_start = 14862 + _CHILDWORKFLOWEXECUTIONTIMEDOUTEVENTATTRIBUTES._serialized_end = 15192 + _CHILDWORKFLOWEXECUTIONTERMINATEDEVENTATTRIBUTES._serialized_start = 15195 + _CHILDWORKFLOWEXECUTIONTERMINATEDEVENTATTRIBUTES._serialized_end = 15471 + _WORKFLOWEXECUTIONOPTIONSUPDATEDEVENTATTRIBUTES._serialized_start = 15474 + _WORKFLOWEXECUTIONOPTIONSUPDATEDEVENTATTRIBUTES._serialized_end = 15880 + _WORKFLOWPROPERTIESMODIFIEDEXTERNALLYEVENTATTRIBUTES._serialized_start = 15883 + _WORKFLOWPROPERTIESMODIFIEDEXTERNALLYEVENTATTRIBUTES._serialized_end = 16203 + _ACTIVITYPROPERTIESMODIFIEDEXTERNALLYEVENTATTRIBUTES._serialized_start = 16206 + _ACTIVITYPROPERTIESMODIFIEDEXTERNALLYEVENTATTRIBUTES._serialized_end = 16350 + _WORKFLOWEXECUTIONUPDATEACCEPTEDEVENTATTRIBUTES._serialized_start = 16353 + _WORKFLOWEXECUTIONUPDATEACCEPTEDEVENTATTRIBUTES._serialized_end = 16573 + _WORKFLOWEXECUTIONUPDATECOMPLETEDEVENTATTRIBUTES._serialized_start = 16576 + _WORKFLOWEXECUTIONUPDATECOMPLETEDEVENTATTRIBUTES._serialized_end = 16746 + _WORKFLOWEXECUTIONUPDATEREJECTEDEVENTATTRIBUTES._serialized_start = 16749 + _WORKFLOWEXECUTIONUPDATEREJECTEDEVENTATTRIBUTES._serialized_end = 17020 + _WORKFLOWEXECUTIONUPDATEADMITTEDEVENTATTRIBUTES._serialized_start = 17023 + _WORKFLOWEXECUTIONUPDATEADMITTEDEVENTATTRIBUTES._serialized_end = 17187 + _WORKFLOWEXECUTIONPAUSEDEVENTATTRIBUTES._serialized_start = 17189 + _WORKFLOWEXECUTIONPAUSEDEVENTATTRIBUTES._serialized_end = 17283 + _WORKFLOWEXECUTIONUNPAUSEDEVENTATTRIBUTES._serialized_start = 17285 + _WORKFLOWEXECUTIONUNPAUSEDEVENTATTRIBUTES._serialized_end = 17381 + _WORKFLOWEXECUTIONTIMESKIPPINGTRANSITIONEDEVENTATTRIBUTES._serialized_start = 17384 + _WORKFLOWEXECUTIONTIMESKIPPINGTRANSITIONEDEVENTATTRIBUTES._serialized_end = 17574 + _NEXUSOPERATIONSCHEDULEDEVENTATTRIBUTES._serialized_start = 17577 + _NEXUSOPERATIONSCHEDULEDEVENTATTRIBUTES._serialized_end = 18141 + _NEXUSOPERATIONSCHEDULEDEVENTATTRIBUTES_NEXUSHEADERENTRY._serialized_start = 18091 + _NEXUSOPERATIONSCHEDULEDEVENTATTRIBUTES_NEXUSHEADERENTRY._serialized_end = 18141 + _NEXUSOPERATIONSTARTEDEVENTATTRIBUTES._serialized_start = 18144 + _NEXUSOPERATIONSTARTEDEVENTATTRIBUTES._serialized_end = 18281 + _NEXUSOPERATIONCOMPLETEDEVENTATTRIBUTES._serialized_start = 18284 + _NEXUSOPERATIONCOMPLETEDEVENTATTRIBUTES._serialized_end = 18421 + _NEXUSOPERATIONFAILEDEVENTATTRIBUTES._serialized_start = 18424 + _NEXUSOPERATIONFAILEDEVENTATTRIBUTES._serialized_end = 18560 + _NEXUSOPERATIONTIMEDOUTEVENTATTRIBUTES._serialized_start = 18563 + _NEXUSOPERATIONTIMEDOUTEVENTATTRIBUTES._serialized_end = 18701 + _NEXUSOPERATIONCANCELEDEVENTATTRIBUTES._serialized_start = 18704 + _NEXUSOPERATIONCANCELEDEVENTATTRIBUTES._serialized_end = 18842 + _NEXUSOPERATIONCANCELREQUESTEDEVENTATTRIBUTES._serialized_start = 18844 + _NEXUSOPERATIONCANCELREQUESTEDEVENTATTRIBUTES._serialized_end = 18960 + _NEXUSOPERATIONCANCELREQUESTCOMPLETEDEVENTATTRIBUTES._serialized_start = 18963 + _NEXUSOPERATIONCANCELREQUESTCOMPLETEDEVENTATTRIBUTES._serialized_end = 19114 + _NEXUSOPERATIONCANCELREQUESTFAILEDEVENTATTRIBUTES._serialized_start = 19117 + _NEXUSOPERATIONCANCELREQUESTFAILEDEVENTATTRIBUTES._serialized_end = 19316 + _HISTORYEVENT._serialized_start = 19319 + _HISTORYEVENT._serialized_end = 27388 + _HISTORY._serialized_start = 27390 + _HISTORY._serialized_end = 27454 # @@protoc_insertion_point(module_scope) diff --git a/temporalio/api/history/v1/message_pb2.pyi b/temporalio/api/history/v1/message_pb2.pyi index ca5a93da5..a8f57b30c 100644 --- a/temporalio/api/history/v1/message_pb2.pyi +++ b/temporalio/api/history/v1/message_pb2.pyi @@ -77,6 +77,8 @@ class WorkflowExecutionStartedEventAttributes(google.protobuf.message.Message): INHERITED_AUTO_UPGRADE_INFO_FIELD_NUMBER: builtins.int EAGER_EXECUTION_ACCEPTED_FIELD_NUMBER: builtins.int DECLINED_TARGET_VERSION_UPGRADE_FIELD_NUMBER: builtins.int + TIME_SKIPPING_CONFIG_FIELD_NUMBER: builtins.int + INITIAL_SKIPPED_DURATION_FIELD_NUMBER: builtins.int @property def workflow_type(self) -> temporalio.api.common.v1.message_pb2.WorkflowType: ... parent_workflow_namespace: builtins.str @@ -300,6 +302,22 @@ class WorkflowExecutionStartedEventAttributes(google.protobuf.message.Message): Used internally by the server during continue-as-new and retry. Should not be read or interpreted by SDKs. """ + @property + def time_skipping_config( + self, + ) -> temporalio.api.workflow.v1.message_pb2.TimeSkippingConfig: + """Initial time-skipping configuration for this workflow execution, recorded at start time. + This may have been set explicitly via the start workflow request, or propagated from a + parent/previous execution. + + The configuration may be updated after start via UpdateWorkflowExecutionOptions, which + will be reflected in the WorkflowExecutionOptionsUpdatedEvent. + """ + @property + def initial_skipped_duration(self) -> google.protobuf.duration_pb2.Duration: + """The time skipped by the previous execution that started this workflow. + It can happen in cases of child workflows and continue-as-new workflows. + """ def __init__( self, *, @@ -356,6 +374,9 @@ class WorkflowExecutionStartedEventAttributes(google.protobuf.message.Message): eager_execution_accepted: builtins.bool = ..., declined_target_version_upgrade: global___DeclinedTargetVersionUpgrade | None = ..., + time_skipping_config: temporalio.api.workflow.v1.message_pb2.TimeSkippingConfig + | None = ..., + initial_skipped_duration: google.protobuf.duration_pb2.Duration | None = ..., ) -> None: ... def HasField( self, @@ -372,6 +393,8 @@ class WorkflowExecutionStartedEventAttributes(google.protobuf.message.Message): b"inherited_auto_upgrade_info", "inherited_pinned_version", b"inherited_pinned_version", + "initial_skipped_duration", + b"initial_skipped_duration", "input", b"input", "last_completion_result", @@ -394,6 +417,8 @@ class WorkflowExecutionStartedEventAttributes(google.protobuf.message.Message): b"source_version_stamp", "task_queue", b"task_queue", + "time_skipping_config", + b"time_skipping_config", "versioning_override", b"versioning_override", "workflow_execution_expiration_time", @@ -439,6 +464,8 @@ class WorkflowExecutionStartedEventAttributes(google.protobuf.message.Message): b"inherited_build_id", "inherited_pinned_version", b"inherited_pinned_version", + "initial_skipped_duration", + b"initial_skipped_duration", "initiator", b"initiator", "input", @@ -475,6 +502,8 @@ class WorkflowExecutionStartedEventAttributes(google.protobuf.message.Message): b"source_version_stamp", "task_queue", b"task_queue", + "time_skipping_config", + b"time_skipping_config", "versioning_override", b"versioning_override", "workflow_execution_expiration_time", @@ -504,15 +533,23 @@ class DeclinedTargetVersionUpgrade(google.protobuf.message.Message): DESCRIPTOR: google.protobuf.descriptor.Descriptor DEPLOYMENT_VERSION_FIELD_NUMBER: builtins.int + REVISION_NUMBER_FIELD_NUMBER: builtins.int @property def deployment_version( self, ) -> temporalio.api.deployment.v1.message_pb2.WorkerDeploymentVersion: ... + revision_number: builtins.int + """Revision number of the task queue routing config at the time the target + was declined. If an incoming target's revision is <= this value, it is + not newer and is not used for deciding whether or not to suppress the + upgrade signal. + """ def __init__( self, *, deployment_version: temporalio.api.deployment.v1.message_pb2.WorkerDeploymentVersion | None = ..., + revision_number: builtins.int = ..., ) -> None: ... def HasField( self, @@ -523,7 +560,10 @@ class DeclinedTargetVersionUpgrade(google.protobuf.message.Message): def ClearField( self, field_name: typing_extensions.Literal[ - "deployment_version", b"deployment_version" + "deployment_version", + b"deployment_version", + "revision_number", + b"revision_number", ], ) -> None: ... @@ -1012,13 +1052,11 @@ class WorkflowTaskCompletedEventAttributes(google.protobuf.message.Message): worker_deployment_version: builtins.str """The Worker Deployment Version that completed this task. Must be set if `versioning_behavior` is set. This value updates workflow execution's `versioning_info.version`. - Experimental. Worker Deployments are experimental and might significantly change in the future. Deprecated. Replaced with `deployment_version`. """ worker_deployment_name: builtins.str """The name of Worker Deployment that completed this task. Must be set if `versioning_behavior` is set. This value updates workflow execution's `worker_deployment_name`. - Experimental. Worker Deployments are experimental and might significantly change in the future. """ @property def deployment_version( @@ -1026,7 +1064,6 @@ class WorkflowTaskCompletedEventAttributes(google.protobuf.message.Message): ) -> temporalio.api.deployment.v1.message_pb2.WorkerDeploymentVersion: """The Worker Deployment Version that completed this task. Must be set if `versioning_behavior` is set. This value updates workflow execution's `versioning_info.deployment_version`. - Experimental. Worker Deployments are experimental and might significantly change in the future. """ def __init__( self, @@ -1985,6 +2022,7 @@ class WorkflowExecutionSignaledEventAttributes(google.protobuf.message.Message): HEADER_FIELD_NUMBER: builtins.int SKIP_GENERATE_WORKFLOW_TASK_FIELD_NUMBER: builtins.int EXTERNAL_WORKFLOW_EXECUTION_FIELD_NUMBER: builtins.int + REQUEST_ID_FIELD_NUMBER: builtins.int signal_name: builtins.str """The name/type of the signal to fire""" @property @@ -2004,6 +2042,10 @@ class WorkflowExecutionSignaledEventAttributes(google.protobuf.message.Message): self, ) -> temporalio.api.common.v1.message_pb2.WorkflowExecution: """When signal origin is a workflow execution, this field is set.""" + request_id: builtins.str + """The request ID of the Signal request, used by the server to attach this to + the correct Event ID when generating link. + """ def __init__( self, *, @@ -2014,6 +2056,7 @@ class WorkflowExecutionSignaledEventAttributes(google.protobuf.message.Message): skip_generate_workflow_task: builtins.bool = ..., external_workflow_execution: temporalio.api.common.v1.message_pb2.WorkflowExecution | None = ..., + request_id: builtins.str = ..., ) -> None: ... def HasField( self, @@ -2037,6 +2080,8 @@ class WorkflowExecutionSignaledEventAttributes(google.protobuf.message.Message): b"identity", "input", b"input", + "request_id", + b"request_id", "signal_name", b"signal_name", "skip_generate_workflow_task", @@ -2597,6 +2642,8 @@ class StartChildWorkflowExecutionInitiatedEventAttributes( SEARCH_ATTRIBUTES_FIELD_NUMBER: builtins.int INHERIT_BUILD_ID_FIELD_NUMBER: builtins.int PRIORITY_FIELD_NUMBER: builtins.int + TIME_SKIPPING_CONFIG_FIELD_NUMBER: builtins.int + INITIAL_SKIPPED_DURATION_FIELD_NUMBER: builtins.int namespace: builtins.str """Namespace of the child workflow. SDKs and UI tools should use `namespace` field but server must use `namespace_id` only. @@ -2650,6 +2697,14 @@ class StartChildWorkflowExecutionInitiatedEventAttributes( @property def priority(self) -> temporalio.api.common.v1.message_pb2.Priority: """Priority metadata""" + @property + def time_skipping_config( + self, + ) -> temporalio.api.workflow.v1.message_pb2.TimeSkippingConfig: + """The propagated time-skipping configuration for the child workflow.""" + @property + def initial_skipped_duration(self) -> google.protobuf.duration_pb2.Duration: + """Propagate the duration skipped to the child workflow.""" def __init__( self, *, @@ -2674,12 +2729,17 @@ class StartChildWorkflowExecutionInitiatedEventAttributes( | None = ..., inherit_build_id: builtins.bool = ..., priority: temporalio.api.common.v1.message_pb2.Priority | None = ..., + time_skipping_config: temporalio.api.workflow.v1.message_pb2.TimeSkippingConfig + | None = ..., + initial_skipped_duration: google.protobuf.duration_pb2.Duration | None = ..., ) -> None: ... def HasField( self, field_name: typing_extensions.Literal[ "header", b"header", + "initial_skipped_duration", + b"initial_skipped_duration", "input", b"input", "memo", @@ -2692,6 +2752,8 @@ class StartChildWorkflowExecutionInitiatedEventAttributes( b"search_attributes", "task_queue", b"task_queue", + "time_skipping_config", + b"time_skipping_config", "workflow_execution_timeout", b"workflow_execution_timeout", "workflow_run_timeout", @@ -2713,6 +2775,8 @@ class StartChildWorkflowExecutionInitiatedEventAttributes( b"header", "inherit_build_id", b"inherit_build_id", + "initial_skipped_duration", + b"initial_skipped_duration", "input", b"input", "memo", @@ -2731,6 +2795,8 @@ class StartChildWorkflowExecutionInitiatedEventAttributes( b"search_attributes", "task_queue", b"task_queue", + "time_skipping_config", + b"time_skipping_config", "workflow_execution_timeout", b"workflow_execution_timeout", "workflow_id", @@ -3260,6 +3326,7 @@ class WorkflowExecutionOptionsUpdatedEventAttributes(google.protobuf.message.Mes ATTACHED_COMPLETION_CALLBACKS_FIELD_NUMBER: builtins.int IDENTITY_FIELD_NUMBER: builtins.int PRIORITY_FIELD_NUMBER: builtins.int + TIME_SKIPPING_CONFIG_FIELD_NUMBER: builtins.int @property def versioning_override( self, @@ -3287,6 +3354,11 @@ class WorkflowExecutionOptionsUpdatedEventAttributes(google.protobuf.message.Mes """Priority override upserted in this event. Represents the full priority; not just partial fields. Ignored if nil. """ + @property + def time_skipping_config( + self, + ) -> temporalio.api.workflow.v1.message_pb2.TimeSkippingConfig: + """If set, the time-skipping configuration was changed. Contains the full updated configuration.""" def __init__( self, *, @@ -3300,11 +3372,18 @@ class WorkflowExecutionOptionsUpdatedEventAttributes(google.protobuf.message.Mes | None = ..., identity: builtins.str = ..., priority: temporalio.api.common.v1.message_pb2.Priority | None = ..., + time_skipping_config: temporalio.api.workflow.v1.message_pb2.TimeSkippingConfig + | None = ..., ) -> None: ... def HasField( self, field_name: typing_extensions.Literal[ - "priority", b"priority", "versioning_override", b"versioning_override" + "priority", + b"priority", + "time_skipping_config", + b"time_skipping_config", + "versioning_override", + b"versioning_override", ], ) -> builtins.bool: ... def ClearField( @@ -3318,6 +3397,8 @@ class WorkflowExecutionOptionsUpdatedEventAttributes(google.protobuf.message.Mes b"identity", "priority", b"priority", + "time_skipping_config", + b"time_skipping_config", "unset_versioning_override", b"unset_versioning_override", "versioning_override", @@ -3680,6 +3761,59 @@ global___WorkflowExecutionUnpausedEventAttributes = ( WorkflowExecutionUnpausedEventAttributes ) +class WorkflowExecutionTimeSkippingTransitionedEventAttributes( + google.protobuf.message.Message +): + """Attributes for an event indicating that time skipping state changed for a workflow execution, + either time was advanced or time skipping was disabled automatically due to a bound being reached. + The worker_may_ignore field in HistoryEvent should always be set true for this event. + """ + + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + TARGET_TIME_FIELD_NUMBER: builtins.int + DISABLED_AFTER_BOUND_FIELD_NUMBER: builtins.int + WALL_CLOCK_TIME_FIELD_NUMBER: builtins.int + @property + def target_time(self) -> google.protobuf.timestamp_pb2.Timestamp: + """The virtual time after time skipping was applied.""" + disabled_after_bound: builtins.bool + """when true, time skipping was disabled automatically due to a bound being reached. + (-- api-linter: core::0140::prepositions=disabled + aip.dev/not-precedent: "after" is used to indicate temporal ordering. --) + """ + @property + def wall_clock_time(self) -> google.protobuf.timestamp_pb2.Timestamp: + """The wall-clock time when the time-skipping state changed event was generated.""" + def __init__( + self, + *, + target_time: google.protobuf.timestamp_pb2.Timestamp | None = ..., + disabled_after_bound: builtins.bool = ..., + wall_clock_time: google.protobuf.timestamp_pb2.Timestamp | None = ..., + ) -> None: ... + def HasField( + self, + field_name: typing_extensions.Literal[ + "target_time", b"target_time", "wall_clock_time", b"wall_clock_time" + ], + ) -> builtins.bool: ... + def ClearField( + self, + field_name: typing_extensions.Literal[ + "disabled_after_bound", + b"disabled_after_bound", + "target_time", + b"target_time", + "wall_clock_time", + b"wall_clock_time", + ], + ) -> None: ... + +global___WorkflowExecutionTimeSkippingTransitionedEventAttributes = ( + WorkflowExecutionTimeSkippingTransitionedEventAttributes +) + class NexusOperationScheduledEventAttributes(google.protobuf.message.Message): """Event marking that an operation was scheduled by a workflow via the ScheduleNexusOperation command.""" @@ -3733,6 +3867,8 @@ class NexusOperationScheduledEventAttributes(google.protobuf.message.Message): Calls are retried internally by the server. (-- api-linter: core::0140::prepositions=disabled aip.dev/not-precedent: "to" is used to indicate interval. --) + (-- api-linter: core::0142::time-field-names=disabled + aip.dev/not-precedent: "timeout" is an acceptable suffix for duration fields in this API. --) """ @property def nexus_header( @@ -4166,6 +4302,7 @@ class HistoryEvent(google.protobuf.message.Message): WORKER_MAY_IGNORE_FIELD_NUMBER: builtins.int USER_METADATA_FIELD_NUMBER: builtins.int LINKS_FIELD_NUMBER: builtins.int + PRINCIPAL_FIELD_NUMBER: builtins.int WORKFLOW_EXECUTION_STARTED_EVENT_ATTRIBUTES_FIELD_NUMBER: builtins.int WORKFLOW_EXECUTION_COMPLETED_EVENT_ATTRIBUTES_FIELD_NUMBER: builtins.int WORKFLOW_EXECUTION_FAILED_EVENT_ATTRIBUTES_FIELD_NUMBER: builtins.int @@ -4233,6 +4370,9 @@ class HistoryEvent(google.protobuf.message.Message): NEXUS_OPERATION_CANCEL_REQUEST_FAILED_EVENT_ATTRIBUTES_FIELD_NUMBER: builtins.int WORKFLOW_EXECUTION_PAUSED_EVENT_ATTRIBUTES_FIELD_NUMBER: builtins.int WORKFLOW_EXECUTION_UNPAUSED_EVENT_ATTRIBUTES_FIELD_NUMBER: builtins.int + WORKFLOW_EXECUTION_TIME_SKIPPING_TRANSITIONED_EVENT_ATTRIBUTES_FIELD_NUMBER: ( + builtins.int + ) event_id: builtins.int """Monotonically increasing event number, starts at 1.""" @property @@ -4269,7 +4409,10 @@ class HistoryEvent(google.protobuf.message.Message): ) -> google.protobuf.internal.containers.RepeatedCompositeFieldContainer[ temporalio.api.common.v1.message_pb2.Link ]: - """Links associated with the event.""" + """Links to related entities, such as the entity that started this event's workflow.""" + @property + def principal(self) -> temporalio.api.common.v1.message_pb2.Principal: + """Server-computed authenticated caller identity associated with this event.""" @property def workflow_execution_started_event_attributes( self, @@ -4504,6 +4647,10 @@ class HistoryEvent(google.protobuf.message.Message): def workflow_execution_unpaused_event_attributes( self, ) -> global___WorkflowExecutionUnpausedEventAttributes: ... + @property + def workflow_execution_time_skipping_transitioned_event_attributes( + self, + ) -> global___WorkflowExecutionTimeSkippingTransitionedEventAttributes: ... def __init__( self, *, @@ -4517,6 +4664,7 @@ class HistoryEvent(google.protobuf.message.Message): | None = ..., links: collections.abc.Iterable[temporalio.api.common.v1.message_pb2.Link] | None = ..., + principal: temporalio.api.common.v1.message_pb2.Principal | None = ..., workflow_execution_started_event_attributes: global___WorkflowExecutionStartedEventAttributes | None = ..., workflow_execution_completed_event_attributes: global___WorkflowExecutionCompletedEventAttributes @@ -4634,6 +4782,8 @@ class HistoryEvent(google.protobuf.message.Message): | None = ..., workflow_execution_unpaused_event_attributes: global___WorkflowExecutionUnpausedEventAttributes | None = ..., + workflow_execution_time_skipping_transitioned_event_attributes: global___WorkflowExecutionTimeSkippingTransitionedEventAttributes + | None = ..., ) -> None: ... def HasField( self, @@ -4694,6 +4844,8 @@ class HistoryEvent(google.protobuf.message.Message): b"nexus_operation_started_event_attributes", "nexus_operation_timed_out_event_attributes", b"nexus_operation_timed_out_event_attributes", + "principal", + b"principal", "request_cancel_external_workflow_execution_failed_event_attributes", b"request_cancel_external_workflow_execution_failed_event_attributes", "request_cancel_external_workflow_execution_initiated_event_attributes", @@ -4736,6 +4888,8 @@ class HistoryEvent(google.protobuf.message.Message): b"workflow_execution_started_event_attributes", "workflow_execution_terminated_event_attributes", b"workflow_execution_terminated_event_attributes", + "workflow_execution_time_skipping_transitioned_event_attributes", + b"workflow_execution_time_skipping_transitioned_event_attributes", "workflow_execution_timed_out_event_attributes", b"workflow_execution_timed_out_event_attributes", "workflow_execution_unpaused_event_attributes", @@ -4829,6 +4983,8 @@ class HistoryEvent(google.protobuf.message.Message): b"nexus_operation_started_event_attributes", "nexus_operation_timed_out_event_attributes", b"nexus_operation_timed_out_event_attributes", + "principal", + b"principal", "request_cancel_external_workflow_execution_failed_event_attributes", b"request_cancel_external_workflow_execution_failed_event_attributes", "request_cancel_external_workflow_execution_initiated_event_attributes", @@ -4877,6 +5033,8 @@ class HistoryEvent(google.protobuf.message.Message): b"workflow_execution_started_event_attributes", "workflow_execution_terminated_event_attributes", b"workflow_execution_terminated_event_attributes", + "workflow_execution_time_skipping_transitioned_event_attributes", + b"workflow_execution_time_skipping_transitioned_event_attributes", "workflow_execution_timed_out_event_attributes", b"workflow_execution_timed_out_event_attributes", "workflow_execution_unpaused_event_attributes", @@ -4968,6 +5126,7 @@ class HistoryEvent(google.protobuf.message.Message): "nexus_operation_cancel_request_failed_event_attributes", "workflow_execution_paused_event_attributes", "workflow_execution_unpaused_event_attributes", + "workflow_execution_time_skipping_transitioned_event_attributes", ] | None ): ... diff --git a/temporalio/api/nexus/v1/__init__.py b/temporalio/api/nexus/v1/__init__.py index 7ae90d590..b85ea67f4 100644 --- a/temporalio/api/nexus/v1/__init__.py +++ b/temporalio/api/nexus/v1/__init__.py @@ -7,6 +7,9 @@ Failure, HandlerError, Link, + NexusOperationExecutionCancellationInfo, + NexusOperationExecutionInfo, + NexusOperationExecutionListInfo, Request, Response, StartOperationRequest, @@ -23,6 +26,9 @@ "Failure", "HandlerError", "Link", + "NexusOperationExecutionCancellationInfo", + "NexusOperationExecutionInfo", + "NexusOperationExecutionListInfo", "Request", "Response", "StartOperationRequest", diff --git a/temporalio/api/nexus/v1/message_pb2.py b/temporalio/api/nexus/v1/message_pb2.py index 923c6470c..c8cff60b0 100644 --- a/temporalio/api/nexus/v1/message_pb2.py +++ b/temporalio/api/nexus/v1/message_pb2.py @@ -14,20 +14,27 @@ _sym_db = _symbol_database.Default() +from google.protobuf import duration_pb2 as google_dot_protobuf_dot_duration__pb2 from google.protobuf import timestamp_pb2 as google_dot_protobuf_dot_timestamp__pb2 from temporalio.api.common.v1 import ( message_pb2 as temporal_dot_api_dot_common_dot_v1_dot_message__pb2, ) +from temporalio.api.enums.v1 import ( + common_pb2 as temporal_dot_api_dot_enums_dot_v1_dot_common__pb2, +) from temporalio.api.enums.v1 import ( nexus_pb2 as temporal_dot_api_dot_enums_dot_v1_dot_nexus__pb2, ) from temporalio.api.failure.v1 import ( message_pb2 as temporal_dot_api_dot_failure_dot_v1_dot_message__pb2, ) +from temporalio.api.sdk.v1 import ( + user_metadata_pb2 as temporal_dot_api_dot_sdk_dot_v1_dot_user__metadata__pb2, +) DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile( - b'\n#temporal/api/nexus/v1/message.proto\x12\x15temporal.api.nexus.v1\x1a\x1fgoogle/protobuf/timestamp.proto\x1a$temporal/api/common/v1/message.proto\x1a!temporal/api/enums/v1/nexus.proto\x1a%temporal/api/failure/v1/message.proto"\xe0\x01\n\x07\x46\x61ilure\x12\x0f\n\x07message\x18\x01 \x01(\t\x12\x13\n\x0bstack_trace\x18\x04 \x01(\t\x12>\n\x08metadata\x18\x02 \x03(\x0b\x32,.temporal.api.nexus.v1.Failure.MetadataEntry\x12\x0f\n\x07\x64\x65tails\x18\x03 \x01(\x0c\x12-\n\x05\x63\x61use\x18\x05 \x01(\x0b\x32\x1e.temporal.api.nexus.v1.Failure\x1a/\n\rMetadataEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01"\xa2\x01\n\x0cHandlerError\x12\x12\n\nerror_type\x18\x01 \x01(\t\x12/\n\x07\x66\x61ilure\x18\x02 \x01(\x0b\x32\x1e.temporal.api.nexus.v1.Failure\x12M\n\x0eretry_behavior\x18\x03 \x01(\x0e\x32\x35.temporal.api.enums.v1.NexusHandlerErrorRetryBehavior"f\n\x1aUnsuccessfulOperationError\x12\x17\n\x0foperation_state\x18\x01 \x01(\t\x12/\n\x07\x66\x61ilure\x18\x02 \x01(\x0b\x32\x1e.temporal.api.nexus.v1.Failure"!\n\x04Link\x12\x0b\n\x03url\x18\x01 \x01(\t\x12\x0c\n\x04type\x18\x02 \x01(\t"\xd1\x02\n\x15StartOperationRequest\x12\x0f\n\x07service\x18\x01 \x01(\t\x12\x11\n\toperation\x18\x02 \x01(\t\x12\x12\n\nrequest_id\x18\x03 \x01(\t\x12\x10\n\x08\x63\x61llback\x18\x04 \x01(\t\x12\x30\n\x07payload\x18\x05 \x01(\x0b\x32\x1f.temporal.api.common.v1.Payload\x12Y\n\x0f\x63\x61llback_header\x18\x06 \x03(\x0b\x32@.temporal.api.nexus.v1.StartOperationRequest.CallbackHeaderEntry\x12*\n\x05links\x18\x07 \x03(\x0b\x32\x1b.temporal.api.nexus.v1.Link\x1a\x35\n\x13\x43\x61llbackHeaderEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01"o\n\x16\x43\x61ncelOperationRequest\x12\x0f\n\x07service\x18\x01 \x01(\t\x12\x11\n\toperation\x18\x02 \x01(\t\x12\x18\n\x0coperation_id\x18\x03 \x01(\tB\x02\x18\x01\x12\x17\n\x0foperation_token\x18\x04 \x01(\t"\xd0\x03\n\x07Request\x12:\n\x06header\x18\x01 \x03(\x0b\x32*.temporal.api.nexus.v1.Request.HeaderEntry\x12\x32\n\x0escheduled_time\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x41\n\x0c\x63\x61pabilities\x18\x64 \x01(\x0b\x32+.temporal.api.nexus.v1.Request.Capabilities\x12G\n\x0fstart_operation\x18\x03 \x01(\x0b\x32,.temporal.api.nexus.v1.StartOperationRequestH\x00\x12I\n\x10\x63\x61ncel_operation\x18\x04 \x01(\x0b\x32-.temporal.api.nexus.v1.CancelOperationRequestH\x00\x12\x10\n\x08\x65ndpoint\x18\n \x01(\t\x1a\x32\n\x0c\x43\x61pabilities\x12"\n\x1atemporal_failure_responses\x18\x01 \x01(\x08\x1a-\n\x0bHeaderEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x42\t\n\x07variant"\x92\x04\n\x16StartOperationResponse\x12J\n\x0csync_success\x18\x01 \x01(\x0b\x32\x32.temporal.api.nexus.v1.StartOperationResponse.SyncH\x00\x12L\n\rasync_success\x18\x02 \x01(\x0b\x32\x33.temporal.api.nexus.v1.StartOperationResponse.AsyncH\x00\x12P\n\x0foperation_error\x18\x03 \x01(\x0b\x32\x31.temporal.api.nexus.v1.UnsuccessfulOperationErrorB\x02\x18\x01H\x00\x12\x33\n\x07\x66\x61ilure\x18\x04 \x01(\x0b\x32 .temporal.api.failure.v1.FailureH\x00\x1a\x64\n\x04Sync\x12\x30\n\x07payload\x18\x01 \x01(\x0b\x32\x1f.temporal.api.common.v1.Payload\x12*\n\x05links\x18\x02 \x03(\x0b\x32\x1b.temporal.api.nexus.v1.Link\x1a\x66\n\x05\x41sync\x12\x18\n\x0coperation_id\x18\x01 \x01(\tB\x02\x18\x01\x12*\n\x05links\x18\x02 \x03(\x0b\x32\x1b.temporal.api.nexus.v1.Link\x12\x17\n\x0foperation_token\x18\x03 \x01(\tB\t\n\x07variant"\x19\n\x17\x43\x61ncelOperationResponse"\xab\x01\n\x08Response\x12H\n\x0fstart_operation\x18\x01 \x01(\x0b\x32-.temporal.api.nexus.v1.StartOperationResponseH\x00\x12J\n\x10\x63\x61ncel_operation\x18\x02 \x01(\x0b\x32..temporal.api.nexus.v1.CancelOperationResponseH\x00\x42\t\n\x07variant"\xd8\x01\n\x08\x45ndpoint\x12\x0f\n\x07version\x18\x01 \x01(\x03\x12\n\n\x02id\x18\x02 \x01(\t\x12\x31\n\x04spec\x18\x03 \x01(\x0b\x32#.temporal.api.nexus.v1.EndpointSpec\x12\x30\n\x0c\x63reated_time\x18\x04 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x36\n\x12last_modified_time\x18\x05 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x12\n\nurl_prefix\x18\x06 \x01(\t"\x89\x01\n\x0c\x45ndpointSpec\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x34\n\x0b\x64\x65scription\x18\x02 \x01(\x0b\x32\x1f.temporal.api.common.v1.Payload\x12\x35\n\x06target\x18\x03 \x01(\x0b\x32%.temporal.api.nexus.v1.EndpointTarget"\xe9\x01\n\x0e\x45ndpointTarget\x12>\n\x06worker\x18\x01 \x01(\x0b\x32,.temporal.api.nexus.v1.EndpointTarget.WorkerH\x00\x12\x42\n\x08\x65xternal\x18\x02 \x01(\x0b\x32..temporal.api.nexus.v1.EndpointTarget.ExternalH\x00\x1a/\n\x06Worker\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x12\n\ntask_queue\x18\x02 \x01(\t\x1a\x17\n\x08\x45xternal\x12\x0b\n\x03url\x18\x01 \x01(\tB\t\n\x07variantB\x84\x01\n\x18io.temporal.api.nexus.v1B\x0cMessageProtoP\x01Z!go.temporal.io/api/nexus/v1;nexus\xaa\x02\x17Temporalio.Api.Nexus.V1\xea\x02\x1aTemporalio::Api::Nexus::V1b\x06proto3' + b'\n#temporal/api/nexus/v1/message.proto\x12\x15temporal.api.nexus.v1\x1a\x1egoogle/protobuf/duration.proto\x1a\x1fgoogle/protobuf/timestamp.proto\x1a$temporal/api/common/v1/message.proto\x1a"temporal/api/enums/v1/common.proto\x1a!temporal/api/enums/v1/nexus.proto\x1a%temporal/api/failure/v1/message.proto\x1a\'temporal/api/sdk/v1/user_metadata.proto"\xe0\x01\n\x07\x46\x61ilure\x12\x0f\n\x07message\x18\x01 \x01(\t\x12\x13\n\x0bstack_trace\x18\x04 \x01(\t\x12>\n\x08metadata\x18\x02 \x03(\x0b\x32,.temporal.api.nexus.v1.Failure.MetadataEntry\x12\x0f\n\x07\x64\x65tails\x18\x03 \x01(\x0c\x12-\n\x05\x63\x61use\x18\x05 \x01(\x0b\x32\x1e.temporal.api.nexus.v1.Failure\x1a/\n\rMetadataEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01"\xa2\x01\n\x0cHandlerError\x12\x12\n\nerror_type\x18\x01 \x01(\t\x12/\n\x07\x66\x61ilure\x18\x02 \x01(\x0b\x32\x1e.temporal.api.nexus.v1.Failure\x12M\n\x0eretry_behavior\x18\x03 \x01(\x0e\x32\x35.temporal.api.enums.v1.NexusHandlerErrorRetryBehavior"f\n\x1aUnsuccessfulOperationError\x12\x17\n\x0foperation_state\x18\x01 \x01(\t\x12/\n\x07\x66\x61ilure\x18\x02 \x01(\x0b\x32\x1e.temporal.api.nexus.v1.Failure"!\n\x04Link\x12\x0b\n\x03url\x18\x01 \x01(\t\x12\x0c\n\x04type\x18\x02 \x01(\t"\xd1\x02\n\x15StartOperationRequest\x12\x0f\n\x07service\x18\x01 \x01(\t\x12\x11\n\toperation\x18\x02 \x01(\t\x12\x12\n\nrequest_id\x18\x03 \x01(\t\x12\x10\n\x08\x63\x61llback\x18\x04 \x01(\t\x12\x30\n\x07payload\x18\x05 \x01(\x0b\x32\x1f.temporal.api.common.v1.Payload\x12Y\n\x0f\x63\x61llback_header\x18\x06 \x03(\x0b\x32@.temporal.api.nexus.v1.StartOperationRequest.CallbackHeaderEntry\x12*\n\x05links\x18\x07 \x03(\x0b\x32\x1b.temporal.api.nexus.v1.Link\x1a\x35\n\x13\x43\x61llbackHeaderEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01"o\n\x16\x43\x61ncelOperationRequest\x12\x0f\n\x07service\x18\x01 \x01(\t\x12\x11\n\toperation\x18\x02 \x01(\t\x12\x18\n\x0coperation_id\x18\x03 \x01(\tB\x02\x18\x01\x12\x17\n\x0foperation_token\x18\x04 \x01(\t"\xd0\x03\n\x07Request\x12:\n\x06header\x18\x01 \x03(\x0b\x32*.temporal.api.nexus.v1.Request.HeaderEntry\x12\x32\n\x0escheduled_time\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x41\n\x0c\x63\x61pabilities\x18\x64 \x01(\x0b\x32+.temporal.api.nexus.v1.Request.Capabilities\x12G\n\x0fstart_operation\x18\x03 \x01(\x0b\x32,.temporal.api.nexus.v1.StartOperationRequestH\x00\x12I\n\x10\x63\x61ncel_operation\x18\x04 \x01(\x0b\x32-.temporal.api.nexus.v1.CancelOperationRequestH\x00\x12\x10\n\x08\x65ndpoint\x18\n \x01(\t\x1a\x32\n\x0c\x43\x61pabilities\x12"\n\x1atemporal_failure_responses\x18\x01 \x01(\x08\x1a-\n\x0bHeaderEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x42\t\n\x07variant"\x92\x04\n\x16StartOperationResponse\x12J\n\x0csync_success\x18\x01 \x01(\x0b\x32\x32.temporal.api.nexus.v1.StartOperationResponse.SyncH\x00\x12L\n\rasync_success\x18\x02 \x01(\x0b\x32\x33.temporal.api.nexus.v1.StartOperationResponse.AsyncH\x00\x12P\n\x0foperation_error\x18\x03 \x01(\x0b\x32\x31.temporal.api.nexus.v1.UnsuccessfulOperationErrorB\x02\x18\x01H\x00\x12\x33\n\x07\x66\x61ilure\x18\x04 \x01(\x0b\x32 .temporal.api.failure.v1.FailureH\x00\x1a\x64\n\x04Sync\x12\x30\n\x07payload\x18\x01 \x01(\x0b\x32\x1f.temporal.api.common.v1.Payload\x12*\n\x05links\x18\x02 \x03(\x0b\x32\x1b.temporal.api.nexus.v1.Link\x1a\x66\n\x05\x41sync\x12\x18\n\x0coperation_id\x18\x01 \x01(\tB\x02\x18\x01\x12*\n\x05links\x18\x02 \x03(\x0b\x32\x1b.temporal.api.nexus.v1.Link\x12\x17\n\x0foperation_token\x18\x03 \x01(\tB\t\n\x07variant"\x19\n\x17\x43\x61ncelOperationResponse"\xab\x01\n\x08Response\x12H\n\x0fstart_operation\x18\x01 \x01(\x0b\x32-.temporal.api.nexus.v1.StartOperationResponseH\x00\x12J\n\x10\x63\x61ncel_operation\x18\x02 \x01(\x0b\x32..temporal.api.nexus.v1.CancelOperationResponseH\x00\x42\t\n\x07variant"\xd8\x01\n\x08\x45ndpoint\x12\x0f\n\x07version\x18\x01 \x01(\x03\x12\n\n\x02id\x18\x02 \x01(\t\x12\x31\n\x04spec\x18\x03 \x01(\x0b\x32#.temporal.api.nexus.v1.EndpointSpec\x12\x30\n\x0c\x63reated_time\x18\x04 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x36\n\x12last_modified_time\x18\x05 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x12\n\nurl_prefix\x18\x06 \x01(\t"\x89\x01\n\x0c\x45ndpointSpec\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x34\n\x0b\x64\x65scription\x18\x02 \x01(\x0b\x32\x1f.temporal.api.common.v1.Payload\x12\x35\n\x06target\x18\x03 \x01(\x0b\x32%.temporal.api.nexus.v1.EndpointTarget"\xe9\x01\n\x0e\x45ndpointTarget\x12>\n\x06worker\x18\x01 \x01(\x0b\x32,.temporal.api.nexus.v1.EndpointTarget.WorkerH\x00\x12\x42\n\x08\x65xternal\x18\x02 \x01(\x0b\x32..temporal.api.nexus.v1.EndpointTarget.ExternalH\x00\x1a/\n\x06Worker\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x12\n\ntask_queue\x18\x02 \x01(\t\x1a\x17\n\x08\x45xternal\x12\x0b\n\x03url\x18\x01 \x01(\tB\t\n\x07variant"\x9d\x03\n\'NexusOperationExecutionCancellationInfo\x12\x32\n\x0erequested_time\x18\x01 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x45\n\x05state\x18\x02 \x01(\x0e\x32\x36.temporal.api.enums.v1.NexusOperationCancellationState\x12\x0f\n\x07\x61ttempt\x18\x03 \x01(\x05\x12>\n\x1alast_attempt_complete_time\x18\x04 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12>\n\x14last_attempt_failure\x18\x05 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12>\n\x1anext_attempt_schedule_time\x18\x06 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x16\n\x0e\x62locked_reason\x18\x07 \x01(\t\x12\x0e\n\x06reason\x18\x08 \x01(\t"\xe5\n\n\x1bNexusOperationExecutionInfo\x12\x14\n\x0coperation_id\x18\x01 \x01(\t\x12\x0e\n\x06run_id\x18\x02 \x01(\t\x12\x10\n\x08\x65ndpoint\x18\x03 \x01(\t\x12\x0f\n\x07service\x18\x04 \x01(\t\x12\x11\n\toperation\x18\x05 \x01(\t\x12\x44\n\x06status\x18\x06 \x01(\x0e\x32\x34.temporal.api.enums.v1.NexusOperationExecutionStatus\x12@\n\x05state\x18\x07 \x01(\x0e\x32\x31.temporal.api.enums.v1.PendingNexusOperationState\x12<\n\x19schedule_to_close_timeout\x18\x08 \x01(\x0b\x32\x19.google.protobuf.Duration\x12<\n\x19schedule_to_start_timeout\x18\t \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x39\n\x16start_to_close_timeout\x18\n \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x0f\n\x07\x61ttempt\x18\x0b \x01(\x05\x12\x31\n\rschedule_time\x18\x0c \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x33\n\x0f\x65xpiration_time\x18\r \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12.\n\nclose_time\x18\x0e \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12>\n\x1alast_attempt_complete_time\x18\x0f \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12>\n\x14last_attempt_failure\x18\x10 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12>\n\x1anext_attempt_schedule_time\x18\x11 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x35\n\x12\x65xecution_duration\x18\x12 \x01(\x0b\x32\x19.google.protobuf.Duration\x12Y\n\x11\x63\x61ncellation_info\x18\x13 \x01(\x0b\x32>.temporal.api.nexus.v1.NexusOperationExecutionCancellationInfo\x12\x16\n\x0e\x62locked_reason\x18\x14 \x01(\t\x12\x12\n\nrequest_id\x18\x15 \x01(\t\x12\x17\n\x0foperation_token\x18\x16 \x01(\t\x12\x1e\n\x16state_transition_count\x18\x17 \x01(\x03\x12\x43\n\x11search_attributes\x18\x18 \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes\x12Y\n\x0cnexus_header\x18\x19 \x03(\x0b\x32\x43.temporal.api.nexus.v1.NexusOperationExecutionInfo.NexusHeaderEntry\x12\x38\n\ruser_metadata\x18\x1a \x01(\x0b\x32!.temporal.api.sdk.v1.UserMetadata\x12+\n\x05links\x18\x1b \x03(\x0b\x32\x1c.temporal.api.common.v1.Link\x12\x10\n\x08identity\x18\x1c \x01(\t\x1a\x32\n\x10NexusHeaderEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01"\xc2\x03\n\x1fNexusOperationExecutionListInfo\x12\x14\n\x0coperation_id\x18\x01 \x01(\t\x12\x0e\n\x06run_id\x18\x02 \x01(\t\x12\x10\n\x08\x65ndpoint\x18\x03 \x01(\t\x12\x0f\n\x07service\x18\x04 \x01(\t\x12\x11\n\toperation\x18\x05 \x01(\t\x12\x31\n\rschedule_time\x18\x06 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12.\n\nclose_time\x18\x07 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x44\n\x06status\x18\x08 \x01(\x0e\x32\x34.temporal.api.enums.v1.NexusOperationExecutionStatus\x12\x43\n\x11search_attributes\x18\t \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes\x12\x1e\n\x16state_transition_count\x18\n \x01(\x03\x12\x35\n\x12\x65xecution_duration\x18\x0b \x01(\x0b\x32\x19.google.protobuf.DurationB\x84\x01\n\x18io.temporal.api.nexus.v1B\x0cMessageProtoP\x01Z!go.temporal.io/api/nexus/v1;nexus\xaa\x02\x17Temporalio.Api.Nexus.V1\xea\x02\x1aTemporalio::Api::Nexus::V1b\x06proto3' ) @@ -56,6 +63,18 @@ _ENDPOINTTARGET = DESCRIPTOR.message_types_by_name["EndpointTarget"] _ENDPOINTTARGET_WORKER = _ENDPOINTTARGET.nested_types_by_name["Worker"] _ENDPOINTTARGET_EXTERNAL = _ENDPOINTTARGET.nested_types_by_name["External"] +_NEXUSOPERATIONEXECUTIONCANCELLATIONINFO = DESCRIPTOR.message_types_by_name[ + "NexusOperationExecutionCancellationInfo" +] +_NEXUSOPERATIONEXECUTIONINFO = DESCRIPTOR.message_types_by_name[ + "NexusOperationExecutionInfo" +] +_NEXUSOPERATIONEXECUTIONINFO_NEXUSHEADERENTRY = ( + _NEXUSOPERATIONEXECUTIONINFO.nested_types_by_name["NexusHeaderEntry"] +) +_NEXUSOPERATIONEXECUTIONLISTINFO = DESCRIPTOR.message_types_by_name[ + "NexusOperationExecutionListInfo" +] Failure = _reflection.GeneratedProtocolMessageType( "Failure", (_message.Message,), @@ -279,6 +298,49 @@ _sym_db.RegisterMessage(EndpointTarget.Worker) _sym_db.RegisterMessage(EndpointTarget.External) +NexusOperationExecutionCancellationInfo = _reflection.GeneratedProtocolMessageType( + "NexusOperationExecutionCancellationInfo", + (_message.Message,), + { + "DESCRIPTOR": _NEXUSOPERATIONEXECUTIONCANCELLATIONINFO, + "__module__": "temporalio.api.nexus.v1.message_pb2", + # @@protoc_insertion_point(class_scope:temporal.api.nexus.v1.NexusOperationExecutionCancellationInfo) + }, +) +_sym_db.RegisterMessage(NexusOperationExecutionCancellationInfo) + +NexusOperationExecutionInfo = _reflection.GeneratedProtocolMessageType( + "NexusOperationExecutionInfo", + (_message.Message,), + { + "NexusHeaderEntry": _reflection.GeneratedProtocolMessageType( + "NexusHeaderEntry", + (_message.Message,), + { + "DESCRIPTOR": _NEXUSOPERATIONEXECUTIONINFO_NEXUSHEADERENTRY, + "__module__": "temporalio.api.nexus.v1.message_pb2", + # @@protoc_insertion_point(class_scope:temporal.api.nexus.v1.NexusOperationExecutionInfo.NexusHeaderEntry) + }, + ), + "DESCRIPTOR": _NEXUSOPERATIONEXECUTIONINFO, + "__module__": "temporalio.api.nexus.v1.message_pb2", + # @@protoc_insertion_point(class_scope:temporal.api.nexus.v1.NexusOperationExecutionInfo) + }, +) +_sym_db.RegisterMessage(NexusOperationExecutionInfo) +_sym_db.RegisterMessage(NexusOperationExecutionInfo.NexusHeaderEntry) + +NexusOperationExecutionListInfo = _reflection.GeneratedProtocolMessageType( + "NexusOperationExecutionListInfo", + (_message.Message,), + { + "DESCRIPTOR": _NEXUSOPERATIONEXECUTIONLISTINFO, + "__module__": "temporalio.api.nexus.v1.message_pb2", + # @@protoc_insertion_point(class_scope:temporal.api.nexus.v1.NexusOperationExecutionListInfo) + }, +) +_sym_db.RegisterMessage(NexusOperationExecutionListInfo) + if _descriptor._USE_C_DESCRIPTORS == False: DESCRIPTOR._options = None DESCRIPTOR._serialized_options = b"\n\030io.temporal.api.nexus.v1B\014MessageProtoP\001Z!go.temporal.io/api/nexus/v1;nexus\252\002\027Temporalio.Api.Nexus.V1\352\002\032Temporalio::Api::Nexus::V1" @@ -300,46 +362,56 @@ _STARTOPERATIONRESPONSE.fields_by_name[ "operation_error" ]._serialized_options = b"\030\001" - _FAILURE._serialized_start = 208 - _FAILURE._serialized_end = 432 - _FAILURE_METADATAENTRY._serialized_start = 385 - _FAILURE_METADATAENTRY._serialized_end = 432 - _HANDLERERROR._serialized_start = 435 - _HANDLERERROR._serialized_end = 597 - _UNSUCCESSFULOPERATIONERROR._serialized_start = 599 - _UNSUCCESSFULOPERATIONERROR._serialized_end = 701 - _LINK._serialized_start = 703 - _LINK._serialized_end = 736 - _STARTOPERATIONREQUEST._serialized_start = 739 - _STARTOPERATIONREQUEST._serialized_end = 1076 - _STARTOPERATIONREQUEST_CALLBACKHEADERENTRY._serialized_start = 1023 - _STARTOPERATIONREQUEST_CALLBACKHEADERENTRY._serialized_end = 1076 - _CANCELOPERATIONREQUEST._serialized_start = 1078 - _CANCELOPERATIONREQUEST._serialized_end = 1189 - _REQUEST._serialized_start = 1192 - _REQUEST._serialized_end = 1656 - _REQUEST_CAPABILITIES._serialized_start = 1548 - _REQUEST_CAPABILITIES._serialized_end = 1598 - _REQUEST_HEADERENTRY._serialized_start = 1600 - _REQUEST_HEADERENTRY._serialized_end = 1645 - _STARTOPERATIONRESPONSE._serialized_start = 1659 - _STARTOPERATIONRESPONSE._serialized_end = 2189 - _STARTOPERATIONRESPONSE_SYNC._serialized_start = 1974 - _STARTOPERATIONRESPONSE_SYNC._serialized_end = 2074 - _STARTOPERATIONRESPONSE_ASYNC._serialized_start = 2076 - _STARTOPERATIONRESPONSE_ASYNC._serialized_end = 2178 - _CANCELOPERATIONRESPONSE._serialized_start = 2191 - _CANCELOPERATIONRESPONSE._serialized_end = 2216 - _RESPONSE._serialized_start = 2219 - _RESPONSE._serialized_end = 2390 - _ENDPOINT._serialized_start = 2393 - _ENDPOINT._serialized_end = 2609 - _ENDPOINTSPEC._serialized_start = 2612 - _ENDPOINTSPEC._serialized_end = 2749 - _ENDPOINTTARGET._serialized_start = 2752 - _ENDPOINTTARGET._serialized_end = 2985 - _ENDPOINTTARGET_WORKER._serialized_start = 2902 - _ENDPOINTTARGET_WORKER._serialized_end = 2949 - _ENDPOINTTARGET_EXTERNAL._serialized_start = 2951 - _ENDPOINTTARGET_EXTERNAL._serialized_end = 2974 + _NEXUSOPERATIONEXECUTIONINFO_NEXUSHEADERENTRY._options = None + _NEXUSOPERATIONEXECUTIONINFO_NEXUSHEADERENTRY._serialized_options = b"8\001" + _FAILURE._serialized_start = 317 + _FAILURE._serialized_end = 541 + _FAILURE_METADATAENTRY._serialized_start = 494 + _FAILURE_METADATAENTRY._serialized_end = 541 + _HANDLERERROR._serialized_start = 544 + _HANDLERERROR._serialized_end = 706 + _UNSUCCESSFULOPERATIONERROR._serialized_start = 708 + _UNSUCCESSFULOPERATIONERROR._serialized_end = 810 + _LINK._serialized_start = 812 + _LINK._serialized_end = 845 + _STARTOPERATIONREQUEST._serialized_start = 848 + _STARTOPERATIONREQUEST._serialized_end = 1185 + _STARTOPERATIONREQUEST_CALLBACKHEADERENTRY._serialized_start = 1132 + _STARTOPERATIONREQUEST_CALLBACKHEADERENTRY._serialized_end = 1185 + _CANCELOPERATIONREQUEST._serialized_start = 1187 + _CANCELOPERATIONREQUEST._serialized_end = 1298 + _REQUEST._serialized_start = 1301 + _REQUEST._serialized_end = 1765 + _REQUEST_CAPABILITIES._serialized_start = 1657 + _REQUEST_CAPABILITIES._serialized_end = 1707 + _REQUEST_HEADERENTRY._serialized_start = 1709 + _REQUEST_HEADERENTRY._serialized_end = 1754 + _STARTOPERATIONRESPONSE._serialized_start = 1768 + _STARTOPERATIONRESPONSE._serialized_end = 2298 + _STARTOPERATIONRESPONSE_SYNC._serialized_start = 2083 + _STARTOPERATIONRESPONSE_SYNC._serialized_end = 2183 + _STARTOPERATIONRESPONSE_ASYNC._serialized_start = 2185 + _STARTOPERATIONRESPONSE_ASYNC._serialized_end = 2287 + _CANCELOPERATIONRESPONSE._serialized_start = 2300 + _CANCELOPERATIONRESPONSE._serialized_end = 2325 + _RESPONSE._serialized_start = 2328 + _RESPONSE._serialized_end = 2499 + _ENDPOINT._serialized_start = 2502 + _ENDPOINT._serialized_end = 2718 + _ENDPOINTSPEC._serialized_start = 2721 + _ENDPOINTSPEC._serialized_end = 2858 + _ENDPOINTTARGET._serialized_start = 2861 + _ENDPOINTTARGET._serialized_end = 3094 + _ENDPOINTTARGET_WORKER._serialized_start = 3011 + _ENDPOINTTARGET_WORKER._serialized_end = 3058 + _ENDPOINTTARGET_EXTERNAL._serialized_start = 3060 + _ENDPOINTTARGET_EXTERNAL._serialized_end = 3083 + _NEXUSOPERATIONEXECUTIONCANCELLATIONINFO._serialized_start = 3097 + _NEXUSOPERATIONEXECUTIONCANCELLATIONINFO._serialized_end = 3510 + _NEXUSOPERATIONEXECUTIONINFO._serialized_start = 3513 + _NEXUSOPERATIONEXECUTIONINFO._serialized_end = 4894 + _NEXUSOPERATIONEXECUTIONINFO_NEXUSHEADERENTRY._serialized_start = 4844 + _NEXUSOPERATIONEXECUTIONINFO_NEXUSHEADERENTRY._serialized_end = 4894 + _NEXUSOPERATIONEXECUTIONLISTINFO._serialized_start = 4897 + _NEXUSOPERATIONEXECUTIONLISTINFO._serialized_end = 5347 # @@protoc_insertion_point(module_scope) diff --git a/temporalio/api/nexus/v1/message_pb2.pyi b/temporalio/api/nexus/v1/message_pb2.pyi index a85121e2d..f3b5e4d7e 100644 --- a/temporalio/api/nexus/v1/message_pb2.pyi +++ b/temporalio/api/nexus/v1/message_pb2.pyi @@ -8,13 +8,16 @@ import collections.abc import sys import google.protobuf.descriptor +import google.protobuf.duration_pb2 import google.protobuf.internal.containers import google.protobuf.message import google.protobuf.timestamp_pb2 import temporalio.api.common.v1.message_pb2 +import temporalio.api.enums.v1.common_pb2 import temporalio.api.enums.v1.nexus_pb2 import temporalio.api.failure.v1.message_pb2 +import temporalio.api.sdk.v1.user_metadata_pb2 if sys.version_info >= (3, 8): import typing as typing_extensions @@ -829,3 +832,480 @@ class EndpointTarget(google.protobuf.message.Message): ) -> typing_extensions.Literal["worker", "external"] | None: ... global___EndpointTarget = EndpointTarget + +class NexusOperationExecutionCancellationInfo(google.protobuf.message.Message): + """NexusOperationExecutionCancellationInfo contains the state of a Nexus operation cancellation.""" + + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + REQUESTED_TIME_FIELD_NUMBER: builtins.int + STATE_FIELD_NUMBER: builtins.int + ATTEMPT_FIELD_NUMBER: builtins.int + LAST_ATTEMPT_COMPLETE_TIME_FIELD_NUMBER: builtins.int + LAST_ATTEMPT_FAILURE_FIELD_NUMBER: builtins.int + NEXT_ATTEMPT_SCHEDULE_TIME_FIELD_NUMBER: builtins.int + BLOCKED_REASON_FIELD_NUMBER: builtins.int + REASON_FIELD_NUMBER: builtins.int + @property + def requested_time(self) -> google.protobuf.timestamp_pb2.Timestamp: + """The time when cancellation was requested.""" + state: temporalio.api.enums.v1.common_pb2.NexusOperationCancellationState.ValueType + attempt: builtins.int + """The number of attempts made to deliver the cancel operation request. + This number represents a minimum bound since the attempt is incremented after the request completes. + """ + @property + def last_attempt_complete_time(self) -> google.protobuf.timestamp_pb2.Timestamp: + """The time when the last attempt completed.""" + @property + def last_attempt_failure(self) -> temporalio.api.failure.v1.message_pb2.Failure: + """The last attempt's failure, if any.""" + @property + def next_attempt_schedule_time(self) -> google.protobuf.timestamp_pb2.Timestamp: + """The time when the next attempt is scheduled.""" + blocked_reason: builtins.str + """If the state is BLOCKED, blocked reason provides additional information.""" + reason: builtins.str + """A reason that may be specified in the CancelNexusOperationRequest.""" + def __init__( + self, + *, + requested_time: google.protobuf.timestamp_pb2.Timestamp | None = ..., + state: temporalio.api.enums.v1.common_pb2.NexusOperationCancellationState.ValueType = ..., + attempt: builtins.int = ..., + last_attempt_complete_time: google.protobuf.timestamp_pb2.Timestamp + | None = ..., + last_attempt_failure: temporalio.api.failure.v1.message_pb2.Failure + | None = ..., + next_attempt_schedule_time: google.protobuf.timestamp_pb2.Timestamp + | None = ..., + blocked_reason: builtins.str = ..., + reason: builtins.str = ..., + ) -> None: ... + def HasField( + self, + field_name: typing_extensions.Literal[ + "last_attempt_complete_time", + b"last_attempt_complete_time", + "last_attempt_failure", + b"last_attempt_failure", + "next_attempt_schedule_time", + b"next_attempt_schedule_time", + "requested_time", + b"requested_time", + ], + ) -> builtins.bool: ... + def ClearField( + self, + field_name: typing_extensions.Literal[ + "attempt", + b"attempt", + "blocked_reason", + b"blocked_reason", + "last_attempt_complete_time", + b"last_attempt_complete_time", + "last_attempt_failure", + b"last_attempt_failure", + "next_attempt_schedule_time", + b"next_attempt_schedule_time", + "reason", + b"reason", + "requested_time", + b"requested_time", + "state", + b"state", + ], + ) -> None: ... + +global___NexusOperationExecutionCancellationInfo = ( + NexusOperationExecutionCancellationInfo +) + +class NexusOperationExecutionInfo(google.protobuf.message.Message): + """Full current state of a standalone Nexus operation, as of the time of the request.""" + + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + class NexusHeaderEntry(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + KEY_FIELD_NUMBER: builtins.int + VALUE_FIELD_NUMBER: builtins.int + key: builtins.str + value: builtins.str + def __init__( + self, + *, + key: builtins.str = ..., + value: builtins.str = ..., + ) -> None: ... + def ClearField( + self, + field_name: typing_extensions.Literal["key", b"key", "value", b"value"], + ) -> None: ... + + OPERATION_ID_FIELD_NUMBER: builtins.int + RUN_ID_FIELD_NUMBER: builtins.int + ENDPOINT_FIELD_NUMBER: builtins.int + SERVICE_FIELD_NUMBER: builtins.int + OPERATION_FIELD_NUMBER: builtins.int + STATUS_FIELD_NUMBER: builtins.int + STATE_FIELD_NUMBER: builtins.int + SCHEDULE_TO_CLOSE_TIMEOUT_FIELD_NUMBER: builtins.int + SCHEDULE_TO_START_TIMEOUT_FIELD_NUMBER: builtins.int + START_TO_CLOSE_TIMEOUT_FIELD_NUMBER: builtins.int + ATTEMPT_FIELD_NUMBER: builtins.int + SCHEDULE_TIME_FIELD_NUMBER: builtins.int + EXPIRATION_TIME_FIELD_NUMBER: builtins.int + CLOSE_TIME_FIELD_NUMBER: builtins.int + LAST_ATTEMPT_COMPLETE_TIME_FIELD_NUMBER: builtins.int + LAST_ATTEMPT_FAILURE_FIELD_NUMBER: builtins.int + NEXT_ATTEMPT_SCHEDULE_TIME_FIELD_NUMBER: builtins.int + EXECUTION_DURATION_FIELD_NUMBER: builtins.int + CANCELLATION_INFO_FIELD_NUMBER: builtins.int + BLOCKED_REASON_FIELD_NUMBER: builtins.int + REQUEST_ID_FIELD_NUMBER: builtins.int + OPERATION_TOKEN_FIELD_NUMBER: builtins.int + STATE_TRANSITION_COUNT_FIELD_NUMBER: builtins.int + SEARCH_ATTRIBUTES_FIELD_NUMBER: builtins.int + NEXUS_HEADER_FIELD_NUMBER: builtins.int + USER_METADATA_FIELD_NUMBER: builtins.int + LINKS_FIELD_NUMBER: builtins.int + IDENTITY_FIELD_NUMBER: builtins.int + operation_id: builtins.str + """Unique identifier of this Nexus operation within its namespace along with run ID (below).""" + run_id: builtins.str + endpoint: builtins.str + """Endpoint name, resolved to a URL via the cluster's endpoint registry.""" + service: builtins.str + """Service name.""" + operation: builtins.str + """Operation name.""" + status: temporalio.api.enums.v1.nexus_pb2.NexusOperationExecutionStatus.ValueType + """A general status for this operation, indicates whether it is currently running or in one of the terminal statuses. + Updated once when the operation is originally scheduled, and again when it reaches a terminal status. + """ + state: temporalio.api.enums.v1.common_pb2.PendingNexusOperationState.ValueType + """More detailed breakdown of NEXUS_OPERATION_EXECUTION_STATUS_RUNNING.""" + @property + def schedule_to_close_timeout(self) -> google.protobuf.duration_pb2.Duration: + """Schedule-to-close timeout for this operation. + (-- api-linter: core::0140::prepositions=disabled + aip.dev/not-precedent: "to" is used to indicate interval. --) + """ + @property + def schedule_to_start_timeout(self) -> google.protobuf.duration_pb2.Duration: + """Schedule-to-start timeout for this operation. + (-- api-linter: core::0140::prepositions=disabled + aip.dev/not-precedent: "to" is used to indicate interval. --) + """ + @property + def start_to_close_timeout(self) -> google.protobuf.duration_pb2.Duration: + """Start-to-close timeout for this operation. + (-- api-linter: core::0140::prepositions=disabled + aip.dev/not-precedent: "to" is used to indicate interval. --) + """ + attempt: builtins.int + """The number of attempts made to deliver the start operation request. + This number is approximate, it is incremented when a task is added to the history queue. + In practice, there could be more attempts if a task is executed but fails to commit, or less attempts if a task + was never executed. + """ + @property + def schedule_time(self) -> google.protobuf.timestamp_pb2.Timestamp: + """Time the operation was originally scheduled via a StartNexusOperation request.""" + @property + def expiration_time(self) -> google.protobuf.timestamp_pb2.Timestamp: + """Scheduled time + schedule to close timeout.""" + @property + def close_time(self) -> google.protobuf.timestamp_pb2.Timestamp: + """Time when the operation transitioned to a closed state.""" + @property + def last_attempt_complete_time(self) -> google.protobuf.timestamp_pb2.Timestamp: + """The time when the last attempt completed.""" + @property + def last_attempt_failure(self) -> temporalio.api.failure.v1.message_pb2.Failure: + """The last attempt's failure, if any.""" + @property + def next_attempt_schedule_time(self) -> google.protobuf.timestamp_pb2.Timestamp: + """The time when the next attempt is scheduled.""" + @property + def execution_duration(self) -> google.protobuf.duration_pb2.Duration: + """Elapsed time from schedule_time to now for running operations or to close_time for closed + operations, including all attempts and backoff between attempts. + """ + @property + def cancellation_info(self) -> global___NexusOperationExecutionCancellationInfo: ... + blocked_reason: builtins.str + """If the state is BLOCKED, blocked reason provides additional information.""" + request_id: builtins.str + """Server-generated request ID used as an idempotency token when submitting start requests to + the handler. Distinct from the request_id in StartNexusOperationRequest, which is the + caller-side idempotency key for the StartNexusOperation RPC itself. + """ + operation_token: builtins.str + """Operation token. Only set for asynchronous operations after a successful StartOperation call.""" + state_transition_count: builtins.int + """Incremented each time the operation's state is mutated in persistence.""" + @property + def search_attributes( + self, + ) -> temporalio.api.common.v1.message_pb2.SearchAttributes: ... + @property + def nexus_header( + self, + ) -> google.protobuf.internal.containers.ScalarMap[builtins.str, builtins.str]: + """Header for context propagation and tracing purposes.""" + @property + def user_metadata(self) -> temporalio.api.sdk.v1.user_metadata_pb2.UserMetadata: + """Metadata for use by user interfaces to display the fixed as-of-start summary and details of the operation.""" + @property + def links( + self, + ) -> google.protobuf.internal.containers.RepeatedCompositeFieldContainer[ + temporalio.api.common.v1.message_pb2.Link + ]: + """Links attached by the handler of this operation on start or completion.""" + identity: builtins.str + """The identity of the client who started this operation.""" + def __init__( + self, + *, + operation_id: builtins.str = ..., + run_id: builtins.str = ..., + endpoint: builtins.str = ..., + service: builtins.str = ..., + operation: builtins.str = ..., + status: temporalio.api.enums.v1.nexus_pb2.NexusOperationExecutionStatus.ValueType = ..., + state: temporalio.api.enums.v1.common_pb2.PendingNexusOperationState.ValueType = ..., + schedule_to_close_timeout: google.protobuf.duration_pb2.Duration | None = ..., + schedule_to_start_timeout: google.protobuf.duration_pb2.Duration | None = ..., + start_to_close_timeout: google.protobuf.duration_pb2.Duration | None = ..., + attempt: builtins.int = ..., + schedule_time: google.protobuf.timestamp_pb2.Timestamp | None = ..., + expiration_time: google.protobuf.timestamp_pb2.Timestamp | None = ..., + close_time: google.protobuf.timestamp_pb2.Timestamp | None = ..., + last_attempt_complete_time: google.protobuf.timestamp_pb2.Timestamp + | None = ..., + last_attempt_failure: temporalio.api.failure.v1.message_pb2.Failure + | None = ..., + next_attempt_schedule_time: google.protobuf.timestamp_pb2.Timestamp + | None = ..., + execution_duration: google.protobuf.duration_pb2.Duration | None = ..., + cancellation_info: global___NexusOperationExecutionCancellationInfo + | None = ..., + blocked_reason: builtins.str = ..., + request_id: builtins.str = ..., + operation_token: builtins.str = ..., + state_transition_count: builtins.int = ..., + search_attributes: temporalio.api.common.v1.message_pb2.SearchAttributes + | None = ..., + nexus_header: collections.abc.Mapping[builtins.str, builtins.str] | None = ..., + user_metadata: temporalio.api.sdk.v1.user_metadata_pb2.UserMetadata + | None = ..., + links: collections.abc.Iterable[temporalio.api.common.v1.message_pb2.Link] + | None = ..., + identity: builtins.str = ..., + ) -> None: ... + def HasField( + self, + field_name: typing_extensions.Literal[ + "cancellation_info", + b"cancellation_info", + "close_time", + b"close_time", + "execution_duration", + b"execution_duration", + "expiration_time", + b"expiration_time", + "last_attempt_complete_time", + b"last_attempt_complete_time", + "last_attempt_failure", + b"last_attempt_failure", + "next_attempt_schedule_time", + b"next_attempt_schedule_time", + "schedule_time", + b"schedule_time", + "schedule_to_close_timeout", + b"schedule_to_close_timeout", + "schedule_to_start_timeout", + b"schedule_to_start_timeout", + "search_attributes", + b"search_attributes", + "start_to_close_timeout", + b"start_to_close_timeout", + "user_metadata", + b"user_metadata", + ], + ) -> builtins.bool: ... + def ClearField( + self, + field_name: typing_extensions.Literal[ + "attempt", + b"attempt", + "blocked_reason", + b"blocked_reason", + "cancellation_info", + b"cancellation_info", + "close_time", + b"close_time", + "endpoint", + b"endpoint", + "execution_duration", + b"execution_duration", + "expiration_time", + b"expiration_time", + "identity", + b"identity", + "last_attempt_complete_time", + b"last_attempt_complete_time", + "last_attempt_failure", + b"last_attempt_failure", + "links", + b"links", + "next_attempt_schedule_time", + b"next_attempt_schedule_time", + "nexus_header", + b"nexus_header", + "operation", + b"operation", + "operation_id", + b"operation_id", + "operation_token", + b"operation_token", + "request_id", + b"request_id", + "run_id", + b"run_id", + "schedule_time", + b"schedule_time", + "schedule_to_close_timeout", + b"schedule_to_close_timeout", + "schedule_to_start_timeout", + b"schedule_to_start_timeout", + "search_attributes", + b"search_attributes", + "service", + b"service", + "start_to_close_timeout", + b"start_to_close_timeout", + "state", + b"state", + "state_transition_count", + b"state_transition_count", + "status", + b"status", + "user_metadata", + b"user_metadata", + ], + ) -> None: ... + +global___NexusOperationExecutionInfo = NexusOperationExecutionInfo + +class NexusOperationExecutionListInfo(google.protobuf.message.Message): + """Limited Nexus operation information returned in the list response. + When adding fields here, ensure that it is also present in NexusOperationExecutionInfo (note that it may already be present in + NexusOperationExecutionInfo but not at the top-level). + """ + + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + OPERATION_ID_FIELD_NUMBER: builtins.int + RUN_ID_FIELD_NUMBER: builtins.int + ENDPOINT_FIELD_NUMBER: builtins.int + SERVICE_FIELD_NUMBER: builtins.int + OPERATION_FIELD_NUMBER: builtins.int + SCHEDULE_TIME_FIELD_NUMBER: builtins.int + CLOSE_TIME_FIELD_NUMBER: builtins.int + STATUS_FIELD_NUMBER: builtins.int + SEARCH_ATTRIBUTES_FIELD_NUMBER: builtins.int + STATE_TRANSITION_COUNT_FIELD_NUMBER: builtins.int + EXECUTION_DURATION_FIELD_NUMBER: builtins.int + operation_id: builtins.str + """A unique identifier of this operation within its namespace along with run ID (below).""" + run_id: builtins.str + """The run ID of the standalone Nexus operation.""" + endpoint: builtins.str + """Endpoint name.""" + service: builtins.str + """Service name.""" + operation: builtins.str + """Operation name.""" + @property + def schedule_time(self) -> google.protobuf.timestamp_pb2.Timestamp: + """Time the operation was originally scheduled via a StartNexusOperation request.""" + @property + def close_time(self) -> google.protobuf.timestamp_pb2.Timestamp: + """If the operation is in a terminal status, this field represents the time the operation transitioned to that status.""" + status: temporalio.api.enums.v1.nexus_pb2.NexusOperationExecutionStatus.ValueType + """The status is updated once, when the operation is originally scheduled, and again when the operation reaches a terminal status.""" + @property + def search_attributes( + self, + ) -> temporalio.api.common.v1.message_pb2.SearchAttributes: + """Search attributes from the start request.""" + state_transition_count: builtins.int + """Updated on terminal status.""" + @property + def execution_duration(self) -> google.protobuf.duration_pb2.Duration: + """The difference between close time and scheduled time. + This field is only populated if the operation is closed. + """ + def __init__( + self, + *, + operation_id: builtins.str = ..., + run_id: builtins.str = ..., + endpoint: builtins.str = ..., + service: builtins.str = ..., + operation: builtins.str = ..., + schedule_time: google.protobuf.timestamp_pb2.Timestamp | None = ..., + close_time: google.protobuf.timestamp_pb2.Timestamp | None = ..., + status: temporalio.api.enums.v1.nexus_pb2.NexusOperationExecutionStatus.ValueType = ..., + search_attributes: temporalio.api.common.v1.message_pb2.SearchAttributes + | None = ..., + state_transition_count: builtins.int = ..., + execution_duration: google.protobuf.duration_pb2.Duration | None = ..., + ) -> None: ... + def HasField( + self, + field_name: typing_extensions.Literal[ + "close_time", + b"close_time", + "execution_duration", + b"execution_duration", + "schedule_time", + b"schedule_time", + "search_attributes", + b"search_attributes", + ], + ) -> builtins.bool: ... + def ClearField( + self, + field_name: typing_extensions.Literal[ + "close_time", + b"close_time", + "endpoint", + b"endpoint", + "execution_duration", + b"execution_duration", + "operation", + b"operation", + "operation_id", + b"operation_id", + "run_id", + b"run_id", + "schedule_time", + b"schedule_time", + "search_attributes", + b"search_attributes", + "service", + b"service", + "state_transition_count", + b"state_transition_count", + "status", + b"status", + ], + ) -> None: ... + +global___NexusOperationExecutionListInfo = NexusOperationExecutionListInfo diff --git a/temporalio/api/nexusservices/__init__.py b/temporalio/api/nexusservices/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/temporalio/api/nexusservices/workerservice/__init__.py b/temporalio/api/nexusservices/workerservice/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/temporalio/api/nexusservices/workerservice/v1/__init__.py b/temporalio/api/nexusservices/workerservice/v1/__init__.py new file mode 100644 index 000000000..0b9e4a6ca --- /dev/null +++ b/temporalio/api/nexusservices/workerservice/v1/__init__.py @@ -0,0 +1,6 @@ +from .request_response_pb2 import ExecuteCommandsRequest, ExecuteCommandsResponse + +__all__ = [ + "ExecuteCommandsRequest", + "ExecuteCommandsResponse", +] diff --git a/temporalio/api/nexusservices/workerservice/v1/request_response_pb2.py b/temporalio/api/nexusservices/workerservice/v1/request_response_pb2.py new file mode 100644 index 000000000..ed045767d --- /dev/null +++ b/temporalio/api/nexusservices/workerservice/v1/request_response_pb2.py @@ -0,0 +1,57 @@ +# -*- coding: utf-8 -*- +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: temporal/api/nexusservices/workerservice/v1/request_response.proto +"""Generated protocol buffer code.""" + +from google.protobuf import descriptor as _descriptor +from google.protobuf import descriptor_pool as _descriptor_pool +from google.protobuf import message as _message +from google.protobuf import reflection as _reflection +from google.protobuf import symbol_database as _symbol_database + +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + +from temporalio.api.worker.v1 import ( + message_pb2 as temporal_dot_api_dot_worker_dot_v1_dot_message__pb2, +) + +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile( + b'\nBtemporal/api/nexusservices/workerservice/v1/request_response.proto\x12+temporal.api.nexusservices.workerservice.v1\x1a$temporal/api/worker/v1/message.proto"Q\n\x16\x45xecuteCommandsRequest\x12\x37\n\x08\x63ommands\x18\x01 \x03(\x0b\x32%.temporal.api.worker.v1.WorkerCommand"W\n\x17\x45xecuteCommandsResponse\x12<\n\x07results\x18\x01 \x03(\x0b\x32+.temporal.api.worker.v1.WorkerCommandResultB\xed\x01\n.io.temporal.api.nexusservices.workerservice.v1B\x14RequestResponseProtoP\x01Z?go.temporal.io/api/nexusservices/workerservice/v1;workerservice\xaa\x02-Temporalio.Api.Nexusservices.Workerservice.V1\xea\x02\x31Temporalio::Api::Nexusservices::Workerservice::V1b\x06proto3' +) + + +_EXECUTECOMMANDSREQUEST = DESCRIPTOR.message_types_by_name["ExecuteCommandsRequest"] +_EXECUTECOMMANDSRESPONSE = DESCRIPTOR.message_types_by_name["ExecuteCommandsResponse"] +ExecuteCommandsRequest = _reflection.GeneratedProtocolMessageType( + "ExecuteCommandsRequest", + (_message.Message,), + { + "DESCRIPTOR": _EXECUTECOMMANDSREQUEST, + "__module__": "temporalio.api.nexusservices.workerservice.v1.request_response_pb2", + # @@protoc_insertion_point(class_scope:temporal.api.nexusservices.workerservice.v1.ExecuteCommandsRequest) + }, +) +_sym_db.RegisterMessage(ExecuteCommandsRequest) + +ExecuteCommandsResponse = _reflection.GeneratedProtocolMessageType( + "ExecuteCommandsResponse", + (_message.Message,), + { + "DESCRIPTOR": _EXECUTECOMMANDSRESPONSE, + "__module__": "temporalio.api.nexusservices.workerservice.v1.request_response_pb2", + # @@protoc_insertion_point(class_scope:temporal.api.nexusservices.workerservice.v1.ExecuteCommandsResponse) + }, +) +_sym_db.RegisterMessage(ExecuteCommandsResponse) + +if _descriptor._USE_C_DESCRIPTORS == False: + DESCRIPTOR._options = None + DESCRIPTOR._serialized_options = b"\n.io.temporal.api.nexusservices.workerservice.v1B\024RequestResponseProtoP\001Z?go.temporal.io/api/nexusservices/workerservice/v1;workerservice\252\002-Temporalio.Api.Nexusservices.Workerservice.V1\352\0021Temporalio::Api::Nexusservices::Workerservice::V1" + _EXECUTECOMMANDSREQUEST._serialized_start = 153 + _EXECUTECOMMANDSREQUEST._serialized_end = 234 + _EXECUTECOMMANDSRESPONSE._serialized_start = 236 + _EXECUTECOMMANDSRESPONSE._serialized_end = 323 +# @@protoc_insertion_point(module_scope) diff --git a/temporalio/api/nexusservices/workerservice/v1/request_response_pb2.pyi b/temporalio/api/nexusservices/workerservice/v1/request_response_pb2.pyi new file mode 100644 index 000000000..8fd328cb8 --- /dev/null +++ b/temporalio/api/nexusservices/workerservice/v1/request_response_pb2.pyi @@ -0,0 +1,80 @@ +""" +@generated by mypy-protobuf. Do not edit manually! +isort:skip_file +""" + +import builtins +import collections.abc +import sys + +import google.protobuf.descriptor +import google.protobuf.internal.containers +import google.protobuf.message + +import temporalio.api.worker.v1.message_pb2 + +if sys.version_info >= (3, 8): + import typing as typing_extensions +else: + import typing_extensions + +DESCRIPTOR: google.protobuf.descriptor.FileDescriptor + +class ExecuteCommandsRequest(google.protobuf.message.Message): + """(-- + Internal Nexus service for server-to-worker communication. + --) + + Request payload for the "ExecuteCommands" Nexus operation. + """ + + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + COMMANDS_FIELD_NUMBER: builtins.int + @property + def commands( + self, + ) -> google.protobuf.internal.containers.RepeatedCompositeFieldContainer[ + temporalio.api.worker.v1.message_pb2.WorkerCommand + ]: ... + def __init__( + self, + *, + commands: collections.abc.Iterable[ + temporalio.api.worker.v1.message_pb2.WorkerCommand + ] + | None = ..., + ) -> None: ... + def ClearField( + self, field_name: typing_extensions.Literal["commands", b"commands"] + ) -> None: ... + +global___ExecuteCommandsRequest = ExecuteCommandsRequest + +class ExecuteCommandsResponse(google.protobuf.message.Message): + """Response payload for the "ExecuteCommands" Nexus operation. + The results list must be 1:1 with the commands list in the request (same size and order). + """ + + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + RESULTS_FIELD_NUMBER: builtins.int + @property + def results( + self, + ) -> google.protobuf.internal.containers.RepeatedCompositeFieldContainer[ + temporalio.api.worker.v1.message_pb2.WorkerCommandResult + ]: ... + def __init__( + self, + *, + results: collections.abc.Iterable[ + temporalio.api.worker.v1.message_pb2.WorkerCommandResult + ] + | None = ..., + ) -> None: ... + def ClearField( + self, field_name: typing_extensions.Literal["results", b"results"] + ) -> None: ... + +global___ExecuteCommandsResponse = ExecuteCommandsResponse diff --git a/temporalio/api/nexusservices/workerservice/v1/request_response_pb2_grpc.py b/temporalio/api/nexusservices/workerservice/v1/request_response_pb2_grpc.py new file mode 100644 index 000000000..bf947056a --- /dev/null +++ b/temporalio/api/nexusservices/workerservice/v1/request_response_pb2_grpc.py @@ -0,0 +1,4 @@ +# Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT! +"""Client and server classes corresponding to protobuf-defined services.""" + +import grpc diff --git a/temporalio/api/nexusservices/workerservice/v1/request_response_pb2_grpc.pyi b/temporalio/api/nexusservices/workerservice/v1/request_response_pb2_grpc.pyi new file mode 100644 index 000000000..f3a5a087e --- /dev/null +++ b/temporalio/api/nexusservices/workerservice/v1/request_response_pb2_grpc.pyi @@ -0,0 +1,4 @@ +""" +@generated by mypy-protobuf. Do not edit manually! +isort:skip_file +""" diff --git a/temporalio/api/sdk/v1/__init__.py b/temporalio/api/sdk/v1/__init__.py index 2657df300..0a72fe5cf 100644 --- a/temporalio/api/sdk/v1/__init__.py +++ b/temporalio/api/sdk/v1/__init__.py @@ -5,6 +5,7 @@ StackTraceFileSlice, StackTraceSDKInfo, ) +from .external_storage_pb2 import ExternalStorageReference from .task_complete_metadata_pb2 import WorkflowTaskCompletedMetadata from .user_metadata_pb2 import UserMetadata from .worker_config_pb2 import WorkerConfig @@ -16,6 +17,7 @@ __all__ = [ "EnhancedStackTrace", + "ExternalStorageReference", "StackTrace", "StackTraceFileLocation", "StackTraceFileSlice", diff --git a/temporalio/api/sdk/v1/external_storage_pb2.py b/temporalio/api/sdk/v1/external_storage_pb2.py new file mode 100644 index 000000000..75676a90a --- /dev/null +++ b/temporalio/api/sdk/v1/external_storage_pb2.py @@ -0,0 +1,56 @@ +# -*- coding: utf-8 -*- +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: temporal/api/sdk/v1/external_storage.proto +"""Generated protocol buffer code.""" + +from google.protobuf import descriptor as _descriptor +from google.protobuf import descriptor_pool as _descriptor_pool +from google.protobuf import message as _message +from google.protobuf import reflection as _reflection +from google.protobuf import symbol_database as _symbol_database + +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile( + b'\n*temporal/api/sdk/v1/external_storage.proto\x12\x13temporal.api.sdk.v1"\xb3\x01\n\x18\x45xternalStorageReference\x12\x13\n\x0b\x64river_name\x18\x01 \x01(\t\x12P\n\nclaim_data\x18\x02 \x03(\x0b\x32<.temporal.api.sdk.v1.ExternalStorageReference.ClaimDataEntry\x1a\x30\n\x0e\x43laimDataEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x42\x82\x01\n\x16io.temporal.api.sdk.v1B\x14\x45xternalStorageProtoP\x01Z\x1dgo.temporal.io/api/sdk/v1;sdk\xaa\x02\x15Temporalio.Api.Sdk.V1\xea\x02\x18Temporalio::Api::Sdk::V1b\x06proto3' +) + + +_EXTERNALSTORAGEREFERENCE = DESCRIPTOR.message_types_by_name["ExternalStorageReference"] +_EXTERNALSTORAGEREFERENCE_CLAIMDATAENTRY = ( + _EXTERNALSTORAGEREFERENCE.nested_types_by_name["ClaimDataEntry"] +) +ExternalStorageReference = _reflection.GeneratedProtocolMessageType( + "ExternalStorageReference", + (_message.Message,), + { + "ClaimDataEntry": _reflection.GeneratedProtocolMessageType( + "ClaimDataEntry", + (_message.Message,), + { + "DESCRIPTOR": _EXTERNALSTORAGEREFERENCE_CLAIMDATAENTRY, + "__module__": "temporalio.api.sdk.v1.external_storage_pb2", + # @@protoc_insertion_point(class_scope:temporal.api.sdk.v1.ExternalStorageReference.ClaimDataEntry) + }, + ), + "DESCRIPTOR": _EXTERNALSTORAGEREFERENCE, + "__module__": "temporalio.api.sdk.v1.external_storage_pb2", + # @@protoc_insertion_point(class_scope:temporal.api.sdk.v1.ExternalStorageReference) + }, +) +_sym_db.RegisterMessage(ExternalStorageReference) +_sym_db.RegisterMessage(ExternalStorageReference.ClaimDataEntry) + +if _descriptor._USE_C_DESCRIPTORS == False: + DESCRIPTOR._options = None + DESCRIPTOR._serialized_options = b"\n\026io.temporal.api.sdk.v1B\024ExternalStorageProtoP\001Z\035go.temporal.io/api/sdk/v1;sdk\252\002\025Temporalio.Api.Sdk.V1\352\002\030Temporalio::Api::Sdk::V1" + _EXTERNALSTORAGEREFERENCE_CLAIMDATAENTRY._options = None + _EXTERNALSTORAGEREFERENCE_CLAIMDATAENTRY._serialized_options = b"8\001" + _EXTERNALSTORAGEREFERENCE._serialized_start = 68 + _EXTERNALSTORAGEREFERENCE._serialized_end = 247 + _EXTERNALSTORAGEREFERENCE_CLAIMDATAENTRY._serialized_start = 199 + _EXTERNALSTORAGEREFERENCE_CLAIMDATAENTRY._serialized_end = 247 +# @@protoc_insertion_point(module_scope) diff --git a/temporalio/api/sdk/v1/external_storage_pb2.pyi b/temporalio/api/sdk/v1/external_storage_pb2.pyi new file mode 100644 index 000000000..9a27636a2 --- /dev/null +++ b/temporalio/api/sdk/v1/external_storage_pb2.pyi @@ -0,0 +1,69 @@ +""" +@generated by mypy-protobuf. Do not edit manually! +isort:skip_file +""" + +import builtins +import collections.abc +import sys + +import google.protobuf.descriptor +import google.protobuf.internal.containers +import google.protobuf.message + +if sys.version_info >= (3, 8): + import typing as typing_extensions +else: + import typing_extensions + +DESCRIPTOR: google.protobuf.descriptor.FileDescriptor + +class ExternalStorageReference(google.protobuf.message.Message): + """ExternalStorageReference identifies a payload stored in an external storage system. + It is used as a claim-check token, allowing the actual payload data to be retrieved + from the named driver using the provided claim data. + """ + + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + class ClaimDataEntry(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + KEY_FIELD_NUMBER: builtins.int + VALUE_FIELD_NUMBER: builtins.int + key: builtins.str + value: builtins.str + def __init__( + self, + *, + key: builtins.str = ..., + value: builtins.str = ..., + ) -> None: ... + def ClearField( + self, + field_name: typing_extensions.Literal["key", b"key", "value", b"value"], + ) -> None: ... + + DRIVER_NAME_FIELD_NUMBER: builtins.int + CLAIM_DATA_FIELD_NUMBER: builtins.int + driver_name: builtins.str + """The name of the storage driver responsible for retrieving the payload.""" + @property + def claim_data( + self, + ) -> google.protobuf.internal.containers.ScalarMap[builtins.str, builtins.str]: + """Driver-specific key-value pairs that identify and provide access to the stored payload.""" + def __init__( + self, + *, + driver_name: builtins.str = ..., + claim_data: collections.abc.Mapping[builtins.str, builtins.str] | None = ..., + ) -> None: ... + def ClearField( + self, + field_name: typing_extensions.Literal[ + "claim_data", b"claim_data", "driver_name", b"driver_name" + ], + ) -> None: ... + +global___ExternalStorageReference = ExternalStorageReference diff --git a/temporalio/api/taskqueue/v1/__init__.py b/temporalio/api/taskqueue/v1/__init__.py index 888c7ff2a..dac573696 100644 --- a/temporalio/api/taskqueue/v1/__init__.py +++ b/temporalio/api/taskqueue/v1/__init__.py @@ -4,6 +4,7 @@ CompatibleBuildIdRedirectRule, CompatibleVersionSet, ConfigMetadata, + PollerGroupInfo, PollerInfo, PollerScalingDecision, RampByPercentage, @@ -32,6 +33,7 @@ "CompatibleBuildIdRedirectRule", "CompatibleVersionSet", "ConfigMetadata", + "PollerGroupInfo", "PollerInfo", "PollerScalingDecision", "RampByPercentage", diff --git a/temporalio/api/taskqueue/v1/message_pb2.py b/temporalio/api/taskqueue/v1/message_pb2.py index 59c8a487b..bf0eab1d0 100644 --- a/temporalio/api/taskqueue/v1/message_pb2.py +++ b/temporalio/api/taskqueue/v1/message_pb2.py @@ -29,7 +29,7 @@ ) DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile( - b'\n\'temporal/api/taskqueue/v1/message.proto\x12\x19temporal.api.taskqueue.v1\x1a\x1egoogle/protobuf/duration.proto\x1a\x1fgoogle/protobuf/timestamp.proto\x1a\x1egoogle/protobuf/wrappers.proto\x1a&temporal/api/enums/v1/task_queue.proto\x1a$temporal/api/common/v1/message.proto\x1a(temporal/api/deployment/v1/message.proto"b\n\tTaskQueue\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x32\n\x04kind\x18\x02 \x01(\x0e\x32$.temporal.api.enums.v1.TaskQueueKind\x12\x13\n\x0bnormal_name\x18\x03 \x01(\t"O\n\x11TaskQueueMetadata\x12:\n\x14max_tasks_per_second\x18\x01 \x01(\x0b\x32\x1c.google.protobuf.DoubleValue"\xda\x02\n\x17TaskQueueVersioningInfo\x12W\n\x1a\x63urrent_deployment_version\x18\x07 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersion\x12\x1b\n\x0f\x63urrent_version\x18\x01 \x01(\tB\x02\x18\x01\x12W\n\x1aramping_deployment_version\x18\t \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersion\x12\x1b\n\x0framping_version\x18\x02 \x01(\tB\x02\x18\x01\x12"\n\x1aramping_version_percentage\x18\x03 \x01(\x02\x12/\n\x0bupdate_time\x18\x04 \x01(\x0b\x32\x1a.google.protobuf.Timestamp"W\n\x19TaskQueueVersionSelection\x12\x11\n\tbuild_ids\x18\x01 \x03(\t\x12\x13\n\x0bunversioned\x18\x02 \x01(\x08\x12\x12\n\nall_active\x18\x03 \x01(\x08"\x95\x02\n\x14TaskQueueVersionInfo\x12R\n\ntypes_info\x18\x01 \x03(\x0b\x32>.temporal.api.taskqueue.v1.TaskQueueVersionInfo.TypesInfoEntry\x12I\n\x11task_reachability\x18\x02 \x01(\x0e\x32..temporal.api.enums.v1.BuildIdTaskReachability\x1a^\n\x0eTypesInfoEntry\x12\x0b\n\x03key\x18\x01 \x01(\x05\x12;\n\x05value\x18\x02 \x01(\x0b\x32,.temporal.api.taskqueue.v1.TaskQueueTypeInfo:\x02\x38\x01"\x85\x01\n\x11TaskQueueTypeInfo\x12\x36\n\x07pollers\x18\x01 \x03(\x0b\x32%.temporal.api.taskqueue.v1.PollerInfo\x12\x38\n\x05stats\x18\x02 \x01(\x0b\x32).temporal.api.taskqueue.v1.TaskQueueStats"\xa4\x01\n\x0eTaskQueueStats\x12!\n\x19\x61pproximate_backlog_count\x18\x01 \x01(\x03\x12:\n\x17\x61pproximate_backlog_age\x18\x02 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x16\n\x0etasks_add_rate\x18\x03 \x01(\x02\x12\x1b\n\x13tasks_dispatch_rate\x18\x04 \x01(\x02"\xac\x01\n\x0fTaskQueueStatus\x12\x1a\n\x12\x62\x61\x63klog_count_hint\x18\x01 \x01(\x03\x12\x12\n\nread_level\x18\x02 \x01(\x03\x12\x11\n\tack_level\x18\x03 \x01(\x03\x12\x17\n\x0frate_per_second\x18\x04 \x01(\x01\x12=\n\rtask_id_block\x18\x05 \x01(\x0b\x32&.temporal.api.taskqueue.v1.TaskIdBlock"/\n\x0bTaskIdBlock\x12\x10\n\x08start_id\x18\x01 \x01(\x03\x12\x0e\n\x06\x65nd_id\x18\x02 \x01(\x03"B\n\x1aTaskQueuePartitionMetadata\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x17\n\x0fowner_host_name\x18\x02 \x01(\t"\x9a\x02\n\nPollerInfo\x12\x34\n\x10last_access_time\x18\x01 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x10\n\x08identity\x18\x02 \x01(\t\x12\x17\n\x0frate_per_second\x18\x03 \x01(\x01\x12Z\n\x1bworker_version_capabilities\x18\x04 \x01(\x0b\x32\x31.temporal.api.common.v1.WorkerVersionCapabilitiesB\x02\x18\x01\x12O\n\x12\x64\x65ployment_options\x18\x05 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentOptions"\x9a\x01\n\x19StickyExecutionAttributes\x12?\n\x11worker_task_queue\x18\x01 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12<\n\x19schedule_to_start_timeout\x18\x02 \x01(\x0b\x32\x19.google.protobuf.Duration")\n\x14\x43ompatibleVersionSet\x12\x11\n\tbuild_ids\x18\x01 \x03(\t"j\n\x15TaskQueueReachability\x12\x12\n\ntask_queue\x18\x01 \x01(\t\x12=\n\x0creachability\x18\x02 \x03(\x0e\x32\'.temporal.api.enums.v1.TaskReachability"z\n\x13\x42uildIdReachability\x12\x10\n\x08\x62uild_id\x18\x01 \x01(\t\x12Q\n\x17task_queue_reachability\x18\x02 \x03(\x0b\x32\x30.temporal.api.taskqueue.v1.TaskQueueReachability"+\n\x10RampByPercentage\x12\x17\n\x0framp_percentage\x18\x01 \x01(\x02"\x80\x01\n\x15\x42uildIdAssignmentRule\x12\x17\n\x0ftarget_build_id\x18\x01 \x01(\t\x12\x46\n\x0fpercentage_ramp\x18\x03 \x01(\x0b\x32+.temporal.api.taskqueue.v1.RampByPercentageH\x00\x42\x06\n\x04ramp"Q\n\x1d\x43ompatibleBuildIdRedirectRule\x12\x17\n\x0fsource_build_id\x18\x01 \x01(\t\x12\x17\n\x0ftarget_build_id\x18\x02 \x01(\t"\x93\x01\n TimestampedBuildIdAssignmentRule\x12>\n\x04rule\x18\x01 \x01(\x0b\x32\x30.temporal.api.taskqueue.v1.BuildIdAssignmentRule\x12/\n\x0b\x63reate_time\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.Timestamp"\xa3\x01\n(TimestampedCompatibleBuildIdRedirectRule\x12\x46\n\x04rule\x18\x01 \x01(\x0b\x32\x38.temporal.api.taskqueue.v1.CompatibleBuildIdRedirectRule\x12/\n\x0b\x63reate_time\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.Timestamp">\n\x15PollerScalingDecision\x12%\n\x1dpoll_request_delta_suggestion\x18\x01 \x01(\x05"(\n\tRateLimit\x12\x1b\n\x13requests_per_second\x18\x01 \x01(\x02"j\n\x0e\x43onfigMetadata\x12\x0e\n\x06reason\x18\x01 \x01(\t\x12\x17\n\x0fupdate_identity\x18\x02 \x01(\t\x12/\n\x0bupdate_time\x18\x03 \x01(\x0b\x32\x1a.google.protobuf.Timestamp"\x88\x01\n\x0fRateLimitConfig\x12\x38\n\nrate_limit\x18\x01 \x01(\x0b\x32$.temporal.api.taskqueue.v1.RateLimit\x12;\n\x08metadata\x18\x02 \x01(\x0b\x32).temporal.api.taskqueue.v1.ConfigMetadata"\xd9\x02\n\x0fTaskQueueConfig\x12\x44\n\x10queue_rate_limit\x18\x01 \x01(\x0b\x32*.temporal.api.taskqueue.v1.RateLimitConfig\x12T\n fairness_keys_rate_limit_default\x18\x02 \x01(\x0b\x32*.temporal.api.taskqueue.v1.RateLimitConfig\x12j\n\x19\x66\x61irness_weight_overrides\x18\x03 \x03(\x0b\x32G.temporal.api.taskqueue.v1.TaskQueueConfig.FairnessWeightOverridesEntry\x1a>\n\x1c\x46\x61irnessWeightOverridesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\x02:\x02\x38\x01\x42\x98\x01\n\x1cio.temporal.api.taskqueue.v1B\x0cMessageProtoP\x01Z)go.temporal.io/api/taskqueue/v1;taskqueue\xaa\x02\x1bTemporalio.Api.TaskQueue.V1\xea\x02\x1eTemporalio::Api::TaskQueue::V1b\x06proto3' + b'\n\'temporal/api/taskqueue/v1/message.proto\x12\x19temporal.api.taskqueue.v1\x1a\x1egoogle/protobuf/duration.proto\x1a\x1fgoogle/protobuf/timestamp.proto\x1a\x1egoogle/protobuf/wrappers.proto\x1a&temporal/api/enums/v1/task_queue.proto\x1a$temporal/api/common/v1/message.proto\x1a(temporal/api/deployment/v1/message.proto"b\n\tTaskQueue\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x32\n\x04kind\x18\x02 \x01(\x0e\x32$.temporal.api.enums.v1.TaskQueueKind\x12\x13\n\x0bnormal_name\x18\x03 \x01(\t"O\n\x11TaskQueueMetadata\x12:\n\x14max_tasks_per_second\x18\x01 \x01(\x0b\x32\x1c.google.protobuf.DoubleValue"\xda\x02\n\x17TaskQueueVersioningInfo\x12W\n\x1a\x63urrent_deployment_version\x18\x07 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersion\x12\x1b\n\x0f\x63urrent_version\x18\x01 \x01(\tB\x02\x18\x01\x12W\n\x1aramping_deployment_version\x18\t \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersion\x12\x1b\n\x0framping_version\x18\x02 \x01(\tB\x02\x18\x01\x12"\n\x1aramping_version_percentage\x18\x03 \x01(\x02\x12/\n\x0bupdate_time\x18\x04 \x01(\x0b\x32\x1a.google.protobuf.Timestamp"W\n\x19TaskQueueVersionSelection\x12\x11\n\tbuild_ids\x18\x01 \x03(\t\x12\x13\n\x0bunversioned\x18\x02 \x01(\x08\x12\x12\n\nall_active\x18\x03 \x01(\x08"\x95\x02\n\x14TaskQueueVersionInfo\x12R\n\ntypes_info\x18\x01 \x03(\x0b\x32>.temporal.api.taskqueue.v1.TaskQueueVersionInfo.TypesInfoEntry\x12I\n\x11task_reachability\x18\x02 \x01(\x0e\x32..temporal.api.enums.v1.BuildIdTaskReachability\x1a^\n\x0eTypesInfoEntry\x12\x0b\n\x03key\x18\x01 \x01(\x05\x12;\n\x05value\x18\x02 \x01(\x0b\x32,.temporal.api.taskqueue.v1.TaskQueueTypeInfo:\x02\x38\x01"\x85\x01\n\x11TaskQueueTypeInfo\x12\x36\n\x07pollers\x18\x01 \x03(\x0b\x32%.temporal.api.taskqueue.v1.PollerInfo\x12\x38\n\x05stats\x18\x02 \x01(\x0b\x32).temporal.api.taskqueue.v1.TaskQueueStats"\xa4\x01\n\x0eTaskQueueStats\x12!\n\x19\x61pproximate_backlog_count\x18\x01 \x01(\x03\x12:\n\x17\x61pproximate_backlog_age\x18\x02 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x16\n\x0etasks_add_rate\x18\x03 \x01(\x02\x12\x1b\n\x13tasks_dispatch_rate\x18\x04 \x01(\x02"\xac\x01\n\x0fTaskQueueStatus\x12\x1a\n\x12\x62\x61\x63klog_count_hint\x18\x01 \x01(\x03\x12\x12\n\nread_level\x18\x02 \x01(\x03\x12\x11\n\tack_level\x18\x03 \x01(\x03\x12\x17\n\x0frate_per_second\x18\x04 \x01(\x01\x12=\n\rtask_id_block\x18\x05 \x01(\x0b\x32&.temporal.api.taskqueue.v1.TaskIdBlock"/\n\x0bTaskIdBlock\x12\x10\n\x08start_id\x18\x01 \x01(\x03\x12\x0e\n\x06\x65nd_id\x18\x02 \x01(\x03"B\n\x1aTaskQueuePartitionMetadata\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x17\n\x0fowner_host_name\x18\x02 \x01(\t"\x9a\x02\n\nPollerInfo\x12\x34\n\x10last_access_time\x18\x01 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x10\n\x08identity\x18\x02 \x01(\t\x12\x17\n\x0frate_per_second\x18\x03 \x01(\x01\x12Z\n\x1bworker_version_capabilities\x18\x04 \x01(\x0b\x32\x31.temporal.api.common.v1.WorkerVersionCapabilitiesB\x02\x18\x01\x12O\n\x12\x64\x65ployment_options\x18\x05 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentOptions"\x9a\x01\n\x19StickyExecutionAttributes\x12?\n\x11worker_task_queue\x18\x01 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12<\n\x19schedule_to_start_timeout\x18\x02 \x01(\x0b\x32\x19.google.protobuf.Duration")\n\x14\x43ompatibleVersionSet\x12\x11\n\tbuild_ids\x18\x01 \x03(\t"j\n\x15TaskQueueReachability\x12\x12\n\ntask_queue\x18\x01 \x01(\t\x12=\n\x0creachability\x18\x02 \x03(\x0e\x32\'.temporal.api.enums.v1.TaskReachability"z\n\x13\x42uildIdReachability\x12\x10\n\x08\x62uild_id\x18\x01 \x01(\t\x12Q\n\x17task_queue_reachability\x18\x02 \x03(\x0b\x32\x30.temporal.api.taskqueue.v1.TaskQueueReachability"+\n\x10RampByPercentage\x12\x17\n\x0framp_percentage\x18\x01 \x01(\x02"\x80\x01\n\x15\x42uildIdAssignmentRule\x12\x17\n\x0ftarget_build_id\x18\x01 \x01(\t\x12\x46\n\x0fpercentage_ramp\x18\x03 \x01(\x0b\x32+.temporal.api.taskqueue.v1.RampByPercentageH\x00\x42\x06\n\x04ramp"Q\n\x1d\x43ompatibleBuildIdRedirectRule\x12\x17\n\x0fsource_build_id\x18\x01 \x01(\t\x12\x17\n\x0ftarget_build_id\x18\x02 \x01(\t"\x93\x01\n TimestampedBuildIdAssignmentRule\x12>\n\x04rule\x18\x01 \x01(\x0b\x32\x30.temporal.api.taskqueue.v1.BuildIdAssignmentRule\x12/\n\x0b\x63reate_time\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.Timestamp"\xa3\x01\n(TimestampedCompatibleBuildIdRedirectRule\x12\x46\n\x04rule\x18\x01 \x01(\x0b\x32\x38.temporal.api.taskqueue.v1.CompatibleBuildIdRedirectRule\x12/\n\x0b\x63reate_time\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.Timestamp"-\n\x0fPollerGroupInfo\x12\n\n\x02id\x18\x01 \x01(\t\x12\x0e\n\x06weight\x18\x02 \x01(\x02">\n\x15PollerScalingDecision\x12%\n\x1dpoll_request_delta_suggestion\x18\x01 \x01(\x05"(\n\tRateLimit\x12\x1b\n\x13requests_per_second\x18\x01 \x01(\x02"j\n\x0e\x43onfigMetadata\x12\x0e\n\x06reason\x18\x01 \x01(\t\x12\x17\n\x0fupdate_identity\x18\x02 \x01(\t\x12/\n\x0bupdate_time\x18\x03 \x01(\x0b\x32\x1a.google.protobuf.Timestamp"\x88\x01\n\x0fRateLimitConfig\x12\x38\n\nrate_limit\x18\x01 \x01(\x0b\x32$.temporal.api.taskqueue.v1.RateLimit\x12;\n\x08metadata\x18\x02 \x01(\x0b\x32).temporal.api.taskqueue.v1.ConfigMetadata"\xd9\x02\n\x0fTaskQueueConfig\x12\x44\n\x10queue_rate_limit\x18\x01 \x01(\x0b\x32*.temporal.api.taskqueue.v1.RateLimitConfig\x12T\n fairness_keys_rate_limit_default\x18\x02 \x01(\x0b\x32*.temporal.api.taskqueue.v1.RateLimitConfig\x12j\n\x19\x66\x61irness_weight_overrides\x18\x03 \x03(\x0b\x32G.temporal.api.taskqueue.v1.TaskQueueConfig.FairnessWeightOverridesEntry\x1a>\n\x1c\x46\x61irnessWeightOverridesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\x02:\x02\x38\x01\x42\x98\x01\n\x1cio.temporal.api.taskqueue.v1B\x0cMessageProtoP\x01Z)go.temporal.io/api/taskqueue/v1;taskqueue\xaa\x02\x1bTemporalio.Api.TaskQueue.V1\xea\x02\x1eTemporalio::Api::TaskQueue::V1b\x06proto3' ) @@ -68,6 +68,7 @@ _TIMESTAMPEDCOMPATIBLEBUILDIDREDIRECTRULE = DESCRIPTOR.message_types_by_name[ "TimestampedCompatibleBuildIdRedirectRule" ] +_POLLERGROUPINFO = DESCRIPTOR.message_types_by_name["PollerGroupInfo"] _POLLERSCALINGDECISION = DESCRIPTOR.message_types_by_name["PollerScalingDecision"] _RATELIMIT = DESCRIPTOR.message_types_by_name["RateLimit"] _CONFIGMETADATA = DESCRIPTOR.message_types_by_name["ConfigMetadata"] @@ -306,6 +307,17 @@ ) _sym_db.RegisterMessage(TimestampedCompatibleBuildIdRedirectRule) +PollerGroupInfo = _reflection.GeneratedProtocolMessageType( + "PollerGroupInfo", + (_message.Message,), + { + "DESCRIPTOR": _POLLERGROUPINFO, + "__module__": "temporalio.api.taskqueue.v1.message_pb2", + # @@protoc_insertion_point(class_scope:temporal.api.taskqueue.v1.PollerGroupInfo) + }, +) +_sym_db.RegisterMessage(PollerGroupInfo) + PollerScalingDecision = _reflection.GeneratedProtocolMessageType( "PollerScalingDecision", (_message.Message,), @@ -432,16 +444,18 @@ _TIMESTAMPEDBUILDIDASSIGNMENTRULE._serialized_end = 2905 _TIMESTAMPEDCOMPATIBLEBUILDIDREDIRECTRULE._serialized_start = 2908 _TIMESTAMPEDCOMPATIBLEBUILDIDREDIRECTRULE._serialized_end = 3071 - _POLLERSCALINGDECISION._serialized_start = 3073 - _POLLERSCALINGDECISION._serialized_end = 3135 - _RATELIMIT._serialized_start = 3137 - _RATELIMIT._serialized_end = 3177 - _CONFIGMETADATA._serialized_start = 3179 - _CONFIGMETADATA._serialized_end = 3285 - _RATELIMITCONFIG._serialized_start = 3288 - _RATELIMITCONFIG._serialized_end = 3424 - _TASKQUEUECONFIG._serialized_start = 3427 - _TASKQUEUECONFIG._serialized_end = 3772 - _TASKQUEUECONFIG_FAIRNESSWEIGHTOVERRIDESENTRY._serialized_start = 3710 - _TASKQUEUECONFIG_FAIRNESSWEIGHTOVERRIDESENTRY._serialized_end = 3772 + _POLLERGROUPINFO._serialized_start = 3073 + _POLLERGROUPINFO._serialized_end = 3118 + _POLLERSCALINGDECISION._serialized_start = 3120 + _POLLERSCALINGDECISION._serialized_end = 3182 + _RATELIMIT._serialized_start = 3184 + _RATELIMIT._serialized_end = 3224 + _CONFIGMETADATA._serialized_start = 3226 + _CONFIGMETADATA._serialized_end = 3332 + _RATELIMITCONFIG._serialized_start = 3335 + _RATELIMITCONFIG._serialized_end = 3471 + _TASKQUEUECONFIG._serialized_start = 3474 + _TASKQUEUECONFIG._serialized_end = 3819 + _TASKQUEUECONFIG_FAIRNESSWEIGHTOVERRIDESENTRY._serialized_start = 3757 + _TASKQUEUECONFIG_FAIRNESSWEIGHTOVERRIDESENTRY._serialized_end = 3819 # @@protoc_insertion_point(module_scope) diff --git a/temporalio/api/taskqueue/v1/message_pb2.pyi b/temporalio/api/taskqueue/v1/message_pb2.pyi index bd5fb755e..e614430d6 100644 --- a/temporalio/api/taskqueue/v1/message_pb2.pyi +++ b/temporalio/api/taskqueue/v1/message_pb2.pyi @@ -86,8 +86,6 @@ class TaskQueueMetadata(google.protobuf.message.Message): global___TaskQueueMetadata = TaskQueueMetadata class TaskQueueVersioningInfo(google.protobuf.message.Message): - """Experimental. Worker Deployments are experimental and might significantly change in the future.""" - DESCRIPTOR: google.protobuf.descriptor.Descriptor CURRENT_DEPLOYMENT_VERSION_FIELD_NUMBER: builtins.int @@ -897,6 +895,25 @@ global___TimestampedCompatibleBuildIdRedirectRule = ( TimestampedCompatibleBuildIdRedirectRule ) +class PollerGroupInfo(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + ID_FIELD_NUMBER: builtins.int + WEIGHT_FIELD_NUMBER: builtins.int + id: builtins.str + weight: builtins.float + def __init__( + self, + *, + id: builtins.str = ..., + weight: builtins.float = ..., + ) -> None: ... + def ClearField( + self, field_name: typing_extensions.Literal["id", b"id", "weight", b"weight"] + ) -> None: ... + +global___PollerGroupInfo = PollerGroupInfo + class PollerScalingDecision(google.protobuf.message.Message): """Attached to task responses to give hints to the SDK about how it may adjust its number of pollers. diff --git a/temporalio/api/worker/v1/__init__.py b/temporalio/api/worker/v1/__init__.py index bdf9575c6..5c1afdf4f 100644 --- a/temporalio/api/worker/v1/__init__.py +++ b/temporalio/api/worker/v1/__init__.py @@ -1,6 +1,10 @@ from .message_pb2 import ( + CancelActivityCommand, + CancelActivityResult, PluginInfo, StorageDriverInfo, + WorkerCommand, + WorkerCommandResult, WorkerHeartbeat, WorkerHostInfo, WorkerInfo, @@ -10,8 +14,12 @@ ) __all__ = [ + "CancelActivityCommand", + "CancelActivityResult", "PluginInfo", "StorageDriverInfo", + "WorkerCommand", + "WorkerCommandResult", "WorkerHeartbeat", "WorkerHostInfo", "WorkerInfo", diff --git a/temporalio/api/worker/v1/message_pb2.py b/temporalio/api/worker/v1/message_pb2.py index cf88c6722..4de9c5b24 100644 --- a/temporalio/api/worker/v1/message_pb2.py +++ b/temporalio/api/worker/v1/message_pb2.py @@ -25,7 +25,7 @@ ) DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile( - b'\n$temporal/api/worker/v1/message.proto\x12\x16temporal.api.worker.v1\x1a\x1egoogle/protobuf/duration.proto\x1a\x1fgoogle/protobuf/timestamp.proto\x1a(temporal/api/deployment/v1/message.proto\x1a"temporal/api/enums/v1/common.proto"\x82\x01\n\x10WorkerPollerInfo\x12\x17\n\x0f\x63urrent_pollers\x18\x01 \x01(\x05\x12=\n\x19last_successful_poll_time\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x16\n\x0eis_autoscaling\x18\x03 \x01(\x08"\xf1\x01\n\x0fWorkerSlotsInfo\x12\x1f\n\x17\x63urrent_available_slots\x18\x01 \x01(\x05\x12\x1a\n\x12\x63urrent_used_slots\x18\x02 \x01(\x05\x12\x1a\n\x12slot_supplier_kind\x18\x03 \x01(\t\x12\x1d\n\x15total_processed_tasks\x18\x04 \x01(\x05\x12\x1a\n\x12total_failed_tasks\x18\x05 \x01(\x05\x12%\n\x1dlast_interval_processed_tasks\x18\x06 \x01(\x05\x12#\n\x1blast_interval_failure_tasks\x18\x07 \x01(\x05"\x94\x01\n\x0eWorkerHostInfo\x12\x11\n\thost_name\x18\x01 \x01(\t\x12\x1b\n\x13worker_grouping_key\x18\x05 \x01(\t\x12\x12\n\nprocess_id\x18\x02 \x01(\t\x12\x1e\n\x16\x63urrent_host_cpu_usage\x18\x03 \x01(\x02\x12\x1e\n\x16\x63urrent_host_mem_usage\x18\x04 \x01(\x02"\x8b\n\n\x0fWorkerHeartbeat\x12\x1b\n\x13worker_instance_key\x18\x01 \x01(\t\x12\x17\n\x0fworker_identity\x18\x02 \x01(\t\x12\x39\n\thost_info\x18\x03 \x01(\x0b\x32&.temporal.api.worker.v1.WorkerHostInfo\x12\x12\n\ntask_queue\x18\x04 \x01(\t\x12O\n\x12\x64\x65ployment_version\x18\x05 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersion\x12\x10\n\x08sdk_name\x18\x06 \x01(\t\x12\x13\n\x0bsdk_version\x18\x07 \x01(\t\x12\x33\n\x06status\x18\x08 \x01(\x0e\x32#.temporal.api.enums.v1.WorkerStatus\x12.\n\nstart_time\x18\t \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x32\n\x0eheartbeat_time\x18\n \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12?\n\x1c\x65lapsed_since_last_heartbeat\x18\x0b \x01(\x0b\x32\x19.google.protobuf.Duration\x12I\n\x18workflow_task_slots_info\x18\x0c \x01(\x0b\x32\'.temporal.api.worker.v1.WorkerSlotsInfo\x12I\n\x18\x61\x63tivity_task_slots_info\x18\r \x01(\x0b\x32\'.temporal.api.worker.v1.WorkerSlotsInfo\x12\x46\n\x15nexus_task_slots_info\x18\x0e \x01(\x0b\x32\'.temporal.api.worker.v1.WorkerSlotsInfo\x12J\n\x19local_activity_slots_info\x18\x0f \x01(\x0b\x32\'.temporal.api.worker.v1.WorkerSlotsInfo\x12\x46\n\x14workflow_poller_info\x18\x10 \x01(\x0b\x32(.temporal.api.worker.v1.WorkerPollerInfo\x12M\n\x1bworkflow_sticky_poller_info\x18\x11 \x01(\x0b\x32(.temporal.api.worker.v1.WorkerPollerInfo\x12\x46\n\x14\x61\x63tivity_poller_info\x18\x12 \x01(\x0b\x32(.temporal.api.worker.v1.WorkerPollerInfo\x12\x43\n\x11nexus_poller_info\x18\x13 \x01(\x0b\x32(.temporal.api.worker.v1.WorkerPollerInfo\x12\x1e\n\x16total_sticky_cache_hit\x18\x14 \x01(\x05\x12\x1f\n\x17total_sticky_cache_miss\x18\x15 \x01(\x05\x12!\n\x19\x63urrent_sticky_cache_size\x18\x16 \x01(\x05\x12\x33\n\x07plugins\x18\x17 \x03(\x0b\x32".temporal.api.worker.v1.PluginInfo\x12:\n\x07\x64rivers\x18\x18 \x03(\x0b\x32).temporal.api.worker.v1.StorageDriverInfo"O\n\nWorkerInfo\x12\x41\n\x10worker_heartbeat\x18\x01 \x01(\x0b\x32\'.temporal.api.worker.v1.WorkerHeartbeat"\xec\x03\n\x0eWorkerListInfo\x12\x1b\n\x13worker_instance_key\x18\x01 \x01(\t\x12\x17\n\x0fworker_identity\x18\x02 \x01(\t\x12\x12\n\ntask_queue\x18\x03 \x01(\t\x12O\n\x12\x64\x65ployment_version\x18\x04 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersion\x12\x10\n\x08sdk_name\x18\x05 \x01(\t\x12\x13\n\x0bsdk_version\x18\x06 \x01(\t\x12\x33\n\x06status\x18\x07 \x01(\x0e\x32#.temporal.api.enums.v1.WorkerStatus\x12.\n\nstart_time\x18\x08 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x11\n\thost_name\x18\t \x01(\t\x12\x1b\n\x13worker_grouping_key\x18\n \x01(\t\x12\x12\n\nprocess_id\x18\x0b \x01(\t\x12\x33\n\x07plugins\x18\x0c \x03(\x0b\x32".temporal.api.worker.v1.PluginInfo\x12:\n\x07\x64rivers\x18\r \x03(\x0b\x32).temporal.api.worker.v1.StorageDriverInfo"+\n\nPluginInfo\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x0f\n\x07version\x18\x02 \x01(\t"!\n\x11StorageDriverInfo\x12\x0c\n\x04type\x18\x01 \x01(\tB\x89\x01\n\x19io.temporal.api.worker.v1B\x0cMessageProtoP\x01Z#go.temporal.io/api/worker/v1;worker\xaa\x02\x18Temporalio.Api.Worker.V1\xea\x02\x1bTemporalio::Api::Worker::V1b\x06proto3' + b'\n$temporal/api/worker/v1/message.proto\x12\x16temporal.api.worker.v1\x1a\x1egoogle/protobuf/duration.proto\x1a\x1fgoogle/protobuf/timestamp.proto\x1a(temporal/api/deployment/v1/message.proto\x1a"temporal/api/enums/v1/common.proto"\x82\x01\n\x10WorkerPollerInfo\x12\x17\n\x0f\x63urrent_pollers\x18\x01 \x01(\x05\x12=\n\x19last_successful_poll_time\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x16\n\x0eis_autoscaling\x18\x03 \x01(\x08"\xf1\x01\n\x0fWorkerSlotsInfo\x12\x1f\n\x17\x63urrent_available_slots\x18\x01 \x01(\x05\x12\x1a\n\x12\x63urrent_used_slots\x18\x02 \x01(\x05\x12\x1a\n\x12slot_supplier_kind\x18\x03 \x01(\t\x12\x1d\n\x15total_processed_tasks\x18\x04 \x01(\x05\x12\x1a\n\x12total_failed_tasks\x18\x05 \x01(\x05\x12%\n\x1dlast_interval_processed_tasks\x18\x06 \x01(\x05\x12#\n\x1blast_interval_failure_tasks\x18\x07 \x01(\x05"\x94\x01\n\x0eWorkerHostInfo\x12\x11\n\thost_name\x18\x01 \x01(\t\x12\x1b\n\x13worker_grouping_key\x18\x05 \x01(\t\x12\x12\n\nprocess_id\x18\x02 \x01(\t\x12\x1e\n\x16\x63urrent_host_cpu_usage\x18\x03 \x01(\x02\x12\x1e\n\x16\x63urrent_host_mem_usage\x18\x04 \x01(\x02"\x8b\n\n\x0fWorkerHeartbeat\x12\x1b\n\x13worker_instance_key\x18\x01 \x01(\t\x12\x17\n\x0fworker_identity\x18\x02 \x01(\t\x12\x39\n\thost_info\x18\x03 \x01(\x0b\x32&.temporal.api.worker.v1.WorkerHostInfo\x12\x12\n\ntask_queue\x18\x04 \x01(\t\x12O\n\x12\x64\x65ployment_version\x18\x05 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersion\x12\x10\n\x08sdk_name\x18\x06 \x01(\t\x12\x13\n\x0bsdk_version\x18\x07 \x01(\t\x12\x33\n\x06status\x18\x08 \x01(\x0e\x32#.temporal.api.enums.v1.WorkerStatus\x12.\n\nstart_time\x18\t \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x32\n\x0eheartbeat_time\x18\n \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12?\n\x1c\x65lapsed_since_last_heartbeat\x18\x0b \x01(\x0b\x32\x19.google.protobuf.Duration\x12I\n\x18workflow_task_slots_info\x18\x0c \x01(\x0b\x32\'.temporal.api.worker.v1.WorkerSlotsInfo\x12I\n\x18\x61\x63tivity_task_slots_info\x18\r \x01(\x0b\x32\'.temporal.api.worker.v1.WorkerSlotsInfo\x12\x46\n\x15nexus_task_slots_info\x18\x0e \x01(\x0b\x32\'.temporal.api.worker.v1.WorkerSlotsInfo\x12J\n\x19local_activity_slots_info\x18\x0f \x01(\x0b\x32\'.temporal.api.worker.v1.WorkerSlotsInfo\x12\x46\n\x14workflow_poller_info\x18\x10 \x01(\x0b\x32(.temporal.api.worker.v1.WorkerPollerInfo\x12M\n\x1bworkflow_sticky_poller_info\x18\x11 \x01(\x0b\x32(.temporal.api.worker.v1.WorkerPollerInfo\x12\x46\n\x14\x61\x63tivity_poller_info\x18\x12 \x01(\x0b\x32(.temporal.api.worker.v1.WorkerPollerInfo\x12\x43\n\x11nexus_poller_info\x18\x13 \x01(\x0b\x32(.temporal.api.worker.v1.WorkerPollerInfo\x12\x1e\n\x16total_sticky_cache_hit\x18\x14 \x01(\x05\x12\x1f\n\x17total_sticky_cache_miss\x18\x15 \x01(\x05\x12!\n\x19\x63urrent_sticky_cache_size\x18\x16 \x01(\x05\x12\x33\n\x07plugins\x18\x17 \x03(\x0b\x32".temporal.api.worker.v1.PluginInfo\x12:\n\x07\x64rivers\x18\x18 \x03(\x0b\x32).temporal.api.worker.v1.StorageDriverInfo"O\n\nWorkerInfo\x12\x41\n\x10worker_heartbeat\x18\x01 \x01(\x0b\x32\'.temporal.api.worker.v1.WorkerHeartbeat"\xec\x03\n\x0eWorkerListInfo\x12\x1b\n\x13worker_instance_key\x18\x01 \x01(\t\x12\x17\n\x0fworker_identity\x18\x02 \x01(\t\x12\x12\n\ntask_queue\x18\x03 \x01(\t\x12O\n\x12\x64\x65ployment_version\x18\x04 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersion\x12\x10\n\x08sdk_name\x18\x05 \x01(\t\x12\x13\n\x0bsdk_version\x18\x06 \x01(\t\x12\x33\n\x06status\x18\x07 \x01(\x0e\x32#.temporal.api.enums.v1.WorkerStatus\x12.\n\nstart_time\x18\x08 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x11\n\thost_name\x18\t \x01(\t\x12\x1b\n\x13worker_grouping_key\x18\n \x01(\t\x12\x12\n\nprocess_id\x18\x0b \x01(\t\x12\x33\n\x07plugins\x18\x0c \x03(\x0b\x32".temporal.api.worker.v1.PluginInfo\x12:\n\x07\x64rivers\x18\r \x03(\x0b\x32).temporal.api.worker.v1.StorageDriverInfo"+\n\nPluginInfo\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x0f\n\x07version\x18\x02 \x01(\t"!\n\x11StorageDriverInfo\x12\x0c\n\x04type\x18\x01 \x01(\t"a\n\rWorkerCommand\x12H\n\x0f\x63\x61ncel_activity\x18\x01 \x01(\x0b\x32-.temporal.api.worker.v1.CancelActivityCommandH\x00\x42\x06\n\x04type"+\n\x15\x43\x61ncelActivityCommand\x12\x12\n\ntask_token\x18\x01 \x01(\x0c"f\n\x13WorkerCommandResult\x12G\n\x0f\x63\x61ncel_activity\x18\x01 \x01(\x0b\x32,.temporal.api.worker.v1.CancelActivityResultH\x00\x42\x06\n\x04type"\x16\n\x14\x43\x61ncelActivityResultB\x89\x01\n\x19io.temporal.api.worker.v1B\x0cMessageProtoP\x01Z#go.temporal.io/api/worker/v1;worker\xaa\x02\x18Temporalio.Api.Worker.V1\xea\x02\x1bTemporalio::Api::Worker::V1b\x06proto3' ) @@ -37,6 +37,10 @@ _WORKERLISTINFO = DESCRIPTOR.message_types_by_name["WorkerListInfo"] _PLUGININFO = DESCRIPTOR.message_types_by_name["PluginInfo"] _STORAGEDRIVERINFO = DESCRIPTOR.message_types_by_name["StorageDriverInfo"] +_WORKERCOMMAND = DESCRIPTOR.message_types_by_name["WorkerCommand"] +_CANCELACTIVITYCOMMAND = DESCRIPTOR.message_types_by_name["CancelActivityCommand"] +_WORKERCOMMANDRESULT = DESCRIPTOR.message_types_by_name["WorkerCommandResult"] +_CANCELACTIVITYRESULT = DESCRIPTOR.message_types_by_name["CancelActivityResult"] WorkerPollerInfo = _reflection.GeneratedProtocolMessageType( "WorkerPollerInfo", (_message.Message,), @@ -125,6 +129,50 @@ ) _sym_db.RegisterMessage(StorageDriverInfo) +WorkerCommand = _reflection.GeneratedProtocolMessageType( + "WorkerCommand", + (_message.Message,), + { + "DESCRIPTOR": _WORKERCOMMAND, + "__module__": "temporalio.api.worker.v1.message_pb2", + # @@protoc_insertion_point(class_scope:temporal.api.worker.v1.WorkerCommand) + }, +) +_sym_db.RegisterMessage(WorkerCommand) + +CancelActivityCommand = _reflection.GeneratedProtocolMessageType( + "CancelActivityCommand", + (_message.Message,), + { + "DESCRIPTOR": _CANCELACTIVITYCOMMAND, + "__module__": "temporalio.api.worker.v1.message_pb2", + # @@protoc_insertion_point(class_scope:temporal.api.worker.v1.CancelActivityCommand) + }, +) +_sym_db.RegisterMessage(CancelActivityCommand) + +WorkerCommandResult = _reflection.GeneratedProtocolMessageType( + "WorkerCommandResult", + (_message.Message,), + { + "DESCRIPTOR": _WORKERCOMMANDRESULT, + "__module__": "temporalio.api.worker.v1.message_pb2", + # @@protoc_insertion_point(class_scope:temporal.api.worker.v1.WorkerCommandResult) + }, +) +_sym_db.RegisterMessage(WorkerCommandResult) + +CancelActivityResult = _reflection.GeneratedProtocolMessageType( + "CancelActivityResult", + (_message.Message,), + { + "DESCRIPTOR": _CANCELACTIVITYRESULT, + "__module__": "temporalio.api.worker.v1.message_pb2", + # @@protoc_insertion_point(class_scope:temporal.api.worker.v1.CancelActivityResult) + }, +) +_sym_db.RegisterMessage(CancelActivityResult) + if _descriptor._USE_C_DESCRIPTORS == False: DESCRIPTOR._options = None DESCRIPTOR._serialized_options = b"\n\031io.temporal.api.worker.v1B\014MessageProtoP\001Z#go.temporal.io/api/worker/v1;worker\252\002\030Temporalio.Api.Worker.V1\352\002\033Temporalio::Api::Worker::V1" @@ -144,4 +192,12 @@ _PLUGININFO._serialized_end = 2648 _STORAGEDRIVERINFO._serialized_start = 2650 _STORAGEDRIVERINFO._serialized_end = 2683 + _WORKERCOMMAND._serialized_start = 2685 + _WORKERCOMMAND._serialized_end = 2782 + _CANCELACTIVITYCOMMAND._serialized_start = 2784 + _CANCELACTIVITYCOMMAND._serialized_end = 2827 + _WORKERCOMMANDRESULT._serialized_start = 2829 + _WORKERCOMMANDRESULT._serialized_end = 2931 + _CANCELACTIVITYRESULT._serialized_start = 2933 + _CANCELACTIVITYRESULT._serialized_end = 2955 # @@protoc_insertion_point(module_scope) diff --git a/temporalio/api/worker/v1/message_pb2.pyi b/temporalio/api/worker/v1/message_pb2.pyi index 632dd49dd..f78916ed5 100644 --- a/temporalio/api/worker/v1/message_pb2.pyi +++ b/temporalio/api/worker/v1/message_pb2.pyi @@ -592,3 +592,96 @@ class StorageDriverInfo(google.protobuf.message.Message): ) -> None: ... global___StorageDriverInfo = StorageDriverInfo + +class WorkerCommand(google.protobuf.message.Message): + """A command sent from the server to a worker.""" + + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + CANCEL_ACTIVITY_FIELD_NUMBER: builtins.int + @property + def cancel_activity(self) -> global___CancelActivityCommand: ... + def __init__( + self, + *, + cancel_activity: global___CancelActivityCommand | None = ..., + ) -> None: ... + def HasField( + self, + field_name: typing_extensions.Literal[ + "cancel_activity", b"cancel_activity", "type", b"type" + ], + ) -> builtins.bool: ... + def ClearField( + self, + field_name: typing_extensions.Literal[ + "cancel_activity", b"cancel_activity", "type", b"type" + ], + ) -> None: ... + def WhichOneof( + self, oneof_group: typing_extensions.Literal["type", b"type"] + ) -> typing_extensions.Literal["cancel_activity"] | None: ... + +global___WorkerCommand = WorkerCommand + +class CancelActivityCommand(google.protobuf.message.Message): + """Cancel an activity if it is still running. Otherwise, do nothing.""" + + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + TASK_TOKEN_FIELD_NUMBER: builtins.int + task_token: builtins.bytes + def __init__( + self, + *, + task_token: builtins.bytes = ..., + ) -> None: ... + def ClearField( + self, field_name: typing_extensions.Literal["task_token", b"task_token"] + ) -> None: ... + +global___CancelActivityCommand = CancelActivityCommand + +class WorkerCommandResult(google.protobuf.message.Message): + """The result of executing a WorkerCommand.""" + + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + CANCEL_ACTIVITY_FIELD_NUMBER: builtins.int + @property + def cancel_activity(self) -> global___CancelActivityResult: ... + def __init__( + self, + *, + cancel_activity: global___CancelActivityResult | None = ..., + ) -> None: ... + def HasField( + self, + field_name: typing_extensions.Literal[ + "cancel_activity", b"cancel_activity", "type", b"type" + ], + ) -> builtins.bool: ... + def ClearField( + self, + field_name: typing_extensions.Literal[ + "cancel_activity", b"cancel_activity", "type", b"type" + ], + ) -> None: ... + def WhichOneof( + self, oneof_group: typing_extensions.Literal["type", b"type"] + ) -> typing_extensions.Literal["cancel_activity"] | None: ... + +global___WorkerCommandResult = WorkerCommandResult + +class CancelActivityResult(google.protobuf.message.Message): + """Result of a CancelActivityCommand. + Treat both successful cancellation and no-op (activity is no longer running) as success. + """ + + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + def __init__( + self, + ) -> None: ... + +global___CancelActivityResult = CancelActivityResult diff --git a/temporalio/api/workflow/v1/__init__.py b/temporalio/api/workflow/v1/__init__.py index ae647ab67..89878d551 100644 --- a/temporalio/api/workflow/v1/__init__.py +++ b/temporalio/api/workflow/v1/__init__.py @@ -13,6 +13,7 @@ RequestIdInfo, ResetPointInfo, ResetPoints, + TimeSkippingConfig, VersioningOverride, WorkflowExecutionConfig, WorkflowExecutionExtendedInfo, @@ -37,6 +38,7 @@ "RequestIdInfo", "ResetPointInfo", "ResetPoints", + "TimeSkippingConfig", "VersioningOverride", "WorkflowExecutionConfig", "WorkflowExecutionExtendedInfo", diff --git a/temporalio/api/workflow/v1/message_pb2.py b/temporalio/api/workflow/v1/message_pb2.py index e743c25ee..8455f8875 100644 --- a/temporalio/api/workflow/v1/message_pb2.py +++ b/temporalio/api/workflow/v1/message_pb2.py @@ -48,7 +48,7 @@ ) DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile( - b'\n&temporal/api/workflow/v1/message.proto\x12\x18temporal.api.workflow.v1\x1a\x1egoogle/protobuf/duration.proto\x1a\x1bgoogle/protobuf/empty.proto\x1a\x1fgoogle/protobuf/timestamp.proto\x1a google/protobuf/field_mask.proto\x1a&temporal/api/activity/v1/message.proto\x1a"temporal/api/enums/v1/common.proto\x1a&temporal/api/enums/v1/event_type.proto\x1a$temporal/api/enums/v1/workflow.proto\x1a$temporal/api/common/v1/message.proto\x1a(temporal/api/deployment/v1/message.proto\x1a%temporal/api/failure/v1/message.proto\x1a\'temporal/api/taskqueue/v1/message.proto\x1a\'temporal/api/sdk/v1/user_metadata.proto"\xf0\t\n\x15WorkflowExecutionInfo\x12<\n\texecution\x18\x01 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x32\n\x04type\x18\x02 \x01(\x0b\x32$.temporal.api.common.v1.WorkflowType\x12.\n\nstart_time\x18\x03 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12.\n\nclose_time\x18\x04 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12>\n\x06status\x18\x05 \x01(\x0e\x32..temporal.api.enums.v1.WorkflowExecutionStatus\x12\x16\n\x0ehistory_length\x18\x06 \x01(\x03\x12\x1b\n\x13parent_namespace_id\x18\x07 \x01(\t\x12\x43\n\x10parent_execution\x18\x08 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x32\n\x0e\x65xecution_time\x18\t \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12*\n\x04memo\x18\n \x01(\x0b\x32\x1c.temporal.api.common.v1.Memo\x12\x43\n\x11search_attributes\x18\x0b \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes\x12@\n\x11\x61uto_reset_points\x18\x0c \x01(\x0b\x32%.temporal.api.workflow.v1.ResetPoints\x12\x12\n\ntask_queue\x18\r \x01(\t\x12\x1e\n\x16state_transition_count\x18\x0e \x01(\x03\x12\x1a\n\x12history_size_bytes\x18\x0f \x01(\x03\x12X\n most_recent_worker_version_stamp\x18\x10 \x01(\x0b\x32*.temporal.api.common.v1.WorkerVersionStampB\x02\x18\x01\x12\x35\n\x12\x65xecution_duration\x18\x11 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x41\n\x0eroot_execution\x18\x12 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x1d\n\x11\x61ssigned_build_id\x18\x13 \x01(\tB\x02\x18\x01\x12\x1e\n\x12inherited_build_id\x18\x14 \x01(\tB\x02\x18\x01\x12\x14\n\x0c\x66irst_run_id\x18\x15 \x01(\t\x12R\n\x0fversioning_info\x18\x16 \x01(\x0b\x32\x39.temporal.api.workflow.v1.WorkflowExecutionVersioningInfo\x12\x1e\n\x16worker_deployment_name\x18\x17 \x01(\t\x12\x32\n\x08priority\x18\x18 \x01(\x0b\x32 .temporal.api.common.v1.Priority\x12#\n\x1b\x65xternal_payload_size_bytes\x18\x19 \x01(\x03\x12\x1e\n\x16\x65xternal_payload_count\x18\x1a \x01(\x03"\xc6\x04\n\x1dWorkflowExecutionExtendedInfo\x12=\n\x19\x65xecution_expiration_time\x18\x01 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x37\n\x13run_expiration_time\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x18\n\x10\x63\x61ncel_requested\x18\x03 \x01(\x08\x12\x33\n\x0flast_reset_time\x18\x04 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x37\n\x13original_start_time\x18\x05 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x14\n\x0creset_run_id\x18\x06 \x01(\t\x12\x65\n\x10request_id_infos\x18\x07 \x03(\x0b\x32K.temporal.api.workflow.v1.WorkflowExecutionExtendedInfo.RequestIdInfosEntry\x12H\n\npause_info\x18\x08 \x01(\x0b\x32\x34.temporal.api.workflow.v1.WorkflowExecutionPauseInfo\x1a^\n\x13RequestIdInfosEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x36\n\x05value\x18\x02 \x01(\x0b\x32\'.temporal.api.workflow.v1.RequestIdInfo:\x02\x38\x01"\x8e\x04\n\x1fWorkflowExecutionVersioningInfo\x12;\n\x08\x62\x65havior\x18\x01 \x01(\x0e\x32).temporal.api.enums.v1.VersioningBehavior\x12>\n\ndeployment\x18\x02 \x01(\x0b\x32&.temporal.api.deployment.v1.DeploymentB\x02\x18\x01\x12\x13\n\x07version\x18\x05 \x01(\tB\x02\x18\x01\x12O\n\x12\x64\x65ployment_version\x18\x07 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersion\x12I\n\x13versioning_override\x18\x03 \x01(\x0b\x32,.temporal.api.workflow.v1.VersioningOverride\x12Q\n\x15\x64\x65ployment_transition\x18\x04 \x01(\x0b\x32..temporal.api.workflow.v1.DeploymentTransitionB\x02\x18\x01\x12Q\n\x12version_transition\x18\x06 \x01(\x0b\x32\x35.temporal.api.workflow.v1.DeploymentVersionTransition\x12\x17\n\x0frevision_number\x18\x08 \x01(\x03"R\n\x14\x44\x65ploymentTransition\x12:\n\ndeployment\x18\x01 \x01(\x0b\x32&.temporal.api.deployment.v1.Deployment"\x83\x01\n\x1b\x44\x65ploymentVersionTransition\x12\x13\n\x07version\x18\x01 \x01(\tB\x02\x18\x01\x12O\n\x12\x64\x65ployment_version\x18\x02 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersion"\xc7\x02\n\x17WorkflowExecutionConfig\x12\x38\n\ntask_queue\x18\x01 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12=\n\x1aworkflow_execution_timeout\x18\x02 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x37\n\x14workflow_run_timeout\x18\x03 \x01(\x0b\x32\x19.google.protobuf.Duration\x12@\n\x1d\x64\x65\x66\x61ult_workflow_task_timeout\x18\x04 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x38\n\ruser_metadata\x18\x05 \x01(\x0b\x32!.temporal.api.sdk.v1.UserMetadata"\xbd\r\n\x13PendingActivityInfo\x12\x13\n\x0b\x61\x63tivity_id\x18\x01 \x01(\t\x12;\n\ractivity_type\x18\x02 \x01(\x0b\x32$.temporal.api.common.v1.ActivityType\x12:\n\x05state\x18\x03 \x01(\x0e\x32+.temporal.api.enums.v1.PendingActivityState\x12;\n\x11heartbeat_details\x18\x04 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x37\n\x13last_heartbeat_time\x18\x05 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x35\n\x11last_started_time\x18\x06 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x0f\n\x07\x61ttempt\x18\x07 \x01(\x05\x12\x18\n\x10maximum_attempts\x18\x08 \x01(\x05\x12\x32\n\x0escheduled_time\x18\t \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x33\n\x0f\x65xpiration_time\x18\n \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x36\n\x0clast_failure\x18\x0b \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12\x1c\n\x14last_worker_identity\x18\x0c \x01(\t\x12;\n\x15use_workflow_build_id\x18\r \x01(\x0b\x32\x16.google.protobuf.EmptyB\x02\x18\x01H\x00\x12\x32\n$last_independently_assigned_build_id\x18\x0e \x01(\tB\x02\x18\x01H\x00\x12Q\n\x19last_worker_version_stamp\x18\x0f \x01(\x0b\x32*.temporal.api.common.v1.WorkerVersionStampB\x02\x18\x01\x12\x39\n\x16\x63urrent_retry_interval\x18\x10 \x01(\x0b\x32\x19.google.protobuf.Duration\x12>\n\x1alast_attempt_complete_time\x18\x11 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12>\n\x1anext_attempt_schedule_time\x18\x12 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x0e\n\x06paused\x18\x13 \x01(\x08\x12\x43\n\x0flast_deployment\x18\x14 \x01(\x0b\x32&.temporal.api.deployment.v1.DeploymentB\x02\x18\x01\x12*\n\x1elast_worker_deployment_version\x18\x15 \x01(\tB\x02\x18\x01\x12T\n\x17last_deployment_version\x18\x19 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersion\x12\x32\n\x08priority\x18\x16 \x01(\x0b\x32 .temporal.api.common.v1.Priority\x12K\n\npause_info\x18\x17 \x01(\x0b\x32\x37.temporal.api.workflow.v1.PendingActivityInfo.PauseInfo\x12\x43\n\x10\x61\x63tivity_options\x18\x18 \x01(\x0b\x32).temporal.api.activity.v1.ActivityOptions\x1a\xcf\x02\n\tPauseInfo\x12.\n\npause_time\x18\x01 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12P\n\x06manual\x18\x02 \x01(\x0b\x32>.temporal.api.workflow.v1.PendingActivityInfo.PauseInfo.ManualH\x00\x12L\n\x04rule\x18\x04 \x01(\x0b\x32<.temporal.api.workflow.v1.PendingActivityInfo.PauseInfo.RuleH\x00\x1a*\n\x06Manual\x12\x10\n\x08identity\x18\x01 \x01(\t\x12\x0e\n\x06reason\x18\x02 \x01(\t\x1a\x39\n\x04Rule\x12\x0f\n\x07rule_id\x18\x01 \x01(\t\x12\x10\n\x08identity\x18\x02 \x01(\t\x12\x0e\n\x06reason\x18\x03 \x01(\tB\x0b\n\tpaused_byB\x13\n\x11\x61ssigned_build_id"\xb9\x01\n\x19PendingChildExecutionInfo\x12\x13\n\x0bworkflow_id\x18\x01 \x01(\t\x12\x0e\n\x06run_id\x18\x02 \x01(\t\x12\x1a\n\x12workflow_type_name\x18\x03 \x01(\t\x12\x14\n\x0cinitiated_id\x18\x04 \x01(\x03\x12\x45\n\x13parent_close_policy\x18\x05 \x01(\x0e\x32(.temporal.api.enums.v1.ParentClosePolicy"\x8d\x02\n\x17PendingWorkflowTaskInfo\x12>\n\x05state\x18\x01 \x01(\x0e\x32/.temporal.api.enums.v1.PendingWorkflowTaskState\x12\x32\n\x0escheduled_time\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12;\n\x17original_scheduled_time\x18\x03 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x30\n\x0cstarted_time\x18\x04 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x0f\n\x07\x61ttempt\x18\x05 \x01(\x05"G\n\x0bResetPoints\x12\x38\n\x06points\x18\x01 \x03(\x0b\x32(.temporal.api.workflow.v1.ResetPointInfo"\xef\x01\n\x0eResetPointInfo\x12\x10\n\x08\x62uild_id\x18\x07 \x01(\t\x12\x1b\n\x0f\x62inary_checksum\x18\x01 \x01(\tB\x02\x18\x01\x12\x0e\n\x06run_id\x18\x02 \x01(\t\x12(\n first_workflow_task_completed_id\x18\x03 \x01(\x03\x12/\n\x0b\x63reate_time\x18\x04 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12/\n\x0b\x65xpire_time\x18\x05 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x12\n\nresettable\x18\x06 \x01(\x08"\x85\x07\n\x18NewWorkflowExecutionInfo\x12\x13\n\x0bworkflow_id\x18\x01 \x01(\t\x12;\n\rworkflow_type\x18\x02 \x01(\x0b\x32$.temporal.api.common.v1.WorkflowType\x12\x38\n\ntask_queue\x18\x03 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12/\n\x05input\x18\x04 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12=\n\x1aworkflow_execution_timeout\x18\x05 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x37\n\x14workflow_run_timeout\x18\x06 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x38\n\x15workflow_task_timeout\x18\x07 \x01(\x0b\x32\x19.google.protobuf.Duration\x12N\n\x18workflow_id_reuse_policy\x18\x08 \x01(\x0e\x32,.temporal.api.enums.v1.WorkflowIdReusePolicy\x12\x39\n\x0cretry_policy\x18\t \x01(\x0b\x32#.temporal.api.common.v1.RetryPolicy\x12\x15\n\rcron_schedule\x18\n \x01(\t\x12*\n\x04memo\x18\x0b \x01(\x0b\x32\x1c.temporal.api.common.v1.Memo\x12\x43\n\x11search_attributes\x18\x0c \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes\x12.\n\x06header\x18\r \x01(\x0b\x32\x1e.temporal.api.common.v1.Header\x12\x38\n\ruser_metadata\x18\x0e \x01(\x0b\x32!.temporal.api.sdk.v1.UserMetadata\x12I\n\x13versioning_override\x18\x0f \x01(\x0b\x32,.temporal.api.workflow.v1.VersioningOverride\x12\x32\n\x08priority\x18\x10 \x01(\x0b\x32 .temporal.api.common.v1.Priority"\xd2\x04\n\x0c\x43\x61llbackInfo\x12\x32\n\x08\x63\x61llback\x18\x01 \x01(\x0b\x32 .temporal.api.common.v1.Callback\x12?\n\x07trigger\x18\x02 \x01(\x0b\x32..temporal.api.workflow.v1.CallbackInfo.Trigger\x12\x35\n\x11registration_time\x18\x03 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x33\n\x05state\x18\x04 \x01(\x0e\x32$.temporal.api.enums.v1.CallbackState\x12\x0f\n\x07\x61ttempt\x18\x05 \x01(\x05\x12>\n\x1alast_attempt_complete_time\x18\x06 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12>\n\x14last_attempt_failure\x18\x07 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12>\n\x1anext_attempt_schedule_time\x18\x08 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x16\n\x0e\x62locked_reason\x18\t \x01(\t\x1a\x10\n\x0eWorkflowClosed\x1a\x66\n\x07Trigger\x12P\n\x0fworkflow_closed\x18\x01 \x01(\x0b\x32\x35.temporal.api.workflow.v1.CallbackInfo.WorkflowClosedH\x00\x42\t\n\x07variant"\x8b\x06\n\x19PendingNexusOperationInfo\x12\x10\n\x08\x65ndpoint\x18\x01 \x01(\t\x12\x0f\n\x07service\x18\x02 \x01(\t\x12\x11\n\toperation\x18\x03 \x01(\t\x12\x18\n\x0coperation_id\x18\x04 \x01(\tB\x02\x18\x01\x12<\n\x19schedule_to_close_timeout\x18\x05 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x32\n\x0escheduled_time\x18\x06 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12@\n\x05state\x18\x07 \x01(\x0e\x32\x31.temporal.api.enums.v1.PendingNexusOperationState\x12\x0f\n\x07\x61ttempt\x18\x08 \x01(\x05\x12>\n\x1alast_attempt_complete_time\x18\t \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12>\n\x14last_attempt_failure\x18\n \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12>\n\x1anext_attempt_schedule_time\x18\x0b \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12S\n\x11\x63\x61ncellation_info\x18\x0c \x01(\x0b\x32\x38.temporal.api.workflow.v1.NexusOperationCancellationInfo\x12\x1a\n\x12scheduled_event_id\x18\r \x01(\x03\x12\x16\n\x0e\x62locked_reason\x18\x0e \x01(\t\x12\x17\n\x0foperation_token\x18\x0f \x01(\t\x12<\n\x19schedule_to_start_timeout\x18\x10 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x39\n\x16start_to_close_timeout\x18\x11 \x01(\x0b\x32\x19.google.protobuf.Duration"\x84\x03\n\x1eNexusOperationCancellationInfo\x12\x32\n\x0erequested_time\x18\x01 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x45\n\x05state\x18\x02 \x01(\x0e\x32\x36.temporal.api.enums.v1.NexusOperationCancellationState\x12\x0f\n\x07\x61ttempt\x18\x03 \x01(\x05\x12>\n\x1alast_attempt_complete_time\x18\x04 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12>\n\x14last_attempt_failure\x18\x05 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12>\n\x1anext_attempt_schedule_time\x18\x06 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x16\n\x0e\x62locked_reason\x18\x07 \x01(\t"\x99\x01\n\x18WorkflowExecutionOptions\x12I\n\x13versioning_override\x18\x01 \x01(\x0b\x32,.temporal.api.workflow.v1.VersioningOverride\x12\x32\n\x08priority\x18\x02 \x01(\x0b\x32 .temporal.api.common.v1.Priority"\xbd\x04\n\x12VersioningOverride\x12M\n\x06pinned\x18\x03 \x01(\x0b\x32;.temporal.api.workflow.v1.VersioningOverride.PinnedOverrideH\x00\x12\x16\n\x0c\x61uto_upgrade\x18\x04 \x01(\x08H\x00\x12?\n\x08\x62\x65havior\x18\x01 \x01(\x0e\x32).temporal.api.enums.v1.VersioningBehaviorB\x02\x18\x01\x12>\n\ndeployment\x18\x02 \x01(\x0b\x32&.temporal.api.deployment.v1.DeploymentB\x02\x18\x01\x12\x1a\n\x0epinned_version\x18\t \x01(\tB\x02\x18\x01\x1a\xad\x01\n\x0ePinnedOverride\x12U\n\x08\x62\x65havior\x18\x01 \x01(\x0e\x32\x43.temporal.api.workflow.v1.VersioningOverride.PinnedOverrideBehavior\x12\x44\n\x07version\x18\x02 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersion"g\n\x16PinnedOverrideBehavior\x12(\n$PINNED_OVERRIDE_BEHAVIOR_UNSPECIFIED\x10\x00\x12#\n\x1fPINNED_OVERRIDE_BEHAVIOR_PINNED\x10\x01\x42\n\n\x08override"i\n\x11OnConflictOptions\x12\x19\n\x11\x61ttach_request_id\x18\x01 \x01(\x08\x12#\n\x1b\x61ttach_completion_callbacks\x18\x02 \x01(\x08\x12\x14\n\x0c\x61ttach_links\x18\x03 \x01(\x08"i\n\rRequestIdInfo\x12\x34\n\nevent_type\x18\x01 \x01(\x0e\x32 .temporal.api.enums.v1.EventType\x12\x10\n\x08\x65vent_id\x18\x02 \x01(\x03\x12\x10\n\x08\x62uffered\x18\x03 \x01(\x08"\xb7\x04\n\x12PostResetOperation\x12V\n\x0fsignal_workflow\x18\x01 \x01(\x0b\x32;.temporal.api.workflow.v1.PostResetOperation.SignalWorkflowH\x00\x12\x65\n\x17update_workflow_options\x18\x02 \x01(\x0b\x32\x42.temporal.api.workflow.v1.PostResetOperation.UpdateWorkflowOptionsH\x00\x1a\xb3\x01\n\x0eSignalWorkflow\x12\x13\n\x0bsignal_name\x18\x01 \x01(\t\x12/\n\x05input\x18\x02 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12.\n\x06header\x18\x03 \x01(\x0b\x32\x1e.temporal.api.common.v1.Header\x12+\n\x05links\x18\x04 \x03(\x0b\x32\x1c.temporal.api.common.v1.Link\x1a\xa0\x01\n\x15UpdateWorkflowOptions\x12V\n\x1aworkflow_execution_options\x18\x01 \x01(\x0b\x32\x32.temporal.api.workflow.v1.WorkflowExecutionOptions\x12/\n\x0bupdate_mask\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.FieldMaskB\t\n\x07variant"o\n\x1aWorkflowExecutionPauseInfo\x12\x10\n\x08identity\x18\x01 \x01(\t\x12/\n\x0bpaused_time\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x0e\n\x06reason\x18\x03 \x01(\tB\x93\x01\n\x1bio.temporal.api.workflow.v1B\x0cMessageProtoP\x01Z\'go.temporal.io/api/workflow/v1;workflow\xaa\x02\x1aTemporalio.Api.Workflow.V1\xea\x02\x1dTemporalio::Api::Workflow::V1b\x06proto3' + b'\n&temporal/api/workflow/v1/message.proto\x12\x18temporal.api.workflow.v1\x1a\x1egoogle/protobuf/duration.proto\x1a\x1bgoogle/protobuf/empty.proto\x1a\x1fgoogle/protobuf/timestamp.proto\x1a google/protobuf/field_mask.proto\x1a&temporal/api/activity/v1/message.proto\x1a"temporal/api/enums/v1/common.proto\x1a&temporal/api/enums/v1/event_type.proto\x1a$temporal/api/enums/v1/workflow.proto\x1a$temporal/api/common/v1/message.proto\x1a(temporal/api/deployment/v1/message.proto\x1a%temporal/api/failure/v1/message.proto\x1a\'temporal/api/taskqueue/v1/message.proto\x1a\'temporal/api/sdk/v1/user_metadata.proto"\xf0\t\n\x15WorkflowExecutionInfo\x12<\n\texecution\x18\x01 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x32\n\x04type\x18\x02 \x01(\x0b\x32$.temporal.api.common.v1.WorkflowType\x12.\n\nstart_time\x18\x03 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12.\n\nclose_time\x18\x04 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12>\n\x06status\x18\x05 \x01(\x0e\x32..temporal.api.enums.v1.WorkflowExecutionStatus\x12\x16\n\x0ehistory_length\x18\x06 \x01(\x03\x12\x1b\n\x13parent_namespace_id\x18\x07 \x01(\t\x12\x43\n\x10parent_execution\x18\x08 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x32\n\x0e\x65xecution_time\x18\t \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12*\n\x04memo\x18\n \x01(\x0b\x32\x1c.temporal.api.common.v1.Memo\x12\x43\n\x11search_attributes\x18\x0b \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes\x12@\n\x11\x61uto_reset_points\x18\x0c \x01(\x0b\x32%.temporal.api.workflow.v1.ResetPoints\x12\x12\n\ntask_queue\x18\r \x01(\t\x12\x1e\n\x16state_transition_count\x18\x0e \x01(\x03\x12\x1a\n\x12history_size_bytes\x18\x0f \x01(\x03\x12X\n most_recent_worker_version_stamp\x18\x10 \x01(\x0b\x32*.temporal.api.common.v1.WorkerVersionStampB\x02\x18\x01\x12\x35\n\x12\x65xecution_duration\x18\x11 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x41\n\x0eroot_execution\x18\x12 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x1d\n\x11\x61ssigned_build_id\x18\x13 \x01(\tB\x02\x18\x01\x12\x1e\n\x12inherited_build_id\x18\x14 \x01(\tB\x02\x18\x01\x12\x14\n\x0c\x66irst_run_id\x18\x15 \x01(\t\x12R\n\x0fversioning_info\x18\x16 \x01(\x0b\x32\x39.temporal.api.workflow.v1.WorkflowExecutionVersioningInfo\x12\x1e\n\x16worker_deployment_name\x18\x17 \x01(\t\x12\x32\n\x08priority\x18\x18 \x01(\x0b\x32 .temporal.api.common.v1.Priority\x12#\n\x1b\x65xternal_payload_size_bytes\x18\x19 \x01(\x03\x12\x1e\n\x16\x65xternal_payload_count\x18\x1a \x01(\x03"\xc6\x04\n\x1dWorkflowExecutionExtendedInfo\x12=\n\x19\x65xecution_expiration_time\x18\x01 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x37\n\x13run_expiration_time\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x18\n\x10\x63\x61ncel_requested\x18\x03 \x01(\x08\x12\x33\n\x0flast_reset_time\x18\x04 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x37\n\x13original_start_time\x18\x05 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x14\n\x0creset_run_id\x18\x06 \x01(\t\x12\x65\n\x10request_id_infos\x18\x07 \x03(\x0b\x32K.temporal.api.workflow.v1.WorkflowExecutionExtendedInfo.RequestIdInfosEntry\x12H\n\npause_info\x18\x08 \x01(\x0b\x32\x34.temporal.api.workflow.v1.WorkflowExecutionPauseInfo\x1a^\n\x13RequestIdInfosEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x36\n\x05value\x18\x02 \x01(\x0b\x32\'.temporal.api.workflow.v1.RequestIdInfo:\x02\x38\x01"\xfb\x04\n\x1fWorkflowExecutionVersioningInfo\x12;\n\x08\x62\x65havior\x18\x01 \x01(\x0e\x32).temporal.api.enums.v1.VersioningBehavior\x12>\n\ndeployment\x18\x02 \x01(\x0b\x32&.temporal.api.deployment.v1.DeploymentB\x02\x18\x01\x12\x13\n\x07version\x18\x05 \x01(\tB\x02\x18\x01\x12O\n\x12\x64\x65ployment_version\x18\x07 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersion\x12I\n\x13versioning_override\x18\x03 \x01(\x0b\x32,.temporal.api.workflow.v1.VersioningOverride\x12Q\n\x15\x64\x65ployment_transition\x18\x04 \x01(\x0b\x32..temporal.api.workflow.v1.DeploymentTransitionB\x02\x18\x01\x12Q\n\x12version_transition\x18\x06 \x01(\x0b\x32\x35.temporal.api.workflow.v1.DeploymentVersionTransition\x12\x17\n\x0frevision_number\x18\x08 \x01(\x03\x12k\n+continue_as_new_initial_versioning_behavior\x18\t \x01(\x0e\x32\x36.temporal.api.enums.v1.ContinueAsNewVersioningBehavior"R\n\x14\x44\x65ploymentTransition\x12:\n\ndeployment\x18\x01 \x01(\x0b\x32&.temporal.api.deployment.v1.Deployment"\x83\x01\n\x1b\x44\x65ploymentVersionTransition\x12\x13\n\x07version\x18\x01 \x01(\tB\x02\x18\x01\x12O\n\x12\x64\x65ployment_version\x18\x02 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersion"\xc7\x02\n\x17WorkflowExecutionConfig\x12\x38\n\ntask_queue\x18\x01 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12=\n\x1aworkflow_execution_timeout\x18\x02 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x37\n\x14workflow_run_timeout\x18\x03 \x01(\x0b\x32\x19.google.protobuf.Duration\x12@\n\x1d\x64\x65\x66\x61ult_workflow_task_timeout\x18\x04 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x38\n\ruser_metadata\x18\x05 \x01(\x0b\x32!.temporal.api.sdk.v1.UserMetadata"\xbd\r\n\x13PendingActivityInfo\x12\x13\n\x0b\x61\x63tivity_id\x18\x01 \x01(\t\x12;\n\ractivity_type\x18\x02 \x01(\x0b\x32$.temporal.api.common.v1.ActivityType\x12:\n\x05state\x18\x03 \x01(\x0e\x32+.temporal.api.enums.v1.PendingActivityState\x12;\n\x11heartbeat_details\x18\x04 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x37\n\x13last_heartbeat_time\x18\x05 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x35\n\x11last_started_time\x18\x06 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x0f\n\x07\x61ttempt\x18\x07 \x01(\x05\x12\x18\n\x10maximum_attempts\x18\x08 \x01(\x05\x12\x32\n\x0escheduled_time\x18\t \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x33\n\x0f\x65xpiration_time\x18\n \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x36\n\x0clast_failure\x18\x0b \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12\x1c\n\x14last_worker_identity\x18\x0c \x01(\t\x12;\n\x15use_workflow_build_id\x18\r \x01(\x0b\x32\x16.google.protobuf.EmptyB\x02\x18\x01H\x00\x12\x32\n$last_independently_assigned_build_id\x18\x0e \x01(\tB\x02\x18\x01H\x00\x12Q\n\x19last_worker_version_stamp\x18\x0f \x01(\x0b\x32*.temporal.api.common.v1.WorkerVersionStampB\x02\x18\x01\x12\x39\n\x16\x63urrent_retry_interval\x18\x10 \x01(\x0b\x32\x19.google.protobuf.Duration\x12>\n\x1alast_attempt_complete_time\x18\x11 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12>\n\x1anext_attempt_schedule_time\x18\x12 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x0e\n\x06paused\x18\x13 \x01(\x08\x12\x43\n\x0flast_deployment\x18\x14 \x01(\x0b\x32&.temporal.api.deployment.v1.DeploymentB\x02\x18\x01\x12*\n\x1elast_worker_deployment_version\x18\x15 \x01(\tB\x02\x18\x01\x12T\n\x17last_deployment_version\x18\x19 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersion\x12\x32\n\x08priority\x18\x16 \x01(\x0b\x32 .temporal.api.common.v1.Priority\x12K\n\npause_info\x18\x17 \x01(\x0b\x32\x37.temporal.api.workflow.v1.PendingActivityInfo.PauseInfo\x12\x43\n\x10\x61\x63tivity_options\x18\x18 \x01(\x0b\x32).temporal.api.activity.v1.ActivityOptions\x1a\xcf\x02\n\tPauseInfo\x12.\n\npause_time\x18\x01 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12P\n\x06manual\x18\x02 \x01(\x0b\x32>.temporal.api.workflow.v1.PendingActivityInfo.PauseInfo.ManualH\x00\x12L\n\x04rule\x18\x04 \x01(\x0b\x32<.temporal.api.workflow.v1.PendingActivityInfo.PauseInfo.RuleH\x00\x1a*\n\x06Manual\x12\x10\n\x08identity\x18\x01 \x01(\t\x12\x0e\n\x06reason\x18\x02 \x01(\t\x1a\x39\n\x04Rule\x12\x0f\n\x07rule_id\x18\x01 \x01(\t\x12\x10\n\x08identity\x18\x02 \x01(\t\x12\x0e\n\x06reason\x18\x03 \x01(\tB\x0b\n\tpaused_byB\x13\n\x11\x61ssigned_build_id"\xb9\x01\n\x19PendingChildExecutionInfo\x12\x13\n\x0bworkflow_id\x18\x01 \x01(\t\x12\x0e\n\x06run_id\x18\x02 \x01(\t\x12\x1a\n\x12workflow_type_name\x18\x03 \x01(\t\x12\x14\n\x0cinitiated_id\x18\x04 \x01(\x03\x12\x45\n\x13parent_close_policy\x18\x05 \x01(\x0e\x32(.temporal.api.enums.v1.ParentClosePolicy"\x8d\x02\n\x17PendingWorkflowTaskInfo\x12>\n\x05state\x18\x01 \x01(\x0e\x32/.temporal.api.enums.v1.PendingWorkflowTaskState\x12\x32\n\x0escheduled_time\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12;\n\x17original_scheduled_time\x18\x03 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x30\n\x0cstarted_time\x18\x04 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x0f\n\x07\x61ttempt\x18\x05 \x01(\x05"G\n\x0bResetPoints\x12\x38\n\x06points\x18\x01 \x03(\x0b\x32(.temporal.api.workflow.v1.ResetPointInfo"\xef\x01\n\x0eResetPointInfo\x12\x10\n\x08\x62uild_id\x18\x07 \x01(\t\x12\x1b\n\x0f\x62inary_checksum\x18\x01 \x01(\tB\x02\x18\x01\x12\x0e\n\x06run_id\x18\x02 \x01(\t\x12(\n first_workflow_task_completed_id\x18\x03 \x01(\x03\x12/\n\x0b\x63reate_time\x18\x04 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12/\n\x0b\x65xpire_time\x18\x05 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x12\n\nresettable\x18\x06 \x01(\x08"\x85\x07\n\x18NewWorkflowExecutionInfo\x12\x13\n\x0bworkflow_id\x18\x01 \x01(\t\x12;\n\rworkflow_type\x18\x02 \x01(\x0b\x32$.temporal.api.common.v1.WorkflowType\x12\x38\n\ntask_queue\x18\x03 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12/\n\x05input\x18\x04 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12=\n\x1aworkflow_execution_timeout\x18\x05 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x37\n\x14workflow_run_timeout\x18\x06 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x38\n\x15workflow_task_timeout\x18\x07 \x01(\x0b\x32\x19.google.protobuf.Duration\x12N\n\x18workflow_id_reuse_policy\x18\x08 \x01(\x0e\x32,.temporal.api.enums.v1.WorkflowIdReusePolicy\x12\x39\n\x0cretry_policy\x18\t \x01(\x0b\x32#.temporal.api.common.v1.RetryPolicy\x12\x15\n\rcron_schedule\x18\n \x01(\t\x12*\n\x04memo\x18\x0b \x01(\x0b\x32\x1c.temporal.api.common.v1.Memo\x12\x43\n\x11search_attributes\x18\x0c \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes\x12.\n\x06header\x18\r \x01(\x0b\x32\x1e.temporal.api.common.v1.Header\x12\x38\n\ruser_metadata\x18\x0e \x01(\x0b\x32!.temporal.api.sdk.v1.UserMetadata\x12I\n\x13versioning_override\x18\x0f \x01(\x0b\x32,.temporal.api.workflow.v1.VersioningOverride\x12\x32\n\x08priority\x18\x10 \x01(\x0b\x32 .temporal.api.common.v1.Priority"\xd2\x04\n\x0c\x43\x61llbackInfo\x12\x32\n\x08\x63\x61llback\x18\x01 \x01(\x0b\x32 .temporal.api.common.v1.Callback\x12?\n\x07trigger\x18\x02 \x01(\x0b\x32..temporal.api.workflow.v1.CallbackInfo.Trigger\x12\x35\n\x11registration_time\x18\x03 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x33\n\x05state\x18\x04 \x01(\x0e\x32$.temporal.api.enums.v1.CallbackState\x12\x0f\n\x07\x61ttempt\x18\x05 \x01(\x05\x12>\n\x1alast_attempt_complete_time\x18\x06 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12>\n\x14last_attempt_failure\x18\x07 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12>\n\x1anext_attempt_schedule_time\x18\x08 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x16\n\x0e\x62locked_reason\x18\t \x01(\t\x1a\x10\n\x0eWorkflowClosed\x1a\x66\n\x07Trigger\x12P\n\x0fworkflow_closed\x18\x01 \x01(\x0b\x32\x35.temporal.api.workflow.v1.CallbackInfo.WorkflowClosedH\x00\x42\t\n\x07variant"\x8b\x06\n\x19PendingNexusOperationInfo\x12\x10\n\x08\x65ndpoint\x18\x01 \x01(\t\x12\x0f\n\x07service\x18\x02 \x01(\t\x12\x11\n\toperation\x18\x03 \x01(\t\x12\x18\n\x0coperation_id\x18\x04 \x01(\tB\x02\x18\x01\x12<\n\x19schedule_to_close_timeout\x18\x05 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x32\n\x0escheduled_time\x18\x06 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12@\n\x05state\x18\x07 \x01(\x0e\x32\x31.temporal.api.enums.v1.PendingNexusOperationState\x12\x0f\n\x07\x61ttempt\x18\x08 \x01(\x05\x12>\n\x1alast_attempt_complete_time\x18\t \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12>\n\x14last_attempt_failure\x18\n \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12>\n\x1anext_attempt_schedule_time\x18\x0b \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12S\n\x11\x63\x61ncellation_info\x18\x0c \x01(\x0b\x32\x38.temporal.api.workflow.v1.NexusOperationCancellationInfo\x12\x1a\n\x12scheduled_event_id\x18\r \x01(\x03\x12\x16\n\x0e\x62locked_reason\x18\x0e \x01(\t\x12\x17\n\x0foperation_token\x18\x0f \x01(\t\x12<\n\x19schedule_to_start_timeout\x18\x10 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x39\n\x16start_to_close_timeout\x18\x11 \x01(\x0b\x32\x19.google.protobuf.Duration"\x84\x03\n\x1eNexusOperationCancellationInfo\x12\x32\n\x0erequested_time\x18\x01 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x45\n\x05state\x18\x02 \x01(\x0e\x32\x36.temporal.api.enums.v1.NexusOperationCancellationState\x12\x0f\n\x07\x61ttempt\x18\x03 \x01(\x05\x12>\n\x1alast_attempt_complete_time\x18\x04 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12>\n\x14last_attempt_failure\x18\x05 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12>\n\x1anext_attempt_schedule_time\x18\x06 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x16\n\x0e\x62locked_reason\x18\x07 \x01(\t"\xe5\x01\n\x18WorkflowExecutionOptions\x12I\n\x13versioning_override\x18\x01 \x01(\x0b\x32,.temporal.api.workflow.v1.VersioningOverride\x12\x32\n\x08priority\x18\x02 \x01(\x0b\x32 .temporal.api.common.v1.Priority\x12J\n\x14time_skipping_config\x18\x03 \x01(\x0b\x32,.temporal.api.workflow.v1.TimeSkippingConfig"\xd6\x01\n\x12TimeSkippingConfig\x12\x0f\n\x07\x65nabled\x18\x01 \x01(\x08\x12\x39\n\x14max_skipped_duration\x18\x04 \x01(\x0b\x32\x19.google.protobuf.DurationH\x00\x12\x39\n\x14max_elapsed_duration\x18\x05 \x01(\x0b\x32\x19.google.protobuf.DurationH\x00\x42\x07\n\x05\x62oundJ\x04\x08\x02\x10\x03J\x04\x08\x06\x10\x07R\x13\x64isable_propagationR\x0fmax_target_time"\xbd\x04\n\x12VersioningOverride\x12M\n\x06pinned\x18\x03 \x01(\x0b\x32;.temporal.api.workflow.v1.VersioningOverride.PinnedOverrideH\x00\x12\x16\n\x0c\x61uto_upgrade\x18\x04 \x01(\x08H\x00\x12?\n\x08\x62\x65havior\x18\x01 \x01(\x0e\x32).temporal.api.enums.v1.VersioningBehaviorB\x02\x18\x01\x12>\n\ndeployment\x18\x02 \x01(\x0b\x32&.temporal.api.deployment.v1.DeploymentB\x02\x18\x01\x12\x1a\n\x0epinned_version\x18\t \x01(\tB\x02\x18\x01\x1a\xad\x01\n\x0ePinnedOverride\x12U\n\x08\x62\x65havior\x18\x01 \x01(\x0e\x32\x43.temporal.api.workflow.v1.VersioningOverride.PinnedOverrideBehavior\x12\x44\n\x07version\x18\x02 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersion"g\n\x16PinnedOverrideBehavior\x12(\n$PINNED_OVERRIDE_BEHAVIOR_UNSPECIFIED\x10\x00\x12#\n\x1fPINNED_OVERRIDE_BEHAVIOR_PINNED\x10\x01\x42\n\n\x08override"i\n\x11OnConflictOptions\x12\x19\n\x11\x61ttach_request_id\x18\x01 \x01(\x08\x12#\n\x1b\x61ttach_completion_callbacks\x18\x02 \x01(\x08\x12\x14\n\x0c\x61ttach_links\x18\x03 \x01(\x08"i\n\rRequestIdInfo\x12\x34\n\nevent_type\x18\x01 \x01(\x0e\x32 .temporal.api.enums.v1.EventType\x12\x10\n\x08\x65vent_id\x18\x02 \x01(\x03\x12\x10\n\x08\x62uffered\x18\x03 \x01(\x08"\xb7\x04\n\x12PostResetOperation\x12V\n\x0fsignal_workflow\x18\x01 \x01(\x0b\x32;.temporal.api.workflow.v1.PostResetOperation.SignalWorkflowH\x00\x12\x65\n\x17update_workflow_options\x18\x02 \x01(\x0b\x32\x42.temporal.api.workflow.v1.PostResetOperation.UpdateWorkflowOptionsH\x00\x1a\xb3\x01\n\x0eSignalWorkflow\x12\x13\n\x0bsignal_name\x18\x01 \x01(\t\x12/\n\x05input\x18\x02 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12.\n\x06header\x18\x03 \x01(\x0b\x32\x1e.temporal.api.common.v1.Header\x12+\n\x05links\x18\x04 \x03(\x0b\x32\x1c.temporal.api.common.v1.Link\x1a\xa0\x01\n\x15UpdateWorkflowOptions\x12V\n\x1aworkflow_execution_options\x18\x01 \x01(\x0b\x32\x32.temporal.api.workflow.v1.WorkflowExecutionOptions\x12/\n\x0bupdate_mask\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.FieldMaskB\t\n\x07variant"o\n\x1aWorkflowExecutionPauseInfo\x12\x10\n\x08identity\x18\x01 \x01(\t\x12/\n\x0bpaused_time\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x0e\n\x06reason\x18\x03 \x01(\tB\x93\x01\n\x1bio.temporal.api.workflow.v1B\x0cMessageProtoP\x01Z\'go.temporal.io/api/workflow/v1;workflow\xaa\x02\x1aTemporalio.Api.Workflow.V1\xea\x02\x1dTemporalio::Api::Workflow::V1b\x06proto3' ) @@ -92,6 +92,7 @@ "NexusOperationCancellationInfo" ] _WORKFLOWEXECUTIONOPTIONS = DESCRIPTOR.message_types_by_name["WorkflowExecutionOptions"] +_TIMESKIPPINGCONFIG = DESCRIPTOR.message_types_by_name["TimeSkippingConfig"] _VERSIONINGOVERRIDE = DESCRIPTOR.message_types_by_name["VersioningOverride"] _VERSIONINGOVERRIDE_PINNEDOVERRIDE = _VERSIONINGOVERRIDE.nested_types_by_name[ "PinnedOverride" @@ -347,6 +348,17 @@ ) _sym_db.RegisterMessage(WorkflowExecutionOptions) +TimeSkippingConfig = _reflection.GeneratedProtocolMessageType( + "TimeSkippingConfig", + (_message.Message,), + { + "DESCRIPTOR": _TIMESKIPPINGCONFIG, + "__module__": "temporalio.api.workflow.v1.message_pb2", + # @@protoc_insertion_point(class_scope:temporal.api.workflow.v1.TimeSkippingConfig) + }, +) +_sym_db.RegisterMessage(TimeSkippingConfig) + VersioningOverride = _reflection.GeneratedProtocolMessageType( "VersioningOverride", (_message.Message,), @@ -514,59 +526,61 @@ _WORKFLOWEXECUTIONEXTENDEDINFO_REQUESTIDINFOSENTRY._serialized_start = 2307 _WORKFLOWEXECUTIONEXTENDEDINFO_REQUESTIDINFOSENTRY._serialized_end = 2401 _WORKFLOWEXECUTIONVERSIONINGINFO._serialized_start = 2404 - _WORKFLOWEXECUTIONVERSIONINGINFO._serialized_end = 2930 - _DEPLOYMENTTRANSITION._serialized_start = 2932 - _DEPLOYMENTTRANSITION._serialized_end = 3014 - _DEPLOYMENTVERSIONTRANSITION._serialized_start = 3017 - _DEPLOYMENTVERSIONTRANSITION._serialized_end = 3148 - _WORKFLOWEXECUTIONCONFIG._serialized_start = 3151 - _WORKFLOWEXECUTIONCONFIG._serialized_end = 3478 - _PENDINGACTIVITYINFO._serialized_start = 3481 - _PENDINGACTIVITYINFO._serialized_end = 5206 - _PENDINGACTIVITYINFO_PAUSEINFO._serialized_start = 4850 - _PENDINGACTIVITYINFO_PAUSEINFO._serialized_end = 5185 - _PENDINGACTIVITYINFO_PAUSEINFO_MANUAL._serialized_start = 5071 - _PENDINGACTIVITYINFO_PAUSEINFO_MANUAL._serialized_end = 5113 - _PENDINGACTIVITYINFO_PAUSEINFO_RULE._serialized_start = 5115 - _PENDINGACTIVITYINFO_PAUSEINFO_RULE._serialized_end = 5172 - _PENDINGCHILDEXECUTIONINFO._serialized_start = 5209 - _PENDINGCHILDEXECUTIONINFO._serialized_end = 5394 - _PENDINGWORKFLOWTASKINFO._serialized_start = 5397 - _PENDINGWORKFLOWTASKINFO._serialized_end = 5666 - _RESETPOINTS._serialized_start = 5668 - _RESETPOINTS._serialized_end = 5739 - _RESETPOINTINFO._serialized_start = 5742 - _RESETPOINTINFO._serialized_end = 5981 - _NEWWORKFLOWEXECUTIONINFO._serialized_start = 5984 - _NEWWORKFLOWEXECUTIONINFO._serialized_end = 6885 - _CALLBACKINFO._serialized_start = 6888 - _CALLBACKINFO._serialized_end = 7482 - _CALLBACKINFO_WORKFLOWCLOSED._serialized_start = 7362 - _CALLBACKINFO_WORKFLOWCLOSED._serialized_end = 7378 - _CALLBACKINFO_TRIGGER._serialized_start = 7380 - _CALLBACKINFO_TRIGGER._serialized_end = 7482 - _PENDINGNEXUSOPERATIONINFO._serialized_start = 7485 - _PENDINGNEXUSOPERATIONINFO._serialized_end = 8264 - _NEXUSOPERATIONCANCELLATIONINFO._serialized_start = 8267 - _NEXUSOPERATIONCANCELLATIONINFO._serialized_end = 8655 - _WORKFLOWEXECUTIONOPTIONS._serialized_start = 8658 - _WORKFLOWEXECUTIONOPTIONS._serialized_end = 8811 - _VERSIONINGOVERRIDE._serialized_start = 8814 - _VERSIONINGOVERRIDE._serialized_end = 9387 - _VERSIONINGOVERRIDE_PINNEDOVERRIDE._serialized_start = 9097 - _VERSIONINGOVERRIDE_PINNEDOVERRIDE._serialized_end = 9270 - _VERSIONINGOVERRIDE_PINNEDOVERRIDEBEHAVIOR._serialized_start = 9272 - _VERSIONINGOVERRIDE_PINNEDOVERRIDEBEHAVIOR._serialized_end = 9375 - _ONCONFLICTOPTIONS._serialized_start = 9389 - _ONCONFLICTOPTIONS._serialized_end = 9494 - _REQUESTIDINFO._serialized_start = 9496 - _REQUESTIDINFO._serialized_end = 9601 - _POSTRESETOPERATION._serialized_start = 9604 - _POSTRESETOPERATION._serialized_end = 10171 - _POSTRESETOPERATION_SIGNALWORKFLOW._serialized_start = 9818 - _POSTRESETOPERATION_SIGNALWORKFLOW._serialized_end = 9997 - _POSTRESETOPERATION_UPDATEWORKFLOWOPTIONS._serialized_start = 10000 - _POSTRESETOPERATION_UPDATEWORKFLOWOPTIONS._serialized_end = 10160 - _WORKFLOWEXECUTIONPAUSEINFO._serialized_start = 10173 - _WORKFLOWEXECUTIONPAUSEINFO._serialized_end = 10284 + _WORKFLOWEXECUTIONVERSIONINGINFO._serialized_end = 3039 + _DEPLOYMENTTRANSITION._serialized_start = 3041 + _DEPLOYMENTTRANSITION._serialized_end = 3123 + _DEPLOYMENTVERSIONTRANSITION._serialized_start = 3126 + _DEPLOYMENTVERSIONTRANSITION._serialized_end = 3257 + _WORKFLOWEXECUTIONCONFIG._serialized_start = 3260 + _WORKFLOWEXECUTIONCONFIG._serialized_end = 3587 + _PENDINGACTIVITYINFO._serialized_start = 3590 + _PENDINGACTIVITYINFO._serialized_end = 5315 + _PENDINGACTIVITYINFO_PAUSEINFO._serialized_start = 4959 + _PENDINGACTIVITYINFO_PAUSEINFO._serialized_end = 5294 + _PENDINGACTIVITYINFO_PAUSEINFO_MANUAL._serialized_start = 5180 + _PENDINGACTIVITYINFO_PAUSEINFO_MANUAL._serialized_end = 5222 + _PENDINGACTIVITYINFO_PAUSEINFO_RULE._serialized_start = 5224 + _PENDINGACTIVITYINFO_PAUSEINFO_RULE._serialized_end = 5281 + _PENDINGCHILDEXECUTIONINFO._serialized_start = 5318 + _PENDINGCHILDEXECUTIONINFO._serialized_end = 5503 + _PENDINGWORKFLOWTASKINFO._serialized_start = 5506 + _PENDINGWORKFLOWTASKINFO._serialized_end = 5775 + _RESETPOINTS._serialized_start = 5777 + _RESETPOINTS._serialized_end = 5848 + _RESETPOINTINFO._serialized_start = 5851 + _RESETPOINTINFO._serialized_end = 6090 + _NEWWORKFLOWEXECUTIONINFO._serialized_start = 6093 + _NEWWORKFLOWEXECUTIONINFO._serialized_end = 6994 + _CALLBACKINFO._serialized_start = 6997 + _CALLBACKINFO._serialized_end = 7591 + _CALLBACKINFO_WORKFLOWCLOSED._serialized_start = 7471 + _CALLBACKINFO_WORKFLOWCLOSED._serialized_end = 7487 + _CALLBACKINFO_TRIGGER._serialized_start = 7489 + _CALLBACKINFO_TRIGGER._serialized_end = 7591 + _PENDINGNEXUSOPERATIONINFO._serialized_start = 7594 + _PENDINGNEXUSOPERATIONINFO._serialized_end = 8373 + _NEXUSOPERATIONCANCELLATIONINFO._serialized_start = 8376 + _NEXUSOPERATIONCANCELLATIONINFO._serialized_end = 8764 + _WORKFLOWEXECUTIONOPTIONS._serialized_start = 8767 + _WORKFLOWEXECUTIONOPTIONS._serialized_end = 8996 + _TIMESKIPPINGCONFIG._serialized_start = 8999 + _TIMESKIPPINGCONFIG._serialized_end = 9213 + _VERSIONINGOVERRIDE._serialized_start = 9216 + _VERSIONINGOVERRIDE._serialized_end = 9789 + _VERSIONINGOVERRIDE_PINNEDOVERRIDE._serialized_start = 9499 + _VERSIONINGOVERRIDE_PINNEDOVERRIDE._serialized_end = 9672 + _VERSIONINGOVERRIDE_PINNEDOVERRIDEBEHAVIOR._serialized_start = 9674 + _VERSIONINGOVERRIDE_PINNEDOVERRIDEBEHAVIOR._serialized_end = 9777 + _ONCONFLICTOPTIONS._serialized_start = 9791 + _ONCONFLICTOPTIONS._serialized_end = 9896 + _REQUESTIDINFO._serialized_start = 9898 + _REQUESTIDINFO._serialized_end = 10003 + _POSTRESETOPERATION._serialized_start = 10006 + _POSTRESETOPERATION._serialized_end = 10573 + _POSTRESETOPERATION_SIGNALWORKFLOW._serialized_start = 10220 + _POSTRESETOPERATION_SIGNALWORKFLOW._serialized_end = 10399 + _POSTRESETOPERATION_UPDATEWORKFLOWOPTIONS._serialized_start = 10402 + _POSTRESETOPERATION_UPDATEWORKFLOWOPTIONS._serialized_end = 10562 + _WORKFLOWEXECUTIONPAUSEINFO._serialized_start = 10575 + _WORKFLOWEXECUTIONPAUSEINFO._serialized_end = 10686 # @@protoc_insertion_point(module_scope) diff --git a/temporalio/api/workflow/v1/message_pb2.pyi b/temporalio/api/workflow/v1/message_pb2.pyi index f18e6bf07..2dbc5c48a 100644 --- a/temporalio/api/workflow/v1/message_pb2.pyi +++ b/temporalio/api/workflow/v1/message_pb2.pyi @@ -156,9 +156,7 @@ class WorkflowExecutionInfo(google.protobuf.message.Message): Experimental. Versioning info is experimental and might change in the future. """ worker_deployment_name: builtins.str - """The name of Worker Deployment that completed the most recent workflow task. - Experimental. Worker Deployments are experimental and might change in the future. - """ + """The name of Worker Deployment that completed the most recent workflow task.""" @property def priority(self) -> temporalio.api.common.v1.message_pb2.Priority: """Priority metadata""" @@ -427,6 +425,7 @@ class WorkflowExecutionVersioningInfo(google.protobuf.message.Message): DEPLOYMENT_TRANSITION_FIELD_NUMBER: builtins.int VERSION_TRANSITION_FIELD_NUMBER: builtins.int REVISION_NUMBER_FIELD_NUMBER: builtins.int + CONTINUE_AS_NEW_INITIAL_VERSIONING_BEHAVIOR_FIELD_NUMBER: builtins.int behavior: temporalio.api.enums.v1.workflow_pb2.VersioningBehavior.ValueType """Versioning behavior determines how the server should treat this execution when workers are upgraded. When present it means this workflow execution is versioned; UNSPECIFIED means @@ -533,6 +532,20 @@ class WorkflowExecutionVersioningInfo(google.protobuf.message.Message): face the problem of inconsistent dispatching that arises from eventual consistency between task queues and their partitions. """ + continue_as_new_initial_versioning_behavior: ( + temporalio.api.enums.v1.workflow_pb2.ContinueAsNewVersioningBehavior.ValueType + ) + """Experimental. + If this workflow is the result of a continue-as-new, this field is set to the initial_versioning_behavior + specified in that command. + Only used for the initial task of this run and the initial task of any retries of this run. + Not passed to children or to future continue-as-new. + + Note: In the first release of Upgrade-on-CaN, when the only ContinueAsNewVersioningBehavior was AutoUpgrade, + a non-empty InheritedAutoUpgradeInfo meant that the workflow should start as AutoUpgrade. So for compatibility + with ContinueAsNew history commands generated during that time, know that an UNSPECIFIED value here is equivalent + to ContinueAsNewVersioningBehaviorAutoUpgrade if the behavior of the workflow is AutoUpgrade. + """ def __init__( self, *, @@ -545,6 +558,7 @@ class WorkflowExecutionVersioningInfo(google.protobuf.message.Message): deployment_transition: global___DeploymentTransition | None = ..., version_transition: global___DeploymentVersionTransition | None = ..., revision_number: builtins.int = ..., + continue_as_new_initial_versioning_behavior: temporalio.api.enums.v1.workflow_pb2.ContinueAsNewVersioningBehavior.ValueType = ..., ) -> None: ... def HasField( self, @@ -566,6 +580,8 @@ class WorkflowExecutionVersioningInfo(google.protobuf.message.Message): field_name: typing_extensions.Literal[ "behavior", b"behavior", + "continue_as_new_initial_versioning_behavior", + b"continue_as_new_initial_versioning_behavior", "deployment", b"deployment", "deployment_transition", @@ -1617,7 +1633,9 @@ class PendingNexusOperationInfo(google.protobuf.message.Message): state: temporalio.api.enums.v1.common_pb2.PendingNexusOperationState.ValueType attempt: builtins.int """The number of attempts made to deliver the start operation request. - This number represents a minimum bound since the attempt is incremented after the request completes. + This number is approximate, it is incremented when a task is added to the history queue. + In practice, there could be more attempts if a task is executed but fails to commit, or less attempts if a task + was never executed. """ @property def last_attempt_complete_time(self) -> google.protobuf.timestamp_pb2.Timestamp: @@ -1822,33 +1840,126 @@ class WorkflowExecutionOptions(google.protobuf.message.Message): VERSIONING_OVERRIDE_FIELD_NUMBER: builtins.int PRIORITY_FIELD_NUMBER: builtins.int + TIME_SKIPPING_CONFIG_FIELD_NUMBER: builtins.int @property def versioning_override(self) -> global___VersioningOverride: """If set, takes precedence over the Versioning Behavior sent by the SDK on Workflow Task completion.""" @property def priority(self) -> temporalio.api.common.v1.message_pb2.Priority: """If set, overrides the workflow's priority sent by the SDK.""" + @property + def time_skipping_config(self) -> global___TimeSkippingConfig: + """Time-skipping configuration for this workflow execution. + If not set, the time-skipping configuration is not updated by this request; + the existing configuration is preserved. + """ def __init__( self, *, versioning_override: global___VersioningOverride | None = ..., priority: temporalio.api.common.v1.message_pb2.Priority | None = ..., + time_skipping_config: global___TimeSkippingConfig | None = ..., ) -> None: ... def HasField( self, field_name: typing_extensions.Literal[ - "priority", b"priority", "versioning_override", b"versioning_override" + "priority", + b"priority", + "time_skipping_config", + b"time_skipping_config", + "versioning_override", + b"versioning_override", ], ) -> builtins.bool: ... def ClearField( self, field_name: typing_extensions.Literal[ - "priority", b"priority", "versioning_override", b"versioning_override" + "priority", + b"priority", + "time_skipping_config", + b"time_skipping_config", + "versioning_override", + b"versioning_override", ], ) -> None: ... global___WorkflowExecutionOptions = WorkflowExecutionOptions +class TimeSkippingConfig(google.protobuf.message.Message): + """Configuration for time skipping during a workflow execution. + When enabled, virtual time advances automatically whenever there is no in-flight work. + In-flight work includes activities, child workflows, Nexus operations, signal/cancel external workflow operations, + and possibly other features added in the future. + User timers are not classified as in-flight work and will be skipped over. + When time advances, it skips to the earlier of the next user timer or the configured bound, if either exists. + + Propagation behavior of time skipping: + The enabled flag, bound fields, and accumulated skipped duration are propagated to related executions as follows: + (1) Child workflows and continue-as-new: both the configuration and the accumulated skipped duration are + inherited from the current execution. The configured bound is shared between the inherited skipped + duration and any additional duration skipped by the new run. + (2) Retry and cron: the configuration and accumulated skipped duration are inherited as recorded when the + current workflow started; the accumulated skipped duration of the current run is not propagated. + (3) Reset: the new run retains the time-skipping configuration of the current execution. Because reset replays + all events up to the reset point and re-applies any UpdateWorkflowExecutionOptions changes made after that + point, the resulting run ends up with the same final time-skipping configuration as the previous run. + """ + + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + ENABLED_FIELD_NUMBER: builtins.int + MAX_SKIPPED_DURATION_FIELD_NUMBER: builtins.int + MAX_ELAPSED_DURATION_FIELD_NUMBER: builtins.int + enabled: builtins.bool + """Enables or disables time skipping for this workflow execution.""" + @property + def max_skipped_duration(self) -> google.protobuf.duration_pb2.Duration: + """Maximum total virtual time that can be skipped.""" + @property + def max_elapsed_duration(self) -> google.protobuf.duration_pb2.Duration: + """Maximum elapsed time since time skipping was enabled. + This includes both skipped time and real time elapsing. + (-- api-linter: core::0142::time-field-names=disabled --) + """ + def __init__( + self, + *, + enabled: builtins.bool = ..., + max_skipped_duration: google.protobuf.duration_pb2.Duration | None = ..., + max_elapsed_duration: google.protobuf.duration_pb2.Duration | None = ..., + ) -> None: ... + def HasField( + self, + field_name: typing_extensions.Literal[ + "bound", + b"bound", + "max_elapsed_duration", + b"max_elapsed_duration", + "max_skipped_duration", + b"max_skipped_duration", + ], + ) -> builtins.bool: ... + def ClearField( + self, + field_name: typing_extensions.Literal[ + "bound", + b"bound", + "enabled", + b"enabled", + "max_elapsed_duration", + b"max_elapsed_duration", + "max_skipped_duration", + b"max_skipped_duration", + ], + ) -> None: ... + def WhichOneof( + self, oneof_group: typing_extensions.Literal["bound", b"bound"] + ) -> ( + typing_extensions.Literal["max_skipped_duration", "max_elapsed_duration"] | None + ): ... + +global___TimeSkippingConfig = TimeSkippingConfig + class VersioningOverride(google.protobuf.message.Message): """Used to override the versioning behavior (and pinned deployment version, if applicable) of a specific workflow execution. If set, this override takes precedence over worker-sent values. diff --git a/temporalio/api/workflowservice/v1/__init__.py b/temporalio/api/workflowservice/v1/__init__.py index ba80b0e9d..1039e5769 100644 --- a/temporalio/api/workflowservice/v1/__init__.py +++ b/temporalio/api/workflowservice/v1/__init__.py @@ -1,16 +1,24 @@ from .request_response_pb2 import ( CountActivityExecutionsRequest, CountActivityExecutionsResponse, + CountNexusOperationExecutionsRequest, + CountNexusOperationExecutionsResponse, CountSchedulesRequest, CountSchedulesResponse, CountWorkflowExecutionsRequest, CountWorkflowExecutionsResponse, CreateScheduleRequest, CreateScheduleResponse, + CreateWorkerDeploymentRequest, + CreateWorkerDeploymentResponse, + CreateWorkerDeploymentVersionRequest, + CreateWorkerDeploymentVersionResponse, CreateWorkflowRuleRequest, CreateWorkflowRuleResponse, DeleteActivityExecutionRequest, DeleteActivityExecutionResponse, + DeleteNexusOperationExecutionRequest, + DeleteNexusOperationExecutionResponse, DeleteScheduleRequest, DeleteScheduleResponse, DeleteWorkerDeploymentRequest, @@ -31,6 +39,8 @@ DescribeDeploymentResponse, DescribeNamespaceRequest, DescribeNamespaceResponse, + DescribeNexusOperationExecutionRequest, + DescribeNexusOperationExecutionResponse, DescribeScheduleRequest, DescribeScheduleResponse, DescribeTaskQueueRequest, @@ -81,6 +91,8 @@ ListDeploymentsResponse, ListNamespacesRequest, ListNamespacesResponse, + ListNexusOperationExecutionsRequest, + ListNexusOperationExecutionsResponse, ListOpenWorkflowExecutionsRequest, ListOpenWorkflowExecutionsResponse, ListScheduleMatchingTimesRequest, @@ -107,6 +119,8 @@ PollActivityExecutionResponse, PollActivityTaskQueueRequest, PollActivityTaskQueueResponse, + PollNexusOperationExecutionRequest, + PollNexusOperationExecutionResponse, PollNexusTaskQueueRequest, PollNexusTaskQueueResponse, PollWorkflowExecutionUpdateRequest, @@ -125,6 +139,8 @@ RegisterNamespaceResponse, RequestCancelActivityExecutionRequest, RequestCancelActivityExecutionResponse, + RequestCancelNexusOperationExecutionRequest, + RequestCancelNexusOperationExecutionResponse, RequestCancelWorkflowExecutionRequest, RequestCancelWorkflowExecutionResponse, ResetActivityRequest, @@ -175,12 +191,16 @@ StartActivityExecutionResponse, StartBatchOperationRequest, StartBatchOperationResponse, + StartNexusOperationExecutionRequest, + StartNexusOperationExecutionResponse, StartWorkflowExecutionRequest, StartWorkflowExecutionResponse, StopBatchOperationRequest, StopBatchOperationResponse, TerminateActivityExecutionRequest, TerminateActivityExecutionResponse, + TerminateNexusOperationExecutionRequest, + TerminateNexusOperationExecutionResponse, TerminateWorkflowExecutionRequest, TerminateWorkflowExecutionResponse, TriggerWorkflowRuleRequest, @@ -201,6 +221,8 @@ UpdateWorkerBuildIdCompatibilityResponse, UpdateWorkerConfigRequest, UpdateWorkerConfigResponse, + UpdateWorkerDeploymentVersionComputeConfigRequest, + UpdateWorkerDeploymentVersionComputeConfigResponse, UpdateWorkerDeploymentVersionMetadataRequest, UpdateWorkerDeploymentVersionMetadataResponse, UpdateWorkerVersioningRulesRequest, @@ -209,21 +231,31 @@ UpdateWorkflowExecutionOptionsResponse, UpdateWorkflowExecutionRequest, UpdateWorkflowExecutionResponse, + ValidateWorkerDeploymentVersionComputeConfigRequest, + ValidateWorkerDeploymentVersionComputeConfigResponse, ) __all__ = [ "CountActivityExecutionsRequest", "CountActivityExecutionsResponse", + "CountNexusOperationExecutionsRequest", + "CountNexusOperationExecutionsResponse", "CountSchedulesRequest", "CountSchedulesResponse", "CountWorkflowExecutionsRequest", "CountWorkflowExecutionsResponse", "CreateScheduleRequest", "CreateScheduleResponse", + "CreateWorkerDeploymentRequest", + "CreateWorkerDeploymentResponse", + "CreateWorkerDeploymentVersionRequest", + "CreateWorkerDeploymentVersionResponse", "CreateWorkflowRuleRequest", "CreateWorkflowRuleResponse", "DeleteActivityExecutionRequest", "DeleteActivityExecutionResponse", + "DeleteNexusOperationExecutionRequest", + "DeleteNexusOperationExecutionResponse", "DeleteScheduleRequest", "DeleteScheduleResponse", "DeleteWorkerDeploymentRequest", @@ -244,6 +276,8 @@ "DescribeDeploymentResponse", "DescribeNamespaceRequest", "DescribeNamespaceResponse", + "DescribeNexusOperationExecutionRequest", + "DescribeNexusOperationExecutionResponse", "DescribeScheduleRequest", "DescribeScheduleResponse", "DescribeTaskQueueRequest", @@ -294,6 +328,8 @@ "ListDeploymentsResponse", "ListNamespacesRequest", "ListNamespacesResponse", + "ListNexusOperationExecutionsRequest", + "ListNexusOperationExecutionsResponse", "ListOpenWorkflowExecutionsRequest", "ListOpenWorkflowExecutionsResponse", "ListScheduleMatchingTimesRequest", @@ -320,6 +356,8 @@ "PollActivityExecutionResponse", "PollActivityTaskQueueRequest", "PollActivityTaskQueueResponse", + "PollNexusOperationExecutionRequest", + "PollNexusOperationExecutionResponse", "PollNexusTaskQueueRequest", "PollNexusTaskQueueResponse", "PollWorkflowExecutionUpdateRequest", @@ -338,6 +376,8 @@ "RegisterNamespaceResponse", "RequestCancelActivityExecutionRequest", "RequestCancelActivityExecutionResponse", + "RequestCancelNexusOperationExecutionRequest", + "RequestCancelNexusOperationExecutionResponse", "RequestCancelWorkflowExecutionRequest", "RequestCancelWorkflowExecutionResponse", "ResetActivityRequest", @@ -388,12 +428,16 @@ "StartActivityExecutionResponse", "StartBatchOperationRequest", "StartBatchOperationResponse", + "StartNexusOperationExecutionRequest", + "StartNexusOperationExecutionResponse", "StartWorkflowExecutionRequest", "StartWorkflowExecutionResponse", "StopBatchOperationRequest", "StopBatchOperationResponse", "TerminateActivityExecutionRequest", "TerminateActivityExecutionResponse", + "TerminateNexusOperationExecutionRequest", + "TerminateNexusOperationExecutionResponse", "TerminateWorkflowExecutionRequest", "TerminateWorkflowExecutionResponse", "TriggerWorkflowRuleRequest", @@ -414,6 +458,8 @@ "UpdateWorkerBuildIdCompatibilityResponse", "UpdateWorkerConfigRequest", "UpdateWorkerConfigResponse", + "UpdateWorkerDeploymentVersionComputeConfigRequest", + "UpdateWorkerDeploymentVersionComputeConfigResponse", "UpdateWorkerDeploymentVersionMetadataRequest", "UpdateWorkerDeploymentVersionMetadataResponse", "UpdateWorkerVersioningRulesRequest", @@ -422,6 +468,8 @@ "UpdateWorkflowExecutionOptionsResponse", "UpdateWorkflowExecutionRequest", "UpdateWorkflowExecutionResponse", + "ValidateWorkerDeploymentVersionComputeConfigRequest", + "ValidateWorkerDeploymentVersionComputeConfigResponse", ] # gRPC is optional diff --git a/temporalio/api/workflowservice/v1/request_response_pb2.py b/temporalio/api/workflowservice/v1/request_response_pb2.py index e8ac9b3a0..71e1a6a0f 100644 --- a/temporalio/api/workflowservice/v1/request_response_pb2.py +++ b/temporalio/api/workflowservice/v1/request_response_pb2.py @@ -30,6 +30,9 @@ from temporalio.api.common.v1 import ( message_pb2 as temporal_dot_api_dot_common_dot_v1_dot_message__pb2, ) +from temporalio.api.compute.v1 import ( + config_pb2 as temporal_dot_api_dot_compute_dot_v1_dot_config__pb2, +) from temporalio.api.deployment.v1 import ( message_pb2 as temporal_dot_api_dot_deployment_dot_v1_dot_message__pb2, ) @@ -51,6 +54,9 @@ from temporalio.api.enums.v1 import ( namespace_pb2 as temporal_dot_api_dot_enums_dot_v1_dot_namespace__pb2, ) +from temporalio.api.enums.v1 import ( + nexus_pb2 as temporal_dot_api_dot_enums_dot_v1_dot_nexus__pb2, +) from temporalio.api.enums.v1 import ( query_pb2 as temporal_dot_api_dot_enums_dot_v1_dot_query__pb2, ) @@ -122,7 +128,7 @@ ) DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile( - b'\n6temporal/api/workflowservice/v1/request_response.proto\x12\x1ftemporal.api.workflowservice.v1\x1a+temporal/api/enums/v1/batch_operation.proto\x1a"temporal/api/enums/v1/common.proto\x1a$temporal/api/enums/v1/workflow.proto\x1a%temporal/api/enums/v1/namespace.proto\x1a(temporal/api/enums/v1/failed_cause.proto\x1a!temporal/api/enums/v1/query.proto\x1a!temporal/api/enums/v1/reset.proto\x1a&temporal/api/enums/v1/task_queue.proto\x1a&temporal/api/enums/v1/deployment.proto\x1a"temporal/api/enums/v1/update.proto\x1a$temporal/api/enums/v1/activity.proto\x1a&temporal/api/activity/v1/message.proto\x1a$temporal/api/common/v1/message.proto\x1a%temporal/api/history/v1/message.proto\x1a&temporal/api/workflow/v1/message.proto\x1a%temporal/api/command/v1/message.proto\x1a(temporal/api/deployment/v1/message.proto\x1a%temporal/api/failure/v1/message.proto\x1a$temporal/api/filter/v1/message.proto\x1a&temporal/api/protocol/v1/message.proto\x1a\'temporal/api/namespace/v1/message.proto\x1a#temporal/api/query/v1/message.proto\x1a)temporal/api/replication/v1/message.proto\x1a#temporal/api/rules/v1/message.proto\x1a\'temporal/api/sdk/v1/worker_config.proto\x1a&temporal/api/schedule/v1/message.proto\x1a\'temporal/api/taskqueue/v1/message.proto\x1a$temporal/api/update/v1/message.proto\x1a%temporal/api/version/v1/message.proto\x1a#temporal/api/batch/v1/message.proto\x1a\x30temporal/api/sdk/v1/task_complete_metadata.proto\x1a\'temporal/api/sdk/v1/user_metadata.proto\x1a#temporal/api/nexus/v1/message.proto\x1a$temporal/api/worker/v1/message.proto\x1a\x1egoogle/protobuf/duration.proto\x1a google/protobuf/field_mask.proto\x1a\x1fgoogle/protobuf/timestamp.proto"\x88\x05\n\x18RegisterNamespaceRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0b\x64\x65scription\x18\x02 \x01(\t\x12\x13\n\x0bowner_email\x18\x03 \x01(\t\x12\x46\n#workflow_execution_retention_period\x18\x04 \x01(\x0b\x32\x19.google.protobuf.Duration\x12G\n\x08\x63lusters\x18\x05 \x03(\x0b\x32\x35.temporal.api.replication.v1.ClusterReplicationConfig\x12\x1b\n\x13\x61\x63tive_cluster_name\x18\x06 \x01(\t\x12Q\n\x04\x64\x61ta\x18\x07 \x03(\x0b\x32\x43.temporal.api.workflowservice.v1.RegisterNamespaceRequest.DataEntry\x12\x16\n\x0esecurity_token\x18\x08 \x01(\t\x12\x1b\n\x13is_global_namespace\x18\t \x01(\x08\x12\x44\n\x16history_archival_state\x18\n \x01(\x0e\x32$.temporal.api.enums.v1.ArchivalState\x12\x1c\n\x14history_archival_uri\x18\x0b \x01(\t\x12G\n\x19visibility_archival_state\x18\x0c \x01(\x0e\x32$.temporal.api.enums.v1.ArchivalState\x12\x1f\n\x17visibility_archival_uri\x18\r \x01(\t\x1a+\n\tDataEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01"\x1b\n\x19RegisterNamespaceResponse"\x89\x01\n\x15ListNamespacesRequest\x12\x11\n\tpage_size\x18\x01 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c\x12\x44\n\x10namespace_filter\x18\x03 \x01(\x0b\x32*.temporal.api.namespace.v1.NamespaceFilter"\x81\x01\n\x16ListNamespacesResponse\x12N\n\nnamespaces\x18\x01 \x03(\x0b\x32:.temporal.api.workflowservice.v1.DescribeNamespaceResponse\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c"9\n\x18\x44\x65scribeNamespaceRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\n\n\x02id\x18\x02 \x01(\t"\xec\x02\n\x19\x44\x65scribeNamespaceResponse\x12@\n\x0enamespace_info\x18\x01 \x01(\x0b\x32(.temporal.api.namespace.v1.NamespaceInfo\x12:\n\x06\x63onfig\x18\x02 \x01(\x0b\x32*.temporal.api.namespace.v1.NamespaceConfig\x12S\n\x12replication_config\x18\x03 \x01(\x0b\x32\x37.temporal.api.replication.v1.NamespaceReplicationConfig\x12\x18\n\x10\x66\x61ilover_version\x18\x04 \x01(\x03\x12\x1b\n\x13is_global_namespace\x18\x05 \x01(\x08\x12\x45\n\x10\x66\x61ilover_history\x18\x06 \x03(\x0b\x32+.temporal.api.replication.v1.FailoverStatus"\xcf\x02\n\x16UpdateNamespaceRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x43\n\x0bupdate_info\x18\x02 \x01(\x0b\x32..temporal.api.namespace.v1.UpdateNamespaceInfo\x12:\n\x06\x63onfig\x18\x03 \x01(\x0b\x32*.temporal.api.namespace.v1.NamespaceConfig\x12S\n\x12replication_config\x18\x04 \x01(\x0b\x32\x37.temporal.api.replication.v1.NamespaceReplicationConfig\x12\x16\n\x0esecurity_token\x18\x05 \x01(\t\x12\x19\n\x11\x64\x65lete_bad_binary\x18\x06 \x01(\t\x12\x19\n\x11promote_namespace\x18\x07 \x01(\x08"\xa3\x02\n\x17UpdateNamespaceResponse\x12@\n\x0enamespace_info\x18\x01 \x01(\x0b\x32(.temporal.api.namespace.v1.NamespaceInfo\x12:\n\x06\x63onfig\x18\x02 \x01(\x0b\x32*.temporal.api.namespace.v1.NamespaceConfig\x12S\n\x12replication_config\x18\x03 \x01(\x0b\x32\x37.temporal.api.replication.v1.NamespaceReplicationConfig\x12\x18\n\x10\x66\x61ilover_version\x18\x04 \x01(\x03\x12\x1b\n\x13is_global_namespace\x18\x05 \x01(\x08"F\n\x19\x44\x65precateNamespaceRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x16\n\x0esecurity_token\x18\x02 \x01(\t"\x1c\n\x1a\x44\x65precateNamespaceResponse"\x87\x0c\n\x1dStartWorkflowExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12;\n\rworkflow_type\x18\x03 \x01(\x0b\x32$.temporal.api.common.v1.WorkflowType\x12\x38\n\ntask_queue\x18\x04 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12/\n\x05input\x18\x05 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12=\n\x1aworkflow_execution_timeout\x18\x06 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x37\n\x14workflow_run_timeout\x18\x07 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x38\n\x15workflow_task_timeout\x18\x08 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x10\n\x08identity\x18\t \x01(\t\x12\x12\n\nrequest_id\x18\n \x01(\t\x12N\n\x18workflow_id_reuse_policy\x18\x0b \x01(\x0e\x32,.temporal.api.enums.v1.WorkflowIdReusePolicy\x12T\n\x1bworkflow_id_conflict_policy\x18\x16 \x01(\x0e\x32/.temporal.api.enums.v1.WorkflowIdConflictPolicy\x12\x39\n\x0cretry_policy\x18\x0c \x01(\x0b\x32#.temporal.api.common.v1.RetryPolicy\x12\x15\n\rcron_schedule\x18\r \x01(\t\x12*\n\x04memo\x18\x0e \x01(\x0b\x32\x1c.temporal.api.common.v1.Memo\x12\x43\n\x11search_attributes\x18\x0f \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes\x12.\n\x06header\x18\x10 \x01(\x0b\x32\x1e.temporal.api.common.v1.Header\x12\x1f\n\x17request_eager_execution\x18\x11 \x01(\x08\x12;\n\x11\x63ontinued_failure\x18\x12 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12@\n\x16last_completion_result\x18\x13 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x37\n\x14workflow_start_delay\x18\x14 \x01(\x0b\x32\x19.google.protobuf.Duration\x12>\n\x14\x63ompletion_callbacks\x18\x15 \x03(\x0b\x32 .temporal.api.common.v1.Callback\x12\x38\n\ruser_metadata\x18\x17 \x01(\x0b\x32!.temporal.api.sdk.v1.UserMetadata\x12+\n\x05links\x18\x18 \x03(\x0b\x32\x1c.temporal.api.common.v1.Link\x12I\n\x13versioning_override\x18\x19 \x01(\x0b\x32,.temporal.api.workflow.v1.VersioningOverride\x12H\n\x13on_conflict_options\x18\x1a \x01(\x0b\x32+.temporal.api.workflow.v1.OnConflictOptions\x12\x32\n\x08priority\x18\x1b \x01(\x0b\x32 .temporal.api.common.v1.Priority\x12\\\n\x1f\x65\x61ger_worker_deployment_options\x18\x1c \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentOptions"\x8a\x02\n\x1eStartWorkflowExecutionResponse\x12\x0e\n\x06run_id\x18\x01 \x01(\t\x12\x0f\n\x07started\x18\x03 \x01(\x08\x12>\n\x06status\x18\x05 \x01(\x0e\x32..temporal.api.enums.v1.WorkflowExecutionStatus\x12[\n\x13\x65\x61ger_workflow_task\x18\x02 \x01(\x0b\x32>.temporal.api.workflowservice.v1.PollWorkflowTaskQueueResponse\x12*\n\x04link\x18\x04 \x01(\x0b\x32\x1c.temporal.api.common.v1.Link"\xaa\x02\n"GetWorkflowExecutionHistoryRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12<\n\texecution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x19\n\x11maximum_page_size\x18\x03 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x04 \x01(\x0c\x12\x16\n\x0ewait_new_event\x18\x05 \x01(\x08\x12P\n\x19history_event_filter_type\x18\x06 \x01(\x0e\x32-.temporal.api.enums.v1.HistoryEventFilterType\x12\x15\n\rskip_archival\x18\x07 \x01(\x08"\xba\x01\n#GetWorkflowExecutionHistoryResponse\x12\x31\n\x07history\x18\x01 \x01(\x0b\x32 .temporal.api.history.v1.History\x12\x35\n\x0braw_history\x18\x02 \x03(\x0b\x32 .temporal.api.common.v1.DataBlob\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c\x12\x10\n\x08\x61rchived\x18\x04 \x01(\x08"\xb0\x01\n)GetWorkflowExecutionHistoryReverseRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12<\n\texecution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x19\n\x11maximum_page_size\x18\x03 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x04 \x01(\x0c"x\n*GetWorkflowExecutionHistoryReverseResponse\x12\x31\n\x07history\x18\x01 \x01(\x0b\x32 .temporal.api.history.v1.History\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c"\xfc\x02\n\x1cPollWorkflowTaskQueueRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x38\n\ntask_queue\x18\x02 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x1b\n\x13worker_instance_key\x18\x08 \x01(\t\x12\x1b\n\x0f\x62inary_checksum\x18\x04 \x01(\tB\x02\x18\x01\x12Z\n\x1bworker_version_capabilities\x18\x05 \x01(\x0b\x32\x31.temporal.api.common.v1.WorkerVersionCapabilitiesB\x02\x18\x01\x12O\n\x12\x64\x65ployment_options\x18\x06 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentOptionsJ\x04\x08\x07\x10\x08R\x10worker_heartbeat"\x91\x07\n\x1dPollWorkflowTaskQueueResponse\x12\x12\n\ntask_token\x18\x01 \x01(\x0c\x12\x45\n\x12workflow_execution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12;\n\rworkflow_type\x18\x03 \x01(\x0b\x32$.temporal.api.common.v1.WorkflowType\x12!\n\x19previous_started_event_id\x18\x04 \x01(\x03\x12\x18\n\x10started_event_id\x18\x05 \x01(\x03\x12\x0f\n\x07\x61ttempt\x18\x06 \x01(\x05\x12\x1a\n\x12\x62\x61\x63klog_count_hint\x18\x07 \x01(\x03\x12\x31\n\x07history\x18\x08 \x01(\x0b\x32 .temporal.api.history.v1.History\x12\x17\n\x0fnext_page_token\x18\t \x01(\x0c\x12\x33\n\x05query\x18\n \x01(\x0b\x32$.temporal.api.query.v1.WorkflowQuery\x12K\n\x1dworkflow_execution_task_queue\x18\x0b \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12\x32\n\x0escheduled_time\x18\x0c \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x30\n\x0cstarted_time\x18\r \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\\\n\x07queries\x18\x0e \x03(\x0b\x32K.temporal.api.workflowservice.v1.PollWorkflowTaskQueueResponse.QueriesEntry\x12\x33\n\x08messages\x18\x0f \x03(\x0b\x32!.temporal.api.protocol.v1.Message\x12Q\n\x17poller_scaling_decision\x18\x10 \x01(\x0b\x32\x30.temporal.api.taskqueue.v1.PollerScalingDecision\x1aT\n\x0cQueriesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x33\n\x05value\x18\x02 \x01(\x0b\x32$.temporal.api.query.v1.WorkflowQuery:\x02\x38\x01"\xca\t\n#RespondWorkflowTaskCompletedRequest\x12\x12\n\ntask_token\x18\x01 \x01(\x0c\x12\x32\n\x08\x63ommands\x18\x02 \x03(\x0b\x32 .temporal.api.command.v1.Command\x12\x10\n\x08identity\x18\x03 \x01(\t\x12O\n\x11sticky_attributes\x18\x04 \x01(\x0b\x32\x34.temporal.api.taskqueue.v1.StickyExecutionAttributes\x12 \n\x18return_new_workflow_task\x18\x05 \x01(\x08\x12&\n\x1e\x66orce_create_new_workflow_task\x18\x06 \x01(\x08\x12\x1b\n\x0f\x62inary_checksum\x18\x07 \x01(\tB\x02\x18\x01\x12m\n\rquery_results\x18\x08 \x03(\x0b\x32V.temporal.api.workflowservice.v1.RespondWorkflowTaskCompletedRequest.QueryResultsEntry\x12\x11\n\tnamespace\x18\t \x01(\t\x12\x13\n\x0bresource_id\x18\x12 \x01(\t\x12L\n\x14worker_version_stamp\x18\n \x01(\x0b\x32*.temporal.api.common.v1.WorkerVersionStampB\x02\x18\x01\x12\x33\n\x08messages\x18\x0b \x03(\x0b\x32!.temporal.api.protocol.v1.Message\x12H\n\x0csdk_metadata\x18\x0c \x01(\x0b\x32\x32.temporal.api.sdk.v1.WorkflowTaskCompletedMetadata\x12\x43\n\x11metering_metadata\x18\r \x01(\x0b\x32(.temporal.api.common.v1.MeteringMetadata\x12g\n\x0c\x63\x61pabilities\x18\x0e \x01(\x0b\x32Q.temporal.api.workflowservice.v1.RespondWorkflowTaskCompletedRequest.Capabilities\x12>\n\ndeployment\x18\x0f \x01(\x0b\x32&.temporal.api.deployment.v1.DeploymentB\x02\x18\x01\x12\x46\n\x13versioning_behavior\x18\x10 \x01(\x0e\x32).temporal.api.enums.v1.VersioningBehavior\x12O\n\x12\x64\x65ployment_options\x18\x11 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentOptions\x1a_\n\x11QueryResultsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x39\n\x05value\x18\x02 \x01(\x0b\x32*.temporal.api.query.v1.WorkflowQueryResult:\x02\x38\x01\x1a\x45\n\x0c\x43\x61pabilities\x12\x35\n-discard_speculative_workflow_task_with_events\x18\x01 \x01(\x08"\xf5\x01\n$RespondWorkflowTaskCompletedResponse\x12U\n\rworkflow_task\x18\x01 \x01(\x0b\x32>.temporal.api.workflowservice.v1.PollWorkflowTaskQueueResponse\x12V\n\x0e\x61\x63tivity_tasks\x18\x02 \x03(\x0b\x32>.temporal.api.workflowservice.v1.PollActivityTaskQueueResponse\x12\x1e\n\x16reset_history_event_id\x18\x03 \x01(\x03"\x8d\x04\n RespondWorkflowTaskFailedRequest\x12\x12\n\ntask_token\x18\x01 \x01(\x0c\x12=\n\x05\x63\x61use\x18\x02 \x01(\x0e\x32..temporal.api.enums.v1.WorkflowTaskFailedCause\x12\x31\n\x07\x66\x61ilure\x18\x03 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12\x10\n\x08identity\x18\x04 \x01(\t\x12\x1b\n\x0f\x62inary_checksum\x18\x05 \x01(\tB\x02\x18\x01\x12\x11\n\tnamespace\x18\x06 \x01(\t\x12\x13\n\x0bresource_id\x18\x0b \x01(\t\x12\x33\n\x08messages\x18\x07 \x03(\x0b\x32!.temporal.api.protocol.v1.Message\x12\x46\n\x0eworker_version\x18\x08 \x01(\x0b\x32*.temporal.api.common.v1.WorkerVersionStampB\x02\x18\x01\x12>\n\ndeployment\x18\t \x01(\x0b\x32&.temporal.api.deployment.v1.DeploymentB\x02\x18\x01\x12O\n\x12\x64\x65ployment_options\x18\n \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentOptions"#\n!RespondWorkflowTaskFailedResponse"\xaa\x03\n\x1cPollActivityTaskQueueRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x38\n\ntask_queue\x18\x02 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x1b\n\x13worker_instance_key\x18\x08 \x01(\t\x12I\n\x13task_queue_metadata\x18\x04 \x01(\x0b\x32,.temporal.api.taskqueue.v1.TaskQueueMetadata\x12Z\n\x1bworker_version_capabilities\x18\x05 \x01(\x0b\x32\x31.temporal.api.common.v1.WorkerVersionCapabilitiesB\x02\x18\x01\x12O\n\x12\x64\x65ployment_options\x18\x06 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentOptionsJ\x04\x08\x07\x10\x08R\x10worker_heartbeat"\x88\x08\n\x1dPollActivityTaskQueueResponse\x12\x12\n\ntask_token\x18\x01 \x01(\x0c\x12\x1a\n\x12workflow_namespace\x18\x02 \x01(\t\x12;\n\rworkflow_type\x18\x03 \x01(\x0b\x32$.temporal.api.common.v1.WorkflowType\x12\x45\n\x12workflow_execution\x18\x04 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12;\n\ractivity_type\x18\x05 \x01(\x0b\x32$.temporal.api.common.v1.ActivityType\x12\x13\n\x0b\x61\x63tivity_id\x18\x06 \x01(\t\x12.\n\x06header\x18\x07 \x01(\x0b\x32\x1e.temporal.api.common.v1.Header\x12/\n\x05input\x18\x08 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12;\n\x11heartbeat_details\x18\t \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x32\n\x0escheduled_time\x18\n \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x42\n\x1e\x63urrent_attempt_scheduled_time\x18\x0b \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x30\n\x0cstarted_time\x18\x0c \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x0f\n\x07\x61ttempt\x18\r \x01(\x05\x12<\n\x19schedule_to_close_timeout\x18\x0e \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x39\n\x16start_to_close_timeout\x18\x0f \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x34\n\x11heartbeat_timeout\x18\x10 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x39\n\x0cretry_policy\x18\x11 \x01(\x0b\x32#.temporal.api.common.v1.RetryPolicy\x12Q\n\x17poller_scaling_decision\x18\x12 \x01(\x0b\x32\x30.temporal.api.taskqueue.v1.PollerScalingDecision\x12\x32\n\x08priority\x18\x13 \x01(\x0b\x32 .temporal.api.common.v1.Priority\x12\x17\n\x0f\x61\x63tivity_run_id\x18\x14 \x01(\t"\xa5\x01\n"RecordActivityTaskHeartbeatRequest\x12\x12\n\ntask_token\x18\x01 \x01(\x0c\x12\x31\n\x07\x64\x65tails\x18\x02 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x11\n\tnamespace\x18\x04 \x01(\t\x12\x13\n\x0bresource_id\x18\x05 \x01(\t"p\n#RecordActivityTaskHeartbeatResponse\x12\x18\n\x10\x63\x61ncel_requested\x18\x01 \x01(\x08\x12\x17\n\x0f\x61\x63tivity_paused\x18\x02 \x01(\x08\x12\x16\n\x0e\x61\x63tivity_reset\x18\x03 \x01(\x08"\xcf\x01\n&RecordActivityTaskHeartbeatByIdRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x12\x13\n\x0b\x61\x63tivity_id\x18\x04 \x01(\t\x12\x31\n\x07\x64\x65tails\x18\x05 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x10\n\x08identity\x18\x06 \x01(\t\x12\x13\n\x0bresource_id\x18\x07 \x01(\t"t\n\'RecordActivityTaskHeartbeatByIdResponse\x12\x18\n\x10\x63\x61ncel_requested\x18\x01 \x01(\x08\x12\x17\n\x0f\x61\x63tivity_paused\x18\x02 \x01(\x08\x12\x16\n\x0e\x61\x63tivity_reset\x18\x03 \x01(\x08"\xfe\x02\n#RespondActivityTaskCompletedRequest\x12\x12\n\ntask_token\x18\x01 \x01(\x0c\x12\x30\n\x06result\x18\x02 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x11\n\tnamespace\x18\x04 \x01(\t\x12\x13\n\x0bresource_id\x18\x08 \x01(\t\x12\x46\n\x0eworker_version\x18\x05 \x01(\x0b\x32*.temporal.api.common.v1.WorkerVersionStampB\x02\x18\x01\x12>\n\ndeployment\x18\x06 \x01(\x0b\x32&.temporal.api.deployment.v1.DeploymentB\x02\x18\x01\x12O\n\x12\x64\x65ployment_options\x18\x07 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentOptions"&\n$RespondActivityTaskCompletedResponse"\xcf\x01\n\'RespondActivityTaskCompletedByIdRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x12\x13\n\x0b\x61\x63tivity_id\x18\x04 \x01(\t\x12\x30\n\x06result\x18\x05 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x10\n\x08identity\x18\x06 \x01(\t\x12\x13\n\x0bresource_id\x18\x07 \x01(\t"*\n(RespondActivityTaskCompletedByIdResponse"\xbe\x03\n RespondActivityTaskFailedRequest\x12\x12\n\ntask_token\x18\x01 \x01(\x0c\x12\x31\n\x07\x66\x61ilure\x18\x02 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x11\n\tnamespace\x18\x04 \x01(\t\x12\x13\n\x0bresource_id\x18\t \x01(\t\x12@\n\x16last_heartbeat_details\x18\x05 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x46\n\x0eworker_version\x18\x06 \x01(\x0b\x32*.temporal.api.common.v1.WorkerVersionStampB\x02\x18\x01\x12>\n\ndeployment\x18\x07 \x01(\x0b\x32&.temporal.api.deployment.v1.DeploymentB\x02\x18\x01\x12O\n\x12\x64\x65ployment_options\x18\x08 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentOptions"W\n!RespondActivityTaskFailedResponse\x12\x32\n\x08\x66\x61ilures\x18\x01 \x03(\x0b\x32 .temporal.api.failure.v1.Failure"\x8f\x02\n$RespondActivityTaskFailedByIdRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x12\x13\n\x0b\x61\x63tivity_id\x18\x04 \x01(\t\x12\x31\n\x07\x66\x61ilure\x18\x05 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12\x10\n\x08identity\x18\x06 \x01(\t\x12@\n\x16last_heartbeat_details\x18\x07 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x13\n\x0bresource_id\x18\x08 \x01(\t"[\n%RespondActivityTaskFailedByIdResponse\x12\x32\n\x08\x66\x61ilures\x18\x01 \x03(\x0b\x32 .temporal.api.failure.v1.Failure"\xfe\x02\n"RespondActivityTaskCanceledRequest\x12\x12\n\ntask_token\x18\x01 \x01(\x0c\x12\x31\n\x07\x64\x65tails\x18\x02 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x11\n\tnamespace\x18\x04 \x01(\t\x12\x13\n\x0bresource_id\x18\x08 \x01(\t\x12\x46\n\x0eworker_version\x18\x05 \x01(\x0b\x32*.temporal.api.common.v1.WorkerVersionStampB\x02\x18\x01\x12>\n\ndeployment\x18\x06 \x01(\x0b\x32&.temporal.api.deployment.v1.DeploymentB\x02\x18\x01\x12O\n\x12\x64\x65ployment_options\x18\x07 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentOptions"%\n#RespondActivityTaskCanceledResponse"\xa0\x02\n&RespondActivityTaskCanceledByIdRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x12\x13\n\x0b\x61\x63tivity_id\x18\x04 \x01(\t\x12\x31\n\x07\x64\x65tails\x18\x05 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x10\n\x08identity\x18\x06 \x01(\t\x12O\n\x12\x64\x65ployment_options\x18\x07 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentOptions\x12\x13\n\x0bresource_id\x18\x08 \x01(\t")\n\'RespondActivityTaskCanceledByIdResponse"\x84\x02\n%RequestCancelWorkflowExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x45\n\x12workflow_execution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x12\n\nrequest_id\x18\x04 \x01(\t\x12\x1e\n\x16\x66irst_execution_run_id\x18\x05 \x01(\t\x12\x0e\n\x06reason\x18\x06 \x01(\t\x12+\n\x05links\x18\x07 \x03(\x0b\x32\x1c.temporal.api.common.v1.Link"(\n&RequestCancelWorkflowExecutionResponse"\xde\x02\n\x1eSignalWorkflowExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x45\n\x12workflow_execution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x13\n\x0bsignal_name\x18\x03 \x01(\t\x12/\n\x05input\x18\x04 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x10\n\x08identity\x18\x05 \x01(\t\x12\x12\n\nrequest_id\x18\x06 \x01(\t\x12\x13\n\x07\x63ontrol\x18\x07 \x01(\tB\x02\x18\x01\x12.\n\x06header\x18\x08 \x01(\x0b\x32\x1e.temporal.api.common.v1.Header\x12+\n\x05links\x18\n \x03(\x0b\x32\x1c.temporal.api.common.v1.LinkJ\x04\x08\t\x10\n"!\n\x1fSignalWorkflowExecutionResponse"\xf1\t\n\'SignalWithStartWorkflowExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12;\n\rworkflow_type\x18\x03 \x01(\x0b\x32$.temporal.api.common.v1.WorkflowType\x12\x38\n\ntask_queue\x18\x04 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12/\n\x05input\x18\x05 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12=\n\x1aworkflow_execution_timeout\x18\x06 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x37\n\x14workflow_run_timeout\x18\x07 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x38\n\x15workflow_task_timeout\x18\x08 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x10\n\x08identity\x18\t \x01(\t\x12\x12\n\nrequest_id\x18\n \x01(\t\x12N\n\x18workflow_id_reuse_policy\x18\x0b \x01(\x0e\x32,.temporal.api.enums.v1.WorkflowIdReusePolicy\x12T\n\x1bworkflow_id_conflict_policy\x18\x16 \x01(\x0e\x32/.temporal.api.enums.v1.WorkflowIdConflictPolicy\x12\x13\n\x0bsignal_name\x18\x0c \x01(\t\x12\x36\n\x0csignal_input\x18\r \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x13\n\x07\x63ontrol\x18\x0e \x01(\tB\x02\x18\x01\x12\x39\n\x0cretry_policy\x18\x0f \x01(\x0b\x32#.temporal.api.common.v1.RetryPolicy\x12\x15\n\rcron_schedule\x18\x10 \x01(\t\x12*\n\x04memo\x18\x11 \x01(\x0b\x32\x1c.temporal.api.common.v1.Memo\x12\x43\n\x11search_attributes\x18\x12 \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes\x12.\n\x06header\x18\x13 \x01(\x0b\x32\x1e.temporal.api.common.v1.Header\x12\x37\n\x14workflow_start_delay\x18\x14 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x38\n\ruser_metadata\x18\x17 \x01(\x0b\x32!.temporal.api.sdk.v1.UserMetadata\x12+\n\x05links\x18\x18 \x03(\x0b\x32\x1c.temporal.api.common.v1.Link\x12I\n\x13versioning_override\x18\x19 \x01(\x0b\x32,.temporal.api.workflow.v1.VersioningOverride\x12\x32\n\x08priority\x18\x1a \x01(\x0b\x32 .temporal.api.common.v1.PriorityJ\x04\x08\x15\x10\x16"K\n(SignalWithStartWorkflowExecutionResponse\x12\x0e\n\x06run_id\x18\x01 \x01(\t\x12\x0f\n\x07started\x18\x02 \x01(\x08"\xc1\x03\n\x1dResetWorkflowExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x45\n\x12workflow_execution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x0e\n\x06reason\x18\x03 \x01(\t\x12%\n\x1dworkflow_task_finish_event_id\x18\x04 \x01(\x03\x12\x12\n\nrequest_id\x18\x05 \x01(\t\x12G\n\x12reset_reapply_type\x18\x06 \x01(\x0e\x32\'.temporal.api.enums.v1.ResetReapplyTypeB\x02\x18\x01\x12S\n\x1breset_reapply_exclude_types\x18\x07 \x03(\x0e\x32..temporal.api.enums.v1.ResetReapplyExcludeType\x12K\n\x15post_reset_operations\x18\x08 \x03(\x0b\x32,.temporal.api.workflow.v1.PostResetOperation\x12\x10\n\x08identity\x18\t \x01(\t"0\n\x1eResetWorkflowExecutionResponse\x12\x0e\n\x06run_id\x18\x01 \x01(\t"\x9f\x02\n!TerminateWorkflowExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x45\n\x12workflow_execution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x0e\n\x06reason\x18\x03 \x01(\t\x12\x31\n\x07\x64\x65tails\x18\x04 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x10\n\x08identity\x18\x05 \x01(\t\x12\x1e\n\x16\x66irst_execution_run_id\x18\x06 \x01(\t\x12+\n\x05links\x18\x07 \x03(\x0b\x32\x1c.temporal.api.common.v1.Link"$\n"TerminateWorkflowExecutionResponse"z\n\x1e\x44\x65leteWorkflowExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x45\n\x12workflow_execution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution"!\n\x1f\x44\x65leteWorkflowExecutionResponse"\xc9\x02\n!ListOpenWorkflowExecutionsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x19\n\x11maximum_page_size\x18\x02 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c\x12\x42\n\x11start_time_filter\x18\x04 \x01(\x0b\x32\'.temporal.api.filter.v1.StartTimeFilter\x12K\n\x10\x65xecution_filter\x18\x05 \x01(\x0b\x32/.temporal.api.filter.v1.WorkflowExecutionFilterH\x00\x12\x41\n\x0btype_filter\x18\x06 \x01(\x0b\x32*.temporal.api.filter.v1.WorkflowTypeFilterH\x00\x42\t\n\x07\x66ilters"\x82\x01\n"ListOpenWorkflowExecutionsResponse\x12\x43\n\nexecutions\x18\x01 \x03(\x0b\x32/.temporal.api.workflow.v1.WorkflowExecutionInfo\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c"\x8a\x03\n#ListClosedWorkflowExecutionsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x19\n\x11maximum_page_size\x18\x02 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c\x12\x42\n\x11start_time_filter\x18\x04 \x01(\x0b\x32\'.temporal.api.filter.v1.StartTimeFilter\x12K\n\x10\x65xecution_filter\x18\x05 \x01(\x0b\x32/.temporal.api.filter.v1.WorkflowExecutionFilterH\x00\x12\x41\n\x0btype_filter\x18\x06 \x01(\x0b\x32*.temporal.api.filter.v1.WorkflowTypeFilterH\x00\x12=\n\rstatus_filter\x18\x07 \x01(\x0b\x32$.temporal.api.filter.v1.StatusFilterH\x00\x42\t\n\x07\x66ilters"\x84\x01\n$ListClosedWorkflowExecutionsResponse\x12\x43\n\nexecutions\x18\x01 \x03(\x0b\x32/.temporal.api.workflow.v1.WorkflowExecutionInfo\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c"m\n\x1dListWorkflowExecutionsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x11\n\tpage_size\x18\x02 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c\x12\r\n\x05query\x18\x04 \x01(\t"~\n\x1eListWorkflowExecutionsResponse\x12\x43\n\nexecutions\x18\x01 \x03(\x0b\x32/.temporal.api.workflow.v1.WorkflowExecutionInfo\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c"u\n%ListArchivedWorkflowExecutionsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x11\n\tpage_size\x18\x02 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c\x12\r\n\x05query\x18\x04 \x01(\t"\x86\x01\n&ListArchivedWorkflowExecutionsResponse\x12\x43\n\nexecutions\x18\x01 \x03(\x0b\x32/.temporal.api.workflow.v1.WorkflowExecutionInfo\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c"m\n\x1dScanWorkflowExecutionsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x11\n\tpage_size\x18\x02 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c\x12\r\n\x05query\x18\x04 \x01(\t"~\n\x1eScanWorkflowExecutionsResponse\x12\x43\n\nexecutions\x18\x01 \x03(\x0b\x32/.temporal.api.workflow.v1.WorkflowExecutionInfo\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c"B\n\x1e\x43ountWorkflowExecutionsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\r\n\x05query\x18\x02 \x01(\t"\xed\x01\n\x1f\x43ountWorkflowExecutionsResponse\x12\r\n\x05\x63ount\x18\x01 \x01(\x03\x12\x61\n\x06groups\x18\x02 \x03(\x0b\x32Q.temporal.api.workflowservice.v1.CountWorkflowExecutionsResponse.AggregationGroup\x1aX\n\x10\x41ggregationGroup\x12\x35\n\x0cgroup_values\x18\x01 \x03(\x0b\x32\x1f.temporal.api.common.v1.Payload\x12\r\n\x05\x63ount\x18\x02 \x01(\x03"\x1c\n\x1aGetSearchAttributesRequest"\xc9\x01\n\x1bGetSearchAttributesResponse\x12T\n\x04keys\x18\x01 \x03(\x0b\x32\x46.temporal.api.workflowservice.v1.GetSearchAttributesResponse.KeysEntry\x1aT\n\tKeysEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x36\n\x05value\x18\x02 \x01(\x0e\x32\'.temporal.api.enums.v1.IndexedValueType:\x02\x38\x01"\xd0\x02\n RespondQueryTaskCompletedRequest\x12\x12\n\ntask_token\x18\x01 \x01(\x0c\x12>\n\x0e\x63ompleted_type\x18\x02 \x01(\x0e\x32&.temporal.api.enums.v1.QueryResultType\x12\x36\n\x0cquery_result\x18\x03 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x15\n\rerror_message\x18\x04 \x01(\t\x12\x11\n\tnamespace\x18\x06 \x01(\t\x12\x31\n\x07\x66\x61ilure\x18\x07 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12=\n\x05\x63\x61use\x18\x08 \x01(\x0e\x32..temporal.api.enums.v1.WorkflowTaskFailedCauseJ\x04\x08\x05\x10\x06"#\n!RespondQueryTaskCompletedResponse"n\n\x1bResetStickyTaskQueueRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12<\n\texecution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution"\x1e\n\x1cResetStickyTaskQueueResponse"\x9b\x02\n\x15ShutdownWorkerRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x19\n\x11sticky_task_queue\x18\x02 \x01(\t\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x0e\n\x06reason\x18\x04 \x01(\t\x12\x41\n\x10worker_heartbeat\x18\x05 \x01(\x0b\x32\'.temporal.api.worker.v1.WorkerHeartbeat\x12\x1b\n\x13worker_instance_key\x18\x06 \x01(\t\x12\x12\n\ntask_queue\x18\x07 \x01(\t\x12>\n\x10task_queue_types\x18\x08 \x03(\x0e\x32$.temporal.api.enums.v1.TaskQueueType"\x18\n\x16ShutdownWorkerResponse"\xe9\x01\n\x14QueryWorkflowRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12<\n\texecution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x33\n\x05query\x18\x03 \x01(\x0b\x32$.temporal.api.query.v1.WorkflowQuery\x12K\n\x16query_reject_condition\x18\x04 \x01(\x0e\x32+.temporal.api.enums.v1.QueryRejectCondition"\x8d\x01\n\x15QueryWorkflowResponse\x12\x36\n\x0cquery_result\x18\x01 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12<\n\x0equery_rejected\x18\x02 \x01(\x0b\x32$.temporal.api.query.v1.QueryRejected"s\n DescribeWorkflowExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12<\n\texecution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution"\x99\x05\n!DescribeWorkflowExecutionResponse\x12K\n\x10\x65xecution_config\x18\x01 \x01(\x0b\x32\x31.temporal.api.workflow.v1.WorkflowExecutionConfig\x12P\n\x17workflow_execution_info\x18\x02 \x01(\x0b\x32/.temporal.api.workflow.v1.WorkflowExecutionInfo\x12I\n\x12pending_activities\x18\x03 \x03(\x0b\x32-.temporal.api.workflow.v1.PendingActivityInfo\x12M\n\x10pending_children\x18\x04 \x03(\x0b\x32\x33.temporal.api.workflow.v1.PendingChildExecutionInfo\x12P\n\x15pending_workflow_task\x18\x05 \x01(\x0b\x32\x31.temporal.api.workflow.v1.PendingWorkflowTaskInfo\x12\x39\n\tcallbacks\x18\x06 \x03(\x0b\x32&.temporal.api.workflow.v1.CallbackInfo\x12U\n\x18pending_nexus_operations\x18\x07 \x03(\x0b\x32\x33.temporal.api.workflow.v1.PendingNexusOperationInfo\x12W\n\x16workflow_extended_info\x18\x08 \x01(\x0b\x32\x37.temporal.api.workflow.v1.WorkflowExecutionExtendedInfo"\x90\x04\n\x18\x44\x65scribeTaskQueueRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x38\n\ntask_queue\x18\x02 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12=\n\x0ftask_queue_type\x18\x03 \x01(\x0e\x32$.temporal.api.enums.v1.TaskQueueType\x12\x14\n\x0creport_stats\x18\x08 \x01(\x08\x12\x15\n\rreport_config\x18\x0b \x01(\x08\x12%\n\x19include_task_queue_status\x18\x04 \x01(\x08\x42\x02\x18\x01\x12\x42\n\x08\x61pi_mode\x18\x05 \x01(\x0e\x32,.temporal.api.enums.v1.DescribeTaskQueueModeB\x02\x18\x01\x12J\n\x08versions\x18\x06 \x01(\x0b\x32\x34.temporal.api.taskqueue.v1.TaskQueueVersionSelectionB\x02\x18\x01\x12\x42\n\x10task_queue_types\x18\x07 \x03(\x0e\x32$.temporal.api.enums.v1.TaskQueueTypeB\x02\x18\x01\x12\x1a\n\x0ereport_pollers\x18\t \x01(\x08\x42\x02\x18\x01\x12$\n\x18report_task_reachability\x18\n \x01(\x08\x42\x02\x18\x01"\xec\x07\n\x19\x44\x65scribeTaskQueueResponse\x12\x36\n\x07pollers\x18\x01 \x03(\x0b\x32%.temporal.api.taskqueue.v1.PollerInfo\x12\x38\n\x05stats\x18\x05 \x01(\x0b\x32).temporal.api.taskqueue.v1.TaskQueueStats\x12q\n\x15stats_by_priority_key\x18\x08 \x03(\x0b\x32R.temporal.api.workflowservice.v1.DescribeTaskQueueResponse.StatsByPriorityKeyEntry\x12K\n\x0fversioning_info\x18\x04 \x01(\x0b\x32\x32.temporal.api.taskqueue.v1.TaskQueueVersioningInfo\x12:\n\x06\x63onfig\x18\x06 \x01(\x0b\x32*.temporal.api.taskqueue.v1.TaskQueueConfig\x12k\n\x14\x65\x66\x66\x65\x63tive_rate_limit\x18\x07 \x01(\x0b\x32M.temporal.api.workflowservice.v1.DescribeTaskQueueResponse.EffectiveRateLimit\x12I\n\x11task_queue_status\x18\x02 \x01(\x0b\x32*.temporal.api.taskqueue.v1.TaskQueueStatusB\x02\x18\x01\x12g\n\rversions_info\x18\x03 \x03(\x0b\x32L.temporal.api.workflowservice.v1.DescribeTaskQueueResponse.VersionsInfoEntryB\x02\x18\x01\x1a\x64\n\x17StatsByPriorityKeyEntry\x12\x0b\n\x03key\x18\x01 \x01(\x05\x12\x38\n\x05value\x18\x02 \x01(\x0b\x32).temporal.api.taskqueue.v1.TaskQueueStats:\x02\x38\x01\x1at\n\x12\x45\x66\x66\x65\x63tiveRateLimit\x12\x1b\n\x13requests_per_second\x18\x01 \x01(\x02\x12\x41\n\x11rate_limit_source\x18\x02 \x01(\x0e\x32&.temporal.api.enums.v1.RateLimitSource\x1a\x64\n\x11VersionsInfoEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12>\n\x05value\x18\x02 \x01(\x0b\x32/.temporal.api.taskqueue.v1.TaskQueueVersionInfo:\x02\x38\x01"\x17\n\x15GetClusterInfoRequest"\xd1\x03\n\x16GetClusterInfoResponse\x12h\n\x11supported_clients\x18\x01 \x03(\x0b\x32M.temporal.api.workflowservice.v1.GetClusterInfoResponse.SupportedClientsEntry\x12\x16\n\x0eserver_version\x18\x02 \x01(\t\x12\x12\n\ncluster_id\x18\x03 \x01(\t\x12:\n\x0cversion_info\x18\x04 \x01(\x0b\x32$.temporal.api.version.v1.VersionInfo\x12\x14\n\x0c\x63luster_name\x18\x05 \x01(\t\x12\x1b\n\x13history_shard_count\x18\x06 \x01(\x05\x12\x19\n\x11persistence_store\x18\x07 \x01(\t\x12\x18\n\x10visibility_store\x18\x08 \x01(\t\x12 \n\x18initial_failover_version\x18\t \x01(\x03\x12"\n\x1a\x66\x61ilover_version_increment\x18\n \x01(\x03\x1a\x37\n\x15SupportedClientsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01"\x16\n\x14GetSystemInfoRequest"\xf4\x03\n\x15GetSystemInfoResponse\x12\x16\n\x0eserver_version\x18\x01 \x01(\t\x12Y\n\x0c\x63\x61pabilities\x18\x02 \x01(\x0b\x32\x43.temporal.api.workflowservice.v1.GetSystemInfoResponse.Capabilities\x1a\xe7\x02\n\x0c\x43\x61pabilities\x12\x1f\n\x17signal_and_query_header\x18\x01 \x01(\x08\x12&\n\x1einternal_error_differentiation\x18\x02 \x01(\x08\x12*\n"activity_failure_include_heartbeat\x18\x03 \x01(\x08\x12\x1a\n\x12supports_schedules\x18\x04 \x01(\x08\x12"\n\x1a\x65ncoded_failure_attributes\x18\x05 \x01(\x08\x12!\n\x19\x62uild_id_based_versioning\x18\x06 \x01(\x08\x12\x13\n\x0bupsert_memo\x18\x07 \x01(\x08\x12\x1c\n\x14\x65\x61ger_workflow_start\x18\x08 \x01(\x08\x12\x14\n\x0csdk_metadata\x18\t \x01(\x08\x12\'\n\x1f\x63ount_group_by_execution_status\x18\n \x01(\x08\x12\r\n\x05nexus\x18\x0b \x01(\x08"m\n\x1eListTaskQueuePartitionsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x38\n\ntask_queue\x18\x02 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue"\xdf\x01\n\x1fListTaskQueuePartitionsResponse\x12]\n\x1e\x61\x63tivity_task_queue_partitions\x18\x01 \x03(\x0b\x32\x35.temporal.api.taskqueue.v1.TaskQueuePartitionMetadata\x12]\n\x1eworkflow_task_queue_partitions\x18\x02 \x03(\x0b\x32\x35.temporal.api.taskqueue.v1.TaskQueuePartitionMetadata"\xcc\x02\n\x15\x43reateScheduleRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bschedule_id\x18\x02 \x01(\t\x12\x34\n\x08schedule\x18\x03 \x01(\x0b\x32".temporal.api.schedule.v1.Schedule\x12>\n\rinitial_patch\x18\x04 \x01(\x0b\x32\'.temporal.api.schedule.v1.SchedulePatch\x12\x10\n\x08identity\x18\x05 \x01(\t\x12\x12\n\nrequest_id\x18\x06 \x01(\t\x12*\n\x04memo\x18\x07 \x01(\x0b\x32\x1c.temporal.api.common.v1.Memo\x12\x43\n\x11search_attributes\x18\x08 \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes"0\n\x16\x43reateScheduleResponse\x12\x16\n\x0e\x63onflict_token\x18\x01 \x01(\x0c"A\n\x17\x44\x65scribeScheduleRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bschedule_id\x18\x02 \x01(\t"\x8f\x02\n\x18\x44\x65scribeScheduleResponse\x12\x34\n\x08schedule\x18\x01 \x01(\x0b\x32".temporal.api.schedule.v1.Schedule\x12\x34\n\x04info\x18\x02 \x01(\x0b\x32&.temporal.api.schedule.v1.ScheduleInfo\x12*\n\x04memo\x18\x03 \x01(\x0b\x32\x1c.temporal.api.common.v1.Memo\x12\x43\n\x11search_attributes\x18\x04 \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes\x12\x16\n\x0e\x63onflict_token\x18\x05 \x01(\x0c"\xf8\x01\n\x15UpdateScheduleRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bschedule_id\x18\x02 \x01(\t\x12\x34\n\x08schedule\x18\x03 \x01(\x0b\x32".temporal.api.schedule.v1.Schedule\x12\x16\n\x0e\x63onflict_token\x18\x04 \x01(\x0c\x12\x10\n\x08identity\x18\x05 \x01(\t\x12\x12\n\nrequest_id\x18\x06 \x01(\t\x12\x43\n\x11search_attributes\x18\x07 \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes"\x18\n\x16UpdateScheduleResponse"\x9c\x01\n\x14PatchScheduleRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bschedule_id\x18\x02 \x01(\t\x12\x36\n\x05patch\x18\x03 \x01(\x0b\x32\'.temporal.api.schedule.v1.SchedulePatch\x12\x10\n\x08identity\x18\x04 \x01(\t\x12\x12\n\nrequest_id\x18\x05 \x01(\t"\x17\n\x15PatchScheduleResponse"\xa8\x01\n ListScheduleMatchingTimesRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bschedule_id\x18\x02 \x01(\t\x12.\n\nstart_time\x18\x03 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12,\n\x08\x65nd_time\x18\x04 \x01(\x0b\x32\x1a.google.protobuf.Timestamp"S\n!ListScheduleMatchingTimesResponse\x12.\n\nstart_time\x18\x01 \x03(\x0b\x32\x1a.google.protobuf.Timestamp"Q\n\x15\x44\x65leteScheduleRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bschedule_id\x18\x02 \x01(\t\x12\x10\n\x08identity\x18\x03 \x01(\t"\x18\n\x16\x44\x65leteScheduleResponse"l\n\x14ListSchedulesRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x19\n\x11maximum_page_size\x18\x02 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c\x12\r\n\x05query\x18\x04 \x01(\t"p\n\x15ListSchedulesResponse\x12>\n\tschedules\x18\x01 \x03(\x0b\x32+.temporal.api.schedule.v1.ScheduleListEntry\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c"9\n\x15\x43ountSchedulesRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\r\n\x05query\x18\x02 \x01(\t"\xdb\x01\n\x16\x43ountSchedulesResponse\x12\r\n\x05\x63ount\x18\x01 \x01(\x03\x12X\n\x06groups\x18\x02 \x03(\x0b\x32H.temporal.api.workflowservice.v1.CountSchedulesResponse.AggregationGroup\x1aX\n\x10\x41ggregationGroup\x12\x35\n\x0cgroup_values\x18\x01 \x03(\x0b\x32\x1f.temporal.api.common.v1.Payload\x12\r\n\x05\x63ount\x18\x02 \x01(\x03"\x86\x05\n\'UpdateWorkerBuildIdCompatibilityRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x12\n\ntask_queue\x18\x02 \x01(\t\x12-\n#add_new_build_id_in_new_default_set\x18\x03 \x01(\tH\x00\x12\x87\x01\n\x1b\x61\x64\x64_new_compatible_build_id\x18\x04 \x01(\x0b\x32`.temporal.api.workflowservice.v1.UpdateWorkerBuildIdCompatibilityRequest.AddNewCompatibleVersionH\x00\x12!\n\x17promote_set_by_build_id\x18\x05 \x01(\tH\x00\x12%\n\x1bpromote_build_id_within_set\x18\x06 \x01(\tH\x00\x12h\n\nmerge_sets\x18\x07 \x01(\x0b\x32R.temporal.api.workflowservice.v1.UpdateWorkerBuildIdCompatibilityRequest.MergeSetsH\x00\x1ao\n\x17\x41\x64\x64NewCompatibleVersion\x12\x14\n\x0cnew_build_id\x18\x01 \x01(\t\x12$\n\x1c\x65xisting_compatible_build_id\x18\x02 \x01(\t\x12\x18\n\x10make_set_default\x18\x03 \x01(\x08\x1aI\n\tMergeSets\x12\x1c\n\x14primary_set_build_id\x18\x01 \x01(\t\x12\x1e\n\x16secondary_set_build_id\x18\x02 \x01(\tB\x0b\n\toperation"@\n(UpdateWorkerBuildIdCompatibilityResponseJ\x04\x08\x01\x10\x02R\x0eversion_set_id"_\n$GetWorkerBuildIdCompatibilityRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x12\n\ntask_queue\x18\x02 \x01(\t\x12\x10\n\x08max_sets\x18\x03 \x01(\x05"t\n%GetWorkerBuildIdCompatibilityResponse\x12K\n\x12major_version_sets\x18\x01 \x03(\x0b\x32/.temporal.api.taskqueue.v1.CompatibleVersionSet"\xb5\r\n"UpdateWorkerVersioningRulesRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x12\n\ntask_queue\x18\x02 \x01(\t\x12\x16\n\x0e\x63onflict_token\x18\x03 \x01(\x0c\x12\x81\x01\n\x16insert_assignment_rule\x18\x04 \x01(\x0b\x32_.temporal.api.workflowservice.v1.UpdateWorkerVersioningRulesRequest.InsertBuildIdAssignmentRuleH\x00\x12\x83\x01\n\x17replace_assignment_rule\x18\x05 \x01(\x0b\x32`.temporal.api.workflowservice.v1.UpdateWorkerVersioningRulesRequest.ReplaceBuildIdAssignmentRuleH\x00\x12\x81\x01\n\x16\x64\x65lete_assignment_rule\x18\x06 \x01(\x0b\x32_.temporal.api.workflowservice.v1.UpdateWorkerVersioningRulesRequest.DeleteBuildIdAssignmentRuleH\x00\x12\x8c\x01\n\x1c\x61\x64\x64_compatible_redirect_rule\x18\x07 \x01(\x0b\x32\x64.temporal.api.workflowservice.v1.UpdateWorkerVersioningRulesRequest.AddCompatibleBuildIdRedirectRuleH\x00\x12\x94\x01\n replace_compatible_redirect_rule\x18\x08 \x01(\x0b\x32h.temporal.api.workflowservice.v1.UpdateWorkerVersioningRulesRequest.ReplaceCompatibleBuildIdRedirectRuleH\x00\x12\x92\x01\n\x1f\x64\x65lete_compatible_redirect_rule\x18\t \x01(\x0b\x32g.temporal.api.workflowservice.v1.UpdateWorkerVersioningRulesRequest.DeleteCompatibleBuildIdRedirectRuleH\x00\x12l\n\x0f\x63ommit_build_id\x18\n \x01(\x0b\x32Q.temporal.api.workflowservice.v1.UpdateWorkerVersioningRulesRequest.CommitBuildIdH\x00\x1aq\n\x1bInsertBuildIdAssignmentRule\x12\x12\n\nrule_index\x18\x01 \x01(\x05\x12>\n\x04rule\x18\x02 \x01(\x0b\x32\x30.temporal.api.taskqueue.v1.BuildIdAssignmentRule\x1a\x81\x01\n\x1cReplaceBuildIdAssignmentRule\x12\x12\n\nrule_index\x18\x01 \x01(\x05\x12>\n\x04rule\x18\x02 \x01(\x0b\x32\x30.temporal.api.taskqueue.v1.BuildIdAssignmentRule\x12\r\n\x05\x66orce\x18\x03 \x01(\x08\x1a@\n\x1b\x44\x65leteBuildIdAssignmentRule\x12\x12\n\nrule_index\x18\x01 \x01(\x05\x12\r\n\x05\x66orce\x18\x02 \x01(\x08\x1aj\n AddCompatibleBuildIdRedirectRule\x12\x46\n\x04rule\x18\x01 \x01(\x0b\x32\x38.temporal.api.taskqueue.v1.CompatibleBuildIdRedirectRule\x1an\n$ReplaceCompatibleBuildIdRedirectRule\x12\x46\n\x04rule\x18\x01 \x01(\x0b\x32\x38.temporal.api.taskqueue.v1.CompatibleBuildIdRedirectRule\x1a>\n#DeleteCompatibleBuildIdRedirectRule\x12\x17\n\x0fsource_build_id\x18\x01 \x01(\t\x1a\x37\n\rCommitBuildId\x12\x17\n\x0ftarget_build_id\x18\x01 \x01(\t\x12\r\n\x05\x66orce\x18\x02 \x01(\x08\x42\x0b\n\toperation"\xfc\x01\n#UpdateWorkerVersioningRulesResponse\x12U\n\x10\x61ssignment_rules\x18\x01 \x03(\x0b\x32;.temporal.api.taskqueue.v1.TimestampedBuildIdAssignmentRule\x12\x66\n\x19\x63ompatible_redirect_rules\x18\x02 \x03(\x0b\x32\x43.temporal.api.taskqueue.v1.TimestampedCompatibleBuildIdRedirectRule\x12\x16\n\x0e\x63onflict_token\x18\x03 \x01(\x0c"H\n\x1fGetWorkerVersioningRulesRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x12\n\ntask_queue\x18\x02 \x01(\t"\xf9\x01\n GetWorkerVersioningRulesResponse\x12U\n\x10\x61ssignment_rules\x18\x01 \x03(\x0b\x32;.temporal.api.taskqueue.v1.TimestampedBuildIdAssignmentRule\x12\x66\n\x19\x63ompatible_redirect_rules\x18\x02 \x03(\x0b\x32\x43.temporal.api.taskqueue.v1.TimestampedCompatibleBuildIdRedirectRule\x12\x16\n\x0e\x63onflict_token\x18\x03 \x01(\x0c"\x9c\x01\n GetWorkerTaskReachabilityRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x11\n\tbuild_ids\x18\x02 \x03(\t\x12\x13\n\x0btask_queues\x18\x03 \x03(\t\x12=\n\x0creachability\x18\x04 \x01(\x0e\x32\'.temporal.api.enums.v1.TaskReachability"r\n!GetWorkerTaskReachabilityResponse\x12M\n\x15\x62uild_id_reachability\x18\x01 \x03(\x0b\x32..temporal.api.taskqueue.v1.BuildIdReachability"\x85\x02\n\x1eUpdateWorkflowExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x45\n\x12workflow_execution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x1e\n\x16\x66irst_execution_run_id\x18\x03 \x01(\t\x12\x37\n\x0bwait_policy\x18\x04 \x01(\x0b\x32".temporal.api.update.v1.WaitPolicy\x12\x30\n\x07request\x18\x05 \x01(\x0b\x32\x1f.temporal.api.update.v1.Request"\xd7\x01\n\x1fUpdateWorkflowExecutionResponse\x12\x35\n\nupdate_ref\x18\x01 \x01(\x0b\x32!.temporal.api.update.v1.UpdateRef\x12\x30\n\x07outcome\x18\x02 \x01(\x0b\x32\x1f.temporal.api.update.v1.Outcome\x12K\n\x05stage\x18\x03 \x01(\x0e\x32<.temporal.api.enums.v1.UpdateWorkflowExecutionLifecycleStage"\xf4\x07\n\x1aStartBatchOperationRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x18\n\x10visibility_query\x18\x02 \x01(\t\x12\x0e\n\x06job_id\x18\x03 \x01(\t\x12\x0e\n\x06reason\x18\x04 \x01(\t\x12=\n\nexecutions\x18\x05 \x03(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12!\n\x19max_operations_per_second\x18\x06 \x01(\x02\x12Q\n\x15termination_operation\x18\n \x01(\x0b\x32\x30.temporal.api.batch.v1.BatchOperationTerminationH\x00\x12G\n\x10signal_operation\x18\x0b \x01(\x0b\x32+.temporal.api.batch.v1.BatchOperationSignalH\x00\x12S\n\x16\x63\x61ncellation_operation\x18\x0c \x01(\x0b\x32\x31.temporal.api.batch.v1.BatchOperationCancellationH\x00\x12K\n\x12\x64\x65letion_operation\x18\r \x01(\x0b\x32-.temporal.api.batch.v1.BatchOperationDeletionH\x00\x12\x45\n\x0freset_operation\x18\x0e \x01(\x0b\x32*.temporal.api.batch.v1.BatchOperationResetH\x00\x12p\n!update_workflow_options_operation\x18\x0f \x01(\x0b\x32\x43.temporal.api.batch.v1.BatchOperationUpdateWorkflowExecutionOptionsH\x00\x12^\n\x1cunpause_activities_operation\x18\x10 \x01(\x0b\x32\x36.temporal.api.batch.v1.BatchOperationUnpauseActivitiesH\x00\x12Z\n\x1areset_activities_operation\x18\x11 \x01(\x0b\x32\x34.temporal.api.batch.v1.BatchOperationResetActivitiesH\x00\x12g\n!update_activity_options_operation\x18\x12 \x01(\x0b\x32:.temporal.api.batch.v1.BatchOperationUpdateActivityOptionsH\x00\x42\x0b\n\toperation"\x1d\n\x1bStartBatchOperationResponse"`\n\x19StopBatchOperationRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x0e\n\x06job_id\x18\x02 \x01(\t\x12\x0e\n\x06reason\x18\x03 \x01(\t\x12\x10\n\x08identity\x18\x04 \x01(\t"\x1c\n\x1aStopBatchOperationResponse"B\n\x1d\x44\x65scribeBatchOperationRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x0e\n\x06job_id\x18\x02 \x01(\t"\x92\x03\n\x1e\x44\x65scribeBatchOperationResponse\x12\x41\n\x0eoperation_type\x18\x01 \x01(\x0e\x32).temporal.api.enums.v1.BatchOperationType\x12\x0e\n\x06job_id\x18\x02 \x01(\t\x12\x39\n\x05state\x18\x03 \x01(\x0e\x32*.temporal.api.enums.v1.BatchOperationState\x12.\n\nstart_time\x18\x04 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12.\n\nclose_time\x18\x05 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x1d\n\x15total_operation_count\x18\x06 \x01(\x03\x12 \n\x18\x63omplete_operation_count\x18\x07 \x01(\x03\x12\x1f\n\x17\x66\x61ilure_operation_count\x18\x08 \x01(\x03\x12\x10\n\x08identity\x18\t \x01(\t\x12\x0e\n\x06reason\x18\n \x01(\t"[\n\x1aListBatchOperationsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x11\n\tpage_size\x18\x02 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c"y\n\x1bListBatchOperationsResponse\x12\x41\n\x0eoperation_info\x18\x01 \x03(\x0b\x32).temporal.api.batch.v1.BatchOperationInfo\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c"\xb9\x01\n"PollWorkflowExecutionUpdateRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x35\n\nupdate_ref\x18\x02 \x01(\x0b\x32!.temporal.api.update.v1.UpdateRef\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x37\n\x0bwait_policy\x18\x04 \x01(\x0b\x32".temporal.api.update.v1.WaitPolicy"\xdb\x01\n#PollWorkflowExecutionUpdateResponse\x12\x30\n\x07outcome\x18\x01 \x01(\x0b\x32\x1f.temporal.api.update.v1.Outcome\x12K\n\x05stage\x18\x02 \x01(\x0e\x32<.temporal.api.enums.v1.UpdateWorkflowExecutionLifecycleStage\x12\x35\n\nupdate_ref\x18\x03 \x01(\x0b\x32!.temporal.api.update.v1.UpdateRef"\x87\x03\n\x19PollNexusTaskQueueRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x10\n\x08identity\x18\x02 \x01(\t\x12\x1b\n\x13worker_instance_key\x18\x08 \x01(\t\x12\x38\n\ntask_queue\x18\x03 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12Z\n\x1bworker_version_capabilities\x18\x04 \x01(\x0b\x32\x31.temporal.api.common.v1.WorkerVersionCapabilitiesB\x02\x18\x01\x12O\n\x12\x64\x65ployment_options\x18\x06 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentOptions\x12\x41\n\x10worker_heartbeat\x18\x07 \x03(\x0b\x32\'.temporal.api.worker.v1.WorkerHeartbeat"\xb4\x01\n\x1aPollNexusTaskQueueResponse\x12\x12\n\ntask_token\x18\x01 \x01(\x0c\x12/\n\x07request\x18\x02 \x01(\x0b\x32\x1e.temporal.api.nexus.v1.Request\x12Q\n\x17poller_scaling_decision\x18\x03 \x01(\x0b\x32\x30.temporal.api.taskqueue.v1.PollerScalingDecision"\x8e\x01\n RespondNexusTaskCompletedRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x10\n\x08identity\x18\x02 \x01(\t\x12\x12\n\ntask_token\x18\x03 \x01(\x0c\x12\x31\n\x08response\x18\x04 \x01(\x0b\x32\x1f.temporal.api.nexus.v1.Response"#\n!RespondNexusTaskCompletedResponse"\xc3\x01\n\x1dRespondNexusTaskFailedRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x10\n\x08identity\x18\x02 \x01(\t\x12\x12\n\ntask_token\x18\x03 \x01(\x0c\x12\x36\n\x05\x65rror\x18\x04 \x01(\x0b\x32#.temporal.api.nexus.v1.HandlerErrorB\x02\x18\x01\x12\x31\n\x07\x66\x61ilure\x18\x05 \x01(\x0b\x32 .temporal.api.failure.v1.Failure" \n\x1eRespondNexusTaskFailedResponse"\xf4\x02\n\x1c\x45xecuteMultiOperationRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12[\n\noperations\x18\x02 \x03(\x0b\x32G.temporal.api.workflowservice.v1.ExecuteMultiOperationRequest.Operation\x12\x13\n\x0bresource_id\x18\x03 \x01(\t\x1a\xce\x01\n\tOperation\x12X\n\x0estart_workflow\x18\x01 \x01(\x0b\x32>.temporal.api.workflowservice.v1.StartWorkflowExecutionRequestH\x00\x12Z\n\x0fupdate_workflow\x18\x02 \x01(\x0b\x32?.temporal.api.workflowservice.v1.UpdateWorkflowExecutionRequestH\x00\x42\x0b\n\toperation"\xcc\x02\n\x1d\x45xecuteMultiOperationResponse\x12Z\n\tresponses\x18\x01 \x03(\x0b\x32G.temporal.api.workflowservice.v1.ExecuteMultiOperationResponse.Response\x1a\xce\x01\n\x08Response\x12Y\n\x0estart_workflow\x18\x01 \x01(\x0b\x32?.temporal.api.workflowservice.v1.StartWorkflowExecutionResponseH\x00\x12[\n\x0fupdate_workflow\x18\x02 \x01(\x0b\x32@.temporal.api.workflowservice.v1.UpdateWorkflowExecutionResponseH\x00\x42\n\n\x08response"\xd0\x02\n\x1cUpdateActivityOptionsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12<\n\texecution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x43\n\x10\x61\x63tivity_options\x18\x04 \x01(\x0b\x32).temporal.api.activity.v1.ActivityOptions\x12/\n\x0bupdate_mask\x18\x05 \x01(\x0b\x32\x1a.google.protobuf.FieldMask\x12\x0c\n\x02id\x18\x06 \x01(\tH\x00\x12\x0e\n\x04type\x18\x07 \x01(\tH\x00\x12\x13\n\tmatch_all\x18\t \x01(\x08H\x00\x12\x18\n\x10restore_original\x18\x08 \x01(\x08\x42\n\n\x08\x61\x63tivity"d\n\x1dUpdateActivityOptionsResponse\x12\x43\n\x10\x61\x63tivity_options\x18\x01 \x01(\x0b\x32).temporal.api.activity.v1.ActivityOptions"\xb3\x01\n\x14PauseActivityRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12<\n\texecution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x0c\n\x02id\x18\x04 \x01(\tH\x00\x12\x0e\n\x04type\x18\x05 \x01(\tH\x00\x12\x0e\n\x06reason\x18\x06 \x01(\tB\n\n\x08\x61\x63tivity"\x17\n\x15PauseActivityResponse"\x98\x02\n\x16UnpauseActivityRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12<\n\texecution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x0c\n\x02id\x18\x04 \x01(\tH\x00\x12\x0e\n\x04type\x18\x05 \x01(\tH\x00\x12\x15\n\x0bunpause_all\x18\x06 \x01(\x08H\x00\x12\x16\n\x0ereset_attempts\x18\x07 \x01(\x08\x12\x17\n\x0freset_heartbeat\x18\x08 \x01(\x08\x12)\n\x06jitter\x18\t \x01(\x0b\x32\x19.google.protobuf.DurationB\n\n\x08\x61\x63tivity"\x19\n\x17UnpauseActivityResponse"\xb3\x02\n\x14ResetActivityRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12<\n\texecution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x0c\n\x02id\x18\x04 \x01(\tH\x00\x12\x0e\n\x04type\x18\x05 \x01(\tH\x00\x12\x13\n\tmatch_all\x18\n \x01(\x08H\x00\x12\x17\n\x0freset_heartbeat\x18\x06 \x01(\x08\x12\x13\n\x0bkeep_paused\x18\x07 \x01(\x08\x12)\n\x06jitter\x18\x08 \x01(\x0b\x32\x19.google.protobuf.Duration\x12 \n\x18restore_original_options\x18\t \x01(\x08\x42\n\n\x08\x61\x63tivity"\x17\n\x15ResetActivityResponse"\x9c\x02\n%UpdateWorkflowExecutionOptionsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x45\n\x12workflow_execution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12V\n\x1aworkflow_execution_options\x18\x03 \x01(\x0b\x32\x32.temporal.api.workflow.v1.WorkflowExecutionOptions\x12/\n\x0bupdate_mask\x18\x04 \x01(\x0b\x32\x1a.google.protobuf.FieldMask\x12\x10\n\x08identity\x18\x05 \x01(\t"\x80\x01\n&UpdateWorkflowExecutionOptionsResponse\x12V\n\x1aworkflow_execution_options\x18\x01 \x01(\x0b\x32\x32.temporal.api.workflow.v1.WorkflowExecutionOptions"j\n\x19\x44\x65scribeDeploymentRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12:\n\ndeployment\x18\x02 \x01(\x0b\x32&.temporal.api.deployment.v1.Deployment"a\n\x1a\x44\x65scribeDeploymentResponse\x12\x43\n\x0f\x64\x65ployment_info\x18\x01 \x01(\x0b\x32*.temporal.api.deployment.v1.DeploymentInfo"\xc2\x01\n&DescribeWorkerDeploymentVersionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x07version\x18\x02 \x01(\tB\x02\x18\x01\x12O\n\x12\x64\x65ployment_version\x18\x03 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersion\x12\x1f\n\x17report_task_queue_stats\x18\x04 \x01(\x08"\x8c\x05\n\'DescribeWorkerDeploymentVersionResponse\x12_\n\x1eworker_deployment_version_info\x18\x01 \x01(\x0b\x32\x37.temporal.api.deployment.v1.WorkerDeploymentVersionInfo\x12v\n\x13version_task_queues\x18\x02 \x03(\x0b\x32Y.temporal.api.workflowservice.v1.DescribeWorkerDeploymentVersionResponse.VersionTaskQueue\x1a\x87\x03\n\x10VersionTaskQueue\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x32\n\x04type\x18\x02 \x01(\x0e\x32$.temporal.api.enums.v1.TaskQueueType\x12\x38\n\x05stats\x18\x03 \x01(\x0b\x32).temporal.api.taskqueue.v1.TaskQueueStats\x12\x90\x01\n\x15stats_by_priority_key\x18\x04 \x03(\x0b\x32q.temporal.api.workflowservice.v1.DescribeWorkerDeploymentVersionResponse.VersionTaskQueue.StatsByPriorityKeyEntry\x1a\x64\n\x17StatsByPriorityKeyEntry\x12\x0b\n\x03key\x18\x01 \x01(\x05\x12\x38\n\x05value\x18\x02 \x01(\x0b\x32).temporal.api.taskqueue.v1.TaskQueueStats:\x02\x38\x01"M\n\x1f\x44\x65scribeWorkerDeploymentRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x17\n\x0f\x64\x65ployment_name\x18\x02 \x01(\t"\x8c\x01\n DescribeWorkerDeploymentResponse\x12\x16\n\x0e\x63onflict_token\x18\x01 \x01(\x0c\x12P\n\x16worker_deployment_info\x18\x02 \x01(\x0b\x32\x30.temporal.api.deployment.v1.WorkerDeploymentInfo"l\n\x16ListDeploymentsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x11\n\tpage_size\x18\x02 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c\x12\x13\n\x0bseries_name\x18\x04 \x01(\t"w\n\x17ListDeploymentsResponse\x12\x17\n\x0fnext_page_token\x18\x01 \x01(\x0c\x12\x43\n\x0b\x64\x65ployments\x18\x02 \x03(\x0b\x32..temporal.api.deployment.v1.DeploymentListInfo"\xcd\x01\n\x1bSetCurrentDeploymentRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12:\n\ndeployment\x18\x02 \x01(\x0b\x32&.temporal.api.deployment.v1.Deployment\x12\x10\n\x08identity\x18\x03 \x01(\t\x12M\n\x0fupdate_metadata\x18\x04 \x01(\x0b\x32\x34.temporal.api.deployment.v1.UpdateDeploymentMetadata"\xb9\x01\n\x1cSetCurrentDeploymentResponse\x12K\n\x17\x63urrent_deployment_info\x18\x01 \x01(\x0b\x32*.temporal.api.deployment.v1.DeploymentInfo\x12L\n\x18previous_deployment_info\x18\x02 \x01(\x0b\x32*.temporal.api.deployment.v1.DeploymentInfo"\xe5\x01\n(SetWorkerDeploymentCurrentVersionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x17\n\x0f\x64\x65ployment_name\x18\x02 \x01(\t\x12\x13\n\x07version\x18\x03 \x01(\tB\x02\x18\x01\x12\x10\n\x08\x62uild_id\x18\x07 \x01(\t\x12\x16\n\x0e\x63onflict_token\x18\x04 \x01(\x0c\x12\x10\n\x08identity\x18\x05 \x01(\t\x12"\n\x1aignore_missing_task_queues\x18\x06 \x01(\x08\x12\x18\n\x10\x61llow_no_pollers\x18\t \x01(\x08"\xbf\x01\n)SetWorkerDeploymentCurrentVersionResponse\x12\x16\n\x0e\x63onflict_token\x18\x01 \x01(\x0c\x12\x1c\n\x10previous_version\x18\x02 \x01(\tB\x02\x18\x01\x12\\\n\x1bprevious_deployment_version\x18\x03 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersionB\x02\x18\x01"\xf9\x01\n(SetWorkerDeploymentRampingVersionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x17\n\x0f\x64\x65ployment_name\x18\x02 \x01(\t\x12\x13\n\x07version\x18\x03 \x01(\tB\x02\x18\x01\x12\x10\n\x08\x62uild_id\x18\x08 \x01(\t\x12\x12\n\npercentage\x18\x04 \x01(\x02\x12\x16\n\x0e\x63onflict_token\x18\x05 \x01(\x0c\x12\x10\n\x08identity\x18\x06 \x01(\t\x12"\n\x1aignore_missing_task_queues\x18\x07 \x01(\x08\x12\x18\n\x10\x61llow_no_pollers\x18\n \x01(\x08"\xe0\x01\n)SetWorkerDeploymentRampingVersionResponse\x12\x16\n\x0e\x63onflict_token\x18\x01 \x01(\x0c\x12\x1c\n\x10previous_version\x18\x02 \x01(\tB\x02\x18\x01\x12\\\n\x1bprevious_deployment_version\x18\x04 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersionB\x02\x18\x01\x12\x1f\n\x13previous_percentage\x18\x03 \x01(\x02\x42\x02\x18\x01"]\n\x1cListWorkerDeploymentsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x11\n\tpage_size\x18\x02 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c"\x9f\x05\n\x1dListWorkerDeploymentsResponse\x12\x17\n\x0fnext_page_token\x18\x01 \x01(\x0c\x12r\n\x12worker_deployments\x18\x02 \x03(\x0b\x32V.temporal.api.workflowservice.v1.ListWorkerDeploymentsResponse.WorkerDeploymentSummary\x1a\xf0\x03\n\x17WorkerDeploymentSummary\x12\x0c\n\x04name\x18\x01 \x01(\t\x12/\n\x0b\x63reate_time\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x41\n\x0erouting_config\x18\x03 \x01(\x0b\x32).temporal.api.deployment.v1.RoutingConfig\x12o\n\x16latest_version_summary\x18\x04 \x01(\x0b\x32O.temporal.api.deployment.v1.WorkerDeploymentInfo.WorkerDeploymentVersionSummary\x12p\n\x17\x63urrent_version_summary\x18\x05 \x01(\x0b\x32O.temporal.api.deployment.v1.WorkerDeploymentInfo.WorkerDeploymentVersionSummary\x12p\n\x17ramping_version_summary\x18\x06 \x01(\x0b\x32O.temporal.api.deployment.v1.WorkerDeploymentInfo.WorkerDeploymentVersionSummary"\xc8\x01\n$DeleteWorkerDeploymentVersionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x07version\x18\x02 \x01(\tB\x02\x18\x01\x12O\n\x12\x64\x65ployment_version\x18\x05 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersion\x12\x15\n\rskip_drainage\x18\x03 \x01(\x08\x12\x10\n\x08identity\x18\x04 \x01(\t"\'\n%DeleteWorkerDeploymentVersionResponse"]\n\x1d\x44\x65leteWorkerDeploymentRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x17\n\x0f\x64\x65ployment_name\x18\x02 \x01(\t\x12\x10\n\x08identity\x18\x03 \x01(\t" \n\x1e\x44\x65leteWorkerDeploymentResponse"\xa2\x03\n,UpdateWorkerDeploymentVersionMetadataRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x07version\x18\x02 \x01(\tB\x02\x18\x01\x12O\n\x12\x64\x65ployment_version\x18\x05 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersion\x12x\n\x0eupsert_entries\x18\x03 \x03(\x0b\x32`.temporal.api.workflowservice.v1.UpdateWorkerDeploymentVersionMetadataRequest.UpsertEntriesEntry\x12\x16\n\x0eremove_entries\x18\x04 \x03(\t\x12\x10\n\x08identity\x18\x06 \x01(\t\x1aU\n\x12UpsertEntriesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12.\n\x05value\x18\x02 \x01(\x0b\x32\x1f.temporal.api.common.v1.Payload:\x02\x38\x01"n\n-UpdateWorkerDeploymentVersionMetadataResponse\x12=\n\x08metadata\x18\x01 \x01(\x0b\x32+.temporal.api.deployment.v1.VersionMetadata"\xbd\x01\n!SetWorkerDeploymentManagerRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x17\n\x0f\x64\x65ployment_name\x18\x02 \x01(\t\x12\x1a\n\x10manager_identity\x18\x03 \x01(\tH\x00\x12\x0e\n\x04self\x18\x04 \x01(\x08H\x00\x12\x16\n\x0e\x63onflict_token\x18\x05 \x01(\x0c\x12\x10\n\x08identity\x18\x06 \x01(\tB\x16\n\x14new_manager_identity"c\n"SetWorkerDeploymentManagerResponse\x12\x16\n\x0e\x63onflict_token\x18\x01 \x01(\x0c\x12%\n\x19previous_manager_identity\x18\x02 \x01(\tB\x02\x18\x01"E\n\x1bGetCurrentDeploymentRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bseries_name\x18\x02 \x01(\t"k\n\x1cGetCurrentDeploymentResponse\x12K\n\x17\x63urrent_deployment_info\x18\x01 \x01(\x0b\x32*.temporal.api.deployment.v1.DeploymentInfo"q\n GetDeploymentReachabilityRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12:\n\ndeployment\x18\x02 \x01(\x0b\x32&.temporal.api.deployment.v1.Deployment"\xe3\x01\n!GetDeploymentReachabilityResponse\x12\x43\n\x0f\x64\x65ployment_info\x18\x01 \x01(\x0b\x32*.temporal.api.deployment.v1.DeploymentInfo\x12\x43\n\x0creachability\x18\x02 \x01(\x0e\x32-.temporal.api.enums.v1.DeploymentReachability\x12\x34\n\x10last_update_time\x18\x03 \x01(\x0b\x32\x1a.google.protobuf.Timestamp"\xb4\x01\n\x19\x43reateWorkflowRuleRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x35\n\x04spec\x18\x02 \x01(\x0b\x32\'.temporal.api.rules.v1.WorkflowRuleSpec\x12\x12\n\nforce_scan\x18\x03 \x01(\x08\x12\x12\n\nrequest_id\x18\x04 \x01(\t\x12\x10\n\x08identity\x18\x05 \x01(\t\x12\x13\n\x0b\x64\x65scription\x18\x06 \x01(\t"_\n\x1a\x43reateWorkflowRuleResponse\x12\x31\n\x04rule\x18\x01 \x01(\x0b\x32#.temporal.api.rules.v1.WorkflowRule\x12\x0e\n\x06job_id\x18\x02 \x01(\t"A\n\x1b\x44\x65scribeWorkflowRuleRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x0f\n\x07rule_id\x18\x02 \x01(\t"Q\n\x1c\x44\x65scribeWorkflowRuleResponse\x12\x31\n\x04rule\x18\x01 \x01(\x0b\x32#.temporal.api.rules.v1.WorkflowRule"?\n\x19\x44\x65leteWorkflowRuleRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x0f\n\x07rule_id\x18\x02 \x01(\t"\x1c\n\x1a\x44\x65leteWorkflowRuleResponse"F\n\x18ListWorkflowRulesRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c"h\n\x19ListWorkflowRulesResponse\x12\x32\n\x05rules\x18\x01 \x03(\x0b\x32#.temporal.api.rules.v1.WorkflowRule\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c"\xce\x01\n\x1aTriggerWorkflowRuleRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12<\n\texecution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x0c\n\x02id\x18\x04 \x01(\tH\x00\x12\x37\n\x04spec\x18\x05 \x01(\x0b\x32\'.temporal.api.rules.v1.WorkflowRuleSpecH\x00\x12\x10\n\x08identity\x18\x03 \x01(\tB\x06\n\x04rule".\n\x1bTriggerWorkflowRuleResponse\x12\x0f\n\x07\x61pplied\x18\x01 \x01(\x08"\x9b\x01\n\x1cRecordWorkerHeartbeatRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x10\n\x08identity\x18\x02 \x01(\t\x12\x41\n\x10worker_heartbeat\x18\x03 \x03(\x0b\x32\'.temporal.api.worker.v1.WorkerHeartbeat\x12\x13\n\x0bresource_id\x18\x04 \x01(\t"\x1f\n\x1dRecordWorkerHeartbeatResponse"b\n\x12ListWorkersRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x11\n\tpage_size\x18\x02 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c\x12\r\n\x05query\x18\x04 \x01(\t"\xa5\x01\n\x13ListWorkersResponse\x12<\n\x0cworkers_info\x18\x01 \x03(\x0b\x32".temporal.api.worker.v1.WorkerInfoB\x02\x18\x01\x12\x37\n\x07workers\x18\x03 \x03(\x0b\x32&.temporal.api.worker.v1.WorkerListInfo\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c"\xd5\x05\n\x1cUpdateTaskQueueConfigRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x10\n\x08identity\x18\x02 \x01(\t\x12\x12\n\ntask_queue\x18\x03 \x01(\t\x12=\n\x0ftask_queue_type\x18\x04 \x01(\x0e\x32$.temporal.api.enums.v1.TaskQueueType\x12n\n\x17update_queue_rate_limit\x18\x05 \x01(\x0b\x32M.temporal.api.workflowservice.v1.UpdateTaskQueueConfigRequest.RateLimitUpdate\x12}\n&update_fairness_key_rate_limit_default\x18\x06 \x01(\x0b\x32M.temporal.api.workflowservice.v1.UpdateTaskQueueConfigRequest.RateLimitUpdate\x12\x84\x01\n\x1dset_fairness_weight_overrides\x18\x07 \x03(\x0b\x32].temporal.api.workflowservice.v1.UpdateTaskQueueConfigRequest.SetFairnessWeightOverridesEntry\x12\'\n\x1funset_fairness_weight_overrides\x18\x08 \x03(\t\x1a[\n\x0fRateLimitUpdate\x12\x38\n\nrate_limit\x18\x01 \x01(\x0b\x32$.temporal.api.taskqueue.v1.RateLimit\x12\x0e\n\x06reason\x18\x02 \x01(\t\x1a\x41\n\x1fSetFairnessWeightOverridesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\x02:\x02\x38\x01"[\n\x1dUpdateTaskQueueConfigResponse\x12:\n\x06\x63onfig\x18\x01 \x01(\x0b\x32*.temporal.api.taskqueue.v1.TaskQueueConfig"\x9e\x01\n\x18\x46\x65tchWorkerConfigRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x10\n\x08identity\x18\x02 \x01(\t\x12\x0e\n\x06reason\x18\x03 \x01(\t\x12\x38\n\x08selector\x18\x06 \x01(\x0b\x32&.temporal.api.common.v1.WorkerSelector\x12\x13\n\x0bresource_id\x18\x07 \x01(\t"U\n\x19\x46\x65tchWorkerConfigResponse\x12\x38\n\rworker_config\x18\x01 \x01(\x0b\x32!.temporal.api.sdk.v1.WorkerConfig"\x8a\x02\n\x19UpdateWorkerConfigRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x10\n\x08identity\x18\x02 \x01(\t\x12\x0e\n\x06reason\x18\x03 \x01(\t\x12\x38\n\rworker_config\x18\x04 \x01(\x0b\x32!.temporal.api.sdk.v1.WorkerConfig\x12/\n\x0bupdate_mask\x18\x05 \x01(\x0b\x32\x1a.google.protobuf.FieldMask\x12\x38\n\x08selector\x18\x06 \x01(\x0b\x32&.temporal.api.common.v1.WorkerSelector\x12\x13\n\x0bresource_id\x18\x07 \x01(\t"d\n\x1aUpdateWorkerConfigResponse\x12:\n\rworker_config\x18\x01 \x01(\x0b\x32!.temporal.api.sdk.v1.WorkerConfigH\x00\x42\n\n\x08response"G\n\x15\x44\x65scribeWorkerRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x1b\n\x13worker_instance_key\x18\x02 \x01(\t"Q\n\x16\x44\x65scribeWorkerResponse\x12\x37\n\x0bworker_info\x18\x01 \x01(\x0b\x32".temporal.api.worker.v1.WorkerInfo"\x8d\x01\n\x1dPauseWorkflowExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x12\x10\n\x08identity\x18\x04 \x01(\t\x12\x0e\n\x06reason\x18\x05 \x01(\t\x12\x12\n\nrequest_id\x18\x06 \x01(\t" \n\x1ePauseWorkflowExecutionResponse"\x8f\x01\n\x1fUnpauseWorkflowExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x12\x10\n\x08identity\x18\x04 \x01(\t\x12\x0e\n\x06reason\x18\x05 \x01(\t\x12\x12\n\nrequest_id\x18\x06 \x01(\t""\n UnpauseWorkflowExecutionResponse"\xb4\x07\n\x1dStartActivityExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x10\n\x08identity\x18\x02 \x01(\t\x12\x12\n\nrequest_id\x18\x03 \x01(\t\x12\x13\n\x0b\x61\x63tivity_id\x18\x04 \x01(\t\x12;\n\ractivity_type\x18\x05 \x01(\x0b\x32$.temporal.api.common.v1.ActivityType\x12\x38\n\ntask_queue\x18\x06 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12<\n\x19schedule_to_close_timeout\x18\x07 \x01(\x0b\x32\x19.google.protobuf.Duration\x12<\n\x19schedule_to_start_timeout\x18\x08 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x39\n\x16start_to_close_timeout\x18\t \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x34\n\x11heartbeat_timeout\x18\n \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x39\n\x0cretry_policy\x18\x0b \x01(\x0b\x32#.temporal.api.common.v1.RetryPolicy\x12/\n\x05input\x18\x0c \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x45\n\x0fid_reuse_policy\x18\r \x01(\x0e\x32,.temporal.api.enums.v1.ActivityIdReusePolicy\x12K\n\x12id_conflict_policy\x18\x0e \x01(\x0e\x32/.temporal.api.enums.v1.ActivityIdConflictPolicy\x12\x43\n\x11search_attributes\x18\x0f \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes\x12.\n\x06header\x18\x10 \x01(\x0b\x32\x1e.temporal.api.common.v1.Header\x12\x38\n\ruser_metadata\x18\x11 \x01(\x0b\x32!.temporal.api.sdk.v1.UserMetadata\x12\x32\n\x08priority\x18\x12 \x01(\x0b\x32 .temporal.api.common.v1.Priority"A\n\x1eStartActivityExecutionResponse\x12\x0e\n\x06run_id\x18\x01 \x01(\t\x12\x0f\n\x07started\x18\x02 \x01(\x08"\xa3\x01\n DescribeActivityExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0b\x61\x63tivity_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x12\x15\n\rinclude_input\x18\x04 \x01(\x08\x12\x17\n\x0finclude_outcome\x18\x05 \x01(\x08\x12\x17\n\x0flong_poll_token\x18\x06 \x01(\x0c"\x81\x02\n!DescribeActivityExecutionResponse\x12\x0e\n\x06run_id\x18\x01 \x01(\t\x12=\n\x04info\x18\x02 \x01(\x0b\x32/.temporal.api.activity.v1.ActivityExecutionInfo\x12/\n\x05input\x18\x03 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x43\n\x07outcome\x18\x04 \x01(\x0b\x32\x32.temporal.api.activity.v1.ActivityExecutionOutcome\x12\x17\n\x0flong_poll_token\x18\x05 \x01(\x0c"V\n\x1cPollActivityExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0b\x61\x63tivity_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t"t\n\x1dPollActivityExecutionResponse\x12\x0e\n\x06run_id\x18\x01 \x01(\t\x12\x43\n\x07outcome\x18\x02 \x01(\x0b\x32\x32.temporal.api.activity.v1.ActivityExecutionOutcome"m\n\x1dListActivityExecutionsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x11\n\tpage_size\x18\x02 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c\x12\r\n\x05query\x18\x04 \x01(\t"\x82\x01\n\x1eListActivityExecutionsResponse\x12G\n\nexecutions\x18\x01 \x03(\x0b\x32\x33.temporal.api.activity.v1.ActivityExecutionListInfo\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c"B\n\x1e\x43ountActivityExecutionsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\r\n\x05query\x18\x02 \x01(\t"\xed\x01\n\x1f\x43ountActivityExecutionsResponse\x12\r\n\x05\x63ount\x18\x01 \x01(\x03\x12\x61\n\x06groups\x18\x02 \x03(\x0b\x32Q.temporal.api.workflowservice.v1.CountActivityExecutionsResponse.AggregationGroup\x1aX\n\x10\x41ggregationGroup\x12\x35\n\x0cgroup_values\x18\x01 \x03(\x0b\x32\x1f.temporal.api.common.v1.Payload\x12\r\n\x05\x63ount\x18\x02 \x01(\x03"\x95\x01\n%RequestCancelActivityExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0b\x61\x63tivity_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x12\x10\n\x08identity\x18\x04 \x01(\t\x12\x12\n\nrequest_id\x18\x05 \x01(\t\x12\x0e\n\x06reason\x18\x06 \x01(\t"(\n&RequestCancelActivityExecutionResponse"\x91\x01\n!TerminateActivityExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0b\x61\x63tivity_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x12\x10\n\x08identity\x18\x04 \x01(\t\x12\x12\n\nrequest_id\x18\x05 \x01(\t\x12\x0e\n\x06reason\x18\x06 \x01(\t"$\n"TerminateActivityExecutionResponse"X\n\x1e\x44\x65leteActivityExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0b\x61\x63tivity_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t"!\n\x1f\x44\x65leteActivityExecutionResponseB\xbe\x01\n"io.temporal.api.workflowservice.v1B\x14RequestResponseProtoP\x01Z5go.temporal.io/api/workflowservice/v1;workflowservice\xaa\x02!Temporalio.Api.WorkflowService.V1\xea\x02$Temporalio::Api::WorkflowService::V1b\x06proto3' + b'\n6temporal/api/workflowservice/v1/request_response.proto\x12\x1ftemporal.api.workflowservice.v1\x1a+temporal/api/enums/v1/batch_operation.proto\x1a"temporal/api/enums/v1/common.proto\x1a$temporal/api/enums/v1/workflow.proto\x1a%temporal/api/enums/v1/namespace.proto\x1a(temporal/api/enums/v1/failed_cause.proto\x1a!temporal/api/enums/v1/query.proto\x1a!temporal/api/enums/v1/reset.proto\x1a&temporal/api/enums/v1/task_queue.proto\x1a&temporal/api/enums/v1/deployment.proto\x1a"temporal/api/enums/v1/update.proto\x1a$temporal/api/enums/v1/activity.proto\x1a!temporal/api/enums/v1/nexus.proto\x1a&temporal/api/activity/v1/message.proto\x1a$temporal/api/common/v1/message.proto\x1a%temporal/api/history/v1/message.proto\x1a&temporal/api/workflow/v1/message.proto\x1a%temporal/api/command/v1/message.proto\x1a$temporal/api/compute/v1/config.proto\x1a(temporal/api/deployment/v1/message.proto\x1a%temporal/api/failure/v1/message.proto\x1a$temporal/api/filter/v1/message.proto\x1a&temporal/api/protocol/v1/message.proto\x1a\'temporal/api/namespace/v1/message.proto\x1a#temporal/api/query/v1/message.proto\x1a)temporal/api/replication/v1/message.proto\x1a#temporal/api/rules/v1/message.proto\x1a\'temporal/api/sdk/v1/worker_config.proto\x1a&temporal/api/schedule/v1/message.proto\x1a\'temporal/api/taskqueue/v1/message.proto\x1a$temporal/api/update/v1/message.proto\x1a%temporal/api/version/v1/message.proto\x1a#temporal/api/batch/v1/message.proto\x1a\x30temporal/api/sdk/v1/task_complete_metadata.proto\x1a\'temporal/api/sdk/v1/user_metadata.proto\x1a#temporal/api/nexus/v1/message.proto\x1a$temporal/api/worker/v1/message.proto\x1a\x1egoogle/protobuf/duration.proto\x1a google/protobuf/field_mask.proto\x1a\x1fgoogle/protobuf/timestamp.proto"\x88\x05\n\x18RegisterNamespaceRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0b\x64\x65scription\x18\x02 \x01(\t\x12\x13\n\x0bowner_email\x18\x03 \x01(\t\x12\x46\n#workflow_execution_retention_period\x18\x04 \x01(\x0b\x32\x19.google.protobuf.Duration\x12G\n\x08\x63lusters\x18\x05 \x03(\x0b\x32\x35.temporal.api.replication.v1.ClusterReplicationConfig\x12\x1b\n\x13\x61\x63tive_cluster_name\x18\x06 \x01(\t\x12Q\n\x04\x64\x61ta\x18\x07 \x03(\x0b\x32\x43.temporal.api.workflowservice.v1.RegisterNamespaceRequest.DataEntry\x12\x16\n\x0esecurity_token\x18\x08 \x01(\t\x12\x1b\n\x13is_global_namespace\x18\t \x01(\x08\x12\x44\n\x16history_archival_state\x18\n \x01(\x0e\x32$.temporal.api.enums.v1.ArchivalState\x12\x1c\n\x14history_archival_uri\x18\x0b \x01(\t\x12G\n\x19visibility_archival_state\x18\x0c \x01(\x0e\x32$.temporal.api.enums.v1.ArchivalState\x12\x1f\n\x17visibility_archival_uri\x18\r \x01(\t\x1a+\n\tDataEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01"\x1b\n\x19RegisterNamespaceResponse"\x89\x01\n\x15ListNamespacesRequest\x12\x11\n\tpage_size\x18\x01 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c\x12\x44\n\x10namespace_filter\x18\x03 \x01(\x0b\x32*.temporal.api.namespace.v1.NamespaceFilter"\x81\x01\n\x16ListNamespacesResponse\x12N\n\nnamespaces\x18\x01 \x03(\x0b\x32:.temporal.api.workflowservice.v1.DescribeNamespaceResponse\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c"9\n\x18\x44\x65scribeNamespaceRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\n\n\x02id\x18\x02 \x01(\t"\xec\x02\n\x19\x44\x65scribeNamespaceResponse\x12@\n\x0enamespace_info\x18\x01 \x01(\x0b\x32(.temporal.api.namespace.v1.NamespaceInfo\x12:\n\x06\x63onfig\x18\x02 \x01(\x0b\x32*.temporal.api.namespace.v1.NamespaceConfig\x12S\n\x12replication_config\x18\x03 \x01(\x0b\x32\x37.temporal.api.replication.v1.NamespaceReplicationConfig\x12\x18\n\x10\x66\x61ilover_version\x18\x04 \x01(\x03\x12\x1b\n\x13is_global_namespace\x18\x05 \x01(\x08\x12\x45\n\x10\x66\x61ilover_history\x18\x06 \x03(\x0b\x32+.temporal.api.replication.v1.FailoverStatus"\xcf\x02\n\x16UpdateNamespaceRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x43\n\x0bupdate_info\x18\x02 \x01(\x0b\x32..temporal.api.namespace.v1.UpdateNamespaceInfo\x12:\n\x06\x63onfig\x18\x03 \x01(\x0b\x32*.temporal.api.namespace.v1.NamespaceConfig\x12S\n\x12replication_config\x18\x04 \x01(\x0b\x32\x37.temporal.api.replication.v1.NamespaceReplicationConfig\x12\x16\n\x0esecurity_token\x18\x05 \x01(\t\x12\x19\n\x11\x64\x65lete_bad_binary\x18\x06 \x01(\t\x12\x19\n\x11promote_namespace\x18\x07 \x01(\x08"\xa3\x02\n\x17UpdateNamespaceResponse\x12@\n\x0enamespace_info\x18\x01 \x01(\x0b\x32(.temporal.api.namespace.v1.NamespaceInfo\x12:\n\x06\x63onfig\x18\x02 \x01(\x0b\x32*.temporal.api.namespace.v1.NamespaceConfig\x12S\n\x12replication_config\x18\x03 \x01(\x0b\x32\x37.temporal.api.replication.v1.NamespaceReplicationConfig\x12\x18\n\x10\x66\x61ilover_version\x18\x04 \x01(\x03\x12\x1b\n\x13is_global_namespace\x18\x05 \x01(\x08"F\n\x19\x44\x65precateNamespaceRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x16\n\x0esecurity_token\x18\x02 \x01(\t"\x1c\n\x1a\x44\x65precateNamespaceResponse"\xd3\x0c\n\x1dStartWorkflowExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12;\n\rworkflow_type\x18\x03 \x01(\x0b\x32$.temporal.api.common.v1.WorkflowType\x12\x38\n\ntask_queue\x18\x04 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12/\n\x05input\x18\x05 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12=\n\x1aworkflow_execution_timeout\x18\x06 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x37\n\x14workflow_run_timeout\x18\x07 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x38\n\x15workflow_task_timeout\x18\x08 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x10\n\x08identity\x18\t \x01(\t\x12\x12\n\nrequest_id\x18\n \x01(\t\x12N\n\x18workflow_id_reuse_policy\x18\x0b \x01(\x0e\x32,.temporal.api.enums.v1.WorkflowIdReusePolicy\x12T\n\x1bworkflow_id_conflict_policy\x18\x16 \x01(\x0e\x32/.temporal.api.enums.v1.WorkflowIdConflictPolicy\x12\x39\n\x0cretry_policy\x18\x0c \x01(\x0b\x32#.temporal.api.common.v1.RetryPolicy\x12\x15\n\rcron_schedule\x18\r \x01(\t\x12*\n\x04memo\x18\x0e \x01(\x0b\x32\x1c.temporal.api.common.v1.Memo\x12\x43\n\x11search_attributes\x18\x0f \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes\x12.\n\x06header\x18\x10 \x01(\x0b\x32\x1e.temporal.api.common.v1.Header\x12\x1f\n\x17request_eager_execution\x18\x11 \x01(\x08\x12;\n\x11\x63ontinued_failure\x18\x12 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12@\n\x16last_completion_result\x18\x13 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x37\n\x14workflow_start_delay\x18\x14 \x01(\x0b\x32\x19.google.protobuf.Duration\x12>\n\x14\x63ompletion_callbacks\x18\x15 \x03(\x0b\x32 .temporal.api.common.v1.Callback\x12\x38\n\ruser_metadata\x18\x17 \x01(\x0b\x32!.temporal.api.sdk.v1.UserMetadata\x12+\n\x05links\x18\x18 \x03(\x0b\x32\x1c.temporal.api.common.v1.Link\x12I\n\x13versioning_override\x18\x19 \x01(\x0b\x32,.temporal.api.workflow.v1.VersioningOverride\x12H\n\x13on_conflict_options\x18\x1a \x01(\x0b\x32+.temporal.api.workflow.v1.OnConflictOptions\x12\x32\n\x08priority\x18\x1b \x01(\x0b\x32 .temporal.api.common.v1.Priority\x12\\\n\x1f\x65\x61ger_worker_deployment_options\x18\x1c \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentOptions\x12J\n\x14time_skipping_config\x18\x1d \x01(\x0b\x32,.temporal.api.workflow.v1.TimeSkippingConfig"\x8a\x02\n\x1eStartWorkflowExecutionResponse\x12\x0e\n\x06run_id\x18\x01 \x01(\t\x12\x0f\n\x07started\x18\x03 \x01(\x08\x12>\n\x06status\x18\x05 \x01(\x0e\x32..temporal.api.enums.v1.WorkflowExecutionStatus\x12[\n\x13\x65\x61ger_workflow_task\x18\x02 \x01(\x0b\x32>.temporal.api.workflowservice.v1.PollWorkflowTaskQueueResponse\x12*\n\x04link\x18\x04 \x01(\x0b\x32\x1c.temporal.api.common.v1.Link"\xaa\x02\n"GetWorkflowExecutionHistoryRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12<\n\texecution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x19\n\x11maximum_page_size\x18\x03 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x04 \x01(\x0c\x12\x16\n\x0ewait_new_event\x18\x05 \x01(\x08\x12P\n\x19history_event_filter_type\x18\x06 \x01(\x0e\x32-.temporal.api.enums.v1.HistoryEventFilterType\x12\x15\n\rskip_archival\x18\x07 \x01(\x08"\xba\x01\n#GetWorkflowExecutionHistoryResponse\x12\x31\n\x07history\x18\x01 \x01(\x0b\x32 .temporal.api.history.v1.History\x12\x35\n\x0braw_history\x18\x02 \x03(\x0b\x32 .temporal.api.common.v1.DataBlob\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c\x12\x10\n\x08\x61rchived\x18\x04 \x01(\x08"\xb0\x01\n)GetWorkflowExecutionHistoryReverseRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12<\n\texecution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x19\n\x11maximum_page_size\x18\x03 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x04 \x01(\x0c"x\n*GetWorkflowExecutionHistoryReverseResponse\x12\x31\n\x07history\x18\x01 \x01(\x0b\x32 .temporal.api.history.v1.History\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c"\xb8\x03\n\x1cPollWorkflowTaskQueueRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x38\n\ntask_queue\x18\x02 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12\x17\n\x0fpoller_group_id\x18\n \x01(\t\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x1b\n\x13worker_instance_key\x18\x08 \x01(\t\x12!\n\x19worker_control_task_queue\x18\t \x01(\t\x12\x1b\n\x0f\x62inary_checksum\x18\x04 \x01(\tB\x02\x18\x01\x12Z\n\x1bworker_version_capabilities\x18\x05 \x01(\x0b\x32\x31.temporal.api.common.v1.WorkerVersionCapabilitiesB\x02\x18\x01\x12O\n\x12\x64\x65ployment_options\x18\x06 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentOptionsJ\x04\x08\x07\x10\x08R\x10worker_heartbeat"\xf2\x07\n\x1dPollWorkflowTaskQueueResponse\x12\x12\n\ntask_token\x18\x01 \x01(\x0c\x12\x45\n\x12workflow_execution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12;\n\rworkflow_type\x18\x03 \x01(\x0b\x32$.temporal.api.common.v1.WorkflowType\x12!\n\x19previous_started_event_id\x18\x04 \x01(\x03\x12\x18\n\x10started_event_id\x18\x05 \x01(\x03\x12\x0f\n\x07\x61ttempt\x18\x06 \x01(\x05\x12\x1a\n\x12\x62\x61\x63klog_count_hint\x18\x07 \x01(\x03\x12\x31\n\x07history\x18\x08 \x01(\x0b\x32 .temporal.api.history.v1.History\x12\x17\n\x0fnext_page_token\x18\t \x01(\x0c\x12\x33\n\x05query\x18\n \x01(\x0b\x32$.temporal.api.query.v1.WorkflowQuery\x12K\n\x1dworkflow_execution_task_queue\x18\x0b \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12\x32\n\x0escheduled_time\x18\x0c \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x30\n\x0cstarted_time\x18\r \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\\\n\x07queries\x18\x0e \x03(\x0b\x32K.temporal.api.workflowservice.v1.PollWorkflowTaskQueueResponse.QueriesEntry\x12\x33\n\x08messages\x18\x0f \x03(\x0b\x32!.temporal.api.protocol.v1.Message\x12Q\n\x17poller_scaling_decision\x18\x10 \x01(\x0b\x32\x30.temporal.api.taskqueue.v1.PollerScalingDecision\x12\x17\n\x0fpoller_group_id\x18\x11 \x01(\t\x12\x46\n\x12poller_group_infos\x18\x12 \x03(\x0b\x32*.temporal.api.taskqueue.v1.PollerGroupInfo\x1aT\n\x0cQueriesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x33\n\x05value\x18\x02 \x01(\x0b\x32$.temporal.api.query.v1.WorkflowQuery:\x02\x38\x01"\x8a\n\n#RespondWorkflowTaskCompletedRequest\x12\x12\n\ntask_token\x18\x01 \x01(\x0c\x12\x32\n\x08\x63ommands\x18\x02 \x03(\x0b\x32 .temporal.api.command.v1.Command\x12\x10\n\x08identity\x18\x03 \x01(\t\x12O\n\x11sticky_attributes\x18\x04 \x01(\x0b\x32\x34.temporal.api.taskqueue.v1.StickyExecutionAttributes\x12 \n\x18return_new_workflow_task\x18\x05 \x01(\x08\x12&\n\x1e\x66orce_create_new_workflow_task\x18\x06 \x01(\x08\x12\x1b\n\x0f\x62inary_checksum\x18\x07 \x01(\tB\x02\x18\x01\x12m\n\rquery_results\x18\x08 \x03(\x0b\x32V.temporal.api.workflowservice.v1.RespondWorkflowTaskCompletedRequest.QueryResultsEntry\x12\x11\n\tnamespace\x18\t \x01(\t\x12\x13\n\x0bresource_id\x18\x12 \x01(\t\x12L\n\x14worker_version_stamp\x18\n \x01(\x0b\x32*.temporal.api.common.v1.WorkerVersionStampB\x02\x18\x01\x12\x33\n\x08messages\x18\x0b \x03(\x0b\x32!.temporal.api.protocol.v1.Message\x12H\n\x0csdk_metadata\x18\x0c \x01(\x0b\x32\x32.temporal.api.sdk.v1.WorkflowTaskCompletedMetadata\x12\x43\n\x11metering_metadata\x18\r \x01(\x0b\x32(.temporal.api.common.v1.MeteringMetadata\x12g\n\x0c\x63\x61pabilities\x18\x0e \x01(\x0b\x32Q.temporal.api.workflowservice.v1.RespondWorkflowTaskCompletedRequest.Capabilities\x12>\n\ndeployment\x18\x0f \x01(\x0b\x32&.temporal.api.deployment.v1.DeploymentB\x02\x18\x01\x12\x46\n\x13versioning_behavior\x18\x10 \x01(\x0e\x32).temporal.api.enums.v1.VersioningBehavior\x12O\n\x12\x64\x65ployment_options\x18\x11 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentOptions\x12\x1b\n\x13worker_instance_key\x18\x13 \x01(\t\x12!\n\x19worker_control_task_queue\x18\x14 \x01(\t\x1a_\n\x11QueryResultsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x39\n\x05value\x18\x02 \x01(\x0b\x32*.temporal.api.query.v1.WorkflowQueryResult:\x02\x38\x01\x1a\x45\n\x0c\x43\x61pabilities\x12\x35\n-discard_speculative_workflow_task_with_events\x18\x01 \x01(\x08"\xf5\x01\n$RespondWorkflowTaskCompletedResponse\x12U\n\rworkflow_task\x18\x01 \x01(\x0b\x32>.temporal.api.workflowservice.v1.PollWorkflowTaskQueueResponse\x12V\n\x0e\x61\x63tivity_tasks\x18\x02 \x03(\x0b\x32>.temporal.api.workflowservice.v1.PollActivityTaskQueueResponse\x12\x1e\n\x16reset_history_event_id\x18\x03 \x01(\x03"\x8d\x04\n RespondWorkflowTaskFailedRequest\x12\x12\n\ntask_token\x18\x01 \x01(\x0c\x12=\n\x05\x63\x61use\x18\x02 \x01(\x0e\x32..temporal.api.enums.v1.WorkflowTaskFailedCause\x12\x31\n\x07\x66\x61ilure\x18\x03 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12\x10\n\x08identity\x18\x04 \x01(\t\x12\x1b\n\x0f\x62inary_checksum\x18\x05 \x01(\tB\x02\x18\x01\x12\x11\n\tnamespace\x18\x06 \x01(\t\x12\x13\n\x0bresource_id\x18\x0b \x01(\t\x12\x33\n\x08messages\x18\x07 \x03(\x0b\x32!.temporal.api.protocol.v1.Message\x12\x46\n\x0eworker_version\x18\x08 \x01(\x0b\x32*.temporal.api.common.v1.WorkerVersionStampB\x02\x18\x01\x12>\n\ndeployment\x18\t \x01(\x0b\x32&.temporal.api.deployment.v1.DeploymentB\x02\x18\x01\x12O\n\x12\x64\x65ployment_options\x18\n \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentOptions"#\n!RespondWorkflowTaskFailedResponse"\xe6\x03\n\x1cPollActivityTaskQueueRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x38\n\ntask_queue\x18\x02 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12\x17\n\x0fpoller_group_id\x18\n \x01(\t\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x1b\n\x13worker_instance_key\x18\x08 \x01(\t\x12!\n\x19worker_control_task_queue\x18\t \x01(\t\x12I\n\x13task_queue_metadata\x18\x04 \x01(\x0b\x32,.temporal.api.taskqueue.v1.TaskQueueMetadata\x12Z\n\x1bworker_version_capabilities\x18\x05 \x01(\x0b\x32\x31.temporal.api.common.v1.WorkerVersionCapabilitiesB\x02\x18\x01\x12O\n\x12\x64\x65ployment_options\x18\x06 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentOptionsJ\x04\x08\x07\x10\x08R\x10worker_heartbeat"\xd0\x08\n\x1dPollActivityTaskQueueResponse\x12\x12\n\ntask_token\x18\x01 \x01(\x0c\x12\x1a\n\x12workflow_namespace\x18\x02 \x01(\t\x12;\n\rworkflow_type\x18\x03 \x01(\x0b\x32$.temporal.api.common.v1.WorkflowType\x12\x45\n\x12workflow_execution\x18\x04 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12;\n\ractivity_type\x18\x05 \x01(\x0b\x32$.temporal.api.common.v1.ActivityType\x12\x13\n\x0b\x61\x63tivity_id\x18\x06 \x01(\t\x12.\n\x06header\x18\x07 \x01(\x0b\x32\x1e.temporal.api.common.v1.Header\x12/\n\x05input\x18\x08 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12;\n\x11heartbeat_details\x18\t \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x32\n\x0escheduled_time\x18\n \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x42\n\x1e\x63urrent_attempt_scheduled_time\x18\x0b \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x30\n\x0cstarted_time\x18\x0c \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x0f\n\x07\x61ttempt\x18\r \x01(\x05\x12<\n\x19schedule_to_close_timeout\x18\x0e \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x39\n\x16start_to_close_timeout\x18\x0f \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x34\n\x11heartbeat_timeout\x18\x10 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x39\n\x0cretry_policy\x18\x11 \x01(\x0b\x32#.temporal.api.common.v1.RetryPolicy\x12Q\n\x17poller_scaling_decision\x18\x12 \x01(\x0b\x32\x30.temporal.api.taskqueue.v1.PollerScalingDecision\x12\x32\n\x08priority\x18\x13 \x01(\x0b\x32 .temporal.api.common.v1.Priority\x12\x17\n\x0f\x61\x63tivity_run_id\x18\x14 \x01(\t\x12\x46\n\x12poller_group_infos\x18\x15 \x03(\x0b\x32*.temporal.api.taskqueue.v1.PollerGroupInfo"\xa5\x01\n"RecordActivityTaskHeartbeatRequest\x12\x12\n\ntask_token\x18\x01 \x01(\x0c\x12\x31\n\x07\x64\x65tails\x18\x02 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x11\n\tnamespace\x18\x04 \x01(\t\x12\x13\n\x0bresource_id\x18\x05 \x01(\t"p\n#RecordActivityTaskHeartbeatResponse\x12\x18\n\x10\x63\x61ncel_requested\x18\x01 \x01(\x08\x12\x17\n\x0f\x61\x63tivity_paused\x18\x02 \x01(\x08\x12\x16\n\x0e\x61\x63tivity_reset\x18\x03 \x01(\x08"\xcf\x01\n&RecordActivityTaskHeartbeatByIdRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x12\x13\n\x0b\x61\x63tivity_id\x18\x04 \x01(\t\x12\x31\n\x07\x64\x65tails\x18\x05 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x10\n\x08identity\x18\x06 \x01(\t\x12\x13\n\x0bresource_id\x18\x07 \x01(\t"t\n\'RecordActivityTaskHeartbeatByIdResponse\x12\x18\n\x10\x63\x61ncel_requested\x18\x01 \x01(\x08\x12\x17\n\x0f\x61\x63tivity_paused\x18\x02 \x01(\x08\x12\x16\n\x0e\x61\x63tivity_reset\x18\x03 \x01(\x08"\xfe\x02\n#RespondActivityTaskCompletedRequest\x12\x12\n\ntask_token\x18\x01 \x01(\x0c\x12\x30\n\x06result\x18\x02 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x11\n\tnamespace\x18\x04 \x01(\t\x12\x13\n\x0bresource_id\x18\x08 \x01(\t\x12\x46\n\x0eworker_version\x18\x05 \x01(\x0b\x32*.temporal.api.common.v1.WorkerVersionStampB\x02\x18\x01\x12>\n\ndeployment\x18\x06 \x01(\x0b\x32&.temporal.api.deployment.v1.DeploymentB\x02\x18\x01\x12O\n\x12\x64\x65ployment_options\x18\x07 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentOptions"&\n$RespondActivityTaskCompletedResponse"\xcf\x01\n\'RespondActivityTaskCompletedByIdRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x12\x13\n\x0b\x61\x63tivity_id\x18\x04 \x01(\t\x12\x30\n\x06result\x18\x05 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x10\n\x08identity\x18\x06 \x01(\t\x12\x13\n\x0bresource_id\x18\x07 \x01(\t"*\n(RespondActivityTaskCompletedByIdResponse"\xbe\x03\n RespondActivityTaskFailedRequest\x12\x12\n\ntask_token\x18\x01 \x01(\x0c\x12\x31\n\x07\x66\x61ilure\x18\x02 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x11\n\tnamespace\x18\x04 \x01(\t\x12\x13\n\x0bresource_id\x18\t \x01(\t\x12@\n\x16last_heartbeat_details\x18\x05 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x46\n\x0eworker_version\x18\x06 \x01(\x0b\x32*.temporal.api.common.v1.WorkerVersionStampB\x02\x18\x01\x12>\n\ndeployment\x18\x07 \x01(\x0b\x32&.temporal.api.deployment.v1.DeploymentB\x02\x18\x01\x12O\n\x12\x64\x65ployment_options\x18\x08 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentOptions"W\n!RespondActivityTaskFailedResponse\x12\x32\n\x08\x66\x61ilures\x18\x01 \x03(\x0b\x32 .temporal.api.failure.v1.Failure"\x8f\x02\n$RespondActivityTaskFailedByIdRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x12\x13\n\x0b\x61\x63tivity_id\x18\x04 \x01(\t\x12\x31\n\x07\x66\x61ilure\x18\x05 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12\x10\n\x08identity\x18\x06 \x01(\t\x12@\n\x16last_heartbeat_details\x18\x07 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x13\n\x0bresource_id\x18\x08 \x01(\t"[\n%RespondActivityTaskFailedByIdResponse\x12\x32\n\x08\x66\x61ilures\x18\x01 \x03(\x0b\x32 .temporal.api.failure.v1.Failure"\xfe\x02\n"RespondActivityTaskCanceledRequest\x12\x12\n\ntask_token\x18\x01 \x01(\x0c\x12\x31\n\x07\x64\x65tails\x18\x02 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x11\n\tnamespace\x18\x04 \x01(\t\x12\x13\n\x0bresource_id\x18\x08 \x01(\t\x12\x46\n\x0eworker_version\x18\x05 \x01(\x0b\x32*.temporal.api.common.v1.WorkerVersionStampB\x02\x18\x01\x12>\n\ndeployment\x18\x06 \x01(\x0b\x32&.temporal.api.deployment.v1.DeploymentB\x02\x18\x01\x12O\n\x12\x64\x65ployment_options\x18\x07 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentOptions"%\n#RespondActivityTaskCanceledResponse"\xa0\x02\n&RespondActivityTaskCanceledByIdRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x12\x13\n\x0b\x61\x63tivity_id\x18\x04 \x01(\t\x12\x31\n\x07\x64\x65tails\x18\x05 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x10\n\x08identity\x18\x06 \x01(\t\x12O\n\x12\x64\x65ployment_options\x18\x07 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentOptions\x12\x13\n\x0bresource_id\x18\x08 \x01(\t")\n\'RespondActivityTaskCanceledByIdResponse"\x84\x02\n%RequestCancelWorkflowExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x45\n\x12workflow_execution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x12\n\nrequest_id\x18\x04 \x01(\t\x12\x1e\n\x16\x66irst_execution_run_id\x18\x05 \x01(\t\x12\x0e\n\x06reason\x18\x06 \x01(\t\x12+\n\x05links\x18\x07 \x03(\x0b\x32\x1c.temporal.api.common.v1.Link"(\n&RequestCancelWorkflowExecutionResponse"\xde\x02\n\x1eSignalWorkflowExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x45\n\x12workflow_execution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x13\n\x0bsignal_name\x18\x03 \x01(\t\x12/\n\x05input\x18\x04 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x10\n\x08identity\x18\x05 \x01(\t\x12\x12\n\nrequest_id\x18\x06 \x01(\t\x12\x13\n\x07\x63ontrol\x18\x07 \x01(\tB\x02\x18\x01\x12.\n\x06header\x18\x08 \x01(\x0b\x32\x1e.temporal.api.common.v1.Header\x12+\n\x05links\x18\n \x03(\x0b\x32\x1c.temporal.api.common.v1.LinkJ\x04\x08\t\x10\n"M\n\x1fSignalWorkflowExecutionResponse\x12*\n\x04link\x18\x01 \x01(\x0b\x32\x1c.temporal.api.common.v1.Link"\xbd\n\n\'SignalWithStartWorkflowExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12;\n\rworkflow_type\x18\x03 \x01(\x0b\x32$.temporal.api.common.v1.WorkflowType\x12\x38\n\ntask_queue\x18\x04 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12/\n\x05input\x18\x05 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12=\n\x1aworkflow_execution_timeout\x18\x06 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x37\n\x14workflow_run_timeout\x18\x07 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x38\n\x15workflow_task_timeout\x18\x08 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x10\n\x08identity\x18\t \x01(\t\x12\x12\n\nrequest_id\x18\n \x01(\t\x12N\n\x18workflow_id_reuse_policy\x18\x0b \x01(\x0e\x32,.temporal.api.enums.v1.WorkflowIdReusePolicy\x12T\n\x1bworkflow_id_conflict_policy\x18\x16 \x01(\x0e\x32/.temporal.api.enums.v1.WorkflowIdConflictPolicy\x12\x13\n\x0bsignal_name\x18\x0c \x01(\t\x12\x36\n\x0csignal_input\x18\r \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x13\n\x07\x63ontrol\x18\x0e \x01(\tB\x02\x18\x01\x12\x39\n\x0cretry_policy\x18\x0f \x01(\x0b\x32#.temporal.api.common.v1.RetryPolicy\x12\x15\n\rcron_schedule\x18\x10 \x01(\t\x12*\n\x04memo\x18\x11 \x01(\x0b\x32\x1c.temporal.api.common.v1.Memo\x12\x43\n\x11search_attributes\x18\x12 \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes\x12.\n\x06header\x18\x13 \x01(\x0b\x32\x1e.temporal.api.common.v1.Header\x12\x37\n\x14workflow_start_delay\x18\x14 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x38\n\ruser_metadata\x18\x17 \x01(\x0b\x32!.temporal.api.sdk.v1.UserMetadata\x12+\n\x05links\x18\x18 \x03(\x0b\x32\x1c.temporal.api.common.v1.Link\x12I\n\x13versioning_override\x18\x19 \x01(\x0b\x32,.temporal.api.workflow.v1.VersioningOverride\x12\x32\n\x08priority\x18\x1a \x01(\x0b\x32 .temporal.api.common.v1.Priority\x12J\n\x14time_skipping_config\x18\x1b \x01(\x0b\x32,.temporal.api.workflow.v1.TimeSkippingConfigJ\x04\x08\x15\x10\x16"~\n(SignalWithStartWorkflowExecutionResponse\x12\x0e\n\x06run_id\x18\x01 \x01(\t\x12\x0f\n\x07started\x18\x02 \x01(\x08\x12\x31\n\x0bsignal_link\x18\x03 \x01(\x0b\x32\x1c.temporal.api.common.v1.Link"\xc1\x03\n\x1dResetWorkflowExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x45\n\x12workflow_execution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x0e\n\x06reason\x18\x03 \x01(\t\x12%\n\x1dworkflow_task_finish_event_id\x18\x04 \x01(\x03\x12\x12\n\nrequest_id\x18\x05 \x01(\t\x12G\n\x12reset_reapply_type\x18\x06 \x01(\x0e\x32\'.temporal.api.enums.v1.ResetReapplyTypeB\x02\x18\x01\x12S\n\x1breset_reapply_exclude_types\x18\x07 \x03(\x0e\x32..temporal.api.enums.v1.ResetReapplyExcludeType\x12K\n\x15post_reset_operations\x18\x08 \x03(\x0b\x32,.temporal.api.workflow.v1.PostResetOperation\x12\x10\n\x08identity\x18\t \x01(\t"0\n\x1eResetWorkflowExecutionResponse\x12\x0e\n\x06run_id\x18\x01 \x01(\t"\x9f\x02\n!TerminateWorkflowExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x45\n\x12workflow_execution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x0e\n\x06reason\x18\x03 \x01(\t\x12\x31\n\x07\x64\x65tails\x18\x04 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x10\n\x08identity\x18\x05 \x01(\t\x12\x1e\n\x16\x66irst_execution_run_id\x18\x06 \x01(\t\x12+\n\x05links\x18\x07 \x03(\x0b\x32\x1c.temporal.api.common.v1.Link"$\n"TerminateWorkflowExecutionResponse"z\n\x1e\x44\x65leteWorkflowExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x45\n\x12workflow_execution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution"!\n\x1f\x44\x65leteWorkflowExecutionResponse"\xc9\x02\n!ListOpenWorkflowExecutionsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x19\n\x11maximum_page_size\x18\x02 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c\x12\x42\n\x11start_time_filter\x18\x04 \x01(\x0b\x32\'.temporal.api.filter.v1.StartTimeFilter\x12K\n\x10\x65xecution_filter\x18\x05 \x01(\x0b\x32/.temporal.api.filter.v1.WorkflowExecutionFilterH\x00\x12\x41\n\x0btype_filter\x18\x06 \x01(\x0b\x32*.temporal.api.filter.v1.WorkflowTypeFilterH\x00\x42\t\n\x07\x66ilters"\x82\x01\n"ListOpenWorkflowExecutionsResponse\x12\x43\n\nexecutions\x18\x01 \x03(\x0b\x32/.temporal.api.workflow.v1.WorkflowExecutionInfo\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c"\x8a\x03\n#ListClosedWorkflowExecutionsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x19\n\x11maximum_page_size\x18\x02 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c\x12\x42\n\x11start_time_filter\x18\x04 \x01(\x0b\x32\'.temporal.api.filter.v1.StartTimeFilter\x12K\n\x10\x65xecution_filter\x18\x05 \x01(\x0b\x32/.temporal.api.filter.v1.WorkflowExecutionFilterH\x00\x12\x41\n\x0btype_filter\x18\x06 \x01(\x0b\x32*.temporal.api.filter.v1.WorkflowTypeFilterH\x00\x12=\n\rstatus_filter\x18\x07 \x01(\x0b\x32$.temporal.api.filter.v1.StatusFilterH\x00\x42\t\n\x07\x66ilters"\x84\x01\n$ListClosedWorkflowExecutionsResponse\x12\x43\n\nexecutions\x18\x01 \x03(\x0b\x32/.temporal.api.workflow.v1.WorkflowExecutionInfo\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c"m\n\x1dListWorkflowExecutionsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x11\n\tpage_size\x18\x02 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c\x12\r\n\x05query\x18\x04 \x01(\t"~\n\x1eListWorkflowExecutionsResponse\x12\x43\n\nexecutions\x18\x01 \x03(\x0b\x32/.temporal.api.workflow.v1.WorkflowExecutionInfo\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c"u\n%ListArchivedWorkflowExecutionsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x11\n\tpage_size\x18\x02 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c\x12\r\n\x05query\x18\x04 \x01(\t"\x86\x01\n&ListArchivedWorkflowExecutionsResponse\x12\x43\n\nexecutions\x18\x01 \x03(\x0b\x32/.temporal.api.workflow.v1.WorkflowExecutionInfo\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c"m\n\x1dScanWorkflowExecutionsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x11\n\tpage_size\x18\x02 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c\x12\r\n\x05query\x18\x04 \x01(\t"~\n\x1eScanWorkflowExecutionsResponse\x12\x43\n\nexecutions\x18\x01 \x03(\x0b\x32/.temporal.api.workflow.v1.WorkflowExecutionInfo\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c"B\n\x1e\x43ountWorkflowExecutionsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\r\n\x05query\x18\x02 \x01(\t"\xed\x01\n\x1f\x43ountWorkflowExecutionsResponse\x12\r\n\x05\x63ount\x18\x01 \x01(\x03\x12\x61\n\x06groups\x18\x02 \x03(\x0b\x32Q.temporal.api.workflowservice.v1.CountWorkflowExecutionsResponse.AggregationGroup\x1aX\n\x10\x41ggregationGroup\x12\x35\n\x0cgroup_values\x18\x01 \x03(\x0b\x32\x1f.temporal.api.common.v1.Payload\x12\r\n\x05\x63ount\x18\x02 \x01(\x03"\x1c\n\x1aGetSearchAttributesRequest"\xc9\x01\n\x1bGetSearchAttributesResponse\x12T\n\x04keys\x18\x01 \x03(\x0b\x32\x46.temporal.api.workflowservice.v1.GetSearchAttributesResponse.KeysEntry\x1aT\n\tKeysEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x36\n\x05value\x18\x02 \x01(\x0e\x32\'.temporal.api.enums.v1.IndexedValueType:\x02\x38\x01"\xe9\x02\n RespondQueryTaskCompletedRequest\x12\x12\n\ntask_token\x18\x01 \x01(\x0c\x12>\n\x0e\x63ompleted_type\x18\x02 \x01(\x0e\x32&.temporal.api.enums.v1.QueryResultType\x12\x36\n\x0cquery_result\x18\x03 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x15\n\rerror_message\x18\x04 \x01(\t\x12\x11\n\tnamespace\x18\x06 \x01(\t\x12\x31\n\x07\x66\x61ilure\x18\x07 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12=\n\x05\x63\x61use\x18\x08 \x01(\x0e\x32..temporal.api.enums.v1.WorkflowTaskFailedCause\x12\x17\n\x0fpoller_group_id\x18\t \x01(\tJ\x04\x08\x05\x10\x06"#\n!RespondQueryTaskCompletedResponse"n\n\x1bResetStickyTaskQueueRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12<\n\texecution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution"\x1e\n\x1cResetStickyTaskQueueResponse"\x9b\x02\n\x15ShutdownWorkerRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x19\n\x11sticky_task_queue\x18\x02 \x01(\t\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x0e\n\x06reason\x18\x04 \x01(\t\x12\x41\n\x10worker_heartbeat\x18\x05 \x01(\x0b\x32\'.temporal.api.worker.v1.WorkerHeartbeat\x12\x1b\n\x13worker_instance_key\x18\x06 \x01(\t\x12\x12\n\ntask_queue\x18\x07 \x01(\t\x12>\n\x10task_queue_types\x18\x08 \x03(\x0e\x32$.temporal.api.enums.v1.TaskQueueType"\x18\n\x16ShutdownWorkerResponse"\xe9\x01\n\x14QueryWorkflowRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12<\n\texecution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x33\n\x05query\x18\x03 \x01(\x0b\x32$.temporal.api.query.v1.WorkflowQuery\x12K\n\x16query_reject_condition\x18\x04 \x01(\x0e\x32+.temporal.api.enums.v1.QueryRejectCondition"\x8d\x01\n\x15QueryWorkflowResponse\x12\x36\n\x0cquery_result\x18\x01 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12<\n\x0equery_rejected\x18\x02 \x01(\x0b\x32$.temporal.api.query.v1.QueryRejected"s\n DescribeWorkflowExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12<\n\texecution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution"\x99\x05\n!DescribeWorkflowExecutionResponse\x12K\n\x10\x65xecution_config\x18\x01 \x01(\x0b\x32\x31.temporal.api.workflow.v1.WorkflowExecutionConfig\x12P\n\x17workflow_execution_info\x18\x02 \x01(\x0b\x32/.temporal.api.workflow.v1.WorkflowExecutionInfo\x12I\n\x12pending_activities\x18\x03 \x03(\x0b\x32-.temporal.api.workflow.v1.PendingActivityInfo\x12M\n\x10pending_children\x18\x04 \x03(\x0b\x32\x33.temporal.api.workflow.v1.PendingChildExecutionInfo\x12P\n\x15pending_workflow_task\x18\x05 \x01(\x0b\x32\x31.temporal.api.workflow.v1.PendingWorkflowTaskInfo\x12\x39\n\tcallbacks\x18\x06 \x03(\x0b\x32&.temporal.api.workflow.v1.CallbackInfo\x12U\n\x18pending_nexus_operations\x18\x07 \x03(\x0b\x32\x33.temporal.api.workflow.v1.PendingNexusOperationInfo\x12W\n\x16workflow_extended_info\x18\x08 \x01(\x0b\x32\x37.temporal.api.workflow.v1.WorkflowExecutionExtendedInfo"\x90\x04\n\x18\x44\x65scribeTaskQueueRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x38\n\ntask_queue\x18\x02 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12=\n\x0ftask_queue_type\x18\x03 \x01(\x0e\x32$.temporal.api.enums.v1.TaskQueueType\x12\x14\n\x0creport_stats\x18\x08 \x01(\x08\x12\x15\n\rreport_config\x18\x0b \x01(\x08\x12%\n\x19include_task_queue_status\x18\x04 \x01(\x08\x42\x02\x18\x01\x12\x42\n\x08\x61pi_mode\x18\x05 \x01(\x0e\x32,.temporal.api.enums.v1.DescribeTaskQueueModeB\x02\x18\x01\x12J\n\x08versions\x18\x06 \x01(\x0b\x32\x34.temporal.api.taskqueue.v1.TaskQueueVersionSelectionB\x02\x18\x01\x12\x42\n\x10task_queue_types\x18\x07 \x03(\x0e\x32$.temporal.api.enums.v1.TaskQueueTypeB\x02\x18\x01\x12\x1a\n\x0ereport_pollers\x18\t \x01(\x08\x42\x02\x18\x01\x12$\n\x18report_task_reachability\x18\n \x01(\x08\x42\x02\x18\x01"\xec\x07\n\x19\x44\x65scribeTaskQueueResponse\x12\x36\n\x07pollers\x18\x01 \x03(\x0b\x32%.temporal.api.taskqueue.v1.PollerInfo\x12\x38\n\x05stats\x18\x05 \x01(\x0b\x32).temporal.api.taskqueue.v1.TaskQueueStats\x12q\n\x15stats_by_priority_key\x18\x08 \x03(\x0b\x32R.temporal.api.workflowservice.v1.DescribeTaskQueueResponse.StatsByPriorityKeyEntry\x12K\n\x0fversioning_info\x18\x04 \x01(\x0b\x32\x32.temporal.api.taskqueue.v1.TaskQueueVersioningInfo\x12:\n\x06\x63onfig\x18\x06 \x01(\x0b\x32*.temporal.api.taskqueue.v1.TaskQueueConfig\x12k\n\x14\x65\x66\x66\x65\x63tive_rate_limit\x18\x07 \x01(\x0b\x32M.temporal.api.workflowservice.v1.DescribeTaskQueueResponse.EffectiveRateLimit\x12I\n\x11task_queue_status\x18\x02 \x01(\x0b\x32*.temporal.api.taskqueue.v1.TaskQueueStatusB\x02\x18\x01\x12g\n\rversions_info\x18\x03 \x03(\x0b\x32L.temporal.api.workflowservice.v1.DescribeTaskQueueResponse.VersionsInfoEntryB\x02\x18\x01\x1a\x64\n\x17StatsByPriorityKeyEntry\x12\x0b\n\x03key\x18\x01 \x01(\x05\x12\x38\n\x05value\x18\x02 \x01(\x0b\x32).temporal.api.taskqueue.v1.TaskQueueStats:\x02\x38\x01\x1at\n\x12\x45\x66\x66\x65\x63tiveRateLimit\x12\x1b\n\x13requests_per_second\x18\x01 \x01(\x02\x12\x41\n\x11rate_limit_source\x18\x02 \x01(\x0e\x32&.temporal.api.enums.v1.RateLimitSource\x1a\x64\n\x11VersionsInfoEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12>\n\x05value\x18\x02 \x01(\x0b\x32/.temporal.api.taskqueue.v1.TaskQueueVersionInfo:\x02\x38\x01"\x17\n\x15GetClusterInfoRequest"\xd1\x03\n\x16GetClusterInfoResponse\x12h\n\x11supported_clients\x18\x01 \x03(\x0b\x32M.temporal.api.workflowservice.v1.GetClusterInfoResponse.SupportedClientsEntry\x12\x16\n\x0eserver_version\x18\x02 \x01(\t\x12\x12\n\ncluster_id\x18\x03 \x01(\t\x12:\n\x0cversion_info\x18\x04 \x01(\x0b\x32$.temporal.api.version.v1.VersionInfo\x12\x14\n\x0c\x63luster_name\x18\x05 \x01(\t\x12\x1b\n\x13history_shard_count\x18\x06 \x01(\x05\x12\x19\n\x11persistence_store\x18\x07 \x01(\t\x12\x18\n\x10visibility_store\x18\x08 \x01(\t\x12 \n\x18initial_failover_version\x18\t \x01(\x03\x12"\n\x1a\x66\x61ilover_version_increment\x18\n \x01(\x03\x1a\x37\n\x15SupportedClientsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01"\x16\n\x14GetSystemInfoRequest"\x97\x04\n\x15GetSystemInfoResponse\x12\x16\n\x0eserver_version\x18\x01 \x01(\t\x12Y\n\x0c\x63\x61pabilities\x18\x02 \x01(\x0b\x32\x43.temporal.api.workflowservice.v1.GetSystemInfoResponse.Capabilities\x1a\x8a\x03\n\x0c\x43\x61pabilities\x12\x1f\n\x17signal_and_query_header\x18\x01 \x01(\x08\x12&\n\x1einternal_error_differentiation\x18\x02 \x01(\x08\x12*\n"activity_failure_include_heartbeat\x18\x03 \x01(\x08\x12\x1a\n\x12supports_schedules\x18\x04 \x01(\x08\x12"\n\x1a\x65ncoded_failure_attributes\x18\x05 \x01(\x08\x12!\n\x19\x62uild_id_based_versioning\x18\x06 \x01(\x08\x12\x13\n\x0bupsert_memo\x18\x07 \x01(\x08\x12\x1c\n\x14\x65\x61ger_workflow_start\x18\x08 \x01(\x08\x12\x14\n\x0csdk_metadata\x18\t \x01(\x08\x12\'\n\x1f\x63ount_group_by_execution_status\x18\n \x01(\x08\x12\r\n\x05nexus\x18\x0b \x01(\x08\x12!\n\x19server_scaled_deployments\x18\x0c \x01(\x08"m\n\x1eListTaskQueuePartitionsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x38\n\ntask_queue\x18\x02 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue"\xdf\x01\n\x1fListTaskQueuePartitionsResponse\x12]\n\x1e\x61\x63tivity_task_queue_partitions\x18\x01 \x03(\x0b\x32\x35.temporal.api.taskqueue.v1.TaskQueuePartitionMetadata\x12]\n\x1eworkflow_task_queue_partitions\x18\x02 \x03(\x0b\x32\x35.temporal.api.taskqueue.v1.TaskQueuePartitionMetadata"\xcc\x02\n\x15\x43reateScheduleRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bschedule_id\x18\x02 \x01(\t\x12\x34\n\x08schedule\x18\x03 \x01(\x0b\x32".temporal.api.schedule.v1.Schedule\x12>\n\rinitial_patch\x18\x04 \x01(\x0b\x32\'.temporal.api.schedule.v1.SchedulePatch\x12\x10\n\x08identity\x18\x05 \x01(\t\x12\x12\n\nrequest_id\x18\x06 \x01(\t\x12*\n\x04memo\x18\x07 \x01(\x0b\x32\x1c.temporal.api.common.v1.Memo\x12\x43\n\x11search_attributes\x18\x08 \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes"0\n\x16\x43reateScheduleResponse\x12\x16\n\x0e\x63onflict_token\x18\x01 \x01(\x0c"A\n\x17\x44\x65scribeScheduleRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bschedule_id\x18\x02 \x01(\t"\x8f\x02\n\x18\x44\x65scribeScheduleResponse\x12\x34\n\x08schedule\x18\x01 \x01(\x0b\x32".temporal.api.schedule.v1.Schedule\x12\x34\n\x04info\x18\x02 \x01(\x0b\x32&.temporal.api.schedule.v1.ScheduleInfo\x12*\n\x04memo\x18\x03 \x01(\x0b\x32\x1c.temporal.api.common.v1.Memo\x12\x43\n\x11search_attributes\x18\x04 \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes\x12\x16\n\x0e\x63onflict_token\x18\x05 \x01(\x0c"\xa4\x02\n\x15UpdateScheduleRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bschedule_id\x18\x02 \x01(\t\x12\x34\n\x08schedule\x18\x03 \x01(\x0b\x32".temporal.api.schedule.v1.Schedule\x12\x16\n\x0e\x63onflict_token\x18\x04 \x01(\x0c\x12\x10\n\x08identity\x18\x05 \x01(\t\x12\x12\n\nrequest_id\x18\x06 \x01(\t\x12\x43\n\x11search_attributes\x18\x07 \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes\x12*\n\x04memo\x18\x08 \x01(\x0b\x32\x1c.temporal.api.common.v1.Memo"\x18\n\x16UpdateScheduleResponse"\x9c\x01\n\x14PatchScheduleRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bschedule_id\x18\x02 \x01(\t\x12\x36\n\x05patch\x18\x03 \x01(\x0b\x32\'.temporal.api.schedule.v1.SchedulePatch\x12\x10\n\x08identity\x18\x04 \x01(\t\x12\x12\n\nrequest_id\x18\x05 \x01(\t"\x17\n\x15PatchScheduleResponse"\xa8\x01\n ListScheduleMatchingTimesRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bschedule_id\x18\x02 \x01(\t\x12.\n\nstart_time\x18\x03 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12,\n\x08\x65nd_time\x18\x04 \x01(\x0b\x32\x1a.google.protobuf.Timestamp"S\n!ListScheduleMatchingTimesResponse\x12.\n\nstart_time\x18\x01 \x03(\x0b\x32\x1a.google.protobuf.Timestamp"Q\n\x15\x44\x65leteScheduleRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bschedule_id\x18\x02 \x01(\t\x12\x10\n\x08identity\x18\x03 \x01(\t"\x18\n\x16\x44\x65leteScheduleResponse"l\n\x14ListSchedulesRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x19\n\x11maximum_page_size\x18\x02 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c\x12\r\n\x05query\x18\x04 \x01(\t"p\n\x15ListSchedulesResponse\x12>\n\tschedules\x18\x01 \x03(\x0b\x32+.temporal.api.schedule.v1.ScheduleListEntry\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c"9\n\x15\x43ountSchedulesRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\r\n\x05query\x18\x02 \x01(\t"\xdb\x01\n\x16\x43ountSchedulesResponse\x12\r\n\x05\x63ount\x18\x01 \x01(\x03\x12X\n\x06groups\x18\x02 \x03(\x0b\x32H.temporal.api.workflowservice.v1.CountSchedulesResponse.AggregationGroup\x1aX\n\x10\x41ggregationGroup\x12\x35\n\x0cgroup_values\x18\x01 \x03(\x0b\x32\x1f.temporal.api.common.v1.Payload\x12\r\n\x05\x63ount\x18\x02 \x01(\x03"\x86\x05\n\'UpdateWorkerBuildIdCompatibilityRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x12\n\ntask_queue\x18\x02 \x01(\t\x12-\n#add_new_build_id_in_new_default_set\x18\x03 \x01(\tH\x00\x12\x87\x01\n\x1b\x61\x64\x64_new_compatible_build_id\x18\x04 \x01(\x0b\x32`.temporal.api.workflowservice.v1.UpdateWorkerBuildIdCompatibilityRequest.AddNewCompatibleVersionH\x00\x12!\n\x17promote_set_by_build_id\x18\x05 \x01(\tH\x00\x12%\n\x1bpromote_build_id_within_set\x18\x06 \x01(\tH\x00\x12h\n\nmerge_sets\x18\x07 \x01(\x0b\x32R.temporal.api.workflowservice.v1.UpdateWorkerBuildIdCompatibilityRequest.MergeSetsH\x00\x1ao\n\x17\x41\x64\x64NewCompatibleVersion\x12\x14\n\x0cnew_build_id\x18\x01 \x01(\t\x12$\n\x1c\x65xisting_compatible_build_id\x18\x02 \x01(\t\x12\x18\n\x10make_set_default\x18\x03 \x01(\x08\x1aI\n\tMergeSets\x12\x1c\n\x14primary_set_build_id\x18\x01 \x01(\t\x12\x1e\n\x16secondary_set_build_id\x18\x02 \x01(\tB\x0b\n\toperation"@\n(UpdateWorkerBuildIdCompatibilityResponseJ\x04\x08\x01\x10\x02R\x0eversion_set_id"_\n$GetWorkerBuildIdCompatibilityRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x12\n\ntask_queue\x18\x02 \x01(\t\x12\x10\n\x08max_sets\x18\x03 \x01(\x05"t\n%GetWorkerBuildIdCompatibilityResponse\x12K\n\x12major_version_sets\x18\x01 \x03(\x0b\x32/.temporal.api.taskqueue.v1.CompatibleVersionSet"\xb5\r\n"UpdateWorkerVersioningRulesRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x12\n\ntask_queue\x18\x02 \x01(\t\x12\x16\n\x0e\x63onflict_token\x18\x03 \x01(\x0c\x12\x81\x01\n\x16insert_assignment_rule\x18\x04 \x01(\x0b\x32_.temporal.api.workflowservice.v1.UpdateWorkerVersioningRulesRequest.InsertBuildIdAssignmentRuleH\x00\x12\x83\x01\n\x17replace_assignment_rule\x18\x05 \x01(\x0b\x32`.temporal.api.workflowservice.v1.UpdateWorkerVersioningRulesRequest.ReplaceBuildIdAssignmentRuleH\x00\x12\x81\x01\n\x16\x64\x65lete_assignment_rule\x18\x06 \x01(\x0b\x32_.temporal.api.workflowservice.v1.UpdateWorkerVersioningRulesRequest.DeleteBuildIdAssignmentRuleH\x00\x12\x8c\x01\n\x1c\x61\x64\x64_compatible_redirect_rule\x18\x07 \x01(\x0b\x32\x64.temporal.api.workflowservice.v1.UpdateWorkerVersioningRulesRequest.AddCompatibleBuildIdRedirectRuleH\x00\x12\x94\x01\n replace_compatible_redirect_rule\x18\x08 \x01(\x0b\x32h.temporal.api.workflowservice.v1.UpdateWorkerVersioningRulesRequest.ReplaceCompatibleBuildIdRedirectRuleH\x00\x12\x92\x01\n\x1f\x64\x65lete_compatible_redirect_rule\x18\t \x01(\x0b\x32g.temporal.api.workflowservice.v1.UpdateWorkerVersioningRulesRequest.DeleteCompatibleBuildIdRedirectRuleH\x00\x12l\n\x0f\x63ommit_build_id\x18\n \x01(\x0b\x32Q.temporal.api.workflowservice.v1.UpdateWorkerVersioningRulesRequest.CommitBuildIdH\x00\x1aq\n\x1bInsertBuildIdAssignmentRule\x12\x12\n\nrule_index\x18\x01 \x01(\x05\x12>\n\x04rule\x18\x02 \x01(\x0b\x32\x30.temporal.api.taskqueue.v1.BuildIdAssignmentRule\x1a\x81\x01\n\x1cReplaceBuildIdAssignmentRule\x12\x12\n\nrule_index\x18\x01 \x01(\x05\x12>\n\x04rule\x18\x02 \x01(\x0b\x32\x30.temporal.api.taskqueue.v1.BuildIdAssignmentRule\x12\r\n\x05\x66orce\x18\x03 \x01(\x08\x1a@\n\x1b\x44\x65leteBuildIdAssignmentRule\x12\x12\n\nrule_index\x18\x01 \x01(\x05\x12\r\n\x05\x66orce\x18\x02 \x01(\x08\x1aj\n AddCompatibleBuildIdRedirectRule\x12\x46\n\x04rule\x18\x01 \x01(\x0b\x32\x38.temporal.api.taskqueue.v1.CompatibleBuildIdRedirectRule\x1an\n$ReplaceCompatibleBuildIdRedirectRule\x12\x46\n\x04rule\x18\x01 \x01(\x0b\x32\x38.temporal.api.taskqueue.v1.CompatibleBuildIdRedirectRule\x1a>\n#DeleteCompatibleBuildIdRedirectRule\x12\x17\n\x0fsource_build_id\x18\x01 \x01(\t\x1a\x37\n\rCommitBuildId\x12\x17\n\x0ftarget_build_id\x18\x01 \x01(\t\x12\r\n\x05\x66orce\x18\x02 \x01(\x08\x42\x0b\n\toperation"\xfc\x01\n#UpdateWorkerVersioningRulesResponse\x12U\n\x10\x61ssignment_rules\x18\x01 \x03(\x0b\x32;.temporal.api.taskqueue.v1.TimestampedBuildIdAssignmentRule\x12\x66\n\x19\x63ompatible_redirect_rules\x18\x02 \x03(\x0b\x32\x43.temporal.api.taskqueue.v1.TimestampedCompatibleBuildIdRedirectRule\x12\x16\n\x0e\x63onflict_token\x18\x03 \x01(\x0c"H\n\x1fGetWorkerVersioningRulesRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x12\n\ntask_queue\x18\x02 \x01(\t"\xf9\x01\n GetWorkerVersioningRulesResponse\x12U\n\x10\x61ssignment_rules\x18\x01 \x03(\x0b\x32;.temporal.api.taskqueue.v1.TimestampedBuildIdAssignmentRule\x12\x66\n\x19\x63ompatible_redirect_rules\x18\x02 \x03(\x0b\x32\x43.temporal.api.taskqueue.v1.TimestampedCompatibleBuildIdRedirectRule\x12\x16\n\x0e\x63onflict_token\x18\x03 \x01(\x0c"\x9c\x01\n GetWorkerTaskReachabilityRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x11\n\tbuild_ids\x18\x02 \x03(\t\x12\x13\n\x0btask_queues\x18\x03 \x03(\t\x12=\n\x0creachability\x18\x04 \x01(\x0e\x32\'.temporal.api.enums.v1.TaskReachability"r\n!GetWorkerTaskReachabilityResponse\x12M\n\x15\x62uild_id_reachability\x18\x01 \x03(\x0b\x32..temporal.api.taskqueue.v1.BuildIdReachability"\x85\x02\n\x1eUpdateWorkflowExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x45\n\x12workflow_execution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x1e\n\x16\x66irst_execution_run_id\x18\x03 \x01(\t\x12\x37\n\x0bwait_policy\x18\x04 \x01(\x0b\x32".temporal.api.update.v1.WaitPolicy\x12\x30\n\x07request\x18\x05 \x01(\x0b\x32\x1f.temporal.api.update.v1.Request"\xd7\x01\n\x1fUpdateWorkflowExecutionResponse\x12\x35\n\nupdate_ref\x18\x01 \x01(\x0b\x32!.temporal.api.update.v1.UpdateRef\x12\x30\n\x07outcome\x18\x02 \x01(\x0b\x32\x1f.temporal.api.update.v1.Outcome\x12K\n\x05stage\x18\x03 \x01(\x0e\x32<.temporal.api.enums.v1.UpdateWorkflowExecutionLifecycleStage"\xf4\x07\n\x1aStartBatchOperationRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x18\n\x10visibility_query\x18\x02 \x01(\t\x12\x0e\n\x06job_id\x18\x03 \x01(\t\x12\x0e\n\x06reason\x18\x04 \x01(\t\x12=\n\nexecutions\x18\x05 \x03(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12!\n\x19max_operations_per_second\x18\x06 \x01(\x02\x12Q\n\x15termination_operation\x18\n \x01(\x0b\x32\x30.temporal.api.batch.v1.BatchOperationTerminationH\x00\x12G\n\x10signal_operation\x18\x0b \x01(\x0b\x32+.temporal.api.batch.v1.BatchOperationSignalH\x00\x12S\n\x16\x63\x61ncellation_operation\x18\x0c \x01(\x0b\x32\x31.temporal.api.batch.v1.BatchOperationCancellationH\x00\x12K\n\x12\x64\x65letion_operation\x18\r \x01(\x0b\x32-.temporal.api.batch.v1.BatchOperationDeletionH\x00\x12\x45\n\x0freset_operation\x18\x0e \x01(\x0b\x32*.temporal.api.batch.v1.BatchOperationResetH\x00\x12p\n!update_workflow_options_operation\x18\x0f \x01(\x0b\x32\x43.temporal.api.batch.v1.BatchOperationUpdateWorkflowExecutionOptionsH\x00\x12^\n\x1cunpause_activities_operation\x18\x10 \x01(\x0b\x32\x36.temporal.api.batch.v1.BatchOperationUnpauseActivitiesH\x00\x12Z\n\x1areset_activities_operation\x18\x11 \x01(\x0b\x32\x34.temporal.api.batch.v1.BatchOperationResetActivitiesH\x00\x12g\n!update_activity_options_operation\x18\x12 \x01(\x0b\x32:.temporal.api.batch.v1.BatchOperationUpdateActivityOptionsH\x00\x42\x0b\n\toperation"\x1d\n\x1bStartBatchOperationResponse"`\n\x19StopBatchOperationRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x0e\n\x06job_id\x18\x02 \x01(\t\x12\x0e\n\x06reason\x18\x03 \x01(\t\x12\x10\n\x08identity\x18\x04 \x01(\t"\x1c\n\x1aStopBatchOperationResponse"B\n\x1d\x44\x65scribeBatchOperationRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x0e\n\x06job_id\x18\x02 \x01(\t"\x92\x03\n\x1e\x44\x65scribeBatchOperationResponse\x12\x41\n\x0eoperation_type\x18\x01 \x01(\x0e\x32).temporal.api.enums.v1.BatchOperationType\x12\x0e\n\x06job_id\x18\x02 \x01(\t\x12\x39\n\x05state\x18\x03 \x01(\x0e\x32*.temporal.api.enums.v1.BatchOperationState\x12.\n\nstart_time\x18\x04 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12.\n\nclose_time\x18\x05 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x1d\n\x15total_operation_count\x18\x06 \x01(\x03\x12 \n\x18\x63omplete_operation_count\x18\x07 \x01(\x03\x12\x1f\n\x17\x66\x61ilure_operation_count\x18\x08 \x01(\x03\x12\x10\n\x08identity\x18\t \x01(\t\x12\x0e\n\x06reason\x18\n \x01(\t"[\n\x1aListBatchOperationsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x11\n\tpage_size\x18\x02 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c"y\n\x1bListBatchOperationsResponse\x12\x41\n\x0eoperation_info\x18\x01 \x03(\x0b\x32).temporal.api.batch.v1.BatchOperationInfo\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c"\xb9\x01\n"PollWorkflowExecutionUpdateRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x35\n\nupdate_ref\x18\x02 \x01(\x0b\x32!.temporal.api.update.v1.UpdateRef\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x37\n\x0bwait_policy\x18\x04 \x01(\x0b\x32".temporal.api.update.v1.WaitPolicy"\xdb\x01\n#PollWorkflowExecutionUpdateResponse\x12\x30\n\x07outcome\x18\x01 \x01(\x0b\x32\x1f.temporal.api.update.v1.Outcome\x12K\n\x05stage\x18\x02 \x01(\x0e\x32<.temporal.api.enums.v1.UpdateWorkflowExecutionLifecycleStage\x12\x35\n\nupdate_ref\x18\x03 \x01(\x0b\x32!.temporal.api.update.v1.UpdateRef"\xa0\x03\n\x19PollNexusTaskQueueRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x38\n\ntask_queue\x18\x03 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12\x17\n\x0fpoller_group_id\x18\t \x01(\t\x12\x10\n\x08identity\x18\x02 \x01(\t\x12\x1b\n\x13worker_instance_key\x18\x08 \x01(\t\x12Z\n\x1bworker_version_capabilities\x18\x04 \x01(\x0b\x32\x31.temporal.api.common.v1.WorkerVersionCapabilitiesB\x02\x18\x01\x12O\n\x12\x64\x65ployment_options\x18\x06 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentOptions\x12\x41\n\x10worker_heartbeat\x18\x07 \x03(\x0b\x32\'.temporal.api.worker.v1.WorkerHeartbeat"\x95\x02\n\x1aPollNexusTaskQueueResponse\x12\x12\n\ntask_token\x18\x01 \x01(\x0c\x12/\n\x07request\x18\x02 \x01(\x0b\x32\x1e.temporal.api.nexus.v1.Request\x12Q\n\x17poller_scaling_decision\x18\x03 \x01(\x0b\x32\x30.temporal.api.taskqueue.v1.PollerScalingDecision\x12\x17\n\x0fpoller_group_id\x18\x04 \x01(\t\x12\x46\n\x12poller_group_infos\x18\x05 \x03(\x0b\x32*.temporal.api.taskqueue.v1.PollerGroupInfo"\xa7\x01\n RespondNexusTaskCompletedRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x10\n\x08identity\x18\x02 \x01(\t\x12\x12\n\ntask_token\x18\x03 \x01(\x0c\x12\x31\n\x08response\x18\x04 \x01(\x0b\x32\x1f.temporal.api.nexus.v1.Response\x12\x17\n\x0fpoller_group_id\x18\x05 \x01(\t"#\n!RespondNexusTaskCompletedResponse"\xdc\x01\n\x1dRespondNexusTaskFailedRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x10\n\x08identity\x18\x02 \x01(\t\x12\x12\n\ntask_token\x18\x03 \x01(\x0c\x12\x36\n\x05\x65rror\x18\x04 \x01(\x0b\x32#.temporal.api.nexus.v1.HandlerErrorB\x02\x18\x01\x12\x31\n\x07\x66\x61ilure\x18\x05 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12\x17\n\x0fpoller_group_id\x18\x06 \x01(\t" \n\x1eRespondNexusTaskFailedResponse"\xf4\x02\n\x1c\x45xecuteMultiOperationRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12[\n\noperations\x18\x02 \x03(\x0b\x32G.temporal.api.workflowservice.v1.ExecuteMultiOperationRequest.Operation\x12\x13\n\x0bresource_id\x18\x03 \x01(\t\x1a\xce\x01\n\tOperation\x12X\n\x0estart_workflow\x18\x01 \x01(\x0b\x32>.temporal.api.workflowservice.v1.StartWorkflowExecutionRequestH\x00\x12Z\n\x0fupdate_workflow\x18\x02 \x01(\x0b\x32?.temporal.api.workflowservice.v1.UpdateWorkflowExecutionRequestH\x00\x42\x0b\n\toperation"\xcc\x02\n\x1d\x45xecuteMultiOperationResponse\x12Z\n\tresponses\x18\x01 \x03(\x0b\x32G.temporal.api.workflowservice.v1.ExecuteMultiOperationResponse.Response\x1a\xce\x01\n\x08Response\x12Y\n\x0estart_workflow\x18\x01 \x01(\x0b\x32?.temporal.api.workflowservice.v1.StartWorkflowExecutionResponseH\x00\x12[\n\x0fupdate_workflow\x18\x02 \x01(\x0b\x32@.temporal.api.workflowservice.v1.UpdateWorkflowExecutionResponseH\x00\x42\n\n\x08response"\xd0\x02\n\x1cUpdateActivityOptionsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12<\n\texecution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x43\n\x10\x61\x63tivity_options\x18\x04 \x01(\x0b\x32).temporal.api.activity.v1.ActivityOptions\x12/\n\x0bupdate_mask\x18\x05 \x01(\x0b\x32\x1a.google.protobuf.FieldMask\x12\x0c\n\x02id\x18\x06 \x01(\tH\x00\x12\x0e\n\x04type\x18\x07 \x01(\tH\x00\x12\x13\n\tmatch_all\x18\t \x01(\x08H\x00\x12\x18\n\x10restore_original\x18\x08 \x01(\x08\x42\n\n\x08\x61\x63tivity"d\n\x1dUpdateActivityOptionsResponse\x12\x43\n\x10\x61\x63tivity_options\x18\x01 \x01(\x0b\x32).temporal.api.activity.v1.ActivityOptions"\xb3\x01\n\x14PauseActivityRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12<\n\texecution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x0c\n\x02id\x18\x04 \x01(\tH\x00\x12\x0e\n\x04type\x18\x05 \x01(\tH\x00\x12\x0e\n\x06reason\x18\x06 \x01(\tB\n\n\x08\x61\x63tivity"\x17\n\x15PauseActivityResponse"\x98\x02\n\x16UnpauseActivityRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12<\n\texecution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x0c\n\x02id\x18\x04 \x01(\tH\x00\x12\x0e\n\x04type\x18\x05 \x01(\tH\x00\x12\x15\n\x0bunpause_all\x18\x06 \x01(\x08H\x00\x12\x16\n\x0ereset_attempts\x18\x07 \x01(\x08\x12\x17\n\x0freset_heartbeat\x18\x08 \x01(\x08\x12)\n\x06jitter\x18\t \x01(\x0b\x32\x19.google.protobuf.DurationB\n\n\x08\x61\x63tivity"\x19\n\x17UnpauseActivityResponse"\xb3\x02\n\x14ResetActivityRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12<\n\texecution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x0c\n\x02id\x18\x04 \x01(\tH\x00\x12\x0e\n\x04type\x18\x05 \x01(\tH\x00\x12\x13\n\tmatch_all\x18\n \x01(\x08H\x00\x12\x17\n\x0freset_heartbeat\x18\x06 \x01(\x08\x12\x13\n\x0bkeep_paused\x18\x07 \x01(\x08\x12)\n\x06jitter\x18\x08 \x01(\x0b\x32\x19.google.protobuf.Duration\x12 \n\x18restore_original_options\x18\t \x01(\x08\x42\n\n\x08\x61\x63tivity"\x17\n\x15ResetActivityResponse"\x9c\x02\n%UpdateWorkflowExecutionOptionsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x45\n\x12workflow_execution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12V\n\x1aworkflow_execution_options\x18\x03 \x01(\x0b\x32\x32.temporal.api.workflow.v1.WorkflowExecutionOptions\x12/\n\x0bupdate_mask\x18\x04 \x01(\x0b\x32\x1a.google.protobuf.FieldMask\x12\x10\n\x08identity\x18\x05 \x01(\t"\x80\x01\n&UpdateWorkflowExecutionOptionsResponse\x12V\n\x1aworkflow_execution_options\x18\x01 \x01(\x0b\x32\x32.temporal.api.workflow.v1.WorkflowExecutionOptions"j\n\x19\x44\x65scribeDeploymentRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12:\n\ndeployment\x18\x02 \x01(\x0b\x32&.temporal.api.deployment.v1.Deployment"a\n\x1a\x44\x65scribeDeploymentResponse\x12\x43\n\x0f\x64\x65ployment_info\x18\x01 \x01(\x0b\x32*.temporal.api.deployment.v1.DeploymentInfo"\xc2\x01\n&DescribeWorkerDeploymentVersionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x07version\x18\x02 \x01(\tB\x02\x18\x01\x12O\n\x12\x64\x65ployment_version\x18\x03 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersion\x12\x1f\n\x17report_task_queue_stats\x18\x04 \x01(\x08"\x8c\x05\n\'DescribeWorkerDeploymentVersionResponse\x12_\n\x1eworker_deployment_version_info\x18\x01 \x01(\x0b\x32\x37.temporal.api.deployment.v1.WorkerDeploymentVersionInfo\x12v\n\x13version_task_queues\x18\x02 \x03(\x0b\x32Y.temporal.api.workflowservice.v1.DescribeWorkerDeploymentVersionResponse.VersionTaskQueue\x1a\x87\x03\n\x10VersionTaskQueue\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x32\n\x04type\x18\x02 \x01(\x0e\x32$.temporal.api.enums.v1.TaskQueueType\x12\x38\n\x05stats\x18\x03 \x01(\x0b\x32).temporal.api.taskqueue.v1.TaskQueueStats\x12\x90\x01\n\x15stats_by_priority_key\x18\x04 \x03(\x0b\x32q.temporal.api.workflowservice.v1.DescribeWorkerDeploymentVersionResponse.VersionTaskQueue.StatsByPriorityKeyEntry\x1a\x64\n\x17StatsByPriorityKeyEntry\x12\x0b\n\x03key\x18\x01 \x01(\x05\x12\x38\n\x05value\x18\x02 \x01(\x0b\x32).temporal.api.taskqueue.v1.TaskQueueStats:\x02\x38\x01"M\n\x1f\x44\x65scribeWorkerDeploymentRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x17\n\x0f\x64\x65ployment_name\x18\x02 \x01(\t"\x8c\x01\n DescribeWorkerDeploymentResponse\x12\x16\n\x0e\x63onflict_token\x18\x01 \x01(\x0c\x12P\n\x16worker_deployment_info\x18\x02 \x01(\x0b\x32\x30.temporal.api.deployment.v1.WorkerDeploymentInfo"l\n\x16ListDeploymentsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x11\n\tpage_size\x18\x02 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c\x12\x13\n\x0bseries_name\x18\x04 \x01(\t"w\n\x17ListDeploymentsResponse\x12\x17\n\x0fnext_page_token\x18\x01 \x01(\x0c\x12\x43\n\x0b\x64\x65ployments\x18\x02 \x03(\x0b\x32..temporal.api.deployment.v1.DeploymentListInfo"\xcd\x01\n\x1bSetCurrentDeploymentRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12:\n\ndeployment\x18\x02 \x01(\x0b\x32&.temporal.api.deployment.v1.Deployment\x12\x10\n\x08identity\x18\x03 \x01(\t\x12M\n\x0fupdate_metadata\x18\x04 \x01(\x0b\x32\x34.temporal.api.deployment.v1.UpdateDeploymentMetadata"\xb9\x01\n\x1cSetCurrentDeploymentResponse\x12K\n\x17\x63urrent_deployment_info\x18\x01 \x01(\x0b\x32*.temporal.api.deployment.v1.DeploymentInfo\x12L\n\x18previous_deployment_info\x18\x02 \x01(\x0b\x32*.temporal.api.deployment.v1.DeploymentInfo"\xe5\x01\n(SetWorkerDeploymentCurrentVersionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x17\n\x0f\x64\x65ployment_name\x18\x02 \x01(\t\x12\x13\n\x07version\x18\x03 \x01(\tB\x02\x18\x01\x12\x10\n\x08\x62uild_id\x18\x07 \x01(\t\x12\x16\n\x0e\x63onflict_token\x18\x04 \x01(\x0c\x12\x10\n\x08identity\x18\x05 \x01(\t\x12"\n\x1aignore_missing_task_queues\x18\x06 \x01(\x08\x12\x18\n\x10\x61llow_no_pollers\x18\t \x01(\x08"\xbf\x01\n)SetWorkerDeploymentCurrentVersionResponse\x12\x16\n\x0e\x63onflict_token\x18\x01 \x01(\x0c\x12\x1c\n\x10previous_version\x18\x02 \x01(\tB\x02\x18\x01\x12\\\n\x1bprevious_deployment_version\x18\x03 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersionB\x02\x18\x01"\xf9\x01\n(SetWorkerDeploymentRampingVersionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x17\n\x0f\x64\x65ployment_name\x18\x02 \x01(\t\x12\x13\n\x07version\x18\x03 \x01(\tB\x02\x18\x01\x12\x10\n\x08\x62uild_id\x18\x08 \x01(\t\x12\x12\n\npercentage\x18\x04 \x01(\x02\x12\x16\n\x0e\x63onflict_token\x18\x05 \x01(\x0c\x12\x10\n\x08identity\x18\x06 \x01(\t\x12"\n\x1aignore_missing_task_queues\x18\x07 \x01(\x08\x12\x18\n\x10\x61llow_no_pollers\x18\n \x01(\x08"\xe0\x01\n)SetWorkerDeploymentRampingVersionResponse\x12\x16\n\x0e\x63onflict_token\x18\x01 \x01(\x0c\x12\x1c\n\x10previous_version\x18\x02 \x01(\tB\x02\x18\x01\x12\\\n\x1bprevious_deployment_version\x18\x04 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersionB\x02\x18\x01\x12\x1f\n\x13previous_percentage\x18\x03 \x01(\x02\x42\x02\x18\x01"q\n\x1d\x43reateWorkerDeploymentRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x17\n\x0f\x64\x65ployment_name\x18\x02 \x01(\t\x12\x10\n\x08identity\x18\x04 \x01(\t\x12\x12\n\nrequest_id\x18\x05 \x01(\t"8\n\x1e\x43reateWorkerDeploymentResponse\x12\x16\n\x0e\x63onflict_token\x18\x01 \x01(\x0c"]\n\x1cListWorkerDeploymentsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x11\n\tpage_size\x18\x02 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c"\x9f\x05\n\x1dListWorkerDeploymentsResponse\x12\x17\n\x0fnext_page_token\x18\x01 \x01(\x0c\x12r\n\x12worker_deployments\x18\x02 \x03(\x0b\x32V.temporal.api.workflowservice.v1.ListWorkerDeploymentsResponse.WorkerDeploymentSummary\x1a\xf0\x03\n\x17WorkerDeploymentSummary\x12\x0c\n\x04name\x18\x01 \x01(\t\x12/\n\x0b\x63reate_time\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x41\n\x0erouting_config\x18\x03 \x01(\x0b\x32).temporal.api.deployment.v1.RoutingConfig\x12o\n\x16latest_version_summary\x18\x04 \x01(\x0b\x32O.temporal.api.deployment.v1.WorkerDeploymentInfo.WorkerDeploymentVersionSummary\x12p\n\x17\x63urrent_version_summary\x18\x05 \x01(\x0b\x32O.temporal.api.deployment.v1.WorkerDeploymentInfo.WorkerDeploymentVersionSummary\x12p\n\x17ramping_version_summary\x18\x06 \x01(\x0b\x32O.temporal.api.deployment.v1.WorkerDeploymentInfo.WorkerDeploymentVersionSummary"\xf0\x01\n$CreateWorkerDeploymentVersionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12O\n\x12\x64\x65ployment_version\x18\x02 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersion\x12>\n\x0e\x63ompute_config\x18\x04 \x01(\x0b\x32&.temporal.api.compute.v1.ComputeConfig\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x12\n\nrequest_id\x18\x05 \x01(\t"\'\n%CreateWorkerDeploymentVersionResponse"\xc8\x01\n$DeleteWorkerDeploymentVersionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x07version\x18\x02 \x01(\tB\x02\x18\x01\x12O\n\x12\x64\x65ployment_version\x18\x05 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersion\x12\x15\n\rskip_drainage\x18\x03 \x01(\x08\x12\x10\n\x08identity\x18\x04 \x01(\t"\'\n%DeleteWorkerDeploymentVersionResponse"]\n\x1d\x44\x65leteWorkerDeploymentRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x17\n\x0f\x64\x65ployment_name\x18\x02 \x01(\t\x12\x10\n\x08identity\x18\x03 \x01(\t" \n\x1e\x44\x65leteWorkerDeploymentResponse"\x84\x04\n1UpdateWorkerDeploymentVersionComputeConfigRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12O\n\x12\x64\x65ployment_version\x18\x02 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersion\x12\x99\x01\n\x1d\x63ompute_config_scaling_groups\x18\x06 \x03(\x0b\x32r.temporal.api.workflowservice.v1.UpdateWorkerDeploymentVersionComputeConfigRequest.ComputeConfigScalingGroupsEntry\x12,\n$remove_compute_config_scaling_groups\x18\x07 \x03(\t\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x12\n\nrequest_id\x18\x04 \x01(\t\x1a{\n\x1f\x43omputeConfigScalingGroupsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12G\n\x05value\x18\x02 \x01(\x0b\x32\x38.temporal.api.compute.v1.ComputeConfigScalingGroupUpdate:\x02\x38\x01"4\n2UpdateWorkerDeploymentVersionComputeConfigResponse"\xf4\x03\n3ValidateWorkerDeploymentVersionComputeConfigRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12O\n\x12\x64\x65ployment_version\x18\x02 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersion\x12\x9b\x01\n\x1d\x63ompute_config_scaling_groups\x18\x06 \x03(\x0b\x32t.temporal.api.workflowservice.v1.ValidateWorkerDeploymentVersionComputeConfigRequest.ComputeConfigScalingGroupsEntry\x12,\n$remove_compute_config_scaling_groups\x18\x07 \x03(\t\x12\x10\n\x08identity\x18\x03 \x01(\t\x1a{\n\x1f\x43omputeConfigScalingGroupsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12G\n\x05value\x18\x02 \x01(\x0b\x32\x38.temporal.api.compute.v1.ComputeConfigScalingGroupUpdate:\x02\x38\x01"6\n4ValidateWorkerDeploymentVersionComputeConfigResponse"\xa2\x03\n,UpdateWorkerDeploymentVersionMetadataRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x07version\x18\x02 \x01(\tB\x02\x18\x01\x12O\n\x12\x64\x65ployment_version\x18\x05 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersion\x12x\n\x0eupsert_entries\x18\x03 \x03(\x0b\x32`.temporal.api.workflowservice.v1.UpdateWorkerDeploymentVersionMetadataRequest.UpsertEntriesEntry\x12\x16\n\x0eremove_entries\x18\x04 \x03(\t\x12\x10\n\x08identity\x18\x06 \x01(\t\x1aU\n\x12UpsertEntriesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12.\n\x05value\x18\x02 \x01(\x0b\x32\x1f.temporal.api.common.v1.Payload:\x02\x38\x01"n\n-UpdateWorkerDeploymentVersionMetadataResponse\x12=\n\x08metadata\x18\x01 \x01(\x0b\x32+.temporal.api.deployment.v1.VersionMetadata"\xbd\x01\n!SetWorkerDeploymentManagerRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x17\n\x0f\x64\x65ployment_name\x18\x02 \x01(\t\x12\x1a\n\x10manager_identity\x18\x03 \x01(\tH\x00\x12\x0e\n\x04self\x18\x04 \x01(\x08H\x00\x12\x16\n\x0e\x63onflict_token\x18\x05 \x01(\x0c\x12\x10\n\x08identity\x18\x06 \x01(\tB\x16\n\x14new_manager_identity"c\n"SetWorkerDeploymentManagerResponse\x12\x16\n\x0e\x63onflict_token\x18\x01 \x01(\x0c\x12%\n\x19previous_manager_identity\x18\x02 \x01(\tB\x02\x18\x01"E\n\x1bGetCurrentDeploymentRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bseries_name\x18\x02 \x01(\t"k\n\x1cGetCurrentDeploymentResponse\x12K\n\x17\x63urrent_deployment_info\x18\x01 \x01(\x0b\x32*.temporal.api.deployment.v1.DeploymentInfo"q\n GetDeploymentReachabilityRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12:\n\ndeployment\x18\x02 \x01(\x0b\x32&.temporal.api.deployment.v1.Deployment"\xe3\x01\n!GetDeploymentReachabilityResponse\x12\x43\n\x0f\x64\x65ployment_info\x18\x01 \x01(\x0b\x32*.temporal.api.deployment.v1.DeploymentInfo\x12\x43\n\x0creachability\x18\x02 \x01(\x0e\x32-.temporal.api.enums.v1.DeploymentReachability\x12\x34\n\x10last_update_time\x18\x03 \x01(\x0b\x32\x1a.google.protobuf.Timestamp"\xb4\x01\n\x19\x43reateWorkflowRuleRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x35\n\x04spec\x18\x02 \x01(\x0b\x32\'.temporal.api.rules.v1.WorkflowRuleSpec\x12\x12\n\nforce_scan\x18\x03 \x01(\x08\x12\x12\n\nrequest_id\x18\x04 \x01(\t\x12\x10\n\x08identity\x18\x05 \x01(\t\x12\x13\n\x0b\x64\x65scription\x18\x06 \x01(\t"_\n\x1a\x43reateWorkflowRuleResponse\x12\x31\n\x04rule\x18\x01 \x01(\x0b\x32#.temporal.api.rules.v1.WorkflowRule\x12\x0e\n\x06job_id\x18\x02 \x01(\t"A\n\x1b\x44\x65scribeWorkflowRuleRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x0f\n\x07rule_id\x18\x02 \x01(\t"Q\n\x1c\x44\x65scribeWorkflowRuleResponse\x12\x31\n\x04rule\x18\x01 \x01(\x0b\x32#.temporal.api.rules.v1.WorkflowRule"?\n\x19\x44\x65leteWorkflowRuleRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x0f\n\x07rule_id\x18\x02 \x01(\t"\x1c\n\x1a\x44\x65leteWorkflowRuleResponse"F\n\x18ListWorkflowRulesRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c"h\n\x19ListWorkflowRulesResponse\x12\x32\n\x05rules\x18\x01 \x03(\x0b\x32#.temporal.api.rules.v1.WorkflowRule\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c"\xce\x01\n\x1aTriggerWorkflowRuleRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12<\n\texecution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x0c\n\x02id\x18\x04 \x01(\tH\x00\x12\x37\n\x04spec\x18\x05 \x01(\x0b\x32\'.temporal.api.rules.v1.WorkflowRuleSpecH\x00\x12\x10\n\x08identity\x18\x03 \x01(\tB\x06\n\x04rule".\n\x1bTriggerWorkflowRuleResponse\x12\x0f\n\x07\x61pplied\x18\x01 \x01(\x08"\x9b\x01\n\x1cRecordWorkerHeartbeatRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x10\n\x08identity\x18\x02 \x01(\t\x12\x41\n\x10worker_heartbeat\x18\x03 \x03(\x0b\x32\'.temporal.api.worker.v1.WorkerHeartbeat\x12\x13\n\x0bresource_id\x18\x04 \x01(\t"\x1f\n\x1dRecordWorkerHeartbeatResponse"b\n\x12ListWorkersRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x11\n\tpage_size\x18\x02 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c\x12\r\n\x05query\x18\x04 \x01(\t"\xa5\x01\n\x13ListWorkersResponse\x12<\n\x0cworkers_info\x18\x01 \x03(\x0b\x32".temporal.api.worker.v1.WorkerInfoB\x02\x18\x01\x12\x37\n\x07workers\x18\x03 \x03(\x0b\x32&.temporal.api.worker.v1.WorkerListInfo\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c"\xd5\x05\n\x1cUpdateTaskQueueConfigRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x10\n\x08identity\x18\x02 \x01(\t\x12\x12\n\ntask_queue\x18\x03 \x01(\t\x12=\n\x0ftask_queue_type\x18\x04 \x01(\x0e\x32$.temporal.api.enums.v1.TaskQueueType\x12n\n\x17update_queue_rate_limit\x18\x05 \x01(\x0b\x32M.temporal.api.workflowservice.v1.UpdateTaskQueueConfigRequest.RateLimitUpdate\x12}\n&update_fairness_key_rate_limit_default\x18\x06 \x01(\x0b\x32M.temporal.api.workflowservice.v1.UpdateTaskQueueConfigRequest.RateLimitUpdate\x12\x84\x01\n\x1dset_fairness_weight_overrides\x18\x07 \x03(\x0b\x32].temporal.api.workflowservice.v1.UpdateTaskQueueConfigRequest.SetFairnessWeightOverridesEntry\x12\'\n\x1funset_fairness_weight_overrides\x18\x08 \x03(\t\x1a[\n\x0fRateLimitUpdate\x12\x38\n\nrate_limit\x18\x01 \x01(\x0b\x32$.temporal.api.taskqueue.v1.RateLimit\x12\x0e\n\x06reason\x18\x02 \x01(\t\x1a\x41\n\x1fSetFairnessWeightOverridesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\x02:\x02\x38\x01"[\n\x1dUpdateTaskQueueConfigResponse\x12:\n\x06\x63onfig\x18\x01 \x01(\x0b\x32*.temporal.api.taskqueue.v1.TaskQueueConfig"\x9e\x01\n\x18\x46\x65tchWorkerConfigRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x10\n\x08identity\x18\x02 \x01(\t\x12\x0e\n\x06reason\x18\x03 \x01(\t\x12\x38\n\x08selector\x18\x06 \x01(\x0b\x32&.temporal.api.common.v1.WorkerSelector\x12\x13\n\x0bresource_id\x18\x07 \x01(\t"U\n\x19\x46\x65tchWorkerConfigResponse\x12\x38\n\rworker_config\x18\x01 \x01(\x0b\x32!.temporal.api.sdk.v1.WorkerConfig"\x8a\x02\n\x19UpdateWorkerConfigRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x10\n\x08identity\x18\x02 \x01(\t\x12\x0e\n\x06reason\x18\x03 \x01(\t\x12\x38\n\rworker_config\x18\x04 \x01(\x0b\x32!.temporal.api.sdk.v1.WorkerConfig\x12/\n\x0bupdate_mask\x18\x05 \x01(\x0b\x32\x1a.google.protobuf.FieldMask\x12\x38\n\x08selector\x18\x06 \x01(\x0b\x32&.temporal.api.common.v1.WorkerSelector\x12\x13\n\x0bresource_id\x18\x07 \x01(\t"d\n\x1aUpdateWorkerConfigResponse\x12:\n\rworker_config\x18\x01 \x01(\x0b\x32!.temporal.api.sdk.v1.WorkerConfigH\x00\x42\n\n\x08response"G\n\x15\x44\x65scribeWorkerRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x1b\n\x13worker_instance_key\x18\x02 \x01(\t"Q\n\x16\x44\x65scribeWorkerResponse\x12\x37\n\x0bworker_info\x18\x01 \x01(\x0b\x32".temporal.api.worker.v1.WorkerInfo"\x8d\x01\n\x1dPauseWorkflowExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x12\x10\n\x08identity\x18\x04 \x01(\t\x12\x0e\n\x06reason\x18\x05 \x01(\t\x12\x12\n\nrequest_id\x18\x06 \x01(\t" \n\x1ePauseWorkflowExecutionResponse"\x8f\x01\n\x1fUnpauseWorkflowExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x12\x10\n\x08identity\x18\x04 \x01(\t\x12\x0e\n\x06reason\x18\x05 \x01(\t\x12\x12\n\nrequest_id\x18\x06 \x01(\t""\n UnpauseWorkflowExecutionResponse"\x99\t\n\x1dStartActivityExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x10\n\x08identity\x18\x02 \x01(\t\x12\x12\n\nrequest_id\x18\x03 \x01(\t\x12\x13\n\x0b\x61\x63tivity_id\x18\x04 \x01(\t\x12;\n\ractivity_type\x18\x05 \x01(\x0b\x32$.temporal.api.common.v1.ActivityType\x12\x38\n\ntask_queue\x18\x06 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12<\n\x19schedule_to_close_timeout\x18\x07 \x01(\x0b\x32\x19.google.protobuf.Duration\x12<\n\x19schedule_to_start_timeout\x18\x08 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x39\n\x16start_to_close_timeout\x18\t \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x34\n\x11heartbeat_timeout\x18\n \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x39\n\x0cretry_policy\x18\x0b \x01(\x0b\x32#.temporal.api.common.v1.RetryPolicy\x12/\n\x05input\x18\x0c \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x45\n\x0fid_reuse_policy\x18\r \x01(\x0e\x32,.temporal.api.enums.v1.ActivityIdReusePolicy\x12K\n\x12id_conflict_policy\x18\x0e \x01(\x0e\x32/.temporal.api.enums.v1.ActivityIdConflictPolicy\x12\x43\n\x11search_attributes\x18\x0f \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes\x12.\n\x06header\x18\x10 \x01(\x0b\x32\x1e.temporal.api.common.v1.Header\x12\x38\n\ruser_metadata\x18\x11 \x01(\x0b\x32!.temporal.api.sdk.v1.UserMetadata\x12\x32\n\x08priority\x18\x12 \x01(\x0b\x32 .temporal.api.common.v1.Priority\x12>\n\x14\x63ompletion_callbacks\x18\x13 \x03(\x0b\x32 .temporal.api.common.v1.Callback\x12+\n\x05links\x18\x14 \x03(\x0b\x32\x1c.temporal.api.common.v1.Link\x12\x46\n\x13on_conflict_options\x18\x15 \x01(\x0b\x32).temporal.api.common.v1.OnConflictOptions\x12.\n\x0bstart_delay\x18\x16 \x01(\x0b\x32\x19.google.protobuf.Duration"m\n\x1eStartActivityExecutionResponse\x12\x0e\n\x06run_id\x18\x01 \x01(\t\x12\x0f\n\x07started\x18\x02 \x01(\x08\x12*\n\x04link\x18\x03 \x01(\x0b\x32\x1c.temporal.api.common.v1.Link"\xa3\x01\n DescribeActivityExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0b\x61\x63tivity_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x12\x15\n\rinclude_input\x18\x04 \x01(\x08\x12\x17\n\x0finclude_outcome\x18\x05 \x01(\x08\x12\x17\n\x0flong_poll_token\x18\x06 \x01(\x0c"\xbc\x02\n!DescribeActivityExecutionResponse\x12\x0e\n\x06run_id\x18\x01 \x01(\t\x12=\n\x04info\x18\x02 \x01(\x0b\x32/.temporal.api.activity.v1.ActivityExecutionInfo\x12/\n\x05input\x18\x03 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x43\n\x07outcome\x18\x04 \x01(\x0b\x32\x32.temporal.api.activity.v1.ActivityExecutionOutcome\x12\x17\n\x0flong_poll_token\x18\x05 \x01(\x0c\x12\x39\n\tcallbacks\x18\x06 \x03(\x0b\x32&.temporal.api.activity.v1.CallbackInfo"V\n\x1cPollActivityExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0b\x61\x63tivity_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t"t\n\x1dPollActivityExecutionResponse\x12\x0e\n\x06run_id\x18\x01 \x01(\t\x12\x43\n\x07outcome\x18\x02 \x01(\x0b\x32\x32.temporal.api.activity.v1.ActivityExecutionOutcome"m\n\x1dListActivityExecutionsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x11\n\tpage_size\x18\x02 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c\x12\r\n\x05query\x18\x04 \x01(\t"\x82\x01\n\x1eListActivityExecutionsResponse\x12G\n\nexecutions\x18\x01 \x03(\x0b\x32\x33.temporal.api.activity.v1.ActivityExecutionListInfo\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c"\xd1\x06\n#StartNexusOperationExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x10\n\x08identity\x18\x02 \x01(\t\x12\x12\n\nrequest_id\x18\x03 \x01(\t\x12\x14\n\x0coperation_id\x18\x04 \x01(\t\x12\x10\n\x08\x65ndpoint\x18\x05 \x01(\t\x12\x0f\n\x07service\x18\x06 \x01(\t\x12\x11\n\toperation\x18\x07 \x01(\t\x12<\n\x19schedule_to_close_timeout\x18\x08 \x01(\x0b\x32\x19.google.protobuf.Duration\x12<\n\x19schedule_to_start_timeout\x18\t \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x39\n\x16start_to_close_timeout\x18\n \x01(\x0b\x32\x19.google.protobuf.Duration\x12.\n\x05input\x18\x0b \x01(\x0b\x32\x1f.temporal.api.common.v1.Payload\x12K\n\x0fid_reuse_policy\x18\x0c \x01(\x0e\x32\x32.temporal.api.enums.v1.NexusOperationIdReusePolicy\x12Q\n\x12id_conflict_policy\x18\r \x01(\x0e\x32\x35.temporal.api.enums.v1.NexusOperationIdConflictPolicy\x12\x43\n\x11search_attributes\x18\x0e \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes\x12k\n\x0cnexus_header\x18\x0f \x03(\x0b\x32U.temporal.api.workflowservice.v1.StartNexusOperationExecutionRequest.NexusHeaderEntry\x12\x38\n\ruser_metadata\x18\x10 \x01(\x0b\x32!.temporal.api.sdk.v1.UserMetadata\x1a\x32\n\x10NexusHeaderEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01"G\n$StartNexusOperationExecutionResponse\x12\x0e\n\x06run_id\x18\x01 \x01(\t\x12\x0f\n\x07started\x18\x02 \x01(\x08"\xaa\x01\n&DescribeNexusOperationExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x14\n\x0coperation_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x12\x15\n\rinclude_input\x18\x04 \x01(\x08\x12\x17\n\x0finclude_outcome\x18\x05 \x01(\x08\x12\x17\n\x0flong_poll_token\x18\x06 \x01(\x0c"\xb7\x02\n\'DescribeNexusOperationExecutionResponse\x12\x0e\n\x06run_id\x18\x01 \x01(\t\x12@\n\x04info\x18\x02 \x01(\x0b\x32\x32.temporal.api.nexus.v1.NexusOperationExecutionInfo\x12.\n\x05input\x18\x03 \x01(\x0b\x32\x1f.temporal.api.common.v1.Payload\x12\x31\n\x06result\x18\x04 \x01(\x0b\x32\x1f.temporal.api.common.v1.PayloadH\x00\x12\x33\n\x07\x66\x61ilure\x18\x05 \x01(\x0b\x32 .temporal.api.failure.v1.FailureH\x00\x12\x17\n\x0flong_poll_token\x18\x06 \x01(\x0c\x42\t\n\x07outcome"\xa1\x01\n"PollNexusOperationExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x14\n\x0coperation_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x12\x42\n\nwait_stage\x18\x04 \x01(\x0e\x32..temporal.api.enums.v1.NexusOperationWaitStage"\x85\x02\n#PollNexusOperationExecutionResponse\x12\x0e\n\x06run_id\x18\x01 \x01(\t\x12\x42\n\nwait_stage\x18\x02 \x01(\x0e\x32..temporal.api.enums.v1.NexusOperationWaitStage\x12\x17\n\x0foperation_token\x18\x03 \x01(\t\x12\x31\n\x06result\x18\x04 \x01(\x0b\x32\x1f.temporal.api.common.v1.PayloadH\x00\x12\x33\n\x07\x66\x61ilure\x18\x05 \x01(\x0b\x32 .temporal.api.failure.v1.FailureH\x00\x42\t\n\x07outcome"s\n#ListNexusOperationExecutionsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x11\n\tpage_size\x18\x02 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c\x12\r\n\x05query\x18\x04 \x01(\t"\x8b\x01\n$ListNexusOperationExecutionsResponse\x12J\n\noperations\x18\x01 \x03(\x0b\x32\x36.temporal.api.nexus.v1.NexusOperationExecutionListInfo\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c"B\n\x1e\x43ountActivityExecutionsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\r\n\x05query\x18\x02 \x01(\t"\xed\x01\n\x1f\x43ountActivityExecutionsResponse\x12\r\n\x05\x63ount\x18\x01 \x01(\x03\x12\x61\n\x06groups\x18\x02 \x03(\x0b\x32Q.temporal.api.workflowservice.v1.CountActivityExecutionsResponse.AggregationGroup\x1aX\n\x10\x41ggregationGroup\x12\x35\n\x0cgroup_values\x18\x01 \x03(\x0b\x32\x1f.temporal.api.common.v1.Payload\x12\r\n\x05\x63ount\x18\x02 \x01(\x03"H\n$CountNexusOperationExecutionsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\r\n\x05query\x18\x02 \x01(\t"\xf9\x01\n%CountNexusOperationExecutionsResponse\x12\r\n\x05\x63ount\x18\x01 \x01(\x03\x12g\n\x06groups\x18\x02 \x03(\x0b\x32W.temporal.api.workflowservice.v1.CountNexusOperationExecutionsResponse.AggregationGroup\x1aX\n\x10\x41ggregationGroup\x12\x35\n\x0cgroup_values\x18\x01 \x03(\x0b\x32\x1f.temporal.api.common.v1.Payload\x12\r\n\x05\x63ount\x18\x02 \x01(\x03"\x95\x01\n%RequestCancelActivityExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0b\x61\x63tivity_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x12\x10\n\x08identity\x18\x04 \x01(\t\x12\x12\n\nrequest_id\x18\x05 \x01(\t\x12\x0e\n\x06reason\x18\x06 \x01(\t"(\n&RequestCancelActivityExecutionResponse"\x91\x01\n!TerminateActivityExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0b\x61\x63tivity_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x12\x10\n\x08identity\x18\x04 \x01(\t\x12\x12\n\nrequest_id\x18\x05 \x01(\t\x12\x0e\n\x06reason\x18\x06 \x01(\t"$\n"TerminateActivityExecutionResponse"X\n\x1e\x44\x65leteActivityExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0b\x61\x63tivity_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t"!\n\x1f\x44\x65leteActivityExecutionResponse"\x9c\x01\n+RequestCancelNexusOperationExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x14\n\x0coperation_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x12\x10\n\x08identity\x18\x04 \x01(\t\x12\x12\n\nrequest_id\x18\x05 \x01(\t\x12\x0e\n\x06reason\x18\x06 \x01(\t".\n,RequestCancelNexusOperationExecutionResponse"\x98\x01\n\'TerminateNexusOperationExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x14\n\x0coperation_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x12\x10\n\x08identity\x18\x04 \x01(\t\x12\x12\n\nrequest_id\x18\x05 \x01(\t\x12\x0e\n\x06reason\x18\x06 \x01(\t"*\n(TerminateNexusOperationExecutionResponse"_\n$DeleteNexusOperationExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x14\n\x0coperation_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t"\'\n%DeleteNexusOperationExecutionResponseB\xbe\x01\n"io.temporal.api.workflowservice.v1B\x14RequestResponseProtoP\x01Z5go.temporal.io/api/workflowservice/v1;workflowservice\xaa\x02!Temporalio.Api.WorkflowService.V1\xea\x02$Temporalio::Api::WorkflowService::V1b\x06proto3' ) @@ -605,6 +611,12 @@ _SETWORKERDEPLOYMENTRAMPINGVERSIONRESPONSE = DESCRIPTOR.message_types_by_name[ "SetWorkerDeploymentRampingVersionResponse" ] +_CREATEWORKERDEPLOYMENTREQUEST = DESCRIPTOR.message_types_by_name[ + "CreateWorkerDeploymentRequest" +] +_CREATEWORKERDEPLOYMENTRESPONSE = DESCRIPTOR.message_types_by_name[ + "CreateWorkerDeploymentResponse" +] _LISTWORKERDEPLOYMENTSREQUEST = DESCRIPTOR.message_types_by_name[ "ListWorkerDeploymentsRequest" ] @@ -614,6 +626,12 @@ _LISTWORKERDEPLOYMENTSRESPONSE_WORKERDEPLOYMENTSUMMARY = ( _LISTWORKERDEPLOYMENTSRESPONSE.nested_types_by_name["WorkerDeploymentSummary"] ) +_CREATEWORKERDEPLOYMENTVERSIONREQUEST = DESCRIPTOR.message_types_by_name[ + "CreateWorkerDeploymentVersionRequest" +] +_CREATEWORKERDEPLOYMENTVERSIONRESPONSE = DESCRIPTOR.message_types_by_name[ + "CreateWorkerDeploymentVersionResponse" +] _DELETEWORKERDEPLOYMENTVERSIONREQUEST = DESCRIPTOR.message_types_by_name[ "DeleteWorkerDeploymentVersionRequest" ] @@ -626,6 +644,30 @@ _DELETEWORKERDEPLOYMENTRESPONSE = DESCRIPTOR.message_types_by_name[ "DeleteWorkerDeploymentResponse" ] +_UPDATEWORKERDEPLOYMENTVERSIONCOMPUTECONFIGREQUEST = DESCRIPTOR.message_types_by_name[ + "UpdateWorkerDeploymentVersionComputeConfigRequest" +] +_UPDATEWORKERDEPLOYMENTVERSIONCOMPUTECONFIGREQUEST_COMPUTECONFIGSCALINGGROUPSENTRY = ( + _UPDATEWORKERDEPLOYMENTVERSIONCOMPUTECONFIGREQUEST.nested_types_by_name[ + "ComputeConfigScalingGroupsEntry" + ] +) +_UPDATEWORKERDEPLOYMENTVERSIONCOMPUTECONFIGRESPONSE = DESCRIPTOR.message_types_by_name[ + "UpdateWorkerDeploymentVersionComputeConfigResponse" +] +_VALIDATEWORKERDEPLOYMENTVERSIONCOMPUTECONFIGREQUEST = DESCRIPTOR.message_types_by_name[ + "ValidateWorkerDeploymentVersionComputeConfigRequest" +] +_VALIDATEWORKERDEPLOYMENTVERSIONCOMPUTECONFIGREQUEST_COMPUTECONFIGSCALINGGROUPSENTRY = ( + _VALIDATEWORKERDEPLOYMENTVERSIONCOMPUTECONFIGREQUEST.nested_types_by_name[ + "ComputeConfigScalingGroupsEntry" + ] +) +_VALIDATEWORKERDEPLOYMENTVERSIONCOMPUTECONFIGRESPONSE = ( + DESCRIPTOR.message_types_by_name[ + "ValidateWorkerDeploymentVersionComputeConfigResponse" + ] +) _UPDATEWORKERDEPLOYMENTVERSIONMETADATAREQUEST = DESCRIPTOR.message_types_by_name[ "UpdateWorkerDeploymentVersionMetadataRequest" ] @@ -753,6 +795,33 @@ _LISTACTIVITYEXECUTIONSRESPONSE = DESCRIPTOR.message_types_by_name[ "ListActivityExecutionsResponse" ] +_STARTNEXUSOPERATIONEXECUTIONREQUEST = DESCRIPTOR.message_types_by_name[ + "StartNexusOperationExecutionRequest" +] +_STARTNEXUSOPERATIONEXECUTIONREQUEST_NEXUSHEADERENTRY = ( + _STARTNEXUSOPERATIONEXECUTIONREQUEST.nested_types_by_name["NexusHeaderEntry"] +) +_STARTNEXUSOPERATIONEXECUTIONRESPONSE = DESCRIPTOR.message_types_by_name[ + "StartNexusOperationExecutionResponse" +] +_DESCRIBENEXUSOPERATIONEXECUTIONREQUEST = DESCRIPTOR.message_types_by_name[ + "DescribeNexusOperationExecutionRequest" +] +_DESCRIBENEXUSOPERATIONEXECUTIONRESPONSE = DESCRIPTOR.message_types_by_name[ + "DescribeNexusOperationExecutionResponse" +] +_POLLNEXUSOPERATIONEXECUTIONREQUEST = DESCRIPTOR.message_types_by_name[ + "PollNexusOperationExecutionRequest" +] +_POLLNEXUSOPERATIONEXECUTIONRESPONSE = DESCRIPTOR.message_types_by_name[ + "PollNexusOperationExecutionResponse" +] +_LISTNEXUSOPERATIONEXECUTIONSREQUEST = DESCRIPTOR.message_types_by_name[ + "ListNexusOperationExecutionsRequest" +] +_LISTNEXUSOPERATIONEXECUTIONSRESPONSE = DESCRIPTOR.message_types_by_name[ + "ListNexusOperationExecutionsResponse" +] _COUNTACTIVITYEXECUTIONSREQUEST = DESCRIPTOR.message_types_by_name[ "CountActivityExecutionsRequest" ] @@ -762,6 +831,15 @@ _COUNTACTIVITYEXECUTIONSRESPONSE_AGGREGATIONGROUP = ( _COUNTACTIVITYEXECUTIONSRESPONSE.nested_types_by_name["AggregationGroup"] ) +_COUNTNEXUSOPERATIONEXECUTIONSREQUEST = DESCRIPTOR.message_types_by_name[ + "CountNexusOperationExecutionsRequest" +] +_COUNTNEXUSOPERATIONEXECUTIONSRESPONSE = DESCRIPTOR.message_types_by_name[ + "CountNexusOperationExecutionsResponse" +] +_COUNTNEXUSOPERATIONEXECUTIONSRESPONSE_AGGREGATIONGROUP = ( + _COUNTNEXUSOPERATIONEXECUTIONSRESPONSE.nested_types_by_name["AggregationGroup"] +) _REQUESTCANCELACTIVITYEXECUTIONREQUEST = DESCRIPTOR.message_types_by_name[ "RequestCancelActivityExecutionRequest" ] @@ -780,6 +858,24 @@ _DELETEACTIVITYEXECUTIONRESPONSE = DESCRIPTOR.message_types_by_name[ "DeleteActivityExecutionResponse" ] +_REQUESTCANCELNEXUSOPERATIONEXECUTIONREQUEST = DESCRIPTOR.message_types_by_name[ + "RequestCancelNexusOperationExecutionRequest" +] +_REQUESTCANCELNEXUSOPERATIONEXECUTIONRESPONSE = DESCRIPTOR.message_types_by_name[ + "RequestCancelNexusOperationExecutionResponse" +] +_TERMINATENEXUSOPERATIONEXECUTIONREQUEST = DESCRIPTOR.message_types_by_name[ + "TerminateNexusOperationExecutionRequest" +] +_TERMINATENEXUSOPERATIONEXECUTIONRESPONSE = DESCRIPTOR.message_types_by_name[ + "TerminateNexusOperationExecutionResponse" +] +_DELETENEXUSOPERATIONEXECUTIONREQUEST = DESCRIPTOR.message_types_by_name[ + "DeleteNexusOperationExecutionRequest" +] +_DELETENEXUSOPERATIONEXECUTIONRESPONSE = DESCRIPTOR.message_types_by_name[ + "DeleteNexusOperationExecutionResponse" +] RegisterNamespaceRequest = _reflection.GeneratedProtocolMessageType( "RegisterNamespaceRequest", (_message.Message,), @@ -2732,6 +2828,28 @@ ) _sym_db.RegisterMessage(SetWorkerDeploymentRampingVersionResponse) +CreateWorkerDeploymentRequest = _reflection.GeneratedProtocolMessageType( + "CreateWorkerDeploymentRequest", + (_message.Message,), + { + "DESCRIPTOR": _CREATEWORKERDEPLOYMENTREQUEST, + "__module__": "temporalio.api.workflowservice.v1.request_response_pb2", + # @@protoc_insertion_point(class_scope:temporal.api.workflowservice.v1.CreateWorkerDeploymentRequest) + }, +) +_sym_db.RegisterMessage(CreateWorkerDeploymentRequest) + +CreateWorkerDeploymentResponse = _reflection.GeneratedProtocolMessageType( + "CreateWorkerDeploymentResponse", + (_message.Message,), + { + "DESCRIPTOR": _CREATEWORKERDEPLOYMENTRESPONSE, + "__module__": "temporalio.api.workflowservice.v1.request_response_pb2", + # @@protoc_insertion_point(class_scope:temporal.api.workflowservice.v1.CreateWorkerDeploymentResponse) + }, +) +_sym_db.RegisterMessage(CreateWorkerDeploymentResponse) + ListWorkerDeploymentsRequest = _reflection.GeneratedProtocolMessageType( "ListWorkerDeploymentsRequest", (_message.Message,), @@ -2764,6 +2882,28 @@ _sym_db.RegisterMessage(ListWorkerDeploymentsResponse) _sym_db.RegisterMessage(ListWorkerDeploymentsResponse.WorkerDeploymentSummary) +CreateWorkerDeploymentVersionRequest = _reflection.GeneratedProtocolMessageType( + "CreateWorkerDeploymentVersionRequest", + (_message.Message,), + { + "DESCRIPTOR": _CREATEWORKERDEPLOYMENTVERSIONREQUEST, + "__module__": "temporalio.api.workflowservice.v1.request_response_pb2", + # @@protoc_insertion_point(class_scope:temporal.api.workflowservice.v1.CreateWorkerDeploymentVersionRequest) + }, +) +_sym_db.RegisterMessage(CreateWorkerDeploymentVersionRequest) + +CreateWorkerDeploymentVersionResponse = _reflection.GeneratedProtocolMessageType( + "CreateWorkerDeploymentVersionResponse", + (_message.Message,), + { + "DESCRIPTOR": _CREATEWORKERDEPLOYMENTVERSIONRESPONSE, + "__module__": "temporalio.api.workflowservice.v1.request_response_pb2", + # @@protoc_insertion_point(class_scope:temporal.api.workflowservice.v1.CreateWorkerDeploymentVersionResponse) + }, +) +_sym_db.RegisterMessage(CreateWorkerDeploymentVersionResponse) + DeleteWorkerDeploymentVersionRequest = _reflection.GeneratedProtocolMessageType( "DeleteWorkerDeploymentVersionRequest", (_message.Message,), @@ -2808,6 +2948,78 @@ ) _sym_db.RegisterMessage(DeleteWorkerDeploymentResponse) +UpdateWorkerDeploymentVersionComputeConfigRequest = _reflection.GeneratedProtocolMessageType( + "UpdateWorkerDeploymentVersionComputeConfigRequest", + (_message.Message,), + { + "ComputeConfigScalingGroupsEntry": _reflection.GeneratedProtocolMessageType( + "ComputeConfigScalingGroupsEntry", + (_message.Message,), + { + "DESCRIPTOR": _UPDATEWORKERDEPLOYMENTVERSIONCOMPUTECONFIGREQUEST_COMPUTECONFIGSCALINGGROUPSENTRY, + "__module__": "temporalio.api.workflowservice.v1.request_response_pb2", + # @@protoc_insertion_point(class_scope:temporal.api.workflowservice.v1.UpdateWorkerDeploymentVersionComputeConfigRequest.ComputeConfigScalingGroupsEntry) + }, + ), + "DESCRIPTOR": _UPDATEWORKERDEPLOYMENTVERSIONCOMPUTECONFIGREQUEST, + "__module__": "temporalio.api.workflowservice.v1.request_response_pb2", + # @@protoc_insertion_point(class_scope:temporal.api.workflowservice.v1.UpdateWorkerDeploymentVersionComputeConfigRequest) + }, +) +_sym_db.RegisterMessage(UpdateWorkerDeploymentVersionComputeConfigRequest) +_sym_db.RegisterMessage( + UpdateWorkerDeploymentVersionComputeConfigRequest.ComputeConfigScalingGroupsEntry +) + +UpdateWorkerDeploymentVersionComputeConfigResponse = ( + _reflection.GeneratedProtocolMessageType( + "UpdateWorkerDeploymentVersionComputeConfigResponse", + (_message.Message,), + { + "DESCRIPTOR": _UPDATEWORKERDEPLOYMENTVERSIONCOMPUTECONFIGRESPONSE, + "__module__": "temporalio.api.workflowservice.v1.request_response_pb2", + # @@protoc_insertion_point(class_scope:temporal.api.workflowservice.v1.UpdateWorkerDeploymentVersionComputeConfigResponse) + }, + ) +) +_sym_db.RegisterMessage(UpdateWorkerDeploymentVersionComputeConfigResponse) + +ValidateWorkerDeploymentVersionComputeConfigRequest = _reflection.GeneratedProtocolMessageType( + "ValidateWorkerDeploymentVersionComputeConfigRequest", + (_message.Message,), + { + "ComputeConfigScalingGroupsEntry": _reflection.GeneratedProtocolMessageType( + "ComputeConfigScalingGroupsEntry", + (_message.Message,), + { + "DESCRIPTOR": _VALIDATEWORKERDEPLOYMENTVERSIONCOMPUTECONFIGREQUEST_COMPUTECONFIGSCALINGGROUPSENTRY, + "__module__": "temporalio.api.workflowservice.v1.request_response_pb2", + # @@protoc_insertion_point(class_scope:temporal.api.workflowservice.v1.ValidateWorkerDeploymentVersionComputeConfigRequest.ComputeConfigScalingGroupsEntry) + }, + ), + "DESCRIPTOR": _VALIDATEWORKERDEPLOYMENTVERSIONCOMPUTECONFIGREQUEST, + "__module__": "temporalio.api.workflowservice.v1.request_response_pb2", + # @@protoc_insertion_point(class_scope:temporal.api.workflowservice.v1.ValidateWorkerDeploymentVersionComputeConfigRequest) + }, +) +_sym_db.RegisterMessage(ValidateWorkerDeploymentVersionComputeConfigRequest) +_sym_db.RegisterMessage( + ValidateWorkerDeploymentVersionComputeConfigRequest.ComputeConfigScalingGroupsEntry +) + +ValidateWorkerDeploymentVersionComputeConfigResponse = ( + _reflection.GeneratedProtocolMessageType( + "ValidateWorkerDeploymentVersionComputeConfigResponse", + (_message.Message,), + { + "DESCRIPTOR": _VALIDATEWORKERDEPLOYMENTVERSIONCOMPUTECONFIGRESPONSE, + "__module__": "temporalio.api.workflowservice.v1.request_response_pb2", + # @@protoc_insertion_point(class_scope:temporal.api.workflowservice.v1.ValidateWorkerDeploymentVersionComputeConfigResponse) + }, + ) +) +_sym_db.RegisterMessage(ValidateWorkerDeploymentVersionComputeConfigResponse) + UpdateWorkerDeploymentVersionMetadataRequest = _reflection.GeneratedProtocolMessageType( "UpdateWorkerDeploymentVersionMetadataRequest", (_message.Message,), @@ -3302,6 +3514,104 @@ ) _sym_db.RegisterMessage(ListActivityExecutionsResponse) +StartNexusOperationExecutionRequest = _reflection.GeneratedProtocolMessageType( + "StartNexusOperationExecutionRequest", + (_message.Message,), + { + "NexusHeaderEntry": _reflection.GeneratedProtocolMessageType( + "NexusHeaderEntry", + (_message.Message,), + { + "DESCRIPTOR": _STARTNEXUSOPERATIONEXECUTIONREQUEST_NEXUSHEADERENTRY, + "__module__": "temporalio.api.workflowservice.v1.request_response_pb2", + # @@protoc_insertion_point(class_scope:temporal.api.workflowservice.v1.StartNexusOperationExecutionRequest.NexusHeaderEntry) + }, + ), + "DESCRIPTOR": _STARTNEXUSOPERATIONEXECUTIONREQUEST, + "__module__": "temporalio.api.workflowservice.v1.request_response_pb2", + # @@protoc_insertion_point(class_scope:temporal.api.workflowservice.v1.StartNexusOperationExecutionRequest) + }, +) +_sym_db.RegisterMessage(StartNexusOperationExecutionRequest) +_sym_db.RegisterMessage(StartNexusOperationExecutionRequest.NexusHeaderEntry) + +StartNexusOperationExecutionResponse = _reflection.GeneratedProtocolMessageType( + "StartNexusOperationExecutionResponse", + (_message.Message,), + { + "DESCRIPTOR": _STARTNEXUSOPERATIONEXECUTIONRESPONSE, + "__module__": "temporalio.api.workflowservice.v1.request_response_pb2", + # @@protoc_insertion_point(class_scope:temporal.api.workflowservice.v1.StartNexusOperationExecutionResponse) + }, +) +_sym_db.RegisterMessage(StartNexusOperationExecutionResponse) + +DescribeNexusOperationExecutionRequest = _reflection.GeneratedProtocolMessageType( + "DescribeNexusOperationExecutionRequest", + (_message.Message,), + { + "DESCRIPTOR": _DESCRIBENEXUSOPERATIONEXECUTIONREQUEST, + "__module__": "temporalio.api.workflowservice.v1.request_response_pb2", + # @@protoc_insertion_point(class_scope:temporal.api.workflowservice.v1.DescribeNexusOperationExecutionRequest) + }, +) +_sym_db.RegisterMessage(DescribeNexusOperationExecutionRequest) + +DescribeNexusOperationExecutionResponse = _reflection.GeneratedProtocolMessageType( + "DescribeNexusOperationExecutionResponse", + (_message.Message,), + { + "DESCRIPTOR": _DESCRIBENEXUSOPERATIONEXECUTIONRESPONSE, + "__module__": "temporalio.api.workflowservice.v1.request_response_pb2", + # @@protoc_insertion_point(class_scope:temporal.api.workflowservice.v1.DescribeNexusOperationExecutionResponse) + }, +) +_sym_db.RegisterMessage(DescribeNexusOperationExecutionResponse) + +PollNexusOperationExecutionRequest = _reflection.GeneratedProtocolMessageType( + "PollNexusOperationExecutionRequest", + (_message.Message,), + { + "DESCRIPTOR": _POLLNEXUSOPERATIONEXECUTIONREQUEST, + "__module__": "temporalio.api.workflowservice.v1.request_response_pb2", + # @@protoc_insertion_point(class_scope:temporal.api.workflowservice.v1.PollNexusOperationExecutionRequest) + }, +) +_sym_db.RegisterMessage(PollNexusOperationExecutionRequest) + +PollNexusOperationExecutionResponse = _reflection.GeneratedProtocolMessageType( + "PollNexusOperationExecutionResponse", + (_message.Message,), + { + "DESCRIPTOR": _POLLNEXUSOPERATIONEXECUTIONRESPONSE, + "__module__": "temporalio.api.workflowservice.v1.request_response_pb2", + # @@protoc_insertion_point(class_scope:temporal.api.workflowservice.v1.PollNexusOperationExecutionResponse) + }, +) +_sym_db.RegisterMessage(PollNexusOperationExecutionResponse) + +ListNexusOperationExecutionsRequest = _reflection.GeneratedProtocolMessageType( + "ListNexusOperationExecutionsRequest", + (_message.Message,), + { + "DESCRIPTOR": _LISTNEXUSOPERATIONEXECUTIONSREQUEST, + "__module__": "temporalio.api.workflowservice.v1.request_response_pb2", + # @@protoc_insertion_point(class_scope:temporal.api.workflowservice.v1.ListNexusOperationExecutionsRequest) + }, +) +_sym_db.RegisterMessage(ListNexusOperationExecutionsRequest) + +ListNexusOperationExecutionsResponse = _reflection.GeneratedProtocolMessageType( + "ListNexusOperationExecutionsResponse", + (_message.Message,), + { + "DESCRIPTOR": _LISTNEXUSOPERATIONEXECUTIONSRESPONSE, + "__module__": "temporalio.api.workflowservice.v1.request_response_pb2", + # @@protoc_insertion_point(class_scope:temporal.api.workflowservice.v1.ListNexusOperationExecutionsResponse) + }, +) +_sym_db.RegisterMessage(ListNexusOperationExecutionsResponse) + CountActivityExecutionsRequest = _reflection.GeneratedProtocolMessageType( "CountActivityExecutionsRequest", (_message.Message,), @@ -3334,6 +3644,38 @@ _sym_db.RegisterMessage(CountActivityExecutionsResponse) _sym_db.RegisterMessage(CountActivityExecutionsResponse.AggregationGroup) +CountNexusOperationExecutionsRequest = _reflection.GeneratedProtocolMessageType( + "CountNexusOperationExecutionsRequest", + (_message.Message,), + { + "DESCRIPTOR": _COUNTNEXUSOPERATIONEXECUTIONSREQUEST, + "__module__": "temporalio.api.workflowservice.v1.request_response_pb2", + # @@protoc_insertion_point(class_scope:temporal.api.workflowservice.v1.CountNexusOperationExecutionsRequest) + }, +) +_sym_db.RegisterMessage(CountNexusOperationExecutionsRequest) + +CountNexusOperationExecutionsResponse = _reflection.GeneratedProtocolMessageType( + "CountNexusOperationExecutionsResponse", + (_message.Message,), + { + "AggregationGroup": _reflection.GeneratedProtocolMessageType( + "AggregationGroup", + (_message.Message,), + { + "DESCRIPTOR": _COUNTNEXUSOPERATIONEXECUTIONSRESPONSE_AGGREGATIONGROUP, + "__module__": "temporalio.api.workflowservice.v1.request_response_pb2", + # @@protoc_insertion_point(class_scope:temporal.api.workflowservice.v1.CountNexusOperationExecutionsResponse.AggregationGroup) + }, + ), + "DESCRIPTOR": _COUNTNEXUSOPERATIONEXECUTIONSRESPONSE, + "__module__": "temporalio.api.workflowservice.v1.request_response_pb2", + # @@protoc_insertion_point(class_scope:temporal.api.workflowservice.v1.CountNexusOperationExecutionsResponse) + }, +) +_sym_db.RegisterMessage(CountNexusOperationExecutionsResponse) +_sym_db.RegisterMessage(CountNexusOperationExecutionsResponse.AggregationGroup) + RequestCancelActivityExecutionRequest = _reflection.GeneratedProtocolMessageType( "RequestCancelActivityExecutionRequest", (_message.Message,), @@ -3400,6 +3742,72 @@ ) _sym_db.RegisterMessage(DeleteActivityExecutionResponse) +RequestCancelNexusOperationExecutionRequest = _reflection.GeneratedProtocolMessageType( + "RequestCancelNexusOperationExecutionRequest", + (_message.Message,), + { + "DESCRIPTOR": _REQUESTCANCELNEXUSOPERATIONEXECUTIONREQUEST, + "__module__": "temporalio.api.workflowservice.v1.request_response_pb2", + # @@protoc_insertion_point(class_scope:temporal.api.workflowservice.v1.RequestCancelNexusOperationExecutionRequest) + }, +) +_sym_db.RegisterMessage(RequestCancelNexusOperationExecutionRequest) + +RequestCancelNexusOperationExecutionResponse = _reflection.GeneratedProtocolMessageType( + "RequestCancelNexusOperationExecutionResponse", + (_message.Message,), + { + "DESCRIPTOR": _REQUESTCANCELNEXUSOPERATIONEXECUTIONRESPONSE, + "__module__": "temporalio.api.workflowservice.v1.request_response_pb2", + # @@protoc_insertion_point(class_scope:temporal.api.workflowservice.v1.RequestCancelNexusOperationExecutionResponse) + }, +) +_sym_db.RegisterMessage(RequestCancelNexusOperationExecutionResponse) + +TerminateNexusOperationExecutionRequest = _reflection.GeneratedProtocolMessageType( + "TerminateNexusOperationExecutionRequest", + (_message.Message,), + { + "DESCRIPTOR": _TERMINATENEXUSOPERATIONEXECUTIONREQUEST, + "__module__": "temporalio.api.workflowservice.v1.request_response_pb2", + # @@protoc_insertion_point(class_scope:temporal.api.workflowservice.v1.TerminateNexusOperationExecutionRequest) + }, +) +_sym_db.RegisterMessage(TerminateNexusOperationExecutionRequest) + +TerminateNexusOperationExecutionResponse = _reflection.GeneratedProtocolMessageType( + "TerminateNexusOperationExecutionResponse", + (_message.Message,), + { + "DESCRIPTOR": _TERMINATENEXUSOPERATIONEXECUTIONRESPONSE, + "__module__": "temporalio.api.workflowservice.v1.request_response_pb2", + # @@protoc_insertion_point(class_scope:temporal.api.workflowservice.v1.TerminateNexusOperationExecutionResponse) + }, +) +_sym_db.RegisterMessage(TerminateNexusOperationExecutionResponse) + +DeleteNexusOperationExecutionRequest = _reflection.GeneratedProtocolMessageType( + "DeleteNexusOperationExecutionRequest", + (_message.Message,), + { + "DESCRIPTOR": _DELETENEXUSOPERATIONEXECUTIONREQUEST, + "__module__": "temporalio.api.workflowservice.v1.request_response_pb2", + # @@protoc_insertion_point(class_scope:temporal.api.workflowservice.v1.DeleteNexusOperationExecutionRequest) + }, +) +_sym_db.RegisterMessage(DeleteNexusOperationExecutionRequest) + +DeleteNexusOperationExecutionResponse = _reflection.GeneratedProtocolMessageType( + "DeleteNexusOperationExecutionResponse", + (_message.Message,), + { + "DESCRIPTOR": _DELETENEXUSOPERATIONEXECUTIONRESPONSE, + "__module__": "temporalio.api.workflowservice.v1.request_response_pb2", + # @@protoc_insertion_point(class_scope:temporal.api.workflowservice.v1.DeleteNexusOperationExecutionResponse) + }, +) +_sym_db.RegisterMessage(DeleteNexusOperationExecutionResponse) + if _descriptor._USE_C_DESCRIPTORS == False: DESCRIPTOR._options = None DESCRIPTOR._serialized_options = b'\n"io.temporal.api.workflowservice.v1B\024RequestResponseProtoP\001Z5go.temporal.io/api/workflowservice/v1;workflowservice\252\002!Temporalio.Api.WorkflowService.V1\352\002$Temporalio::Api::WorkflowService::V1' @@ -3593,6 +4001,10 @@ _DELETEWORKERDEPLOYMENTVERSIONREQUEST.fields_by_name[ "version" ]._serialized_options = b"\030\001" + _UPDATEWORKERDEPLOYMENTVERSIONCOMPUTECONFIGREQUEST_COMPUTECONFIGSCALINGGROUPSENTRY._options = None + _UPDATEWORKERDEPLOYMENTVERSIONCOMPUTECONFIGREQUEST_COMPUTECONFIGSCALINGGROUPSENTRY._serialized_options = b"8\001" + _VALIDATEWORKERDEPLOYMENTVERSIONCOMPUTECONFIGREQUEST_COMPUTECONFIGSCALINGGROUPSENTRY._options = None + _VALIDATEWORKERDEPLOYMENTVERSIONCOMPUTECONFIGREQUEST_COMPUTECONFIGSCALINGGROUPSENTRY._serialized_options = b"8\001" _UPDATEWORKERDEPLOYMENTVERSIONMETADATAREQUEST_UPSERTENTRIESENTRY._options = None _UPDATEWORKERDEPLOYMENTVERSIONMETADATAREQUEST_UPSERTENTRIESENTRY._serialized_options = b"8\001" _UPDATEWORKERDEPLOYMENTVERSIONMETADATAREQUEST.fields_by_name[ @@ -3613,498 +4025,556 @@ ]._serialized_options = b"\030\001" _UPDATETASKQUEUECONFIGREQUEST_SETFAIRNESSWEIGHTOVERRIDESENTRY._options = None _UPDATETASKQUEUECONFIGREQUEST_SETFAIRNESSWEIGHTOVERRIDESENTRY._serialized_options = b"8\001" - _REGISTERNAMESPACEREQUEST._serialized_start = 1530 - _REGISTERNAMESPACEREQUEST._serialized_end = 2178 - _REGISTERNAMESPACEREQUEST_DATAENTRY._serialized_start = 2135 - _REGISTERNAMESPACEREQUEST_DATAENTRY._serialized_end = 2178 - _REGISTERNAMESPACERESPONSE._serialized_start = 2180 - _REGISTERNAMESPACERESPONSE._serialized_end = 2207 - _LISTNAMESPACESREQUEST._serialized_start = 2210 - _LISTNAMESPACESREQUEST._serialized_end = 2347 - _LISTNAMESPACESRESPONSE._serialized_start = 2350 - _LISTNAMESPACESRESPONSE._serialized_end = 2479 - _DESCRIBENAMESPACEREQUEST._serialized_start = 2481 - _DESCRIBENAMESPACEREQUEST._serialized_end = 2538 - _DESCRIBENAMESPACERESPONSE._serialized_start = 2541 - _DESCRIBENAMESPACERESPONSE._serialized_end = 2905 - _UPDATENAMESPACEREQUEST._serialized_start = 2908 - _UPDATENAMESPACEREQUEST._serialized_end = 3243 - _UPDATENAMESPACERESPONSE._serialized_start = 3246 - _UPDATENAMESPACERESPONSE._serialized_end = 3537 - _DEPRECATENAMESPACEREQUEST._serialized_start = 3539 - _DEPRECATENAMESPACEREQUEST._serialized_end = 3609 - _DEPRECATENAMESPACERESPONSE._serialized_start = 3611 - _DEPRECATENAMESPACERESPONSE._serialized_end = 3639 - _STARTWORKFLOWEXECUTIONREQUEST._serialized_start = 3642 - _STARTWORKFLOWEXECUTIONREQUEST._serialized_end = 5185 - _STARTWORKFLOWEXECUTIONRESPONSE._serialized_start = 5188 - _STARTWORKFLOWEXECUTIONRESPONSE._serialized_end = 5454 - _GETWORKFLOWEXECUTIONHISTORYREQUEST._serialized_start = 5457 - _GETWORKFLOWEXECUTIONHISTORYREQUEST._serialized_end = 5755 - _GETWORKFLOWEXECUTIONHISTORYRESPONSE._serialized_start = 5758 - _GETWORKFLOWEXECUTIONHISTORYRESPONSE._serialized_end = 5944 - _GETWORKFLOWEXECUTIONHISTORYREVERSEREQUEST._serialized_start = 5947 - _GETWORKFLOWEXECUTIONHISTORYREVERSEREQUEST._serialized_end = 6123 - _GETWORKFLOWEXECUTIONHISTORYREVERSERESPONSE._serialized_start = 6125 - _GETWORKFLOWEXECUTIONHISTORYREVERSERESPONSE._serialized_end = 6245 - _POLLWORKFLOWTASKQUEUEREQUEST._serialized_start = 6248 - _POLLWORKFLOWTASKQUEUEREQUEST._serialized_end = 6628 - _POLLWORKFLOWTASKQUEUERESPONSE._serialized_start = 6631 - _POLLWORKFLOWTASKQUEUERESPONSE._serialized_end = 7544 - _POLLWORKFLOWTASKQUEUERESPONSE_QUERIESENTRY._serialized_start = 7460 - _POLLWORKFLOWTASKQUEUERESPONSE_QUERIESENTRY._serialized_end = 7544 - _RESPONDWORKFLOWTASKCOMPLETEDREQUEST._serialized_start = 7547 - _RESPONDWORKFLOWTASKCOMPLETEDREQUEST._serialized_end = 8773 - _RESPONDWORKFLOWTASKCOMPLETEDREQUEST_QUERYRESULTSENTRY._serialized_start = 8607 - _RESPONDWORKFLOWTASKCOMPLETEDREQUEST_QUERYRESULTSENTRY._serialized_end = 8702 - _RESPONDWORKFLOWTASKCOMPLETEDREQUEST_CAPABILITIES._serialized_start = 8704 - _RESPONDWORKFLOWTASKCOMPLETEDREQUEST_CAPABILITIES._serialized_end = 8773 - _RESPONDWORKFLOWTASKCOMPLETEDRESPONSE._serialized_start = 8776 - _RESPONDWORKFLOWTASKCOMPLETEDRESPONSE._serialized_end = 9021 - _RESPONDWORKFLOWTASKFAILEDREQUEST._serialized_start = 9024 - _RESPONDWORKFLOWTASKFAILEDREQUEST._serialized_end = 9549 - _RESPONDWORKFLOWTASKFAILEDRESPONSE._serialized_start = 9551 - _RESPONDWORKFLOWTASKFAILEDRESPONSE._serialized_end = 9586 - _POLLACTIVITYTASKQUEUEREQUEST._serialized_start = 9589 - _POLLACTIVITYTASKQUEUEREQUEST._serialized_end = 10015 - _POLLACTIVITYTASKQUEUERESPONSE._serialized_start = 10018 - _POLLACTIVITYTASKQUEUERESPONSE._serialized_end = 11050 - _RECORDACTIVITYTASKHEARTBEATREQUEST._serialized_start = 11053 - _RECORDACTIVITYTASKHEARTBEATREQUEST._serialized_end = 11218 - _RECORDACTIVITYTASKHEARTBEATRESPONSE._serialized_start = 11220 - _RECORDACTIVITYTASKHEARTBEATRESPONSE._serialized_end = 11332 - _RECORDACTIVITYTASKHEARTBEATBYIDREQUEST._serialized_start = 11335 - _RECORDACTIVITYTASKHEARTBEATBYIDREQUEST._serialized_end = 11542 - _RECORDACTIVITYTASKHEARTBEATBYIDRESPONSE._serialized_start = 11544 - _RECORDACTIVITYTASKHEARTBEATBYIDRESPONSE._serialized_end = 11660 - _RESPONDACTIVITYTASKCOMPLETEDREQUEST._serialized_start = 11663 - _RESPONDACTIVITYTASKCOMPLETEDREQUEST._serialized_end = 12045 - _RESPONDACTIVITYTASKCOMPLETEDRESPONSE._serialized_start = 12047 - _RESPONDACTIVITYTASKCOMPLETEDRESPONSE._serialized_end = 12085 - _RESPONDACTIVITYTASKCOMPLETEDBYIDREQUEST._serialized_start = 12088 - _RESPONDACTIVITYTASKCOMPLETEDBYIDREQUEST._serialized_end = 12295 - _RESPONDACTIVITYTASKCOMPLETEDBYIDRESPONSE._serialized_start = 12297 - _RESPONDACTIVITYTASKCOMPLETEDBYIDRESPONSE._serialized_end = 12339 - _RESPONDACTIVITYTASKFAILEDREQUEST._serialized_start = 12342 - _RESPONDACTIVITYTASKFAILEDREQUEST._serialized_end = 12788 - _RESPONDACTIVITYTASKFAILEDRESPONSE._serialized_start = 12790 - _RESPONDACTIVITYTASKFAILEDRESPONSE._serialized_end = 12877 - _RESPONDACTIVITYTASKFAILEDBYIDREQUEST._serialized_start = 12880 - _RESPONDACTIVITYTASKFAILEDBYIDREQUEST._serialized_end = 13151 - _RESPONDACTIVITYTASKFAILEDBYIDRESPONSE._serialized_start = 13153 - _RESPONDACTIVITYTASKFAILEDBYIDRESPONSE._serialized_end = 13244 - _RESPONDACTIVITYTASKCANCELEDREQUEST._serialized_start = 13247 - _RESPONDACTIVITYTASKCANCELEDREQUEST._serialized_end = 13629 - _RESPONDACTIVITYTASKCANCELEDRESPONSE._serialized_start = 13631 - _RESPONDACTIVITYTASKCANCELEDRESPONSE._serialized_end = 13668 - _RESPONDACTIVITYTASKCANCELEDBYIDREQUEST._serialized_start = 13671 - _RESPONDACTIVITYTASKCANCELEDBYIDREQUEST._serialized_end = 13959 - _RESPONDACTIVITYTASKCANCELEDBYIDRESPONSE._serialized_start = 13961 - _RESPONDACTIVITYTASKCANCELEDBYIDRESPONSE._serialized_end = 14002 - _REQUESTCANCELWORKFLOWEXECUTIONREQUEST._serialized_start = 14005 - _REQUESTCANCELWORKFLOWEXECUTIONREQUEST._serialized_end = 14265 - _REQUESTCANCELWORKFLOWEXECUTIONRESPONSE._serialized_start = 14267 - _REQUESTCANCELWORKFLOWEXECUTIONRESPONSE._serialized_end = 14307 - _SIGNALWORKFLOWEXECUTIONREQUEST._serialized_start = 14310 - _SIGNALWORKFLOWEXECUTIONREQUEST._serialized_end = 14660 - _SIGNALWORKFLOWEXECUTIONRESPONSE._serialized_start = 14662 - _SIGNALWORKFLOWEXECUTIONRESPONSE._serialized_end = 14695 - _SIGNALWITHSTARTWORKFLOWEXECUTIONREQUEST._serialized_start = 14698 - _SIGNALWITHSTARTWORKFLOWEXECUTIONREQUEST._serialized_end = 15963 - _SIGNALWITHSTARTWORKFLOWEXECUTIONRESPONSE._serialized_start = 15965 - _SIGNALWITHSTARTWORKFLOWEXECUTIONRESPONSE._serialized_end = 16040 - _RESETWORKFLOWEXECUTIONREQUEST._serialized_start = 16043 - _RESETWORKFLOWEXECUTIONREQUEST._serialized_end = 16492 - _RESETWORKFLOWEXECUTIONRESPONSE._serialized_start = 16494 - _RESETWORKFLOWEXECUTIONRESPONSE._serialized_end = 16542 - _TERMINATEWORKFLOWEXECUTIONREQUEST._serialized_start = 16545 - _TERMINATEWORKFLOWEXECUTIONREQUEST._serialized_end = 16832 - _TERMINATEWORKFLOWEXECUTIONRESPONSE._serialized_start = 16834 - _TERMINATEWORKFLOWEXECUTIONRESPONSE._serialized_end = 16870 - _DELETEWORKFLOWEXECUTIONREQUEST._serialized_start = 16872 - _DELETEWORKFLOWEXECUTIONREQUEST._serialized_end = 16994 - _DELETEWORKFLOWEXECUTIONRESPONSE._serialized_start = 16996 - _DELETEWORKFLOWEXECUTIONRESPONSE._serialized_end = 17029 - _LISTOPENWORKFLOWEXECUTIONSREQUEST._serialized_start = 17032 - _LISTOPENWORKFLOWEXECUTIONSREQUEST._serialized_end = 17361 - _LISTOPENWORKFLOWEXECUTIONSRESPONSE._serialized_start = 17364 - _LISTOPENWORKFLOWEXECUTIONSRESPONSE._serialized_end = 17494 - _LISTCLOSEDWORKFLOWEXECUTIONSREQUEST._serialized_start = 17497 - _LISTCLOSEDWORKFLOWEXECUTIONSREQUEST._serialized_end = 17891 - _LISTCLOSEDWORKFLOWEXECUTIONSRESPONSE._serialized_start = 17894 - _LISTCLOSEDWORKFLOWEXECUTIONSRESPONSE._serialized_end = 18026 - _LISTWORKFLOWEXECUTIONSREQUEST._serialized_start = 18028 - _LISTWORKFLOWEXECUTIONSREQUEST._serialized_end = 18137 - _LISTWORKFLOWEXECUTIONSRESPONSE._serialized_start = 18139 - _LISTWORKFLOWEXECUTIONSRESPONSE._serialized_end = 18265 - _LISTARCHIVEDWORKFLOWEXECUTIONSREQUEST._serialized_start = 18267 - _LISTARCHIVEDWORKFLOWEXECUTIONSREQUEST._serialized_end = 18384 - _LISTARCHIVEDWORKFLOWEXECUTIONSRESPONSE._serialized_start = 18387 - _LISTARCHIVEDWORKFLOWEXECUTIONSRESPONSE._serialized_end = 18521 - _SCANWORKFLOWEXECUTIONSREQUEST._serialized_start = 18523 - _SCANWORKFLOWEXECUTIONSREQUEST._serialized_end = 18632 - _SCANWORKFLOWEXECUTIONSRESPONSE._serialized_start = 18634 - _SCANWORKFLOWEXECUTIONSRESPONSE._serialized_end = 18760 - _COUNTWORKFLOWEXECUTIONSREQUEST._serialized_start = 18762 - _COUNTWORKFLOWEXECUTIONSREQUEST._serialized_end = 18828 - _COUNTWORKFLOWEXECUTIONSRESPONSE._serialized_start = 18831 - _COUNTWORKFLOWEXECUTIONSRESPONSE._serialized_end = 19068 - _COUNTWORKFLOWEXECUTIONSRESPONSE_AGGREGATIONGROUP._serialized_start = 18980 - _COUNTWORKFLOWEXECUTIONSRESPONSE_AGGREGATIONGROUP._serialized_end = 19068 - _GETSEARCHATTRIBUTESREQUEST._serialized_start = 19070 - _GETSEARCHATTRIBUTESREQUEST._serialized_end = 19098 - _GETSEARCHATTRIBUTESRESPONSE._serialized_start = 19101 - _GETSEARCHATTRIBUTESRESPONSE._serialized_end = 19302 - _GETSEARCHATTRIBUTESRESPONSE_KEYSENTRY._serialized_start = 19218 - _GETSEARCHATTRIBUTESRESPONSE_KEYSENTRY._serialized_end = 19302 - _RESPONDQUERYTASKCOMPLETEDREQUEST._serialized_start = 19305 - _RESPONDQUERYTASKCOMPLETEDREQUEST._serialized_end = 19641 - _RESPONDQUERYTASKCOMPLETEDRESPONSE._serialized_start = 19643 - _RESPONDQUERYTASKCOMPLETEDRESPONSE._serialized_end = 19678 - _RESETSTICKYTASKQUEUEREQUEST._serialized_start = 19680 - _RESETSTICKYTASKQUEUEREQUEST._serialized_end = 19790 - _RESETSTICKYTASKQUEUERESPONSE._serialized_start = 19792 - _RESETSTICKYTASKQUEUERESPONSE._serialized_end = 19822 - _SHUTDOWNWORKERREQUEST._serialized_start = 19825 - _SHUTDOWNWORKERREQUEST._serialized_end = 20108 - _SHUTDOWNWORKERRESPONSE._serialized_start = 20110 - _SHUTDOWNWORKERRESPONSE._serialized_end = 20134 - _QUERYWORKFLOWREQUEST._serialized_start = 20137 - _QUERYWORKFLOWREQUEST._serialized_end = 20370 - _QUERYWORKFLOWRESPONSE._serialized_start = 20373 - _QUERYWORKFLOWRESPONSE._serialized_end = 20514 - _DESCRIBEWORKFLOWEXECUTIONREQUEST._serialized_start = 20516 - _DESCRIBEWORKFLOWEXECUTIONREQUEST._serialized_end = 20631 - _DESCRIBEWORKFLOWEXECUTIONRESPONSE._serialized_start = 20634 - _DESCRIBEWORKFLOWEXECUTIONRESPONSE._serialized_end = 21299 - _DESCRIBETASKQUEUEREQUEST._serialized_start = 21302 - _DESCRIBETASKQUEUEREQUEST._serialized_end = 21830 - _DESCRIBETASKQUEUERESPONSE._serialized_start = 21833 - _DESCRIBETASKQUEUERESPONSE._serialized_end = 22837 - _DESCRIBETASKQUEUERESPONSE_STATSBYPRIORITYKEYENTRY._serialized_start = 22517 - _DESCRIBETASKQUEUERESPONSE_STATSBYPRIORITYKEYENTRY._serialized_end = 22617 - _DESCRIBETASKQUEUERESPONSE_EFFECTIVERATELIMIT._serialized_start = 22619 - _DESCRIBETASKQUEUERESPONSE_EFFECTIVERATELIMIT._serialized_end = 22735 - _DESCRIBETASKQUEUERESPONSE_VERSIONSINFOENTRY._serialized_start = 22737 - _DESCRIBETASKQUEUERESPONSE_VERSIONSINFOENTRY._serialized_end = 22837 - _GETCLUSTERINFOREQUEST._serialized_start = 22839 - _GETCLUSTERINFOREQUEST._serialized_end = 22862 - _GETCLUSTERINFORESPONSE._serialized_start = 22865 - _GETCLUSTERINFORESPONSE._serialized_end = 23330 - _GETCLUSTERINFORESPONSE_SUPPORTEDCLIENTSENTRY._serialized_start = 23275 - _GETCLUSTERINFORESPONSE_SUPPORTEDCLIENTSENTRY._serialized_end = 23330 - _GETSYSTEMINFOREQUEST._serialized_start = 23332 - _GETSYSTEMINFOREQUEST._serialized_end = 23354 - _GETSYSTEMINFORESPONSE._serialized_start = 23357 - _GETSYSTEMINFORESPONSE._serialized_end = 23857 - _GETSYSTEMINFORESPONSE_CAPABILITIES._serialized_start = 23498 - _GETSYSTEMINFORESPONSE_CAPABILITIES._serialized_end = 23857 - _LISTTASKQUEUEPARTITIONSREQUEST._serialized_start = 23859 - _LISTTASKQUEUEPARTITIONSREQUEST._serialized_end = 23968 - _LISTTASKQUEUEPARTITIONSRESPONSE._serialized_start = 23971 - _LISTTASKQUEUEPARTITIONSRESPONSE._serialized_end = 24194 - _CREATESCHEDULEREQUEST._serialized_start = 24197 - _CREATESCHEDULEREQUEST._serialized_end = 24529 - _CREATESCHEDULERESPONSE._serialized_start = 24531 - _CREATESCHEDULERESPONSE._serialized_end = 24579 - _DESCRIBESCHEDULEREQUEST._serialized_start = 24581 - _DESCRIBESCHEDULEREQUEST._serialized_end = 24646 - _DESCRIBESCHEDULERESPONSE._serialized_start = 24649 - _DESCRIBESCHEDULERESPONSE._serialized_end = 24920 - _UPDATESCHEDULEREQUEST._serialized_start = 24923 - _UPDATESCHEDULEREQUEST._serialized_end = 25171 - _UPDATESCHEDULERESPONSE._serialized_start = 25173 - _UPDATESCHEDULERESPONSE._serialized_end = 25197 - _PATCHSCHEDULEREQUEST._serialized_start = 25200 - _PATCHSCHEDULEREQUEST._serialized_end = 25356 - _PATCHSCHEDULERESPONSE._serialized_start = 25358 - _PATCHSCHEDULERESPONSE._serialized_end = 25381 - _LISTSCHEDULEMATCHINGTIMESREQUEST._serialized_start = 25384 - _LISTSCHEDULEMATCHINGTIMESREQUEST._serialized_end = 25552 - _LISTSCHEDULEMATCHINGTIMESRESPONSE._serialized_start = 25554 - _LISTSCHEDULEMATCHINGTIMESRESPONSE._serialized_end = 25637 - _DELETESCHEDULEREQUEST._serialized_start = 25639 - _DELETESCHEDULEREQUEST._serialized_end = 25720 - _DELETESCHEDULERESPONSE._serialized_start = 25722 - _DELETESCHEDULERESPONSE._serialized_end = 25746 - _LISTSCHEDULESREQUEST._serialized_start = 25748 - _LISTSCHEDULESREQUEST._serialized_end = 25856 - _LISTSCHEDULESRESPONSE._serialized_start = 25858 - _LISTSCHEDULESRESPONSE._serialized_end = 25970 - _COUNTSCHEDULESREQUEST._serialized_start = 25972 - _COUNTSCHEDULESREQUEST._serialized_end = 26029 - _COUNTSCHEDULESRESPONSE._serialized_start = 26032 - _COUNTSCHEDULESRESPONSE._serialized_end = 26251 - _COUNTSCHEDULESRESPONSE_AGGREGATIONGROUP._serialized_start = 18980 - _COUNTSCHEDULESRESPONSE_AGGREGATIONGROUP._serialized_end = 19068 - _UPDATEWORKERBUILDIDCOMPATIBILITYREQUEST._serialized_start = 26254 - _UPDATEWORKERBUILDIDCOMPATIBILITYREQUEST._serialized_end = 26900 - _UPDATEWORKERBUILDIDCOMPATIBILITYREQUEST_ADDNEWCOMPATIBLEVERSION._serialized_start = 26701 + _STARTNEXUSOPERATIONEXECUTIONREQUEST_NEXUSHEADERENTRY._options = None + _STARTNEXUSOPERATIONEXECUTIONREQUEST_NEXUSHEADERENTRY._serialized_options = b"8\001" + _REGISTERNAMESPACEREQUEST._serialized_start = 1603 + _REGISTERNAMESPACEREQUEST._serialized_end = 2251 + _REGISTERNAMESPACEREQUEST_DATAENTRY._serialized_start = 2208 + _REGISTERNAMESPACEREQUEST_DATAENTRY._serialized_end = 2251 + _REGISTERNAMESPACERESPONSE._serialized_start = 2253 + _REGISTERNAMESPACERESPONSE._serialized_end = 2280 + _LISTNAMESPACESREQUEST._serialized_start = 2283 + _LISTNAMESPACESREQUEST._serialized_end = 2420 + _LISTNAMESPACESRESPONSE._serialized_start = 2423 + _LISTNAMESPACESRESPONSE._serialized_end = 2552 + _DESCRIBENAMESPACEREQUEST._serialized_start = 2554 + _DESCRIBENAMESPACEREQUEST._serialized_end = 2611 + _DESCRIBENAMESPACERESPONSE._serialized_start = 2614 + _DESCRIBENAMESPACERESPONSE._serialized_end = 2978 + _UPDATENAMESPACEREQUEST._serialized_start = 2981 + _UPDATENAMESPACEREQUEST._serialized_end = 3316 + _UPDATENAMESPACERESPONSE._serialized_start = 3319 + _UPDATENAMESPACERESPONSE._serialized_end = 3610 + _DEPRECATENAMESPACEREQUEST._serialized_start = 3612 + _DEPRECATENAMESPACEREQUEST._serialized_end = 3682 + _DEPRECATENAMESPACERESPONSE._serialized_start = 3684 + _DEPRECATENAMESPACERESPONSE._serialized_end = 3712 + _STARTWORKFLOWEXECUTIONREQUEST._serialized_start = 3715 + _STARTWORKFLOWEXECUTIONREQUEST._serialized_end = 5334 + _STARTWORKFLOWEXECUTIONRESPONSE._serialized_start = 5337 + _STARTWORKFLOWEXECUTIONRESPONSE._serialized_end = 5603 + _GETWORKFLOWEXECUTIONHISTORYREQUEST._serialized_start = 5606 + _GETWORKFLOWEXECUTIONHISTORYREQUEST._serialized_end = 5904 + _GETWORKFLOWEXECUTIONHISTORYRESPONSE._serialized_start = 5907 + _GETWORKFLOWEXECUTIONHISTORYRESPONSE._serialized_end = 6093 + _GETWORKFLOWEXECUTIONHISTORYREVERSEREQUEST._serialized_start = 6096 + _GETWORKFLOWEXECUTIONHISTORYREVERSEREQUEST._serialized_end = 6272 + _GETWORKFLOWEXECUTIONHISTORYREVERSERESPONSE._serialized_start = 6274 + _GETWORKFLOWEXECUTIONHISTORYREVERSERESPONSE._serialized_end = 6394 + _POLLWORKFLOWTASKQUEUEREQUEST._serialized_start = 6397 + _POLLWORKFLOWTASKQUEUEREQUEST._serialized_end = 6837 + _POLLWORKFLOWTASKQUEUERESPONSE._serialized_start = 6840 + _POLLWORKFLOWTASKQUEUERESPONSE._serialized_end = 7850 + _POLLWORKFLOWTASKQUEUERESPONSE_QUERIESENTRY._serialized_start = 7766 + _POLLWORKFLOWTASKQUEUERESPONSE_QUERIESENTRY._serialized_end = 7850 + _RESPONDWORKFLOWTASKCOMPLETEDREQUEST._serialized_start = 7853 + _RESPONDWORKFLOWTASKCOMPLETEDREQUEST._serialized_end = 9143 + _RESPONDWORKFLOWTASKCOMPLETEDREQUEST_QUERYRESULTSENTRY._serialized_start = 8977 + _RESPONDWORKFLOWTASKCOMPLETEDREQUEST_QUERYRESULTSENTRY._serialized_end = 9072 + _RESPONDWORKFLOWTASKCOMPLETEDREQUEST_CAPABILITIES._serialized_start = 9074 + _RESPONDWORKFLOWTASKCOMPLETEDREQUEST_CAPABILITIES._serialized_end = 9143 + _RESPONDWORKFLOWTASKCOMPLETEDRESPONSE._serialized_start = 9146 + _RESPONDWORKFLOWTASKCOMPLETEDRESPONSE._serialized_end = 9391 + _RESPONDWORKFLOWTASKFAILEDREQUEST._serialized_start = 9394 + _RESPONDWORKFLOWTASKFAILEDREQUEST._serialized_end = 9919 + _RESPONDWORKFLOWTASKFAILEDRESPONSE._serialized_start = 9921 + _RESPONDWORKFLOWTASKFAILEDRESPONSE._serialized_end = 9956 + _POLLACTIVITYTASKQUEUEREQUEST._serialized_start = 9959 + _POLLACTIVITYTASKQUEUEREQUEST._serialized_end = 10445 + _POLLACTIVITYTASKQUEUERESPONSE._serialized_start = 10448 + _POLLACTIVITYTASKQUEUERESPONSE._serialized_end = 11552 + _RECORDACTIVITYTASKHEARTBEATREQUEST._serialized_start = 11555 + _RECORDACTIVITYTASKHEARTBEATREQUEST._serialized_end = 11720 + _RECORDACTIVITYTASKHEARTBEATRESPONSE._serialized_start = 11722 + _RECORDACTIVITYTASKHEARTBEATRESPONSE._serialized_end = 11834 + _RECORDACTIVITYTASKHEARTBEATBYIDREQUEST._serialized_start = 11837 + _RECORDACTIVITYTASKHEARTBEATBYIDREQUEST._serialized_end = 12044 + _RECORDACTIVITYTASKHEARTBEATBYIDRESPONSE._serialized_start = 12046 + _RECORDACTIVITYTASKHEARTBEATBYIDRESPONSE._serialized_end = 12162 + _RESPONDACTIVITYTASKCOMPLETEDREQUEST._serialized_start = 12165 + _RESPONDACTIVITYTASKCOMPLETEDREQUEST._serialized_end = 12547 + _RESPONDACTIVITYTASKCOMPLETEDRESPONSE._serialized_start = 12549 + _RESPONDACTIVITYTASKCOMPLETEDRESPONSE._serialized_end = 12587 + _RESPONDACTIVITYTASKCOMPLETEDBYIDREQUEST._serialized_start = 12590 + _RESPONDACTIVITYTASKCOMPLETEDBYIDREQUEST._serialized_end = 12797 + _RESPONDACTIVITYTASKCOMPLETEDBYIDRESPONSE._serialized_start = 12799 + _RESPONDACTIVITYTASKCOMPLETEDBYIDRESPONSE._serialized_end = 12841 + _RESPONDACTIVITYTASKFAILEDREQUEST._serialized_start = 12844 + _RESPONDACTIVITYTASKFAILEDREQUEST._serialized_end = 13290 + _RESPONDACTIVITYTASKFAILEDRESPONSE._serialized_start = 13292 + _RESPONDACTIVITYTASKFAILEDRESPONSE._serialized_end = 13379 + _RESPONDACTIVITYTASKFAILEDBYIDREQUEST._serialized_start = 13382 + _RESPONDACTIVITYTASKFAILEDBYIDREQUEST._serialized_end = 13653 + _RESPONDACTIVITYTASKFAILEDBYIDRESPONSE._serialized_start = 13655 + _RESPONDACTIVITYTASKFAILEDBYIDRESPONSE._serialized_end = 13746 + _RESPONDACTIVITYTASKCANCELEDREQUEST._serialized_start = 13749 + _RESPONDACTIVITYTASKCANCELEDREQUEST._serialized_end = 14131 + _RESPONDACTIVITYTASKCANCELEDRESPONSE._serialized_start = 14133 + _RESPONDACTIVITYTASKCANCELEDRESPONSE._serialized_end = 14170 + _RESPONDACTIVITYTASKCANCELEDBYIDREQUEST._serialized_start = 14173 + _RESPONDACTIVITYTASKCANCELEDBYIDREQUEST._serialized_end = 14461 + _RESPONDACTIVITYTASKCANCELEDBYIDRESPONSE._serialized_start = 14463 + _RESPONDACTIVITYTASKCANCELEDBYIDRESPONSE._serialized_end = 14504 + _REQUESTCANCELWORKFLOWEXECUTIONREQUEST._serialized_start = 14507 + _REQUESTCANCELWORKFLOWEXECUTIONREQUEST._serialized_end = 14767 + _REQUESTCANCELWORKFLOWEXECUTIONRESPONSE._serialized_start = 14769 + _REQUESTCANCELWORKFLOWEXECUTIONRESPONSE._serialized_end = 14809 + _SIGNALWORKFLOWEXECUTIONREQUEST._serialized_start = 14812 + _SIGNALWORKFLOWEXECUTIONREQUEST._serialized_end = 15162 + _SIGNALWORKFLOWEXECUTIONRESPONSE._serialized_start = 15164 + _SIGNALWORKFLOWEXECUTIONRESPONSE._serialized_end = 15241 + _SIGNALWITHSTARTWORKFLOWEXECUTIONREQUEST._serialized_start = 15244 + _SIGNALWITHSTARTWORKFLOWEXECUTIONREQUEST._serialized_end = 16585 + _SIGNALWITHSTARTWORKFLOWEXECUTIONRESPONSE._serialized_start = 16587 + _SIGNALWITHSTARTWORKFLOWEXECUTIONRESPONSE._serialized_end = 16713 + _RESETWORKFLOWEXECUTIONREQUEST._serialized_start = 16716 + _RESETWORKFLOWEXECUTIONREQUEST._serialized_end = 17165 + _RESETWORKFLOWEXECUTIONRESPONSE._serialized_start = 17167 + _RESETWORKFLOWEXECUTIONRESPONSE._serialized_end = 17215 + _TERMINATEWORKFLOWEXECUTIONREQUEST._serialized_start = 17218 + _TERMINATEWORKFLOWEXECUTIONREQUEST._serialized_end = 17505 + _TERMINATEWORKFLOWEXECUTIONRESPONSE._serialized_start = 17507 + _TERMINATEWORKFLOWEXECUTIONRESPONSE._serialized_end = 17543 + _DELETEWORKFLOWEXECUTIONREQUEST._serialized_start = 17545 + _DELETEWORKFLOWEXECUTIONREQUEST._serialized_end = 17667 + _DELETEWORKFLOWEXECUTIONRESPONSE._serialized_start = 17669 + _DELETEWORKFLOWEXECUTIONRESPONSE._serialized_end = 17702 + _LISTOPENWORKFLOWEXECUTIONSREQUEST._serialized_start = 17705 + _LISTOPENWORKFLOWEXECUTIONSREQUEST._serialized_end = 18034 + _LISTOPENWORKFLOWEXECUTIONSRESPONSE._serialized_start = 18037 + _LISTOPENWORKFLOWEXECUTIONSRESPONSE._serialized_end = 18167 + _LISTCLOSEDWORKFLOWEXECUTIONSREQUEST._serialized_start = 18170 + _LISTCLOSEDWORKFLOWEXECUTIONSREQUEST._serialized_end = 18564 + _LISTCLOSEDWORKFLOWEXECUTIONSRESPONSE._serialized_start = 18567 + _LISTCLOSEDWORKFLOWEXECUTIONSRESPONSE._serialized_end = 18699 + _LISTWORKFLOWEXECUTIONSREQUEST._serialized_start = 18701 + _LISTWORKFLOWEXECUTIONSREQUEST._serialized_end = 18810 + _LISTWORKFLOWEXECUTIONSRESPONSE._serialized_start = 18812 + _LISTWORKFLOWEXECUTIONSRESPONSE._serialized_end = 18938 + _LISTARCHIVEDWORKFLOWEXECUTIONSREQUEST._serialized_start = 18940 + _LISTARCHIVEDWORKFLOWEXECUTIONSREQUEST._serialized_end = 19057 + _LISTARCHIVEDWORKFLOWEXECUTIONSRESPONSE._serialized_start = 19060 + _LISTARCHIVEDWORKFLOWEXECUTIONSRESPONSE._serialized_end = 19194 + _SCANWORKFLOWEXECUTIONSREQUEST._serialized_start = 19196 + _SCANWORKFLOWEXECUTIONSREQUEST._serialized_end = 19305 + _SCANWORKFLOWEXECUTIONSRESPONSE._serialized_start = 19307 + _SCANWORKFLOWEXECUTIONSRESPONSE._serialized_end = 19433 + _COUNTWORKFLOWEXECUTIONSREQUEST._serialized_start = 19435 + _COUNTWORKFLOWEXECUTIONSREQUEST._serialized_end = 19501 + _COUNTWORKFLOWEXECUTIONSRESPONSE._serialized_start = 19504 + _COUNTWORKFLOWEXECUTIONSRESPONSE._serialized_end = 19741 + _COUNTWORKFLOWEXECUTIONSRESPONSE_AGGREGATIONGROUP._serialized_start = 19653 + _COUNTWORKFLOWEXECUTIONSRESPONSE_AGGREGATIONGROUP._serialized_end = 19741 + _GETSEARCHATTRIBUTESREQUEST._serialized_start = 19743 + _GETSEARCHATTRIBUTESREQUEST._serialized_end = 19771 + _GETSEARCHATTRIBUTESRESPONSE._serialized_start = 19774 + _GETSEARCHATTRIBUTESRESPONSE._serialized_end = 19975 + _GETSEARCHATTRIBUTESRESPONSE_KEYSENTRY._serialized_start = 19891 + _GETSEARCHATTRIBUTESRESPONSE_KEYSENTRY._serialized_end = 19975 + _RESPONDQUERYTASKCOMPLETEDREQUEST._serialized_start = 19978 + _RESPONDQUERYTASKCOMPLETEDREQUEST._serialized_end = 20339 + _RESPONDQUERYTASKCOMPLETEDRESPONSE._serialized_start = 20341 + _RESPONDQUERYTASKCOMPLETEDRESPONSE._serialized_end = 20376 + _RESETSTICKYTASKQUEUEREQUEST._serialized_start = 20378 + _RESETSTICKYTASKQUEUEREQUEST._serialized_end = 20488 + _RESETSTICKYTASKQUEUERESPONSE._serialized_start = 20490 + _RESETSTICKYTASKQUEUERESPONSE._serialized_end = 20520 + _SHUTDOWNWORKERREQUEST._serialized_start = 20523 + _SHUTDOWNWORKERREQUEST._serialized_end = 20806 + _SHUTDOWNWORKERRESPONSE._serialized_start = 20808 + _SHUTDOWNWORKERRESPONSE._serialized_end = 20832 + _QUERYWORKFLOWREQUEST._serialized_start = 20835 + _QUERYWORKFLOWREQUEST._serialized_end = 21068 + _QUERYWORKFLOWRESPONSE._serialized_start = 21071 + _QUERYWORKFLOWRESPONSE._serialized_end = 21212 + _DESCRIBEWORKFLOWEXECUTIONREQUEST._serialized_start = 21214 + _DESCRIBEWORKFLOWEXECUTIONREQUEST._serialized_end = 21329 + _DESCRIBEWORKFLOWEXECUTIONRESPONSE._serialized_start = 21332 + _DESCRIBEWORKFLOWEXECUTIONRESPONSE._serialized_end = 21997 + _DESCRIBETASKQUEUEREQUEST._serialized_start = 22000 + _DESCRIBETASKQUEUEREQUEST._serialized_end = 22528 + _DESCRIBETASKQUEUERESPONSE._serialized_start = 22531 + _DESCRIBETASKQUEUERESPONSE._serialized_end = 23535 + _DESCRIBETASKQUEUERESPONSE_STATSBYPRIORITYKEYENTRY._serialized_start = 23215 + _DESCRIBETASKQUEUERESPONSE_STATSBYPRIORITYKEYENTRY._serialized_end = 23315 + _DESCRIBETASKQUEUERESPONSE_EFFECTIVERATELIMIT._serialized_start = 23317 + _DESCRIBETASKQUEUERESPONSE_EFFECTIVERATELIMIT._serialized_end = 23433 + _DESCRIBETASKQUEUERESPONSE_VERSIONSINFOENTRY._serialized_start = 23435 + _DESCRIBETASKQUEUERESPONSE_VERSIONSINFOENTRY._serialized_end = 23535 + _GETCLUSTERINFOREQUEST._serialized_start = 23537 + _GETCLUSTERINFOREQUEST._serialized_end = 23560 + _GETCLUSTERINFORESPONSE._serialized_start = 23563 + _GETCLUSTERINFORESPONSE._serialized_end = 24028 + _GETCLUSTERINFORESPONSE_SUPPORTEDCLIENTSENTRY._serialized_start = 23973 + _GETCLUSTERINFORESPONSE_SUPPORTEDCLIENTSENTRY._serialized_end = 24028 + _GETSYSTEMINFOREQUEST._serialized_start = 24030 + _GETSYSTEMINFOREQUEST._serialized_end = 24052 + _GETSYSTEMINFORESPONSE._serialized_start = 24055 + _GETSYSTEMINFORESPONSE._serialized_end = 24590 + _GETSYSTEMINFORESPONSE_CAPABILITIES._serialized_start = 24196 + _GETSYSTEMINFORESPONSE_CAPABILITIES._serialized_end = 24590 + _LISTTASKQUEUEPARTITIONSREQUEST._serialized_start = 24592 + _LISTTASKQUEUEPARTITIONSREQUEST._serialized_end = 24701 + _LISTTASKQUEUEPARTITIONSRESPONSE._serialized_start = 24704 + _LISTTASKQUEUEPARTITIONSRESPONSE._serialized_end = 24927 + _CREATESCHEDULEREQUEST._serialized_start = 24930 + _CREATESCHEDULEREQUEST._serialized_end = 25262 + _CREATESCHEDULERESPONSE._serialized_start = 25264 + _CREATESCHEDULERESPONSE._serialized_end = 25312 + _DESCRIBESCHEDULEREQUEST._serialized_start = 25314 + _DESCRIBESCHEDULEREQUEST._serialized_end = 25379 + _DESCRIBESCHEDULERESPONSE._serialized_start = 25382 + _DESCRIBESCHEDULERESPONSE._serialized_end = 25653 + _UPDATESCHEDULEREQUEST._serialized_start = 25656 + _UPDATESCHEDULEREQUEST._serialized_end = 25948 + _UPDATESCHEDULERESPONSE._serialized_start = 25950 + _UPDATESCHEDULERESPONSE._serialized_end = 25974 + _PATCHSCHEDULEREQUEST._serialized_start = 25977 + _PATCHSCHEDULEREQUEST._serialized_end = 26133 + _PATCHSCHEDULERESPONSE._serialized_start = 26135 + _PATCHSCHEDULERESPONSE._serialized_end = 26158 + _LISTSCHEDULEMATCHINGTIMESREQUEST._serialized_start = 26161 + _LISTSCHEDULEMATCHINGTIMESREQUEST._serialized_end = 26329 + _LISTSCHEDULEMATCHINGTIMESRESPONSE._serialized_start = 26331 + _LISTSCHEDULEMATCHINGTIMESRESPONSE._serialized_end = 26414 + _DELETESCHEDULEREQUEST._serialized_start = 26416 + _DELETESCHEDULEREQUEST._serialized_end = 26497 + _DELETESCHEDULERESPONSE._serialized_start = 26499 + _DELETESCHEDULERESPONSE._serialized_end = 26523 + _LISTSCHEDULESREQUEST._serialized_start = 26525 + _LISTSCHEDULESREQUEST._serialized_end = 26633 + _LISTSCHEDULESRESPONSE._serialized_start = 26635 + _LISTSCHEDULESRESPONSE._serialized_end = 26747 + _COUNTSCHEDULESREQUEST._serialized_start = 26749 + _COUNTSCHEDULESREQUEST._serialized_end = 26806 + _COUNTSCHEDULESRESPONSE._serialized_start = 26809 + _COUNTSCHEDULESRESPONSE._serialized_end = 27028 + _COUNTSCHEDULESRESPONSE_AGGREGATIONGROUP._serialized_start = 19653 + _COUNTSCHEDULESRESPONSE_AGGREGATIONGROUP._serialized_end = 19741 + _UPDATEWORKERBUILDIDCOMPATIBILITYREQUEST._serialized_start = 27031 + _UPDATEWORKERBUILDIDCOMPATIBILITYREQUEST._serialized_end = 27677 + _UPDATEWORKERBUILDIDCOMPATIBILITYREQUEST_ADDNEWCOMPATIBLEVERSION._serialized_start = 27478 _UPDATEWORKERBUILDIDCOMPATIBILITYREQUEST_ADDNEWCOMPATIBLEVERSION._serialized_end = ( - 26812 + 27589 ) - _UPDATEWORKERBUILDIDCOMPATIBILITYREQUEST_MERGESETS._serialized_start = 26814 - _UPDATEWORKERBUILDIDCOMPATIBILITYREQUEST_MERGESETS._serialized_end = 26887 - _UPDATEWORKERBUILDIDCOMPATIBILITYRESPONSE._serialized_start = 26902 - _UPDATEWORKERBUILDIDCOMPATIBILITYRESPONSE._serialized_end = 26966 - _GETWORKERBUILDIDCOMPATIBILITYREQUEST._serialized_start = 26968 - _GETWORKERBUILDIDCOMPATIBILITYREQUEST._serialized_end = 27063 - _GETWORKERBUILDIDCOMPATIBILITYRESPONSE._serialized_start = 27065 - _GETWORKERBUILDIDCOMPATIBILITYRESPONSE._serialized_end = 27181 - _UPDATEWORKERVERSIONINGRULESREQUEST._serialized_start = 27184 - _UPDATEWORKERVERSIONINGRULESREQUEST._serialized_end = 28901 - _UPDATEWORKERVERSIONINGRULESREQUEST_INSERTBUILDIDASSIGNMENTRULE._serialized_start = 28236 + _UPDATEWORKERBUILDIDCOMPATIBILITYREQUEST_MERGESETS._serialized_start = 27591 + _UPDATEWORKERBUILDIDCOMPATIBILITYREQUEST_MERGESETS._serialized_end = 27664 + _UPDATEWORKERBUILDIDCOMPATIBILITYRESPONSE._serialized_start = 27679 + _UPDATEWORKERBUILDIDCOMPATIBILITYRESPONSE._serialized_end = 27743 + _GETWORKERBUILDIDCOMPATIBILITYREQUEST._serialized_start = 27745 + _GETWORKERBUILDIDCOMPATIBILITYREQUEST._serialized_end = 27840 + _GETWORKERBUILDIDCOMPATIBILITYRESPONSE._serialized_start = 27842 + _GETWORKERBUILDIDCOMPATIBILITYRESPONSE._serialized_end = 27958 + _UPDATEWORKERVERSIONINGRULESREQUEST._serialized_start = 27961 + _UPDATEWORKERVERSIONINGRULESREQUEST._serialized_end = 29678 + _UPDATEWORKERVERSIONINGRULESREQUEST_INSERTBUILDIDASSIGNMENTRULE._serialized_start = 29013 _UPDATEWORKERVERSIONINGRULESREQUEST_INSERTBUILDIDASSIGNMENTRULE._serialized_end = ( - 28349 + 29126 ) - _UPDATEWORKERVERSIONINGRULESREQUEST_REPLACEBUILDIDASSIGNMENTRULE._serialized_start = 28352 + _UPDATEWORKERVERSIONINGRULESREQUEST_REPLACEBUILDIDASSIGNMENTRULE._serialized_start = 29129 _UPDATEWORKERVERSIONINGRULESREQUEST_REPLACEBUILDIDASSIGNMENTRULE._serialized_end = ( - 28481 + 29258 ) - _UPDATEWORKERVERSIONINGRULESREQUEST_DELETEBUILDIDASSIGNMENTRULE._serialized_start = 28483 + _UPDATEWORKERVERSIONINGRULESREQUEST_DELETEBUILDIDASSIGNMENTRULE._serialized_start = 29260 _UPDATEWORKERVERSIONINGRULESREQUEST_DELETEBUILDIDASSIGNMENTRULE._serialized_end = ( - 28547 + 29324 ) - _UPDATEWORKERVERSIONINGRULESREQUEST_ADDCOMPATIBLEBUILDIDREDIRECTRULE._serialized_start = 28549 - _UPDATEWORKERVERSIONINGRULESREQUEST_ADDCOMPATIBLEBUILDIDREDIRECTRULE._serialized_end = 28655 - _UPDATEWORKERVERSIONINGRULESREQUEST_REPLACECOMPATIBLEBUILDIDREDIRECTRULE._serialized_start = 28657 - _UPDATEWORKERVERSIONINGRULESREQUEST_REPLACECOMPATIBLEBUILDIDREDIRECTRULE._serialized_end = 28767 - _UPDATEWORKERVERSIONINGRULESREQUEST_DELETECOMPATIBLEBUILDIDREDIRECTRULE._serialized_start = 28769 - _UPDATEWORKERVERSIONINGRULESREQUEST_DELETECOMPATIBLEBUILDIDREDIRECTRULE._serialized_end = 28831 - _UPDATEWORKERVERSIONINGRULESREQUEST_COMMITBUILDID._serialized_start = 28833 - _UPDATEWORKERVERSIONINGRULESREQUEST_COMMITBUILDID._serialized_end = 28888 - _UPDATEWORKERVERSIONINGRULESRESPONSE._serialized_start = 28904 - _UPDATEWORKERVERSIONINGRULESRESPONSE._serialized_end = 29156 - _GETWORKERVERSIONINGRULESREQUEST._serialized_start = 29158 - _GETWORKERVERSIONINGRULESREQUEST._serialized_end = 29230 - _GETWORKERVERSIONINGRULESRESPONSE._serialized_start = 29233 - _GETWORKERVERSIONINGRULESRESPONSE._serialized_end = 29482 - _GETWORKERTASKREACHABILITYREQUEST._serialized_start = 29485 - _GETWORKERTASKREACHABILITYREQUEST._serialized_end = 29641 - _GETWORKERTASKREACHABILITYRESPONSE._serialized_start = 29643 - _GETWORKERTASKREACHABILITYRESPONSE._serialized_end = 29757 - _UPDATEWORKFLOWEXECUTIONREQUEST._serialized_start = 29760 - _UPDATEWORKFLOWEXECUTIONREQUEST._serialized_end = 30021 - _UPDATEWORKFLOWEXECUTIONRESPONSE._serialized_start = 30024 - _UPDATEWORKFLOWEXECUTIONRESPONSE._serialized_end = 30239 - _STARTBATCHOPERATIONREQUEST._serialized_start = 30242 - _STARTBATCHOPERATIONREQUEST._serialized_end = 31254 - _STARTBATCHOPERATIONRESPONSE._serialized_start = 31256 - _STARTBATCHOPERATIONRESPONSE._serialized_end = 31285 - _STOPBATCHOPERATIONREQUEST._serialized_start = 31287 - _STOPBATCHOPERATIONREQUEST._serialized_end = 31383 - _STOPBATCHOPERATIONRESPONSE._serialized_start = 31385 - _STOPBATCHOPERATIONRESPONSE._serialized_end = 31413 - _DESCRIBEBATCHOPERATIONREQUEST._serialized_start = 31415 - _DESCRIBEBATCHOPERATIONREQUEST._serialized_end = 31481 - _DESCRIBEBATCHOPERATIONRESPONSE._serialized_start = 31484 - _DESCRIBEBATCHOPERATIONRESPONSE._serialized_end = 31886 - _LISTBATCHOPERATIONSREQUEST._serialized_start = 31888 - _LISTBATCHOPERATIONSREQUEST._serialized_end = 31979 - _LISTBATCHOPERATIONSRESPONSE._serialized_start = 31981 - _LISTBATCHOPERATIONSRESPONSE._serialized_end = 32102 - _POLLWORKFLOWEXECUTIONUPDATEREQUEST._serialized_start = 32105 - _POLLWORKFLOWEXECUTIONUPDATEREQUEST._serialized_end = 32290 - _POLLWORKFLOWEXECUTIONUPDATERESPONSE._serialized_start = 32293 - _POLLWORKFLOWEXECUTIONUPDATERESPONSE._serialized_end = 32512 - _POLLNEXUSTASKQUEUEREQUEST._serialized_start = 32515 - _POLLNEXUSTASKQUEUEREQUEST._serialized_end = 32906 - _POLLNEXUSTASKQUEUERESPONSE._serialized_start = 32909 - _POLLNEXUSTASKQUEUERESPONSE._serialized_end = 33089 - _RESPONDNEXUSTASKCOMPLETEDREQUEST._serialized_start = 33092 - _RESPONDNEXUSTASKCOMPLETEDREQUEST._serialized_end = 33234 - _RESPONDNEXUSTASKCOMPLETEDRESPONSE._serialized_start = 33236 - _RESPONDNEXUSTASKCOMPLETEDRESPONSE._serialized_end = 33271 - _RESPONDNEXUSTASKFAILEDREQUEST._serialized_start = 33274 - _RESPONDNEXUSTASKFAILEDREQUEST._serialized_end = 33469 - _RESPONDNEXUSTASKFAILEDRESPONSE._serialized_start = 33471 - _RESPONDNEXUSTASKFAILEDRESPONSE._serialized_end = 33503 - _EXECUTEMULTIOPERATIONREQUEST._serialized_start = 33506 - _EXECUTEMULTIOPERATIONREQUEST._serialized_end = 33878 - _EXECUTEMULTIOPERATIONREQUEST_OPERATION._serialized_start = 33672 - _EXECUTEMULTIOPERATIONREQUEST_OPERATION._serialized_end = 33878 - _EXECUTEMULTIOPERATIONRESPONSE._serialized_start = 33881 - _EXECUTEMULTIOPERATIONRESPONSE._serialized_end = 34213 - _EXECUTEMULTIOPERATIONRESPONSE_RESPONSE._serialized_start = 34007 - _EXECUTEMULTIOPERATIONRESPONSE_RESPONSE._serialized_end = 34213 - _UPDATEACTIVITYOPTIONSREQUEST._serialized_start = 34216 - _UPDATEACTIVITYOPTIONSREQUEST._serialized_end = 34552 - _UPDATEACTIVITYOPTIONSRESPONSE._serialized_start = 34554 - _UPDATEACTIVITYOPTIONSRESPONSE._serialized_end = 34654 - _PAUSEACTIVITYREQUEST._serialized_start = 34657 - _PAUSEACTIVITYREQUEST._serialized_end = 34836 - _PAUSEACTIVITYRESPONSE._serialized_start = 34838 - _PAUSEACTIVITYRESPONSE._serialized_end = 34861 - _UNPAUSEACTIVITYREQUEST._serialized_start = 34864 - _UNPAUSEACTIVITYREQUEST._serialized_end = 35144 - _UNPAUSEACTIVITYRESPONSE._serialized_start = 35146 - _UNPAUSEACTIVITYRESPONSE._serialized_end = 35171 - _RESETACTIVITYREQUEST._serialized_start = 35174 - _RESETACTIVITYREQUEST._serialized_end = 35481 - _RESETACTIVITYRESPONSE._serialized_start = 35483 - _RESETACTIVITYRESPONSE._serialized_end = 35506 - _UPDATEWORKFLOWEXECUTIONOPTIONSREQUEST._serialized_start = 35509 - _UPDATEWORKFLOWEXECUTIONOPTIONSREQUEST._serialized_end = 35793 - _UPDATEWORKFLOWEXECUTIONOPTIONSRESPONSE._serialized_start = 35796 - _UPDATEWORKFLOWEXECUTIONOPTIONSRESPONSE._serialized_end = 35924 - _DESCRIBEDEPLOYMENTREQUEST._serialized_start = 35926 - _DESCRIBEDEPLOYMENTREQUEST._serialized_end = 36032 - _DESCRIBEDEPLOYMENTRESPONSE._serialized_start = 36034 - _DESCRIBEDEPLOYMENTRESPONSE._serialized_end = 36131 - _DESCRIBEWORKERDEPLOYMENTVERSIONREQUEST._serialized_start = 36134 - _DESCRIBEWORKERDEPLOYMENTVERSIONREQUEST._serialized_end = 36328 - _DESCRIBEWORKERDEPLOYMENTVERSIONRESPONSE._serialized_start = 36331 - _DESCRIBEWORKERDEPLOYMENTVERSIONRESPONSE._serialized_end = 36983 - _DESCRIBEWORKERDEPLOYMENTVERSIONRESPONSE_VERSIONTASKQUEUE._serialized_start = 36592 - _DESCRIBEWORKERDEPLOYMENTVERSIONRESPONSE_VERSIONTASKQUEUE._serialized_end = 36983 - _DESCRIBEWORKERDEPLOYMENTVERSIONRESPONSE_VERSIONTASKQUEUE_STATSBYPRIORITYKEYENTRY._serialized_start = 22517 - _DESCRIBEWORKERDEPLOYMENTVERSIONRESPONSE_VERSIONTASKQUEUE_STATSBYPRIORITYKEYENTRY._serialized_end = 22617 - _DESCRIBEWORKERDEPLOYMENTREQUEST._serialized_start = 36985 - _DESCRIBEWORKERDEPLOYMENTREQUEST._serialized_end = 37062 - _DESCRIBEWORKERDEPLOYMENTRESPONSE._serialized_start = 37065 - _DESCRIBEWORKERDEPLOYMENTRESPONSE._serialized_end = 37205 - _LISTDEPLOYMENTSREQUEST._serialized_start = 37207 - _LISTDEPLOYMENTSREQUEST._serialized_end = 37315 - _LISTDEPLOYMENTSRESPONSE._serialized_start = 37317 - _LISTDEPLOYMENTSRESPONSE._serialized_end = 37436 - _SETCURRENTDEPLOYMENTREQUEST._serialized_start = 37439 - _SETCURRENTDEPLOYMENTREQUEST._serialized_end = 37644 - _SETCURRENTDEPLOYMENTRESPONSE._serialized_start = 37647 - _SETCURRENTDEPLOYMENTRESPONSE._serialized_end = 37832 - _SETWORKERDEPLOYMENTCURRENTVERSIONREQUEST._serialized_start = 37835 - _SETWORKERDEPLOYMENTCURRENTVERSIONREQUEST._serialized_end = 38064 - _SETWORKERDEPLOYMENTCURRENTVERSIONRESPONSE._serialized_start = 38067 - _SETWORKERDEPLOYMENTCURRENTVERSIONRESPONSE._serialized_end = 38258 - _SETWORKERDEPLOYMENTRAMPINGVERSIONREQUEST._serialized_start = 38261 - _SETWORKERDEPLOYMENTRAMPINGVERSIONREQUEST._serialized_end = 38510 - _SETWORKERDEPLOYMENTRAMPINGVERSIONRESPONSE._serialized_start = 38513 - _SETWORKERDEPLOYMENTRAMPINGVERSIONRESPONSE._serialized_end = 38737 - _LISTWORKERDEPLOYMENTSREQUEST._serialized_start = 38739 - _LISTWORKERDEPLOYMENTSREQUEST._serialized_end = 38832 - _LISTWORKERDEPLOYMENTSRESPONSE._serialized_start = 38835 - _LISTWORKERDEPLOYMENTSRESPONSE._serialized_end = 39506 - _LISTWORKERDEPLOYMENTSRESPONSE_WORKERDEPLOYMENTSUMMARY._serialized_start = 39010 - _LISTWORKERDEPLOYMENTSRESPONSE_WORKERDEPLOYMENTSUMMARY._serialized_end = 39506 - _DELETEWORKERDEPLOYMENTVERSIONREQUEST._serialized_start = 39509 - _DELETEWORKERDEPLOYMENTVERSIONREQUEST._serialized_end = 39709 - _DELETEWORKERDEPLOYMENTVERSIONRESPONSE._serialized_start = 39711 - _DELETEWORKERDEPLOYMENTVERSIONRESPONSE._serialized_end = 39750 - _DELETEWORKERDEPLOYMENTREQUEST._serialized_start = 39752 - _DELETEWORKERDEPLOYMENTREQUEST._serialized_end = 39845 - _DELETEWORKERDEPLOYMENTRESPONSE._serialized_start = 39847 - _DELETEWORKERDEPLOYMENTRESPONSE._serialized_end = 39879 - _UPDATEWORKERDEPLOYMENTVERSIONMETADATAREQUEST._serialized_start = 39882 - _UPDATEWORKERDEPLOYMENTVERSIONMETADATAREQUEST._serialized_end = 40300 - _UPDATEWORKERDEPLOYMENTVERSIONMETADATAREQUEST_UPSERTENTRIESENTRY._serialized_start = 40215 + _UPDATEWORKERVERSIONINGRULESREQUEST_ADDCOMPATIBLEBUILDIDREDIRECTRULE._serialized_start = 29326 + _UPDATEWORKERVERSIONINGRULESREQUEST_ADDCOMPATIBLEBUILDIDREDIRECTRULE._serialized_end = 29432 + _UPDATEWORKERVERSIONINGRULESREQUEST_REPLACECOMPATIBLEBUILDIDREDIRECTRULE._serialized_start = 29434 + _UPDATEWORKERVERSIONINGRULESREQUEST_REPLACECOMPATIBLEBUILDIDREDIRECTRULE._serialized_end = 29544 + _UPDATEWORKERVERSIONINGRULESREQUEST_DELETECOMPATIBLEBUILDIDREDIRECTRULE._serialized_start = 29546 + _UPDATEWORKERVERSIONINGRULESREQUEST_DELETECOMPATIBLEBUILDIDREDIRECTRULE._serialized_end = 29608 + _UPDATEWORKERVERSIONINGRULESREQUEST_COMMITBUILDID._serialized_start = 29610 + _UPDATEWORKERVERSIONINGRULESREQUEST_COMMITBUILDID._serialized_end = 29665 + _UPDATEWORKERVERSIONINGRULESRESPONSE._serialized_start = 29681 + _UPDATEWORKERVERSIONINGRULESRESPONSE._serialized_end = 29933 + _GETWORKERVERSIONINGRULESREQUEST._serialized_start = 29935 + _GETWORKERVERSIONINGRULESREQUEST._serialized_end = 30007 + _GETWORKERVERSIONINGRULESRESPONSE._serialized_start = 30010 + _GETWORKERVERSIONINGRULESRESPONSE._serialized_end = 30259 + _GETWORKERTASKREACHABILITYREQUEST._serialized_start = 30262 + _GETWORKERTASKREACHABILITYREQUEST._serialized_end = 30418 + _GETWORKERTASKREACHABILITYRESPONSE._serialized_start = 30420 + _GETWORKERTASKREACHABILITYRESPONSE._serialized_end = 30534 + _UPDATEWORKFLOWEXECUTIONREQUEST._serialized_start = 30537 + _UPDATEWORKFLOWEXECUTIONREQUEST._serialized_end = 30798 + _UPDATEWORKFLOWEXECUTIONRESPONSE._serialized_start = 30801 + _UPDATEWORKFLOWEXECUTIONRESPONSE._serialized_end = 31016 + _STARTBATCHOPERATIONREQUEST._serialized_start = 31019 + _STARTBATCHOPERATIONREQUEST._serialized_end = 32031 + _STARTBATCHOPERATIONRESPONSE._serialized_start = 32033 + _STARTBATCHOPERATIONRESPONSE._serialized_end = 32062 + _STOPBATCHOPERATIONREQUEST._serialized_start = 32064 + _STOPBATCHOPERATIONREQUEST._serialized_end = 32160 + _STOPBATCHOPERATIONRESPONSE._serialized_start = 32162 + _STOPBATCHOPERATIONRESPONSE._serialized_end = 32190 + _DESCRIBEBATCHOPERATIONREQUEST._serialized_start = 32192 + _DESCRIBEBATCHOPERATIONREQUEST._serialized_end = 32258 + _DESCRIBEBATCHOPERATIONRESPONSE._serialized_start = 32261 + _DESCRIBEBATCHOPERATIONRESPONSE._serialized_end = 32663 + _LISTBATCHOPERATIONSREQUEST._serialized_start = 32665 + _LISTBATCHOPERATIONSREQUEST._serialized_end = 32756 + _LISTBATCHOPERATIONSRESPONSE._serialized_start = 32758 + _LISTBATCHOPERATIONSRESPONSE._serialized_end = 32879 + _POLLWORKFLOWEXECUTIONUPDATEREQUEST._serialized_start = 32882 + _POLLWORKFLOWEXECUTIONUPDATEREQUEST._serialized_end = 33067 + _POLLWORKFLOWEXECUTIONUPDATERESPONSE._serialized_start = 33070 + _POLLWORKFLOWEXECUTIONUPDATERESPONSE._serialized_end = 33289 + _POLLNEXUSTASKQUEUEREQUEST._serialized_start = 33292 + _POLLNEXUSTASKQUEUEREQUEST._serialized_end = 33708 + _POLLNEXUSTASKQUEUERESPONSE._serialized_start = 33711 + _POLLNEXUSTASKQUEUERESPONSE._serialized_end = 33988 + _RESPONDNEXUSTASKCOMPLETEDREQUEST._serialized_start = 33991 + _RESPONDNEXUSTASKCOMPLETEDREQUEST._serialized_end = 34158 + _RESPONDNEXUSTASKCOMPLETEDRESPONSE._serialized_start = 34160 + _RESPONDNEXUSTASKCOMPLETEDRESPONSE._serialized_end = 34195 + _RESPONDNEXUSTASKFAILEDREQUEST._serialized_start = 34198 + _RESPONDNEXUSTASKFAILEDREQUEST._serialized_end = 34418 + _RESPONDNEXUSTASKFAILEDRESPONSE._serialized_start = 34420 + _RESPONDNEXUSTASKFAILEDRESPONSE._serialized_end = 34452 + _EXECUTEMULTIOPERATIONREQUEST._serialized_start = 34455 + _EXECUTEMULTIOPERATIONREQUEST._serialized_end = 34827 + _EXECUTEMULTIOPERATIONREQUEST_OPERATION._serialized_start = 34621 + _EXECUTEMULTIOPERATIONREQUEST_OPERATION._serialized_end = 34827 + _EXECUTEMULTIOPERATIONRESPONSE._serialized_start = 34830 + _EXECUTEMULTIOPERATIONRESPONSE._serialized_end = 35162 + _EXECUTEMULTIOPERATIONRESPONSE_RESPONSE._serialized_start = 34956 + _EXECUTEMULTIOPERATIONRESPONSE_RESPONSE._serialized_end = 35162 + _UPDATEACTIVITYOPTIONSREQUEST._serialized_start = 35165 + _UPDATEACTIVITYOPTIONSREQUEST._serialized_end = 35501 + _UPDATEACTIVITYOPTIONSRESPONSE._serialized_start = 35503 + _UPDATEACTIVITYOPTIONSRESPONSE._serialized_end = 35603 + _PAUSEACTIVITYREQUEST._serialized_start = 35606 + _PAUSEACTIVITYREQUEST._serialized_end = 35785 + _PAUSEACTIVITYRESPONSE._serialized_start = 35787 + _PAUSEACTIVITYRESPONSE._serialized_end = 35810 + _UNPAUSEACTIVITYREQUEST._serialized_start = 35813 + _UNPAUSEACTIVITYREQUEST._serialized_end = 36093 + _UNPAUSEACTIVITYRESPONSE._serialized_start = 36095 + _UNPAUSEACTIVITYRESPONSE._serialized_end = 36120 + _RESETACTIVITYREQUEST._serialized_start = 36123 + _RESETACTIVITYREQUEST._serialized_end = 36430 + _RESETACTIVITYRESPONSE._serialized_start = 36432 + _RESETACTIVITYRESPONSE._serialized_end = 36455 + _UPDATEWORKFLOWEXECUTIONOPTIONSREQUEST._serialized_start = 36458 + _UPDATEWORKFLOWEXECUTIONOPTIONSREQUEST._serialized_end = 36742 + _UPDATEWORKFLOWEXECUTIONOPTIONSRESPONSE._serialized_start = 36745 + _UPDATEWORKFLOWEXECUTIONOPTIONSRESPONSE._serialized_end = 36873 + _DESCRIBEDEPLOYMENTREQUEST._serialized_start = 36875 + _DESCRIBEDEPLOYMENTREQUEST._serialized_end = 36981 + _DESCRIBEDEPLOYMENTRESPONSE._serialized_start = 36983 + _DESCRIBEDEPLOYMENTRESPONSE._serialized_end = 37080 + _DESCRIBEWORKERDEPLOYMENTVERSIONREQUEST._serialized_start = 37083 + _DESCRIBEWORKERDEPLOYMENTVERSIONREQUEST._serialized_end = 37277 + _DESCRIBEWORKERDEPLOYMENTVERSIONRESPONSE._serialized_start = 37280 + _DESCRIBEWORKERDEPLOYMENTVERSIONRESPONSE._serialized_end = 37932 + _DESCRIBEWORKERDEPLOYMENTVERSIONRESPONSE_VERSIONTASKQUEUE._serialized_start = 37541 + _DESCRIBEWORKERDEPLOYMENTVERSIONRESPONSE_VERSIONTASKQUEUE._serialized_end = 37932 + _DESCRIBEWORKERDEPLOYMENTVERSIONRESPONSE_VERSIONTASKQUEUE_STATSBYPRIORITYKEYENTRY._serialized_start = 23215 + _DESCRIBEWORKERDEPLOYMENTVERSIONRESPONSE_VERSIONTASKQUEUE_STATSBYPRIORITYKEYENTRY._serialized_end = 23315 + _DESCRIBEWORKERDEPLOYMENTREQUEST._serialized_start = 37934 + _DESCRIBEWORKERDEPLOYMENTREQUEST._serialized_end = 38011 + _DESCRIBEWORKERDEPLOYMENTRESPONSE._serialized_start = 38014 + _DESCRIBEWORKERDEPLOYMENTRESPONSE._serialized_end = 38154 + _LISTDEPLOYMENTSREQUEST._serialized_start = 38156 + _LISTDEPLOYMENTSREQUEST._serialized_end = 38264 + _LISTDEPLOYMENTSRESPONSE._serialized_start = 38266 + _LISTDEPLOYMENTSRESPONSE._serialized_end = 38385 + _SETCURRENTDEPLOYMENTREQUEST._serialized_start = 38388 + _SETCURRENTDEPLOYMENTREQUEST._serialized_end = 38593 + _SETCURRENTDEPLOYMENTRESPONSE._serialized_start = 38596 + _SETCURRENTDEPLOYMENTRESPONSE._serialized_end = 38781 + _SETWORKERDEPLOYMENTCURRENTVERSIONREQUEST._serialized_start = 38784 + _SETWORKERDEPLOYMENTCURRENTVERSIONREQUEST._serialized_end = 39013 + _SETWORKERDEPLOYMENTCURRENTVERSIONRESPONSE._serialized_start = 39016 + _SETWORKERDEPLOYMENTCURRENTVERSIONRESPONSE._serialized_end = 39207 + _SETWORKERDEPLOYMENTRAMPINGVERSIONREQUEST._serialized_start = 39210 + _SETWORKERDEPLOYMENTRAMPINGVERSIONREQUEST._serialized_end = 39459 + _SETWORKERDEPLOYMENTRAMPINGVERSIONRESPONSE._serialized_start = 39462 + _SETWORKERDEPLOYMENTRAMPINGVERSIONRESPONSE._serialized_end = 39686 + _CREATEWORKERDEPLOYMENTREQUEST._serialized_start = 39688 + _CREATEWORKERDEPLOYMENTREQUEST._serialized_end = 39801 + _CREATEWORKERDEPLOYMENTRESPONSE._serialized_start = 39803 + _CREATEWORKERDEPLOYMENTRESPONSE._serialized_end = 39859 + _LISTWORKERDEPLOYMENTSREQUEST._serialized_start = 39861 + _LISTWORKERDEPLOYMENTSREQUEST._serialized_end = 39954 + _LISTWORKERDEPLOYMENTSRESPONSE._serialized_start = 39957 + _LISTWORKERDEPLOYMENTSRESPONSE._serialized_end = 40628 + _LISTWORKERDEPLOYMENTSRESPONSE_WORKERDEPLOYMENTSUMMARY._serialized_start = 40132 + _LISTWORKERDEPLOYMENTSRESPONSE_WORKERDEPLOYMENTSUMMARY._serialized_end = 40628 + _CREATEWORKERDEPLOYMENTVERSIONREQUEST._serialized_start = 40631 + _CREATEWORKERDEPLOYMENTVERSIONREQUEST._serialized_end = 40871 + _CREATEWORKERDEPLOYMENTVERSIONRESPONSE._serialized_start = 40873 + _CREATEWORKERDEPLOYMENTVERSIONRESPONSE._serialized_end = 40912 + _DELETEWORKERDEPLOYMENTVERSIONREQUEST._serialized_start = 40915 + _DELETEWORKERDEPLOYMENTVERSIONREQUEST._serialized_end = 41115 + _DELETEWORKERDEPLOYMENTVERSIONRESPONSE._serialized_start = 41117 + _DELETEWORKERDEPLOYMENTVERSIONRESPONSE._serialized_end = 41156 + _DELETEWORKERDEPLOYMENTREQUEST._serialized_start = 41158 + _DELETEWORKERDEPLOYMENTREQUEST._serialized_end = 41251 + _DELETEWORKERDEPLOYMENTRESPONSE._serialized_start = 41253 + _DELETEWORKERDEPLOYMENTRESPONSE._serialized_end = 41285 + _UPDATEWORKERDEPLOYMENTVERSIONCOMPUTECONFIGREQUEST._serialized_start = 41288 + _UPDATEWORKERDEPLOYMENTVERSIONCOMPUTECONFIGREQUEST._serialized_end = 41804 + _UPDATEWORKERDEPLOYMENTVERSIONCOMPUTECONFIGREQUEST_COMPUTECONFIGSCALINGGROUPSENTRY._serialized_start = 41681 + _UPDATEWORKERDEPLOYMENTVERSIONCOMPUTECONFIGREQUEST_COMPUTECONFIGSCALINGGROUPSENTRY._serialized_end = 41804 + _UPDATEWORKERDEPLOYMENTVERSIONCOMPUTECONFIGRESPONSE._serialized_start = 41806 + _UPDATEWORKERDEPLOYMENTVERSIONCOMPUTECONFIGRESPONSE._serialized_end = 41858 + _VALIDATEWORKERDEPLOYMENTVERSIONCOMPUTECONFIGREQUEST._serialized_start = 41861 + _VALIDATEWORKERDEPLOYMENTVERSIONCOMPUTECONFIGREQUEST._serialized_end = 42361 + _VALIDATEWORKERDEPLOYMENTVERSIONCOMPUTECONFIGREQUEST_COMPUTECONFIGSCALINGGROUPSENTRY._serialized_start = 41681 + _VALIDATEWORKERDEPLOYMENTVERSIONCOMPUTECONFIGREQUEST_COMPUTECONFIGSCALINGGROUPSENTRY._serialized_end = 41804 + _VALIDATEWORKERDEPLOYMENTVERSIONCOMPUTECONFIGRESPONSE._serialized_start = 42363 + _VALIDATEWORKERDEPLOYMENTVERSIONCOMPUTECONFIGRESPONSE._serialized_end = 42417 + _UPDATEWORKERDEPLOYMENTVERSIONMETADATAREQUEST._serialized_start = 42420 + _UPDATEWORKERDEPLOYMENTVERSIONMETADATAREQUEST._serialized_end = 42838 + _UPDATEWORKERDEPLOYMENTVERSIONMETADATAREQUEST_UPSERTENTRIESENTRY._serialized_start = 42753 _UPDATEWORKERDEPLOYMENTVERSIONMETADATAREQUEST_UPSERTENTRIESENTRY._serialized_end = ( - 40300 + 42838 ) - _UPDATEWORKERDEPLOYMENTVERSIONMETADATARESPONSE._serialized_start = 40302 - _UPDATEWORKERDEPLOYMENTVERSIONMETADATARESPONSE._serialized_end = 40412 - _SETWORKERDEPLOYMENTMANAGERREQUEST._serialized_start = 40415 - _SETWORKERDEPLOYMENTMANAGERREQUEST._serialized_end = 40604 - _SETWORKERDEPLOYMENTMANAGERRESPONSE._serialized_start = 40606 - _SETWORKERDEPLOYMENTMANAGERRESPONSE._serialized_end = 40705 - _GETCURRENTDEPLOYMENTREQUEST._serialized_start = 40707 - _GETCURRENTDEPLOYMENTREQUEST._serialized_end = 40776 - _GETCURRENTDEPLOYMENTRESPONSE._serialized_start = 40778 - _GETCURRENTDEPLOYMENTRESPONSE._serialized_end = 40885 - _GETDEPLOYMENTREACHABILITYREQUEST._serialized_start = 40887 - _GETDEPLOYMENTREACHABILITYREQUEST._serialized_end = 41000 - _GETDEPLOYMENTREACHABILITYRESPONSE._serialized_start = 41003 - _GETDEPLOYMENTREACHABILITYRESPONSE._serialized_end = 41230 - _CREATEWORKFLOWRULEREQUEST._serialized_start = 41233 - _CREATEWORKFLOWRULEREQUEST._serialized_end = 41413 - _CREATEWORKFLOWRULERESPONSE._serialized_start = 41415 - _CREATEWORKFLOWRULERESPONSE._serialized_end = 41510 - _DESCRIBEWORKFLOWRULEREQUEST._serialized_start = 41512 - _DESCRIBEWORKFLOWRULEREQUEST._serialized_end = 41577 - _DESCRIBEWORKFLOWRULERESPONSE._serialized_start = 41579 - _DESCRIBEWORKFLOWRULERESPONSE._serialized_end = 41660 - _DELETEWORKFLOWRULEREQUEST._serialized_start = 41662 - _DELETEWORKFLOWRULEREQUEST._serialized_end = 41725 - _DELETEWORKFLOWRULERESPONSE._serialized_start = 41727 - _DELETEWORKFLOWRULERESPONSE._serialized_end = 41755 - _LISTWORKFLOWRULESREQUEST._serialized_start = 41757 - _LISTWORKFLOWRULESREQUEST._serialized_end = 41827 - _LISTWORKFLOWRULESRESPONSE._serialized_start = 41829 - _LISTWORKFLOWRULESRESPONSE._serialized_end = 41933 - _TRIGGERWORKFLOWRULEREQUEST._serialized_start = 41936 - _TRIGGERWORKFLOWRULEREQUEST._serialized_end = 42142 - _TRIGGERWORKFLOWRULERESPONSE._serialized_start = 42144 - _TRIGGERWORKFLOWRULERESPONSE._serialized_end = 42190 - _RECORDWORKERHEARTBEATREQUEST._serialized_start = 42193 - _RECORDWORKERHEARTBEATREQUEST._serialized_end = 42348 - _RECORDWORKERHEARTBEATRESPONSE._serialized_start = 42350 - _RECORDWORKERHEARTBEATRESPONSE._serialized_end = 42381 - _LISTWORKERSREQUEST._serialized_start = 42383 - _LISTWORKERSREQUEST._serialized_end = 42481 - _LISTWORKERSRESPONSE._serialized_start = 42484 - _LISTWORKERSRESPONSE._serialized_end = 42649 - _UPDATETASKQUEUECONFIGREQUEST._serialized_start = 42652 - _UPDATETASKQUEUECONFIGREQUEST._serialized_end = 43377 - _UPDATETASKQUEUECONFIGREQUEST_RATELIMITUPDATE._serialized_start = 43219 - _UPDATETASKQUEUECONFIGREQUEST_RATELIMITUPDATE._serialized_end = 43310 + _UPDATEWORKERDEPLOYMENTVERSIONMETADATARESPONSE._serialized_start = 42840 + _UPDATEWORKERDEPLOYMENTVERSIONMETADATARESPONSE._serialized_end = 42950 + _SETWORKERDEPLOYMENTMANAGERREQUEST._serialized_start = 42953 + _SETWORKERDEPLOYMENTMANAGERREQUEST._serialized_end = 43142 + _SETWORKERDEPLOYMENTMANAGERRESPONSE._serialized_start = 43144 + _SETWORKERDEPLOYMENTMANAGERRESPONSE._serialized_end = 43243 + _GETCURRENTDEPLOYMENTREQUEST._serialized_start = 43245 + _GETCURRENTDEPLOYMENTREQUEST._serialized_end = 43314 + _GETCURRENTDEPLOYMENTRESPONSE._serialized_start = 43316 + _GETCURRENTDEPLOYMENTRESPONSE._serialized_end = 43423 + _GETDEPLOYMENTREACHABILITYREQUEST._serialized_start = 43425 + _GETDEPLOYMENTREACHABILITYREQUEST._serialized_end = 43538 + _GETDEPLOYMENTREACHABILITYRESPONSE._serialized_start = 43541 + _GETDEPLOYMENTREACHABILITYRESPONSE._serialized_end = 43768 + _CREATEWORKFLOWRULEREQUEST._serialized_start = 43771 + _CREATEWORKFLOWRULEREQUEST._serialized_end = 43951 + _CREATEWORKFLOWRULERESPONSE._serialized_start = 43953 + _CREATEWORKFLOWRULERESPONSE._serialized_end = 44048 + _DESCRIBEWORKFLOWRULEREQUEST._serialized_start = 44050 + _DESCRIBEWORKFLOWRULEREQUEST._serialized_end = 44115 + _DESCRIBEWORKFLOWRULERESPONSE._serialized_start = 44117 + _DESCRIBEWORKFLOWRULERESPONSE._serialized_end = 44198 + _DELETEWORKFLOWRULEREQUEST._serialized_start = 44200 + _DELETEWORKFLOWRULEREQUEST._serialized_end = 44263 + _DELETEWORKFLOWRULERESPONSE._serialized_start = 44265 + _DELETEWORKFLOWRULERESPONSE._serialized_end = 44293 + _LISTWORKFLOWRULESREQUEST._serialized_start = 44295 + _LISTWORKFLOWRULESREQUEST._serialized_end = 44365 + _LISTWORKFLOWRULESRESPONSE._serialized_start = 44367 + _LISTWORKFLOWRULESRESPONSE._serialized_end = 44471 + _TRIGGERWORKFLOWRULEREQUEST._serialized_start = 44474 + _TRIGGERWORKFLOWRULEREQUEST._serialized_end = 44680 + _TRIGGERWORKFLOWRULERESPONSE._serialized_start = 44682 + _TRIGGERWORKFLOWRULERESPONSE._serialized_end = 44728 + _RECORDWORKERHEARTBEATREQUEST._serialized_start = 44731 + _RECORDWORKERHEARTBEATREQUEST._serialized_end = 44886 + _RECORDWORKERHEARTBEATRESPONSE._serialized_start = 44888 + _RECORDWORKERHEARTBEATRESPONSE._serialized_end = 44919 + _LISTWORKERSREQUEST._serialized_start = 44921 + _LISTWORKERSREQUEST._serialized_end = 45019 + _LISTWORKERSRESPONSE._serialized_start = 45022 + _LISTWORKERSRESPONSE._serialized_end = 45187 + _UPDATETASKQUEUECONFIGREQUEST._serialized_start = 45190 + _UPDATETASKQUEUECONFIGREQUEST._serialized_end = 45915 + _UPDATETASKQUEUECONFIGREQUEST_RATELIMITUPDATE._serialized_start = 45757 + _UPDATETASKQUEUECONFIGREQUEST_RATELIMITUPDATE._serialized_end = 45848 _UPDATETASKQUEUECONFIGREQUEST_SETFAIRNESSWEIGHTOVERRIDESENTRY._serialized_start = ( - 43312 + 45850 ) _UPDATETASKQUEUECONFIGREQUEST_SETFAIRNESSWEIGHTOVERRIDESENTRY._serialized_end = ( - 43377 + 45915 ) - _UPDATETASKQUEUECONFIGRESPONSE._serialized_start = 43379 - _UPDATETASKQUEUECONFIGRESPONSE._serialized_end = 43470 - _FETCHWORKERCONFIGREQUEST._serialized_start = 43473 - _FETCHWORKERCONFIGREQUEST._serialized_end = 43631 - _FETCHWORKERCONFIGRESPONSE._serialized_start = 43633 - _FETCHWORKERCONFIGRESPONSE._serialized_end = 43718 - _UPDATEWORKERCONFIGREQUEST._serialized_start = 43721 - _UPDATEWORKERCONFIGREQUEST._serialized_end = 43987 - _UPDATEWORKERCONFIGRESPONSE._serialized_start = 43989 - _UPDATEWORKERCONFIGRESPONSE._serialized_end = 44089 - _DESCRIBEWORKERREQUEST._serialized_start = 44091 - _DESCRIBEWORKERREQUEST._serialized_end = 44162 - _DESCRIBEWORKERRESPONSE._serialized_start = 44164 - _DESCRIBEWORKERRESPONSE._serialized_end = 44245 - _PAUSEWORKFLOWEXECUTIONREQUEST._serialized_start = 44248 - _PAUSEWORKFLOWEXECUTIONREQUEST._serialized_end = 44389 - _PAUSEWORKFLOWEXECUTIONRESPONSE._serialized_start = 44391 - _PAUSEWORKFLOWEXECUTIONRESPONSE._serialized_end = 44423 - _UNPAUSEWORKFLOWEXECUTIONREQUEST._serialized_start = 44426 - _UNPAUSEWORKFLOWEXECUTIONREQUEST._serialized_end = 44569 - _UNPAUSEWORKFLOWEXECUTIONRESPONSE._serialized_start = 44571 - _UNPAUSEWORKFLOWEXECUTIONRESPONSE._serialized_end = 44605 - _STARTACTIVITYEXECUTIONREQUEST._serialized_start = 44608 - _STARTACTIVITYEXECUTIONREQUEST._serialized_end = 45556 - _STARTACTIVITYEXECUTIONRESPONSE._serialized_start = 45558 - _STARTACTIVITYEXECUTIONRESPONSE._serialized_end = 45623 - _DESCRIBEACTIVITYEXECUTIONREQUEST._serialized_start = 45626 - _DESCRIBEACTIVITYEXECUTIONREQUEST._serialized_end = 45789 - _DESCRIBEACTIVITYEXECUTIONRESPONSE._serialized_start = 45792 - _DESCRIBEACTIVITYEXECUTIONRESPONSE._serialized_end = 46049 - _POLLACTIVITYEXECUTIONREQUEST._serialized_start = 46051 - _POLLACTIVITYEXECUTIONREQUEST._serialized_end = 46137 - _POLLACTIVITYEXECUTIONRESPONSE._serialized_start = 46139 - _POLLACTIVITYEXECUTIONRESPONSE._serialized_end = 46255 - _LISTACTIVITYEXECUTIONSREQUEST._serialized_start = 46257 - _LISTACTIVITYEXECUTIONSREQUEST._serialized_end = 46366 - _LISTACTIVITYEXECUTIONSRESPONSE._serialized_start = 46369 - _LISTACTIVITYEXECUTIONSRESPONSE._serialized_end = 46499 - _COUNTACTIVITYEXECUTIONSREQUEST._serialized_start = 46501 - _COUNTACTIVITYEXECUTIONSREQUEST._serialized_end = 46567 - _COUNTACTIVITYEXECUTIONSRESPONSE._serialized_start = 46570 - _COUNTACTIVITYEXECUTIONSRESPONSE._serialized_end = 46807 - _COUNTACTIVITYEXECUTIONSRESPONSE_AGGREGATIONGROUP._serialized_start = 18980 - _COUNTACTIVITYEXECUTIONSRESPONSE_AGGREGATIONGROUP._serialized_end = 19068 - _REQUESTCANCELACTIVITYEXECUTIONREQUEST._serialized_start = 46810 - _REQUESTCANCELACTIVITYEXECUTIONREQUEST._serialized_end = 46959 - _REQUESTCANCELACTIVITYEXECUTIONRESPONSE._serialized_start = 46961 - _REQUESTCANCELACTIVITYEXECUTIONRESPONSE._serialized_end = 47001 - _TERMINATEACTIVITYEXECUTIONREQUEST._serialized_start = 47004 - _TERMINATEACTIVITYEXECUTIONREQUEST._serialized_end = 47149 - _TERMINATEACTIVITYEXECUTIONRESPONSE._serialized_start = 47151 - _TERMINATEACTIVITYEXECUTIONRESPONSE._serialized_end = 47187 - _DELETEACTIVITYEXECUTIONREQUEST._serialized_start = 47189 - _DELETEACTIVITYEXECUTIONREQUEST._serialized_end = 47277 - _DELETEACTIVITYEXECUTIONRESPONSE._serialized_start = 47279 - _DELETEACTIVITYEXECUTIONRESPONSE._serialized_end = 47312 + _UPDATETASKQUEUECONFIGRESPONSE._serialized_start = 45917 + _UPDATETASKQUEUECONFIGRESPONSE._serialized_end = 46008 + _FETCHWORKERCONFIGREQUEST._serialized_start = 46011 + _FETCHWORKERCONFIGREQUEST._serialized_end = 46169 + _FETCHWORKERCONFIGRESPONSE._serialized_start = 46171 + _FETCHWORKERCONFIGRESPONSE._serialized_end = 46256 + _UPDATEWORKERCONFIGREQUEST._serialized_start = 46259 + _UPDATEWORKERCONFIGREQUEST._serialized_end = 46525 + _UPDATEWORKERCONFIGRESPONSE._serialized_start = 46527 + _UPDATEWORKERCONFIGRESPONSE._serialized_end = 46627 + _DESCRIBEWORKERREQUEST._serialized_start = 46629 + _DESCRIBEWORKERREQUEST._serialized_end = 46700 + _DESCRIBEWORKERRESPONSE._serialized_start = 46702 + _DESCRIBEWORKERRESPONSE._serialized_end = 46783 + _PAUSEWORKFLOWEXECUTIONREQUEST._serialized_start = 46786 + _PAUSEWORKFLOWEXECUTIONREQUEST._serialized_end = 46927 + _PAUSEWORKFLOWEXECUTIONRESPONSE._serialized_start = 46929 + _PAUSEWORKFLOWEXECUTIONRESPONSE._serialized_end = 46961 + _UNPAUSEWORKFLOWEXECUTIONREQUEST._serialized_start = 46964 + _UNPAUSEWORKFLOWEXECUTIONREQUEST._serialized_end = 47107 + _UNPAUSEWORKFLOWEXECUTIONRESPONSE._serialized_start = 47109 + _UNPAUSEWORKFLOWEXECUTIONRESPONSE._serialized_end = 47143 + _STARTACTIVITYEXECUTIONREQUEST._serialized_start = 47146 + _STARTACTIVITYEXECUTIONREQUEST._serialized_end = 48323 + _STARTACTIVITYEXECUTIONRESPONSE._serialized_start = 48325 + _STARTACTIVITYEXECUTIONRESPONSE._serialized_end = 48434 + _DESCRIBEACTIVITYEXECUTIONREQUEST._serialized_start = 48437 + _DESCRIBEACTIVITYEXECUTIONREQUEST._serialized_end = 48600 + _DESCRIBEACTIVITYEXECUTIONRESPONSE._serialized_start = 48603 + _DESCRIBEACTIVITYEXECUTIONRESPONSE._serialized_end = 48919 + _POLLACTIVITYEXECUTIONREQUEST._serialized_start = 48921 + _POLLACTIVITYEXECUTIONREQUEST._serialized_end = 49007 + _POLLACTIVITYEXECUTIONRESPONSE._serialized_start = 49009 + _POLLACTIVITYEXECUTIONRESPONSE._serialized_end = 49125 + _LISTACTIVITYEXECUTIONSREQUEST._serialized_start = 49127 + _LISTACTIVITYEXECUTIONSREQUEST._serialized_end = 49236 + _LISTACTIVITYEXECUTIONSRESPONSE._serialized_start = 49239 + _LISTACTIVITYEXECUTIONSRESPONSE._serialized_end = 49369 + _STARTNEXUSOPERATIONEXECUTIONREQUEST._serialized_start = 49372 + _STARTNEXUSOPERATIONEXECUTIONREQUEST._serialized_end = 50221 + _STARTNEXUSOPERATIONEXECUTIONREQUEST_NEXUSHEADERENTRY._serialized_start = 50171 + _STARTNEXUSOPERATIONEXECUTIONREQUEST_NEXUSHEADERENTRY._serialized_end = 50221 + _STARTNEXUSOPERATIONEXECUTIONRESPONSE._serialized_start = 50223 + _STARTNEXUSOPERATIONEXECUTIONRESPONSE._serialized_end = 50294 + _DESCRIBENEXUSOPERATIONEXECUTIONREQUEST._serialized_start = 50297 + _DESCRIBENEXUSOPERATIONEXECUTIONREQUEST._serialized_end = 50467 + _DESCRIBENEXUSOPERATIONEXECUTIONRESPONSE._serialized_start = 50470 + _DESCRIBENEXUSOPERATIONEXECUTIONRESPONSE._serialized_end = 50781 + _POLLNEXUSOPERATIONEXECUTIONREQUEST._serialized_start = 50784 + _POLLNEXUSOPERATIONEXECUTIONREQUEST._serialized_end = 50945 + _POLLNEXUSOPERATIONEXECUTIONRESPONSE._serialized_start = 50948 + _POLLNEXUSOPERATIONEXECUTIONRESPONSE._serialized_end = 51209 + _LISTNEXUSOPERATIONEXECUTIONSREQUEST._serialized_start = 51211 + _LISTNEXUSOPERATIONEXECUTIONSREQUEST._serialized_end = 51326 + _LISTNEXUSOPERATIONEXECUTIONSRESPONSE._serialized_start = 51329 + _LISTNEXUSOPERATIONEXECUTIONSRESPONSE._serialized_end = 51468 + _COUNTACTIVITYEXECUTIONSREQUEST._serialized_start = 51470 + _COUNTACTIVITYEXECUTIONSREQUEST._serialized_end = 51536 + _COUNTACTIVITYEXECUTIONSRESPONSE._serialized_start = 51539 + _COUNTACTIVITYEXECUTIONSRESPONSE._serialized_end = 51776 + _COUNTACTIVITYEXECUTIONSRESPONSE_AGGREGATIONGROUP._serialized_start = 19653 + _COUNTACTIVITYEXECUTIONSRESPONSE_AGGREGATIONGROUP._serialized_end = 19741 + _COUNTNEXUSOPERATIONEXECUTIONSREQUEST._serialized_start = 51778 + _COUNTNEXUSOPERATIONEXECUTIONSREQUEST._serialized_end = 51850 + _COUNTNEXUSOPERATIONEXECUTIONSRESPONSE._serialized_start = 51853 + _COUNTNEXUSOPERATIONEXECUTIONSRESPONSE._serialized_end = 52102 + _COUNTNEXUSOPERATIONEXECUTIONSRESPONSE_AGGREGATIONGROUP._serialized_start = 19653 + _COUNTNEXUSOPERATIONEXECUTIONSRESPONSE_AGGREGATIONGROUP._serialized_end = 19741 + _REQUESTCANCELACTIVITYEXECUTIONREQUEST._serialized_start = 52105 + _REQUESTCANCELACTIVITYEXECUTIONREQUEST._serialized_end = 52254 + _REQUESTCANCELACTIVITYEXECUTIONRESPONSE._serialized_start = 52256 + _REQUESTCANCELACTIVITYEXECUTIONRESPONSE._serialized_end = 52296 + _TERMINATEACTIVITYEXECUTIONREQUEST._serialized_start = 52299 + _TERMINATEACTIVITYEXECUTIONREQUEST._serialized_end = 52444 + _TERMINATEACTIVITYEXECUTIONRESPONSE._serialized_start = 52446 + _TERMINATEACTIVITYEXECUTIONRESPONSE._serialized_end = 52482 + _DELETEACTIVITYEXECUTIONREQUEST._serialized_start = 52484 + _DELETEACTIVITYEXECUTIONREQUEST._serialized_end = 52572 + _DELETEACTIVITYEXECUTIONRESPONSE._serialized_start = 52574 + _DELETEACTIVITYEXECUTIONRESPONSE._serialized_end = 52607 + _REQUESTCANCELNEXUSOPERATIONEXECUTIONREQUEST._serialized_start = 52610 + _REQUESTCANCELNEXUSOPERATIONEXECUTIONREQUEST._serialized_end = 52766 + _REQUESTCANCELNEXUSOPERATIONEXECUTIONRESPONSE._serialized_start = 52768 + _REQUESTCANCELNEXUSOPERATIONEXECUTIONRESPONSE._serialized_end = 52814 + _TERMINATENEXUSOPERATIONEXECUTIONREQUEST._serialized_start = 52817 + _TERMINATENEXUSOPERATIONEXECUTIONREQUEST._serialized_end = 52969 + _TERMINATENEXUSOPERATIONEXECUTIONRESPONSE._serialized_start = 52971 + _TERMINATENEXUSOPERATIONEXECUTIONRESPONSE._serialized_end = 53013 + _DELETENEXUSOPERATIONEXECUTIONREQUEST._serialized_start = 53015 + _DELETENEXUSOPERATIONEXECUTIONREQUEST._serialized_end = 53110 + _DELETENEXUSOPERATIONEXECUTIONRESPONSE._serialized_start = 53112 + _DELETENEXUSOPERATIONEXECUTIONRESPONSE._serialized_end = 53151 # @@protoc_insertion_point(module_scope) diff --git a/temporalio/api/workflowservice/v1/request_response_pb2.pyi b/temporalio/api/workflowservice/v1/request_response_pb2.pyi index 7facbef4d..98b0c046e 100644 --- a/temporalio/api/workflowservice/v1/request_response_pb2.pyi +++ b/temporalio/api/workflowservice/v1/request_response_pb2.pyi @@ -18,6 +18,7 @@ import temporalio.api.activity.v1.message_pb2 import temporalio.api.batch.v1.message_pb2 import temporalio.api.command.v1.message_pb2 import temporalio.api.common.v1.message_pb2 +import temporalio.api.compute.v1.config_pb2 import temporalio.api.deployment.v1.message_pb2 import temporalio.api.enums.v1.activity_pb2 import temporalio.api.enums.v1.batch_operation_pb2 @@ -25,6 +26,7 @@ import temporalio.api.enums.v1.common_pb2 import temporalio.api.enums.v1.deployment_pb2 import temporalio.api.enums.v1.failed_cause_pb2 import temporalio.api.enums.v1.namespace_pb2 +import temporalio.api.enums.v1.nexus_pb2 import temporalio.api.enums.v1.query_pb2 import temporalio.api.enums.v1.reset_pb2 import temporalio.api.enums.v1.task_queue_pb2 @@ -551,6 +553,7 @@ class StartWorkflowExecutionRequest(google.protobuf.message.Message): ON_CONFLICT_OPTIONS_FIELD_NUMBER: builtins.int PRIORITY_FIELD_NUMBER: builtins.int EAGER_WORKER_DEPLOYMENT_OPTIONS_FIELD_NUMBER: builtins.int + TIME_SKIPPING_CONFIG_FIELD_NUMBER: builtins.int namespace: builtins.str workflow_id: builtins.str @property @@ -672,6 +675,11 @@ class StartWorkflowExecutionRequest(google.protobuf.message.Message): self, ) -> temporalio.api.deployment.v1.message_pb2.WorkerDeploymentOptions: """Deployment Options of the worker who will process the eager task. Passed when `request_eager_execution=true`.""" + @property + def time_skipping_config( + self, + ) -> temporalio.api.workflow.v1.message_pb2.TimeSkippingConfig: + """Time-skipping configuration. If not set, time skipping is disabled.""" def __init__( self, *, @@ -713,6 +721,8 @@ class StartWorkflowExecutionRequest(google.protobuf.message.Message): priority: temporalio.api.common.v1.message_pb2.Priority | None = ..., eager_worker_deployment_options: temporalio.api.deployment.v1.message_pb2.WorkerDeploymentOptions | None = ..., + time_skipping_config: temporalio.api.workflow.v1.message_pb2.TimeSkippingConfig + | None = ..., ) -> None: ... def HasField( self, @@ -739,6 +749,8 @@ class StartWorkflowExecutionRequest(google.protobuf.message.Message): b"search_attributes", "task_queue", b"task_queue", + "time_skipping_config", + b"time_skipping_config", "user_metadata", b"user_metadata", "versioning_override", @@ -794,6 +806,8 @@ class StartWorkflowExecutionRequest(google.protobuf.message.Message): b"search_attributes", "task_queue", b"task_queue", + "time_skipping_config", + b"time_skipping_config", "user_metadata", b"user_metadata", "versioning_override", @@ -1068,20 +1082,32 @@ class PollWorkflowTaskQueueRequest(google.protobuf.message.Message): NAMESPACE_FIELD_NUMBER: builtins.int TASK_QUEUE_FIELD_NUMBER: builtins.int + POLLER_GROUP_ID_FIELD_NUMBER: builtins.int IDENTITY_FIELD_NUMBER: builtins.int WORKER_INSTANCE_KEY_FIELD_NUMBER: builtins.int + WORKER_CONTROL_TASK_QUEUE_FIELD_NUMBER: builtins.int BINARY_CHECKSUM_FIELD_NUMBER: builtins.int WORKER_VERSION_CAPABILITIES_FIELD_NUMBER: builtins.int DEPLOYMENT_OPTIONS_FIELD_NUMBER: builtins.int namespace: builtins.str @property def task_queue(self) -> temporalio.api.taskqueue.v1.message_pb2.TaskQueue: ... + poller_group_id: builtins.str + """Unless this is the first poll, the client must pass one of the poller group IDs received in + `poller_group_infos` of the last the PollWorkflowTaskQueueResponse according to the + instructions. If not set, the poll is routed randomly which can cause it being blocked + without receiving a task while the queue actually has tasks in another server location. + """ identity: builtins.str """The identity of the worker/client who is polling this task queue""" worker_instance_key: builtins.str """A unique key for this worker instance, used for tracking worker lifecycle. This is guaranteed to be unique, whereas identity is not guaranteed to be unique. """ + worker_control_task_queue: builtins.str + """A dedicated per-worker Nexus task queue on which the server sends control + tasks (e.g. activity cancellation) to this specific worker instance. + """ binary_checksum: builtins.str """Deprecated. Use deployment_options instead. Each worker process should provide an ID unique to the specific set of code it is running @@ -1099,16 +1125,16 @@ class PollWorkflowTaskQueueRequest(google.protobuf.message.Message): def deployment_options( self, ) -> temporalio.api.deployment.v1.message_pb2.WorkerDeploymentOptions: - """Worker deployment options that user has set in the worker. - Experimental. Worker Deployments are experimental and might significantly change in the future. - """ + """Worker deployment options that user has set in the worker.""" def __init__( self, *, namespace: builtins.str = ..., task_queue: temporalio.api.taskqueue.v1.message_pb2.TaskQueue | None = ..., + poller_group_id: builtins.str = ..., identity: builtins.str = ..., worker_instance_key: builtins.str = ..., + worker_control_task_queue: builtins.str = ..., binary_checksum: builtins.str = ..., worker_version_capabilities: temporalio.api.common.v1.message_pb2.WorkerVersionCapabilities | None = ..., @@ -1137,8 +1163,12 @@ class PollWorkflowTaskQueueRequest(google.protobuf.message.Message): b"identity", "namespace", b"namespace", + "poller_group_id", + b"poller_group_id", "task_queue", b"task_queue", + "worker_control_task_queue", + b"worker_control_task_queue", "worker_instance_key", b"worker_instance_key", "worker_version_capabilities", @@ -1189,6 +1219,8 @@ class PollWorkflowTaskQueueResponse(google.protobuf.message.Message): QUERIES_FIELD_NUMBER: builtins.int MESSAGES_FIELD_NUMBER: builtins.int POLLER_SCALING_DECISION_FIELD_NUMBER: builtins.int + POLLER_GROUP_ID_FIELD_NUMBER: builtins.int + POLLER_GROUP_INFOS_FIELD_NUMBER: builtins.int task_token: builtins.bytes """A unique identifier for this task""" @property @@ -1272,6 +1304,23 @@ class PollWorkflowTaskQueueResponse(google.protobuf.message.Message): self, ) -> temporalio.api.taskqueue.v1.message_pb2.PollerScalingDecision: """Server-advised information the SDK may use to adjust its poller count.""" + poller_group_id: builtins.str + """This poller group ID identifies the owner of the workflow task awaiting for query response. + Corresponding RespondQueryTaskCompleted should pass this value for proper routing. + """ + @property + def poller_group_infos( + self, + ) -> google.protobuf.internal.containers.RepeatedCompositeFieldContainer[ + temporalio.api.taskqueue.v1.message_pb2.PollerGroupInfo + ]: + """The weighted list of poller groups IDs that client should use for future polls to this task + queue. Client is expected to: + 1. Maintain minimum number of pollers no less than the number of groups. + 2. Try to assign the next poll to a group without any pending polls, + 3. If every group has some pending polls, assign the next poll to a group randomly + according to the weights. + """ def __init__( self, *, @@ -1300,6 +1349,11 @@ class PollWorkflowTaskQueueResponse(google.protobuf.message.Message): | None = ..., poller_scaling_decision: temporalio.api.taskqueue.v1.message_pb2.PollerScalingDecision | None = ..., + poller_group_id: builtins.str = ..., + poller_group_infos: collections.abc.Iterable[ + temporalio.api.taskqueue.v1.message_pb2.PollerGroupInfo + ] + | None = ..., ) -> None: ... def HasField( self, @@ -1335,6 +1389,10 @@ class PollWorkflowTaskQueueResponse(google.protobuf.message.Message): b"messages", "next_page_token", b"next_page_token", + "poller_group_id", + b"poller_group_id", + "poller_group_infos", + b"poller_group_infos", "poller_scaling_decision", b"poller_scaling_decision", "previous_started_event_id", @@ -1432,6 +1490,8 @@ class RespondWorkflowTaskCompletedRequest(google.protobuf.message.Message): DEPLOYMENT_FIELD_NUMBER: builtins.int VERSIONING_BEHAVIOR_FIELD_NUMBER: builtins.int DEPLOYMENT_OPTIONS_FIELD_NUMBER: builtins.int + WORKER_INSTANCE_KEY_FIELD_NUMBER: builtins.int + WORKER_CONTROL_TASK_QUEUE_FIELD_NUMBER: builtins.int task_token: builtins.bytes """The task token as received in `PollWorkflowTaskQueueResponse`""" @property @@ -1522,6 +1582,14 @@ class RespondWorkflowTaskCompletedRequest(google.protobuf.message.Message): self, ) -> temporalio.api.deployment.v1.message_pb2.WorkerDeploymentOptions: """Worker deployment options that user has set in the worker.""" + worker_instance_key: builtins.str + """A unique key for this worker instance, used for tracking worker lifecycle. + This is guaranteed to be unique, whereas identity is not guaranteed to be unique. + """ + worker_control_task_queue: builtins.str + """A dedicated per-worker Nexus task queue on which the server sends control + tasks (e.g. activity cancellation) to this specific worker instance. + """ def __init__( self, *, @@ -1558,6 +1626,8 @@ class RespondWorkflowTaskCompletedRequest(google.protobuf.message.Message): versioning_behavior: temporalio.api.enums.v1.workflow_pb2.VersioningBehavior.ValueType = ..., deployment_options: temporalio.api.deployment.v1.message_pb2.WorkerDeploymentOptions | None = ..., + worker_instance_key: builtins.str = ..., + worker_control_task_queue: builtins.str = ..., ) -> None: ... def HasField( self, @@ -1615,6 +1685,10 @@ class RespondWorkflowTaskCompletedRequest(google.protobuf.message.Message): b"task_token", "versioning_behavior", b"versioning_behavior", + "worker_control_task_queue", + b"worker_control_task_queue", + "worker_instance_key", + b"worker_instance_key", "worker_version_stamp", b"worker_version_stamp", ], @@ -1802,20 +1876,32 @@ class PollActivityTaskQueueRequest(google.protobuf.message.Message): NAMESPACE_FIELD_NUMBER: builtins.int TASK_QUEUE_FIELD_NUMBER: builtins.int + POLLER_GROUP_ID_FIELD_NUMBER: builtins.int IDENTITY_FIELD_NUMBER: builtins.int WORKER_INSTANCE_KEY_FIELD_NUMBER: builtins.int + WORKER_CONTROL_TASK_QUEUE_FIELD_NUMBER: builtins.int TASK_QUEUE_METADATA_FIELD_NUMBER: builtins.int WORKER_VERSION_CAPABILITIES_FIELD_NUMBER: builtins.int DEPLOYMENT_OPTIONS_FIELD_NUMBER: builtins.int namespace: builtins.str @property def task_queue(self) -> temporalio.api.taskqueue.v1.message_pb2.TaskQueue: ... + poller_group_id: builtins.str + """Unless this is the first poll, the client must pass one of the poller group IDs received in + `poller_group_infos` of the last the PollActivityTaskQueueResponse according to the + instructions. If not set, the poll is routed randomly which can cause it being blocked + without receiving a task while the queue actually has tasks in another server location. + """ identity: builtins.str """The identity of the worker/client""" worker_instance_key: builtins.str """A unique key for this worker instance, used for tracking worker lifecycle. This is guaranteed to be unique, whereas identity is not guaranteed to be unique. """ + worker_control_task_queue: builtins.str + """A dedicated per-worker Nexus task queue on which the server sends control + tasks (e.g. activity cancellation) to this specific worker instance. + """ @property def task_queue_metadata( self, @@ -1838,8 +1924,10 @@ class PollActivityTaskQueueRequest(google.protobuf.message.Message): *, namespace: builtins.str = ..., task_queue: temporalio.api.taskqueue.v1.message_pb2.TaskQueue | None = ..., + poller_group_id: builtins.str = ..., identity: builtins.str = ..., worker_instance_key: builtins.str = ..., + worker_control_task_queue: builtins.str = ..., task_queue_metadata: temporalio.api.taskqueue.v1.message_pb2.TaskQueueMetadata | None = ..., worker_version_capabilities: temporalio.api.common.v1.message_pb2.WorkerVersionCapabilities @@ -1869,10 +1957,14 @@ class PollActivityTaskQueueRequest(google.protobuf.message.Message): b"identity", "namespace", b"namespace", + "poller_group_id", + b"poller_group_id", "task_queue", b"task_queue", "task_queue_metadata", b"task_queue_metadata", + "worker_control_task_queue", + b"worker_control_task_queue", "worker_instance_key", b"worker_instance_key", "worker_version_capabilities", @@ -1905,6 +1997,7 @@ class PollActivityTaskQueueResponse(google.protobuf.message.Message): POLLER_SCALING_DECISION_FIELD_NUMBER: builtins.int PRIORITY_FIELD_NUMBER: builtins.int ACTIVITY_RUN_ID_FIELD_NUMBER: builtins.int + POLLER_GROUP_INFOS_FIELD_NUMBER: builtins.int task_token: builtins.bytes """A unique identifier for this task""" workflow_namespace: builtins.str @@ -1985,6 +2078,19 @@ class PollActivityTaskQueueResponse(google.protobuf.message.Message): """Priority metadata""" activity_run_id: builtins.str """The run ID of the activity execution, only set for standalone activities.""" + @property + def poller_group_infos( + self, + ) -> google.protobuf.internal.containers.RepeatedCompositeFieldContainer[ + temporalio.api.taskqueue.v1.message_pb2.PollerGroupInfo + ]: + """The weighted list of poller groups IDs that client should use for future polls to this task + queue. Client is expected to: + 1. Maintain minimum number of pollers no less than the number of groups. + 2. Try to assign the next poll to a group without any pending polls, + 3. If every group has some pending polls, assign the next poll to a group randomly + according to the weights. + """ def __init__( self, *, @@ -2011,6 +2117,10 @@ class PollActivityTaskQueueResponse(google.protobuf.message.Message): | None = ..., priority: temporalio.api.common.v1.message_pb2.Priority | None = ..., activity_run_id: builtins.str = ..., + poller_group_infos: collections.abc.Iterable[ + temporalio.api.taskqueue.v1.message_pb2.PollerGroupInfo + ] + | None = ..., ) -> None: ... def HasField( self, @@ -2068,6 +2178,8 @@ class PollActivityTaskQueueResponse(google.protobuf.message.Message): b"heartbeat_timeout", "input", b"input", + "poller_group_infos", + b"poller_group_infos", "poller_scaling_decision", b"poller_scaling_decision", "priority", @@ -3054,8 +3166,23 @@ global___SignalWorkflowExecutionRequest = SignalWorkflowExecutionRequest class SignalWorkflowExecutionResponse(google.protobuf.message.Message): DESCRIPTOR: google.protobuf.descriptor.Descriptor + LINK_FIELD_NUMBER: builtins.int + @property + def link(self) -> temporalio.api.common.v1.message_pb2.Link: + """Link to be associated with the WorkflowExecutionSignaled event. + Added on the response to propagate the backlink. + Available from Temporal server 1.31 and up. + """ def __init__( self, + *, + link: temporalio.api.common.v1.message_pb2.Link | None = ..., + ) -> None: ... + def HasField( + self, field_name: typing_extensions.Literal["link", b"link"] + ) -> builtins.bool: ... + def ClearField( + self, field_name: typing_extensions.Literal["link", b"link"] ) -> None: ... global___SignalWorkflowExecutionResponse = SignalWorkflowExecutionResponse @@ -3088,6 +3215,7 @@ class SignalWithStartWorkflowExecutionRequest(google.protobuf.message.Message): LINKS_FIELD_NUMBER: builtins.int VERSIONING_OVERRIDE_FIELD_NUMBER: builtins.int PRIORITY_FIELD_NUMBER: builtins.int + TIME_SKIPPING_CONFIG_FIELD_NUMBER: builtins.int namespace: builtins.str workflow_id: builtins.str @property @@ -3179,6 +3307,11 @@ class SignalWithStartWorkflowExecutionRequest(google.protobuf.message.Message): @property def priority(self) -> temporalio.api.common.v1.message_pb2.Priority: """Priority metadata""" + @property + def time_skipping_config( + self, + ) -> temporalio.api.workflow.v1.message_pb2.TimeSkippingConfig: + """Time-skipping configuration. If not set, time skipping is disabled.""" def __init__( self, *, @@ -3211,6 +3344,8 @@ class SignalWithStartWorkflowExecutionRequest(google.protobuf.message.Message): versioning_override: temporalio.api.workflow.v1.message_pb2.VersioningOverride | None = ..., priority: temporalio.api.common.v1.message_pb2.Priority | None = ..., + time_skipping_config: temporalio.api.workflow.v1.message_pb2.TimeSkippingConfig + | None = ..., ) -> None: ... def HasField( self, @@ -3231,6 +3366,8 @@ class SignalWithStartWorkflowExecutionRequest(google.protobuf.message.Message): b"signal_input", "task_queue", b"task_queue", + "time_skipping_config", + b"time_skipping_config", "user_metadata", b"user_metadata", "versioning_override", @@ -3280,6 +3417,8 @@ class SignalWithStartWorkflowExecutionRequest(google.protobuf.message.Message): b"signal_name", "task_queue", b"task_queue", + "time_skipping_config", + b"time_skipping_config", "user_metadata", b"user_metadata", "versioning_override", @@ -3312,20 +3451,31 @@ class SignalWithStartWorkflowExecutionResponse(google.protobuf.message.Message): RUN_ID_FIELD_NUMBER: builtins.int STARTED_FIELD_NUMBER: builtins.int + SIGNAL_LINK_FIELD_NUMBER: builtins.int run_id: builtins.str """The run id of the workflow that was started - or just signaled, if it was already running.""" started: builtins.bool """If true, a new workflow was started.""" + @property + def signal_link(self) -> temporalio.api.common.v1.message_pb2.Link: + """Link to be associated with the WorkflowExecutionSignaled event. + Added on the response to propagate the backlink. + Available from Temporal server 1.31 and up. + """ def __init__( self, *, run_id: builtins.str = ..., started: builtins.bool = ..., + signal_link: temporalio.api.common.v1.message_pb2.Link | None = ..., ) -> None: ... + def HasField( + self, field_name: typing_extensions.Literal["signal_link", b"signal_link"] + ) -> builtins.bool: ... def ClearField( self, field_name: typing_extensions.Literal[ - "run_id", b"run_id", "started", b"started" + "run_id", b"run_id", "signal_link", b"signal_link", "started", b"started" ], ) -> None: ... @@ -4145,6 +4295,7 @@ class RespondQueryTaskCompletedRequest(google.protobuf.message.Message): NAMESPACE_FIELD_NUMBER: builtins.int FAILURE_FIELD_NUMBER: builtins.int CAUSE_FIELD_NUMBER: builtins.int + POLLER_GROUP_ID_FIELD_NUMBER: builtins.int task_token: builtins.bytes completed_type: temporalio.api.enums.v1.query_pb2.QueryResultType.ValueType @property @@ -4173,6 +4324,10 @@ class RespondQueryTaskCompletedRequest(google.protobuf.message.Message): """Why did the task fail? It's important to note that many of the variants in this enum cannot apply to worker responses. See the type's doc for more. """ + poller_group_id: builtins.str + """Client must forward the poller_group_id received in PollWorkflowTaskQueueResponse for proper + routing of the response. + """ def __init__( self, *, @@ -4183,6 +4338,7 @@ class RespondQueryTaskCompletedRequest(google.protobuf.message.Message): namespace: builtins.str = ..., failure: temporalio.api.failure.v1.message_pb2.Failure | None = ..., cause: temporalio.api.enums.v1.failed_cause_pb2.WorkflowTaskFailedCause.ValueType = ..., + poller_group_id: builtins.str = ..., ) -> None: ... def HasField( self, @@ -4203,6 +4359,8 @@ class RespondQueryTaskCompletedRequest(google.protobuf.message.Message): b"failure", "namespace", b"namespace", + "poller_group_id", + b"poller_group_id", "query_result", b"query_result", "task_token", @@ -5038,6 +5196,7 @@ class GetSystemInfoResponse(google.protobuf.message.Message): SDK_METADATA_FIELD_NUMBER: builtins.int COUNT_GROUP_BY_EXECUTION_STATUS_FIELD_NUMBER: builtins.int NEXUS_FIELD_NUMBER: builtins.int + SERVER_SCALED_DEPLOYMENTS_FIELD_NUMBER: builtins.int signal_and_query_header: builtins.bool """True if signal and query headers are supported.""" internal_error_differentiation: builtins.bool @@ -5074,6 +5233,11 @@ class GetSystemInfoResponse(google.protobuf.message.Message): """True if the server supports Nexus operations. This flag is dependent both on server version and for Nexus to be enabled via server configuration. """ + server_scaled_deployments: builtins.bool + """True if the server supports server-scaled deployments. + This flag is dependent both on server version and for server-scaled deployments + to be enabled via server configuration. + """ def __init__( self, *, @@ -5088,6 +5252,7 @@ class GetSystemInfoResponse(google.protobuf.message.Message): sdk_metadata: builtins.bool = ..., count_group_by_execution_status: builtins.bool = ..., nexus: builtins.bool = ..., + server_scaled_deployments: builtins.bool = ..., ) -> None: ... def ClearField( self, @@ -5108,6 +5273,8 @@ class GetSystemInfoResponse(google.protobuf.message.Message): b"nexus", "sdk_metadata", b"sdk_metadata", + "server_scaled_deployments", + b"server_scaled_deployments", "signal_and_query_header", b"signal_and_query_header", "supports_schedules", @@ -5420,6 +5587,7 @@ class UpdateScheduleRequest(google.protobuf.message.Message): IDENTITY_FIELD_NUMBER: builtins.int REQUEST_ID_FIELD_NUMBER: builtins.int SEARCH_ATTRIBUTES_FIELD_NUMBER: builtins.int + MEMO_FIELD_NUMBER: builtins.int namespace: builtins.str """The namespace of the schedule to update.""" schedule_id: builtins.str @@ -5449,6 +5617,12 @@ class UpdateScheduleRequest(google.protobuf.message.Message): Note: you cannot only update the search attributes with `UpdateScheduleRequest`, you must also set the `schedule` field; otherwise, it will unset the schedule. """ + @property + def memo(self) -> temporalio.api.common.v1.message_pb2.Memo: + """Schedule memo to replace. If set, replaces the entire memo. + Do not set this field if you do not want to update the memo. + A non-null empty object will clear the memo. + """ def __init__( self, *, @@ -5460,11 +5634,17 @@ class UpdateScheduleRequest(google.protobuf.message.Message): request_id: builtins.str = ..., search_attributes: temporalio.api.common.v1.message_pb2.SearchAttributes | None = ..., + memo: temporalio.api.common.v1.message_pb2.Memo | None = ..., ) -> None: ... def HasField( self, field_name: typing_extensions.Literal[ - "schedule", b"schedule", "search_attributes", b"search_attributes" + "memo", + b"memo", + "schedule", + b"schedule", + "search_attributes", + b"search_attributes", ], ) -> builtins.bool: ... def ClearField( @@ -5474,6 +5654,8 @@ class UpdateScheduleRequest(google.protobuf.message.Message): b"conflict_token", "identity", b"identity", + "memo", + b"memo", "namespace", b"namespace", "request_id", @@ -7329,13 +7511,22 @@ class PollNexusTaskQueueRequest(google.protobuf.message.Message): DESCRIPTOR: google.protobuf.descriptor.Descriptor NAMESPACE_FIELD_NUMBER: builtins.int + TASK_QUEUE_FIELD_NUMBER: builtins.int + POLLER_GROUP_ID_FIELD_NUMBER: builtins.int IDENTITY_FIELD_NUMBER: builtins.int WORKER_INSTANCE_KEY_FIELD_NUMBER: builtins.int - TASK_QUEUE_FIELD_NUMBER: builtins.int WORKER_VERSION_CAPABILITIES_FIELD_NUMBER: builtins.int DEPLOYMENT_OPTIONS_FIELD_NUMBER: builtins.int WORKER_HEARTBEAT_FIELD_NUMBER: builtins.int namespace: builtins.str + @property + def task_queue(self) -> temporalio.api.taskqueue.v1.message_pb2.TaskQueue: ... + poller_group_id: builtins.str + """Unless this is the first poll, the client must pass one of the poller group IDs received in + `poller_group_infos` of the last the PollNexusTaskQueueResponse according to the + instructions. If not set, the poll is routed randomly which can cause it being blocked + without receiving a task while the queue actually has tasks in another server location. + """ identity: builtins.str """The identity of the client who initiated this request.""" worker_instance_key: builtins.str @@ -7343,8 +7534,6 @@ class PollNexusTaskQueueRequest(google.protobuf.message.Message): This is guaranteed to be unique, whereas identity is not guaranteed to be unique. """ @property - def task_queue(self) -> temporalio.api.taskqueue.v1.message_pb2.TaskQueue: ... - @property def worker_version_capabilities( self, ) -> temporalio.api.common.v1.message_pb2.WorkerVersionCapabilities: @@ -7368,9 +7557,10 @@ class PollNexusTaskQueueRequest(google.protobuf.message.Message): self, *, namespace: builtins.str = ..., + task_queue: temporalio.api.taskqueue.v1.message_pb2.TaskQueue | None = ..., + poller_group_id: builtins.str = ..., identity: builtins.str = ..., worker_instance_key: builtins.str = ..., - task_queue: temporalio.api.taskqueue.v1.message_pb2.TaskQueue | None = ..., worker_version_capabilities: temporalio.api.common.v1.message_pb2.WorkerVersionCapabilities | None = ..., deployment_options: temporalio.api.deployment.v1.message_pb2.WorkerDeploymentOptions @@ -7400,6 +7590,8 @@ class PollNexusTaskQueueRequest(google.protobuf.message.Message): b"identity", "namespace", b"namespace", + "poller_group_id", + b"poller_group_id", "task_queue", b"task_queue", "worker_heartbeat", @@ -7419,6 +7611,8 @@ class PollNexusTaskQueueResponse(google.protobuf.message.Message): TASK_TOKEN_FIELD_NUMBER: builtins.int REQUEST_FIELD_NUMBER: builtins.int POLLER_SCALING_DECISION_FIELD_NUMBER: builtins.int + POLLER_GROUP_ID_FIELD_NUMBER: builtins.int + POLLER_GROUP_INFOS_FIELD_NUMBER: builtins.int task_token: builtins.bytes """An opaque unique identifier for this task for correlating a completion request the embedded request.""" @property @@ -7429,6 +7623,25 @@ class PollNexusTaskQueueResponse(google.protobuf.message.Message): self, ) -> temporalio.api.taskqueue.v1.message_pb2.PollerScalingDecision: """Server-advised information the SDK may use to adjust its poller count.""" + poller_group_id: builtins.str + """This poller group ID identifies the owner of the nexus task awaiting for synchronous + response. + Corresponding `RespondNexusTaskCompleted` and `RespondNexusTaskFailed` calls should pass this + value for proper response routing. + """ + @property + def poller_group_infos( + self, + ) -> google.protobuf.internal.containers.RepeatedCompositeFieldContainer[ + temporalio.api.taskqueue.v1.message_pb2.PollerGroupInfo + ]: + """The weighted list of poller groups IDs that client should use for future polls to this task + queue. Client is expected to: + 1. Maintain minimum number of pollers no less than the number of groups. + 2. Try to assign the next poll to a group without any pending polls, + 3. If every group has some pending polls, assign the next poll to a group randomly + according to the weights. + """ def __init__( self, *, @@ -7436,6 +7649,11 @@ class PollNexusTaskQueueResponse(google.protobuf.message.Message): request: temporalio.api.nexus.v1.message_pb2.Request | None = ..., poller_scaling_decision: temporalio.api.taskqueue.v1.message_pb2.PollerScalingDecision | None = ..., + poller_group_id: builtins.str = ..., + poller_group_infos: collections.abc.Iterable[ + temporalio.api.taskqueue.v1.message_pb2.PollerGroupInfo + ] + | None = ..., ) -> None: ... def HasField( self, @@ -7446,6 +7664,10 @@ class PollNexusTaskQueueResponse(google.protobuf.message.Message): def ClearField( self, field_name: typing_extensions.Literal[ + "poller_group_id", + b"poller_group_id", + "poller_group_infos", + b"poller_group_infos", "poller_scaling_decision", b"poller_scaling_decision", "request", @@ -7464,6 +7686,7 @@ class RespondNexusTaskCompletedRequest(google.protobuf.message.Message): IDENTITY_FIELD_NUMBER: builtins.int TASK_TOKEN_FIELD_NUMBER: builtins.int RESPONSE_FIELD_NUMBER: builtins.int + POLLER_GROUP_ID_FIELD_NUMBER: builtins.int namespace: builtins.str identity: builtins.str """The identity of the client who initiated this request.""" @@ -7472,6 +7695,10 @@ class RespondNexusTaskCompletedRequest(google.protobuf.message.Message): @property def response(self) -> temporalio.api.nexus.v1.message_pb2.Response: """Embedded response to be translated into a frontend response.""" + poller_group_id: builtins.str + """Client must forward the poller_group_id received in PollNexusTaskQueueResponse for proper + routing of the response. + """ def __init__( self, *, @@ -7479,6 +7706,7 @@ class RespondNexusTaskCompletedRequest(google.protobuf.message.Message): identity: builtins.str = ..., task_token: builtins.bytes = ..., response: temporalio.api.nexus.v1.message_pb2.Response | None = ..., + poller_group_id: builtins.str = ..., ) -> None: ... def HasField( self, field_name: typing_extensions.Literal["response", b"response"] @@ -7490,6 +7718,8 @@ class RespondNexusTaskCompletedRequest(google.protobuf.message.Message): b"identity", "namespace", b"namespace", + "poller_group_id", + b"poller_group_id", "response", b"response", "task_token", @@ -7516,6 +7746,7 @@ class RespondNexusTaskFailedRequest(google.protobuf.message.Message): TASK_TOKEN_FIELD_NUMBER: builtins.int ERROR_FIELD_NUMBER: builtins.int FAILURE_FIELD_NUMBER: builtins.int + POLLER_GROUP_ID_FIELD_NUMBER: builtins.int namespace: builtins.str identity: builtins.str """The identity of the client who initiated this request.""" @@ -7527,6 +7758,10 @@ class RespondNexusTaskFailedRequest(google.protobuf.message.Message): @property def failure(self) -> temporalio.api.failure.v1.message_pb2.Failure: """The error the handler failed with. Must contain a NexusHandlerFailureInfo object.""" + poller_group_id: builtins.str + """Client must forward the poller_group_id received in PollNexusTaskQueueResponse for proper + routing of the response. + """ def __init__( self, *, @@ -7535,6 +7770,7 @@ class RespondNexusTaskFailedRequest(google.protobuf.message.Message): task_token: builtins.bytes = ..., error: temporalio.api.nexus.v1.message_pb2.HandlerError | None = ..., failure: temporalio.api.failure.v1.message_pb2.Failure | None = ..., + poller_group_id: builtins.str = ..., ) -> None: ... def HasField( self, @@ -7551,6 +7787,8 @@ class RespondNexusTaskFailedRequest(google.protobuf.message.Message): b"identity", "namespace", b"namespace", + "poller_group_id", + b"poller_group_id", "task_token", b"task_token", ], @@ -9033,6 +9271,68 @@ global___SetWorkerDeploymentRampingVersionResponse = ( SetWorkerDeploymentRampingVersionResponse ) +class CreateWorkerDeploymentRequest(google.protobuf.message.Message): + """Creates a new WorkerDeployment.""" + + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + NAMESPACE_FIELD_NUMBER: builtins.int + DEPLOYMENT_NAME_FIELD_NUMBER: builtins.int + IDENTITY_FIELD_NUMBER: builtins.int + REQUEST_ID_FIELD_NUMBER: builtins.int + namespace: builtins.str + deployment_name: builtins.str + """The name of the Worker Deployment to create. If a Worker Deployment with + this name already exists, an error will be returned. + """ + identity: builtins.str + """Optional. The identity of the client who initiated this request.""" + request_id: builtins.str + """A unique identifier for this create request for idempotence. Typically UUIDv4.""" + def __init__( + self, + *, + namespace: builtins.str = ..., + deployment_name: builtins.str = ..., + identity: builtins.str = ..., + request_id: builtins.str = ..., + ) -> None: ... + def ClearField( + self, + field_name: typing_extensions.Literal[ + "deployment_name", + b"deployment_name", + "identity", + b"identity", + "namespace", + b"namespace", + "request_id", + b"request_id", + ], + ) -> None: ... + +global___CreateWorkerDeploymentRequest = CreateWorkerDeploymentRequest + +class CreateWorkerDeploymentResponse(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + CONFLICT_TOKEN_FIELD_NUMBER: builtins.int + conflict_token: builtins.bytes + """This value is returned so that it can be optionally passed to APIs that + write to the WorkerDeployment state to ensure that the state did not + change between this API call and a future write. + """ + def __init__( + self, + *, + conflict_token: builtins.bytes = ..., + ) -> None: ... + def ClearField( + self, field_name: typing_extensions.Literal["conflict_token", b"conflict_token"] + ) -> None: ... + +global___CreateWorkerDeploymentResponse = CreateWorkerDeploymentResponse + class ListWorkerDeploymentsRequest(google.protobuf.message.Message): DESCRIPTOR: google.protobuf.descriptor.Descriptor @@ -9179,6 +9479,80 @@ class ListWorkerDeploymentsResponse(google.protobuf.message.Message): global___ListWorkerDeploymentsResponse = ListWorkerDeploymentsResponse +class CreateWorkerDeploymentVersionRequest(google.protobuf.message.Message): + """Creates a new WorkerDeploymentVersion.""" + + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + NAMESPACE_FIELD_NUMBER: builtins.int + DEPLOYMENT_VERSION_FIELD_NUMBER: builtins.int + COMPUTE_CONFIG_FIELD_NUMBER: builtins.int + IDENTITY_FIELD_NUMBER: builtins.int + REQUEST_ID_FIELD_NUMBER: builtins.int + namespace: builtins.str + @property + def deployment_version( + self, + ) -> temporalio.api.deployment.v1.message_pb2.WorkerDeploymentVersion: + """Required.""" + @property + def compute_config(self) -> temporalio.api.compute.v1.config_pb2.ComputeConfig: + """Optional. Contains the new worker compute configuration for the Worker + Deployment. Used for worker scale management. + """ + identity: builtins.str + """Optional. The identity of the client who initiated this request.""" + request_id: builtins.str + """A unique identifier for this create request for idempotence. Typically UUIDv4. + If a second request with the same ID is recieved, it is considered a successful no-op. + Retrying with a different request ID for the same deployment name + build ID is an error. + """ + def __init__( + self, + *, + namespace: builtins.str = ..., + deployment_version: temporalio.api.deployment.v1.message_pb2.WorkerDeploymentVersion + | None = ..., + compute_config: temporalio.api.compute.v1.config_pb2.ComputeConfig | None = ..., + identity: builtins.str = ..., + request_id: builtins.str = ..., + ) -> None: ... + def HasField( + self, + field_name: typing_extensions.Literal[ + "compute_config", + b"compute_config", + "deployment_version", + b"deployment_version", + ], + ) -> builtins.bool: ... + def ClearField( + self, + field_name: typing_extensions.Literal[ + "compute_config", + b"compute_config", + "deployment_version", + b"deployment_version", + "identity", + b"identity", + "namespace", + b"namespace", + "request_id", + b"request_id", + ], + ) -> None: ... + +global___CreateWorkerDeploymentVersionRequest = CreateWorkerDeploymentVersionRequest + +class CreateWorkerDeploymentVersionResponse(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + def __init__( + self, + ) -> None: ... + +global___CreateWorkerDeploymentVersionResponse = CreateWorkerDeploymentVersionResponse + class DeleteWorkerDeploymentVersionRequest(google.protobuf.message.Message): """Used for manual deletion of Versions. User can delete a Version only when all the following conditions are met: @@ -9296,24 +9670,29 @@ class DeleteWorkerDeploymentResponse(google.protobuf.message.Message): global___DeleteWorkerDeploymentResponse = DeleteWorkerDeploymentResponse -class UpdateWorkerDeploymentVersionMetadataRequest(google.protobuf.message.Message): - """Used to update the user-defined metadata of a Worker Deployment Version.""" +class UpdateWorkerDeploymentVersionComputeConfigRequest( + google.protobuf.message.Message +): + """Used to update the compute config of a Worker Deployment Version.""" DESCRIPTOR: google.protobuf.descriptor.Descriptor - class UpsertEntriesEntry(google.protobuf.message.Message): + class ComputeConfigScalingGroupsEntry(google.protobuf.message.Message): DESCRIPTOR: google.protobuf.descriptor.Descriptor KEY_FIELD_NUMBER: builtins.int VALUE_FIELD_NUMBER: builtins.int key: builtins.str @property - def value(self) -> temporalio.api.common.v1.message_pb2.Payload: ... + def value( + self, + ) -> temporalio.api.compute.v1.config_pb2.ComputeConfigScalingGroupUpdate: ... def __init__( self, *, key: builtins.str = ..., - value: temporalio.api.common.v1.message_pb2.Payload | None = ..., + value: temporalio.api.compute.v1.config_pb2.ComputeConfigScalingGroupUpdate + | None = ..., ) -> None: ... def HasField( self, field_name: typing_extensions.Literal["value", b"value"] @@ -9324,45 +9703,54 @@ class UpdateWorkerDeploymentVersionMetadataRequest(google.protobuf.message.Messa ) -> None: ... NAMESPACE_FIELD_NUMBER: builtins.int - VERSION_FIELD_NUMBER: builtins.int DEPLOYMENT_VERSION_FIELD_NUMBER: builtins.int - UPSERT_ENTRIES_FIELD_NUMBER: builtins.int - REMOVE_ENTRIES_FIELD_NUMBER: builtins.int + COMPUTE_CONFIG_SCALING_GROUPS_FIELD_NUMBER: builtins.int + REMOVE_COMPUTE_CONFIG_SCALING_GROUPS_FIELD_NUMBER: builtins.int IDENTITY_FIELD_NUMBER: builtins.int + REQUEST_ID_FIELD_NUMBER: builtins.int namespace: builtins.str - version: builtins.str - """Deprecated. Use `deployment_version`.""" @property def deployment_version( self, ) -> temporalio.api.deployment.v1.message_pb2.WorkerDeploymentVersion: """Required.""" @property - def upsert_entries( + def compute_config_scaling_groups( self, ) -> google.protobuf.internal.containers.MessageMap[ - builtins.str, temporalio.api.common.v1.message_pb2.Payload - ]: ... + builtins.str, + temporalio.api.compute.v1.config_pb2.ComputeConfigScalingGroupUpdate, + ]: + """Optional. Contains the compute config scaling groups to add or update for the Worker + Deployment. + """ @property - def remove_entries( + def remove_compute_config_scaling_groups( self, ) -> google.protobuf.internal.containers.RepeatedScalarFieldContainer[builtins.str]: - """List of keys to remove from the metadata.""" + """Optional. Contains the compute config scaling groups to remove from the Worker Deployment.""" identity: builtins.str """Optional. The identity of the client who initiated this request.""" + request_id: builtins.str + """A unique identifier for this create request for idempotence. Typically UUIDv4. + If a second request with the same ID is recieved, it is considered a successful no-op. + Retrying with a different request ID for the same deployment name + build ID is an error. + """ def __init__( self, *, namespace: builtins.str = ..., - version: builtins.str = ..., deployment_version: temporalio.api.deployment.v1.message_pb2.WorkerDeploymentVersion | None = ..., - upsert_entries: collections.abc.Mapping[ - builtins.str, temporalio.api.common.v1.message_pb2.Payload + compute_config_scaling_groups: collections.abc.Mapping[ + builtins.str, + temporalio.api.compute.v1.config_pb2.ComputeConfigScalingGroupUpdate, ] | None = ..., - remove_entries: collections.abc.Iterable[builtins.str] | None = ..., + remove_compute_config_scaling_groups: collections.abc.Iterable[builtins.str] + | None = ..., identity: builtins.str = ..., + request_id: builtins.str = ..., ) -> None: ... def HasField( self, @@ -9373,59 +9761,282 @@ class UpdateWorkerDeploymentVersionMetadataRequest(google.protobuf.message.Messa def ClearField( self, field_name: typing_extensions.Literal[ + "compute_config_scaling_groups", + b"compute_config_scaling_groups", "deployment_version", b"deployment_version", "identity", b"identity", "namespace", b"namespace", - "remove_entries", - b"remove_entries", - "upsert_entries", - b"upsert_entries", - "version", - b"version", + "remove_compute_config_scaling_groups", + b"remove_compute_config_scaling_groups", + "request_id", + b"request_id", ], ) -> None: ... -global___UpdateWorkerDeploymentVersionMetadataRequest = ( - UpdateWorkerDeploymentVersionMetadataRequest +global___UpdateWorkerDeploymentVersionComputeConfigRequest = ( + UpdateWorkerDeploymentVersionComputeConfigRequest ) -class UpdateWorkerDeploymentVersionMetadataResponse(google.protobuf.message.Message): +class UpdateWorkerDeploymentVersionComputeConfigResponse( + google.protobuf.message.Message +): DESCRIPTOR: google.protobuf.descriptor.Descriptor - METADATA_FIELD_NUMBER: builtins.int - @property - def metadata(self) -> temporalio.api.deployment.v1.message_pb2.VersionMetadata: - """Full metadata after performing the update.""" def __init__( self, - *, - metadata: temporalio.api.deployment.v1.message_pb2.VersionMetadata | None = ..., - ) -> None: ... - def HasField( - self, field_name: typing_extensions.Literal["metadata", b"metadata"] - ) -> builtins.bool: ... - def ClearField( - self, field_name: typing_extensions.Literal["metadata", b"metadata"] ) -> None: ... -global___UpdateWorkerDeploymentVersionMetadataResponse = ( - UpdateWorkerDeploymentVersionMetadataResponse +global___UpdateWorkerDeploymentVersionComputeConfigResponse = ( + UpdateWorkerDeploymentVersionComputeConfigResponse ) -class SetWorkerDeploymentManagerRequest(google.protobuf.message.Message): - """Update the ManagerIdentity of a Worker Deployment.""" +class ValidateWorkerDeploymentVersionComputeConfigRequest( + google.protobuf.message.Message +): + """Used to validate the compute config without attaching it to a Worker Deployment Version.""" DESCRIPTOR: google.protobuf.descriptor.Descriptor - NAMESPACE_FIELD_NUMBER: builtins.int - DEPLOYMENT_NAME_FIELD_NUMBER: builtins.int - MANAGER_IDENTITY_FIELD_NUMBER: builtins.int - SELF_FIELD_NUMBER: builtins.int - CONFLICT_TOKEN_FIELD_NUMBER: builtins.int - IDENTITY_FIELD_NUMBER: builtins.int + class ComputeConfigScalingGroupsEntry(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + KEY_FIELD_NUMBER: builtins.int + VALUE_FIELD_NUMBER: builtins.int + key: builtins.str + @property + def value( + self, + ) -> temporalio.api.compute.v1.config_pb2.ComputeConfigScalingGroupUpdate: ... + def __init__( + self, + *, + key: builtins.str = ..., + value: temporalio.api.compute.v1.config_pb2.ComputeConfigScalingGroupUpdate + | None = ..., + ) -> None: ... + def HasField( + self, field_name: typing_extensions.Literal["value", b"value"] + ) -> builtins.bool: ... + def ClearField( + self, + field_name: typing_extensions.Literal["key", b"key", "value", b"value"], + ) -> None: ... + + NAMESPACE_FIELD_NUMBER: builtins.int + DEPLOYMENT_VERSION_FIELD_NUMBER: builtins.int + COMPUTE_CONFIG_SCALING_GROUPS_FIELD_NUMBER: builtins.int + REMOVE_COMPUTE_CONFIG_SCALING_GROUPS_FIELD_NUMBER: builtins.int + IDENTITY_FIELD_NUMBER: builtins.int + namespace: builtins.str + @property + def deployment_version( + self, + ) -> temporalio.api.deployment.v1.message_pb2.WorkerDeploymentVersion: + """Required.""" + @property + def compute_config_scaling_groups( + self, + ) -> google.protobuf.internal.containers.MessageMap[ + builtins.str, + temporalio.api.compute.v1.config_pb2.ComputeConfigScalingGroupUpdate, + ]: + """Optional. Contains the compute config scaling groups to add or update for the Worker + Deployment. + """ + @property + def remove_compute_config_scaling_groups( + self, + ) -> google.protobuf.internal.containers.RepeatedScalarFieldContainer[builtins.str]: + """Optional. Contains the compute config scaling groups to remove from the Worker Deployment.""" + identity: builtins.str + """Optional. The identity of the client who initiated this request.""" + def __init__( + self, + *, + namespace: builtins.str = ..., + deployment_version: temporalio.api.deployment.v1.message_pb2.WorkerDeploymentVersion + | None = ..., + compute_config_scaling_groups: collections.abc.Mapping[ + builtins.str, + temporalio.api.compute.v1.config_pb2.ComputeConfigScalingGroupUpdate, + ] + | None = ..., + remove_compute_config_scaling_groups: collections.abc.Iterable[builtins.str] + | None = ..., + identity: builtins.str = ..., + ) -> None: ... + def HasField( + self, + field_name: typing_extensions.Literal[ + "deployment_version", b"deployment_version" + ], + ) -> builtins.bool: ... + def ClearField( + self, + field_name: typing_extensions.Literal[ + "compute_config_scaling_groups", + b"compute_config_scaling_groups", + "deployment_version", + b"deployment_version", + "identity", + b"identity", + "namespace", + b"namespace", + "remove_compute_config_scaling_groups", + b"remove_compute_config_scaling_groups", + ], + ) -> None: ... + +global___ValidateWorkerDeploymentVersionComputeConfigRequest = ( + ValidateWorkerDeploymentVersionComputeConfigRequest +) + +class ValidateWorkerDeploymentVersionComputeConfigResponse( + google.protobuf.message.Message +): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + def __init__( + self, + ) -> None: ... + +global___ValidateWorkerDeploymentVersionComputeConfigResponse = ( + ValidateWorkerDeploymentVersionComputeConfigResponse +) + +class UpdateWorkerDeploymentVersionMetadataRequest(google.protobuf.message.Message): + """Used to update the user-defined metadata of a Worker Deployment Version.""" + + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + class UpsertEntriesEntry(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + KEY_FIELD_NUMBER: builtins.int + VALUE_FIELD_NUMBER: builtins.int + key: builtins.str + @property + def value(self) -> temporalio.api.common.v1.message_pb2.Payload: ... + def __init__( + self, + *, + key: builtins.str = ..., + value: temporalio.api.common.v1.message_pb2.Payload | None = ..., + ) -> None: ... + def HasField( + self, field_name: typing_extensions.Literal["value", b"value"] + ) -> builtins.bool: ... + def ClearField( + self, + field_name: typing_extensions.Literal["key", b"key", "value", b"value"], + ) -> None: ... + + NAMESPACE_FIELD_NUMBER: builtins.int + VERSION_FIELD_NUMBER: builtins.int + DEPLOYMENT_VERSION_FIELD_NUMBER: builtins.int + UPSERT_ENTRIES_FIELD_NUMBER: builtins.int + REMOVE_ENTRIES_FIELD_NUMBER: builtins.int + IDENTITY_FIELD_NUMBER: builtins.int + namespace: builtins.str + version: builtins.str + """Deprecated. Use `deployment_version`.""" + @property + def deployment_version( + self, + ) -> temporalio.api.deployment.v1.message_pb2.WorkerDeploymentVersion: + """Required.""" + @property + def upsert_entries( + self, + ) -> google.protobuf.internal.containers.MessageMap[ + builtins.str, temporalio.api.common.v1.message_pb2.Payload + ]: ... + @property + def remove_entries( + self, + ) -> google.protobuf.internal.containers.RepeatedScalarFieldContainer[builtins.str]: + """List of keys to remove from the metadata.""" + identity: builtins.str + """Optional. The identity of the client who initiated this request.""" + def __init__( + self, + *, + namespace: builtins.str = ..., + version: builtins.str = ..., + deployment_version: temporalio.api.deployment.v1.message_pb2.WorkerDeploymentVersion + | None = ..., + upsert_entries: collections.abc.Mapping[ + builtins.str, temporalio.api.common.v1.message_pb2.Payload + ] + | None = ..., + remove_entries: collections.abc.Iterable[builtins.str] | None = ..., + identity: builtins.str = ..., + ) -> None: ... + def HasField( + self, + field_name: typing_extensions.Literal[ + "deployment_version", b"deployment_version" + ], + ) -> builtins.bool: ... + def ClearField( + self, + field_name: typing_extensions.Literal[ + "deployment_version", + b"deployment_version", + "identity", + b"identity", + "namespace", + b"namespace", + "remove_entries", + b"remove_entries", + "upsert_entries", + b"upsert_entries", + "version", + b"version", + ], + ) -> None: ... + +global___UpdateWorkerDeploymentVersionMetadataRequest = ( + UpdateWorkerDeploymentVersionMetadataRequest +) + +class UpdateWorkerDeploymentVersionMetadataResponse(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + METADATA_FIELD_NUMBER: builtins.int + @property + def metadata(self) -> temporalio.api.deployment.v1.message_pb2.VersionMetadata: + """Full metadata after performing the update.""" + def __init__( + self, + *, + metadata: temporalio.api.deployment.v1.message_pb2.VersionMetadata | None = ..., + ) -> None: ... + def HasField( + self, field_name: typing_extensions.Literal["metadata", b"metadata"] + ) -> builtins.bool: ... + def ClearField( + self, field_name: typing_extensions.Literal["metadata", b"metadata"] + ) -> None: ... + +global___UpdateWorkerDeploymentVersionMetadataResponse = ( + UpdateWorkerDeploymentVersionMetadataResponse +) + +class SetWorkerDeploymentManagerRequest(google.protobuf.message.Message): + """Update the ManagerIdentity of a Worker Deployment.""" + + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + NAMESPACE_FIELD_NUMBER: builtins.int + DEPLOYMENT_NAME_FIELD_NUMBER: builtins.int + MANAGER_IDENTITY_FIELD_NUMBER: builtins.int + SELF_FIELD_NUMBER: builtins.int + CONFLICT_TOKEN_FIELD_NUMBER: builtins.int + IDENTITY_FIELD_NUMBER: builtins.int namespace: builtins.str deployment_name: builtins.str manager_identity: builtins.str @@ -10633,6 +11244,10 @@ class StartActivityExecutionRequest(google.protobuf.message.Message): HEADER_FIELD_NUMBER: builtins.int USER_METADATA_FIELD_NUMBER: builtins.int PRIORITY_FIELD_NUMBER: builtins.int + COMPLETION_CALLBACKS_FIELD_NUMBER: builtins.int + LINKS_FIELD_NUMBER: builtins.int + ON_CONFLICT_OPTIONS_FIELD_NUMBER: builtins.int + START_DELAY_FIELD_NUMBER: builtins.int namespace: builtins.str identity: builtins.str """The identity of the client who initiated this request""" @@ -10710,6 +11325,32 @@ class StartActivityExecutionRequest(google.protobuf.message.Message): @property def priority(self) -> temporalio.api.common.v1.message_pb2.Priority: """Priority metadata.""" + @property + def completion_callbacks( + self, + ) -> google.protobuf.internal.containers.RepeatedCompositeFieldContainer[ + temporalio.api.common.v1.message_pb2.Callback + ]: + """Callbacks to be called by the server when this activity reaches a terminal state. + Callback addresses must be whitelisted in the server's dynamic configuration. + """ + @property + def links( + self, + ) -> google.protobuf.internal.containers.RepeatedCompositeFieldContainer[ + temporalio.api.common.v1.message_pb2.Link + ]: + """Links to be associated with the activity. Callbacks may also have associated links; + links already included with a callback should not be duplicated here. + """ + @property + def on_conflict_options( + self, + ) -> temporalio.api.common.v1.message_pb2.OnConflictOptions: + """Options for handling conflicts when using ACTIVITY_ID_CONFLICT_POLICY_USE_EXISTING.""" + @property + def start_delay(self) -> google.protobuf.duration_pb2.Duration: + """Time to wait before dispatching the first activity task. This delay is not applied to retry attempts.""" def __init__( self, *, @@ -10733,6 +11374,15 @@ class StartActivityExecutionRequest(google.protobuf.message.Message): user_metadata: temporalio.api.sdk.v1.user_metadata_pb2.UserMetadata | None = ..., priority: temporalio.api.common.v1.message_pb2.Priority | None = ..., + completion_callbacks: collections.abc.Iterable[ + temporalio.api.common.v1.message_pb2.Callback + ] + | None = ..., + links: collections.abc.Iterable[temporalio.api.common.v1.message_pb2.Link] + | None = ..., + on_conflict_options: temporalio.api.common.v1.message_pb2.OnConflictOptions + | None = ..., + start_delay: google.protobuf.duration_pb2.Duration | None = ..., ) -> None: ... def HasField( self, @@ -10745,6 +11395,8 @@ class StartActivityExecutionRequest(google.protobuf.message.Message): b"heartbeat_timeout", "input", b"input", + "on_conflict_options", + b"on_conflict_options", "priority", b"priority", "retry_policy", @@ -10755,6 +11407,8 @@ class StartActivityExecutionRequest(google.protobuf.message.Message): b"schedule_to_start_timeout", "search_attributes", b"search_attributes", + "start_delay", + b"start_delay", "start_to_close_timeout", b"start_to_close_timeout", "task_queue", @@ -10770,6 +11424,8 @@ class StartActivityExecutionRequest(google.protobuf.message.Message): b"activity_id", "activity_type", b"activity_type", + "completion_callbacks", + b"completion_callbacks", "header", b"header", "heartbeat_timeout", @@ -10782,8 +11438,12 @@ class StartActivityExecutionRequest(google.protobuf.message.Message): b"identity", "input", b"input", + "links", + b"links", "namespace", b"namespace", + "on_conflict_options", + b"on_conflict_options", "priority", b"priority", "request_id", @@ -10796,6 +11456,8 @@ class StartActivityExecutionRequest(google.protobuf.message.Message): b"schedule_to_start_timeout", "search_attributes", b"search_attributes", + "start_delay", + b"start_delay", "start_to_close_timeout", b"start_to_close_timeout", "task_queue", @@ -10812,20 +11474,28 @@ class StartActivityExecutionResponse(google.protobuf.message.Message): RUN_ID_FIELD_NUMBER: builtins.int STARTED_FIELD_NUMBER: builtins.int + LINK_FIELD_NUMBER: builtins.int run_id: builtins.str """The run ID of the activity that was started - or used (via ACTIVITY_ID_CONFLICT_POLICY_USE_EXISTING).""" started: builtins.bool """If true, a new activity was started.""" + @property + def link(self) -> temporalio.api.common.v1.message_pb2.Link: + """Link to the started activity.""" def __init__( self, *, run_id: builtins.str = ..., started: builtins.bool = ..., + link: temporalio.api.common.v1.message_pb2.Link | None = ..., ) -> None: ... + def HasField( + self, field_name: typing_extensions.Literal["link", b"link"] + ) -> builtins.bool: ... def ClearField( self, field_name: typing_extensions.Literal[ - "run_id", b"run_id", "started", b"started" + "link", b"link", "run_id", b"run_id", "started", b"started" ], ) -> None: ... @@ -10894,6 +11564,7 @@ class DescribeActivityExecutionResponse(google.protobuf.message.Message): INPUT_FIELD_NUMBER: builtins.int OUTCOME_FIELD_NUMBER: builtins.int LONG_POLL_TOKEN_FIELD_NUMBER: builtins.int + CALLBACKS_FIELD_NUMBER: builtins.int run_id: builtins.str """The run ID of the activity, useful when run_id was not specified in the request.""" @property @@ -10911,7 +11582,14 @@ class DescribeActivityExecutionResponse(google.protobuf.message.Message): """Only set if the activity is completed and include_outcome was true in the request.""" long_poll_token: builtins.bytes """Token for follow-on long-poll requests. Absent only if the activity is complete.""" - def __init__( + @property + def callbacks( + self, + ) -> google.protobuf.internal.containers.RepeatedCompositeFieldContainer[ + temporalio.api.activity.v1.message_pb2.CallbackInfo + ]: + """Callbacks attached to this activity execution and their current state.""" + def __init__( self, *, run_id: builtins.str = ..., @@ -10920,6 +11598,10 @@ class DescribeActivityExecutionResponse(google.protobuf.message.Message): outcome: temporalio.api.activity.v1.message_pb2.ActivityExecutionOutcome | None = ..., long_poll_token: builtins.bytes = ..., + callbacks: collections.abc.Iterable[ + temporalio.api.activity.v1.message_pb2.CallbackInfo + ] + | None = ..., ) -> None: ... def HasField( self, @@ -10930,6 +11612,8 @@ class DescribeActivityExecutionResponse(google.protobuf.message.Message): def ClearField( self, field_name: typing_extensions.Literal[ + "callbacks", + b"callbacks", "info", b"info", "input", @@ -10965,48 +11649,565 @@ class PollActivityExecutionRequest(google.protobuf.message.Message): def ClearField( self, field_name: typing_extensions.Literal[ - "activity_id", - b"activity_id", + "activity_id", + b"activity_id", + "namespace", + b"namespace", + "run_id", + b"run_id", + ], + ) -> None: ... + +global___PollActivityExecutionRequest = PollActivityExecutionRequest + +class PollActivityExecutionResponse(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + RUN_ID_FIELD_NUMBER: builtins.int + OUTCOME_FIELD_NUMBER: builtins.int + run_id: builtins.str + """The run ID of the activity, useful when run_id was not specified in the request.""" + @property + def outcome( + self, + ) -> temporalio.api.activity.v1.message_pb2.ActivityExecutionOutcome: ... + def __init__( + self, + *, + run_id: builtins.str = ..., + outcome: temporalio.api.activity.v1.message_pb2.ActivityExecutionOutcome + | None = ..., + ) -> None: ... + def HasField( + self, field_name: typing_extensions.Literal["outcome", b"outcome"] + ) -> builtins.bool: ... + def ClearField( + self, + field_name: typing_extensions.Literal[ + "outcome", b"outcome", "run_id", b"run_id" + ], + ) -> None: ... + +global___PollActivityExecutionResponse = PollActivityExecutionResponse + +class ListActivityExecutionsRequest(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + NAMESPACE_FIELD_NUMBER: builtins.int + PAGE_SIZE_FIELD_NUMBER: builtins.int + NEXT_PAGE_TOKEN_FIELD_NUMBER: builtins.int + QUERY_FIELD_NUMBER: builtins.int + namespace: builtins.str + page_size: builtins.int + """Max number of executions to return per page.""" + next_page_token: builtins.bytes + """Token returned in ListActivityExecutionsResponse.""" + query: builtins.str + """Visibility query, see https://docs.temporal.io/list-filter for the syntax.""" + def __init__( + self, + *, + namespace: builtins.str = ..., + page_size: builtins.int = ..., + next_page_token: builtins.bytes = ..., + query: builtins.str = ..., + ) -> None: ... + def ClearField( + self, + field_name: typing_extensions.Literal[ + "namespace", + b"namespace", + "next_page_token", + b"next_page_token", + "page_size", + b"page_size", + "query", + b"query", + ], + ) -> None: ... + +global___ListActivityExecutionsRequest = ListActivityExecutionsRequest + +class ListActivityExecutionsResponse(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + EXECUTIONS_FIELD_NUMBER: builtins.int + NEXT_PAGE_TOKEN_FIELD_NUMBER: builtins.int + @property + def executions( + self, + ) -> google.protobuf.internal.containers.RepeatedCompositeFieldContainer[ + temporalio.api.activity.v1.message_pb2.ActivityExecutionListInfo + ]: ... + next_page_token: builtins.bytes + """Token to use to fetch the next page. If empty, there is no next page.""" + def __init__( + self, + *, + executions: collections.abc.Iterable[ + temporalio.api.activity.v1.message_pb2.ActivityExecutionListInfo + ] + | None = ..., + next_page_token: builtins.bytes = ..., + ) -> None: ... + def ClearField( + self, + field_name: typing_extensions.Literal[ + "executions", b"executions", "next_page_token", b"next_page_token" + ], + ) -> None: ... + +global___ListActivityExecutionsResponse = ListActivityExecutionsResponse + +class StartNexusOperationExecutionRequest(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + class NexusHeaderEntry(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + KEY_FIELD_NUMBER: builtins.int + VALUE_FIELD_NUMBER: builtins.int + key: builtins.str + value: builtins.str + def __init__( + self, + *, + key: builtins.str = ..., + value: builtins.str = ..., + ) -> None: ... + def ClearField( + self, + field_name: typing_extensions.Literal["key", b"key", "value", b"value"], + ) -> None: ... + + NAMESPACE_FIELD_NUMBER: builtins.int + IDENTITY_FIELD_NUMBER: builtins.int + REQUEST_ID_FIELD_NUMBER: builtins.int + OPERATION_ID_FIELD_NUMBER: builtins.int + ENDPOINT_FIELD_NUMBER: builtins.int + SERVICE_FIELD_NUMBER: builtins.int + OPERATION_FIELD_NUMBER: builtins.int + SCHEDULE_TO_CLOSE_TIMEOUT_FIELD_NUMBER: builtins.int + SCHEDULE_TO_START_TIMEOUT_FIELD_NUMBER: builtins.int + START_TO_CLOSE_TIMEOUT_FIELD_NUMBER: builtins.int + INPUT_FIELD_NUMBER: builtins.int + ID_REUSE_POLICY_FIELD_NUMBER: builtins.int + ID_CONFLICT_POLICY_FIELD_NUMBER: builtins.int + SEARCH_ATTRIBUTES_FIELD_NUMBER: builtins.int + NEXUS_HEADER_FIELD_NUMBER: builtins.int + USER_METADATA_FIELD_NUMBER: builtins.int + namespace: builtins.str + identity: builtins.str + """The identity of the client who initiated this request.""" + request_id: builtins.str + """A unique identifier for this caller-side start request. Typically UUIDv4. + StartOperation requests sent to the handler will use a server-generated request ID. + """ + operation_id: builtins.str + """Identifier for this operation. This is a caller-side ID, distinct from any internal + operation identifiers generated by the handler. Must be unique among operations in the + same namespace, subject to the rules imposed by id_reuse_policy and id_conflict_policy. + """ + endpoint: builtins.str + """Endpoint name, resolved to a URL via the cluster's endpoint registry.""" + service: builtins.str + """Service name.""" + operation: builtins.str + """Operation name.""" + @property + def schedule_to_close_timeout(self) -> google.protobuf.duration_pb2.Duration: + """Schedule-to-close timeout for this operation. + Indicates how long the caller is willing to wait for operation completion. + Calls are retried internally by the server. + (-- api-linter: core::0140::prepositions=disabled + aip.dev/not-precedent: "to" is used to indicate interval. --) + """ + @property + def schedule_to_start_timeout(self) -> google.protobuf.duration_pb2.Duration: + """Schedule-to-start timeout for this operation. + Indicates how long the caller is willing to wait for the operation to be started (or completed if synchronous) + by the handler. + If not set or zero, no schedule-to-start timeout is enforced. + (-- api-linter: core::0140::prepositions=disabled + aip.dev/not-precedent: "to" is used to indicate interval. --) + """ + @property + def start_to_close_timeout(self) -> google.protobuf.duration_pb2.Duration: + """Start-to-close timeout for this operation. + Indicates how long the caller is willing to wait for an asynchronous operation to complete after it has been + started. Synchronous operations ignore this timeout. + If not set or zero, no start-to-close timeout is enforced. + (-- api-linter: core::0140::prepositions=disabled + aip.dev/not-precedent: "to" is used to indicate interval. --) + """ + @property + def input(self) -> temporalio.api.common.v1.message_pb2.Payload: + """Serialized input to the operation. Passed as the request payload.""" + id_reuse_policy: ( + temporalio.api.enums.v1.nexus_pb2.NexusOperationIdReusePolicy.ValueType + ) + """Defines whether to allow re-using the operation id from a previously *closed* operation. + The default policy is NEXUS_OPERATION_ID_REUSE_POLICY_ALLOW_DUPLICATE. + """ + id_conflict_policy: ( + temporalio.api.enums.v1.nexus_pb2.NexusOperationIdConflictPolicy.ValueType + ) + """Defines how to resolve an operation id conflict with a *running* operation. + The default policy is NEXUS_OPERATION_ID_CONFLICT_POLICY_FAIL. + """ + @property + def search_attributes( + self, + ) -> temporalio.api.common.v1.message_pb2.SearchAttributes: + """Search attributes for indexing.""" + @property + def nexus_header( + self, + ) -> google.protobuf.internal.containers.ScalarMap[builtins.str, builtins.str]: + """Header to attach to the Nexus request. + Users are responsible for encrypting sensitive data in this header as it is stored in workflow history and + transmitted to external services as-is. + This is useful for propagating tracing information. + Note these headers are not the same as Temporal headers on internal activities and child workflows, these are + transmitted to Nexus operations that may be external and are not traditional payloads. + """ + @property + def user_metadata(self) -> temporalio.api.sdk.v1.user_metadata_pb2.UserMetadata: + """Metadata for use by user interfaces to display the fixed as-of-start summary and details of the operation.""" + def __init__( + self, + *, + namespace: builtins.str = ..., + identity: builtins.str = ..., + request_id: builtins.str = ..., + operation_id: builtins.str = ..., + endpoint: builtins.str = ..., + service: builtins.str = ..., + operation: builtins.str = ..., + schedule_to_close_timeout: google.protobuf.duration_pb2.Duration | None = ..., + schedule_to_start_timeout: google.protobuf.duration_pb2.Duration | None = ..., + start_to_close_timeout: google.protobuf.duration_pb2.Duration | None = ..., + input: temporalio.api.common.v1.message_pb2.Payload | None = ..., + id_reuse_policy: temporalio.api.enums.v1.nexus_pb2.NexusOperationIdReusePolicy.ValueType = ..., + id_conflict_policy: temporalio.api.enums.v1.nexus_pb2.NexusOperationIdConflictPolicy.ValueType = ..., + search_attributes: temporalio.api.common.v1.message_pb2.SearchAttributes + | None = ..., + nexus_header: collections.abc.Mapping[builtins.str, builtins.str] | None = ..., + user_metadata: temporalio.api.sdk.v1.user_metadata_pb2.UserMetadata + | None = ..., + ) -> None: ... + def HasField( + self, + field_name: typing_extensions.Literal[ + "input", + b"input", + "schedule_to_close_timeout", + b"schedule_to_close_timeout", + "schedule_to_start_timeout", + b"schedule_to_start_timeout", + "search_attributes", + b"search_attributes", + "start_to_close_timeout", + b"start_to_close_timeout", + "user_metadata", + b"user_metadata", + ], + ) -> builtins.bool: ... + def ClearField( + self, + field_name: typing_extensions.Literal[ + "endpoint", + b"endpoint", + "id_conflict_policy", + b"id_conflict_policy", + "id_reuse_policy", + b"id_reuse_policy", + "identity", + b"identity", + "input", + b"input", + "namespace", + b"namespace", + "nexus_header", + b"nexus_header", + "operation", + b"operation", + "operation_id", + b"operation_id", + "request_id", + b"request_id", + "schedule_to_close_timeout", + b"schedule_to_close_timeout", + "schedule_to_start_timeout", + b"schedule_to_start_timeout", + "search_attributes", + b"search_attributes", + "service", + b"service", + "start_to_close_timeout", + b"start_to_close_timeout", + "user_metadata", + b"user_metadata", + ], + ) -> None: ... + +global___StartNexusOperationExecutionRequest = StartNexusOperationExecutionRequest + +class StartNexusOperationExecutionResponse(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + RUN_ID_FIELD_NUMBER: builtins.int + STARTED_FIELD_NUMBER: builtins.int + run_id: builtins.str + """The run ID of the operation that was started - or used (via NEXUS_OPERATION_ID_CONFLICT_POLICY_USE_EXISTING).""" + started: builtins.bool + """If true, a new operation was started.""" + def __init__( + self, + *, + run_id: builtins.str = ..., + started: builtins.bool = ..., + ) -> None: ... + def ClearField( + self, + field_name: typing_extensions.Literal[ + "run_id", b"run_id", "started", b"started" + ], + ) -> None: ... + +global___StartNexusOperationExecutionResponse = StartNexusOperationExecutionResponse + +class DescribeNexusOperationExecutionRequest(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + NAMESPACE_FIELD_NUMBER: builtins.int + OPERATION_ID_FIELD_NUMBER: builtins.int + RUN_ID_FIELD_NUMBER: builtins.int + INCLUDE_INPUT_FIELD_NUMBER: builtins.int + INCLUDE_OUTCOME_FIELD_NUMBER: builtins.int + LONG_POLL_TOKEN_FIELD_NUMBER: builtins.int + namespace: builtins.str + operation_id: builtins.str + run_id: builtins.str + """Operation run ID. If empty the request targets the latest run.""" + include_input: builtins.bool + """Include the input field in the response.""" + include_outcome: builtins.bool + """Include the outcome (result/failure) in the response if the operation has completed.""" + long_poll_token: builtins.bytes + """Token from a previous DescribeNexusOperationExecutionResponse. If present, this RPC will long-poll until operation + state changes from the state encoded in this token. If absent, return current state immediately. + If present, run_id must also be present. + Note that operation state may change multiple times between requests, therefore it is not + guaranteed that a client making a sequence of long-poll requests will see a complete + sequence of state changes. + """ + def __init__( + self, + *, + namespace: builtins.str = ..., + operation_id: builtins.str = ..., + run_id: builtins.str = ..., + include_input: builtins.bool = ..., + include_outcome: builtins.bool = ..., + long_poll_token: builtins.bytes = ..., + ) -> None: ... + def ClearField( + self, + field_name: typing_extensions.Literal[ + "include_input", + b"include_input", + "include_outcome", + b"include_outcome", + "long_poll_token", + b"long_poll_token", + "namespace", + b"namespace", + "operation_id", + b"operation_id", + "run_id", + b"run_id", + ], + ) -> None: ... + +global___DescribeNexusOperationExecutionRequest = DescribeNexusOperationExecutionRequest + +class DescribeNexusOperationExecutionResponse(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + RUN_ID_FIELD_NUMBER: builtins.int + INFO_FIELD_NUMBER: builtins.int + INPUT_FIELD_NUMBER: builtins.int + RESULT_FIELD_NUMBER: builtins.int + FAILURE_FIELD_NUMBER: builtins.int + LONG_POLL_TOKEN_FIELD_NUMBER: builtins.int + run_id: builtins.str + """The run ID of the operation, useful when run_id was not specified in the request.""" + @property + def info(self) -> temporalio.api.nexus.v1.message_pb2.NexusOperationExecutionInfo: + """Information about the operation.""" + @property + def input(self) -> temporalio.api.common.v1.message_pb2.Payload: + """Serialized operation input, passed as the request payload. + Only set if include_input was true in the request. + """ + @property + def result(self) -> temporalio.api.common.v1.message_pb2.Payload: + """The result if the operation completed successfully.""" + @property + def failure(self) -> temporalio.api.failure.v1.message_pb2.Failure: + """The failure if the operation completed unsuccessfully.""" + long_poll_token: builtins.bytes + """Token for follow-on long-poll requests. Absent only if the operation is complete.""" + def __init__( + self, + *, + run_id: builtins.str = ..., + info: temporalio.api.nexus.v1.message_pb2.NexusOperationExecutionInfo + | None = ..., + input: temporalio.api.common.v1.message_pb2.Payload | None = ..., + result: temporalio.api.common.v1.message_pb2.Payload | None = ..., + failure: temporalio.api.failure.v1.message_pb2.Failure | None = ..., + long_poll_token: builtins.bytes = ..., + ) -> None: ... + def HasField( + self, + field_name: typing_extensions.Literal[ + "failure", + b"failure", + "info", + b"info", + "input", + b"input", + "outcome", + b"outcome", + "result", + b"result", + ], + ) -> builtins.bool: ... + def ClearField( + self, + field_name: typing_extensions.Literal[ + "failure", + b"failure", + "info", + b"info", + "input", + b"input", + "long_poll_token", + b"long_poll_token", + "outcome", + b"outcome", + "result", + b"result", + "run_id", + b"run_id", + ], + ) -> None: ... + def WhichOneof( + self, oneof_group: typing_extensions.Literal["outcome", b"outcome"] + ) -> typing_extensions.Literal["result", "failure"] | None: ... + +global___DescribeNexusOperationExecutionResponse = ( + DescribeNexusOperationExecutionResponse +) + +class PollNexusOperationExecutionRequest(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + NAMESPACE_FIELD_NUMBER: builtins.int + OPERATION_ID_FIELD_NUMBER: builtins.int + RUN_ID_FIELD_NUMBER: builtins.int + WAIT_STAGE_FIELD_NUMBER: builtins.int + namespace: builtins.str + operation_id: builtins.str + run_id: builtins.str + """Operation run ID. If empty the request targets the latest run.""" + wait_stage: temporalio.api.enums.v1.nexus_pb2.NexusOperationWaitStage.ValueType + """Stage to wait for. The operation may be in a more advanced stage when the poll is unblocked.""" + def __init__( + self, + *, + namespace: builtins.str = ..., + operation_id: builtins.str = ..., + run_id: builtins.str = ..., + wait_stage: temporalio.api.enums.v1.nexus_pb2.NexusOperationWaitStage.ValueType = ..., + ) -> None: ... + def ClearField( + self, + field_name: typing_extensions.Literal[ "namespace", b"namespace", + "operation_id", + b"operation_id", "run_id", b"run_id", + "wait_stage", + b"wait_stage", ], ) -> None: ... -global___PollActivityExecutionRequest = PollActivityExecutionRequest +global___PollNexusOperationExecutionRequest = PollNexusOperationExecutionRequest -class PollActivityExecutionResponse(google.protobuf.message.Message): +class PollNexusOperationExecutionResponse(google.protobuf.message.Message): DESCRIPTOR: google.protobuf.descriptor.Descriptor RUN_ID_FIELD_NUMBER: builtins.int - OUTCOME_FIELD_NUMBER: builtins.int + WAIT_STAGE_FIELD_NUMBER: builtins.int + OPERATION_TOKEN_FIELD_NUMBER: builtins.int + RESULT_FIELD_NUMBER: builtins.int + FAILURE_FIELD_NUMBER: builtins.int run_id: builtins.str - """The run ID of the activity, useful when run_id was not specified in the request.""" + """The run ID of the operation, useful when run_id was not specified in the request.""" + wait_stage: temporalio.api.enums.v1.nexus_pb2.NexusOperationWaitStage.ValueType + """The current stage of the operation. May be more advanced than the stage requested in the poll.""" + operation_token: builtins.str + """Operation token. Only populated for asynchronous operations after a successful StartOperation call.""" @property - def outcome( - self, - ) -> temporalio.api.activity.v1.message_pb2.ActivityExecutionOutcome: ... + def result(self) -> temporalio.api.common.v1.message_pb2.Payload: + """The result if the operation completed successfully.""" + @property + def failure(self) -> temporalio.api.failure.v1.message_pb2.Failure: + """The failure if the operation completed unsuccessfully.""" def __init__( self, *, run_id: builtins.str = ..., - outcome: temporalio.api.activity.v1.message_pb2.ActivityExecutionOutcome - | None = ..., + wait_stage: temporalio.api.enums.v1.nexus_pb2.NexusOperationWaitStage.ValueType = ..., + operation_token: builtins.str = ..., + result: temporalio.api.common.v1.message_pb2.Payload | None = ..., + failure: temporalio.api.failure.v1.message_pb2.Failure | None = ..., ) -> None: ... def HasField( - self, field_name: typing_extensions.Literal["outcome", b"outcome"] + self, + field_name: typing_extensions.Literal[ + "failure", b"failure", "outcome", b"outcome", "result", b"result" + ], ) -> builtins.bool: ... def ClearField( self, field_name: typing_extensions.Literal[ - "outcome", b"outcome", "run_id", b"run_id" + "failure", + b"failure", + "operation_token", + b"operation_token", + "outcome", + b"outcome", + "result", + b"result", + "run_id", + b"run_id", + "wait_stage", + b"wait_stage", ], ) -> None: ... + def WhichOneof( + self, oneof_group: typing_extensions.Literal["outcome", b"outcome"] + ) -> typing_extensions.Literal["result", "failure"] | None: ... -global___PollActivityExecutionResponse = PollActivityExecutionResponse +global___PollNexusOperationExecutionResponse = PollNexusOperationExecutionResponse -class ListActivityExecutionsRequest(google.protobuf.message.Message): +class ListNexusOperationExecutionsRequest(google.protobuf.message.Message): DESCRIPTOR: google.protobuf.descriptor.Descriptor NAMESPACE_FIELD_NUMBER: builtins.int @@ -11015,11 +12216,25 @@ class ListActivityExecutionsRequest(google.protobuf.message.Message): QUERY_FIELD_NUMBER: builtins.int namespace: builtins.str page_size: builtins.int - """Max number of executions to return per page.""" + """Max number of operations to return per page.""" next_page_token: builtins.bytes - """Token returned in ListActivityExecutionsResponse.""" + """Token returned in ListNexusOperationExecutionsResponse.""" query: builtins.str - """Visibility query, see https://docs.temporal.io/list-filter for the syntax.""" + """Visibility query, see https://docs.temporal.io/list-filter for the syntax. + Search attributes that are avaialble for Nexus operations include: + - OperationId + - RunId + - Endpoint + - Service + - Operation + - RequestId + - StartTime + - ExecutionTime + - CloseTime + - ExecutionStatus + - ExecutionDuration + - StateTransitionCount + """ def __init__( self, *, @@ -11042,26 +12257,26 @@ class ListActivityExecutionsRequest(google.protobuf.message.Message): ], ) -> None: ... -global___ListActivityExecutionsRequest = ListActivityExecutionsRequest +global___ListNexusOperationExecutionsRequest = ListNexusOperationExecutionsRequest -class ListActivityExecutionsResponse(google.protobuf.message.Message): +class ListNexusOperationExecutionsResponse(google.protobuf.message.Message): DESCRIPTOR: google.protobuf.descriptor.Descriptor - EXECUTIONS_FIELD_NUMBER: builtins.int + OPERATIONS_FIELD_NUMBER: builtins.int NEXT_PAGE_TOKEN_FIELD_NUMBER: builtins.int @property - def executions( + def operations( self, ) -> google.protobuf.internal.containers.RepeatedCompositeFieldContainer[ - temporalio.api.activity.v1.message_pb2.ActivityExecutionListInfo + temporalio.api.nexus.v1.message_pb2.NexusOperationExecutionListInfo ]: ... next_page_token: builtins.bytes """Token to use to fetch the next page. If empty, there is no next page.""" def __init__( self, *, - executions: collections.abc.Iterable[ - temporalio.api.activity.v1.message_pb2.ActivityExecutionListInfo + operations: collections.abc.Iterable[ + temporalio.api.nexus.v1.message_pb2.NexusOperationExecutionListInfo ] | None = ..., next_page_token: builtins.bytes = ..., @@ -11069,11 +12284,11 @@ class ListActivityExecutionsResponse(google.protobuf.message.Message): def ClearField( self, field_name: typing_extensions.Literal[ - "executions", b"executions", "next_page_token", b"next_page_token" + "next_page_token", b"next_page_token", "operations", b"operations" ], ) -> None: ... -global___ListActivityExecutionsResponse = ListActivityExecutionsResponse +global___ListNexusOperationExecutionsResponse = ListNexusOperationExecutionsResponse class CountActivityExecutionsRequest(google.protobuf.message.Message): DESCRIPTOR: google.protobuf.descriptor.Descriptor @@ -11163,6 +12378,96 @@ class CountActivityExecutionsResponse(google.protobuf.message.Message): global___CountActivityExecutionsResponse = CountActivityExecutionsResponse +class CountNexusOperationExecutionsRequest(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + NAMESPACE_FIELD_NUMBER: builtins.int + QUERY_FIELD_NUMBER: builtins.int + namespace: builtins.str + query: builtins.str + """Visibility query, see https://docs.temporal.io/list-filter for the syntax. + See also ListNexusOperationExecutionsRequest for search attributes available for Nexus operations. + """ + def __init__( + self, + *, + namespace: builtins.str = ..., + query: builtins.str = ..., + ) -> None: ... + def ClearField( + self, + field_name: typing_extensions.Literal[ + "namespace", b"namespace", "query", b"query" + ], + ) -> None: ... + +global___CountNexusOperationExecutionsRequest = CountNexusOperationExecutionsRequest + +class CountNexusOperationExecutionsResponse(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + class AggregationGroup(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + GROUP_VALUES_FIELD_NUMBER: builtins.int + COUNT_FIELD_NUMBER: builtins.int + @property + def group_values( + self, + ) -> google.protobuf.internal.containers.RepeatedCompositeFieldContainer[ + temporalio.api.common.v1.message_pb2.Payload + ]: ... + count: builtins.int + def __init__( + self, + *, + group_values: collections.abc.Iterable[ + temporalio.api.common.v1.message_pb2.Payload + ] + | None = ..., + count: builtins.int = ..., + ) -> None: ... + def ClearField( + self, + field_name: typing_extensions.Literal[ + "count", b"count", "group_values", b"group_values" + ], + ) -> None: ... + + COUNT_FIELD_NUMBER: builtins.int + GROUPS_FIELD_NUMBER: builtins.int + count: builtins.int + """If `query` is not grouping by any field, the count is an approximate number + of operations that match the query. + If `query` is grouping by a field, the count is simply the sum of the counts + of the groups returned in the response. This number can be smaller than the + total number of operations matching the query. + """ + @property + def groups( + self, + ) -> google.protobuf.internal.containers.RepeatedCompositeFieldContainer[ + global___CountNexusOperationExecutionsResponse.AggregationGroup + ]: + """Contains the groups if the request is grouping by a field. + The list might not be complete, and the counts of each group is approximate. + """ + def __init__( + self, + *, + count: builtins.int = ..., + groups: collections.abc.Iterable[ + global___CountNexusOperationExecutionsResponse.AggregationGroup + ] + | None = ..., + ) -> None: ... + def ClearField( + self, + field_name: typing_extensions.Literal["count", b"count", "groups", b"groups"], + ) -> None: ... + +global___CountNexusOperationExecutionsResponse = CountNexusOperationExecutionsResponse + class RequestCancelActivityExecutionRequest(google.protobuf.message.Message): DESCRIPTOR: google.protobuf.descriptor.Descriptor @@ -11320,3 +12625,167 @@ class DeleteActivityExecutionResponse(google.protobuf.message.Message): ) -> None: ... global___DeleteActivityExecutionResponse = DeleteActivityExecutionResponse + +class RequestCancelNexusOperationExecutionRequest(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + NAMESPACE_FIELD_NUMBER: builtins.int + OPERATION_ID_FIELD_NUMBER: builtins.int + RUN_ID_FIELD_NUMBER: builtins.int + IDENTITY_FIELD_NUMBER: builtins.int + REQUEST_ID_FIELD_NUMBER: builtins.int + REASON_FIELD_NUMBER: builtins.int + namespace: builtins.str + operation_id: builtins.str + run_id: builtins.str + """Operation run ID, targets the latest run if empty.""" + identity: builtins.str + """The identity of the client who initiated this request.""" + request_id: builtins.str + """Used to de-dupe cancellation requests.""" + reason: builtins.str + """Reason for requesting the cancellation, recorded and available via the DescribeNexusOperationExecution API.""" + def __init__( + self, + *, + namespace: builtins.str = ..., + operation_id: builtins.str = ..., + run_id: builtins.str = ..., + identity: builtins.str = ..., + request_id: builtins.str = ..., + reason: builtins.str = ..., + ) -> None: ... + def ClearField( + self, + field_name: typing_extensions.Literal[ + "identity", + b"identity", + "namespace", + b"namespace", + "operation_id", + b"operation_id", + "reason", + b"reason", + "request_id", + b"request_id", + "run_id", + b"run_id", + ], + ) -> None: ... + +global___RequestCancelNexusOperationExecutionRequest = ( + RequestCancelNexusOperationExecutionRequest +) + +class RequestCancelNexusOperationExecutionResponse(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + def __init__( + self, + ) -> None: ... + +global___RequestCancelNexusOperationExecutionResponse = ( + RequestCancelNexusOperationExecutionResponse +) + +class TerminateNexusOperationExecutionRequest(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + NAMESPACE_FIELD_NUMBER: builtins.int + OPERATION_ID_FIELD_NUMBER: builtins.int + RUN_ID_FIELD_NUMBER: builtins.int + IDENTITY_FIELD_NUMBER: builtins.int + REQUEST_ID_FIELD_NUMBER: builtins.int + REASON_FIELD_NUMBER: builtins.int + namespace: builtins.str + operation_id: builtins.str + run_id: builtins.str + """Operation run ID, targets the latest run if empty.""" + identity: builtins.str + """The identity of the client who initiated this request.""" + request_id: builtins.str + """Used to de-dupe termination requests.""" + reason: builtins.str + """Reason for requesting the termination, recorded in the operation's result failure outcome.""" + def __init__( + self, + *, + namespace: builtins.str = ..., + operation_id: builtins.str = ..., + run_id: builtins.str = ..., + identity: builtins.str = ..., + request_id: builtins.str = ..., + reason: builtins.str = ..., + ) -> None: ... + def ClearField( + self, + field_name: typing_extensions.Literal[ + "identity", + b"identity", + "namespace", + b"namespace", + "operation_id", + b"operation_id", + "reason", + b"reason", + "request_id", + b"request_id", + "run_id", + b"run_id", + ], + ) -> None: ... + +global___TerminateNexusOperationExecutionRequest = ( + TerminateNexusOperationExecutionRequest +) + +class TerminateNexusOperationExecutionResponse(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + def __init__( + self, + ) -> None: ... + +global___TerminateNexusOperationExecutionResponse = ( + TerminateNexusOperationExecutionResponse +) + +class DeleteNexusOperationExecutionRequest(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + NAMESPACE_FIELD_NUMBER: builtins.int + OPERATION_ID_FIELD_NUMBER: builtins.int + RUN_ID_FIELD_NUMBER: builtins.int + namespace: builtins.str + operation_id: builtins.str + run_id: builtins.str + """Operation run ID, targets the latest run if empty.""" + def __init__( + self, + *, + namespace: builtins.str = ..., + operation_id: builtins.str = ..., + run_id: builtins.str = ..., + ) -> None: ... + def ClearField( + self, + field_name: typing_extensions.Literal[ + "namespace", + b"namespace", + "operation_id", + b"operation_id", + "run_id", + b"run_id", + ], + ) -> None: ... + +global___DeleteNexusOperationExecutionRequest = DeleteNexusOperationExecutionRequest + +class DeleteNexusOperationExecutionResponse(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + def __init__( + self, + ) -> None: ... + +global___DeleteNexusOperationExecutionResponse = DeleteNexusOperationExecutionResponse diff --git a/temporalio/api/workflowservice/v1/service_pb2.py b/temporalio/api/workflowservice/v1/service_pb2.py index a4d09080a..d49923458 100644 --- a/temporalio/api/workflowservice/v1/service_pb2.py +++ b/temporalio/api/workflowservice/v1/service_pb2.py @@ -24,7 +24,7 @@ ) DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile( - b'\n-temporal/api/workflowservice/v1/service.proto\x12\x1ftemporal.api.workflowservice.v1\x1a\x36temporal/api/workflowservice/v1/request_response.proto\x1a\x1cgoogle/api/annotations.proto\x1a+temporal/api/protometa/v1/annotations.proto2\xfb\xf7\x01\n\x0fWorkflowService\x12\xc3\x01\n\x11RegisterNamespace\x12\x39.temporal.api.workflowservice.v1.RegisterNamespaceRequest\x1a:.temporal.api.workflowservice.v1.RegisterNamespaceResponse"7\x82\xd3\xe4\x93\x02\x31"\x13/cluster/namespaces:\x01*Z\x17"\x12/api/v1/namespaces:\x01*\x12\xd5\x01\n\x11\x44\x65scribeNamespace\x12\x39.temporal.api.workflowservice.v1.DescribeNamespaceRequest\x1a:.temporal.api.workflowservice.v1.DescribeNamespaceResponse"I\x82\xd3\xe4\x93\x02\x43\x12\x1f/cluster/namespaces/{namespace}Z \x12\x1e/api/v1/namespaces/{namespace}\x12\xb4\x01\n\x0eListNamespaces\x12\x36.temporal.api.workflowservice.v1.ListNamespacesRequest\x1a\x37.temporal.api.workflowservice.v1.ListNamespacesResponse"1\x82\xd3\xe4\x93\x02+\x12\x13/cluster/namespacesZ\x14\x12\x12/api/v1/namespaces\x12\xe3\x01\n\x0fUpdateNamespace\x12\x37.temporal.api.workflowservice.v1.UpdateNamespaceRequest\x1a\x38.temporal.api.workflowservice.v1.UpdateNamespaceResponse"]\x82\xd3\xe4\x93\x02W"&/cluster/namespaces/{namespace}/update:\x01*Z*"%/api/v1/namespaces/{namespace}/update:\x01*\x12\x8f\x01\n\x12\x44\x65precateNamespace\x12:.temporal.api.workflowservice.v1.DeprecateNamespaceRequest\x1a;.temporal.api.workflowservice.v1.DeprecateNamespaceResponse"\x00\x12\xc6\x02\n\x16StartWorkflowExecution\x12>.temporal.api.workflowservice.v1.StartWorkflowExecutionRequest\x1a?.temporal.api.workflowservice.v1.StartWorkflowExecutionResponse"\xaa\x01\x82\xd3\xe4\x93\x02q"//namespaces/{namespace}/workflows/{workflow_id}:\x01*Z;"6/api/v1/namespaces/{namespace}/workflows/{workflow_id}:\x01*\x8a\x9d\xcc\x1b.\n\x14temporal-resource-id\x12\x16workflow:{workflow_id}\x12\xcb\x01\n\x15\x45xecuteMultiOperation\x12=.temporal.api.workflowservice.v1.ExecuteMultiOperationRequest\x1a>.temporal.api.workflowservice.v1.ExecuteMultiOperationResponse"3\x8a\x9d\xcc\x1b.\n\x14temporal-resource-id\x12\x16workflow:{resource_id}\x12\xfe\x02\n\x1bGetWorkflowExecutionHistory\x12\x43.temporal.api.workflowservice.v1.GetWorkflowExecutionHistoryRequest\x1a\x44.temporal.api.workflowservice.v1.GetWorkflowExecutionHistoryResponse"\xd3\x01\x82\xd3\xe4\x93\x02\x8f\x01\x12\x41/namespaces/{namespace}/workflows/{execution.workflow_id}/historyZJ\x12H/api/v1/namespaces/{namespace}/workflows/{execution.workflow_id}/history\x8a\x9d\xcc\x1b\x38\n\x14temporal-resource-id\x12 workflow:{execution.workflow_id}\x12\xa3\x03\n"GetWorkflowExecutionHistoryReverse\x12J.temporal.api.workflowservice.v1.GetWorkflowExecutionHistoryReverseRequest\x1aK.temporal.api.workflowservice.v1.GetWorkflowExecutionHistoryReverseResponse"\xe3\x01\x82\xd3\xe4\x93\x02\x9f\x01\x12I/namespaces/{namespace}/workflows/{execution.workflow_id}/history-reverseZR\x12P/api/v1/namespaces/{namespace}/workflows/{execution.workflow_id}/history-reverse\x8a\x9d\xcc\x1b\x38\n\x14temporal-resource-id\x12 workflow:{execution.workflow_id}\x12\x98\x01\n\x15PollWorkflowTaskQueue\x12=.temporal.api.workflowservice.v1.PollWorkflowTaskQueueRequest\x1a>.temporal.api.workflowservice.v1.PollWorkflowTaskQueueResponse"\x00\x12\xe0\x01\n\x1cRespondWorkflowTaskCompleted\x12\x44.temporal.api.workflowservice.v1.RespondWorkflowTaskCompletedRequest\x1a\x45.temporal.api.workflowservice.v1.RespondWorkflowTaskCompletedResponse"3\x8a\x9d\xcc\x1b.\n\x14temporal-resource-id\x12\x16workflow:{resource_id}\x12\xd7\x01\n\x19RespondWorkflowTaskFailed\x12\x41.temporal.api.workflowservice.v1.RespondWorkflowTaskFailedRequest\x1a\x42.temporal.api.workflowservice.v1.RespondWorkflowTaskFailedResponse"3\x8a\x9d\xcc\x1b.\n\x14temporal-resource-id\x12\x16workflow:{resource_id}\x12\x98\x01\n\x15PollActivityTaskQueue\x12=.temporal.api.workflowservice.v1.PollActivityTaskQueueRequest\x1a>.temporal.api.workflowservice.v1.PollActivityTaskQueueResponse"\x00\x12\xc2\x02\n\x1bRecordActivityTaskHeartbeat\x12\x43.temporal.api.workflowservice.v1.RecordActivityTaskHeartbeatRequest\x1a\x44.temporal.api.workflowservice.v1.RecordActivityTaskHeartbeatResponse"\x97\x01\x82\xd3\xe4\x93\x02g"*/namespaces/{namespace}/activity-heartbeat:\x01*Z6"1/api/v1/namespaces/{namespace}/activity-heartbeat:\x01*\x8a\x9d\xcc\x1b%\n\x14temporal-resource-id\x12\r{resource_id}\x12\xa8\x04\n\x1fRecordActivityTaskHeartbeatById\x12G.temporal.api.workflowservice.v1.RecordActivityTaskHeartbeatByIdRequest\x1aH.temporal.api.workflowservice.v1.RecordActivityTaskHeartbeatByIdResponse"\xf1\x02\x82\xd3\xe4\x93\x02\xc0\x02":/namespaces/{namespace}/activities/{activity_id}/heartbeat:\x01*ZF"A/api/v1/namespaces/{namespace}/activities/{activity_id}/heartbeat:\x01*ZW"R/namespaces/{namespace}/workflows/{workflow_id}/activities/{activity_id}/heartbeat:\x01*Z^"Y/api/v1/namespaces/{namespace}/workflows/{workflow_id}/activities/{activity_id}/heartbeat:\x01*\x8a\x9d\xcc\x1b%\n\x14temporal-resource-id\x12\r{resource_id}\x12\xc3\x02\n\x1cRespondActivityTaskCompleted\x12\x44.temporal.api.workflowservice.v1.RespondActivityTaskCompletedRequest\x1a\x45.temporal.api.workflowservice.v1.RespondActivityTaskCompletedResponse"\x95\x01\x82\xd3\xe4\x93\x02\x65")/namespaces/{namespace}/activity-complete:\x01*Z5"0/api/v1/namespaces/{namespace}/activity-complete:\x01*\x8a\x9d\xcc\x1b%\n\x14temporal-resource-id\x12\r{resource_id}\x12\xa7\x04\n RespondActivityTaskCompletedById\x12H.temporal.api.workflowservice.v1.RespondActivityTaskCompletedByIdRequest\x1aI.temporal.api.workflowservice.v1.RespondActivityTaskCompletedByIdResponse"\xed\x02\x82\xd3\xe4\x93\x02\xbc\x02"9/namespaces/{namespace}/activities/{activity_id}/complete:\x01*ZE"@/api/v1/namespaces/{namespace}/activities/{activity_id}/complete:\x01*ZV"Q/namespaces/{namespace}/workflows/{workflow_id}/activities/{activity_id}/complete:\x01*Z]"X/api/v1/namespaces/{namespace}/workflows/{workflow_id}/activities/{activity_id}/complete:\x01*\x8a\x9d\xcc\x1b%\n\x14temporal-resource-id\x12\r{resource_id}\x12\xb2\x02\n\x19RespondActivityTaskFailed\x12\x41.temporal.api.workflowservice.v1.RespondActivityTaskFailedRequest\x1a\x42.temporal.api.workflowservice.v1.RespondActivityTaskFailedResponse"\x8d\x01\x82\xd3\xe4\x93\x02]"%/namespaces/{namespace}/activity-fail:\x01*Z1",/api/v1/namespaces/{namespace}/activity-fail:\x01*\x8a\x9d\xcc\x1b%\n\x14temporal-resource-id\x12\r{resource_id}\x12\x8e\x04\n\x1dRespondActivityTaskFailedById\x12\x45.temporal.api.workflowservice.v1.RespondActivityTaskFailedByIdRequest\x1a\x46.temporal.api.workflowservice.v1.RespondActivityTaskFailedByIdResponse"\xdd\x02\x82\xd3\xe4\x93\x02\xac\x02"5/namespaces/{namespace}/activities/{activity_id}/fail:\x01*ZA".temporal.api.workflowservice.v1.ResetWorkflowExecutionRequest\x1a?.temporal.api.workflowservice.v1.ResetWorkflowExecutionResponse"\xf0\x01\x82\xd3\xe4\x93\x02\xa3\x01"H/namespaces/{namespace}/workflows/{workflow_execution.workflow_id}/reset:\x01*ZT"O/api/v1/namespaces/{namespace}/workflows/{workflow_execution.workflow_id}/reset:\x01*\x8a\x9d\xcc\x1b\x41\n\x14temporal-resource-id\x12)workflow:{workflow_execution.workflow_id}\x12\xa0\x03\n\x1aTerminateWorkflowExecution\x12\x42.temporal.api.workflowservice.v1.TerminateWorkflowExecutionRequest\x1a\x43.temporal.api.workflowservice.v1.TerminateWorkflowExecutionResponse"\xf8\x01\x82\xd3\xe4\x93\x02\xab\x01"L/namespaces/{namespace}/workflows/{workflow_execution.workflow_id}/terminate:\x01*ZX"S/api/v1/namespaces/{namespace}/workflows/{workflow_execution.workflow_id}/terminate:\x01*\x8a\x9d\xcc\x1b\x41\n\x14temporal-resource-id\x12)workflow:{workflow_execution.workflow_id}\x12\xe4\x01\n\x17\x44\x65leteWorkflowExecution\x12?.temporal.api.workflowservice.v1.DeleteWorkflowExecutionRequest\x1a@.temporal.api.workflowservice.v1.DeleteWorkflowExecutionResponse"F\x8a\x9d\xcc\x1b\x41\n\x14temporal-resource-id\x12)workflow:{workflow_execution.workflow_id}\x12\xa7\x01\n\x1aListOpenWorkflowExecutions\x12\x42.temporal.api.workflowservice.v1.ListOpenWorkflowExecutionsRequest\x1a\x43.temporal.api.workflowservice.v1.ListOpenWorkflowExecutionsResponse"\x00\x12\xad\x01\n\x1cListClosedWorkflowExecutions\x12\x44.temporal.api.workflowservice.v1.ListClosedWorkflowExecutionsRequest\x1a\x45.temporal.api.workflowservice.v1.ListClosedWorkflowExecutionsResponse"\x00\x12\xf0\x01\n\x16ListWorkflowExecutions\x12>.temporal.api.workflowservice.v1.ListWorkflowExecutionsRequest\x1a?.temporal.api.workflowservice.v1.ListWorkflowExecutionsResponse"U\x82\xd3\xe4\x93\x02O\x12!/namespaces/{namespace}/workflowsZ*\x12(/api/v1/namespaces/{namespace}/workflows\x12\x9a\x02\n\x1eListArchivedWorkflowExecutions\x12\x46.temporal.api.workflowservice.v1.ListArchivedWorkflowExecutionsRequest\x1aG.temporal.api.workflowservice.v1.ListArchivedWorkflowExecutionsResponse"g\x82\xd3\xe4\x93\x02\x61\x12*/namespaces/{namespace}/archived-workflowsZ3\x12\x31/api/v1/namespaces/{namespace}/archived-workflows\x12\x9b\x01\n\x16ScanWorkflowExecutions\x12>.temporal.api.workflowservice.v1.ScanWorkflowExecutionsRequest\x1a?.temporal.api.workflowservice.v1.ScanWorkflowExecutionsResponse"\x00\x12\xfd\x01\n\x17\x43ountWorkflowExecutions\x12?.temporal.api.workflowservice.v1.CountWorkflowExecutionsRequest\x1a@.temporal.api.workflowservice.v1.CountWorkflowExecutionsResponse"_\x82\xd3\xe4\x93\x02Y\x12&/namespaces/{namespace}/workflow-countZ/\x12-/api/v1/namespaces/{namespace}/workflow-count\x12\x92\x01\n\x13GetSearchAttributes\x12;.temporal.api.workflowservice.v1.GetSearchAttributesRequest\x1a<.temporal.api.workflowservice.v1.GetSearchAttributesResponse"\x00\x12\xa4\x01\n\x19RespondQueryTaskCompleted\x12\x41.temporal.api.workflowservice.v1.RespondQueryTaskCompletedRequest\x1a\x42.temporal.api.workflowservice.v1.RespondQueryTaskCompletedResponse"\x00\x12\xd2\x01\n\x14ResetStickyTaskQueue\x12<.temporal.api.workflowservice.v1.ResetStickyTaskQueueRequest\x1a=.temporal.api.workflowservice.v1.ResetStickyTaskQueueResponse"=\x8a\x9d\xcc\x1b\x38\n\x14temporal-resource-id\x12 workflow:{execution.workflow_id}\x12\x83\x01\n\x0eShutdownWorker\x12\x36.temporal.api.workflowservice.v1.ShutdownWorkerRequest\x1a\x37.temporal.api.workflowservice.v1.ShutdownWorkerResponse"\x00\x12\xfc\x02\n\rQueryWorkflow\x12\x35.temporal.api.workflowservice.v1.QueryWorkflowRequest\x1a\x36.temporal.api.workflowservice.v1.QueryWorkflowResponse"\xfb\x01\x82\xd3\xe4\x93\x02\xb7\x01"R/namespaces/{namespace}/workflows/{execution.workflow_id}/query/{query.query_type}:\x01*Z^"Y/api/v1/namespaces/{namespace}/workflows/{execution.workflow_id}/query/{query.query_type}:\x01*\x8a\x9d\xcc\x1b\x38\n\x14temporal-resource-id\x12 workflow:{execution.workflow_id}\x12\xe7\x02\n\x19\x44\x65scribeWorkflowExecution\x12\x41.temporal.api.workflowservice.v1.DescribeWorkflowExecutionRequest\x1a\x42.temporal.api.workflowservice.v1.DescribeWorkflowExecutionResponse"\xc2\x01\x82\xd3\xe4\x93\x02\x7f\x12\x39/namespaces/{namespace}/workflows/{execution.workflow_id}ZB\x12@/api/v1/namespaces/{namespace}/workflows/{execution.workflow_id}\x8a\x9d\xcc\x1b\x38\n\x14temporal-resource-id\x12 workflow:{execution.workflow_id}\x12\xc2\x02\n\x11\x44\x65scribeTaskQueue\x12\x39.temporal.api.workflowservice.v1.DescribeTaskQueueRequest\x1a:.temporal.api.workflowservice.v1.DescribeTaskQueueResponse"\xb5\x01\x82\xd3\xe4\x93\x02w\x12\x35/namespaces/{namespace}/task-queues/{task_queue.name}Z>\x12/namespaces/{namespace}/schedules/{schedule_id}/matching-timesZG\x12\x45/api/v1/namespaces/{namespace}/schedules/{schedule_id}/matching-times\x8a\x9d\xcc\x1b.\n\x14temporal-resource-id\x12\x16schedule:{schedule_id}\x12\xa8\x02\n\x0e\x44\x65leteSchedule\x12\x36.temporal.api.workflowservice.v1.DeleteScheduleRequest\x1a\x37.temporal.api.workflowservice.v1.DeleteScheduleResponse"\xa4\x01\x82\xd3\xe4\x93\x02k*//namespaces/{namespace}/schedules/{schedule_id}Z8*6/api/v1/namespaces/{namespace}/schedules/{schedule_id}\x8a\x9d\xcc\x1b.\n\x14temporal-resource-id\x12\x16schedule:{schedule_id}\x12\xd5\x01\n\rListSchedules\x12\x35.temporal.api.workflowservice.v1.ListSchedulesRequest\x1a\x36.temporal.api.workflowservice.v1.ListSchedulesResponse"U\x82\xd3\xe4\x93\x02O\x12!/namespaces/{namespace}/schedulesZ*\x12(/api/v1/namespaces/{namespace}/schedules\x12\xe2\x01\n\x0e\x43ountSchedules\x12\x36.temporal.api.workflowservice.v1.CountSchedulesRequest\x1a\x37.temporal.api.workflowservice.v1.CountSchedulesResponse"_\x82\xd3\xe4\x93\x02Y\x12&/namespaces/{namespace}/schedule-countZ/\x12-/api/v1/namespaces/{namespace}/schedule-count\x12\xb9\x01\n UpdateWorkerBuildIdCompatibility\x12H.temporal.api.workflowservice.v1.UpdateWorkerBuildIdCompatibilityRequest\x1aI.temporal.api.workflowservice.v1.UpdateWorkerBuildIdCompatibilityResponse"\x00\x12\xe1\x02\n\x1dGetWorkerBuildIdCompatibility\x12\x45.temporal.api.workflowservice.v1.GetWorkerBuildIdCompatibilityRequest\x1a\x46.temporal.api.workflowservice.v1.GetWorkerBuildIdCompatibilityResponse"\xb0\x01\x82\xd3\xe4\x93\x02\xa9\x01\x12N/namespaces/{namespace}/task-queues/{task_queue}/worker-build-id-compatibilityZW\x12U/api/v1/namespaces/{namespace}/task-queues/{task_queue}/worker-build-id-compatibility\x12\xaa\x01\n\x1bUpdateWorkerVersioningRules\x12\x43.temporal.api.workflowservice.v1.UpdateWorkerVersioningRulesRequest\x1a\x44.temporal.api.workflowservice.v1.UpdateWorkerVersioningRulesResponse"\x00\x12\xc6\x02\n\x18GetWorkerVersioningRules\x12@.temporal.api.workflowservice.v1.GetWorkerVersioningRulesRequest\x1a\x41.temporal.api.workflowservice.v1.GetWorkerVersioningRulesResponse"\xa4\x01\x82\xd3\xe4\x93\x02\x9d\x01\x12H/namespaces/{namespace}/task-queues/{task_queue}/worker-versioning-rulesZQ\x12O/api/v1/namespaces/{namespace}/task-queues/{task_queue}/worker-versioning-rules\x12\x97\x02\n\x19GetWorkerTaskReachability\x12\x41.temporal.api.workflowservice.v1.GetWorkerTaskReachabilityRequest\x1a\x42.temporal.api.workflowservice.v1.GetWorkerTaskReachabilityResponse"s\x82\xd3\xe4\x93\x02m\x12\x30/namespaces/{namespace}/worker-task-reachabilityZ9\x12\x37/api/v1/namespaces/{namespace}/worker-task-reachability\x12\xc8\x02\n\x12\x44\x65scribeDeployment\x12:.temporal.api.workflowservice.v1.DescribeDeploymentRequest\x1a;.temporal.api.workflowservice.v1.DescribeDeploymentResponse"\xb8\x01\x82\xd3\xe4\x93\x02\xb1\x01\x12R/namespaces/{namespace}/deployments/{deployment.series_name}/{deployment.build_id}Z[\x12Y/api/v1/namespaces/{namespace}/deployments/{deployment.series_name}/{deployment.build_id}\x12\x81\x04\n\x1f\x44\x65scribeWorkerDeploymentVersion\x12G.temporal.api.workflowservice.v1.DescribeWorkerDeploymentVersionRequest\x1aH.temporal.api.workflowservice.v1.DescribeWorkerDeploymentVersionResponse"\xca\x02\x82\xd3\xe4\x93\x02\xf7\x01\x12u/namespaces/{namespace}/worker-deployment-versions/{deployment_version.deployment_name}/{deployment_version.build_id}Z~\x12|/api/v1/namespaces/{namespace}/worker-deployment-versions/{deployment_version.deployment_name}/{deployment_version.build_id}\x8a\x9d\xcc\x1bG\n\x14temporal-resource-id\x12/deployment:{deployment_version.deployment_name}\x12\xdf\x01\n\x0fListDeployments\x12\x37.temporal.api.workflowservice.v1.ListDeploymentsRequest\x1a\x38.temporal.api.workflowservice.v1.ListDeploymentsResponse"Y\x82\xd3\xe4\x93\x02S\x12#/namespaces/{namespace}/deploymentsZ,\x12*/api/v1/namespaces/{namespace}/deployments\x12\xf7\x02\n\x19GetDeploymentReachability\x12\x41.temporal.api.workflowservice.v1.GetDeploymentReachabilityRequest\x1a\x42.temporal.api.workflowservice.v1.GetDeploymentReachabilityResponse"\xd2\x01\x82\xd3\xe4\x93\x02\xcb\x01\x12_/namespaces/{namespace}/deployments/{deployment.series_name}/{deployment.build_id}/reachabilityZh\x12\x66/api/v1/namespaces/{namespace}/deployments/{deployment.series_name}/{deployment.build_id}/reachability\x12\x99\x02\n\x14GetCurrentDeployment\x12<.temporal.api.workflowservice.v1.GetCurrentDeploymentRequest\x1a=.temporal.api.workflowservice.v1.GetCurrentDeploymentResponse"\x83\x01\x82\xd3\xe4\x93\x02}\x12\x38/namespaces/{namespace}/current-deployment/{series_name}ZA\x12?/api/v1/namespaces/{namespace}/current-deployment/{series_name}\x12\xb6\x02\n\x14SetCurrentDeployment\x12<.temporal.api.workflowservice.v1.SetCurrentDeploymentRequest\x1a=.temporal.api.workflowservice.v1.SetCurrentDeploymentResponse"\xa0\x01\x82\xd3\xe4\x93\x02\x99\x01"C/namespaces/{namespace}/current-deployment/{deployment.series_name}:\x01*ZO"J/api/v1/namespaces/{namespace}/current-deployment/{deployment.series_name}:\x01*\x12\xb0\x03\n!SetWorkerDeploymentCurrentVersion\x12I.temporal.api.workflowservice.v1.SetWorkerDeploymentCurrentVersionRequest\x1aJ.temporal.api.workflowservice.v1.SetWorkerDeploymentCurrentVersionResponse"\xf3\x01\x82\xd3\xe4\x93\x02\xb3\x01"P/namespaces/{namespace}/worker-deployments/{deployment_name}/set-current-version:\x01*Z\\"W/api/v1/namespaces/{namespace}/worker-deployments/{deployment_name}/set-current-version:\x01*\x8a\x9d\xcc\x1b\x34\n\x14temporal-resource-id\x12\x1c\x64\x65ployment:{deployment_name}\x12\xe7\x02\n\x18\x44\x65scribeWorkerDeployment\x12@.temporal.api.workflowservice.v1.DescribeWorkerDeploymentRequest\x1a\x41.temporal.api.workflowservice.v1.DescribeWorkerDeploymentResponse"\xc5\x01\x82\xd3\xe4\x93\x02\x85\x01\x12.temporal.api.workflowservice.v1.DeleteWorkerDeploymentRequest\x1a?.temporal.api.workflowservice.v1.DeleteWorkerDeploymentResponse"\xc5\x01\x82\xd3\xe4\x93\x02\x85\x01*.temporal.api.workflowservice.v1.ListWorkerDeploymentsResponse"g\x82\xd3\xe4\x93\x02\x61\x12*/namespaces/{namespace}/worker-deploymentsZ3\x12\x31/api/v1/namespaces/{namespace}/worker-deployments\x12\xbc\x04\n%UpdateWorkerDeploymentVersionMetadata\x12M.temporal.api.workflowservice.v1.UpdateWorkerDeploymentVersionMetadataRequest\x1aN.temporal.api.workflowservice.v1.UpdateWorkerDeploymentVersionMetadataResponse"\xf3\x02\x82\xd3\xe4\x93\x02\xa0\x02"\x85\x01/namespaces/{namespace}/worker-deployment-versions/{deployment_version.deployment_name}/{deployment_version.build_id}/update-metadata:\x01*Z\x92\x01"\x8c\x01/api/v1/namespaces/{namespace}/worker-deployment-versions/{deployment_version.deployment_name}/{deployment_version.build_id}/update-metadata:\x01*\x8a\x9d\xcc\x1bG\n\x14temporal-resource-id\x12/deployment:{deployment_version.deployment_name}\x12\x8b\x03\n\x1aSetWorkerDeploymentManager\x12\x42.temporal.api.workflowservice.v1.SetWorkerDeploymentManagerRequest\x1a\x43.temporal.api.workflowservice.v1.SetWorkerDeploymentManagerResponse"\xe3\x01\x82\xd3\xe4\x93\x02\xa3\x01"H/namespaces/{namespace}/worker-deployments/{deployment_name}/set-manager:\x01*ZT"O/api/v1/namespaces/{namespace}/worker-deployments/{deployment_name}/set-manager:\x01*\x8a\x9d\xcc\x1b\x34\n\x14temporal-resource-id\x12\x1c\x64\x65ployment:{deployment_name}\x12\xbb\x03\n\x17UpdateWorkflowExecution\x12?.temporal.api.workflowservice.v1.UpdateWorkflowExecutionRequest\x1a@.temporal.api.workflowservice.v1.UpdateWorkflowExecutionResponse"\x9c\x02\x82\xd3\xe4\x93\x02\xcf\x01"^/namespaces/{namespace}/workflows/{workflow_execution.workflow_id}/update/{request.input.name}:\x01*Zj"e/api/v1/namespaces/{namespace}/workflows/{workflow_execution.workflow_id}/update/{request.input.name}:\x01*\x8a\x9d\xcc\x1b\x41\n\x14temporal-resource-id\x12)workflow:{workflow_execution.workflow_id}\x12\xfb\x01\n\x1bPollWorkflowExecutionUpdate\x12\x43.temporal.api.workflowservice.v1.PollWorkflowExecutionUpdateRequest\x1a\x44.temporal.api.workflowservice.v1.PollWorkflowExecutionUpdateResponse"Q\x8a\x9d\xcc\x1bL\n\x14temporal-resource-id\x12\x34workflow:{update_ref.workflow_execution.workflow_id}\x12\xb9\x02\n\x13StartBatchOperation\x12;.temporal.api.workflowservice.v1.StartBatchOperationRequest\x1a<.temporal.api.workflowservice.v1.StartBatchOperationResponse"\xa6\x01\x82\xd3\xe4\x93\x02u"1/namespaces/{namespace}/batch-operations/{job_id}:\x01*Z="8/api/v1/namespaces/{namespace}/batch-operations/{job_id}:\x01*\x8a\x9d\xcc\x1b&\n\x14temporal-resource-id\x12\x0e\x62\x61tch:{job_id}\x12\xc0\x02\n\x12StopBatchOperation\x12:.temporal.api.workflowservice.v1.StopBatchOperationRequest\x1a;.temporal.api.workflowservice.v1.StopBatchOperationResponse"\xb0\x01\x82\xd3\xe4\x93\x02\x7f"6/namespaces/{namespace}/batch-operations/{job_id}/stop:\x01*ZB"=/api/v1/namespaces/{namespace}/batch-operations/{job_id}/stop:\x01*\x8a\x9d\xcc\x1b&\n\x14temporal-resource-id\x12\x0e\x62\x61tch:{job_id}\x12\xbc\x02\n\x16\x44\x65scribeBatchOperation\x12>.temporal.api.workflowservice.v1.DescribeBatchOperationRequest\x1a?.temporal.api.workflowservice.v1.DescribeBatchOperationResponse"\xa0\x01\x82\xd3\xe4\x93\x02o\x12\x31/namespaces/{namespace}/batch-operations/{job_id}Z:\x12\x38/api/v1/namespaces/{namespace}/batch-operations/{job_id}\x8a\x9d\xcc\x1b&\n\x14temporal-resource-id\x12\x0e\x62\x61tch:{job_id}\x12\xf5\x01\n\x13ListBatchOperations\x12;.temporal.api.workflowservice.v1.ListBatchOperationsRequest\x1a<.temporal.api.workflowservice.v1.ListBatchOperationsResponse"c\x82\xd3\xe4\x93\x02]\x12(/namespaces/{namespace}/batch-operationsZ1\x12//api/v1/namespaces/{namespace}/batch-operations\x12\x8f\x01\n\x12PollNexusTaskQueue\x12:.temporal.api.workflowservice.v1.PollNexusTaskQueueRequest\x1a;.temporal.api.workflowservice.v1.PollNexusTaskQueueResponse"\x00\x12\xa4\x01\n\x19RespondNexusTaskCompleted\x12\x41.temporal.api.workflowservice.v1.RespondNexusTaskCompletedRequest\x1a\x42.temporal.api.workflowservice.v1.RespondNexusTaskCompletedResponse"\x00\x12\x9b\x01\n\x16RespondNexusTaskFailed\x12>.temporal.api.workflowservice.v1.RespondNexusTaskFailedRequest\x1a?.temporal.api.workflowservice.v1.RespondNexusTaskFailedResponse"\x00\x12\xe8\x02\n\x15UpdateActivityOptions\x12=.temporal.api.workflowservice.v1.UpdateActivityOptionsRequest\x1a>.temporal.api.workflowservice.v1.UpdateActivityOptionsResponse"\xcf\x01\x82\xd3\xe4\x93\x02\x8b\x01".temporal.api.workflowservice.v1.RecordWorkerHeartbeatResponse"\x9c\x01\x82\xd3\xe4\x93\x02\x65")/namespaces/{namespace}/workers/heartbeat:\x01*Z5"0/api/v1/namespaces/{namespace}/workers/heartbeat:\x01*\x8a\x9d\xcc\x1b,\n\x14temporal-resource-id\x12\x14worker:{resource_id}\x12\xcb\x01\n\x0bListWorkers\x12\x33.temporal.api.workflowservice.v1.ListWorkersRequest\x1a\x34.temporal.api.workflowservice.v1.ListWorkersResponse"Q\x82\xd3\xe4\x93\x02K\x12\x1f/namespaces/{namespace}/workersZ(\x12&/api/v1/namespaces/{namespace}/workers\x12\xe2\x02\n\x15UpdateTaskQueueConfig\x12=.temporal.api.workflowservice.v1.UpdateTaskQueueConfigRequest\x1a>.temporal.api.workflowservice.v1.UpdateTaskQueueConfigResponse"\xc9\x01\x82\xd3\xe4\x93\x02\x8f\x01">/namespaces/{namespace}/task-queues/{task_queue}/update-config:\x01*ZJ"E/api/v1/namespaces/{namespace}/task-queues/{task_queue}/update-config:\x01*\x8a\x9d\xcc\x1b.\n\x14temporal-resource-id\x12\x16taskqueue:{task_queue}\x12\xaf\x02\n\x11\x46\x65tchWorkerConfig\x12\x39.temporal.api.workflowservice.v1.FetchWorkerConfigRequest\x1a:.temporal.api.workflowservice.v1.FetchWorkerConfigResponse"\xa2\x01\x82\xd3\xe4\x93\x02k",/namespaces/{namespace}/workers/fetch-config:\x01*Z8"3/api/v1/namespaces/{namespace}/workers/fetch-config:\x01*\x8a\x9d\xcc\x1b,\n\x14temporal-resource-id\x12\x14worker:{resource_id}\x12\xb4\x02\n\x12UpdateWorkerConfig\x12:.temporal.api.workflowservice.v1.UpdateWorkerConfigRequest\x1a;.temporal.api.workflowservice.v1.UpdateWorkerConfigResponse"\xa4\x01\x82\xd3\xe4\x93\x02m"-/namespaces/{namespace}/workers/update-config:\x01*Z9"4/api/v1/namespaces/{namespace}/workers/update-config:\x01*\x8a\x9d\xcc\x1b,\n\x14temporal-resource-id\x12\x14worker:{resource_id}\x12\xcd\x02\n\x0e\x44\x65scribeWorker\x12\x36.temporal.api.workflowservice.v1.DescribeWorkerRequest\x1a\x37.temporal.api.workflowservice.v1.DescribeWorkerResponse"\xc9\x01\x82\xd3\xe4\x93\x02\x89\x01\x12>/namespaces/{namespace}/workers/describe/{worker_instance_key}ZG\x12\x45/api/v1/namespaces/{namespace}/workers/describe/{worker_instance_key}\x8a\x9d\xcc\x1b\x34\n\x14temporal-resource-id\x12\x1cworker:{worker_instance_key}\x12\xd2\x02\n\x16PauseWorkflowExecution\x12>.temporal.api.workflowservice.v1.PauseWorkflowExecutionRequest\x1a?.temporal.api.workflowservice.v1.PauseWorkflowExecutionResponse"\xb6\x01\x82\xd3\xe4\x93\x02}"5/namespaces/{namespace}/workflows/{workflow_id}/pause:\x01*ZA"/api/v1/namespaces/{namespace}/workflows/{workflow_id}/unpause:\x01*\x8a\x9d\xcc\x1b.\n\x14temporal-resource-id\x12\x16workflow:{workflow_id}\x12\x94\x02\n\x16StartActivityExecution\x12>.temporal.api.workflowservice.v1.StartActivityExecutionRequest\x1a?.temporal.api.workflowservice.v1.StartActivityExecutionResponse"y\x82\xd3\xe4\x93\x02s"0/namespaces/{namespace}/activities/{activity_id}:\x01*Z<"7/api/v1/namespaces/{namespace}/activities/{activity_id}:\x01*\x12\x97\x02\n\x19\x44\x65scribeActivityExecution\x12\x41.temporal.api.workflowservice.v1.DescribeActivityExecutionRequest\x1a\x42.temporal.api.workflowservice.v1.DescribeActivityExecutionResponse"s\x82\xd3\xe4\x93\x02m\x12\x30/namespaces/{namespace}/activities/{activity_id}Z9\x12\x37/api/v1/namespaces/{namespace}/activities/{activity_id}\x12\x9c\x02\n\x15PollActivityExecution\x12=.temporal.api.workflowservice.v1.PollActivityExecutionRequest\x1a>.temporal.api.workflowservice.v1.PollActivityExecutionResponse"\x83\x01\x82\xd3\xe4\x93\x02}\x12\x38/namespaces/{namespace}/activities/{activity_id}/outcomeZA\x12?/api/v1/namespaces/{namespace}/activities/{activity_id}/outcome\x12\xf2\x01\n\x16ListActivityExecutions\x12>.temporal.api.workflowservice.v1.ListActivityExecutionsRequest\x1a?.temporal.api.workflowservice.v1.ListActivityExecutionsResponse"W\x82\xd3\xe4\x93\x02Q\x12"/namespaces/{namespace}/activitiesZ+\x12)/api/v1/namespaces/{namespace}/activities\x12\xfd\x01\n\x17\x43ountActivityExecutions\x12?.temporal.api.workflowservice.v1.CountActivityExecutionsRequest\x1a@.temporal.api.workflowservice.v1.CountActivityExecutionsResponse"_\x82\xd3\xe4\x93\x02Y\x12&/namespaces/{namespace}/activity-countZ/\x12-/api/v1/namespaces/{namespace}/activity-count\x12\xbc\x02\n\x1eRequestCancelActivityExecution\x12\x46.temporal.api.workflowservice.v1.RequestCancelActivityExecutionRequest\x1aG.temporal.api.workflowservice.v1.RequestCancelActivityExecutionResponse"\x88\x01\x82\xd3\xe4\x93\x02\x81\x01"7/namespaces/{namespace}/activities/{activity_id}/cancel:\x01*ZC">/api/v1/namespaces/{namespace}/activities/{activity_id}/cancel:\x01*\x12\xb6\x02\n\x1aTerminateActivityExecution\x12\x42.temporal.api.workflowservice.v1.TerminateActivityExecutionRequest\x1a\x43.temporal.api.workflowservice.v1.TerminateActivityExecutionResponse"\x8e\x01\x82\xd3\xe4\x93\x02\x87\x01":/namespaces/{namespace}/activities/{activity_id}/terminate:\x01*ZF"A/api/v1/namespaces/{namespace}/activities/{activity_id}/terminate:\x01*\x12\x9e\x01\n\x17\x44\x65leteActivityExecution\x12?.temporal.api.workflowservice.v1.DeleteActivityExecutionRequest\x1a@.temporal.api.workflowservice.v1.DeleteActivityExecutionResponse"\x00\x42\xb6\x01\n"io.temporal.api.workflowservice.v1B\x0cServiceProtoP\x01Z5go.temporal.io/api/workflowservice/v1;workflowservice\xaa\x02!Temporalio.Api.WorkflowService.V1\xea\x02$Temporalio::Api::WorkflowService::V1b\x06proto3' + b'\n-temporal/api/workflowservice/v1/service.proto\x12\x1ftemporal.api.workflowservice.v1\x1a\x36temporal/api/workflowservice/v1/request_response.proto\x1a\x1cgoogle/api/annotations.proto\x1a+temporal/api/protometa/v1/annotations.proto2\xa9\x9c\x02\n\x0fWorkflowService\x12\xc3\x01\n\x11RegisterNamespace\x12\x39.temporal.api.workflowservice.v1.RegisterNamespaceRequest\x1a:.temporal.api.workflowservice.v1.RegisterNamespaceResponse"7\x82\xd3\xe4\x93\x02\x31"\x13/cluster/namespaces:\x01*Z\x17"\x12/api/v1/namespaces:\x01*\x12\xd5\x01\n\x11\x44\x65scribeNamespace\x12\x39.temporal.api.workflowservice.v1.DescribeNamespaceRequest\x1a:.temporal.api.workflowservice.v1.DescribeNamespaceResponse"I\x82\xd3\xe4\x93\x02\x43\x12\x1f/cluster/namespaces/{namespace}Z \x12\x1e/api/v1/namespaces/{namespace}\x12\xb4\x01\n\x0eListNamespaces\x12\x36.temporal.api.workflowservice.v1.ListNamespacesRequest\x1a\x37.temporal.api.workflowservice.v1.ListNamespacesResponse"1\x82\xd3\xe4\x93\x02+\x12\x13/cluster/namespacesZ\x14\x12\x12/api/v1/namespaces\x12\xe3\x01\n\x0fUpdateNamespace\x12\x37.temporal.api.workflowservice.v1.UpdateNamespaceRequest\x1a\x38.temporal.api.workflowservice.v1.UpdateNamespaceResponse"]\x82\xd3\xe4\x93\x02W"&/cluster/namespaces/{namespace}/update:\x01*Z*"%/api/v1/namespaces/{namespace}/update:\x01*\x12\x8f\x01\n\x12\x44\x65precateNamespace\x12:.temporal.api.workflowservice.v1.DeprecateNamespaceRequest\x1a;.temporal.api.workflowservice.v1.DeprecateNamespaceResponse"\x00\x12\xc6\x02\n\x16StartWorkflowExecution\x12>.temporal.api.workflowservice.v1.StartWorkflowExecutionRequest\x1a?.temporal.api.workflowservice.v1.StartWorkflowExecutionResponse"\xaa\x01\x82\xd3\xe4\x93\x02q"//namespaces/{namespace}/workflows/{workflow_id}:\x01*Z;"6/api/v1/namespaces/{namespace}/workflows/{workflow_id}:\x01*\x8a\x9d\xcc\x1b.\n\x14temporal-resource-id\x12\x16workflow:{workflow_id}\x12\xc2\x01\n\x15\x45xecuteMultiOperation\x12=.temporal.api.workflowservice.v1.ExecuteMultiOperationRequest\x1a>.temporal.api.workflowservice.v1.ExecuteMultiOperationResponse"*\x8a\x9d\xcc\x1b%\n\x14temporal-resource-id\x12\r{resource_id}\x12\xfe\x02\n\x1bGetWorkflowExecutionHistory\x12\x43.temporal.api.workflowservice.v1.GetWorkflowExecutionHistoryRequest\x1a\x44.temporal.api.workflowservice.v1.GetWorkflowExecutionHistoryResponse"\xd3\x01\x82\xd3\xe4\x93\x02\x8f\x01\x12\x41/namespaces/{namespace}/workflows/{execution.workflow_id}/historyZJ\x12H/api/v1/namespaces/{namespace}/workflows/{execution.workflow_id}/history\x8a\x9d\xcc\x1b\x38\n\x14temporal-resource-id\x12 workflow:{execution.workflow_id}\x12\xa3\x03\n"GetWorkflowExecutionHistoryReverse\x12J.temporal.api.workflowservice.v1.GetWorkflowExecutionHistoryReverseRequest\x1aK.temporal.api.workflowservice.v1.GetWorkflowExecutionHistoryReverseResponse"\xe3\x01\x82\xd3\xe4\x93\x02\x9f\x01\x12I/namespaces/{namespace}/workflows/{execution.workflow_id}/history-reverseZR\x12P/api/v1/namespaces/{namespace}/workflows/{execution.workflow_id}/history-reverse\x8a\x9d\xcc\x1b\x38\n\x14temporal-resource-id\x12 workflow:{execution.workflow_id}\x12\xcd\x01\n\x15PollWorkflowTaskQueue\x12=.temporal.api.workflowservice.v1.PollWorkflowTaskQueueRequest\x1a>.temporal.api.workflowservice.v1.PollWorkflowTaskQueueResponse"5\x8a\x9d\xcc\x1b\x30\n\x14temporal-resource-id\x12\x18poller:{poller_group_id}\x12\xd7\x01\n\x1cRespondWorkflowTaskCompleted\x12\x44.temporal.api.workflowservice.v1.RespondWorkflowTaskCompletedRequest\x1a\x45.temporal.api.workflowservice.v1.RespondWorkflowTaskCompletedResponse"*\x8a\x9d\xcc\x1b%\n\x14temporal-resource-id\x12\r{resource_id}\x12\xce\x01\n\x19RespondWorkflowTaskFailed\x12\x41.temporal.api.workflowservice.v1.RespondWorkflowTaskFailedRequest\x1a\x42.temporal.api.workflowservice.v1.RespondWorkflowTaskFailedResponse"*\x8a\x9d\xcc\x1b%\n\x14temporal-resource-id\x12\r{resource_id}\x12\xcd\x01\n\x15PollActivityTaskQueue\x12=.temporal.api.workflowservice.v1.PollActivityTaskQueueRequest\x1a>.temporal.api.workflowservice.v1.PollActivityTaskQueueResponse"5\x8a\x9d\xcc\x1b\x30\n\x14temporal-resource-id\x12\x18poller:{poller_group_id}\x12\xc2\x02\n\x1bRecordActivityTaskHeartbeat\x12\x43.temporal.api.workflowservice.v1.RecordActivityTaskHeartbeatRequest\x1a\x44.temporal.api.workflowservice.v1.RecordActivityTaskHeartbeatResponse"\x97\x01\x82\xd3\xe4\x93\x02g"*/namespaces/{namespace}/activity-heartbeat:\x01*Z6"1/api/v1/namespaces/{namespace}/activity-heartbeat:\x01*\x8a\x9d\xcc\x1b%\n\x14temporal-resource-id\x12\r{resource_id}\x12\xa8\x04\n\x1fRecordActivityTaskHeartbeatById\x12G.temporal.api.workflowservice.v1.RecordActivityTaskHeartbeatByIdRequest\x1aH.temporal.api.workflowservice.v1.RecordActivityTaskHeartbeatByIdResponse"\xf1\x02\x82\xd3\xe4\x93\x02\xc0\x02":/namespaces/{namespace}/activities/{activity_id}/heartbeat:\x01*ZF"A/api/v1/namespaces/{namespace}/activities/{activity_id}/heartbeat:\x01*ZW"R/namespaces/{namespace}/workflows/{workflow_id}/activities/{activity_id}/heartbeat:\x01*Z^"Y/api/v1/namespaces/{namespace}/workflows/{workflow_id}/activities/{activity_id}/heartbeat:\x01*\x8a\x9d\xcc\x1b%\n\x14temporal-resource-id\x12\r{resource_id}\x12\xc3\x02\n\x1cRespondActivityTaskCompleted\x12\x44.temporal.api.workflowservice.v1.RespondActivityTaskCompletedRequest\x1a\x45.temporal.api.workflowservice.v1.RespondActivityTaskCompletedResponse"\x95\x01\x82\xd3\xe4\x93\x02\x65")/namespaces/{namespace}/activity-complete:\x01*Z5"0/api/v1/namespaces/{namespace}/activity-complete:\x01*\x8a\x9d\xcc\x1b%\n\x14temporal-resource-id\x12\r{resource_id}\x12\xa7\x04\n RespondActivityTaskCompletedById\x12H.temporal.api.workflowservice.v1.RespondActivityTaskCompletedByIdRequest\x1aI.temporal.api.workflowservice.v1.RespondActivityTaskCompletedByIdResponse"\xed\x02\x82\xd3\xe4\x93\x02\xbc\x02"9/namespaces/{namespace}/activities/{activity_id}/complete:\x01*ZE"@/api/v1/namespaces/{namespace}/activities/{activity_id}/complete:\x01*ZV"Q/namespaces/{namespace}/workflows/{workflow_id}/activities/{activity_id}/complete:\x01*Z]"X/api/v1/namespaces/{namespace}/workflows/{workflow_id}/activities/{activity_id}/complete:\x01*\x8a\x9d\xcc\x1b%\n\x14temporal-resource-id\x12\r{resource_id}\x12\xb2\x02\n\x19RespondActivityTaskFailed\x12\x41.temporal.api.workflowservice.v1.RespondActivityTaskFailedRequest\x1a\x42.temporal.api.workflowservice.v1.RespondActivityTaskFailedResponse"\x8d\x01\x82\xd3\xe4\x93\x02]"%/namespaces/{namespace}/activity-fail:\x01*Z1",/api/v1/namespaces/{namespace}/activity-fail:\x01*\x8a\x9d\xcc\x1b%\n\x14temporal-resource-id\x12\r{resource_id}\x12\x8e\x04\n\x1dRespondActivityTaskFailedById\x12\x45.temporal.api.workflowservice.v1.RespondActivityTaskFailedByIdRequest\x1a\x46.temporal.api.workflowservice.v1.RespondActivityTaskFailedByIdResponse"\xdd\x02\x82\xd3\xe4\x93\x02\xac\x02"5/namespaces/{namespace}/activities/{activity_id}/fail:\x01*ZA".temporal.api.workflowservice.v1.ResetWorkflowExecutionRequest\x1a?.temporal.api.workflowservice.v1.ResetWorkflowExecutionResponse"\xf0\x01\x82\xd3\xe4\x93\x02\xa3\x01"H/namespaces/{namespace}/workflows/{workflow_execution.workflow_id}/reset:\x01*ZT"O/api/v1/namespaces/{namespace}/workflows/{workflow_execution.workflow_id}/reset:\x01*\x8a\x9d\xcc\x1b\x41\n\x14temporal-resource-id\x12)workflow:{workflow_execution.workflow_id}\x12\xa0\x03\n\x1aTerminateWorkflowExecution\x12\x42.temporal.api.workflowservice.v1.TerminateWorkflowExecutionRequest\x1a\x43.temporal.api.workflowservice.v1.TerminateWorkflowExecutionResponse"\xf8\x01\x82\xd3\xe4\x93\x02\xab\x01"L/namespaces/{namespace}/workflows/{workflow_execution.workflow_id}/terminate:\x01*ZX"S/api/v1/namespaces/{namespace}/workflows/{workflow_execution.workflow_id}/terminate:\x01*\x8a\x9d\xcc\x1b\x41\n\x14temporal-resource-id\x12)workflow:{workflow_execution.workflow_id}\x12\xe4\x01\n\x17\x44\x65leteWorkflowExecution\x12?.temporal.api.workflowservice.v1.DeleteWorkflowExecutionRequest\x1a@.temporal.api.workflowservice.v1.DeleteWorkflowExecutionResponse"F\x8a\x9d\xcc\x1b\x41\n\x14temporal-resource-id\x12)workflow:{workflow_execution.workflow_id}\x12\xa7\x01\n\x1aListOpenWorkflowExecutions\x12\x42.temporal.api.workflowservice.v1.ListOpenWorkflowExecutionsRequest\x1a\x43.temporal.api.workflowservice.v1.ListOpenWorkflowExecutionsResponse"\x00\x12\xad\x01\n\x1cListClosedWorkflowExecutions\x12\x44.temporal.api.workflowservice.v1.ListClosedWorkflowExecutionsRequest\x1a\x45.temporal.api.workflowservice.v1.ListClosedWorkflowExecutionsResponse"\x00\x12\xf0\x01\n\x16ListWorkflowExecutions\x12>.temporal.api.workflowservice.v1.ListWorkflowExecutionsRequest\x1a?.temporal.api.workflowservice.v1.ListWorkflowExecutionsResponse"U\x82\xd3\xe4\x93\x02O\x12!/namespaces/{namespace}/workflowsZ*\x12(/api/v1/namespaces/{namespace}/workflows\x12\x9a\x02\n\x1eListArchivedWorkflowExecutions\x12\x46.temporal.api.workflowservice.v1.ListArchivedWorkflowExecutionsRequest\x1aG.temporal.api.workflowservice.v1.ListArchivedWorkflowExecutionsResponse"g\x82\xd3\xe4\x93\x02\x61\x12*/namespaces/{namespace}/archived-workflowsZ3\x12\x31/api/v1/namespaces/{namespace}/archived-workflows\x12\x9b\x01\n\x16ScanWorkflowExecutions\x12>.temporal.api.workflowservice.v1.ScanWorkflowExecutionsRequest\x1a?.temporal.api.workflowservice.v1.ScanWorkflowExecutionsResponse"\x00\x12\xfd\x01\n\x17\x43ountWorkflowExecutions\x12?.temporal.api.workflowservice.v1.CountWorkflowExecutionsRequest\x1a@.temporal.api.workflowservice.v1.CountWorkflowExecutionsResponse"_\x82\xd3\xe4\x93\x02Y\x12&/namespaces/{namespace}/workflow-countZ/\x12-/api/v1/namespaces/{namespace}/workflow-count\x12\x92\x01\n\x13GetSearchAttributes\x12;.temporal.api.workflowservice.v1.GetSearchAttributesRequest\x1a<.temporal.api.workflowservice.v1.GetSearchAttributesResponse"\x00\x12\xd9\x01\n\x19RespondQueryTaskCompleted\x12\x41.temporal.api.workflowservice.v1.RespondQueryTaskCompletedRequest\x1a\x42.temporal.api.workflowservice.v1.RespondQueryTaskCompletedResponse"5\x8a\x9d\xcc\x1b\x30\n\x14temporal-resource-id\x12\x18poller:{poller_group_id}\x12\xd2\x01\n\x14ResetStickyTaskQueue\x12<.temporal.api.workflowservice.v1.ResetStickyTaskQueueRequest\x1a=.temporal.api.workflowservice.v1.ResetStickyTaskQueueResponse"=\x8a\x9d\xcc\x1b\x38\n\x14temporal-resource-id\x12 workflow:{execution.workflow_id}\x12\x83\x01\n\x0eShutdownWorker\x12\x36.temporal.api.workflowservice.v1.ShutdownWorkerRequest\x1a\x37.temporal.api.workflowservice.v1.ShutdownWorkerResponse"\x00\x12\xfc\x02\n\rQueryWorkflow\x12\x35.temporal.api.workflowservice.v1.QueryWorkflowRequest\x1a\x36.temporal.api.workflowservice.v1.QueryWorkflowResponse"\xfb\x01\x82\xd3\xe4\x93\x02\xb7\x01"R/namespaces/{namespace}/workflows/{execution.workflow_id}/query/{query.query_type}:\x01*Z^"Y/api/v1/namespaces/{namespace}/workflows/{execution.workflow_id}/query/{query.query_type}:\x01*\x8a\x9d\xcc\x1b\x38\n\x14temporal-resource-id\x12 workflow:{execution.workflow_id}\x12\xe7\x02\n\x19\x44\x65scribeWorkflowExecution\x12\x41.temporal.api.workflowservice.v1.DescribeWorkflowExecutionRequest\x1a\x42.temporal.api.workflowservice.v1.DescribeWorkflowExecutionResponse"\xc2\x01\x82\xd3\xe4\x93\x02\x7f\x12\x39/namespaces/{namespace}/workflows/{execution.workflow_id}ZB\x12@/api/v1/namespaces/{namespace}/workflows/{execution.workflow_id}\x8a\x9d\xcc\x1b\x38\n\x14temporal-resource-id\x12 workflow:{execution.workflow_id}\x12\xc2\x02\n\x11\x44\x65scribeTaskQueue\x12\x39.temporal.api.workflowservice.v1.DescribeTaskQueueRequest\x1a:.temporal.api.workflowservice.v1.DescribeTaskQueueResponse"\xb5\x01\x82\xd3\xe4\x93\x02w\x12\x35/namespaces/{namespace}/task-queues/{task_queue.name}Z>\x12/namespaces/{namespace}/schedules/{schedule_id}/matching-timesZG\x12\x45/api/v1/namespaces/{namespace}/schedules/{schedule_id}/matching-times\x8a\x9d\xcc\x1b.\n\x14temporal-resource-id\x12\x16schedule:{schedule_id}\x12\xa8\x02\n\x0e\x44\x65leteSchedule\x12\x36.temporal.api.workflowservice.v1.DeleteScheduleRequest\x1a\x37.temporal.api.workflowservice.v1.DeleteScheduleResponse"\xa4\x01\x82\xd3\xe4\x93\x02k*//namespaces/{namespace}/schedules/{schedule_id}Z8*6/api/v1/namespaces/{namespace}/schedules/{schedule_id}\x8a\x9d\xcc\x1b.\n\x14temporal-resource-id\x12\x16schedule:{schedule_id}\x12\xd5\x01\n\rListSchedules\x12\x35.temporal.api.workflowservice.v1.ListSchedulesRequest\x1a\x36.temporal.api.workflowservice.v1.ListSchedulesResponse"U\x82\xd3\xe4\x93\x02O\x12!/namespaces/{namespace}/schedulesZ*\x12(/api/v1/namespaces/{namespace}/schedules\x12\xe2\x01\n\x0e\x43ountSchedules\x12\x36.temporal.api.workflowservice.v1.CountSchedulesRequest\x1a\x37.temporal.api.workflowservice.v1.CountSchedulesResponse"_\x82\xd3\xe4\x93\x02Y\x12&/namespaces/{namespace}/schedule-countZ/\x12-/api/v1/namespaces/{namespace}/schedule-count\x12\xb9\x01\n UpdateWorkerBuildIdCompatibility\x12H.temporal.api.workflowservice.v1.UpdateWorkerBuildIdCompatibilityRequest\x1aI.temporal.api.workflowservice.v1.UpdateWorkerBuildIdCompatibilityResponse"\x00\x12\xe1\x02\n\x1dGetWorkerBuildIdCompatibility\x12\x45.temporal.api.workflowservice.v1.GetWorkerBuildIdCompatibilityRequest\x1a\x46.temporal.api.workflowservice.v1.GetWorkerBuildIdCompatibilityResponse"\xb0\x01\x82\xd3\xe4\x93\x02\xa9\x01\x12N/namespaces/{namespace}/task-queues/{task_queue}/worker-build-id-compatibilityZW\x12U/api/v1/namespaces/{namespace}/task-queues/{task_queue}/worker-build-id-compatibility\x12\xaa\x01\n\x1bUpdateWorkerVersioningRules\x12\x43.temporal.api.workflowservice.v1.UpdateWorkerVersioningRulesRequest\x1a\x44.temporal.api.workflowservice.v1.UpdateWorkerVersioningRulesResponse"\x00\x12\xc6\x02\n\x18GetWorkerVersioningRules\x12@.temporal.api.workflowservice.v1.GetWorkerVersioningRulesRequest\x1a\x41.temporal.api.workflowservice.v1.GetWorkerVersioningRulesResponse"\xa4\x01\x82\xd3\xe4\x93\x02\x9d\x01\x12H/namespaces/{namespace}/task-queues/{task_queue}/worker-versioning-rulesZQ\x12O/api/v1/namespaces/{namespace}/task-queues/{task_queue}/worker-versioning-rules\x12\x97\x02\n\x19GetWorkerTaskReachability\x12\x41.temporal.api.workflowservice.v1.GetWorkerTaskReachabilityRequest\x1a\x42.temporal.api.workflowservice.v1.GetWorkerTaskReachabilityResponse"s\x82\xd3\xe4\x93\x02m\x12\x30/namespaces/{namespace}/worker-task-reachabilityZ9\x12\x37/api/v1/namespaces/{namespace}/worker-task-reachability\x12\xc8\x02\n\x12\x44\x65scribeDeployment\x12:.temporal.api.workflowservice.v1.DescribeDeploymentRequest\x1a;.temporal.api.workflowservice.v1.DescribeDeploymentResponse"\xb8\x01\x82\xd3\xe4\x93\x02\xb1\x01\x12R/namespaces/{namespace}/deployments/{deployment.series_name}/{deployment.build_id}Z[\x12Y/api/v1/namespaces/{namespace}/deployments/{deployment.series_name}/{deployment.build_id}\x12\x81\x04\n\x1f\x44\x65scribeWorkerDeploymentVersion\x12G.temporal.api.workflowservice.v1.DescribeWorkerDeploymentVersionRequest\x1aH.temporal.api.workflowservice.v1.DescribeWorkerDeploymentVersionResponse"\xca\x02\x82\xd3\xe4\x93\x02\xf7\x01\x12u/namespaces/{namespace}/worker-deployment-versions/{deployment_version.deployment_name}/{deployment_version.build_id}Z~\x12|/api/v1/namespaces/{namespace}/worker-deployment-versions/{deployment_version.deployment_name}/{deployment_version.build_id}\x8a\x9d\xcc\x1bG\n\x14temporal-resource-id\x12/deployment:{deployment_version.deployment_name}\x12\xdf\x01\n\x0fListDeployments\x12\x37.temporal.api.workflowservice.v1.ListDeploymentsRequest\x1a\x38.temporal.api.workflowservice.v1.ListDeploymentsResponse"Y\x82\xd3\xe4\x93\x02S\x12#/namespaces/{namespace}/deploymentsZ,\x12*/api/v1/namespaces/{namespace}/deployments\x12\xf7\x02\n\x19GetDeploymentReachability\x12\x41.temporal.api.workflowservice.v1.GetDeploymentReachabilityRequest\x1a\x42.temporal.api.workflowservice.v1.GetDeploymentReachabilityResponse"\xd2\x01\x82\xd3\xe4\x93\x02\xcb\x01\x12_/namespaces/{namespace}/deployments/{deployment.series_name}/{deployment.build_id}/reachabilityZh\x12\x66/api/v1/namespaces/{namespace}/deployments/{deployment.series_name}/{deployment.build_id}/reachability\x12\x99\x02\n\x14GetCurrentDeployment\x12<.temporal.api.workflowservice.v1.GetCurrentDeploymentRequest\x1a=.temporal.api.workflowservice.v1.GetCurrentDeploymentResponse"\x83\x01\x82\xd3\xe4\x93\x02}\x12\x38/namespaces/{namespace}/current-deployment/{series_name}ZA\x12?/api/v1/namespaces/{namespace}/current-deployment/{series_name}\x12\xb6\x02\n\x14SetCurrentDeployment\x12<.temporal.api.workflowservice.v1.SetCurrentDeploymentRequest\x1a=.temporal.api.workflowservice.v1.SetCurrentDeploymentResponse"\xa0\x01\x82\xd3\xe4\x93\x02\x99\x01"C/namespaces/{namespace}/current-deployment/{deployment.series_name}:\x01*ZO"J/api/v1/namespaces/{namespace}/current-deployment/{deployment.series_name}:\x01*\x12\xb0\x03\n!SetWorkerDeploymentCurrentVersion\x12I.temporal.api.workflowservice.v1.SetWorkerDeploymentCurrentVersionRequest\x1aJ.temporal.api.workflowservice.v1.SetWorkerDeploymentCurrentVersionResponse"\xf3\x01\x82\xd3\xe4\x93\x02\xb3\x01"P/namespaces/{namespace}/worker-deployments/{deployment_name}/set-current-version:\x01*Z\\"W/api/v1/namespaces/{namespace}/worker-deployments/{deployment_name}/set-current-version:\x01*\x8a\x9d\xcc\x1b\x34\n\x14temporal-resource-id\x12\x1c\x64\x65ployment:{deployment_name}\x12\xe7\x02\n\x18\x44\x65scribeWorkerDeployment\x12@.temporal.api.workflowservice.v1.DescribeWorkerDeploymentRequest\x1a\x41.temporal.api.workflowservice.v1.DescribeWorkerDeploymentResponse"\xc5\x01\x82\xd3\xe4\x93\x02\x85\x01\x12.temporal.api.workflowservice.v1.DeleteWorkerDeploymentRequest\x1a?.temporal.api.workflowservice.v1.DeleteWorkerDeploymentResponse"\xc5\x01\x82\xd3\xe4\x93\x02\x85\x01*.temporal.api.workflowservice.v1.ListWorkerDeploymentsResponse"g\x82\xd3\xe4\x93\x02\x61\x12*/namespaces/{namespace}/worker-deploymentsZ3\x12\x31/api/v1/namespaces/{namespace}/worker-deployments\x12\xae\x02\n\x16\x43reateWorkerDeployment\x12>.temporal.api.workflowservice.v1.CreateWorkerDeploymentRequest\x1a?.temporal.api.workflowservice.v1.CreateWorkerDeploymentResponse"\x92\x01\x82\xd3\xe4\x93\x02\x8b\x01".temporal.api.workflowservice.v1.DescribeBatchOperationRequest\x1a?.temporal.api.workflowservice.v1.DescribeBatchOperationResponse"\xa0\x01\x82\xd3\xe4\x93\x02o\x12\x31/namespaces/{namespace}/batch-operations/{job_id}Z:\x12\x38/api/v1/namespaces/{namespace}/batch-operations/{job_id}\x8a\x9d\xcc\x1b&\n\x14temporal-resource-id\x12\x0e\x62\x61tch:{job_id}\x12\xf5\x01\n\x13ListBatchOperations\x12;.temporal.api.workflowservice.v1.ListBatchOperationsRequest\x1a<.temporal.api.workflowservice.v1.ListBatchOperationsResponse"c\x82\xd3\xe4\x93\x02]\x12(/namespaces/{namespace}/batch-operationsZ1\x12//api/v1/namespaces/{namespace}/batch-operations\x12\xc4\x01\n\x12PollNexusTaskQueue\x12:.temporal.api.workflowservice.v1.PollNexusTaskQueueRequest\x1a;.temporal.api.workflowservice.v1.PollNexusTaskQueueResponse"5\x8a\x9d\xcc\x1b\x30\n\x14temporal-resource-id\x12\x18poller:{poller_group_id}\x12\xd9\x01\n\x19RespondNexusTaskCompleted\x12\x41.temporal.api.workflowservice.v1.RespondNexusTaskCompletedRequest\x1a\x42.temporal.api.workflowservice.v1.RespondNexusTaskCompletedResponse"5\x8a\x9d\xcc\x1b\x30\n\x14temporal-resource-id\x12\x18poller:{poller_group_id}\x12\xd0\x01\n\x16RespondNexusTaskFailed\x12>.temporal.api.workflowservice.v1.RespondNexusTaskFailedRequest\x1a?.temporal.api.workflowservice.v1.RespondNexusTaskFailedResponse"5\x8a\x9d\xcc\x1b\x30\n\x14temporal-resource-id\x12\x18poller:{poller_group_id}\x12\xe8\x02\n\x15UpdateActivityOptions\x12=.temporal.api.workflowservice.v1.UpdateActivityOptionsRequest\x1a>.temporal.api.workflowservice.v1.UpdateActivityOptionsResponse"\xcf\x01\x82\xd3\xe4\x93\x02\x8b\x01".temporal.api.workflowservice.v1.RecordWorkerHeartbeatResponse"\x95\x01\x82\xd3\xe4\x93\x02\x65")/namespaces/{namespace}/workers/heartbeat:\x01*Z5"0/api/v1/namespaces/{namespace}/workers/heartbeat:\x01*\x8a\x9d\xcc\x1b%\n\x14temporal-resource-id\x12\r{resource_id}\x12\xcb\x01\n\x0bListWorkers\x12\x33.temporal.api.workflowservice.v1.ListWorkersRequest\x1a\x34.temporal.api.workflowservice.v1.ListWorkersResponse"Q\x82\xd3\xe4\x93\x02K\x12\x1f/namespaces/{namespace}/workersZ(\x12&/api/v1/namespaces/{namespace}/workers\x12\xe2\x02\n\x15UpdateTaskQueueConfig\x12=.temporal.api.workflowservice.v1.UpdateTaskQueueConfigRequest\x1a>.temporal.api.workflowservice.v1.UpdateTaskQueueConfigResponse"\xc9\x01\x82\xd3\xe4\x93\x02\x8f\x01">/namespaces/{namespace}/task-queues/{task_queue}/update-config:\x01*ZJ"E/api/v1/namespaces/{namespace}/task-queues/{task_queue}/update-config:\x01*\x8a\x9d\xcc\x1b.\n\x14temporal-resource-id\x12\x16taskqueue:{task_queue}\x12\xa8\x02\n\x11\x46\x65tchWorkerConfig\x12\x39.temporal.api.workflowservice.v1.FetchWorkerConfigRequest\x1a:.temporal.api.workflowservice.v1.FetchWorkerConfigResponse"\x9b\x01\x82\xd3\xe4\x93\x02k",/namespaces/{namespace}/workers/fetch-config:\x01*Z8"3/api/v1/namespaces/{namespace}/workers/fetch-config:\x01*\x8a\x9d\xcc\x1b%\n\x14temporal-resource-id\x12\r{resource_id}\x12\xad\x02\n\x12UpdateWorkerConfig\x12:.temporal.api.workflowservice.v1.UpdateWorkerConfigRequest\x1a;.temporal.api.workflowservice.v1.UpdateWorkerConfigResponse"\x9d\x01\x82\xd3\xe4\x93\x02m"-/namespaces/{namespace}/workers/update-config:\x01*Z9"4/api/v1/namespaces/{namespace}/workers/update-config:\x01*\x8a\x9d\xcc\x1b%\n\x14temporal-resource-id\x12\r{resource_id}\x12\xcd\x02\n\x0e\x44\x65scribeWorker\x12\x36.temporal.api.workflowservice.v1.DescribeWorkerRequest\x1a\x37.temporal.api.workflowservice.v1.DescribeWorkerResponse"\xc9\x01\x82\xd3\xe4\x93\x02\x89\x01\x12>/namespaces/{namespace}/workers/describe/{worker_instance_key}ZG\x12\x45/api/v1/namespaces/{namespace}/workers/describe/{worker_instance_key}\x8a\x9d\xcc\x1b\x34\n\x14temporal-resource-id\x12\x1cworker:{worker_instance_key}\x12\xd2\x02\n\x16PauseWorkflowExecution\x12>.temporal.api.workflowservice.v1.PauseWorkflowExecutionRequest\x1a?.temporal.api.workflowservice.v1.PauseWorkflowExecutionResponse"\xb6\x01\x82\xd3\xe4\x93\x02}"5/namespaces/{namespace}/workflows/{workflow_id}/pause:\x01*ZA"/api/v1/namespaces/{namespace}/workflows/{workflow_id}/unpause:\x01*\x8a\x9d\xcc\x1b.\n\x14temporal-resource-id\x12\x16workflow:{workflow_id}\x12\xc8\x02\n\x16StartActivityExecution\x12>.temporal.api.workflowservice.v1.StartActivityExecutionRequest\x1a?.temporal.api.workflowservice.v1.StartActivityExecutionResponse"\xac\x01\x82\xd3\xe4\x93\x02s"0/namespaces/{namespace}/activities/{activity_id}:\x01*Z<"7/api/v1/namespaces/{namespace}/activities/{activity_id}:\x01*\x8a\x9d\xcc\x1b.\n\x14temporal-resource-id\x12\x16\x61\x63tivity:{activity_id}\x12\xb6\x02\n\x1cStartNexusOperationExecution\x12\x44.temporal.api.workflowservice.v1.StartNexusOperationExecutionRequest\x1a\x45.temporal.api.workflowservice.v1.StartNexusOperationExecutionResponse"\x88\x01\x82\xd3\xe4\x93\x02\x81\x01"7/namespaces/{namespace}/nexus-operations/{operation_id}:\x01*ZC">/api/v1/namespaces/{namespace}/nexus-operations/{operation_id}:\x01*\x12\xcb\x02\n\x19\x44\x65scribeActivityExecution\x12\x41.temporal.api.workflowservice.v1.DescribeActivityExecutionRequest\x1a\x42.temporal.api.workflowservice.v1.DescribeActivityExecutionResponse"\xa6\x01\x82\xd3\xe4\x93\x02m\x12\x30/namespaces/{namespace}/activities/{activity_id}Z9\x12\x37/api/v1/namespaces/{namespace}/activities/{activity_id}\x8a\x9d\xcc\x1b.\n\x14temporal-resource-id\x12\x16\x61\x63tivity:{activity_id}\x12\xb8\x02\n\x1f\x44\x65scribeNexusOperationExecution\x12G.temporal.api.workflowservice.v1.DescribeNexusOperationExecutionRequest\x1aH.temporal.api.workflowservice.v1.DescribeNexusOperationExecutionResponse"\x81\x01\x82\xd3\xe4\x93\x02{\x12\x37/namespaces/{namespace}/nexus-operations/{operation_id}Z@\x12>/api/v1/namespaces/{namespace}/nexus-operations/{operation_id}\x12\xcf\x02\n\x15PollActivityExecution\x12=.temporal.api.workflowservice.v1.PollActivityExecutionRequest\x1a>.temporal.api.workflowservice.v1.PollActivityExecutionResponse"\xb6\x01\x82\xd3\xe4\x93\x02}\x12\x38/namespaces/{namespace}/activities/{activity_id}/outcomeZA\x12?/api/v1/namespaces/{namespace}/activities/{activity_id}/outcome\x8a\x9d\xcc\x1b.\n\x14temporal-resource-id\x12\x16\x61\x63tivity:{activity_id}\x12\xb7\x02\n\x1bPollNexusOperationExecution\x12\x43.temporal.api.workflowservice.v1.PollNexusOperationExecutionRequest\x1a\x44.temporal.api.workflowservice.v1.PollNexusOperationExecutionResponse"\x8c\x01\x82\xd3\xe4\x93\x02\x85\x01\x12.temporal.api.workflowservice.v1.ListActivityExecutionsRequest\x1a?.temporal.api.workflowservice.v1.ListActivityExecutionsResponse"W\x82\xd3\xe4\x93\x02Q\x12"/namespaces/{namespace}/activitiesZ+\x12)/api/v1/namespaces/{namespace}/activities\x12\x90\x02\n\x1cListNexusOperationExecutions\x12\x44.temporal.api.workflowservice.v1.ListNexusOperationExecutionsRequest\x1a\x45.temporal.api.workflowservice.v1.ListNexusOperationExecutionsResponse"c\x82\xd3\xe4\x93\x02]\x12(/namespaces/{namespace}/nexus-operationsZ1\x12//api/v1/namespaces/{namespace}/nexus-operations\x12\xfd\x01\n\x17\x43ountActivityExecutions\x12?.temporal.api.workflowservice.v1.CountActivityExecutionsRequest\x1a@.temporal.api.workflowservice.v1.CountActivityExecutionsResponse"_\x82\xd3\xe4\x93\x02Y\x12&/namespaces/{namespace}/activity-countZ/\x12-/api/v1/namespaces/{namespace}/activity-count\x12\x9d\x02\n\x1d\x43ountNexusOperationExecutions\x12\x45.temporal.api.workflowservice.v1.CountNexusOperationExecutionsRequest\x1a\x46.temporal.api.workflowservice.v1.CountNexusOperationExecutionsResponse"m\x82\xd3\xe4\x93\x02g\x12-/namespaces/{namespace}/nexus-operation-countZ6\x12\x34/api/v1/namespaces/{namespace}/nexus-operation-count\x12\xef\x02\n\x1eRequestCancelActivityExecution\x12\x46.temporal.api.workflowservice.v1.RequestCancelActivityExecutionRequest\x1aG.temporal.api.workflowservice.v1.RequestCancelActivityExecutionResponse"\xbb\x01\x82\xd3\xe4\x93\x02\x81\x01"7/namespaces/{namespace}/activities/{activity_id}/cancel:\x01*ZC">/api/v1/namespaces/{namespace}/activities/{activity_id}/cancel:\x01*\x8a\x9d\xcc\x1b.\n\x14temporal-resource-id\x12\x16\x61\x63tivity:{activity_id}\x12\xdc\x02\n$RequestCancelNexusOperationExecution\x12L.temporal.api.workflowservice.v1.RequestCancelNexusOperationExecutionRequest\x1aM.temporal.api.workflowservice.v1.RequestCancelNexusOperationExecutionResponse"\x96\x01\x82\xd3\xe4\x93\x02\x8f\x01">/namespaces/{namespace}/nexus-operations/{operation_id}/cancel:\x01*ZJ"E/api/v1/namespaces/{namespace}/nexus-operations/{operation_id}/cancel:\x01*\x12\xe9\x02\n\x1aTerminateActivityExecution\x12\x42.temporal.api.workflowservice.v1.TerminateActivityExecutionRequest\x1a\x43.temporal.api.workflowservice.v1.TerminateActivityExecutionResponse"\xc1\x01\x82\xd3\xe4\x93\x02\x87\x01":/namespaces/{namespace}/activities/{activity_id}/terminate:\x01*ZF"A/api/v1/namespaces/{namespace}/activities/{activity_id}/terminate:\x01*\x8a\x9d\xcc\x1b.\n\x14temporal-resource-id\x12\x16\x61\x63tivity:{activity_id}\x12\x9e\x01\n\x17\x44\x65leteActivityExecution\x12?.temporal.api.workflowservice.v1.DeleteActivityExecutionRequest\x1a@.temporal.api.workflowservice.v1.DeleteActivityExecutionResponse"\x00\x12\xd6\x02\n TerminateNexusOperationExecution\x12H.temporal.api.workflowservice.v1.TerminateNexusOperationExecutionRequest\x1aI.temporal.api.workflowservice.v1.TerminateNexusOperationExecutionResponse"\x9c\x01\x82\xd3\xe4\x93\x02\x95\x01"A/namespaces/{namespace}/nexus-operations/{operation_id}/terminate:\x01*ZM"H/api/v1/namespaces/{namespace}/nexus-operations/{operation_id}/terminate:\x01*\x12\xb0\x01\n\x1d\x44\x65leteNexusOperationExecution\x12\x45.temporal.api.workflowservice.v1.DeleteNexusOperationExecutionRequest\x1a\x46.temporal.api.workflowservice.v1.DeleteNexusOperationExecutionResponse"\x00\x42\xb6\x01\n"io.temporal.api.workflowservice.v1B\x0cServiceProtoP\x01Z5go.temporal.io/api/workflowservice/v1;workflowservice\xaa\x02!Temporalio.Api.WorkflowService.V1\xea\x02$Temporalio::Api::WorkflowService::V1b\x06proto3' ) @@ -56,7 +56,7 @@ _WORKFLOWSERVICE.methods_by_name[ "ExecuteMultiOperation" ]._serialized_options = ( - b"\212\235\314\033.\n\024temporal-resource-id\022\026workflow:{resource_id}" + b"\212\235\314\033%\n\024temporal-resource-id\022\r{resource_id}" ) _WORKFLOWSERVICE.methods_by_name["GetWorkflowExecutionHistory"]._options = None _WORKFLOWSERVICE.methods_by_name[ @@ -68,17 +68,29 @@ _WORKFLOWSERVICE.methods_by_name[ "GetWorkflowExecutionHistoryReverse" ]._serialized_options = b"\202\323\344\223\002\237\001\022I/namespaces/{namespace}/workflows/{execution.workflow_id}/history-reverseZR\022P/api/v1/namespaces/{namespace}/workflows/{execution.workflow_id}/history-reverse\212\235\314\0338\n\024temporal-resource-id\022 workflow:{execution.workflow_id}" + _WORKFLOWSERVICE.methods_by_name["PollWorkflowTaskQueue"]._options = None + _WORKFLOWSERVICE.methods_by_name[ + "PollWorkflowTaskQueue" + ]._serialized_options = ( + b"\212\235\314\0330\n\024temporal-resource-id\022\030poller:{poller_group_id}" + ) _WORKFLOWSERVICE.methods_by_name["RespondWorkflowTaskCompleted"]._options = None _WORKFLOWSERVICE.methods_by_name[ "RespondWorkflowTaskCompleted" ]._serialized_options = ( - b"\212\235\314\033.\n\024temporal-resource-id\022\026workflow:{resource_id}" + b"\212\235\314\033%\n\024temporal-resource-id\022\r{resource_id}" ) _WORKFLOWSERVICE.methods_by_name["RespondWorkflowTaskFailed"]._options = None _WORKFLOWSERVICE.methods_by_name[ "RespondWorkflowTaskFailed" ]._serialized_options = ( - b"\212\235\314\033.\n\024temporal-resource-id\022\026workflow:{resource_id}" + b"\212\235\314\033%\n\024temporal-resource-id\022\r{resource_id}" + ) + _WORKFLOWSERVICE.methods_by_name["PollActivityTaskQueue"]._options = None + _WORKFLOWSERVICE.methods_by_name[ + "PollActivityTaskQueue" + ]._serialized_options = ( + b"\212\235\314\0330\n\024temporal-resource-id\022\030poller:{poller_group_id}" ) _WORKFLOWSERVICE.methods_by_name["RecordActivityTaskHeartbeat"]._options = None _WORKFLOWSERVICE.methods_by_name[ @@ -148,6 +160,12 @@ _WORKFLOWSERVICE.methods_by_name[ "CountWorkflowExecutions" ]._serialized_options = b"\202\323\344\223\002Y\022&/namespaces/{namespace}/workflow-countZ/\022-/api/v1/namespaces/{namespace}/workflow-count" + _WORKFLOWSERVICE.methods_by_name["RespondQueryTaskCompleted"]._options = None + _WORKFLOWSERVICE.methods_by_name[ + "RespondQueryTaskCompleted" + ]._serialized_options = ( + b"\212\235\314\0330\n\024temporal-resource-id\022\030poller:{poller_group_id}" + ) _WORKFLOWSERVICE.methods_by_name["ResetStickyTaskQueue"]._options = None _WORKFLOWSERVICE.methods_by_name[ "ResetStickyTaskQueue" @@ -276,6 +294,26 @@ _WORKFLOWSERVICE.methods_by_name[ "ListWorkerDeployments" ]._serialized_options = b"\202\323\344\223\002a\022*/namespaces/{namespace}/worker-deploymentsZ3\0221/api/v1/namespaces/{namespace}/worker-deployments" + _WORKFLOWSERVICE.methods_by_name["CreateWorkerDeployment"]._options = None + _WORKFLOWSERVICE.methods_by_name[ + "CreateWorkerDeployment" + ]._serialized_options = b'\202\323\344\223\002\213\001"/api/v1/namespaces/{namespace}/nexus-operations/{operation_id}:\001*' _WORKFLOWSERVICE.methods_by_name["DescribeActivityExecution"]._options = None _WORKFLOWSERVICE.methods_by_name[ "DescribeActivityExecution" - ]._serialized_options = b"\202\323\344\223\002m\0220/namespaces/{namespace}/activities/{activity_id}Z9\0227/api/v1/namespaces/{namespace}/activities/{activity_id}" + ]._serialized_options = b"\202\323\344\223\002m\0220/namespaces/{namespace}/activities/{activity_id}Z9\0227/api/v1/namespaces/{namespace}/activities/{activity_id}\212\235\314\033.\n\024temporal-resource-id\022\026activity:{activity_id}" + _WORKFLOWSERVICE.methods_by_name["DescribeNexusOperationExecution"]._options = None + _WORKFLOWSERVICE.methods_by_name[ + "DescribeNexusOperationExecution" + ]._serialized_options = b"\202\323\344\223\002{\0227/namespaces/{namespace}/nexus-operations/{operation_id}Z@\022>/api/v1/namespaces/{namespace}/nexus-operations/{operation_id}" _WORKFLOWSERVICE.methods_by_name["PollActivityExecution"]._options = None _WORKFLOWSERVICE.methods_by_name[ "PollActivityExecution" - ]._serialized_options = b"\202\323\344\223\002}\0228/namespaces/{namespace}/activities/{activity_id}/outcomeZA\022?/api/v1/namespaces/{namespace}/activities/{activity_id}/outcome" + ]._serialized_options = b"\202\323\344\223\002}\0228/namespaces/{namespace}/activities/{activity_id}/outcomeZA\022?/api/v1/namespaces/{namespace}/activities/{activity_id}/outcome\212\235\314\033.\n\024temporal-resource-id\022\026activity:{activity_id}" + _WORKFLOWSERVICE.methods_by_name["PollNexusOperationExecution"]._options = None + _WORKFLOWSERVICE.methods_by_name[ + "PollNexusOperationExecution" + ]._serialized_options = b"\202\323\344\223\002\205\001\022/api/v1/namespaces/{namespace}/activities/{activity_id}/cancel:\001*' + ]._serialized_options = b'\202\323\344\223\002\201\001"7/namespaces/{namespace}/activities/{activity_id}/cancel:\001*ZC">/api/v1/namespaces/{namespace}/activities/{activity_id}/cancel:\001*\212\235\314\033.\n\024temporal-resource-id\022\026activity:{activity_id}' + _WORKFLOWSERVICE.methods_by_name[ + "RequestCancelNexusOperationExecution" + ]._options = None + _WORKFLOWSERVICE.methods_by_name[ + "RequestCancelNexusOperationExecution" + ]._serialized_options = b'\202\323\344\223\002\217\001">/namespaces/{namespace}/nexus-operations/{operation_id}/cancel:\001*ZJ"E/api/v1/namespaces/{namespace}/nexus-operations/{operation_id}/cancel:\001*' _WORKFLOWSERVICE.methods_by_name["TerminateActivityExecution"]._options = None _WORKFLOWSERVICE.methods_by_name[ "TerminateActivityExecution" - ]._serialized_options = b'\202\323\344\223\002\207\001":/namespaces/{namespace}/activities/{activity_id}/terminate:\001*ZF"A/api/v1/namespaces/{namespace}/activities/{activity_id}/terminate:\001*' + ]._serialized_options = b'\202\323\344\223\002\207\001":/namespaces/{namespace}/activities/{activity_id}/terminate:\001*ZF"A/api/v1/namespaces/{namespace}/activities/{activity_id}/terminate:\001*\212\235\314\033.\n\024temporal-resource-id\022\026activity:{activity_id}' + _WORKFLOWSERVICE.methods_by_name["TerminateNexusOperationExecution"]._options = None + _WORKFLOWSERVICE.methods_by_name[ + "TerminateNexusOperationExecution" + ]._serialized_options = b'\202\323\344\223\002\225\001"A/namespaces/{namespace}/nexus-operations/{operation_id}/terminate:\001*ZM"H/api/v1/namespaces/{namespace}/nexus-operations/{operation_id}/terminate:\001*' _WORKFLOWSERVICE._serialized_start = 215 - _WORKFLOWSERVICE._serialized_end = 31954 + _WORKFLOWSERVICE._serialized_end = 36608 # @@protoc_insertion_point(module_scope) diff --git a/temporalio/api/workflowservice/v1/service_pb2_grpc.py b/temporalio/api/workflowservice/v1/service_pb2_grpc.py index 0950eb582..3190ce460 100644 --- a/temporalio/api/workflowservice/v1/service_pb2_grpc.py +++ b/temporalio/api/workflowservice/v1/service_pb2_grpc.py @@ -368,6 +368,26 @@ def __init__(self, channel): request_serializer=temporal_dot_api_dot_workflowservice_dot_v1_dot_request__response__pb2.ListWorkerDeploymentsRequest.SerializeToString, response_deserializer=temporal_dot_api_dot_workflowservice_dot_v1_dot_request__response__pb2.ListWorkerDeploymentsResponse.FromString, ) + self.CreateWorkerDeployment = channel.unary_unary( + "/temporal.api.workflowservice.v1.WorkflowService/CreateWorkerDeployment", + request_serializer=temporal_dot_api_dot_workflowservice_dot_v1_dot_request__response__pb2.CreateWorkerDeploymentRequest.SerializeToString, + response_deserializer=temporal_dot_api_dot_workflowservice_dot_v1_dot_request__response__pb2.CreateWorkerDeploymentResponse.FromString, + ) + self.CreateWorkerDeploymentVersion = channel.unary_unary( + "/temporal.api.workflowservice.v1.WorkflowService/CreateWorkerDeploymentVersion", + request_serializer=temporal_dot_api_dot_workflowservice_dot_v1_dot_request__response__pb2.CreateWorkerDeploymentVersionRequest.SerializeToString, + response_deserializer=temporal_dot_api_dot_workflowservice_dot_v1_dot_request__response__pb2.CreateWorkerDeploymentVersionResponse.FromString, + ) + self.UpdateWorkerDeploymentVersionComputeConfig = channel.unary_unary( + "/temporal.api.workflowservice.v1.WorkflowService/UpdateWorkerDeploymentVersionComputeConfig", + request_serializer=temporal_dot_api_dot_workflowservice_dot_v1_dot_request__response__pb2.UpdateWorkerDeploymentVersionComputeConfigRequest.SerializeToString, + response_deserializer=temporal_dot_api_dot_workflowservice_dot_v1_dot_request__response__pb2.UpdateWorkerDeploymentVersionComputeConfigResponse.FromString, + ) + self.ValidateWorkerDeploymentVersionComputeConfig = channel.unary_unary( + "/temporal.api.workflowservice.v1.WorkflowService/ValidateWorkerDeploymentVersionComputeConfig", + request_serializer=temporal_dot_api_dot_workflowservice_dot_v1_dot_request__response__pb2.ValidateWorkerDeploymentVersionComputeConfigRequest.SerializeToString, + response_deserializer=temporal_dot_api_dot_workflowservice_dot_v1_dot_request__response__pb2.ValidateWorkerDeploymentVersionComputeConfigResponse.FromString, + ) self.UpdateWorkerDeploymentVersionMetadata = channel.unary_unary( "/temporal.api.workflowservice.v1.WorkflowService/UpdateWorkerDeploymentVersionMetadata", request_serializer=temporal_dot_api_dot_workflowservice_dot_v1_dot_request__response__pb2.UpdateWorkerDeploymentVersionMetadataRequest.SerializeToString, @@ -518,31 +538,61 @@ def __init__(self, channel): request_serializer=temporal_dot_api_dot_workflowservice_dot_v1_dot_request__response__pb2.StartActivityExecutionRequest.SerializeToString, response_deserializer=temporal_dot_api_dot_workflowservice_dot_v1_dot_request__response__pb2.StartActivityExecutionResponse.FromString, ) + self.StartNexusOperationExecution = channel.unary_unary( + "/temporal.api.workflowservice.v1.WorkflowService/StartNexusOperationExecution", + request_serializer=temporal_dot_api_dot_workflowservice_dot_v1_dot_request__response__pb2.StartNexusOperationExecutionRequest.SerializeToString, + response_deserializer=temporal_dot_api_dot_workflowservice_dot_v1_dot_request__response__pb2.StartNexusOperationExecutionResponse.FromString, + ) self.DescribeActivityExecution = channel.unary_unary( "/temporal.api.workflowservice.v1.WorkflowService/DescribeActivityExecution", request_serializer=temporal_dot_api_dot_workflowservice_dot_v1_dot_request__response__pb2.DescribeActivityExecutionRequest.SerializeToString, response_deserializer=temporal_dot_api_dot_workflowservice_dot_v1_dot_request__response__pb2.DescribeActivityExecutionResponse.FromString, ) + self.DescribeNexusOperationExecution = channel.unary_unary( + "/temporal.api.workflowservice.v1.WorkflowService/DescribeNexusOperationExecution", + request_serializer=temporal_dot_api_dot_workflowservice_dot_v1_dot_request__response__pb2.DescribeNexusOperationExecutionRequest.SerializeToString, + response_deserializer=temporal_dot_api_dot_workflowservice_dot_v1_dot_request__response__pb2.DescribeNexusOperationExecutionResponse.FromString, + ) self.PollActivityExecution = channel.unary_unary( "/temporal.api.workflowservice.v1.WorkflowService/PollActivityExecution", request_serializer=temporal_dot_api_dot_workflowservice_dot_v1_dot_request__response__pb2.PollActivityExecutionRequest.SerializeToString, response_deserializer=temporal_dot_api_dot_workflowservice_dot_v1_dot_request__response__pb2.PollActivityExecutionResponse.FromString, ) + self.PollNexusOperationExecution = channel.unary_unary( + "/temporal.api.workflowservice.v1.WorkflowService/PollNexusOperationExecution", + request_serializer=temporal_dot_api_dot_workflowservice_dot_v1_dot_request__response__pb2.PollNexusOperationExecutionRequest.SerializeToString, + response_deserializer=temporal_dot_api_dot_workflowservice_dot_v1_dot_request__response__pb2.PollNexusOperationExecutionResponse.FromString, + ) self.ListActivityExecutions = channel.unary_unary( "/temporal.api.workflowservice.v1.WorkflowService/ListActivityExecutions", request_serializer=temporal_dot_api_dot_workflowservice_dot_v1_dot_request__response__pb2.ListActivityExecutionsRequest.SerializeToString, response_deserializer=temporal_dot_api_dot_workflowservice_dot_v1_dot_request__response__pb2.ListActivityExecutionsResponse.FromString, ) + self.ListNexusOperationExecutions = channel.unary_unary( + "/temporal.api.workflowservice.v1.WorkflowService/ListNexusOperationExecutions", + request_serializer=temporal_dot_api_dot_workflowservice_dot_v1_dot_request__response__pb2.ListNexusOperationExecutionsRequest.SerializeToString, + response_deserializer=temporal_dot_api_dot_workflowservice_dot_v1_dot_request__response__pb2.ListNexusOperationExecutionsResponse.FromString, + ) self.CountActivityExecutions = channel.unary_unary( "/temporal.api.workflowservice.v1.WorkflowService/CountActivityExecutions", request_serializer=temporal_dot_api_dot_workflowservice_dot_v1_dot_request__response__pb2.CountActivityExecutionsRequest.SerializeToString, response_deserializer=temporal_dot_api_dot_workflowservice_dot_v1_dot_request__response__pb2.CountActivityExecutionsResponse.FromString, ) + self.CountNexusOperationExecutions = channel.unary_unary( + "/temporal.api.workflowservice.v1.WorkflowService/CountNexusOperationExecutions", + request_serializer=temporal_dot_api_dot_workflowservice_dot_v1_dot_request__response__pb2.CountNexusOperationExecutionsRequest.SerializeToString, + response_deserializer=temporal_dot_api_dot_workflowservice_dot_v1_dot_request__response__pb2.CountNexusOperationExecutionsResponse.FromString, + ) self.RequestCancelActivityExecution = channel.unary_unary( "/temporal.api.workflowservice.v1.WorkflowService/RequestCancelActivityExecution", request_serializer=temporal_dot_api_dot_workflowservice_dot_v1_dot_request__response__pb2.RequestCancelActivityExecutionRequest.SerializeToString, response_deserializer=temporal_dot_api_dot_workflowservice_dot_v1_dot_request__response__pb2.RequestCancelActivityExecutionResponse.FromString, ) + self.RequestCancelNexusOperationExecution = channel.unary_unary( + "/temporal.api.workflowservice.v1.WorkflowService/RequestCancelNexusOperationExecution", + request_serializer=temporal_dot_api_dot_workflowservice_dot_v1_dot_request__response__pb2.RequestCancelNexusOperationExecutionRequest.SerializeToString, + response_deserializer=temporal_dot_api_dot_workflowservice_dot_v1_dot_request__response__pb2.RequestCancelNexusOperationExecutionResponse.FromString, + ) self.TerminateActivityExecution = channel.unary_unary( "/temporal.api.workflowservice.v1.WorkflowService/TerminateActivityExecution", request_serializer=temporal_dot_api_dot_workflowservice_dot_v1_dot_request__response__pb2.TerminateActivityExecutionRequest.SerializeToString, @@ -553,6 +603,16 @@ def __init__(self, channel): request_serializer=temporal_dot_api_dot_workflowservice_dot_v1_dot_request__response__pb2.DeleteActivityExecutionRequest.SerializeToString, response_deserializer=temporal_dot_api_dot_workflowservice_dot_v1_dot_request__response__pb2.DeleteActivityExecutionResponse.FromString, ) + self.TerminateNexusOperationExecution = channel.unary_unary( + "/temporal.api.workflowservice.v1.WorkflowService/TerminateNexusOperationExecution", + request_serializer=temporal_dot_api_dot_workflowservice_dot_v1_dot_request__response__pb2.TerminateNexusOperationExecutionRequest.SerializeToString, + response_deserializer=temporal_dot_api_dot_workflowservice_dot_v1_dot_request__response__pb2.TerminateNexusOperationExecutionResponse.FromString, + ) + self.DeleteNexusOperationExecution = channel.unary_unary( + "/temporal.api.workflowservice.v1.WorkflowService/DeleteNexusOperationExecution", + request_serializer=temporal_dot_api_dot_workflowservice_dot_v1_dot_request__response__pb2.DeleteNexusOperationExecutionRequest.SerializeToString, + response_deserializer=temporal_dot_api_dot_workflowservice_dot_v1_dot_request__response__pb2.DeleteNexusOperationExecutionResponse.FromString, + ) class WorkflowServiceServicer(object): @@ -1306,6 +1366,42 @@ def ListWorkerDeployments(self, request, context): context.set_details("Method not implemented!") raise NotImplementedError("Method not implemented!") + def CreateWorkerDeployment(self, request, context): + """Creates a new Worker Deployment. + + Experimental. This API might significantly change or be removed in a + future release. + """ + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details("Method not implemented!") + raise NotImplementedError("Method not implemented!") + + def CreateWorkerDeploymentVersion(self, request, context): + """Creates a new Worker Deployment Version. + + Experimental. This API might significantly change or be removed in a + future release. + """ + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details("Method not implemented!") + raise NotImplementedError("Method not implemented!") + + def UpdateWorkerDeploymentVersionComputeConfig(self, request, context): + """Updates the compute config attached to a Worker Deployment Version. + Experimental. This API might significantly change or be removed in a future release. + """ + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details("Method not implemented!") + raise NotImplementedError("Method not implemented!") + + def ValidateWorkerDeploymentVersionComputeConfig(self, request, context): + """Validates the compute config without attaching it to a Worker Deployment Version. + Experimental. This API might significantly change or be removed in a future release. + """ + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details("Method not implemented!") + raise NotImplementedError("Method not implemented!") + def UpdateWorkerDeploymentVersionMetadata(self, request, context): """Updates the user-given metadata attached to a Worker Deployment Version. Experimental. This API might significantly change or be removed in a future release. @@ -1597,6 +1693,16 @@ def StartActivityExecution(self, request, context): context.set_details("Method not implemented!") raise NotImplementedError("Method not implemented!") + def StartNexusOperationExecution(self, request, context): + """StartNexusOperationExecution starts a new Nexus operation. + + Returns a `NexusOperationExecutionAlreadyStarted` error if an instance already exists with same operation ID in this + namespace unless permitted by the specified ID conflict policy. + """ + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details("Method not implemented!") + raise NotImplementedError("Method not implemented!") + def DescribeActivityExecution(self, request, context): """DescribeActivityExecution returns information about an activity execution. It can be used to: @@ -1608,6 +1714,17 @@ def DescribeActivityExecution(self, request, context): context.set_details("Method not implemented!") raise NotImplementedError("Method not implemented!") + def DescribeNexusOperationExecution(self, request, context): + """DescribeNexusOperationExecution returns information about a Nexus operation. + Supported use cases include: + - Get current operation info without waiting + - Long-poll for next state change and return new operation info + Response can optionally include operation input or outcome (if the operation has completed). + """ + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details("Method not implemented!") + raise NotImplementedError("Method not implemented!") + def PollActivityExecution(self, request, context): """PollActivityExecution long-polls for an activity execution to complete and returns the outcome (result or failure). @@ -1616,18 +1733,38 @@ def PollActivityExecution(self, request, context): context.set_details("Method not implemented!") raise NotImplementedError("Method not implemented!") + def PollNexusOperationExecution(self, request, context): + """PollNexusOperationExecution long-polls for a Nexus operation for a given wait stage to complete and returns + the outcome (result or failure). + """ + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details("Method not implemented!") + raise NotImplementedError("Method not implemented!") + def ListActivityExecutions(self, request, context): """ListActivityExecutions is a visibility API to list activity executions in a specific namespace.""" context.set_code(grpc.StatusCode.UNIMPLEMENTED) context.set_details("Method not implemented!") raise NotImplementedError("Method not implemented!") + def ListNexusOperationExecutions(self, request, context): + """ListNexusOperationExecutions is a visibility API to list Nexus operations in a specific namespace.""" + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details("Method not implemented!") + raise NotImplementedError("Method not implemented!") + def CountActivityExecutions(self, request, context): """CountActivityExecutions is a visibility API to count activity executions in a specific namespace.""" context.set_code(grpc.StatusCode.UNIMPLEMENTED) context.set_details("Method not implemented!") raise NotImplementedError("Method not implemented!") + def CountNexusOperationExecutions(self, request, context): + """CountNexusOperationExecutions is a visibility API to count Nexus operations in a specific namespace.""" + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details("Method not implemented!") + raise NotImplementedError("Method not implemented!") + def RequestCancelActivityExecution(self, request, context): """RequestCancelActivityExecution requests cancellation of an activity execution. @@ -1640,6 +1777,17 @@ def RequestCancelActivityExecution(self, request, context): context.set_details("Method not implemented!") raise NotImplementedError("Method not implemented!") + def RequestCancelNexusOperationExecution(self, request, context): + """RequestCancelNexusOperationExecution requests cancellation of a Nexus operation. + + Requesting to cancel an operation does not automatically transition the operation to canceled status. + The operation will only transition to canceled status if it supports cancellation and the handler + processes the cancellation request. + """ + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details("Method not implemented!") + raise NotImplementedError("Method not implemented!") + def TerminateActivityExecution(self, request, context): """TerminateActivityExecution terminates an existing activity execution immediately. @@ -1663,6 +1811,28 @@ def DeleteActivityExecution(self, request, context): context.set_details("Method not implemented!") raise NotImplementedError("Method not implemented!") + def TerminateNexusOperationExecution(self, request, context): + """TerminateNexusOperationExecution terminates an existing Nexus operation immediately. + + Termination happens immediately and the operation handler cannot react to it. A terminated operation will have + its outcome set to a failure with a termination reason. + """ + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details("Method not implemented!") + raise NotImplementedError("Method not implemented!") + + def DeleteNexusOperationExecution(self, request, context): + """DeleteNexusOperationExecution asynchronously deletes a specific Nexus operation run (when + run_id is provided) or the latest run (when run_id is not provided). If the operation + is running, it will be terminated before deletion. + + (-- api-linter: core::0127::http-annotation=disabled + aip.dev/not-precedent: Nexus operation deletion not exposed to HTTP, users should use cancel or terminate. --) + """ + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details("Method not implemented!") + raise NotImplementedError("Method not implemented!") + def add_WorkflowServiceServicer_to_server(servicer, server): rpc_method_handlers = { @@ -2006,6 +2176,26 @@ def add_WorkflowServiceServicer_to_server(servicer, server): request_deserializer=temporal_dot_api_dot_workflowservice_dot_v1_dot_request__response__pb2.ListWorkerDeploymentsRequest.FromString, response_serializer=temporal_dot_api_dot_workflowservice_dot_v1_dot_request__response__pb2.ListWorkerDeploymentsResponse.SerializeToString, ), + "CreateWorkerDeployment": grpc.unary_unary_rpc_method_handler( + servicer.CreateWorkerDeployment, + request_deserializer=temporal_dot_api_dot_workflowservice_dot_v1_dot_request__response__pb2.CreateWorkerDeploymentRequest.FromString, + response_serializer=temporal_dot_api_dot_workflowservice_dot_v1_dot_request__response__pb2.CreateWorkerDeploymentResponse.SerializeToString, + ), + "CreateWorkerDeploymentVersion": grpc.unary_unary_rpc_method_handler( + servicer.CreateWorkerDeploymentVersion, + request_deserializer=temporal_dot_api_dot_workflowservice_dot_v1_dot_request__response__pb2.CreateWorkerDeploymentVersionRequest.FromString, + response_serializer=temporal_dot_api_dot_workflowservice_dot_v1_dot_request__response__pb2.CreateWorkerDeploymentVersionResponse.SerializeToString, + ), + "UpdateWorkerDeploymentVersionComputeConfig": grpc.unary_unary_rpc_method_handler( + servicer.UpdateWorkerDeploymentVersionComputeConfig, + request_deserializer=temporal_dot_api_dot_workflowservice_dot_v1_dot_request__response__pb2.UpdateWorkerDeploymentVersionComputeConfigRequest.FromString, + response_serializer=temporal_dot_api_dot_workflowservice_dot_v1_dot_request__response__pb2.UpdateWorkerDeploymentVersionComputeConfigResponse.SerializeToString, + ), + "ValidateWorkerDeploymentVersionComputeConfig": grpc.unary_unary_rpc_method_handler( + servicer.ValidateWorkerDeploymentVersionComputeConfig, + request_deserializer=temporal_dot_api_dot_workflowservice_dot_v1_dot_request__response__pb2.ValidateWorkerDeploymentVersionComputeConfigRequest.FromString, + response_serializer=temporal_dot_api_dot_workflowservice_dot_v1_dot_request__response__pb2.ValidateWorkerDeploymentVersionComputeConfigResponse.SerializeToString, + ), "UpdateWorkerDeploymentVersionMetadata": grpc.unary_unary_rpc_method_handler( servicer.UpdateWorkerDeploymentVersionMetadata, request_deserializer=temporal_dot_api_dot_workflowservice_dot_v1_dot_request__response__pb2.UpdateWorkerDeploymentVersionMetadataRequest.FromString, @@ -2156,31 +2346,61 @@ def add_WorkflowServiceServicer_to_server(servicer, server): request_deserializer=temporal_dot_api_dot_workflowservice_dot_v1_dot_request__response__pb2.StartActivityExecutionRequest.FromString, response_serializer=temporal_dot_api_dot_workflowservice_dot_v1_dot_request__response__pb2.StartActivityExecutionResponse.SerializeToString, ), + "StartNexusOperationExecution": grpc.unary_unary_rpc_method_handler( + servicer.StartNexusOperationExecution, + request_deserializer=temporal_dot_api_dot_workflowservice_dot_v1_dot_request__response__pb2.StartNexusOperationExecutionRequest.FromString, + response_serializer=temporal_dot_api_dot_workflowservice_dot_v1_dot_request__response__pb2.StartNexusOperationExecutionResponse.SerializeToString, + ), "DescribeActivityExecution": grpc.unary_unary_rpc_method_handler( servicer.DescribeActivityExecution, request_deserializer=temporal_dot_api_dot_workflowservice_dot_v1_dot_request__response__pb2.DescribeActivityExecutionRequest.FromString, response_serializer=temporal_dot_api_dot_workflowservice_dot_v1_dot_request__response__pb2.DescribeActivityExecutionResponse.SerializeToString, ), + "DescribeNexusOperationExecution": grpc.unary_unary_rpc_method_handler( + servicer.DescribeNexusOperationExecution, + request_deserializer=temporal_dot_api_dot_workflowservice_dot_v1_dot_request__response__pb2.DescribeNexusOperationExecutionRequest.FromString, + response_serializer=temporal_dot_api_dot_workflowservice_dot_v1_dot_request__response__pb2.DescribeNexusOperationExecutionResponse.SerializeToString, + ), "PollActivityExecution": grpc.unary_unary_rpc_method_handler( servicer.PollActivityExecution, request_deserializer=temporal_dot_api_dot_workflowservice_dot_v1_dot_request__response__pb2.PollActivityExecutionRequest.FromString, response_serializer=temporal_dot_api_dot_workflowservice_dot_v1_dot_request__response__pb2.PollActivityExecutionResponse.SerializeToString, ), + "PollNexusOperationExecution": grpc.unary_unary_rpc_method_handler( + servicer.PollNexusOperationExecution, + request_deserializer=temporal_dot_api_dot_workflowservice_dot_v1_dot_request__response__pb2.PollNexusOperationExecutionRequest.FromString, + response_serializer=temporal_dot_api_dot_workflowservice_dot_v1_dot_request__response__pb2.PollNexusOperationExecutionResponse.SerializeToString, + ), "ListActivityExecutions": grpc.unary_unary_rpc_method_handler( servicer.ListActivityExecutions, request_deserializer=temporal_dot_api_dot_workflowservice_dot_v1_dot_request__response__pb2.ListActivityExecutionsRequest.FromString, response_serializer=temporal_dot_api_dot_workflowservice_dot_v1_dot_request__response__pb2.ListActivityExecutionsResponse.SerializeToString, ), + "ListNexusOperationExecutions": grpc.unary_unary_rpc_method_handler( + servicer.ListNexusOperationExecutions, + request_deserializer=temporal_dot_api_dot_workflowservice_dot_v1_dot_request__response__pb2.ListNexusOperationExecutionsRequest.FromString, + response_serializer=temporal_dot_api_dot_workflowservice_dot_v1_dot_request__response__pb2.ListNexusOperationExecutionsResponse.SerializeToString, + ), "CountActivityExecutions": grpc.unary_unary_rpc_method_handler( servicer.CountActivityExecutions, request_deserializer=temporal_dot_api_dot_workflowservice_dot_v1_dot_request__response__pb2.CountActivityExecutionsRequest.FromString, response_serializer=temporal_dot_api_dot_workflowservice_dot_v1_dot_request__response__pb2.CountActivityExecutionsResponse.SerializeToString, ), + "CountNexusOperationExecutions": grpc.unary_unary_rpc_method_handler( + servicer.CountNexusOperationExecutions, + request_deserializer=temporal_dot_api_dot_workflowservice_dot_v1_dot_request__response__pb2.CountNexusOperationExecutionsRequest.FromString, + response_serializer=temporal_dot_api_dot_workflowservice_dot_v1_dot_request__response__pb2.CountNexusOperationExecutionsResponse.SerializeToString, + ), "RequestCancelActivityExecution": grpc.unary_unary_rpc_method_handler( servicer.RequestCancelActivityExecution, request_deserializer=temporal_dot_api_dot_workflowservice_dot_v1_dot_request__response__pb2.RequestCancelActivityExecutionRequest.FromString, response_serializer=temporal_dot_api_dot_workflowservice_dot_v1_dot_request__response__pb2.RequestCancelActivityExecutionResponse.SerializeToString, ), + "RequestCancelNexusOperationExecution": grpc.unary_unary_rpc_method_handler( + servicer.RequestCancelNexusOperationExecution, + request_deserializer=temporal_dot_api_dot_workflowservice_dot_v1_dot_request__response__pb2.RequestCancelNexusOperationExecutionRequest.FromString, + response_serializer=temporal_dot_api_dot_workflowservice_dot_v1_dot_request__response__pb2.RequestCancelNexusOperationExecutionResponse.SerializeToString, + ), "TerminateActivityExecution": grpc.unary_unary_rpc_method_handler( servicer.TerminateActivityExecution, request_deserializer=temporal_dot_api_dot_workflowservice_dot_v1_dot_request__response__pb2.TerminateActivityExecutionRequest.FromString, @@ -2191,6 +2411,16 @@ def add_WorkflowServiceServicer_to_server(servicer, server): request_deserializer=temporal_dot_api_dot_workflowservice_dot_v1_dot_request__response__pb2.DeleteActivityExecutionRequest.FromString, response_serializer=temporal_dot_api_dot_workflowservice_dot_v1_dot_request__response__pb2.DeleteActivityExecutionResponse.SerializeToString, ), + "TerminateNexusOperationExecution": grpc.unary_unary_rpc_method_handler( + servicer.TerminateNexusOperationExecution, + request_deserializer=temporal_dot_api_dot_workflowservice_dot_v1_dot_request__response__pb2.TerminateNexusOperationExecutionRequest.FromString, + response_serializer=temporal_dot_api_dot_workflowservice_dot_v1_dot_request__response__pb2.TerminateNexusOperationExecutionResponse.SerializeToString, + ), + "DeleteNexusOperationExecution": grpc.unary_unary_rpc_method_handler( + servicer.DeleteNexusOperationExecution, + request_deserializer=temporal_dot_api_dot_workflowservice_dot_v1_dot_request__response__pb2.DeleteNexusOperationExecutionRequest.FromString, + response_serializer=temporal_dot_api_dot_workflowservice_dot_v1_dot_request__response__pb2.DeleteNexusOperationExecutionResponse.SerializeToString, + ), } generic_handler = grpc.method_handlers_generic_handler( "temporal.api.workflowservice.v1.WorkflowService", rpc_method_handlers @@ -4185,6 +4415,122 @@ def ListWorkerDeployments( metadata, ) + @staticmethod + def CreateWorkerDeployment( + request, + target, + options=(), + channel_credentials=None, + call_credentials=None, + insecure=False, + compression=None, + wait_for_ready=None, + timeout=None, + metadata=None, + ): + return grpc.experimental.unary_unary( + request, + target, + "/temporal.api.workflowservice.v1.WorkflowService/CreateWorkerDeployment", + temporal_dot_api_dot_workflowservice_dot_v1_dot_request__response__pb2.CreateWorkerDeploymentRequest.SerializeToString, + temporal_dot_api_dot_workflowservice_dot_v1_dot_request__response__pb2.CreateWorkerDeploymentResponse.FromString, + options, + channel_credentials, + insecure, + call_credentials, + compression, + wait_for_ready, + timeout, + metadata, + ) + + @staticmethod + def CreateWorkerDeploymentVersion( + request, + target, + options=(), + channel_credentials=None, + call_credentials=None, + insecure=False, + compression=None, + wait_for_ready=None, + timeout=None, + metadata=None, + ): + return grpc.experimental.unary_unary( + request, + target, + "/temporal.api.workflowservice.v1.WorkflowService/CreateWorkerDeploymentVersion", + temporal_dot_api_dot_workflowservice_dot_v1_dot_request__response__pb2.CreateWorkerDeploymentVersionRequest.SerializeToString, + temporal_dot_api_dot_workflowservice_dot_v1_dot_request__response__pb2.CreateWorkerDeploymentVersionResponse.FromString, + options, + channel_credentials, + insecure, + call_credentials, + compression, + wait_for_ready, + timeout, + metadata, + ) + + @staticmethod + def UpdateWorkerDeploymentVersionComputeConfig( + request, + target, + options=(), + channel_credentials=None, + call_credentials=None, + insecure=False, + compression=None, + wait_for_ready=None, + timeout=None, + metadata=None, + ): + return grpc.experimental.unary_unary( + request, + target, + "/temporal.api.workflowservice.v1.WorkflowService/UpdateWorkerDeploymentVersionComputeConfig", + temporal_dot_api_dot_workflowservice_dot_v1_dot_request__response__pb2.UpdateWorkerDeploymentVersionComputeConfigRequest.SerializeToString, + temporal_dot_api_dot_workflowservice_dot_v1_dot_request__response__pb2.UpdateWorkerDeploymentVersionComputeConfigResponse.FromString, + options, + channel_credentials, + insecure, + call_credentials, + compression, + wait_for_ready, + timeout, + metadata, + ) + + @staticmethod + def ValidateWorkerDeploymentVersionComputeConfig( + request, + target, + options=(), + channel_credentials=None, + call_credentials=None, + insecure=False, + compression=None, + wait_for_ready=None, + timeout=None, + metadata=None, + ): + return grpc.experimental.unary_unary( + request, + target, + "/temporal.api.workflowservice.v1.WorkflowService/ValidateWorkerDeploymentVersionComputeConfig", + temporal_dot_api_dot_workflowservice_dot_v1_dot_request__response__pb2.ValidateWorkerDeploymentVersionComputeConfigRequest.SerializeToString, + temporal_dot_api_dot_workflowservice_dot_v1_dot_request__response__pb2.ValidateWorkerDeploymentVersionComputeConfigResponse.FromString, + options, + channel_credentials, + insecure, + call_credentials, + compression, + wait_for_ready, + timeout, + metadata, + ) + @staticmethod def UpdateWorkerDeploymentVersionMetadata( request, @@ -5055,6 +5401,35 @@ def StartActivityExecution( metadata, ) + @staticmethod + def StartNexusOperationExecution( + request, + target, + options=(), + channel_credentials=None, + call_credentials=None, + insecure=False, + compression=None, + wait_for_ready=None, + timeout=None, + metadata=None, + ): + return grpc.experimental.unary_unary( + request, + target, + "/temporal.api.workflowservice.v1.WorkflowService/StartNexusOperationExecution", + temporal_dot_api_dot_workflowservice_dot_v1_dot_request__response__pb2.StartNexusOperationExecutionRequest.SerializeToString, + temporal_dot_api_dot_workflowservice_dot_v1_dot_request__response__pb2.StartNexusOperationExecutionResponse.FromString, + options, + channel_credentials, + insecure, + call_credentials, + compression, + wait_for_ready, + timeout, + metadata, + ) + @staticmethod def DescribeActivityExecution( request, @@ -5084,6 +5459,35 @@ def DescribeActivityExecution( metadata, ) + @staticmethod + def DescribeNexusOperationExecution( + request, + target, + options=(), + channel_credentials=None, + call_credentials=None, + insecure=False, + compression=None, + wait_for_ready=None, + timeout=None, + metadata=None, + ): + return grpc.experimental.unary_unary( + request, + target, + "/temporal.api.workflowservice.v1.WorkflowService/DescribeNexusOperationExecution", + temporal_dot_api_dot_workflowservice_dot_v1_dot_request__response__pb2.DescribeNexusOperationExecutionRequest.SerializeToString, + temporal_dot_api_dot_workflowservice_dot_v1_dot_request__response__pb2.DescribeNexusOperationExecutionResponse.FromString, + options, + channel_credentials, + insecure, + call_credentials, + compression, + wait_for_ready, + timeout, + metadata, + ) + @staticmethod def PollActivityExecution( request, @@ -5113,6 +5517,35 @@ def PollActivityExecution( metadata, ) + @staticmethod + def PollNexusOperationExecution( + request, + target, + options=(), + channel_credentials=None, + call_credentials=None, + insecure=False, + compression=None, + wait_for_ready=None, + timeout=None, + metadata=None, + ): + return grpc.experimental.unary_unary( + request, + target, + "/temporal.api.workflowservice.v1.WorkflowService/PollNexusOperationExecution", + temporal_dot_api_dot_workflowservice_dot_v1_dot_request__response__pb2.PollNexusOperationExecutionRequest.SerializeToString, + temporal_dot_api_dot_workflowservice_dot_v1_dot_request__response__pb2.PollNexusOperationExecutionResponse.FromString, + options, + channel_credentials, + insecure, + call_credentials, + compression, + wait_for_ready, + timeout, + metadata, + ) + @staticmethod def ListActivityExecutions( request, @@ -5142,6 +5575,35 @@ def ListActivityExecutions( metadata, ) + @staticmethod + def ListNexusOperationExecutions( + request, + target, + options=(), + channel_credentials=None, + call_credentials=None, + insecure=False, + compression=None, + wait_for_ready=None, + timeout=None, + metadata=None, + ): + return grpc.experimental.unary_unary( + request, + target, + "/temporal.api.workflowservice.v1.WorkflowService/ListNexusOperationExecutions", + temporal_dot_api_dot_workflowservice_dot_v1_dot_request__response__pb2.ListNexusOperationExecutionsRequest.SerializeToString, + temporal_dot_api_dot_workflowservice_dot_v1_dot_request__response__pb2.ListNexusOperationExecutionsResponse.FromString, + options, + channel_credentials, + insecure, + call_credentials, + compression, + wait_for_ready, + timeout, + metadata, + ) + @staticmethod def CountActivityExecutions( request, @@ -5171,6 +5633,35 @@ def CountActivityExecutions( metadata, ) + @staticmethod + def CountNexusOperationExecutions( + request, + target, + options=(), + channel_credentials=None, + call_credentials=None, + insecure=False, + compression=None, + wait_for_ready=None, + timeout=None, + metadata=None, + ): + return grpc.experimental.unary_unary( + request, + target, + "/temporal.api.workflowservice.v1.WorkflowService/CountNexusOperationExecutions", + temporal_dot_api_dot_workflowservice_dot_v1_dot_request__response__pb2.CountNexusOperationExecutionsRequest.SerializeToString, + temporal_dot_api_dot_workflowservice_dot_v1_dot_request__response__pb2.CountNexusOperationExecutionsResponse.FromString, + options, + channel_credentials, + insecure, + call_credentials, + compression, + wait_for_ready, + timeout, + metadata, + ) + @staticmethod def RequestCancelActivityExecution( request, @@ -5200,6 +5691,35 @@ def RequestCancelActivityExecution( metadata, ) + @staticmethod + def RequestCancelNexusOperationExecution( + request, + target, + options=(), + channel_credentials=None, + call_credentials=None, + insecure=False, + compression=None, + wait_for_ready=None, + timeout=None, + metadata=None, + ): + return grpc.experimental.unary_unary( + request, + target, + "/temporal.api.workflowservice.v1.WorkflowService/RequestCancelNexusOperationExecution", + temporal_dot_api_dot_workflowservice_dot_v1_dot_request__response__pb2.RequestCancelNexusOperationExecutionRequest.SerializeToString, + temporal_dot_api_dot_workflowservice_dot_v1_dot_request__response__pb2.RequestCancelNexusOperationExecutionResponse.FromString, + options, + channel_credentials, + insecure, + call_credentials, + compression, + wait_for_ready, + timeout, + metadata, + ) + @staticmethod def TerminateActivityExecution( request, @@ -5257,3 +5777,61 @@ def DeleteActivityExecution( timeout, metadata, ) + + @staticmethod + def TerminateNexusOperationExecution( + request, + target, + options=(), + channel_credentials=None, + call_credentials=None, + insecure=False, + compression=None, + wait_for_ready=None, + timeout=None, + metadata=None, + ): + return grpc.experimental.unary_unary( + request, + target, + "/temporal.api.workflowservice.v1.WorkflowService/TerminateNexusOperationExecution", + temporal_dot_api_dot_workflowservice_dot_v1_dot_request__response__pb2.TerminateNexusOperationExecutionRequest.SerializeToString, + temporal_dot_api_dot_workflowservice_dot_v1_dot_request__response__pb2.TerminateNexusOperationExecutionResponse.FromString, + options, + channel_credentials, + insecure, + call_credentials, + compression, + wait_for_ready, + timeout, + metadata, + ) + + @staticmethod + def DeleteNexusOperationExecution( + request, + target, + options=(), + channel_credentials=None, + call_credentials=None, + insecure=False, + compression=None, + wait_for_ready=None, + timeout=None, + metadata=None, + ): + return grpc.experimental.unary_unary( + request, + target, + "/temporal.api.workflowservice.v1.WorkflowService/DeleteNexusOperationExecution", + temporal_dot_api_dot_workflowservice_dot_v1_dot_request__response__pb2.DeleteNexusOperationExecutionRequest.SerializeToString, + temporal_dot_api_dot_workflowservice_dot_v1_dot_request__response__pb2.DeleteNexusOperationExecutionResponse.FromString, + options, + channel_credentials, + insecure, + call_credentials, + compression, + wait_for_ready, + timeout, + metadata, + ) diff --git a/temporalio/api/workflowservice/v1/service_pb2_grpc.pyi b/temporalio/api/workflowservice/v1/service_pb2_grpc.pyi index 8e58d1f18..caaf0d52e 100644 --- a/temporalio/api/workflowservice/v1/service_pb2_grpc.pyi +++ b/temporalio/api/workflowservice/v1/service_pb2_grpc.pyi @@ -693,6 +693,38 @@ class WorkflowServiceStub: """Lists all Worker Deployments that are tracked in the Namespace. Experimental. This API might significantly change or be removed in a future release. """ + CreateWorkerDeployment: grpc.UnaryUnaryMultiCallable[ + temporalio.api.workflowservice.v1.request_response_pb2.CreateWorkerDeploymentRequest, + temporalio.api.workflowservice.v1.request_response_pb2.CreateWorkerDeploymentResponse, + ] + """Creates a new Worker Deployment. + + Experimental. This API might significantly change or be removed in a + future release. + """ + CreateWorkerDeploymentVersion: grpc.UnaryUnaryMultiCallable[ + temporalio.api.workflowservice.v1.request_response_pb2.CreateWorkerDeploymentVersionRequest, + temporalio.api.workflowservice.v1.request_response_pb2.CreateWorkerDeploymentVersionResponse, + ] + """Creates a new Worker Deployment Version. + + Experimental. This API might significantly change or be removed in a + future release. + """ + UpdateWorkerDeploymentVersionComputeConfig: grpc.UnaryUnaryMultiCallable[ + temporalio.api.workflowservice.v1.request_response_pb2.UpdateWorkerDeploymentVersionComputeConfigRequest, + temporalio.api.workflowservice.v1.request_response_pb2.UpdateWorkerDeploymentVersionComputeConfigResponse, + ] + """Updates the compute config attached to a Worker Deployment Version. + Experimental. This API might significantly change or be removed in a future release. + """ + ValidateWorkerDeploymentVersionComputeConfig: grpc.UnaryUnaryMultiCallable[ + temporalio.api.workflowservice.v1.request_response_pb2.ValidateWorkerDeploymentVersionComputeConfigRequest, + temporalio.api.workflowservice.v1.request_response_pb2.ValidateWorkerDeploymentVersionComputeConfigResponse, + ] + """Validates the compute config without attaching it to a Worker Deployment Version. + Experimental. This API might significantly change or be removed in a future release. + """ UpdateWorkerDeploymentVersionMetadata: grpc.UnaryUnaryMultiCallable[ temporalio.api.workflowservice.v1.request_response_pb2.UpdateWorkerDeploymentVersionMetadataRequest, temporalio.api.workflowservice.v1.request_response_pb2.UpdateWorkerDeploymentVersionMetadataResponse, @@ -954,6 +986,15 @@ class WorkflowServiceStub: Returns an `ActivityExecutionAlreadyStarted` error if an instance already exists with same activity ID in this namespace unless permitted by the specified ID conflict policy. """ + StartNexusOperationExecution: grpc.UnaryUnaryMultiCallable[ + temporalio.api.workflowservice.v1.request_response_pb2.StartNexusOperationExecutionRequest, + temporalio.api.workflowservice.v1.request_response_pb2.StartNexusOperationExecutionResponse, + ] + """StartNexusOperationExecution starts a new Nexus operation. + + Returns a `NexusOperationExecutionAlreadyStarted` error if an instance already exists with same operation ID in this + namespace unless permitted by the specified ID conflict policy. + """ DescribeActivityExecution: grpc.UnaryUnaryMultiCallable[ temporalio.api.workflowservice.v1.request_response_pb2.DescribeActivityExecutionRequest, temporalio.api.workflowservice.v1.request_response_pb2.DescribeActivityExecutionResponse, @@ -964,6 +1005,16 @@ class WorkflowServiceStub: - Long-poll for next state change and return new activity info Response can optionally include activity input or outcome (if the activity has completed). """ + DescribeNexusOperationExecution: grpc.UnaryUnaryMultiCallable[ + temporalio.api.workflowservice.v1.request_response_pb2.DescribeNexusOperationExecutionRequest, + temporalio.api.workflowservice.v1.request_response_pb2.DescribeNexusOperationExecutionResponse, + ] + """DescribeNexusOperationExecution returns information about a Nexus operation. + Supported use cases include: + - Get current operation info without waiting + - Long-poll for next state change and return new operation info + Response can optionally include operation input or outcome (if the operation has completed). + """ PollActivityExecution: grpc.UnaryUnaryMultiCallable[ temporalio.api.workflowservice.v1.request_response_pb2.PollActivityExecutionRequest, temporalio.api.workflowservice.v1.request_response_pb2.PollActivityExecutionResponse, @@ -971,16 +1022,33 @@ class WorkflowServiceStub: """PollActivityExecution long-polls for an activity execution to complete and returns the outcome (result or failure). """ + PollNexusOperationExecution: grpc.UnaryUnaryMultiCallable[ + temporalio.api.workflowservice.v1.request_response_pb2.PollNexusOperationExecutionRequest, + temporalio.api.workflowservice.v1.request_response_pb2.PollNexusOperationExecutionResponse, + ] + """PollNexusOperationExecution long-polls for a Nexus operation for a given wait stage to complete and returns + the outcome (result or failure). + """ ListActivityExecutions: grpc.UnaryUnaryMultiCallable[ temporalio.api.workflowservice.v1.request_response_pb2.ListActivityExecutionsRequest, temporalio.api.workflowservice.v1.request_response_pb2.ListActivityExecutionsResponse, ] """ListActivityExecutions is a visibility API to list activity executions in a specific namespace.""" + ListNexusOperationExecutions: grpc.UnaryUnaryMultiCallable[ + temporalio.api.workflowservice.v1.request_response_pb2.ListNexusOperationExecutionsRequest, + temporalio.api.workflowservice.v1.request_response_pb2.ListNexusOperationExecutionsResponse, + ] + """ListNexusOperationExecutions is a visibility API to list Nexus operations in a specific namespace.""" CountActivityExecutions: grpc.UnaryUnaryMultiCallable[ temporalio.api.workflowservice.v1.request_response_pb2.CountActivityExecutionsRequest, temporalio.api.workflowservice.v1.request_response_pb2.CountActivityExecutionsResponse, ] """CountActivityExecutions is a visibility API to count activity executions in a specific namespace.""" + CountNexusOperationExecutions: grpc.UnaryUnaryMultiCallable[ + temporalio.api.workflowservice.v1.request_response_pb2.CountNexusOperationExecutionsRequest, + temporalio.api.workflowservice.v1.request_response_pb2.CountNexusOperationExecutionsResponse, + ] + """CountNexusOperationExecutions is a visibility API to count Nexus operations in a specific namespace.""" RequestCancelActivityExecution: grpc.UnaryUnaryMultiCallable[ temporalio.api.workflowservice.v1.request_response_pb2.RequestCancelActivityExecutionRequest, temporalio.api.workflowservice.v1.request_response_pb2.RequestCancelActivityExecutionResponse, @@ -992,6 +1060,16 @@ class WorkflowServiceStub: delivered via `cancel_requested` in the heartbeat response; SDKs surface this via language-idiomatic mechanisms (context cancellation, exceptions, abort signals). """ + RequestCancelNexusOperationExecution: grpc.UnaryUnaryMultiCallable[ + temporalio.api.workflowservice.v1.request_response_pb2.RequestCancelNexusOperationExecutionRequest, + temporalio.api.workflowservice.v1.request_response_pb2.RequestCancelNexusOperationExecutionResponse, + ] + """RequestCancelNexusOperationExecution requests cancellation of a Nexus operation. + + Requesting to cancel an operation does not automatically transition the operation to canceled status. + The operation will only transition to canceled status if it supports cancellation and the handler + processes the cancellation request. + """ TerminateActivityExecution: grpc.UnaryUnaryMultiCallable[ temporalio.api.workflowservice.v1.request_response_pb2.TerminateActivityExecutionRequest, temporalio.api.workflowservice.v1.request_response_pb2.TerminateActivityExecutionResponse, @@ -1013,6 +1091,26 @@ class WorkflowServiceStub: (-- api-linter: core::0127::http-annotation=disabled aip.dev/not-precedent: Activity deletion not exposed to HTTP, users should use cancel or terminate. --) """ + TerminateNexusOperationExecution: grpc.UnaryUnaryMultiCallable[ + temporalio.api.workflowservice.v1.request_response_pb2.TerminateNexusOperationExecutionRequest, + temporalio.api.workflowservice.v1.request_response_pb2.TerminateNexusOperationExecutionResponse, + ] + """TerminateNexusOperationExecution terminates an existing Nexus operation immediately. + + Termination happens immediately and the operation handler cannot react to it. A terminated operation will have + its outcome set to a failure with a termination reason. + """ + DeleteNexusOperationExecution: grpc.UnaryUnaryMultiCallable[ + temporalio.api.workflowservice.v1.request_response_pb2.DeleteNexusOperationExecutionRequest, + temporalio.api.workflowservice.v1.request_response_pb2.DeleteNexusOperationExecutionResponse, + ] + """DeleteNexusOperationExecution asynchronously deletes a specific Nexus operation run (when + run_id is provided) or the latest run (when run_id is not provided). If the operation + is running, it will be terminated before deletion. + + (-- api-linter: core::0127::http-annotation=disabled + aip.dev/not-precedent: Nexus operation deletion not exposed to HTTP, users should use cancel or terminate. --) + """ class WorkflowServiceServicer(metaclass=abc.ABCMeta): """WorkflowService API defines how Temporal SDKs and other clients interact with the Temporal server @@ -1842,6 +1940,46 @@ class WorkflowServiceServicer(metaclass=abc.ABCMeta): Experimental. This API might significantly change or be removed in a future release. """ @abc.abstractmethod + def CreateWorkerDeployment( + self, + request: temporalio.api.workflowservice.v1.request_response_pb2.CreateWorkerDeploymentRequest, + context: grpc.ServicerContext, + ) -> temporalio.api.workflowservice.v1.request_response_pb2.CreateWorkerDeploymentResponse: + """Creates a new Worker Deployment. + + Experimental. This API might significantly change or be removed in a + future release. + """ + @abc.abstractmethod + def CreateWorkerDeploymentVersion( + self, + request: temporalio.api.workflowservice.v1.request_response_pb2.CreateWorkerDeploymentVersionRequest, + context: grpc.ServicerContext, + ) -> temporalio.api.workflowservice.v1.request_response_pb2.CreateWorkerDeploymentVersionResponse: + """Creates a new Worker Deployment Version. + + Experimental. This API might significantly change or be removed in a + future release. + """ + @abc.abstractmethod + def UpdateWorkerDeploymentVersionComputeConfig( + self, + request: temporalio.api.workflowservice.v1.request_response_pb2.UpdateWorkerDeploymentVersionComputeConfigRequest, + context: grpc.ServicerContext, + ) -> temporalio.api.workflowservice.v1.request_response_pb2.UpdateWorkerDeploymentVersionComputeConfigResponse: + """Updates the compute config attached to a Worker Deployment Version. + Experimental. This API might significantly change or be removed in a future release. + """ + @abc.abstractmethod + def ValidateWorkerDeploymentVersionComputeConfig( + self, + request: temporalio.api.workflowservice.v1.request_response_pb2.ValidateWorkerDeploymentVersionComputeConfigRequest, + context: grpc.ServicerContext, + ) -> temporalio.api.workflowservice.v1.request_response_pb2.ValidateWorkerDeploymentVersionComputeConfigResponse: + """Validates the compute config without attaching it to a Worker Deployment Version. + Experimental. This API might significantly change or be removed in a future release. + """ + @abc.abstractmethod def UpdateWorkerDeploymentVersionMetadata( self, request: temporalio.api.workflowservice.v1.request_response_pb2.UpdateWorkerDeploymentVersionMetadataRequest, @@ -2167,6 +2305,17 @@ class WorkflowServiceServicer(metaclass=abc.ABCMeta): unless permitted by the specified ID conflict policy. """ @abc.abstractmethod + def StartNexusOperationExecution( + self, + request: temporalio.api.workflowservice.v1.request_response_pb2.StartNexusOperationExecutionRequest, + context: grpc.ServicerContext, + ) -> temporalio.api.workflowservice.v1.request_response_pb2.StartNexusOperationExecutionResponse: + """StartNexusOperationExecution starts a new Nexus operation. + + Returns a `NexusOperationExecutionAlreadyStarted` error if an instance already exists with same operation ID in this + namespace unless permitted by the specified ID conflict policy. + """ + @abc.abstractmethod def DescribeActivityExecution( self, request: temporalio.api.workflowservice.v1.request_response_pb2.DescribeActivityExecutionRequest, @@ -2179,6 +2328,18 @@ class WorkflowServiceServicer(metaclass=abc.ABCMeta): Response can optionally include activity input or outcome (if the activity has completed). """ @abc.abstractmethod + def DescribeNexusOperationExecution( + self, + request: temporalio.api.workflowservice.v1.request_response_pb2.DescribeNexusOperationExecutionRequest, + context: grpc.ServicerContext, + ) -> temporalio.api.workflowservice.v1.request_response_pb2.DescribeNexusOperationExecutionResponse: + """DescribeNexusOperationExecution returns information about a Nexus operation. + Supported use cases include: + - Get current operation info without waiting + - Long-poll for next state change and return new operation info + Response can optionally include operation input or outcome (if the operation has completed). + """ + @abc.abstractmethod def PollActivityExecution( self, request: temporalio.api.workflowservice.v1.request_response_pb2.PollActivityExecutionRequest, @@ -2188,6 +2349,15 @@ class WorkflowServiceServicer(metaclass=abc.ABCMeta): outcome (result or failure). """ @abc.abstractmethod + def PollNexusOperationExecution( + self, + request: temporalio.api.workflowservice.v1.request_response_pb2.PollNexusOperationExecutionRequest, + context: grpc.ServicerContext, + ) -> temporalio.api.workflowservice.v1.request_response_pb2.PollNexusOperationExecutionResponse: + """PollNexusOperationExecution long-polls for a Nexus operation for a given wait stage to complete and returns + the outcome (result or failure). + """ + @abc.abstractmethod def ListActivityExecutions( self, request: temporalio.api.workflowservice.v1.request_response_pb2.ListActivityExecutionsRequest, @@ -2195,6 +2365,13 @@ class WorkflowServiceServicer(metaclass=abc.ABCMeta): ) -> temporalio.api.workflowservice.v1.request_response_pb2.ListActivityExecutionsResponse: """ListActivityExecutions is a visibility API to list activity executions in a specific namespace.""" @abc.abstractmethod + def ListNexusOperationExecutions( + self, + request: temporalio.api.workflowservice.v1.request_response_pb2.ListNexusOperationExecutionsRequest, + context: grpc.ServicerContext, + ) -> temporalio.api.workflowservice.v1.request_response_pb2.ListNexusOperationExecutionsResponse: + """ListNexusOperationExecutions is a visibility API to list Nexus operations in a specific namespace.""" + @abc.abstractmethod def CountActivityExecutions( self, request: temporalio.api.workflowservice.v1.request_response_pb2.CountActivityExecutionsRequest, @@ -2202,6 +2379,13 @@ class WorkflowServiceServicer(metaclass=abc.ABCMeta): ) -> temporalio.api.workflowservice.v1.request_response_pb2.CountActivityExecutionsResponse: """CountActivityExecutions is a visibility API to count activity executions in a specific namespace.""" @abc.abstractmethod + def CountNexusOperationExecutions( + self, + request: temporalio.api.workflowservice.v1.request_response_pb2.CountNexusOperationExecutionsRequest, + context: grpc.ServicerContext, + ) -> temporalio.api.workflowservice.v1.request_response_pb2.CountNexusOperationExecutionsResponse: + """CountNexusOperationExecutions is a visibility API to count Nexus operations in a specific namespace.""" + @abc.abstractmethod def RequestCancelActivityExecution( self, request: temporalio.api.workflowservice.v1.request_response_pb2.RequestCancelActivityExecutionRequest, @@ -2215,6 +2399,18 @@ class WorkflowServiceServicer(metaclass=abc.ABCMeta): language-idiomatic mechanisms (context cancellation, exceptions, abort signals). """ @abc.abstractmethod + def RequestCancelNexusOperationExecution( + self, + request: temporalio.api.workflowservice.v1.request_response_pb2.RequestCancelNexusOperationExecutionRequest, + context: grpc.ServicerContext, + ) -> temporalio.api.workflowservice.v1.request_response_pb2.RequestCancelNexusOperationExecutionResponse: + """RequestCancelNexusOperationExecution requests cancellation of a Nexus operation. + + Requesting to cancel an operation does not automatically transition the operation to canceled status. + The operation will only transition to canceled status if it supports cancellation and the handler + processes the cancellation request. + """ + @abc.abstractmethod def TerminateActivityExecution( self, request: temporalio.api.workflowservice.v1.request_response_pb2.TerminateActivityExecutionRequest, @@ -2239,6 +2435,30 @@ class WorkflowServiceServicer(metaclass=abc.ABCMeta): (-- api-linter: core::0127::http-annotation=disabled aip.dev/not-precedent: Activity deletion not exposed to HTTP, users should use cancel or terminate. --) """ + @abc.abstractmethod + def TerminateNexusOperationExecution( + self, + request: temporalio.api.workflowservice.v1.request_response_pb2.TerminateNexusOperationExecutionRequest, + context: grpc.ServicerContext, + ) -> temporalio.api.workflowservice.v1.request_response_pb2.TerminateNexusOperationExecutionResponse: + """TerminateNexusOperationExecution terminates an existing Nexus operation immediately. + + Termination happens immediately and the operation handler cannot react to it. A terminated operation will have + its outcome set to a failure with a termination reason. + """ + @abc.abstractmethod + def DeleteNexusOperationExecution( + self, + request: temporalio.api.workflowservice.v1.request_response_pb2.DeleteNexusOperationExecutionRequest, + context: grpc.ServicerContext, + ) -> temporalio.api.workflowservice.v1.request_response_pb2.DeleteNexusOperationExecutionResponse: + """DeleteNexusOperationExecution asynchronously deletes a specific Nexus operation run (when + run_id is provided) or the latest run (when run_id is not provided). If the operation + is running, it will be terminated before deletion. + + (-- api-linter: core::0127::http-annotation=disabled + aip.dev/not-precedent: Nexus operation deletion not exposed to HTTP, users should use cancel or terminate. --) + """ def add_WorkflowServiceServicer_to_server( servicer: WorkflowServiceServicer, server: grpc.Server diff --git a/temporalio/bridge/Cargo.lock b/temporalio/bridge/Cargo.lock index c31dafdb6..829d1bc90 100644 --- a/temporalio/bridge/Cargo.lock +++ b/temporalio/bridge/Cargo.lock @@ -372,20 +372,6 @@ dependencies = [ "syn", ] -[[package]] -name = "dashmap" -version = "6.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5041cc499144891f3790297212f32a74fb938e5136a14943f338ef9e0ae276cf" -dependencies = [ - "cfg-if", - "crossbeam-utils", - "hashbrown 0.14.5", - "lock_api", - "once_cell", - "parking_lot_core", -] - [[package]] name = "derive_more" version = "2.0.1" @@ -683,12 +669,6 @@ version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" -[[package]] -name = "futures-timer" -version = "3.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f288b0a4f20f9a56b5d1da57e2227c661b7b16168e2f72365f57b63326e29b24" - [[package]] name = "futures-util" version = "0.3.31" @@ -764,29 +744,6 @@ version = "0.31.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" -[[package]] -name = "governor" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "444405bbb1a762387aa22dd569429533b54a1d8759d35d3b64cb39b0293eaa19" -dependencies = [ - "cfg-if", - "dashmap", - "futures-sink", - "futures-timer", - "futures-util", - "getrandom 0.3.3", - "hashbrown 0.15.5", - "nonzero_ext", - "parking_lot", - "portable-atomic", - "quanta", - "rand 0.9.2", - "smallvec", - "spinning_top", - "web-time", -] - [[package]] name = "h2" version = "0.4.12" @@ -806,20 +763,12 @@ dependencies = [ "tracing", ] -[[package]] -name = "hashbrown" -version = "0.14.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" - [[package]] name = "hashbrown" version = "0.15.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" dependencies = [ - "allocator-api2", - "equivalent", "foldhash 0.1.5", ] @@ -919,6 +868,7 @@ dependencies = [ "hyper", "hyper-util", "rustls", + "rustls-native-certs", "rustls-pki-types", "tokio", "tokio-rustls", @@ -1400,12 +1350,6 @@ version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1d87ecb2933e8aeadb3e3a02b828fed80a7528047e68b4f424523a0981a3a084" -[[package]] -name = "nonzero_ext" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38bf9645c8b145698bb0b18a4637dcacbc421ea49bef2317e4fd8065a387cf21" - [[package]] name = "ntapi" version = "0.4.1" @@ -1484,7 +1428,6 @@ dependencies = [ "js-sys", "pin-project-lite", "thiserror 2.0.15", - "tracing", ] [[package]] @@ -1516,7 +1459,6 @@ dependencies = [ "thiserror 2.0.15", "tokio", "tonic", - "tracing", ] [[package]] @@ -1962,21 +1904,6 @@ dependencies = [ "serde", ] -[[package]] -name = "quanta" -version = "0.12.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3ab5a9d756f0d97bdc89019bd2e4ea098cf9cde50ee7564dde6b81ccc8f06c7" -dependencies = [ - "crossbeam-utils", - "libc", - "once_cell", - "raw-cpuid", - "wasi 0.11.1+wasi-snapshot-preview1", - "web-sys", - "winapi", -] - [[package]] name = "quinn" version = "0.11.8" @@ -2130,15 +2057,6 @@ version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0c8d0fd677905edcbeedbf2edb6494d676f0e98d54d5cf9bda0b061cb8fb8aba" -[[package]] -name = "raw-cpuid" -version = "11.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6df7ab838ed27997ba19a4664507e6f82b41fe6e20be42929332156e5e85146" -dependencies = [ - "bitflags", -] - [[package]] name = "redox_syscall" version = "0.5.17" @@ -2203,16 +2121,22 @@ dependencies = [ "http-body", "http-body-util", "hyper", + "hyper-rustls", "hyper-util", "js-sys", "log", "percent-encoding", "pin-project-lite", + "quinn", + "rustls", + "rustls-native-certs", + "rustls-pki-types", "serde", "serde_json", "serde_urlencoded", "sync_wrapper", "tokio", + "tokio-rustls", "tower", "tower-http", "tower-service", @@ -2595,15 +2519,6 @@ dependencies = [ "windows-sys 0.59.0", ] -[[package]] -name = "spinning_top" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d96d2d1d716fb500937168cc09353ffdc7a012be8475ac7308e1bdf0e3923300" -dependencies = [ - "lock_api", -] - [[package]] name = "stable_deref_trait" version = "1.2.0" @@ -2720,7 +2635,7 @@ dependencies = [ [[package]] name = "temporalio-client" -version = "0.2.0" +version = "0.3.0" dependencies = [ "anyhow", "async-trait", @@ -2750,7 +2665,7 @@ dependencies = [ [[package]] name = "temporalio-common" -version = "0.2.0" +version = "0.3.0" dependencies = [ "anyhow", "async-trait", @@ -2795,7 +2710,7 @@ dependencies = [ [[package]] name = "temporalio-macros" -version = "0.2.0" +version = "0.3.0" dependencies = [ "proc-macro2", "quote", @@ -2804,7 +2719,7 @@ dependencies = [ [[package]] name = "temporalio-sdk-core" -version = "0.2.0" +version = "0.3.0" dependencies = [ "anyhow", "async-trait", @@ -2812,7 +2727,6 @@ dependencies = [ "bon", "crossbeam-channel", "crossbeam-utils", - "dashmap", "derive_more", "enum-iterator", "enum_dispatch", @@ -2820,7 +2734,6 @@ dependencies = [ "futures", "futures-util", "gethostname", - "governor", "itertools", "lru", "mockall", @@ -3299,8 +3212,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2f87b8aa10b915a06587d0dec516c282ff295b475d94abf425d62b57710070a2" dependencies = [ "getrandom 0.3.3", - "js-sys", - "wasm-bindgen", ] [[package]] diff --git a/temporalio/bridge/Cargo.toml b/temporalio/bridge/Cargo.toml index e1d375a76..31e8ee633 100644 --- a/temporalio/bridge/Cargo.toml +++ b/temporalio/bridge/Cargo.toml @@ -28,11 +28,11 @@ pyo3 = { version = "0.25", features = [ ] } pyo3-async-runtimes = { version = "0.25", features = ["tokio-runtime"] } pythonize = "0.25" -temporalio-client = { version = "0.2.0", path = "./sdk-core/crates/client" } -temporalio-common = { version = "0.2.0", path = "./sdk-core/crates/common", features = [ +temporalio-client = { version = "0.3.0", path = "./sdk-core/crates/client" } +temporalio-common = { version = "0.3.0", path = "./sdk-core/crates/common", features = [ "envconfig", "otel" ]} -temporalio-sdk-core = { version = "0.2.0", path = "./sdk-core/crates/sdk-core", features = [ +temporalio-sdk-core = { version = "0.3.0", path = "./sdk-core/crates/sdk-core", features = [ "ephemeral-server", ] } tokio = "1.26" diff --git a/temporalio/bridge/sdk-core b/temporalio/bridge/sdk-core index b544f95da..2872b5363 160000 --- a/temporalio/bridge/sdk-core +++ b/temporalio/bridge/sdk-core @@ -1 +1 @@ -Subproject commit b544f95da46b21e8a642229b8d7f1b017c88e84e +Subproject commit 2872b5363e1b745cfb90313ebc7a507c5d25c398 diff --git a/temporalio/bridge/services_generated.py b/temporalio/bridge/services_generated.py index b503aaff0..f483c318a 100644 --- a/temporalio/bridge/services_generated.py +++ b/temporalio/bridge/services_generated.py @@ -45,6 +45,24 @@ async def count_activity_executions( timeout=timeout, ) + async def count_nexus_operation_executions( + self, + req: temporalio.api.workflowservice.v1.CountNexusOperationExecutionsRequest, + retry: bool = False, + metadata: Mapping[str, str | bytes] = {}, + timeout: timedelta | None = None, + ) -> temporalio.api.workflowservice.v1.CountNexusOperationExecutionsResponse: + """Invokes the WorkflowService.count_nexus_operation_executions rpc method.""" + return await self._client._rpc_call( + rpc="count_nexus_operation_executions", + req=req, + service=self._service, + resp_type=temporalio.api.workflowservice.v1.CountNexusOperationExecutionsResponse, + retry=retry, + metadata=metadata, + timeout=timeout, + ) + async def count_schedules( self, req: temporalio.api.workflowservice.v1.CountSchedulesRequest, @@ -99,6 +117,42 @@ async def create_schedule( timeout=timeout, ) + async def create_worker_deployment( + self, + req: temporalio.api.workflowservice.v1.CreateWorkerDeploymentRequest, + retry: bool = False, + metadata: Mapping[str, str | bytes] = {}, + timeout: timedelta | None = None, + ) -> temporalio.api.workflowservice.v1.CreateWorkerDeploymentResponse: + """Invokes the WorkflowService.create_worker_deployment rpc method.""" + return await self._client._rpc_call( + rpc="create_worker_deployment", + req=req, + service=self._service, + resp_type=temporalio.api.workflowservice.v1.CreateWorkerDeploymentResponse, + retry=retry, + metadata=metadata, + timeout=timeout, + ) + + async def create_worker_deployment_version( + self, + req: temporalio.api.workflowservice.v1.CreateWorkerDeploymentVersionRequest, + retry: bool = False, + metadata: Mapping[str, str | bytes] = {}, + timeout: timedelta | None = None, + ) -> temporalio.api.workflowservice.v1.CreateWorkerDeploymentVersionResponse: + """Invokes the WorkflowService.create_worker_deployment_version rpc method.""" + return await self._client._rpc_call( + rpc="create_worker_deployment_version", + req=req, + service=self._service, + resp_type=temporalio.api.workflowservice.v1.CreateWorkerDeploymentVersionResponse, + retry=retry, + metadata=metadata, + timeout=timeout, + ) + async def create_workflow_rule( self, req: temporalio.api.workflowservice.v1.CreateWorkflowRuleRequest, @@ -135,6 +189,24 @@ async def delete_activity_execution( timeout=timeout, ) + async def delete_nexus_operation_execution( + self, + req: temporalio.api.workflowservice.v1.DeleteNexusOperationExecutionRequest, + retry: bool = False, + metadata: Mapping[str, str | bytes] = {}, + timeout: timedelta | None = None, + ) -> temporalio.api.workflowservice.v1.DeleteNexusOperationExecutionResponse: + """Invokes the WorkflowService.delete_nexus_operation_execution rpc method.""" + return await self._client._rpc_call( + rpc="delete_nexus_operation_execution", + req=req, + service=self._service, + resp_type=temporalio.api.workflowservice.v1.DeleteNexusOperationExecutionResponse, + retry=retry, + metadata=metadata, + timeout=timeout, + ) + async def delete_schedule( self, req: temporalio.api.workflowservice.v1.DeleteScheduleRequest, @@ -315,6 +387,24 @@ async def describe_namespace( timeout=timeout, ) + async def describe_nexus_operation_execution( + self, + req: temporalio.api.workflowservice.v1.DescribeNexusOperationExecutionRequest, + retry: bool = False, + metadata: Mapping[str, str | bytes] = {}, + timeout: timedelta | None = None, + ) -> temporalio.api.workflowservice.v1.DescribeNexusOperationExecutionResponse: + """Invokes the WorkflowService.describe_nexus_operation_execution rpc method.""" + return await self._client._rpc_call( + rpc="describe_nexus_operation_execution", + req=req, + service=self._service, + resp_type=temporalio.api.workflowservice.v1.DescribeNexusOperationExecutionResponse, + retry=retry, + metadata=metadata, + timeout=timeout, + ) + async def describe_schedule( self, req: temporalio.api.workflowservice.v1.DescribeScheduleRequest, @@ -765,6 +855,24 @@ async def list_namespaces( timeout=timeout, ) + async def list_nexus_operation_executions( + self, + req: temporalio.api.workflowservice.v1.ListNexusOperationExecutionsRequest, + retry: bool = False, + metadata: Mapping[str, str | bytes] = {}, + timeout: timedelta | None = None, + ) -> temporalio.api.workflowservice.v1.ListNexusOperationExecutionsResponse: + """Invokes the WorkflowService.list_nexus_operation_executions rpc method.""" + return await self._client._rpc_call( + rpc="list_nexus_operation_executions", + req=req, + service=self._service, + resp_type=temporalio.api.workflowservice.v1.ListNexusOperationExecutionsResponse, + retry=retry, + metadata=metadata, + timeout=timeout, + ) + async def list_open_workflow_executions( self, req: temporalio.api.workflowservice.v1.ListOpenWorkflowExecutionsRequest, @@ -999,6 +1107,24 @@ async def poll_activity_task_queue( timeout=timeout, ) + async def poll_nexus_operation_execution( + self, + req: temporalio.api.workflowservice.v1.PollNexusOperationExecutionRequest, + retry: bool = False, + metadata: Mapping[str, str | bytes] = {}, + timeout: timedelta | None = None, + ) -> temporalio.api.workflowservice.v1.PollNexusOperationExecutionResponse: + """Invokes the WorkflowService.poll_nexus_operation_execution rpc method.""" + return await self._client._rpc_call( + rpc="poll_nexus_operation_execution", + req=req, + service=self._service, + resp_type=temporalio.api.workflowservice.v1.PollNexusOperationExecutionResponse, + retry=retry, + metadata=metadata, + timeout=timeout, + ) + async def poll_nexus_task_queue( self, req: temporalio.api.workflowservice.v1.PollNexusTaskQueueRequest, @@ -1161,6 +1287,24 @@ async def request_cancel_activity_execution( timeout=timeout, ) + async def request_cancel_nexus_operation_execution( + self, + req: temporalio.api.workflowservice.v1.RequestCancelNexusOperationExecutionRequest, + retry: bool = False, + metadata: Mapping[str, str | bytes] = {}, + timeout: timedelta | None = None, + ) -> temporalio.api.workflowservice.v1.RequestCancelNexusOperationExecutionResponse: + """Invokes the WorkflowService.request_cancel_nexus_operation_execution rpc method.""" + return await self._client._rpc_call( + rpc="request_cancel_nexus_operation_execution", + req=req, + service=self._service, + resp_type=temporalio.api.workflowservice.v1.RequestCancelNexusOperationExecutionResponse, + retry=retry, + metadata=metadata, + timeout=timeout, + ) + async def request_cancel_workflow_execution( self, req: temporalio.api.workflowservice.v1.RequestCancelWorkflowExecutionRequest, @@ -1611,6 +1755,24 @@ async def start_batch_operation( timeout=timeout, ) + async def start_nexus_operation_execution( + self, + req: temporalio.api.workflowservice.v1.StartNexusOperationExecutionRequest, + retry: bool = False, + metadata: Mapping[str, str | bytes] = {}, + timeout: timedelta | None = None, + ) -> temporalio.api.workflowservice.v1.StartNexusOperationExecutionResponse: + """Invokes the WorkflowService.start_nexus_operation_execution rpc method.""" + return await self._client._rpc_call( + rpc="start_nexus_operation_execution", + req=req, + service=self._service, + resp_type=temporalio.api.workflowservice.v1.StartNexusOperationExecutionResponse, + retry=retry, + metadata=metadata, + timeout=timeout, + ) + async def start_workflow_execution( self, req: temporalio.api.workflowservice.v1.StartWorkflowExecutionRequest, @@ -1665,6 +1827,24 @@ async def terminate_activity_execution( timeout=timeout, ) + async def terminate_nexus_operation_execution( + self, + req: temporalio.api.workflowservice.v1.TerminateNexusOperationExecutionRequest, + retry: bool = False, + metadata: Mapping[str, str | bytes] = {}, + timeout: timedelta | None = None, + ) -> temporalio.api.workflowservice.v1.TerminateNexusOperationExecutionResponse: + """Invokes the WorkflowService.terminate_nexus_operation_execution rpc method.""" + return await self._client._rpc_call( + rpc="terminate_nexus_operation_execution", + req=req, + service=self._service, + resp_type=temporalio.api.workflowservice.v1.TerminateNexusOperationExecutionResponse, + retry=retry, + metadata=metadata, + timeout=timeout, + ) + async def terminate_workflow_execution( self, req: temporalio.api.workflowservice.v1.TerminateWorkflowExecutionRequest, @@ -1845,6 +2025,24 @@ async def update_worker_config( timeout=timeout, ) + async def update_worker_deployment_version_compute_config( + self, + req: temporalio.api.workflowservice.v1.UpdateWorkerDeploymentVersionComputeConfigRequest, + retry: bool = False, + metadata: Mapping[str, str | bytes] = {}, + timeout: timedelta | None = None, + ) -> temporalio.api.workflowservice.v1.UpdateWorkerDeploymentVersionComputeConfigResponse: + """Invokes the WorkflowService.update_worker_deployment_version_compute_config rpc method.""" + return await self._client._rpc_call( + rpc="update_worker_deployment_version_compute_config", + req=req, + service=self._service, + resp_type=temporalio.api.workflowservice.v1.UpdateWorkerDeploymentVersionComputeConfigResponse, + retry=retry, + metadata=metadata, + timeout=timeout, + ) + async def update_worker_deployment_version_metadata( self, req: temporalio.api.workflowservice.v1.UpdateWorkerDeploymentVersionMetadataRequest, @@ -1919,6 +2117,24 @@ async def update_workflow_execution_options( timeout=timeout, ) + async def validate_worker_deployment_version_compute_config( + self, + req: temporalio.api.workflowservice.v1.ValidateWorkerDeploymentVersionComputeConfigRequest, + retry: bool = False, + metadata: Mapping[str, str | bytes] = {}, + timeout: timedelta | None = None, + ) -> temporalio.api.workflowservice.v1.ValidateWorkerDeploymentVersionComputeConfigResponse: + """Invokes the WorkflowService.validate_worker_deployment_version_compute_config rpc method.""" + return await self._client._rpc_call( + rpc="validate_worker_deployment_version_compute_config", + req=req, + service=self._service, + resp_type=temporalio.api.workflowservice.v1.ValidateWorkerDeploymentVersionComputeConfigResponse, + retry=retry, + metadata=metadata, + timeout=timeout, + ) + class OperatorService: """RPC calls for the OperatorService.""" diff --git a/temporalio/bridge/src/client.rs b/temporalio/bridge/src/client.rs index 3e91f2110..cc00bcfe0 100644 --- a/temporalio/bridge/src/client.rs +++ b/temporalio/bridge/src/client.rs @@ -9,7 +9,7 @@ use temporalio_client::tonic::{ }; use temporalio_client::{ ClientKeepAliveOptions as CoreClientKeepAliveConfig, Connection, ConnectionOptions, - HttpConnectProxyOptions, RetryOptions, + DnsLoadBalancingOptions, HttpConnectProxyOptions, RetryOptions, }; use url::Url; @@ -235,6 +235,7 @@ impl ClientConfig { metrics_meter: Option, ) -> PyResult { let (ascii_headers, binary_headers) = partition_headers(self.metadata); + let has_proxy = self.http_connect_proxy_config.is_some(); let conn_opts = ConnectionOptions::new( Url::parse(&self.target_url) .map_err(|err| PyValueError::new_err(format!("invalid target URL: {err}")))?, @@ -248,6 +249,11 @@ impl ClientConfig { ) .keep_alive(self.keep_alive_config.map(Into::into)) .maybe_http_connect_proxy(self.http_connect_proxy_config.map(Into::into)) + .dns_load_balancing(if has_proxy { + None + } else { + Some(DnsLoadBalancingOptions::default()) + }) .headers(ascii_headers) .binary_headers(binary_headers) .maybe_api_key(self.api_key) diff --git a/temporalio/bridge/src/client_rpc_generated.rs b/temporalio/bridge/src/client_rpc_generated.rs index 8c952e54d..85c537225 100644 --- a/temporalio/bridge/src/client_rpc_generated.rs +++ b/temporalio/bridge/src/client_rpc_generated.rs @@ -29,6 +29,15 @@ impl ClientRef { count_activity_executions ) } + "count_nexus_operation_executions" => { + rpc_call!( + connection, + call, + WorkflowService, + workflow_service, + count_nexus_operation_executions + ) + } "count_schedules" => { rpc_call!( connection, @@ -56,6 +65,24 @@ impl ClientRef { create_schedule ) } + "create_worker_deployment" => { + rpc_call!( + connection, + call, + WorkflowService, + workflow_service, + create_worker_deployment + ) + } + "create_worker_deployment_version" => { + rpc_call!( + connection, + call, + WorkflowService, + workflow_service, + create_worker_deployment_version + ) + } "create_workflow_rule" => { rpc_call!( connection, @@ -74,6 +101,15 @@ impl ClientRef { delete_activity_execution ) } + "delete_nexus_operation_execution" => { + rpc_call!( + connection, + call, + WorkflowService, + workflow_service, + delete_nexus_operation_execution + ) + } "delete_schedule" => { rpc_call!( connection, @@ -164,6 +200,15 @@ impl ClientRef { describe_namespace ) } + "describe_nexus_operation_execution" => { + rpc_call!( + connection, + call, + WorkflowService, + workflow_service, + describe_nexus_operation_execution + ) + } "describe_schedule" => { rpc_call!( connection, @@ -389,6 +434,15 @@ impl ClientRef { list_namespaces ) } + "list_nexus_operation_executions" => { + rpc_call!( + connection, + call, + WorkflowService, + workflow_service, + list_nexus_operation_executions + ) + } "list_open_workflow_executions" => { rpc_call!( connection, @@ -506,6 +560,15 @@ impl ClientRef { poll_activity_task_queue ) } + "poll_nexus_operation_execution" => { + rpc_call!( + connection, + call, + WorkflowService, + workflow_service, + poll_nexus_operation_execution + ) + } "poll_nexus_task_queue" => { rpc_call!( connection, @@ -587,6 +650,15 @@ impl ClientRef { request_cancel_activity_execution ) } + "request_cancel_nexus_operation_execution" => { + rpc_call!( + connection, + call, + WorkflowService, + workflow_service, + request_cancel_nexus_operation_execution + ) + } "request_cancel_workflow_execution" => { rpc_call!( connection, @@ -812,6 +884,15 @@ impl ClientRef { start_batch_operation ) } + "start_nexus_operation_execution" => { + rpc_call!( + connection, + call, + WorkflowService, + workflow_service, + start_nexus_operation_execution + ) + } "start_workflow_execution" => { rpc_call!( connection, @@ -839,6 +920,15 @@ impl ClientRef { terminate_activity_execution ) } + "terminate_nexus_operation_execution" => { + rpc_call!( + connection, + call, + WorkflowService, + workflow_service, + terminate_nexus_operation_execution + ) + } "terminate_workflow_execution" => { rpc_call!( connection, @@ -929,6 +1019,15 @@ impl ClientRef { update_worker_config ) } + "update_worker_deployment_version_compute_config" => { + rpc_call!( + connection, + call, + WorkflowService, + workflow_service, + update_worker_deployment_version_compute_config + ) + } "update_worker_deployment_version_metadata" => { rpc_call!( connection, @@ -965,6 +1064,15 @@ impl ClientRef { update_workflow_execution_options ) } + "validate_worker_deployment_version_compute_config" => { + rpc_call!( + connection, + call, + WorkflowService, + workflow_service, + validate_worker_deployment_version_compute_config + ) + } _ => { return Err(PyValueError::new_err(format!( "Unknown RPC call {}", diff --git a/temporalio/bridge/src/worker.rs b/temporalio/bridge/src/worker.rs index 4820fd843..d37226614 100644 --- a/temporalio/bridge/src/worker.rs +++ b/temporalio/bridge/src/worker.rs @@ -684,6 +684,7 @@ impl WorkerRef { } fn initiate_shutdown(&self) -> PyResult<()> { + enter_sync!(self.runtime); let worker = self.worker.as_ref().unwrap().clone(); worker.initiate_shutdown(); Ok(()) From 30b2b6387546c3c0ddc4a2a773ab4cb30519fc53 Mon Sep 17 00:00:00 2001 From: Donald Pinckney Date: Mon, 27 Apr 2026 20:08:37 -0400 Subject: [PATCH 063/226] Add AI Foundations as CODEOWNERs of AI plugins (#1482) * Update CODEOWNERS to include new module owners * Update CODEOWNERS to include test directories * Comment edit * Remove CODEOWNERS for pydantic files Removed CODEOWNERS entries for pydantic.py and its tests. --------- Co-authored-by: tconley1428 --- .github/CODEOWNERS | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 7bdb4ecab..c718b40c0 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -3,3 +3,16 @@ # @temporalio/sdk will be requested for review when # someone opens a pull request. * @temporalio/sdk + + +# Below are owners for modules in the temporalio/contrib/ +# and tests/contrib/ directories that are owned by teams +# other than the SDK team. For each one, we add the owning team, +# as well as @temporalio/sdk, so the SDK team can continue to +# manage repo-wide concerns. +/temporalio/contrib/google_adk_agents/ @temporalio/ai-sdk @temporalio/sdk +/temporalio/contrib/langsmith/ @temporalio/ai-sdk @temporalio/sdk +/temporalio/contrib/openai_agents/ @temporalio/ai-sdk @temporalio/sdk +/tests/contrib/google_adk_agents/ @temporalio/ai-sdk @temporalio/sdk +/tests/contrib/langsmith/ @temporalio/ai-sdk @temporalio/sdk +/tests/contrib/openai_agents/ @temporalio/ai-sdk @temporalio/sdk From 776bae2457926b6429a5e47f3a5370b6377afb58 Mon Sep 17 00:00:00 2001 From: Chris Olszewski Date: Tue, 28 Apr 2026 10:31:31 -0400 Subject: [PATCH 064/226] chore: update submodule to sdk-rust (#1480) * Rename sdk-core submodule repo to sdk-rust * update comments --- README.md | 2 +- tests/worker/test_workflow.py | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 5968b2072..38d643881 100644 --- a/README.md +++ b/README.md @@ -1937,7 +1937,7 @@ users are encouraged to not use gevent in asyncio applications (including Tempor # Development The Python SDK is built to work with Python 3.9 and newer. It is built using -[SDK Core](https://github.com/temporalio/sdk-core/) which is written in Rust. +[SDK Core](https://github.com/temporalio/sdk-rust/) which is written in Rust. ### Building diff --git a/tests/worker/test_workflow.py b/tests/worker/test_workflow.py index cf84db758..7b3fd4709 100644 --- a/tests/worker/test_workflow.py +++ b/tests/worker/test_workflow.py @@ -943,7 +943,7 @@ async def run(self, params: CancelActivityWorkflowParams) -> None: self._activity_result = await handle except ActivityError as err: self._activity_result = f"Error: {err.cause.__class__.__name__}" - # TODO(cretz): Remove when https://github.com/temporalio/sdk-core/issues/323 is fixed + # TODO(cretz): Remove when https://github.com/temporalio/sdk-rust/issues/323 is fixed except CancelledError as err: self._activity_result = f"Error: {err.__class__.__name__}" # Wait forever @@ -2430,7 +2430,7 @@ async def test_workflow_dataclass_typed(client: Client, env: WorkflowEnvironment # TODO(cretz): Fix if env.supports_time_skipping: pytest.skip( - "Java test server: https://github.com/temporalio/sdk-core/issues/390" + "Java test server: https://github.com/temporalio/sdk-rust/issues/390" ) async with new_worker( client, DataClassTypedWorkflow, activities=[data_class_typed_activity] @@ -7246,7 +7246,7 @@ async def test_workflow_deadlock_interruptible(client: Client): # TODO(cretz): Improve this test and other deadlock/eviction tests by # checking slot counts with Core. There are a couple of bugs where used slot # counts are off by one and slots are released before eviction (see - # https://github.com/temporalio/sdk-core/issues/894). + # https://github.com/temporalio/sdk-rust/issues/894). # This worker used to not be able to shutdown because we hung evictions on # deadlock From 052249085827f6c40b2c39a32ca7f39763590598 Mon Sep 17 00:00:00 2001 From: Brian Strauch Date: Tue, 28 Apr 2026 13:28:15 -0700 Subject: [PATCH 065/226] AI-36: Add LangGraph plugin (#1448) * add langgraph plugin * add experimental package warnings * fix ruff lint * fix pyright lint errors * fixed some mypy lints * fix docstring lints * copilot code review * fix mypy lint * separate graphs and entrypoints by task queue to avoid concurrent write bug * use graph.node or task_id for activity names to avoid collisions * rm local conftest in favor of global and fix lint * allow langgraph 1.1 * uv lock * add default_activity_options * add replay test * fix gaps in missing tests * introduce an interceptor to patch is_running only in the workflow, then use init functions for graph compilation * add interceptor * remove graph and entrypoint functions in favor of direct graph usage * rename cache() to get_cache() * remove interceptor * allow metadata to be accessed from node func and test * Fix import sorting in test_node_metadata.py * Fix formatting in langgraph_plugin.py * Fix mypy errors: add type params to StateGraph and use State() constructor * Fix langsmith sandbox crash when langchain_core is installed The LangSmithPlugin passes langsmith through the workflow sandbox, but langsmith conditionally imports langchain_core when it's available. With the langgraph extra adding langchain_core as a transitive dep, this conditional import now fires inside the sandbox, where langchain_core's lazy module loading triggers a restricted access on concurrent.futures.ThreadPoolExecutor. Two fixes: - Pre-import langchain_core.runnables.config at plugin load time so it's in sys.modules before the sandbox starts - Add langchain_core to the sandbox passthrough list - Add a timeout to _poll_query in langsmith tests to prevent infinite hangs if a workflow never reaches the expected state * Suppress basedpyright unused import warning for langchain_core preload * Skip langgraph async tests on Python < 3.11 and warn plugin users LangGraph's Functional API (@task/@entrypoint) and interrupt() require Python >= 3.11 for async context variable propagation via asyncio.create_task(context=...). On older versions, get_config() raises "Called get_config outside of a runnable context". This is a documented LangGraph limitation: https://reference.langchain.com/python/langgraph/config/get_store/ - Skip test_e2e_functional.py, test_interrupt.py, and test_replay_interrupt on Python < 3.11 - Add a runtime warning in LangGraphPlugin.__init__ on Python < 3.11 * Remove duplicate pytest import in test_interrupt.py * Fix basedpyright reportUnreachable warning on version check * Increase execution_timeout for OpenAI tests that call the real API test_hello_world_agent[False] had a 5s execution timeout and test_input_guardrail[False] had a 10s timeout, but both use a 30s activity start_to_close_timeout. The workflow times out before the OpenAI API call can complete on slower CI runners. Bump both to 60s. * Revert "allow metadata to be accessed from node func and test" This reverts commit c84c22f06f8e8d2132cd035531cfbd6578a3aa7a. * Revert "rename cache() to get_cache()" This reverts commit ec8244ccc9b0871e49c254d88eb4f955312a450f. * Revert "remove graph and entrypoint functions in favor of direct graph usage" This reverts commit 8ef609f09704a5c001006ec9af5ff96a18203ad1. * reimplement node metadata fixes * scope graphs and entrypoints to workflow, rename files * test sync nodes and tasks, send * support command goto/update * add test for command * raise error if node or task has a retry policy * support runtime context * fix lint * Revert changes to langsmith test_integration.py * code review * Remove langchain_core from LangSmith plugin sandbox passthroughs (CI experiment) * Restore langchain_core to LangSmith plugin sandbox passthroughs * underscore py files in langgraph plugin dir * include all serializable data for langgraph config * mention langsmith tracing in readme * require execute_in * fix lint * fix flaky test * fix docs --------- Co-authored-by: DABH --- pyproject.toml | 2 + temporalio/contrib/langgraph/README.md | 170 +++++++++ temporalio/contrib/langgraph/__init__.py | 25 ++ temporalio/contrib/langgraph/_activity.py | 152 ++++++++ temporalio/contrib/langgraph/_interceptor.py | 61 ++++ .../contrib/langgraph/_langgraph_config.py | 160 +++++++++ temporalio/contrib/langgraph/_plugin.py | 262 ++++++++++++++ temporalio/contrib/langgraph/_task_cache.py | 83 +++++ temporalio/contrib/langsmith/_plugin.py | 12 +- tests/contrib/langgraph/__init__.py | 0 .../langgraph/e2e_functional_entrypoints.py | 144 ++++++++ .../langgraph/e2e_functional_workflows.py | 97 +++++ tests/contrib/langgraph/test_command.py | 68 ++++ .../contrib/langgraph/test_continue_as_new.py | 72 ++++ .../langgraph/test_continue_as_new_cached.py | 131 +++++++ .../contrib/langgraph/test_e2e_functional.py | 338 ++++++++++++++++++ .../langgraph/test_execute_in_workflow.py | 51 +++ tests/contrib/langgraph/test_interrupt.py | 97 +++++ tests/contrib/langgraph/test_node_metadata.py | 65 ++++ .../langgraph/test_plugin_validation.py | 89 +++++ tests/contrib/langgraph/test_replay.py | 93 +++++ tests/contrib/langgraph/test_send.py | 76 ++++ tests/contrib/langgraph/test_streaming.py | 68 ++++ .../langgraph/test_subgraph_activity.py | 67 ++++ .../langgraph/test_subgraph_workflow.py | 67 ++++ tests/contrib/langgraph/test_sync_node.py | 59 +++ tests/contrib/langgraph/test_sync_task.py | 69 ++++ tests/contrib/langgraph/test_timeout.py | 63 ++++ tests/contrib/langgraph/test_two_nodes.py | 65 ++++ uv.lock | 152 +++++++- 30 files changed, 2850 insertions(+), 8 deletions(-) create mode 100644 temporalio/contrib/langgraph/README.md create mode 100644 temporalio/contrib/langgraph/__init__.py create mode 100644 temporalio/contrib/langgraph/_activity.py create mode 100644 temporalio/contrib/langgraph/_interceptor.py create mode 100644 temporalio/contrib/langgraph/_langgraph_config.py create mode 100644 temporalio/contrib/langgraph/_plugin.py create mode 100644 temporalio/contrib/langgraph/_task_cache.py create mode 100644 tests/contrib/langgraph/__init__.py create mode 100644 tests/contrib/langgraph/e2e_functional_entrypoints.py create mode 100644 tests/contrib/langgraph/e2e_functional_workflows.py create mode 100644 tests/contrib/langgraph/test_command.py create mode 100644 tests/contrib/langgraph/test_continue_as_new.py create mode 100644 tests/contrib/langgraph/test_continue_as_new_cached.py create mode 100644 tests/contrib/langgraph/test_e2e_functional.py create mode 100644 tests/contrib/langgraph/test_execute_in_workflow.py create mode 100644 tests/contrib/langgraph/test_interrupt.py create mode 100644 tests/contrib/langgraph/test_node_metadata.py create mode 100644 tests/contrib/langgraph/test_plugin_validation.py create mode 100644 tests/contrib/langgraph/test_replay.py create mode 100644 tests/contrib/langgraph/test_send.py create mode 100644 tests/contrib/langgraph/test_streaming.py create mode 100644 tests/contrib/langgraph/test_subgraph_activity.py create mode 100644 tests/contrib/langgraph/test_subgraph_workflow.py create mode 100644 tests/contrib/langgraph/test_sync_node.py create mode 100644 tests/contrib/langgraph/test_sync_task.py create mode 100644 tests/contrib/langgraph/test_timeout.py create mode 100644 tests/contrib/langgraph/test_two_nodes.py diff --git a/pyproject.toml b/pyproject.toml index 9e0987b6b..1168373ea 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -30,6 +30,7 @@ opentelemetry = ["opentelemetry-api>=1.11.1,<2", "opentelemetry-sdk>=1.11.1,<2"] pydantic = ["pydantic>=2.0.0,<3"] openai-agents = ["openai-agents>=0.14.0", "mcp>=1.9.4, <2"] google-adk = ["google-adk>=1.27.0,<2"] +langgraph = ["langgraph>=1.1.0"] langsmith = ["langsmith>=0.7.0,<0.8"] lambda-worker-otel = [ "opentelemetry-api>=1.11.1,<2", @@ -79,6 +80,7 @@ dev = [ "pytest-rerunfailures>=16.1", "pytest-xdist>=3.6,<4", "moto[s3,server]>=5", + "langgraph>=1.1.0", "langsmith>=0.7.0,<0.8", "setuptools<82", "opentelemetry-exporter-otlp-proto-grpc>=1.11.1,<2", diff --git a/temporalio/contrib/langgraph/README.md b/temporalio/contrib/langgraph/README.md new file mode 100644 index 000000000..7c41b5da7 --- /dev/null +++ b/temporalio/contrib/langgraph/README.md @@ -0,0 +1,170 @@ +# LangGraph Plugin for Temporal Python SDK + +⚠️ **This package is currently at an experimental release stage.** ⚠️ + +This Temporal [Plugin](https://docs.temporal.io/develop/plugins-guide) allows you to run [LangGraph](https://www.langchain.com/langgraph) nodes and tasks as Temporal Activities, giving your AI workflows durable execution, automatic retries, and timeouts. It supports both the LangGraph Graph API (``StateGraph``) and Functional API (``@entrypoint`` / ``@task``). + +## Installation + +```sh +uv add temporalio[langgraph] +``` + +## Plugin Initialization + +### Graph API + +```python +from langgraph.graph import StateGraph +from temporalio.contrib.langgraph import LangGraphPlugin + +g = StateGraph(State) +g.add_node("my_node", my_node, metadata={"execute_in": "activity"}) + +plugin = LangGraphPlugin(graphs={"my-graph": g}) +``` + +### Functional API + +```python +from temporalio.contrib.langgraph import LangGraphPlugin + +plugin = LangGraphPlugin( + entrypoints={"my_entrypoint": my_entrypoint}, + tasks=[my_task], + activity_options={"my_task": {"execute_in": "activity"}}, +) +``` + +## Checkpointer + +If your LangGraph code requires a checkpointer (for example, if you're using interrupts), use `InMemorySaver`. +Temporal handles durability, so third-party checkpointers (like PostgreSQL or Redis) are not needed. + +```python +import langgraph.checkpoint.memory +import typing + +from temporalio.contrib.langgraph import graph +from temporalio import workflow + +@workflow.defn +class MyWorkflow: + @workflow.run + async def run(self, input: str) -> typing.Any: + g = graph("my-graph").compile( + checkpointer=langgraph.checkpoint.memory.InMemorySaver(), + ) + + ... +``` + +## Execution Location + +Every node (Graph API) and task (Functional API) must be labeled with `execute_in`, set to either `"activity"` or `"workflow"`. This is required per node/task; it cannot be set in `default_activity_options`. + +```python +# Graph API +graph.add_node("my_node", my_node, metadata={"execute_in": "activity"}) +graph.add_node("tool_node", tool_node, metadata={"execute_in": "workflow"}) + +# Functional API +plugin = LangGraphPlugin( + tasks=[my_task, tool_task], + activity_options={ + "my_task": {"execute_in": "activity"}, + "tool_task": {"execute_in": "workflow"}, + }, +) +``` + +## Activity Options + +Options are passed through to [`workflow.execute_activity()`](https://python.temporal.io/temporalio.workflow.html#execute_activity), which supports parameters like `start_to_close_timeout`, `retry_policy`, `schedule_to_close_timeout`, `heartbeat_timeout`, and more. + +### Graph API + +Pass Activity options as node `metadata` when calling `add_node`: + +```python +from datetime import timedelta +from temporalio.common import RetryPolicy + +g = StateGraph(State) +g.add_node("my_node", my_node, metadata={ + "execute_in": "activity", + "start_to_close_timeout": timedelta(seconds=30), + "retry_policy": RetryPolicy(maximum_attempts=3), +}) +``` + +### Functional API + +Pass Activity options to the `LangGraphPlugin` constructor, keyed by task function name: + +```python +from datetime import timedelta +from temporalio.common import RetryPolicy +from temporalio.contrib.langgraph import LangGraphPlugin + +plugin = LangGraphPlugin( + entrypoints={"my_entrypoint": my_entrypoint}, + tasks=[my_task], + activity_options={ + "my_task": { + "execute_in": "activity", + "start_to_close_timeout": timedelta(seconds=30), + "retry_policy": RetryPolicy(maximum_attempts=3), + }, + }, +) +``` + +### Runtime Context + +LangGraph's run-scoped context (`context_schema`) is reconstructed on the Activity side, so nodes and tasks can read from and write to `runtime.context`: + +```python +from langgraph.runtime import Runtime +from typing_extensions import TypedDict + +from temporalio.contrib.langgraph import graph + +class Context(TypedDict): + user_id: str + +async def my_node(state: State, runtime: Runtime[Context]) -> dict: + return {"user": runtime.context["user_id"]} + +# In the Workflow: +g = graph("my-graph").compile() +await g.ainvoke({...}, context=Context(user_id="alice")) +``` + +Your `context` object must be serializable by the configured Temporal payload converter, since it crosses the Activity boundary. + +## Tracing + +We recommend the [Temporal LangSmith Plugin](https://github.com/temporalio/sdk-python/tree/main/temporalio/contrib/langsmith) to trace your LangGraph Workflows and Activities. + +## Stores are not supported + +LangGraph's `Store` (e.g. `InMemoryStore` passed via `graph.compile(store=...)` or `@entrypoint(store=...)`) isn't accessible inside Activity-wrapped nodes: the Store holds live state that can't cross the Activity boundary, and Activities may run on a different worker than the Workflow. If you pass a store, the plugin logs a warning on first use and `runtime.store` is `None` inside nodes. + +Use Workflow state for per-run memory, or an external database (Postgres/Redis/etc.) configured on each worker if you need shared memory across runs. + +## Running Tests + +Install dependencies: + +```sh +uv sync --all-extras +``` + +Run the test suite: + +```sh +uv run pytest tests/contrib/langgraph +``` + +Tests start a local Temporal dev server automatically — no external server needed. diff --git a/temporalio/contrib/langgraph/__init__.py b/temporalio/contrib/langgraph/__init__.py new file mode 100644 index 000000000..c12d459a6 --- /dev/null +++ b/temporalio/contrib/langgraph/__init__.py @@ -0,0 +1,25 @@ +"""LangGraph plugin for Temporal SDK. + +.. warning:: + This package is experimental and may change in future versions. + Use with caution in production environments. + +This plugin runs `LangGraph `_ nodes +and tasks as Temporal Activities, giving your AI agent workflows durable +execution, automatic retries, and timeouts. It supports both the LangGraph Graph +API (``StateGraph``) and Functional API (``@entrypoint`` / ``@task``). +""" + +from temporalio.contrib.langgraph._plugin import ( + LangGraphPlugin, + cache, + entrypoint, + graph, +) + +__all__ = [ + "LangGraphPlugin", + "entrypoint", + "cache", + "graph", +] diff --git a/temporalio/contrib/langgraph/_activity.py b/temporalio/contrib/langgraph/_activity.py new file mode 100644 index 000000000..f1d66a200 --- /dev/null +++ b/temporalio/contrib/langgraph/_activity.py @@ -0,0 +1,152 @@ +"""Activity wrappers for executing LangGraph nodes and tasks.""" + +from collections.abc import Awaitable +from dataclasses import dataclass +from inspect import iscoroutinefunction, signature +from typing import Any, Callable + +from langgraph.errors import GraphInterrupt +from langgraph.types import Command, Interrupt + +from temporalio import workflow +from temporalio.contrib.langgraph._langgraph_config import ( + get_langgraph_config, + set_langgraph_config, + strip_runnable_config, +) +from temporalio.contrib.langgraph._task_cache import ( + cache_key, + cache_lookup, + cache_put, +) + +# Per-run dedupe so we only warn once when a user passes a Store via +# graph.compile(store=...) / @entrypoint(store=...). Cleared by +# LangGraphInterceptor.execute_workflow on workflow exit. +_warned_store_runs: set[str] = set() + + +def clear_store_warning(run_id: str) -> None: + """Drop the store-warning dedupe entry for a workflow run.""" + _warned_store_runs.discard(run_id) + + +@dataclass +class ActivityInput: + """Input for a LangGraph activity, containing args, kwargs, and config.""" + + args: tuple[Any, ...] + kwargs: dict[str, Any] + langgraph_config: dict[str, Any] + + +@dataclass +class ActivityOutput: + """Output from an Activity, containing result, command, or interrupts.""" + + result: Any = None + langgraph_command: Any = None + langgraph_interrupts: tuple[Interrupt] | None = None + + +def wrap_activity( + func: Callable, +) -> Callable[[ActivityInput], Awaitable[ActivityOutput]]: + """Wrap a function as a Temporal activity that handles LangGraph config and interrupts.""" + # Graph nodes declare `runtime: Runtime[Ctx]` in their signature; tasks + # don't and instead reach for Runtime via get_runtime(). We re-inject the + # reconstructed Runtime only when the user function asks. + accepts_runtime = "runtime" in signature(func).parameters + + async def wrapper(input: ActivityInput) -> ActivityOutput: + runtime = set_langgraph_config(input.langgraph_config) + kwargs = dict(input.kwargs) + if accepts_runtime: + kwargs["runtime"] = runtime + try: + if iscoroutinefunction(func): + result = await func(*input.args, **kwargs) + else: + result = func(*input.args, **kwargs) + if isinstance(result, Command): + return ActivityOutput(langgraph_command=result) + return ActivityOutput(result=result) + except GraphInterrupt as e: + return ActivityOutput(langgraph_interrupts=e.args[0]) + + return wrapper + + +def wrap_execute_activity( + afunc: Callable[[ActivityInput], Awaitable[ActivityOutput]], + task_id: str = "", + **execute_activity_kwargs: Any, +) -> Callable[..., Any]: + """Wrap an activity function to be called via workflow.execute_activity with caching.""" + + async def wrapper(*args: Any, **kwargs: Any) -> Any: + # LangGraph may inject a RunnableConfig as the 'config' kwarg. Strip it + # down to a serializable subset so it can cross the activity boundary; + # callbacks, stores, etc. aren't serializable. + if "config" in kwargs: + kwargs["config"] = strip_runnable_config(kwargs["config"]) + + # LangGraph may inject a Runtime as the 'runtime' kwarg. It's + # reconstructed on the activity side from the serialized langgraph + # config, so drop the live Runtime from the kwargs that cross the + # activity boundary (it holds non-serializable stream_writer, store). + runtime = kwargs.pop("runtime", None) + run_id = workflow.info().run_id + if ( + getattr(runtime, "store", None) is not None + and run_id not in _warned_store_runs + ): + _warned_store_runs.add(run_id) + workflow.logger.warning( + "LangGraph Store passed via compile(store=...) / @entrypoint(store=...) " + "is not accessible inside activity-wrapped nodes and tasks: the Store " + "object isn't serializable across the activity boundary, and activities " + "may run on a different worker than the workflow. Use a backend-backed " + "store (Postgres/Redis) configured on each worker if you need shared " + "memory, or use workflow state for per-run memory." + ) + + langgraph_config = get_langgraph_config() + + # Check task result cache (for continue-as-new deduplication). + key = ( + cache_key(task_id, args, kwargs, langgraph_config.get("context")) + if task_id + else "" + ) + if task_id: + found, cached = cache_lookup(key) + if found: + return cached + + input = ActivityInput( + args=args, kwargs=kwargs, langgraph_config=langgraph_config + ) + output = await workflow.execute_activity( + afunc, input, **execute_activity_kwargs + ) + if output.langgraph_interrupts is not None: + raise GraphInterrupt(output.langgraph_interrupts) + + result = output.result + if output.langgraph_command is not None: + cmd = output.langgraph_command + result = Command( + graph=cmd["graph"], + update=cmd["update"], + resume=cmd["resume"], + goto=cmd["goto"], + ) + + # Store in cache for future continue-as-new cycles. + if task_id: + cache_put(key, result) + + return result + + return wrapper diff --git a/temporalio/contrib/langgraph/_interceptor.py b/temporalio/contrib/langgraph/_interceptor.py new file mode 100644 index 000000000..fd583c052 --- /dev/null +++ b/temporalio/contrib/langgraph/_interceptor.py @@ -0,0 +1,61 @@ +"""Workflow interceptor that scopes LangGraph graphs/entrypoints to the workflow run.""" + +# pyright: reportMissingTypeStubs=false + +from __future__ import annotations + +from typing import Any + +from langgraph.graph import StateGraph +from langgraph.pregel import Pregel + +from temporalio import workflow +from temporalio.contrib.langgraph._activity import clear_store_warning +from temporalio.worker import ( + ExecuteWorkflowInput, + Interceptor, + WorkflowInboundInterceptor, + WorkflowInterceptorClassInput, + WorkflowOutboundInterceptor, +) + +_workflow_graphs: dict[str, dict[str, StateGraph[Any, Any, Any, Any]]] = {} +_workflow_entrypoints: dict[str, dict[str, Pregel[Any, Any, Any, Any]]] = {} + + +class LangGraphInterceptor(Interceptor): + """Interceptor that registers a workflow's graphs and entrypoints for the run.""" + + def __init__( + self, + graphs: dict[str, StateGraph[Any, Any, Any, Any]], + entrypoints: dict[str, Pregel[Any, Any, Any, Any]], + ) -> None: + """Initialize with the graphs and entrypoints to scope to each workflow run.""" + self._graphs = graphs + self._entrypoints = entrypoints + + def workflow_interceptor_class( + self, input: WorkflowInterceptorClassInput + ) -> type[WorkflowInboundInterceptor]: + """Return the inbound interceptor class used to scope graphs per run.""" + graphs = self._graphs + entrypoints = self._entrypoints + + class Inbound(WorkflowInboundInterceptor): + def init(self, outbound: WorkflowOutboundInterceptor) -> None: + run_id = outbound.info().run_id + _workflow_graphs[run_id] = graphs + _workflow_entrypoints[run_id] = entrypoints + super().init(outbound) + + async def execute_workflow(self, input: ExecuteWorkflowInput) -> Any: + try: + return await self.next.execute_workflow(input) + finally: + run_id = workflow.info().run_id + _workflow_graphs.pop(run_id, None) + _workflow_entrypoints.pop(run_id, None) + clear_store_warning(run_id) + + return Inbound diff --git a/temporalio/contrib/langgraph/_langgraph_config.py b/temporalio/contrib/langgraph/_langgraph_config.py new file mode 100644 index 000000000..4cc529477 --- /dev/null +++ b/temporalio/contrib/langgraph/_langgraph_config.py @@ -0,0 +1,160 @@ +"""LangGraph configuration management for Temporal workflows.""" + +# pyright: reportMissingTypeStubs=false + +import dataclasses +from typing import Any + +from langchain_core.runnables.config import var_child_runnable_config +from langgraph._internal._constants import ( + CONFIG_KEY_CHECKPOINT_ID, + CONFIG_KEY_CHECKPOINT_MAP, + CONFIG_KEY_CHECKPOINT_NS, + CONFIG_KEY_DURABILITY, + CONFIG_KEY_RESUMING, + CONFIG_KEY_RUNTIME, + CONFIG_KEY_SCRATCHPAD, + CONFIG_KEY_SEND, + CONFIG_KEY_TASK_ID, + CONFIG_KEY_THREAD_ID, +) +from langgraph._internal._scratchpad import PregelScratchpad +from langgraph.graph.state import RunnableConfig +from langgraph.pregel._algo import LazyAtomicCounter +from langgraph.runtime import ExecutionInfo, Runtime + + +def strip_runnable_config(config: RunnableConfig | None) -> RunnableConfig: + """Return a serializable subset of a RunnableConfig. + + LangGraph injects the active RunnableConfig into user functions as a + config kwarg. The full object holds non-serializable things (callbacks, + checkpointer/store/cache handles, pregel send/read callables) that can't + cross an activity boundary, so we keep only primitive fields and the + serializable subset of configurable. + """ + orig = config or {} + configurable = orig.get("configurable") or {} + + result: RunnableConfig = { + "tags": list(orig.get("tags") or []), + "metadata": dict(orig.get("metadata") or {}), + } + if run_name := orig.get("run_name"): + result["run_name"] = run_name + if run_id := orig.get("run_id"): + result["run_id"] = run_id + if (recursion_limit := orig.get("recursion_limit")) is not None: + result["recursion_limit"] = recursion_limit + + stripped_configurable: dict[str, Any] = { + key: configurable[key] + for key in ( + CONFIG_KEY_CHECKPOINT_NS, + CONFIG_KEY_CHECKPOINT_ID, + CONFIG_KEY_CHECKPOINT_MAP, + CONFIG_KEY_THREAD_ID, + CONFIG_KEY_TASK_ID, + CONFIG_KEY_RESUMING, + CONFIG_KEY_DURABILITY, + ) + if key in configurable + } + if stripped_configurable: + result["configurable"] = stripped_configurable + return result + + +def get_langgraph_config() -> dict[str, Any]: + """Get the current LangGraph runnable config as a serializable dict.""" + config = var_child_runnable_config.get() + configurable = (config or {}).get("configurable") or {} + scratchpad = configurable.get(CONFIG_KEY_SCRATCHPAD) + runtime = configurable.get(CONFIG_KEY_RUNTIME) + execution_info = getattr(runtime, "execution_info", None) + + stripped = strip_runnable_config(config) + return { + **stripped, + "configurable": { + **(stripped.get("configurable") or {}), + CONFIG_KEY_SCRATCHPAD: { + "step": getattr(scratchpad, "step", 0), + "stop": getattr(scratchpad, "stop", 0), + "resume": list(getattr(scratchpad, "resume", [])), + "null_resume": scratchpad.get_null_resume() if scratchpad else None, + }, + }, + "context": getattr(runtime, "context", None), + "previous": getattr(runtime, "previous", None), + "execution_info": ( + dataclasses.asdict(execution_info) if execution_info else None + ), + } + + +def set_langgraph_config(config: dict[str, Any]) -> Runtime: + """Restore a LangGraph runnable config from a serialized dict. + + Returns the reconstructed Runtime so callers can re-inject it into the + user function's kwargs without needing to know the configurable layout. + """ + configurable = config.get("configurable") or {} + scratchpad = configurable.get(CONFIG_KEY_SCRATCHPAD) or {} + null_resume_box = [scratchpad.get("null_resume")] + + def get_null_resume(consume: bool = False) -> Any: + val = null_resume_box[0] + if consume and val is not None: + null_resume_box[0] = None + return val + + execution_info_dict = config.get("execution_info") + runtime = Runtime( + context=config.get("context"), + stream_writer=lambda _: None, + previous=config.get("previous"), + execution_info=( + ExecutionInfo(**execution_info_dict) if execution_info_dict else None + ), + ) + + restored_configurable: dict[str, Any] = { + key: configurable[key] + for key in ( + CONFIG_KEY_CHECKPOINT_NS, + CONFIG_KEY_CHECKPOINT_ID, + CONFIG_KEY_CHECKPOINT_MAP, + CONFIG_KEY_THREAD_ID, + CONFIG_KEY_TASK_ID, + CONFIG_KEY_RESUMING, + CONFIG_KEY_DURABILITY, + ) + if key in configurable + } + restored_configurable[CONFIG_KEY_SCRATCHPAD] = PregelScratchpad( + step=scratchpad.get("step", 0), + stop=scratchpad.get("stop", 0), + call_counter=LazyAtomicCounter(), + interrupt_counter=LazyAtomicCounter(), + get_null_resume=get_null_resume, + resume=list(scratchpad.get("resume", [])), + subgraph_counter=LazyAtomicCounter(), + ) + restored_configurable[CONFIG_KEY_SEND] = lambda _: None + restored_configurable[CONFIG_KEY_RUNTIME] = runtime + + runnable_config: RunnableConfig = {"configurable": restored_configurable} + if tags := config.get("tags"): + runnable_config["tags"] = tags + if metadata := config.get("metadata"): + runnable_config["metadata"] = metadata + if run_name := config.get("run_name"): + runnable_config["run_name"] = run_name + if run_id := config.get("run_id"): + runnable_config["run_id"] = run_id + if (recursion_limit := config.get("recursion_limit")) is not None: + runnable_config["recursion_limit"] = recursion_limit + + var_child_runnable_config.set(runnable_config) + return runtime diff --git a/temporalio/contrib/langgraph/_plugin.py b/temporalio/contrib/langgraph/_plugin.py new file mode 100644 index 000000000..a624f62a7 --- /dev/null +++ b/temporalio/contrib/langgraph/_plugin.py @@ -0,0 +1,262 @@ +"""LangGraph plugin for running LangGraph nodes and tasks as Temporal activities.""" + +# pyright: reportMissingTypeStubs=false + +from __future__ import annotations + +import inspect +import sys +import warnings +from dataclasses import replace +from typing import Any, Callable + +from langgraph._internal._runnable import RunnableCallable +from langgraph.graph import StateGraph +from langgraph.pregel import Pregel + +from temporalio import activity, workflow +from temporalio.contrib.langgraph._activity import wrap_activity, wrap_execute_activity +from temporalio.contrib.langgraph._interceptor import ( + LangGraphInterceptor, + _workflow_entrypoints, + _workflow_graphs, +) +from temporalio.contrib.langgraph._task_cache import ( + get_task_cache, + set_task_cache, + task_id, +) +from temporalio.plugin import SimplePlugin +from temporalio.worker import WorkflowRunner +from temporalio.worker.workflow_sandbox import SandboxedWorkflowRunner + +_ACTIVITY_OPTION_KEYS: frozenset[str] = frozenset( + {"execute_in", *inspect.signature(workflow.execute_activity).parameters} +) + + +class LangGraphPlugin(SimplePlugin): + """LangGraph plugin for Temporal SDK. + + .. warning:: + This package is experimental and may change in future versions. + Use with caution in production environments. + + This plugin runs `LangGraph `_ nodes + and tasks as Temporal Activities, giving your AI agent workflows durable + execution, automatic retries, and timeouts. It supports both the LangGraph Graph + API (``StateGraph``) and Functional API (``@entrypoint`` / ``@task``). + """ + + def __init__( + self, + # Graph API + graphs: dict[str, StateGraph[Any, Any, Any, Any]] | None = None, + # Functional API + entrypoints: dict[str, Pregel[Any, Any, Any, Any]] | None = None, + tasks: list | None = None, + # TODO: Remove activity_options when we have support for @task(metadata=...) + activity_options: dict[str, dict[str, Any]] | None = None, + default_activity_options: dict[str, Any] | None = None, + ): + """Initialize the LangGraph plugin with graphs, entrypoints, and tasks.""" + if sys.version_info < (3, 11): + warnings.warn( # type: ignore[reportUnreachable] + "LangGraphPlugin requires Python >= 3.11 for full async support. " + "On older versions, the Functional API (@task/@entrypoint) and " + "interrupt() will not work because LangGraph relies on " + "contextvars propagation through asyncio.create_task(), which is " + "only available in Python 3.11+. See " + "https://reference.langchain.com/python/langgraph/config/get_store/", + stacklevel=2, + ) + + if default_activity_options and "execute_in" in default_activity_options: + raise ValueError( + "execute_in cannot be set in default_activity_options. " + "Set it on each node's metadata (Graph API) or in " + "activity_options[task_name] (Functional API)." + ) + + self.activities: list = [] + + # Graph API: Wrap graph nodes as Temporal Activities. + if graphs: + for graph_name, graph in graphs.items(): + for node_name, node in graph.nodes.items(): + if node.retry_policy: + raise ValueError( + f"Node {graph_name}.{node_name} has a LangGraph " + f"retry_policy set. Use Temporal activity options " + f"instead, e.g. pass retry_policy=RetryPolicy(...) " + f"via default_activity_options or in the node's " + f"metadata dict." + ) + runnable = node.runnable + if not isinstance(runnable, RunnableCallable): + raise ValueError(f"Node {node_name} must be a RunnableCallable") + user_func = runnable.afunc or runnable.func + if user_func is None: + raise ValueError(f"Node {node_name} must have a function") + # Keep 'config' (for metadata/tags) and 'runtime' (for + # context + store — reconstructed on the activity side). + # Drop writer/etc., which hold non-serializable objects + # that can't cross the activity boundary. + runnable.func_accepts = { + k: v + for k, v in runnable.func_accepts.items() + if k in ("config", "runtime") + } + # Split node.metadata into activity options vs. user + # metadata. Activity-option keys (timeouts, retry policy, + # etc.) become kwargs to workflow.execute_activity; user + # keys stay on node.metadata so LangGraph exposes them to + # the node function via config["metadata"]. + node_meta = node.metadata or {} + node_opts = { + k: v for k, v in node_meta.items() if k in _ACTIVITY_OPTION_KEYS + } + node.metadata = { + k: v + for k, v in node_meta.items() + if k not in _ACTIVITY_OPTION_KEYS + } + if "execute_in" not in node_opts: + raise ValueError( + f"Node {graph_name}.{node_name} is missing required " + f"'execute_in' in metadata. Set it to 'activity' or " + f"'workflow'." + ) + opts = {**(default_activity_options or {}), **node_opts} + # Route all LangGraph node calls through afunc so the async + # activity wrapper is always used. wrap_activity handles + # sync vs. async user functions inside the activity itself. + runnable.afunc = self.execute( + f"{graph_name}.{node_name}", user_func, opts + ) + runnable.func = None + + # Functional API: Wrap @task functions as Temporal Activities. + if tasks: + for task in tasks: + name = task.func.__name__ + if task.retry_policy: + raise ValueError( + f"Task {name} has a LangGraph retry_policy set. " + f"Use Temporal activity options instead, e.g. pass " + f"retry_policy=RetryPolicy(...) via " + f"default_activity_options or activity_options[{name!r}]." + ) + task_opts = (activity_options or {}).get(name, {}) + if "execute_in" not in task_opts: + raise ValueError( + f"Task {name} is missing required 'execute_in' in " + f"activity_options[{name!r}]. Set it to 'activity' or " + f"'workflow'." + ) + opts = { + **(default_activity_options or {}), + **task_opts, + } + + task.func = self.execute(task_id(task.func), task.func, opts) + task.func.__name__ = name + task.func.__qualname__ = getattr(task.func, "__qualname__", name) + + def workflow_runner(runner: WorkflowRunner | None) -> WorkflowRunner: + if not runner: + raise ValueError("No WorkflowRunner provided to the LangGraph plugin.") + if isinstance(runner, SandboxedWorkflowRunner): + return replace( + runner, + restrictions=runner.restrictions.with_passthrough_modules( + "langchain", + "langchain_core", + "langgraph", + "langsmith", + "numpy", # LangSmith uses numpy + ), + ) + return runner + + super().__init__( + "langchain.LangGraphPlugin", + activities=self.activities, + workflow_runner=workflow_runner, + interceptors=[LangGraphInterceptor(graphs or {}, entrypoints or {})], + ) + + def execute( + self, + activity_name: str, + func: Callable, + kwargs: dict[str, Any] | None = None, + ) -> Callable: + """Prepare a node or task to execute as an activity or inline in the workflow.""" + opts = kwargs or {} + execute_in = opts.pop("execute_in") + + if execute_in == "activity": + a = activity.defn(name=activity_name)(wrap_activity(func)) + self.activities.append(a) + return wrap_execute_activity(a, task_id=task_id(func), **opts) + elif execute_in == "workflow": + return func + else: + raise ValueError(f"Invalid execute_in value: {execute_in}") + + +def graph( + name: str, cache: dict[str, Any] | None = None +) -> StateGraph[Any, Any, Any, Any]: + """Retrieve a registered graph by name. + + Args: + name: Graph name as registered with LangGraphPlugin. + cache: Optional task result cache from a previous cache() call. + Restores cached results so previously-completed nodes are + not re-executed after continue-as-new. + """ + set_task_cache(cache or {}) + graphs = _workflow_graphs.get(workflow.info().run_id) + if graphs is None: + raise RuntimeError( + "graph() must be called from inside a workflow running under LangGraphPlugin" + ) + if name not in graphs: + raise KeyError(f"Graph {name!r} not found. Available graphs: {list(graphs)}") + return graphs[name] + + +def entrypoint( + name: str, cache: dict[str, Any] | None = None +) -> Pregel[Any, Any, Any, Any]: + """Retrieve a registered entrypoint by name. + + Args: + name: Entrypoint name as registered with Plugin. + cache: Optional task result cache from a previous cache() call. + Restores cached results so previously-completed tasks are + not re-executed after continue-as-new. + """ + set_task_cache(cache or {}) + entrypoints = _workflow_entrypoints.get(workflow.info().run_id) + if entrypoints is None: + raise RuntimeError( + "entrypoint() must be called from inside a workflow running under LangGraphPlugin" + ) + if name not in entrypoints: + raise KeyError( + f"Entrypoint {name!r} not found. Available entrypoints: {list(entrypoints)}" + ) + return entrypoints[name] + + +def cache() -> dict[str, Any] | None: + """Return the task result cache as a serializable dict. + + Returns a dict suitable for passing to entrypoint(name, cache=...) to + restore cached task results across continue-as-new boundaries. + Returns None if the cache is empty. + """ + return get_task_cache() or None diff --git a/temporalio/contrib/langgraph/_task_cache.py b/temporalio/contrib/langgraph/_task_cache.py new file mode 100644 index 000000000..ab3e683d7 --- /dev/null +++ b/temporalio/contrib/langgraph/_task_cache.py @@ -0,0 +1,83 @@ +"""Task result cache for continue-as-new support. + +Caches task results by (module.qualname, args, kwargs) hash so that previously +completed tasks are not re-executed after a continue-as-new. The cache state +is a plain dict that can travel through workflow.continue_as_new(). +""" + +from __future__ import annotations + +from contextvars import ContextVar +from hashlib import sha256 +from json import dumps +from typing import Any + +_task_cache: ContextVar[dict[str, Any] | None] = ContextVar( + "_temporal_task_cache", default=None +) + + +def set_task_cache(cache: dict[str, Any] | None) -> None: + """Set the task result cache for the current context.""" + _task_cache.set(cache) + + +def get_task_cache() -> dict[str, Any] | None: + """Get the task result cache for the current context.""" + return _task_cache.get() + + +def task_id(func: Any) -> str: + """Return the fully-qualified module.qualname for a function. + + Raises ValueError for functions that cannot be identified unambiguously + (lambdas, closures, __main__ functions). + """ + module = getattr(func, "__module__", None) + qualname = getattr(func, "__qualname__", None) or getattr(func, "__name__", None) + + if module is None or qualname is None: + raise ValueError( + f"Cannot identify task {func}: missing __module__ or __qualname__. " + "Tasks must be defined at module level." + ) + if module == "__main__": + raise ValueError( + f"Cannot identify task {qualname}: defined in __main__. " + "Tasks must be importable from a named module." + ) + if "" in qualname: + raise ValueError( + f"Cannot identify task {qualname}: closures/local functions are not supported. " + "Tasks must be defined at module level." + ) + return f"{module}.{qualname}" + + +def cache_key( + task_id: str, + args: tuple[Any, ...], + kwargs: dict[str, Any], + context: Any = None, +) -> str: + """Build a cache key from the full task identifier, arguments, and runtime context.""" + try: + key_str = dumps([task_id, args, kwargs, context], sort_keys=True, default=str) + except (TypeError, ValueError): + key_str = repr([task_id, args, kwargs, context]) + return sha256(key_str.encode()).hexdigest()[:32] + + +def cache_lookup(key: str) -> tuple[bool, Any]: + """Return (True, value) if cached, (False, None) otherwise.""" + cache = _task_cache.get() + if cache is not None and key in cache: + return True, cache[key] + return False, None + + +def cache_put(key: str, value: Any) -> None: + """Store a value in the task result cache.""" + cache = _task_cache.get() + if cache is not None: + cache[key] = value diff --git a/temporalio/contrib/langsmith/_plugin.py b/temporalio/contrib/langsmith/_plugin.py index 6e9fba0ee..789c93414 100644 --- a/temporalio/contrib/langsmith/_plugin.py +++ b/temporalio/contrib/langsmith/_plugin.py @@ -9,6 +9,15 @@ import langsmith +# langsmith conditionally imports langchain_core when it is installed. +# Pre-import the lazily-loaded submodule so it is in sys.modules before the +# workflow sandbox starts; otherwise the sandbox's __getattr__-triggered +# import hits restrictions on concurrent.futures.ThreadPoolExecutor. +try: + import langchain_core.runnables.config # noqa: F401 # pyright: ignore[reportUnusedImport] +except ImportError: + pass + from temporalio.contrib.langsmith._interceptor import LangSmithInterceptor from temporalio.plugin import SimplePlugin from temporalio.worker import WorkflowRunner @@ -62,7 +71,8 @@ def workflow_runner(runner: WorkflowRunner | None) -> WorkflowRunner: return dataclasses.replace( runner, restrictions=runner.restrictions.with_passthrough_modules( - "langsmith" + "langsmith", + "langchain_core", ), ) return runner diff --git a/tests/contrib/langgraph/__init__.py b/tests/contrib/langgraph/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/tests/contrib/langgraph/e2e_functional_entrypoints.py b/tests/contrib/langgraph/e2e_functional_entrypoints.py new file mode 100644 index 000000000..7f16abe8d --- /dev/null +++ b/tests/contrib/langgraph/e2e_functional_entrypoints.py @@ -0,0 +1,144 @@ +"""Functional API entrypoint definitions for E2E tests. + +These define @task and @entrypoint functions used in functional API E2E tests. +""" + +from __future__ import annotations + +import asyncio + +import langgraph.types +from langgraph.func import entrypoint, task # pyright: ignore[reportMissingTypeStubs] + + +@task +def double_value(x: int) -> int: + return x * 2 + + +@task +def add_ten(x: int) -> int: + return x + 10 + + +@entrypoint() +async def simple_functional_entrypoint(value: int) -> dict: + doubled = await double_value(value) + result = await add_ten(doubled) + return {"result": result} + + +# Track task execution count for continue-as-new testing +_task_execution_counts: dict[str, int] = {} + + +def get_task_execution_counts() -> dict[str, int]: + return _task_execution_counts.copy() + + +def reset_task_execution_counts() -> None: + _task_execution_counts.clear() + + +@task +def expensive_task_a(x: int) -> int: + _task_execution_counts["task_a"] = _task_execution_counts.get("task_a", 0) + 1 + return x * 3 + + +@task +def expensive_task_b(x: int) -> int: + _task_execution_counts["task_b"] = _task_execution_counts.get("task_b", 0) + 1 + return x + 100 + + +@task +def expensive_task_c(x: int) -> int: + _task_execution_counts["task_c"] = _task_execution_counts.get("task_c", 0) + 1 + return x * 2 + + +@entrypoint() +async def continue_as_new_entrypoint(value: int) -> dict: + """For input 10: 10 * 3 = 30 -> 30 + 100 = 130 -> 130 * 2 = 260""" + result_a = await expensive_task_a(value) + result_b = await expensive_task_b(result_a) + result_c = await expensive_task_c(result_b) + return {"result": result_c} + + +@task +def step_1(x: int) -> int: + _task_execution_counts["step_1"] = _task_execution_counts.get("step_1", 0) + 1 + return x * 2 + + +@task +def step_2(x: int) -> int: + _task_execution_counts["step_2"] = _task_execution_counts.get("step_2", 0) + 1 + return x + 5 + + +@task +def step_3(x: int) -> int: + _task_execution_counts["step_3"] = _task_execution_counts.get("step_3", 0) + 1 + return x * 3 + + +@task +def step_4(x: int) -> int: + _task_execution_counts["step_4"] = _task_execution_counts.get("step_4", 0) + 1 + return x - 10 + + +@task +def step_5(x: int) -> int: + _task_execution_counts["step_5"] = _task_execution_counts.get("step_5", 0) + 1 + return x + 100 + + +@entrypoint() +async def partial_execution_entrypoint(input_data: dict) -> dict: + """For value=10, all 5 tasks: 10*2=20 -> +5=25 -> *3=75 -> -10=65 -> +100=165""" + value = input_data["value"] + stop_after = input_data.get("stop_after", 5) + + result = value + result = await step_1(result) + if stop_after == 1: + return {"result": result, "completed_tasks": 1} + result = await step_2(result) + if stop_after == 2: + return {"result": result, "completed_tasks": 2} + result = await step_3(result) + if stop_after == 3: + return {"result": result, "completed_tasks": 3} + result = await step_4(result) + if stop_after == 4: + return {"result": result, "completed_tasks": 4} + result = await step_5(result) + return {"result": result, "completed_tasks": 5} + + +@task +def ask_human(question: str) -> str: + return langgraph.types.interrupt(question) + + +@entrypoint() +async def interrupt_entrypoint(value: str) -> dict: + """Entrypoint that interrupts for human input, then returns the answer.""" + answer = await ask_human("Do you approve?") + return {"input": value, "answer": answer} + + +@task +async def slow_task(x: int) -> int: + await asyncio.sleep(1) + return x + + +@entrypoint() +async def slow_entrypoint(value: int) -> dict: + result = await slow_task(value) + return {"result": result} diff --git a/tests/contrib/langgraph/e2e_functional_workflows.py b/tests/contrib/langgraph/e2e_functional_workflows.py new file mode 100644 index 000000000..d355bdb28 --- /dev/null +++ b/tests/contrib/langgraph/e2e_functional_workflows.py @@ -0,0 +1,97 @@ +"""Workflow definitions for Functional API E2E tests.""" + +from __future__ import annotations + +from dataclasses import dataclass +from typing import Any + +from temporalio import workflow +from temporalio.contrib.langgraph import cache, entrypoint + + +@workflow.defn +class SimpleFunctionalE2EWorkflow: + def __init__(self) -> None: + self.app = entrypoint("e2e_simple_functional") + + @workflow.run + async def run(self, input_value: int) -> dict: + return await self.app.ainvoke(input_value) + + +@workflow.defn +class SlowFunctionalWorkflow: + def __init__(self) -> None: + self.app = entrypoint("e2e_slow_functional") + + @workflow.run + async def run(self, input_value: int) -> dict: + return await self.app.ainvoke(input_value) + + +@dataclass +class ContinueAsNewInput: + value: int + cache: dict[str, Any] | None = None + task_a_done: bool = False + task_b_done: bool = False + + +@workflow.defn +class ContinueAsNewFunctionalWorkflow: + """Continues-as-new after each phase, passing cache for task deduplication.""" + + @workflow.run + async def run(self, input_data: ContinueAsNewInput) -> dict[str, Any]: + app = entrypoint("e2e_continue_as_new_functional", cache=input_data.cache) + + result = await app.ainvoke(input_data.value) + + if not input_data.task_a_done: + workflow.continue_as_new( + ContinueAsNewInput( + value=input_data.value, + cache=cache(), + task_a_done=True, + ) + ) + + if not input_data.task_b_done: + workflow.continue_as_new( + ContinueAsNewInput( + value=input_data.value, + cache=cache(), + task_a_done=True, + task_b_done=True, + ) + ) + + return result + + +@dataclass +class PartialExecutionInput: + value: int + cache: dict[str, Any] | None = None + phase: int = 1 + + +@workflow.defn +class PartialExecutionWorkflow: + """Phase 1: 3 tasks + cache. Phase 2: all 5 (1-3 cached).""" + + @workflow.run + async def run(self, input_data: PartialExecutionInput) -> dict[str, Any]: + app = entrypoint("e2e_partial_execution", cache=input_data.cache) + + if input_data.phase == 1: + await app.ainvoke({"value": input_data.value, "stop_after": 3}) + workflow.continue_as_new( + PartialExecutionInput( + value=input_data.value, + cache=cache(), + phase=2, + ) + ) + + return await app.ainvoke({"value": input_data.value, "stop_after": 5}) diff --git a/tests/contrib/langgraph/test_command.py b/tests/contrib/langgraph/test_command.py new file mode 100644 index 000000000..59a2fd68b --- /dev/null +++ b/tests/contrib/langgraph/test_command.py @@ -0,0 +1,68 @@ +from datetime import timedelta +from typing import Any, Literal +from uuid import uuid4 + +from langgraph.graph import ( # pyright: ignore[reportMissingTypeStubs] + START, + StateGraph, +) +from langgraph.types import Command +from typing_extensions import TypedDict + +from temporalio import workflow +from temporalio.client import Client +from temporalio.contrib.langgraph import LangGraphPlugin, graph +from temporalio.worker import Worker + + +class State(TypedDict): + value: str + + +def node_a(state: State) -> Command[Literal["node_b"]]: + return Command(update={"value": state["value"] + "a"}, goto="node_b") + + +def node_b(state: State) -> Command[Literal["__end__"]]: + return Command(update={"value": state["value"] + "b"}, goto="__end__") + + +@workflow.defn +class CommandWorkflow: + def __init__(self) -> None: + self.app = graph("my-graph").compile() + + @workflow.run + async def run(self, input: str) -> Any: + return await self.app.ainvoke({"value": input}) + + +async def test_command_goto_and_update(client: Client): + g = StateGraph(State) + g.add_node("node_a", node_a, metadata={"execute_in": "activity"}) + g.add_node("node_b", node_b, metadata={"execute_in": "activity"}) + g.add_edge(START, "node_a") + + task_queue = f"command-{uuid4()}" + + async with Worker( + client, + task_queue=task_queue, + workflows=[CommandWorkflow], + plugins=[ + LangGraphPlugin( + graphs={"my-graph": g}, + default_activity_options={ + "start_to_close_timeout": timedelta(seconds=10) + }, + ) + ], + ): + result = await client.execute_workflow( + CommandWorkflow.run, + "", + id=f"test-command-{uuid4()}", + task_queue=task_queue, + ) + + assert result == {"value": "ab"} diff --git a/tests/contrib/langgraph/test_continue_as_new.py b/tests/contrib/langgraph/test_continue_as_new.py new file mode 100644 index 000000000..304862361 --- /dev/null +++ b/tests/contrib/langgraph/test_continue_as_new.py @@ -0,0 +1,72 @@ +from datetime import timedelta +from typing import Any +from uuid import uuid4 + +from langgraph.checkpoint.memory import InMemorySaver +from langgraph.graph import START, StateGraph # pyright: ignore[reportMissingTypeStubs] +from langgraph.graph.state import ( # pyright: ignore[reportMissingTypeStubs] + RunnableConfig, +) +from typing_extensions import TypedDict + +from temporalio import workflow +from temporalio.client import Client +from temporalio.contrib.langgraph import LangGraphPlugin, graph +from temporalio.worker import Worker + + +class State(TypedDict): + value: str + + +async def node(state: State) -> dict[str, str]: + return {"value": state["value"] + "a"} + + +@workflow.defn +class ContinueAsNewWorkflow: + def __init__(self) -> None: + self.app = graph("my-graph").compile(checkpointer=InMemorySaver()) + + @workflow.run + async def run(self, values: State) -> Any: + config = RunnableConfig({"configurable": {"thread_id": "1"}}) + + await self.app.aupdate_state(config, values) + await self.app.ainvoke(values, config) + + if len(values["value"]) < 3: + state = await self.app.aget_state(config) + workflow.continue_as_new(state.values) + + return values + + +async def test_continue_as_new(client: Client): + g = StateGraph(State) + g.add_node("node", node, metadata={"execute_in": "activity"}) + g.add_edge(START, "node") + + task_queue = f"my-graph-{uuid4()}" + + async with Worker( + client, + task_queue=task_queue, + workflows=[ContinueAsNewWorkflow], + plugins=[ + LangGraphPlugin( + graphs={"my-graph": g}, + default_activity_options={ + "start_to_close_timeout": timedelta(seconds=10) + }, + ) + ], + ): + result = await client.execute_workflow( + ContinueAsNewWorkflow.run, + State(value=""), + id=f"test-workflow-{uuid4()}", + task_queue=task_queue, + ) + + assert result == {"value": "aaa"} diff --git a/tests/contrib/langgraph/test_continue_as_new_cached.py b/tests/contrib/langgraph/test_continue_as_new_cached.py new file mode 100644 index 000000000..b19620999 --- /dev/null +++ b/tests/contrib/langgraph/test_continue_as_new_cached.py @@ -0,0 +1,131 @@ +"""Test Graph API continue-as-new with task result caching. + +Verifies that node results are cached across continue-as-new boundaries, +so nodes don't re-execute when the graph is re-invoked with the same state. +""" + +from dataclasses import dataclass +from datetime import timedelta +from typing import Any +from uuid import uuid4 + +from langgraph.graph import START, StateGraph # pyright: ignore[reportMissingTypeStubs] +from typing_extensions import TypedDict + +from temporalio import workflow +from temporalio.client import Client +from temporalio.contrib.langgraph import LangGraphPlugin, cache, graph +from temporalio.worker import Worker + +# Track execution counts to verify caching +_execution_counts: dict[str, int] = {} + + +def _reset(): + _execution_counts.clear() + + +class State(TypedDict): + value: int + + +async def multiply_by_3(state: State) -> dict[str, int]: + _execution_counts["multiply"] = _execution_counts.get("multiply", 0) + 1 + return {"value": state["value"] * 3} + + +async def add_100(state: State) -> dict[str, int]: + _execution_counts["add"] = _execution_counts.get("add", 0) + 1 + return {"value": state["value"] + 100} + + +async def double(state: State) -> dict[str, int]: + _execution_counts["double"] = _execution_counts.get("double", 0) + 1 + return {"value": state["value"] * 2} + + +@dataclass +class GraphContinueAsNewInput: + value: int + cache: dict[str, Any] | None = None + phase: int = 1 # 1, 2, 3 — continues-as-new after phases 1 and 2 + + +@workflow.defn +class GraphContinueAsNewWorkflow: + """Runs a 3-node graph, continuing-as-new after each phase. + + Phase 1: runs graph (all 3 nodes execute), continues-as-new with cache. + Phase 2: runs graph again with same input (all 3 cached), continues-as-new. + Phase 3: runs graph again with same input (all 3 cached), returns result. + + Without caching: each node executes 3 times. + With caching: each node executes once (first run), cached for phases 2 & 3. + """ + + @workflow.run + async def run(self, input_data: GraphContinueAsNewInput) -> dict[str, int]: + app = graph("cached-graph", cache=input_data.cache).compile() + result = await app.ainvoke({"value": input_data.value}) + + if input_data.phase < 3: + workflow.continue_as_new( + GraphContinueAsNewInput( + value=input_data.value, + cache=cache(), + phase=input_data.phase + 1, + ) + ) + + return result + + +async def test_graph_continue_as_new_cached(client: Client): + """Each node executes once despite 3 continue-as-new cycles. + + Graph: multiply_by_3 -> add_100 -> double + Input 10: 10 * 3 = 30 -> 30 + 100 = 130 -> 130 * 2 = 260 + """ + _reset() + + metadata = { + "execute_in": "activity", + "start_to_close_timeout": timedelta(seconds=10), + } + g = StateGraph(State) + g.add_node("multiply_by_3", multiply_by_3, metadata=metadata) + g.add_node("add_100", add_100, metadata=metadata) + g.add_node("double", double, metadata=metadata) + g.add_edge(START, "multiply_by_3") + g.add_edge("multiply_by_3", "add_100") + g.add_edge("add_100", "double") + + task_queue = f"graph-cached-{uuid4()}" + + async with Worker( + client, + task_queue=task_queue, + workflows=[GraphContinueAsNewWorkflow], + plugins=[LangGraphPlugin(graphs={"cached-graph": g})], + ): + result = await client.execute_workflow( + GraphContinueAsNewWorkflow.run, + GraphContinueAsNewInput(value=10), + id=f"graph-cached-{uuid4()}", + task_queue=task_queue, + execution_timeout=timedelta(seconds=60), + ) + + # 10 * 3 = 30 -> + 100 = 130 -> * 2 = 260 + assert result == {"value": 260} + + # Each node should execute exactly once — phases 2 and 3 use cached results. + assert ( + _execution_counts.get("multiply", 0) == 1 + ), f"multiply executed {_execution_counts.get('multiply', 0)} times, expected 1" + assert ( + _execution_counts.get("add", 0) == 1 + ), f"add executed {_execution_counts.get('add', 0)} times, expected 1" + assert ( + _execution_counts.get("double", 0) == 1 + ), f"double executed {_execution_counts.get('double', 0)} times, expected 1" diff --git a/tests/contrib/langgraph/test_e2e_functional.py b/tests/contrib/langgraph/test_e2e_functional.py new file mode 100644 index 000000000..649a0b619 --- /dev/null +++ b/tests/contrib/langgraph/test_e2e_functional.py @@ -0,0 +1,338 @@ +"""End-to-end tests for LangGraph Functional API integration (v1 and v2). + +Requires a running Temporal test server (started by conftest.py). +LangGraph's Functional API requires Python >= 3.11 for async context +variable propagation (see langgraph.config.get_config). +""" + +from __future__ import annotations + +import sys +from datetime import timedelta +from typing import Any +from uuid import uuid4 + +import pytest + +pytestmark = pytest.mark.skipif( + sys.version_info < (3, 11), + reason="LangGraph Functional API requires Python >= 3.11 for async context propagation", +) +from langchain_core.runnables import RunnableConfig +from langgraph.checkpoint.memory import InMemorySaver +from langgraph.func import ( # pyright: ignore[reportMissingTypeStubs] + entrypoint as lg_entrypoint, +) +from langgraph.func import task # pyright: ignore[reportMissingTypeStubs] +from langgraph.types import Command +from pytest import raises + +from temporalio import workflow +from temporalio.client import Client, WorkflowFailureError +from temporalio.common import RetryPolicy +from temporalio.contrib.langgraph import LangGraphPlugin, entrypoint +from temporalio.worker import Worker +from tests.contrib.langgraph.e2e_functional_entrypoints import ( + add_ten, + ask_human, + continue_as_new_entrypoint, + double_value, + expensive_task_a, + expensive_task_b, + expensive_task_c, + get_task_execution_counts, + interrupt_entrypoint, + partial_execution_entrypoint, + reset_task_execution_counts, + simple_functional_entrypoint, + slow_entrypoint, + slow_task, + step_1, + step_2, + step_3, + step_4, + step_5, +) +from tests.contrib.langgraph.e2e_functional_workflows import ( + ContinueAsNewFunctionalWorkflow, + ContinueAsNewInput, + PartialExecutionInput, + PartialExecutionWorkflow, + SimpleFunctionalE2EWorkflow, + SlowFunctionalWorkflow, +) + +_DEFAULT_ACTIVITY_OPTIONS = {"start_to_close_timeout": timedelta(seconds=30)} + + +def _execute_in_activity(*task_names: str) -> dict[str, dict[str, Any]]: + return {name: {"execute_in": "activity"} for name in task_names} + + +# V2-only tasks defined here to avoid sharing mutated _TaskFunction objects +# (Plugin wraps task.func in-place). + + +@task +def triple_value(x: int) -> int: + return x * 3 + + +@task +def add_five(x: int) -> int: + return x + 5 + + +@lg_entrypoint() +async def simple_v2_entrypoint(value: int) -> dict: + tripled = await triple_value(value) + result = await add_five(tripled) + return {"result": result} + + +@workflow.defn +class SimpleV2Workflow: + def __init__(self) -> None: + self.app = entrypoint("v2_simple") + + @workflow.run + async def run(self, input_value: int) -> dict[str, Any]: + result = await self.app.ainvoke(input_value, version="v2") + return result.value + + +@workflow.defn +class InterruptV2FunctionalWorkflow: + def __init__(self) -> None: + self.app = entrypoint("v2_interrupt") + self.app.checkpointer = InMemorySaver() + + @workflow.run + async def run(self, input_value: str) -> dict[str, Any]: + config = RunnableConfig( + {"configurable": {"thread_id": workflow.info().workflow_id}} + ) + + result = await self.app.ainvoke(input_value, config, version="v2") + + assert result.value == {} + assert len(result.interrupts) == 1 + assert result.interrupts[0].value == "Do you approve?" + + resumed = await self.app.ainvoke( + Command(resume="approved"), config, version="v2" + ) + return resumed.value + + +class TestFunctionalAPIBasicExecution: + @pytest.mark.parametrize( + "workflow_cls,entrypoint_func,entrypoint_name,tasks,expected_result", + [ + ( + SimpleFunctionalE2EWorkflow, + simple_functional_entrypoint, + "e2e_simple_functional", + [double_value, add_ten], + 30, + ), + ( + SimpleV2Workflow, + simple_v2_entrypoint, + "v2_simple", + [triple_value, add_five], + 35, + ), + ], + ids=["v1", "v2"], + ) + async def test_simple_entrypoint( + self, + client: Client, + workflow_cls: Any, + entrypoint_func: Any, + entrypoint_name: str, + tasks: list, + expected_result: int, + ) -> None: + task_queue = f"e2e-functional-{uuid4()}" + + async with Worker( + client, + task_queue=task_queue, + workflows=[workflow_cls], + plugins=[ + LangGraphPlugin( + entrypoints={entrypoint_name: entrypoint_func}, + tasks=tasks, + activity_options=_execute_in_activity( + *(t.func.__name__ for t in tasks) + ), + default_activity_options=_DEFAULT_ACTIVITY_OPTIONS, + ) + ], + ): + result = await client.execute_workflow( + workflow_cls.run, + 10, + id=f"e2e-functional-{uuid4()}", + task_queue=task_queue, + execution_timeout=timedelta(seconds=30), + ) + + assert result["result"] == expected_result + + +class TestFunctionalAPIContinueAsNew: + async def test_continue_as_new_with_checkpoint(self, client: Client) -> None: + """10 * 3 = 30 -> + 100 = 130 -> * 2 = 260. Each task executes once.""" + reset_task_execution_counts() + + tasks = [expensive_task_a, expensive_task_b, expensive_task_c] + task_queue = f"e2e-continue-as-new-{uuid4()}" + + async with Worker( + client, + task_queue=task_queue, + workflows=[ContinueAsNewFunctionalWorkflow], + plugins=[ + LangGraphPlugin( + entrypoints={ + "e2e_continue_as_new_functional": continue_as_new_entrypoint + }, + tasks=tasks, + activity_options=_execute_in_activity( + *(getattr(t.func, "__name__") for t in tasks) + ), + default_activity_options=_DEFAULT_ACTIVITY_OPTIONS, + ) + ], + ): + result = await client.execute_workflow( + ContinueAsNewFunctionalWorkflow.run, + ContinueAsNewInput(value=10), + id=f"e2e-continue-as-new-{uuid4()}", + task_queue=task_queue, + execution_timeout=timedelta(seconds=60), + ) + + assert result["result"] == 260 + + counts = get_task_execution_counts() + assert ( + counts.get("task_a", 0) == 1 + ), f"task_a executed {counts.get('task_a', 0)} times, expected 1" + assert ( + counts.get("task_b", 0) == 1 + ), f"task_b executed {counts.get('task_b', 0)} times, expected 1" + assert ( + counts.get("task_c", 0) == 1 + ), f"task_c executed {counts.get('task_c', 0)} times, expected 1" + + +class TestFunctionalAPIPartialExecution: + async def test_partial_execution_five_tasks(self, client: Client) -> None: + """10*2=20 -> +5=25 -> *3=75 -> -10=65 -> +100=165. Each task executes once.""" + reset_task_execution_counts() + + tasks = [step_1, step_2, step_3, step_4, step_5] + task_queue = f"e2e-partial-{uuid4()}" + + async with Worker( + client, + task_queue=task_queue, + workflows=[PartialExecutionWorkflow], + plugins=[ + LangGraphPlugin( + entrypoints={"e2e_partial_execution": partial_execution_entrypoint}, + tasks=tasks, + activity_options=_execute_in_activity( + *(getattr(t.func, "__name__") for t in tasks) + ), + default_activity_options=_DEFAULT_ACTIVITY_OPTIONS, + ) + ], + ): + result = await client.execute_workflow( + PartialExecutionWorkflow.run, + PartialExecutionInput(value=10), + id=f"e2e-partial-{uuid4()}", + task_queue=task_queue, + execution_timeout=timedelta(seconds=60), + ) + + assert result["result"] == 165 + assert result["completed_tasks"] == 5 + + counts = get_task_execution_counts() + for i in range(1, 6): + assert ( + counts.get(f"step_{i}", 0) == 1 + ), f"step_{i} executed {counts.get(f'step_{i}', 0)} times, expected 1" + + +class TestFunctionalAPIInterruptV2: + async def test_interrupt_v2_functional(self, client: Client) -> None: + """version='v2' separates interrupts from value in functional API.""" + tasks = [ask_human] + task_queue = f"v2-interrupt-{uuid4()}" + + async with Worker( + client, + task_queue=task_queue, + workflows=[InterruptV2FunctionalWorkflow], + plugins=[ + LangGraphPlugin( + entrypoints={"v2_interrupt": interrupt_entrypoint}, + tasks=tasks, + activity_options=_execute_in_activity( + *(getattr(t.func, "__name__") for t in tasks) + ), + default_activity_options=_DEFAULT_ACTIVITY_OPTIONS, + ) + ], + ): + result = await client.execute_workflow( + InterruptV2FunctionalWorkflow.run, + "hello", + id=f"v2-interrupt-{uuid4()}", + task_queue=task_queue, + execution_timeout=timedelta(seconds=30), + ) + + assert result["input"] == "hello" + assert result["answer"] == "approved" + + +class TestFunctionalAPIPerTaskOptions: + async def test_per_task_activity_options_override(self, client: Client) -> None: + """activity_options[task_name] overrides default_activity_options for that task.""" + task_queue = f"e2e-per-task-options-{uuid4()}" + + async with Worker( + client, + task_queue=task_queue, + workflows=[SlowFunctionalWorkflow], + plugins=[ + LangGraphPlugin( + entrypoints={"e2e_slow_functional": slow_entrypoint}, + tasks=[slow_task], + default_activity_options=_DEFAULT_ACTIVITY_OPTIONS, + activity_options={ + "slow_task": { + "execute_in": "activity", + "start_to_close_timeout": timedelta(milliseconds=100), + "retry_policy": RetryPolicy(maximum_attempts=1), + } + }, + ) + ], + ): + with raises(WorkflowFailureError): + await client.execute_workflow( + SlowFunctionalWorkflow.run, + 1, + id=f"e2e-per-task-options-{uuid4()}", + task_queue=task_queue, + execution_timeout=timedelta(seconds=30), + ) diff --git a/tests/contrib/langgraph/test_execute_in_workflow.py b/tests/contrib/langgraph/test_execute_in_workflow.py new file mode 100644 index 000000000..15b44f5a9 --- /dev/null +++ b/tests/contrib/langgraph/test_execute_in_workflow.py @@ -0,0 +1,51 @@ +from typing import Any +from uuid import uuid4 + +from langgraph.graph import START, StateGraph # pyright: ignore[reportMissingTypeStubs] +from typing_extensions import TypedDict + +from temporalio import workflow +from temporalio.client import Client +from temporalio.contrib.langgraph import LangGraphPlugin, graph +from temporalio.worker import Worker + + +class State(TypedDict): + value: str + + +async def node(state: State) -> dict[str, str]: # pyright: ignore[reportUnusedParameter] + return {"value": "done"} + + +@workflow.defn +class ExecuteInWorkflowWorkflow: + def __init__(self) -> None: + self.app = graph("my-graph").compile() + + @workflow.run + async def run(self, input: str) -> Any: + return await self.app.ainvoke({"value": input}) + + +async def test_execute_in_workflow(client: Client): + g = StateGraph(State) + g.add_node("node", node, metadata={"execute_in": "workflow"}) + g.add_edge(START, "node") + + task_queue = f"my-graph-{uuid4()}" + + async with Worker( + client, + task_queue=task_queue, + workflows=[ExecuteInWorkflowWorkflow], + plugins=[LangGraphPlugin(graphs={"my-graph": g})], + ): + result = await client.execute_workflow( + ExecuteInWorkflowWorkflow.run, + "", + id=f"test-workflow-{uuid4()}", + task_queue=task_queue, + ) + + assert result == {"value": "done"} diff --git a/tests/contrib/langgraph/test_interrupt.py b/tests/contrib/langgraph/test_interrupt.py new file mode 100644 index 000000000..6d4547d76 --- /dev/null +++ b/tests/contrib/langgraph/test_interrupt.py @@ -0,0 +1,97 @@ +import sys +from datetime import timedelta +from typing import Any +from uuid import uuid4 + +import langgraph.types +import pytest + +pytestmark = pytest.mark.skipif( + sys.version_info < (3, 11), + reason="langgraph.types.interrupt() requires Python >= 3.11 for async context propagation", +) +from langgraph.checkpoint.memory import InMemorySaver +from langgraph.graph import START, StateGraph # pyright: ignore[reportMissingTypeStubs] +from langgraph.graph.state import ( # pyright: ignore[reportMissingTypeStubs] + RunnableConfig, +) +from typing_extensions import TypedDict + +from temporalio import workflow +from temporalio.client import Client +from temporalio.contrib.langgraph import LangGraphPlugin, graph +from temporalio.worker import Worker + + +class State(TypedDict): + value: str + + +async def node(state: State) -> dict[str, str]: # pyright: ignore[reportUnusedParameter] + return {"value": langgraph.types.interrupt("Continue?")} + + +@workflow.defn +class InterruptWorkflow: + def __init__(self) -> None: + self.app = graph("my-graph").compile(checkpointer=InMemorySaver()) + + @workflow.run + async def run(self, input: str) -> Any: + config = RunnableConfig({"configurable": {"thread_id": "1"}}) + + result = await self.app.ainvoke({"value": input}, config) + assert result["__interrupt__"][0].value == "Continue?" + + return await self.app.ainvoke(langgraph.types.Command(resume="yes"), config) + + +@workflow.defn +class InterruptV2Workflow: + def __init__(self) -> None: + self.app = graph("my-graph").compile(checkpointer=InMemorySaver()) + + @workflow.run + async def run(self, input: str) -> Any: + config = RunnableConfig({"configurable": {"thread_id": "1"}}) + + result = await self.app.ainvoke({"value": input}, config, version="v2") + + assert result.value == {"value": ""} + assert len(result.interrupts) == 1 + assert result.interrupts[0].value == "Continue?" + + return await self.app.ainvoke(langgraph.types.Command(resume="yes"), config) + + +@pytest.mark.parametrize( + "workflow_cls", [InterruptWorkflow, InterruptV2Workflow], ids=["v1", "v2"] +) +async def test_interrupt(client: Client, workflow_cls: Any) -> None: + g = StateGraph(State) + g.add_node("node", node, metadata={"execute_in": "activity"}) + g.add_edge(START, "node") + + task_queue = f"interrupt-{uuid4()}" + + async with Worker( + client, + task_queue=task_queue, + workflows=[workflow_cls], + plugins=[ + LangGraphPlugin( + graphs={"my-graph": g}, + default_activity_options={ + "start_to_close_timeout": timedelta(seconds=10) + }, + ) + ], + ): + result = await client.execute_workflow( + workflow_cls.run, + "", + id=f"test-workflow-{uuid4()}", + task_queue=task_queue, + ) + + assert result == {"value": "yes"} diff --git a/tests/contrib/langgraph/test_node_metadata.py b/tests/contrib/langgraph/test_node_metadata.py new file mode 100644 index 000000000..ca022d3a1 --- /dev/null +++ b/tests/contrib/langgraph/test_node_metadata.py @@ -0,0 +1,65 @@ +from datetime import timedelta +from typing import Any +from uuid import uuid4 + +from langchain_core.runnables import ( + RunnableConfig, # pyright: ignore[reportMissingTypeStubs] +) +from langgraph.graph import START, StateGraph # pyright: ignore[reportMissingTypeStubs] +from typing_extensions import TypedDict + +from temporalio import workflow +from temporalio.client import Client +from temporalio.contrib.langgraph import LangGraphPlugin +from temporalio.worker import Worker + + +class State(TypedDict): + value: str + + +async def node(state: State, config: RunnableConfig) -> dict[str, str]: + metadata = config.get("metadata") or {} + return {"value": state["value"] + str(metadata.get("my_key", "NOT_FOUND"))} + + +metadata_graph: StateGraph[State, None, State, State] = StateGraph(State) +metadata_graph.add_node( + "node", + node, + metadata={ + "execute_in": "activity", + "start_to_close_timeout": timedelta(seconds=10), + "my_key": "my_value", + }, +) +metadata_graph.add_edge(START, "node") + + +@workflow.defn +class NodeMetadataWorkflow: + def __init__(self) -> None: + self.app = metadata_graph.compile() + + @workflow.run + async def run(self, input: str) -> Any: + return await self.app.ainvoke({"value": input}) + + +async def test_node_metadata_readable_in_node(client: Client): + task_queue = f"my-graph-{uuid4()}" + + async with Worker( + client, + task_queue=task_queue, + workflows=[NodeMetadataWorkflow], + plugins=[LangGraphPlugin(graphs={"my-graph": metadata_graph})], + ): + result = await client.execute_workflow( + NodeMetadataWorkflow.run, + "prefix-", + id=f"test-workflow-{uuid4()}", + task_queue=task_queue, + ) + + assert result == {"value": "prefix-my_value"} diff --git a/tests/contrib/langgraph/test_plugin_validation.py b/tests/contrib/langgraph/test_plugin_validation.py new file mode 100644 index 000000000..5b66c2241 --- /dev/null +++ b/tests/contrib/langgraph/test_plugin_validation.py @@ -0,0 +1,89 @@ +"""Tests for LangGraphPlugin validation.""" + +from __future__ import annotations + +from typing import Any +from uuid import uuid4 + +from langchain_core.runnables import RunnableLambda +from langgraph.func import task # pyright: ignore[reportMissingTypeStubs] +from langgraph.graph import START, StateGraph # pyright: ignore[reportMissingTypeStubs] +from langgraph.types import RetryPolicy # pyright: ignore[reportMissingTypeStubs] +from pytest import raises +from typing_extensions import TypedDict + +from temporalio.contrib.langgraph import LangGraphPlugin + + +class State(TypedDict): + value: str + + +async def async_node(state: State) -> dict[str, str]: # pyright: ignore[reportUnusedParameter] + return {"value": "done"} + + +def sync_node(state: State) -> dict[str, str]: # pyright: ignore[reportUnusedParameter] + return {"value": "done"} + + +def test_non_runnable_callable_node_raises() -> None: + """Nodes whose runnable isn't a RunnableCallable can't be wrapped as activities.""" + g = StateGraph(State) + g.add_node("node", RunnableLambda(sync_node)) + g.add_edge(START, "node") + + with raises(ValueError, match="must be a RunnableCallable"): + LangGraphPlugin(graphs={f"validation-{uuid4()}": g}) + + +def test_invalid_execute_in_raises() -> None: + g = StateGraph(State) + g.add_node("node", async_node, metadata={"execute_in": "bogus"}) + g.add_edge(START, "node") + + with raises(ValueError, match="Invalid execute_in value"): + LangGraphPlugin(graphs={f"validation-{uuid4()}": g}) + + +def test_graph_node_missing_execute_in_raises() -> None: + g = StateGraph(State) + g.add_node("node", async_node) + g.add_edge(START, "node") + + with raises(ValueError, match="missing required 'execute_in'"): + LangGraphPlugin(graphs={f"validation-{uuid4()}": g}) + + +def test_functional_task_missing_execute_in_raises() -> None: + @task + def my_task(x: int) -> int: + return x + 1 + + with raises(ValueError, match="missing required 'execute_in'"): + LangGraphPlugin(tasks=[my_task]) + + +def test_execute_in_in_default_activity_options_raises() -> None: + with raises(ValueError, match="cannot be set in default_activity_options"): + LangGraphPlugin(default_activity_options={"execute_in": "activity"}) + + +def test_node_retry_policy_raises() -> None: + g = StateGraph(State) + g.add_node("node", async_node, retry_policy=RetryPolicy(max_attempts=3)) + g.add_edge(START, "node") + + with raises(ValueError, match="retry_policy"): + LangGraphPlugin(graphs={f"validation-{uuid4()}": g}) + + +def test_task_retry_policy_raises() -> None: + decorator: Any = task(retry_policy=RetryPolicy(max_attempts=3)) + + @decorator + def my_task(x: int) -> int: + return x + 1 + + with raises(ValueError, match="retry_policy"): + LangGraphPlugin(tasks=[my_task]) diff --git a/tests/contrib/langgraph/test_replay.py b/tests/contrib/langgraph/test_replay.py new file mode 100644 index 000000000..f5d1a8e92 --- /dev/null +++ b/tests/contrib/langgraph/test_replay.py @@ -0,0 +1,93 @@ +import sys +from datetime import timedelta +from uuid import uuid4 + +import pytest +from langgraph.graph import START, StateGraph # pyright: ignore[reportMissingTypeStubs] + +from temporalio.client import Client +from temporalio.contrib.langgraph import LangGraphPlugin +from temporalio.worker import Replayer, Worker +from tests.contrib.langgraph.test_interrupt import ( + InterruptWorkflow, +) +from tests.contrib.langgraph.test_interrupt import ( + State as InterruptState, +) +from tests.contrib.langgraph.test_interrupt import ( + node as interrupt_node, +) +from tests.contrib.langgraph.test_two_nodes import ( + State, + TwoNodesWorkflow, + node_a, + node_b, +) + + +async def test_replay(client: Client): + g = StateGraph(State) + g.add_node("node_a", node_a, metadata={"execute_in": "activity"}) + g.add_node("node_b", node_b, metadata={"execute_in": "activity"}) + g.add_edge(START, "node_a") + g.add_edge("node_a", "node_b") + + task_queue = f"my-graph-{uuid4()}" + plugin = LangGraphPlugin( + graphs={"my-graph": g}, + default_activity_options={"start_to_close_timeout": timedelta(seconds=10)}, + ) + + async with Worker( + client, + task_queue=task_queue, + workflows=[TwoNodesWorkflow], + plugins=[plugin], + ): + handle = await client.start_workflow( + TwoNodesWorkflow.run, + "", + id=f"test-workflow-{uuid4()}", + task_queue=task_queue, + ) + await handle.result() + + await Replayer( + workflows=[TwoNodesWorkflow], + plugins=[plugin], + ).replay_workflow(await handle.fetch_history()) + + +@pytest.mark.skipif( + sys.version_info < (3, 11), + reason="langgraph.types.interrupt() requires Python >= 3.11 for async context propagation", +) +async def test_replay_interrupt(client: Client): + g = StateGraph(InterruptState) + g.add_node("node", interrupt_node, metadata={"execute_in": "activity"}) + g.add_edge(START, "node") + + task_queue = f"interrupt-replay-{uuid4()}" + plugin = LangGraphPlugin( + graphs={"my-graph": g}, + default_activity_options={"start_to_close_timeout": timedelta(seconds=10)}, + ) + + async with Worker( + client, + task_queue=task_queue, + workflows=[InterruptWorkflow], + plugins=[plugin], + ): + handle = await client.start_workflow( + InterruptWorkflow.run, + "", + id=f"test-interrupt-replay-{uuid4()}", + task_queue=task_queue, + ) + await handle.result() + + await Replayer( + workflows=[InterruptWorkflow], + plugins=[plugin], + ).replay_workflow(await handle.fetch_history()) diff --git a/tests/contrib/langgraph/test_send.py b/tests/contrib/langgraph/test_send.py new file mode 100644 index 000000000..6576c65b3 --- /dev/null +++ b/tests/contrib/langgraph/test_send.py @@ -0,0 +1,76 @@ +import operator +from datetime import timedelta +from typing import Annotated, Any +from uuid import uuid4 + +from langgraph.graph import ( # pyright: ignore[reportMissingTypeStubs] + END, + START, + StateGraph, +) +from langgraph.types import Send +from typing_extensions import TypedDict + +from temporalio import workflow +from temporalio.client import Client +from temporalio.contrib.langgraph import LangGraphPlugin, graph +from temporalio.worker import Worker + + +class State(TypedDict): + items: list[str] + results: Annotated[list[str], operator.add] + + +class WorkerState(TypedDict): + item: str + + +def worker(state: WorkerState) -> dict[str, list[str]]: + return {"results": [state["item"].upper()]} + + +async def fan_out(state: State) -> list[Send]: + return [Send("worker", {"item": item}) for item in state["items"]] + + +@workflow.defn +class SendWorkflow: + def __init__(self) -> None: + self.app = graph("my-graph").compile() + + @workflow.run + async def run(self, items: list[str]) -> Any: + return await self.app.ainvoke({"items": items, "results": []}) + + +async def test_send(client: Client): + g = StateGraph(State) + g.add_node("worker", worker, metadata={"execute_in": "activity"}) + g.add_conditional_edges(START, fan_out, ["worker"]) + g.add_edge("worker", END) + + task_queue = f"send-{uuid4()}" + + async with Worker( + client, + task_queue=task_queue, + workflows=[SendWorkflow], + plugins=[ + LangGraphPlugin( + graphs={"my-graph": g}, + default_activity_options={ + "start_to_close_timeout": timedelta(seconds=10) + }, + ) + ], + ): + result = await client.execute_workflow( + SendWorkflow.run, + ["a", "b", "c"], + id=f"test-send-{uuid4()}", + task_queue=task_queue, + ) + + assert result["items"] == ["a", "b", "c"] + assert sorted(result["results"]) == ["A", "B", "C"] diff --git a/tests/contrib/langgraph/test_streaming.py b/tests/contrib/langgraph/test_streaming.py new file mode 100644 index 000000000..f47feffee --- /dev/null +++ b/tests/contrib/langgraph/test_streaming.py @@ -0,0 +1,68 @@ +from datetime import timedelta +from typing import Any +from uuid import uuid4 + +from langgraph.graph import START, StateGraph # pyright: ignore[reportMissingTypeStubs] +from typing_extensions import TypedDict + +from temporalio import workflow +from temporalio.client import Client +from temporalio.contrib.langgraph import LangGraphPlugin, graph +from temporalio.worker import Worker + + +class State(TypedDict): + value: str + + +async def node_a(state: State) -> dict[str, str]: + return {"value": state["value"] + "a"} + + +async def node_b(state: State) -> dict[str, str]: + return {"value": state["value"] + "b"} + + +@workflow.defn +class StreamingWorkflow: + def __init__(self) -> None: + self.app = graph("streaming").compile() + + @workflow.run + async def run(self, input: str) -> Any: + chunks = [] + async for chunk in self.app.astream({"value": input}): + chunks.append(chunk) + return chunks + + +async def test_streaming(client: Client): + g = StateGraph(State) + g.add_node("node_a", node_a, metadata={"execute_in": "activity"}) + g.add_node("node_b", node_b, metadata={"execute_in": "activity"}) + g.add_edge(START, "node_a") + g.add_edge("node_a", "node_b") + + task_queue = f"streaming-{uuid4()}" + + async with Worker( + client, + task_queue=task_queue, + workflows=[StreamingWorkflow], + plugins=[ + LangGraphPlugin( + graphs={"streaming": g}, + default_activity_options={ + "start_to_close_timeout": timedelta(seconds=10) + }, + ) + ], + ): + chunks = await client.execute_workflow( + StreamingWorkflow.run, + "", + id=f"test-streaming-{uuid4()}", + task_queue=task_queue, + ) + + assert chunks == [{"node_a": {"value": "a"}}, {"node_b": {"value": "ab"}}] diff --git a/tests/contrib/langgraph/test_subgraph_activity.py b/tests/contrib/langgraph/test_subgraph_activity.py new file mode 100644 index 000000000..76600fa57 --- /dev/null +++ b/tests/contrib/langgraph/test_subgraph_activity.py @@ -0,0 +1,67 @@ +from datetime import timedelta +from typing import Any +from uuid import uuid4 + +from langgraph.graph import START, StateGraph # pyright: ignore[reportMissingTypeStubs] +from typing_extensions import TypedDict + +from temporalio import workflow +from temporalio.client import Client +from temporalio.contrib.langgraph import LangGraphPlugin, graph +from temporalio.worker import Worker + + +class State(TypedDict): + value: str + + +async def child_node(state: State) -> dict[str, str]: # pyright: ignore[reportUnusedParameter] + return {"value": "child"} + + +async def parent_node(state: State) -> dict[str, str]: + child: StateGraph[State, None, State, State] = StateGraph(State) + child.add_node("child_node", child_node) + child.add_edge(START, "child_node") + + return await child.compile().ainvoke(state) + + +@workflow.defn +class ActivitySubgraphWorkflow: + def __init__(self) -> None: + self.app = graph("parent").compile() + + @workflow.run + async def run(self, input: str) -> Any: + return await self.app.ainvoke({"value": input}) + + +async def test_activity_subgraph(client: Client): + parent = StateGraph(State) + parent.add_node("parent_node", parent_node, metadata={"execute_in": "activity"}) + parent.add_edge(START, "parent_node") + + task_queue = f"subgraph-{uuid4()}" + + async with Worker( + client, + task_queue=task_queue, + workflows=[ActivitySubgraphWorkflow], + plugins=[ + LangGraphPlugin( + graphs={"parent": parent}, + default_activity_options={ + "start_to_close_timeout": timedelta(seconds=10) + }, + ) + ], + ): + result = await client.execute_workflow( + ActivitySubgraphWorkflow.run, + "", + id=f"test-workflow-{uuid4()}", + task_queue=task_queue, + ) + + assert result == {"value": "child"} diff --git a/tests/contrib/langgraph/test_subgraph_workflow.py b/tests/contrib/langgraph/test_subgraph_workflow.py new file mode 100644 index 000000000..a3b3741b5 --- /dev/null +++ b/tests/contrib/langgraph/test_subgraph_workflow.py @@ -0,0 +1,67 @@ +from datetime import timedelta +from typing import Any +from uuid import uuid4 + +from langgraph.graph import START, StateGraph # pyright: ignore[reportMissingTypeStubs] +from typing_extensions import TypedDict + +from temporalio import workflow +from temporalio.client import Client +from temporalio.contrib.langgraph import LangGraphPlugin, graph +from temporalio.worker import Worker + + +class State(TypedDict): + value: str + + +async def child_node(state: State) -> dict[str, str]: # pyright: ignore[reportUnusedParameter] + return {"value": "child"} + + +async def parent_node(state: State) -> dict[str, str]: + return await graph("child").compile().ainvoke(state) + + +@workflow.defn +class WorkflowSubgraphWorkflow: + def __init__(self) -> None: + self.app = graph("parent").compile() + + @workflow.run + async def run(self, input: str) -> Any: + return await self.app.ainvoke({"value": input}) + + +async def test_workflow_subgraph(client: Client): + child = StateGraph(State) + child.add_node( + "child_node", + child_node, + metadata={ + "execute_in": "activity", + "start_to_close_timeout": timedelta(seconds=10), + }, + ) + child.add_edge(START, "child_node") + + parent = StateGraph(State) + parent.add_node("parent_node", parent_node, metadata={"execute_in": "workflow"}) + parent.add_edge(START, "parent_node") + + task_queue = f"subgraph-{uuid4()}" + + async with Worker( + client, + task_queue=task_queue, + workflows=[WorkflowSubgraphWorkflow], + plugins=[LangGraphPlugin(graphs={"parent": parent, "child": child})], + ): + result = await client.execute_workflow( + WorkflowSubgraphWorkflow.run, + "", + id=f"test-workflow-{uuid4()}", + task_queue=task_queue, + ) + + assert result == {"value": "child"} diff --git a/tests/contrib/langgraph/test_sync_node.py b/tests/contrib/langgraph/test_sync_node.py new file mode 100644 index 000000000..92ec1beed --- /dev/null +++ b/tests/contrib/langgraph/test_sync_node.py @@ -0,0 +1,59 @@ +from datetime import timedelta +from typing import Any +from uuid import uuid4 + +from langgraph.graph import START, StateGraph # pyright: ignore[reportMissingTypeStubs] +from typing_extensions import TypedDict + +from temporalio import workflow +from temporalio.client import Client +from temporalio.contrib.langgraph import LangGraphPlugin, graph +from temporalio.worker import Worker + + +class State(TypedDict): + value: str + + +def sync_node(state: State) -> dict[str, str]: + return {"value": state["value"] + "!"} + + +@workflow.defn +class SyncNodeWorkflow: + def __init__(self) -> None: + self.app = graph("my-graph").compile() + + @workflow.run + async def run(self, input: str) -> Any: + return await self.app.ainvoke({"value": input}) + + +async def test_sync_node(client: Client): + g = StateGraph(State) + g.add_node("sync_node", sync_node, metadata={"execute_in": "activity"}) + g.add_edge(START, "sync_node") + + task_queue = f"sync-node-{uuid4()}" + + async with Worker( + client, + task_queue=task_queue, + workflows=[SyncNodeWorkflow], + plugins=[ + LangGraphPlugin( + graphs={"my-graph": g}, + default_activity_options={ + "start_to_close_timeout": timedelta(seconds=10) + }, + ) + ], + ): + result = await client.execute_workflow( + SyncNodeWorkflow.run, + "hello", + id=f"test-sync-node-{uuid4()}", + task_queue=task_queue, + ) + + assert result == {"value": "hello!"} diff --git a/tests/contrib/langgraph/test_sync_task.py b/tests/contrib/langgraph/test_sync_task.py new file mode 100644 index 000000000..fa820e522 --- /dev/null +++ b/tests/contrib/langgraph/test_sync_task.py @@ -0,0 +1,69 @@ +import sys +from datetime import timedelta +from typing import Any +from uuid import uuid4 + +import pytest + +pytestmark = pytest.mark.skipif( + sys.version_info < (3, 11), + reason="LangGraph Functional API requires Python >= 3.11 for async context propagation", +) +from langgraph.func import ( # pyright: ignore[reportMissingTypeStubs] + entrypoint as lg_entrypoint, +) +from langgraph.func import task # pyright: ignore[reportMissingTypeStubs] + +from temporalio import workflow +from temporalio.client import Client +from temporalio.contrib.langgraph import LangGraphPlugin, entrypoint +from temporalio.worker import Worker + + +@task +def sync_task(x: int) -> int: + return x + 1 + + +@lg_entrypoint() +async def sync_task_entrypoint(value: int) -> dict[str, int]: + result = await sync_task(value) + return {"result": result} + + +@workflow.defn +class SyncTaskWorkflow: + def __init__(self) -> None: + self.app = entrypoint("sync-task") + + @workflow.run + async def run(self, input: int) -> Any: + return await self.app.ainvoke(input) + + +async def test_sync_task(client: Client): + task_queue = f"sync-task-{uuid4()}" + + async with Worker( + client, + task_queue=task_queue, + workflows=[SyncTaskWorkflow], + plugins=[ + LangGraphPlugin( + entrypoints={"sync-task": sync_task_entrypoint}, + tasks=[sync_task], + activity_options={"sync_task": {"execute_in": "activity"}}, + default_activity_options={ + "start_to_close_timeout": timedelta(seconds=10) + }, + ) + ], + ): + result = await client.execute_workflow( + SyncTaskWorkflow.run, + 41, + id=f"test-sync-task-{uuid4()}", + task_queue=task_queue, + ) + + assert result == {"result": 42} diff --git a/tests/contrib/langgraph/test_timeout.py b/tests/contrib/langgraph/test_timeout.py new file mode 100644 index 000000000..12561c146 --- /dev/null +++ b/tests/contrib/langgraph/test_timeout.py @@ -0,0 +1,63 @@ +from asyncio import sleep +from datetime import timedelta +from typing import Any +from uuid import uuid4 + +from langgraph.graph import START, StateGraph # pyright: ignore[reportMissingTypeStubs] +from pytest import raises +from typing_extensions import TypedDict + +from temporalio import workflow +from temporalio.client import Client, WorkflowFailureError +from temporalio.common import RetryPolicy +from temporalio.contrib.langgraph import LangGraphPlugin, graph +from temporalio.worker import Worker + + +class State(TypedDict): + value: str + + +async def node(state: State) -> dict[str, str]: # pyright: ignore[reportUnusedParameter] + await sleep(1) # 1 second + return {"value": "done"} + + +@workflow.defn +class TimeoutWorkflow: + def __init__(self) -> None: + self.app = graph("my-graph").compile() + + @workflow.run + async def run(self, input: str) -> Any: + return await self.app.ainvoke({"value": input}) + + +async def test_timeout(client: Client): + g = StateGraph(State) + g.add_node("node", node, metadata={"execute_in": "activity"}) + g.add_edge(START, "node") + + task_queue = f"my-graph-{uuid4()}" + + async with Worker( + client, + task_queue=task_queue, + workflows=[TimeoutWorkflow], + plugins=[ + LangGraphPlugin( + graphs={"my-graph": g}, + default_activity_options={ + "start_to_close_timeout": timedelta(milliseconds=100), + "retry_policy": RetryPolicy(maximum_attempts=1), + }, + ) + ], + ): + with raises(WorkflowFailureError): + await client.execute_workflow( + TimeoutWorkflow.run, + "", + id=f"test-workflow-{uuid4()}", + task_queue=task_queue, + ) diff --git a/tests/contrib/langgraph/test_two_nodes.py b/tests/contrib/langgraph/test_two_nodes.py new file mode 100644 index 000000000..6b974d90f --- /dev/null +++ b/tests/contrib/langgraph/test_two_nodes.py @@ -0,0 +1,65 @@ +from datetime import timedelta +from typing import Any +from uuid import uuid4 + +from langgraph.graph import START, StateGraph # pyright: ignore[reportMissingTypeStubs] +from typing_extensions import TypedDict + +from temporalio import workflow +from temporalio.client import Client +from temporalio.contrib.langgraph import LangGraphPlugin, graph +from temporalio.worker import Worker + + +class State(TypedDict): + value: str + + +async def node_a(state: State) -> dict[str, str]: + return {"value": state["value"] + "a"} + + +async def node_b(state: State) -> dict[str, str]: + return {"value": state["value"] + "b"} + + +@workflow.defn +class TwoNodesWorkflow: + def __init__(self) -> None: + self.app = graph("my-graph").compile() + + @workflow.run + async def run(self, input: str) -> Any: + return await self.app.ainvoke({"value": input}) + + +async def test_two_nodes(client: Client): + g = StateGraph(State) + g.add_node("node_a", node_a, metadata={"execute_in": "activity"}) + g.add_node("node_b", node_b, metadata={"execute_in": "activity"}) + g.add_edge(START, "node_a") + g.add_edge("node_a", "node_b") + + task_queue = f"my-graph-{uuid4()}" + + async with Worker( + client, + task_queue=task_queue, + workflows=[TwoNodesWorkflow], + plugins=[ + LangGraphPlugin( + graphs={"my-graph": g}, + default_activity_options={ + "start_to_close_timeout": timedelta(seconds=10) + }, + ) + ], + ): + result = await client.execute_workflow( + TwoNodesWorkflow.run, + "", + id=f"test-workflow-{uuid4()}", + task_queue=task_queue, + ) + + assert result == {"value": "ab"} diff --git a/uv.lock b/uv.lock index bdc25a507..4fba27fc0 100644 --- a/uv.lock +++ b/uv.lock @@ -8,6 +8,13 @@ resolution-markers = [ "python_full_version < '3.11'", ] +[options] +exclude-newer = "2026-04-13T21:30:54.856039Z" +exclude-newer-span = "P1W" + +[options.exclude-newer-package] +openai-agents = false + [[package]] name = "aioboto3" version = "15.5.0" @@ -1812,7 +1819,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/38/3f/9859f655d11901e7b2996c6e3d33e0caa9a1d4572c3bc61ed0faa64b2f4c/greenlet-3.3.2-cp310-cp310-macosx_11_0_universal2.whl", hash = "sha256:9bc885b89709d901859cf95179ec9f6bb67a3d2bb1f0e88456461bd4b7f8fd0d", size = 277747, upload-time = "2026-02-20T20:16:21.325Z" }, { url = "https://files.pythonhosted.org/packages/fb/07/cb284a8b5c6498dbd7cba35d31380bb123d7dceaa7907f606c8ff5993cbf/greenlet-3.3.2-cp310-cp310-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b568183cf65b94919be4438dc28416b234b678c608cafac8874dfeeb2a9bbe13", size = 579202, upload-time = "2026-02-20T20:47:28.955Z" }, { url = "https://files.pythonhosted.org/packages/ed/45/67922992b3a152f726163b19f890a85129a992f39607a2a53155de3448b8/greenlet-3.3.2-cp310-cp310-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:527fec58dc9f90efd594b9b700662ed3fb2493c2122067ac9c740d98080a620e", size = 590620, upload-time = "2026-02-20T20:55:55.581Z" }, - { url = "https://files.pythonhosted.org/packages/03/5f/6e2a7d80c353587751ef3d44bb947f0565ec008a2e0927821c007e96d3a7/greenlet-3.3.2-cp310-cp310-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:508c7f01f1791fbc8e011bd508f6794cb95397fdb198a46cb6635eb5b78d85a7", size = 602132, upload-time = "2026-02-20T21:02:43.261Z" }, { url = "https://files.pythonhosted.org/packages/ad/55/9f1ebb5a825215fadcc0f7d5073f6e79e3007e3282b14b22d6aba7ca6cb8/greenlet-3.3.2-cp310-cp310-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ad0c8917dd42a819fe77e6bdfcb84e3379c0de956469301d9fd36427a1ca501f", size = 591729, upload-time = "2026-02-20T20:20:58.395Z" }, { url = "https://files.pythonhosted.org/packages/24/b4/21f5455773d37f94b866eb3cf5caed88d6cea6dd2c6e1f9c34f463cba3ec/greenlet-3.3.2-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:97245cc10e5515dbc8c3104b2928f7f02b6813002770cfaffaf9a6e0fc2b94ef", size = 1551946, upload-time = "2026-02-20T20:49:31.102Z" }, { url = "https://files.pythonhosted.org/packages/00/68/91f061a926abead128fe1a87f0b453ccf07368666bd59ffa46016627a930/greenlet-3.3.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:8c1fdd7d1b309ff0da81d60a9688a8bd044ac4e18b250320a96fc68d31c209ca", size = 1618494, upload-time = "2026-02-20T20:21:06.541Z" }, @@ -1820,7 +1826,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/f3/47/16400cb42d18d7a6bb46f0626852c1718612e35dcb0dffa16bbaffdf5dd2/greenlet-3.3.2-cp311-cp311-macosx_11_0_universal2.whl", hash = "sha256:c56692189a7d1c7606cb794be0a8381470d95c57ce5be03fb3d0ef57c7853b86", size = 278890, upload-time = "2026-02-20T20:19:39.263Z" }, { url = "https://files.pythonhosted.org/packages/a3/90/42762b77a5b6aa96cd8c0e80612663d39211e8ae8a6cd47c7f1249a66262/greenlet-3.3.2-cp311-cp311-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1ebd458fa8285960f382841da585e02201b53a5ec2bac6b156fc623b5ce4499f", size = 581120, upload-time = "2026-02-20T20:47:30.161Z" }, { url = "https://files.pythonhosted.org/packages/bf/6f/f3d64f4fa0a9c7b5c5b3c810ff1df614540d5aa7d519261b53fba55d4df9/greenlet-3.3.2-cp311-cp311-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:a443358b33c4ec7b05b79a7c8b466f5d275025e750298be7340f8fc63dff2a55", size = 594363, upload-time = "2026-02-20T20:55:56.965Z" }, - { url = "https://files.pythonhosted.org/packages/9c/8b/1430a04657735a3f23116c2e0d5eb10220928846e4537a938a41b350bed6/greenlet-3.3.2-cp311-cp311-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:4375a58e49522698d3e70cc0b801c19433021b5c37686f7ce9c65b0d5c8677d2", size = 605046, upload-time = "2026-02-20T21:02:45.234Z" }, { url = "https://files.pythonhosted.org/packages/72/83/3e06a52aca8128bdd4dcd67e932b809e76a96ab8c232a8b025b2850264c5/greenlet-3.3.2-cp311-cp311-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8e2cd90d413acbf5e77ae41e5d3c9b3ac1d011a756d7284d7f3f2b806bbd6358", size = 594156, upload-time = "2026-02-20T20:20:59.955Z" }, { url = "https://files.pythonhosted.org/packages/70/79/0de5e62b873e08fe3cef7dbe84e5c4bc0e8ed0c7ff131bccb8405cd107c8/greenlet-3.3.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:442b6057453c8cb29b4fb36a2ac689382fc71112273726e2423f7f17dc73bf99", size = 1554649, upload-time = "2026-02-20T20:49:32.293Z" }, { url = "https://files.pythonhosted.org/packages/5a/00/32d30dee8389dc36d42170a9c66217757289e2afb0de59a3565260f38373/greenlet-3.3.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:45abe8eb6339518180d5a7fa47fa01945414d7cca5ecb745346fc6a87d2750be", size = 1619472, upload-time = "2026-02-20T20:21:07.966Z" }, @@ -1829,7 +1834,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/ea/ab/1608e5a7578e62113506740b88066bf09888322a311cff602105e619bd87/greenlet-3.3.2-cp312-cp312-macosx_11_0_universal2.whl", hash = "sha256:ac8d61d4343b799d1e526db579833d72f23759c71e07181c2d2944e429eb09cd", size = 280358, upload-time = "2026-02-20T20:17:43.971Z" }, { url = "https://files.pythonhosted.org/packages/a5/23/0eae412a4ade4e6623ff7626e38998cb9b11e9ff1ebacaa021e4e108ec15/greenlet-3.3.2-cp312-cp312-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3ceec72030dae6ac0c8ed7591b96b70410a8be370b6a477b1dbc072856ad02bd", size = 601217, upload-time = "2026-02-20T20:47:31.462Z" }, { url = "https://files.pythonhosted.org/packages/f8/16/5b1678a9c07098ecb9ab2dd159fafaf12e963293e61ee8d10ecb55273e5e/greenlet-3.3.2-cp312-cp312-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:a2a5be83a45ce6188c045bcc44b0ee037d6a518978de9a5d97438548b953a1ac", size = 611792, upload-time = "2026-02-20T20:55:58.423Z" }, - { url = "https://files.pythonhosted.org/packages/5c/c5/cc09412a29e43406eba18d61c70baa936e299bc27e074e2be3806ed29098/greenlet-3.3.2-cp312-cp312-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:ae9e21c84035c490506c17002f5c8ab25f980205c3e61ddb3a2a2a2e6c411fcb", size = 626250, upload-time = "2026-02-20T21:02:46.596Z" }, { url = "https://files.pythonhosted.org/packages/50/1f/5155f55bd71cabd03765a4aac9ac446be129895271f73872c36ebd4b04b6/greenlet-3.3.2-cp312-cp312-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:43e99d1749147ac21dde49b99c9abffcbc1e2d55c67501465ef0930d6e78e070", size = 613875, upload-time = "2026-02-20T20:21:01.102Z" }, { url = "https://files.pythonhosted.org/packages/fc/dd/845f249c3fcd69e32df80cdab059b4be8b766ef5830a3d0aa9d6cad55beb/greenlet-3.3.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:4c956a19350e2c37f2c48b336a3afb4bff120b36076d9d7fb68cb44e05d95b79", size = 1571467, upload-time = "2026-02-20T20:49:33.495Z" }, { url = "https://files.pythonhosted.org/packages/2a/50/2649fe21fcc2b56659a452868e695634722a6655ba245d9f77f5656010bf/greenlet-3.3.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:6c6f8ba97d17a1e7d664151284cb3315fc5f8353e75221ed4324f84eb162b395", size = 1640001, upload-time = "2026-02-20T20:21:09.154Z" }, @@ -1838,7 +1842,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/ac/48/f8b875fa7dea7dd9b33245e37f065af59df6a25af2f9561efa8d822fde51/greenlet-3.3.2-cp313-cp313-macosx_11_0_universal2.whl", hash = "sha256:aa6ac98bdfd716a749b84d4034486863fd81c3abde9aa3cf8eff9127981a4ae4", size = 279120, upload-time = "2026-02-20T20:19:01.9Z" }, { url = "https://files.pythonhosted.org/packages/49/8d/9771d03e7a8b1ee456511961e1b97a6d77ae1dea4a34a5b98eee706689d3/greenlet-3.3.2-cp313-cp313-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ab0c7e7901a00bc0a7284907273dc165b32e0d109a6713babd04471327ff7986", size = 603238, upload-time = "2026-02-20T20:47:32.873Z" }, { url = "https://files.pythonhosted.org/packages/59/0e/4223c2bbb63cd5c97f28ffb2a8aee71bdfb30b323c35d409450f51b91e3e/greenlet-3.3.2-cp313-cp313-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:d248d8c23c67d2291ffd47af766e2a3aa9fa1c6703155c099feb11f526c63a92", size = 614219, upload-time = "2026-02-20T20:55:59.817Z" }, - { url = "https://files.pythonhosted.org/packages/94/2b/4d012a69759ac9d77210b8bfb128bc621125f5b20fc398bce3940d036b1c/greenlet-3.3.2-cp313-cp313-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:ccd21bb86944ca9be6d967cf7691e658e43417782bce90b5d2faeda0ff78a7dd", size = 628268, upload-time = "2026-02-20T21:02:48.024Z" }, { url = "https://files.pythonhosted.org/packages/7a/34/259b28ea7a2a0c904b11cd36c79b8cef8019b26ee5dbe24e73b469dea347/greenlet-3.3.2-cp313-cp313-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b6997d360a4e6a4e936c0f9625b1c20416b8a0ea18a8e19cabbefc712e7397ab", size = 616774, upload-time = "2026-02-20T20:21:02.454Z" }, { url = "https://files.pythonhosted.org/packages/0a/03/996c2d1689d486a6e199cb0f1cf9e4aa940c500e01bdf201299d7d61fa69/greenlet-3.3.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:64970c33a50551c7c50491671265d8954046cb6e8e2999aacdd60e439b70418a", size = 1571277, upload-time = "2026-02-20T20:49:34.795Z" }, { url = "https://files.pythonhosted.org/packages/d9/c4/2570fc07f34a39f2caf0bf9f24b0a1a0a47bc2e8e465b2c2424821389dfc/greenlet-3.3.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:1a9172f5bf6bd88e6ba5a84e0a68afeac9dc7b6b412b245dd64f52d83c81e55b", size = 1640455, upload-time = "2026-02-20T20:21:10.261Z" }, @@ -1847,7 +1850,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/3f/ae/8bffcbd373b57a5992cd077cbe8858fff39110480a9d50697091faea6f39/greenlet-3.3.2-cp314-cp314-macosx_11_0_universal2.whl", hash = "sha256:8d1658d7291f9859beed69a776c10822a0a799bc4bfe1bd4272bb60e62507dab", size = 279650, upload-time = "2026-02-20T20:18:00.783Z" }, { url = "https://files.pythonhosted.org/packages/d1/c0/45f93f348fa49abf32ac8439938726c480bd96b2a3c6f4d949ec0124b69f/greenlet-3.3.2-cp314-cp314-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:18cb1b7337bca281915b3c5d5ae19f4e76d35e1df80f4ad3c1a7be91fadf1082", size = 650295, upload-time = "2026-02-20T20:47:34.036Z" }, { url = "https://files.pythonhosted.org/packages/b3/de/dd7589b3f2b8372069ab3e4763ea5329940fc7ad9dcd3e272a37516d7c9b/greenlet-3.3.2-cp314-cp314-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:c2e47408e8ce1c6f1ceea0dffcdf6ebb85cc09e55c7af407c99f1112016e45e9", size = 662163, upload-time = "2026-02-20T20:56:01.295Z" }, - { url = "https://files.pythonhosted.org/packages/cd/ac/85804f74f1ccea31ba518dcc8ee6f14c79f73fe36fa1beba38930806df09/greenlet-3.3.2-cp314-cp314-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:e3cb43ce200f59483eb82949bf1835a99cf43d7571e900d7c8d5c62cdf25d2f9", size = 675371, upload-time = "2026-02-20T21:02:49.664Z" }, { url = "https://files.pythonhosted.org/packages/d2/d8/09bfa816572a4d83bccd6750df1926f79158b1c36c5f73786e26dbe4ee38/greenlet-3.3.2-cp314-cp314-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:63d10328839d1973e5ba35e98cccbca71b232b14051fd957b6f8b6e8e80d0506", size = 664160, upload-time = "2026-02-20T20:21:04.015Z" }, { url = "https://files.pythonhosted.org/packages/48/cf/56832f0c8255d27f6c35d41b5ec91168d74ec721d85f01a12131eec6b93c/greenlet-3.3.2-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:8e4ab3cfb02993c8cc248ea73d7dae6cec0253e9afa311c9b37e603ca9fad2ce", size = 1619181, upload-time = "2026-02-20T20:49:36.052Z" }, { url = "https://files.pythonhosted.org/packages/0a/23/b90b60a4aabb4cec0796e55f25ffbfb579a907c3898cd2905c8918acaa16/greenlet-3.3.2-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:94ad81f0fd3c0c0681a018a976e5c2bd2ca2d9d94895f23e7bb1af4e8af4e2d5", size = 1687713, upload-time = "2026-02-20T20:21:11.684Z" }, @@ -1856,7 +1858,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/98/6d/8f2ef704e614bcf58ed43cfb8d87afa1c285e98194ab2cfad351bf04f81e/greenlet-3.3.2-cp314-cp314t-macosx_11_0_universal2.whl", hash = "sha256:e26e72bec7ab387ac80caa7496e0f908ff954f31065b0ffc1f8ecb1338b11b54", size = 286617, upload-time = "2026-02-20T20:19:29.856Z" }, { url = "https://files.pythonhosted.org/packages/5e/0d/93894161d307c6ea237a43988f27eba0947b360b99ac5239ad3fe09f0b47/greenlet-3.3.2-cp314-cp314t-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8b466dff7a4ffda6ca975979bab80bdadde979e29fc947ac3be4451428d8b0e4", size = 655189, upload-time = "2026-02-20T20:47:35.742Z" }, { url = "https://files.pythonhosted.org/packages/f5/2c/d2d506ebd8abcb57386ec4f7ba20f4030cbe56eae541bc6fd6ef399c0b41/greenlet-3.3.2-cp314-cp314t-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:b8bddc5b73c9720bea487b3bffdb1840fe4e3656fba3bd40aa1489e9f37877ff", size = 658225, upload-time = "2026-02-20T20:56:02.527Z" }, - { url = "https://files.pythonhosted.org/packages/d1/67/8197b7e7e602150938049d8e7f30de1660cfb87e4c8ee349b42b67bdb2e1/greenlet-3.3.2-cp314-cp314t-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:59b3e2c40f6706b05a9cd299c836c6aa2378cabe25d021acd80f13abf81181cf", size = 666581, upload-time = "2026-02-20T21:02:51.526Z" }, { url = "https://files.pythonhosted.org/packages/8e/30/3a09155fbf728673a1dea713572d2d31159f824a37c22da82127056c44e4/greenlet-3.3.2-cp314-cp314t-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b26b0f4428b871a751968285a1ac9648944cea09807177ac639b030bddebcea4", size = 657907, upload-time = "2026-02-20T20:21:05.259Z" }, { url = "https://files.pythonhosted.org/packages/f3/fd/d05a4b7acd0154ed758797f0a43b4c0962a843bedfe980115e842c5b2d08/greenlet-3.3.2-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:1fb39a11ee2e4d94be9a76671482be9398560955c9e568550de0224e41104727", size = 1618857, upload-time = "2026-02-20T20:49:37.309Z" }, { url = "https://files.pythonhosted.org/packages/6f/e1/50ee92a5db521de8f35075b5eff060dd43d39ebd46c2181a2042f7070385/greenlet-3.3.2-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:20154044d9085151bc309e7689d6f7ba10027f8f5a8c0676ad398b951913d89e", size = 1680010, upload-time = "2026-02-20T20:21:13.427Z" }, @@ -2474,6 +2475,81 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/81/db/e655086b7f3a705df045bf0933bdd9c2f79bb3c97bfef1384598bb79a217/keyring-25.7.0-py3-none-any.whl", hash = "sha256:be4a0b195f149690c166e850609a477c532ddbfbaed96a404d4e43f8d5e2689f", size = 39160, upload-time = "2025-11-16T16:26:08.402Z" }, ] +[[package]] +name = "langchain-core" +version = "1.2.28" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "jsonpatch" }, + { name = "langsmith" }, + { name = "packaging" }, + { name = "pydantic" }, + { name = "pyyaml" }, + { name = "tenacity" }, + { name = "typing-extensions" }, + { name = "uuid-utils" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/f8/a4/317a1a3ac1df33a64adb3670bf88bbe3b3d5baa274db6863a979db472897/langchain_core-1.2.28.tar.gz", hash = "sha256:271a3d8bd618f795fdeba112b0753980457fc90537c46a0c11998516a74dc2cb", size = 846119, upload-time = "2026-04-08T18:19:34.867Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/a8/92/32f785f077c7e898da97064f113c73fbd9ad55d1e2169cf3a391b183dedb/langchain_core-1.2.28-py3-none-any.whl", hash = "sha256:80764232581eaf8057bcefa71dbf8adc1f6a28d257ebd8b95ba9b8b452e8c6ac", size = 508727, upload-time = "2026-04-08T18:19:32.823Z" }, +] + +[[package]] +name = "langgraph" +version = "1.1.6" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "langchain-core" }, + { name = "langgraph-checkpoint" }, + { name = "langgraph-prebuilt" }, + { name = "langgraph-sdk" }, + { name = "pydantic" }, + { name = "xxhash" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/5c/e5/d3f72ead3c7f15769d5a9c07e373628f1fbaf6cbe7735694d7085859acf6/langgraph-1.1.6.tar.gz", hash = "sha256:1783f764b08a607e9f288dbcf6da61caeb0dd40b337e5c9fb8b412341fbc0b60", size = 549634, upload-time = "2026-04-03T19:01:32.561Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/71/e6/b36ecdb3ff4ba9a290708d514bae89ebbe2f554b6abbe4642acf3fddbe51/langgraph-1.1.6-py3-none-any.whl", hash = "sha256:fdbf5f54fa5a5a4c4b09b7b5e537f1b2fa283d2f0f610d3457ddeecb479458b9", size = 169755, upload-time = "2026-04-03T19:01:30.686Z" }, +] + +[[package]] +name = "langgraph-checkpoint" +version = "4.0.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "langchain-core" }, + { name = "ormsgpack" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/b1/44/a8df45d1e8b4637e29789fa8bae1db022c953cc7ac80093cfc52e923547e/langgraph_checkpoint-4.0.1.tar.gz", hash = "sha256:b433123735df11ade28829e40ce25b9be614930cd50245ff2af60629234befd9", size = 158135, upload-time = "2026-02-27T21:06:16.092Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/65/4c/09a4a0c42f5d2fc38d6c4d67884788eff7fd2cfdf367fdf7033de908b4c0/langgraph_checkpoint-4.0.1-py3-none-any.whl", hash = "sha256:e3adcd7a0e0166f3b48b8cf508ce0ea366e7420b5a73aa81289888727769b034", size = 50453, upload-time = "2026-02-27T21:06:14.293Z" }, +] + +[[package]] +name = "langgraph-prebuilt" +version = "1.0.9" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "langchain-core" }, + { name = "langgraph-checkpoint" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/99/4c/06dac899f4945bedb0c3a1583c19484c2cc894114ea30d9a538dd270086e/langgraph_prebuilt-1.0.9.tar.gz", hash = "sha256:93de7512e9caade4b77ead92428f6215c521fdb71b8ffda8cd55f0ad814e64de", size = 165850, upload-time = "2026-04-03T14:06:37.721Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/1d/a2/8368ac187b75e7f9d938ca075d34f116683f5cfc48d924029ee79aea147b/langgraph_prebuilt-1.0.9-py3-none-any.whl", hash = "sha256:776c8e3154a5aef5ad0e5bf3f263f2dcaab3983786cc20014b7f955d99d2d1b2", size = 35958, upload-time = "2026-04-03T14:06:36.58Z" }, +] + +[[package]] +name = "langgraph-sdk" +version = "0.3.13" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "httpx" }, + { name = "orjson" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/0e/db/77a45127dddcfea5e4256ba916182903e4c31dc4cfca305b8c386f0a9e53/langgraph_sdk-0.3.13.tar.gz", hash = "sha256:419ca5663eec3cec192ad194ac0647c0c826866b446073eb40f384f950986cd5", size = 196360, upload-time = "2026-04-07T20:34:18.766Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/fe/ef/64d64e9f8eea47ce7b939aa6da6863b674c8d418647813c20111645fcc62/langgraph_sdk-0.3.13-py3-none-any.whl", hash = "sha256:aee09e345c90775f6de9d6f4c7b847cfc652e49055c27a2aed0d981af2af3bd0", size = 96668, upload-time = "2026-04-07T20:34:17.866Z" }, +] + [[package]] name = "langsmith" version = "0.7.26" @@ -3682,6 +3758,62 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/c0/d1/facb5b5051fabb0ef9d26c6544d87ef19a939a9a001198655d0d891062dd/orjson-3.11.8-cp314-cp314-win_arm64.whl", hash = "sha256:6ccdea2c213cf9f3d9490cbd5d427693c870753df41e6cb375bd79bcbafc8817", size = 127330, upload-time = "2026-03-31T16:16:25.496Z" }, ] +[[package]] +name = "ormsgpack" +version = "1.12.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/12/0c/f1761e21486942ab9bb6feaebc610fa074f7c5e496e6962dea5873348077/ormsgpack-1.12.2.tar.gz", hash = "sha256:944a2233640273bee67521795a73cf1e959538e0dfb7ac635505010455e53b33", size = 39031, upload-time = "2026-01-18T20:55:28.023Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/93/fa/a91f70829ebccf6387c4946e0a1a109f6ba0d6a28d65f628bedfad94b890/ormsgpack-1.12.2-cp310-cp310-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:c1429217f8f4d7fcb053523bbbac6bed5e981af0b85ba616e6df7cce53c19657", size = 378262, upload-time = "2026-01-18T20:55:22.284Z" }, + { url = "https://files.pythonhosted.org/packages/5f/62/3698a9a0c487252b5c6a91926e5654e79e665708ea61f67a8bdeceb022bf/ormsgpack-1.12.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5f13034dc6c84a6280c6c33db7ac420253852ea233fc3ee27c8875f8dd651163", size = 203034, upload-time = "2026-01-18T20:55:53.324Z" }, + { url = "https://files.pythonhosted.org/packages/66/3a/f716f64edc4aec2744e817660b317e2f9bb8de372338a95a96198efa1ac1/ormsgpack-1.12.2-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:59f5da97000c12bc2d50e988bdc8576b21f6ab4e608489879d35b2c07a8ab51a", size = 210538, upload-time = "2026-01-18T20:55:20.097Z" }, + { url = "https://files.pythonhosted.org/packages/72/30/a436be9ce27d693d4e19fa94900028067133779f09fc45776db3f689c822/ormsgpack-1.12.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9e4459c3f27066beadb2b81ea48a076a417aafffff7df1d3c11c519190ed44f2", size = 212401, upload-time = "2026-01-18T20:55:46.447Z" }, + { url = "https://files.pythonhosted.org/packages/10/c5/cde98300fd33fee84ca71de4751b19aeeca675f0cf3c0ec4b043f40f3b76/ormsgpack-1.12.2-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:7a1c460655d7288407ffa09065e322a7231997c0d62ce914bf3a96ad2dc6dedd", size = 387080, upload-time = "2026-01-18T20:56:00.884Z" }, + { url = "https://files.pythonhosted.org/packages/6a/31/30bf445ef827546747c10889dd254b3d84f92b591300efe4979d792f4c41/ormsgpack-1.12.2-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:458e4568be13d311ef7d8877275e7ccbe06c0e01b39baaac874caaa0f46d826c", size = 482346, upload-time = "2026-01-18T20:55:39.831Z" }, + { url = "https://files.pythonhosted.org/packages/2e/f5/e1745ddf4fa246c921b5ca253636c4c700ff768d78032f79171289159f6e/ormsgpack-1.12.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:8cde5eaa6c6cbc8622db71e4a23de56828e3d876aeb6460ffbcb5b8aff91093b", size = 425178, upload-time = "2026-01-18T20:55:27.106Z" }, + { url = "https://files.pythonhosted.org/packages/8d/a2/e6532ed7716aed03dede8df2d0d0d4150710c2122647d94b474147ccd891/ormsgpack-1.12.2-cp310-cp310-win_amd64.whl", hash = "sha256:dc7a33be14c347893edbb1ceda89afbf14c467d593a5ee92c11de4f1666b4d4f", size = 117183, upload-time = "2026-01-18T20:55:55.52Z" }, + { url = "https://files.pythonhosted.org/packages/4b/08/8b68f24b18e69d92238aa8f258218e6dfeacf4381d9d07ab8df303f524a9/ormsgpack-1.12.2-cp311-cp311-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:bd5f4bf04c37888e864f08e740c5a573c4017f6fd6e99fa944c5c935fabf2dd9", size = 378266, upload-time = "2026-01-18T20:55:59.876Z" }, + { url = "https://files.pythonhosted.org/packages/0d/24/29fc13044ecb7c153523ae0a1972269fcd613650d1fa1a9cec1044c6b666/ormsgpack-1.12.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:34d5b28b3570e9fed9a5a76528fc7230c3c76333bc214798958e58e9b79cc18a", size = 203035, upload-time = "2026-01-18T20:55:30.59Z" }, + { url = "https://files.pythonhosted.org/packages/ad/c2/00169fb25dd8f9213f5e8a549dfb73e4d592009ebc85fbbcd3e1dcac575b/ormsgpack-1.12.2-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:3708693412c28f3538fb5a65da93787b6bbab3484f6bc6e935bfb77a62400ae5", size = 210539, upload-time = "2026-01-18T20:55:48.569Z" }, + { url = "https://files.pythonhosted.org/packages/1b/33/543627f323ff3c73091f51d6a20db28a1a33531af30873ea90c5ac95a9b5/ormsgpack-1.12.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:43013a3f3e2e902e1d05e72c0f1aeb5bedbb8e09240b51e26792a3c89267e181", size = 212401, upload-time = "2026-01-18T20:56:10.101Z" }, + { url = "https://files.pythonhosted.org/packages/e8/5d/f70e2c3da414f46186659d24745483757bcc9adccb481a6eb93e2b729301/ormsgpack-1.12.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:7c8b1667a72cbba74f0ae7ecf3105a5e01304620ed14528b2cb4320679d2869b", size = 387082, upload-time = "2026-01-18T20:56:12.047Z" }, + { url = "https://files.pythonhosted.org/packages/c0/d6/06e8dc920c7903e051f30934d874d4afccc9bb1c09dcaf0bc03a7de4b343/ormsgpack-1.12.2-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:df6961442140193e517303d0b5d7bc2e20e69a879c2d774316125350c4a76b92", size = 482346, upload-time = "2026-01-18T20:56:05.152Z" }, + { url = "https://files.pythonhosted.org/packages/66/c4/f337ac0905eed9c393ef990c54565cd33644918e0a8031fe48c098c71dbf/ormsgpack-1.12.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:c6a4c34ddef109647c769d69be65fa1de7a6022b02ad45546a69b3216573eb4a", size = 425181, upload-time = "2026-01-18T20:55:37.83Z" }, + { url = "https://files.pythonhosted.org/packages/78/29/6d5758fabef3babdf4bbbc453738cc7de9cd3334e4c38dd5737e27b85653/ormsgpack-1.12.2-cp311-cp311-win_amd64.whl", hash = "sha256:73670ed0375ecc303858e3613f407628dd1fca18fe6ac57b7b7ce66cc7bb006c", size = 117182, upload-time = "2026-01-18T20:55:31.472Z" }, + { url = "https://files.pythonhosted.org/packages/c4/57/17a15549233c37e7fd054c48fe9207492e06b026dbd872b826a0b5f833b6/ormsgpack-1.12.2-cp311-cp311-win_arm64.whl", hash = "sha256:c2be829954434e33601ae5da328cccce3266b098927ca7a30246a0baec2ce7bd", size = 111464, upload-time = "2026-01-18T20:55:38.811Z" }, + { url = "https://files.pythonhosted.org/packages/4c/36/16c4b1921c308a92cef3bf6663226ae283395aa0ff6e154f925c32e91ff5/ormsgpack-1.12.2-cp312-cp312-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:7a29d09b64b9694b588ff2f80e9826bdceb3a2b91523c5beae1fab27d5c940e7", size = 378618, upload-time = "2026-01-18T20:55:50.835Z" }, + { url = "https://files.pythonhosted.org/packages/c0/68/468de634079615abf66ed13bb5c34ff71da237213f29294363beeeca5306/ormsgpack-1.12.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0b39e629fd2e1c5b2f46f99778450b59454d1f901bc507963168985e79f09c5d", size = 203186, upload-time = "2026-01-18T20:56:11.163Z" }, + { url = "https://files.pythonhosted.org/packages/73/a9/d756e01961442688b7939bacd87ce13bfad7d26ce24f910f6028178b2cc8/ormsgpack-1.12.2-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:958dcb270d30a7cb633a45ee62b9444433fa571a752d2ca484efdac07480876e", size = 210738, upload-time = "2026-01-18T20:56:09.181Z" }, + { url = "https://files.pythonhosted.org/packages/7b/ba/795b1036888542c9113269a3f5690ab53dd2258c6fb17676ac4bd44fcf94/ormsgpack-1.12.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:58d379d72b6c5e964851c77cfedfb386e474adee4fd39791c2c5d9efb53505cc", size = 212569, upload-time = "2026-01-18T20:56:06.135Z" }, + { url = "https://files.pythonhosted.org/packages/6c/aa/bff73c57497b9e0cba8837c7e4bcab584b1a6dbc91a5dd5526784a5030c8/ormsgpack-1.12.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:8463a3fc5f09832e67bdb0e2fda6d518dc4281b133166146a67f54c08496442e", size = 387166, upload-time = "2026-01-18T20:55:36.738Z" }, + { url = "https://files.pythonhosted.org/packages/d3/cf/f8283cba44bcb7b14f97b6274d449db276b3a86589bdb363169b51bc12de/ormsgpack-1.12.2-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:eddffb77eff0bad4e67547d67a130604e7e2dfbb7b0cde0796045be4090f35c6", size = 482498, upload-time = "2026-01-18T20:55:29.626Z" }, + { url = "https://files.pythonhosted.org/packages/05/be/71e37b852d723dfcbe952ad04178c030df60d6b78eba26bfd14c9a40575e/ormsgpack-1.12.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:fcd55e5f6ba0dbce624942adf9f152062135f991a0126064889f68eb850de0dd", size = 425518, upload-time = "2026-01-18T20:55:49.556Z" }, + { url = "https://files.pythonhosted.org/packages/7a/0c/9803aa883d18c7ef197213cd2cbf73ba76472a11fe100fb7dab2884edf48/ormsgpack-1.12.2-cp312-cp312-win_amd64.whl", hash = "sha256:d024b40828f1dde5654faebd0d824f9cc29ad46891f626272dd5bfd7af2333a4", size = 117462, upload-time = "2026-01-18T20:55:47.726Z" }, + { url = "https://files.pythonhosted.org/packages/c8/9e/029e898298b2cc662f10d7a15652a53e3b525b1e7f07e21fef8536a09bb8/ormsgpack-1.12.2-cp312-cp312-win_arm64.whl", hash = "sha256:da538c542bac7d1c8f3f2a937863dba36f013108ce63e55745941dda4b75dbb6", size = 111559, upload-time = "2026-01-18T20:55:54.273Z" }, + { url = "https://files.pythonhosted.org/packages/eb/29/bb0eba3288c0449efbb013e9c6f58aea79cf5cb9ee1921f8865f04c1a9d7/ormsgpack-1.12.2-cp313-cp313-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:5ea60cb5f210b1cfbad8c002948d73447508e629ec375acb82910e3efa8ff355", size = 378661, upload-time = "2026-01-18T20:55:57.765Z" }, + { url = "https://files.pythonhosted.org/packages/6e/31/5efa31346affdac489acade2926989e019e8ca98129658a183e3add7af5e/ormsgpack-1.12.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f3601f19afdbea273ed70b06495e5794606a8b690a568d6c996a90d7255e51c1", size = 203194, upload-time = "2026-01-18T20:56:08.252Z" }, + { url = "https://files.pythonhosted.org/packages/eb/56/d0087278beef833187e0167f8527235ebe6f6ffc2a143e9de12a98b1ce87/ormsgpack-1.12.2-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:29a9f17a3dac6054c0dce7925e0f4995c727f7c41859adf9b5572180f640d172", size = 210778, upload-time = "2026-01-18T20:55:17.694Z" }, + { url = "https://files.pythonhosted.org/packages/1c/a2/072343e1413d9443e5a252a8eb591c2d5b1bffbe5e7bfc78c069361b92eb/ormsgpack-1.12.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:39c1bd2092880e413902910388be8715f70b9f15f20779d44e673033a6146f2d", size = 212592, upload-time = "2026-01-18T20:55:32.747Z" }, + { url = "https://files.pythonhosted.org/packages/a2/8b/a0da3b98a91d41187a63b02dda14267eefc2a74fcb43cc2701066cf1510e/ormsgpack-1.12.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:50b7249244382209877deedeee838aef1542f3d0fc28b8fe71ca9d7e1896a0d7", size = 387164, upload-time = "2026-01-18T20:55:40.853Z" }, + { url = "https://files.pythonhosted.org/packages/19/bb/6d226bc4cf9fc20d8eb1d976d027a3f7c3491e8f08289a2e76abe96a65f3/ormsgpack-1.12.2-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:5af04800d844451cf102a59c74a841324868d3f1625c296a06cc655c542a6685", size = 482516, upload-time = "2026-01-18T20:55:42.033Z" }, + { url = "https://files.pythonhosted.org/packages/fb/f1/bb2c7223398543dedb3dbf8bb93aaa737b387de61c5feaad6f908841b782/ormsgpack-1.12.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:cec70477d4371cd524534cd16472d8b9cc187e0e3043a8790545a9a9b296c258", size = 425539, upload-time = "2026-01-18T20:55:24.727Z" }, + { url = "https://files.pythonhosted.org/packages/7b/e8/0fb45f57a2ada1fed374f7494c8cd55e2f88ccd0ab0a669aa3468716bf5f/ormsgpack-1.12.2-cp313-cp313-win_amd64.whl", hash = "sha256:21f4276caca5c03a818041d637e4019bc84f9d6ca8baa5ea03e5cc8bf56140e9", size = 117459, upload-time = "2026-01-18T20:55:56.876Z" }, + { url = "https://files.pythonhosted.org/packages/7a/d4/0cfeea1e960d550a131001a7f38a5132c7ae3ebde4c82af1f364ccc5d904/ormsgpack-1.12.2-cp313-cp313-win_arm64.whl", hash = "sha256:baca4b6773d20a82e36d6fd25f341064244f9f86a13dead95dd7d7f996f51709", size = 111577, upload-time = "2026-01-18T20:55:43.605Z" }, + { url = "https://files.pythonhosted.org/packages/94/16/24d18851334be09c25e87f74307c84950f18c324a4d3c0b41dabdbf19c29/ormsgpack-1.12.2-cp314-cp314-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:bc68dd5915f4acf66ff2010ee47c8906dc1cf07399b16f4089f8c71733f6e36c", size = 378717, upload-time = "2026-01-18T20:55:26.164Z" }, + { url = "https://files.pythonhosted.org/packages/b5/a2/88b9b56f83adae8032ac6a6fa7f080c65b3baf9b6b64fd3d37bd202991d4/ormsgpack-1.12.2-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:46d084427b4132553940070ad95107266656cb646ea9da4975f85cb1a6676553", size = 203183, upload-time = "2026-01-18T20:55:18.815Z" }, + { url = "https://files.pythonhosted.org/packages/a9/80/43e4555963bf602e5bdc79cbc8debd8b6d5456c00d2504df9775e74b450b/ormsgpack-1.12.2-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:c010da16235806cf1d7bc4c96bf286bfa91c686853395a299b3ddb49499a3e13", size = 210814, upload-time = "2026-01-18T20:55:33.973Z" }, + { url = "https://files.pythonhosted.org/packages/78/e1/7cfbf28de8bca6efe7e525b329c31277d1b64ce08dcba723971c241a9d60/ormsgpack-1.12.2-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:18867233df592c997154ff942a6503df274b5ac1765215bceba7a231bea2745d", size = 212634, upload-time = "2026-01-18T20:55:28.634Z" }, + { url = "https://files.pythonhosted.org/packages/95/f8/30ae5716e88d792a4e879debee195653c26ddd3964c968594ddef0a3cc7e/ormsgpack-1.12.2-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:b009049086ddc6b8f80c76b3955df1aa22a5fbd7673c525cd63bf91f23122ede", size = 387139, upload-time = "2026-01-18T20:56:02.013Z" }, + { url = "https://files.pythonhosted.org/packages/dc/81/aee5b18a3e3a0e52f718b37ab4b8af6fae0d9d6a65103036a90c2a8ffb5d/ormsgpack-1.12.2-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:1dcc17d92b6390d4f18f937cf0b99054824a7815818012ddca925d6e01c2e49e", size = 482578, upload-time = "2026-01-18T20:55:35.117Z" }, + { url = "https://files.pythonhosted.org/packages/bd/17/71c9ba472d5d45f7546317f467a5fc941929cd68fb32796ca3d13dcbaec2/ormsgpack-1.12.2-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:f04b5e896d510b07c0ad733d7fce2d44b260c5e6c402d272128f8941984e4285", size = 425539, upload-time = "2026-01-18T20:56:04.009Z" }, + { url = "https://files.pythonhosted.org/packages/2e/a6/ac99cd7fe77e822fed5250ff4b86fa66dd4238937dd178d2299f10b69816/ormsgpack-1.12.2-cp314-cp314-win_amd64.whl", hash = "sha256:ae3aba7eed4ca7cb79fd3436eddd29140f17ea254b91604aa1eb19bfcedb990f", size = 117493, upload-time = "2026-01-18T20:56:07.343Z" }, + { url = "https://files.pythonhosted.org/packages/3a/67/339872846a1ae4592535385a1c1f93614138566d7af094200c9c3b45d1e5/ormsgpack-1.12.2-cp314-cp314-win_arm64.whl", hash = "sha256:118576ea6006893aea811b17429bfc561b4778fad393f5f538c84af70b01260c", size = 111579, upload-time = "2026-01-18T20:55:21.161Z" }, + { url = "https://files.pythonhosted.org/packages/49/c2/6feb972dc87285ad381749d3882d8aecbde9f6ecf908dd717d33d66df095/ormsgpack-1.12.2-cp314-cp314t-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:7121b3d355d3858781dc40dafe25a32ff8a8242b9d80c692fd548a4b1f7fd3c8", size = 378721, upload-time = "2026-01-18T20:55:52.12Z" }, + { url = "https://files.pythonhosted.org/packages/a3/9a/900a6b9b413e0f8a471cf07830f9cf65939af039a362204b36bd5b581d8b/ormsgpack-1.12.2-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4ee766d2e78251b7a63daf1cddfac36a73562d3ddef68cacfb41b2af64698033", size = 203170, upload-time = "2026-01-18T20:55:44.469Z" }, + { url = "https://files.pythonhosted.org/packages/87/4c/27a95466354606b256f24fad464d7c97ab62bce6cc529dd4673e1179b8fb/ormsgpack-1.12.2-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:292410a7d23de9b40444636b9b8f1e4e4b814af7f1ef476e44887e52a123f09d", size = 212816, upload-time = "2026-01-18T20:55:23.501Z" }, + { url = "https://files.pythonhosted.org/packages/73/cd/29cee6007bddf7a834e6cd6f536754c0535fcb939d384f0f37a38b1cddb8/ormsgpack-1.12.2-cp314-cp314t-win_amd64.whl", hash = "sha256:837dd316584485b72ef451d08dd3e96c4a11d12e4963aedb40e08f89685d8ec2", size = 117232, upload-time = "2026-01-18T20:55:45.448Z" }, +] + [[package]] name = "packaging" version = "26.0" @@ -5039,6 +5171,9 @@ lambda-worker-otel = [ { name = "opentelemetry-sdk-extension-aws" }, { name = "opentelemetry-semantic-conventions" }, ] +langgraph = [ + { name = "langgraph" }, +] langsmith = [ { name = "langsmith" }, ] @@ -5061,6 +5196,7 @@ dev = [ { name = "googleapis-common-protos" }, { name = "grpcio-tools" }, { name = "httpx" }, + { name = "langgraph" }, { name = "langsmith" }, { name = "litellm" }, { name = "maturin" }, @@ -5096,6 +5232,7 @@ requires-dist = [ { name = "aioboto3", marker = "extra == 'aioboto3'", specifier = ">=10.4.0" }, { name = "google-adk", marker = "extra == 'google-adk'", specifier = ">=1.27.0,<2" }, { name = "grpcio", marker = "extra == 'grpc'", specifier = ">=1.48.2,<2" }, + { name = "langgraph", marker = "extra == 'langgraph'", specifier = ">=1.1.0" }, { name = "langsmith", marker = "extra == 'langsmith'", specifier = ">=0.7.0,<0.8" }, { name = "mcp", marker = "extra == 'openai-agents'", specifier = ">=1.9.4,<2" }, { name = "nexus-rpc", specifier = "==1.4.0" }, @@ -5114,7 +5251,7 @@ requires-dist = [ { name = "types-protobuf", specifier = ">=3.20,<7.0.0" }, { name = "typing-extensions", specifier = ">=4.2.0,<5" }, ] -provides-extras = ["grpc", "opentelemetry", "pydantic", "openai-agents", "google-adk", "langsmith", "lambda-worker-otel", "aioboto3"] +provides-extras = ["grpc", "opentelemetry", "pydantic", "openai-agents", "google-adk", "langgraph", "langsmith", "lambda-worker-otel", "aioboto3"] [package.metadata.requires-dev] dev = [ @@ -5123,6 +5260,7 @@ dev = [ { name = "googleapis-common-protos", specifier = "==1.70.0" }, { name = "grpcio-tools", specifier = ">=1.48.2,<2" }, { name = "httpx", specifier = ">=0.28.1" }, + { name = "langgraph", specifier = ">=1.1.0" }, { name = "langsmith", specifier = ">=0.7.0,<0.8" }, { name = "litellm", specifier = ">=1.83.0" }, { name = "maturin", specifier = ">=1.8.2" }, From 8a6d0e0f329280df2e9f9f1bc7ab4835ee7a3462 Mon Sep 17 00:00:00 2001 From: Justin Anderson <44687433+jmaeagle99@users.noreply.github.com> Date: Tue, 28 Apr 2026 19:46:30 -0700 Subject: [PATCH 066/226] =?UTF-8?q?=F0=9F=92=A5=20Use=20ExternalStorageRef?= =?UTF-8?q?erence=20proto=20for=20payload=20references=20(#1486)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- temporalio/converter/_data_converter.py | 33 +++--- temporalio/converter/_extstore.py | 68 ++++++++---- tests/test_extstore.py | 141 +++++++++++++++++++++--- tests/worker/test_extstore.py | 55 ++++----- 4 files changed, 209 insertions(+), 88 deletions(-) diff --git a/temporalio/converter/_data_converter.py b/temporalio/converter/_data_converter.py index 0323466e7..13b48e695 100644 --- a/temporalio/converter/_data_converter.py +++ b/temporalio/converter/_data_converter.py @@ -14,11 +14,11 @@ import temporalio.api.common.v1 import temporalio.api.failure.v1 import temporalio.common +from temporalio.api.sdk.v1.external_storage_pb2 import ExternalStorageReference from temporalio.converter._extstore import ( _REFERENCE_ENCODING, ExternalStorage, StorageDriverStoreContext, - StorageWarning, ) from temporalio.converter._failure_converter import ( FailureConverter, @@ -41,6 +41,17 @@ WithSerializationContext, ) +_REFERENCE_MESSAGE_TYPE = ExternalStorageReference.DESCRIPTOR.full_name.encode() + + +def _is_reference_payload(p: temporalio.api.common.v1.Payload) -> bool: + """Return True if *p* is an external-storage reference payload.""" + return p.metadata.get("encoding") == _REFERENCE_ENCODING or ( + p.metadata.get("encoding") == b"json/protobuf" + and p.metadata.get("messageType") == _REFERENCE_MESSAGE_TYPE + ) + + # Import defaults from public API to avoid pydoctor cross-reference issues if TYPE_CHECKING: from temporalio.converter import DefaultFailureConverter, DefaultPayloadConverter @@ -307,13 +318,9 @@ async def _transform_inbound_payloads( if self.external_storage: await self.external_storage._retrieve_payloads(payloads) else: - if any( - p.metadata.get("encoding") == _REFERENCE_ENCODING - for p in payloads.payloads - ): - warnings.warn( - "[TMPRL1105] Detected externally stored payload(s) but external storage is not configured.", - StorageWarning, + if any(_is_reference_payload(p) for p in payloads.payloads): + raise RuntimeError( + "[TMPRL1105] Detected externally stored payload(s) but external storage is not configured." ) if self.payload_codec: await self.payload_codec.decode_wrapper(payloads) @@ -348,13 +355,9 @@ async def _external_retrieve_payload_sequence( retrieved_payloads ) else: - if any( - p.metadata.get("encoding") == _REFERENCE_ENCODING - for p in retrieved_payloads - ): - warnings.warn( - "[TMPRL1105] Detected externally stored payload(s) but external storage is not configured.", - StorageWarning, + if any(_is_reference_payload(p) for p in retrieved_payloads): + raise RuntimeError( + "[TMPRL1105] Detected externally stored payload(s) but external storage is not configured." ) return retrieved_payloads diff --git a/temporalio/converter/_extstore.py b/temporalio/converter/_extstore.py index 55b1686bf..c31424acf 100644 --- a/temporalio/converter/_extstore.py +++ b/temporalio/converter/_extstore.py @@ -18,7 +18,11 @@ from typing_extensions import Self from temporalio.api.common.v1 import Payload, Payloads -from temporalio.converter._payload_converter import JSONPlainPayloadConverter +from temporalio.api.sdk.v1.external_storage_pb2 import ExternalStorageReference +from temporalio.converter._payload_converter import ( + JSONPlainPayloadConverter, + JSONProtoPayloadConverter, +) _T = TypeVar("_T") @@ -225,6 +229,11 @@ class StorageWarning(RuntimeWarning): @dataclass(frozen=True) class _StorageReference: + """Legacy external storage reference used only on the retrieval path as a + fallback for in-flight workflows that were written before the + ExternalStorageReference proto was introduced. + """ + driver_name: str driver_claim: StorageDriverClaim @@ -278,8 +287,9 @@ class ExternalStorage: ) """Store context bound to this instance via :meth:`_with_store_context`.""" - _claim_converter: ClassVar[JSONPlainPayloadConverter] = JSONPlainPayloadConverter( - encoding=_REFERENCE_ENCODING.decode() + _claim_converter: ClassVar[JSONProtoPayloadConverter] = JSONProtoPayloadConverter() + _legacy_claim_converter: ClassVar[JSONPlainPayloadConverter] = ( + JSONPlainPayloadConverter(encoding=_REFERENCE_ENCODING.decode()) ) def __post_init__(self) -> None: @@ -357,9 +367,9 @@ async def _store_payload(self, payload: Payload) -> Payload: self._validate_claim_length(claims, expected=1, driver=driver) external_size = payload.ByteSize() - reference = _StorageReference( + reference = ExternalStorageReference( driver_name=driver.name(), - driver_claim=claims[0], + claim_data=claims[0].claim_data, ) reference_payload = self._claim_converter.to_payload(reference) if reference_payload is None: @@ -421,9 +431,9 @@ async def _store_payload_sequence( self._validate_claim_length(claims, expected=len(indices), driver=driver) for i, claim in enumerate(claims): - reference = _StorageReference( + reference = ExternalStorageReference( driver_name=driver.name(), - driver_claim=claim, + claim_data=claim.claim_data, ) reference_payload = self._claim_converter.to_payload(reference) if reference_payload is None: @@ -443,20 +453,35 @@ async def _store_payload_sequence( return results - async def _retrieve_payload(self, payload: Payload) -> Payload: + def _decode_reference(self, payload: Payload) -> ExternalStorageReference | None: + """Decode an external storage reference from a payload.""" if len(payload.external_payloads) == 0: - return payload - - start_time = time.monotonic() + return None + encoding = payload.metadata.get("encoding", b"") + if encoding == _REFERENCE_ENCODING: + legacy = self._legacy_claim_converter.from_payload( + payload, _StorageReference + ) + if not isinstance(legacy, _StorageReference): + return None + return ExternalStorageReference( + driver_name=legacy.driver_name, + claim_data=legacy.driver_claim.claim_data, + ) + ref = self._claim_converter.from_payload(payload, ExternalStorageReference) + return ref if isinstance(ref, ExternalStorageReference) else None - reference = self._claim_converter.from_payload(payload, _StorageReference) - if not isinstance(reference, _StorageReference): + async def _retrieve_payload(self, payload: Payload) -> Payload: + ref = self._decode_reference(payload) + if ref is None: return payload - driver = self._get_driver_by_name(reference.driver_name) + start_time = time.monotonic() + driver = self._get_driver_by_name(ref.driver_name) context = StorageDriverRetrieveContext() + claim = StorageDriverClaim(claim_data=dict(ref.claim_data)) - stored_payloads = await driver.retrieve(context, [reference.driver_claim]) + stored_payloads = await driver.retrieve(context, [claim]) self._validate_payload_length(stored_payloads, expected=1, driver=driver) @@ -486,15 +511,12 @@ async def _retrieve_payload_sequence( driver_claims: dict[StorageDriver, list[tuple[int, StorageDriverClaim]]] = {} for index, payload in enumerate(payloads): - if len(payload.external_payloads) == 0: + ref = self._decode_reference(payload) + if ref is None: continue - - reference = self._claim_converter.from_payload(payload, _StorageReference) - if not isinstance(reference, _StorageReference): - continue - - driver = self._get_driver_by_name(reference.driver_name) - driver_claims.setdefault(driver, []).append((index, reference.driver_claim)) + driver = self._get_driver_by_name(ref.driver_name) + claim = StorageDriverClaim(claim_data=dict(ref.claim_data)) + driver_claims.setdefault(driver, []).append((index, claim)) if not driver_claims: return results diff --git a/tests/test_extstore.py b/tests/test_extstore.py index 1771778a7..196632042 100644 --- a/tests/test_extstore.py +++ b/tests/test_extstore.py @@ -6,6 +6,7 @@ import pytest from temporalio.api.common.v1 import Payload +from temporalio.api.sdk.v1.external_storage_pb2 import ExternalStorageReference from temporalio.converter import ( DataConverter, ExternalStorage, @@ -16,9 +17,26 @@ StorageDriverRetrieveContext, StorageDriverStoreContext, ) -from temporalio.converter._extstore import _StorageReference +from temporalio.converter._extstore import _REFERENCE_ENCODING, _StorageReference +from temporalio.converter._payload_converter import JSONProtoPayloadConverter from temporalio.exceptions import ApplicationError +_legacy_ref_converter = JSONPlainPayloadConverter(encoding=_REFERENCE_ENCODING.decode()) + + +def _make_legacy_payload( + driver_name: str, claim_data: dict[str, str], size_bytes: int +) -> Payload: + """Build a reference payload in the legacy ``json/external-storage-reference`` format.""" + ref = _StorageReference( + driver_name=driver_name, + driver_claim=StorageDriverClaim(claim_data=claim_data), + ) + payload = _legacy_ref_converter.to_payload(ref) + assert payload is not None + payload.external_payloads.add().size_bytes = size_bytes + return payload + class InMemoryTestDriver(StorageDriver): """In-memory storage driver for testing.""" @@ -115,7 +133,7 @@ async def test_extstore_encode_decode(self): assert driver._retrieve_calls == 1 async def test_extstore_reference_structure(self): - """Test that external storage creates proper reference structure.""" + """Externalized payloads are written as ExternalStorageReference proto (json/protobuf encoding).""" converter = DataConverter( external_storage=ExternalStorage( drivers=[InMemoryTestDriver("test-driver")], @@ -123,25 +141,19 @@ async def test_extstore_reference_structure(self): ) ) - # Create large payload large_value = "x" * 100 encoded = await converter.encode([large_value]) - # Verify reference structure reference_payload = encoded[0] assert len(reference_payload.external_payloads) > 0 + assert reference_payload.metadata.get("encoding") == b"json/protobuf" - # The payload should contain a serialized _ExternalStorageReference - # Deserialize it to verify structure using the same encoding - claim_converter = JSONPlainPayloadConverter( - encoding="json/external-storage-reference" + reference = JSONProtoPayloadConverter().from_payload( + reference_payload, ExternalStorageReference ) - reference = claim_converter.from_payload(reference_payload, _StorageReference) - - assert isinstance(reference, _StorageReference) - assert "test-driver" == reference.driver_name - assert isinstance(reference.driver_claim, StorageDriverClaim) - assert "key" in reference.driver_claim.claim_data + assert isinstance(reference, ExternalStorageReference) + assert reference.driver_name == "test-driver" + assert "key" in reference.claim_data async def test_extstore_composite_conditional(self): """Test using multiple drivers based on size.""" @@ -482,9 +494,10 @@ async def test_selector_always_first_driver_handles_all_stores(self): assert second._store_calls == 0 # The reference in history names the first driver. - ref = JSONPlainPayloadConverter( - encoding="json/external-storage-reference" - ).from_payload(encoded[0], _StorageReference) + ref = JSONProtoPayloadConverter().from_payload( + encoded[0], ExternalStorageReference + ) + assert isinstance(ref, ExternalStorageReference) assert ref.driver_name == "driver-first" # Retrieval also goes to the first driver. @@ -694,5 +707,99 @@ def test_negative_payload_size_threshold_raises(self, threshold: int): ) +class TestBackwardCompat: + """Tests that the retrieval path handles the legacy ``json/external-storage-reference`` + format for in-flight workflows written before the ExternalStorageReference proto.""" + + async def test_legacy_format_single_payload_decode(self): + """A single payload in the legacy reference format is retrieved correctly.""" + driver = InMemoryTestDriver() + + inner_payload = (await DataConverter().encode(["x" * 200]))[0] + stored_key = "payload-0" + driver._storage[stored_key] = inner_payload.SerializeToString() + + legacy_payload = _make_legacy_payload( + driver_name=driver.name(), + claim_data={"key": stored_key}, + size_bytes=inner_payload.ByteSize(), + ) + + converter = DataConverter( + external_storage=ExternalStorage( + drivers=[driver], + payload_size_threshold=100, + ) + ) + decoded = await converter.decode([legacy_payload], [str]) + assert decoded[0] == "x" * 200 + assert driver._retrieve_calls == 1 + + async def test_legacy_and_new_format_mixed_batch_decode(self): + """A batch containing legacy-format, new proto-format, and inline payloads + all decode correctly in a single call.""" + driver = InMemoryTestDriver() + converter = DataConverter( + external_storage=ExternalStorage( + drivers=[driver], + payload_size_threshold=50, + ) + ) + + new_value = "new-format-value" * 20 + inline_value = "small" + encoded = await converter.encode([new_value, inline_value]) + new_format_payload = encoded[0] + inline_payload = encoded[1] + assert driver._store_calls == 1 + + legacy_value = "legacy-format-value" * 20 + legacy_inner = (await DataConverter().encode([legacy_value]))[0] + stored_key = f"payload-{len(driver._storage)}" + driver._storage[stored_key] = legacy_inner.SerializeToString() + legacy_payload = _make_legacy_payload( + driver_name=driver.name(), + claim_data={"key": stored_key}, + size_bytes=legacy_inner.ByteSize(), + ) + + decoded = await converter.decode( + [legacy_payload, new_format_payload, inline_payload], [str, str, str] + ) + assert decoded[0] == legacy_value + assert decoded[1] == new_value + assert decoded[2] == inline_value + # Both external payloads share the same driver and are batched into one retrieve call. + assert driver._retrieve_calls == 1 + + async def test_new_format_encode_round_trips(self): + """Payloads written with the new ExternalStorageReference format round-trip + correctly and carry the expected proto encoding.""" + driver = InMemoryTestDriver() + converter = DataConverter( + external_storage=ExternalStorage( + drivers=[driver], + payload_size_threshold=50, + ) + ) + + value = "round-trip-value" * 20 + encoded = await converter.encode([value]) + ref_payload = encoded[0] + + assert ref_payload.metadata.get("encoding") == b"json/protobuf" + assert len(ref_payload.external_payloads) > 0 + + ref = JSONProtoPayloadConverter().from_payload( + ref_payload, ExternalStorageReference + ) + assert isinstance(ref, ExternalStorageReference) + assert ref.driver_name == driver.name() + assert "key" in ref.claim_data + + decoded = await converter.decode(encoded, [str]) + assert decoded[0] == value + + if __name__ == "__main__": pytest.main([__file__, "-v"]) diff --git a/tests/worker/test_extstore.py b/tests/worker/test_extstore.py index 2265ed8ee..e186f4e67 100644 --- a/tests/worker/test_extstore.py +++ b/tests/worker/test_extstore.py @@ -27,7 +27,6 @@ StorageDriverRetrieveContext, StorageDriverStoreContext, StorageDriverWorkflowInfo, - StorageWarning, ) from temporalio.exceptions import ActivityError, ApplicationError from temporalio.testing._workflow import WorkflowEnvironment @@ -406,23 +405,18 @@ async def test_replay_extstore_history_fails_without_extstore( ) history = await handle.fetch_history() - # Replay without external storage — the reference payload cannot be decoded. - # The middleware emits a StorageWarning when it encounters a reference payload - # with no driver configured. - with pytest.warns( - StorageWarning, - match=r"^\[TMPRL1105\] Detected externally stored payload\(s\) but external storage is not configured\.$", - ): - result = await Replayer(workflows=[ExtStoreWorkflow]).replay_workflow( - history, raise_on_replay_failure=False - ) - # Must be a task-failure RuntimeError, not a NondeterminismError — external - # storage decode failures are distinct from workflow code changes. + # Replay without external storage: decode_activation raises when it + # encounters a reference payload with no driver configured, producing a + # task failure (not a NondeterminismError). + result = await Replayer(workflows=[ExtStoreWorkflow]).replay_workflow( + history, raise_on_replay_failure=False + ) assert isinstance(result.replay_failure, RuntimeError) assert not isinstance(result.replay_failure, workflow.NondeterminismError) - # The message is the full activation-completion failure string; the - # "Failed decoding arguments" text from _convert_payloads is embedded in it. - assert "Failed decoding arguments" in result.replay_failure.args[0] + assert ( + "[TMPRL1105] Detected externally stored payload(s) but external storage is not configured." + in result.replay_failure.args[0] + ) async def test_replay_extstore_history_succeeds_with_correct_extstore( @@ -483,9 +477,9 @@ async def test_replay_extstore_history_fails_with_empty_driver( async def test_replay_extstore_activity_result_fails_without_extstore( env: WorkflowEnvironment, ) -> None: - """A history where only the activity result was stored externally (the - workflow input is small enough to be inline) also fails to replay without - external storage — verifying that mid-workflow decode failures are caught.""" + """A history where only the activity result was stored externally also fails + to replay without external storage, verifying that mid-workflow reference + payloads are caught regardless of whether the workflow uses the result.""" driver = InMemoryTestDriver() handle = await _run_extstore_workflow_and_fetch_history( env, @@ -496,22 +490,17 @@ async def test_replay_extstore_activity_result_fails_without_extstore( history = await handle.fetch_history() # Replay without external storage. The workflow input decodes fine, but - # when the ActivityTaskCompleted result is delivered back to the workflow - # coroutine it cannot be decoded. - with pytest.warns( - StorageWarning, - match=r"^\[TMPRL1105\] Detected externally stored payload\(s\) but external storage is not configured\.$", - ): - result = await Replayer(workflows=[ExtStoreWorkflow]).replay_workflow( - history, raise_on_replay_failure=False - ) - # Mid-workflow decode failure is still a task failure (RuntimeError), not - # nondeterminism. + # decode_activation raises when the ActivityTaskCompleted reference payload + # is encountered, producing a task failure (not a NondeterminismError). + result = await Replayer(workflows=[ExtStoreWorkflow]).replay_workflow( + history, raise_on_replay_failure=False + ) assert isinstance(result.replay_failure, RuntimeError) assert not isinstance(result.replay_failure, workflow.NondeterminismError) - # The message is the full activation-completion failure string; the - # "Failed decoding arguments" text from _convert_payloads is embedded in it. - assert "Failed decoding arguments" in result.replay_failure.args[0] + assert ( + "[TMPRL1105] Detected externally stored payload(s) but external storage is not configured." + in result.replay_failure.args[0] + ) async def test_extstore_chained_activities( From a247744e191606e934b51fa2e0b5736b90d1a529 Mon Sep 17 00:00:00 2001 From: Drew Hoskins Date: Wed, 29 Apr 2026 11:33:38 -0700 Subject: [PATCH 067/226] Add describe to S3 driver client (#1487) --- temporalio/contrib/aws/s3driver/README.md | 5 +- temporalio/contrib/aws/s3driver/_client.py | 9 +++ temporalio/contrib/aws/s3driver/_driver.py | 20 ++++++- temporalio/contrib/aws/s3driver/aioboto3.py | 8 +++ tests/contrib/aws/s3driver/test_s3driver.py | 56 +++++++++++++++++-- .../aws/s3driver/test_s3driver_worker.py | 2 +- 6 files changed, 91 insertions(+), 9 deletions(-) diff --git a/temporalio/contrib/aws/s3driver/README.md b/temporalio/contrib/aws/s3driver/README.md index c9520a688..ce58789df 100644 --- a/temporalio/contrib/aws/s3driver/README.md +++ b/temporalio/contrib/aws/s3driver/README.md @@ -23,8 +23,9 @@ from temporalio.contrib.aws.s3driver.aioboto3 import new_aioboto3_client from temporalio.converter import DataConverter, ExternalStorage session = aioboto3.Session() -# Credentials and region are resolved automatically from the standard AWS credential -# chain e.g. environment variables, ~/.aws/config, IAM instance profile, and so on. +# To see how to set credentials and region via environment, config objects, or configuration files, +# see: +# https://docs.aws.amazon.com/boto3/latest/guide/configuration.html async with session.client("s3") as s3_client: driver = S3StorageDriver( client=new_aioboto3_client(s3_client), diff --git a/temporalio/contrib/aws/s3driver/_client.py b/temporalio/contrib/aws/s3driver/_client.py index 16e4c6a8c..f49eead87 100644 --- a/temporalio/contrib/aws/s3driver/_client.py +++ b/temporalio/contrib/aws/s3driver/_client.py @@ -7,6 +7,7 @@ from __future__ import annotations from abc import ABC, abstractmethod +from collections.abc import Mapping class S3StorageDriverClient(ABC): @@ -30,3 +31,11 @@ async def object_exists(self, *, bucket: str, key: str) -> bool: @abstractmethod async def get_object(self, *, bucket: str, key: str) -> bytes: """Download and return the bytes stored at the given S3 *bucket* and *key*.""" + + def describe(self) -> Mapping[str, str]: + """Return client-specific diagnostic metadata (e.g. region, credentials + source) that the driver appends to error messages. Implementations may + override this to surface configuration that is useful for debugging + common misconfigurations. Returns an empty mapping by default. + """ + return {} diff --git a/temporalio/contrib/aws/s3driver/_driver.py b/temporalio/contrib/aws/s3driver/_driver.py index f784e67d1..445bfda8a 100644 --- a/temporalio/contrib/aws/s3driver/_driver.py +++ b/temporalio/contrib/aws/s3driver/_driver.py @@ -26,6 +26,20 @@ _T = TypeVar("_T") +def _format_client_context(client: S3StorageDriverClient) -> str: + """Format the client's ``describe()`` output as ", k=v, k=v" for error + messages. Returns an empty string when the client reports no metadata or + describe itself raises (diagnostic output must never mask the real error). + """ + try: + info = client.describe() + except Exception: + return "" + if not info: + return "" + return "".join(f", {k}={v}" for k, v in info.items()) + + async def _gather_with_cancellation( coros: Sequence[Coroutine[Any, Any, _T]], ) -> list[_T]: @@ -156,7 +170,8 @@ async def _upload(payload: Payload) -> StorageDriverClaim: ) except Exception as e: raise RuntimeError( - f"S3StorageDriver store failed [bucket={bucket}, key={key}]" + f"S3StorageDriver store failed [bucket={bucket}, key={key}" + f"{_format_client_context(self._client)}]" ) from e return StorageDriverClaim( @@ -185,7 +200,8 @@ async def _download(claim: StorageDriverClaim) -> Payload: payload_bytes = await self._client.get_object(bucket=bucket, key=key) except Exception as e: raise RuntimeError( - f"S3StorageDriver retrieve failed [bucket={bucket}, key={key}]" + f"S3StorageDriver retrieve failed [bucket={bucket}, key={key}" + f"{_format_client_context(self._client)}]" ) from e hash_algorithm = claim.claim_data.get("hash_algorithm") diff --git a/temporalio/contrib/aws/s3driver/aioboto3.py b/temporalio/contrib/aws/s3driver/aioboto3.py index b3da8b7c6..971ccfdba 100644 --- a/temporalio/contrib/aws/s3driver/aioboto3.py +++ b/temporalio/contrib/aws/s3driver/aioboto3.py @@ -7,6 +7,7 @@ from __future__ import annotations import io +from collections.abc import Mapping from botocore.exceptions import ClientError from types_aiobotocore_s3.client import S3Client @@ -34,6 +35,13 @@ def __init__(self, client: S3Client) -> None: """ self._client = client + def describe(self) -> Mapping[str, str]: + """Region of the wrapped aioboto3 client, surfaced in driver error + messages to short-circuit the most common silent 403 misconfiguration. + """ + region = self._client.meta.region_name + return {"region": region} if region else {} + async def object_exists(self, *, bucket: str, key: str) -> bool: """Check existence via aioboto3's ``head_object``.""" try: diff --git a/tests/contrib/aws/s3driver/test_s3driver.py b/tests/contrib/aws/s3driver/test_s3driver.py index ac11158fa..fb8c60544 100644 --- a/tests/contrib/aws/s3driver/test_s3driver.py +++ b/tests/contrib/aws/s3driver/test_s3driver.py @@ -26,6 +26,8 @@ S3StorageDriver, S3StorageDriverClient, ) +from temporalio.contrib.aws.s3driver._driver import _format_client_context +from temporalio.contrib.aws.s3driver.aioboto3 import _Aioboto3StorageDriverClient from temporalio.converter import ( JSONPlainPayloadConverter, StorageDriverActivityInfo, @@ -34,7 +36,7 @@ StorageDriverStoreContext, StorageDriverWorkflowInfo, ) -from tests.contrib.aws.s3driver.conftest import BUCKET +from tests.contrib.aws.s3driver.conftest import BUCKET, REGION _CONVERTER = JSONPlainPayloadConverter() @@ -618,7 +620,7 @@ async def test_store_nonexistent_bucket_raises( await driver.store(make_store_context(), [payload]) assert ( str(exc_info.value) - == f"S3StorageDriver store failed [bucket={bucket}, key={expected_key}]" + == f"S3StorageDriver store failed [bucket={bucket}, key={expected_key}, region={REGION}]" ) assert isinstance(exc_info.value.__cause__, ClientError) assert ( @@ -636,7 +638,7 @@ async def test_retrieve_nonexistent_key_raises( await driver.retrieve(StorageDriverRetrieveContext(), [claim]) assert ( str(exc_info.value) - == f"S3StorageDriver retrieve failed [bucket={BUCKET}, key={key}]" + == f"S3StorageDriver retrieve failed [bucket={BUCKET}, key={key}, region={REGION}]" ) assert isinstance(exc_info.value.__cause__, ClientError) assert ( @@ -655,7 +657,7 @@ async def test_retrieve_nonexistent_bucket_raises( await driver.retrieve(StorageDriverRetrieveContext(), [claim]) assert ( str(exc_info.value) - == f"S3StorageDriver retrieve failed [bucket={bucket}, key={key}]" + == f"S3StorageDriver retrieve failed [bucket={bucket}, key={key}, region={REGION}]" ) assert isinstance(exc_info.value.__cause__, ClientError) assert ( @@ -839,3 +841,49 @@ async def test_retrieve_cancels_remaining_on_failure( assert ( len(faulty_client.cancelled) == 2 ), "Expected 2 remaining tasks to be cancelled" + + +# --------------------------------------------------------------------------- +# TestAioboto3StorageDriverClientDescribe +# --------------------------------------------------------------------------- + + +class TestAioboto3StorageDriverClientDescribe: + def _make_client(self, region: str | None) -> _Aioboto3StorageDriverClient: + mock_s3 = MagicMock() + mock_s3.meta.region_name = region + return _Aioboto3StorageDriverClient(mock_s3) + + def test_returns_region(self) -> None: + client = self._make_client(region="ap-southeast-1") + assert client.describe() == {"region": "ap-southeast-1"} + + def test_omits_region_when_none(self) -> None: + client = self._make_client(region=None) + assert client.describe() == {} + + def test_omits_region_when_empty_string(self) -> None: + client = self._make_client(region="") + assert client.describe() == {} + + +# --------------------------------------------------------------------------- +# TestFormatClientContext +# --------------------------------------------------------------------------- + + +class TestFormatClientContext: + def test_formats_entry(self) -> None: + client = MagicMock(spec=S3StorageDriverClient) + client.describe.return_value = {"region": "us-east-1"} + assert _format_client_context(client) == ", region=us-east-1" + + def test_returns_empty_string_for_empty_describe(self) -> None: + client = MagicMock(spec=S3StorageDriverClient) + client.describe.return_value = {} + assert _format_client_context(client) == "" + + def test_returns_empty_string_when_describe_raises(self) -> None: + client = MagicMock(spec=S3StorageDriverClient) + client.describe.side_effect = RuntimeError("oops") + assert _format_client_context(client) == "" diff --git a/tests/contrib/aws/s3driver/test_s3driver_worker.py b/tests/contrib/aws/s3driver/test_s3driver_worker.py index 86039bfd5..4478b06fe 100644 --- a/tests/contrib/aws/s3driver/test_s3driver_worker.py +++ b/tests/contrib/aws/s3driver/test_s3driver_worker.py @@ -506,4 +506,4 @@ async def test_s3_store_failure_surfaces_in_workflow_history( msg = app_error.message assert f"S3StorageDriver store failed [bucket={bad_bucket}, key=" in msg assert f"/wt/LargeOutputNoRetryWorkflow/wi/{workflow_id}/ri/" in msg - assert f"/d/sha256/{expected_hash}]" in msg + assert f"/d/sha256/{expected_hash}, region={REGION}]" in msg From f6e113d596020efcfb9daf1bed6784209039ddb3 Mon Sep 17 00:00:00 2001 From: Spencer Judge Date: Wed, 29 Apr 2026 17:29:33 -0700 Subject: [PATCH 068/226] Add start_delay for SAA (#1491) --- temporalio/client.py | 53 ++++++++++++++++++++++++++++++++++++++++++ tests/test_activity.py | 15 ++++++++++++ 2 files changed, 68 insertions(+) diff --git a/temporalio/client.py b/temporalio/client.py index f781774c1..1ae8de106 100644 --- a/temporalio/client.py +++ b/temporalio/client.py @@ -1292,6 +1292,7 @@ async def start_activity( search_attributes: temporalio.common.TypedSearchAttributes | None = None, summary: str | None = None, priority: temporalio.common.Priority = temporalio.common.Priority.default, + start_delay: timedelta | None = None, rpc_metadata: Mapping[str, str | bytes] = {}, rpc_timeout: timedelta | None = None, ) -> ActivityHandle[ReturnType]: ... @@ -1314,6 +1315,7 @@ async def start_activity( search_attributes: temporalio.common.TypedSearchAttributes | None = None, summary: str | None = None, priority: temporalio.common.Priority = temporalio.common.Priority.default, + start_delay: timedelta | None = None, rpc_metadata: Mapping[str, str | bytes] = {}, rpc_timeout: timedelta | None = None, ) -> ActivityHandle[ReturnType]: ... @@ -1337,6 +1339,7 @@ async def start_activity( search_attributes: temporalio.common.TypedSearchAttributes | None = None, summary: str | None = None, priority: temporalio.common.Priority = temporalio.common.Priority.default, + start_delay: timedelta | None = None, rpc_metadata: Mapping[str, str | bytes] = {}, rpc_timeout: timedelta | None = None, ) -> ActivityHandle[ReturnType]: ... @@ -1360,6 +1363,7 @@ async def start_activity( search_attributes: temporalio.common.TypedSearchAttributes | None = None, summary: str | None = None, priority: temporalio.common.Priority = temporalio.common.Priority.default, + start_delay: timedelta | None = None, rpc_metadata: Mapping[str, str | bytes] = {}, rpc_timeout: timedelta | None = None, ) -> ActivityHandle[ReturnType]: ... @@ -1383,6 +1387,7 @@ async def start_activity( search_attributes: temporalio.common.TypedSearchAttributes | None = None, summary: str | None = None, priority: temporalio.common.Priority = temporalio.common.Priority.default, + start_delay: timedelta | None = None, rpc_metadata: Mapping[str, str | bytes] = {}, rpc_timeout: timedelta | None = None, ) -> ActivityHandle[ReturnType]: ... @@ -1406,6 +1411,7 @@ async def start_activity( search_attributes: temporalio.common.TypedSearchAttributes | None = None, summary: str | None = None, priority: temporalio.common.Priority = temporalio.common.Priority.default, + start_delay: timedelta | None = None, rpc_metadata: Mapping[str, str | bytes] = {}, rpc_timeout: timedelta | None = None, ) -> ActivityHandle[ReturnType]: ... @@ -1431,6 +1437,7 @@ async def start_activity( search_attributes: temporalio.common.TypedSearchAttributes | None = None, summary: str | None = None, priority: temporalio.common.Priority = temporalio.common.Priority.default, + start_delay: timedelta | None = None, rpc_metadata: Mapping[str, str | bytes] = {}, rpc_timeout: timedelta | None = None, ) -> ActivityHandle[Any]: ... @@ -1457,6 +1464,7 @@ async def start_activity( search_attributes: temporalio.common.TypedSearchAttributes | None = None, summary: str | None = None, priority: temporalio.common.Priority = temporalio.common.Priority.default, + start_delay: timedelta | None = None, rpc_metadata: Mapping[str, str | bytes] = {}, rpc_timeout: timedelta | None = None, ) -> ActivityHandle[ReturnType]: @@ -1485,6 +1493,8 @@ async def start_activity( summary: A single-line fixed summary for this activity that may appear in the UI/CLI. This can be in single-line Temporal markdown format. priority: Priority of the activity execution. + start_delay: Time to wait before dispatching the activity. + This delay is not applied to retry attempts. rpc_metadata: Headers used on the RPC call. rpc_timeout: Optional RPC deadline to set for the RPC call. @@ -1510,6 +1520,7 @@ async def start_activity( retry_policy=retry_policy, search_attributes=search_attributes, summary=summary, + start_delay=start_delay, headers={}, rpc_metadata=rpc_metadata, rpc_timeout=rpc_timeout, @@ -1535,6 +1546,7 @@ async def execute_activity( search_attributes: temporalio.common.TypedSearchAttributes | None = None, summary: str | None = None, priority: temporalio.common.Priority = temporalio.common.Priority.default, + start_delay: timedelta | None = None, rpc_metadata: Mapping[str, str | bytes] = {}, rpc_timeout: timedelta | None = None, ) -> ReturnType: ... @@ -1557,6 +1569,7 @@ async def execute_activity( search_attributes: temporalio.common.TypedSearchAttributes | None = None, summary: str | None = None, priority: temporalio.common.Priority = temporalio.common.Priority.default, + start_delay: timedelta | None = None, rpc_metadata: Mapping[str, str | bytes] = {}, rpc_timeout: timedelta | None = None, ) -> ReturnType: ... @@ -1580,6 +1593,7 @@ async def execute_activity( search_attributes: temporalio.common.TypedSearchAttributes | None = None, summary: str | None = None, priority: temporalio.common.Priority = temporalio.common.Priority.default, + start_delay: timedelta | None = None, rpc_metadata: Mapping[str, str | bytes] = {}, rpc_timeout: timedelta | None = None, ) -> ReturnType: ... @@ -1603,6 +1617,7 @@ async def execute_activity( search_attributes: temporalio.common.TypedSearchAttributes | None = None, summary: str | None = None, priority: temporalio.common.Priority = temporalio.common.Priority.default, + start_delay: timedelta | None = None, rpc_metadata: Mapping[str, str | bytes] = {}, rpc_timeout: timedelta | None = None, ) -> ReturnType: ... @@ -1626,6 +1641,7 @@ async def execute_activity( search_attributes: temporalio.common.TypedSearchAttributes | None = None, summary: str | None = None, priority: temporalio.common.Priority = temporalio.common.Priority.default, + start_delay: timedelta | None = None, rpc_metadata: Mapping[str, str | bytes] = {}, rpc_timeout: timedelta | None = None, ) -> ReturnType: ... @@ -1649,6 +1665,7 @@ async def execute_activity( search_attributes: temporalio.common.TypedSearchAttributes | None = None, summary: str | None = None, priority: temporalio.common.Priority = temporalio.common.Priority.default, + start_delay: timedelta | None = None, rpc_metadata: Mapping[str, str | bytes] = {}, rpc_timeout: timedelta | None = None, ) -> ReturnType: ... @@ -1674,6 +1691,7 @@ async def execute_activity( search_attributes: temporalio.common.TypedSearchAttributes | None = None, summary: str | None = None, priority: temporalio.common.Priority = temporalio.common.Priority.default, + start_delay: timedelta | None = None, rpc_metadata: Mapping[str, str | bytes] = {}, rpc_timeout: timedelta | None = None, ) -> Any: ... @@ -1700,6 +1718,7 @@ async def execute_activity( search_attributes: temporalio.common.TypedSearchAttributes | None = None, summary: str | None = None, priority: temporalio.common.Priority = temporalio.common.Priority.default, + start_delay: timedelta | None = None, rpc_metadata: Mapping[str, str | bytes] = {}, rpc_timeout: timedelta | None = None, ) -> ReturnType: @@ -1734,6 +1753,7 @@ async def execute_activity( search_attributes=search_attributes, summary=summary, priority=priority, + start_delay=start_delay, rpc_metadata=rpc_metadata, rpc_timeout=rpc_timeout, ) @@ -1757,6 +1777,7 @@ async def start_activity_class( search_attributes: temporalio.common.TypedSearchAttributes | None = None, summary: str | None = None, priority: temporalio.common.Priority = temporalio.common.Priority.default, + start_delay: timedelta | None = None, rpc_metadata: Mapping[str, str | bytes] = {}, rpc_timeout: timedelta | None = None, ) -> ActivityHandle[ReturnType]: ... @@ -1779,6 +1800,7 @@ async def start_activity_class( search_attributes: temporalio.common.TypedSearchAttributes | None = None, summary: str | None = None, priority: temporalio.common.Priority = temporalio.common.Priority.default, + start_delay: timedelta | None = None, rpc_metadata: Mapping[str, str | bytes] = {}, rpc_timeout: timedelta | None = None, ) -> ActivityHandle[ReturnType]: ... @@ -1802,6 +1824,7 @@ async def start_activity_class( search_attributes: temporalio.common.TypedSearchAttributes | None = None, summary: str | None = None, priority: temporalio.common.Priority = temporalio.common.Priority.default, + start_delay: timedelta | None = None, rpc_metadata: Mapping[str, str | bytes] = {}, rpc_timeout: timedelta | None = None, ) -> ActivityHandle[ReturnType]: ... @@ -1825,6 +1848,7 @@ async def start_activity_class( search_attributes: temporalio.common.TypedSearchAttributes | None = None, summary: str | None = None, priority: temporalio.common.Priority = temporalio.common.Priority.default, + start_delay: timedelta | None = None, rpc_metadata: Mapping[str, str | bytes] = {}, rpc_timeout: timedelta | None = None, ) -> ActivityHandle[ReturnType]: ... @@ -1848,6 +1872,7 @@ async def start_activity_class( search_attributes: temporalio.common.TypedSearchAttributes | None = None, summary: str | None = None, priority: temporalio.common.Priority = temporalio.common.Priority.default, + start_delay: timedelta | None = None, rpc_metadata: Mapping[str, str | bytes] = {}, rpc_timeout: timedelta | None = None, ) -> ActivityHandle[ReturnType]: ... @@ -1871,6 +1896,7 @@ async def start_activity_class( search_attributes: temporalio.common.TypedSearchAttributes | None = None, summary: str | None = None, priority: temporalio.common.Priority = temporalio.common.Priority.default, + start_delay: timedelta | None = None, rpc_metadata: Mapping[str, str | bytes] = {}, rpc_timeout: timedelta | None = None, ) -> ActivityHandle[ReturnType]: ... @@ -1894,6 +1920,7 @@ async def start_activity_class( search_attributes: temporalio.common.TypedSearchAttributes | None = None, summary: str | None = None, priority: temporalio.common.Priority = temporalio.common.Priority.default, + start_delay: timedelta | None = None, rpc_metadata: Mapping[str, str | bytes] = {}, rpc_timeout: timedelta | None = None, ) -> ActivityHandle[Any]: @@ -1921,6 +1948,7 @@ async def start_activity_class( search_attributes=search_attributes, summary=summary, priority=priority, + start_delay=start_delay, rpc_metadata=rpc_metadata, rpc_timeout=rpc_timeout, ) @@ -1943,6 +1971,7 @@ async def execute_activity_class( search_attributes: temporalio.common.TypedSearchAttributes | None = None, summary: str | None = None, priority: temporalio.common.Priority = temporalio.common.Priority.default, + start_delay: timedelta | None = None, rpc_metadata: Mapping[str, str | bytes] = {}, rpc_timeout: timedelta | None = None, ) -> ReturnType: ... @@ -1965,6 +1994,7 @@ async def execute_activity_class( search_attributes: temporalio.common.TypedSearchAttributes | None = None, summary: str | None = None, priority: temporalio.common.Priority = temporalio.common.Priority.default, + start_delay: timedelta | None = None, rpc_metadata: Mapping[str, str | bytes] = {}, rpc_timeout: timedelta | None = None, ) -> ReturnType: ... @@ -1988,6 +2018,7 @@ async def execute_activity_class( search_attributes: temporalio.common.TypedSearchAttributes | None = None, summary: str | None = None, priority: temporalio.common.Priority = temporalio.common.Priority.default, + start_delay: timedelta | None = None, rpc_metadata: Mapping[str, str | bytes] = {}, rpc_timeout: timedelta | None = None, ) -> ReturnType: ... @@ -2011,6 +2042,7 @@ async def execute_activity_class( search_attributes: temporalio.common.TypedSearchAttributes | None = None, summary: str | None = None, priority: temporalio.common.Priority = temporalio.common.Priority.default, + start_delay: timedelta | None = None, rpc_metadata: Mapping[str, str | bytes] = {}, rpc_timeout: timedelta | None = None, ) -> ReturnType: ... @@ -2034,6 +2066,7 @@ async def execute_activity_class( search_attributes: temporalio.common.TypedSearchAttributes | None = None, summary: str | None = None, priority: temporalio.common.Priority = temporalio.common.Priority.default, + start_delay: timedelta | None = None, rpc_metadata: Mapping[str, str | bytes] = {}, rpc_timeout: timedelta | None = None, ) -> ReturnType: ... @@ -2057,6 +2090,7 @@ async def execute_activity_class( search_attributes: temporalio.common.TypedSearchAttributes | None = None, summary: str | None = None, priority: temporalio.common.Priority = temporalio.common.Priority.default, + start_delay: timedelta | None = None, rpc_metadata: Mapping[str, str | bytes] = {}, rpc_timeout: timedelta | None = None, ) -> ReturnType: ... @@ -2080,6 +2114,7 @@ async def execute_activity_class( search_attributes: temporalio.common.TypedSearchAttributes | None = None, summary: str | None = None, priority: temporalio.common.Priority = temporalio.common.Priority.default, + start_delay: timedelta | None = None, rpc_metadata: Mapping[str, str | bytes] = {}, rpc_timeout: timedelta | None = None, ) -> Any: @@ -2107,6 +2142,7 @@ async def execute_activity_class( search_attributes=search_attributes, summary=summary, priority=priority, + start_delay=start_delay, rpc_metadata=rpc_metadata, rpc_timeout=rpc_timeout, ) @@ -2129,6 +2165,7 @@ async def start_activity_method( search_attributes: temporalio.common.TypedSearchAttributes | None = None, summary: str | None = None, priority: temporalio.common.Priority = temporalio.common.Priority.default, + start_delay: timedelta | None = None, rpc_metadata: Mapping[str, str | bytes] = {}, rpc_timeout: timedelta | None = None, ) -> ActivityHandle[ReturnType]: ... @@ -2152,6 +2189,7 @@ async def start_activity_method( search_attributes: temporalio.common.TypedSearchAttributes | None = None, summary: str | None = None, priority: temporalio.common.Priority = temporalio.common.Priority.default, + start_delay: timedelta | None = None, rpc_metadata: Mapping[str, str | bytes] = {}, rpc_timeout: timedelta | None = None, ) -> ActivityHandle[ReturnType]: ... @@ -2177,6 +2215,7 @@ async def start_activity_method( search_attributes: temporalio.common.TypedSearchAttributes | None = None, summary: str | None = None, priority: temporalio.common.Priority = temporalio.common.Priority.default, + start_delay: timedelta | None = None, rpc_metadata: Mapping[str, str | bytes] = {}, rpc_timeout: timedelta | None = None, ) -> ActivityHandle[ReturnType]: ... @@ -2200,6 +2239,7 @@ async def start_activity_method( search_attributes: temporalio.common.TypedSearchAttributes | None = None, summary: str | None = None, priority: temporalio.common.Priority = temporalio.common.Priority.default, + start_delay: timedelta | None = None, rpc_metadata: Mapping[str, str | bytes] = {}, rpc_timeout: timedelta | None = None, ) -> ActivityHandle[ReturnType]: ... @@ -2223,6 +2263,7 @@ async def start_activity_method( search_attributes: temporalio.common.TypedSearchAttributes | None = None, summary: str | None = None, priority: temporalio.common.Priority = temporalio.common.Priority.default, + start_delay: timedelta | None = None, rpc_metadata: Mapping[str, str | bytes] = {}, rpc_timeout: timedelta | None = None, ) -> ActivityHandle[Any]: @@ -2250,6 +2291,7 @@ async def start_activity_method( search_attributes=search_attributes, summary=summary, priority=priority, + start_delay=start_delay, rpc_metadata=rpc_metadata, rpc_timeout=rpc_timeout, ) @@ -2272,6 +2314,7 @@ async def execute_activity_method( search_attributes: temporalio.common.TypedSearchAttributes | None = None, summary: str | None = None, priority: temporalio.common.Priority = temporalio.common.Priority.default, + start_delay: timedelta | None = None, rpc_metadata: Mapping[str, str | bytes] = {}, rpc_timeout: timedelta | None = None, ) -> ReturnType: ... @@ -2295,6 +2338,7 @@ async def execute_activity_method( search_attributes: temporalio.common.TypedSearchAttributes | None = None, summary: str | None = None, priority: temporalio.common.Priority = temporalio.common.Priority.default, + start_delay: timedelta | None = None, rpc_metadata: Mapping[str, str | bytes] = {}, rpc_timeout: timedelta | None = None, ) -> ReturnType: ... @@ -2320,6 +2364,7 @@ async def execute_activity_method( search_attributes: temporalio.common.TypedSearchAttributes | None = None, summary: str | None = None, priority: temporalio.common.Priority = temporalio.common.Priority.default, + start_delay: timedelta | None = None, rpc_metadata: Mapping[str, str | bytes] = {}, rpc_timeout: timedelta | None = None, ) -> ReturnType: ... @@ -2343,6 +2388,7 @@ async def execute_activity_method( search_attributes: temporalio.common.TypedSearchAttributes | None = None, summary: str | None = None, priority: temporalio.common.Priority = temporalio.common.Priority.default, + start_delay: timedelta | None = None, rpc_metadata: Mapping[str, str | bytes] = {}, rpc_timeout: timedelta | None = None, ) -> ReturnType: ... @@ -2366,6 +2412,7 @@ async def execute_activity_method( search_attributes: temporalio.common.TypedSearchAttributes | None = None, summary: str | None = None, priority: temporalio.common.Priority = temporalio.common.Priority.default, + start_delay: timedelta | None = None, rpc_metadata: Mapping[str, str | bytes] = {}, rpc_timeout: timedelta | None = None, ) -> Any: @@ -2393,6 +2440,7 @@ async def execute_activity_method( search_attributes=search_attributes, summary=summary, priority=priority, + start_delay=start_delay, rpc_metadata=rpc_metadata, rpc_timeout=rpc_timeout, ) @@ -7441,6 +7489,7 @@ class StartActivityInput: priority: temporalio.common.Priority search_attributes: temporalio.common.TypedSearchAttributes | None summary: str | None + start_delay: timedelta | None headers: Mapping[str, temporalio.api.common.v1.Payload] rpc_metadata: Mapping[str, str | bytes] rpc_timeout: timedelta | None @@ -8400,6 +8449,8 @@ async def start_activity(self, input: StartActivityInput) -> ActivityHandle[Any] raise ValueError( "Activity must have start_to_close_timeout or schedule_to_close_timeout" ) + if input.start_delay is not None and input.start_delay < timedelta(0): + raise ValueError("start_delay must be non-negative") req = await self._build_start_activity_execution_request(input) resp: temporalio.api.workflowservice.v1.StartActivityExecutionResponse @@ -8476,6 +8527,8 @@ async def _build_start_activity_execution_request( req.schedule_to_start_timeout.FromTimedelta(input.schedule_to_start_timeout) if input.heartbeat_timeout is not None: req.heartbeat_timeout.FromTimedelta(input.heartbeat_timeout) + if input.start_delay is not None: + req.start_delay.FromTimedelta(input.start_delay) if input.retry_policy is not None: input.retry_policy.apply_to_proto(req.retry_policy) diff --git a/tests/test_activity.py b/tests/test_activity.py index 8e851c8b1..8ed4729ec 100644 --- a/tests/test_activity.py +++ b/tests/test_activity.py @@ -220,6 +220,7 @@ async def test_start_activity_calls_interceptor( activity_id = str(uuid.uuid4()) task_queue = str(uuid.uuid4()) + start_delay = timedelta(seconds=3) await intercepted_client.start_activity( increment, @@ -227,6 +228,7 @@ async def test_start_activity_calls_interceptor( id=activity_id, task_queue=task_queue, start_to_close_timeout=timedelta(seconds=5), + start_delay=start_delay, ) assert len(interceptor.start_activity_calls) == 1 @@ -234,6 +236,7 @@ async def test_start_activity_calls_interceptor( assert call.id == activity_id assert call.task_queue == task_queue assert call.activity_type == "increment" + assert call.start_delay == start_delay async def test_describe_activity_calls_interceptor( @@ -413,6 +416,18 @@ async def test_count_activities_calls_interceptor( assert call.query == query +async def test_start_activity_rejects_negative_start_delay(client: Client): + with pytest.raises(ValueError, match="start_delay must be non-negative"): + await client.start_activity( + increment, + args=(1,), + id=str(uuid.uuid4()), + task_queue=str(uuid.uuid4()), + start_to_close_timeout=timedelta(seconds=5), + start_delay=timedelta(seconds=-1), + ) + + async def test_get_result(client: Client, env: WorkflowEnvironment): if env.supports_time_skipping: pytest.skip( From 370608c489607b0ac90fa520cabff7d0d1c51b3a Mon Sep 17 00:00:00 2001 From: tconley1428 Date: Thu, 30 Apr 2026 10:38:38 -0700 Subject: [PATCH 069/226] Update Python and Cargo lockfiles (#1483) * Update lockfiles * Update pytest to 9 * Fix sandbox warning test for pytest 9 * Remove action count validation and try finally to delete schedules * Formatting * Langsmith ceiling of 0.7.34 until updated to match new API for aio_to_thread --- pyproject.toml | 4 +- temporalio/bridge/Cargo.lock | 4 +- tests/test_client.py | 45 +- tests/worker/workflow_sandbox/test_runner.py | 4 +- uv.lock | 1108 +++++++++--------- 5 files changed, 584 insertions(+), 581 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 1168373ea..ac9127e49 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -61,7 +61,7 @@ dev = [ "pydocstyle>=6.3.0,<7", "pydoctor>=25.10.1,<26", "pyright==1.1.403", - "pytest~=7.4", + "pytest~=9.0", "pytest-asyncio>=0.21,<0.22", "pytest-timeout~=2.2", "ruff>=0.5.0,<0.6", @@ -81,7 +81,7 @@ dev = [ "pytest-xdist>=3.6,<4", "moto[s3,server]>=5", "langgraph>=1.1.0", - "langsmith>=0.7.0,<0.8", + "langsmith>=0.7.0,<0.7.34", "setuptools<82", "opentelemetry-exporter-otlp-proto-grpc>=1.11.1,<2", "opentelemetry-semantic-conventions>=0.40b0,<1", diff --git a/temporalio/bridge/Cargo.lock b/temporalio/bridge/Cargo.lock index 829d1bc90..39403b364 100644 --- a/temporalio/bridge/Cargo.lock +++ b/temporalio/bridge/Cargo.lock @@ -2304,9 +2304,9 @@ checksum = "f87165f0995f63a9fbeea62b64d10b4d9d8e78ec6d7d51fb2125fda7bb36788f" [[package]] name = "rustls-webpki" -version = "0.103.10" +version = "0.103.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df33b2b81ac578cabaf06b89b0631153a3f416b0a886e8a7a1707fb51abbd1ef" +checksum = "61c429a8649f110dddef65e2a5ad240f747e85f7758a6bccc7e5777bd33f756e" dependencies = [ "aws-lc-rs", "ring", diff --git a/tests/test_client.py b/tests/test_client.py index 530c166f0..d3749b665 100644 --- a/tests/test_client.py +++ b/tests/test_client.py @@ -1136,30 +1136,27 @@ async def test_schedule_backfill( ) ], ) - # We accept both 1.24 and pre-1.24 action counts - assert (await handle.describe()).info.num_actions in [1, 2] - - # Add two more backfills and and -2m will be deduped - await handle.backfill( - # 3 actions on Server >= 1.24, 2 actions on Server < 1.24 - ScheduleBackfill( - start_at=begin - timedelta(minutes=4), - end_at=begin - timedelta(minutes=2), - overlap=ScheduleOverlapPolicy.ALLOW_ALL, - ), - # 3 actions on Server >= 1.24, 2 actions on Server < 1.24, except on - # Server >= 1.24, there is overlap with the prior backfill, so this is - # only net +2 actions, regardless of Server version. - ScheduleBackfill( - start_at=begin - timedelta(minutes=2), - end_at=begin, - overlap=ScheduleOverlapPolicy.ALLOW_ALL, - ), - ) - assert (await handle.describe()).info.num_actions in [5, 7] - - await handle.delete() - await assert_no_schedules(client) + try: + # Add two more backfills. Older servers treat the end time as + # exclusive, 1.24+ servers treat it as inclusive, and 1.31+ servers no + # longer dedupe the overlapping ALLOW_ALL backfills below. + await handle.backfill( + # 3 actions on Server >= 1.24, 2 actions on Server < 1.24 + ScheduleBackfill( + start_at=begin - timedelta(minutes=4), + end_at=begin - timedelta(minutes=2), + overlap=ScheduleOverlapPolicy.ALLOW_ALL, + ), + # 3 actions on Server >= 1.24, 2 actions on Server < 1.24. + ScheduleBackfill( + start_at=begin - timedelta(minutes=2), + end_at=begin, + overlap=ScheduleOverlapPolicy.ALLOW_ALL, + ), + ) + finally: + await handle.delete() + await assert_no_schedules(client) async def test_schedule_create_limited_actions_validation( diff --git a/tests/worker/workflow_sandbox/test_runner.py b/tests/worker/workflow_sandbox/test_runner.py index 44e58fa3c..288da0861 100644 --- a/tests/worker/workflow_sandbox/test_runner.py +++ b/tests/worker/workflow_sandbox/test_runner.py @@ -8,6 +8,7 @@ import sys import time import uuid +import warnings from collections.abc import Callable, Sequence from dataclasses import dataclass from datetime import date, datetime, timedelta @@ -645,7 +646,8 @@ async def test_workflow_sandbox_import_suppress_warnings(client: Client): workflows=[SupressWarningsLazyImportWorkflow], workflow_runner=SandboxedWorkflowRunner(restrictions), ) as worker: - with pytest.warns(None) as recorder: # type:ignore + with warnings.catch_warnings(record=True) as recorder: + warnings.simplefilter("always") await client.execute_workflow( SupressWarningsLazyImportWorkflow.run, id=f"workflow-{uuid.uuid4()}", diff --git a/uv.lock b/uv.lock index 4fba27fc0..ecb7e38f9 100644 --- a/uv.lock +++ b/uv.lock @@ -9,7 +9,7 @@ resolution-markers = [ ] [options] -exclude-newer = "2026-04-13T21:30:54.856039Z" +exclude-newer = "2026-04-23T15:55:57.051193Z" exclude-newer-span = "P1W" [options.exclude-newer-package] @@ -296,14 +296,15 @@ wheels = [ [[package]] name = "authlib" -version = "1.6.9" +version = "1.7.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "cryptography" }, + { name = "joserfc" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/af/98/00d3dd826d46959ad8e32af2dbb2398868fd9fd0683c26e56d0789bd0e68/authlib-1.6.9.tar.gz", hash = "sha256:d8f2421e7e5980cc1ddb4e32d3f5fa659cfaf60d8eaf3281ebed192e4ab74f04", size = 165134, upload-time = "2026-03-02T07:44:01.998Z" } +sdist = { url = "https://files.pythonhosted.org/packages/d9/82/4d0603f30c1b4629b1f091bb266b0d7986434891d6940a8c87f8098db24e/authlib-1.7.0.tar.gz", hash = "sha256:b3e326c9aa9cc3ea95fe7d89fd880722d3608da4d00e8a27e061e64b48d801d5", size = 175890, upload-time = "2026-04-18T11:00:28.559Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/53/23/b65f568ed0c22f1efacb744d2db1a33c8068f384b8c9b482b52ebdbc3ef6/authlib-1.6.9-py2.py3-none-any.whl", hash = "sha256:f08b4c14e08f0861dc18a32357b33fbcfd2ea86cfe3fe149484b4d764c4a0ac3", size = 244197, upload-time = "2026-03-02T07:44:00.307Z" }, + { url = "https://files.pythonhosted.org/packages/ca/48/c954218b2a250e23f178f10167c4173fecb5a75d2c206f0a67ba58006c26/authlib-1.7.0-py2.py3-none-any.whl", hash = "sha256:e36817afb02f6f0b6bf55f150782499ddd6ddf44b402bb055d3263cc65ac9ae0", size = 258779, upload-time = "2026-04-18T11:00:26.64Z" }, ] [[package]] @@ -317,7 +318,7 @@ wheels = [ [[package]] name = "aws-sam-translator" -version = "1.103.0" +version = "1.106.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "boto3" }, @@ -325,9 +326,9 @@ dependencies = [ { name = "pydantic" }, { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/d0/e3/82cc7240504b1c0d2d7ed7028b05ccceedb02932b8638c61a8372a5d875f/aws_sam_translator-1.103.0.tar.gz", hash = "sha256:8317b72ef412db581dc7846932a44dfc1729adea578d9307a3e6ece46a7882ca", size = 344881, upload-time = "2025-11-21T19:50:51.818Z" } +sdist = { url = "https://files.pythonhosted.org/packages/d3/52/feef23ec9392e2321ab889fa491a1a86d5818d35948bc331cd92dae0087c/aws_sam_translator-1.106.0.tar.gz", hash = "sha256:87712ced7eb6835fea2d4e9674ba7268494aa98f5b186ec5ad684245e2707ef7", size = 355440, upload-time = "2025-12-17T19:07:05.078Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/ce/86/6414c215ff0a10b33bf89622951e7d4413106320657535d2ba0e4f634661/aws_sam_translator-1.103.0-py3-none-any.whl", hash = "sha256:d4eb4a1efa62f00b253ee5f8c0084bd4b7687186c6a12338f900ebe07ff74dad", size = 403100, upload-time = "2025-11-21T19:50:50.528Z" }, + { url = "https://files.pythonhosted.org/packages/64/b9/8272f2a22ab1c225ded0fafc702adca0f6631777df9999f7b9b793c48feb/aws_sam_translator-1.106.0-py3-none-any.whl", hash = "sha256:09e58160cdba3539dd37be209bc2accf51f8b71f8d4cc5431e248f794b122644", size = 415433, upload-time = "2025-12-17T19:07:03.285Z" }, ] [[package]] @@ -451,11 +452,11 @@ filecache = [ [[package]] name = "certifi" -version = "2026.2.25" +version = "2026.4.22" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/af/2d/7bf41579a8986e348fa033a31cdd0e4121114f6bce2457e8876010b092dd/certifi-2026.2.25.tar.gz", hash = "sha256:e887ab5cee78ea814d3472169153c2d12cd43b14bd03329a39a9c6e2e80bfba7", size = 155029, upload-time = "2026-02-25T02:54:17.342Z" } +sdist = { url = "https://files.pythonhosted.org/packages/25/ee/6caf7a40c36a1220410afe15a1cc64993a1f864871f698c0f93acb72842a/certifi-2026.4.22.tar.gz", hash = "sha256:8d455352a37b71bf76a79caa83a3d6c25afee4a385d632127b6afb3963f1c580", size = 137077, upload-time = "2026-04-22T11:26:11.191Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/9a/3c/c17fb3ca2d9c3acff52e30b309f538586f9f5b9c9cf454f3845fc9af4881/certifi-2026.2.25-py3-none-any.whl", hash = "sha256:027692e4402ad994f1c42e52a4997a9763c646b73e4096e4d5d6db8af1d6f0fa", size = 153684, upload-time = "2026-02-25T02:54:15.766Z" }, + { url = "https://files.pythonhosted.org/packages/22/30/7cd8fdcdfbc5b869528b079bfb76dcdf6056b1a2097a662e5e8c04f42965/certifi-2026.4.22-py3-none-any.whl", hash = "sha256:3cb2210c8f88ba2318d29b0388d1023c8492ff72ecdde4ebdaddbb13a31b1c4a", size = 135707, upload-time = "2026-04-22T11:26:09.372Z" }, ] [[package]] @@ -542,7 +543,7 @@ wheels = [ [[package]] name = "cfn-lint" -version = "1.41.0" +version = "1.47.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "aws-sam-translator" }, @@ -554,9 +555,9 @@ dependencies = [ { name = "sympy" }, { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/ee/b5/436c192cdf8dbddd8e09a591384f126c5a47937c14953d87b1dacacd0543/cfn_lint-1.41.0.tar.gz", hash = "sha256:6feca1cf57f9ed2833bab68d9b1d38c8033611e571fa792e45ab4a39e2b8ab57", size = 3408534, upload-time = "2025-11-18T20:03:33.431Z" } +sdist = { url = "https://files.pythonhosted.org/packages/10/34/e66811016e7709cab78b0cf896437b922d7537986ac727344663b6cc2044/cfn_lint-1.47.1.tar.gz", hash = "sha256:b2eedbcee3aa104602f79933e3ad74c01f0fa1e226b70327118926fd78d8d3f1", size = 3672271, upload-time = "2026-03-24T15:59:34.526Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/cf/5e/81ef8f87894543210d783a495c8880cfb0b5baa0ee3bcc6d852f1b343863/cfn_lint-1.41.0-py3-none-any.whl", hash = "sha256:cd43f76f59a664b2bad580840827849fac0d56a3b80e9a41315d8ab5ff6b563a", size = 5674429, upload-time = "2025-11-18T20:03:31.083Z" }, + { url = "https://files.pythonhosted.org/packages/a5/88/19802ef0e1ef6259c4bc4b58226c0e7ff8b7ae93806ca32354c007e3480a/cfn_lint-1.47.1-py3-none-any.whl", hash = "sha256:3a4b5dba0fd03c24f2bc0e112a88ad90fa29014971e881b8f1e297d22f398a97", size = 5299292, upload-time = "2026-03-24T15:59:31.86Z" }, ] [[package]] @@ -686,14 +687,14 @@ wheels = [ [[package]] name = "click" -version = "8.3.2" +version = "8.3.3" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "colorama", marker = "sys_platform == 'win32'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/57/75/31212c6bf2503fdf920d87fee5d7a86a2e3bcf444984126f13d8e4016804/click-8.3.2.tar.gz", hash = "sha256:14162b8b3b3550a7d479eafa77dfd3c38d9dc8951f6f69c78913a8f9a7540fd5", size = 302856, upload-time = "2026-04-03T19:14:45.118Z" } +sdist = { url = "https://files.pythonhosted.org/packages/bb/63/f9e1ea081ce35720d8b92acde70daaedace594dc93b693c869e0d5910718/click-8.3.3.tar.gz", hash = "sha256:398329ad4837b2ff7cbe1dd166a4c0f8900c3ca3a218de04466f38f6497f18a2", size = 328061, upload-time = "2026-04-22T15:11:27.506Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/e4/20/71885d8b97d4f3dde17b1fdb92dbd4908b00541c5a3379787137285f602e/click-8.3.2-py3-none-any.whl", hash = "sha256:1924d2c27c5653561cd2cae4548d1406039cb79b858b747cfea24924bbc1616d", size = 108379, upload-time = "2026-04-03T19:14:43.505Z" }, + { url = "https://files.pythonhosted.org/packages/ae/44/c1221527f6a71a01ec6fbad7fa78f1d50dfa02217385cf0fa3eec7087d59/click-8.3.3-py3-none-any.whl", hash = "sha256:a2bf429bb3033c89fa4936ffb35d5cb471e3719e1f3c8a7c3fff0b8314305613", size = 110502, upload-time = "2026-04-22T15:11:25.044Z" }, ] [[package]] @@ -852,62 +853,62 @@ toml = [ [[package]] name = "cryptography" -version = "46.0.6" +version = "46.0.7" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "cffi", marker = "platform_python_implementation != 'PyPy'" }, { name = "typing-extensions", marker = "python_full_version < '3.11'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/a4/ba/04b1bd4218cbc58dc90ce967106d51582371b898690f3ae0402876cc4f34/cryptography-46.0.6.tar.gz", hash = "sha256:27550628a518c5c6c903d84f637fbecf287f6cb9ced3804838a1295dc1fd0759", size = 750542, upload-time = "2026-03-25T23:34:53.396Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/47/23/9285e15e3bc57325b0a72e592921983a701efc1ee8f91c06c5f0235d86d9/cryptography-46.0.6-cp311-abi3-macosx_10_9_universal2.whl", hash = "sha256:64235194bad039a10bb6d2d930ab3323baaec67e2ce36215fd0952fad0930ca8", size = 7176401, upload-time = "2026-03-25T23:33:22.096Z" }, - { url = "https://files.pythonhosted.org/packages/60/f8/e61f8f13950ab6195b31913b42d39f0f9afc7d93f76710f299b5ec286ae6/cryptography-46.0.6-cp311-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:26031f1e5ca62fcb9d1fcb34b2b60b390d1aacaa15dc8b895a9ed00968b97b30", size = 4275275, upload-time = "2026-03-25T23:33:23.844Z" }, - { url = "https://files.pythonhosted.org/packages/19/69/732a736d12c2631e140be2348b4ad3d226302df63ef64d30dfdb8db7ad1c/cryptography-46.0.6-cp311-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:9a693028b9cbe51b5a1136232ee8f2bc242e4e19d456ded3fa7c86e43c713b4a", size = 4425320, upload-time = "2026-03-25T23:33:25.703Z" }, - { url = "https://files.pythonhosted.org/packages/d4/12/123be7292674abf76b21ac1fc0e1af50661f0e5b8f0ec8285faac18eb99e/cryptography-46.0.6-cp311-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:67177e8a9f421aa2d3a170c3e56eca4e0128883cf52a071a7cbf53297f18b175", size = 4278082, upload-time = "2026-03-25T23:33:27.423Z" }, - { url = "https://files.pythonhosted.org/packages/5b/ba/d5e27f8d68c24951b0a484924a84c7cdaed7502bac9f18601cd357f8b1d2/cryptography-46.0.6-cp311-abi3-manylinux_2_28_ppc64le.whl", hash = "sha256:d9528b535a6c4f8ff37847144b8986a9a143585f0540fbcb1a98115b543aa463", size = 4926514, upload-time = "2026-03-25T23:33:29.206Z" }, - { url = "https://files.pythonhosted.org/packages/34/71/1ea5a7352ae516d5512d17babe7e1b87d9db5150b21f794b1377eac1edc0/cryptography-46.0.6-cp311-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:22259338084d6ae497a19bae5d4c66b7ca1387d3264d1c2c0e72d9e9b6a77b97", size = 4457766, upload-time = "2026-03-25T23:33:30.834Z" }, - { url = "https://files.pythonhosted.org/packages/01/59/562be1e653accee4fdad92c7a2e88fced26b3fdfce144047519bbebc299e/cryptography-46.0.6-cp311-abi3-manylinux_2_31_armv7l.whl", hash = "sha256:760997a4b950ff00d418398ad73fbc91aa2894b5c1db7ccb45b4f68b42a63b3c", size = 3986535, upload-time = "2026-03-25T23:33:33.02Z" }, - { url = "https://files.pythonhosted.org/packages/d6/8b/b1ebfeb788bf4624d36e45ed2662b8bd43a05ff62157093c1539c1288a18/cryptography-46.0.6-cp311-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:3dfa6567f2e9e4c5dceb8ccb5a708158a2a871052fa75c8b78cb0977063f1507", size = 4277618, upload-time = "2026-03-25T23:33:34.567Z" }, - { url = "https://files.pythonhosted.org/packages/dd/52/a005f8eabdb28df57c20f84c44d397a755782d6ff6d455f05baa2785bd91/cryptography-46.0.6-cp311-abi3-manylinux_2_34_ppc64le.whl", hash = "sha256:cdcd3edcbc5d55757e5f5f3d330dd00007ae463a7e7aa5bf132d1f22a4b62b19", size = 4890802, upload-time = "2026-03-25T23:33:37.034Z" }, - { url = "https://files.pythonhosted.org/packages/ec/4d/8e7d7245c79c617d08724e2efa397737715ca0ec830ecb3c91e547302555/cryptography-46.0.6-cp311-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:d4e4aadb7fc1f88687f47ca20bb7227981b03afaae69287029da08096853b738", size = 4457425, upload-time = "2026-03-25T23:33:38.904Z" }, - { url = "https://files.pythonhosted.org/packages/1d/5c/f6c3596a1430cec6f949085f0e1a970638d76f81c3ea56d93d564d04c340/cryptography-46.0.6-cp311-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:2b417edbe8877cda9022dde3a008e2deb50be9c407eef034aeeb3a8b11d9db3c", size = 4405530, upload-time = "2026-03-25T23:33:40.842Z" }, - { url = "https://files.pythonhosted.org/packages/7e/c9/9f9cea13ee2dbde070424e0c4f621c091a91ffcc504ffea5e74f0e1daeff/cryptography-46.0.6-cp311-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:380343e0653b1c9d7e1f55b52aaa2dbb2fdf2730088d48c43ca1c7c0abb7cc2f", size = 4667896, upload-time = "2026-03-25T23:33:42.781Z" }, - { url = "https://files.pythonhosted.org/packages/ad/b5/1895bc0821226f129bc74d00eccfc6a5969e2028f8617c09790bf89c185e/cryptography-46.0.6-cp311-abi3-win32.whl", hash = "sha256:bcb87663e1f7b075e48c3be3ecb5f0b46c8fc50b50a97cf264e7f60242dca3f2", size = 3026348, upload-time = "2026-03-25T23:33:45.021Z" }, - { url = "https://files.pythonhosted.org/packages/c3/f8/c9bcbf0d3e6ad288b9d9aa0b1dee04b063d19e8c4f871855a03ab3a297ab/cryptography-46.0.6-cp311-abi3-win_amd64.whl", hash = "sha256:6739d56300662c468fddb0e5e291f9b4d084bead381667b9e654c7dd81705124", size = 3483896, upload-time = "2026-03-25T23:33:46.649Z" }, - { url = "https://files.pythonhosted.org/packages/01/41/3a578f7fd5c70611c0aacba52cd13cb364a5dee895a5c1d467208a9380b0/cryptography-46.0.6-cp314-cp314t-macosx_10_9_universal2.whl", hash = "sha256:2ef9e69886cbb137c2aef9772c2e7138dc581fad4fcbcf13cc181eb5a3ab6275", size = 7117147, upload-time = "2026-03-25T23:33:48.249Z" }, - { url = "https://files.pythonhosted.org/packages/fa/87/887f35a6fca9dde90cad08e0de0c89263a8e59b2d2ff904fd9fcd8025b6f/cryptography-46.0.6-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:7f417f034f91dcec1cb6c5c35b07cdbb2ef262557f701b4ecd803ee8cefed4f4", size = 4266221, upload-time = "2026-03-25T23:33:49.874Z" }, - { url = "https://files.pythonhosted.org/packages/aa/a8/0a90c4f0b0871e0e3d1ed126aed101328a8a57fd9fd17f00fb67e82a51ca/cryptography-46.0.6-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:d24c13369e856b94892a89ddf70b332e0b70ad4a5c43cf3e9cb71d6d7ffa1f7b", size = 4408952, upload-time = "2026-03-25T23:33:52.128Z" }, - { url = "https://files.pythonhosted.org/packages/16/0b/b239701eb946523e4e9f329336e4ff32b1247e109cbab32d1a7b61da8ed7/cryptography-46.0.6-cp314-cp314t-manylinux_2_28_aarch64.whl", hash = "sha256:aad75154a7ac9039936d50cf431719a2f8d4ed3d3c277ac03f3339ded1a5e707", size = 4270141, upload-time = "2026-03-25T23:33:54.11Z" }, - { url = "https://files.pythonhosted.org/packages/0f/a8/976acdd4f0f30df7b25605f4b9d3d89295351665c2091d18224f7ad5cdbf/cryptography-46.0.6-cp314-cp314t-manylinux_2_28_ppc64le.whl", hash = "sha256:3c21d92ed15e9cfc6eb64c1f5a0326db22ca9c2566ca46d845119b45b4400361", size = 4904178, upload-time = "2026-03-25T23:33:55.725Z" }, - { url = "https://files.pythonhosted.org/packages/b1/1b/bf0e01a88efd0e59679b69f42d4afd5bced8700bb5e80617b2d63a3741af/cryptography-46.0.6-cp314-cp314t-manylinux_2_28_x86_64.whl", hash = "sha256:4668298aef7cddeaf5c6ecc244c2302a2b8e40f384255505c22875eebb47888b", size = 4441812, upload-time = "2026-03-25T23:33:57.364Z" }, - { url = "https://files.pythonhosted.org/packages/bb/8b/11df86de2ea389c65aa1806f331cae145f2ed18011f30234cc10ca253de8/cryptography-46.0.6-cp314-cp314t-manylinux_2_31_armv7l.whl", hash = "sha256:8ce35b77aaf02f3b59c90b2c8a05c73bac12cea5b4e8f3fbece1f5fddea5f0ca", size = 3963923, upload-time = "2026-03-25T23:33:59.361Z" }, - { url = "https://files.pythonhosted.org/packages/91/e0/207fb177c3a9ef6a8108f234208c3e9e76a6aa8cf20d51932916bd43bda0/cryptography-46.0.6-cp314-cp314t-manylinux_2_34_aarch64.whl", hash = "sha256:c89eb37fae9216985d8734c1afd172ba4927f5a05cfd9bf0e4863c6d5465b013", size = 4269695, upload-time = "2026-03-25T23:34:00.909Z" }, - { url = "https://files.pythonhosted.org/packages/21/5e/19f3260ed1e95bced52ace7501fabcd266df67077eeb382b79c81729d2d3/cryptography-46.0.6-cp314-cp314t-manylinux_2_34_ppc64le.whl", hash = "sha256:ed418c37d095aeddf5336898a132fba01091f0ac5844e3e8018506f014b6d2c4", size = 4869785, upload-time = "2026-03-25T23:34:02.796Z" }, - { url = "https://files.pythonhosted.org/packages/10/38/cd7864d79aa1d92ef6f1a584281433419b955ad5a5ba8d1eb6c872165bcb/cryptography-46.0.6-cp314-cp314t-manylinux_2_34_x86_64.whl", hash = "sha256:69cf0056d6947edc6e6760e5f17afe4bea06b56a9ac8a06de9d2bd6b532d4f3a", size = 4441404, upload-time = "2026-03-25T23:34:04.35Z" }, - { url = "https://files.pythonhosted.org/packages/09/0a/4fe7a8d25fed74419f91835cf5829ade6408fd1963c9eae9c4bce390ecbb/cryptography-46.0.6-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:8e7304c4f4e9490e11efe56af6713983460ee0780f16c63f219984dab3af9d2d", size = 4397549, upload-time = "2026-03-25T23:34:06.342Z" }, - { url = "https://files.pythonhosted.org/packages/5f/a0/7d738944eac6513cd60a8da98b65951f4a3b279b93479a7e8926d9cd730b/cryptography-46.0.6-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:b928a3ca837c77a10e81a814a693f2295200adb3352395fad024559b7be7a736", size = 4651874, upload-time = "2026-03-25T23:34:07.916Z" }, - { url = "https://files.pythonhosted.org/packages/cb/f1/c2326781ca05208845efca38bf714f76939ae446cd492d7613808badedf1/cryptography-46.0.6-cp314-cp314t-win32.whl", hash = "sha256:97c8115b27e19e592a05c45d0dd89c57f81f841cc9880e353e0d3bf25b2139ed", size = 3001511, upload-time = "2026-03-25T23:34:09.892Z" }, - { url = "https://files.pythonhosted.org/packages/c9/57/fe4a23eb549ac9d903bd4698ffda13383808ef0876cc912bcb2838799ece/cryptography-46.0.6-cp314-cp314t-win_amd64.whl", hash = "sha256:c797e2517cb7880f8297e2c0f43bb910e91381339336f75d2c1c2cbf811b70b4", size = 3471692, upload-time = "2026-03-25T23:34:11.613Z" }, - { url = "https://files.pythonhosted.org/packages/c4/cc/f330e982852403da79008552de9906804568ae9230da8432f7496ce02b71/cryptography-46.0.6-cp38-abi3-macosx_10_9_universal2.whl", hash = "sha256:12cae594e9473bca1a7aceb90536060643128bb274fcea0fc459ab90f7d1ae7a", size = 7162776, upload-time = "2026-03-25T23:34:13.308Z" }, - { url = "https://files.pythonhosted.org/packages/49/b3/dc27efd8dcc4bff583b3f01d4a3943cd8b5821777a58b3a6a5f054d61b79/cryptography-46.0.6-cp38-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:639301950939d844a9e1c4464d7e07f902fe9a7f6b215bb0d4f28584729935d8", size = 4270529, upload-time = "2026-03-25T23:34:15.019Z" }, - { url = "https://files.pythonhosted.org/packages/e6/05/e8d0e6eb4f0d83365b3cb0e00eb3c484f7348db0266652ccd84632a3d58d/cryptography-46.0.6-cp38-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:ed3775295fb91f70b4027aeba878d79b3e55c0b3e97eaa4de71f8f23a9f2eb77", size = 4414827, upload-time = "2026-03-25T23:34:16.604Z" }, - { url = "https://files.pythonhosted.org/packages/2f/97/daba0f5d2dc6d855e2dcb70733c812558a7977a55dd4a6722756628c44d1/cryptography-46.0.6-cp38-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:8927ccfbe967c7df312ade694f987e7e9e22b2425976ddbf28271d7e58845290", size = 4271265, upload-time = "2026-03-25T23:34:18.586Z" }, - { url = "https://files.pythonhosted.org/packages/89/06/fe1fce39a37ac452e58d04b43b0855261dac320a2ebf8f5260dd55b201a9/cryptography-46.0.6-cp38-abi3-manylinux_2_28_ppc64le.whl", hash = "sha256:b12c6b1e1651e42ab5de8b1e00dc3b6354fdfd778e7fa60541ddacc27cd21410", size = 4916800, upload-time = "2026-03-25T23:34:20.561Z" }, - { url = "https://files.pythonhosted.org/packages/ff/8a/b14f3101fe9c3592603339eb5d94046c3ce5f7fc76d6512a2d40efd9724e/cryptography-46.0.6-cp38-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:063b67749f338ca9c5a0b7fe438a52c25f9526b851e24e6c9310e7195aad3b4d", size = 4448771, upload-time = "2026-03-25T23:34:22.406Z" }, - { url = "https://files.pythonhosted.org/packages/01/b3/0796998056a66d1973fd52ee89dc1bb3b6581960a91ad4ac705f182d398f/cryptography-46.0.6-cp38-abi3-manylinux_2_31_armv7l.whl", hash = "sha256:02fad249cb0e090b574e30b276a3da6a149e04ee2f049725b1f69e7b8351ec70", size = 3978333, upload-time = "2026-03-25T23:34:24.281Z" }, - { url = "https://files.pythonhosted.org/packages/c5/3d/db200af5a4ffd08918cd55c08399dc6c9c50b0bc72c00a3246e099d3a849/cryptography-46.0.6-cp38-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:7e6142674f2a9291463e5e150090b95a8519b2fb6e6aaec8917dd8d094ce750d", size = 4271069, upload-time = "2026-03-25T23:34:25.895Z" }, - { url = "https://files.pythonhosted.org/packages/d7/18/61acfd5b414309d74ee838be321c636fe71815436f53c9f0334bf19064fa/cryptography-46.0.6-cp38-abi3-manylinux_2_34_ppc64le.whl", hash = "sha256:456b3215172aeefb9284550b162801d62f5f264a081049a3e94307fe20792cfa", size = 4878358, upload-time = "2026-03-25T23:34:27.67Z" }, - { url = "https://files.pythonhosted.org/packages/8b/65/5bf43286d566f8171917cae23ac6add941654ccf085d739195a4eacf1674/cryptography-46.0.6-cp38-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:341359d6c9e68834e204ceaf25936dffeafea3829ab80e9503860dcc4f4dac58", size = 4448061, upload-time = "2026-03-25T23:34:29.375Z" }, - { url = "https://files.pythonhosted.org/packages/e0/25/7e49c0fa7205cf3597e525d156a6bce5b5c9de1fd7e8cb01120e459f205a/cryptography-46.0.6-cp38-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:9a9c42a2723999a710445bc0d974e345c32adfd8d2fac6d8a251fa829ad31cfb", size = 4399103, upload-time = "2026-03-25T23:34:32.036Z" }, - { url = "https://files.pythonhosted.org/packages/44/46/466269e833f1c4718d6cd496ffe20c56c9c8d013486ff66b4f69c302a68d/cryptography-46.0.6-cp38-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:6617f67b1606dfd9fe4dbfa354a9508d4a6d37afe30306fe6c101b7ce3274b72", size = 4659255, upload-time = "2026-03-25T23:34:33.679Z" }, - { url = "https://files.pythonhosted.org/packages/0a/09/ddc5f630cc32287d2c953fc5d32705e63ec73e37308e5120955316f53827/cryptography-46.0.6-cp38-abi3-win32.whl", hash = "sha256:7f6690b6c55e9c5332c0b59b9c8a3fb232ebf059094c17f9019a51e9827df91c", size = 3010660, upload-time = "2026-03-25T23:34:35.418Z" }, - { url = "https://files.pythonhosted.org/packages/1b/82/ca4893968aeb2709aacfb57a30dec6fa2ab25b10fa9f064b8882ce33f599/cryptography-46.0.6-cp38-abi3-win_amd64.whl", hash = "sha256:79e865c642cfc5c0b3eb12af83c35c5aeff4fa5c672dc28c43721c2c9fdd2f0f", size = 3471160, upload-time = "2026-03-25T23:34:37.191Z" }, - { url = "https://files.pythonhosted.org/packages/2e/84/7ccff00ced5bac74b775ce0beb7d1be4e8637536b522b5df9b73ada42da2/cryptography-46.0.6-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:2ea0f37e9a9cf0df2952893ad145fd9627d326a59daec9b0802480fa3bcd2ead", size = 3475444, upload-time = "2026-03-25T23:34:38.944Z" }, - { url = "https://files.pythonhosted.org/packages/bc/1f/4c926f50df7749f000f20eede0c896769509895e2648db5da0ed55db711d/cryptography-46.0.6-pp311-pypy311_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:a3e84d5ec9ba01f8fd03802b2147ba77f0c8f2617b2aff254cedd551844209c8", size = 4218227, upload-time = "2026-03-25T23:34:40.871Z" }, - { url = "https://files.pythonhosted.org/packages/c6/65/707be3ffbd5f786028665c3223e86e11c4cda86023adbc56bd72b1b6bab5/cryptography-46.0.6-pp311-pypy311_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:12f0fa16cc247b13c43d56d7b35287ff1569b5b1f4c5e87e92cc4fcc00cd10c0", size = 4381399, upload-time = "2026-03-25T23:34:42.609Z" }, - { url = "https://files.pythonhosted.org/packages/f3/6d/73557ed0ef7d73d04d9aba745d2c8e95218213687ee5e76b7d236a5030fc/cryptography-46.0.6-pp311-pypy311_pp73-manylinux_2_34_aarch64.whl", hash = "sha256:50575a76e2951fe7dbd1f56d181f8c5ceeeb075e9ff88e7ad997d2f42af06e7b", size = 4217595, upload-time = "2026-03-25T23:34:44.205Z" }, - { url = "https://files.pythonhosted.org/packages/9e/c5/e1594c4eec66a567c3ac4400008108a415808be2ce13dcb9a9045c92f1a0/cryptography-46.0.6-pp311-pypy311_pp73-manylinux_2_34_x86_64.whl", hash = "sha256:90e5f0a7b3be5f40c3a0a0eafb32c681d8d2c181fc2a1bdabe9b3f611d9f6b1a", size = 4380912, upload-time = "2026-03-25T23:34:46.328Z" }, - { url = "https://files.pythonhosted.org/packages/1a/89/843b53614b47f97fe1abc13f9a86efa5ec9e275292c457af1d4a60dc80e0/cryptography-46.0.6-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:6728c49e3b2c180ef26f8e9f0a883a2c585638db64cf265b49c9ba10652d430e", size = 3409955, upload-time = "2026-03-25T23:34:48.465Z" }, +sdist = { url = "https://files.pythonhosted.org/packages/47/93/ac8f3d5ff04d54bc814e961a43ae5b0b146154c89c61b47bb07557679b18/cryptography-46.0.7.tar.gz", hash = "sha256:e4cfd68c5f3e0bfdad0d38e023239b96a2fe84146481852dffbcca442c245aa5", size = 750652, upload-time = "2026-04-08T01:57:54.692Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/0b/5d/4a8f770695d73be252331e60e526291e3df0c9b27556a90a6b47bccca4c2/cryptography-46.0.7-cp311-abi3-macosx_10_9_universal2.whl", hash = "sha256:ea42cbe97209df307fdc3b155f1b6fa2577c0defa8f1f7d3be7d31d189108ad4", size = 7179869, upload-time = "2026-04-08T01:56:17.157Z" }, + { url = "https://files.pythonhosted.org/packages/5f/45/6d80dc379b0bbc1f9d1e429f42e4cb9e1d319c7a8201beffd967c516ea01/cryptography-46.0.7-cp311-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:b36a4695e29fe69215d75960b22577197aca3f7a25b9cf9d165dcfe9d80bc325", size = 4275492, upload-time = "2026-04-08T01:56:19.36Z" }, + { url = "https://files.pythonhosted.org/packages/4a/9a/1765afe9f572e239c3469f2cb429f3ba7b31878c893b246b4b2994ffe2fe/cryptography-46.0.7-cp311-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:5ad9ef796328c5e3c4ceed237a183f5d41d21150f972455a9d926593a1dcb308", size = 4426670, upload-time = "2026-04-08T01:56:21.415Z" }, + { url = "https://files.pythonhosted.org/packages/8f/3e/af9246aaf23cd4ee060699adab1e47ced3f5f7e7a8ffdd339f817b446462/cryptography-46.0.7-cp311-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:73510b83623e080a2c35c62c15298096e2a5dc8d51c3b4e1740211839d0dea77", size = 4280275, upload-time = "2026-04-08T01:56:23.539Z" }, + { url = "https://files.pythonhosted.org/packages/0f/54/6bbbfc5efe86f9d71041827b793c24811a017c6ac0fd12883e4caa86b8ed/cryptography-46.0.7-cp311-abi3-manylinux_2_28_ppc64le.whl", hash = "sha256:cbd5fb06b62bd0721e1170273d3f4d5a277044c47ca27ee257025146c34cbdd1", size = 4928402, upload-time = "2026-04-08T01:56:25.624Z" }, + { url = "https://files.pythonhosted.org/packages/2d/cf/054b9d8220f81509939599c8bdbc0c408dbd2bdd41688616a20731371fe0/cryptography-46.0.7-cp311-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:420b1e4109cc95f0e5700eed79908cef9268265c773d3a66f7af1eef53d409ef", size = 4459985, upload-time = "2026-04-08T01:56:27.309Z" }, + { url = "https://files.pythonhosted.org/packages/f9/46/4e4e9c6040fb01c7467d47217d2f882daddeb8828f7df800cb806d8a2288/cryptography-46.0.7-cp311-abi3-manylinux_2_31_armv7l.whl", hash = "sha256:24402210aa54baae71d99441d15bb5a1919c195398a87b563df84468160a65de", size = 3990652, upload-time = "2026-04-08T01:56:29.095Z" }, + { url = "https://files.pythonhosted.org/packages/36/5f/313586c3be5a2fbe87e4c9a254207b860155a8e1f3cca99f9910008e7d08/cryptography-46.0.7-cp311-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:8a469028a86f12eb7d2fe97162d0634026d92a21f3ae0ac87ed1c4a447886c83", size = 4279805, upload-time = "2026-04-08T01:56:30.928Z" }, + { url = "https://files.pythonhosted.org/packages/69/33/60dfc4595f334a2082749673386a4d05e4f0cf4df8248e63b2c3437585f2/cryptography-46.0.7-cp311-abi3-manylinux_2_34_ppc64le.whl", hash = "sha256:9694078c5d44c157ef3162e3bf3946510b857df5a3955458381d1c7cfc143ddb", size = 4892883, upload-time = "2026-04-08T01:56:32.614Z" }, + { url = "https://files.pythonhosted.org/packages/c7/0b/333ddab4270c4f5b972f980adef4faa66951a4aaf646ca067af597f15563/cryptography-46.0.7-cp311-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:42a1e5f98abb6391717978baf9f90dc28a743b7d9be7f0751a6f56a75d14065b", size = 4459756, upload-time = "2026-04-08T01:56:34.306Z" }, + { url = "https://files.pythonhosted.org/packages/d2/14/633913398b43b75f1234834170947957c6b623d1701ffc7a9600da907e89/cryptography-46.0.7-cp311-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:91bbcb08347344f810cbe49065914fe048949648f6bd5c2519f34619142bbe85", size = 4410244, upload-time = "2026-04-08T01:56:35.977Z" }, + { url = "https://files.pythonhosted.org/packages/10/f2/19ceb3b3dc14009373432af0c13f46aa08e3ce334ec6eff13492e1812ccd/cryptography-46.0.7-cp311-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:5d1c02a14ceb9148cc7816249f64f623fbfee39e8c03b3650d842ad3f34d637e", size = 4674868, upload-time = "2026-04-08T01:56:38.034Z" }, + { url = "https://files.pythonhosted.org/packages/1a/bb/a5c213c19ee94b15dfccc48f363738633a493812687f5567addbcbba9f6f/cryptography-46.0.7-cp311-abi3-win32.whl", hash = "sha256:d23c8ca48e44ee015cd0a54aeccdf9f09004eba9fc96f38c911011d9ff1bd457", size = 3026504, upload-time = "2026-04-08T01:56:39.666Z" }, + { url = "https://files.pythonhosted.org/packages/2b/02/7788f9fefa1d060ca68717c3901ae7fffa21ee087a90b7f23c7a603c32ae/cryptography-46.0.7-cp311-abi3-win_amd64.whl", hash = "sha256:397655da831414d165029da9bc483bed2fe0e75dde6a1523ec2fe63f3c46046b", size = 3488363, upload-time = "2026-04-08T01:56:41.893Z" }, + { url = "https://files.pythonhosted.org/packages/7b/56/15619b210e689c5403bb0540e4cb7dbf11a6bf42e483b7644e471a2812b3/cryptography-46.0.7-cp314-cp314t-macosx_10_9_universal2.whl", hash = "sha256:d151173275e1728cf7839aaa80c34fe550c04ddb27b34f48c232193df8db5842", size = 7119671, upload-time = "2026-04-08T01:56:44Z" }, + { url = "https://files.pythonhosted.org/packages/74/66/e3ce040721b0b5599e175ba91ab08884c75928fbeb74597dd10ef13505d2/cryptography-46.0.7-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:db0f493b9181c7820c8134437eb8b0b4792085d37dbb24da050476ccb664e59c", size = 4268551, upload-time = "2026-04-08T01:56:46.071Z" }, + { url = "https://files.pythonhosted.org/packages/03/11/5e395f961d6868269835dee1bafec6a1ac176505a167f68b7d8818431068/cryptography-46.0.7-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:ebd6daf519b9f189f85c479427bbd6e9c9037862cf8fe89ee35503bd209ed902", size = 4408887, upload-time = "2026-04-08T01:56:47.718Z" }, + { url = "https://files.pythonhosted.org/packages/40/53/8ed1cf4c3b9c8e611e7122fb56f1c32d09e1fff0f1d77e78d9ff7c82653e/cryptography-46.0.7-cp314-cp314t-manylinux_2_28_aarch64.whl", hash = "sha256:b7b412817be92117ec5ed95f880defe9cf18a832e8cafacf0a22337dc1981b4d", size = 4271354, upload-time = "2026-04-08T01:56:49.312Z" }, + { url = "https://files.pythonhosted.org/packages/50/46/cf71e26025c2e767c5609162c866a78e8a2915bbcfa408b7ca495c6140c4/cryptography-46.0.7-cp314-cp314t-manylinux_2_28_ppc64le.whl", hash = "sha256:fbfd0e5f273877695cb93baf14b185f4878128b250cc9f8e617ea0c025dfb022", size = 4905845, upload-time = "2026-04-08T01:56:50.916Z" }, + { url = "https://files.pythonhosted.org/packages/c0/ea/01276740375bac6249d0a971ebdf6b4dc9ead0ee0a34ef3b5a88c1a9b0d4/cryptography-46.0.7-cp314-cp314t-manylinux_2_28_x86_64.whl", hash = "sha256:ffca7aa1d00cf7d6469b988c581598f2259e46215e0140af408966a24cf086ce", size = 4444641, upload-time = "2026-04-08T01:56:52.882Z" }, + { url = "https://files.pythonhosted.org/packages/3d/4c/7d258f169ae71230f25d9f3d06caabcff8c3baf0978e2b7d65e0acac3827/cryptography-46.0.7-cp314-cp314t-manylinux_2_31_armv7l.whl", hash = "sha256:60627cf07e0d9274338521205899337c5d18249db56865f943cbe753aa96f40f", size = 3967749, upload-time = "2026-04-08T01:56:54.597Z" }, + { url = "https://files.pythonhosted.org/packages/b5/2a/2ea0767cad19e71b3530e4cad9605d0b5e338b6a1e72c37c9c1ceb86c333/cryptography-46.0.7-cp314-cp314t-manylinux_2_34_aarch64.whl", hash = "sha256:80406c3065e2c55d7f49a9550fe0c49b3f12e5bfff5dedb727e319e1afb9bf99", size = 4270942, upload-time = "2026-04-08T01:56:56.416Z" }, + { url = "https://files.pythonhosted.org/packages/41/3d/fe14df95a83319af25717677e956567a105bb6ab25641acaa093db79975d/cryptography-46.0.7-cp314-cp314t-manylinux_2_34_ppc64le.whl", hash = "sha256:c5b1ccd1239f48b7151a65bc6dd54bcfcc15e028c8ac126d3fada09db0e07ef1", size = 4871079, upload-time = "2026-04-08T01:56:58.31Z" }, + { url = "https://files.pythonhosted.org/packages/9c/59/4a479e0f36f8f378d397f4eab4c850b4ffb79a2f0d58704b8fa0703ddc11/cryptography-46.0.7-cp314-cp314t-manylinux_2_34_x86_64.whl", hash = "sha256:d5f7520159cd9c2154eb61eb67548ca05c5774d39e9c2c4339fd793fe7d097b2", size = 4443999, upload-time = "2026-04-08T01:57:00.508Z" }, + { url = "https://files.pythonhosted.org/packages/28/17/b59a741645822ec6d04732b43c5d35e4ef58be7bfa84a81e5ae6f05a1d33/cryptography-46.0.7-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:fcd8eac50d9138c1d7fc53a653ba60a2bee81a505f9f8850b6b2888555a45d0e", size = 4399191, upload-time = "2026-04-08T01:57:02.654Z" }, + { url = "https://files.pythonhosted.org/packages/59/6a/bb2e166d6d0e0955f1e9ff70f10ec4b2824c9cfcdb4da772c7dd69cc7d80/cryptography-46.0.7-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:65814c60f8cc400c63131584e3e1fad01235edba2614b61fbfbfa954082db0ee", size = 4655782, upload-time = "2026-04-08T01:57:04.592Z" }, + { url = "https://files.pythonhosted.org/packages/95/b6/3da51d48415bcb63b00dc17c2eff3a651b7c4fed484308d0f19b30e8cb2c/cryptography-46.0.7-cp314-cp314t-win32.whl", hash = "sha256:fdd1736fed309b4300346f88f74cd120c27c56852c3838cab416e7a166f67298", size = 3002227, upload-time = "2026-04-08T01:57:06.91Z" }, + { url = "https://files.pythonhosted.org/packages/32/a8/9f0e4ed57ec9cebe506e58db11ae472972ecb0c659e4d52bbaee80ca340a/cryptography-46.0.7-cp314-cp314t-win_amd64.whl", hash = "sha256:e06acf3c99be55aa3b516397fe42f5855597f430add9c17fa46bf2e0fb34c9bb", size = 3475332, upload-time = "2026-04-08T01:57:08.807Z" }, + { url = "https://files.pythonhosted.org/packages/a7/7f/cd42fc3614386bc0c12f0cb3c4ae1fc2bbca5c9662dfed031514911d513d/cryptography-46.0.7-cp38-abi3-macosx_10_9_universal2.whl", hash = "sha256:462ad5cb1c148a22b2e3bcc5ad52504dff325d17daf5df8d88c17dda1f75f2a4", size = 7165618, upload-time = "2026-04-08T01:57:10.645Z" }, + { url = "https://files.pythonhosted.org/packages/a5/d0/36a49f0262d2319139d2829f773f1b97ef8aef7f97e6e5bd21455e5a8fb5/cryptography-46.0.7-cp38-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:84d4cced91f0f159a7ddacad249cc077e63195c36aac40b4150e7a57e84fffe7", size = 4270628, upload-time = "2026-04-08T01:57:12.885Z" }, + { url = "https://files.pythonhosted.org/packages/8a/6c/1a42450f464dda6ffbe578a911f773e54dd48c10f9895a23a7e88b3e7db5/cryptography-46.0.7-cp38-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:128c5edfe5e5938b86b03941e94fac9ee793a94452ad1365c9fc3f4f62216832", size = 4415405, upload-time = "2026-04-08T01:57:14.923Z" }, + { url = "https://files.pythonhosted.org/packages/9a/92/4ed714dbe93a066dc1f4b4581a464d2d7dbec9046f7c8b7016f5286329e2/cryptography-46.0.7-cp38-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:5e51be372b26ef4ba3de3c167cd3d1022934bc838ae9eaad7e644986d2a3d163", size = 4272715, upload-time = "2026-04-08T01:57:16.638Z" }, + { url = "https://files.pythonhosted.org/packages/b7/e6/a26b84096eddd51494bba19111f8fffe976f6a09f132706f8f1bf03f51f7/cryptography-46.0.7-cp38-abi3-manylinux_2_28_ppc64le.whl", hash = "sha256:cdf1a610ef82abb396451862739e3fc93b071c844399e15b90726ef7470eeaf2", size = 4918400, upload-time = "2026-04-08T01:57:19.021Z" }, + { url = "https://files.pythonhosted.org/packages/c7/08/ffd537b605568a148543ac3c2b239708ae0bd635064bab41359252ef88ed/cryptography-46.0.7-cp38-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:1d25aee46d0c6f1a501adcddb2d2fee4b979381346a78558ed13e50aa8a59067", size = 4450634, upload-time = "2026-04-08T01:57:21.185Z" }, + { url = "https://files.pythonhosted.org/packages/16/01/0cd51dd86ab5b9befe0d031e276510491976c3a80e9f6e31810cce46c4ad/cryptography-46.0.7-cp38-abi3-manylinux_2_31_armv7l.whl", hash = "sha256:cdfbe22376065ffcf8be74dc9a909f032df19bc58a699456a21712d6e5eabfd0", size = 3985233, upload-time = "2026-04-08T01:57:22.862Z" }, + { url = "https://files.pythonhosted.org/packages/92/49/819d6ed3a7d9349c2939f81b500a738cb733ab62fbecdbc1e38e83d45e12/cryptography-46.0.7-cp38-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:abad9dac36cbf55de6eb49badd4016806b3165d396f64925bf2999bcb67837ba", size = 4271955, upload-time = "2026-04-08T01:57:24.814Z" }, + { url = "https://files.pythonhosted.org/packages/80/07/ad9b3c56ebb95ed2473d46df0847357e01583f4c52a85754d1a55e29e4d0/cryptography-46.0.7-cp38-abi3-manylinux_2_34_ppc64le.whl", hash = "sha256:935ce7e3cfdb53e3536119a542b839bb94ec1ad081013e9ab9b7cfd478b05006", size = 4879888, upload-time = "2026-04-08T01:57:26.88Z" }, + { url = "https://files.pythonhosted.org/packages/b8/c7/201d3d58f30c4c2bdbe9b03844c291feb77c20511cc3586daf7edc12a47b/cryptography-46.0.7-cp38-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:35719dc79d4730d30f1c2b6474bd6acda36ae2dfae1e3c16f2051f215df33ce0", size = 4449961, upload-time = "2026-04-08T01:57:29.068Z" }, + { url = "https://files.pythonhosted.org/packages/a5/ef/649750cbf96f3033c3c976e112265c33906f8e462291a33d77f90356548c/cryptography-46.0.7-cp38-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:7bbc6ccf49d05ac8f7d7b5e2e2c33830d4fe2061def88210a126d130d7f71a85", size = 4401696, upload-time = "2026-04-08T01:57:31.029Z" }, + { url = "https://files.pythonhosted.org/packages/41/52/a8908dcb1a389a459a29008c29966c1d552588d4ae6d43f3a1a4512e0ebe/cryptography-46.0.7-cp38-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:a1529d614f44b863a7b480c6d000fe93b59acee9c82ffa027cfadc77521a9f5e", size = 4664256, upload-time = "2026-04-08T01:57:33.144Z" }, + { url = "https://files.pythonhosted.org/packages/4b/fa/f0ab06238e899cc3fb332623f337a7364f36f4bb3f2534c2bb95a35b132c/cryptography-46.0.7-cp38-abi3-win32.whl", hash = "sha256:f247c8c1a1fb45e12586afbb436ef21ff1e80670b2861a90353d9b025583d246", size = 3013001, upload-time = "2026-04-08T01:57:34.933Z" }, + { url = "https://files.pythonhosted.org/packages/d2/f1/00ce3bde3ca542d1acd8f8cfa38e446840945aa6363f9b74746394b14127/cryptography-46.0.7-cp38-abi3-win_amd64.whl", hash = "sha256:506c4ff91eff4f82bdac7633318a526b1d1309fc07ca76a3ad182cb5b686d6d3", size = 3472985, upload-time = "2026-04-08T01:57:36.714Z" }, + { url = "https://files.pythonhosted.org/packages/63/0c/dca8abb64e7ca4f6b2978769f6fea5ad06686a190cec381f0a796fdcaaba/cryptography-46.0.7-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:fc9ab8856ae6cf7c9358430e49b368f3108f050031442eaeb6b9d87e4dcf4e4f", size = 3476879, upload-time = "2026-04-08T01:57:38.664Z" }, + { url = "https://files.pythonhosted.org/packages/3a/ea/075aac6a84b7c271578d81a2f9968acb6e273002408729f2ddff517fed4a/cryptography-46.0.7-pp311-pypy311_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:d3b99c535a9de0adced13d159c5a9cf65c325601aa30f4be08afd680643e9c15", size = 4219700, upload-time = "2026-04-08T01:57:40.625Z" }, + { url = "https://files.pythonhosted.org/packages/6c/7b/1c55db7242b5e5612b29fc7a630e91ee7a6e3c8e7bf5406d22e206875fbd/cryptography-46.0.7-pp311-pypy311_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:d02c738dacda7dc2a74d1b2b3177042009d5cab7c7079db74afc19e56ca1b455", size = 4385982, upload-time = "2026-04-08T01:57:42.725Z" }, + { url = "https://files.pythonhosted.org/packages/cb/da/9870eec4b69c63ef5925bf7d8342b7e13bc2ee3d47791461c4e49ca212f4/cryptography-46.0.7-pp311-pypy311_pp73-manylinux_2_34_aarch64.whl", hash = "sha256:04959522f938493042d595a736e7dbdff6eb6cc2339c11465b3ff89343b65f65", size = 4219115, upload-time = "2026-04-08T01:57:44.939Z" }, + { url = "https://files.pythonhosted.org/packages/f4/72/05aa5832b82dd341969e9a734d1812a6aadb088d9eb6f0430fc337cc5a8f/cryptography-46.0.7-pp311-pypy311_pp73-manylinux_2_34_x86_64.whl", hash = "sha256:3986ac1dee6def53797289999eabe84798ad7817f3e97779b5061a95b0ee4968", size = 4385479, upload-time = "2026-04-08T01:57:46.86Z" }, + { url = "https://files.pythonhosted.org/packages/20/2a/1b016902351a523aa2bd446b50a5bc1175d7a7d1cf90fe2ef904f9b84ebc/cryptography-46.0.7-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:258514877e15963bd43b558917bc9f54cf7cf866c38aa576ebf47a77ddbc43a4", size = 3412829, upload-time = "2026-04-08T01:57:48.874Z" }, ] [[package]] @@ -948,11 +949,11 @@ wheels = [ [[package]] name = "docstring-parser" -version = "0.17.0" +version = "0.18.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/b2/9d/c3b43da9515bd270df0f80548d9944e389870713cc1fe2b8fb35fe2bcefd/docstring_parser-0.17.0.tar.gz", hash = "sha256:583de4a309722b3315439bb31d64ba3eebada841f2e2cee23b99df001434c912", size = 27442, upload-time = "2025-07-21T07:35:01.868Z" } +sdist = { url = "https://files.pythonhosted.org/packages/e0/4d/f332313098c1de1b2d2ff91cf2674415cc7cddab2ca1b01ae29774bd5fdf/docstring_parser-0.18.0.tar.gz", hash = "sha256:292510982205c12b1248696f44959db3cdd1740237a968ea1e2e7a900eeb2015", size = 29341, upload-time = "2026-04-14T04:09:19.867Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/55/e2/2537ebcff11c1ee1ff17d8d0b6f4db75873e3b0fb32c2d4a2ee31ecb310a/docstring_parser-0.17.0-py3-none-any.whl", hash = "sha256:cf2569abd23dce8099b300f9b4fa8191e9582dda731fd533daf54c4551658708", size = 36896, upload-time = "2025-07-21T07:35:00.684Z" }, + { url = "https://files.pythonhosted.org/packages/a7/5f/ed01f9a3cdffbd5a008556fc7b2a08ddb1cc6ace7effa7340604b1d16699/docstring_parser-0.18.0-py3-none-any.whl", hash = "sha256:b3fcbed555c47d8479be0796ef7e19c2670d428d72e96da63f3a40122860374b", size = 22484, upload-time = "2026-04-14T04:09:18.638Z" }, ] [[package]] @@ -969,7 +970,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", marker = "python_full_version < '3.13'" }, ] 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 = [ @@ -987,7 +988,7 @@ wheels = [ [[package]] name = "fastapi" -version = "0.135.3" +version = "0.136.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "annotated-doc" }, @@ -996,9 +997,9 @@ dependencies = [ { name = "typing-extensions" }, { name = "typing-inspection" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/f7/e6/7adb4c5fa231e82c35b8f5741a9f2d055f520c29af5546fd70d3e8e1cd2e/fastapi-0.135.3.tar.gz", hash = "sha256:bd6d7caf1a2bdd8d676843cdcd2287729572a1ef524fc4d65c17ae002a1be654", size = 396524, upload-time = "2026-04-01T16:23:58.188Z" } +sdist = { url = "https://files.pythonhosted.org/packages/4e/d9/e66315807e41e69e7f6a1b42a162dada2f249c5f06ad3f1a95f84ab336ef/fastapi-0.136.0.tar.gz", hash = "sha256:cf08e067cc66e106e102d9ba659463abfac245200752f8a5b7b1e813de4ff73e", size = 396607, upload-time = "2026-04-16T11:47:13.623Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/84/a4/5caa2de7f917a04ada20018eccf60d6cc6145b0199d55ca3711b0fc08312/fastapi-0.135.3-py3-none-any.whl", hash = "sha256:9b0f590c813acd13d0ab43dd8494138eb58e484bfac405db1f3187cfc5810d98", size = 117734, upload-time = "2026-04-01T16:23:59.328Z" }, + { url = "https://files.pythonhosted.org/packages/26/a3/0bd5f0cdb0bbc92650e8dc457e9250358411ee5d1b65e42b6632387daf81/fastapi-0.136.0-py3-none-any.whl", hash = "sha256:8793d44ec7378e2be07f8a013cf7f7aa47d6327d0dfe9804862688ec4541a6b4", size = 117556, upload-time = "2026-04-16T11:47:11.922Z" }, ] [[package]] @@ -1066,11 +1067,11 @@ wheels = [ [[package]] name = "filelock" -version = "3.25.2" +version = "3.29.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/94/b8/00651a0f559862f3bb7d6f7477b192afe3f583cc5e26403b44e59a55ab34/filelock-3.25.2.tar.gz", hash = "sha256:b64ece2b38f4ca29dd3e810287aa8c48182bbecd1ae6e9ae126c9b35f1382694", size = 40480, upload-time = "2026-03-11T20:45:38.487Z" } +sdist = { url = "https://files.pythonhosted.org/packages/b5/fe/997687a931ab51049acce6fa1f23e8f01216374ea81374ddee763c493db5/filelock-3.29.0.tar.gz", hash = "sha256:69974355e960702e789734cb4871f884ea6fe50bd8404051a3530bc07809cf90", size = 57571, upload-time = "2026-04-19T15:39:10.068Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/a4/a5/842ae8f0c08b61d6484b52f99a03510a3a72d23141942d216ebe81fefbce/filelock-3.25.2-py3-none-any.whl", hash = "sha256:ca8afb0da15f229774c9ad1b455ed96e85a81373065fb10446672f64444ddf70", size = 26759, upload-time = "2026-03-11T20:45:37.437Z" }, + { url = "https://files.pythonhosted.org/packages/81/47/dd9a212ef6e343a6857485ffe25bba537304f1913bdbed446a23f7f592e1/filelock-3.29.0-py3-none-any.whl", hash = "sha256:96f5f6344709aa1572bbf631c640e4ebeeb519e08da902c39a001882f30ac258", size = 39812, upload-time = "2026-04-19T15:39:08.752Z" }, ] [[package]] @@ -1235,7 +1236,7 @@ wheels = [ [[package]] name = "google-adk" -version = "1.28.1" +version = "1.31.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "aiosqlite" }, @@ -1284,14 +1285,14 @@ dependencies = [ { name = "watchdog" }, { name = "websockets" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/83/bd/ce670dca7a32b1bc46410edece7781d8db06aa5a48d7323f1c2aa30384b6/google_adk-1.28.1.tar.gz", hash = "sha256:76e6ec4a13f981bd9c2c7782e8b37b0e973b570b699b750a52444998e8886ced", size = 2318960, upload-time = "2026-04-02T22:21:02.796Z" } +sdist = { url = "https://files.pythonhosted.org/packages/9b/f7/e2371e8a871202f47f8911992da7daf8623dd61e714e0af5c6fec019ba67/google_adk-1.31.1.tar.gz", hash = "sha256:e56416264f62e931709da6262bc9fe05140faeb7a889a2fe8f5684617e8a05c3", size = 2408228, upload-time = "2026-04-21T02:06:48.623Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/7e/51/1926ef771b3223fcd0ff0568c9f5429d45239cdc6f09d9ecbb7a4cc69c1f/google_adk-1.28.1-py3-none-any.whl", hash = "sha256:ee7cdf90ba05737be3a2aa4867804324a02f2918bd810e746fe6416184e11511", size = 2729150, upload-time = "2026-04-02T22:21:01.096Z" }, + { url = "https://files.pythonhosted.org/packages/c8/02/6e7b88b122708569004ac024ec7f6773cc9d10ce1b086a4a6668a95ca142/google_adk-1.31.1-py3-none-any.whl", hash = "sha256:8f5d9c67c9a87832c2fe581bd4b1248dddf8964c98351a38e2663f0999bc7209", size = 2850553, upload-time = "2026-04-21T02:06:45.992Z" }, ] [[package]] name = "google-api-core" -version = "2.30.2" +version = "2.30.3" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "google-auth" }, @@ -1300,9 +1301,9 @@ dependencies = [ { name = "protobuf" }, { name = "requests" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/1a/2e/83ca41eb400eb228f9279ec14ed66f6475218b59af4c6daec2d5a509fe83/google_api_core-2.30.2.tar.gz", hash = "sha256:9a8113e1a88bdc09a7ff629707f2214d98d61c7f6ceb0ea38c42a095d02dc0f9", size = 176862, upload-time = "2026-04-02T21:23:44.876Z" } +sdist = { url = "https://files.pythonhosted.org/packages/16/ce/502a57fb0ec752026d24df1280b162294b22a0afb98a326084f9a979138b/google_api_core-2.30.3.tar.gz", hash = "sha256:e601a37f148585319b26db36e219df68c5d07b6382cff2d580e83404e44d641b", size = 177001, upload-time = "2026-04-10T00:41:28.035Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/84/e1/ebd5100cbb202e561c0c8b59e485ef3bd63fa9beb610f3fdcaea443f0288/google_api_core-2.30.2-py3-none-any.whl", hash = "sha256:a4c226766d6af2580577db1f1a51bf53cd262f722b49731ce7414c43068a9594", size = 173236, upload-time = "2026-04-02T21:23:06.395Z" }, + { url = "https://files.pythonhosted.org/packages/03/15/e56f351cf6ef1cfea58e6ac226a7318ed1deb2218c4b3cc9bd9e4b786c5a/google_api_core-2.30.3-py3-none-any.whl", hash = "sha256:a85761ba72c444dad5d611c2220633480b2b6be2521eca69cca2dbb3ffd6bfe8", size = 173274, upload-time = "2026-04-09T22:57:16.198Z" }, ] [package.optional-dependencies] @@ -1313,7 +1314,7 @@ grpc = [ [[package]] name = "google-api-python-client" -version = "2.193.0" +version = "2.194.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "google-api-core" }, @@ -1322,22 +1323,22 @@ dependencies = [ { name = "httplib2" }, { name = "uritemplate" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/90/f4/e14b6815d3b1885328dd209676a3a4c704882743ac94e18ef0093894f5c8/google_api_python_client-2.193.0.tar.gz", hash = "sha256:8f88d16e89d11341e0a8b199cafde0fb7e6b44260dffb88d451577cbd1bb5d33", size = 14281006, upload-time = "2026-03-17T18:25:29.415Z" } +sdist = { url = "https://files.pythonhosted.org/packages/60/ab/e83af0eb043e4ccc49571ca7a6a49984e9d00f4e9e6e6f1238d60bc84dce/google_api_python_client-2.194.0.tar.gz", hash = "sha256:db92647bd1a90f40b79c9618461553c2b20b6a43ce7395fa6de07132dc14f023", size = 14443469, upload-time = "2026-04-08T23:07:35.757Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/f0/6d/fe75167797790a56d17799b75e1129bb93f7ff061efc7b36e9731bd4be2b/google_api_python_client-2.193.0-py3-none-any.whl", hash = "sha256:c42aa324b822109901cfecab5dc4fc3915d35a7b376835233c916c70610322db", size = 14856490, upload-time = "2026-03-17T18:25:26.608Z" }, + { url = "https://files.pythonhosted.org/packages/b0/34/5a624e49f179aa5b0cb87b2ce8093960299030ff40423bfbde09360eb908/google_api_python_client-2.194.0-py3-none-any.whl", hash = "sha256:61eaaac3b8fc8fdf11c08af87abc3d1342d1b37319cc1b57405f86ef7697e717", size = 15016514, upload-time = "2026-04-08T23:07:33.093Z" }, ] [[package]] name = "google-auth" -version = "2.49.1" +version = "2.49.2" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "cryptography" }, { name = "pyasn1-modules" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/ea/80/6a696a07d3d3b0a92488933532f03dbefa4a24ab80fb231395b9a2a1be77/google_auth-2.49.1.tar.gz", hash = "sha256:16d40da1c3c5a0533f57d268fe72e0ebb0ae1cc3b567024122651c045d879b64", size = 333825, upload-time = "2026-03-12T19:30:58.135Z" } +sdist = { url = "https://files.pythonhosted.org/packages/c6/fc/e925290a1ad95c975c459e2df070fac2b90954e13a0370ac505dff78cb99/google_auth-2.49.2.tar.gz", hash = "sha256:c1ae38500e73065dcae57355adb6278cf8b5c8e391994ae9cbadbcb9631ab409", size = 333958, upload-time = "2026-04-10T00:41:21.888Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/e9/eb/c6c2478d8a8d633460be40e2a8a6f8f429171997a35a96f81d3b680dec83/google_auth-2.49.1-py3-none-any.whl", hash = "sha256:195ebe3dca18eddd1b3db5edc5189b76c13e96f29e73043b923ebcf3f1a860f7", size = 240737, upload-time = "2026-03-12T19:30:53.159Z" }, + { url = "https://files.pythonhosted.org/packages/73/76/d241a5c927433420507215df6cac1b1fa4ac0ba7a794df42a84326c68da8/google_auth-2.49.2-py3-none-any.whl", hash = "sha256:c2720924dfc82dedb962c9f52cabb2ab16714fd0a6a707e40561d217574ed6d5", size = 240638, upload-time = "2026-04-10T00:41:14.501Z" }, ] [package.optional-dependencies] @@ -1363,7 +1364,7 @@ wheels = [ [[package]] name = "google-cloud-aiplatform" -version = "1.145.0" +version = "1.148.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "docstring-parser" }, @@ -1379,9 +1380,9 @@ dependencies = [ { name = "pydantic" }, { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/26/e5/6442d9d2c019456638825d4665b1e87ec4eaf1d182950ba426d0f0210eab/google_cloud_aiplatform-1.145.0.tar.gz", hash = "sha256:7894c4f3d2684bdb60e9a122004c01678e3b585174a27298ae7a3ed1e5eaf3bd", size = 10222904, upload-time = "2026-04-02T14:06:58.322Z" } +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/3d/c6/23e98d3407d5e2416a3dfaecb0a053da899848c50db69e5f2b61a555ce06/google_cloud_aiplatform-1.145.0-py2.py3-none-any.whl", hash = "sha256:4d1c31797a8bd8f3342ed5f186dd30d1f6bca73ddbee2bde452777100d2ddc11", size = 8396640, upload-time = "2026-04-02T14:06:54.125Z" }, + { 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] @@ -1582,7 +1583,7 @@ wheels = [ [[package]] name = "google-cloud-pubsub" -version = "2.36.0" +version = "2.37.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "google-api-core", extra = ["grpc"] }, @@ -1595,9 +1596,9 @@ dependencies = [ { name = "proto-plus" }, { name = "protobuf" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/4e/8d/f5cece431daaa2024129569ed35e6eb90a72bb51f0c96e5c7f5cab6d34d7/google_cloud_pubsub-2.36.0.tar.gz", hash = "sha256:96e057e5f83433ce428852095d652c2f7fc193f0f77db1f27cc39186fe69c1f4", size = 401324, upload-time = "2026-03-12T19:31:02.099Z" } +sdist = { url = "https://files.pythonhosted.org/packages/50/89/558c48382d6875335ea6cd7f6409acfbf256b9f7fbc2ad1c19976aabdb1f/google_cloud_pubsub-2.37.0.tar.gz", hash = "sha256:7c5ba9beb5236e2b83c091dd6171423dc7d6d0e989391bd09f60dbd242b29f10", size = 403391, upload-time = "2026-04-10T00:41:17.799Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/93/fd/d0a8f0f93a4d115282ecdd8ef0267e4611bde6ca29c9dba803f3ebae7115/google_cloud_pubsub-2.36.0-py3-none-any.whl", hash = "sha256:d6726ccf9373924e0746338dadf8244b9aa1a97a24130b59a2106c926ea37598", size = 323364, upload-time = "2026-03-12T19:30:48.077Z" }, + { url = "https://files.pythonhosted.org/packages/64/f1/bb7162ec50971b1d252e6837d05f64f185d5cfe4e08de8f706e363c305d9/google_cloud_pubsub-2.37.0-py3-none-any.whl", hash = "sha256:dd912422cf66e4ffb423b0d5391ca81bdfa408eb0f21f57adecdb6fb3b1e0bb1", size = 325136, upload-time = "2026-04-10T00:41:01.391Z" }, ] [[package]] @@ -1636,7 +1637,7 @@ wheels = [ [[package]] name = "google-cloud-spanner" -version = "3.64.0" +version = "3.65.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "google-api-core", extra = ["grpc"] }, @@ -1653,9 +1654,9 @@ dependencies = [ { name = "protobuf" }, { name = "sqlparse" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/cf/67/573b14674bd74c8f0630125e13fd52791c76e6a34f21862358913fa41742/google_cloud_spanner-3.64.0.tar.gz", hash = "sha256:02c26601eaaef6abba78efe5c55187b16550aeab0671ed0a65ab2d78bf7c019e", size = 884721, upload-time = "2026-04-01T16:14:38.479Z" } +sdist = { url = "https://files.pythonhosted.org/packages/0d/90/b3e3c9c7b1a5ebc76d780fcda58e3a27208d5a10c6c5b78fab64dc5ea5f9/google_cloud_spanner-3.65.0.tar.gz", hash = "sha256:434139bd1439528398cd2a96e390a57182420747c214a33f317bbac64afd9c5c", size = 889154, upload-time = "2026-04-13T22:14:34.416Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/23/93/0ae1f0edfb9d9a0fc85d234b085b1cd7a3c5444f5bb85f1315f76c654313/google_cloud_spanner-3.64.0-py3-none-any.whl", hash = "sha256:9dd8b268c511def6bef118f9d8d9cbea98509727d13388a8365d5b72e13acf7c", size = 607319, upload-time = "2026-04-01T16:14:36.224Z" }, + { url = "https://files.pythonhosted.org/packages/be/c6/0f0806253de7e1ef5943a9e30df7798c0f5dd6e840707a899975e17d4c60/google_cloud_spanner-3.65.0-py3-none-any.whl", hash = "sha256:67ca892698d9530d10c682be7c38265089088b57272af3e57f1ea7afb9e88eff", size = 614036, upload-time = "2026-04-13T22:14:32.533Z" }, ] [[package]] @@ -1744,7 +1745,7 @@ wheels = [ [[package]] name = "google-genai" -version = "1.70.0" +version = "1.73.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "anyio" }, @@ -1758,9 +1759,9 @@ dependencies = [ { name = "typing-extensions" }, { name = "websockets" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/74/dd/28e4682904b183acbfad3fe6409f13a42f69bb8eab6e882d3bcbea1dde01/google_genai-1.70.0.tar.gz", hash = "sha256:36b67b0fc6f319e08d1f1efd808b790107b1809c8743a05d55dfcf9d9fad7719", size = 519550, upload-time = "2026-04-01T10:52:46.487Z" } +sdist = { url = "https://files.pythonhosted.org/packages/3d/d8/40f5f107e5a2976bbac52d421f04d14fc221b55a8f05e66be44b2f739fe6/google_genai-1.73.1.tar.gz", hash = "sha256:b637e3a3b9e2eccc46f27136d470165803de84eca52abfed2e7352081a4d5a15", size = 530998, upload-time = "2026-04-14T21:06:19.153Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/36/a3/d4564c8a9beaf6a3cef8d70fa6354318572cebfee65db4f01af0d41f45ba/google_genai-1.70.0-py3-none-any.whl", hash = "sha256:b74c24549d8b4208f4c736fd11857374788e1ffffc725de45d706e35c97fceee", size = 760584, upload-time = "2026-04-01T10:52:44.349Z" }, + { url = "https://files.pythonhosted.org/packages/65/af/508e0528015240d710c6763f7c89ff44fab9a94a80b4377e265d692cbfd6/google_genai-1.73.1-py3-none-any.whl", hash = "sha256:af2d2287d25e42a187de19811ef33beb2e347c7e2bdb4dc8c467d78254e43a2c", size = 783595, upload-time = "2026-04-14T21:06:17.464Z" }, ] [[package]] @@ -1812,56 +1813,56 @@ wheels = [ [[package]] name = "greenlet" -version = "3.3.2" +version = "3.4.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/a3/51/1664f6b78fc6ebbd98019a1fd730e83fa78f2db7058f72b1463d3612b8db/greenlet-3.3.2.tar.gz", hash = "sha256:2eaf067fc6d886931c7962e8c6bede15d2f01965560f3359b27c80bde2d151f2", size = 188267, upload-time = "2026-02-20T20:54:15.531Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/38/3f/9859f655d11901e7b2996c6e3d33e0caa9a1d4572c3bc61ed0faa64b2f4c/greenlet-3.3.2-cp310-cp310-macosx_11_0_universal2.whl", hash = "sha256:9bc885b89709d901859cf95179ec9f6bb67a3d2bb1f0e88456461bd4b7f8fd0d", size = 277747, upload-time = "2026-02-20T20:16:21.325Z" }, - { url = "https://files.pythonhosted.org/packages/fb/07/cb284a8b5c6498dbd7cba35d31380bb123d7dceaa7907f606c8ff5993cbf/greenlet-3.3.2-cp310-cp310-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b568183cf65b94919be4438dc28416b234b678c608cafac8874dfeeb2a9bbe13", size = 579202, upload-time = "2026-02-20T20:47:28.955Z" }, - { url = "https://files.pythonhosted.org/packages/ed/45/67922992b3a152f726163b19f890a85129a992f39607a2a53155de3448b8/greenlet-3.3.2-cp310-cp310-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:527fec58dc9f90efd594b9b700662ed3fb2493c2122067ac9c740d98080a620e", size = 590620, upload-time = "2026-02-20T20:55:55.581Z" }, - { url = "https://files.pythonhosted.org/packages/ad/55/9f1ebb5a825215fadcc0f7d5073f6e79e3007e3282b14b22d6aba7ca6cb8/greenlet-3.3.2-cp310-cp310-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ad0c8917dd42a819fe77e6bdfcb84e3379c0de956469301d9fd36427a1ca501f", size = 591729, upload-time = "2026-02-20T20:20:58.395Z" }, - { url = "https://files.pythonhosted.org/packages/24/b4/21f5455773d37f94b866eb3cf5caed88d6cea6dd2c6e1f9c34f463cba3ec/greenlet-3.3.2-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:97245cc10e5515dbc8c3104b2928f7f02b6813002770cfaffaf9a6e0fc2b94ef", size = 1551946, upload-time = "2026-02-20T20:49:31.102Z" }, - { url = "https://files.pythonhosted.org/packages/00/68/91f061a926abead128fe1a87f0b453ccf07368666bd59ffa46016627a930/greenlet-3.3.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:8c1fdd7d1b309ff0da81d60a9688a8bd044ac4e18b250320a96fc68d31c209ca", size = 1618494, upload-time = "2026-02-20T20:21:06.541Z" }, - { url = "https://files.pythonhosted.org/packages/ac/78/f93e840cbaef8becaf6adafbaf1319682a6c2d8c1c20224267a5c6c8c891/greenlet-3.3.2-cp310-cp310-win_amd64.whl", hash = "sha256:5d0e35379f93a6d0222de929a25ab47b5eb35b5ef4721c2b9cbcc4036129ff1f", size = 230092, upload-time = "2026-02-20T20:17:09.379Z" }, - { url = "https://files.pythonhosted.org/packages/f3/47/16400cb42d18d7a6bb46f0626852c1718612e35dcb0dffa16bbaffdf5dd2/greenlet-3.3.2-cp311-cp311-macosx_11_0_universal2.whl", hash = "sha256:c56692189a7d1c7606cb794be0a8381470d95c57ce5be03fb3d0ef57c7853b86", size = 278890, upload-time = "2026-02-20T20:19:39.263Z" }, - { url = "https://files.pythonhosted.org/packages/a3/90/42762b77a5b6aa96cd8c0e80612663d39211e8ae8a6cd47c7f1249a66262/greenlet-3.3.2-cp311-cp311-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1ebd458fa8285960f382841da585e02201b53a5ec2bac6b156fc623b5ce4499f", size = 581120, upload-time = "2026-02-20T20:47:30.161Z" }, - { url = "https://files.pythonhosted.org/packages/bf/6f/f3d64f4fa0a9c7b5c5b3c810ff1df614540d5aa7d519261b53fba55d4df9/greenlet-3.3.2-cp311-cp311-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:a443358b33c4ec7b05b79a7c8b466f5d275025e750298be7340f8fc63dff2a55", size = 594363, upload-time = "2026-02-20T20:55:56.965Z" }, - { url = "https://files.pythonhosted.org/packages/72/83/3e06a52aca8128bdd4dcd67e932b809e76a96ab8c232a8b025b2850264c5/greenlet-3.3.2-cp311-cp311-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8e2cd90d413acbf5e77ae41e5d3c9b3ac1d011a756d7284d7f3f2b806bbd6358", size = 594156, upload-time = "2026-02-20T20:20:59.955Z" }, - { url = "https://files.pythonhosted.org/packages/70/79/0de5e62b873e08fe3cef7dbe84e5c4bc0e8ed0c7ff131bccb8405cd107c8/greenlet-3.3.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:442b6057453c8cb29b4fb36a2ac689382fc71112273726e2423f7f17dc73bf99", size = 1554649, upload-time = "2026-02-20T20:49:32.293Z" }, - { url = "https://files.pythonhosted.org/packages/5a/00/32d30dee8389dc36d42170a9c66217757289e2afb0de59a3565260f38373/greenlet-3.3.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:45abe8eb6339518180d5a7fa47fa01945414d7cca5ecb745346fc6a87d2750be", size = 1619472, upload-time = "2026-02-20T20:21:07.966Z" }, - { url = "https://files.pythonhosted.org/packages/f1/3a/efb2cf697fbccdf75b24e2c18025e7dfa54c4f31fab75c51d0fe79942cef/greenlet-3.3.2-cp311-cp311-win_amd64.whl", hash = "sha256:1e692b2dae4cc7077cbb11b47d258533b48c8fde69a33d0d8a82e2fe8d8531d5", size = 230389, upload-time = "2026-02-20T20:17:18.772Z" }, - { url = "https://files.pythonhosted.org/packages/e1/a1/65bbc059a43a7e2143ec4fc1f9e3f673e04f9c7b371a494a101422ac4fd5/greenlet-3.3.2-cp311-cp311-win_arm64.whl", hash = "sha256:02b0a8682aecd4d3c6c18edf52bc8e51eacdd75c8eac52a790a210b06aa295fd", size = 229645, upload-time = "2026-02-20T20:18:18.695Z" }, - { url = "https://files.pythonhosted.org/packages/ea/ab/1608e5a7578e62113506740b88066bf09888322a311cff602105e619bd87/greenlet-3.3.2-cp312-cp312-macosx_11_0_universal2.whl", hash = "sha256:ac8d61d4343b799d1e526db579833d72f23759c71e07181c2d2944e429eb09cd", size = 280358, upload-time = "2026-02-20T20:17:43.971Z" }, - { url = "https://files.pythonhosted.org/packages/a5/23/0eae412a4ade4e6623ff7626e38998cb9b11e9ff1ebacaa021e4e108ec15/greenlet-3.3.2-cp312-cp312-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3ceec72030dae6ac0c8ed7591b96b70410a8be370b6a477b1dbc072856ad02bd", size = 601217, upload-time = "2026-02-20T20:47:31.462Z" }, - { url = "https://files.pythonhosted.org/packages/f8/16/5b1678a9c07098ecb9ab2dd159fafaf12e963293e61ee8d10ecb55273e5e/greenlet-3.3.2-cp312-cp312-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:a2a5be83a45ce6188c045bcc44b0ee037d6a518978de9a5d97438548b953a1ac", size = 611792, upload-time = "2026-02-20T20:55:58.423Z" }, - { url = "https://files.pythonhosted.org/packages/50/1f/5155f55bd71cabd03765a4aac9ac446be129895271f73872c36ebd4b04b6/greenlet-3.3.2-cp312-cp312-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:43e99d1749147ac21dde49b99c9abffcbc1e2d55c67501465ef0930d6e78e070", size = 613875, upload-time = "2026-02-20T20:21:01.102Z" }, - { url = "https://files.pythonhosted.org/packages/fc/dd/845f249c3fcd69e32df80cdab059b4be8b766ef5830a3d0aa9d6cad55beb/greenlet-3.3.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:4c956a19350e2c37f2c48b336a3afb4bff120b36076d9d7fb68cb44e05d95b79", size = 1571467, upload-time = "2026-02-20T20:49:33.495Z" }, - { url = "https://files.pythonhosted.org/packages/2a/50/2649fe21fcc2b56659a452868e695634722a6655ba245d9f77f5656010bf/greenlet-3.3.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:6c6f8ba97d17a1e7d664151284cb3315fc5f8353e75221ed4324f84eb162b395", size = 1640001, upload-time = "2026-02-20T20:21:09.154Z" }, - { url = "https://files.pythonhosted.org/packages/9b/40/cc802e067d02af8b60b6771cea7d57e21ef5e6659912814babb42b864713/greenlet-3.3.2-cp312-cp312-win_amd64.whl", hash = "sha256:34308836d8370bddadb41f5a7ce96879b72e2fdfb4e87729330c6ab52376409f", size = 231081, upload-time = "2026-02-20T20:17:28.121Z" }, - { url = "https://files.pythonhosted.org/packages/58/2e/fe7f36ff1982d6b10a60d5e0740c759259a7d6d2e1dc41da6d96de32fff6/greenlet-3.3.2-cp312-cp312-win_arm64.whl", hash = "sha256:d3a62fa76a32b462a97198e4c9e99afb9ab375115e74e9a83ce180e7a496f643", size = 230331, upload-time = "2026-02-20T20:17:23.34Z" }, - { url = "https://files.pythonhosted.org/packages/ac/48/f8b875fa7dea7dd9b33245e37f065af59df6a25af2f9561efa8d822fde51/greenlet-3.3.2-cp313-cp313-macosx_11_0_universal2.whl", hash = "sha256:aa6ac98bdfd716a749b84d4034486863fd81c3abde9aa3cf8eff9127981a4ae4", size = 279120, upload-time = "2026-02-20T20:19:01.9Z" }, - { url = "https://files.pythonhosted.org/packages/49/8d/9771d03e7a8b1ee456511961e1b97a6d77ae1dea4a34a5b98eee706689d3/greenlet-3.3.2-cp313-cp313-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ab0c7e7901a00bc0a7284907273dc165b32e0d109a6713babd04471327ff7986", size = 603238, upload-time = "2026-02-20T20:47:32.873Z" }, - { url = "https://files.pythonhosted.org/packages/59/0e/4223c2bbb63cd5c97f28ffb2a8aee71bdfb30b323c35d409450f51b91e3e/greenlet-3.3.2-cp313-cp313-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:d248d8c23c67d2291ffd47af766e2a3aa9fa1c6703155c099feb11f526c63a92", size = 614219, upload-time = "2026-02-20T20:55:59.817Z" }, - { url = "https://files.pythonhosted.org/packages/7a/34/259b28ea7a2a0c904b11cd36c79b8cef8019b26ee5dbe24e73b469dea347/greenlet-3.3.2-cp313-cp313-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b6997d360a4e6a4e936c0f9625b1c20416b8a0ea18a8e19cabbefc712e7397ab", size = 616774, upload-time = "2026-02-20T20:21:02.454Z" }, - { url = "https://files.pythonhosted.org/packages/0a/03/996c2d1689d486a6e199cb0f1cf9e4aa940c500e01bdf201299d7d61fa69/greenlet-3.3.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:64970c33a50551c7c50491671265d8954046cb6e8e2999aacdd60e439b70418a", size = 1571277, upload-time = "2026-02-20T20:49:34.795Z" }, - { url = "https://files.pythonhosted.org/packages/d9/c4/2570fc07f34a39f2caf0bf9f24b0a1a0a47bc2e8e465b2c2424821389dfc/greenlet-3.3.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:1a9172f5bf6bd88e6ba5a84e0a68afeac9dc7b6b412b245dd64f52d83c81e55b", size = 1640455, upload-time = "2026-02-20T20:21:10.261Z" }, - { url = "https://files.pythonhosted.org/packages/91/39/5ef5aa23bc545aa0d31e1b9b55822b32c8da93ba657295840b6b34124009/greenlet-3.3.2-cp313-cp313-win_amd64.whl", hash = "sha256:a7945dd0eab63ded0a48e4dcade82939783c172290a7903ebde9e184333ca124", size = 230961, upload-time = "2026-02-20T20:16:58.461Z" }, - { url = "https://files.pythonhosted.org/packages/62/6b/a89f8456dcb06becff288f563618e9f20deed8dd29beea14f9a168aef64b/greenlet-3.3.2-cp313-cp313-win_arm64.whl", hash = "sha256:394ead29063ee3515b4e775216cb756b2e3b4a7e55ae8fd884f17fa579e6b327", size = 230221, upload-time = "2026-02-20T20:17:37.152Z" }, - { url = "https://files.pythonhosted.org/packages/3f/ae/8bffcbd373b57a5992cd077cbe8858fff39110480a9d50697091faea6f39/greenlet-3.3.2-cp314-cp314-macosx_11_0_universal2.whl", hash = "sha256:8d1658d7291f9859beed69a776c10822a0a799bc4bfe1bd4272bb60e62507dab", size = 279650, upload-time = "2026-02-20T20:18:00.783Z" }, - { url = "https://files.pythonhosted.org/packages/d1/c0/45f93f348fa49abf32ac8439938726c480bd96b2a3c6f4d949ec0124b69f/greenlet-3.3.2-cp314-cp314-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:18cb1b7337bca281915b3c5d5ae19f4e76d35e1df80f4ad3c1a7be91fadf1082", size = 650295, upload-time = "2026-02-20T20:47:34.036Z" }, - { url = "https://files.pythonhosted.org/packages/b3/de/dd7589b3f2b8372069ab3e4763ea5329940fc7ad9dcd3e272a37516d7c9b/greenlet-3.3.2-cp314-cp314-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:c2e47408e8ce1c6f1ceea0dffcdf6ebb85cc09e55c7af407c99f1112016e45e9", size = 662163, upload-time = "2026-02-20T20:56:01.295Z" }, - { url = "https://files.pythonhosted.org/packages/d2/d8/09bfa816572a4d83bccd6750df1926f79158b1c36c5f73786e26dbe4ee38/greenlet-3.3.2-cp314-cp314-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:63d10328839d1973e5ba35e98cccbca71b232b14051fd957b6f8b6e8e80d0506", size = 664160, upload-time = "2026-02-20T20:21:04.015Z" }, - { url = "https://files.pythonhosted.org/packages/48/cf/56832f0c8255d27f6c35d41b5ec91168d74ec721d85f01a12131eec6b93c/greenlet-3.3.2-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:8e4ab3cfb02993c8cc248ea73d7dae6cec0253e9afa311c9b37e603ca9fad2ce", size = 1619181, upload-time = "2026-02-20T20:49:36.052Z" }, - { url = "https://files.pythonhosted.org/packages/0a/23/b90b60a4aabb4cec0796e55f25ffbfb579a907c3898cd2905c8918acaa16/greenlet-3.3.2-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:94ad81f0fd3c0c0681a018a976e5c2bd2ca2d9d94895f23e7bb1af4e8af4e2d5", size = 1687713, upload-time = "2026-02-20T20:21:11.684Z" }, - { url = "https://files.pythonhosted.org/packages/f3/ca/2101ca3d9223a1dc125140dbc063644dca76df6ff356531eb27bc267b446/greenlet-3.3.2-cp314-cp314-win_amd64.whl", hash = "sha256:8c4dd0f3997cf2512f7601563cc90dfb8957c0cff1e3a1b23991d4ea1776c492", size = 232034, upload-time = "2026-02-20T20:20:08.186Z" }, - { url = "https://files.pythonhosted.org/packages/f6/4a/ecf894e962a59dea60f04877eea0fd5724618da89f1867b28ee8b91e811f/greenlet-3.3.2-cp314-cp314-win_arm64.whl", hash = "sha256:cd6f9e2bbd46321ba3bbb4c8a15794d32960e3b0ae2cc4d49a1a53d314805d71", size = 231437, upload-time = "2026-02-20T20:18:59.722Z" }, - { url = "https://files.pythonhosted.org/packages/98/6d/8f2ef704e614bcf58ed43cfb8d87afa1c285e98194ab2cfad351bf04f81e/greenlet-3.3.2-cp314-cp314t-macosx_11_0_universal2.whl", hash = "sha256:e26e72bec7ab387ac80caa7496e0f908ff954f31065b0ffc1f8ecb1338b11b54", size = 286617, upload-time = "2026-02-20T20:19:29.856Z" }, - { url = "https://files.pythonhosted.org/packages/5e/0d/93894161d307c6ea237a43988f27eba0947b360b99ac5239ad3fe09f0b47/greenlet-3.3.2-cp314-cp314t-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8b466dff7a4ffda6ca975979bab80bdadde979e29fc947ac3be4451428d8b0e4", size = 655189, upload-time = "2026-02-20T20:47:35.742Z" }, - { url = "https://files.pythonhosted.org/packages/f5/2c/d2d506ebd8abcb57386ec4f7ba20f4030cbe56eae541bc6fd6ef399c0b41/greenlet-3.3.2-cp314-cp314t-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:b8bddc5b73c9720bea487b3bffdb1840fe4e3656fba3bd40aa1489e9f37877ff", size = 658225, upload-time = "2026-02-20T20:56:02.527Z" }, - { url = "https://files.pythonhosted.org/packages/8e/30/3a09155fbf728673a1dea713572d2d31159f824a37c22da82127056c44e4/greenlet-3.3.2-cp314-cp314t-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b26b0f4428b871a751968285a1ac9648944cea09807177ac639b030bddebcea4", size = 657907, upload-time = "2026-02-20T20:21:05.259Z" }, - { url = "https://files.pythonhosted.org/packages/f3/fd/d05a4b7acd0154ed758797f0a43b4c0962a843bedfe980115e842c5b2d08/greenlet-3.3.2-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:1fb39a11ee2e4d94be9a76671482be9398560955c9e568550de0224e41104727", size = 1618857, upload-time = "2026-02-20T20:49:37.309Z" }, - { url = "https://files.pythonhosted.org/packages/6f/e1/50ee92a5db521de8f35075b5eff060dd43d39ebd46c2181a2042f7070385/greenlet-3.3.2-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:20154044d9085151bc309e7689d6f7ba10027f8f5a8c0676ad398b951913d89e", size = 1680010, upload-time = "2026-02-20T20:21:13.427Z" }, - { url = "https://files.pythonhosted.org/packages/29/4b/45d90626aef8e65336bed690106d1382f7a43665e2249017e9527df8823b/greenlet-3.3.2-cp314-cp314t-win_amd64.whl", hash = "sha256:c04c5e06ec3e022cbfe2cd4a846e1d4e50087444f875ff6d2c2ad8445495cf1a", size = 237086, upload-time = "2026-02-20T20:20:45.786Z" }, +sdist = { url = "https://files.pythonhosted.org/packages/86/94/a5935717b307d7c71fe877b52b884c6af707d2d2090db118a03fbd799369/greenlet-3.4.0.tar.gz", hash = "sha256:f50a96b64dafd6169e595a5c56c9146ef80333e67d4476a65a9c55f400fc22ff", size = 195913, upload-time = "2026-04-08T17:08:00.863Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/0c/bc/e30e1e3d5e8860b0e0ce4d2b16b2681b77fd13542fc0d72f7e3c22d16eff/greenlet-3.4.0-cp310-cp310-macosx_11_0_universal2.whl", hash = "sha256:d18eae9a7fb0f499efcd146b8c9750a2e1f6e0e93b5a382b3481875354a430e6", size = 284315, upload-time = "2026-04-08T17:02:52.322Z" }, + { url = "https://files.pythonhosted.org/packages/5b/cc/e023ae1967d2a26737387cac083e99e47f65f58868bd155c4c80c01ec4e0/greenlet-3.4.0-cp310-cp310-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:636d2f95c309e35f650e421c23297d5011716be15d966e6328b367c9fc513a82", size = 601916, upload-time = "2026-04-08T16:24:35.533Z" }, + { url = "https://files.pythonhosted.org/packages/67/32/5be1677954b6d8810b33abe94e3eb88726311c58fa777dc97e390f7caf5a/greenlet-3.4.0-cp310-cp310-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:234582c20af9742583c3b2ddfbdbb58a756cfff803763ffaae1ac7990a9fac31", size = 616399, upload-time = "2026-04-08T16:30:54.536Z" }, + { url = "https://files.pythonhosted.org/packages/74/bf/2d58d5ea515704f83e34699128c9072a34bea27d2b6a556e102105fe62a5/greenlet-3.4.0-cp310-cp310-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:523677e69cd4711b5a014e37bc1fb3a29947c3e3a5bb6a527e1cc50312e5a398", size = 611978, upload-time = "2026-04-08T15:56:31.335Z" }, + { url = "https://files.pythonhosted.org/packages/bd/69/6525049b6c179d8a923256304d8387b8bdd4acab1acf0407852463c6d514/greenlet-3.4.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:b45e45fe47a19051a396abb22e19e7836a59ee6c5a90f3be427343c37908d65b", size = 1571957, upload-time = "2026-04-08T16:26:17.041Z" }, + { url = "https://files.pythonhosted.org/packages/4e/6c/bbfb798b05fec736a0d24dc23e81b45bcee87f45a83cfb39db031853bddc/greenlet-3.4.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:5434271357be07f3ad0936c312645853b7e689e679e29310e2de09a9ea6c3adf", size = 1637223, upload-time = "2026-04-08T15:57:27.556Z" }, + { url = "https://files.pythonhosted.org/packages/b7/7d/981fe0e7c07bd9d5e7eb18decb8590a11e3955878291f7a7de2e9c668eb7/greenlet-3.4.0-cp310-cp310-win_amd64.whl", hash = "sha256:a19093fbad824ed7c0f355b5ff4214bffda5f1a7f35f29b31fcaa240cc0135ab", size = 237902, upload-time = "2026-04-08T17:03:14.16Z" }, + { url = "https://files.pythonhosted.org/packages/fb/c6/dba32cab7e3a625b011aa5647486e2d28423a48845a2998c126dd69c85e1/greenlet-3.4.0-cp311-cp311-macosx_11_0_universal2.whl", hash = "sha256:805bebb4945094acbab757d34d6e1098be6de8966009ab9ca54f06ff492def58", size = 285504, upload-time = "2026-04-08T15:52:14.071Z" }, + { url = "https://files.pythonhosted.org/packages/54/f4/7cb5c2b1feb9a1f50e038be79980dfa969aa91979e5e3a18fdbcfad2c517/greenlet-3.4.0-cp311-cp311-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:439fc2f12b9b512d9dfa681c5afe5f6b3232c708d13e6f02c845e0d9f4c2d8c6", size = 605476, upload-time = "2026-04-08T16:24:37.064Z" }, + { url = "https://files.pythonhosted.org/packages/d6/af/b66ab0b2f9a4c5a867c136bf66d9599f34f21a1bcca26a2884a29c450bd9/greenlet-3.4.0-cp311-cp311-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:a70ed1cb0295bee1df57b63bf7f46b4e56a5c93709eea769c1fec1bb23a95875", size = 618336, upload-time = "2026-04-08T16:30:56.59Z" }, + { url = "https://files.pythonhosted.org/packages/e5/5c/8c5633ece6ba611d64bf2770219a98dd439921d6424e4e8cf16b0ac74ea5/greenlet-3.4.0-cp311-cp311-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c660bce1940a1acae5f51f0a064f1bc785d07ea16efcb4bc708090afc4d69e83", size = 613515, upload-time = "2026-04-08T15:56:32.478Z" }, + { url = "https://files.pythonhosted.org/packages/a9/df/950d15bca0d90a0e7395eb777903060504cdb509b7b705631e8fb69ff415/greenlet-3.4.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:ee407d4d1ca9dc632265aee1c8732c4a2d60adff848057cdebfe5fe94eb2c8a2", size = 1574623, upload-time = "2026-04-08T16:26:18.596Z" }, + { url = "https://files.pythonhosted.org/packages/1a/e7/0839afab829fcb7333c9ff6d80c040949510055d2d4d63251f0d1c7c804e/greenlet-3.4.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:956215d5e355fffa7c021d168728321fd4d31fd730ac609b1653b450f6a4bc71", size = 1639579, upload-time = "2026-04-08T15:57:29.231Z" }, + { url = "https://files.pythonhosted.org/packages/d9/2b/b4482401e9bcaf9f5c97f67ead38db89c19520ff6d0d6699979c6efcc200/greenlet-3.4.0-cp311-cp311-win_amd64.whl", hash = "sha256:5cb614ace7c27571270354e9c9f696554d073f8aa9319079dcba466bbdead711", size = 238233, upload-time = "2026-04-08T17:02:54.286Z" }, + { url = "https://files.pythonhosted.org/packages/0c/4d/d8123a4e0bcd583d5cfc8ddae0bbe29c67aab96711be331a7cc935a35966/greenlet-3.4.0-cp311-cp311-win_arm64.whl", hash = "sha256:04403ac74fe295a361f650818de93be11b5038a78f49ccfb64d3b1be8fbf1267", size = 235045, upload-time = "2026-04-08T17:04:05.072Z" }, + { url = "https://files.pythonhosted.org/packages/65/8b/3669ad3b3f247a791b2b4aceb3aa5a31f5f6817bf547e4e1ff712338145a/greenlet-3.4.0-cp312-cp312-macosx_11_0_universal2.whl", hash = "sha256:1a54a921561dd9518d31d2d3db4d7f80e589083063ab4d3e2e950756ef809e1a", size = 286902, upload-time = "2026-04-08T15:52:12.138Z" }, + { url = "https://files.pythonhosted.org/packages/38/3e/3c0e19b82900873e2d8469b590a6c4b3dfd2b316d0591f1c26b38a4879a5/greenlet-3.4.0-cp312-cp312-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:16dec271460a9a2b154e3b1c2fa1050ce6280878430320e85e08c166772e3f97", size = 606099, upload-time = "2026-04-08T16:24:38.408Z" }, + { url = "https://files.pythonhosted.org/packages/b5/33/99fef65e7754fc76a4ed14794074c38c9ed3394a5bd129d7f61b705f3168/greenlet-3.4.0-cp312-cp312-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:90036ce224ed6fe75508c1907a77e4540176dcf0744473627785dd519c6f9996", size = 618837, upload-time = "2026-04-08T16:30:58.298Z" }, + { url = "https://files.pythonhosted.org/packages/36/f7/229f3aed6948faa20e0616a0b8568da22e365ede6a54d7d369058b128afd/greenlet-3.4.0-cp312-cp312-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a1c4f6b453006efb8310affb2d132832e9bbb4fc01ce6df6b70d810d38f1f6dc", size = 615062, upload-time = "2026-04-08T15:56:33.766Z" }, + { url = "https://files.pythonhosted.org/packages/08/97/d988180011aa40135c46cd0d0cf01dd97f7162bae14139b4a3ef54889ba5/greenlet-3.4.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:9b2d9a138ffa0e306d0e2b72976d2fb10b97e690d40ab36a472acaab0838e2de", size = 1573511, upload-time = "2026-04-08T16:26:20.058Z" }, + { url = "https://files.pythonhosted.org/packages/d4/0f/a5a26fe152fb3d12e6a474181f6e9848283504d0afd095f353d85726374b/greenlet-3.4.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:8424683caf46eb0eb6f626cb95e008e8cc30d0cb675bdfa48200925c79b38a08", size = 1640396, upload-time = "2026-04-08T15:57:30.88Z" }, + { url = "https://files.pythonhosted.org/packages/42/cf/bb2c32d9a100e36ee9f6e38fad6b1e082b8184010cb06259b49e1266ca01/greenlet-3.4.0-cp312-cp312-win_amd64.whl", hash = "sha256:a0a53fb071531d003b075c444014ff8f8b1a9898d36bb88abd9ac7b3524648a2", size = 238892, upload-time = "2026-04-08T17:03:10.094Z" }, + { url = "https://files.pythonhosted.org/packages/b7/47/6c41314bac56e71436ce551c7fbe3cc830ed857e6aa9708dbb9c65142eb6/greenlet-3.4.0-cp312-cp312-win_arm64.whl", hash = "sha256:f38b81880ba28f232f1f675893a39cf7b6db25b31cc0a09bb50787ecf957e85e", size = 235599, upload-time = "2026-04-08T15:52:54.3Z" }, + { url = "https://files.pythonhosted.org/packages/7a/75/7e9cd1126a1e1f0cd67b0eda02e5221b28488d352684704a78ed505bd719/greenlet-3.4.0-cp313-cp313-macosx_11_0_universal2.whl", hash = "sha256:43748988b097f9c6f09364f260741aa73c80747f63389824435c7a50bfdfd5c1", size = 285856, upload-time = "2026-04-08T15:52:45.82Z" }, + { url = "https://files.pythonhosted.org/packages/9d/c4/3e2df392e5cb199527c4d9dbcaa75c14edcc394b45040f0189f649631e3c/greenlet-3.4.0-cp313-cp313-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5566e4e2cd7a880e8c27618e3eab20f3494452d12fd5129edef7b2f7aa9a36d1", size = 610208, upload-time = "2026-04-08T16:24:39.674Z" }, + { url = "https://files.pythonhosted.org/packages/da/af/750cdfda1d1bd30a6c28080245be8d0346e669a98fdbae7f4102aa95fff3/greenlet-3.4.0-cp313-cp313-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:1054c5a3c78e2ab599d452f23f7adafef55062a783a8e241d24f3b633ba6ff82", size = 621269, upload-time = "2026-04-08T16:30:59.767Z" }, + { url = "https://files.pythonhosted.org/packages/54/78/0cbc693622cd54ebe25207efbb3a0eb07c2639cb8594f6e3aaaa0bb077a8/greenlet-3.4.0-cp313-cp313-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f82cb6cddc27dd81c96b1506f4aa7def15070c3b2a67d4e46fd19016aacce6cf", size = 617549, upload-time = "2026-04-08T15:56:34.893Z" }, + { url = "https://files.pythonhosted.org/packages/ba/c0/8966767de01343c1ff47e8b855dc78e7d1a8ed2b7b9c83576a57e289f81d/greenlet-3.4.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:227a46251ecba4ff46ae742bc5ce95c91d5aceb4b02f885487aff269c127a729", size = 1575310, upload-time = "2026-04-08T16:26:21.671Z" }, + { url = "https://files.pythonhosted.org/packages/b8/38/bcdc71ba05e9a5fda87f63ffc2abcd1f15693b659346df994a48c968003d/greenlet-3.4.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:5b99e87be7eba788dd5b75ba1cde5639edffdec5f91fe0d734a249535ec3408c", size = 1640435, upload-time = "2026-04-08T15:57:32.572Z" }, + { url = "https://files.pythonhosted.org/packages/a1/c2/19b664b7173b9e4ef5f77e8cef9f14c20ec7fce7920dc1ccd7afd955d093/greenlet-3.4.0-cp313-cp313-win_amd64.whl", hash = "sha256:849f8bc17acd6295fcb5de8e46d55cc0e52381c56eaf50a2afd258e97bc65940", size = 238760, upload-time = "2026-04-08T17:04:03.878Z" }, + { url = "https://files.pythonhosted.org/packages/9b/96/795619651d39c7fbd809a522f881aa6f0ead504cc8201c3a5b789dfaef99/greenlet-3.4.0-cp313-cp313-win_arm64.whl", hash = "sha256:9390ad88b652b1903814eaabd629ca184db15e0eeb6fe8a390bbf8b9106ae15a", size = 235498, upload-time = "2026-04-08T17:05:00.584Z" }, + { url = "https://files.pythonhosted.org/packages/78/02/bde66806e8f169cf90b14d02c500c44cdbe02c8e224c9c67bafd1b8cadd1/greenlet-3.4.0-cp314-cp314-macosx_11_0_universal2.whl", hash = "sha256:10a07aca6babdd18c16a3f4f8880acfffc2b88dfe431ad6aa5f5740759d7d75e", size = 286291, upload-time = "2026-04-08T17:09:34.307Z" }, + { url = "https://files.pythonhosted.org/packages/05/1f/39da1c336a87d47c58352fb8a78541ce63d63ae57c5b9dae1fe02801bbc2/greenlet-3.4.0-cp314-cp314-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:076e21040b3a917d3ce4ad68fb5c3c6b32f1405616c4a57aa83120979649bd3d", size = 656749, upload-time = "2026-04-08T16:24:41.721Z" }, + { url = "https://files.pythonhosted.org/packages/d3/6c/90ee29a4ee27af7aa2e2ec408799eeb69ee3fcc5abcecac6ddd07a5cd0f2/greenlet-3.4.0-cp314-cp314-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:e82689eea4a237e530bb5cb41b180ef81fa2160e1f89422a67be7d90da67f615", size = 669084, upload-time = "2026-04-08T16:31:01.372Z" }, + { url = "https://files.pythonhosted.org/packages/07/49/d4cad6e5381a50947bb973d2f6cf6592621451b09368b8c20d9b8af49c5b/greenlet-3.4.0-cp314-cp314-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4df3b0b2289ec686d3c821a5fee44259c05cfe824dd5e6e12c8e5f5df23085cf", size = 665621, upload-time = "2026-04-08T15:56:35.995Z" }, + { url = "https://files.pythonhosted.org/packages/37/31/d1edd54f424761b5d47718822f506b435b6aab2f3f93b465441143ea5119/greenlet-3.4.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:8bff29d586ea415688f4cec96a591fcc3bf762d046a796cdadc1fdb6e7f2d5bf", size = 1622259, upload-time = "2026-04-08T16:26:23.201Z" }, + { url = "https://files.pythonhosted.org/packages/b0/c6/6d3f9cdcb21c4e12a79cb332579f1c6aa1af78eb68059c5a957c7812d95e/greenlet-3.4.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:8a569c2fb840c53c13a2b8967c63621fafbd1a0e015b9c82f408c33d626a2fda", size = 1686916, upload-time = "2026-04-08T15:57:34.282Z" }, + { url = "https://files.pythonhosted.org/packages/63/45/c1ca4a1ad975de4727e52d3ffe641ae23e1d7a8ffaa8ff7a0477e1827b92/greenlet-3.4.0-cp314-cp314-win_amd64.whl", hash = "sha256:207ba5b97ea8b0b60eb43ffcacf26969dd83726095161d676aac03ff913ee50d", size = 239821, upload-time = "2026-04-08T17:03:48.423Z" }, + { url = "https://files.pythonhosted.org/packages/71/c4/6f621023364d7e85a4769c014c8982f98053246d142420e0328980933ceb/greenlet-3.4.0-cp314-cp314-win_arm64.whl", hash = "sha256:f8296d4e2b92af34ebde81085a01690f26a51eb9ac09a0fcadb331eb36dbc802", size = 236932, upload-time = "2026-04-08T17:04:33.551Z" }, + { url = "https://files.pythonhosted.org/packages/d4/8f/18d72b629783f5e8d045a76f5325c1e938e659a9e4da79c7dcd10169a48d/greenlet-3.4.0-cp314-cp314t-macosx_11_0_universal2.whl", hash = "sha256:d70012e51df2dbbccfaf63a40aaf9b40c8bed37c3e3a38751c926301ce538ece", size = 294681, upload-time = "2026-04-08T15:52:35.778Z" }, + { url = "https://files.pythonhosted.org/packages/9e/ad/5fa86ec46769c4153820d58a04062285b3b9e10ba3d461ee257b68dcbf53/greenlet-3.4.0-cp314-cp314t-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a58bec0751f43068cd40cff31bb3ca02ad6000b3a51ca81367af4eb5abc480c8", size = 658899, upload-time = "2026-04-08T16:24:43.32Z" }, + { url = "https://files.pythonhosted.org/packages/43/f0/4e8174ca0e87ae748c409f055a1ba161038c43cc0a5a6f1433a26ac2e5bf/greenlet-3.4.0-cp314-cp314t-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:05fa0803561028f4b2e3b490ee41216a842eaee11aed004cc343a996d9523aa2", size = 665284, upload-time = "2026-04-08T16:31:02.833Z" }, + { url = "https://files.pythonhosted.org/packages/19/da/991cf7cd33662e2df92a1274b7eb4d61769294d38a1bba8a45f31364845e/greenlet-3.4.0-cp314-cp314t-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e60d38719cb80b3ab5e85f9f1aed4960acfde09868af6762ccb27b260d68f4ed", size = 661861, upload-time = "2026-04-08T15:56:37.269Z" }, + { url = "https://files.pythonhosted.org/packages/36/c5/6c2c708e14db3d9caea4b459d8464f58c32047451142fe2cfd90e7458f41/greenlet-3.4.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:7f50c804733b43eded05ae694691c9aa68bca7d0a867d67d4a3f514742a2d53f", size = 1622182, upload-time = "2026-04-08T16:26:24.777Z" }, + { url = "https://files.pythonhosted.org/packages/7a/4c/50c5fed19378e11a29fabab1f6be39ea95358f4a0a07e115a51ca93385d8/greenlet-3.4.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:2d4f0635dc4aa638cda4b2f5a07ae9a2cff9280327b581a3fcb6f317b4fbc38a", size = 1685050, upload-time = "2026-04-08T15:57:36.453Z" }, + { url = "https://files.pythonhosted.org/packages/db/72/85ae954d734703ab48e622c59d4ce35d77ce840c265814af9c078cacc7aa/greenlet-3.4.0-cp314-cp314t-win_amd64.whl", hash = "sha256:1a4a48f24681300c640f143ba7c404270e1ebbbcf34331d7104a4ff40f8ea705", size = 245554, upload-time = "2026-04-08T17:03:50.044Z" }, ] [[package]] @@ -2129,7 +2130,7 @@ wheels = [ [[package]] name = "huggingface-hub" -version = "1.9.1" +version = "1.11.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "filelock" }, @@ -2142,9 +2143,9 @@ dependencies = [ { name = "typer" }, { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/44/40/68d9b286b125d9318ae95c8f8b206e8672e7244b0eea61ebb4a88037638c/huggingface_hub-1.9.1.tar.gz", hash = "sha256:442af372207cc24dcb089caf507fcd7dbc1217c11d6059a06f6b90afe64e8bd2", size = 750355, upload-time = "2026-04-07T13:47:59.167Z" } +sdist = { url = "https://files.pythonhosted.org/packages/dc/89/e7aa12d8a6b9259bed10671abb25ae6fa437c0f88a86ecbf59617bae7759/huggingface_hub-1.11.0.tar.gz", hash = "sha256:15fb3713c7f9cdff7b808a94fd91664f661ab142796bb48c9cd9493e8d166278", size = 761749, upload-time = "2026-04-16T13:07:39.73Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/3d/af/10a89c54937dccf6c10792770f362d96dd67aedfde108e6e1fd7a0836789/huggingface_hub-1.9.1-py3-none-any.whl", hash = "sha256:8dae771b969b318203727a6c6c5209d25e661f6f0dd010fc09cc4a12cf81c657", size = 637356, upload-time = "2026-04-07T13:47:57.239Z" }, + { url = "https://files.pythonhosted.org/packages/37/02/4f3f8997d1ea7fe0146b343e5e14bd065fa87af790d07e5576d31b31cc18/huggingface_hub-1.11.0-py3-none-any.whl", hash = "sha256:42a6de0afbfeb5e022222d36398f029679db4eb4778801aafda32257ae9131ab", size = 645499, upload-time = "2026-04-16T13:07:37.716Z" }, ] [[package]] @@ -2161,11 +2162,11 @@ wheels = [ [[package]] name = "idna" -version = "3.11" +version = "3.13" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/6f/6d/0703ccc57f3a7233505399edb88de3cbd678da106337b9fcde432b65ed60/idna-3.11.tar.gz", hash = "sha256:795dafcc9c04ed0c1fb032c2aa73654d8e8c5023a7df64a53f39190ada629902", size = 194582, upload-time = "2025-10-12T14:55:20.501Z" } +sdist = { url = "https://files.pythonhosted.org/packages/ce/cc/762dfb036166873f0059f3b7de4565e1b5bc3d6f28a414c13da27e442f99/idna-3.13.tar.gz", hash = "sha256:585ea8fe5d69b9181ec1afba340451fba6ba764af97026f92a91d4eef164a242", size = 194210, upload-time = "2026-04-22T16:42:42.314Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/0e/61/66938bbb5fc52dbdf84594873d5b51fb1f7c7794e9c0f5bd885f30bc507b/idna-3.11-py3-none-any.whl", hash = "sha256:771a87f49d9defaf64091e6e6fe9c18d4833f140bd19464795bc32d966ca37ea", size = 71008, upload-time = "2025-10-12T14:55:18.883Z" }, + { url = "https://files.pythonhosted.org/packages/5d/13/ad7d7ca3808a898b4612b6fe93cde56b53f3034dcde235acb1f0e1df24c6/idna-3.13-py3-none-any.whl", hash = "sha256:892ea0cde124a99ce773decba204c5552b69c3c67ffd5f232eb7696135bc8bb3", size = 68629, upload-time = "2026-04-22T16:42:40.909Z" }, ] [[package]] @@ -2270,99 +2271,105 @@ wheels = [ [[package]] name = "jiter" -version = "0.13.0" +version = "0.14.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/0d/5e/4ec91646aee381d01cdb9974e30882c9cd3b8c5d1079d6b5ff4af522439a/jiter-0.13.0.tar.gz", hash = "sha256:f2839f9c2c7e2dffc1bc5929a510e14ce0a946be9365fd1219e7ef342dae14f4", size = 164847, upload-time = "2026-02-02T12:37:56.441Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/d0/5a/41da76c5ea07bec1b0472b6b2fdb1b651074d504b19374d7e130e0cdfb25/jiter-0.13.0-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:2ffc63785fd6c7977defe49b9824ae6ce2b2e2b77ce539bdaf006c26da06342e", size = 311164, upload-time = "2026-02-02T12:35:17.688Z" }, - { url = "https://files.pythonhosted.org/packages/40/cb/4a1bf994a3e869f0d39d10e11efb471b76d0ad70ecbfb591427a46c880c2/jiter-0.13.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:4a638816427006c1e3f0013eb66d391d7a3acda99a7b0cf091eff4497ccea33a", size = 320296, upload-time = "2026-02-02T12:35:19.828Z" }, - { url = "https://files.pythonhosted.org/packages/09/82/acd71ca9b50ecebadc3979c541cd717cce2fe2bc86236f4fa597565d8f1a/jiter-0.13.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:19928b5d1ce0ff8c1ee1b9bdef3b5bfc19e8304f1b904e436caf30bc15dc6cf5", size = 352742, upload-time = "2026-02-02T12:35:21.258Z" }, - { url = "https://files.pythonhosted.org/packages/71/03/d1fc996f3aecfd42eb70922edecfb6dd26421c874503e241153ad41df94f/jiter-0.13.0-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:309549b778b949d731a2f0e1594a3f805716be704a73bf3ad9a807eed5eb5721", size = 363145, upload-time = "2026-02-02T12:35:24.653Z" }, - { url = "https://files.pythonhosted.org/packages/f1/61/a30492366378cc7a93088858f8991acd7d959759fe6138c12a4644e58e81/jiter-0.13.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:bcdabaea26cb04e25df3103ce47f97466627999260290349a88c8136ecae0060", size = 487683, upload-time = "2026-02-02T12:35:26.162Z" }, - { url = "https://files.pythonhosted.org/packages/20/4e/4223cffa9dbbbc96ed821c5aeb6bca510848c72c02086d1ed3f1da3d58a7/jiter-0.13.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a3a377af27b236abbf665a69b2bdd680e3b5a0bd2af825cd3b81245279a7606c", size = 373579, upload-time = "2026-02-02T12:35:27.582Z" }, - { url = "https://files.pythonhosted.org/packages/fe/c9/b0489a01329ab07a83812d9ebcffe7820a38163c6d9e7da644f926ff877c/jiter-0.13.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fe49d3ff6db74321f144dff9addd4a5874d3105ac5ba7c5b77fac099cfae31ae", size = 362904, upload-time = "2026-02-02T12:35:28.925Z" }, - { url = "https://files.pythonhosted.org/packages/05/af/53e561352a44afcba9a9bc67ee1d320b05a370aed8df54eafe714c4e454d/jiter-0.13.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2113c17c9a67071b0f820733c0893ed1d467b5fcf4414068169e5c2cabddb1e2", size = 392380, upload-time = "2026-02-02T12:35:30.385Z" }, - { url = "https://files.pythonhosted.org/packages/76/2a/dd805c3afb8ed5b326c5ae49e725d1b1255b9754b1b77dbecdc621b20773/jiter-0.13.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:ab1185ca5c8b9491b55ebf6c1e8866b8f68258612899693e24a92c5fdb9455d5", size = 517939, upload-time = "2026-02-02T12:35:31.865Z" }, - { url = "https://files.pythonhosted.org/packages/20/2a/7b67d76f55b8fe14c937e7640389612f05f9a4145fc28ae128aaa5e62257/jiter-0.13.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:9621ca242547edc16400981ca3231e0c91c0c4c1ab8573a596cd9bb3575d5c2b", size = 551696, upload-time = "2026-02-02T12:35:33.306Z" }, - { url = "https://files.pythonhosted.org/packages/85/9c/57cdd64dac8f4c6ab8f994fe0eb04dc9fd1db102856a4458fcf8a99dfa62/jiter-0.13.0-cp310-cp310-win32.whl", hash = "sha256:a7637d92b1c9d7a771e8c56f445c7f84396d48f2e756e5978840ecba2fac0894", size = 204592, upload-time = "2026-02-02T12:35:34.58Z" }, - { url = "https://files.pythonhosted.org/packages/a7/38/f4f3ea5788b8a5bae7510a678cdc747eda0c45ffe534f9878ff37e7cf3b3/jiter-0.13.0-cp310-cp310-win_amd64.whl", hash = "sha256:c1b609e5cbd2f52bb74fb721515745b407df26d7b800458bd97cb3b972c29e7d", size = 206016, upload-time = "2026-02-02T12:35:36.435Z" }, - { url = "https://files.pythonhosted.org/packages/71/29/499f8c9eaa8a16751b1c0e45e6f5f1761d180da873d417996cc7bddc8eef/jiter-0.13.0-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:ea026e70a9a28ebbdddcbcf0f1323128a8db66898a06eaad3a4e62d2f554d096", size = 311157, upload-time = "2026-02-02T12:35:37.758Z" }, - { url = "https://files.pythonhosted.org/packages/50/f6/566364c777d2ab450b92100bea11333c64c38d32caf8dc378b48e5b20c46/jiter-0.13.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:66aa3e663840152d18cc8ff1e4faad3dd181373491b9cfdc6004b92198d67911", size = 319729, upload-time = "2026-02-02T12:35:39.246Z" }, - { url = "https://files.pythonhosted.org/packages/73/dd/560f13ec5e4f116d8ad2658781646cca91b617ae3b8758d4a5076b278f70/jiter-0.13.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c3524798e70655ff19aec58c7d05adb1f074fecff62da857ea9be2b908b6d701", size = 354766, upload-time = "2026-02-02T12:35:40.662Z" }, - { url = "https://files.pythonhosted.org/packages/7c/0d/061faffcfe94608cbc28a0d42a77a74222bdf5055ccdbe5fd2292b94f510/jiter-0.13.0-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ec7e287d7fbd02cb6e22f9a00dd9c9cd504c40a61f2c61e7e1f9690a82726b4c", size = 362587, upload-time = "2026-02-02T12:35:42.025Z" }, - { url = "https://files.pythonhosted.org/packages/92/c9/c66a7864982fd38a9773ec6e932e0398d1262677b8c60faecd02ffb67bf3/jiter-0.13.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:47455245307e4debf2ce6c6e65a717550a0244231240dcf3b8f7d64e4c2f22f4", size = 487537, upload-time = "2026-02-02T12:35:43.459Z" }, - { url = "https://files.pythonhosted.org/packages/6c/86/84eb4352cd3668f16d1a88929b5888a3fe0418ea8c1dfc2ad4e7bf6e069a/jiter-0.13.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ee9da221dca6e0429c2704c1b3655fe7b025204a71d4d9b73390c759d776d165", size = 373717, upload-time = "2026-02-02T12:35:44.928Z" }, - { url = "https://files.pythonhosted.org/packages/6e/09/9fe4c159358176f82d4390407a03f506a8659ed13ca3ac93a843402acecf/jiter-0.13.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:24ab43126d5e05f3d53a36a8e11eb2f23304c6c1117844aaaf9a0aa5e40b5018", size = 362683, upload-time = "2026-02-02T12:35:46.636Z" }, - { url = "https://files.pythonhosted.org/packages/c9/5e/85f3ab9caca0c1d0897937d378b4a515cae9e119730563572361ea0c48ae/jiter-0.13.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:9da38b4fedde4fb528c740c2564628fbab737166a0e73d6d46cb4bb5463ff411", size = 392345, upload-time = "2026-02-02T12:35:48.088Z" }, - { url = "https://files.pythonhosted.org/packages/12/4c/05b8629ad546191939e6f0c2f17e29f542a398f4a52fb987bc70b6d1eb8b/jiter-0.13.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:0b34c519e17658ed88d5047999a93547f8889f3c1824120c26ad6be5f27b6cf5", size = 517775, upload-time = "2026-02-02T12:35:49.482Z" }, - { url = "https://files.pythonhosted.org/packages/4d/88/367ea2eb6bc582c7052e4baf5ddf57ebe5ab924a88e0e09830dfb585c02d/jiter-0.13.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:d2a6394e6af690d462310a86b53c47ad75ac8c21dc79f120714ea449979cb1d3", size = 551325, upload-time = "2026-02-02T12:35:51.104Z" }, - { url = "https://files.pythonhosted.org/packages/f3/12/fa377ffb94a2f28c41afaed093e0d70cfe512035d5ecb0cad0ae4792d35e/jiter-0.13.0-cp311-cp311-win32.whl", hash = "sha256:0f0c065695f616a27c920a56ad0d4fc46415ef8b806bf8fc1cacf25002bd24e1", size = 204709, upload-time = "2026-02-02T12:35:52.467Z" }, - { url = "https://files.pythonhosted.org/packages/cb/16/8e8203ce92f844dfcd3d9d6a5a7322c77077248dbb12da52d23193a839cd/jiter-0.13.0-cp311-cp311-win_amd64.whl", hash = "sha256:0733312953b909688ae3c2d58d043aa040f9f1a6a75693defed7bc2cc4bf2654", size = 204560, upload-time = "2026-02-02T12:35:53.925Z" }, - { url = "https://files.pythonhosted.org/packages/44/26/97cc40663deb17b9e13c3a5cf29251788c271b18ee4d262c8f94798b8336/jiter-0.13.0-cp311-cp311-win_arm64.whl", hash = "sha256:5d9b34ad56761b3bf0fbe8f7e55468704107608512350962d3317ffd7a4382d5", size = 189608, upload-time = "2026-02-02T12:35:55.304Z" }, - { url = "https://files.pythonhosted.org/packages/2e/30/7687e4f87086829955013ca12a9233523349767f69653ebc27036313def9/jiter-0.13.0-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:0a2bd69fc1d902e89925fc34d1da51b2128019423d7b339a45d9e99c894e0663", size = 307958, upload-time = "2026-02-02T12:35:57.165Z" }, - { url = "https://files.pythonhosted.org/packages/c3/27/e57f9a783246ed95481e6749cc5002a8a767a73177a83c63ea71f0528b90/jiter-0.13.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:f917a04240ef31898182f76a332f508f2cc4b57d2b4d7ad2dbfebbfe167eb505", size = 318597, upload-time = "2026-02-02T12:35:58.591Z" }, - { url = "https://files.pythonhosted.org/packages/cf/52/e5719a60ac5d4d7c5995461a94ad5ef962a37c8bf5b088390e6fad59b2ff/jiter-0.13.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c1e2b199f446d3e82246b4fd9236d7cb502dc2222b18698ba0d986d2fecc6152", size = 348821, upload-time = "2026-02-02T12:36:00.093Z" }, - { url = "https://files.pythonhosted.org/packages/61/db/c1efc32b8ba4c740ab3fc2d037d8753f67685f475e26b9d6536a4322bcdd/jiter-0.13.0-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:04670992b576fa65bd056dbac0c39fe8bd67681c380cb2b48efa885711d9d726", size = 364163, upload-time = "2026-02-02T12:36:01.937Z" }, - { url = "https://files.pythonhosted.org/packages/55/8a/fb75556236047c8806995671a18e4a0ad646ed255276f51a20f32dceaeec/jiter-0.13.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5a1aff1fbdb803a376d4d22a8f63f8e7ccbce0b4890c26cc7af9e501ab339ef0", size = 483709, upload-time = "2026-02-02T12:36:03.41Z" }, - { url = "https://files.pythonhosted.org/packages/7e/16/43512e6ee863875693a8e6f6d532e19d650779d6ba9a81593ae40a9088ff/jiter-0.13.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3b3fb8c2053acaef8580809ac1d1f7481a0a0bdc012fd7f5d8b18fb696a5a089", size = 370480, upload-time = "2026-02-02T12:36:04.791Z" }, - { url = "https://files.pythonhosted.org/packages/f8/4c/09b93e30e984a187bc8aaa3510e1ec8dcbdcd71ca05d2f56aac0492453aa/jiter-0.13.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bdaba7d87e66f26a2c45d8cbadcbfc4bf7884182317907baf39cfe9775bb4d93", size = 360735, upload-time = "2026-02-02T12:36:06.994Z" }, - { url = "https://files.pythonhosted.org/packages/1a/1b/46c5e349019874ec5dfa508c14c37e29864ea108d376ae26d90bee238cd7/jiter-0.13.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:7b88d649135aca526da172e48083da915ec086b54e8e73a425ba50999468cc08", size = 391814, upload-time = "2026-02-02T12:36:08.368Z" }, - { url = "https://files.pythonhosted.org/packages/15/9e/26184760e85baee7162ad37b7912797d2077718476bf91517641c92b3639/jiter-0.13.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:e404ea551d35438013c64b4f357b0474c7abf9f781c06d44fcaf7a14c69ff9e2", size = 513990, upload-time = "2026-02-02T12:36:09.993Z" }, - { url = "https://files.pythonhosted.org/packages/e9/34/2c9355247d6debad57a0a15e76ab1566ab799388042743656e566b3b7de1/jiter-0.13.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:1f4748aad1b4a93c8bdd70f604d0f748cdc0e8744c5547798acfa52f10e79228", size = 548021, upload-time = "2026-02-02T12:36:11.376Z" }, - { url = "https://files.pythonhosted.org/packages/ac/4a/9f2c23255d04a834398b9c2e0e665382116911dc4d06b795710503cdad25/jiter-0.13.0-cp312-cp312-win32.whl", hash = "sha256:0bf670e3b1445fc4d31612199f1744f67f889ee1bbae703c4b54dc097e5dd394", size = 203024, upload-time = "2026-02-02T12:36:12.682Z" }, - { url = "https://files.pythonhosted.org/packages/09/ee/f0ae675a957ae5a8f160be3e87acea6b11dc7b89f6b7ab057e77b2d2b13a/jiter-0.13.0-cp312-cp312-win_amd64.whl", hash = "sha256:15db60e121e11fe186c0b15236bd5d18381b9ddacdcf4e659feb96fc6c969c92", size = 205424, upload-time = "2026-02-02T12:36:13.93Z" }, - { url = "https://files.pythonhosted.org/packages/1b/02/ae611edf913d3cbf02c97cdb90374af2082c48d7190d74c1111dde08bcdd/jiter-0.13.0-cp312-cp312-win_arm64.whl", hash = "sha256:41f92313d17989102f3cb5dd533a02787cdb99454d494344b0361355da52fcb9", size = 186818, upload-time = "2026-02-02T12:36:15.308Z" }, - { url = "https://files.pythonhosted.org/packages/91/9c/7ee5a6ff4b9991e1a45263bfc46731634c4a2bde27dfda6c8251df2d958c/jiter-0.13.0-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:1f8a55b848cbabf97d861495cd65f1e5c590246fabca8b48e1747c4dfc8f85bf", size = 306897, upload-time = "2026-02-02T12:36:16.748Z" }, - { url = "https://files.pythonhosted.org/packages/7c/02/be5b870d1d2be5dd6a91bdfb90f248fbb7dcbd21338f092c6b89817c3dbf/jiter-0.13.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:f556aa591c00f2c45eb1b89f68f52441a016034d18b65da60e2d2875bbbf344a", size = 317507, upload-time = "2026-02-02T12:36:18.351Z" }, - { url = "https://files.pythonhosted.org/packages/da/92/b25d2ec333615f5f284f3a4024f7ce68cfa0604c322c6808b2344c7f5d2b/jiter-0.13.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f7e1d61da332ec412350463891923f960c3073cf1aae93b538f0bb4c8cd46efb", size = 350560, upload-time = "2026-02-02T12:36:19.746Z" }, - { url = "https://files.pythonhosted.org/packages/be/ec/74dcb99fef0aca9fbe56b303bf79f6bd839010cb18ad41000bf6cc71eec0/jiter-0.13.0-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:3097d665a27bc96fd9bbf7f86178037db139f319f785e4757ce7ccbf390db6c2", size = 363232, upload-time = "2026-02-02T12:36:21.243Z" }, - { url = "https://files.pythonhosted.org/packages/1b/37/f17375e0bb2f6a812d4dd92d7616e41917f740f3e71343627da9db2824ce/jiter-0.13.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9d01ecc3a8cbdb6f25a37bd500510550b64ddf9f7d64a107d92f3ccb25035d0f", size = 483727, upload-time = "2026-02-02T12:36:22.688Z" }, - { url = "https://files.pythonhosted.org/packages/77/d2/a71160a5ae1a1e66c1395b37ef77da67513b0adba73b993a27fbe47eb048/jiter-0.13.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ed9bbc30f5d60a3bdf63ae76beb3f9db280d7f195dfcfa61af792d6ce912d159", size = 370799, upload-time = "2026-02-02T12:36:24.106Z" }, - { url = "https://files.pythonhosted.org/packages/01/99/ed5e478ff0eb4e8aa5fd998f9d69603c9fd3f32de3bd16c2b1194f68361c/jiter-0.13.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:98fbafb6e88256f4454de33c1f40203d09fc33ed19162a68b3b257b29ca7f663", size = 359120, upload-time = "2026-02-02T12:36:25.519Z" }, - { url = "https://files.pythonhosted.org/packages/16/be/7ffd08203277a813f732ba897352797fa9493faf8dc7995b31f3d9cb9488/jiter-0.13.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:5467696f6b827f1116556cb0db620440380434591e93ecee7fd14d1a491b6daa", size = 390664, upload-time = "2026-02-02T12:36:26.866Z" }, - { url = "https://files.pythonhosted.org/packages/d1/84/e0787856196d6d346264d6dcccb01f741e5f0bd014c1d9a2ebe149caf4f3/jiter-0.13.0-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:2d08c9475d48b92892583df9da592a0e2ac49bcd41fae1fec4f39ba6cf107820", size = 513543, upload-time = "2026-02-02T12:36:28.217Z" }, - { url = "https://files.pythonhosted.org/packages/65/50/ecbd258181c4313cf79bca6c88fb63207d04d5bf5e4f65174114d072aa55/jiter-0.13.0-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:aed40e099404721d7fcaf5b89bd3b4568a4666358bcac7b6b15c09fb6252ab68", size = 547262, upload-time = "2026-02-02T12:36:29.678Z" }, - { url = "https://files.pythonhosted.org/packages/27/da/68f38d12e7111d2016cd198161b36e1f042bd115c169255bcb7ec823a3bf/jiter-0.13.0-cp313-cp313-win32.whl", hash = "sha256:36ebfbcffafb146d0e6ffb3e74d51e03d9c35ce7c625c8066cdbfc7b953bdc72", size = 200630, upload-time = "2026-02-02T12:36:31.808Z" }, - { url = "https://files.pythonhosted.org/packages/25/65/3bd1a972c9a08ecd22eb3b08a95d1941ebe6938aea620c246cf426ae09c2/jiter-0.13.0-cp313-cp313-win_amd64.whl", hash = "sha256:8d76029f077379374cf0dbc78dbe45b38dec4a2eb78b08b5194ce836b2517afc", size = 202602, upload-time = "2026-02-02T12:36:33.679Z" }, - { url = "https://files.pythonhosted.org/packages/15/fe/13bd3678a311aa67686bb303654792c48206a112068f8b0b21426eb6851e/jiter-0.13.0-cp313-cp313-win_arm64.whl", hash = "sha256:bb7613e1a427cfcb6ea4544f9ac566b93d5bf67e0d48c787eca673ff9c9dff2b", size = 185939, upload-time = "2026-02-02T12:36:35.065Z" }, - { url = "https://files.pythonhosted.org/packages/49/19/a929ec002ad3228bc97ca01dbb14f7632fffdc84a95ec92ceaf4145688ae/jiter-0.13.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:fa476ab5dd49f3bf3a168e05f89358c75a17608dbabb080ef65f96b27c19ab10", size = 316616, upload-time = "2026-02-02T12:36:36.579Z" }, - { url = "https://files.pythonhosted.org/packages/52/56/d19a9a194afa37c1728831e5fb81b7722c3de18a3109e8f282bfc23e587a/jiter-0.13.0-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ade8cb6ff5632a62b7dbd4757d8c5573f7a2e9ae285d6b5b841707d8363205ef", size = 346850, upload-time = "2026-02-02T12:36:38.058Z" }, - { url = "https://files.pythonhosted.org/packages/36/4a/94e831c6bf287754a8a019cb966ed39ff8be6ab78cadecf08df3bb02d505/jiter-0.13.0-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9950290340acc1adaded363edd94baebcee7dabdfa8bee4790794cd5cfad2af6", size = 358551, upload-time = "2026-02-02T12:36:39.417Z" }, - { url = "https://files.pythonhosted.org/packages/a2/ec/a4c72c822695fa80e55d2b4142b73f0012035d9fcf90eccc56bc060db37c/jiter-0.13.0-cp313-cp313t-win_amd64.whl", hash = "sha256:2b4972c6df33731aac0742b64fd0d18e0a69bc7d6e03108ce7d40c85fd9e3e6d", size = 201950, upload-time = "2026-02-02T12:36:40.791Z" }, - { url = "https://files.pythonhosted.org/packages/b6/00/393553ec27b824fbc29047e9c7cd4a3951d7fbe4a76743f17e44034fa4e4/jiter-0.13.0-cp313-cp313t-win_arm64.whl", hash = "sha256:701a1e77d1e593c1b435315ff625fd071f0998c5f02792038a5ca98899261b7d", size = 185852, upload-time = "2026-02-02T12:36:42.077Z" }, - { url = "https://files.pythonhosted.org/packages/6e/f5/f1997e987211f6f9bd71b8083047b316208b4aca0b529bb5f8c96c89ef3e/jiter-0.13.0-cp314-cp314-macosx_10_12_x86_64.whl", hash = "sha256:cc5223ab19fe25e2f0bf2643204ad7318896fe3729bf12fde41b77bfc4fafff0", size = 308804, upload-time = "2026-02-02T12:36:43.496Z" }, - { url = "https://files.pythonhosted.org/packages/cd/8f/5482a7677731fd44881f0204981ce2d7175db271f82cba2085dd2212e095/jiter-0.13.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:9776ebe51713acf438fd9b4405fcd86893ae5d03487546dae7f34993217f8a91", size = 318787, upload-time = "2026-02-02T12:36:45.071Z" }, - { url = "https://files.pythonhosted.org/packages/f3/b9/7257ac59778f1cd025b26a23c5520a36a424f7f1b068f2442a5b499b7464/jiter-0.13.0-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:879e768938e7b49b5e90b7e3fecc0dbec01b8cb89595861fb39a8967c5220d09", size = 353880, upload-time = "2026-02-02T12:36:47.365Z" }, - { url = "https://files.pythonhosted.org/packages/c3/87/719eec4a3f0841dad99e3d3604ee4cba36af4419a76f3cb0b8e2e691ad67/jiter-0.13.0-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:682161a67adea11e3aae9038c06c8b4a9a71023228767477d683f69903ebc607", size = 366702, upload-time = "2026-02-02T12:36:48.871Z" }, - { url = "https://files.pythonhosted.org/packages/d2/65/415f0a75cf6921e43365a1bc227c565cb949caca8b7532776e430cbaa530/jiter-0.13.0-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a13b68cd1cd8cc9de8f244ebae18ccb3e4067ad205220ef324c39181e23bbf66", size = 486319, upload-time = "2026-02-02T12:36:53.006Z" }, - { url = "https://files.pythonhosted.org/packages/54/a2/9e12b48e82c6bbc6081fd81abf915e1443add1b13d8fc586e1d90bb02bb8/jiter-0.13.0-cp314-cp314-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:87ce0f14c6c08892b610686ae8be350bf368467b6acd5085a5b65441e2bf36d2", size = 372289, upload-time = "2026-02-02T12:36:54.593Z" }, - { url = "https://files.pythonhosted.org/packages/4e/c1/e4693f107a1789a239c759a432e9afc592366f04e901470c2af89cfd28e1/jiter-0.13.0-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0c365005b05505a90d1c47856420980d0237adf82f70c4aff7aebd3c1cc143ad", size = 360165, upload-time = "2026-02-02T12:36:56.112Z" }, - { url = "https://files.pythonhosted.org/packages/17/08/91b9ea976c1c758240614bd88442681a87672eebc3d9a6dde476874e706b/jiter-0.13.0-cp314-cp314-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:1317fdffd16f5873e46ce27d0e0f7f4f90f0cdf1d86bf6abeaea9f63ca2c401d", size = 389634, upload-time = "2026-02-02T12:36:57.495Z" }, - { url = "https://files.pythonhosted.org/packages/18/23/58325ef99390d6d40427ed6005bf1ad54f2577866594bcf13ce55675f87d/jiter-0.13.0-cp314-cp314-musllinux_1_1_aarch64.whl", hash = "sha256:c05b450d37ba0c9e21c77fef1f205f56bcee2330bddca68d344baebfc55ae0df", size = 514933, upload-time = "2026-02-02T12:36:58.909Z" }, - { url = "https://files.pythonhosted.org/packages/5b/25/69f1120c7c395fd276c3996bb8adefa9c6b84c12bb7111e5c6ccdcd8526d/jiter-0.13.0-cp314-cp314-musllinux_1_1_x86_64.whl", hash = "sha256:775e10de3849d0631a97c603f996f518159272db00fdda0a780f81752255ee9d", size = 548842, upload-time = "2026-02-02T12:37:00.433Z" }, - { url = "https://files.pythonhosted.org/packages/18/05/981c9669d86850c5fbb0d9e62bba144787f9fba84546ba43d624ee27ef29/jiter-0.13.0-cp314-cp314-win32.whl", hash = "sha256:632bf7c1d28421c00dd8bbb8a3bac5663e1f57d5cd5ed962bce3c73bf62608e6", size = 202108, upload-time = "2026-02-02T12:37:01.718Z" }, - { url = "https://files.pythonhosted.org/packages/8d/96/cdcf54dd0b0341db7d25413229888a346c7130bd20820530905fdb65727b/jiter-0.13.0-cp314-cp314-win_amd64.whl", hash = "sha256:f22ef501c3f87ede88f23f9b11e608581c14f04db59b6a801f354397ae13739f", size = 204027, upload-time = "2026-02-02T12:37:03.075Z" }, - { url = "https://files.pythonhosted.org/packages/fb/f9/724bcaaab7a3cd727031fe4f6995cb86c4bd344909177c186699c8dec51a/jiter-0.13.0-cp314-cp314-win_arm64.whl", hash = "sha256:07b75fe09a4ee8e0c606200622e571e44943f47254f95e2436c8bdcaceb36d7d", size = 187199, upload-time = "2026-02-02T12:37:04.414Z" }, - { url = "https://files.pythonhosted.org/packages/62/92/1661d8b9fd6a3d7a2d89831db26fe3c1509a287d83ad7838831c7b7a5c7e/jiter-0.13.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:964538479359059a35fb400e769295d4b315ae61e4105396d355a12f7fef09f0", size = 318423, upload-time = "2026-02-02T12:37:05.806Z" }, - { url = "https://files.pythonhosted.org/packages/4f/3b/f77d342a54d4ebcd128e520fc58ec2f5b30a423b0fd26acdfc0c6fef8e26/jiter-0.13.0-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e104da1db1c0991b3eaed391ccd650ae8d947eab1480c733e5a3fb28d4313e40", size = 351438, upload-time = "2026-02-02T12:37:07.189Z" }, - { url = "https://files.pythonhosted.org/packages/76/b3/ba9a69f0e4209bd3331470c723c2f5509e6f0482e416b612431a5061ed71/jiter-0.13.0-cp314-cp314t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:0e3a5f0cde8ff433b8e88e41aa40131455420fb3649a3c7abdda6145f8cb7202", size = 364774, upload-time = "2026-02-02T12:37:08.579Z" }, - { url = "https://files.pythonhosted.org/packages/b3/16/6cdb31fa342932602458dbb631bfbd47f601e03d2e4950740e0b2100b570/jiter-0.13.0-cp314-cp314t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:57aab48f40be1db920a582b30b116fe2435d184f77f0e4226f546794cedd9cf0", size = 487238, upload-time = "2026-02-02T12:37:10.066Z" }, - { url = "https://files.pythonhosted.org/packages/ed/b1/956cc7abaca8d95c13aa8d6c9b3f3797241c246cd6e792934cc4c8b250d2/jiter-0.13.0-cp314-cp314t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7772115877c53f62beeb8fd853cab692dbc04374ef623b30f997959a4c0e7e95", size = 372892, upload-time = "2026-02-02T12:37:11.656Z" }, - { url = "https://files.pythonhosted.org/packages/26/c4/97ecde8b1e74f67b8598c57c6fccf6df86ea7861ed29da84629cdbba76c4/jiter-0.13.0-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1211427574b17b633cfceba5040de8081e5abf114f7a7602f73d2e16f9fdaa59", size = 360309, upload-time = "2026-02-02T12:37:13.244Z" }, - { url = "https://files.pythonhosted.org/packages/4b/d7/eabe3cf46715854ccc80be2cd78dd4c36aedeb30751dbf85a1d08c14373c/jiter-0.13.0-cp314-cp314t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:7beae3a3d3b5212d3a55d2961db3c292e02e302feb43fce6a3f7a31b90ea6dfe", size = 389607, upload-time = "2026-02-02T12:37:14.881Z" }, - { url = "https://files.pythonhosted.org/packages/df/2d/03963fc0804e6109b82decfb9974eb92df3797fe7222428cae12f8ccaa0c/jiter-0.13.0-cp314-cp314t-musllinux_1_1_aarch64.whl", hash = "sha256:e5562a0f0e90a6223b704163ea28e831bd3a9faa3512a711f031611e6b06c939", size = 514986, upload-time = "2026-02-02T12:37:16.326Z" }, - { url = "https://files.pythonhosted.org/packages/f6/6c/8c83b45eb3eb1c1e18d841fe30b4b5bc5619d781267ca9bc03e005d8fd0a/jiter-0.13.0-cp314-cp314t-musllinux_1_1_x86_64.whl", hash = "sha256:6c26a424569a59140fb51160a56df13f438a2b0967365e987889186d5fc2f6f9", size = 548756, upload-time = "2026-02-02T12:37:17.736Z" }, - { url = "https://files.pythonhosted.org/packages/47/66/eea81dfff765ed66c68fd2ed8c96245109e13c896c2a5015c7839c92367e/jiter-0.13.0-cp314-cp314t-win32.whl", hash = "sha256:24dc96eca9f84da4131cdf87a95e6ce36765c3b156fc9ae33280873b1c32d5f6", size = 201196, upload-time = "2026-02-02T12:37:19.101Z" }, - { url = "https://files.pythonhosted.org/packages/ff/32/4ac9c7a76402f8f00d00842a7f6b83b284d0cf7c1e9d4227bc95aa6d17fa/jiter-0.13.0-cp314-cp314t-win_amd64.whl", hash = "sha256:0a8d76c7524087272c8ae913f5d9d608bd839154b62c4322ef65723d2e5bb0b8", size = 204215, upload-time = "2026-02-02T12:37:20.495Z" }, - { url = "https://files.pythonhosted.org/packages/f9/8e/7def204fea9f9be8b3c21a6f2dd6c020cf56c7d5ff753e0e23ed7f9ea57e/jiter-0.13.0-cp314-cp314t-win_arm64.whl", hash = "sha256:2c26cf47e2cad140fa23b6d58d435a7c0161f5c514284802f25e87fddfe11024", size = 187152, upload-time = "2026-02-02T12:37:22.124Z" }, - { url = "https://files.pythonhosted.org/packages/79/b3/3c29819a27178d0e461a8571fb63c6ae38be6dc36b78b3ec2876bbd6a910/jiter-0.13.0-graalpy311-graalpy242_311_native-macosx_10_12_x86_64.whl", hash = "sha256:b1cbfa133241d0e6bdab48dcdc2604e8ba81512f6bbd68ec3e8e1357dd3c316c", size = 307016, upload-time = "2026-02-02T12:37:42.755Z" }, - { url = "https://files.pythonhosted.org/packages/eb/ae/60993e4b07b1ac5ebe46da7aa99fdbb802eb986c38d26e3883ac0125c4e0/jiter-0.13.0-graalpy311-graalpy242_311_native-macosx_11_0_arm64.whl", hash = "sha256:db367d8be9fad6e8ebbac4a7578b7af562e506211036cba2c06c3b998603c3d2", size = 305024, upload-time = "2026-02-02T12:37:44.774Z" }, - { url = "https://files.pythonhosted.org/packages/77/fa/2227e590e9cf98803db2811f172b2d6460a21539ab73006f251c66f44b14/jiter-0.13.0-graalpy311-graalpy242_311_native-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:45f6f8efb2f3b0603092401dc2df79fa89ccbc027aaba4174d2d4133ed661434", size = 339337, upload-time = "2026-02-02T12:37:46.668Z" }, - { url = "https://files.pythonhosted.org/packages/2d/92/015173281f7eb96c0ef580c997da8ef50870d4f7f4c9e03c845a1d62ae04/jiter-0.13.0-graalpy311-graalpy242_311_native-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:597245258e6ad085d064780abfb23a284d418d3e61c57362d9449c6c7317ee2d", size = 346395, upload-time = "2026-02-02T12:37:48.09Z" }, - { url = "https://files.pythonhosted.org/packages/80/60/e50fa45dd7e2eae049f0ce964663849e897300433921198aef94b6ffa23a/jiter-0.13.0-graalpy312-graalpy250_312_native-macosx_10_12_x86_64.whl", hash = "sha256:3d744a6061afba08dd7ae375dcde870cffb14429b7477e10f67e9e6d68772a0a", size = 305169, upload-time = "2026-02-02T12:37:50.376Z" }, - { url = "https://files.pythonhosted.org/packages/d2/73/a009f41c5eed71c49bec53036c4b33555afcdee70682a18c6f66e396c039/jiter-0.13.0-graalpy312-graalpy250_312_native-macosx_11_0_arm64.whl", hash = "sha256:ff732bd0a0e778f43d5009840f20b935e79087b4dc65bd36f1cd0f9b04b8ff7f", size = 303808, upload-time = "2026-02-02T12:37:52.092Z" }, - { url = "https://files.pythonhosted.org/packages/c4/10/528b439290763bff3d939268085d03382471b442f212dca4ff5f12802d43/jiter-0.13.0-graalpy312-graalpy250_312_native-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ab44b178f7981fcaea7e0a5df20e773c663d06ffda0198f1a524e91b2fde7e59", size = 337384, upload-time = "2026-02-02T12:37:53.582Z" }, - { url = "https://files.pythonhosted.org/packages/67/8a/a342b2f0251f3dac4ca17618265d93bf244a2a4d089126e81e4c1056ac50/jiter-0.13.0-graalpy312-graalpy250_312_native-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7bb00b6d26db67a05fe3e12c76edc75f32077fb51deed13822dc648fa373bc19", size = 343768, upload-time = "2026-02-02T12:37:55.055Z" }, +sdist = { url = "https://files.pythonhosted.org/packages/6e/c1/0cddc6eb17d4c53a99840953f95dd3accdc5cfc7a337b0e9b26476276be9/jiter-0.14.0.tar.gz", hash = "sha256:e8a39e66dac7153cf3f964a12aad515afa8d74938ec5cc0018adcdae5367c79e", size = 165725, upload-time = "2026-04-10T14:28:42.01Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/64/2e/a9959997739c403378d0a4a3a1c4ed80b60aeace216c4d37b303a9fc60a4/jiter-0.14.0-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:02f36a5c700f105ac04a6556fe664a59037a2c200db3b7e88784fac2ddf02531", size = 316927, upload-time = "2026-04-10T14:25:40.753Z" }, + { url = "https://files.pythonhosted.org/packages/27/72/b6de8a531e0adbadd839bec301165feb1fccf00e9ff55073ba2dd20f0043/jiter-0.14.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:41eab6c09ceffb6f0fe25e214b3068146edb1eda3649ca2aee2a061029c7ba2e", size = 321181, upload-time = "2026-04-10T14:25:42.621Z" }, + { url = "https://files.pythonhosted.org/packages/db/d8/2040b9efa13c917f855c40890ae4119fe02c25b7c7677d5b4fa820a851fc/jiter-0.14.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5cf4d4c109641f9cfaf4a7b6aebd51654e405cd00fa9ebbf87163b8b97b325aa", size = 347387, upload-time = "2026-04-10T14:25:44.212Z" }, + { url = "https://files.pythonhosted.org/packages/49/62/655c0ad5ce6a8e90f9068c175b8a236877d753e460762b3183c136db1c5b/jiter-0.14.0-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:b80c7b41a628e6be2213ad0ece763c5f88aa5ee003fa394d58acaaee1f4b8342", size = 373083, upload-time = "2026-04-10T14:25:45.55Z" }, + { url = "https://files.pythonhosted.org/packages/f1/66/549c40fa068f08710b7570869c306a051eb67a29758bd64f4114f730554c/jiter-0.14.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:fb3dbf7cc0d4dbe73cce307ebe7eefa7f73a7d3d854dd119ea0c243f03e40927", size = 463639, upload-time = "2026-04-10T14:25:47.452Z" }, + { url = "https://files.pythonhosted.org/packages/25/2f/97a32a05fed14ed58a18e181fdfb619e05163f3726b54ee6080ec0539c09/jiter-0.14.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7054adcdeb06b46efd17b5734f75817a44a2d06d3748e36c3a023a1bb52af9ec", size = 380735, upload-time = "2026-04-10T14:25:49.305Z" }, + { url = "https://files.pythonhosted.org/packages/2a/3b/4347e1d6c2a973d653bbb7a2d671a2d2426e54b52ba735b8ff0d0a29b75c/jiter-0.14.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d597cd1bf6790376f3fffc7c708766e57301d99a19314824ea0ccc9c3c70e1e2", size = 358632, upload-time = "2026-04-10T14:25:50.931Z" }, + { url = "https://files.pythonhosted.org/packages/ef/24/ca452fbf2ea33548ed30ce68a39a50442d3f7c9bf0704a7af958a930c057/jiter-0.14.0-cp310-cp310-manylinux_2_31_riscv64.whl", hash = "sha256:df63a14878da754427926281626fd3ee249424a186e25a274e78176d42945264", size = 359969, upload-time = "2026-04-10T14:25:52.381Z" }, + { url = "https://files.pythonhosted.org/packages/e3/a3/94470a0d199287caabeb4da2bb2ae5f6d17f3cf05dfc975d7cb064d58e0f/jiter-0.14.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:4ea73187627bcc5810e085df715e8a99da8bdfd96a7eb36b4b4df700ba6d4c9c", size = 397529, upload-time = "2026-04-10T14:25:53.801Z" }, + { url = "https://files.pythonhosted.org/packages/cf/71/6768edc09d7c45c39f093feb3de105fa718a3e982b5208b8a2ed6382b44b/jiter-0.14.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:9f541eaf7bb8382367a1a23d6fc3d6aad57f8dd8c18c3c17f838bee20f217220", size = 522342, upload-time = "2026-04-10T14:25:55.396Z" }, + { url = "https://files.pythonhosted.org/packages/3d/6b/5c2e17559a0f4e96e934479f7137df46c939e983fa05244e674815befb73/jiter-0.14.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:107465250de4fce00fdb47166bcd51df8e634e049541174fe3c71848e44f52ce", size = 556784, upload-time = "2026-04-10T14:25:56.927Z" }, + { url = "https://files.pythonhosted.org/packages/b1/83/c25f3556a60fc74d11199100f1b6cc0c006b815c8494dea8ca16fe398732/jiter-0.14.0-cp310-cp310-win32.whl", hash = "sha256:ffb2a08a406465bb076b7cc1df41d833106d3cf7905076cc73f0cb90078c7d10", size = 208439, upload-time = "2026-04-10T14:25:58.796Z" }, + { url = "https://files.pythonhosted.org/packages/2e/99/781a1b413f0989b7f2ea203b094b331685f1a35e52e0a45e5d000ecaab27/jiter-0.14.0-cp310-cp310-win_amd64.whl", hash = "sha256:cb8b682d10cb0cce7ff4c1af7244af7022c9b01ae16d46c357bdd0df13afb25d", size = 204558, upload-time = "2026-04-10T14:26:00.208Z" }, + { url = "https://files.pythonhosted.org/packages/8a/1f/198ae537fccb7080a0ed655eb56abf64a92f79489dfbf79f40fa34225bcd/jiter-0.14.0-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:7e791e247b8044512e070bd1f3633dc08350d32776d2d6e7473309d0edf256a2", size = 316896, upload-time = "2026-04-10T14:26:01.986Z" }, + { url = "https://files.pythonhosted.org/packages/cf/34/da67cff3fce964a36d03c3e365fb0f8726ade2a6cfd4d3c70107e216ead6/jiter-0.14.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:71527ce13fd5a0c4e40ad37331f8c547177dbb2dd0a93e5278b6a5eecf748804", size = 321085, upload-time = "2026-04-10T14:26:03.364Z" }, + { url = "https://files.pythonhosted.org/packages/ed/36/4c72e67180d4e71a4f5dcf7886d0840e83c49ab11788172177a77570326e/jiter-0.14.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:02c4a7ab56f746014874f2c525584c0daca1dec37f66fd707ecef3b7e5c2228c", size = 347393, upload-time = "2026-04-10T14:26:05.314Z" }, + { url = "https://files.pythonhosted.org/packages/bc/db/9b39e09ceafa9878235c0fc29e3e3f9b12a4c6a98ea3085b998cadf3accc/jiter-0.14.0-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:376e9dafff914253bb9d46cdc5f7965607fbe7feb0a491c34e35f92b2770702e", size = 372937, upload-time = "2026-04-10T14:26:06.884Z" }, + { url = "https://files.pythonhosted.org/packages/b0/96/0dcba1d7a82c1b720774b48ef239376addbaf30df24c34742ac4a57b67b2/jiter-0.14.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:23ad2a7a9da1935575c820428dd8d2490ce4d23189691ce33da1fc0a58e14e1c", size = 463646, upload-time = "2026-04-10T14:26:08.345Z" }, + { url = "https://files.pythonhosted.org/packages/f1/e3/f61b71543e746e6b8b805e7755814fc242715c16f1dba58e1cbccb8032c2/jiter-0.14.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:54b3ddf5786bc7732d293bba3411ac637ecfa200a39983166d1df86a59a43c9f", size = 380225, upload-time = "2026-04-10T14:26:10.161Z" }, + { url = "https://files.pythonhosted.org/packages/ad/5e/0ddeb7096aca099114abe36c4921016e8d251e6f35f5890240b31f1f60ae/jiter-0.14.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5c001d5a646c2a50dc055dd526dad5d5245969e8234d2b1131d0451e81f3a373", size = 358682, upload-time = "2026-04-10T14:26:11.574Z" }, + { url = "https://files.pythonhosted.org/packages/e9/d1/fe0c46cd7fda9cad8f1ff9ad217dc61f1e4280b21052ec6dfe88c1446ef2/jiter-0.14.0-cp311-cp311-manylinux_2_31_riscv64.whl", hash = "sha256:834bb5bdabca2e91592a03d373838a8d0a1b8bbde7077ae6913fd2fc51812d00", size = 359973, upload-time = "2026-04-10T14:26:13.316Z" }, + { url = "https://files.pythonhosted.org/packages/ac/21/f5317f91729b501019184771c80d60abd89907009e7bfa6c7e348c5bdd44/jiter-0.14.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:4e9178be60e229b1b2b0710f61b9e24d1f4f8556985a83ff4c4f95920eea7314", size = 397568, upload-time = "2026-04-10T14:26:15.212Z" }, + { url = "https://files.pythonhosted.org/packages/e9/05/79d8f33fb2bf168db0df5c9cd16fe440a8ada57e929d3677b22712c2568f/jiter-0.14.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:a7e4ccff04ec03614e62c613e976a3a5860dc9714ce8266f44328bdc8b1cab2c", size = 522535, upload-time = "2026-04-10T14:26:16.956Z" }, + { url = "https://files.pythonhosted.org/packages/5c/00/d1e3ff3d2a465e67f08507d74bafb2dcd29eba91dc939820e39e8dea38b8/jiter-0.14.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:69539d936fb5d55caf6ecd33e2e884de083ff0ea28579780d56c4403094bb8d9", size = 556709, upload-time = "2026-04-10T14:26:18.5Z" }, + { url = "https://files.pythonhosted.org/packages/60/5b/bbb2189f62ace8d95e869aa4c84c9946616f301e2d02895a6f20dcc3bba3/jiter-0.14.0-cp311-cp311-win32.whl", hash = "sha256:4927d09b3e572787cc5e0a5318601448e1ab9391bcef95677f5840c2d00eaa6d", size = 208660, upload-time = "2026-04-10T14:26:20.511Z" }, + { url = "https://files.pythonhosted.org/packages/b8/86/c500b53dcbf08575f5963e536ebd757a1f7c568272ba5d180b212c9a87fb/jiter-0.14.0-cp311-cp311-win_amd64.whl", hash = "sha256:42d6ed359ac49eb922fdd565f209c57340aa06d589c84c8413e42a0f9ae1b842", size = 204659, upload-time = "2026-04-10T14:26:22.152Z" }, + { url = "https://files.pythonhosted.org/packages/75/4a/a676249049d42cb29bef82233e4fe0524d414cbe3606c7a4b311193c2f77/jiter-0.14.0-cp311-cp311-win_arm64.whl", hash = "sha256:6dd689f5f4a5a33747b28686e051095beb214fe28cfda5e9fe58a295a788f593", size = 194772, upload-time = "2026-04-10T14:26:23.458Z" }, + { url = "https://files.pythonhosted.org/packages/5a/68/7390a418f10897da93b158f2d5a8bd0bcd73a0f9ec3bb36917085bb759ef/jiter-0.14.0-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:2fb2ce3a7bc331256dfb14cefc34832366bb28a9aca81deaf43bbf2a5659e607", size = 316295, upload-time = "2026-04-10T14:26:24.887Z" }, + { url = "https://files.pythonhosted.org/packages/60/a0/5854ac00ff63551c52c6c89534ec6aba4b93474e7924d64e860b1c94165b/jiter-0.14.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:5252a7ca23785cef5d02d4ece6077a1b556a410c591b379f82091c3001e14844", size = 315898, upload-time = "2026-04-10T14:26:26.601Z" }, + { url = "https://files.pythonhosted.org/packages/41/a1/4f44832650a16b18e8391f1bf1d6ca4909bc738351826bcc198bba4357f4/jiter-0.14.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c409578cbd77c338975670ada777add4efd53379667edf0aceea730cabede6fb", size = 343730, upload-time = "2026-04-10T14:26:28.326Z" }, + { url = "https://files.pythonhosted.org/packages/48/64/a329e9d469f86307203594b1707e11ae51c3348d03bfd514a5f997870012/jiter-0.14.0-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:7ede4331a1899d604463369c730dbb961ffdc5312bc7f16c41c2896415b1304a", size = 370102, upload-time = "2026-04-10T14:26:30.089Z" }, + { url = "https://files.pythonhosted.org/packages/94/c1/5e3dfc59635aa4d4c7bd20a820ac1d09b8ed851568356802cf1c08edb3cf/jiter-0.14.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:92cd8b6025981a041f5310430310b55b25ca593972c16407af8837d3d7d2ca01", size = 461335, upload-time = "2026-04-10T14:26:31.911Z" }, + { url = "https://files.pythonhosted.org/packages/e3/1b/dd157009dbc058f7b00108f545ccb72a2d56461395c4fc7b9cfdccb00af4/jiter-0.14.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:351bf6eda4e3a7ceb876377840c702e9a3e4ecc4624dbfb2d6463c67ae52637d", size = 378536, upload-time = "2026-04-10T14:26:33.595Z" }, + { url = "https://files.pythonhosted.org/packages/91/78/256013667b7c10b8834f8e6e54cd3e562d4c6e34227a1596addccc05e38c/jiter-0.14.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c1dcfbeb93d9ecd9ca128bbf8910120367777973fa193fb9a39c31237d8df165", size = 353859, upload-time = "2026-04-10T14:26:35.098Z" }, + { url = "https://files.pythonhosted.org/packages/de/d9/137d65ade9093a409fe80955ce60b12bb753722c986467aeda47faf450ad/jiter-0.14.0-cp312-cp312-manylinux_2_31_riscv64.whl", hash = "sha256:ae039aaef8de3f8157ecc1fdd4d85043ac4f57538c245a0afaecb8321ec951c3", size = 357626, upload-time = "2026-04-10T14:26:36.685Z" }, + { url = "https://files.pythonhosted.org/packages/2e/48/76750835b87029342727c1a268bea8878ab988caf81ee4e7b880900eeb5a/jiter-0.14.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:7d9d51eb96c82a9652933bd769fe6de66877d6eb2b2440e281f2938c51b5643e", size = 393172, upload-time = "2026-04-10T14:26:38.097Z" }, + { url = "https://files.pythonhosted.org/packages/a6/60/456c4e81d5c8045279aefe60e9e483be08793828800a4e64add8fdde7f2a/jiter-0.14.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:d824ca4148b705970bf4e120924a212fdfca9859a73e42bd7889a63a4ea6bb98", size = 520300, upload-time = "2026-04-10T14:26:39.532Z" }, + { url = "https://files.pythonhosted.org/packages/a8/9f/2020e0984c235f678dced38fe4eec3058cf528e6af36ebf969b410305941/jiter-0.14.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:ff3a6465b3a0f54b1a430f45c3c0ba7d61ceb45cbc3e33f9e1a7f638d690baf3", size = 553059, upload-time = "2026-04-10T14:26:40.991Z" }, + { url = "https://files.pythonhosted.org/packages/ef/32/e2d298e1a22a4bbe6062136d1c7192db7dba003a6975e51d9a9eecabc4c2/jiter-0.14.0-cp312-cp312-win32.whl", hash = "sha256:5dec7c0a3e98d2a3f8a2e67382d0d7c3ac60c69103a4b271da889b4e8bb1e129", size = 206030, upload-time = "2026-04-10T14:26:42.517Z" }, + { url = "https://files.pythonhosted.org/packages/36/ac/96369141b3d8a4a8e4590e983085efe1c436f35c0cda940dd76d942e3e40/jiter-0.14.0-cp312-cp312-win_amd64.whl", hash = "sha256:fc7e37b4b8bc7e80a63ad6cfa5fc11fab27dbfea4cc4ae644b1ab3f273dc348f", size = 201603, upload-time = "2026-04-10T14:26:44.328Z" }, + { url = "https://files.pythonhosted.org/packages/01/c3/75d847f264647017d7e3052bbcc8b1e24b95fa139c320c5f5066fa7a0bdd/jiter-0.14.0-cp312-cp312-win_arm64.whl", hash = "sha256:ee4a72f12847ef29b072aee9ad5474041ab2924106bdca9fcf5d7d965853e057", size = 191525, upload-time = "2026-04-10T14:26:46Z" }, + { url = "https://files.pythonhosted.org/packages/97/2a/09f70020898507a89279659a1afe3364d57fc1b2c89949081975d135f6f5/jiter-0.14.0-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:af72f204cf4d44258e5b4c1745130ac45ddab0e71a06333b01de660ab4187a94", size = 315502, upload-time = "2026-04-10T14:26:47.697Z" }, + { url = "https://files.pythonhosted.org/packages/d6/be/080c96a45cd74f9fce5db4fd68510b88087fb37ffe2541ff73c12db92535/jiter-0.14.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:4b77da71f6e819be5fbcec11a453fde5b1d0267ef6ed487e2a392fd8e14e4e3a", size = 314870, upload-time = "2026-04-10T14:26:49.149Z" }, + { url = "https://files.pythonhosted.org/packages/7d/5e/2d0fee155826a968a832cc32438de5e2a193292c8721ca70d0b53e58245b/jiter-0.14.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:77f4ea612fe8b84b8b04e51d0e78029ecf3466348e25973f953de6e6a59aa4c1", size = 343406, upload-time = "2026-04-10T14:26:50.762Z" }, + { url = "https://files.pythonhosted.org/packages/70/af/bf9ee0d3a4f8dc0d679fc1337f874fe60cdbf841ebbb304b374e1c9aaceb/jiter-0.14.0-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:62fe2451f8fcc0240261e6a4df18ecbcd58327857e61e625b2393ea3b468aac9", size = 369415, upload-time = "2026-04-10T14:26:52.188Z" }, + { url = "https://files.pythonhosted.org/packages/0f/83/8e8561eadba31f4d3948a5b712fb0447ec71c3560b57a855449e7b8ddc98/jiter-0.14.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6112f26f5afc75bcb475787d29da3aa92f9d09c7858f632f4be6ffe607be82e9", size = 461456, upload-time = "2026-04-10T14:26:53.611Z" }, + { url = "https://files.pythonhosted.org/packages/f6/c9/c5299e826a5fe6108d172b344033f61c69b1bb979dd8d9ddd4278a160971/jiter-0.14.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:215a6cb8fb7dc702aa35d475cc00ddc7f970e5c0b1417fb4b4ac5d82fa2a29db", size = 378488, upload-time = "2026-04-10T14:26:55.211Z" }, + { url = "https://files.pythonhosted.org/packages/5d/37/c16d9d15c0a471b8644b1abe3c82668092a707d9bedcf076f24ff2e380cd/jiter-0.14.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fc4ab96a30fb3cb2c7e0cd33f7616c8860da5f5674438988a54ac717caccdbaa", size = 353242, upload-time = "2026-04-10T14:26:56.705Z" }, + { url = "https://files.pythonhosted.org/packages/58/ea/8050cb0dc654e728e1bfacbc0c640772f2181af5dedd13ae70145743a439/jiter-0.14.0-cp313-cp313-manylinux_2_31_riscv64.whl", hash = "sha256:3a99c1387b1f2928f799a9de899193484d66206a50e98233b6b088a7f0c1edb2", size = 356823, upload-time = "2026-04-10T14:26:58.281Z" }, + { url = "https://files.pythonhosted.org/packages/b0/3b/cf71506d270e5f84d97326bf220e47aed9b95e9a4a060758fb07772170ab/jiter-0.14.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:ab18d11074485438695f8d34a1b6da61db9754248f96d51341956607a8f39985", size = 392564, upload-time = "2026-04-10T14:27:00.018Z" }, + { url = "https://files.pythonhosted.org/packages/b0/cc/8c6c74a3efb5bd671bfd14f51e8a73375464ca914b1551bc3b40e26ac2c9/jiter-0.14.0-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:801028dcfc26ac0895e4964cbc0fd62c73be9fd4a7d7b1aaf6e5790033a719b7", size = 520322, upload-time = "2026-04-10T14:27:01.664Z" }, + { url = "https://files.pythonhosted.org/packages/41/24/68d7b883ec959884ddf00d019b2e0e82ba81b167e1253684fa90519ce33c/jiter-0.14.0-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:ad425b087aafb4a1c7e1e98a279200743b9aaf30c3e0ba723aec93f061bd9bc8", size = 552619, upload-time = "2026-04-10T14:27:03.316Z" }, + { url = "https://files.pythonhosted.org/packages/b6/89/b1a0985223bbf3150ff9e8f46f98fc9360c1de94f48abe271bbe1b465682/jiter-0.14.0-cp313-cp313-win32.whl", hash = "sha256:882bcb9b334318e233950b8be366fe5f92c86b66a7e449e76975dfd6d776a01f", size = 205699, upload-time = "2026-04-10T14:27:04.662Z" }, + { url = "https://files.pythonhosted.org/packages/4c/19/3f339a5a7f14a11730e67f6be34f9d5105751d547b615ef593fa122a5ded/jiter-0.14.0-cp313-cp313-win_amd64.whl", hash = "sha256:9b8c571a5dba09b98bd3462b5a53f27209a5cbbe85670391692ede71974e979f", size = 201323, upload-time = "2026-04-10T14:27:06.139Z" }, + { url = "https://files.pythonhosted.org/packages/50/56/752dd89c84be0e022a8ea3720bcfa0a8431db79a962578544812ce061739/jiter-0.14.0-cp313-cp313-win_arm64.whl", hash = "sha256:34f19dcc35cb1abe7c369b3756babf8c7f04595c0807a848df8f26ef8298ef92", size = 191099, upload-time = "2026-04-10T14:27:07.564Z" }, + { url = "https://files.pythonhosted.org/packages/91/28/292916f354f25a1fe8cf2c918d1415c699a4a659ae00be0430e1c5d9ffea/jiter-0.14.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:e89bcd7d426a75bb4952c696b267075790d854a07aad4c9894551a82c5b574ab", size = 320880, upload-time = "2026-04-10T14:27:09.326Z" }, + { url = "https://files.pythonhosted.org/packages/ad/c7/b002a7d8b8957ac3d469bd59c18ef4b1595a5216ae0de639a287b9816023/jiter-0.14.0-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7b25beaa0d4447ea8c7ae0c18c688905d34840d7d0b937f2f7bdd52162c98a40", size = 346563, upload-time = "2026-04-10T14:27:11.287Z" }, + { url = "https://files.pythonhosted.org/packages/f9/3b/f8d07580d8706021d255a6356b8fab13ee4c869412995550ce6ed4ddf97d/jiter-0.14.0-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:651a8758dd413c51e3b7f6557cdc6921faf70b14106f45f969f091f5cda990ea", size = 357928, upload-time = "2026-04-10T14:27:12.729Z" }, + { url = "https://files.pythonhosted.org/packages/47/5b/ac1a974da29e35507230383110ffec59998b290a8732585d04e19a9eb5ba/jiter-0.14.0-cp313-cp313t-win_amd64.whl", hash = "sha256:e1a7eead856a5038a8d291f1447176ab0b525c77a279a058121b5fccee257f6f", size = 203519, upload-time = "2026-04-10T14:27:14.125Z" }, + { url = "https://files.pythonhosted.org/packages/96/6d/9fc8433d667d2454271378a79747d8c76c10b51b482b454e6190e511f244/jiter-0.14.0-cp313-cp313t-win_arm64.whl", hash = "sha256:2e692633a12cda97e352fdcd1c4acc971b1c28707e1e33aeef782b0cbf051975", size = 190113, upload-time = "2026-04-10T14:27:16.638Z" }, + { url = "https://files.pythonhosted.org/packages/4f/1e/354ed92461b165bd581f9ef5150971a572c873ec3b68a916d5aa91da3cc2/jiter-0.14.0-cp314-cp314-macosx_10_12_x86_64.whl", hash = "sha256:6f396837fc7577871ca8c12edaf239ed9ccef3bbe39904ae9b8b63ce0a48b140", size = 315277, upload-time = "2026-04-10T14:27:18.109Z" }, + { url = "https://files.pythonhosted.org/packages/a6/95/8c7c7028aa8636ac21b7a55faef3e34215e6ed0cbf5ae58258427f621aa3/jiter-0.14.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:a4d50ea3d8ba4176f79754333bd35f1bbcd28e91adc13eb9b7ca91bc52a6cef9", size = 315923, upload-time = "2026-04-10T14:27:19.603Z" }, + { url = "https://files.pythonhosted.org/packages/47/40/e2a852a44c4a089f2681a16611b7ce113224a80fd8504c46d78491b47220/jiter-0.14.0-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ce17f8a050447d1b4153bda4fb7d26e6a9e74eb4f4a41913f30934c5075bf615", size = 344943, upload-time = "2026-04-10T14:27:21.262Z" }, + { url = "https://files.pythonhosted.org/packages/fc/1f/670f92adee1e9895eac41e8a4d623b6da68c4d46249d8b556b60b63f949e/jiter-0.14.0-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:f4f1c4b125e1652aefbc2e2c1617b60a160ab789d180e3d423c41439e5f32850", size = 369725, upload-time = "2026-04-10T14:27:22.766Z" }, + { url = "https://files.pythonhosted.org/packages/01/2f/541c9ba567d05de1c4874a0f8f8c5e3fd78e2b874266623da9a775cf46e0/jiter-0.14.0-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:be808176a6a3a14321d18c603f2d40741858a7c4fc982f83232842689fe86dd9", size = 461210, upload-time = "2026-04-10T14:27:24.315Z" }, + { url = "https://files.pythonhosted.org/packages/ce/a9/c31cbec09627e0d5de7aeaec7690dba03e090caa808fefd8133137cf45bc/jiter-0.14.0-cp314-cp314-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:26679d58ba816f88c3849306dd58cb863a90a1cf352cdd4ef67e30ccf8a77994", size = 380002, upload-time = "2026-04-10T14:27:26.155Z" }, + { url = "https://files.pythonhosted.org/packages/50/02/3c05c1666c41904a2f607475a73e7a4763d1cbde2d18229c4f85b22dc253/jiter-0.14.0-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:80381f5a19af8fa9aef743f080e34f6b25ebd89656475f8cf0470ec6157052aa", size = 354678, upload-time = "2026-04-10T14:27:27.701Z" }, + { url = "https://files.pythonhosted.org/packages/7d/97/e15b33545c2b13518f560d695f974b9891b311641bdcf178d63177e8801e/jiter-0.14.0-cp314-cp314-manylinux_2_31_riscv64.whl", hash = "sha256:004df5fdb8ecbd6d99f3227df18ba1a259254c4359736a2e6f036c944e02d7c5", size = 358920, upload-time = "2026-04-10T14:27:29.256Z" }, + { url = "https://files.pythonhosted.org/packages/ad/d2/8b1461def6b96ba44530df20d07ef7a1c7da22f3f9bf1727e2d611077bf1/jiter-0.14.0-cp314-cp314-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:cff5708f7ed0fa098f2b53446c6fa74c48469118e5cd7497b4f1cd569ab06928", size = 394512, upload-time = "2026-04-10T14:27:31.344Z" }, + { url = "https://files.pythonhosted.org/packages/e3/88/837566dd6ed6e452e8d3205355afd484ce44b2533edfa4ed73a298ea893e/jiter-0.14.0-cp314-cp314-musllinux_1_1_aarch64.whl", hash = "sha256:2492e5f06c36a976d25c7cc347a60e26d5470178d44cde1b9b75e60b4e519f28", size = 521120, upload-time = "2026-04-10T14:27:33.299Z" }, + { url = "https://files.pythonhosted.org/packages/89/6b/b00b45c4d1b4c031777fe161d620b755b5b02cdade1e316dcb46e4471d63/jiter-0.14.0-cp314-cp314-musllinux_1_1_x86_64.whl", hash = "sha256:7609cfbe3a03d37bfdbf5052012d5a879e72b83168a363deae7b3a26564d57de", size = 553668, upload-time = "2026-04-10T14:27:34.868Z" }, + { url = "https://files.pythonhosted.org/packages/ad/d8/6fe5b42011d19397433d345716eac16728ac241862a2aac9c91923c7509a/jiter-0.14.0-cp314-cp314-win32.whl", hash = "sha256:7282342d32e357543565286b6450378c3cd402eea333fc1ebe146f1fabb306fc", size = 207001, upload-time = "2026-04-10T14:27:36.455Z" }, + { url = "https://files.pythonhosted.org/packages/e5/43/5c2e08da1efad5e410f0eaaabeadd954812612c33fbbd8fd5328b489139d/jiter-0.14.0-cp314-cp314-win_amd64.whl", hash = "sha256:bd77945f38866a448e73b0b7637366afa814d4617790ecd88a18ca74377e6c02", size = 202187, upload-time = "2026-04-10T14:27:38Z" }, + { url = "https://files.pythonhosted.org/packages/aa/1f/6e39ac0b4cdfa23e606af5b245df5f9adaa76f35e0c5096790da430ca506/jiter-0.14.0-cp314-cp314-win_arm64.whl", hash = "sha256:f2d4c61da0821ee42e0cdf5489da60a6d074306313a377c2b35af464955a3611", size = 192257, upload-time = "2026-04-10T14:27:39.504Z" }, + { url = "https://files.pythonhosted.org/packages/05/57/7dbc0ffbbb5176a27e3518716608aa464aee2e2887dc938f0b900a120449/jiter-0.14.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:1bf7ff85517dd2f20a5750081d2b75083c1b269cf75afc7511bdf1f9548beb3b", size = 323441, upload-time = "2026-04-10T14:27:41.039Z" }, + { url = "https://files.pythonhosted.org/packages/83/6e/7b3314398d8983f06b557aa21b670511ec72d3b79a68ee5e4d9bff972286/jiter-0.14.0-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c8ef8791c3e78d6c6b157c6d360fbb5c715bebb8113bc6a9303c5caff012754a", size = 348109, upload-time = "2026-04-10T14:27:42.552Z" }, + { url = "https://files.pythonhosted.org/packages/ae/4f/8dc674bcd7db6dba566de73c08c763c337058baff1dbeb34567045b27cdc/jiter-0.14.0-cp314-cp314t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e74663b8b10da1fe0f4e4703fd7980d24ad17174b6bb35d8498d6e3ebce2ae6a", size = 368328, upload-time = "2026-04-10T14:27:44.574Z" }, + { url = "https://files.pythonhosted.org/packages/3b/5f/188e09a1f20906f98bbdec44ed820e19f4e8eb8aff88b9d1a5a497587ff3/jiter-0.14.0-cp314-cp314t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1aca29ba52913f78362ec9c2da62f22cdc4c3083313403f90c15460979b84d9b", size = 463301, upload-time = "2026-04-10T14:27:46.717Z" }, + { url = "https://files.pythonhosted.org/packages/ac/f0/19046ef965ed8f349e8554775bb12ff4352f443fbe12b95d31f575891256/jiter-0.14.0-cp314-cp314t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8b39b7d87a952b79949af5fef44d2544e58c21a28da7f1bae3ef166455c61746", size = 378891, upload-time = "2026-04-10T14:27:48.32Z" }, + { url = "https://files.pythonhosted.org/packages/c4/c3/da43bd8431ee175695777ee78cf0e93eacbb47393ff493f18c45231b427d/jiter-0.14.0-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:78d918a68b26e9fab068c2b5453577ef04943ab2807b9a6275df2a812599a310", size = 360749, upload-time = "2026-04-10T14:27:49.88Z" }, + { url = "https://files.pythonhosted.org/packages/72/26/e054771be889707c6161dbdec9c23d33a9ec70945395d70f07cfea1e9a6f/jiter-0.14.0-cp314-cp314t-manylinux_2_31_riscv64.whl", hash = "sha256:b08997c35aee1201c1a5361466a8fb9162d03ae7bf6568df70b6c859f1e654a4", size = 358526, upload-time = "2026-04-10T14:27:51.504Z" }, + { url = "https://files.pythonhosted.org/packages/c3/0f/7bea65ea2a6d91f2bf989ff11a18136644392bf2b0497a1fa50934c30a9c/jiter-0.14.0-cp314-cp314t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:260bf7ca20704d58d41f669e5e9fe7fe2fa72901a6b324e79056f5d52e9c9be2", size = 393926, upload-time = "2026-04-10T14:27:53.368Z" }, + { url = "https://files.pythonhosted.org/packages/3c/a1/b1ff7d70deef61ac0b7c6c2f12d2ace950cdeecb4fdc94500a0926802857/jiter-0.14.0-cp314-cp314t-musllinux_1_1_aarch64.whl", hash = "sha256:37826e3df29e60f30a382f9294348d0238ef127f4b5d7f5f8da78b5b9e050560", size = 521052, upload-time = "2026-04-10T14:27:55.058Z" }, + { url = "https://files.pythonhosted.org/packages/0b/7b/3b0649983cbaf15eda26a414b5b1982e910c67bd6f7b1b490f3cfc76896a/jiter-0.14.0-cp314-cp314t-musllinux_1_1_x86_64.whl", hash = "sha256:645be49c46f2900937ba0eaf871ad5183c96858c0af74b6becc7f4e367e36e06", size = 553716, upload-time = "2026-04-10T14:27:57.269Z" }, + { url = "https://files.pythonhosted.org/packages/97/f8/33d78c83bd93ae0c0af05293a6660f88a1977caef39a6d72a84afab94ce0/jiter-0.14.0-cp314-cp314t-win32.whl", hash = "sha256:2f7877ed45118de283786178eceaf877110abacd04fde31efff3940ae9672674", size = 207957, upload-time = "2026-04-10T14:27:59.285Z" }, + { url = "https://files.pythonhosted.org/packages/d6/ac/2b760516c03e2227826d1f7025d89bf6bf6357a28fe75c2a2800873c50bf/jiter-0.14.0-cp314-cp314t-win_amd64.whl", hash = "sha256:14c0cb10337c49f5eafe8e7364daca5e29a020ea03580b8f8e6c597fed4e1588", size = 204690, upload-time = "2026-04-10T14:28:00.962Z" }, + { url = "https://files.pythonhosted.org/packages/dc/2e/a44c20c58aeed0355f2d326969a181696aeb551a25195f47563908a815be/jiter-0.14.0-cp314-cp314t-win_arm64.whl", hash = "sha256:5419d4aa2024961da9fe12a9cfe7484996735dca99e8e090b5c88595ef1951ff", size = 191338, upload-time = "2026-04-10T14:28:02.853Z" }, + { url = "https://files.pythonhosted.org/packages/32/a1/ef34ca2cab2962598591636a1804b93645821201cc0095d4a93a9a329c9d/jiter-0.14.0-graalpy311-graalpy242_311_native-macosx_10_12_x86_64.whl", hash = "sha256:a25ffa2dbbdf8721855612f6dca15c108224b12d0c4024d0ac3d7902132b4211", size = 311366, upload-time = "2026-04-10T14:28:27.943Z" }, + { url = "https://files.pythonhosted.org/packages/60/bb/520576a532a6b8a6f42747afed289c8448c879a34d7802fe2c832d4fd38f/jiter-0.14.0-graalpy311-graalpy242_311_native-macosx_11_0_arm64.whl", hash = "sha256:0ac9cbaa86c10996b92bd12c91659b60f939f8e28fcfa6bc11a0e90a774ce95b", size = 309873, upload-time = "2026-04-10T14:28:29.688Z" }, + { url = "https://files.pythonhosted.org/packages/b2/7c/c16db114ea1f2f532f198aa8dc39585026af45af362c69a0492f31bc4821/jiter-0.14.0-graalpy311-graalpy242_311_native-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:844e73b6c56b505e9e169234ea3bdea2ea43f769f847f47ac559ba1d2361ebea", size = 344816, upload-time = "2026-04-10T14:28:31.348Z" }, + { url = "https://files.pythonhosted.org/packages/99/8f/15e7741ff19e9bcd4d753f7ff22f988fd54592f134ca13701c13ea8c20e0/jiter-0.14.0-graalpy311-graalpy242_311_native-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e52c076f187405fc21523c746c04399c9af8ece566077ed147b2126f2bcba577", size = 351445, upload-time = "2026-04-10T14:28:33.093Z" }, + { url = "https://files.pythonhosted.org/packages/21/42/9042c3f3019de4adcb8c16591c325ec7255beea9fcd33a42a43f3b0b1000/jiter-0.14.0-graalpy312-graalpy250_312_native-macosx_10_12_x86_64.whl", hash = "sha256:fbd9e482663ca9d005d051330e4d2d8150bb208a209409c10f7e7dfdf7c49da9", size = 308810, upload-time = "2026-04-10T14:28:34.673Z" }, + { url = "https://files.pythonhosted.org/packages/60/cf/a7e19b308bd86bb04776803b1f01a5f9a287a4c55205f4708827ee487fbf/jiter-0.14.0-graalpy312-graalpy250_312_native-macosx_11_0_arm64.whl", hash = "sha256:33a20d838b91ef376b3a56896d5b04e725c7df5bc4864cc6569cf046a8d73b6d", size = 308443, upload-time = "2026-04-10T14:28:36.658Z" }, + { url = "https://files.pythonhosted.org/packages/ca/44/e26ede3f0caeff93f222559cb0cc4ca68579f07d009d7b6010c5b586f9b1/jiter-0.14.0-graalpy312-graalpy250_312_native-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:432c4db5255d86a259efde91e55cb4c8d18c0521d844c9e2e7efcce3899fb016", size = 343039, upload-time = "2026-04-10T14:28:38.356Z" }, + { url = "https://files.pythonhosted.org/packages/da/e9/1f9ada30cef7b05e74bb06f52127e7a724976c225f46adb65c37b1dadfb6/jiter-0.14.0-graalpy312-graalpy250_312_native-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:67f00d94b281174144d6532a04b66a12cb866cbdc47c3af3bfe2973677f9861a", size = 349613, upload-time = "2026-04-10T14:28:40.066Z" }, ] [[package]] @@ -2376,14 +2383,14 @@ wheels = [ [[package]] name = "joserfc" -version = "1.6.3" +version = "1.6.4" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "cryptography" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/ce/90/b8cc8635c4ce2e5e8104bf26ef147f6e599478f6329107283cdc53aae97f/joserfc-1.6.3.tar.gz", hash = "sha256:c00c2830db969b836cba197e830e738dd9dda0955f1794e55d3c636f17f5c9a6", size = 229090, upload-time = "2026-02-25T15:33:38.167Z" } +sdist = { url = "https://files.pythonhosted.org/packages/de/c6/de8fdbdfa75c8ca04fead38a82d573df8a82906e984c349d58665f459558/joserfc-1.6.4.tar.gz", hash = "sha256:34ce5f499bfcc5e9ad4cc75077f9278ab3227b71da9aaf28f9ab705f8a560d3c", size = 231866, upload-time = "2026-04-13T13:15:40.632Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/12/4f/124b3301067b752f44f292f0b9a74e837dd75ff863ee39500a082fc4c733/joserfc-1.6.3-py3-none-any.whl", hash = "sha256:6beab3635358cbc565cb94fb4c53d0557e6d10a15b933e2134939351590bda9a", size = 70465, upload-time = "2026-02-25T15:33:36.997Z" }, + { url = "https://files.pythonhosted.org/packages/b6/f7/210b27752e972edb36d239315b08d3eb6b14824cc4a590da2337d195260b/joserfc-1.6.4-py3-none-any.whl", hash = "sha256:3e4a22b509b41908989237a045e25c8308d5fd47ab96bdae2dd8057c6451003a", size = 70464, upload-time = "2026-04-13T13:15:39.259Z" }, ] [[package]] @@ -2477,7 +2484,7 @@ wheels = [ [[package]] name = "langchain-core" -version = "1.2.28" +version = "1.3.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "jsonpatch" }, @@ -2489,14 +2496,14 @@ dependencies = [ { name = "typing-extensions" }, { name = "uuid-utils" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/f8/a4/317a1a3ac1df33a64adb3670bf88bbe3b3d5baa274db6863a979db472897/langchain_core-1.2.28.tar.gz", hash = "sha256:271a3d8bd618f795fdeba112b0753980457fc90537c46a0c11998516a74dc2cb", size = 846119, upload-time = "2026-04-08T18:19:34.867Z" } +sdist = { url = "https://files.pythonhosted.org/packages/92/fe/20190232d9b513242899dbb0c2bb77e31b4d61e343743adbe90ebc2603d2/langchain_core-1.3.0.tar.gz", hash = "sha256:14a39f528bf459aa3aa40d0a7f7f1bae7520d435ef991ae14a4ceb74d8c49046", size = 860755, upload-time = "2026-04-17T14:51:38.298Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/a8/92/32f785f077c7e898da97064f113c73fbd9ad55d1e2169cf3a391b183dedb/langchain_core-1.2.28-py3-none-any.whl", hash = "sha256:80764232581eaf8057bcefa71dbf8adc1f6a28d257ebd8b95ba9b8b452e8c6ac", size = 508727, upload-time = "2026-04-08T18:19:32.823Z" }, + { url = "https://files.pythonhosted.org/packages/f8/e2/dbfa347aa072a6dc4cd38d6f9ebfc730b4c14c258c47f480f4c5c546f177/langchain_core-1.3.0-py3-none-any.whl", hash = "sha256:baf16ee028475df177b9ab8869a751c79406d64a6f12125b93802991b566cced", size = 515140, upload-time = "2026-04-17T14:51:36.274Z" }, ] [[package]] name = "langgraph" -version = "1.1.6" +version = "1.1.9" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "langchain-core" }, @@ -2506,35 +2513,35 @@ dependencies = [ { name = "pydantic" }, { name = "xxhash" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/5c/e5/d3f72ead3c7f15769d5a9c07e373628f1fbaf6cbe7735694d7085859acf6/langgraph-1.1.6.tar.gz", hash = "sha256:1783f764b08a607e9f288dbcf6da61caeb0dd40b337e5c9fb8b412341fbc0b60", size = 549634, upload-time = "2026-04-03T19:01:32.561Z" } +sdist = { url = "https://files.pythonhosted.org/packages/8c/d5/9d9c65d5500a1ca7ea63d6d65aecfb248037018a74d7d4ef52e276bb4e4b/langgraph-1.1.9.tar.gz", hash = "sha256:bc5a49d5a5e71fda1f9c53c06c62f4caec9a95545b739d130a58b6ab3269e274", size = 560717, upload-time = "2026-04-21T13:43:06.809Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/71/e6/b36ecdb3ff4ba9a290708d514bae89ebbe2f554b6abbe4642acf3fddbe51/langgraph-1.1.6-py3-none-any.whl", hash = "sha256:fdbf5f54fa5a5a4c4b09b7b5e537f1b2fa283d2f0f610d3457ddeecb479458b9", size = 169755, upload-time = "2026-04-03T19:01:30.686Z" }, + { url = "https://files.pythonhosted.org/packages/16/58/0380420e66619d12c992c1f8cfda0c7a04e8f0fe8a84752245b9e7b1cba7/langgraph-1.1.9-py3-none-any.whl", hash = "sha256:7db13ceecde4ea643df6c097dcc9e534895dcd9fcc6500eeff2f2cde0fab16b2", size = 173744, upload-time = "2026-04-21T13:43:05.513Z" }, ] [[package]] name = "langgraph-checkpoint" -version = "4.0.1" +version = "4.0.2" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "langchain-core" }, { name = "ormsgpack" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/b1/44/a8df45d1e8b4637e29789fa8bae1db022c953cc7ac80093cfc52e923547e/langgraph_checkpoint-4.0.1.tar.gz", hash = "sha256:b433123735df11ade28829e40ce25b9be614930cd50245ff2af60629234befd9", size = 158135, upload-time = "2026-02-27T21:06:16.092Z" } +sdist = { url = "https://files.pythonhosted.org/packages/2e/f2/cf8086e1f1a3358d9228805614e72602c281b18307f3fae64a5b854aad2d/langgraph_checkpoint-4.0.2.tar.gz", hash = "sha256:4f6f99cba8e272deabf81b2d8cdc96582af07a57a6ad591cdf216bb310497039", size = 160810, upload-time = "2026-04-15T21:03:00.062Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/65/4c/09a4a0c42f5d2fc38d6c4d67884788eff7fd2cfdf367fdf7033de908b4c0/langgraph_checkpoint-4.0.1-py3-none-any.whl", hash = "sha256:e3adcd7a0e0166f3b48b8cf508ce0ea366e7420b5a73aa81289888727769b034", size = 50453, upload-time = "2026-02-27T21:06:14.293Z" }, + { url = "https://files.pythonhosted.org/packages/b9/5a/6dba29dd89b0a46ae21c707da0f9d17e94f27d3e481ed15bc99d6bd20aa6/langgraph_checkpoint-4.0.2-py3-none-any.whl", hash = "sha256:59b0f29216128a629c58dd07c98aa004f82f51805d5573126ffb419b753ff253", size = 51000, upload-time = "2026-04-15T21:02:59.096Z" }, ] [[package]] name = "langgraph-prebuilt" -version = "1.0.9" +version = "1.0.10" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "langchain-core" }, { name = "langgraph-checkpoint" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/99/4c/06dac899f4945bedb0c3a1583c19484c2cc894114ea30d9a538dd270086e/langgraph_prebuilt-1.0.9.tar.gz", hash = "sha256:93de7512e9caade4b77ead92428f6215c521fdb71b8ffda8cd55f0ad814e64de", size = 165850, upload-time = "2026-04-03T14:06:37.721Z" } +sdist = { url = "https://files.pythonhosted.org/packages/fe/c8/01471b1b5601f2e9c9a69c39fc9a2fb8611613ede0002e5a2b81c0acd850/langgraph_prebuilt-1.0.10.tar.gz", hash = "sha256:5a6fc513f8907074563b6218ff991c4ed9db19ac63101314919686e8029ddb07", size = 169769, upload-time = "2026-04-17T17:59:45.373Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/1d/a2/8368ac187b75e7f9d938ca075d34f116683f5cfc48d924029ee79aea147b/langgraph_prebuilt-1.0.9-py3-none-any.whl", hash = "sha256:776c8e3154a5aef5ad0e5bf3f263f2dcaab3983786cc20014b7f955d99d2d1b2", size = 35958, upload-time = "2026-04-03T14:06:36.58Z" }, + { url = "https://files.pythonhosted.org/packages/50/49/d073375beabdc6955df6cbe570ba7786836bd4c817ae998955d35037f2fd/langgraph_prebuilt-1.0.10-py3-none-any.whl", hash = "sha256:e3baa1977d819982e690a357ba5bb77ccc1d4d8d4a029c48e502a3b6d171185f", size = 36086, upload-time = "2026-04-17T17:59:44.395Z" }, ] [[package]] @@ -2552,7 +2559,7 @@ wheels = [ [[package]] name = "langsmith" -version = "0.7.26" +version = "0.7.33" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "httpx" }, @@ -2565,9 +2572,9 @@ dependencies = [ { name = "xxhash" }, { name = "zstandard" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/76/86/6de4f6f0451a9658f26f633e0bb090552a4dafd7df3f1ae7f0d40558e67e/langsmith-0.7.26.tar.gz", hash = "sha256:a3e06f3d689ce7195717aa6b8f91082319819ec7ea9b9a62cdcd3d9dc25bfc7b", size = 1146118, upload-time = "2026-04-06T15:01:03.336Z" } +sdist = { url = "https://files.pythonhosted.org/packages/6f/75/1ee27b3510bf5b1b569b9695c9466c256caab45885bd569c0c67720236ad/langsmith-0.7.33.tar.gz", hash = "sha256:fa2d81ad6e8374a81fda9291894f6fcae714e55fbf11a0b07578e3cd4b1ea384", size = 1186298, upload-time = "2026-04-20T16:17:54.583Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/81/8e/7eb7d65ce62e98e74b9f18f193ea7ac3996d4fbd71fffcc67d0f7ba3103e/langsmith-0.7.26-py3-none-any.whl", hash = "sha256:fe5c877972cea450c1c48251c8fae0f18543c8d19dfdb9ff9a9c4263763dde4e", size = 360160, upload-time = "2026-04-06T15:01:01.516Z" }, + { url = "https://files.pythonhosted.org/packages/f4/76/53033db34ffccd25d62c32b23b9468f7228b455da6976e1c420ae31555c4/langsmith-0.7.33-py3-none-any.whl", hash = "sha256:5b535b991d52d3b664ebb8dc6f95afcf8d0acb42e062ac45a54a6a4820139f20", size = 378981, upload-time = "2026-04-20T16:17:52.503Z" }, ] [[package]] @@ -2649,14 +2656,14 @@ wheels = [ [[package]] name = "mako" -version = "1.3.10" +version = "1.3.11" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "markupsafe" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/9e/38/bd5b78a920a64d708fe6bc8e0a2c075e1389d53bef8413725c63ba041535/mako-1.3.10.tar.gz", hash = "sha256:99579a6f39583fa7e5630a28c3c1f440e4e97a414b80372649c0ce338da2ea28", size = 392474, upload-time = "2025-04-10T12:44:31.16Z" } +sdist = { url = "https://files.pythonhosted.org/packages/59/8a/805404d0c0b9f3d7a326475ca008db57aea9c5c9f2e1e39ed0faa335571c/mako-1.3.11.tar.gz", hash = "sha256:071eb4ab4c5010443152255d77db7faa6ce5916f35226eb02dc34479b6858069", size = 399811, upload-time = "2026-04-14T20:19:51.493Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/87/fb/99f81ac72ae23375f22b7afdb7642aba97c00a713c217124420147681a2f/mako-1.3.10-py3-none-any.whl", hash = "sha256:baef24a52fc4fc514a0887ac600f9f1cff3d82c61d4d700a1fa84d597b88db59", size = 78509, upload-time = "2025-04-10T12:50:53.297Z" }, + { url = "https://files.pythonhosted.org/packages/68/a5/19d7aaa7e433713ffe881df33705925a196afb9532efc8475d26593921a6/mako-1.3.11-py3-none-any.whl", hash = "sha256:e372c6e333cf004aa736a15f425087ec977e1fcbd2966aae7f17c8dc1da27a77", size = 78503, upload-time = "2026-04-14T20:19:53.233Z" }, ] [[package]] @@ -2758,26 +2765,26 @@ wheels = [ [[package]] name = "maturin" -version = "1.12.6" +version = "1.13.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "tomli", marker = "python_full_version < '3.11'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/0c/18/8b2eebd3ea086a5ec73d7081f95ec64918ceda1900075902fc296ea3ad55/maturin-1.12.6.tar.gz", hash = "sha256:d37be3a811a7f2ee28a0fa0964187efa50e90f21da0c6135c27787fa0b6a89db", size = 269165, upload-time = "2026-03-01T14:54:04.21Z" } +sdist = { url = "https://files.pythonhosted.org/packages/39/16/b284a7bc4af3dd87717c784278c1b8cb18606ad1f6f7a671c47bfd9c3df0/maturin-1.13.1.tar.gz", hash = "sha256:9a87ff3b8e4d1c6eac33ebfe8e261e8236516d98d45c0323550621819b5a1a2f", size = 340369, upload-time = "2026-04-09T15:14:07.026Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/71/8b/9ddfde8a485489e3ebdc50ee3042ef1c854f00dfea776b951068f6ffe451/maturin-1.12.6-py3-none-linux_armv6l.whl", hash = "sha256:6892b4176992fcc143f9d1c1c874a816e9a041248eef46433db87b0f0aff4278", size = 9789847, upload-time = "2026-03-01T14:54:09.172Z" }, - { url = "https://files.pythonhosted.org/packages/ef/e8/5f7fd3763f214a77ac0388dbcc71cc30aec5490016bd0c8e6bd729fc7b0a/maturin-1.12.6-py3-none-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:c0c742beeeef7fb93b6a81bd53e75507887e396fd1003c45117658d063812dad", size = 19023833, upload-time = "2026-03-01T14:53:46.743Z" }, - { url = "https://files.pythonhosted.org/packages/e0/7f/706ff3839c8b2046436d4c2bc97596c558728264d18abc298a1ad862a4be/maturin-1.12.6-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:2cb41139295eed6411d3cdafc7430738094c2721f34b7eeb44f33cac516115dc", size = 9821620, upload-time = "2026-03-01T14:54:12.04Z" }, - { url = "https://files.pythonhosted.org/packages/0e/9c/70917fb123c8dd6b595e913616c9c72d730cbf4a2b6cac8077dc02a12586/maturin-1.12.6-py3-none-manylinux_2_12_i686.manylinux2010_i686.musllinux_1_1_i686.whl", hash = "sha256:351f3af1488a7cbdcff3b6d8482c17164273ac981378a13a4a9937a49aec7d71", size = 9849107, upload-time = "2026-03-01T14:53:48.971Z" }, - { url = "https://files.pythonhosted.org/packages/59/ea/f1d6ad95c0a12fbe761a7c28a57540341f188564dbe8ad730a4d1788cd32/maturin-1.12.6-py3-none-manylinux_2_12_x86_64.manylinux2010_x86_64.musllinux_1_1_x86_64.whl", hash = "sha256:6dbddfe4dc7ddee60bbac854870bd7cfec660acb54d015d24597d59a1c828f61", size = 10242855, upload-time = "2026-03-01T14:53:44.605Z" }, - { url = "https://files.pythonhosted.org/packages/93/1b/2419843a4f1d2fb4747f3dc3d9c4a2881cd97a3274dd94738fcdf0835e79/maturin-1.12.6-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.musllinux_1_1_aarch64.whl", hash = "sha256:8fdb0f63e77ee3df0f027a120e9af78dbc31edf0eb0f263d55783c250c33b728", size = 9674972, upload-time = "2026-03-01T14:53:52.763Z" }, - { url = "https://files.pythonhosted.org/packages/71/46/b60ab2fc996d904b40e55bd475599dcdccd8f7ad3e649bf95e87970df466/maturin-1.12.6-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.musllinux_1_1_armv7l.whl", hash = "sha256:fa84b7493a2e80759cacc2e668fa5b444d55b9994e90707c42904f55d6322c1e", size = 9645755, upload-time = "2026-03-01T14:53:58.497Z" }, - { url = "https://files.pythonhosted.org/packages/a4/96/03f2b55a8c226805115232fc23c4a4f33f0c9d39e11efab8166dc440f80d/maturin-1.12.6-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.musllinux_1_1_ppc64le.whl", hash = "sha256:e90dc12bc6a38e9495692a36c9e231c4d7e0c9bfde60719468ab7d8673db3c45", size = 12737612, upload-time = "2026-03-01T14:54:05.393Z" }, - { url = "https://files.pythonhosted.org/packages/2b/c2/648667022c5b53cdccefa67c245e8a984970f3045820f00c2e23bdb2aff4/maturin-1.12.6-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:06fc8d089f98623ce924c669b70911dfed30f9a29956c362945f727f9abc546b", size = 10455028, upload-time = "2026-03-01T14:54:07.349Z" }, - { url = "https://files.pythonhosted.org/packages/63/d6/5b5efe3ca0c043357ed3f8d2b2d556169fdbf1ff75e50e8e597708a359d2/maturin-1.12.6-py3-none-manylinux_2_31_riscv64.musllinux_1_1_riscv64.whl", hash = "sha256:75133e56274d43b9227fd49dca9a86e32f1fd56a7b55544910c4ce978c2bb5aa", size = 10014531, upload-time = "2026-03-01T14:53:54.548Z" }, - { url = "https://files.pythonhosted.org/packages/68/d5/39c594c27b1a8b32a0cb95fff9ad60b888c4352d1d1c389ac1bd20dc1e16/maturin-1.12.6-py3-none-win32.whl", hash = "sha256:3f32e0a3720b81423c9d35c14e728cb1f954678124749776dc72d533ea1115e8", size = 8553012, upload-time = "2026-03-01T14:53:50.706Z" }, - { url = "https://files.pythonhosted.org/packages/94/66/b262832a91747e04051e21f986bd01a8af81fbffafacc7d66a11e79aab5f/maturin-1.12.6-py3-none-win_amd64.whl", hash = "sha256:977290159d252db946054a0555263c59b3d0c7957135c69e690f4b1558ee9983", size = 9890470, upload-time = "2026-03-01T14:53:56.659Z" }, - { url = "https://files.pythonhosted.org/packages/e3/47/76b8ca470ddc8d7d36aa8c15f5a6aed1841806bb93a0f4ead8ee61e9a088/maturin-1.12.6-py3-none-win_arm64.whl", hash = "sha256:bae91976cdc8148038e13c881e1e844e5c63e58e026e8b9945aa2d19b3b4ae89", size = 8606158, upload-time = "2026-03-01T14:54:02.423Z" }, + { url = "https://files.pythonhosted.org/packages/43/4d/a23fc95be881aa8c7a6ea353410417872e4d7065df03d7f3db8f0dbed4a7/maturin-1.13.1-py3-none-linux_armv6l.whl", hash = "sha256:416e4e01cb88b798e606ee43929df897e42c1647b722ef68283816cca99a8742", size = 10102444, upload-time = "2026-04-09T15:13:48.393Z" }, + { url = "https://files.pythonhosted.org/packages/a6/1e/65c385d65bae95cf04895d52f39dbed8b1453ae55da2903d252ade40a774/maturin-1.13.1-py3-none-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:72888e87819ce546d0d2df900e4b385e4ef299077d92ee37b48923a5602dae94", size = 19576043, upload-time = "2026-04-09T15:14:08.685Z" }, + { url = "https://files.pythonhosted.org/packages/8f/13/f6bc868d0bfecd9314870b97f530a167e31f7878ac4945c78245c6eef69c/maturin-1.13.1-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:98b5fcf1a186c217830a8295ecc2989c6b1cf50945417adfc15252107b9475b7", size = 10117339, upload-time = "2026-04-09T15:13:40.559Z" }, + { url = "https://files.pythonhosted.org/packages/51/58/279e081305c11c1c1c4fccacf77df8959646c5d4de7a57ec7e787653e270/maturin-1.13.1-py3-none-manylinux_2_12_i686.manylinux2010_i686.musllinux_1_1_i686.whl", hash = "sha256:3da18cccf2f683c0977bff9146a0908d6ffce836d600665736ac01679f588cb9", size = 10139689, upload-time = "2026-04-09T15:13:38.291Z" }, + { url = "https://files.pythonhosted.org/packages/00/94/69391af5396c6aab723932240803f49e5f3de3dd7c57d32f02d237a0ce32/maturin-1.13.1-py3-none-manylinux_2_12_x86_64.manylinux2010_x86_64.musllinux_1_1_x86_64.whl", hash = "sha256:6b1e5916a253243e8f5f9e847b62bbc98420eec48c9ce2e2e8724c6da89d359b", size = 10551141, upload-time = "2026-04-09T15:13:42.887Z" }, + { url = "https://files.pythonhosted.org/packages/9e/bf/4edac2667b49e3733438062ae416413b8fc8d42e1bd499ba15e1fb02fc55/maturin-1.13.1-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.musllinux_1_1_aarch64.whl", hash = "sha256:dc91031e0619c1e28730279ef9ee5f106c9b9ec806b013f888676b242f892eb7", size = 9983094, upload-time = "2026-04-09T15:13:56.868Z" }, + { url = "https://files.pythonhosted.org/packages/79/94/a6d651cfe8fc6bf2e892c90e3cdbb25c06d81c9115140d03ea1a68a97575/maturin-1.13.1-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.musllinux_1_1_armv7l.whl", hash = "sha256:001741c6cff56aa8ea59a0d78ae990c0550d0e3e82b00b683eedb4158a8ef7e6", size = 9949980, upload-time = "2026-04-09T15:13:59.185Z" }, + { url = "https://files.pythonhosted.org/packages/b5/d1/82c067464f848e38af9910bce55eb54302b1c1284a279d515dbfcf5994f5/maturin-1.13.1-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.musllinux_1_1_ppc64le.whl", hash = "sha256:01c845825c917c07c1d0b2c9032c59c16a7d383d1e649a46481d3e5693c2750f", size = 13186276, upload-time = "2026-04-09T15:13:45.725Z" }, + { url = "https://files.pythonhosted.org/packages/7c/f4/25367baf1025580f047f9b37598bb3fadc416e24536afd4f28e190335c73/maturin-1.13.1-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f69093ed4a0e6464e52a7fc26d714f859ce15630ec8070743398c6bf41f38a9e", size = 10891837, upload-time = "2026-04-09T15:13:35.68Z" }, + { url = "https://files.pythonhosted.org/packages/af/be/caafad8ce74974b7deafdf144d12f758993dfea4c66c9905b138f51a7792/maturin-1.13.1-py3-none-manylinux_2_31_riscv64.musllinux_1_1_riscv64.whl", hash = "sha256:c1490584f3c70af45466ee99065b49e6657ebdccac6b10571bb44681309c9396", size = 10351032, upload-time = "2026-04-09T15:14:01.632Z" }, + { url = "https://files.pythonhosted.org/packages/66/0e/970a721d27cfa410e8bfa0a1e32e6ef52cb8169692110a5fdabe1af3f570/maturin-1.13.1-py3-none-win32.whl", hash = "sha256:c6a720b252c99de072922dbe4432ab19662b6f80045b0355fec23bdfccb450da", size = 8855465, upload-time = "2026-04-09T15:13:51.122Z" }, + { url = "https://files.pythonhosted.org/packages/88/70/7c1e0d65fa147d5479055a171541c82b8cdfc1c825d85a82240470f14176/maturin-1.13.1-py3-none-win_amd64.whl", hash = "sha256:a2017d2281203d0c6570240e7d746564d766d756105823b7de68bda6ae722711", size = 10230471, upload-time = "2026-04-09T15:13:53.89Z" }, + { url = "https://files.pythonhosted.org/packages/c5/2a/afe0193b673a79ffd2e01ad999511b7e9e6b49af02bb3759d82a78c3043d/maturin-1.13.1-py3-none-win_arm64.whl", hash = "sha256:2839024dcd65776abb4759e5bca29941971e095574162a4d335191da4be9ff24", size = 8905575, upload-time = "2026-04-09T15:14:03.891Z" }, ] [[package]] @@ -2930,16 +2937,16 @@ wheels = [ [[package]] name = "more-itertools" -version = "11.0.1" +version = "11.0.2" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/24/24/e0acc4bf54cba50c1d432c70a72a3df96db4a321b2c4c68432a60759044f/more_itertools-11.0.1.tar.gz", hash = "sha256:fefaf25b7ab08f0b45fa9f1892cae93b9fc0089ef034d39213bce15f1cc9e199", size = 144739, upload-time = "2026-04-02T16:17:45.061Z" } +sdist = { url = "https://files.pythonhosted.org/packages/a2/f7/139d22fef48ac78127d18e01d80cf1be40236ae489769d17f35c3d425293/more_itertools-11.0.2.tar.gz", hash = "sha256:392a9e1e362cbc106a2457d37cabf9b36e5e12efd4ebff1654630e76597df804", size = 144659, upload-time = "2026-04-09T15:01:33.297Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/d8/f4/5e52c7319b8087acef603ed6e50dc325c02eaa999355414830468611f13c/more_itertools-11.0.1-py3-none-any.whl", hash = "sha256:eaf287826069452a8f61026c597eae2428b2d1ba2859083abbf240b46842ce6d", size = 72182, upload-time = "2026-04-02T16:17:43.724Z" }, + { url = "https://files.pythonhosted.org/packages/cb/98/6af411189d9413534c3eb691182bff1f5c6d44ed2f93f2edfe52a1bbceb8/more_itertools-11.0.2-py3-none-any.whl", hash = "sha256:6e35b35f818b01f691643c6c611bc0902f2e92b46c18fffa77ae1e7c46e912e4", size = 71939, upload-time = "2026-04-09T15:01:32.21Z" }, ] [[package]] name = "moto" -version = "5.1.22" +version = "5.1.18" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "boto3" }, @@ -2952,9 +2959,9 @@ dependencies = [ { name = "werkzeug" }, { name = "xmltodict" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/b2/3d/1765accbf753dc1ae52f26a2e2ed2881d78c2eb9322c178e45312472e4a0/moto-5.1.22.tar.gz", hash = "sha256:e5b2c378296e4da50ce5a3c355a1743c8d6d396ea41122f5bb2a40f9b9a8cc0e", size = 8547792, upload-time = "2026-03-08T21:06:43.731Z" } +sdist = { url = "https://files.pythonhosted.org/packages/e3/6a/a73bef67261bfab55714390f07c7df97531d00cea730b7c0ace4d0ad7669/moto-5.1.18.tar.gz", hash = "sha256:45298ef7b88561b839f6fe3e9da2a6e2ecd10283c7bf3daf43a07a97465885f9", size = 8271655, upload-time = "2025-11-30T22:03:59.58Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/46/4f/8812a01e3e0bd6be3e13b90432fb5c696af9a720af3f00e6eba5ad748345/moto-5.1.22-py3-none-any.whl", hash = "sha256:d9f20ae3cf29c44f93c1f8f06c8f48d5560e5dc027816ef1d0d2059741ffcfbe", size = 6617400, upload-time = "2026-03-08T21:06:41.093Z" }, + { url = "https://files.pythonhosted.org/packages/83/d4/6991df072b34741a0c115e8d21dc2fe142e4b497319d762e957f6677f001/moto-5.1.18-py3-none-any.whl", hash = "sha256:b65aa8fc9032c5c574415451e14fd7da4e43fd50b8bdcb5f10289ad382c25bcf", size = 6357278, upload-time = "2025-11-30T22:03:56.831Z" }, ] [package.optional-dependencies] @@ -2964,7 +2971,6 @@ s3 = [ ] server = [ { name = "antlr4-python3-runtime" }, - { name = "aws-sam-translator" }, { name = "aws-xray-sdk" }, { name = "cfn-lint" }, { name = "docker" }, @@ -2975,7 +2981,6 @@ server = [ { name = "jsonpath-ng" }, { name = "openapi-spec-validator" }, { name = "py-partiql-parser" }, - { name = "pydantic" }, { name = "pyparsing" }, { name = "pyyaml" }, { name = "setuptools" }, @@ -3339,23 +3344,23 @@ wheels = [ [[package]] name = "nodejs-wheel-binaries" -version = "24.14.1" +version = "24.15.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/f1/87/e5755ad739daafce2e152ab609293d65e6c663b399e28a4bbcd0f4af1f45/nodejs_wheel_binaries-24.14.1.tar.gz", hash = "sha256:d00ae0c86d7e1bfa798e8f8ad282db751af157cdcaa1208a1b9a2cf2a85ac821", size = 8056, upload-time = "2026-03-31T14:07:27Z" } +sdist = { url = "https://files.pythonhosted.org/packages/3f/70/a1e4f4d5986768ab90cc860b1cc3660fd2ded74ca175a900a5c29f839c7d/nodejs_wheel_binaries-24.15.0.tar.gz", hash = "sha256:b43f5c4f6e5768d8845b2ae4682eb703a19bf7aadc84187e2d903ed3a611c859", size = 8057, upload-time = "2026-04-19T15:48:16.899Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/8b/b7/9765d9a5d3b95475829ef5965d4a4f6f4badb034ee4e18c2d5f8b9b65d6f/nodejs_wheel_binaries-24.14.1-py2.py3-none-macosx_13_0_arm64.whl", hash = "sha256:d9e856ba0f2d3d2659869e6e0f4cae6874faeeeca7f879131a88451356373ac4", size = 54945603, upload-time = "2026-03-31T14:06:58.526Z" }, - { url = "https://files.pythonhosted.org/packages/6f/15/bc2fa51ee31ce597b2af1905081e5a5add07fe0cf619bfa531d7df2f1f1b/nodejs_wheel_binaries-24.14.1-py2.py3-none-macosx_13_0_x86_64.whl", hash = "sha256:634f57829ebfdfe95d096f32a50c5cdd3a6c72a94dcf2b92a8bef9868cccb13e", size = 55119951, upload-time = "2026-03-31T14:07:02.597Z" }, - { url = "https://files.pythonhosted.org/packages/a6/dd/92ff0831262af4bbb5473d4e7964fd27afb0901a2690a6ff7bc3d220d97f/nodejs_wheel_binaries-24.14.1-py2.py3-none-manylinux_2_28_aarch64.whl", hash = "sha256:404b563467129e6a0ea7006a38b3d8af0ebfbc340b31a6a0af2c59ea3af90b7c", size = 59487620, upload-time = "2026-03-31T14:07:06.198Z" }, - { url = "https://files.pythonhosted.org/packages/45/36/bbbee3adf6afd00944e5a86ebd64987dea90bd347090155a4989dc3e8594/nodejs_wheel_binaries-24.14.1-py2.py3-none-manylinux_2_28_x86_64.whl", hash = "sha256:7863c62f8a3946b727831f71375a9ae00205b3258478476034b49c3a1d57ac12", size = 59986044, upload-time = "2026-03-31T14:07:09.846Z" }, - { url = "https://files.pythonhosted.org/packages/05/16/119e4168bf7ed17ad7961d122701c75ac86135fa243a958b960a3f1b7055/nodejs_wheel_binaries-24.14.1-py2.py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:a3f64daa1235fa6a83c778ded98d5fe4e74979ca54aa2ffb807f0805c57c3abe", size = 61489823, upload-time = "2026-03-31T14:07:13.378Z" }, - { url = "https://files.pythonhosted.org/packages/8c/a6/d581996827b9d1133094dc347f1c4e3d2a70557973ce7a427a03337b1427/nodejs_wheel_binaries-24.14.1-py2.py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:810a48ce096925ead0690f7d143e48fb902ebfc9212097e8f6cb3ac6cbe8f314", size = 62069740, upload-time = "2026-03-31T14:07:17.006Z" }, - { url = "https://files.pythonhosted.org/packages/27/da/396d1a48cbf3d5899461bda12fa97ae4010d7e4013e7f28230cb04af5818/nodejs_wheel_binaries-24.14.1-py2.py3-none-win_amd64.whl", hash = "sha256:7a087b6a727fb9242d1cc83c8b121711bd0e9686408d27de48b34b23dfb26ac5", size = 41400067, upload-time = "2026-03-31T14:07:20.513Z" }, - { url = "https://files.pythonhosted.org/packages/13/b7/adb21cf549934579e98934531e7f9b038d583fc9c2dd4b82ea01cc31bdd2/nodejs_wheel_binaries-24.14.1-py2.py3-none-win_arm64.whl", hash = "sha256:978fdfe76624c48111ab99ed0f99f9d4c1c682e420b0212ac9e1daee52f20283", size = 39096873, upload-time = "2026-03-31T14:07:23.977Z" }, + { url = "https://files.pythonhosted.org/packages/85/66/54051d14853d6ab4fb85f8be9b042b530be653357fb9a19557498bc91ab7/nodejs_wheel_binaries-24.15.0-py2.py3-none-macosx_13_0_arm64.whl", hash = "sha256:a6232fa8b754220941f52388c8ead923f7c1c7fdf0ea0d98f657523bd9a81ef4", size = 55173485, upload-time = "2026-04-19T15:47:34.561Z" }, + { url = "https://files.pythonhosted.org/packages/ad/5f/66acada164da5ca10a0824db021aa7394ae18396c550cd9280e839a43126/nodejs_wheel_binaries-24.15.0-py2.py3-none-macosx_13_0_x86_64.whl", hash = "sha256:001a6b62c69d9109c1738163cca00608dd2722e8663af59300054ea02610972d", size = 55348100, upload-time = "2026-04-19T15:47:40.521Z" }, + { url = "https://files.pythonhosted.org/packages/0d/2d/0cbd5ff40c9bb030ca1735d8f8793bd74f08a4cbd49100a1d19313ea57ab/nodejs_wheel_binaries-24.15.0-py2.py3-none-manylinux_2_28_aarch64.whl", hash = "sha256:0fbc48765e60ed0ff30d43898dbf5cadbadf2e5f1e7f204afc2b01493b7ebce6", size = 59668206, upload-time = "2026-04-19T15:47:46.848Z" }, + { url = "https://files.pythonhosted.org/packages/da/d5/91ac63951ec75927a486b83b8cafe650e360fa70ac01dc94adfb32b93b97/nodejs_wheel_binaries-24.15.0-py2.py3-none-manylinux_2_28_x86_64.whl", hash = "sha256:20ee0536809795da8a4942fc1ab4cbdebbcaaf29383eab67ba8874268fb00008", size = 60206736, upload-time = "2026-04-19T15:47:52.668Z" }, + { url = "https://files.pythonhosted.org/packages/db/72/dc22776974d928869c0c30d23ee98ed7df254243c2df68f09f5963e8e8b8/nodejs_wheel_binaries-24.15.0-py2.py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:1fade6c214285e72472ca40a631e98ff36559671cd5eefc8bf009471d67f04b4", size = 61720456, upload-time = "2026-04-19T15:47:58.325Z" }, + { url = "https://files.pythonhosted.org/packages/01/0a/34461b9050cb45ee371dccdefc622aef6351506ea2691b08fc761ca67150/nodejs_wheel_binaries-24.15.0-py2.py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:3984cb8d87766567aee67a49743227ab40ede6f47734ec990ff90e50b74e7740", size = 62326172, upload-time = "2026-04-19T15:48:04.094Z" }, + { url = "https://files.pythonhosted.org/packages/c9/17/09252bf35672dba926649d59dfe51443a0f6955ad13784e91131d5ec82a2/nodejs_wheel_binaries-24.15.0-py2.py3-none-win_amd64.whl", hash = "sha256:a437601956b532dcb3082046e6978e622733f90edc0932cbb9adb3bb97a16501", size = 41543461, upload-time = "2026-04-19T15:48:09.332Z" }, + { url = "https://files.pythonhosted.org/packages/0a/7e/b649777d148e1e0c2ce349156603cdb12f7ed99921b95d93717393650193/nodejs_wheel_binaries-24.15.0-py2.py3-none-win_arm64.whl", hash = "sha256:bdf4a431e08321a32efc604111c6f23941f87055d796a537e8c4110daecad23f", size = 39233248, upload-time = "2026-04-19T15:48:13.326Z" }, ] [[package]] name = "openai" -version = "2.30.0" +version = "2.32.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "anyio" }, @@ -3367,14 +3372,14 @@ dependencies = [ { name = "tqdm" }, { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/88/15/52580c8fbc16d0675d516e8749806eda679b16de1e4434ea06fb6feaa610/openai-2.30.0.tar.gz", hash = "sha256:92f7661c990bda4b22a941806c83eabe4896c3094465030dd882a71abe80c885", size = 676084, upload-time = "2026-03-25T22:08:59.96Z" } +sdist = { url = "https://files.pythonhosted.org/packages/ed/59/bdcc6b759b8c42dd73afaf5bf8f902c04b37987a5514dbc1c64dba390fef/openai-2.32.0.tar.gz", hash = "sha256:c54b27a9e4cb8d51f0dd94972ffd1a04437efeb259a9e60d8922b8bd26fe55e0", size = 693286, upload-time = "2026-04-15T22:28:19.434Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/2a/9e/5bfa2270f902d5b92ab7d41ce0475b8630572e71e349b2a4996d14bdda93/openai-2.30.0-py3-none-any.whl", hash = "sha256:9a5ae616888eb2748ec5e0c5b955a51592e0b201a11f4262db920f2a78c5231d", size = 1146656, upload-time = "2026-03-25T22:08:58.2Z" }, + { url = "https://files.pythonhosted.org/packages/1e/c1/d6e64ccd0536bf616556f0cad2b6d94a8125f508d25cfd814b1d2db4e2f1/openai-2.32.0-py3-none-any.whl", hash = "sha256:4dcc9badeb4bf54ad0d187453742f290226d30150890b7890711bda4f32f192f", size = 1162570, upload-time = "2026-04-15T22:28:17.714Z" }, ] [[package]] name = "openai-agents" -version = "0.14.0" +version = "0.14.8" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "griffelib" }, @@ -3386,9 +3391,9 @@ dependencies = [ { name = "typing-extensions" }, { name = "websockets" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/f2/3c/965968ab53d6afc1d6e4223b6b2e8cdfca15f39fdcc20cfe5dd526ea99f4/openai_agents-0.14.0.tar.gz", hash = "sha256:d82cbafbeea5b189712c243664552268df16082fa14f1778af40f706eb976692", size = 5192284, upload-time = "2026-04-15T17:12:10.191Z" } +sdist = { url = "https://files.pythonhosted.org/packages/d5/8a/d36ab647f05e790ec97dda9e4c0eb39d8840269d6a5194887b5dec92bd0d/openai_agents-0.14.8.tar.gz", hash = "sha256:fe1cb58b4150a07292a94f15d8fd5217ee9195bd6bcd8a6a46fdb1d9b08a70b7", size = 5314520, upload-time = "2026-04-29T03:40:07.6Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/8d/3e/0be9a884d3b770114572e0be101ab8adb04a7f1a99620261e7393b72a655/openai_agents-0.14.0-py3-none-any.whl", hash = "sha256:5a1dad74de95970efbf4a3f89dfd50d6a22202d9105b81d7abb25a0be3d493c7", size = 795734, upload-time = "2026-04-15T17:12:08.001Z" }, + { url = "https://files.pythonhosted.org/packages/af/6e/1e9adcedcde7b163579b88a68f765a4915be4ead0713270386d9432cfd2f/openai_agents-0.14.8-py3-none-any.whl", hash = "sha256:2937ef582ccaa45d59e89839ed8948cb2a6d808bc9940f0881793c21f37f7776", size = 817332, upload-time = "2026-04-29T03:40:05.68Z" }, ] [package.optional-dependencies] @@ -3432,7 +3437,7 @@ wheels = [ [[package]] name = "openinference-instrumentation" -version = "0.1.46" +version = "0.1.47" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "openinference-semantic-conventions" }, @@ -3440,9 +3445,9 @@ dependencies = [ { name = "opentelemetry-sdk" }, { name = "wrapt" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/64/8d/9b76b43e8b2ee2ccf1fe15b21c924095f9c0e4839919bcd4951b1c99c2ab/openinference_instrumentation-0.1.46.tar.gz", hash = "sha256:0b520002a1c682c525dcab49005c209bfd71611e8e4e4933b49779d5e899e6db", size = 23937, upload-time = "2026-03-04T10:13:48.883Z" } +sdist = { url = "https://files.pythonhosted.org/packages/18/d4/390c47304f172161e7d1ccdf6e4d02bc3f5612741a6768d652eb264b2edc/openinference_instrumentation-0.1.47.tar.gz", hash = "sha256:4f68930d974c04bdf765b31262fd8ec35c3b6b1b24dbbadbbdec2c685024b06b", size = 23931, upload-time = "2026-04-22T00:39:25.472Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/25/d1/f6668492152a4180492044313e2dc427fbc237904f6bb1629abd030e3469/openinference_instrumentation-0.1.46-py3-none-any.whl", hash = "sha256:f7b63ccd5f93ce82e4e40035c9faa6b021984cbe06ad791f4cf033551533bc48", size = 30124, upload-time = "2026-03-04T10:13:47.613Z" }, + { url = "https://files.pythonhosted.org/packages/1a/83/31420c5f503fec0f6b3cc66d9a93a10b656ce77bbe16421cdb4aad5b12fe/openinference_instrumentation-0.1.47-py3-none-any.whl", hash = "sha256:8496b29de79d0ceb7a7e5a523920da73351f192800fddd43aebc23c58d5586b9", size = 30112, upload-time = "2026-04-22T00:39:24.561Z" }, ] [[package]] @@ -3483,11 +3488,11 @@ wheels = [ [[package]] name = "openinference-semantic-conventions" -version = "0.1.28" +version = "0.1.29" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/df/32/c79bf8bd3ea5a00e492449b31ca600bbc2a8e88a301e42c872af925a156c/openinference_semantic_conventions-0.1.28.tar.gz", hash = "sha256:6388465174e8ab3f27ebc6a9e9bb2e1b804d30caefb57234e16db874da1c6a7b", size = 12893, upload-time = "2026-03-11T04:45:46.543Z" } +sdist = { url = "https://files.pythonhosted.org/packages/15/6b/9ed67f9ce8c92436b297207abde730800b00bdec7e114f71b8dfe91cd26b/openinference_semantic_conventions-0.1.29.tar.gz", hash = "sha256:bbeb6472777a45a574169894bb9c4d80c6832a8befd32ab238cb875438ce1044", size = 12959, upload-time = "2026-04-22T00:39:27.916Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/04/40/34b570462c3ce250277254bb0cca655eb39b64c0dffe63cd7751f103f8d6/openinference_semantic_conventions-0.1.28-py3-none-any.whl", hash = "sha256:a2fed5bb167aa56c1c7448cdb7a8d775f989339ba1f8b04a7b45d4f8388cccfb", size = 10522, upload-time = "2026-03-11T04:45:45.423Z" }, + { url = "https://files.pythonhosted.org/packages/be/7b/45ad1b95315b5563baa7338c8e8088bb1af66905c46e1bd1fe6ecbe30ea8/openinference_semantic_conventions-0.1.29-py3-none-any.whl", hash = "sha256:f45e0b1cf79fe407af4722bcf391a01565f0878c95be3ebcc9382245d0367cc5", size = 10582, upload-time = "2026-04-22T00:39:27.066Z" }, ] [[package]] @@ -3816,11 +3821,11 @@ wheels = [ [[package]] name = "packaging" -version = "26.0" +version = "26.1" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/65/ee/299d360cdc32edc7d2cf530f3accf79c4fca01e96ffc950d8a52213bd8e4/packaging-26.0.tar.gz", hash = "sha256:00243ae351a257117b6a241061796684b084ed1c516a08c48a3f7e147a9d80b4", size = 143416, upload-time = "2026-01-21T20:50:39.064Z" } +sdist = { url = "https://files.pythonhosted.org/packages/df/de/0d2b39fb4af88a0258f3bac87dfcbb48e73fbdea4a2ed0e2213f9a4c2f9a/packaging-26.1.tar.gz", hash = "sha256:f042152b681c4bfac5cae2742a55e103d27ab2ec0f3d88037136b6bfe7c9c5de", size = 215519, upload-time = "2026-04-14T21:12:49.362Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/b7/b9/c538f279a4e237a006a2c98387d081e9eb060d203d8ed34467cc0f0b9b53/packaging-26.0-py3-none-any.whl", hash = "sha256:b36f1fef9334a5588b4166f8bcd26a14e521f2b55e6b9de3aaa80d3ff7a37529", size = 74366, upload-time = "2026-01-21T20:50:37.788Z" }, + { url = "https://files.pythonhosted.org/packages/7a/c2/920ef838e2f0028c8262f16101ec09ebd5969864e5a64c4c05fad0617c56/packaging-26.1-py3-none-any.whl", hash = "sha256:5d9c0669c6285e491e0ced2eee587eaf67b670d94a19e94e3984a481aba6802f", size = 95831, upload-time = "2026-04-14T21:12:47.56Z" }, ] [[package]] @@ -3834,11 +3839,11 @@ wheels = [ [[package]] name = "pathspec" -version = "1.0.4" +version = "1.1.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/fa/36/e27608899f9b8d4dff0617b2d9ab17ca5608956ca44461ac14ac48b44015/pathspec-1.0.4.tar.gz", hash = "sha256:0210e2ae8a21a9137c0d470578cb0e595af87edaa6ebf12ff176f14a02e0e645", size = 131200, upload-time = "2026-01-27T03:59:46.938Z" } +sdist = { url = "https://files.pythonhosted.org/packages/2e/17/9c3094b822982b9f1ea666d8580ce59000f61f87c1663556fb72031ad9ec/pathspec-1.1.0.tar.gz", hash = "sha256:f5d7c555da02fd8dde3e4a2354b6aba817a89112fa8f333f7917a2a4834dd080", size = 133918, upload-time = "2026-04-23T01:46:22.298Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/ef/3c/2c197d226f9ea224a9ab8d197933f9da0ae0aac5b6e0f884e2b8d9c8e9f7/pathspec-1.0.4-py3-none-any.whl", hash = "sha256:fb6ae2fd4e7c921a165808a552060e722767cfa526f99ca5156ed2ce45a5c723", size = 55206, upload-time = "2026-01-27T03:59:45.137Z" }, + { url = "https://files.pythonhosted.org/packages/fa/c9/8eed0486f074e9f1ca7f8ce5ad663e65f12fdab344028d658fa1b03d35e0/pathspec-1.1.0-py3-none-any.whl", hash = "sha256:574b128f7456bd899045ccd142dd446af7e6cfd0072d63ad73fbc55fbb4aaa42", size = 56264, upload-time = "2026-04-23T01:46:20.606Z" }, ] [[package]] @@ -3852,11 +3857,11 @@ wheels = [ [[package]] name = "platformdirs" -version = "4.9.4" +version = "4.9.6" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/19/56/8d4c30c8a1d07013911a8fdbd8f89440ef9f08d07a1b50ab8ca8be5a20f9/platformdirs-4.9.4.tar.gz", hash = "sha256:1ec356301b7dc906d83f371c8f487070e99d3ccf9e501686456394622a01a934", size = 28737, upload-time = "2026-03-05T18:34:13.271Z" } +sdist = { url = "https://files.pythonhosted.org/packages/9f/4a/0883b8e3802965322523f0b200ecf33d31f10991d0401162f4b23c698b42/platformdirs-4.9.6.tar.gz", hash = "sha256:3bfa75b0ad0db84096ae777218481852c0ebc6c727b3168c1b9e0118e458cf0a", size = 29400, upload-time = "2026-04-09T00:04:10.812Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/63/d7/97f7e3a6abb67d8080dd406fd4df842c2be0efaf712d1c899c32a075027c/platformdirs-4.9.4-py3-none-any.whl", hash = "sha256:68a9a4619a666ea6439f2ff250c12a853cd1cbd5158d258bd824a7df6be2f868", size = 21216, upload-time = "2026-03-05T18:34:12.172Z" }, + { url = "https://files.pythonhosted.org/packages/75/a6/a0a304dc33b49145b21f4808d763822111e67d1c3a32b524a1baf947b6e1/platformdirs-4.9.6-py3-none-any.whl", hash = "sha256:e61adb1d5e5cb3441b4b7710bea7e4c12250ca49439228cc1021c00dcfac0917", size = 21348, upload-time = "2026-04-09T00:04:09.463Z" }, ] [[package]] @@ -4034,59 +4039,59 @@ wheels = [ [[package]] name = "pyarrow" -version = "23.0.1" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/88/22/134986a4cc224d593c1afde5494d18ff629393d74cc2eddb176669f234a4/pyarrow-23.0.1.tar.gz", hash = "sha256:b8c5873e33440b2bc2f4a79d2b47017a89c5a24116c055625e6f2ee50523f019", size = 1167336, upload-time = "2026-02-16T10:14:12.39Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/bc/a8/24e5dc6855f50a62936ceb004e6e9645e4219a8065f304145d7fb8a79d5d/pyarrow-23.0.1-cp310-cp310-macosx_12_0_arm64.whl", hash = "sha256:3fab8f82571844eb3c460f90a75583801d14ca0cc32b1acc8c361650e006fd56", size = 34307390, upload-time = "2026-02-16T10:08:08.654Z" }, - { url = "https://files.pythonhosted.org/packages/bc/8e/4be5617b4aaae0287f621ad31c6036e5f63118cfca0dc57d42121ff49b51/pyarrow-23.0.1-cp310-cp310-macosx_12_0_x86_64.whl", hash = "sha256:3f91c038b95f71ddfc865f11d5876c42f343b4495535bd262c7b321b0b94507c", size = 35853761, upload-time = "2026-02-16T10:08:17.811Z" }, - { url = "https://files.pythonhosted.org/packages/2e/08/3e56a18819462210432ae37d10f5c8eed3828be1d6c751b6e6a2e93c286a/pyarrow-23.0.1-cp310-cp310-manylinux_2_28_aarch64.whl", hash = "sha256:d0744403adabef53c985a7f8a082b502a368510c40d184df349a0a8754533258", size = 44493116, upload-time = "2026-02-16T10:08:25.792Z" }, - { url = "https://files.pythonhosted.org/packages/f8/82/c40b68001dbec8a3faa4c08cd8c200798ac732d2854537c5449dc859f55a/pyarrow-23.0.1-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:c33b5bf406284fd0bba436ed6f6c3ebe8e311722b441d89397c54f871c6863a2", size = 47564532, upload-time = "2026-02-16T10:08:34.27Z" }, - { url = "https://files.pythonhosted.org/packages/20/bc/73f611989116b6f53347581b02177f9f620efdf3cd3f405d0e83cdf53a83/pyarrow-23.0.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:ddf743e82f69dcd6dbbcb63628895d7161e04e56794ef80550ac6f3315eeb1d5", size = 48183685, upload-time = "2026-02-16T10:08:42.889Z" }, - { url = "https://files.pythonhosted.org/packages/b0/cc/6c6b3ecdae2a8c3aced99956187e8302fc954cc2cca2a37cf2111dad16ce/pyarrow-23.0.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:e052a211c5ac9848ae15d5ec875ed0943c0221e2fcfe69eee80b604b4e703222", size = 50605582, upload-time = "2026-02-16T10:08:51.641Z" }, - { url = "https://files.pythonhosted.org/packages/8d/94/d359e708672878d7638a04a0448edf7c707f9e5606cee11e15aaa5c7535a/pyarrow-23.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:5abde149bb3ce524782d838eb67ac095cd3fd6090eba051130589793f1a7f76d", size = 27521148, upload-time = "2026-02-16T10:08:58.077Z" }, - { url = "https://files.pythonhosted.org/packages/b0/41/8e6b6ef7e225d4ceead8459427a52afdc23379768f54dd3566014d7618c1/pyarrow-23.0.1-cp311-cp311-macosx_12_0_arm64.whl", hash = "sha256:6f0147ee9e0386f519c952cc670eb4a8b05caa594eeffe01af0e25f699e4e9bb", size = 34302230, upload-time = "2026-02-16T10:09:03.859Z" }, - { url = "https://files.pythonhosted.org/packages/bf/4a/1472c00392f521fea03ae93408bf445cc7bfa1ab81683faf9bc188e36629/pyarrow-23.0.1-cp311-cp311-macosx_12_0_x86_64.whl", hash = "sha256:0ae6e17c828455b6265d590100c295193f93cc5675eb0af59e49dbd00d2de350", size = 35850050, upload-time = "2026-02-16T10:09:11.877Z" }, - { url = "https://files.pythonhosted.org/packages/0c/b2/bd1f2f05ded56af7f54d702c8364c9c43cd6abb91b0e9933f3d77b4f4132/pyarrow-23.0.1-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:fed7020203e9ef273360b9e45be52a2a47d3103caf156a30ace5247ffb51bdbd", size = 44491918, upload-time = "2026-02-16T10:09:18.144Z" }, - { url = "https://files.pythonhosted.org/packages/0b/62/96459ef5b67957eac38a90f541d1c28833d1b367f014a482cb63f3b7cd2d/pyarrow-23.0.1-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:26d50dee49d741ac0e82185033488d28d35be4d763ae6f321f97d1140eb7a0e9", size = 47562811, upload-time = "2026-02-16T10:09:25.792Z" }, - { url = "https://files.pythonhosted.org/packages/7d/94/1170e235add1f5f45a954e26cd0e906e7e74e23392dcb560de471f7366ec/pyarrow-23.0.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:3c30143b17161310f151f4a2bcfe41b5ff744238c1039338779424e38579d701", size = 48183766, upload-time = "2026-02-16T10:09:34.645Z" }, - { url = "https://files.pythonhosted.org/packages/0e/2d/39a42af4570377b99774cdb47f63ee6c7da7616bd55b3d5001aa18edfe4f/pyarrow-23.0.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:db2190fa79c80a23fdd29fef4b8992893f024ae7c17d2f5f4db7171fa30c2c78", size = 50607669, upload-time = "2026-02-16T10:09:44.153Z" }, - { url = "https://files.pythonhosted.org/packages/00/ca/db94101c187f3df742133ac837e93b1f269ebdac49427f8310ee40b6a58f/pyarrow-23.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:f00f993a8179e0e1c9713bcc0baf6d6c01326a406a9c23495ec1ba9c9ebf2919", size = 27527698, upload-time = "2026-02-16T10:09:50.263Z" }, - { url = "https://files.pythonhosted.org/packages/9a/4b/4166bb5abbfe6f750fc60ad337c43ecf61340fa52ab386da6e8dbf9e63c4/pyarrow-23.0.1-cp312-cp312-macosx_12_0_arm64.whl", hash = "sha256:f4b0dbfa124c0bb161f8b5ebb40f1a680b70279aa0c9901d44a2b5a20806039f", size = 34214575, upload-time = "2026-02-16T10:09:56.225Z" }, - { url = "https://files.pythonhosted.org/packages/e1/da/3f941e3734ac8088ea588b53e860baeddac8323ea40ce22e3d0baa865cc9/pyarrow-23.0.1-cp312-cp312-macosx_12_0_x86_64.whl", hash = "sha256:7707d2b6673f7de054e2e83d59f9e805939038eebe1763fe811ee8fa5c0cd1a7", size = 35832540, upload-time = "2026-02-16T10:10:03.428Z" }, - { url = "https://files.pythonhosted.org/packages/88/7c/3d841c366620e906d54430817531b877ba646310296df42ef697308c2705/pyarrow-23.0.1-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:86ff03fb9f1a320266e0de855dee4b17da6794c595d207f89bba40d16b5c78b9", size = 44470940, upload-time = "2026-02-16T10:10:10.704Z" }, - { url = "https://files.pythonhosted.org/packages/2c/a5/da83046273d990f256cb79796a190bbf7ec999269705ddc609403f8c6b06/pyarrow-23.0.1-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:813d99f31275919c383aab17f0f455a04f5a429c261cc411b1e9a8f5e4aaaa05", size = 47586063, upload-time = "2026-02-16T10:10:17.95Z" }, - { url = "https://files.pythonhosted.org/packages/5b/3c/b7d2ebcff47a514f47f9da1e74b7949138c58cfeb108cdd4ee62f43f0cf3/pyarrow-23.0.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:bf5842f960cddd2ef757d486041d57c96483efc295a8c4a0e20e704cbbf39c67", size = 48173045, upload-time = "2026-02-16T10:10:25.363Z" }, - { url = "https://files.pythonhosted.org/packages/43/b2/b40961262213beaba6acfc88698eb773dfce32ecdf34d19291db94c2bd73/pyarrow-23.0.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:564baf97c858ecc03ec01a41062e8f4698abc3e6e2acd79c01c2e97880a19730", size = 50621741, upload-time = "2026-02-16T10:10:33.477Z" }, - { url = "https://files.pythonhosted.org/packages/f6/70/1fdda42d65b28b078e93d75d371b2185a61da89dda4def8ba6ba41ebdeb4/pyarrow-23.0.1-cp312-cp312-win_amd64.whl", hash = "sha256:07deae7783782ac7250989a7b2ecde9b3c343a643f82e8a4df03d93b633006f0", size = 27620678, upload-time = "2026-02-16T10:10:39.31Z" }, - { url = "https://files.pythonhosted.org/packages/47/10/2cbe4c6f0fb83d2de37249567373d64327a5e4d8db72f486db42875b08f6/pyarrow-23.0.1-cp313-cp313-macosx_12_0_arm64.whl", hash = "sha256:6b8fda694640b00e8af3c824f99f789e836720aa8c9379fb435d4c4953a756b8", size = 34210066, upload-time = "2026-02-16T10:10:45.487Z" }, - { url = "https://files.pythonhosted.org/packages/cb/4f/679fa7e84dadbaca7a65f7cdba8d6c83febbd93ca12fa4adf40ba3b6362b/pyarrow-23.0.1-cp313-cp313-macosx_12_0_x86_64.whl", hash = "sha256:8ff51b1addc469b9444b7c6f3548e19dc931b172ab234e995a60aea9f6e6025f", size = 35825526, upload-time = "2026-02-16T10:10:52.266Z" }, - { url = "https://files.pythonhosted.org/packages/f9/63/d2747d930882c9d661e9398eefc54f15696547b8983aaaf11d4a2e8b5426/pyarrow-23.0.1-cp313-cp313-manylinux_2_28_aarch64.whl", hash = "sha256:71c5be5cbf1e1cb6169d2a0980850bccb558ddc9b747b6206435313c47c37677", size = 44473279, upload-time = "2026-02-16T10:11:01.557Z" }, - { url = "https://files.pythonhosted.org/packages/b3/93/10a48b5e238de6d562a411af6467e71e7aedbc9b87f8d3a35f1560ae30fb/pyarrow-23.0.1-cp313-cp313-manylinux_2_28_x86_64.whl", hash = "sha256:9b6f4f17b43bc39d56fec96e53fe89d94bac3eb134137964371b45352d40d0c2", size = 47585798, upload-time = "2026-02-16T10:11:09.401Z" }, - { url = "https://files.pythonhosted.org/packages/5c/20/476943001c54ef078dbf9542280e22741219a184a0632862bca4feccd666/pyarrow-23.0.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:9fc13fc6c403d1337acab46a2c4346ca6c9dec5780c3c697cf8abfd5e19b6b37", size = 48179446, upload-time = "2026-02-16T10:11:17.781Z" }, - { url = "https://files.pythonhosted.org/packages/4b/b6/5dd0c47b335fcd8edba9bfab78ad961bd0fd55ebe53468cc393f45e0be60/pyarrow-23.0.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:5c16ed4f53247fa3ffb12a14d236de4213a4415d127fe9cebed33d51671113e2", size = 50623972, upload-time = "2026-02-16T10:11:26.185Z" }, - { url = "https://files.pythonhosted.org/packages/d5/09/a532297c9591a727d67760e2e756b83905dd89adb365a7f6e9c72578bcc1/pyarrow-23.0.1-cp313-cp313-win_amd64.whl", hash = "sha256:cecfb12ef629cf6be0b1887f9f86463b0dd3dc3195ae6224e74006be4736035a", size = 27540749, upload-time = "2026-02-16T10:12:23.297Z" }, - { url = "https://files.pythonhosted.org/packages/a5/8e/38749c4b1303e6ae76b3c80618f84861ae0c55dd3c2273842ea6f8258233/pyarrow-23.0.1-cp313-cp313t-macosx_12_0_arm64.whl", hash = "sha256:29f7f7419a0e30264ea261fdc0e5fe63ce5a6095003db2945d7cd78df391a7e1", size = 34471544, upload-time = "2026-02-16T10:11:32.535Z" }, - { url = "https://files.pythonhosted.org/packages/a3/73/f237b2bc8c669212f842bcfd842b04fc8d936bfc9d471630569132dc920d/pyarrow-23.0.1-cp313-cp313t-macosx_12_0_x86_64.whl", hash = "sha256:33d648dc25b51fd8055c19e4261e813dfc4d2427f068bcecc8b53d01b81b0500", size = 35949911, upload-time = "2026-02-16T10:11:39.813Z" }, - { url = "https://files.pythonhosted.org/packages/0c/86/b912195eee0903b5611bf596833def7d146ab2d301afeb4b722c57ffc966/pyarrow-23.0.1-cp313-cp313t-manylinux_2_28_aarch64.whl", hash = "sha256:cd395abf8f91c673dd3589cadc8cc1ee4e8674fa61b2e923c8dd215d9c7d1f41", size = 44520337, upload-time = "2026-02-16T10:11:47.764Z" }, - { url = "https://files.pythonhosted.org/packages/69/c2/f2a717fb824f62d0be952ea724b4f6f9372a17eed6f704b5c9526f12f2f1/pyarrow-23.0.1-cp313-cp313t-manylinux_2_28_x86_64.whl", hash = "sha256:00be9576d970c31defb5c32eb72ef585bf600ef6d0a82d5eccaae96639cf9d07", size = 47548944, upload-time = "2026-02-16T10:11:56.607Z" }, - { url = "https://files.pythonhosted.org/packages/84/a7/90007d476b9f0dc308e3bc57b832d004f848fd6c0da601375d20d92d1519/pyarrow-23.0.1-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:c2139549494445609f35a5cda4eb94e2c9e4d704ce60a095b342f82460c73a83", size = 48236269, upload-time = "2026-02-16T10:12:04.47Z" }, - { url = "https://files.pythonhosted.org/packages/b0/3f/b16fab3e77709856eb6ac328ce35f57a6d4a18462c7ca5186ef31b45e0e0/pyarrow-23.0.1-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:7044b442f184d84e2351e5084600f0d7343d6117aabcbc1ac78eb1ae11eb4125", size = 50604794, upload-time = "2026-02-16T10:12:11.797Z" }, - { url = "https://files.pythonhosted.org/packages/e9/a1/22df0620a9fac31d68397a75465c344e83c3dfe521f7612aea33e27ab6c0/pyarrow-23.0.1-cp313-cp313t-win_amd64.whl", hash = "sha256:a35581e856a2fafa12f3f54fce4331862b1cfb0bef5758347a858a4aa9d6bae8", size = 27660642, upload-time = "2026-02-16T10:12:17.746Z" }, - { url = "https://files.pythonhosted.org/packages/8d/1b/6da9a89583ce7b23ac611f183ae4843cd3a6cf54f079549b0e8c14031e73/pyarrow-23.0.1-cp314-cp314-macosx_12_0_arm64.whl", hash = "sha256:5df1161da23636a70838099d4aaa65142777185cc0cdba4037a18cee7d8db9ca", size = 34238755, upload-time = "2026-02-16T10:12:32.819Z" }, - { url = "https://files.pythonhosted.org/packages/ae/b5/d58a241fbe324dbaeb8df07be6af8752c846192d78d2272e551098f74e88/pyarrow-23.0.1-cp314-cp314-macosx_12_0_x86_64.whl", hash = "sha256:fa8e51cb04b9f8c9c5ace6bab63af9a1f88d35c0d6cbf53e8c17c098552285e1", size = 35847826, upload-time = "2026-02-16T10:12:38.949Z" }, - { url = "https://files.pythonhosted.org/packages/54/a5/8cbc83f04aba433ca7b331b38f39e000efd9f0c7ce47128670e737542996/pyarrow-23.0.1-cp314-cp314-manylinux_2_28_aarch64.whl", hash = "sha256:0b95a3994f015be13c63148fef8832e8a23938128c185ee951c98908a696e0eb", size = 44536859, upload-time = "2026-02-16T10:12:45.467Z" }, - { url = "https://files.pythonhosted.org/packages/36/2e/c0f017c405fcdc252dbccafbe05e36b0d0eb1ea9a958f081e01c6972927f/pyarrow-23.0.1-cp314-cp314-manylinux_2_28_x86_64.whl", hash = "sha256:4982d71350b1a6e5cfe1af742c53dfb759b11ce14141870d05d9e540d13bc5d1", size = 47614443, upload-time = "2026-02-16T10:12:55.525Z" }, - { url = "https://files.pythonhosted.org/packages/af/6b/2314a78057912f5627afa13ba43809d9d653e6630859618b0fd81a4e0759/pyarrow-23.0.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:c250248f1fe266db627921c89b47b7c06fee0489ad95b04d50353537d74d6886", size = 48232991, upload-time = "2026-02-16T10:13:04.729Z" }, - { url = "https://files.pythonhosted.org/packages/40/f2/1bcb1d3be3460832ef3370d621142216e15a2c7c62602a4ea19ec240dd64/pyarrow-23.0.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:5f4763b83c11c16e5f4c15601ba6dfa849e20723b46aa2617cb4bffe8768479f", size = 50645077, upload-time = "2026-02-16T10:13:14.147Z" }, - { url = "https://files.pythonhosted.org/packages/eb/3f/b1da7b61cd66566a4d4c8383d376c606d1c34a906c3f1cb35c479f59d1aa/pyarrow-23.0.1-cp314-cp314-win_amd64.whl", hash = "sha256:3a4c85ef66c134161987c17b147d6bffdca4566f9a4c1d81a0a01cdf08414ea5", size = 28234271, upload-time = "2026-02-16T10:14:09.397Z" }, - { url = "https://files.pythonhosted.org/packages/b5/78/07f67434e910a0f7323269be7bfbf58699bd0c1d080b18a1ab49ba943fe8/pyarrow-23.0.1-cp314-cp314t-macosx_12_0_arm64.whl", hash = "sha256:17cd28e906c18af486a499422740298c52d7c6795344ea5002a7720b4eadf16d", size = 34488692, upload-time = "2026-02-16T10:13:21.541Z" }, - { url = "https://files.pythonhosted.org/packages/50/76/34cf7ae93ece1f740a04910d9f7e80ba166b9b4ab9596a953e9e62b90fe1/pyarrow-23.0.1-cp314-cp314t-macosx_12_0_x86_64.whl", hash = "sha256:76e823d0e86b4fb5e1cf4a58d293036e678b5a4b03539be933d3b31f9406859f", size = 35964383, upload-time = "2026-02-16T10:13:28.63Z" }, - { url = "https://files.pythonhosted.org/packages/46/90/459b827238936d4244214be7c684e1b366a63f8c78c380807ae25ed92199/pyarrow-23.0.1-cp314-cp314t-manylinux_2_28_aarch64.whl", hash = "sha256:a62e1899e3078bf65943078b3ad2a6ddcacf2373bc06379aac61b1e548a75814", size = 44538119, upload-time = "2026-02-16T10:13:35.506Z" }, - { url = "https://files.pythonhosted.org/packages/28/a1/93a71ae5881e99d1f9de1d4554a87be37da11cd6b152239fb5bd924fdc64/pyarrow-23.0.1-cp314-cp314t-manylinux_2_28_x86_64.whl", hash = "sha256:df088e8f640c9fae3b1f495b3c64755c4e719091caf250f3a74d095ddf3c836d", size = 47571199, upload-time = "2026-02-16T10:13:42.504Z" }, - { url = "https://files.pythonhosted.org/packages/88/a3/d2c462d4ef313521eaf2eff04d204ac60775263f1fb08c374b543f79f610/pyarrow-23.0.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:46718a220d64677c93bc243af1d44b55998255427588e400677d7192671845c7", size = 48259435, upload-time = "2026-02-16T10:13:49.226Z" }, - { url = "https://files.pythonhosted.org/packages/cc/f1/11a544b8c3d38a759eb3fbb022039117fd633e9a7b19e4841cc3da091915/pyarrow-23.0.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:a09f3876e87f48bc2f13583ab551f0379e5dfb83210391e68ace404181a20690", size = 50629149, upload-time = "2026-02-16T10:13:57.238Z" }, - { url = "https://files.pythonhosted.org/packages/50/f2/c0e76a0b451ffdf0cf788932e182758eb7558953f4f27f1aff8e2518b653/pyarrow-23.0.1-cp314-cp314t-win_amd64.whl", hash = "sha256:527e8d899f14bd15b740cd5a54ad56b7f98044955373a17179d5956ddb93d9ce", size = 28365807, upload-time = "2026-02-16T10:14:03.892Z" }, +version = "24.0.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/91/13/13e1069b351bdc3881266e11147ffccf687505dbb0ea74036237f5d454a5/pyarrow-24.0.0.tar.gz", hash = "sha256:85fe721a14dd823aca09127acbb06c3ca723efbd436c004f16bca601b04dcc83", size = 1180261, upload-time = "2026-04-21T10:51:25.837Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/a5/bf/a34fee1d624152124fa8355c42f34195ad5fe5233ce5bb87946432047d52/pyarrow-24.0.0-cp310-cp310-macosx_12_0_arm64.whl", hash = "sha256:7c2b98645d576a0b9616892ead22b64a83a5f043c5e2ca15ebcefcb5b70c80cb", size = 35076681, upload-time = "2026-04-21T08:51:46.845Z" }, + { url = "https://files.pythonhosted.org/packages/1d/41/64180033d7027afce12dc96d0fe1f504c6fa112190582b458acea2399530/pyarrow-24.0.0-cp310-cp310-macosx_12_0_x86_64.whl", hash = "sha256:644a246325b8c69c595ad1dd4b463eba4b0cdb731370e4a86137d433208d6147", size = 36684260, upload-time = "2026-04-21T08:51:53.642Z" }, + { url = "https://files.pythonhosted.org/packages/57/02/9b9320e673dd8a99411fac78690f3df92f6dd6f59754c750110bca66d64e/pyarrow-24.0.0-cp310-cp310-manylinux_2_28_aarch64.whl", hash = "sha256:3a577bd840ca83f646f0a625dbc571dba7044c43c2d1503afc378b570954345c", size = 45698566, upload-time = "2026-04-21T10:46:02.133Z" }, + { url = "https://files.pythonhosted.org/packages/67/33/f75e91b9a64c3f33c787e263c93b871ad91b8a4a68c1d5cebddd9840e835/pyarrow-24.0.0-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:e3268e43984d0b1a185c89b4cfff282a7ead12fc93f56cfd7088bdbcbe727041", size = 48835562, upload-time = "2026-04-21T10:46:10.278Z" }, + { url = "https://files.pythonhosted.org/packages/a5/63/097510448e47e4091faa41c43ba92f97cecaab8f4535b56a3d149578f634/pyarrow-24.0.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:2392d954fcb920f42d230284b677605e4e2fbb11f2821e823e642abd67fbb491", size = 49394997, upload-time = "2026-04-21T10:46:18.08Z" }, + { url = "https://files.pythonhosted.org/packages/60/6b/c047d6222ab279024a062742d1807e2fbaf27bba88a98637299ff47b9236/pyarrow-24.0.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:bec9373df11544592b0ba7ec2af0e35059e5f0e7647c6183a854dedd193298f1", size = 51911424, upload-time = "2026-04-21T10:46:25.347Z" }, + { url = "https://files.pythonhosted.org/packages/3a/ba/464cc70761c2a525d97ebd84e21c31ebd47f3ef4bdcee117009f51c46f24/pyarrow-24.0.0-cp310-cp310-win_amd64.whl", hash = "sha256:c42ab9439498270139cc63e18847a02afe5c8b3ed9c931266533cfe378bd3591", size = 27251730, upload-time = "2026-04-21T10:46:30.913Z" }, + { url = "https://files.pythonhosted.org/packages/62/c9/a47ab7ece0d86cbe6678418a0fbd1ac4bb493b9184a3891dfa0e7f287ae0/pyarrow-24.0.0-cp311-cp311-macosx_12_0_arm64.whl", hash = "sha256:b0e131f880cda8d04e076cee175a46fc0e8bc8b65c99c6c09dff6669335fde74", size = 35068898, upload-time = "2026-04-21T10:46:36.599Z" }, + { url = "https://files.pythonhosted.org/packages/d1/bc/8db86617a9a58008acf8913d6fed68ea2a46acb6de928db28d724c891a68/pyarrow-24.0.0-cp311-cp311-macosx_12_0_x86_64.whl", hash = "sha256:1b2fe7f9a5566401a0ef2571f197eb92358925c1f0c8dba305d6e43ea0871bb3", size = 36679915, upload-time = "2026-04-21T10:46:42.602Z" }, + { url = "https://files.pythonhosted.org/packages/eb/8e/fb178720400ef69db251eb4a9c3ccf4af269bc1feb5055529b8fc87170d1/pyarrow-24.0.0-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:0b3537c00fb8d384f15ac1e79b6eb6db04a16514c8c1d22e59a9b95c8ba42868", size = 45697931, upload-time = "2026-04-21T10:46:48.403Z" }, + { url = "https://files.pythonhosted.org/packages/f3/27/99c42abe8e21b44f4917f62631f3aa31404882a2c41d8a4cd5c110e13d52/pyarrow-24.0.0-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:14e31a3c9e35f1ab6356c6378f6f72830e6d2d5f1791df3774a7b097d18a6a1e", size = 48837449, upload-time = "2026-04-21T10:46:55.329Z" }, + { url = "https://files.pythonhosted.org/packages/36/b6/333749e2666e9032891125bf9c691146e92901bece62030ac1430e2e7c88/pyarrow-24.0.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:b7d9a514e73bc42711e6a35aaccf3587c520024fe0a25d830a1a8a27c15f4f57", size = 49395949, upload-time = "2026-04-21T10:47:01.869Z" }, + { url = "https://files.pythonhosted.org/packages/17/25/c5201706a2dd374e8ba6ee3fd7a8c89fb7ffc16eed5217a91fd2bd7f7626/pyarrow-24.0.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:b196eb3f931862af3fa84c2a253514d859c08e0d8fe020e07be12e75a5a9780c", size = 51912986, upload-time = "2026-04-21T10:47:09.872Z" }, + { url = "https://files.pythonhosted.org/packages/f8/d2/4d1bbba65320b21a49678d6fbdc6ff7c649251359fdcfc03568c4136231d/pyarrow-24.0.0-cp311-cp311-win_amd64.whl", hash = "sha256:35405aecb474e683fb36af650618fd5340ee5471fc65a21b36076a18bbc6c981", size = 27255371, upload-time = "2026-04-21T10:47:15.943Z" }, + { url = "https://files.pythonhosted.org/packages/b4/a9/9686d9f07837f91f775e8932659192e02c74f9d8920524b480b85212cc68/pyarrow-24.0.0-cp312-cp312-macosx_12_0_arm64.whl", hash = "sha256:6233c9ed9ab9d1db47de57d9753256d9dcffbf42db341576099f0fd9f6bf4810", size = 34981559, upload-time = "2026-04-21T10:47:22.17Z" }, + { url = "https://files.pythonhosted.org/packages/80/b6/0ddf0e9b6ead3474ab087ae598c76b031fc45532bf6a63f3a553440fb258/pyarrow-24.0.0-cp312-cp312-macosx_12_0_x86_64.whl", hash = "sha256:f7616236ec1bc2b15bfdec22a71ab38851c86f8f05ff64f379e1278cf20c634a", size = 36663654, upload-time = "2026-04-21T10:47:28.315Z" }, + { url = "https://files.pythonhosted.org/packages/7c/3b/926382efe8ce27ba729071d3566ade6dfb86bdf112f366000196b2f5780a/pyarrow-24.0.0-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:1617043b99bd33e5318ae18eb2919af09c71322ef1ca46566cdafc6e6712fb66", size = 45679394, upload-time = "2026-04-21T10:47:34.821Z" }, + { url = "https://files.pythonhosted.org/packages/b3/7a/829f7d9dfd37c207206081d6dad474d81dde29952401f07f2ba507814818/pyarrow-24.0.0-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:6165461f55ef6314f026de6638d661188e3455d3ec49834556a0ebbdbace18bb", size = 48863122, upload-time = "2026-04-21T10:47:42.056Z" }, + { url = "https://files.pythonhosted.org/packages/5f/e8/f88ce625fe8babaae64e8db2d417c7653adb3019b08aae85c5ed787dc816/pyarrow-24.0.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:3b13dedfe76a0ad2d1d859b0811b53827a4e9d93a0bcb05cf59333ab4980cc7e", size = 49376032, upload-time = "2026-04-21T10:47:48.967Z" }, + { url = "https://files.pythonhosted.org/packages/36/7a/82c363caa145fff88fb475da50d3bf52bb024f61917be5424c3392eaf878/pyarrow-24.0.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:25ea65d868eb04015cd18e6df2fbe98f07e5bda2abefabcb88fce39a947716f6", size = 51929490, upload-time = "2026-04-21T10:47:55.981Z" }, + { url = "https://files.pythonhosted.org/packages/66/1c/e3e72c8014ad2743ca64a701652c733cc5cbcee15c0463a32a8c55518d9e/pyarrow-24.0.0-cp312-cp312-win_amd64.whl", hash = "sha256:295f0a7f2e242dabd513737cf076007dc5b2d59237e3eca37b05c0c6446f3826", size = 27355660, upload-time = "2026-04-21T10:48:01.718Z" }, + { url = "https://files.pythonhosted.org/packages/6f/d3/a1abf004482026ddc17f4503db227787fa3cfe41ec5091ff20e4fea55e57/pyarrow-24.0.0-cp313-cp313-macosx_12_0_arm64.whl", hash = "sha256:02b001b3ed4723caa44f6cd1af2d5c86aa2cf9971dacc2ffa55b21237713dfba", size = 34976759, upload-time = "2026-04-21T10:48:07.258Z" }, + { url = "https://files.pythonhosted.org/packages/4f/4a/34f0a36d28a2dd32225301b79daad44e243dc1a2bb77d43b60749be255c4/pyarrow-24.0.0-cp313-cp313-macosx_12_0_x86_64.whl", hash = "sha256:04920d6a71aabd08a0417709efce97d45ea8e6fb733d9ca9ecffb13c67839f68", size = 36658471, upload-time = "2026-04-21T10:48:13.347Z" }, + { url = "https://files.pythonhosted.org/packages/1f/78/543b94712ae8bb1a6023bcc1acf1a740fbff8286747c289cd9468fced2a5/pyarrow-24.0.0-cp313-cp313-manylinux_2_28_aarch64.whl", hash = "sha256:a964266397740257f16f7bb2e4f08a0c81454004beab8ff59dd531b73610e9f2", size = 45675981, upload-time = "2026-04-21T10:48:20.201Z" }, + { url = "https://files.pythonhosted.org/packages/84/9f/8fb7c222b100d314137fa40ec050de56cd8c6d957d1cfff685ce72f15b17/pyarrow-24.0.0-cp313-cp313-manylinux_2_28_x86_64.whl", hash = "sha256:6f066b179d68c413374294bc1735f68475457c933258df594443bb9d88ddc2a0", size = 48859172, upload-time = "2026-04-21T10:48:27.541Z" }, + { url = "https://files.pythonhosted.org/packages/a7/d3/1ea72538e6c8b3b475ed78d1049a2c518e655761ea50fe1171fc855fcab7/pyarrow-24.0.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:1183baeb14c5f587b1ec52831e665718ce632caab84b7cd6b85fd44f96114495", size = 49385733, upload-time = "2026-04-21T10:48:34.7Z" }, + { url = "https://files.pythonhosted.org/packages/c3/be/c3d8b06a1ba35f2260f8e1f771abbee7d5e345c0937aab90675706b1690a/pyarrow-24.0.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:806f24b4085453c197a5078218d1ee08783ebbba271badd153d1ae22a3ee804f", size = 51934335, upload-time = "2026-04-21T10:48:42.099Z" }, + { url = "https://files.pythonhosted.org/packages/9c/62/89e07a1e7329d2cde3e3c6994ba0839a24977a2beda8be6005ea3d860b99/pyarrow-24.0.0-cp313-cp313-win_amd64.whl", hash = "sha256:e4505fc6583f7b05ab854934896bcac8253b04ac1171a77dfb73efef92076d91", size = 27271748, upload-time = "2026-04-21T10:49:42.532Z" }, + { url = "https://files.pythonhosted.org/packages/17/1a/cff3a59f80b5b1658549d46611b67163f65e0664431c076ad728bf9d5af4/pyarrow-24.0.0-cp313-cp313t-macosx_12_0_arm64.whl", hash = "sha256:1a4e45017efbf115032e4475ee876d525e0e36c742214fbe405332480ecd6275", size = 35238554, upload-time = "2026-04-21T10:48:48.526Z" }, + { url = "https://files.pythonhosted.org/packages/a8/99/cce0f42a327bfef2c420fb6078a3eb834826e5d6697bf3009fe11d2ad051/pyarrow-24.0.0-cp313-cp313t-macosx_12_0_x86_64.whl", hash = "sha256:7986f1fa71cee060ad00758bcc79d3a93bab8559bf978fab9e53472a2e25a17b", size = 36782301, upload-time = "2026-04-21T10:48:55.181Z" }, + { url = "https://files.pythonhosted.org/packages/2a/66/8e560d5ff6793ca29aca213c53eec0dd482dd46cb93b2819e5aab52e4252/pyarrow-24.0.0-cp313-cp313t-manylinux_2_28_aarch64.whl", hash = "sha256:d3e0b61e8efb24ed38898e5cdc5fffa9124be480008d401a1f8071500494ae42", size = 45721929, upload-time = "2026-04-21T10:49:03.676Z" }, + { url = "https://files.pythonhosted.org/packages/27/0c/a26e25505d030716e078d9f16eb74973cbf0b33b672884e9f9da1c83b871/pyarrow-24.0.0-cp313-cp313t-manylinux_2_28_x86_64.whl", hash = "sha256:55a3bc1e3df3b5567b7d27ef551b2283f0c68a5e86f1cd56abc569da4f31335b", size = 48825365, upload-time = "2026-04-21T10:49:11.714Z" }, + { url = "https://files.pythonhosted.org/packages/5f/eb/771f9ecb0c65e73fe9dccdd1717901b9594f08c4515d000c7c62df573811/pyarrow-24.0.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:641f795b361874ac9da5294f8f443dfdbee355cf2bd9e3b8d97aaac2306b9b37", size = 49451819, upload-time = "2026-04-21T10:49:21.474Z" }, + { url = "https://files.pythonhosted.org/packages/48/da/61ae89a88732f5a785646f3ec6125dbb640fa98a540eb2b9889caa561403/pyarrow-24.0.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:8adc8e6ce5fccf5dc707046ae4914fd537def529709cc0d285d37a7f9cd442ca", size = 51909252, upload-time = "2026-04-21T10:49:31.164Z" }, + { url = "https://files.pythonhosted.org/packages/cb/1a/8dd5cafab7b66573fa91c03d06d213356ad4edd71813aa75e08ce2b3a844/pyarrow-24.0.0-cp313-cp313t-win_amd64.whl", hash = "sha256:9b18371ad2f44044b81a8d23bc2d8a9b6a6226dca775e8e16cfee640473d6c5d", size = 27388127, upload-time = "2026-04-21T10:49:37.334Z" }, + { url = "https://files.pythonhosted.org/packages/ad/80/d022a34ff05d2cbedd8ccf841fc1f532ecfa9eb5ed1711b56d0e0ea71fc9/pyarrow-24.0.0-cp314-cp314-macosx_12_0_arm64.whl", hash = "sha256:1cc9057f0319e26333b357e17f3c2c022f1a83739b48a88b25bfd5fa2dc18838", size = 35007997, upload-time = "2026-04-21T10:49:48.796Z" }, + { url = "https://files.pythonhosted.org/packages/1a/ff/f01485fda6f4e5d441afb8dd5e7681e4db18826c1e271852f5d3957d6a80/pyarrow-24.0.0-cp314-cp314-macosx_12_0_x86_64.whl", hash = "sha256:e6f1278ee4785b6db21229374a1c9e54ec7c549de5d1efc9630b6207de7e170b", size = 36678720, upload-time = "2026-04-21T10:49:55.858Z" }, + { url = "https://files.pythonhosted.org/packages/9e/c2/2d2d5fea814237923f71b36495211f20b43a1576f9a4d6da7e751a64ec6f/pyarrow-24.0.0-cp314-cp314-manylinux_2_28_aarch64.whl", hash = "sha256:adbbedc55506cbdabb830890444fb856bfb0060c46c6f8026c6c2f2cf86ae795", size = 45741852, upload-time = "2026-04-21T10:50:04.624Z" }, + { url = "https://files.pythonhosted.org/packages/8e/3a/28ba9c1c1ebdbb5f1b94dfebb46f207e52e6a554b7fe4132540fde29a3a0/pyarrow-24.0.0-cp314-cp314-manylinux_2_28_x86_64.whl", hash = "sha256:ae8a1145af31d903fa9bb166824d7abe9b4681a000b0159c9fb99c11bc11ad26", size = 48889852, upload-time = "2026-04-21T10:50:12.293Z" }, + { url = "https://files.pythonhosted.org/packages/df/51/4a389acfd31dca009f8fb82d7f510bb4130f2b3a8e18cf00194d0687d8ac/pyarrow-24.0.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:d7027eba1df3b2069e2e8d80f644fa0918b68c46432af3d088ddd390d063ecde", size = 49445207, upload-time = "2026-04-21T10:50:20.677Z" }, + { url = "https://files.pythonhosted.org/packages/19/4b/0bab2b23d2ae901b1b9a03c0efd4b2d070256f8ce3fc43f6e58c167b2081/pyarrow-24.0.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:e56a1ffe9bf7b727432b89104cc0849c21582949dd7bdcb34f17b2001a351a76", size = 51954117, upload-time = "2026-04-21T10:50:29.14Z" }, + { url = "https://files.pythonhosted.org/packages/29/88/f4e9145da0417b3d2c12035a8492b35ff4a3dbc653e614fcfb51d9dedb38/pyarrow-24.0.0-cp314-cp314-win_amd64.whl", hash = "sha256:38be1808cdd068605b787e6ca9119b27eb275a0234e50212c3492331680c3b1e", size = 28001155, upload-time = "2026-04-21T10:51:22.337Z" }, + { url = "https://files.pythonhosted.org/packages/79/4f/46a49a63f43526da895b1a45bbb51d5baf8e4d77159f8528fc3e5490007f/pyarrow-24.0.0-cp314-cp314t-macosx_12_0_arm64.whl", hash = "sha256:418e48ce50a45a6a6c73c454677203a9c75c966cb1e92ca3370959185f197a05", size = 35250387, upload-time = "2026-04-21T10:50:35.552Z" }, + { url = "https://files.pythonhosted.org/packages/a0/da/d5e0cd5ef00796922404806d5f00325cdadc3441ce2c13fe7115f2df9a64/pyarrow-24.0.0-cp314-cp314t-macosx_12_0_x86_64.whl", hash = "sha256:2f16197705a230a78270cdd4ea8a1d57e86b2fdcbc34a1f6aebc72e65c986f9a", size = 36797102, upload-time = "2026-04-21T10:50:42.417Z" }, + { url = "https://files.pythonhosted.org/packages/34/c7/5904145b0a593a05236c882933d439b5720f0a145381179063722fbfc123/pyarrow-24.0.0-cp314-cp314t-manylinux_2_28_aarch64.whl", hash = "sha256:fb24ac194bfc5e86839d7dcd52092ee31e5fe6733fe11f5e3b06ef0812b20072", size = 45745118, upload-time = "2026-04-21T10:50:49.324Z" }, + { url = "https://files.pythonhosted.org/packages/13/d3/cca42fe166d1c6e4d5b80e530b7949104d10e17508a90ae202dac205ce2a/pyarrow-24.0.0-cp314-cp314t-manylinux_2_28_x86_64.whl", hash = "sha256:9700ebd9a51f5895ce75ff4ac4b3c47a7d4b42bc618be8e713e5d56bacf5f931", size = 48844765, upload-time = "2026-04-21T10:50:55.579Z" }, + { url = "https://files.pythonhosted.org/packages/b0/49/942c3b79878ba928324d1e17c274ed84581db8c0a749b24bcf4cbdf15bd3/pyarrow-24.0.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:d8ddd2768da81d3ee08cfea9b597f4abb4e8e1dc8ae7e204b608d23a0d3ab699", size = 49471890, upload-time = "2026-04-21T10:51:02.439Z" }, + { url = "https://files.pythonhosted.org/packages/76/97/ff71431000a75d84135a1ace5ca4ba11726a231a8007bbb320a4c54075d5/pyarrow-24.0.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:61a3d7eaa97a14768b542f3d284dc6400dd2470d9f080708b13cd46b6ae18136", size = 51932250, upload-time = "2026-04-21T10:51:10.576Z" }, + { url = "https://files.pythonhosted.org/packages/51/be/6f79d55816d5c22557cf27533543d5d70dfe692adfbee4b99f2760674f38/pyarrow-24.0.0-cp314-cp314t-win_amd64.whl", hash = "sha256:c91d00057f23b8d353039520dc3a6c09d8608164c692e9f59a175a42b2ae0c19", size = 28131282, upload-time = "2026-04-21T10:51:16.815Z" }, ] [[package]] @@ -4121,7 +4126,7 @@ wheels = [ [[package]] name = "pydantic" -version = "2.12.4" +version = "2.13.3" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "annotated-types" }, @@ -4129,141 +4134,139 @@ dependencies = [ { name = "typing-extensions" }, { name = "typing-inspection" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/96/ad/a17bc283d7d81837c061c49e3eaa27a45991759a1b7eae1031921c6bd924/pydantic-2.12.4.tar.gz", hash = "sha256:0f8cb9555000a4b5b617f66bfd2566264c4984b27589d3b845685983e8ea85ac", size = 821038, upload-time = "2025-11-05T10:50:08.59Z" } +sdist = { url = "https://files.pythonhosted.org/packages/d9/e4/40d09941a2cebcb20609b86a559817d5b9291c49dd6f8c87e5feffbe703a/pydantic-2.13.3.tar.gz", hash = "sha256:af09e9d1d09f4e7fe37145c1f577e1d61ceb9a41924bf0094a36506285d0a84d", size = 844068, upload-time = "2026-04-20T14:46:43.632Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/82/2f/e68750da9b04856e2a7ec56fc6f034a5a79775e9b9a81882252789873798/pydantic-2.12.4-py3-none-any.whl", hash = "sha256:92d3d202a745d46f9be6df459ac5a064fdaa3c1c4cd8adcfa332ccf3c05f871e", size = 463400, upload-time = "2025-11-05T10:50:06.732Z" }, + { url = "https://files.pythonhosted.org/packages/f3/0a/fd7d723f8f8153418fb40cf9c940e82004fce7e987026b08a68a36dd3fe7/pydantic-2.13.3-py3-none-any.whl", hash = "sha256:6db14ac8dfc9a1e57f87ea2c0de670c251240f43cb0c30a5130e9720dc612927", size = 471981, upload-time = "2026-04-20T14:46:41.402Z" }, ] [[package]] name = "pydantic-core" -version = "2.41.5" +version = "2.46.3" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/71/70/23b021c950c2addd24ec408e9ab05d59b035b39d97cdc1130e1bce647bb6/pydantic_core-2.41.5.tar.gz", hash = "sha256:08daa51ea16ad373ffd5e7606252cc32f07bc72b28284b6bc9c6df804816476e", size = 460952, upload-time = "2025-11-04T13:43:49.098Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/c6/90/32c9941e728d564b411d574d8ee0cf09b12ec978cb22b294995bae5549a5/pydantic_core-2.41.5-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:77b63866ca88d804225eaa4af3e664c5faf3568cea95360d21f4725ab6e07146", size = 2107298, upload-time = "2025-11-04T13:39:04.116Z" }, - { url = "https://files.pythonhosted.org/packages/fb/a8/61c96a77fe28993d9a6fb0f4127e05430a267b235a124545d79fea46dd65/pydantic_core-2.41.5-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:dfa8a0c812ac681395907e71e1274819dec685fec28273a28905df579ef137e2", size = 1901475, upload-time = "2025-11-04T13:39:06.055Z" }, - { url = "https://files.pythonhosted.org/packages/5d/b6/338abf60225acc18cdc08b4faef592d0310923d19a87fba1faf05af5346e/pydantic_core-2.41.5-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5921a4d3ca3aee735d9fd163808f5e8dd6c6972101e4adbda9a4667908849b97", size = 1918815, upload-time = "2025-11-04T13:39:10.41Z" }, - { url = "https://files.pythonhosted.org/packages/d1/1c/2ed0433e682983d8e8cba9c8d8ef274d4791ec6a6f24c58935b90e780e0a/pydantic_core-2.41.5-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e25c479382d26a2a41b7ebea1043564a937db462816ea07afa8a44c0866d52f9", size = 2065567, upload-time = "2025-11-04T13:39:12.244Z" }, - { url = "https://files.pythonhosted.org/packages/b3/24/cf84974ee7d6eae06b9e63289b7b8f6549d416b5c199ca2d7ce13bbcf619/pydantic_core-2.41.5-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f547144f2966e1e16ae626d8ce72b4cfa0caedc7fa28052001c94fb2fcaa1c52", size = 2230442, upload-time = "2025-11-04T13:39:13.962Z" }, - { url = "https://files.pythonhosted.org/packages/fd/21/4e287865504b3edc0136c89c9c09431be326168b1eb7841911cbc877a995/pydantic_core-2.41.5-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6f52298fbd394f9ed112d56f3d11aabd0d5bd27beb3084cc3d8ad069483b8941", size = 2350956, upload-time = "2025-11-04T13:39:15.889Z" }, - { url = "https://files.pythonhosted.org/packages/a8/76/7727ef2ffa4b62fcab916686a68a0426b9b790139720e1934e8ba797e238/pydantic_core-2.41.5-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:100baa204bb412b74fe285fb0f3a385256dad1d1879f0a5cb1499ed2e83d132a", size = 2068253, upload-time = "2025-11-04T13:39:17.403Z" }, - { url = "https://files.pythonhosted.org/packages/d5/8c/a4abfc79604bcb4c748e18975c44f94f756f08fb04218d5cb87eb0d3a63e/pydantic_core-2.41.5-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:05a2c8852530ad2812cb7914dc61a1125dc4e06252ee98e5638a12da6cc6fb6c", size = 2177050, upload-time = "2025-11-04T13:39:19.351Z" }, - { url = "https://files.pythonhosted.org/packages/67/b1/de2e9a9a79b480f9cb0b6e8b6ba4c50b18d4e89852426364c66aa82bb7b3/pydantic_core-2.41.5-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:29452c56df2ed968d18d7e21f4ab0ac55e71dc59524872f6fc57dcf4a3249ed2", size = 2147178, upload-time = "2025-11-04T13:39:21Z" }, - { url = "https://files.pythonhosted.org/packages/16/c1/dfb33f837a47b20417500efaa0378adc6635b3c79e8369ff7a03c494b4ac/pydantic_core-2.41.5-cp310-cp310-musllinux_1_1_armv7l.whl", hash = "sha256:d5160812ea7a8a2ffbe233d8da666880cad0cbaf5d4de74ae15c313213d62556", size = 2341833, upload-time = "2025-11-04T13:39:22.606Z" }, - { url = "https://files.pythonhosted.org/packages/47/36/00f398642a0f4b815a9a558c4f1dca1b4020a7d49562807d7bc9ff279a6c/pydantic_core-2.41.5-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:df3959765b553b9440adfd3c795617c352154e497a4eaf3752555cfb5da8fc49", size = 2321156, upload-time = "2025-11-04T13:39:25.843Z" }, - { url = "https://files.pythonhosted.org/packages/7e/70/cad3acd89fde2010807354d978725ae111ddf6d0ea46d1ea1775b5c1bd0c/pydantic_core-2.41.5-cp310-cp310-win32.whl", hash = "sha256:1f8d33a7f4d5a7889e60dc39856d76d09333d8a6ed0f5f1190635cbec70ec4ba", size = 1989378, upload-time = "2025-11-04T13:39:27.92Z" }, - { url = "https://files.pythonhosted.org/packages/76/92/d338652464c6c367e5608e4488201702cd1cbb0f33f7b6a85a60fe5f3720/pydantic_core-2.41.5-cp310-cp310-win_amd64.whl", hash = "sha256:62de39db01b8d593e45871af2af9e497295db8d73b085f6bfd0b18c83c70a8f9", size = 2013622, upload-time = "2025-11-04T13:39:29.848Z" }, - { url = "https://files.pythonhosted.org/packages/e8/72/74a989dd9f2084b3d9530b0915fdda64ac48831c30dbf7c72a41a5232db8/pydantic_core-2.41.5-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:a3a52f6156e73e7ccb0f8cced536adccb7042be67cb45f9562e12b319c119da6", size = 2105873, upload-time = "2025-11-04T13:39:31.373Z" }, - { url = "https://files.pythonhosted.org/packages/12/44/37e403fd9455708b3b942949e1d7febc02167662bf1a7da5b78ee1ea2842/pydantic_core-2.41.5-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:7f3bf998340c6d4b0c9a2f02d6a400e51f123b59565d74dc60d252ce888c260b", size = 1899826, upload-time = "2025-11-04T13:39:32.897Z" }, - { url = "https://files.pythonhosted.org/packages/33/7f/1d5cab3ccf44c1935a359d51a8a2a9e1a654b744b5e7f80d41b88d501eec/pydantic_core-2.41.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:378bec5c66998815d224c9ca994f1e14c0c21cb95d2f52b6021cc0b2a58f2a5a", size = 1917869, upload-time = "2025-11-04T13:39:34.469Z" }, - { url = "https://files.pythonhosted.org/packages/6e/6a/30d94a9674a7fe4f4744052ed6c5e083424510be1e93da5bc47569d11810/pydantic_core-2.41.5-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e7b576130c69225432866fe2f4a469a85a54ade141d96fd396dffcf607b558f8", size = 2063890, upload-time = "2025-11-04T13:39:36.053Z" }, - { url = "https://files.pythonhosted.org/packages/50/be/76e5d46203fcb2750e542f32e6c371ffa9b8ad17364cf94bb0818dbfb50c/pydantic_core-2.41.5-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6cb58b9c66f7e4179a2d5e0f849c48eff5c1fca560994d6eb6543abf955a149e", size = 2229740, upload-time = "2025-11-04T13:39:37.753Z" }, - { url = "https://files.pythonhosted.org/packages/d3/ee/fed784df0144793489f87db310a6bbf8118d7b630ed07aa180d6067e653a/pydantic_core-2.41.5-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:88942d3a3dff3afc8288c21e565e476fc278902ae4d6d134f1eeda118cc830b1", size = 2350021, upload-time = "2025-11-04T13:39:40.94Z" }, - { url = "https://files.pythonhosted.org/packages/c8/be/8fed28dd0a180dca19e72c233cbf58efa36df055e5b9d90d64fd1740b828/pydantic_core-2.41.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f31d95a179f8d64d90f6831d71fa93290893a33148d890ba15de25642c5d075b", size = 2066378, upload-time = "2025-11-04T13:39:42.523Z" }, - { url = "https://files.pythonhosted.org/packages/b0/3b/698cf8ae1d536a010e05121b4958b1257f0b5522085e335360e53a6b1c8b/pydantic_core-2.41.5-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:c1df3d34aced70add6f867a8cf413e299177e0c22660cc767218373d0779487b", size = 2175761, upload-time = "2025-11-04T13:39:44.553Z" }, - { url = "https://files.pythonhosted.org/packages/b8/ba/15d537423939553116dea94ce02f9c31be0fa9d0b806d427e0308ec17145/pydantic_core-2.41.5-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:4009935984bd36bd2c774e13f9a09563ce8de4abaa7226f5108262fa3e637284", size = 2146303, upload-time = "2025-11-04T13:39:46.238Z" }, - { url = "https://files.pythonhosted.org/packages/58/7f/0de669bf37d206723795f9c90c82966726a2ab06c336deba4735b55af431/pydantic_core-2.41.5-cp311-cp311-musllinux_1_1_armv7l.whl", hash = "sha256:34a64bc3441dc1213096a20fe27e8e128bd3ff89921706e83c0b1ac971276594", size = 2340355, upload-time = "2025-11-04T13:39:48.002Z" }, - { url = "https://files.pythonhosted.org/packages/e5/de/e7482c435b83d7e3c3ee5ee4451f6e8973cff0eb6007d2872ce6383f6398/pydantic_core-2.41.5-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:c9e19dd6e28fdcaa5a1de679aec4141f691023916427ef9bae8584f9c2fb3b0e", size = 2319875, upload-time = "2025-11-04T13:39:49.705Z" }, - { url = "https://files.pythonhosted.org/packages/fe/e6/8c9e81bb6dd7560e33b9053351c29f30c8194b72f2d6932888581f503482/pydantic_core-2.41.5-cp311-cp311-win32.whl", hash = "sha256:2c010c6ded393148374c0f6f0bf89d206bf3217f201faa0635dcd56bd1520f6b", size = 1987549, upload-time = "2025-11-04T13:39:51.842Z" }, - { url = "https://files.pythonhosted.org/packages/11/66/f14d1d978ea94d1bc21fc98fcf570f9542fe55bfcc40269d4e1a21c19bf7/pydantic_core-2.41.5-cp311-cp311-win_amd64.whl", hash = "sha256:76ee27c6e9c7f16f47db7a94157112a2f3a00e958bc626e2f4ee8bec5c328fbe", size = 2011305, upload-time = "2025-11-04T13:39:53.485Z" }, - { url = "https://files.pythonhosted.org/packages/56/d8/0e271434e8efd03186c5386671328154ee349ff0354d83c74f5caaf096ed/pydantic_core-2.41.5-cp311-cp311-win_arm64.whl", hash = "sha256:4bc36bbc0b7584de96561184ad7f012478987882ebf9f9c389b23f432ea3d90f", size = 1972902, upload-time = "2025-11-04T13:39:56.488Z" }, - { url = "https://files.pythonhosted.org/packages/5f/5d/5f6c63eebb5afee93bcaae4ce9a898f3373ca23df3ccaef086d0233a35a7/pydantic_core-2.41.5-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:f41a7489d32336dbf2199c8c0a215390a751c5b014c2c1c5366e817202e9cdf7", size = 2110990, upload-time = "2025-11-04T13:39:58.079Z" }, - { url = "https://files.pythonhosted.org/packages/aa/32/9c2e8ccb57c01111e0fd091f236c7b371c1bccea0fa85247ac55b1e2b6b6/pydantic_core-2.41.5-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:070259a8818988b9a84a449a2a7337c7f430a22acc0859c6b110aa7212a6d9c0", size = 1896003, upload-time = "2025-11-04T13:39:59.956Z" }, - { url = "https://files.pythonhosted.org/packages/68/b8/a01b53cb0e59139fbc9e4fda3e9724ede8de279097179be4ff31f1abb65a/pydantic_core-2.41.5-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e96cea19e34778f8d59fe40775a7a574d95816eb150850a85a7a4c8f4b94ac69", size = 1919200, upload-time = "2025-11-04T13:40:02.241Z" }, - { url = "https://files.pythonhosted.org/packages/38/de/8c36b5198a29bdaade07b5985e80a233a5ac27137846f3bc2d3b40a47360/pydantic_core-2.41.5-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ed2e99c456e3fadd05c991f8f437ef902e00eedf34320ba2b0842bd1c3ca3a75", size = 2052578, upload-time = "2025-11-04T13:40:04.401Z" }, - { url = "https://files.pythonhosted.org/packages/00/b5/0e8e4b5b081eac6cb3dbb7e60a65907549a1ce035a724368c330112adfdd/pydantic_core-2.41.5-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:65840751b72fbfd82c3c640cff9284545342a4f1eb1586ad0636955b261b0b05", size = 2208504, upload-time = "2025-11-04T13:40:06.072Z" }, - { url = "https://files.pythonhosted.org/packages/77/56/87a61aad59c7c5b9dc8caad5a41a5545cba3810c3e828708b3d7404f6cef/pydantic_core-2.41.5-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e536c98a7626a98feb2d3eaf75944ef6f3dbee447e1f841eae16f2f0a72d8ddc", size = 2335816, upload-time = "2025-11-04T13:40:07.835Z" }, - { url = "https://files.pythonhosted.org/packages/0d/76/941cc9f73529988688a665a5c0ecff1112b3d95ab48f81db5f7606f522d3/pydantic_core-2.41.5-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eceb81a8d74f9267ef4081e246ffd6d129da5d87e37a77c9bde550cb04870c1c", size = 2075366, upload-time = "2025-11-04T13:40:09.804Z" }, - { url = "https://files.pythonhosted.org/packages/d3/43/ebef01f69baa07a482844faaa0a591bad1ef129253ffd0cdaa9d8a7f72d3/pydantic_core-2.41.5-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d38548150c39b74aeeb0ce8ee1d8e82696f4a4e16ddc6de7b1d8823f7de4b9b5", size = 2171698, upload-time = "2025-11-04T13:40:12.004Z" }, - { url = "https://files.pythonhosted.org/packages/b1/87/41f3202e4193e3bacfc2c065fab7706ebe81af46a83d3e27605029c1f5a6/pydantic_core-2.41.5-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:c23e27686783f60290e36827f9c626e63154b82b116d7fe9adba1fda36da706c", size = 2132603, upload-time = "2025-11-04T13:40:13.868Z" }, - { url = "https://files.pythonhosted.org/packages/49/7d/4c00df99cb12070b6bccdef4a195255e6020a550d572768d92cc54dba91a/pydantic_core-2.41.5-cp312-cp312-musllinux_1_1_armv7l.whl", hash = "sha256:482c982f814460eabe1d3bb0adfdc583387bd4691ef00b90575ca0d2b6fe2294", size = 2329591, upload-time = "2025-11-04T13:40:15.672Z" }, - { url = "https://files.pythonhosted.org/packages/cc/6a/ebf4b1d65d458f3cda6a7335d141305dfa19bdc61140a884d165a8a1bbc7/pydantic_core-2.41.5-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:bfea2a5f0b4d8d43adf9d7b8bf019fb46fdd10a2e5cde477fbcb9d1fa08c68e1", size = 2319068, upload-time = "2025-11-04T13:40:17.532Z" }, - { url = "https://files.pythonhosted.org/packages/49/3b/774f2b5cd4192d5ab75870ce4381fd89cf218af999515baf07e7206753f0/pydantic_core-2.41.5-cp312-cp312-win32.whl", hash = "sha256:b74557b16e390ec12dca509bce9264c3bbd128f8a2c376eaa68003d7f327276d", size = 1985908, upload-time = "2025-11-04T13:40:19.309Z" }, - { url = "https://files.pythonhosted.org/packages/86/45/00173a033c801cacf67c190fef088789394feaf88a98a7035b0e40d53dc9/pydantic_core-2.41.5-cp312-cp312-win_amd64.whl", hash = "sha256:1962293292865bca8e54702b08a4f26da73adc83dd1fcf26fbc875b35d81c815", size = 2020145, upload-time = "2025-11-04T13:40:21.548Z" }, - { url = "https://files.pythonhosted.org/packages/f9/22/91fbc821fa6d261b376a3f73809f907cec5ca6025642c463d3488aad22fb/pydantic_core-2.41.5-cp312-cp312-win_arm64.whl", hash = "sha256:1746d4a3d9a794cacae06a5eaaccb4b8643a131d45fbc9af23e353dc0a5ba5c3", size = 1976179, upload-time = "2025-11-04T13:40:23.393Z" }, - { url = "https://files.pythonhosted.org/packages/87/06/8806241ff1f70d9939f9af039c6c35f2360cf16e93c2ca76f184e76b1564/pydantic_core-2.41.5-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:941103c9be18ac8daf7b7adca8228f8ed6bb7a1849020f643b3a14d15b1924d9", size = 2120403, upload-time = "2025-11-04T13:40:25.248Z" }, - { url = "https://files.pythonhosted.org/packages/94/02/abfa0e0bda67faa65fef1c84971c7e45928e108fe24333c81f3bfe35d5f5/pydantic_core-2.41.5-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:112e305c3314f40c93998e567879e887a3160bb8689ef3d2c04b6cc62c33ac34", size = 1896206, upload-time = "2025-11-04T13:40:27.099Z" }, - { url = "https://files.pythonhosted.org/packages/15/df/a4c740c0943e93e6500f9eb23f4ca7ec9bf71b19e608ae5b579678c8d02f/pydantic_core-2.41.5-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0cbaad15cb0c90aa221d43c00e77bb33c93e8d36e0bf74760cd00e732d10a6a0", size = 1919307, upload-time = "2025-11-04T13:40:29.806Z" }, - { url = "https://files.pythonhosted.org/packages/9a/e3/6324802931ae1d123528988e0e86587c2072ac2e5394b4bc2bc34b61ff6e/pydantic_core-2.41.5-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:03ca43e12fab6023fc79d28ca6b39b05f794ad08ec2feccc59a339b02f2b3d33", size = 2063258, upload-time = "2025-11-04T13:40:33.544Z" }, - { url = "https://files.pythonhosted.org/packages/c9/d4/2230d7151d4957dd79c3044ea26346c148c98fbf0ee6ebd41056f2d62ab5/pydantic_core-2.41.5-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:dc799088c08fa04e43144b164feb0c13f9a0bc40503f8df3e9fde58a3c0c101e", size = 2214917, upload-time = "2025-11-04T13:40:35.479Z" }, - { url = "https://files.pythonhosted.org/packages/e6/9f/eaac5df17a3672fef0081b6c1bb0b82b33ee89aa5cec0d7b05f52fd4a1fa/pydantic_core-2.41.5-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:97aeba56665b4c3235a0e52b2c2f5ae9cd071b8a8310ad27bddb3f7fb30e9aa2", size = 2332186, upload-time = "2025-11-04T13:40:37.436Z" }, - { url = "https://files.pythonhosted.org/packages/cf/4e/35a80cae583a37cf15604b44240e45c05e04e86f9cfd766623149297e971/pydantic_core-2.41.5-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:406bf18d345822d6c21366031003612b9c77b3e29ffdb0f612367352aab7d586", size = 2073164, upload-time = "2025-11-04T13:40:40.289Z" }, - { url = "https://files.pythonhosted.org/packages/bf/e3/f6e262673c6140dd3305d144d032f7bd5f7497d3871c1428521f19f9efa2/pydantic_core-2.41.5-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:b93590ae81f7010dbe380cdeab6f515902ebcbefe0b9327cc4804d74e93ae69d", size = 2179146, upload-time = "2025-11-04T13:40:42.809Z" }, - { url = "https://files.pythonhosted.org/packages/75/c7/20bd7fc05f0c6ea2056a4565c6f36f8968c0924f19b7d97bbfea55780e73/pydantic_core-2.41.5-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:01a3d0ab748ee531f4ea6c3e48ad9dac84ddba4b0d82291f87248f2f9de8d740", size = 2137788, upload-time = "2025-11-04T13:40:44.752Z" }, - { url = "https://files.pythonhosted.org/packages/3a/8d/34318ef985c45196e004bc46c6eab2eda437e744c124ef0dbe1ff2c9d06b/pydantic_core-2.41.5-cp313-cp313-musllinux_1_1_armv7l.whl", hash = "sha256:6561e94ba9dacc9c61bce40e2d6bdc3bfaa0259d3ff36ace3b1e6901936d2e3e", size = 2340133, upload-time = "2025-11-04T13:40:46.66Z" }, - { url = "https://files.pythonhosted.org/packages/9c/59/013626bf8c78a5a5d9350d12e7697d3d4de951a75565496abd40ccd46bee/pydantic_core-2.41.5-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:915c3d10f81bec3a74fbd4faebe8391013ba61e5a1a8d48c4455b923bdda7858", size = 2324852, upload-time = "2025-11-04T13:40:48.575Z" }, - { url = "https://files.pythonhosted.org/packages/1a/d9/c248c103856f807ef70c18a4f986693a46a8ffe1602e5d361485da502d20/pydantic_core-2.41.5-cp313-cp313-win32.whl", hash = "sha256:650ae77860b45cfa6e2cdafc42618ceafab3a2d9a3811fcfbd3bbf8ac3c40d36", size = 1994679, upload-time = "2025-11-04T13:40:50.619Z" }, - { url = "https://files.pythonhosted.org/packages/9e/8b/341991b158ddab181cff136acd2552c9f35bd30380422a639c0671e99a91/pydantic_core-2.41.5-cp313-cp313-win_amd64.whl", hash = "sha256:79ec52ec461e99e13791ec6508c722742ad745571f234ea6255bed38c6480f11", size = 2019766, upload-time = "2025-11-04T13:40:52.631Z" }, - { url = "https://files.pythonhosted.org/packages/73/7d/f2f9db34af103bea3e09735bb40b021788a5e834c81eedb541991badf8f5/pydantic_core-2.41.5-cp313-cp313-win_arm64.whl", hash = "sha256:3f84d5c1b4ab906093bdc1ff10484838aca54ef08de4afa9de0f5f14d69639cd", size = 1981005, upload-time = "2025-11-04T13:40:54.734Z" }, - { url = "https://files.pythonhosted.org/packages/ea/28/46b7c5c9635ae96ea0fbb779e271a38129df2550f763937659ee6c5dbc65/pydantic_core-2.41.5-cp314-cp314-macosx_10_12_x86_64.whl", hash = "sha256:3f37a19d7ebcdd20b96485056ba9e8b304e27d9904d233d7b1015db320e51f0a", size = 2119622, upload-time = "2025-11-04T13:40:56.68Z" }, - { url = "https://files.pythonhosted.org/packages/74/1a/145646e5687e8d9a1e8d09acb278c8535ebe9e972e1f162ed338a622f193/pydantic_core-2.41.5-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:1d1d9764366c73f996edd17abb6d9d7649a7eb690006ab6adbda117717099b14", size = 1891725, upload-time = "2025-11-04T13:40:58.807Z" }, - { url = "https://files.pythonhosted.org/packages/23/04/e89c29e267b8060b40dca97bfc64a19b2a3cf99018167ea1677d96368273/pydantic_core-2.41.5-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:25e1c2af0fce638d5f1988b686f3b3ea8cd7de5f244ca147c777769e798a9cd1", size = 1915040, upload-time = "2025-11-04T13:41:00.853Z" }, - { url = "https://files.pythonhosted.org/packages/84/a3/15a82ac7bd97992a82257f777b3583d3e84bdb06ba6858f745daa2ec8a85/pydantic_core-2.41.5-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:506d766a8727beef16b7adaeb8ee6217c64fc813646b424d0804d67c16eddb66", size = 2063691, upload-time = "2025-11-04T13:41:03.504Z" }, - { url = "https://files.pythonhosted.org/packages/74/9b/0046701313c6ef08c0c1cf0e028c67c770a4e1275ca73131563c5f2a310a/pydantic_core-2.41.5-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4819fa52133c9aa3c387b3328f25c1facc356491e6135b459f1de698ff64d869", size = 2213897, upload-time = "2025-11-04T13:41:05.804Z" }, - { url = "https://files.pythonhosted.org/packages/8a/cd/6bac76ecd1b27e75a95ca3a9a559c643b3afcd2dd62086d4b7a32a18b169/pydantic_core-2.41.5-cp314-cp314-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2b761d210c9ea91feda40d25b4efe82a1707da2ef62901466a42492c028553a2", size = 2333302, upload-time = "2025-11-04T13:41:07.809Z" }, - { url = "https://files.pythonhosted.org/packages/4c/d2/ef2074dc020dd6e109611a8be4449b98cd25e1b9b8a303c2f0fca2f2bcf7/pydantic_core-2.41.5-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:22f0fb8c1c583a3b6f24df2470833b40207e907b90c928cc8d3594b76f874375", size = 2064877, upload-time = "2025-11-04T13:41:09.827Z" }, - { url = "https://files.pythonhosted.org/packages/18/66/e9db17a9a763d72f03de903883c057b2592c09509ccfe468187f2a2eef29/pydantic_core-2.41.5-cp314-cp314-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2782c870e99878c634505236d81e5443092fba820f0373997ff75f90f68cd553", size = 2180680, upload-time = "2025-11-04T13:41:12.379Z" }, - { url = "https://files.pythonhosted.org/packages/d3/9e/3ce66cebb929f3ced22be85d4c2399b8e85b622db77dad36b73c5387f8f8/pydantic_core-2.41.5-cp314-cp314-musllinux_1_1_aarch64.whl", hash = "sha256:0177272f88ab8312479336e1d777f6b124537d47f2123f89cb37e0accea97f90", size = 2138960, upload-time = "2025-11-04T13:41:14.627Z" }, - { url = "https://files.pythonhosted.org/packages/a6/62/205a998f4327d2079326b01abee48e502ea739d174f0a89295c481a2272e/pydantic_core-2.41.5-cp314-cp314-musllinux_1_1_armv7l.whl", hash = "sha256:63510af5e38f8955b8ee5687740d6ebf7c2a0886d15a6d65c32814613681bc07", size = 2339102, upload-time = "2025-11-04T13:41:16.868Z" }, - { url = "https://files.pythonhosted.org/packages/3c/0d/f05e79471e889d74d3d88f5bd20d0ed189ad94c2423d81ff8d0000aab4ff/pydantic_core-2.41.5-cp314-cp314-musllinux_1_1_x86_64.whl", hash = "sha256:e56ba91f47764cc14f1daacd723e3e82d1a89d783f0f5afe9c364b8bb491ccdb", size = 2326039, upload-time = "2025-11-04T13:41:18.934Z" }, - { url = "https://files.pythonhosted.org/packages/ec/e1/e08a6208bb100da7e0c4b288eed624a703f4d129bde2da475721a80cab32/pydantic_core-2.41.5-cp314-cp314-win32.whl", hash = "sha256:aec5cf2fd867b4ff45b9959f8b20ea3993fc93e63c7363fe6851424c8a7e7c23", size = 1995126, upload-time = "2025-11-04T13:41:21.418Z" }, - { url = "https://files.pythonhosted.org/packages/48/5d/56ba7b24e9557f99c9237e29f5c09913c81eeb2f3217e40e922353668092/pydantic_core-2.41.5-cp314-cp314-win_amd64.whl", hash = "sha256:8e7c86f27c585ef37c35e56a96363ab8de4e549a95512445b85c96d3e2f7c1bf", size = 2015489, upload-time = "2025-11-04T13:41:24.076Z" }, - { url = "https://files.pythonhosted.org/packages/4e/bb/f7a190991ec9e3e0ba22e4993d8755bbc4a32925c0b5b42775c03e8148f9/pydantic_core-2.41.5-cp314-cp314-win_arm64.whl", hash = "sha256:e672ba74fbc2dc8eea59fb6d4aed6845e6905fc2a8afe93175d94a83ba2a01a0", size = 1977288, upload-time = "2025-11-04T13:41:26.33Z" }, - { url = "https://files.pythonhosted.org/packages/92/ed/77542d0c51538e32e15afe7899d79efce4b81eee631d99850edc2f5e9349/pydantic_core-2.41.5-cp314-cp314t-macosx_10_12_x86_64.whl", hash = "sha256:8566def80554c3faa0e65ac30ab0932b9e3a5cd7f8323764303d468e5c37595a", size = 2120255, upload-time = "2025-11-04T13:41:28.569Z" }, - { url = "https://files.pythonhosted.org/packages/bb/3d/6913dde84d5be21e284439676168b28d8bbba5600d838b9dca99de0fad71/pydantic_core-2.41.5-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:b80aa5095cd3109962a298ce14110ae16b8c1aece8b72f9dafe81cf597ad80b3", size = 1863760, upload-time = "2025-11-04T13:41:31.055Z" }, - { url = "https://files.pythonhosted.org/packages/5a/f0/e5e6b99d4191da102f2b0eb9687aaa7f5bea5d9964071a84effc3e40f997/pydantic_core-2.41.5-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3006c3dd9ba34b0c094c544c6006cc79e87d8612999f1a5d43b769b89181f23c", size = 1878092, upload-time = "2025-11-04T13:41:33.21Z" }, - { url = "https://files.pythonhosted.org/packages/71/48/36fb760642d568925953bcc8116455513d6e34c4beaa37544118c36aba6d/pydantic_core-2.41.5-cp314-cp314t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:72f6c8b11857a856bcfa48c86f5368439f74453563f951e473514579d44aa612", size = 2053385, upload-time = "2025-11-04T13:41:35.508Z" }, - { url = "https://files.pythonhosted.org/packages/20/25/92dc684dd8eb75a234bc1c764b4210cf2646479d54b47bf46061657292a8/pydantic_core-2.41.5-cp314-cp314t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5cb1b2f9742240e4bb26b652a5aeb840aa4b417c7748b6f8387927bc6e45e40d", size = 2218832, upload-time = "2025-11-04T13:41:37.732Z" }, - { url = "https://files.pythonhosted.org/packages/e2/09/f53e0b05023d3e30357d82eb35835d0f6340ca344720a4599cd663dca599/pydantic_core-2.41.5-cp314-cp314t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:bd3d54f38609ff308209bd43acea66061494157703364ae40c951f83ba99a1a9", size = 2327585, upload-time = "2025-11-04T13:41:40Z" }, - { url = "https://files.pythonhosted.org/packages/aa/4e/2ae1aa85d6af35a39b236b1b1641de73f5a6ac4d5a7509f77b814885760c/pydantic_core-2.41.5-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2ff4321e56e879ee8d2a879501c8e469414d948f4aba74a2d4593184eb326660", size = 2041078, upload-time = "2025-11-04T13:41:42.323Z" }, - { url = "https://files.pythonhosted.org/packages/cd/13/2e215f17f0ef326fc72afe94776edb77525142c693767fc347ed6288728d/pydantic_core-2.41.5-cp314-cp314t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d0d2568a8c11bf8225044aa94409e21da0cb09dcdafe9ecd10250b2baad531a9", size = 2173914, upload-time = "2025-11-04T13:41:45.221Z" }, - { url = "https://files.pythonhosted.org/packages/02/7a/f999a6dcbcd0e5660bc348a3991c8915ce6599f4f2c6ac22f01d7a10816c/pydantic_core-2.41.5-cp314-cp314t-musllinux_1_1_aarch64.whl", hash = "sha256:a39455728aabd58ceabb03c90e12f71fd30fa69615760a075b9fec596456ccc3", size = 2129560, upload-time = "2025-11-04T13:41:47.474Z" }, - { url = "https://files.pythonhosted.org/packages/3a/b1/6c990ac65e3b4c079a4fb9f5b05f5b013afa0f4ed6780a3dd236d2cbdc64/pydantic_core-2.41.5-cp314-cp314t-musllinux_1_1_armv7l.whl", hash = "sha256:239edca560d05757817c13dc17c50766136d21f7cd0fac50295499ae24f90fdf", size = 2329244, upload-time = "2025-11-04T13:41:49.992Z" }, - { url = "https://files.pythonhosted.org/packages/d9/02/3c562f3a51afd4d88fff8dffb1771b30cfdfd79befd9883ee094f5b6c0d8/pydantic_core-2.41.5-cp314-cp314t-musllinux_1_1_x86_64.whl", hash = "sha256:2a5e06546e19f24c6a96a129142a75cee553cc018ffee48a460059b1185f4470", size = 2331955, upload-time = "2025-11-04T13:41:54.079Z" }, - { url = "https://files.pythonhosted.org/packages/5c/96/5fb7d8c3c17bc8c62fdb031c47d77a1af698f1d7a406b0f79aaa1338f9ad/pydantic_core-2.41.5-cp314-cp314t-win32.whl", hash = "sha256:b4ececa40ac28afa90871c2cc2b9ffd2ff0bf749380fbdf57d165fd23da353aa", size = 1988906, upload-time = "2025-11-04T13:41:56.606Z" }, - { url = "https://files.pythonhosted.org/packages/22/ed/182129d83032702912c2e2d8bbe33c036f342cc735737064668585dac28f/pydantic_core-2.41.5-cp314-cp314t-win_amd64.whl", hash = "sha256:80aa89cad80b32a912a65332f64a4450ed00966111b6615ca6816153d3585a8c", size = 1981607, upload-time = "2025-11-04T13:41:58.889Z" }, - { url = "https://files.pythonhosted.org/packages/9f/ed/068e41660b832bb0b1aa5b58011dea2a3fe0ba7861ff38c4d4904c1c1a99/pydantic_core-2.41.5-cp314-cp314t-win_arm64.whl", hash = "sha256:35b44f37a3199f771c3eaa53051bc8a70cd7b54f333531c59e29fd4db5d15008", size = 1974769, upload-time = "2025-11-04T13:42:01.186Z" }, - { url = "https://files.pythonhosted.org/packages/11/72/90fda5ee3b97e51c494938a4a44c3a35a9c96c19bba12372fb9c634d6f57/pydantic_core-2.41.5-graalpy311-graalpy242_311_native-macosx_10_12_x86_64.whl", hash = "sha256:b96d5f26b05d03cc60f11a7761a5ded1741da411e7fe0909e27a5e6a0cb7b034", size = 2115441, upload-time = "2025-11-04T13:42:39.557Z" }, - { url = "https://files.pythonhosted.org/packages/1f/53/8942f884fa33f50794f119012dc6a1a02ac43a56407adaac20463df8e98f/pydantic_core-2.41.5-graalpy311-graalpy242_311_native-macosx_11_0_arm64.whl", hash = "sha256:634e8609e89ceecea15e2d61bc9ac3718caaaa71963717bf3c8f38bfde64242c", size = 1930291, upload-time = "2025-11-04T13:42:42.169Z" }, - { url = "https://files.pythonhosted.org/packages/79/c8/ecb9ed9cd942bce09fc888ee960b52654fbdbede4ba6c2d6e0d3b1d8b49c/pydantic_core-2.41.5-graalpy311-graalpy242_311_native-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:93e8740d7503eb008aa2df04d3b9735f845d43ae845e6dcd2be0b55a2da43cd2", size = 1948632, upload-time = "2025-11-04T13:42:44.564Z" }, - { url = "https://files.pythonhosted.org/packages/2e/1b/687711069de7efa6af934e74f601e2a4307365e8fdc404703afc453eab26/pydantic_core-2.41.5-graalpy311-graalpy242_311_native-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f15489ba13d61f670dcc96772e733aad1a6f9c429cc27574c6cdaed82d0146ad", size = 2138905, upload-time = "2025-11-04T13:42:47.156Z" }, - { url = "https://files.pythonhosted.org/packages/09/32/59b0c7e63e277fa7911c2fc70ccfb45ce4b98991e7ef37110663437005af/pydantic_core-2.41.5-graalpy312-graalpy250_312_native-macosx_10_12_x86_64.whl", hash = "sha256:7da7087d756b19037bc2c06edc6c170eeef3c3bafcb8f532ff17d64dc427adfd", size = 2110495, upload-time = "2025-11-04T13:42:49.689Z" }, - { url = "https://files.pythonhosted.org/packages/aa/81/05e400037eaf55ad400bcd318c05bb345b57e708887f07ddb2d20e3f0e98/pydantic_core-2.41.5-graalpy312-graalpy250_312_native-macosx_11_0_arm64.whl", hash = "sha256:aabf5777b5c8ca26f7824cb4a120a740c9588ed58df9b2d196ce92fba42ff8dc", size = 1915388, upload-time = "2025-11-04T13:42:52.215Z" }, - { url = "https://files.pythonhosted.org/packages/6e/0d/e3549b2399f71d56476b77dbf3cf8937cec5cd70536bdc0e374a421d0599/pydantic_core-2.41.5-graalpy312-graalpy250_312_native-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c007fe8a43d43b3969e8469004e9845944f1a80e6acd47c150856bb87f230c56", size = 1942879, upload-time = "2025-11-04T13:42:56.483Z" }, - { url = "https://files.pythonhosted.org/packages/f7/07/34573da085946b6a313d7c42f82f16e8920bfd730665de2d11c0c37a74b5/pydantic_core-2.41.5-graalpy312-graalpy250_312_native-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:76d0819de158cd855d1cbb8fcafdf6f5cf1eb8e470abe056d5d161106e38062b", size = 2139017, upload-time = "2025-11-04T13:42:59.471Z" }, - { url = "https://files.pythonhosted.org/packages/e6/b0/1a2aa41e3b5a4ba11420aba2d091b2d17959c8d1519ece3627c371951e73/pydantic_core-2.41.5-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:b5819cd790dbf0c5eb9f82c73c16b39a65dd6dd4d1439dcdea7816ec9adddab8", size = 2103351, upload-time = "2025-11-04T13:43:02.058Z" }, - { url = "https://files.pythonhosted.org/packages/a4/ee/31b1f0020baaf6d091c87900ae05c6aeae101fa4e188e1613c80e4f1ea31/pydantic_core-2.41.5-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:5a4e67afbc95fa5c34cf27d9089bca7fcab4e51e57278d710320a70b956d1b9a", size = 1925363, upload-time = "2025-11-04T13:43:05.159Z" }, - { url = "https://files.pythonhosted.org/packages/e1/89/ab8e86208467e467a80deaca4e434adac37b10a9d134cd2f99b28a01e483/pydantic_core-2.41.5-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ece5c59f0ce7d001e017643d8d24da587ea1f74f6993467d85ae8a5ef9d4f42b", size = 2135615, upload-time = "2025-11-04T13:43:08.116Z" }, - { url = "https://files.pythonhosted.org/packages/99/0a/99a53d06dd0348b2008f2f30884b34719c323f16c3be4e6cc1203b74a91d/pydantic_core-2.41.5-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:16f80f7abe3351f8ea6858914ddc8c77e02578544a0ebc15b4c2e1a0e813b0b2", size = 2175369, upload-time = "2025-11-04T13:43:12.49Z" }, - { url = "https://files.pythonhosted.org/packages/6d/94/30ca3b73c6d485b9bb0bc66e611cff4a7138ff9736b7e66bcf0852151636/pydantic_core-2.41.5-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:33cb885e759a705b426baada1fe68cbb0a2e68e34c5d0d0289a364cf01709093", size = 2144218, upload-time = "2025-11-04T13:43:15.431Z" }, - { url = "https://files.pythonhosted.org/packages/87/57/31b4f8e12680b739a91f472b5671294236b82586889ef764b5fbc6669238/pydantic_core-2.41.5-pp310-pypy310_pp73-musllinux_1_1_armv7l.whl", hash = "sha256:c8d8b4eb992936023be7dee581270af5c6e0697a8559895f527f5b7105ecd36a", size = 2329951, upload-time = "2025-11-04T13:43:18.062Z" }, - { url = "https://files.pythonhosted.org/packages/7d/73/3c2c8edef77b8f7310e6fb012dbc4b8551386ed575b9eb6fb2506e28a7eb/pydantic_core-2.41.5-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:242a206cd0318f95cd21bdacff3fcc3aab23e79bba5cac3db5a841c9ef9c6963", size = 2318428, upload-time = "2025-11-04T13:43:20.679Z" }, - { url = "https://files.pythonhosted.org/packages/2f/02/8559b1f26ee0d502c74f9cca5c0d2fd97e967e083e006bbbb4e97f3a043a/pydantic_core-2.41.5-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:d3a978c4f57a597908b7e697229d996d77a6d3c94901e9edee593adada95ce1a", size = 2147009, upload-time = "2025-11-04T13:43:23.286Z" }, - { url = "https://files.pythonhosted.org/packages/5f/9b/1b3f0e9f9305839d7e84912f9e8bfbd191ed1b1ef48083609f0dabde978c/pydantic_core-2.41.5-pp311-pypy311_pp73-macosx_10_12_x86_64.whl", hash = "sha256:b2379fa7ed44ddecb5bfe4e48577d752db9fc10be00a6b7446e9663ba143de26", size = 2101980, upload-time = "2025-11-04T13:43:25.97Z" }, - { url = "https://files.pythonhosted.org/packages/a4/ed/d71fefcb4263df0da6a85b5d8a7508360f2f2e9b3bf5814be9c8bccdccc1/pydantic_core-2.41.5-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:266fb4cbf5e3cbd0b53669a6d1b039c45e3ce651fd5442eff4d07c2cc8d66808", size = 1923865, upload-time = "2025-11-04T13:43:28.763Z" }, - { url = "https://files.pythonhosted.org/packages/ce/3a/626b38db460d675f873e4444b4bb030453bbe7b4ba55df821d026a0493c4/pydantic_core-2.41.5-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:58133647260ea01e4d0500089a8c4f07bd7aa6ce109682b1426394988d8aaacc", size = 2134256, upload-time = "2025-11-04T13:43:31.71Z" }, - { url = "https://files.pythonhosted.org/packages/83/d9/8412d7f06f616bbc053d30cb4e5f76786af3221462ad5eee1f202021eb4e/pydantic_core-2.41.5-pp311-pypy311_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:287dad91cfb551c363dc62899a80e9e14da1f0e2b6ebde82c806612ca2a13ef1", size = 2174762, upload-time = "2025-11-04T13:43:34.744Z" }, - { url = "https://files.pythonhosted.org/packages/55/4c/162d906b8e3ba3a99354e20faa1b49a85206c47de97a639510a0e673f5da/pydantic_core-2.41.5-pp311-pypy311_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:03b77d184b9eb40240ae9fd676ca364ce1085f203e1b1256f8ab9984dca80a84", size = 2143141, upload-time = "2025-11-04T13:43:37.701Z" }, - { url = "https://files.pythonhosted.org/packages/1f/f2/f11dd73284122713f5f89fc940f370d035fa8e1e078d446b3313955157fe/pydantic_core-2.41.5-pp311-pypy311_pp73-musllinux_1_1_armv7l.whl", hash = "sha256:a668ce24de96165bb239160b3d854943128f4334822900534f2fe947930e5770", size = 2330317, upload-time = "2025-11-04T13:43:40.406Z" }, - { url = "https://files.pythonhosted.org/packages/88/9d/b06ca6acfe4abb296110fb1273a4d848a0bfb2ff65f3ee92127b3244e16b/pydantic_core-2.41.5-pp311-pypy311_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:f14f8f046c14563f8eb3f45f499cc658ab8d10072961e07225e507adb700e93f", size = 2316992, upload-time = "2025-11-04T13:43:43.602Z" }, - { url = "https://files.pythonhosted.org/packages/36/c7/cfc8e811f061c841d7990b0201912c3556bfeb99cdcb7ed24adc8d6f8704/pydantic_core-2.41.5-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:56121965f7a4dc965bff783d70b907ddf3d57f6eba29b6d2e5dabfaf07799c51", size = 2145302, upload-time = "2025-11-04T13:43:46.64Z" }, +sdist = { url = "https://files.pythonhosted.org/packages/2a/ef/f7abb56c49382a246fd2ce9c799691e3c3e7175ec74b14d99e798bcddb1a/pydantic_core-2.46.3.tar.gz", hash = "sha256:41c178f65b8c29807239d47e6050262eb6bf84eb695e41101e62e38df4a5bc2c", size = 471412, upload-time = "2026-04-20T14:40:56.672Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/22/98/b50eb9a411e87483b5c65dba4fa430a06bac4234d3403a40e5a9905ebcd0/pydantic_core-2.46.3-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:1da3786b8018e60349680720158cc19161cc3b4bdd815beb0a321cd5ce1ad5b1", size = 2108971, upload-time = "2026-04-20T14:43:51.945Z" }, + { url = "https://files.pythonhosted.org/packages/08/4b/f364b9d161718ff2217160a4b5d41ce38de60aed91c3689ebffa1c939d23/pydantic_core-2.46.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:cc0988cb29d21bf4a9d5cf2ef970b5c0e38d8d8e107a493278c05dc6c1dda69f", size = 1949588, upload-time = "2026-04-20T14:44:10.386Z" }, + { url = "https://files.pythonhosted.org/packages/8f/8b/30bd03ee83b2f5e29f5ba8e647ab3c456bf56f2ec72fdbcc0215484a0854/pydantic_core-2.46.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:27f9067c3bfadd04c55484b89c0d267981b2f3512850f6f66e1e74204a4e4ce3", size = 1975986, upload-time = "2026-04-20T14:43:57.106Z" }, + { url = "https://files.pythonhosted.org/packages/3c/54/13ccf954d84ec275d5d023d5786e4aa48840bc9f161f2838dc98e1153518/pydantic_core-2.46.3-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:a642ac886ecf6402d9882d10c405dcf4b902abeb2972cd5fb4a48c83cd59279a", size = 2055830, upload-time = "2026-04-20T14:44:15.499Z" }, + { url = "https://files.pythonhosted.org/packages/be/0e/65f38125e660fdbd72aa858e7dfae893645cfa0e7b13d333e174a367cd23/pydantic_core-2.46.3-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:79f561438481f28681584b89e2effb22855e2179880314bcddbf5968e935e807", size = 2222340, upload-time = "2026-04-20T14:41:51.353Z" }, + { url = "https://files.pythonhosted.org/packages/d1/88/f3ab7739efe0e7e80777dbb84c59eb98518e3f57ea433206194c2e425272/pydantic_core-2.46.3-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:57a973eae4665352a47cf1a99b4ee864620f2fe663a217d7a8da68a1f3a5bfda", size = 2280727, upload-time = "2026-04-20T14:41:30.461Z" }, + { url = "https://files.pythonhosted.org/packages/2a/6d/c228219080817bec4982f9531cadb18da6aaa770fdeb114f49c237ac2c9f/pydantic_core-2.46.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:83d002b97072a53ea150d63e0a3adfae5670cef5aa8a6e490240e482d3b22e57", size = 2092158, upload-time = "2026-04-20T14:44:07.305Z" }, + { url = "https://files.pythonhosted.org/packages/0f/b1/525a16711e7c6d61635fac3b0bd54600b5c5d9f60c6fc5aaab26b64a2297/pydantic_core-2.46.3-cp310-cp310-manylinux_2_31_riscv64.whl", hash = "sha256:b40ddd51e7c44b28cfaef746c9d3c506d658885e0a46f9eeef2ee815cbf8e045", size = 2116626, upload-time = "2026-04-20T14:42:34.118Z" }, + { url = "https://files.pythonhosted.org/packages/ef/7c/17d30673351439a6951bf54f564cf2443ab00ae264ec9df00e2efd710eb5/pydantic_core-2.46.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:ac5ec7fb9b87f04ee839af2d53bcadea57ded7d229719f56c0ed895bff987943", size = 2160691, upload-time = "2026-04-20T14:41:14.023Z" }, + { url = "https://files.pythonhosted.org/packages/86/66/af8adbcbc0886ead7f1a116606a534d75a307e71e6e08226000d51b880d2/pydantic_core-2.46.3-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:a3b11c812f61b3129c4905781a2601dfdfdea5fe1e6c1cfb696b55d14e9c054f", size = 2182543, upload-time = "2026-04-20T14:40:48.886Z" }, + { url = "https://files.pythonhosted.org/packages/b0/37/6de71e0f54c54a4190010f57deb749e1ddf75c568ada3b1320b70067f121/pydantic_core-2.46.3-cp310-cp310-musllinux_1_1_armv7l.whl", hash = "sha256:1108da631e602e5b3c38d6d04fe5bb3bfa54349e6918e3ca6cf570b2e2b2f9d4", size = 2324513, upload-time = "2026-04-20T14:42:36.121Z" }, + { url = "https://files.pythonhosted.org/packages/51/b1/9fc74ce94f603d5ef59ff258ca9c2c8fb902fb548d340a96f77f4d1c3b7f/pydantic_core-2.46.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:de885175515bcfa98ae618c1df7a072f13d179f81376c8007112af20567fd08a", size = 2361853, upload-time = "2026-04-20T14:43:24.886Z" }, + { url = "https://files.pythonhosted.org/packages/40/d0/4c652fc592db35f100279ee751d5a145aca1b9a7984b9684ba7c1b5b0535/pydantic_core-2.46.3-cp310-cp310-win32.whl", hash = "sha256:d11058e3201527d41bc6b545c79187c9e4bf85e15a236a6007f0e991518882b7", size = 1980465, upload-time = "2026-04-20T14:44:46.239Z" }, + { url = "https://files.pythonhosted.org/packages/27/b8/a920453c38afbe1f355e1ea0b0d94a0a3e0b0879d32d793108755fa171d5/pydantic_core-2.46.3-cp310-cp310-win_amd64.whl", hash = "sha256:3612edf65c8ea67ac13616c4d23af12faef1ae435a8a93e5934c2a0cbbdd1fd6", size = 2073884, upload-time = "2026-04-20T14:43:01.201Z" }, + { url = "https://files.pythonhosted.org/packages/22/a2/1ba90a83e85a3f94c796b184f3efde9c72f2830dcda493eea8d59ba78e6d/pydantic_core-2.46.3-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:ab124d49d0459b2373ecf54118a45c28a1e6d4192a533fbc915e70f556feb8e5", size = 2106740, upload-time = "2026-04-20T14:41:20.932Z" }, + { url = "https://files.pythonhosted.org/packages/b6/f6/99ae893c89a0b9d3daec9f95487aa676709aa83f67643b3f0abaf4ab628a/pydantic_core-2.46.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:cca67d52a5c7a16aed2b3999e719c4bcf644074eac304a5d3d62dd70ae7d4b2c", size = 1948293, upload-time = "2026-04-20T14:43:42.115Z" }, + { url = "https://files.pythonhosted.org/packages/3e/b8/2e8e636dc9e3f16c2e16bf0849e24be82c5ee82c603c65fc0326666328fc/pydantic_core-2.46.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5c024e08c0ba23e6fd68c771a521e9d6a792f2ebb0fa734296b36394dc30390e", size = 1973222, upload-time = "2026-04-20T14:41:57.841Z" }, + { url = "https://files.pythonhosted.org/packages/34/36/0e730beec4d83c5306f417afbd82ff237d9a21e83c5edf675f31ed84c1fe/pydantic_core-2.46.3-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:6645ce7eec4928e29a1e3b3d5c946621d105d3e79f0c9cddf07c2a9770949287", size = 2053852, upload-time = "2026-04-20T14:40:43.077Z" }, + { url = "https://files.pythonhosted.org/packages/4b/f0/3071131f47e39136a17814576e0fada9168569f7f8c0e6ac4d1ede6a4958/pydantic_core-2.46.3-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a712c7118e6c5ea96562f7b488435172abb94a3c53c22c9efc1412264a45cbbe", size = 2221134, upload-time = "2026-04-20T14:43:03.349Z" }, + { url = "https://files.pythonhosted.org/packages/2f/a9/a2dc023eec5aa4b02a467874bad32e2446957d2adcab14e107eab502e978/pydantic_core-2.46.3-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:69a868ef3ff206343579021c40faf3b1edc64b1cc508ff243a28b0a514ccb050", size = 2279785, upload-time = "2026-04-20T14:41:19.285Z" }, + { url = "https://files.pythonhosted.org/packages/0a/44/93f489d16fb63fbd41c670441536541f6e8cfa1e5a69f40bc9c5d30d8c90/pydantic_core-2.46.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cc7e8c32db809aa0f6ea1d6869ebc8518a65d5150fdfad8bcae6a49ae32a22e2", size = 2089404, upload-time = "2026-04-20T14:43:10.108Z" }, + { url = "https://files.pythonhosted.org/packages/2a/78/8692e3aa72b2d004f7a5d937f1dfdc8552ba26caf0bec75f342c40f00dec/pydantic_core-2.46.3-cp311-cp311-manylinux_2_31_riscv64.whl", hash = "sha256:3481bd1341dc85779ee506bc8e1196a277ace359d89d28588a9468c3ecbe63fa", size = 2114898, upload-time = "2026-04-20T14:44:51.475Z" }, + { url = "https://files.pythonhosted.org/packages/6a/62/e83133f2e7832532060175cebf1f13748f4c7e7e7165cdd1f611f174494b/pydantic_core-2.46.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:8690eba565c6d68ffd3a8655525cbdd5246510b44a637ee2c6c03a7ebfe64d3c", size = 2157856, upload-time = "2026-04-20T14:43:46.64Z" }, + { url = "https://files.pythonhosted.org/packages/6d/ec/6a500e3ad7718ee50583fae79c8651f5d37e3abce1fa9ae177ae65842c53/pydantic_core-2.46.3-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:4de88889d7e88d50d40ee5b39d5dac0bcaef9ba91f7e536ac064e6b2834ecccf", size = 2180168, upload-time = "2026-04-20T14:42:00.302Z" }, + { url = "https://files.pythonhosted.org/packages/d8/53/8267811054b1aa7fc1dc7ded93812372ef79a839f5e23558136a6afbfde1/pydantic_core-2.46.3-cp311-cp311-musllinux_1_1_armv7l.whl", hash = "sha256:e480080975c1ef7f780b8f99ed72337e7cc5efea2e518a20a692e8e7b278eb8b", size = 2322885, upload-time = "2026-04-20T14:41:05.253Z" }, + { url = "https://files.pythonhosted.org/packages/c8/c1/1c0acdb3aa0856ddc4ecc55214578f896f2de16f400cf51627eb3c26c1c4/pydantic_core-2.46.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:de3a5c376f8cd94da9a1b8fd3dd1c16c7a7b216ed31dc8ce9fd7a22bf13b836e", size = 2360328, upload-time = "2026-04-20T14:41:43.991Z" }, + { url = "https://files.pythonhosted.org/packages/f0/d0/ef39cd0f4a926814f360e71c1adeab48ad214d9727e4deb48eedfb5bce1a/pydantic_core-2.46.3-cp311-cp311-win32.whl", hash = "sha256:fc331a5314ffddd5385b9ee9d0d2fee0b13c27e0e02dad71b1ae5d6561f51eeb", size = 1979464, upload-time = "2026-04-20T14:43:12.215Z" }, + { url = "https://files.pythonhosted.org/packages/18/9c/f41951b0d858e343f1cf09398b2a7b3014013799744f2c4a8ad6a3eec4f2/pydantic_core-2.46.3-cp311-cp311-win_amd64.whl", hash = "sha256:b5b9c6cf08a8a5e502698f5e153056d12c34b8fb30317e0c5fd06f45162a6346", size = 2070837, upload-time = "2026-04-20T14:41:47.707Z" }, + { url = "https://files.pythonhosted.org/packages/9f/1e/264a17cd582f6ed50950d4d03dd5fefd84e570e238afe1cb3e25cf238769/pydantic_core-2.46.3-cp311-cp311-win_arm64.whl", hash = "sha256:5dfd51cf457482f04ec49491811a2b8fd5b843b64b11eecd2d7a1ee596ea78a6", size = 2053647, upload-time = "2026-04-20T14:42:27.535Z" }, + { url = "https://files.pythonhosted.org/packages/4b/cb/5b47425556ecc1f3fe18ed2a0083188aa46e1dd812b06e406475b3a5d536/pydantic_core-2.46.3-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:b11b59b3eee90a80a36701ddb4576d9ae31f93f05cb9e277ceaa09e6bf074a67", size = 2101946, upload-time = "2026-04-20T14:40:52.581Z" }, + { url = "https://files.pythonhosted.org/packages/a1/4f/2fb62c2267cae99b815bbf4a7b9283812c88ca3153ef29f7707200f1d4e5/pydantic_core-2.46.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:af8653713055ea18a3abc1537fe2ebc42f5b0bbb768d1eb79fd74eb47c0ac089", size = 1951612, upload-time = "2026-04-20T14:42:42.996Z" }, + { url = "https://files.pythonhosted.org/packages/50/6e/b7348fd30d6556d132cddd5bd79f37f96f2601fe0608afac4f5fb01ec0b3/pydantic_core-2.46.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:75a519dab6d63c514f3a81053e5266c549679e4aa88f6ec57f2b7b854aceb1b0", size = 1977027, upload-time = "2026-04-20T14:42:02.001Z" }, + { url = "https://files.pythonhosted.org/packages/82/11/31d60ee2b45540d3fb0b29302a393dbc01cd771c473f5b5147bcd353e593/pydantic_core-2.46.3-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:a6cd87cb1575b1ad05ba98894c5b5c96411ef678fa2f6ed2576607095b8d9789", size = 2063008, upload-time = "2026-04-20T14:44:17.952Z" }, + { url = "https://files.pythonhosted.org/packages/8a/db/3a9d1957181b59258f44a2300ab0f0be9d1e12d662a4f57bb31250455c52/pydantic_core-2.46.3-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f80a55484b8d843c8ada81ebf70a682f3f00a3d40e378c06cf17ecb44d280d7d", size = 2233082, upload-time = "2026-04-20T14:40:57.934Z" }, + { url = "https://files.pythonhosted.org/packages/9c/e1/3277c38792aeb5cfb18c2f0c5785a221d9ff4e149abbe1184d53d5f72273/pydantic_core-2.46.3-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3861f1731b90c50a3266316b9044f5c9b405eecb8e299b0a7120596334e4fe9c", size = 2304615, upload-time = "2026-04-20T14:42:12.584Z" }, + { url = "https://files.pythonhosted.org/packages/5e/d5/e3d9717c9eba10855325650afd2a9cba8e607321697f18953af9d562da2f/pydantic_core-2.46.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fb528e295ed31570ac3dcc9bfdd6e0150bc11ce6168ac87a8082055cf1a67395", size = 2094380, upload-time = "2026-04-20T14:43:05.522Z" }, + { url = "https://files.pythonhosted.org/packages/a1/20/abac35dedcbfd66c6f0b03e4e3564511771d6c9b7ede10a362d03e110d9b/pydantic_core-2.46.3-cp312-cp312-manylinux_2_31_riscv64.whl", hash = "sha256:367508faa4973b992b271ba1494acaab36eb7e8739d1e47be5035fb1ea225396", size = 2135429, upload-time = "2026-04-20T14:41:55.549Z" }, + { url = "https://files.pythonhosted.org/packages/6c/a5/41bfd1df69afad71b5cf0535055bccc73022715ad362edbc124bc1e021d7/pydantic_core-2.46.3-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:5ad3c826fe523e4becf4fe39baa44286cff85ef137c729a2c5e269afbfd0905d", size = 2174582, upload-time = "2026-04-20T14:41:45.96Z" }, + { url = "https://files.pythonhosted.org/packages/79/65/38d86ea056b29b2b10734eb23329b7a7672ca604df4f2b6e9c02d4ee22fe/pydantic_core-2.46.3-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:ec638c5d194ef8af27db69f16c954a09797c0dc25015ad6123eb2c73a4d271ca", size = 2187533, upload-time = "2026-04-20T14:40:55.367Z" }, + { url = "https://files.pythonhosted.org/packages/b6/55/a1129141678a2026badc539ad1dee0a71d06f54c2f06a4bd68c030ac781b/pydantic_core-2.46.3-cp312-cp312-musllinux_1_1_armv7l.whl", hash = "sha256:28ed528c45446062ee66edb1d33df5d88828ae167de76e773a3c7f64bd14e976", size = 2332985, upload-time = "2026-04-20T14:44:13.05Z" }, + { url = "https://files.pythonhosted.org/packages/d7/60/cb26f4077719f709e54819f4e8e1d43f4091f94e285eb6bd21e1190a7b7c/pydantic_core-2.46.3-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:aed19d0c783886d5bd86d80ae5030006b45e28464218747dcf83dabfdd092c7b", size = 2373670, upload-time = "2026-04-20T14:41:53.421Z" }, + { url = "https://files.pythonhosted.org/packages/6b/7e/c3f21882bdf1d8d086876f81b5e296206c69c6082551d776895de7801fa0/pydantic_core-2.46.3-cp312-cp312-win32.whl", hash = "sha256:06d5d8820cbbdb4147578c1fe7ffcd5b83f34508cb9f9ab76e807be7db6ff0a4", size = 1966722, upload-time = "2026-04-20T14:44:30.588Z" }, + { url = "https://files.pythonhosted.org/packages/57/be/6b5e757b859013ebfbd7adba02f23b428f37c86dcbf78b5bb0b4ffd36e99/pydantic_core-2.46.3-cp312-cp312-win_amd64.whl", hash = "sha256:c3212fda0ee959c1dd04c60b601ec31097aaa893573a3a1abd0a47bcac2968c1", size = 2072970, upload-time = "2026-04-20T14:42:54.248Z" }, + { url = "https://files.pythonhosted.org/packages/bf/f8/a989b21cc75e9a32d24192ef700eea606521221a89faa40c919ce884f2b1/pydantic_core-2.46.3-cp312-cp312-win_arm64.whl", hash = "sha256:f1f8338dd7a7f31761f1f1a3c47503a9a3b34eea3c8b01fa6ee96408affb5e72", size = 2035963, upload-time = "2026-04-20T14:44:20.4Z" }, + { url = "https://files.pythonhosted.org/packages/9b/3c/9b5e8eb9821936d065439c3b0fb1490ffa64163bfe7e1595985a47896073/pydantic_core-2.46.3-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:12bc98de041458b80c86c56b24df1d23832f3e166cbaff011f25d187f5c62c37", size = 2102109, upload-time = "2026-04-20T14:41:24.219Z" }, + { url = "https://files.pythonhosted.org/packages/91/97/1c41d1f5a19f241d8069f1e249853bcce378cdb76eec8ab636d7bc426280/pydantic_core-2.46.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:85348b8f89d2c3508b65b16c3c33a4da22b8215138d8b996912bb1532868885f", size = 1951820, upload-time = "2026-04-20T14:42:14.236Z" }, + { url = "https://files.pythonhosted.org/packages/30/b4/d03a7ae14571bc2b6b3c7b122441154720619afe9a336fa3a95434df5e2f/pydantic_core-2.46.3-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1105677a6df914b1fb71a81b96c8cce7726857e1717d86001f29be06a25ee6f8", size = 1977785, upload-time = "2026-04-20T14:42:31.648Z" }, + { url = "https://files.pythonhosted.org/packages/ae/0c/4086f808834b59e3c8f1aa26df8f4b6d998cdcf354a143d18ef41529d1fe/pydantic_core-2.46.3-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:87082cd65669a33adeba5470769e9704c7cf026cc30afb9cc77fd865578ebaad", size = 2062761, upload-time = "2026-04-20T14:40:37.093Z" }, + { url = "https://files.pythonhosted.org/packages/fa/71/a649be5a5064c2df0db06e0a512c2281134ed2fcc981f52a657936a7527c/pydantic_core-2.46.3-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:60e5f66e12c4f5212d08522963380eaaeac5ebd795826cfd19b2dfb0c7a52b9c", size = 2232989, upload-time = "2026-04-20T14:42:59.254Z" }, + { url = "https://files.pythonhosted.org/packages/a2/84/7756e75763e810b3a710f4724441d1ecc5883b94aacb07ca71c5fb5cfb69/pydantic_core-2.46.3-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b6cdf19bf84128d5e7c37e8a73a0c5c10d51103a650ac585d42dd6ae233f2b7f", size = 2303975, upload-time = "2026-04-20T14:41:32.287Z" }, + { url = "https://files.pythonhosted.org/packages/6c/35/68a762e0c1e31f35fa0dac733cbd9f5b118042853698de9509c8e5bf128b/pydantic_core-2.46.3-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:031bb17f4885a43773c8c763089499f242aee2ea85cf17154168775dccdecf35", size = 2095325, upload-time = "2026-04-20T14:42:47.685Z" }, + { url = "https://files.pythonhosted.org/packages/77/bf/1bf8c9a8e91836c926eae5e3e51dce009bf495a60ca56060689d3df3f340/pydantic_core-2.46.3-cp313-cp313-manylinux_2_31_riscv64.whl", hash = "sha256:bcf2a8b2982a6673693eae7348ef3d8cf3979c1d63b54fca7c397a635cc68687", size = 2133368, upload-time = "2026-04-20T14:41:22.766Z" }, + { url = "https://files.pythonhosted.org/packages/e5/50/87d818d6bab915984995157ceb2380f5aac4e563dddbed6b56f0ed057aba/pydantic_core-2.46.3-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:28e8cf2f52d72ced402a137145923a762cbb5081e48b34312f7a0c8f55928ec3", size = 2173908, upload-time = "2026-04-20T14:42:52.044Z" }, + { url = "https://files.pythonhosted.org/packages/91/88/a311fb306d0bd6185db41fa14ae888fb81d0baf648a761ae760d30819d33/pydantic_core-2.46.3-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:17eaface65d9fc5abb940003020309c1bf7a211f5f608d7870297c367e6f9022", size = 2186422, upload-time = "2026-04-20T14:43:29.55Z" }, + { url = "https://files.pythonhosted.org/packages/8f/79/28fd0d81508525ab2054fef7c77a638c8b5b0afcbbaeee493cf7c3fef7e1/pydantic_core-2.46.3-cp313-cp313-musllinux_1_1_armv7l.whl", hash = "sha256:93fd339f23408a07e98950a89644f92c54d8729719a40b30c0a30bb9ebc55d23", size = 2332709, upload-time = "2026-04-20T14:42:16.134Z" }, + { url = "https://files.pythonhosted.org/packages/b3/21/795bf5fe5c0f379308b8ef19c50dedab2e7711dbc8d0c2acf08f1c7daa05/pydantic_core-2.46.3-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:23cbdb3aaa74dfe0837975dbf69b469753bbde8eacace524519ffdb6b6e89eb7", size = 2372428, upload-time = "2026-04-20T14:41:10.974Z" }, + { url = "https://files.pythonhosted.org/packages/45/b3/ed14c659cbe7605e3ef063077680a64680aec81eb1a04763a05190d49b7f/pydantic_core-2.46.3-cp313-cp313-win32.whl", hash = "sha256:610eda2e3838f401105e6326ca304f5da1e15393ae25dacae5c5c63f2c275b13", size = 1965601, upload-time = "2026-04-20T14:41:42.128Z" }, + { url = "https://files.pythonhosted.org/packages/ef/bb/adb70d9a762ddd002d723fbf1bd492244d37da41e3af7b74ad212609027e/pydantic_core-2.46.3-cp313-cp313-win_amd64.whl", hash = "sha256:68cc7866ed863db34351294187f9b729964c371ba33e31c26f478471c52e1ed0", size = 2071517, upload-time = "2026-04-20T14:43:36.096Z" }, + { url = "https://files.pythonhosted.org/packages/52/eb/66faefabebfe68bd7788339c9c9127231e680b11906368c67ce112fdb47f/pydantic_core-2.46.3-cp313-cp313-win_arm64.whl", hash = "sha256:f64b5537ac62b231572879cd08ec05600308636a5d63bcbdb15063a466977bec", size = 2035802, upload-time = "2026-04-20T14:43:38.507Z" }, + { url = "https://files.pythonhosted.org/packages/7f/db/a7bcb4940183fda36022cd18ba8dd12f2dff40740ec7b58ce7457befa416/pydantic_core-2.46.3-cp314-cp314-macosx_10_12_x86_64.whl", hash = "sha256:afa3aa644f74e290cdede48a7b0bee37d1c35e71b05105f6b340d484af536d9b", size = 2097614, upload-time = "2026-04-20T14:44:38.374Z" }, + { url = "https://files.pythonhosted.org/packages/24/35/e4066358a22e3e99519db370494c7528f5a2aa1367370e80e27e20283543/pydantic_core-2.46.3-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:ced3310e51aa425f7f77da8bbbb5212616655bedbe82c70944320bc1dbe5e018", size = 1951896, upload-time = "2026-04-20T14:40:53.996Z" }, + { url = "https://files.pythonhosted.org/packages/87/92/37cf4049d1636996e4b888c05a501f40a43ff218983a551d57f9d5e14f0d/pydantic_core-2.46.3-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e29908922ce9da1a30b4da490bd1d3d82c01dcfdf864d2a74aacee674d0bfa34", size = 1979314, upload-time = "2026-04-20T14:41:49.446Z" }, + { url = "https://files.pythonhosted.org/packages/d8/36/9ff4d676dfbdfb2d591cf43f3d90ded01e15b1404fd101180ed2d62a2fd3/pydantic_core-2.46.3-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:0c9ff69140423eea8ed2d5477df3ba037f671f5e897d206d921bc9fdc39613e7", size = 2056133, upload-time = "2026-04-20T14:42:23.574Z" }, + { url = "https://files.pythonhosted.org/packages/bc/f0/405b442a4d7ba855b06eec8b2bf9c617d43b8432d099dfdc7bf999293495/pydantic_core-2.46.3-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b675ab0a0d5b1c8fdb81195dc5bcefea3f3c240871cdd7ff9a2de8aa50772eb2", size = 2228726, upload-time = "2026-04-20T14:44:22.816Z" }, + { url = "https://files.pythonhosted.org/packages/e7/f8/65cd92dd5a0bd89ba277a98ecbfaf6fc36bbd3300973c7a4b826d6ab1391/pydantic_core-2.46.3-cp314-cp314-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0087084960f209a9a4af50ecd1fb063d9ad3658c07bb81a7a53f452dacbfb2ba", size = 2301214, upload-time = "2026-04-20T14:44:48.792Z" }, + { url = "https://files.pythonhosted.org/packages/fd/86/ef96a4c6e79e7a2d0410826a68fbc0eccc0fd44aa733be199d5fcac3bb87/pydantic_core-2.46.3-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ed42e6cc8e1b0e2b9b96e2276bad70ae625d10d6d524aed0c93de974ae029f9f", size = 2099927, upload-time = "2026-04-20T14:41:40.196Z" }, + { url = "https://files.pythonhosted.org/packages/6d/53/269caf30e0096e0a8a8f929d1982a27b3879872cca2d917d17c2f9fdf4fe/pydantic_core-2.46.3-cp314-cp314-manylinux_2_31_riscv64.whl", hash = "sha256:f1771ce258afb3e4201e67d154edbbae712a76a6081079fe247c2f53c6322c22", size = 2128789, upload-time = "2026-04-20T14:41:15.868Z" }, + { url = "https://files.pythonhosted.org/packages/00/b0/1a6d9b6a587e118482910c244a1c5acf4d192604174132efd12bf0ac486f/pydantic_core-2.46.3-cp314-cp314-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:a7610b6a5242a6c736d8ad47fd5fff87fcfe8f833b281b1c409c3d6835d9227f", size = 2173815, upload-time = "2026-04-20T14:44:25.152Z" }, + { url = "https://files.pythonhosted.org/packages/87/56/e7e00d4041a7e62b5a40815590114db3b535bf3ca0bf4dca9f16cef25246/pydantic_core-2.46.3-cp314-cp314-musllinux_1_1_aarch64.whl", hash = "sha256:ff5e7783bcc5476e1db448bf268f11cb257b1c276d3e89f00b5727be86dd0127", size = 2181608, upload-time = "2026-04-20T14:41:28.933Z" }, + { url = "https://files.pythonhosted.org/packages/e8/22/4bd23c3d41f7c185d60808a1de83c76cf5aeabf792f6c636a55c3b1ec7f9/pydantic_core-2.46.3-cp314-cp314-musllinux_1_1_armv7l.whl", hash = "sha256:9d2e32edcc143bc01e95300671915d9ca052d4f745aa0a49c48d4803f8a85f2c", size = 2326968, upload-time = "2026-04-20T14:42:03.962Z" }, + { url = "https://files.pythonhosted.org/packages/24/ac/66cd45129e3915e5ade3b292cb3bc7fd537f58f8f8dbdaba6170f7cabb74/pydantic_core-2.46.3-cp314-cp314-musllinux_1_1_x86_64.whl", hash = "sha256:6e42d83d1c6b87fa56b521479cff237e626a292f3b31b6345c15a99121b454c1", size = 2369842, upload-time = "2026-04-20T14:41:35.52Z" }, + { url = "https://files.pythonhosted.org/packages/a2/51/dd4248abb84113615473aa20d5545b7c4cd73c8644003b5259686f93996c/pydantic_core-2.46.3-cp314-cp314-win32.whl", hash = "sha256:07bc6d2a28c3adb4f7c6ae46aa4f2d2929af127f587ed44057af50bf1ce0f505", size = 1959661, upload-time = "2026-04-20T14:41:00.042Z" }, + { url = "https://files.pythonhosted.org/packages/20/eb/59980e5f1ae54a3b86372bd9f0fa373ea2d402e8cdcd3459334430f91e91/pydantic_core-2.46.3-cp314-cp314-win_amd64.whl", hash = "sha256:8940562319bc621da30714617e6a7eaa6b98c84e8c685bcdc02d7ed5e7c7c44e", size = 2071686, upload-time = "2026-04-20T14:43:16.471Z" }, + { url = "https://files.pythonhosted.org/packages/8c/db/1cf77e5247047dfee34bc01fa9bca134854f528c8eb053e144298893d370/pydantic_core-2.46.3-cp314-cp314-win_arm64.whl", hash = "sha256:5dcbbcf4d22210ced8f837c96db941bdb078f419543472aca5d9a0bb7cddc7df", size = 2026907, upload-time = "2026-04-20T14:43:31.732Z" }, + { url = "https://files.pythonhosted.org/packages/57/c0/b3df9f6a543276eadba0a48487b082ca1f201745329d97dbfa287034a230/pydantic_core-2.46.3-cp314-cp314t-macosx_10_12_x86_64.whl", hash = "sha256:d0fe3dce1e836e418f912c1ad91c73357d03e556a4d286f441bf34fed2dbeecf", size = 2095047, upload-time = "2026-04-20T14:42:37.982Z" }, + { url = "https://files.pythonhosted.org/packages/66/57/886a938073b97556c168fd99e1a7305bb363cd30a6d2c76086bf0587b32a/pydantic_core-2.46.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:9ce92e58abc722dac1bf835a6798a60b294e48eb0e625ec9fd994b932ac5feee", size = 1934329, upload-time = "2026-04-20T14:43:49.655Z" }, + { url = "https://files.pythonhosted.org/packages/0b/7c/b42eaa5c34b13b07ecb51da21761297a9b8eb43044c864a035999998f328/pydantic_core-2.46.3-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a03e6467f0f5ab796a486146d1b887b2dc5e5f9b3288898c1b1c3ad974e53e4a", size = 1974847, upload-time = "2026-04-20T14:42:10.737Z" }, + { url = "https://files.pythonhosted.org/packages/e6/9b/92b42db6543e7de4f99ae977101a2967b63122d4b6cf7773812da2d7d5b5/pydantic_core-2.46.3-cp314-cp314t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:2798b6ba041b9d70acfb9071a2ea13c8456dd1e6a5555798e41ba7b0790e329c", size = 2041742, upload-time = "2026-04-20T14:40:44.262Z" }, + { url = "https://files.pythonhosted.org/packages/0f/19/46fbe1efabb5aa2834b43b9454e70f9a83ad9c338c1291e48bdc4fecf167/pydantic_core-2.46.3-cp314-cp314t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9be3e221bdc6d69abf294dcf7aff6af19c31a5cdcc8f0aa3b14be29df4bd03b1", size = 2236235, upload-time = "2026-04-20T14:41:27.307Z" }, + { url = "https://files.pythonhosted.org/packages/77/da/b3f95bc009ad60ec53120f5d16c6faa8cabdbe8a20d83849a1f2b8728148/pydantic_core-2.46.3-cp314-cp314t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f13936129ce841f2a5ddf6f126fea3c43cd128807b5a59588c37cf10178c2e64", size = 2282633, upload-time = "2026-04-20T14:44:33.271Z" }, + { url = "https://files.pythonhosted.org/packages/cc/6e/401336117722e28f32fb8220df676769d28ebdf08f2f4469646d404c43a3/pydantic_core-2.46.3-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:28b5f2ef03416facccb1c6ef744c69793175fd27e44ef15669201601cf423acb", size = 2109679, upload-time = "2026-04-20T14:44:41.065Z" }, + { url = "https://files.pythonhosted.org/packages/fc/53/b289f9bc8756a32fe718c46f55afaeaf8d489ee18d1a1e7be1db73f42cc4/pydantic_core-2.46.3-cp314-cp314t-manylinux_2_31_riscv64.whl", hash = "sha256:830d1247d77ad23852314f069e9d7ddafeec5f684baf9d7e7065ed46a049c4e6", size = 2108342, upload-time = "2026-04-20T14:42:50.144Z" }, + { url = "https://files.pythonhosted.org/packages/10/5b/8292fc7c1f9111f1b2b7c1b0dcf1179edcd014fc3ea4517499f50b829d71/pydantic_core-2.46.3-cp314-cp314t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d0793c90c1a3c74966e7975eaef3ed30ebdff3260a0f815a62a22adc17e4c01c", size = 2157208, upload-time = "2026-04-20T14:42:08.133Z" }, + { url = "https://files.pythonhosted.org/packages/2b/9e/f80044e9ec07580f057a89fc131f78dda7a58751ddf52bbe05eaf31db50f/pydantic_core-2.46.3-cp314-cp314t-musllinux_1_1_aarch64.whl", hash = "sha256:d2d0aead851b66f5245ec0c4fb2612ef457f8bbafefdf65a2bf9d6bac6140f47", size = 2167237, upload-time = "2026-04-20T14:42:25.412Z" }, + { url = "https://files.pythonhosted.org/packages/f8/84/6781a1b037f3b96be9227edbd1101f6d3946746056231bf4ac48cdff1a8d/pydantic_core-2.46.3-cp314-cp314t-musllinux_1_1_armv7l.whl", hash = "sha256:2f40e4246676beb31c5ce77c38a55ca4e465c6b38d11ea1bd935420568e0b1ab", size = 2312540, upload-time = "2026-04-20T14:40:40.313Z" }, + { url = "https://files.pythonhosted.org/packages/3e/db/19c0839feeb728e7df03255581f198dfdf1c2aeb1e174a8420b63c5252e5/pydantic_core-2.46.3-cp314-cp314t-musllinux_1_1_x86_64.whl", hash = "sha256:cf489cf8986c543939aeee17a09c04d6ffb43bfef8ca16fcbcc5cfdcbed24dba", size = 2369556, upload-time = "2026-04-20T14:41:09.427Z" }, + { url = "https://files.pythonhosted.org/packages/e0/15/3228774cb7cd45f5f721ddf1b2242747f4eb834d0c491f0c02d606f09fed/pydantic_core-2.46.3-cp314-cp314t-win32.whl", hash = "sha256:ffe0883b56cfc05798bf994164d2b2ff03efe2d22022a2bb080f3b626176dd56", size = 1949756, upload-time = "2026-04-20T14:41:25.717Z" }, + { url = "https://files.pythonhosted.org/packages/b8/2a/c79cf53fd91e5a87e30d481809f52f9a60dd221e39de66455cf04deaad37/pydantic_core-2.46.3-cp314-cp314t-win_amd64.whl", hash = "sha256:706d9d0ce9cf4593d07270d8e9f53b161f90c57d315aeec4fb4fd7a8b10240d8", size = 2051305, upload-time = "2026-04-20T14:43:18.627Z" }, + { url = "https://files.pythonhosted.org/packages/0b/db/d8182a7f1d9343a032265aae186eb063fe26ca4c40f256b21e8da4498e89/pydantic_core-2.46.3-cp314-cp314t-win_arm64.whl", hash = "sha256:77706aeb41df6a76568434701e0917da10692da28cb69d5fb6919ce5fdb07374", size = 2026310, upload-time = "2026-04-20T14:41:01.778Z" }, + { url = "https://files.pythonhosted.org/packages/66/7f/03dbad45cd3aa9083fbc93c210ae8b005af67e4136a14186950a747c6874/pydantic_core-2.46.3-graalpy311-graalpy242_311_native-macosx_10_12_x86_64.whl", hash = "sha256:9715525891ed524a0a1eb6d053c74d4d4ad5017677fb00af0b7c2644a31bae46", size = 2105683, upload-time = "2026-04-20T14:42:19.779Z" }, + { url = "https://files.pythonhosted.org/packages/26/22/4dc186ac8ea6b257e9855031f51b62a9637beac4d68ac06bee02f046f836/pydantic_core-2.46.3-graalpy311-graalpy242_311_native-macosx_11_0_arm64.whl", hash = "sha256:9d2f400712a99a013aff420ef1eb9be077f8189a36c1e3ef87660b4e1088a874", size = 1940052, upload-time = "2026-04-20T14:43:59.274Z" }, + { url = "https://files.pythonhosted.org/packages/0d/ca/d376391a5aff1f2e8188960d7873543608130a870961c2b6b5236627c116/pydantic_core-2.46.3-graalpy311-graalpy242_311_native-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bd2aab0e2e9dc2daf36bd2686c982535d5e7b1d930a1344a7bb6e82baab42a76", size = 1988172, upload-time = "2026-04-20T14:41:17.469Z" }, + { url = "https://files.pythonhosted.org/packages/0e/6b/523b9f85c23788755d6ab949329de692a2e3a584bc6beb67fef5e035aa9d/pydantic_core-2.46.3-graalpy311-graalpy242_311_native-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4e9d76736da5f362fabfeea6a69b13b7f2be405c6d6966f06b2f6bfff7e64531", size = 2128596, upload-time = "2026-04-20T14:40:41.707Z" }, + { url = "https://files.pythonhosted.org/packages/34/42/f426db557e8ab2791bc7562052299944a118655496fbff99914e564c0a94/pydantic_core-2.46.3-graalpy312-graalpy250_312_native-macosx_10_12_x86_64.whl", hash = "sha256:b12dd51f1187c2eb489af8e20f880362db98e954b54ab792fa5d92e8bcc6b803", size = 2091877, upload-time = "2026-04-20T14:43:27.091Z" }, + { url = "https://files.pythonhosted.org/packages/5c/4f/86a832a9d14df58e663bfdf4627dc00d3317c2bd583c4fb23390b0f04b8e/pydantic_core-2.46.3-graalpy312-graalpy250_312_native-macosx_11_0_arm64.whl", hash = "sha256:f00a0961b125f1a47af7bcc17f00782e12f4cd056f83416006b30111d941dfa3", size = 1932428, upload-time = "2026-04-20T14:40:45.781Z" }, + { url = "https://files.pythonhosted.org/packages/11/1a/fe857968954d93fb78e0d4b6df5c988c74c4aaa67181c60be7cfe327c0ca/pydantic_core-2.46.3-graalpy312-graalpy250_312_native-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:57697d7c056aca4bbb680200f96563e841a6386ac1129370a0102592f4dddff5", size = 1997550, upload-time = "2026-04-20T14:44:02.425Z" }, + { url = "https://files.pythonhosted.org/packages/17/eb/9d89ad2d9b0ba8cd65393d434471621b98912abb10fbe1df08e480ba57b5/pydantic_core-2.46.3-graalpy312-graalpy250_312_native-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fd35aa21299def8db7ef4fe5c4ff862941a9a158ca7b63d61e66fe67d30416b4", size = 2137657, upload-time = "2026-04-20T14:42:45.149Z" }, + { url = "https://files.pythonhosted.org/packages/1f/da/99d40830684f81dec901cac521b5b91c095394cc1084b9433393cde1c2df/pydantic_core-2.46.3-pp311-pypy311_pp73-macosx_10_12_x86_64.whl", hash = "sha256:13afdd885f3d71280cf286b13b310ee0f7ccfefd1dbbb661514a474b726e2f25", size = 2107973, upload-time = "2026-04-20T14:42:06.175Z" }, + { url = "https://files.pythonhosted.org/packages/99/a5/87024121818d75bbb2a98ddbaf638e40e7a18b5e0f5492c9ca4b1b316107/pydantic_core-2.46.3-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:f91c0aff3e3ee0928edd1232c57f643a7a003e6edf1860bc3afcdc749cb513f3", size = 1947191, upload-time = "2026-04-20T14:43:14.319Z" }, + { url = "https://files.pythonhosted.org/packages/60/62/0c1acfe10945b83a6a59d19fbaa92f48825381509e5701b855c08f13db76/pydantic_core-2.46.3-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6529d1d128321a58d30afcc97b49e98836542f68dd41b33c2e972bb9e5290536", size = 2123791, upload-time = "2026-04-20T14:43:22.766Z" }, + { url = "https://files.pythonhosted.org/packages/75/3e/3b2393b4c8f44285561dc30b00cf307a56a2eff7c483a824db3b8221ca51/pydantic_core-2.46.3-pp311-pypy311_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:975c267cff4f7e7272eacbe50f6cc03ca9a3da4c4fbd66fffd89c94c1e311aa1", size = 2153197, upload-time = "2026-04-20T14:44:27.932Z" }, + { url = "https://files.pythonhosted.org/packages/ba/75/5af02fb35505051eee727c061f2881c555ab4f8ddb2d42da715a42c9731b/pydantic_core-2.46.3-pp311-pypy311_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:2b8e4f2bbdf71415c544b4b1138b8060db7b6611bc927e8064c769f64bed651c", size = 2181073, upload-time = "2026-04-20T14:43:20.729Z" }, + { url = "https://files.pythonhosted.org/packages/10/92/7e0e1bd9ca3c68305db037560ca2876f89b2647deb2f8b6319005de37505/pydantic_core-2.46.3-pp311-pypy311_pp73-musllinux_1_1_armv7l.whl", hash = "sha256:e61ea8e9fff9606d09178f577ff8ccdd7206ff73d6552bcec18e1033c4254b85", size = 2315886, upload-time = "2026-04-20T14:44:04.826Z" }, + { url = "https://files.pythonhosted.org/packages/b8/d8/101655f27eaf3e44558ead736b2795d12500598beed4683f279396fa186e/pydantic_core-2.46.3-pp311-pypy311_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:b504bda01bafc69b6d3c7a0c7f039dcf60f47fab70e06fe23f57b5c75bdc82b8", size = 2360528, upload-time = "2026-04-20T14:40:47.431Z" }, + { url = "https://files.pythonhosted.org/packages/07/0f/1c34a74c8d07136f0d729ffe5e1fdab04fbdaa7684f61a92f92511a84a15/pydantic_core-2.46.3-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:b00b76f7142fc60c762ce579bd29c8fa44aaa56592dd3c54fab3928d0d4ca6ff", size = 2184144, upload-time = "2026-04-20T14:42:57Z" }, ] [[package]] name = "pydantic-settings" -version = "2.13.1" +version = "2.14.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "pydantic" }, { name = "python-dotenv" }, { name = "typing-inspection" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/52/6d/fffca34caecc4a3f97bda81b2098da5e8ab7efc9a66e819074a11955d87e/pydantic_settings-2.13.1.tar.gz", hash = "sha256:b4c11847b15237fb0171e1462bf540e294affb9b86db4d9aa5c01730bdbe4025", size = 223826, upload-time = "2026-02-19T13:45:08.055Z" } +sdist = { url = "https://files.pythonhosted.org/packages/42/98/c8345dccdc31de4228c039a98f6467a941e39558da41c1744fbe29fa5666/pydantic_settings-2.14.0.tar.gz", hash = "sha256:24285fd4b0e0c06507dd9fdfd331ee23794305352aaec8fc4eb92d4047aeb67d", size = 235709, upload-time = "2026-04-20T13:37:40.293Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/00/4b/ccc026168948fec4f7555b9164c724cf4125eac006e176541483d2c959be/pydantic_settings-2.13.1-py3-none-any.whl", hash = "sha256:d56fd801823dbeae7f0975e1f8c8e25c258eb75d278ea7abb5d9cebb01b56237", size = 58929, upload-time = "2026-02-19T13:45:06.034Z" }, + { url = "https://files.pythonhosted.org/packages/01/dd/bebff3040138f00ae8a102d426b27349b9a49acc310fcae7f92112d867e3/pydantic_settings-2.14.0-py3-none-any.whl", hash = "sha256:fc8d5d692eb7092e43c8647c1c35a3ecd00e040fcf02ed86f4cb5458ca62182e", size = 60940, upload-time = "2026-04-20T13:37:38.586Z" }, ] [[package]] @@ -4362,7 +4365,7 @@ wheels = [ [[package]] name = "pytest" -version = "7.4.4" +version = "9.0.3" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "colorama", marker = "sys_platform == 'win32'" }, @@ -4370,11 +4373,12 @@ dependencies = [ { name = "iniconfig" }, { name = "packaging" }, { name = "pluggy" }, + { name = "pygments" }, { name = "tomli", marker = "python_full_version < '3.11'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/80/1f/9d8e98e4133ffb16c90f3b405c43e38d3abb715bb5d7a63a5a684f7e46a3/pytest-7.4.4.tar.gz", hash = "sha256:2cf0005922c6ace4a3e2ec8b4080eb0d9753fdc93107415332f50ce9e7994280", size = 1357116, upload-time = "2023-12-31T12:00:18.035Z" } +sdist = { url = "https://files.pythonhosted.org/packages/7d/0d/549bd94f1a0a402dc8cf64563a117c0f3765662e2e668477624baeec44d5/pytest-9.0.3.tar.gz", hash = "sha256:b86ada508af81d19edeb213c681b1d48246c1a91d304c6c81a427674c17eb91c", size = 1572165, upload-time = "2026-04-07T17:16:18.027Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/51/ff/f6e8b8f39e08547faece4bd80f89d5a8de68a38b2d179cc1c4490ffa3286/pytest-7.4.4-py3-none-any.whl", hash = "sha256:b090cdf5ed60bf4c45261be03239c2c1c22df034fbffe691abe93cd80cea01d8", size = 325287, upload-time = "2023-12-31T12:00:13.963Z" }, + { url = "https://files.pythonhosted.org/packages/d4/24/a372aaf5c9b7208e7112038812994107bc65a84cd00e0354a88c2c77a617/pytest-9.0.3-py3-none-any.whl", hash = "sha256:2c5efc453d45394fdd706ade797c0a81091eccd1d6e4bccfcd476e2b8e0ab5d9", size = 375249, upload-time = "2026-04-07T17:16:16.13Z" }, ] [[package]] @@ -4477,11 +4481,11 @@ wheels = [ [[package]] name = "python-multipart" -version = "0.0.24" +version = "0.0.26" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/8a/45/e23b5dc14ddb9918ae4a625379506b17b6f8fc56ca1d82db62462f59aea6/python_multipart-0.0.24.tar.gz", hash = "sha256:9574c97e1c026e00bc30340ef7c7d76739512ab4dfd428fec8c330fa6a5cc3c8", size = 37695, upload-time = "2026-04-05T20:49:13.829Z" } +sdist = { url = "https://files.pythonhosted.org/packages/88/71/b145a380824a960ebd60e1014256dbb7d2253f2316ff2d73dfd8928ec2c3/python_multipart-0.0.26.tar.gz", hash = "sha256:08fadc45918cd615e26846437f50c5d6d23304da32c341f289a617127b081f17", size = 43501, upload-time = "2026-04-10T14:09:59.473Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/a3/73/89930efabd4da63cea44a3f438aeb753d600123570e6d6264e763617a9ce/python_multipart-0.0.24-py3-none-any.whl", hash = "sha256:9b110a98db707df01a53c194f0af075e736a770dc5058089650d70b4a182f950", size = 24420, upload-time = "2026-04-05T20:49:12.555Z" }, + { url = "https://files.pythonhosted.org/packages/9a/22/f1925cdda983ab66fc8ec6ec8014b959262747e58bdca26a4e3d1da29d56/python_multipart-0.0.26-py3-none-any.whl", hash = "sha256:c0b169f8c4484c13b0dcf2ef0ec3a4adb255c4b7d18d8e420477d2b1dd03f185", size = 28847, upload-time = "2026-04-10T14:09:58.131Z" }, ] [[package]] @@ -4792,15 +4796,15 @@ wheels = [ [[package]] name = "rich" -version = "14.3.3" +version = "15.0.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "markdown-it-py" }, { name = "pygments" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/b3/c6/f3b320c27991c46f43ee9d856302c70dc2d0fb2dba4842ff739d5f46b393/rich-14.3.3.tar.gz", hash = "sha256:b8daa0b9e4eef54dd8cf7c86c03713f53241884e814f4e2f5fb342fe520f639b", size = 230582, upload-time = "2026-02-19T17:23:12.474Z" } +sdist = { url = "https://files.pythonhosted.org/packages/c0/8f/0722ca900cc807c13a6a0c696dacf35430f72e0ec571c4275d2371fca3e9/rich-15.0.0.tar.gz", hash = "sha256:edd07a4824c6b40189fb7ac9bc4c52536e9780fbbfbddf6f1e2502c31b068c36", size = 230680, upload-time = "2026-04-12T08:24:00.75Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/14/25/b208c5683343959b670dc001595f2f3737e051da617f66c31f7c4fa93abc/rich-14.3.3-py3-none-any.whl", hash = "sha256:793431c1f8619afa7d3b52b2cdec859562b950ea0d4b6b505397612db8d5362d", size = 310458, upload-time = "2026-02-19T17:23:13.732Z" }, + { url = "https://files.pythonhosted.org/packages/82/3b/64d4899d73f91ba49a8c18a8ff3f0ea8f1c1d75481760df8c68ef5235bf5/rich-15.0.0-py3-none-any.whl", hash = "sha256:33bd4ef74232fb73fe9279a257718407f169c09b78a87ad3d296f548e27de0bb", size = 310654, upload-time = "2026-04-12T08:24:02.83Z" }, ] [[package]] @@ -5261,7 +5265,7 @@ dev = [ { name = "grpcio-tools", specifier = ">=1.48.2,<2" }, { name = "httpx", specifier = ">=0.28.1" }, { name = "langgraph", specifier = ">=1.1.0" }, - { name = "langsmith", specifier = ">=0.7.0,<0.8" }, + { name = "langsmith", specifier = ">=0.7.0,<0.7.34" }, { name = "litellm", specifier = ">=1.83.0" }, { name = "maturin", specifier = ">=1.8.2" }, { name = "moto", extras = ["s3", "server"], specifier = ">=5" }, @@ -5278,7 +5282,7 @@ dev = [ { name = "pydocstyle", specifier = ">=6.3.0,<7" }, { name = "pydoctor", specifier = ">=25.10.1,<26" }, { name = "pyright", specifier = "==1.1.403" }, - { name = "pytest", specifier = "~=7.4" }, + { name = "pytest", specifier = "~=9.0" }, { name = "pytest-asyncio", specifier = ">=0.21,<0.22" }, { name = "pytest-cov", specifier = ">=6.1.1" }, { name = "pytest-pretty", specifier = ">=1.3.0" }, @@ -5506,7 +5510,7 @@ wheels = [ [[package]] name = "typer" -version = "0.24.1" +version = "0.24.2" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "annotated-doc" }, @@ -5514,9 +5518,9 @@ dependencies = [ { name = "rich" }, { name = "shellingham" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/f5/24/cb09efec5cc954f7f9b930bf8279447d24618bb6758d4f6adf2574c41780/typer-0.24.1.tar.gz", hash = "sha256:e39b4732d65fbdcde189ae76cf7cd48aeae72919dea1fdfc16593be016256b45", size = 118613, upload-time = "2026-02-21T16:54:40.609Z" } +sdist = { url = "https://files.pythonhosted.org/packages/83/b8/9ebb531b6c2d377af08ac6746a5df3425b21853a5d2260876919b58a2a4a/typer-0.24.2.tar.gz", hash = "sha256:ec070dcfca1408e85ee203c6365001e818c3b7fffe686fd07ff2d68095ca0480", size = 119849, upload-time = "2026-04-22T17:45:34.413Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/4a/91/48db081e7a63bb37284f9fbcefda7c44c277b18b0e13fbc36ea2335b71e6/typer-0.24.1-py3-none-any.whl", hash = "sha256:112c1f0ce578bfb4cab9ffdabc68f031416ebcc216536611ba21f04e9aa84c9e", size = 56085, upload-time = "2026-02-21T16:54:41.616Z" }, + { url = "https://files.pythonhosted.org/packages/39/d1/9484b497e0a0410b901c12b8251c3e746e1e863f7d28419ffe06f7892fda/typer-0.24.2-py3-none-any.whl", hash = "sha256:b618bc3d721f9a8d30f3e05565be26416d06e9bcc29d49bc491dc26aba674fa8", size = 55977, upload-time = "2026-04-22T17:45:33.055Z" }, ] [[package]] @@ -5541,15 +5545,15 @@ s3 = [ [[package]] name = "types-aiobotocore" -version = "3.3.0" +version = "3.5.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "botocore-stubs" }, { name = "typing-extensions", marker = "python_full_version < '3.12'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/e7/93/e22753dc6b941093f19f0bfe87af5424e00310eaf52dd7d0d8306a6fe094/types_aiobotocore-3.3.0.tar.gz", hash = "sha256:c754c2888631d56c370cab4d2108da2bfd3afe80049303fb7132004ead3b21d6", size = 86908, upload-time = "2026-03-19T02:35:49.176Z" } +sdist = { url = "https://files.pythonhosted.org/packages/d5/99/3863acdc373aa621cf56634bb08145fb54f2213e647d893c1ac7b2636c11/types_aiobotocore-3.5.0.tar.gz", hash = "sha256:8636c9e5a9837d41e45264570349d98c0cdad51fe7961ee19664a11094bb2262", size = 87983, upload-time = "2026-04-23T02:57:02.576Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/97/c7/53a786a82bde6307fd79059357c1d2f510667019d78dd71d8787c49bec7f/types_aiobotocore-3.3.0-py3-none-any.whl", hash = "sha256:017e9666d5cba2c26134256ad5e4efb320a68352358b9f3257b4e2aae3fb4c18", size = 54364, upload-time = "2026-03-19T02:35:45.567Z" }, + { url = "https://files.pythonhosted.org/packages/ed/d7/2b2d4d5b64b81149b08cc3fde6e826788c703c012b687cd4cc4d83742afd/types_aiobotocore-3.5.0-py3-none-any.whl", hash = "sha256:7c75ff73c10098d1d885e5b061f05945afdc4e9d0d5b573274292c329abe8a62", size = 54805, upload-time = "2026-04-23T02:56:59.721Z" }, ] [[package]] @@ -5584,14 +5588,14 @@ wheels = [ [[package]] name = "types-requests" -version = "2.33.0.20260402" +version = "2.33.0.20260408" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "urllib3" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/c1/7b/a06527d20af1441d813360b8e0ce152a75b7d8e4aab7c7d0a156f405d7ec/types_requests-2.33.0.20260402.tar.gz", hash = "sha256:1bdd3ada9b869741c5c4b887d2c8b4e38284a1449751823b5ebbccba3eefd9da", size = 23851, upload-time = "2026-04-02T04:19:55.942Z" } +sdist = { url = "https://files.pythonhosted.org/packages/69/6a/749dc53a54a3f35842c1f8197b3ca6b54af6d7458a1bfc75f6629b6da666/types_requests-2.33.0.20260408.tar.gz", hash = "sha256:95b9a86376807a216b2fb412b47617b202091c3ea7c078f47cc358d5528ccb7b", size = 23882, upload-time = "2026-04-08T04:34:49.33Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/51/65/3853bb6bac5ae789dc7e28781154705c27859eccc8e46282c3f36780f5f5/types_requests-2.33.0.20260402-py3-none-any.whl", hash = "sha256:c98372d7124dd5d10af815ee25c013897592ff92af27b27e22c98984102c3254", size = 20739, upload-time = "2026-04-02T04:19:54.955Z" }, + { url = "https://files.pythonhosted.org/packages/90/b8/78fd6c037de4788c040fdd323b3369804400351b7827473920f6c1d03c10/types_requests-2.33.0.20260408-py3-none-any.whl", hash = "sha256:81f31d5ea4acb39f03be7bc8bed569ba6d5a9c5d97e89f45ac43d819b68ca50f", size = 20739, upload-time = "2026-04-08T04:34:48.325Z" }, ] [[package]] @@ -5694,16 +5698,16 @@ wheels = [ [[package]] name = "uvicorn" -version = "0.44.0" +version = "0.46.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "click" }, { name = "h11" }, { name = "typing-extensions", marker = "python_full_version < '3.11'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/5e/da/6eee1ff8b6cbeed47eeb5229749168e81eb4b7b999a1a15a7176e51410c9/uvicorn-0.44.0.tar.gz", hash = "sha256:6c942071b68f07e178264b9152f1f16dfac5da85880c4ce06366a96d70d4f31e", size = 86947, upload-time = "2026-04-06T09:23:22.826Z" } +sdist = { url = "https://files.pythonhosted.org/packages/1f/93/041fca8274050e40e6791f267d82e0e2e27dd165627bd640d3e0e378d877/uvicorn-0.46.0.tar.gz", hash = "sha256:fb9da0926999cc6cb22dc7cd71a94a632f078e6ae47ff683c5c420750fb7413d", size = 88758, upload-time = "2026-04-23T07:16:00.151Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/b7/23/a5bbd9600dd607411fa644c06ff4951bec3a4d82c4b852374024359c19c0/uvicorn-0.44.0-py3-none-any.whl", hash = "sha256:ce937c99a2cc70279556967274414c087888e8cec9f9c94644dfca11bd3ced89", size = 69425, upload-time = "2026-04-06T09:23:21.524Z" }, + { url = "https://files.pythonhosted.org/packages/31/a3/5b1562db76a5a488274b2332a97199b32d0442aca0ed193697fd47786316/uvicorn-0.46.0-py3-none-any.whl", hash = "sha256:bbebbcbed972d162afca128605223022bedd345b7bc7855ce66deb31487a9048", size = 70926, upload-time = "2026-04-23T07:15:58.355Z" }, ] [[package]] @@ -6147,49 +6151,49 @@ wheels = [ [[package]] name = "zipp" -version = "3.23.0" +version = "3.23.1" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/e3/02/0f2892c661036d50ede074e376733dca2ae7c6eb617489437771209d4180/zipp-3.23.0.tar.gz", hash = "sha256:a07157588a12518c9d4034df3fbbee09c814741a33ff63c05fa29d26a2404166", size = 25547, upload-time = "2025-06-08T17:06:39.4Z" } +sdist = { url = "https://files.pythonhosted.org/packages/30/21/093488dfc7cc8964ded15ab726fad40f25fd3d788fd741cc1c5a17d78ee8/zipp-3.23.1.tar.gz", hash = "sha256:32120e378d32cd9714ad503c1d024619063ec28aad2248dc6672ad13edfa5110", size = 25965, upload-time = "2026-04-13T23:21:46.6Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/2e/54/647ade08bf0db230bfea292f893923872fd20be6ac6f53b2b936ba839d75/zipp-3.23.0-py3-none-any.whl", hash = "sha256:071652d6115ed432f5ce1d34c336c0adfd6a884660d1e9712a256d3d3bd4b14e", size = 10276, upload-time = "2025-06-08T17:06:38.034Z" }, + { url = "https://files.pythonhosted.org/packages/08/8a/0861bec20485572fbddf3dfba2910e38fe249796cb73ecdeb74e07eeb8d3/zipp-3.23.1-py3-none-any.whl", hash = "sha256:0b3596c50a5c700c9cb40ba8d86d9f2cc4807e9bedb06bcdf7fac85633e444dc", size = 10378, upload-time = "2026-04-13T23:21:45.386Z" }, ] [[package]] name = "zope-interface" -version = "8.2" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/86/a4/77daa5ba398996d16bb43fc721599d27d03eae68fe3c799de1963c72e228/zope_interface-8.2.tar.gz", hash = "sha256:afb20c371a601d261b4f6edb53c3c418c249db1a9717b0baafc9a9bb39ba1224", size = 254019, upload-time = "2026-01-09T07:51:07.253Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/b1/fa/6d9eb3a33998a3019d7eb4fa1802d01d6602fad90e0aea443e6e0fe8e49a/zope_interface-8.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:788c293f3165964ec6527b2d861072c68eef53425213f36d3893ebee89a89623", size = 207541, upload-time = "2026-01-09T08:04:55.378Z" }, - { url = "https://files.pythonhosted.org/packages/19/8c/ad23c96fdee84cb1f768f6695dac187cc26e9038e01c69713ba0f7dc46ab/zope_interface-8.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9a4e785097e741a1c953b3970ce28f2823bd63c00adc5d276f2981dd66c96c15", size = 208075, upload-time = "2026-01-09T08:04:57.118Z" }, - { url = "https://files.pythonhosted.org/packages/dd/35/1bfd5fec31a307f0cf4065ee74ade63858ded3e2a71e248f1508118fcc95/zope_interface-8.2-cp310-cp310-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:16c69da19a06566664ddd4785f37cad5693a51d48df1515d264c20d005d322e2", size = 249528, upload-time = "2026-01-09T08:04:59.074Z" }, - { url = "https://files.pythonhosted.org/packages/c6/3a/5d50b5fdb0f8226a2edff6adb7efdd3762ec95dff827dbab1761cb9a9e85/zope_interface-8.2-cp310-cp310-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:c31acfa3d7cde48bec45701b0e1f4698daffc378f559bfb296837d8c834732f6", size = 254646, upload-time = "2026-01-09T08:05:00.964Z" }, - { url = "https://files.pythonhosted.org/packages/2f/2a/ee7d675e151578eaf77828b8faac2b7ed9a69fead350bf5cf0e4afe7c73d/zope_interface-8.2-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:0723507127f8269b8f3f22663168f717e9c9742107d1b6c9f419df561b71aa6d", size = 255083, upload-time = "2026-01-09T08:05:02.857Z" }, - { url = "https://files.pythonhosted.org/packages/5d/07/99e2342f976c3700e142eddc01524e375a9e9078869a6885d9c72f3a3659/zope_interface-8.2-cp310-cp310-win_amd64.whl", hash = "sha256:3bf73a910bb27344def2d301a03329c559a79b308e1e584686b74171d736be4e", size = 211924, upload-time = "2026-01-09T08:05:04.702Z" }, - { url = "https://files.pythonhosted.org/packages/98/97/9c2aa8caae79915ed64eb114e18816f178984c917aa9adf2a18345e4f2e5/zope_interface-8.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c65ade7ea85516e428651048489f5e689e695c79188761de8c622594d1e13322", size = 208081, upload-time = "2026-01-09T08:05:06.623Z" }, - { url = "https://files.pythonhosted.org/packages/34/86/4e2fcb01a8f6780ac84923748e450af0805531f47c0956b83065c99ab543/zope_interface-8.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:a1ef4b43659e1348f35f38e7d1a6bbc1682efde239761f335ffc7e31e798b65b", size = 208522, upload-time = "2026-01-09T08:05:07.986Z" }, - { url = "https://files.pythonhosted.org/packages/f6/eb/08e277da32ddcd4014922854096cf6dcb7081fad415892c2da1bedefbf02/zope_interface-8.2-cp311-cp311-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:dfc4f44e8de2ff4eba20af4f0a3ca42d3c43ab24a08e49ccd8558b7a4185b466", size = 255198, upload-time = "2026-01-09T08:05:09.532Z" }, - { url = "https://files.pythonhosted.org/packages/ea/a1/b32484f3281a5dc83bc713ad61eca52c543735cdf204543172087a074a74/zope_interface-8.2-cp311-cp311-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:8f094bfb49179ec5dc9981cb769af1275702bd64720ef94874d9e34da1390d4c", size = 259970, upload-time = "2026-01-09T08:05:11.477Z" }, - { url = "https://files.pythonhosted.org/packages/f6/81/bca0e8ae1e487d4093a8a7cfed2118aa2d4758c8cfd66e59d2af09d71f1c/zope_interface-8.2-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:d2bb8e7364e18f083bf6744ccf30433b2a5f236c39c95df8514e3c13007098ce", size = 261153, upload-time = "2026-01-09T08:05:13.402Z" }, - { url = "https://files.pythonhosted.org/packages/40/1e/e3ff2a708011e56b10b271b038d4cb650a8ad5b7d24352fe2edf6d6b187a/zope_interface-8.2-cp311-cp311-win_amd64.whl", hash = "sha256:6f4b4dfcfdfaa9177a600bb31cebf711fdb8c8e9ed84f14c61c420c6aa398489", size = 212330, upload-time = "2026-01-09T08:05:15.267Z" }, - { url = "https://files.pythonhosted.org/packages/e0/a0/1e1fabbd2e9c53ef92b69df6d14f4adc94ec25583b1380336905dc37e9a0/zope_interface-8.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:624b6787fc7c3e45fa401984f6add2c736b70a7506518c3b537ffaacc4b29d4c", size = 208785, upload-time = "2026-01-09T08:05:17.348Z" }, - { url = "https://files.pythonhosted.org/packages/c3/2a/88d098a06975c722a192ef1fb7d623d1b57c6a6997cf01a7aabb45ab1970/zope_interface-8.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:bc9ded9e97a0ed17731d479596ed1071e53b18e6fdb2fc33af1e43f5fd2d3aaa", size = 208976, upload-time = "2026-01-09T08:05:18.792Z" }, - { url = "https://files.pythonhosted.org/packages/e9/e8/757398549fdfd2f8c89f32c82ae4d2f0537ae2a5d2f21f4a2f711f5a059f/zope_interface-8.2-cp312-cp312-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:532367553e4420c80c0fc0cabcc2c74080d495573706f66723edee6eae53361d", size = 259411, upload-time = "2026-01-09T08:05:20.567Z" }, - { url = "https://files.pythonhosted.org/packages/91/af/502601f0395ce84dff622f63cab47488657a04d0065547df42bee3a680ff/zope_interface-8.2-cp312-cp312-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:2bf9cf275468bafa3c72688aad8cfcbe3d28ee792baf0b228a1b2d93bd1d541a", size = 264859, upload-time = "2026-01-09T08:05:22.234Z" }, - { url = "https://files.pythonhosted.org/packages/89/0c/d2f765b9b4814a368a7c1b0ac23b68823c6789a732112668072fe596945d/zope_interface-8.2-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:0009d2d3c02ea783045d7804da4fd016245e5c5de31a86cebba66dd6914d59a2", size = 264398, upload-time = "2026-01-09T08:05:23.853Z" }, - { url = "https://files.pythonhosted.org/packages/4a/81/2f171fbc4222066957e6b9220c4fb9146792540102c37e6d94e5d14aad97/zope_interface-8.2-cp312-cp312-win_amd64.whl", hash = "sha256:845d14e580220ae4544bd4d7eb800f0b6034fe5585fc2536806e0a26c2ee6640", size = 212444, upload-time = "2026-01-09T08:05:25.148Z" }, - { url = "https://files.pythonhosted.org/packages/66/47/45188fb101fa060b20e6090e500682398ab415e516a0c228fbb22bc7def2/zope_interface-8.2-cp313-cp313-macosx_10_9_x86_64.whl", hash = "sha256:6068322004a0158c80dfd4708dfb103a899635408c67c3b10e9acec4dbacefec", size = 209170, upload-time = "2026-01-09T08:05:26.616Z" }, - { url = "https://files.pythonhosted.org/packages/09/03/f6b9336c03c2b48403c4eb73a1ec961d94dc2fb5354c583dfb5fa05fd41f/zope_interface-8.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:2499de92e8275d0dd68f84425b3e19e9268cd1fa8507997900fa4175f157733c", size = 209229, upload-time = "2026-01-09T08:05:28.521Z" }, - { url = "https://files.pythonhosted.org/packages/07/b1/65fe1dca708569f302ade02e6cdca309eab6752bc9f80105514f5b708651/zope_interface-8.2-cp313-cp313-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:f777e68c76208503609c83ca021a6864902b646530a1a39abb9ed310d1100664", size = 259393, upload-time = "2026-01-09T08:05:29.897Z" }, - { url = "https://files.pythonhosted.org/packages/eb/a5/97b49cfceb6ed53d3dcfb3f3ebf24d83b5553194f0337fbbb3a9fec6cf78/zope_interface-8.2-cp313-cp313-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:9b05a919fdb0ed6ea942e5a7800e09a8b6cdae6f98fee1bef1c9d1a3fc43aaa0", size = 264863, upload-time = "2026-01-09T08:05:31.501Z" }, - { url = "https://files.pythonhosted.org/packages/cb/02/0b7a77292810efe3a0586a505b077ebafd5114e10c6e6e659f0c8e387e1f/zope_interface-8.2-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:ccc62b5712dd7bd64cfba3ee63089fb11e840f5914b990033beeae3b2180b6cb", size = 264369, upload-time = "2026-01-09T08:05:32.941Z" }, - { url = "https://files.pythonhosted.org/packages/fb/1d/0d1ff3846302ed1b5bbf659316d8084b30106770a5f346b7ff4e9f540f80/zope_interface-8.2-cp313-cp313-win_amd64.whl", hash = "sha256:34f877d1d3bb7565c494ed93828fa6417641ca26faf6e8f044e0d0d500807028", size = 212447, upload-time = "2026-01-09T08:05:35.064Z" }, - { url = "https://files.pythonhosted.org/packages/1a/da/3c89de3917751446728b8898b4d53318bc2f8f6bf8196e150a063c59905e/zope_interface-8.2-cp314-cp314-macosx_10_9_x86_64.whl", hash = "sha256:46c7e4e8cbc698398a67e56ca985d19cb92365b4aafbeb6a712e8c101090f4cb", size = 209223, upload-time = "2026-01-09T08:05:36.449Z" }, - { url = "https://files.pythonhosted.org/packages/00/7f/62d00ec53f0a6e5df0c984781e6f3999ed265129c4c3413df8128d1e0207/zope_interface-8.2-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:a87fc7517f825a97ff4a4ca4c8a950593c59e0f8e7bfe1b6f898a38d5ba9f9cf", size = 209366, upload-time = "2026-01-09T08:05:38.197Z" }, - { url = "https://files.pythonhosted.org/packages/ef/a2/f241986315174be8e00aabecfc2153cf8029c1327cab8ed53a9d979d7e08/zope_interface-8.2-cp314-cp314-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:ccf52f7d44d669203c2096c1a0c2c15d52e36b2e7a9413df50f48392c7d4d080", size = 261037, upload-time = "2026-01-09T08:05:39.568Z" }, - { url = "https://files.pythonhosted.org/packages/02/cc/b321c51d6936ede296a1b8860cf173bee2928357fe1fff7f97234899173f/zope_interface-8.2-cp314-cp314-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:aae807efc7bd26302eb2fea05cd6de7d59269ed6ae23a6de1ee47add6de99b8c", size = 264219, upload-time = "2026-01-09T08:05:41.624Z" }, - { url = "https://files.pythonhosted.org/packages/ab/fb/5f5e7b40a2f4efd873fe173624795ca47eaa22e29051270c981361b45209/zope_interface-8.2-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:05a0e42d6d830f547e114de2e7cd15750dc6c0c78f8138e6c5035e51ddfff37c", size = 264390, upload-time = "2026-01-09T08:05:42.936Z" }, - { url = "https://files.pythonhosted.org/packages/f9/82/3f2bc594370bc3abd58e5f9085d263bf682a222f059ed46275cde0570810/zope_interface-8.2-cp314-cp314-win_amd64.whl", hash = "sha256:561ce42390bee90bae51cf1c012902a8033b2aaefbd0deed81e877562a116d48", size = 212585, upload-time = "2026-01-09T08:05:44.419Z" }, +version = "8.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/c9/04/0b1d92e7d31507c5fbe203d9cc1ae80fb0645688c7af751ea0ec18c2223e/zope_interface-8.3.tar.gz", hash = "sha256:e1a9de7d0b5b5c249a73b91aebf4598ce05e334303af6aa94865893283e9ff10", size = 256822, upload-time = "2026-04-10T06:12:35.036Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/5e/47/791e8da00c00332d4db7f9add22cb102c523e452ea0449bb63eb7dcc3c17/zope_interface-8.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:c8a2f9c4ee0f2ad4817e9481684993d33b66d9b815f9157a716a189af483bc34", size = 210367, upload-time = "2026-04-10T06:21:50.304Z" }, + { url = "https://files.pythonhosted.org/packages/8b/d5/92bad86cb429af22f59f6e08227c58c74a3d8395a64a5ca61b9301fc6171/zope_interface-8.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:99c84e12efe0e17f03c6bb5a8ea18fb2841e6666ee0b8331d5967fec84337884", size = 210726, upload-time = "2026-04-10T06:21:52.375Z" }, + { url = "https://files.pythonhosted.org/packages/cb/55/ddf1aeb3e4d5f7a343599a76dafc0766ec42b32112bfedc37f7ddeff753f/zope_interface-8.3-cp310-cp310-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:a918f8e73c35a1352a4b49db67b90b37d33fb7651c834def3f0e3784437bb3a8", size = 254046, upload-time = "2026-04-10T06:21:54.332Z" }, + { url = "https://files.pythonhosted.org/packages/b6/4f/a52a78b389c79d85d3d4afbf71b2984bd4a8a682beec248cdc21576b13a6/zope_interface-8.3-cp310-cp310-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:5a5b50d0dcdb4200f1936f75b6688bd86de5c14c5d20bed2e004300a04521826", size = 258910, upload-time = "2026-04-10T06:21:56.588Z" }, + { url = "https://files.pythonhosted.org/packages/08/34/2841cb5c1dea43a1e3893deb0ed412d4eeb16f4a3eb4daf2465d24b71069/zope_interface-8.3-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:731eaf0a0f2a683315a2dfc2953ef831ae51e062b87cff6220e0e5102a83b612", size = 259521, upload-time = "2026-04-10T06:21:58.505Z" }, + { url = "https://files.pythonhosted.org/packages/23/ff/66ba0f3aba2d3724e425fdb99122d6f7927a37d623492a606477094a6891/zope_interface-8.3-cp310-cp310-win_amd64.whl", hash = "sha256:5e9861493457268f923d8aae4052383922162c3d56094c4e3a9ff83173d64be3", size = 214205, upload-time = "2026-04-10T06:22:00.611Z" }, + { url = "https://files.pythonhosted.org/packages/0d/99/cee01c7e8be6c5889f2c74914196decd91170011f420c9912792336f284c/zope_interface-8.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:e8964f1a13b07c8770eab88b7a6cd0870c3e36442e4ef4937f36fd0b6d1cea2c", size = 210875, upload-time = "2026-04-10T06:22:02.746Z" }, + { url = "https://files.pythonhosted.org/packages/e2/f1/cf7a49b36385ed1ee0cc7f6b8861904f1533a3286e01cd1e3c2eb72976b9/zope_interface-8.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:ec2728e3cf685126ccd2e0f7635fb60edf116f76f402dd66f4df13d9d9348b4b", size = 211199, upload-time = "2026-04-10T06:22:04.596Z" }, + { url = "https://files.pythonhosted.org/packages/cc/86/1ccb73ce9189b1345b7824830a18796ae0b33317d3725d8a034a6ce06501/zope_interface-8.3-cp311-cp311-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:568b97cb701fd2830b52198a2885e851317a019e1912eaad107860e3cca71964", size = 259885, upload-time = "2026-04-10T06:22:06.403Z" }, + { url = "https://files.pythonhosted.org/packages/a1/de/d0185211ad4902641c0233b7c3b42e21582ffac24f5afe5cc4736b196346/zope_interface-8.3-cp311-cp311-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:62839e4201869a29f99742df7f7139cac4ce301850d3787da37f84e271ad9b95", size = 264308, upload-time = "2026-04-10T06:22:08.425Z" }, + { url = "https://files.pythonhosted.org/packages/0e/e5/ac6f24cdaa04711246d425a2ca301e2f3c97e8d6d672b44258eb2ceb92ff/zope_interface-8.3-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:d287183767926bc9841e51471a28b77c7b49fddf65016aa7faf5a1447e2b6558", size = 265594, upload-time = "2026-04-10T06:22:10.111Z" }, + { url = "https://files.pythonhosted.org/packages/b3/ca/e888c67123b6a7019936c67b5ebcc9396fdb3067cf278d7541d24f4c1a86/zope_interface-8.3-cp311-cp311-win_amd64.whl", hash = "sha256:12a33bb596ca20520e44f97918950cfc66a632ac0278a7f40608217cc4269948", size = 214562, upload-time = "2026-04-10T06:22:12.681Z" }, + { url = "https://files.pythonhosted.org/packages/16/1e/7ed593f9c3664e560febe1f132fdf73b8bb9a3de6e3448093b0167239c8c/zope_interface-8.3-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:b361b7ce566bc024e55f74eb1e88afc14039d7bd8ea13eeff3b7a8400dc59683", size = 211571, upload-time = "2026-04-10T06:22:14.775Z" }, + { url = "https://files.pythonhosted.org/packages/cf/31/844979b472f30efd2a68480738c9a3be518786b0885137075616607e88c7/zope_interface-8.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:f5be73ca1304daa3046ee5835f7fa6b3badadf02102b570532dd57cd25dd72d6", size = 211748, upload-time = "2026-04-10T06:22:16.695Z" }, + { url = "https://files.pythonhosted.org/packages/6e/b6/71f5c9d8dde7334e1b67306fea5814c67eac92d871bb0dfc664c9f3355f1/zope_interface-8.3-cp312-cp312-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:961af756797e36c1e77f7d0dc8ac1322de0c071eaa1a641dbe3b790061968dd9", size = 264718, upload-time = "2026-04-10T06:22:19.473Z" }, + { url = "https://files.pythonhosted.org/packages/94/e3/5eab77fd6795ca37b9ed1aeea5290170018938549322003745bdcd939238/zope_interface-8.3-cp312-cp312-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:a6329f296b70f62043bf2df06eb91b4be040baee32ec4a3e0314f3893fa5c51c", size = 269795, upload-time = "2026-04-10T06:22:21.728Z" }, + { url = "https://files.pythonhosted.org/packages/a2/2f/4bc8807d65833f06335a49beb1786bafcf748cde7472ba14cdb4db463ba8/zope_interface-8.3-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:f420f6c96307ff265981c510782f0ed97475107b78ca9fca0bb04fe36f363eb4", size = 269418, upload-time = "2026-04-10T06:22:23.802Z" }, + { url = "https://files.pythonhosted.org/packages/50/3d/1cfaf770bc6bc64edec3d4c5f17b5dbe600bf93cd2caac5ee0880eb9f9e0/zope_interface-8.3-cp312-cp312-win_amd64.whl", hash = "sha256:ffeae9102aa6ba5bd2f9a547016347bd87c9cf01aea564936c0d165fff0b1242", size = 214390, upload-time = "2026-04-10T06:22:25.735Z" }, + { url = "https://files.pythonhosted.org/packages/27/da/ff205c5463e52ad64cc40be667fdff2b01b9754a385c6b95bac01645fa4f/zope_interface-8.3-cp313-cp313-macosx_10_9_x86_64.whl", hash = "sha256:1aa0e1d72212cedc38b2156bbca08cf24625c057135a7947ef6b19bc732b2772", size = 211889, upload-time = "2026-04-10T06:22:27.612Z" }, + { url = "https://files.pythonhosted.org/packages/c7/21/0cc848e22769b1cf4c0cd636ec2e60ea05cfb958423435ea526d5a291fe8/zope_interface-8.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:54ab83218a8f6947ba4b6cb1a121f1e1abe2e418b838ccdac71639d0f97e734e", size = 211961, upload-time = "2026-04-10T06:22:29.575Z" }, + { url = "https://files.pythonhosted.org/packages/e3/54/815c9dbb90336c50694b4c7ef7ced06bc389e5597200c77457b557a0221c/zope_interface-8.3-cp313-cp313-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:34d6c10fa790005487c471e0e4ab537b0fa9a70e55a96994e51ffeef92205fa4", size = 264409, upload-time = "2026-04-10T06:22:31.426Z" }, + { url = "https://files.pythonhosted.org/packages/3a/69/2e5c30adde0e94552d934971fa6eba107449d3d11fa086cfcfeb8ea6354d/zope_interface-8.3-cp313-cp313-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:93108d5f8dee20177a637438bf4df4c6faf8a317c9d4a8b1d5e78123854e3317", size = 269592, upload-time = "2026-04-10T06:22:33.393Z" }, + { url = "https://files.pythonhosted.org/packages/23/8a/fbb1dceb5c5400b2b27934aa102d29fe4cb06732122e7f409efebeb6e097/zope_interface-8.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:8f81d90f80b9fbf36602549e2f187861c9d7139837f8c9dd685ce3b933c6360f", size = 269548, upload-time = "2026-04-10T06:22:35.339Z" }, + { url = "https://files.pythonhosted.org/packages/a2/70/abd0bb9cc9b1a9a718f30c81f46a184a2e751dd80cf57db142ffa42730da/zope_interface-8.3-cp313-cp313-win_amd64.whl", hash = "sha256:96106a5f609bb355e1aec6ab0361213c8af0843ca1e1ba9c42eacfbd0910914e", size = 214391, upload-time = "2026-04-10T06:22:36.969Z" }, + { url = "https://files.pythonhosted.org/packages/8a/d9/95fe0d4d8da09042383c42f239e0106f1019ec86a27ed9f5000e754f6e7a/zope_interface-8.3-cp314-cp314-macosx_10_9_x86_64.whl", hash = "sha256:96f0001b49227d756770fc70ecde49f19332ae98ec98e1bbbf2fd7a87e9d4e45", size = 211979, upload-time = "2026-04-10T06:22:38.628Z" }, + { url = "https://files.pythonhosted.org/packages/f3/01/b6f694444ea1c911a4ea915f4ef066a95e9d1a58256a30c131ec88c3ae64/zope_interface-8.3-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:3853bfb808084e1b4a3a769b00bd8b58a52b0c4a4fc5c23de26d283cd8beb627", size = 212038, upload-time = "2026-04-10T06:22:40.475Z" }, + { url = "https://files.pythonhosted.org/packages/f7/cf/237de1fba4f05686bc344eeb035236bd89890679c8211f129f05b5971ccf/zope_interface-8.3-cp314-cp314-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:33a13acba79ef693fb64ceb6193ece913d39586f184797f133c1bc549da86851", size = 266041, upload-time = "2026-04-10T06:22:42.093Z" }, + { url = "https://files.pythonhosted.org/packages/58/5f/df85b1ff5626d7f05231e69b7efd38bdc2c82ca363495e0bb112aaf655b3/zope_interface-8.3-cp314-cp314-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:e9f7e4b46741a11a9e1fab8b68710f08dec700e9f1b877cdca02480fbebe4846", size = 269094, upload-time = "2026-04-10T06:22:43.832Z" }, + { url = "https://files.pythonhosted.org/packages/5f/10/7ad1ff9c514fe38b176fc1271967c453074eb386a4515bd3b957c485f3a8/zope_interface-8.3-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:8ce49d43366e12aeccd14fcaebb3ef110f50f5795e0d4a95383ea057365cedf2", size = 269413, upload-time = "2026-04-10T06:22:45.573Z" }, + { url = "https://files.pythonhosted.org/packages/38/42/3b0b5edee7801e0dd5c42c2c9bb4ec8bec430a6628462eb1315db76a7954/zope_interface-8.3-cp314-cp314-win_amd64.whl", hash = "sha256:301db4049c79a15a3b29d89795e150daf0e9ae701404b112ad6585ea863f6ef5", size = 215170, upload-time = "2026-04-10T06:22:47.115Z" }, ] [[package]] From bb433be70f284a033340a5431f9f9ef7c4fc12f9 Mon Sep 17 00:00:00 2001 From: Johann Schleier-Smith Date: Thu, 30 Apr 2026 12:43:27 -0700 Subject: [PATCH 070/226] Add Workflow Streams library (#1423) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Add temporalio.contrib.pubsub — reusable pub/sub for workflows A workflow mixin (PubSubMixin) that turns any workflow into a pub/sub broker. Activities and starters publish via batched signals; external clients subscribe via long-poll updates exposed as an async iterator. Key design decisions: - Payloads are opaque bytes for cross-language compatibility - Topics are plain strings, no hierarchy or prefix matching - Global monotonic offsets (not per-topic) for simple continuation - Batching built into PubSubClient with Nagle-like timer + priority flush - Structured concurrency: no fire-and-forget tasks, trio-compatible - Continue-as-new support: drain_pubsub() + get_pubsub_state() + validator to cleanly drain polls, plus follow_continues on the subscriber side Module layout: _types.py — PubSubItem, PublishInput, PollInput, PollResult, PubSubState _mixin.py — PubSubMixin (signal, update, query handlers) _client.py — PubSubClient (batcher, async iterator, CAN resilience) 9 E2E integration tests covering: activity publish + subscribe, topic filtering, offset-based replay, interleaved workflow/activity publish, priority flush, iterator cancellation, context manager flush, concurrent subscribers, and mixin coexistence with application signals/queries. Co-Authored-By: Claude Opus 4.6 (1M context) * Fix PubSubState CAN serialization and simplify subscribe error handling PubSubState is now a Pydantic model so it survives serialization through Pydantic-based data converters when embedded in Any-typed fields. Without this, continue-as-new would fail with "'dict' object has no attribute 'log'" because Pydantic deserializes Any fields as plain dicts. Added two CAN tests: - test_continue_as_new_any_typed_fails: documents that Any-typed fields lose PubSubState type information (negative test) - test_continue_as_new_properly_typed: verifies CAN works with properly typed PubSubState | None fields Simplified subscribe() exception handling: removed the broad except Exception clause that tried _follow_continue_as_new() on every error. Now only catches WorkflowUpdateRPCTimeoutOrCancelledError for CAN follow. Co-Authored-By: Claude Opus 4.6 (1M context) * Polish pub/sub contrib: README, flush safety, init guard, factory method README.md: usage-oriented documentation covering workflow mixin, activity publishing, subscribing, continue-as-new, and cross-language protocol. flush() safety: items are now removed from the buffer only after the signal succeeds. Previously, buffer.clear() ran before the signal, losing items on failure. Added test_flush_retains_items_on_signal_failure. init_pubsub() guard: publish() and _pubsub_publish signal handler now check for initialization and raise a clear RuntimeError instead of a cryptic AttributeError. PubSubClient.for_workflow() factory: preferred constructor that takes a Client + workflow_id. Enables follow_continues in subscribe() without accessing private WorkflowHandle._client. The handle-based constructor remains for simple cases that don't need CAN following. activity_pubsub_client() now uses for_workflow() internally with proper keyword-only typed arguments instead of **kwargs: object. CAN test timing: replaced asyncio.sleep(2) with assert_eq_eventually polling for a different run_id, matching sdk-python test patterns. Co-Authored-By: Claude Opus 4.6 (1M context) * Add init guards to poll/query handlers and fix README CAN example _pubsub_poll and _pubsub_offset now call _check_initialized() for a clear RuntimeError instead of cryptic AttributeError when init_pubsub() is forgotten. README CAN example now includes the required imports (@dataclass, workflow) and @workflow.init decorator. Co-Authored-By: Claude Opus 4.6 (1M context) * Guard validator against missing init_pubsub, fix PubSubState docstring The poll validator accesses _pubsub_draining, which would AttributeError if init_pubsub() was never called. Added _check_initialized() guard. Fixed PubSubState docstring: the field must be typed as PubSubState | None, not Any. The old docstring incorrectly implied Any-typed fields would work. Co-Authored-By: Claude Opus 4.6 (1M context) * Guard get_pubsub_state/drain_pubsub, add replay and max_batch_size tests get_pubsub_state() and drain_pubsub() now call _check_initialized(). Previously drain_pubsub() could silently set _pubsub_draining on an uninitialized instance, which init_pubsub() would then reset to False. New tests: - test_max_batch_size: verifies auto-flush when buffer reaches limit, using max_cached_workflows=0 to also test replay safety - test_replay_safety: interleaved workflow/activity publish with max_cached_workflows=0, proving the mixin is determinism-safe Co-Authored-By: Claude Opus 4.6 (1M context) * Add review comments and design addenda for pubsub redesign Review comments (#@AGENT: annotations) capture design questions on: - Topic offset model and information leakage (resolved: global offsets with BFF-layer containment, per NATS JetStream model) - Exactly-once publish delivery (resolved: publisher ID + sequence number dedup, per Kafka producer model) - Flush concurrency (resolved: asyncio.Lock with buffer swap) - CAN follow behavior, poll rate limiting, activity context detection, validator purpose, pyright errors, API ergonomics DESIGN-ADDENDUM-TOPICS.md: full exploration of per-topic vs global offsets with industry survey (Kafka, Redis, NATS, PubNub, Google Pub/Sub, RabbitMQ). Concludes global offsets are correct for workflow-scoped pub/sub; leakage contained at BFF trust boundary. DESIGN-ADDENDUM-DEDUP.md: exactly-once delivery via publisher ID + monotonic sequence number. Workflow dedup state is dict[str, int], bounded by publisher count. Buffer swap pattern with sequence reuse on failure. PubSubState carries publisher_sequences through CAN. Co-Authored-By: Claude Opus 4.6 (1M context) * Implement pubsub redesign: dedup, base_offset, flush safety, API cleanup Types: - Remove offset from PubSubItem (global offset is now derived) - Add publisher_id + sequence to PublishInput for exactly-once dedup - Add base_offset + publisher_sequences to PubSubState for CAN - Use Field(default_factory=...) for Pydantic mutable defaults Mixin: - Add _pubsub_base_offset for future log truncation support - Add _pubsub_publisher_sequences for signal deduplication - Dedup in signal handler: reject if sequence <= last seen - Poll uses base_offset arithmetic for offset translation - Class-body type declarations for basedpyright compatibility - Validator docstring explaining drain/CAN interaction - Module docstring gives specific init_pubsub() guidance Client: - asyncio.Lock + buffer swap for flush concurrency safety - Publisher ID (uuid) + monotonic sequence for exactly-once delivery - Sequence advances on failure to prevent data loss when new items merge with retry batch (found via Codex review) - Remove follow_continues param — always follow CAN via describe() - Configurable poll_interval (default 0.1s) for rate limiting - Merge activity_pubsub_client() into for_workflow() with auto-detect - _follow_continue_as_new is async with describe() check Tests: - New test_dedup_rejects_duplicate_signal - Updated flush failure test for new sequence semantics - All activities use PubSubClient.for_workflow() - Remove PubSubItem.offset assertions - poll_interval=0 in test helper for speed Docs: - DESIGN-v2.md: consolidated design doc superseding original + addenda - README.md: updated API reference - DESIGN-ADDENDUM-DEDUP.md: corrected flush failure semantics Co-Authored-By: Claude Opus 4.6 (1M context) * TLA+-verified dedup rewrite, TTL pruning, truncation, API improvements Rewrite the client-side dedup algorithm to match the formally verified TLA+ protocol: failed flushes keep a separate _pending batch and retry with the same sequence number. Only advance the confirmed sequence on success. TLC proves NoDuplicates and OrderPreserved for the correct algorithm, and finds duplicates in the old algorithm. Add TTL-based pruning of publisher dedup entries during continue-as-new (default 15 min). Add max_retry_duration (default 600s) to bound client retries — must be less than publisher_ttl for safety. Both constraints are formally verified in PubSubDedupTTL.tla. Add truncate_pubsub() for explicit log prefix truncation. Add publisher_last_seen timestamps for TTL tracking. Preserve legacy state without timestamps during upgrade. API changes: for_workflow→create, flush removed (use priority=True), poll_interval→poll_cooldown, publisher ID shortened to 16 hex chars. Includes TLA+ specs (correct, broken, inductive, multi-publisher TTL), PROOF.md with per-action preservation arguments, scope and limitations. Co-Authored-By: Claude Opus 4.6 (1M context) * Remove TLA+ proof references from implementation code Co-Authored-By: Claude Opus 4.6 (1M context) * Update uv.lock Co-Authored-By: Claude Opus 4.6 (1M context) * Add signal vs update dedup analysis; clarify ordering guarantees New analysis document evaluates whether publishing should use signals or updates, examining Temporal's native dedup (Update ID per-run, request_id for RPCs) vs the application-level (publisher_id, sequence) protocol. Conclusion: app-level dedup is permanent for signals but could be dropped for updates once temporal/temporal#6375 is fixed. Non-blocking flush keeps signals as the right choice for streaming. Updates DESIGN-v2.md section 6 to be precise about the two Temporal guarantees that signal ordering relies on: sequential send order and history-order handler invocation. Co-Authored-By: Claude Opus 4.6 (1M context) * Add end-to-end dedup analysis: proper layering for three duplicate types Analyzes deduplication through the end-to-end principle lens. Three types of duplicates exist in the pipeline, each handled at the layer that introduces them: - Type A (duplicate LLM work): belongs at application layer — data escapes to consumers before the duplicate exists, so only the application can resolve it - Type B (duplicate signal batches): belongs in pub/sub workflow — encapsulates transport details and is the only layer that can detect them correctly - Type C (duplicate SSE delivery): belongs at BFF/browser layer Concludes the (publisher_id, sequence) protocol is correctly placed. Co-Authored-By: Claude Opus 4.6 (1M context) * Expand DESIGN-v2 with offset model rationale and BFF/SSE reconnection design Fill gaps identified during design review: - Document why per-topic offsets were rejected (trust model, cursor portability, unjustified complexity) inline rather than only in historical addendum - Expand BFF section with the four reconnection options considered and the decision to use SSE Last-Event-ID with BFF-assigned gapless IDs - Add poll efficiency characteristics (O(new items) common case) - Document BFF restart fallback (replay from turn start) Co-Authored-By: Claude Opus 4.6 (1M context) * pubsub: use base64 wire format with native bytes API Wire types (PublishEntry, _WireItem, PollResult, PubSubState) encode data as base64 strings for cross-language compatibility across all Temporal SDKs. User-facing types (PubSubItem) use native bytes. Conversion happens inside handlers: - Signal handler decodes base64 → bytes on ingest - Poll handler encodes bytes → base64 on response - Client publish() accepts bytes, encodes for signal - Client subscribe() decodes poll response, yields bytes This means Go/Java/.NET ports get cross-language compat for free since their JSON serializers encode byte[] as base64 by default. Co-Authored-By: Claude Opus 4.6 (1M context) * pubsub: remove poll timeout and update design doc Remove the bounded poll wait from PubSubMixin and trim trailing whitespace from types. Update DESIGN-v2.md with streaming plugin rationale (no fencing needed, UI handles repeat delivery). Co-Authored-By: Claude Opus 4.6 (1M context) * Add token-level streaming to OpenAI and ADK Temporal plugins Add opt-in streaming code path to both agent framework plugins. When enabled, the model activity calls the streaming LLM endpoint, publishes TEXT_DELTA/THINKING_DELTA/TOOL_CALL_START events via PubSubClient as a side channel, and returns the complete response for the workflow to process (unchanged interface). OpenAI Agents SDK: - ModelActivityParameters.enable_streaming flag - New invoke_model_activity_streaming method on ModelActivity - ModelResponse reconstructed from ResponseCompletedEvent - Uses @_auto_heartbeater for periodic heartbeats - Routing in _temporal_model_stub (rejects local activities) Google ADK: - TemporalModel(streaming=True) constructor parameter - New invoke_model_streaming activity using stream=True - Registered in GoogleAdkPlugin Both use batch_interval=0.1s for near-real-time token delivery. No pubsub module changes needed. Co-Authored-By: Claude Opus 4.6 (1M context) * pubsub: replace PubSubState Pydantic model with plain dataclass The Pydantic BaseModel was introduced as a workaround for Any-typed fields losing type information during continue-as-new serialization. The actual fix is using concrete type annotations (PubSubState | None), which the default data converter handles correctly for dataclasses — no Pydantic dependency needed. This removes the pydantic import from the pubsub contrib module entirely, making it work out of the box with the default data converter. All 18 tests pass, including both continue-as-new tests. Co-Authored-By: Claude Opus 4.6 (1M context) * pubsub: add per-item offsets to PubSubItem and _WireItem Implements DESIGN-ADDENDUM-ITEM-OFFSET.md. The poll handler now annotates each item with its global offset (base_offset + position in log), enabling subscribers to track fine-grained consumption progress for truncation. This is needed for the voice-terminal agent where audio chunks must not be truncated until actually played, not merely received. - Add offset field to PubSubItem and _WireItem (default 0) - Poll handler computes offset from base_offset + log_offset + enumerate index - subscribe() passes wire_item.offset through to yielded PubSubItem - Tests: per-item offsets, offsets with topic filtering, offsets after truncation Co-Authored-By: Claude Opus 4.6 (1M context) * pubsub: add design addendum for per-item offsets Documents the motivation and design for adding offset fields to PubSubItem and _WireItem, enabling subscribers to track consumption at item granularity rather than batch boundaries. Driven by the voice-terminal agent's need to truncate only after audio playback, not just after receipt. Co-Authored-By: Claude Opus 4.6 (1M context) * pubsub: fix truncated offset crash and add recovery Three changes: 1. Poll handler: replace ValueError with ApplicationError(non_retryable=True) when requested offset has been truncated. This fails the UPDATE (client gets the error) without crashing the WORKFLOW TASK — avoids the poison pill during replay that caused permanent workflow failures. 2. Poll handler: treat from_offset=0 as "from the beginning of whatever exists" (i.e., from base_offset). This lets subscribers recover from truncation by resubscribing from 0 without knowing the current base. 3. PubSubClient.subscribe(): catch WorkflowUpdateFailedError with type TruncatedOffset and retry from offset 0, auto-recovering. New tests: - test_poll_truncated_offset_returns_application_error - test_poll_offset_zero_after_truncation - test_subscribe_recovers_from_truncation Co-Authored-By: Claude Opus 4.6 (1M context) * Add cross-workflow and cross-namespace pub/sub tests Verify that PubSubClient can subscribe to events from a different workflow (same namespace) and that Nexus operations can start pub/sub broker workflows in a separate namespace with cross-namespace subscription working end-to-end. No library changes needed. Co-Authored-By: Claude Opus 4.6 (1M context) * pubsub: cap poll response at ~1MB and skip cooldown when more data ready Poll responses now estimate wire size (base64 data + topic) and stop adding items once the response exceeds 1MB. The new `more_ready` flag on PollResult tells the subscriber that more data is available, so it skips the poll_cooldown sleep and immediately re-polls. This avoids unnecessary latency during big reloads or catch-up scenarios while keeping individual update payloads within Temporal's recommended limits. Co-Authored-By: Claude Opus 4.6 (1M context) * Add compatibility contract to pub/sub design doc Codify the four wire evolution rules that have been followed implicitly through four addenda: additive-only fields with defaults, immutable handler names, forward-compatible PubSubState, and no application-level version negotiation. Includes a precedent table showing all past changes and reasoning for why version fields in payloads would cause silent data loss on signals. Co-Authored-By: Claude Opus 4.6 (1M context) * Fix sequence reuse after retry timeout (TLA+-verified) After max_retry_duration expires, the client dropped the pending batch without advancing _sequence. The next batch reused the same sequence number, which could be silently deduplicated by the workflow if the timed-out signal was actually delivered — causing permanent data loss for those items. The fix advances _sequence to _pending_seq before clearing _pending, ensuring subsequent batches always get a fresh sequence number. TLA+ verification: - Added DropPendingBuggy/DropPendingFixed actions to PubSubDedup.tla - Added SequenceFreshness invariant: (pending=<<>>) => (confirmed_seq >= wf_last_seq) - BuggyDropSpec FAILS SequenceFreshness (confirmed_seq=0 < wf_last_seq=1) - FixedDropSpec PASSES all invariants (489 distinct states) - NoDuplicates passes for both — the bug causes data loss, not duplicates Python test: - test_retry_timeout_sequence_reuse_causes_data_loss demonstrates the end-to-end consequence: reused seq=1 is rejected, fresh seq=2 accepted Co-Authored-By: Claude Opus 4.6 (1M context) * Remove backward-compat code and historical design docs from pubsub This is a new release with no legacy to support. Changes: - _mixin.py: Remove ts-is-None fallback that retained publishers without timestamps. All publishers always have timestamps, so this was dead code. - _types.py: Clean up docstrings referencing addendum docs - DESIGN-v2.md: Remove backward-compat framing, addendum references, and historical file listing. Keep the actual evolution rules. - PROOF.md: "Legacy publisher_id" → "Empty publisher_id" - README.md: Reference DESIGN-v2.md instead of deleted addendum - Delete DESIGN.md and 4 DESIGN-ADDENDUM-*.md files (preserved in the top-level streaming-comparisons repo) - Delete stale TLA+ trace .bin files Co-Authored-By: Claude Opus 4.6 (1M context) * Update pubsub README: rename for_workflow → create, streamline docs Simplify the README to focus on essential API patterns. Rename for_workflow() to create() throughout, condense the topics section, remove the exactly-once and type-warning sections (these details belong in DESIGN-v2.md), and update the API reference table with current parameter signatures. Also fix whitespace alignment in DESIGN-v2.md diagram. Co-Authored-By: Claude Opus 4.6 (1M context) * Fix continue-as-new example to show application state carried alongside pubsub state The CAN example only showed pubsub_state being passed through, which could mislead readers into thinking that's all that's needed. Updated to include a representative application field (items_processed) to make it clear that your own workflow state must also be carried across the CAN boundary. Co-Authored-By: Claude Opus 4.6 (1M context) * Add motivation and architectural context to pubsub README intro Replace the terse opening with two paragraphs that explain why this module exists (boilerplate around batching, offsets, topics, CAN), ground it in concrete use cases (order updates, AI streaming, pipeline progress), and call out the Temporal primitives it builds on (signals for publish, updates for subscribe, client-side batching for compaction). Co-Authored-By: Claude Opus 4.6 (1M context) * Move bytes/base64 payload detail to Cross-Language Protocol section This is an implementation detail more relevant to cross-language interop than to the introductory overview. Co-Authored-By: Claude Opus 4.6 (1M context) * Move analysis docs and TLA+ verification out of pubsub module Design analysis (end-to-end dedup, signal-vs-update) and TLA+ formal verification specs are reference material, not part of the distributed module. Moved to worktree-level docs/. DESIGN-v2.md updated with three additions: - Decision #12: signals for publish, updates for poll (rationale) - Dedup scope section: Type A/B/C taxonomy with end-to-end principle - Session ordering: flush_lock mechanism and Temporal docs citation Removed file-path references to verification/ specs from DESIGN-v2.md since they no longer live in the module. Co-Authored-By: Claude Opus 4.6 (1M context) * Remove TLA+ references, document opaque-bytes and JSON converter rationale Remove references to PubSubDedup.tla from code comments, test docstrings, and the design doc — the TLA+ spec was moved out of the published module. Add design rationale for opaque bytes vs typed payloads (decoupling, layering, type hints). Document the JSON data converter requirement for cross-language interop in both the design doc and README. Co-Authored-By: Claude Opus 4.6 (1M context) * Clean up pubsub tests: remove redundant cases, de-flake barriers Review pass over tests/contrib/pubsub/test_pubsub.py: Delete redundant tests: - test_poll_offset_zero_after_truncation and test_per_item_offsets_after_truncation were fully covered by test_truncate_pubsub and test_subscribe_recovers_from_truncation. - test_small_response_more_ready_false was the trivial branch of the big-response test; fold a single more_ready=False assertion into test_poll_more_ready_when_response_exceeds_size_limit instead of standing up a separate workflow. - test_subscribe_from_offset merged into test_per_item_offsets, renamed to test_subscribe_from_offset_and_per_item_offsets. - test_retry_timeout_sequence_reuse_causes_data_loss was effectively a rename of test_dedup_rejects_duplicate_signal and asserted the BUG (silent dedup) rather than the FIX, so it would fail if the behavior became stricter. Rewrite white-box tests to be behavioral: - test_flush_keeps_pending_on_signal_failure and test_max_retry_duration_expiry asserted on private _buffer, _pending, _pending_seq, _sequence fields — any refactor of the retry state machine broke them even with preserved behavior. Replaced with test_flush_retry_preserves_items_after_failures and test_flush_raises_after_max_retry_duration, which use patch.object(handle, "signal", ...) to inject delivery failures against a real workflow and assert observable outcomes. - test_continue_as_new_any_typed_fails used an absence-timeout assertion (len == 0 within 3s) that would flake on slow CI and pass for the wrong reason. Switched to assert_task_fail_eventually on the new run, which asserts the specific failure mode. Remove sleep-as-barrier anti-pattern: Drop ~10 asyncio.sleep(0.3-0.5) barriers after __pubsub_publish / truncate signals. A subsequent query or update naturally waits for prior signals to be processed by the worker, so the sleeps were both redundant and brittle. Replace the while True: sleep(0.1) describe- poll in the cross-namespace test with assert_eq_eventually. Fix test_priority_flush to actually test priority: The 0.5s sleep at the end of the publish_with_priority activity made the test pass regardless — __aexit__ would always flush before the 10s external collect timeout elapsed. Extended the activity hold to ~10s and tightened the collect timeout to 5s so that a priority- wakeup regression surfaces as a missing item instead of a pass via exit-time flush. The hold is long enough that worker teardown outraces activity completion, so tests still finish in sub-second wall time. Result: 30 → 25 tests, 1848 → ~1590 lines, all passing in 5s. Co-Authored-By: Claude Opus 4.7 (1M context) * Replace remaining brittle sleeps in pubsub tests and type handle helpers Follow-up to the prior cleanup. The two remaining timing-based sleeps are replaced with explicit coordination, and helper functions taking a handle now carry proper type annotations. test_iterator_cancellation: publish a seed item and wait for an asyncio.Event set on first yield (bounded by asyncio.timeout), then cancel. The iterator is provably active at cancel time, so the test no longer races against an arbitrary sleep. test_flush_raises_after_max_retry_duration: inject a controllable clock via patch of temporalio.contrib.pubsub._client.time.monotonic. Advance the clock between the failing flush and the retry check so the timeout fires deterministically without depending on wall-clock speed or clock resolution. _is_different_run and collect_items now annotate their handle parameters as WorkflowHandle[Any, Any] (WorkflowHandle is generic over workflow class and return type; the helpers are polymorphic). Co-Authored-By: Claude Opus 4.7 (1M context) * Clarify that pubsub truncation is workflow-side only No external truncate API exists — truncation is a workflow-internal decision (retention policy, consumer progress), so external callers must define their own signal or update that invokes truncate_pubsub. - Expand the TruncateSignalWorkflow docstring to call out that it's test scaffolding and to point to the integration pattern. - Note the workflow-side-only nature in the README table row. Co-Authored-By: Claude Opus 4.7 (1M context) * Switch test truncate from signal to update for explicit completion Signals are fire-and-forget. The truncate tests relied on "a subsequent update acts as a barrier for prior signals" — true but implicit. An update handler returns only after it completes, making the contract explicit and removing a class of reader confusion. Rename TruncateSignalWorkflow → TruncateWorkflow, change truncate from @workflow.signal to @workflow.update, and switch the three call sites from handle.signal("truncate", ...) to handle.execute_update(...). Drop stale barrier comments now that completion is intrinsic. Co-Authored-By: Claude Opus 4.7 (1M context) * Delete test_mixin_coexistence Every other workflow in this file mixes PubSubMixin with a user-defined close signal (and custom init/run), so coexistence is proven implicitly by the full suite. The only unique claim here was that an app query coexists with the mixin's __pubsub_offset query — a vanishingly small risk given Temporal SDK registers handlers by explicit name and there is no shared registry. If a future conflict did arise, dozens of tests would fail, not just this one. Co-Authored-By: Claude Opus 4.7 (1M context) * Force interleaving in test_concurrent_subscribers The prior version started two subscribe tasks via asyncio.gather and asserted each received its expected items. That passes even if subscriber A fully drains its items before subscriber B's first poll goes out — the test never observed interleaving, only topic filtering under parallel calls. Reshape the test as a ping-pong: publish A-0, wait (via asyncio.Event) for A to receive it; publish B-0, wait for B to receive it. At that point both subscribers are mid-subscription and polling for item 2, so both __pubsub_poll updates are in flight simultaneously. Repeat for item 2. A sequential execution cannot satisfy the publish order because B's first item isn't published until after A has received its first. Co-Authored-By: Claude Opus 4.7 (1M context) * Strengthen CAN test, widen TTL margins, document Any-field pitfall Three related test-quality changes after a Codex challenge pass. Delete test_continue_as_new_any_typed_fails (and its workflow/input classes). It exercised the default Temporal data converter behavior (Any-typed dataclass field deserializes as dict) rather than a pubsub concern, and relied on a weak assert_task_fail_eventually that would pass for any task failure. Replace with a doc note on init_pubsub() warning about Any-typed pubsub_state fields, keeping the guidance where a user looks when wiring up CAN. Strengthen test_continue_as_new_properly_typed. Previously only verified log contents and offsets survived CAN. Now also verifies publisher dedup state survives: seeds publisher_id="pub" sequence=1, CANs, and asserts on publisher_sequences directly via a new query handler. Three assertions — after CAN, after a duplicate publish, and after a fresh-sequence publish — bracket the dedup contract without inferring it from log length. Inline the previously-shared _run_can_test helper since only one caller remained. Widen TTL test margins from (0.3s sleep, 0.1s TTL) to (1.0s sleep, 0.5s TTL). The tighter margin left ~100ms headroom on each side for pub-old to prune and pub-new to survive — borderline on slow CI where worker scheduling between publish and query can itself exceed 100ms. The new margins tolerate multi-hundred-ms scheduling jitter in both directions. Co-Authored-By: Claude Opus 4.7 (1M context) * Hoist inline imports to module level in pubsub tests Four sets of function-local imports had no technical justification — no circular imports, no optional dependencies, no heavy-module deferral benefit for a test file. They were editorial drift from incremental additions. Move them to the top of the file: - WorkflowUpdateFailedError (was local in truncate-error test) - unittest.mock.patch (was duplicated in two retry tests) - temporalio.api.nexus.v1, temporalio.api.operatorservice.v1 (was local in create_cross_namespace_endpoint helper) - google.protobuf.duration_pb2, temporalio.api.workflowservice.v1 (was local in cross-namespace Nexus test) Co-Authored-By: Claude Opus 4.7 (1M context) * Fix __aexit__ drain race and strengthen pubsub tests PubSubClient.__aexit__ could silently drop items on context-manager exit. A single _flush() processes either pending OR buffer (if/elif), so when the flusher task was cancelled mid-signal (pending set) while the producer had added more items (buffer non-empty), the final flush handled pending and left buffered items orphaned. Real impact: agent streaming that publishes a last token and immediately exits the context manager could silently drop trailing tokens depending on timing. Fix by draining both in a loop until pending and buffer are empty. This bug was latent in test_max_batch_size because that test's activity loop had no awaits — the flusher never ran during the loop, so pending never accumulated concurrently with buffer. Strengthening the test exposed it. Test changes: - test_max_batch_size: add an await asyncio.sleep(0) between publishes (matches real agent workloads that yield on every LLM token) and assert via publisher_sequences query that max_batch_size actually triggers >=2 mid-loop flushes, not a single exit flush. Without this the test passed even if max_batch_size were ignored entirely. - test_replay_safety: assert the full ordered 7-item sequence and offsets rather than just endpoints. Endpoint-only checks would miss mid-stream replay corruption (reordering, duplication, drops). - test_poll_truncated_offset_returns_application_error: add a comment explaining why pytest.raises(WorkflowUpdateFailedError) suffices to prove the handler raised ApplicationError — Temporal's update protocol completes with this error only for ApplicationError; other exceptions fail the workflow task instead, causing execute_update to hang rather than raise. Co-Authored-By: Claude Opus 4.7 (1M context) * Style + docstring cleanups in pubsub contrib module Address a small set of stylistic issues flagged during review. Fix stale docstring in PubSubState's PollResult: the field is more_ready, not has_more. Readers following the docstring would have looked for a non-existent attribute. Add generic parameters to the WorkflowHandle annotation in PubSubClient.__init__ (WorkflowHandle[Any, Any]). Matches the treatment applied earlier in the tests; PubSubClient is polymorphic over workflow types. Rename the signal/update handler parameters in PubSubMixin from `input` (which shadowed the builtin) to `payload`. The type names (PublishInput, PollInput) already convey "input," so the parameter name was redundant. Drop the now-unnecessary `# noqa: A002` on the validator. Clarify the PubSubClient.__init__ docstring about continue-as-new: previously said "prefer create() when you need CAN following," now explicitly notes that the direct-handle form does not follow CAN and will stop yielding once the original run ends. Run `ruff check --select I --fix` and `ruff format` to bring the module and tests into line with project lint. Co-Authored-By: Claude Opus 4.7 (1M context) * Apply pubsub review feedback: init pattern, force_flush, from_activity Four changes responding to review comments on sdk-python PR #1423: C1 (init_pubsub pattern). Docstrings, README, and DESIGN-v2.md now advise a single call site from @workflow.init with prior_state threaded through the workflow input, instead of the previous "call in __init__ for fresh, in run() for CAN" split. The signature is unchanged (prior_state is still optional and defaults to None) — the change is to the blessed pattern. C2 (rename priority -> force_flush). PubSubClient.publish() renames the kwarg to force_flush. The kwarg never implied ordering — it just forces an immediate flush of the buffer — so the new name is accurate. Internal test helpers, comments, and docs updated. C3 (split create / from_activity). PubSubClient.create() now requires explicit (client, workflow_id); the silent auto-detect path is gone. A new PubSubClient.from_activity() classmethod pulls both from the current activity context. This removes the failure mode where omitting args outside an activity produced a confusing runtime error. Activity-side test helpers migrated to from_activity(). C5 (truncation rationale). DESIGN-v2.md section 10 no longer describes truncation as "deferred to a future iteration" — the feature is implemented, and voice streaming workflows have shown it's needed in practice. Because CAN is the standard pattern for long-running workflows, workflow history size is not the binding constraint; in-memory log growth between CAN boundaries is. The section now says so. Tests pass (23/23, pytest tests/contrib/pubsub/). Co-Authored-By: Claude Opus 4.7 (1M context) * Migrate pubsub payloads from opaque bytes to Temporal Payload Addresses PR #1423 review comment C4: expose Temporal Payload at the PubSubItem / PublishEntry boundary so subscribers can decode via subscribe(result_type=T), matching execute_update(result_type=...). API changes: - PubSubMixin.publish(topic, value): value is any payload-convertible object or a pre-built Payload (zero-copy). - PubSubClient.publish(topic, value, force_flush=False): same shape; defers conversion to flush time, batching cost amortized. - PubSubClient.subscribe(topics, *, result_type=None, ...): yields PubSubItem whose data is a Payload by default, or the decoded result_type when one is supplied. - PubSubItem.data is now Any (Payload | decoded value). Wire format and codec decisions: - PublishEntry.data / _WireItem.data are base64(Payload.SerializeToString()). Nested Payload inside a dataclass fails with "Object of type Payload is not JSON serializable" because the default JSON converter only special-cases top-level Payloads on signal/update args. The base64-of-serialized- proto wire format keeps the JSON envelope while preserving Payload.metadata end-to-end. Round-trip is guarded by the new test_payload_roundtrip_prototype.py tests. - Per-item encoding uses the SYNC payload converter (workflow.payload_ converter() on the mixin, client.data_converter.payload_converter on the client). The codec chain (encryption, PII-redaction, compression) is NOT invoked per item — Temporal already runs the user's DataConverter.encode on the __pubsub_publish signal envelope and the __pubsub_poll update response, so running the codec per item as well would double-encrypt/compress (and compressing already-encrypted bytes defeats the codec). The per-item Payload still carries encoding metadata ("encoding: json/plain", "messageType: ...") which is what the subscribe(result_type=T) decode path actually needs. - Workflow-side and client-side are now codec-symmetric; the previously-feared asymmetry does not exist. Tests: - Existing pubsub tests updated: collect_items takes the Client (needed to reach the payload converter), subscribe calls pass result_type=bytes where they compare against raw bytes. - Added test_structured_type_round_trip: workflow publishes dataclass values, subscriber decodes via result_type= — exercises the primary value-add of the migration. - Added test_payload_roundtrip_prototype.py as a regression guard for the wire-format choice: one test asserts nested Payload in a dataclass fails, another asserts base64(proto(Payload)) round-trips. All 26 pubsub tests pass. Co-Authored-By: Claude Opus 4.7 (1M context) * Bump sdk-core submodule to match temporalio-client 0.2.0 The bridge's Cargo.toml requires temporalio-client = "0.2.0" (set in 68561ee7), but commit c4ec6e70 ("Update pubsub README: rename for_workflow → create") inadvertently reverted the sdk-core submodule pointer to f188eb53, a commit that still had the client crate at 0.1.0. This left uv/maturin unable to build the Rust bridge on this branch: Cargo resolves the requirement against the vendored crate and rejects 0.1.0 for the "^0.2.0" spec. Restore the pointer to b544f95d — the commit origin/main uses with the same Cargo.toml, so the bridge and its sdk-core workspace are consistent again. No Python code changes; purely a submodule pointer fix. Co-Authored-By: Claude Opus 4.7 (1M context) * Port Notion narrative into DESIGN-v2.md and add sync-policy note Reconciles DESIGN-v2.md with the "Streaming API Design Considerations" Notion page so both track the authoritative Python implementation. The Notion page had richer narrative (durable-streams framing, pull-vs-push reasoning, one-way-door callouts, offset-options comparison table, alternatives-considered list for wire evolution, end-to-end-principle writeup). This change brings that into the in-repo doc. Changes: - New top-of-doc note establishing that the Python code in sdk-python/temporalio/contrib/pubsub/ is authoritative; both DESIGN-v2.md and the Notion page track it. - New Decision #1 "Durable streams" explaining the durable-by-default choice vs ephemeral streams (simpler model, reliability, correctness). Existing decisions renumbered. - Decision #4 (Global offsets) gains the 6-option ecosystem comparison table and a one-way-door callout flagging the wire-protocol commitment. - Decision #9 (Subscription is poll-based) expanded with the pull-vs-push trade-off (back-pressure, subscriber-controlled read position, data-at-rest) and explicit "both layers are exposed" framing. - New "Design Principles" section with the Saltzer/Reed/Clark end-to-end-dedup framing and the "retries remain in the log" contract, with a one-way-door callout on the append-only-of-attempts contract. - Compatibility section gains a full alternatives-considered list (version field, versioned handler names, protocol negotiation, SDK version embedding, accepting silent incompatibility) and a two-part one-way-door callout on immutable handler names + no version field. - New "Ecosystem analogs" section: a compact one-paragraph summary (NATS JetStream for offsets, Kafka for idempotent producers, Redis for blocking pull, Workflow SDK as the durable-execution peer) with a pointer to the Notion page for the full comparison tables. The Notion page itself is still behind on the Payload migration (Decision #5 "Opaque message payloads" needs rewriting, API signatures still show priority= and data: bytes). That update is deferred pending resolution of an open reviewer discussion on activity-retry/dedup (discussion 34a8fc56-7738-808c-b29b-001c5066e9d2) whose substance overlaps with the Decision #5 rewrite. Co-Authored-By: Claude Opus 4.7 (1M context) * Apply pubsub API renames to ADK/OpenAI streaming plugins Follow-ups missed when the contrib/pubsub refactor renamed PubSubClient.create(batch_interval=...) → PubSubClient.from_activity(...) and publish(..., priority=True) → publish(..., force_flush=True). Both plugin activities still called the old signatures and failed at runtime with TypeError on the first publish. Also update the streaming tests to pass result_type=bytes to pubsub.subscribe(); after the bytes→Payload migration, item.data is a raw Payload unless a result_type is specified, so json.loads(item.data) was TypeErroring. Co-Authored-By: Claude Opus 4.7 (1M context) * Replace PubSubMixin with PubSub dynamic handler registration Users no longer inherit a mixin class. Instead, they construct `PubSub(prior_state=...)` from `@workflow.init`; the constructor registers the `__pubsub_publish` signal, `__pubsub_poll` update (with validator), and `__pubsub_offset` query handlers dynamically via `workflow.set_signal_handler`, `set_update_handler`, and `set_query_handler`. The pub/sub wire contract (handler names, payload shapes, offset semantics) is unchanged. This matches how other-language SDKs will express the same pattern — imperative handler registration from inside the workflow body rather than inheritance — and lets the workflow retain its normal single base class. The constructor raises RuntimeError in two misuse cases: 1. Called twice on the same workflow — detected via `workflow.get_signal_handler("__pubsub_publish") is not None`. 2. Called from anywhere other than `__init__` — detected by inspecting the immediate caller's frame. History-length based detection was tried first but has two false positives (pre-start signals inflate first-task history length beyond 3, and cache eviction legitimately re-runs `__init__` with a higher current history length), so frame inspection is the correct mechanism. Method renames on the broker (no longer needed as `_pubsub_*` prefixes now that they live on a dedicated object): init_pubsub(prior_state=None) -> PubSub(prior_state=None) self.publish(topic, value) -> self.pubsub.publish(topic, value) self.get_pubsub_state(...) -> self.pubsub.get_state(...) self.drain_pubsub() -> self.pubsub.drain() self.truncate_pubsub(up_to) -> self.pubsub.truncate(up_to) Co-Authored-By: Claude Opus 4.7 (1M context) * Document per-poll fan-out and list future-work items in DESIGN-v2 Fan-out: add a subsection under Design Decision 9 explaining that each __pubsub_poll is an independent update RPC with no shared delivery, so items destined for N subscribers cross the wire N times. Spells out the three concurrent-subscriber shapes (same topic/offset, different offsets, disjoint topics) and the rationale for the per-poll model. Future Work: new top-level section with three items — shared workflow fan-out (optimization of the above), workflow-defined filters and transforms, and a safe workflow-side subscribe() API. Each entry names the relevant design questions left open rather than prescribing an implementation. Co-Authored-By: Claude Opus 4.7 (1M context) * openai_agents: publish raw stream events, drop normalization layer The streaming activity previously maintained a normalization layer: ~50 lines of if/elif mapping OpenAI event types (response.output_text.delta, response.reasoning_summary_*, etc.) to custom app event names (TEXT_DELTA, THINKING_*, LLM_CALL_START/COMPLETE), plus text-delta accumulation into a synthesized TEXT_COMPLETE, plus a function-call filter on output_item.added. That normalization made sense when a shared UI consumed events from multiple providers, but each provider-plugin should expose its native event stream and let consumers render idiomatically. The activity now publishes each yielded OpenAI event as its Pydantic JSON and returns the ModelResponse built from the final ResponseCompletedEvent — three lines inside the stream loop. Also factored out three helpers shared between the streaming and non-streaming activities (both paths were duplicating them verbatim): _build_tools_and_handoffs — tool/handoff reconstruction from dataclass form _build_tool — single tool-by-type dispatch _raise_for_openai_status — APIStatusError -> retry-posture translation The local-activity guard in _temporal_model_stub.py gains a comment explaining the two reasons streaming can't use local activities (no heartbeat channel, no pubsub signal context from the activity). Tests: replaced the normalized-event assertions with raw-event assertions; dropped the rich-dispatcher coverage test since there's no dispatcher left to cover. 115 passing / 16 skipped. Downstream impact: consumers that depend on the normalized event names (temporal-streaming-agents-samples frontend, shared-frontend hooks) need to switch on raw OpenAI event types instead. Co-Authored-By: Claude Opus 4.7 (1M context) * Fix lint findings from CI (ruff format, pyright, pydocstyle) - ruff format: apply formatter to auto-generated style changes. - pyright: replace dict literals for Response.text/usage with the pydantic model types (ResponseTextConfig, ResponseUsage, InputTokensDetails, OutputTokensDetails). - basedpyright: suppress reportUnusedFunction on the private _encode_payload/_decode_payload helpers in pubsub._types (they are used from sibling modules, which basedpyright does not credit) and reportUnusedParameter on the CAN workflow run() input arg. - pydocstyle: add docstrings to PubSubClient.__aenter__/__aexit__. * Fix Python 3.10 lint/type errors in pubsub tests - typing.Self requires 3.11; import from typing_extensions like the rest of the SDK does. - asyncio.timeout requires 3.11; fall back to async_timeout.timeout on 3.10 (async_timeout is an aiohttp transitive dep there). * pubsub tests: also suppress reportUnreachable on the 3.11 import branch On Python 3.10 CI, the `if sys.version_info >= (3, 11):` branch is what basedpyright flags as unreachable. The ignore needs to be on both branches so it is silent under every Python version in the matrix. * pubsub tests: attach reportUnreachable ignore to the import-stmt line The previous attempt placed the pragma on the indented `timeout as _async_timeout` line, but basedpyright reports reportUnreachable against the outer `from ... import (` line (the block-opening statement), so the pragma had no effect. Move the ignore up to the import line and combine with reportMissingImports there. Locally verified clean on Python 3.10, 3.11, and 3.14 via `uv run --python poe lint`. * pubsub: fix dynamic-signal-vs-update race and pydoctor cross-ref Under parallel test load we saw test_poll_truncated_offset_returns_ application_error fail with "Cannot truncate to offset 3: only 0 items exist" — traced to an activation-ordering race. When a workflow receives an activation containing [InitializeWorkflow, Signal(__pubsub_publish), Update(truncate)] in one batch, _WorkflowInstanceImpl.activate groups signals and updates into job_sets[1] and init into job_sets[2]. During _apply of job_sets[1], __pubsub_publish (a dynamic signal registered inside PubSub.__init__) has no handler yet, so it is buffered; truncate is class-level @workflow.update, found in self._updates at activation time, and its task is created immediately and queued in self._ready. _run_once then lazy-instantiates the workflow, __init__ runs set_signal_handler which dispatches the buffered signal via a new task appended to self._ready after the update task. FIFO event-loop dispatch runs truncate against an empty log first; the handler raised ValueError which poisoned the whole workflow task. Fixes: 1. temporalio/contrib/pubsub/_broker.py — PubSub.truncate now raises ApplicationError(type="TruncateOutOfRange", non_retryable=True) instead of ValueError when the offset is past the end of the log. Matches what _on_poll already does for TruncatedOffset and lets update handlers surface the error cleanly without failing the task. 2. tests/contrib/pubsub/test_pubsub.py — TruncateWorkflow seeds the log from @workflow.init with a prepub_count arg. Three tests (test_poll_truncated_offset_returns_application_error, test_subscribe_recovers_from_truncation, test_truncate_pubsub) now pass prepub_count=5 to start_workflow rather than sending a client-side __pubsub_publish signal, sidestepping the dynamic- signal-before-init race entirely. 3. Tighten the poll-after-truncation assertion to check cause.type == "TruncatedOffset", and add test_truncate_past_end_raises_application_error to cover the new TruncateOutOfRange branch of PubSub.truncate. 4. temporalio/contrib/pubsub/_client.py — pydoctor couldn't resolve :class:\`~temporalio.api.common.v1.Payload\` against the generated proto module and was failing the docs build; switched that one cross-ref to plain backticks. Verified locally on Python 3.10 and 3.14: full lint clean, docs build clean, and pubsub tests pass 27/27 across three parallel runs. * pubsub: document sync-handler/publish race with asyncio.sleep(0) recipe Add a visible "Gotcha" section to the contrib/pubsub README covering the case where a custom synchronous update or signal handler reads PubSub state and races a same-activation __pubsub_publish signal. The race is inherent to registering __pubsub_publish dynamically from @workflow.init: on the first activation the signal is buffered until __init__ runs, and any class-level sync handler scheduled in the same activation observes pre-publish state. Framing in the README distinguishes the two cases where users do or don't need to care: - Independent producer/consumer shape (the common PubSub use): the handler already has to tolerate out-of-order arrival for reasons unrelated to this race, so no recipe is required. - Sequential same-client publish->update ordering: use the recipe. Recipe is a one-line "await asyncio.sleep(0)" at the top of the handler, which is a pure asyncio yield with no Temporal timer, no history events, and no server round trip. Explicit call-out that workflow.sleep(0) is not a substitute. Also extend SIGNAL-UPDATE-RACE.md with a "Zooming out" section that explains why the application layer typically subsumes this race, and update the Recommendation to treat the SDK-level dispatch fix (option 4) as optional follow-up rather than a must-fix. The PubSub class docstring gets a short note pointing at the README. Co-Authored-By: Claude Opus 4.7 (1M context) * pubsub tests: switch TruncateWorkflow.truncate to the async recipe The existing TruncateWorkflow sidestepped the dynamic-signal-vs-update race by seeding the log from @workflow.init via prepub_count. That kept CI green but meant the test workflow did not exercise the pattern the README now asks users to follow (await asyncio.sleep(0) at the top of sync-shaped handlers reading PubSub state). Make truncate async with the recipe so the test workflow is a living example of the documented pattern, and simplify the docstring now that the race is closed in the handler rather than avoided via init-time seeding. prepub_count is kept as a convenience for the error-path tests that just need deterministic log content. All four truncate tests still pass. Co-Authored-By: Claude Opus 4.7 (1M context) * pubsub: add public async flush() barrier flush() is an explicit synchronization point: it returns once items buffered at call time have been signaled to the workflow and acknowledged by the server, and returns immediately when the buffer is empty. It complements the two existing flush mechanisms (force_flush=True on publish, context-manager exit) for the case where the caller needs proof that prior publications landed but the moment doesn't naturally correspond to a specific event. Implementation reuses _flush() under the existing flush_lock, looped while either _pending or _buffer is non-empty so the pending-vs-buffer staging in _flush() can drain in one call. DESIGN-v2 updates the API table and replaces the "no public flush()" paragraph with a section framing the three complementary flush mechanisms and when each is appropriate. Test test_explicit_flush_barrier exercises the documented contract: empty-buffer no-op, flush as a barrier with batch_interval=60s so a regression hangs rather than passing on the timer, and idempotent second flush. Co-Authored-By: Claude Opus 4.7 (1M context) * pubsub: document migration to server-side request_id dedup Workflow-side (publisher_id, sequence) dedup is a polyfill for two gaps in Temporal's built-in signal request_id dedup: 1. The Python SDK does not expose request_id on WorkflowHandle.signal(), so cross-_flush() retries always allocate a fresh request_id and bypass server-side dedup even within a single run. 2. pendingSignalRequestedIDs is per-run mutable state and is not copied across continue-as-new, so retries that straddle CAN are accepted as fresh signals (verified empirically on dev server and Temporal Cloud — see experiments/can-signal-dup/README.md). When (1) and (2) are both fixed, the workflow-side check becomes redundant. The dedup keys at both layers already align on (publisher_id, sequence), so the migration is mechanical — pin request_id=f"{publisher_id}:{seq}" in _flush(), drop the dedup branch in _on_publish, retire publisher_sequences / publisher_last_seen / publisher_ttl from PubSubState in a follow-up wire-format pass. Adds a "Future Work" subsection in DESIGN-v2 capturing the prerequisites, the diff (what changes / stays / goes), and the rollout sequencing. Adds short pointer comments at the two code sites that would change so a future maintainer encounters the design note at the right place. No behavior change. Co-Authored-By: Claude Opus 4.7 (1M context) * pubsub: accept a single string for subscribe(topics=...) Convenience for single-topic subscribers — the common case. The previous signature required wrapping a single topic in a list, which is noisy at every call site. Internally we normalize to a list before issuing the poll update; behavior for None / empty list / multi-topic list is unchanged. Co-Authored-By: Claude Opus 4.7 (1M context) * pubsub: prefix internal handler names with __temporal_ Rename the wire-level handler identifiers to follow the existing __temporal_ convention (__temporal_workflow_metadata, __temporal_activity_definition, etc.) so they are clearly recognizable as Temporal-internal and won't collide with user-defined handlers: __pubsub_publish -> __temporal_pubsub_publish __pubsub_poll -> __temporal_pubsub_poll __pubsub_offset -> __temporal_pubsub_offset Updates the broker/client implementation, tests, and design docs. Co-Authored-By: Claude Opus 4.7 (1M context) * pubsub: clean up three lint suppressions flagged by codex review - _broker.py:_validate_poll — rename `payload` to `_payload`, drop `del payload` and `# noqa: ARG002`. The noqa was dead code: CI runs only `ruff check --select I` (import sort), so ARG rules never fire. Underscore prefix silences basedpyright's reportUnusedParameter cleanly. - test_pubsub.py:ContinueAsNewTypedWorkflow.run — rename `input` to `_input` with `del _input`, drop the `type:ignore`. Now matches the existing `_prepub_count` pattern at TruncateWorkflow.run for the same @workflow.init/@workflow.run signature constraint. - test_pubsub.py async_timeout import — declare `async-timeout` as an explicit dev dep gated on `python_version < '3.11'`, drop the `reportMissingImports` half of the test pragma. Closes the audit gap of relying on aiohttp's transitive on 3.10. Kept the `reportUnreachable` ignores — still needed because basedpyright resolves `sys.version_info` against its own runtime, not the matrix Python. Verified `poe lint` clean on Python 3.10, 3.11, 3.14. Co-Authored-By: Claude Opus 4.7 (1M context) * pubsub: add PubSub.continue_as_new helper Packages the drain + wait-for-handlers + workflow.continue_as_new recipe behind `await self.pubsub.continue_as_new(build_args)`. The builder is typed `Callable[[PubSubState], Sequence[Any]]` and is invoked after drain stabilizes with the post-drain state as its single argument, so the snapshot ordering is structural rather than documented-by-prose. The helper deliberately does not mirror workflow.continue_as_new's 12-param signature; workflows that need to override task_queue, retry_policy, etc. fall back to the explicit drain/wait/CAN recipe. Reverses the 2026-04-24 rejection in DESIGN-v2 Future Work: the state-bound-builder shape resolves the "second footgun" objection to the zero-arg-lambda form (caller could still write self.pubsub.get_state() inside the lambda; with a state parameter the helper controls the read). Co-Authored-By: Claude Opus 4.7 (1M context) * pubsub: switch timing parameters to timedelta Brian noted on PR #1423 that timedelta is the convention in this codebase for duration parameters. Migrating the public API surface: - ``PubSubClient`` constructor / ``create`` / ``from_activity``: ``batch_interval`` and ``max_retry_duration`` now take ``timedelta`` (previously ``float`` seconds). - ``PubSubClient.subscribe``: ``poll_cooldown`` now takes ``timedelta`` (previously ``float`` seconds). - ``PubSub.get_state`` and ``PubSub.continue_as_new``: ``publisher_ttl`` now takes ``timedelta`` (previously ``float`` seconds). Internals continue to use ``.total_seconds()`` where needed (asyncio timeouts, comparisons against ``workflow.time()``). The TTL test workflow query keeps its arg as ``float`` seconds and constructs the ``timedelta`` inside the handler — query payloads use the default JSON converter, which does not serialize ``timedelta``. Docs and examples in DESIGN-v2.md and README.md updated to use ``timedelta(...)`` literals. This is contrib/preview, so no float-compat shim — callers that previously passed numeric seconds need to migrate. Co-Authored-By: Claude Opus 4.7 (1M context) * openai-agents: hook stream_response, opt in via Runner.run_streamed Previously, streaming was a plugin-level flag (``enable_streaming``) that silently rerouted ``Runner.run`` to a streaming activity which synthesized a ``ModelResponse`` from the terminal ``ResponseCompletedEvent`` and dropped intermediate stream events. Reviewers flagged two problems with that shape: 1. ``Runner.run`` callers did not opt into streaming behavior — flipping the plugin flag elsewhere changed what a workflow saw at runtime. That is the kind of spooky-action-at-a-distance that produces non-determinism if the flag is changed mid-history. 2. ``Model.stream_response`` is the natural hookpoint for streaming in the agents SDK. ``Runner.run_streamed`` already exposes the correct user-facing API — we just had not implemented it. This commit reworks both: - ``_TemporalModelStub.stream_response`` now executes the streaming activity and yields each event from its return list (an async generator). ``get_response`` keeps the non-streaming path; the ``enable_streaming`` branch is gone. - ``invoke_model_activity_streaming`` returns ``list[TResponseStreamEvent]`` rather than a synthesized ``ModelResponse``, and publishes the raw events to the configured pub/sub topic via ``pubsub.publish(topic, event)`` (relying on the payload converter rather than manual JSON encoding). - ``TemporalOpenAIRunner.run_streamed`` performs the same agent conversion + sandbox checks as ``run`` and forwards to the underlying ``AgentRunner.run_streamed``. Its ``run_loop_task`` is wrapped to mirror the ``AgentsException -> AgentsWorkflowError`` rewrap done in ``run`` (the plugin registers ``AgentsWorkflowError`` in ``workflow_failure_exception_types``; without the wrap, durable failures would surface as retrying workflow-task errors instead of terminal workflow failures). - The shared ``ActivityModelInput``-building logic is factored into ``_TemporalModelStub._build_activity_input`` so the two methods do not duplicate it. New plugin config on ``ModelActivityParameters``: - ``streaming_event_topic: str | None = "events"`` — set to ``None`` to skip pub/sub entirely (no ``PubSubClient`` constructed; workflows that consume only via ``stream_events()`` then need no broker). - ``streaming_event_batch_interval: timedelta = timedelta(milliseconds=100)`` — interval for the pub/sub publisher's flusher. The streaming activity keeps the ``@_auto_heartbeater`` decorator so long initial-token latency or pauses between chunks do not trip ``heartbeat_timeout``. Explicit per-event ``activity.heartbeat()`` is removed as redundant. Status-code retry block in ``_raise_for_openai_status`` now carries a short comment explaining 408/409/429 (Brian's review note). Tests (``test_openai_streaming.py``) switch to ``Runner.run_streamed`` and verify that both the workflow-side iteration (via ``stream_events()`` exposed through a query) and the pub/sub side channel observe the same native OpenAI events. A separate test covers ``streaming_event_topic=None``. Co-Authored-By: Claude Opus 4.7 (1M context) * google-adk: honor stream=True, publish raw LlmResponse chunks Mirrors the OpenAI-side rework: streaming opt-in moves from a constructor flag to the SDK-native API, and the streaming activity publishes raw response objects rather than synthesizing custom event types. - ``TemporalModel.generate_content_async(stream=True)`` is now honored. Users opt into streaming via the ADK-native API path — e.g. ``RunConfig(streaming_mode=StreamingMode.SSE)`` on ``runner.run_async`` — rather than a plugin-level ``streaming`` flag (which is removed). - ``invoke_model_streaming`` publishes each ``LlmResponse`` directly via ``pubsub.publish(topic, response)``. The previously-synthesized ``LLM_CALL_START`` / ``TEXT_DELTA`` / ``TOOL_CALL_START`` / ``TEXT_COMPLETE`` / ``LLM_CALL_COMPLETE`` events are gone — those semantic distinctions are speculative until the lifecycle hook design is settled (deferred to a follow-up). Raw publishes also remove the redundant double ``force_flush`` and the unused ``logger`` import that the review flagged. New constructor config on ``TemporalModel``: - ``streaming_event_topic: str | None = "events"`` — set to ``None`` to skip pub/sub entirely. - ``streaming_event_batch_interval: timedelta = timedelta(milliseconds=100)`` — interval for the publisher's flusher. ``_plugin.py`` annotates the activities list as ``list[Callable[..., Any]]`` because ``invoke_model`` and ``invoke_model_streaming`` now have different signatures (streaming takes the topic and batch interval), so type inference on the bare list literal would not satisfy ``SimplePlugin``'s parameter type. Tests (``test_adk_streaming.py``) opt into streaming via ``RunConfig(streaming_mode=StreamingMode.SSE)`` and subscribe to the pub/sub topic with ``result_type=LlmResponse``, asserting the raw chunks round-trip intact. Co-Authored-By: Claude Opus 4.7 (1M context) * pubsub: README CAN example uses generic AppState carrier Replace the ad-hoc items_processed counter with a nested AppState dataclass so the snapshot pattern reads symmetrically: app_state beside pubsub_state, each round-tripped the same way. Also rename the build_args lambda parameter to pubsub_state to disambiguate which snapshot it carries. Co-Authored-By: Claude Opus 4.7 (1M context) * PR #1423 mechanical cleanup from review Four small fixes from the PR review thread: - ``_raise_for_openai_status``: consolidate the two ``raise ApplicationError`` branches into one with ``non_retryable=not retryable``. The retryable / non-retryable case now picks a label for the message string instead of duplicating the raise. Suggested by Brian (3150542100). - ``PubSubClient._flush``: encode the buffer before clearing it. The prior order (``self._buffer = []`` then ``_encode_buffer(raw)``) silently dropped items if the payload converter raised — items were already detached from ``self._buffer`` and unrecoverable. Now encoding is attempted first; on exception the buffer is preserved for inspection or retry. Caught by Copilot (3150579181). - ``PubSubClient.from_activity``: replace the ``assert workflow_id is not None`` check with an explicit ``raise RuntimeError``. ``-O`` strips asserts, which would turn the validation into a ``None`` propagation rather than a clear error. Caught by Copilot (3150579197). - ``_types.py`` and ``__init__.py`` module docstrings: rewrite the codec-scope wording. The previous phrasing implied the codec chain runs per item, but the implementation runs codec once on the signal/update envelope (per-item ``Payload`` is built by the payload converter, not the codec chain). Caught by Copilot (3150579211, 3150579227). Co-Authored-By: Claude Opus 4.7 (1M context) * pubsub: import Sequence from collections.abc basedpyright on Python 3.10+ flags `typing.Sequence` as deprecated (reportDeprecated). Switch to `collections.abc.Sequence`, which is the canonical source post-PEP 585. Co-Authored-By: Claude Opus 4.7 (1M context) * pubsub: merge per-publisher dedup state into PublisherState Replace parallel publisher_sequences/publisher_last_seen dicts on PubSubState with a single publishers: dict[str, PublisherState], encoding the "every publisher has both fields" invariant in the type and removing a defensive .get(pid, 0.0) lookup at TTL-prune time. Switch last_seen from float (Unix seconds via workflow.time()) to datetime (workflow.now()), so TTL pruning can compare directly against the publisher_ttl: timedelta parameter without a total_seconds() conversion. Co-Authored-By: Claude Opus 4.7 (1M context) * pubsub: move SIGNAL-UPDATE-RACE.md analysis out of contrib The activation-ordering analysis is project-internal review context, not something to ship in the SDK. Moved to the streaming-comparisons project root; the user-facing recipe stays in the contrib README. Co-Authored-By: Claude Opus 4.7 (1M context) * pubsub: soften codec chain wording Treat encryption/compression as examples of codec transforms rather than enumerating "PII-redaction" as a distinct named feature. The codec chain runs whatever transforms the user has configured; the docs shouldn't imply a closed list. Co-Authored-By: Claude Opus 4.7 (1M context) * update publish example * contrib: mark pubsub and streaming surfaces as experimental The new pubsub module and the streaming entry points added to the openai-agents and google-adk plugins (commits c3370a7c, 88dac52b) lack the docstring-level experimental warning that other contrib modules carry (langsmith, opentelemetry). Add it on the public surface so users see the warning in the API docs and IDE tooltips. - pubsub: package docstring, ``PubSub``, ``PubSubClient``, and every exported dataclass (``PubSubItem``, ``PublishEntry``, ``PublishInput``, ``PollInput``, ``PollResult``, ``PublisherState``, ``PubSubState``); README banner. - openai-agents streaming: ``Runner.run_streamed``, ``ModelActivity.invoke_model_activity_streaming``, ``ModelActivityParameters.streaming_event_topic``, ``ModelActivityParameters.streaming_event_batch_interval``. - google-adk streaming: ``invoke_model_streaming``, ``TemporalModel.__init__`` ``streaming_event_*`` args, ``TemporalModel.generate_content_async`` ``stream`` arg. The openai-agents README also still claimed streaming was unsupported ("Streaming and voice agents are not supported", "does not presently support streaming", Streaming row marked No). Replace with a new ``## Streaming`` section showing ``Runner.run_streamed`` usage and the ``use_local_activity`` incompatibility, and update the support table to ``Yes (experimental)``. Clarify in the prose that ``RunResultStreaming.stream_events()`` wraps native events as ``RawResponsesStreamEvent.data``, while pubsub subscribers receive the unwrapped events directly. Voice support table: realtime is structurally incompatible (websocket sessions don't survive worker loss) and stays ``No``, but ``VoicePipeline`` runs in the user's process and can delegate ``VoiceWorkflowBase.run`` to a Temporal workflow that calls ``Runner.run`` / ``run_streamed``, so flip pipelines to ``Yes`` with a footnote explaining the composition pattern. Co-Authored-By: Claude Opus 4.7 (1M context) * openai-agents: drop unused logger imports Co-Authored-By: Claude Opus 4.7 (1M context) * pubsub: refresh DESIGN-v2 to match current implementation Document the caller-frame init guard, signal/update race recipe, truncate semantics, wire-form log snapshot, and JSON-converter scope. Replace lingering "mixin" references with PubSub and update the dedup-removal recipe to match _broker.py. Co-Authored-By: Claude Opus 4.7 (1M context) * openai-agents: factor workflow-only setup into _prepare_workflow_run Runner.run() and Runner.run_streamed() duplicated ~80 lines of workflow-only setup: callable-tool rejection, MCP server type validation, SQLiteSession rejection, RunConfig defaulting, string-model -> _TemporalModelStub replacement, sandbox configuration validation, and the recursive _convert_agent walk over the handoff graph. Drift between the two paths was a real risk — a fix to one would not automatically apply to the other. Extract _prepare_workflow_run, called by both. The helper mutates kwargs in place (writing back the rewritten run_config) and returns the converted starting agent. Both call sites then splat **kwargs into the underlying SDK runner. Side effect: run() previously forwarded a hand-maintained whitelist of named kwargs (context, max_turns, hooks, run_config, previous_response_id, session) and silently dropped the other RunOptions keys — error_handlers, auto_previous_response_id, conversation_id. The splat shape forwards the full RunOptions surface, matching what a non-workflow caller would see. run_streamed() also tightens its kwargs type from **kwargs: Any to **kwargs: Unpack[RunOptions[TContext]], matching run(). Co-Authored-By: Claude Opus 4.7 (1M context) * contrib: default streaming_event_topic to None for opt-in publishing Both openai_agents.ModelActivityParameters and google_adk_agents. TemporalModel previously defaulted streaming_event_topic to "events". That meant any workflow using Runner.run_streamed (OpenAI) or generate_content_async(stream=True) (ADK) would silently publish every stream event to topic "events" — even if the workflow never hosted a PubSub broker, in which case the publish signals were unhandled and dropped. Pydantic-ai's TemporalModel already defaults the same option to None (opt-in). This commit aligns the other two plugins with that shape: publishing is now an explicit opt-in, set the topic to enable. Tests that exercise the publish path now set streaming_event_topic="events" explicitly. The OpenAI README's streaming snippet no longer constructs a PubSub broker (the workflow- side stream_events() iteration doesn't need one); a follow-up paragraph documents the explicit OpenAIAgentsPlugin(...) config required for external publishing. Co-Authored-By: Claude Opus 4.7 (1M context) * contrib: rename pubsub module to workflow_stream Selected feature name is "Workflow Streams" (see docs/rename-to-workflow-streams.md and docs/naming-analysis.md in the streaming-comparisons superrepo). The contrib module, classes, wire- protocol handlers, and tests are renamed in one atomic change so the build stays green; cross-module callers in openai_agents and google_adk_agents are updated in the same commit because they import WorkflowStreamClient directly. Module: temporalio.contrib.pubsub -> temporalio.contrib.workflow_stream Classes: PubSub -> WorkflowStream PubSubClient -> WorkflowStreamClient PubSubState -> WorkflowStreamState PubSubItem -> WorkflowStreamItem _WireItem -> _WorkflowStreamWireItem Wire handlers: __temporal_pubsub_publish -> __temporal_workflow_stream_publish __temporal_pubsub_poll -> __temporal_workflow_stream_poll __temporal_pubsub_offset -> __temporal_workflow_stream_offset File rename: _broker.py -> _stream.py (the class is the stream itself, not a workflow; "broker" carried pub/sub framing) Method verbs publish/subscribe stay literal per the rename doc. The operation-level dataclasses PublishEntry/PublishInput/PollInput/ PollResult/PublisherState are also kept bare for parity with the verbs; the doc's mapping for PublishEntry is intentionally not followed. Module path is singular workflow_stream (not plural workflow_streams as in the rename doc) to match every other single-feature contrib module in sdk-python (aws, langsmith, opentelemetry, pubsub, pydantic) and sdk-typescript (activity, client, worker, workflow, contrib-pubsub). Plurals in both SDKs are reserved for genuine collections. The wire-handler rename does break compatibility with any in-flight workflow; per the rename doc that is acceptable since this contrib has not been publicly released and the demo app rebuilds against the new SDK in a follow-up PR. The whitespace-only edit to openai_agents/_mcp.py is a pre-existing lint failure picked up by ruff --fix during this work; flagged here because it is unrelated to the rename. Co-Authored-By: Claude Opus 4.7 (1M context) * workflow_stream: rename DESIGN-v2.md to DESIGN.md The "v2" suffix was a holdover from when an earlier design was kept alongside. There is now a single canonical design document; the filename should match. Title and the file-tree code block inside the doc are also updated; remaining "v2" references in the body refer to hypothetical future protocol versions, not to this document. Co-Authored-By: Claude Opus 4.7 (1M context) * contrib: tighten OpenAI/ADK streaming tests, drop redundant cases Removed two non-streaming tests already covered by the main test files (test_hello_world_agent in test_openai.py, test_single_agent in test_google_adk_agents.py) and a dead TruncatedStreamingTestModel class. Strengthened the remaining streaming tests: - OpenAI workflow-side assertion now requires exact ordered match against the published list instead of `in` membership. - OpenAI `streaming_event_topic=None` test registers a WorkflowStream and asserts offset==0 to actually prove no publishing occurred. - ADK StreamingTestModel raises if called with stream=False, so a regression that drops the flag fails the test. - ADK final-result assertion checks `result == "world!"` instead of the vacuous `result is not None`. Co-Authored-By: Claude Opus 4.7 (1M context) * workflow_stream: clarify activity-side publishing in README Updates the intro paragraph to mention "associated Activities" alongside workflows, and adds a one-line note in the activity-side section that the target workflow must construct a WorkflowStream from @workflow.init or publish signals are dropped. The dropped-signal warning was already in the OpenAI/ADK plugin docstrings; this restates it where someone landing on the activity-side example would see it. Co-Authored-By: Claude Opus 4.7 (1M context) * workflow_stream: post-rename docs and test cleanup - DESIGN.md: redraw architecture diagram so handler names and state fields fit cleanly inside the box. Layout-only — no information changes. Update the in-doc test path reference for the rename below. - _types.py: drop a stale cross-reference to docs/pubsub-payload-migration.md (lives in a different repo and has not been renamed in lockstep). Remaining DESIGN.md §5 reference is sufficient. - Rename tests/contrib/workflow_stream/test_payload_roundtrip_prototype.py to test_payload_roundtrip.py. The file is no longer a prototype that de-risked the migration; it is the regression guard for the chosen Payload wire format. Filename now matches the docstring framing. Co-Authored-By: Claude Opus 4.7 (1M context) * workflow_stream: document standalone-activity usage and cover with tests from_activity() requires an activity scheduled by a workflow. Clarify the docstring, give a more actionable error message that points at create() with an explicit workflow id, and add a README example for the standalone-activity pattern. Three new integration tests exercise publish, subscribe, and the from_activity misuse error from activities started directly via Client.start_activity (skipped under the Java time-skipping server, which does not support that API). Co-Authored-By: Claude Opus 4.7 (1M context) * workflow_stream: ruff format test_workflow_stream.py Co-Authored-By: Claude Opus 4.7 (1M context) * workflow_stream: note deferred final-flag dedup-prune proposal Adds a Future Work pointer to docs/pubsub-design-analysis/final-flag-prune.md, which proposes a `final: bool` field on PublishInput so cleanly-exited publishers can have their dedup PublisherState pruned on a tighter schedule than the full publisher_ttl. Deferred for now. Co-Authored-By: Claude Opus 4.7 (1M context) * workflow_stream: trim README to point at docs.temporal.io The Workflow Streams user guide now lives at https://docs.temporal.io/develop/python/workflows/workflow-stream and is the primary reference. Replace the long quick-start / API-reference README with a short motivating summary, key technical highlights, and a prominent link to the docs site. DESIGN.md gets one extra sentence at the top reframing it as the contributor/internals doc and pointing readers at the user docs. * workflow_stream: drop in-tree DESIGN.md Reviewer flagged the 1419-line design doc as a maintenance burden — the implementation has already drifted from a few sections, and keeping it synchronized in-tree adds churn for every refactor. Move the canonical design notes out of the SDK; the README continues to point at the docs.temporal.io guide for users, and the design file is preserved in the streaming-comparisons project for future reference. Strip the ``DESIGN.md`` references from README.md and _types.py so no in-tree pointer remains. Co-Authored-By: Claude Opus 4.7 (1M context) * openai_agents: require streaming_event_topic and fail fast Address tconley feedback that (a) the non-streaming activity should not carry inputs only meaningful to the streaming path, and (b) invoking streaming with topic=None is a footgun with no real benefit (the workflow gets the chunked list batched at activity completion either way; "no-publish streaming" doesn't deliver real-time value to anyone). Changes: - Split ``ActivityModelInput`` (TypedDict) into the base shape used by ``invoke_model_activity`` and a ``StreamingActivityModelInput`` subclass with ``streaming_event_topic: Required[str]`` and the batch interval used only by ``invoke_model_activity_streaming``. The streaming activity now always opens a ``WorkflowStreamClient``; the ``topic is None`` branch and its docstring caveat are removed. - Validate at the runner before delegating to the agents framework. ``TemporalOpenAIRunner.run_streamed`` raises ``AgentsWorkflowError`` when ``model_params.streaming_event_topic`` is unset, or when ``use_local_activity=True`` (local activities have no heartbeat or signal channel). Both checks must happen here rather than inside the stub's ``stream_response``: the agents framework runs the model in a background task and silently captures errors into ``RunResultStreaming._stored_exception``, which can be lost when the queue completion sentinel is read before the task is observed as done — failing in the runner short-circuits before the framework starts the task. The stub keeps a defensive guard for direct callers. - Update ``ModelActivityParameters`` and the integration README so the documented contract matches the runtime behavior. - Replace the ``StreamingWithoutStreamTopicWorkflow`` test with ``StreamingRequiresTopicWorkflow`` covering the topic-missing path, and add ``test_streaming_rejects_local_activity`` for the use_local_activity case. Co-Authored-By: Claude Opus 4.7 (1M context) * google_adk_agents: single-input dataclass and required topic Address tconley feedback on the ADK streaming activity — activities should take a single dataclass input, and invoking streaming without a topic is a footgun for the same reasons as on the OpenAI side (the workflow only sees chunks batched at activity completion, so the "streaming without publishing" path delivers no real-time value). Changes: - Wrap ``invoke_model_streaming`` inputs in ``StreamingInvokeInput`` (llm_request + streaming_event_topic + streaming_event_batch_interval). Drop the ``topic is None`` branch; the activity always opens a ``WorkflowStreamClient`` and publishes each chunk. ``invoke_model`` (non-streaming) keeps its existing ``LlmRequest`` argument since that already satisfies the single-input convention. - Validate in ``TemporalModel.generate_content_async`` before scheduling the streaming activity. Raise ``ApplicationError(non_retryable=True)`` so the failure surfaces as a terminal workflow failure without needing plugin-level ``workflow_failure_exception_types`` registration. - Update the constructor docstring to reflect the now-required topic. - Add ``StreamingAdkRequiresTopicWorkflow`` plus ``test_streaming_requires_topic`` covering the no-topic path. Co-Authored-By: Claude Opus 4.7 (1M context) * workflow_stream: rename from_activity to from_within_activity Per PR review feedback (Sushisource), rename the WorkflowStreamClient classmethod and update all call sites, references, error messages, comments, and tests. The new name reads more clearly at the call site — it documents that the method must be invoked from inside an activity rather than that it builds something derived from one — and matches how we already describe it in the docstring ("must be called from within an activity"). * workflow_stream: default-decode in subscribe, RawValue for raw access Per PR review feedback, drop the special case where subscribe() with no result_type yields a raw Payload, and instead delegate to the payload converter's default Any decoding (the same behavior as signal/update/query handlers without a type hint). Callers that want the original Payload pass result_type=temporalio.common.RawValue, mirroring the standard Temporal convention. The only caller-visible change for typed callers is the no-result_type path: a JSON-converter consumer that previously got back a Payload now gets back a Python dict/list/scalar (or bytes for binary payloads). Heterogeneous-topic dispatchers relying on Payload.metadata should switch to result_type=RawValue and read item.data.payload.metadata. Adds a regression test covering both default decode (dict) and RawValue passthrough (Payload bytes preserved). * workflow_streams: rename module from workflow_stream Public surface moves from temporalio.contrib.workflow_stream to temporalio.contrib.workflow_streams. Internal signal/update/query names (__temporal_workflow_stream_*) are wire identifiers and stay unchanged so existing histories and mixed-version clients keep working. Co-Authored-By: Claude Opus 4.7 (1M context) * workflow_streams: introduce typed topic handles Add TopicHandle[T] (client-side: publish + subscribe) and WorkflowTopicHandle[T] (workflow-side: publish only), constructed via WorkflowStreamClient.topic(name, type=T) and WorkflowStream.topic(name, type=T) respectively. Each publisher instance binds a topic name to exactly one T; re-binding to a different type raises RuntimeError, and re-binding to the same type is idempotent. The check uses Python equality on the type object — primitives, dataclasses, generic aliases, and unions all compare structurally. No subtype/union-superset recognition; no cross-process coordination. Pre-built Payload values still pass through topic.publish regardless of the bound type (zero-copy fast path preserved); the signature accepts T | Payload to model this. typing.Any is the documented escape hatch for heterogeneous topics. The existing publish() methods are kept for now (delegated to a shared _publish_to_topic) and marked as preferred-replaced-by TopicHandle in their docstrings. A follow-up commit removes them and migrates call sites. Tests cover: workflow-side publish + client-side typed subscribe, client-side type-uniqueness and idempotency, in-workflow-init type-uniqueness via TopicHandleUniquenessWorkflow, and pre-built Payload passthrough on a typed handle. * workflow_streams: reject type=Payload on topic handles Per Codex review feedback on the topic-handle introduction commit: binding a topic to type=Payload would let publish work (via the existing isinstance(value, Payload) zero-copy path) but quietly break TopicHandle.subscribe — the payload converter has no Payload decode path, so JSON items would fail conversion and binary items would decode to bytes rather than Payload. Reject type=Payload at WorkflowStreamClient.topic() and WorkflowStream.topic() with a clear error pointing callers at the right idioms: type=typing.Any for heterogeneous topics, pre-built Payload values published via any-typed handle (zero- copy fast path), and result_type=RawValue on WorkflowStreamClient.subscribe for raw payload access. Adds a regression assertion to test_topic_handle_client_uniqueness and pulls a stray Payload-recommendation out of the topic() docstrings. * workflow_streams: remove WorkflowStream(Client).publish in favor of topic handles Drops the un-typed publish(topic, value) entry points on WorkflowStream and WorkflowStreamClient. Publishers now go through WorkflowStream.topic(name, type=T) and WorkflowStreamClient.topic(name, type=T) which return typed TopicHandle / WorkflowTopicHandle objects. Topic handles are the only supported publish API. Per Codex review on PR #1423: per-instance type uniqueness is a factory-level invariant — handle-based publishing on a single publisher cannot mix Ts on a topic, while still allowing escape hatches (type=typing.Any for heterogeneous topics, pre-built Payload values via the zero-copy fast path on any-typed handle). Migrates the internal users: - temporalio/contrib/openai_agents/_invoke_model_activity.py uses type=Any (TResponseStreamEvent is an annotated union, not a class) - temporalio/contrib/google_adk_agents/_model.py uses type=LlmResponse - All workflow_streams tests migrated to the handle form, preserving existing topic names and types * workflow_streams: fix dangling publish refs in docstrings after a8d3dfc1 CI's pydoctor step on Python 3.14 ubuntu-latest failed because the previous commit removed the public publish() methods on WorkflowStream and WorkflowStreamClient but left :meth:\`WorkflowStream.publish\`, :meth:\`WorkflowStreamClient.publish\`, and an unqualified :py:meth:\`publish\` reference in module/method docstrings. Repoint them at the surviving topic-handle methods. * contrib: revert openai_agents and google_adk_agents to main Splits the openai_agents streaming integration and the google_adk_agents streaming integration out of PR #1423 — they will land in their own follow-up PRs that depend on the workflow_streams contrib module shipping first. Reverts to origin/main: - temporalio/contrib/openai_agents/_invoke_model_activity.py - temporalio/contrib/openai_agents/_mcp.py - temporalio/contrib/openai_agents/_model_parameters.py - temporalio/contrib/openai_agents/_openai_runner.py - temporalio/contrib/openai_agents/_temporal_model_stub.py - temporalio/contrib/openai_agents/_temporal_openai_agents.py - temporalio/contrib/openai_agents/README.md - temporalio/contrib/google_adk_agents/_model.py - temporalio/contrib/google_adk_agents/_plugin.py Removes the streaming-specific test files added on this branch: - tests/contrib/openai_agents/test_openai_streaming.py - tests/contrib/google_adk_agents/test_adk_streaming.py This PR is now scoped to the workflow_streams contrib module only. * workflow_streams: rename WorkflowStream.drain to stop_polling Per PR review feedback, rename the workflow-side state-transition method that releases waiting subscribers and rejects new poll updates. The previous name implied "wait for buffered items to flush"; the operation actually evicts pollers and refuses new ones, while keeping publishes and get_state/continue_as_new valid for the rest of the run. The new name describes that precisely. Updates the continue_as_new helper, the explicit-recipe docstring, and the one test that drives the explicit recipe. Internal _draining state flag stays as-is (private implementation detail). * workflow_streams: make topic(type=...) optional, default to Any Per discussion: heterogeneous topics and dynamic-topic forwarders previously had to write type=cast(type[Any], cast(object, Any)) at the call site to satisfy pyright (typing.Any is a special form, not a class). Make the type kwarg optional and default to typing.Any so the natural form is just client.topic("name") / stream.topic("name"). The type-uniformity invariant is unchanged: each instance binds a topic name to exactly one type; mixing untyped (= Any) with a specific type still raises. typing.Any can also be passed explicitly, with the cast still required for type-strict callers. Adds overloads so callers that pass type=T still get a typed TopicHandle[T] from pyright; the no-type form returns TopicHandle[Any] / WorkflowTopicHandle[Any]. Updates the existing test to exercise both the omitted-type and explicit-type=Any paths. * workflow_streams: rename stop_polling to detach_pollers Better captures the operation. The method releases the in-flight __temporal_workflow_stream_poll update handlers (subscribers were "attached" to the stream's drain signal; this detaches them so they return to the caller, who can then follow continue-as-new or stop) and rejects new poll attachments. "stop_polling" ambiguously suggested the stream itself was the one polling; "detach_pollers" names the actor (the pollers / subscribers) and captures the relationship. Updates the continue_as_new helper and the explicit-recipe docstring/test accordingly. * workflow_streams: clarify docstrings flagged in PR #1423 review - Class Note: lead with the dynamic-registration cause and broaden to cover both signal and update class-level handlers; drop stale pointer to a removed README "Gotcha" section. - get_state: reword "publisher dedup entries" → "dedup state for publishers idle longer than publisher_ttl". - continue_as_new: replace the three-line arrow recipe with a proper code-block. Co-Authored-By: Claude Opus 4.7 (1M context) * workflow_streams: reject subscribe(result_type=Payload) and add tests - WorkflowStreamClient.subscribe now raises RuntimeError when called with result_type=Payload, matching the topic-handle layer's type=Payload rejection. Closes the direct-subscribe escape hatch for the Payload-vs-decoded-T ambiguity flagged in PR #1423 review. - New regression test test_subscribe_with_payload_result_type_rejected. - Extend TopicHandleUniquenessWorkflow probe to also cover the workflow-side WorkflowStream.topic(type=Payload) rejection — the client-side equivalent was already covered, the workflow side was not. Co-Authored-By: Claude Opus 4.7 (1M context) * workflow_streams: parametrize WorkflowStreamItem on decoded data type Make WorkflowStreamItem generic in T so subscribers get a typed data field that matches the result_type passed to subscribe: - subscribe(result_type=T) -> WorkflowStreamItem[T] - subscribe() -> WorkflowStreamItem[Any] - subscribe(result_type=RawValue) -> WorkflowStreamItem[RawValue] Adds def-style overloads to WorkflowStreamClient.subscribe (matching the existing TopicHandle/WorkflowTopicHandle generic style) and tightens TopicHandle.subscribe to AsyncIterator[WorkflowStreamItem[T]]. The internal workflow-side _log is annotated as list[WorkflowStreamItem[Payload]] since the workflow does not decode. No runtime behavior change; existing tests (which use unparameterized WorkflowStreamItem) continue to type-check as WorkflowStreamItem[Any]. Co-Authored-By: Claude Opus 4.7 (1M context) * workflow_streams: tighten README intro and fix samples link Drop the payload/codec paragraph from the README intro — it duplicates material that the docs site guide already covers. Update the samples link to the new workflow-streams directory and the docs link to the libraries section. Co-Authored-By: Claude Opus 4.7 (1M context) * workflow_streams: fix truncation race + graceful subscribe-on-completion Two bugs surfaced running the workflow_streams samples end-to-end. _on_poll captured ``log_offset = from_offset - base_offset`` as a local before its ``wait_condition``. A ``truncate()`` between this poll's arrival and the wait firing changed ``base_offset`` underneath the closure, so the predicate kept comparing ``len(self._log)`` against the pre-truncate value and the poll only returned when the long-poll RPC timed out (~60s). Fix: evaluate the predicate against the current ``base_offset`` on every check, and add a ``from_offset < base_offset`` arm so the existing TruncatedOffset path handles truncation past the subscriber's position. subscribe() raised on workflow completion: once the hosting workflow reached a terminal state, the next ``execute_update`` returned ``RPCError(NOT_FOUND, "workflow execution already completed")`` and an in-flight poll caught at completion surfaced as ``WorkflowUpdateFailedError(AcceptedUpdateCompletedWorkflow)``. Both were unhandled, contradicting the README's claim that "the subscriber's iterator exits normally" on workflow completion. Fix: catch both, follow continue-as-new where applicable, otherwise check ``describe()`` for a terminal state and exit cleanly. Re-raise on a genuine NOT_FOUND for a workflow that never existed (targeting mistake). Adds a private ``_workflow_in_terminal_state()`` helper alongside the existing ``_follow_continue_as_new()``. Adds a regression test for the truncation race: a parked poll at ``from_offset=10`` is woken by a ``publish_then_truncate`` update that advances ``base_offset`` past it in a single workflow activation, and the test asserts the poll surfaces ``TruncatedOffset``. Verified to catch the bug — without the fix the test times out at the long-poll RPC ceiling. Also renames the internal ``_draining`` latch to ``_detaching`` to track the public API rename trail (``drain`` → ``stop_polling`` → ``detach_pollers``); the field had been left behind. No public-API change. Co-Authored-By: Claude Opus 4.7 (1M context) --------- Co-authored-by: Claude Opus 4.6 (1M context) Co-authored-by: Tim Conley --- pyproject.toml | 1 + temporalio/contrib/workflow_streams/README.md | 33 + .../contrib/workflow_streams/__init__.py | 43 + .../contrib/workflow_streams/_client.py | 628 ++++ .../contrib/workflow_streams/_stream.py | 469 +++ .../contrib/workflow_streams/_topic_handle.py | 164 ++ temporalio/contrib/workflow_streams/_types.py | 171 ++ tests/contrib/workflow_streams/__init__.py | 0 .../test_payload_roundtrip.py | 137 + .../workflow_streams/test_workflow_streams.py | 2569 +++++++++++++++++ uv.lock | 6 +- 11 files changed, 4219 insertions(+), 2 deletions(-) create mode 100644 temporalio/contrib/workflow_streams/README.md create mode 100644 temporalio/contrib/workflow_streams/__init__.py create mode 100644 temporalio/contrib/workflow_streams/_client.py create mode 100644 temporalio/contrib/workflow_streams/_stream.py create mode 100644 temporalio/contrib/workflow_streams/_topic_handle.py create mode 100644 temporalio/contrib/workflow_streams/_types.py create mode 100644 tests/contrib/workflow_streams/__init__.py create mode 100644 tests/contrib/workflow_streams/test_payload_roundtrip.py create mode 100644 tests/contrib/workflow_streams/test_workflow_streams.py diff --git a/pyproject.toml b/pyproject.toml index ac9127e49..61fe159fb 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -86,6 +86,7 @@ dev = [ "opentelemetry-exporter-otlp-proto-grpc>=1.11.1,<2", "opentelemetry-semantic-conventions>=0.40b0,<1", "opentelemetry-sdk-extension-aws>=2.0.0,<3", + "async-timeout>=4.0,<6; python_version < '3.11'", ] [tool.poe.tasks] diff --git a/temporalio/contrib/workflow_streams/README.md b/temporalio/contrib/workflow_streams/README.md new file mode 100644 index 000000000..ba5582e52 --- /dev/null +++ b/temporalio/contrib/workflow_streams/README.md @@ -0,0 +1,33 @@ +# Temporal Workflow Streams + +> ⚠️ **This package is currently at an experimental release stage.** ⚠️ + +**Workflow Streams** is a Temporal Python SDK contrib library that gives a +Workflow a durable, offset-addressed event channel for keeping outside +observers updated on the progress of the Workflow and its Activities. +Typical uses include driving a UI for a long-running AI agent, surfacing +status during in-flight payment or order processing, and reporting progress +from data pipelines. It is not designed for ultra-low-latency applications +such as real-time voice; per-roundtrip latency is around 100ms, and cost +scales with durable batches rather than tokens. + +Under the hood the stream is built directly on Temporal's existing +message-passing primitives: Signals carry publishes, Updates serve +long-poll subscriptions, and a Query exposes the current global offset. +The library packages the boilerplate that turns those primitives into +a usable stream: batching to amortize per-event overhead, deduplication +for exactly-once delivery, topic filtering, and continue-as-new helpers +that hand stream state across Workflow runs. + +## Documentation + +📖 **The full guide lives in the Temporal documentation site:** +**[Workflow Streams — Python SDK](https://docs.temporal.io/develop/python/libraries/workflow-streams)** + +It covers installation, enabling streaming on a Workflow, publishing from +Workflows and Activities, subscribing, continue-as-new, delivery semantics, +codec and payload encoding, architecture, and caveats — with runnable code +snippets throughout. + +For runnable end-to-end examples, see the +[Workflow Streams samples](https://github.com/temporalio/samples-python/tree/main/workflow-streams). diff --git a/temporalio/contrib/workflow_streams/__init__.py b/temporalio/contrib/workflow_streams/__init__.py new file mode 100644 index 000000000..41f670f0c --- /dev/null +++ b/temporalio/contrib/workflow_streams/__init__.py @@ -0,0 +1,43 @@ +"""Workflow Streams for Temporal workflows. + +.. warning:: + This package is experimental and may change in future versions. + +The Workflow Streams contrib library gives a workflow a durable, +offset-addressed event channel built from Signals and polling Updates +with an SSE bridge. Cost scales with durable batches, not tokens. +Latency is around 100ms per roundtrip; not for ultra-low-latency voice. + +See :py:class:`WorkflowStream` for the workflow-side stream object and +:py:class:`WorkflowStreamClient` for the external client interface. +""" + +from temporalio.contrib.workflow_streams._client import WorkflowStreamClient +from temporalio.contrib.workflow_streams._stream import WorkflowStream +from temporalio.contrib.workflow_streams._topic_handle import ( + TopicHandle, + WorkflowTopicHandle, +) +from temporalio.contrib.workflow_streams._types import ( + PollInput, + PollResult, + PublishEntry, + PublisherState, + PublishInput, + WorkflowStreamItem, + WorkflowStreamState, +) + +__all__ = [ + "PollInput", + "PollResult", + "PublishEntry", + "PublishInput", + "PublisherState", + "TopicHandle", + "WorkflowStream", + "WorkflowStreamClient", + "WorkflowStreamItem", + "WorkflowStreamState", + "WorkflowTopicHandle", +] diff --git a/temporalio/contrib/workflow_streams/_client.py b/temporalio/contrib/workflow_streams/_client.py new file mode 100644 index 000000000..e28437e69 --- /dev/null +++ b/temporalio/contrib/workflow_streams/_client.py @@ -0,0 +1,628 @@ +"""External-side client for Workflow Streams. + +Used by activities, starters, and any code with a workflow handle to +publish messages and subscribe to topics on a workflow that hosts a +:class:`WorkflowStream`. + +Each published value is turned into a :class:`Payload` via the client's +sync payload converter. The **codec chain** (e.g. encryption, compression) +is **not** run per item — it runs once at the envelope +level when Temporal's SDK encodes the ``__temporal_workflow_stream_publish`` +signal args and the ``__temporal_workflow_stream_poll`` update result. +Running the codec per item as well would double-encrypt / double-compress, +because the envelope path covers the items again. The per-item +``Payload`` still carries the encoding metadata (``encoding: json/plain``, +``messageType``, etc.) required by ``subscribe(result_type=T)`` on the +consumer side. +""" + +from __future__ import annotations + +import asyncio +import time +import uuid +from collections.abc import AsyncIterator +from datetime import timedelta +from typing import Any, TypeVar, overload + +from typing_extensions import Self + +from temporalio import activity +from temporalio.api.common.v1 import Payload +from temporalio.client import ( + Client, + WorkflowExecutionStatus, + WorkflowHandle, + WorkflowUpdateFailedError, + WorkflowUpdateRPCTimeoutOrCancelledError, +) +from temporalio.converter import DataConverter, PayloadConverter +from temporalio.service import RPCError, RPCStatusCode + +from ._topic_handle import TopicHandle +from ._types import ( + PollInput, + PollResult, + PublishEntry, + PublishInput, + WorkflowStreamItem, + _decode_payload, + _encode_payload, +) + +T = TypeVar("T") + + +class WorkflowStreamClient: + """Client for publishing to and subscribing from a workflow stream. + + .. warning:: + This class is experimental and may change in future versions. + + Create via :py:meth:`create` (explicit client + workflow id), + :py:meth:`from_within_activity` (infer both from the current activity + context), or by passing a handle directly to the constructor. + + For publishing, bind a typed topic handle and use the client as + an async context manager to get automatic batching:: + + client = WorkflowStreamClient.create(temporal_client, workflow_id) + events = client.topic("events", type=MyEvent) + async with client: + events.publish(my_event) + events.publish(another_event, force_flush=True) + ... # more publishing + # Buffer is flushed automatically on context manager exit. + + For subscribing:: + + client = WorkflowStreamClient.create(temporal_client, workflow_id) + async for item in client.subscribe(["events"], result_type=MyEvent): + process(item.data) + """ + + def __init__( + self, + handle: WorkflowHandle[Any, Any], + *, + client: Client | None = None, + batch_interval: timedelta = timedelta(seconds=2), + max_batch_size: int | None = None, + max_retry_duration: timedelta = timedelta(seconds=600), + ) -> None: + """Create a stream client from a workflow handle. + + Prefer :py:meth:`create` — it enables continue-as-new following + in ``subscribe()`` and supplies the :class:`Client` needed to + reach the data converter chain. + + Args: + handle: Workflow handle to the workflow hosting the stream. + client: Temporal client whose payload converter will be used + to turn published values into ``Payload`` objects and to + decode subscriptions when ``result_type`` is set. The + codec chain is **not** applied per item (doing so would + double-encrypt — see module docstring). If ``None``, the + default payload converter is used. + batch_interval: Interval between automatic flushes. + max_batch_size: Auto-flush when buffer reaches this size. + max_retry_duration: Maximum time to retry a failed flush + before raising TimeoutError. Must be less than the + workflow's ``publisher_ttl`` (default 15 minutes) to + preserve exactly-once delivery. Default: 10 minutes. + """ + self._handle: WorkflowHandle[Any, Any] = handle + self._client: Client | None = client + self._workflow_id = handle.id + self._batch_interval = batch_interval + self._max_batch_size = max_batch_size + self._max_retry_duration = max_retry_duration + self._buffer: list[tuple[str, Any]] = [] + self._flush_event = asyncio.Event() + self._flush_task: asyncio.Task[None] | None = None + self._flush_lock = asyncio.Lock() + self._publisher_id: str = uuid.uuid4().hex[:16] + self._sequence: int = 0 + self._pending: list[PublishEntry] | None = None + self._pending_seq: int = 0 + self._pending_since: float | None = None + self._topic_types: dict[str, type[Any]] = {} + + @classmethod + def create( + cls, + client: Client, + workflow_id: str, + *, + batch_interval: timedelta = timedelta(seconds=2), + max_batch_size: int | None = None, + max_retry_duration: timedelta = timedelta(seconds=600), + ) -> WorkflowStreamClient: + """Create a stream client from a Temporal client and workflow ID. + + Use this when the caller has an explicit ``Client`` and + ``workflow_id`` in hand (starters, BFFs, other workflows' + activities). For code running inside an activity that targets + its own parent workflow, see :py:meth:`from_within_activity`. + + A client created through this method follows continue-as-new + chains in ``subscribe()`` and uses the client's payload + converter for per-item ``Payload`` construction. + + Args: + client: Temporal client. + workflow_id: ID of the workflow hosting the stream. + batch_interval: Interval between automatic flushes. + max_batch_size: Auto-flush when buffer reaches this size. + max_retry_duration: Maximum time to retry a failed flush + before raising TimeoutError. Default: 10 minutes. + """ + handle = client.get_workflow_handle(workflow_id) + return cls( + handle, + client=client, + batch_interval=batch_interval, + max_batch_size=max_batch_size, + max_retry_duration=max_retry_duration, + ) + + @classmethod + def from_within_activity( + cls, + *, + batch_interval: timedelta = timedelta(seconds=2), + max_batch_size: int | None = None, + max_retry_duration: timedelta = timedelta(seconds=600), + ) -> WorkflowStreamClient: + """Create a stream client targeting the current activity's parent workflow. + + Must be called from within an activity that was scheduled by a + workflow. The Temporal client and parent workflow id are taken + from the activity context. + + Standalone activities — those started directly via + :py:meth:`temporalio.client.Client.start_activity` rather than + from a workflow — have no parent workflow, so this method + raises. Use :py:meth:`create` from a standalone activity, + passing ``activity.client()`` and the target workflow id + explicitly (typically threaded through the activity's input). + + Args: + batch_interval: Interval between automatic flushes. + max_batch_size: Auto-flush when buffer reaches this size. + max_retry_duration: Maximum time to retry a failed flush + before raising TimeoutError. Default: 10 minutes. + """ + info = activity.info() + workflow_id = info.workflow_id + if workflow_id is None: + raise RuntimeError( + "from_within_activity requires an activity scheduled by a workflow; " + "this activity has no parent workflow. From a standalone " + "activity, use WorkflowStreamClient.create(activity.client(), " + "workflow_id) with the target workflow id passed in explicitly." + ) + return cls.create( + activity.client(), + workflow_id, + batch_interval=batch_interval, + max_batch_size=max_batch_size, + max_retry_duration=max_retry_duration, + ) + + async def __aenter__(self) -> Self: + """Start the background flusher task.""" + self._flush_task = asyncio.create_task(self._run_flusher()) + return self + + async def __aexit__(self, *_exc: object) -> None: + """Stop the flusher and flush any remaining buffered entries.""" + if self._flush_task: + self._flush_task.cancel() + try: + await self._flush_task + except asyncio.CancelledError: + pass + self._flush_task = None + # Drain both pending and buffer. A single _flush() processes + # either pending OR buffer, not both — so if the flusher was + # cancelled mid-signal (pending set) while the producer added + # more items (buffer non-empty), a single final flush would + # orphan the buffer. + while self._pending is not None or self._buffer: + await self._flush() + + def _publish_to_topic( + self, topic: str, value: Any, *, force_flush: bool = False + ) -> None: + """Internal publish path used by :class:`TopicHandle`. + + Not part of the public API — call + :meth:`TopicHandle.publish` instead. + """ + self._buffer.append((topic, value)) + if force_flush or ( + self._max_batch_size is not None + and len(self._buffer) >= self._max_batch_size + ): + self._flush_event.set() + + @overload + def topic(self, name: str) -> TopicHandle[Any]: ... + @overload + def topic(self, name: str, *, type: type[T]) -> TopicHandle[T]: ... + + def topic( + self, name: str, *, type: type[T] | None = None + ) -> TopicHandle[T] | TopicHandle[Any]: + """Return a typed handle for publishing to and subscribing from ``name``. + + The handle records the topic name and value type so call sites + do not have to repeat them. Each :class:`WorkflowStreamClient` + instance binds a topic name to exactly one type: a second call + with an unequal type raises ``RuntimeError``. Repeating the + same call with the same type is idempotent and returns an + equivalent handle. + + Type uniformity is checked only on this client instance — it + does not coordinate across processes. The check uses Python + equality on the type object; subtype and union-superset + relationships are not recognized. + + Omitting ``type`` (or passing ``type=typing.Any``) is the + documented escape hatch for heterogeneous topics or + dynamic-topic forwarders: the handle accepts any value, and + subscribers receive the converter's default decoded value. + Pre-built ``Payload`` values can be passed to + :meth:`TopicHandle.publish` regardless of the bound type + (zero-copy fast path) — there is no need to bind the topic to + ``Payload`` itself, and doing so would break the subscribe + path (use ``result_type=RawValue`` on + :meth:`WorkflowStreamClient.subscribe` if you need raw + payloads on a subscriber). + + Args: + name: Topic name. + type: Value type bound to this handle. Used as the + ``result_type`` when subscribing through the handle. + Defaults to ``typing.Any`` (heterogeneous topic). + + Returns: + :class:`TopicHandle` bound to ``name`` and the resolved + type. + + Raises: + RuntimeError: If ``name`` is already bound on this client + to a different type. + """ + bound: Any = Any if type is None else type + if bound is Payload: + raise RuntimeError( + "Cannot bind a topic to type=Payload: the payload converter " + "has no Payload decode path, so TopicHandle.subscribe would " + "fail. Pre-built Payload values can be passed to " + "TopicHandle.publish on any-typed handle (zero-copy fast " + "path); omit type (or pass type=typing.Any) for " + "heterogeneous topics, and subscribe via " + "WorkflowStreamClient.subscribe with result_type=RawValue " + "when raw payloads are needed." + ) + existing = self._topic_types.get(name) + if existing is not None and existing != bound: + raise RuntimeError( + f"Topic {name!r} is already bound to type {existing!r} on this " + f"client; refusing to rebind to {bound!r}. Use a single type " + f"per topic, or omit type (=typing.Any) for heterogeneous topics." + ) + self._topic_types[name] = bound + return TopicHandle(self, name, bound) + + async def flush(self) -> None: + """Flush buffered (and pending) items and wait for server confirmation. + + Returns once the items buffered at call time have been signaled to + the workflow and acknowledged by the server. Returns immediately + if there is nothing to send. + + This is in addition to the declarative ``force_flush=True`` on + :py:meth:`TopicHandle.publish` and to the automatic flush on + context-manager exit. Use this when you need a synchronization + point — proof that prior publications have reached the + server — at a moment that does not naturally correspond to a + specific event. + + Safe to call concurrently with topic-handle publishes and with + the background flusher: the flush lock serializes signal sends. + Items added concurrently after entry may piggyback on this + flush or be deferred to a subsequent one. + + Raises: + TimeoutError: If a pending batch from a prior failure cannot + be sent within ``max_retry_duration``. The pending batch + is dropped; subsequent publications use a fresh sequence. + """ + while self._pending is not None or self._buffer: + await self._flush() + + def _payload_converter(self) -> PayloadConverter: + """Return the sync payload converter for per-item encode/decode. + + Uses the configured client's payload converter when available; + otherwise falls back to the default. The codec chain + (e.g. encryption, compression) is intentionally not + invoked here — it runs once at the envelope level when the + signal/update goes over the wire. See module docstring. + """ + if self._client is not None: + return self._client.data_converter.payload_converter + return DataConverter.default.payload_converter + + def _encode_buffer(self, entries: list[tuple[str, Any]]) -> list[PublishEntry]: + """Convert buffered (topic, value) pairs to wire entries. + + Non-Payload values go through the sync payload converter so the + resulting ``Payload`` carries encoding metadata for + ``result_type=`` decode on the consumer side. Pre-built + Payloads bypass conversion. + """ + converter = self._payload_converter() + out: list[PublishEntry] = [] + for topic, value in entries: + if isinstance(value, Payload): + payload = value + else: + payload = converter.to_payloads([value])[0] + out.append(PublishEntry(topic=topic, data=_encode_payload(payload))) + return out + + async def _flush(self) -> None: + """Send buffered or pending messages to the workflow via signal. + + On failure, the pending batch and sequence are kept for retry. + Only advances the confirmed sequence on success. + """ + async with self._flush_lock: + if self._pending is not None: + # Retry path: check max_retry_duration + if ( + self._pending_since is not None + and time.monotonic() - self._pending_since + > self._max_retry_duration.total_seconds() + ): + # Advance confirmed sequence so the next batch gets + # a fresh sequence number. Without this, the next + # batch reuses pending_seq, which the workflow may + # have already accepted — causing silent dedup + # (data loss). See DropPendingFixed / + # SequenceFreshness in the design doc. + self._sequence = self._pending_seq + self._pending = None + self._pending_seq = 0 + self._pending_since = None + raise TimeoutError( + f"Flush retry exceeded max_retry_duration " + f"({self._max_retry_duration}). Pending batch dropped. " + f"If the signal was delivered, items are in the log. " + f"If not, they are lost." + ) + batch = self._pending + seq = self._pending_seq + elif self._buffer: + # New batch path. Encode before clearing the buffer so + # a payload-converter exception leaves the items in + # place for inspection or retry rather than silently + # dropping them. + batch = self._encode_buffer(self._buffer) + self._buffer = [] + seq = self._sequence + 1 + self._pending = batch + self._pending_seq = seq + self._pending_since = time.monotonic() + else: + return + + try: + # If the SDK ever exposes request_id on signal() and the + # server dedups it across CAN, pinning + # request_id=f"{publisher_id}:{seq}" here lets the + # workflow-side dedup go away. See DESIGN §"Replace + # workflow-side dedup with server-side request_id". + await self._handle.signal( + "__temporal_workflow_stream_publish", + PublishInput( + items=batch, + publisher_id=self._publisher_id, + sequence=seq, + ), + ) + # Success: advance confirmed sequence, clear pending + self._sequence = seq + self._pending = None + self._pending_seq = 0 + self._pending_since = None + except Exception: + # Pending stays set for retry on the next _flush() call + raise + + async def _run_flusher(self) -> None: + """Background task: wait for timer OR force_flush wakeup, then flush.""" + while True: + try: + await asyncio.wait_for( + self._flush_event.wait(), + timeout=self._batch_interval.total_seconds(), + ) + except asyncio.TimeoutError: + pass + self._flush_event.clear() + await self._flush() + + @overload + def subscribe( + self, + topics: str | list[str] | None = ..., + from_offset: int = ..., + *, + result_type: type[T], + poll_cooldown: timedelta = ..., + ) -> AsyncIterator[WorkflowStreamItem[T]]: ... + @overload + def subscribe( + self, + topics: str | list[str] | None = ..., + from_offset: int = ..., + *, + result_type: None = None, + poll_cooldown: timedelta = ..., + ) -> AsyncIterator[WorkflowStreamItem[Any]]: ... + + async def subscribe( + self, + topics: str | list[str] | None = None, + from_offset: int = 0, + *, + result_type: type | None = None, + poll_cooldown: timedelta = timedelta(milliseconds=100), + ) -> AsyncIterator[WorkflowStreamItem[Any]]: + """Async iterator that polls for new items. + + Automatically follows continue-as-new chains when the client + was created via :py:meth:`create`. + + Args: + topics: Topic filter. A single topic name, a list of topic + names, or None. None or empty list means all topics. + from_offset: Global offset to start reading from. + result_type: Optional target type. Each yielded + :class:`WorkflowStreamItem` has its ``data`` decoded via + the client's sync payload converter. When omitted, the + converter's default ``Any`` decoding is used (for the + stock JSON converter that means a Python primitive, + ``dict``, or ``list``). Pass + ``result_type=temporalio.common.RawValue`` for an + opaque ``RawValue`` wrapping the original + ``Payload`` — useful for heterogeneous topics where + the caller dispatches on ``Payload.metadata`` or wants + to forward the bytes without decoding. + poll_cooldown: Minimum interval between polls to avoid + overwhelming the workflow when items arrive faster + than the poll round-trip. Defaults to 100ms. + + Yields: + :class:`WorkflowStreamItem` for each matching item. + """ + if result_type is Payload: + raise RuntimeError( + "Cannot subscribe with result_type=Payload: the payload " + "converter has no Payload decode path. Omit result_type " + "for default decoding, or pass result_type=RawValue to " + "receive a RawValue wrapping the raw Payload." + ) + topic_filter: list[str] + if topics is None: + topic_filter = [] + elif isinstance(topics, str): + topic_filter = [topics] + else: + topic_filter = topics + offset = from_offset + while True: + try: + result: PollResult = await self._handle.execute_update( + "__temporal_workflow_stream_poll", + PollInput(topics=topic_filter, from_offset=offset), + result_type=PollResult, + ) + except asyncio.CancelledError: + return + except WorkflowUpdateFailedError as e: + cause_type = getattr(e.cause, "type", None) + if cause_type == "TruncatedOffset": + # Subscriber fell behind truncation. Retry from + # offset 0 which the stream treats as "from the + # beginning of whatever exists" (i.e., from + # base_offset). + offset = 0 + continue + if cause_type == "AcceptedUpdateCompletedWorkflow": + # Workflow returned (or continued-as-new) before + # this poll's update completed. Either follow the + # chain or exit cleanly. + if await self._follow_continue_as_new(): + continue + return + raise + except WorkflowUpdateRPCTimeoutOrCancelledError: + if await self._follow_continue_as_new(): + continue + return + except RPCError as e: + # Workflow may have completed between polls; subscribe + # exits cleanly on terminal status so callers don't + # have to wrap the iterator in error handling for the + # normal end-of-stream case. + if e.status != RPCStatusCode.NOT_FOUND: + raise + if await self._follow_continue_as_new(): + continue + if await self._workflow_in_terminal_state(): + return + raise + converter = self._payload_converter() + for wire_item in result.items: + payload = _decode_payload(wire_item.data) + data: Any = ( + converter.from_payload(payload) + if result_type is None + else converter.from_payload(payload, result_type) + ) + yield WorkflowStreamItem( + topic=wire_item.topic, + data=data, + offset=wire_item.offset, + ) + offset = result.next_offset + cooldown_secs = poll_cooldown.total_seconds() + if not result.more_ready and cooldown_secs > 0: + await asyncio.sleep(cooldown_secs) + + async def _follow_continue_as_new(self) -> bool: + """Check if the workflow continued-as-new and re-target the handle. + + Returns True if the handle was updated (caller should retry). + """ + if self._client is None: + return False + try: + desc = await self._handle.describe() + except Exception: + return False + if desc.status == WorkflowExecutionStatus.CONTINUED_AS_NEW: + self._handle = self._client.get_workflow_handle(self._workflow_id) + return True + return False + + async def _workflow_in_terminal_state(self) -> bool: + """Return True if the workflow has reached a terminal state. + + Used by ``subscribe()`` to distinguish "workflow finished — + stream is done" from "wrong workflow id" when a poll RPC + returns NOT_FOUND. + """ + try: + desc = await self._handle.describe() + except Exception: + return False + return desc.status in ( + WorkflowExecutionStatus.COMPLETED, + WorkflowExecutionStatus.FAILED, + WorkflowExecutionStatus.CANCELED, + WorkflowExecutionStatus.TERMINATED, + WorkflowExecutionStatus.TIMED_OUT, + ) + + async def get_offset(self) -> int: + """Query the current global offset (base_offset + log length).""" + return await self._handle.query( + "__temporal_workflow_stream_offset", result_type=int + ) diff --git a/temporalio/contrib/workflow_streams/_stream.py b/temporalio/contrib/workflow_streams/_stream.py new file mode 100644 index 000000000..2753f04c2 --- /dev/null +++ b/temporalio/contrib/workflow_streams/_stream.py @@ -0,0 +1,469 @@ +"""Workflow-side stream object for Workflow Streams. + +Instantiate :class:`WorkflowStream` once from your workflow's ``@workflow.init`` +method. The constructor registers the stream signal, update, and query +handlers on the current workflow via +:func:`temporalio.workflow.set_signal_handler`, +:func:`temporalio.workflow.set_update_handler`, and +:func:`temporalio.workflow.set_query_handler`. + +For workflows that support continue-as-new, include a +``WorkflowStreamState | None`` field on the workflow input and pass it as +``prior_state`` — it is ``None`` on fresh starts and carries accumulated +state on continue-as-new. + +Workflow-side and client-side topic handles +(:meth:`WorkflowTopicHandle.publish` and +:meth:`TopicHandle.publish`) both use the synchronous payload +converter for per-item ``Payload`` construction. The codec chain +(e.g. encryption, compression) is **not** run per item on either +side — it runs once at the envelope level when Temporal's SDK +encodes the signal/update that carries the batch. Running it per +item as well would double-encrypt, because every signal arg +already goes through the client's ``DataConverter.encode`` at +dispatch time. +""" + +from __future__ import annotations + +import sys +from collections.abc import Sequence +from datetime import timedelta +from typing import Any, Callable, NoReturn, TypeVar, overload + +from temporalio import workflow +from temporalio.api.common.v1 import Payload +from temporalio.exceptions import ApplicationError + +from ._topic_handle import WorkflowTopicHandle +from ._types import ( + PollInput, + PollResult, + PublisherState, + PublishInput, + WorkflowStreamItem, + WorkflowStreamState, + _decode_payload, + _encode_payload, + _WorkflowStreamWireItem, +) + +_PUBLISH_SIGNAL = "__temporal_workflow_stream_publish" +_POLL_UPDATE = "__temporal_workflow_stream_poll" +_OFFSET_QUERY = "__temporal_workflow_stream_offset" + +_MAX_POLL_RESPONSE_BYTES = 1_000_000 + +T = TypeVar("T") + + +def _payload_wire_size(payload: Payload, topic: str) -> int: + """Approximate poll-response contribution of a single item. + + Wire form is ``_WorkflowStreamWireItem(topic, base64(proto(Payload)), offset)``. + Base64 inflates by ~4/3; we use the serialized length as a + conservative approximation. + """ + return (payload.ByteSize() * 4 + 2) // 3 + len(topic) + + +class WorkflowStream: + """Workflow-side stream object — append-only log with publish/poll handlers. + + .. warning:: + This class is experimental and may change in future versions. + + Construct once from ``@workflow.init``; the constructor registers + the stream signal, update, and query handlers on the current + workflow. Raises :class:`RuntimeError` if a ``WorkflowStream`` has + already been registered on the workflow. + + Registered handlers: + + - ``__temporal_workflow_stream_publish`` signal — external publish with dedup + - ``__temporal_workflow_stream_poll`` update — long-poll subscription + - ``__temporal_workflow_stream_offset`` query — current log length + + Note: + Because the publish handler is registered dynamically from + ``__init__``, on the activation where the stream is + constructed the publish signal can be buffered until after + class-level signal/update handlers are scheduled. Define + such handlers as ``async`` and ``await asyncio.sleep(0)`` + before reading stream state, so the publish signal is + processed first. + """ + + def __init__(self, prior_state: WorkflowStreamState | None = None) -> None: + """Initialize stream state and register workflow handlers. + + Must be called directly from the workflow's ``@workflow.init`` + method. Calls made from ``@workflow.run``, helper methods, or + signal/update/query handlers raise :class:`RuntimeError`. + + The check inspects the immediate caller's frame and requires the + function name to be ``__init__``. + + Args: + prior_state: State carried from a previous run via + :meth:`get_state` through continue-as-new, or ``None`` + on first start. + + Raises: + RuntimeError: If not called directly from a method named + ``__init__``, or if the stream signal handler is + already registered on this workflow (i.e., + ``WorkflowStream`` was instantiated twice). + + Note: + When carrying state across continue-as-new, type the + carrying field as ``WorkflowStreamState | None``, not + ``Any``. The default data converter deserializes ``Any`` + fields as plain dicts, which silently strips the + ``WorkflowStreamState`` type and breaks the new run. + """ + caller = sys._getframe(1) + caller_name = caller.f_code.co_name + if caller_name != "__init__": + raise RuntimeError( + "WorkflowStream must be constructed directly from the workflow's " + f"@workflow.init method, not from {caller_name!r}." + ) + if workflow.get_signal_handler(_PUBLISH_SIGNAL) is not None: + raise RuntimeError( + "WorkflowStream is already registered on this workflow. " + "Construct WorkflowStream(...) at most once from @workflow.init." + ) + + if prior_state is not None: + self._log: list[WorkflowStreamItem[Payload]] = [ + WorkflowStreamItem(topic=item.topic, data=_decode_payload(item.data)) + for item in prior_state.log + ] + self._base_offset: int = prior_state.base_offset + self._publishers: dict[str, PublisherState] = { + pid: PublisherState(sequence=ps.sequence, last_seen=ps.last_seen) + for pid, ps in prior_state.publishers.items() + } + else: + self._log = [] + self._base_offset = 0 + self._publishers = {} + self._detaching: bool = False + self._topic_types: dict[str, type[Any]] = {} + + workflow.set_signal_handler(_PUBLISH_SIGNAL, self._on_publish) + workflow.set_update_handler( + _POLL_UPDATE, self._on_poll, validator=self._validate_poll + ) + workflow.set_query_handler(_OFFSET_QUERY, self._on_offset) + + def _publish_to_topic(self, topic: str, value: Any) -> None: + """Internal publish path used by :class:`WorkflowTopicHandle`. + + Not part of the public API — call + :meth:`WorkflowTopicHandle.publish` instead. + """ + if isinstance(value, Payload): + payload = value + else: + payload = workflow.payload_converter().to_payloads([value])[0] + self._log.append(WorkflowStreamItem(topic=topic, data=payload)) + + @overload + def topic(self, name: str) -> WorkflowTopicHandle[Any]: ... + @overload + def topic(self, name: str, *, type: type[T]) -> WorkflowTopicHandle[T]: ... + + def topic( + self, name: str, *, type: type[T] | None = None + ) -> WorkflowTopicHandle[T] | WorkflowTopicHandle[Any]: + """Return a typed handle for publishing to ``name`` from this workflow. + + The handle records the topic name and value type so call sites + do not have to repeat them. Each :class:`WorkflowStream` + instance binds a topic name to exactly one type: a second call + with an unequal type raises ``RuntimeError``. Repeating the + same call with the same type is idempotent and returns an + equivalent handle. + + Type uniformity is checked only on this stream instance — it + does not coordinate across publishers (other workflows, + activities, external clients). The check uses Python equality + on the type object; subtype and union-superset relationships + are not recognized. + + Omitting ``type`` (or passing ``type=typing.Any``) is the + documented escape hatch for heterogeneous topics. Pre-built + ``Payload`` values can be passed to + :meth:`WorkflowTopicHandle.publish` regardless of the bound + type (zero-copy fast path) — there is no need to bind the + topic to ``Payload`` itself. + + Args: + name: Topic name. + type: Value type bound to this handle. Defaults to + ``typing.Any`` (heterogeneous topic). + + Returns: + :class:`WorkflowTopicHandle` bound to ``name`` and the + resolved type. + + Raises: + RuntimeError: If ``name`` is already bound on this stream + to a different type. + """ + bound: Any = Any if type is None else type + if bound is Payload: + raise RuntimeError( + "Cannot bind a topic to type=Payload. Pre-built Payload " + "values can be passed to WorkflowTopicHandle.publish on " + "any-typed handle (zero-copy fast path); omit type (or " + "pass type=typing.Any) for heterogeneous topics." + ) + existing = self._topic_types.get(name) + if existing is not None and existing != bound: + raise RuntimeError( + f"Topic {name!r} is already bound to type {existing!r} on this " + f"workflow stream; refusing to rebind to {bound!r}. Use a " + f"single type per topic, or omit type (=typing.Any) for " + f"heterogeneous topics." + ) + self._topic_types[name] = bound + return WorkflowTopicHandle(self, name, bound) + + def get_state( + self, *, publisher_ttl: timedelta = timedelta(seconds=900) + ) -> WorkflowStreamState: + """Return a serializable snapshot of stream state for continue-as-new. + + Drops dedup state for publishers idle longer than + ``publisher_ttl``. The TTL must exceed the + ``max_retry_duration`` of any client that may still be + retrying a failed flush. + + Args: + publisher_ttl: Duration after which an idle publisher's + dedup state is dropped. Default 15 minutes. + """ + now = workflow.now() + + active_publishers = { + pid: ps + for pid, ps in self._publishers.items() + if now - ps.last_seen < publisher_ttl + } + + return WorkflowStreamState( + log=[ + _WorkflowStreamWireItem( + topic=item.topic, data=_encode_payload(item.data) + ) + for item in self._log + ], + base_offset=self._base_offset, + publishers=active_publishers, + ) + + def detach_pollers(self) -> None: + """Release waiting pollers and reject new poll updates. + + After this call the stream's ``__temporal_workflow_stream_poll`` + update handler releases its in-flight subscribers on this run: + each waiting poll returns its current item batch (often empty) + so the consumer can either follow continue-as-new or stop, and + new polls are rejected at the validator. Publishes still land + in the in-memory log and ``get_state`` / ``continue_as_new`` + remain valid — the stream is being held open just long enough + to snapshot state and hand off to the next run. + + Call this before + ``await workflow.wait_condition(workflow.all_handlers_finished)`` + and ``workflow.continue_as_new()``. + """ + self._detaching = True + + async def continue_as_new( + self, + build_args: Callable[[WorkflowStreamState], Sequence[Any]], + *, + publisher_ttl: timedelta = timedelta(seconds=900), + ) -> NoReturn: + """Detach pollers, wait for handlers, continue-as-new with built args. + + Replaces this three-line recipe for the common case where the + only continue-as-new parameter that varies is ``args``: + + .. code-block:: python + + self.stream.detach_pollers() + await workflow.wait_condition(workflow.all_handlers_finished) + workflow.continue_as_new(args=...) + + ``build_args`` is invoked *after* pollers have been detached, + with the post-detach :class:`WorkflowStreamState` as its single + argument. The caller threads that state into whatever input + dataclass the workflow expects: + + .. code-block:: python + + await self.stream.continue_as_new(lambda state: [WorkflowInput( + items_processed=self.items_processed, + stream_state=state, + )]) + + Workflows that need to override other CAN parameters + (``task_queue``, ``retry_policy``, ``run_timeout``, etc.) should + keep using the explicit ``detach_pollers`` / ``wait_condition`` / + ``workflow.continue_as_new(...)`` recipe. + + Args: + build_args: Callable that receives the post-detach stream + state and returns the positional ``args`` for the new + run. + publisher_ttl: Forwarded to :meth:`get_state`. + + Does not return; ``workflow.continue_as_new`` raises an internal + exception that the SDK uses to close the run. + """ + self.detach_pollers() + await workflow.wait_condition(workflow.all_handlers_finished) + workflow.continue_as_new( + args=build_args(self.get_state(publisher_ttl=publisher_ttl)), + ) + + def truncate(self, up_to_offset: int) -> None: + """Discard log entries before ``up_to_offset``. + + After truncation, polls requesting an offset before the new + base will receive an ApplicationError. All global offsets + remain monotonic. + + Raises ApplicationError (not ValueError) when ``up_to_offset`` + is past the end of the log so that callers invoking this from + an update handler surface it as an update failure rather than + a workflow-task poison pill. + + Args: + up_to_offset: The global offset to truncate up to + (exclusive). Entries at offsets + ``[base_offset, up_to_offset)`` are discarded. + """ + log_index = up_to_offset - self._base_offset + if log_index <= 0: + return + if log_index > len(self._log): + raise ApplicationError( + f"Cannot truncate to offset {up_to_offset}: " + f"valid range is [{self._base_offset}, {self._base_offset + len(self._log)})", + type="TruncateOutOfRange", + non_retryable=True, + ) + self._log = self._log[log_index:] + self._base_offset = up_to_offset + + def _on_publish(self, payload: PublishInput) -> None: + """Receive publications from external clients (activities, starters). + + Deduplicates using (publisher_id, sequence). If publisher_id is + set and the sequence is <= the last seen sequence for that + publisher, the entire batch is dropped as a duplicate. Batches + are atomic: the dedup decision applies to the whole batch, not + individual items. + + This block is a polyfill for missing server-side ``request_id`` + dedup across continue-as-new. If the SDK ever exposes + ``request_id`` on signals and the server dedups it across CAN, + this branch and the ``_publishers`` state become redundant. See + DESIGN §"Replace workflow-side dedup with server-side + request_id" for the migration plan. + """ + if payload.publisher_id: + existing = self._publishers.get(payload.publisher_id) + if existing is not None and payload.sequence <= existing.sequence: + return + self._publishers[payload.publisher_id] = PublisherState( + sequence=payload.sequence, + last_seen=workflow.now(), + ) + for entry in payload.items: + self._log.append( + WorkflowStreamItem(topic=entry.topic, data=_decode_payload(entry.data)) + ) + + async def _on_poll(self, payload: PollInput) -> PollResult: + """Long-poll: block until new items available or detaching, then return.""" + # Re-evaluate the predicate against current ``_base_offset`` on + # every iteration: a ``truncate()`` between this poll's arrival + # and the wait firing changes ``log_offset`` underneath us, so + # capturing it as a local would freeze the wait against stale + # state and the poll would only return when the long-poll RPC + # times out. + await workflow.wait_condition( + lambda: ( + payload.from_offset < self._base_offset + or len(self._log) > payload.from_offset - self._base_offset + or self._detaching + ), + ) + log_offset = payload.from_offset - self._base_offset + if log_offset < 0: + if payload.from_offset == 0: + # "From the beginning" — start at whatever is available. + log_offset = 0 + else: + # Subscriber had a specific position that's been + # truncated. ApplicationError fails this update (client + # gets the error) without crashing the workflow task — + # avoids a poison pill during replay. + raise ApplicationError( + f"Requested offset {payload.from_offset} has been truncated. " + f"Current base offset is {self._base_offset}.", + type="TruncatedOffset", + non_retryable=True, + ) + all_new = self._log[log_offset:] + if payload.topics: + topic_set = set(payload.topics) + candidates = [ + (self._base_offset + log_offset + i, item) + for i, item in enumerate(all_new) + if item.topic in topic_set + ] + else: + candidates = [ + (self._base_offset + log_offset + i, item) + for i, item in enumerate(all_new) + ] + # Cap response size to ~1MB wire bytes. + wire_items: list[_WorkflowStreamWireItem] = [] + size = 0 + more_ready = False + next_offset = self._base_offset + len(self._log) + for off, item in candidates: + item_size = _payload_wire_size(item.data, item.topic) + if size + item_size > _MAX_POLL_RESPONSE_BYTES and wire_items: + # Resume from this item on the next poll. + next_offset = off + more_ready = True + break + size += item_size + wire_items.append( + _WorkflowStreamWireItem( + topic=item.topic, data=_encode_payload(item.data), offset=off + ) + ) + return PollResult( + items=wire_items, + next_offset=next_offset, + more_ready=more_ready, + ) + + def _validate_poll(self, _payload: PollInput) -> None: + """Reject new polls when pollers are detached for continue-as-new.""" + if self._detaching: + raise RuntimeError("Workflow pollers are detached for continue-as-new") + + def _on_offset(self) -> int: + """Return the current global offset (base_offset + log length).""" + return self._base_offset + len(self._log) diff --git a/temporalio/contrib/workflow_streams/_topic_handle.py b/temporalio/contrib/workflow_streams/_topic_handle.py new file mode 100644 index 000000000..3b94e226f --- /dev/null +++ b/temporalio/contrib/workflow_streams/_topic_handle.py @@ -0,0 +1,164 @@ +"""Typed topic handles for Workflow Streams. + +A topic handle is a thin typed view over an underlying publisher. It +carries the topic name and the value type ``T`` so call sites do not +have to repeat them on every publish, and so cross-language SDKs can +mirror the binding cleanly. + +Type-uniformity is enforced per publisher instance: each +:class:`WorkflowStreamClient` (or :class:`WorkflowStream`) maps a topic +name to exactly one bound ``T``. Re-binding the same name to an +unequal type raises ``RuntimeError``. The check uses Python equality +on the type object — primitives, dataclasses, generic aliases, and +unions all compare structurally — and intentionally does not attempt +to recognize subtype or union-superset relationships. +""" + +from __future__ import annotations + +from collections.abc import AsyncIterator +from datetime import timedelta +from typing import TYPE_CHECKING, Generic, TypeVar + +from temporalio.api.common.v1 import Payload + +from ._types import WorkflowStreamItem + +if TYPE_CHECKING: + from ._client import WorkflowStreamClient + from ._stream import WorkflowStream + +T = TypeVar("T") + + +class TopicHandle(Generic[T]): + """Client-side handle for publishing to and subscribing from a single topic. + + .. warning:: + This class is experimental and may change in future versions. + + Constructed via :meth:`WorkflowStreamClient.topic`. Publishes share + the underlying client's batching, dedup, and codec path; this + object holds only the topic name and bound type. + """ + + def __init__( + self, + client: WorkflowStreamClient, + name: str, + type: type[T], + ) -> None: + """Bind the handle to a client, topic name, and type. + + Prefer :meth:`WorkflowStreamClient.topic` over calling this + directly; the factory is what records the per-client type + binding and rejects conflicts. + """ + self._client = client + self._name = name + self._type = type + + @property + def name(self) -> str: + """The topic name this handle is bound to.""" + return self._name + + @property + def type(self) -> type[T]: + """The value type this handle is bound to.""" + return self._type + + def publish(self, value: T | Payload, *, force_flush: bool = False) -> None: + """Buffer ``value`` for publishing on this topic. + + Equivalent to the underlying client's publish path; the value + flows through the same buffer, batch interval, and dedup + sequence. + + Args: + value: Value to publish. Goes through the client's sync + payload converter at flush time. A pre-built + :class:`temporalio.api.common.v1.Payload` bypasses + conversion (zero-copy fast path), regardless of the + handle's bound type. + force_flush: If True, wake the flusher to send immediately + (fire-and-forget — does not block the caller). + """ + self._client._publish_to_topic(self._name, value, force_flush=force_flush) + + async def subscribe( + self, + from_offset: int = 0, + *, + poll_cooldown: timedelta = timedelta(milliseconds=100), + ) -> AsyncIterator[WorkflowStreamItem[T]]: + """Async iterator over items on this topic, decoded as ``T``. + + For raw ``Payload`` access, or any other decode type that + differs from the handle's bound ``T``, use + :meth:`WorkflowStreamClient.subscribe` directly with an + explicit ``result_type`` (typically + :class:`temporalio.common.RawValue`). The handle's bound + type intentionally cannot be ``Payload`` — the converter has + no Payload decode path. + + Args: + from_offset: Global offset to start reading from. + poll_cooldown: Minimum interval between polls when there + are no new items. + """ + async for item in self._client.subscribe( + [self._name], + from_offset=from_offset, + result_type=self._type, + poll_cooldown=poll_cooldown, + ): + yield item + + +class WorkflowTopicHandle(Generic[T]): + """Workflow-side handle for publishing to a single topic. + + .. warning:: + This class is experimental and may change in future versions. + + Constructed via :meth:`WorkflowStream.topic`. Has no + ``subscribe`` — workflows do not consume their own stream. + """ + + def __init__( + self, + stream: WorkflowStream, + name: str, + type: type[T], + ) -> None: + """Bind the handle to a stream, topic name, and type. + + Prefer :meth:`WorkflowStream.topic` over calling this directly; + the factory is what records the per-stream type binding and + rejects conflicts. + """ + self._stream = stream + self._name = name + self._type = type + + @property + def name(self) -> str: + """The topic name this handle is bound to.""" + return self._name + + @property + def type(self) -> type[T]: + """The value type this handle is bound to.""" + return self._type + + def publish(self, value: T | Payload) -> None: + """Append ``value`` to the workflow stream on this topic. + + Args: + value: Value to publish. Goes through the workflow's sync + payload converter. A pre-built + :class:`temporalio.api.common.v1.Payload` bypasses + conversion, regardless of the handle's bound type. + """ + self._stream._publish_to_topic(self._name, value) diff --git a/temporalio/contrib/workflow_streams/_types.py b/temporalio/contrib/workflow_streams/_types.py new file mode 100644 index 000000000..94bfb1a9b --- /dev/null +++ b/temporalio/contrib/workflow_streams/_types.py @@ -0,0 +1,171 @@ +"""Shared data types for the Workflow Streams contrib module. + +The user-facing ``data`` fields on :class:`WorkflowStreamItem` are +:class:`temporalio.api.common.v1.Payload`. Per-item values are converted to +``Payload`` by the payload converter at publish time, and the resulting +bytes/metadata are preserved per item so subscribers can decode with +``subscribe(result_type=T)``. The codec chain (e.g. encryption, compression) +applies once at the outer signal/update envelope level — not separately to each +embedded item — so codec behavior is symmetric between workflow-side and +client-side publishing. + +The wire representation (``PublishEntry``, ``_WorkflowStreamWireItem``) uses +base64-encoded ``Payload.SerializeToString()`` bytes because the default JSON +payload converter cannot serialize a ``Payload`` embedded inside a dataclass +(it only special-cases top-level Payloads on signal/update args). +""" + +from __future__ import annotations + +import base64 +from dataclasses import dataclass, field +from datetime import datetime +from typing import Generic, TypeVar + +from temporalio.api.common.v1 import Payload + +T = TypeVar("T") + + +# basedpyright flags _-prefixed module-level functions as unused even when +# sibling modules import them (_stream.py, _client.py). Vanilla pyright does +# not. Suppressions below are required for `poe lint`. +def _encode_payload(payload: Payload) -> str: # pyright: ignore[reportUnusedFunction] + """Wire format: base64(Payload.SerializeToString()).""" + return base64.b64encode(payload.SerializeToString()).decode("ascii") + + +def _decode_payload(wire: str) -> Payload: # pyright: ignore[reportUnusedFunction] + """Inverse of :func:`_encode_payload`.""" + payload = Payload() + payload.ParseFromString(base64.b64decode(wire)) + return payload + + +@dataclass +class WorkflowStreamItem(Generic[T]): + """A single item in the workflow stream's log. + + .. warning:: + This class is experimental and may change in future versions. + + The ``data`` field carries the decoded value produced by + :meth:`WorkflowStreamClient.subscribe`. The generic parameter ``T`` + matches the ``result_type`` passed to ``subscribe``: an instance of + ``T`` when ``result_type=T``, the converter's default ``Any`` + decoding when ``result_type`` is omitted, or a + :class:`temporalio.common.RawValue` wrapping the original + ``Payload`` when ``result_type=RawValue``. + + The ``offset`` field is populated at poll time from the item's + position in the global log. + """ + + topic: str + data: T + offset: int = 0 + + +@dataclass +class PublishEntry: + """A single entry to publish via signal (wire type). + + .. warning:: + This class is experimental and may change in future versions. + + ``data`` is base64-encoded ``Payload.SerializeToString()`` output — + see module docstring for why a nested ``Payload`` cannot be used + directly. + """ + + topic: str + data: str + + +@dataclass +class PublishInput: + """Signal payload: batch of entries to publish. + + .. warning:: + This class is experimental and may change in future versions. + + Includes publisher_id and sequence to ensure exactly-once delivery. + """ + + items: list[PublishEntry] = field(default_factory=list) + publisher_id: str = "" + sequence: int = 0 + + +@dataclass +class PollInput: + """Update payload: request to poll for new items. + + .. warning:: + This class is experimental and may change in future versions. + """ + + topics: list[str] = field(default_factory=list) + from_offset: int = 0 + + +@dataclass +class _WorkflowStreamWireItem: + """Wire representation of a WorkflowStreamItem (base64 of serialized Payload).""" + + topic: str + data: str + offset: int = 0 + + +@dataclass +class PollResult: + """Update response: items matching the poll request. + + .. warning:: + This class is experimental and may change in future versions. + + ``items`` use the wire representation. When ``more_ready`` is True, + the response was truncated to stay within size limits and the + subscriber should poll again immediately rather than applying a + cooldown delay. + """ + + items: list[_WorkflowStreamWireItem] = field(default_factory=list) + next_offset: int = 0 + more_ready: bool = False + + +@dataclass +class PublisherState: + """Per-publisher dedup state. + + .. warning:: + This class is experimental and may change in future versions. + + Tracks the last accepted ``sequence`` and the ``workflow.now()`` at + which it was accepted, used together for at-least-once dedup and + TTL-based pruning at continue-as-new time. + """ + + sequence: int + last_seen: datetime + + +@dataclass +class WorkflowStreamState: + """Serializable snapshot of stream state for continue-as-new. + + .. warning:: + This class is experimental and may change in future versions. + + The containing workflow input must type the field as + ``WorkflowStreamState | None``, not ``Any``, so the default data converter + can reconstruct the dataclass from JSON. + + Log items use the wire representation for serialization stability. + """ + + log: list[_WorkflowStreamWireItem] = field(default_factory=list) + base_offset: int = 0 + publishers: dict[str, PublisherState] = field(default_factory=dict) diff --git a/tests/contrib/workflow_streams/__init__.py b/tests/contrib/workflow_streams/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/tests/contrib/workflow_streams/test_payload_roundtrip.py b/tests/contrib/workflow_streams/test_payload_roundtrip.py new file mode 100644 index 000000000..545d3a405 --- /dev/null +++ b/tests/contrib/workflow_streams/test_payload_roundtrip.py @@ -0,0 +1,137 @@ +"""Regression guards for the workflow_streams Payload wire format. + +1. The default JSON converter does not handle ``Payload`` embedded in a + dataclass — serialization fails with ``TypeError``. This rules out a + naive nested-Payload wire format. +2. A proto-serialized ``Payload`` inside a dataclass does round-trip. + This is the wire format used: base64 of ``Payload.SerializeToString()`` + inside ``PublishEntry``/``_WorkflowStreamWireItem``, surfacing + ``Payload`` (or a decoded value via ``result_type=``) at the user API. +""" + +from __future__ import annotations + +import base64 +import uuid +from dataclasses import dataclass, field + +import pytest + +from temporalio import workflow +from temporalio.api.common.v1 import Payload +from temporalio.client import Client +from tests.helpers import new_worker + + +@dataclass +class NestedPayloadEnvelope: + items: list[Payload] = field(default_factory=list) + + +@dataclass +class SerializedEntry: + topic: str + data: str # base64(Payload.SerializeToString()) + + +@dataclass +class SerializedEnvelope: + items: list[SerializedEntry] = field(default_factory=list) + + +@workflow.defn +class NestedPayloadWorkflow: + def __init__(self) -> None: + self._received: NestedPayloadEnvelope | None = None + + @workflow.signal + def receive(self, envelope: NestedPayloadEnvelope) -> None: + self._received = envelope + + @workflow.query + def decoded_strings(self) -> list[str]: + assert self._received is not None + conv = workflow.payload_converter() + return [conv.from_payload(p, str) for p in self._received.items] + + @workflow.run + async def run(self) -> None: + await workflow.wait_condition(lambda: self._received is not None) + + +@workflow.defn +class SerializedPayloadWorkflow: + def __init__(self) -> None: + self._received: SerializedEnvelope | None = None + + @workflow.signal + def receive(self, envelope: SerializedEnvelope) -> None: + self._received = envelope + + @workflow.query + def decoded_strings(self) -> list[str]: + assert self._received is not None + conv = workflow.payload_converter() + out: list[str] = [] + for entry in self._received.items: + p = Payload() + p.ParseFromString(base64.b64decode(entry.data)) + out.append(conv.from_payload(p, str)) + return out + + @workflow.query + def topics(self) -> list[str]: + assert self._received is not None + return [e.topic for e in self._received.items] + + @workflow.run + async def run(self) -> None: + await workflow.wait_condition(lambda: self._received is not None) + + +@pytest.mark.asyncio +async def test_nested_payload_in_dataclass_fails(client: Client) -> None: + """Confirm the load-bearing negative result: Payload inside dataclass doesn't serialize.""" + conv = client.data_converter.payload_converter + payloads = [conv.to_payloads([v])[0] for v in ["hello", "world"]] + envelope = NestedPayloadEnvelope(items=payloads) + + async with new_worker(client, NestedPayloadWorkflow) as worker: + handle = await client.start_workflow( + NestedPayloadWorkflow.run, + id=f"nested-payload-{uuid.uuid4()}", + task_queue=worker.task_queue, + ) + with pytest.raises(TypeError, match="Payload is not JSON serializable"): + await handle.signal(NestedPayloadWorkflow.receive, envelope) + await handle.terminate() + + +@pytest.mark.asyncio +async def test_serialized_payload_fallback_round_trips(client: Client) -> None: + """Proto-serialize Payload -> base64 -> dataclass round-trips through signal.""" + conv = client.data_converter.payload_converter + originals = ["hello", "world", "payload"] + payloads = [conv.to_payloads([v])[0] for v in originals] + envelope = SerializedEnvelope( + items=[ + SerializedEntry( + topic=f"t{i}", + data=base64.b64encode(p.SerializeToString()).decode("ascii"), + ) + for i, p in enumerate(payloads) + ] + ) + + async with new_worker(client, SerializedPayloadWorkflow) as worker: + handle = await client.start_workflow( + SerializedPayloadWorkflow.run, + id=f"serialized-payload-{uuid.uuid4()}", + task_queue=worker.task_queue, + ) + await handle.signal(SerializedPayloadWorkflow.receive, envelope) + decoded = await handle.query(SerializedPayloadWorkflow.decoded_strings) + assert decoded == originals + topics = await handle.query(SerializedPayloadWorkflow.topics) + assert topics == ["t0", "t1", "t2"] + await handle.result() diff --git a/tests/contrib/workflow_streams/test_workflow_streams.py b/tests/contrib/workflow_streams/test_workflow_streams.py new file mode 100644 index 000000000..203e1313d --- /dev/null +++ b/tests/contrib/workflow_streams/test_workflow_streams.py @@ -0,0 +1,2569 @@ +"""E2E integration tests for temporalio.contrib.workflow_streams.""" + +from __future__ import annotations + +import asyncio +import sys +import uuid +from dataclasses import dataclass +from datetime import timedelta +from typing import Any, cast +from unittest.mock import patch + +if sys.version_info >= (3, 11): + from asyncio import timeout as _async_timeout # pyright: ignore[reportUnreachable] +else: + from async_timeout import ( # pyright: ignore[reportUnreachable] + timeout as _async_timeout, + ) + +import google.protobuf.duration_pb2 +import nexusrpc +import nexusrpc.handler +import pytest + +import temporalio.api.nexus.v1 +import temporalio.api.operatorservice.v1 +import temporalio.api.workflowservice.v1 +from temporalio import activity, nexus, workflow +from temporalio.client import ( + Client, + WorkflowHandle, + WorkflowUpdateFailedError, + WorkflowUpdateStage, +) +from temporalio.common import RawValue +from temporalio.contrib.workflow_streams import ( + PollInput, + PollResult, + PublishEntry, + PublishInput, + TopicHandle, + WorkflowStream, + WorkflowStreamClient, + WorkflowStreamItem, + WorkflowStreamState, + WorkflowTopicHandle, +) +from temporalio.contrib.workflow_streams._types import _encode_payload +from temporalio.converter import DataConverter +from temporalio.exceptions import ApplicationError +from temporalio.nexus import WorkflowRunOperationContext, workflow_run_operation +from temporalio.testing import WorkflowEnvironment +from temporalio.worker import Worker +from tests.helpers import assert_eq_eventually, new_worker +from tests.helpers.nexus import make_nexus_endpoint_name + + +def _wire_bytes(data: bytes) -> str: + """Build a PublishEntry.data string from raw bytes. + + Mirrors what :class:`WorkflowStreamClient` produces on the encode path: + default payload converter turns the bytes into a ``Payload``, which + is then proto-serialized and base64-encoded for the wire. + """ + payload = DataConverter.default.payload_converter.to_payloads([data])[0] + return _encode_payload(payload) + + +# --------------------------------------------------------------------------- +# Test workflows (must be module-level, not local classes) +# --------------------------------------------------------------------------- + + +@workflow.defn +class BasicWorkflowStreamWorkflow: + @workflow.init + def __init__(self) -> None: + self.stream = WorkflowStream() + self._closed = False + + @workflow.signal + def close(self) -> None: + self._closed = True + + @workflow.run + async def run(self) -> None: + await workflow.wait_condition(lambda: self._closed) + + +@workflow.defn +class ActivityPublishWorkflow: + @workflow.init + def __init__(self, count: int) -> None: + self.stream = WorkflowStream() + self._closed = False + + @workflow.signal + def close(self) -> None: + self._closed = True + + @workflow.run + async def run(self, count: int) -> None: + await workflow.execute_activity( + "publish_items", + count, + start_to_close_timeout=timedelta(seconds=30), + heartbeat_timeout=timedelta(seconds=10), + ) + self.stream.topic("status", type=bytes).publish(b"activity_done") + await workflow.wait_condition(lambda: self._closed) + + +@dataclass +class AgentEvent: + kind: str + payload: dict[str, Any] + + +@workflow.defn +class StructuredPublishWorkflow: + @workflow.init + def __init__(self, count: int) -> None: + self.stream = WorkflowStream() + self._closed = False + + @workflow.signal + def close(self) -> None: + self._closed = True + + @workflow.run + async def run(self, count: int) -> None: + for i in range(count): + self.stream.topic("events", type=AgentEvent).publish( + AgentEvent(kind="tick", payload={"i": i}) + ) + await workflow.wait_condition(lambda: self._closed) + + +@workflow.defn +class TopicHandlePublishWorkflow: + """Workflow that publishes via the workflow-side topic handle.""" + + @workflow.init + def __init__(self, count: int) -> None: + self.stream = WorkflowStream() + self.events = self.stream.topic("events", type=AgentEvent) + self._closed = False + + @workflow.signal + def close(self) -> None: + self._closed = True + + @workflow.run + async def run(self, count: int) -> None: + for i in range(count): + self.events.publish(AgentEvent(kind="tick", payload={"i": i})) + await workflow.wait_condition(lambda: self._closed) + + +@workflow.defn +class WorkflowSidePublishWorkflow: + @workflow.init + def __init__(self, count: int) -> None: + self.stream = WorkflowStream() + self._closed = False + + @workflow.signal + def close(self) -> None: + self._closed = True + + @workflow.run + async def run(self, count: int) -> None: + for i in range(count): + self.stream.topic("events", type=bytes).publish(f"item-{i}".encode()) + await workflow.wait_condition(lambda: self._closed) + + +@workflow.defn +class MultiTopicWorkflow: + @workflow.init + def __init__(self, count: int) -> None: + self.stream = WorkflowStream() + self._closed = False + + @workflow.signal + def close(self) -> None: + self._closed = True + + @workflow.run + async def run(self, count: int) -> None: + await workflow.execute_activity( + "publish_multi_topic", + count, + start_to_close_timeout=timedelta(seconds=30), + heartbeat_timeout=timedelta(seconds=10), + ) + await workflow.wait_condition(lambda: self._closed) + + +@workflow.defn +class InterleavedWorkflow: + @workflow.init + def __init__(self, count: int) -> None: + self.stream = WorkflowStream() + self._closed = False + + @workflow.signal + def close(self) -> None: + self._closed = True + + @workflow.run + async def run(self, count: int) -> None: + self.stream.topic("status", type=bytes).publish(b"started") + await workflow.execute_activity( + "publish_items", + count, + start_to_close_timeout=timedelta(seconds=30), + heartbeat_timeout=timedelta(seconds=10), + ) + self.stream.topic("status", type=bytes).publish(b"done") + await workflow.wait_condition(lambda: self._closed) + + +@workflow.defn +class PriorityWorkflow: + @workflow.init + def __init__(self) -> None: + self.stream = WorkflowStream() + self._closed = False + + @workflow.signal + def close(self) -> None: + self._closed = True + + @workflow.run + async def run(self) -> None: + await workflow.execute_activity( + "publish_with_priority", + start_to_close_timeout=timedelta(seconds=30), + heartbeat_timeout=timedelta(seconds=10), + ) + await workflow.wait_condition(lambda: self._closed) + + +@workflow.defn +class FlushOnExitWorkflow: + @workflow.init + def __init__(self, count: int) -> None: + self.stream = WorkflowStream() + self._closed = False + + @workflow.signal + def close(self) -> None: + self._closed = True + + @workflow.run + async def run(self, count: int) -> None: + await workflow.execute_activity( + "publish_batch_test", + count, + start_to_close_timeout=timedelta(seconds=30), + heartbeat_timeout=timedelta(seconds=10), + ) + await workflow.wait_condition(lambda: self._closed) + + +@workflow.defn +class MaxBatchWorkflow: + @workflow.init + def __init__(self, count: int) -> None: + self.stream = WorkflowStream() + self._closed = False + + @workflow.signal + def close(self) -> None: + self._closed = True + + @workflow.query + def publisher_sequences(self) -> dict[str, int]: + return {pid: ps.sequence for pid, ps in self.stream._publishers.items()} + + @workflow.run + async def run(self, count: int) -> None: + await workflow.execute_activity( + "publish_with_max_batch", + count, + start_to_close_timeout=timedelta(seconds=30), + heartbeat_timeout=timedelta(seconds=10), + ) + self.stream.topic("status", type=bytes).publish(b"activity_done") + await workflow.wait_condition(lambda: self._closed) + + +@workflow.defn +class LateWorkflowStreamWorkflow: + """Calls WorkflowStream() from @workflow.run, not from @workflow.init. + + The constructor inspects the caller's frame and requires the + function name to be ``__init__``; called from ``run``, it must + raise ``RuntimeError``. The workflow returns the error message so + the test can assert on it without forcing a workflow task failure. + """ + + @workflow.run + async def run(self) -> str: + try: + WorkflowStream() + except RuntimeError as e: + return str(e) + return "no error raised" + + +@workflow.defn +class DoubleInitWorkflow: + """Calls WorkflowStream() twice from @workflow.init. + + The first call succeeds; the second must raise RuntimeError because + the workflow stream signal handler is already registered. The workflow + stashes the error message so the test can assert on it without + forcing a workflow task failure. + """ + + @workflow.init + def __init__(self) -> None: + self.stream = WorkflowStream() + self._closed = False + self.double_init_error: str | None = None + try: + WorkflowStream() + except RuntimeError as e: + self.double_init_error = str(e) + + @workflow.signal + def close(self) -> None: + self._closed = True + + @workflow.query + def get_double_init_error(self) -> str | None: + return self.double_init_error + + @workflow.run + async def run(self) -> None: + await workflow.wait_condition(lambda: self._closed) + + +# --------------------------------------------------------------------------- +# Activities +# --------------------------------------------------------------------------- + + +@activity.defn(name="publish_items") +async def publish_items(count: int) -> None: + client = WorkflowStreamClient.from_within_activity( + batch_interval=timedelta(milliseconds=500) + ) + async with client: + for i in range(count): + activity.heartbeat() + client.topic("events", type=bytes).publish(f"item-{i}".encode()) + + +@activity.defn(name="publish_multi_topic") +async def publish_multi_topic(count: int) -> None: + topics = ["a", "b", "c"] + client = WorkflowStreamClient.from_within_activity( + batch_interval=timedelta(milliseconds=500) + ) + async with client: + for i in range(count): + activity.heartbeat() + topic = topics[i % len(topics)] + client.topic(topic, type=bytes).publish(f"{topic}-{i}".encode()) + + +@activity.defn(name="publish_with_priority") +async def publish_with_priority() -> None: + # Long batch_interval AND long post-publish hold ensure that only a + # working force_flush wakeup can deliver items before __aexit__ flushes. + # The hold is deliberately much longer than the test's collect timeout + # so a regression (force_flush no-op) surfaces as a missing item rather + # than flaking on slow CI. + client = WorkflowStreamClient.from_within_activity( + batch_interval=timedelta(seconds=60) + ) + async with client: + client.topic("events", type=bytes).publish(b"normal-0") + client.topic("events", type=bytes).publish(b"normal-1") + client.topic("events", type=bytes).publish(b"priority", force_flush=True) + for _ in range(100): + activity.heartbeat() + await asyncio.sleep(0.1) + + +@activity.defn(name="publish_batch_test") +async def publish_batch_test(count: int) -> None: + client = WorkflowStreamClient.from_within_activity( + batch_interval=timedelta(seconds=60) + ) + async with client: + for i in range(count): + activity.heartbeat() + client.topic("events", type=bytes).publish(f"item-{i}".encode()) + + +@activity.defn(name="publish_with_max_batch") +async def publish_with_max_batch(count: int) -> None: + client = WorkflowStreamClient.from_within_activity( + batch_interval=timedelta(seconds=60), max_batch_size=3 + ) + async with client: + for i in range(count): + activity.heartbeat() + client.topic("events", type=bytes).publish(f"item-{i}".encode()) + # Yield so the flusher task can run when max_batch_size triggers + # _flush_event. Real workloads (e.g. agents awaiting LLM streams) + # yield constantly; a tight loop with no awaits would never let + # the flusher fire and would collapse back to exit-only flushing. + await asyncio.sleep(0) + # Long batch_interval ensures only max_batch_size triggers flushes. + # Context manager exit flushes any remainder. + + +# --------------------------------------------------------------------------- +# Helpers +# --------------------------------------------------------------------------- + + +async def _is_different_run( + old_handle: WorkflowHandle[Any, Any], + new_handle: WorkflowHandle[Any, Any], +) -> bool: + """Check if new_handle points to a different run than old_handle.""" + try: + desc = await new_handle.describe() + return desc.run_id != old_handle.result_run_id + except Exception: + return False + + +async def collect_items( + client: Client, + handle: WorkflowHandle[Any, Any], + topics: list[str] | None, + from_offset: int, + expected_count: int, + timeout: float = 15.0, + *, + result_type: type | None = bytes, +) -> list[WorkflowStreamItem]: + """Subscribe and collect exactly expected_count items, with timeout. + + Default ``result_type=bytes`` matches the bytes-oriented tests that + compare ``item.data`` against literal byte strings. Pass + ``result_type=None`` for the converter's default ``Any`` decoding, + or ``result_type=RawValue`` for a ``RawValue``-wrapped ``Payload``. + """ + stream = WorkflowStreamClient.create(client, handle.id) + items: list[WorkflowStreamItem] = [] + try: + async with _async_timeout(timeout): + async for item in stream.subscribe( + topics=topics, + from_offset=from_offset, + poll_cooldown=timedelta(0), + result_type=result_type, + ): + items.append(item) + if len(items) >= expected_count: + break + except asyncio.TimeoutError: + pass + return items + + +# --------------------------------------------------------------------------- +# Tests +# --------------------------------------------------------------------------- + + +@pytest.mark.asyncio +async def test_activity_publish_and_subscribe(client: Client) -> None: + """Activity publishes items, external client subscribes and receives them.""" + count = 10 + async with new_worker( + client, + ActivityPublishWorkflow, + activities=[publish_items], + ) as worker: + handle = await client.start_workflow( + ActivityPublishWorkflow.run, + count, + id=f"workflow-stream-basic-{uuid.uuid4()}", + task_queue=worker.task_queue, + ) + # Collect activity items + the "activity_done" status item + items = await collect_items(client, handle, None, 0, count + 1) + assert len(items) == count + 1 + + # Check activity items + for i in range(count): + assert items[i].topic == "events" + assert items[i].data == f"item-{i}".encode() + + # Check workflow-side status item + assert items[count].topic == "status" + assert items[count].data == b"activity_done" + + await handle.signal(ActivityPublishWorkflow.close) + + +@pytest.mark.asyncio +async def test_structured_type_round_trip(client: Client) -> None: + """Workflow publishes dataclass values; subscriber decodes via result_type.""" + count = 4 + async with new_worker(client, StructuredPublishWorkflow) as worker: + handle = await client.start_workflow( + StructuredPublishWorkflow.run, + count, + id=f"workflow-stream-structured-{uuid.uuid4()}", + task_queue=worker.task_queue, + ) + + items = await collect_items( + client, handle, None, 0, count, result_type=AgentEvent + ) + assert len(items) == count + for i, item in enumerate(items): + assert isinstance(item.data, AgentEvent) + assert item.data == AgentEvent(kind="tick", payload={"i": i}) + + await handle.signal(StructuredPublishWorkflow.close) + + +@pytest.mark.asyncio +async def test_subscribe_default_decode_and_raw_value(client: Client) -> None: + """No ``result_type`` decodes via Any; ``result_type=RawValue`` yields a ``Payload``.""" + count = 2 + async with new_worker(client, StructuredPublishWorkflow) as worker: + handle = await client.start_workflow( + StructuredPublishWorkflow.run, + count, + id=f"workflow-stream-default-decode-{uuid.uuid4()}", + task_queue=worker.task_queue, + ) + + any_items = await collect_items( + client, handle, None, 0, count, result_type=None + ) + assert len(any_items) == count + for i, item in enumerate(any_items): + # Default JSON converter decodes a dataclass to a plain dict. + assert item.data == {"kind": "tick", "payload": {"i": i}} + + raw_items = await collect_items( + client, handle, None, 0, count, result_type=RawValue + ) + assert len(raw_items) == count + for item in raw_items: + assert isinstance(item.data, RawValue) + assert item.data.payload.data # non-empty serialized JSON bytes + + await handle.signal(StructuredPublishWorkflow.close) + + +@pytest.mark.asyncio +async def test_subscribe_with_payload_result_type_rejected(client: Client) -> None: + """``subscribe(result_type=Payload)`` raises — there is no Payload decode path. + + Mirrors the topic-handle rejection (``stream.topic(name, type=Payload)``) + so the direct ``subscribe`` API can't smuggle in the same ambiguity that + the topic-handle layer already guards against. Users wanting raw payloads + pass ``result_type=RawValue``. + """ + from temporalio.api.common.v1 import Payload + + handle = client.get_workflow_handle("nonexistent-workflow-id") + stream = WorkflowStreamClient(handle) + with pytest.raises(RuntimeError, match="result_type=Payload"): + async for _ in stream.subscribe(result_type=Payload): + pass + + +@pytest.mark.asyncio +async def test_topic_handle_workflow_side_publish_and_subscribe( + client: Client, +) -> None: + """Workflow publishes via WorkflowStream.topic; client subscribes via TopicHandle.""" + count = 3 + async with new_worker(client, TopicHandlePublishWorkflow) as worker: + handle = await client.start_workflow( + TopicHandlePublishWorkflow.run, + count, + id=f"workflow-stream-topic-handle-{uuid.uuid4()}", + task_queue=worker.task_queue, + ) + + stream = WorkflowStreamClient.create(client, handle.id) + events = stream.topic("events", type=AgentEvent) + assert isinstance(events, TopicHandle) + assert events.name == "events" + assert events.type is AgentEvent + + items: list[WorkflowStreamItem] = [] + async with _async_timeout(15.0): + async for item in events.subscribe(poll_cooldown=timedelta(0)): + items.append(item) + if len(items) >= count: + break + assert [item.data for item in items] == [ + AgentEvent(kind="tick", payload={"i": i}) for i in range(count) + ] + + await handle.signal(TopicHandlePublishWorkflow.close) + + +@workflow.defn +class TopicHandleUniquenessWorkflow: + """Probes the WorkflowStream.topic uniqueness check in @workflow.init. + + Returns a tuple (idempotent_ok, error_message) so the test can assert + both branches: same-type rebind is silent, different-type rebind raises. + """ + + @workflow.init + def __init__(self) -> None: + from temporalio.api.common.v1 import Payload + + self.stream = WorkflowStream() + first = self.stream.topic("events", type=AgentEvent) + self._idempotent_ok = ( + isinstance( + self.stream.topic("events", type=AgentEvent), WorkflowTopicHandle + ) + and first.type is AgentEvent + ) + try: + self.stream.topic("events", type=bytes) + except RuntimeError as exc: + self._error = str(exc) + else: + self._error = "" + try: + self.stream.topic("misused", type=Payload) + except RuntimeError as exc: + self._payload_error = str(exc) + else: + self._payload_error = "" + + @workflow.run + async def run(self) -> tuple[bool, str, str]: + return (self._idempotent_ok, self._error, self._payload_error) + + +@pytest.mark.asyncio +async def test_topic_handle_uniqueness_on_workflow_stream(client: Client) -> None: + """Same-type rebind is idempotent; different-type rebind raises in @workflow.init. + + Also covers the workflow-side rejection of ``type=Payload`` — + binding a topic to ``Payload`` itself has no decode path, so + ``WorkflowStream.topic`` raises in ``@workflow.init``. + """ + async with new_worker(client, TopicHandleUniquenessWorkflow) as worker: + idempotent_ok, error, payload_error = await client.execute_workflow( + TopicHandleUniquenessWorkflow.run, + id=f"workflow-stream-handle-unique-{uuid.uuid4()}", + task_queue=worker.task_queue, + ) + assert idempotent_ok is True + assert "already bound to type" in error + assert "events" in error + assert "type=Payload" in payload_error + + +@pytest.mark.asyncio +async def test_topic_handle_client_uniqueness(client: Client) -> None: + """Re-binding a topic name to a different type on a client raises.""" + handle = client.get_workflow_handle("nonexistent-workflow-id") + stream = WorkflowStreamClient(handle) + + first = stream.topic("events", type=AgentEvent) + assert first.name == "events" + assert first.type is AgentEvent + + # Same type is idempotent. + again = stream.topic("events", type=AgentEvent) + assert again.type is AgentEvent + + # Different type raises. + with pytest.raises(RuntimeError, match="already bound to type"): + stream.topic("events", type=bytes) + + # Different topic with a different type is fine. + other = stream.topic("other", type=bytes) + assert other.type is bytes + + # Any escape hatch coexists on a different topic. Omitting ``type`` + # is the documented form (defaults to ``typing.Any``); we also + # exercise the explicit ``type=Any`` path with the cast required + # because ``Any`` is a typing special form rather than a class. + raw = stream.topic("forwarded") + assert raw.type is Any + explicit = stream.topic( + "forwarded-explicit", type=cast(type[Any], cast(object, Any)) + ) + assert explicit.type is Any + + # Binding to Payload itself is rejected — subscribers would have + # no decode path. Pre-built Payload values can still be published + # via a normally-typed handle (zero-copy fast path). + from temporalio.api.common.v1 import Payload + + with pytest.raises(RuntimeError, match="type=Payload"): + stream.topic("misused", type=Payload) + + +@pytest.mark.asyncio +async def test_topic_handle_payload_passthrough(client: Client) -> None: + """Pre-built Payloads pass through topic.publish regardless of bound type.""" + count = 2 + async with new_worker(client, BasicWorkflowStreamWorkflow) as worker: + handle = await client.start_workflow( + BasicWorkflowStreamWorkflow.run, + id=f"workflow-stream-handle-payload-{uuid.uuid4()}", + task_queue=worker.task_queue, + ) + + stream = WorkflowStreamClient.create( + client, handle.id, batch_interval=timedelta(milliseconds=50) + ) + events = stream.topic("events", type=bytes) + async with stream: + converter = DataConverter.default.payload_converter + for i in range(count): + payload = converter.to_payloads([f"raw-{i}".encode()])[0] + events.publish(payload) + await stream.flush() + + items = await collect_items(client, handle, ["events"], 0, count) + assert [item.data for item in items] == [ + f"raw-{i}".encode() for i in range(count) + ] + + await handle.signal(BasicWorkflowStreamWorkflow.close) + + +@pytest.mark.asyncio +async def test_topic_filtering(client: Client) -> None: + """Publish to multiple topics, subscribe with filter.""" + count = 9 # 3 per topic + async with new_worker( + client, + MultiTopicWorkflow, + activities=[publish_multi_topic], + ) as worker: + handle = await client.start_workflow( + MultiTopicWorkflow.run, + count, + id=f"workflow-stream-filter-{uuid.uuid4()}", + task_queue=worker.task_queue, + ) + + # Subscribe to topic "a" only — should get 3 items + a_items = await collect_items(client, handle, ["a"], 0, 3) + assert len(a_items) == 3 + assert all(item.topic == "a" for item in a_items) + + # Subscribe to ["a", "c"] — should get 6 items + ac_items = await collect_items(client, handle, ["a", "c"], 0, 6) + assert len(ac_items) == 6 + assert all(item.topic in ("a", "c") for item in ac_items) + + # Subscribe to all (None) — should get all 9 + all_items = await collect_items(client, handle, None, 0, 9) + assert len(all_items) == 9 + + await handle.signal(MultiTopicWorkflow.close) + + +@pytest.mark.asyncio +async def test_subscribe_from_offset_and_per_item_offsets(client: Client) -> None: + """Subscribe from zero and non-zero offsets; each item carries its global offset.""" + count = 5 + async with new_worker( + client, + WorkflowSidePublishWorkflow, + ) as worker: + handle = await client.start_workflow( + WorkflowSidePublishWorkflow.run, + count, + id=f"workflow-stream-offset-{uuid.uuid4()}", + task_queue=worker.task_queue, + ) + + # Subscribe from offset 0 — all items, offsets 0..count-1 + all_items = await collect_items(client, handle, None, 0, count) + assert len(all_items) == count + for i, item in enumerate(all_items): + assert item.offset == i + assert item.data == f"item-{i}".encode() + + # Subscribe from offset 3 — items 3, 4 with offsets 3, 4 + later_items = await collect_items(client, handle, None, 3, 2) + assert len(later_items) == 2 + assert later_items[0].offset == 3 + assert later_items[0].data == b"item-3" + assert later_items[1].offset == 4 + assert later_items[1].data == b"item-4" + + await handle.signal(WorkflowSidePublishWorkflow.close) + + +@pytest.mark.asyncio +async def test_per_item_offsets_with_topic_filter(client: Client) -> None: + """Per-item offsets are global (not per-topic) even when filtering.""" + count = 9 # 3 per topic (a, b, c round-robin) + async with new_worker( + client, + MultiTopicWorkflow, + activities=[publish_multi_topic], + ) as worker: + handle = await client.start_workflow( + MultiTopicWorkflow.run, + count, + id=f"workflow-stream-item-offset-filter-{uuid.uuid4()}", + task_queue=worker.task_queue, + ) + + # Subscribe to topic "a" only — items are at global offsets 0, 3, 6 + a_items = await collect_items(client, handle, ["a"], 0, 3) + assert len(a_items) == 3 + assert a_items[0].offset == 0 + assert a_items[1].offset == 3 + assert a_items[2].offset == 6 + + # Subscribe to topic "b" — items are at global offsets 1, 4, 7 + b_items = await collect_items(client, handle, ["b"], 0, 3) + assert len(b_items) == 3 + assert b_items[0].offset == 1 + assert b_items[1].offset == 4 + assert b_items[2].offset == 7 + + await handle.signal(MultiTopicWorkflow.close) + + +@pytest.mark.asyncio +async def test_poll_truncated_offset_returns_application_error(client: Client) -> None: + """Polling a truncated offset raises ApplicationError (not ValueError) + and does not crash the workflow task.""" + async with new_worker( + client, + TruncateWorkflow, + ) as worker: + handle = await client.start_workflow( + TruncateWorkflow.run, + 5, + id=f"workflow-stream-trunc-error-{uuid.uuid4()}", + task_queue=worker.task_queue, + ) + + # Truncate up to offset 3 via update — completion is explicit. + await handle.execute_update("truncate", 3) + + # Poll from offset 1 (truncated) — should get ApplicationError, + # NOT crash the workflow task. Catching WorkflowUpdateFailedError is + # sufficient to prove the handler raised ApplicationError: Temporal's + # update protocol completes the update with this error only when the + # handler raises ApplicationError. A bare ValueError (or any other + # exception) would fail the workflow task instead, causing + # execute_update to hang — not raise. The follow-up collect_items + # below proves the workflow task wasn't poisoned. + with pytest.raises(WorkflowUpdateFailedError) as exc_info: + await handle.execute_update( + "__temporal_workflow_stream_poll", + PollInput(topics=[], from_offset=1), + result_type=PollResult, + ) + cause = exc_info.value.cause + assert isinstance(cause, ApplicationError) + assert cause.type == "TruncatedOffset" + + # Workflow should still be usable — poll from valid offset 3 + items = await collect_items(client, handle, None, 3, 2) + assert len(items) == 2 + assert items[0].offset == 3 + + await handle.signal("close") + + +@pytest.mark.asyncio +async def test_truncate_past_end_raises_application_error(client: Client) -> None: + """truncate() with an offset past the log end raises ApplicationError + (type=TruncateOutOfRange) — the update surfaces as a clean failure + without poisoning the workflow task.""" + async with new_worker( + client, + TruncateWorkflow, + ) as worker: + handle = await client.start_workflow( + TruncateWorkflow.run, + 2, + id=f"workflow-stream-trunc-oor-{uuid.uuid4()}", + task_queue=worker.task_queue, + ) + + # Only 2 items exist; asking to truncate to offset 5 is out of range. + with pytest.raises(WorkflowUpdateFailedError) as exc_info: + await handle.execute_update("truncate", 5) + cause = exc_info.value.cause + assert isinstance(cause, ApplicationError) + assert cause.type == "TruncateOutOfRange" + + # Workflow task wasn't poisoned — a valid poll still completes. + items = await collect_items(client, handle, None, 0, 2) + assert len(items) == 2 + + await handle.signal("close") + + +@pytest.mark.asyncio +async def test_subscribe_recovers_from_truncation(client: Client) -> None: + """subscribe() auto-recovers when offset falls behind truncation.""" + async with new_worker( + client, + TruncateWorkflow, + ) as worker: + handle = await client.start_workflow( + TruncateWorkflow.run, + 5, + id=f"workflow-stream-trunc-recover-{uuid.uuid4()}", + task_queue=worker.task_queue, + ) + + # Truncate first 3. The update returns after the handler completes. + await handle.execute_update("truncate", 3) + + # subscribe from offset 1 (truncated) — should auto-recover + # and deliver items from base_offset (3) + stream = WorkflowStreamClient(handle) + items: list[WorkflowStreamItem] = [] + try: + async with _async_timeout(5): + async for item in stream.subscribe( + from_offset=1, poll_cooldown=timedelta(0), result_type=bytes + ): + items.append(item) + if len(items) >= 2: + break + except asyncio.TimeoutError: + pass + assert len(items) == 2 + assert items[0].offset == 3 + + await handle.signal("close") + + +@pytest.mark.asyncio +async def test_truncate_during_waiting_poll_raises_truncated_offset( + client: Client, +) -> None: + """A truncate that advances ``base_offset`` past a waiting poll's + ``from_offset`` must wake the poll and raise ``TruncatedOffset``. + + Reproduces the bug where ``_on_poll`` captured ``log_offset`` once + before ``wait_condition`` and then sliced ``self._log[log_offset:]`` + against the post-truncate state. With the old predicate + ``len(self._log) > log_offset`` the wait would either never fire + (truncation shrinks the log below the captured offset) or fire on a + later publish and silently emit the wrong items at offsets the + subscriber had already moved past. + """ + async with new_worker(client, TruncateRaceWorkflow) as worker: + handle = await client.start_workflow( + TruncateRaceWorkflow.run, + id=f"workflow-stream-trunc-race-{uuid.uuid4()}", + task_queue=worker.task_queue, + ) + + # Seed: 5 items at offsets 0..4. base_offset stays 0. + await handle.execute_update(TruncateRaceWorkflow.publish, 5) + + # Park a poll from offset=10 — past the current end of the log. + # With wait_for_stage=ACCEPTED the handler has begun executing + # and is parked at workflow.wait_condition by the time the + # client gets the handle back. + poll_handle = await handle.start_update( + "__temporal_workflow_stream_poll", + PollInput(topics=[], from_offset=10), + result_type=PollResult, + wait_for_stage=WorkflowUpdateStage.ACCEPTED, + ) + + # In one workflow activation: publish 7 more items (log grows to + # 12 entries at offsets 0..11) and then truncate to 11. Result: + # base_offset=11, log=[item @11]. The waiting poll's + # from_offset=10 is now strictly less than base_offset, so the + # fixed predicate must wake it and the post-wait recompute must + # raise TruncatedOffset. Both halves of the fix are exercised: + # without the predicate change the wait stays asleep through + # this activation; without the post-wait recompute the slice + # silently returns wrong items / next_offset. + await handle.execute_update(TruncateRaceWorkflow.publish_then_truncate, (7, 11)) + + with pytest.raises(WorkflowUpdateFailedError) as exc_info: + await poll_handle.result() + cause = exc_info.value.cause + assert isinstance(cause, ApplicationError) + assert cause.type == "TruncatedOffset" + + await handle.signal(TruncateRaceWorkflow.close) + + +@pytest.mark.asyncio +async def test_workflow_and_activity_publish_interleaved(client: Client) -> None: + """Workflow publishes status events around activity publishing.""" + count = 5 + async with new_worker( + client, + InterleavedWorkflow, + activities=[publish_items], + ) as worker: + handle = await client.start_workflow( + InterleavedWorkflow.run, + count, + id=f"workflow-stream-interleave-{uuid.uuid4()}", + task_queue=worker.task_queue, + ) + + # Total: 1 (started) + count (activity) + 1 (done) = count + 2 + items = await collect_items(client, handle, None, 0, count + 2) + assert len(items) == count + 2 + + # First item is workflow-side "started" + assert items[0].topic == "status" + assert items[0].data == b"started" + + # Middle items are from activity + for i in range(count): + assert items[i + 1].topic == "events" + assert items[i + 1].data == f"item-{i}".encode() + + # Last item is workflow-side "done" + assert items[count + 1].topic == "status" + assert items[count + 1].data == b"done" + + await handle.signal(InterleavedWorkflow.close) + + +@pytest.mark.asyncio +async def test_priority_flush(client: Client) -> None: + """Priority publish triggers immediate flush without waiting for timer.""" + async with new_worker( + client, + PriorityWorkflow, + activities=[publish_with_priority], + ) as worker: + handle = await client.start_workflow( + PriorityWorkflow.run, + id=f"workflow-stream-priority-{uuid.uuid4()}", + task_queue=worker.task_queue, + ) + + # If priority works, items arrive within milliseconds of the publish. + # The activity holds for ~10s after priority publish; this timeout + # gives plenty of margin for workflow/worker scheduling on slow CI + # while staying well below the activity hold so a regression (no + # priority wakeup) surfaces as a missing item, not a pass via + # __aexit__ flush. + items = await collect_items(client, handle, None, 0, 3, timeout=5.0) + assert len(items) == 3 + assert items[2].data == b"priority" + + await handle.signal(PriorityWorkflow.close) + + +@pytest.mark.asyncio +async def test_iterator_cancellation(client: Client) -> None: + """Cancelling a subscription iterator after it has yielded an item + completes cleanly.""" + async with new_worker( + client, + BasicWorkflowStreamWorkflow, + ) as worker: + handle = await client.start_workflow( + BasicWorkflowStreamWorkflow.run, + id=f"workflow-stream-cancel-{uuid.uuid4()}", + task_queue=worker.task_queue, + ) + + # Seed one item so the iterator provably reaches an active state + # before we cancel — no sleep-based wait. + await handle.signal( + "__temporal_workflow_stream_publish", + PublishInput( + items=[PublishEntry(topic="events", data=_wire_bytes(b"seed"))] + ), + ) + + stream_client = WorkflowStreamClient.create(client, handle.id) + first_item = asyncio.Event() + items: list[WorkflowStreamItem] = [] + + async def subscribe_and_collect() -> None: + async for item in stream_client.subscribe( + from_offset=0, poll_cooldown=timedelta(0), result_type=bytes + ): + items.append(item) + first_item.set() + + task = asyncio.create_task(subscribe_and_collect()) + # Bounded wait so a subscribe regression fails fast instead of hanging. + async with _async_timeout(5): + await first_item.wait() + task.cancel() + try: + await task + except asyncio.CancelledError: + pass + + assert len(items) == 1 + assert items[0].data == b"seed" + + await handle.signal(BasicWorkflowStreamWorkflow.close) + + +@pytest.mark.asyncio +async def test_context_manager_flushes_on_exit(client: Client) -> None: + """Context manager exit flushes all buffered items.""" + count = 5 + async with new_worker( + client, + FlushOnExitWorkflow, + activities=[publish_batch_test], + ) as worker: + handle = await client.start_workflow( + FlushOnExitWorkflow.run, + count, + id=f"workflow-stream-flush-{uuid.uuid4()}", + task_queue=worker.task_queue, + ) + + # Despite 60s batch interval, all items arrive because __aexit__ flushes + items = await collect_items(client, handle, None, 0, count, timeout=15.0) + assert len(items) == count + for i in range(count): + assert items[i].data == f"item-{i}".encode() + + await handle.signal(FlushOnExitWorkflow.close) + + +@pytest.mark.asyncio +async def test_explicit_flush_barrier(client: Client) -> None: + """``await client.flush()`` is a synchronization point. + + Verifies the documented contract: + 1. Returns immediately when the buffer is empty. + 2. After it returns, items published before the call are durable + on the workflow side (observable via ``get_offset()``) — even + when the timer-driven flush would not yet have fired. + 3. Calling it again after a successful flush is a no-op. + + Uses a 60s ``batch_interval`` so a regression where ``flush()`` + silently relies on the background timer surfaces as a hang + against the test's 5s timeout, not a slow pass. + """ + async with new_worker( + client, + BasicWorkflowStreamWorkflow, + ) as worker: + handle = await client.start_workflow( + BasicWorkflowStreamWorkflow.run, + id=f"workflow-stream-flush-barrier-{uuid.uuid4()}", + task_queue=worker.task_queue, + ) + + stream = WorkflowStreamClient.create( + client, handle.id, batch_interval=timedelta(seconds=60) + ) + + async with _async_timeout(5): + # 1. Empty-buffer flush is a no-op (must not block). + assert await stream.get_offset() == 0 + await stream.flush() + assert await stream.get_offset() == 0 + + # 2. Flush makes prior publishes visible without waiting on + # the 60s batch timer. + stream.topic("events", type=bytes).publish(b"a") + stream.topic("events", type=bytes).publish(b"b") + stream.topic("events", type=bytes).publish(b"c") + await stream.flush() + assert await stream.get_offset() == 3 + + # 3. Second flush with no new items is a no-op. + await stream.flush() + assert await stream.get_offset() == 3 + + await handle.signal(BasicWorkflowStreamWorkflow.close) + + +@pytest.mark.asyncio +async def test_concurrent_subscribers(client: Client) -> None: + """Two subscribers on different topics make interleaved progress. + + Publishes A-0, waits for subscriber A to observe it; publishes B-0, + waits for subscriber B to observe it. At this point both subscribers + have received exactly one item and are polling for their second, + so both subscriptions are provably in flight at the same time. + Then publishes A-1, B-1 the same way. A sequential execution (A drains + then B starts) cannot satisfy the ordering because B's first item + isn't published until after A has already received its first. + """ + async with new_worker( + client, + BasicWorkflowStreamWorkflow, + ) as worker: + handle = await client.start_workflow( + BasicWorkflowStreamWorkflow.run, + id=f"workflow-stream-concurrent-{uuid.uuid4()}", + task_queue=worker.task_queue, + ) + + stream = WorkflowStreamClient(handle) + a_items: list[WorkflowStreamItem] = [] + b_items: list[WorkflowStreamItem] = [] + a_got = [asyncio.Event(), asyncio.Event()] + b_got = [asyncio.Event(), asyncio.Event()] + + async def collect( + topic: str, + collected: list[WorkflowStreamItem], + events: list[asyncio.Event], + ) -> None: + async for item in stream.subscribe( + topics=[topic], + from_offset=0, + poll_cooldown=timedelta(0), + result_type=bytes, + ): + collected.append(item) + events[len(collected) - 1].set() + if len(collected) >= len(events): + break + + a_task = asyncio.create_task(collect("a", a_items, a_got)) + b_task = asyncio.create_task(collect("b", b_items, b_got)) + + async def publish(topic: str, data: bytes) -> None: + await handle.signal( + "__temporal_workflow_stream_publish", + PublishInput(items=[PublishEntry(topic=topic, data=_wire_bytes(data))]), + ) + + try: + async with _async_timeout(10): + await publish("a", b"a-0") + await a_got[0].wait() + await publish("b", b"b-0") + await b_got[0].wait() + # Both subscribers are now mid-subscription, each having + # seen one item and polling for the next. + await publish("a", b"a-1") + await a_got[1].wait() + await publish("b", b"b-1") + await b_got[1].wait() + + await asyncio.gather(a_task, b_task) + finally: + a_task.cancel() + b_task.cancel() + + assert [i.data for i in a_items] == [b"a-0", b"a-1"] + assert [i.data for i in b_items] == [b"b-0", b"b-1"] + + await handle.signal(BasicWorkflowStreamWorkflow.close) + + +@pytest.mark.asyncio +async def test_max_batch_size(client: Client) -> None: + """max_batch_size triggers auto-flush without waiting for timer.""" + count = 7 # with max_batch_size=3: flushes at 3, 6, then remainder 1 on exit + async with new_worker( + client, + MaxBatchWorkflow, + activities=[publish_with_max_batch], + max_cached_workflows=0, + ) as worker: + handle = await client.start_workflow( + MaxBatchWorkflow.run, + count, + id=f"workflow-stream-maxbatch-{uuid.uuid4()}", + task_queue=worker.task_queue, + ) + # count items from activity + 1 "activity_done" from workflow + items = await collect_items(client, handle, None, 0, count + 1, timeout=15.0) + assert len(items) == count + 1 + for i in range(count): + assert items[i].data == f"item-{i}".encode() + + # max_batch_size actually engages: at least one flush fires during + # the publish loop, so 7 items ship as >=2 signals. Without this + # assertion the test would pass even if max_batch_size were ignored + # and all 7 items went out in a single exit-time flush (batch_count + # == 1). Note: max_batch_size is a *trigger* threshold, not a cap — + # the flusher may take more items from the buffer than max_batch_size + # if more were added while a prior signal was in flight, so the exact + # batch count depends on interleaving. Asserting >= 2 is the + # non-flaky way to verify the mechanism is live. + seqs = await handle.query(MaxBatchWorkflow.publisher_sequences) + assert len(seqs) == 1, f"expected one publisher, got {seqs}" + (batch_count,) = seqs.values() + assert batch_count >= 2, ( + f"expected >=2 batches with max_batch_size=3 and 7 items, got " + f"{batch_count} — max_batch_size did not trigger a mid-loop flush" + ) + + await handle.signal(MaxBatchWorkflow.close) + + +@pytest.mark.asyncio +async def test_replay_safety(client: Client) -> None: + """Workflow stream broker survives workflow replay (max_cached_workflows=0).""" + async with new_worker( + client, + InterleavedWorkflow, + activities=[publish_items], + max_cached_workflows=0, + ) as worker: + handle = await client.start_workflow( + InterleavedWorkflow.run, + 5, + id=f"workflow-stream-replay-{uuid.uuid4()}", + task_queue=worker.task_queue, + ) + # 1 (started) + 5 (activity) + 1 (done) = 7 + items = await collect_items(client, handle, None, 0, 7) + # Full ordered sequence — endpoint-only checks would miss mid-stream + # replay corruption (reordering, duplication, dropped items). + assert [i.data for i in items] == [ + b"started", + b"item-0", + b"item-1", + b"item-2", + b"item-3", + b"item-4", + b"done", + ] + assert [i.offset for i in items] == list(range(7)) + await handle.signal(InterleavedWorkflow.close) + + +@pytest.mark.asyncio +async def test_flush_retry_preserves_items_after_failures( + client: Client, +) -> None: + """After flush failures, a subsequent successful flush delivers all items + in publish order, exactly once. + + Exercises the retry code path behaviorally: simulated delivery failures + must not drop items, must not duplicate them on retry, and must not + reorder items published during the failed state. + """ + async with new_worker(client, BasicWorkflowStreamWorkflow) as worker: + handle = await client.start_workflow( + BasicWorkflowStreamWorkflow.run, + id=f"workflow-stream-flush-retry-{uuid.uuid4()}", + task_queue=worker.task_queue, + ) + + stream = WorkflowStreamClient(handle) + real_signal = handle.signal + fail_remaining = 2 + + async def maybe_failing_signal(*args: Any, **kwargs: Any) -> Any: + nonlocal fail_remaining + if fail_remaining > 0: + fail_remaining -= 1 + raise RuntimeError("simulated delivery failure") + return await real_signal(*args, **kwargs) + + with patch.object(handle, "signal", side_effect=maybe_failing_signal): + stream.topic("events", type=bytes).publish(b"item-0") + stream.topic("events", type=bytes).publish(b"item-1") + with pytest.raises(RuntimeError): + await stream._flush() + + # Publish more during the failed state — must not overtake the + # pending retry on eventual delivery. + stream.topic("events", type=bytes).publish(b"item-2") + with pytest.raises(RuntimeError): + await stream._flush() + + # Third flush succeeds, delivering the pending retry batch. + await stream._flush() + # Fourth flush delivers the buffered "item-2". + await stream._flush() + + items = await collect_items(client, handle, None, 0, 3) + assert [i.data for i in items] == [b"item-0", b"item-1", b"item-2"] + + await handle.signal(BasicWorkflowStreamWorkflow.close) + + +@pytest.mark.asyncio +async def test_flush_raises_after_max_retry_duration(client: Client) -> None: + """When max_retry_duration is exceeded, flush raises TimeoutError and the + client can resume publishing without losing subsequent items.""" + async with new_worker(client, BasicWorkflowStreamWorkflow) as worker: + handle = await client.start_workflow( + BasicWorkflowStreamWorkflow.run, + id=f"workflow-stream-retry-expiry-{uuid.uuid4()}", + task_queue=worker.task_queue, + ) + + # Inject a controllable clock into the client module. The client's + # retry check compares `time.monotonic() - _pending_since` against + # `max_retry_duration`, so advancing the clock between flushes makes + # the timeout fire deterministically regardless of wall-clock speed + # or clock resolution. + stream = WorkflowStreamClient( + handle, max_retry_duration=timedelta(milliseconds=100) + ) + real_signal = handle.signal + fail_signals = True + + async def maybe_failing_signal(*args: Any, **kwargs: Any) -> Any: + if fail_signals: + raise RuntimeError("simulated failure") + return await real_signal(*args, **kwargs) + + clock = [0.0] + with ( + patch( + "temporalio.contrib.workflow_streams._client.time.monotonic", + side_effect=lambda: clock[0], + ), + patch.object(handle, "signal", side_effect=maybe_failing_signal), + ): + stream.topic("events", type=bytes).publish(b"lost") + + # First flush fails and enters the pending-retry state. + with pytest.raises(RuntimeError): + await stream._flush() + + # Advance the clock well past max_retry_duration. + clock[0] = 10.0 + + # Next flush raises TimeoutError — the pending batch is abandoned. + with pytest.raises(TimeoutError, match="max_retry_duration"): + await stream._flush() + + # Stop failing signals; subsequent publishes must succeed. + fail_signals = False + stream.topic("events", type=bytes).publish(b"kept") + await stream._flush() + + items = await collect_items(client, handle, None, 0, 1) + assert len(items) == 1 + assert items[0].data == b"kept" + + await handle.signal(BasicWorkflowStreamWorkflow.close) + + +@pytest.mark.asyncio +async def test_dedup_rejects_duplicate_signal(client: Client) -> None: + """Workflow deduplicates signals with the same publisher_id + sequence.""" + async with new_worker( + client, + BasicWorkflowStreamWorkflow, + ) as worker: + handle = await client.start_workflow( + BasicWorkflowStreamWorkflow.run, + id=f"workflow-stream-dedup-{uuid.uuid4()}", + task_queue=worker.task_queue, + ) + + # Send a batch with publisher_id and sequence + await handle.signal( + "__temporal_workflow_stream_publish", + PublishInput( + items=[PublishEntry(topic="events", data=_wire_bytes(b"item-0"))], + publisher_id="test-pub", + sequence=1, + ), + ) + + # Send the same sequence again — should be deduped + await handle.signal( + "__temporal_workflow_stream_publish", + PublishInput( + items=[PublishEntry(topic="events", data=_wire_bytes(b"duplicate"))], + publisher_id="test-pub", + sequence=1, + ), + ) + + # Send a new sequence — should go through + await handle.signal( + "__temporal_workflow_stream_publish", + PublishInput( + items=[PublishEntry(topic="events", data=_wire_bytes(b"item-1"))], + publisher_id="test-pub", + sequence=2, + ), + ) + + # Should have 2 items, not 3 (collect_items' update call acts as barrier) + items = await collect_items(client, handle, None, 0, 2) + assert len(items) == 2 + assert items[0].data == b"item-0" + assert items[1].data == b"item-1" + + # Verify offset is 2 (not 3) + stream_client = WorkflowStreamClient(handle) + offset = await stream_client.get_offset() + assert offset == 2 + + await handle.signal(BasicWorkflowStreamWorkflow.close) + + +@pytest.mark.asyncio +async def test_double_init_raises(client: Client) -> None: + """Instantiating WorkflowStream twice from @workflow.init raises RuntimeError. + + The first WorkflowStream() registers the __temporal_workflow_stream_publish signal handler; the + second call detects the existing handler and raises rather than + silently overwriting it. + """ + async with new_worker(client, DoubleInitWorkflow) as worker: + handle = await client.start_workflow( + DoubleInitWorkflow.run, + id=f"workflow-stream-double-init-{uuid.uuid4()}", + task_queue=worker.task_queue, + ) + err = await handle.query(DoubleInitWorkflow.get_double_init_error) + assert err is not None + assert "already registered" in err + await handle.signal(DoubleInitWorkflow.close) + + +@pytest.mark.asyncio +async def test_workflow_stream_outside_init_raises(client: Client) -> None: + """Constructing WorkflowStream outside @workflow.init raises RuntimeError. + + The workflow calls WorkflowStream() from @workflow.run; the caller-frame + guard must reject the call because the caller's function name is + ``run``, not ``__init__``. + """ + async with new_worker(client, LateWorkflowStreamWorkflow) as worker: + result = await client.execute_workflow( + LateWorkflowStreamWorkflow.run, + id=f"workflow-stream-late-init-{uuid.uuid4()}", + task_queue=worker.task_queue, + ) + assert "must be constructed directly from the workflow's" in result + assert "'run'" in result + + +@pytest.mark.asyncio +async def test_truncate_stream(client: Client) -> None: + """WorkflowStream.truncate discards prefix and adjusts base_offset.""" + async with new_worker( + client, + TruncateWorkflow, + ) as worker: + handle = await client.start_workflow( + TruncateWorkflow.run, + 5, + id=f"workflow-stream-truncate-{uuid.uuid4()}", + task_queue=worker.task_queue, + ) + + # Verify all 5 items + items = await collect_items(client, handle, None, 0, 5) + assert len(items) == 5 + + # Truncate up to offset 3 (discard items 0, 1, 2). The update + # returns after the handler completes. + await handle.execute_update("truncate", 3) + + # Offset should still be 5 (truncation moves base_offset, not tail) + stream_client = WorkflowStreamClient(handle) + offset = await stream_client.get_offset() + assert offset == 5 + + # Reading from offset 3 should work (items 3, 4) + items_after = await collect_items(client, handle, None, 3, 2) + assert len(items_after) == 2 + assert items_after[0].data == b"item-3" + assert items_after[1].data == b"item-4" + + await handle.signal("close") + + +@pytest.mark.asyncio +async def test_ttl_pruning_in_get_stream_state(client: Client) -> None: + """WorkflowStream.get_state prunes publishers whose last-seen time exceeds the + TTL while retaining newer publishers. The log itself is unaffected. + + Uses a wall-clock gap between publishes so that workflow.time() + advances between the two publishers' tasks. workflow.time() can't be + cleanly injected from outside, so a short real sleep is the mechanism. + """ + async with new_worker( + client, + TTLTestWorkflow, + ) as worker: + handle = await client.start_workflow( + TTLTestWorkflow.run, + id=f"workflow-stream-ttl-{uuid.uuid4()}", + task_queue=worker.task_queue, + ) + + # pub-old arrives first. + await handle.signal( + "__temporal_workflow_stream_publish", + PublishInput( + items=[PublishEntry(topic="events", data=_wire_bytes(b"old"))], + publisher_id="pub-old", + sequence=1, + ), + ) + + # Sanity: pub-old is recorded (generous TTL retains it). + state_before = await handle.query(TTLTestWorkflow.get_state_with_ttl, 9999.0) + assert "pub-old" in state_before.publishers + + # Let workflow.time() advance by real wall-clock time. Use a + # generous gap (1.0s) relative to the TTL (0.5s) so the test + # tolerates CI scheduling delays — pub-old must be >=0.5s past, + # pub-new must be <0.5s past, at the moment of the query. + await asyncio.sleep(1.0) + + # pub-new arrives after the gap. + await handle.signal( + "__temporal_workflow_stream_publish", + PublishInput( + items=[PublishEntry(topic="events", data=_wire_bytes(b"new"))], + publisher_id="pub-new", + sequence=1, + ), + ) + + # TTL=0.5s prunes pub-old (~1.0s old) but keeps pub-new (~0s). + state = await handle.query(TTLTestWorkflow.get_state_with_ttl, 0.5) + assert "pub-old" not in state.publishers + assert "pub-new" in state.publishers + # Log contents are not touched by publisher pruning. + assert len(state.log) == 2 + + await handle.signal("close") + + +# --------------------------------------------------------------------------- +# Truncate and TTL test workflows +# --------------------------------------------------------------------------- + + +@workflow.defn +class TruncateWorkflow: + """Test scaffolding that exposes WorkflowStream.truncate via a user-authored + update. + + The contrib module does not define a built-in external truncate API — + truncation is a workflow-internal decision (typically driven by + consumer progress or a retention policy). Workflows that want external + control wire up their own signal or update. We use an update here so + callers get explicit completion (signals are fire-and-forget). + + The ``truncate`` update is ``async`` and opens with + ``await asyncio.sleep(0)`` — the documented recipe from the + contrib/stream README for sync-shaped handlers that read ``WorkflowStream`` + state. The yield lets any buffered ``__temporal_workflow_stream_publish`` signal in + the same activation apply before the handler inspects ``self._log``. + This keeps the test workflow aligned with the pattern users are + directed to follow. + + ``prepub_count`` seeds the log with N byte-payload items during + ``@workflow.init`` as test convenience, so the error-path tests + have deterministic log content without an extra round trip to + publish from the client. + """ + + @workflow.init + def __init__(self, prepub_count: int = 0) -> None: + self.stream = WorkflowStream() + self._closed = False + for i in range(prepub_count): + self.stream.topic("events", type=bytes).publish(f"item-{i}".encode()) + + @workflow.signal + def close(self) -> None: + self._closed = True + + @workflow.update + async def truncate(self, up_to_offset: int) -> None: + # Recipe from README.md "Gotcha" section: yield once so any + # buffered __temporal_workflow_stream_publish in the same activation applies + # before we read self._log. asyncio.sleep(0) is a pure asyncio + # yield — no Temporal timer, no history event. + await asyncio.sleep(0) + self.stream.truncate(up_to_offset) + + @workflow.run + async def run(self, _prepub_count: int = 0) -> None: + # _prepub_count is consumed in @workflow.init above. @workflow.run + # must accept the same positional args, but the names are free + # to differ. + del _prepub_count + await workflow.wait_condition(lambda: self._closed) + + +@workflow.defn +class TruncateRaceWorkflow: + """Workflow that exposes ``publish`` and ``publish_then_truncate`` + updates so a test can deterministically interleave a waiting + ``__temporal_workflow_stream_poll`` update against a truncate that + advances ``base_offset`` past the poll's ``from_offset``. + + The ``publish_then_truncate`` handler runs publish loop and truncate + in a single workflow activation (no awaits between them), so a poll + parked at ``wait_condition`` sees the post-truncate state on its + next predicate evaluation rather than firing on an intermediate + publish. + """ + + @workflow.init + def __init__(self) -> None: + self.stream = WorkflowStream() + self._closed = False + + @workflow.signal + def close(self) -> None: + self._closed = True + + @workflow.update + async def publish(self, count: int) -> None: + await asyncio.sleep(0) + topic = self.stream.topic("events", type=bytes) + for i in range(count): + topic.publish(f"item-{i}".encode()) + + @workflow.update + async def publish_then_truncate(self, args: tuple[int, int]) -> None: + await asyncio.sleep(0) + publish_count, truncate_to = args + topic = self.stream.topic("events", type=bytes) + for i in range(publish_count): + topic.publish(f"prepub-{i}".encode()) + self.stream.truncate(truncate_to) + + @workflow.run + async def run(self) -> None: + await workflow.wait_condition(lambda: self._closed) + + +@workflow.defn +class TTLTestWorkflow: + """Workflow that exposes WorkflowStream.get_state via query for TTL testing.""" + + @workflow.init + def __init__(self) -> None: + self.stream = WorkflowStream() + self._closed = False + + @workflow.signal + def close(self) -> None: + self._closed = True + + @workflow.query + def get_state_with_ttl(self, ttl_seconds: float) -> WorkflowStreamState: + # Query arg is passed as float because the default JSON payload + # converter does not serialize ``timedelta``; convert here. + return self.stream.get_state(publisher_ttl=timedelta(seconds=ttl_seconds)) + + @workflow.run + async def run(self) -> None: + await workflow.wait_condition(lambda: self._closed) + + +# --------------------------------------------------------------------------- +# Continue-as-new workflow and test +# --------------------------------------------------------------------------- + + +@dataclass +class CANWorkflowInputTyped: + """Uses proper typing.""" + + stream_state: WorkflowStreamState | None = None + + +@workflow.defn +class ContinueAsNewTypedWorkflow: + """CAN workflow using properly-typed stream_state.""" + + @workflow.init + def __init__(self, input: CANWorkflowInputTyped) -> None: + self.stream = WorkflowStream(prior_state=input.stream_state) + self._should_continue = False + self._closed = False + + @workflow.signal + def close(self) -> None: + self._closed = True + + @workflow.signal + def trigger_continue(self) -> None: + self._should_continue = True + + @workflow.query + def publisher_sequences(self) -> dict[str, int]: + return {pid: ps.sequence for pid, ps in self.stream._publishers.items()} + + @workflow.run + async def run(self, _input: CANWorkflowInputTyped) -> None: + # _input is consumed in @workflow.init above. @workflow.run must + # accept the same positional args, but the names are free to differ. + del _input + while True: + await workflow.wait_condition(lambda: self._should_continue or self._closed) + if self._closed: + return + if self._should_continue: + self._should_continue = False + self.stream.detach_pollers() + await workflow.wait_condition(workflow.all_handlers_finished) + workflow.continue_as_new( + args=[ + CANWorkflowInputTyped( + stream_state=self.stream.get_state(), + ) + ] + ) + + +@pytest.mark.asyncio +async def test_continue_as_new_properly_typed(client: Client) -> None: + """CAN preserves the log, global offsets, AND publisher dedup state + when stream_state is properly typed as ``WorkflowStreamState | None``.""" + async with new_worker( + client, + ContinueAsNewTypedWorkflow, + ) as worker: + handle = await client.start_workflow( + ContinueAsNewTypedWorkflow.run, + CANWorkflowInputTyped(), + id=f"workflow-stream-can-{uuid.uuid4()}", + task_queue=worker.task_queue, + ) + + # Publish 3 items with an explicit publisher_id/sequence so dedup + # state is seeded and we can verify it survives CAN. + await handle.signal( + "__temporal_workflow_stream_publish", + PublishInput( + items=[ + PublishEntry(topic="events", data=_wire_bytes(b"item-0")), + PublishEntry(topic="events", data=_wire_bytes(b"item-1")), + PublishEntry(topic="events", data=_wire_bytes(b"item-2")), + ], + publisher_id="pub", + sequence=1, + ), + ) + + items_before = await collect_items(client, handle, None, 0, 3) + assert len(items_before) == 3 + + await handle.signal(ContinueAsNewTypedWorkflow.trigger_continue) + + new_handle = client.get_workflow_handle(handle.id) + await assert_eq_eventually( + True, + lambda: _is_different_run(handle, new_handle), + ) + + # Log contents and offsets preserved across CAN. + items_after = await collect_items(client, new_handle, None, 0, 3) + assert [i.data for i in items_after] == [b"item-0", b"item-1", b"item-2"] + assert [i.offset for i in items_after] == [0, 1, 2] + + # Dedup state preserved: the carried publisher_sequences dict has + # pub -> 1 after CAN. + seqs_after_can = await new_handle.query( + ContinueAsNewTypedWorkflow.publisher_sequences + ) + assert seqs_after_can == {"pub": 1} + + # Re-sending publisher_id="pub", sequence=1 must be rejected by + # dedup — both the log and the publisher_sequences entry stay put. + await new_handle.signal( + "__temporal_workflow_stream_publish", + PublishInput( + items=[ + PublishEntry(topic="events", data=_wire_bytes(b"dup")), + ], + publisher_id="pub", + sequence=1, + ), + ) + seqs_after_dup = await new_handle.query( + ContinueAsNewTypedWorkflow.publisher_sequences + ) + assert seqs_after_dup == {"pub": 1} + + # A fresh sequence from the same publisher is accepted, advances + # publisher_sequences to 2, and the new item gets offset 3. + await new_handle.signal( + "__temporal_workflow_stream_publish", + PublishInput( + items=[ + PublishEntry(topic="events", data=_wire_bytes(b"item-3")), + ], + publisher_id="pub", + sequence=2, + ), + ) + seqs_after_accept = await new_handle.query( + ContinueAsNewTypedWorkflow.publisher_sequences + ) + assert seqs_after_accept == {"pub": 2} + items_all = await collect_items(client, new_handle, None, 0, 4) + assert [i.data for i in items_all] == [ + b"item-0", + b"item-1", + b"item-2", + b"item-3", + ] + assert items_all[3].offset == 3 + + await new_handle.signal(ContinueAsNewTypedWorkflow.close) + + +@workflow.defn +class ContinueAsNewHelperWorkflow: + """CAN workflow that uses the packaged ``WorkflowStream.continue_as_new`` helper.""" + + @workflow.init + def __init__(self, input: CANWorkflowInputTyped) -> None: + self.stream = WorkflowStream(prior_state=input.stream_state) + self._should_continue = False + self._closed = False + + @workflow.signal + def close(self) -> None: + self._closed = True + + @workflow.signal + def trigger_continue(self) -> None: + self._should_continue = True + + @workflow.run + async def run(self, _input: CANWorkflowInputTyped) -> None: + del _input + while True: + await workflow.wait_condition(lambda: self._should_continue or self._closed) + if self._closed: + return + if self._should_continue: + self._should_continue = False + await self.stream.continue_as_new( + lambda state: [CANWorkflowInputTyped(stream_state=state)], + ) + + +@pytest.mark.asyncio +async def test_continue_as_new_helper(client: Client) -> None: + """The ``WorkflowStream.continue_as_new`` helper preserves log and dedup state + just like the explicit detach_pollers/wait/CAN recipe.""" + async with new_worker( + client, + ContinueAsNewHelperWorkflow, + ) as worker: + handle = await client.start_workflow( + ContinueAsNewHelperWorkflow.run, + CANWorkflowInputTyped(), + id=f"workflow-stream-can-helper-{uuid.uuid4()}", + task_queue=worker.task_queue, + ) + + await handle.signal( + "__temporal_workflow_stream_publish", + PublishInput( + items=[ + PublishEntry(topic="events", data=_wire_bytes(b"item-0")), + PublishEntry(topic="events", data=_wire_bytes(b"item-1")), + ], + publisher_id="pub", + sequence=1, + ), + ) + + items_before = await collect_items(client, handle, None, 0, 2) + assert [i.data for i in items_before] == [b"item-0", b"item-1"] + + await handle.signal(ContinueAsNewHelperWorkflow.trigger_continue) + + new_handle = client.get_workflow_handle(handle.id) + await assert_eq_eventually( + True, + lambda: _is_different_run(handle, new_handle), + ) + + items_after = await collect_items(client, new_handle, None, 0, 2) + assert [i.data for i in items_after] == [b"item-0", b"item-1"] + assert [i.offset for i in items_after] == [0, 1] + + await new_handle.signal(ContinueAsNewHelperWorkflow.close) + + +# --------------------------------------------------------------------------- +# Cross-workflow workflow stream (Scenario 1) +# --------------------------------------------------------------------------- + + +@dataclass +class CrossWorkflowInput: + broker_workflow_id: str + expected_count: int + + +@workflow.defn +class BrokerWorkflow: + @workflow.init + def __init__(self, count: int) -> None: + self.stream = WorkflowStream() + self._closed = False + + @workflow.signal + def close(self) -> None: + self._closed = True + + @workflow.run + async def run(self, count: int) -> None: + for i in range(count): + self.stream.topic("events", type=bytes).publish(f"broker-{i}".encode()) + await workflow.wait_condition(lambda: self._closed) + + +@workflow.defn +class SubscriberWorkflow: + @workflow.run + async def run(self, input: CrossWorkflowInput) -> list[str]: + return await workflow.execute_activity( + "subscribe_to_broker", + input, + start_to_close_timeout=timedelta(seconds=30), + heartbeat_timeout=timedelta(seconds=10), + ) + + +@activity.defn(name="subscribe_to_broker") +async def subscribe_to_broker(input: CrossWorkflowInput) -> list[str]: + client = WorkflowStreamClient.create( + client=activity.client(), + workflow_id=input.broker_workflow_id, + ) + items: list[str] = [] + async with _async_timeout(15.0): + async for item in client.subscribe( + topics=["events"], + from_offset=0, + poll_cooldown=timedelta(0), + result_type=bytes, + ): + items.append(item.data.decode()) + activity.heartbeat() + if len(items) >= input.expected_count: + break + return items + + +@pytest.mark.asyncio +async def test_cross_workflow_stream(client: Client) -> None: + """Workflow B's activity subscribes to events published by Workflow A.""" + count = 5 + task_queue = str(uuid.uuid4()) + + async with new_worker( + client, + BrokerWorkflow, + SubscriberWorkflow, + activities=[subscribe_to_broker], + task_queue=task_queue, + ): + broker_id = f"workflow-stream-broker-{uuid.uuid4()}" + broker_handle = await client.start_workflow( + BrokerWorkflow.run, + count, + id=broker_id, + task_queue=task_queue, + ) + + sub_handle = await client.start_workflow( + SubscriberWorkflow.run, + CrossWorkflowInput( + broker_workflow_id=broker_id, + expected_count=count, + ), + id=f"workflow-stream-subscriber-{uuid.uuid4()}", + task_queue=task_queue, + ) + + result = await sub_handle.result() + assert result == [f"broker-{i}" for i in range(count)] + + # Also verify external subscription still works + external_items = await collect_items( + client, broker_handle, ["events"], 0, count + ) + assert len(external_items) == count + + await broker_handle.signal(BrokerWorkflow.close) + + +# --------------------------------------------------------------------------- +# Standalone activity (started directly via Client, no parent workflow) +# --------------------------------------------------------------------------- + + +@dataclass +class StandalonePublishInput: + broker_workflow_id: str + count: int + + +@activity.defn(name="standalone_publish_to_broker") +async def standalone_publish_to_broker(input: StandalonePublishInput) -> None: + """Publish to a broker workflow from a standalone activity. + + Same usage as in any external program: build a Client (here taken + via ``activity.client()``), pass an explicit workflow id to + ``WorkflowStreamClient.create``. ``from_within_activity`` is not usable + here because the activity has no parent workflow. + """ + assert ( + activity.info().workflow_id is None + ), "test bug: this activity should be standalone" + client = WorkflowStreamClient.create( + client=activity.client(), + workflow_id=input.broker_workflow_id, + batch_interval=timedelta(milliseconds=500), + ) + async with client: + for i in range(input.count): + activity.heartbeat() + client.topic("events", type=bytes).publish(f"standalone-{i}".encode()) + + +@activity.defn(name="standalone_subscribe_to_broker") +async def standalone_subscribe_to_broker(input: CrossWorkflowInput) -> list[str]: + assert ( + activity.info().workflow_id is None + ), "test bug: this activity should be standalone" + client = WorkflowStreamClient.create( + client=activity.client(), + workflow_id=input.broker_workflow_id, + ) + items: list[str] = [] + async with _async_timeout(15.0): + async for item in client.subscribe( + topics=["events"], + from_offset=0, + poll_cooldown=timedelta(0), + result_type=bytes, + ): + items.append(item.data.decode()) + activity.heartbeat() + if len(items) >= input.expected_count: + break + return items + + +@activity.defn(name="standalone_from_within_activity_misuse") +async def standalone_from_within_activity_misuse() -> str: + """Calling from_within_activity in a standalone activity must raise a clear error.""" + try: + WorkflowStreamClient.from_within_activity() + except RuntimeError as e: + return str(e) + return "" + + +@pytest.mark.asyncio +async def test_standalone_activity_publish( + client: Client, env: WorkflowEnvironment +) -> None: + """Activity started directly via Client.start_activity publishes via create().""" + if env.supports_time_skipping: + pytest.skip( + "Java test server does not support Client.start_activity: " + "https://github.com/temporalio/sdk-java/issues/2741" + ) + count = 5 + task_queue = str(uuid.uuid4()) + + async with new_worker( + client, + BasicWorkflowStreamWorkflow, + activities=[standalone_publish_to_broker], + task_queue=task_queue, + ): + broker_id = f"workflow-stream-standalone-broker-{uuid.uuid4()}" + broker_handle = await client.start_workflow( + BasicWorkflowStreamWorkflow.run, + id=broker_id, + task_queue=task_queue, + ) + + activity_handle = await client.start_activity( + standalone_publish_to_broker, + StandalonePublishInput(broker_workflow_id=broker_id, count=count), + id=f"standalone-publish-{uuid.uuid4()}", + task_queue=task_queue, + start_to_close_timeout=timedelta(seconds=30), + heartbeat_timeout=timedelta(seconds=10), + ) + await activity_handle.result() + + items = await collect_items(client, broker_handle, ["events"], 0, count) + assert [i.data for i in items] == [ + f"standalone-{i}".encode() for i in range(count) + ] + + await broker_handle.signal(BasicWorkflowStreamWorkflow.close) + + +@pytest.mark.asyncio +async def test_standalone_activity_subscribe( + client: Client, env: WorkflowEnvironment +) -> None: + """Standalone activity subscribes to a broker workflow via create().""" + if env.supports_time_skipping: + pytest.skip( + "Java test server does not support Client.start_activity: " + "https://github.com/temporalio/sdk-java/issues/2741" + ) + count = 5 + task_queue = str(uuid.uuid4()) + + async with new_worker( + client, + BrokerWorkflow, + activities=[standalone_subscribe_to_broker], + task_queue=task_queue, + ): + broker_id = f"workflow-stream-standalone-sub-broker-{uuid.uuid4()}" + broker_handle = await client.start_workflow( + BrokerWorkflow.run, + count, + id=broker_id, + task_queue=task_queue, + ) + + activity_handle = await client.start_activity( + standalone_subscribe_to_broker, + CrossWorkflowInput( + broker_workflow_id=broker_id, + expected_count=count, + ), + id=f"standalone-subscribe-{uuid.uuid4()}", + task_queue=task_queue, + start_to_close_timeout=timedelta(seconds=30), + heartbeat_timeout=timedelta(seconds=10), + ) + result = await activity_handle.result() + assert result == [f"broker-{i}" for i in range(count)] + + await broker_handle.signal(BrokerWorkflow.close) + + +@pytest.mark.asyncio +async def test_from_within_activity_in_standalone_activity_raises( + client: Client, env: WorkflowEnvironment +) -> None: + """from_within_activity() raises a clear error pointing at create() when used in a + standalone activity (one without a parent workflow).""" + if env.supports_time_skipping: + pytest.skip( + "Java test server does not support Client.start_activity: " + "https://github.com/temporalio/sdk-java/issues/2741" + ) + task_queue = str(uuid.uuid4()) + + async with new_worker( + client, + activities=[standalone_from_within_activity_misuse], + task_queue=task_queue, + ): + activity_handle = await client.start_activity( + standalone_from_within_activity_misuse, + id=f"standalone-misuse-{uuid.uuid4()}", + task_queue=task_queue, + start_to_close_timeout=timedelta(seconds=10), + ) + msg = await activity_handle.result() + assert "no parent workflow" in msg + assert "WorkflowStreamClient.create" in msg + + +# --------------------------------------------------------------------------- +# Cross-namespace workflow stream via Nexus (Scenario 2) +# --------------------------------------------------------------------------- + + +@dataclass +class StartBrokerInput: + count: int + broker_id: str + + +@dataclass +class NexusCallerInput: + count: int + broker_id: str + endpoint: str + + +@workflow.defn +class NexusBrokerWorkflow: + @workflow.init + def __init__(self, count: int) -> None: + self.stream = WorkflowStream() + self._closed = False + + @workflow.signal + def close(self) -> None: + self._closed = True + + @workflow.run + async def run(self, count: int) -> str: + for i in range(count): + self.stream.topic("events", type=bytes).publish(f"nexus-{i}".encode()) + await workflow.wait_condition(lambda: self._closed) + return "done" + + +@nexusrpc.service +class WorkflowStreamNexusService: + start_broker: nexusrpc.Operation[StartBrokerInput, str] + + +@nexusrpc.handler.service_handler(service=WorkflowStreamNexusService) +class WorkflowStreamNexusHandler: + @workflow_run_operation + async def start_broker( + self, ctx: WorkflowRunOperationContext, input: StartBrokerInput + ) -> nexus.WorkflowHandle[str]: + return await ctx.start_workflow( + NexusBrokerWorkflow.run, + input.count, + id=input.broker_id, + ) + + +@workflow.defn +class NexusCallerWorkflow: + @workflow.run + async def run(self, input: NexusCallerInput) -> str: + nc = workflow.create_nexus_client( + service=WorkflowStreamNexusService, + endpoint=input.endpoint, + ) + return await nc.execute_operation( + WorkflowStreamNexusService.start_broker, + StartBrokerInput(count=input.count, broker_id=input.broker_id), + ) + + +async def create_cross_namespace_endpoint( + client: Client, + endpoint_name: str, + target_namespace: str, + task_queue: str, +) -> None: + await client.operator_service.create_nexus_endpoint( + temporalio.api.operatorservice.v1.CreateNexusEndpointRequest( + spec=temporalio.api.nexus.v1.EndpointSpec( + name=endpoint_name, + target=temporalio.api.nexus.v1.EndpointTarget( + worker=temporalio.api.nexus.v1.EndpointTarget.Worker( + namespace=target_namespace, + task_queue=task_queue, + ) + ), + ) + ) + ) + + +@pytest.mark.asyncio +async def test_poll_more_ready_when_response_exceeds_size_limit( + client: Client, +) -> None: + """Poll response sets more_ready=True when items exceed ~1MB wire size.""" + async with new_worker( + client, + BasicWorkflowStreamWorkflow, + ) as worker: + handle = await client.start_workflow( + BasicWorkflowStreamWorkflow.run, + id=f"workflow-stream-more-ready-{uuid.uuid4()}", + task_queue=worker.task_queue, + ) + + # Publish items that total well over 1MB in the poll response. + # Send in separate signals to stay under the RPC size limit. + # Each item is ~200KB; 8 items = ~1.6MB wire (base64 inflates ~33%). + chunk = b"x" * 200_000 + for _ in range(8): + await handle.signal( + "__temporal_workflow_stream_publish", + PublishInput( + items=[PublishEntry(topic="big", data=_wire_bytes(chunk))] + ), + ) + + # First poll from offset 0 — should get some items but not all. + # (The update acts as a barrier for all prior publish signals.) + result1: PollResult = await handle.execute_update( + "__temporal_workflow_stream_poll", + PollInput(topics=[], from_offset=0), + result_type=PollResult, + ) + assert result1.more_ready is True + assert len(result1.items) < 8 + assert result1.next_offset < 8 + + # Continue polling until we have all items + all_items = list(result1.items) + offset = result1.next_offset + last_result: PollResult = result1 + while len(all_items) < 8: + last_result = await handle.execute_update( + "__temporal_workflow_stream_poll", + PollInput(topics=[], from_offset=offset), + result_type=PollResult, + ) + all_items.extend(last_result.items) + offset = last_result.next_offset + assert len(all_items) == 8 + # The final poll that drained the log should set more_ready=False + assert last_result.more_ready is False + + await handle.signal(BasicWorkflowStreamWorkflow.close) + + +@pytest.mark.asyncio +async def test_subscribe_iterates_through_more_ready(client: Client) -> None: + """Subscriber correctly yields all items when polls are size-truncated.""" + async with new_worker( + client, + BasicWorkflowStreamWorkflow, + ) as worker: + handle = await client.start_workflow( + BasicWorkflowStreamWorkflow.run, + id=f"workflow-stream-more-ready-iter-{uuid.uuid4()}", + task_queue=worker.task_queue, + ) + + # Publish 8 x 200KB items (~2MB+ wire, exceeds 1MB cap) + chunk = b"x" * 200_000 + for _ in range(8): + await handle.signal( + "__temporal_workflow_stream_publish", + PublishInput( + items=[PublishEntry(topic="big", data=_wire_bytes(chunk))] + ), + ) + + # subscribe() should seamlessly iterate through all 8 items + items = await collect_items(client, handle, None, 0, 8, timeout=10.0) + assert len(items) == 8 + for item in items: + assert item.data == chunk + + await handle.signal(BasicWorkflowStreamWorkflow.close) + + +@pytest.mark.asyncio +async def test_cross_namespace_nexus_stream( + client: Client, env: WorkflowEnvironment +) -> None: + """Nexus operation starts a workflow stream broker in another namespace; test subscribes.""" + if env.supports_time_skipping: + pytest.skip("Nexus not supported with time-skipping server") + + count = 5 + handler_ns = f"handler-ns-{uuid.uuid4().hex[:8]}" + task_queue = str(uuid.uuid4()) + endpoint_name = make_nexus_endpoint_name(task_queue) + broker_id = f"nexus-broker-{uuid.uuid4()}" + + # Register the handler namespace with the dev server + await client.workflow_service.register_namespace( + temporalio.api.workflowservice.v1.RegisterNamespaceRequest( + namespace=handler_ns, + workflow_execution_retention_period=google.protobuf.duration_pb2.Duration( + seconds=86400, + ), + ) + ) + + handler_client = await Client.connect( + client.service_client.config.target_host, + namespace=handler_ns, + ) + + # Create endpoint targeting the handler namespace + await create_cross_namespace_endpoint( + client, + endpoint_name, + target_namespace=handler_ns, + task_queue=task_queue, + ) + + # Handler worker in handler namespace + async with Worker( + handler_client, + task_queue=task_queue, + workflows=[NexusBrokerWorkflow], + nexus_service_handlers=[WorkflowStreamNexusHandler()], + ): + # Caller worker in default namespace + caller_tq = str(uuid.uuid4()) + async with new_worker( + client, + NexusCallerWorkflow, + task_queue=caller_tq, + ): + # Start caller — invokes Nexus op which starts broker in handler ns + caller_handle = await client.start_workflow( + NexusCallerWorkflow.run, + NexusCallerInput( + count=count, + broker_id=broker_id, + endpoint=endpoint_name, + ), + id=f"nexus-caller-{uuid.uuid4()}", + task_queue=caller_tq, + ) + + # Wait for the broker workflow to be started by the Nexus operation + broker_handle = handler_client.get_workflow_handle(broker_id) + + async def broker_started() -> bool: + try: + await broker_handle.describe() + return True + except Exception: + return False + + await assert_eq_eventually( + True, broker_started, timeout=timedelta(seconds=15) + ) + + # Subscribe to broker events from the handler namespace + items = await collect_items( + handler_client, broker_handle, ["events"], 0, count + ) + assert len(items) == count + for i in range(count): + assert items[i].topic == "events" + assert items[i].data == f"nexus-{i}".encode() + + # Clean up — signal broker to close so caller can complete + await broker_handle.signal("close") + result = await caller_handle.result() + assert result == "done" diff --git a/uv.lock b/uv.lock index ecb7e38f9..eb9dc75a6 100644 --- a/uv.lock +++ b/uv.lock @@ -9,7 +9,7 @@ resolution-markers = [ ] [options] -exclude-newer = "2026-04-23T15:55:57.051193Z" +exclude-newer = "2026-04-23T17:46:27.746666Z" exclude-newer-span = "P1W" [options.exclude-newer-package] @@ -970,7 +970,7 @@ name = "exceptiongroup" version = "1.3.1" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "typing-extensions", marker = "python_full_version < '3.13'" }, + { name = "typing-extensions", marker = "python_full_version < '3.11'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/50/79/66800aadf48771f6b62f7eb014e352e5d06856655206165d775e675a02c9/exceptiongroup-1.3.1.tar.gz", hash = "sha256:8b412432c6055b0b7d14c310000ae93352ed6754f70fa8f7c34141f91c4e3219", size = 30371, upload-time = "2025-11-21T23:01:54.787Z" } wheels = [ @@ -5195,6 +5195,7 @@ pydantic = [ [package.dev-dependencies] dev = [ + { name = "async-timeout", marker = "python_full_version < '3.11'" }, { name = "basedpyright" }, { name = "cibuildwheel" }, { name = "googleapis-common-protos" }, @@ -5259,6 +5260,7 @@ provides-extras = ["grpc", "opentelemetry", "pydantic", "openai-agents", "google [package.metadata.requires-dev] dev = [ + { name = "async-timeout", marker = "python_full_version < '3.11'", specifier = ">=4.0,<6" }, { name = "basedpyright", specifier = "==1.34.0" }, { name = "cibuildwheel", specifier = ">=2.22.0,<3" }, { name = "googleapis-common-protos", specifier = "==1.70.0" }, From 19aa13e0b14bb26b06a10a9706163627a396e3af Mon Sep 17 00:00:00 2001 From: tconley1428 Date: Thu, 30 Apr 2026 15:15:05 -0700 Subject: [PATCH 071/226] Bump version to 1.27.0 (#1496) --- pyproject.toml | 2 +- temporalio/service.py | 2 +- uv.lock | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 61fe159fb..d85badb64 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "temporalio" -version = "1.26.0" +version = "1.27.0" description = "Temporal.io Python SDK" authors = [{ name = "Temporal Technologies Inc", email = "sdk@temporal.io" }] requires-python = ">=3.10" diff --git a/temporalio/service.py b/temporalio/service.py index cbb3dc9be..14b4d1fe5 100644 --- a/temporalio/service.py +++ b/temporalio/service.py @@ -24,7 +24,7 @@ import temporalio.runtime from temporalio.bridge.client import RPCError as BridgeRPCError -__version__ = "1.26.0" +__version__ = "1.27.0" ServiceRequest = TypeVar("ServiceRequest", bound=google.protobuf.message.Message) ServiceResponse = TypeVar("ServiceResponse", bound=google.protobuf.message.Message) diff --git a/uv.lock b/uv.lock index eb9dc75a6..c78ab196c 100644 --- a/uv.lock +++ b/uv.lock @@ -5147,7 +5147,7 @@ wheels = [ [[package]] name = "temporalio" -version = "1.26.0" +version = "1.27.0" source = { virtual = "." } dependencies = [ { name = "nexus-rpc" }, From 85dde16fd9cc3ab1ace4de2ef326d24d10438e4f Mon Sep 17 00:00:00 2001 From: Brian Strauch Date: Thu, 30 Apr 2026 16:39:47 -0700 Subject: [PATCH 072/226] Fix flaky pause_and_assert helper (#1493) --- tests/helpers/__init__.py | 44 ++++++++++++++++++++++++++++------- tests/worker/test_workflow.py | 4 ++++ 2 files changed, 39 insertions(+), 9 deletions(-) diff --git a/tests/helpers/__init__.py b/tests/helpers/__init__.py index d7012213a..f467f8aa3 100644 --- a/tests/helpers/__init__.py +++ b/tests/helpers/__init__.py @@ -3,6 +3,7 @@ import logging.handlers import queue import socket +import threading import time import uuid from collections.abc import Awaitable, Callable, Iterator, Sequence @@ -265,8 +266,28 @@ async def get_pending_activity_info( return None +_wait_for_pause_events: dict[str, threading.Event] = {} + + +def wait_for_pause_event(activity_id: str) -> None: + event = _wait_for_pause_events.get(activity_id) + if event is not None: + event.wait() + + +async def async_wait_for_pause_event(activity_id: str) -> None: + event = _wait_for_pause_events.get(activity_id) + if event is not None: + await asyncio.get_running_loop().run_in_executor(None, event.wait) + + async def pause_and_assert(client: Client, handle: WorkflowHandle, activity_id: str): - """Pause the given activity and assert it becomes paused.""" + """Pause the given activity and assert it becomes paused. + + Registers an event before calling the pause API so cooperating test + activities (those that catch the pause-induced cancel via + wait_for_pause_release) hang until we have observed paused=true. + """ desc = await handle.describe() req = PauseActivityRequest( namespace=client.namespace, @@ -276,14 +297,19 @@ async def pause_and_assert(client: Client, handle: WorkflowHandle, activity_id: ), id=activity_id, ) - await client.workflow_service.pause_activity(req) - # Assert eventually paused - async def check_paused() -> bool: - info = await assert_pending_activity_exists_eventually(handle, activity_id) - return info.paused + _wait_for_pause_events[activity_id] = threading.Event() + try: + await client.workflow_service.pause_activity(req) + + async def check_paused() -> None: + info = await assert_pending_activity_exists_eventually(handle, activity_id) + assert info.paused, f"Activity {activity_id} not yet paused" - await assert_eventually(check_paused) + await assert_eventually(check_paused) + finally: + _wait_for_pause_events[activity_id].set() + del _wait_for_pause_events[activity_id] async def unpause_and_assert(client: Client, handle: WorkflowHandle, activity_id: str): @@ -300,9 +326,9 @@ async def unpause_and_assert(client: Client, handle: WorkflowHandle, activity_id await client.workflow_service.unpause_activity(req) # Assert eventually not paused - async def check_unpaused() -> bool: + async def check_unpaused() -> None: info = await assert_pending_activity_exists_eventually(handle, activity_id) - return not info.paused + assert not info.paused, f"Activity {activity_id} still paused" await assert_eventually(check_unpaused) diff --git a/tests/worker/test_workflow.py b/tests/worker/test_workflow.py index 7b3fd4709..71f48cc63 100644 --- a/tests/worker/test_workflow.py +++ b/tests/worker/test_workflow.py @@ -130,12 +130,14 @@ assert_pending_activity_exists_eventually, assert_task_fail_eventually, assert_workflow_exists_eventually, + async_wait_for_pause_event, ensure_search_attributes_present, find_free_port, get_pending_activity_info, new_worker, pause_and_assert, unpause_and_assert, + wait_for_pause_event, workflow_update_exists, ) from tests.helpers.cache_eviction import ( @@ -7782,6 +7784,7 @@ async def heartbeat_activity( except (CancelledError, asyncio.CancelledError) as err: if not catch_err: raise err + await async_wait_for_pause_event(activity.info().activity_id) return activity.cancellation_details() finally: activity.heartbeat("finally-complete") @@ -7801,6 +7804,7 @@ def sync_heartbeat_activity( except (CancelledError, asyncio.CancelledError) as err: if not catch_err: raise err + wait_for_pause_event(activity.info().activity_id) return activity.cancellation_details() finally: activity.heartbeat("finally-complete") From 257909946a78e56a20565a3f8210c444853ee69d Mon Sep 17 00:00:00 2001 From: David Hyde Date: Fri, 1 May 2026 11:13:27 -0500 Subject: [PATCH 073/226] Fix flaky LangGraph timeout tests (#1495) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Fix flaky LangGraph timeout tests The test activities slept for 1s with a 100ms start_to_close_timeout. Since Temporal does not actively cancel an activity when start_to_close_timeout fires (it just rejects late completions), the server processing the activity completion raced with it processing the timeout, and on slow runners (Windows CI) the completion sometimes won — causing test_timeout to fail with "DID NOT RAISE WorkflowFailureError". Increase the activity sleep to 30s so the timer reliably fires long before the activity could complete naturally. Worker-shutdown cancellation cleans up the still-sleeping activity when the test exits its `async with Worker(...)` block, so runtime is unchanged. Same fix applied to slow_task, used by the otherwise-identical pattern in test_per_task_activity_options_override. * Use Event().wait() instead of a long sleep Replaces the 30s sleep with await asyncio.Event().wait() to make the intent explicit: the activity has no natural exit, so it can only end via the start_to_close_timeout firing or worker-shutdown cancellation. * Drop unhelpful comments * Add brief comment, rename slow_task to waiting_task The function never sleeps anymore — it waits on an Event() that's never set — so "slow" was misleading. waiting_task names what it actually does. * Fix import sort order after rename --- tests/contrib/langgraph/e2e_functional_entrypoints.py | 7 ++++--- tests/contrib/langgraph/test_e2e_functional.py | 6 +++--- tests/contrib/langgraph/test_timeout.py | 5 +++-- 3 files changed, 10 insertions(+), 8 deletions(-) diff --git a/tests/contrib/langgraph/e2e_functional_entrypoints.py b/tests/contrib/langgraph/e2e_functional_entrypoints.py index 7f16abe8d..516fdeb52 100644 --- a/tests/contrib/langgraph/e2e_functional_entrypoints.py +++ b/tests/contrib/langgraph/e2e_functional_entrypoints.py @@ -133,12 +133,13 @@ async def interrupt_entrypoint(value: str) -> dict: @task -async def slow_task(x: int) -> int: - await asyncio.sleep(1) +async def waiting_task(x: int) -> int: + # Wait (forever) until start_to_close_timeout or worker shutdown cancellation + await asyncio.Event().wait() return x @entrypoint() async def slow_entrypoint(value: int) -> dict: - result = await slow_task(value) + result = await waiting_task(value) return {"result": result} diff --git a/tests/contrib/langgraph/test_e2e_functional.py b/tests/contrib/langgraph/test_e2e_functional.py index 649a0b619..7f4ffab88 100644 --- a/tests/contrib/langgraph/test_e2e_functional.py +++ b/tests/contrib/langgraph/test_e2e_functional.py @@ -46,12 +46,12 @@ reset_task_execution_counts, simple_functional_entrypoint, slow_entrypoint, - slow_task, step_1, step_2, step_3, step_4, step_5, + waiting_task, ) from tests.contrib.langgraph.e2e_functional_workflows import ( ContinueAsNewFunctionalWorkflow, @@ -316,10 +316,10 @@ async def test_per_task_activity_options_override(self, client: Client) -> None: plugins=[ LangGraphPlugin( entrypoints={"e2e_slow_functional": slow_entrypoint}, - tasks=[slow_task], + tasks=[waiting_task], default_activity_options=_DEFAULT_ACTIVITY_OPTIONS, activity_options={ - "slow_task": { + "waiting_task": { "execute_in": "activity", "start_to_close_timeout": timedelta(milliseconds=100), "retry_policy": RetryPolicy(maximum_attempts=1), diff --git a/tests/contrib/langgraph/test_timeout.py b/tests/contrib/langgraph/test_timeout.py index 12561c146..7138e3a57 100644 --- a/tests/contrib/langgraph/test_timeout.py +++ b/tests/contrib/langgraph/test_timeout.py @@ -1,4 +1,4 @@ -from asyncio import sleep +import asyncio from datetime import timedelta from typing import Any from uuid import uuid4 @@ -19,7 +19,8 @@ class State(TypedDict): async def node(state: State) -> dict[str, str]: # pyright: ignore[reportUnusedParameter] - await sleep(1) # 1 second + # Wait (forever) until start_to_close_timeout or worker shutdown cancellation + await asyncio.Event().wait() return {"value": "done"} From c4f1371cddb396f3e173e7e2955c91ccb9310b30 Mon Sep 17 00:00:00 2001 From: Christopher Constable Date: Fri, 1 May 2026 12:14:55 -0400 Subject: [PATCH 074/226] feat(otel): remove span creation for saa operations that do not currently propagate tracing headers. (#1492) * feat(otel): remove span creation for saa operations that do not currently propagate tracing headers. * docs(README): add poe format instructions to style section of README. --------- Co-authored-by: tconley1428 --- README.md | 5 ++ .../contrib/opentelemetry/_interceptor.py | 40 ---------------- .../opentelemetry/_otel_interceptor.py | 48 ------------------- .../opentelemetry/test_opentelemetry.py | 40 ++++------------ .../test_opentelemetry_plugin.py | 44 +++++++---------- 5 files changed, 31 insertions(+), 146 deletions(-) diff --git a/README.md b/README.md index 38d643881..019d6f576 100644 --- a/README.md +++ b/README.md @@ -2103,6 +2103,11 @@ tests. ### Style +``` +# runs ruff + cargo fmt +poe format +``` + * Mostly [Google Style Guide](https://google.github.io/styleguide/pyguide.html). Notable exceptions: * We use [ruff](https://docs.astral.sh/ruff/) for formatting, so that takes precedence * In tests and example code, can import individual classes/functions to make it more readable. Can also do this for diff --git a/temporalio/contrib/opentelemetry/_interceptor.py b/temporalio/contrib/opentelemetry/_interceptor.py index 2c6323707..eb22f8be6 100644 --- a/temporalio/contrib/opentelemetry/_interceptor.py +++ b/temporalio/contrib/opentelemetry/_interceptor.py @@ -355,46 +355,6 @@ async def start_activity( ): return await super().start_activity(input) - async def cancel_activity( - self, input: temporalio.client.CancelActivityInput - ) -> None: - with self.root._start_as_current_span( - "CancelActivity", - attributes={"temporalActivityID": input.activity_id}, - kind=opentelemetry.trace.SpanKind.CLIENT, - ): - return await super().cancel_activity(input) - - async def terminate_activity( - self, input: temporalio.client.TerminateActivityInput - ) -> None: - with self.root._start_as_current_span( - "TerminateActivity", - attributes={"temporalActivityID": input.activity_id}, - kind=opentelemetry.trace.SpanKind.CLIENT, - ): - return await super().terminate_activity(input) - - async def describe_activity( - self, input: temporalio.client.DescribeActivityInput - ) -> temporalio.client.ActivityExecutionDescription: - with self.root._start_as_current_span( - "DescribeActivity", - attributes={"temporalActivityID": input.activity_id}, - kind=opentelemetry.trace.SpanKind.CLIENT, - ): - return await super().describe_activity(input) - - async def count_activities( - self, input: temporalio.client.CountActivitiesInput - ) -> temporalio.client.ActivityExecutionCount: - with self.root._start_as_current_span( - "CountActivities", - attributes={}, - kind=opentelemetry.trace.SpanKind.CLIENT, - ): - return await super().count_activities(input) - class _TracingActivityInboundInterceptor(temporalio.worker.ActivityInboundInterceptor): def __init__( diff --git a/temporalio/contrib/opentelemetry/_otel_interceptor.py b/temporalio/contrib/opentelemetry/_otel_interceptor.py index 089e73da7..6062f5022 100644 --- a/temporalio/contrib/opentelemetry/_otel_interceptor.py +++ b/temporalio/contrib/opentelemetry/_otel_interceptor.py @@ -319,54 +319,6 @@ async def start_activity( input.headers = _context_to_headers(input.headers) return await super().start_activity(input) - async def cancel_activity( - self, input: temporalio.client.CancelActivityInput - ) -> None: - with _maybe_span( - get_tracer(__name__), - "CancelActivity", - add_temporal_spans=self._add_temporal_spans, - attributes={"temporalActivityID": input.activity_id}, - kind=opentelemetry.trace.SpanKind.CLIENT, - ): - return await super().cancel_activity(input) - - async def terminate_activity( - self, input: temporalio.client.TerminateActivityInput - ) -> None: - with _maybe_span( - get_tracer(__name__), - "TerminateActivity", - add_temporal_spans=self._add_temporal_spans, - attributes={"temporalActivityID": input.activity_id}, - kind=opentelemetry.trace.SpanKind.CLIENT, - ): - return await super().terminate_activity(input) - - async def describe_activity( - self, input: temporalio.client.DescribeActivityInput - ) -> temporalio.client.ActivityExecutionDescription: - with _maybe_span( - get_tracer(__name__), - "DescribeActivity", - add_temporal_spans=self._add_temporal_spans, - attributes={"temporalActivityID": input.activity_id}, - kind=opentelemetry.trace.SpanKind.CLIENT, - ): - return await super().describe_activity(input) - - async def count_activities( - self, input: temporalio.client.CountActivitiesInput - ) -> temporalio.client.ActivityExecutionCount: - with _maybe_span( - get_tracer(__name__), - "CountActivities", - add_temporal_spans=self._add_temporal_spans, - attributes={}, - kind=opentelemetry.trace.SpanKind.CLIENT, - ): - return await super().count_activities(input) - class _TracingActivityInboundInterceptor(temporalio.worker.ActivityInboundInterceptor): def __init__( diff --git a/tests/contrib/opentelemetry/test_opentelemetry.py b/tests/contrib/opentelemetry/test_opentelemetry.py index 2dd17e303..94bb3fda5 100644 --- a/tests/contrib/opentelemetry/test_opentelemetry.py +++ b/tests/contrib/opentelemetry/test_opentelemetry.py @@ -960,6 +960,7 @@ async def test_opentelemetry_standalone_activity_tracing( client = Client(**client_config) task_queue = f"task_queue_{uuid.uuid4()}" + activity_id = f"activity_{uuid.uuid4()}" async with Worker( client, task_queue=task_queue, @@ -968,44 +969,23 @@ async def test_opentelemetry_standalone_activity_tracing( handle = await client.start_activity( tracing_activity, TracingActivityParam(heartbeat=False), - id=f"activity_{uuid.uuid4()}", + id=activity_id, task_queue=task_queue, schedule_to_close_timeout=timedelta(seconds=10), ) await handle.result() - # Use a queue with no worker so activities stay in SCHEDULED state, - # allowing describe/cancel/terminate to be called without a race. - no_worker_queue = f"task_queue_{uuid.uuid4()}" - - cancel_handle = await client.start_activity( - tracing_activity, - TracingActivityParam(heartbeat=False), - id=f"activity_{uuid.uuid4()}", - task_queue=no_worker_queue, - schedule_to_close_timeout=timedelta(seconds=30), - ) - await cancel_handle.describe() - await cancel_handle.cancel() - - terminate_handle = await client.start_activity( - tracing_activity, - TracingActivityParam(heartbeat=False), - id=f"activity_{uuid.uuid4()}", - task_queue=no_worker_queue, - schedule_to_close_timeout=timedelta(seconds=30), - ) - await terminate_handle.terminate() - - assert dump_spans(exporter.get_finished_spans(), with_attributes=False) == [ + finished_spans = exporter.get_finished_spans() + assert dump_spans(finished_spans, with_attributes=False) == [ "StartActivity:tracing_activity", " RunActivity:tracing_activity", - "StartActivity:tracing_activity", - "DescribeActivity", - "CancelActivity", - "StartActivity:tracing_activity", - "TerminateActivity", ] + start_activity_span = next( + s for s in finished_spans if s.name == "StartActivity:tracing_activity" + ) + assert start_activity_span.attributes is not None + assert start_activity_span.attributes["temporalActivityID"] == activity_id + assert start_activity_span.attributes["temporalActivityType"] == "tracing_activity" def test_opentelemetry_safe_detach(): diff --git a/tests/contrib/opentelemetry/test_opentelemetry_plugin.py b/tests/contrib/opentelemetry/test_opentelemetry_plugin.py index 29acf0b6a..06ad330ed 100644 --- a/tests/contrib/opentelemetry/test_opentelemetry_plugin.py +++ b/tests/contrib/opentelemetry/test_opentelemetry_plugin.py @@ -585,49 +585,37 @@ async def test_otel_standalone_activity_tracing( new_config["plugins"] = [OpenTelemetryPlugin(add_temporal_spans=True)] new_client = Client(**new_config) + activity_id = f"activity_{uuid.uuid4()}" async with new_worker( new_client, activities=[simple_no_context_activity], ) as worker: handle = await new_client.start_activity( simple_no_context_activity, - id=f"activity_{uuid.uuid4()}", + id=activity_id, task_queue=worker.task_queue, schedule_to_close_timeout=timedelta(seconds=10), ) await handle.result() - # Use a queue with no worker so activities stay in SCHEDULED state, - # allowing describe/cancel/terminate to be called without a race. - no_worker_queue = f"task_queue_{uuid.uuid4()}" - - cancel_handle = await new_client.start_activity( - simple_no_context_activity, - id=f"activity_{uuid.uuid4()}", - task_queue=no_worker_queue, - schedule_to_close_timeout=timedelta(seconds=30), - ) - await cancel_handle.describe() - await cancel_handle.cancel() - - terminate_handle = await new_client.start_activity( - simple_no_context_activity, - id=f"activity_{uuid.uuid4()}", - task_queue=no_worker_queue, - schedule_to_close_timeout=timedelta(seconds=30), - ) - await terminate_handle.terminate() - - assert dump_spans(exporter.get_finished_spans(), with_attributes=False) == [ + finished_spans = exporter.get_finished_spans() + assert dump_spans(finished_spans, with_attributes=False) == [ "StartActivity:simple_no_context_activity", " RunActivity:simple_no_context_activity", " Activity", - "StartActivity:simple_no_context_activity", - "DescribeActivity", - "CancelActivity", - "StartActivity:simple_no_context_activity", - "TerminateActivity", ] + start_activity_span = next( + s + for s in finished_spans + if s.name == "StartActivity:simple_no_context_activity" + and s.attributes is not None + and s.attributes.get("temporalActivityID") == activity_id + ) + assert start_activity_span.attributes is not None + assert ( + start_activity_span.attributes["temporalActivityType"] + == "simple_no_context_activity" + ) def test_replay_safe_span_delegates_extra_attributes(): From dbcbcb87e5091ae2f477cc57922e8b7bb06a1eb7 Mon Sep 17 00:00:00 2001 From: Thomas Hardy Date: Fri, 1 May 2026 11:27:22 -0700 Subject: [PATCH 075/226] CaN USE_RAMPING_VERSION versioning behaviour (#1499) --- temporalio/workflow.py | 19 ++++++++ tests/__init__.py | 2 +- tests/worker/test_worker.py | 92 +++++++++++++++++++++++++++++++++++++ 3 files changed, 112 insertions(+), 1 deletion(-) diff --git a/temporalio/workflow.py b/temporalio/workflow.py index 59a353286..40f17302c 100644 --- a/temporalio/workflow.py +++ b/temporalio/workflow.py @@ -5426,6 +5426,25 @@ class ContinueAsNewVersioningBehavior(IntEnum): effective version will be whatever is specified by the Versioning Override until the override is removed. """ + USE_RAMPING_VERSION = int( + temporalio.api.enums.v1.ContinueAsNewVersioningBehavior.CONTINUE_AS_NEW_VERSIONING_BEHAVIOR_USE_RAMPING_VERSION + ) + """Use the Ramping Version of the workflow's task queue at start time, regardless of the workflow's + Target Version. After the first workflow task completes, the workflow will use whatever Versioning + Behavior it is annotated with. If there is no Ramping Version by the time that the first workflow task + is dispatched, it will be sent to the Current Version. + + It is highly discouraged to use this if the workflow is annotated with AutoUpgrade behavior, because + this setting ONLY applies to the first task of the workflow. If, after the first task, the workflow + is AutoUpgrade, it will behave like a normal AutoUpgrade workflow and go to the Target Version, which + may be the Current Version instead of the Ramping Version. + + Note that if the workflow being continued has a Pinned override, that override will be inherited by the + new workflow run regardless of the ContinueAsNewVersioningBehavior specified in the continue-as-new + command. Versioning Override always takes precedence until it's removed manually via + UpdateWorkflowExecutionOptions. + """ + ServiceT = TypeVar("ServiceT") diff --git a/tests/__init__.py b/tests/__init__.py index 5af71def3..86e6edb54 100644 --- a/tests/__init__.py +++ b/tests/__init__.py @@ -1 +1 @@ -DEV_SERVER_DOWNLOAD_VERSION = "v1.6.1-server-1.31.0-151.0" +DEV_SERVER_DOWNLOAD_VERSION = "v1.7.0" diff --git a/tests/worker/test_worker.py b/tests/worker/test_worker.py index 4aa366735..bd9d9b898 100644 --- a/tests/worker/test_worker.py +++ b/tests/worker/test_worker.py @@ -1456,6 +1456,40 @@ async def run(self, attempt: int) -> str: # type:ignore[reportUnusedParameter] return "v2.0" +@workflow.defn( + name="ContinueAsNewWithRampingVersion", + versioning_behavior=VersioningBehavior.PINNED, +) +class ContinueAsNewWithRampingVersionV1: + def __init__(self) -> None: + self._should_continue_as_new = False + + @workflow.run + async def run(self, attempt: int) -> str: + if attempt > 0: + return "v1.0" + + await workflow.wait_condition(lambda: self._should_continue_as_new) + workflow.continue_as_new( + arg=attempt + 1, + initial_versioning_behavior=workflow.ContinueAsNewVersioningBehavior.USE_RAMPING_VERSION, + ) + + @workflow.signal + def do_continue_as_new(self) -> None: + self._should_continue_as_new = True + + +@workflow.defn( + name="ContinueAsNewWithRampingVersion", + versioning_behavior=VersioningBehavior.PINNED, +) +class ContinueAsNewWithRampingVersionV2: + @workflow.run + async def run(self, attempt: int) -> str: # type:ignore[reportUnusedParameter] + return "v2.0" + + async def wait_for_workflow_running_on_version( handle: WorkflowHandle[Any, Any], expected_build_id: str ) -> None: @@ -1545,6 +1579,64 @@ async def test_continue_as_new_with_version_upgrade( assert result == "v2.0" +async def test_continue_as_new_with_ramping_version( + client: Client, env: WorkflowEnvironment +): + if env.supports_time_skipping: + pytest.skip("Test Server doesn't support worker deployments") + + deployment_name = f"deployment-can-ramping-{uuid.uuid4()}" + v1 = WorkerDeploymentVersion(deployment_name=deployment_name, build_id="1.0") + v2 = WorkerDeploymentVersion(deployment_name=deployment_name, build_id="2.0") + + async with ( + new_worker( + client, + ContinueAsNewWithRampingVersionV1, + deployment_config=WorkerDeploymentConfig( + version=v1, + use_worker_versioning=True, + ), + ) as w1, + new_worker( + client, + ContinueAsNewWithRampingVersionV2, + deployment_config=WorkerDeploymentConfig( + version=v2, + use_worker_versioning=True, + ), + task_queue=w1.task_queue, + ), + ): + describe_resp = await wait_until_worker_deployment_visible(client, v1) + + resp2 = await set_current_deployment_version( + client, describe_resp.conflict_token, v1 + ) + await wait_for_worker_deployment_routing_config_propagation( + client, deployment_name, v1.build_id + ) + + handle = await client.start_workflow( + "ContinueAsNewWithRampingVersion", + 0, + id=f"test-can-ramping-version-{uuid.uuid4()}", + task_queue=w1.task_queue, + ) + await wait_for_workflow_running_on_version(handle, v1.build_id) + + await wait_until_worker_deployment_visible(client, v2) + await set_ramping_version(client, resp2.conflict_token, v2, 0) + await wait_for_worker_deployment_routing_config_propagation( + client, deployment_name, v1.build_id, v2.build_id + ) + + await handle.signal(ContinueAsNewWithRampingVersionV1.do_continue_as_new) + + result = await handle.result() + assert result == "v2.0" + + def test_worker_config_matches_init_params(): """WorkerConfig TypedDict keys must match Worker.__init__ kwargs.""" import inspect From aa95444622e748456bbe1a2475cbb80ff9daddd4 Mon Sep 17 00:00:00 2001 From: Drew Hoskins Date: Fri, 1 May 2026 16:46:26 -0700 Subject: [PATCH 076/226] Report 'client_region' in S3 diagnostics for clarity (#1494) --- temporalio/contrib/aws/s3driver/aioboto3.py | 2 +- tests/contrib/aws/s3driver/conftest.py | 4 ++-- tests/contrib/aws/s3driver/test_s3driver.py | 10 +++++----- tests/contrib/aws/s3driver/test_s3driver_worker.py | 6 +++--- 4 files changed, 11 insertions(+), 11 deletions(-) diff --git a/temporalio/contrib/aws/s3driver/aioboto3.py b/temporalio/contrib/aws/s3driver/aioboto3.py index 971ccfdba..f6eda82ec 100644 --- a/temporalio/contrib/aws/s3driver/aioboto3.py +++ b/temporalio/contrib/aws/s3driver/aioboto3.py @@ -40,7 +40,7 @@ def describe(self) -> Mapping[str, str]: messages to short-circuit the most common silent 403 misconfiguration. """ region = self._client.meta.region_name - return {"region": region} if region else {} + return {"client_region": region} if region else {} async def object_exists(self, *, bucket: str, key: str) -> bool: """Check existence via aioboto3's ``head_object``.""" diff --git a/tests/contrib/aws/s3driver/conftest.py b/tests/contrib/aws/s3driver/conftest.py index 71a0a8749..6213014af 100644 --- a/tests/contrib/aws/s3driver/conftest.py +++ b/tests/contrib/aws/s3driver/conftest.py @@ -14,7 +14,7 @@ from temporalio.contrib.aws.s3driver.aioboto3 import new_aioboto3_client BUCKET = "test-bucket" -REGION = "us-east-1" +CLIENT_REGION = "us-east-1" def _find_free_port() -> int: @@ -50,7 +50,7 @@ async def aioboto3_client(moto_server_url: str) -> AsyncIterator[S3Client]: session = aioboto3.Session() async with session.client( "s3", - region_name=REGION, + region_name=CLIENT_REGION, endpoint_url=moto_server_url, aws_access_key_id="testing", aws_secret_access_key="testing", diff --git a/tests/contrib/aws/s3driver/test_s3driver.py b/tests/contrib/aws/s3driver/test_s3driver.py index fb8c60544..64e0d53ab 100644 --- a/tests/contrib/aws/s3driver/test_s3driver.py +++ b/tests/contrib/aws/s3driver/test_s3driver.py @@ -36,7 +36,7 @@ StorageDriverStoreContext, StorageDriverWorkflowInfo, ) -from tests.contrib.aws.s3driver.conftest import BUCKET, REGION +from tests.contrib.aws.s3driver.conftest import BUCKET, CLIENT_REGION _CONVERTER = JSONPlainPayloadConverter() @@ -620,7 +620,7 @@ async def test_store_nonexistent_bucket_raises( await driver.store(make_store_context(), [payload]) assert ( str(exc_info.value) - == f"S3StorageDriver store failed [bucket={bucket}, key={expected_key}, region={REGION}]" + == f"S3StorageDriver store failed [bucket={bucket}, key={expected_key}, client_region={CLIENT_REGION}]" ) assert isinstance(exc_info.value.__cause__, ClientError) assert ( @@ -638,7 +638,7 @@ async def test_retrieve_nonexistent_key_raises( await driver.retrieve(StorageDriverRetrieveContext(), [claim]) assert ( str(exc_info.value) - == f"S3StorageDriver retrieve failed [bucket={BUCKET}, key={key}, region={REGION}]" + == f"S3StorageDriver retrieve failed [bucket={BUCKET}, key={key}, client_region={CLIENT_REGION}]" ) assert isinstance(exc_info.value.__cause__, ClientError) assert ( @@ -657,7 +657,7 @@ async def test_retrieve_nonexistent_bucket_raises( await driver.retrieve(StorageDriverRetrieveContext(), [claim]) assert ( str(exc_info.value) - == f"S3StorageDriver retrieve failed [bucket={bucket}, key={key}, region={REGION}]" + == f"S3StorageDriver retrieve failed [bucket={bucket}, key={key}, client_region={CLIENT_REGION}]" ) assert isinstance(exc_info.value.__cause__, ClientError) assert ( @@ -856,7 +856,7 @@ def _make_client(self, region: str | None) -> _Aioboto3StorageDriverClient: def test_returns_region(self) -> None: client = self._make_client(region="ap-southeast-1") - assert client.describe() == {"region": "ap-southeast-1"} + assert client.describe() == {"client_region": "ap-southeast-1"} def test_omits_region_when_none(self) -> None: client = self._make_client(region=None) diff --git a/tests/contrib/aws/s3driver/test_s3driver_worker.py b/tests/contrib/aws/s3driver/test_s3driver_worker.py index 4478b06fe..61729535f 100644 --- a/tests/contrib/aws/s3driver/test_s3driver_worker.py +++ b/tests/contrib/aws/s3driver/test_s3driver_worker.py @@ -25,7 +25,7 @@ from temporalio.converter import ExternalStorage, JSONPlainPayloadConverter from temporalio.exceptions import ActivityError, ApplicationError from temporalio.testing import WorkflowEnvironment -from tests.contrib.aws.s3driver.conftest import BUCKET, REGION +from tests.contrib.aws.s3driver.conftest import BUCKET, CLIENT_REGION from tests.contrib.aws.s3driver.workflows import ( LARGE, ChildWorkflow, @@ -463,7 +463,7 @@ async def test_s3_store_failure_surfaces_in_workflow_history( session = aioboto3.Session() async with session.client( "s3", - region_name=REGION, + region_name=CLIENT_REGION, endpoint_url=moto_server_url, aws_access_key_id="testing", aws_secret_access_key="testing", @@ -506,4 +506,4 @@ async def test_s3_store_failure_surfaces_in_workflow_history( msg = app_error.message assert f"S3StorageDriver store failed [bucket={bad_bucket}, key=" in msg assert f"/wt/LargeOutputNoRetryWorkflow/wi/{workflow_id}/ri/" in msg - assert f"/d/sha256/{expected_hash}, region={REGION}]" in msg + assert f"/d/sha256/{expected_hash}, client_region={CLIENT_REGION}]" in msg From 8de1cef9f95edaeea676b1faaa7b3f4d2456ee19 Mon Sep 17 00:00:00 2001 From: Johann Schleier-Smith Date: Wed, 6 May 2026 13:03:12 -0700 Subject: [PATCH 077/226] contrib/openai_agents: stream model events via Workflow Streams (#1497) * contrib: openai_agents streaming integration Re-applies the openai_agents streaming integration originally split out of PR #1423 on commit 59c7582c, updated for the post-PR API: TResponseStreamEvent is a typing-special form, not a class, so the topic stays untyped (default Any) and subscribers pass result_type=TResponseStreamEvent on their own subscribe call. Opt in via `OpenAIAgentsPlugin(model_params=ModelActivityParameters( streaming_event_topic="..."))`. Co-Authored-By: Claude Opus 4.7 (1M context) * rename * fix lint * remove streaming heartbeat_timeout default, document recommendation Drop the implicit 30s fallback for streaming activities and document that heartbeat_timeout should be set lower than start_to_close_timeout so a stuck model call is detected before the overall activity timeout fires. --------- Co-authored-by: Claude Opus 4.7 (1M context) Co-authored-by: Brian Strauch --- temporalio/contrib/openai_agents/README.md | 97 ++++- .../openai_agents/_invoke_model_activity.py | 286 ++++++++------ temporalio/contrib/openai_agents/_mcp.py | 3 - .../openai_agents/_model_parameters.py | 28 +- .../contrib/openai_agents/_openai_runner.py | 154 ++++++-- .../openai_agents/_temporal_model_stub.py | 131 +++++-- .../openai_agents/_temporal_openai_agents.py | 6 +- .../openai_agents/test_openai_streaming.py | 348 ++++++++++++++++++ 8 files changed, 874 insertions(+), 179 deletions(-) create mode 100644 tests/contrib/openai_agents/test_openai_streaming.py diff --git a/temporalio/contrib/openai_agents/README.md b/temporalio/contrib/openai_agents/README.md index ae1243dcb..31f668b16 100644 --- a/temporalio/contrib/openai_agents/README.md +++ b/temporalio/contrib/openai_agents/README.md @@ -576,10 +576,82 @@ result = await Runner.run( ) ``` +## Streaming + +⚠️ **Experimental** - This functionality is subject to change prior to General Availability. + +The integration supports streaming model responses via the SDK-native +`Runner.run_streamed` API. Inside a workflow, model calls execute as a +streaming activity (`invoke_model_activity_streaming`) that consumes +`Model.stream_response` and returns the collected list of native OpenAI +response events. The workflow surfaces those events to the caller +through `RunResultStreaming.stream_events()`, which wraps them in the +agents-SDK `StreamEvent` union (so raw model events arrive as +`RawResponsesStreamEvent.data`). + +External consumers (UIs, tracing pipelines, etc.) observe events as +they arrive by hosting a [`WorkflowStream`](../workflow_streams/README.md) +in the workflow and subscribing with `WorkflowStreamClient`. The +streaming activity publishes each event to the topic configured on +`ModelActivityParameters.streaming_topic`. The topic is required +when using `Runner.run_streamed`; calling it without a configured topic +raises before any activity is scheduled. + +Example workflow consuming events via `stream_events()` while the +streaming activity publishes to the `"events"` topic: + +```python +from agents import Agent, Runner +from agents.stream_events import RawResponsesStreamEvent + +from temporalio import workflow + +@workflow.defn +class MyAgent: + @workflow.run + async def run(self, prompt: str) -> str: + agent = Agent(name="Assistant", instructions="...") + result = Runner.run_streamed(agent, prompt) + async for event in result.stream_events(): + if isinstance(event, RawResponsesStreamEvent): + raw_event = event.data # native OpenAI ResponseStreamEvent + ... + return result.final_output +``` + +To publish raw model events to external subscribers, host a +`WorkflowStream` in the workflow and configure +`OpenAIAgentsPlugin(model_params=ModelActivityParameters(streaming_topic="events"))`. See [`temporalio.contrib.workflow_streams`](../workflow_streams/README.md) for the +publisher and subscriber API. + +`RunResultStreaming.stream_events()` yields the agents-SDK +`StreamEvent` union (`RawResponsesStreamEvent`, `RunItemStreamEvent`, +`AgentUpdatedStreamEvent`); native OpenAI response events arrive +wrapped as `RawResponsesStreamEvent.data`. Workflow-stream subscribers, +by contrast, receive the unwrapped native events directly because the +streaming activity publishes them straight from `Model.stream_response`. + +Streaming is incompatible with `use_local_activity` because local +activities support neither activity heartbeats nor the workflow stream +signal channel. + +Activity retries surface to workflow-stream subscribers but not to +`RunResultStreaming.stream_events()`. Events are published to the +stream as `Model.stream_response` produces them, so a partial attempt +that fails mid-response leaves its emitted events on the stream and the +retry attempt publishes a second sequence. `stream_events()` only sees +the final successful attempt's collected events because it consumes the +activity's return value. Workflow-stream subscribers should treat +retries the same way as any other workflow_streams publisher — see +[Delivery semantics](../workflow_streams/README.md) for the trade and +the conventional `RETRY` event pattern for surfacing the transition to +consumers. + ## Feature Support This integration is presently subject to certain limitations. -Streaming and voice agents are not supported. +Realtime agents are not supported. Streaming is supported via +`Runner.run_streamed` — see [Streaming](#streaming) above. Certain tools are not suitable for a distributed computing environment, so these have been disabled as well. ### Model Providers @@ -591,12 +663,10 @@ Certain tools are not suitable for a distributed computing environment, so these ### Model Response format -This integration does not presently support streaming. - -| Model Response | Supported | -| :------------- | :-------: | -| Get Response | Yes | -| Streaming | No | +| Model Response | Supported | +| :------------- | :------------------: | +| Get Response | Yes | +| Streaming | Yes (experimental) | ### Tools @@ -900,10 +970,15 @@ If OTEL instrumentation is not enabled, the integration works normally without a ### Voice -| Mode | Supported | -| :----------------------- | :-------: | -| Voice agents (pipelines) | No | -| Realtime agents | No | +| Mode | Supported | +| :----------------------- | :-----------: | +| Voice agents (pipelines) | Yes [^voice] | +| Realtime agents | No | + +[^voice]: `VoicePipeline` runs in your process and delegates the agent + step (`VoiceWorkflowBase.run`) to a Temporal workflow that uses + `Runner.run` or `Runner.run_streamed`. STT and TTS run outside + Temporal; the agent loop is durable. ### Utilities diff --git a/temporalio/contrib/openai_agents/_invoke_model_activity.py b/temporalio/contrib/openai_agents/_invoke_model_activity.py index cffd8855e..1aa836eee 100644 --- a/temporalio/contrib/openai_agents/_invoke_model_activity.py +++ b/temporalio/contrib/openai_agents/_invoke_model_activity.py @@ -6,7 +6,7 @@ import enum from dataclasses import dataclass from datetime import timedelta -from typing import Any +from typing import Any, NoReturn from agents import ( AgentOutputSchemaBase, @@ -27,6 +27,7 @@ UserError, WebSearchTool, ) +from agents.items import TResponseStreamEvent from agents.tool import ( ApplyPatchTool, LocalShellTool, @@ -43,6 +44,7 @@ from temporalio import activity from temporalio.contrib.openai_agents._heartbeat_decorator import _auto_heartbeater +from temporalio.contrib.workflow_streams import WorkflowStreamClient from temporalio.exceptions import ApplicationError @@ -187,6 +189,119 @@ class ActivityModelInput(TypedDict, total=False): prompt: Any | None +class StreamingActivityModelInput(ActivityModelInput, total=False): + """Input for the invoke_model_activity_streaming activity. + + Adds the streaming-only fields on top of :class:`ActivityModelInput`. + """ + + streaming_topic: Required[str] + streaming_batch_interval: timedelta + + +async def _empty_on_invoke_tool(_ctx: RunContextWrapper[Any], _input: str) -> str: + return "" + + +async def _empty_on_invoke_handoff(_ctx: RunContextWrapper[Any], _input: str) -> Any: + return None + + +async def _noop_shell_executor(*_a: Any, **_kw: Any) -> str: + return "" + + +def _build_tool(tool: ToolInput) -> Tool: + """Reconstruct a Tool from its data-conversion-friendly input form.""" + if isinstance( + tool, + ( + FileSearchTool, + WebSearchTool, + ImageGenerationTool, + CodeInterpreterTool, + LocalShellTool, + ToolSearchTool, + ), + ): + return tool + elif isinstance(tool, ShellToolInput): + return ShellTool( + name=tool.name, + environment=tool.environment, + executor=_noop_shell_executor, + ) + elif isinstance(tool, ApplyPatchToolInput): + return ApplyPatchTool(name=tool.name, editor=_NoopApplyPatchEditor()) + elif isinstance(tool, HostedMCPToolInput): + return HostedMCPTool(tool_config=tool.tool_config) + elif isinstance(tool, FunctionToolInput): + return FunctionTool( + name=tool.name, + description=tool.description, + params_json_schema=tool.params_json_schema, + on_invoke_tool=_empty_on_invoke_tool, + strict_json_schema=tool.strict_json_schema, + ) + else: + raise UserError(f"Unknown tool type: {tool.name}") # type:ignore[reportUnreachable] + + +def _build_tools_and_handoffs( + input: ActivityModelInput, +) -> tuple[list[Tool], list[Handoff[Any, Any]]]: + tools = [_build_tool(x) for x in input.get("tools", [])] + handoffs: list[Handoff[Any, Any]] = [ + Handoff( + tool_name=x.tool_name, + tool_description=x.tool_description, + input_json_schema=x.input_json_schema, + agent_name=x.agent_name, + strict_json_schema=x.strict_json_schema, + on_invoke_handoff=_empty_on_invoke_handoff, + ) + for x in input.get("handoffs", []) + ] + return tools, handoffs + + +def _raise_for_openai_status(e: APIStatusError) -> NoReturn: + """Translate an OpenAI APIStatusError into the right retry posture.""" + retry_after: timedelta | None = None + retry_after_ms_header = e.response.headers.get("retry-after-ms") + if retry_after_ms_header is not None: + retry_after = timedelta(milliseconds=float(retry_after_ms_header)) + + if retry_after is None: + retry_after_header = e.response.headers.get("retry-after") + if retry_after_header is not None: + retry_after = timedelta(seconds=float(retry_after_header)) + + should_retry_header = e.response.headers.get("x-should-retry") + if should_retry_header == "true": + raise e + if should_retry_header == "false": + raise ApplicationError( + "Non retryable OpenAI error", + non_retryable=True, + next_retry_delay=retry_after, + ) from e + + # Retry on 408 (Request Timeout), 409 (Conflict / often transient + # state mismatch), 429 (Too Many Requests / rate-limited), and any + # 5xx (server-side errors). All other 4xx codes are caller errors + # that won't recover on retry. + retryable = ( + e.response.status_code in [408, 409, 429] or e.response.status_code >= 500 + ) + raise ApplicationError( + f"{'Retryable' if retryable else 'Non retryable'} OpenAI status code: " + f"{e.response.status_code}", + non_retryable=not retryable, + next_retry_delay=retry_after, + ) from e + + class ModelActivity: """Class wrapper for model invocation activities to allow model customization. By default, we use an OpenAIProvider with retries disabled. Disabling retries in your model of choice is recommended to allow activity retries to define the retry model. @@ -203,72 +318,7 @@ def __init__(self, model_provider: ModelProvider | None = None): async def invoke_model_activity(self, input: ActivityModelInput) -> ModelResponse: """Activity that invokes a model with the given input.""" model = self._model_provider.get_model(input.get("model_name")) - - async def empty_on_invoke_tool( - _ctx: RunContextWrapper[Any], _input: str - ) -> str: - return "" - - async def empty_on_invoke_handoff( - _ctx: RunContextWrapper[Any], _input: str - ) -> Any: - return None - - def make_tool(tool: ToolInput) -> Tool: - if isinstance( - tool, - ( - FileSearchTool, - WebSearchTool, - ImageGenerationTool, - CodeInterpreterTool, - LocalShellTool, - ToolSearchTool, - ), - ): - return tool - elif isinstance(tool, ShellToolInput): - - async def _noop_executor(*a: Any, **kw: Any) -> str: # type: ignore[reportUnusedParameter] - return "" - - return ShellTool( - name=tool.name, - environment=tool.environment, - executor=_noop_executor, - ) - elif isinstance(tool, ApplyPatchToolInput): - return ApplyPatchTool( - name=tool.name, - editor=_NoopApplyPatchEditor(), - ) - elif isinstance(tool, HostedMCPToolInput): - return HostedMCPTool( - tool_config=tool.tool_config, - ) - elif isinstance(tool, FunctionToolInput): - return FunctionTool( - name=tool.name, - description=tool.description, - params_json_schema=tool.params_json_schema, - on_invoke_tool=empty_on_invoke_tool, - strict_json_schema=tool.strict_json_schema, - ) - else: - raise UserError(f"Unknown tool type: {tool.name}") # type:ignore[reportUnreachable] - - tools = [make_tool(x) for x in input.get("tools", [])] - handoffs: list[Handoff[Any, Any]] = [ - Handoff( - tool_name=x.tool_name, - tool_description=x.tool_description, - input_json_schema=x.input_json_schema, - agent_name=x.agent_name, - strict_json_schema=x.strict_json_schema, - on_invoke_handoff=empty_on_invoke_handoff, - ) - for x in input.get("handoffs", []) - ] + tools, handoffs = _build_tools_and_handoffs(input) try: return await model.get_response( @@ -284,40 +334,68 @@ async def _noop_executor(*a: Any, **kw: Any) -> str: # type: ignore[reportUnuse prompt=input.get("prompt"), ) except APIStatusError as e: - # Listen to server hints - retry_after = None - retry_after_ms_header = e.response.headers.get("retry-after-ms") - if retry_after_ms_header is not None: - retry_after = timedelta(milliseconds=float(retry_after_ms_header)) - - if retry_after is None: - retry_after_header = e.response.headers.get("retry-after") - if retry_after_header is not None: - retry_after = timedelta(seconds=float(retry_after_header)) - - should_retry_header = e.response.headers.get("x-should-retry") - if should_retry_header == "true": - raise e - if should_retry_header == "false": - raise ApplicationError( - "Non retryable OpenAI error", - non_retryable=True, - next_retry_delay=retry_after, - ) from e - - # Specifically retryable status codes - if ( - e.response.status_code in [408, 409, 429] - or e.response.status_code >= 500 - ): - raise ApplicationError( - f"Retryable OpenAI status code: {e.response.status_code}", - non_retryable=False, - next_retry_delay=retry_after, - ) from e - - raise ApplicationError( - f"Non retryable OpenAI status code: {e.response.status_code}", - non_retryable=True, - next_retry_delay=retry_after, - ) from e + _raise_for_openai_status(e) + + @activity.defn + @_auto_heartbeater + async def invoke_model_activity_streaming( + self, input: StreamingActivityModelInput + ) -> list[TResponseStreamEvent]: + """Streaming-aware model activity. + + .. warning:: + Streaming support is experimental and may change in future + versions. + + Calls ``model.stream_response()`` and returns the collected list + of native OpenAI stream events. The workflow's + ``Model.stream_response`` stub yields these to the agents + framework, which builds the final ``ModelResponse`` from the + terminal ``ResponseCompletedEvent``. + + Each event is also published to the workflow's stream on + ``streaming_topic`` so external consumers (UIs, tracing, + etc.) can observe events as they arrive. + + Heartbeats run on a background task via ``_auto_heartbeater`` so + long initial-token latency or long pauses between chunks do not + trip ``heartbeat_timeout``. + """ + model = self._model_provider.get_model(input.get("model_name")) + tools, handoffs = _build_tools_and_handoffs(input) + + topic = input["streaming_topic"] + batch_interval = input.get( + "streaming_batch_interval", timedelta(milliseconds=100) + ) + events: list[TResponseStreamEvent] = [] + + stream = WorkflowStreamClient.from_within_activity( + batch_interval=batch_interval + ) + # TResponseStreamEvent is a typing.Annotated[Union[...]] — a typing + # special form, not a class — so it cannot be passed as type[T]. + # Leave the topic untyped (default Any); subscribers that want + # typed decode can pass result_type=TResponseStreamEvent on + # their own subscribe call. + events_topic = stream.topic(topic) + async with stream: + try: + async for event in model.stream_response( + system_instructions=input.get("system_instructions"), + input=input["input"], + model_settings=input["model_settings"], + tools=tools, + output_schema=input.get("output_schema"), + handoffs=handoffs, + tracing=ModelTracing(input["tracing"]), + previous_response_id=input.get("previous_response_id"), + conversation_id=input.get("conversation_id"), + prompt=input.get("prompt"), + ): + events.append(event) + events_topic.publish(event) + except APIStatusError as e: + _raise_for_openai_status(e) + + return events diff --git a/temporalio/contrib/openai_agents/_mcp.py b/temporalio/contrib/openai_agents/_mcp.py index 78ac5daa0..ba494c42d 100644 --- a/temporalio/contrib/openai_agents/_mcp.py +++ b/temporalio/contrib/openai_agents/_mcp.py @@ -2,7 +2,6 @@ import dataclasses import functools import inspect -import logging from collections.abc import Callable, Sequence from contextlib import AbstractAsyncContextManager from datetime import timedelta @@ -28,8 +27,6 @@ from temporalio.worker import PollerBehaviorSimpleMaximum, Worker from temporalio.workflow import ActivityConfig, ActivityHandle -logger = logging.getLogger(__name__) - @dataclasses.dataclass class _StatelessListToolsArguments: diff --git a/temporalio/contrib/openai_agents/_model_parameters.py b/temporalio/contrib/openai_agents/_model_parameters.py index 55827e0d5..c7dcf0a35 100644 --- a/temporalio/contrib/openai_agents/_model_parameters.py +++ b/temporalio/contrib/openai_agents/_model_parameters.py @@ -49,7 +49,10 @@ class ModelActivityParameters: """Maximum time for the activity to complete.""" heartbeat_timeout: timedelta | None = None - """Maximum time between heartbeats.""" + """Maximum time between heartbeats. For streaming + (``Runner.run_streamed``), set this lower than + ``start_to_close_timeout`` so a stuck model call is detected before the + overall activity timeout fires.""" retry_policy: RetryPolicy | None = None """Policy for retrying failed activities.""" @@ -68,3 +71,26 @@ class ModelActivityParameters: use_local_activity: bool = False """Whether to use a local activity. If changed during a workflow execution, that would break determinism.""" + + streaming_topic: str | None = None + """Stream topic to publish raw model stream events to when the workflow + calls ``Runner.run_streamed``. Required for ``Runner.run_streamed``; + if left as ``None``, ``run_streamed`` raises before scheduling any + activity. The workflow must host a + :class:`temporalio.contrib.workflow_streams.WorkflowStream` to receive + the publishes; otherwise the signals are unhandled and dropped. + + Streaming is incompatible with ``use_local_activity`` (local activities + do not support heartbeats or the workflow stream signal channel). + + .. warning:: + Streaming support is experimental and may change in future + versions.""" + + streaming_batch_interval: timedelta = timedelta(milliseconds=100) + """Interval between automatic flushes for the stream publisher used + by the streaming activity. + + .. warning:: + Streaming support is experimental and may change in future + versions.""" diff --git a/temporalio/contrib/openai_agents/_openai_runner.py b/temporalio/contrib/openai_agents/_openai_runner.py index 1884ff8a6..478217c8f 100644 --- a/temporalio/contrib/openai_agents/_openai_runner.py +++ b/temporalio/contrib/openai_agents/_openai_runner.py @@ -1,5 +1,5 @@ import dataclasses -from collections.abc import Awaitable +from collections.abc import AsyncIterator, Awaitable from typing import Any, Callable from agents import ( @@ -15,7 +15,7 @@ TContext, TResponseInputItem, ) -from agents.run import DEFAULT_AGENT_RUNNER, DEFAULT_MAX_TURNS, AgentRunner, RunOptions +from agents.run import DEFAULT_AGENT_RUNNER, AgentRunner, RunOptions from agents.sandbox import SandboxAgent from typing_extensions import Unpack @@ -114,20 +114,12 @@ def __init__( self._runner = DEFAULT_AGENT_RUNNER or AgentRunner() self.model_params = model_params - async def run( + def _prepare_workflow_run( self, starting_agent: Agent[TContext], - input: str | list[TResponseInputItem] | RunState[TContext], - **kwargs: Unpack[RunOptions[TContext]], - ) -> RunResult: - """Run the agent in a Temporal workflow.""" - if not workflow.in_workflow(): - return await self._runner.run( - starting_agent, - input, - **kwargs, - ) - + kwargs: RunOptions[TContext], + ) -> Agent[Any]: + """Workflow-only validation and ``kwargs`` rewrite shared by ``run()`` and ``run_streamed()``.""" for t in starting_agent.tools: if callable(t): raise ValueError( @@ -152,16 +144,10 @@ async def run( f"Unknown mcp_server type {type(s)} may not work durably." ) - context = kwargs.get("context") - max_turns = kwargs.get("max_turns", DEFAULT_MAX_TURNS) - hooks = kwargs.get("hooks") - run_config = kwargs.get("run_config") - previous_response_id = kwargs.get("previous_response_id") - session = kwargs.get("session") - - if isinstance(session, SQLiteSession): + if isinstance(kwargs.get("session"), SQLiteSession): raise ValueError("Temporal workflows don't support SQLite sessions.") + run_config = kwargs.get("run_config") if run_config is None: run_config = RunConfig() @@ -176,6 +162,7 @@ async def run( run_config.model, model_params=self.model_params, agent=None ), ) + # run_config.sandbox is global for the entire run — configure it if any agent needs it. if _has_sandbox_agent(starting_agent) or run_config.sandbox: if run_config.sandbox is None: @@ -199,16 +186,30 @@ async def run( "Do not pass a raw sandbox client directly." ) + kwargs["run_config"] = run_config + return _convert_agent(self.model_params, starting_agent, None) + + async def run( + self, + starting_agent: Agent[TContext], + input: str | list[TResponseInputItem] | RunState[TContext], + **kwargs: Unpack[RunOptions[TContext]], + ) -> RunResult: + """Run the agent in a Temporal workflow.""" + if not workflow.in_workflow(): + return await self._runner.run( + starting_agent, + input, + **kwargs, + ) + + converted_agent = self._prepare_workflow_run(starting_agent, kwargs) + try: return await self._runner.run( - starting_agent=_convert_agent(self.model_params, starting_agent, None), + starting_agent=converted_agent, input=input, - context=context, - max_turns=max_turns, - hooks=hooks, - run_config=run_config, - previous_response_id=previous_response_id, - session=session, + **kwargs, ) except AgentsException as e: # In order for workflow failures to properly fail the workflow, we need to rewrap them in @@ -241,16 +242,105 @@ def run_streamed( self, starting_agent: Agent[TContext], input: str | list[TResponseInputItem] | RunState[TContext], - **kwargs: Any, + **kwargs: Unpack[RunOptions[TContext]], ) -> RunResultStreaming: - """Run the agent with streaming responses (not supported in Temporal workflows).""" + """Run the agent with streaming responses. + + .. warning:: + Streaming inside Temporal workflows is experimental and may + change in future versions. + + Inside a workflow, model calls execute as the streaming model + activity. The workflow consumes events via + ``RunResultStreaming.stream_events()`` after each activity + completes; external clients can subscribe to the configured + stream topic to receive events as they arrive. + """ if not workflow.in_workflow(): return self._runner.run_streamed( starting_agent, input, **kwargs, ) - raise RuntimeError("Temporal workflows do not support streaming.") + + # Fail-fast before the agents framework starts a background task: + # validation raised inside ``Model.stream_response`` is otherwise + # captured into ``RunResultStreaming._stored_exception`` and may + # be silently dropped if the queue completion sentinel is read + # before the run_loop_task is observed as done. + if self.model_params.streaming_topic is None: + raise AgentsWorkflowError( + "Runner.run_streamed requires " + "ModelActivityParameters.streaming_topic to be set." + ) + if self.model_params.use_local_activity: + raise AgentsWorkflowError( + "Runner.run_streamed is incompatible with " + "use_local_activity (local activities do not support " + "heartbeats or the workflow stream signal channel)." + ) + + converted_agent = self._prepare_workflow_run(starting_agent, kwargs) + + streamed_result = self._runner.run_streamed( + starting_agent=converted_agent, + input=input, + **kwargs, + ) + + # Mirror the AgentsException -> AgentsWorkflowError rewrap done + # in run() above. The streaming runner attaches the actual run + # to ``run_loop_task``; we wrap ``stream_events()`` (rather than + # the task itself) so the rewrap happens on the consumer's + # coroutine. Wrapping in a second asyncio task introduces a + # scheduling gap: ``RunResultStreaming.stream_events()`` reads + # the queue completion sentinel as soon as the run loop ends, + # but the wrapper task only resumes its ``await`` after another + # event-loop tick — between those two points, ``_check_errors`` + # sees no exception and ``_await_task_safely`` later swallows + # the rewrapped one. Iterating the underlying generator first, + # then inspecting the finished task on exit, keeps the rewrap + # race-free without touching ``run_loop_task``. + original_stream_events = streamed_result.stream_events + run_loop_task = streamed_result.run_loop_task + + async def _stream_events_with_rewrap() -> AsyncIterator[Any]: + try: + async for event in original_stream_events(): + yield event + except AgentsException as e: + _reraise_workflow_failure(e) + raise + # The agents framework may have stored the run-loop + # exception on ``_stored_exception`` (or surfaced it through + # the iterator) without re-raising it through stream_events. + # By the time the iterator is exhausted, ``run_loop_task`` + # is done — surface its exception here so a failed run + # cannot appear successful, applying the workflow-failure + # rewrap when applicable. + if run_loop_task is not None and run_loop_task.done(): + exc = run_loop_task.exception() + if exc is not None: + if isinstance(exc, AgentsException): + _reraise_workflow_failure(exc) + raise exc + + streamed_result.stream_events = _stream_events_with_rewrap # type: ignore[method-assign] + return streamed_result + + +def _reraise_workflow_failure(e: AgentsException) -> None: + """Rewrap an AgentsException whose cause is a Temporal workflow failure. + + Returns normally when ``e`` is not workflow-failure-bearing so the + caller can re-raise the original. + """ + if e.__cause__ and workflow.is_failure_exception(e.__cause__): + reraise = AgentsWorkflowError( + f"Workflow failure exception in Agents Framework: {e}" + ) + reraise.__traceback__ = e.__traceback__ + raise reraise from e.__cause__ def _model_name(agent: Agent[Any]) -> str | None: diff --git a/temporalio/contrib/openai_agents/_temporal_model_stub.py b/temporalio/contrib/openai_agents/_temporal_model_stub.py index 03e689f17..7f9ab11d9 100644 --- a/temporalio/contrib/openai_agents/_temporal_model_stub.py +++ b/temporalio/contrib/openai_agents/_temporal_model_stub.py @@ -1,12 +1,5 @@ from __future__ import annotations -import logging - -from temporalio import workflow -from temporalio.contrib.openai_agents._model_parameters import ModelActivityParameters - -logger = logging.getLogger(__name__) - from collections.abc import AsyncIterator from typing import Any @@ -32,6 +25,7 @@ from agents.tool import ApplyPatchTool, LocalShellTool, ShellTool, ToolSearchTool from openai.types.responses.response_prompt_param import ResponsePromptParam +from temporalio import workflow from temporalio.contrib.openai_agents._invoke_model_activity import ( ActivityModelInput, AgentOutputSchemaInput, @@ -42,8 +36,10 @@ ModelActivity, ModelTracingInput, ShellToolInput, + StreamingActivityModelInput, ToolInput, ) +from temporalio.contrib.openai_agents._model_parameters import ModelActivityParameters class _TemporalModelStub(Model): # type:ignore[reportUnusedClass] @@ -60,8 +56,9 @@ def __init__( self.model_params = model_params self.agent = agent - async def get_response( + def _build_activity_input( self, + *, system_instructions: str | None, input: str | list[TResponseInputItem], model_settings: ModelSettings, @@ -69,11 +66,10 @@ async def get_response( output_schema: AgentOutputSchemaBase | None, handoffs: list[Handoff], tracing: ModelTracing, - *, previous_response_id: str | None, conversation_id: str | None, prompt: ResponsePromptParam | None, - ) -> ModelResponse: + ) -> tuple[ActivityModelInput, str | None]: def make_tool_info(tool: Tool) -> ToolInput: if isinstance( tool, @@ -166,6 +162,35 @@ def make_tool_info(tool: Tool) -> ToolInput: else: summary = None + return activity_input, summary + + async def get_response( + self, + system_instructions: str | None, + input: str | list[TResponseInputItem], + model_settings: ModelSettings, + tools: list[Tool], + output_schema: AgentOutputSchemaBase | None, + handoffs: list[Handoff], + tracing: ModelTracing, + *, + previous_response_id: str | None, + conversation_id: str | None, + prompt: ResponsePromptParam | None, + ) -> ModelResponse: + activity_input, summary = self._build_activity_input( + system_instructions=system_instructions, + input=input, + model_settings=model_settings, + tools=tools, + output_schema=output_schema, + handoffs=handoffs, + tracing=tracing, + previous_response_id=previous_response_id, + conversation_id=conversation_id, + prompt=prompt, + ) + if self.model_params.use_local_activity: return await workflow.execute_local_activity_method( ModelActivity.invoke_model_activity, @@ -177,23 +202,22 @@ def make_tool_info(tool: Tool) -> ToolInput: retry_policy=self.model_params.retry_policy, cancellation_type=self.model_params.cancellation_type, ) - else: - return await workflow.execute_activity_method( - ModelActivity.invoke_model_activity, - activity_input, - summary=summary, - task_queue=self.model_params.task_queue, - schedule_to_close_timeout=self.model_params.schedule_to_close_timeout, - schedule_to_start_timeout=self.model_params.schedule_to_start_timeout, - start_to_close_timeout=self.model_params.start_to_close_timeout, - heartbeat_timeout=self.model_params.heartbeat_timeout, - retry_policy=self.model_params.retry_policy, - cancellation_type=self.model_params.cancellation_type, - versioning_intent=self.model_params.versioning_intent, - priority=self.model_params.priority, - ) + return await workflow.execute_activity_method( + ModelActivity.invoke_model_activity, + activity_input, + summary=summary, + task_queue=self.model_params.task_queue, + schedule_to_close_timeout=self.model_params.schedule_to_close_timeout, + schedule_to_start_timeout=self.model_params.schedule_to_start_timeout, + start_to_close_timeout=self.model_params.start_to_close_timeout, + heartbeat_timeout=self.model_params.heartbeat_timeout, + retry_policy=self.model_params.retry_policy, + cancellation_type=self.model_params.cancellation_type, + versioning_intent=self.model_params.versioning_intent, + priority=self.model_params.priority, + ) - def stream_response( + async def stream_response( self, system_instructions: str | None, input: str | list[TResponseInputItem], @@ -207,4 +231,57 @@ def stream_response( conversation_id: str | None, prompt: ResponsePromptParam | None, ) -> AsyncIterator[TResponseStreamEvent]: - raise NotImplementedError("Temporal model doesn't support streams yet") + # Streaming relies on activity heartbeats to detect a stuck LLM + # call and on WorkflowStreamClient.from_within_activity() to signal + # partial results back to the workflow. Local activities support + # neither: their result commits with the workflow task, so there + # is no independent task to heartbeat against or to send signals + # from. + if self.model_params.use_local_activity: + raise ValueError( + "Streaming is incompatible with use_local_activity " + "(local activities do not support heartbeats or the " + "workflow stream signal channel)." + ) + + topic = self.model_params.streaming_topic + if topic is None: + raise ValueError( + "Runner.run_streamed requires " + "ModelActivityParameters.streaming_topic to be set." + ) + + base_input, summary = self._build_activity_input( + system_instructions=system_instructions, + input=input, + model_settings=model_settings, + tools=tools, + output_schema=output_schema, + handoffs=handoffs, + tracing=tracing, + previous_response_id=previous_response_id, + conversation_id=conversation_id, + prompt=prompt, + ) + streaming_input: StreamingActivityModelInput = { + **base_input, + "streaming_topic": topic, + "streaming_batch_interval": self.model_params.streaming_batch_interval, + } + + events = await workflow.execute_activity_method( + ModelActivity.invoke_model_activity_streaming, + streaming_input, + summary=summary, + task_queue=self.model_params.task_queue, + schedule_to_close_timeout=self.model_params.schedule_to_close_timeout, + schedule_to_start_timeout=self.model_params.schedule_to_start_timeout, + start_to_close_timeout=self.model_params.start_to_close_timeout, + heartbeat_timeout=self.model_params.heartbeat_timeout, + retry_policy=self.model_params.retry_policy, + cancellation_type=self.model_params.cancellation_type, + versioning_intent=self.model_params.versioning_intent, + priority=self.model_params.priority, + ) + for event in events: + yield event diff --git a/temporalio/contrib/openai_agents/_temporal_openai_agents.py b/temporalio/contrib/openai_agents/_temporal_openai_agents.py index f7757723c..60b4b36ef 100644 --- a/temporalio/contrib/openai_agents/_temporal_openai_agents.py +++ b/temporalio/contrib/openai_agents/_temporal_openai_agents.py @@ -205,7 +205,11 @@ def add_activities( if not register_activities: return activities or [] - new_activities = [ModelActivity(model_provider).invoke_model_activity] + model_activity = ModelActivity(model_provider) + new_activities = [ + model_activity.invoke_model_activity, + model_activity.invoke_model_activity_streaming, + ] server_names = [server.name for server in mcp_server_providers] if len(server_names) != len(set(server_names)): diff --git a/tests/contrib/openai_agents/test_openai_streaming.py b/tests/contrib/openai_agents/test_openai_streaming.py new file mode 100644 index 000000000..851dc207d --- /dev/null +++ b/tests/contrib/openai_agents/test_openai_streaming.py @@ -0,0 +1,348 @@ +"""Integration tests for OpenAI Agents streaming support. + +Streaming is opt-in via ``Runner.run_streamed``. Events flow back to the +workflow through ``RunResultStreaming.stream_events()`` (in batch after +each model activity completes) and to external consumers in real time +via the configured stream topic. +""" + +import asyncio +import logging +import uuid +from collections.abc import AsyncIterator +from datetime import timedelta +from typing import Any + +import pytest +from agents import ( + Agent, + AgentOutputSchemaBase, + Handoff, + Model, + ModelResponse, + ModelSettings, + ModelTracing, + Runner, + Tool, + TResponseInputItem, + Usage, +) +from agents.items import TResponseStreamEvent +from openai.types.responses import ( + Response, + ResponseCompletedEvent, + ResponseOutputMessage, + ResponseOutputText, + ResponseTextConfig, + ResponseTextDeltaEvent, + ResponseUsage, +) +from openai.types.responses.response_usage import ( + InputTokensDetails, + OutputTokensDetails, +) +from openai.types.shared.response_format_text import ResponseFormatText + +from temporalio import workflow +from temporalio.client import Client, WorkflowFailureError +from temporalio.contrib.openai_agents import ModelActivityParameters +from temporalio.contrib.openai_agents.testing import AgentEnvironment +from temporalio.contrib.workflow_streams import WorkflowStream, WorkflowStreamClient +from tests.helpers import new_worker + +logger = logging.getLogger(__name__) + + +class StreamingTestModel(Model): + """Test model that yields text deltas followed by a ResponseCompletedEvent.""" + + __test__ = False + + async def get_response( + self, + system_instructions: str | None, + input: str | list[TResponseInputItem], + model_settings: ModelSettings, + tools: list[Tool], + output_schema: AgentOutputSchemaBase | None, + handoffs: list[Handoff], + tracing: ModelTracing, + **kwargs: Any, + ) -> ModelResponse: + return ModelResponse( + output=[ + ResponseOutputMessage( + id="msg_test", + content=[ + ResponseOutputText( + text="Hello world!", + annotations=[], + type="output_text", + logprobs=[], + ) + ], + role="assistant", + status="completed", + type="message", + ) + ], + usage=Usage(), + response_id=None, + ) + + async def stream_response( + self, + system_instructions: str | None, + input: str | list[TResponseInputItem], + model_settings: ModelSettings, + tools: list[Tool], + output_schema: AgentOutputSchemaBase | None, + handoffs: list[Handoff], + tracing: ModelTracing, + **kwargs: Any, + ) -> AsyncIterator[TResponseStreamEvent]: + # Yield text deltas + yield ResponseTextDeltaEvent( + content_index=0, + delta="Hello ", + item_id="item1", + output_index=0, + sequence_number=0, + type="response.output_text.delta", + logprobs=[], + ) + yield ResponseTextDeltaEvent( + content_index=0, + delta="world!", + item_id="item1", + output_index=0, + sequence_number=1, + type="response.output_text.delta", + logprobs=[], + ) + + # Yield the final completed event + response = Response( + id="resp_test", + created_at=0, + error=None, + incomplete_details=None, + instructions=None, + metadata={}, + model="test", + object="response", + output=[ + ResponseOutputMessage( + id="msg_test", + content=[ + ResponseOutputText( + text="Hello world!", + annotations=[], + type="output_text", + logprobs=[], + ) + ], + role="assistant", + status="completed", + type="message", + ) + ], + parallel_tool_calls=True, + temperature=1.0, + tool_choice="auto", + tools=[], + top_p=1.0, + status="completed", + text=ResponseTextConfig(format=ResponseFormatText(type="text")), + truncation="disabled", + usage=ResponseUsage( + input_tokens=10, + output_tokens=5, + total_tokens=15, + input_tokens_details=InputTokensDetails(cached_tokens=0), + output_tokens_details=OutputTokensDetails(reasoning_tokens=0), + ), + ) + yield ResponseCompletedEvent( + response=response, sequence_number=2, type="response.completed" + ) + + +@workflow.defn +class StreamingOpenAIWorkflow: + """Test workflow that opts into streaming via ``Runner.run_streamed``. + + Workflow code consumes events from ``stream_events()`` and exposes + the seen event types via a query so the test can verify both the + in-workflow iteration and the external stream subscriber observe the + same events. + """ + + @workflow.init + def __init__(self, prompt: str) -> None: + self.stream = WorkflowStream() + self.workflow_event_types: list[str] = [] + + @workflow.run + async def run(self, prompt: str) -> str: + agent = Agent[None]( + name="Assistant", + instructions="You are a test agent.", + ) + result = Runner.run_streamed(starting_agent=agent, input=prompt) + async for event in result.stream_events(): + raw = getattr(event, "data", None) + event_type = getattr(raw, "type", None) + if event_type is not None: + self.workflow_event_types.append(event_type) + return result.final_output + + @workflow.query + def get_workflow_event_types(self) -> list[str]: + return self.workflow_event_types + + +@workflow.defn +class StreamingRequiresTopicWorkflow: + """Workflow that opts into ``Runner.run_streamed`` while the model + plugin was configured without a ``streaming_topic``. + + The stub raises before scheduling the streaming activity; this + propagates out of ``Runner.run_streamed`` and fails the workflow. + """ + + @workflow.run + async def run(self, prompt: str) -> str: + agent = Agent[None]( + name="Assistant", + instructions="You are a test agent.", + ) + result = Runner.run_streamed(starting_agent=agent, input=prompt) + async for _ in result.stream_events(): + pass + return result.final_output + + +@pytest.mark.asyncio +async def test_streaming_publishes_raw_events(client: Client): + """Both the workflow consumer (via stream_events) and the stream + topic see the same native OpenAI events, in order, with no + normalization.""" + async with AgentEnvironment( + model=StreamingTestModel(), + model_params=ModelActivityParameters( + start_to_close_timeout=timedelta(seconds=30), + streaming_topic="events", + ), + ) as env: + client = env.applied_on_client(client) + workflow_id = f"openai-streaming-test-{uuid.uuid4()}" + + async with new_worker( + client, StreamingOpenAIWorkflow, max_cached_workflows=0 + ) as worker: + handle = await client.start_workflow( + StreamingOpenAIWorkflow.run, + "Hello", + id=workflow_id, + task_queue=worker.task_queue, + execution_timeout=timedelta(seconds=30), + ) + + stream = WorkflowStreamClient.create(client, workflow_id) + published: list[TResponseStreamEvent] = [] + + async def collect_events() -> None: + async for item in stream.subscribe( + ["events"], + from_offset=0, + # TResponseStreamEvent is a discriminated union + # (Annotated[..., Discriminator]); Pydantic decodes + # it via TypeAdapter at runtime, but the type + # checkers see ``Annotated`` rather than ``type``. + result_type=TResponseStreamEvent, # type: ignore[arg-type,call-overload] + poll_cooldown=timedelta(milliseconds=50), + ): + published.append(item.data) + if item.data.type == "response.completed": + break + + collect_task = asyncio.create_task(collect_events()) + result = await handle.result() + await asyncio.wait_for(collect_task, timeout=10.0) + + workflow_event_types = await handle.query( + StreamingOpenAIWorkflow.get_workflow_event_types + ) + + assert result == "Hello world!" + + published_types = [e.type for e in published] + assert published_types == [ + "response.output_text.delta", + "response.output_text.delta", + "response.completed", + ], f"Unexpected published event sequence: {published_types}" + + deltas = [e.delta for e in published if e.type == "response.output_text.delta"] + assert deltas == ["Hello ", "world!"] + + # Workflow-side iteration sees the same model events in the same order. + assert workflow_event_types == published_types + + +@pytest.mark.asyncio +async def test_streaming_requires_topic(client: Client): + """``Runner.run_streamed`` fails fast when the plugin has no topic + configured. The error is raised in ``stream_response`` before any + streaming activity is scheduled.""" + async with AgentEnvironment( + model=StreamingTestModel(), + model_params=ModelActivityParameters( + start_to_close_timeout=timedelta(seconds=30), + streaming_topic=None, + ), + ) as env: + client = env.applied_on_client(client) + async with new_worker( + client, StreamingRequiresTopicWorkflow, max_cached_workflows=0 + ) as worker: + with pytest.raises(WorkflowFailureError) as exc_info: + await client.execute_workflow( + StreamingRequiresTopicWorkflow.run, + "Hi", + id=f"openai-streaming-requires-topic-{uuid.uuid4()}", + task_queue=worker.task_queue, + execution_timeout=timedelta(seconds=30), + ) + + assert "streaming_topic" in str(exc_info.value.cause) + + +@pytest.mark.asyncio +async def test_streaming_rejects_local_activity(client: Client): + """``Runner.run_streamed`` fails fast when the plugin is configured + with ``use_local_activity=True``. Local activities support neither + heartbeats nor the workflow-stream signal channel.""" + async with AgentEnvironment( + model=StreamingTestModel(), + model_params=ModelActivityParameters( + start_to_close_timeout=timedelta(seconds=30), + streaming_topic="events", + use_local_activity=True, + ), + ) as env: + client = env.applied_on_client(client) + async with new_worker( + client, StreamingRequiresTopicWorkflow, max_cached_workflows=0 + ) as worker: + with pytest.raises(WorkflowFailureError) as exc_info: + await client.execute_workflow( + StreamingRequiresTopicWorkflow.run, + "Hi", + id=f"openai-streaming-rejects-local-{uuid.uuid4()}", + task_queue=worker.task_queue, + execution_timeout=timedelta(seconds=30), + ) + + assert "use_local_activity" in str(exc_info.value.cause) From a161d18b05e96ed4abcd678dc4b4bfa3cc84926d Mon Sep 17 00:00:00 2001 From: Johann Schleier-Smith Date: Wed, 6 May 2026 13:03:24 -0700 Subject: [PATCH 078/226] contrib/google_adk_agents: stream LlmResponse chunks via Workflow Streams (#1498) * contrib: google_adk_agents streaming integration Re-applies the google_adk_agents streaming integration originally split out of PR #1423 on commit 59c7582c. The bridge honors `stream=True` and publishes raw `LlmResponse` chunks through a typed topic handle. Opt in via the plugin's `streaming_event_topic` parameter. Co-Authored-By: Claude Opus 4.7 (1M context) * Update tests/contrib/google_adk_agents/test_adk_streaming.py * Update tests/contrib/google_adk_agents/test_adk_streaming.py * rename params --------- Co-authored-by: Claude Opus 4.7 (1M context) Co-authored-by: Brian Strauch --- .../contrib/google_adk_agents/_model.py | 109 +++++++++- .../contrib/google_adk_agents/_plugin.py | 16 +- .../google_adk_agents/test_adk_streaming.py | 195 ++++++++++++++++++ 3 files changed, 311 insertions(+), 9 deletions(-) create mode 100644 tests/contrib/google_adk_agents/test_adk_streaming.py diff --git a/temporalio/contrib/google_adk_agents/_model.py b/temporalio/contrib/google_adk_agents/_model.py index 8b32a7432..1992d0f4c 100644 --- a/temporalio/contrib/google_adk_agents/_model.py +++ b/temporalio/contrib/google_adk_agents/_model.py @@ -1,4 +1,5 @@ from collections.abc import AsyncGenerator, Callable +from dataclasses import dataclass from datetime import timedelta from google.adk.models import BaseLlm, LLMRegistry @@ -7,6 +8,8 @@ import temporalio.workflow from temporalio import activity, workflow +from temporalio.contrib.workflow_streams import WorkflowStreamClient +from temporalio.exceptions import ApplicationError from temporalio.workflow import ActivityConfig @@ -36,6 +39,58 @@ async def invoke_model(llm_request: LlmRequest) -> list[LlmResponse]: ] +@dataclass +class StreamingInvokeInput: + """Input for :func:`invoke_model_streaming`.""" + + llm_request: LlmRequest + streaming_topic: str + streaming_batch_interval: timedelta + + +@activity.defn +async def invoke_model_streaming( + input: StreamingInvokeInput, +) -> list[LlmResponse]: + """Streaming-aware model activity. + + .. warning:: + Streaming support is experimental and may change in future + versions. + + Calls the LLM with ``stream=True`` and returns the collected list of + raw ``LlmResponse`` chunks. The workflow's ``TemporalModel.generate_content_async`` + yields these to the caller. + + Each response is also published to the workflow's stream on + ``streaming_topic`` so external consumers (UIs, tracing, etc.) + can observe responses as they arrive. + """ + llm_request = input.llm_request + if llm_request.model is None: + raise ValueError("No model name provided, could not create LLM.") + + llm = LLMRegistry.new_llm(llm_request.model) + if not llm: + raise ValueError(f"Failed to create LLM for model: {llm_request.model}") + + responses: list[LlmResponse] = [] + + stream = WorkflowStreamClient.from_within_activity( + batch_interval=input.streaming_batch_interval, + ) + events = stream.topic(input.streaming_topic, type=LlmResponse) + async with stream: + async for response in llm.generate_content_async( + llm_request=llm_request, stream=True + ): + activity.heartbeat() + responses.append(response) + events.publish(response) + + return responses + + class TemporalModel(BaseLlm): """A Temporal-based LLM model that executes model invocations as activities.""" @@ -45,9 +100,15 @@ def __init__( activity_config: ActivityConfig | None = None, *, summary_fn: Callable[[LlmRequest], str | None] | None = None, + streaming_topic: str | None = None, + streaming_batch_interval: timedelta = timedelta(milliseconds=100), ) -> None: """Initialize the TemporalModel. + Streaming is selected by the caller via the ADK + ``generate_content_async(stream=True)`` argument; no plugin-level + flag is needed. + Args: model_name: The name of the model to use. activity_config: Configuration options for the activity execution. @@ -56,6 +117,19 @@ def __init__( deterministic as it is called during workflow execution. If the callable raises, the exception will propagate and fail the workflow task. + streaming_topic: Stream topic to publish raw + ``LlmResponse`` chunks to when streaming. Required when + callers invoke ``generate_content_async(stream=True)``; + if ``None``, the streaming call raises before scheduling + an activity. The workflow must host a + :class:`temporalio.contrib.workflow_streams.WorkflowStream` + to receive the publishes; otherwise the signals are + unhandled and dropped. Streaming support is + experimental and may change in future versions. + streaming_batch_interval: Interval between automatic + flushes for the stream publisher used by the streaming + activity. Streaming support is experimental and may + change in future versions. Raises: ValueError: If both ``ActivityConfig["summary"]`` and ``summary_fn`` are set. @@ -63,6 +137,8 @@ def __init__( super().__init__(model=model_name) self._model_name = model_name self._summary_fn = summary_fn + self._streaming_topic = streaming_topic + self._streaming_batch_interval = streaming_batch_interval self._activity_config = ActivityConfig( start_to_close_timeout=timedelta(seconds=60) ) @@ -80,7 +156,10 @@ async def generate_content_async( Args: llm_request: The LLM request containing model parameters and content. - stream: Whether to stream the response (currently ignored). + stream: Whether to use the streaming activity. When ``True``, + each chunk is also published to ``streaming_topic`` + (if set) for external consumers. Streaming support is + experimental and may change in future versions. Yields: The responses from the model. @@ -103,10 +182,28 @@ async def generate_content_async( agent_name = llm_request.config.labels.get("adk_agent_name") if agent_name: config["summary"] = agent_name - responses = await workflow.execute_activity( - invoke_model, - args=[llm_request], - **config, - ) + + if stream: + if self._streaming_topic is None: + raise ApplicationError( + "generate_content_async(stream=True) requires " + "TemporalModel(streaming_topic=...) to be set.", + non_retryable=True, + ) + responses = await workflow.execute_activity( + invoke_model_streaming, + StreamingInvokeInput( + llm_request=llm_request, + streaming_topic=self._streaming_topic, + streaming_batch_interval=self._streaming_batch_interval, + ), + **config, + ) + else: + responses = await workflow.execute_activity( + invoke_model, + args=[llm_request], + **config, + ) for response in responses: yield response diff --git a/temporalio/contrib/google_adk_agents/_plugin.py b/temporalio/contrib/google_adk_agents/_plugin.py index 9be321398..7344485c8 100644 --- a/temporalio/contrib/google_adk_agents/_plugin.py +++ b/temporalio/contrib/google_adk_agents/_plugin.py @@ -3,12 +3,16 @@ import dataclasses import time import uuid -from collections.abc import AsyncIterator +from collections.abc import AsyncIterator, Callable from contextlib import asynccontextmanager +from typing import Any from temporalio import workflow from temporalio.contrib.google_adk_agents._mcp import TemporalMcpToolSetProvider -from temporalio.contrib.google_adk_agents._model import invoke_model +from temporalio.contrib.google_adk_agents._model import ( + invoke_model, + invoke_model_streaming, +) from temporalio.contrib.pydantic import ( PydanticPayloadConverter, ToJsonOptions, @@ -95,7 +99,13 @@ def workflow_runner(runner: WorkflowRunner | None) -> WorkflowRunner: ) return runner - new_activities = [invoke_model] + # Annotate as Sequence[Callable[..., Any]] because invoke_model + # and invoke_model_streaming have different signatures, so the + # inferred list type would not satisfy SimplePlugin's parameter. + new_activities: list[Callable[..., Any]] = [ + invoke_model, + invoke_model_streaming, + ] if toolset_providers is not None: for toolset_provider in toolset_providers: new_activities.extend(toolset_provider._get_activities()) diff --git a/tests/contrib/google_adk_agents/test_adk_streaming.py b/tests/contrib/google_adk_agents/test_adk_streaming.py new file mode 100644 index 000000000..30aecd9f4 --- /dev/null +++ b/tests/contrib/google_adk_agents/test_adk_streaming.py @@ -0,0 +1,195 @@ +"""Integration tests for ADK streaming support. + +Verifies that the streaming model activity publishes raw ``LlmResponse`` +chunks via the WorkflowStream broker. Non-streaming behavior is covered +by ``test_google_adk_agents.py``. +""" + +import asyncio +import uuid +from collections.abc import AsyncGenerator +from datetime import timedelta + +import pytest +from google.adk import Agent +from google.adk.agents.run_config import RunConfig, StreamingMode +from google.adk.models import BaseLlm, LLMRegistry +from google.adk.models.llm_request import LlmRequest +from google.adk.models.llm_response import LlmResponse +from google.adk.runners import InMemoryRunner +from google.genai.types import Content, Part + +from temporalio import workflow +from temporalio.client import Client, WorkflowFailureError +from temporalio.contrib.google_adk_agents import GoogleAdkPlugin, TemporalModel +from temporalio.contrib.workflow_streams import WorkflowStream, WorkflowStreamClient +from temporalio.worker import Worker + + +class StreamingTestModel(BaseLlm): + """Test model that yields multiple partial responses to simulate streaming.""" + + @classmethod + def supported_models(cls) -> list[str]: + return ["streaming_test_model"] + + async def generate_content_async( + self, llm_request: LlmRequest, stream: bool = False + ) -> AsyncGenerator[LlmResponse, None]: + # The streaming activity must call us with stream=True; if a + # regression drops the flag this test should fail. + if not stream: + raise AssertionError( + "StreamingTestModel.generate_content_async requires stream=True" + ) + yield LlmResponse(content=Content(role="model", parts=[Part(text="Hello ")])) + yield LlmResponse(content=Content(role="model", parts=[Part(text="world!")])) + + +@workflow.defn +class StreamingAdkWorkflow: + """Test workflow that opts into streaming via RunConfig.streaming_mode.""" + + @workflow.init + def __init__(self, prompt: str) -> None: + self.stream = WorkflowStream() + + @workflow.run + async def run(self, prompt: str) -> str: + model = TemporalModel("streaming_test_model", streaming_topic="events") + agent = Agent( + name="test_agent", + model=model, + instruction="You are a test agent.", + ) + + runner = InMemoryRunner(agent=agent, app_name="test-app") + session = await runner.session_service.create_session( + app_name="test-app", user_id="test" + ) + + final_text = "" + async for event in runner.run_async( + user_id="test", + session_id=session.id, + new_message=Content(role="user", parts=[Part(text=prompt)]), + run_config=RunConfig(streaming_mode=StreamingMode.SSE), + ): + if event.content and event.content.parts: + for part in event.content.parts: + if part.text: + final_text = part.text + + return final_text + + +@pytest.mark.asyncio +async def test_streaming_publishes_events(client: Client): + """Streaming activity publishes raw LlmResponse chunks to the topic.""" + LLMRegistry.register(StreamingTestModel) + + new_config = client.config() + new_config["plugins"] = [GoogleAdkPlugin()] + client = Client(**new_config) + + workflow_id = f"adk-streaming-test-{uuid.uuid4()}" + + async with Worker( + client, + task_queue="adk-streaming-test", + workflows=[StreamingAdkWorkflow], + max_cached_workflows=0, + ): + handle = await client.start_workflow( + StreamingAdkWorkflow.run, + "Hello", + id=workflow_id, + task_queue="adk-streaming-test", + execution_timeout=timedelta(seconds=30), + ) + + stream = WorkflowStreamClient.create(client, workflow_id) + responses: list[LlmResponse] = [] + + async def collect_events() -> None: + async for item in stream.subscribe( + ["events"], + from_offset=0, + result_type=LlmResponse, + poll_cooldown=timedelta(milliseconds=50), + ): + responses.append(item.data) + if len(responses) >= 2: + break + + collect_task = asyncio.create_task(collect_events()) + result = await handle.result() + await asyncio.wait_for(collect_task, timeout=10.0) + + # Workflow assembles streamed parts; the last part it observes is "world!". + assert result == "world!" + + texts: list[str] = [] + for r in responses: + if r.content and r.content.parts: + for part in r.content.parts: + if part.text: + texts.append(part.text) + assert texts == ["Hello ", "world!"], f"Unexpected text deltas: {texts}" + + +@workflow.defn +class StreamingAdkRequiresTopicWorkflow: + """Calls ``generate_content_async(stream=True)`` without configuring + ``streaming_topic``; the call must raise before any activity + is scheduled.""" + + @workflow.run + async def run(self, prompt: str) -> str: + model = TemporalModel("streaming_test_model") + agent = Agent( + name="test_agent", + model=model, + instruction="You are a test agent.", + ) + runner = InMemoryRunner(agent=agent, app_name="test-app") + session = await runner.session_service.create_session( + app_name="test-app", user_id="test" + ) + async for _ in runner.run_async( + user_id="test", + session_id=session.id, + new_message=Content(role="user", parts=[Part(text=prompt)]), + run_config=RunConfig(streaming_mode=StreamingMode.SSE), + ): + pass + return "should not reach" + + +@pytest.mark.asyncio +async def test_streaming_requires_topic(client: Client): + """``stream=True`` fails fast when no streaming topic was configured + on ``TemporalModel``. The error is raised in the workflow before any + streaming activity is scheduled.""" + LLMRegistry.register(StreamingTestModel) + + new_config = client.config() + new_config["plugins"] = [GoogleAdkPlugin()] + client = Client(**new_config) + + async with Worker( + client, + task_queue="adk-streaming-requires-topic", + workflows=[StreamingAdkRequiresTopicWorkflow], + max_cached_workflows=0, + ): + with pytest.raises(WorkflowFailureError) as exc_info: + await client.execute_workflow( + StreamingAdkRequiresTopicWorkflow.run, + "Hi", + id=f"adk-streaming-requires-topic-{uuid.uuid4()}", + task_queue="adk-streaming-requires-topic", + execution_timeout=timedelta(seconds=30), + ) + + assert "streaming_topic" in str(exc_info.value.cause) From 6ac702a4eeaae66f4335d53e004151b1ac990c2d Mon Sep 17 00:00:00 2001 From: Brian Strauch Date: Fri, 8 May 2026 13:15:54 -0700 Subject: [PATCH 079/226] Fix CI, bump openinference-instrumentation-google-adk to 0.1.11 (#1508) * Cap google-adk<1.32 in dev deps for openinference compat * Bump openinference-instrumentation-google-adk to 0.1.11 for google-adk 1.32 compat --- pyproject.toml | 4 ++-- uv.lock | 11 ++++++----- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index d85badb64..e75dd365b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -75,7 +75,7 @@ dev = [ "openai-agents>=0.14.0; python_version >= '3.14'", "openai-agents[litellm]>=0.14.0; python_version < '3.14'", "litellm>=1.83.0", - "openinference-instrumentation-google-adk>=0.1.8", + "openinference-instrumentation-google-adk>=0.1.11", "googleapis-common-protos==1.70.0", "pytest-rerunfailures>=16.1", "pytest-xdist>=3.6,<4", @@ -256,4 +256,4 @@ exclude = ["temporalio/bridge/target/**/*"] # Prevent uv commands from building the package by default package = false exclude-newer = "1 week" -exclude-newer-package = { openai-agents = false } +exclude-newer-package = { openai-agents = false, openinference-instrumentation-google-adk = false } diff --git a/uv.lock b/uv.lock index c78ab196c..6712dd259 100644 --- a/uv.lock +++ b/uv.lock @@ -9,11 +9,12 @@ resolution-markers = [ ] [options] -exclude-newer = "2026-04-23T17:46:27.746666Z" +exclude-newer = "2026-05-01T17:48:32.303305Z" exclude-newer-span = "P1W" [options.exclude-newer-package] openai-agents = false +openinference-instrumentation-google-adk = false [[package]] name = "aioboto3" @@ -3452,7 +3453,7 @@ wheels = [ [[package]] name = "openinference-instrumentation-google-adk" -version = "0.1.10" +version = "0.1.11" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "openinference-instrumentation" }, @@ -3463,9 +3464,9 @@ dependencies = [ { name = "typing-extensions" }, { name = "wrapt" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/25/7a/bba3337066dcd391f7091d840c6d22e351a9f8412bb8de4b901cc6443aa9/openinference_instrumentation_google_adk-0.1.10.tar.gz", hash = "sha256:5ccb61d58532b2d829b71b411a997b573ddc2b03dcd5481fb2f9f67ec7368a97", size = 12383, upload-time = "2026-03-03T08:07:34.296Z" } +sdist = { url = "https://files.pythonhosted.org/packages/79/7e/a6a6c7dc7bd01e098374cdee69b10b6586d2f7a481ed34f8a283fcbfd830/openinference_instrumentation_google_adk-0.1.11.tar.gz", hash = "sha256:b36310d4e8b8143d41fe5c74be04c09f367710ec8019471f232bb721ede143b1", size = 14473, upload-time = "2026-05-05T06:43:34.828Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/3a/82/8ee4f5f40d2353ac643668c4f6a98e0ce51a76afeab1cfba2dab1976d7c4/openinference_instrumentation_google_adk-0.1.10-py3-none-any.whl", hash = "sha256:d97be628ce60b8eeab017f34ffaa2ec6fdaa11c64f3d0a032706ef74659e2a3e", size = 14201, upload-time = "2026-03-03T08:07:33.406Z" }, + { url = "https://files.pythonhosted.org/packages/c7/51/0d4df97fd0fb3ac2282dc268e9a11f82523f881e623264291d6abf2fd5ed/openinference_instrumentation_google_adk-0.1.11-py3-none-any.whl", hash = "sha256:8dd546f9db3a6589106287b8a99b99f06361ac95e6e0b32305e6ce1a76f98630", size = 16384, upload-time = "2026-05-05T06:43:33.836Z" }, ] [[package]] @@ -5275,7 +5276,7 @@ dev = [ { name = "mypy-protobuf", specifier = ">=3.3.0,<4" }, { name = "openai-agents", marker = "python_full_version >= '3.14'", specifier = ">=0.14.0" }, { name = "openai-agents", extras = ["litellm"], marker = "python_full_version < '3.14'", specifier = ">=0.14.0" }, - { name = "openinference-instrumentation-google-adk", specifier = ">=0.1.8" }, + { name = "openinference-instrumentation-google-adk", specifier = ">=0.1.11" }, { name = "openinference-instrumentation-openai-agents", specifier = ">=0.1.0" }, { name = "opentelemetry-exporter-otlp-proto-grpc", specifier = ">=1.11.1,<2" }, { name = "opentelemetry-sdk-extension-aws", specifier = ">=2.0.0,<3" }, From 5bff3b038dc6b8673ae0e5890808cf03f8ab5a20 Mon Sep 17 00:00:00 2001 From: xumaple <45406854+xumaple@users.noreply.github.com> Date: Mon, 11 May 2026 13:06:11 -0400 Subject: [PATCH 080/226] AI-183: Respect LANGSMITH_TRACING env var in LangSmith plugin (#1509) * AI-183: Respect LANGSMITH_TRACING env var in LangSmith plugin LangSmithInterceptor previously hard-coded `enabled=True` in every `tracing_context(...)` call (4 sites: workflow, activity, nexus start, nexus cancel) and `_maybe_run` gated only on `add_temporal_runs`. This meant `LANGSMITH_TRACING=false` was a no-op when the plugin was installed. Defer to langsmith's native polarity: drop `enabled` from all four `tracing_context(...)` calls so langsmith's own `tracing_is_enabled()` resolution takes over, and short-circuit `_maybe_run` on `tracing_is_enabled()` in addition to the existing `add_temporal_runs` gate. Behavior change: the plugin is no longer "on by default" once installed. Users must now explicitly opt in via `LANGSMITH_TRACING=true`, matching langsmith's standard mechanism. Cross-process: `tracing_is_enabled()` checks for an active parent run tree before consulting env vars, so an inbound parent trace propagated via headers will continue locally even when `LANGSMITH_TRACING=false` (documented in `_maybe_run`'s docstring). Adds 5 tests in tests/contrib/langsmith/test_tracing_env_override.py covering both `add_temporal_runs` modes, the legacy `LANGCHAIN_TRACING_V2` env var, the Nexus start path, and a positive control. Adds two autouse fixtures in tests/contrib/langsmith/conftest.py: one to clear langsmith's env-var lru_cache between tests, and one to set `LANGSMITH_TRACING=true` by default for the suite (preserving the prior "tracing on" assumption that the existing 87 tests rely on; individual tests override). Co-Authored-By: Claude Opus 4.7 (1M context) * AI-183: Move cross-process Note out of _maybe_run bullet list The Note paragraph was sandwiched between two bullets, breaking RST definition list parsing. Pydoctor reported "Definition list ends without a blank line; unexpected unindent." Move the Note after all bullets, as a standalone paragraph before ``Args:``. No content change. Co-Authored-By: Claude Opus 4.7 (1M context) --------- Co-authored-by: Claude Opus 4.7 (1M context) --- temporalio/contrib/langsmith/_interceptor.py | 23 +- tests/contrib/langsmith/conftest.py | 31 +++ tests/contrib/langsmith/test_interceptor.py | 5 +- .../langsmith/test_tracing_env_override.py | 243 ++++++++++++++++++ 4 files changed, 290 insertions(+), 12 deletions(-) create mode 100644 tests/contrib/langsmith/test_tracing_env_override.py diff --git a/temporalio/contrib/langsmith/_interceptor.py b/temporalio/contrib/langsmith/_interceptor.py index 6789ddea4..b3dd78574 100644 --- a/temporalio/contrib/langsmith/_interceptor.py +++ b/temporalio/contrib/langsmith/_interceptor.py @@ -12,6 +12,7 @@ from typing import Any, ClassVar, NoReturn, Protocol import langsmith +import langsmith.utils import nexusrpc.handler from langsmith import tracing_context from langsmith.run_helpers import get_current_run_tree @@ -43,6 +44,7 @@ } ) + # --------------------------------------------------------------------------- # Context helpers # --------------------------------------------------------------------------- @@ -457,7 +459,8 @@ def _maybe_run( ) -> Iterator[None]: """Create a LangSmith run, handling errors. - - If add_temporal_runs is False, yields None (no run created). + - If add_temporal_runs is False **or** ``langsmith.utils.tracing_is_enabled()`` + returns False, yields None (no run created). Context propagation is handled unconditionally by callers. - When a run IS created, uses :class:`_ReplaySafeRunTree` for replay and event loop safety, then sets it as ambient context via @@ -465,6 +468,15 @@ def _maybe_run( returns it and ``_inject_current_context()`` can inject it. - On exception: marks run as errored (unless benign ApplicationError), re-raises. + Note on ``tracing_is_enabled()`` and cross-process traces: + ``tracing_is_enabled()`` checks for an active run tree in context + *before* consulting the ``LANGSMITH_TRACING`` env var (langsmith + semantics). If a parent run is propagated into this worker via + headers from an upstream tracer, tracing continues regardless of + ``LANGSMITH_TRACING=false``. This matches langsmith's "continue + mid-trace" model: the env var suppresses *new* local traces but + does not break an inbound parent trace. + Args: client: LangSmith client instance. name: Display name for the run. @@ -477,7 +489,7 @@ def _maybe_run( project_name: LangSmith project name override. executor: ThreadPoolExecutor for background I/O. """ - if not add_temporal_runs: + if not add_temporal_runs or not langsmith.utils.tracing_is_enabled(): yield None return @@ -717,12 +729,8 @@ async def execute_activity( "temporalRunID": info.workflow_run_id or "", "temporalActivityID": info.activity_id or "", } - # Unconditionally set tracing context so @traceable functions inside - # activities inherit the plugin's client and parent, regardless of - # the add_temporal_runs toggle. tracing_args: dict[str, Any] = { "client": self._config._client, - "enabled": True, "project_name": self._config._project_name, "parent": parent, } @@ -786,7 +794,6 @@ def _workflow_maybe_run( ) tracing_args: dict[str, Any] = { "client": self._config._client, - "enabled": True, "project_name": self._config._project_name, "parent": tracing_parent, } @@ -947,7 +954,6 @@ async def execute_nexus_operation_start( ) tracing_args: dict[str, Any] = { "client": self._config._client, - "enabled": True, "project_name": self._config._project_name, "parent": parent, } @@ -967,7 +973,6 @@ async def execute_nexus_operation_cancel( ) tracing_args: dict[str, Any] = { "client": self._config._client, - "enabled": True, "project_name": self._config._project_name, "parent": parent, } diff --git a/tests/contrib/langsmith/conftest.py b/tests/contrib/langsmith/conftest.py index 9022477f4..1d90bae5e 100644 --- a/tests/contrib/langsmith/conftest.py +++ b/tests/contrib/langsmith/conftest.py @@ -6,6 +6,37 @@ from typing import Any from unittest.mock import MagicMock +import pytest + + +@pytest.fixture(autouse=True) +def _clear_langsmith_env_cache() -> Any: # pyright: ignore[reportUnusedFunction] + """Clear langsmith's lru_cache before and after each test. + + Tests manipulate LANGSMITH_TRACING / LANGCHAIN_TRACING_V2 env vars. + langsmith.utils.get_env_var caches results, so stale values would + leak across tests (or into other test modules in the same session). + """ + import langsmith.utils + + langsmith.utils.get_env_var.cache_clear() # type: ignore[attr-defined] + yield + langsmith.utils.get_env_var.cache_clear() # type: ignore[attr-defined] + + +@pytest.fixture(autouse=True) +def _enable_langsmith_tracing(monkeypatch: pytest.MonkeyPatch) -> None: # pyright: ignore[reportUnusedFunction] + """Enable LangSmith tracing by default for all tests in this directory. + + The plugin defers to ``langsmith.utils.tracing_is_enabled()``, which + requires ``LANGSMITH_TRACING=true`` (or equivalent). Without this + fixture, tests that expect runs would see zero. + + Individual tests can override with ``monkeypatch.setenv("LANGSMITH_TRACING", "false")`` + to verify disabled behavior. + """ + monkeypatch.setenv("LANGSMITH_TRACING", "true") + @dataclass class _RunRecord: diff --git a/tests/contrib/langsmith/test_interceptor.py b/tests/contrib/langsmith/test_interceptor.py index 96fdc1170..45d86bc5f 100644 --- a/tests/contrib/langsmith/test_interceptor.py +++ b/tests/contrib/langsmith/test_interceptor.py @@ -1111,7 +1111,6 @@ async def test_false_still_propagates_context( # (unconditionally, before _maybe_run) mock_tracing_ctx.assert_called_once_with( client=config._client, - enabled=True, project_name=None, parent=mock_extracted_parent, ) @@ -1143,8 +1142,8 @@ async def test_false_activity_no_parent_no_context( await act_interceptor.execute_activity(mock_act_input) MockRunTree.assert_not_called() - # tracing_context called with client and enabled (no parent) + # tracing_context called with client (no parent) mock_tracing_ctx.assert_called_once_with( - client=config._client, enabled=True, project_name=None, parent=None + client=config._client, project_name=None, parent=None ) mock_act_next.execute_activity.assert_called_once() diff --git a/tests/contrib/langsmith/test_tracing_env_override.py b/tests/contrib/langsmith/test_tracing_env_override.py new file mode 100644 index 000000000..543d1897c --- /dev/null +++ b/tests/contrib/langsmith/test_tracing_env_override.py @@ -0,0 +1,243 @@ +"""Tests that LangSmithPlugin defers to ``langsmith.utils.tracing_is_enabled()``. + +Tracing requires the env to explicitly say so (``LANGSMITH_TRACING=true`` etc); +it is off when the env is unset or set to ``false``. Tests verify that +``LANGSMITH_TRACING=false`` produces zero runs and ``LANGSMITH_TRACING=true`` +produces runs. +""" + +from __future__ import annotations + +import uuid +from datetime import timedelta + +import pytest +from langsmith import traceable + +from temporalio import activity, workflow +from temporalio.client import Client +from temporalio.testing import WorkflowEnvironment +from tests.contrib.langsmith.test_integration import ( + DirectTraceableNexusService, + NexusDirectTraceableWorkflow, + _make_client_and_collector, +) +from tests.helpers import new_worker +from tests.helpers.nexus import make_nexus_endpoint_name + +# --------------------------------------------------------------------------- +# Sample workflow / activity +# --------------------------------------------------------------------------- + + +@traceable(name="inner_call") +async def _inner_call(prompt: str) -> str: + return f"response to: {prompt}" + + +@traceable +@activity.defn +async def env_override_activity() -> str: + result = await _inner_call("hello") + return result + + +@workflow.defn +class EnvOverrideWorkflow: + @workflow.run + async def run(self) -> str: + return await workflow.execute_activity( + env_override_activity, + start_to_close_timeout=timedelta(seconds=10), + ) + + +# --------------------------------------------------------------------------- +# Tests +# --------------------------------------------------------------------------- + + +class TestTracingEnvOverride: + """LangSmithPlugin must respect LANGSMITH_TRACING=false.""" + + async def test_no_runs_when_tracing_disabled_with_temporal_runs( + self, + client: Client, + env: WorkflowEnvironment, # type:ignore[reportUnusedParameter] + monkeypatch: pytest.MonkeyPatch, + ) -> None: + """With LANGSMITH_TRACING=false and add_temporal_runs=True, no runs.""" + monkeypatch.setenv("LANGSMITH_TRACING", "false") + monkeypatch.delenv("LANGCHAIN_TRACING_V2", raising=False) + + temporal_client, collector, _ = _make_client_and_collector( + client, add_temporal_runs=True + ) + + async with new_worker( + temporal_client, + EnvOverrideWorkflow, + activities=[env_override_activity], + max_cached_workflows=0, + ) as worker: + handle = await temporal_client.start_workflow( + EnvOverrideWorkflow.run, + id=f"env-override-temporal-{uuid.uuid4()}", + task_queue=worker.task_queue, + ) + result = await handle.result() + + assert result == "response to: hello" + assert len(collector.runs) == 0, ( + f"Expected zero LangSmith runs when LANGSMITH_TRACING=false, " + f"but got {len(collector.runs)}: " + f"{[r.name for r in collector.runs]}" + ) + + async def test_no_runs_when_tracing_disabled_without_temporal_runs( + self, + client: Client, + env: WorkflowEnvironment, # type:ignore[reportUnusedParameter] + monkeypatch: pytest.MonkeyPatch, + ) -> None: + """With LANGSMITH_TRACING=false and add_temporal_runs=False, no runs.""" + monkeypatch.setenv("LANGSMITH_TRACING", "false") + monkeypatch.delenv("LANGCHAIN_TRACING_V2", raising=False) + + temporal_client, collector, _ = _make_client_and_collector( + client, add_temporal_runs=False + ) + + async with new_worker( + temporal_client, + EnvOverrideWorkflow, + activities=[env_override_activity], + max_cached_workflows=0, + ) as worker: + handle = await temporal_client.start_workflow( + EnvOverrideWorkflow.run, + id=f"env-override-no-temporal-{uuid.uuid4()}", + task_queue=worker.task_queue, + ) + result = await handle.result() + + assert result == "response to: hello" + assert len(collector.runs) == 0, ( + f"Expected zero LangSmith runs when LANGSMITH_TRACING=false, " + f"but got {len(collector.runs)}: " + f"{[r.name for r in collector.runs]}" + ) + + async def test_no_runs_when_langchain_tracing_v2_disabled( + self, + client: Client, + env: WorkflowEnvironment, # type:ignore[reportUnusedParameter] + monkeypatch: pytest.MonkeyPatch, + ) -> None: + """LANGCHAIN_TRACING_V2=false also suppresses runs (legacy env var).""" + monkeypatch.setenv("LANGCHAIN_TRACING_V2", "false") + monkeypatch.delenv("LANGSMITH_TRACING", raising=False) + + temporal_client, collector, _ = _make_client_and_collector( + client, add_temporal_runs=True + ) + + async with new_worker( + temporal_client, + EnvOverrideWorkflow, + activities=[env_override_activity], + max_cached_workflows=0, + ) as worker: + handle = await temporal_client.start_workflow( + EnvOverrideWorkflow.run, + id=f"env-override-v2-{uuid.uuid4()}", + task_queue=worker.task_queue, + ) + result = await handle.result() + + assert result == "response to: hello" + assert len(collector.runs) == 0, ( + f"Expected zero LangSmith runs when LANGCHAIN_TRACING_V2=false, " + f"but got {len(collector.runs)}: " + f"{[r.name for r in collector.runs]}" + ) + + async def test_no_runs_when_tracing_disabled_for_nexus_start( + self, + client: Client, + env: WorkflowEnvironment, + monkeypatch: pytest.MonkeyPatch, + ) -> None: + """With LANGSMITH_TRACING=false, nexus start handler emits no runs.""" + if env.supports_time_skipping: + pytest.skip("Time-skipping server doesn't persist headers.") + + monkeypatch.setenv("LANGSMITH_TRACING", "false") + monkeypatch.delenv("LANGCHAIN_TRACING_V2", raising=False) + + temporal_client, collector, _ = _make_client_and_collector( + client, add_temporal_runs=True + ) + + task_queue = f"env-override-nexus-{uuid.uuid4()}" + async with new_worker( + temporal_client, + NexusDirectTraceableWorkflow, + nexus_service_handlers=[DirectTraceableNexusService()], + task_queue=task_queue, + max_cached_workflows=0, + ) as worker: + await env.create_nexus_endpoint( + make_nexus_endpoint_name(worker.task_queue), + worker.task_queue, + ) + handle = await temporal_client.start_workflow( + NexusDirectTraceableWorkflow.run, + id=f"env-override-nexus-{uuid.uuid4()}", + task_queue=worker.task_queue, + ) + result = await handle.result() + + assert result == "response to: nexus-input" + assert len(collector.runs) == 0, ( + f"Expected zero LangSmith runs when LANGSMITH_TRACING=false " + f"(nexus start path), but got {len(collector.runs)}: " + f"{[r.name for r in collector.runs]}" + ) + + # NOTE: test_no_runs_when_tracing_disabled_for_nexus_cancel is not + # included — cancelling an in-flight nexus operation requires non-trivial + # orchestration (long-running handler + external cancel signal). Flagged + # for a follow-up ticket. + + async def test_runs_emitted_when_tracing_enabled( + self, + client: Client, + env: WorkflowEnvironment, # type:ignore[reportUnusedParameter] + monkeypatch: pytest.MonkeyPatch, + ) -> None: + """Positive control: with LANGSMITH_TRACING=true, runs ARE emitted.""" + monkeypatch.setenv("LANGSMITH_TRACING", "true") + monkeypatch.delenv("LANGCHAIN_TRACING_V2", raising=False) + + temporal_client, collector, _ = _make_client_and_collector( + client, add_temporal_runs=True + ) + + async with new_worker( + temporal_client, + EnvOverrideWorkflow, + activities=[env_override_activity], + max_cached_workflows=0, + ) as worker: + handle = await temporal_client.start_workflow( + EnvOverrideWorkflow.run, + id=f"env-enabled-{uuid.uuid4()}", + task_queue=worker.task_queue, + ) + result = await handle.result() + + assert result == "response to: hello" + assert ( + len(collector.runs) > 0 + ), "Expected LangSmith runs when LANGSMITH_TRACING=true, but got none" From 7bf5434a4e04add1a6d450be1eedaf9f6972807f Mon Sep 17 00:00:00 2001 From: tconley1428 Date: Tue, 12 May 2026 09:04:21 -0700 Subject: [PATCH 081/226] Fix minor API break from latest OpenAI Agents version (#1511) * Fix minor API break from latest OpenAI Agents version * Fix model to gpt-4o in chat completions --- pyproject.toml | 2 +- .../contrib/openai_agents/_temporal_trace_provider.py | 4 ++-- tests/contrib/openai_agents/test_openai.py | 1 + uv.lock | 10 +++++----- 4 files changed, 9 insertions(+), 8 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index e75dd365b..94cbd9327 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -28,7 +28,7 @@ classifiers = [ grpc = ["grpcio>=1.48.2,<2"] opentelemetry = ["opentelemetry-api>=1.11.1,<2", "opentelemetry-sdk>=1.11.1,<2"] pydantic = ["pydantic>=2.0.0,<3"] -openai-agents = ["openai-agents>=0.14.0", "mcp>=1.9.4, <2"] +openai-agents = ["openai-agents>=0.17.1", "mcp>=1.9.4, <2"] google-adk = ["google-adk>=1.27.0,<2"] langgraph = ["langgraph>=1.1.0"] langsmith = ["langsmith>=0.7.0,<0.8"] diff --git a/temporalio/contrib/openai_agents/_temporal_trace_provider.py b/temporalio/contrib/openai_agents/_temporal_trace_provider.py index 4590b52f4..347473545 100644 --- a/temporalio/contrib/openai_agents/_temporal_trace_provider.py +++ b/temporalio/contrib/openai_agents/_temporal_trace_provider.py @@ -124,8 +124,8 @@ def on_span_end(self, span: Span[Any]) -> None: self._impl.on_span_end(span) - def shutdown(self) -> None: - self._impl.shutdown() + def shutdown(self, timeout: float | None = None) -> None: + self._impl.shutdown(timeout) def force_flush(self) -> None: self._impl.force_flush() diff --git a/tests/contrib/openai_agents/test_openai.py b/tests/contrib/openai_agents/test_openai.py index 8824aac77..294acc1d0 100644 --- a/tests/contrib/openai_agents/test_openai.py +++ b/tests/contrib/openai_agents/test_openai.py @@ -1359,6 +1359,7 @@ async def run(self) -> None: agent: Agent = Agent( name="Assistant", instructions="You are a helpful assistant.", + model="gpt-4o", tools=[function_tool(self.run_tool)], ) await Runner.run( diff --git a/uv.lock b/uv.lock index 6712dd259..7bdd0bd79 100644 --- a/uv.lock +++ b/uv.lock @@ -9,7 +9,7 @@ resolution-markers = [ ] [options] -exclude-newer = "2026-05-01T17:48:32.303305Z" +exclude-newer = "2026-05-04T16:34:12.029346Z" exclude-newer-span = "P1W" [options.exclude-newer-package] @@ -3380,7 +3380,7 @@ wheels = [ [[package]] name = "openai-agents" -version = "0.14.8" +version = "0.17.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "griffelib" }, @@ -3392,9 +3392,9 @@ dependencies = [ { name = "typing-extensions" }, { name = "websockets" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/d5/8a/d36ab647f05e790ec97dda9e4c0eb39d8840269d6a5194887b5dec92bd0d/openai_agents-0.14.8.tar.gz", hash = "sha256:fe1cb58b4150a07292a94f15d8fd5217ee9195bd6bcd8a6a46fdb1d9b08a70b7", size = 5314520, upload-time = "2026-04-29T03:40:07.6Z" } +sdist = { url = "https://files.pythonhosted.org/packages/04/c9/a0a5a5fad76710f0c77fd104f868bdf0360e0e58bc37a89238c6c6410a92/openai_agents-0.17.1.tar.gz", hash = "sha256:6d5e77956a2804ff6f230d57bcc2bc315364a796f7aced0ecfa43440686c096c", size = 5400291, upload-time = "2026-05-11T06:57:01.385Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/af/6e/1e9adcedcde7b163579b88a68f765a4915be4ead0713270386d9432cfd2f/openai_agents-0.14.8-py3-none-any.whl", hash = "sha256:2937ef582ccaa45d59e89839ed8948cb2a6d808bc9940f0881793c21f37f7776", size = 817332, upload-time = "2026-04-29T03:40:05.68Z" }, + { url = "https://files.pythonhosted.org/packages/c3/0c/13c87bcf2510a761767094bc103818d1d676f24ad2f48406c9e74c82fd76/openai_agents-0.17.1-py3-none-any.whl", hash = "sha256:41598c98969d972d46a5028b9a79ca62a563a2b85ebb829ccc48b5daa2e34960", size = 837555, upload-time = "2026-05-11T06:56:59.247Z" }, ] [package.optional-dependencies] @@ -5242,7 +5242,7 @@ requires-dist = [ { name = "langsmith", marker = "extra == 'langsmith'", specifier = ">=0.7.0,<0.8" }, { name = "mcp", marker = "extra == 'openai-agents'", specifier = ">=1.9.4,<2" }, { name = "nexus-rpc", specifier = "==1.4.0" }, - { name = "openai-agents", marker = "extra == 'openai-agents'", specifier = ">=0.14.0" }, + { name = "openai-agents", marker = "extra == 'openai-agents'", specifier = ">=0.17.1" }, { name = "opentelemetry-api", marker = "extra == 'lambda-worker-otel'", specifier = ">=1.11.1,<2" }, { name = "opentelemetry-api", marker = "extra == 'opentelemetry'", specifier = ">=1.11.1,<2" }, { name = "opentelemetry-exporter-otlp-proto-grpc", marker = "extra == 'lambda-worker-otel'", specifier = ">=1.11.1,<2" }, From f721b8adf5be5e48710ff2523df8553f2fb4e5dc Mon Sep 17 00:00:00 2001 From: Spencer Judge Date: Tue, 12 May 2026 11:01:43 -0700 Subject: [PATCH 082/226] Plumb through option for configuring DNS resolver (#1501) --- temporalio/bridge/client.py | 10 ++++++++++ temporalio/bridge/src/client.rs | 30 ++++++++++++++++++++++++----- temporalio/client.py | 16 ++++++++++++++++ temporalio/service.py | 34 +++++++++++++++++++++++++++++++++ tests/test_service.py | 23 ++++++++++++++++++++++ 5 files changed, 108 insertions(+), 5 deletions(-) diff --git a/temporalio/bridge/client.py b/temporalio/bridge/client.py index 564005ef0..9941010de 100644 --- a/temporalio/bridge/client.py +++ b/temporalio/bridge/client.py @@ -57,6 +57,15 @@ class ClientHttpConnectProxyConfig: basic_auth: tuple[str, str] | None +@dataclass +class ClientDnsLoadBalancingConfig: + """Python representation of the Rust struct for configuring DNS load + balancing. + """ + + resolution_interval_millis: int + + @dataclass class ClientConfig: """Python representation of the Rust struct for configuring the client.""" @@ -71,6 +80,7 @@ class ClientConfig: client_name: str client_version: str http_connect_proxy_config: ClientHttpConnectProxyConfig | None + dns_load_balancing_config: ClientDnsLoadBalancingConfig | None @dataclass diff --git a/temporalio/bridge/src/client.rs b/temporalio/bridge/src/client.rs index cc00bcfe0..8da620a74 100644 --- a/temporalio/bridge/src/client.rs +++ b/temporalio/bridge/src/client.rs @@ -11,6 +11,7 @@ use temporalio_client::{ ClientKeepAliveOptions as CoreClientKeepAliveConfig, Connection, ConnectionOptions, DnsLoadBalancingOptions, HttpConnectProxyOptions, RetryOptions, }; +use tracing::warn; use url::Url; use crate::runtime; @@ -35,6 +36,7 @@ pub struct ClientConfig { retry_config: Option, keep_alive_config: Option, http_connect_proxy_config: Option, + dns_load_balancing_config: Option, } #[derive(FromPyObject)] @@ -67,6 +69,11 @@ struct ClientHttpConnectProxyConfig { pub basic_auth: Option<(String, String)>, } +#[derive(FromPyObject)] +struct ClientDnsLoadBalancingConfig { + pub resolution_interval_millis: u64, +} + #[derive(FromPyObject)] pub(crate) struct RpcCall { pub(crate) rpc: String, @@ -236,6 +243,15 @@ impl ClientConfig { ) -> PyResult { let (ascii_headers, binary_headers) = partition_headers(self.metadata); let has_proxy = self.http_connect_proxy_config.is_some(); + // Core rejects DNS load balancing alongside an HTTP CONNECT proxy, so + // suppress DNS LB whenever a proxy is configured to keep the + // pre-existing behavior even if a caller leaves the default. + let dns_load_balancing = if has_proxy { + warn!("Disabling DNS load balancing because http_connect_proxy_config is set"); + None + } else { + self.dns_load_balancing_config.map(Into::into) + }; let conn_opts = ConnectionOptions::new( Url::parse(&self.target_url) .map_err(|err| PyValueError::new_err(format!("invalid target URL: {err}")))?, @@ -249,11 +265,7 @@ impl ClientConfig { ) .keep_alive(self.keep_alive_config.map(Into::into)) .maybe_http_connect_proxy(self.http_connect_proxy_config.map(Into::into)) - .dns_load_balancing(if has_proxy { - None - } else { - Some(DnsLoadBalancingOptions::default()) - }) + .dns_load_balancing(dns_load_balancing) .headers(ascii_headers) .binary_headers(binary_headers) .maybe_api_key(self.api_key) @@ -322,3 +334,11 @@ impl From for HttpConnectProxyOptions { } } } + +impl From for DnsLoadBalancingOptions { + fn from(conf: ClientDnsLoadBalancingConfig) -> Self { + let mut opts = DnsLoadBalancingOptions::default(); + opts.resolution_interval = Duration::from_millis(conf.resolution_interval_millis); + opts + } +} diff --git a/temporalio/client.py b/temporalio/client.py index 1ae8de106..7b7d99ab2 100644 --- a/temporalio/client.py +++ b/temporalio/client.py @@ -74,6 +74,7 @@ ) from temporalio.service import ( ConnectConfig, + DnsLoadBalancingConfig, HttpConnectProxyConfig, KeepAliveConfig, RetryConfig, @@ -139,6 +140,8 @@ async def connect( lazy: bool = False, runtime: temporalio.runtime.Runtime | None = None, http_connect_proxy_config: HttpConnectProxyConfig | None = None, + dns_load_balancing_config: DnsLoadBalancingConfig + | None = DnsLoadBalancingConfig.default, header_codec_behavior: HeaderCodecBehavior = HeaderCodecBehavior.NO_CODEC, ) -> Self: """Connect to a Temporal server. @@ -194,6 +197,11 @@ async def connect( used for workers. runtime: The runtime for this client, or the default if unset. http_connect_proxy_config: Configuration for HTTP CONNECT proxy. + dns_load_balancing_config: DNS load balancing configuration for the + client connection. Default is to re-resolve DNS every 30s. Can + be set to ``None`` to disable. Silently disabled when + ``http_connect_proxy_config`` is set, since the two are mutually + exclusive. header_codec_behavior: Encoding behavior for headers sent by the client. """ connect_config = temporalio.service.ConnectConfig( @@ -207,6 +215,7 @@ async def connect( lazy=lazy, runtime=runtime, http_connect_proxy_config=http_connect_proxy_config, + dns_load_balancing_config=dns_load_balancing_config, ) def make_lambda( @@ -2873,6 +2882,7 @@ class ClientConnectConfig(TypedDict, total=False): lazy: bool runtime: temporalio.runtime.Runtime | None http_connect_proxy_config: HttpConnectProxyConfig | None + dns_load_balancing_config: DnsLoadBalancingConfig | None header_codec_behavior: HeaderCodecBehavior @@ -9774,6 +9784,7 @@ async def connect( lazy: bool = False, runtime: temporalio.runtime.Runtime | None = None, http_connect_proxy_config: HttpConnectProxyConfig | None = None, + dns_load_balancing_config: DnsLoadBalancingConfig | None = None, ) -> CloudOperationsClient: """Connect to a Temporal Cloud Operations API. @@ -9810,6 +9821,10 @@ async def connect( used for workers. runtime: The runtime for this client, or the default if unset. http_connect_proxy_config: Configuration for HTTP CONNECT proxy. + dns_load_balancing_config: DNS load balancing configuration for the + client connection. Default is disabled. Silently disabled when + ``http_connect_proxy_config`` is set, since the two are mutually + exclusive. """ # Add version if given if version: @@ -9826,6 +9841,7 @@ async def connect( lazy=lazy, runtime=runtime, http_connect_proxy_config=http_connect_proxy_config, + dns_load_balancing_config=dns_load_balancing_config, ) return CloudOperationsClient( await temporalio.service.ServiceClient.connect(connect_config) diff --git a/temporalio/service.py b/temporalio/service.py index 14b4d1fe5..345a45fbf 100644 --- a/temporalio/service.py +++ b/temporalio/service.py @@ -132,6 +132,32 @@ def _to_bridge_config( ) +@dataclass(frozen=True) +class DnsLoadBalancingConfig: + """DNS load balancing configuration for client connections. + + When enabled, Core periodically re-resolves the target host's DNS records + and round-robins requests across the resolved addresses. Cannot be used + together with :py:class:`HttpConnectProxyConfig` -- DNS load balancing is + silently disabled when an HTTP CONNECT proxy is configured. + """ + + resolution_interval_millis: int = 30000 + """How often to re-resolve DNS, in milliseconds.""" + default: ClassVar[DnsLoadBalancingConfig] + """Default DNS load balancing config.""" + + def _to_bridge_config( + self, + ) -> temporalio.bridge.client.ClientDnsLoadBalancingConfig: + return temporalio.bridge.client.ClientDnsLoadBalancingConfig( + resolution_interval_millis=self.resolution_interval_millis, + ) + + +DnsLoadBalancingConfig.default = DnsLoadBalancingConfig() + + @dataclass class ConnectConfig: """Config for connecting to the server.""" @@ -146,6 +172,9 @@ class ConnectConfig: lazy: bool = False runtime: temporalio.runtime.Runtime | None = None http_connect_proxy_config: HttpConnectProxyConfig | None = None + dns_load_balancing_config: DnsLoadBalancingConfig | None = ( + DnsLoadBalancingConfig.default + ) def __post_init__(self) -> None: """Set extra defaults on unset properties.""" @@ -203,6 +232,11 @@ def _to_bridge_config(self) -> temporalio.bridge.client.ClientConfig: if self.http_connect_proxy_config else None ), + dns_load_balancing_config=( + self.dns_load_balancing_config._to_bridge_config() + if self.dns_load_balancing_config + else None + ), ) diff --git a/tests/test_service.py b/tests/test_service.py index 9fdcd9fc7..067f59cc5 100644 --- a/tests/test_service.py +++ b/tests/test_service.py @@ -219,6 +219,29 @@ def test_connect_config_tls_explicit_config_preserved(): assert config.tls == tls_config +def test_connect_config_dns_load_balancing_custom(): + """Custom DnsLoadBalancingConfig is forwarded to the bridge unchanged.""" + config = temporalio.service.ConnectConfig( + target_host="localhost:7233", + dns_load_balancing_config=temporalio.service.DnsLoadBalancingConfig( + resolution_interval_millis=5000, + ), + ) + bridge_config = config._to_bridge_config() + assert bridge_config.dns_load_balancing_config is not None + assert bridge_config.dns_load_balancing_config.resolution_interval_millis == 5000 + + +def test_connect_config_dns_load_balancing_disabled(): + """Setting dns_load_balancing_config=None forwards None to the bridge.""" + config = temporalio.service.ConnectConfig( + target_host="localhost:7233", + dns_load_balancing_config=None, + ) + bridge_config = config._to_bridge_config() + assert bridge_config.dns_load_balancing_config is None + + async def test_rpc_execution_not_unknown(client: Client): """ Execute each rpc method and expect a failure, but ensure the failure is not that the rpc method is unknown From ddc2b2910d9d05307a95cf7f0d7262b137228621 Mon Sep 17 00:00:00 2001 From: Thomas Hardy Date: Wed, 13 May 2026 11:43:47 -0400 Subject: [PATCH 083/226] release-1.27.1 (#1514) --- pyproject.toml | 2 +- temporalio/service.py | 2 +- uv.lock | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 94cbd9327..055236834 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "temporalio" -version = "1.27.0" +version = "1.27.1" description = "Temporal.io Python SDK" authors = [{ name = "Temporal Technologies Inc", email = "sdk@temporal.io" }] requires-python = ">=3.10" diff --git a/temporalio/service.py b/temporalio/service.py index 345a45fbf..6ee963fdb 100644 --- a/temporalio/service.py +++ b/temporalio/service.py @@ -24,7 +24,7 @@ import temporalio.runtime from temporalio.bridge.client import RPCError as BridgeRPCError -__version__ = "1.27.0" +__version__ = "1.27.1" ServiceRequest = TypeVar("ServiceRequest", bound=google.protobuf.message.Message) ServiceResponse = TypeVar("ServiceResponse", bound=google.protobuf.message.Message) diff --git a/uv.lock b/uv.lock index 7bdd0bd79..d93db4cc1 100644 --- a/uv.lock +++ b/uv.lock @@ -9,7 +9,7 @@ resolution-markers = [ ] [options] -exclude-newer = "2026-05-04T16:34:12.029346Z" +exclude-newer = "0001-01-01T00:00:00Z" # This has no effect and is included for backwards compatibility when using relative exclude-newer values. exclude-newer-span = "P1W" [options.exclude-newer-package] @@ -5148,7 +5148,7 @@ wheels = [ [[package]] name = "temporalio" -version = "1.27.0" +version = "1.27.1" source = { virtual = "." } dependencies = [ { name = "nexus-rpc" }, From e76e155f444a9a321f1806e107f845506dc867c9 Mon Sep 17 00:00:00 2001 From: Thomas Hardy Date: Wed, 13 May 2026 20:06:01 -0400 Subject: [PATCH 084/226] default dns lb config to None (#1518) --- temporalio/client.py | 3 +-- temporalio/service.py | 4 +--- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/temporalio/client.py b/temporalio/client.py index 7b7d99ab2..ff7ae4314 100644 --- a/temporalio/client.py +++ b/temporalio/client.py @@ -140,8 +140,7 @@ async def connect( lazy: bool = False, runtime: temporalio.runtime.Runtime | None = None, http_connect_proxy_config: HttpConnectProxyConfig | None = None, - dns_load_balancing_config: DnsLoadBalancingConfig - | None = DnsLoadBalancingConfig.default, + dns_load_balancing_config: DnsLoadBalancingConfig | None = None, header_codec_behavior: HeaderCodecBehavior = HeaderCodecBehavior.NO_CODEC, ) -> Self: """Connect to a Temporal server. diff --git a/temporalio/service.py b/temporalio/service.py index 6ee963fdb..f1ff8c765 100644 --- a/temporalio/service.py +++ b/temporalio/service.py @@ -172,9 +172,7 @@ class ConnectConfig: lazy: bool = False runtime: temporalio.runtime.Runtime | None = None http_connect_proxy_config: HttpConnectProxyConfig | None = None - dns_load_balancing_config: DnsLoadBalancingConfig | None = ( - DnsLoadBalancingConfig.default - ) + dns_load_balancing_config: DnsLoadBalancingConfig | None = None def __post_init__(self) -> None: """Set extra defaults on unset properties.""" From c9e28737bc994ad7b1002f3651aa443bd3303567 Mon Sep 17 00:00:00 2001 From: Thomas Hardy Date: Wed, 13 May 2026 21:48:16 -0400 Subject: [PATCH 085/226] release 1.27.2 (#1522) --- pyproject.toml | 2 +- temporalio/service.py | 2 +- uv.lock | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 055236834..f3275f850 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "temporalio" -version = "1.27.1" +version = "1.27.2" description = "Temporal.io Python SDK" authors = [{ name = "Temporal Technologies Inc", email = "sdk@temporal.io" }] requires-python = ">=3.10" diff --git a/temporalio/service.py b/temporalio/service.py index f1ff8c765..f3583c1ee 100644 --- a/temporalio/service.py +++ b/temporalio/service.py @@ -24,7 +24,7 @@ import temporalio.runtime from temporalio.bridge.client import RPCError as BridgeRPCError -__version__ = "1.27.1" +__version__ = "1.27.2" ServiceRequest = TypeVar("ServiceRequest", bound=google.protobuf.message.Message) ServiceResponse = TypeVar("ServiceResponse", bound=google.protobuf.message.Message) diff --git a/uv.lock b/uv.lock index d93db4cc1..b523c21eb 100644 --- a/uv.lock +++ b/uv.lock @@ -5148,7 +5148,7 @@ wheels = [ [[package]] name = "temporalio" -version = "1.27.1" +version = "1.27.2" source = { virtual = "." } dependencies = [ { name = "nexus-rpc" }, From 92cab10eb0533a31efdeb15fdaa71f75d5bf13aa Mon Sep 17 00:00:00 2001 From: Brian Strauch Date: Thu, 14 May 2026 15:27:09 -0700 Subject: [PATCH 086/226] Bump ruff to 0.15 and reformat (#1507) * Bump ruff to 0.15 and reformat Also bump `[tool.ruff] target-version` from py39 to py310 to match `requires-python`; the old setting caused 0.15 to reject `match` statements in the codebase. * Restrict lockfile changes to ruff only --- pyproject.toml | 4 +- scripts/gen_bridge_client.py | 2 +- scripts/gen_protos.py | 12 +- .../worker/workflow_sandbox/_importer.py | 2 +- tests/conftest.py | 18 +- .../aws/lambda_worker/test_lambda_worker.py | 12 +- tests/contrib/aws/s3driver/test_s3driver.py | 18 +- .../langgraph/test_continue_as_new_cached.py | 18 +- .../contrib/langgraph/test_e2e_functional.py | 24 +-- tests/contrib/langsmith/test_integration.py | 72 +++---- .../openai_agents/test_openai_tracing.py | 180 +++++++++--------- .../opentelemetry/test_opentelemetry.py | 30 +-- .../test_opentelemetry_plugin.py | 30 +-- .../workflow_streams/test_workflow_streams.py | 12 +- tests/nexus/test_workflow_caller.py | 24 +-- .../test_workflow_caller_error_chains.py | 12 +- tests/nexus/test_workflow_run_operation.py | 6 +- tests/test_activity.py | 6 +- tests/test_extstore.py | 6 +- tests/test_plugins.py | 26 +-- tests/test_runtime.py | 12 +- tests/test_serialization_context.py | 2 +- tests/test_service.py | 6 +- tests/test_workflow.py | 6 +- tests/worker/test_command_aware_visitor.py | 12 +- uv.lock | 44 ++--- 26 files changed, 299 insertions(+), 297 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index f3275f850..f43b10079 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -64,7 +64,7 @@ dev = [ "pytest~=9.0", "pytest-asyncio>=0.21,<0.22", "pytest-timeout~=2.2", - "ruff>=0.5.0,<0.6", + "ruff>=0.15.12,<0.16", "toml>=0.10.2,<0.11", "twine>=4.0.1,<5", "maturin>=1.8.2", @@ -239,7 +239,7 @@ exclude = [ ] [tool.ruff] -target-version = "py39" +target-version = "py310" [build-system] requires = ["maturin>=1.0,<2.0"] diff --git a/scripts/gen_bridge_client.py b/scripts/gen_bridge_client.py index 07706f1f3..f06dd29e6 100644 --- a/scripts/gen_bridge_client.py +++ b/scripts/gen_bridge_client.py @@ -42,7 +42,7 @@ def generate_python_services( ''') def service_name(s): - return f"import {sanitize_proto_name(s.full_name)[:-len(s.name)-1]}" + return f"import {sanitize_proto_name(s.full_name)[: -len(s.name) - 1]}" service_imports = [ service_name(service_descriptor) diff --git a/scripts/gen_protos.py b/scripts/gen_protos.py index 0047952dc..e2be3975b 100644 --- a/scripts/gen_protos.py +++ b/scripts/gen_protos.py @@ -153,12 +153,12 @@ def check_proto_toolchain_versions(): _, _, proto_version = line.partition("==") elif line.startswith("grpcio-tools"): _, _, grpcio_tools_version = line.partition("==") - assert proto_version.startswith( - "3." - ), f"expected 3.x protobuf, found {proto_version}" - assert grpcio_tools_version.startswith( - "1.48." - ), f"expected 1.48.x grpcio-tools, found {grpcio_tools_version}" + assert proto_version.startswith("3."), ( + f"expected 3.x protobuf, found {proto_version}" + ) + assert grpcio_tools_version.startswith("1.48."), ( + f"expected 1.48.x grpcio-tools, found {grpcio_tools_version}" + ) def generate_protos(output_dir: Path): diff --git a/temporalio/worker/workflow_sandbox/_importer.py b/temporalio/worker/workflow_sandbox/_importer.py index 010c0c082..42f0e06b2 100644 --- a/temporalio/worker/workflow_sandbox/_importer.py +++ b/temporalio/worker/workflow_sandbox/_importer.py @@ -558,7 +558,7 @@ def _calc___package__(globals: Mapping[str, object]) -> str: if package is not None: if spec is not None and package != spec.parent: warnings.warn( - "__package__ != __spec__.parent " f"({package!r} != {spec.parent!r})", + f"__package__ != __spec__.parent ({package!r} != {spec.parent!r})", DeprecationWarning, stacklevel=3, ) diff --git a/tests/conftest.py b/tests/conftest.py index 303af2e3b..48d5f0669 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -19,25 +19,25 @@ # If there is an integration test environment variable set, we must remove the # first path from the sys.path so we can import the wheel instead if os.getenv("TEMPORAL_INTEGRATION_TEST"): - assert ( - sys.path[0] == os.getcwd() - ), "Expected first sys.path to be the current working dir" + assert sys.path[0] == os.getcwd(), ( + "Expected first sys.path to be the current working dir" + ) sys.path.pop(0) # Import temporalio and confirm it is prefixed with virtual env import temporalio - assert temporalio.__file__.startswith( - sys.prefix - ), f"Expected {temporalio.__file__} to be in {sys.prefix}" + assert temporalio.__file__.startswith(sys.prefix), ( + f"Expected {temporalio.__file__} to be in {sys.prefix}" + ) # Unless specifically overridden, we expect tests to run under protobuf 4.x/5.x lib import google.protobuf protobuf_version = google.protobuf.__version__ if os.getenv("TEMPORAL_TEST_PROTO3"): - assert protobuf_version.startswith( - "3." - ), f"Expected protobuf 3.x, got {protobuf_version}" + assert protobuf_version.startswith("3."), ( + f"Expected protobuf 3.x, got {protobuf_version}" + ) else: assert ( protobuf_version.startswith("4.") diff --git a/tests/contrib/aws/lambda_worker/test_lambda_worker.py b/tests/contrib/aws/lambda_worker/test_lambda_worker.py index 178e078ac..cda1cd12f 100644 --- a/tests/contrib/aws/lambda_worker/test_lambda_worker.py +++ b/tests/contrib/aws/lambda_worker/test_lambda_worker.py @@ -247,11 +247,13 @@ def fake_create_worker(_client: Any, **kwargs: Any) -> Any: load_config=lambda: ClientConfigProfile(), getenv={"TEMPORAL_TASK_QUEUE": "test-queue"}.get, # type: ignore[arg-type] extract_lambda_ctx=lambda ctx: ( - ctx.aws_request_id, - ctx.invoked_function_arn, - ) - if hasattr(ctx, "aws_request_id") - else None, + ( + ctx.aws_request_id, + ctx.invoked_function_arn, + ) + if hasattr(ctx, "aws_request_id") + else None + ), ) diff --git a/tests/contrib/aws/s3driver/test_s3driver.py b/tests/contrib/aws/s3driver/test_s3driver.py index 64e0d53ab..19b3419f8 100644 --- a/tests/contrib/aws/s3driver/test_s3driver.py +++ b/tests/contrib/aws/s3driver/test_s3driver.py @@ -430,9 +430,9 @@ async def test_skips_upload_when_key_exists( assert counting_driver_client.put_object_count == 1 await driver.store(make_store_context(), [payload]) - assert ( - counting_driver_client.put_object_count == 1 - ), "put_object should not be called for an existing key" + assert counting_driver_client.put_object_count == 1, ( + "put_object should not be called for an existing key" + ) async def test_skips_upload_preserves_data( self, driver_client: S3StorageDriverClient @@ -812,9 +812,9 @@ async def test_store_cancels_remaining_on_failure( assert isinstance(exc_info.value.__cause__, ConnectionError) assert str(exc_info.value.__cause__) == "S3 connection lost" - assert ( - len(faulty_client.cancelled) == 2 - ), "Expected 2 remaining tasks to be cancelled" + assert len(faulty_client.cancelled) == 2, ( + "Expected 2 remaining tasks to be cancelled" + ) async def test_retrieve_cancels_remaining_on_failure( self, driver_client: S3StorageDriverClient @@ -838,9 +838,9 @@ async def test_retrieve_cancels_remaining_on_failure( assert isinstance(exc_info.value.__cause__, ConnectionError) assert str(exc_info.value.__cause__) == "S3 connection lost" - assert ( - len(faulty_client.cancelled) == 2 - ), "Expected 2 remaining tasks to be cancelled" + assert len(faulty_client.cancelled) == 2, ( + "Expected 2 remaining tasks to be cancelled" + ) # --------------------------------------------------------------------------- diff --git a/tests/contrib/langgraph/test_continue_as_new_cached.py b/tests/contrib/langgraph/test_continue_as_new_cached.py index b19620999..af41f384f 100644 --- a/tests/contrib/langgraph/test_continue_as_new_cached.py +++ b/tests/contrib/langgraph/test_continue_as_new_cached.py @@ -120,12 +120,12 @@ async def test_graph_continue_as_new_cached(client: Client): assert result == {"value": 260} # Each node should execute exactly once — phases 2 and 3 use cached results. - assert ( - _execution_counts.get("multiply", 0) == 1 - ), f"multiply executed {_execution_counts.get('multiply', 0)} times, expected 1" - assert ( - _execution_counts.get("add", 0) == 1 - ), f"add executed {_execution_counts.get('add', 0)} times, expected 1" - assert ( - _execution_counts.get("double", 0) == 1 - ), f"double executed {_execution_counts.get('double', 0)} times, expected 1" + assert _execution_counts.get("multiply", 0) == 1, ( + f"multiply executed {_execution_counts.get('multiply', 0)} times, expected 1" + ) + assert _execution_counts.get("add", 0) == 1, ( + f"add executed {_execution_counts.get('add', 0)} times, expected 1" + ) + assert _execution_counts.get("double", 0) == 1, ( + f"double executed {_execution_counts.get('double', 0)} times, expected 1" + ) diff --git a/tests/contrib/langgraph/test_e2e_functional.py b/tests/contrib/langgraph/test_e2e_functional.py index 7f4ffab88..d10efb483 100644 --- a/tests/contrib/langgraph/test_e2e_functional.py +++ b/tests/contrib/langgraph/test_e2e_functional.py @@ -219,15 +219,15 @@ async def test_continue_as_new_with_checkpoint(self, client: Client) -> None: assert result["result"] == 260 counts = get_task_execution_counts() - assert ( - counts.get("task_a", 0) == 1 - ), f"task_a executed {counts.get('task_a', 0)} times, expected 1" - assert ( - counts.get("task_b", 0) == 1 - ), f"task_b executed {counts.get('task_b', 0)} times, expected 1" - assert ( - counts.get("task_c", 0) == 1 - ), f"task_c executed {counts.get('task_c', 0)} times, expected 1" + assert counts.get("task_a", 0) == 1, ( + f"task_a executed {counts.get('task_a', 0)} times, expected 1" + ) + assert counts.get("task_b", 0) == 1, ( + f"task_b executed {counts.get('task_b', 0)} times, expected 1" + ) + assert counts.get("task_c", 0) == 1, ( + f"task_c executed {counts.get('task_c', 0)} times, expected 1" + ) class TestFunctionalAPIPartialExecution: @@ -266,9 +266,9 @@ async def test_partial_execution_five_tasks(self, client: Client) -> None: counts = get_task_execution_counts() for i in range(1, 6): - assert ( - counts.get(f"step_{i}", 0) == 1 - ), f"step_{i} executed {counts.get(f'step_{i}', 0)} times, expected 1" + assert counts.get(f"step_{i}", 0) == 1, ( + f"step_{i} executed {counts.get(f'step_{i}', 0)} times, expected 1" + ) class TestFunctionalAPIInterruptV2: diff --git a/tests/contrib/langsmith/test_integration.py b/tests/contrib/langsmith/test_integration.py index 78d48c71e..a89d1ea4a 100644 --- a/tests/contrib/langsmith/test_integration.py +++ b/tests/contrib/langsmith/test_integration.py @@ -367,27 +367,27 @@ async def test_workflow_activity_trace_hierarchy( " RunActivity:simple_activity", " simple_activity", ] - assert ( - hierarchy == expected - ), f"Hierarchy mismatch.\nExpected:\n{expected}\nActual:\n{hierarchy}" + assert hierarchy == expected, ( + f"Hierarchy mismatch.\nExpected:\n{expected}\nActual:\n{hierarchy}" + ) # Verify run_type: RunActivity is "tool", others are "chain" for run in collector.runs: if run.name == "RunActivity:simple_activity": - assert ( - run.run_type == "tool" - ), f"Expected RunActivity run_type='tool', got '{run.run_type}'" + assert run.run_type == "tool", ( + f"Expected RunActivity run_type='tool', got '{run.run_type}'" + ) else: - assert ( - run.run_type == "chain" - ), f"Expected {run.name} run_type='chain', got '{run.run_type}'" + assert run.run_type == "chain", ( + f"Expected {run.name} run_type='chain', got '{run.run_type}'" + ) # Verify successful runs have outputs == {"status": "ok"} for run in collector.runs: if ":" in run.name: # Interceptor runs use "Type:Name" format - assert run.outputs == { - "status": "ok" - }, f"Expected {run.name} outputs={{'status': 'ok'}}, got {run.outputs}" + assert run.outputs == {"status": "ok"}, ( + f"Expected {run.name} outputs={{'status': 'ok'}}, got {run.outputs}" + ) # --------------------------------------------------------------------------- @@ -475,9 +475,9 @@ async def test_activity_failure_marked( " RunActivity:failing_activity", " failing_activity", ] - assert ( - hierarchy == expected - ), f"Hierarchy mismatch.\nExpected:\n{expected}\nActual:\n{hierarchy}" + assert hierarchy == expected, ( + f"Hierarchy mismatch.\nExpected:\n{expected}\nActual:\n{hierarchy}" + ) # Verify the RunActivity run has an error activity_runs = [ r for r in collector.runs if r.name == "RunActivity:failing_activity" @@ -514,9 +514,9 @@ async def test_workflow_failure_marked( "StartWorkflow:FailingWorkflow", "RunWorkflow:FailingWorkflow", ] - assert ( - hierarchy == expected - ), f"Hierarchy mismatch.\nExpected:\n{expected}\nActual:\n{hierarchy}" + assert hierarchy == expected, ( + f"Hierarchy mismatch.\nExpected:\n{expected}\nActual:\n{hierarchy}" + ) # Verify the RunWorkflow run has an error wf_runs = [r for r in collector.runs if r.name == "RunWorkflow:FailingWorkflow"] assert len(wf_runs) == 1 @@ -555,9 +555,9 @@ async def test_benign_error_not_marked( " RunActivity:benign_failing_activity", " benign_failing_activity", ] - assert ( - hierarchy == expected - ), f"Hierarchy mismatch.\nExpected:\n{expected}\nActual:\n{hierarchy}" + assert hierarchy == expected, ( + f"Hierarchy mismatch.\nExpected:\n{expected}\nActual:\n{hierarchy}" + ) # The RunActivity run for benign error should NOT have error set activity_runs = [ r for r in collector.runs if r.name == "RunActivity:benign_failing_activity" @@ -988,15 +988,15 @@ async def test_factory_traceable_no_external_context( " outer_chain", " inner_llm_call", ] - assert ( - hierarchy == expected - ), f"Hierarchy mismatch.\nExpected:\n{expected}\nActual:\n{hierarchy}" + assert hierarchy == expected, ( + f"Hierarchy mismatch.\nExpected:\n{expected}\nActual:\n{hierarchy}" + ) # Verify no duplicate run IDs (replay safety with max_cached_workflows=0) run_ids = [r.id for r in collector.runs] - assert len(run_ids) == len( - set(run_ids) - ), f"Duplicate run IDs found (replay issue): {run_ids}" + assert len(run_ids) == len(set(run_ids)), ( + f"Duplicate run IDs found (replay issue): {run_ids}" + ) async def test_factory_passes_project_name_to_children( self, @@ -1081,15 +1081,15 @@ async def test_mixed_sync_async_traceable_with_temporal_runs( " outer_chain", " inner_llm_call", ] - assert ( - hierarchy == expected - ), f"Hierarchy mismatch.\nExpected:\n{expected}\nActual:\n{hierarchy}" + assert hierarchy == expected, ( + f"Hierarchy mismatch.\nExpected:\n{expected}\nActual:\n{hierarchy}" + ) # Verify no duplicate run IDs (replay safety with max_cached_workflows=0) run_ids = [r.id for r in collector.runs] - assert len(run_ids) == len( - set(run_ids) - ), f"Duplicate run IDs found (replay issue): {run_ids}" + assert len(run_ids) == len(set(run_ids)), ( + f"Duplicate run IDs found (replay issue): {run_ids}" + ) # --- Nexus service with direct @traceable call in handler --- @@ -1190,9 +1190,9 @@ async def test_nexus_direct_traceable_without_temporal_runs( "nexus_direct_traceable", " inner_llm_call", ] - assert ( - hierarchy == expected - ), f"Hierarchy mismatch.\nExpected:\n{expected}\nActual:\n{hierarchy}" + assert hierarchy == expected, ( + f"Hierarchy mismatch.\nExpected:\n{expected}\nActual:\n{hierarchy}" + ) # --------------------------------------------------------------------------- diff --git a/tests/contrib/openai_agents/test_openai_tracing.py b/tests/contrib/openai_agents/test_openai_tracing.py index 7613ae49e..facc3212b 100644 --- a/tests/contrib/openai_agents/test_openai_tracing.py +++ b/tests/contrib/openai_agents/test_openai_tracing.py @@ -369,20 +369,20 @@ async def ready() -> bool: assert workflow_span is not None, "Workflow span should exist" # Verify parenting: External trace should be root, workflow span should be child of external trace - assert ( - external_span.parent is None - ), "External trace should have no parent (be root)" + assert external_span.parent is None, ( + "External trace should have no parent (be root)" + ) assert workflow_span.parent is not None, "Workflow span should have a parent" assert external_span.context is not None, "External span should have context" - assert ( - workflow_span.parent.span_id == external_span.context.span_id - ), "Workflow span should be child of external trace" + assert workflow_span.parent.span_id == external_span.context.span_id, ( + "Workflow span should be child of external trace" + ) # Verify all spans have unique IDs span_ids = [span.context.span_id for span in spans if span.context] - assert len(span_ids) == len( - set(span_ids) - ), f"All spans should have unique IDs, got: {span_ids}" + assert len(span_ids) == len(set(span_ids)), ( + f"All spans should have unique IDs, got: {span_ids}" + ) async def test_external_trace_and_span_to_workflow_spans( @@ -462,27 +462,27 @@ async def ready() -> bool: assert workflow_span is not None, "Workflow span should exist" # Verify parenting: External span should be child of trace, workflow span should be child of external span - assert ( - external_trace_span.parent is None - ), "External trace should have no parent (be root)" + assert external_trace_span.parent is None, ( + "External trace should have no parent (be root)" + ) assert external_span.parent is not None, "External span should have a parent" - assert ( - external_trace_span.context is not None - ), "External trace span should have context" - assert ( - external_span.parent.span_id == external_trace_span.context.span_id - ), "External span should be child of external trace" + assert external_trace_span.context is not None, ( + "External trace span should have context" + ) + assert external_span.parent.span_id == external_trace_span.context.span_id, ( + "External span should be child of external trace" + ) assert workflow_span.parent is not None, "Workflow span should have a parent" assert external_span.context is not None, "External span should have context" - assert ( - workflow_span.parent.span_id == external_span.context.span_id - ), "Workflow span should be child of external span" + assert workflow_span.parent.span_id == external_span.context.span_id, ( + "Workflow span should be child of external span" + ) # Verify all spans have unique IDs span_ids = [span.context.span_id for span in spans if span.context] - assert len(span_ids) == len( - set(span_ids) - ), f"All spans should have unique IDs, got: {span_ids}" + assert len(span_ids) == len(set(span_ids)), ( + f"All spans should have unique IDs, got: {span_ids}" + ) async def test_workflow_only_trace_to_spans( @@ -556,16 +556,16 @@ async def ready() -> bool: assert workflow_span is not None, "Workflow span should exist" # Verify parenting: Workflow trace should be root, workflow span should be child of workflow trace - assert ( - workflow_trace_span.parent is None - ), "Workflow trace should have no parent (be root)" + assert workflow_trace_span.parent is None, ( + "Workflow trace should have no parent (be root)" + ) assert workflow_span.parent is not None, "Workflow span should have a parent" - assert ( - workflow_trace_span.context is not None - ), "Workflow trace span should have context" - assert ( - workflow_span.parent.span_id == workflow_trace_span.context.span_id - ), "Workflow span should be child of workflow trace" + assert workflow_trace_span.context is not None, ( + "Workflow trace span should have context" + ) + assert workflow_span.parent.span_id == workflow_trace_span.context.span_id, ( + "Workflow span should be child of workflow trace" + ) @workflow.defn @@ -611,14 +611,14 @@ async def test_custom_span_without_trace_context( if "Should not appear" in span.name or "Neither should this" in span.name ] - assert ( - len(custom_spans) == 0 - ), f"Expected no custom spans without trace context, but found: {[s.name for s in custom_spans]}" + assert len(custom_spans) == 0, ( + f"Expected no custom spans without trace context, but found: {[s.name for s in custom_spans]}" + ) # Should have no spans at all since no trace was started and spans should be dropped - assert ( - len(spans) == 0 - ), f"Expected no spans without trace context, but found: {[s.name for s in spans]}" + assert len(spans) == 0, ( + f"Expected no spans without trace context, but found: {[s.name for s in spans]}" + ) async def test_otel_tracing_in_runner( @@ -696,35 +696,35 @@ async def test_otel_tracing_in_runner( span_ids = {span.context.span_id for span in spans if span.context} for span in spans: if span.parent: - assert ( - span.parent.span_id in span_ids - ), f"Span '{span.name}' has invalid parent reference - parent span doesn't exist" + assert span.parent.span_id in span_ids, ( + f"Span '{span.name}' has invalid parent reference - parent span doesn't exist" + ) # Validate logical parent-child relationships match user code structure workflow_trace_spans = [span for span in spans if "Research workflow" in span.name] - assert ( - len(workflow_trace_spans) == 1 - ), f"Expected exactly one 'Research workflow' trace, got {len(workflow_trace_spans)}" + assert len(workflow_trace_spans) == 1, ( + f"Expected exactly one 'Research workflow' trace, got {len(workflow_trace_spans)}" + ) workflow_span = workflow_trace_spans[0] assert workflow_span.context is not None # Research manager should be child of workflow trace research_span = research_manager_spans[0] assert research_span.context is not None - assert ( - research_span.parent is not None - ), "Research manager span should have a parent" - assert ( - research_span.parent.span_id == workflow_span.context.span_id - ), "Expected 'Research manager' to be child of 'Research workflow' trace" + assert research_span.parent is not None, ( + "Research manager span should have a parent" + ) + assert research_span.parent.span_id == workflow_span.context.span_id, ( + "Expected 'Research manager' to be child of 'Research workflow' trace" + ) # Search the web should be child of research manager search_span = search_web_spans[0] assert search_span.context is not None assert search_span.parent is not None, "Search the web span should have a parent" - assert ( - search_span.parent.span_id == research_span.context.span_id - ), "Expected 'Search the web' to be child of 'Research manager' span" + assert search_span.parent.span_id == research_span.context.span_id, ( + "Expected 'Search the web' to be child of 'Research manager' span" + ) # All search agent spans should be descendants of "Search the web" # (the SDK now inserts a "task" span between "Search the web" and the agent) @@ -741,12 +741,12 @@ def is_descendant_of(child: ReadableSpan, ancestor_span_id: int) -> bool: return False for search_agent_span in search_agent_spans: - assert ( - search_agent_span.parent is not None - ), f"Search agent span '{search_agent_span.name}' should have a parent" - assert is_descendant_of( - search_agent_span, search_span.context.span_id - ), f"Expected all 'Search agent' spans to be descendants of 'Search the web' span" + assert search_agent_span.parent is not None, ( + f"Search agent span '{search_agent_span.name}' should have a parent" + ) + assert is_descendant_of(search_agent_span, search_span.context.span_id), ( + f"Expected all 'Search agent' spans to be descendants of 'Search the web' span" + ) # PlannerAgent and WriterAgent should be descendants of research manager planner_spans = [span for span in spans if "PlannerAgent" in span.name] @@ -754,15 +754,15 @@ def is_descendant_of(child: ReadableSpan, ancestor_span_id: int) -> bool: for planner_span in planner_spans: assert planner_span.parent is not None, "PlannerAgent span should have a parent" - assert is_descendant_of( - planner_span, research_span.context.span_id - ), "Expected 'PlannerAgent' to be descendant of 'Research manager' span" + assert is_descendant_of(planner_span, research_span.context.span_id), ( + "Expected 'PlannerAgent' to be descendant of 'Research manager' span" + ) for writer_span in writer_spans: assert writer_span.parent is not None, "WriterAgent span should have a parent" - assert is_descendant_of( - writer_span, research_span.context.span_id - ), "Expected 'WriterAgent' to be descendant of 'Research manager' span" + assert is_descendant_of(writer_span, research_span.context.span_id), ( + "Expected 'WriterAgent' to be descendant of 'Research manager' span" + ) @workflow.defn @@ -879,32 +879,32 @@ async def ready() -> bool: assert direct_otel_span is not None, "Direct OTEL span should exist" # Verify parenting chain: Client SDK trace -> Workflow SDK span -> Direct OTEL span - assert ( - client_sdk_trace_span.parent is None - ), "Client SDK trace should have no parent (be root)" + assert client_sdk_trace_span.parent is None, ( + "Client SDK trace should have no parent (be root)" + ) - assert ( - workflow_sdk_span.parent is not None - ), "Workflow SDK span should have a parent" - assert ( - client_sdk_trace_span.context is not None - ), "Client SDK trace span should have context" - assert ( - workflow_sdk_span.parent.span_id == client_sdk_trace_span.context.span_id - ), "Workflow SDK span should be child of Client SDK trace" + assert workflow_sdk_span.parent is not None, ( + "Workflow SDK span should have a parent" + ) + assert client_sdk_trace_span.context is not None, ( + "Client SDK trace span should have context" + ) + assert workflow_sdk_span.parent.span_id == client_sdk_trace_span.context.span_id, ( + "Workflow SDK span should be child of Client SDK trace" + ) assert direct_otel_span.parent is not None, "Direct OTEL span should have a parent" - assert ( - workflow_sdk_span.context is not None - ), "Workflow SDK span should have context" - assert ( - direct_otel_span.parent.span_id == workflow_sdk_span.context.span_id - ), "Direct OTEL span should be child of Workflow SDK span" + assert workflow_sdk_span.context is not None, ( + "Workflow SDK span should have context" + ) + assert direct_otel_span.parent.span_id == workflow_sdk_span.context.span_id, ( + "Direct OTEL span should be child of Workflow SDK span" + ) # Verify all spans belong to the same trace - assert ( - workflow_sdk_span.context is not None - ), "Workflow SDK span should have context" + assert workflow_sdk_span.context is not None, ( + "Workflow SDK span should have context" + ) assert direct_otel_span.context is not None, "Direct OTEL span should have context" assert ( client_sdk_trace_span.context.trace_id @@ -914,6 +914,6 @@ async def ready() -> bool: # Verify all spans have unique IDs span_ids = [span.context.span_id for span in spans if span.context] - assert len(span_ids) == len( - set(span_ids) - ), f"All spans should have unique IDs, got: {span_ids}" + assert len(span_ids) == len(set(span_ids)), ( + f"All spans should have unique IDs, got: {span_ids}" + ) diff --git a/tests/contrib/opentelemetry/test_opentelemetry.py b/tests/contrib/opentelemetry/test_opentelemetry.py index 94bb3fda5..71e2fa41d 100644 --- a/tests/contrib/opentelemetry/test_opentelemetry.py +++ b/tests/contrib/opentelemetry/test_opentelemetry.py @@ -720,12 +720,12 @@ async def test_opentelemetry_baggage_propagation_basic(client_with_tracing: Clie task_queue=task_queue, ) - assert ( - result["user_id"] == "test-user-123" - ), "user.id baggage should propagate to activity" - assert ( - result["tenant_id"] == "some-corp" - ), "tenant.id baggage should propagate to activity" + assert result["user_id"] == "test-user-123", ( + "user.id baggage should propagate to activity" + ) + assert result["tenant_id"] == "some-corp", ( + "tenant.id baggage should propagate to activity" + ) @activity.defn @@ -886,15 +886,15 @@ def tracked_detach(token): # type:ignore[reportMissingParameterType] id=f"workflow_{uuid.uuid4()}", task_queue=task_queue, ) - assert ( - not expect_failure - ), "This test should have raised an exception" + assert not expect_failure, ( + "This test should have raised an exception" + ) except Exception: assert expect_failure, "This test is not expeced to raise" - assert ( - attach_count == detach_count - ), f"Context leak detected: {attach_count} attaches vs {detach_count} detaches. " + assert attach_count == detach_count, ( + f"Context leak detected: {attach_count} attaches vs {detach_count} detaches. " + ) assert attach_count > 0, "Expected at least one context attach/detach" finally: @@ -1030,6 +1030,6 @@ def otel_context_error(record: logging.LogRecord) -> bool: and "Failed to detach context" in record.message ) - assert ( - capturer.find(otel_context_error) is None - ), "Detach from context message should not be logged" + assert capturer.find(otel_context_error) is None, ( + "Detach from context message should not be logged" + ) diff --git a/tests/contrib/opentelemetry/test_opentelemetry_plugin.py b/tests/contrib/opentelemetry/test_opentelemetry_plugin.py index 06ad330ed..3fd50e89b 100644 --- a/tests/contrib/opentelemetry/test_opentelemetry_plugin.py +++ b/tests/contrib/opentelemetry/test_opentelemetry_plugin.py @@ -123,9 +123,9 @@ async def test_otel_tracing_basic(client: Client, reset_otel_tracer_provider: An # Verify the span hierarchy matches expectations actual_hierarchy = dump_spans(spans, with_attributes=False) - assert ( - actual_hierarchy == expected_hierarchy - ), f"Span hierarchy mismatch.\nExpected:\n{expected_hierarchy}\nActual:\n{actual_hierarchy}" + assert actual_hierarchy == expected_hierarchy, ( + f"Span hierarchy mismatch.\nExpected:\n{expected_hierarchy}\nActual:\n{actual_hierarchy}" + ) @workflow.defn @@ -382,9 +382,9 @@ async def test_opentelemetry_comprehensive_tracing( # Verify the span hierarchy matches expectations actual_hierarchy = dump_spans(spans, with_attributes=False) - assert ( - actual_hierarchy == expected_hierarchy - ), f"Span hierarchy mismatch.\nExpected:\n{expected_hierarchy}\nActual:\n{actual_hierarchy}" + assert actual_hierarchy == expected_hierarchy, ( + f"Span hierarchy mismatch.\nExpected:\n{expected_hierarchy}\nActual:\n{actual_hierarchy}" + ) async def test_otel_tracing_with_added_spans( @@ -439,9 +439,9 @@ async def test_otel_tracing_with_added_spans( # Verify the span hierarchy matches expectations actual_hierarchy = dump_spans(spans, with_attributes=False) - assert ( - actual_hierarchy == expected_hierarchy - ), f"Span hierarchy mismatch.\nExpected:\n{expected_hierarchy}\nActual:\n{actual_hierarchy}" + assert actual_hierarchy == expected_hierarchy, ( + f"Span hierarchy mismatch.\nExpected:\n{expected_hierarchy}\nActual:\n{actual_hierarchy}" + ) task_fail_once_workflow_has_failed = False @@ -507,9 +507,9 @@ async def test_otel_tracing_workflow_task_failure( ] actual_hierarchy = dump_spans(spans, with_attributes=False) - assert ( - actual_hierarchy == expected_hierarchy - ), f"Span hierarchy mismatch.\nExpected:\n{expected_hierarchy}\nActual:\n{actual_hierarchy}" + assert actual_hierarchy == expected_hierarchy, ( + f"Span hierarchy mismatch.\nExpected:\n{expected_hierarchy}\nActual:\n{actual_hierarchy}" + ) @workflow.defn @@ -562,9 +562,9 @@ async def test_otel_tracing_workflow_failure( ] actual_hierarchy = dump_spans(spans, with_attributes=False) - assert ( - actual_hierarchy == expected_hierarchy - ), f"Span hierarchy mismatch.\nExpected:\n{expected_hierarchy}\nActual:\n{actual_hierarchy}" + assert actual_hierarchy == expected_hierarchy, ( + f"Span hierarchy mismatch.\nExpected:\n{expected_hierarchy}\nActual:\n{actual_hierarchy}" + ) async def test_otel_standalone_activity_tracing( diff --git a/tests/contrib/workflow_streams/test_workflow_streams.py b/tests/contrib/workflow_streams/test_workflow_streams.py index 203e1313d..7353cbdd5 100644 --- a/tests/contrib/workflow_streams/test_workflow_streams.py +++ b/tests/contrib/workflow_streams/test_workflow_streams.py @@ -2133,9 +2133,9 @@ async def standalone_publish_to_broker(input: StandalonePublishInput) -> None: ``WorkflowStreamClient.create``. ``from_within_activity`` is not usable here because the activity has no parent workflow. """ - assert ( - activity.info().workflow_id is None - ), "test bug: this activity should be standalone" + assert activity.info().workflow_id is None, ( + "test bug: this activity should be standalone" + ) client = WorkflowStreamClient.create( client=activity.client(), workflow_id=input.broker_workflow_id, @@ -2149,9 +2149,9 @@ async def standalone_publish_to_broker(input: StandalonePublishInput) -> None: @activity.defn(name="standalone_subscribe_to_broker") async def standalone_subscribe_to_broker(input: CrossWorkflowInput) -> list[str]: - assert ( - activity.info().workflow_id is None - ), "test bug: this activity should be standalone" + assert activity.info().workflow_id is None, ( + "test bug: this activity should be standalone" + ) client = WorkflowStreamClient.create( client=activity.client(), workflow_id=input.broker_workflow_id, diff --git a/tests/nexus/test_workflow_caller.py b/tests/nexus/test_workflow_caller.py index 38f51cd63..df6ace9fa 100644 --- a/tests/nexus/test_workflow_caller.py +++ b/tests/nexus/test_workflow_caller.py @@ -440,13 +440,13 @@ async def run( self._nexus_operation_start_resolved = True if not input.op_input.response_type.exception_in_operation_start: if isinstance(input.op_input.response_type, SyncResponse): - assert ( - op_handle.operation_token is None - ), "operation_token should be absent after a sync response" + assert op_handle.operation_token is None, ( + "operation_token should be absent after a sync response" + ) else: - assert ( - op_handle.operation_token - ), "operation_token should be present after an async response" + assert op_handle.operation_token, ( + "operation_token should be present after an async response" + ) if request_cancel: # Even for SyncResponse, the op_handle future is not done at this point; that @@ -2302,16 +2302,16 @@ async def test_request_deadline_is_accessible_in_operation( assert len(service_handler.start_deadlines_received) == 1 deadline = service_handler.start_deadlines_received[0] - assert ( - deadline is not None - ), "request_deadline should be set in StartOperationContext" + assert deadline is not None, ( + "request_deadline should be set in StartOperationContext" + ) assert deadline.tzinfo is timezone.utc, "request_deadline should be in utc" await asyncio.wait_for(service_handler.cancel_received.wait(), 1) assert len(service_handler.cancel_deadlines_received) == 1 deadline = service_handler.cancel_deadlines_received[0] - assert ( - deadline is not None - ), "request_deadline should be set in CancelOperationContext" + assert deadline is not None, ( + "request_deadline should be set in CancelOperationContext" + ) assert deadline.tzinfo is timezone.utc, "request_deadline should be in utc" diff --git a/tests/nexus/test_workflow_caller_error_chains.py b/tests/nexus/test_workflow_caller_error_chains.py index 28831e476..9ff84f405 100644 --- a/tests/nexus/test_workflow_caller_error_chains.py +++ b/tests/nexus/test_workflow_caller_error_chains.py @@ -574,15 +574,15 @@ def _validate_exception_chain( # Check remaining expected errors are all optional while expected_idx < len(expected_chain): expected = expected_chain[expected_idx] - assert ( - expected.optional - ), f"Required expected error not found in chain: {expected}" + assert expected.optional, ( + f"Required expected error not found in chain: {expected}" + ) expected_idx += 1 # Check no remaining actual errors - assert actual_idx == len( - actual_chain - ), f"Unexpected errors in chain: {actual_chain[actual_idx:]}" + assert actual_idx == len(actual_chain), ( + f"Unexpected errors in chain: {actual_chain[actual_idx:]}" + ) @workflow.defn(sandboxed=False) diff --git a/tests/nexus/test_workflow_run_operation.py b/tests/nexus/test_workflow_run_operation.py index 489353165..3ba9545fc 100644 --- a/tests/nexus/test_workflow_run_operation.py +++ b/tests/nexus/test_workflow_run_operation.py @@ -182,7 +182,7 @@ async def test_request_deadline_is_accessible_in_workflow_run_operation( assert len(service_handler.start_deadlines_received) == 1 deadline = service_handler.start_deadlines_received[0] - assert ( - deadline is not None - ), "request_deadline should be set in WorkflowRunOperationContext" + assert deadline is not None, ( + "request_deadline should be set in WorkflowRunOperationContext" + ) assert deadline.tzinfo is timezone.utc, "request_deadline should be in utc" diff --git a/tests/test_activity.py b/tests/test_activity.py index 8ed4729ec..172040257 100644 --- a/tests/test_activity.py +++ b/tests/test_activity.py @@ -867,9 +867,9 @@ async def test_id_conflict_policy_fail(client: Client, env: WorkflowEnvironment) id_conflict_policy=ActivityIDConflictPolicy.FAIL, ) assert err.value.activity_id == activity_id - assert "Activity" in str( - err.value - ), f"Expected 'Activity' in error message, got: {err.value}" + assert "Activity" in str(err.value), ( + f"Expected 'Activity' in error message, got: {err.value}" + ) async def test_id_conflict_policy_use_existing( diff --git a/tests/test_extstore.py b/tests/test_extstore.py index 196632042..9a058c582 100644 --- a/tests/test_extstore.py +++ b/tests/test_extstore.py @@ -162,9 +162,9 @@ async def test_extstore_composite_conditional(self): options = ExternalStorage( drivers=[hot_driver, cold_driver], - driver_selector=lambda context, payload: hot_driver - if payload.ByteSize() < 500 - else cold_driver, + driver_selector=lambda context, payload: ( + hot_driver if payload.ByteSize() < 500 else cold_driver + ), payload_size_threshold=100, ) converter = DataConverter(external_storage=options) diff --git a/tests/test_plugins.py b/tests/test_plugins.py index e54f8065f..e8823af27 100644 --- a/tests/test_plugins.py +++ b/tests/test_plugins.py @@ -6,8 +6,8 @@ from typing import cast import pytest - import temporalio.bridge.temporal_sdk_bridge + import temporalio.client import temporalio.converter import temporalio.worker @@ -463,9 +463,9 @@ async def test_simple_plugin_worker_interceptor_only_used_on_worker( # The interceptor should NOT have been used for client interception # since the plugin was not added to the client - assert ( - not interceptor.client_intercepted - ), "Client interceptor should not have been used" + assert not interceptor.client_intercepted, ( + "Client interceptor should not have been used" + ) # The interceptor SHOULD have been used for worker interception # even though it was specified in interceptors @@ -527,9 +527,9 @@ async def test_simple_plugin_interceptor_duplication_when_used_on_client_and_wor assert result == "Hello, test!" # The workflow interceptor should only be called ONCE, not twice - assert ( - interceptor.call_count["execute_workflow"] == 1 - ), f"Expected execute_workflow to be called once, but was called {interceptor.call_count['execute_workflow']} times. This indicates interceptor duplication in execution." + assert interceptor.call_count["execute_workflow"] == 1, ( + f"Expected execute_workflow to be called once, but was called {interceptor.call_count['execute_workflow']} times. This indicates interceptor duplication in execution." + ) async def test_simple_plugin_no_duplication_when_interceptor_in_both_client_and_worker_params( @@ -571,9 +571,9 @@ async def test_simple_plugin_no_duplication_when_interceptor_in_both_client_and_ assert result == "Hello, test!" # The workflow interceptor should only be called ONCE, not twice - assert ( - interceptor.call_count["execute_workflow"] == 1 - ), f"Expected execute_workflow to be called once, but was called {interceptor.call_count['execute_workflow']} times. This indicates interceptor duplication in execution." + assert interceptor.call_count["execute_workflow"] == 1, ( + f"Expected execute_workflow to be called once, but was called {interceptor.call_count['execute_workflow']} times. This indicates interceptor duplication in execution." + ) async def test_simple_plugin_no_duplication_in_interceptor_chain( @@ -612,6 +612,6 @@ async def test_simple_plugin_no_duplication_in_interceptor_chain( assert result == "Hello, test!" # The workflow interceptor should only be called ONCE, not twice - assert ( - interceptor.call_count["execute_workflow"] == 1 - ), f"Expected execute_workflow to be called once, but was called {interceptor.call_count['execute_workflow']} times. This indicates interceptor duplication in the chain." + assert interceptor.call_count["execute_workflow"] == 1, ( + f"Expected execute_workflow to be called once, but was called {interceptor.call_count['execute_workflow']} times. This indicates interceptor duplication in the chain." + ) diff --git a/tests/test_runtime.py b/tests/test_runtime.py index 609df3ff8..c29961c52 100644 --- a/tests/test_runtime.py +++ b/tests/test_runtime.py @@ -255,15 +255,15 @@ async def check_metrics() -> None: metrics_output = f.read().decode("utf-8") for key, buckets in histogram_overrides.items(): - assert ( - key in metrics_output - ), f"Missing {key} in full output: {metrics_output}" + assert key in metrics_output, ( + f"Missing {key} in full output: {metrics_output}" + ) for bucket in buckets: # expect to have {key}_bucket and le={bucket} in the same line with arbitrary strings between them regex = re.compile(f'{key}_bucket.*le="{bucket}"') - assert regex.search( - metrics_output - ), f"Missing bucket for {key} in full output: {metrics_output}" + assert regex.search(metrics_output), ( + f"Missing bucket for {key} in full output: {metrics_output}" + ) # Wait for metrics to appear and match the expected buckets await assert_eventually(check_metrics) diff --git a/tests/test_serialization_context.py b/tests/test_serialization_context.py index 8e8fcf048..0fde2aa96 100644 --- a/tests/test_serialization_context.py +++ b/tests/test_serialization_context.py @@ -1600,7 +1600,7 @@ def __init__(self): @workflow.run async def run(self, _data: str) -> str: await workflow.wait_condition( - lambda: (self.received_signal and self.received_update) + lambda: self.received_signal and self.received_update ) # Run them in parallel to check that data converter operations do not mix up contexts when # there are multiple concurrent payload types. diff --git a/tests/test_service.py b/tests/test_service.py index 067f59cc5..8de337308 100644 --- a/tests/test_service.py +++ b/tests/test_service.py @@ -272,9 +272,9 @@ async def test_method( try: await rpc_call(request, timeout=timedelta(milliseconds=1)) except ValueError as err: - assert ( - "Unknown RPC call" not in str(err) - ), f"Unexpected unknown-RPC error for {target_service_name}.{method_name}: {err}" + assert "Unknown RPC call" not in str(err), ( + f"Unexpected unknown-RPC error for {target_service_name}.{method_name}: {err}" + ) except temporalio.service.RPCError: pass diff --git a/tests/test_workflow.py b/tests/test_workflow.py index 8bd06ad9b..5618c34f5 100644 --- a/tests/test_workflow.py +++ b/tests/test_workflow.py @@ -446,9 +446,9 @@ def test_parameters_identical_up_to_naming(): for f1, f2 in itertools.combinations(fns, 2): name1, name2 = f1.__name__, f2.__name__ expect_equal = name1[0] == name2[0] - assert ( - workflow._parameters_identical_up_to_naming(f1, f2) == (expect_equal) - ), f"expected {name1} and {name2} parameters{' ' if expect_equal else ' not '}to compare equal" + assert workflow._parameters_identical_up_to_naming(f1, f2) == (expect_equal), ( + f"expected {name1} and {name2} parameters{' ' if expect_equal else ' not '}to compare equal" + ) @workflow.defn diff --git a/tests/worker/test_command_aware_visitor.py b/tests/worker/test_command_aware_visitor.py index b8488689e..f354c8614 100644 --- a/tests/worker/test_command_aware_visitor.py +++ b/tests/worker/test_command_aware_visitor.py @@ -65,13 +65,13 @@ def test_command_aware_visitor_has_methods_for_all_seq_protos_with_payloads(): # Sanity check: we should have fewer overrides than total protos with seq # (because some don't have payloads) - assert len(commands_with_payloads) < len( - command_protos - ), "Should have some commands without payloads" + assert len(commands_with_payloads) < len(command_protos), ( + "Should have some commands without payloads" + ) # All activation jobs except FireTimer have payloads - assert ( - len(jobs_with_payloads) == len(job_protos) - 1 - ), "Should have exactly one activation job without payloads (FireTimer)" + assert len(jobs_with_payloads) == len(job_protos) - 1, ( + "Should have exactly one activation job without payloads (FireTimer)" + ) def _get_workflow_command_protos_with_seq() -> Iterator[type[Any]]: diff --git a/uv.lock b/uv.lock index b523c21eb..985872473 100644 --- a/uv.lock +++ b/uv.lock @@ -4932,27 +4932,27 @@ wheels = [ [[package]] name = "ruff" -version = "0.5.7" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/bf/2b/69e5e412f9d390adbdbcbf4f64d6914fa61b44b08839a6584655014fc524/ruff-0.5.7.tar.gz", hash = "sha256:8dfc0a458797f5d9fb622dd0efc52d796f23f0a1493a9527f4e49a550ae9a7e5", size = 2449817, upload-time = "2024-08-08T15:43:07.467Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/6b/eb/06e06aaf96af30a68e83b357b037008c54a2ddcbad4f989535007c700394/ruff-0.5.7-py3-none-linux_armv6l.whl", hash = "sha256:548992d342fc404ee2e15a242cdbea4f8e39a52f2e7752d0e4cbe88d2d2f416a", size = 9570571, upload-time = "2024-08-08T15:41:56.537Z" }, - { url = "https://files.pythonhosted.org/packages/a4/10/1be32aeaab8728f78f673e7a47dd813222364479b2d6573dbcf0085e83ea/ruff-0.5.7-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:00cc8872331055ee017c4f1071a8a31ca0809ccc0657da1d154a1d2abac5c0be", size = 8685138, upload-time = "2024-08-08T15:42:02.833Z" }, - { url = "https://files.pythonhosted.org/packages/3d/1d/c218ce83beb4394ba04d05e9aa2ae6ce9fba8405688fe878b0fdb40ce855/ruff-0.5.7-py3-none-macosx_11_0_arm64.whl", hash = "sha256:eaf3d86a1fdac1aec8a3417a63587d93f906c678bb9ed0b796da7b59c1114a1e", size = 8266785, upload-time = "2024-08-08T15:42:08.321Z" }, - { url = "https://files.pythonhosted.org/packages/26/79/7f49509bd844476235b40425756def366b227a9714191c91f02fb2178635/ruff-0.5.7-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a01c34400097b06cf8a6e61b35d6d456d5bd1ae6961542de18ec81eaf33b4cb8", size = 9983964, upload-time = "2024-08-08T15:42:12.419Z" }, - { url = "https://files.pythonhosted.org/packages/bf/b1/939836b70bf9fcd5e5cd3ea67fdb8abb9eac7631351d32f26544034a35e4/ruff-0.5.7-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:fcc8054f1a717e2213500edaddcf1dbb0abad40d98e1bd9d0ad364f75c763eea", size = 9359490, upload-time = "2024-08-08T15:42:16.713Z" }, - { url = "https://files.pythonhosted.org/packages/32/7d/b3db19207de105daad0c8b704b2c6f2a011f9c07017bd58d8d6e7b8eba19/ruff-0.5.7-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7f70284e73f36558ef51602254451e50dd6cc479f8b6f8413a95fcb5db4a55fc", size = 10170833, upload-time = "2024-08-08T15:42:20.54Z" }, - { url = "https://files.pythonhosted.org/packages/a2/45/eae9da55f3357a1ac04220230b8b07800bf516e6dd7e1ad20a2ff3b03b1b/ruff-0.5.7-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:a78ad870ae3c460394fc95437d43deb5c04b5c29297815a2a1de028903f19692", size = 10896360, upload-time = "2024-08-08T15:42:25.2Z" }, - { url = "https://files.pythonhosted.org/packages/99/67/4388b36d145675f4c51ebec561fcd4298a0e2550c81e629116f83ce45a39/ruff-0.5.7-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9ccd078c66a8e419475174bfe60a69adb36ce04f8d4e91b006f1329d5cd44bcf", size = 10477094, upload-time = "2024-08-08T15:42:29.553Z" }, - { url = "https://files.pythonhosted.org/packages/e1/9c/f5e6ed1751dc187a4ecf19a4970dd30a521c0ee66b7941c16e292a4043fb/ruff-0.5.7-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7e31c9bad4ebf8fdb77b59cae75814440731060a09a0e0077d559a556453acbb", size = 11480896, upload-time = "2024-08-08T15:42:33.772Z" }, - { url = "https://files.pythonhosted.org/packages/c8/3b/2b683be597bbd02046678fc3fc1c199c641512b20212073b58f173822bb3/ruff-0.5.7-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8d796327eed8e168164346b769dd9a27a70e0298d667b4ecee6877ce8095ec8e", size = 10179702, upload-time = "2024-08-08T15:42:38.038Z" }, - { url = "https://files.pythonhosted.org/packages/f1/38/c2d94054dc4b3d1ea4c2ba3439b2a7095f08d1c8184bc41e6abe2a688be7/ruff-0.5.7-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:4a09ea2c3f7778cc635e7f6edf57d566a8ee8f485f3c4454db7771efb692c499", size = 9982855, upload-time = "2024-08-08T15:42:42.031Z" }, - { url = "https://files.pythonhosted.org/packages/7d/e7/1433db2da505ffa8912dcf5b28a8743012ee780cbc20ad0bf114787385d9/ruff-0.5.7-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:a36d8dcf55b3a3bc353270d544fb170d75d2dff41eba5df57b4e0b67a95bb64e", size = 9433156, upload-time = "2024-08-08T15:42:45.339Z" }, - { url = "https://files.pythonhosted.org/packages/e0/36/4fa43250e67741edeea3d366f59a1dc993d4d89ad493a36cbaa9889895f2/ruff-0.5.7-py3-none-musllinux_1_2_i686.whl", hash = "sha256:9369c218f789eefbd1b8d82a8cf25017b523ac47d96b2f531eba73770971c9e5", size = 9782971, upload-time = "2024-08-08T15:42:49.354Z" }, - { url = "https://files.pythonhosted.org/packages/80/0e/8c276103d518e5cf9202f70630aaa494abf6fc71c04d87c08b6d3cd07a4b/ruff-0.5.7-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:b88ca3db7eb377eb24fb7c82840546fb7acef75af4a74bd36e9ceb37a890257e", size = 10247775, upload-time = "2024-08-08T15:42:53.294Z" }, - { url = "https://files.pythonhosted.org/packages/cb/b9/673096d61276f39291b729dddde23c831a5833d98048349835782688a0ec/ruff-0.5.7-py3-none-win32.whl", hash = "sha256:33d61fc0e902198a3e55719f4be6b375b28f860b09c281e4bdbf783c0566576a", size = 7841772, upload-time = "2024-08-08T15:42:57.488Z" }, - { url = "https://files.pythonhosted.org/packages/67/1c/4520c98bfc06b9c73cd1457686d4d3935d40046b1ddea08403e5a6deff51/ruff-0.5.7-py3-none-win_amd64.whl", hash = "sha256:083bbcbe6fadb93cd86709037acc510f86eed5a314203079df174c40bbbca6b3", size = 8699779, upload-time = "2024-08-08T15:43:00.429Z" }, - { url = "https://files.pythonhosted.org/packages/38/23/b3763a237d2523d40a31fe2d1a301191fe392dd48d3014977d079cf8c0bd/ruff-0.5.7-py3-none-win_arm64.whl", hash = "sha256:2dca26154ff9571995107221d0aeaad0e75a77b5a682d6236cf89a58c70b76f4", size = 8091891, upload-time = "2024-08-08T15:43:04.162Z" }, +version = "0.15.12" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/99/43/3291f1cc9106f4c63bdce7a8d0df5047fe8422a75b091c16b5e9355e0b11/ruff-0.15.12.tar.gz", hash = "sha256:ecea26adb26b4232c0c2ca19ccbc0083a68344180bba2a600605538ce51a40a6", size = 4643852, upload-time = "2026-04-24T18:17:14.305Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c3/6e/e78ffb61d4686f3d96ba3df2c801161843746dcbcbb17a1e927d4829312b/ruff-0.15.12-py3-none-linux_armv6l.whl", hash = "sha256:f86f176e188e94d6bdbc09f09bfd9dc729059ad93d0e7390b5a73efe19f8861c", size = 10640713, upload-time = "2026-04-24T18:17:22.841Z" }, + { url = "https://files.pythonhosted.org/packages/ae/08/a317bc231fb9e7b93e4ef3089501e51922ff88d6936ce5cf870c4fe55419/ruff-0.15.12-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:e3bcd123364c3770b8e1b7baaf343cc99a35f197c5c6e8af79015c666c423a6c", size = 11069267, upload-time = "2026-04-24T18:17:30.105Z" }, + { url = "https://files.pythonhosted.org/packages/aa/a4/f828e9718d3dce1f5f11c39c4f65afd32783c8b2aebb2e3d259e492c47bd/ruff-0.15.12-py3-none-macosx_11_0_arm64.whl", hash = "sha256:fe87510d000220aa1ed530d4448a7c696a0cae1213e5ec30e5874287b66557b5", size = 10397182, upload-time = "2026-04-24T18:17:07.177Z" }, + { url = "https://files.pythonhosted.org/packages/71/e0/3310fc6d1b5e1fdea22bf3b1b807c7e187b581021b0d7d4514cccdb5fb71/ruff-0.15.12-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:84a1630093121375a3e2a95b4a6dc7b59e2b4ee76216e32d81aae550a832d002", size = 10758012, upload-time = "2026-04-24T18:16:55.759Z" }, + { url = "https://files.pythonhosted.org/packages/11/c1/a606911aee04c324ddaa883ae418f3569792fd3c4a10c50e0dd0a2311e1e/ruff-0.15.12-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:fb129f40f114f089ebe0ca56c0d251cf2061b17651d464bb6478dc01e69f11f5", size = 10447479, upload-time = "2026-04-24T18:16:51.677Z" }, + { url = "https://files.pythonhosted.org/packages/9d/68/4201e8444f0894f21ab4aeeaee68aa4f10b51613514a20d80bd628d57e88/ruff-0.15.12-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b0c862b172d695db7598426b8af465e7e9ac00a3ea2a3630ee67eb82e366aaa6", size = 11234040, upload-time = "2026-04-24T18:17:16.529Z" }, + { url = "https://files.pythonhosted.org/packages/34/ff/8a6d6cf4ccc23fd67060874e832c18919d1557a0611ebef03fdb01fff11e/ruff-0.15.12-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2849ea9f3484c3aca43a82f484210370319e7170df4dfe4843395ddf6c57bc33", size = 12087377, upload-time = "2026-04-24T18:17:04.944Z" }, + { url = "https://files.pythonhosted.org/packages/85/f6/c669cf73f5152f623d34e69866a46d5e6185816b19fcd5b6dd8a2d299922/ruff-0.15.12-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9e77c7e51c07fe396826d5969a5b846d9cd4c402535835fb6e21ce8b28fef847", size = 11367784, upload-time = "2026-04-24T18:17:25.409Z" }, + { url = "https://files.pythonhosted.org/packages/e8/39/c61d193b8a1daaa8977f7dea9e8d8ba866e02ea7b65d32f6861693aa4c12/ruff-0.15.12-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:83b2f4f2f3b1026b5fb449b467d9264bf22067b600f7b6f41fc5958909f449d0", size = 11344088, upload-time = "2026-04-24T18:17:12.258Z" }, + { url = "https://files.pythonhosted.org/packages/c2/8d/49afab3645e31e12c590acb6d3b5b69d7aab5b81926dbaf7461f9441f37a/ruff-0.15.12-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:9ba3b8f1afd7e2e43d8943e55f249e13f9682fde09711644a6e7290eb4f3e339", size = 11271770, upload-time = "2026-04-24T18:17:02.457Z" }, + { url = "https://files.pythonhosted.org/packages/46/06/33f41fe94403e2b755481cdfb9b7ef3e4e0ed031c4581124658d935d52b4/ruff-0.15.12-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:e852ba9fdc890655e1d78f2df1499efbe0e54126bd405362154a75e2bde159c5", size = 10719355, upload-time = "2026-04-24T18:17:27.648Z" }, + { url = "https://files.pythonhosted.org/packages/0d/59/18aa4e014debbf559670e4048e39260a85c7fcee84acfd761ac01e7b8d35/ruff-0.15.12-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:dd8aed930da53780d22fc70bdf84452c843cf64f8cb4eb38984319c24c5cd5fd", size = 10462758, upload-time = "2026-04-24T18:17:32.347Z" }, + { url = "https://files.pythonhosted.org/packages/25/e7/cc9f16fd0f3b5fddcbd7ec3d6ae30c8f3fde1047f32a4093a98d633c6570/ruff-0.15.12-py3-none-musllinux_1_2_i686.whl", hash = "sha256:01da3988d225628b709493d7dc67c3b9b12c0210016b08690ef9bd27970b262b", size = 10953498, upload-time = "2026-04-24T18:17:20.674Z" }, + { url = "https://files.pythonhosted.org/packages/72/7a/a9ba7f98c7a575978698f4230c5e8cc54bbc761af34f560818f933dafa0c/ruff-0.15.12-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:9cae0f92bd5700d1213188b31cd3bdd2b315361296d10b96b8e2337d3d11f53e", size = 11447765, upload-time = "2026-04-24T18:17:09.755Z" }, + { url = "https://files.pythonhosted.org/packages/ea/f9/0ae446942c846b8266059ad8a30702a35afae55f5cdc54c5adf8d7afdc27/ruff-0.15.12-py3-none-win32.whl", hash = "sha256:d0185894e038d7043ba8fd6aee7499ece6462dc0ea9f1e260c7451807c714c20", size = 10657277, upload-time = "2026-04-24T18:17:18.591Z" }, + { url = "https://files.pythonhosted.org/packages/33/f1/9614e03e1cdcbf9437570b5400ced8a720b5db22b28d8e0f1bda429f660d/ruff-0.15.12-py3-none-win_amd64.whl", hash = "sha256:c87a162d61ab3adca47c03f7f717c68672edec7d1b5499e652331780fe74950d", size = 11837758, upload-time = "2026-04-24T18:17:00.113Z" }, + { url = "https://files.pythonhosted.org/packages/c0/98/6beb4b351e472e5f4c4613f7c35a5290b8be2497e183825310c4c3a3984b/ruff-0.15.12-py3-none-win_arm64.whl", hash = "sha256:a538f7a82d061cee7be55542aca1d86d1393d55d81d4fcc314370f4340930d4f", size = 11120821, upload-time = "2026-04-24T18:16:57.979Z" }, ] [[package]] @@ -5292,7 +5292,7 @@ dev = [ { name = "pytest-rerunfailures", specifier = ">=16.1" }, { name = "pytest-timeout", specifier = "~=2.2" }, { name = "pytest-xdist", specifier = ">=3.6,<4" }, - { name = "ruff", specifier = ">=0.5.0,<0.6" }, + { name = "ruff", specifier = ">=0.15.12,<0.16" }, { name = "setuptools", specifier = "<82" }, { name = "toml", specifier = ">=0.10.2,<0.11" }, { name = "twine", specifier = ">=4.0.1,<5" }, From 01eef556a04d76fbd759368a1062d53f2c193b15 Mon Sep 17 00:00:00 2001 From: tconley1428 Date: Thu, 14 May 2026 19:05:30 -0700 Subject: [PATCH 087/226] Format LangSmith tracing env override test (#1531) --- tests/contrib/langsmith/test_tracing_env_override.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/contrib/langsmith/test_tracing_env_override.py b/tests/contrib/langsmith/test_tracing_env_override.py index 543d1897c..9d871e1d3 100644 --- a/tests/contrib/langsmith/test_tracing_env_override.py +++ b/tests/contrib/langsmith/test_tracing_env_override.py @@ -238,6 +238,6 @@ async def test_runs_emitted_when_tracing_enabled( result = await handle.result() assert result == "response to: hello" - assert ( - len(collector.runs) > 0 - ), "Expected LangSmith runs when LANGSMITH_TRACING=true, but got none" + assert len(collector.runs) > 0, ( + "Expected LangSmith runs when LANGSMITH_TRACING=true, but got none" + ) From c9e4d4a7b2d305fec5fb3f25567abae2893adb67 Mon Sep 17 00:00:00 2001 From: Sathvik Kalikivaya Date: Fri, 15 May 2026 20:17:14 +0530 Subject: [PATCH 088/226] Fix swallowed CancelledError in start_child_workflow and Nexus operations (Issue #1445) (#1472) * Fix swallowed CancelledError in start_child_workflow and Nexus operations (Issue #1445) * fix: guard CancelledError re-raise with _cancel_requested check (fixes #1445) * Fix pre-existing lint errors in test file and added a blank mistakenly removed in worker/_workflow_instance.py * Revert unrelated lint fixes, removed the extra blank line causing error * formatting --------- Co-authored-by: tconley1428 Co-authored-by: Thomas Hardy Co-authored-by: Thomas Hardy --- temporalio/worker/_workflow_instance.py | 4 ++ tests/worker/test_workflow.py | 55 +++++++++++++++++++++++-- 2 files changed, 56 insertions(+), 3 deletions(-) diff --git a/temporalio/worker/_workflow_instance.py b/temporalio/worker/_workflow_instance.py index fea97564b..fff0a42cd 100644 --- a/temporalio/worker/_workflow_instance.py +++ b/temporalio/worker/_workflow_instance.py @@ -2025,6 +2025,8 @@ async def run_child() -> Any: return handle except asyncio.CancelledError: apply_child_cancel_error() + if self._cancel_requested: + raise async def _outbound_start_nexus_operation( self, input: StartNexusOperationInput[Any, OutputT] @@ -2065,6 +2067,8 @@ async def operation_handle_fn() -> OutputT: except asyncio.CancelledError: cancel_command = self._add_command() handle._apply_cancel_command(cancel_command) + if self._cancel_requested: + raise #### Miscellaneous helpers #### # These are in alphabetical order. diff --git a/tests/worker/test_workflow.py b/tests/worker/test_workflow.py index 71f48cc63..3b06c8d1d 100644 --- a/tests/worker/test_workflow.py +++ b/tests/worker/test_workflow.py @@ -1211,9 +1211,58 @@ async def test_workflow_cancel_child_started(client: Client, use_execute: bool): assert isinstance(err.value.cause.cause, CancelledError) -@pytest.mark.skip(reason="unable to easily prevent child start currently") -async def test_workflow_cancel_child_unstarted(_client: Client): - raise NotImplementedError +@workflow.defn +class CancelDuringChildStartWorkflow: + def __init__(self) -> None: + self._proceed = False + + @workflow.signal + def proceed(self) -> None: + self._proceed = True + + @workflow.run + async def run(self) -> None: + await workflow.wait_condition(lambda: self._proceed) + # Start a child on a task queue with no worker. The child's first WFT + # never starts, so _start_fut remains unresolved and the start loop + # blocks forever. + await workflow.start_child_workflow( + LongSleepWorkflow.run, + id=f"{workflow.info().workflow_id}_child", + task_queue="nonexistent-task-queue-no-worker-abc123", + ) + await workflow.sleep(1000) + + +async def test_workflow_cancel_child_unstarted(client: Client): + # Regression test for https://github.com/temporalio/sdk-python/issues/1445 + # + # When cancellation arrived while the parent was waiting for a child + # workflow to start, the CancelledError was caught in the start loop + # to send a cancel command to the child — but was not re-raised. + # Because _start_fut never resolves (child on a queue with no worker), + # the loop would keep waiting forever, hanging the parent workflow. + # + # The fix: re-raise only when self._cancel_requested is True, which + # distinguishes Temporal workflow cancellation from other CancelledError + # sources such as asyncio.wait_for timeouts. + async with new_worker( + client, + CancelDuringChildStartWorkflow, + # Deliberately not registering LongSleepWorkflow and not starting + # a worker on the child's task queue. + ) as worker: + handle = await client.start_workflow( + CancelDuringChildStartWorkflow.run, + id=f"workflow-{uuid.uuid4()}", + task_queue=worker.task_queue, + execution_timeout=timedelta(seconds=30), + ) + await handle.signal(CancelDuringChildStartWorkflow.proceed) + await handle.cancel() + with pytest.raises(WorkflowFailureError) as err: + await handle.result() + assert isinstance(err.value.cause, CancelledError) @workflow.defn From 8afa4eb1ce921ebf613c5a9275a096da7a54331c Mon Sep 17 00:00:00 2001 From: xumaple <45406854+xumaple@users.noreply.github.com> Date: Mon, 18 May 2026 11:08:36 -0400 Subject: [PATCH 089/226] Use LangSmith's official runtime override API instead of monkey-patching aio_to_thread (#1477) LangSmith 0.7.34 added `set_runtime_overrides(aio_to_thread=...)` which provides a supported hook for frameworks with non-standard event loops. This replaces the process-wide monkey-patch of `langsmith._internal._aiter.aio_to_thread` with a call to the official API, making the integration less fragile against LangSmith internal refactors. Co-authored-by: Claude Opus 4.6 (1M context) --- pyproject.toml | 4 +- temporalio/contrib/langsmith/_interceptor.py | 60 ++++++++++---------- temporalio/contrib/langsmith/_plugin.py | 1 + uv.lock | 12 ++-- 4 files changed, 38 insertions(+), 39 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index f43b10079..81bb05922 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -31,7 +31,7 @@ pydantic = ["pydantic>=2.0.0,<3"] openai-agents = ["openai-agents>=0.17.1", "mcp>=1.9.4, <2"] google-adk = ["google-adk>=1.27.0,<2"] langgraph = ["langgraph>=1.1.0"] -langsmith = ["langsmith>=0.7.0,<0.8"] +langsmith = ["langsmith>=0.7.34,<0.8"] lambda-worker-otel = [ "opentelemetry-api>=1.11.1,<2", "opentelemetry-sdk>=1.11.1,<2", @@ -81,7 +81,7 @@ dev = [ "pytest-xdist>=3.6,<4", "moto[s3,server]>=5", "langgraph>=1.1.0", - "langsmith>=0.7.0,<0.7.34", + "langsmith>=0.7.34,<0.8", "setuptools<82", "opentelemetry-exporter-otlp-proto-grpc>=1.11.1,<2", "opentelemetry-semantic-conventions>=0.40b0,<1", diff --git a/temporalio/contrib/langsmith/_interceptor.py b/temporalio/contrib/langsmith/_interceptor.py index b3dd78574..a7eea0714 100644 --- a/temporalio/contrib/langsmith/_interceptor.py +++ b/temporalio/contrib/langsmith/_interceptor.py @@ -154,48 +154,46 @@ def _get_current_run_for_propagation() -> RunTree | None: # --------------------------------------------------------------------------- -# Workflow event loop safety: patch @traceable's aio_to_thread +# Workflow event loop safety: override @traceable's aio_to_thread # --------------------------------------------------------------------------- -_aio_to_thread_patched = False +_aio_to_thread_override_installed = False -def _patch_aio_to_thread() -> None: - """Patch langsmith's ``aio_to_thread`` to run synchronously in workflows. +async def _temporal_aio_to_thread( + default_aio_to_thread: Callable[..., Any], + ctx: Any, + func: Callable[..., Any], + /, + *args: Any, + **kwargs: Any, +) -> Any: + """Run LangSmith's ``aio_to_thread`` synchronously inside Temporal workflows. The ``@traceable`` decorator on async functions uses ``aio_to_thread()`` → ``loop.run_in_executor()`` for run setup/teardown. The Temporal workflow - event loop does not support ``run_in_executor``. This patch runs those - functions synchronously on the workflow thread when inside a workflow. - Functions passed here must not perform blocking I/O. + event loop does not support ``run_in_executor``. This override runs those + functions synchronously on the workflow thread when inside a workflow, + and delegates to the default implementation outside workflows. + Registered via ``langsmith.set_runtime_overrides(aio_to_thread=...)``. """ - global _aio_to_thread_patched # noqa: PLW0603 - if _aio_to_thread_patched: - return - - import langsmith._internal._aiter as _aiter + if not temporalio.workflow.in_workflow(): + return await default_aio_to_thread(ctx, func, *args, **kwargs) + with temporalio.workflow.unsafe.sandbox_unrestricted(): + return ctx.run(func, *args, **kwargs) - _original = _aiter.aio_to_thread - import contextvars +def _install_aio_to_thread_override() -> None: + """Install the ``aio_to_thread`` override via LangSmith's official API. - async def _safe_aio_to_thread( - func: Callable[..., Any], - /, - *args: Any, - __ctx: contextvars.Context | None = None, - **kwargs: Any, - ) -> Any: - if not temporalio.workflow.in_workflow(): - return await _original(func, *args, __ctx=__ctx, **kwargs) - with temporalio.workflow.unsafe.sandbox_unrestricted(): - # Run without ctx.run() so context var changes propagate - # to the caller. Safe because workflows are single-threaded. - return func(*args, **kwargs) - - _aiter.aio_to_thread = _safe_aio_to_thread # type: ignore[assignment] - _aio_to_thread_patched = True + Safe to call multiple times; the override is only installed once. + """ + global _aio_to_thread_override_installed # noqa: PLW0603 + if _aio_to_thread_override_installed: + return + langsmith.set_runtime_overrides(aio_to_thread=_temporal_aio_to_thread) + _aio_to_thread_override_installed = True # --------------------------------------------------------------------------- @@ -611,7 +609,7 @@ def workflow_interceptor_class( self, input: temporalio.worker.WorkflowInterceptorClassInput ) -> type[_LangSmithWorkflowInboundInterceptor]: """Return the workflow interceptor class with config bound.""" - _patch_aio_to_thread() + _install_aio_to_thread_override() config = self class InterceptorWithConfig(_LangSmithWorkflowInboundInterceptor): diff --git a/temporalio/contrib/langsmith/_plugin.py b/temporalio/contrib/langsmith/_plugin.py index 789c93414..cb2333ff1 100644 --- a/temporalio/contrib/langsmith/_plugin.py +++ b/temporalio/contrib/langsmith/_plugin.py @@ -73,6 +73,7 @@ def workflow_runner(runner: WorkflowRunner | None) -> WorkflowRunner: restrictions=runner.restrictions.with_passthrough_modules( "langsmith", "langchain_core", + "opentelemetry", ), ) return runner diff --git a/uv.lock b/uv.lock index 985872473..256651ff7 100644 --- a/uv.lock +++ b/uv.lock @@ -9,7 +9,7 @@ resolution-markers = [ ] [options] -exclude-newer = "0001-01-01T00:00:00Z" # This has no effect and is included for backwards compatibility when using relative exclude-newer values. +exclude-newer = "2026-05-07T19:04:44.331561Z" exclude-newer-span = "P1W" [options.exclude-newer-package] @@ -2560,7 +2560,7 @@ wheels = [ [[package]] name = "langsmith" -version = "0.7.33" +version = "0.7.38" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "httpx" }, @@ -2573,9 +2573,9 @@ dependencies = [ { name = "xxhash" }, { name = "zstandard" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/6f/75/1ee27b3510bf5b1b569b9695c9466c256caab45885bd569c0c67720236ad/langsmith-0.7.33.tar.gz", hash = "sha256:fa2d81ad6e8374a81fda9291894f6fcae714e55fbf11a0b07578e3cd4b1ea384", size = 1186298, upload-time = "2026-04-20T16:17:54.583Z" } +sdist = { url = "https://files.pythonhosted.org/packages/af/c9/b3e54cfcb480876dfe33ecfdd64feeb621a86d9e6f4a6b9eb46851807018/langsmith-0.7.38.tar.gz", hash = "sha256:0db529b768d66c45f22fe959a0af7151342704fefafdecf3c60b14097c14fdb1", size = 4431914, upload-time = "2026-04-29T00:21:42.865Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/f4/76/53033db34ffccd25d62c32b23b9468f7228b455da6976e1c420ae31555c4/langsmith-0.7.33-py3-none-any.whl", hash = "sha256:5b535b991d52d3b664ebb8dc6f95afcf8d0acb42e062ac45a54a6a4820139f20", size = 378981, upload-time = "2026-04-20T16:17:52.503Z" }, + { url = "https://files.pythonhosted.org/packages/86/bc/a19d0a6d5575c637796675831dbef3555568e84d913f14ec579f92162ffa/langsmith-0.7.38-py3-none-any.whl", hash = "sha256:9c400ad508c0e4edc37bd55987047c6b8aac36ddd55f6096e3806f4d6a100618", size = 392310, upload-time = "2026-04-29T00:21:40.534Z" }, ] [[package]] @@ -5239,7 +5239,7 @@ requires-dist = [ { name = "google-adk", marker = "extra == 'google-adk'", specifier = ">=1.27.0,<2" }, { name = "grpcio", marker = "extra == 'grpc'", specifier = ">=1.48.2,<2" }, { name = "langgraph", marker = "extra == 'langgraph'", specifier = ">=1.1.0" }, - { name = "langsmith", marker = "extra == 'langsmith'", specifier = ">=0.7.0,<0.8" }, + { name = "langsmith", marker = "extra == 'langsmith'", specifier = ">=0.7.34,<0.8" }, { name = "mcp", marker = "extra == 'openai-agents'", specifier = ">=1.9.4,<2" }, { name = "nexus-rpc", specifier = "==1.4.0" }, { name = "openai-agents", marker = "extra == 'openai-agents'", specifier = ">=0.17.1" }, @@ -5268,7 +5268,7 @@ dev = [ { name = "grpcio-tools", specifier = ">=1.48.2,<2" }, { name = "httpx", specifier = ">=0.28.1" }, { name = "langgraph", specifier = ">=1.1.0" }, - { name = "langsmith", specifier = ">=0.7.0,<0.7.34" }, + { name = "langsmith", specifier = ">=0.7.34,<0.8" }, { name = "litellm", specifier = ">=1.83.0" }, { name = "maturin", specifier = ">=1.8.2" }, { name = "moto", extras = ["s3", "server"], specifier = ">=5" }, From 25059fa4eab88efe51ec2f2560a999144d65f33e Mon Sep 17 00:00:00 2001 From: Maciej Dudkowski Date: Mon, 18 May 2026 13:41:24 -0400 Subject: [PATCH 090/226] (CI) Disable caching cargo binaries (#1537) --- .github/workflows/build-binaries.yml | 1 + .github/workflows/ci.yml | 4 ++++ .github/workflows/nightly-throughput-stress.yml | 1 + .github/workflows/run-bench.yml | 1 + 4 files changed, 7 insertions(+) diff --git a/.github/workflows/build-binaries.yml b/.github/workflows/build-binaries.yml index 1b1f2370d..fb565aaf1 100644 --- a/.github/workflows/build-binaries.yml +++ b/.github/workflows/build-binaries.yml @@ -45,6 +45,7 @@ jobs: - if: ${{ runner.os != 'Linux' }} uses: Swatinem/rust-cache@e18b497796c12c097a38f9edb9d0641fb99eee32 # v2 with: + cache-bin: false workspaces: temporalio/bridge -> target - uses: astral-sh/setup-uv@cec208311dfd045dd5311c1add060b2062131d57 # v8 - run: uv sync --all-extras diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 6294f6d9a..59282e249 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -46,6 +46,7 @@ jobs: components: "clippy" - uses: Swatinem/rust-cache@e18b497796c12c097a38f9edb9d0641fb99eee32 # v2 with: + cache-bin: false workspaces: temporalio/bridge -> target - uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5 with: @@ -111,6 +112,7 @@ jobs: - uses: dtolnay/rust-toolchain@29eef336d9b2848a0b548edc03f92a220660cdb8 # stable - uses: Swatinem/rust-cache@e18b497796c12c097a38f9edb9d0641fb99eee32 # v2 with: + cache-bin: false workspaces: temporalio/bridge -> target - uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5 with: @@ -147,6 +149,7 @@ jobs: components: "clippy" - uses: Swatinem/rust-cache@e18b497796c12c097a38f9edb9d0641fb99eee32 # v2 with: + cache-bin: false workspaces: temporalio/bridge -> target - uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5 with: @@ -185,6 +188,7 @@ jobs: - uses: dtolnay/rust-toolchain@29eef336d9b2848a0b548edc03f92a220660cdb8 # stable - uses: Swatinem/rust-cache@e18b497796c12c097a38f9edb9d0641fb99eee32 # v2 with: + cache-bin: false workspaces: temporalio/bridge -> target - uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5 with: diff --git a/.github/workflows/nightly-throughput-stress.yml b/.github/workflows/nightly-throughput-stress.yml index 65d71bf8d..46d33eb77 100644 --- a/.github/workflows/nightly-throughput-stress.yml +++ b/.github/workflows/nightly-throughput-stress.yml @@ -91,6 +91,7 @@ jobs: - name: Setup Rust cache uses: Swatinem/rust-cache@e18b497796c12c097a38f9edb9d0641fb99eee32 # v2 with: + cache-bin: false workspaces: temporalio/bridge -> target - name: Setup Python diff --git a/.github/workflows/run-bench.yml b/.github/workflows/run-bench.yml index a5a874a30..eb2868bb2 100644 --- a/.github/workflows/run-bench.yml +++ b/.github/workflows/run-bench.yml @@ -37,6 +37,7 @@ jobs: toolchain: stable - uses: Swatinem/rust-cache@e18b497796c12c097a38f9edb9d0641fb99eee32 # v2 with: + cache-bin: false workspaces: temporalio/bridge -> target - uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5 with: From 1e6dff4522a16112b57b1331839340b0711bdd7f Mon Sep 17 00:00:00 2001 From: tconley1428 Date: Mon, 18 May 2026 11:35:36 -0700 Subject: [PATCH 091/226] Refactor client module into package (#1530) * Refactor client module into package * Restore client compatibility reexports * Add client export compatibility test * Format client export test * Update test_client_exports.py --- temporalio/client.py | 10011 ---------------------- temporalio/client/__init__.py | 346 + temporalio/client/_activity.py | 913 ++ temporalio/client/_callback.py | 5 + temporalio/client/_client.py | 2898 +++++++ temporalio/client/_cloud.py | 181 + temporalio/client/_exceptions.py | 139 + temporalio/client/_helpers.py | 202 + temporalio/client/_impl.py | 1410 +++ temporalio/client/_interceptor.py | 783 ++ temporalio/client/_plugin.py | 75 + temporalio/client/_schedule.py | 1604 ++++ temporalio/client/_worker_versioning.py | 278 + temporalio/client/_workflow.py | 2000 +++++ tests/test_client_exports.py | 216 + 15 files changed, 11050 insertions(+), 10011 deletions(-) delete mode 100644 temporalio/client.py create mode 100644 temporalio/client/__init__.py create mode 100644 temporalio/client/_activity.py create mode 100644 temporalio/client/_callback.py create mode 100644 temporalio/client/_client.py create mode 100644 temporalio/client/_cloud.py create mode 100644 temporalio/client/_exceptions.py create mode 100644 temporalio/client/_helpers.py create mode 100644 temporalio/client/_impl.py create mode 100644 temporalio/client/_interceptor.py create mode 100644 temporalio/client/_plugin.py create mode 100644 temporalio/client/_schedule.py create mode 100644 temporalio/client/_worker_versioning.py create mode 100644 temporalio/client/_workflow.py create mode 100644 tests/test_client_exports.py diff --git a/temporalio/client.py b/temporalio/client.py deleted file mode 100644 index ff7ae4314..000000000 --- a/temporalio/client.py +++ /dev/null @@ -1,10011 +0,0 @@ -"""Client for accessing Temporal.""" - -from __future__ import annotations - -import abc -import asyncio -import copy -import dataclasses -import functools -import inspect -import json -import re -import uuid -import warnings -from abc import ABC, abstractmethod -from asyncio import Future -from collections.abc import ( - AsyncIterator, - Awaitable, - Callable, - Iterable, - Mapping, - Sequence, -) -from dataclasses import dataclass -from datetime import datetime, timedelta, timezone -from enum import Enum, IntEnum -from typing import ( - Any, - Concatenate, - Generic, - cast, - overload, -) - -import google.protobuf.duration_pb2 -import google.protobuf.json_format -import google.protobuf.timestamp_pb2 -from google.protobuf.internal.containers import MessageMap -from typing_extensions import Required, Self, TypedDict - -import temporalio.activity -import temporalio.api.activity.v1 -import temporalio.api.common.v1 -import temporalio.api.enums.v1 -import temporalio.api.errordetails.v1 -import temporalio.api.failure.v1 -import temporalio.api.history.v1 -import temporalio.api.schedule.v1 -import temporalio.api.sdk.v1 -import temporalio.api.taskqueue.v1 -import temporalio.api.update.v1 -import temporalio.api.workflow.v1 -import temporalio.api.workflowservice.v1 -import temporalio.common -import temporalio.converter -import temporalio.converter._search_attributes -import temporalio.exceptions -import temporalio.nexus -import temporalio.nexus._operation_context -import temporalio.runtime -import temporalio.service -import temporalio.workflow -from temporalio.activity import ActivityCancellationDetails -from temporalio.converter import ( - ActivitySerializationContext, - DataConverter, - SerializationContext, - StorageDriverActivityInfo, - StorageDriverStoreContext, - StorageDriverWorkflowInfo, - WithSerializationContext, - WorkflowSerializationContext, -) -from temporalio.service import ( - ConnectConfig, - DnsLoadBalancingConfig, - HttpConnectProxyConfig, - KeepAliveConfig, - RetryConfig, - RPCError, - RPCStatusCode, - ServiceClient, - TLSConfig, -) - -from .common import HeaderCodecBehavior -from .types import ( - AnyType, - CallableAsyncNoParam, - CallableAsyncSingleParam, - CallableSyncNoParam, - CallableSyncSingleParam, - LocalReturnType, - MethodAsyncNoParam, - MethodAsyncSingleParam, - MethodSyncOrAsyncNoParam, - MethodSyncOrAsyncSingleParam, - MultiParamSpec, - ParamType, - ReturnType, - SelfType, -) - - -class Client: - """Client for accessing Temporal. - - Most users will use :py:meth:`connect` to create a client. The - :py:attr:`service` property provides access to a raw gRPC client. To create - another client, like for a different namespace, :py:func:`Client` may be - directly instantiated with a :py:attr:`service` of another. - - Clients are not thread-safe and should only be used in the event loop they - are first connected in. If a client needs to be used from another thread - than where it was created, make sure the event loop where it was created is - captured, and then call :py:func:`asyncio.run_coroutine_threadsafe` with the - client call and that event loop. - - Clients do not work across forks since runtimes do not work across forks. - """ - - @classmethod - async def connect( - cls, - target_host: str, - *, - namespace: str = "default", - api_key: str | None = None, - data_converter: temporalio.converter.DataConverter = temporalio.converter.DataConverter.default, - plugins: Sequence[Plugin] = [], - interceptors: Sequence[Interceptor] = [], - default_workflow_query_reject_condition: None - | (temporalio.common.QueryRejectCondition) = None, - tls: bool | TLSConfig | None = None, - retry_config: RetryConfig | None = None, - keep_alive_config: KeepAliveConfig | None = KeepAliveConfig.default, - rpc_metadata: Mapping[str, str | bytes] = {}, - identity: str | None = None, - lazy: bool = False, - runtime: temporalio.runtime.Runtime | None = None, - http_connect_proxy_config: HttpConnectProxyConfig | None = None, - dns_load_balancing_config: DnsLoadBalancingConfig | None = None, - header_codec_behavior: HeaderCodecBehavior = HeaderCodecBehavior.NO_CODEC, - ) -> Self: - """Connect to a Temporal server. - - Args: - target_host: ``host:port`` for the Temporal server. For local - development, this is often "localhost:7233". - namespace: Namespace to use for client calls. - api_key: API key for Temporal. This becomes the "Authorization" - HTTP header with "Bearer " prepended. This is only set if RPC - metadata doesn't already have an "authorization" key. - data_converter: Data converter to use for all data conversions - to/from payloads. - plugins: Set of plugins that are chained together to allow - intercepting and modifying client creation and service connection. - The earlier plugins wrap the later ones. - - Any plugins that also implement - :py:class:`temporalio.worker.Plugin` will be used as worker - plugins too so they should not be given when creating a - worker. - interceptors: Set of interceptors that are chained together to allow - intercepting of client calls. The earlier interceptors wrap the - later ones. - - Any interceptors that also implement - :py:class:`temporalio.worker.Interceptor` will be used as worker - interceptors too so they should not be given when creating a - worker. - default_workflow_query_reject_condition: The default rejection - condition for workflow queries if not set during query. See - :py:meth:`WorkflowHandle.query` for details on the rejection - condition. - tls: If ``None``, the default, TLS will be enabled automatically - when ``api_key`` is provided, otherwise TLS is disabled. If - ``False``, do not use TLS. If ``True``, use system default TLS - configuration. If TLS configuration present, that TLS - configuration will be used. - retry_config: Retry configuration for direct service calls (when - opted in) or all high-level calls made by this client (which all - opt-in to retries by default). If unset, a default retry - configuration is used. - keep_alive_config: Keep-alive configuration for the client - connection. Default is to check every 30s and kill the - connection if a response doesn't come back in 15s. Can be set to - ``None`` to disable. - rpc_metadata: Headers to use for all calls to the server. Keys here - can be overriden by per-call RPC metadata keys. - identity: Identity for this client. If unset, a default is created - based on the version of the SDK. - lazy: If true, the client will not connect until the first call is - attempted or a worker is created with it. Lazy clients cannot be - used for workers. - runtime: The runtime for this client, or the default if unset. - http_connect_proxy_config: Configuration for HTTP CONNECT proxy. - dns_load_balancing_config: DNS load balancing configuration for the - client connection. Default is to re-resolve DNS every 30s. Can - be set to ``None`` to disable. Silently disabled when - ``http_connect_proxy_config`` is set, since the two are mutually - exclusive. - header_codec_behavior: Encoding behavior for headers sent by the client. - """ - connect_config = temporalio.service.ConnectConfig( - target_host=target_host, - api_key=api_key, - tls=tls, - retry_config=retry_config, - keep_alive_config=keep_alive_config, - rpc_metadata=rpc_metadata, - identity=identity or "", - lazy=lazy, - runtime=runtime, - http_connect_proxy_config=http_connect_proxy_config, - dns_load_balancing_config=dns_load_balancing_config, - ) - - def make_lambda( - plugin: Plugin, next: Callable[[ConnectConfig], Awaitable[ServiceClient]] - ): - return lambda config: plugin.connect_service_client(config, next) - - next_function = ServiceClient.connect - for plugin in reversed(plugins): - next_function = make_lambda(plugin, next_function) - - service_client = await next_function(connect_config) - - return cls( - service_client, - namespace=namespace, - data_converter=data_converter, - interceptors=interceptors, - default_workflow_query_reject_condition=default_workflow_query_reject_condition, - header_codec_behavior=header_codec_behavior, - plugins=plugins, - ) - - def __init__( - self, - service_client: temporalio.service.ServiceClient, - *, - namespace: str = "default", - data_converter: temporalio.converter.DataConverter = temporalio.converter.DataConverter.default, - plugins: Sequence[Plugin] = [], - interceptors: Sequence[Interceptor] = [], - default_workflow_query_reject_condition: None - | (temporalio.common.QueryRejectCondition) = None, - header_codec_behavior: HeaderCodecBehavior = HeaderCodecBehavior.NO_CODEC, - ): - """Create a Temporal client from a service client. - - See :py:meth:`connect` for details on the parameters. - """ - # Store the config for tracking - config = ClientConfig( - service_client=service_client, - namespace=namespace, - data_converter=data_converter, - plugins=plugins, - interceptors=interceptors, - default_workflow_query_reject_condition=default_workflow_query_reject_condition, - header_codec_behavior=header_codec_behavior, - ) - self._initial_config = config.copy() - - for plugin in plugins: - config = plugin.configure_client(config) - - self._init_from_config(config) - - def _init_from_config(self, config: ClientConfig): - self._config = config - - # Iterate over interceptors in reverse building the impl - self._impl: OutboundInterceptor = _ClientImpl(self) - for interceptor in reversed(list(self._config["interceptors"])): - self._impl = interceptor.intercept_client(self._impl) - - def config(self, *, active_config: bool = False) -> ClientConfig: - """Config, as a dictionary, used to create this client. - - Args: - active_config: If true, return the modified configuration in use rather than the initial one - provided to the client. - - This makes a shallow copy of the config each call. - """ - config = self._config.copy() if active_config else self._initial_config.copy() - config["interceptors"] = list(config["interceptors"]) - return config - - @property - def service_client(self) -> temporalio.service.ServiceClient: - """Raw gRPC service client.""" - return self._config["service_client"] - - @property - def workflow_service(self) -> temporalio.service.WorkflowService: - """Raw gRPC workflow service client.""" - return self._config["service_client"].workflow_service - - @property - def operator_service(self) -> temporalio.service.OperatorService: - """Raw gRPC operator service client.""" - return self._config["service_client"].operator_service - - @property - def test_service(self) -> temporalio.service.TestService: - """Raw gRPC test service client.""" - return self._config["service_client"].test_service - - @property - def namespace(self) -> str: - """Namespace used in calls by this client.""" - return self._config["namespace"] - - @property - def identity(self) -> str: - """Identity used in calls by this client.""" - return self._config["service_client"].config.identity - - @property - def data_converter(self) -> temporalio.converter.DataConverter: - """Data converter used by this client.""" - return self._config["data_converter"] - - @property - def rpc_metadata(self) -> Mapping[str, str | bytes]: - """Headers for every call made by this client. - - Do not use mutate this mapping. Rather, set this property with an - entirely new mapping to change the headers. - """ - return self.service_client.config.rpc_metadata - - @rpc_metadata.setter - def rpc_metadata(self, value: Mapping[str, str | bytes]) -> None: - """Update the headers for this client. - - Do not mutate this mapping after set. Rather, set an entirely new - mapping if changes are needed. - - Raises: - TypeError: the key/value pair is not a valid gRPC ASCII or binary metadata. - All binary metadata must be supplied as bytes, and the key must end in '-bin'. - - .. warning:: - Attempting to set an invalid binary RPC metadata value may leave the client - in an inconsistent state (as well as raise a :py:class:`TypeError`). - """ - # Update config and perform update - # This may raise if the metadata is invalid: - self.service_client.update_rpc_metadata(value) - self.service_client.config.rpc_metadata = value - - @property - def api_key(self) -> str | None: - """API key for every call made by this client.""" - return self.service_client.config.api_key - - @api_key.setter - def api_key(self, value: str | None) -> None: - """Update the API key for this client. - - This is only set if RPCmetadata doesn't already have an "authorization" - key. - """ - # Update config and perform update - self.service_client.config.api_key = value - self.service_client.update_api_key(value) - - # Overload for no-param workflow - @overload - async def start_workflow( - self, - workflow: MethodAsyncNoParam[SelfType, ReturnType], - *, - id: str, - task_queue: str, - execution_timeout: timedelta | None = None, - run_timeout: timedelta | None = None, - task_timeout: timedelta | None = None, - id_reuse_policy: temporalio.common.WorkflowIDReusePolicy = temporalio.common.WorkflowIDReusePolicy.ALLOW_DUPLICATE, - id_conflict_policy: temporalio.common.WorkflowIDConflictPolicy = temporalio.common.WorkflowIDConflictPolicy.UNSPECIFIED, - retry_policy: temporalio.common.RetryPolicy | None = None, - cron_schedule: str = "", - memo: Mapping[str, Any] | None = None, - search_attributes: None - | ( - temporalio.common.TypedSearchAttributes | temporalio.common.SearchAttributes - ) = None, - static_summary: str | None = None, - static_details: str | None = None, - start_delay: timedelta | None = None, - start_signal: str | None = None, - start_signal_args: Sequence[Any] = [], - rpc_metadata: Mapping[str, str | bytes] = {}, - rpc_timeout: timedelta | None = None, - request_eager_start: bool = False, - priority: temporalio.common.Priority = temporalio.common.Priority.default, - versioning_override: temporalio.common.VersioningOverride | None = None, - ) -> WorkflowHandle[SelfType, ReturnType]: ... - - # Overload for single-param workflow - @overload - async def start_workflow( - self, - workflow: MethodAsyncSingleParam[SelfType, ParamType, ReturnType], - arg: ParamType, - *, - id: str, - task_queue: str, - execution_timeout: timedelta | None = None, - run_timeout: timedelta | None = None, - task_timeout: timedelta | None = None, - id_reuse_policy: temporalio.common.WorkflowIDReusePolicy = temporalio.common.WorkflowIDReusePolicy.ALLOW_DUPLICATE, - id_conflict_policy: temporalio.common.WorkflowIDConflictPolicy = temporalio.common.WorkflowIDConflictPolicy.UNSPECIFIED, - retry_policy: temporalio.common.RetryPolicy | None = None, - cron_schedule: str = "", - memo: Mapping[str, Any] | None = None, - search_attributes: None - | ( - temporalio.common.TypedSearchAttributes | temporalio.common.SearchAttributes - ) = None, - static_summary: str | None = None, - static_details: str | None = None, - start_delay: timedelta | None = None, - start_signal: str | None = None, - start_signal_args: Sequence[Any] = [], - rpc_metadata: Mapping[str, str | bytes] = {}, - rpc_timeout: timedelta | None = None, - request_eager_start: bool = False, - priority: temporalio.common.Priority = temporalio.common.Priority.default, - versioning_override: temporalio.common.VersioningOverride | None = None, - ) -> WorkflowHandle[SelfType, ReturnType]: ... - - # Overload for multi-param workflow - @overload - async def start_workflow( - self, - workflow: Callable[ - Concatenate[SelfType, MultiParamSpec], Awaitable[ReturnType] - ], - *, - args: Sequence[Any], - id: str, - task_queue: str, - execution_timeout: timedelta | None = None, - run_timeout: timedelta | None = None, - task_timeout: timedelta | None = None, - id_reuse_policy: temporalio.common.WorkflowIDReusePolicy = temporalio.common.WorkflowIDReusePolicy.ALLOW_DUPLICATE, - id_conflict_policy: temporalio.common.WorkflowIDConflictPolicy = temporalio.common.WorkflowIDConflictPolicy.UNSPECIFIED, - retry_policy: temporalio.common.RetryPolicy | None = None, - cron_schedule: str = "", - memo: Mapping[str, Any] | None = None, - search_attributes: None - | ( - temporalio.common.TypedSearchAttributes | temporalio.common.SearchAttributes - ) = None, - static_summary: str | None = None, - static_details: str | None = None, - start_delay: timedelta | None = None, - start_signal: str | None = None, - start_signal_args: Sequence[Any] = [], - rpc_metadata: Mapping[str, str | bytes] = {}, - rpc_timeout: timedelta | None = None, - request_eager_start: bool = False, - priority: temporalio.common.Priority = temporalio.common.Priority.default, - versioning_override: temporalio.common.VersioningOverride | None = None, - ) -> WorkflowHandle[SelfType, ReturnType]: ... - - # Overload for string-name workflow - @overload - async def start_workflow( - self, - workflow: str, - arg: Any = temporalio.common._arg_unset, - *, - args: Sequence[Any] = [], - id: str, - task_queue: str, - result_type: type | None = None, - execution_timeout: timedelta | None = None, - run_timeout: timedelta | None = None, - task_timeout: timedelta | None = None, - id_reuse_policy: temporalio.common.WorkflowIDReusePolicy = temporalio.common.WorkflowIDReusePolicy.ALLOW_DUPLICATE, - id_conflict_policy: temporalio.common.WorkflowIDConflictPolicy = temporalio.common.WorkflowIDConflictPolicy.UNSPECIFIED, - retry_policy: temporalio.common.RetryPolicy | None = None, - cron_schedule: str = "", - memo: Mapping[str, Any] | None = None, - search_attributes: None - | ( - temporalio.common.TypedSearchAttributes | temporalio.common.SearchAttributes - ) = None, - static_summary: str | None = None, - static_details: str | None = None, - start_delay: timedelta | None = None, - start_signal: str | None = None, - start_signal_args: Sequence[Any] = [], - rpc_metadata: Mapping[str, str | bytes] = {}, - rpc_timeout: timedelta | None = None, - request_eager_start: bool = False, - priority: temporalio.common.Priority = temporalio.common.Priority.default, - versioning_override: temporalio.common.VersioningOverride | None = None, - ) -> WorkflowHandle[Any, Any]: ... - - async def start_workflow( - self, - workflow: str | Callable[..., Awaitable[Any]], - arg: Any = temporalio.common._arg_unset, - *, - args: Sequence[Any] = [], - id: str, - task_queue: str, - result_type: type | None = None, - execution_timeout: timedelta | None = None, - run_timeout: timedelta | None = None, - task_timeout: timedelta | None = None, - id_reuse_policy: temporalio.common.WorkflowIDReusePolicy = temporalio.common.WorkflowIDReusePolicy.ALLOW_DUPLICATE, - id_conflict_policy: temporalio.common.WorkflowIDConflictPolicy = temporalio.common.WorkflowIDConflictPolicy.UNSPECIFIED, - retry_policy: temporalio.common.RetryPolicy | None = None, - cron_schedule: str = "", - memo: Mapping[str, Any] | None = None, - search_attributes: None - | ( - temporalio.common.TypedSearchAttributes | temporalio.common.SearchAttributes - ) = None, - static_summary: str | None = None, - static_details: str | None = None, - start_delay: timedelta | None = None, - start_signal: str | None = None, - start_signal_args: Sequence[Any] = [], - rpc_metadata: Mapping[str, str | bytes] = {}, - rpc_timeout: timedelta | None = None, - request_eager_start: bool = False, - priority: temporalio.common.Priority = temporalio.common.Priority.default, - versioning_override: temporalio.common.VersioningOverride | None = None, - # The following options should not be considered part of the public API. They - # are deliberately not exposed in overloads, and are not subject to any - # backwards compatibility guarantees. - callbacks: Sequence[Callback] = [], - workflow_event_links: Sequence[ - temporalio.api.common.v1.Link.WorkflowEvent - ] = [], - request_id: str | None = None, - stack_level: int = 2, - ) -> WorkflowHandle[Any, Any]: - """Start a workflow and return its handle. - - Args: - workflow: String name or class method decorated with - ``@workflow.run`` for the workflow to start. - arg: Single argument to the workflow. - args: Multiple arguments to the workflow. Cannot be set if arg is. - id: Unique identifier for the workflow execution. - task_queue: Task queue to run the workflow on. - result_type: For string workflows, this can set the specific result - type hint to deserialize into. - execution_timeout: Total workflow execution timeout including - retries and continue as new. - run_timeout: Timeout of a single workflow run. - task_timeout: Timeout of a single workflow task. - id_conflict_policy: Behavior when a workflow is currently running with the same ID. - Default is UNSPECIFIED, which effectively means fail the start attempt. - Set to USE_EXISTING for idempotent deduplication on workflow ID. - Cannot be set if ``id_reuse_policy`` is set to TERMINATE_IF_RUNNING. - id_reuse_policy: Behavior when a closed workflow with the same ID exists. - Default is ALLOW_DUPLICATE. - retry_policy: Retry policy for the workflow. - cron_schedule: See https://docs.temporal.io/docs/content/what-is-a-temporal-cron-job/ - memo: Memo for the workflow. - search_attributes: Search attributes for the workflow. The - dictionary form of this is deprecated, use - :py:class:`temporalio.common.TypedSearchAttributes`. - static_summary: A single-line fixed summary for this workflow execution that may appear - in the UI/CLI. This can be in single-line Temporal markdown format. - static_details: General fixed details for this workflow execution that may appear in - UI/CLI. This can be in Temporal markdown format and can span multiple lines. This is - a fixed value on the workflow that cannot be updated. For details that can be - updated, use :py:meth:`temporalio.workflow.get_current_details` within the workflow. - start_delay: Amount of time to wait before starting the workflow. - This does not work with ``cron_schedule``. - start_signal: If present, this signal is sent as signal-with-start - instead of traditional workflow start. - start_signal_args: Arguments for start_signal if start_signal - present. - rpc_metadata: Headers used on the RPC call. Keys here override - client-level RPC metadata keys. - rpc_timeout: Optional RPC deadline to set for the RPC call. - request_eager_start: Potentially reduce the latency to start this workflow by - encouraging the server to start it on a local worker running with - this same client. - priority: Priority of the workflow execution. - versioning_override: Overrides the versioning behavior for this workflow. - - Returns: - A workflow handle to the started workflow. - - Raises: - temporalio.exceptions.WorkflowAlreadyStartedError: Workflow has - already been started. - RPCError: Workflow could not be started for some other reason. - """ - temporalio.common._warn_on_deprecated_search_attributes( - search_attributes, stack_level=stack_level - ) - name, result_type_from_type_hint = ( - temporalio.workflow._Definition.get_name_and_result_type(workflow) - ) - return await self._impl.start_workflow( - StartWorkflowInput( - workflow=name, - args=temporalio.common._arg_or_args(arg, args), - id=id, - task_queue=task_queue, - execution_timeout=execution_timeout, - run_timeout=run_timeout, - task_timeout=task_timeout, - id_reuse_policy=id_reuse_policy, - id_conflict_policy=id_conflict_policy, - retry_policy=retry_policy, - cron_schedule=cron_schedule, - memo=memo, - search_attributes=search_attributes, - start_delay=start_delay, - versioning_override=versioning_override, - headers={}, - static_summary=static_summary, - static_details=static_details, - start_signal=start_signal, - start_signal_args=start_signal_args, - ret_type=result_type or result_type_from_type_hint, - rpc_metadata=rpc_metadata, - rpc_timeout=rpc_timeout, - request_eager_start=request_eager_start, - priority=priority, - callbacks=callbacks, - workflow_event_links=workflow_event_links, - request_id=request_id, - ) - ) - - # Overload for no-param workflow - @overload - async def execute_workflow( - self, - workflow: MethodAsyncNoParam[SelfType, ReturnType], - *, - id: str, - task_queue: str, - execution_timeout: timedelta | None = None, - run_timeout: timedelta | None = None, - task_timeout: timedelta | None = None, - id_reuse_policy: temporalio.common.WorkflowIDReusePolicy = temporalio.common.WorkflowIDReusePolicy.ALLOW_DUPLICATE, - id_conflict_policy: temporalio.common.WorkflowIDConflictPolicy = temporalio.common.WorkflowIDConflictPolicy.UNSPECIFIED, - retry_policy: temporalio.common.RetryPolicy | None = None, - cron_schedule: str = "", - memo: Mapping[str, Any] | None = None, - search_attributes: None - | ( - temporalio.common.TypedSearchAttributes | temporalio.common.SearchAttributes - ) = None, - static_summary: str | None = None, - static_details: str | None = None, - start_delay: timedelta | None = None, - start_signal: str | None = None, - start_signal_args: Sequence[Any] = [], - rpc_metadata: Mapping[str, str | bytes] = {}, - rpc_timeout: timedelta | None = None, - request_eager_start: bool = False, - priority: temporalio.common.Priority = temporalio.common.Priority.default, - versioning_override: temporalio.common.VersioningOverride | None = None, - ) -> ReturnType: ... - - # Overload for single-param workflow - @overload - async def execute_workflow( - self, - workflow: MethodAsyncSingleParam[SelfType, ParamType, ReturnType], - arg: ParamType, - *, - id: str, - task_queue: str, - execution_timeout: timedelta | None = None, - run_timeout: timedelta | None = None, - task_timeout: timedelta | None = None, - id_reuse_policy: temporalio.common.WorkflowIDReusePolicy = temporalio.common.WorkflowIDReusePolicy.ALLOW_DUPLICATE, - id_conflict_policy: temporalio.common.WorkflowIDConflictPolicy = temporalio.common.WorkflowIDConflictPolicy.UNSPECIFIED, - retry_policy: temporalio.common.RetryPolicy | None = None, - cron_schedule: str = "", - memo: Mapping[str, Any] | None = None, - search_attributes: None - | ( - temporalio.common.TypedSearchAttributes | temporalio.common.SearchAttributes - ) = None, - static_summary: str | None = None, - static_details: str | None = None, - start_delay: timedelta | None = None, - start_signal: str | None = None, - start_signal_args: Sequence[Any] = [], - rpc_metadata: Mapping[str, str | bytes] = {}, - rpc_timeout: timedelta | None = None, - request_eager_start: bool = False, - priority: temporalio.common.Priority = temporalio.common.Priority.default, - versioning_override: temporalio.common.VersioningOverride | None = None, - ) -> ReturnType: ... - - # Overload for multi-param workflow - @overload - async def execute_workflow( - self, - workflow: Callable[ - Concatenate[SelfType, MultiParamSpec], Awaitable[ReturnType] - ], - *, - args: Sequence[Any], - id: str, - task_queue: str, - execution_timeout: timedelta | None = None, - run_timeout: timedelta | None = None, - task_timeout: timedelta | None = None, - id_reuse_policy: temporalio.common.WorkflowIDReusePolicy = temporalio.common.WorkflowIDReusePolicy.ALLOW_DUPLICATE, - id_conflict_policy: temporalio.common.WorkflowIDConflictPolicy = temporalio.common.WorkflowIDConflictPolicy.UNSPECIFIED, - retry_policy: temporalio.common.RetryPolicy | None = None, - cron_schedule: str = "", - memo: Mapping[str, Any] | None = None, - search_attributes: None - | ( - temporalio.common.TypedSearchAttributes | temporalio.common.SearchAttributes - ) = None, - static_summary: str | None = None, - static_details: str | None = None, - start_delay: timedelta | None = None, - start_signal: str | None = None, - start_signal_args: Sequence[Any] = [], - rpc_metadata: Mapping[str, str | bytes] = {}, - rpc_timeout: timedelta | None = None, - request_eager_start: bool = False, - priority: temporalio.common.Priority = temporalio.common.Priority.default, - versioning_override: temporalio.common.VersioningOverride | None = None, - ) -> ReturnType: ... - - # Overload for string-name workflow - @overload - async def execute_workflow( - self, - workflow: str, - arg: Any = temporalio.common._arg_unset, - *, - args: Sequence[Any] = [], - id: str, - task_queue: str, - result_type: type | None = None, - execution_timeout: timedelta | None = None, - run_timeout: timedelta | None = None, - task_timeout: timedelta | None = None, - id_reuse_policy: temporalio.common.WorkflowIDReusePolicy = temporalio.common.WorkflowIDReusePolicy.ALLOW_DUPLICATE, - id_conflict_policy: temporalio.common.WorkflowIDConflictPolicy = temporalio.common.WorkflowIDConflictPolicy.UNSPECIFIED, - retry_policy: temporalio.common.RetryPolicy | None = None, - cron_schedule: str = "", - memo: Mapping[str, Any] | None = None, - search_attributes: None - | ( - temporalio.common.TypedSearchAttributes | temporalio.common.SearchAttributes - ) = None, - static_summary: str | None = None, - static_details: str | None = None, - start_delay: timedelta | None = None, - start_signal: str | None = None, - start_signal_args: Sequence[Any] = [], - rpc_metadata: Mapping[str, str | bytes] = {}, - rpc_timeout: timedelta | None = None, - request_eager_start: bool = False, - priority: temporalio.common.Priority = temporalio.common.Priority.default, - versioning_override: temporalio.common.VersioningOverride | None = None, - ) -> Any: ... - - async def execute_workflow( - self, - workflow: str | Callable[..., Awaitable[Any]], - arg: Any = temporalio.common._arg_unset, - *, - args: Sequence[Any] = [], - id: str, - task_queue: str, - result_type: type | None = None, - execution_timeout: timedelta | None = None, - run_timeout: timedelta | None = None, - task_timeout: timedelta | None = None, - id_reuse_policy: temporalio.common.WorkflowIDReusePolicy = temporalio.common.WorkflowIDReusePolicy.ALLOW_DUPLICATE, - id_conflict_policy: temporalio.common.WorkflowIDConflictPolicy = temporalio.common.WorkflowIDConflictPolicy.UNSPECIFIED, - retry_policy: temporalio.common.RetryPolicy | None = None, - cron_schedule: str = "", - memo: Mapping[str, Any] | None = None, - search_attributes: None - | ( - temporalio.common.TypedSearchAttributes | temporalio.common.SearchAttributes - ) = None, - static_summary: str | None = None, - static_details: str | None = None, - start_delay: timedelta | None = None, - start_signal: str | None = None, - start_signal_args: Sequence[Any] = [], - rpc_metadata: Mapping[str, str | bytes] = {}, - rpc_timeout: timedelta | None = None, - request_eager_start: bool = False, - priority: temporalio.common.Priority = temporalio.common.Priority.default, - versioning_override: temporalio.common.VersioningOverride | None = None, - ) -> Any: - """Start a workflow and wait for completion. - - This is a shortcut for :py:meth:`start_workflow` + - :py:meth:`WorkflowHandle.result`. - """ - return await ( - # We have to tell MyPy to ignore errors here because we want to call - # the non-@overload form of this and MyPy does not support that - await self.start_workflow( # type: ignore - workflow, # type: ignore[arg-type] - arg, - args=args, - task_queue=task_queue, - result_type=result_type, - id=id, - execution_timeout=execution_timeout, - run_timeout=run_timeout, - task_timeout=task_timeout, - id_reuse_policy=id_reuse_policy, - id_conflict_policy=id_conflict_policy, - retry_policy=retry_policy, - cron_schedule=cron_schedule, - memo=memo, - search_attributes=search_attributes, - static_summary=static_summary, - static_details=static_details, - start_delay=start_delay, - start_signal=start_signal, - start_signal_args=start_signal_args, - rpc_metadata=rpc_metadata, - rpc_timeout=rpc_timeout, - request_eager_start=request_eager_start, - priority=priority, - versioning_override=versioning_override, - stack_level=3, - ) - ).result() - - def get_workflow_handle( - self, - workflow_id: str, - *, - run_id: str | None = None, - first_execution_run_id: str | None = None, - result_type: type | None = None, - ) -> WorkflowHandle[Any, Any]: - """Get a workflow handle to an existing workflow by its ID. - - Args: - workflow_id: Workflow ID to get a handle to. - run_id: Run ID that will be used for all calls. - first_execution_run_id: First execution run ID used for cancellation - and termination. - result_type: The result type to deserialize into if known. - - Returns: - The workflow handle. - """ - return WorkflowHandle( - self, - workflow_id, - run_id=run_id, - result_run_id=run_id, - first_execution_run_id=first_execution_run_id, - result_type=result_type, - ) - - def get_workflow_handle_for( - self, - workflow: ( - MethodAsyncNoParam[SelfType, ReturnType] - | MethodAsyncSingleParam[SelfType, Any, ReturnType] - ), - workflow_id: str, - *, - run_id: str | None = None, - first_execution_run_id: str | None = None, - ) -> WorkflowHandle[SelfType, ReturnType]: - """Get a typed workflow handle to an existing workflow by its ID. - - This is the same as :py:meth:`get_workflow_handle` but typed. - - Args: - workflow: The workflow run method to use for typing the handle. - workflow_id: Workflow ID to get a handle to. - run_id: Run ID that will be used for all calls. - first_execution_run_id: First execution run ID used for cancellation - and termination. - - Returns: - The workflow handle. - """ - defn = temporalio.workflow._Definition.must_from_run_fn(workflow) - return self.get_workflow_handle( - workflow_id, - run_id=run_id, - first_execution_run_id=first_execution_run_id, - result_type=defn.ret_type, - ) - - # Overload for no-param update - @overload - async def execute_update_with_start_workflow( - self, - update: temporalio.workflow.UpdateMethodMultiParam[[SelfType], LocalReturnType], - *, - start_workflow_operation: WithStartWorkflowOperation[SelfType, Any], - id: str | None = None, - rpc_metadata: Mapping[str, str | bytes] = {}, - rpc_timeout: timedelta | None = None, - ) -> LocalReturnType: ... - - # Overload for single-param update - @overload - async def execute_update_with_start_workflow( - self, - update: temporalio.workflow.UpdateMethodMultiParam[ - [SelfType, ParamType], LocalReturnType - ], - arg: ParamType, - *, - start_workflow_operation: WithStartWorkflowOperation[SelfType, Any], - id: str | None = None, - rpc_metadata: Mapping[str, str | bytes] = {}, - rpc_timeout: timedelta | None = None, - ) -> LocalReturnType: ... - - # Overload for multi-param update - @overload - async def execute_update_with_start_workflow( - self, - update: temporalio.workflow.UpdateMethodMultiParam[ - MultiParamSpec, LocalReturnType - ], - *, - args: MultiParamSpec.args, # type: ignore - start_workflow_operation: WithStartWorkflowOperation[SelfType, Any], - id: str | None = None, - rpc_metadata: Mapping[str, str | bytes] = {}, - rpc_timeout: timedelta | None = None, - ) -> LocalReturnType: ... - - # Overload for string-name update - @overload - async def execute_update_with_start_workflow( - self, - update: str, - arg: Any = temporalio.common._arg_unset, - *, - start_workflow_operation: WithStartWorkflowOperation[Any, Any], - args: Sequence[Any] = [], - id: str | None = None, - result_type: type | None = None, - rpc_metadata: Mapping[str, str | bytes] = {}, - rpc_timeout: timedelta | None = None, - ) -> Any: ... - - async def execute_update_with_start_workflow( - self, - update: str | Callable, - arg: Any = temporalio.common._arg_unset, - *, - start_workflow_operation: WithStartWorkflowOperation[Any, Any], - args: Sequence[Any] = [], - id: str | None = None, - result_type: type | None = None, - rpc_metadata: Mapping[str, str | bytes] = {}, - rpc_timeout: timedelta | None = None, - ) -> Any: - """Send an update-with-start request and wait for the update to complete. - - A WorkflowIDConflictPolicy must be set in the start_workflow_operation. If the - specified workflow execution is not running, a new workflow execution is started - and the update is sent in the first workflow task. Alternatively if the specified - workflow execution is running then, if the WorkflowIDConflictPolicy is - USE_EXISTING, the update is issued against the specified workflow, and if the - WorkflowIDConflictPolicy is FAIL, an error is returned. This call will block until - the update has completed, and return the update result. Note that this means that - the call will not return successfully until the update has been delivered to a - worker. - - Args: - update: Update function or name on the workflow. arg: Single argument to the - update. - args: Multiple arguments to the update. Cannot be set if arg is. - start_workflow_operation: a WithStartWorkflowOperation definining the - WorkflowIDConflictPolicy and how to start the workflow in the event that a - workflow is started. - id: ID of the update. If not set, the default is a new UUID. - result_type: For string updates, this can set the specific result - type hint to deserialize into. - rpc_metadata: Headers used on the RPC call. Keys here override - client-level RPC metadata keys. - rpc_timeout: Optional RPC deadline to set for the RPC call. - - Raises: - WorkflowUpdateFailedError: If the update failed. - WorkflowUpdateRPCTimeoutOrCancelledError: This update call timed out - or was cancelled. This doesn't mean the update itself was timed out or - cancelled. - - RPCError: There was some issue starting the workflow or sending the update to - the workflow. - """ - handle = await self._start_update_with_start( - update, - arg, - args=args, - start_workflow_operation=start_workflow_operation, - wait_for_stage=WorkflowUpdateStage.COMPLETED, - id=id, - result_type=result_type, - rpc_metadata=rpc_metadata, - rpc_timeout=rpc_timeout, - ) - return await handle.result() - - # Overload for no-param start update - @overload - async def start_update_with_start_workflow( - self, - update: temporalio.workflow.UpdateMethodMultiParam[[SelfType], LocalReturnType], - *, - start_workflow_operation: WithStartWorkflowOperation[SelfType, Any], - wait_for_stage: WorkflowUpdateStage, - id: str | None = None, - rpc_metadata: Mapping[str, str | bytes] = {}, - rpc_timeout: timedelta | None = None, - ) -> WorkflowUpdateHandle[LocalReturnType]: ... - - # Overload for single-param start update - @overload - async def start_update_with_start_workflow( - self, - update: temporalio.workflow.UpdateMethodMultiParam[ - [SelfType, ParamType], LocalReturnType - ], - arg: ParamType, - *, - start_workflow_operation: WithStartWorkflowOperation[SelfType, Any], - wait_for_stage: WorkflowUpdateStage, - id: str | None = None, - rpc_metadata: Mapping[str, str | bytes] = {}, - rpc_timeout: timedelta | None = None, - ) -> WorkflowUpdateHandle[LocalReturnType]: ... - - # Overload for multi-param start update - @overload - async def start_update_with_start_workflow( - self, - update: temporalio.workflow.UpdateMethodMultiParam[ - MultiParamSpec, LocalReturnType - ], - *, - args: MultiParamSpec.args, # type: ignore - start_workflow_operation: WithStartWorkflowOperation[SelfType, Any], - wait_for_stage: WorkflowUpdateStage, - id: str | None = None, - rpc_metadata: Mapping[str, str | bytes] = {}, - rpc_timeout: timedelta | None = None, - ) -> WorkflowUpdateHandle[LocalReturnType]: ... - - # Overload for string-name start update - @overload - async def start_update_with_start_workflow( - self, - update: str, - arg: Any = temporalio.common._arg_unset, - *, - start_workflow_operation: WithStartWorkflowOperation[Any, Any], - wait_for_stage: WorkflowUpdateStage, - args: Sequence[Any] = [], - id: str | None = None, - result_type: type | None = None, - rpc_metadata: Mapping[str, str | bytes] = {}, - rpc_timeout: timedelta | None = None, - ) -> WorkflowUpdateHandle[Any]: ... - - async def start_update_with_start_workflow( - self, - update: str | Callable, - arg: Any = temporalio.common._arg_unset, - *, - start_workflow_operation: WithStartWorkflowOperation[Any, Any], - wait_for_stage: WorkflowUpdateStage, - args: Sequence[Any] = [], - id: str | None = None, - result_type: type | None = None, - rpc_metadata: Mapping[str, str | bytes] = {}, - rpc_timeout: timedelta | None = None, - ) -> WorkflowUpdateHandle[Any]: - """Send an update-with-start request and wait for it to be accepted. - - A WorkflowIDConflictPolicy must be set in the start_workflow_operation. If the - specified workflow execution is not running, a new workflow execution is started - and the update is sent in the first workflow task. Alternatively if the specified - workflow execution is running then, if the WorkflowIDConflictPolicy is - USE_EXISTING, the update is issued against the specified workflow, and if the - WorkflowIDConflictPolicy is FAIL, an error is returned. This call will block until - the update has been accepted, and return a WorkflowUpdateHandle. Note that this - means that the call will not return successfully until the update has been - delivered to a worker. - - Args: - update: Update function or name on the workflow. arg: Single argument to the - update. - args: Multiple arguments to the update. Cannot be set if arg is. - start_workflow_operation: a WithStartWorkflowOperation definining the - WorkflowIDConflictPolicy and how to start the workflow in the event that a - workflow is started. - wait_for_stage: Required stage to wait until returning: either ACCEPTED or - COMPLETED. ADMITTED is not currently supported. See - https://docs.temporal.io/workflows#update for more details. - id: ID of the update. If not set, the default is a new UUID. - result_type: For string updates, this can set the specific result - type hint to deserialize into. - rpc_metadata: Headers used on the RPC call. Keys here override - client-level RPC metadata keys. - rpc_timeout: Optional RPC deadline to set for the RPC call. - - Raises: - WorkflowUpdateFailedError: If the update failed. - WorkflowUpdateRPCTimeoutOrCancelledError: This update call timed out - or was cancelled. This doesn't mean the update itself was timed out or - cancelled. - - RPCError: There was some issue starting the workflow or sending the update to - the workflow. - """ - return await self._start_update_with_start( - update, - arg, - wait_for_stage=wait_for_stage, - args=args, - id=id, - result_type=result_type, - start_workflow_operation=start_workflow_operation, - rpc_metadata=rpc_metadata, - rpc_timeout=rpc_timeout, - ) - - async def _start_update_with_start( - self, - update: str | Callable, - arg: Any = temporalio.common._arg_unset, - *, - wait_for_stage: WorkflowUpdateStage, - args: Sequence[Any] = [], - id: str | None = None, - result_type: type | None = None, - start_workflow_operation: WithStartWorkflowOperation[SelfType, ReturnType], - rpc_metadata: Mapping[str, str | bytes] = {}, - rpc_timeout: timedelta | None = None, - ) -> WorkflowUpdateHandle[Any]: - if wait_for_stage == WorkflowUpdateStage.ADMITTED: - raise ValueError("ADMITTED wait stage not supported") - - if start_workflow_operation._used: - raise RuntimeError("WithStartWorkflowOperation cannot be reused") - start_workflow_operation._used = True - - update_name, result_type_from_type_hint = ( - temporalio.workflow._UpdateDefinition.get_name_and_result_type(update) - ) - - update_input = UpdateWithStartUpdateWorkflowInput( - update_id=id, - update=update_name, - args=temporalio.common._arg_or_args(arg, args), - headers={}, - ret_type=result_type or result_type_from_type_hint, - rpc_metadata=rpc_metadata, - rpc_timeout=rpc_timeout, - wait_for_stage=wait_for_stage, - ) - - def on_start( - start_response: temporalio.api.workflowservice.v1.StartWorkflowExecutionResponse, - ): - start_workflow_operation._workflow_handle.set_result( - WorkflowHandle( - self, - start_workflow_operation._start_workflow_input.id, - first_execution_run_id=start_response.run_id, - result_run_id=start_response.run_id, - result_type=start_workflow_operation._start_workflow_input.ret_type, - ) - ) - - def on_start_error( - error: BaseException, - ): - start_workflow_operation._workflow_handle.set_exception(error) - - input = StartWorkflowUpdateWithStartInput( - start_workflow_input=start_workflow_operation._start_workflow_input, - update_workflow_input=update_input, - _on_start=on_start, - _on_start_error=on_start_error, - ) - - return await self._impl.start_update_with_start_workflow(input) - - def list_workflows( - self, - query: str | None = None, - *, - limit: int | None = None, - page_size: int = 1000, - next_page_token: bytes | None = None, - rpc_metadata: Mapping[str, str | bytes] = {}, - rpc_timeout: timedelta | None = None, - ) -> WorkflowExecutionAsyncIterator: - """List workflows. - - This does not make a request until the first iteration is attempted. - Therefore any errors will not occur until then. - - Args: - query: A Temporal visibility list filter. See Temporal documentation - concerning visibility list filters including behavior when left - unset. - limit: Maximum number of workflows to return. If unset, all - workflows are returned. Only applies if using the - returned :py:class:`WorkflowExecutionAsyncIterator`. - as an async iterator. - page_size: Maximum number of results for each page. - next_page_token: A previously obtained next page token if doing - pagination. Usually not needed as the iterator automatically - starts from the beginning. - rpc_metadata: Headers used on each RPC call. Keys here override - client-level RPC metadata keys. - rpc_timeout: Optional RPC deadline to set for each RPC call. - - Returns: - An async iterator that can be used with ``async for``. - """ - return self._impl.list_workflows( - ListWorkflowsInput( - query=query, - page_size=page_size, - next_page_token=next_page_token, - rpc_metadata=rpc_metadata, - rpc_timeout=rpc_timeout, - limit=limit, - ) - ) - - async def count_workflows( - self, - query: str | None = None, - rpc_metadata: Mapping[str, str | bytes] = {}, - rpc_timeout: timedelta | None = None, - ) -> WorkflowExecutionCount: - """Count workflows. - - Args: - query: A Temporal visibility filter. See Temporal documentation - concerning visibility list filters. - rpc_metadata: Headers used on each RPC call. Keys here override - client-level RPC metadata keys. - rpc_timeout: Optional RPC deadline to set for each RPC call. - - Returns: - Count of workflows. - """ - return await self._impl.count_workflows( - CountWorkflowsInput( - query=query, rpc_metadata=rpc_metadata, rpc_timeout=rpc_timeout - ) - ) - - # async no-param - @overload - async def start_activity( - self, - activity: CallableAsyncNoParam[ReturnType], - *, - id: str, - task_queue: str, - schedule_to_close_timeout: timedelta | None = None, - schedule_to_start_timeout: timedelta | None = None, - start_to_close_timeout: timedelta | None = None, - heartbeat_timeout: timedelta | None = None, - id_reuse_policy: temporalio.common.ActivityIDReusePolicy = temporalio.common.ActivityIDReusePolicy.ALLOW_DUPLICATE, - id_conflict_policy: temporalio.common.ActivityIDConflictPolicy = temporalio.common.ActivityIDConflictPolicy.FAIL, - retry_policy: temporalio.common.RetryPolicy | None = None, - search_attributes: temporalio.common.TypedSearchAttributes | None = None, - summary: str | None = None, - priority: temporalio.common.Priority = temporalio.common.Priority.default, - start_delay: timedelta | None = None, - rpc_metadata: Mapping[str, str | bytes] = {}, - rpc_timeout: timedelta | None = None, - ) -> ActivityHandle[ReturnType]: ... - - # sync no-param - @overload - async def start_activity( - self, - activity: CallableSyncNoParam[ReturnType], - *, - id: str, - task_queue: str, - schedule_to_close_timeout: timedelta | None = None, - schedule_to_start_timeout: timedelta | None = None, - start_to_close_timeout: timedelta | None = None, - heartbeat_timeout: timedelta | None = None, - id_reuse_policy: temporalio.common.ActivityIDReusePolicy = temporalio.common.ActivityIDReusePolicy.ALLOW_DUPLICATE, - id_conflict_policy: temporalio.common.ActivityIDConflictPolicy = temporalio.common.ActivityIDConflictPolicy.FAIL, - retry_policy: temporalio.common.RetryPolicy | None = None, - search_attributes: temporalio.common.TypedSearchAttributes | None = None, - summary: str | None = None, - priority: temporalio.common.Priority = temporalio.common.Priority.default, - start_delay: timedelta | None = None, - rpc_metadata: Mapping[str, str | bytes] = {}, - rpc_timeout: timedelta | None = None, - ) -> ActivityHandle[ReturnType]: ... - - # async single-param - @overload - async def start_activity( - self, - activity: CallableAsyncSingleParam[ParamType, ReturnType], - arg: ParamType, - *, - id: str, - task_queue: str, - schedule_to_close_timeout: timedelta | None = None, - schedule_to_start_timeout: timedelta | None = None, - start_to_close_timeout: timedelta | None = None, - heartbeat_timeout: timedelta | None = None, - id_reuse_policy: temporalio.common.ActivityIDReusePolicy = temporalio.common.ActivityIDReusePolicy.ALLOW_DUPLICATE, - id_conflict_policy: temporalio.common.ActivityIDConflictPolicy = temporalio.common.ActivityIDConflictPolicy.FAIL, - retry_policy: temporalio.common.RetryPolicy | None = None, - search_attributes: temporalio.common.TypedSearchAttributes | None = None, - summary: str | None = None, - priority: temporalio.common.Priority = temporalio.common.Priority.default, - start_delay: timedelta | None = None, - rpc_metadata: Mapping[str, str | bytes] = {}, - rpc_timeout: timedelta | None = None, - ) -> ActivityHandle[ReturnType]: ... - - # sync single-param - @overload - async def start_activity( - self, - activity: CallableSyncSingleParam[ParamType, ReturnType], - arg: ParamType, - *, - id: str, - task_queue: str, - schedule_to_close_timeout: timedelta | None = None, - schedule_to_start_timeout: timedelta | None = None, - start_to_close_timeout: timedelta | None = None, - heartbeat_timeout: timedelta | None = None, - id_reuse_policy: temporalio.common.ActivityIDReusePolicy = temporalio.common.ActivityIDReusePolicy.ALLOW_DUPLICATE, - id_conflict_policy: temporalio.common.ActivityIDConflictPolicy = temporalio.common.ActivityIDConflictPolicy.FAIL, - retry_policy: temporalio.common.RetryPolicy | None = None, - search_attributes: temporalio.common.TypedSearchAttributes | None = None, - summary: str | None = None, - priority: temporalio.common.Priority = temporalio.common.Priority.default, - start_delay: timedelta | None = None, - rpc_metadata: Mapping[str, str | bytes] = {}, - rpc_timeout: timedelta | None = None, - ) -> ActivityHandle[ReturnType]: ... - - # async multi-param - @overload - async def start_activity( - self, - activity: Callable[..., Awaitable[ReturnType]], - *, - args: Sequence[Any], - id: str, - task_queue: str, - schedule_to_close_timeout: timedelta | None = None, - schedule_to_start_timeout: timedelta | None = None, - start_to_close_timeout: timedelta | None = None, - heartbeat_timeout: timedelta | None = None, - id_reuse_policy: temporalio.common.ActivityIDReusePolicy = temporalio.common.ActivityIDReusePolicy.ALLOW_DUPLICATE, - id_conflict_policy: temporalio.common.ActivityIDConflictPolicy = temporalio.common.ActivityIDConflictPolicy.FAIL, - retry_policy: temporalio.common.RetryPolicy | None = None, - search_attributes: temporalio.common.TypedSearchAttributes | None = None, - summary: str | None = None, - priority: temporalio.common.Priority = temporalio.common.Priority.default, - start_delay: timedelta | None = None, - rpc_metadata: Mapping[str, str | bytes] = {}, - rpc_timeout: timedelta | None = None, - ) -> ActivityHandle[ReturnType]: ... - - # sync multi-param - @overload - async def start_activity( - self, - activity: Callable[..., ReturnType], - *, - args: Sequence[Any], - id: str, - task_queue: str, - schedule_to_close_timeout: timedelta | None = None, - schedule_to_start_timeout: timedelta | None = None, - start_to_close_timeout: timedelta | None = None, - heartbeat_timeout: timedelta | None = None, - id_reuse_policy: temporalio.common.ActivityIDReusePolicy = temporalio.common.ActivityIDReusePolicy.ALLOW_DUPLICATE, - id_conflict_policy: temporalio.common.ActivityIDConflictPolicy = temporalio.common.ActivityIDConflictPolicy.FAIL, - retry_policy: temporalio.common.RetryPolicy | None = None, - search_attributes: temporalio.common.TypedSearchAttributes | None = None, - summary: str | None = None, - priority: temporalio.common.Priority = temporalio.common.Priority.default, - start_delay: timedelta | None = None, - rpc_metadata: Mapping[str, str | bytes] = {}, - rpc_timeout: timedelta | None = None, - ) -> ActivityHandle[ReturnType]: ... - - # string name - @overload - async def start_activity( - self, - activity: str, - arg: Any = temporalio.common._arg_unset, - *, - args: Sequence[Any] = [], - id: str, - task_queue: str, - result_type: type | None = None, - schedule_to_close_timeout: timedelta | None = None, - schedule_to_start_timeout: timedelta | None = None, - start_to_close_timeout: timedelta | None = None, - heartbeat_timeout: timedelta | None = None, - id_reuse_policy: temporalio.common.ActivityIDReusePolicy = temporalio.common.ActivityIDReusePolicy.ALLOW_DUPLICATE, - id_conflict_policy: temporalio.common.ActivityIDConflictPolicy = temporalio.common.ActivityIDConflictPolicy.FAIL, - retry_policy: temporalio.common.RetryPolicy | None = None, - search_attributes: temporalio.common.TypedSearchAttributes | None = None, - summary: str | None = None, - priority: temporalio.common.Priority = temporalio.common.Priority.default, - start_delay: timedelta | None = None, - rpc_metadata: Mapping[str, str | bytes] = {}, - rpc_timeout: timedelta | None = None, - ) -> ActivityHandle[Any]: ... - - async def start_activity( - self, - activity: ( - str | Callable[..., Awaitable[ReturnType]] | Callable[..., ReturnType] - ), - arg: Any = temporalio.common._arg_unset, - *, - args: Sequence[Any] = [], - id: str, - task_queue: str, - result_type: type | None = None, - # Either schedule_to_close_timeout or start_to_close_timeout must be present - schedule_to_close_timeout: timedelta | None = None, - schedule_to_start_timeout: timedelta | None = None, - start_to_close_timeout: timedelta | None = None, - heartbeat_timeout: timedelta | None = None, - id_reuse_policy: temporalio.common.ActivityIDReusePolicy = temporalio.common.ActivityIDReusePolicy.ALLOW_DUPLICATE, - id_conflict_policy: temporalio.common.ActivityIDConflictPolicy = temporalio.common.ActivityIDConflictPolicy.FAIL, - retry_policy: temporalio.common.RetryPolicy | None = None, - search_attributes: temporalio.common.TypedSearchAttributes | None = None, - summary: str | None = None, - priority: temporalio.common.Priority = temporalio.common.Priority.default, - start_delay: timedelta | None = None, - rpc_metadata: Mapping[str, str | bytes] = {}, - rpc_timeout: timedelta | None = None, - ) -> ActivityHandle[ReturnType]: - """Start an activity and return its handle. - - .. warning:: - This API is experimental. - - Args: - activity: String name or callable activity function to execute. - arg: Single argument to the activity. - args: Multiple arguments to the activity. Cannot be set if arg is. - id: Unique identifier for the activity. Required. - task_queue: Task queue to send the activity to. - result_type: For string name activities, optional type to deserialize result into. - schedule_to_close_timeout: Total time allowed for the activity from schedule to completion. - schedule_to_start_timeout: Time allowed for the activity to sit in the task queue. - start_to_close_timeout: Time allowed for a single execution attempt. - heartbeat_timeout: Time between heartbeats before the activity is considered failed. - id_reuse_policy: How to handle reusing activity IDs from closed activities. - Default is ALLOW_DUPLICATE. - id_conflict_policy: How to handle activity ID conflicts with running activities. - Default is FAIL. - retry_policy: Retry policy for the activity. - search_attributes: Search attributes for the activity. - summary: A single-line fixed summary for this activity that may appear - in the UI/CLI. This can be in single-line Temporal markdown format. - priority: Priority of the activity execution. - start_delay: Time to wait before dispatching the activity. - This delay is not applied to retry attempts. - rpc_metadata: Headers used on the RPC call. - rpc_timeout: Optional RPC deadline to set for the RPC call. - - Returns: - A handle to the started activity. - """ - name, result_type_from_type_annotation = ( - temporalio.activity._Definition.get_name_and_result_type(activity) - ) - return await self._impl.start_activity( - StartActivityInput( - activity_type=name, - args=temporalio.common._arg_or_args(arg, args), - id=id, - task_queue=task_queue, - result_type=result_type or result_type_from_type_annotation, - schedule_to_close_timeout=schedule_to_close_timeout, - schedule_to_start_timeout=schedule_to_start_timeout, - start_to_close_timeout=start_to_close_timeout, - heartbeat_timeout=heartbeat_timeout, - id_reuse_policy=id_reuse_policy, - id_conflict_policy=id_conflict_policy, - retry_policy=retry_policy, - search_attributes=search_attributes, - summary=summary, - start_delay=start_delay, - headers={}, - rpc_metadata=rpc_metadata, - rpc_timeout=rpc_timeout, - priority=priority, - ) - ) - - # async no-param - @overload - async def execute_activity( - self, - activity: CallableAsyncNoParam[ReturnType], - *, - id: str, - task_queue: str, - schedule_to_close_timeout: timedelta | None = None, - schedule_to_start_timeout: timedelta | None = None, - start_to_close_timeout: timedelta | None = None, - heartbeat_timeout: timedelta | None = None, - id_reuse_policy: temporalio.common.ActivityIDReusePolicy = temporalio.common.ActivityIDReusePolicy.ALLOW_DUPLICATE, - id_conflict_policy: temporalio.common.ActivityIDConflictPolicy = temporalio.common.ActivityIDConflictPolicy.FAIL, - retry_policy: temporalio.common.RetryPolicy | None = None, - search_attributes: temporalio.common.TypedSearchAttributes | None = None, - summary: str | None = None, - priority: temporalio.common.Priority = temporalio.common.Priority.default, - start_delay: timedelta | None = None, - rpc_metadata: Mapping[str, str | bytes] = {}, - rpc_timeout: timedelta | None = None, - ) -> ReturnType: ... - - # sync no-param - @overload - async def execute_activity( - self, - activity: CallableSyncNoParam[ReturnType], - *, - id: str, - task_queue: str, - schedule_to_close_timeout: timedelta | None = None, - schedule_to_start_timeout: timedelta | None = None, - start_to_close_timeout: timedelta | None = None, - heartbeat_timeout: timedelta | None = None, - id_reuse_policy: temporalio.common.ActivityIDReusePolicy = temporalio.common.ActivityIDReusePolicy.ALLOW_DUPLICATE, - id_conflict_policy: temporalio.common.ActivityIDConflictPolicy = temporalio.common.ActivityIDConflictPolicy.FAIL, - retry_policy: temporalio.common.RetryPolicy | None = None, - search_attributes: temporalio.common.TypedSearchAttributes | None = None, - summary: str | None = None, - priority: temporalio.common.Priority = temporalio.common.Priority.default, - start_delay: timedelta | None = None, - rpc_metadata: Mapping[str, str | bytes] = {}, - rpc_timeout: timedelta | None = None, - ) -> ReturnType: ... - - # async single-param - @overload - async def execute_activity( - self, - activity: CallableAsyncSingleParam[ParamType, ReturnType], - arg: ParamType, - *, - id: str, - task_queue: str, - schedule_to_close_timeout: timedelta | None = None, - schedule_to_start_timeout: timedelta | None = None, - start_to_close_timeout: timedelta | None = None, - heartbeat_timeout: timedelta | None = None, - id_reuse_policy: temporalio.common.ActivityIDReusePolicy = temporalio.common.ActivityIDReusePolicy.ALLOW_DUPLICATE, - id_conflict_policy: temporalio.common.ActivityIDConflictPolicy = temporalio.common.ActivityIDConflictPolicy.FAIL, - retry_policy: temporalio.common.RetryPolicy | None = None, - search_attributes: temporalio.common.TypedSearchAttributes | None = None, - summary: str | None = None, - priority: temporalio.common.Priority = temporalio.common.Priority.default, - start_delay: timedelta | None = None, - rpc_metadata: Mapping[str, str | bytes] = {}, - rpc_timeout: timedelta | None = None, - ) -> ReturnType: ... - - # sync single-param - @overload - async def execute_activity( - self, - activity: CallableSyncSingleParam[ParamType, ReturnType], - arg: ParamType, - *, - id: str, - task_queue: str, - schedule_to_close_timeout: timedelta | None = None, - schedule_to_start_timeout: timedelta | None = None, - start_to_close_timeout: timedelta | None = None, - heartbeat_timeout: timedelta | None = None, - id_reuse_policy: temporalio.common.ActivityIDReusePolicy = temporalio.common.ActivityIDReusePolicy.ALLOW_DUPLICATE, - id_conflict_policy: temporalio.common.ActivityIDConflictPolicy = temporalio.common.ActivityIDConflictPolicy.FAIL, - retry_policy: temporalio.common.RetryPolicy | None = None, - search_attributes: temporalio.common.TypedSearchAttributes | None = None, - summary: str | None = None, - priority: temporalio.common.Priority = temporalio.common.Priority.default, - start_delay: timedelta | None = None, - rpc_metadata: Mapping[str, str | bytes] = {}, - rpc_timeout: timedelta | None = None, - ) -> ReturnType: ... - - # async multi-param - @overload - async def execute_activity( - self, - activity: Callable[..., Awaitable[ReturnType]], - *, - args: Sequence[Any], - id: str, - task_queue: str, - schedule_to_close_timeout: timedelta | None = None, - schedule_to_start_timeout: timedelta | None = None, - start_to_close_timeout: timedelta | None = None, - heartbeat_timeout: timedelta | None = None, - id_reuse_policy: temporalio.common.ActivityIDReusePolicy = temporalio.common.ActivityIDReusePolicy.ALLOW_DUPLICATE, - id_conflict_policy: temporalio.common.ActivityIDConflictPolicy = temporalio.common.ActivityIDConflictPolicy.FAIL, - retry_policy: temporalio.common.RetryPolicy | None = None, - search_attributes: temporalio.common.TypedSearchAttributes | None = None, - summary: str | None = None, - priority: temporalio.common.Priority = temporalio.common.Priority.default, - start_delay: timedelta | None = None, - rpc_metadata: Mapping[str, str | bytes] = {}, - rpc_timeout: timedelta | None = None, - ) -> ReturnType: ... - - # sync multi-param - @overload - async def execute_activity( - self, - activity: Callable[..., ReturnType], - *, - args: Sequence[Any], - id: str, - task_queue: str, - schedule_to_close_timeout: timedelta | None = None, - schedule_to_start_timeout: timedelta | None = None, - start_to_close_timeout: timedelta | None = None, - heartbeat_timeout: timedelta | None = None, - id_reuse_policy: temporalio.common.ActivityIDReusePolicy = temporalio.common.ActivityIDReusePolicy.ALLOW_DUPLICATE, - id_conflict_policy: temporalio.common.ActivityIDConflictPolicy = temporalio.common.ActivityIDConflictPolicy.FAIL, - retry_policy: temporalio.common.RetryPolicy | None = None, - search_attributes: temporalio.common.TypedSearchAttributes | None = None, - summary: str | None = None, - priority: temporalio.common.Priority = temporalio.common.Priority.default, - start_delay: timedelta | None = None, - rpc_metadata: Mapping[str, str | bytes] = {}, - rpc_timeout: timedelta | None = None, - ) -> ReturnType: ... - - # string name - @overload - async def execute_activity( - self, - activity: str, - arg: Any = temporalio.common._arg_unset, - *, - args: Sequence[Any] = [], - id: str, - task_queue: str, - result_type: type | None = None, - schedule_to_close_timeout: timedelta | None = None, - schedule_to_start_timeout: timedelta | None = None, - start_to_close_timeout: timedelta | None = None, - heartbeat_timeout: timedelta | None = None, - id_reuse_policy: temporalio.common.ActivityIDReusePolicy = temporalio.common.ActivityIDReusePolicy.ALLOW_DUPLICATE, - id_conflict_policy: temporalio.common.ActivityIDConflictPolicy = temporalio.common.ActivityIDConflictPolicy.FAIL, - retry_policy: temporalio.common.RetryPolicy | None = None, - search_attributes: temporalio.common.TypedSearchAttributes | None = None, - summary: str | None = None, - priority: temporalio.common.Priority = temporalio.common.Priority.default, - start_delay: timedelta | None = None, - rpc_metadata: Mapping[str, str | bytes] = {}, - rpc_timeout: timedelta | None = None, - ) -> Any: ... - - async def execute_activity( - self, - activity: ( - str | Callable[..., Awaitable[ReturnType]] | Callable[..., ReturnType] - ), - arg: Any = temporalio.common._arg_unset, - *, - args: Sequence[Any] = [], - id: str, - task_queue: str, - result_type: type | None = None, - # Either schedule_to_close_timeout or start_to_close_timeout must be present - schedule_to_close_timeout: timedelta | None = None, - schedule_to_start_timeout: timedelta | None = None, - start_to_close_timeout: timedelta | None = None, - heartbeat_timeout: timedelta | None = None, - id_reuse_policy: temporalio.common.ActivityIDReusePolicy = temporalio.common.ActivityIDReusePolicy.ALLOW_DUPLICATE, - id_conflict_policy: temporalio.common.ActivityIDConflictPolicy = temporalio.common.ActivityIDConflictPolicy.FAIL, - retry_policy: temporalio.common.RetryPolicy | None = None, - search_attributes: temporalio.common.TypedSearchAttributes | None = None, - summary: str | None = None, - priority: temporalio.common.Priority = temporalio.common.Priority.default, - start_delay: timedelta | None = None, - rpc_metadata: Mapping[str, str | bytes] = {}, - rpc_timeout: timedelta | None = None, - ) -> ReturnType: - """Start an activity, wait for it to complete, and return its result. - - .. warning:: - This API is experimental. - - This is a convenience method that combines :py:meth:`start_activity` and - :py:meth:`ActivityHandle.result`. - - Returns: - The result of the activity. - - Raises: - ActivityFailureError: If the activity completed with a failure. - """ - handle: ActivityHandle[ReturnType] = await self.start_activity( - cast(Any, activity), - arg, - args=args, - id=id, - task_queue=task_queue, - result_type=result_type, - schedule_to_close_timeout=schedule_to_close_timeout, - schedule_to_start_timeout=schedule_to_start_timeout, - start_to_close_timeout=start_to_close_timeout, - heartbeat_timeout=heartbeat_timeout, - id_reuse_policy=id_reuse_policy, - id_conflict_policy=id_conflict_policy, - retry_policy=retry_policy, - search_attributes=search_attributes, - summary=summary, - priority=priority, - start_delay=start_delay, - rpc_metadata=rpc_metadata, - rpc_timeout=rpc_timeout, - ) - return await handle.result() - - # async no-param - @overload - async def start_activity_class( - self, - activity: type[CallableAsyncNoParam[ReturnType]], - *, - id: str, - task_queue: str, - schedule_to_close_timeout: timedelta | None = None, - schedule_to_start_timeout: timedelta | None = None, - start_to_close_timeout: timedelta | None = None, - heartbeat_timeout: timedelta | None = None, - id_reuse_policy: temporalio.common.ActivityIDReusePolicy = temporalio.common.ActivityIDReusePolicy.ALLOW_DUPLICATE, - id_conflict_policy: temporalio.common.ActivityIDConflictPolicy = temporalio.common.ActivityIDConflictPolicy.FAIL, - retry_policy: temporalio.common.RetryPolicy | None = None, - search_attributes: temporalio.common.TypedSearchAttributes | None = None, - summary: str | None = None, - priority: temporalio.common.Priority = temporalio.common.Priority.default, - start_delay: timedelta | None = None, - rpc_metadata: Mapping[str, str | bytes] = {}, - rpc_timeout: timedelta | None = None, - ) -> ActivityHandle[ReturnType]: ... - - # sync no-param - @overload - async def start_activity_class( - self, - activity: type[CallableSyncNoParam[ReturnType]], - *, - id: str, - task_queue: str, - schedule_to_close_timeout: timedelta | None = None, - schedule_to_start_timeout: timedelta | None = None, - start_to_close_timeout: timedelta | None = None, - heartbeat_timeout: timedelta | None = None, - id_reuse_policy: temporalio.common.ActivityIDReusePolicy = temporalio.common.ActivityIDReusePolicy.ALLOW_DUPLICATE, - id_conflict_policy: temporalio.common.ActivityIDConflictPolicy = temporalio.common.ActivityIDConflictPolicy.FAIL, - retry_policy: temporalio.common.RetryPolicy | None = None, - search_attributes: temporalio.common.TypedSearchAttributes | None = None, - summary: str | None = None, - priority: temporalio.common.Priority = temporalio.common.Priority.default, - start_delay: timedelta | None = None, - rpc_metadata: Mapping[str, str | bytes] = {}, - rpc_timeout: timedelta | None = None, - ) -> ActivityHandle[ReturnType]: ... - - # async single-param - @overload - async def start_activity_class( - self, - activity: type[CallableAsyncSingleParam[ParamType, ReturnType]], - arg: ParamType, - *, - id: str, - task_queue: str, - schedule_to_close_timeout: timedelta | None = None, - schedule_to_start_timeout: timedelta | None = None, - start_to_close_timeout: timedelta | None = None, - heartbeat_timeout: timedelta | None = None, - id_reuse_policy: temporalio.common.ActivityIDReusePolicy = temporalio.common.ActivityIDReusePolicy.ALLOW_DUPLICATE, - id_conflict_policy: temporalio.common.ActivityIDConflictPolicy = temporalio.common.ActivityIDConflictPolicy.FAIL, - retry_policy: temporalio.common.RetryPolicy | None = None, - search_attributes: temporalio.common.TypedSearchAttributes | None = None, - summary: str | None = None, - priority: temporalio.common.Priority = temporalio.common.Priority.default, - start_delay: timedelta | None = None, - rpc_metadata: Mapping[str, str | bytes] = {}, - rpc_timeout: timedelta | None = None, - ) -> ActivityHandle[ReturnType]: ... - - # sync single-param - @overload - async def start_activity_class( - self, - activity: type[CallableSyncSingleParam[ParamType, ReturnType]], - arg: ParamType, - *, - id: str, - task_queue: str, - schedule_to_close_timeout: timedelta | None = None, - schedule_to_start_timeout: timedelta | None = None, - start_to_close_timeout: timedelta | None = None, - heartbeat_timeout: timedelta | None = None, - id_reuse_policy: temporalio.common.ActivityIDReusePolicy = temporalio.common.ActivityIDReusePolicy.ALLOW_DUPLICATE, - id_conflict_policy: temporalio.common.ActivityIDConflictPolicy = temporalio.common.ActivityIDConflictPolicy.FAIL, - retry_policy: temporalio.common.RetryPolicy | None = None, - search_attributes: temporalio.common.TypedSearchAttributes | None = None, - summary: str | None = None, - priority: temporalio.common.Priority = temporalio.common.Priority.default, - start_delay: timedelta | None = None, - rpc_metadata: Mapping[str, str | bytes] = {}, - rpc_timeout: timedelta | None = None, - ) -> ActivityHandle[ReturnType]: ... - - # async multi-param - @overload - async def start_activity_class( - self, - activity: type[Callable[..., Awaitable[ReturnType]]], # type: ignore[reportInvalidTypeForm] - *, - args: Sequence[Any], - id: str, - task_queue: str, - schedule_to_close_timeout: timedelta | None = None, - schedule_to_start_timeout: timedelta | None = None, - start_to_close_timeout: timedelta | None = None, - heartbeat_timeout: timedelta | None = None, - id_reuse_policy: temporalio.common.ActivityIDReusePolicy = temporalio.common.ActivityIDReusePolicy.ALLOW_DUPLICATE, - id_conflict_policy: temporalio.common.ActivityIDConflictPolicy = temporalio.common.ActivityIDConflictPolicy.FAIL, - retry_policy: temporalio.common.RetryPolicy | None = None, - search_attributes: temporalio.common.TypedSearchAttributes | None = None, - summary: str | None = None, - priority: temporalio.common.Priority = temporalio.common.Priority.default, - start_delay: timedelta | None = None, - rpc_metadata: Mapping[str, str | bytes] = {}, - rpc_timeout: timedelta | None = None, - ) -> ActivityHandle[ReturnType]: ... - - # sync multi-param - @overload - async def start_activity_class( - self, - activity: type[Callable[..., ReturnType]], # type: ignore[reportInvalidTypeForm] - *, - args: Sequence[Any], - id: str, - task_queue: str, - schedule_to_close_timeout: timedelta | None = None, - schedule_to_start_timeout: timedelta | None = None, - start_to_close_timeout: timedelta | None = None, - heartbeat_timeout: timedelta | None = None, - id_reuse_policy: temporalio.common.ActivityIDReusePolicy = temporalio.common.ActivityIDReusePolicy.ALLOW_DUPLICATE, - id_conflict_policy: temporalio.common.ActivityIDConflictPolicy = temporalio.common.ActivityIDConflictPolicy.FAIL, - retry_policy: temporalio.common.RetryPolicy | None = None, - search_attributes: temporalio.common.TypedSearchAttributes | None = None, - summary: str | None = None, - priority: temporalio.common.Priority = temporalio.common.Priority.default, - start_delay: timedelta | None = None, - rpc_metadata: Mapping[str, str | bytes] = {}, - rpc_timeout: timedelta | None = None, - ) -> ActivityHandle[ReturnType]: ... - - async def start_activity_class( - self, - activity: type[Callable], # type: ignore[reportInvalidTypeForm] - arg: Any = temporalio.common._arg_unset, - *, - args: Sequence[Any] = [], - id: str, - task_queue: str, - result_type: type | None = None, - schedule_to_close_timeout: timedelta | None = None, - schedule_to_start_timeout: timedelta | None = None, - start_to_close_timeout: timedelta | None = None, - heartbeat_timeout: timedelta | None = None, - id_reuse_policy: temporalio.common.ActivityIDReusePolicy = temporalio.common.ActivityIDReusePolicy.ALLOW_DUPLICATE, - id_conflict_policy: temporalio.common.ActivityIDConflictPolicy = temporalio.common.ActivityIDConflictPolicy.FAIL, - retry_policy: temporalio.common.RetryPolicy | None = None, - search_attributes: temporalio.common.TypedSearchAttributes | None = None, - summary: str | None = None, - priority: temporalio.common.Priority = temporalio.common.Priority.default, - start_delay: timedelta | None = None, - rpc_metadata: Mapping[str, str | bytes] = {}, - rpc_timeout: timedelta | None = None, - ) -> ActivityHandle[Any]: - """Start an activity from a callable class. - - .. warning:: - This API is experimental. - - See :py:meth:`start_activity` for parameter and return details. - """ - return await self.start_activity( - cast(Any, activity), - arg, - args=args, - id=id, - task_queue=task_queue, - result_type=result_type, - schedule_to_close_timeout=schedule_to_close_timeout, - schedule_to_start_timeout=schedule_to_start_timeout, - start_to_close_timeout=start_to_close_timeout, - heartbeat_timeout=heartbeat_timeout, - id_reuse_policy=id_reuse_policy, - id_conflict_policy=id_conflict_policy, - retry_policy=retry_policy, - search_attributes=search_attributes, - summary=summary, - priority=priority, - start_delay=start_delay, - rpc_metadata=rpc_metadata, - rpc_timeout=rpc_timeout, - ) - - # async no-param - @overload - async def execute_activity_class( - self, - activity: type[CallableAsyncNoParam[ReturnType]], - *, - id: str, - task_queue: str, - schedule_to_close_timeout: timedelta | None = None, - schedule_to_start_timeout: timedelta | None = None, - start_to_close_timeout: timedelta | None = None, - heartbeat_timeout: timedelta | None = None, - id_reuse_policy: temporalio.common.ActivityIDReusePolicy = temporalio.common.ActivityIDReusePolicy.ALLOW_DUPLICATE, - id_conflict_policy: temporalio.common.ActivityIDConflictPolicy = temporalio.common.ActivityIDConflictPolicy.FAIL, - retry_policy: temporalio.common.RetryPolicy | None = None, - search_attributes: temporalio.common.TypedSearchAttributes | None = None, - summary: str | None = None, - priority: temporalio.common.Priority = temporalio.common.Priority.default, - start_delay: timedelta | None = None, - rpc_metadata: Mapping[str, str | bytes] = {}, - rpc_timeout: timedelta | None = None, - ) -> ReturnType: ... - - # sync no-param - @overload - async def execute_activity_class( - self, - activity: type[CallableSyncNoParam[ReturnType]], - *, - id: str, - task_queue: str, - schedule_to_close_timeout: timedelta | None = None, - schedule_to_start_timeout: timedelta | None = None, - start_to_close_timeout: timedelta | None = None, - heartbeat_timeout: timedelta | None = None, - id_reuse_policy: temporalio.common.ActivityIDReusePolicy = temporalio.common.ActivityIDReusePolicy.ALLOW_DUPLICATE, - id_conflict_policy: temporalio.common.ActivityIDConflictPolicy = temporalio.common.ActivityIDConflictPolicy.FAIL, - retry_policy: temporalio.common.RetryPolicy | None = None, - search_attributes: temporalio.common.TypedSearchAttributes | None = None, - summary: str | None = None, - priority: temporalio.common.Priority = temporalio.common.Priority.default, - start_delay: timedelta | None = None, - rpc_metadata: Mapping[str, str | bytes] = {}, - rpc_timeout: timedelta | None = None, - ) -> ReturnType: ... - - # async single-param - @overload - async def execute_activity_class( - self, - activity: type[CallableAsyncSingleParam[ParamType, ReturnType]], - arg: ParamType, - *, - id: str, - task_queue: str, - schedule_to_close_timeout: timedelta | None = None, - schedule_to_start_timeout: timedelta | None = None, - start_to_close_timeout: timedelta | None = None, - heartbeat_timeout: timedelta | None = None, - id_reuse_policy: temporalio.common.ActivityIDReusePolicy = temporalio.common.ActivityIDReusePolicy.ALLOW_DUPLICATE, - id_conflict_policy: temporalio.common.ActivityIDConflictPolicy = temporalio.common.ActivityIDConflictPolicy.FAIL, - retry_policy: temporalio.common.RetryPolicy | None = None, - search_attributes: temporalio.common.TypedSearchAttributes | None = None, - summary: str | None = None, - priority: temporalio.common.Priority = temporalio.common.Priority.default, - start_delay: timedelta | None = None, - rpc_metadata: Mapping[str, str | bytes] = {}, - rpc_timeout: timedelta | None = None, - ) -> ReturnType: ... - - # sync single-param - @overload - async def execute_activity_class( - self, - activity: type[CallableSyncSingleParam[ParamType, ReturnType]], - arg: ParamType, - *, - id: str, - task_queue: str, - schedule_to_close_timeout: timedelta | None = None, - schedule_to_start_timeout: timedelta | None = None, - start_to_close_timeout: timedelta | None = None, - heartbeat_timeout: timedelta | None = None, - id_reuse_policy: temporalio.common.ActivityIDReusePolicy = temporalio.common.ActivityIDReusePolicy.ALLOW_DUPLICATE, - id_conflict_policy: temporalio.common.ActivityIDConflictPolicy = temporalio.common.ActivityIDConflictPolicy.FAIL, - retry_policy: temporalio.common.RetryPolicy | None = None, - search_attributes: temporalio.common.TypedSearchAttributes | None = None, - summary: str | None = None, - priority: temporalio.common.Priority = temporalio.common.Priority.default, - start_delay: timedelta | None = None, - rpc_metadata: Mapping[str, str | bytes] = {}, - rpc_timeout: timedelta | None = None, - ) -> ReturnType: ... - - # async multi-param - @overload - async def execute_activity_class( - self, - activity: type[Callable[..., Awaitable[ReturnType]]], # type: ignore[reportInvalidTypeForm] - *, - args: Sequence[Any], - id: str, - task_queue: str, - schedule_to_close_timeout: timedelta | None = None, - schedule_to_start_timeout: timedelta | None = None, - start_to_close_timeout: timedelta | None = None, - heartbeat_timeout: timedelta | None = None, - id_reuse_policy: temporalio.common.ActivityIDReusePolicy = temporalio.common.ActivityIDReusePolicy.ALLOW_DUPLICATE, - id_conflict_policy: temporalio.common.ActivityIDConflictPolicy = temporalio.common.ActivityIDConflictPolicy.FAIL, - retry_policy: temporalio.common.RetryPolicy | None = None, - search_attributes: temporalio.common.TypedSearchAttributes | None = None, - summary: str | None = None, - priority: temporalio.common.Priority = temporalio.common.Priority.default, - start_delay: timedelta | None = None, - rpc_metadata: Mapping[str, str | bytes] = {}, - rpc_timeout: timedelta | None = None, - ) -> ReturnType: ... - - # sync multi-param - @overload - async def execute_activity_class( - self, - activity: type[Callable[..., ReturnType]], # type: ignore[reportInvalidTypeForm] - *, - args: Sequence[Any], - id: str, - task_queue: str, - schedule_to_close_timeout: timedelta | None = None, - schedule_to_start_timeout: timedelta | None = None, - start_to_close_timeout: timedelta | None = None, - heartbeat_timeout: timedelta | None = None, - id_reuse_policy: temporalio.common.ActivityIDReusePolicy = temporalio.common.ActivityIDReusePolicy.ALLOW_DUPLICATE, - id_conflict_policy: temporalio.common.ActivityIDConflictPolicy = temporalio.common.ActivityIDConflictPolicy.FAIL, - retry_policy: temporalio.common.RetryPolicy | None = None, - search_attributes: temporalio.common.TypedSearchAttributes | None = None, - summary: str | None = None, - priority: temporalio.common.Priority = temporalio.common.Priority.default, - start_delay: timedelta | None = None, - rpc_metadata: Mapping[str, str | bytes] = {}, - rpc_timeout: timedelta | None = None, - ) -> ReturnType: ... - - async def execute_activity_class( - self, - activity: type[Callable], # type: ignore[reportInvalidTypeForm] - arg: Any = temporalio.common._arg_unset, - *, - args: Sequence[Any] = [], - id: str, - task_queue: str, - result_type: type | None = None, - schedule_to_close_timeout: timedelta | None = None, - schedule_to_start_timeout: timedelta | None = None, - start_to_close_timeout: timedelta | None = None, - heartbeat_timeout: timedelta | None = None, - id_reuse_policy: temporalio.common.ActivityIDReusePolicy = temporalio.common.ActivityIDReusePolicy.ALLOW_DUPLICATE, - id_conflict_policy: temporalio.common.ActivityIDConflictPolicy = temporalio.common.ActivityIDConflictPolicy.FAIL, - retry_policy: temporalio.common.RetryPolicy | None = None, - search_attributes: temporalio.common.TypedSearchAttributes | None = None, - summary: str | None = None, - priority: temporalio.common.Priority = temporalio.common.Priority.default, - start_delay: timedelta | None = None, - rpc_metadata: Mapping[str, str | bytes] = {}, - rpc_timeout: timedelta | None = None, - ) -> Any: - """Start an activity from a callable class and wait for completion. - - .. warning:: - This API is experimental. - - This is a shortcut for ``await`` :py:meth:`start_activity_class`. - """ - return await self.execute_activity( - cast(Any, activity), - arg, - args=args, - id=id, - task_queue=task_queue, - result_type=result_type, - schedule_to_close_timeout=schedule_to_close_timeout, - schedule_to_start_timeout=schedule_to_start_timeout, - start_to_close_timeout=start_to_close_timeout, - heartbeat_timeout=heartbeat_timeout, - id_reuse_policy=id_reuse_policy, - id_conflict_policy=id_conflict_policy, - retry_policy=retry_policy, - search_attributes=search_attributes, - summary=summary, - priority=priority, - start_delay=start_delay, - rpc_metadata=rpc_metadata, - rpc_timeout=rpc_timeout, - ) - - # async no-param - @overload - async def start_activity_method( - self, - activity: MethodAsyncNoParam[SelfType, ReturnType], - *, - id: str, - task_queue: str, - schedule_to_close_timeout: timedelta | None = None, - schedule_to_start_timeout: timedelta | None = None, - start_to_close_timeout: timedelta | None = None, - heartbeat_timeout: timedelta | None = None, - id_reuse_policy: temporalio.common.ActivityIDReusePolicy = temporalio.common.ActivityIDReusePolicy.ALLOW_DUPLICATE, - id_conflict_policy: temporalio.common.ActivityIDConflictPolicy = temporalio.common.ActivityIDConflictPolicy.FAIL, - retry_policy: temporalio.common.RetryPolicy | None = None, - search_attributes: temporalio.common.TypedSearchAttributes | None = None, - summary: str | None = None, - priority: temporalio.common.Priority = temporalio.common.Priority.default, - start_delay: timedelta | None = None, - rpc_metadata: Mapping[str, str | bytes] = {}, - rpc_timeout: timedelta | None = None, - ) -> ActivityHandle[ReturnType]: ... - - # async single-param - @overload - async def start_activity_method( - self, - activity: MethodAsyncSingleParam[SelfType, ParamType, ReturnType], - arg: ParamType, - *, - id: str, - task_queue: str, - schedule_to_close_timeout: timedelta | None = None, - schedule_to_start_timeout: timedelta | None = None, - start_to_close_timeout: timedelta | None = None, - heartbeat_timeout: timedelta | None = None, - id_reuse_policy: temporalio.common.ActivityIDReusePolicy = temporalio.common.ActivityIDReusePolicy.ALLOW_DUPLICATE, - id_conflict_policy: temporalio.common.ActivityIDConflictPolicy = temporalio.common.ActivityIDConflictPolicy.FAIL, - retry_policy: temporalio.common.RetryPolicy | None = None, - search_attributes: temporalio.common.TypedSearchAttributes | None = None, - summary: str | None = None, - priority: temporalio.common.Priority = temporalio.common.Priority.default, - start_delay: timedelta | None = None, - rpc_metadata: Mapping[str, str | bytes] = {}, - rpc_timeout: timedelta | None = None, - ) -> ActivityHandle[ReturnType]: ... - - # async multi-param - @overload - async def start_activity_method( - self, - activity: Callable[ - Concatenate[SelfType, MultiParamSpec], Awaitable[ReturnType] - ], - *, - args: Sequence[Any], - id: str, - task_queue: str, - schedule_to_close_timeout: timedelta | None = None, - schedule_to_start_timeout: timedelta | None = None, - start_to_close_timeout: timedelta | None = None, - heartbeat_timeout: timedelta | None = None, - id_reuse_policy: temporalio.common.ActivityIDReusePolicy = temporalio.common.ActivityIDReusePolicy.ALLOW_DUPLICATE, - id_conflict_policy: temporalio.common.ActivityIDConflictPolicy = temporalio.common.ActivityIDConflictPolicy.FAIL, - retry_policy: temporalio.common.RetryPolicy | None = None, - search_attributes: temporalio.common.TypedSearchAttributes | None = None, - summary: str | None = None, - priority: temporalio.common.Priority = temporalio.common.Priority.default, - start_delay: timedelta | None = None, - rpc_metadata: Mapping[str, str | bytes] = {}, - rpc_timeout: timedelta | None = None, - ) -> ActivityHandle[ReturnType]: ... - - # sync multi-param - @overload - async def start_activity_method( - self, - activity: Callable[Concatenate[SelfType, MultiParamSpec], ReturnType], - *, - args: Sequence[Any], - id: str, - task_queue: str, - schedule_to_close_timeout: timedelta | None = None, - schedule_to_start_timeout: timedelta | None = None, - start_to_close_timeout: timedelta | None = None, - heartbeat_timeout: timedelta | None = None, - id_reuse_policy: temporalio.common.ActivityIDReusePolicy = temporalio.common.ActivityIDReusePolicy.ALLOW_DUPLICATE, - id_conflict_policy: temporalio.common.ActivityIDConflictPolicy = temporalio.common.ActivityIDConflictPolicy.FAIL, - retry_policy: temporalio.common.RetryPolicy | None = None, - search_attributes: temporalio.common.TypedSearchAttributes | None = None, - summary: str | None = None, - priority: temporalio.common.Priority = temporalio.common.Priority.default, - start_delay: timedelta | None = None, - rpc_metadata: Mapping[str, str | bytes] = {}, - rpc_timeout: timedelta | None = None, - ) -> ActivityHandle[ReturnType]: ... - - async def start_activity_method( - self, - activity: Callable, - arg: Any = temporalio.common._arg_unset, - *, - args: Sequence[Any] = [], - id: str, - task_queue: str, - result_type: type | None = None, - schedule_to_close_timeout: timedelta | None = None, - schedule_to_start_timeout: timedelta | None = None, - start_to_close_timeout: timedelta | None = None, - heartbeat_timeout: timedelta | None = None, - id_reuse_policy: temporalio.common.ActivityIDReusePolicy = temporalio.common.ActivityIDReusePolicy.ALLOW_DUPLICATE, - id_conflict_policy: temporalio.common.ActivityIDConflictPolicy = temporalio.common.ActivityIDConflictPolicy.FAIL, - retry_policy: temporalio.common.RetryPolicy | None = None, - search_attributes: temporalio.common.TypedSearchAttributes | None = None, - summary: str | None = None, - priority: temporalio.common.Priority = temporalio.common.Priority.default, - start_delay: timedelta | None = None, - rpc_metadata: Mapping[str, str | bytes] = {}, - rpc_timeout: timedelta | None = None, - ) -> ActivityHandle[Any]: - """Start an activity from a method. - - .. warning:: - This API is experimental. - - See :py:meth:`start_activity` for parameter and return details. - """ - return await self.start_activity( - cast(Any, activity), - arg, - args=args, - id=id, - task_queue=task_queue, - result_type=result_type, - schedule_to_close_timeout=schedule_to_close_timeout, - schedule_to_start_timeout=schedule_to_start_timeout, - start_to_close_timeout=start_to_close_timeout, - heartbeat_timeout=heartbeat_timeout, - id_reuse_policy=id_reuse_policy, - id_conflict_policy=id_conflict_policy, - retry_policy=retry_policy, - search_attributes=search_attributes, - summary=summary, - priority=priority, - start_delay=start_delay, - rpc_metadata=rpc_metadata, - rpc_timeout=rpc_timeout, - ) - - # async no-param - @overload - async def execute_activity_method( - self, - activity: MethodAsyncNoParam[SelfType, ReturnType], - *, - id: str, - task_queue: str, - schedule_to_close_timeout: timedelta | None = None, - schedule_to_start_timeout: timedelta | None = None, - start_to_close_timeout: timedelta | None = None, - heartbeat_timeout: timedelta | None = None, - id_reuse_policy: temporalio.common.ActivityIDReusePolicy = temporalio.common.ActivityIDReusePolicy.ALLOW_DUPLICATE, - id_conflict_policy: temporalio.common.ActivityIDConflictPolicy = temporalio.common.ActivityIDConflictPolicy.FAIL, - retry_policy: temporalio.common.RetryPolicy | None = None, - search_attributes: temporalio.common.TypedSearchAttributes | None = None, - summary: str | None = None, - priority: temporalio.common.Priority = temporalio.common.Priority.default, - start_delay: timedelta | None = None, - rpc_metadata: Mapping[str, str | bytes] = {}, - rpc_timeout: timedelta | None = None, - ) -> ReturnType: ... - - # async single-param - @overload - async def execute_activity_method( - self, - activity: MethodAsyncSingleParam[SelfType, ParamType, ReturnType], - arg: ParamType, - *, - id: str, - task_queue: str, - schedule_to_close_timeout: timedelta | None = None, - schedule_to_start_timeout: timedelta | None = None, - start_to_close_timeout: timedelta | None = None, - heartbeat_timeout: timedelta | None = None, - id_reuse_policy: temporalio.common.ActivityIDReusePolicy = temporalio.common.ActivityIDReusePolicy.ALLOW_DUPLICATE, - id_conflict_policy: temporalio.common.ActivityIDConflictPolicy = temporalio.common.ActivityIDConflictPolicy.FAIL, - retry_policy: temporalio.common.RetryPolicy | None = None, - search_attributes: temporalio.common.TypedSearchAttributes | None = None, - summary: str | None = None, - priority: temporalio.common.Priority = temporalio.common.Priority.default, - start_delay: timedelta | None = None, - rpc_metadata: Mapping[str, str | bytes] = {}, - rpc_timeout: timedelta | None = None, - ) -> ReturnType: ... - - # async multi-param - @overload - async def execute_activity_method( - self, - activity: Callable[ - Concatenate[SelfType, MultiParamSpec], Awaitable[ReturnType] - ], - *, - args: Sequence[Any], - id: str, - task_queue: str, - schedule_to_close_timeout: timedelta | None = None, - schedule_to_start_timeout: timedelta | None = None, - start_to_close_timeout: timedelta | None = None, - heartbeat_timeout: timedelta | None = None, - id_reuse_policy: temporalio.common.ActivityIDReusePolicy = temporalio.common.ActivityIDReusePolicy.ALLOW_DUPLICATE, - id_conflict_policy: temporalio.common.ActivityIDConflictPolicy = temporalio.common.ActivityIDConflictPolicy.FAIL, - retry_policy: temporalio.common.RetryPolicy | None = None, - search_attributes: temporalio.common.TypedSearchAttributes | None = None, - summary: str | None = None, - priority: temporalio.common.Priority = temporalio.common.Priority.default, - start_delay: timedelta | None = None, - rpc_metadata: Mapping[str, str | bytes] = {}, - rpc_timeout: timedelta | None = None, - ) -> ReturnType: ... - - # sync multi-param - @overload - async def execute_activity_method( - self, - activity: Callable[Concatenate[SelfType, MultiParamSpec], ReturnType], - *, - args: Sequence[Any], - id: str, - task_queue: str, - schedule_to_close_timeout: timedelta | None = None, - schedule_to_start_timeout: timedelta | None = None, - start_to_close_timeout: timedelta | None = None, - heartbeat_timeout: timedelta | None = None, - id_reuse_policy: temporalio.common.ActivityIDReusePolicy = temporalio.common.ActivityIDReusePolicy.ALLOW_DUPLICATE, - id_conflict_policy: temporalio.common.ActivityIDConflictPolicy = temporalio.common.ActivityIDConflictPolicy.FAIL, - retry_policy: temporalio.common.RetryPolicy | None = None, - search_attributes: temporalio.common.TypedSearchAttributes | None = None, - summary: str | None = None, - priority: temporalio.common.Priority = temporalio.common.Priority.default, - start_delay: timedelta | None = None, - rpc_metadata: Mapping[str, str | bytes] = {}, - rpc_timeout: timedelta | None = None, - ) -> ReturnType: ... - - async def execute_activity_method( - self, - activity: Callable, - arg: Any = temporalio.common._arg_unset, - *, - args: Sequence[Any] = [], - id: str, - task_queue: str, - result_type: type | None = None, - schedule_to_close_timeout: timedelta | None = None, - schedule_to_start_timeout: timedelta | None = None, - start_to_close_timeout: timedelta | None = None, - heartbeat_timeout: timedelta | None = None, - id_reuse_policy: temporalio.common.ActivityIDReusePolicy = temporalio.common.ActivityIDReusePolicy.ALLOW_DUPLICATE, - id_conflict_policy: temporalio.common.ActivityIDConflictPolicy = temporalio.common.ActivityIDConflictPolicy.FAIL, - retry_policy: temporalio.common.RetryPolicy | None = None, - search_attributes: temporalio.common.TypedSearchAttributes | None = None, - summary: str | None = None, - priority: temporalio.common.Priority = temporalio.common.Priority.default, - start_delay: timedelta | None = None, - rpc_metadata: Mapping[str, str | bytes] = {}, - rpc_timeout: timedelta | None = None, - ) -> Any: - """Start an activity from a method and wait for completion. - - .. warning:: - This API is experimental. - - This is a shortcut for ``await`` :py:meth:`start_activity_method`. - """ - return await self.execute_activity( - cast(Any, activity), - arg, - args=args, - id=id, - task_queue=task_queue, - result_type=result_type, - schedule_to_close_timeout=schedule_to_close_timeout, - schedule_to_start_timeout=schedule_to_start_timeout, - start_to_close_timeout=start_to_close_timeout, - heartbeat_timeout=heartbeat_timeout, - id_reuse_policy=id_reuse_policy, - id_conflict_policy=id_conflict_policy, - retry_policy=retry_policy, - search_attributes=search_attributes, - summary=summary, - priority=priority, - start_delay=start_delay, - rpc_metadata=rpc_metadata, - rpc_timeout=rpc_timeout, - ) - - def list_activities( - self, - query: str, - *, - limit: int | None = None, - page_size: int = 1000, - next_page_token: bytes | None = None, - rpc_metadata: Mapping[str, str | bytes] = {}, - rpc_timeout: timedelta | None = None, - ) -> ActivityExecutionAsyncIterator: - """List activities not started by a workflow. - - .. warning:: - This API is experimental. - - This does not make a request until the first iteration is attempted. - Therefore any errors will not occur until then. - - Args: - query: A Temporal visibility list filter for activities. Required. - limit: Maximum number of activities to return. If unset, all - activities are returned. Only applies if using the - returned :py:class:`ActivityExecutionAsyncIterator` - as an async iterator. - page_size: Maximum number of results for each page. - next_page_token: A previously obtained next page token if doing - pagination. Usually not needed as the iterator automatically - starts from the beginning. - rpc_metadata: Headers used on each RPC call. Keys here override - client-level RPC metadata keys. - rpc_timeout: Optional RPC deadline to set for each RPC call. - - Returns: - An async iterator that can be used with ``async for``. - """ - return self._impl.list_activities( - ListActivitiesInput( - query=query, - page_size=page_size, - next_page_token=next_page_token, - rpc_metadata=rpc_metadata, - rpc_timeout=rpc_timeout, - limit=limit, - ) - ) - - async def count_activities( - self, - query: str | None = None, - *, - rpc_metadata: Mapping[str, str | bytes] = {}, - rpc_timeout: timedelta | None = None, - ) -> ActivityExecutionCount: - """Count activities not started by a workflow. - - .. warning:: - This API is experimental. - - Args: - query: A Temporal visibility filter for activities. - rpc_metadata: Headers used on the RPC call. Keys here override - client-level RPC metadata keys. - rpc_timeout: Optional RPC deadline to set for the RPC call. - - Returns: - Count of activities. - """ - return await self._impl.count_activities( - CountActivitiesInput( - query=query, rpc_metadata=rpc_metadata, rpc_timeout=rpc_timeout - ) - ) - - @overload - def get_activity_handle( - self, - activity_id: str, - *, - run_id: str | None = None, - ) -> ActivityHandle[Any]: ... - - @overload - def get_activity_handle( - self, - activity_id: str, - *, - run_id: str | None = None, - result_type: type[ReturnType], - ) -> ActivityHandle[ReturnType]: ... - - def get_activity_handle( - self, - activity_id: str, - *, - run_id: str | None = None, - result_type: type | None = None, - ) -> ActivityHandle[Any]: - """Get a handle to an existing activity, as the caller of that activity. - - The activity must not have been started by a workflow. - - .. warning:: - This API is experimental. - - To get a handle to an activity execution that you control for manual completion and - heartbeating, see :py:meth:`Client.get_async_activity_handle`. - - Args: - activity_id: The activity ID. - run_id: The activity run ID. If not provided, targets the latest run. - result_type: The result type to deserialize into. - - Returns: - A handle to the activity. - """ - return ActivityHandle( - self, - activity_id, - run_id=run_id, - result_type=result_type, - ) - - @overload - def get_async_activity_handle( - self, *, activity_id: str, run_id: str | None = None - ) -> AsyncActivityHandle: - pass - - @overload - def get_async_activity_handle( - self, *, workflow_id: str, run_id: str | None, activity_id: str - ) -> AsyncActivityHandle: - pass - - @overload - def get_async_activity_handle(self, *, task_token: bytes) -> AsyncActivityHandle: - pass - - def get_async_activity_handle( - self, - *, - workflow_id: str | None = None, - run_id: str | None = None, - activity_id: str | None = None, - task_token: bytes | None = None, - ) -> AsyncActivityHandle: - """Get a handle to an activity execution that you control, for manual - completion and heartbeating. - - To get a handle to an activity execution as the caller of that activity, - see :py:meth:`Client.get_activity_handle`. - - This function may be used to get a handle to an activity started by a - client, or an activity started by a workflow. - - To get a handle to an activity started by a workflow, use one of the - following two calls: - - Supply ``workflow_id``, ``run_id``, and ``activity_id`` - - Supply the activity ``task_token`` alone - - To get a handle to an activity not started by a workflow, supply - ``activity_id`` and ``run_id`` - - Args: - workflow_id: Workflow ID for the activity, or None if not a workflow - activity. Cannot be set if task_token is set. - run_id: Run ID for the activity or workflow. Cannot be set if - task_token is set. - activity_id: ID for the activity. Cannot be set if task_token is - set. - task_token: Task token for the activity. Cannot be set with other - fields. - - Returns: - A handle that can be used for completion or heartbeating. - """ - if task_token is not None: - if workflow_id is not None or run_id is not None or activity_id is not None: - raise ValueError("Task token cannot be present with other IDs") - return AsyncActivityHandle(self, task_token) - elif workflow_id is not None: - if activity_id is None: - raise ValueError( - "Workflow ID, run ID, and activity ID must all be given together" - ) - return AsyncActivityHandle( - self, - AsyncActivityIDReference( - workflow_id=workflow_id, run_id=run_id, activity_id=activity_id - ), - ) - elif activity_id is not None: - return AsyncActivityHandle( - self, - AsyncActivityIDReference( - activity_id=activity_id, - run_id=run_id, - workflow_id=None, - ), - ) - raise ValueError( - "Require task token, or workflow_id & run_id & activity_id, or activity_id & run_id" - ) - - async def create_schedule( - self, - id: str, - schedule: Schedule, - *, - trigger_immediately: bool = False, - backfill: Sequence[ScheduleBackfill] = [], - memo: Mapping[str, Any] | None = None, - search_attributes: None - | ( - temporalio.common.TypedSearchAttributes | temporalio.common.SearchAttributes - ) = None, - rpc_metadata: Mapping[str, str | bytes] = {}, - rpc_timeout: timedelta | None = None, - ) -> ScheduleHandle: - """Create a schedule and return its handle. - - Args: - id: Unique identifier of the schedule. - schedule: Schedule to create. - trigger_immediately: If true, trigger one action immediately when - creating the schedule. - backfill: Set of time periods to take actions on as if that time - passed right now. - memo: Memo for the schedule. Memo for a scheduled workflow is part - of the schedule action. - search_attributes: Search attributes for the schedule. Search - attributes for a scheduled workflow are part of the scheduled - action. The dictionary form of this is DEPRECATED, use - :py:class:`temporalio.common.TypedSearchAttributes`. - rpc_metadata: Headers used on the RPC call. Keys here override - client-level RPC metadata keys. - rpc_timeout: Optional RPC deadline to set for the RPC call. - - Returns: - A handle to the created schedule. - - Raises: - ScheduleAlreadyRunningError: If a schedule with this ID is already - running. - """ - temporalio.common._warn_on_deprecated_search_attributes(search_attributes) - return await self._impl.create_schedule( - CreateScheduleInput( - id=id, - schedule=schedule, - trigger_immediately=trigger_immediately, - backfill=backfill, - memo=memo, - search_attributes=search_attributes, - rpc_metadata=rpc_metadata, - rpc_timeout=rpc_timeout, - ) - ) - - def get_schedule_handle(self, id: str) -> ScheduleHandle: - """Get a schedule handle for the given ID.""" - return ScheduleHandle(self, id) - - async def list_schedules( - self, - query: str | None = None, - *, - page_size: int = 1000, - next_page_token: bytes | None = None, - rpc_metadata: Mapping[str, str | bytes] = {}, - rpc_timeout: timedelta | None = None, - ) -> ScheduleAsyncIterator: - """List schedules. - - This does not make a request until the first iteration is attempted. - Therefore any errors will not occur until then. - - Note, this list is eventually consistent. Therefore if a schedule is - added or deleted, it may not be available in the list immediately. - - Args: - page_size: Maximum number of results for each page. - query: A Temporal visibility list filter. See Temporal documentation - concerning visibility list filters including behavior when left - unset. - next_page_token: A previously obtained next page token if doing - pagination. Usually not needed as the iterator automatically - starts from the beginning. - rpc_metadata: Headers used on each RPC call. Keys here override - client-level RPC metadata keys. - rpc_timeout: Optional RPC deadline to set for each RPC call. - - Returns: - An async iterator that can be used with ``async for``. - """ - return self._impl.list_schedules( - ListSchedulesInput( - page_size=page_size, - next_page_token=next_page_token, - rpc_metadata=rpc_metadata, - rpc_timeout=rpc_timeout, - query=query, - ) - ) - - async def update_worker_build_id_compatibility( - self, - task_queue: str, - operation: BuildIdOp, - rpc_metadata: Mapping[str, str | bytes] = {}, - rpc_timeout: timedelta | None = None, - ) -> None: - """Used to add new Build IDs or otherwise update the relative compatibility of Build Ids as - defined on a specific task queue for the Worker Versioning feature. - - For more on this feature, see https://docs.temporal.io/workers#worker-versioning - - .. deprecated:: - Legacy API, see the docs above for new usage - - Args: - task_queue: The task queue to target. - operation: The operation to perform. - rpc_metadata: Headers used on each RPC call. Keys here override - client-level RPC metadata keys. - rpc_timeout: Optional RPC deadline to set for each RPC call. - """ - return await self._impl.update_worker_build_id_compatibility( - UpdateWorkerBuildIdCompatibilityInput( - task_queue, - operation, - rpc_metadata=rpc_metadata, - rpc_timeout=rpc_timeout, - ) - ) - - async def get_worker_build_id_compatibility( - self, - task_queue: str, - max_sets: int | None = None, - rpc_metadata: Mapping[str, str | bytes] = {}, - rpc_timeout: timedelta | None = None, - ) -> WorkerBuildIdVersionSets: - """Get the Build ID compatibility sets for a specific task queue. - - For more on this feature, see https://docs.temporal.io/workers#worker-versioning - - .. deprecated:: - Legacy API, see the docs above for new usage - - Args: - task_queue: The task queue to target. - max_sets: The maximum number of sets to return. If not specified, all sets will be - returned. - rpc_metadata: Headers used on each RPC call. Keys here override - client-level RPC metadata keys. - rpc_timeout: Optional RPC deadline to set for each RPC call. - """ - return await self._impl.get_worker_build_id_compatibility( - GetWorkerBuildIdCompatibilityInput( - task_queue, - max_sets, - rpc_metadata=rpc_metadata, - rpc_timeout=rpc_timeout, - ) - ) - - async def get_worker_task_reachability( - self, - build_ids: Sequence[str], - task_queues: Sequence[str] = [], - reachability_type: TaskReachabilityType | None = None, - rpc_metadata: Mapping[str, str | bytes] = {}, - rpc_timeout: timedelta | None = None, - ) -> WorkerTaskReachability: - """Determine if some Build IDs for certain Task Queues could have tasks dispatched to them. - - For more on this feature, see https://docs.temporal.io/workers#worker-versioning - - .. deprecated:: - Legacy API, see the docs above for new usage - - Args: - build_ids: The Build IDs to query the reachability of. At least one must be specified. - task_queues: Task Queues to restrict the query to. If not specified, all Task Queues - will be searched. When requesting a large number of task queues or all task queues - associated with the given Build IDs in a namespace, all Task Queues will be listed - in the response but some of them may not contain reachability information due to a - server enforced limit. When reaching the limit, task queues that reachability - information could not be retrieved for will be marked with a ``NotFetched`` entry in - {@link BuildIdReachability.taskQueueReachability}. The caller may issue another call - to get the reachability for those task queues. - reachability_type: The kind of reachability this request is concerned with. - rpc_metadata: Headers used on each RPC call. Keys here override - client-level RPC metadata keys. - rpc_timeout: Optional RPC deadline to set for each RPC call. - """ - return await self._impl.get_worker_task_reachability( - GetWorkerTaskReachabilityInput( - build_ids, - task_queues, - reachability_type, - rpc_metadata=rpc_metadata, - rpc_timeout=rpc_timeout, - ) - ) - - -class ClientConnectConfig(TypedDict, total=False): - """TypedDict of keyword arguments for :py:meth:`Client.connect`.""" - - target_host: str - namespace: str - api_key: str | None - data_converter: temporalio.converter.DataConverter - plugins: Sequence[Plugin] - interceptors: Sequence[Interceptor] - default_workflow_query_reject_condition: ( - temporalio.common.QueryRejectCondition | None - ) - tls: bool | TLSConfig | None - retry_config: RetryConfig | None - keep_alive_config: KeepAliveConfig | None - rpc_metadata: Mapping[str, str | bytes] - identity: str | None - lazy: bool - runtime: temporalio.runtime.Runtime | None - http_connect_proxy_config: HttpConnectProxyConfig | None - dns_load_balancing_config: DnsLoadBalancingConfig | None - header_codec_behavior: HeaderCodecBehavior - - -class ClientConfig(TypedDict, total=False): - """TypedDict of config originally passed to :py:meth:`Client`.""" - - service_client: Required[temporalio.service.ServiceClient] - namespace: Required[str] - data_converter: Required[temporalio.converter.DataConverter] - plugins: Required[Sequence[Plugin]] - interceptors: Required[Sequence[Interceptor]] - default_workflow_query_reject_condition: Required[ - temporalio.common.QueryRejectCondition | None - ] - header_codec_behavior: Required[HeaderCodecBehavior] - - -class WorkflowHistoryEventFilterType(IntEnum): - """Type of history events to get for a workflow. - - See :py:class:`temporalio.api.enums.v1.HistoryEventFilterType`. - """ - - ALL_EVENT = int( - temporalio.api.enums.v1.HistoryEventFilterType.HISTORY_EVENT_FILTER_TYPE_ALL_EVENT - ) - CLOSE_EVENT = int( - temporalio.api.enums.v1.HistoryEventFilterType.HISTORY_EVENT_FILTER_TYPE_CLOSE_EVENT - ) - - -class WorkflowHandle(Generic[SelfType, ReturnType]): - """Handle for interacting with a workflow. - - This is usually created via :py:meth:`Client.get_workflow_handle` or - returned from :py:meth:`Client.start_workflow`. - """ - - def __init__( - self, - client: Client, - id: str, - *, - run_id: str | None = None, - result_run_id: str | None = None, - first_execution_run_id: str | None = None, - result_type: type | None = None, - start_workflow_response: None - | ( - temporalio.api.workflowservice.v1.StartWorkflowExecutionResponse - | temporalio.api.workflowservice.v1.SignalWithStartWorkflowExecutionResponse - ) = None, - ) -> None: - """Create workflow handle.""" - self._client = client - self._id = id - self._run_id = run_id - self._result_run_id = result_run_id - self._first_execution_run_id = first_execution_run_id - self._result_type = result_type - self._start_workflow_response = start_workflow_response - self.__temporal_eagerly_started = False - - @functools.cached_property - def _data_converter(self) -> temporalio.converter.DataConverter: - return self._client.data_converter.with_context( - temporalio.converter.WorkflowSerializationContext( - namespace=self._client.namespace, workflow_id=self._id - ) - ) - - @property - def id(self) -> str: - """ID of the workflow.""" - return self._id - - @property - def run_id(self) -> str | None: - """If present, run ID used to ensure that requested operations apply - to this exact run. - - This is only created via :py:meth:`Client.get_workflow_handle`. - :py:meth:`Client.start_workflow` will not set this value. - - This cannot be mutated. If a different run ID is needed, - :py:meth:`Client.get_workflow_handle` must be used instead. - """ - return self._run_id - - @property - def result_run_id(self) -> str | None: - """Run ID used for :py:meth:`result` calls if present to ensure result - is for a workflow starting from this run. - - When this handle is created via :py:meth:`Client.get_workflow_handle`, - this is the same as run_id. When this handle is created via - :py:meth:`Client.start_workflow`, this value will be the resulting run - ID. - - This cannot be mutated. If a different run ID is needed, - :py:meth:`Client.get_workflow_handle` must be used instead. - """ - return self._result_run_id - - @property - def first_execution_run_id(self) -> str | None: - """Run ID used to ensure requested operations apply to a workflow ID - started with this run ID. - - This can be set when using :py:meth:`Client.get_workflow_handle`. When - :py:meth:`Client.start_workflow` is called without a start signal, this - is set to the resulting run. - - This cannot be mutated. If a different first execution run ID is needed, - :py:meth:`Client.get_workflow_handle` must be used instead. - """ - return self._first_execution_run_id - - async def result( - self, - *, - follow_runs: bool = True, - rpc_metadata: Mapping[str, str | bytes] = {}, - rpc_timeout: timedelta | None = None, - ) -> ReturnType: - """Wait for result of the workflow. - - This will use :py:attr:`result_run_id` if present to base the result on. - To use another run ID, a new handle must be created via - :py:meth:`Client.get_workflow_handle`. - - Args: - follow_runs: If true (default), workflow runs will be continually - fetched, until the most recent one is found. If false, return - the result from the first run targeted by the request if that run - ends in a result, otherwise raise an exception. - rpc_metadata: Headers used on the RPC call. Keys here override - client-level RPC metadata keys. - rpc_timeout: Optional RPC deadline to set for each RPC call. Note, - this is the timeout for each history RPC call not this overall - function. - - Returns: - Result of the workflow after being converted by the data converter. - - Raises: - WorkflowFailureError: Workflow failed, was cancelled, was - terminated, or timed out. Use the - :py:attr:`WorkflowFailureError.cause` to see the underlying - reason. - Exception: Other possible failures during result fetching. - """ - # We have to maintain our own run ID because it can change if we follow - # executions - hist_run_id = self._result_run_id - while True: - async for event in self._fetch_history_events_for_run( - hist_run_id, - wait_new_event=True, - event_filter_type=WorkflowHistoryEventFilterType.CLOSE_EVENT, - skip_archival=True, - rpc_metadata=rpc_metadata, - rpc_timeout=rpc_timeout, - ): - if event.HasField("workflow_execution_completed_event_attributes"): - complete_attr = event.workflow_execution_completed_event_attributes - # Follow execution - if follow_runs and complete_attr.new_execution_run_id: - hist_run_id = complete_attr.new_execution_run_id - break - # Ignoring anything after the first response like TypeScript - type_hints = [self._result_type] if self._result_type else None - results = await self._data_converter.decode_wrapper( - complete_attr.result, - type_hints, - ) - if not results: - return cast(ReturnType, None) - elif len(results) > 1: - warnings.warn(f"Expected single result, got {len(results)}") - return cast(ReturnType, results[0]) - elif event.HasField("workflow_execution_failed_event_attributes"): - fail_attr = event.workflow_execution_failed_event_attributes - # Follow execution - if follow_runs and fail_attr.new_execution_run_id: - hist_run_id = fail_attr.new_execution_run_id - break - raise WorkflowFailureError( - cause=await self._data_converter.decode_failure( - fail_attr.failure - ), - ) - elif event.HasField("workflow_execution_canceled_event_attributes"): - cancel_attr = event.workflow_execution_canceled_event_attributes - raise WorkflowFailureError( - cause=temporalio.exceptions.CancelledError( - "Workflow cancelled", - *( - await self._data_converter.decode_wrapper( - cancel_attr.details - ) - ), - ) - ) - elif event.HasField("workflow_execution_terminated_event_attributes"): - term_attr = event.workflow_execution_terminated_event_attributes - raise WorkflowFailureError( - cause=temporalio.exceptions.TerminatedError( - term_attr.reason or "Workflow terminated", - *( - await self._data_converter.decode_wrapper( - term_attr.details - ) - ), - ), - ) - elif event.HasField("workflow_execution_timed_out_event_attributes"): - time_attr = event.workflow_execution_timed_out_event_attributes - # Follow execution - if follow_runs and time_attr.new_execution_run_id: - hist_run_id = time_attr.new_execution_run_id - break - raise WorkflowFailureError( - cause=temporalio.exceptions.TimeoutError( - "Workflow timed out", - type=temporalio.exceptions.TimeoutType.START_TO_CLOSE, - last_heartbeat_details=[], - ), - ) - elif event.HasField( - "workflow_execution_continued_as_new_event_attributes" - ): - cont_attr = ( - event.workflow_execution_continued_as_new_event_attributes - ) - if not cont_attr.new_execution_run_id: - raise RuntimeError( - "Unexpectedly missing new run ID from continue as new" - ) - # Follow execution - if follow_runs: - hist_run_id = cont_attr.new_execution_run_id - break - raise WorkflowContinuedAsNewError(cont_attr.new_execution_run_id) - # This is reached on break which means that there's a different run - # ID if we're following. If there's not, it's an error because no - # event was given (should never happen). - if hist_run_id is None: - raise RuntimeError("No completion event found") - - async def cancel( - self, - *, - rpc_metadata: Mapping[str, str | bytes] = {}, - rpc_timeout: timedelta | None = None, - ) -> None: - """Cancel the workflow. - - This will issue a cancellation for :py:attr:`run_id` if present. This - call will make sure to use the run chain starting from - :py:attr:`first_execution_run_id` if present. To create handles with - these values, use :py:meth:`Client.get_workflow_handle`. - - .. warning:: - Handles created as a result of :py:meth:`Client.start_workflow` with - a start signal will cancel the latest workflow with the same - workflow ID even if it is unrelated to the started workflow. - - Args: - rpc_metadata: Headers used on the RPC call. Keys here override - client-level RPC metadata keys. - rpc_timeout: Optional RPC deadline to set for the RPC call. - - Raises: - RPCError: Workflow could not be cancelled. - """ - await self._client._impl.cancel_workflow( - CancelWorkflowInput( - id=self._id, - run_id=self._run_id, - first_execution_run_id=self._first_execution_run_id, - rpc_metadata=rpc_metadata, - rpc_timeout=rpc_timeout, - ) - ) - - async def describe( - self, - *, - rpc_metadata: Mapping[str, str | bytes] = {}, - rpc_timeout: timedelta | None = None, - ) -> WorkflowExecutionDescription: - """Get workflow details. - - This will get details for :py:attr:`run_id` if present. To use a - different run ID, create a new handle with via - :py:meth:`Client.get_workflow_handle`. - - .. warning:: - Handles created as a result of :py:meth:`Client.start_workflow` will - describe the latest workflow with the same workflow ID even if it is - unrelated to the started workflow. - - Args: - rpc_metadata: Headers used on the RPC call. Keys here override - client-level RPC metadata keys. - rpc_timeout: Optional RPC deadline to set for the RPC call. - - Returns: - Workflow details. - - Raises: - RPCError: Workflow details could not be fetched. - """ - return await self._client._impl.describe_workflow( - DescribeWorkflowInput( - id=self._id, - run_id=self._run_id, - rpc_metadata=rpc_metadata, - rpc_timeout=rpc_timeout, - ) - ) - - async def fetch_history( - self, - *, - event_filter_type: WorkflowHistoryEventFilterType = WorkflowHistoryEventFilterType.ALL_EVENT, - skip_archival: bool = False, - rpc_metadata: Mapping[str, str | bytes] = {}, - rpc_timeout: timedelta | None = None, - ) -> WorkflowHistory: - """Get workflow history. - - This is a shortcut for :py:meth:`fetch_history_events` that just fetches - all events. - """ - return WorkflowHistory( - workflow_id=self.id, - events=[ - v - async for v in self.fetch_history_events( - event_filter_type=event_filter_type, - skip_archival=skip_archival, - rpc_metadata=rpc_metadata, - rpc_timeout=rpc_timeout, - ) - ], - ) - - def fetch_history_events( - self, - *, - page_size: int | None = None, - next_page_token: bytes | None = None, - wait_new_event: bool = False, - event_filter_type: WorkflowHistoryEventFilterType = WorkflowHistoryEventFilterType.ALL_EVENT, - skip_archival: bool = False, - rpc_metadata: Mapping[str, str | bytes] = {}, - rpc_timeout: timedelta | None = None, - ) -> WorkflowHistoryEventAsyncIterator: - """Get workflow history events as an async iterator. - - This does not make a request until the first iteration is attempted. - Therefore any errors will not occur until then. - - Args: - page_size: Maximum amount to fetch per request if any maximum. - next_page_token: A specific page token to fetch. - wait_new_event: Whether the event fetching request will wait for new - events or just return right away. - event_filter_type: Which events to obtain. - skip_archival: Whether to skip archival. - rpc_metadata: Headers used on each RPC call. Keys here override - client-level RPC metadata keys. - rpc_timeout: Optional RPC deadline to set for each RPC call. - - Returns: - An async iterator that doesn't begin fetching until iterated on. - """ - return self._fetch_history_events_for_run( - self._run_id, - page_size=page_size, - next_page_token=next_page_token, - wait_new_event=wait_new_event, - event_filter_type=event_filter_type, - skip_archival=skip_archival, - rpc_metadata=rpc_metadata, - rpc_timeout=rpc_timeout, - ) - - def _fetch_history_events_for_run( - self, - run_id: str | None, - *, - page_size: int | None = None, - next_page_token: bytes | None = None, - wait_new_event: bool = False, - event_filter_type: WorkflowHistoryEventFilterType = WorkflowHistoryEventFilterType.ALL_EVENT, - skip_archival: bool = False, - rpc_metadata: Mapping[str, str | bytes] = {}, - rpc_timeout: timedelta | None = None, - ) -> WorkflowHistoryEventAsyncIterator: - return self._client._impl.fetch_workflow_history_events( - FetchWorkflowHistoryEventsInput( - id=self._id, - run_id=run_id, - page_size=page_size, - next_page_token=next_page_token, - wait_new_event=wait_new_event, - event_filter_type=event_filter_type, - skip_archival=skip_archival, - rpc_metadata=rpc_metadata, - rpc_timeout=rpc_timeout, - ) - ) - - # Overload for no-param query - @overload - async def query( - self, - query: MethodSyncOrAsyncNoParam[SelfType, LocalReturnType], - *, - reject_condition: temporalio.common.QueryRejectCondition | None = None, - rpc_metadata: Mapping[str, str | bytes] = {}, - rpc_timeout: timedelta | None = None, - ) -> LocalReturnType: ... - - # Overload for single-param query - @overload - async def query( - self, - query: MethodSyncOrAsyncSingleParam[SelfType, ParamType, LocalReturnType], - arg: ParamType, - *, - reject_condition: temporalio.common.QueryRejectCondition | None = None, - rpc_metadata: Mapping[str, str | bytes] = {}, - rpc_timeout: timedelta | None = None, - ) -> LocalReturnType: ... - - # Overload for multi-param query - @overload - async def query( - self, - query: Callable[ - Concatenate[SelfType, MultiParamSpec], - Awaitable[LocalReturnType] | LocalReturnType, - ], - *, - args: Sequence[Any], - reject_condition: temporalio.common.QueryRejectCondition | None = None, - rpc_metadata: Mapping[str, str | bytes] = {}, - rpc_timeout: timedelta | None = None, - ) -> LocalReturnType: ... - - # Overload for string-name query - @overload - async def query( - self, - query: str, - arg: Any = temporalio.common._arg_unset, - *, - args: Sequence[Any] = [], - result_type: type | None = None, - reject_condition: temporalio.common.QueryRejectCondition | None = None, - rpc_metadata: Mapping[str, str | bytes] = {}, - rpc_timeout: timedelta | None = None, - ) -> Any: ... - - async def query( - self, - query: str | Callable, - arg: Any = temporalio.common._arg_unset, - *, - args: Sequence[Any] = [], - result_type: type | None = None, - reject_condition: temporalio.common.QueryRejectCondition | None = None, - rpc_metadata: Mapping[str, str | bytes] = {}, - rpc_timeout: timedelta | None = None, - ) -> Any: - """Query the workflow. - - This will query for :py:attr:`run_id` if present. To use a different - run ID, create a new handle with - :py:meth:`Client.get_workflow_handle`. - - .. warning:: - Handles created as a result of :py:meth:`Client.start_workflow` will - query the latest workflow with the same workflow ID even if it is - unrelated to the started workflow. - - Args: - query: Query function or name on the workflow. - arg: Single argument to the query. - args: Multiple arguments to the query. Cannot be set if arg is. - result_type: For string queries, this can set the specific result - type hint to deserialize into. - reject_condition: Condition for rejecting the query. If unset/None, - defaults to the client's default (which is defaulted to None). - rpc_metadata: Headers used on the RPC call. Keys here override - client-level RPC metadata keys. - rpc_timeout: Optional RPC deadline to set for the RPC call. - - Returns: - Result of the query. - - Raises: - WorkflowQueryRejectedError: A query reject condition was satisfied. - RPCError: Workflow details could not be fetched. - """ - query_name: str - ret_type = result_type - if callable(query): - defn = temporalio.workflow._QueryDefinition.from_fn(query) - if not defn: - raise RuntimeError( - f"Query definition not found on {query.__qualname__}, " - "is it decorated with @workflow.query?" - ) - elif not defn.name: - raise RuntimeError("Cannot invoke dynamic query definition") - # TODO(cretz): Check count/type of args at runtime? - query_name = defn.name - ret_type = defn.ret_type - else: - query_name = str(query) - - return await self._client._impl.query_workflow( - QueryWorkflowInput( - id=self._id, - run_id=self._run_id, - query=query_name, - args=temporalio.common._arg_or_args(arg, args), - reject_condition=reject_condition - or self._client._config["default_workflow_query_reject_condition"], - headers={}, - ret_type=ret_type, - rpc_metadata=rpc_metadata, - rpc_timeout=rpc_timeout, - ) - ) - - # Overload for no-param signal - @overload - async def signal( - self, - signal: MethodSyncOrAsyncNoParam[SelfType, None], - *, - rpc_metadata: Mapping[str, str | bytes] = {}, - rpc_timeout: timedelta | None = None, - ) -> None: ... - - # Overload for single-param signal - @overload - async def signal( - self, - signal: MethodSyncOrAsyncSingleParam[SelfType, ParamType, None], - arg: ParamType, - *, - rpc_metadata: Mapping[str, str | bytes] = {}, - rpc_timeout: timedelta | None = None, - ) -> None: ... - - # Overload for multi-param signal - @overload - async def signal( - self, - signal: Callable[Concatenate[SelfType, MultiParamSpec], Awaitable[None] | None], - *, - args: Sequence[Any], - rpc_metadata: Mapping[str, str | bytes] = {}, - rpc_timeout: timedelta | None = None, - ) -> None: ... - - # Overload for string-name signal - @overload - async def signal( - self, - signal: str, - arg: Any = temporalio.common._arg_unset, - *, - args: Sequence[Any] = [], - rpc_metadata: Mapping[str, str | bytes] = {}, - rpc_timeout: timedelta | None = None, - ) -> None: ... - - async def signal( - self, - signal: str | Callable, - arg: Any = temporalio.common._arg_unset, - *, - args: Sequence[Any] = [], - rpc_metadata: Mapping[str, str | bytes] = {}, - rpc_timeout: timedelta | None = None, - ) -> None: - """Send a signal to the workflow. - - This will signal for :py:attr:`run_id` if present. To use a different - run ID, create a new handle with via - :py:meth:`Client.get_workflow_handle`. - - .. warning:: - Handles created as a result of :py:meth:`Client.start_workflow` will - signal the latest workflow with the same workflow ID even if it is - unrelated to the started workflow. - - Args: - signal: Signal function or name on the workflow. - arg: Single argument to the signal. - args: Multiple arguments to the signal. Cannot be set if arg is. - rpc_metadata: Headers used on the RPC call. Keys here override - client-level RPC metadata keys. - rpc_timeout: Optional RPC deadline to set for the RPC call. - - Raises: - RPCError: Workflow could not be signalled. - """ - await self._client._impl.signal_workflow( - SignalWorkflowInput( - id=self._id, - run_id=self._run_id, - signal=temporalio.workflow._SignalDefinition.must_name_from_fn_or_str( - signal - ), - args=temporalio.common._arg_or_args(arg, args), - headers={}, - rpc_metadata=rpc_metadata, - rpc_timeout=rpc_timeout, - ) - ) - - async def terminate( - self, - *args: Any, - reason: str | None = None, - rpc_metadata: Mapping[str, str | bytes] = {}, - rpc_timeout: timedelta | None = None, - ) -> None: - """Terminate the workflow. - - This will issue a termination for :py:attr:`run_id` if present. This - call will make sure to use the run chain starting from - :py:attr:`first_execution_run_id` if present. To create handles with - these values, use :py:meth:`Client.get_workflow_handle`. - - .. warning:: - Handles created as a result of :py:meth:`Client.start_workflow` with - a start signal will terminate the latest workflow with the same - workflow ID even if it is unrelated to the started workflow. - - Args: - args: Details to store on the termination. - reason: Reason for the termination. - rpc_metadata: Headers used on the RPC call. Keys here override - client-level RPC metadata keys. - rpc_timeout: Optional RPC deadline to set for the RPC call. - - Raises: - RPCError: Workflow could not be terminated. - """ - await self._client._impl.terminate_workflow( - TerminateWorkflowInput( - id=self._id, - run_id=self._run_id, - args=args, - reason=reason, - first_execution_run_id=self._first_execution_run_id, - rpc_metadata=rpc_metadata, - rpc_timeout=rpc_timeout, - ) - ) - - # Overload for no-param update - @overload - async def execute_update( - self, - update: temporalio.workflow.UpdateMethodMultiParam[[SelfType], LocalReturnType], - *, - id: str | None = None, - rpc_metadata: Mapping[str, str | bytes] = {}, - rpc_timeout: timedelta | None = None, - ) -> LocalReturnType: ... - - # Overload for single-param update - @overload - async def execute_update( - self, - update: temporalio.workflow.UpdateMethodMultiParam[ - [SelfType, ParamType], LocalReturnType - ], - arg: ParamType, - *, - id: str | None = None, - rpc_metadata: Mapping[str, str | bytes] = {}, - rpc_timeout: timedelta | None = None, - ) -> LocalReturnType: ... - - # Overload for multi-param update - @overload - async def execute_update( - self, - update: temporalio.workflow.UpdateMethodMultiParam[ - MultiParamSpec, LocalReturnType - ], - *, - args: MultiParamSpec.args, # type: ignore - id: str | None = None, - rpc_metadata: Mapping[str, str | bytes] = {}, - rpc_timeout: timedelta | None = None, - ) -> LocalReturnType: ... - - # Overload for string-name update - @overload - async def execute_update( - self, - update: str, - arg: Any = temporalio.common._arg_unset, - *, - args: Sequence[Any] = [], - id: str | None = None, - result_type: type | None = None, - rpc_metadata: Mapping[str, str | bytes] = {}, - rpc_timeout: timedelta | None = None, - ) -> Any: ... - - async def execute_update( - self, - update: str | Callable, - arg: Any = temporalio.common._arg_unset, - *, - args: Sequence[Any] = [], - id: str | None = None, - result_type: type | None = None, - rpc_metadata: Mapping[str, str | bytes] = {}, - rpc_timeout: timedelta | None = None, - ) -> Any: - """Send an update request to the workflow and wait for it to complete. - - This will target the workflow with :py:attr:`run_id` if present. To use a - different run ID, create a new handle with via :py:meth:`Client.get_workflow_handle`. - - Args: - update: Update function or name on the workflow. - arg: Single argument to the update. - args: Multiple arguments to the update. Cannot be set if arg is. - id: ID of the update. If not set, the default is a new UUID. - result_type: For string updates, this can set the specific result - type hint to deserialize into. - rpc_metadata: Headers used on the RPC call. Keys here override - client-level RPC metadata keys. - rpc_timeout: Optional RPC deadline to set for the RPC call. - - Raises: - WorkflowUpdateFailedError: If the update failed. - WorkflowUpdateRPCTimeoutOrCancelledError: This update call timed out - or was cancelled. This doesn't mean the update itself was timed - out or cancelled. - RPCError: There was some issue sending the update to the workflow. - """ - handle = await self._start_update( - update, - arg, - args=args, - wait_for_stage=WorkflowUpdateStage.COMPLETED, - id=id, - result_type=result_type, - rpc_metadata=rpc_metadata, - rpc_timeout=rpc_timeout, - ) - return await handle.result() - - # Overload for no-param start update - @overload - async def start_update( - self, - update: temporalio.workflow.UpdateMethodMultiParam[[SelfType], LocalReturnType], - *, - wait_for_stage: WorkflowUpdateStage, - id: str | None = None, - rpc_metadata: Mapping[str, str | bytes] = {}, - rpc_timeout: timedelta | None = None, - ) -> WorkflowUpdateHandle[LocalReturnType]: ... - - # Overload for single-param start update - @overload - async def start_update( - self, - update: temporalio.workflow.UpdateMethodMultiParam[ - [SelfType, ParamType], LocalReturnType - ], - arg: ParamType, - *, - wait_for_stage: WorkflowUpdateStage, - id: str | None = None, - rpc_metadata: Mapping[str, str | bytes] = {}, - rpc_timeout: timedelta | None = None, - ) -> WorkflowUpdateHandle[LocalReturnType]: ... - - # Overload for multi-param start update - @overload - async def start_update( - self, - update: temporalio.workflow.UpdateMethodMultiParam[ - MultiParamSpec, LocalReturnType - ], - *, - args: MultiParamSpec.args, # type: ignore - wait_for_stage: WorkflowUpdateStage, - id: str | None = None, - rpc_metadata: Mapping[str, str | bytes] = {}, - rpc_timeout: timedelta | None = None, - ) -> WorkflowUpdateHandle[LocalReturnType]: ... - - # Overload for string-name start update - @overload - async def start_update( - self, - update: str, - arg: Any = temporalio.common._arg_unset, - *, - wait_for_stage: WorkflowUpdateStage, - args: Sequence[Any] = [], - id: str | None = None, - result_type: type | None = None, - rpc_metadata: Mapping[str, str | bytes] = {}, - rpc_timeout: timedelta | None = None, - ) -> WorkflowUpdateHandle[Any]: ... - - async def start_update( - self, - update: str | Callable, - arg: Any = temporalio.common._arg_unset, - *, - wait_for_stage: WorkflowUpdateStage, - args: Sequence[Any] = [], - id: str | None = None, - result_type: type | None = None, - rpc_metadata: Mapping[str, str | bytes] = {}, - rpc_timeout: timedelta | None = None, - ) -> WorkflowUpdateHandle[Any]: - """Send an update request to the workflow and return a handle to it. - - This will target the workflow with :py:attr:`run_id` if present. To use a - different run ID, create a new handle with via :py:meth:`Client.get_workflow_handle`. - - Args: - update: Update function or name on the workflow. arg: Single argument to the - update. - wait_for_stage: Required stage to wait until returning: either ACCEPTED or - COMPLETED. ADMITTED is not currently supported. See - https://docs.temporal.io/workflows#update for more details. - args: Multiple arguments to the update. Cannot be set if arg is. - id: ID of the update. If not set, the default is a new UUID. - result_type: For string updates, this can set the specific result - type hint to deserialize into. - rpc_metadata: Headers used on the RPC call. Keys here override - client-level RPC metadata keys. - rpc_timeout: Optional RPC deadline to set for the RPC call. - - Raises: - WorkflowUpdateRPCTimeoutOrCancelledError: This update call timed out - or was cancelled. This doesn't mean the update itself was timed out or - cancelled. - RPCError: There was some issue sending the update to the workflow. - """ - return await self._start_update( - update, - arg, - wait_for_stage=wait_for_stage, - args=args, - id=id, - result_type=result_type, - rpc_metadata=rpc_metadata, - rpc_timeout=rpc_timeout, - ) - - async def _start_update( - self, - update: str | Callable, - arg: Any = temporalio.common._arg_unset, - *, - wait_for_stage: WorkflowUpdateStage, - args: Sequence[Any] = [], - id: str | None = None, - result_type: type | None = None, - rpc_metadata: Mapping[str, str | bytes] = {}, - rpc_timeout: timedelta | None = None, - ) -> WorkflowUpdateHandle[Any]: - if wait_for_stage == WorkflowUpdateStage.ADMITTED: - raise ValueError("ADMITTED wait stage not supported") - - update_name, result_type_from_type_hint = ( - temporalio.workflow._UpdateDefinition.get_name_and_result_type(update) - ) - - return await self._client._impl.start_workflow_update( - StartWorkflowUpdateInput( - id=self._id, - run_id=self._run_id, - first_execution_run_id=self.first_execution_run_id, - update_id=id, - update=update_name, - args=temporalio.common._arg_or_args(arg, args), - headers={}, - ret_type=result_type or result_type_from_type_hint, - rpc_metadata=rpc_metadata, - rpc_timeout=rpc_timeout, - wait_for_stage=wait_for_stage, - ) - ) - - def get_update_handle( - self, - id: str, - *, - workflow_run_id: str | None = None, - result_type: type | None = None, - ) -> WorkflowUpdateHandle[Any]: - """Get a handle for an update. The handle can be used to wait on the - update result. - - Users may prefer the more typesafe :py:meth:`get_update_handle_for` - which accepts an update definition. - - Args: - id: Update ID to get a handle to. - workflow_run_id: Run ID to tie the handle to. If this is not set, - the :py:attr:`run_id` will be used. - result_type: The result type to deserialize into if known. - - Returns: - The update handle. - """ - return WorkflowUpdateHandle( - self._client, - id, - self._id, - workflow_run_id=workflow_run_id or self._run_id, - result_type=result_type, - ) - - def get_update_handle_for( - self, - update: temporalio.workflow.UpdateMethodMultiParam[Any, LocalReturnType], - id: str, - *, - workflow_run_id: str | None = None, - ) -> WorkflowUpdateHandle[LocalReturnType]: - """Get a typed handle for an update. The handle can be used to wait on - the update result. - - This is the same as :py:meth:`get_update_handle` but typed. - - Args: - update: The update method to use for typing the handle. - id: Update ID to get a handle to. - workflow_run_id: Run ID to tie the handle to. If this is not set, - the :py:attr:`run_id` will be used. - - Returns: - The update handle. - """ - return self.get_update_handle( - id, workflow_run_id=workflow_run_id, result_type=update._defn.ret_type - ) - - -class WithStartWorkflowOperation(Generic[SelfType, ReturnType]): - """Defines a start-workflow operation used by update-with-start requests. - - Update-With-Start allows you to send an update to a workflow, while starting the - workflow if necessary. - """ - - # Overload for no-param workflow, with_start - @overload - def __init__( - self, - workflow: MethodAsyncNoParam[SelfType, ReturnType], - *, - id: str, - task_queue: str, - id_conflict_policy: temporalio.common.WorkflowIDConflictPolicy, - execution_timeout: timedelta | None = None, - run_timeout: timedelta | None = None, - task_timeout: timedelta | None = None, - id_reuse_policy: temporalio.common.WorkflowIDReusePolicy = temporalio.common.WorkflowIDReusePolicy.ALLOW_DUPLICATE, - retry_policy: temporalio.common.RetryPolicy | None = None, - cron_schedule: str = "", - memo: Mapping[str, Any] | None = None, - search_attributes: None - | ( - temporalio.common.TypedSearchAttributes | temporalio.common.SearchAttributes - ) = None, - static_summary: str | None = None, - static_details: str | None = None, - start_delay: timedelta | None = None, - rpc_metadata: Mapping[str, str | bytes] = {}, - rpc_timeout: timedelta | None = None, - priority: temporalio.common.Priority = temporalio.common.Priority.default, - versioning_override: temporalio.common.VersioningOverride | None = None, - ) -> None: ... - - # Overload for single-param workflow, with_start - @overload - def __init__( - self, - workflow: MethodAsyncSingleParam[SelfType, ParamType, ReturnType], - arg: ParamType, - *, - id: str, - task_queue: str, - id_conflict_policy: temporalio.common.WorkflowIDConflictPolicy, - execution_timeout: timedelta | None = None, - run_timeout: timedelta | None = None, - task_timeout: timedelta | None = None, - id_reuse_policy: temporalio.common.WorkflowIDReusePolicy = temporalio.common.WorkflowIDReusePolicy.ALLOW_DUPLICATE, - retry_policy: temporalio.common.RetryPolicy | None = None, - cron_schedule: str = "", - memo: Mapping[str, Any] | None = None, - search_attributes: None - | ( - temporalio.common.TypedSearchAttributes | temporalio.common.SearchAttributes - ) = None, - static_summary: str | None = None, - static_details: str | None = None, - start_delay: timedelta | None = None, - rpc_metadata: Mapping[str, str | bytes] = {}, - rpc_timeout: timedelta | None = None, - priority: temporalio.common.Priority = temporalio.common.Priority.default, - versioning_override: temporalio.common.VersioningOverride | None = None, - ) -> None: ... - - # Overload for multi-param workflow, with_start - @overload - def __init__( - self, - workflow: Callable[ - Concatenate[SelfType, MultiParamSpec], Awaitable[ReturnType] - ], - *, - args: Sequence[Any], - id: str, - task_queue: str, - id_conflict_policy: temporalio.common.WorkflowIDConflictPolicy, - execution_timeout: timedelta | None = None, - run_timeout: timedelta | None = None, - task_timeout: timedelta | None = None, - id_reuse_policy: temporalio.common.WorkflowIDReusePolicy = temporalio.common.WorkflowIDReusePolicy.ALLOW_DUPLICATE, - retry_policy: temporalio.common.RetryPolicy | None = None, - cron_schedule: str = "", - memo: Mapping[str, Any] | None = None, - search_attributes: None - | ( - temporalio.common.TypedSearchAttributes | temporalio.common.SearchAttributes - ) = None, - static_summary: str | None = None, - static_details: str | None = None, - start_delay: timedelta | None = None, - rpc_metadata: Mapping[str, str | bytes] = {}, - rpc_timeout: timedelta | None = None, - priority: temporalio.common.Priority = temporalio.common.Priority.default, - versioning_override: temporalio.common.VersioningOverride | None = None, - ) -> None: ... - - # Overload for string-name workflow, with_start - @overload - def __init__( - self, - workflow: str, - arg: Any = temporalio.common._arg_unset, - *, - args: Sequence[Any] = [], - id: str, - task_queue: str, - id_conflict_policy: temporalio.common.WorkflowIDConflictPolicy, - result_type: type | None = None, - execution_timeout: timedelta | None = None, - run_timeout: timedelta | None = None, - task_timeout: timedelta | None = None, - id_reuse_policy: temporalio.common.WorkflowIDReusePolicy = temporalio.common.WorkflowIDReusePolicy.ALLOW_DUPLICATE, - retry_policy: temporalio.common.RetryPolicy | None = None, - cron_schedule: str = "", - memo: Mapping[str, Any] | None = None, - search_attributes: None - | ( - temporalio.common.TypedSearchAttributes | temporalio.common.SearchAttributes - ) = None, - static_summary: str | None = None, - static_details: str | None = None, - start_delay: timedelta | None = None, - rpc_metadata: Mapping[str, str | bytes] = {}, - rpc_timeout: timedelta | None = None, - priority: temporalio.common.Priority = temporalio.common.Priority.default, - versioning_override: temporalio.common.VersioningOverride | None = None, - ) -> None: ... - - def __init__( - self, - workflow: str | Callable[..., Awaitable[Any]], - arg: Any = temporalio.common._arg_unset, - *, - args: Sequence[Any] = [], - id: str, - task_queue: str, - id_conflict_policy: temporalio.common.WorkflowIDConflictPolicy, - result_type: type | None = None, - execution_timeout: timedelta | None = None, - run_timeout: timedelta | None = None, - task_timeout: timedelta | None = None, - id_reuse_policy: temporalio.common.WorkflowIDReusePolicy = temporalio.common.WorkflowIDReusePolicy.ALLOW_DUPLICATE, - retry_policy: temporalio.common.RetryPolicy | None = None, - cron_schedule: str = "", - memo: Mapping[str, Any] | None = None, - search_attributes: None - | ( - temporalio.common.TypedSearchAttributes | temporalio.common.SearchAttributes - ) = None, - static_summary: str | None = None, - static_details: str | None = None, - start_delay: timedelta | None = None, - rpc_metadata: Mapping[str, str | bytes] = {}, - rpc_timeout: timedelta | None = None, - priority: temporalio.common.Priority = temporalio.common.Priority.default, - versioning_override: temporalio.common.VersioningOverride | None = None, - stack_level: int = 2, - ) -> None: - """Create a WithStartWorkflowOperation. - - See :py:meth:`temporalio.client.Client.start_workflow` for documentation of the - arguments. - """ - temporalio.common._warn_on_deprecated_search_attributes( - search_attributes, stack_level=stack_level - ) - name, result_type_from_run_fn = ( - temporalio.workflow._Definition.get_name_and_result_type(workflow) - ) - if id_conflict_policy == temporalio.common.WorkflowIDConflictPolicy.UNSPECIFIED: - raise ValueError("WorkflowIDConflictPolicy is required") - - self._start_workflow_input = UpdateWithStartStartWorkflowInput( - workflow=name, - args=temporalio.common._arg_or_args(arg, args), - id=id, - task_queue=task_queue, - execution_timeout=execution_timeout, - run_timeout=run_timeout, - task_timeout=task_timeout, - id_reuse_policy=id_reuse_policy, - id_conflict_policy=id_conflict_policy, - retry_policy=retry_policy, - cron_schedule=cron_schedule, - memo=memo, - search_attributes=search_attributes, - static_summary=static_summary, - static_details=static_details, - start_delay=start_delay, - headers={}, - ret_type=result_type or result_type_from_run_fn, - rpc_metadata=rpc_metadata, - rpc_timeout=rpc_timeout, - priority=priority, - versioning_override=versioning_override, - ) - self._workflow_handle: Future[WorkflowHandle[SelfType, ReturnType]] = Future() - self._used = False - - async def workflow_handle(self) -> WorkflowHandle[SelfType, ReturnType]: - """Wait until workflow is running and return a WorkflowHandle.""" - return await self._workflow_handle - - -class ActivityExecutionAsyncIterator: - """Asynchronous iterator for activity execution values. - - You should typically use ``async for`` on this iterator and not call any of its methods. - - .. warning:: - This API is experimental. - """ - - def __init__( - self, - client: Client, - input: ListActivitiesInput, - ) -> None: - """Create an asynchronous iterator for the given input. - - Users should not create this directly, but rather use - :py:meth:`Client.list_activities`. - """ - self._client = client - self._input = input - self._next_page_token = input.next_page_token - self._current_page: Sequence[ActivityExecution] | None = None - self._current_page_index = 0 - self._limit = input.limit - self._yielded = 0 - - @property - def current_page_index(self) -> int: - """Index of the entry in the current page that will be returned from - the next :py:meth:`__anext__` call. - """ - return self._current_page_index - - @property - def current_page(self) -> Sequence[ActivityExecution] | None: - """Current page, if it has been fetched yet.""" - return self._current_page - - @property - def next_page_token(self) -> bytes | None: - """Token for the next page request if any.""" - return self._next_page_token - - async def fetch_next_page(self, *, page_size: int | None = None) -> None: - """Fetch the next page of results. - - Args: - page_size: Override the page size this iterator was originally - created with. - """ - page_size = page_size or self._input.page_size - if self._limit is not None and self._limit - self._yielded < page_size: - page_size = self._limit - self._yielded - - resp = await self._client.workflow_service.list_activity_executions( - temporalio.api.workflowservice.v1.ListActivityExecutionsRequest( - namespace=self._client.namespace, - page_size=page_size, - next_page_token=self._next_page_token or b"", - query=self._input.query or "", - ), - retry=True, - metadata=self._input.rpc_metadata, - timeout=self._input.rpc_timeout, - ) - - self._current_page = [ - ActivityExecution._from_raw_info(v, self._client.namespace) - for v in resp.executions - ] - self._current_page_index = 0 - self._next_page_token = resp.next_page_token or None - - def __aiter__(self) -> ActivityExecutionAsyncIterator: - """Return self as the iterator.""" - return self - - async def __anext__(self) -> ActivityExecution: - """Get the next execution on this iterator, fetching next page if - necessary. - """ - if self._limit is not None and self._yielded >= self._limit: - raise StopAsyncIteration - while True: - # No page? fetch and continue - if self._current_page is None: - await self.fetch_next_page() - continue - # No more left in page? - if self._current_page_index >= len(self._current_page): - # If there is a next page token, try to get another page and try - # again - if self._next_page_token is not None: - await self.fetch_next_page() - continue - # No more pages means we're done - raise StopAsyncIteration - # Get current, increment page index, and return - ret = self._current_page[self._current_page_index] - self._current_page_index += 1 - self._yielded += 1 - return ret - - -@dataclass(frozen=True) -class ActivityExecution: - """Info for an activity execution not started by a workflow, from list response. - - .. warning:: - This API is experimental. - """ - - activity_id: str - """Activity ID.""" - - activity_run_id: str | None - """Run ID of the activity.""" - - activity_type: str - """Type name of the activity.""" - - close_time: datetime | None - """Time the activity reached a terminal status, if closed.""" - - execution_duration: timedelta | None - """Duration from scheduled to close time, only populated if closed.""" - - namespace: str - """Namespace of the activity (copied from calling client).""" - - raw_info: ( - temporalio.api.activity.v1.ActivityExecutionListInfo - | temporalio.api.activity.v1.ActivityExecutionInfo - ) - """Underlying protobuf info.""" - - scheduled_time: datetime - """Time the activity was originally scheduled.""" - - state_transition_count: int | None - """Number of state transitions, if available.""" - - status: ActivityExecutionStatus - """Current status of the activity.""" - - task_queue: str - """Task queue the activity was scheduled on.""" - - typed_search_attributes: temporalio.common.TypedSearchAttributes - """Current set of search attributes if any.""" - - @classmethod - def _from_raw_info( - cls, info: temporalio.api.activity.v1.ActivityExecutionListInfo, namespace: str - ) -> Self: - """Create from raw proto activity list info.""" - return cls( - activity_id=info.activity_id, - activity_run_id=info.run_id or None, - activity_type=( - info.activity_type.name if info.HasField("activity_type") else "" - ), - close_time=( - info.close_time.ToDatetime().replace(tzinfo=timezone.utc) - if info.HasField("close_time") - else None - ), - execution_duration=( - info.execution_duration.ToTimedelta() - if info.HasField("execution_duration") - else None - ), - namespace=namespace, - raw_info=info, - scheduled_time=( - info.schedule_time.ToDatetime().replace(tzinfo=timezone.utc) - if info.HasField("schedule_time") - else datetime.min - ), - state_transition_count=( - info.state_transition_count if info.state_transition_count else None - ), - status=( - ActivityExecutionStatus(info.status) - if info.status - else ActivityExecutionStatus.UNSPECIFIED - ), - task_queue=info.task_queue, - typed_search_attributes=temporalio.converter.decode_typed_search_attributes( - info.search_attributes - ), - ) - - -@dataclass(frozen=True) -class ActivityExecutionDescription(ActivityExecution): - """Detailed information about an activity execution not started by a workflow. - - .. warning:: - This API is experimental. - """ - - attempt: int - """Current attempt number.""" - - canceled_reason: str | None - """Reason for cancellation, if cancel was requested.""" - - current_retry_interval: timedelta | None - """Time until the next retry, if applicable.""" - - eager_execution_requested: bool - """Whether eager execution was requested for this activity.""" - - expiration_time: datetime - """Scheduled time plus schedule_to_close_timeout.""" - - last_attempt_complete_time: datetime | None - """Time when the last attempt completed.""" - - last_failure: Exception | None - """Failure from the last failed attempt, if any.""" - - last_heartbeat_time: datetime | None - """Time of the last heartbeat.""" - - last_started_time: datetime | None - """Time the last attempt was started.""" - - last_worker_identity: str - """Identity of the last worker that processed the activity.""" - - next_attempt_schedule_time: datetime | None - """Time when the next attempt will be scheduled.""" - - paused: bool - """Whether the activity is paused.""" - - raw_heartbeat_details: Sequence[temporalio.api.common.v1.Payload] - """Details from the last heartbeat.""" - - retry_policy: temporalio.common.RetryPolicy | None - """Retry policy for the activity.""" - - run_state: PendingActivityState | None - """More detailed breakdown if status is RUNNING.""" - - long_poll_token: bytes | None - """Token for follow-on long-poll requests. None if the activity is complete.""" - - @classmethod - async def _from_execution_info( - cls, - info: temporalio.api.activity.v1.ActivityExecutionInfo, - long_poll_token: bytes | None, - namespace: str, - data_converter: temporalio.converter.DataConverter, - ) -> Self: - """Create from raw proto activity execution info.""" - # Decode heartbeat details if present - decoded_heartbeat_details: Sequence[temporalio.api.common.v1.Payload] = ( - info.heartbeat_details.payloads - ) - if decoded_heartbeat_details and data_converter.payload_codec: - decoded_heartbeat_details = await data_converter.payload_codec.decode( - decoded_heartbeat_details - ) - - return cls( - activity_id=info.activity_id, - activity_run_id=info.run_id or None, - activity_type=( - info.activity_type.name if info.HasField("activity_type") else "" - ), - attempt=info.attempt, - canceled_reason=info.canceled_reason or None, - close_time=( - info.close_time.ToDatetime(tzinfo=timezone.utc) - if info.HasField("close_time") - else None - ), - current_retry_interval=( - info.current_retry_interval.ToTimedelta() - if info.HasField("current_retry_interval") - else None - ), - eager_execution_requested=getattr(info, "eager_execution_requested", False), - execution_duration=( - info.execution_duration.ToTimedelta() - if info.HasField("execution_duration") - else None - ), - expiration_time=( - info.expiration_time.ToDatetime(tzinfo=timezone.utc) - if info.HasField("expiration_time") - else datetime.min - ), - last_attempt_complete_time=( - info.last_attempt_complete_time.ToDatetime(tzinfo=timezone.utc) - if info.HasField("last_attempt_complete_time") - else None - ), - last_failure=( - cast( - Exception | None, - await data_converter.decode_failure(info.last_failure), - ) - if info.HasField("last_failure") - else None - ), - last_heartbeat_time=( - info.last_heartbeat_time.ToDatetime(tzinfo=timezone.utc) - if info.HasField("last_heartbeat_time") - else None - ), - last_started_time=( - info.last_started_time.ToDatetime(tzinfo=timezone.utc) - if info.HasField("last_started_time") - else None - ), - last_worker_identity=info.last_worker_identity, - long_poll_token=long_poll_token or None, - namespace=namespace, - next_attempt_schedule_time=( - info.next_attempt_schedule_time.ToDatetime(tzinfo=timezone.utc) - if info.HasField("next_attempt_schedule_time") - else None - ), - paused=getattr(info, "paused", False), - raw_heartbeat_details=decoded_heartbeat_details, - raw_info=info, - retry_policy=temporalio.common.RetryPolicy.from_proto(info.retry_policy) - if info.HasField("retry_policy") - else None, - run_state=( - PendingActivityState(info.run_state) if info.run_state else None - ), - scheduled_time=(info.schedule_time.ToDatetime(tzinfo=timezone.utc)), - state_transition_count=( - info.state_transition_count if info.state_transition_count else None - ), - status=( - ActivityExecutionStatus(info.status) - if info.status - else ActivityExecutionStatus.UNSPECIFIED - ), - task_queue=info.task_queue, - typed_search_attributes=temporalio.converter.decode_typed_search_attributes( - info.search_attributes - ), - ) - - -class ActivityExecutionStatus(IntEnum): - """Status of an activity execution. - - .. warning:: - This API is experimental. - - See :py:class:`temporalio.api.enums.v1.ActivityExecutionStatus`. - """ - - UNSPECIFIED = int( - temporalio.api.enums.v1.ActivityExecutionStatus.ACTIVITY_EXECUTION_STATUS_UNSPECIFIED - ) - RUNNING = int( - temporalio.api.enums.v1.ActivityExecutionStatus.ACTIVITY_EXECUTION_STATUS_RUNNING - ) - COMPLETED = int( - temporalio.api.enums.v1.ActivityExecutionStatus.ACTIVITY_EXECUTION_STATUS_COMPLETED - ) - FAILED = int( - temporalio.api.enums.v1.ActivityExecutionStatus.ACTIVITY_EXECUTION_STATUS_FAILED - ) - CANCELED = int( - temporalio.api.enums.v1.ActivityExecutionStatus.ACTIVITY_EXECUTION_STATUS_CANCELED - ) - TERMINATED = int( - temporalio.api.enums.v1.ActivityExecutionStatus.ACTIVITY_EXECUTION_STATUS_TERMINATED - ) - TIMED_OUT = int( - temporalio.api.enums.v1.ActivityExecutionStatus.ACTIVITY_EXECUTION_STATUS_TIMED_OUT - ) - - -class PendingActivityState(IntEnum): - """Detailed state of an activity execution that is in ACTIVITY_EXECUTION_STATUS_RUNNING. - - .. warning:: - This API is experimental. - - See :py:class:`temporalio.api.enums.v1.PendingActivityState`. - """ - - UNSPECIFIED = int( - temporalio.api.enums.v1.PendingActivityState.PENDING_ACTIVITY_STATE_UNSPECIFIED - ) - SCHEDULED = int( - temporalio.api.enums.v1.PendingActivityState.PENDING_ACTIVITY_STATE_SCHEDULED - ) - STARTED = int( - temporalio.api.enums.v1.PendingActivityState.PENDING_ACTIVITY_STATE_STARTED - ) - CANCEL_REQUESTED = int( - temporalio.api.enums.v1.PendingActivityState.PENDING_ACTIVITY_STATE_CANCEL_REQUESTED - ) - PAUSED = int( - temporalio.api.enums.v1.PendingActivityState.PENDING_ACTIVITY_STATE_PAUSED - ) - PAUSE_REQUESTED = int( - temporalio.api.enums.v1.PendingActivityState.PENDING_ACTIVITY_STATE_PAUSE_REQUESTED - ) - - -@dataclass(frozen=True) -class ActivityExecutionCount: - """Representation of a count from a count activities call. - - .. warning:: - This API is experimental. - """ - - count: int - """Total count matching the filter, if any.""" - - groups: Sequence[ActivityExecutionCountAggregationGroup] - """Aggregation groups if requested.""" - - @staticmethod - def _from_raw( - resp: temporalio.api.workflowservice.v1.CountActivityExecutionsResponse, - ) -> ActivityExecutionCount: - """Create from raw proto response.""" - return ActivityExecutionCount( - count=resp.count, - groups=[ - ActivityExecutionCountAggregationGroup._from_raw(g) for g in resp.groups - ], - ) - - -@dataclass(frozen=True) -class ActivityExecutionCountAggregationGroup: - """A single aggregation group from a count activities call. - - .. warning:: - This API is experimental. - """ - - count: int - """Count for this group.""" - - group_values: Sequence[temporalio.common.SearchAttributeValue] - """Values that define this group.""" - - @staticmethod - def _from_raw( - raw: temporalio.api.workflowservice.v1.CountActivityExecutionsResponse.AggregationGroup, - ) -> ActivityExecutionCountAggregationGroup: - return ActivityExecutionCountAggregationGroup( - count=raw.count, - group_values=[ - temporalio.converter._search_attributes._decode_search_attribute_value( - v - ) - for v in raw.group_values - ], - ) - - -@dataclass(frozen=True) -class AsyncActivityIDReference: - """Reference to an async activity by its qualified ID.""" - - workflow_id: str | None - run_id: str | None - activity_id: str - - -class AsyncActivityHandle(WithSerializationContext): - """Handle representing an external activity for completion and heartbeat.""" - - def __init__( - self, - client: Client, - id_or_token: AsyncActivityIDReference | bytes, - data_converter_override: DataConverter | None = None, - ) -> None: - """Create an async activity handle.""" - self._client = client - self._id_or_token = id_or_token - self._data_converter_override = data_converter_override - - async def heartbeat( - self, - *details: Any, - rpc_metadata: Mapping[str, str | bytes] = {}, - rpc_timeout: timedelta | None = None, - ) -> None: - """Record a heartbeat for the activity. - - Args: - details: Details of the heartbeat. - rpc_metadata: Headers used on the RPC call. Keys here override - client-level RPC metadata keys. - rpc_timeout: Optional RPC deadline to set for the RPC call. - """ - await self._client._impl.heartbeat_async_activity( - HeartbeatAsyncActivityInput( - id_or_token=self._id_or_token, - details=details, - rpc_metadata=rpc_metadata, - rpc_timeout=rpc_timeout, - data_converter_override=self._data_converter_override, - ), - ) - - async def complete( - self, - result: Any | None = temporalio.common._arg_unset, - *, - rpc_metadata: Mapping[str, str | bytes] = {}, - rpc_timeout: timedelta | None = None, - ) -> None: - """Complete the activity. - - Args: - result: Result of the activity if any. - rpc_metadata: Headers used on the RPC call. Keys here override - client-level RPC metadata keys. - rpc_timeout: Optional RPC deadline to set for the RPC call. - """ - await self._client._impl.complete_async_activity( - CompleteAsyncActivityInput( - id_or_token=self._id_or_token, - result=result, - rpc_metadata=rpc_metadata, - rpc_timeout=rpc_timeout, - data_converter_override=self._data_converter_override, - ), - ) - - async def fail( - self, - error: Exception, - *, - last_heartbeat_details: Sequence[Any] = [], - rpc_metadata: Mapping[str, str | bytes] = {}, - rpc_timeout: timedelta | None = None, - ) -> None: - """Fail the activity. - - Args: - error: Error for the activity. - last_heartbeat_details: Last heartbeat details for the activity. - rpc_metadata: Headers used on the RPC call. Keys here override - client-level RPC metadata keys. - rpc_timeout: Optional RPC deadline to set for the RPC call. - """ - await self._client._impl.fail_async_activity( - FailAsyncActivityInput( - id_or_token=self._id_or_token, - error=error, - last_heartbeat_details=last_heartbeat_details, - rpc_metadata=rpc_metadata, - rpc_timeout=rpc_timeout, - data_converter_override=self._data_converter_override, - ), - ) - - async def report_cancellation( - self, - *details: Any, - rpc_metadata: Mapping[str, str | bytes] = {}, - rpc_timeout: timedelta | None = None, - ) -> None: - """Report the activity as cancelled. - - Args: - details: Cancellation details. - rpc_metadata: Headers used on the RPC call. Keys here override - client-level RPC metadata keys. - rpc_timeout: Optional RPC deadline to set for the RPC call. - """ - await self._client._impl.report_cancellation_async_activity( - ReportCancellationAsyncActivityInput( - id_or_token=self._id_or_token, - details=details, - rpc_metadata=rpc_metadata, - rpc_timeout=rpc_timeout, - data_converter_override=self._data_converter_override, - ), - ) - - def with_context(self, context: SerializationContext) -> Self: - """Create a new AsyncActivityHandle with a different serialization context. - - Payloads received by the activity will be decoded and deserialized using a data converter - with :py:class:`ActivitySerializationContext` set as context. If you are using a custom data - converter that makes use of this context then you can use this method to supply matching - context data to the data converter used to serialize and encode the outbound payloads. - """ - data_converter = self._client.data_converter.with_context(context) - if data_converter is self._client.data_converter: - return self - cls = type(self) - if cls.__init__ is not AsyncActivityHandle.__init__: - raise TypeError( - "If you have subclassed AsyncActivityHandle and overridden the __init__ method " - "then you must override with_context to return an instance of your class." - ) - return cls( - self._client, - self._id_or_token, - data_converter, - ) - - -class ActivityHandle(Generic[ReturnType]): - """Handle representing an activity execution not started by a workflow. - - .. warning:: - This API is experimental. - """ - - def __init__( - self, - client: Client, - id: str, - *, - run_id: str | None = None, - result_type: type | None = None, - ) -> None: - """Create activity handle.""" - self._client = client - self._id = id - self._run_id = run_id - self._result_type = result_type - self._known_outcome: ( - temporalio.api.activity.v1.ActivityExecutionOutcome | None - ) = None - - @functools.cached_property - def _data_converter(self) -> temporalio.converter.DataConverter: - return self._client.data_converter.with_context( - ActivitySerializationContext( - namespace=self._client.namespace, - activity_id=self._id, - activity_type=None, - activity_task_queue=None, - is_local=False, - workflow_id=None, - workflow_type=None, - ) - ) - - @property - def id(self) -> str: - """ID of the activity.""" - return self._id - - @property - def run_id(self) -> str | None: - """Run ID of the activity.""" - return self._run_id - - async def result( - self, - *, - rpc_metadata: Mapping[str, str | bytes] = {}, - rpc_timeout: timedelta | None = None, - ) -> ReturnType: - """Wait for result of the activity. - - .. warning:: - This API is experimental. - - The result may already be known if this method has been called before, - in which case no network call is made. Otherwise the result will be - polled for until it is available. - - Args: - rpc_metadata: Headers used on the RPC call. Keys here override - client-level RPC metadata keys. - rpc_timeout: Optional RPC deadline to set for each RPC call. Note: - this is the timeout for each RPC call while polling, not a - timeout for the function as a whole. If an individual RPC - times out, it will be retried until the result is available. - - Returns: - The result of the activity. - - Raises: - ActivityFailureError: If the activity completed with a failure. - RPCError: Activity result could not be fetched for some reason. - """ - await self._poll_until_outcome( - rpc_metadata=rpc_metadata, rpc_timeout=rpc_timeout - ) - - # Convert outcome to failure or value - assert self._known_outcome - if self._known_outcome.HasField("failure"): - raise ActivityFailureError( - cause=await self._data_converter.decode_failure( - self._known_outcome.failure - ), - ) - if not self._known_outcome.result.payloads: - return None # type: ignore - type_hints = [self._result_type] if self._result_type else None - results = await self._data_converter.decode( - self._known_outcome.result.payloads, type_hints - ) - if not results: - return None # type: ignore - elif len(results) > 1: - warnings.warn(f"Expected single activity result, got {len(results)}") - return results[0] - - async def _poll_until_outcome( - self, - rpc_metadata: Mapping[str, str | bytes] = {}, - rpc_timeout: timedelta | None = None, - ) -> None: - """Poll for activity result until it's available.""" - if self._known_outcome: - return - - req = temporalio.api.workflowservice.v1.PollActivityExecutionRequest( - namespace=self._client.namespace, - activity_id=self._id, - run_id=self._run_id or "", - ) - - # Continue polling as long as we have no outcome - while True: - try: - res = await self._client.workflow_service.poll_activity_execution( - req, - retry=True, - metadata=rpc_metadata, - timeout=rpc_timeout, - ) - if res.HasField("outcome"): - self._known_outcome = res.outcome - return - except RPCError as err: - if err.status == RPCStatusCode.DEADLINE_EXCEEDED: - # Deadline exceeded is expected with long polling; retry - continue - elif err.status == RPCStatusCode.CANCELLED: - raise asyncio.CancelledError() from err - else: - raise - except asyncio.CancelledError: - raise - - async def cancel( - self, - *, - reason: str | None = None, - rpc_metadata: Mapping[str, str | bytes] = {}, - rpc_timeout: timedelta | None = None, - ) -> None: - """Request cancellation of the activity. - - .. warning:: - This API is experimental. - - Requesting cancellation of an activity does not automatically transition the activity to - canceled status. If the activity is heartbeating, a :py:class:`exceptions.CancelledError` - exception will be raised when receiving the heartbeat response; if the activity allows this - exception to bubble out, the activity will transition to canceled status. If the activity it - is not heartbeating, this method will have no effect on activity status. - - Args: - reason: Reason for the cancellation. Recorded and available via describe. - rpc_metadata: Headers used on the RPC call. - rpc_timeout: Optional RPC deadline to set for the RPC call. - """ - await self._client._impl.cancel_activity( - CancelActivityInput( - activity_id=self._id, - activity_run_id=self._run_id, - reason=reason, - rpc_metadata=rpc_metadata, - rpc_timeout=rpc_timeout, - ) - ) - - async def terminate( - self, - *, - reason: str | None = None, - rpc_metadata: Mapping[str, str | bytes] = {}, - rpc_timeout: timedelta | None = None, - ) -> None: - """Terminate the activity execution immediately. - - .. warning:: - This API is experimental. - - Termination does not reach the worker and the activity code cannot react to it. - A terminated activity may have a running attempt and will be requested to be - canceled by the server when it heartbeats. - - Args: - reason: Reason for the termination. - rpc_metadata: Headers used on the RPC call. - rpc_timeout: Optional RPC deadline to set for the RPC call. - """ - await self._client._impl.terminate_activity( - TerminateActivityInput( - activity_id=self._id, - activity_run_id=self._run_id, - reason=reason, - rpc_metadata=rpc_metadata, - rpc_timeout=rpc_timeout, - ) - ) - - async def describe( - self, - *, - long_poll_token: bytes | None = None, - rpc_metadata: Mapping[str, str | bytes] = {}, - rpc_timeout: timedelta | None = None, - ) -> ActivityExecutionDescription: - """Describe the activity execution. - - .. warning:: - This API is experimental. - - Args: - long_poll_token: Token from a previous describe response. If provided, - the request will long-poll until the activity state changes. - rpc_metadata: Headers used on the RPC call. - rpc_timeout: Optional RPC deadline to set for the RPC call. - - Returns: - Activity execution description. - """ - return await self._client._impl.describe_activity( - DescribeActivityInput( - activity_id=self._id, - activity_run_id=self._run_id, - long_poll_token=long_poll_token, - rpc_metadata=rpc_metadata, - rpc_timeout=rpc_timeout, - ) - ) - - -@dataclass -class WorkflowExecution: - """Info for a single workflow execution run.""" - - close_time: datetime | None - """When the workflow was closed if closed.""" - - execution_time: datetime | None - """When this workflow run started or should start.""" - - history_length: int - """Number of events in the history.""" - - id: str - """ID for the workflow.""" - - namespace: str - """Namespace for the workflow.""" - - parent_id: str | None - """ID for the parent workflow if this was started as a child.""" - - parent_run_id: str | None - """Run ID for the parent workflow if this was started as a child.""" - - root_id: str | None - """ID for the root workflow.""" - - root_run_id: str | None - """Run ID for the root workflow.""" - - raw_info: temporalio.api.workflow.v1.WorkflowExecutionInfo - """Underlying protobuf info.""" - - run_id: str - """Run ID for this workflow run.""" - - search_attributes: temporalio.common.SearchAttributes - """Current set of search attributes if any. - - .. deprecated:: - Use :py:attr:`typed_search_attributes` instead. - """ - - start_time: datetime - """When the workflow was created.""" - - status: WorkflowExecutionStatus | None - """Status for the workflow.""" - - task_queue: str - """Task queue for the workflow.""" - - typed_search_attributes: temporalio.common.TypedSearchAttributes - """Current set of search attributes if any.""" - - workflow_type: str - """Type name for the workflow.""" - - _context_free_data_converter: temporalio.converter.DataConverter - - @property - def data_converter(self) -> temporalio.converter.DataConverter: - """Data converter for the workflow.""" - return self._context_free_data_converter.with_context( - WorkflowSerializationContext( - namespace=self.namespace, - workflow_id=self.id, - ) - ) - - @classmethod - def _from_raw_info( - cls, - info: temporalio.api.workflow.v1.WorkflowExecutionInfo, - namespace: str, - converter: temporalio.converter.DataConverter, - **additional_fields: Any, - ) -> Self: - return cls( - close_time=( - info.close_time.ToDatetime().replace(tzinfo=timezone.utc) - if info.HasField("close_time") - else None - ), - execution_time=( - info.execution_time.ToDatetime().replace(tzinfo=timezone.utc) - if info.HasField("execution_time") - else None - ), - history_length=info.history_length, - id=info.execution.workflow_id, - namespace=namespace, - parent_id=( - info.parent_execution.workflow_id - if info.HasField("parent_execution") - else None - ), - parent_run_id=( - info.parent_execution.run_id - if info.HasField("parent_execution") - else None - ), - root_id=( - info.root_execution.workflow_id - if info.HasField("root_execution") - else None - ), - root_run_id=( - info.root_execution.run_id if info.HasField("root_execution") else None - ), - raw_info=info, - run_id=info.execution.run_id, - search_attributes=temporalio.converter.decode_search_attributes( - info.search_attributes - ), - start_time=info.start_time.ToDatetime().replace(tzinfo=timezone.utc), - status=WorkflowExecutionStatus(info.status) if info.status else None, - task_queue=info.task_queue, - typed_search_attributes=temporalio.converter.decode_typed_search_attributes( - info.search_attributes - ), - workflow_type=info.type.name, - _context_free_data_converter=converter, - **additional_fields, - ) - - async def memo(self) -> Mapping[str, Any]: - """Workflow's memo values, converted without type hints. - - Since type hints are not used, the default converted values will come - back. For example, if the memo was originally created with a dataclass, - the value will be a dict. To convert using proper type hints, use - :py:meth:`memo_value`. - - Returns: - Mapping of all memo keys and they values without type hints. - """ - return await self.data_converter._decode_memo(self.raw_info.memo) - - @overload - async def memo_value( - self, key: str, default: Any = temporalio.common._arg_unset - ) -> Any: ... - - @overload - async def memo_value( - self, key: str, *, type_hint: type[ParamType] - ) -> ParamType: ... - - @overload - async def memo_value( - self, key: str, default: AnyType, *, type_hint: type[ParamType] - ) -> AnyType | ParamType: ... - - async def memo_value( - self, - key: str, - default: Any = temporalio.common._arg_unset, - *, - type_hint: type | None = None, - ) -> Any: - """Memo value for the given key, optional default, and optional type - hint. - - Args: - key: Key to get memo value for. - default: Default to use if key is not present. If unset, a - :py:class:`KeyError` is raised when the key does not exist. - type_hint: type hint to use when converting. - - Returns: - Memo value, converted with the type hint if present. - - Raises: - KeyError: Key not present and default not set. - """ - return await self.data_converter._decode_memo_field( - self.raw_info.memo, key, default, type_hint - ) - - -@dataclass -class WorkflowExecutionDescription(WorkflowExecution): - """Description for a single workflow execution run.""" - - raw_description: temporalio.api.workflowservice.v1.DescribeWorkflowExecutionResponse - """Underlying protobuf description.""" - - _static_summary: str | None = None - _static_details: str | None = None - _metadata_decoded: bool = False - - async def static_summary(self) -> str | None: - """Gets the single-line fixed summary for this workflow execution that may appear in - UI/CLI. This can be in single-line Temporal markdown format. - """ - if not self._metadata_decoded: - await self._decode_metadata() - return self._static_summary - - async def static_details(self) -> str | None: - """Gets the general fixed details for this workflow execution that may appear in UI/CLI. - This can be in Temporal markdown format and can span multiple lines. - """ - if not self._metadata_decoded: - await self._decode_metadata() - return self._static_details - - async def _decode_metadata(self) -> None: - """Internal method to decode metadata lazily.""" - self._static_summary, self._static_details = await _decode_user_metadata( - self.data_converter, self.raw_description.execution_config.user_metadata - ) - self._metadata_decoded = True - - @staticmethod - async def _from_raw_description( - description: temporalio.api.workflowservice.v1.DescribeWorkflowExecutionResponse, - namespace: str, - converter: temporalio.converter.DataConverter, - ) -> WorkflowExecutionDescription: - return WorkflowExecutionDescription._from_raw_info( - description.workflow_execution_info, - namespace=namespace, - converter=converter, - raw_description=description, - ) - - -class WorkflowExecutionStatus(IntEnum): - """Status of a workflow execution. - - See :py:class:`temporalio.api.enums.v1.WorkflowExecutionStatus`. - """ - - RUNNING = int( - temporalio.api.enums.v1.WorkflowExecutionStatus.WORKFLOW_EXECUTION_STATUS_RUNNING - ) - COMPLETED = int( - temporalio.api.enums.v1.WorkflowExecutionStatus.WORKFLOW_EXECUTION_STATUS_COMPLETED - ) - FAILED = int( - temporalio.api.enums.v1.WorkflowExecutionStatus.WORKFLOW_EXECUTION_STATUS_FAILED - ) - CANCELED = int( - temporalio.api.enums.v1.WorkflowExecutionStatus.WORKFLOW_EXECUTION_STATUS_CANCELED - ) - TERMINATED = int( - temporalio.api.enums.v1.WorkflowExecutionStatus.WORKFLOW_EXECUTION_STATUS_TERMINATED - ) - CONTINUED_AS_NEW = int( - temporalio.api.enums.v1.WorkflowExecutionStatus.WORKFLOW_EXECUTION_STATUS_CONTINUED_AS_NEW - ) - TIMED_OUT = int( - temporalio.api.enums.v1.WorkflowExecutionStatus.WORKFLOW_EXECUTION_STATUS_TIMED_OUT - ) - - -@dataclass -class WorkflowExecutionCount: - """Representation of a count from a count workflows call.""" - - count: int - """Approximate number of workflows matching the original query. - - If the query had a group-by clause, this is simply the sum of all the counts - in py:attr:`groups`. - """ - - groups: Sequence[WorkflowExecutionCountAggregationGroup] - """Groups if the query had a group-by clause, or empty if not.""" - - @staticmethod - def _from_raw( - raw: temporalio.api.workflowservice.v1.CountWorkflowExecutionsResponse, - ) -> WorkflowExecutionCount: - return WorkflowExecutionCount( - count=raw.count, - groups=[ - WorkflowExecutionCountAggregationGroup._from_raw(g) for g in raw.groups - ], - ) - - -@dataclass -class WorkflowExecutionCountAggregationGroup: - """Aggregation group if the workflow count query had a group-by clause.""" - - count: int - """Approximate number of workflows matching the original query for this - group. - """ - - group_values: Sequence[temporalio.common.SearchAttributeValue] - """Search attribute values for this group.""" - - @staticmethod - def _from_raw( - raw: temporalio.api.workflowservice.v1.CountWorkflowExecutionsResponse.AggregationGroup, - ) -> WorkflowExecutionCountAggregationGroup: - return WorkflowExecutionCountAggregationGroup( - count=raw.count, - group_values=[ - temporalio.converter._search_attributes._decode_search_attribute_value( - v - ) - for v in raw.group_values - ], - ) - - -class WorkflowExecutionAsyncIterator: - """Asynchronous iterator for :py:class:`WorkflowExecution` values. - - Most users should use ``async for`` on this iterator and not call any of the - methods within. To consume the workflows as histories, call - :py:meth:`map_histories`. - """ - - def __init__( - self, - client: Client, - input: ListWorkflowsInput, - ) -> None: - """Create an asynchronous iterator for the given input. - - Users should not create this directly, but rather use - :py:meth:`Client.list_workflows`. - """ - self._client = client - self._input = input - self._next_page_token = input.next_page_token - self._current_page: Sequence[WorkflowExecution] | None = None - self._current_page_index = 0 - self._limit = input.limit - self._yielded = 0 - - @property - def current_page_index(self) -> int: - """Index of the entry in the current page that will be returned from - the next :py:meth:`__anext__` call. - """ - return self._current_page_index - - @property - def current_page(self) -> Sequence[WorkflowExecution] | None: - """Current page, if it has been fetched yet.""" - return self._current_page - - @property - def next_page_token(self) -> bytes | None: - """Token for the next page request if any.""" - return self._next_page_token - - async def fetch_next_page(self, *, page_size: int | None = None) -> None: - """Fetch the next page if any. - - Args: - page_size: Override the page size this iterator was originally - created with. - """ - page_size = page_size or self._input.page_size - if self._limit is not None and self._limit - self._yielded < page_size: - page_size = self._limit - self._yielded - - resp = await self._client.workflow_service.list_workflow_executions( - temporalio.api.workflowservice.v1.ListWorkflowExecutionsRequest( - namespace=self._client.namespace, - page_size=page_size, - next_page_token=self._next_page_token or b"", - query=self._input.query or "", - ), - retry=True, - metadata=self._input.rpc_metadata, - timeout=self._input.rpc_timeout, - ) - - self._current_page = [ - WorkflowExecution._from_raw_info( - v, self._client.namespace, self._client.data_converter - ) - for v in resp.executions - ] - self._current_page_index = 0 - self._next_page_token = resp.next_page_token or None - - def __aiter__(self) -> WorkflowExecutionAsyncIterator: - """Return self as the iterator.""" - return self - - async def __anext__(self) -> WorkflowExecution: - """Get the next execution on this iterator, fetching next page if - necessary. - """ - if self._limit is not None and self._yielded >= self._limit: - raise StopAsyncIteration - while True: - # No page? fetch and continue - if self._current_page is None: - await self.fetch_next_page() - continue - # No more left in page? - if self._current_page_index >= len(self._current_page): - # If there is a next page token, try to get another page and try - # again - if self._next_page_token is not None: - await self.fetch_next_page() - continue - # No more pages means we're done - raise StopAsyncIteration - # Get current, increment page index, and return - ret = self._current_page[self._current_page_index] - self._current_page_index += 1 - self._yielded += 1 - return ret - - async def map_histories( - self, - *, - event_filter_type: WorkflowHistoryEventFilterType = WorkflowHistoryEventFilterType.ALL_EVENT, - skip_archival: bool = False, - rpc_metadata: Mapping[str, str | bytes] = {}, - rpc_timeout: timedelta | None = None, - ) -> AsyncIterator[WorkflowHistory]: - """Create an async iterator consuming all workflows and calling - :py:meth:`WorkflowHandle.fetch_history` on each one. - - This is just a shortcut for ``fetch_history``, see that method for - parameter details. - """ - async for v in self: - yield await self._client.get_workflow_handle( - v.id, run_id=v.run_id - ).fetch_history( - event_filter_type=event_filter_type, - skip_archival=skip_archival, - rpc_metadata=rpc_metadata, - rpc_timeout=rpc_timeout, - ) - - -@dataclass(frozen=True) -class WorkflowHistory: - """A workflow's ID and immutable history.""" - - workflow_id: str - """ID of the workflow.""" - - events: Sequence[temporalio.api.history.v1.HistoryEvent] - """History events for the workflow.""" - - @property - def run_id(self) -> str: - """Run ID extracted from the first event.""" - if not self.events: - raise RuntimeError("No events") - if not self.events[0].HasField("workflow_execution_started_event_attributes"): - raise RuntimeError("First event is not workflow start") - return self.events[ - 0 - ].workflow_execution_started_event_attributes.original_execution_run_id - - @staticmethod - def from_json(workflow_id: str, history: str | dict[str, Any]) -> WorkflowHistory: - """Construct a WorkflowHistory from an ID and a json dump of history. - - This is built to work both with Temporal UI/CLI JSON as well as - :py:meth:`to_json` even though they are slightly different. - - Args: - workflow_id: The workflow's ID - history: A string or parsed-to-dict representation of workflow - history - - Returns: - Workflow history - """ - parsed = _history_from_json(history) - return WorkflowHistory(workflow_id, parsed.events) - - def to_json(self) -> str: - """Convert this history to JSON. - - Note, this does not include the workflow ID. - """ - return google.protobuf.json_format.MessageToJson( - temporalio.api.history.v1.History(events=self.events) - ) - - def to_json_dict(self) -> dict[str, Any]: - """Convert this history to JSON-compatible dict. - - Note, this does not include the workflow ID. - """ - return google.protobuf.json_format.MessageToDict( - temporalio.api.history.v1.History(events=self.events) - ) - - -@dataclass -class WorkflowHistoryEventAsyncIterator: - """Asynchronous iterator for history events of a workflow. - - Most users should use ``async for`` on this iterator and not call any of the - methods within. - """ - - def __init__( - self, - client: Client, - input: FetchWorkflowHistoryEventsInput, - ) -> None: - """Create an asynchronous iterator for the given input. - - Users should not create this directly, but rather use - :py:meth:`WorkflowHandle.fetch_history_events`. - """ - self._client = client - self._input = input - self._next_page_token = input.next_page_token - self._current_page: ( - None | (Sequence[temporalio.api.history.v1.HistoryEvent]) - ) = None - self._current_page_index = 0 - - @property - def current_page_index(self) -> int: - """Index of the entry in the current page that will be returned from - the next :py:meth:`__anext__` call. - """ - return self._current_page_index - - @property - def current_page( - self, - ) -> Sequence[temporalio.api.history.v1.HistoryEvent] | None: - """Current page, if it has been fetched yet.""" - return self._current_page - - @property - def next_page_token(self) -> bytes | None: - """Token for the next page request if any.""" - return self._next_page_token - - async def fetch_next_page(self, *, page_size: int | None = None) -> None: # type:ignore[reportUnusedParameter] # https://github.com/temporalio/sdk-python/issues/1239 - """Fetch the next page if any. - - Args: - page_size: Override the page size this iterator was originally - created with. - """ - resp = await self._client.workflow_service.get_workflow_execution_history( - temporalio.api.workflowservice.v1.GetWorkflowExecutionHistoryRequest( - namespace=self._client.namespace, - execution=temporalio.api.common.v1.WorkflowExecution( - workflow_id=self._input.id, - run_id=self._input.run_id or "", - ), - maximum_page_size=page_size or self._input.page_size or 0, - next_page_token=self._next_page_token or b"", - wait_new_event=self._input.wait_new_event, - history_event_filter_type=temporalio.api.enums.v1.HistoryEventFilterType.ValueType( - self._input.event_filter_type - ), - skip_archival=self._input.skip_archival, - ), - retry=True, - metadata=self._input.rpc_metadata, - timeout=self._input.rpc_timeout, - ) - # We don't support raw history - assert len(resp.raw_history) == 0 - self._current_page = list(resp.history.events) - self._current_page_index = 0 - self._next_page_token = resp.next_page_token or None - - def __aiter__(self) -> WorkflowHistoryEventAsyncIterator: - """Return self as the iterator.""" - return self - - async def __anext__(self) -> temporalio.api.history.v1.HistoryEvent: - """Get the next execution on this iterator, fetching next page if - necessary. - """ - while True: - # No page? fetch and continue - if self._current_page is None: - await self.fetch_next_page() - continue - # No more left in page? - if self._current_page_index >= len(self._current_page): - # If there is a next page token, try to get another page and try - # again - if self._next_page_token is not None: - await self.fetch_next_page() - continue - # No more pages means we're done - raise StopAsyncIteration - # Increment page index and return - ret = self._current_page[self._current_page_index] - self._current_page_index += 1 - return ret - - -class ScheduleHandle: - """Handle for interacting with a schedule. - - This is usually created via :py:meth:`Client.get_schedule_handle` or - returned from :py:meth:`Client.create_schedule`. - - Attributes: - id: ID of the schedule. - """ - - def __init__(self, client: Client, id: str) -> None: - """Create schedule handle.""" - self._client = client - self.id = id - - async def backfill( - self, - *backfill: ScheduleBackfill, - rpc_metadata: Mapping[str, str | bytes] = {}, - rpc_timeout: timedelta | None = None, - ) -> None: - """Backfill the schedule by going through the specified time periods as - if they passed right now. - - Args: - backfill: Backfill periods. - rpc_metadata: Headers used on the RPC call. Keys here override - client-level RPC metadata keys. - rpc_timeout: Optional RPC deadline to set for the RPC call. - """ - if not backfill: - raise ValueError("At least one backfill required") - await self._client._impl.backfill_schedule( - BackfillScheduleInput( - id=self.id, - backfills=backfill, - rpc_metadata=rpc_metadata, - rpc_timeout=rpc_timeout, - ), - ) - - async def delete( - self, - *, - rpc_metadata: Mapping[str, str | bytes] = {}, - rpc_timeout: timedelta | None = None, - ) -> None: - """Delete this schedule. - - Args: - rpc_metadata: Headers used on the RPC call. Keys here override - client-level RPC metadata keys. - rpc_timeout: Optional RPC deadline to set for the RPC call. - """ - await self._client._impl.delete_schedule( - DeleteScheduleInput( - id=self.id, - rpc_metadata=rpc_metadata, - rpc_timeout=rpc_timeout, - ), - ) - - async def describe( - self, - *, - rpc_metadata: Mapping[str, str | bytes] = {}, - rpc_timeout: timedelta | None = None, - ) -> ScheduleDescription: - """Fetch this schedule's description. - - Args: - rpc_metadata: Headers used on the RPC call. Keys here override - client-level RPC metadata keys. - rpc_timeout: Optional RPC deadline to set for the RPC call. - """ - return await self._client._impl.describe_schedule( - DescribeScheduleInput( - id=self.id, - rpc_metadata=rpc_metadata, - rpc_timeout=rpc_timeout, - ), - ) - - async def pause( - self, - *, - note: str | None = None, - rpc_metadata: Mapping[str, str | bytes] = {}, - rpc_timeout: timedelta | None = None, - ) -> None: - """Pause the schedule and set a note. - - Args: - note: Note to set on the schedule. - rpc_metadata: Headers used on the RPC call. Keys here override - client-level RPC metadata keys. - rpc_timeout: Optional RPC deadline to set for the RPC call. - """ - await self._client._impl.pause_schedule( - PauseScheduleInput( - id=self.id, - note=note, - rpc_metadata=rpc_metadata, - rpc_timeout=rpc_timeout, - ), - ) - - async def trigger( - self, - *, - overlap: ScheduleOverlapPolicy | None = None, - rpc_metadata: Mapping[str, str | bytes] = {}, - rpc_timeout: timedelta | None = None, - ) -> None: - """Trigger an action on this schedule to happen immediately. - - Args: - overlap: If set, overrides the schedule's overlap policy. - rpc_metadata: Headers used on the RPC call. Keys here override - client-level RPC metadata keys. - rpc_timeout: Optional RPC deadline to set for the RPC call. - """ - await self._client._impl.trigger_schedule( - TriggerScheduleInput( - id=self.id, - overlap=overlap, - rpc_metadata=rpc_metadata, - rpc_timeout=rpc_timeout, - ), - ) - - async def unpause( - self, - *, - note: str | None = None, - rpc_metadata: Mapping[str, str | bytes] = {}, - rpc_timeout: timedelta | None = None, - ) -> None: - """Unpause the schedule and set a note. - - Args: - note: Note to set on the schedule. - rpc_metadata: Headers used on the RPC call. Keys here override - client-level RPC metadata keys. - rpc_timeout: Optional RPC deadline to set for the RPC call. - """ - await self._client._impl.unpause_schedule( - UnpauseScheduleInput( - id=self.id, - note=note, - rpc_metadata=rpc_metadata, - rpc_timeout=rpc_timeout, - ), - ) - - @overload - async def update( - self, - updater: Callable[[ScheduleUpdateInput], ScheduleUpdate | None], - *, - rpc_metadata: Mapping[str, str | bytes] = {}, - rpc_timeout: timedelta | None = None, - ) -> None: ... - - @overload - async def update( - self, - updater: Callable[[ScheduleUpdateInput], Awaitable[ScheduleUpdate | None]], - *, - rpc_metadata: Mapping[str, str | bytes] = {}, - rpc_timeout: timedelta | None = None, - ) -> None: ... - - async def update( - self, - updater: Callable[ - [ScheduleUpdateInput], - ScheduleUpdate | None | Awaitable[ScheduleUpdate | None], - ], - *, - rpc_metadata: Mapping[str, str | bytes] = {}, - rpc_timeout: timedelta | None = None, - ) -> None: - """Update a schedule using a callback to build the update from the - description. - - The callback may be invoked multiple times in a conflict-resolution - loop. - - Args: - updater: Callback that returns the update. It accepts a - :py:class:`ScheduleUpdateInput` and returns a - :py:class:`ScheduleUpdate`. If None is returned or an error - occurs, the update is not attempted. This may be called multiple - times. - rpc_metadata: Headers used on the RPC call. Keys here override - client-level RPC metadata keys. This is for every call made - within. - rpc_timeout: Optional RPC deadline to set for the RPC call. This is - for each call made within, not overall. - """ - await self._client._impl.update_schedule( - UpdateScheduleInput( - id=self.id, - updater=updater, - rpc_metadata=rpc_metadata, - rpc_timeout=rpc_timeout, - ), - ) - - -@dataclass -class ScheduleSpec: - """Specification of the times scheduled actions may occur. - - The times are the union of :py:attr:`calendars`, :py:attr:`intervals`, and - :py:attr:`cron_expressions` excluding anything in :py:attr:`skip`. - """ - - calendars: Sequence[ScheduleCalendarSpec] = dataclasses.field(default_factory=list) - """Calendar-based specification of times.""" - - intervals: Sequence[ScheduleIntervalSpec] = dataclasses.field(default_factory=list) - """Interval-based specification of times.""" - - cron_expressions: Sequence[str] = dataclasses.field(default_factory=list) - """Cron-based specification of times. - - This is provided for easy migration from legacy string-based cron - scheduling. New uses should use :py:attr:`calendars` instead. These - expressions will be translated to calendar-based specifications on the - server. - """ - - skip: Sequence[ScheduleCalendarSpec] = dataclasses.field(default_factory=list) - """Set of matching calendar times that will be skipped.""" - - start_at: datetime | None = None - """Time before which any matching times will be skipped.""" - - end_at: datetime | None = None - """Time after which any matching times will be skipped.""" - - jitter: timedelta | None = None - """Jitter to apply each action. - - An action's scheduled time will be incremented by a random value between 0 - and this value if present (but not past the next schedule). - """ - - time_zone_name: str | None = None - """IANA time zone name, for example ``US/Central``.""" - - @staticmethod - def _from_proto(spec: temporalio.api.schedule.v1.ScheduleSpec) -> ScheduleSpec: - return ScheduleSpec( - calendars=[ - ScheduleCalendarSpec._from_proto(c) for c in spec.structured_calendar - ], - intervals=[ScheduleIntervalSpec._from_proto(i) for i in spec.interval], - cron_expressions=spec.cron_string, - skip=[ - ScheduleCalendarSpec._from_proto(c) - for c in spec.exclude_structured_calendar - ], - start_at=spec.start_time.ToDatetime().replace(tzinfo=timezone.utc) - if spec.HasField("start_time") - else None, - end_at=spec.end_time.ToDatetime().replace(tzinfo=timezone.utc) - if spec.HasField("end_time") - else None, - jitter=spec.jitter.ToTimedelta() if spec.HasField("jitter") else None, - time_zone_name=spec.timezone_name or None, - ) - - def _to_proto(self) -> temporalio.api.schedule.v1.ScheduleSpec: - start_time: google.protobuf.timestamp_pb2.Timestamp | None = None - if self.start_at: - start_time = google.protobuf.timestamp_pb2.Timestamp() - start_time.FromDatetime(self.start_at) - end_time: google.protobuf.timestamp_pb2.Timestamp | None = None - if self.end_at: - end_time = google.protobuf.timestamp_pb2.Timestamp() - end_time.FromDatetime(self.end_at) - jitter: google.protobuf.duration_pb2.Duration | None = None - if self.jitter: - jitter = google.protobuf.duration_pb2.Duration() - jitter.FromTimedelta(self.jitter) - return temporalio.api.schedule.v1.ScheduleSpec( - structured_calendar=[cal._to_proto() for cal in self.calendars], - cron_string=self.cron_expressions, - interval=[i._to_proto() for i in self.intervals], - exclude_structured_calendar=[cal._to_proto() for cal in self.skip], - start_time=start_time, - end_time=end_time, - jitter=jitter, - timezone_name=self.time_zone_name or "", - ) - - -@dataclass(frozen=True) -class ScheduleRange: - """Inclusive range for a schedule match value.""" - - start: int - """Inclusive start of the range.""" - - end: int = 0 - """Inclusive end of the range. - - If unset or less than start, defaults to start. - """ - - step: int = 0 - """ - Step to take between each value. - - Unset or 0 defaults as 1. - """ - - def __post_init__(self): - """Set field defaults.""" - # Class is frozen, so we must setattr bypassing dataclass setattr - if self.end < self.start: - object.__setattr__(self, "end", self.start) - if self.step == 0: - object.__setattr__(self, "step", 1) - - @staticmethod - def _from_protos( - ranges: Sequence[temporalio.api.schedule.v1.Range], - ) -> Sequence[ScheduleRange]: - return tuple(ScheduleRange._from_proto(r) for r in ranges) - - @staticmethod - def _from_proto(range: temporalio.api.schedule.v1.Range) -> ScheduleRange: - return ScheduleRange(start=range.start, end=range.end, step=range.step) - - @staticmethod - def _to_protos( - ranges: Sequence[ScheduleRange], - ) -> Sequence[temporalio.api.schedule.v1.Range]: - return tuple(r._to_proto() for r in ranges) - - def _to_proto(self) -> temporalio.api.schedule.v1.Range: - return temporalio.api.schedule.v1.Range( - start=self.start, end=self.end, step=self.step - ) - - -@dataclass -class ScheduleCalendarSpec: - """Specification relative to calendar time when to run an action. - - A timestamp matches if at least one range of each field matches except for - year. If year is missing, that means all years match. For all fields besides - year, at least one range must be present to match anything. - """ - - second: Sequence[ScheduleRange] = (ScheduleRange(0),) - """Second range to match, 0-59. Default matches 0.""" - - minute: Sequence[ScheduleRange] = (ScheduleRange(0),) - """Minute range to match, 0-59. Default matches 0.""" - - hour: Sequence[ScheduleRange] = (ScheduleRange(0),) - """Hour range to match, 0-23. Default matches 0.""" - - day_of_month: Sequence[ScheduleRange] = (ScheduleRange(1, 31),) - """Day of month range to match, 1-31. Default matches all days.""" - - month: Sequence[ScheduleRange] = (ScheduleRange(1, 12),) - """Month range to match, 1-12. Default matches all months.""" - - year: Sequence[ScheduleRange] = () - """Optional year range to match. Default of empty matches all years.""" - - day_of_week: Sequence[ScheduleRange] = (ScheduleRange(0, 6),) - """Day of week range to match, 0-6, 0 is Sunday. Default matches all - days.""" - - comment: str | None = None - """Description of this schedule.""" - - @staticmethod - def _from_proto( - spec: temporalio.api.schedule.v1.StructuredCalendarSpec, - ) -> ScheduleCalendarSpec: - return ScheduleCalendarSpec( - second=ScheduleRange._from_protos(spec.second), - minute=ScheduleRange._from_protos(spec.minute), - hour=ScheduleRange._from_protos(spec.hour), - day_of_month=ScheduleRange._from_protos(spec.day_of_month), - month=ScheduleRange._from_protos(spec.month), - year=ScheduleRange._from_protos(spec.year), - day_of_week=ScheduleRange._from_protos(spec.day_of_week), - comment=spec.comment or None, - ) - - def _to_proto(self) -> temporalio.api.schedule.v1.StructuredCalendarSpec: - return temporalio.api.schedule.v1.StructuredCalendarSpec( - second=ScheduleRange._to_protos(self.second), - minute=ScheduleRange._to_protos(self.minute), - hour=ScheduleRange._to_protos(self.hour), - day_of_month=ScheduleRange._to_protos(self.day_of_month), - month=ScheduleRange._to_protos(self.month), - year=ScheduleRange._to_protos(self.year), - day_of_week=ScheduleRange._to_protos(self.day_of_week), - comment=self.comment or "", - ) - - -@dataclass -class ScheduleIntervalSpec: - """Specification for scheduling on an interval. - - Matches times expressed as epoch + (n * every) + offset. - """ - - every: timedelta - """Period to repeat the interval.""" - - offset: timedelta | None = None - """Fixed offset added to each interval period.""" - - @staticmethod - def _from_proto( - spec: temporalio.api.schedule.v1.IntervalSpec, - ) -> ScheduleIntervalSpec: - return ScheduleIntervalSpec( - every=spec.interval.ToTimedelta(), - offset=spec.phase.ToTimedelta() if spec.HasField("phase") else None, - ) - - def _to_proto(self) -> temporalio.api.schedule.v1.IntervalSpec: - interval = google.protobuf.duration_pb2.Duration() - interval.FromTimedelta(self.every) - phase: google.protobuf.duration_pb2.Duration | None = None - if self.offset: - phase = google.protobuf.duration_pb2.Duration() - phase.FromTimedelta(self.offset) - return temporalio.api.schedule.v1.IntervalSpec(interval=interval, phase=phase) - - -class ScheduleAction(ABC): - """Base class for an action a schedule can take. - - See :py:class:`ScheduleActionStartWorkflow` for the most commonly used - implementation. - """ - - @staticmethod - def _from_proto( - action: temporalio.api.schedule.v1.ScheduleAction, - ) -> ScheduleAction: - if action.HasField("start_workflow"): - return ScheduleActionStartWorkflow._from_proto(action.start_workflow) - else: - raise ValueError(f"Unsupported action: {action.WhichOneof('action')}") - - @abstractmethod - async def _to_proto( - self, client: Client - ) -> temporalio.api.schedule.v1.ScheduleAction: ... - - -@dataclass -class ScheduleActionStartWorkflow(ScheduleAction): - """Schedule action to start a workflow.""" - - workflow: str - args: Sequence[Any] | Sequence[temporalio.api.common.v1.Payload] - id: str - task_queue: str - execution_timeout: timedelta | None - run_timeout: timedelta | None - task_timeout: timedelta | None - retry_policy: temporalio.common.RetryPolicy | None - memo: None | (Mapping[str, Any] | Mapping[str, temporalio.api.common.v1.Payload]) - typed_search_attributes: temporalio.common.TypedSearchAttributes - untyped_search_attributes: temporalio.common.SearchAttributes - """This is deprecated and is only present in case existing untyped - attributes already exist for update. This should never be used when - creating.""" - static_summary: str | temporalio.api.common.v1.Payload | None - static_details: str | temporalio.api.common.v1.Payload | None - priority: temporalio.common.Priority - - headers: Mapping[str, temporalio.api.common.v1.Payload] | None - """ - Headers may still be encoded by the payload codec if present. - """ - _from_raw: bool = dataclasses.field(compare=False, init=False) - - @staticmethod - def _from_proto( # pyright: ignore - info: temporalio.api.workflow.v1.NewWorkflowExecutionInfo, # type: ignore[override] - ) -> ScheduleActionStartWorkflow: - return ScheduleActionStartWorkflow("", raw_info=info) - - # Overload for no-param workflow - @overload - def __init__( - self, - workflow: MethodAsyncNoParam[SelfType, ReturnType], - *, - id: str, - task_queue: str, - execution_timeout: timedelta | None = None, - run_timeout: timedelta | None = None, - task_timeout: timedelta | None = None, - retry_policy: temporalio.common.RetryPolicy | None = None, - memo: Mapping[str, Any] | None = None, - typed_search_attributes: temporalio.common.TypedSearchAttributes = temporalio.common.TypedSearchAttributes.empty, - static_summary: str | None = None, - static_details: str | None = None, - priority: temporalio.common.Priority = temporalio.common.Priority.default, - ) -> None: ... - - # Overload for single-param workflow - @overload - def __init__( - self, - workflow: MethodAsyncSingleParam[SelfType, ParamType, ReturnType], - arg: ParamType, - *, - id: str, - task_queue: str, - execution_timeout: timedelta | None = None, - run_timeout: timedelta | None = None, - task_timeout: timedelta | None = None, - retry_policy: temporalio.common.RetryPolicy | None = None, - memo: Mapping[str, Any] | None = None, - typed_search_attributes: temporalio.common.TypedSearchAttributes = temporalio.common.TypedSearchAttributes.empty, - static_summary: str | None = None, - static_details: str | None = None, - priority: temporalio.common.Priority = temporalio.common.Priority.default, - ) -> None: ... - - # Overload for multi-param workflow - @overload - def __init__( - self, - workflow: Callable[ - Concatenate[SelfType, MultiParamSpec], Awaitable[ReturnType] - ], - *, - args: Sequence[Any], - id: str, - task_queue: str, - execution_timeout: timedelta | None = None, - run_timeout: timedelta | None = None, - task_timeout: timedelta | None = None, - retry_policy: temporalio.common.RetryPolicy | None = None, - memo: Mapping[str, Any] | None = None, - typed_search_attributes: temporalio.common.TypedSearchAttributes = temporalio.common.TypedSearchAttributes.empty, - static_summary: str | None = None, - static_details: str | None = None, - priority: temporalio.common.Priority = temporalio.common.Priority.default, - ) -> None: ... - - # Overload for string-name workflow - @overload - def __init__( - self, - workflow: str, - arg: Any = temporalio.common._arg_unset, - *, - args: Sequence[Any] = [], - id: str, - task_queue: str, - execution_timeout: timedelta | None = None, - run_timeout: timedelta | None = None, - task_timeout: timedelta | None = None, - retry_policy: temporalio.common.RetryPolicy | None = None, - memo: Mapping[str, Any] | None = None, - typed_search_attributes: temporalio.common.TypedSearchAttributes = temporalio.common.TypedSearchAttributes.empty, - static_summary: str | None = None, - static_details: str | None = None, - priority: temporalio.common.Priority = temporalio.common.Priority.default, - ) -> None: ... - - # Overload for raw info - @overload - def __init__( - self, - workflow: str, - *, - raw_info: temporalio.api.workflow.v1.NewWorkflowExecutionInfo, - ) -> None: ... - - def __init__( - self, - workflow: str | Callable[..., Awaitable[Any]], - arg: Any = temporalio.common._arg_unset, - *, - args: Sequence[Any] = [], - id: str | None = None, - task_queue: str | None = None, - execution_timeout: timedelta | None = None, - run_timeout: timedelta | None = None, - task_timeout: timedelta | None = None, - retry_policy: temporalio.common.RetryPolicy | None = None, - memo: Mapping[str, Any] | None = None, - typed_search_attributes: temporalio.common.TypedSearchAttributes = temporalio.common.TypedSearchAttributes.empty, - untyped_search_attributes: temporalio.common.SearchAttributes = {}, - static_summary: str | None = None, - static_details: str | None = None, - headers: Mapping[str, temporalio.api.common.v1.Payload] | None = None, - raw_info: temporalio.api.workflow.v1.NewWorkflowExecutionInfo | None = None, - priority: temporalio.common.Priority = temporalio.common.Priority.default, - ) -> None: - """Create a start-workflow action. - - See :py:meth:`Client.start_workflow` for details on these parameter - values. - """ - super().__init__() - if raw_info: - self._from_raw = True - # Ignore other fields - self.workflow = raw_info.workflow_type.name - self.args = raw_info.input.payloads if raw_info.input else [] - self.id = raw_info.workflow_id - self.task_queue = raw_info.task_queue.name - self.execution_timeout = ( - raw_info.workflow_execution_timeout.ToTimedelta() - if raw_info.HasField("workflow_execution_timeout") - else None - ) - self.run_timeout = ( - raw_info.workflow_run_timeout.ToTimedelta() - if raw_info.HasField("workflow_run_timeout") - else None - ) - self.task_timeout = ( - raw_info.workflow_task_timeout.ToTimedelta() - if raw_info.HasField("workflow_task_timeout") - else None - ) - self.retry_policy = ( - temporalio.common.RetryPolicy.from_proto(raw_info.retry_policy) - if raw_info.HasField("retry_policy") - else None - ) - self.memo = raw_info.memo.fields if raw_info.memo.fields else None - self.typed_search_attributes = ( - temporalio.converter.decode_typed_search_attributes( - raw_info.search_attributes - ) - ) - self.headers = raw_info.header.fields if raw_info.header.fields else None - # Also set the untyped attributes as the set of attributes from - # decode with the typed ones removed - self.untyped_search_attributes = ( - temporalio.converter.decode_search_attributes( - raw_info.search_attributes - ) - ) - for pair in self.typed_search_attributes: - if pair.key.name in self.untyped_search_attributes: - # We know this is mutable here - del self.untyped_search_attributes[pair.key.name] # type: ignore - self.static_summary = ( - raw_info.user_metadata.summary - if raw_info.HasField("user_metadata") and raw_info.user_metadata.summary - else None - ) - self.static_details = ( - raw_info.user_metadata.details - if raw_info.HasField("user_metadata") and raw_info.user_metadata.details - else None - ) - self.priority = ( - temporalio.common.Priority._from_proto(raw_info.priority) - if raw_info.HasField("priority") and raw_info.priority - else temporalio.common.Priority.default - ) - else: - self._from_raw = False - if not id: - raise ValueError("ID required") - if not task_queue: - raise ValueError("Task queue required") - # Use definition if callable - if callable(workflow): - defn = temporalio.workflow._Definition.must_from_run_fn(workflow) - if not defn.name: - raise ValueError("Cannot schedule dynamic workflow explicitly") - workflow = defn.name - elif not isinstance(workflow, str): - raise TypeError("Workflow must be a string or callable") # type:ignore[reportUnreachable] - self.workflow = workflow - self.args = temporalio.common._arg_or_args(arg, args) - self.id = id - self.task_queue = task_queue - self.execution_timeout = execution_timeout - self.run_timeout = run_timeout - self.task_timeout = task_timeout - self.retry_policy = retry_policy - self.memo = memo - self.typed_search_attributes = typed_search_attributes - self.untyped_search_attributes = untyped_search_attributes - self.headers = headers # encode here - self.static_summary = static_summary - self.static_details = static_details - self.priority = priority - - async def _to_proto( - self, client: Client - ) -> temporalio.api.schedule.v1.ScheduleAction: - execution_timeout: google.protobuf.duration_pb2.Duration | None = None - if self.execution_timeout: - execution_timeout = google.protobuf.duration_pb2.Duration() - execution_timeout.FromTimedelta(self.execution_timeout) - run_timeout: google.protobuf.duration_pb2.Duration | None = None - if self.run_timeout: - run_timeout = google.protobuf.duration_pb2.Duration() - run_timeout.FromTimedelta(self.run_timeout) - task_timeout: google.protobuf.duration_pb2.Duration | None = None - if self.task_timeout: - task_timeout = google.protobuf.duration_pb2.Duration() - task_timeout.FromTimedelta(self.task_timeout) - retry_policy: temporalio.api.common.v1.RetryPolicy | None = None - if self.retry_policy: - retry_policy = temporalio.api.common.v1.RetryPolicy() - self.retry_policy.apply_to_proto(retry_policy) - priority: temporalio.api.common.v1.Priority | None = None - if self.priority: - priority = self.priority._to_proto() - data_converter = client.data_converter._with_contexts( - WorkflowSerializationContext( - namespace=client.namespace, - workflow_id=self.id, - ), - StorageDriverStoreContext( - target=StorageDriverWorkflowInfo( - id=self.id, type=self.workflow, namespace=client.namespace - ), - ), - ) - action = temporalio.api.schedule.v1.ScheduleAction( - start_workflow=temporalio.api.workflow.v1.NewWorkflowExecutionInfo( - workflow_id=self.id, - workflow_type=temporalio.api.common.v1.WorkflowType(name=self.workflow), - task_queue=temporalio.api.taskqueue.v1.TaskQueue(name=self.task_queue), - input=( - temporalio.api.common.v1.Payloads( - payloads=[ - a - if isinstance(a, temporalio.api.common.v1.Payload) - else (await data_converter.encode([a]))[0] - for a in self.args - ] - ) - if self.args - else None - ), - workflow_execution_timeout=execution_timeout, - workflow_run_timeout=run_timeout, - workflow_task_timeout=task_timeout, - retry_policy=retry_policy, - memo=await data_converter._encode_memo(self.memo) - if self.memo - else None, - user_metadata=await _encode_user_metadata( - data_converter, self.static_summary, self.static_details - ), - priority=priority, - ), - ) - # Add any untyped attributes that are not also in the typed set - untyped_not_in_typed = { - k: v - for k, v in self.untyped_search_attributes.items() - if k not in self.typed_search_attributes - } - if untyped_not_in_typed: - temporalio.converter.encode_search_attributes( - untyped_not_in_typed, action.start_workflow.search_attributes - ) - # TODO (dan): confirm whether this be `is not None` - if self.typed_search_attributes: - temporalio.converter.encode_search_attributes( - self.typed_search_attributes, - action.start_workflow.search_attributes, - ) - if self.headers: - await _apply_headers( - self.headers, - action.start_workflow.header.fields, - client.config(active_config=True)["header_codec_behavior"] - == HeaderCodecBehavior.CODEC - and not self._from_raw, - client.data_converter, - ) - return action - - -class ScheduleOverlapPolicy(IntEnum): - """Controls what happens when a workflow would be started by a schedule but - one is already running. - """ - - SKIP = int( - temporalio.api.enums.v1.ScheduleOverlapPolicy.SCHEDULE_OVERLAP_POLICY_SKIP - ) - """Don't start anything. - - When the workflow completes, the next scheduled event after that time will - be considered. - """ - - BUFFER_ONE = int( - temporalio.api.enums.v1.ScheduleOverlapPolicy.SCHEDULE_OVERLAP_POLICY_BUFFER_ONE - ) - """Start the workflow again soon as the current one completes, but only - buffer one start in this way. - - If another start is supposed to happen when the workflow is running, and one - is already buffered, then only the first one will be started after the - running workflow finishes. - """ - - BUFFER_ALL = int( - temporalio.api.enums.v1.ScheduleOverlapPolicy.SCHEDULE_OVERLAP_POLICY_BUFFER_ALL - ) - """Buffer up any number of starts to all happen sequentially, immediately - after the running workflow completes.""" - - CANCEL_OTHER = int( - temporalio.api.enums.v1.ScheduleOverlapPolicy.SCHEDULE_OVERLAP_POLICY_CANCEL_OTHER - ) - """If there is another workflow running, cancel it, and start the new one - after the old one completes cancellation.""" - - TERMINATE_OTHER = int( - temporalio.api.enums.v1.ScheduleOverlapPolicy.SCHEDULE_OVERLAP_POLICY_TERMINATE_OTHER - ) - """If there is another workflow running, terminate it and start the new one - immediately.""" - - ALLOW_ALL = int( - temporalio.api.enums.v1.ScheduleOverlapPolicy.SCHEDULE_OVERLAP_POLICY_ALLOW_ALL - ) - """Start any number of concurrent workflows. - - Note that with this policy, last completion result and last failure will not - be available since workflows are not sequential.""" - - -@dataclass -class ScheduleBackfill: - """Time period and policy for actions taken as if the time passed right - now. - """ - - start_at: datetime - """Start of the range to evaluate the schedule in. - - This is exclusive - """ - end_at: datetime - overlap: ScheduleOverlapPolicy | None = None - - def _to_proto(self) -> temporalio.api.schedule.v1.BackfillRequest: - start_time = google.protobuf.timestamp_pb2.Timestamp() - start_time.FromDatetime(self.start_at) - end_time = google.protobuf.timestamp_pb2.Timestamp() - end_time.FromDatetime(self.end_at) - overlap_policy = temporalio.api.enums.v1.ScheduleOverlapPolicy.SCHEDULE_OVERLAP_POLICY_UNSPECIFIED - if self.overlap: - overlap_policy = temporalio.api.enums.v1.ScheduleOverlapPolicy.ValueType( - self.overlap - ) - return temporalio.api.schedule.v1.BackfillRequest( - start_time=start_time, - end_time=end_time, - overlap_policy=overlap_policy, - ) - - -@dataclass -class SchedulePolicy: - """Policies of a schedule.""" - - overlap: ScheduleOverlapPolicy = dataclasses.field( - default_factory=lambda: ScheduleOverlapPolicy.SKIP - ) - """Controls what happens when an action is started while another is still - running.""" - - catchup_window: timedelta = timedelta(days=365) - """After a Temporal server is unavailable, amount of time in the past to - execute missed actions.""" - - pause_on_failure: bool = False - """Whether to pause the schedule if an action fails or times out. - - Note: For workflows, this only applies after all retries have been - exhausted. - """ - - @staticmethod - def _from_proto(pol: temporalio.api.schedule.v1.SchedulePolicies) -> SchedulePolicy: - return SchedulePolicy( - overlap=ScheduleOverlapPolicy(int(pol.overlap_policy)), - catchup_window=pol.catchup_window.ToTimedelta(), - pause_on_failure=pol.pause_on_failure, - ) - - def _to_proto(self) -> temporalio.api.schedule.v1.SchedulePolicies: - catchup_window = google.protobuf.duration_pb2.Duration() - catchup_window.FromTimedelta(self.catchup_window) - return temporalio.api.schedule.v1.SchedulePolicies( - overlap_policy=temporalio.api.enums.v1.ScheduleOverlapPolicy.ValueType( - self.overlap - ), - catchup_window=catchup_window, - pause_on_failure=self.pause_on_failure, - ) - - -@dataclass -class ScheduleState: - """State of a schedule.""" - - note: str | None = None - """Human readable message for the schedule. - - The system may overwrite this value on certain conditions like - pause-on-failure. - """ - - paused: bool = False - """Whether the schedule is paused.""" - - # Cannot be set to True on create - limited_actions: bool = False - """ - If true, remaining actions will be decremented for each action taken. - - On schedule create, this must be set to true if :py:attr:`remaining_actions` - is non-zero and left false if :py:attr:`remaining_actions` is zero. - """ - - remaining_actions: int = 0 - """Actions remaining on this schedule. - - Once this number hits 0, no further actions are scheduled automatically. - """ - - @staticmethod - def _from_proto(state: temporalio.api.schedule.v1.ScheduleState) -> ScheduleState: - return ScheduleState( - note=state.notes or None, - paused=state.paused, - limited_actions=state.limited_actions, - remaining_actions=state.remaining_actions, - ) - - def _to_proto(self) -> temporalio.api.schedule.v1.ScheduleState: - return temporalio.api.schedule.v1.ScheduleState( - notes=self.note or "", - paused=self.paused, - limited_actions=self.limited_actions, - remaining_actions=self.remaining_actions, - ) - - -@dataclass -class Schedule: - """A schedule for periodically running an action.""" - - action: ScheduleAction - """Action taken when scheduled.""" - - spec: ScheduleSpec - """When the action is taken.""" - - policy: SchedulePolicy = dataclasses.field(default_factory=SchedulePolicy) - """Schedule policies.""" - - state: ScheduleState = dataclasses.field(default_factory=ScheduleState) - """State of the schedule.""" - - @staticmethod - def _from_proto(sched: temporalio.api.schedule.v1.Schedule) -> Schedule: - return Schedule( - action=ScheduleAction._from_proto(sched.action), - spec=ScheduleSpec._from_proto(sched.spec), - policy=SchedulePolicy._from_proto(sched.policies), - state=ScheduleState._from_proto(sched.state), - ) - - async def _to_proto(self, client: Client) -> temporalio.api.schedule.v1.Schedule: - catchup_window = google.protobuf.duration_pb2.Duration() - catchup_window.FromTimedelta(self.policy.catchup_window) - return temporalio.api.schedule.v1.Schedule( - spec=self.spec._to_proto(), - action=await self.action._to_proto(client), - policies=self.policy._to_proto(), - state=self.state._to_proto(), - ) - - -@dataclass -class ScheduleDescription: - """Description of a schedule.""" - - id: str - """ID of the schedule.""" - - schedule: Schedule - """Schedule details that can be mutated.""" - - info: ScheduleInfo - """Information about the schedule.""" - - typed_search_attributes: temporalio.common.TypedSearchAttributes - """Search attributes on the schedule.""" - - search_attributes: temporalio.common.SearchAttributes - """Search attributes on the schedule. - - .. deprecated:: - Use :py:attr:`typed_search_attributes` instead. - """ - - data_converter: temporalio.converter.DataConverter - """Data converter used for memo decoding.""" - - raw_description: temporalio.api.workflowservice.v1.DescribeScheduleResponse - """Raw description of the schedule.""" - - @staticmethod - def _from_proto( - id: str, - desc: temporalio.api.workflowservice.v1.DescribeScheduleResponse, - converter: temporalio.converter.DataConverter, - ) -> ScheduleDescription: - return ScheduleDescription( - id=id, - schedule=Schedule._from_proto(desc.schedule), - info=ScheduleInfo._from_proto(desc.info), - typed_search_attributes=temporalio.converter.decode_typed_search_attributes( - desc.search_attributes - ), - search_attributes=temporalio.converter.decode_search_attributes( - desc.search_attributes - ), - data_converter=converter, - raw_description=desc, - ) - - async def memo(self) -> Mapping[str, Any]: - """Schedule's memo values, converted without type hints. - - Since type hints are not used, the default converted values will come - back. For example, if the memo was originally created with a dataclass, - the value will be a dict. To convert using proper type hints, use - :py:meth:`memo_value`. - - Returns: - Mapping of all memo keys and they values without type hints. - """ - return await self.data_converter._decode_memo(self.raw_description.memo) - - @overload - async def memo_value( - self, key: str, default: Any = temporalio.common._arg_unset - ) -> Any: ... - - @overload - async def memo_value( - self, key: str, *, type_hint: type[ParamType] - ) -> ParamType: ... - - @overload - async def memo_value( - self, key: str, default: AnyType, *, type_hint: type[ParamType] - ) -> AnyType | ParamType: ... - - async def memo_value( - self, - key: str, - default: Any = temporalio.common._arg_unset, - *, - type_hint: type | None = None, - ) -> Any: - """Memo value for the given key, optional default, and optional type - hint. - - Args: - key: Key to get memo value for. - default: Default to use if key is not present. If unset, a - :py:class:`KeyError` is raised when the key does not exist. - type_hint: type hint to use when converting. - - Returns: - Memo value, converted with the type hint if present. - - Raises: - KeyError: Key not present and default not set. - """ - return await self.data_converter._decode_memo_field( - self.raw_description.memo, key, default, type_hint - ) - - -@dataclass -class ScheduleInfo: - """Information about a schedule.""" - - num_actions: int - """Number of actions taken by this schedule.""" - - num_actions_missed_catchup_window: int - """Number of times an action was skipped due to missing the catchup - window.""" - - num_actions_skipped_overlap: int - """Number of actions skipped due to overlap.""" - - running_actions: Sequence[ScheduleActionExecution] - """Currently running actions.""" - - recent_actions: Sequence[ScheduleActionResult] - """10 most recent actions, oldest first.""" - - next_action_times: Sequence[datetime] - """Next 10 scheduled action times.""" - - created_at: datetime - """When the schedule was created.""" - - last_updated_at: datetime | None - """When the schedule was last updated.""" - - @staticmethod - def _from_proto(info: temporalio.api.schedule.v1.ScheduleInfo) -> ScheduleInfo: - return ScheduleInfo( - num_actions=info.action_count, - num_actions_missed_catchup_window=info.missed_catchup_window, - num_actions_skipped_overlap=info.overlap_skipped, - running_actions=[ - ScheduleActionExecutionStartWorkflow._from_proto(r) - for r in info.running_workflows - ], - recent_actions=[ - ScheduleActionResult._from_proto(r) for r in info.recent_actions - ], - next_action_times=[ - f.ToDatetime().replace(tzinfo=timezone.utc) - for f in info.future_action_times - ], - created_at=info.create_time.ToDatetime().replace(tzinfo=timezone.utc), - last_updated_at=info.update_time.ToDatetime().replace(tzinfo=timezone.utc) - if info.HasField("update_time") - else None, - ) - - -class ScheduleActionExecution(ABC): - """Base class for an action execution.""" - - pass - - -@dataclass -class ScheduleActionExecutionStartWorkflow(ScheduleActionExecution): - """Execution of a scheduled workflow start.""" - - workflow_id: str - """Workflow ID.""" - - first_execution_run_id: str - """Workflow run ID.""" - - @staticmethod - def _from_proto( - exec: temporalio.api.common.v1.WorkflowExecution, - ) -> ScheduleActionExecutionStartWorkflow: - return ScheduleActionExecutionStartWorkflow( - workflow_id=exec.workflow_id, - first_execution_run_id=exec.run_id, - ) - - -@dataclass -class ScheduleActionResult: - """Information about when an action took place.""" - - scheduled_at: datetime - """Scheduled time of the action including jitter.""" - - started_at: datetime - """When the action actually started.""" - - action: ScheduleActionExecution - """Action that took place.""" - - @staticmethod - def _from_proto( - res: temporalio.api.schedule.v1.ScheduleActionResult, - ) -> ScheduleActionResult: - return ScheduleActionResult( - scheduled_at=res.schedule_time.ToDatetime().replace(tzinfo=timezone.utc), - started_at=res.actual_time.ToDatetime().replace(tzinfo=timezone.utc), - action=ScheduleActionExecutionStartWorkflow._from_proto( - res.start_workflow_result - ), - ) - - -@dataclass -class ScheduleUpdateInput: - """Parameter for an update callback for :py:meth:`ScheduleHandle.update`.""" - - description: ScheduleDescription - """Current description of the schedule.""" - - -@dataclass -class ScheduleUpdate: - """Result of an update callback for :py:meth:`ScheduleHandle.update`.""" - - schedule: Schedule - """Schedule to update.""" - - search_attributes: temporalio.common.TypedSearchAttributes | None = None - """Search attributes to update.""" - - -@dataclass -class ScheduleListDescription: - """Description of a listed schedule.""" - - id: str - """ID of the schedule.""" - - schedule: ScheduleListSchedule | None - """Schedule details that can be mutated. - - This may not be present in older Temporal servers without advanced - visibility. - """ - - info: ScheduleListInfo | None - """Information about the schedule. - - This may not be present in older Temporal servers without advanced - visibility. - """ - - typed_search_attributes: temporalio.common.TypedSearchAttributes - """Search attributes on the schedule.""" - - search_attributes: temporalio.common.SearchAttributes - """Search attributes on the schedule. - - .. deprecated:: - Use :py:attr:`typed_search_attributes` instead. - """ - - data_converter: temporalio.converter.DataConverter - """Data converter used for memo decoding.""" - - raw_entry: temporalio.api.schedule.v1.ScheduleListEntry - """Raw description of the schedule.""" - - @staticmethod - def _from_proto( - entry: temporalio.api.schedule.v1.ScheduleListEntry, - converter: temporalio.converter.DataConverter, - ) -> ScheduleListDescription: - return ScheduleListDescription( - id=entry.schedule_id, - schedule=ScheduleListSchedule._from_proto(entry.info) - if entry.HasField("info") - else None, - info=ScheduleListInfo._from_proto(entry.info) - if entry.HasField("info") - else None, - typed_search_attributes=temporalio.converter.decode_typed_search_attributes( - entry.search_attributes - ), - search_attributes=temporalio.converter.decode_search_attributes( - entry.search_attributes - ), - data_converter=converter, - raw_entry=entry, - ) - - async def memo(self) -> Mapping[str, Any]: - """Schedule's memo values, converted without type hints. - - Since type hints are not used, the default converted values will come - back. For example, if the memo was originally created with a dataclass, - the value will be a dict. To convert using proper type hints, use - :py:meth:`memo_value`. - - Returns: - Mapping of all memo keys and they values without type hints. - """ - return await self.data_converter._decode_memo(self.raw_entry.memo) - - @overload - async def memo_value( - self, key: str, default: Any = temporalio.common._arg_unset - ) -> Any: ... - - @overload - async def memo_value( - self, key: str, *, type_hint: type[ParamType] - ) -> ParamType: ... - - @overload - async def memo_value( - self, key: str, default: AnyType, *, type_hint: type[ParamType] - ) -> AnyType | ParamType: ... - - async def memo_value( - self, - key: str, - default: Any = temporalio.common._arg_unset, - *, - type_hint: type | None = None, - ) -> Any: - """Memo value for the given key, optional default, and optional type - hint. - - Args: - key: Key to get memo value for. - default: Default to use if key is not present. If unset, a - :py:class:`KeyError` is raised when the key does not exist. - type_hint: type hint to use when converting. - - Returns: - Memo value, converted with the type hint if present. - - Raises: - KeyError: Key not present and default not set. - """ - return await self.data_converter._decode_memo_field( - self.raw_entry.memo, key, default, type_hint - ) - - -@dataclass -class ScheduleListSchedule: - """Details for a listed schedule.""" - - action: ScheduleListAction - """Action taken when scheduled.""" - - spec: ScheduleSpec - """When the action is taken.""" - - state: ScheduleListState - """State of the schedule.""" - - @staticmethod - def _from_proto( - info: temporalio.api.schedule.v1.ScheduleListInfo, - ) -> ScheduleListSchedule: - # Only start workflow supported for now - if not info.HasField("workflow_type"): - raise ValueError("Unknown action on schedule") - return ScheduleListSchedule( - action=ScheduleListActionStartWorkflow(workflow=info.workflow_type.name), - spec=ScheduleSpec._from_proto(info.spec), - state=ScheduleListState._from_proto(info), - ) - - -class ScheduleListAction(ABC): - """Base class for an action a listed schedule can take.""" - - pass - - -@dataclass -class ScheduleListActionStartWorkflow(ScheduleListAction): - """Action to start a workflow on a listed schedule.""" - - workflow: str - """Workflow type name.""" - - -@dataclass -class ScheduleListInfo: - """Information about a listed schedule.""" - - recent_actions: Sequence[ScheduleActionResult] - """Most recent actions, oldest first. - - This may be a smaller amount than present on - :py:attr:`ScheduleDescription.info`. - """ - - next_action_times: Sequence[datetime] - """Next scheduled action times. - - This may be a smaller amount than present on - :py:attr:`ScheduleDescription.info`. - """ - - @staticmethod - def _from_proto( - info: temporalio.api.schedule.v1.ScheduleListInfo, - ) -> ScheduleListInfo: - return ScheduleListInfo( - recent_actions=[ - ScheduleActionResult._from_proto(r) for r in info.recent_actions - ], - next_action_times=[ - f.ToDatetime().replace(tzinfo=timezone.utc) - for f in info.future_action_times - ], - ) - - -@dataclass -class ScheduleListState: - """State of a listed schedule.""" - - note: str | None - """Human readable message for the schedule. - - The system may overwrite this value on certain conditions like - pause-on-failure. - """ - - paused: bool - """Whether the schedule is paused.""" - - @staticmethod - def _from_proto( - info: temporalio.api.schedule.v1.ScheduleListInfo, - ) -> ScheduleListState: - return ScheduleListState( - note=info.notes or None, - paused=info.paused, - ) - - -class ScheduleAsyncIterator: - """Asynchronous iterator for :py:class:`ScheduleListDescription` values. - - Most users should use ``async for`` on this iterator and not call any of the - methods within. - """ - - def __init__( - self, - client: Client, - input: ListSchedulesInput, - ) -> None: - """Create an asynchronous iterator for the given input. - - Users should not create this directly, but rather use - :py:meth:`Client.list_schedules`. - """ - self._client = client - self._input = input - self._next_page_token = input.next_page_token - self._current_page: Sequence[ScheduleListDescription] | None = None - self._current_page_index = 0 - - @property - def current_page_index(self) -> int: - """Index of the entry in the current page that will be returned from - the next :py:meth:`__anext__` call. - """ - return self._current_page_index - - @property - def current_page(self) -> Sequence[ScheduleListDescription] | None: - """Current page, if it has been fetched yet.""" - return self._current_page - - @property - def next_page_token(self) -> bytes | None: - """Token for the next page request if any.""" - return self._next_page_token - - async def fetch_next_page(self, *, page_size: int | None = None) -> None: - """Fetch the next page if any. - - Args: - page_size: Override the page size this iterator was originally - created with. - """ - resp = await self._client.workflow_service.list_schedules( - temporalio.api.workflowservice.v1.ListSchedulesRequest( - namespace=self._client.namespace, - maximum_page_size=page_size or self._input.page_size, - next_page_token=self._next_page_token or b"", - query=self._input.query or "", - ), - retry=True, - metadata=self._input.rpc_metadata, - timeout=self._input.rpc_timeout, - ) - self._current_page = [ - ScheduleListDescription._from_proto(v, self._client.data_converter) - for v in resp.schedules - ] - self._current_page_index = 0 - self._next_page_token = resp.next_page_token or None - - def __aiter__(self) -> ScheduleAsyncIterator: - """Return self as the iterator.""" - return self - - async def __anext__(self) -> ScheduleListDescription: - """Get the next execution on this iterator, fetching next page if - necessary. - """ - while True: - # No page? fetch and continue - if self._current_page is None: - await self.fetch_next_page() - continue - # No more left in page? - if self._current_page_index >= len(self._current_page): - # If there is a next page token, try to get another page and try - # again - if self._next_page_token is not None: - await self.fetch_next_page() - continue - # No more pages means we're done - raise StopAsyncIteration - # Get current, increment page index, and return - ret = self._current_page[self._current_page_index] - self._current_page_index += 1 - return ret - - -class WorkflowUpdateHandle(Generic[LocalReturnType]): - """Handle for a workflow update execution request.""" - - def __init__( - self, - client: Client, - id: str, - workflow_id: str, - *, - workflow_run_id: str | None = None, - result_type: type | None = None, - known_outcome: temporalio.api.update.v1.Outcome | None = None, - ): - """Create a workflow update handle. - - Users should not create this directly, but rather use - :py:meth:`WorkflowHandle.start_update` or :py:meth:`WorkflowHandle.get_update_handle`. - """ - self._client = client - self._id = id - self._workflow_id = workflow_id - self._workflow_run_id = workflow_run_id - self._result_type = result_type - self._known_outcome = known_outcome - - @functools.cached_property - def _data_converter(self) -> temporalio.converter.DataConverter: - return self._client.data_converter.with_context( - WorkflowSerializationContext( - namespace=self._client.namespace, - workflow_id=self.workflow_id, - ) - ) - - @property - def id(self) -> str: - """ID of this Update request.""" - return self._id - - @property - def workflow_id(self) -> str: - """The ID of the Workflow targeted by this Update.""" - return self._workflow_id - - @property - def workflow_run_id(self) -> str | None: - """If specified, the specific run of the Workflow targeted by this Update.""" - return self._workflow_run_id - - async def result( - self, - *, - rpc_metadata: Mapping[str, str | bytes] = {}, - rpc_timeout: timedelta | None = None, - ) -> LocalReturnType: - """Wait for and return the result of the update. The result may already be known in which case no network call - is made. Otherwise the result will be polled for until it is returned. - - Args: - rpc_metadata: Headers used on the RPC call. Keys here override client-level RPC metadata keys. - rpc_timeout: Optional RPC deadline to set for each RPC call. Note: this is the timeout for each - RPC call while polling, not a timeout for the function as a whole. If an individual RPC times out, - it will be retried until the result is available. - - Raises: - WorkflowUpdateFailedError: If the update failed. - WorkflowUpdateRPCTimeoutOrCancelledError: This update call timed out - or was cancelled. This doesn't mean the update itself was timed - out or cancelled. - RPCError: Update result could not be fetched for some other reason. - """ - # Poll until outcome reached - await self._poll_until_outcome( - rpc_metadata=rpc_metadata, rpc_timeout=rpc_timeout - ) - - # Convert outcome to failure or value - assert self._known_outcome - if self._known_outcome.HasField("failure"): - raise WorkflowUpdateFailedError( - await self._data_converter.decode_failure(self._known_outcome.failure), - ) - if not self._known_outcome.success.payloads: - return None # type: ignore - type_hints = [self._result_type] if self._result_type else None - results = await self._data_converter.decode( - self._known_outcome.success.payloads, type_hints - ) - if not results: - return None # type: ignore - elif len(results) > 1: - warnings.warn(f"Expected single update result, got {len(results)}") - return results[0] - - async def _poll_until_outcome( - self, - rpc_metadata: Mapping[str, str | bytes] = {}, - rpc_timeout: timedelta | None = None, - ) -> None: - if self._known_outcome: - return - req = temporalio.api.workflowservice.v1.PollWorkflowExecutionUpdateRequest( - namespace=self._client.namespace, - update_ref=temporalio.api.update.v1.UpdateRef( - workflow_execution=temporalio.api.common.v1.WorkflowExecution( - workflow_id=self.workflow_id, - run_id=self.workflow_run_id or "", - ), - update_id=self.id, - ), - identity=self._client.identity, - wait_policy=temporalio.api.update.v1.WaitPolicy( - lifecycle_stage=temporalio.api.enums.v1.UpdateWorkflowExecutionLifecycleStage.UPDATE_WORKFLOW_EXECUTION_LIFECYCLE_STAGE_COMPLETED - ), - ) - - # Continue polling as long as we have no outcome - while True: - try: - res = ( - await self._client.workflow_service.poll_workflow_execution_update( - req, - retry=True, - metadata=rpc_metadata, - timeout=rpc_timeout, - ) - ) - if res.HasField("outcome"): - self._known_outcome = res.outcome - return - except RPCError as err: - if ( - err.status == RPCStatusCode.DEADLINE_EXCEEDED - or err.status == RPCStatusCode.CANCELLED - ): - raise WorkflowUpdateRPCTimeoutOrCancelledError() from err - else: - raise - except asyncio.CancelledError as err: - raise WorkflowUpdateRPCTimeoutOrCancelledError() from err - - -class WorkflowUpdateStage(IntEnum): - """Stage to wait for workflow update to reach before returning from - ``start_update``. - """ - - ADMITTED = int( - temporalio.api.enums.v1.UpdateWorkflowExecutionLifecycleStage.UPDATE_WORKFLOW_EXECUTION_LIFECYCLE_STAGE_ADMITTED - ) - ACCEPTED = int( - temporalio.api.enums.v1.UpdateWorkflowExecutionLifecycleStage.UPDATE_WORKFLOW_EXECUTION_LIFECYCLE_STAGE_ACCEPTED - ) - COMPLETED = int( - temporalio.api.enums.v1.UpdateWorkflowExecutionLifecycleStage.UPDATE_WORKFLOW_EXECUTION_LIFECYCLE_STAGE_COMPLETED - ) - - -class WorkflowFailureError(temporalio.exceptions.TemporalError): - """Error that occurs when a workflow is unsuccessful.""" - - def __init__(self, *, cause: BaseException) -> None: - """Create workflow failure error.""" - super().__init__("Workflow execution failed") - self.__cause__ = cause - - @property - def cause(self) -> BaseException: - """Cause of the workflow failure.""" - assert self.__cause__ - return self.__cause__ - - -class WorkflowContinuedAsNewError(temporalio.exceptions.TemporalError): - """Error that occurs when a workflow was continued as new.""" - - def __init__(self, new_execution_run_id: str) -> None: - """Create workflow continue as new error.""" - super().__init__("Workflow continued as new") - self._new_execution_run_id = new_execution_run_id - - @property - def new_execution_run_id(self) -> str: - """New execution run ID the workflow continued to""" - return self._new_execution_run_id - - -class WorkflowQueryRejectedError(temporalio.exceptions.TemporalError): - """Error that occurs when a query was rejected.""" - - def __init__(self, status: WorkflowExecutionStatus | None) -> None: - """Create workflow query rejected error.""" - super().__init__(f"Query rejected, status: {status}") - self._status = status - - @property - def status(self) -> WorkflowExecutionStatus | None: - """Get workflow execution status causing rejection.""" - return self._status - - -class WorkflowQueryFailedError(temporalio.exceptions.TemporalError): - """Error that occurs when a query fails.""" - - def __init__(self, message: str) -> None: - """Create workflow query failed error.""" - super().__init__(message) - self._message = message - - @property - def message(self) -> str: - """Get query failed message.""" - return self._message - - -class WorkflowUpdateFailedError(temporalio.exceptions.TemporalError): - """Error that occurs when an update fails.""" - - def __init__(self, cause: BaseException) -> None: - """Create workflow update failed error.""" - super().__init__("Workflow update failed") - self.__cause__ = cause - - @property - def cause(self) -> BaseException: - """Cause of the update failure.""" - assert self.__cause__ - return self.__cause__ - - -class RPCTimeoutOrCancelledError(temporalio.exceptions.TemporalError): - """Error that occurs on some client calls that timeout or get cancelled.""" - - pass - - -class WorkflowUpdateRPCTimeoutOrCancelledError(RPCTimeoutOrCancelledError): - """Error that occurs when update RPC call times out or is cancelled. - - Note, this is not related to any general concept of timing out or cancelling - a running update, this is only related to the client call itself. - """ - - def __init__(self) -> None: - """Create workflow update timeout or cancelled error.""" - super().__init__("Timeout or cancellation waiting for update") - - -class ActivityFailureError(temporalio.exceptions.TemporalError): - """Error that occurs when an activity is unsuccessful. - - .. warning:: - This API is experimental. - """ - - def __init__(self, *, cause: BaseException) -> None: - """Create activity failure error.""" - super().__init__("Activity execution failed") - self.__cause__ = cause - - @property - def cause(self) -> BaseException: - """Cause of the activity failure.""" - assert self.__cause__ - return self.__cause__ - - -class AsyncActivityCancelledError(temporalio.exceptions.TemporalError): - """Error that occurs when async activity attempted heartbeat but was cancelled.""" - - def __init__(self, details: ActivityCancellationDetails | None = None) -> None: - """Create async activity cancelled error.""" - super().__init__("Activity cancelled") - self.details = details - - -class ScheduleAlreadyRunningError(temporalio.exceptions.TemporalError): - """Error when a schedule is already running.""" - - def __init__(self) -> None: - """Create schedule already running error.""" - super().__init__("Schedule already running") - - -@dataclass -class StartWorkflowInput: - """Input for :py:meth:`OutboundInterceptor.start_workflow`.""" - - workflow: str - args: Sequence[Any] - id: str - task_queue: str - execution_timeout: timedelta | None - run_timeout: timedelta | None - task_timeout: timedelta | None - id_reuse_policy: temporalio.common.WorkflowIDReusePolicy - id_conflict_policy: temporalio.common.WorkflowIDConflictPolicy - retry_policy: temporalio.common.RetryPolicy | None - cron_schedule: str - memo: Mapping[str, Any] | None - search_attributes: None | ( - temporalio.common.SearchAttributes | temporalio.common.TypedSearchAttributes - ) - start_delay: timedelta | None - headers: Mapping[str, temporalio.api.common.v1.Payload] - start_signal: str | None - start_signal_args: Sequence[Any] - static_summary: str | None - static_details: str | None - # Type may be absent - ret_type: type | None - rpc_metadata: Mapping[str, str | bytes] - rpc_timeout: timedelta | None - request_eager_start: bool - priority: temporalio.common.Priority - # The following options are experimental and unstable. - callbacks: Sequence[Callback] - workflow_event_links: Sequence[temporalio.api.common.v1.Link.WorkflowEvent] - request_id: str | None - versioning_override: temporalio.common.VersioningOverride | None = None - - -@dataclass -class CancelWorkflowInput: - """Input for :py:meth:`OutboundInterceptor.cancel_workflow`.""" - - id: str - run_id: str | None - first_execution_run_id: str | None - rpc_metadata: Mapping[str, str | bytes] - rpc_timeout: timedelta | None - - -@dataclass -class DescribeWorkflowInput: - """Input for :py:meth:`OutboundInterceptor.describe_workflow`.""" - - id: str - run_id: str | None - rpc_metadata: Mapping[str, str | bytes] - rpc_timeout: timedelta | None - - -@dataclass -class FetchWorkflowHistoryEventsInput: - """Input for :py:meth:`OutboundInterceptor.fetch_workflow_history_events`.""" - - id: str - run_id: str | None - page_size: int | None - next_page_token: bytes | None - wait_new_event: bool - event_filter_type: WorkflowHistoryEventFilterType - skip_archival: bool - rpc_metadata: Mapping[str, str | bytes] - rpc_timeout: timedelta | None - - -@dataclass -class ListWorkflowsInput: - """Input for :py:meth:`OutboundInterceptor.list_workflows`.""" - - query: str | None - page_size: int - next_page_token: bytes | None - rpc_metadata: Mapping[str, str | bytes] - rpc_timeout: timedelta | None - limit: int | None - - -@dataclass -class CountWorkflowsInput: - """Input for :py:meth:`OutboundInterceptor.count_workflows`.""" - - query: str | None - rpc_metadata: Mapping[str, str | bytes] - rpc_timeout: timedelta | None - - -@dataclass -class QueryWorkflowInput: - """Input for :py:meth:`OutboundInterceptor.query_workflow`.""" - - id: str - run_id: str | None - query: str - args: Sequence[Any] - reject_condition: temporalio.common.QueryRejectCondition | None - headers: Mapping[str, temporalio.api.common.v1.Payload] - # Type may be absent - ret_type: type | None - rpc_metadata: Mapping[str, str | bytes] - rpc_timeout: timedelta | None - - -@dataclass -class SignalWorkflowInput: - """Input for :py:meth:`OutboundInterceptor.signal_workflow`.""" - - id: str - run_id: str | None - signal: str - args: Sequence[Any] - headers: Mapping[str, temporalio.api.common.v1.Payload] - rpc_metadata: Mapping[str, str | bytes] - rpc_timeout: timedelta | None - - -@dataclass -class TerminateWorkflowInput: - """Input for :py:meth:`OutboundInterceptor.terminate_workflow`.""" - - id: str - run_id: str | None - first_execution_run_id: str | None - args: Sequence[Any] - reason: str | None - rpc_metadata: Mapping[str, str | bytes] - rpc_timeout: timedelta | None - - -@dataclass -class StartActivityInput: - """Input for :py:meth:`OutboundInterceptor.start_activity`. - - .. warning:: - This API is experimental. - """ - - activity_type: str - args: Sequence[Any] - id: str - task_queue: str - result_type: type | None - schedule_to_close_timeout: timedelta | None - start_to_close_timeout: timedelta | None - schedule_to_start_timeout: timedelta | None - heartbeat_timeout: timedelta | None - id_reuse_policy: temporalio.common.ActivityIDReusePolicy - id_conflict_policy: temporalio.common.ActivityIDConflictPolicy - retry_policy: temporalio.common.RetryPolicy | None - priority: temporalio.common.Priority - search_attributes: temporalio.common.TypedSearchAttributes | None - summary: str | None - start_delay: timedelta | None - headers: Mapping[str, temporalio.api.common.v1.Payload] - rpc_metadata: Mapping[str, str | bytes] - rpc_timeout: timedelta | None - - -@dataclass -class CancelActivityInput: - """Input for :py:meth:`OutboundInterceptor.cancel_activity`. - - .. warning:: - This API is experimental. - """ - - activity_id: str - activity_run_id: str | None - reason: str | None - rpc_metadata: Mapping[str, str | bytes] - rpc_timeout: timedelta | None - - -@dataclass -class TerminateActivityInput: - """Input for :py:meth:`OutboundInterceptor.terminate_activity`. - - .. warning:: - This API is experimental. - """ - - activity_id: str - activity_run_id: str | None - reason: str | None - rpc_metadata: Mapping[str, str | bytes] - rpc_timeout: timedelta | None - - -@dataclass -class DescribeActivityInput: - """Input for :py:meth:`OutboundInterceptor.describe_activity`. - - .. warning:: - This API is experimental. - """ - - activity_id: str - activity_run_id: str | None - long_poll_token: bytes | None - rpc_metadata: Mapping[str, str | bytes] - rpc_timeout: timedelta | None - - -@dataclass -class ListActivitiesInput: - """Input for :py:meth:`OutboundInterceptor.list_activities`. - - .. warning:: - This API is experimental. - """ - - query: str | None - page_size: int - next_page_token: bytes | None - rpc_metadata: Mapping[str, str | bytes] - rpc_timeout: timedelta | None - limit: int | None - - -@dataclass -class CountActivitiesInput: - """Input for :py:meth:`OutboundInterceptor.count_activities`. - - .. warning:: - This API is experimental. - """ - - query: str | None - rpc_metadata: Mapping[str, str | bytes] - rpc_timeout: timedelta | None - - -@dataclass -class StartWorkflowUpdateInput: - """Input for :py:meth:`OutboundInterceptor.start_workflow_update`.""" - - id: str - run_id: str | None - first_execution_run_id: str | None - update_id: str | None - update: str - args: Sequence[Any] - wait_for_stage: WorkflowUpdateStage - headers: Mapping[str, temporalio.api.common.v1.Payload] - ret_type: type | None - rpc_metadata: Mapping[str, str | bytes] - rpc_timeout: timedelta | None - - -@dataclass -class UpdateWithStartUpdateWorkflowInput: - """Update input for :py:meth:`OutboundInterceptor.start_update_with_start_workflow`.""" - - update_id: str | None - update: str - args: Sequence[Any] - wait_for_stage: WorkflowUpdateStage - headers: Mapping[str, temporalio.api.common.v1.Payload] - ret_type: type | None - rpc_metadata: Mapping[str, str | bytes] - rpc_timeout: timedelta | None - - -@dataclass -class UpdateWithStartStartWorkflowInput: - """StartWorkflow input for :py:meth:`OutboundInterceptor.start_update_with_start_workflow`.""" - - # Similar to StartWorkflowInput but without e.g. run_id, start_signal, - # start_signal_args, request_eager_start. - - workflow: str - args: Sequence[Any] - id: str - task_queue: str - execution_timeout: timedelta | None - run_timeout: timedelta | None - task_timeout: timedelta | None - id_reuse_policy: temporalio.common.WorkflowIDReusePolicy - id_conflict_policy: temporalio.common.WorkflowIDConflictPolicy - retry_policy: temporalio.common.RetryPolicy | None - cron_schedule: str - memo: Mapping[str, Any] | None - search_attributes: None | ( - temporalio.common.SearchAttributes | temporalio.common.TypedSearchAttributes - ) - start_delay: timedelta | None - headers: Mapping[str, temporalio.api.common.v1.Payload] - static_summary: str | None - static_details: str | None - # Type may be absent - ret_type: type | None - rpc_metadata: Mapping[str, str | bytes] - rpc_timeout: timedelta | None - priority: temporalio.common.Priority - versioning_override: temporalio.common.VersioningOverride | None = None - - -@dataclass -class StartWorkflowUpdateWithStartInput: - """Input for :py:meth:`OutboundInterceptor.start_update_with_start_workflow`.""" - - start_workflow_input: UpdateWithStartStartWorkflowInput - update_workflow_input: UpdateWithStartUpdateWorkflowInput - _on_start: Callable[ - [temporalio.api.workflowservice.v1.StartWorkflowExecutionResponse], None - ] - _on_start_error: Callable[[BaseException], None] - - -@dataclass -class HeartbeatAsyncActivityInput: - """Input for :py:meth:`OutboundInterceptor.heartbeat_async_activity`.""" - - id_or_token: AsyncActivityIDReference | bytes - details: Sequence[Any] - rpc_metadata: Mapping[str, str | bytes] - rpc_timeout: timedelta | None - data_converter_override: DataConverter | None = None - - -@dataclass -class CompleteAsyncActivityInput: - """Input for :py:meth:`OutboundInterceptor.complete_async_activity`.""" - - id_or_token: AsyncActivityIDReference | bytes - result: Any | None - rpc_metadata: Mapping[str, str | bytes] - rpc_timeout: timedelta | None - data_converter_override: DataConverter | None = None - - -@dataclass -class FailAsyncActivityInput: - """Input for :py:meth:`OutboundInterceptor.fail_async_activity`.""" - - id_or_token: AsyncActivityIDReference | bytes - error: Exception - last_heartbeat_details: Sequence[Any] - rpc_metadata: Mapping[str, str | bytes] - rpc_timeout: timedelta | None - data_converter_override: DataConverter | None = None - - -@dataclass -class ReportCancellationAsyncActivityInput: - """Input for :py:meth:`OutboundInterceptor.report_cancellation_async_activity`.""" - - id_or_token: AsyncActivityIDReference | bytes - details: Sequence[Any] - rpc_metadata: Mapping[str, str | bytes] - rpc_timeout: timedelta | None - data_converter_override: DataConverter | None = None - - -@dataclass -class CreateScheduleInput: - """Input for :py:meth:`OutboundInterceptor.create_schedule`.""" - - id: str - schedule: Schedule - trigger_immediately: bool - backfill: Sequence[ScheduleBackfill] - memo: Mapping[str, Any] | None - search_attributes: None | ( - temporalio.common.SearchAttributes | temporalio.common.TypedSearchAttributes - ) - rpc_metadata: Mapping[str, str | bytes] - rpc_timeout: timedelta | None - - -@dataclass -class ListSchedulesInput: - """Input for :py:meth:`OutboundInterceptor.list_schedules`.""" - - page_size: int - next_page_token: bytes | None - rpc_metadata: Mapping[str, str | bytes] - rpc_timeout: timedelta | None - query: str | None = None - - -@dataclass -class BackfillScheduleInput: - """Input for :py:meth:`OutboundInterceptor.backfill_schedule`.""" - - id: str - backfills: Sequence[ScheduleBackfill] - rpc_metadata: Mapping[str, str | bytes] - rpc_timeout: timedelta | None - - -@dataclass -class DeleteScheduleInput: - """Input for :py:meth:`OutboundInterceptor.delete_schedule`.""" - - id: str - rpc_metadata: Mapping[str, str | bytes] - rpc_timeout: timedelta | None - - -@dataclass -class DescribeScheduleInput: - """Input for :py:meth:`OutboundInterceptor.describe_schedule`.""" - - id: str - rpc_metadata: Mapping[str, str | bytes] - rpc_timeout: timedelta | None - - -@dataclass -class PauseScheduleInput: - """Input for :py:meth:`OutboundInterceptor.pause_schedule`.""" - - id: str - note: str | None - rpc_metadata: Mapping[str, str | bytes] - rpc_timeout: timedelta | None - - -@dataclass -class TriggerScheduleInput: - """Input for :py:meth:`OutboundInterceptor.trigger_schedule`.""" - - id: str - overlap: ScheduleOverlapPolicy | None - rpc_metadata: Mapping[str, str | bytes] - rpc_timeout: timedelta | None - - -@dataclass -class UnpauseScheduleInput: - """Input for :py:meth:`OutboundInterceptor.unpause_schedule`.""" - - id: str - note: str | None - rpc_metadata: Mapping[str, str | bytes] - rpc_timeout: timedelta | None - - -@dataclass -class UpdateScheduleInput: - """Input for :py:meth:`OutboundInterceptor.update_schedule`.""" - - id: str - updater: Callable[ - [ScheduleUpdateInput], - ScheduleUpdate | None | Awaitable[ScheduleUpdate | None], - ] - rpc_metadata: Mapping[str, str | bytes] - rpc_timeout: timedelta | None - - -@dataclass -class UpdateWorkerBuildIdCompatibilityInput: - """Input for :py:meth:`OutboundInterceptor.update_worker_build_id_compatibility`.""" - - task_queue: str - operation: BuildIdOp - rpc_metadata: Mapping[str, str | bytes] - rpc_timeout: timedelta | None - - -@dataclass -class GetWorkerBuildIdCompatibilityInput: - """Input for :py:meth:`OutboundInterceptor.get_worker_build_id_compatibility`.""" - - task_queue: str - max_sets: int | None - rpc_metadata: Mapping[str, str | bytes] - rpc_timeout: timedelta | None - - -@dataclass -class GetWorkerTaskReachabilityInput: - """Input for :py:meth:`OutboundInterceptor.get_worker_task_reachability`.""" - - build_ids: Sequence[str] - task_queues: Sequence[str] - reachability: TaskReachabilityType | None - rpc_metadata: Mapping[str, str | bytes] - rpc_timeout: timedelta | None - - -@dataclass -class Interceptor: - """Interceptor for clients. - - This should be extended by any client interceptors. - """ - - def intercept_client(self, next: OutboundInterceptor) -> OutboundInterceptor: - """Method called for intercepting a client. - - Args: - next: The underlying outbound interceptor this interceptor should - delegate to. - - Returns: - The new interceptor that will be called for each client call. - """ - return next - - -class OutboundInterceptor: - """OutboundInterceptor for intercepting client calls. - - This should be extended by any client outbound interceptors. - """ - - def __init__(self, next: OutboundInterceptor) -> None: - """Create the outbound interceptor. - - Args: - next: The next interceptor in the chain. The default implementation - of all calls is to delegate to the next interceptor. - """ - self.next = next - - ### Workflow calls - - async def start_workflow( - self, input: StartWorkflowInput - ) -> WorkflowHandle[Any, Any]: - """Called for every :py:meth:`Client.start_workflow` call.""" - return await self.next.start_workflow(input) - - async def cancel_workflow(self, input: CancelWorkflowInput) -> None: - """Called for every :py:meth:`WorkflowHandle.cancel` call.""" - await self.next.cancel_workflow(input) - - async def describe_workflow( - self, input: DescribeWorkflowInput - ) -> WorkflowExecutionDescription: - """Called for every :py:meth:`WorkflowHandle.describe` call.""" - return await self.next.describe_workflow(input) - - def fetch_workflow_history_events( - self, input: FetchWorkflowHistoryEventsInput - ) -> WorkflowHistoryEventAsyncIterator: - """Called for every :py:meth:`WorkflowHandle.fetch_history_events` call.""" - return self.next.fetch_workflow_history_events(input) - - def list_workflows( - self, input: ListWorkflowsInput - ) -> WorkflowExecutionAsyncIterator: - """Called for every :py:meth:`Client.list_workflows` call.""" - return self.next.list_workflows(input) - - async def count_workflows( - self, input: CountWorkflowsInput - ) -> WorkflowExecutionCount: - """Called for every :py:meth:`Client.count_workflows` call.""" - return await self.next.count_workflows(input) - - async def query_workflow(self, input: QueryWorkflowInput) -> Any: - """Called for every :py:meth:`WorkflowHandle.query` call.""" - return await self.next.query_workflow(input) - - async def signal_workflow(self, input: SignalWorkflowInput) -> None: - """Called for every :py:meth:`WorkflowHandle.signal` call.""" - await self.next.signal_workflow(input) - - async def terminate_workflow(self, input: TerminateWorkflowInput) -> None: - """Called for every :py:meth:`WorkflowHandle.terminate` call.""" - await self.next.terminate_workflow(input) - - ### Activity calls - - async def start_activity(self, input: StartActivityInput) -> ActivityHandle[Any]: - """Called for every :py:meth:`Client.start_activity` call. - - .. warning:: - This API is experimental. - """ - return await self.next.start_activity(input) - - async def cancel_activity(self, input: CancelActivityInput) -> None: - """Called for every :py:meth:`ActivityHandle.cancel` call. - - .. warning:: - This API is experimental. - """ - await self.next.cancel_activity(input) - - async def terminate_activity(self, input: TerminateActivityInput) -> None: - """Called for every :py:meth:`ActivityHandle.terminate` call. - - .. warning:: - This API is experimental. - """ - await self.next.terminate_activity(input) - - async def describe_activity( - self, input: DescribeActivityInput - ) -> ActivityExecutionDescription: - """Called for every :py:meth:`ActivityHandle.describe` call. - - .. warning:: - This API is experimental. - """ - return await self.next.describe_activity(input) - - def list_activities( - self, input: ListActivitiesInput - ) -> ActivityExecutionAsyncIterator: - """Called for every :py:meth:`Client.list_activities` call. - - .. warning:: - This API is experimental. - """ - return self.next.list_activities(input) - - async def count_activities( - self, input: CountActivitiesInput - ) -> ActivityExecutionCount: - """Called for every :py:meth:`Client.count_activities` call. - - .. warning:: - This API is experimental. - """ - return await self.next.count_activities(input) - - async def start_workflow_update( - self, input: StartWorkflowUpdateInput - ) -> WorkflowUpdateHandle[Any]: - """Called for every :py:meth:`WorkflowHandle.start_update` and :py:meth:`WorkflowHandle.execute_update` call.""" - return await self.next.start_workflow_update(input) - - async def start_update_with_start_workflow( - self, input: StartWorkflowUpdateWithStartInput - ) -> WorkflowUpdateHandle[Any]: - """Called for every :py:meth:`Client.start_update_with_start_workflow` and :py:meth:`Client.execute_update_with_start_workflow` call.""" - return await self.next.start_update_with_start_workflow(input) - - ### Async activity calls - - async def heartbeat_async_activity( - self, input: HeartbeatAsyncActivityInput - ) -> None: - """Called for every :py:meth:`AsyncActivityHandle.heartbeat` call.""" - await self.next.heartbeat_async_activity(input) - - async def complete_async_activity(self, input: CompleteAsyncActivityInput) -> None: - """Called for every :py:meth:`AsyncActivityHandle.complete` call.""" - await self.next.complete_async_activity(input) - - async def fail_async_activity(self, input: FailAsyncActivityInput) -> None: - """Called for every :py:meth:`AsyncActivityHandle.fail` call.""" - await self.next.fail_async_activity(input) - - async def report_cancellation_async_activity( - self, input: ReportCancellationAsyncActivityInput - ) -> None: - """Called for every :py:meth:`AsyncActivityHandle.report_cancellation` call.""" - await self.next.report_cancellation_async_activity(input) - - ### Schedule calls - - async def create_schedule(self, input: CreateScheduleInput) -> ScheduleHandle: - """Called for every :py:meth:`Client.create_schedule` call.""" - return await self.next.create_schedule(input) - - def list_schedules(self, input: ListSchedulesInput) -> ScheduleAsyncIterator: - """Called for every :py:meth:`Client.list_schedules` call.""" - return self.next.list_schedules(input) - - async def backfill_schedule(self, input: BackfillScheduleInput) -> None: - """Called for every :py:meth:`ScheduleHandle.backfill` call.""" - await self.next.backfill_schedule(input) - - async def delete_schedule(self, input: DeleteScheduleInput) -> None: - """Called for every :py:meth:`ScheduleHandle.delete` call.""" - await self.next.delete_schedule(input) - - async def describe_schedule( - self, input: DescribeScheduleInput - ) -> ScheduleDescription: - """Called for every :py:meth:`ScheduleHandle.describe` call.""" - return await self.next.describe_schedule(input) - - async def pause_schedule(self, input: PauseScheduleInput) -> None: - """Called for every :py:meth:`ScheduleHandle.pause` call.""" - await self.next.pause_schedule(input) - - async def trigger_schedule(self, input: TriggerScheduleInput) -> None: - """Called for every :py:meth:`ScheduleHandle.trigger` call.""" - await self.next.trigger_schedule(input) - - async def unpause_schedule(self, input: UnpauseScheduleInput) -> None: - """Called for every :py:meth:`ScheduleHandle.unpause` call.""" - await self.next.unpause_schedule(input) - - async def update_schedule(self, input: UpdateScheduleInput) -> None: - """Called for every :py:meth:`ScheduleHandle.update` call.""" - await self.next.update_schedule(input) - - async def update_worker_build_id_compatibility( - self, input: UpdateWorkerBuildIdCompatibilityInput - ) -> None: - """Called for every :py:meth:`Client.update_worker_build_id_compatibility` call.""" - await self.next.update_worker_build_id_compatibility(input) - - async def get_worker_build_id_compatibility( - self, input: GetWorkerBuildIdCompatibilityInput - ) -> WorkerBuildIdVersionSets: - """Called for every :py:meth:`Client.get_worker_build_id_compatibility` call.""" - return await self.next.get_worker_build_id_compatibility(input) - - async def get_worker_task_reachability( - self, input: GetWorkerTaskReachabilityInput - ) -> WorkerTaskReachability: - """Called for every :py:meth:`Client.get_worker_task_reachability` call.""" - return await self.next.get_worker_task_reachability(input) - - -class _ClientImpl(OutboundInterceptor): - def __init__(self, client: Client) -> None: # type: ignore - # We are intentionally not calling the base class's __init__ here - self._client = client - - ### Workflow calls - - async def start_workflow( - self, input: StartWorkflowInput - ) -> WorkflowHandle[Any, Any]: - req: ( - temporalio.api.workflowservice.v1.StartWorkflowExecutionRequest - | temporalio.api.workflowservice.v1.SignalWithStartWorkflowExecutionRequest - ) - if input.start_signal is not None: - req = await self._build_signal_with_start_workflow_execution_request(input) - else: - req = await self._build_start_workflow_execution_request(input) - - resp: ( - temporalio.api.workflowservice.v1.StartWorkflowExecutionResponse - | temporalio.api.workflowservice.v1.SignalWithStartWorkflowExecutionResponse - ) - first_execution_run_id = None - eagerly_started = False - try: - if isinstance( - req, - temporalio.api.workflowservice.v1.SignalWithStartWorkflowExecutionRequest, - ): - resp = await self._client.workflow_service.signal_with_start_workflow_execution( - req, - retry=True, - metadata=input.rpc_metadata, - timeout=input.rpc_timeout, - ) - else: - resp = await self._client.workflow_service.start_workflow_execution( - req, - retry=True, - metadata=input.rpc_metadata, - timeout=input.rpc_timeout, - ) - first_execution_run_id = resp.run_id - eagerly_started = resp.HasField("eager_workflow_task") - except RPCError as err: - # If the status is ALREADY_EXISTS and the details can be extracted - # as already started, use a different exception - if err.status == RPCStatusCode.ALREADY_EXISTS and err.grpc_status.details: - details = temporalio.api.errordetails.v1.WorkflowExecutionAlreadyStartedFailure() - if err.grpc_status.details[0].Unpack(details): - raise temporalio.exceptions.WorkflowAlreadyStartedError( - input.id, input.workflow, run_id=details.run_id - ) - raise - handle: WorkflowHandle[Any, Any] = WorkflowHandle( - self._client, - req.workflow_id, - result_run_id=resp.run_id, - first_execution_run_id=first_execution_run_id, - result_type=input.ret_type, - start_workflow_response=resp, - ) - setattr(handle, "__temporal_eagerly_started", eagerly_started) - return handle - - async def _build_start_workflow_execution_request( - self, input: StartWorkflowInput - ) -> temporalio.api.workflowservice.v1.StartWorkflowExecutionRequest: - req = temporalio.api.workflowservice.v1.StartWorkflowExecutionRequest() - await self._populate_start_workflow_execution_request(req, input) - # _populate_start_workflow_execution_request is used for both StartWorkflowInput - # and UpdateWithStartStartWorkflowInput. UpdateWithStartStartWorkflowInput does - # not have the following two fields so they are handled here. - req.request_eager_execution = input.request_eager_start - if input.request_id: - req.request_id = input.request_id - - links = [ - temporalio.api.common.v1.Link(workflow_event=link) - for link in input.workflow_event_links - ] - req.completion_callbacks.extend( - temporalio.api.common.v1.Callback( - nexus=temporalio.api.common.v1.Callback.Nexus( - url=callback.url, - header=callback.headers, - ), - links=links, - ) - for callback in input.callbacks - ) - # Links are duplicated on request for compatibility with older server versions. - req.links.extend(links) - - if temporalio.nexus._operation_context._in_nexus_backing_workflow_start_context(): - req.on_conflict_options.attach_request_id = True - req.on_conflict_options.attach_completion_callbacks = True - req.on_conflict_options.attach_links = True - - return req - - async def _build_signal_with_start_workflow_execution_request( - self, input: StartWorkflowInput - ) -> temporalio.api.workflowservice.v1.SignalWithStartWorkflowExecutionRequest: - assert input.start_signal - data_converter = self._client.data_converter._with_contexts( - WorkflowSerializationContext( - namespace=self._client.namespace, - workflow_id=input.id, - ), - StorageDriverStoreContext( - target=StorageDriverWorkflowInfo( - id=input.id, type=input.workflow, namespace=self._client.namespace - ), - ), - ) - req = temporalio.api.workflowservice.v1.SignalWithStartWorkflowExecutionRequest( - signal_name=input.start_signal - ) - if input.start_signal_args: - req.signal_input.payloads.extend( - await data_converter.encode(input.start_signal_args) - ) - await self._populate_start_workflow_execution_request(req, input) - return req - - async def _build_update_with_start_start_workflow_execution_request( - self, input: UpdateWithStartStartWorkflowInput - ) -> temporalio.api.workflowservice.v1.StartWorkflowExecutionRequest: - req = temporalio.api.workflowservice.v1.StartWorkflowExecutionRequest() - await self._populate_start_workflow_execution_request(req, input) - return req - - async def _populate_start_workflow_execution_request( - self, - req: ( - temporalio.api.workflowservice.v1.StartWorkflowExecutionRequest - | temporalio.api.workflowservice.v1.SignalWithStartWorkflowExecutionRequest - ), - input: StartWorkflowInput | UpdateWithStartStartWorkflowInput, - ) -> None: - data_converter = self._client.data_converter._with_contexts( - WorkflowSerializationContext( - namespace=self._client.namespace, - workflow_id=input.id, - ), - StorageDriverStoreContext( - target=StorageDriverWorkflowInfo( - id=input.id, type=input.workflow, namespace=self._client.namespace - ), - ), - ) - req.namespace = self._client.namespace - req.workflow_id = input.id - req.workflow_type.name = input.workflow - req.task_queue.name = input.task_queue - if input.args: - req.input.payloads.extend(await data_converter.encode(input.args)) - if input.execution_timeout is not None: - req.workflow_execution_timeout.FromTimedelta(input.execution_timeout) - if input.run_timeout is not None: - req.workflow_run_timeout.FromTimedelta(input.run_timeout) - if input.task_timeout is not None: - req.workflow_task_timeout.FromTimedelta(input.task_timeout) - req.identity = self._client.identity - req.request_id = str(uuid.uuid4()) - req.workflow_id_reuse_policy = cast( - "temporalio.api.enums.v1.WorkflowIdReusePolicy.ValueType", - int(input.id_reuse_policy), - ) - req.workflow_id_conflict_policy = cast( - "temporalio.api.enums.v1.WorkflowIdConflictPolicy.ValueType", - int(input.id_conflict_policy), - ) - - if input.retry_policy is not None: - input.retry_policy.apply_to_proto(req.retry_policy) - req.cron_schedule = input.cron_schedule - if input.memo is not None: - await data_converter._encode_memo_existing(input.memo, req.memo) - if input.search_attributes is not None: - temporalio.converter.encode_search_attributes( - input.search_attributes, req.search_attributes - ) - metadata = await _encode_user_metadata( - data_converter, input.static_summary, input.static_details - ) - if metadata is not None: - req.user_metadata.CopyFrom(metadata) - if input.start_delay is not None: - req.workflow_start_delay.FromTimedelta(input.start_delay) - if input.headers is not None: # type:ignore[reportUnnecessaryComparison] - await self._apply_headers(input.headers, req.header.fields) - if input.priority is not None: # type:ignore[reportUnnecessaryComparison] - req.priority.CopyFrom(input.priority._to_proto()) - if input.versioning_override is not None: - req.versioning_override.CopyFrom(input.versioning_override._to_proto()) - - async def cancel_workflow(self, input: CancelWorkflowInput) -> None: - await self._client.workflow_service.request_cancel_workflow_execution( - temporalio.api.workflowservice.v1.RequestCancelWorkflowExecutionRequest( - namespace=self._client.namespace, - workflow_execution=temporalio.api.common.v1.WorkflowExecution( - workflow_id=input.id, - run_id=input.run_id or "", - ), - identity=self._client.identity, - request_id=str(uuid.uuid4()), - first_execution_run_id=input.first_execution_run_id or "", - ), - retry=True, - metadata=input.rpc_metadata, - timeout=input.rpc_timeout, - ) - - async def describe_workflow( - self, input: DescribeWorkflowInput - ) -> WorkflowExecutionDescription: - return await WorkflowExecutionDescription._from_raw_description( - await self._client.workflow_service.describe_workflow_execution( - temporalio.api.workflowservice.v1.DescribeWorkflowExecutionRequest( - namespace=self._client.namespace, - execution=temporalio.api.common.v1.WorkflowExecution( - workflow_id=input.id, - run_id=input.run_id or "", - ), - ), - retry=True, - metadata=input.rpc_metadata, - timeout=input.rpc_timeout, - ), - namespace=self._client.namespace, - converter=self._client.data_converter.with_context( - WorkflowSerializationContext( - namespace=self._client.namespace, - workflow_id=input.id, - ) - ), - ) - - def fetch_workflow_history_events( - self, input: FetchWorkflowHistoryEventsInput - ) -> WorkflowHistoryEventAsyncIterator: - return WorkflowHistoryEventAsyncIterator(self._client, input) - - def list_workflows( - self, input: ListWorkflowsInput - ) -> WorkflowExecutionAsyncIterator: - return WorkflowExecutionAsyncIterator(self._client, input) - - async def count_workflows( - self, input: CountWorkflowsInput - ) -> WorkflowExecutionCount: - return WorkflowExecutionCount._from_raw( - await self._client.workflow_service.count_workflow_executions( - temporalio.api.workflowservice.v1.CountWorkflowExecutionsRequest( - namespace=self._client.namespace, - query=input.query or "", - ), - retry=True, - metadata=input.rpc_metadata, - timeout=input.rpc_timeout, - ) - ) - - async def query_workflow(self, input: QueryWorkflowInput) -> Any: - data_converter = self._client.data_converter._with_contexts( - WorkflowSerializationContext( - namespace=self._client.namespace, - workflow_id=input.id, - ), - StorageDriverStoreContext( - target=StorageDriverWorkflowInfo( - id=input.id, - run_id=input.run_id or None, - namespace=self._client.namespace, - ), - ), - ) - req = temporalio.api.workflowservice.v1.QueryWorkflowRequest( - namespace=self._client.namespace, - execution=temporalio.api.common.v1.WorkflowExecution( - workflow_id=input.id, - run_id=input.run_id or "", - ), - ) - if input.reject_condition: - req.query_reject_condition = cast( - "temporalio.api.enums.v1.QueryRejectCondition.ValueType", - int(input.reject_condition), - ) - req.query.query_type = input.query - if input.args: - req.query.query_args.payloads.extend( - await data_converter.encode(input.args) - ) - if input.headers is not None: # type:ignore[reportUnnecessaryComparison] - await self._apply_headers(input.headers, req.query.header.fields) - try: - resp = await self._client.workflow_service.query_workflow( - req, - retry=True, - metadata=input.rpc_metadata, - timeout=input.rpc_timeout, - ) - except RPCError as err: - # If the status is INVALID_ARGUMENT, we can assume it's a query - # failed error - if err.status == RPCStatusCode.INVALID_ARGUMENT: - raise WorkflowQueryFailedError(err.message) - else: - raise - if resp.HasField("query_rejected"): - raise WorkflowQueryRejectedError( - WorkflowExecutionStatus(resp.query_rejected.status) - if resp.query_rejected.status - else None - ) - if not resp.query_result.payloads: - return None - type_hints = [input.ret_type] if input.ret_type else None - results = await data_converter.decode(resp.query_result.payloads, type_hints) - if not results: - return None - elif len(results) > 1: - warnings.warn(f"Expected single query result, got {len(results)}") - return results[0] - - async def signal_workflow(self, input: SignalWorkflowInput) -> None: - data_converter = self._client.data_converter._with_contexts( - WorkflowSerializationContext( - namespace=self._client.namespace, - workflow_id=input.id, - ), - StorageDriverStoreContext( - target=StorageDriverWorkflowInfo( - id=input.id, - run_id=input.run_id or None, - namespace=self._client.namespace, - ), - ), - ) - req = temporalio.api.workflowservice.v1.SignalWorkflowExecutionRequest( - namespace=self._client.namespace, - workflow_execution=temporalio.api.common.v1.WorkflowExecution( - workflow_id=input.id, - run_id=input.run_id or "", - ), - signal_name=input.signal, - identity=self._client.identity, - request_id=str(uuid.uuid4()), - ) - if input.args: - req.input.payloads.extend(await data_converter.encode(input.args)) - if input.headers is not None: # type:ignore[reportUnnecessaryComparison] - await self._apply_headers(input.headers, req.header.fields) - await self._client.workflow_service.signal_workflow_execution( - req, retry=True, metadata=input.rpc_metadata, timeout=input.rpc_timeout - ) - - async def terminate_workflow(self, input: TerminateWorkflowInput) -> None: - data_converter = self._client.data_converter._with_contexts( - WorkflowSerializationContext( - namespace=self._client.namespace, - workflow_id=input.id, - ), - StorageDriverStoreContext( - target=StorageDriverWorkflowInfo( - id=input.id, - run_id=input.run_id or None, - namespace=self._client.namespace, - ), - ), - ) - req = temporalio.api.workflowservice.v1.TerminateWorkflowExecutionRequest( - namespace=self._client.namespace, - workflow_execution=temporalio.api.common.v1.WorkflowExecution( - workflow_id=input.id, - run_id=input.run_id or "", - ), - reason=input.reason or "", - identity=self._client.identity, - first_execution_run_id=input.first_execution_run_id or "", - ) - if input.args: - req.details.payloads.extend(await data_converter.encode(input.args)) - await self._client.workflow_service.terminate_workflow_execution( - req, retry=True, metadata=input.rpc_metadata, timeout=input.rpc_timeout - ) - - async def start_activity(self, input: StartActivityInput) -> ActivityHandle[Any]: - """Start an activity and return a handle to it.""" - if not (input.start_to_close_timeout or input.schedule_to_close_timeout): - raise ValueError( - "Activity must have start_to_close_timeout or schedule_to_close_timeout" - ) - if input.start_delay is not None and input.start_delay < timedelta(0): - raise ValueError("start_delay must be non-negative") - req = await self._build_start_activity_execution_request(input) - - resp: temporalio.api.workflowservice.v1.StartActivityExecutionResponse - try: - resp = await self._client.workflow_service.start_activity_execution( - req, - retry=True, - metadata=input.rpc_metadata, - timeout=input.rpc_timeout, - ) - except RPCError as err: - # If the status is ALREADY_EXISTS and the details can be extracted - # as already started, use a different exception - if err.status == RPCStatusCode.ALREADY_EXISTS and err.grpc_status.details: - details = temporalio.api.errordetails.v1.ActivityExecutionAlreadyStartedFailure() - if err.grpc_status.details[0].Unpack(details): - raise temporalio.exceptions.ActivityAlreadyStartedError( - input.id, input.activity_type, run_id=details.run_id - ) - raise - return ActivityHandle( - self._client, - input.id, - run_id=resp.run_id, - result_type=input.result_type, - ) - - async def _build_start_activity_execution_request( - self, input: StartActivityInput - ) -> temporalio.api.workflowservice.v1.StartActivityExecutionRequest: - """Build StartActivityExecutionRequest from input.""" - data_converter = self._client.data_converter._with_contexts( - ActivitySerializationContext( - namespace=self._client.namespace, - activity_id=input.id, - activity_type=input.activity_type, - activity_task_queue=input.task_queue, - is_local=False, - workflow_id=None, - workflow_type=None, - ), - StorageDriverStoreContext( - target=StorageDriverActivityInfo( - id=input.id, - type=input.activity_type, - namespace=self._client.namespace, - ), - ), - ) - - req = temporalio.api.workflowservice.v1.StartActivityExecutionRequest( - namespace=self._client.namespace, - identity=self._client.identity, - activity_id=input.id, - activity_type=temporalio.api.common.v1.ActivityType( - name=input.activity_type - ), - task_queue=temporalio.api.taskqueue.v1.TaskQueue(name=input.task_queue), - id_reuse_policy=cast( - "temporalio.api.enums.v1.ActivityIdReusePolicy.ValueType", - int(input.id_reuse_policy), - ), - id_conflict_policy=cast( - "temporalio.api.enums.v1.ActivityIdConflictPolicy.ValueType", - int(input.id_conflict_policy), - ), - ) - - if input.schedule_to_close_timeout is not None: - req.schedule_to_close_timeout.FromTimedelta(input.schedule_to_close_timeout) - if input.start_to_close_timeout is not None: - req.start_to_close_timeout.FromTimedelta(input.start_to_close_timeout) - if input.schedule_to_start_timeout is not None: - req.schedule_to_start_timeout.FromTimedelta(input.schedule_to_start_timeout) - if input.heartbeat_timeout is not None: - req.heartbeat_timeout.FromTimedelta(input.heartbeat_timeout) - if input.start_delay is not None: - req.start_delay.FromTimedelta(input.start_delay) - if input.retry_policy is not None: - input.retry_policy.apply_to_proto(req.retry_policy) - - # Set input payloads - if input.args: - req.input.payloads.extend(await data_converter.encode(input.args)) - - # Set search attributes - if input.search_attributes is not None: - temporalio.converter.encode_search_attributes( - input.search_attributes, req.search_attributes - ) - - # Set user metadata - metadata = await _encode_user_metadata(data_converter, input.summary, None) - if metadata is not None: - req.user_metadata.CopyFrom(metadata) - - # Set headers - if input.headers: - await self._apply_headers(input.headers, req.header.fields) - - # Set priority - req.priority.CopyFrom(input.priority._to_proto()) - - return req - - async def cancel_activity(self, input: CancelActivityInput) -> None: - """Cancel an activity.""" - await self._client.workflow_service.request_cancel_activity_execution( - temporalio.api.workflowservice.v1.RequestCancelActivityExecutionRequest( - namespace=self._client.namespace, - activity_id=input.activity_id, - run_id=input.activity_run_id or "", - identity=self._client.identity, - request_id=str(uuid.uuid4()), - reason=input.reason or "", - ), - retry=True, - metadata=input.rpc_metadata, - timeout=input.rpc_timeout, - ) - - async def terminate_activity(self, input: TerminateActivityInput) -> None: - """Terminate an activity.""" - await self._client.workflow_service.terminate_activity_execution( - temporalio.api.workflowservice.v1.TerminateActivityExecutionRequest( - namespace=self._client.namespace, - activity_id=input.activity_id, - run_id=input.activity_run_id or "", - reason=input.reason or "", - identity=self._client.identity, - ), - retry=True, - metadata=input.rpc_metadata, - timeout=input.rpc_timeout, - ) - - async def describe_activity( - self, input: DescribeActivityInput - ) -> ActivityExecutionDescription: - """Describe an activity.""" - resp = await self._client.workflow_service.describe_activity_execution( - temporalio.api.workflowservice.v1.DescribeActivityExecutionRequest( - namespace=self._client.namespace, - activity_id=input.activity_id, - run_id=input.activity_run_id or "", - long_poll_token=input.long_poll_token or b"", - ), - retry=True, - metadata=input.rpc_metadata, - timeout=input.rpc_timeout, - ) - return await ActivityExecutionDescription._from_execution_info( - info=resp.info, - long_poll_token=resp.long_poll_token or None, - namespace=self._client.namespace, - data_converter=self._client.data_converter.with_context( - WorkflowSerializationContext( - namespace=self._client.namespace, - workflow_id=input.activity_id, # Using activity_id as workflow_id for activities not started by a workflow - ) - ), - ) - - def list_activities( - self, input: ListActivitiesInput - ) -> ActivityExecutionAsyncIterator: - return ActivityExecutionAsyncIterator(self._client, input) - - async def count_activities( - self, input: CountActivitiesInput - ) -> ActivityExecutionCount: - return ActivityExecutionCount._from_raw( - await self._client.workflow_service.count_activity_executions( - temporalio.api.workflowservice.v1.CountActivityExecutionsRequest( - namespace=self._client.namespace, - query=input.query or "", - ), - retry=True, - metadata=input.rpc_metadata, - timeout=input.rpc_timeout, - ) - ) - - async def start_workflow_update( - self, input: StartWorkflowUpdateInput - ) -> WorkflowUpdateHandle[Any]: - workflow_id = input.id - req = await self._build_update_workflow_execution_request(input, workflow_id) - - # Repeatedly try to invoke UpdateWorkflowExecution until the update is durable. - resp: temporalio.api.workflowservice.v1.UpdateWorkflowExecutionResponse - while True: - try: - resp = await self._client.workflow_service.update_workflow_execution( - req, - retry=True, - metadata=input.rpc_metadata, - timeout=input.rpc_timeout, - ) - except RPCError as err: - if ( - err.status == RPCStatusCode.DEADLINE_EXCEEDED - or err.status == RPCStatusCode.CANCELLED - ): - raise WorkflowUpdateRPCTimeoutOrCancelledError() from err - else: - raise - except asyncio.CancelledError as err: - raise WorkflowUpdateRPCTimeoutOrCancelledError() from err - if ( - resp.stage - >= temporalio.api.enums.v1.UpdateWorkflowExecutionLifecycleStage.UPDATE_WORKFLOW_EXECUTION_LIFECYCLE_STAGE_ACCEPTED - ): - break - - # Build the handle. If the user's wait stage is COMPLETED, make sure we - # poll for result. - handle: WorkflowUpdateHandle[Any] = WorkflowUpdateHandle( - client=self._client, - id=req.request.meta.update_id, - workflow_id=workflow_id, - workflow_run_id=resp.update_ref.workflow_execution.run_id, - result_type=input.ret_type, - ) - if resp.HasField("outcome"): - handle._known_outcome = resp.outcome - if input.wait_for_stage == WorkflowUpdateStage.COMPLETED: - await handle._poll_until_outcome() - return handle - - async def _build_update_workflow_execution_request( - self, - input: StartWorkflowUpdateInput | UpdateWithStartUpdateWorkflowInput, - workflow_id: str, - ) -> temporalio.api.workflowservice.v1.UpdateWorkflowExecutionRequest: - data_converter = self._client.data_converter._with_contexts( - WorkflowSerializationContext( - namespace=self._client.namespace, - workflow_id=workflow_id, - ), - StorageDriverStoreContext( - target=StorageDriverWorkflowInfo( - id=workflow_id, - run_id=(input.run_id or None) - if isinstance(input, StartWorkflowUpdateInput) - else None, - namespace=self._client.namespace, - ), - ), - ) - run_id, first_execution_run_id = ( - ( - input.run_id, - input.first_execution_run_id, - ) - if isinstance(input, StartWorkflowUpdateInput) - else (None, None) - ) - req = temporalio.api.workflowservice.v1.UpdateWorkflowExecutionRequest( - namespace=self._client.namespace, - workflow_execution=temporalio.api.common.v1.WorkflowExecution( - workflow_id=workflow_id, - run_id=run_id or "", - ), - first_execution_run_id=first_execution_run_id or "", - request=temporalio.api.update.v1.Request( - meta=temporalio.api.update.v1.Meta( - update_id=input.update_id or str(uuid.uuid4()), - identity=self._client.identity, - ), - input=temporalio.api.update.v1.Input( - name=input.update, - ), - ), - wait_policy=temporalio.api.update.v1.WaitPolicy( - lifecycle_stage=temporalio.api.enums.v1.UpdateWorkflowExecutionLifecycleStage.ValueType( - input.wait_for_stage - ) - ), - ) - if input.args: - req.request.input.args.payloads.extend( - await data_converter.encode(input.args) - ) - if input.headers is not None: # type:ignore[reportUnnecessaryComparison] - await self._apply_headers(input.headers, req.request.input.header.fields) - return req - - async def start_update_with_start_workflow( - self, input: StartWorkflowUpdateWithStartInput - ) -> WorkflowUpdateHandle[Any]: - seen_start = False - - def on_start( - start_response: temporalio.api.workflowservice.v1.StartWorkflowExecutionResponse, - ): - nonlocal seen_start - if not seen_start: - input._on_start(start_response) - seen_start = True - - err: BaseException | None = None - - try: - return await self._start_workflow_update_with_start( - input.start_workflow_input, input.update_workflow_input, on_start - ) - except asyncio.CancelledError as _err: - err = _err - raise WorkflowUpdateRPCTimeoutOrCancelledError() from err - except RPCError as _err: - err = _err - if err.status in [ - RPCStatusCode.DEADLINE_EXCEEDED, - RPCStatusCode.CANCELLED, - ]: - raise WorkflowUpdateRPCTimeoutOrCancelledError() from err - else: - multiop_failure = ( - temporalio.api.errordetails.v1.MultiOperationExecutionFailure() - ) - if err.grpc_status.details and err.grpc_status.details[0].Unpack( - multiop_failure - ): - status = next( - ( - st - for st in multiop_failure.statuses - if ( - st.code != RPCStatusCode.OK - and not ( - st.details - and st.details[0].Is( - temporalio.api.failure.v1.MultiOperationExecutionAborted.DESCRIPTOR - ) - ) - ) - ), - None, - ) - if status and status.code in list(RPCStatusCode): - if ( - status.code == RPCStatusCode.ALREADY_EXISTS - and status.details - ): - details = temporalio.api.errordetails.v1.WorkflowExecutionAlreadyStartedFailure() - if status.details[0].Unpack(details): - err = temporalio.exceptions.WorkflowAlreadyStartedError( - input.start_workflow_input.id, - input.start_workflow_input.workflow, - run_id=details.run_id, - ) - else: - err = RPCError( - status.message, - RPCStatusCode(status.code), - err.raw_grpc_status, - ) - raise err - finally: - if err and not seen_start: - input._on_start_error(err) - - async def _start_workflow_update_with_start( - self, - start_input: UpdateWithStartStartWorkflowInput, - update_input: UpdateWithStartUpdateWorkflowInput, - on_start: Callable[ - [temporalio.api.workflowservice.v1.StartWorkflowExecutionResponse], None - ], - ) -> WorkflowUpdateHandle[Any]: - start_req = ( - await self._build_update_with_start_start_workflow_execution_request( - start_input - ) - ) - update_req = await self._build_update_workflow_execution_request( - update_input, workflow_id=start_input.id - ) - multiop_req = temporalio.api.workflowservice.v1.ExecuteMultiOperationRequest( - namespace=self._client.namespace, - operations=[ - temporalio.api.workflowservice.v1.ExecuteMultiOperationRequest.Operation( - start_workflow=start_req - ), - temporalio.api.workflowservice.v1.ExecuteMultiOperationRequest.Operation( - update_workflow=update_req - ), - ], - ) - - # Repeatedly try to invoke ExecuteMultiOperation until the update is durable - while True: - multiop_response = ( - await self._client.workflow_service.execute_multi_operation(multiop_req) - ) - start_response = multiop_response.responses[0].start_workflow - update_response = multiop_response.responses[1].update_workflow - on_start(start_response) - known_outcome = ( - update_response.outcome if update_response.HasField("outcome") else None - ) - if ( - update_response.stage - >= temporalio.api.enums.v1.UpdateWorkflowExecutionLifecycleStage.UPDATE_WORKFLOW_EXECUTION_LIFECYCLE_STAGE_ACCEPTED - ): - break - - handle: WorkflowUpdateHandle[Any] = WorkflowUpdateHandle( - client=self._client, - id=update_req.request.meta.update_id, - workflow_id=start_input.id, - workflow_run_id=start_response.run_id, - known_outcome=known_outcome, - result_type=update_input.ret_type, - ) - if update_input.wait_for_stage == WorkflowUpdateStage.COMPLETED: - await handle._poll_until_outcome() - - return handle - - ### Async activity calls - - def _get_async_activity_store_context( - self, id_or_token: AsyncActivityIDReference | bytes - ) -> StorageDriverStoreContext: - if isinstance(id_or_token, AsyncActivityIDReference): - if id_or_token.workflow_id: - return StorageDriverStoreContext( - target=StorageDriverWorkflowInfo( - id=id_or_token.workflow_id or None, - run_id=id_or_token.run_id or None, - namespace=self._client.namespace, - ), - ) - return StorageDriverStoreContext( - target=StorageDriverActivityInfo( - id=id_or_token.activity_id, - run_id=id_or_token.run_id or None, - namespace=self._client.namespace, - ), - ) - else: - return StorageDriverStoreContext(target=None) - - async def heartbeat_async_activity( - self, input: HeartbeatAsyncActivityInput - ) -> None: - data_converter = ( - input.data_converter_override or self._client.data_converter - )._with_store_context(self._get_async_activity_store_context(input.id_or_token)) - details = ( - None - if not input.details - else await data_converter.encode_wrapper(input.details) - ) - if isinstance(input.id_or_token, AsyncActivityIDReference): - resp_by_id = await self._client.workflow_service.record_activity_task_heartbeat_by_id( - temporalio.api.workflowservice.v1.RecordActivityTaskHeartbeatByIdRequest( - workflow_id=input.id_or_token.workflow_id or "", - run_id=input.id_or_token.run_id or "", - activity_id=input.id_or_token.activity_id, - namespace=self._client.namespace, - identity=self._client.identity, - details=details, - ), - retry=True, - metadata=input.rpc_metadata, - timeout=input.rpc_timeout, - ) - if ( - resp_by_id.cancel_requested - or resp_by_id.activity_paused - or resp_by_id.activity_reset - ): - raise AsyncActivityCancelledError( - details=ActivityCancellationDetails( - cancel_requested=resp_by_id.cancel_requested, - paused=resp_by_id.activity_paused, - reset=resp_by_id.activity_reset, - ) - ) - - else: - resp = await self._client.workflow_service.record_activity_task_heartbeat( - temporalio.api.workflowservice.v1.RecordActivityTaskHeartbeatRequest( - task_token=input.id_or_token, - namespace=self._client.namespace, - identity=self._client.identity, - details=details, - ), - retry=True, - metadata=input.rpc_metadata, - timeout=input.rpc_timeout, - ) - if resp.cancel_requested or resp.activity_paused: - raise AsyncActivityCancelledError( - details=ActivityCancellationDetails( - cancel_requested=resp.cancel_requested, - paused=resp.activity_paused, - reset=resp.activity_reset, - ) - ) - - async def complete_async_activity(self, input: CompleteAsyncActivityInput) -> None: - data_converter = ( - input.data_converter_override or self._client.data_converter - )._with_store_context(self._get_async_activity_store_context(input.id_or_token)) - result = ( - None - if input.result is temporalio.common._arg_unset - else await data_converter.encode_wrapper([input.result]) - ) - if isinstance(input.id_or_token, AsyncActivityIDReference): - await self._client.workflow_service.respond_activity_task_completed_by_id( - temporalio.api.workflowservice.v1.RespondActivityTaskCompletedByIdRequest( - workflow_id=input.id_or_token.workflow_id or "", - run_id=input.id_or_token.run_id or "", - activity_id=input.id_or_token.activity_id, - namespace=self._client.namespace, - identity=self._client.identity, - result=result, - ), - retry=True, - metadata=input.rpc_metadata, - timeout=input.rpc_timeout, - ) - else: - await self._client.workflow_service.respond_activity_task_completed( - temporalio.api.workflowservice.v1.RespondActivityTaskCompletedRequest( - task_token=input.id_or_token, - namespace=self._client.namespace, - identity=self._client.identity, - result=result, - ), - retry=True, - metadata=input.rpc_metadata, - timeout=input.rpc_timeout, - ) - - async def fail_async_activity(self, input: FailAsyncActivityInput) -> None: - data_converter = ( - input.data_converter_override or self._client.data_converter - )._with_store_context(self._get_async_activity_store_context(input.id_or_token)) - - failure = temporalio.api.failure.v1.Failure() - await data_converter.encode_failure(input.error, failure) - last_heartbeat_details = ( - await data_converter.encode_wrapper(input.last_heartbeat_details) - if input.last_heartbeat_details - else None - ) - if isinstance(input.id_or_token, AsyncActivityIDReference): - await self._client.workflow_service.respond_activity_task_failed_by_id( - temporalio.api.workflowservice.v1.RespondActivityTaskFailedByIdRequest( - workflow_id=input.id_or_token.workflow_id or "", - run_id=input.id_or_token.run_id or "", - activity_id=input.id_or_token.activity_id, - namespace=self._client.namespace, - identity=self._client.identity, - failure=failure, - last_heartbeat_details=last_heartbeat_details, - ), - retry=True, - metadata=input.rpc_metadata, - timeout=input.rpc_timeout, - ) - else: - await self._client.workflow_service.respond_activity_task_failed( - temporalio.api.workflowservice.v1.RespondActivityTaskFailedRequest( - task_token=input.id_or_token, - namespace=self._client.namespace, - identity=self._client.identity, - failure=failure, - last_heartbeat_details=last_heartbeat_details, - ), - retry=True, - metadata=input.rpc_metadata, - timeout=input.rpc_timeout, - ) - - async def report_cancellation_async_activity( - self, input: ReportCancellationAsyncActivityInput - ) -> None: - data_converter = ( - input.data_converter_override or self._client.data_converter - )._with_store_context(self._get_async_activity_store_context(input.id_or_token)) - details = ( - None - if not input.details - else await data_converter.encode_wrapper(input.details) - ) - if isinstance(input.id_or_token, AsyncActivityIDReference): - await self._client.workflow_service.respond_activity_task_canceled_by_id( - temporalio.api.workflowservice.v1.RespondActivityTaskCanceledByIdRequest( - workflow_id=input.id_or_token.workflow_id or "", - run_id=input.id_or_token.run_id or "", - activity_id=input.id_or_token.activity_id, - namespace=self._client.namespace, - identity=self._client.identity, - details=details, - ), - retry=True, - metadata=input.rpc_metadata, - timeout=input.rpc_timeout, - ) - else: - await self._client.workflow_service.respond_activity_task_canceled( - temporalio.api.workflowservice.v1.RespondActivityTaskCanceledRequest( - task_token=input.id_or_token, - namespace=self._client.namespace, - identity=self._client.identity, - details=details, - ), - retry=True, - metadata=input.rpc_metadata, - timeout=input.rpc_timeout, - ) - - ### Schedule calls - - async def create_schedule(self, input: CreateScheduleInput) -> ScheduleHandle: - # Limited actions must be false if remaining actions is 0 and must be - # true if remaining actions is non-zero - if ( - input.schedule.state.limited_actions - and not input.schedule.state.remaining_actions - ): - raise ValueError( - "Must set limited actions to false if there are no remaining actions set" - ) - if ( - not input.schedule.state.limited_actions - and input.schedule.state.remaining_actions - ): - raise ValueError( - "Must set limited actions to true if there are remaining actions set" - ) - - initial_patch: temporalio.api.schedule.v1.SchedulePatch | None = None - if input.trigger_immediately or input.backfill: - initial_patch = temporalio.api.schedule.v1.SchedulePatch( - trigger_immediately=temporalio.api.schedule.v1.TriggerImmediatelyRequest( - overlap_policy=temporalio.api.enums.v1.ScheduleOverlapPolicy.ValueType( - input.schedule.policy.overlap - ), - ) - if input.trigger_immediately - else None, - backfill_request=[b._to_proto() for b in input.backfill] - if input.backfill - else None, - ) - try: - request = temporalio.api.workflowservice.v1.CreateScheduleRequest( - namespace=self._client.namespace, - schedule_id=input.id, - schedule=await input.schedule._to_proto(self._client), - initial_patch=initial_patch, - identity=self._client.identity, - request_id=str(uuid.uuid4()), - memo=await self._client.data_converter._encode_memo(input.memo) - if input.memo - else None, - ) - if input.search_attributes: - temporalio.converter.encode_search_attributes( - input.search_attributes, request.search_attributes - ) - await self._client.workflow_service.create_schedule( - request, - retry=True, - metadata=input.rpc_metadata, - timeout=input.rpc_timeout, - ) - except RPCError as err: - already_started = ( - err.status == RPCStatusCode.ALREADY_EXISTS - and err.grpc_status.details - and err.grpc_status.details[0].Is( - temporalio.api.errordetails.v1.WorkflowExecutionAlreadyStartedFailure.DESCRIPTOR - ) - ) - if already_started: - raise ScheduleAlreadyRunningError() - raise - return ScheduleHandle(self._client, input.id) - - def list_schedules(self, input: ListSchedulesInput) -> ScheduleAsyncIterator: - return ScheduleAsyncIterator(self._client, input) - - async def backfill_schedule(self, input: BackfillScheduleInput) -> None: - await self._client.workflow_service.patch_schedule( - temporalio.api.workflowservice.v1.PatchScheduleRequest( - namespace=self._client.namespace, - schedule_id=input.id, - patch=temporalio.api.schedule.v1.SchedulePatch( - backfill_request=[b._to_proto() for b in input.backfills], - ), - identity=self._client.identity, - request_id=str(uuid.uuid4()), - ), - retry=True, - metadata=input.rpc_metadata, - timeout=input.rpc_timeout, - ) - - async def delete_schedule(self, input: DeleteScheduleInput) -> None: - await self._client.workflow_service.delete_schedule( - temporalio.api.workflowservice.v1.DeleteScheduleRequest( - namespace=self._client.namespace, - schedule_id=input.id, - identity=self._client.identity, - ), - retry=True, - metadata=input.rpc_metadata, - timeout=input.rpc_timeout, - ) - - async def describe_schedule( - self, input: DescribeScheduleInput - ) -> ScheduleDescription: - return ScheduleDescription._from_proto( - input.id, - await self._client.workflow_service.describe_schedule( - temporalio.api.workflowservice.v1.DescribeScheduleRequest( - namespace=self._client.namespace, - schedule_id=input.id, - ), - retry=True, - metadata=input.rpc_metadata, - timeout=input.rpc_timeout, - ), - self._client.data_converter, - ) - - async def pause_schedule(self, input: PauseScheduleInput) -> None: - await self._client.workflow_service.patch_schedule( - temporalio.api.workflowservice.v1.PatchScheduleRequest( - namespace=self._client.namespace, - schedule_id=input.id, - patch=temporalio.api.schedule.v1.SchedulePatch( - pause=input.note or "Paused via Python SDK", - ), - identity=self._client.identity, - request_id=str(uuid.uuid4()), - ), - retry=True, - metadata=input.rpc_metadata, - timeout=input.rpc_timeout, - ) - - async def trigger_schedule(self, input: TriggerScheduleInput) -> None: - overlap_policy = temporalio.api.enums.v1.ScheduleOverlapPolicy.SCHEDULE_OVERLAP_POLICY_UNSPECIFIED - if input.overlap: - overlap_policy = temporalio.api.enums.v1.ScheduleOverlapPolicy.ValueType( - input.overlap - ) - await self._client.workflow_service.patch_schedule( - temporalio.api.workflowservice.v1.PatchScheduleRequest( - namespace=self._client.namespace, - schedule_id=input.id, - patch=temporalio.api.schedule.v1.SchedulePatch( - trigger_immediately=temporalio.api.schedule.v1.TriggerImmediatelyRequest( - overlap_policy=overlap_policy, - ), - ), - identity=self._client.identity, - request_id=str(uuid.uuid4()), - ), - retry=True, - metadata=input.rpc_metadata, - timeout=input.rpc_timeout, - ) - - async def unpause_schedule(self, input: UnpauseScheduleInput) -> None: - await self._client.workflow_service.patch_schedule( - temporalio.api.workflowservice.v1.PatchScheduleRequest( - namespace=self._client.namespace, - schedule_id=input.id, - patch=temporalio.api.schedule.v1.SchedulePatch( - unpause=input.note or "Unpaused via Python SDK", - ), - identity=self._client.identity, - request_id=str(uuid.uuid4()), - ), - retry=True, - metadata=input.rpc_metadata, - timeout=input.rpc_timeout, - ) - - async def update_schedule(self, input: UpdateScheduleInput) -> None: - # TODO(cretz): This is supposed to be a retry-conflict loop, but we do - # not yet have a way to know update failure is due to conflict token - # mismatch - update = input.updater( - ScheduleUpdateInput( - description=ScheduleDescription._from_proto( - input.id, - await self._client.workflow_service.describe_schedule( - temporalio.api.workflowservice.v1.DescribeScheduleRequest( - namespace=self._client.namespace, - schedule_id=input.id, - ), - retry=True, - metadata=input.rpc_metadata, - timeout=input.rpc_timeout, - ), - self._client.data_converter, - ) - ) - ) - if inspect.iscoroutine(update): - update = await update - if not update: - return - assert isinstance(update, ScheduleUpdate) - request = temporalio.api.workflowservice.v1.UpdateScheduleRequest( - namespace=self._client.namespace, - schedule_id=input.id, - schedule=await update.schedule._to_proto(self._client), - identity=self._client.identity, - request_id=str(uuid.uuid4()), - ) - if update.search_attributes is not None: - request.search_attributes.indexed_fields.clear() # Ensure that we at least create an empty map - temporalio.converter.encode_search_attributes( - update.search_attributes, request.search_attributes - ) - await self._client.workflow_service.update_schedule( - request, - retry=True, - metadata=input.rpc_metadata, - timeout=input.rpc_timeout, - ) - - async def update_worker_build_id_compatibility( - self, input: UpdateWorkerBuildIdCompatibilityInput - ) -> None: - req = input.operation._as_partial_proto() - req.namespace = self._client.namespace - req.task_queue = input.task_queue - await self._client.workflow_service.update_worker_build_id_compatibility( - req, retry=True, metadata=input.rpc_metadata, timeout=input.rpc_timeout - ) - - async def get_worker_build_id_compatibility( - self, input: GetWorkerBuildIdCompatibilityInput - ) -> WorkerBuildIdVersionSets: - req = temporalio.api.workflowservice.v1.GetWorkerBuildIdCompatibilityRequest( - namespace=self._client.namespace, - task_queue=input.task_queue, - max_sets=input.max_sets or 0, - ) - resp = await self._client.workflow_service.get_worker_build_id_compatibility( - req, retry=True, metadata=input.rpc_metadata, timeout=input.rpc_timeout - ) - return WorkerBuildIdVersionSets._from_proto(resp) - - async def get_worker_task_reachability( - self, input: GetWorkerTaskReachabilityInput - ) -> WorkerTaskReachability: - req = temporalio.api.workflowservice.v1.GetWorkerTaskReachabilityRequest( - namespace=self._client.namespace, - build_ids=input.build_ids, - task_queues=input.task_queues, - reachability=input.reachability._to_proto() - if input.reachability - else temporalio.api.enums.v1.TaskReachability.TASK_REACHABILITY_UNSPECIFIED, - ) - resp = await self._client.workflow_service.get_worker_task_reachability( - req, retry=True, metadata=input.rpc_metadata, timeout=input.rpc_timeout - ) - return WorkerTaskReachability._from_proto(resp) - - async def _apply_headers( - self, - source: Mapping[str, temporalio.api.common.v1.Payload] | None, - dest: MessageMap[str, temporalio.api.common.v1.Payload], - ) -> None: - await _apply_headers( - source, - dest, - self._client.config(active_config=True)["header_codec_behavior"] - == HeaderCodecBehavior.CODEC, - self._client.data_converter, - ) - - -async def _apply_headers( - source: Mapping[str, temporalio.api.common.v1.Payload] | None, - dest: MessageMap[str, temporalio.api.common.v1.Payload], - encode_headers: bool, - data_converter: DataConverter, -) -> None: - if source is None: - return - if encode_headers: - for payload in source.values(): - payload.CopyFrom(await data_converter._transform_outbound_payload(payload)) - temporalio.common._apply_headers(source, dest) - - -def _history_from_json( - history: str | dict[str, Any], -) -> temporalio.api.history.v1.History: - if isinstance(history, str): - history = json.loads(history) - else: - # Copy the dict so we can mutate it - history = copy.deepcopy(history) - if not isinstance(history, dict): - raise ValueError("JSON history not a dictionary") - events = history.get("events") - if not isinstance(events, Iterable): - raise ValueError("History does not have iterable 'events'") - for event in events: - if not isinstance(event, dict): - raise ValueError("Event not a dictionary") - _fix_history_enum( - "CANCEL_EXTERNAL_WORKFLOW_EXECUTION_FAILED_CAUSE", - event, - "requestCancelExternalWorkflowExecutionFailedEventAttributes", - "cause", - ) - _fix_history_enum("CONTINUE_AS_NEW_INITIATOR", event, "*", "initiator") - _fix_history_enum("EVENT_TYPE", event, "eventType") - _fix_history_enum( - "PARENT_CLOSE_POLICY", - event, - "startChildWorkflowExecutionInitiatedEventAttributes", - "parentClosePolicy", - ) - _fix_history_enum("RETRY_STATE", event, "*", "retryState") - _fix_history_enum( - "SIGNAL_EXTERNAL_WORKFLOW_EXECUTION_FAILED_CAUSE", - event, - "signalExternalWorkflowExecutionFailedEventAttributes", - "cause", - ) - _fix_history_enum( - "START_CHILD_WORKFLOW_EXECUTION_FAILED_CAUSE", - event, - "startChildWorkflowExecutionFailedEventAttributes", - "cause", - ) - _fix_history_enum("TASK_QUEUE_KIND", event, "*", "taskQueue", "kind") - _fix_history_enum( - "TIMEOUT_TYPE", - event, - "workflowTaskTimedOutEventAttributes", - "timeoutType", - ) - _fix_history_enum( - "WORKFLOW_ID_REUSE_POLICY", - event, - "startChildWorkflowExecutionInitiatedEventAttributes", - "workflowIdReusePolicy", - ) - _fix_history_enum( - "WORKFLOW_TASK_FAILED_CAUSE", - event, - "workflowTaskFailedEventAttributes", - "cause", - ) - _fix_history_failure(event, "*", "failure") - _fix_history_failure(event, "activityTaskStartedEventAttributes", "lastFailure") - _fix_history_failure( - event, "workflowExecutionStartedEventAttributes", "continuedFailure" - ) - return google.protobuf.json_format.ParseDict( - history, temporalio.api.history.v1.History(), ignore_unknown_fields=True - ) - - -_pascal_case_match = re.compile("([A-Z]+)") - - -def _fix_history_failure(parent: dict[str, Any], *attrs: str) -> None: - _fix_history_enum( - "TIMEOUT_TYPE", parent, *attrs, "timeoutFailureInfo", "timeoutType" - ) - _fix_history_enum("RETRY_STATE", parent, *attrs, "*", "retryState") - # Recurse into causes. First collect all failure parents. - parents = [parent] - for attr in attrs: - new_parents = [] - for parent in parents: - if attr == "*": - for v in parent.values(): - if isinstance(v, dict): - new_parents.append(v) - else: - child = parent.get(attr) - if isinstance(child, dict): - new_parents.append(child) - if not new_parents: - return - parents = new_parents - # Fix each - for parent in parents: - _fix_history_failure(parent, "cause") - - -def _fix_history_enum(prefix: str, parent: dict[str, Any], *attrs: str) -> None: - # If the attr is "*", we need to handle all dict children - if attrs[0] == "*": - for child in parent.values(): - if isinstance(child, dict): - _fix_history_enum(prefix, child, *attrs[1:]) - else: - child = parent.get(attrs[0]) - if isinstance(child, str) and len(attrs) == 1: - # We only fix it if it doesn't already have the prefix - if not parent[attrs[0]].startswith(prefix): - parent[attrs[0]] = ( - prefix + _pascal_case_match.sub(r"_\1", child).upper() - ) - elif isinstance(child, dict) and len(attrs) > 1: - _fix_history_enum(prefix, child, *attrs[1:]) - elif isinstance(child, list) and len(attrs) > 1: - for child_item in child: - if isinstance(child_item, dict): - _fix_history_enum(prefix, child_item, *attrs[1:]) - - -@dataclass(frozen=True) -class WorkerBuildIdVersionSets: - """Represents the sets of compatible Build ID versions associated with some Task Queue, as - fetched by :py:meth:`Client.get_worker_build_id_compatibility`. - """ - - version_sets: Sequence[BuildIdVersionSet] - """All version sets that were fetched for this task queue.""" - - def default_set(self) -> BuildIdVersionSet: - """Returns the default version set for this task queue.""" - return self.version_sets[-1] - - def default_build_id(self) -> str: - """Returns the default Build ID for this task queue.""" - return self.default_set().default() - - @staticmethod - def _from_proto( - resp: temporalio.api.workflowservice.v1.GetWorkerBuildIdCompatibilityResponse, - ) -> WorkerBuildIdVersionSets: - return WorkerBuildIdVersionSets( - version_sets=[ - BuildIdVersionSet(mvs.build_ids) for mvs in resp.major_version_sets - ] - ) - - -@dataclass(frozen=True) -class BuildIdVersionSet: - """A set of Build IDs which are compatible with each other.""" - - build_ids: Sequence[str] - """All Build IDs contained in the set.""" - - def default(self) -> str: - """Returns the default Build ID for this set.""" - return self.build_ids[-1] - - -class BuildIdOp(ABC): - """Base class for Build ID operations as used by - :py:meth:`Client.update_worker_build_id_compatibility`. - """ - - @abstractmethod - def _as_partial_proto( - self, - ) -> temporalio.api.workflowservice.v1.UpdateWorkerBuildIdCompatibilityRequest: - """Returns a partial request with the operation populated. Caller must populate - non-operation fields. This is done b/c there's no good way to assign a non-primitive message - as the operation after initializing the request. - """ - ... - - -@dataclass(frozen=True) -class BuildIdOpAddNewDefault(BuildIdOp): - """Adds a new Build Id into a new set, which will be used as the default set for - the queue. This means all new workflows will start on this Build Id. - """ - - build_id: str - - def _as_partial_proto( - self, - ) -> temporalio.api.workflowservice.v1.UpdateWorkerBuildIdCompatibilityRequest: - return ( - temporalio.api.workflowservice.v1.UpdateWorkerBuildIdCompatibilityRequest( - add_new_build_id_in_new_default_set=self.build_id - ) - ) - - -@dataclass(frozen=True) -class BuildIdOpAddNewCompatible(BuildIdOp): - """Adds a new Build Id into an existing compatible set. The newly added ID becomes - the default for that compatible set, and thus new workflow tasks for workflows which have been - executing on workers in that set will now start on this new Build Id. - """ - - build_id: str - """The Build Id to add to the compatible set.""" - - existing_compatible_build_id: str - """A Build Id which must already be defined on the task queue, and is used to find the - compatible set to add the new id to. - """ - - promote_set: bool = False - """If set to true, the targeted set will also be promoted to become the overall default set for - the queue.""" - - def _as_partial_proto( - self, - ) -> temporalio.api.workflowservice.v1.UpdateWorkerBuildIdCompatibilityRequest: - return temporalio.api.workflowservice.v1.UpdateWorkerBuildIdCompatibilityRequest( - add_new_compatible_build_id=temporalio.api.workflowservice.v1.UpdateWorkerBuildIdCompatibilityRequest.AddNewCompatibleVersion( - new_build_id=self.build_id, - existing_compatible_build_id=self.existing_compatible_build_id, - make_set_default=self.promote_set, - ) - ) - - -@dataclass(frozen=True) -class BuildIdOpPromoteSetByBuildId(BuildIdOp): - """Promotes a set of compatible Build Ids to become the current default set for the task queue. - Any Build Id in the set may be used to target it. - """ - - build_id: str - """A Build Id which must already be defined on the task queue, and is used to find the - compatible set to promote.""" - - def _as_partial_proto( - self, - ) -> temporalio.api.workflowservice.v1.UpdateWorkerBuildIdCompatibilityRequest: - return ( - temporalio.api.workflowservice.v1.UpdateWorkerBuildIdCompatibilityRequest( - promote_set_by_build_id=self.build_id - ) - ) - - -@dataclass(frozen=True) -class BuildIdOpPromoteBuildIdWithinSet(BuildIdOp): - """Promotes a Build Id within an existing set to become the default ID for that set.""" - - build_id: str - - def _as_partial_proto( - self, - ) -> temporalio.api.workflowservice.v1.UpdateWorkerBuildIdCompatibilityRequest: - return ( - temporalio.api.workflowservice.v1.UpdateWorkerBuildIdCompatibilityRequest( - promote_build_id_within_set=self.build_id - ) - ) - - -@dataclass(frozen=True) -class BuildIdOpMergeSets(BuildIdOp): - """Merges two sets into one set, thus declaring all the Build Ids in both as compatible with one - another. The default of the primary set is maintained as the merged set's overall default. - """ - - primary_build_id: str - """A Build Id which and is used to find the primary set to be merged.""" - - secondary_build_id: str - """A Build Id which and is used to find the secondary set to be merged.""" - - def _as_partial_proto( - self, - ) -> temporalio.api.workflowservice.v1.UpdateWorkerBuildIdCompatibilityRequest: - return temporalio.api.workflowservice.v1.UpdateWorkerBuildIdCompatibilityRequest( - merge_sets=temporalio.api.workflowservice.v1.UpdateWorkerBuildIdCompatibilityRequest.MergeSets( - primary_set_build_id=self.primary_build_id, - secondary_set_build_id=self.secondary_build_id, - ) - ) - - -@dataclass(frozen=True) -class WorkerTaskReachability: - """Contains information about the reachability of some Build IDs""" - - build_id_reachability: Mapping[str, BuildIdReachability] - """Maps Build IDs to information about their reachability""" - - @staticmethod - def _from_proto( - resp: temporalio.api.workflowservice.v1.GetWorkerTaskReachabilityResponse, - ) -> WorkerTaskReachability: - mapping = dict() - for bid_reach in resp.build_id_reachability: - tq_mapping = dict() - unretrieved = set() - for tq_reach in bid_reach.task_queue_reachability: - if tq_reach.reachability == [ - temporalio.api.enums.v1.TaskReachability.TASK_REACHABILITY_UNSPECIFIED - ]: - unretrieved.add(tq_reach.task_queue) - continue - tq_mapping[tq_reach.task_queue] = [ - TaskReachabilityType._from_proto(r) for r in tq_reach.reachability - ] - - mapping[bid_reach.build_id] = BuildIdReachability( - task_queue_reachability=tq_mapping, - unretrieved_task_queues=frozenset(unretrieved), - ) - - return WorkerTaskReachability(build_id_reachability=mapping) - - -@dataclass(frozen=True) -class BuildIdReachability: - """Contains information about the reachability of a specific Build ID""" - - task_queue_reachability: Mapping[str, Sequence[TaskReachabilityType]] - """Maps Task Queue names to the reachability status of the Build ID on that queue. If the value - is an empty list, the Build ID is not reachable on that queue. - """ - - unretrieved_task_queues: frozenset[str] - """If any Task Queues could not be retrieved because the server limits the number that can be - queried at once, they will be listed here. - """ - - -class TaskReachabilityType(Enum): - """Enumerates how a task might reach certain kinds of workflows""" - - NEW_WORKFLOWS = 1 - EXISTING_WORKFLOWS = 2 - OPEN_WORKFLOWS = 3 - CLOSED_WORKFLOWS = 4 - - @staticmethod - def _from_proto( - reachability: temporalio.api.enums.v1.TaskReachability.ValueType, - ) -> TaskReachabilityType: - if ( - reachability - == temporalio.api.enums.v1.TaskReachability.TASK_REACHABILITY_NEW_WORKFLOWS - ): - return TaskReachabilityType.NEW_WORKFLOWS - elif ( - reachability - == temporalio.api.enums.v1.TaskReachability.TASK_REACHABILITY_EXISTING_WORKFLOWS - ): - return TaskReachabilityType.EXISTING_WORKFLOWS - elif ( - reachability - == temporalio.api.enums.v1.TaskReachability.TASK_REACHABILITY_OPEN_WORKFLOWS - ): - return TaskReachabilityType.OPEN_WORKFLOWS - elif ( - reachability - == temporalio.api.enums.v1.TaskReachability.TASK_REACHABILITY_CLOSED_WORKFLOWS - ): - return TaskReachabilityType.CLOSED_WORKFLOWS - else: - raise ValueError(f"Cannot convert reachability type: {reachability}") - - def _to_proto(self) -> temporalio.api.enums.v1.TaskReachability.ValueType: - if self == TaskReachabilityType.NEW_WORKFLOWS: - return ( - temporalio.api.enums.v1.TaskReachability.TASK_REACHABILITY_NEW_WORKFLOWS - ) - elif self == TaskReachabilityType.EXISTING_WORKFLOWS: - return temporalio.api.enums.v1.TaskReachability.TASK_REACHABILITY_EXISTING_WORKFLOWS - elif self == TaskReachabilityType.OPEN_WORKFLOWS: - return temporalio.api.enums.v1.TaskReachability.TASK_REACHABILITY_OPEN_WORKFLOWS - elif self == TaskReachabilityType.CLOSED_WORKFLOWS: - return temporalio.api.enums.v1.TaskReachability.TASK_REACHABILITY_CLOSED_WORKFLOWS - else: - return ( - temporalio.api.enums.v1.TaskReachability.TASK_REACHABILITY_UNSPECIFIED - ) - - -class CloudOperationsClient: - """Client for accessing Temporal Cloud Operations API. - - .. warning:: - This client and the API are experimental - - Most users will use :py:meth:`connect` to create a client. The - :py:attr:`cloud_service` property provides access to a raw gRPC cloud - service client. - - Clients are not thread-safe and should only be used in the event loop they - are first connected in. If a client needs to be used from another thread - than where it was created, make sure the event loop where it was created is - captured, and then call :py:func:`asyncio.run_coroutine_threadsafe` with the - client call and that event loop. - - Clients do not work across forks since runtimes do not work across forks. - """ - - @staticmethod - async def connect( - *, - api_key: str | None = None, - version: str | None = None, - target_host: str = "saas-api.tmprl.cloud:443", - tls: bool | TLSConfig = True, - retry_config: RetryConfig | None = None, - keep_alive_config: KeepAliveConfig | None = KeepAliveConfig.default, - rpc_metadata: Mapping[str, str | bytes] = {}, - identity: str | None = None, - lazy: bool = False, - runtime: temporalio.runtime.Runtime | None = None, - http_connect_proxy_config: HttpConnectProxyConfig | None = None, - dns_load_balancing_config: DnsLoadBalancingConfig | None = None, - ) -> CloudOperationsClient: - """Connect to a Temporal Cloud Operations API. - - .. warning:: - This client and the API are experimental - - Args: - api_key: API key for Temporal. This becomes the "Authorization" - HTTP header with "Bearer " prepended. This is only set if RPC - metadata doesn't already have an "authorization" key. This is - essentially required for access to the cloud API. - version: Version header for safer mutations. May or may not be - required depending on cloud settings. - target_host: ``host:port`` for the Temporal server. The default is - to the common cloud endpoint. - tls: If true, the default, use system default TLS configuration. If - false, the default, do not use TLS. If TLS configuration - present, that TLS configuration will be used. The default is - usually required to access the API. - retry_config: Retry configuration for direct service calls (when - opted in) or all high-level calls made by this client (which all - opt-in to retries by default). If unset, a default retry - configuration is used. - keep_alive_config: Keep-alive configuration for the client - connection. Default is to check every 30s and kill the - connection if a response doesn't come back in 15s. Can be set to - ``None`` to disable. - rpc_metadata: Headers to use for all calls to the server. Keys here - can be overriden by per-call RPC metadata keys. - identity: Identity for this client. If unset, a default is created - based on the version of the SDK. - lazy: If true, the client will not connect until the first call is - attempted or a worker is created with it. Lazy clients cannot be - used for workers. - runtime: The runtime for this client, or the default if unset. - http_connect_proxy_config: Configuration for HTTP CONNECT proxy. - dns_load_balancing_config: DNS load balancing configuration for the - client connection. Default is disabled. Silently disabled when - ``http_connect_proxy_config`` is set, since the two are mutually - exclusive. - """ - # Add version if given - if version: - rpc_metadata = dict(rpc_metadata) - rpc_metadata["temporal-cloud-api-version"] = version - connect_config = temporalio.service.ConnectConfig( - target_host=target_host, - api_key=api_key, - tls=tls, - retry_config=retry_config, - keep_alive_config=keep_alive_config, - rpc_metadata=rpc_metadata, - identity=identity or "", - lazy=lazy, - runtime=runtime, - http_connect_proxy_config=http_connect_proxy_config, - dns_load_balancing_config=dns_load_balancing_config, - ) - return CloudOperationsClient( - await temporalio.service.ServiceClient.connect(connect_config) - ) - - def __init__( - self, - service_client: temporalio.service.ServiceClient, - ): - """Create a Temporal Cloud Operations client from a service client. - - .. warning:: - This client and the API are experimental - - Args: - service_client: Existing service client to use. - """ - self._service_client = service_client - - @property - def service_client(self) -> temporalio.service.ServiceClient: - """Raw gRPC service client.""" - return self._service_client - - @property - def cloud_service(self) -> temporalio.service.CloudService: - """Raw gRPC cloud service client.""" - return self._service_client.cloud_service - - @property - def identity(self) -> str: - """Identity used in calls by this client.""" - return self._service_client.config.identity - - @property - def rpc_metadata(self) -> Mapping[str, str | bytes]: - """Headers for every call made by this client. - - Do not use mutate this mapping. Rather, set this property with an - entirely new mapping to change the headers. This may include the - ``temporal-cloud-api-version`` header if set. - """ - return self.service_client.config.rpc_metadata - - @rpc_metadata.setter - def rpc_metadata(self, value: Mapping[str, str | bytes]) -> None: - """Update the headers for this client. - - Do not mutate this mapping after set. Rather, set an entirely new - mapping if changes are needed. Currently this must be set with the - ``temporal-cloud-api-version`` header if it is needed. - """ - # Update config and perform update - self.service_client.config.rpc_metadata = value - self.service_client.update_rpc_metadata(value) - - @property - def api_key(self) -> str | None: - """API key for every call made by this client.""" - return self.service_client.config.api_key - - @api_key.setter - def api_key(self, value: str | None) -> None: - """Update the API key for this client. - - This is only set if RPCmetadata doesn't already have an "authorization" - key. - """ - # Update config and perform update - self.service_client.config.api_key = value - self.service_client.update_api_key(value) - - -# Intended to become a union of callback types -Callback = temporalio.nexus.NexusCallback - - -async def _encode_user_metadata( - converter: temporalio.converter.DataConverter, - summary: str | temporalio.api.common.v1.Payload | None, - details: str | temporalio.api.common.v1.Payload | None, -) -> temporalio.api.sdk.v1.UserMetadata | None: - if summary is None and details is None: - return None - enc_summary = None - enc_details = None - if summary is not None: - if isinstance(summary, str): - enc_summary = (await converter.encode([summary]))[0] - else: - enc_summary = summary - if details is not None: - if isinstance(details, str): - enc_details = (await converter.encode([details]))[0] - else: - enc_details = details - return temporalio.api.sdk.v1.UserMetadata(summary=enc_summary, details=enc_details) - - -async def _decode_user_metadata( - converter: temporalio.converter.DataConverter, - metadata: temporalio.api.sdk.v1.UserMetadata | None, -) -> tuple[str | None, str | None]: - """Returns (summary, details)""" - if metadata is None: - return None, None - return ( - None - if not metadata.HasField("summary") - else (await converter.decode([metadata.summary]))[0], - None - if not metadata.HasField("details") - else (await converter.decode([metadata.details]))[0], - ) - - -class Plugin(abc.ABC): - """Base class for client plugins that can intercept and modify client behavior. - - Plugins allow customization of client creation and service connection processes - through a chain of responsibility pattern. Each plugin can modify the client - configuration or intercept service client connections. - - If the plugin is also a temporalio.worker.Plugin, it will additionally be propagated as a worker plugin. - You should likley not also provide it to the worker as that will result in the plugin being applied twice. - """ - - def name(self) -> str: - """Get the name of this plugin. Can be overridden if desired to provide a more appropriate name. - - Returns: - The fully qualified name of the plugin class (module.classname). - """ - return type(self).__module__ + "." + type(self).__qualname__ - - @abstractmethod - def configure_client(self, config: ClientConfig) -> ClientConfig: - """Hook called when creating a client to allow modification of configuration. - - This method is called during client creation and allows plugins to modify - the client configuration before the client is fully initialized. Plugins - can add interceptors, modify connection parameters, or change other settings. - - Args: - config: The client configuration dictionary to potentially modify. - - Returns: - The modified client configuration. - """ - - @abstractmethod - async def connect_service_client( - self, - config: ConnectConfig, - next: Callable[[ConnectConfig], Awaitable[ServiceClient]], - ) -> ServiceClient: - """Hook called when connecting to the Temporal service. - - This method is called during service client connection and allows plugins - to intercept or modify the connection process. Plugins can modify connection - parameters, add authentication, or provide custom connection logic. - - Args: - config: The service connection configuration. - - Returns: - The connected service client. - """ diff --git a/temporalio/client/__init__.py b/temporalio/client/__init__.py new file mode 100644 index 000000000..c403b8bcc --- /dev/null +++ b/temporalio/client/__init__.py @@ -0,0 +1,346 @@ +"""Client for accessing Temporal.""" + +from __future__ import annotations + +from temporalio.activity import ActivityCancellationDetails +from temporalio.converter import ( + ActivitySerializationContext, + DataConverter, + SerializationContext, + StorageDriverActivityInfo, + StorageDriverStoreContext, + StorageDriverWorkflowInfo, + WithSerializationContext, + WorkflowSerializationContext, +) +from temporalio.service import ( + ConnectConfig, + DnsLoadBalancingConfig, + HttpConnectProxyConfig, + KeepAliveConfig, + RetryConfig, + RPCError, + RPCStatusCode, + ServiceClient, + TLSConfig, +) + +from ..common import HeaderCodecBehavior +from ..types import ( + AnyType, + CallableAsyncNoParam, + CallableAsyncSingleParam, + CallableSyncNoParam, + CallableSyncSingleParam, + LocalReturnType, + MethodAsyncNoParam, + MethodAsyncSingleParam, + MethodSyncOrAsyncNoParam, + MethodSyncOrAsyncSingleParam, + MultiParamSpec, + ParamType, + ReturnType, + SelfType, +) +from ._activity import ( + ActivityExecution, + ActivityExecutionAsyncIterator, + ActivityExecutionCount, + ActivityExecutionCountAggregationGroup, + ActivityExecutionDescription, + ActivityExecutionStatus, + ActivityHandle, + AsyncActivityHandle, + AsyncActivityIDReference, + PendingActivityState, +) +from ._callback import ( + Callback, +) +from ._client import ( + Client, + ClientConfig, + ClientConnectConfig, +) +from ._cloud import ( + CloudOperationsClient, +) +from ._exceptions import ( + ActivityFailureError, + AsyncActivityCancelledError, + RPCTimeoutOrCancelledError, + ScheduleAlreadyRunningError, + WorkflowContinuedAsNewError, + WorkflowFailureError, + WorkflowQueryFailedError, + WorkflowQueryRejectedError, + WorkflowUpdateFailedError, + WorkflowUpdateRPCTimeoutOrCancelledError, +) +from ._helpers import ( + _apply_headers, + _decode_user_metadata, + _encode_user_metadata, + _fix_history_enum, + _fix_history_failure, + _history_from_json, + _pascal_case_match, +) +from ._impl import _ClientImpl +from ._interceptor import ( + BackfillScheduleInput, + CancelActivityInput, + CancelWorkflowInput, + CompleteAsyncActivityInput, + CountActivitiesInput, + CountWorkflowsInput, + CreateScheduleInput, + DeleteScheduleInput, + DescribeActivityInput, + DescribeScheduleInput, + DescribeWorkflowInput, + FailAsyncActivityInput, + FetchWorkflowHistoryEventsInput, + GetWorkerBuildIdCompatibilityInput, + GetWorkerTaskReachabilityInput, + HeartbeatAsyncActivityInput, + Interceptor, + ListActivitiesInput, + ListSchedulesInput, + ListWorkflowsInput, + OutboundInterceptor, + PauseScheduleInput, + QueryWorkflowInput, + ReportCancellationAsyncActivityInput, + SignalWorkflowInput, + StartActivityInput, + StartWorkflowInput, + StartWorkflowUpdateInput, + StartWorkflowUpdateWithStartInput, + TerminateActivityInput, + TerminateWorkflowInput, + TriggerScheduleInput, + UnpauseScheduleInput, + UpdateScheduleInput, + UpdateWithStartStartWorkflowInput, + UpdateWithStartUpdateWorkflowInput, + UpdateWorkerBuildIdCompatibilityInput, +) +from ._plugin import ( + Plugin, +) +from ._schedule import ( + Schedule, + ScheduleAction, + ScheduleActionExecution, + ScheduleActionExecutionStartWorkflow, + ScheduleActionResult, + ScheduleActionStartWorkflow, + ScheduleAsyncIterator, + ScheduleBackfill, + ScheduleCalendarSpec, + ScheduleDescription, + ScheduleHandle, + ScheduleInfo, + ScheduleIntervalSpec, + ScheduleListAction, + ScheduleListActionStartWorkflow, + ScheduleListDescription, + ScheduleListInfo, + ScheduleListSchedule, + ScheduleListState, + ScheduleOverlapPolicy, + SchedulePolicy, + ScheduleRange, + ScheduleSpec, + ScheduleState, + ScheduleUpdate, + ScheduleUpdateInput, +) +from ._worker_versioning import ( + BuildIdOp, + BuildIdOpAddNewCompatible, + BuildIdOpAddNewDefault, + BuildIdOpMergeSets, + BuildIdOpPromoteBuildIdWithinSet, + BuildIdOpPromoteSetByBuildId, + BuildIdReachability, + BuildIdVersionSet, + TaskReachabilityType, + WorkerBuildIdVersionSets, + WorkerTaskReachability, +) +from ._workflow import ( + WithStartWorkflowOperation, + WorkflowExecution, + WorkflowExecutionAsyncIterator, + WorkflowExecutionCount, + WorkflowExecutionCountAggregationGroup, + WorkflowExecutionDescription, + WorkflowExecutionStatus, + WorkflowHandle, + WorkflowHistory, + WorkflowHistoryEventAsyncIterator, + WorkflowHistoryEventFilterType, + WorkflowUpdateHandle, + WorkflowUpdateStage, +) + +__all__ = [ + "Client", + "ClientConnectConfig", + "ClientConfig", + "WorkflowHistoryEventFilterType", + "WorkflowHandle", + "WithStartWorkflowOperation", + "WorkflowExecution", + "WorkflowExecutionDescription", + "WorkflowExecutionStatus", + "WorkflowExecutionCount", + "WorkflowExecutionCountAggregationGroup", + "WorkflowExecutionAsyncIterator", + "WorkflowHistory", + "WorkflowHistoryEventAsyncIterator", + "WorkflowUpdateHandle", + "WorkflowUpdateStage", + "ActivityExecutionAsyncIterator", + "ActivityExecution", + "ActivityExecutionDescription", + "ActivityExecutionStatus", + "PendingActivityState", + "ActivityExecutionCount", + "ActivityExecutionCountAggregationGroup", + "AsyncActivityIDReference", + "AsyncActivityHandle", + "ActivityHandle", + "ScheduleHandle", + "ScheduleSpec", + "ScheduleRange", + "ScheduleCalendarSpec", + "ScheduleIntervalSpec", + "ScheduleAction", + "ScheduleActionStartWorkflow", + "ScheduleOverlapPolicy", + "ScheduleBackfill", + "SchedulePolicy", + "ScheduleState", + "Schedule", + "ScheduleDescription", + "ScheduleInfo", + "ScheduleActionExecution", + "ScheduleActionExecutionStartWorkflow", + "ScheduleActionResult", + "ScheduleUpdateInput", + "ScheduleUpdate", + "ScheduleListDescription", + "ScheduleListSchedule", + "ScheduleListAction", + "ScheduleListActionStartWorkflow", + "ScheduleListInfo", + "ScheduleListState", + "ScheduleAsyncIterator", + "WorkflowFailureError", + "WorkflowContinuedAsNewError", + "WorkflowQueryRejectedError", + "WorkflowQueryFailedError", + "WorkflowUpdateFailedError", + "RPCTimeoutOrCancelledError", + "WorkflowUpdateRPCTimeoutOrCancelledError", + "ActivityFailureError", + "AsyncActivityCancelledError", + "ScheduleAlreadyRunningError", + "StartWorkflowInput", + "CancelWorkflowInput", + "DescribeWorkflowInput", + "FetchWorkflowHistoryEventsInput", + "ListWorkflowsInput", + "CountWorkflowsInput", + "QueryWorkflowInput", + "SignalWorkflowInput", + "TerminateWorkflowInput", + "StartActivityInput", + "CancelActivityInput", + "TerminateActivityInput", + "DescribeActivityInput", + "ListActivitiesInput", + "CountActivitiesInput", + "StartWorkflowUpdateInput", + "UpdateWithStartUpdateWorkflowInput", + "UpdateWithStartStartWorkflowInput", + "StartWorkflowUpdateWithStartInput", + "HeartbeatAsyncActivityInput", + "CompleteAsyncActivityInput", + "FailAsyncActivityInput", + "ReportCancellationAsyncActivityInput", + "CreateScheduleInput", + "ListSchedulesInput", + "BackfillScheduleInput", + "DeleteScheduleInput", + "DescribeScheduleInput", + "PauseScheduleInput", + "TriggerScheduleInput", + "UnpauseScheduleInput", + "UpdateScheduleInput", + "UpdateWorkerBuildIdCompatibilityInput", + "GetWorkerBuildIdCompatibilityInput", + "GetWorkerTaskReachabilityInput", + "Interceptor", + "OutboundInterceptor", + "WorkerBuildIdVersionSets", + "BuildIdVersionSet", + "BuildIdOp", + "BuildIdOpAddNewDefault", + "BuildIdOpAddNewCompatible", + "BuildIdOpPromoteSetByBuildId", + "BuildIdOpPromoteBuildIdWithinSet", + "BuildIdOpMergeSets", + "WorkerTaskReachability", + "BuildIdReachability", + "TaskReachabilityType", + "CloudOperationsClient", + "Plugin", + "Callback", + "_ClientImpl", + "_apply_headers", + "_decode_user_metadata", + "_encode_user_metadata", + "_fix_history_enum", + "_fix_history_failure", + "_history_from_json", + "_pascal_case_match", + # Re-export Temporal-owned names that old temporalio/client.py imported at + # module scope so explicit imports from temporalio.client keep working. + "ActivityCancellationDetails", + "ActivitySerializationContext", + "DataConverter", + "SerializationContext", + "StorageDriverActivityInfo", + "StorageDriverStoreContext", + "StorageDriverWorkflowInfo", + "WithSerializationContext", + "WorkflowSerializationContext", + "ConnectConfig", + "DnsLoadBalancingConfig", + "HttpConnectProxyConfig", + "KeepAliveConfig", + "RetryConfig", + "RPCError", + "RPCStatusCode", + "ServiceClient", + "TLSConfig", + "HeaderCodecBehavior", + "AnyType", + "CallableAsyncNoParam", + "CallableAsyncSingleParam", + "CallableSyncNoParam", + "CallableSyncSingleParam", + "LocalReturnType", + "MethodAsyncNoParam", + "MethodAsyncSingleParam", + "MethodSyncOrAsyncNoParam", + "MethodSyncOrAsyncSingleParam", + "MultiParamSpec", + "ParamType", + "ReturnType", + "SelfType", +] diff --git a/temporalio/client/_activity.py b/temporalio/client/_activity.py new file mode 100644 index 000000000..99c9ede31 --- /dev/null +++ b/temporalio/client/_activity.py @@ -0,0 +1,913 @@ +"""Client support for accessing Temporal.""" + +from __future__ import annotations + +import asyncio +import functools +import warnings +from collections.abc import ( + Mapping, + Sequence, +) +from dataclasses import dataclass +from datetime import datetime, timedelta, timezone +from enum import IntEnum +from typing import ( + TYPE_CHECKING, + Any, + Generic, + cast, +) + +from typing_extensions import Self + +import temporalio.api.activity.v1 +import temporalio.api.common.v1 +import temporalio.api.enums.v1 +import temporalio.api.workflowservice.v1 +import temporalio.common +import temporalio.converter +import temporalio.converter._search_attributes +from temporalio.converter import ( + ActivitySerializationContext, + DataConverter, + SerializationContext, + WithSerializationContext, +) +from temporalio.service import ( + RPCError, + RPCStatusCode, +) + +from ..types import ( + ReturnType, +) +from ._exceptions import ActivityFailureError +from ._interceptor import ( + CancelActivityInput, + CompleteAsyncActivityInput, + DescribeActivityInput, + FailAsyncActivityInput, + HeartbeatAsyncActivityInput, + ReportCancellationAsyncActivityInput, + TerminateActivityInput, +) + +if TYPE_CHECKING: + from ._client import Client + from ._interceptor import ListActivitiesInput + + +class ActivityExecutionAsyncIterator: + """Asynchronous iterator for activity execution values. + + You should typically use ``async for`` on this iterator and not call any of its methods. + + .. warning:: + This API is experimental. + """ + + def __init__( + self, + client: Client, + input: ListActivitiesInput, + ) -> None: + """Create an asynchronous iterator for the given input. + + Users should not create this directly, but rather use + :py:meth:`Client.list_activities`. + """ + self._client = client + self._input = input + self._next_page_token = input.next_page_token + self._current_page: Sequence[ActivityExecution] | None = None + self._current_page_index = 0 + self._limit = input.limit + self._yielded = 0 + + @property + def current_page_index(self) -> int: + """Index of the entry in the current page that will be returned from + the next :py:meth:`__anext__` call. + """ + return self._current_page_index + + @property + def current_page(self) -> Sequence[ActivityExecution] | None: + """Current page, if it has been fetched yet.""" + return self._current_page + + @property + def next_page_token(self) -> bytes | None: + """Token for the next page request if any.""" + return self._next_page_token + + async def fetch_next_page(self, *, page_size: int | None = None) -> None: + """Fetch the next page of results. + + Args: + page_size: Override the page size this iterator was originally + created with. + """ + page_size = page_size or self._input.page_size + if self._limit is not None and self._limit - self._yielded < page_size: + page_size = self._limit - self._yielded + + resp = await self._client.workflow_service.list_activity_executions( + temporalio.api.workflowservice.v1.ListActivityExecutionsRequest( + namespace=self._client.namespace, + page_size=page_size, + next_page_token=self._next_page_token or b"", + query=self._input.query or "", + ), + retry=True, + metadata=self._input.rpc_metadata, + timeout=self._input.rpc_timeout, + ) + + self._current_page = [ + ActivityExecution._from_raw_info(v, self._client.namespace) + for v in resp.executions + ] + self._current_page_index = 0 + self._next_page_token = resp.next_page_token or None + + def __aiter__(self) -> ActivityExecutionAsyncIterator: + """Return self as the iterator.""" + return self + + async def __anext__(self) -> ActivityExecution: + """Get the next execution on this iterator, fetching next page if + necessary. + """ + if self._limit is not None and self._yielded >= self._limit: + raise StopAsyncIteration + while True: + # No page? fetch and continue + if self._current_page is None: + await self.fetch_next_page() + continue + # No more left in page? + if self._current_page_index >= len(self._current_page): + # If there is a next page token, try to get another page and try + # again + if self._next_page_token is not None: + await self.fetch_next_page() + continue + # No more pages means we're done + raise StopAsyncIteration + # Get current, increment page index, and return + ret = self._current_page[self._current_page_index] + self._current_page_index += 1 + self._yielded += 1 + return ret + + +@dataclass(frozen=True) +class ActivityExecution: + """Info for an activity execution not started by a workflow, from list response. + + .. warning:: + This API is experimental. + """ + + activity_id: str + """Activity ID.""" + + activity_run_id: str | None + """Run ID of the activity.""" + + activity_type: str + """Type name of the activity.""" + + close_time: datetime | None + """Time the activity reached a terminal status, if closed.""" + + execution_duration: timedelta | None + """Duration from scheduled to close time, only populated if closed.""" + + namespace: str + """Namespace of the activity (copied from calling client).""" + + raw_info: ( + temporalio.api.activity.v1.ActivityExecutionListInfo + | temporalio.api.activity.v1.ActivityExecutionInfo + ) + """Underlying protobuf info.""" + + scheduled_time: datetime + """Time the activity was originally scheduled.""" + + state_transition_count: int | None + """Number of state transitions, if available.""" + + status: ActivityExecutionStatus + """Current status of the activity.""" + + task_queue: str + """Task queue the activity was scheduled on.""" + + typed_search_attributes: temporalio.common.TypedSearchAttributes + """Current set of search attributes if any.""" + + @classmethod + def _from_raw_info( + cls, info: temporalio.api.activity.v1.ActivityExecutionListInfo, namespace: str + ) -> Self: + """Create from raw proto activity list info.""" + return cls( + activity_id=info.activity_id, + activity_run_id=info.run_id or None, + activity_type=( + info.activity_type.name if info.HasField("activity_type") else "" + ), + close_time=( + info.close_time.ToDatetime().replace(tzinfo=timezone.utc) + if info.HasField("close_time") + else None + ), + execution_duration=( + info.execution_duration.ToTimedelta() + if info.HasField("execution_duration") + else None + ), + namespace=namespace, + raw_info=info, + scheduled_time=( + info.schedule_time.ToDatetime().replace(tzinfo=timezone.utc) + if info.HasField("schedule_time") + else datetime.min + ), + state_transition_count=( + info.state_transition_count if info.state_transition_count else None + ), + status=( + ActivityExecutionStatus(info.status) + if info.status + else ActivityExecutionStatus.UNSPECIFIED + ), + task_queue=info.task_queue, + typed_search_attributes=temporalio.converter.decode_typed_search_attributes( + info.search_attributes + ), + ) + + +@dataclass(frozen=True) +class ActivityExecutionDescription(ActivityExecution): + """Detailed information about an activity execution not started by a workflow. + + .. warning:: + This API is experimental. + """ + + attempt: int + """Current attempt number.""" + + canceled_reason: str | None + """Reason for cancellation, if cancel was requested.""" + + current_retry_interval: timedelta | None + """Time until the next retry, if applicable.""" + + eager_execution_requested: bool + """Whether eager execution was requested for this activity.""" + + expiration_time: datetime + """Scheduled time plus schedule_to_close_timeout.""" + + last_attempt_complete_time: datetime | None + """Time when the last attempt completed.""" + + last_failure: Exception | None + """Failure from the last failed attempt, if any.""" + + last_heartbeat_time: datetime | None + """Time of the last heartbeat.""" + + last_started_time: datetime | None + """Time the last attempt was started.""" + + last_worker_identity: str + """Identity of the last worker that processed the activity.""" + + next_attempt_schedule_time: datetime | None + """Time when the next attempt will be scheduled.""" + + paused: bool + """Whether the activity is paused.""" + + raw_heartbeat_details: Sequence[temporalio.api.common.v1.Payload] + """Details from the last heartbeat.""" + + retry_policy: temporalio.common.RetryPolicy | None + """Retry policy for the activity.""" + + run_state: PendingActivityState | None + """More detailed breakdown if status is RUNNING.""" + + long_poll_token: bytes | None + """Token for follow-on long-poll requests. None if the activity is complete.""" + + @classmethod + async def _from_execution_info( + cls, + info: temporalio.api.activity.v1.ActivityExecutionInfo, + long_poll_token: bytes | None, + namespace: str, + data_converter: temporalio.converter.DataConverter, + ) -> Self: + """Create from raw proto activity execution info.""" + # Decode heartbeat details if present + decoded_heartbeat_details: Sequence[temporalio.api.common.v1.Payload] = ( + info.heartbeat_details.payloads + ) + if decoded_heartbeat_details and data_converter.payload_codec: + decoded_heartbeat_details = await data_converter.payload_codec.decode( + decoded_heartbeat_details + ) + + return cls( + activity_id=info.activity_id, + activity_run_id=info.run_id or None, + activity_type=( + info.activity_type.name if info.HasField("activity_type") else "" + ), + attempt=info.attempt, + canceled_reason=info.canceled_reason or None, + close_time=( + info.close_time.ToDatetime(tzinfo=timezone.utc) + if info.HasField("close_time") + else None + ), + current_retry_interval=( + info.current_retry_interval.ToTimedelta() + if info.HasField("current_retry_interval") + else None + ), + eager_execution_requested=getattr(info, "eager_execution_requested", False), + execution_duration=( + info.execution_duration.ToTimedelta() + if info.HasField("execution_duration") + else None + ), + expiration_time=( + info.expiration_time.ToDatetime(tzinfo=timezone.utc) + if info.HasField("expiration_time") + else datetime.min + ), + last_attempt_complete_time=( + info.last_attempt_complete_time.ToDatetime(tzinfo=timezone.utc) + if info.HasField("last_attempt_complete_time") + else None + ), + last_failure=( + cast( + Exception | None, + await data_converter.decode_failure(info.last_failure), + ) + if info.HasField("last_failure") + else None + ), + last_heartbeat_time=( + info.last_heartbeat_time.ToDatetime(tzinfo=timezone.utc) + if info.HasField("last_heartbeat_time") + else None + ), + last_started_time=( + info.last_started_time.ToDatetime(tzinfo=timezone.utc) + if info.HasField("last_started_time") + else None + ), + last_worker_identity=info.last_worker_identity, + long_poll_token=long_poll_token or None, + namespace=namespace, + next_attempt_schedule_time=( + info.next_attempt_schedule_time.ToDatetime(tzinfo=timezone.utc) + if info.HasField("next_attempt_schedule_time") + else None + ), + paused=getattr(info, "paused", False), + raw_heartbeat_details=decoded_heartbeat_details, + raw_info=info, + retry_policy=temporalio.common.RetryPolicy.from_proto(info.retry_policy) + if info.HasField("retry_policy") + else None, + run_state=( + PendingActivityState(info.run_state) if info.run_state else None + ), + scheduled_time=(info.schedule_time.ToDatetime(tzinfo=timezone.utc)), + state_transition_count=( + info.state_transition_count if info.state_transition_count else None + ), + status=( + ActivityExecutionStatus(info.status) + if info.status + else ActivityExecutionStatus.UNSPECIFIED + ), + task_queue=info.task_queue, + typed_search_attributes=temporalio.converter.decode_typed_search_attributes( + info.search_attributes + ), + ) + + +class ActivityExecutionStatus(IntEnum): + """Status of an activity execution. + + .. warning:: + This API is experimental. + + See :py:class:`temporalio.api.enums.v1.ActivityExecutionStatus`. + """ + + UNSPECIFIED = int( + temporalio.api.enums.v1.ActivityExecutionStatus.ACTIVITY_EXECUTION_STATUS_UNSPECIFIED + ) + RUNNING = int( + temporalio.api.enums.v1.ActivityExecutionStatus.ACTIVITY_EXECUTION_STATUS_RUNNING + ) + COMPLETED = int( + temporalio.api.enums.v1.ActivityExecutionStatus.ACTIVITY_EXECUTION_STATUS_COMPLETED + ) + FAILED = int( + temporalio.api.enums.v1.ActivityExecutionStatus.ACTIVITY_EXECUTION_STATUS_FAILED + ) + CANCELED = int( + temporalio.api.enums.v1.ActivityExecutionStatus.ACTIVITY_EXECUTION_STATUS_CANCELED + ) + TERMINATED = int( + temporalio.api.enums.v1.ActivityExecutionStatus.ACTIVITY_EXECUTION_STATUS_TERMINATED + ) + TIMED_OUT = int( + temporalio.api.enums.v1.ActivityExecutionStatus.ACTIVITY_EXECUTION_STATUS_TIMED_OUT + ) + + +class PendingActivityState(IntEnum): + """Detailed state of an activity execution that is in ACTIVITY_EXECUTION_STATUS_RUNNING. + + .. warning:: + This API is experimental. + + See :py:class:`temporalio.api.enums.v1.PendingActivityState`. + """ + + UNSPECIFIED = int( + temporalio.api.enums.v1.PendingActivityState.PENDING_ACTIVITY_STATE_UNSPECIFIED + ) + SCHEDULED = int( + temporalio.api.enums.v1.PendingActivityState.PENDING_ACTIVITY_STATE_SCHEDULED + ) + STARTED = int( + temporalio.api.enums.v1.PendingActivityState.PENDING_ACTIVITY_STATE_STARTED + ) + CANCEL_REQUESTED = int( + temporalio.api.enums.v1.PendingActivityState.PENDING_ACTIVITY_STATE_CANCEL_REQUESTED + ) + PAUSED = int( + temporalio.api.enums.v1.PendingActivityState.PENDING_ACTIVITY_STATE_PAUSED + ) + PAUSE_REQUESTED = int( + temporalio.api.enums.v1.PendingActivityState.PENDING_ACTIVITY_STATE_PAUSE_REQUESTED + ) + + +@dataclass(frozen=True) +class ActivityExecutionCount: + """Representation of a count from a count activities call. + + .. warning:: + This API is experimental. + """ + + count: int + """Total count matching the filter, if any.""" + + groups: Sequence[ActivityExecutionCountAggregationGroup] + """Aggregation groups if requested.""" + + @staticmethod + def _from_raw( + resp: temporalio.api.workflowservice.v1.CountActivityExecutionsResponse, + ) -> ActivityExecutionCount: + """Create from raw proto response.""" + return ActivityExecutionCount( + count=resp.count, + groups=[ + ActivityExecutionCountAggregationGroup._from_raw(g) for g in resp.groups + ], + ) + + +@dataclass(frozen=True) +class ActivityExecutionCountAggregationGroup: + """A single aggregation group from a count activities call. + + .. warning:: + This API is experimental. + """ + + count: int + """Count for this group.""" + + group_values: Sequence[temporalio.common.SearchAttributeValue] + """Values that define this group.""" + + @staticmethod + def _from_raw( + raw: temporalio.api.workflowservice.v1.CountActivityExecutionsResponse.AggregationGroup, + ) -> ActivityExecutionCountAggregationGroup: + return ActivityExecutionCountAggregationGroup( + count=raw.count, + group_values=[ + temporalio.converter._search_attributes._decode_search_attribute_value( + v + ) + for v in raw.group_values + ], + ) + + +@dataclass(frozen=True) +class AsyncActivityIDReference: + """Reference to an async activity by its qualified ID.""" + + workflow_id: str | None + run_id: str | None + activity_id: str + + +class AsyncActivityHandle(WithSerializationContext): + """Handle representing an external activity for completion and heartbeat.""" + + def __init__( + self, + client: Client, + id_or_token: AsyncActivityIDReference | bytes, + data_converter_override: DataConverter | None = None, + ) -> None: + """Create an async activity handle.""" + self._client = client + self._id_or_token = id_or_token + self._data_converter_override = data_converter_override + + async def heartbeat( + self, + *details: Any, + rpc_metadata: Mapping[str, str | bytes] = {}, + rpc_timeout: timedelta | None = None, + ) -> None: + """Record a heartbeat for the activity. + + Args: + details: Details of the heartbeat. + rpc_metadata: Headers used on the RPC call. Keys here override + client-level RPC metadata keys. + rpc_timeout: Optional RPC deadline to set for the RPC call. + """ + await self._client._impl.heartbeat_async_activity( + HeartbeatAsyncActivityInput( + id_or_token=self._id_or_token, + details=details, + rpc_metadata=rpc_metadata, + rpc_timeout=rpc_timeout, + data_converter_override=self._data_converter_override, + ), + ) + + async def complete( + self, + result: Any | None = temporalio.common._arg_unset, + *, + rpc_metadata: Mapping[str, str | bytes] = {}, + rpc_timeout: timedelta | None = None, + ) -> None: + """Complete the activity. + + Args: + result: Result of the activity if any. + rpc_metadata: Headers used on the RPC call. Keys here override + client-level RPC metadata keys. + rpc_timeout: Optional RPC deadline to set for the RPC call. + """ + await self._client._impl.complete_async_activity( + CompleteAsyncActivityInput( + id_or_token=self._id_or_token, + result=result, + rpc_metadata=rpc_metadata, + rpc_timeout=rpc_timeout, + data_converter_override=self._data_converter_override, + ), + ) + + async def fail( + self, + error: Exception, + *, + last_heartbeat_details: Sequence[Any] = [], + rpc_metadata: Mapping[str, str | bytes] = {}, + rpc_timeout: timedelta | None = None, + ) -> None: + """Fail the activity. + + Args: + error: Error for the activity. + last_heartbeat_details: Last heartbeat details for the activity. + rpc_metadata: Headers used on the RPC call. Keys here override + client-level RPC metadata keys. + rpc_timeout: Optional RPC deadline to set for the RPC call. + """ + await self._client._impl.fail_async_activity( + FailAsyncActivityInput( + id_or_token=self._id_or_token, + error=error, + last_heartbeat_details=last_heartbeat_details, + rpc_metadata=rpc_metadata, + rpc_timeout=rpc_timeout, + data_converter_override=self._data_converter_override, + ), + ) + + async def report_cancellation( + self, + *details: Any, + rpc_metadata: Mapping[str, str | bytes] = {}, + rpc_timeout: timedelta | None = None, + ) -> None: + """Report the activity as cancelled. + + Args: + details: Cancellation details. + rpc_metadata: Headers used on the RPC call. Keys here override + client-level RPC metadata keys. + rpc_timeout: Optional RPC deadline to set for the RPC call. + """ + await self._client._impl.report_cancellation_async_activity( + ReportCancellationAsyncActivityInput( + id_or_token=self._id_or_token, + details=details, + rpc_metadata=rpc_metadata, + rpc_timeout=rpc_timeout, + data_converter_override=self._data_converter_override, + ), + ) + + def with_context(self, context: SerializationContext) -> Self: + """Create a new AsyncActivityHandle with a different serialization context. + + Payloads received by the activity will be decoded and deserialized using a data converter + with :py:class:`ActivitySerializationContext` set as context. If you are using a custom data + converter that makes use of this context then you can use this method to supply matching + context data to the data converter used to serialize and encode the outbound payloads. + """ + data_converter = self._client.data_converter.with_context(context) + if data_converter is self._client.data_converter: + return self + cls = type(self) + if cls.__init__ is not AsyncActivityHandle.__init__: + raise TypeError( + "If you have subclassed AsyncActivityHandle and overridden the __init__ method " + "then you must override with_context to return an instance of your class." + ) + return cls( + self._client, + self._id_or_token, + data_converter, + ) + + +class ActivityHandle(Generic[ReturnType]): + """Handle representing an activity execution not started by a workflow. + + .. warning:: + This API is experimental. + """ + + def __init__( + self, + client: Client, + id: str, + *, + run_id: str | None = None, + result_type: type | None = None, + ) -> None: + """Create activity handle.""" + self._client = client + self._id = id + self._run_id = run_id + self._result_type = result_type + self._known_outcome: ( + temporalio.api.activity.v1.ActivityExecutionOutcome | None + ) = None + + @functools.cached_property + def _data_converter(self) -> temporalio.converter.DataConverter: + return self._client.data_converter.with_context( + ActivitySerializationContext( + namespace=self._client.namespace, + activity_id=self._id, + activity_type=None, + activity_task_queue=None, + is_local=False, + workflow_id=None, + workflow_type=None, + ) + ) + + @property + def id(self) -> str: + """ID of the activity.""" + return self._id + + @property + def run_id(self) -> str | None: + """Run ID of the activity.""" + return self._run_id + + async def result( + self, + *, + rpc_metadata: Mapping[str, str | bytes] = {}, + rpc_timeout: timedelta | None = None, + ) -> ReturnType: + """Wait for result of the activity. + + .. warning:: + This API is experimental. + + The result may already be known if this method has been called before, + in which case no network call is made. Otherwise the result will be + polled for until it is available. + + Args: + rpc_metadata: Headers used on the RPC call. Keys here override + client-level RPC metadata keys. + rpc_timeout: Optional RPC deadline to set for each RPC call. Note: + this is the timeout for each RPC call while polling, not a + timeout for the function as a whole. If an individual RPC + times out, it will be retried until the result is available. + + Returns: + The result of the activity. + + Raises: + ActivityFailureError: If the activity completed with a failure. + RPCError: Activity result could not be fetched for some reason. + """ + await self._poll_until_outcome( + rpc_metadata=rpc_metadata, rpc_timeout=rpc_timeout + ) + + # Convert outcome to failure or value + assert self._known_outcome + if self._known_outcome.HasField("failure"): + raise ActivityFailureError( + cause=await self._data_converter.decode_failure( + self._known_outcome.failure + ), + ) + if not self._known_outcome.result.payloads: + return None # type: ignore + type_hints = [self._result_type] if self._result_type else None + results = await self._data_converter.decode( + self._known_outcome.result.payloads, type_hints + ) + if not results: + return None # type: ignore + elif len(results) > 1: + warnings.warn(f"Expected single activity result, got {len(results)}") + return results[0] + + async def _poll_until_outcome( + self, + rpc_metadata: Mapping[str, str | bytes] = {}, + rpc_timeout: timedelta | None = None, + ) -> None: + """Poll for activity result until it's available.""" + if self._known_outcome: + return + + req = temporalio.api.workflowservice.v1.PollActivityExecutionRequest( + namespace=self._client.namespace, + activity_id=self._id, + run_id=self._run_id or "", + ) + + # Continue polling as long as we have no outcome + while True: + try: + res = await self._client.workflow_service.poll_activity_execution( + req, + retry=True, + metadata=rpc_metadata, + timeout=rpc_timeout, + ) + if res.HasField("outcome"): + self._known_outcome = res.outcome + return + except RPCError as err: + if err.status == RPCStatusCode.DEADLINE_EXCEEDED: + # Deadline exceeded is expected with long polling; retry + continue + elif err.status == RPCStatusCode.CANCELLED: + raise asyncio.CancelledError() from err + else: + raise + except asyncio.CancelledError: + raise + + async def cancel( + self, + *, + reason: str | None = None, + rpc_metadata: Mapping[str, str | bytes] = {}, + rpc_timeout: timedelta | None = None, + ) -> None: + """Request cancellation of the activity. + + .. warning:: + This API is experimental. + + Requesting cancellation of an activity does not automatically transition the activity to + canceled status. If the activity is heartbeating, a :py:class:`exceptions.CancelledError` + exception will be raised when receiving the heartbeat response; if the activity allows this + exception to bubble out, the activity will transition to canceled status. If the activity it + is not heartbeating, this method will have no effect on activity status. + + Args: + reason: Reason for the cancellation. Recorded and available via describe. + rpc_metadata: Headers used on the RPC call. + rpc_timeout: Optional RPC deadline to set for the RPC call. + """ + await self._client._impl.cancel_activity( + CancelActivityInput( + activity_id=self._id, + activity_run_id=self._run_id, + reason=reason, + rpc_metadata=rpc_metadata, + rpc_timeout=rpc_timeout, + ) + ) + + async def terminate( + self, + *, + reason: str | None = None, + rpc_metadata: Mapping[str, str | bytes] = {}, + rpc_timeout: timedelta | None = None, + ) -> None: + """Terminate the activity execution immediately. + + .. warning:: + This API is experimental. + + Termination does not reach the worker and the activity code cannot react to it. + A terminated activity may have a running attempt and will be requested to be + canceled by the server when it heartbeats. + + Args: + reason: Reason for the termination. + rpc_metadata: Headers used on the RPC call. + rpc_timeout: Optional RPC deadline to set for the RPC call. + """ + await self._client._impl.terminate_activity( + TerminateActivityInput( + activity_id=self._id, + activity_run_id=self._run_id, + reason=reason, + rpc_metadata=rpc_metadata, + rpc_timeout=rpc_timeout, + ) + ) + + async def describe( + self, + *, + long_poll_token: bytes | None = None, + rpc_metadata: Mapping[str, str | bytes] = {}, + rpc_timeout: timedelta | None = None, + ) -> ActivityExecutionDescription: + """Describe the activity execution. + + .. warning:: + This API is experimental. + + Args: + long_poll_token: Token from a previous describe response. If provided, + the request will long-poll until the activity state changes. + rpc_metadata: Headers used on the RPC call. + rpc_timeout: Optional RPC deadline to set for the RPC call. + + Returns: + Activity execution description. + """ + return await self._client._impl.describe_activity( + DescribeActivityInput( + activity_id=self._id, + activity_run_id=self._run_id, + long_poll_token=long_poll_token, + rpc_metadata=rpc_metadata, + rpc_timeout=rpc_timeout, + ) + ) diff --git a/temporalio/client/_callback.py b/temporalio/client/_callback.py new file mode 100644 index 000000000..45aa89030 --- /dev/null +++ b/temporalio/client/_callback.py @@ -0,0 +1,5 @@ +from __future__ import annotations + +import temporalio.nexus + +Callback = temporalio.nexus.NexusCallback diff --git a/temporalio/client/_client.py b/temporalio/client/_client.py new file mode 100644 index 000000000..437c9f2b2 --- /dev/null +++ b/temporalio/client/_client.py @@ -0,0 +1,2898 @@ +"""Client support for accessing Temporal.""" + +from __future__ import annotations + +from collections.abc import ( + Awaitable, + Callable, + Mapping, + Sequence, +) +from datetime import timedelta +from typing import ( + TYPE_CHECKING, + Any, + Concatenate, + cast, + overload, +) + +from typing_extensions import Required, Self, TypedDict + +import temporalio.activity +import temporalio.api.common.v1 +import temporalio.api.workflowservice.v1 +import temporalio.common +import temporalio.converter +import temporalio.runtime +import temporalio.service +import temporalio.workflow +from temporalio.service import ( + ConnectConfig, + DnsLoadBalancingConfig, + HttpConnectProxyConfig, + KeepAliveConfig, + RetryConfig, + ServiceClient, + TLSConfig, +) + +from ..common import HeaderCodecBehavior +from ..types import ( + CallableAsyncNoParam, + CallableAsyncSingleParam, + CallableSyncNoParam, + CallableSyncSingleParam, + LocalReturnType, + MethodAsyncNoParam, + MethodAsyncSingleParam, + MultiParamSpec, + ParamType, + ReturnType, + SelfType, +) +from ._activity import ( + ActivityExecutionAsyncIterator, + ActivityExecutionCount, + ActivityHandle, + AsyncActivityHandle, + AsyncActivityIDReference, +) +from ._callback import Callback +from ._impl import _ClientImpl +from ._interceptor import ( + CountActivitiesInput, + CountWorkflowsInput, + CreateScheduleInput, + GetWorkerBuildIdCompatibilityInput, + GetWorkerTaskReachabilityInput, + ListActivitiesInput, + ListSchedulesInput, + ListWorkflowsInput, + OutboundInterceptor, + StartActivityInput, + StartWorkflowInput, + StartWorkflowUpdateWithStartInput, + UpdateWithStartUpdateWorkflowInput, + UpdateWorkerBuildIdCompatibilityInput, +) +from ._schedule import ( + Schedule, + ScheduleAsyncIterator, + ScheduleBackfill, + ScheduleHandle, +) +from ._worker_versioning import ( + BuildIdOp, + TaskReachabilityType, + WorkerBuildIdVersionSets, + WorkerTaskReachability, +) +from ._workflow import ( + WithStartWorkflowOperation, + WorkflowExecutionAsyncIterator, + WorkflowExecutionCount, + WorkflowHandle, + WorkflowUpdateHandle, + WorkflowUpdateStage, +) + +if TYPE_CHECKING: + from ._interceptor import Interceptor + from ._plugin import Plugin + + +class Client: + """Client for accessing Temporal. + + Most users will use :py:meth:`connect` to create a client. The + :py:attr:`service` property provides access to a raw gRPC client. To create + another client, like for a different namespace, :py:func:`Client` may be + directly instantiated with a :py:attr:`service` of another. + + Clients are not thread-safe and should only be used in the event loop they + are first connected in. If a client needs to be used from another thread + than where it was created, make sure the event loop where it was created is + captured, and then call :py:func:`asyncio.run_coroutine_threadsafe` with the + client call and that event loop. + + Clients do not work across forks since runtimes do not work across forks. + """ + + @classmethod + async def connect( + cls, + target_host: str, + *, + namespace: str = "default", + api_key: str | None = None, + data_converter: temporalio.converter.DataConverter = temporalio.converter.DataConverter.default, + plugins: Sequence[Plugin] = [], + interceptors: Sequence[Interceptor] = [], + default_workflow_query_reject_condition: None + | (temporalio.common.QueryRejectCondition) = None, + tls: bool | TLSConfig | None = None, + retry_config: RetryConfig | None = None, + keep_alive_config: KeepAliveConfig | None = KeepAliveConfig.default, + rpc_metadata: Mapping[str, str | bytes] = {}, + identity: str | None = None, + lazy: bool = False, + runtime: temporalio.runtime.Runtime | None = None, + http_connect_proxy_config: HttpConnectProxyConfig | None = None, + dns_load_balancing_config: DnsLoadBalancingConfig | None = None, + header_codec_behavior: HeaderCodecBehavior = HeaderCodecBehavior.NO_CODEC, + ) -> Self: + """Connect to a Temporal server. + + Args: + target_host: ``host:port`` for the Temporal server. For local + development, this is often "localhost:7233". + namespace: Namespace to use for client calls. + api_key: API key for Temporal. This becomes the "Authorization" + HTTP header with "Bearer " prepended. This is only set if RPC + metadata doesn't already have an "authorization" key. + data_converter: Data converter to use for all data conversions + to/from payloads. + plugins: Set of plugins that are chained together to allow + intercepting and modifying client creation and service connection. + The earlier plugins wrap the later ones. + + Any plugins that also implement + :py:class:`temporalio.worker.Plugin` will be used as worker + plugins too so they should not be given when creating a + worker. + interceptors: Set of interceptors that are chained together to allow + intercepting of client calls. The earlier interceptors wrap the + later ones. + + Any interceptors that also implement + :py:class:`temporalio.worker.Interceptor` will be used as worker + interceptors too so they should not be given when creating a + worker. + default_workflow_query_reject_condition: The default rejection + condition for workflow queries if not set during query. See + :py:meth:`WorkflowHandle.query` for details on the rejection + condition. + tls: If ``None``, the default, TLS will be enabled automatically + when ``api_key`` is provided, otherwise TLS is disabled. If + ``False``, do not use TLS. If ``True``, use system default TLS + configuration. If TLS configuration present, that TLS + configuration will be used. + retry_config: Retry configuration for direct service calls (when + opted in) or all high-level calls made by this client (which all + opt-in to retries by default). If unset, a default retry + configuration is used. + keep_alive_config: Keep-alive configuration for the client + connection. Default is to check every 30s and kill the + connection if a response doesn't come back in 15s. Can be set to + ``None`` to disable. + rpc_metadata: Headers to use for all calls to the server. Keys here + can be overriden by per-call RPC metadata keys. + identity: Identity for this client. If unset, a default is created + based on the version of the SDK. + lazy: If true, the client will not connect until the first call is + attempted or a worker is created with it. Lazy clients cannot be + used for workers. + runtime: The runtime for this client, or the default if unset. + http_connect_proxy_config: Configuration for HTTP CONNECT proxy. + dns_load_balancing_config: DNS load balancing configuration for the + client connection. Default is to re-resolve DNS every 30s. Can + be set to ``None`` to disable. Silently disabled when + ``http_connect_proxy_config`` is set, since the two are mutually + exclusive. + header_codec_behavior: Encoding behavior for headers sent by the client. + """ + connect_config = temporalio.service.ConnectConfig( + target_host=target_host, + api_key=api_key, + tls=tls, + retry_config=retry_config, + keep_alive_config=keep_alive_config, + rpc_metadata=rpc_metadata, + identity=identity or "", + lazy=lazy, + runtime=runtime, + http_connect_proxy_config=http_connect_proxy_config, + dns_load_balancing_config=dns_load_balancing_config, + ) + + def make_lambda( + plugin: Plugin, next: Callable[[ConnectConfig], Awaitable[ServiceClient]] + ): + return lambda config: plugin.connect_service_client(config, next) + + next_function = ServiceClient.connect + for plugin in reversed(plugins): + next_function = make_lambda(plugin, next_function) + + service_client = await next_function(connect_config) + + return cls( + service_client, + namespace=namespace, + data_converter=data_converter, + interceptors=interceptors, + default_workflow_query_reject_condition=default_workflow_query_reject_condition, + header_codec_behavior=header_codec_behavior, + plugins=plugins, + ) + + def __init__( + self, + service_client: temporalio.service.ServiceClient, + *, + namespace: str = "default", + data_converter: temporalio.converter.DataConverter = temporalio.converter.DataConverter.default, + plugins: Sequence[Plugin] = [], + interceptors: Sequence[Interceptor] = [], + default_workflow_query_reject_condition: None + | (temporalio.common.QueryRejectCondition) = None, + header_codec_behavior: HeaderCodecBehavior = HeaderCodecBehavior.NO_CODEC, + ): + """Create a Temporal client from a service client. + + See :py:meth:`connect` for details on the parameters. + """ + # Store the config for tracking + config = ClientConfig( + service_client=service_client, + namespace=namespace, + data_converter=data_converter, + plugins=plugins, + interceptors=interceptors, + default_workflow_query_reject_condition=default_workflow_query_reject_condition, + header_codec_behavior=header_codec_behavior, + ) + self._initial_config = config.copy() + + for plugin in plugins: + config = plugin.configure_client(config) + + self._init_from_config(config) + + def _init_from_config(self, config: ClientConfig): + self._config = config + + # Iterate over interceptors in reverse building the impl + self._impl: OutboundInterceptor = _ClientImpl(self) + for interceptor in reversed(list(self._config["interceptors"])): + self._impl = interceptor.intercept_client(self._impl) + + def config(self, *, active_config: bool = False) -> ClientConfig: + """Config, as a dictionary, used to create this client. + + Args: + active_config: If true, return the modified configuration in use rather than the initial one + provided to the client. + + This makes a shallow copy of the config each call. + """ + config = self._config.copy() if active_config else self._initial_config.copy() + config["interceptors"] = list(config["interceptors"]) + return config + + @property + def service_client(self) -> temporalio.service.ServiceClient: + """Raw gRPC service client.""" + return self._config["service_client"] + + @property + def workflow_service(self) -> temporalio.service.WorkflowService: + """Raw gRPC workflow service client.""" + return self._config["service_client"].workflow_service + + @property + def operator_service(self) -> temporalio.service.OperatorService: + """Raw gRPC operator service client.""" + return self._config["service_client"].operator_service + + @property + def test_service(self) -> temporalio.service.TestService: + """Raw gRPC test service client.""" + return self._config["service_client"].test_service + + @property + def namespace(self) -> str: + """Namespace used in calls by this client.""" + return self._config["namespace"] + + @property + def identity(self) -> str: + """Identity used in calls by this client.""" + return self._config["service_client"].config.identity + + @property + def data_converter(self) -> temporalio.converter.DataConverter: + """Data converter used by this client.""" + return self._config["data_converter"] + + @property + def rpc_metadata(self) -> Mapping[str, str | bytes]: + """Headers for every call made by this client. + + Do not use mutate this mapping. Rather, set this property with an + entirely new mapping to change the headers. + """ + return self.service_client.config.rpc_metadata + + @rpc_metadata.setter + def rpc_metadata(self, value: Mapping[str, str | bytes]) -> None: + """Update the headers for this client. + + Do not mutate this mapping after set. Rather, set an entirely new + mapping if changes are needed. + + Raises: + TypeError: the key/value pair is not a valid gRPC ASCII or binary metadata. + All binary metadata must be supplied as bytes, and the key must end in '-bin'. + + .. warning:: + Attempting to set an invalid binary RPC metadata value may leave the client + in an inconsistent state (as well as raise a :py:class:`TypeError`). + """ + # Update config and perform update + # This may raise if the metadata is invalid: + self.service_client.update_rpc_metadata(value) + self.service_client.config.rpc_metadata = value + + @property + def api_key(self) -> str | None: + """API key for every call made by this client.""" + return self.service_client.config.api_key + + @api_key.setter + def api_key(self, value: str | None) -> None: + """Update the API key for this client. + + This is only set if RPCmetadata doesn't already have an "authorization" + key. + """ + # Update config and perform update + self.service_client.config.api_key = value + self.service_client.update_api_key(value) + + # Overload for no-param workflow + @overload + async def start_workflow( + self, + workflow: MethodAsyncNoParam[SelfType, ReturnType], + *, + id: str, + task_queue: str, + execution_timeout: timedelta | None = None, + run_timeout: timedelta | None = None, + task_timeout: timedelta | None = None, + id_reuse_policy: temporalio.common.WorkflowIDReusePolicy = temporalio.common.WorkflowIDReusePolicy.ALLOW_DUPLICATE, + id_conflict_policy: temporalio.common.WorkflowIDConflictPolicy = temporalio.common.WorkflowIDConflictPolicy.UNSPECIFIED, + retry_policy: temporalio.common.RetryPolicy | None = None, + cron_schedule: str = "", + memo: Mapping[str, Any] | None = None, + search_attributes: None + | ( + temporalio.common.TypedSearchAttributes | temporalio.common.SearchAttributes + ) = None, + static_summary: str | None = None, + static_details: str | None = None, + start_delay: timedelta | None = None, + start_signal: str | None = None, + start_signal_args: Sequence[Any] = [], + rpc_metadata: Mapping[str, str | bytes] = {}, + rpc_timeout: timedelta | None = None, + request_eager_start: bool = False, + priority: temporalio.common.Priority = temporalio.common.Priority.default, + versioning_override: temporalio.common.VersioningOverride | None = None, + ) -> WorkflowHandle[SelfType, ReturnType]: ... + + # Overload for single-param workflow + @overload + async def start_workflow( + self, + workflow: MethodAsyncSingleParam[SelfType, ParamType, ReturnType], + arg: ParamType, + *, + id: str, + task_queue: str, + execution_timeout: timedelta | None = None, + run_timeout: timedelta | None = None, + task_timeout: timedelta | None = None, + id_reuse_policy: temporalio.common.WorkflowIDReusePolicy = temporalio.common.WorkflowIDReusePolicy.ALLOW_DUPLICATE, + id_conflict_policy: temporalio.common.WorkflowIDConflictPolicy = temporalio.common.WorkflowIDConflictPolicy.UNSPECIFIED, + retry_policy: temporalio.common.RetryPolicy | None = None, + cron_schedule: str = "", + memo: Mapping[str, Any] | None = None, + search_attributes: None + | ( + temporalio.common.TypedSearchAttributes | temporalio.common.SearchAttributes + ) = None, + static_summary: str | None = None, + static_details: str | None = None, + start_delay: timedelta | None = None, + start_signal: str | None = None, + start_signal_args: Sequence[Any] = [], + rpc_metadata: Mapping[str, str | bytes] = {}, + rpc_timeout: timedelta | None = None, + request_eager_start: bool = False, + priority: temporalio.common.Priority = temporalio.common.Priority.default, + versioning_override: temporalio.common.VersioningOverride | None = None, + ) -> WorkflowHandle[SelfType, ReturnType]: ... + + # Overload for multi-param workflow + @overload + async def start_workflow( + self, + workflow: Callable[ + Concatenate[SelfType, MultiParamSpec], Awaitable[ReturnType] + ], + *, + args: Sequence[Any], + id: str, + task_queue: str, + execution_timeout: timedelta | None = None, + run_timeout: timedelta | None = None, + task_timeout: timedelta | None = None, + id_reuse_policy: temporalio.common.WorkflowIDReusePolicy = temporalio.common.WorkflowIDReusePolicy.ALLOW_DUPLICATE, + id_conflict_policy: temporalio.common.WorkflowIDConflictPolicy = temporalio.common.WorkflowIDConflictPolicy.UNSPECIFIED, + retry_policy: temporalio.common.RetryPolicy | None = None, + cron_schedule: str = "", + memo: Mapping[str, Any] | None = None, + search_attributes: None + | ( + temporalio.common.TypedSearchAttributes | temporalio.common.SearchAttributes + ) = None, + static_summary: str | None = None, + static_details: str | None = None, + start_delay: timedelta | None = None, + start_signal: str | None = None, + start_signal_args: Sequence[Any] = [], + rpc_metadata: Mapping[str, str | bytes] = {}, + rpc_timeout: timedelta | None = None, + request_eager_start: bool = False, + priority: temporalio.common.Priority = temporalio.common.Priority.default, + versioning_override: temporalio.common.VersioningOverride | None = None, + ) -> WorkflowHandle[SelfType, ReturnType]: ... + + # Overload for string-name workflow + @overload + async def start_workflow( + self, + workflow: str, + arg: Any = temporalio.common._arg_unset, + *, + args: Sequence[Any] = [], + id: str, + task_queue: str, + result_type: type | None = None, + execution_timeout: timedelta | None = None, + run_timeout: timedelta | None = None, + task_timeout: timedelta | None = None, + id_reuse_policy: temporalio.common.WorkflowIDReusePolicy = temporalio.common.WorkflowIDReusePolicy.ALLOW_DUPLICATE, + id_conflict_policy: temporalio.common.WorkflowIDConflictPolicy = temporalio.common.WorkflowIDConflictPolicy.UNSPECIFIED, + retry_policy: temporalio.common.RetryPolicy | None = None, + cron_schedule: str = "", + memo: Mapping[str, Any] | None = None, + search_attributes: None + | ( + temporalio.common.TypedSearchAttributes | temporalio.common.SearchAttributes + ) = None, + static_summary: str | None = None, + static_details: str | None = None, + start_delay: timedelta | None = None, + start_signal: str | None = None, + start_signal_args: Sequence[Any] = [], + rpc_metadata: Mapping[str, str | bytes] = {}, + rpc_timeout: timedelta | None = None, + request_eager_start: bool = False, + priority: temporalio.common.Priority = temporalio.common.Priority.default, + versioning_override: temporalio.common.VersioningOverride | None = None, + ) -> WorkflowHandle[Any, Any]: ... + + async def start_workflow( + self, + workflow: str | Callable[..., Awaitable[Any]], + arg: Any = temporalio.common._arg_unset, + *, + args: Sequence[Any] = [], + id: str, + task_queue: str, + result_type: type | None = None, + execution_timeout: timedelta | None = None, + run_timeout: timedelta | None = None, + task_timeout: timedelta | None = None, + id_reuse_policy: temporalio.common.WorkflowIDReusePolicy = temporalio.common.WorkflowIDReusePolicy.ALLOW_DUPLICATE, + id_conflict_policy: temporalio.common.WorkflowIDConflictPolicy = temporalio.common.WorkflowIDConflictPolicy.UNSPECIFIED, + retry_policy: temporalio.common.RetryPolicy | None = None, + cron_schedule: str = "", + memo: Mapping[str, Any] | None = None, + search_attributes: None + | ( + temporalio.common.TypedSearchAttributes | temporalio.common.SearchAttributes + ) = None, + static_summary: str | None = None, + static_details: str | None = None, + start_delay: timedelta | None = None, + start_signal: str | None = None, + start_signal_args: Sequence[Any] = [], + rpc_metadata: Mapping[str, str | bytes] = {}, + rpc_timeout: timedelta | None = None, + request_eager_start: bool = False, + priority: temporalio.common.Priority = temporalio.common.Priority.default, + versioning_override: temporalio.common.VersioningOverride | None = None, + # The following options should not be considered part of the public API. They + # are deliberately not exposed in overloads, and are not subject to any + # backwards compatibility guarantees. + callbacks: Sequence[Callback] = [], + workflow_event_links: Sequence[ + temporalio.api.common.v1.Link.WorkflowEvent + ] = [], + request_id: str | None = None, + stack_level: int = 2, + ) -> WorkflowHandle[Any, Any]: + """Start a workflow and return its handle. + + Args: + workflow: String name or class method decorated with + ``@workflow.run`` for the workflow to start. + arg: Single argument to the workflow. + args: Multiple arguments to the workflow. Cannot be set if arg is. + id: Unique identifier for the workflow execution. + task_queue: Task queue to run the workflow on. + result_type: For string workflows, this can set the specific result + type hint to deserialize into. + execution_timeout: Total workflow execution timeout including + retries and continue as new. + run_timeout: Timeout of a single workflow run. + task_timeout: Timeout of a single workflow task. + id_conflict_policy: Behavior when a workflow is currently running with the same ID. + Default is UNSPECIFIED, which effectively means fail the start attempt. + Set to USE_EXISTING for idempotent deduplication on workflow ID. + Cannot be set if ``id_reuse_policy`` is set to TERMINATE_IF_RUNNING. + id_reuse_policy: Behavior when a closed workflow with the same ID exists. + Default is ALLOW_DUPLICATE. + retry_policy: Retry policy for the workflow. + cron_schedule: See https://docs.temporal.io/docs/content/what-is-a-temporal-cron-job/ + memo: Memo for the workflow. + search_attributes: Search attributes for the workflow. The + dictionary form of this is deprecated, use + :py:class:`temporalio.common.TypedSearchAttributes`. + static_summary: A single-line fixed summary for this workflow execution that may appear + in the UI/CLI. This can be in single-line Temporal markdown format. + static_details: General fixed details for this workflow execution that may appear in + UI/CLI. This can be in Temporal markdown format and can span multiple lines. This is + a fixed value on the workflow that cannot be updated. For details that can be + updated, use :py:meth:`temporalio.workflow.get_current_details` within the workflow. + start_delay: Amount of time to wait before starting the workflow. + This does not work with ``cron_schedule``. + start_signal: If present, this signal is sent as signal-with-start + instead of traditional workflow start. + start_signal_args: Arguments for start_signal if start_signal + present. + rpc_metadata: Headers used on the RPC call. Keys here override + client-level RPC metadata keys. + rpc_timeout: Optional RPC deadline to set for the RPC call. + request_eager_start: Potentially reduce the latency to start this workflow by + encouraging the server to start it on a local worker running with + this same client. + priority: Priority of the workflow execution. + versioning_override: Overrides the versioning behavior for this workflow. + + Returns: + A workflow handle to the started workflow. + + Raises: + temporalio.exceptions.WorkflowAlreadyStartedError: Workflow has + already been started. + RPCError: Workflow could not be started for some other reason. + """ + temporalio.common._warn_on_deprecated_search_attributes( + search_attributes, stack_level=stack_level + ) + name, result_type_from_type_hint = ( + temporalio.workflow._Definition.get_name_and_result_type(workflow) + ) + return await self._impl.start_workflow( + StartWorkflowInput( + workflow=name, + args=temporalio.common._arg_or_args(arg, args), + id=id, + task_queue=task_queue, + execution_timeout=execution_timeout, + run_timeout=run_timeout, + task_timeout=task_timeout, + id_reuse_policy=id_reuse_policy, + id_conflict_policy=id_conflict_policy, + retry_policy=retry_policy, + cron_schedule=cron_schedule, + memo=memo, + search_attributes=search_attributes, + start_delay=start_delay, + versioning_override=versioning_override, + headers={}, + static_summary=static_summary, + static_details=static_details, + start_signal=start_signal, + start_signal_args=start_signal_args, + ret_type=result_type or result_type_from_type_hint, + rpc_metadata=rpc_metadata, + rpc_timeout=rpc_timeout, + request_eager_start=request_eager_start, + priority=priority, + callbacks=callbacks, + workflow_event_links=workflow_event_links, + request_id=request_id, + ) + ) + + # Overload for no-param workflow + @overload + async def execute_workflow( + self, + workflow: MethodAsyncNoParam[SelfType, ReturnType], + *, + id: str, + task_queue: str, + execution_timeout: timedelta | None = None, + run_timeout: timedelta | None = None, + task_timeout: timedelta | None = None, + id_reuse_policy: temporalio.common.WorkflowIDReusePolicy = temporalio.common.WorkflowIDReusePolicy.ALLOW_DUPLICATE, + id_conflict_policy: temporalio.common.WorkflowIDConflictPolicy = temporalio.common.WorkflowIDConflictPolicy.UNSPECIFIED, + retry_policy: temporalio.common.RetryPolicy | None = None, + cron_schedule: str = "", + memo: Mapping[str, Any] | None = None, + search_attributes: None + | ( + temporalio.common.TypedSearchAttributes | temporalio.common.SearchAttributes + ) = None, + static_summary: str | None = None, + static_details: str | None = None, + start_delay: timedelta | None = None, + start_signal: str | None = None, + start_signal_args: Sequence[Any] = [], + rpc_metadata: Mapping[str, str | bytes] = {}, + rpc_timeout: timedelta | None = None, + request_eager_start: bool = False, + priority: temporalio.common.Priority = temporalio.common.Priority.default, + versioning_override: temporalio.common.VersioningOverride | None = None, + ) -> ReturnType: ... + + # Overload for single-param workflow + @overload + async def execute_workflow( + self, + workflow: MethodAsyncSingleParam[SelfType, ParamType, ReturnType], + arg: ParamType, + *, + id: str, + task_queue: str, + execution_timeout: timedelta | None = None, + run_timeout: timedelta | None = None, + task_timeout: timedelta | None = None, + id_reuse_policy: temporalio.common.WorkflowIDReusePolicy = temporalio.common.WorkflowIDReusePolicy.ALLOW_DUPLICATE, + id_conflict_policy: temporalio.common.WorkflowIDConflictPolicy = temporalio.common.WorkflowIDConflictPolicy.UNSPECIFIED, + retry_policy: temporalio.common.RetryPolicy | None = None, + cron_schedule: str = "", + memo: Mapping[str, Any] | None = None, + search_attributes: None + | ( + temporalio.common.TypedSearchAttributes | temporalio.common.SearchAttributes + ) = None, + static_summary: str | None = None, + static_details: str | None = None, + start_delay: timedelta | None = None, + start_signal: str | None = None, + start_signal_args: Sequence[Any] = [], + rpc_metadata: Mapping[str, str | bytes] = {}, + rpc_timeout: timedelta | None = None, + request_eager_start: bool = False, + priority: temporalio.common.Priority = temporalio.common.Priority.default, + versioning_override: temporalio.common.VersioningOverride | None = None, + ) -> ReturnType: ... + + # Overload for multi-param workflow + @overload + async def execute_workflow( + self, + workflow: Callable[ + Concatenate[SelfType, MultiParamSpec], Awaitable[ReturnType] + ], + *, + args: Sequence[Any], + id: str, + task_queue: str, + execution_timeout: timedelta | None = None, + run_timeout: timedelta | None = None, + task_timeout: timedelta | None = None, + id_reuse_policy: temporalio.common.WorkflowIDReusePolicy = temporalio.common.WorkflowIDReusePolicy.ALLOW_DUPLICATE, + id_conflict_policy: temporalio.common.WorkflowIDConflictPolicy = temporalio.common.WorkflowIDConflictPolicy.UNSPECIFIED, + retry_policy: temporalio.common.RetryPolicy | None = None, + cron_schedule: str = "", + memo: Mapping[str, Any] | None = None, + search_attributes: None + | ( + temporalio.common.TypedSearchAttributes | temporalio.common.SearchAttributes + ) = None, + static_summary: str | None = None, + static_details: str | None = None, + start_delay: timedelta | None = None, + start_signal: str | None = None, + start_signal_args: Sequence[Any] = [], + rpc_metadata: Mapping[str, str | bytes] = {}, + rpc_timeout: timedelta | None = None, + request_eager_start: bool = False, + priority: temporalio.common.Priority = temporalio.common.Priority.default, + versioning_override: temporalio.common.VersioningOverride | None = None, + ) -> ReturnType: ... + + # Overload for string-name workflow + @overload + async def execute_workflow( + self, + workflow: str, + arg: Any = temporalio.common._arg_unset, + *, + args: Sequence[Any] = [], + id: str, + task_queue: str, + result_type: type | None = None, + execution_timeout: timedelta | None = None, + run_timeout: timedelta | None = None, + task_timeout: timedelta | None = None, + id_reuse_policy: temporalio.common.WorkflowIDReusePolicy = temporalio.common.WorkflowIDReusePolicy.ALLOW_DUPLICATE, + id_conflict_policy: temporalio.common.WorkflowIDConflictPolicy = temporalio.common.WorkflowIDConflictPolicy.UNSPECIFIED, + retry_policy: temporalio.common.RetryPolicy | None = None, + cron_schedule: str = "", + memo: Mapping[str, Any] | None = None, + search_attributes: None + | ( + temporalio.common.TypedSearchAttributes | temporalio.common.SearchAttributes + ) = None, + static_summary: str | None = None, + static_details: str | None = None, + start_delay: timedelta | None = None, + start_signal: str | None = None, + start_signal_args: Sequence[Any] = [], + rpc_metadata: Mapping[str, str | bytes] = {}, + rpc_timeout: timedelta | None = None, + request_eager_start: bool = False, + priority: temporalio.common.Priority = temporalio.common.Priority.default, + versioning_override: temporalio.common.VersioningOverride | None = None, + ) -> Any: ... + + async def execute_workflow( + self, + workflow: str | Callable[..., Awaitable[Any]], + arg: Any = temporalio.common._arg_unset, + *, + args: Sequence[Any] = [], + id: str, + task_queue: str, + result_type: type | None = None, + execution_timeout: timedelta | None = None, + run_timeout: timedelta | None = None, + task_timeout: timedelta | None = None, + id_reuse_policy: temporalio.common.WorkflowIDReusePolicy = temporalio.common.WorkflowIDReusePolicy.ALLOW_DUPLICATE, + id_conflict_policy: temporalio.common.WorkflowIDConflictPolicy = temporalio.common.WorkflowIDConflictPolicy.UNSPECIFIED, + retry_policy: temporalio.common.RetryPolicy | None = None, + cron_schedule: str = "", + memo: Mapping[str, Any] | None = None, + search_attributes: None + | ( + temporalio.common.TypedSearchAttributes | temporalio.common.SearchAttributes + ) = None, + static_summary: str | None = None, + static_details: str | None = None, + start_delay: timedelta | None = None, + start_signal: str | None = None, + start_signal_args: Sequence[Any] = [], + rpc_metadata: Mapping[str, str | bytes] = {}, + rpc_timeout: timedelta | None = None, + request_eager_start: bool = False, + priority: temporalio.common.Priority = temporalio.common.Priority.default, + versioning_override: temporalio.common.VersioningOverride | None = None, + ) -> Any: + """Start a workflow and wait for completion. + + This is a shortcut for :py:meth:`start_workflow` + + :py:meth:`WorkflowHandle.result`. + """ + return await ( + # We have to tell MyPy to ignore errors here because we want to call + # the non-@overload form of this and MyPy does not support that + await self.start_workflow( # type: ignore + workflow, # type: ignore[arg-type] + arg, + args=args, + task_queue=task_queue, + result_type=result_type, + id=id, + execution_timeout=execution_timeout, + run_timeout=run_timeout, + task_timeout=task_timeout, + id_reuse_policy=id_reuse_policy, + id_conflict_policy=id_conflict_policy, + retry_policy=retry_policy, + cron_schedule=cron_schedule, + memo=memo, + search_attributes=search_attributes, + static_summary=static_summary, + static_details=static_details, + start_delay=start_delay, + start_signal=start_signal, + start_signal_args=start_signal_args, + rpc_metadata=rpc_metadata, + rpc_timeout=rpc_timeout, + request_eager_start=request_eager_start, + priority=priority, + versioning_override=versioning_override, + stack_level=3, + ) + ).result() + + def get_workflow_handle( + self, + workflow_id: str, + *, + run_id: str | None = None, + first_execution_run_id: str | None = None, + result_type: type | None = None, + ) -> WorkflowHandle[Any, Any]: + """Get a workflow handle to an existing workflow by its ID. + + Args: + workflow_id: Workflow ID to get a handle to. + run_id: Run ID that will be used for all calls. + first_execution_run_id: First execution run ID used for cancellation + and termination. + result_type: The result type to deserialize into if known. + + Returns: + The workflow handle. + """ + return WorkflowHandle( + self, + workflow_id, + run_id=run_id, + result_run_id=run_id, + first_execution_run_id=first_execution_run_id, + result_type=result_type, + ) + + def get_workflow_handle_for( + self, + workflow: ( + MethodAsyncNoParam[SelfType, ReturnType] + | MethodAsyncSingleParam[SelfType, Any, ReturnType] + ), + workflow_id: str, + *, + run_id: str | None = None, + first_execution_run_id: str | None = None, + ) -> WorkflowHandle[SelfType, ReturnType]: + """Get a typed workflow handle to an existing workflow by its ID. + + This is the same as :py:meth:`get_workflow_handle` but typed. + + Args: + workflow: The workflow run method to use for typing the handle. + workflow_id: Workflow ID to get a handle to. + run_id: Run ID that will be used for all calls. + first_execution_run_id: First execution run ID used for cancellation + and termination. + + Returns: + The workflow handle. + """ + defn = temporalio.workflow._Definition.must_from_run_fn(workflow) + return self.get_workflow_handle( + workflow_id, + run_id=run_id, + first_execution_run_id=first_execution_run_id, + result_type=defn.ret_type, + ) + + # Overload for no-param update + @overload + async def execute_update_with_start_workflow( + self, + update: temporalio.workflow.UpdateMethodMultiParam[[SelfType], LocalReturnType], + *, + start_workflow_operation: WithStartWorkflowOperation[SelfType, Any], + id: str | None = None, + rpc_metadata: Mapping[str, str | bytes] = {}, + rpc_timeout: timedelta | None = None, + ) -> LocalReturnType: ... + + # Overload for single-param update + @overload + async def execute_update_with_start_workflow( + self, + update: temporalio.workflow.UpdateMethodMultiParam[ + [SelfType, ParamType], LocalReturnType + ], + arg: ParamType, + *, + start_workflow_operation: WithStartWorkflowOperation[SelfType, Any], + id: str | None = None, + rpc_metadata: Mapping[str, str | bytes] = {}, + rpc_timeout: timedelta | None = None, + ) -> LocalReturnType: ... + + # Overload for multi-param update + @overload + async def execute_update_with_start_workflow( + self, + update: temporalio.workflow.UpdateMethodMultiParam[ + MultiParamSpec, LocalReturnType + ], + *, + args: MultiParamSpec.args, # type: ignore + start_workflow_operation: WithStartWorkflowOperation[SelfType, Any], + id: str | None = None, + rpc_metadata: Mapping[str, str | bytes] = {}, + rpc_timeout: timedelta | None = None, + ) -> LocalReturnType: ... + + # Overload for string-name update + @overload + async def execute_update_with_start_workflow( + self, + update: str, + arg: Any = temporalio.common._arg_unset, + *, + start_workflow_operation: WithStartWorkflowOperation[Any, Any], + args: Sequence[Any] = [], + id: str | None = None, + result_type: type | None = None, + rpc_metadata: Mapping[str, str | bytes] = {}, + rpc_timeout: timedelta | None = None, + ) -> Any: ... + + async def execute_update_with_start_workflow( + self, + update: str | Callable, + arg: Any = temporalio.common._arg_unset, + *, + start_workflow_operation: WithStartWorkflowOperation[Any, Any], + args: Sequence[Any] = [], + id: str | None = None, + result_type: type | None = None, + rpc_metadata: Mapping[str, str | bytes] = {}, + rpc_timeout: timedelta | None = None, + ) -> Any: + """Send an update-with-start request and wait for the update to complete. + + A WorkflowIDConflictPolicy must be set in the start_workflow_operation. If the + specified workflow execution is not running, a new workflow execution is started + and the update is sent in the first workflow task. Alternatively if the specified + workflow execution is running then, if the WorkflowIDConflictPolicy is + USE_EXISTING, the update is issued against the specified workflow, and if the + WorkflowIDConflictPolicy is FAIL, an error is returned. This call will block until + the update has completed, and return the update result. Note that this means that + the call will not return successfully until the update has been delivered to a + worker. + + Args: + update: Update function or name on the workflow. arg: Single argument to the + update. + args: Multiple arguments to the update. Cannot be set if arg is. + start_workflow_operation: a WithStartWorkflowOperation definining the + WorkflowIDConflictPolicy and how to start the workflow in the event that a + workflow is started. + id: ID of the update. If not set, the default is a new UUID. + result_type: For string updates, this can set the specific result + type hint to deserialize into. + rpc_metadata: Headers used on the RPC call. Keys here override + client-level RPC metadata keys. + rpc_timeout: Optional RPC deadline to set for the RPC call. + + Raises: + WorkflowUpdateFailedError: If the update failed. + WorkflowUpdateRPCTimeoutOrCancelledError: This update call timed out + or was cancelled. This doesn't mean the update itself was timed out or + cancelled. + + RPCError: There was some issue starting the workflow or sending the update to + the workflow. + """ + handle = await self._start_update_with_start( + update, + arg, + args=args, + start_workflow_operation=start_workflow_operation, + wait_for_stage=WorkflowUpdateStage.COMPLETED, + id=id, + result_type=result_type, + rpc_metadata=rpc_metadata, + rpc_timeout=rpc_timeout, + ) + return await handle.result() + + # Overload for no-param start update + @overload + async def start_update_with_start_workflow( + self, + update: temporalio.workflow.UpdateMethodMultiParam[[SelfType], LocalReturnType], + *, + start_workflow_operation: WithStartWorkflowOperation[SelfType, Any], + wait_for_stage: WorkflowUpdateStage, + id: str | None = None, + rpc_metadata: Mapping[str, str | bytes] = {}, + rpc_timeout: timedelta | None = None, + ) -> WorkflowUpdateHandle[LocalReturnType]: ... + + # Overload for single-param start update + @overload + async def start_update_with_start_workflow( + self, + update: temporalio.workflow.UpdateMethodMultiParam[ + [SelfType, ParamType], LocalReturnType + ], + arg: ParamType, + *, + start_workflow_operation: WithStartWorkflowOperation[SelfType, Any], + wait_for_stage: WorkflowUpdateStage, + id: str | None = None, + rpc_metadata: Mapping[str, str | bytes] = {}, + rpc_timeout: timedelta | None = None, + ) -> WorkflowUpdateHandle[LocalReturnType]: ... + + # Overload for multi-param start update + @overload + async def start_update_with_start_workflow( + self, + update: temporalio.workflow.UpdateMethodMultiParam[ + MultiParamSpec, LocalReturnType + ], + *, + args: MultiParamSpec.args, # type: ignore + start_workflow_operation: WithStartWorkflowOperation[SelfType, Any], + wait_for_stage: WorkflowUpdateStage, + id: str | None = None, + rpc_metadata: Mapping[str, str | bytes] = {}, + rpc_timeout: timedelta | None = None, + ) -> WorkflowUpdateHandle[LocalReturnType]: ... + + # Overload for string-name start update + @overload + async def start_update_with_start_workflow( + self, + update: str, + arg: Any = temporalio.common._arg_unset, + *, + start_workflow_operation: WithStartWorkflowOperation[Any, Any], + wait_for_stage: WorkflowUpdateStage, + args: Sequence[Any] = [], + id: str | None = None, + result_type: type | None = None, + rpc_metadata: Mapping[str, str | bytes] = {}, + rpc_timeout: timedelta | None = None, + ) -> WorkflowUpdateHandle[Any]: ... + + async def start_update_with_start_workflow( + self, + update: str | Callable, + arg: Any = temporalio.common._arg_unset, + *, + start_workflow_operation: WithStartWorkflowOperation[Any, Any], + wait_for_stage: WorkflowUpdateStage, + args: Sequence[Any] = [], + id: str | None = None, + result_type: type | None = None, + rpc_metadata: Mapping[str, str | bytes] = {}, + rpc_timeout: timedelta | None = None, + ) -> WorkflowUpdateHandle[Any]: + """Send an update-with-start request and wait for it to be accepted. + + A WorkflowIDConflictPolicy must be set in the start_workflow_operation. If the + specified workflow execution is not running, a new workflow execution is started + and the update is sent in the first workflow task. Alternatively if the specified + workflow execution is running then, if the WorkflowIDConflictPolicy is + USE_EXISTING, the update is issued against the specified workflow, and if the + WorkflowIDConflictPolicy is FAIL, an error is returned. This call will block until + the update has been accepted, and return a WorkflowUpdateHandle. Note that this + means that the call will not return successfully until the update has been + delivered to a worker. + + Args: + update: Update function or name on the workflow. arg: Single argument to the + update. + args: Multiple arguments to the update. Cannot be set if arg is. + start_workflow_operation: a WithStartWorkflowOperation definining the + WorkflowIDConflictPolicy and how to start the workflow in the event that a + workflow is started. + wait_for_stage: Required stage to wait until returning: either ACCEPTED or + COMPLETED. ADMITTED is not currently supported. See + https://docs.temporal.io/workflows#update for more details. + id: ID of the update. If not set, the default is a new UUID. + result_type: For string updates, this can set the specific result + type hint to deserialize into. + rpc_metadata: Headers used on the RPC call. Keys here override + client-level RPC metadata keys. + rpc_timeout: Optional RPC deadline to set for the RPC call. + + Raises: + WorkflowUpdateFailedError: If the update failed. + WorkflowUpdateRPCTimeoutOrCancelledError: This update call timed out + or was cancelled. This doesn't mean the update itself was timed out or + cancelled. + + RPCError: There was some issue starting the workflow or sending the update to + the workflow. + """ + return await self._start_update_with_start( + update, + arg, + wait_for_stage=wait_for_stage, + args=args, + id=id, + result_type=result_type, + start_workflow_operation=start_workflow_operation, + rpc_metadata=rpc_metadata, + rpc_timeout=rpc_timeout, + ) + + async def _start_update_with_start( + self, + update: str | Callable, + arg: Any = temporalio.common._arg_unset, + *, + wait_for_stage: WorkflowUpdateStage, + args: Sequence[Any] = [], + id: str | None = None, + result_type: type | None = None, + start_workflow_operation: WithStartWorkflowOperation[SelfType, ReturnType], + rpc_metadata: Mapping[str, str | bytes] = {}, + rpc_timeout: timedelta | None = None, + ) -> WorkflowUpdateHandle[Any]: + if wait_for_stage == WorkflowUpdateStage.ADMITTED: + raise ValueError("ADMITTED wait stage not supported") + + if start_workflow_operation._used: + raise RuntimeError("WithStartWorkflowOperation cannot be reused") + start_workflow_operation._used = True + + update_name, result_type_from_type_hint = ( + temporalio.workflow._UpdateDefinition.get_name_and_result_type(update) + ) + + update_input = UpdateWithStartUpdateWorkflowInput( + update_id=id, + update=update_name, + args=temporalio.common._arg_or_args(arg, args), + headers={}, + ret_type=result_type or result_type_from_type_hint, + rpc_metadata=rpc_metadata, + rpc_timeout=rpc_timeout, + wait_for_stage=wait_for_stage, + ) + + def on_start( + start_response: temporalio.api.workflowservice.v1.StartWorkflowExecutionResponse, + ): + start_workflow_operation._workflow_handle.set_result( + WorkflowHandle( + self, + start_workflow_operation._start_workflow_input.id, + first_execution_run_id=start_response.run_id, + result_run_id=start_response.run_id, + result_type=start_workflow_operation._start_workflow_input.ret_type, + ) + ) + + def on_start_error( + error: BaseException, + ): + start_workflow_operation._workflow_handle.set_exception(error) + + input = StartWorkflowUpdateWithStartInput( + start_workflow_input=start_workflow_operation._start_workflow_input, + update_workflow_input=update_input, + _on_start=on_start, + _on_start_error=on_start_error, + ) + + return await self._impl.start_update_with_start_workflow(input) + + def list_workflows( + self, + query: str | None = None, + *, + limit: int | None = None, + page_size: int = 1000, + next_page_token: bytes | None = None, + rpc_metadata: Mapping[str, str | bytes] = {}, + rpc_timeout: timedelta | None = None, + ) -> WorkflowExecutionAsyncIterator: + """List workflows. + + This does not make a request until the first iteration is attempted. + Therefore any errors will not occur until then. + + Args: + query: A Temporal visibility list filter. See Temporal documentation + concerning visibility list filters including behavior when left + unset. + limit: Maximum number of workflows to return. If unset, all + workflows are returned. Only applies if using the + returned :py:class:`WorkflowExecutionAsyncIterator`. + as an async iterator. + page_size: Maximum number of results for each page. + next_page_token: A previously obtained next page token if doing + pagination. Usually not needed as the iterator automatically + starts from the beginning. + rpc_metadata: Headers used on each RPC call. Keys here override + client-level RPC metadata keys. + rpc_timeout: Optional RPC deadline to set for each RPC call. + + Returns: + An async iterator that can be used with ``async for``. + """ + return self._impl.list_workflows( + ListWorkflowsInput( + query=query, + page_size=page_size, + next_page_token=next_page_token, + rpc_metadata=rpc_metadata, + rpc_timeout=rpc_timeout, + limit=limit, + ) + ) + + async def count_workflows( + self, + query: str | None = None, + rpc_metadata: Mapping[str, str | bytes] = {}, + rpc_timeout: timedelta | None = None, + ) -> WorkflowExecutionCount: + """Count workflows. + + Args: + query: A Temporal visibility filter. See Temporal documentation + concerning visibility list filters. + rpc_metadata: Headers used on each RPC call. Keys here override + client-level RPC metadata keys. + rpc_timeout: Optional RPC deadline to set for each RPC call. + + Returns: + Count of workflows. + """ + return await self._impl.count_workflows( + CountWorkflowsInput( + query=query, rpc_metadata=rpc_metadata, rpc_timeout=rpc_timeout + ) + ) + + # async no-param + @overload + async def start_activity( + self, + activity: CallableAsyncNoParam[ReturnType], + *, + id: str, + task_queue: str, + schedule_to_close_timeout: timedelta | None = None, + schedule_to_start_timeout: timedelta | None = None, + start_to_close_timeout: timedelta | None = None, + heartbeat_timeout: timedelta | None = None, + id_reuse_policy: temporalio.common.ActivityIDReusePolicy = temporalio.common.ActivityIDReusePolicy.ALLOW_DUPLICATE, + id_conflict_policy: temporalio.common.ActivityIDConflictPolicy = temporalio.common.ActivityIDConflictPolicy.FAIL, + retry_policy: temporalio.common.RetryPolicy | None = None, + search_attributes: temporalio.common.TypedSearchAttributes | None = None, + summary: str | None = None, + priority: temporalio.common.Priority = temporalio.common.Priority.default, + start_delay: timedelta | None = None, + rpc_metadata: Mapping[str, str | bytes] = {}, + rpc_timeout: timedelta | None = None, + ) -> ActivityHandle[ReturnType]: ... + + # sync no-param + @overload + async def start_activity( + self, + activity: CallableSyncNoParam[ReturnType], + *, + id: str, + task_queue: str, + schedule_to_close_timeout: timedelta | None = None, + schedule_to_start_timeout: timedelta | None = None, + start_to_close_timeout: timedelta | None = None, + heartbeat_timeout: timedelta | None = None, + id_reuse_policy: temporalio.common.ActivityIDReusePolicy = temporalio.common.ActivityIDReusePolicy.ALLOW_DUPLICATE, + id_conflict_policy: temporalio.common.ActivityIDConflictPolicy = temporalio.common.ActivityIDConflictPolicy.FAIL, + retry_policy: temporalio.common.RetryPolicy | None = None, + search_attributes: temporalio.common.TypedSearchAttributes | None = None, + summary: str | None = None, + priority: temporalio.common.Priority = temporalio.common.Priority.default, + start_delay: timedelta | None = None, + rpc_metadata: Mapping[str, str | bytes] = {}, + rpc_timeout: timedelta | None = None, + ) -> ActivityHandle[ReturnType]: ... + + # async single-param + @overload + async def start_activity( + self, + activity: CallableAsyncSingleParam[ParamType, ReturnType], + arg: ParamType, + *, + id: str, + task_queue: str, + schedule_to_close_timeout: timedelta | None = None, + schedule_to_start_timeout: timedelta | None = None, + start_to_close_timeout: timedelta | None = None, + heartbeat_timeout: timedelta | None = None, + id_reuse_policy: temporalio.common.ActivityIDReusePolicy = temporalio.common.ActivityIDReusePolicy.ALLOW_DUPLICATE, + id_conflict_policy: temporalio.common.ActivityIDConflictPolicy = temporalio.common.ActivityIDConflictPolicy.FAIL, + retry_policy: temporalio.common.RetryPolicy | None = None, + search_attributes: temporalio.common.TypedSearchAttributes | None = None, + summary: str | None = None, + priority: temporalio.common.Priority = temporalio.common.Priority.default, + start_delay: timedelta | None = None, + rpc_metadata: Mapping[str, str | bytes] = {}, + rpc_timeout: timedelta | None = None, + ) -> ActivityHandle[ReturnType]: ... + + # sync single-param + @overload + async def start_activity( + self, + activity: CallableSyncSingleParam[ParamType, ReturnType], + arg: ParamType, + *, + id: str, + task_queue: str, + schedule_to_close_timeout: timedelta | None = None, + schedule_to_start_timeout: timedelta | None = None, + start_to_close_timeout: timedelta | None = None, + heartbeat_timeout: timedelta | None = None, + id_reuse_policy: temporalio.common.ActivityIDReusePolicy = temporalio.common.ActivityIDReusePolicy.ALLOW_DUPLICATE, + id_conflict_policy: temporalio.common.ActivityIDConflictPolicy = temporalio.common.ActivityIDConflictPolicy.FAIL, + retry_policy: temporalio.common.RetryPolicy | None = None, + search_attributes: temporalio.common.TypedSearchAttributes | None = None, + summary: str | None = None, + priority: temporalio.common.Priority = temporalio.common.Priority.default, + start_delay: timedelta | None = None, + rpc_metadata: Mapping[str, str | bytes] = {}, + rpc_timeout: timedelta | None = None, + ) -> ActivityHandle[ReturnType]: ... + + # async multi-param + @overload + async def start_activity( + self, + activity: Callable[..., Awaitable[ReturnType]], + *, + args: Sequence[Any], + id: str, + task_queue: str, + schedule_to_close_timeout: timedelta | None = None, + schedule_to_start_timeout: timedelta | None = None, + start_to_close_timeout: timedelta | None = None, + heartbeat_timeout: timedelta | None = None, + id_reuse_policy: temporalio.common.ActivityIDReusePolicy = temporalio.common.ActivityIDReusePolicy.ALLOW_DUPLICATE, + id_conflict_policy: temporalio.common.ActivityIDConflictPolicy = temporalio.common.ActivityIDConflictPolicy.FAIL, + retry_policy: temporalio.common.RetryPolicy | None = None, + search_attributes: temporalio.common.TypedSearchAttributes | None = None, + summary: str | None = None, + priority: temporalio.common.Priority = temporalio.common.Priority.default, + start_delay: timedelta | None = None, + rpc_metadata: Mapping[str, str | bytes] = {}, + rpc_timeout: timedelta | None = None, + ) -> ActivityHandle[ReturnType]: ... + + # sync multi-param + @overload + async def start_activity( + self, + activity: Callable[..., ReturnType], + *, + args: Sequence[Any], + id: str, + task_queue: str, + schedule_to_close_timeout: timedelta | None = None, + schedule_to_start_timeout: timedelta | None = None, + start_to_close_timeout: timedelta | None = None, + heartbeat_timeout: timedelta | None = None, + id_reuse_policy: temporalio.common.ActivityIDReusePolicy = temporalio.common.ActivityIDReusePolicy.ALLOW_DUPLICATE, + id_conflict_policy: temporalio.common.ActivityIDConflictPolicy = temporalio.common.ActivityIDConflictPolicy.FAIL, + retry_policy: temporalio.common.RetryPolicy | None = None, + search_attributes: temporalio.common.TypedSearchAttributes | None = None, + summary: str | None = None, + priority: temporalio.common.Priority = temporalio.common.Priority.default, + start_delay: timedelta | None = None, + rpc_metadata: Mapping[str, str | bytes] = {}, + rpc_timeout: timedelta | None = None, + ) -> ActivityHandle[ReturnType]: ... + + # string name + @overload + async def start_activity( + self, + activity: str, + arg: Any = temporalio.common._arg_unset, + *, + args: Sequence[Any] = [], + id: str, + task_queue: str, + result_type: type | None = None, + schedule_to_close_timeout: timedelta | None = None, + schedule_to_start_timeout: timedelta | None = None, + start_to_close_timeout: timedelta | None = None, + heartbeat_timeout: timedelta | None = None, + id_reuse_policy: temporalio.common.ActivityIDReusePolicy = temporalio.common.ActivityIDReusePolicy.ALLOW_DUPLICATE, + id_conflict_policy: temporalio.common.ActivityIDConflictPolicy = temporalio.common.ActivityIDConflictPolicy.FAIL, + retry_policy: temporalio.common.RetryPolicy | None = None, + search_attributes: temporalio.common.TypedSearchAttributes | None = None, + summary: str | None = None, + priority: temporalio.common.Priority = temporalio.common.Priority.default, + start_delay: timedelta | None = None, + rpc_metadata: Mapping[str, str | bytes] = {}, + rpc_timeout: timedelta | None = None, + ) -> ActivityHandle[Any]: ... + + async def start_activity( + self, + activity: ( + str | Callable[..., Awaitable[ReturnType]] | Callable[..., ReturnType] + ), + arg: Any = temporalio.common._arg_unset, + *, + args: Sequence[Any] = [], + id: str, + task_queue: str, + result_type: type | None = None, + # Either schedule_to_close_timeout or start_to_close_timeout must be present + schedule_to_close_timeout: timedelta | None = None, + schedule_to_start_timeout: timedelta | None = None, + start_to_close_timeout: timedelta | None = None, + heartbeat_timeout: timedelta | None = None, + id_reuse_policy: temporalio.common.ActivityIDReusePolicy = temporalio.common.ActivityIDReusePolicy.ALLOW_DUPLICATE, + id_conflict_policy: temporalio.common.ActivityIDConflictPolicy = temporalio.common.ActivityIDConflictPolicy.FAIL, + retry_policy: temporalio.common.RetryPolicy | None = None, + search_attributes: temporalio.common.TypedSearchAttributes | None = None, + summary: str | None = None, + priority: temporalio.common.Priority = temporalio.common.Priority.default, + start_delay: timedelta | None = None, + rpc_metadata: Mapping[str, str | bytes] = {}, + rpc_timeout: timedelta | None = None, + ) -> ActivityHandle[ReturnType]: + """Start an activity and return its handle. + + .. warning:: + This API is experimental. + + Args: + activity: String name or callable activity function to execute. + arg: Single argument to the activity. + args: Multiple arguments to the activity. Cannot be set if arg is. + id: Unique identifier for the activity. Required. + task_queue: Task queue to send the activity to. + result_type: For string name activities, optional type to deserialize result into. + schedule_to_close_timeout: Total time allowed for the activity from schedule to completion. + schedule_to_start_timeout: Time allowed for the activity to sit in the task queue. + start_to_close_timeout: Time allowed for a single execution attempt. + heartbeat_timeout: Time between heartbeats before the activity is considered failed. + id_reuse_policy: How to handle reusing activity IDs from closed activities. + Default is ALLOW_DUPLICATE. + id_conflict_policy: How to handle activity ID conflicts with running activities. + Default is FAIL. + retry_policy: Retry policy for the activity. + search_attributes: Search attributes for the activity. + summary: A single-line fixed summary for this activity that may appear + in the UI/CLI. This can be in single-line Temporal markdown format. + priority: Priority of the activity execution. + start_delay: Time to wait before dispatching the activity. + This delay is not applied to retry attempts. + rpc_metadata: Headers used on the RPC call. + rpc_timeout: Optional RPC deadline to set for the RPC call. + + Returns: + A handle to the started activity. + """ + name, result_type_from_type_annotation = ( + temporalio.activity._Definition.get_name_and_result_type(activity) + ) + return await self._impl.start_activity( + StartActivityInput( + activity_type=name, + args=temporalio.common._arg_or_args(arg, args), + id=id, + task_queue=task_queue, + result_type=result_type or result_type_from_type_annotation, + schedule_to_close_timeout=schedule_to_close_timeout, + schedule_to_start_timeout=schedule_to_start_timeout, + start_to_close_timeout=start_to_close_timeout, + heartbeat_timeout=heartbeat_timeout, + id_reuse_policy=id_reuse_policy, + id_conflict_policy=id_conflict_policy, + retry_policy=retry_policy, + search_attributes=search_attributes, + summary=summary, + start_delay=start_delay, + headers={}, + rpc_metadata=rpc_metadata, + rpc_timeout=rpc_timeout, + priority=priority, + ) + ) + + # async no-param + @overload + async def execute_activity( + self, + activity: CallableAsyncNoParam[ReturnType], + *, + id: str, + task_queue: str, + schedule_to_close_timeout: timedelta | None = None, + schedule_to_start_timeout: timedelta | None = None, + start_to_close_timeout: timedelta | None = None, + heartbeat_timeout: timedelta | None = None, + id_reuse_policy: temporalio.common.ActivityIDReusePolicy = temporalio.common.ActivityIDReusePolicy.ALLOW_DUPLICATE, + id_conflict_policy: temporalio.common.ActivityIDConflictPolicy = temporalio.common.ActivityIDConflictPolicy.FAIL, + retry_policy: temporalio.common.RetryPolicy | None = None, + search_attributes: temporalio.common.TypedSearchAttributes | None = None, + summary: str | None = None, + priority: temporalio.common.Priority = temporalio.common.Priority.default, + start_delay: timedelta | None = None, + rpc_metadata: Mapping[str, str | bytes] = {}, + rpc_timeout: timedelta | None = None, + ) -> ReturnType: ... + + # sync no-param + @overload + async def execute_activity( + self, + activity: CallableSyncNoParam[ReturnType], + *, + id: str, + task_queue: str, + schedule_to_close_timeout: timedelta | None = None, + schedule_to_start_timeout: timedelta | None = None, + start_to_close_timeout: timedelta | None = None, + heartbeat_timeout: timedelta | None = None, + id_reuse_policy: temporalio.common.ActivityIDReusePolicy = temporalio.common.ActivityIDReusePolicy.ALLOW_DUPLICATE, + id_conflict_policy: temporalio.common.ActivityIDConflictPolicy = temporalio.common.ActivityIDConflictPolicy.FAIL, + retry_policy: temporalio.common.RetryPolicy | None = None, + search_attributes: temporalio.common.TypedSearchAttributes | None = None, + summary: str | None = None, + priority: temporalio.common.Priority = temporalio.common.Priority.default, + start_delay: timedelta | None = None, + rpc_metadata: Mapping[str, str | bytes] = {}, + rpc_timeout: timedelta | None = None, + ) -> ReturnType: ... + + # async single-param + @overload + async def execute_activity( + self, + activity: CallableAsyncSingleParam[ParamType, ReturnType], + arg: ParamType, + *, + id: str, + task_queue: str, + schedule_to_close_timeout: timedelta | None = None, + schedule_to_start_timeout: timedelta | None = None, + start_to_close_timeout: timedelta | None = None, + heartbeat_timeout: timedelta | None = None, + id_reuse_policy: temporalio.common.ActivityIDReusePolicy = temporalio.common.ActivityIDReusePolicy.ALLOW_DUPLICATE, + id_conflict_policy: temporalio.common.ActivityIDConflictPolicy = temporalio.common.ActivityIDConflictPolicy.FAIL, + retry_policy: temporalio.common.RetryPolicy | None = None, + search_attributes: temporalio.common.TypedSearchAttributes | None = None, + summary: str | None = None, + priority: temporalio.common.Priority = temporalio.common.Priority.default, + start_delay: timedelta | None = None, + rpc_metadata: Mapping[str, str | bytes] = {}, + rpc_timeout: timedelta | None = None, + ) -> ReturnType: ... + + # sync single-param + @overload + async def execute_activity( + self, + activity: CallableSyncSingleParam[ParamType, ReturnType], + arg: ParamType, + *, + id: str, + task_queue: str, + schedule_to_close_timeout: timedelta | None = None, + schedule_to_start_timeout: timedelta | None = None, + start_to_close_timeout: timedelta | None = None, + heartbeat_timeout: timedelta | None = None, + id_reuse_policy: temporalio.common.ActivityIDReusePolicy = temporalio.common.ActivityIDReusePolicy.ALLOW_DUPLICATE, + id_conflict_policy: temporalio.common.ActivityIDConflictPolicy = temporalio.common.ActivityIDConflictPolicy.FAIL, + retry_policy: temporalio.common.RetryPolicy | None = None, + search_attributes: temporalio.common.TypedSearchAttributes | None = None, + summary: str | None = None, + priority: temporalio.common.Priority = temporalio.common.Priority.default, + start_delay: timedelta | None = None, + rpc_metadata: Mapping[str, str | bytes] = {}, + rpc_timeout: timedelta | None = None, + ) -> ReturnType: ... + + # async multi-param + @overload + async def execute_activity( + self, + activity: Callable[..., Awaitable[ReturnType]], + *, + args: Sequence[Any], + id: str, + task_queue: str, + schedule_to_close_timeout: timedelta | None = None, + schedule_to_start_timeout: timedelta | None = None, + start_to_close_timeout: timedelta | None = None, + heartbeat_timeout: timedelta | None = None, + id_reuse_policy: temporalio.common.ActivityIDReusePolicy = temporalio.common.ActivityIDReusePolicy.ALLOW_DUPLICATE, + id_conflict_policy: temporalio.common.ActivityIDConflictPolicy = temporalio.common.ActivityIDConflictPolicy.FAIL, + retry_policy: temporalio.common.RetryPolicy | None = None, + search_attributes: temporalio.common.TypedSearchAttributes | None = None, + summary: str | None = None, + priority: temporalio.common.Priority = temporalio.common.Priority.default, + start_delay: timedelta | None = None, + rpc_metadata: Mapping[str, str | bytes] = {}, + rpc_timeout: timedelta | None = None, + ) -> ReturnType: ... + + # sync multi-param + @overload + async def execute_activity( + self, + activity: Callable[..., ReturnType], + *, + args: Sequence[Any], + id: str, + task_queue: str, + schedule_to_close_timeout: timedelta | None = None, + schedule_to_start_timeout: timedelta | None = None, + start_to_close_timeout: timedelta | None = None, + heartbeat_timeout: timedelta | None = None, + id_reuse_policy: temporalio.common.ActivityIDReusePolicy = temporalio.common.ActivityIDReusePolicy.ALLOW_DUPLICATE, + id_conflict_policy: temporalio.common.ActivityIDConflictPolicy = temporalio.common.ActivityIDConflictPolicy.FAIL, + retry_policy: temporalio.common.RetryPolicy | None = None, + search_attributes: temporalio.common.TypedSearchAttributes | None = None, + summary: str | None = None, + priority: temporalio.common.Priority = temporalio.common.Priority.default, + start_delay: timedelta | None = None, + rpc_metadata: Mapping[str, str | bytes] = {}, + rpc_timeout: timedelta | None = None, + ) -> ReturnType: ... + + # string name + @overload + async def execute_activity( + self, + activity: str, + arg: Any = temporalio.common._arg_unset, + *, + args: Sequence[Any] = [], + id: str, + task_queue: str, + result_type: type | None = None, + schedule_to_close_timeout: timedelta | None = None, + schedule_to_start_timeout: timedelta | None = None, + start_to_close_timeout: timedelta | None = None, + heartbeat_timeout: timedelta | None = None, + id_reuse_policy: temporalio.common.ActivityIDReusePolicy = temporalio.common.ActivityIDReusePolicy.ALLOW_DUPLICATE, + id_conflict_policy: temporalio.common.ActivityIDConflictPolicy = temporalio.common.ActivityIDConflictPolicy.FAIL, + retry_policy: temporalio.common.RetryPolicy | None = None, + search_attributes: temporalio.common.TypedSearchAttributes | None = None, + summary: str | None = None, + priority: temporalio.common.Priority = temporalio.common.Priority.default, + start_delay: timedelta | None = None, + rpc_metadata: Mapping[str, str | bytes] = {}, + rpc_timeout: timedelta | None = None, + ) -> Any: ... + + async def execute_activity( + self, + activity: ( + str | Callable[..., Awaitable[ReturnType]] | Callable[..., ReturnType] + ), + arg: Any = temporalio.common._arg_unset, + *, + args: Sequence[Any] = [], + id: str, + task_queue: str, + result_type: type | None = None, + # Either schedule_to_close_timeout or start_to_close_timeout must be present + schedule_to_close_timeout: timedelta | None = None, + schedule_to_start_timeout: timedelta | None = None, + start_to_close_timeout: timedelta | None = None, + heartbeat_timeout: timedelta | None = None, + id_reuse_policy: temporalio.common.ActivityIDReusePolicy = temporalio.common.ActivityIDReusePolicy.ALLOW_DUPLICATE, + id_conflict_policy: temporalio.common.ActivityIDConflictPolicy = temporalio.common.ActivityIDConflictPolicy.FAIL, + retry_policy: temporalio.common.RetryPolicy | None = None, + search_attributes: temporalio.common.TypedSearchAttributes | None = None, + summary: str | None = None, + priority: temporalio.common.Priority = temporalio.common.Priority.default, + start_delay: timedelta | None = None, + rpc_metadata: Mapping[str, str | bytes] = {}, + rpc_timeout: timedelta | None = None, + ) -> ReturnType: + """Start an activity, wait for it to complete, and return its result. + + .. warning:: + This API is experimental. + + This is a convenience method that combines :py:meth:`start_activity` and + :py:meth:`ActivityHandle.result`. + + Returns: + The result of the activity. + + Raises: + ActivityFailureError: If the activity completed with a failure. + """ + handle: ActivityHandle[ReturnType] = await self.start_activity( + cast(Any, activity), + arg, + args=args, + id=id, + task_queue=task_queue, + result_type=result_type, + schedule_to_close_timeout=schedule_to_close_timeout, + schedule_to_start_timeout=schedule_to_start_timeout, + start_to_close_timeout=start_to_close_timeout, + heartbeat_timeout=heartbeat_timeout, + id_reuse_policy=id_reuse_policy, + id_conflict_policy=id_conflict_policy, + retry_policy=retry_policy, + search_attributes=search_attributes, + summary=summary, + priority=priority, + start_delay=start_delay, + rpc_metadata=rpc_metadata, + rpc_timeout=rpc_timeout, + ) + return await handle.result() + + # async no-param + @overload + async def start_activity_class( + self, + activity: type[CallableAsyncNoParam[ReturnType]], + *, + id: str, + task_queue: str, + schedule_to_close_timeout: timedelta | None = None, + schedule_to_start_timeout: timedelta | None = None, + start_to_close_timeout: timedelta | None = None, + heartbeat_timeout: timedelta | None = None, + id_reuse_policy: temporalio.common.ActivityIDReusePolicy = temporalio.common.ActivityIDReusePolicy.ALLOW_DUPLICATE, + id_conflict_policy: temporalio.common.ActivityIDConflictPolicy = temporalio.common.ActivityIDConflictPolicy.FAIL, + retry_policy: temporalio.common.RetryPolicy | None = None, + search_attributes: temporalio.common.TypedSearchAttributes | None = None, + summary: str | None = None, + priority: temporalio.common.Priority = temporalio.common.Priority.default, + start_delay: timedelta | None = None, + rpc_metadata: Mapping[str, str | bytes] = {}, + rpc_timeout: timedelta | None = None, + ) -> ActivityHandle[ReturnType]: ... + + # sync no-param + @overload + async def start_activity_class( + self, + activity: type[CallableSyncNoParam[ReturnType]], + *, + id: str, + task_queue: str, + schedule_to_close_timeout: timedelta | None = None, + schedule_to_start_timeout: timedelta | None = None, + start_to_close_timeout: timedelta | None = None, + heartbeat_timeout: timedelta | None = None, + id_reuse_policy: temporalio.common.ActivityIDReusePolicy = temporalio.common.ActivityIDReusePolicy.ALLOW_DUPLICATE, + id_conflict_policy: temporalio.common.ActivityIDConflictPolicy = temporalio.common.ActivityIDConflictPolicy.FAIL, + retry_policy: temporalio.common.RetryPolicy | None = None, + search_attributes: temporalio.common.TypedSearchAttributes | None = None, + summary: str | None = None, + priority: temporalio.common.Priority = temporalio.common.Priority.default, + start_delay: timedelta | None = None, + rpc_metadata: Mapping[str, str | bytes] = {}, + rpc_timeout: timedelta | None = None, + ) -> ActivityHandle[ReturnType]: ... + + # async single-param + @overload + async def start_activity_class( + self, + activity: type[CallableAsyncSingleParam[ParamType, ReturnType]], + arg: ParamType, + *, + id: str, + task_queue: str, + schedule_to_close_timeout: timedelta | None = None, + schedule_to_start_timeout: timedelta | None = None, + start_to_close_timeout: timedelta | None = None, + heartbeat_timeout: timedelta | None = None, + id_reuse_policy: temporalio.common.ActivityIDReusePolicy = temporalio.common.ActivityIDReusePolicy.ALLOW_DUPLICATE, + id_conflict_policy: temporalio.common.ActivityIDConflictPolicy = temporalio.common.ActivityIDConflictPolicy.FAIL, + retry_policy: temporalio.common.RetryPolicy | None = None, + search_attributes: temporalio.common.TypedSearchAttributes | None = None, + summary: str | None = None, + priority: temporalio.common.Priority = temporalio.common.Priority.default, + start_delay: timedelta | None = None, + rpc_metadata: Mapping[str, str | bytes] = {}, + rpc_timeout: timedelta | None = None, + ) -> ActivityHandle[ReturnType]: ... + + # sync single-param + @overload + async def start_activity_class( + self, + activity: type[CallableSyncSingleParam[ParamType, ReturnType]], + arg: ParamType, + *, + id: str, + task_queue: str, + schedule_to_close_timeout: timedelta | None = None, + schedule_to_start_timeout: timedelta | None = None, + start_to_close_timeout: timedelta | None = None, + heartbeat_timeout: timedelta | None = None, + id_reuse_policy: temporalio.common.ActivityIDReusePolicy = temporalio.common.ActivityIDReusePolicy.ALLOW_DUPLICATE, + id_conflict_policy: temporalio.common.ActivityIDConflictPolicy = temporalio.common.ActivityIDConflictPolicy.FAIL, + retry_policy: temporalio.common.RetryPolicy | None = None, + search_attributes: temporalio.common.TypedSearchAttributes | None = None, + summary: str | None = None, + priority: temporalio.common.Priority = temporalio.common.Priority.default, + start_delay: timedelta | None = None, + rpc_metadata: Mapping[str, str | bytes] = {}, + rpc_timeout: timedelta | None = None, + ) -> ActivityHandle[ReturnType]: ... + + # async multi-param + @overload + async def start_activity_class( + self, + activity: type[Callable[..., Awaitable[ReturnType]]], # type: ignore[reportInvalidTypeForm] + *, + args: Sequence[Any], + id: str, + task_queue: str, + schedule_to_close_timeout: timedelta | None = None, + schedule_to_start_timeout: timedelta | None = None, + start_to_close_timeout: timedelta | None = None, + heartbeat_timeout: timedelta | None = None, + id_reuse_policy: temporalio.common.ActivityIDReusePolicy = temporalio.common.ActivityIDReusePolicy.ALLOW_DUPLICATE, + id_conflict_policy: temporalio.common.ActivityIDConflictPolicy = temporalio.common.ActivityIDConflictPolicy.FAIL, + retry_policy: temporalio.common.RetryPolicy | None = None, + search_attributes: temporalio.common.TypedSearchAttributes | None = None, + summary: str | None = None, + priority: temporalio.common.Priority = temporalio.common.Priority.default, + start_delay: timedelta | None = None, + rpc_metadata: Mapping[str, str | bytes] = {}, + rpc_timeout: timedelta | None = None, + ) -> ActivityHandle[ReturnType]: ... + + # sync multi-param + @overload + async def start_activity_class( + self, + activity: type[Callable[..., ReturnType]], # type: ignore[reportInvalidTypeForm] + *, + args: Sequence[Any], + id: str, + task_queue: str, + schedule_to_close_timeout: timedelta | None = None, + schedule_to_start_timeout: timedelta | None = None, + start_to_close_timeout: timedelta | None = None, + heartbeat_timeout: timedelta | None = None, + id_reuse_policy: temporalio.common.ActivityIDReusePolicy = temporalio.common.ActivityIDReusePolicy.ALLOW_DUPLICATE, + id_conflict_policy: temporalio.common.ActivityIDConflictPolicy = temporalio.common.ActivityIDConflictPolicy.FAIL, + retry_policy: temporalio.common.RetryPolicy | None = None, + search_attributes: temporalio.common.TypedSearchAttributes | None = None, + summary: str | None = None, + priority: temporalio.common.Priority = temporalio.common.Priority.default, + start_delay: timedelta | None = None, + rpc_metadata: Mapping[str, str | bytes] = {}, + rpc_timeout: timedelta | None = None, + ) -> ActivityHandle[ReturnType]: ... + + async def start_activity_class( + self, + activity: type[Callable], # type: ignore[reportInvalidTypeForm] + arg: Any = temporalio.common._arg_unset, + *, + args: Sequence[Any] = [], + id: str, + task_queue: str, + result_type: type | None = None, + schedule_to_close_timeout: timedelta | None = None, + schedule_to_start_timeout: timedelta | None = None, + start_to_close_timeout: timedelta | None = None, + heartbeat_timeout: timedelta | None = None, + id_reuse_policy: temporalio.common.ActivityIDReusePolicy = temporalio.common.ActivityIDReusePolicy.ALLOW_DUPLICATE, + id_conflict_policy: temporalio.common.ActivityIDConflictPolicy = temporalio.common.ActivityIDConflictPolicy.FAIL, + retry_policy: temporalio.common.RetryPolicy | None = None, + search_attributes: temporalio.common.TypedSearchAttributes | None = None, + summary: str | None = None, + priority: temporalio.common.Priority = temporalio.common.Priority.default, + start_delay: timedelta | None = None, + rpc_metadata: Mapping[str, str | bytes] = {}, + rpc_timeout: timedelta | None = None, + ) -> ActivityHandle[Any]: + """Start an activity from a callable class. + + .. warning:: + This API is experimental. + + See :py:meth:`start_activity` for parameter and return details. + """ + return await self.start_activity( + cast(Any, activity), + arg, + args=args, + id=id, + task_queue=task_queue, + result_type=result_type, + schedule_to_close_timeout=schedule_to_close_timeout, + schedule_to_start_timeout=schedule_to_start_timeout, + start_to_close_timeout=start_to_close_timeout, + heartbeat_timeout=heartbeat_timeout, + id_reuse_policy=id_reuse_policy, + id_conflict_policy=id_conflict_policy, + retry_policy=retry_policy, + search_attributes=search_attributes, + summary=summary, + priority=priority, + start_delay=start_delay, + rpc_metadata=rpc_metadata, + rpc_timeout=rpc_timeout, + ) + + # async no-param + @overload + async def execute_activity_class( + self, + activity: type[CallableAsyncNoParam[ReturnType]], + *, + id: str, + task_queue: str, + schedule_to_close_timeout: timedelta | None = None, + schedule_to_start_timeout: timedelta | None = None, + start_to_close_timeout: timedelta | None = None, + heartbeat_timeout: timedelta | None = None, + id_reuse_policy: temporalio.common.ActivityIDReusePolicy = temporalio.common.ActivityIDReusePolicy.ALLOW_DUPLICATE, + id_conflict_policy: temporalio.common.ActivityIDConflictPolicy = temporalio.common.ActivityIDConflictPolicy.FAIL, + retry_policy: temporalio.common.RetryPolicy | None = None, + search_attributes: temporalio.common.TypedSearchAttributes | None = None, + summary: str | None = None, + priority: temporalio.common.Priority = temporalio.common.Priority.default, + start_delay: timedelta | None = None, + rpc_metadata: Mapping[str, str | bytes] = {}, + rpc_timeout: timedelta | None = None, + ) -> ReturnType: ... + + # sync no-param + @overload + async def execute_activity_class( + self, + activity: type[CallableSyncNoParam[ReturnType]], + *, + id: str, + task_queue: str, + schedule_to_close_timeout: timedelta | None = None, + schedule_to_start_timeout: timedelta | None = None, + start_to_close_timeout: timedelta | None = None, + heartbeat_timeout: timedelta | None = None, + id_reuse_policy: temporalio.common.ActivityIDReusePolicy = temporalio.common.ActivityIDReusePolicy.ALLOW_DUPLICATE, + id_conflict_policy: temporalio.common.ActivityIDConflictPolicy = temporalio.common.ActivityIDConflictPolicy.FAIL, + retry_policy: temporalio.common.RetryPolicy | None = None, + search_attributes: temporalio.common.TypedSearchAttributes | None = None, + summary: str | None = None, + priority: temporalio.common.Priority = temporalio.common.Priority.default, + start_delay: timedelta | None = None, + rpc_metadata: Mapping[str, str | bytes] = {}, + rpc_timeout: timedelta | None = None, + ) -> ReturnType: ... + + # async single-param + @overload + async def execute_activity_class( + self, + activity: type[CallableAsyncSingleParam[ParamType, ReturnType]], + arg: ParamType, + *, + id: str, + task_queue: str, + schedule_to_close_timeout: timedelta | None = None, + schedule_to_start_timeout: timedelta | None = None, + start_to_close_timeout: timedelta | None = None, + heartbeat_timeout: timedelta | None = None, + id_reuse_policy: temporalio.common.ActivityIDReusePolicy = temporalio.common.ActivityIDReusePolicy.ALLOW_DUPLICATE, + id_conflict_policy: temporalio.common.ActivityIDConflictPolicy = temporalio.common.ActivityIDConflictPolicy.FAIL, + retry_policy: temporalio.common.RetryPolicy | None = None, + search_attributes: temporalio.common.TypedSearchAttributes | None = None, + summary: str | None = None, + priority: temporalio.common.Priority = temporalio.common.Priority.default, + start_delay: timedelta | None = None, + rpc_metadata: Mapping[str, str | bytes] = {}, + rpc_timeout: timedelta | None = None, + ) -> ReturnType: ... + + # sync single-param + @overload + async def execute_activity_class( + self, + activity: type[CallableSyncSingleParam[ParamType, ReturnType]], + arg: ParamType, + *, + id: str, + task_queue: str, + schedule_to_close_timeout: timedelta | None = None, + schedule_to_start_timeout: timedelta | None = None, + start_to_close_timeout: timedelta | None = None, + heartbeat_timeout: timedelta | None = None, + id_reuse_policy: temporalio.common.ActivityIDReusePolicy = temporalio.common.ActivityIDReusePolicy.ALLOW_DUPLICATE, + id_conflict_policy: temporalio.common.ActivityIDConflictPolicy = temporalio.common.ActivityIDConflictPolicy.FAIL, + retry_policy: temporalio.common.RetryPolicy | None = None, + search_attributes: temporalio.common.TypedSearchAttributes | None = None, + summary: str | None = None, + priority: temporalio.common.Priority = temporalio.common.Priority.default, + start_delay: timedelta | None = None, + rpc_metadata: Mapping[str, str | bytes] = {}, + rpc_timeout: timedelta | None = None, + ) -> ReturnType: ... + + # async multi-param + @overload + async def execute_activity_class( + self, + activity: type[Callable[..., Awaitable[ReturnType]]], # type: ignore[reportInvalidTypeForm] + *, + args: Sequence[Any], + id: str, + task_queue: str, + schedule_to_close_timeout: timedelta | None = None, + schedule_to_start_timeout: timedelta | None = None, + start_to_close_timeout: timedelta | None = None, + heartbeat_timeout: timedelta | None = None, + id_reuse_policy: temporalio.common.ActivityIDReusePolicy = temporalio.common.ActivityIDReusePolicy.ALLOW_DUPLICATE, + id_conflict_policy: temporalio.common.ActivityIDConflictPolicy = temporalio.common.ActivityIDConflictPolicy.FAIL, + retry_policy: temporalio.common.RetryPolicy | None = None, + search_attributes: temporalio.common.TypedSearchAttributes | None = None, + summary: str | None = None, + priority: temporalio.common.Priority = temporalio.common.Priority.default, + start_delay: timedelta | None = None, + rpc_metadata: Mapping[str, str | bytes] = {}, + rpc_timeout: timedelta | None = None, + ) -> ReturnType: ... + + # sync multi-param + @overload + async def execute_activity_class( + self, + activity: type[Callable[..., ReturnType]], # type: ignore[reportInvalidTypeForm] + *, + args: Sequence[Any], + id: str, + task_queue: str, + schedule_to_close_timeout: timedelta | None = None, + schedule_to_start_timeout: timedelta | None = None, + start_to_close_timeout: timedelta | None = None, + heartbeat_timeout: timedelta | None = None, + id_reuse_policy: temporalio.common.ActivityIDReusePolicy = temporalio.common.ActivityIDReusePolicy.ALLOW_DUPLICATE, + id_conflict_policy: temporalio.common.ActivityIDConflictPolicy = temporalio.common.ActivityIDConflictPolicy.FAIL, + retry_policy: temporalio.common.RetryPolicy | None = None, + search_attributes: temporalio.common.TypedSearchAttributes | None = None, + summary: str | None = None, + priority: temporalio.common.Priority = temporalio.common.Priority.default, + start_delay: timedelta | None = None, + rpc_metadata: Mapping[str, str | bytes] = {}, + rpc_timeout: timedelta | None = None, + ) -> ReturnType: ... + + async def execute_activity_class( + self, + activity: type[Callable], # type: ignore[reportInvalidTypeForm] + arg: Any = temporalio.common._arg_unset, + *, + args: Sequence[Any] = [], + id: str, + task_queue: str, + result_type: type | None = None, + schedule_to_close_timeout: timedelta | None = None, + schedule_to_start_timeout: timedelta | None = None, + start_to_close_timeout: timedelta | None = None, + heartbeat_timeout: timedelta | None = None, + id_reuse_policy: temporalio.common.ActivityIDReusePolicy = temporalio.common.ActivityIDReusePolicy.ALLOW_DUPLICATE, + id_conflict_policy: temporalio.common.ActivityIDConflictPolicy = temporalio.common.ActivityIDConflictPolicy.FAIL, + retry_policy: temporalio.common.RetryPolicy | None = None, + search_attributes: temporalio.common.TypedSearchAttributes | None = None, + summary: str | None = None, + priority: temporalio.common.Priority = temporalio.common.Priority.default, + start_delay: timedelta | None = None, + rpc_metadata: Mapping[str, str | bytes] = {}, + rpc_timeout: timedelta | None = None, + ) -> Any: + """Start an activity from a callable class and wait for completion. + + .. warning:: + This API is experimental. + + This is a shortcut for ``await`` :py:meth:`start_activity_class`. + """ + return await self.execute_activity( + cast(Any, activity), + arg, + args=args, + id=id, + task_queue=task_queue, + result_type=result_type, + schedule_to_close_timeout=schedule_to_close_timeout, + schedule_to_start_timeout=schedule_to_start_timeout, + start_to_close_timeout=start_to_close_timeout, + heartbeat_timeout=heartbeat_timeout, + id_reuse_policy=id_reuse_policy, + id_conflict_policy=id_conflict_policy, + retry_policy=retry_policy, + search_attributes=search_attributes, + summary=summary, + priority=priority, + start_delay=start_delay, + rpc_metadata=rpc_metadata, + rpc_timeout=rpc_timeout, + ) + + # async no-param + @overload + async def start_activity_method( + self, + activity: MethodAsyncNoParam[SelfType, ReturnType], + *, + id: str, + task_queue: str, + schedule_to_close_timeout: timedelta | None = None, + schedule_to_start_timeout: timedelta | None = None, + start_to_close_timeout: timedelta | None = None, + heartbeat_timeout: timedelta | None = None, + id_reuse_policy: temporalio.common.ActivityIDReusePolicy = temporalio.common.ActivityIDReusePolicy.ALLOW_DUPLICATE, + id_conflict_policy: temporalio.common.ActivityIDConflictPolicy = temporalio.common.ActivityIDConflictPolicy.FAIL, + retry_policy: temporalio.common.RetryPolicy | None = None, + search_attributes: temporalio.common.TypedSearchAttributes | None = None, + summary: str | None = None, + priority: temporalio.common.Priority = temporalio.common.Priority.default, + start_delay: timedelta | None = None, + rpc_metadata: Mapping[str, str | bytes] = {}, + rpc_timeout: timedelta | None = None, + ) -> ActivityHandle[ReturnType]: ... + + # async single-param + @overload + async def start_activity_method( + self, + activity: MethodAsyncSingleParam[SelfType, ParamType, ReturnType], + arg: ParamType, + *, + id: str, + task_queue: str, + schedule_to_close_timeout: timedelta | None = None, + schedule_to_start_timeout: timedelta | None = None, + start_to_close_timeout: timedelta | None = None, + heartbeat_timeout: timedelta | None = None, + id_reuse_policy: temporalio.common.ActivityIDReusePolicy = temporalio.common.ActivityIDReusePolicy.ALLOW_DUPLICATE, + id_conflict_policy: temporalio.common.ActivityIDConflictPolicy = temporalio.common.ActivityIDConflictPolicy.FAIL, + retry_policy: temporalio.common.RetryPolicy | None = None, + search_attributes: temporalio.common.TypedSearchAttributes | None = None, + summary: str | None = None, + priority: temporalio.common.Priority = temporalio.common.Priority.default, + start_delay: timedelta | None = None, + rpc_metadata: Mapping[str, str | bytes] = {}, + rpc_timeout: timedelta | None = None, + ) -> ActivityHandle[ReturnType]: ... + + # async multi-param + @overload + async def start_activity_method( + self, + activity: Callable[ + Concatenate[SelfType, MultiParamSpec], Awaitable[ReturnType] + ], + *, + args: Sequence[Any], + id: str, + task_queue: str, + schedule_to_close_timeout: timedelta | None = None, + schedule_to_start_timeout: timedelta | None = None, + start_to_close_timeout: timedelta | None = None, + heartbeat_timeout: timedelta | None = None, + id_reuse_policy: temporalio.common.ActivityIDReusePolicy = temporalio.common.ActivityIDReusePolicy.ALLOW_DUPLICATE, + id_conflict_policy: temporalio.common.ActivityIDConflictPolicy = temporalio.common.ActivityIDConflictPolicy.FAIL, + retry_policy: temporalio.common.RetryPolicy | None = None, + search_attributes: temporalio.common.TypedSearchAttributes | None = None, + summary: str | None = None, + priority: temporalio.common.Priority = temporalio.common.Priority.default, + start_delay: timedelta | None = None, + rpc_metadata: Mapping[str, str | bytes] = {}, + rpc_timeout: timedelta | None = None, + ) -> ActivityHandle[ReturnType]: ... + + # sync multi-param + @overload + async def start_activity_method( + self, + activity: Callable[Concatenate[SelfType, MultiParamSpec], ReturnType], + *, + args: Sequence[Any], + id: str, + task_queue: str, + schedule_to_close_timeout: timedelta | None = None, + schedule_to_start_timeout: timedelta | None = None, + start_to_close_timeout: timedelta | None = None, + heartbeat_timeout: timedelta | None = None, + id_reuse_policy: temporalio.common.ActivityIDReusePolicy = temporalio.common.ActivityIDReusePolicy.ALLOW_DUPLICATE, + id_conflict_policy: temporalio.common.ActivityIDConflictPolicy = temporalio.common.ActivityIDConflictPolicy.FAIL, + retry_policy: temporalio.common.RetryPolicy | None = None, + search_attributes: temporalio.common.TypedSearchAttributes | None = None, + summary: str | None = None, + priority: temporalio.common.Priority = temporalio.common.Priority.default, + start_delay: timedelta | None = None, + rpc_metadata: Mapping[str, str | bytes] = {}, + rpc_timeout: timedelta | None = None, + ) -> ActivityHandle[ReturnType]: ... + + async def start_activity_method( + self, + activity: Callable, + arg: Any = temporalio.common._arg_unset, + *, + args: Sequence[Any] = [], + id: str, + task_queue: str, + result_type: type | None = None, + schedule_to_close_timeout: timedelta | None = None, + schedule_to_start_timeout: timedelta | None = None, + start_to_close_timeout: timedelta | None = None, + heartbeat_timeout: timedelta | None = None, + id_reuse_policy: temporalio.common.ActivityIDReusePolicy = temporalio.common.ActivityIDReusePolicy.ALLOW_DUPLICATE, + id_conflict_policy: temporalio.common.ActivityIDConflictPolicy = temporalio.common.ActivityIDConflictPolicy.FAIL, + retry_policy: temporalio.common.RetryPolicy | None = None, + search_attributes: temporalio.common.TypedSearchAttributes | None = None, + summary: str | None = None, + priority: temporalio.common.Priority = temporalio.common.Priority.default, + start_delay: timedelta | None = None, + rpc_metadata: Mapping[str, str | bytes] = {}, + rpc_timeout: timedelta | None = None, + ) -> ActivityHandle[Any]: + """Start an activity from a method. + + .. warning:: + This API is experimental. + + See :py:meth:`start_activity` for parameter and return details. + """ + return await self.start_activity( + cast(Any, activity), + arg, + args=args, + id=id, + task_queue=task_queue, + result_type=result_type, + schedule_to_close_timeout=schedule_to_close_timeout, + schedule_to_start_timeout=schedule_to_start_timeout, + start_to_close_timeout=start_to_close_timeout, + heartbeat_timeout=heartbeat_timeout, + id_reuse_policy=id_reuse_policy, + id_conflict_policy=id_conflict_policy, + retry_policy=retry_policy, + search_attributes=search_attributes, + summary=summary, + priority=priority, + start_delay=start_delay, + rpc_metadata=rpc_metadata, + rpc_timeout=rpc_timeout, + ) + + # async no-param + @overload + async def execute_activity_method( + self, + activity: MethodAsyncNoParam[SelfType, ReturnType], + *, + id: str, + task_queue: str, + schedule_to_close_timeout: timedelta | None = None, + schedule_to_start_timeout: timedelta | None = None, + start_to_close_timeout: timedelta | None = None, + heartbeat_timeout: timedelta | None = None, + id_reuse_policy: temporalio.common.ActivityIDReusePolicy = temporalio.common.ActivityIDReusePolicy.ALLOW_DUPLICATE, + id_conflict_policy: temporalio.common.ActivityIDConflictPolicy = temporalio.common.ActivityIDConflictPolicy.FAIL, + retry_policy: temporalio.common.RetryPolicy | None = None, + search_attributes: temporalio.common.TypedSearchAttributes | None = None, + summary: str | None = None, + priority: temporalio.common.Priority = temporalio.common.Priority.default, + start_delay: timedelta | None = None, + rpc_metadata: Mapping[str, str | bytes] = {}, + rpc_timeout: timedelta | None = None, + ) -> ReturnType: ... + + # async single-param + @overload + async def execute_activity_method( + self, + activity: MethodAsyncSingleParam[SelfType, ParamType, ReturnType], + arg: ParamType, + *, + id: str, + task_queue: str, + schedule_to_close_timeout: timedelta | None = None, + schedule_to_start_timeout: timedelta | None = None, + start_to_close_timeout: timedelta | None = None, + heartbeat_timeout: timedelta | None = None, + id_reuse_policy: temporalio.common.ActivityIDReusePolicy = temporalio.common.ActivityIDReusePolicy.ALLOW_DUPLICATE, + id_conflict_policy: temporalio.common.ActivityIDConflictPolicy = temporalio.common.ActivityIDConflictPolicy.FAIL, + retry_policy: temporalio.common.RetryPolicy | None = None, + search_attributes: temporalio.common.TypedSearchAttributes | None = None, + summary: str | None = None, + priority: temporalio.common.Priority = temporalio.common.Priority.default, + start_delay: timedelta | None = None, + rpc_metadata: Mapping[str, str | bytes] = {}, + rpc_timeout: timedelta | None = None, + ) -> ReturnType: ... + + # async multi-param + @overload + async def execute_activity_method( + self, + activity: Callable[ + Concatenate[SelfType, MultiParamSpec], Awaitable[ReturnType] + ], + *, + args: Sequence[Any], + id: str, + task_queue: str, + schedule_to_close_timeout: timedelta | None = None, + schedule_to_start_timeout: timedelta | None = None, + start_to_close_timeout: timedelta | None = None, + heartbeat_timeout: timedelta | None = None, + id_reuse_policy: temporalio.common.ActivityIDReusePolicy = temporalio.common.ActivityIDReusePolicy.ALLOW_DUPLICATE, + id_conflict_policy: temporalio.common.ActivityIDConflictPolicy = temporalio.common.ActivityIDConflictPolicy.FAIL, + retry_policy: temporalio.common.RetryPolicy | None = None, + search_attributes: temporalio.common.TypedSearchAttributes | None = None, + summary: str | None = None, + priority: temporalio.common.Priority = temporalio.common.Priority.default, + start_delay: timedelta | None = None, + rpc_metadata: Mapping[str, str | bytes] = {}, + rpc_timeout: timedelta | None = None, + ) -> ReturnType: ... + + # sync multi-param + @overload + async def execute_activity_method( + self, + activity: Callable[Concatenate[SelfType, MultiParamSpec], ReturnType], + *, + args: Sequence[Any], + id: str, + task_queue: str, + schedule_to_close_timeout: timedelta | None = None, + schedule_to_start_timeout: timedelta | None = None, + start_to_close_timeout: timedelta | None = None, + heartbeat_timeout: timedelta | None = None, + id_reuse_policy: temporalio.common.ActivityIDReusePolicy = temporalio.common.ActivityIDReusePolicy.ALLOW_DUPLICATE, + id_conflict_policy: temporalio.common.ActivityIDConflictPolicy = temporalio.common.ActivityIDConflictPolicy.FAIL, + retry_policy: temporalio.common.RetryPolicy | None = None, + search_attributes: temporalio.common.TypedSearchAttributes | None = None, + summary: str | None = None, + priority: temporalio.common.Priority = temporalio.common.Priority.default, + start_delay: timedelta | None = None, + rpc_metadata: Mapping[str, str | bytes] = {}, + rpc_timeout: timedelta | None = None, + ) -> ReturnType: ... + + async def execute_activity_method( + self, + activity: Callable, + arg: Any = temporalio.common._arg_unset, + *, + args: Sequence[Any] = [], + id: str, + task_queue: str, + result_type: type | None = None, + schedule_to_close_timeout: timedelta | None = None, + schedule_to_start_timeout: timedelta | None = None, + start_to_close_timeout: timedelta | None = None, + heartbeat_timeout: timedelta | None = None, + id_reuse_policy: temporalio.common.ActivityIDReusePolicy = temporalio.common.ActivityIDReusePolicy.ALLOW_DUPLICATE, + id_conflict_policy: temporalio.common.ActivityIDConflictPolicy = temporalio.common.ActivityIDConflictPolicy.FAIL, + retry_policy: temporalio.common.RetryPolicy | None = None, + search_attributes: temporalio.common.TypedSearchAttributes | None = None, + summary: str | None = None, + priority: temporalio.common.Priority = temporalio.common.Priority.default, + start_delay: timedelta | None = None, + rpc_metadata: Mapping[str, str | bytes] = {}, + rpc_timeout: timedelta | None = None, + ) -> Any: + """Start an activity from a method and wait for completion. + + .. warning:: + This API is experimental. + + This is a shortcut for ``await`` :py:meth:`start_activity_method`. + """ + return await self.execute_activity( + cast(Any, activity), + arg, + args=args, + id=id, + task_queue=task_queue, + result_type=result_type, + schedule_to_close_timeout=schedule_to_close_timeout, + schedule_to_start_timeout=schedule_to_start_timeout, + start_to_close_timeout=start_to_close_timeout, + heartbeat_timeout=heartbeat_timeout, + id_reuse_policy=id_reuse_policy, + id_conflict_policy=id_conflict_policy, + retry_policy=retry_policy, + search_attributes=search_attributes, + summary=summary, + priority=priority, + start_delay=start_delay, + rpc_metadata=rpc_metadata, + rpc_timeout=rpc_timeout, + ) + + def list_activities( + self, + query: str, + *, + limit: int | None = None, + page_size: int = 1000, + next_page_token: bytes | None = None, + rpc_metadata: Mapping[str, str | bytes] = {}, + rpc_timeout: timedelta | None = None, + ) -> ActivityExecutionAsyncIterator: + """List activities not started by a workflow. + + .. warning:: + This API is experimental. + + This does not make a request until the first iteration is attempted. + Therefore any errors will not occur until then. + + Args: + query: A Temporal visibility list filter for activities. Required. + limit: Maximum number of activities to return. If unset, all + activities are returned. Only applies if using the + returned :py:class:`ActivityExecutionAsyncIterator` + as an async iterator. + page_size: Maximum number of results for each page. + next_page_token: A previously obtained next page token if doing + pagination. Usually not needed as the iterator automatically + starts from the beginning. + rpc_metadata: Headers used on each RPC call. Keys here override + client-level RPC metadata keys. + rpc_timeout: Optional RPC deadline to set for each RPC call. + + Returns: + An async iterator that can be used with ``async for``. + """ + return self._impl.list_activities( + ListActivitiesInput( + query=query, + page_size=page_size, + next_page_token=next_page_token, + rpc_metadata=rpc_metadata, + rpc_timeout=rpc_timeout, + limit=limit, + ) + ) + + async def count_activities( + self, + query: str | None = None, + *, + rpc_metadata: Mapping[str, str | bytes] = {}, + rpc_timeout: timedelta | None = None, + ) -> ActivityExecutionCount: + """Count activities not started by a workflow. + + .. warning:: + This API is experimental. + + Args: + query: A Temporal visibility filter for activities. + rpc_metadata: Headers used on the RPC call. Keys here override + client-level RPC metadata keys. + rpc_timeout: Optional RPC deadline to set for the RPC call. + + Returns: + Count of activities. + """ + return await self._impl.count_activities( + CountActivitiesInput( + query=query, rpc_metadata=rpc_metadata, rpc_timeout=rpc_timeout + ) + ) + + @overload + def get_activity_handle( + self, + activity_id: str, + *, + run_id: str | None = None, + ) -> ActivityHandle[Any]: ... + + @overload + def get_activity_handle( + self, + activity_id: str, + *, + run_id: str | None = None, + result_type: type[ReturnType], + ) -> ActivityHandle[ReturnType]: ... + + def get_activity_handle( + self, + activity_id: str, + *, + run_id: str | None = None, + result_type: type | None = None, + ) -> ActivityHandle[Any]: + """Get a handle to an existing activity, as the caller of that activity. + + The activity must not have been started by a workflow. + + .. warning:: + This API is experimental. + + To get a handle to an activity execution that you control for manual completion and + heartbeating, see :py:meth:`Client.get_async_activity_handle`. + + Args: + activity_id: The activity ID. + run_id: The activity run ID. If not provided, targets the latest run. + result_type: The result type to deserialize into. + + Returns: + A handle to the activity. + """ + return ActivityHandle( + self, + activity_id, + run_id=run_id, + result_type=result_type, + ) + + @overload + def get_async_activity_handle( + self, *, activity_id: str, run_id: str | None = None + ) -> AsyncActivityHandle: + pass + + @overload + def get_async_activity_handle( + self, *, workflow_id: str, run_id: str | None, activity_id: str + ) -> AsyncActivityHandle: + pass + + @overload + def get_async_activity_handle(self, *, task_token: bytes) -> AsyncActivityHandle: + pass + + def get_async_activity_handle( + self, + *, + workflow_id: str | None = None, + run_id: str | None = None, + activity_id: str | None = None, + task_token: bytes | None = None, + ) -> AsyncActivityHandle: + """Get a handle to an activity execution that you control, for manual + completion and heartbeating. + + To get a handle to an activity execution as the caller of that activity, + see :py:meth:`Client.get_activity_handle`. + + This function may be used to get a handle to an activity started by a + client, or an activity started by a workflow. + + To get a handle to an activity started by a workflow, use one of the + following two calls: + - Supply ``workflow_id``, ``run_id``, and ``activity_id`` + - Supply the activity ``task_token`` alone + + To get a handle to an activity not started by a workflow, supply + ``activity_id`` and ``run_id`` + + Args: + workflow_id: Workflow ID for the activity, or None if not a workflow + activity. Cannot be set if task_token is set. + run_id: Run ID for the activity or workflow. Cannot be set if + task_token is set. + activity_id: ID for the activity. Cannot be set if task_token is + set. + task_token: Task token for the activity. Cannot be set with other + fields. + + Returns: + A handle that can be used for completion or heartbeating. + """ + if task_token is not None: + if workflow_id is not None or run_id is not None or activity_id is not None: + raise ValueError("Task token cannot be present with other IDs") + return AsyncActivityHandle(self, task_token) + elif workflow_id is not None: + if activity_id is None: + raise ValueError( + "Workflow ID, run ID, and activity ID must all be given together" + ) + return AsyncActivityHandle( + self, + AsyncActivityIDReference( + workflow_id=workflow_id, run_id=run_id, activity_id=activity_id + ), + ) + elif activity_id is not None: + return AsyncActivityHandle( + self, + AsyncActivityIDReference( + activity_id=activity_id, + run_id=run_id, + workflow_id=None, + ), + ) + raise ValueError( + "Require task token, or workflow_id & run_id & activity_id, or activity_id & run_id" + ) + + async def create_schedule( + self, + id: str, + schedule: Schedule, + *, + trigger_immediately: bool = False, + backfill: Sequence[ScheduleBackfill] = [], + memo: Mapping[str, Any] | None = None, + search_attributes: None + | ( + temporalio.common.TypedSearchAttributes | temporalio.common.SearchAttributes + ) = None, + rpc_metadata: Mapping[str, str | bytes] = {}, + rpc_timeout: timedelta | None = None, + ) -> ScheduleHandle: + """Create a schedule and return its handle. + + Args: + id: Unique identifier of the schedule. + schedule: Schedule to create. + trigger_immediately: If true, trigger one action immediately when + creating the schedule. + backfill: Set of time periods to take actions on as if that time + passed right now. + memo: Memo for the schedule. Memo for a scheduled workflow is part + of the schedule action. + search_attributes: Search attributes for the schedule. Search + attributes for a scheduled workflow are part of the scheduled + action. The dictionary form of this is DEPRECATED, use + :py:class:`temporalio.common.TypedSearchAttributes`. + rpc_metadata: Headers used on the RPC call. Keys here override + client-level RPC metadata keys. + rpc_timeout: Optional RPC deadline to set for the RPC call. + + Returns: + A handle to the created schedule. + + Raises: + ScheduleAlreadyRunningError: If a schedule with this ID is already + running. + """ + temporalio.common._warn_on_deprecated_search_attributes(search_attributes) + return await self._impl.create_schedule( + CreateScheduleInput( + id=id, + schedule=schedule, + trigger_immediately=trigger_immediately, + backfill=backfill, + memo=memo, + search_attributes=search_attributes, + rpc_metadata=rpc_metadata, + rpc_timeout=rpc_timeout, + ) + ) + + def get_schedule_handle(self, id: str) -> ScheduleHandle: + """Get a schedule handle for the given ID.""" + return ScheduleHandle(self, id) + + async def list_schedules( + self, + query: str | None = None, + *, + page_size: int = 1000, + next_page_token: bytes | None = None, + rpc_metadata: Mapping[str, str | bytes] = {}, + rpc_timeout: timedelta | None = None, + ) -> ScheduleAsyncIterator: + """List schedules. + + This does not make a request until the first iteration is attempted. + Therefore any errors will not occur until then. + + Note, this list is eventually consistent. Therefore if a schedule is + added or deleted, it may not be available in the list immediately. + + Args: + page_size: Maximum number of results for each page. + query: A Temporal visibility list filter. See Temporal documentation + concerning visibility list filters including behavior when left + unset. + next_page_token: A previously obtained next page token if doing + pagination. Usually not needed as the iterator automatically + starts from the beginning. + rpc_metadata: Headers used on each RPC call. Keys here override + client-level RPC metadata keys. + rpc_timeout: Optional RPC deadline to set for each RPC call. + + Returns: + An async iterator that can be used with ``async for``. + """ + return self._impl.list_schedules( + ListSchedulesInput( + page_size=page_size, + next_page_token=next_page_token, + rpc_metadata=rpc_metadata, + rpc_timeout=rpc_timeout, + query=query, + ) + ) + + async def update_worker_build_id_compatibility( + self, + task_queue: str, + operation: BuildIdOp, + rpc_metadata: Mapping[str, str | bytes] = {}, + rpc_timeout: timedelta | None = None, + ) -> None: + """Used to add new Build IDs or otherwise update the relative compatibility of Build Ids as + defined on a specific task queue for the Worker Versioning feature. + + For more on this feature, see https://docs.temporal.io/workers#worker-versioning + + .. deprecated:: + Legacy API, see the docs above for new usage + + Args: + task_queue: The task queue to target. + operation: The operation to perform. + rpc_metadata: Headers used on each RPC call. Keys here override + client-level RPC metadata keys. + rpc_timeout: Optional RPC deadline to set for each RPC call. + """ + return await self._impl.update_worker_build_id_compatibility( + UpdateWorkerBuildIdCompatibilityInput( + task_queue, + operation, + rpc_metadata=rpc_metadata, + rpc_timeout=rpc_timeout, + ) + ) + + async def get_worker_build_id_compatibility( + self, + task_queue: str, + max_sets: int | None = None, + rpc_metadata: Mapping[str, str | bytes] = {}, + rpc_timeout: timedelta | None = None, + ) -> WorkerBuildIdVersionSets: + """Get the Build ID compatibility sets for a specific task queue. + + For more on this feature, see https://docs.temporal.io/workers#worker-versioning + + .. deprecated:: + Legacy API, see the docs above for new usage + + Args: + task_queue: The task queue to target. + max_sets: The maximum number of sets to return. If not specified, all sets will be + returned. + rpc_metadata: Headers used on each RPC call. Keys here override + client-level RPC metadata keys. + rpc_timeout: Optional RPC deadline to set for each RPC call. + """ + return await self._impl.get_worker_build_id_compatibility( + GetWorkerBuildIdCompatibilityInput( + task_queue, + max_sets, + rpc_metadata=rpc_metadata, + rpc_timeout=rpc_timeout, + ) + ) + + async def get_worker_task_reachability( + self, + build_ids: Sequence[str], + task_queues: Sequence[str] = [], + reachability_type: TaskReachabilityType | None = None, + rpc_metadata: Mapping[str, str | bytes] = {}, + rpc_timeout: timedelta | None = None, + ) -> WorkerTaskReachability: + """Determine if some Build IDs for certain Task Queues could have tasks dispatched to them. + + For more on this feature, see https://docs.temporal.io/workers#worker-versioning + + .. deprecated:: + Legacy API, see the docs above for new usage + + Args: + build_ids: The Build IDs to query the reachability of. At least one must be specified. + task_queues: Task Queues to restrict the query to. If not specified, all Task Queues + will be searched. When requesting a large number of task queues or all task queues + associated with the given Build IDs in a namespace, all Task Queues will be listed + in the response but some of them may not contain reachability information due to a + server enforced limit. When reaching the limit, task queues that reachability + information could not be retrieved for will be marked with a ``NotFetched`` entry in + {@link BuildIdReachability.taskQueueReachability}. The caller may issue another call + to get the reachability for those task queues. + reachability_type: The kind of reachability this request is concerned with. + rpc_metadata: Headers used on each RPC call. Keys here override + client-level RPC metadata keys. + rpc_timeout: Optional RPC deadline to set for each RPC call. + """ + return await self._impl.get_worker_task_reachability( + GetWorkerTaskReachabilityInput( + build_ids, + task_queues, + reachability_type, + rpc_metadata=rpc_metadata, + rpc_timeout=rpc_timeout, + ) + ) + + +class ClientConnectConfig(TypedDict, total=False): + """TypedDict of keyword arguments for :py:meth:`Client.connect`.""" + + target_host: str + namespace: str + api_key: str | None + data_converter: temporalio.converter.DataConverter + plugins: Sequence[Plugin] + interceptors: Sequence[Interceptor] + default_workflow_query_reject_condition: ( + temporalio.common.QueryRejectCondition | None + ) + tls: bool | TLSConfig | None + retry_config: RetryConfig | None + keep_alive_config: KeepAliveConfig | None + rpc_metadata: Mapping[str, str | bytes] + identity: str | None + lazy: bool + runtime: temporalio.runtime.Runtime | None + http_connect_proxy_config: HttpConnectProxyConfig | None + dns_load_balancing_config: DnsLoadBalancingConfig | None + header_codec_behavior: HeaderCodecBehavior + + +class ClientConfig(TypedDict, total=False): + """TypedDict of config originally passed to :py:meth:`Client`.""" + + service_client: Required[temporalio.service.ServiceClient] + namespace: Required[str] + data_converter: Required[temporalio.converter.DataConverter] + plugins: Required[Sequence[Plugin]] + interceptors: Required[Sequence[Interceptor]] + default_workflow_query_reject_condition: Required[ + temporalio.common.QueryRejectCondition | None + ] + header_codec_behavior: Required[HeaderCodecBehavior] diff --git a/temporalio/client/_cloud.py b/temporalio/client/_cloud.py new file mode 100644 index 000000000..51966666d --- /dev/null +++ b/temporalio/client/_cloud.py @@ -0,0 +1,181 @@ +"""Client support for accessing Temporal.""" + +from __future__ import annotations + +from collections.abc import ( + Mapping, +) + +import temporalio.runtime +import temporalio.service +from temporalio.service import ( + DnsLoadBalancingConfig, + HttpConnectProxyConfig, + KeepAliveConfig, + RetryConfig, + TLSConfig, +) + + +class CloudOperationsClient: + """Client for accessing Temporal Cloud Operations API. + + .. warning:: + This client and the API are experimental + + Most users will use :py:meth:`connect` to create a client. The + :py:attr:`cloud_service` property provides access to a raw gRPC cloud + service client. + + Clients are not thread-safe and should only be used in the event loop they + are first connected in. If a client needs to be used from another thread + than where it was created, make sure the event loop where it was created is + captured, and then call :py:func:`asyncio.run_coroutine_threadsafe` with the + client call and that event loop. + + Clients do not work across forks since runtimes do not work across forks. + """ + + @staticmethod + async def connect( + *, + api_key: str | None = None, + version: str | None = None, + target_host: str = "saas-api.tmprl.cloud:443", + tls: bool | TLSConfig = True, + retry_config: RetryConfig | None = None, + keep_alive_config: KeepAliveConfig | None = KeepAliveConfig.default, + rpc_metadata: Mapping[str, str | bytes] = {}, + identity: str | None = None, + lazy: bool = False, + runtime: temporalio.runtime.Runtime | None = None, + http_connect_proxy_config: HttpConnectProxyConfig | None = None, + dns_load_balancing_config: DnsLoadBalancingConfig | None = None, + ) -> CloudOperationsClient: + """Connect to a Temporal Cloud Operations API. + + .. warning:: + This client and the API are experimental + + Args: + api_key: API key for Temporal. This becomes the "Authorization" + HTTP header with "Bearer " prepended. This is only set if RPC + metadata doesn't already have an "authorization" key. This is + essentially required for access to the cloud API. + version: Version header for safer mutations. May or may not be + required depending on cloud settings. + target_host: ``host:port`` for the Temporal server. The default is + to the common cloud endpoint. + tls: If true, the default, use system default TLS configuration. If + false, the default, do not use TLS. If TLS configuration + present, that TLS configuration will be used. The default is + usually required to access the API. + retry_config: Retry configuration for direct service calls (when + opted in) or all high-level calls made by this client (which all + opt-in to retries by default). If unset, a default retry + configuration is used. + keep_alive_config: Keep-alive configuration for the client + connection. Default is to check every 30s and kill the + connection if a response doesn't come back in 15s. Can be set to + ``None`` to disable. + rpc_metadata: Headers to use for all calls to the server. Keys here + can be overriden by per-call RPC metadata keys. + identity: Identity for this client. If unset, a default is created + based on the version of the SDK. + lazy: If true, the client will not connect until the first call is + attempted or a worker is created with it. Lazy clients cannot be + used for workers. + runtime: The runtime for this client, or the default if unset. + http_connect_proxy_config: Configuration for HTTP CONNECT proxy. + dns_load_balancing_config: DNS load balancing configuration for the + client connection. Default is disabled. Silently disabled when + ``http_connect_proxy_config`` is set, since the two are mutually + exclusive. + """ + # Add version if given + if version: + rpc_metadata = dict(rpc_metadata) + rpc_metadata["temporal-cloud-api-version"] = version + connect_config = temporalio.service.ConnectConfig( + target_host=target_host, + api_key=api_key, + tls=tls, + retry_config=retry_config, + keep_alive_config=keep_alive_config, + rpc_metadata=rpc_metadata, + identity=identity or "", + lazy=lazy, + runtime=runtime, + http_connect_proxy_config=http_connect_proxy_config, + dns_load_balancing_config=dns_load_balancing_config, + ) + return CloudOperationsClient( + await temporalio.service.ServiceClient.connect(connect_config) + ) + + def __init__( + self, + service_client: temporalio.service.ServiceClient, + ): + """Create a Temporal Cloud Operations client from a service client. + + .. warning:: + This client and the API are experimental + + Args: + service_client: Existing service client to use. + """ + self._service_client = service_client + + @property + def service_client(self) -> temporalio.service.ServiceClient: + """Raw gRPC service client.""" + return self._service_client + + @property + def cloud_service(self) -> temporalio.service.CloudService: + """Raw gRPC cloud service client.""" + return self._service_client.cloud_service + + @property + def identity(self) -> str: + """Identity used in calls by this client.""" + return self._service_client.config.identity + + @property + def rpc_metadata(self) -> Mapping[str, str | bytes]: + """Headers for every call made by this client. + + Do not use mutate this mapping. Rather, set this property with an + entirely new mapping to change the headers. This may include the + ``temporal-cloud-api-version`` header if set. + """ + return self.service_client.config.rpc_metadata + + @rpc_metadata.setter + def rpc_metadata(self, value: Mapping[str, str | bytes]) -> None: + """Update the headers for this client. + + Do not mutate this mapping after set. Rather, set an entirely new + mapping if changes are needed. Currently this must be set with the + ``temporal-cloud-api-version`` header if it is needed. + """ + # Update config and perform update + self.service_client.config.rpc_metadata = value + self.service_client.update_rpc_metadata(value) + + @property + def api_key(self) -> str | None: + """API key for every call made by this client.""" + return self.service_client.config.api_key + + @api_key.setter + def api_key(self, value: str | None) -> None: + """Update the API key for this client. + + This is only set if RPCmetadata doesn't already have an "authorization" + key. + """ + # Update config and perform update + self.service_client.config.api_key = value + self.service_client.update_api_key(value) diff --git a/temporalio/client/_exceptions.py b/temporalio/client/_exceptions.py new file mode 100644 index 000000000..fdcd263e6 --- /dev/null +++ b/temporalio/client/_exceptions.py @@ -0,0 +1,139 @@ +"""Client support for accessing Temporal.""" + +from __future__ import annotations + +from typing import ( + TYPE_CHECKING, +) + +import temporalio.exceptions +from temporalio.activity import ActivityCancellationDetails + +if TYPE_CHECKING: + from ._workflow import WorkflowExecutionStatus + + +class WorkflowFailureError(temporalio.exceptions.TemporalError): + """Error that occurs when a workflow is unsuccessful.""" + + def __init__(self, *, cause: BaseException) -> None: + """Create workflow failure error.""" + super().__init__("Workflow execution failed") + self.__cause__ = cause + + @property + def cause(self) -> BaseException: + """Cause of the workflow failure.""" + assert self.__cause__ + return self.__cause__ + + +class WorkflowContinuedAsNewError(temporalio.exceptions.TemporalError): + """Error that occurs when a workflow was continued as new.""" + + def __init__(self, new_execution_run_id: str) -> None: + """Create workflow continue as new error.""" + super().__init__("Workflow continued as new") + self._new_execution_run_id = new_execution_run_id + + @property + def new_execution_run_id(self) -> str: + """New execution run ID the workflow continued to""" + return self._new_execution_run_id + + +class WorkflowQueryRejectedError(temporalio.exceptions.TemporalError): + """Error that occurs when a query was rejected.""" + + def __init__(self, status: WorkflowExecutionStatus | None) -> None: + """Create workflow query rejected error.""" + super().__init__(f"Query rejected, status: {status}") + self._status = status + + @property + def status(self) -> WorkflowExecutionStatus | None: + """Get workflow execution status causing rejection.""" + return self._status + + +class WorkflowQueryFailedError(temporalio.exceptions.TemporalError): + """Error that occurs when a query fails.""" + + def __init__(self, message: str) -> None: + """Create workflow query failed error.""" + super().__init__(message) + self._message = message + + @property + def message(self) -> str: + """Get query failed message.""" + return self._message + + +class WorkflowUpdateFailedError(temporalio.exceptions.TemporalError): + """Error that occurs when an update fails.""" + + def __init__(self, cause: BaseException) -> None: + """Create workflow update failed error.""" + super().__init__("Workflow update failed") + self.__cause__ = cause + + @property + def cause(self) -> BaseException: + """Cause of the update failure.""" + assert self.__cause__ + return self.__cause__ + + +class RPCTimeoutOrCancelledError(temporalio.exceptions.TemporalError): + """Error that occurs on some client calls that timeout or get cancelled.""" + + pass + + +class WorkflowUpdateRPCTimeoutOrCancelledError(RPCTimeoutOrCancelledError): + """Error that occurs when update RPC call times out or is cancelled. + + Note, this is not related to any general concept of timing out or cancelling + a running update, this is only related to the client call itself. + """ + + def __init__(self) -> None: + """Create workflow update timeout or cancelled error.""" + super().__init__("Timeout or cancellation waiting for update") + + +class ActivityFailureError(temporalio.exceptions.TemporalError): + """Error that occurs when an activity is unsuccessful. + + .. warning:: + This API is experimental. + """ + + def __init__(self, *, cause: BaseException) -> None: + """Create activity failure error.""" + super().__init__("Activity execution failed") + self.__cause__ = cause + + @property + def cause(self) -> BaseException: + """Cause of the activity failure.""" + assert self.__cause__ + return self.__cause__ + + +class AsyncActivityCancelledError(temporalio.exceptions.TemporalError): + """Error that occurs when async activity attempted heartbeat but was cancelled.""" + + def __init__(self, details: ActivityCancellationDetails | None = None) -> None: + """Create async activity cancelled error.""" + super().__init__("Activity cancelled") + self.details = details + + +class ScheduleAlreadyRunningError(temporalio.exceptions.TemporalError): + """Error when a schedule is already running.""" + + def __init__(self) -> None: + """Create schedule already running error.""" + super().__init__("Schedule already running") diff --git a/temporalio/client/_helpers.py b/temporalio/client/_helpers.py new file mode 100644 index 000000000..08a584651 --- /dev/null +++ b/temporalio/client/_helpers.py @@ -0,0 +1,202 @@ +"""Client support for accessing Temporal.""" + +from __future__ import annotations + +import copy +import json +import re +from collections.abc import ( + Iterable, + Mapping, +) +from typing import ( + Any, +) + +import google.protobuf.json_format +from google.protobuf.internal.containers import MessageMap + +import temporalio.api.common.v1 +import temporalio.api.history.v1 +import temporalio.api.sdk.v1 +import temporalio.common +import temporalio.converter +from temporalio.converter import ( + DataConverter, +) + + +async def _apply_headers( # pyright: ignore[reportUnusedFunction] + source: Mapping[str, temporalio.api.common.v1.Payload] | None, + dest: MessageMap[str, temporalio.api.common.v1.Payload], + encode_headers: bool, + data_converter: DataConverter, +) -> None: + if source is None: + return + if encode_headers: + for payload in source.values(): + payload.CopyFrom(await data_converter._transform_outbound_payload(payload)) + temporalio.common._apply_headers(source, dest) + + +def _history_from_json( # pyright: ignore[reportUnusedFunction] + history: str | dict[str, Any], +) -> temporalio.api.history.v1.History: + if isinstance(history, str): + history = json.loads(history) + else: + # Copy the dict so we can mutate it + history = copy.deepcopy(history) + if not isinstance(history, dict): + raise ValueError("JSON history not a dictionary") + events = history.get("events") + if not isinstance(events, Iterable): + raise ValueError("History does not have iterable 'events'") + for event in events: + if not isinstance(event, dict): + raise ValueError("Event not a dictionary") + _fix_history_enum( + "CANCEL_EXTERNAL_WORKFLOW_EXECUTION_FAILED_CAUSE", + event, + "requestCancelExternalWorkflowExecutionFailedEventAttributes", + "cause", + ) + _fix_history_enum("CONTINUE_AS_NEW_INITIATOR", event, "*", "initiator") + _fix_history_enum("EVENT_TYPE", event, "eventType") + _fix_history_enum( + "PARENT_CLOSE_POLICY", + event, + "startChildWorkflowExecutionInitiatedEventAttributes", + "parentClosePolicy", + ) + _fix_history_enum("RETRY_STATE", event, "*", "retryState") + _fix_history_enum( + "SIGNAL_EXTERNAL_WORKFLOW_EXECUTION_FAILED_CAUSE", + event, + "signalExternalWorkflowExecutionFailedEventAttributes", + "cause", + ) + _fix_history_enum( + "START_CHILD_WORKFLOW_EXECUTION_FAILED_CAUSE", + event, + "startChildWorkflowExecutionFailedEventAttributes", + "cause", + ) + _fix_history_enum("TASK_QUEUE_KIND", event, "*", "taskQueue", "kind") + _fix_history_enum( + "TIMEOUT_TYPE", + event, + "workflowTaskTimedOutEventAttributes", + "timeoutType", + ) + _fix_history_enum( + "WORKFLOW_ID_REUSE_POLICY", + event, + "startChildWorkflowExecutionInitiatedEventAttributes", + "workflowIdReusePolicy", + ) + _fix_history_enum( + "WORKFLOW_TASK_FAILED_CAUSE", + event, + "workflowTaskFailedEventAttributes", + "cause", + ) + _fix_history_failure(event, "*", "failure") + _fix_history_failure(event, "activityTaskStartedEventAttributes", "lastFailure") + _fix_history_failure( + event, "workflowExecutionStartedEventAttributes", "continuedFailure" + ) + return google.protobuf.json_format.ParseDict( + history, temporalio.api.history.v1.History(), ignore_unknown_fields=True + ) + + +def _fix_history_failure(parent: dict[str, Any], *attrs: str) -> None: + _fix_history_enum( + "TIMEOUT_TYPE", parent, *attrs, "timeoutFailureInfo", "timeoutType" + ) + _fix_history_enum("RETRY_STATE", parent, *attrs, "*", "retryState") + # Recurse into causes. First collect all failure parents. + parents = [parent] + for attr in attrs: + new_parents = [] + for parent in parents: + if attr == "*": + for v in parent.values(): + if isinstance(v, dict): + new_parents.append(v) + else: + child = parent.get(attr) + if isinstance(child, dict): + new_parents.append(child) + if not new_parents: + return + parents = new_parents + # Fix each + for parent in parents: + _fix_history_failure(parent, "cause") + + +_pascal_case_match = re.compile("([A-Z]+)") + + +def _fix_history_enum(prefix: str, parent: dict[str, Any], *attrs: str) -> None: + # If the attr is "*", we need to handle all dict children + if attrs[0] == "*": + for child in parent.values(): + if isinstance(child, dict): + _fix_history_enum(prefix, child, *attrs[1:]) + else: + child = parent.get(attrs[0]) + if isinstance(child, str) and len(attrs) == 1: + # We only fix it if it doesn't already have the prefix + if not parent[attrs[0]].startswith(prefix): + parent[attrs[0]] = ( + prefix + _pascal_case_match.sub(r"_\1", child).upper() + ) + elif isinstance(child, dict) and len(attrs) > 1: + _fix_history_enum(prefix, child, *attrs[1:]) + elif isinstance(child, list) and len(attrs) > 1: + for child_item in child: + if isinstance(child_item, dict): + _fix_history_enum(prefix, child_item, *attrs[1:]) + + +async def _encode_user_metadata( # pyright: ignore[reportUnusedFunction] + converter: temporalio.converter.DataConverter, + summary: str | temporalio.api.common.v1.Payload | None, + details: str | temporalio.api.common.v1.Payload | None, +) -> temporalio.api.sdk.v1.UserMetadata | None: + if summary is None and details is None: + return None + enc_summary = None + enc_details = None + if summary is not None: + if isinstance(summary, str): + enc_summary = (await converter.encode([summary]))[0] + else: + enc_summary = summary + if details is not None: + if isinstance(details, str): + enc_details = (await converter.encode([details]))[0] + else: + enc_details = details + return temporalio.api.sdk.v1.UserMetadata(summary=enc_summary, details=enc_details) + + +async def _decode_user_metadata( # pyright: ignore[reportUnusedFunction] + converter: temporalio.converter.DataConverter, + metadata: temporalio.api.sdk.v1.UserMetadata | None, +) -> tuple[str | None, str | None]: + """Returns (summary, details)""" + if metadata is None: + return None, None + return ( + None + if not metadata.HasField("summary") + else (await converter.decode([metadata.summary]))[0], + None + if not metadata.HasField("details") + else (await converter.decode([metadata.details]))[0], + ) diff --git a/temporalio/client/_impl.py b/temporalio/client/_impl.py new file mode 100644 index 000000000..0c05a2dd7 --- /dev/null +++ b/temporalio/client/_impl.py @@ -0,0 +1,1410 @@ +"""Client support for accessing Temporal.""" + +from __future__ import annotations + +import asyncio +import inspect +import uuid +import warnings +from collections.abc import ( + Callable, + Mapping, +) +from datetime import timedelta +from typing import ( + TYPE_CHECKING, + Any, + cast, +) + +from google.protobuf.internal.containers import MessageMap + +import temporalio.api.common.v1 +import temporalio.api.enums.v1 +import temporalio.api.errordetails.v1 +import temporalio.api.failure.v1 +import temporalio.api.schedule.v1 +import temporalio.api.taskqueue.v1 +import temporalio.api.update.v1 +import temporalio.api.workflowservice.v1 +import temporalio.common +import temporalio.converter +import temporalio.exceptions +import temporalio.nexus +import temporalio.nexus._operation_context +from temporalio.activity import ActivityCancellationDetails +from temporalio.converter import ( + ActivitySerializationContext, + StorageDriverActivityInfo, + StorageDriverStoreContext, + StorageDriverWorkflowInfo, + WorkflowSerializationContext, +) +from temporalio.service import ( + RPCError, + RPCStatusCode, +) + +from ..common import HeaderCodecBehavior +from ._activity import ( + ActivityExecutionAsyncIterator, + ActivityExecutionCount, + ActivityExecutionDescription, + ActivityHandle, + AsyncActivityIDReference, +) +from ._exceptions import ( + AsyncActivityCancelledError, + ScheduleAlreadyRunningError, + WorkflowQueryFailedError, + WorkflowQueryRejectedError, + WorkflowUpdateRPCTimeoutOrCancelledError, +) +from ._helpers import _apply_headers, _encode_user_metadata +from ._interceptor import ( + BackfillScheduleInput, + CancelActivityInput, + CancelWorkflowInput, + CompleteAsyncActivityInput, + CountActivitiesInput, + CountWorkflowsInput, + CreateScheduleInput, + DeleteScheduleInput, + DescribeActivityInput, + DescribeScheduleInput, + DescribeWorkflowInput, + FailAsyncActivityInput, + FetchWorkflowHistoryEventsInput, + GetWorkerBuildIdCompatibilityInput, + GetWorkerTaskReachabilityInput, + HeartbeatAsyncActivityInput, + ListActivitiesInput, + ListSchedulesInput, + ListWorkflowsInput, + OutboundInterceptor, + PauseScheduleInput, + QueryWorkflowInput, + ReportCancellationAsyncActivityInput, + SignalWorkflowInput, + StartActivityInput, + StartWorkflowInput, + StartWorkflowUpdateInput, + StartWorkflowUpdateWithStartInput, + TerminateActivityInput, + TerminateWorkflowInput, + TriggerScheduleInput, + UnpauseScheduleInput, + UpdateScheduleInput, + UpdateWithStartStartWorkflowInput, + UpdateWithStartUpdateWorkflowInput, + UpdateWorkerBuildIdCompatibilityInput, +) +from ._schedule import ( + ScheduleAsyncIterator, + ScheduleDescription, + ScheduleHandle, + ScheduleUpdate, + ScheduleUpdateInput, +) +from ._worker_versioning import WorkerBuildIdVersionSets, WorkerTaskReachability +from ._workflow import ( + WorkflowExecutionAsyncIterator, + WorkflowExecutionCount, + WorkflowExecutionDescription, + WorkflowExecutionStatus, + WorkflowHandle, + WorkflowHistoryEventAsyncIterator, + WorkflowUpdateHandle, + WorkflowUpdateStage, +) + +if TYPE_CHECKING: + from ._client import Client + + +class _ClientImpl(OutboundInterceptor): # pyright: ignore[reportUnusedClass] + def __init__(self, client: Client) -> None: # type: ignore + # We are intentionally not calling the base class's __init__ here + self._client = client + + ### Workflow calls + + async def start_workflow( + self, input: StartWorkflowInput + ) -> WorkflowHandle[Any, Any]: + req: ( + temporalio.api.workflowservice.v1.StartWorkflowExecutionRequest + | temporalio.api.workflowservice.v1.SignalWithStartWorkflowExecutionRequest + ) + if input.start_signal is not None: + req = await self._build_signal_with_start_workflow_execution_request(input) + else: + req = await self._build_start_workflow_execution_request(input) + + resp: ( + temporalio.api.workflowservice.v1.StartWorkflowExecutionResponse + | temporalio.api.workflowservice.v1.SignalWithStartWorkflowExecutionResponse + ) + first_execution_run_id = None + eagerly_started = False + try: + if isinstance( + req, + temporalio.api.workflowservice.v1.SignalWithStartWorkflowExecutionRequest, + ): + resp = await self._client.workflow_service.signal_with_start_workflow_execution( + req, + retry=True, + metadata=input.rpc_metadata, + timeout=input.rpc_timeout, + ) + else: + resp = await self._client.workflow_service.start_workflow_execution( + req, + retry=True, + metadata=input.rpc_metadata, + timeout=input.rpc_timeout, + ) + first_execution_run_id = resp.run_id + eagerly_started = resp.HasField("eager_workflow_task") + except RPCError as err: + # If the status is ALREADY_EXISTS and the details can be extracted + # as already started, use a different exception + if err.status == RPCStatusCode.ALREADY_EXISTS and err.grpc_status.details: + details = temporalio.api.errordetails.v1.WorkflowExecutionAlreadyStartedFailure() + if err.grpc_status.details[0].Unpack(details): + raise temporalio.exceptions.WorkflowAlreadyStartedError( + input.id, input.workflow, run_id=details.run_id + ) + raise + handle: WorkflowHandle[Any, Any] = WorkflowHandle( + self._client, + req.workflow_id, + result_run_id=resp.run_id, + first_execution_run_id=first_execution_run_id, + result_type=input.ret_type, + start_workflow_response=resp, + ) + setattr(handle, "__temporal_eagerly_started", eagerly_started) + return handle + + async def _build_start_workflow_execution_request( + self, input: StartWorkflowInput + ) -> temporalio.api.workflowservice.v1.StartWorkflowExecutionRequest: + req = temporalio.api.workflowservice.v1.StartWorkflowExecutionRequest() + await self._populate_start_workflow_execution_request(req, input) + # _populate_start_workflow_execution_request is used for both StartWorkflowInput + # and UpdateWithStartStartWorkflowInput. UpdateWithStartStartWorkflowInput does + # not have the following two fields so they are handled here. + req.request_eager_execution = input.request_eager_start + if input.request_id: + req.request_id = input.request_id + + links = [ + temporalio.api.common.v1.Link(workflow_event=link) + for link in input.workflow_event_links + ] + req.completion_callbacks.extend( + temporalio.api.common.v1.Callback( + nexus=temporalio.api.common.v1.Callback.Nexus( + url=callback.url, + header=callback.headers, + ), + links=links, + ) + for callback in input.callbacks + ) + # Links are duplicated on request for compatibility with older server versions. + req.links.extend(links) + + if temporalio.nexus._operation_context._in_nexus_backing_workflow_start_context(): + req.on_conflict_options.attach_request_id = True + req.on_conflict_options.attach_completion_callbacks = True + req.on_conflict_options.attach_links = True + + return req + + async def _build_signal_with_start_workflow_execution_request( + self, input: StartWorkflowInput + ) -> temporalio.api.workflowservice.v1.SignalWithStartWorkflowExecutionRequest: + assert input.start_signal + data_converter = self._client.data_converter._with_contexts( + WorkflowSerializationContext( + namespace=self._client.namespace, + workflow_id=input.id, + ), + StorageDriverStoreContext( + target=StorageDriverWorkflowInfo( + id=input.id, type=input.workflow, namespace=self._client.namespace + ), + ), + ) + req = temporalio.api.workflowservice.v1.SignalWithStartWorkflowExecutionRequest( + signal_name=input.start_signal + ) + if input.start_signal_args: + req.signal_input.payloads.extend( + await data_converter.encode(input.start_signal_args) + ) + await self._populate_start_workflow_execution_request(req, input) + return req + + async def _build_update_with_start_start_workflow_execution_request( + self, input: UpdateWithStartStartWorkflowInput + ) -> temporalio.api.workflowservice.v1.StartWorkflowExecutionRequest: + req = temporalio.api.workflowservice.v1.StartWorkflowExecutionRequest() + await self._populate_start_workflow_execution_request(req, input) + return req + + async def _populate_start_workflow_execution_request( + self, + req: ( + temporalio.api.workflowservice.v1.StartWorkflowExecutionRequest + | temporalio.api.workflowservice.v1.SignalWithStartWorkflowExecutionRequest + ), + input: StartWorkflowInput | UpdateWithStartStartWorkflowInput, + ) -> None: + data_converter = self._client.data_converter._with_contexts( + WorkflowSerializationContext( + namespace=self._client.namespace, + workflow_id=input.id, + ), + StorageDriverStoreContext( + target=StorageDriverWorkflowInfo( + id=input.id, type=input.workflow, namespace=self._client.namespace + ), + ), + ) + req.namespace = self._client.namespace + req.workflow_id = input.id + req.workflow_type.name = input.workflow + req.task_queue.name = input.task_queue + if input.args: + req.input.payloads.extend(await data_converter.encode(input.args)) + if input.execution_timeout is not None: + req.workflow_execution_timeout.FromTimedelta(input.execution_timeout) + if input.run_timeout is not None: + req.workflow_run_timeout.FromTimedelta(input.run_timeout) + if input.task_timeout is not None: + req.workflow_task_timeout.FromTimedelta(input.task_timeout) + req.identity = self._client.identity + req.request_id = str(uuid.uuid4()) + req.workflow_id_reuse_policy = cast( + "temporalio.api.enums.v1.WorkflowIdReusePolicy.ValueType", + int(input.id_reuse_policy), + ) + req.workflow_id_conflict_policy = cast( + "temporalio.api.enums.v1.WorkflowIdConflictPolicy.ValueType", + int(input.id_conflict_policy), + ) + + if input.retry_policy is not None: + input.retry_policy.apply_to_proto(req.retry_policy) + req.cron_schedule = input.cron_schedule + if input.memo is not None: + await data_converter._encode_memo_existing(input.memo, req.memo) + if input.search_attributes is not None: + temporalio.converter.encode_search_attributes( + input.search_attributes, req.search_attributes + ) + metadata = await _encode_user_metadata( + data_converter, input.static_summary, input.static_details + ) + if metadata is not None: + req.user_metadata.CopyFrom(metadata) + if input.start_delay is not None: + req.workflow_start_delay.FromTimedelta(input.start_delay) + if input.headers is not None: # type:ignore[reportUnnecessaryComparison] + await self._apply_headers(input.headers, req.header.fields) + if input.priority is not None: # type:ignore[reportUnnecessaryComparison] + req.priority.CopyFrom(input.priority._to_proto()) + if input.versioning_override is not None: + req.versioning_override.CopyFrom(input.versioning_override._to_proto()) + + async def cancel_workflow(self, input: CancelWorkflowInput) -> None: + await self._client.workflow_service.request_cancel_workflow_execution( + temporalio.api.workflowservice.v1.RequestCancelWorkflowExecutionRequest( + namespace=self._client.namespace, + workflow_execution=temporalio.api.common.v1.WorkflowExecution( + workflow_id=input.id, + run_id=input.run_id or "", + ), + identity=self._client.identity, + request_id=str(uuid.uuid4()), + first_execution_run_id=input.first_execution_run_id or "", + ), + retry=True, + metadata=input.rpc_metadata, + timeout=input.rpc_timeout, + ) + + async def describe_workflow( + self, input: DescribeWorkflowInput + ) -> WorkflowExecutionDescription: + return await WorkflowExecutionDescription._from_raw_description( + await self._client.workflow_service.describe_workflow_execution( + temporalio.api.workflowservice.v1.DescribeWorkflowExecutionRequest( + namespace=self._client.namespace, + execution=temporalio.api.common.v1.WorkflowExecution( + workflow_id=input.id, + run_id=input.run_id or "", + ), + ), + retry=True, + metadata=input.rpc_metadata, + timeout=input.rpc_timeout, + ), + namespace=self._client.namespace, + converter=self._client.data_converter.with_context( + WorkflowSerializationContext( + namespace=self._client.namespace, + workflow_id=input.id, + ) + ), + ) + + def fetch_workflow_history_events( + self, input: FetchWorkflowHistoryEventsInput + ) -> WorkflowHistoryEventAsyncIterator: + return WorkflowHistoryEventAsyncIterator(self._client, input) + + def list_workflows( + self, input: ListWorkflowsInput + ) -> WorkflowExecutionAsyncIterator: + return WorkflowExecutionAsyncIterator(self._client, input) + + async def count_workflows( + self, input: CountWorkflowsInput + ) -> WorkflowExecutionCount: + return WorkflowExecutionCount._from_raw( + await self._client.workflow_service.count_workflow_executions( + temporalio.api.workflowservice.v1.CountWorkflowExecutionsRequest( + namespace=self._client.namespace, + query=input.query or "", + ), + retry=True, + metadata=input.rpc_metadata, + timeout=input.rpc_timeout, + ) + ) + + async def query_workflow(self, input: QueryWorkflowInput) -> Any: + data_converter = self._client.data_converter._with_contexts( + WorkflowSerializationContext( + namespace=self._client.namespace, + workflow_id=input.id, + ), + StorageDriverStoreContext( + target=StorageDriverWorkflowInfo( + id=input.id, + run_id=input.run_id or None, + namespace=self._client.namespace, + ), + ), + ) + req = temporalio.api.workflowservice.v1.QueryWorkflowRequest( + namespace=self._client.namespace, + execution=temporalio.api.common.v1.WorkflowExecution( + workflow_id=input.id, + run_id=input.run_id or "", + ), + ) + if input.reject_condition: + req.query_reject_condition = cast( + "temporalio.api.enums.v1.QueryRejectCondition.ValueType", + int(input.reject_condition), + ) + req.query.query_type = input.query + if input.args: + req.query.query_args.payloads.extend( + await data_converter.encode(input.args) + ) + if input.headers is not None: # type:ignore[reportUnnecessaryComparison] + await self._apply_headers(input.headers, req.query.header.fields) + try: + resp = await self._client.workflow_service.query_workflow( + req, + retry=True, + metadata=input.rpc_metadata, + timeout=input.rpc_timeout, + ) + except RPCError as err: + # If the status is INVALID_ARGUMENT, we can assume it's a query + # failed error + if err.status == RPCStatusCode.INVALID_ARGUMENT: + raise WorkflowQueryFailedError(err.message) + else: + raise + if resp.HasField("query_rejected"): + raise WorkflowQueryRejectedError( + WorkflowExecutionStatus(resp.query_rejected.status) + if resp.query_rejected.status + else None + ) + if not resp.query_result.payloads: + return None + type_hints = [input.ret_type] if input.ret_type else None + results = await data_converter.decode(resp.query_result.payloads, type_hints) + if not results: + return None + elif len(results) > 1: + warnings.warn(f"Expected single query result, got {len(results)}") + return results[0] + + async def signal_workflow(self, input: SignalWorkflowInput) -> None: + data_converter = self._client.data_converter._with_contexts( + WorkflowSerializationContext( + namespace=self._client.namespace, + workflow_id=input.id, + ), + StorageDriverStoreContext( + target=StorageDriverWorkflowInfo( + id=input.id, + run_id=input.run_id or None, + namespace=self._client.namespace, + ), + ), + ) + req = temporalio.api.workflowservice.v1.SignalWorkflowExecutionRequest( + namespace=self._client.namespace, + workflow_execution=temporalio.api.common.v1.WorkflowExecution( + workflow_id=input.id, + run_id=input.run_id or "", + ), + signal_name=input.signal, + identity=self._client.identity, + request_id=str(uuid.uuid4()), + ) + if input.args: + req.input.payloads.extend(await data_converter.encode(input.args)) + if input.headers is not None: # type:ignore[reportUnnecessaryComparison] + await self._apply_headers(input.headers, req.header.fields) + await self._client.workflow_service.signal_workflow_execution( + req, retry=True, metadata=input.rpc_metadata, timeout=input.rpc_timeout + ) + + async def terminate_workflow(self, input: TerminateWorkflowInput) -> None: + data_converter = self._client.data_converter._with_contexts( + WorkflowSerializationContext( + namespace=self._client.namespace, + workflow_id=input.id, + ), + StorageDriverStoreContext( + target=StorageDriverWorkflowInfo( + id=input.id, + run_id=input.run_id or None, + namespace=self._client.namespace, + ), + ), + ) + req = temporalio.api.workflowservice.v1.TerminateWorkflowExecutionRequest( + namespace=self._client.namespace, + workflow_execution=temporalio.api.common.v1.WorkflowExecution( + workflow_id=input.id, + run_id=input.run_id or "", + ), + reason=input.reason or "", + identity=self._client.identity, + first_execution_run_id=input.first_execution_run_id or "", + ) + if input.args: + req.details.payloads.extend(await data_converter.encode(input.args)) + await self._client.workflow_service.terminate_workflow_execution( + req, retry=True, metadata=input.rpc_metadata, timeout=input.rpc_timeout + ) + + async def start_activity(self, input: StartActivityInput) -> ActivityHandle[Any]: + """Start an activity and return a handle to it.""" + if not (input.start_to_close_timeout or input.schedule_to_close_timeout): + raise ValueError( + "Activity must have start_to_close_timeout or schedule_to_close_timeout" + ) + if input.start_delay is not None and input.start_delay < timedelta(0): + raise ValueError("start_delay must be non-negative") + req = await self._build_start_activity_execution_request(input) + + resp: temporalio.api.workflowservice.v1.StartActivityExecutionResponse + try: + resp = await self._client.workflow_service.start_activity_execution( + req, + retry=True, + metadata=input.rpc_metadata, + timeout=input.rpc_timeout, + ) + except RPCError as err: + # If the status is ALREADY_EXISTS and the details can be extracted + # as already started, use a different exception + if err.status == RPCStatusCode.ALREADY_EXISTS and err.grpc_status.details: + details = temporalio.api.errordetails.v1.ActivityExecutionAlreadyStartedFailure() + if err.grpc_status.details[0].Unpack(details): + raise temporalio.exceptions.ActivityAlreadyStartedError( + input.id, input.activity_type, run_id=details.run_id + ) + raise + return ActivityHandle( + self._client, + input.id, + run_id=resp.run_id, + result_type=input.result_type, + ) + + async def _build_start_activity_execution_request( + self, input: StartActivityInput + ) -> temporalio.api.workflowservice.v1.StartActivityExecutionRequest: + """Build StartActivityExecutionRequest from input.""" + data_converter = self._client.data_converter._with_contexts( + ActivitySerializationContext( + namespace=self._client.namespace, + activity_id=input.id, + activity_type=input.activity_type, + activity_task_queue=input.task_queue, + is_local=False, + workflow_id=None, + workflow_type=None, + ), + StorageDriverStoreContext( + target=StorageDriverActivityInfo( + id=input.id, + type=input.activity_type, + namespace=self._client.namespace, + ), + ), + ) + + req = temporalio.api.workflowservice.v1.StartActivityExecutionRequest( + namespace=self._client.namespace, + identity=self._client.identity, + activity_id=input.id, + activity_type=temporalio.api.common.v1.ActivityType( + name=input.activity_type + ), + task_queue=temporalio.api.taskqueue.v1.TaskQueue(name=input.task_queue), + id_reuse_policy=cast( + "temporalio.api.enums.v1.ActivityIdReusePolicy.ValueType", + int(input.id_reuse_policy), + ), + id_conflict_policy=cast( + "temporalio.api.enums.v1.ActivityIdConflictPolicy.ValueType", + int(input.id_conflict_policy), + ), + ) + + if input.schedule_to_close_timeout is not None: + req.schedule_to_close_timeout.FromTimedelta(input.schedule_to_close_timeout) + if input.start_to_close_timeout is not None: + req.start_to_close_timeout.FromTimedelta(input.start_to_close_timeout) + if input.schedule_to_start_timeout is not None: + req.schedule_to_start_timeout.FromTimedelta(input.schedule_to_start_timeout) + if input.heartbeat_timeout is not None: + req.heartbeat_timeout.FromTimedelta(input.heartbeat_timeout) + if input.start_delay is not None: + req.start_delay.FromTimedelta(input.start_delay) + if input.retry_policy is not None: + input.retry_policy.apply_to_proto(req.retry_policy) + + # Set input payloads + if input.args: + req.input.payloads.extend(await data_converter.encode(input.args)) + + # Set search attributes + if input.search_attributes is not None: + temporalio.converter.encode_search_attributes( + input.search_attributes, req.search_attributes + ) + + # Set user metadata + metadata = await _encode_user_metadata(data_converter, input.summary, None) + if metadata is not None: + req.user_metadata.CopyFrom(metadata) + + # Set headers + if input.headers: + await self._apply_headers(input.headers, req.header.fields) + + # Set priority + req.priority.CopyFrom(input.priority._to_proto()) + + return req + + async def cancel_activity(self, input: CancelActivityInput) -> None: + """Cancel an activity.""" + await self._client.workflow_service.request_cancel_activity_execution( + temporalio.api.workflowservice.v1.RequestCancelActivityExecutionRequest( + namespace=self._client.namespace, + activity_id=input.activity_id, + run_id=input.activity_run_id or "", + identity=self._client.identity, + request_id=str(uuid.uuid4()), + reason=input.reason or "", + ), + retry=True, + metadata=input.rpc_metadata, + timeout=input.rpc_timeout, + ) + + async def terminate_activity(self, input: TerminateActivityInput) -> None: + """Terminate an activity.""" + await self._client.workflow_service.terminate_activity_execution( + temporalio.api.workflowservice.v1.TerminateActivityExecutionRequest( + namespace=self._client.namespace, + activity_id=input.activity_id, + run_id=input.activity_run_id or "", + reason=input.reason or "", + identity=self._client.identity, + ), + retry=True, + metadata=input.rpc_metadata, + timeout=input.rpc_timeout, + ) + + async def describe_activity( + self, input: DescribeActivityInput + ) -> ActivityExecutionDescription: + """Describe an activity.""" + resp = await self._client.workflow_service.describe_activity_execution( + temporalio.api.workflowservice.v1.DescribeActivityExecutionRequest( + namespace=self._client.namespace, + activity_id=input.activity_id, + run_id=input.activity_run_id or "", + long_poll_token=input.long_poll_token or b"", + ), + retry=True, + metadata=input.rpc_metadata, + timeout=input.rpc_timeout, + ) + return await ActivityExecutionDescription._from_execution_info( + info=resp.info, + long_poll_token=resp.long_poll_token or None, + namespace=self._client.namespace, + data_converter=self._client.data_converter.with_context( + WorkflowSerializationContext( + namespace=self._client.namespace, + workflow_id=input.activity_id, # Using activity_id as workflow_id for activities not started by a workflow + ) + ), + ) + + def list_activities( + self, input: ListActivitiesInput + ) -> ActivityExecutionAsyncIterator: + return ActivityExecutionAsyncIterator(self._client, input) + + async def count_activities( + self, input: CountActivitiesInput + ) -> ActivityExecutionCount: + return ActivityExecutionCount._from_raw( + await self._client.workflow_service.count_activity_executions( + temporalio.api.workflowservice.v1.CountActivityExecutionsRequest( + namespace=self._client.namespace, + query=input.query or "", + ), + retry=True, + metadata=input.rpc_metadata, + timeout=input.rpc_timeout, + ) + ) + + async def start_workflow_update( + self, input: StartWorkflowUpdateInput + ) -> WorkflowUpdateHandle[Any]: + workflow_id = input.id + req = await self._build_update_workflow_execution_request(input, workflow_id) + + # Repeatedly try to invoke UpdateWorkflowExecution until the update is durable. + resp: temporalio.api.workflowservice.v1.UpdateWorkflowExecutionResponse + while True: + try: + resp = await self._client.workflow_service.update_workflow_execution( + req, + retry=True, + metadata=input.rpc_metadata, + timeout=input.rpc_timeout, + ) + except RPCError as err: + if ( + err.status == RPCStatusCode.DEADLINE_EXCEEDED + or err.status == RPCStatusCode.CANCELLED + ): + raise WorkflowUpdateRPCTimeoutOrCancelledError() from err + else: + raise + except asyncio.CancelledError as err: + raise WorkflowUpdateRPCTimeoutOrCancelledError() from err + if ( + resp.stage + >= temporalio.api.enums.v1.UpdateWorkflowExecutionLifecycleStage.UPDATE_WORKFLOW_EXECUTION_LIFECYCLE_STAGE_ACCEPTED + ): + break + + # Build the handle. If the user's wait stage is COMPLETED, make sure we + # poll for result. + handle: WorkflowUpdateHandle[Any] = WorkflowUpdateHandle( + client=self._client, + id=req.request.meta.update_id, + workflow_id=workflow_id, + workflow_run_id=resp.update_ref.workflow_execution.run_id, + result_type=input.ret_type, + ) + if resp.HasField("outcome"): + handle._known_outcome = resp.outcome + if input.wait_for_stage == WorkflowUpdateStage.COMPLETED: + await handle._poll_until_outcome() + return handle + + async def _build_update_workflow_execution_request( + self, + input: StartWorkflowUpdateInput | UpdateWithStartUpdateWorkflowInput, + workflow_id: str, + ) -> temporalio.api.workflowservice.v1.UpdateWorkflowExecutionRequest: + data_converter = self._client.data_converter._with_contexts( + WorkflowSerializationContext( + namespace=self._client.namespace, + workflow_id=workflow_id, + ), + StorageDriverStoreContext( + target=StorageDriverWorkflowInfo( + id=workflow_id, + run_id=(input.run_id or None) + if isinstance(input, StartWorkflowUpdateInput) + else None, + namespace=self._client.namespace, + ), + ), + ) + run_id, first_execution_run_id = ( + ( + input.run_id, + input.first_execution_run_id, + ) + if isinstance(input, StartWorkflowUpdateInput) + else (None, None) + ) + req = temporalio.api.workflowservice.v1.UpdateWorkflowExecutionRequest( + namespace=self._client.namespace, + workflow_execution=temporalio.api.common.v1.WorkflowExecution( + workflow_id=workflow_id, + run_id=run_id or "", + ), + first_execution_run_id=first_execution_run_id or "", + request=temporalio.api.update.v1.Request( + meta=temporalio.api.update.v1.Meta( + update_id=input.update_id or str(uuid.uuid4()), + identity=self._client.identity, + ), + input=temporalio.api.update.v1.Input( + name=input.update, + ), + ), + wait_policy=temporalio.api.update.v1.WaitPolicy( + lifecycle_stage=temporalio.api.enums.v1.UpdateWorkflowExecutionLifecycleStage.ValueType( + input.wait_for_stage + ) + ), + ) + if input.args: + req.request.input.args.payloads.extend( + await data_converter.encode(input.args) + ) + if input.headers is not None: # type:ignore[reportUnnecessaryComparison] + await self._apply_headers(input.headers, req.request.input.header.fields) + return req + + async def start_update_with_start_workflow( + self, input: StartWorkflowUpdateWithStartInput + ) -> WorkflowUpdateHandle[Any]: + seen_start = False + + def on_start( + start_response: temporalio.api.workflowservice.v1.StartWorkflowExecutionResponse, + ): + nonlocal seen_start + if not seen_start: + input._on_start(start_response) + seen_start = True + + err: BaseException | None = None + + try: + return await self._start_workflow_update_with_start( + input.start_workflow_input, input.update_workflow_input, on_start + ) + except asyncio.CancelledError as _err: + err = _err + raise WorkflowUpdateRPCTimeoutOrCancelledError() from err + except RPCError as _err: + err = _err + if err.status in [ + RPCStatusCode.DEADLINE_EXCEEDED, + RPCStatusCode.CANCELLED, + ]: + raise WorkflowUpdateRPCTimeoutOrCancelledError() from err + else: + multiop_failure = ( + temporalio.api.errordetails.v1.MultiOperationExecutionFailure() + ) + if err.grpc_status.details and err.grpc_status.details[0].Unpack( + multiop_failure + ): + status = next( + ( + st + for st in multiop_failure.statuses + if ( + st.code != RPCStatusCode.OK + and not ( + st.details + and st.details[0].Is( + temporalio.api.failure.v1.MultiOperationExecutionAborted.DESCRIPTOR + ) + ) + ) + ), + None, + ) + if status and status.code in list(RPCStatusCode): + if ( + status.code == RPCStatusCode.ALREADY_EXISTS + and status.details + ): + details = temporalio.api.errordetails.v1.WorkflowExecutionAlreadyStartedFailure() + if status.details[0].Unpack(details): + err = temporalio.exceptions.WorkflowAlreadyStartedError( + input.start_workflow_input.id, + input.start_workflow_input.workflow, + run_id=details.run_id, + ) + else: + err = RPCError( + status.message, + RPCStatusCode(status.code), + err.raw_grpc_status, + ) + raise err + finally: + if err and not seen_start: + input._on_start_error(err) + + async def _start_workflow_update_with_start( + self, + start_input: UpdateWithStartStartWorkflowInput, + update_input: UpdateWithStartUpdateWorkflowInput, + on_start: Callable[ + [temporalio.api.workflowservice.v1.StartWorkflowExecutionResponse], None + ], + ) -> WorkflowUpdateHandle[Any]: + start_req = ( + await self._build_update_with_start_start_workflow_execution_request( + start_input + ) + ) + update_req = await self._build_update_workflow_execution_request( + update_input, workflow_id=start_input.id + ) + multiop_req = temporalio.api.workflowservice.v1.ExecuteMultiOperationRequest( + namespace=self._client.namespace, + operations=[ + temporalio.api.workflowservice.v1.ExecuteMultiOperationRequest.Operation( + start_workflow=start_req + ), + temporalio.api.workflowservice.v1.ExecuteMultiOperationRequest.Operation( + update_workflow=update_req + ), + ], + ) + + # Repeatedly try to invoke ExecuteMultiOperation until the update is durable + while True: + multiop_response = ( + await self._client.workflow_service.execute_multi_operation(multiop_req) + ) + start_response = multiop_response.responses[0].start_workflow + update_response = multiop_response.responses[1].update_workflow + on_start(start_response) + known_outcome = ( + update_response.outcome if update_response.HasField("outcome") else None + ) + if ( + update_response.stage + >= temporalio.api.enums.v1.UpdateWorkflowExecutionLifecycleStage.UPDATE_WORKFLOW_EXECUTION_LIFECYCLE_STAGE_ACCEPTED + ): + break + + handle: WorkflowUpdateHandle[Any] = WorkflowUpdateHandle( + client=self._client, + id=update_req.request.meta.update_id, + workflow_id=start_input.id, + workflow_run_id=start_response.run_id, + known_outcome=known_outcome, + result_type=update_input.ret_type, + ) + if update_input.wait_for_stage == WorkflowUpdateStage.COMPLETED: + await handle._poll_until_outcome() + + return handle + + ### Async activity calls + + def _get_async_activity_store_context( + self, id_or_token: AsyncActivityIDReference | bytes + ) -> StorageDriverStoreContext: + if isinstance(id_or_token, AsyncActivityIDReference): + if id_or_token.workflow_id: + return StorageDriverStoreContext( + target=StorageDriverWorkflowInfo( + id=id_or_token.workflow_id or None, + run_id=id_or_token.run_id or None, + namespace=self._client.namespace, + ), + ) + return StorageDriverStoreContext( + target=StorageDriverActivityInfo( + id=id_or_token.activity_id, + run_id=id_or_token.run_id or None, + namespace=self._client.namespace, + ), + ) + else: + return StorageDriverStoreContext(target=None) + + async def heartbeat_async_activity( + self, input: HeartbeatAsyncActivityInput + ) -> None: + data_converter = ( + input.data_converter_override or self._client.data_converter + )._with_store_context(self._get_async_activity_store_context(input.id_or_token)) + details = ( + None + if not input.details + else await data_converter.encode_wrapper(input.details) + ) + if isinstance(input.id_or_token, AsyncActivityIDReference): + resp_by_id = await self._client.workflow_service.record_activity_task_heartbeat_by_id( + temporalio.api.workflowservice.v1.RecordActivityTaskHeartbeatByIdRequest( + workflow_id=input.id_or_token.workflow_id or "", + run_id=input.id_or_token.run_id or "", + activity_id=input.id_or_token.activity_id, + namespace=self._client.namespace, + identity=self._client.identity, + details=details, + ), + retry=True, + metadata=input.rpc_metadata, + timeout=input.rpc_timeout, + ) + if ( + resp_by_id.cancel_requested + or resp_by_id.activity_paused + or resp_by_id.activity_reset + ): + raise AsyncActivityCancelledError( + details=ActivityCancellationDetails( + cancel_requested=resp_by_id.cancel_requested, + paused=resp_by_id.activity_paused, + reset=resp_by_id.activity_reset, + ) + ) + + else: + resp = await self._client.workflow_service.record_activity_task_heartbeat( + temporalio.api.workflowservice.v1.RecordActivityTaskHeartbeatRequest( + task_token=input.id_or_token, + namespace=self._client.namespace, + identity=self._client.identity, + details=details, + ), + retry=True, + metadata=input.rpc_metadata, + timeout=input.rpc_timeout, + ) + if resp.cancel_requested or resp.activity_paused: + raise AsyncActivityCancelledError( + details=ActivityCancellationDetails( + cancel_requested=resp.cancel_requested, + paused=resp.activity_paused, + reset=resp.activity_reset, + ) + ) + + async def complete_async_activity(self, input: CompleteAsyncActivityInput) -> None: + data_converter = ( + input.data_converter_override or self._client.data_converter + )._with_store_context(self._get_async_activity_store_context(input.id_or_token)) + result = ( + None + if input.result is temporalio.common._arg_unset + else await data_converter.encode_wrapper([input.result]) + ) + if isinstance(input.id_or_token, AsyncActivityIDReference): + await self._client.workflow_service.respond_activity_task_completed_by_id( + temporalio.api.workflowservice.v1.RespondActivityTaskCompletedByIdRequest( + workflow_id=input.id_or_token.workflow_id or "", + run_id=input.id_or_token.run_id or "", + activity_id=input.id_or_token.activity_id, + namespace=self._client.namespace, + identity=self._client.identity, + result=result, + ), + retry=True, + metadata=input.rpc_metadata, + timeout=input.rpc_timeout, + ) + else: + await self._client.workflow_service.respond_activity_task_completed( + temporalio.api.workflowservice.v1.RespondActivityTaskCompletedRequest( + task_token=input.id_or_token, + namespace=self._client.namespace, + identity=self._client.identity, + result=result, + ), + retry=True, + metadata=input.rpc_metadata, + timeout=input.rpc_timeout, + ) + + async def fail_async_activity(self, input: FailAsyncActivityInput) -> None: + data_converter = ( + input.data_converter_override or self._client.data_converter + )._with_store_context(self._get_async_activity_store_context(input.id_or_token)) + + failure = temporalio.api.failure.v1.Failure() + await data_converter.encode_failure(input.error, failure) + last_heartbeat_details = ( + await data_converter.encode_wrapper(input.last_heartbeat_details) + if input.last_heartbeat_details + else None + ) + if isinstance(input.id_or_token, AsyncActivityIDReference): + await self._client.workflow_service.respond_activity_task_failed_by_id( + temporalio.api.workflowservice.v1.RespondActivityTaskFailedByIdRequest( + workflow_id=input.id_or_token.workflow_id or "", + run_id=input.id_or_token.run_id or "", + activity_id=input.id_or_token.activity_id, + namespace=self._client.namespace, + identity=self._client.identity, + failure=failure, + last_heartbeat_details=last_heartbeat_details, + ), + retry=True, + metadata=input.rpc_metadata, + timeout=input.rpc_timeout, + ) + else: + await self._client.workflow_service.respond_activity_task_failed( + temporalio.api.workflowservice.v1.RespondActivityTaskFailedRequest( + task_token=input.id_or_token, + namespace=self._client.namespace, + identity=self._client.identity, + failure=failure, + last_heartbeat_details=last_heartbeat_details, + ), + retry=True, + metadata=input.rpc_metadata, + timeout=input.rpc_timeout, + ) + + async def report_cancellation_async_activity( + self, input: ReportCancellationAsyncActivityInput + ) -> None: + data_converter = ( + input.data_converter_override or self._client.data_converter + )._with_store_context(self._get_async_activity_store_context(input.id_or_token)) + details = ( + None + if not input.details + else await data_converter.encode_wrapper(input.details) + ) + if isinstance(input.id_or_token, AsyncActivityIDReference): + await self._client.workflow_service.respond_activity_task_canceled_by_id( + temporalio.api.workflowservice.v1.RespondActivityTaskCanceledByIdRequest( + workflow_id=input.id_or_token.workflow_id or "", + run_id=input.id_or_token.run_id or "", + activity_id=input.id_or_token.activity_id, + namespace=self._client.namespace, + identity=self._client.identity, + details=details, + ), + retry=True, + metadata=input.rpc_metadata, + timeout=input.rpc_timeout, + ) + else: + await self._client.workflow_service.respond_activity_task_canceled( + temporalio.api.workflowservice.v1.RespondActivityTaskCanceledRequest( + task_token=input.id_or_token, + namespace=self._client.namespace, + identity=self._client.identity, + details=details, + ), + retry=True, + metadata=input.rpc_metadata, + timeout=input.rpc_timeout, + ) + + ### Schedule calls + + async def create_schedule(self, input: CreateScheduleInput) -> ScheduleHandle: + # Limited actions must be false if remaining actions is 0 and must be + # true if remaining actions is non-zero + if ( + input.schedule.state.limited_actions + and not input.schedule.state.remaining_actions + ): + raise ValueError( + "Must set limited actions to false if there are no remaining actions set" + ) + if ( + not input.schedule.state.limited_actions + and input.schedule.state.remaining_actions + ): + raise ValueError( + "Must set limited actions to true if there are remaining actions set" + ) + + initial_patch: temporalio.api.schedule.v1.SchedulePatch | None = None + if input.trigger_immediately or input.backfill: + initial_patch = temporalio.api.schedule.v1.SchedulePatch( + trigger_immediately=temporalio.api.schedule.v1.TriggerImmediatelyRequest( + overlap_policy=temporalio.api.enums.v1.ScheduleOverlapPolicy.ValueType( + input.schedule.policy.overlap + ), + ) + if input.trigger_immediately + else None, + backfill_request=[b._to_proto() for b in input.backfill] + if input.backfill + else None, + ) + try: + request = temporalio.api.workflowservice.v1.CreateScheduleRequest( + namespace=self._client.namespace, + schedule_id=input.id, + schedule=await input.schedule._to_proto(self._client), + initial_patch=initial_patch, + identity=self._client.identity, + request_id=str(uuid.uuid4()), + memo=await self._client.data_converter._encode_memo(input.memo) + if input.memo + else None, + ) + if input.search_attributes: + temporalio.converter.encode_search_attributes( + input.search_attributes, request.search_attributes + ) + await self._client.workflow_service.create_schedule( + request, + retry=True, + metadata=input.rpc_metadata, + timeout=input.rpc_timeout, + ) + except RPCError as err: + already_started = ( + err.status == RPCStatusCode.ALREADY_EXISTS + and err.grpc_status.details + and err.grpc_status.details[0].Is( + temporalio.api.errordetails.v1.WorkflowExecutionAlreadyStartedFailure.DESCRIPTOR + ) + ) + if already_started: + raise ScheduleAlreadyRunningError() + raise + return ScheduleHandle(self._client, input.id) + + def list_schedules(self, input: ListSchedulesInput) -> ScheduleAsyncIterator: + return ScheduleAsyncIterator(self._client, input) + + async def backfill_schedule(self, input: BackfillScheduleInput) -> None: + await self._client.workflow_service.patch_schedule( + temporalio.api.workflowservice.v1.PatchScheduleRequest( + namespace=self._client.namespace, + schedule_id=input.id, + patch=temporalio.api.schedule.v1.SchedulePatch( + backfill_request=[b._to_proto() for b in input.backfills], + ), + identity=self._client.identity, + request_id=str(uuid.uuid4()), + ), + retry=True, + metadata=input.rpc_metadata, + timeout=input.rpc_timeout, + ) + + async def delete_schedule(self, input: DeleteScheduleInput) -> None: + await self._client.workflow_service.delete_schedule( + temporalio.api.workflowservice.v1.DeleteScheduleRequest( + namespace=self._client.namespace, + schedule_id=input.id, + identity=self._client.identity, + ), + retry=True, + metadata=input.rpc_metadata, + timeout=input.rpc_timeout, + ) + + async def describe_schedule( + self, input: DescribeScheduleInput + ) -> ScheduleDescription: + return ScheduleDescription._from_proto( + input.id, + await self._client.workflow_service.describe_schedule( + temporalio.api.workflowservice.v1.DescribeScheduleRequest( + namespace=self._client.namespace, + schedule_id=input.id, + ), + retry=True, + metadata=input.rpc_metadata, + timeout=input.rpc_timeout, + ), + self._client.data_converter, + ) + + async def pause_schedule(self, input: PauseScheduleInput) -> None: + await self._client.workflow_service.patch_schedule( + temporalio.api.workflowservice.v1.PatchScheduleRequest( + namespace=self._client.namespace, + schedule_id=input.id, + patch=temporalio.api.schedule.v1.SchedulePatch( + pause=input.note or "Paused via Python SDK", + ), + identity=self._client.identity, + request_id=str(uuid.uuid4()), + ), + retry=True, + metadata=input.rpc_metadata, + timeout=input.rpc_timeout, + ) + + async def trigger_schedule(self, input: TriggerScheduleInput) -> None: + overlap_policy = temporalio.api.enums.v1.ScheduleOverlapPolicy.SCHEDULE_OVERLAP_POLICY_UNSPECIFIED + if input.overlap: + overlap_policy = temporalio.api.enums.v1.ScheduleOverlapPolicy.ValueType( + input.overlap + ) + await self._client.workflow_service.patch_schedule( + temporalio.api.workflowservice.v1.PatchScheduleRequest( + namespace=self._client.namespace, + schedule_id=input.id, + patch=temporalio.api.schedule.v1.SchedulePatch( + trigger_immediately=temporalio.api.schedule.v1.TriggerImmediatelyRequest( + overlap_policy=overlap_policy, + ), + ), + identity=self._client.identity, + request_id=str(uuid.uuid4()), + ), + retry=True, + metadata=input.rpc_metadata, + timeout=input.rpc_timeout, + ) + + async def unpause_schedule(self, input: UnpauseScheduleInput) -> None: + await self._client.workflow_service.patch_schedule( + temporalio.api.workflowservice.v1.PatchScheduleRequest( + namespace=self._client.namespace, + schedule_id=input.id, + patch=temporalio.api.schedule.v1.SchedulePatch( + unpause=input.note or "Unpaused via Python SDK", + ), + identity=self._client.identity, + request_id=str(uuid.uuid4()), + ), + retry=True, + metadata=input.rpc_metadata, + timeout=input.rpc_timeout, + ) + + async def update_schedule(self, input: UpdateScheduleInput) -> None: + # TODO(cretz): This is supposed to be a retry-conflict loop, but we do + # not yet have a way to know update failure is due to conflict token + # mismatch + update = input.updater( + ScheduleUpdateInput( + description=ScheduleDescription._from_proto( + input.id, + await self._client.workflow_service.describe_schedule( + temporalio.api.workflowservice.v1.DescribeScheduleRequest( + namespace=self._client.namespace, + schedule_id=input.id, + ), + retry=True, + metadata=input.rpc_metadata, + timeout=input.rpc_timeout, + ), + self._client.data_converter, + ) + ) + ) + if inspect.iscoroutine(update): + update = await update + if not update: + return + assert isinstance(update, ScheduleUpdate) + request = temporalio.api.workflowservice.v1.UpdateScheduleRequest( + namespace=self._client.namespace, + schedule_id=input.id, + schedule=await update.schedule._to_proto(self._client), + identity=self._client.identity, + request_id=str(uuid.uuid4()), + ) + if update.search_attributes is not None: + request.search_attributes.indexed_fields.clear() # Ensure that we at least create an empty map + temporalio.converter.encode_search_attributes( + update.search_attributes, request.search_attributes + ) + await self._client.workflow_service.update_schedule( + request, + retry=True, + metadata=input.rpc_metadata, + timeout=input.rpc_timeout, + ) + + async def update_worker_build_id_compatibility( + self, input: UpdateWorkerBuildIdCompatibilityInput + ) -> None: + req = input.operation._as_partial_proto() + req.namespace = self._client.namespace + req.task_queue = input.task_queue + await self._client.workflow_service.update_worker_build_id_compatibility( + req, retry=True, metadata=input.rpc_metadata, timeout=input.rpc_timeout + ) + + async def get_worker_build_id_compatibility( + self, input: GetWorkerBuildIdCompatibilityInput + ) -> WorkerBuildIdVersionSets: + req = temporalio.api.workflowservice.v1.GetWorkerBuildIdCompatibilityRequest( + namespace=self._client.namespace, + task_queue=input.task_queue, + max_sets=input.max_sets or 0, + ) + resp = await self._client.workflow_service.get_worker_build_id_compatibility( + req, retry=True, metadata=input.rpc_metadata, timeout=input.rpc_timeout + ) + return WorkerBuildIdVersionSets._from_proto(resp) + + async def get_worker_task_reachability( + self, input: GetWorkerTaskReachabilityInput + ) -> WorkerTaskReachability: + req = temporalio.api.workflowservice.v1.GetWorkerTaskReachabilityRequest( + namespace=self._client.namespace, + build_ids=input.build_ids, + task_queues=input.task_queues, + reachability=input.reachability._to_proto() + if input.reachability + else temporalio.api.enums.v1.TaskReachability.TASK_REACHABILITY_UNSPECIFIED, + ) + resp = await self._client.workflow_service.get_worker_task_reachability( + req, retry=True, metadata=input.rpc_metadata, timeout=input.rpc_timeout + ) + return WorkerTaskReachability._from_proto(resp) + + async def _apply_headers( + self, + source: Mapping[str, temporalio.api.common.v1.Payload] | None, + dest: MessageMap[str, temporalio.api.common.v1.Payload], + ) -> None: + await _apply_headers( + source, + dest, + self._client.config(active_config=True)["header_codec_behavior"] + == HeaderCodecBehavior.CODEC, + self._client.data_converter, + ) diff --git a/temporalio/client/_interceptor.py b/temporalio/client/_interceptor.py new file mode 100644 index 000000000..486c9bbd4 --- /dev/null +++ b/temporalio/client/_interceptor.py @@ -0,0 +1,783 @@ +"""Client support for accessing Temporal.""" + +from __future__ import annotations + +from collections.abc import ( + Awaitable, + Callable, + Mapping, + Sequence, +) +from dataclasses import dataclass +from datetime import timedelta +from typing import ( + TYPE_CHECKING, + Any, +) + +import temporalio.api.common.v1 +import temporalio.api.workflowservice.v1 +import temporalio.common +from temporalio.converter import ( + DataConverter, +) + +from ._callback import Callback + +if TYPE_CHECKING: + from ._activity import ( + ActivityExecutionAsyncIterator, + ActivityExecutionCount, + ActivityExecutionDescription, + ActivityHandle, + AsyncActivityIDReference, + ) + from ._schedule import ( + Schedule, + ScheduleAsyncIterator, + ScheduleBackfill, + ScheduleDescription, + ScheduleHandle, + ScheduleOverlapPolicy, + ScheduleUpdate, + ScheduleUpdateInput, + ) + from ._worker_versioning import ( + BuildIdOp, + TaskReachabilityType, + WorkerBuildIdVersionSets, + WorkerTaskReachability, + ) + from ._workflow import ( + WorkflowExecutionAsyncIterator, + WorkflowExecutionCount, + WorkflowExecutionDescription, + WorkflowHandle, + WorkflowHistoryEventAsyncIterator, + WorkflowHistoryEventFilterType, + WorkflowUpdateHandle, + WorkflowUpdateStage, + ) + + +@dataclass +class StartWorkflowInput: + """Input for :py:meth:`OutboundInterceptor.start_workflow`.""" + + workflow: str + args: Sequence[Any] + id: str + task_queue: str + execution_timeout: timedelta | None + run_timeout: timedelta | None + task_timeout: timedelta | None + id_reuse_policy: temporalio.common.WorkflowIDReusePolicy + id_conflict_policy: temporalio.common.WorkflowIDConflictPolicy + retry_policy: temporalio.common.RetryPolicy | None + cron_schedule: str + memo: Mapping[str, Any] | None + search_attributes: None | ( + temporalio.common.SearchAttributes | temporalio.common.TypedSearchAttributes + ) + start_delay: timedelta | None + headers: Mapping[str, temporalio.api.common.v1.Payload] + start_signal: str | None + start_signal_args: Sequence[Any] + static_summary: str | None + static_details: str | None + # Type may be absent + ret_type: type | None + rpc_metadata: Mapping[str, str | bytes] + rpc_timeout: timedelta | None + request_eager_start: bool + priority: temporalio.common.Priority + # The following options are experimental and unstable. + callbacks: Sequence[Callback] + workflow_event_links: Sequence[temporalio.api.common.v1.Link.WorkflowEvent] + request_id: str | None + versioning_override: temporalio.common.VersioningOverride | None = None + + +@dataclass +class CancelWorkflowInput: + """Input for :py:meth:`OutboundInterceptor.cancel_workflow`.""" + + id: str + run_id: str | None + first_execution_run_id: str | None + rpc_metadata: Mapping[str, str | bytes] + rpc_timeout: timedelta | None + + +@dataclass +class DescribeWorkflowInput: + """Input for :py:meth:`OutboundInterceptor.describe_workflow`.""" + + id: str + run_id: str | None + rpc_metadata: Mapping[str, str | bytes] + rpc_timeout: timedelta | None + + +@dataclass +class FetchWorkflowHistoryEventsInput: + """Input for :py:meth:`OutboundInterceptor.fetch_workflow_history_events`.""" + + id: str + run_id: str | None + page_size: int | None + next_page_token: bytes | None + wait_new_event: bool + event_filter_type: WorkflowHistoryEventFilterType + skip_archival: bool + rpc_metadata: Mapping[str, str | bytes] + rpc_timeout: timedelta | None + + +@dataclass +class ListWorkflowsInput: + """Input for :py:meth:`OutboundInterceptor.list_workflows`.""" + + query: str | None + page_size: int + next_page_token: bytes | None + rpc_metadata: Mapping[str, str | bytes] + rpc_timeout: timedelta | None + limit: int | None + + +@dataclass +class CountWorkflowsInput: + """Input for :py:meth:`OutboundInterceptor.count_workflows`.""" + + query: str | None + rpc_metadata: Mapping[str, str | bytes] + rpc_timeout: timedelta | None + + +@dataclass +class QueryWorkflowInput: + """Input for :py:meth:`OutboundInterceptor.query_workflow`.""" + + id: str + run_id: str | None + query: str + args: Sequence[Any] + reject_condition: temporalio.common.QueryRejectCondition | None + headers: Mapping[str, temporalio.api.common.v1.Payload] + # Type may be absent + ret_type: type | None + rpc_metadata: Mapping[str, str | bytes] + rpc_timeout: timedelta | None + + +@dataclass +class SignalWorkflowInput: + """Input for :py:meth:`OutboundInterceptor.signal_workflow`.""" + + id: str + run_id: str | None + signal: str + args: Sequence[Any] + headers: Mapping[str, temporalio.api.common.v1.Payload] + rpc_metadata: Mapping[str, str | bytes] + rpc_timeout: timedelta | None + + +@dataclass +class TerminateWorkflowInput: + """Input for :py:meth:`OutboundInterceptor.terminate_workflow`.""" + + id: str + run_id: str | None + first_execution_run_id: str | None + args: Sequence[Any] + reason: str | None + rpc_metadata: Mapping[str, str | bytes] + rpc_timeout: timedelta | None + + +@dataclass +class StartActivityInput: + """Input for :py:meth:`OutboundInterceptor.start_activity`. + + .. warning:: + This API is experimental. + """ + + activity_type: str + args: Sequence[Any] + id: str + task_queue: str + result_type: type | None + schedule_to_close_timeout: timedelta | None + start_to_close_timeout: timedelta | None + schedule_to_start_timeout: timedelta | None + heartbeat_timeout: timedelta | None + id_reuse_policy: temporalio.common.ActivityIDReusePolicy + id_conflict_policy: temporalio.common.ActivityIDConflictPolicy + retry_policy: temporalio.common.RetryPolicy | None + priority: temporalio.common.Priority + search_attributes: temporalio.common.TypedSearchAttributes | None + summary: str | None + start_delay: timedelta | None + headers: Mapping[str, temporalio.api.common.v1.Payload] + rpc_metadata: Mapping[str, str | bytes] + rpc_timeout: timedelta | None + + +@dataclass +class CancelActivityInput: + """Input for :py:meth:`OutboundInterceptor.cancel_activity`. + + .. warning:: + This API is experimental. + """ + + activity_id: str + activity_run_id: str | None + reason: str | None + rpc_metadata: Mapping[str, str | bytes] + rpc_timeout: timedelta | None + + +@dataclass +class TerminateActivityInput: + """Input for :py:meth:`OutboundInterceptor.terminate_activity`. + + .. warning:: + This API is experimental. + """ + + activity_id: str + activity_run_id: str | None + reason: str | None + rpc_metadata: Mapping[str, str | bytes] + rpc_timeout: timedelta | None + + +@dataclass +class DescribeActivityInput: + """Input for :py:meth:`OutboundInterceptor.describe_activity`. + + .. warning:: + This API is experimental. + """ + + activity_id: str + activity_run_id: str | None + long_poll_token: bytes | None + rpc_metadata: Mapping[str, str | bytes] + rpc_timeout: timedelta | None + + +@dataclass +class ListActivitiesInput: + """Input for :py:meth:`OutboundInterceptor.list_activities`. + + .. warning:: + This API is experimental. + """ + + query: str | None + page_size: int + next_page_token: bytes | None + rpc_metadata: Mapping[str, str | bytes] + rpc_timeout: timedelta | None + limit: int | None + + +@dataclass +class CountActivitiesInput: + """Input for :py:meth:`OutboundInterceptor.count_activities`. + + .. warning:: + This API is experimental. + """ + + query: str | None + rpc_metadata: Mapping[str, str | bytes] + rpc_timeout: timedelta | None + + +@dataclass +class StartWorkflowUpdateInput: + """Input for :py:meth:`OutboundInterceptor.start_workflow_update`.""" + + id: str + run_id: str | None + first_execution_run_id: str | None + update_id: str | None + update: str + args: Sequence[Any] + wait_for_stage: WorkflowUpdateStage + headers: Mapping[str, temporalio.api.common.v1.Payload] + ret_type: type | None + rpc_metadata: Mapping[str, str | bytes] + rpc_timeout: timedelta | None + + +@dataclass +class UpdateWithStartUpdateWorkflowInput: + """Update input for :py:meth:`OutboundInterceptor.start_update_with_start_workflow`.""" + + update_id: str | None + update: str + args: Sequence[Any] + wait_for_stage: WorkflowUpdateStage + headers: Mapping[str, temporalio.api.common.v1.Payload] + ret_type: type | None + rpc_metadata: Mapping[str, str | bytes] + rpc_timeout: timedelta | None + + +@dataclass +class UpdateWithStartStartWorkflowInput: + """StartWorkflow input for :py:meth:`OutboundInterceptor.start_update_with_start_workflow`.""" + + # Similar to StartWorkflowInput but without e.g. run_id, start_signal, + # start_signal_args, request_eager_start. + + workflow: str + args: Sequence[Any] + id: str + task_queue: str + execution_timeout: timedelta | None + run_timeout: timedelta | None + task_timeout: timedelta | None + id_reuse_policy: temporalio.common.WorkflowIDReusePolicy + id_conflict_policy: temporalio.common.WorkflowIDConflictPolicy + retry_policy: temporalio.common.RetryPolicy | None + cron_schedule: str + memo: Mapping[str, Any] | None + search_attributes: None | ( + temporalio.common.SearchAttributes | temporalio.common.TypedSearchAttributes + ) + start_delay: timedelta | None + headers: Mapping[str, temporalio.api.common.v1.Payload] + static_summary: str | None + static_details: str | None + # Type may be absent + ret_type: type | None + rpc_metadata: Mapping[str, str | bytes] + rpc_timeout: timedelta | None + priority: temporalio.common.Priority + versioning_override: temporalio.common.VersioningOverride | None = None + + +@dataclass +class StartWorkflowUpdateWithStartInput: + """Input for :py:meth:`OutboundInterceptor.start_update_with_start_workflow`.""" + + start_workflow_input: UpdateWithStartStartWorkflowInput + update_workflow_input: UpdateWithStartUpdateWorkflowInput + _on_start: Callable[ + [temporalio.api.workflowservice.v1.StartWorkflowExecutionResponse], None + ] + _on_start_error: Callable[[BaseException], None] + + +@dataclass +class HeartbeatAsyncActivityInput: + """Input for :py:meth:`OutboundInterceptor.heartbeat_async_activity`.""" + + id_or_token: AsyncActivityIDReference | bytes + details: Sequence[Any] + rpc_metadata: Mapping[str, str | bytes] + rpc_timeout: timedelta | None + data_converter_override: DataConverter | None = None + + +@dataclass +class CompleteAsyncActivityInput: + """Input for :py:meth:`OutboundInterceptor.complete_async_activity`.""" + + id_or_token: AsyncActivityIDReference | bytes + result: Any | None + rpc_metadata: Mapping[str, str | bytes] + rpc_timeout: timedelta | None + data_converter_override: DataConverter | None = None + + +@dataclass +class FailAsyncActivityInput: + """Input for :py:meth:`OutboundInterceptor.fail_async_activity`.""" + + id_or_token: AsyncActivityIDReference | bytes + error: Exception + last_heartbeat_details: Sequence[Any] + rpc_metadata: Mapping[str, str | bytes] + rpc_timeout: timedelta | None + data_converter_override: DataConverter | None = None + + +@dataclass +class ReportCancellationAsyncActivityInput: + """Input for :py:meth:`OutboundInterceptor.report_cancellation_async_activity`.""" + + id_or_token: AsyncActivityIDReference | bytes + details: Sequence[Any] + rpc_metadata: Mapping[str, str | bytes] + rpc_timeout: timedelta | None + data_converter_override: DataConverter | None = None + + +@dataclass +class CreateScheduleInput: + """Input for :py:meth:`OutboundInterceptor.create_schedule`.""" + + id: str + schedule: Schedule + trigger_immediately: bool + backfill: Sequence[ScheduleBackfill] + memo: Mapping[str, Any] | None + search_attributes: None | ( + temporalio.common.SearchAttributes | temporalio.common.TypedSearchAttributes + ) + rpc_metadata: Mapping[str, str | bytes] + rpc_timeout: timedelta | None + + +@dataclass +class ListSchedulesInput: + """Input for :py:meth:`OutboundInterceptor.list_schedules`.""" + + page_size: int + next_page_token: bytes | None + rpc_metadata: Mapping[str, str | bytes] + rpc_timeout: timedelta | None + query: str | None = None + + +@dataclass +class BackfillScheduleInput: + """Input for :py:meth:`OutboundInterceptor.backfill_schedule`.""" + + id: str + backfills: Sequence[ScheduleBackfill] + rpc_metadata: Mapping[str, str | bytes] + rpc_timeout: timedelta | None + + +@dataclass +class DeleteScheduleInput: + """Input for :py:meth:`OutboundInterceptor.delete_schedule`.""" + + id: str + rpc_metadata: Mapping[str, str | bytes] + rpc_timeout: timedelta | None + + +@dataclass +class DescribeScheduleInput: + """Input for :py:meth:`OutboundInterceptor.describe_schedule`.""" + + id: str + rpc_metadata: Mapping[str, str | bytes] + rpc_timeout: timedelta | None + + +@dataclass +class PauseScheduleInput: + """Input for :py:meth:`OutboundInterceptor.pause_schedule`.""" + + id: str + note: str | None + rpc_metadata: Mapping[str, str | bytes] + rpc_timeout: timedelta | None + + +@dataclass +class TriggerScheduleInput: + """Input for :py:meth:`OutboundInterceptor.trigger_schedule`.""" + + id: str + overlap: ScheduleOverlapPolicy | None + rpc_metadata: Mapping[str, str | bytes] + rpc_timeout: timedelta | None + + +@dataclass +class UnpauseScheduleInput: + """Input for :py:meth:`OutboundInterceptor.unpause_schedule`.""" + + id: str + note: str | None + rpc_metadata: Mapping[str, str | bytes] + rpc_timeout: timedelta | None + + +@dataclass +class UpdateScheduleInput: + """Input for :py:meth:`OutboundInterceptor.update_schedule`.""" + + id: str + updater: Callable[ + [ScheduleUpdateInput], + ScheduleUpdate | None | Awaitable[ScheduleUpdate | None], + ] + rpc_metadata: Mapping[str, str | bytes] + rpc_timeout: timedelta | None + + +@dataclass +class UpdateWorkerBuildIdCompatibilityInput: + """Input for :py:meth:`OutboundInterceptor.update_worker_build_id_compatibility`.""" + + task_queue: str + operation: BuildIdOp + rpc_metadata: Mapping[str, str | bytes] + rpc_timeout: timedelta | None + + +@dataclass +class GetWorkerBuildIdCompatibilityInput: + """Input for :py:meth:`OutboundInterceptor.get_worker_build_id_compatibility`.""" + + task_queue: str + max_sets: int | None + rpc_metadata: Mapping[str, str | bytes] + rpc_timeout: timedelta | None + + +@dataclass +class GetWorkerTaskReachabilityInput: + """Input for :py:meth:`OutboundInterceptor.get_worker_task_reachability`.""" + + build_ids: Sequence[str] + task_queues: Sequence[str] + reachability: TaskReachabilityType | None + rpc_metadata: Mapping[str, str | bytes] + rpc_timeout: timedelta | None + + +@dataclass +class Interceptor: + """Interceptor for clients. + + This should be extended by any client interceptors. + """ + + def intercept_client(self, next: OutboundInterceptor) -> OutboundInterceptor: + """Method called for intercepting a client. + + Args: + next: The underlying outbound interceptor this interceptor should + delegate to. + + Returns: + The new interceptor that will be called for each client call. + """ + return next + + +class OutboundInterceptor: + """OutboundInterceptor for intercepting client calls. + + This should be extended by any client outbound interceptors. + """ + + def __init__(self, next: OutboundInterceptor) -> None: + """Create the outbound interceptor. + + Args: + next: The next interceptor in the chain. The default implementation + of all calls is to delegate to the next interceptor. + """ + self.next = next + + ### Workflow calls + + async def start_workflow( + self, input: StartWorkflowInput + ) -> WorkflowHandle[Any, Any]: + """Called for every :py:meth:`Client.start_workflow` call.""" + return await self.next.start_workflow(input) + + async def cancel_workflow(self, input: CancelWorkflowInput) -> None: + """Called for every :py:meth:`WorkflowHandle.cancel` call.""" + await self.next.cancel_workflow(input) + + async def describe_workflow( + self, input: DescribeWorkflowInput + ) -> WorkflowExecutionDescription: + """Called for every :py:meth:`WorkflowHandle.describe` call.""" + return await self.next.describe_workflow(input) + + def fetch_workflow_history_events( + self, input: FetchWorkflowHistoryEventsInput + ) -> WorkflowHistoryEventAsyncIterator: + """Called for every :py:meth:`WorkflowHandle.fetch_history_events` call.""" + return self.next.fetch_workflow_history_events(input) + + def list_workflows( + self, input: ListWorkflowsInput + ) -> WorkflowExecutionAsyncIterator: + """Called for every :py:meth:`Client.list_workflows` call.""" + return self.next.list_workflows(input) + + async def count_workflows( + self, input: CountWorkflowsInput + ) -> WorkflowExecutionCount: + """Called for every :py:meth:`Client.count_workflows` call.""" + return await self.next.count_workflows(input) + + async def query_workflow(self, input: QueryWorkflowInput) -> Any: + """Called for every :py:meth:`WorkflowHandle.query` call.""" + return await self.next.query_workflow(input) + + async def signal_workflow(self, input: SignalWorkflowInput) -> None: + """Called for every :py:meth:`WorkflowHandle.signal` call.""" + await self.next.signal_workflow(input) + + async def terminate_workflow(self, input: TerminateWorkflowInput) -> None: + """Called for every :py:meth:`WorkflowHandle.terminate` call.""" + await self.next.terminate_workflow(input) + + ### Activity calls + + async def start_activity(self, input: StartActivityInput) -> ActivityHandle[Any]: + """Called for every :py:meth:`Client.start_activity` call. + + .. warning:: + This API is experimental. + """ + return await self.next.start_activity(input) + + async def cancel_activity(self, input: CancelActivityInput) -> None: + """Called for every :py:meth:`ActivityHandle.cancel` call. + + .. warning:: + This API is experimental. + """ + await self.next.cancel_activity(input) + + async def terminate_activity(self, input: TerminateActivityInput) -> None: + """Called for every :py:meth:`ActivityHandle.terminate` call. + + .. warning:: + This API is experimental. + """ + await self.next.terminate_activity(input) + + async def describe_activity( + self, input: DescribeActivityInput + ) -> ActivityExecutionDescription: + """Called for every :py:meth:`ActivityHandle.describe` call. + + .. warning:: + This API is experimental. + """ + return await self.next.describe_activity(input) + + def list_activities( + self, input: ListActivitiesInput + ) -> ActivityExecutionAsyncIterator: + """Called for every :py:meth:`Client.list_activities` call. + + .. warning:: + This API is experimental. + """ + return self.next.list_activities(input) + + async def count_activities( + self, input: CountActivitiesInput + ) -> ActivityExecutionCount: + """Called for every :py:meth:`Client.count_activities` call. + + .. warning:: + This API is experimental. + """ + return await self.next.count_activities(input) + + async def start_workflow_update( + self, input: StartWorkflowUpdateInput + ) -> WorkflowUpdateHandle[Any]: + """Called for every :py:meth:`WorkflowHandle.start_update` and :py:meth:`WorkflowHandle.execute_update` call.""" + return await self.next.start_workflow_update(input) + + async def start_update_with_start_workflow( + self, input: StartWorkflowUpdateWithStartInput + ) -> WorkflowUpdateHandle[Any]: + """Called for every :py:meth:`Client.start_update_with_start_workflow` and :py:meth:`Client.execute_update_with_start_workflow` call.""" + return await self.next.start_update_with_start_workflow(input) + + ### Async activity calls + + async def heartbeat_async_activity( + self, input: HeartbeatAsyncActivityInput + ) -> None: + """Called for every :py:meth:`AsyncActivityHandle.heartbeat` call.""" + await self.next.heartbeat_async_activity(input) + + async def complete_async_activity(self, input: CompleteAsyncActivityInput) -> None: + """Called for every :py:meth:`AsyncActivityHandle.complete` call.""" + await self.next.complete_async_activity(input) + + async def fail_async_activity(self, input: FailAsyncActivityInput) -> None: + """Called for every :py:meth:`AsyncActivityHandle.fail` call.""" + await self.next.fail_async_activity(input) + + async def report_cancellation_async_activity( + self, input: ReportCancellationAsyncActivityInput + ) -> None: + """Called for every :py:meth:`AsyncActivityHandle.report_cancellation` call.""" + await self.next.report_cancellation_async_activity(input) + + ### Schedule calls + + async def create_schedule(self, input: CreateScheduleInput) -> ScheduleHandle: + """Called for every :py:meth:`Client.create_schedule` call.""" + return await self.next.create_schedule(input) + + def list_schedules(self, input: ListSchedulesInput) -> ScheduleAsyncIterator: + """Called for every :py:meth:`Client.list_schedules` call.""" + return self.next.list_schedules(input) + + async def backfill_schedule(self, input: BackfillScheduleInput) -> None: + """Called for every :py:meth:`ScheduleHandle.backfill` call.""" + await self.next.backfill_schedule(input) + + async def delete_schedule(self, input: DeleteScheduleInput) -> None: + """Called for every :py:meth:`ScheduleHandle.delete` call.""" + await self.next.delete_schedule(input) + + async def describe_schedule( + self, input: DescribeScheduleInput + ) -> ScheduleDescription: + """Called for every :py:meth:`ScheduleHandle.describe` call.""" + return await self.next.describe_schedule(input) + + async def pause_schedule(self, input: PauseScheduleInput) -> None: + """Called for every :py:meth:`ScheduleHandle.pause` call.""" + await self.next.pause_schedule(input) + + async def trigger_schedule(self, input: TriggerScheduleInput) -> None: + """Called for every :py:meth:`ScheduleHandle.trigger` call.""" + await self.next.trigger_schedule(input) + + async def unpause_schedule(self, input: UnpauseScheduleInput) -> None: + """Called for every :py:meth:`ScheduleHandle.unpause` call.""" + await self.next.unpause_schedule(input) + + async def update_schedule(self, input: UpdateScheduleInput) -> None: + """Called for every :py:meth:`ScheduleHandle.update` call.""" + await self.next.update_schedule(input) + + async def update_worker_build_id_compatibility( + self, input: UpdateWorkerBuildIdCompatibilityInput + ) -> None: + """Called for every :py:meth:`Client.update_worker_build_id_compatibility` call.""" + await self.next.update_worker_build_id_compatibility(input) + + async def get_worker_build_id_compatibility( + self, input: GetWorkerBuildIdCompatibilityInput + ) -> WorkerBuildIdVersionSets: + """Called for every :py:meth:`Client.get_worker_build_id_compatibility` call.""" + return await self.next.get_worker_build_id_compatibility(input) + + async def get_worker_task_reachability( + self, input: GetWorkerTaskReachabilityInput + ) -> WorkerTaskReachability: + """Called for every :py:meth:`Client.get_worker_task_reachability` call.""" + return await self.next.get_worker_task_reachability(input) diff --git a/temporalio/client/_plugin.py b/temporalio/client/_plugin.py new file mode 100644 index 000000000..95b47e43d --- /dev/null +++ b/temporalio/client/_plugin.py @@ -0,0 +1,75 @@ +"""Client support for accessing Temporal.""" + +from __future__ import annotations + +import abc +from abc import abstractmethod +from collections.abc import ( + Awaitable, + Callable, +) +from typing import ( + TYPE_CHECKING, +) + +from temporalio.service import ( + ConnectConfig, + ServiceClient, +) + +if TYPE_CHECKING: + from ._client import ClientConfig + + +class Plugin(abc.ABC): + """Base class for client plugins that can intercept and modify client behavior. + + Plugins allow customization of client creation and service connection processes + through a chain of responsibility pattern. Each plugin can modify the client + configuration or intercept service client connections. + + If the plugin is also a temporalio.worker.Plugin, it will additionally be propagated as a worker plugin. + You should likley not also provide it to the worker as that will result in the plugin being applied twice. + """ + + def name(self) -> str: + """Get the name of this plugin. Can be overridden if desired to provide a more appropriate name. + + Returns: + The fully qualified name of the plugin class (module.classname). + """ + return type(self).__module__ + "." + type(self).__qualname__ + + @abstractmethod + def configure_client(self, config: ClientConfig) -> ClientConfig: + """Hook called when creating a client to allow modification of configuration. + + This method is called during client creation and allows plugins to modify + the client configuration before the client is fully initialized. Plugins + can add interceptors, modify connection parameters, or change other settings. + + Args: + config: The client configuration dictionary to potentially modify. + + Returns: + The modified client configuration. + """ + + @abstractmethod + async def connect_service_client( + self, + config: ConnectConfig, + next: Callable[[ConnectConfig], Awaitable[ServiceClient]], + ) -> ServiceClient: + """Hook called when connecting to the Temporal service. + + This method is called during service client connection and allows plugins + to intercept or modify the connection process. Plugins can modify connection + parameters, add authentication, or provide custom connection logic. + + Args: + config: The service connection configuration. + + Returns: + The connected service client. + """ diff --git a/temporalio/client/_schedule.py b/temporalio/client/_schedule.py new file mode 100644 index 000000000..15946cfe8 --- /dev/null +++ b/temporalio/client/_schedule.py @@ -0,0 +1,1604 @@ +"""Client support for accessing Temporal.""" + +from __future__ import annotations + +import dataclasses +from abc import ABC, abstractmethod +from collections.abc import ( + Awaitable, + Callable, + Mapping, + Sequence, +) +from dataclasses import dataclass +from datetime import datetime, timedelta, timezone +from enum import IntEnum +from typing import ( + TYPE_CHECKING, + Any, + Concatenate, + overload, +) + +import google.protobuf.duration_pb2 +import google.protobuf.timestamp_pb2 + +import temporalio.api.common.v1 +import temporalio.api.enums.v1 +import temporalio.api.schedule.v1 +import temporalio.api.taskqueue.v1 +import temporalio.api.workflow.v1 +import temporalio.api.workflowservice.v1 +import temporalio.common +import temporalio.converter +import temporalio.workflow +from temporalio.converter import ( + StorageDriverStoreContext, + StorageDriverWorkflowInfo, + WorkflowSerializationContext, +) + +from ..common import HeaderCodecBehavior +from ..types import ( + AnyType, + MethodAsyncNoParam, + MethodAsyncSingleParam, + MultiParamSpec, + ParamType, + ReturnType, + SelfType, +) +from ._helpers import _apply_headers, _encode_user_metadata +from ._interceptor import ( + BackfillScheduleInput, + DeleteScheduleInput, + DescribeScheduleInput, + PauseScheduleInput, + TriggerScheduleInput, + UnpauseScheduleInput, + UpdateScheduleInput, +) + +if TYPE_CHECKING: + from ._client import Client + from ._interceptor import ListSchedulesInput + + +class ScheduleHandle: + """Handle for interacting with a schedule. + + This is usually created via :py:meth:`Client.get_schedule_handle` or + returned from :py:meth:`Client.create_schedule`. + + Attributes: + id: ID of the schedule. + """ + + def __init__(self, client: Client, id: str) -> None: + """Create schedule handle.""" + self._client = client + self.id = id + + async def backfill( + self, + *backfill: ScheduleBackfill, + rpc_metadata: Mapping[str, str | bytes] = {}, + rpc_timeout: timedelta | None = None, + ) -> None: + """Backfill the schedule by going through the specified time periods as + if they passed right now. + + Args: + backfill: Backfill periods. + rpc_metadata: Headers used on the RPC call. Keys here override + client-level RPC metadata keys. + rpc_timeout: Optional RPC deadline to set for the RPC call. + """ + if not backfill: + raise ValueError("At least one backfill required") + await self._client._impl.backfill_schedule( + BackfillScheduleInput( + id=self.id, + backfills=backfill, + rpc_metadata=rpc_metadata, + rpc_timeout=rpc_timeout, + ), + ) + + async def delete( + self, + *, + rpc_metadata: Mapping[str, str | bytes] = {}, + rpc_timeout: timedelta | None = None, + ) -> None: + """Delete this schedule. + + Args: + rpc_metadata: Headers used on the RPC call. Keys here override + client-level RPC metadata keys. + rpc_timeout: Optional RPC deadline to set for the RPC call. + """ + await self._client._impl.delete_schedule( + DeleteScheduleInput( + id=self.id, + rpc_metadata=rpc_metadata, + rpc_timeout=rpc_timeout, + ), + ) + + async def describe( + self, + *, + rpc_metadata: Mapping[str, str | bytes] = {}, + rpc_timeout: timedelta | None = None, + ) -> ScheduleDescription: + """Fetch this schedule's description. + + Args: + rpc_metadata: Headers used on the RPC call. Keys here override + client-level RPC metadata keys. + rpc_timeout: Optional RPC deadline to set for the RPC call. + """ + return await self._client._impl.describe_schedule( + DescribeScheduleInput( + id=self.id, + rpc_metadata=rpc_metadata, + rpc_timeout=rpc_timeout, + ), + ) + + async def pause( + self, + *, + note: str | None = None, + rpc_metadata: Mapping[str, str | bytes] = {}, + rpc_timeout: timedelta | None = None, + ) -> None: + """Pause the schedule and set a note. + + Args: + note: Note to set on the schedule. + rpc_metadata: Headers used on the RPC call. Keys here override + client-level RPC metadata keys. + rpc_timeout: Optional RPC deadline to set for the RPC call. + """ + await self._client._impl.pause_schedule( + PauseScheduleInput( + id=self.id, + note=note, + rpc_metadata=rpc_metadata, + rpc_timeout=rpc_timeout, + ), + ) + + async def trigger( + self, + *, + overlap: ScheduleOverlapPolicy | None = None, + rpc_metadata: Mapping[str, str | bytes] = {}, + rpc_timeout: timedelta | None = None, + ) -> None: + """Trigger an action on this schedule to happen immediately. + + Args: + overlap: If set, overrides the schedule's overlap policy. + rpc_metadata: Headers used on the RPC call. Keys here override + client-level RPC metadata keys. + rpc_timeout: Optional RPC deadline to set for the RPC call. + """ + await self._client._impl.trigger_schedule( + TriggerScheduleInput( + id=self.id, + overlap=overlap, + rpc_metadata=rpc_metadata, + rpc_timeout=rpc_timeout, + ), + ) + + async def unpause( + self, + *, + note: str | None = None, + rpc_metadata: Mapping[str, str | bytes] = {}, + rpc_timeout: timedelta | None = None, + ) -> None: + """Unpause the schedule and set a note. + + Args: + note: Note to set on the schedule. + rpc_metadata: Headers used on the RPC call. Keys here override + client-level RPC metadata keys. + rpc_timeout: Optional RPC deadline to set for the RPC call. + """ + await self._client._impl.unpause_schedule( + UnpauseScheduleInput( + id=self.id, + note=note, + rpc_metadata=rpc_metadata, + rpc_timeout=rpc_timeout, + ), + ) + + @overload + async def update( + self, + updater: Callable[[ScheduleUpdateInput], ScheduleUpdate | None], + *, + rpc_metadata: Mapping[str, str | bytes] = {}, + rpc_timeout: timedelta | None = None, + ) -> None: ... + + @overload + async def update( + self, + updater: Callable[[ScheduleUpdateInput], Awaitable[ScheduleUpdate | None]], + *, + rpc_metadata: Mapping[str, str | bytes] = {}, + rpc_timeout: timedelta | None = None, + ) -> None: ... + + async def update( + self, + updater: Callable[ + [ScheduleUpdateInput], + ScheduleUpdate | None | Awaitable[ScheduleUpdate | None], + ], + *, + rpc_metadata: Mapping[str, str | bytes] = {}, + rpc_timeout: timedelta | None = None, + ) -> None: + """Update a schedule using a callback to build the update from the + description. + + The callback may be invoked multiple times in a conflict-resolution + loop. + + Args: + updater: Callback that returns the update. It accepts a + :py:class:`ScheduleUpdateInput` and returns a + :py:class:`ScheduleUpdate`. If None is returned or an error + occurs, the update is not attempted. This may be called multiple + times. + rpc_metadata: Headers used on the RPC call. Keys here override + client-level RPC metadata keys. This is for every call made + within. + rpc_timeout: Optional RPC deadline to set for the RPC call. This is + for each call made within, not overall. + """ + await self._client._impl.update_schedule( + UpdateScheduleInput( + id=self.id, + updater=updater, + rpc_metadata=rpc_metadata, + rpc_timeout=rpc_timeout, + ), + ) + + +@dataclass +class ScheduleSpec: + """Specification of the times scheduled actions may occur. + + The times are the union of :py:attr:`calendars`, :py:attr:`intervals`, and + :py:attr:`cron_expressions` excluding anything in :py:attr:`skip`. + """ + + calendars: Sequence[ScheduleCalendarSpec] = dataclasses.field(default_factory=list) + """Calendar-based specification of times.""" + + intervals: Sequence[ScheduleIntervalSpec] = dataclasses.field(default_factory=list) + """Interval-based specification of times.""" + + cron_expressions: Sequence[str] = dataclasses.field(default_factory=list) + """Cron-based specification of times. + + This is provided for easy migration from legacy string-based cron + scheduling. New uses should use :py:attr:`calendars` instead. These + expressions will be translated to calendar-based specifications on the + server. + """ + + skip: Sequence[ScheduleCalendarSpec] = dataclasses.field(default_factory=list) + """Set of matching calendar times that will be skipped.""" + + start_at: datetime | None = None + """Time before which any matching times will be skipped.""" + + end_at: datetime | None = None + """Time after which any matching times will be skipped.""" + + jitter: timedelta | None = None + """Jitter to apply each action. + + An action's scheduled time will be incremented by a random value between 0 + and this value if present (but not past the next schedule). + """ + + time_zone_name: str | None = None + """IANA time zone name, for example ``US/Central``.""" + + @staticmethod + def _from_proto(spec: temporalio.api.schedule.v1.ScheduleSpec) -> ScheduleSpec: + return ScheduleSpec( + calendars=[ + ScheduleCalendarSpec._from_proto(c) for c in spec.structured_calendar + ], + intervals=[ScheduleIntervalSpec._from_proto(i) for i in spec.interval], + cron_expressions=spec.cron_string, + skip=[ + ScheduleCalendarSpec._from_proto(c) + for c in spec.exclude_structured_calendar + ], + start_at=spec.start_time.ToDatetime().replace(tzinfo=timezone.utc) + if spec.HasField("start_time") + else None, + end_at=spec.end_time.ToDatetime().replace(tzinfo=timezone.utc) + if spec.HasField("end_time") + else None, + jitter=spec.jitter.ToTimedelta() if spec.HasField("jitter") else None, + time_zone_name=spec.timezone_name or None, + ) + + def _to_proto(self) -> temporalio.api.schedule.v1.ScheduleSpec: + start_time: google.protobuf.timestamp_pb2.Timestamp | None = None + if self.start_at: + start_time = google.protobuf.timestamp_pb2.Timestamp() + start_time.FromDatetime(self.start_at) + end_time: google.protobuf.timestamp_pb2.Timestamp | None = None + if self.end_at: + end_time = google.protobuf.timestamp_pb2.Timestamp() + end_time.FromDatetime(self.end_at) + jitter: google.protobuf.duration_pb2.Duration | None = None + if self.jitter: + jitter = google.protobuf.duration_pb2.Duration() + jitter.FromTimedelta(self.jitter) + return temporalio.api.schedule.v1.ScheduleSpec( + structured_calendar=[cal._to_proto() for cal in self.calendars], + cron_string=self.cron_expressions, + interval=[i._to_proto() for i in self.intervals], + exclude_structured_calendar=[cal._to_proto() for cal in self.skip], + start_time=start_time, + end_time=end_time, + jitter=jitter, + timezone_name=self.time_zone_name or "", + ) + + +@dataclass(frozen=True) +class ScheduleRange: + """Inclusive range for a schedule match value.""" + + start: int + """Inclusive start of the range.""" + + end: int = 0 + """Inclusive end of the range. + + If unset or less than start, defaults to start. + """ + + step: int = 0 + """ + Step to take between each value. + + Unset or 0 defaults as 1. + """ + + def __post_init__(self): + """Set field defaults.""" + # Class is frozen, so we must setattr bypassing dataclass setattr + if self.end < self.start: + object.__setattr__(self, "end", self.start) + if self.step == 0: + object.__setattr__(self, "step", 1) + + @staticmethod + def _from_protos( + ranges: Sequence[temporalio.api.schedule.v1.Range], + ) -> Sequence[ScheduleRange]: + return tuple(ScheduleRange._from_proto(r) for r in ranges) + + @staticmethod + def _from_proto(range: temporalio.api.schedule.v1.Range) -> ScheduleRange: + return ScheduleRange(start=range.start, end=range.end, step=range.step) + + @staticmethod + def _to_protos( + ranges: Sequence[ScheduleRange], + ) -> Sequence[temporalio.api.schedule.v1.Range]: + return tuple(r._to_proto() for r in ranges) + + def _to_proto(self) -> temporalio.api.schedule.v1.Range: + return temporalio.api.schedule.v1.Range( + start=self.start, end=self.end, step=self.step + ) + + +@dataclass +class ScheduleCalendarSpec: + """Specification relative to calendar time when to run an action. + + A timestamp matches if at least one range of each field matches except for + year. If year is missing, that means all years match. For all fields besides + year, at least one range must be present to match anything. + """ + + second: Sequence[ScheduleRange] = (ScheduleRange(0),) + """Second range to match, 0-59. Default matches 0.""" + + minute: Sequence[ScheduleRange] = (ScheduleRange(0),) + """Minute range to match, 0-59. Default matches 0.""" + + hour: Sequence[ScheduleRange] = (ScheduleRange(0),) + """Hour range to match, 0-23. Default matches 0.""" + + day_of_month: Sequence[ScheduleRange] = (ScheduleRange(1, 31),) + """Day of month range to match, 1-31. Default matches all days.""" + + month: Sequence[ScheduleRange] = (ScheduleRange(1, 12),) + """Month range to match, 1-12. Default matches all months.""" + + year: Sequence[ScheduleRange] = () + """Optional year range to match. Default of empty matches all years.""" + + day_of_week: Sequence[ScheduleRange] = (ScheduleRange(0, 6),) + """Day of week range to match, 0-6, 0 is Sunday. Default matches all + days.""" + + comment: str | None = None + """Description of this schedule.""" + + @staticmethod + def _from_proto( + spec: temporalio.api.schedule.v1.StructuredCalendarSpec, + ) -> ScheduleCalendarSpec: + return ScheduleCalendarSpec( + second=ScheduleRange._from_protos(spec.second), + minute=ScheduleRange._from_protos(spec.minute), + hour=ScheduleRange._from_protos(spec.hour), + day_of_month=ScheduleRange._from_protos(spec.day_of_month), + month=ScheduleRange._from_protos(spec.month), + year=ScheduleRange._from_protos(spec.year), + day_of_week=ScheduleRange._from_protos(spec.day_of_week), + comment=spec.comment or None, + ) + + def _to_proto(self) -> temporalio.api.schedule.v1.StructuredCalendarSpec: + return temporalio.api.schedule.v1.StructuredCalendarSpec( + second=ScheduleRange._to_protos(self.second), + minute=ScheduleRange._to_protos(self.minute), + hour=ScheduleRange._to_protos(self.hour), + day_of_month=ScheduleRange._to_protos(self.day_of_month), + month=ScheduleRange._to_protos(self.month), + year=ScheduleRange._to_protos(self.year), + day_of_week=ScheduleRange._to_protos(self.day_of_week), + comment=self.comment or "", + ) + + +@dataclass +class ScheduleIntervalSpec: + """Specification for scheduling on an interval. + + Matches times expressed as epoch + (n * every) + offset. + """ + + every: timedelta + """Period to repeat the interval.""" + + offset: timedelta | None = None + """Fixed offset added to each interval period.""" + + @staticmethod + def _from_proto( + spec: temporalio.api.schedule.v1.IntervalSpec, + ) -> ScheduleIntervalSpec: + return ScheduleIntervalSpec( + every=spec.interval.ToTimedelta(), + offset=spec.phase.ToTimedelta() if spec.HasField("phase") else None, + ) + + def _to_proto(self) -> temporalio.api.schedule.v1.IntervalSpec: + interval = google.protobuf.duration_pb2.Duration() + interval.FromTimedelta(self.every) + phase: google.protobuf.duration_pb2.Duration | None = None + if self.offset: + phase = google.protobuf.duration_pb2.Duration() + phase.FromTimedelta(self.offset) + return temporalio.api.schedule.v1.IntervalSpec(interval=interval, phase=phase) + + +class ScheduleAction(ABC): + """Base class for an action a schedule can take. + + See :py:class:`ScheduleActionStartWorkflow` for the most commonly used + implementation. + """ + + @staticmethod + def _from_proto( + action: temporalio.api.schedule.v1.ScheduleAction, + ) -> ScheduleAction: + if action.HasField("start_workflow"): + return ScheduleActionStartWorkflow._from_proto(action.start_workflow) + else: + raise ValueError(f"Unsupported action: {action.WhichOneof('action')}") + + @abstractmethod + async def _to_proto( + self, client: Client + ) -> temporalio.api.schedule.v1.ScheduleAction: ... + + +@dataclass +class ScheduleActionStartWorkflow(ScheduleAction): + """Schedule action to start a workflow.""" + + workflow: str + args: Sequence[Any] | Sequence[temporalio.api.common.v1.Payload] + id: str + task_queue: str + execution_timeout: timedelta | None + run_timeout: timedelta | None + task_timeout: timedelta | None + retry_policy: temporalio.common.RetryPolicy | None + memo: None | (Mapping[str, Any] | Mapping[str, temporalio.api.common.v1.Payload]) + typed_search_attributes: temporalio.common.TypedSearchAttributes + untyped_search_attributes: temporalio.common.SearchAttributes + """This is deprecated and is only present in case existing untyped + attributes already exist for update. This should never be used when + creating.""" + static_summary: str | temporalio.api.common.v1.Payload | None + static_details: str | temporalio.api.common.v1.Payload | None + priority: temporalio.common.Priority + + headers: Mapping[str, temporalio.api.common.v1.Payload] | None + """ + Headers may still be encoded by the payload codec if present. + """ + _from_raw: bool = dataclasses.field(compare=False, init=False) + + @staticmethod + def _from_proto( # pyright: ignore + info: temporalio.api.workflow.v1.NewWorkflowExecutionInfo, # type: ignore[override] + ) -> ScheduleActionStartWorkflow: + return ScheduleActionStartWorkflow("", raw_info=info) + + # Overload for no-param workflow + @overload + def __init__( + self, + workflow: MethodAsyncNoParam[SelfType, ReturnType], + *, + id: str, + task_queue: str, + execution_timeout: timedelta | None = None, + run_timeout: timedelta | None = None, + task_timeout: timedelta | None = None, + retry_policy: temporalio.common.RetryPolicy | None = None, + memo: Mapping[str, Any] | None = None, + typed_search_attributes: temporalio.common.TypedSearchAttributes = temporalio.common.TypedSearchAttributes.empty, + static_summary: str | None = None, + static_details: str | None = None, + priority: temporalio.common.Priority = temporalio.common.Priority.default, + ) -> None: ... + + # Overload for single-param workflow + @overload + def __init__( + self, + workflow: MethodAsyncSingleParam[SelfType, ParamType, ReturnType], + arg: ParamType, + *, + id: str, + task_queue: str, + execution_timeout: timedelta | None = None, + run_timeout: timedelta | None = None, + task_timeout: timedelta | None = None, + retry_policy: temporalio.common.RetryPolicy | None = None, + memo: Mapping[str, Any] | None = None, + typed_search_attributes: temporalio.common.TypedSearchAttributes = temporalio.common.TypedSearchAttributes.empty, + static_summary: str | None = None, + static_details: str | None = None, + priority: temporalio.common.Priority = temporalio.common.Priority.default, + ) -> None: ... + + # Overload for multi-param workflow + @overload + def __init__( + self, + workflow: Callable[ + Concatenate[SelfType, MultiParamSpec], Awaitable[ReturnType] + ], + *, + args: Sequence[Any], + id: str, + task_queue: str, + execution_timeout: timedelta | None = None, + run_timeout: timedelta | None = None, + task_timeout: timedelta | None = None, + retry_policy: temporalio.common.RetryPolicy | None = None, + memo: Mapping[str, Any] | None = None, + typed_search_attributes: temporalio.common.TypedSearchAttributes = temporalio.common.TypedSearchAttributes.empty, + static_summary: str | None = None, + static_details: str | None = None, + priority: temporalio.common.Priority = temporalio.common.Priority.default, + ) -> None: ... + + # Overload for string-name workflow + @overload + def __init__( + self, + workflow: str, + arg: Any = temporalio.common._arg_unset, + *, + args: Sequence[Any] = [], + id: str, + task_queue: str, + execution_timeout: timedelta | None = None, + run_timeout: timedelta | None = None, + task_timeout: timedelta | None = None, + retry_policy: temporalio.common.RetryPolicy | None = None, + memo: Mapping[str, Any] | None = None, + typed_search_attributes: temporalio.common.TypedSearchAttributes = temporalio.common.TypedSearchAttributes.empty, + static_summary: str | None = None, + static_details: str | None = None, + priority: temporalio.common.Priority = temporalio.common.Priority.default, + ) -> None: ... + + # Overload for raw info + @overload + def __init__( + self, + workflow: str, + *, + raw_info: temporalio.api.workflow.v1.NewWorkflowExecutionInfo, + ) -> None: ... + + def __init__( + self, + workflow: str | Callable[..., Awaitable[Any]], + arg: Any = temporalio.common._arg_unset, + *, + args: Sequence[Any] = [], + id: str | None = None, + task_queue: str | None = None, + execution_timeout: timedelta | None = None, + run_timeout: timedelta | None = None, + task_timeout: timedelta | None = None, + retry_policy: temporalio.common.RetryPolicy | None = None, + memo: Mapping[str, Any] | None = None, + typed_search_attributes: temporalio.common.TypedSearchAttributes = temporalio.common.TypedSearchAttributes.empty, + untyped_search_attributes: temporalio.common.SearchAttributes = {}, + static_summary: str | None = None, + static_details: str | None = None, + headers: Mapping[str, temporalio.api.common.v1.Payload] | None = None, + raw_info: temporalio.api.workflow.v1.NewWorkflowExecutionInfo | None = None, + priority: temporalio.common.Priority = temporalio.common.Priority.default, + ) -> None: + """Create a start-workflow action. + + See :py:meth:`Client.start_workflow` for details on these parameter + values. + """ + super().__init__() + if raw_info: + self._from_raw = True + # Ignore other fields + self.workflow = raw_info.workflow_type.name + self.args = raw_info.input.payloads if raw_info.input else [] + self.id = raw_info.workflow_id + self.task_queue = raw_info.task_queue.name + self.execution_timeout = ( + raw_info.workflow_execution_timeout.ToTimedelta() + if raw_info.HasField("workflow_execution_timeout") + else None + ) + self.run_timeout = ( + raw_info.workflow_run_timeout.ToTimedelta() + if raw_info.HasField("workflow_run_timeout") + else None + ) + self.task_timeout = ( + raw_info.workflow_task_timeout.ToTimedelta() + if raw_info.HasField("workflow_task_timeout") + else None + ) + self.retry_policy = ( + temporalio.common.RetryPolicy.from_proto(raw_info.retry_policy) + if raw_info.HasField("retry_policy") + else None + ) + self.memo = raw_info.memo.fields if raw_info.memo.fields else None + self.typed_search_attributes = ( + temporalio.converter.decode_typed_search_attributes( + raw_info.search_attributes + ) + ) + self.headers = raw_info.header.fields if raw_info.header.fields else None + # Also set the untyped attributes as the set of attributes from + # decode with the typed ones removed + self.untyped_search_attributes = ( + temporalio.converter.decode_search_attributes( + raw_info.search_attributes + ) + ) + for pair in self.typed_search_attributes: + if pair.key.name in self.untyped_search_attributes: + # We know this is mutable here + del self.untyped_search_attributes[pair.key.name] # type: ignore + self.static_summary = ( + raw_info.user_metadata.summary + if raw_info.HasField("user_metadata") and raw_info.user_metadata.summary + else None + ) + self.static_details = ( + raw_info.user_metadata.details + if raw_info.HasField("user_metadata") and raw_info.user_metadata.details + else None + ) + self.priority = ( + temporalio.common.Priority._from_proto(raw_info.priority) + if raw_info.HasField("priority") and raw_info.priority + else temporalio.common.Priority.default + ) + else: + self._from_raw = False + if not id: + raise ValueError("ID required") + if not task_queue: + raise ValueError("Task queue required") + # Use definition if callable + if callable(workflow): + defn = temporalio.workflow._Definition.must_from_run_fn(workflow) + if not defn.name: + raise ValueError("Cannot schedule dynamic workflow explicitly") + workflow = defn.name + elif not isinstance(workflow, str): + raise TypeError("Workflow must be a string or callable") # type:ignore[reportUnreachable] + self.workflow = workflow + self.args = temporalio.common._arg_or_args(arg, args) + self.id = id + self.task_queue = task_queue + self.execution_timeout = execution_timeout + self.run_timeout = run_timeout + self.task_timeout = task_timeout + self.retry_policy = retry_policy + self.memo = memo + self.typed_search_attributes = typed_search_attributes + self.untyped_search_attributes = untyped_search_attributes + self.headers = headers # encode here + self.static_summary = static_summary + self.static_details = static_details + self.priority = priority + + async def _to_proto( + self, client: Client + ) -> temporalio.api.schedule.v1.ScheduleAction: + execution_timeout: google.protobuf.duration_pb2.Duration | None = None + if self.execution_timeout: + execution_timeout = google.protobuf.duration_pb2.Duration() + execution_timeout.FromTimedelta(self.execution_timeout) + run_timeout: google.protobuf.duration_pb2.Duration | None = None + if self.run_timeout: + run_timeout = google.protobuf.duration_pb2.Duration() + run_timeout.FromTimedelta(self.run_timeout) + task_timeout: google.protobuf.duration_pb2.Duration | None = None + if self.task_timeout: + task_timeout = google.protobuf.duration_pb2.Duration() + task_timeout.FromTimedelta(self.task_timeout) + retry_policy: temporalio.api.common.v1.RetryPolicy | None = None + if self.retry_policy: + retry_policy = temporalio.api.common.v1.RetryPolicy() + self.retry_policy.apply_to_proto(retry_policy) + priority: temporalio.api.common.v1.Priority | None = None + if self.priority: + priority = self.priority._to_proto() + data_converter = client.data_converter._with_contexts( + WorkflowSerializationContext( + namespace=client.namespace, + workflow_id=self.id, + ), + StorageDriverStoreContext( + target=StorageDriverWorkflowInfo( + id=self.id, type=self.workflow, namespace=client.namespace + ), + ), + ) + action = temporalio.api.schedule.v1.ScheduleAction( + start_workflow=temporalio.api.workflow.v1.NewWorkflowExecutionInfo( + workflow_id=self.id, + workflow_type=temporalio.api.common.v1.WorkflowType(name=self.workflow), + task_queue=temporalio.api.taskqueue.v1.TaskQueue(name=self.task_queue), + input=( + temporalio.api.common.v1.Payloads( + payloads=[ + a + if isinstance(a, temporalio.api.common.v1.Payload) + else (await data_converter.encode([a]))[0] + for a in self.args + ] + ) + if self.args + else None + ), + workflow_execution_timeout=execution_timeout, + workflow_run_timeout=run_timeout, + workflow_task_timeout=task_timeout, + retry_policy=retry_policy, + memo=await data_converter._encode_memo(self.memo) + if self.memo + else None, + user_metadata=await _encode_user_metadata( + data_converter, self.static_summary, self.static_details + ), + priority=priority, + ), + ) + # Add any untyped attributes that are not also in the typed set + untyped_not_in_typed = { + k: v + for k, v in self.untyped_search_attributes.items() + if k not in self.typed_search_attributes + } + if untyped_not_in_typed: + temporalio.converter.encode_search_attributes( + untyped_not_in_typed, action.start_workflow.search_attributes + ) + # TODO (dan): confirm whether this be `is not None` + if self.typed_search_attributes: + temporalio.converter.encode_search_attributes( + self.typed_search_attributes, + action.start_workflow.search_attributes, + ) + if self.headers: + await _apply_headers( + self.headers, + action.start_workflow.header.fields, + client.config(active_config=True)["header_codec_behavior"] + == HeaderCodecBehavior.CODEC + and not self._from_raw, + client.data_converter, + ) + return action + + +class ScheduleOverlapPolicy(IntEnum): + """Controls what happens when a workflow would be started by a schedule but + one is already running. + """ + + SKIP = int( + temporalio.api.enums.v1.ScheduleOverlapPolicy.SCHEDULE_OVERLAP_POLICY_SKIP + ) + """Don't start anything. + + When the workflow completes, the next scheduled event after that time will + be considered. + """ + + BUFFER_ONE = int( + temporalio.api.enums.v1.ScheduleOverlapPolicy.SCHEDULE_OVERLAP_POLICY_BUFFER_ONE + ) + """Start the workflow again soon as the current one completes, but only + buffer one start in this way. + + If another start is supposed to happen when the workflow is running, and one + is already buffered, then only the first one will be started after the + running workflow finishes. + """ + + BUFFER_ALL = int( + temporalio.api.enums.v1.ScheduleOverlapPolicy.SCHEDULE_OVERLAP_POLICY_BUFFER_ALL + ) + """Buffer up any number of starts to all happen sequentially, immediately + after the running workflow completes.""" + + CANCEL_OTHER = int( + temporalio.api.enums.v1.ScheduleOverlapPolicy.SCHEDULE_OVERLAP_POLICY_CANCEL_OTHER + ) + """If there is another workflow running, cancel it, and start the new one + after the old one completes cancellation.""" + + TERMINATE_OTHER = int( + temporalio.api.enums.v1.ScheduleOverlapPolicy.SCHEDULE_OVERLAP_POLICY_TERMINATE_OTHER + ) + """If there is another workflow running, terminate it and start the new one + immediately.""" + + ALLOW_ALL = int( + temporalio.api.enums.v1.ScheduleOverlapPolicy.SCHEDULE_OVERLAP_POLICY_ALLOW_ALL + ) + """Start any number of concurrent workflows. + + Note that with this policy, last completion result and last failure will not + be available since workflows are not sequential.""" + + +@dataclass +class ScheduleBackfill: + """Time period and policy for actions taken as if the time passed right + now. + """ + + start_at: datetime + """Start of the range to evaluate the schedule in. + + This is exclusive + """ + end_at: datetime + overlap: ScheduleOverlapPolicy | None = None + + def _to_proto(self) -> temporalio.api.schedule.v1.BackfillRequest: + start_time = google.protobuf.timestamp_pb2.Timestamp() + start_time.FromDatetime(self.start_at) + end_time = google.protobuf.timestamp_pb2.Timestamp() + end_time.FromDatetime(self.end_at) + overlap_policy = temporalio.api.enums.v1.ScheduleOverlapPolicy.SCHEDULE_OVERLAP_POLICY_UNSPECIFIED + if self.overlap: + overlap_policy = temporalio.api.enums.v1.ScheduleOverlapPolicy.ValueType( + self.overlap + ) + return temporalio.api.schedule.v1.BackfillRequest( + start_time=start_time, + end_time=end_time, + overlap_policy=overlap_policy, + ) + + +@dataclass +class SchedulePolicy: + """Policies of a schedule.""" + + overlap: ScheduleOverlapPolicy = dataclasses.field( + default_factory=lambda: ScheduleOverlapPolicy.SKIP + ) + """Controls what happens when an action is started while another is still + running.""" + + catchup_window: timedelta = timedelta(days=365) + """After a Temporal server is unavailable, amount of time in the past to + execute missed actions.""" + + pause_on_failure: bool = False + """Whether to pause the schedule if an action fails or times out. + + Note: For workflows, this only applies after all retries have been + exhausted. + """ + + @staticmethod + def _from_proto(pol: temporalio.api.schedule.v1.SchedulePolicies) -> SchedulePolicy: + return SchedulePolicy( + overlap=ScheduleOverlapPolicy(int(pol.overlap_policy)), + catchup_window=pol.catchup_window.ToTimedelta(), + pause_on_failure=pol.pause_on_failure, + ) + + def _to_proto(self) -> temporalio.api.schedule.v1.SchedulePolicies: + catchup_window = google.protobuf.duration_pb2.Duration() + catchup_window.FromTimedelta(self.catchup_window) + return temporalio.api.schedule.v1.SchedulePolicies( + overlap_policy=temporalio.api.enums.v1.ScheduleOverlapPolicy.ValueType( + self.overlap + ), + catchup_window=catchup_window, + pause_on_failure=self.pause_on_failure, + ) + + +@dataclass +class ScheduleState: + """State of a schedule.""" + + note: str | None = None + """Human readable message for the schedule. + + The system may overwrite this value on certain conditions like + pause-on-failure. + """ + + paused: bool = False + """Whether the schedule is paused.""" + + # Cannot be set to True on create + limited_actions: bool = False + """ + If true, remaining actions will be decremented for each action taken. + + On schedule create, this must be set to true if :py:attr:`remaining_actions` + is non-zero and left false if :py:attr:`remaining_actions` is zero. + """ + + remaining_actions: int = 0 + """Actions remaining on this schedule. + + Once this number hits 0, no further actions are scheduled automatically. + """ + + @staticmethod + def _from_proto(state: temporalio.api.schedule.v1.ScheduleState) -> ScheduleState: + return ScheduleState( + note=state.notes or None, + paused=state.paused, + limited_actions=state.limited_actions, + remaining_actions=state.remaining_actions, + ) + + def _to_proto(self) -> temporalio.api.schedule.v1.ScheduleState: + return temporalio.api.schedule.v1.ScheduleState( + notes=self.note or "", + paused=self.paused, + limited_actions=self.limited_actions, + remaining_actions=self.remaining_actions, + ) + + +@dataclass +class Schedule: + """A schedule for periodically running an action.""" + + action: ScheduleAction + """Action taken when scheduled.""" + + spec: ScheduleSpec + """When the action is taken.""" + + policy: SchedulePolicy = dataclasses.field(default_factory=SchedulePolicy) + """Schedule policies.""" + + state: ScheduleState = dataclasses.field(default_factory=ScheduleState) + """State of the schedule.""" + + @staticmethod + def _from_proto(sched: temporalio.api.schedule.v1.Schedule) -> Schedule: + return Schedule( + action=ScheduleAction._from_proto(sched.action), + spec=ScheduleSpec._from_proto(sched.spec), + policy=SchedulePolicy._from_proto(sched.policies), + state=ScheduleState._from_proto(sched.state), + ) + + async def _to_proto(self, client: Client) -> temporalio.api.schedule.v1.Schedule: + catchup_window = google.protobuf.duration_pb2.Duration() + catchup_window.FromTimedelta(self.policy.catchup_window) + return temporalio.api.schedule.v1.Schedule( + spec=self.spec._to_proto(), + action=await self.action._to_proto(client), + policies=self.policy._to_proto(), + state=self.state._to_proto(), + ) + + +@dataclass +class ScheduleDescription: + """Description of a schedule.""" + + id: str + """ID of the schedule.""" + + schedule: Schedule + """Schedule details that can be mutated.""" + + info: ScheduleInfo + """Information about the schedule.""" + + typed_search_attributes: temporalio.common.TypedSearchAttributes + """Search attributes on the schedule.""" + + search_attributes: temporalio.common.SearchAttributes + """Search attributes on the schedule. + + .. deprecated:: + Use :py:attr:`typed_search_attributes` instead. + """ + + data_converter: temporalio.converter.DataConverter + """Data converter used for memo decoding.""" + + raw_description: temporalio.api.workflowservice.v1.DescribeScheduleResponse + """Raw description of the schedule.""" + + @staticmethod + def _from_proto( + id: str, + desc: temporalio.api.workflowservice.v1.DescribeScheduleResponse, + converter: temporalio.converter.DataConverter, + ) -> ScheduleDescription: + return ScheduleDescription( + id=id, + schedule=Schedule._from_proto(desc.schedule), + info=ScheduleInfo._from_proto(desc.info), + typed_search_attributes=temporalio.converter.decode_typed_search_attributes( + desc.search_attributes + ), + search_attributes=temporalio.converter.decode_search_attributes( + desc.search_attributes + ), + data_converter=converter, + raw_description=desc, + ) + + async def memo(self) -> Mapping[str, Any]: + """Schedule's memo values, converted without type hints. + + Since type hints are not used, the default converted values will come + back. For example, if the memo was originally created with a dataclass, + the value will be a dict. To convert using proper type hints, use + :py:meth:`memo_value`. + + Returns: + Mapping of all memo keys and they values without type hints. + """ + return await self.data_converter._decode_memo(self.raw_description.memo) + + @overload + async def memo_value( + self, key: str, default: Any = temporalio.common._arg_unset + ) -> Any: ... + + @overload + async def memo_value( + self, key: str, *, type_hint: type[ParamType] + ) -> ParamType: ... + + @overload + async def memo_value( + self, key: str, default: AnyType, *, type_hint: type[ParamType] + ) -> AnyType | ParamType: ... + + async def memo_value( + self, + key: str, + default: Any = temporalio.common._arg_unset, + *, + type_hint: type | None = None, + ) -> Any: + """Memo value for the given key, optional default, and optional type + hint. + + Args: + key: Key to get memo value for. + default: Default to use if key is not present. If unset, a + :py:class:`KeyError` is raised when the key does not exist. + type_hint: type hint to use when converting. + + Returns: + Memo value, converted with the type hint if present. + + Raises: + KeyError: Key not present and default not set. + """ + return await self.data_converter._decode_memo_field( + self.raw_description.memo, key, default, type_hint + ) + + +@dataclass +class ScheduleInfo: + """Information about a schedule.""" + + num_actions: int + """Number of actions taken by this schedule.""" + + num_actions_missed_catchup_window: int + """Number of times an action was skipped due to missing the catchup + window.""" + + num_actions_skipped_overlap: int + """Number of actions skipped due to overlap.""" + + running_actions: Sequence[ScheduleActionExecution] + """Currently running actions.""" + + recent_actions: Sequence[ScheduleActionResult] + """10 most recent actions, oldest first.""" + + next_action_times: Sequence[datetime] + """Next 10 scheduled action times.""" + + created_at: datetime + """When the schedule was created.""" + + last_updated_at: datetime | None + """When the schedule was last updated.""" + + @staticmethod + def _from_proto(info: temporalio.api.schedule.v1.ScheduleInfo) -> ScheduleInfo: + return ScheduleInfo( + num_actions=info.action_count, + num_actions_missed_catchup_window=info.missed_catchup_window, + num_actions_skipped_overlap=info.overlap_skipped, + running_actions=[ + ScheduleActionExecutionStartWorkflow._from_proto(r) + for r in info.running_workflows + ], + recent_actions=[ + ScheduleActionResult._from_proto(r) for r in info.recent_actions + ], + next_action_times=[ + f.ToDatetime().replace(tzinfo=timezone.utc) + for f in info.future_action_times + ], + created_at=info.create_time.ToDatetime().replace(tzinfo=timezone.utc), + last_updated_at=info.update_time.ToDatetime().replace(tzinfo=timezone.utc) + if info.HasField("update_time") + else None, + ) + + +class ScheduleActionExecution(ABC): + """Base class for an action execution.""" + + pass + + +@dataclass +class ScheduleActionExecutionStartWorkflow(ScheduleActionExecution): + """Execution of a scheduled workflow start.""" + + workflow_id: str + """Workflow ID.""" + + first_execution_run_id: str + """Workflow run ID.""" + + @staticmethod + def _from_proto( + exec: temporalio.api.common.v1.WorkflowExecution, + ) -> ScheduleActionExecutionStartWorkflow: + return ScheduleActionExecutionStartWorkflow( + workflow_id=exec.workflow_id, + first_execution_run_id=exec.run_id, + ) + + +@dataclass +class ScheduleActionResult: + """Information about when an action took place.""" + + scheduled_at: datetime + """Scheduled time of the action including jitter.""" + + started_at: datetime + """When the action actually started.""" + + action: ScheduleActionExecution + """Action that took place.""" + + @staticmethod + def _from_proto( + res: temporalio.api.schedule.v1.ScheduleActionResult, + ) -> ScheduleActionResult: + return ScheduleActionResult( + scheduled_at=res.schedule_time.ToDatetime().replace(tzinfo=timezone.utc), + started_at=res.actual_time.ToDatetime().replace(tzinfo=timezone.utc), + action=ScheduleActionExecutionStartWorkflow._from_proto( + res.start_workflow_result + ), + ) + + +@dataclass +class ScheduleUpdateInput: + """Parameter for an update callback for :py:meth:`ScheduleHandle.update`.""" + + description: ScheduleDescription + """Current description of the schedule.""" + + +@dataclass +class ScheduleUpdate: + """Result of an update callback for :py:meth:`ScheduleHandle.update`.""" + + schedule: Schedule + """Schedule to update.""" + + search_attributes: temporalio.common.TypedSearchAttributes | None = None + """Search attributes to update.""" + + +@dataclass +class ScheduleListDescription: + """Description of a listed schedule.""" + + id: str + """ID of the schedule.""" + + schedule: ScheduleListSchedule | None + """Schedule details that can be mutated. + + This may not be present in older Temporal servers without advanced + visibility. + """ + + info: ScheduleListInfo | None + """Information about the schedule. + + This may not be present in older Temporal servers without advanced + visibility. + """ + + typed_search_attributes: temporalio.common.TypedSearchAttributes + """Search attributes on the schedule.""" + + search_attributes: temporalio.common.SearchAttributes + """Search attributes on the schedule. + + .. deprecated:: + Use :py:attr:`typed_search_attributes` instead. + """ + + data_converter: temporalio.converter.DataConverter + """Data converter used for memo decoding.""" + + raw_entry: temporalio.api.schedule.v1.ScheduleListEntry + """Raw description of the schedule.""" + + @staticmethod + def _from_proto( + entry: temporalio.api.schedule.v1.ScheduleListEntry, + converter: temporalio.converter.DataConverter, + ) -> ScheduleListDescription: + return ScheduleListDescription( + id=entry.schedule_id, + schedule=ScheduleListSchedule._from_proto(entry.info) + if entry.HasField("info") + else None, + info=ScheduleListInfo._from_proto(entry.info) + if entry.HasField("info") + else None, + typed_search_attributes=temporalio.converter.decode_typed_search_attributes( + entry.search_attributes + ), + search_attributes=temporalio.converter.decode_search_attributes( + entry.search_attributes + ), + data_converter=converter, + raw_entry=entry, + ) + + async def memo(self) -> Mapping[str, Any]: + """Schedule's memo values, converted without type hints. + + Since type hints are not used, the default converted values will come + back. For example, if the memo was originally created with a dataclass, + the value will be a dict. To convert using proper type hints, use + :py:meth:`memo_value`. + + Returns: + Mapping of all memo keys and they values without type hints. + """ + return await self.data_converter._decode_memo(self.raw_entry.memo) + + @overload + async def memo_value( + self, key: str, default: Any = temporalio.common._arg_unset + ) -> Any: ... + + @overload + async def memo_value( + self, key: str, *, type_hint: type[ParamType] + ) -> ParamType: ... + + @overload + async def memo_value( + self, key: str, default: AnyType, *, type_hint: type[ParamType] + ) -> AnyType | ParamType: ... + + async def memo_value( + self, + key: str, + default: Any = temporalio.common._arg_unset, + *, + type_hint: type | None = None, + ) -> Any: + """Memo value for the given key, optional default, and optional type + hint. + + Args: + key: Key to get memo value for. + default: Default to use if key is not present. If unset, a + :py:class:`KeyError` is raised when the key does not exist. + type_hint: type hint to use when converting. + + Returns: + Memo value, converted with the type hint if present. + + Raises: + KeyError: Key not present and default not set. + """ + return await self.data_converter._decode_memo_field( + self.raw_entry.memo, key, default, type_hint + ) + + +@dataclass +class ScheduleListSchedule: + """Details for a listed schedule.""" + + action: ScheduleListAction + """Action taken when scheduled.""" + + spec: ScheduleSpec + """When the action is taken.""" + + state: ScheduleListState + """State of the schedule.""" + + @staticmethod + def _from_proto( + info: temporalio.api.schedule.v1.ScheduleListInfo, + ) -> ScheduleListSchedule: + # Only start workflow supported for now + if not info.HasField("workflow_type"): + raise ValueError("Unknown action on schedule") + return ScheduleListSchedule( + action=ScheduleListActionStartWorkflow(workflow=info.workflow_type.name), + spec=ScheduleSpec._from_proto(info.spec), + state=ScheduleListState._from_proto(info), + ) + + +class ScheduleListAction(ABC): + """Base class for an action a listed schedule can take.""" + + pass + + +@dataclass +class ScheduleListActionStartWorkflow(ScheduleListAction): + """Action to start a workflow on a listed schedule.""" + + workflow: str + """Workflow type name.""" + + +@dataclass +class ScheduleListInfo: + """Information about a listed schedule.""" + + recent_actions: Sequence[ScheduleActionResult] + """Most recent actions, oldest first. + + This may be a smaller amount than present on + :py:attr:`ScheduleDescription.info`. + """ + + next_action_times: Sequence[datetime] + """Next scheduled action times. + + This may be a smaller amount than present on + :py:attr:`ScheduleDescription.info`. + """ + + @staticmethod + def _from_proto( + info: temporalio.api.schedule.v1.ScheduleListInfo, + ) -> ScheduleListInfo: + return ScheduleListInfo( + recent_actions=[ + ScheduleActionResult._from_proto(r) for r in info.recent_actions + ], + next_action_times=[ + f.ToDatetime().replace(tzinfo=timezone.utc) + for f in info.future_action_times + ], + ) + + +@dataclass +class ScheduleListState: + """State of a listed schedule.""" + + note: str | None + """Human readable message for the schedule. + + The system may overwrite this value on certain conditions like + pause-on-failure. + """ + + paused: bool + """Whether the schedule is paused.""" + + @staticmethod + def _from_proto( + info: temporalio.api.schedule.v1.ScheduleListInfo, + ) -> ScheduleListState: + return ScheduleListState( + note=info.notes or None, + paused=info.paused, + ) + + +class ScheduleAsyncIterator: + """Asynchronous iterator for :py:class:`ScheduleListDescription` values. + + Most users should use ``async for`` on this iterator and not call any of the + methods within. + """ + + def __init__( + self, + client: Client, + input: ListSchedulesInput, + ) -> None: + """Create an asynchronous iterator for the given input. + + Users should not create this directly, but rather use + :py:meth:`Client.list_schedules`. + """ + self._client = client + self._input = input + self._next_page_token = input.next_page_token + self._current_page: Sequence[ScheduleListDescription] | None = None + self._current_page_index = 0 + + @property + def current_page_index(self) -> int: + """Index of the entry in the current page that will be returned from + the next :py:meth:`__anext__` call. + """ + return self._current_page_index + + @property + def current_page(self) -> Sequence[ScheduleListDescription] | None: + """Current page, if it has been fetched yet.""" + return self._current_page + + @property + def next_page_token(self) -> bytes | None: + """Token for the next page request if any.""" + return self._next_page_token + + async def fetch_next_page(self, *, page_size: int | None = None) -> None: + """Fetch the next page if any. + + Args: + page_size: Override the page size this iterator was originally + created with. + """ + resp = await self._client.workflow_service.list_schedules( + temporalio.api.workflowservice.v1.ListSchedulesRequest( + namespace=self._client.namespace, + maximum_page_size=page_size or self._input.page_size, + next_page_token=self._next_page_token or b"", + query=self._input.query or "", + ), + retry=True, + metadata=self._input.rpc_metadata, + timeout=self._input.rpc_timeout, + ) + self._current_page = [ + ScheduleListDescription._from_proto(v, self._client.data_converter) + for v in resp.schedules + ] + self._current_page_index = 0 + self._next_page_token = resp.next_page_token or None + + def __aiter__(self) -> ScheduleAsyncIterator: + """Return self as the iterator.""" + return self + + async def __anext__(self) -> ScheduleListDescription: + """Get the next execution on this iterator, fetching next page if + necessary. + """ + while True: + # No page? fetch and continue + if self._current_page is None: + await self.fetch_next_page() + continue + # No more left in page? + if self._current_page_index >= len(self._current_page): + # If there is a next page token, try to get another page and try + # again + if self._next_page_token is not None: + await self.fetch_next_page() + continue + # No more pages means we're done + raise StopAsyncIteration + # Get current, increment page index, and return + ret = self._current_page[self._current_page_index] + self._current_page_index += 1 + return ret diff --git a/temporalio/client/_worker_versioning.py b/temporalio/client/_worker_versioning.py new file mode 100644 index 000000000..d6ef8f257 --- /dev/null +++ b/temporalio/client/_worker_versioning.py @@ -0,0 +1,278 @@ +"""Client support for accessing Temporal.""" + +from __future__ import annotations + +from abc import ABC, abstractmethod +from collections.abc import ( + Mapping, + Sequence, +) +from dataclasses import dataclass +from enum import Enum + +import temporalio.api.enums.v1 +import temporalio.api.workflowservice.v1 + + +@dataclass(frozen=True) +class WorkerBuildIdVersionSets: + """Represents the sets of compatible Build ID versions associated with some Task Queue, as + fetched by :py:meth:`Client.get_worker_build_id_compatibility`. + """ + + version_sets: Sequence[BuildIdVersionSet] + """All version sets that were fetched for this task queue.""" + + def default_set(self) -> BuildIdVersionSet: + """Returns the default version set for this task queue.""" + return self.version_sets[-1] + + def default_build_id(self) -> str: + """Returns the default Build ID for this task queue.""" + return self.default_set().default() + + @staticmethod + def _from_proto( + resp: temporalio.api.workflowservice.v1.GetWorkerBuildIdCompatibilityResponse, + ) -> WorkerBuildIdVersionSets: + return WorkerBuildIdVersionSets( + version_sets=[ + BuildIdVersionSet(mvs.build_ids) for mvs in resp.major_version_sets + ] + ) + + +@dataclass(frozen=True) +class BuildIdVersionSet: + """A set of Build IDs which are compatible with each other.""" + + build_ids: Sequence[str] + """All Build IDs contained in the set.""" + + def default(self) -> str: + """Returns the default Build ID for this set.""" + return self.build_ids[-1] + + +class BuildIdOp(ABC): + """Base class for Build ID operations as used by + :py:meth:`Client.update_worker_build_id_compatibility`. + """ + + @abstractmethod + def _as_partial_proto( + self, + ) -> temporalio.api.workflowservice.v1.UpdateWorkerBuildIdCompatibilityRequest: + """Returns a partial request with the operation populated. Caller must populate + non-operation fields. This is done b/c there's no good way to assign a non-primitive message + as the operation after initializing the request. + """ + ... + + +@dataclass(frozen=True) +class BuildIdOpAddNewDefault(BuildIdOp): + """Adds a new Build Id into a new set, which will be used as the default set for + the queue. This means all new workflows will start on this Build Id. + """ + + build_id: str + + def _as_partial_proto( + self, + ) -> temporalio.api.workflowservice.v1.UpdateWorkerBuildIdCompatibilityRequest: + return ( + temporalio.api.workflowservice.v1.UpdateWorkerBuildIdCompatibilityRequest( + add_new_build_id_in_new_default_set=self.build_id + ) + ) + + +@dataclass(frozen=True) +class BuildIdOpAddNewCompatible(BuildIdOp): + """Adds a new Build Id into an existing compatible set. The newly added ID becomes + the default for that compatible set, and thus new workflow tasks for workflows which have been + executing on workers in that set will now start on this new Build Id. + """ + + build_id: str + """The Build Id to add to the compatible set.""" + + existing_compatible_build_id: str + """A Build Id which must already be defined on the task queue, and is used to find the + compatible set to add the new id to. + """ + + promote_set: bool = False + """If set to true, the targeted set will also be promoted to become the overall default set for + the queue.""" + + def _as_partial_proto( + self, + ) -> temporalio.api.workflowservice.v1.UpdateWorkerBuildIdCompatibilityRequest: + return temporalio.api.workflowservice.v1.UpdateWorkerBuildIdCompatibilityRequest( + add_new_compatible_build_id=temporalio.api.workflowservice.v1.UpdateWorkerBuildIdCompatibilityRequest.AddNewCompatibleVersion( + new_build_id=self.build_id, + existing_compatible_build_id=self.existing_compatible_build_id, + make_set_default=self.promote_set, + ) + ) + + +@dataclass(frozen=True) +class BuildIdOpPromoteSetByBuildId(BuildIdOp): + """Promotes a set of compatible Build Ids to become the current default set for the task queue. + Any Build Id in the set may be used to target it. + """ + + build_id: str + """A Build Id which must already be defined on the task queue, and is used to find the + compatible set to promote.""" + + def _as_partial_proto( + self, + ) -> temporalio.api.workflowservice.v1.UpdateWorkerBuildIdCompatibilityRequest: + return ( + temporalio.api.workflowservice.v1.UpdateWorkerBuildIdCompatibilityRequest( + promote_set_by_build_id=self.build_id + ) + ) + + +@dataclass(frozen=True) +class BuildIdOpPromoteBuildIdWithinSet(BuildIdOp): + """Promotes a Build Id within an existing set to become the default ID for that set.""" + + build_id: str + + def _as_partial_proto( + self, + ) -> temporalio.api.workflowservice.v1.UpdateWorkerBuildIdCompatibilityRequest: + return ( + temporalio.api.workflowservice.v1.UpdateWorkerBuildIdCompatibilityRequest( + promote_build_id_within_set=self.build_id + ) + ) + + +@dataclass(frozen=True) +class BuildIdOpMergeSets(BuildIdOp): + """Merges two sets into one set, thus declaring all the Build Ids in both as compatible with one + another. The default of the primary set is maintained as the merged set's overall default. + """ + + primary_build_id: str + """A Build Id which and is used to find the primary set to be merged.""" + + secondary_build_id: str + """A Build Id which and is used to find the secondary set to be merged.""" + + def _as_partial_proto( + self, + ) -> temporalio.api.workflowservice.v1.UpdateWorkerBuildIdCompatibilityRequest: + return temporalio.api.workflowservice.v1.UpdateWorkerBuildIdCompatibilityRequest( + merge_sets=temporalio.api.workflowservice.v1.UpdateWorkerBuildIdCompatibilityRequest.MergeSets( + primary_set_build_id=self.primary_build_id, + secondary_set_build_id=self.secondary_build_id, + ) + ) + + +@dataclass(frozen=True) +class WorkerTaskReachability: + """Contains information about the reachability of some Build IDs""" + + build_id_reachability: Mapping[str, BuildIdReachability] + """Maps Build IDs to information about their reachability""" + + @staticmethod + def _from_proto( + resp: temporalio.api.workflowservice.v1.GetWorkerTaskReachabilityResponse, + ) -> WorkerTaskReachability: + mapping = dict() + for bid_reach in resp.build_id_reachability: + tq_mapping = dict() + unretrieved = set() + for tq_reach in bid_reach.task_queue_reachability: + if tq_reach.reachability == [ + temporalio.api.enums.v1.TaskReachability.TASK_REACHABILITY_UNSPECIFIED + ]: + unretrieved.add(tq_reach.task_queue) + continue + tq_mapping[tq_reach.task_queue] = [ + TaskReachabilityType._from_proto(r) for r in tq_reach.reachability + ] + + mapping[bid_reach.build_id] = BuildIdReachability( + task_queue_reachability=tq_mapping, + unretrieved_task_queues=frozenset(unretrieved), + ) + + return WorkerTaskReachability(build_id_reachability=mapping) + + +@dataclass(frozen=True) +class BuildIdReachability: + """Contains information about the reachability of a specific Build ID""" + + task_queue_reachability: Mapping[str, Sequence[TaskReachabilityType]] + """Maps Task Queue names to the reachability status of the Build ID on that queue. If the value + is an empty list, the Build ID is not reachable on that queue. + """ + + unretrieved_task_queues: frozenset[str] + """If any Task Queues could not be retrieved because the server limits the number that can be + queried at once, they will be listed here. + """ + + +class TaskReachabilityType(Enum): + """Enumerates how a task might reach certain kinds of workflows""" + + NEW_WORKFLOWS = 1 + EXISTING_WORKFLOWS = 2 + OPEN_WORKFLOWS = 3 + CLOSED_WORKFLOWS = 4 + + @staticmethod + def _from_proto( + reachability: temporalio.api.enums.v1.TaskReachability.ValueType, + ) -> TaskReachabilityType: + if ( + reachability + == temporalio.api.enums.v1.TaskReachability.TASK_REACHABILITY_NEW_WORKFLOWS + ): + return TaskReachabilityType.NEW_WORKFLOWS + elif ( + reachability + == temporalio.api.enums.v1.TaskReachability.TASK_REACHABILITY_EXISTING_WORKFLOWS + ): + return TaskReachabilityType.EXISTING_WORKFLOWS + elif ( + reachability + == temporalio.api.enums.v1.TaskReachability.TASK_REACHABILITY_OPEN_WORKFLOWS + ): + return TaskReachabilityType.OPEN_WORKFLOWS + elif ( + reachability + == temporalio.api.enums.v1.TaskReachability.TASK_REACHABILITY_CLOSED_WORKFLOWS + ): + return TaskReachabilityType.CLOSED_WORKFLOWS + else: + raise ValueError(f"Cannot convert reachability type: {reachability}") + + def _to_proto(self) -> temporalio.api.enums.v1.TaskReachability.ValueType: + if self == TaskReachabilityType.NEW_WORKFLOWS: + return ( + temporalio.api.enums.v1.TaskReachability.TASK_REACHABILITY_NEW_WORKFLOWS + ) + elif self == TaskReachabilityType.EXISTING_WORKFLOWS: + return temporalio.api.enums.v1.TaskReachability.TASK_REACHABILITY_EXISTING_WORKFLOWS + elif self == TaskReachabilityType.OPEN_WORKFLOWS: + return temporalio.api.enums.v1.TaskReachability.TASK_REACHABILITY_OPEN_WORKFLOWS + elif self == TaskReachabilityType.CLOSED_WORKFLOWS: + return temporalio.api.enums.v1.TaskReachability.TASK_REACHABILITY_CLOSED_WORKFLOWS + else: + return ( + temporalio.api.enums.v1.TaskReachability.TASK_REACHABILITY_UNSPECIFIED + ) diff --git a/temporalio/client/_workflow.py b/temporalio/client/_workflow.py new file mode 100644 index 000000000..22ac00d84 --- /dev/null +++ b/temporalio/client/_workflow.py @@ -0,0 +1,2000 @@ +"""Client support for accessing Temporal.""" + +from __future__ import annotations + +import asyncio +import functools +import warnings +from asyncio import Future +from collections.abc import ( + AsyncIterator, + Awaitable, + Callable, + Mapping, + Sequence, +) +from dataclasses import dataclass +from datetime import datetime, timedelta, timezone +from enum import IntEnum +from typing import ( + TYPE_CHECKING, + Any, + Concatenate, + Generic, + cast, + overload, +) + +import google.protobuf.json_format +from typing_extensions import Self + +import temporalio.api.common.v1 +import temporalio.api.enums.v1 +import temporalio.api.history.v1 +import temporalio.api.update.v1 +import temporalio.api.workflow.v1 +import temporalio.api.workflowservice.v1 +import temporalio.common +import temporalio.converter +import temporalio.converter._search_attributes +import temporalio.exceptions +import temporalio.workflow +from temporalio.converter import ( + WorkflowSerializationContext, +) +from temporalio.service import ( + RPCError, + RPCStatusCode, +) + +from ..types import ( + AnyType, + LocalReturnType, + MethodAsyncNoParam, + MethodAsyncSingleParam, + MethodSyncOrAsyncNoParam, + MethodSyncOrAsyncSingleParam, + MultiParamSpec, + ParamType, + ReturnType, + SelfType, +) +from ._exceptions import ( + WorkflowContinuedAsNewError, + WorkflowFailureError, + WorkflowUpdateFailedError, + WorkflowUpdateRPCTimeoutOrCancelledError, +) +from ._helpers import _decode_user_metadata, _history_from_json +from ._interceptor import ( + CancelWorkflowInput, + DescribeWorkflowInput, + FetchWorkflowHistoryEventsInput, + QueryWorkflowInput, + SignalWorkflowInput, + StartWorkflowUpdateInput, + TerminateWorkflowInput, + UpdateWithStartStartWorkflowInput, +) + +if TYPE_CHECKING: + from ._client import Client + from ._interceptor import ListWorkflowsInput + + +class WorkflowHistoryEventFilterType(IntEnum): + """Type of history events to get for a workflow. + + See :py:class:`temporalio.api.enums.v1.HistoryEventFilterType`. + """ + + ALL_EVENT = int( + temporalio.api.enums.v1.HistoryEventFilterType.HISTORY_EVENT_FILTER_TYPE_ALL_EVENT + ) + CLOSE_EVENT = int( + temporalio.api.enums.v1.HistoryEventFilterType.HISTORY_EVENT_FILTER_TYPE_CLOSE_EVENT + ) + + +class WorkflowHandle(Generic[SelfType, ReturnType]): + """Handle for interacting with a workflow. + + This is usually created via :py:meth:`Client.get_workflow_handle` or + returned from :py:meth:`Client.start_workflow`. + """ + + def __init__( + self, + client: Client, + id: str, + *, + run_id: str | None = None, + result_run_id: str | None = None, + first_execution_run_id: str | None = None, + result_type: type | None = None, + start_workflow_response: None + | ( + temporalio.api.workflowservice.v1.StartWorkflowExecutionResponse + | temporalio.api.workflowservice.v1.SignalWithStartWorkflowExecutionResponse + ) = None, + ) -> None: + """Create workflow handle.""" + self._client = client + self._id = id + self._run_id = run_id + self._result_run_id = result_run_id + self._first_execution_run_id = first_execution_run_id + self._result_type = result_type + self._start_workflow_response = start_workflow_response + self.__temporal_eagerly_started = False + + @functools.cached_property + def _data_converter(self) -> temporalio.converter.DataConverter: + return self._client.data_converter.with_context( + temporalio.converter.WorkflowSerializationContext( + namespace=self._client.namespace, workflow_id=self._id + ) + ) + + @property + def id(self) -> str: + """ID of the workflow.""" + return self._id + + @property + def run_id(self) -> str | None: + """If present, run ID used to ensure that requested operations apply + to this exact run. + + This is only created via :py:meth:`Client.get_workflow_handle`. + :py:meth:`Client.start_workflow` will not set this value. + + This cannot be mutated. If a different run ID is needed, + :py:meth:`Client.get_workflow_handle` must be used instead. + """ + return self._run_id + + @property + def result_run_id(self) -> str | None: + """Run ID used for :py:meth:`result` calls if present to ensure result + is for a workflow starting from this run. + + When this handle is created via :py:meth:`Client.get_workflow_handle`, + this is the same as run_id. When this handle is created via + :py:meth:`Client.start_workflow`, this value will be the resulting run + ID. + + This cannot be mutated. If a different run ID is needed, + :py:meth:`Client.get_workflow_handle` must be used instead. + """ + return self._result_run_id + + @property + def first_execution_run_id(self) -> str | None: + """Run ID used to ensure requested operations apply to a workflow ID + started with this run ID. + + This can be set when using :py:meth:`Client.get_workflow_handle`. When + :py:meth:`Client.start_workflow` is called without a start signal, this + is set to the resulting run. + + This cannot be mutated. If a different first execution run ID is needed, + :py:meth:`Client.get_workflow_handle` must be used instead. + """ + return self._first_execution_run_id + + async def result( + self, + *, + follow_runs: bool = True, + rpc_metadata: Mapping[str, str | bytes] = {}, + rpc_timeout: timedelta | None = None, + ) -> ReturnType: + """Wait for result of the workflow. + + This will use :py:attr:`result_run_id` if present to base the result on. + To use another run ID, a new handle must be created via + :py:meth:`Client.get_workflow_handle`. + + Args: + follow_runs: If true (default), workflow runs will be continually + fetched, until the most recent one is found. If false, return + the result from the first run targeted by the request if that run + ends in a result, otherwise raise an exception. + rpc_metadata: Headers used on the RPC call. Keys here override + client-level RPC metadata keys. + rpc_timeout: Optional RPC deadline to set for each RPC call. Note, + this is the timeout for each history RPC call not this overall + function. + + Returns: + Result of the workflow after being converted by the data converter. + + Raises: + WorkflowFailureError: Workflow failed, was cancelled, was + terminated, or timed out. Use the + :py:attr:`WorkflowFailureError.cause` to see the underlying + reason. + Exception: Other possible failures during result fetching. + """ + # We have to maintain our own run ID because it can change if we follow + # executions + hist_run_id = self._result_run_id + while True: + async for event in self._fetch_history_events_for_run( + hist_run_id, + wait_new_event=True, + event_filter_type=WorkflowHistoryEventFilterType.CLOSE_EVENT, + skip_archival=True, + rpc_metadata=rpc_metadata, + rpc_timeout=rpc_timeout, + ): + if event.HasField("workflow_execution_completed_event_attributes"): + complete_attr = event.workflow_execution_completed_event_attributes + # Follow execution + if follow_runs and complete_attr.new_execution_run_id: + hist_run_id = complete_attr.new_execution_run_id + break + # Ignoring anything after the first response like TypeScript + type_hints = [self._result_type] if self._result_type else None + results = await self._data_converter.decode_wrapper( + complete_attr.result, + type_hints, + ) + if not results: + return cast(ReturnType, None) + elif len(results) > 1: + warnings.warn(f"Expected single result, got {len(results)}") + return cast(ReturnType, results[0]) + elif event.HasField("workflow_execution_failed_event_attributes"): + fail_attr = event.workflow_execution_failed_event_attributes + # Follow execution + if follow_runs and fail_attr.new_execution_run_id: + hist_run_id = fail_attr.new_execution_run_id + break + raise WorkflowFailureError( + cause=await self._data_converter.decode_failure( + fail_attr.failure + ), + ) + elif event.HasField("workflow_execution_canceled_event_attributes"): + cancel_attr = event.workflow_execution_canceled_event_attributes + raise WorkflowFailureError( + cause=temporalio.exceptions.CancelledError( + "Workflow cancelled", + *( + await self._data_converter.decode_wrapper( + cancel_attr.details + ) + ), + ) + ) + elif event.HasField("workflow_execution_terminated_event_attributes"): + term_attr = event.workflow_execution_terminated_event_attributes + raise WorkflowFailureError( + cause=temporalio.exceptions.TerminatedError( + term_attr.reason or "Workflow terminated", + *( + await self._data_converter.decode_wrapper( + term_attr.details + ) + ), + ), + ) + elif event.HasField("workflow_execution_timed_out_event_attributes"): + time_attr = event.workflow_execution_timed_out_event_attributes + # Follow execution + if follow_runs and time_attr.new_execution_run_id: + hist_run_id = time_attr.new_execution_run_id + break + raise WorkflowFailureError( + cause=temporalio.exceptions.TimeoutError( + "Workflow timed out", + type=temporalio.exceptions.TimeoutType.START_TO_CLOSE, + last_heartbeat_details=[], + ), + ) + elif event.HasField( + "workflow_execution_continued_as_new_event_attributes" + ): + cont_attr = ( + event.workflow_execution_continued_as_new_event_attributes + ) + if not cont_attr.new_execution_run_id: + raise RuntimeError( + "Unexpectedly missing new run ID from continue as new" + ) + # Follow execution + if follow_runs: + hist_run_id = cont_attr.new_execution_run_id + break + raise WorkflowContinuedAsNewError(cont_attr.new_execution_run_id) + # This is reached on break which means that there's a different run + # ID if we're following. If there's not, it's an error because no + # event was given (should never happen). + if hist_run_id is None: + raise RuntimeError("No completion event found") + + async def cancel( + self, + *, + rpc_metadata: Mapping[str, str | bytes] = {}, + rpc_timeout: timedelta | None = None, + ) -> None: + """Cancel the workflow. + + This will issue a cancellation for :py:attr:`run_id` if present. This + call will make sure to use the run chain starting from + :py:attr:`first_execution_run_id` if present. To create handles with + these values, use :py:meth:`Client.get_workflow_handle`. + + .. warning:: + Handles created as a result of :py:meth:`Client.start_workflow` with + a start signal will cancel the latest workflow with the same + workflow ID even if it is unrelated to the started workflow. + + Args: + rpc_metadata: Headers used on the RPC call. Keys here override + client-level RPC metadata keys. + rpc_timeout: Optional RPC deadline to set for the RPC call. + + Raises: + RPCError: Workflow could not be cancelled. + """ + await self._client._impl.cancel_workflow( + CancelWorkflowInput( + id=self._id, + run_id=self._run_id, + first_execution_run_id=self._first_execution_run_id, + rpc_metadata=rpc_metadata, + rpc_timeout=rpc_timeout, + ) + ) + + async def describe( + self, + *, + rpc_metadata: Mapping[str, str | bytes] = {}, + rpc_timeout: timedelta | None = None, + ) -> WorkflowExecutionDescription: + """Get workflow details. + + This will get details for :py:attr:`run_id` if present. To use a + different run ID, create a new handle with via + :py:meth:`Client.get_workflow_handle`. + + .. warning:: + Handles created as a result of :py:meth:`Client.start_workflow` will + describe the latest workflow with the same workflow ID even if it is + unrelated to the started workflow. + + Args: + rpc_metadata: Headers used on the RPC call. Keys here override + client-level RPC metadata keys. + rpc_timeout: Optional RPC deadline to set for the RPC call. + + Returns: + Workflow details. + + Raises: + RPCError: Workflow details could not be fetched. + """ + return await self._client._impl.describe_workflow( + DescribeWorkflowInput( + id=self._id, + run_id=self._run_id, + rpc_metadata=rpc_metadata, + rpc_timeout=rpc_timeout, + ) + ) + + async def fetch_history( + self, + *, + event_filter_type: WorkflowHistoryEventFilterType = WorkflowHistoryEventFilterType.ALL_EVENT, + skip_archival: bool = False, + rpc_metadata: Mapping[str, str | bytes] = {}, + rpc_timeout: timedelta | None = None, + ) -> WorkflowHistory: + """Get workflow history. + + This is a shortcut for :py:meth:`fetch_history_events` that just fetches + all events. + """ + return WorkflowHistory( + workflow_id=self.id, + events=[ + v + async for v in self.fetch_history_events( + event_filter_type=event_filter_type, + skip_archival=skip_archival, + rpc_metadata=rpc_metadata, + rpc_timeout=rpc_timeout, + ) + ], + ) + + def fetch_history_events( + self, + *, + page_size: int | None = None, + next_page_token: bytes | None = None, + wait_new_event: bool = False, + event_filter_type: WorkflowHistoryEventFilterType = WorkflowHistoryEventFilterType.ALL_EVENT, + skip_archival: bool = False, + rpc_metadata: Mapping[str, str | bytes] = {}, + rpc_timeout: timedelta | None = None, + ) -> WorkflowHistoryEventAsyncIterator: + """Get workflow history events as an async iterator. + + This does not make a request until the first iteration is attempted. + Therefore any errors will not occur until then. + + Args: + page_size: Maximum amount to fetch per request if any maximum. + next_page_token: A specific page token to fetch. + wait_new_event: Whether the event fetching request will wait for new + events or just return right away. + event_filter_type: Which events to obtain. + skip_archival: Whether to skip archival. + rpc_metadata: Headers used on each RPC call. Keys here override + client-level RPC metadata keys. + rpc_timeout: Optional RPC deadline to set for each RPC call. + + Returns: + An async iterator that doesn't begin fetching until iterated on. + """ + return self._fetch_history_events_for_run( + self._run_id, + page_size=page_size, + next_page_token=next_page_token, + wait_new_event=wait_new_event, + event_filter_type=event_filter_type, + skip_archival=skip_archival, + rpc_metadata=rpc_metadata, + rpc_timeout=rpc_timeout, + ) + + def _fetch_history_events_for_run( + self, + run_id: str | None, + *, + page_size: int | None = None, + next_page_token: bytes | None = None, + wait_new_event: bool = False, + event_filter_type: WorkflowHistoryEventFilterType = WorkflowHistoryEventFilterType.ALL_EVENT, + skip_archival: bool = False, + rpc_metadata: Mapping[str, str | bytes] = {}, + rpc_timeout: timedelta | None = None, + ) -> WorkflowHistoryEventAsyncIterator: + return self._client._impl.fetch_workflow_history_events( + FetchWorkflowHistoryEventsInput( + id=self._id, + run_id=run_id, + page_size=page_size, + next_page_token=next_page_token, + wait_new_event=wait_new_event, + event_filter_type=event_filter_type, + skip_archival=skip_archival, + rpc_metadata=rpc_metadata, + rpc_timeout=rpc_timeout, + ) + ) + + # Overload for no-param query + @overload + async def query( + self, + query: MethodSyncOrAsyncNoParam[SelfType, LocalReturnType], + *, + reject_condition: temporalio.common.QueryRejectCondition | None = None, + rpc_metadata: Mapping[str, str | bytes] = {}, + rpc_timeout: timedelta | None = None, + ) -> LocalReturnType: ... + + # Overload for single-param query + @overload + async def query( + self, + query: MethodSyncOrAsyncSingleParam[SelfType, ParamType, LocalReturnType], + arg: ParamType, + *, + reject_condition: temporalio.common.QueryRejectCondition | None = None, + rpc_metadata: Mapping[str, str | bytes] = {}, + rpc_timeout: timedelta | None = None, + ) -> LocalReturnType: ... + + # Overload for multi-param query + @overload + async def query( + self, + query: Callable[ + Concatenate[SelfType, MultiParamSpec], + Awaitable[LocalReturnType] | LocalReturnType, + ], + *, + args: Sequence[Any], + reject_condition: temporalio.common.QueryRejectCondition | None = None, + rpc_metadata: Mapping[str, str | bytes] = {}, + rpc_timeout: timedelta | None = None, + ) -> LocalReturnType: ... + + # Overload for string-name query + @overload + async def query( + self, + query: str, + arg: Any = temporalio.common._arg_unset, + *, + args: Sequence[Any] = [], + result_type: type | None = None, + reject_condition: temporalio.common.QueryRejectCondition | None = None, + rpc_metadata: Mapping[str, str | bytes] = {}, + rpc_timeout: timedelta | None = None, + ) -> Any: ... + + async def query( + self, + query: str | Callable, + arg: Any = temporalio.common._arg_unset, + *, + args: Sequence[Any] = [], + result_type: type | None = None, + reject_condition: temporalio.common.QueryRejectCondition | None = None, + rpc_metadata: Mapping[str, str | bytes] = {}, + rpc_timeout: timedelta | None = None, + ) -> Any: + """Query the workflow. + + This will query for :py:attr:`run_id` if present. To use a different + run ID, create a new handle with + :py:meth:`Client.get_workflow_handle`. + + .. warning:: + Handles created as a result of :py:meth:`Client.start_workflow` will + query the latest workflow with the same workflow ID even if it is + unrelated to the started workflow. + + Args: + query: Query function or name on the workflow. + arg: Single argument to the query. + args: Multiple arguments to the query. Cannot be set if arg is. + result_type: For string queries, this can set the specific result + type hint to deserialize into. + reject_condition: Condition for rejecting the query. If unset/None, + defaults to the client's default (which is defaulted to None). + rpc_metadata: Headers used on the RPC call. Keys here override + client-level RPC metadata keys. + rpc_timeout: Optional RPC deadline to set for the RPC call. + + Returns: + Result of the query. + + Raises: + WorkflowQueryRejectedError: A query reject condition was satisfied. + RPCError: Workflow details could not be fetched. + """ + query_name: str + ret_type = result_type + if callable(query): + defn = temporalio.workflow._QueryDefinition.from_fn(query) + if not defn: + raise RuntimeError( + f"Query definition not found on {query.__qualname__}, " + "is it decorated with @workflow.query?" + ) + elif not defn.name: + raise RuntimeError("Cannot invoke dynamic query definition") + # TODO(cretz): Check count/type of args at runtime? + query_name = defn.name + ret_type = defn.ret_type + else: + query_name = str(query) + + return await self._client._impl.query_workflow( + QueryWorkflowInput( + id=self._id, + run_id=self._run_id, + query=query_name, + args=temporalio.common._arg_or_args(arg, args), + reject_condition=reject_condition + or self._client._config["default_workflow_query_reject_condition"], + headers={}, + ret_type=ret_type, + rpc_metadata=rpc_metadata, + rpc_timeout=rpc_timeout, + ) + ) + + # Overload for no-param signal + @overload + async def signal( + self, + signal: MethodSyncOrAsyncNoParam[SelfType, None], + *, + rpc_metadata: Mapping[str, str | bytes] = {}, + rpc_timeout: timedelta | None = None, + ) -> None: ... + + # Overload for single-param signal + @overload + async def signal( + self, + signal: MethodSyncOrAsyncSingleParam[SelfType, ParamType, None], + arg: ParamType, + *, + rpc_metadata: Mapping[str, str | bytes] = {}, + rpc_timeout: timedelta | None = None, + ) -> None: ... + + # Overload for multi-param signal + @overload + async def signal( + self, + signal: Callable[Concatenate[SelfType, MultiParamSpec], Awaitable[None] | None], + *, + args: Sequence[Any], + rpc_metadata: Mapping[str, str | bytes] = {}, + rpc_timeout: timedelta | None = None, + ) -> None: ... + + # Overload for string-name signal + @overload + async def signal( + self, + signal: str, + arg: Any = temporalio.common._arg_unset, + *, + args: Sequence[Any] = [], + rpc_metadata: Mapping[str, str | bytes] = {}, + rpc_timeout: timedelta | None = None, + ) -> None: ... + + async def signal( + self, + signal: str | Callable, + arg: Any = temporalio.common._arg_unset, + *, + args: Sequence[Any] = [], + rpc_metadata: Mapping[str, str | bytes] = {}, + rpc_timeout: timedelta | None = None, + ) -> None: + """Send a signal to the workflow. + + This will signal for :py:attr:`run_id` if present. To use a different + run ID, create a new handle with via + :py:meth:`Client.get_workflow_handle`. + + .. warning:: + Handles created as a result of :py:meth:`Client.start_workflow` will + signal the latest workflow with the same workflow ID even if it is + unrelated to the started workflow. + + Args: + signal: Signal function or name on the workflow. + arg: Single argument to the signal. + args: Multiple arguments to the signal. Cannot be set if arg is. + rpc_metadata: Headers used on the RPC call. Keys here override + client-level RPC metadata keys. + rpc_timeout: Optional RPC deadline to set for the RPC call. + + Raises: + RPCError: Workflow could not be signalled. + """ + await self._client._impl.signal_workflow( + SignalWorkflowInput( + id=self._id, + run_id=self._run_id, + signal=temporalio.workflow._SignalDefinition.must_name_from_fn_or_str( + signal + ), + args=temporalio.common._arg_or_args(arg, args), + headers={}, + rpc_metadata=rpc_metadata, + rpc_timeout=rpc_timeout, + ) + ) + + async def terminate( + self, + *args: Any, + reason: str | None = None, + rpc_metadata: Mapping[str, str | bytes] = {}, + rpc_timeout: timedelta | None = None, + ) -> None: + """Terminate the workflow. + + This will issue a termination for :py:attr:`run_id` if present. This + call will make sure to use the run chain starting from + :py:attr:`first_execution_run_id` if present. To create handles with + these values, use :py:meth:`Client.get_workflow_handle`. + + .. warning:: + Handles created as a result of :py:meth:`Client.start_workflow` with + a start signal will terminate the latest workflow with the same + workflow ID even if it is unrelated to the started workflow. + + Args: + args: Details to store on the termination. + reason: Reason for the termination. + rpc_metadata: Headers used on the RPC call. Keys here override + client-level RPC metadata keys. + rpc_timeout: Optional RPC deadline to set for the RPC call. + + Raises: + RPCError: Workflow could not be terminated. + """ + await self._client._impl.terminate_workflow( + TerminateWorkflowInput( + id=self._id, + run_id=self._run_id, + args=args, + reason=reason, + first_execution_run_id=self._first_execution_run_id, + rpc_metadata=rpc_metadata, + rpc_timeout=rpc_timeout, + ) + ) + + # Overload for no-param update + @overload + async def execute_update( + self, + update: temporalio.workflow.UpdateMethodMultiParam[[SelfType], LocalReturnType], + *, + id: str | None = None, + rpc_metadata: Mapping[str, str | bytes] = {}, + rpc_timeout: timedelta | None = None, + ) -> LocalReturnType: ... + + # Overload for single-param update + @overload + async def execute_update( + self, + update: temporalio.workflow.UpdateMethodMultiParam[ + [SelfType, ParamType], LocalReturnType + ], + arg: ParamType, + *, + id: str | None = None, + rpc_metadata: Mapping[str, str | bytes] = {}, + rpc_timeout: timedelta | None = None, + ) -> LocalReturnType: ... + + # Overload for multi-param update + @overload + async def execute_update( + self, + update: temporalio.workflow.UpdateMethodMultiParam[ + MultiParamSpec, LocalReturnType + ], + *, + args: MultiParamSpec.args, # type: ignore + id: str | None = None, + rpc_metadata: Mapping[str, str | bytes] = {}, + rpc_timeout: timedelta | None = None, + ) -> LocalReturnType: ... + + # Overload for string-name update + @overload + async def execute_update( + self, + update: str, + arg: Any = temporalio.common._arg_unset, + *, + args: Sequence[Any] = [], + id: str | None = None, + result_type: type | None = None, + rpc_metadata: Mapping[str, str | bytes] = {}, + rpc_timeout: timedelta | None = None, + ) -> Any: ... + + async def execute_update( + self, + update: str | Callable, + arg: Any = temporalio.common._arg_unset, + *, + args: Sequence[Any] = [], + id: str | None = None, + result_type: type | None = None, + rpc_metadata: Mapping[str, str | bytes] = {}, + rpc_timeout: timedelta | None = None, + ) -> Any: + """Send an update request to the workflow and wait for it to complete. + + This will target the workflow with :py:attr:`run_id` if present. To use a + different run ID, create a new handle with via :py:meth:`Client.get_workflow_handle`. + + Args: + update: Update function or name on the workflow. + arg: Single argument to the update. + args: Multiple arguments to the update. Cannot be set if arg is. + id: ID of the update. If not set, the default is a new UUID. + result_type: For string updates, this can set the specific result + type hint to deserialize into. + rpc_metadata: Headers used on the RPC call. Keys here override + client-level RPC metadata keys. + rpc_timeout: Optional RPC deadline to set for the RPC call. + + Raises: + WorkflowUpdateFailedError: If the update failed. + WorkflowUpdateRPCTimeoutOrCancelledError: This update call timed out + or was cancelled. This doesn't mean the update itself was timed + out or cancelled. + RPCError: There was some issue sending the update to the workflow. + """ + handle = await self._start_update( + update, + arg, + args=args, + wait_for_stage=WorkflowUpdateStage.COMPLETED, + id=id, + result_type=result_type, + rpc_metadata=rpc_metadata, + rpc_timeout=rpc_timeout, + ) + return await handle.result() + + # Overload for no-param start update + @overload + async def start_update( + self, + update: temporalio.workflow.UpdateMethodMultiParam[[SelfType], LocalReturnType], + *, + wait_for_stage: WorkflowUpdateStage, + id: str | None = None, + rpc_metadata: Mapping[str, str | bytes] = {}, + rpc_timeout: timedelta | None = None, + ) -> WorkflowUpdateHandle[LocalReturnType]: ... + + # Overload for single-param start update + @overload + async def start_update( + self, + update: temporalio.workflow.UpdateMethodMultiParam[ + [SelfType, ParamType], LocalReturnType + ], + arg: ParamType, + *, + wait_for_stage: WorkflowUpdateStage, + id: str | None = None, + rpc_metadata: Mapping[str, str | bytes] = {}, + rpc_timeout: timedelta | None = None, + ) -> WorkflowUpdateHandle[LocalReturnType]: ... + + # Overload for multi-param start update + @overload + async def start_update( + self, + update: temporalio.workflow.UpdateMethodMultiParam[ + MultiParamSpec, LocalReturnType + ], + *, + args: MultiParamSpec.args, # type: ignore + wait_for_stage: WorkflowUpdateStage, + id: str | None = None, + rpc_metadata: Mapping[str, str | bytes] = {}, + rpc_timeout: timedelta | None = None, + ) -> WorkflowUpdateHandle[LocalReturnType]: ... + + # Overload for string-name start update + @overload + async def start_update( + self, + update: str, + arg: Any = temporalio.common._arg_unset, + *, + wait_for_stage: WorkflowUpdateStage, + args: Sequence[Any] = [], + id: str | None = None, + result_type: type | None = None, + rpc_metadata: Mapping[str, str | bytes] = {}, + rpc_timeout: timedelta | None = None, + ) -> WorkflowUpdateHandle[Any]: ... + + async def start_update( + self, + update: str | Callable, + arg: Any = temporalio.common._arg_unset, + *, + wait_for_stage: WorkflowUpdateStage, + args: Sequence[Any] = [], + id: str | None = None, + result_type: type | None = None, + rpc_metadata: Mapping[str, str | bytes] = {}, + rpc_timeout: timedelta | None = None, + ) -> WorkflowUpdateHandle[Any]: + """Send an update request to the workflow and return a handle to it. + + This will target the workflow with :py:attr:`run_id` if present. To use a + different run ID, create a new handle with via :py:meth:`Client.get_workflow_handle`. + + Args: + update: Update function or name on the workflow. arg: Single argument to the + update. + wait_for_stage: Required stage to wait until returning: either ACCEPTED or + COMPLETED. ADMITTED is not currently supported. See + https://docs.temporal.io/workflows#update for more details. + args: Multiple arguments to the update. Cannot be set if arg is. + id: ID of the update. If not set, the default is a new UUID. + result_type: For string updates, this can set the specific result + type hint to deserialize into. + rpc_metadata: Headers used on the RPC call. Keys here override + client-level RPC metadata keys. + rpc_timeout: Optional RPC deadline to set for the RPC call. + + Raises: + WorkflowUpdateRPCTimeoutOrCancelledError: This update call timed out + or was cancelled. This doesn't mean the update itself was timed out or + cancelled. + RPCError: There was some issue sending the update to the workflow. + """ + return await self._start_update( + update, + arg, + wait_for_stage=wait_for_stage, + args=args, + id=id, + result_type=result_type, + rpc_metadata=rpc_metadata, + rpc_timeout=rpc_timeout, + ) + + async def _start_update( + self, + update: str | Callable, + arg: Any = temporalio.common._arg_unset, + *, + wait_for_stage: WorkflowUpdateStage, + args: Sequence[Any] = [], + id: str | None = None, + result_type: type | None = None, + rpc_metadata: Mapping[str, str | bytes] = {}, + rpc_timeout: timedelta | None = None, + ) -> WorkflowUpdateHandle[Any]: + if wait_for_stage == WorkflowUpdateStage.ADMITTED: + raise ValueError("ADMITTED wait stage not supported") + + update_name, result_type_from_type_hint = ( + temporalio.workflow._UpdateDefinition.get_name_and_result_type(update) + ) + + return await self._client._impl.start_workflow_update( + StartWorkflowUpdateInput( + id=self._id, + run_id=self._run_id, + first_execution_run_id=self.first_execution_run_id, + update_id=id, + update=update_name, + args=temporalio.common._arg_or_args(arg, args), + headers={}, + ret_type=result_type or result_type_from_type_hint, + rpc_metadata=rpc_metadata, + rpc_timeout=rpc_timeout, + wait_for_stage=wait_for_stage, + ) + ) + + def get_update_handle( + self, + id: str, + *, + workflow_run_id: str | None = None, + result_type: type | None = None, + ) -> WorkflowUpdateHandle[Any]: + """Get a handle for an update. The handle can be used to wait on the + update result. + + Users may prefer the more typesafe :py:meth:`get_update_handle_for` + which accepts an update definition. + + Args: + id: Update ID to get a handle to. + workflow_run_id: Run ID to tie the handle to. If this is not set, + the :py:attr:`run_id` will be used. + result_type: The result type to deserialize into if known. + + Returns: + The update handle. + """ + return WorkflowUpdateHandle( + self._client, + id, + self._id, + workflow_run_id=workflow_run_id or self._run_id, + result_type=result_type, + ) + + def get_update_handle_for( + self, + update: temporalio.workflow.UpdateMethodMultiParam[Any, LocalReturnType], + id: str, + *, + workflow_run_id: str | None = None, + ) -> WorkflowUpdateHandle[LocalReturnType]: + """Get a typed handle for an update. The handle can be used to wait on + the update result. + + This is the same as :py:meth:`get_update_handle` but typed. + + Args: + update: The update method to use for typing the handle. + id: Update ID to get a handle to. + workflow_run_id: Run ID to tie the handle to. If this is not set, + the :py:attr:`run_id` will be used. + + Returns: + The update handle. + """ + return self.get_update_handle( + id, workflow_run_id=workflow_run_id, result_type=update._defn.ret_type + ) + + +class WithStartWorkflowOperation(Generic[SelfType, ReturnType]): + """Defines a start-workflow operation used by update-with-start requests. + + Update-With-Start allows you to send an update to a workflow, while starting the + workflow if necessary. + """ + + # Overload for no-param workflow, with_start + @overload + def __init__( + self, + workflow: MethodAsyncNoParam[SelfType, ReturnType], + *, + id: str, + task_queue: str, + id_conflict_policy: temporalio.common.WorkflowIDConflictPolicy, + execution_timeout: timedelta | None = None, + run_timeout: timedelta | None = None, + task_timeout: timedelta | None = None, + id_reuse_policy: temporalio.common.WorkflowIDReusePolicy = temporalio.common.WorkflowIDReusePolicy.ALLOW_DUPLICATE, + retry_policy: temporalio.common.RetryPolicy | None = None, + cron_schedule: str = "", + memo: Mapping[str, Any] | None = None, + search_attributes: None + | ( + temporalio.common.TypedSearchAttributes | temporalio.common.SearchAttributes + ) = None, + static_summary: str | None = None, + static_details: str | None = None, + start_delay: timedelta | None = None, + rpc_metadata: Mapping[str, str | bytes] = {}, + rpc_timeout: timedelta | None = None, + priority: temporalio.common.Priority = temporalio.common.Priority.default, + versioning_override: temporalio.common.VersioningOverride | None = None, + ) -> None: ... + + # Overload for single-param workflow, with_start + @overload + def __init__( + self, + workflow: MethodAsyncSingleParam[SelfType, ParamType, ReturnType], + arg: ParamType, + *, + id: str, + task_queue: str, + id_conflict_policy: temporalio.common.WorkflowIDConflictPolicy, + execution_timeout: timedelta | None = None, + run_timeout: timedelta | None = None, + task_timeout: timedelta | None = None, + id_reuse_policy: temporalio.common.WorkflowIDReusePolicy = temporalio.common.WorkflowIDReusePolicy.ALLOW_DUPLICATE, + retry_policy: temporalio.common.RetryPolicy | None = None, + cron_schedule: str = "", + memo: Mapping[str, Any] | None = None, + search_attributes: None + | ( + temporalio.common.TypedSearchAttributes | temporalio.common.SearchAttributes + ) = None, + static_summary: str | None = None, + static_details: str | None = None, + start_delay: timedelta | None = None, + rpc_metadata: Mapping[str, str | bytes] = {}, + rpc_timeout: timedelta | None = None, + priority: temporalio.common.Priority = temporalio.common.Priority.default, + versioning_override: temporalio.common.VersioningOverride | None = None, + ) -> None: ... + + # Overload for multi-param workflow, with_start + @overload + def __init__( + self, + workflow: Callable[ + Concatenate[SelfType, MultiParamSpec], Awaitable[ReturnType] + ], + *, + args: Sequence[Any], + id: str, + task_queue: str, + id_conflict_policy: temporalio.common.WorkflowIDConflictPolicy, + execution_timeout: timedelta | None = None, + run_timeout: timedelta | None = None, + task_timeout: timedelta | None = None, + id_reuse_policy: temporalio.common.WorkflowIDReusePolicy = temporalio.common.WorkflowIDReusePolicy.ALLOW_DUPLICATE, + retry_policy: temporalio.common.RetryPolicy | None = None, + cron_schedule: str = "", + memo: Mapping[str, Any] | None = None, + search_attributes: None + | ( + temporalio.common.TypedSearchAttributes | temporalio.common.SearchAttributes + ) = None, + static_summary: str | None = None, + static_details: str | None = None, + start_delay: timedelta | None = None, + rpc_metadata: Mapping[str, str | bytes] = {}, + rpc_timeout: timedelta | None = None, + priority: temporalio.common.Priority = temporalio.common.Priority.default, + versioning_override: temporalio.common.VersioningOverride | None = None, + ) -> None: ... + + # Overload for string-name workflow, with_start + @overload + def __init__( + self, + workflow: str, + arg: Any = temporalio.common._arg_unset, + *, + args: Sequence[Any] = [], + id: str, + task_queue: str, + id_conflict_policy: temporalio.common.WorkflowIDConflictPolicy, + result_type: type | None = None, + execution_timeout: timedelta | None = None, + run_timeout: timedelta | None = None, + task_timeout: timedelta | None = None, + id_reuse_policy: temporalio.common.WorkflowIDReusePolicy = temporalio.common.WorkflowIDReusePolicy.ALLOW_DUPLICATE, + retry_policy: temporalio.common.RetryPolicy | None = None, + cron_schedule: str = "", + memo: Mapping[str, Any] | None = None, + search_attributes: None + | ( + temporalio.common.TypedSearchAttributes | temporalio.common.SearchAttributes + ) = None, + static_summary: str | None = None, + static_details: str | None = None, + start_delay: timedelta | None = None, + rpc_metadata: Mapping[str, str | bytes] = {}, + rpc_timeout: timedelta | None = None, + priority: temporalio.common.Priority = temporalio.common.Priority.default, + versioning_override: temporalio.common.VersioningOverride | None = None, + ) -> None: ... + + def __init__( + self, + workflow: str | Callable[..., Awaitable[Any]], + arg: Any = temporalio.common._arg_unset, + *, + args: Sequence[Any] = [], + id: str, + task_queue: str, + id_conflict_policy: temporalio.common.WorkflowIDConflictPolicy, + result_type: type | None = None, + execution_timeout: timedelta | None = None, + run_timeout: timedelta | None = None, + task_timeout: timedelta | None = None, + id_reuse_policy: temporalio.common.WorkflowIDReusePolicy = temporalio.common.WorkflowIDReusePolicy.ALLOW_DUPLICATE, + retry_policy: temporalio.common.RetryPolicy | None = None, + cron_schedule: str = "", + memo: Mapping[str, Any] | None = None, + search_attributes: None + | ( + temporalio.common.TypedSearchAttributes | temporalio.common.SearchAttributes + ) = None, + static_summary: str | None = None, + static_details: str | None = None, + start_delay: timedelta | None = None, + rpc_metadata: Mapping[str, str | bytes] = {}, + rpc_timeout: timedelta | None = None, + priority: temporalio.common.Priority = temporalio.common.Priority.default, + versioning_override: temporalio.common.VersioningOverride | None = None, + stack_level: int = 2, + ) -> None: + """Create a WithStartWorkflowOperation. + + See :py:meth:`temporalio.client.Client.start_workflow` for documentation of the + arguments. + """ + temporalio.common._warn_on_deprecated_search_attributes( + search_attributes, stack_level=stack_level + ) + name, result_type_from_run_fn = ( + temporalio.workflow._Definition.get_name_and_result_type(workflow) + ) + if id_conflict_policy == temporalio.common.WorkflowIDConflictPolicy.UNSPECIFIED: + raise ValueError("WorkflowIDConflictPolicy is required") + + self._start_workflow_input = UpdateWithStartStartWorkflowInput( + workflow=name, + args=temporalio.common._arg_or_args(arg, args), + id=id, + task_queue=task_queue, + execution_timeout=execution_timeout, + run_timeout=run_timeout, + task_timeout=task_timeout, + id_reuse_policy=id_reuse_policy, + id_conflict_policy=id_conflict_policy, + retry_policy=retry_policy, + cron_schedule=cron_schedule, + memo=memo, + search_attributes=search_attributes, + static_summary=static_summary, + static_details=static_details, + start_delay=start_delay, + headers={}, + ret_type=result_type or result_type_from_run_fn, + rpc_metadata=rpc_metadata, + rpc_timeout=rpc_timeout, + priority=priority, + versioning_override=versioning_override, + ) + self._workflow_handle: Future[WorkflowHandle[SelfType, ReturnType]] = Future() + self._used = False + + async def workflow_handle(self) -> WorkflowHandle[SelfType, ReturnType]: + """Wait until workflow is running and return a WorkflowHandle.""" + return await self._workflow_handle + + +@dataclass +class WorkflowExecution: + """Info for a single workflow execution run.""" + + close_time: datetime | None + """When the workflow was closed if closed.""" + + execution_time: datetime | None + """When this workflow run started or should start.""" + + history_length: int + """Number of events in the history.""" + + id: str + """ID for the workflow.""" + + namespace: str + """Namespace for the workflow.""" + + parent_id: str | None + """ID for the parent workflow if this was started as a child.""" + + parent_run_id: str | None + """Run ID for the parent workflow if this was started as a child.""" + + root_id: str | None + """ID for the root workflow.""" + + root_run_id: str | None + """Run ID for the root workflow.""" + + raw_info: temporalio.api.workflow.v1.WorkflowExecutionInfo + """Underlying protobuf info.""" + + run_id: str + """Run ID for this workflow run.""" + + search_attributes: temporalio.common.SearchAttributes + """Current set of search attributes if any. + + .. deprecated:: + Use :py:attr:`typed_search_attributes` instead. + """ + + start_time: datetime + """When the workflow was created.""" + + status: WorkflowExecutionStatus | None + """Status for the workflow.""" + + task_queue: str + """Task queue for the workflow.""" + + typed_search_attributes: temporalio.common.TypedSearchAttributes + """Current set of search attributes if any.""" + + workflow_type: str + """Type name for the workflow.""" + + _context_free_data_converter: temporalio.converter.DataConverter + + @property + def data_converter(self) -> temporalio.converter.DataConverter: + """Data converter for the workflow.""" + return self._context_free_data_converter.with_context( + WorkflowSerializationContext( + namespace=self.namespace, + workflow_id=self.id, + ) + ) + + @classmethod + def _from_raw_info( + cls, + info: temporalio.api.workflow.v1.WorkflowExecutionInfo, + namespace: str, + converter: temporalio.converter.DataConverter, + **additional_fields: Any, + ) -> Self: + return cls( + close_time=( + info.close_time.ToDatetime().replace(tzinfo=timezone.utc) + if info.HasField("close_time") + else None + ), + execution_time=( + info.execution_time.ToDatetime().replace(tzinfo=timezone.utc) + if info.HasField("execution_time") + else None + ), + history_length=info.history_length, + id=info.execution.workflow_id, + namespace=namespace, + parent_id=( + info.parent_execution.workflow_id + if info.HasField("parent_execution") + else None + ), + parent_run_id=( + info.parent_execution.run_id + if info.HasField("parent_execution") + else None + ), + root_id=( + info.root_execution.workflow_id + if info.HasField("root_execution") + else None + ), + root_run_id=( + info.root_execution.run_id if info.HasField("root_execution") else None + ), + raw_info=info, + run_id=info.execution.run_id, + search_attributes=temporalio.converter.decode_search_attributes( + info.search_attributes + ), + start_time=info.start_time.ToDatetime().replace(tzinfo=timezone.utc), + status=WorkflowExecutionStatus(info.status) if info.status else None, + task_queue=info.task_queue, + typed_search_attributes=temporalio.converter.decode_typed_search_attributes( + info.search_attributes + ), + workflow_type=info.type.name, + _context_free_data_converter=converter, + **additional_fields, + ) + + async def memo(self) -> Mapping[str, Any]: + """Workflow's memo values, converted without type hints. + + Since type hints are not used, the default converted values will come + back. For example, if the memo was originally created with a dataclass, + the value will be a dict. To convert using proper type hints, use + :py:meth:`memo_value`. + + Returns: + Mapping of all memo keys and they values without type hints. + """ + return await self.data_converter._decode_memo(self.raw_info.memo) + + @overload + async def memo_value( + self, key: str, default: Any = temporalio.common._arg_unset + ) -> Any: ... + + @overload + async def memo_value( + self, key: str, *, type_hint: type[ParamType] + ) -> ParamType: ... + + @overload + async def memo_value( + self, key: str, default: AnyType, *, type_hint: type[ParamType] + ) -> AnyType | ParamType: ... + + async def memo_value( + self, + key: str, + default: Any = temporalio.common._arg_unset, + *, + type_hint: type | None = None, + ) -> Any: + """Memo value for the given key, optional default, and optional type + hint. + + Args: + key: Key to get memo value for. + default: Default to use if key is not present. If unset, a + :py:class:`KeyError` is raised when the key does not exist. + type_hint: type hint to use when converting. + + Returns: + Memo value, converted with the type hint if present. + + Raises: + KeyError: Key not present and default not set. + """ + return await self.data_converter._decode_memo_field( + self.raw_info.memo, key, default, type_hint + ) + + +@dataclass +class WorkflowExecutionDescription(WorkflowExecution): + """Description for a single workflow execution run.""" + + raw_description: temporalio.api.workflowservice.v1.DescribeWorkflowExecutionResponse + """Underlying protobuf description.""" + + _static_summary: str | None = None + _static_details: str | None = None + _metadata_decoded: bool = False + + async def static_summary(self) -> str | None: + """Gets the single-line fixed summary for this workflow execution that may appear in + UI/CLI. This can be in single-line Temporal markdown format. + """ + if not self._metadata_decoded: + await self._decode_metadata() + return self._static_summary + + async def static_details(self) -> str | None: + """Gets the general fixed details for this workflow execution that may appear in UI/CLI. + This can be in Temporal markdown format and can span multiple lines. + """ + if not self._metadata_decoded: + await self._decode_metadata() + return self._static_details + + async def _decode_metadata(self) -> None: + """Internal method to decode metadata lazily.""" + self._static_summary, self._static_details = await _decode_user_metadata( + self.data_converter, self.raw_description.execution_config.user_metadata + ) + self._metadata_decoded = True + + @staticmethod + async def _from_raw_description( + description: temporalio.api.workflowservice.v1.DescribeWorkflowExecutionResponse, + namespace: str, + converter: temporalio.converter.DataConverter, + ) -> WorkflowExecutionDescription: + return WorkflowExecutionDescription._from_raw_info( + description.workflow_execution_info, + namespace=namespace, + converter=converter, + raw_description=description, + ) + + +class WorkflowExecutionStatus(IntEnum): + """Status of a workflow execution. + + See :py:class:`temporalio.api.enums.v1.WorkflowExecutionStatus`. + """ + + RUNNING = int( + temporalio.api.enums.v1.WorkflowExecutionStatus.WORKFLOW_EXECUTION_STATUS_RUNNING + ) + COMPLETED = int( + temporalio.api.enums.v1.WorkflowExecutionStatus.WORKFLOW_EXECUTION_STATUS_COMPLETED + ) + FAILED = int( + temporalio.api.enums.v1.WorkflowExecutionStatus.WORKFLOW_EXECUTION_STATUS_FAILED + ) + CANCELED = int( + temporalio.api.enums.v1.WorkflowExecutionStatus.WORKFLOW_EXECUTION_STATUS_CANCELED + ) + TERMINATED = int( + temporalio.api.enums.v1.WorkflowExecutionStatus.WORKFLOW_EXECUTION_STATUS_TERMINATED + ) + CONTINUED_AS_NEW = int( + temporalio.api.enums.v1.WorkflowExecutionStatus.WORKFLOW_EXECUTION_STATUS_CONTINUED_AS_NEW + ) + TIMED_OUT = int( + temporalio.api.enums.v1.WorkflowExecutionStatus.WORKFLOW_EXECUTION_STATUS_TIMED_OUT + ) + + +@dataclass +class WorkflowExecutionCount: + """Representation of a count from a count workflows call.""" + + count: int + """Approximate number of workflows matching the original query. + + If the query had a group-by clause, this is simply the sum of all the counts + in py:attr:`groups`. + """ + + groups: Sequence[WorkflowExecutionCountAggregationGroup] + """Groups if the query had a group-by clause, or empty if not.""" + + @staticmethod + def _from_raw( + raw: temporalio.api.workflowservice.v1.CountWorkflowExecutionsResponse, + ) -> WorkflowExecutionCount: + return WorkflowExecutionCount( + count=raw.count, + groups=[ + WorkflowExecutionCountAggregationGroup._from_raw(g) for g in raw.groups + ], + ) + + +@dataclass +class WorkflowExecutionCountAggregationGroup: + """Aggregation group if the workflow count query had a group-by clause.""" + + count: int + """Approximate number of workflows matching the original query for this + group. + """ + + group_values: Sequence[temporalio.common.SearchAttributeValue] + """Search attribute values for this group.""" + + @staticmethod + def _from_raw( + raw: temporalio.api.workflowservice.v1.CountWorkflowExecutionsResponse.AggregationGroup, + ) -> WorkflowExecutionCountAggregationGroup: + return WorkflowExecutionCountAggregationGroup( + count=raw.count, + group_values=[ + temporalio.converter._search_attributes._decode_search_attribute_value( + v + ) + for v in raw.group_values + ], + ) + + +class WorkflowExecutionAsyncIterator: + """Asynchronous iterator for :py:class:`WorkflowExecution` values. + + Most users should use ``async for`` on this iterator and not call any of the + methods within. To consume the workflows as histories, call + :py:meth:`map_histories`. + """ + + def __init__( + self, + client: Client, + input: ListWorkflowsInput, + ) -> None: + """Create an asynchronous iterator for the given input. + + Users should not create this directly, but rather use + :py:meth:`Client.list_workflows`. + """ + self._client = client + self._input = input + self._next_page_token = input.next_page_token + self._current_page: Sequence[WorkflowExecution] | None = None + self._current_page_index = 0 + self._limit = input.limit + self._yielded = 0 + + @property + def current_page_index(self) -> int: + """Index of the entry in the current page that will be returned from + the next :py:meth:`__anext__` call. + """ + return self._current_page_index + + @property + def current_page(self) -> Sequence[WorkflowExecution] | None: + """Current page, if it has been fetched yet.""" + return self._current_page + + @property + def next_page_token(self) -> bytes | None: + """Token for the next page request if any.""" + return self._next_page_token + + async def fetch_next_page(self, *, page_size: int | None = None) -> None: + """Fetch the next page if any. + + Args: + page_size: Override the page size this iterator was originally + created with. + """ + page_size = page_size or self._input.page_size + if self._limit is not None and self._limit - self._yielded < page_size: + page_size = self._limit - self._yielded + + resp = await self._client.workflow_service.list_workflow_executions( + temporalio.api.workflowservice.v1.ListWorkflowExecutionsRequest( + namespace=self._client.namespace, + page_size=page_size, + next_page_token=self._next_page_token or b"", + query=self._input.query or "", + ), + retry=True, + metadata=self._input.rpc_metadata, + timeout=self._input.rpc_timeout, + ) + + self._current_page = [ + WorkflowExecution._from_raw_info( + v, self._client.namespace, self._client.data_converter + ) + for v in resp.executions + ] + self._current_page_index = 0 + self._next_page_token = resp.next_page_token or None + + def __aiter__(self) -> WorkflowExecutionAsyncIterator: + """Return self as the iterator.""" + return self + + async def __anext__(self) -> WorkflowExecution: + """Get the next execution on this iterator, fetching next page if + necessary. + """ + if self._limit is not None and self._yielded >= self._limit: + raise StopAsyncIteration + while True: + # No page? fetch and continue + if self._current_page is None: + await self.fetch_next_page() + continue + # No more left in page? + if self._current_page_index >= len(self._current_page): + # If there is a next page token, try to get another page and try + # again + if self._next_page_token is not None: + await self.fetch_next_page() + continue + # No more pages means we're done + raise StopAsyncIteration + # Get current, increment page index, and return + ret = self._current_page[self._current_page_index] + self._current_page_index += 1 + self._yielded += 1 + return ret + + async def map_histories( + self, + *, + event_filter_type: WorkflowHistoryEventFilterType = WorkflowHistoryEventFilterType.ALL_EVENT, + skip_archival: bool = False, + rpc_metadata: Mapping[str, str | bytes] = {}, + rpc_timeout: timedelta | None = None, + ) -> AsyncIterator[WorkflowHistory]: + """Create an async iterator consuming all workflows and calling + :py:meth:`WorkflowHandle.fetch_history` on each one. + + This is just a shortcut for ``fetch_history``, see that method for + parameter details. + """ + async for v in self: + yield await self._client.get_workflow_handle( + v.id, run_id=v.run_id + ).fetch_history( + event_filter_type=event_filter_type, + skip_archival=skip_archival, + rpc_metadata=rpc_metadata, + rpc_timeout=rpc_timeout, + ) + + +@dataclass(frozen=True) +class WorkflowHistory: + """A workflow's ID and immutable history.""" + + workflow_id: str + """ID of the workflow.""" + + events: Sequence[temporalio.api.history.v1.HistoryEvent] + """History events for the workflow.""" + + @property + def run_id(self) -> str: + """Run ID extracted from the first event.""" + if not self.events: + raise RuntimeError("No events") + if not self.events[0].HasField("workflow_execution_started_event_attributes"): + raise RuntimeError("First event is not workflow start") + return self.events[ + 0 + ].workflow_execution_started_event_attributes.original_execution_run_id + + @staticmethod + def from_json(workflow_id: str, history: str | dict[str, Any]) -> WorkflowHistory: + """Construct a WorkflowHistory from an ID and a json dump of history. + + This is built to work both with Temporal UI/CLI JSON as well as + :py:meth:`to_json` even though they are slightly different. + + Args: + workflow_id: The workflow's ID + history: A string or parsed-to-dict representation of workflow + history + + Returns: + Workflow history + """ + parsed = _history_from_json(history) + return WorkflowHistory(workflow_id, parsed.events) + + def to_json(self) -> str: + """Convert this history to JSON. + + Note, this does not include the workflow ID. + """ + return google.protobuf.json_format.MessageToJson( + temporalio.api.history.v1.History(events=self.events) + ) + + def to_json_dict(self) -> dict[str, Any]: + """Convert this history to JSON-compatible dict. + + Note, this does not include the workflow ID. + """ + return google.protobuf.json_format.MessageToDict( + temporalio.api.history.v1.History(events=self.events) + ) + + +@dataclass +class WorkflowHistoryEventAsyncIterator: + """Asynchronous iterator for history events of a workflow. + + Most users should use ``async for`` on this iterator and not call any of the + methods within. + """ + + def __init__( + self, + client: Client, + input: FetchWorkflowHistoryEventsInput, + ) -> None: + """Create an asynchronous iterator for the given input. + + Users should not create this directly, but rather use + :py:meth:`WorkflowHandle.fetch_history_events`. + """ + self._client = client + self._input = input + self._next_page_token = input.next_page_token + self._current_page: ( + None | (Sequence[temporalio.api.history.v1.HistoryEvent]) + ) = None + self._current_page_index = 0 + + @property + def current_page_index(self) -> int: + """Index of the entry in the current page that will be returned from + the next :py:meth:`__anext__` call. + """ + return self._current_page_index + + @property + def current_page( + self, + ) -> Sequence[temporalio.api.history.v1.HistoryEvent] | None: + """Current page, if it has been fetched yet.""" + return self._current_page + + @property + def next_page_token(self) -> bytes | None: + """Token for the next page request if any.""" + return self._next_page_token + + async def fetch_next_page(self, *, page_size: int | None = None) -> None: # type:ignore[reportUnusedParameter] # https://github.com/temporalio/sdk-python/issues/1239 + """Fetch the next page if any. + + Args: + page_size: Override the page size this iterator was originally + created with. + """ + resp = await self._client.workflow_service.get_workflow_execution_history( + temporalio.api.workflowservice.v1.GetWorkflowExecutionHistoryRequest( + namespace=self._client.namespace, + execution=temporalio.api.common.v1.WorkflowExecution( + workflow_id=self._input.id, + run_id=self._input.run_id or "", + ), + maximum_page_size=page_size or self._input.page_size or 0, + next_page_token=self._next_page_token or b"", + wait_new_event=self._input.wait_new_event, + history_event_filter_type=temporalio.api.enums.v1.HistoryEventFilterType.ValueType( + self._input.event_filter_type + ), + skip_archival=self._input.skip_archival, + ), + retry=True, + metadata=self._input.rpc_metadata, + timeout=self._input.rpc_timeout, + ) + # We don't support raw history + assert len(resp.raw_history) == 0 + self._current_page = list(resp.history.events) + self._current_page_index = 0 + self._next_page_token = resp.next_page_token or None + + def __aiter__(self) -> WorkflowHistoryEventAsyncIterator: + """Return self as the iterator.""" + return self + + async def __anext__(self) -> temporalio.api.history.v1.HistoryEvent: + """Get the next execution on this iterator, fetching next page if + necessary. + """ + while True: + # No page? fetch and continue + if self._current_page is None: + await self.fetch_next_page() + continue + # No more left in page? + if self._current_page_index >= len(self._current_page): + # If there is a next page token, try to get another page and try + # again + if self._next_page_token is not None: + await self.fetch_next_page() + continue + # No more pages means we're done + raise StopAsyncIteration + # Increment page index and return + ret = self._current_page[self._current_page_index] + self._current_page_index += 1 + return ret + + +class WorkflowUpdateHandle(Generic[LocalReturnType]): + """Handle for a workflow update execution request.""" + + def __init__( + self, + client: Client, + id: str, + workflow_id: str, + *, + workflow_run_id: str | None = None, + result_type: type | None = None, + known_outcome: temporalio.api.update.v1.Outcome | None = None, + ): + """Create a workflow update handle. + + Users should not create this directly, but rather use + :py:meth:`WorkflowHandle.start_update` or :py:meth:`WorkflowHandle.get_update_handle`. + """ + self._client = client + self._id = id + self._workflow_id = workflow_id + self._workflow_run_id = workflow_run_id + self._result_type = result_type + self._known_outcome = known_outcome + + @functools.cached_property + def _data_converter(self) -> temporalio.converter.DataConverter: + return self._client.data_converter.with_context( + WorkflowSerializationContext( + namespace=self._client.namespace, + workflow_id=self.workflow_id, + ) + ) + + @property + def id(self) -> str: + """ID of this Update request.""" + return self._id + + @property + def workflow_id(self) -> str: + """The ID of the Workflow targeted by this Update.""" + return self._workflow_id + + @property + def workflow_run_id(self) -> str | None: + """If specified, the specific run of the Workflow targeted by this Update.""" + return self._workflow_run_id + + async def result( + self, + *, + rpc_metadata: Mapping[str, str | bytes] = {}, + rpc_timeout: timedelta | None = None, + ) -> LocalReturnType: + """Wait for and return the result of the update. The result may already be known in which case no network call + is made. Otherwise the result will be polled for until it is returned. + + Args: + rpc_metadata: Headers used on the RPC call. Keys here override client-level RPC metadata keys. + rpc_timeout: Optional RPC deadline to set for each RPC call. Note: this is the timeout for each + RPC call while polling, not a timeout for the function as a whole. If an individual RPC times out, + it will be retried until the result is available. + + Raises: + WorkflowUpdateFailedError: If the update failed. + WorkflowUpdateRPCTimeoutOrCancelledError: This update call timed out + or was cancelled. This doesn't mean the update itself was timed + out or cancelled. + RPCError: Update result could not be fetched for some other reason. + """ + # Poll until outcome reached + await self._poll_until_outcome( + rpc_metadata=rpc_metadata, rpc_timeout=rpc_timeout + ) + + # Convert outcome to failure or value + assert self._known_outcome + if self._known_outcome.HasField("failure"): + raise WorkflowUpdateFailedError( + await self._data_converter.decode_failure(self._known_outcome.failure), + ) + if not self._known_outcome.success.payloads: + return None # type: ignore + type_hints = [self._result_type] if self._result_type else None + results = await self._data_converter.decode( + self._known_outcome.success.payloads, type_hints + ) + if not results: + return None # type: ignore + elif len(results) > 1: + warnings.warn(f"Expected single update result, got {len(results)}") + return results[0] + + async def _poll_until_outcome( + self, + rpc_metadata: Mapping[str, str | bytes] = {}, + rpc_timeout: timedelta | None = None, + ) -> None: + if self._known_outcome: + return + req = temporalio.api.workflowservice.v1.PollWorkflowExecutionUpdateRequest( + namespace=self._client.namespace, + update_ref=temporalio.api.update.v1.UpdateRef( + workflow_execution=temporalio.api.common.v1.WorkflowExecution( + workflow_id=self.workflow_id, + run_id=self.workflow_run_id or "", + ), + update_id=self.id, + ), + identity=self._client.identity, + wait_policy=temporalio.api.update.v1.WaitPolicy( + lifecycle_stage=temporalio.api.enums.v1.UpdateWorkflowExecutionLifecycleStage.UPDATE_WORKFLOW_EXECUTION_LIFECYCLE_STAGE_COMPLETED + ), + ) + + # Continue polling as long as we have no outcome + while True: + try: + res = ( + await self._client.workflow_service.poll_workflow_execution_update( + req, + retry=True, + metadata=rpc_metadata, + timeout=rpc_timeout, + ) + ) + if res.HasField("outcome"): + self._known_outcome = res.outcome + return + except RPCError as err: + if ( + err.status == RPCStatusCode.DEADLINE_EXCEEDED + or err.status == RPCStatusCode.CANCELLED + ): + raise WorkflowUpdateRPCTimeoutOrCancelledError() from err + else: + raise + except asyncio.CancelledError as err: + raise WorkflowUpdateRPCTimeoutOrCancelledError() from err + + +class WorkflowUpdateStage(IntEnum): + """Stage to wait for workflow update to reach before returning from + ``start_update``. + """ + + ADMITTED = int( + temporalio.api.enums.v1.UpdateWorkflowExecutionLifecycleStage.UPDATE_WORKFLOW_EXECUTION_LIFECYCLE_STAGE_ADMITTED + ) + ACCEPTED = int( + temporalio.api.enums.v1.UpdateWorkflowExecutionLifecycleStage.UPDATE_WORKFLOW_EXECUTION_LIFECYCLE_STAGE_ACCEPTED + ) + COMPLETED = int( + temporalio.api.enums.v1.UpdateWorkflowExecutionLifecycleStage.UPDATE_WORKFLOW_EXECUTION_LIFECYCLE_STAGE_COMPLETED + ) diff --git a/tests/test_client_exports.py b/tests/test_client_exports.py new file mode 100644 index 000000000..6f4a6eb04 --- /dev/null +++ b/tests/test_client_exports.py @@ -0,0 +1,216 @@ +import temporalio.client + +# Generated from temporalio.client on main +EXPECTED_CLIENT_EXPORTS = [ + "ActivityCancellationDetails", + "ActivityExecution", + "ActivityExecutionAsyncIterator", + "ActivityExecutionCount", + "ActivityExecutionCountAggregationGroup", + "ActivityExecutionDescription", + "ActivityExecutionStatus", + "ActivityFailureError", + "ActivityHandle", + "ActivitySerializationContext", + "AnyType", + "AsyncActivityCancelledError", + "AsyncActivityHandle", + "AsyncActivityIDReference", + "BackfillScheduleInput", + "BuildIdOp", + "BuildIdOpAddNewCompatible", + "BuildIdOpAddNewDefault", + "BuildIdOpMergeSets", + "BuildIdOpPromoteBuildIdWithinSet", + "BuildIdOpPromoteSetByBuildId", + "BuildIdReachability", + "BuildIdVersionSet", + "CallableAsyncNoParam", + "CallableAsyncSingleParam", + "CallableSyncNoParam", + "CallableSyncSingleParam", + "Callback", + "CancelActivityInput", + "CancelWorkflowInput", + "Client", + "ClientConfig", + "ClientConnectConfig", + "CloudOperationsClient", + "CompleteAsyncActivityInput", + "ConnectConfig", + "CountActivitiesInput", + "CountWorkflowsInput", + "CreateScheduleInput", + "DataConverter", + "DeleteScheduleInput", + "DescribeActivityInput", + "DescribeScheduleInput", + "DescribeWorkflowInput", + "DnsLoadBalancingConfig", + "FailAsyncActivityInput", + "FetchWorkflowHistoryEventsInput", + "GetWorkerBuildIdCompatibilityInput", + "GetWorkerTaskReachabilityInput", + "HeaderCodecBehavior", + "HeartbeatAsyncActivityInput", + "HttpConnectProxyConfig", + "Interceptor", + "KeepAliveConfig", + "ListActivitiesInput", + "ListSchedulesInput", + "ListWorkflowsInput", + "LocalReturnType", + "MethodAsyncNoParam", + "MethodAsyncSingleParam", + "MethodSyncOrAsyncNoParam", + "MethodSyncOrAsyncSingleParam", + "MultiParamSpec", + "OutboundInterceptor", + "ParamType", + "PauseScheduleInput", + "PendingActivityState", + "Plugin", + "QueryWorkflowInput", + "RPCError", + "RPCStatusCode", + "RPCTimeoutOrCancelledError", + "ReportCancellationAsyncActivityInput", + "RetryConfig", + "ReturnType", + "Schedule", + "ScheduleAction", + "ScheduleActionExecution", + "ScheduleActionExecutionStartWorkflow", + "ScheduleActionResult", + "ScheduleActionStartWorkflow", + "ScheduleAlreadyRunningError", + "ScheduleAsyncIterator", + "ScheduleBackfill", + "ScheduleCalendarSpec", + "ScheduleDescription", + "ScheduleHandle", + "ScheduleInfo", + "ScheduleIntervalSpec", + "ScheduleListAction", + "ScheduleListActionStartWorkflow", + "ScheduleListDescription", + "ScheduleListInfo", + "ScheduleListSchedule", + "ScheduleListState", + "ScheduleOverlapPolicy", + "SchedulePolicy", + "ScheduleRange", + "ScheduleSpec", + "ScheduleState", + "ScheduleUpdate", + "ScheduleUpdateInput", + "SelfType", + "SerializationContext", + "ServiceClient", + "SignalWorkflowInput", + "StartActivityInput", + "StartWorkflowInput", + "StartWorkflowUpdateInput", + "StartWorkflowUpdateWithStartInput", + "StorageDriverActivityInfo", + "StorageDriverStoreContext", + "StorageDriverWorkflowInfo", + "TLSConfig", + "TaskReachabilityType", + "TerminateActivityInput", + "TerminateWorkflowInput", + "TriggerScheduleInput", + "UnpauseScheduleInput", + "UpdateScheduleInput", + "UpdateWithStartStartWorkflowInput", + "UpdateWithStartUpdateWorkflowInput", + "UpdateWorkerBuildIdCompatibilityInput", + "WithSerializationContext", + "WithStartWorkflowOperation", + "WorkerBuildIdVersionSets", + "WorkerTaskReachability", + "WorkflowContinuedAsNewError", + "WorkflowExecution", + "WorkflowExecutionAsyncIterator", + "WorkflowExecutionCount", + "WorkflowExecutionCountAggregationGroup", + "WorkflowExecutionDescription", + "WorkflowExecutionStatus", + "WorkflowFailureError", + "WorkflowHandle", + "WorkflowHistory", + "WorkflowHistoryEventAsyncIterator", + "WorkflowHistoryEventFilterType", + "WorkflowQueryFailedError", + "WorkflowQueryRejectedError", + "WorkflowSerializationContext", + "WorkflowUpdateFailedError", + "WorkflowUpdateHandle", + "WorkflowUpdateRPCTimeoutOrCancelledError", + "WorkflowUpdateStage", + "_ClientImpl", + "_apply_headers", + "_decode_user_metadata", + "_encode_user_metadata", + "_fix_history_enum", + "_fix_history_failure", + "_history_from_json", + "_pascal_case_match", + "annotations", +] + + +EXPECTED_INTENTIONALLY_REMOVED_CLIENT_EXPORTS = [ + "ABC", + "Any", + "AsyncIterator", + "Awaitable", + "Callable", + "Concatenate", + "Enum", + "Future", + "Generic", + "IntEnum", + "Iterable", + "Mapping", + "MessageMap", + "Required", + "Self", + "Sequence", + "TypedDict", + "abc", + "abstractmethod", + "asyncio", + "cast", + "copy", + "dataclass", + "dataclasses", + "datetime", + "functools", + "google", + "inspect", + "json", + "overload", + "re", + "temporalio", + "timedelta", + "timezone", + "uuid", + "warnings", +] + + +def test_client_module_exports_match_main() -> None: + missing = [ + name for name in EXPECTED_CLIENT_EXPORTS if not hasattr(temporalio.client, name) + ] + assert not missing + + +def test_client_module_drops_intentionally_removed_import_exports() -> None: + exported = [ + name + for name in EXPECTED_INTENTIONALLY_REMOVED_CLIENT_EXPORTS + if hasattr(temporalio.client, name) + ] + assert not exported From 7556b16fe5e479e0c894328adf47623c923a2d66 Mon Sep 17 00:00:00 2001 From: Brian Strauch Date: Mon, 18 May 2026 13:16:15 -0700 Subject: [PATCH 092/226] Remove exclude-newer-package option (#1529) * Remove exclude-newer-package option * DEBUG: -vv on uv remove to capture resolution trace * Revert "DEBUG: -vv on uv remove to capture resolution trace" This reverts commit ea0afa56a64a31313626381ba2cee5923c8350c0. --- pyproject.toml | 1 - uv.lock | 4 ---- 2 files changed, 5 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 81bb05922..a5f509227 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -256,4 +256,3 @@ exclude = ["temporalio/bridge/target/**/*"] # Prevent uv commands from building the package by default package = false exclude-newer = "1 week" -exclude-newer-package = { openai-agents = false, openinference-instrumentation-google-adk = false } diff --git a/uv.lock b/uv.lock index 256651ff7..f378016db 100644 --- a/uv.lock +++ b/uv.lock @@ -12,10 +12,6 @@ resolution-markers = [ exclude-newer = "2026-05-07T19:04:44.331561Z" exclude-newer-span = "P1W" -[options.exclude-newer-package] -openai-agents = false -openinference-instrumentation-google-adk = false - [[package]] name = "aioboto3" version = "15.5.0" From d39b612df3c795708c96afa7eea0d9ac7d329b3c Mon Sep 17 00:00:00 2001 From: tconley1428 Date: Mon, 18 May 2026 13:46:43 -0700 Subject: [PATCH 093/226] Refactor `workflow.py` into package (#1488) * Refactor workflow into package * Fix workflow package exports * Aggregate workflow exports * Clean up workflow package reexports * Sort workflow package reexports * Restore workflow compatibility reexports * Add workflow export compatibility test * Format workflow export test * Update test_workflow_exports.py --- temporalio/contrib/aws/s3driver/README.md | 2 +- temporalio/workflow.py | 5907 --------------------- temporalio/workflow/__init__.py | 320 ++ temporalio/workflow/_activities.py | 2008 +++++++ temporalio/workflow/_asyncio.py | 180 + temporalio/workflow/_context.py | 917 ++++ temporalio/workflow/_definition.py | 466 ++ temporalio/workflow/_exceptions.py | 119 + temporalio/workflow/_handlers.py | 587 ++ temporalio/workflow/_nexus.py | 503 ++ temporalio/workflow/_sandbox.py | 321 ++ temporalio/workflow/_workflow_ops.py | 1010 ++++ tests/test_workflow_exports.py | 219 + 13 files changed, 6651 insertions(+), 5908 deletions(-) delete mode 100644 temporalio/workflow.py create mode 100644 temporalio/workflow/__init__.py create mode 100644 temporalio/workflow/_activities.py create mode 100644 temporalio/workflow/_asyncio.py create mode 100644 temporalio/workflow/_context.py create mode 100644 temporalio/workflow/_definition.py create mode 100644 temporalio/workflow/_exceptions.py create mode 100644 temporalio/workflow/_handlers.py create mode 100644 temporalio/workflow/_nexus.py create mode 100644 temporalio/workflow/_sandbox.py create mode 100644 temporalio/workflow/_workflow_ops.py create mode 100644 tests/test_workflow_exports.py diff --git a/temporalio/contrib/aws/s3driver/README.md b/temporalio/contrib/aws/s3driver/README.md index ce58789df..73b9b3299 100644 --- a/temporalio/contrib/aws/s3driver/README.md +++ b/temporalio/contrib/aws/s3driver/README.md @@ -23,7 +23,7 @@ from temporalio.contrib.aws.s3driver.aioboto3 import new_aioboto3_client from temporalio.converter import DataConverter, ExternalStorage session = aioboto3.Session() -# To see how to set credentials and region via environment, config objects, or configuration files, +# To see how to set credentials and region via environment, config objects, or configuration files, # see: # https://docs.aws.amazon.com/boto3/latest/guide/configuration.html async with session.client("s3") as s3_client: diff --git a/temporalio/workflow.py b/temporalio/workflow.py deleted file mode 100644 index 40f17302c..000000000 --- a/temporalio/workflow.py +++ /dev/null @@ -1,5907 +0,0 @@ -"""Utilities that can decorate or be called inside workflows.""" - -from __future__ import annotations - -import asyncio -import contextvars -import inspect -import logging -import sys -import threading -import typing -import uuid -import warnings -from abc import ABC, abstractmethod -from collections.abc import ( - Awaitable, - Callable, - Generator, - Iterable, - Iterator, - Mapping, - MutableMapping, - Sequence, -) -from contextlib import contextmanager -from dataclasses import dataclass -from datetime import datetime, timedelta, timezone -from enum import Enum, Flag, IntEnum, auto -from functools import partial -from random import Random -from typing import ( - TYPE_CHECKING, - Any, - Concatenate, - Generic, - Literal, - NoReturn, - TypeVar, - cast, - overload, -) - -import nexusrpc -import nexusrpc.handler -from nexusrpc import InputT, OutputT -from typing_extensions import ( - Protocol, - TypedDict, - runtime_checkable, -) - -import temporalio.api.common.v1 -import temporalio.api.enums -import temporalio.api.enums.v1 -import temporalio.bridge.proto.child_workflow -import temporalio.bridge.proto.common -import temporalio.bridge.proto.nexus -import temporalio.bridge.proto.workflow_commands -import temporalio.common -import temporalio.converter -import temporalio.exceptions -import temporalio.nexus -import temporalio.workflow -from temporalio.nexus._util import ServiceHandlerT - -from .types import ( - AnyType, - CallableAsyncNoParam, - CallableAsyncSingleParam, - CallableAsyncType, - CallableSyncNoParam, - CallableSyncOrAsyncReturnNoneType, - CallableSyncOrAsyncType, - CallableSyncSingleParam, - CallableType, - ClassType, - MethodAsyncNoParam, - MethodAsyncSingleParam, - MethodSyncNoParam, - MethodSyncOrAsyncNoParam, - MethodSyncOrAsyncSingleParam, - MethodSyncSingleParam, - MultiParamSpec, - ParamType, - ProtocolReturnType, - ReturnType, - SelfType, -) - - -@overload -def defn(cls: ClassType) -> ClassType: ... - - -@overload -def defn( - *, - name: str | None = None, - sandboxed: bool = True, - failure_exception_types: Sequence[type[BaseException]] = [], - versioning_behavior: temporalio.common.VersioningBehavior = temporalio.common.VersioningBehavior.UNSPECIFIED, -) -> Callable[[ClassType], ClassType]: ... - - -@overload -def defn( - *, - sandboxed: bool = True, - dynamic: bool = False, - versioning_behavior: temporalio.common.VersioningBehavior = temporalio.common.VersioningBehavior.UNSPECIFIED, -) -> Callable[[ClassType], ClassType]: ... - - -def defn( - cls: ClassType | None = None, - *, - name: str | None = None, - sandboxed: bool = True, - dynamic: bool = False, - failure_exception_types: Sequence[type[BaseException]] = [], - versioning_behavior: temporalio.common.VersioningBehavior = temporalio.common.VersioningBehavior.UNSPECIFIED, -) -> Callable[[ClassType], ClassType]: - """Decorator for workflow classes. - - This must be set on any registered workflow class (it is ignored if on a - base class). - - Args: - cls: The class to decorate. - name: Name to use for the workflow. Defaults to class ``__name__``. This - cannot be set if dynamic is set. - sandboxed: Whether the workflow should run in a sandbox. Default is - true. - dynamic: If true, this activity will be dynamic. Dynamic workflows have - to accept a single 'Sequence[RawValue]' parameter. This cannot be - set to true if name is present. - failure_exception_types: The types of exceptions that, if a - workflow-thrown exception extends, will cause the workflow/update to - fail instead of suspending the workflow via task failure. These are - applied in addition to ones set on the worker constructor. If - ``Exception`` is set, it effectively will fail a workflow/update in - all user exception cases. WARNING: This setting is experimental. - versioning_behavior: Specifies the versioning behavior to use for this workflow. - """ - - def decorator(cls: ClassType) -> ClassType: - # This performs validation - _Definition._apply_to_class( - cls, - workflow_name=name or cls.__name__ if not dynamic else None, - sandboxed=sandboxed, - failure_exception_types=failure_exception_types, - versioning_behavior=versioning_behavior, - ) - return cls - - if cls is not None: - return decorator(cls) - return decorator - - -def init( - init_fn: CallableType, -) -> CallableType: - """Decorator for the workflow init method. - - This may be used on the __init__ method of the workflow class to specify - that it accepts the same workflow input arguments as the ``@workflow.run`` - method. If used, the parameters of your __init__ and ``@workflow.run`` - methods must be identical. - - Args: - init_fn: The __init__ method to decorate. - """ - if init_fn.__name__ != "__init__": - raise ValueError("@workflow.init may only be used on the __init__ method") - - setattr(init_fn, "__temporal_workflow_init", True) - return init_fn - - -def run(fn: CallableAsyncType) -> CallableAsyncType: - """Decorator for the workflow run method. - - This must be used on one and only one async method defined on the same class - as ``@workflow.defn``. This can be defined on a base class method but must - then be explicitly overridden and defined on the workflow class. - - Run methods can only have positional parameters. Best practice is to only - take a single object/dataclass argument that can accept more fields later if - needed. - - Args: - fn: The function to decorate. - """ - if not inspect.iscoroutinefunction(fn): - raise ValueError("Workflow run method must be an async function") - # Disallow local classes because we need to have the class globally - # referenceable by name - if "" in fn.__qualname__: - raise ValueError( - "Local classes unsupported, @workflow.run cannot be on a local class" - ) - setattr(fn, "__temporal_workflow_run", True) - # TODO(cretz): Why is MyPy unhappy with this return? - return fn # type: ignore[return-value] - - -class HandlerUnfinishedPolicy(Enum): - """Actions taken if a workflow terminates with running handlers. - - Policy defining actions taken when a workflow exits while update or signal handlers are running. - The workflow exit may be due to successful return, failure, cancellation, or continue-as-new. - """ - - WARN_AND_ABANDON = 1 - """Issue a warning in addition to abandoning.""" - ABANDON = 2 - """Abandon the handler. - - In the case of an update handler this means that the client will receive an error rather than - the update result.""" - - -class UnfinishedUpdateHandlersWarning(RuntimeWarning): - """The workflow exited before all update handlers had finished executing.""" - - -class UnfinishedSignalHandlersWarning(RuntimeWarning): - """The workflow exited before all signal handlers had finished executing.""" - - -@overload -def signal( - fn: CallableSyncOrAsyncReturnNoneType, -) -> CallableSyncOrAsyncReturnNoneType: ... - - -@overload -def signal( - *, - unfinished_policy: HandlerUnfinishedPolicy = HandlerUnfinishedPolicy.WARN_AND_ABANDON, - description: str | None = None, -) -> Callable[ - [CallableSyncOrAsyncReturnNoneType], CallableSyncOrAsyncReturnNoneType -]: ... - - -@overload -def signal( - *, - name: str, - unfinished_policy: HandlerUnfinishedPolicy = HandlerUnfinishedPolicy.WARN_AND_ABANDON, - description: str | None = None, -) -> Callable[ - [CallableSyncOrAsyncReturnNoneType], CallableSyncOrAsyncReturnNoneType -]: ... - - -@overload -def signal( - *, - dynamic: Literal[True], - unfinished_policy: HandlerUnfinishedPolicy = HandlerUnfinishedPolicy.WARN_AND_ABANDON, - description: str | None = None, -) -> Callable[ - [CallableSyncOrAsyncReturnNoneType], CallableSyncOrAsyncReturnNoneType -]: ... - - -def signal( - fn: CallableSyncOrAsyncReturnNoneType | None = None, - *, - name: str | None = None, - dynamic: bool | None = False, - unfinished_policy: HandlerUnfinishedPolicy = HandlerUnfinishedPolicy.WARN_AND_ABANDON, - description: str | None = None, -) -> ( - Callable[[CallableSyncOrAsyncReturnNoneType], CallableSyncOrAsyncReturnNoneType] - | CallableSyncOrAsyncReturnNoneType -): - """Decorator for a workflow signal method. - - This is used on any async or non-async method that you wish to be called upon - receiving a signal. If a function overrides one with this decorator, it too - must be decorated. - - Signal methods can only have positional parameters. Best practice for - non-dynamic signal methods is to only take a single object/dataclass - argument that can accept more fields later if needed. Return values from - signal methods are ignored. - - Args: - fn: The function to decorate. - name: Signal name. Defaults to method ``__name__``. Cannot be present - when ``dynamic`` is present. - dynamic: If true, this handles all signals not otherwise handled. The - parameters of the method must be self, a string name, and a - ``*args`` positional varargs. Cannot be present when ``name`` is - present. - unfinished_policy: Actions taken if a workflow terminates with - a running instance of this handler. - description: A short description of the signal that may appear in the UI/CLI. - """ - - def decorator( - name: str | None, - unfinished_policy: HandlerUnfinishedPolicy, - fn: CallableSyncOrAsyncReturnNoneType, - ) -> CallableSyncOrAsyncReturnNoneType: - if not name and not dynamic: - name = fn.__name__ - defn = _SignalDefinition( - name=name, - fn=fn, - is_method=True, - unfinished_policy=unfinished_policy, - description=description, - ) - setattr(fn, "__temporal_signal_definition", defn) - if defn.dynamic_vararg: - warnings.warn( - "Dynamic signals with vararg third param is deprecated, use Sequence[RawValue]", - DeprecationWarning, - stacklevel=2, - ) - return fn - - if not fn: - if name is not None and dynamic: - raise RuntimeError("Cannot provide name and dynamic boolean") - return partial(decorator, name, unfinished_policy) - else: - return decorator(fn.__name__, unfinished_policy, fn) - - -@overload -def query(fn: CallableType) -> CallableType: ... - - -@overload -def query( - *, name: str, description: str | None = None -) -> Callable[[CallableType], CallableType]: ... - - -@overload -def query( - *, dynamic: Literal[True], description: str | None = None -) -> Callable[[CallableType], CallableType]: ... - - -@overload -def query(*, description: str) -> Callable[[CallableType], CallableType]: ... - - -def query( - fn: CallableType | None = None, # type: ignore[reportInvalidTypeVarUse] - *, - name: str | None = None, - dynamic: bool | None = False, - description: str | None = None, -): - """Decorator for a workflow query method. - - This is used on any non-async method that expects to handle a query. If a - function overrides one with this decorator, it too must be decorated. - - Query methods can only have positional parameters. Best practice for - non-dynamic query methods is to only take a single object/dataclass - argument that can accept more fields later if needed. The return value is - the resulting query value. Query methods must not mutate any workflow state. - - Args: - fn: The function to decorate. - name: Query name. Defaults to method ``__name__``. Cannot be present - when ``dynamic`` is present. - dynamic: If true, this handles all queries not otherwise handled. The - parameters of the method should be self, a string name, and a - ``Sequence[RawValue]``. An older form of this accepted vararg - parameters which will now warn. Cannot be present when ``name`` is - present. - description: A short description of the query that may appear in the UI/CLI. - """ - - def decorator( - name: str | None, - description: str | None, - fn: CallableType, - *, - bypass_async_check: bool = False, - ) -> CallableType: - if not name and not dynamic: - name = fn.__name__ - if not bypass_async_check and inspect.iscoroutinefunction(fn): - warnings.warn( - "Queries as async def functions are deprecated", - DeprecationWarning, - stacklevel=2, - ) - defn = _QueryDefinition( - name=name, fn=fn, is_method=True, description=description - ) - setattr(fn, "__temporal_query_definition", defn) - if defn.dynamic_vararg: - warnings.warn( - "Dynamic queries with vararg third param is deprecated, use Sequence[RawValue]", - DeprecationWarning, - stacklevel=2, - ) - return fn - - if name is not None or dynamic or description: - if name is not None and dynamic: - raise RuntimeError("Cannot provide name and dynamic boolean") - return partial(decorator, name, description) - if fn is None: - raise RuntimeError("Cannot create query without function or name or dynamic") - if inspect.iscoroutinefunction(fn): - warnings.warn( - "Queries as async def functions are deprecated", - DeprecationWarning, - stacklevel=2, - ) - return decorator(fn.__name__, description, fn, bypass_async_check=True) - - -@dataclass(frozen=True) -class DynamicWorkflowConfig: - """Returned by functions using the :py:func:`dynamic_config` decorator, see it for more.""" - - failure_exception_types: Sequence[type[BaseException]] | None = None - """The types of exceptions that, if a workflow-thrown exception extends, will cause the - workflow/update to fail instead of suspending the workflow via task failure. These are applied - in addition to ones set on the worker constructor. If ``Exception`` is set, it effectively will - fail a workflow/update in all user exception cases. - - Always overrides the equivalent parameter on :py:func:`defn` if set not-None. - - WARNING: This setting is experimental. - """ - versioning_behavior: temporalio.common.VersioningBehavior = ( - temporalio.common.VersioningBehavior.UNSPECIFIED - ) - """Specifies the versioning behavior to use for this workflow. - - Always overrides the equivalent parameter on :py:func:`defn`. - """ - - -def dynamic_config( - fn: MethodSyncNoParam[SelfType, DynamicWorkflowConfig], -) -> MethodSyncNoParam[SelfType, DynamicWorkflowConfig]: - """Decorator to allow configuring a dynamic workflow's behavior. - - Because dynamic workflows may conceptually represent more than one workflow type, it may be - desirable to have different settings for fields that would normally be passed to - :py:func:`defn`, but vary based on the workflow type name or other information available in - the workflow's context. This function will be called after the workflow's :py:func:`init`, - if it has one, but before the workflow's :py:func:`run` method. - - The method must only take self as a parameter, and any values set in the class it returns will - override those provided to :py:func:`defn`. - - Cannot be specified on non-dynamic workflows. - - Args: - fn: The function to decorate. - """ - if inspect.iscoroutinefunction(fn): - raise ValueError("Workflow dynamic_config method must be synchronous") - params = list(inspect.signature(fn).parameters.values()) - if len(params) != 1: - raise ValueError("Workflow dynamic_config method must only take self parameter") - - # Add marker attribute - setattr(fn, "__temporal_workflow_dynamic_config", True) - return fn - - -@dataclass(frozen=True) -class Info: - """Information about the running workflow. - - Retrieved inside a workflow via :py:func:`info`. This object is immutable - with the exception of the :py:attr:`search_attributes` and - :py:attr:`typed_search_attributes` which is updated on - :py:func:`upsert_search_attributes`. - - Note, required fields may be added here in future versions. This class - should never be constructed by users. - """ - - attempt: int - continued_run_id: str | None - cron_schedule: str | None - execution_timeout: timedelta | None - first_execution_run_id: str - headers: Mapping[str, temporalio.api.common.v1.Payload] - namespace: str - parent: ParentInfo | None - root: RootInfo | None - priority: temporalio.common.Priority - """The priority of this workflow execution. If not set, or this server predates priorities, - then returns a default instance.""" - raw_memo: Mapping[str, temporalio.api.common.v1.Payload] - retry_policy: temporalio.common.RetryPolicy | None - run_id: str - run_timeout: timedelta | None - - search_attributes: temporalio.common.SearchAttributes - """Search attributes for the workflow. - - .. deprecated:: - Use :py:attr:`typed_search_attributes` instead. - """ - - start_time: datetime - """The start time of the first task executed by the workflow.""" - - task_queue: str - task_timeout: timedelta - - typed_search_attributes: temporalio.common.TypedSearchAttributes - """Search attributes for the workflow. - - Note, this may have invalid values or be missing values if passing the - deprecated form of dictionary attributes to - :py:meth:`upsert_search_attributes`. - """ - - workflow_id: str - - workflow_start_time: datetime - """The start time of the workflow based on the workflow initialization.""" - - workflow_type: str - - def _logger_details(self) -> Mapping[str, Any]: - return { - # TODO(cretz): worker ID? - "attempt": self.attempt, - "namespace": self.namespace, - "run_id": self.run_id, - "task_queue": self.task_queue, - "workflow_id": self.workflow_id, - "workflow_type": self.workflow_type, - } - - def get_current_build_id(self) -> str: - """Get the Build ID of the worker which executed the current Workflow Task. - - May be undefined if the task was completed by a worker without a Build ID. If this worker is - the one executing this task for the first time and has a Build ID set, then its ID will be - used. This value may change over the lifetime of the workflow run, but is deterministic and - safe to use for branching. - - .. deprecated:: - Use get_current_deployment_version instead. - """ - return _Runtime.current().workflow_get_current_build_id() - - def get_current_deployment_version( - self, - ) -> temporalio.common.WorkerDeploymentVersion | None: - """Get the deployment version of the worker which executed the current Workflow Task. - - May be None if the task was completed by a worker without a deployment version or build - id. If this worker is the one executing this task for the first time and has a deployment - version set, then its ID will be used. This value may change over the lifetime of the - workflow run, but is deterministic and safe to use for branching. - """ - return _Runtime.current().workflow_get_current_deployment_version() - - def get_current_history_length(self) -> int: - """Get the current number of events in history. - - Note, this value may not be up to date if accessed inside a query. - - Returns: - Current number of events in history (up until the current task). - """ - return _Runtime.current().workflow_get_current_history_length() - - def get_current_history_size(self) -> int: - """Get the current byte size of history. - - Note, this value may not be up to date if accessed inside a query. - - Returns: - Current byte-size of history (up until the current task). - """ - return _Runtime.current().workflow_get_current_history_size() - - def is_continue_as_new_suggested(self) -> bool: - """Get whether or not continue as new is suggested. - - Note, this value may not be up to date if accessed inside a query. - - Returns: - True if the server is configured to suggest continue as new and it - is suggested. - """ - return _Runtime.current().workflow_is_continue_as_new_suggested() - - def is_target_worker_deployment_version_changed(self) -> bool: - """Check whether the target worker deployment version has changed. - - Note: Upgrade-on-Continue-as-New is currently experimental. - - Returns: - True if the target worker deployment version has changed. - """ - return _Runtime.current().workflow_is_target_worker_deployment_version_changed() - - -@dataclass(frozen=True) -class ParentInfo: - """Information about the parent workflow.""" - - namespace: str - run_id: str - workflow_id: str - - -@dataclass(frozen=True) -class RootInfo: - """Information about the root workflow.""" - - run_id: str - workflow_id: str - - -@dataclass(frozen=True) -class UpdateInfo: - """Information about a workflow update.""" - - id: str - """Update ID.""" - - name: str - """Update type name.""" - - @property - def _logger_details(self) -> Mapping[str, Any]: - """Data to be included in string appended to default logging output.""" - return { - "update_id": self.id, - "update_name": self.name, - } - - -class _Runtime(ABC): - @staticmethod - def current() -> _Runtime: - loop = _Runtime.maybe_current() - if not loop: - raise _NotInWorkflowEventLoopError("Not in workflow event loop") - return loop - - @staticmethod - def maybe_current() -> _Runtime | None: - try: - return getattr( - asyncio.get_running_loop(), "__temporal_workflow_runtime", None - ) - except RuntimeError: - return None - - @staticmethod - def set_on_loop(loop: asyncio.AbstractEventLoop, runtime: _Runtime | None) -> None: - if runtime: - setattr(loop, "__temporal_workflow_runtime", runtime) - elif hasattr(loop, "__temporal_workflow_runtime"): - delattr(loop, "__temporal_workflow_runtime") - - def __init__(self) -> None: - super().__init__() - self._logger_details: Mapping[str, Any] | None = None - - @property - def logger_details(self) -> Mapping[str, Any]: - if self._logger_details is None: - self._logger_details = self.workflow_info()._logger_details() - return self._logger_details - - @abstractmethod - def workflow_all_handlers_finished(self) -> bool: ... - - @abstractmethod - def workflow_continue_as_new( - self, - *args: Any, - workflow: None | Callable | str, - task_queue: str | None, - run_timeout: timedelta | None, - task_timeout: timedelta | None, - retry_policy: temporalio.common.RetryPolicy | None, - memo: Mapping[str, Any] | None, - search_attributes: None - | ( - temporalio.common.SearchAttributes | temporalio.common.TypedSearchAttributes - ), - versioning_intent: VersioningIntent | None, - initial_versioning_behavior: ContinueAsNewVersioningBehavior | None, - ) -> NoReturn: ... - - @abstractmethod - def workflow_extern_functions(self) -> Mapping[str, Callable]: ... - - @abstractmethod - def workflow_get_current_build_id(self) -> str: ... - - @abstractmethod - def workflow_get_current_deployment_version( - self, - ) -> temporalio.common.WorkerDeploymentVersion | None: ... - - @abstractmethod - def workflow_get_current_history_length(self) -> int: ... - - @abstractmethod - def workflow_get_current_history_size(self) -> int: ... - - @abstractmethod - def workflow_get_external_workflow_handle( - self, id: str, *, run_id: str | None - ) -> ExternalWorkflowHandle[Any]: ... - - @abstractmethod - def workflow_get_query_handler(self, name: str | None) -> Callable | None: ... - - @abstractmethod - def workflow_get_signal_handler(self, name: str | None) -> Callable | None: ... - - @abstractmethod - def workflow_get_update_handler(self, name: str | None) -> Callable | None: ... - - @abstractmethod - def workflow_get_update_validator(self, name: str | None) -> Callable | None: ... - - @abstractmethod - def workflow_info(self) -> Info: ... - - @abstractmethod - def workflow_instance(self) -> Any: ... - - @abstractmethod - def workflow_is_continue_as_new_suggested(self) -> bool: ... - - @abstractmethod - def workflow_is_target_worker_deployment_version_changed(self) -> bool: ... - - @abstractmethod - def workflow_is_replaying(self) -> bool: ... - - @abstractmethod - def workflow_is_replaying_history_events(self) -> bool: ... - - @abstractmethod - def workflow_is_read_only(self) -> bool: ... - - @abstractmethod - def workflow_memo(self) -> Mapping[str, Any]: ... - - @abstractmethod - def workflow_memo_value( - self, key: str, default: Any, *, type_hint: type | None - ) -> Any: ... - - @abstractmethod - def workflow_upsert_memo(self, updates: Mapping[str, Any]) -> None: ... - - @abstractmethod - def workflow_metric_meter(self) -> temporalio.common.MetricMeter: ... - - @abstractmethod - def workflow_patch(self, id: str, *, deprecated: bool) -> bool: ... - - @abstractmethod - def workflow_payload_converter(self) -> temporalio.converter.PayloadConverter: ... - - @abstractmethod - def workflow_random(self) -> Random: ... - - @abstractmethod - def workflow_set_query_handler( - self, name: str | None, handler: Callable | None - ) -> None: ... - - @abstractmethod - def workflow_set_signal_handler( - self, name: str | None, handler: Callable | None - ) -> None: ... - - @abstractmethod - def workflow_set_update_handler( - self, - name: str | None, - handler: Callable | None, - validator: Callable | None, - ) -> None: ... - - @abstractmethod - def workflow_start_activity( - self, - activity: Any, - *args: Any, - task_queue: str | None, - result_type: type | None, - schedule_to_close_timeout: timedelta | None, - schedule_to_start_timeout: timedelta | None, - start_to_close_timeout: timedelta | None, - heartbeat_timeout: timedelta | None, - retry_policy: temporalio.common.RetryPolicy | None, - cancellation_type: ActivityCancellationType, - activity_id: str | None, - versioning_intent: VersioningIntent | None, - summary: str | None = None, - priority: temporalio.common.Priority = temporalio.common.Priority.default, - ) -> ActivityHandle[Any]: ... - - @abstractmethod - async def workflow_start_child_workflow( - self, - workflow: Any, - *args: Any, - id: str, - task_queue: str | None, - result_type: type | None, - cancellation_type: ChildWorkflowCancellationType, - parent_close_policy: ParentClosePolicy, - execution_timeout: timedelta | None, - run_timeout: timedelta | None, - task_timeout: timedelta | None, - id_reuse_policy: temporalio.common.WorkflowIDReusePolicy, - retry_policy: temporalio.common.RetryPolicy | None, - cron_schedule: str, - memo: Mapping[str, Any] | None, - search_attributes: None - | ( - temporalio.common.SearchAttributes | temporalio.common.TypedSearchAttributes - ), - versioning_intent: VersioningIntent | None, - static_summary: str | None = None, - static_details: str | None = None, - priority: temporalio.common.Priority = temporalio.common.Priority.default, - ) -> ChildWorkflowHandle[Any, Any]: ... - - @abstractmethod - def workflow_start_local_activity( - self, - activity: Any, - *args: Any, - result_type: type | None, - schedule_to_close_timeout: timedelta | None, - schedule_to_start_timeout: timedelta | None, - start_to_close_timeout: timedelta | None, - retry_policy: temporalio.common.RetryPolicy | None, - local_retry_threshold: timedelta | None, - cancellation_type: ActivityCancellationType, - activity_id: str | None, - summary: str | None, - ) -> ActivityHandle[Any]: ... - - @abstractmethod - async def workflow_start_nexus_operation( - self, - endpoint: str, - service: str, - operation: nexusrpc.Operation[InputT, OutputT] | str | Callable[..., Any], - input: Any, - output_type: type[OutputT] | None, - schedule_to_close_timeout: timedelta | None, - schedule_to_start_timeout: timedelta | None, - start_to_close_timeout: timedelta | None, - cancellation_type: temporalio.workflow.NexusOperationCancellationType, - headers: Mapping[str, str] | None, - summary: str | None, - ) -> NexusOperationHandle[OutputT]: ... - - @abstractmethod - def workflow_time_ns(self) -> int: ... - - @abstractmethod - def workflow_upsert_search_attributes( - self, - attributes: ( - temporalio.common.SearchAttributes - | Sequence[temporalio.common.SearchAttributeUpdate] - ), - ) -> None: ... - - @abstractmethod - async def workflow_sleep( - self, duration: float, *, summary: str | None = None - ) -> None: ... - - @abstractmethod - async def workflow_wait_condition( - self, - fn: Callable[[], bool], - *, - timeout: float | None = None, - timeout_summary: str | None = None, - ) -> None: ... - - @abstractmethod - def workflow_get_current_details(self) -> str: ... - - @abstractmethod - def workflow_set_current_details(self, details: str): ... - - @abstractmethod - def workflow_is_failure_exception(self, err: BaseException) -> bool: ... - - @abstractmethod - def workflow_has_last_completion_result(self) -> bool: ... - - @abstractmethod - def workflow_last_completion_result(self, type_hint: type | None) -> Any | None: ... - - @abstractmethod - def workflow_last_failure(self) -> BaseException | None: ... - - @abstractmethod - def workflow_random_seed(self) -> int: ... - - @abstractmethod - def workflow_register_random_seed_callback( - self, callback: Callable[[int], None] - ) -> None: ... - - -_current_update_info: contextvars.ContextVar[UpdateInfo] = contextvars.ContextVar( - "__temporal_current_update_info" -) - - -def _set_current_update_info(info: UpdateInfo) -> None: # type: ignore[reportUnusedFunction] - _current_update_info.set(info) - - -def current_update_info() -> UpdateInfo | None: - """Info for the current update if any. - - This is powered by :py:mod:`contextvars` so it is only valid within the - update handler and coroutines/tasks it has started. - - Returns: - Info for the current update handler the code calling this is executing - within if any. - """ - return _current_update_info.get(None) - - -def deprecate_patch(id: str) -> None: - """Mark a patch as deprecated. - - This marks a workflow that had :py:func:`patched` in a previous version of - the code as no longer applicable because all workflows that use the old code - path are done and will never be queried again. Therefore the old code path - is removed as well. - - Args: - id: The identifier originally used with :py:func:`patched`. - """ - _Runtime.current().workflow_patch(id, deprecated=True) - - -def extern_functions() -> Mapping[str, Callable]: - """External functions available in the workflow sandbox. - - Returns: - Mapping of external functions that can be called from inside a workflow - sandbox. - """ - return _Runtime.current().workflow_extern_functions() - - -def info() -> Info: - """Current workflow's info. - - Returns: - Info for the currently running workflow. - """ - return _Runtime.current().workflow_info() - - -def instance() -> Any: - """Current workflow's instance. - - Returns: - The currently running workflow instance. - """ - return _Runtime.current().workflow_instance() - - -def in_workflow() -> bool: - """Whether the code is currently running in a workflow.""" - return _Runtime.maybe_current() is not None - - -def memo() -> Mapping[str, Any]: - """Current workflow's memo values, converted without type hints. - - Since type hints are not used, the default converted values will come back. - For example, if the memo was originally created with a dataclass, the value - will be a dict. To convert using proper type hints, use - :py:func:`memo_value`. - - Returns: - Mapping of all memo keys and they values without type hints. - """ - return _Runtime.current().workflow_memo() - - -def is_failure_exception(err: BaseException) -> bool: - """Checks if the given exception is a workflow failure in the current workflow. - - Returns: - True if the given exception is a workflow failure in the current workflow. - """ - return _Runtime.current().workflow_is_failure_exception(err) - - -@overload -def memo_value(key: str, default: Any = temporalio.common._arg_unset) -> Any: ... - - -@overload -def memo_value(key: str, *, type_hint: type[ParamType]) -> ParamType: ... - - -@overload -def memo_value( - key: str, default: AnyType, *, type_hint: type[ParamType] -) -> AnyType | ParamType: ... - - -def memo_value( - key: str, - default: Any = temporalio.common._arg_unset, - *, - type_hint: type | None = None, -) -> Any: - """Memo value for the given key, optional default, and optional type - hint. - - Args: - key: Key to get memo value for. - default: Default to use if key is not present. If unset, a - :py:class:`KeyError` is raised when the key does not exist. - type_hint: Type hint to use when converting. - - Returns: - Memo value, converted with the type hint if present. - - Raises: - KeyError: Key not present and default not set. - """ - return _Runtime.current().workflow_memo_value(key, default, type_hint=type_hint) - - -def upsert_memo(updates: Mapping[str, Any]) -> None: - """Adds, modifies, and/or removes memos, with upsert semantics. - - Every memo that has a matching key has its value replaced with the one specified in ``updates``. - If the value is set to ``None``, the memo is removed instead. - For every key with no existing memo, a new memo is added with specified value (unless the value is ``None``). - Memos with keys not included in ``updates`` remain unchanged. - """ - return _Runtime.current().workflow_upsert_memo(updates) - - -def get_current_details() -> str: - """Get the current details of the workflow which may appear in the UI/CLI. - Unlike static details set at start, this value can be updated throughout - the life of the workflow and is independent of the static details. - This can be in Temporal markdown format and can span multiple lines. - """ - return _Runtime.current().workflow_get_current_details() - - -def has_last_completion_result() -> bool: - """Gets whether there is a last completion result of the workflow.""" - return _Runtime.current().workflow_has_last_completion_result() - - -@overload -def get_last_completion_result() -> Any | None: ... - - -@overload -def get_last_completion_result(type_hint: type[ParamType]) -> ParamType | None: ... - - -def get_last_completion_result(type_hint: type | None = None) -> Any | None: - """Get the result of the last run of the workflow. This will be None if there was - no previous completion or the result was None. has_last_completion_result() - can be used to differentiate. - """ - return _Runtime.current().workflow_last_completion_result(type_hint) - - -def get_last_failure() -> BaseException | None: - """Get the last failure of the workflow if it has run previously.""" - return _Runtime.current().workflow_last_failure() - - -def set_current_details(description: str) -> None: - """Set the current details of the workflow which may appear in the UI/CLI. - Unlike static details set at start, this value can be updated throughout - the life of the workflow and is independent of the static details. - This can be in Temporal markdown format and can span multiple lines. - """ - _Runtime.current().workflow_set_current_details(description) - - -def metric_meter() -> temporalio.common.MetricMeter: - """Get the metric meter for the current workflow. - - This meter is replay safe which means that metrics will not be recorded - during replay. - - Returns: - Current metric meter for this workflow for recording metrics. - """ - return _Runtime.current().workflow_metric_meter() - - -def now() -> datetime: - """Current time from the workflow perspective. - - This is the workflow equivalent of :py:func:`datetime.now` with the - :py:attr:`timezone.utc` parameter. - - Returns: - UTC datetime for the current workflow time. The datetime does have UTC - set as the time zone. - """ - return datetime.fromtimestamp(time(), timezone.utc) - - -def patched(id: str) -> bool: - """Patch a workflow. - - When called, this will only return true if code should take the newer path - which means this is either not replaying or is replaying and has seen this - patch before. - - Use :py:func:`deprecate_patch` when all workflows are done and will never be - queried again. The old code path can be used at that time too. - - Args: - id: The identifier for this patch. This identifier may be used - repeatedly in the same workflow to represent the same patch - - Returns: - True if this should take the newer path, false if it should take the - older path. - """ - return _Runtime.current().workflow_patch(id, deprecated=False) - - -def payload_converter() -> temporalio.converter.PayloadConverter: - """Get the payload converter for the current workflow. - - The returned converter has :py:class:`temporalio.converter.WorkflowSerializationContext` set. - This is often used for dynamic workflows/signals/queries to convert - payloads. - """ - return _Runtime.current().workflow_payload_converter() - - -def random() -> Random: - """Get a deterministic pseudo-random number generator. - - Note, this random number generator is not cryptographically safe and should - not be used for security purposes. - - Returns: - The deterministically-seeded pseudo-random number generator. - """ - return _Runtime.current().workflow_random() - - -def random_seed() -> int: - """Get the current random seed value from core. - - This returns the seed value currently being used by the workflow's - deterministic random number generator. - - Returns: - The current random seed as an integer. - """ - return _Runtime.current().workflow_random_seed() - - -def register_random_seed_callback(callback: Callable[[int], None]) -> None: - """Register a callback to be notified when the random seed changes. - - The callback will be invoked whenever the workflow receives a new random - seed from the core. This is useful for maintaining external random number - generators that need to stay in sync with the workflow's randomness. - - Args: - callback: Function to be called with the new seed value when it changes. - """ - return _Runtime.current().workflow_register_random_seed_callback(callback) - - -def new_random() -> Random: - """Create a Random instance that automatically reseeds when the workflow seed changes. - - This creates a new Random instance that is initially seeded with the current - workflow seed, and automatically registers a callback to reseed itself - whenever the workflow receives a new seed from core. - - Returns: - A Random instance that stays synchronized with the workflow's randomness. - """ - current_seed = random_seed() - auto_random = Random(current_seed) - - def reseed_callback(new_seed: int) -> None: - auto_random.seed(new_seed) - - register_random_seed_callback(reseed_callback) - return auto_random - - -def time() -> float: - """Current seconds since the epoch from the workflow perspective. - - This is the workflow equivalent of :py:func:`time.time`. - - Returns: - Seconds since the epoch as a float. - """ - return time_ns() / 1e9 - - -def time_ns() -> int: - """Current nanoseconds since the epoch from the workflow perspective. - - This is the workflow equivalent of :py:func:`time.time_ns`. - - Returns: - Nanoseconds since the epoch - """ - return _Runtime.current().workflow_time_ns() - - -def upsert_search_attributes( - attributes: ( - temporalio.common.SearchAttributes - | Sequence[temporalio.common.SearchAttributeUpdate] - ), -) -> None: - """Upsert search attributes for this workflow. - - Args: - attributes: The attributes to set. This should be a sequence of - updates (i.e. values created via value_set and value_unset calls on - search attribute keys). The dictionary form of attributes is - DEPRECATED and if used, result in invalid key types on the - typed_search_attributes property in the info. - """ - if not attributes: - return - temporalio.common._warn_on_deprecated_search_attributes(attributes) - _Runtime.current().workflow_upsert_search_attributes(attributes) - - -# Needs to be defined here to avoid a circular import -@runtime_checkable -class UpdateMethodMultiParam(Protocol[MultiParamSpec, ProtocolReturnType]): - """Decorated workflow update functions implement this.""" - - _defn: temporalio.workflow._UpdateDefinition - - def __call__( - self, *args: MultiParamSpec.args, **kwargs: MultiParamSpec.kwargs - ) -> ProtocolReturnType | Awaitable[ProtocolReturnType]: - """Generic callable type callback.""" - ... - - def validator( - self, vfunc: Callable[MultiParamSpec, None] - ) -> Callable[MultiParamSpec, None]: - """Use to decorate a function to validate the arguments passed to the update handler.""" - ... - - -@overload -def update( - fn: Callable[MultiParamSpec, Awaitable[ReturnType]], -) -> UpdateMethodMultiParam[MultiParamSpec, ReturnType]: ... - - -@overload -def update( - fn: Callable[MultiParamSpec, ReturnType], -) -> UpdateMethodMultiParam[MultiParamSpec, ReturnType]: ... - - -@overload -def update( - *, - unfinished_policy: HandlerUnfinishedPolicy = HandlerUnfinishedPolicy.WARN_AND_ABANDON, - description: str | None = None, -) -> Callable[ - [Callable[MultiParamSpec, ReturnType]], - UpdateMethodMultiParam[MultiParamSpec, ReturnType], -]: ... - - -@overload -def update( - *, - name: str, - unfinished_policy: HandlerUnfinishedPolicy = HandlerUnfinishedPolicy.WARN_AND_ABANDON, - description: str | None = None, -) -> Callable[ - [Callable[MultiParamSpec, ReturnType]], - UpdateMethodMultiParam[MultiParamSpec, ReturnType], -]: ... - - -@overload -def update( - *, - dynamic: Literal[True], - unfinished_policy: HandlerUnfinishedPolicy = HandlerUnfinishedPolicy.WARN_AND_ABANDON, - description: str | None = None, -) -> Callable[ - [Callable[MultiParamSpec, ReturnType]], - UpdateMethodMultiParam[MultiParamSpec, ReturnType], -]: ... - - -def update( - fn: CallableSyncOrAsyncType | None = None, # type: ignore[reportInvalidTypeVarUse] - *, - name: str | None = None, - dynamic: bool | None = False, - unfinished_policy: HandlerUnfinishedPolicy = HandlerUnfinishedPolicy.WARN_AND_ABANDON, - description: str | None = None, -) -> ( - UpdateMethodMultiParam[MultiParamSpec, ReturnType] - | Callable[ - [Callable[MultiParamSpec, ReturnType]], - UpdateMethodMultiParam[MultiParamSpec, ReturnType], - ] -): - """Decorator for a workflow update handler method. - - This is used on any async or non-async method that you wish to be called upon - receiving an update. If a function overrides one with this decorator, it too - must be decorated. - - You may also optionally define a validator method that will be called before - this handler you have applied this decorator to. You can specify the validator - with ``@update_handler_function_name.validator``. - - Update methods can only have positional parameters. Best practice for - non-dynamic update methods is to only take a single object/dataclass - argument that can accept more fields later if needed. The handler may return - a serializable value which will be sent back to the caller of the update. - - Args: - fn: The function to decorate. - name: Update name. Defaults to method ``__name__``. Cannot be present - when ``dynamic`` is present. - dynamic: If true, this handles all updates not otherwise handled. The - parameters of the method must be self, a string name, and a - ``*args`` positional varargs. Cannot be present when ``name`` is - present. - unfinished_policy: Actions taken if a workflow terminates with - a running instance of this handler. - description: A short description of the update that may appear in the UI/CLI. - """ - - def decorator( - name: str | None, - unfinished_policy: HandlerUnfinishedPolicy, - fn: CallableSyncOrAsyncType, - ) -> CallableSyncOrAsyncType: - if not name and not dynamic: - name = fn.__name__ - defn = _UpdateDefinition( - name=name, - fn=fn, - is_method=True, - unfinished_policy=unfinished_policy, - description=description, - ) - if defn.dynamic_vararg: - raise RuntimeError( - "Dynamic updates do not support a vararg third param, use Sequence[RawValue]", - ) - setattr(fn, "_defn", defn) - setattr(fn, "validator", partial(_update_validator, defn)) - return fn - - if not fn: - if name is not None and dynamic: - raise RuntimeError("Cannot provide name and dynamic boolean") - return partial(decorator, name, unfinished_policy) # type: ignore[reportReturnType, return-value] - else: - return decorator(fn.__name__, unfinished_policy, fn) # type: ignore[reportReturnType, return-value] - - -def _update_validator( - update_def: _UpdateDefinition, fn: Callable[..., None] | None = None -) -> Callable[..., None] | None: - """Decorator for a workflow update validator method.""" - if fn is not None: - update_def.set_validator(fn) - return fn - - -def uuid4() -> uuid.UUID: - """Get a new, determinism-safe v4 UUID based on :py:func:`random`. - - Note, this UUID is not cryptographically safe and should not be used for - security purposes. - - Returns: - A deterministically-seeded v4 UUID. - """ - return uuid.UUID(bytes=random().getrandbits(16 * 8).to_bytes(16, "big"), version=4) - - -async def sleep(duration: float | timedelta, *, summary: str | None = None) -> None: - """Sleep for the given duration. - - Args: - duration: Duration to sleep in seconds or as a timedelta. - summary: A single-line fixed summary for this timer that may appear in UI/CLI. - This can be in single-line Temporal markdown format. - """ - await _Runtime.current().workflow_sleep( - duration=( - duration.total_seconds() if isinstance(duration, timedelta) else duration - ), - summary=summary, - ) - - -async def wait_condition( - fn: Callable[[], bool], - *, - timeout: timedelta | float | None = None, - timeout_summary: str | None = None, -) -> None: - """Wait on a callback to become true. - - This function returns when the callback returns true (invoked each loop - iteration) or the timeout has been reached. - - Args: - fn: Non-async callback that accepts no parameters and returns a boolean. - timeout: Optional number of seconds to wait until throwing - :py:class:`asyncio.TimeoutError`. - timeout_summary: Optional simple string identifying the timer (created if ``timeout`` is - present) that may be visible in UI/CLI. While it can be normal text, it is best to treat - as a timer ID. - """ - await _Runtime.current().workflow_wait_condition( - fn, - timeout=timeout.total_seconds() if isinstance(timeout, timedelta) else timeout, - timeout_summary=timeout_summary, - ) - - -_sandbox_unrestricted = threading.local() -_in_sandbox = threading.local() -_imports_passed_through = threading.local() -_sandbox_import_notification_policy_override = threading.local() - - -class SandboxImportNotificationPolicy(Flag): - """Defines the behavior taken when modules are imported into the sandbox after the workflow is initially loaded or unintentionally missing from the passthrough list.""" - - SILENT = auto() - """Allow imports that do not violate sandbox restrictions and no warnings are generated.""" - WARN_ON_DYNAMIC_IMPORT = auto() - """Allows dynamic imports that do not violate sandbox restrictions but issues a warning when an import is triggered in the sandbox after initial workflow load.""" - WARN_ON_UNINTENTIONAL_PASSTHROUGH = auto() - """Allows imports that do not violate sandbox restrictions but issues a warning when an import is triggered in the sandbox that was unintentionally passed through.""" - RAISE_ON_UNINTENTIONAL_PASSTHROUGH = auto() - """Raise an error when an import is triggered in the sandbox that was unintentionally passed through.""" - - -class unsafe: - """Contains static methods that should not normally be called during - workflow execution except in advanced cases. - """ - - def __init__(self) -> None: # noqa: D107 - raise NotImplementedError - - @staticmethod - def in_sandbox() -> bool: - """Whether the code is executing on a sandboxed thread. - - Returns: - True if the code is executing in the sandbox thread. - """ - return getattr(_in_sandbox, "value", False) - - @staticmethod - def _set_in_sandbox(v: bool) -> None: - _in_sandbox.value = v - - @staticmethod - def is_replaying() -> bool: - """Whether the workflow is currently replaying. - - This includes queries and update validators that occur during replay. - - Returns: - True if the workflow is currently replaying - """ - return _Runtime.current().workflow_is_replaying() - - @staticmethod - def is_replaying_history_events() -> bool: - """Whether the workflow is replaying history events. - - This excludes queries and update validators, which are live operations. - - Returns: - True if replaying history events, False otherwise. - """ - return _Runtime.current().workflow_is_replaying_history_events() - - @staticmethod - def is_read_only() -> bool: - """Whether the workflow is currently in read-only mode. - - Read-only mode occurs during queries and update validators where - side effects are not allowed. - - Returns: - True if the workflow is in read-only mode, False otherwise. - """ - return _Runtime.current().workflow_is_read_only() - - @staticmethod - def is_sandbox_unrestricted() -> bool: - """Whether the current block of code is not restricted via sandbox. - - Returns: - True if the current code is not restricted in the sandbox. - """ - # Activations happen in different threads than init and possibly the - # local hasn't been initialized in _that_ thread, so we allow unset here - # instead of just setting value = False globally. - return getattr(_sandbox_unrestricted, "value", False) - - @staticmethod - @contextmanager - def sandbox_unrestricted() -> Iterator[None]: - """A context manager to run code without sandbox restrictions.""" - # Only apply if not already applied. Nested calls just continue - # unrestricted. - if unsafe.is_sandbox_unrestricted(): - yield None - return - _sandbox_unrestricted.value = True - try: - yield None - finally: - _sandbox_unrestricted.value = False - - @staticmethod - def is_imports_passed_through() -> bool: - """Whether the current block of code is in - :py:meth:imports_passed_through. - - Returns: - True if the current code's imports will be passed through - """ - # See comment in is_sandbox_unrestricted for why we allow unset instead - # of just global false. - return getattr(_imports_passed_through, "value", False) - - @staticmethod - @contextmanager - def imports_passed_through() -> Iterator[None]: - """Context manager to mark all imports that occur within it as passed - through (meaning not reloaded by the sandbox). - """ - # Only apply if not already applied. Nested calls just continue - # passed through. - if unsafe.is_imports_passed_through(): - yield None - return - _imports_passed_through.value = True - try: - yield None - finally: - _imports_passed_through.value = False - - @staticmethod - def current_import_notification_policy_override() -> ( - SandboxImportNotificationPolicy | None - ): - """Gets the current import notification policy override if one is set.""" - applied_policy = getattr( - _sandbox_import_notification_policy_override, - "value", - None, - ) - return applied_policy - - @staticmethod - @contextmanager - def sandbox_import_notification_policy( - policy: SandboxImportNotificationPolicy, - ) -> Iterator[None]: - """Context manager to apply the given import notification policy.""" - original_policy = _sandbox_import_notification_policy_override.value = getattr( - _sandbox_import_notification_policy_override, - "value", - None, - ) - _sandbox_import_notification_policy_override.value = policy - try: - yield None - finally: - _sandbox_import_notification_policy_override.value = original_policy - - -def _build_log_context( - workflow_details: Mapping[str, Any] | None, - update_details: Mapping[str, Any] | None = None, - *, - workflow_info_on_message: bool = True, - workflow_info_on_extra: bool = True, - full_workflow_info: Info | None = None, -) -> tuple[dict[str, Any], dict[str, Any]]: - """Build the msg_extra suffix and extra dict entries for a temporal log record. - - Returns: - (msg_extra, extra) where msg_extra should be appended to the log message - and extra should be merged into the log record's extra dict. - """ - msg_extra: dict[str, Any] = {} - extra: dict[str, Any] = {} - - if workflow_details is not None: - if workflow_info_on_message: - msg_extra.update(workflow_details) - if workflow_info_on_extra: - extra["temporal_workflow"] = dict(workflow_details) - - if update_details is not None: - if workflow_info_on_message: - msg_extra.update(update_details) - if workflow_info_on_extra: - extra.setdefault("temporal_workflow", {}).update(update_details) - - if full_workflow_info is not None: - extra["workflow_info"] = full_workflow_info - - return msg_extra, extra - - -class LoggerAdapter(logging.LoggerAdapter): - """Adapter that adds details to the log about the running workflow. - - Attributes: - workflow_info_on_message: Boolean for whether a string representation of - a dict of some workflow info will be appended to each message. - Default is True. - workflow_info_on_extra: Boolean for whether a ``temporal_workflow`` - dictionary value will be added to the ``extra`` dictionary with some - workflow info, making it present on the ``LogRecord.__dict__`` for - use by others. Default is True. - full_workflow_info_on_extra: Boolean for whether a ``workflow_info`` - value will be added to the ``extra`` dictionary with the entire - workflow info, making it present on the ``LogRecord.__dict__`` for - use by others. Default is False. - log_during_replay: Boolean for whether logs should occur during replay. - Default is False. - - Values added to ``extra`` are merged with the ``extra`` dictionary from a - logging call, with values from the logging call taking precedence. I.e. the - behavior is that of ``merge_extra=True`` in Python >= 3.13. - """ - - def __init__(self, logger: logging.Logger, extra: Mapping[str, Any] | None) -> None: - """Create the logger adapter.""" - super().__init__(logger, extra or {}) - self.workflow_info_on_message = True - self.workflow_info_on_extra = True - self.full_workflow_info_on_extra = False - self.log_during_replay = False - self.disable_sandbox = False - - def process( - self, msg: Any, kwargs: MutableMapping[str, Any] - ) -> tuple[Any, MutableMapping[str, Any]]: - """Override to add workflow details.""" - msg_extra: dict[str, Any] = {} - extra: dict[str, Any] = {} - - if ( - self.workflow_info_on_message - or self.workflow_info_on_extra - or self.full_workflow_info_on_extra - ): - runtime = _Runtime.maybe_current() - update_info = current_update_info() - msg_extra, extra = _build_log_context( - runtime.logger_details if runtime else None, - update_info._logger_details if update_info else None, - workflow_info_on_message=self.workflow_info_on_message, - workflow_info_on_extra=self.workflow_info_on_extra, - full_workflow_info=runtime.workflow_info() - if runtime and self.full_workflow_info_on_extra - else None, - ) - - kwargs["extra"] = {**extra, **(kwargs.get("extra") or {})} - if msg_extra: - msg = f"{msg} ({msg_extra})" - return msg, kwargs - - def log( - self, - level: int, - msg: object, - *args: Any, - stacklevel: int = 1, - **kwargs: Any, - ): - """Override to potentially disable the sandbox.""" - if sys.version_info < (3, 11) and stacklevel == 1: - # An additional stacklevel is needed on 3.10 because it doesn't skip internal frames until after stacklevel - # is decremented, so it needs an additional stacklevel to skip the internal frame. - stacklevel += 1 # type: ignore[reportUnreachable] - stacklevel += 1 - if self.disable_sandbox: - with unsafe.sandbox_unrestricted(): - with unsafe.imports_passed_through(): - super().log(level, msg, *args, stacklevel=stacklevel, **kwargs) - else: - super().log(level, msg, *args, stacklevel=stacklevel, **kwargs) - - def isEnabledFor(self, level: int) -> bool: - """Override to ignore replay logs.""" - if not self.log_during_replay and unsafe.is_replaying_history_events(): - return False - return super().isEnabledFor(level) - - @property - def base_logger(self) -> logging.Logger: - """Underlying logger usable for actions such as adding - handlers/formatters. - """ - return self.logger - - def unsafe_disable_sandbox(self, value: bool = True): - """Disable the sandbox during log processing. - Can be turned back on with unsafe_disable_sandbox(False). - """ - self.disable_sandbox = value - - -logger = LoggerAdapter(logging.getLogger(__name__), None) -"""Logger that will have contextual workflow details embedded. - -Logs are skipped during replay by default. -""" - - -@dataclass(frozen=True) -class _Definition: - name: str | None - cls: type - run_fn: Callable[..., Awaitable] - signals: Mapping[str | None, _SignalDefinition] - queries: Mapping[str | None, _QueryDefinition] - updates: Mapping[str | None, _UpdateDefinition] - sandboxed: bool - failure_exception_types: Sequence[type[BaseException]] - # Types loaded on post init if both are None - arg_types: list[type] | None = None - ret_type: type | None = None - versioning_behavior: temporalio.common.VersioningBehavior | None = None - dynamic_config_fn: Callable[..., DynamicWorkflowConfig] | None = None - - @staticmethod - def from_class(cls: type) -> _Definition | None: # type: ignore[reportSelfClsParameterName] - # We make sure to only return it if it's on _this_ class - defn = getattr(cls, "__temporal_workflow_definition", None) - if defn and defn.cls == cls: - return defn - return None - - @staticmethod - def must_from_class(cls: type) -> _Definition: # type: ignore[reportSelfClsParameterName] - ret = _Definition.from_class(cls) - if ret: - return ret - cls_name = getattr(cls, "__name__", "") - raise ValueError( - f"Workflow {cls_name} missing attributes, was it decorated with @workflow.defn?" - ) - - @staticmethod - def from_run_fn(fn: Callable[..., Awaitable[Any]]) -> _Definition | None: - return getattr(fn, "__temporal_workflow_definition", None) - - @staticmethod - def must_from_run_fn(fn: Callable[..., Awaitable[Any]]) -> _Definition: - ret = _Definition.from_run_fn(fn) - if ret: - return ret - fn_name = getattr(fn, "__qualname__", "") - raise ValueError( - f"Function {fn_name} missing attributes, was it decorated with @workflow.run and was its class decorated with @workflow.defn?" - ) - - @classmethod - def get_name_and_result_type( - cls, name_or_run_fn: str | Callable[..., Awaitable[Any]] - ) -> tuple[str, type | None]: - if isinstance(name_or_run_fn, str): - return name_or_run_fn, None - elif callable(name_or_run_fn): - defn = cls.must_from_run_fn(name_or_run_fn) - if not defn.name: - raise ValueError("Cannot invoke dynamic workflow explicitly") - return defn.name, defn.ret_type - else: - raise TypeError("Workflow must be a string or callable") # type: ignore[reportUnreachable] - - @staticmethod - def _apply_to_class( - cls: type, # type: ignore[reportSelfClsParameterName] - *, - workflow_name: str | None, - sandboxed: bool, - failure_exception_types: Sequence[type[BaseException]], - versioning_behavior: temporalio.common.VersioningBehavior, - ) -> None: - # Check it's not being doubly applied - if _Definition.from_class(cls): - raise ValueError("Class already contains workflow definition") - issues: list[str] = [] - - # Collect run fn and all signal/query/update fns - init_fn: Callable[..., None] | None = None - run_fn: Callable[..., Awaitable[Any]] | None = None - dynamic_config_fn: Callable[..., DynamicWorkflowConfig] | None = None - seen_run_attr = False - signals: dict[str | None, _SignalDefinition] = {} - queries: dict[str | None, _QueryDefinition] = {} - updates: dict[str | None, _UpdateDefinition] = {} - for name, member in inspect.getmembers(cls): - if hasattr(member, "__temporal_workflow_run"): - seen_run_attr = True - if not _is_unbound_method_on_cls(member, cls): - issues.append( - f"@workflow.run method {name} must be defined on {cls.__qualname__}" - ) - elif run_fn is not None: - issues.append( - f"Multiple @workflow.run methods found (at least on {name} and {run_fn.__name__})" - ) - else: - # We can guarantee the @workflow.run decorator did - # validation of the function itself - run_fn = member - elif hasattr(member, "__temporal_signal_definition"): - signal_defn = cast( - _SignalDefinition, getattr(member, "__temporal_signal_definition") - ) - if signal_defn.name in signals: - defn_name = signal_defn.name or "" - # TODO(cretz): Remove cast when https://github.com/python/mypy/issues/5485 fixed - other_fn = cast(Callable, signals[signal_defn.name].fn) - issues.append( - f"Multiple signal methods found for {defn_name} " - f"(at least on {name} and {other_fn.__name__})" - ) - else: - signals[signal_defn.name] = signal_defn - elif hasattr(member, "__temporal_query_definition"): - query_defn = cast( - _QueryDefinition, getattr(member, "__temporal_query_definition") - ) - if query_defn.name in queries: - defn_name = query_defn.name or "" - issues.append( - f"Multiple query methods found for {defn_name} " - f"(at least on {name} and {queries[query_defn.name].fn.__name__})" - ) - else: - queries[query_defn.name] = query_defn - elif name == "__init__" and hasattr(member, "__temporal_workflow_init"): - init_fn = member - elif hasattr(member, "__temporal_workflow_dynamic_config"): - if workflow_name: - issues.append( - "@workflow.dynamic_config can only be used in dynamic workflows, but " - f"workflow class {workflow_name} ({cls.__name__}) is not dynamic" - ) - if dynamic_config_fn: - issues.append( - "@workflow.dynamic_config can only be defined once per workflow" - ) - dynamic_config_fn = member - elif isinstance(member, UpdateMethodMultiParam): - update_defn = member._defn - if update_defn.name in updates: - defn_name = update_defn.name or "" - issues.append( - f"Multiple update methods found for {defn_name} " - f"(at least on {name} and {updates[update_defn.name].fn.__name__})" - ) - elif update_defn.validator and not _parameters_identical_up_to_naming( - update_defn.fn, update_defn.validator - ): - issues.append( - f"Update validator method {update_defn.validator.__name__} parameters " - f"do not match update method {update_defn.fn.__name__} parameters" - ) - else: - updates[update_defn.name] = update_defn - - # Check base classes haven't defined things with different decorators - for base_cls in inspect.getmro(cls)[1:]: - for _, base_member in inspect.getmembers(base_cls): - # We only care about methods defined on this class - if not inspect.isfunction(base_member) or not _is_unbound_method_on_cls( - base_member, base_cls - ): - continue - if hasattr(base_member, "__temporal_workflow_run"): - seen_run_attr = True - if not run_fn or base_member.__name__ != run_fn.__name__: - issues.append( - f"@workflow.run defined on {base_member.__qualname__} but not on the override" - ) - elif hasattr(base_member, "__temporal_signal_definition"): - signal_defn = cast( - _SignalDefinition, - getattr(base_member, "__temporal_signal_definition"), - ) - if signal_defn.name not in signals: - issues.append( - f"@workflow.signal defined on {base_member.__qualname__} but not on the override" - ) - elif hasattr(base_member, "__temporal_query_definition"): - query_defn = cast( - _QueryDefinition, - getattr(base_member, "__temporal_query_definition"), - ) - if query_defn.name not in queries: - issues.append( - f"@workflow.query defined on {base_member.__qualname__} but not on the override" - ) - elif isinstance(base_member, UpdateMethodMultiParam): - update_defn = base_member._defn - if update_defn.name not in updates: - issues.append( - f"@workflow.update defined on {base_member.__qualname__} but not on the override" - ) - - if not seen_run_attr: - issues.append("Missing @workflow.run method") - if init_fn and run_fn: - if not _parameters_identical_up_to_naming(init_fn, run_fn): - issues.append( - "@workflow.init and @workflow.run method parameters do not match" - ) - if issues: - if len(issues) == 1: - raise ValueError(f"Invalid workflow class: {issues[0]}") - raise ValueError( - f"Invalid workflow class for {len(issues)} reasons: {', '.join(issues)}" - ) - - assert run_fn - assert seen_run_attr - defn = _Definition( - name=workflow_name, - cls=cls, - run_fn=run_fn, - signals=signals, - queries=queries, - updates=updates, - sandboxed=sandboxed, - failure_exception_types=failure_exception_types, - versioning_behavior=versioning_behavior, - dynamic_config_fn=dynamic_config_fn, - ) - setattr(cls, "__temporal_workflow_definition", defn) - setattr(run_fn, "__temporal_workflow_definition", defn) - - def __post_init__(self) -> None: - if self.arg_types is None and self.ret_type is None: - dynamic = self.name is None - arg_types, ret_type = temporalio.common._type_hints_from_func(self.run_fn) - # If dynamic, must be a sequence of raw values - if dynamic and ( - not arg_types - or len(arg_types) != 1 - or arg_types[0] != Sequence[temporalio.common.RawValue] - ): - raise TypeError( - "Dynamic workflow must accept a single Sequence[temporalio.common.RawValue]" - ) - object.__setattr__(self, "arg_types", arg_types) - object.__setattr__(self, "ret_type", ret_type) - - -def _parameters_identical_up_to_naming(fn1: Callable, fn2: Callable) -> bool: - """Return True if the functions have identical parameter lists, ignoring parameter names.""" - - def params(fn: Callable) -> list[inspect.Parameter]: - # Ignore name when comparing parameters (remaining fields are kind, - # default, and annotation). - return [p.replace(name="x") for p in inspect.signature(fn).parameters.values()] - - # We require that any type annotations present match exactly; i.e. we do - # not support any notion of subtype compatibility. - return params(fn1) == params(fn2) - - -# Async safe version of partial -def _bind_method(obj: Any, fn: Callable[..., Any]) -> Callable[..., Any]: - # Curry instance on the definition function since that represents an - # unbound method - if inspect.iscoroutinefunction(fn): - # We cannot use functools.partial here because in <= 3.7 that isn't - # considered an inspect.iscoroutinefunction - fn = cast(Callable[..., Awaitable[Any]], fn) - - async def with_object(*args: Any, **kwargs: Any) -> Any: - return await fn(obj, *args, **kwargs) - - return with_object - return partial(fn, obj) - - -# Returns true if normal form, false if vararg form -def _assert_dynamic_handler_args( - fn: Callable, arg_types: list[type] | None, is_method: bool -) -> bool: - # Dynamic query/signal/update must have three args: self, name, and - # Sequence[RawValue]. An older form accepted varargs for the third param for signals/queries so - # we will too (but will warn in the signal/query code). - params = list(inspect.signature(fn).parameters.values()) - total_expected_params = 3 if is_method else 2 - if ( - len(params) == total_expected_params - and params[-2].kind is inspect.Parameter.POSITIONAL_OR_KEYWORD - and params[-1].kind is inspect.Parameter.VAR_POSITIONAL - ): - # Old var-arg form - return False - if ( - not arg_types - or len(arg_types) != 2 - or arg_types[0] != str - or ( - arg_types[1] != Sequence[temporalio.common.RawValue] - and arg_types[1] != typing.Sequence[temporalio.common.RawValue] # type: ignore[reportDeprecated] - ) - ): - raise RuntimeError( - "Dynamic handler must have 3 arguments: self, str, and Sequence[temporalio.common.RawValue]" - ) - return True - - -@dataclass(frozen=True) -class _SignalDefinition: - # None if dynamic - name: str | None - fn: Callable[..., None | Awaitable[None]] - is_method: bool - unfinished_policy: HandlerUnfinishedPolicy = ( - HandlerUnfinishedPolicy.WARN_AND_ABANDON - ) - description: str | None = None - # Types loaded on post init if None - arg_types: list[type] | None = None - dynamic_vararg: bool = False - - @staticmethod - def from_fn(fn: Callable) -> _SignalDefinition | None: - return getattr(fn, "__temporal_signal_definition", None) - - @staticmethod - def must_name_from_fn_or_str(signal: str | Callable) -> str: - if callable(signal): - defn = _SignalDefinition.from_fn(signal) - if not defn: - raise RuntimeError( - f"Signal definition not found on {signal.__qualname__}, " - "is it decorated with @workflow.signal?" - ) - elif not defn.name: - raise RuntimeError("Cannot invoke dynamic signal definition") - # TODO(cretz): Check count/type of args at runtime? - return defn.name - return str(signal) - - def __post_init__(self) -> None: - if self.arg_types is None: - arg_types, _ = temporalio.common._type_hints_from_func(self.fn) - # If dynamic, assert it - if not self.name: - object.__setattr__( - self, - "dynamic_vararg", - not _assert_dynamic_handler_args( - self.fn, arg_types, self.is_method - ), - ) - object.__setattr__(self, "arg_types", arg_types) - - def bind_fn(self, obj: Any) -> Callable[..., Any]: - return _bind_method(obj, self.fn) - - -@dataclass(frozen=True) -class _QueryDefinition: - # None if dynamic - name: str | None - fn: Callable[..., Any] - is_method: bool - description: str | None = None - # Types loaded on post init if both are None - arg_types: list[type] | None = None - ret_type: type | None = None - dynamic_vararg: bool = False - - @staticmethod - def from_fn(fn: Callable) -> _QueryDefinition | None: - return getattr(fn, "__temporal_query_definition", None) - - def __post_init__(self) -> None: - if self.arg_types is None and self.ret_type is None: - arg_types, ret_type = temporalio.common._type_hints_from_func(self.fn) - # If dynamic, assert it - if not self.name: - object.__setattr__( - self, - "dynamic_vararg", - not _assert_dynamic_handler_args( - self.fn, arg_types, self.is_method - ), - ) - object.__setattr__(self, "arg_types", arg_types) - object.__setattr__(self, "ret_type", ret_type) - - def bind_fn(self, obj: Any) -> Callable[..., Any]: - return _bind_method(obj, self.fn) - - -@dataclass(frozen=True) -class _UpdateDefinition: - # None if dynamic - name: str | None - fn: Callable[..., Any | Awaitable[Any]] - is_method: bool - unfinished_policy: HandlerUnfinishedPolicy = ( - HandlerUnfinishedPolicy.WARN_AND_ABANDON - ) - description: str | None = None - # Types loaded on post init if None - arg_types: list[type] | None = None - ret_type: type | None = None - validator: Callable[..., None] | None = None - dynamic_vararg: bool = False - - def __post_init__(self) -> None: - if self.arg_types is None: - arg_types, ret_type = temporalio.common._type_hints_from_func(self.fn) - # Disallow dynamic varargs - if not self.name and not _assert_dynamic_handler_args( - self.fn, arg_types, self.is_method - ): - raise RuntimeError( - "Dynamic updates do not support a vararg third param, use Sequence[RawValue]", - ) - object.__setattr__(self, "arg_types", arg_types) - object.__setattr__(self, "ret_type", ret_type) - - def bind_fn(self, obj: Any) -> Callable[..., Any]: - return _bind_method(obj, self.fn) - - def bind_validator(self, obj: Any) -> Callable[..., Any]: - if self.validator is not None: - return _bind_method(obj, self.validator) - return lambda *args, **kwargs: None - - def set_validator(self, validator: Callable[..., None]) -> None: - if self.validator: - raise RuntimeError(f"Validator already set for update {self.name}") - object.__setattr__(self, "validator", validator) - - @classmethod - def get_name_and_result_type( - cls, - name_or_update_fn: str | Callable[..., Any], - ) -> tuple[str, type | None]: - if isinstance(name_or_update_fn, temporalio.workflow.UpdateMethodMultiParam): - defn = name_or_update_fn._defn - if not defn.name: - raise RuntimeError("Cannot invoke dynamic update definition") - # TODO(cretz): Check count/type of args at runtime? - return defn.name, defn.ret_type - else: - return str(name_or_update_fn), None - - -# See https://mypy.readthedocs.io/en/latest/runtime_troubles.html#using-classes-that-are-generic-in-stubs-but-not-at-runtime -if TYPE_CHECKING: - - class _AsyncioTask(asyncio.Task[AnyType]): - pass - -else: - # TODO: inherited classes should be other way around? - class _AsyncioTask(Generic[AnyType], asyncio.Task): - pass - - -class ActivityHandle(_AsyncioTask[ReturnType]): # type: ignore[type-var] - """Handle returned from :py:func:`start_activity` and - :py:func:`start_local_activity`. - - This extends :py:class:`asyncio.Task` and supports all task features. - """ - - pass - - -class ActivityCancellationType(IntEnum): - """How an activity cancellation should be handled.""" - - TRY_CANCEL = int( - temporalio.bridge.proto.workflow_commands.ActivityCancellationType.TRY_CANCEL - ) - WAIT_CANCELLATION_COMPLETED = int( - temporalio.bridge.proto.workflow_commands.ActivityCancellationType.WAIT_CANCELLATION_COMPLETED - ) - ABANDON = int( - temporalio.bridge.proto.workflow_commands.ActivityCancellationType.ABANDON - ) - - -class ActivityConfig(TypedDict, total=False): - """TypedDict of config that can be used for :py:func:`start_activity` and - :py:func:`execute_activity`. - """ - - task_queue: str | None - schedule_to_close_timeout: timedelta | None - schedule_to_start_timeout: timedelta | None - start_to_close_timeout: timedelta | None - heartbeat_timeout: timedelta | None - retry_policy: temporalio.common.RetryPolicy | None - cancellation_type: ActivityCancellationType - activity_id: str | None - versioning_intent: VersioningIntent | None - summary: str | None - priority: temporalio.common.Priority - - -# Overload for async no-param activity -@overload -def start_activity( - activity: CallableAsyncNoParam[ReturnType], - *, - task_queue: str | None = None, - schedule_to_close_timeout: timedelta | None = None, - schedule_to_start_timeout: timedelta | None = None, - start_to_close_timeout: timedelta | None = None, - heartbeat_timeout: timedelta | None = None, - retry_policy: temporalio.common.RetryPolicy | None = None, - cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, - activity_id: str | None = None, - versioning_intent: VersioningIntent | None = None, - summary: str | None = None, - priority: temporalio.common.Priority = temporalio.common.Priority.default, -) -> ActivityHandle[ReturnType]: ... - - -# Overload for sync no-param activity -@overload -def start_activity( - activity: CallableSyncNoParam[ReturnType], - *, - task_queue: str | None = None, - schedule_to_close_timeout: timedelta | None = None, - schedule_to_start_timeout: timedelta | None = None, - start_to_close_timeout: timedelta | None = None, - heartbeat_timeout: timedelta | None = None, - retry_policy: temporalio.common.RetryPolicy | None = None, - cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, - activity_id: str | None = None, - versioning_intent: VersioningIntent | None = None, - summary: str | None = None, - priority: temporalio.common.Priority = temporalio.common.Priority.default, -) -> ActivityHandle[ReturnType]: ... - - -# Overload for async single-param activity -@overload -def start_activity( - activity: CallableAsyncSingleParam[ParamType, ReturnType], - arg: ParamType, - *, - task_queue: str | None = None, - schedule_to_close_timeout: timedelta | None = None, - schedule_to_start_timeout: timedelta | None = None, - start_to_close_timeout: timedelta | None = None, - heartbeat_timeout: timedelta | None = None, - retry_policy: temporalio.common.RetryPolicy | None = None, - cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, - activity_id: str | None = None, - versioning_intent: VersioningIntent | None = None, - summary: str | None = None, - priority: temporalio.common.Priority = temporalio.common.Priority.default, -) -> ActivityHandle[ReturnType]: ... - - -# Overload for sync single-param activity -@overload -def start_activity( - activity: CallableSyncSingleParam[ParamType, ReturnType], - arg: ParamType, - *, - task_queue: str | None = None, - schedule_to_close_timeout: timedelta | None = None, - schedule_to_start_timeout: timedelta | None = None, - start_to_close_timeout: timedelta | None = None, - heartbeat_timeout: timedelta | None = None, - retry_policy: temporalio.common.RetryPolicy | None = None, - cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, - activity_id: str | None = None, - versioning_intent: VersioningIntent | None = None, - summary: str | None = None, - priority: temporalio.common.Priority = temporalio.common.Priority.default, -) -> ActivityHandle[ReturnType]: ... - - -# Overload for async multi-param activity -@overload -def start_activity( - activity: Callable[..., Awaitable[ReturnType]], - *, - args: Sequence[Any], - task_queue: str | None = None, - schedule_to_close_timeout: timedelta | None = None, - schedule_to_start_timeout: timedelta | None = None, - start_to_close_timeout: timedelta | None = None, - heartbeat_timeout: timedelta | None = None, - retry_policy: temporalio.common.RetryPolicy | None = None, - cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, - activity_id: str | None = None, - versioning_intent: VersioningIntent | None = None, - summary: str | None = None, - priority: temporalio.common.Priority = temporalio.common.Priority.default, -) -> ActivityHandle[ReturnType]: ... - - -# Overload for sync multi-param activity -@overload -def start_activity( - activity: Callable[..., ReturnType], - *, - args: Sequence[Any], - task_queue: str | None = None, - schedule_to_close_timeout: timedelta | None = None, - schedule_to_start_timeout: timedelta | None = None, - start_to_close_timeout: timedelta | None = None, - heartbeat_timeout: timedelta | None = None, - retry_policy: temporalio.common.RetryPolicy | None = None, - cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, - activity_id: str | None = None, - versioning_intent: VersioningIntent | None = None, - summary: str | None = None, - priority: temporalio.common.Priority = temporalio.common.Priority.default, -) -> ActivityHandle[ReturnType]: ... - - -# Overload for string-name activity -@overload -def start_activity( - activity: str, - arg: Any = temporalio.common._arg_unset, - *, - args: Sequence[Any] = [], - task_queue: str | None = None, - result_type: type | None = None, - schedule_to_close_timeout: timedelta | None = None, - schedule_to_start_timeout: timedelta | None = None, - start_to_close_timeout: timedelta | None = None, - heartbeat_timeout: timedelta | None = None, - retry_policy: temporalio.common.RetryPolicy | None = None, - cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, - activity_id: str | None = None, - versioning_intent: VersioningIntent | None = None, - summary: str | None = None, - priority: temporalio.common.Priority = temporalio.common.Priority.default, -) -> ActivityHandle[Any]: ... - - -def start_activity( - activity: Any, - arg: Any = temporalio.common._arg_unset, - *, - args: Sequence[Any] = [], - task_queue: str | None = None, - result_type: type | None = None, - schedule_to_close_timeout: timedelta | None = None, - schedule_to_start_timeout: timedelta | None = None, - start_to_close_timeout: timedelta | None = None, - heartbeat_timeout: timedelta | None = None, - retry_policy: temporalio.common.RetryPolicy | None = None, - cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, - activity_id: str | None = None, - versioning_intent: VersioningIntent | None = None, - summary: str | None = None, - priority: temporalio.common.Priority = temporalio.common.Priority.default, -) -> ActivityHandle[Any]: - """Start an activity and return its handle. - - At least one of ``schedule_to_close_timeout`` or ``start_to_close_timeout`` - must be present. - - Args: - activity: Activity name or function reference. - arg: Single argument to the activity. - args: Multiple arguments to the activity. Cannot be set if arg is. - task_queue: Task queue to run the activity on. Defaults to the current - workflow's task queue. - result_type: For string activities, this can set the specific result - type hint to deserialize into. - schedule_to_close_timeout: Max amount of time the activity can take from - first being scheduled to being completed before it times out. This - is inclusive of all retries. - schedule_to_start_timeout: Max amount of time the activity can take to - be started from first being scheduled. - start_to_close_timeout: Max amount of time a single activity run can - take from when it starts to when it completes. This is per retry. - heartbeat_timeout: How frequently an activity must invoke heartbeat - while running before it is considered timed out. - retry_policy: How an activity is retried on failure. If unset, a - server-defined default is used. Set maximum attempts to 1 to disable - retries. - cancellation_type: How the activity is treated when it is cancelled from - the workflow. - activity_id: Optional unique identifier for the activity. This is an - advanced setting that should not be set unless users are sure they - need to. Contact Temporal before setting this value. - versioning_intent: When using the Worker Versioning feature, specifies whether this Activity - should run on a worker with a compatible Build Id or not. - Deprecated: Use Worker Deployment versioning instead. - summary: A single-line fixed summary for this activity that may appear in UI/CLI. - This can be in single-line Temporal markdown format. - priority: Priority of the activity. - - Returns: - An activity handle to the activity which is an async task. - """ - return _Runtime.current().workflow_start_activity( - activity, - *temporalio.common._arg_or_args(arg, args), - task_queue=task_queue, - result_type=result_type, - schedule_to_close_timeout=schedule_to_close_timeout, - schedule_to_start_timeout=schedule_to_start_timeout, - start_to_close_timeout=start_to_close_timeout, - heartbeat_timeout=heartbeat_timeout, - retry_policy=retry_policy, - cancellation_type=cancellation_type, - activity_id=activity_id, - versioning_intent=versioning_intent, - summary=summary, - priority=priority, - ) - - -# Overload for async no-param activity -@overload -async def execute_activity( - activity: CallableAsyncNoParam[ReturnType], - *, - task_queue: str | None = None, - schedule_to_close_timeout: timedelta | None = None, - schedule_to_start_timeout: timedelta | None = None, - start_to_close_timeout: timedelta | None = None, - heartbeat_timeout: timedelta | None = None, - retry_policy: temporalio.common.RetryPolicy | None = None, - cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, - activity_id: str | None = None, - versioning_intent: VersioningIntent | None = None, - summary: str | None = None, - priority: temporalio.common.Priority = temporalio.common.Priority.default, -) -> ReturnType: ... - - -# Overload for sync no-param activity -@overload -async def execute_activity( - activity: CallableSyncNoParam[ReturnType], - *, - task_queue: str | None = None, - schedule_to_close_timeout: timedelta | None = None, - schedule_to_start_timeout: timedelta | None = None, - start_to_close_timeout: timedelta | None = None, - heartbeat_timeout: timedelta | None = None, - retry_policy: temporalio.common.RetryPolicy | None = None, - cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, - activity_id: str | None = None, - versioning_intent: VersioningIntent | None = None, - summary: str | None = None, - priority: temporalio.common.Priority = temporalio.common.Priority.default, -) -> ReturnType: ... - - -# Overload for async single-param activity -@overload -async def execute_activity( - activity: CallableAsyncSingleParam[ParamType, ReturnType], - arg: ParamType, - *, - task_queue: str | None = None, - schedule_to_close_timeout: timedelta | None = None, - schedule_to_start_timeout: timedelta | None = None, - start_to_close_timeout: timedelta | None = None, - heartbeat_timeout: timedelta | None = None, - retry_policy: temporalio.common.RetryPolicy | None = None, - cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, - activity_id: str | None = None, - versioning_intent: VersioningIntent | None = None, - summary: str | None = None, - priority: temporalio.common.Priority = temporalio.common.Priority.default, -) -> ReturnType: ... - - -# Overload for sync single-param activity -@overload -async def execute_activity( - activity: CallableSyncSingleParam[ParamType, ReturnType], - arg: ParamType, - *, - task_queue: str | None = None, - schedule_to_close_timeout: timedelta | None = None, - schedule_to_start_timeout: timedelta | None = None, - start_to_close_timeout: timedelta | None = None, - heartbeat_timeout: timedelta | None = None, - retry_policy: temporalio.common.RetryPolicy | None = None, - cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, - activity_id: str | None = None, - versioning_intent: VersioningIntent | None = None, - summary: str | None = None, - priority: temporalio.common.Priority = temporalio.common.Priority.default, -) -> ReturnType: ... - - -# Overload for async multi-param activity -@overload -async def execute_activity( - activity: Callable[..., Awaitable[ReturnType]], - *, - args: Sequence[Any], - task_queue: str | None = None, - schedule_to_close_timeout: timedelta | None = None, - schedule_to_start_timeout: timedelta | None = None, - start_to_close_timeout: timedelta | None = None, - heartbeat_timeout: timedelta | None = None, - retry_policy: temporalio.common.RetryPolicy | None = None, - cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, - activity_id: str | None = None, - versioning_intent: VersioningIntent | None = None, - summary: str | None = None, - priority: temporalio.common.Priority = temporalio.common.Priority.default, -) -> ReturnType: ... - - -# Overload for sync multi-param activity -@overload -async def execute_activity( - activity: Callable[..., ReturnType], - *, - args: Sequence[Any], - task_queue: str | None = None, - schedule_to_close_timeout: timedelta | None = None, - schedule_to_start_timeout: timedelta | None = None, - start_to_close_timeout: timedelta | None = None, - heartbeat_timeout: timedelta | None = None, - retry_policy: temporalio.common.RetryPolicy | None = None, - cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, - activity_id: str | None = None, - versioning_intent: VersioningIntent | None = None, - summary: str | None = None, - priority: temporalio.common.Priority = temporalio.common.Priority.default, -) -> ReturnType: ... - - -# Overload for string-name activity -@overload -async def execute_activity( - activity: str, - arg: Any = temporalio.common._arg_unset, - *, - args: Sequence[Any] = [], - task_queue: str | None = None, - result_type: type | None = None, - schedule_to_close_timeout: timedelta | None = None, - schedule_to_start_timeout: timedelta | None = None, - start_to_close_timeout: timedelta | None = None, - heartbeat_timeout: timedelta | None = None, - retry_policy: temporalio.common.RetryPolicy | None = None, - cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, - activity_id: str | None = None, - versioning_intent: VersioningIntent | None = None, - summary: str | None = None, - priority: temporalio.common.Priority = temporalio.common.Priority.default, -) -> Any: ... - - -async def execute_activity( - activity: Any, - arg: Any = temporalio.common._arg_unset, - *, - args: Sequence[Any] = [], - task_queue: str | None = None, - result_type: type | None = None, - schedule_to_close_timeout: timedelta | None = None, - schedule_to_start_timeout: timedelta | None = None, - start_to_close_timeout: timedelta | None = None, - heartbeat_timeout: timedelta | None = None, - retry_policy: temporalio.common.RetryPolicy | None = None, - cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, - activity_id: str | None = None, - versioning_intent: VersioningIntent | None = None, - summary: str | None = None, - priority: temporalio.common.Priority = temporalio.common.Priority.default, -) -> Any: - """Start an activity and wait for completion. - - This is a shortcut for ``await`` :py:meth:`start_activity`. - """ - # We call the runtime directly instead of top-level start_activity to ensure - # we don't miss new parameters - return await _Runtime.current().workflow_start_activity( - activity, - *temporalio.common._arg_or_args(arg, args), - task_queue=task_queue, - result_type=result_type, - schedule_to_close_timeout=schedule_to_close_timeout, - schedule_to_start_timeout=schedule_to_start_timeout, - start_to_close_timeout=start_to_close_timeout, - heartbeat_timeout=heartbeat_timeout, - retry_policy=retry_policy, - cancellation_type=cancellation_type, - activity_id=activity_id, - versioning_intent=versioning_intent, - summary=summary, - priority=priority, - ) - - -# Overload for async no-param activity -@overload -def start_activity_class( - activity: type[CallableAsyncNoParam[ReturnType]], - *, - task_queue: str | None = None, - schedule_to_close_timeout: timedelta | None = None, - schedule_to_start_timeout: timedelta | None = None, - start_to_close_timeout: timedelta | None = None, - heartbeat_timeout: timedelta | None = None, - retry_policy: temporalio.common.RetryPolicy | None = None, - cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, - activity_id: str | None = None, - versioning_intent: VersioningIntent | None = None, - summary: str | None = None, - priority: temporalio.common.Priority = temporalio.common.Priority.default, -) -> ActivityHandle[ReturnType]: ... - - -# Overload for sync no-param activity -@overload -def start_activity_class( - activity: type[CallableSyncNoParam[ReturnType]], - *, - task_queue: str | None = None, - schedule_to_close_timeout: timedelta | None = None, - schedule_to_start_timeout: timedelta | None = None, - start_to_close_timeout: timedelta | None = None, - heartbeat_timeout: timedelta | None = None, - retry_policy: temporalio.common.RetryPolicy | None = None, - cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, - activity_id: str | None = None, - versioning_intent: VersioningIntent | None = None, - summary: str | None = None, - priority: temporalio.common.Priority = temporalio.common.Priority.default, -) -> ActivityHandle[ReturnType]: ... - - -# Overload for async single-param activity -@overload -def start_activity_class( - activity: type[CallableAsyncSingleParam[ParamType, ReturnType]], - arg: ParamType, - *, - task_queue: str | None = None, - schedule_to_close_timeout: timedelta | None = None, - schedule_to_start_timeout: timedelta | None = None, - start_to_close_timeout: timedelta | None = None, - heartbeat_timeout: timedelta | None = None, - retry_policy: temporalio.common.RetryPolicy | None = None, - cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, - activity_id: str | None = None, - versioning_intent: VersioningIntent | None = None, - summary: str | None = None, - priority: temporalio.common.Priority = temporalio.common.Priority.default, -) -> ActivityHandle[ReturnType]: ... - - -# Overload for sync single-param activity -@overload -def start_activity_class( - activity: type[CallableSyncSingleParam[ParamType, ReturnType]], - arg: ParamType, - *, - task_queue: str | None = None, - schedule_to_close_timeout: timedelta | None = None, - schedule_to_start_timeout: timedelta | None = None, - start_to_close_timeout: timedelta | None = None, - heartbeat_timeout: timedelta | None = None, - retry_policy: temporalio.common.RetryPolicy | None = None, - cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, - activity_id: str | None = None, - versioning_intent: VersioningIntent | None = None, - summary: str | None = None, - priority: temporalio.common.Priority = temporalio.common.Priority.default, -) -> ActivityHandle[ReturnType]: ... - - -# Overload for async multi-param activity -@overload -def start_activity_class( - activity: type[Callable[..., Awaitable[ReturnType]]], # type: ignore[reportOverlappingOverload] - *, - args: Sequence[Any], - task_queue: str | None = None, - schedule_to_close_timeout: timedelta | None = None, - schedule_to_start_timeout: timedelta | None = None, - start_to_close_timeout: timedelta | None = None, - heartbeat_timeout: timedelta | None = None, - retry_policy: temporalio.common.RetryPolicy | None = None, - cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, - activity_id: str | None = None, - versioning_intent: VersioningIntent | None = None, - summary: str | None = None, - priority: temporalio.common.Priority = temporalio.common.Priority.default, -) -> ActivityHandle[ReturnType]: ... - - -# Overload for sync multi-param activity -@overload -def start_activity_class( # type: ignore[reportOverlappingOverload] - activity: type[Callable[..., ReturnType]], # type: ignore[reportOverlappingOverload] - *, - args: Sequence[Any], - task_queue: str | None = None, - schedule_to_close_timeout: timedelta | None = None, - schedule_to_start_timeout: timedelta | None = None, - start_to_close_timeout: timedelta | None = None, - heartbeat_timeout: timedelta | None = None, - retry_policy: temporalio.common.RetryPolicy | None = None, - cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, - activity_id: str | None = None, - versioning_intent: VersioningIntent | None = None, - summary: str | None = None, - priority: temporalio.common.Priority = temporalio.common.Priority.default, -) -> ActivityHandle[ReturnType]: ... - - -def start_activity_class( - activity: type[Callable], # type: ignore[reportOverlappingOverload] - arg: Any = temporalio.common._arg_unset, - *, - args: Sequence[Any] = [], - task_queue: str | None = None, - schedule_to_close_timeout: timedelta | None = None, - schedule_to_start_timeout: timedelta | None = None, - start_to_close_timeout: timedelta | None = None, - heartbeat_timeout: timedelta | None = None, - retry_policy: temporalio.common.RetryPolicy | None = None, - cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, - activity_id: str | None = None, - versioning_intent: VersioningIntent | None = None, - summary: str | None = None, - priority: temporalio.common.Priority = temporalio.common.Priority.default, -) -> ActivityHandle[Any]: - """Start an activity from a callable class. - - See :py:meth:`start_activity` for parameter and return details. - """ - return _Runtime.current().workflow_start_activity( - activity, - *temporalio.common._arg_or_args(arg, args), - task_queue=task_queue, - result_type=None, - schedule_to_close_timeout=schedule_to_close_timeout, - schedule_to_start_timeout=schedule_to_start_timeout, - start_to_close_timeout=start_to_close_timeout, - heartbeat_timeout=heartbeat_timeout, - retry_policy=retry_policy, - cancellation_type=cancellation_type, - activity_id=activity_id, - versioning_intent=versioning_intent, - summary=summary, - priority=priority, - ) - - -# Overload for async no-param activity -@overload -async def execute_activity_class( - activity: type[CallableAsyncNoParam[ReturnType]], - *, - task_queue: str | None = None, - schedule_to_close_timeout: timedelta | None = None, - schedule_to_start_timeout: timedelta | None = None, - start_to_close_timeout: timedelta | None = None, - heartbeat_timeout: timedelta | None = None, - retry_policy: temporalio.common.RetryPolicy | None = None, - cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, - activity_id: str | None = None, - versioning_intent: VersioningIntent | None = None, - summary: str | None = None, - priority: temporalio.common.Priority = temporalio.common.Priority.default, -) -> ReturnType: ... - - -# Overload for sync no-param activity -@overload -async def execute_activity_class( - activity: type[CallableSyncNoParam[ReturnType]], - *, - task_queue: str | None = None, - schedule_to_close_timeout: timedelta | None = None, - schedule_to_start_timeout: timedelta | None = None, - start_to_close_timeout: timedelta | None = None, - heartbeat_timeout: timedelta | None = None, - retry_policy: temporalio.common.RetryPolicy | None = None, - cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, - activity_id: str | None = None, - versioning_intent: VersioningIntent | None = None, - summary: str | None = None, - priority: temporalio.common.Priority = temporalio.common.Priority.default, -) -> ReturnType: ... - - -# Overload for async single-param activity -@overload -async def execute_activity_class( - activity: type[CallableAsyncSingleParam[ParamType, ReturnType]], - arg: ParamType, - *, - task_queue: str | None = None, - schedule_to_close_timeout: timedelta | None = None, - schedule_to_start_timeout: timedelta | None = None, - start_to_close_timeout: timedelta | None = None, - heartbeat_timeout: timedelta | None = None, - retry_policy: temporalio.common.RetryPolicy | None = None, - cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, - activity_id: str | None = None, - versioning_intent: VersioningIntent | None = None, - summary: str | None = None, - priority: temporalio.common.Priority = temporalio.common.Priority.default, -) -> ReturnType: ... - - -# Overload for sync single-param activity -@overload -async def execute_activity_class( - activity: type[CallableSyncSingleParam[ParamType, ReturnType]], - arg: ParamType, - *, - task_queue: str | None = None, - schedule_to_close_timeout: timedelta | None = None, - schedule_to_start_timeout: timedelta | None = None, - start_to_close_timeout: timedelta | None = None, - heartbeat_timeout: timedelta | None = None, - retry_policy: temporalio.common.RetryPolicy | None = None, - cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, - activity_id: str | None = None, - versioning_intent: VersioningIntent | None = None, - summary: str | None = None, - priority: temporalio.common.Priority = temporalio.common.Priority.default, -) -> ReturnType: ... - - -# Overload for async multi-param activity -@overload -async def execute_activity_class( - activity: type[Callable[..., Awaitable[ReturnType]]], # type: ignore[reportOverlappingOverload] - *, - args: Sequence[Any], - task_queue: str | None = None, - schedule_to_close_timeout: timedelta | None = None, - schedule_to_start_timeout: timedelta | None = None, - start_to_close_timeout: timedelta | None = None, - heartbeat_timeout: timedelta | None = None, - retry_policy: temporalio.common.RetryPolicy | None = None, - cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, - activity_id: str | None = None, - versioning_intent: VersioningIntent | None = None, - summary: str | None = None, - priority: temporalio.common.Priority = temporalio.common.Priority.default, -) -> ReturnType: ... - - -# Overload for sync multi-param activity -@overload -async def execute_activity_class( - activity: type[Callable[..., ReturnType]], # type: ignore[reportOverlappingOverload] - *, - args: Sequence[Any], - task_queue: str | None = None, - schedule_to_close_timeout: timedelta | None = None, - schedule_to_start_timeout: timedelta | None = None, - start_to_close_timeout: timedelta | None = None, - heartbeat_timeout: timedelta | None = None, - retry_policy: temporalio.common.RetryPolicy | None = None, - cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, - activity_id: str | None = None, - versioning_intent: VersioningIntent | None = None, - summary: str | None = None, - priority: temporalio.common.Priority = temporalio.common.Priority.default, -) -> ReturnType: ... - - -async def execute_activity_class( - activity: type[Callable], # type: ignore[reportOverlappingOverload] - arg: Any = temporalio.common._arg_unset, - *, - args: Sequence[Any] = [], - task_queue: str | None = None, - schedule_to_close_timeout: timedelta | None = None, - schedule_to_start_timeout: timedelta | None = None, - start_to_close_timeout: timedelta | None = None, - heartbeat_timeout: timedelta | None = None, - retry_policy: temporalio.common.RetryPolicy | None = None, - cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, - activity_id: str | None = None, - versioning_intent: VersioningIntent | None = None, - summary: str | None = None, - priority: temporalio.common.Priority = temporalio.common.Priority.default, -) -> Any: - """Start an activity from a callable class and wait for completion. - - This is a shortcut for ``await`` :py:meth:`start_activity_class`. - """ - return await _Runtime.current().workflow_start_activity( - activity, - *temporalio.common._arg_or_args(arg, args), - task_queue=task_queue, - result_type=None, - schedule_to_close_timeout=schedule_to_close_timeout, - schedule_to_start_timeout=schedule_to_start_timeout, - start_to_close_timeout=start_to_close_timeout, - heartbeat_timeout=heartbeat_timeout, - retry_policy=retry_policy, - cancellation_type=cancellation_type, - activity_id=activity_id, - versioning_intent=versioning_intent, - summary=summary, - priority=priority, - ) - - -# Overload for async no-param activity -@overload -def start_activity_method( - activity: MethodAsyncNoParam[SelfType, ReturnType], - *, - task_queue: str | None = None, - schedule_to_close_timeout: timedelta | None = None, - schedule_to_start_timeout: timedelta | None = None, - start_to_close_timeout: timedelta | None = None, - heartbeat_timeout: timedelta | None = None, - retry_policy: temporalio.common.RetryPolicy | None = None, - cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, - activity_id: str | None = None, - versioning_intent: VersioningIntent | None = None, - summary: str | None = None, - priority: temporalio.common.Priority = temporalio.common.Priority.default, -) -> ActivityHandle[ReturnType]: ... - - -# Overload for sync no-param activity -@overload -def start_activity_method( - activity: MethodSyncNoParam[SelfType, ReturnType], - *, - task_queue: str | None = None, - schedule_to_close_timeout: timedelta | None = None, - schedule_to_start_timeout: timedelta | None = None, - start_to_close_timeout: timedelta | None = None, - heartbeat_timeout: timedelta | None = None, - retry_policy: temporalio.common.RetryPolicy | None = None, - cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, - activity_id: str | None = None, - versioning_intent: VersioningIntent | None = None, - summary: str | None = None, - priority: temporalio.common.Priority = temporalio.common.Priority.default, -) -> ActivityHandle[ReturnType]: ... - - -# Overload for async single-param activity -@overload -def start_activity_method( - activity: MethodAsyncSingleParam[SelfType, ParamType, ReturnType], - arg: ParamType, - *, - task_queue: str | None = None, - schedule_to_close_timeout: timedelta | None = None, - schedule_to_start_timeout: timedelta | None = None, - start_to_close_timeout: timedelta | None = None, - heartbeat_timeout: timedelta | None = None, - retry_policy: temporalio.common.RetryPolicy | None = None, - cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, - activity_id: str | None = None, - versioning_intent: VersioningIntent | None = None, - summary: str | None = None, - priority: temporalio.common.Priority = temporalio.common.Priority.default, -) -> ActivityHandle[ReturnType]: ... - - -# Overload for sync single-param activity -@overload -def start_activity_method( - activity: MethodSyncSingleParam[SelfType, ParamType, ReturnType], - arg: ParamType, - *, - task_queue: str | None = None, - schedule_to_close_timeout: timedelta | None = None, - schedule_to_start_timeout: timedelta | None = None, - start_to_close_timeout: timedelta | None = None, - heartbeat_timeout: timedelta | None = None, - retry_policy: temporalio.common.RetryPolicy | None = None, - cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, - activity_id: str | None = None, - versioning_intent: VersioningIntent | None = None, - summary: str | None = None, - priority: temporalio.common.Priority = temporalio.common.Priority.default, -) -> ActivityHandle[ReturnType]: ... - - -# Overload for async multi-param activity -@overload -def start_activity_method( - activity: Callable[Concatenate[SelfType, MultiParamSpec], Awaitable[ReturnType]], - *, - args: Sequence[Any], - task_queue: str | None = None, - schedule_to_close_timeout: timedelta | None = None, - schedule_to_start_timeout: timedelta | None = None, - start_to_close_timeout: timedelta | None = None, - heartbeat_timeout: timedelta | None = None, - retry_policy: temporalio.common.RetryPolicy | None = None, - cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, - activity_id: str | None = None, - versioning_intent: VersioningIntent | None = None, - summary: str | None = None, - priority: temporalio.common.Priority = temporalio.common.Priority.default, -) -> ActivityHandle[ReturnType]: ... - - -# Overload for sync multi-param activity -@overload -def start_activity_method( - activity: Callable[Concatenate[SelfType, MultiParamSpec], ReturnType], - *, - args: Sequence[Any], - task_queue: str | None = None, - schedule_to_close_timeout: timedelta | None = None, - schedule_to_start_timeout: timedelta | None = None, - start_to_close_timeout: timedelta | None = None, - heartbeat_timeout: timedelta | None = None, - retry_policy: temporalio.common.RetryPolicy | None = None, - cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, - activity_id: str | None = None, - versioning_intent: VersioningIntent | None = None, - summary: str | None = None, - priority: temporalio.common.Priority = temporalio.common.Priority.default, -) -> ActivityHandle[ReturnType]: ... - - -def start_activity_method( - activity: Callable, - arg: Any = temporalio.common._arg_unset, - *, - args: Sequence[Any] = [], - task_queue: str | None = None, - schedule_to_close_timeout: timedelta | None = None, - schedule_to_start_timeout: timedelta | None = None, - start_to_close_timeout: timedelta | None = None, - heartbeat_timeout: timedelta | None = None, - retry_policy: temporalio.common.RetryPolicy | None = None, - cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, - activity_id: str | None = None, - versioning_intent: VersioningIntent | None = None, - summary: str | None = None, - priority: temporalio.common.Priority = temporalio.common.Priority.default, -) -> ActivityHandle[Any]: - """Start an activity from a method. - - See :py:meth:`start_activity` for parameter and return details. - """ - return _Runtime.current().workflow_start_activity( - activity, - *temporalio.common._arg_or_args(arg, args), - task_queue=task_queue, - result_type=None, - schedule_to_close_timeout=schedule_to_close_timeout, - schedule_to_start_timeout=schedule_to_start_timeout, - start_to_close_timeout=start_to_close_timeout, - heartbeat_timeout=heartbeat_timeout, - retry_policy=retry_policy, - cancellation_type=cancellation_type, - activity_id=activity_id, - versioning_intent=versioning_intent, - summary=summary, - priority=priority, - ) - - -# Overload for async no-param activity -@overload -async def execute_activity_method( - activity: MethodAsyncNoParam[SelfType, ReturnType], - *, - task_queue: str | None = None, - schedule_to_close_timeout: timedelta | None = None, - schedule_to_start_timeout: timedelta | None = None, - start_to_close_timeout: timedelta | None = None, - heartbeat_timeout: timedelta | None = None, - retry_policy: temporalio.common.RetryPolicy | None = None, - cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, - activity_id: str | None = None, - versioning_intent: VersioningIntent | None = None, - summary: str | None = None, - priority: temporalio.common.Priority = temporalio.common.Priority.default, -) -> ReturnType: ... - - -# Overload for sync no-param activity -@overload -async def execute_activity_method( - activity: MethodSyncNoParam[SelfType, ReturnType], - *, - task_queue: str | None = None, - schedule_to_close_timeout: timedelta | None = None, - schedule_to_start_timeout: timedelta | None = None, - start_to_close_timeout: timedelta | None = None, - heartbeat_timeout: timedelta | None = None, - retry_policy: temporalio.common.RetryPolicy | None = None, - cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, - activity_id: str | None = None, - versioning_intent: VersioningIntent | None = None, - summary: str | None = None, - priority: temporalio.common.Priority = temporalio.common.Priority.default, -) -> ReturnType: ... - - -# Overload for async single-param activity -@overload -async def execute_activity_method( - activity: MethodAsyncSingleParam[SelfType, ParamType, ReturnType], - arg: ParamType, - *, - task_queue: str | None = None, - schedule_to_close_timeout: timedelta | None = None, - schedule_to_start_timeout: timedelta | None = None, - start_to_close_timeout: timedelta | None = None, - heartbeat_timeout: timedelta | None = None, - retry_policy: temporalio.common.RetryPolicy | None = None, - cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, - activity_id: str | None = None, - versioning_intent: VersioningIntent | None = None, - summary: str | None = None, - priority: temporalio.common.Priority = temporalio.common.Priority.default, -) -> ReturnType: ... - - -# Overload for sync single-param activity -@overload -async def execute_activity_method( - activity: MethodSyncSingleParam[SelfType, ParamType, ReturnType], - arg: ParamType, - *, - task_queue: str | None = None, - schedule_to_close_timeout: timedelta | None = None, - schedule_to_start_timeout: timedelta | None = None, - start_to_close_timeout: timedelta | None = None, - heartbeat_timeout: timedelta | None = None, - retry_policy: temporalio.common.RetryPolicy | None = None, - cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, - activity_id: str | None = None, - versioning_intent: VersioningIntent | None = None, - summary: str | None = None, - priority: temporalio.common.Priority = temporalio.common.Priority.default, -) -> ReturnType: ... - - -# Overload for async multi-param activity -@overload -async def execute_activity_method( - activity: Callable[Concatenate[SelfType, MultiParamSpec], Awaitable[ReturnType]], - *, - args: Sequence[Any], - task_queue: str | None = None, - schedule_to_close_timeout: timedelta | None = None, - schedule_to_start_timeout: timedelta | None = None, - start_to_close_timeout: timedelta | None = None, - heartbeat_timeout: timedelta | None = None, - retry_policy: temporalio.common.RetryPolicy | None = None, - cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, - activity_id: str | None = None, - versioning_intent: VersioningIntent | None = None, - summary: str | None = None, - priority: temporalio.common.Priority = temporalio.common.Priority.default, -) -> ReturnType: ... - - -# Overload for sync multi-param activity -@overload -async def execute_activity_method( - activity: Callable[Concatenate[SelfType, MultiParamSpec], ReturnType], - *, - args: Sequence[Any], - task_queue: str | None = None, - schedule_to_close_timeout: timedelta | None = None, - schedule_to_start_timeout: timedelta | None = None, - start_to_close_timeout: timedelta | None = None, - heartbeat_timeout: timedelta | None = None, - retry_policy: temporalio.common.RetryPolicy | None = None, - cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, - activity_id: str | None = None, - versioning_intent: VersioningIntent | None = None, - summary: str | None = None, - priority: temporalio.common.Priority = temporalio.common.Priority.default, -) -> ReturnType: ... - - -async def execute_activity_method( - activity: Callable, - arg: Any = temporalio.common._arg_unset, - *, - args: Sequence[Any] = [], - task_queue: str | None = None, - schedule_to_close_timeout: timedelta | None = None, - schedule_to_start_timeout: timedelta | None = None, - start_to_close_timeout: timedelta | None = None, - heartbeat_timeout: timedelta | None = None, - retry_policy: temporalio.common.RetryPolicy | None = None, - cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, - activity_id: str | None = None, - versioning_intent: VersioningIntent | None = None, - summary: str | None = None, - priority: temporalio.common.Priority = temporalio.common.Priority.default, -) -> Any: - """Start an activity from a method and wait for completion. - - This is a shortcut for ``await`` :py:meth:`start_activity_method`. - """ - # We call the runtime directly instead of top-level start_activity to ensure - # we don't miss new parameters - return await _Runtime.current().workflow_start_activity( - activity, - *temporalio.common._arg_or_args(arg, args), - task_queue=task_queue, - result_type=None, - schedule_to_close_timeout=schedule_to_close_timeout, - schedule_to_start_timeout=schedule_to_start_timeout, - start_to_close_timeout=start_to_close_timeout, - heartbeat_timeout=heartbeat_timeout, - retry_policy=retry_policy, - cancellation_type=cancellation_type, - activity_id=activity_id, - versioning_intent=versioning_intent, - summary=summary, - priority=priority, - ) - - -class LocalActivityConfig(TypedDict, total=False): - """TypedDict of config that can be used for :py:func:`start_local_activity` - and :py:func:`execute_local_activity`. - """ - - schedule_to_close_timeout: timedelta | None - schedule_to_start_timeout: timedelta | None - start_to_close_timeout: timedelta | None - retry_policy: temporalio.common.RetryPolicy | None - local_retry_threshold: timedelta | None - cancellation_type: ActivityCancellationType - activity_id: str | None - summary: str | None - - -# Overload for async no-param activity -@overload -def start_local_activity( - activity: CallableAsyncNoParam[ReturnType], - *, - schedule_to_close_timeout: timedelta | None = None, - schedule_to_start_timeout: timedelta | None = None, - start_to_close_timeout: timedelta | None = None, - retry_policy: temporalio.common.RetryPolicy | None = None, - local_retry_threshold: timedelta | None = None, - cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, - activity_id: str | None = None, - summary: str | None = None, -) -> ActivityHandle[ReturnType]: ... - - -# Overload for sync no-param activity -@overload -def start_local_activity( - activity: CallableSyncNoParam[ReturnType], - *, - activity_id: str | None = None, - schedule_to_close_timeout: timedelta | None = None, - schedule_to_start_timeout: timedelta | None = None, - start_to_close_timeout: timedelta | None = None, - retry_policy: temporalio.common.RetryPolicy | None = None, - local_retry_threshold: timedelta | None = None, - cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, - summary: str | None = None, -) -> ActivityHandle[ReturnType]: ... - - -# Overload for async single-param activity -@overload -def start_local_activity( - activity: CallableAsyncSingleParam[ParamType, ReturnType], - arg: ParamType, - *, - schedule_to_close_timeout: timedelta | None = None, - schedule_to_start_timeout: timedelta | None = None, - start_to_close_timeout: timedelta | None = None, - retry_policy: temporalio.common.RetryPolicy | None = None, - local_retry_threshold: timedelta | None = None, - cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, - activity_id: str | None = None, - summary: str | None = None, -) -> ActivityHandle[ReturnType]: ... - - -# Overload for sync single-param activity -@overload -def start_local_activity( - activity: CallableSyncSingleParam[ParamType, ReturnType], - arg: ParamType, - *, - schedule_to_close_timeout: timedelta | None = None, - schedule_to_start_timeout: timedelta | None = None, - start_to_close_timeout: timedelta | None = None, - retry_policy: temporalio.common.RetryPolicy | None = None, - local_retry_threshold: timedelta | None = None, - cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, - activity_id: str | None = None, - summary: str | None = None, -) -> ActivityHandle[ReturnType]: ... - - -# Overload for async multi-param activity -@overload -def start_local_activity( - activity: Callable[..., Awaitable[ReturnType]], - *, - args: Sequence[Any], - schedule_to_close_timeout: timedelta | None = None, - schedule_to_start_timeout: timedelta | None = None, - start_to_close_timeout: timedelta | None = None, - retry_policy: temporalio.common.RetryPolicy | None = None, - local_retry_threshold: timedelta | None = None, - cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, - activity_id: str | None = None, - summary: str | None = None, -) -> ActivityHandle[ReturnType]: ... - - -# Overload for sync multi-param activity -@overload -def start_local_activity( - activity: Callable[..., ReturnType], - *, - args: Sequence[Any], - schedule_to_close_timeout: timedelta | None = None, - schedule_to_start_timeout: timedelta | None = None, - start_to_close_timeout: timedelta | None = None, - retry_policy: temporalio.common.RetryPolicy | None = None, - local_retry_threshold: timedelta | None = None, - cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, - activity_id: str | None = None, - summary: str | None = None, -) -> ActivityHandle[ReturnType]: ... - - -# Overload for string-name activity -@overload -def start_local_activity( - activity: str, - arg: Any = temporalio.common._arg_unset, - *, - args: Sequence[Any] = [], - result_type: type | None = None, - schedule_to_close_timeout: timedelta | None = None, - schedule_to_start_timeout: timedelta | None = None, - start_to_close_timeout: timedelta | None = None, - retry_policy: temporalio.common.RetryPolicy | None = None, - local_retry_threshold: timedelta | None = None, - cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, - activity_id: str | None = None, - summary: str | None = None, -) -> ActivityHandle[Any]: ... - - -def start_local_activity( - activity: Any, - arg: Any = temporalio.common._arg_unset, - *, - args: Sequence[Any] = [], - result_type: type | None = None, - schedule_to_close_timeout: timedelta | None = None, - schedule_to_start_timeout: timedelta | None = None, - start_to_close_timeout: timedelta | None = None, - retry_policy: temporalio.common.RetryPolicy | None = None, - local_retry_threshold: timedelta | None = None, - cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, - activity_id: str | None = None, - summary: str | None = None, -) -> ActivityHandle[Any]: - """Start a local activity and return its handle. - - At least one of ``schedule_to_close_timeout`` or ``start_to_close_timeout`` - must be present. - - Args: - activity: Activity name or function reference. - arg: Single argument to the activity. - args: Multiple arguments to the activity. Cannot be set if arg is. - result_type: For string activities, this can set the specific result - type hint to deserialize into. - schedule_to_close_timeout: Max amount of time the activity can take from - first being scheduled to being completed before it times out. This - is inclusive of all retries. - schedule_to_start_timeout: Max amount of time the activity can take to - be started from first being scheduled. - start_to_close_timeout: Max amount of time a single activity run can - take from when it starts to when it completes. This is per retry. - retry_policy: How an activity is retried on failure. If unset, an - SDK-defined default is used. Set maximum attempts to 1 to disable - retries. - cancellation_type: How the activity is treated when it is cancelled from - the workflow. - activity_id: Optional unique identifier for the activity. This is an - advanced setting that should not be set unless users are sure they - need to. Contact Temporal before setting this value. - summary: Optional summary for the activity. - - Returns: - An activity handle to the activity which is an async task. - """ - return _Runtime.current().workflow_start_local_activity( - activity, - *temporalio.common._arg_or_args(arg, args), - result_type=result_type, - schedule_to_close_timeout=schedule_to_close_timeout, - schedule_to_start_timeout=schedule_to_start_timeout, - start_to_close_timeout=start_to_close_timeout, - retry_policy=retry_policy, - local_retry_threshold=local_retry_threshold, - cancellation_type=cancellation_type, - activity_id=activity_id, - summary=summary, - ) - - -# Overload for async no-param activity -@overload -async def execute_local_activity( - activity: CallableAsyncNoParam[ReturnType], - *, - schedule_to_close_timeout: timedelta | None = None, - schedule_to_start_timeout: timedelta | None = None, - start_to_close_timeout: timedelta | None = None, - retry_policy: temporalio.common.RetryPolicy | None = None, - local_retry_threshold: timedelta | None = None, - cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, - activity_id: str | None = None, - summary: str | None = None, -) -> ReturnType: ... - - -# Overload for sync no-param activity -@overload -async def execute_local_activity( - activity: CallableSyncNoParam[ReturnType], - *, - schedule_to_close_timeout: timedelta | None = None, - schedule_to_start_timeout: timedelta | None = None, - start_to_close_timeout: timedelta | None = None, - retry_policy: temporalio.common.RetryPolicy | None = None, - local_retry_threshold: timedelta | None = None, - cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, - activity_id: str | None = None, - summary: str | None = None, -) -> ReturnType: ... - - -# Overload for async single-param activity -@overload -async def execute_local_activity( - activity: CallableAsyncSingleParam[ParamType, ReturnType], - arg: ParamType, - *, - schedule_to_close_timeout: timedelta | None = None, - schedule_to_start_timeout: timedelta | None = None, - start_to_close_timeout: timedelta | None = None, - retry_policy: temporalio.common.RetryPolicy | None = None, - local_retry_threshold: timedelta | None = None, - cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, - activity_id: str | None = None, - summary: str | None = None, -) -> ReturnType: ... - - -# Overload for sync single-param activity -@overload -async def execute_local_activity( - activity: CallableSyncSingleParam[ParamType, ReturnType], - arg: ParamType, - *, - schedule_to_close_timeout: timedelta | None = None, - schedule_to_start_timeout: timedelta | None = None, - start_to_close_timeout: timedelta | None = None, - retry_policy: temporalio.common.RetryPolicy | None = None, - local_retry_threshold: timedelta | None = None, - cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, - activity_id: str | None = None, - summary: str | None = None, -) -> ReturnType: ... - - -# Overload for async multi-param activity -@overload -async def execute_local_activity( - activity: Callable[..., Awaitable[ReturnType]], - *, - args: Sequence[Any], - schedule_to_close_timeout: timedelta | None = None, - schedule_to_start_timeout: timedelta | None = None, - start_to_close_timeout: timedelta | None = None, - retry_policy: temporalio.common.RetryPolicy | None = None, - local_retry_threshold: timedelta | None = None, - cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, - activity_id: str | None = None, - summary: str | None = None, -) -> ReturnType: ... - - -# Overload for sync multi-param activity -@overload -async def execute_local_activity( - activity: Callable[..., ReturnType], - *, - args: Sequence[Any], - schedule_to_close_timeout: timedelta | None = None, - schedule_to_start_timeout: timedelta | None = None, - start_to_close_timeout: timedelta | None = None, - retry_policy: temporalio.common.RetryPolicy | None = None, - local_retry_threshold: timedelta | None = None, - cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, - activity_id: str | None = None, - summary: str | None = None, -) -> ReturnType: ... - - -# Overload for string-name activity -@overload -async def execute_local_activity( - activity: str, - arg: Any = temporalio.common._arg_unset, - *, - args: Sequence[Any] = [], - result_type: type | None = None, - schedule_to_close_timeout: timedelta | None = None, - schedule_to_start_timeout: timedelta | None = None, - start_to_close_timeout: timedelta | None = None, - retry_policy: temporalio.common.RetryPolicy | None = None, - local_retry_threshold: timedelta | None = None, - cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, - activity_id: str | None = None, - summary: str | None = None, -) -> Any: ... - - -async def execute_local_activity( - activity: Any, - arg: Any = temporalio.common._arg_unset, - *, - args: Sequence[Any] = [], - result_type: type | None = None, - schedule_to_close_timeout: timedelta | None = None, - schedule_to_start_timeout: timedelta | None = None, - start_to_close_timeout: timedelta | None = None, - retry_policy: temporalio.common.RetryPolicy | None = None, - local_retry_threshold: timedelta | None = None, - cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, - activity_id: str | None = None, - summary: str | None = None, -) -> Any: - """Start a local activity and wait for completion. - - This is a shortcut for ``await`` :py:meth:`start_local_activity`. - """ - # We call the runtime directly instead of top-level start_local_activity to - # ensure we don't miss new parameters - return await _Runtime.current().workflow_start_local_activity( - activity, - *temporalio.common._arg_or_args(arg, args), - result_type=result_type, - schedule_to_close_timeout=schedule_to_close_timeout, - schedule_to_start_timeout=schedule_to_start_timeout, - start_to_close_timeout=start_to_close_timeout, - retry_policy=retry_policy, - local_retry_threshold=local_retry_threshold, - cancellation_type=cancellation_type, - activity_id=activity_id, - summary=summary, - ) - - -# Overload for async no-param activity -@overload -def start_local_activity_class( - activity: type[CallableAsyncNoParam[ReturnType]], - *, - schedule_to_close_timeout: timedelta | None = None, - schedule_to_start_timeout: timedelta | None = None, - start_to_close_timeout: timedelta | None = None, - retry_policy: temporalio.common.RetryPolicy | None = None, - local_retry_threshold: timedelta | None = None, - cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, - activity_id: str | None = None, -) -> ActivityHandle[ReturnType]: ... - - -# Overload for sync no-param activity -@overload -def start_local_activity_class( - activity: type[CallableSyncNoParam[ReturnType]], - *, - schedule_to_close_timeout: timedelta | None = None, - schedule_to_start_timeout: timedelta | None = None, - start_to_close_timeout: timedelta | None = None, - retry_policy: temporalio.common.RetryPolicy | None = None, - local_retry_threshold: timedelta | None = None, - cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, - activity_id: str | None = None, -) -> ActivityHandle[ReturnType]: ... - - -# Overload for async single-param activity -@overload -def start_local_activity_class( - activity: type[CallableAsyncSingleParam[ParamType, ReturnType]], - arg: ParamType, - *, - schedule_to_close_timeout: timedelta | None = None, - schedule_to_start_timeout: timedelta | None = None, - start_to_close_timeout: timedelta | None = None, - retry_policy: temporalio.common.RetryPolicy | None = None, - local_retry_threshold: timedelta | None = None, - cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, - activity_id: str | None = None, -) -> ActivityHandle[ReturnType]: ... - - -# Overload for sync single-param activity -@overload -def start_local_activity_class( - activity: type[CallableSyncSingleParam[ParamType, ReturnType]], - arg: ParamType, - *, - schedule_to_close_timeout: timedelta | None = None, - schedule_to_start_timeout: timedelta | None = None, - start_to_close_timeout: timedelta | None = None, - retry_policy: temporalio.common.RetryPolicy | None = None, - local_retry_threshold: timedelta | None = None, - cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, - activity_id: str | None = None, -) -> ActivityHandle[ReturnType]: ... - - -# Overload for async multi-param activity -@overload -def start_local_activity_class( - activity: type[Callable[..., Awaitable[ReturnType]]], # type: ignore[reportInvalidTypeForm] - *, - args: Sequence[Any], - schedule_to_close_timeout: timedelta | None = None, - schedule_to_start_timeout: timedelta | None = None, - start_to_close_timeout: timedelta | None = None, - retry_policy: temporalio.common.RetryPolicy | None = None, - local_retry_threshold: timedelta | None = None, - cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, - activity_id: str | None = None, -) -> ActivityHandle[ReturnType]: ... - - -# Overload for sync multi-param activity -@overload -def start_local_activity_class( # type: ignore[reportOverlappingOverload] - activity: type[Callable[..., ReturnType]], # type: ignore[reportInvalidTypeForm] - *, - args: Sequence[Any], - schedule_to_close_timeout: timedelta | None = None, - schedule_to_start_timeout: timedelta | None = None, - start_to_close_timeout: timedelta | None = None, - retry_policy: temporalio.common.RetryPolicy | None = None, - local_retry_threshold: timedelta | None = None, - cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, - activity_id: str | None = None, -) -> ActivityHandle[ReturnType]: ... - - -def start_local_activity_class( - activity: type[Callable], # type: ignore[reportInvalidTypeForm] - arg: Any = temporalio.common._arg_unset, - *, - args: Sequence[Any] = [], - schedule_to_close_timeout: timedelta | None = None, - schedule_to_start_timeout: timedelta | None = None, - start_to_close_timeout: timedelta | None = None, - retry_policy: temporalio.common.RetryPolicy | None = None, - local_retry_threshold: timedelta | None = None, - cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, - activity_id: str | None = None, - summary: str | None = None, -) -> ActivityHandle[Any]: - """Start a local activity from a callable class. - - See :py:meth:`start_local_activity` for parameter and return details. - """ - return _Runtime.current().workflow_start_local_activity( - activity, - *temporalio.common._arg_or_args(arg, args), - result_type=None, - schedule_to_close_timeout=schedule_to_close_timeout, - schedule_to_start_timeout=schedule_to_start_timeout, - start_to_close_timeout=start_to_close_timeout, - retry_policy=retry_policy, - local_retry_threshold=local_retry_threshold, - cancellation_type=cancellation_type, - activity_id=activity_id, - summary=summary, - ) - - -# Overload for async no-param activity -@overload -async def execute_local_activity_class( - activity: type[CallableAsyncNoParam[ReturnType]], - *, - schedule_to_close_timeout: timedelta | None = None, - schedule_to_start_timeout: timedelta | None = None, - start_to_close_timeout: timedelta | None = None, - retry_policy: temporalio.common.RetryPolicy | None = None, - local_retry_threshold: timedelta | None = None, - cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, - activity_id: str | None = None, - summary: str | None = None, -) -> ReturnType: ... - - -# Overload for sync no-param activity -@overload -async def execute_local_activity_class( - activity: type[CallableSyncNoParam[ReturnType]], - *, - schedule_to_close_timeout: timedelta | None = None, - schedule_to_start_timeout: timedelta | None = None, - start_to_close_timeout: timedelta | None = None, - retry_policy: temporalio.common.RetryPolicy | None = None, - local_retry_threshold: timedelta | None = None, - cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, - activity_id: str | None = None, - summary: str | None = None, -) -> ReturnType: ... - - -# Overload for async single-param activity -@overload -async def execute_local_activity_class( - activity: type[CallableAsyncSingleParam[ParamType, ReturnType]], - arg: ParamType, - *, - schedule_to_close_timeout: timedelta | None = None, - schedule_to_start_timeout: timedelta | None = None, - start_to_close_timeout: timedelta | None = None, - retry_policy: temporalio.common.RetryPolicy | None = None, - local_retry_threshold: timedelta | None = None, - cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, - activity_id: str | None = None, - summary: str | None = None, -) -> ReturnType: ... - - -# Overload for sync single-param activity -@overload -async def execute_local_activity_class( - activity: type[CallableSyncSingleParam[ParamType, ReturnType]], - arg: ParamType, - *, - schedule_to_close_timeout: timedelta | None = None, - schedule_to_start_timeout: timedelta | None = None, - start_to_close_timeout: timedelta | None = None, - retry_policy: temporalio.common.RetryPolicy | None = None, - local_retry_threshold: timedelta | None = None, - cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, - activity_id: str | None = None, - summary: str | None = None, -) -> ReturnType: ... - - -# Overload for async multi-param activity -@overload -async def execute_local_activity_class( # type: ignore[reportOverlappingOverload] - activity: type[Callable[..., Awaitable[ReturnType]]], # type: ignore[reportInvalidTypeForm] - *, - args: Sequence[Any], - schedule_to_close_timeout: timedelta | None = None, - schedule_to_start_timeout: timedelta | None = None, - start_to_close_timeout: timedelta | None = None, - retry_policy: temporalio.common.RetryPolicy | None = None, - local_retry_threshold: timedelta | None = None, - cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, - activity_id: str | None = None, - summary: str | None = None, -) -> ReturnType: ... - - -# Overload for sync multi-param activity -@overload -async def execute_local_activity_class( - activity: type[Callable[..., ReturnType]], # type: ignore[reportInvalidTypeForm] - *, - args: Sequence[Any], - schedule_to_close_timeout: timedelta | None = None, - schedule_to_start_timeout: timedelta | None = None, - start_to_close_timeout: timedelta | None = None, - retry_policy: temporalio.common.RetryPolicy | None = None, - local_retry_threshold: timedelta | None = None, - cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, - activity_id: str | None = None, - summary: str | None = None, -) -> ReturnType: ... - - -async def execute_local_activity_class( - activity: type[Callable], # type: ignore[reportInvalidTypeForm] - arg: Any = temporalio.common._arg_unset, - *, - args: Sequence[Any] = [], - schedule_to_close_timeout: timedelta | None = None, - schedule_to_start_timeout: timedelta | None = None, - start_to_close_timeout: timedelta | None = None, - retry_policy: temporalio.common.RetryPolicy | None = None, - local_retry_threshold: timedelta | None = None, - cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, - activity_id: str | None = None, - summary: str | None = None, -) -> Any: - """Start a local activity from a callable class and wait for completion. - - This is a shortcut for ``await`` :py:meth:`start_local_activity_class`. - """ - # We call the runtime directly instead of top-level start_local_activity to - # ensure we don't miss new parameters - return await _Runtime.current().workflow_start_local_activity( - activity, - *temporalio.common._arg_or_args(arg, args), - result_type=None, - schedule_to_close_timeout=schedule_to_close_timeout, - schedule_to_start_timeout=schedule_to_start_timeout, - start_to_close_timeout=start_to_close_timeout, - retry_policy=retry_policy, - local_retry_threshold=local_retry_threshold, - cancellation_type=cancellation_type, - activity_id=activity_id, - summary=summary, - ) - - -# Overload for async no-param activity -@overload -def start_local_activity_method( - activity: MethodAsyncNoParam[SelfType, ReturnType], - *, - schedule_to_close_timeout: timedelta | None = None, - schedule_to_start_timeout: timedelta | None = None, - start_to_close_timeout: timedelta | None = None, - retry_policy: temporalio.common.RetryPolicy | None = None, - local_retry_threshold: timedelta | None = None, - cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, - activity_id: str | None = None, - summary: str | None = None, -) -> ActivityHandle[ReturnType]: ... - - -# Overload for sync no-param activity -@overload -def start_local_activity_method( - activity: MethodSyncNoParam[SelfType, ReturnType], - *, - schedule_to_close_timeout: timedelta | None = None, - schedule_to_start_timeout: timedelta | None = None, - start_to_close_timeout: timedelta | None = None, - retry_policy: temporalio.common.RetryPolicy | None = None, - local_retry_threshold: timedelta | None = None, - cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, - activity_id: str | None = None, - summary: str | None = None, -) -> ActivityHandle[ReturnType]: ... - - -# Overload for async single-param activity -@overload -def start_local_activity_method( - activity: MethodAsyncSingleParam[SelfType, ParamType, ReturnType], - arg: ParamType, - *, - schedule_to_close_timeout: timedelta | None = None, - schedule_to_start_timeout: timedelta | None = None, - start_to_close_timeout: timedelta | None = None, - retry_policy: temporalio.common.RetryPolicy | None = None, - local_retry_threshold: timedelta | None = None, - cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, - activity_id: str | None = None, - summary: str | None = None, -) -> ActivityHandle[ReturnType]: ... - - -# Overload for sync single-param activity -@overload -def start_local_activity_method( - activity: MethodSyncSingleParam[SelfType, ParamType, ReturnType], - arg: ParamType, - *, - schedule_to_close_timeout: timedelta | None = None, - schedule_to_start_timeout: timedelta | None = None, - start_to_close_timeout: timedelta | None = None, - retry_policy: temporalio.common.RetryPolicy | None = None, - local_retry_threshold: timedelta | None = None, - cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, - activity_id: str | None = None, - summary: str | None = None, -) -> ActivityHandle[ReturnType]: ... - - -# Overload for async multi-param activity -@overload -def start_local_activity_method( - activity: Callable[Concatenate[SelfType, MultiParamSpec], Awaitable[ReturnType]], - *, - args: Sequence[Any], - schedule_to_close_timeout: timedelta | None = None, - schedule_to_start_timeout: timedelta | None = None, - start_to_close_timeout: timedelta | None = None, - retry_policy: temporalio.common.RetryPolicy | None = None, - local_retry_threshold: timedelta | None = None, - cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, - activity_id: str | None = None, - summary: str | None = None, -) -> ActivityHandle[ReturnType]: ... - - -# Overload for sync multi-param activity -@overload -def start_local_activity_method( - activity: Callable[Concatenate[SelfType, MultiParamSpec], ReturnType], - *, - args: Sequence[Any], - schedule_to_close_timeout: timedelta | None = None, - schedule_to_start_timeout: timedelta | None = None, - start_to_close_timeout: timedelta | None = None, - retry_policy: temporalio.common.RetryPolicy | None = None, - local_retry_threshold: timedelta | None = None, - cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, - activity_id: str | None = None, - summary: str | None = None, -) -> ActivityHandle[ReturnType]: ... - - -def start_local_activity_method( - activity: Callable, - arg: Any = temporalio.common._arg_unset, - *, - args: Sequence[Any] = [], - schedule_to_close_timeout: timedelta | None = None, - schedule_to_start_timeout: timedelta | None = None, - start_to_close_timeout: timedelta | None = None, - retry_policy: temporalio.common.RetryPolicy | None = None, - local_retry_threshold: timedelta | None = None, - cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, - activity_id: str | None = None, - summary: str | None = None, -) -> ActivityHandle[Any]: - """Start a local activity from a method. - - See :py:meth:`start_local_activity` for parameter and return details. - """ - return _Runtime.current().workflow_start_local_activity( - activity, - *temporalio.common._arg_or_args(arg, args), - result_type=None, - schedule_to_close_timeout=schedule_to_close_timeout, - schedule_to_start_timeout=schedule_to_start_timeout, - start_to_close_timeout=start_to_close_timeout, - retry_policy=retry_policy, - local_retry_threshold=local_retry_threshold, - cancellation_type=cancellation_type, - activity_id=activity_id, - summary=summary, - ) - - -# Overload for async no-param activity -@overload -async def execute_local_activity_method( - activity: MethodAsyncNoParam[SelfType, ReturnType], - *, - schedule_to_close_timeout: timedelta | None = None, - schedule_to_start_timeout: timedelta | None = None, - start_to_close_timeout: timedelta | None = None, - retry_policy: temporalio.common.RetryPolicy | None = None, - local_retry_threshold: timedelta | None = None, - cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, - activity_id: str | None = None, - summary: str | None = None, -) -> ReturnType: ... - - -# Overload for sync no-param activity -@overload -async def execute_local_activity_method( - activity: MethodSyncNoParam[SelfType, ReturnType], - *, - schedule_to_close_timeout: timedelta | None = None, - schedule_to_start_timeout: timedelta | None = None, - start_to_close_timeout: timedelta | None = None, - retry_policy: temporalio.common.RetryPolicy | None = None, - local_retry_threshold: timedelta | None = None, - cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, - activity_id: str | None = None, - summary: str | None = None, -) -> ReturnType: ... - - -# Overload for async single-param activity -@overload -async def execute_local_activity_method( - activity: MethodAsyncSingleParam[SelfType, ParamType, ReturnType], - arg: ParamType, - *, - schedule_to_close_timeout: timedelta | None = None, - schedule_to_start_timeout: timedelta | None = None, - start_to_close_timeout: timedelta | None = None, - retry_policy: temporalio.common.RetryPolicy | None = None, - local_retry_threshold: timedelta | None = None, - cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, - activity_id: str | None = None, - summary: str | None = None, -) -> ReturnType: ... - - -# Overload for sync single-param activity -@overload -async def execute_local_activity_method( - activity: MethodSyncSingleParam[SelfType, ParamType, ReturnType], - arg: ParamType, - *, - schedule_to_close_timeout: timedelta | None = None, - schedule_to_start_timeout: timedelta | None = None, - start_to_close_timeout: timedelta | None = None, - retry_policy: temporalio.common.RetryPolicy | None = None, - local_retry_threshold: timedelta | None = None, - cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, - activity_id: str | None = None, - summary: str | None = None, -) -> ReturnType: ... - - -# Overload for async multi-param activity -@overload -async def execute_local_activity_method( - activity: Callable[Concatenate[SelfType, MultiParamSpec], Awaitable[ReturnType]], - *, - args: Sequence[Any], - schedule_to_close_timeout: timedelta | None = None, - schedule_to_start_timeout: timedelta | None = None, - start_to_close_timeout: timedelta | None = None, - retry_policy: temporalio.common.RetryPolicy | None = None, - local_retry_threshold: timedelta | None = None, - cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, - activity_id: str | None = None, - summary: str | None = None, -) -> ReturnType: ... - - -# Overload for sync multi-param activity -@overload -async def execute_local_activity_method( - activity: Callable[Concatenate[SelfType, MultiParamSpec], ReturnType], - *, - args: Sequence[Any], - schedule_to_close_timeout: timedelta | None = None, - schedule_to_start_timeout: timedelta | None = None, - start_to_close_timeout: timedelta | None = None, - retry_policy: temporalio.common.RetryPolicy | None = None, - local_retry_threshold: timedelta | None = None, - cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, - activity_id: str | None = None, - summary: str | None = None, -) -> ReturnType: ... - - -async def execute_local_activity_method( - activity: Callable, - arg: Any = temporalio.common._arg_unset, - *, - args: Sequence[Any] = [], - schedule_to_close_timeout: timedelta | None = None, - schedule_to_start_timeout: timedelta | None = None, - start_to_close_timeout: timedelta | None = None, - retry_policy: temporalio.common.RetryPolicy | None = None, - local_retry_threshold: timedelta | None = None, - cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, - activity_id: str | None = None, - summary: str | None = None, -) -> Any: - """Start a local activity from a method and wait for completion. - - This is a shortcut for ``await`` :py:meth:`start_local_activity_method`. - """ - # We call the runtime directly instead of top-level start_local_activity to - # ensure we don't miss new parameters - return await _Runtime.current().workflow_start_local_activity( - activity, - *temporalio.common._arg_or_args(arg, args), - result_type=None, - schedule_to_close_timeout=schedule_to_close_timeout, - schedule_to_start_timeout=schedule_to_start_timeout, - start_to_close_timeout=start_to_close_timeout, - retry_policy=retry_policy, - local_retry_threshold=local_retry_threshold, - cancellation_type=cancellation_type, - activity_id=activity_id, - summary=summary, - ) - - -class ChildWorkflowHandle(_AsyncioTask[ReturnType], Generic[SelfType, ReturnType]): # type: ignore[type-var] - """Handle for interacting with a child workflow. - - This is created via :py:func:`start_child_workflow`. - - This extends :py:class:`asyncio.Task` and supports all task features. - """ - - @property - def id(self) -> str: - """ID for the workflow.""" - raise NotImplementedError - - @property - def first_execution_run_id(self) -> str | None: - """Run ID for the workflow.""" - raise NotImplementedError - - @overload - async def signal( - self, - signal: MethodSyncOrAsyncNoParam[SelfType, None], - ) -> None: ... - - @overload - async def signal( - self, - signal: MethodSyncOrAsyncSingleParam[SelfType, ParamType, None], - arg: ParamType, - ) -> None: ... - - @overload - async def signal( - self, - signal: Callable[Concatenate[SelfType, MultiParamSpec], Awaitable[None] | None], - *, - args: Sequence[Any], - ) -> None: ... - - @overload - async def signal( - self, - signal: str, - arg: Any = temporalio.common._arg_unset, - *, - args: Sequence[Any] = [], - ) -> None: ... - - async def signal( - self, - signal: str | Callable, # type: ignore[reportUnusedParameter] - arg: Any = temporalio.common._arg_unset, # type: ignore[reportUnusedParameter] - *, - args: Sequence[Any] = [], # type: ignore[reportUnusedParameter] - ) -> None: - """Signal this child workflow. - - Args: - signal: Name or method reference for the signal. - arg: Single argument to the signal. - args: Multiple arguments to the signal. Cannot be set if arg is. - - """ - raise NotImplementedError - - -class ChildWorkflowCancellationType(IntEnum): - """How a child workflow cancellation should be handled.""" - - ABANDON = int( - temporalio.bridge.proto.child_workflow.ChildWorkflowCancellationType.ABANDON - ) - TRY_CANCEL = int( - temporalio.bridge.proto.child_workflow.ChildWorkflowCancellationType.TRY_CANCEL - ) - WAIT_CANCELLATION_COMPLETED = int( - temporalio.bridge.proto.child_workflow.ChildWorkflowCancellationType.WAIT_CANCELLATION_COMPLETED - ) - WAIT_CANCELLATION_REQUESTED = int( - temporalio.bridge.proto.child_workflow.ChildWorkflowCancellationType.WAIT_CANCELLATION_REQUESTED - ) - - -class ParentClosePolicy(IntEnum): - """How a child workflow should be handled when the parent closes.""" - - UNSPECIFIED = int( - temporalio.bridge.proto.child_workflow.ParentClosePolicy.PARENT_CLOSE_POLICY_UNSPECIFIED - ) - TERMINATE = int( - temporalio.bridge.proto.child_workflow.ParentClosePolicy.PARENT_CLOSE_POLICY_TERMINATE - ) - ABANDON = int( - temporalio.bridge.proto.child_workflow.ParentClosePolicy.PARENT_CLOSE_POLICY_ABANDON - ) - REQUEST_CANCEL = int( - temporalio.bridge.proto.child_workflow.ParentClosePolicy.PARENT_CLOSE_POLICY_REQUEST_CANCEL - ) - - -class ChildWorkflowConfig(TypedDict, total=False): - """TypedDict of config that can be used for :py:func:`start_child_workflow` - and :py:func:`execute_child_workflow`. - """ - - id: str | None - task_queue: str | None - cancellation_type: ChildWorkflowCancellationType - parent_close_policy: ParentClosePolicy - execution_timeout: timedelta | None - run_timeout: timedelta | None - task_timeout: timedelta | None - id_reuse_policy: temporalio.common.WorkflowIDReusePolicy - retry_policy: temporalio.common.RetryPolicy | None - cron_schedule: str - memo: Mapping[str, Any] | None - search_attributes: None | ( - temporalio.common.SearchAttributes | temporalio.common.TypedSearchAttributes - ) - versioning_intent: VersioningIntent | None - static_summary: str | None - static_details: str | None - priority: temporalio.common.Priority - - -# Overload for no-param workflow -@overload -async def start_child_workflow( - workflow: MethodAsyncNoParam[SelfType, ReturnType], - *, - id: str | None = None, - task_queue: str | None = None, - cancellation_type: ChildWorkflowCancellationType = ChildWorkflowCancellationType.WAIT_CANCELLATION_COMPLETED, - parent_close_policy: ParentClosePolicy = ParentClosePolicy.TERMINATE, - execution_timeout: timedelta | None = None, - run_timeout: timedelta | None = None, - task_timeout: timedelta | None = None, - id_reuse_policy: temporalio.common.WorkflowIDReusePolicy = temporalio.common.WorkflowIDReusePolicy.ALLOW_DUPLICATE, - retry_policy: temporalio.common.RetryPolicy | None = None, - cron_schedule: str = "", - memo: Mapping[str, Any] | None = None, - search_attributes: None - | ( - temporalio.common.SearchAttributes | temporalio.common.TypedSearchAttributes - ) = None, - versioning_intent: VersioningIntent | None = None, - static_summary: str | None = None, - static_details: str | None = None, - priority: temporalio.common.Priority = temporalio.common.Priority.default, -) -> ChildWorkflowHandle[SelfType, ReturnType]: ... - - -# Overload for single-param workflow -@overload -async def start_child_workflow( - workflow: MethodAsyncSingleParam[SelfType, ParamType, ReturnType], - arg: ParamType, - *, - id: str | None = None, - task_queue: str | None = None, - cancellation_type: ChildWorkflowCancellationType = ChildWorkflowCancellationType.WAIT_CANCELLATION_COMPLETED, - parent_close_policy: ParentClosePolicy = ParentClosePolicy.TERMINATE, - execution_timeout: timedelta | None = None, - run_timeout: timedelta | None = None, - task_timeout: timedelta | None = None, - id_reuse_policy: temporalio.common.WorkflowIDReusePolicy = temporalio.common.WorkflowIDReusePolicy.ALLOW_DUPLICATE, - retry_policy: temporalio.common.RetryPolicy | None = None, - cron_schedule: str = "", - memo: Mapping[str, Any] | None = None, - search_attributes: None - | ( - temporalio.common.SearchAttributes | temporalio.common.TypedSearchAttributes - ) = None, - versioning_intent: VersioningIntent | None = None, - static_summary: str | None = None, - static_details: str | None = None, - priority: temporalio.common.Priority = temporalio.common.Priority.default, -) -> ChildWorkflowHandle[SelfType, ReturnType]: ... - - -# Overload for multi-param workflow -@overload -async def start_child_workflow( - workflow: Callable[Concatenate[SelfType, MultiParamSpec], Awaitable[ReturnType]], - *, - args: Sequence[Any], - id: str | None = None, - task_queue: str | None = None, - cancellation_type: ChildWorkflowCancellationType = ChildWorkflowCancellationType.WAIT_CANCELLATION_COMPLETED, - parent_close_policy: ParentClosePolicy = ParentClosePolicy.TERMINATE, - execution_timeout: timedelta | None = None, - run_timeout: timedelta | None = None, - task_timeout: timedelta | None = None, - id_reuse_policy: temporalio.common.WorkflowIDReusePolicy = temporalio.common.WorkflowIDReusePolicy.ALLOW_DUPLICATE, - retry_policy: temporalio.common.RetryPolicy | None = None, - cron_schedule: str = "", - memo: Mapping[str, Any] | None = None, - search_attributes: None - | ( - temporalio.common.SearchAttributes | temporalio.common.TypedSearchAttributes - ) = None, - versioning_intent: VersioningIntent | None = None, - static_summary: str | None = None, - static_details: str | None = None, - priority: temporalio.common.Priority = temporalio.common.Priority.default, -) -> ChildWorkflowHandle[SelfType, ReturnType]: ... - - -# Overload for string-name workflow -@overload -async def start_child_workflow( - workflow: str, - arg: Any = temporalio.common._arg_unset, - *, - args: Sequence[Any] = [], - id: str | None = None, - task_queue: str | None = None, - result_type: type | None = None, - cancellation_type: ChildWorkflowCancellationType = ChildWorkflowCancellationType.WAIT_CANCELLATION_COMPLETED, - parent_close_policy: ParentClosePolicy = ParentClosePolicy.TERMINATE, - execution_timeout: timedelta | None = None, - run_timeout: timedelta | None = None, - task_timeout: timedelta | None = None, - id_reuse_policy: temporalio.common.WorkflowIDReusePolicy = temporalio.common.WorkflowIDReusePolicy.ALLOW_DUPLICATE, - retry_policy: temporalio.common.RetryPolicy | None = None, - cron_schedule: str = "", - memo: Mapping[str, Any] | None = None, - search_attributes: None - | ( - temporalio.common.SearchAttributes | temporalio.common.TypedSearchAttributes - ) = None, - versioning_intent: VersioningIntent | None = None, - static_summary: str | None = None, - static_details: str | None = None, - priority: temporalio.common.Priority = temporalio.common.Priority.default, -) -> ChildWorkflowHandle[Any, Any]: ... - - -async def start_child_workflow( - workflow: Any, - arg: Any = temporalio.common._arg_unset, - *, - args: Sequence[Any] = [], - id: str | None = None, - task_queue: str | None = None, - result_type: type | None = None, - cancellation_type: ChildWorkflowCancellationType = ChildWorkflowCancellationType.WAIT_CANCELLATION_COMPLETED, - parent_close_policy: ParentClosePolicy = ParentClosePolicy.TERMINATE, - execution_timeout: timedelta | None = None, - run_timeout: timedelta | None = None, - task_timeout: timedelta | None = None, - id_reuse_policy: temporalio.common.WorkflowIDReusePolicy = temporalio.common.WorkflowIDReusePolicy.ALLOW_DUPLICATE, - retry_policy: temporalio.common.RetryPolicy | None = None, - cron_schedule: str = "", - memo: Mapping[str, Any] | None = None, - search_attributes: None - | ( - temporalio.common.SearchAttributes | temporalio.common.TypedSearchAttributes - ) = None, - versioning_intent: VersioningIntent | None = None, - static_summary: str | None = None, - static_details: str | None = None, - priority: temporalio.common.Priority = temporalio.common.Priority.default, -) -> ChildWorkflowHandle[Any, Any]: - """Start a child workflow and return its handle. - - Args: - workflow: String name or class method decorated with ``@workflow.run`` - for the workflow to start. - arg: Single argument to the child workflow. - args: Multiple arguments to the child workflow. Cannot be set if arg is. - id: Optional unique identifier for the workflow execution. If not set, - defaults to :py:func:`uuid4`. - task_queue: Task queue to run the workflow on. Defaults to the current - workflow's task queue. - result_type: For string workflows, this can set the specific result type - hint to deserialize into. - cancellation_type: How the child workflow will react to cancellation. - parent_close_policy: How to handle the child workflow when the parent - workflow closes. - execution_timeout: Total workflow execution timeout including - retries and continue as new. - run_timeout: Timeout of a single workflow run. - task_timeout: Timeout of a single workflow task. - id_reuse_policy: How already-existing IDs are treated. - retry_policy: Retry policy for the workflow. - cron_schedule: See https://docs.temporal.io/docs/content/what-is-a-temporal-cron-job/ - memo: Memo for the workflow. - search_attributes: Search attributes for the workflow. The dictionary - form of this is DEPRECATED. - versioning_intent: When using the Worker Versioning feature, specifies whether this Child - Workflow should run on a worker with a compatible Build Id or not. - Deprecated: Use Worker Deployment versioning instead. - static_summary: A single-line fixed summary for this child workflow execution that may appear - in the UI/CLI. This can be in single-line Temporal markdown format. - static_details: General fixed details for this child workflow execution that may appear in - UI/CLI. This can be in Temporal markdown format and can span multiple lines. This is - a fixed value on the workflow that cannot be updated. For details that can be - updated, use :py:meth:`get_current_details` within the workflow. - priority: Priority to use for this workflow. - - Returns: - A workflow handle to the started/existing workflow. - """ - temporalio.common._warn_on_deprecated_search_attributes(search_attributes) - return await _Runtime.current().workflow_start_child_workflow( - workflow, - *temporalio.common._arg_or_args(arg, args), - id=id or str(uuid4()), - task_queue=task_queue, - result_type=result_type, - cancellation_type=cancellation_type, - parent_close_policy=parent_close_policy, - execution_timeout=execution_timeout, - run_timeout=run_timeout, - task_timeout=task_timeout, - id_reuse_policy=id_reuse_policy, - retry_policy=retry_policy, - cron_schedule=cron_schedule, - memo=memo, - search_attributes=search_attributes, - versioning_intent=versioning_intent, - static_summary=static_summary, - static_details=static_details, - priority=priority, - ) - - -# Overload for no-param workflow -@overload -async def execute_child_workflow( - workflow: MethodAsyncNoParam[SelfType, ReturnType], - *, - id: str | None = None, - task_queue: str | None = None, - cancellation_type: ChildWorkflowCancellationType = ChildWorkflowCancellationType.WAIT_CANCELLATION_COMPLETED, - parent_close_policy: ParentClosePolicy = ParentClosePolicy.TERMINATE, - execution_timeout: timedelta | None = None, - run_timeout: timedelta | None = None, - task_timeout: timedelta | None = None, - id_reuse_policy: temporalio.common.WorkflowIDReusePolicy = temporalio.common.WorkflowIDReusePolicy.ALLOW_DUPLICATE, - retry_policy: temporalio.common.RetryPolicy | None = None, - cron_schedule: str = "", - memo: Mapping[str, Any] | None = None, - search_attributes: None - | ( - temporalio.common.SearchAttributes | temporalio.common.TypedSearchAttributes - ) = None, - versioning_intent: VersioningIntent | None = None, - static_summary: str | None = None, - static_details: str | None = None, - priority: temporalio.common.Priority = temporalio.common.Priority.default, -) -> ReturnType: ... - - -# Overload for single-param workflow -@overload -async def execute_child_workflow( - workflow: MethodAsyncSingleParam[SelfType, ParamType, ReturnType], - arg: ParamType, - *, - id: str | None = None, - task_queue: str | None = None, - cancellation_type: ChildWorkflowCancellationType = ChildWorkflowCancellationType.WAIT_CANCELLATION_COMPLETED, - parent_close_policy: ParentClosePolicy = ParentClosePolicy.TERMINATE, - execution_timeout: timedelta | None = None, - run_timeout: timedelta | None = None, - task_timeout: timedelta | None = None, - id_reuse_policy: temporalio.common.WorkflowIDReusePolicy = temporalio.common.WorkflowIDReusePolicy.ALLOW_DUPLICATE, - retry_policy: temporalio.common.RetryPolicy | None = None, - cron_schedule: str = "", - memo: Mapping[str, Any] | None = None, - search_attributes: None - | ( - temporalio.common.SearchAttributes | temporalio.common.TypedSearchAttributes - ) = None, - versioning_intent: VersioningIntent | None = None, - static_summary: str | None = None, - static_details: str | None = None, - priority: temporalio.common.Priority = temporalio.common.Priority.default, -) -> ReturnType: ... - - -# Overload for multi-param workflow -@overload -async def execute_child_workflow( - workflow: Callable[Concatenate[SelfType, MultiParamSpec], Awaitable[ReturnType]], - *, - args: Sequence[Any], - id: str | None = None, - task_queue: str | None = None, - cancellation_type: ChildWorkflowCancellationType = ChildWorkflowCancellationType.WAIT_CANCELLATION_COMPLETED, - parent_close_policy: ParentClosePolicy = ParentClosePolicy.TERMINATE, - execution_timeout: timedelta | None = None, - run_timeout: timedelta | None = None, - task_timeout: timedelta | None = None, - id_reuse_policy: temporalio.common.WorkflowIDReusePolicy = temporalio.common.WorkflowIDReusePolicy.ALLOW_DUPLICATE, - retry_policy: temporalio.common.RetryPolicy | None = None, - cron_schedule: str = "", - memo: Mapping[str, Any] | None = None, - search_attributes: None - | ( - temporalio.common.SearchAttributes | temporalio.common.TypedSearchAttributes - ) = None, - versioning_intent: VersioningIntent | None = None, - static_summary: str | None = None, - static_details: str | None = None, - priority: temporalio.common.Priority = temporalio.common.Priority.default, -) -> ReturnType: ... - - -# Overload for string-name workflow -@overload -async def execute_child_workflow( - workflow: str, - arg: Any = temporalio.common._arg_unset, - *, - args: Sequence[Any] = [], - id: str | None = None, - task_queue: str | None = None, - result_type: type | None = None, - cancellation_type: ChildWorkflowCancellationType = ChildWorkflowCancellationType.WAIT_CANCELLATION_COMPLETED, - parent_close_policy: ParentClosePolicy = ParentClosePolicy.TERMINATE, - execution_timeout: timedelta | None = None, - run_timeout: timedelta | None = None, - task_timeout: timedelta | None = None, - id_reuse_policy: temporalio.common.WorkflowIDReusePolicy = temporalio.common.WorkflowIDReusePolicy.ALLOW_DUPLICATE, - retry_policy: temporalio.common.RetryPolicy | None = None, - cron_schedule: str = "", - memo: Mapping[str, Any] | None = None, - search_attributes: None - | ( - temporalio.common.SearchAttributes | temporalio.common.TypedSearchAttributes - ) = None, - versioning_intent: VersioningIntent | None = None, - static_summary: str | None = None, - static_details: str | None = None, - priority: temporalio.common.Priority = temporalio.common.Priority.default, -) -> Any: ... - - -async def execute_child_workflow( - workflow: Any, - arg: Any = temporalio.common._arg_unset, - *, - args: Sequence[Any] = [], - id: str | None = None, - task_queue: str | None = None, - result_type: type | None = None, - cancellation_type: ChildWorkflowCancellationType = ChildWorkflowCancellationType.WAIT_CANCELLATION_COMPLETED, - parent_close_policy: ParentClosePolicy = ParentClosePolicy.TERMINATE, - execution_timeout: timedelta | None = None, - run_timeout: timedelta | None = None, - task_timeout: timedelta | None = None, - id_reuse_policy: temporalio.common.WorkflowIDReusePolicy = temporalio.common.WorkflowIDReusePolicy.ALLOW_DUPLICATE, - retry_policy: temporalio.common.RetryPolicy | None = None, - cron_schedule: str = "", - memo: Mapping[str, Any] | None = None, - search_attributes: None - | ( - temporalio.common.SearchAttributes | temporalio.common.TypedSearchAttributes - ) = None, - versioning_intent: VersioningIntent | None = None, - static_summary: str | None = None, - static_details: str | None = None, - priority: temporalio.common.Priority = temporalio.common.Priority.default, -) -> Any: - """Start a child workflow and wait for completion. - - This is a shortcut for ``await (await`` :py:meth:`start_child_workflow` ``)``. - """ - temporalio.common._warn_on_deprecated_search_attributes(search_attributes) - # We call the runtime directly instead of top-level start_child_workflow to - # ensure we don't miss new parameters - handle = await _Runtime.current().workflow_start_child_workflow( - workflow, - *temporalio.common._arg_or_args(arg, args), - id=id or str(uuid4()), - task_queue=task_queue, - result_type=result_type, - cancellation_type=cancellation_type, - parent_close_policy=parent_close_policy, - execution_timeout=execution_timeout, - run_timeout=run_timeout, - task_timeout=task_timeout, - id_reuse_policy=id_reuse_policy, - retry_policy=retry_policy, - cron_schedule=cron_schedule, - memo=memo, - search_attributes=search_attributes, - versioning_intent=versioning_intent, - static_summary=static_summary, - static_details=static_details, - priority=priority, - ) - return await handle - - -class NexusOperationHandle(Generic[OutputT]): - """Handle for interacting with a Nexus operation.""" - - # TODO(nexus-preview): should attempts to instantiate directly throw? - - def cancel(self) -> bool: - """Request cancellation of the operation.""" - raise NotImplementedError - - def __await__(self) -> Generator[Any, Any, OutputT]: - """Support await.""" - raise NotImplementedError - - @property - def operation_token(self) -> str | None: - """The operation token for this handle.""" - raise NotImplementedError - - -class ExternalWorkflowHandle(Generic[SelfType]): - """Handle for interacting with an external workflow. - - This is created via :py:func:`get_external_workflow_handle` or - :py:func:`get_external_workflow_handle_for`. - """ - - @property - def id(self) -> str: - """ID for the workflow.""" - raise NotImplementedError - - @property - def run_id(self) -> str | None: - """Run ID for the workflow if any.""" - raise NotImplementedError - - @overload - async def signal( - self, - signal: MethodSyncOrAsyncNoParam[SelfType, None], - ) -> None: ... - - @overload - async def signal( - self, - signal: MethodSyncOrAsyncSingleParam[SelfType, ParamType, None], - arg: ParamType, - ) -> None: ... - - @overload - async def signal( - self, - signal: str, - arg: Any = temporalio.common._arg_unset, - *, - args: Sequence[Any] = [], - ) -> None: ... - - async def signal( - self, - signal: str | Callable, # type: ignore[reportUnusedParameter] - arg: Any = temporalio.common._arg_unset, # type: ignore[reportUnusedParameter] - *, - args: Sequence[Any] = [], # type: ignore[reportUnusedParameter] - ) -> None: - """Signal this external workflow. - - Args: - signal: Name or method reference for the signal. - arg: Single argument to the signal. - args: Multiple arguments to the signal. Cannot be set if arg is. - - """ - raise NotImplementedError - - async def cancel(self) -> None: - """Send a cancellation request to this external workflow. - - This will fail if the workflow cannot accept the request (e.g. if the - workflow is not found). - """ - raise NotImplementedError - - -def get_external_workflow_handle( - workflow_id: str, - *, - run_id: str | None = None, -) -> ExternalWorkflowHandle[Any]: - """Get a workflow handle to an existing workflow by its ID. - - Args: - workflow_id: Workflow ID to get a handle to. - run_id: Optional run ID for the workflow. - - Returns: - The external workflow handle. - """ - return _Runtime.current().workflow_get_external_workflow_handle( - workflow_id, run_id=run_id - ) - - -def get_external_workflow_handle_for( - workflow: MethodAsyncNoParam[SelfType, Any] # type: ignore[reportUnusedParameter] - | MethodAsyncSingleParam[SelfType, Any, Any], - workflow_id: str, - *, - run_id: str | None = None, -) -> ExternalWorkflowHandle[SelfType]: - """Get a typed workflow handle to an existing workflow by its ID. - - This is the same as :py:func:`get_external_workflow_handle` but typed. Note, - the workflow type given is not validated, it is only for typing. - - Args: - workflow: The workflow run method to use for typing the handle. - workflow_id: Workflow ID to get a handle to. - run_id: Optional run ID for the workflow. - - Returns: - The external workflow handle. - """ - return get_external_workflow_handle(workflow_id, run_id=run_id) - - -class ContinueAsNewError(BaseException): - """Error thrown by :py:func:`continue_as_new`. - - This should not be caught, but instead be allowed to throw out of the - workflow which then triggers the continue as new. This should never be - instantiated directly. - """ - - def __init__(self, *args: object) -> None: - """Direct instantiation is disabled. Use :py:func:`continue_as_new`.""" - if type(self) == ContinueAsNewError: - raise RuntimeError("Cannot instantiate ContinueAsNewError directly") - super().__init__(*args) - - -# Overload for self (unfortunately, cannot type args) -@overload -def continue_as_new( - arg: Any = temporalio.common._arg_unset, - *, - args: Sequence[Any] = [], - task_queue: str | None = None, - run_timeout: timedelta | None = None, - task_timeout: timedelta | None = None, - retry_policy: temporalio.common.RetryPolicy | None = None, - memo: Mapping[str, Any] | None = None, - search_attributes: None - | ( - temporalio.common.SearchAttributes | temporalio.common.TypedSearchAttributes - ) = None, - versioning_intent: VersioningIntent | None = None, - initial_versioning_behavior: ContinueAsNewVersioningBehavior | None = None, -) -> NoReturn: ... - - -# Overload for no-param workflow -@overload -def continue_as_new( - *, - workflow: MethodAsyncNoParam[SelfType, Any], - task_queue: str | None = None, - run_timeout: timedelta | None = None, - task_timeout: timedelta | None = None, - retry_policy: temporalio.common.RetryPolicy | None = None, - memo: Mapping[str, Any] | None = None, - search_attributes: None - | ( - temporalio.common.SearchAttributes | temporalio.common.TypedSearchAttributes - ) = None, - versioning_intent: VersioningIntent | None = None, - initial_versioning_behavior: ContinueAsNewVersioningBehavior | None = None, -) -> NoReturn: ... - - -# Overload for single-param workflow -@overload -def continue_as_new( - arg: ParamType, - *, - workflow: MethodAsyncSingleParam[SelfType, ParamType, Any], - task_queue: str | None = None, - run_timeout: timedelta | None = None, - task_timeout: timedelta | None = None, - retry_policy: temporalio.common.RetryPolicy | None = None, - memo: Mapping[str, Any] | None = None, - search_attributes: None - | ( - temporalio.common.SearchAttributes | temporalio.common.TypedSearchAttributes - ) = None, - versioning_intent: VersioningIntent | None = None, - initial_versioning_behavior: ContinueAsNewVersioningBehavior | None = None, -) -> NoReturn: ... - - -# Overload for multi-param workflow -@overload -def continue_as_new( - *, - workflow: Callable[Concatenate[SelfType, MultiParamSpec], Awaitable[Any]], - args: Sequence[Any], - task_queue: str | None = None, - run_timeout: timedelta | None = None, - task_timeout: timedelta | None = None, - retry_policy: temporalio.common.RetryPolicy | None = None, - memo: Mapping[str, Any] | None = None, - search_attributes: None - | ( - temporalio.common.SearchAttributes | temporalio.common.TypedSearchAttributes - ) = None, - versioning_intent: VersioningIntent | None = None, - initial_versioning_behavior: ContinueAsNewVersioningBehavior | None = None, -) -> NoReturn: ... - - -# Overload for string-name workflow -@overload -def continue_as_new( - *, - workflow: str, - args: Sequence[Any] = [], - task_queue: str | None = None, - run_timeout: timedelta | None = None, - task_timeout: timedelta | None = None, - retry_policy: temporalio.common.RetryPolicy | None = None, - memo: Mapping[str, Any] | None = None, - search_attributes: None - | ( - temporalio.common.SearchAttributes | temporalio.common.TypedSearchAttributes - ) = None, - versioning_intent: VersioningIntent | None = None, - initial_versioning_behavior: ContinueAsNewVersioningBehavior | None = None, -) -> NoReturn: ... - - -def continue_as_new( - arg: Any = temporalio.common._arg_unset, - *, - args: Sequence[Any] = [], - workflow: None | Callable | str = None, - task_queue: str | None = None, - run_timeout: timedelta | None = None, - task_timeout: timedelta | None = None, - retry_policy: temporalio.common.RetryPolicy | None = None, - memo: Mapping[str, Any] | None = None, - search_attributes: None - | ( - temporalio.common.SearchAttributes | temporalio.common.TypedSearchAttributes - ) = None, - versioning_intent: VersioningIntent | None = None, - initial_versioning_behavior: ContinueAsNewVersioningBehavior | None = None, -) -> NoReturn: - """Stop the workflow immediately and continue as new. - - Args: - arg: Single argument to the continued workflow. - args: Multiple arguments to the continued workflow. Cannot be set if arg - is. - workflow: Specific workflow to continue to. Defaults to the current - workflow. - task_queue: Task queue to run the workflow on. Defaults to the current - workflow's task queue. - run_timeout: Timeout of a single workflow run. Defaults to the current - workflow's run timeout. - task_timeout: Timeout of a single workflow task. Defaults to the current - workflow's task timeout. - memo: Memo for the workflow. Defaults to the current workflow's memo. - search_attributes: Search attributes for the workflow. Defaults to the - current workflow's search attributes. The dictionary form of this is - DEPRECATED. - versioning_intent: When using the Worker Versioning feature, specifies whether this Workflow - should Continue-as-New onto a worker with a compatible Build Id or not. - Deprecated: Use Worker Deployment versioning instead. - - Returns: - Never returns, always raises a :py:class:`ContinueAsNewError`. - - Raises: - ContinueAsNewError: Always raised by this function. Should not be caught - but instead be allowed to - """ - temporalio.common._warn_on_deprecated_search_attributes(search_attributes) - _Runtime.current().workflow_continue_as_new( - *temporalio.common._arg_or_args(arg, args), - workflow=workflow, - task_queue=task_queue, - run_timeout=run_timeout, - task_timeout=task_timeout, - retry_policy=retry_policy, - memo=memo, - search_attributes=search_attributes, - versioning_intent=versioning_intent, - initial_versioning_behavior=initial_versioning_behavior, - ) - - -def get_signal_handler(name: str) -> Callable | None: - """Get the signal handler for the given name if any. - - This includes handlers created via the ``@workflow.signal`` decorator. - - Args: - name: Name of the signal. - - Returns: - Callable for the signal if any. If a handler is not found for the name, - this will not return the dynamic handler even if there is one. - """ - return _Runtime.current().workflow_get_signal_handler(name) - - -def set_signal_handler(name: str, handler: Callable | None) -> None: - """Set or unset the signal handler for the given name. - - This overrides any existing handlers for the given name, including handlers - created via the ``@workflow.signal`` decorator. - - When set, all unhandled past signals for the given name are immediately sent - to the handler. - - Args: - name: Name of the signal. - handler: Callable to set or None to unset. - """ - _Runtime.current().workflow_set_signal_handler(name, handler) - - -def get_dynamic_signal_handler() -> Callable | None: - """Get the dynamic signal handler if any. - - This includes dynamic handlers created via the ``@workflow.signal`` - decorator. - - Returns: - Callable for the dynamic signal handler if any. - """ - return _Runtime.current().workflow_get_signal_handler(None) - - -def set_dynamic_signal_handler(handler: Callable | None) -> None: - """Set or unset the dynamic signal handler. - - This overrides the existing dynamic handler even if it was created via the - ``@workflow.signal`` decorator. - - When set, all unhandled past signals are immediately sent to the handler. - - Args: - handler: Callable to set or None to unset. - """ - _Runtime.current().workflow_set_signal_handler(None, handler) - - -def get_query_handler(name: str) -> Callable | None: - """Get the query handler for the given name if any. - - This includes handlers created via the ``@workflow.query`` decorator. - - Args: - name: Name of the query. - - Returns: - Callable for the query if any. If a handler is not found for the name, - this will not return the dynamic handler even if there is one. - """ - return _Runtime.current().workflow_get_query_handler(name) - - -def set_query_handler(name: str, handler: Callable | None) -> None: - """Set or unset the query handler for the given name. - - This overrides any existing handlers for the given name, including handlers - created via the ``@workflow.query`` decorator. - - Args: - name: Name of the query. - handler: Callable to set or None to unset. - """ - _Runtime.current().workflow_set_query_handler(name, handler) - - -def get_dynamic_query_handler() -> Callable | None: - """Get the dynamic query handler if any. - - This includes dynamic handlers created via the ``@workflow.query`` - decorator. - - Returns: - Callable for the dynamic query handler if any. - """ - return _Runtime.current().workflow_get_query_handler(None) - - -def set_dynamic_query_handler(handler: Callable | None) -> None: - """Set or unset the dynamic query handler. - - This overrides the existing dynamic handler even if it was created via the - ``@workflow.query`` decorator. - - Args: - handler: Callable to set or None to unset. - """ - _Runtime.current().workflow_set_query_handler(None, handler) - - -def get_update_handler(name: str) -> Callable | None: - """Get the update handler for the given name if any. - - This includes handlers created via the ``@workflow.update`` decorator. - - Args: - name: Name of the update. - - Returns: - Callable for the update if any. If a handler is not found for the name, - this will not return the dynamic handler even if there is one. - """ - return _Runtime.current().workflow_get_update_handler(name) - - -def set_update_handler( - name: str, handler: Callable | None, *, validator: Callable | None = None -) -> None: - """Set or unset the update handler for the given name. - - This overrides any existing handlers for the given name, including handlers - created via the ``@workflow.update`` decorator. - - Args: - name: Name of the update. - handler: Callable to set or None to unset. - validator: Callable to set or None to unset as the update validator. - """ - _Runtime.current().workflow_set_update_handler(name, handler, validator) - - -def get_dynamic_update_handler() -> Callable | None: - """Get the dynamic update handler if any. - - This includes dynamic handlers created via the ``@workflow.update`` - decorator. - - Returns: - Callable for the dynamic update handler if any. - """ - return _Runtime.current().workflow_get_update_handler(None) - - -def set_dynamic_update_handler( - handler: Callable | None, *, validator: Callable | None = None -) -> None: - """Set or unset the dynamic update handler. - - This overrides the existing dynamic handler even if it was created via the - ``@workflow.update`` decorator. - - Args: - handler: Callable to set or None to unset. - validator: Callable to set or None to unset as the update validator. - """ - _Runtime.current().workflow_set_update_handler(None, handler, validator) - - -def all_handlers_finished() -> bool: - """Whether update and signal handlers have finished executing. - - Consider waiting on this condition before workflow return or continue-as-new, to prevent - interruption of in-progress handlers by workflow exit: - ``await workflow.wait_condition(lambda: workflow.all_handlers_finished())`` - - Returns: - True if there are no in-progress update or signal handler executions. - """ - return _Runtime.current().workflow_all_handlers_finished() - - -def as_completed( - fs: Iterable[Awaitable[AnyType]], *, timeout: float | None = None -) -> Iterator[Awaitable[AnyType]]: - """Return an iterator whose values are coroutines. - - This is a deterministic version of :py:func:`asyncio.as_completed`. This - function should be used instead of that one in workflows. - """ - # Taken almost verbatim from - # https://github.com/python/cpython/blob/v3.12.3/Lib/asyncio/tasks.py#L584 - # but the "set" is changed out for a "list" and fixed up some typing/format - - if asyncio.isfuture(fs) or asyncio.iscoroutine(fs): - raise TypeError(f"expect an iterable of futures, not {type(fs).__name__}") - - done: asyncio.Queue[asyncio.Future | None] = asyncio.Queue() - - loop = asyncio.get_event_loop() - todo: list[asyncio.Future] = [asyncio.ensure_future(f, loop=loop) for f in list(fs)] - timeout_handle = None - - def _on_timeout(): - for f in todo: - f.remove_done_callback(_on_completion) - done.put_nowait(None) # Queue a dummy value for _wait_for_one(). - todo.clear() # Can't do todo.remove(f) in the loop. - - def _on_completion(f): # type:ignore[reportMissingParameterType] - if not todo: - return # _on_timeout() was here first. - todo.remove(f) - done.put_nowait(f) - if not todo and timeout_handle is not None: - timeout_handle.cancel() - - async def _wait_for_one(): - f = await done.get() - if f is None: - # Dummy value from _on_timeout(). - raise asyncio.TimeoutError - return f.result() # May raise f.exception(). - - for f in todo: - f.add_done_callback(_on_completion) - if todo and timeout is not None: - timeout_handle = loop.call_later(timeout, _on_timeout) - for _ in range(len(todo)): - yield _wait_for_one() - - -if TYPE_CHECKING: - _FT = TypeVar("_FT", bound=asyncio.Future[Any]) -else: - _FT = TypeVar("_FT", bound=asyncio.Future) - - -@overload -async def wait( # type: ignore[misc] - fs: Iterable[_FT], - *, - timeout: float | None = None, - return_when: str = asyncio.ALL_COMPLETED, -) -> tuple[list[_FT], list[_FT]]: ... - - -@overload -async def wait( - fs: Iterable[asyncio.Task[AnyType]], - *, - timeout: float | None = None, - return_when: str = asyncio.ALL_COMPLETED, -) -> tuple[list[asyncio.Task[AnyType]], list[asyncio.Task[AnyType]]]: ... - - -async def wait( - fs: Iterable, - *, - timeout: float | None = None, - return_when: str = asyncio.ALL_COMPLETED, -) -> tuple: - """Wait for the Futures or Tasks given by fs to complete. - - This is a deterministic version of :py:func:`asyncio.wait`. This function - should be used instead of that one in workflows. - """ - # Taken almost verbatim from - # https://github.com/python/cpython/blob/v3.12.3/Lib/asyncio/tasks.py#L435 - # but the "set" is changed out for a "list" and fixed up some typing/format - - if asyncio.isfuture(fs) or asyncio.iscoroutine(fs): - raise TypeError(f"Expect an iterable of Tasks/Futures, not {type(fs).__name__}") - if not fs: - raise ValueError("Sequence of Tasks/Futures must not be empty.") - if return_when not in ( - asyncio.FIRST_COMPLETED, - asyncio.FIRST_EXCEPTION, - asyncio.ALL_COMPLETED, - ): - raise ValueError(f"Invalid return_when value: {return_when}") - - fs = list(fs) - - if any(asyncio.iscoroutine(f) for f in fs): - raise TypeError("Passing coroutines is forbidden, use tasks explicitly.") - - loop = asyncio.get_running_loop() - return await _wait(fs, timeout, return_when, loop) - - -async def _wait( - fs: Iterable[asyncio.Future | asyncio.Task], - timeout: float | None, - return_when: str, - loop: asyncio.AbstractEventLoop, -) -> tuple[list, list]: - # Taken almost verbatim from - # https://github.com/python/cpython/blob/v3.12.3/Lib/asyncio/tasks.py#L522 - # but the "set" is changed out for a "list" and fixed up some typing/format - - assert fs, "Sequence of Tasks/Futures must not be empty." - waiter = loop.create_future() - timeout_handle = None - if timeout is not None: - timeout_handle = loop.call_later(timeout, _release_waiter, waiter) - counter = len(fs) # type: ignore[arg-type] - - def _on_completion(f): # type:ignore[reportMissingParameterType] - nonlocal counter - counter -= 1 - if ( - counter <= 0 - or return_when == asyncio.FIRST_COMPLETED - or return_when == asyncio.FIRST_EXCEPTION - and (not f.cancelled() and f.exception() is not None) - ): - if timeout_handle is not None: - timeout_handle.cancel() - if not waiter.done(): - waiter.set_result(None) - - for f in fs: - f.add_done_callback(_on_completion) - - try: - await waiter - finally: - if timeout_handle is not None: - timeout_handle.cancel() - for f in fs: - f.remove_done_callback(_on_completion) - - done, pending = [], [] - for f in fs: - if f.done(): - done.append(f) - else: - pending.append(f) - return done, pending - - -def _release_waiter(waiter: asyncio.Future[Any], *_args: Any) -> None: - # Taken almost verbatim from - # https://github.com/python/cpython/blob/v3.12.3/Lib/asyncio/tasks.py#L467 - - if not waiter.done(): - waiter.set_result(None) - - -def _is_unbound_method_on_cls(fn: Callable[..., Any], cls: type) -> bool: - # Python 3 does not make this easy, ref https://stackoverflow.com/questions/3589311 - return ( - inspect.isfunction(fn) - and inspect.getmodule(fn) is inspect.getmodule(cls) - and fn.__qualname__.rsplit(".", 1)[0] == cls.__name__ - ) - - -class NondeterminismError(temporalio.exceptions.TemporalError): - """Error that can be thrown during replay for non-deterministic workflow.""" - - def __init__(self, message: str) -> None: - """Initialize a nondeterminism error.""" - super().__init__(message) - self.message = message - - -class ReadOnlyContextError(temporalio.exceptions.TemporalError): - """Error thrown when trying to do mutable workflow calls in a read-only - context like a query or update validator. - """ - - def __init__(self, message: str) -> None: - """Initialize a read-only context error.""" - super().__init__(message) - self.message = message - - -class _NotInWorkflowEventLoopError(temporalio.exceptions.TemporalError): - def __init__(self, *args: object) -> None: - super().__init__("Not in workflow event loop") - self.message = "Not in workflow event loop" - - -class VersioningIntent(Enum): - """Indicates whether the user intends certain commands to be run on a compatible worker Build - Id version or not. - - `COMPATIBLE` indicates that the command should run on a worker with compatible version if - possible. It may not be possible if the target task queue does not also have knowledge of the - current worker's Build Id. - - `DEFAULT` indicates that the command should run on the target task queue's current - overall-default Build Id. - - Where this type is accepted optionally, an unset value indicates that the SDK should choose the - most sensible default behavior for the type of command, accounting for whether the command will - be run on the same task queue as the current worker. - - .. deprecated:: - Use Worker Deployment versioning instead. - """ - - COMPATIBLE = 1 - DEFAULT = 2 - - def _to_proto(self) -> temporalio.bridge.proto.common.VersioningIntent.ValueType: - if self == VersioningIntent.COMPATIBLE: - return temporalio.bridge.proto.common.VersioningIntent.COMPATIBLE - elif self == VersioningIntent.DEFAULT: - return temporalio.bridge.proto.common.VersioningIntent.DEFAULT - return temporalio.bridge.proto.common.VersioningIntent.UNSPECIFIED - - -class ContinueAsNewVersioningBehavior(IntEnum): - """Experimental. Optionally decide the versioning behavior that the first task of the new run should use. - For example, choose to AutoUpgrade on continue-as-new instead of inheriting the pinned version - of the previous run. - """ - - UNSPECIFIED = int( - temporalio.api.enums.v1.ContinueAsNewVersioningBehavior.CONTINUE_AS_NEW_VERSIONING_BEHAVIOR_UNSPECIFIED - ) - """An initial versioning behavior is not set, follow the existing continue-as-new inheritance semantics. - See https://docs.temporal.io/worker-versioning#inheritance-semantics for more detail. - """ - - AUTO_UPGRADE = int( - temporalio.api.enums.v1.ContinueAsNewVersioningBehavior.CONTINUE_AS_NEW_VERSIONING_BEHAVIOR_AUTO_UPGRADE - ) - """Start the new run with AutoUpgrade behavior. Use the Target Version of the workflow's task queue at - start-time, as AutoUpgrade workflows do. After the first workflow task completes, use whatever - Versioning Behavior the workflow is annotated with in the workflow code. - - Note that if the previous workflow had a Pinned override, that override will be inherited by the - new workflow run regardless of the ContinueAsNewVersioningBehavior specified in the continue-as-new - command. If a Pinned override is inherited by the new run, and the new run starts with AutoUpgrade - behavior, the base version of the new run will be the Target Version as described above, but the - effective version will be whatever is specified by the Versioning Override until the override is removed. - """ - - USE_RAMPING_VERSION = int( - temporalio.api.enums.v1.ContinueAsNewVersioningBehavior.CONTINUE_AS_NEW_VERSIONING_BEHAVIOR_USE_RAMPING_VERSION - ) - """Use the Ramping Version of the workflow's task queue at start time, regardless of the workflow's - Target Version. After the first workflow task completes, the workflow will use whatever Versioning - Behavior it is annotated with. If there is no Ramping Version by the time that the first workflow task - is dispatched, it will be sent to the Current Version. - - It is highly discouraged to use this if the workflow is annotated with AutoUpgrade behavior, because - this setting ONLY applies to the first task of the workflow. If, after the first task, the workflow - is AutoUpgrade, it will behave like a normal AutoUpgrade workflow and go to the Target Version, which - may be the Current Version instead of the Ramping Version. - - Note that if the workflow being continued has a Pinned override, that override will be inherited by the - new workflow run regardless of the ContinueAsNewVersioningBehavior specified in the continue-as-new - command. Versioning Override always takes precedence until it's removed manually via - UpdateWorkflowExecutionOptions. - """ - - -ServiceT = TypeVar("ServiceT") - - -class NexusOperationCancellationType(IntEnum): - """Defines behavior of a Nexus operation when the caller workflow initiates cancellation. - - Pass one of these values to :py:meth:`NexusClient.start_operation` to define cancellation - behavior. - - To initiate cancellation, use :py:meth:`NexusOperationHandle.cancel` and then ``await`` the - operation handle. This will result in a :py:class:`exceptions.NexusOperationError`. The values - of this enum define what is guaranteed to have happened by that point. - """ - - ABANDON = int(temporalio.bridge.proto.nexus.NexusOperationCancellationType.ABANDON) - """Do not send any cancellation request to the operation handler; just report cancellation to the caller""" - - TRY_CANCEL = int( - temporalio.bridge.proto.nexus.NexusOperationCancellationType.TRY_CANCEL - ) - """Send a cancellation request but immediately report cancellation to the caller. Note that this - does not guarantee that cancellation is delivered to the operation handler if the caller exits - before the delivery is done. - """ - - WAIT_REQUESTED = int( - temporalio.bridge.proto.nexus.NexusOperationCancellationType.WAIT_CANCELLATION_REQUESTED - ) - """Send a cancellation request and wait for confirmation that the request was received. - Does not wait for the operation to complete. - """ - - WAIT_COMPLETED = int( - temporalio.bridge.proto.nexus.NexusOperationCancellationType.WAIT_CANCELLATION_COMPLETED - ) - """Send a cancellation request and wait for the operation to complete. - Note that the operation may not complete as cancelled (for example, if it catches the - :py:exc:`asyncio.CancelledError` resulting from the cancellation request).""" - - -class NexusClient(ABC, Generic[ServiceT]): - """A client for invoking Nexus operations. - - Example:: - - nexus_client = workflow.create_nexus_client( - endpoint=my_nexus_endpoint, - service=MyService, - ) - handle = await nexus_client.start_operation( - operation=MyService.my_operation, - input=MyOperationInput(value="hello"), - schedule_to_close_timeout=timedelta(seconds=10), - ) - result = await handle.result() - """ - - # Overload for nexusrpc.Operation - @overload - @abstractmethod - async def start_operation( - self, - operation: nexusrpc.Operation[InputT, OutputT], - input: InputT, - *, - output_type: type[OutputT] | None = None, - schedule_to_close_timeout: timedelta | None = None, - schedule_to_start_timeout: timedelta | None = None, - start_to_close_timeout: timedelta | None = None, - cancellation_type: NexusOperationCancellationType = NexusOperationCancellationType.WAIT_COMPLETED, - headers: Mapping[str, str] | None = None, - summary: str | None = None, - ) -> NexusOperationHandle[OutputT]: ... - - # Overload for string operation name - @overload - @abstractmethod - async def start_operation( - self, - operation: str, - input: Any, - *, - output_type: type[OutputT] | None = None, - schedule_to_close_timeout: timedelta | None = None, - schedule_to_start_timeout: timedelta | None = None, - start_to_close_timeout: timedelta | None = None, - cancellation_type: NexusOperationCancellationType = NexusOperationCancellationType.WAIT_COMPLETED, - headers: Mapping[str, str] | None = None, - summary: str | None = None, - ) -> NexusOperationHandle[OutputT]: ... - - # Overload for workflow_run_operation methods - @overload - @abstractmethod - async def start_operation( - self, - operation: Callable[ - [ServiceHandlerT, temporalio.nexus.WorkflowRunOperationContext, InputT], - Awaitable[temporalio.nexus.WorkflowHandle[OutputT]], - ], - input: InputT, - *, - output_type: type[OutputT] | None = None, - schedule_to_close_timeout: timedelta | None = None, - schedule_to_start_timeout: timedelta | None = None, - start_to_close_timeout: timedelta | None = None, - cancellation_type: NexusOperationCancellationType = NexusOperationCancellationType.WAIT_COMPLETED, - headers: Mapping[str, str] | None = None, - summary: str | None = None, - ) -> NexusOperationHandle[OutputT]: ... - - # Overload for sync_operation methods (async def) - @overload - @abstractmethod - async def start_operation( - self, - operation: Callable[ - [ServiceHandlerT, nexusrpc.handler.StartOperationContext, InputT], - Awaitable[OutputT], - ], - input: InputT, - *, - output_type: type[OutputT] | None = None, - schedule_to_close_timeout: timedelta | None = None, - schedule_to_start_timeout: timedelta | None = None, - start_to_close_timeout: timedelta | None = None, - cancellation_type: NexusOperationCancellationType = NexusOperationCancellationType.WAIT_COMPLETED, - headers: Mapping[str, str] | None = None, - summary: str | None = None, - ) -> NexusOperationHandle[OutputT]: ... - - # Overload for sync_operation methods (def) - @overload - @abstractmethod - async def start_operation( - self, - operation: Callable[ - [ServiceHandlerT, nexusrpc.handler.StartOperationContext, InputT], - OutputT, - ], - input: InputT, - *, - output_type: type[OutputT] | None = None, - schedule_to_close_timeout: timedelta | None = None, - schedule_to_start_timeout: timedelta | None = None, - start_to_close_timeout: timedelta | None = None, - cancellation_type: NexusOperationCancellationType = NexusOperationCancellationType.WAIT_COMPLETED, - headers: Mapping[str, str] | None = None, - summary: str | None = None, - ) -> NexusOperationHandle[OutputT]: ... - - # Overload for operation_handler - @overload - @abstractmethod - async def start_operation( - self, - operation: Callable[ - [ServiceHandlerT], nexusrpc.handler.OperationHandler[InputT, OutputT] - ], - input: InputT, - *, - output_type: type[OutputT] | None = None, - schedule_to_close_timeout: timedelta | None = None, - schedule_to_start_timeout: timedelta | None = None, - start_to_close_timeout: timedelta | None = None, - cancellation_type: NexusOperationCancellationType = NexusOperationCancellationType.WAIT_COMPLETED, - headers: Mapping[str, str] | None = None, - summary: str | None = None, - ) -> NexusOperationHandle[OutputT]: ... - - @abstractmethod - async def start_operation( - self, - operation: Any, - input: Any, - *, - output_type: type[OutputT] | None = None, - schedule_to_close_timeout: timedelta | None = None, - schedule_to_start_timeout: timedelta | None = None, - start_to_close_timeout: timedelta | None = None, - cancellation_type: NexusOperationCancellationType = NexusOperationCancellationType.WAIT_COMPLETED, - headers: Mapping[str, str] | None = None, - summary: str | None = None, - ) -> Any: - """Start a Nexus operation and return its handle. - - Args: - operation: The Nexus operation. - input: The Nexus operation input. - output_type: The Nexus operation output type. - schedule_to_close_timeout: Timeout for the entire operation attempt. - schedule_to_start_timeout: Timeout for the operation to be started. - start_to_close_timeout: Timeout for async operations to complete after starting. - headers: Headers to send with the Nexus HTTP request. - - Returns: - A handle to the Nexus operation. The result can be obtained as - ```python - await handle.result() - ``` - """ - ... - - # Overload for nexusrpc.Operation - @overload - @abstractmethod - async def execute_operation( - self, - operation: nexusrpc.Operation[InputT, OutputT], - input: InputT, - *, - output_type: type[OutputT] | None = None, - schedule_to_close_timeout: timedelta | None = None, - schedule_to_start_timeout: timedelta | None = None, - start_to_close_timeout: timedelta | None = None, - cancellation_type: NexusOperationCancellationType = NexusOperationCancellationType.WAIT_COMPLETED, - headers: Mapping[str, str] | None = None, - summary: str | None = None, - ) -> OutputT: ... - - # Overload for string operation name - @overload - @abstractmethod - async def execute_operation( - self, - operation: str, - input: Any, - *, - output_type: type[OutputT] | None = None, - schedule_to_close_timeout: timedelta | None = None, - schedule_to_start_timeout: timedelta | None = None, - start_to_close_timeout: timedelta | None = None, - cancellation_type: NexusOperationCancellationType = NexusOperationCancellationType.WAIT_COMPLETED, - headers: Mapping[str, str] | None = None, - summary: str | None = None, - ) -> OutputT: ... - - # Overload for workflow_run_operation methods - @overload - @abstractmethod - async def execute_operation( - self, - operation: Callable[ - [ServiceHandlerT, temporalio.nexus.WorkflowRunOperationContext, InputT], - Awaitable[temporalio.nexus.WorkflowHandle[OutputT]], - ], - input: InputT, - *, - output_type: type[OutputT] | None = None, - schedule_to_close_timeout: timedelta | None = None, - schedule_to_start_timeout: timedelta | None = None, - start_to_close_timeout: timedelta | None = None, - cancellation_type: NexusOperationCancellationType = NexusOperationCancellationType.WAIT_COMPLETED, - headers: Mapping[str, str] | None = None, - summary: str | None = None, - ) -> OutputT: ... - - # Overload for sync_operation methods (async def) - @overload - @abstractmethod - async def execute_operation( - self, - operation: Callable[ - [ServiceT, nexusrpc.handler.StartOperationContext, InputT], - Awaitable[OutputT], - ], - input: InputT, - *, - output_type: type[OutputT] | None = None, - schedule_to_close_timeout: timedelta | None = None, - schedule_to_start_timeout: timedelta | None = None, - start_to_close_timeout: timedelta | None = None, - cancellation_type: NexusOperationCancellationType = NexusOperationCancellationType.WAIT_COMPLETED, - headers: Mapping[str, str] | None = None, - summary: str | None = None, - ) -> OutputT: ... - - # Overload for sync_operation methods (def) - @overload - @abstractmethod - async def execute_operation( - self, - operation: Callable[ - [ServiceT, nexusrpc.handler.StartOperationContext, InputT], - OutputT, - ], - input: InputT, - *, - output_type: type[OutputT] | None = None, - schedule_to_close_timeout: timedelta | None = None, - schedule_to_start_timeout: timedelta | None = None, - start_to_close_timeout: timedelta | None = None, - cancellation_type: NexusOperationCancellationType = NexusOperationCancellationType.WAIT_COMPLETED, - headers: Mapping[str, str] | None = None, - summary: str | None = None, - ) -> OutputT: ... - - # Overload for operation_handler - @overload - @abstractmethod - async def execute_operation( - self, - operation: Callable[ - [ServiceT], - nexusrpc.handler.OperationHandler[InputT, OutputT], - ], - input: InputT, - *, - output_type: type[OutputT] | None = None, - schedule_to_close_timeout: timedelta | None = None, - schedule_to_start_timeout: timedelta | None = None, - start_to_close_timeout: timedelta | None = None, - cancellation_type: NexusOperationCancellationType = NexusOperationCancellationType.WAIT_COMPLETED, - headers: Mapping[str, str] | None = None, - summary: str | None = None, - ) -> OutputT: ... - - @abstractmethod - async def execute_operation( - self, - operation: Any, - input: Any, - *, - output_type: type[OutputT] | None = None, - schedule_to_close_timeout: timedelta | None = None, - schedule_to_start_timeout: timedelta | None = None, - start_to_close_timeout: timedelta | None = None, - cancellation_type: NexusOperationCancellationType = NexusOperationCancellationType.WAIT_COMPLETED, - headers: Mapping[str, str] | None = None, - summary: str | None = None, - ) -> Any: - """Execute a Nexus operation and return its result. - - Args: - operation: The Nexus operation. - input: The Nexus operation input. - output_type: The Nexus operation output type. - schedule_to_close_timeout: Timeout for the entire operation attempt. - schedule_to_start_timeout: Timeout for the operation to be started. - start_to_close_timeout: Timeout for async operations to complete after starting. - headers: Headers to send with the Nexus HTTP request. - - Returns: - The operation result. - """ - ... - - -class _NexusClient(NexusClient[ServiceT]): - def __init__( - self, - *, - endpoint: str, - service: type[ServiceT] | str, - ) -> None: - """Create a Nexus client. - - Args: - service: The Nexus service. - endpoint: The Nexus endpoint. - """ - # If service is not a str, then it must be a service interface or implementation - # class. - if isinstance(service, str): - self.service_name = service - elif service_defn := nexusrpc.get_service_definition(service): - self.service_name = service_defn.name - else: - raise ValueError( - f"`service` may be a name (str), or a class decorated with either " - f"@nexusrpc.handler.service_handler or @nexusrpc.service. " - f"Invalid service type: {type(service)}" - ) - self.endpoint = endpoint - - async def start_operation( - self, - operation: Any, - input: Any, - *, - output_type: type[OutputT] | None = None, - schedule_to_close_timeout: timedelta | None = None, - schedule_to_start_timeout: timedelta | None = None, - start_to_close_timeout: timedelta | None = None, - cancellation_type: NexusOperationCancellationType = NexusOperationCancellationType.WAIT_COMPLETED, - headers: Mapping[str, str] | None = None, - summary: str | None = None, - ) -> Any: - return ( - await temporalio.workflow._Runtime.current().workflow_start_nexus_operation( - endpoint=self.endpoint, - service=self.service_name, - operation=operation, - input=input, - output_type=output_type, - schedule_to_close_timeout=schedule_to_close_timeout, - schedule_to_start_timeout=schedule_to_start_timeout, - start_to_close_timeout=start_to_close_timeout, - cancellation_type=cancellation_type, - headers=headers, - summary=summary, - ) - ) - - async def execute_operation( - self, - operation: Any, - input: Any, - *, - output_type: type[OutputT] | None = None, - schedule_to_close_timeout: timedelta | None = None, - schedule_to_start_timeout: timedelta | None = None, - start_to_close_timeout: timedelta | None = None, - cancellation_type: NexusOperationCancellationType = NexusOperationCancellationType.WAIT_COMPLETED, - headers: Mapping[str, str] | None = None, - summary: str | None = None, - ) -> Any: - handle = await self.start_operation( - operation, - input, - output_type=output_type, - schedule_to_close_timeout=schedule_to_close_timeout, - schedule_to_start_timeout=schedule_to_start_timeout, - start_to_close_timeout=start_to_close_timeout, - cancellation_type=cancellation_type, - headers=headers, - summary=summary, - ) - return await handle - - -@overload -def create_nexus_client( - *, - service: type[ServiceT], - endpoint: str, -) -> NexusClient[ServiceT]: ... - - -@overload -def create_nexus_client( - *, - service: str, - endpoint: str, -) -> NexusClient[Any]: ... - - -def create_nexus_client( - *, - service: type[ServiceT] | str, - endpoint: str, -) -> NexusClient[ServiceT]: - """Create a Nexus client. - - Args: - service: The Nexus service. - endpoint: The Nexus endpoint. - """ - return _NexusClient(endpoint=endpoint, service=service) diff --git a/temporalio/workflow/__init__.py b/temporalio/workflow/__init__.py new file mode 100644 index 000000000..792b4e1e8 --- /dev/null +++ b/temporalio/workflow/__init__.py @@ -0,0 +1,320 @@ +"""Utilities that can decorate or be called inside workflows.""" + +from __future__ import annotations + +from temporalio.nexus._util import ServiceHandlerT + +from ..types import ( + AnyType, + CallableAsyncNoParam, + CallableAsyncSingleParam, + CallableAsyncType, + CallableSyncNoParam, + CallableSyncOrAsyncReturnNoneType, + CallableSyncOrAsyncType, + CallableSyncSingleParam, + CallableType, + ClassType, + MethodAsyncNoParam, + MethodAsyncSingleParam, + MethodSyncNoParam, + MethodSyncOrAsyncNoParam, + MethodSyncOrAsyncSingleParam, + MethodSyncSingleParam, + MultiParamSpec, + ParamType, + ProtocolReturnType, + ReturnType, + SelfType, +) +from ._activities import ( + ActivityCancellationType, + ActivityConfig, + ActivityHandle, + LocalActivityConfig, + _AsyncioTask, + execute_activity, + execute_activity_class, + execute_activity_method, + execute_local_activity, + execute_local_activity_class, + execute_local_activity_method, + start_activity, + start_activity_class, + start_activity_method, + start_local_activity, + start_local_activity_class, + start_local_activity_method, +) +from ._asyncio import ( + _FT, + _release_waiter, + _wait, + as_completed, + wait, +) +from ._context import ( + Info, + ParentInfo, + RootInfo, + UpdateInfo, + _current_update_info, + _Runtime, + _set_current_update_info, + current_update_info, + deprecate_patch, + extern_functions, + get_current_details, + get_last_completion_result, + get_last_failure, + has_last_completion_result, + in_workflow, + info, + instance, + is_failure_exception, + memo, + memo_value, + metric_meter, + new_random, + now, + patched, + payload_converter, + random, + random_seed, + register_random_seed_callback, + set_current_details, + sleep, + time, + time_ns, + upsert_memo, + upsert_search_attributes, + uuid4, + wait_condition, +) +from ._definition import ( + DynamicWorkflowConfig, + _Definition, + _is_unbound_method_on_cls, + _parameters_identical_up_to_naming, + defn, + dynamic_config, + init, + run, +) +from ._exceptions import ( + ContinueAsNewVersioningBehavior, + NondeterminismError, + ReadOnlyContextError, + VersioningIntent, + _NotInWorkflowEventLoopError, +) +from ._handlers import ( + HandlerUnfinishedPolicy, + UnfinishedSignalHandlersWarning, + UnfinishedUpdateHandlersWarning, + UpdateMethodMultiParam, + _assert_dynamic_handler_args, + _bind_method, + _QueryDefinition, + _SignalDefinition, + _update_validator, + _UpdateDefinition, + query, + signal, + update, +) +from ._nexus import ( + NexusClient, + NexusOperationCancellationType, + NexusOperationHandle, + ServiceT, + _NexusClient, + create_nexus_client, +) +from ._sandbox import ( + LoggerAdapter, + SandboxImportNotificationPolicy, + _build_log_context, + _imports_passed_through, + _in_sandbox, + _sandbox_import_notification_policy_override, + _sandbox_unrestricted, + logger, + unsafe, +) +from ._workflow_ops import ( + ChildWorkflowCancellationType, + ChildWorkflowConfig, + ChildWorkflowHandle, + ContinueAsNewError, + ExternalWorkflowHandle, + ParentClosePolicy, + all_handlers_finished, + continue_as_new, + execute_child_workflow, + get_dynamic_query_handler, + get_dynamic_signal_handler, + get_dynamic_update_handler, + get_external_workflow_handle, + get_external_workflow_handle_for, + get_query_handler, + get_signal_handler, + get_update_handler, + set_dynamic_query_handler, + set_dynamic_signal_handler, + set_dynamic_update_handler, + set_query_handler, + set_signal_handler, + set_update_handler, + start_child_workflow, +) + +__all__ = [ + "ActivityCancellationType", + "ActivityConfig", + "ActivityHandle", + "LocalActivityConfig", + "execute_activity", + "execute_activity_class", + "execute_activity_method", + "execute_local_activity", + "execute_local_activity_class", + "execute_local_activity_method", + "start_activity", + "start_activity_class", + "start_activity_method", + "start_local_activity", + "start_local_activity_class", + "start_local_activity_method", + "as_completed", + "wait", + "Info", + "ParentInfo", + "RootInfo", + "UpdateInfo", + "current_update_info", + "deprecate_patch", + "extern_functions", + "get_current_details", + "get_last_completion_result", + "get_last_failure", + "has_last_completion_result", + "in_workflow", + "info", + "instance", + "is_failure_exception", + "memo", + "memo_value", + "metric_meter", + "new_random", + "now", + "patched", + "payload_converter", + "random", + "random_seed", + "register_random_seed_callback", + "set_current_details", + "sleep", + "time", + "time_ns", + "upsert_memo", + "upsert_search_attributes", + "uuid4", + "wait_condition", + "DynamicWorkflowConfig", + "defn", + "dynamic_config", + "init", + "run", + "NondeterminismError", + "ReadOnlyContextError", + "VersioningIntent", + "ContinueAsNewVersioningBehavior", + "HandlerUnfinishedPolicy", + "UnfinishedSignalHandlersWarning", + "UnfinishedUpdateHandlersWarning", + "UpdateMethodMultiParam", + "query", + "signal", + "update", + "NexusClient", + "NexusOperationCancellationType", + "NexusOperationHandle", + "ServiceT", + "create_nexus_client", + "LoggerAdapter", + "SandboxImportNotificationPolicy", + "logger", + "unsafe", + "ChildWorkflowCancellationType", + "ChildWorkflowConfig", + "ChildWorkflowHandle", + "ContinueAsNewError", + "ExternalWorkflowHandle", + "ParentClosePolicy", + "all_handlers_finished", + "continue_as_new", + "execute_child_workflow", + "get_dynamic_query_handler", + "get_dynamic_signal_handler", + "get_dynamic_update_handler", + "get_external_workflow_handle", + "get_external_workflow_handle_for", + "get_query_handler", + "get_signal_handler", + "get_update_handler", + "set_dynamic_query_handler", + "set_dynamic_signal_handler", + "set_dynamic_update_handler", + "set_query_handler", + "set_signal_handler", + "set_update_handler", + "start_child_workflow", + "_AsyncioTask", + "_FT", + "_release_waiter", + "_wait", + "_current_update_info", + "_Runtime", + "_set_current_update_info", + "_Definition", + "_is_unbound_method_on_cls", + "_parameters_identical_up_to_naming", + "_NotInWorkflowEventLoopError", + "_assert_dynamic_handler_args", + "_bind_method", + "_QueryDefinition", + "_SignalDefinition", + "_update_validator", + "_UpdateDefinition", + "_NexusClient", + "_build_log_context", + "_imports_passed_through", + "_in_sandbox", + "_sandbox_import_notification_policy_override", + "_sandbox_unrestricted", + # Re-export Temporal-owned names that old temporalio/workflow.py imported + # at module scope so explicit imports from temporalio.workflow keep working. + "ServiceHandlerT", + "AnyType", + "CallableAsyncNoParam", + "CallableAsyncSingleParam", + "CallableAsyncType", + "CallableSyncNoParam", + "CallableSyncOrAsyncReturnNoneType", + "CallableSyncOrAsyncType", + "CallableSyncSingleParam", + "CallableType", + "ClassType", + "MethodAsyncNoParam", + "MethodAsyncSingleParam", + "MethodSyncNoParam", + "MethodSyncOrAsyncNoParam", + "MethodSyncOrAsyncSingleParam", + "MethodSyncSingleParam", + "MultiParamSpec", + "ParamType", + "ProtocolReturnType", + "ReturnType", + "SelfType", +] diff --git a/temporalio/workflow/_activities.py b/temporalio/workflow/_activities.py new file mode 100644 index 000000000..ef883c016 --- /dev/null +++ b/temporalio/workflow/_activities.py @@ -0,0 +1,2008 @@ +from __future__ import annotations + +import asyncio +from collections.abc import Awaitable, Callable, Sequence +from datetime import timedelta +from enum import IntEnum +from typing import TYPE_CHECKING, Any, Concatenate, Generic, TypedDict, overload + +import temporalio.bridge.proto.workflow_commands +import temporalio.common + +from ..types import ( + AnyType, + CallableAsyncNoParam, + CallableAsyncSingleParam, + CallableSyncNoParam, + CallableSyncSingleParam, + MethodAsyncNoParam, + MethodAsyncSingleParam, + MethodSyncNoParam, + MethodSyncSingleParam, + MultiParamSpec, + ParamType, + ReturnType, + SelfType, +) +from ._context import _Runtime +from ._exceptions import VersioningIntent + +__all__ = [ + "ActivityCancellationType", + "ActivityConfig", + "ActivityHandle", + "LocalActivityConfig", + "execute_activity", + "execute_activity_class", + "execute_activity_method", + "execute_local_activity", + "execute_local_activity_class", + "execute_local_activity_method", + "start_activity", + "start_activity_class", + "start_activity_method", + "start_local_activity", + "start_local_activity_class", + "start_local_activity_method", +] + +# See https://mypy.readthedocs.io/en/latest/runtime_troubles.html#using-classes-that-are-generic-in-stubs-but-not-at-runtime +if TYPE_CHECKING: + + class _AsyncioTask(asyncio.Task[AnyType]): + pass + +else: + # TODO: inherited classes should be other way around? + class _AsyncioTask(Generic[AnyType], asyncio.Task): + pass + + +class ActivityHandle(_AsyncioTask[ReturnType]): # type: ignore[type-var] + """Handle returned from :py:func:`start_activity` and + :py:func:`start_local_activity`. + + This extends :py:class:`asyncio.Task` and supports all task features. + """ + + pass + + +class ActivityCancellationType(IntEnum): + """How an activity cancellation should be handled.""" + + TRY_CANCEL = int( + temporalio.bridge.proto.workflow_commands.ActivityCancellationType.TRY_CANCEL + ) + WAIT_CANCELLATION_COMPLETED = int( + temporalio.bridge.proto.workflow_commands.ActivityCancellationType.WAIT_CANCELLATION_COMPLETED + ) + ABANDON = int( + temporalio.bridge.proto.workflow_commands.ActivityCancellationType.ABANDON + ) + + +class ActivityConfig(TypedDict, total=False): + """TypedDict of config that can be used for :py:func:`start_activity` and + :py:func:`execute_activity`. + """ + + task_queue: str | None + schedule_to_close_timeout: timedelta | None + schedule_to_start_timeout: timedelta | None + start_to_close_timeout: timedelta | None + heartbeat_timeout: timedelta | None + retry_policy: temporalio.common.RetryPolicy | None + cancellation_type: ActivityCancellationType + activity_id: str | None + versioning_intent: VersioningIntent | None + summary: str | None + priority: temporalio.common.Priority + + +# Overload for async no-param activity +@overload +def start_activity( + activity: CallableAsyncNoParam[ReturnType], + *, + task_queue: str | None = None, + schedule_to_close_timeout: timedelta | None = None, + schedule_to_start_timeout: timedelta | None = None, + start_to_close_timeout: timedelta | None = None, + heartbeat_timeout: timedelta | None = None, + retry_policy: temporalio.common.RetryPolicy | None = None, + cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, + activity_id: str | None = None, + versioning_intent: VersioningIntent | None = None, + summary: str | None = None, + priority: temporalio.common.Priority = temporalio.common.Priority.default, +) -> ActivityHandle[ReturnType]: ... + + +# Overload for sync no-param activity +@overload +def start_activity( + activity: CallableSyncNoParam[ReturnType], + *, + task_queue: str | None = None, + schedule_to_close_timeout: timedelta | None = None, + schedule_to_start_timeout: timedelta | None = None, + start_to_close_timeout: timedelta | None = None, + heartbeat_timeout: timedelta | None = None, + retry_policy: temporalio.common.RetryPolicy | None = None, + cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, + activity_id: str | None = None, + versioning_intent: VersioningIntent | None = None, + summary: str | None = None, + priority: temporalio.common.Priority = temporalio.common.Priority.default, +) -> ActivityHandle[ReturnType]: ... + + +# Overload for async single-param activity +@overload +def start_activity( + activity: CallableAsyncSingleParam[ParamType, ReturnType], + arg: ParamType, + *, + task_queue: str | None = None, + schedule_to_close_timeout: timedelta | None = None, + schedule_to_start_timeout: timedelta | None = None, + start_to_close_timeout: timedelta | None = None, + heartbeat_timeout: timedelta | None = None, + retry_policy: temporalio.common.RetryPolicy | None = None, + cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, + activity_id: str | None = None, + versioning_intent: VersioningIntent | None = None, + summary: str | None = None, + priority: temporalio.common.Priority = temporalio.common.Priority.default, +) -> ActivityHandle[ReturnType]: ... + + +# Overload for sync single-param activity +@overload +def start_activity( + activity: CallableSyncSingleParam[ParamType, ReturnType], + arg: ParamType, + *, + task_queue: str | None = None, + schedule_to_close_timeout: timedelta | None = None, + schedule_to_start_timeout: timedelta | None = None, + start_to_close_timeout: timedelta | None = None, + heartbeat_timeout: timedelta | None = None, + retry_policy: temporalio.common.RetryPolicy | None = None, + cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, + activity_id: str | None = None, + versioning_intent: VersioningIntent | None = None, + summary: str | None = None, + priority: temporalio.common.Priority = temporalio.common.Priority.default, +) -> ActivityHandle[ReturnType]: ... + + +# Overload for async multi-param activity +@overload +def start_activity( + activity: Callable[..., Awaitable[ReturnType]], + *, + args: Sequence[Any], + task_queue: str | None = None, + schedule_to_close_timeout: timedelta | None = None, + schedule_to_start_timeout: timedelta | None = None, + start_to_close_timeout: timedelta | None = None, + heartbeat_timeout: timedelta | None = None, + retry_policy: temporalio.common.RetryPolicy | None = None, + cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, + activity_id: str | None = None, + versioning_intent: VersioningIntent | None = None, + summary: str | None = None, + priority: temporalio.common.Priority = temporalio.common.Priority.default, +) -> ActivityHandle[ReturnType]: ... + + +# Overload for sync multi-param activity +@overload +def start_activity( + activity: Callable[..., ReturnType], + *, + args: Sequence[Any], + task_queue: str | None = None, + schedule_to_close_timeout: timedelta | None = None, + schedule_to_start_timeout: timedelta | None = None, + start_to_close_timeout: timedelta | None = None, + heartbeat_timeout: timedelta | None = None, + retry_policy: temporalio.common.RetryPolicy | None = None, + cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, + activity_id: str | None = None, + versioning_intent: VersioningIntent | None = None, + summary: str | None = None, + priority: temporalio.common.Priority = temporalio.common.Priority.default, +) -> ActivityHandle[ReturnType]: ... + + +# Overload for string-name activity +@overload +def start_activity( + activity: str, + arg: Any = temporalio.common._arg_unset, + *, + args: Sequence[Any] = [], + task_queue: str | None = None, + result_type: type | None = None, + schedule_to_close_timeout: timedelta | None = None, + schedule_to_start_timeout: timedelta | None = None, + start_to_close_timeout: timedelta | None = None, + heartbeat_timeout: timedelta | None = None, + retry_policy: temporalio.common.RetryPolicy | None = None, + cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, + activity_id: str | None = None, + versioning_intent: VersioningIntent | None = None, + summary: str | None = None, + priority: temporalio.common.Priority = temporalio.common.Priority.default, +) -> ActivityHandle[Any]: ... + + +def start_activity( + activity: Any, + arg: Any = temporalio.common._arg_unset, + *, + args: Sequence[Any] = [], + task_queue: str | None = None, + result_type: type | None = None, + schedule_to_close_timeout: timedelta | None = None, + schedule_to_start_timeout: timedelta | None = None, + start_to_close_timeout: timedelta | None = None, + heartbeat_timeout: timedelta | None = None, + retry_policy: temporalio.common.RetryPolicy | None = None, + cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, + activity_id: str | None = None, + versioning_intent: VersioningIntent | None = None, + summary: str | None = None, + priority: temporalio.common.Priority = temporalio.common.Priority.default, +) -> ActivityHandle[Any]: + """Start an activity and return its handle. + + At least one of ``schedule_to_close_timeout`` or ``start_to_close_timeout`` + must be present. + + Args: + activity: Activity name or function reference. + arg: Single argument to the activity. + args: Multiple arguments to the activity. Cannot be set if arg is. + task_queue: Task queue to run the activity on. Defaults to the current + workflow's task queue. + result_type: For string activities, this can set the specific result + type hint to deserialize into. + schedule_to_close_timeout: Max amount of time the activity can take from + first being scheduled to being completed before it times out. This + is inclusive of all retries. + schedule_to_start_timeout: Max amount of time the activity can take to + be started from first being scheduled. + start_to_close_timeout: Max amount of time a single activity run can + take from when it starts to when it completes. This is per retry. + heartbeat_timeout: How frequently an activity must invoke heartbeat + while running before it is considered timed out. + retry_policy: How an activity is retried on failure. If unset, a + server-defined default is used. Set maximum attempts to 1 to disable + retries. + cancellation_type: How the activity is treated when it is cancelled from + the workflow. + activity_id: Optional unique identifier for the activity. This is an + advanced setting that should not be set unless users are sure they + need to. Contact Temporal before setting this value. + versioning_intent: When using the Worker Versioning feature, specifies whether this Activity + should run on a worker with a compatible Build Id or not. + Deprecated: Use Worker Deployment versioning instead. + summary: A single-line fixed summary for this activity that may appear in UI/CLI. + This can be in single-line Temporal markdown format. + priority: Priority of the activity. + + Returns: + An activity handle to the activity which is an async task. + """ + return _Runtime.current().workflow_start_activity( + activity, + *temporalio.common._arg_or_args(arg, args), + task_queue=task_queue, + result_type=result_type, + schedule_to_close_timeout=schedule_to_close_timeout, + schedule_to_start_timeout=schedule_to_start_timeout, + start_to_close_timeout=start_to_close_timeout, + heartbeat_timeout=heartbeat_timeout, + retry_policy=retry_policy, + cancellation_type=cancellation_type, + activity_id=activity_id, + versioning_intent=versioning_intent, + summary=summary, + priority=priority, + ) + + +# Overload for async no-param activity +@overload +async def execute_activity( + activity: CallableAsyncNoParam[ReturnType], + *, + task_queue: str | None = None, + schedule_to_close_timeout: timedelta | None = None, + schedule_to_start_timeout: timedelta | None = None, + start_to_close_timeout: timedelta | None = None, + heartbeat_timeout: timedelta | None = None, + retry_policy: temporalio.common.RetryPolicy | None = None, + cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, + activity_id: str | None = None, + versioning_intent: VersioningIntent | None = None, + summary: str | None = None, + priority: temporalio.common.Priority = temporalio.common.Priority.default, +) -> ReturnType: ... + + +# Overload for sync no-param activity +@overload +async def execute_activity( + activity: CallableSyncNoParam[ReturnType], + *, + task_queue: str | None = None, + schedule_to_close_timeout: timedelta | None = None, + schedule_to_start_timeout: timedelta | None = None, + start_to_close_timeout: timedelta | None = None, + heartbeat_timeout: timedelta | None = None, + retry_policy: temporalio.common.RetryPolicy | None = None, + cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, + activity_id: str | None = None, + versioning_intent: VersioningIntent | None = None, + summary: str | None = None, + priority: temporalio.common.Priority = temporalio.common.Priority.default, +) -> ReturnType: ... + + +# Overload for async single-param activity +@overload +async def execute_activity( + activity: CallableAsyncSingleParam[ParamType, ReturnType], + arg: ParamType, + *, + task_queue: str | None = None, + schedule_to_close_timeout: timedelta | None = None, + schedule_to_start_timeout: timedelta | None = None, + start_to_close_timeout: timedelta | None = None, + heartbeat_timeout: timedelta | None = None, + retry_policy: temporalio.common.RetryPolicy | None = None, + cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, + activity_id: str | None = None, + versioning_intent: VersioningIntent | None = None, + summary: str | None = None, + priority: temporalio.common.Priority = temporalio.common.Priority.default, +) -> ReturnType: ... + + +# Overload for sync single-param activity +@overload +async def execute_activity( + activity: CallableSyncSingleParam[ParamType, ReturnType], + arg: ParamType, + *, + task_queue: str | None = None, + schedule_to_close_timeout: timedelta | None = None, + schedule_to_start_timeout: timedelta | None = None, + start_to_close_timeout: timedelta | None = None, + heartbeat_timeout: timedelta | None = None, + retry_policy: temporalio.common.RetryPolicy | None = None, + cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, + activity_id: str | None = None, + versioning_intent: VersioningIntent | None = None, + summary: str | None = None, + priority: temporalio.common.Priority = temporalio.common.Priority.default, +) -> ReturnType: ... + + +# Overload for async multi-param activity +@overload +async def execute_activity( + activity: Callable[..., Awaitable[ReturnType]], + *, + args: Sequence[Any], + task_queue: str | None = None, + schedule_to_close_timeout: timedelta | None = None, + schedule_to_start_timeout: timedelta | None = None, + start_to_close_timeout: timedelta | None = None, + heartbeat_timeout: timedelta | None = None, + retry_policy: temporalio.common.RetryPolicy | None = None, + cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, + activity_id: str | None = None, + versioning_intent: VersioningIntent | None = None, + summary: str | None = None, + priority: temporalio.common.Priority = temporalio.common.Priority.default, +) -> ReturnType: ... + + +# Overload for sync multi-param activity +@overload +async def execute_activity( + activity: Callable[..., ReturnType], + *, + args: Sequence[Any], + task_queue: str | None = None, + schedule_to_close_timeout: timedelta | None = None, + schedule_to_start_timeout: timedelta | None = None, + start_to_close_timeout: timedelta | None = None, + heartbeat_timeout: timedelta | None = None, + retry_policy: temporalio.common.RetryPolicy | None = None, + cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, + activity_id: str | None = None, + versioning_intent: VersioningIntent | None = None, + summary: str | None = None, + priority: temporalio.common.Priority = temporalio.common.Priority.default, +) -> ReturnType: ... + + +# Overload for string-name activity +@overload +async def execute_activity( + activity: str, + arg: Any = temporalio.common._arg_unset, + *, + args: Sequence[Any] = [], + task_queue: str | None = None, + result_type: type | None = None, + schedule_to_close_timeout: timedelta | None = None, + schedule_to_start_timeout: timedelta | None = None, + start_to_close_timeout: timedelta | None = None, + heartbeat_timeout: timedelta | None = None, + retry_policy: temporalio.common.RetryPolicy | None = None, + cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, + activity_id: str | None = None, + versioning_intent: VersioningIntent | None = None, + summary: str | None = None, + priority: temporalio.common.Priority = temporalio.common.Priority.default, +) -> Any: ... + + +async def execute_activity( + activity: Any, + arg: Any = temporalio.common._arg_unset, + *, + args: Sequence[Any] = [], + task_queue: str | None = None, + result_type: type | None = None, + schedule_to_close_timeout: timedelta | None = None, + schedule_to_start_timeout: timedelta | None = None, + start_to_close_timeout: timedelta | None = None, + heartbeat_timeout: timedelta | None = None, + retry_policy: temporalio.common.RetryPolicy | None = None, + cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, + activity_id: str | None = None, + versioning_intent: VersioningIntent | None = None, + summary: str | None = None, + priority: temporalio.common.Priority = temporalio.common.Priority.default, +) -> Any: + """Start an activity and wait for completion. + + This is a shortcut for ``await`` :py:meth:`start_activity`. + """ + # We call the runtime directly instead of top-level start_activity to ensure + # we don't miss new parameters + return await _Runtime.current().workflow_start_activity( + activity, + *temporalio.common._arg_or_args(arg, args), + task_queue=task_queue, + result_type=result_type, + schedule_to_close_timeout=schedule_to_close_timeout, + schedule_to_start_timeout=schedule_to_start_timeout, + start_to_close_timeout=start_to_close_timeout, + heartbeat_timeout=heartbeat_timeout, + retry_policy=retry_policy, + cancellation_type=cancellation_type, + activity_id=activity_id, + versioning_intent=versioning_intent, + summary=summary, + priority=priority, + ) + + +# Overload for async no-param activity +@overload +def start_activity_class( + activity: type[CallableAsyncNoParam[ReturnType]], + *, + task_queue: str | None = None, + schedule_to_close_timeout: timedelta | None = None, + schedule_to_start_timeout: timedelta | None = None, + start_to_close_timeout: timedelta | None = None, + heartbeat_timeout: timedelta | None = None, + retry_policy: temporalio.common.RetryPolicy | None = None, + cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, + activity_id: str | None = None, + versioning_intent: VersioningIntent | None = None, + summary: str | None = None, + priority: temporalio.common.Priority = temporalio.common.Priority.default, +) -> ActivityHandle[ReturnType]: ... + + +# Overload for sync no-param activity +@overload +def start_activity_class( + activity: type[CallableSyncNoParam[ReturnType]], + *, + task_queue: str | None = None, + schedule_to_close_timeout: timedelta | None = None, + schedule_to_start_timeout: timedelta | None = None, + start_to_close_timeout: timedelta | None = None, + heartbeat_timeout: timedelta | None = None, + retry_policy: temporalio.common.RetryPolicy | None = None, + cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, + activity_id: str | None = None, + versioning_intent: VersioningIntent | None = None, + summary: str | None = None, + priority: temporalio.common.Priority = temporalio.common.Priority.default, +) -> ActivityHandle[ReturnType]: ... + + +# Overload for async single-param activity +@overload +def start_activity_class( + activity: type[CallableAsyncSingleParam[ParamType, ReturnType]], + arg: ParamType, + *, + task_queue: str | None = None, + schedule_to_close_timeout: timedelta | None = None, + schedule_to_start_timeout: timedelta | None = None, + start_to_close_timeout: timedelta | None = None, + heartbeat_timeout: timedelta | None = None, + retry_policy: temporalio.common.RetryPolicy | None = None, + cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, + activity_id: str | None = None, + versioning_intent: VersioningIntent | None = None, + summary: str | None = None, + priority: temporalio.common.Priority = temporalio.common.Priority.default, +) -> ActivityHandle[ReturnType]: ... + + +# Overload for sync single-param activity +@overload +def start_activity_class( + activity: type[CallableSyncSingleParam[ParamType, ReturnType]], + arg: ParamType, + *, + task_queue: str | None = None, + schedule_to_close_timeout: timedelta | None = None, + schedule_to_start_timeout: timedelta | None = None, + start_to_close_timeout: timedelta | None = None, + heartbeat_timeout: timedelta | None = None, + retry_policy: temporalio.common.RetryPolicy | None = None, + cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, + activity_id: str | None = None, + versioning_intent: VersioningIntent | None = None, + summary: str | None = None, + priority: temporalio.common.Priority = temporalio.common.Priority.default, +) -> ActivityHandle[ReturnType]: ... + + +# Overload for async multi-param activity +@overload +def start_activity_class( + activity: type[Callable[..., Awaitable[ReturnType]]], # type: ignore[reportOverlappingOverload] + *, + args: Sequence[Any], + task_queue: str | None = None, + schedule_to_close_timeout: timedelta | None = None, + schedule_to_start_timeout: timedelta | None = None, + start_to_close_timeout: timedelta | None = None, + heartbeat_timeout: timedelta | None = None, + retry_policy: temporalio.common.RetryPolicy | None = None, + cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, + activity_id: str | None = None, + versioning_intent: VersioningIntent | None = None, + summary: str | None = None, + priority: temporalio.common.Priority = temporalio.common.Priority.default, +) -> ActivityHandle[ReturnType]: ... + + +# Overload for sync multi-param activity +@overload +def start_activity_class( # type: ignore[reportOverlappingOverload] + activity: type[Callable[..., ReturnType]], # type: ignore[reportOverlappingOverload] + *, + args: Sequence[Any], + task_queue: str | None = None, + schedule_to_close_timeout: timedelta | None = None, + schedule_to_start_timeout: timedelta | None = None, + start_to_close_timeout: timedelta | None = None, + heartbeat_timeout: timedelta | None = None, + retry_policy: temporalio.common.RetryPolicy | None = None, + cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, + activity_id: str | None = None, + versioning_intent: VersioningIntent | None = None, + summary: str | None = None, + priority: temporalio.common.Priority = temporalio.common.Priority.default, +) -> ActivityHandle[ReturnType]: ... + + +def start_activity_class( + activity: type[Callable], # type: ignore[reportOverlappingOverload] + arg: Any = temporalio.common._arg_unset, + *, + args: Sequence[Any] = [], + task_queue: str | None = None, + schedule_to_close_timeout: timedelta | None = None, + schedule_to_start_timeout: timedelta | None = None, + start_to_close_timeout: timedelta | None = None, + heartbeat_timeout: timedelta | None = None, + retry_policy: temporalio.common.RetryPolicy | None = None, + cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, + activity_id: str | None = None, + versioning_intent: VersioningIntent | None = None, + summary: str | None = None, + priority: temporalio.common.Priority = temporalio.common.Priority.default, +) -> ActivityHandle[Any]: + """Start an activity from a callable class. + + See :py:meth:`start_activity` for parameter and return details. + """ + return _Runtime.current().workflow_start_activity( + activity, + *temporalio.common._arg_or_args(arg, args), + task_queue=task_queue, + result_type=None, + schedule_to_close_timeout=schedule_to_close_timeout, + schedule_to_start_timeout=schedule_to_start_timeout, + start_to_close_timeout=start_to_close_timeout, + heartbeat_timeout=heartbeat_timeout, + retry_policy=retry_policy, + cancellation_type=cancellation_type, + activity_id=activity_id, + versioning_intent=versioning_intent, + summary=summary, + priority=priority, + ) + + +# Overload for async no-param activity +@overload +async def execute_activity_class( + activity: type[CallableAsyncNoParam[ReturnType]], + *, + task_queue: str | None = None, + schedule_to_close_timeout: timedelta | None = None, + schedule_to_start_timeout: timedelta | None = None, + start_to_close_timeout: timedelta | None = None, + heartbeat_timeout: timedelta | None = None, + retry_policy: temporalio.common.RetryPolicy | None = None, + cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, + activity_id: str | None = None, + versioning_intent: VersioningIntent | None = None, + summary: str | None = None, + priority: temporalio.common.Priority = temporalio.common.Priority.default, +) -> ReturnType: ... + + +# Overload for sync no-param activity +@overload +async def execute_activity_class( + activity: type[CallableSyncNoParam[ReturnType]], + *, + task_queue: str | None = None, + schedule_to_close_timeout: timedelta | None = None, + schedule_to_start_timeout: timedelta | None = None, + start_to_close_timeout: timedelta | None = None, + heartbeat_timeout: timedelta | None = None, + retry_policy: temporalio.common.RetryPolicy | None = None, + cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, + activity_id: str | None = None, + versioning_intent: VersioningIntent | None = None, + summary: str | None = None, + priority: temporalio.common.Priority = temporalio.common.Priority.default, +) -> ReturnType: ... + + +# Overload for async single-param activity +@overload +async def execute_activity_class( + activity: type[CallableAsyncSingleParam[ParamType, ReturnType]], + arg: ParamType, + *, + task_queue: str | None = None, + schedule_to_close_timeout: timedelta | None = None, + schedule_to_start_timeout: timedelta | None = None, + start_to_close_timeout: timedelta | None = None, + heartbeat_timeout: timedelta | None = None, + retry_policy: temporalio.common.RetryPolicy | None = None, + cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, + activity_id: str | None = None, + versioning_intent: VersioningIntent | None = None, + summary: str | None = None, + priority: temporalio.common.Priority = temporalio.common.Priority.default, +) -> ReturnType: ... + + +# Overload for sync single-param activity +@overload +async def execute_activity_class( + activity: type[CallableSyncSingleParam[ParamType, ReturnType]], + arg: ParamType, + *, + task_queue: str | None = None, + schedule_to_close_timeout: timedelta | None = None, + schedule_to_start_timeout: timedelta | None = None, + start_to_close_timeout: timedelta | None = None, + heartbeat_timeout: timedelta | None = None, + retry_policy: temporalio.common.RetryPolicy | None = None, + cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, + activity_id: str | None = None, + versioning_intent: VersioningIntent | None = None, + summary: str | None = None, + priority: temporalio.common.Priority = temporalio.common.Priority.default, +) -> ReturnType: ... + + +# Overload for async multi-param activity +@overload +async def execute_activity_class( + activity: type[Callable[..., Awaitable[ReturnType]]], # type: ignore[reportOverlappingOverload] + *, + args: Sequence[Any], + task_queue: str | None = None, + schedule_to_close_timeout: timedelta | None = None, + schedule_to_start_timeout: timedelta | None = None, + start_to_close_timeout: timedelta | None = None, + heartbeat_timeout: timedelta | None = None, + retry_policy: temporalio.common.RetryPolicy | None = None, + cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, + activity_id: str | None = None, + versioning_intent: VersioningIntent | None = None, + summary: str | None = None, + priority: temporalio.common.Priority = temporalio.common.Priority.default, +) -> ReturnType: ... + + +# Overload for sync multi-param activity +@overload +async def execute_activity_class( + activity: type[Callable[..., ReturnType]], # type: ignore[reportOverlappingOverload] + *, + args: Sequence[Any], + task_queue: str | None = None, + schedule_to_close_timeout: timedelta | None = None, + schedule_to_start_timeout: timedelta | None = None, + start_to_close_timeout: timedelta | None = None, + heartbeat_timeout: timedelta | None = None, + retry_policy: temporalio.common.RetryPolicy | None = None, + cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, + activity_id: str | None = None, + versioning_intent: VersioningIntent | None = None, + summary: str | None = None, + priority: temporalio.common.Priority = temporalio.common.Priority.default, +) -> ReturnType: ... + + +async def execute_activity_class( + activity: type[Callable], # type: ignore[reportOverlappingOverload] + arg: Any = temporalio.common._arg_unset, + *, + args: Sequence[Any] = [], + task_queue: str | None = None, + schedule_to_close_timeout: timedelta | None = None, + schedule_to_start_timeout: timedelta | None = None, + start_to_close_timeout: timedelta | None = None, + heartbeat_timeout: timedelta | None = None, + retry_policy: temporalio.common.RetryPolicy | None = None, + cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, + activity_id: str | None = None, + versioning_intent: VersioningIntent | None = None, + summary: str | None = None, + priority: temporalio.common.Priority = temporalio.common.Priority.default, +) -> Any: + """Start an activity from a callable class and wait for completion. + + This is a shortcut for ``await`` :py:meth:`start_activity_class`. + """ + return await _Runtime.current().workflow_start_activity( + activity, + *temporalio.common._arg_or_args(arg, args), + task_queue=task_queue, + result_type=None, + schedule_to_close_timeout=schedule_to_close_timeout, + schedule_to_start_timeout=schedule_to_start_timeout, + start_to_close_timeout=start_to_close_timeout, + heartbeat_timeout=heartbeat_timeout, + retry_policy=retry_policy, + cancellation_type=cancellation_type, + activity_id=activity_id, + versioning_intent=versioning_intent, + summary=summary, + priority=priority, + ) + + +# Overload for async no-param activity +@overload +def start_activity_method( + activity: MethodAsyncNoParam[SelfType, ReturnType], + *, + task_queue: str | None = None, + schedule_to_close_timeout: timedelta | None = None, + schedule_to_start_timeout: timedelta | None = None, + start_to_close_timeout: timedelta | None = None, + heartbeat_timeout: timedelta | None = None, + retry_policy: temporalio.common.RetryPolicy | None = None, + cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, + activity_id: str | None = None, + versioning_intent: VersioningIntent | None = None, + summary: str | None = None, + priority: temporalio.common.Priority = temporalio.common.Priority.default, +) -> ActivityHandle[ReturnType]: ... + + +# Overload for sync no-param activity +@overload +def start_activity_method( + activity: MethodSyncNoParam[SelfType, ReturnType], + *, + task_queue: str | None = None, + schedule_to_close_timeout: timedelta | None = None, + schedule_to_start_timeout: timedelta | None = None, + start_to_close_timeout: timedelta | None = None, + heartbeat_timeout: timedelta | None = None, + retry_policy: temporalio.common.RetryPolicy | None = None, + cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, + activity_id: str | None = None, + versioning_intent: VersioningIntent | None = None, + summary: str | None = None, + priority: temporalio.common.Priority = temporalio.common.Priority.default, +) -> ActivityHandle[ReturnType]: ... + + +# Overload for async single-param activity +@overload +def start_activity_method( + activity: MethodAsyncSingleParam[SelfType, ParamType, ReturnType], + arg: ParamType, + *, + task_queue: str | None = None, + schedule_to_close_timeout: timedelta | None = None, + schedule_to_start_timeout: timedelta | None = None, + start_to_close_timeout: timedelta | None = None, + heartbeat_timeout: timedelta | None = None, + retry_policy: temporalio.common.RetryPolicy | None = None, + cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, + activity_id: str | None = None, + versioning_intent: VersioningIntent | None = None, + summary: str | None = None, + priority: temporalio.common.Priority = temporalio.common.Priority.default, +) -> ActivityHandle[ReturnType]: ... + + +# Overload for sync single-param activity +@overload +def start_activity_method( + activity: MethodSyncSingleParam[SelfType, ParamType, ReturnType], + arg: ParamType, + *, + task_queue: str | None = None, + schedule_to_close_timeout: timedelta | None = None, + schedule_to_start_timeout: timedelta | None = None, + start_to_close_timeout: timedelta | None = None, + heartbeat_timeout: timedelta | None = None, + retry_policy: temporalio.common.RetryPolicy | None = None, + cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, + activity_id: str | None = None, + versioning_intent: VersioningIntent | None = None, + summary: str | None = None, + priority: temporalio.common.Priority = temporalio.common.Priority.default, +) -> ActivityHandle[ReturnType]: ... + + +# Overload for async multi-param activity +@overload +def start_activity_method( + activity: Callable[Concatenate[SelfType, MultiParamSpec], Awaitable[ReturnType]], + *, + args: Sequence[Any], + task_queue: str | None = None, + schedule_to_close_timeout: timedelta | None = None, + schedule_to_start_timeout: timedelta | None = None, + start_to_close_timeout: timedelta | None = None, + heartbeat_timeout: timedelta | None = None, + retry_policy: temporalio.common.RetryPolicy | None = None, + cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, + activity_id: str | None = None, + versioning_intent: VersioningIntent | None = None, + summary: str | None = None, + priority: temporalio.common.Priority = temporalio.common.Priority.default, +) -> ActivityHandle[ReturnType]: ... + + +# Overload for sync multi-param activity +@overload +def start_activity_method( + activity: Callable[Concatenate[SelfType, MultiParamSpec], ReturnType], + *, + args: Sequence[Any], + task_queue: str | None = None, + schedule_to_close_timeout: timedelta | None = None, + schedule_to_start_timeout: timedelta | None = None, + start_to_close_timeout: timedelta | None = None, + heartbeat_timeout: timedelta | None = None, + retry_policy: temporalio.common.RetryPolicy | None = None, + cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, + activity_id: str | None = None, + versioning_intent: VersioningIntent | None = None, + summary: str | None = None, + priority: temporalio.common.Priority = temporalio.common.Priority.default, +) -> ActivityHandle[ReturnType]: ... + + +def start_activity_method( + activity: Callable, + arg: Any = temporalio.common._arg_unset, + *, + args: Sequence[Any] = [], + task_queue: str | None = None, + schedule_to_close_timeout: timedelta | None = None, + schedule_to_start_timeout: timedelta | None = None, + start_to_close_timeout: timedelta | None = None, + heartbeat_timeout: timedelta | None = None, + retry_policy: temporalio.common.RetryPolicy | None = None, + cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, + activity_id: str | None = None, + versioning_intent: VersioningIntent | None = None, + summary: str | None = None, + priority: temporalio.common.Priority = temporalio.common.Priority.default, +) -> ActivityHandle[Any]: + """Start an activity from a method. + + See :py:meth:`start_activity` for parameter and return details. + """ + return _Runtime.current().workflow_start_activity( + activity, + *temporalio.common._arg_or_args(arg, args), + task_queue=task_queue, + result_type=None, + schedule_to_close_timeout=schedule_to_close_timeout, + schedule_to_start_timeout=schedule_to_start_timeout, + start_to_close_timeout=start_to_close_timeout, + heartbeat_timeout=heartbeat_timeout, + retry_policy=retry_policy, + cancellation_type=cancellation_type, + activity_id=activity_id, + versioning_intent=versioning_intent, + summary=summary, + priority=priority, + ) + + +# Overload for async no-param activity +@overload +async def execute_activity_method( + activity: MethodAsyncNoParam[SelfType, ReturnType], + *, + task_queue: str | None = None, + schedule_to_close_timeout: timedelta | None = None, + schedule_to_start_timeout: timedelta | None = None, + start_to_close_timeout: timedelta | None = None, + heartbeat_timeout: timedelta | None = None, + retry_policy: temporalio.common.RetryPolicy | None = None, + cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, + activity_id: str | None = None, + versioning_intent: VersioningIntent | None = None, + summary: str | None = None, + priority: temporalio.common.Priority = temporalio.common.Priority.default, +) -> ReturnType: ... + + +# Overload for sync no-param activity +@overload +async def execute_activity_method( + activity: MethodSyncNoParam[SelfType, ReturnType], + *, + task_queue: str | None = None, + schedule_to_close_timeout: timedelta | None = None, + schedule_to_start_timeout: timedelta | None = None, + start_to_close_timeout: timedelta | None = None, + heartbeat_timeout: timedelta | None = None, + retry_policy: temporalio.common.RetryPolicy | None = None, + cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, + activity_id: str | None = None, + versioning_intent: VersioningIntent | None = None, + summary: str | None = None, + priority: temporalio.common.Priority = temporalio.common.Priority.default, +) -> ReturnType: ... + + +# Overload for async single-param activity +@overload +async def execute_activity_method( + activity: MethodAsyncSingleParam[SelfType, ParamType, ReturnType], + arg: ParamType, + *, + task_queue: str | None = None, + schedule_to_close_timeout: timedelta | None = None, + schedule_to_start_timeout: timedelta | None = None, + start_to_close_timeout: timedelta | None = None, + heartbeat_timeout: timedelta | None = None, + retry_policy: temporalio.common.RetryPolicy | None = None, + cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, + activity_id: str | None = None, + versioning_intent: VersioningIntent | None = None, + summary: str | None = None, + priority: temporalio.common.Priority = temporalio.common.Priority.default, +) -> ReturnType: ... + + +# Overload for sync single-param activity +@overload +async def execute_activity_method( + activity: MethodSyncSingleParam[SelfType, ParamType, ReturnType], + arg: ParamType, + *, + task_queue: str | None = None, + schedule_to_close_timeout: timedelta | None = None, + schedule_to_start_timeout: timedelta | None = None, + start_to_close_timeout: timedelta | None = None, + heartbeat_timeout: timedelta | None = None, + retry_policy: temporalio.common.RetryPolicy | None = None, + cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, + activity_id: str | None = None, + versioning_intent: VersioningIntent | None = None, + summary: str | None = None, + priority: temporalio.common.Priority = temporalio.common.Priority.default, +) -> ReturnType: ... + + +# Overload for async multi-param activity +@overload +async def execute_activity_method( + activity: Callable[Concatenate[SelfType, MultiParamSpec], Awaitable[ReturnType]], + *, + args: Sequence[Any], + task_queue: str | None = None, + schedule_to_close_timeout: timedelta | None = None, + schedule_to_start_timeout: timedelta | None = None, + start_to_close_timeout: timedelta | None = None, + heartbeat_timeout: timedelta | None = None, + retry_policy: temporalio.common.RetryPolicy | None = None, + cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, + activity_id: str | None = None, + versioning_intent: VersioningIntent | None = None, + summary: str | None = None, + priority: temporalio.common.Priority = temporalio.common.Priority.default, +) -> ReturnType: ... + + +# Overload for sync multi-param activity +@overload +async def execute_activity_method( + activity: Callable[Concatenate[SelfType, MultiParamSpec], ReturnType], + *, + args: Sequence[Any], + task_queue: str | None = None, + schedule_to_close_timeout: timedelta | None = None, + schedule_to_start_timeout: timedelta | None = None, + start_to_close_timeout: timedelta | None = None, + heartbeat_timeout: timedelta | None = None, + retry_policy: temporalio.common.RetryPolicy | None = None, + cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, + activity_id: str | None = None, + versioning_intent: VersioningIntent | None = None, + summary: str | None = None, + priority: temporalio.common.Priority = temporalio.common.Priority.default, +) -> ReturnType: ... + + +async def execute_activity_method( + activity: Callable, + arg: Any = temporalio.common._arg_unset, + *, + args: Sequence[Any] = [], + task_queue: str | None = None, + schedule_to_close_timeout: timedelta | None = None, + schedule_to_start_timeout: timedelta | None = None, + start_to_close_timeout: timedelta | None = None, + heartbeat_timeout: timedelta | None = None, + retry_policy: temporalio.common.RetryPolicy | None = None, + cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, + activity_id: str | None = None, + versioning_intent: VersioningIntent | None = None, + summary: str | None = None, + priority: temporalio.common.Priority = temporalio.common.Priority.default, +) -> Any: + """Start an activity from a method and wait for completion. + + This is a shortcut for ``await`` :py:meth:`start_activity_method`. + """ + # We call the runtime directly instead of top-level start_activity to ensure + # we don't miss new parameters + return await _Runtime.current().workflow_start_activity( + activity, + *temporalio.common._arg_or_args(arg, args), + task_queue=task_queue, + result_type=None, + schedule_to_close_timeout=schedule_to_close_timeout, + schedule_to_start_timeout=schedule_to_start_timeout, + start_to_close_timeout=start_to_close_timeout, + heartbeat_timeout=heartbeat_timeout, + retry_policy=retry_policy, + cancellation_type=cancellation_type, + activity_id=activity_id, + versioning_intent=versioning_intent, + summary=summary, + priority=priority, + ) + + +class LocalActivityConfig(TypedDict, total=False): + """TypedDict of config that can be used for :py:func:`start_local_activity` + and :py:func:`execute_local_activity`. + """ + + schedule_to_close_timeout: timedelta | None + schedule_to_start_timeout: timedelta | None + start_to_close_timeout: timedelta | None + retry_policy: temporalio.common.RetryPolicy | None + local_retry_threshold: timedelta | None + cancellation_type: ActivityCancellationType + activity_id: str | None + summary: str | None + + +# Overload for async no-param activity +@overload +def start_local_activity( + activity: CallableAsyncNoParam[ReturnType], + *, + schedule_to_close_timeout: timedelta | None = None, + schedule_to_start_timeout: timedelta | None = None, + start_to_close_timeout: timedelta | None = None, + retry_policy: temporalio.common.RetryPolicy | None = None, + local_retry_threshold: timedelta | None = None, + cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, + activity_id: str | None = None, + summary: str | None = None, +) -> ActivityHandle[ReturnType]: ... + + +# Overload for sync no-param activity +@overload +def start_local_activity( + activity: CallableSyncNoParam[ReturnType], + *, + activity_id: str | None = None, + schedule_to_close_timeout: timedelta | None = None, + schedule_to_start_timeout: timedelta | None = None, + start_to_close_timeout: timedelta | None = None, + retry_policy: temporalio.common.RetryPolicy | None = None, + local_retry_threshold: timedelta | None = None, + cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, + summary: str | None = None, +) -> ActivityHandle[ReturnType]: ... + + +# Overload for async single-param activity +@overload +def start_local_activity( + activity: CallableAsyncSingleParam[ParamType, ReturnType], + arg: ParamType, + *, + schedule_to_close_timeout: timedelta | None = None, + schedule_to_start_timeout: timedelta | None = None, + start_to_close_timeout: timedelta | None = None, + retry_policy: temporalio.common.RetryPolicy | None = None, + local_retry_threshold: timedelta | None = None, + cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, + activity_id: str | None = None, + summary: str | None = None, +) -> ActivityHandle[ReturnType]: ... + + +# Overload for sync single-param activity +@overload +def start_local_activity( + activity: CallableSyncSingleParam[ParamType, ReturnType], + arg: ParamType, + *, + schedule_to_close_timeout: timedelta | None = None, + schedule_to_start_timeout: timedelta | None = None, + start_to_close_timeout: timedelta | None = None, + retry_policy: temporalio.common.RetryPolicy | None = None, + local_retry_threshold: timedelta | None = None, + cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, + activity_id: str | None = None, + summary: str | None = None, +) -> ActivityHandle[ReturnType]: ... + + +# Overload for async multi-param activity +@overload +def start_local_activity( + activity: Callable[..., Awaitable[ReturnType]], + *, + args: Sequence[Any], + schedule_to_close_timeout: timedelta | None = None, + schedule_to_start_timeout: timedelta | None = None, + start_to_close_timeout: timedelta | None = None, + retry_policy: temporalio.common.RetryPolicy | None = None, + local_retry_threshold: timedelta | None = None, + cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, + activity_id: str | None = None, + summary: str | None = None, +) -> ActivityHandle[ReturnType]: ... + + +# Overload for sync multi-param activity +@overload +def start_local_activity( + activity: Callable[..., ReturnType], + *, + args: Sequence[Any], + schedule_to_close_timeout: timedelta | None = None, + schedule_to_start_timeout: timedelta | None = None, + start_to_close_timeout: timedelta | None = None, + retry_policy: temporalio.common.RetryPolicy | None = None, + local_retry_threshold: timedelta | None = None, + cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, + activity_id: str | None = None, + summary: str | None = None, +) -> ActivityHandle[ReturnType]: ... + + +# Overload for string-name activity +@overload +def start_local_activity( + activity: str, + arg: Any = temporalio.common._arg_unset, + *, + args: Sequence[Any] = [], + result_type: type | None = None, + schedule_to_close_timeout: timedelta | None = None, + schedule_to_start_timeout: timedelta | None = None, + start_to_close_timeout: timedelta | None = None, + retry_policy: temporalio.common.RetryPolicy | None = None, + local_retry_threshold: timedelta | None = None, + cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, + activity_id: str | None = None, + summary: str | None = None, +) -> ActivityHandle[Any]: ... + + +def start_local_activity( + activity: Any, + arg: Any = temporalio.common._arg_unset, + *, + args: Sequence[Any] = [], + result_type: type | None = None, + schedule_to_close_timeout: timedelta | None = None, + schedule_to_start_timeout: timedelta | None = None, + start_to_close_timeout: timedelta | None = None, + retry_policy: temporalio.common.RetryPolicy | None = None, + local_retry_threshold: timedelta | None = None, + cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, + activity_id: str | None = None, + summary: str | None = None, +) -> ActivityHandle[Any]: + """Start a local activity and return its handle. + + At least one of ``schedule_to_close_timeout`` or ``start_to_close_timeout`` + must be present. + + Args: + activity: Activity name or function reference. + arg: Single argument to the activity. + args: Multiple arguments to the activity. Cannot be set if arg is. + result_type: For string activities, this can set the specific result + type hint to deserialize into. + schedule_to_close_timeout: Max amount of time the activity can take from + first being scheduled to being completed before it times out. This + is inclusive of all retries. + schedule_to_start_timeout: Max amount of time the activity can take to + be started from first being scheduled. + start_to_close_timeout: Max amount of time a single activity run can + take from when it starts to when it completes. This is per retry. + retry_policy: How an activity is retried on failure. If unset, an + SDK-defined default is used. Set maximum attempts to 1 to disable + retries. + cancellation_type: How the activity is treated when it is cancelled from + the workflow. + activity_id: Optional unique identifier for the activity. This is an + advanced setting that should not be set unless users are sure they + need to. Contact Temporal before setting this value. + summary: Optional summary for the activity. + + Returns: + An activity handle to the activity which is an async task. + """ + return _Runtime.current().workflow_start_local_activity( + activity, + *temporalio.common._arg_or_args(arg, args), + result_type=result_type, + schedule_to_close_timeout=schedule_to_close_timeout, + schedule_to_start_timeout=schedule_to_start_timeout, + start_to_close_timeout=start_to_close_timeout, + retry_policy=retry_policy, + local_retry_threshold=local_retry_threshold, + cancellation_type=cancellation_type, + activity_id=activity_id, + summary=summary, + ) + + +# Overload for async no-param activity +@overload +async def execute_local_activity( + activity: CallableAsyncNoParam[ReturnType], + *, + schedule_to_close_timeout: timedelta | None = None, + schedule_to_start_timeout: timedelta | None = None, + start_to_close_timeout: timedelta | None = None, + retry_policy: temporalio.common.RetryPolicy | None = None, + local_retry_threshold: timedelta | None = None, + cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, + activity_id: str | None = None, + summary: str | None = None, +) -> ReturnType: ... + + +# Overload for sync no-param activity +@overload +async def execute_local_activity( + activity: CallableSyncNoParam[ReturnType], + *, + schedule_to_close_timeout: timedelta | None = None, + schedule_to_start_timeout: timedelta | None = None, + start_to_close_timeout: timedelta | None = None, + retry_policy: temporalio.common.RetryPolicy | None = None, + local_retry_threshold: timedelta | None = None, + cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, + activity_id: str | None = None, + summary: str | None = None, +) -> ReturnType: ... + + +# Overload for async single-param activity +@overload +async def execute_local_activity( + activity: CallableAsyncSingleParam[ParamType, ReturnType], + arg: ParamType, + *, + schedule_to_close_timeout: timedelta | None = None, + schedule_to_start_timeout: timedelta | None = None, + start_to_close_timeout: timedelta | None = None, + retry_policy: temporalio.common.RetryPolicy | None = None, + local_retry_threshold: timedelta | None = None, + cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, + activity_id: str | None = None, + summary: str | None = None, +) -> ReturnType: ... + + +# Overload for sync single-param activity +@overload +async def execute_local_activity( + activity: CallableSyncSingleParam[ParamType, ReturnType], + arg: ParamType, + *, + schedule_to_close_timeout: timedelta | None = None, + schedule_to_start_timeout: timedelta | None = None, + start_to_close_timeout: timedelta | None = None, + retry_policy: temporalio.common.RetryPolicy | None = None, + local_retry_threshold: timedelta | None = None, + cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, + activity_id: str | None = None, + summary: str | None = None, +) -> ReturnType: ... + + +# Overload for async multi-param activity +@overload +async def execute_local_activity( + activity: Callable[..., Awaitable[ReturnType]], + *, + args: Sequence[Any], + schedule_to_close_timeout: timedelta | None = None, + schedule_to_start_timeout: timedelta | None = None, + start_to_close_timeout: timedelta | None = None, + retry_policy: temporalio.common.RetryPolicy | None = None, + local_retry_threshold: timedelta | None = None, + cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, + activity_id: str | None = None, + summary: str | None = None, +) -> ReturnType: ... + + +# Overload for sync multi-param activity +@overload +async def execute_local_activity( + activity: Callable[..., ReturnType], + *, + args: Sequence[Any], + schedule_to_close_timeout: timedelta | None = None, + schedule_to_start_timeout: timedelta | None = None, + start_to_close_timeout: timedelta | None = None, + retry_policy: temporalio.common.RetryPolicy | None = None, + local_retry_threshold: timedelta | None = None, + cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, + activity_id: str | None = None, + summary: str | None = None, +) -> ReturnType: ... + + +# Overload for string-name activity +@overload +async def execute_local_activity( + activity: str, + arg: Any = temporalio.common._arg_unset, + *, + args: Sequence[Any] = [], + result_type: type | None = None, + schedule_to_close_timeout: timedelta | None = None, + schedule_to_start_timeout: timedelta | None = None, + start_to_close_timeout: timedelta | None = None, + retry_policy: temporalio.common.RetryPolicy | None = None, + local_retry_threshold: timedelta | None = None, + cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, + activity_id: str | None = None, + summary: str | None = None, +) -> Any: ... + + +async def execute_local_activity( + activity: Any, + arg: Any = temporalio.common._arg_unset, + *, + args: Sequence[Any] = [], + result_type: type | None = None, + schedule_to_close_timeout: timedelta | None = None, + schedule_to_start_timeout: timedelta | None = None, + start_to_close_timeout: timedelta | None = None, + retry_policy: temporalio.common.RetryPolicy | None = None, + local_retry_threshold: timedelta | None = None, + cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, + activity_id: str | None = None, + summary: str | None = None, +) -> Any: + """Start a local activity and wait for completion. + + This is a shortcut for ``await`` :py:meth:`start_local_activity`. + """ + # We call the runtime directly instead of top-level start_local_activity to + # ensure we don't miss new parameters + return await _Runtime.current().workflow_start_local_activity( + activity, + *temporalio.common._arg_or_args(arg, args), + result_type=result_type, + schedule_to_close_timeout=schedule_to_close_timeout, + schedule_to_start_timeout=schedule_to_start_timeout, + start_to_close_timeout=start_to_close_timeout, + retry_policy=retry_policy, + local_retry_threshold=local_retry_threshold, + cancellation_type=cancellation_type, + activity_id=activity_id, + summary=summary, + ) + + +# Overload for async no-param activity +@overload +def start_local_activity_class( + activity: type[CallableAsyncNoParam[ReturnType]], + *, + schedule_to_close_timeout: timedelta | None = None, + schedule_to_start_timeout: timedelta | None = None, + start_to_close_timeout: timedelta | None = None, + retry_policy: temporalio.common.RetryPolicy | None = None, + local_retry_threshold: timedelta | None = None, + cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, + activity_id: str | None = None, +) -> ActivityHandle[ReturnType]: ... + + +# Overload for sync no-param activity +@overload +def start_local_activity_class( + activity: type[CallableSyncNoParam[ReturnType]], + *, + schedule_to_close_timeout: timedelta | None = None, + schedule_to_start_timeout: timedelta | None = None, + start_to_close_timeout: timedelta | None = None, + retry_policy: temporalio.common.RetryPolicy | None = None, + local_retry_threshold: timedelta | None = None, + cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, + activity_id: str | None = None, +) -> ActivityHandle[ReturnType]: ... + + +# Overload for async single-param activity +@overload +def start_local_activity_class( + activity: type[CallableAsyncSingleParam[ParamType, ReturnType]], + arg: ParamType, + *, + schedule_to_close_timeout: timedelta | None = None, + schedule_to_start_timeout: timedelta | None = None, + start_to_close_timeout: timedelta | None = None, + retry_policy: temporalio.common.RetryPolicy | None = None, + local_retry_threshold: timedelta | None = None, + cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, + activity_id: str | None = None, +) -> ActivityHandle[ReturnType]: ... + + +# Overload for sync single-param activity +@overload +def start_local_activity_class( + activity: type[CallableSyncSingleParam[ParamType, ReturnType]], + arg: ParamType, + *, + schedule_to_close_timeout: timedelta | None = None, + schedule_to_start_timeout: timedelta | None = None, + start_to_close_timeout: timedelta | None = None, + retry_policy: temporalio.common.RetryPolicy | None = None, + local_retry_threshold: timedelta | None = None, + cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, + activity_id: str | None = None, +) -> ActivityHandle[ReturnType]: ... + + +# Overload for async multi-param activity +@overload +def start_local_activity_class( + activity: type[Callable[..., Awaitable[ReturnType]]], # type: ignore[reportInvalidTypeForm] + *, + args: Sequence[Any], + schedule_to_close_timeout: timedelta | None = None, + schedule_to_start_timeout: timedelta | None = None, + start_to_close_timeout: timedelta | None = None, + retry_policy: temporalio.common.RetryPolicy | None = None, + local_retry_threshold: timedelta | None = None, + cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, + activity_id: str | None = None, +) -> ActivityHandle[ReturnType]: ... + + +# Overload for sync multi-param activity +@overload +def start_local_activity_class( # type: ignore[reportOverlappingOverload] + activity: type[Callable[..., ReturnType]], # type: ignore[reportInvalidTypeForm] + *, + args: Sequence[Any], + schedule_to_close_timeout: timedelta | None = None, + schedule_to_start_timeout: timedelta | None = None, + start_to_close_timeout: timedelta | None = None, + retry_policy: temporalio.common.RetryPolicy | None = None, + local_retry_threshold: timedelta | None = None, + cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, + activity_id: str | None = None, +) -> ActivityHandle[ReturnType]: ... + + +def start_local_activity_class( + activity: type[Callable], # type: ignore[reportInvalidTypeForm] + arg: Any = temporalio.common._arg_unset, + *, + args: Sequence[Any] = [], + schedule_to_close_timeout: timedelta | None = None, + schedule_to_start_timeout: timedelta | None = None, + start_to_close_timeout: timedelta | None = None, + retry_policy: temporalio.common.RetryPolicy | None = None, + local_retry_threshold: timedelta | None = None, + cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, + activity_id: str | None = None, + summary: str | None = None, +) -> ActivityHandle[Any]: + """Start a local activity from a callable class. + + See :py:meth:`start_local_activity` for parameter and return details. + """ + return _Runtime.current().workflow_start_local_activity( + activity, + *temporalio.common._arg_or_args(arg, args), + result_type=None, + schedule_to_close_timeout=schedule_to_close_timeout, + schedule_to_start_timeout=schedule_to_start_timeout, + start_to_close_timeout=start_to_close_timeout, + retry_policy=retry_policy, + local_retry_threshold=local_retry_threshold, + cancellation_type=cancellation_type, + activity_id=activity_id, + summary=summary, + ) + + +# Overload for async no-param activity +@overload +async def execute_local_activity_class( + activity: type[CallableAsyncNoParam[ReturnType]], + *, + schedule_to_close_timeout: timedelta | None = None, + schedule_to_start_timeout: timedelta | None = None, + start_to_close_timeout: timedelta | None = None, + retry_policy: temporalio.common.RetryPolicy | None = None, + local_retry_threshold: timedelta | None = None, + cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, + activity_id: str | None = None, + summary: str | None = None, +) -> ReturnType: ... + + +# Overload for sync no-param activity +@overload +async def execute_local_activity_class( + activity: type[CallableSyncNoParam[ReturnType]], + *, + schedule_to_close_timeout: timedelta | None = None, + schedule_to_start_timeout: timedelta | None = None, + start_to_close_timeout: timedelta | None = None, + retry_policy: temporalio.common.RetryPolicy | None = None, + local_retry_threshold: timedelta | None = None, + cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, + activity_id: str | None = None, + summary: str | None = None, +) -> ReturnType: ... + + +# Overload for async single-param activity +@overload +async def execute_local_activity_class( + activity: type[CallableAsyncSingleParam[ParamType, ReturnType]], + arg: ParamType, + *, + schedule_to_close_timeout: timedelta | None = None, + schedule_to_start_timeout: timedelta | None = None, + start_to_close_timeout: timedelta | None = None, + retry_policy: temporalio.common.RetryPolicy | None = None, + local_retry_threshold: timedelta | None = None, + cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, + activity_id: str | None = None, + summary: str | None = None, +) -> ReturnType: ... + + +# Overload for sync single-param activity +@overload +async def execute_local_activity_class( + activity: type[CallableSyncSingleParam[ParamType, ReturnType]], + arg: ParamType, + *, + schedule_to_close_timeout: timedelta | None = None, + schedule_to_start_timeout: timedelta | None = None, + start_to_close_timeout: timedelta | None = None, + retry_policy: temporalio.common.RetryPolicy | None = None, + local_retry_threshold: timedelta | None = None, + cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, + activity_id: str | None = None, + summary: str | None = None, +) -> ReturnType: ... + + +# Overload for async multi-param activity +@overload +async def execute_local_activity_class( # type: ignore[reportOverlappingOverload] + activity: type[Callable[..., Awaitable[ReturnType]]], # type: ignore[reportInvalidTypeForm] + *, + args: Sequence[Any], + schedule_to_close_timeout: timedelta | None = None, + schedule_to_start_timeout: timedelta | None = None, + start_to_close_timeout: timedelta | None = None, + retry_policy: temporalio.common.RetryPolicy | None = None, + local_retry_threshold: timedelta | None = None, + cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, + activity_id: str | None = None, + summary: str | None = None, +) -> ReturnType: ... + + +# Overload for sync multi-param activity +@overload +async def execute_local_activity_class( + activity: type[Callable[..., ReturnType]], # type: ignore[reportInvalidTypeForm] + *, + args: Sequence[Any], + schedule_to_close_timeout: timedelta | None = None, + schedule_to_start_timeout: timedelta | None = None, + start_to_close_timeout: timedelta | None = None, + retry_policy: temporalio.common.RetryPolicy | None = None, + local_retry_threshold: timedelta | None = None, + cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, + activity_id: str | None = None, + summary: str | None = None, +) -> ReturnType: ... + + +async def execute_local_activity_class( + activity: type[Callable], # type: ignore[reportInvalidTypeForm] + arg: Any = temporalio.common._arg_unset, + *, + args: Sequence[Any] = [], + schedule_to_close_timeout: timedelta | None = None, + schedule_to_start_timeout: timedelta | None = None, + start_to_close_timeout: timedelta | None = None, + retry_policy: temporalio.common.RetryPolicy | None = None, + local_retry_threshold: timedelta | None = None, + cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, + activity_id: str | None = None, + summary: str | None = None, +) -> Any: + """Start a local activity from a callable class and wait for completion. + + This is a shortcut for ``await`` :py:meth:`start_local_activity_class`. + """ + # We call the runtime directly instead of top-level start_local_activity to + # ensure we don't miss new parameters + return await _Runtime.current().workflow_start_local_activity( + activity, + *temporalio.common._arg_or_args(arg, args), + result_type=None, + schedule_to_close_timeout=schedule_to_close_timeout, + schedule_to_start_timeout=schedule_to_start_timeout, + start_to_close_timeout=start_to_close_timeout, + retry_policy=retry_policy, + local_retry_threshold=local_retry_threshold, + cancellation_type=cancellation_type, + activity_id=activity_id, + summary=summary, + ) + + +# Overload for async no-param activity +@overload +def start_local_activity_method( + activity: MethodAsyncNoParam[SelfType, ReturnType], + *, + schedule_to_close_timeout: timedelta | None = None, + schedule_to_start_timeout: timedelta | None = None, + start_to_close_timeout: timedelta | None = None, + retry_policy: temporalio.common.RetryPolicy | None = None, + local_retry_threshold: timedelta | None = None, + cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, + activity_id: str | None = None, + summary: str | None = None, +) -> ActivityHandle[ReturnType]: ... + + +# Overload for sync no-param activity +@overload +def start_local_activity_method( + activity: MethodSyncNoParam[SelfType, ReturnType], + *, + schedule_to_close_timeout: timedelta | None = None, + schedule_to_start_timeout: timedelta | None = None, + start_to_close_timeout: timedelta | None = None, + retry_policy: temporalio.common.RetryPolicy | None = None, + local_retry_threshold: timedelta | None = None, + cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, + activity_id: str | None = None, + summary: str | None = None, +) -> ActivityHandle[ReturnType]: ... + + +# Overload for async single-param activity +@overload +def start_local_activity_method( + activity: MethodAsyncSingleParam[SelfType, ParamType, ReturnType], + arg: ParamType, + *, + schedule_to_close_timeout: timedelta | None = None, + schedule_to_start_timeout: timedelta | None = None, + start_to_close_timeout: timedelta | None = None, + retry_policy: temporalio.common.RetryPolicy | None = None, + local_retry_threshold: timedelta | None = None, + cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, + activity_id: str | None = None, + summary: str | None = None, +) -> ActivityHandle[ReturnType]: ... + + +# Overload for sync single-param activity +@overload +def start_local_activity_method( + activity: MethodSyncSingleParam[SelfType, ParamType, ReturnType], + arg: ParamType, + *, + schedule_to_close_timeout: timedelta | None = None, + schedule_to_start_timeout: timedelta | None = None, + start_to_close_timeout: timedelta | None = None, + retry_policy: temporalio.common.RetryPolicy | None = None, + local_retry_threshold: timedelta | None = None, + cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, + activity_id: str | None = None, + summary: str | None = None, +) -> ActivityHandle[ReturnType]: ... + + +# Overload for async multi-param activity +@overload +def start_local_activity_method( + activity: Callable[Concatenate[SelfType, MultiParamSpec], Awaitable[ReturnType]], + *, + args: Sequence[Any], + schedule_to_close_timeout: timedelta | None = None, + schedule_to_start_timeout: timedelta | None = None, + start_to_close_timeout: timedelta | None = None, + retry_policy: temporalio.common.RetryPolicy | None = None, + local_retry_threshold: timedelta | None = None, + cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, + activity_id: str | None = None, + summary: str | None = None, +) -> ActivityHandle[ReturnType]: ... + + +# Overload for sync multi-param activity +@overload +def start_local_activity_method( + activity: Callable[Concatenate[SelfType, MultiParamSpec], ReturnType], + *, + args: Sequence[Any], + schedule_to_close_timeout: timedelta | None = None, + schedule_to_start_timeout: timedelta | None = None, + start_to_close_timeout: timedelta | None = None, + retry_policy: temporalio.common.RetryPolicy | None = None, + local_retry_threshold: timedelta | None = None, + cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, + activity_id: str | None = None, + summary: str | None = None, +) -> ActivityHandle[ReturnType]: ... + + +def start_local_activity_method( + activity: Callable, + arg: Any = temporalio.common._arg_unset, + *, + args: Sequence[Any] = [], + schedule_to_close_timeout: timedelta | None = None, + schedule_to_start_timeout: timedelta | None = None, + start_to_close_timeout: timedelta | None = None, + retry_policy: temporalio.common.RetryPolicy | None = None, + local_retry_threshold: timedelta | None = None, + cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, + activity_id: str | None = None, + summary: str | None = None, +) -> ActivityHandle[Any]: + """Start a local activity from a method. + + See :py:meth:`start_local_activity` for parameter and return details. + """ + return _Runtime.current().workflow_start_local_activity( + activity, + *temporalio.common._arg_or_args(arg, args), + result_type=None, + schedule_to_close_timeout=schedule_to_close_timeout, + schedule_to_start_timeout=schedule_to_start_timeout, + start_to_close_timeout=start_to_close_timeout, + retry_policy=retry_policy, + local_retry_threshold=local_retry_threshold, + cancellation_type=cancellation_type, + activity_id=activity_id, + summary=summary, + ) + + +# Overload for async no-param activity +@overload +async def execute_local_activity_method( + activity: MethodAsyncNoParam[SelfType, ReturnType], + *, + schedule_to_close_timeout: timedelta | None = None, + schedule_to_start_timeout: timedelta | None = None, + start_to_close_timeout: timedelta | None = None, + retry_policy: temporalio.common.RetryPolicy | None = None, + local_retry_threshold: timedelta | None = None, + cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, + activity_id: str | None = None, + summary: str | None = None, +) -> ReturnType: ... + + +# Overload for sync no-param activity +@overload +async def execute_local_activity_method( + activity: MethodSyncNoParam[SelfType, ReturnType], + *, + schedule_to_close_timeout: timedelta | None = None, + schedule_to_start_timeout: timedelta | None = None, + start_to_close_timeout: timedelta | None = None, + retry_policy: temporalio.common.RetryPolicy | None = None, + local_retry_threshold: timedelta | None = None, + cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, + activity_id: str | None = None, + summary: str | None = None, +) -> ReturnType: ... + + +# Overload for async single-param activity +@overload +async def execute_local_activity_method( + activity: MethodAsyncSingleParam[SelfType, ParamType, ReturnType], + arg: ParamType, + *, + schedule_to_close_timeout: timedelta | None = None, + schedule_to_start_timeout: timedelta | None = None, + start_to_close_timeout: timedelta | None = None, + retry_policy: temporalio.common.RetryPolicy | None = None, + local_retry_threshold: timedelta | None = None, + cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, + activity_id: str | None = None, + summary: str | None = None, +) -> ReturnType: ... + + +# Overload for sync single-param activity +@overload +async def execute_local_activity_method( + activity: MethodSyncSingleParam[SelfType, ParamType, ReturnType], + arg: ParamType, + *, + schedule_to_close_timeout: timedelta | None = None, + schedule_to_start_timeout: timedelta | None = None, + start_to_close_timeout: timedelta | None = None, + retry_policy: temporalio.common.RetryPolicy | None = None, + local_retry_threshold: timedelta | None = None, + cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, + activity_id: str | None = None, + summary: str | None = None, +) -> ReturnType: ... + + +# Overload for async multi-param activity +@overload +async def execute_local_activity_method( + activity: Callable[Concatenate[SelfType, MultiParamSpec], Awaitable[ReturnType]], + *, + args: Sequence[Any], + schedule_to_close_timeout: timedelta | None = None, + schedule_to_start_timeout: timedelta | None = None, + start_to_close_timeout: timedelta | None = None, + retry_policy: temporalio.common.RetryPolicy | None = None, + local_retry_threshold: timedelta | None = None, + cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, + activity_id: str | None = None, + summary: str | None = None, +) -> ReturnType: ... + + +# Overload for sync multi-param activity +@overload +async def execute_local_activity_method( + activity: Callable[Concatenate[SelfType, MultiParamSpec], ReturnType], + *, + args: Sequence[Any], + schedule_to_close_timeout: timedelta | None = None, + schedule_to_start_timeout: timedelta | None = None, + start_to_close_timeout: timedelta | None = None, + retry_policy: temporalio.common.RetryPolicy | None = None, + local_retry_threshold: timedelta | None = None, + cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, + activity_id: str | None = None, + summary: str | None = None, +) -> ReturnType: ... + + +async def execute_local_activity_method( + activity: Callable, + arg: Any = temporalio.common._arg_unset, + *, + args: Sequence[Any] = [], + schedule_to_close_timeout: timedelta | None = None, + schedule_to_start_timeout: timedelta | None = None, + start_to_close_timeout: timedelta | None = None, + retry_policy: temporalio.common.RetryPolicy | None = None, + local_retry_threshold: timedelta | None = None, + cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, + activity_id: str | None = None, + summary: str | None = None, +) -> Any: + """Start a local activity from a method and wait for completion. + + This is a shortcut for ``await`` :py:meth:`start_local_activity_method`. + """ + # We call the runtime directly instead of top-level start_local_activity to + # ensure we don't miss new parameters + return await _Runtime.current().workflow_start_local_activity( + activity, + *temporalio.common._arg_or_args(arg, args), + result_type=None, + schedule_to_close_timeout=schedule_to_close_timeout, + schedule_to_start_timeout=schedule_to_start_timeout, + start_to_close_timeout=start_to_close_timeout, + retry_policy=retry_policy, + local_retry_threshold=local_retry_threshold, + cancellation_type=cancellation_type, + activity_id=activity_id, + summary=summary, + ) diff --git a/temporalio/workflow/_asyncio.py b/temporalio/workflow/_asyncio.py new file mode 100644 index 000000000..5ca7e66d8 --- /dev/null +++ b/temporalio/workflow/_asyncio.py @@ -0,0 +1,180 @@ +from __future__ import annotations + +import asyncio +from collections.abc import Awaitable, Iterable, Iterator +from typing import TYPE_CHECKING, Any, TypeVar, overload + +from ..types import AnyType + +__all__ = [ + "as_completed", + "wait", +] + + +def as_completed( + fs: Iterable[Awaitable[AnyType]], *, timeout: float | None = None +) -> Iterator[Awaitable[AnyType]]: + """Return an iterator whose values are coroutines. + + This is a deterministic version of :py:func:`asyncio.as_completed`. This + function should be used instead of that one in workflows. + """ + # Taken almost verbatim from + # https://github.com/python/cpython/blob/v3.12.3/Lib/asyncio/tasks.py#L584 + # but the "set" is changed out for a "list" and fixed up some typing/format + + if asyncio.isfuture(fs) or asyncio.iscoroutine(fs): + raise TypeError(f"expect an iterable of futures, not {type(fs).__name__}") + + done: asyncio.Queue[asyncio.Future | None] = asyncio.Queue() + + loop = asyncio.get_event_loop() + todo: list[asyncio.Future] = [asyncio.ensure_future(f, loop=loop) for f in list(fs)] + timeout_handle = None + + def _on_timeout(): + for f in todo: + f.remove_done_callback(_on_completion) + done.put_nowait(None) # Queue a dummy value for _wait_for_one(). + todo.clear() # Can't do todo.remove(f) in the loop. + + def _on_completion(f): # type:ignore[reportMissingParameterType] + if not todo: + return # _on_timeout() was here first. + todo.remove(f) + done.put_nowait(f) + if not todo and timeout_handle is not None: + timeout_handle.cancel() + + async def _wait_for_one(): + f = await done.get() + if f is None: + # Dummy value from _on_timeout(). + raise asyncio.TimeoutError + return f.result() # May raise f.exception(). + + for f in todo: + f.add_done_callback(_on_completion) + if todo and timeout is not None: + timeout_handle = loop.call_later(timeout, _on_timeout) + for _ in range(len(todo)): + yield _wait_for_one() + + +if TYPE_CHECKING: + _FT = TypeVar("_FT", bound=asyncio.Future[Any]) +else: + _FT = TypeVar("_FT", bound=asyncio.Future) + + +@overload +async def wait( # type: ignore[misc] + fs: Iterable[_FT], + *, + timeout: float | None = None, + return_when: str = asyncio.ALL_COMPLETED, +) -> tuple[list[_FT], list[_FT]]: ... + + +@overload +async def wait( + fs: Iterable[asyncio.Task[AnyType]], + *, + timeout: float | None = None, + return_when: str = asyncio.ALL_COMPLETED, +) -> tuple[list[asyncio.Task[AnyType]], list[asyncio.Task[AnyType]]]: ... + + +async def wait( + fs: Iterable, + *, + timeout: float | None = None, + return_when: str = asyncio.ALL_COMPLETED, +) -> tuple: + """Wait for the Futures or Tasks given by fs to complete. + + This is a deterministic version of :py:func:`asyncio.wait`. This function + should be used instead of that one in workflows. + """ + # Taken almost verbatim from + # https://github.com/python/cpython/blob/v3.12.3/Lib/asyncio/tasks.py#L435 + # but the "set" is changed out for a "list" and fixed up some typing/format + + if asyncio.isfuture(fs) or asyncio.iscoroutine(fs): + raise TypeError(f"Expect an iterable of Tasks/Futures, not {type(fs).__name__}") + if not fs: + raise ValueError("Sequence of Tasks/Futures must not be empty.") + if return_when not in ( + asyncio.FIRST_COMPLETED, + asyncio.FIRST_EXCEPTION, + asyncio.ALL_COMPLETED, + ): + raise ValueError(f"Invalid return_when value: {return_when}") + + fs = list(fs) + + if any(asyncio.iscoroutine(f) for f in fs): + raise TypeError("Passing coroutines is forbidden, use tasks explicitly.") + + loop = asyncio.get_running_loop() + return await _wait(fs, timeout, return_when, loop) + + +async def _wait( + fs: Iterable[asyncio.Future | asyncio.Task], + timeout: float | None, + return_when: str, + loop: asyncio.AbstractEventLoop, +) -> tuple[list, list]: + # Taken almost verbatim from + # https://github.com/python/cpython/blob/v3.12.3/Lib/asyncio/tasks.py#L522 + # but the "set" is changed out for a "list" and fixed up some typing/format + + assert fs, "Sequence of Tasks/Futures must not be empty." + waiter = loop.create_future() + timeout_handle = None + if timeout is not None: + timeout_handle = loop.call_later(timeout, _release_waiter, waiter) + counter = len(fs) # type: ignore[arg-type] + + def _on_completion(f): # type:ignore[reportMissingParameterType] + nonlocal counter + counter -= 1 + if ( + counter <= 0 + or return_when == asyncio.FIRST_COMPLETED + or return_when == asyncio.FIRST_EXCEPTION + and (not f.cancelled() and f.exception() is not None) + ): + if timeout_handle is not None: + timeout_handle.cancel() + if not waiter.done(): + waiter.set_result(None) + + for f in fs: + f.add_done_callback(_on_completion) + + try: + await waiter + finally: + if timeout_handle is not None: + timeout_handle.cancel() + for f in fs: + f.remove_done_callback(_on_completion) + + done, pending = [], [] + for f in fs: + if f.done(): + done.append(f) + else: + pending.append(f) + return done, pending + + +def _release_waiter(waiter: asyncio.Future[Any], *_args: Any) -> None: + # Taken almost verbatim from + # https://github.com/python/cpython/blob/v3.12.3/Lib/asyncio/tasks.py#L467 + + if not waiter.done(): + waiter.set_result(None) diff --git a/temporalio/workflow/_context.py b/temporalio/workflow/_context.py new file mode 100644 index 000000000..5c3f22cc9 --- /dev/null +++ b/temporalio/workflow/_context.py @@ -0,0 +1,917 @@ +from __future__ import annotations + +import asyncio +import contextvars +import uuid +from abc import ABC, abstractmethod +from collections.abc import Callable, Mapping, Sequence +from dataclasses import dataclass +from datetime import datetime, timedelta, timezone +from random import Random +from typing import TYPE_CHECKING, Any, NoReturn, overload + +import nexusrpc +from nexusrpc import InputT, OutputT + +import temporalio.api.common.v1 +import temporalio.common +import temporalio.converter + +from ..types import AnyType, ParamType +from ._exceptions import _NotInWorkflowEventLoopError + +if TYPE_CHECKING: + from ._activities import ActivityCancellationType, ActivityHandle + from ._exceptions import ContinueAsNewVersioningBehavior, VersioningIntent + from ._nexus import NexusOperationCancellationType, NexusOperationHandle + from ._workflow_ops import ( + ChildWorkflowCancellationType, + ChildWorkflowHandle, + ExternalWorkflowHandle, + ParentClosePolicy, + ) + +__all__ = [ + "Info", + "ParentInfo", + "RootInfo", + "UpdateInfo", + "current_update_info", + "deprecate_patch", + "extern_functions", + "get_current_details", + "get_last_completion_result", + "get_last_failure", + "has_last_completion_result", + "in_workflow", + "info", + "instance", + "is_failure_exception", + "memo", + "memo_value", + "metric_meter", + "new_random", + "now", + "patched", + "payload_converter", + "random", + "random_seed", + "register_random_seed_callback", + "set_current_details", + "sleep", + "time", + "time_ns", + "upsert_memo", + "upsert_search_attributes", + "uuid4", + "wait_condition", +] + + +@dataclass(frozen=True) +class Info: + """Information about the running workflow. + + Retrieved inside a workflow via :py:func:`info`. This object is immutable + with the exception of the :py:attr:`search_attributes` and + :py:attr:`typed_search_attributes` which is updated on + :py:func:`upsert_search_attributes`. + + Note, required fields may be added here in future versions. This class + should never be constructed by users. + """ + + attempt: int + continued_run_id: str | None + cron_schedule: str | None + execution_timeout: timedelta | None + first_execution_run_id: str + headers: Mapping[str, temporalio.api.common.v1.Payload] + namespace: str + parent: ParentInfo | None + root: RootInfo | None + priority: temporalio.common.Priority + """The priority of this workflow execution. If not set, or this server predates priorities, + then returns a default instance.""" + raw_memo: Mapping[str, temporalio.api.common.v1.Payload] + retry_policy: temporalio.common.RetryPolicy | None + run_id: str + run_timeout: timedelta | None + + search_attributes: temporalio.common.SearchAttributes + """Search attributes for the workflow. + + .. deprecated:: + Use :py:attr:`typed_search_attributes` instead. + """ + + start_time: datetime + """The start time of the first task executed by the workflow.""" + + task_queue: str + task_timeout: timedelta + + typed_search_attributes: temporalio.common.TypedSearchAttributes + """Search attributes for the workflow. + + Note, this may have invalid values or be missing values if passing the + deprecated form of dictionary attributes to + :py:meth:`upsert_search_attributes`. + """ + + workflow_id: str + + workflow_start_time: datetime + """The start time of the workflow based on the workflow initialization.""" + + workflow_type: str + + def _logger_details(self) -> Mapping[str, Any]: + return { + # TODO(cretz): worker ID? + "attempt": self.attempt, + "namespace": self.namespace, + "run_id": self.run_id, + "task_queue": self.task_queue, + "workflow_id": self.workflow_id, + "workflow_type": self.workflow_type, + } + + def get_current_build_id(self) -> str: + """Get the Build ID of the worker which executed the current Workflow Task. + + May be undefined if the task was completed by a worker without a Build ID. If this worker is + the one executing this task for the first time and has a Build ID set, then its ID will be + used. This value may change over the lifetime of the workflow run, but is deterministic and + safe to use for branching. + + .. deprecated:: + Use get_current_deployment_version instead. + """ + return _Runtime.current().workflow_get_current_build_id() + + def get_current_deployment_version( + self, + ) -> temporalio.common.WorkerDeploymentVersion | None: + """Get the deployment version of the worker which executed the current Workflow Task. + + May be None if the task was completed by a worker without a deployment version or build + id. If this worker is the one executing this task for the first time and has a deployment + version set, then its ID will be used. This value may change over the lifetime of the + workflow run, but is deterministic and safe to use for branching. + """ + return _Runtime.current().workflow_get_current_deployment_version() + + def get_current_history_length(self) -> int: + """Get the current number of events in history. + + Note, this value may not be up to date if accessed inside a query. + + Returns: + Current number of events in history (up until the current task). + """ + return _Runtime.current().workflow_get_current_history_length() + + def get_current_history_size(self) -> int: + """Get the current byte size of history. + + Note, this value may not be up to date if accessed inside a query. + + Returns: + Current byte-size of history (up until the current task). + """ + return _Runtime.current().workflow_get_current_history_size() + + def is_continue_as_new_suggested(self) -> bool: + """Get whether or not continue as new is suggested. + + Note, this value may not be up to date if accessed inside a query. + + Returns: + True if the server is configured to suggest continue as new and it + is suggested. + """ + return _Runtime.current().workflow_is_continue_as_new_suggested() + + def is_target_worker_deployment_version_changed(self) -> bool: + """Check whether the target worker deployment version has changed. + + Note: Upgrade-on-Continue-as-New is currently experimental. + + Returns: + True if the target worker deployment version has changed. + """ + return _Runtime.current().workflow_is_target_worker_deployment_version_changed() + + +@dataclass(frozen=True) +class ParentInfo: + """Information about the parent workflow.""" + + namespace: str + run_id: str + workflow_id: str + + +@dataclass(frozen=True) +class RootInfo: + """Information about the root workflow.""" + + run_id: str + workflow_id: str + + +@dataclass(frozen=True) +class UpdateInfo: + """Information about a workflow update.""" + + id: str + """Update ID.""" + + name: str + """Update type name.""" + + @property + def _logger_details(self) -> Mapping[str, Any]: + """Data to be included in string appended to default logging output.""" + return { + "update_id": self.id, + "update_name": self.name, + } + + +class _Runtime(ABC): + @staticmethod + def current() -> _Runtime: + loop = _Runtime.maybe_current() + if not loop: + raise _NotInWorkflowEventLoopError("Not in workflow event loop") + return loop + + @staticmethod + def maybe_current() -> _Runtime | None: + try: + return getattr( + asyncio.get_running_loop(), "__temporal_workflow_runtime", None + ) + except RuntimeError: + return None + + @staticmethod + def set_on_loop(loop: asyncio.AbstractEventLoop, runtime: _Runtime | None) -> None: + if runtime: + setattr(loop, "__temporal_workflow_runtime", runtime) + elif hasattr(loop, "__temporal_workflow_runtime"): + delattr(loop, "__temporal_workflow_runtime") + + def __init__(self) -> None: + super().__init__() + self._logger_details: Mapping[str, Any] | None = None + + @property + def logger_details(self) -> Mapping[str, Any]: + if self._logger_details is None: + self._logger_details = self.workflow_info()._logger_details() + return self._logger_details + + @abstractmethod + def workflow_all_handlers_finished(self) -> bool: ... + + @abstractmethod + def workflow_continue_as_new( + self, + *args: Any, + workflow: None | Callable | str, + task_queue: str | None, + run_timeout: timedelta | None, + task_timeout: timedelta | None, + retry_policy: temporalio.common.RetryPolicy | None, + memo: Mapping[str, Any] | None, + search_attributes: None + | ( + temporalio.common.SearchAttributes | temporalio.common.TypedSearchAttributes + ), + versioning_intent: VersioningIntent | None, + initial_versioning_behavior: ContinueAsNewVersioningBehavior | None, + ) -> NoReturn: ... + + @abstractmethod + def workflow_extern_functions(self) -> Mapping[str, Callable]: ... + + @abstractmethod + def workflow_get_current_build_id(self) -> str: ... + + @abstractmethod + def workflow_get_current_deployment_version( + self, + ) -> temporalio.common.WorkerDeploymentVersion | None: ... + + @abstractmethod + def workflow_get_current_history_length(self) -> int: ... + + @abstractmethod + def workflow_get_current_history_size(self) -> int: ... + + @abstractmethod + def workflow_get_external_workflow_handle( + self, id: str, *, run_id: str | None + ) -> ExternalWorkflowHandle[Any]: ... + + @abstractmethod + def workflow_get_query_handler(self, name: str | None) -> Callable | None: ... + + @abstractmethod + def workflow_get_signal_handler(self, name: str | None) -> Callable | None: ... + + @abstractmethod + def workflow_get_update_handler(self, name: str | None) -> Callable | None: ... + + @abstractmethod + def workflow_get_update_validator(self, name: str | None) -> Callable | None: ... + + @abstractmethod + def workflow_info(self) -> Info: ... + + @abstractmethod + def workflow_instance(self) -> Any: ... + + @abstractmethod + def workflow_is_continue_as_new_suggested(self) -> bool: ... + + @abstractmethod + def workflow_is_target_worker_deployment_version_changed(self) -> bool: ... + + @abstractmethod + def workflow_is_replaying(self) -> bool: ... + + @abstractmethod + def workflow_is_replaying_history_events(self) -> bool: ... + + @abstractmethod + def workflow_is_read_only(self) -> bool: ... + + @abstractmethod + def workflow_memo(self) -> Mapping[str, Any]: ... + + @abstractmethod + def workflow_memo_value( + self, key: str, default: Any, *, type_hint: type | None + ) -> Any: ... + + @abstractmethod + def workflow_upsert_memo(self, updates: Mapping[str, Any]) -> None: ... + + @abstractmethod + def workflow_metric_meter(self) -> temporalio.common.MetricMeter: ... + + @abstractmethod + def workflow_patch(self, id: str, *, deprecated: bool) -> bool: ... + + @abstractmethod + def workflow_payload_converter(self) -> temporalio.converter.PayloadConverter: ... + + @abstractmethod + def workflow_random(self) -> Random: ... + + @abstractmethod + def workflow_set_query_handler( + self, name: str | None, handler: Callable | None + ) -> None: ... + + @abstractmethod + def workflow_set_signal_handler( + self, name: str | None, handler: Callable | None + ) -> None: ... + + @abstractmethod + def workflow_set_update_handler( + self, + name: str | None, + handler: Callable | None, + validator: Callable | None, + ) -> None: ... + + @abstractmethod + def workflow_start_activity( + self, + activity: Any, + *args: Any, + task_queue: str | None, + result_type: type | None, + schedule_to_close_timeout: timedelta | None, + schedule_to_start_timeout: timedelta | None, + start_to_close_timeout: timedelta | None, + heartbeat_timeout: timedelta | None, + retry_policy: temporalio.common.RetryPolicy | None, + cancellation_type: ActivityCancellationType, + activity_id: str | None, + versioning_intent: VersioningIntent | None, + summary: str | None = None, + priority: temporalio.common.Priority = temporalio.common.Priority.default, + ) -> ActivityHandle[Any]: ... + + @abstractmethod + async def workflow_start_child_workflow( + self, + workflow: Any, + *args: Any, + id: str, + task_queue: str | None, + result_type: type | None, + cancellation_type: ChildWorkflowCancellationType, + parent_close_policy: ParentClosePolicy, + execution_timeout: timedelta | None, + run_timeout: timedelta | None, + task_timeout: timedelta | None, + id_reuse_policy: temporalio.common.WorkflowIDReusePolicy, + retry_policy: temporalio.common.RetryPolicy | None, + cron_schedule: str, + memo: Mapping[str, Any] | None, + search_attributes: None + | ( + temporalio.common.SearchAttributes | temporalio.common.TypedSearchAttributes + ), + versioning_intent: VersioningIntent | None, + static_summary: str | None = None, + static_details: str | None = None, + priority: temporalio.common.Priority = temporalio.common.Priority.default, + ) -> ChildWorkflowHandle[Any, Any]: ... + + @abstractmethod + def workflow_start_local_activity( + self, + activity: Any, + *args: Any, + result_type: type | None, + schedule_to_close_timeout: timedelta | None, + schedule_to_start_timeout: timedelta | None, + start_to_close_timeout: timedelta | None, + retry_policy: temporalio.common.RetryPolicy | None, + local_retry_threshold: timedelta | None, + cancellation_type: ActivityCancellationType, + activity_id: str | None, + summary: str | None, + ) -> ActivityHandle[Any]: ... + + @abstractmethod + async def workflow_start_nexus_operation( + self, + endpoint: str, + service: str, + operation: nexusrpc.Operation[InputT, OutputT] | str | Callable[..., Any], + input: Any, + output_type: type[OutputT] | None, + schedule_to_close_timeout: timedelta | None, + schedule_to_start_timeout: timedelta | None, + start_to_close_timeout: timedelta | None, + cancellation_type: NexusOperationCancellationType, + headers: Mapping[str, str] | None, + summary: str | None, + ) -> NexusOperationHandle[OutputT]: ... + + @abstractmethod + def workflow_time_ns(self) -> int: ... + + @abstractmethod + def workflow_upsert_search_attributes( + self, + attributes: ( + temporalio.common.SearchAttributes + | Sequence[temporalio.common.SearchAttributeUpdate] + ), + ) -> None: ... + + @abstractmethod + async def workflow_sleep( + self, duration: float, *, summary: str | None = None + ) -> None: ... + + @abstractmethod + async def workflow_wait_condition( + self, + fn: Callable[[], bool], + *, + timeout: float | None = None, + timeout_summary: str | None = None, + ) -> None: ... + + @abstractmethod + def workflow_get_current_details(self) -> str: ... + + @abstractmethod + def workflow_set_current_details(self, details: str): ... + + @abstractmethod + def workflow_is_failure_exception(self, err: BaseException) -> bool: ... + + @abstractmethod + def workflow_has_last_completion_result(self) -> bool: ... + + @abstractmethod + def workflow_last_completion_result(self, type_hint: type | None) -> Any | None: ... + + @abstractmethod + def workflow_last_failure(self) -> BaseException | None: ... + + @abstractmethod + def workflow_random_seed(self) -> int: ... + + @abstractmethod + def workflow_register_random_seed_callback( + self, callback: Callable[[int], None] + ) -> None: ... + + +_current_update_info: contextvars.ContextVar[UpdateInfo] = contextvars.ContextVar( + "__temporal_current_update_info" +) + + +def _set_current_update_info(info: UpdateInfo) -> None: # type: ignore[reportUnusedFunction] + _current_update_info.set(info) + + +def current_update_info() -> UpdateInfo | None: + """Info for the current update if any. + + This is powered by :py:mod:`contextvars` so it is only valid within the + update handler and coroutines/tasks it has started. + + Returns: + Info for the current update handler the code calling this is executing + within if any. + """ + return _current_update_info.get(None) + + +def deprecate_patch(id: str) -> None: + """Mark a patch as deprecated. + + This marks a workflow that had :py:func:`patched` in a previous version of + the code as no longer applicable because all workflows that use the old code + path are done and will never be queried again. Therefore the old code path + is removed as well. + + Args: + id: The identifier originally used with :py:func:`patched`. + """ + _Runtime.current().workflow_patch(id, deprecated=True) + + +def extern_functions() -> Mapping[str, Callable]: + """External functions available in the workflow sandbox. + + Returns: + Mapping of external functions that can be called from inside a workflow + sandbox. + """ + return _Runtime.current().workflow_extern_functions() + + +def info() -> Info: + """Current workflow's info. + + Returns: + Info for the currently running workflow. + """ + return _Runtime.current().workflow_info() + + +def instance() -> Any: + """Current workflow's instance. + + Returns: + The currently running workflow instance. + """ + return _Runtime.current().workflow_instance() + + +def in_workflow() -> bool: + """Whether the code is currently running in a workflow.""" + return _Runtime.maybe_current() is not None + + +def memo() -> Mapping[str, Any]: + """Current workflow's memo values, converted without type hints. + + Since type hints are not used, the default converted values will come back. + For example, if the memo was originally created with a dataclass, the value + will be a dict. To convert using proper type hints, use + :py:func:`memo_value`. + + Returns: + Mapping of all memo keys and they values without type hints. + """ + return _Runtime.current().workflow_memo() + + +def is_failure_exception(err: BaseException) -> bool: + """Checks if the given exception is a workflow failure in the current workflow. + + Returns: + True if the given exception is a workflow failure in the current workflow. + """ + return _Runtime.current().workflow_is_failure_exception(err) + + +@overload +def memo_value(key: str, default: Any = temporalio.common._arg_unset) -> Any: ... + + +@overload +def memo_value(key: str, *, type_hint: type[ParamType]) -> ParamType: ... + + +@overload +def memo_value( + key: str, default: AnyType, *, type_hint: type[ParamType] +) -> AnyType | ParamType: ... + + +def memo_value( + key: str, + default: Any = temporalio.common._arg_unset, + *, + type_hint: type | None = None, +) -> Any: + """Memo value for the given key, optional default, and optional type + hint. + + Args: + key: Key to get memo value for. + default: Default to use if key is not present. If unset, a + :py:class:`KeyError` is raised when the key does not exist. + type_hint: Type hint to use when converting. + + Returns: + Memo value, converted with the type hint if present. + + Raises: + KeyError: Key not present and default not set. + """ + return _Runtime.current().workflow_memo_value(key, default, type_hint=type_hint) + + +def upsert_memo(updates: Mapping[str, Any]) -> None: + """Adds, modifies, and/or removes memos, with upsert semantics. + + Every memo that has a matching key has its value replaced with the one specified in ``updates``. + If the value is set to ``None``, the memo is removed instead. + For every key with no existing memo, a new memo is added with specified value (unless the value is ``None``). + Memos with keys not included in ``updates`` remain unchanged. + """ + return _Runtime.current().workflow_upsert_memo(updates) + + +def get_current_details() -> str: + """Get the current details of the workflow which may appear in the UI/CLI. + Unlike static details set at start, this value can be updated throughout + the life of the workflow and is independent of the static details. + This can be in Temporal markdown format and can span multiple lines. + """ + return _Runtime.current().workflow_get_current_details() + + +def has_last_completion_result() -> bool: + """Gets whether there is a last completion result of the workflow.""" + return _Runtime.current().workflow_has_last_completion_result() + + +@overload +def get_last_completion_result() -> Any | None: ... + + +@overload +def get_last_completion_result(type_hint: type[ParamType]) -> ParamType | None: ... + + +def get_last_completion_result(type_hint: type | None = None) -> Any | None: + """Get the result of the last run of the workflow. This will be None if there was + no previous completion or the result was None. has_last_completion_result() + can be used to differentiate. + """ + return _Runtime.current().workflow_last_completion_result(type_hint) + + +def get_last_failure() -> BaseException | None: + """Get the last failure of the workflow if it has run previously.""" + return _Runtime.current().workflow_last_failure() + + +def set_current_details(description: str) -> None: + """Set the current details of the workflow which may appear in the UI/CLI. + Unlike static details set at start, this value can be updated throughout + the life of the workflow and is independent of the static details. + This can be in Temporal markdown format and can span multiple lines. + """ + _Runtime.current().workflow_set_current_details(description) + + +def metric_meter() -> temporalio.common.MetricMeter: + """Get the metric meter for the current workflow. + + This meter is replay safe which means that metrics will not be recorded + during replay. + + Returns: + Current metric meter for this workflow for recording metrics. + """ + return _Runtime.current().workflow_metric_meter() + + +def now() -> datetime: + """Current time from the workflow perspective. + + This is the workflow equivalent of :py:func:`datetime.now` with the + :py:attr:`timezone.utc` parameter. + + Returns: + UTC datetime for the current workflow time. The datetime does have UTC + set as the time zone. + """ + return datetime.fromtimestamp(time(), timezone.utc) + + +def patched(id: str) -> bool: + """Patch a workflow. + + When called, this will only return true if code should take the newer path + which means this is either not replaying or is replaying and has seen this + patch before. + + Use :py:func:`deprecate_patch` when all workflows are done and will never be + queried again. The old code path can be used at that time too. + + Args: + id: The identifier for this patch. This identifier may be used + repeatedly in the same workflow to represent the same patch + + Returns: + True if this should take the newer path, false if it should take the + older path. + """ + return _Runtime.current().workflow_patch(id, deprecated=False) + + +def payload_converter() -> temporalio.converter.PayloadConverter: + """Get the payload converter for the current workflow. + + The returned converter has :py:class:`temporalio.converter.WorkflowSerializationContext` set. + This is often used for dynamic workflows/signals/queries to convert + payloads. + """ + return _Runtime.current().workflow_payload_converter() + + +def random() -> Random: + """Get a deterministic pseudo-random number generator. + + Note, this random number generator is not cryptographically safe and should + not be used for security purposes. + + Returns: + The deterministically-seeded pseudo-random number generator. + """ + return _Runtime.current().workflow_random() + + +def random_seed() -> int: + """Get the current random seed value from core. + + This returns the seed value currently being used by the workflow's + deterministic random number generator. + + Returns: + The current random seed as an integer. + """ + return _Runtime.current().workflow_random_seed() + + +def register_random_seed_callback(callback: Callable[[int], None]) -> None: + """Register a callback to be notified when the random seed changes. + + The callback will be invoked whenever the workflow receives a new random + seed from the core. This is useful for maintaining external random number + generators that need to stay in sync with the workflow's randomness. + + Args: + callback: Function to be called with the new seed value when it changes. + """ + return _Runtime.current().workflow_register_random_seed_callback(callback) + + +def new_random() -> Random: + """Create a Random instance that automatically reseeds when the workflow seed changes. + + This creates a new Random instance that is initially seeded with the current + workflow seed, and automatically registers a callback to reseed itself + whenever the workflow receives a new seed from core. + + Returns: + A Random instance that stays synchronized with the workflow's randomness. + """ + current_seed = random_seed() + auto_random = Random(current_seed) + + def reseed_callback(new_seed: int) -> None: + auto_random.seed(new_seed) + + register_random_seed_callback(reseed_callback) + return auto_random + + +def time() -> float: + """Current seconds since the epoch from the workflow perspective. + + This is the workflow equivalent of :py:func:`time.time`. + + Returns: + Seconds since the epoch as a float. + """ + return time_ns() / 1e9 + + +def time_ns() -> int: + """Current nanoseconds since the epoch from the workflow perspective. + + This is the workflow equivalent of :py:func:`time.time_ns`. + + Returns: + Nanoseconds since the epoch + """ + return _Runtime.current().workflow_time_ns() + + +def upsert_search_attributes( + attributes: ( + temporalio.common.SearchAttributes + | Sequence[temporalio.common.SearchAttributeUpdate] + ), +) -> None: + """Upsert search attributes for this workflow. + + Args: + attributes: The attributes to set. This should be a sequence of + updates (i.e. values created via value_set and value_unset calls on + search attribute keys). The dictionary form of attributes is + DEPRECATED and if used, result in invalid key types on the + typed_search_attributes property in the info. + """ + if not attributes: + return + temporalio.common._warn_on_deprecated_search_attributes(attributes) + _Runtime.current().workflow_upsert_search_attributes(attributes) + + +def uuid4() -> uuid.UUID: + """Get a new, determinism-safe v4 UUID based on :py:func:`random`. + + Note, this UUID is not cryptographically safe and should not be used for + security purposes. + + Returns: + A deterministically-seeded v4 UUID. + """ + return uuid.UUID(bytes=random().getrandbits(16 * 8).to_bytes(16, "big"), version=4) + + +async def sleep(duration: float | timedelta, *, summary: str | None = None) -> None: + """Sleep for the given duration. + + Args: + duration: Duration to sleep in seconds or as a timedelta. + summary: A single-line fixed summary for this timer that may appear in UI/CLI. + This can be in single-line Temporal markdown format. + """ + await _Runtime.current().workflow_sleep( + duration=( + duration.total_seconds() if isinstance(duration, timedelta) else duration + ), + summary=summary, + ) + + +async def wait_condition( + fn: Callable[[], bool], + *, + timeout: timedelta | float | None = None, + timeout_summary: str | None = None, +) -> None: + """Wait on a callback to become true. + + This function returns when the callback returns true (invoked each loop + iteration) or the timeout has been reached. + + Args: + fn: Non-async callback that accepts no parameters and returns a boolean. + timeout: Optional number of seconds to wait until throwing + :py:class:`asyncio.TimeoutError`. + timeout_summary: Optional simple string identifying the timer (created if ``timeout`` is + present) that may be visible in UI/CLI. While it can be normal text, it is best to treat + as a timer ID. + """ + await _Runtime.current().workflow_wait_condition( + fn, + timeout=timeout.total_seconds() if isinstance(timeout, timedelta) else timeout, + timeout_summary=timeout_summary, + ) diff --git a/temporalio/workflow/_definition.py b/temporalio/workflow/_definition.py new file mode 100644 index 000000000..c1ce21169 --- /dev/null +++ b/temporalio/workflow/_definition.py @@ -0,0 +1,466 @@ +from __future__ import annotations + +import inspect +from collections.abc import Awaitable, Callable, Mapping, Sequence +from dataclasses import dataclass +from typing import Any, cast, overload + +import temporalio.common + +from ..types import ( + CallableAsyncType, + CallableType, + ClassType, + MethodSyncNoParam, + SelfType, +) +from ._handlers import ( + UpdateMethodMultiParam, + _QueryDefinition, + _SignalDefinition, + _UpdateDefinition, +) + +__all__ = [ + "DynamicWorkflowConfig", + "defn", + "dynamic_config", + "init", + "run", +] + + +@overload +def defn(cls: ClassType) -> ClassType: ... + + +@overload +def defn( + *, + name: str | None = None, + sandboxed: bool = True, + failure_exception_types: Sequence[type[BaseException]] = [], + versioning_behavior: temporalio.common.VersioningBehavior = temporalio.common.VersioningBehavior.UNSPECIFIED, +) -> Callable[[ClassType], ClassType]: ... + + +@overload +def defn( + *, + sandboxed: bool = True, + dynamic: bool = False, + versioning_behavior: temporalio.common.VersioningBehavior = temporalio.common.VersioningBehavior.UNSPECIFIED, +) -> Callable[[ClassType], ClassType]: ... + + +def defn( + cls: ClassType | None = None, + *, + name: str | None = None, + sandboxed: bool = True, + dynamic: bool = False, + failure_exception_types: Sequence[type[BaseException]] = [], + versioning_behavior: temporalio.common.VersioningBehavior = temporalio.common.VersioningBehavior.UNSPECIFIED, +) -> Callable[[ClassType], ClassType]: + """Decorator for workflow classes. + + This must be set on any registered workflow class (it is ignored if on a + base class). + + Args: + cls: The class to decorate. + name: Name to use for the workflow. Defaults to class ``__name__``. This + cannot be set if dynamic is set. + sandboxed: Whether the workflow should run in a sandbox. Default is + true. + dynamic: If true, this activity will be dynamic. Dynamic workflows have + to accept a single 'Sequence[RawValue]' parameter. This cannot be + set to true if name is present. + failure_exception_types: The types of exceptions that, if a + workflow-thrown exception extends, will cause the workflow/update to + fail instead of suspending the workflow via task failure. These are + applied in addition to ones set on the worker constructor. If + ``Exception`` is set, it effectively will fail a workflow/update in + all user exception cases. WARNING: This setting is experimental. + versioning_behavior: Specifies the versioning behavior to use for this workflow. + """ + + def decorator(cls: ClassType) -> ClassType: + # This performs validation + _Definition._apply_to_class( + cls, + workflow_name=name or cls.__name__ if not dynamic else None, + sandboxed=sandboxed, + failure_exception_types=failure_exception_types, + versioning_behavior=versioning_behavior, + ) + return cls + + if cls is not None: + return decorator(cls) + return decorator + + +def init( + init_fn: CallableType, +) -> CallableType: + """Decorator for the workflow init method. + + This may be used on the __init__ method of the workflow class to specify + that it accepts the same workflow input arguments as the ``@workflow.run`` + method. If used, the parameters of your __init__ and ``@workflow.run`` + methods must be identical. + + Args: + init_fn: The __init__ method to decorate. + """ + if init_fn.__name__ != "__init__": + raise ValueError("@workflow.init may only be used on the __init__ method") + + setattr(init_fn, "__temporal_workflow_init", True) + return init_fn + + +def run(fn: CallableAsyncType) -> CallableAsyncType: + """Decorator for the workflow run method. + + This must be used on one and only one async method defined on the same class + as ``@workflow.defn``. This can be defined on a base class method but must + then be explicitly overridden and defined on the workflow class. + + Run methods can only have positional parameters. Best practice is to only + take a single object/dataclass argument that can accept more fields later if + needed. + + Args: + fn: The function to decorate. + """ + if not inspect.iscoroutinefunction(fn): + raise ValueError("Workflow run method must be an async function") + # Disallow local classes because we need to have the class globally + # referenceable by name + if "" in fn.__qualname__: + raise ValueError( + "Local classes unsupported, @workflow.run cannot be on a local class" + ) + setattr(fn, "__temporal_workflow_run", True) + # TODO(cretz): Why is MyPy unhappy with this return? + return fn # type: ignore[return-value] + + +@dataclass(frozen=True) +class DynamicWorkflowConfig: + """Returned by functions using the :py:func:`dynamic_config` decorator, see it for more.""" + + failure_exception_types: Sequence[type[BaseException]] | None = None + """The types of exceptions that, if a workflow-thrown exception extends, will cause the + workflow/update to fail instead of suspending the workflow via task failure. These are applied + in addition to ones set on the worker constructor. If ``Exception`` is set, it effectively will + fail a workflow/update in all user exception cases. + + Always overrides the equivalent parameter on :py:func:`defn` if set not-None. + + WARNING: This setting is experimental. + """ + versioning_behavior: temporalio.common.VersioningBehavior = ( + temporalio.common.VersioningBehavior.UNSPECIFIED + ) + """Specifies the versioning behavior to use for this workflow. + + Always overrides the equivalent parameter on :py:func:`defn`. + """ + + +def dynamic_config( + fn: MethodSyncNoParam[SelfType, DynamicWorkflowConfig], +) -> MethodSyncNoParam[SelfType, DynamicWorkflowConfig]: + """Decorator to allow configuring a dynamic workflow's behavior. + + Because dynamic workflows may conceptually represent more than one workflow type, it may be + desirable to have different settings for fields that would normally be passed to + :py:func:`defn`, but vary based on the workflow type name or other information available in + the workflow's context. This function will be called after the workflow's :py:func:`init`, + if it has one, but before the workflow's :py:func:`run` method. + + The method must only take self as a parameter, and any values set in the class it returns will + override those provided to :py:func:`defn`. + + Cannot be specified on non-dynamic workflows. + + Args: + fn: The function to decorate. + """ + if inspect.iscoroutinefunction(fn): + raise ValueError("Workflow dynamic_config method must be synchronous") + params = list(inspect.signature(fn).parameters.values()) + if len(params) != 1: + raise ValueError("Workflow dynamic_config method must only take self parameter") + + # Add marker attribute + setattr(fn, "__temporal_workflow_dynamic_config", True) + return fn + + +@dataclass(frozen=True) +class _Definition: + name: str | None + cls: type + run_fn: Callable[..., Awaitable] + signals: Mapping[str | None, _SignalDefinition] + queries: Mapping[str | None, _QueryDefinition] + updates: Mapping[str | None, _UpdateDefinition] + sandboxed: bool + failure_exception_types: Sequence[type[BaseException]] + # Types loaded on post init if both are None + arg_types: list[type] | None = None + ret_type: type | None = None + versioning_behavior: temporalio.common.VersioningBehavior | None = None + dynamic_config_fn: Callable[..., DynamicWorkflowConfig] | None = None + + @staticmethod + def from_class(cls: type) -> _Definition | None: # type: ignore[reportSelfClsParameterName] + # We make sure to only return it if it's on _this_ class + defn = getattr(cls, "__temporal_workflow_definition", None) + if defn and defn.cls == cls: + return defn + return None + + @staticmethod + def must_from_class(cls: type) -> _Definition: # type: ignore[reportSelfClsParameterName] + ret = _Definition.from_class(cls) + if ret: + return ret + cls_name = getattr(cls, "__name__", "") + raise ValueError( + f"Workflow {cls_name} missing attributes, was it decorated with @workflow.defn?" + ) + + @staticmethod + def from_run_fn(fn: Callable[..., Awaitable[Any]]) -> _Definition | None: + return getattr(fn, "__temporal_workflow_definition", None) + + @staticmethod + def must_from_run_fn(fn: Callable[..., Awaitable[Any]]) -> _Definition: + ret = _Definition.from_run_fn(fn) + if ret: + return ret + fn_name = getattr(fn, "__qualname__", "") + raise ValueError( + f"Function {fn_name} missing attributes, was it decorated with @workflow.run and was its class decorated with @workflow.defn?" + ) + + @classmethod + def get_name_and_result_type( + cls, name_or_run_fn: str | Callable[..., Awaitable[Any]] + ) -> tuple[str, type | None]: + if isinstance(name_or_run_fn, str): + return name_or_run_fn, None + elif callable(name_or_run_fn): + defn = cls.must_from_run_fn(name_or_run_fn) + if not defn.name: + raise ValueError("Cannot invoke dynamic workflow explicitly") + return defn.name, defn.ret_type + else: + raise TypeError("Workflow must be a string or callable") # type: ignore[reportUnreachable] + + @staticmethod + def _apply_to_class( + cls: type, # type: ignore[reportSelfClsParameterName] + *, + workflow_name: str | None, + sandboxed: bool, + failure_exception_types: Sequence[type[BaseException]], + versioning_behavior: temporalio.common.VersioningBehavior, + ) -> None: + # Check it's not being doubly applied + if _Definition.from_class(cls): + raise ValueError("Class already contains workflow definition") + issues: list[str] = [] + + # Collect run fn and all signal/query/update fns + init_fn: Callable[..., None] | None = None + run_fn: Callable[..., Awaitable[Any]] | None = None + dynamic_config_fn: Callable[..., DynamicWorkflowConfig] | None = None + seen_run_attr = False + signals: dict[str | None, _SignalDefinition] = {} + queries: dict[str | None, _QueryDefinition] = {} + updates: dict[str | None, _UpdateDefinition] = {} + for name, member in inspect.getmembers(cls): + if hasattr(member, "__temporal_workflow_run"): + seen_run_attr = True + if not _is_unbound_method_on_cls(member, cls): + issues.append( + f"@workflow.run method {name} must be defined on {cls.__qualname__}" + ) + elif run_fn is not None: + issues.append( + f"Multiple @workflow.run methods found (at least on {name} and {run_fn.__name__})" + ) + else: + # We can guarantee the @workflow.run decorator did + # validation of the function itself + run_fn = member + elif hasattr(member, "__temporal_signal_definition"): + signal_defn = cast( + _SignalDefinition, getattr(member, "__temporal_signal_definition") + ) + if signal_defn.name in signals: + defn_name = signal_defn.name or "" + # TODO(cretz): Remove cast when https://github.com/python/mypy/issues/5485 fixed + other_fn = cast(Callable, signals[signal_defn.name].fn) + issues.append( + f"Multiple signal methods found for {defn_name} " + f"(at least on {name} and {other_fn.__name__})" + ) + else: + signals[signal_defn.name] = signal_defn + elif hasattr(member, "__temporal_query_definition"): + query_defn = cast( + _QueryDefinition, getattr(member, "__temporal_query_definition") + ) + if query_defn.name in queries: + defn_name = query_defn.name or "" + issues.append( + f"Multiple query methods found for {defn_name} " + f"(at least on {name} and {queries[query_defn.name].fn.__name__})" + ) + else: + queries[query_defn.name] = query_defn + elif name == "__init__" and hasattr(member, "__temporal_workflow_init"): + init_fn = member + elif hasattr(member, "__temporal_workflow_dynamic_config"): + if workflow_name: + issues.append( + "@workflow.dynamic_config can only be used in dynamic workflows, but " + f"workflow class {workflow_name} ({cls.__name__}) is not dynamic" + ) + if dynamic_config_fn: + issues.append( + "@workflow.dynamic_config can only be defined once per workflow" + ) + dynamic_config_fn = member + elif isinstance(member, UpdateMethodMultiParam): + update_defn = member._defn + if update_defn.name in updates: + defn_name = update_defn.name or "" + issues.append( + f"Multiple update methods found for {defn_name} " + f"(at least on {name} and {updates[update_defn.name].fn.__name__})" + ) + elif update_defn.validator and not _parameters_identical_up_to_naming( + update_defn.fn, update_defn.validator + ): + issues.append( + f"Update validator method {update_defn.validator.__name__} parameters " + f"do not match update method {update_defn.fn.__name__} parameters" + ) + else: + updates[update_defn.name] = update_defn + + # Check base classes haven't defined things with different decorators + for base_cls in inspect.getmro(cls)[1:]: + for _, base_member in inspect.getmembers(base_cls): + # We only care about methods defined on this class + if not inspect.isfunction(base_member) or not _is_unbound_method_on_cls( + base_member, base_cls + ): + continue + if hasattr(base_member, "__temporal_workflow_run"): + seen_run_attr = True + if not run_fn or base_member.__name__ != run_fn.__name__: + issues.append( + f"@workflow.run defined on {base_member.__qualname__} but not on the override" + ) + elif hasattr(base_member, "__temporal_signal_definition"): + signal_defn = cast( + _SignalDefinition, + getattr(base_member, "__temporal_signal_definition"), + ) + if signal_defn.name not in signals: + issues.append( + f"@workflow.signal defined on {base_member.__qualname__} but not on the override" + ) + elif hasattr(base_member, "__temporal_query_definition"): + query_defn = cast( + _QueryDefinition, + getattr(base_member, "__temporal_query_definition"), + ) + if query_defn.name not in queries: + issues.append( + f"@workflow.query defined on {base_member.__qualname__} but not on the override" + ) + elif isinstance(base_member, UpdateMethodMultiParam): + update_defn = base_member._defn + if update_defn.name not in updates: + issues.append( + f"@workflow.update defined on {base_member.__qualname__} but not on the override" + ) + + if not seen_run_attr: + issues.append("Missing @workflow.run method") + if init_fn and run_fn: + if not _parameters_identical_up_to_naming(init_fn, run_fn): + issues.append( + "@workflow.init and @workflow.run method parameters do not match" + ) + if issues: + if len(issues) == 1: + raise ValueError(f"Invalid workflow class: {issues[0]}") + raise ValueError( + f"Invalid workflow class for {len(issues)} reasons: {', '.join(issues)}" + ) + + assert run_fn + assert seen_run_attr + defn = _Definition( + name=workflow_name, + cls=cls, + run_fn=run_fn, + signals=signals, + queries=queries, + updates=updates, + sandboxed=sandboxed, + failure_exception_types=failure_exception_types, + versioning_behavior=versioning_behavior, + dynamic_config_fn=dynamic_config_fn, + ) + setattr(cls, "__temporal_workflow_definition", defn) + setattr(run_fn, "__temporal_workflow_definition", defn) + + def __post_init__(self) -> None: + if self.arg_types is None and self.ret_type is None: + dynamic = self.name is None + arg_types, ret_type = temporalio.common._type_hints_from_func(self.run_fn) + # If dynamic, must be a sequence of raw values + if dynamic and ( + not arg_types + or len(arg_types) != 1 + or arg_types[0] != Sequence[temporalio.common.RawValue] + ): + raise TypeError( + "Dynamic workflow must accept a single Sequence[temporalio.common.RawValue]" + ) + object.__setattr__(self, "arg_types", arg_types) + object.__setattr__(self, "ret_type", ret_type) + + +def _parameters_identical_up_to_naming(fn1: Callable, fn2: Callable) -> bool: + """Return True if the functions have identical parameter lists, ignoring parameter names.""" + + def params(fn: Callable) -> list[inspect.Parameter]: + # Ignore name when comparing parameters (remaining fields are kind, + # default, and annotation). + return [p.replace(name="x") for p in inspect.signature(fn).parameters.values()] + + # We require that any type annotations present match exactly; i.e. we do + # not support any notion of subtype compatibility. + return params(fn1) == params(fn2) + + +def _is_unbound_method_on_cls(fn: Callable[..., Any], cls: type) -> bool: + # Python 3 does not make this easy, ref https://stackoverflow.com/questions/3589311 + return ( + inspect.isfunction(fn) + and inspect.getmodule(fn) is inspect.getmodule(cls) + and fn.__qualname__.rsplit(".", 1)[0] == cls.__name__ + ) diff --git a/temporalio/workflow/_exceptions.py b/temporalio/workflow/_exceptions.py new file mode 100644 index 000000000..2d34c2fed --- /dev/null +++ b/temporalio/workflow/_exceptions.py @@ -0,0 +1,119 @@ +from __future__ import annotations + +from enum import Enum, IntEnum + +import temporalio.api.enums.v1 +import temporalio.bridge.proto.common +import temporalio.exceptions + +__all__ = [ + "NondeterminismError", + "ReadOnlyContextError", + "VersioningIntent", + "ContinueAsNewVersioningBehavior", +] + + +class NondeterminismError(temporalio.exceptions.TemporalError): + """Error that can be thrown during replay for non-deterministic workflow.""" + + def __init__(self, message: str) -> None: + """Initialize a nondeterminism error.""" + super().__init__(message) + self.message = message + + +class ReadOnlyContextError(temporalio.exceptions.TemporalError): + """Error thrown when trying to do mutable workflow calls in a read-only + context like a query or update validator. + """ + + def __init__(self, message: str) -> None: + """Initialize a read-only context error.""" + super().__init__(message) + self.message = message + + +class _NotInWorkflowEventLoopError( # pyright: ignore[reportUnusedClass] + temporalio.exceptions.TemporalError +): + def __init__(self, *args: object) -> None: + super().__init__("Not in workflow event loop") + self.message = "Not in workflow event loop" + + +class VersioningIntent(Enum): + """Indicates whether the user intends certain commands to be run on a compatible worker Build + Id version or not. + + `COMPATIBLE` indicates that the command should run on a worker with compatible version if + possible. It may not be possible if the target task queue does not also have knowledge of the + current worker's Build Id. + + `DEFAULT` indicates that the command should run on the target task queue's current + overall-default Build Id. + + Where this type is accepted optionally, an unset value indicates that the SDK should choose the + most sensible default behavior for the type of command, accounting for whether the command will + be run on the same task queue as the current worker. + + .. deprecated:: + Use Worker Deployment versioning instead. + """ + + COMPATIBLE = 1 + DEFAULT = 2 + + def _to_proto(self) -> temporalio.bridge.proto.common.VersioningIntent.ValueType: + if self == VersioningIntent.COMPATIBLE: + return temporalio.bridge.proto.common.VersioningIntent.COMPATIBLE + elif self == VersioningIntent.DEFAULT: + return temporalio.bridge.proto.common.VersioningIntent.DEFAULT + return temporalio.bridge.proto.common.VersioningIntent.UNSPECIFIED + + +class ContinueAsNewVersioningBehavior(IntEnum): + """Experimental. Optionally decide the versioning behavior that the first task of the new run should use. + For example, choose to AutoUpgrade on continue-as-new instead of inheriting the pinned version + of the previous run. + """ + + UNSPECIFIED = int( + temporalio.api.enums.v1.ContinueAsNewVersioningBehavior.CONTINUE_AS_NEW_VERSIONING_BEHAVIOR_UNSPECIFIED + ) + """An initial versioning behavior is not set, follow the existing continue-as-new inheritance semantics. + See https://docs.temporal.io/worker-versioning#inheritance-semantics for more detail. + """ + + AUTO_UPGRADE = int( + temporalio.api.enums.v1.ContinueAsNewVersioningBehavior.CONTINUE_AS_NEW_VERSIONING_BEHAVIOR_AUTO_UPGRADE + ) + """Start the new run with AutoUpgrade behavior. Use the Target Version of the workflow's task queue at + start-time, as AutoUpgrade workflows do. After the first workflow task completes, use whatever + Versioning Behavior the workflow is annotated with in the workflow code. + + Note that if the previous workflow had a Pinned override, that override will be inherited by the + new workflow run regardless of the ContinueAsNewVersioningBehavior specified in the continue-as-new + command. If a Pinned override is inherited by the new run, and the new run starts with AutoUpgrade + behavior, the base version of the new run will be the Target Version as described above, but the + effective version will be whatever is specified by the Versioning Override until the override is removed. + """ + + USE_RAMPING_VERSION = int( + temporalio.api.enums.v1.ContinueAsNewVersioningBehavior.CONTINUE_AS_NEW_VERSIONING_BEHAVIOR_USE_RAMPING_VERSION + ) + """Use the Ramping Version of the workflow's task queue at start time, regardless of the workflow's + Target Version. After the first workflow task completes, the workflow will use whatever Versioning + Behavior it is annotated with. If there is no Ramping Version by the time that the first workflow task + is dispatched, it will be sent to the Current Version. + + It is highly discouraged to use this if the workflow is annotated with AutoUpgrade behavior, because + this setting ONLY applies to the first task of the workflow. If, after the first task, the workflow + is AutoUpgrade, it will behave like a normal AutoUpgrade workflow and go to the Target Version, which + may be the Current Version instead of the Ramping Version. + + Note that if the workflow being continued has a Pinned override, that override will be inherited by the + new workflow run regardless of the ContinueAsNewVersioningBehavior specified in the continue-as-new + command. Versioning Override always takes precedence until it's removed manually via + UpdateWorkflowExecutionOptions. + """ diff --git a/temporalio/workflow/_handlers.py b/temporalio/workflow/_handlers.py new file mode 100644 index 000000000..afa0bb6e4 --- /dev/null +++ b/temporalio/workflow/_handlers.py @@ -0,0 +1,587 @@ +from __future__ import annotations + +import inspect +import typing +import warnings +from collections.abc import Awaitable, Callable, Sequence +from dataclasses import dataclass +from enum import Enum +from functools import partial +from typing import Any, Literal, cast, overload + +from typing_extensions import Protocol, runtime_checkable + +import temporalio.common + +from ..types import ( + CallableSyncOrAsyncReturnNoneType, + CallableSyncOrAsyncType, + CallableType, + MultiParamSpec, + ProtocolReturnType, + ReturnType, +) + +__all__ = [ + "HandlerUnfinishedPolicy", + "UnfinishedSignalHandlersWarning", + "UnfinishedUpdateHandlersWarning", + "UpdateMethodMultiParam", + "query", + "signal", + "update", +] + + +class HandlerUnfinishedPolicy(Enum): + """Actions taken if a workflow terminates with running handlers. + + Policy defining actions taken when a workflow exits while update or signal handlers are running. + The workflow exit may be due to successful return, failure, cancellation, or continue-as-new. + """ + + WARN_AND_ABANDON = 1 + """Issue a warning in addition to abandoning.""" + ABANDON = 2 + """Abandon the handler. + + In the case of an update handler this means that the client will receive an error rather than + the update result.""" + + +class UnfinishedUpdateHandlersWarning(RuntimeWarning): + """The workflow exited before all update handlers had finished executing.""" + + +class UnfinishedSignalHandlersWarning(RuntimeWarning): + """The workflow exited before all signal handlers had finished executing.""" + + +@overload +def signal( + fn: CallableSyncOrAsyncReturnNoneType, +) -> CallableSyncOrAsyncReturnNoneType: ... + + +@overload +def signal( + *, + unfinished_policy: HandlerUnfinishedPolicy = HandlerUnfinishedPolicy.WARN_AND_ABANDON, + description: str | None = None, +) -> Callable[ + [CallableSyncOrAsyncReturnNoneType], CallableSyncOrAsyncReturnNoneType +]: ... + + +@overload +def signal( + *, + name: str, + unfinished_policy: HandlerUnfinishedPolicy = HandlerUnfinishedPolicy.WARN_AND_ABANDON, + description: str | None = None, +) -> Callable[ + [CallableSyncOrAsyncReturnNoneType], CallableSyncOrAsyncReturnNoneType +]: ... + + +@overload +def signal( + *, + dynamic: Literal[True], + unfinished_policy: HandlerUnfinishedPolicy = HandlerUnfinishedPolicy.WARN_AND_ABANDON, + description: str | None = None, +) -> Callable[ + [CallableSyncOrAsyncReturnNoneType], CallableSyncOrAsyncReturnNoneType +]: ... + + +def signal( + fn: CallableSyncOrAsyncReturnNoneType | None = None, + *, + name: str | None = None, + dynamic: bool | None = False, + unfinished_policy: HandlerUnfinishedPolicy = HandlerUnfinishedPolicy.WARN_AND_ABANDON, + description: str | None = None, +) -> ( + Callable[[CallableSyncOrAsyncReturnNoneType], CallableSyncOrAsyncReturnNoneType] + | CallableSyncOrAsyncReturnNoneType +): + """Decorator for a workflow signal method. + + This is used on any async or non-async method that you wish to be called upon + receiving a signal. If a function overrides one with this decorator, it too + must be decorated. + + Signal methods can only have positional parameters. Best practice for + non-dynamic signal methods is to only take a single object/dataclass + argument that can accept more fields later if needed. Return values from + signal methods are ignored. + + Args: + fn: The function to decorate. + name: Signal name. Defaults to method ``__name__``. Cannot be present + when ``dynamic`` is present. + dynamic: If true, this handles all signals not otherwise handled. The + parameters of the method must be self, a string name, and a + ``*args`` positional varargs. Cannot be present when ``name`` is + present. + unfinished_policy: Actions taken if a workflow terminates with + a running instance of this handler. + description: A short description of the signal that may appear in the UI/CLI. + """ + + def decorator( + name: str | None, + unfinished_policy: HandlerUnfinishedPolicy, + fn: CallableSyncOrAsyncReturnNoneType, + ) -> CallableSyncOrAsyncReturnNoneType: + if not name and not dynamic: + name = fn.__name__ + defn = _SignalDefinition( + name=name, + fn=fn, + is_method=True, + unfinished_policy=unfinished_policy, + description=description, + ) + setattr(fn, "__temporal_signal_definition", defn) + if defn.dynamic_vararg: + warnings.warn( + "Dynamic signals with vararg third param is deprecated, use Sequence[RawValue]", + DeprecationWarning, + stacklevel=2, + ) + return fn + + if not fn: + if name is not None and dynamic: + raise RuntimeError("Cannot provide name and dynamic boolean") + return partial(decorator, name, unfinished_policy) + else: + return decorator(fn.__name__, unfinished_policy, fn) + + +@overload +def query(fn: CallableType) -> CallableType: ... + + +@overload +def query( + *, name: str, description: str | None = None +) -> Callable[[CallableType], CallableType]: ... + + +@overload +def query( + *, dynamic: Literal[True], description: str | None = None +) -> Callable[[CallableType], CallableType]: ... + + +@overload +def query(*, description: str) -> Callable[[CallableType], CallableType]: ... + + +def query( + fn: CallableType | None = None, # type: ignore[reportInvalidTypeVarUse] + *, + name: str | None = None, + dynamic: bool | None = False, + description: str | None = None, +): + """Decorator for a workflow query method. + + This is used on any non-async method that expects to handle a query. If a + function overrides one with this decorator, it too must be decorated. + + Query methods can only have positional parameters. Best practice for + non-dynamic query methods is to only take a single object/dataclass + argument that can accept more fields later if needed. The return value is + the resulting query value. Query methods must not mutate any workflow state. + + Args: + fn: The function to decorate. + name: Query name. Defaults to method ``__name__``. Cannot be present + when ``dynamic`` is present. + dynamic: If true, this handles all queries not otherwise handled. The + parameters of the method should be self, a string name, and a + ``Sequence[RawValue]``. An older form of this accepted vararg + parameters which will now warn. Cannot be present when ``name`` is + present. + description: A short description of the query that may appear in the UI/CLI. + """ + + def decorator( + name: str | None, + description: str | None, + fn: CallableType, + *, + bypass_async_check: bool = False, + ) -> CallableType: + if not name and not dynamic: + name = fn.__name__ + if not bypass_async_check and inspect.iscoroutinefunction(fn): + warnings.warn( + "Queries as async def functions are deprecated", + DeprecationWarning, + stacklevel=2, + ) + defn = _QueryDefinition( + name=name, fn=fn, is_method=True, description=description + ) + setattr(fn, "__temporal_query_definition", defn) + if defn.dynamic_vararg: + warnings.warn( + "Dynamic queries with vararg third param is deprecated, use Sequence[RawValue]", + DeprecationWarning, + stacklevel=2, + ) + return fn + + if name is not None or dynamic or description: + if name is not None and dynamic: + raise RuntimeError("Cannot provide name and dynamic boolean") + return partial(decorator, name, description) + if fn is None: + raise RuntimeError("Cannot create query without function or name or dynamic") + if inspect.iscoroutinefunction(fn): + warnings.warn( + "Queries as async def functions are deprecated", + DeprecationWarning, + stacklevel=2, + ) + return decorator(fn.__name__, description, fn, bypass_async_check=True) + + +@runtime_checkable +class UpdateMethodMultiParam(Protocol[MultiParamSpec, ProtocolReturnType]): + """Decorated workflow update functions implement this.""" + + _defn: _UpdateDefinition + + def __call__( + self, *args: MultiParamSpec.args, **kwargs: MultiParamSpec.kwargs + ) -> ProtocolReturnType | Awaitable[ProtocolReturnType]: + """Generic callable type callback.""" + ... + + def validator( + self, vfunc: Callable[MultiParamSpec, None] + ) -> Callable[MultiParamSpec, None]: + """Use to decorate a function to validate the arguments passed to the update handler.""" + ... + + +@overload +def update( + fn: Callable[MultiParamSpec, Awaitable[ReturnType]], +) -> UpdateMethodMultiParam[MultiParamSpec, ReturnType]: ... + + +@overload +def update( + fn: Callable[MultiParamSpec, ReturnType], +) -> UpdateMethodMultiParam[MultiParamSpec, ReturnType]: ... + + +@overload +def update( + *, + unfinished_policy: HandlerUnfinishedPolicy = HandlerUnfinishedPolicy.WARN_AND_ABANDON, + description: str | None = None, +) -> Callable[ + [Callable[MultiParamSpec, ReturnType]], + UpdateMethodMultiParam[MultiParamSpec, ReturnType], +]: ... + + +@overload +def update( + *, + name: str, + unfinished_policy: HandlerUnfinishedPolicy = HandlerUnfinishedPolicy.WARN_AND_ABANDON, + description: str | None = None, +) -> Callable[ + [Callable[MultiParamSpec, ReturnType]], + UpdateMethodMultiParam[MultiParamSpec, ReturnType], +]: ... + + +@overload +def update( + *, + dynamic: Literal[True], + unfinished_policy: HandlerUnfinishedPolicy = HandlerUnfinishedPolicy.WARN_AND_ABANDON, + description: str | None = None, +) -> Callable[ + [Callable[MultiParamSpec, ReturnType]], + UpdateMethodMultiParam[MultiParamSpec, ReturnType], +]: ... + + +def update( + fn: CallableSyncOrAsyncType | None = None, # type: ignore[reportInvalidTypeVarUse] + *, + name: str | None = None, + dynamic: bool | None = False, + unfinished_policy: HandlerUnfinishedPolicy = HandlerUnfinishedPolicy.WARN_AND_ABANDON, + description: str | None = None, +) -> ( + UpdateMethodMultiParam[MultiParamSpec, ReturnType] + | Callable[ + [Callable[MultiParamSpec, ReturnType]], + UpdateMethodMultiParam[MultiParamSpec, ReturnType], + ] +): + """Decorator for a workflow update handler method. + + This is used on any async or non-async method that you wish to be called upon + receiving an update. If a function overrides one with this decorator, it too + must be decorated. + + You may also optionally define a validator method that will be called before + this handler you have applied this decorator to. You can specify the validator + with ``@update_handler_function_name.validator``. + + Update methods can only have positional parameters. Best practice for + non-dynamic update methods is to only take a single object/dataclass + argument that can accept more fields later if needed. The handler may return + a serializable value which will be sent back to the caller of the update. + + Args: + fn: The function to decorate. + name: Update name. Defaults to method ``__name__``. Cannot be present + when ``dynamic`` is present. + dynamic: If true, this handles all updates not otherwise handled. The + parameters of the method must be self, a string name, and a + ``*args`` positional varargs. Cannot be present when ``name`` is + present. + unfinished_policy: Actions taken if a workflow terminates with + a running instance of this handler. + description: A short description of the update that may appear in the UI/CLI. + """ + + def decorator( + name: str | None, + unfinished_policy: HandlerUnfinishedPolicy, + fn: CallableSyncOrAsyncType, + ) -> CallableSyncOrAsyncType: + if not name and not dynamic: + name = fn.__name__ + defn = _UpdateDefinition( + name=name, + fn=fn, + is_method=True, + unfinished_policy=unfinished_policy, + description=description, + ) + if defn.dynamic_vararg: + raise RuntimeError( + "Dynamic updates do not support a vararg third param, use Sequence[RawValue]", + ) + setattr(fn, "_defn", defn) + setattr(fn, "validator", partial(_update_validator, defn)) + return fn + + if not fn: + if name is not None and dynamic: + raise RuntimeError("Cannot provide name and dynamic boolean") + return partial(decorator, name, unfinished_policy) # type: ignore[reportReturnType, return-value] + else: + return decorator(fn.__name__, unfinished_policy, fn) # type: ignore[reportReturnType, return-value] + + +def _update_validator( + update_def: _UpdateDefinition, fn: Callable[..., None] | None = None +) -> Callable[..., None] | None: + """Decorator for a workflow update validator method.""" + if fn is not None: + update_def.set_validator(fn) + return fn + + +def _bind_method(obj: Any, fn: Callable[..., Any]) -> Callable[..., Any]: + # Curry instance on the definition function since that represents an + # unbound method + if inspect.iscoroutinefunction(fn): + # We cannot use functools.partial here because in <= 3.7 that isn't + # considered an inspect.iscoroutinefunction + fn = cast(Callable[..., Awaitable[Any]], fn) + + async def with_object(*args: Any, **kwargs: Any) -> Any: + return await fn(obj, *args, **kwargs) + + return with_object + return partial(fn, obj) + + +def _assert_dynamic_handler_args( + fn: Callable, arg_types: list[type] | None, is_method: bool +) -> bool: + # Dynamic query/signal/update must have three args: self, name, and + # Sequence[RawValue]. An older form accepted varargs for the third param for signals/queries so + # we will too (but will warn in the signal/query code). + params = list(inspect.signature(fn).parameters.values()) + total_expected_params = 3 if is_method else 2 + if ( + len(params) == total_expected_params + and params[-2].kind is inspect.Parameter.POSITIONAL_OR_KEYWORD + and params[-1].kind is inspect.Parameter.VAR_POSITIONAL + ): + # Old var-arg form + return False + if ( + not arg_types + or len(arg_types) != 2 + or arg_types[0] is not str + or ( + arg_types[1] != Sequence[temporalio.common.RawValue] + and arg_types[1] != typing.Sequence[temporalio.common.RawValue] # type: ignore[reportDeprecated] + ) + ): + raise RuntimeError( + "Dynamic handler must have 3 arguments: self, str, and Sequence[RawValue]" + ) + return True + + +@dataclass(frozen=True) +class _SignalDefinition: + # None if dynamic + name: str | None + fn: Callable[..., None | Awaitable[None]] + is_method: bool + unfinished_policy: HandlerUnfinishedPolicy = ( + HandlerUnfinishedPolicy.WARN_AND_ABANDON + ) + description: str | None = None + # Types loaded on post init if None + arg_types: list[type] | None = None + dynamic_vararg: bool = False + + @staticmethod + def from_fn(fn: Callable) -> _SignalDefinition | None: + return getattr(fn, "__temporal_signal_definition", None) + + @staticmethod + def must_name_from_fn_or_str(signal: str | Callable) -> str: + if callable(signal): + defn = _SignalDefinition.from_fn(signal) + if not defn: + raise RuntimeError( + f"Signal definition not found on {signal.__qualname__}, " + "is it decorated with @workflow.signal?" + ) + elif not defn.name: + raise RuntimeError("Cannot invoke dynamic signal definition") + # TODO(cretz): Check count/type of args at runtime? + return defn.name + return str(signal) + + def __post_init__(self) -> None: + if self.arg_types is None: + arg_types, _ = temporalio.common._type_hints_from_func(self.fn) + # If dynamic, assert it + if not self.name: + object.__setattr__( + self, + "dynamic_vararg", + not _assert_dynamic_handler_args( + self.fn, arg_types, self.is_method + ), + ) + object.__setattr__(self, "arg_types", arg_types) + + def bind_fn(self, obj: Any) -> Callable[..., Any]: + return _bind_method(obj, self.fn) + + +@dataclass(frozen=True) +class _QueryDefinition: + # None if dynamic + name: str | None + fn: Callable[..., Any] + is_method: bool + description: str | None = None + # Types loaded on post init if both are None + arg_types: list[type] | None = None + ret_type: type | None = None + dynamic_vararg: bool = False + + @staticmethod + def from_fn(fn: Callable) -> _QueryDefinition | None: + return getattr(fn, "__temporal_query_definition", None) + + def __post_init__(self) -> None: + if self.arg_types is None and self.ret_type is None: + arg_types, ret_type = temporalio.common._type_hints_from_func(self.fn) + # If dynamic, assert it + if not self.name: + object.__setattr__( + self, + "dynamic_vararg", + not _assert_dynamic_handler_args( + self.fn, arg_types, self.is_method + ), + ) + object.__setattr__(self, "arg_types", arg_types) + object.__setattr__(self, "ret_type", ret_type) + + def bind_fn(self, obj: Any) -> Callable[..., Any]: + return _bind_method(obj, self.fn) + + +@dataclass(frozen=True) +class _UpdateDefinition: + # None if dynamic + name: str | None + fn: Callable[..., Any | Awaitable[Any]] + is_method: bool + unfinished_policy: HandlerUnfinishedPolicy = ( + HandlerUnfinishedPolicy.WARN_AND_ABANDON + ) + description: str | None = None + # Types loaded on post init if None + arg_types: list[type] | None = None + ret_type: type | None = None + validator: Callable[..., None] | None = None + dynamic_vararg: bool = False + + def __post_init__(self) -> None: + if self.arg_types is None: + arg_types, ret_type = temporalio.common._type_hints_from_func(self.fn) + # Disallow dynamic varargs + if not self.name and not _assert_dynamic_handler_args( + self.fn, arg_types, self.is_method + ): + raise RuntimeError( + "Dynamic updates do not support a vararg third param, use Sequence[RawValue]", + ) + object.__setattr__(self, "arg_types", arg_types) + object.__setattr__(self, "ret_type", ret_type) + + def bind_fn(self, obj: Any) -> Callable[..., Any]: + return _bind_method(obj, self.fn) + + def bind_validator(self, obj: Any) -> Callable[..., Any]: + if self.validator is not None: + return _bind_method(obj, self.validator) + return lambda *args, **kwargs: None + + def set_validator(self, validator: Callable[..., None]) -> None: + if self.validator: + raise RuntimeError(f"Validator already set for update {self.name}") + object.__setattr__(self, "validator", validator) + + @classmethod + def get_name_and_result_type( + cls, + name_or_update_fn: str | Callable[..., Any], + ) -> tuple[str, type | None]: + if isinstance(name_or_update_fn, UpdateMethodMultiParam): + defn = name_or_update_fn._defn + if not defn.name: + raise RuntimeError("Cannot invoke dynamic update definition") + # TODO(cretz): Check count/type of args at runtime? + return defn.name, defn.ret_type + else: + return str(name_or_update_fn), None diff --git a/temporalio/workflow/_nexus.py b/temporalio/workflow/_nexus.py new file mode 100644 index 000000000..7b3b842fe --- /dev/null +++ b/temporalio/workflow/_nexus.py @@ -0,0 +1,503 @@ +from __future__ import annotations + +from abc import ABC, abstractmethod +from collections.abc import Awaitable, Callable, Generator, Mapping +from datetime import timedelta +from enum import IntEnum +from typing import Any, Generic, TypeVar, overload + +import nexusrpc +import nexusrpc.handler +from nexusrpc import InputT, OutputT + +import temporalio.bridge.proto.nexus +import temporalio.nexus +from temporalio.nexus._util import ServiceHandlerT + +from ._context import _Runtime + +__all__ = [ + "NexusClient", + "NexusOperationCancellationType", + "NexusOperationHandle", + "ServiceT", + "create_nexus_client", +] + + +class NexusOperationHandle(Generic[OutputT]): + """Handle for interacting with a Nexus operation.""" + + # TODO(nexus-preview): should attempts to instantiate directly throw? + + def cancel(self) -> bool: + """Request cancellation of the operation.""" + raise NotImplementedError + + def __await__(self) -> Generator[Any, Any, OutputT]: + """Support await.""" + raise NotImplementedError + + @property + def operation_token(self) -> str | None: + """The operation token for this handle.""" + raise NotImplementedError + + +ServiceT = TypeVar("ServiceT") + + +class NexusOperationCancellationType(IntEnum): + """Defines behavior of a Nexus operation when the caller workflow initiates cancellation. + + Pass one of these values to :py:meth:`NexusClient.start_operation` to define cancellation + behavior. + + To initiate cancellation, use :py:meth:`NexusOperationHandle.cancel` and then ``await`` the + operation handle. This will result in a :py:class:`exceptions.NexusOperationError`. The values + of this enum define what is guaranteed to have happened by that point. + """ + + ABANDON = int(temporalio.bridge.proto.nexus.NexusOperationCancellationType.ABANDON) + """Do not send any cancellation request to the operation handler; just report cancellation to the caller""" + + TRY_CANCEL = int( + temporalio.bridge.proto.nexus.NexusOperationCancellationType.TRY_CANCEL + ) + """Send a cancellation request but immediately report cancellation to the caller. Note that this + does not guarantee that cancellation is delivered to the operation handler if the caller exits + before the delivery is done. + """ + + WAIT_REQUESTED = int( + temporalio.bridge.proto.nexus.NexusOperationCancellationType.WAIT_CANCELLATION_REQUESTED + ) + """Send a cancellation request and wait for confirmation that the request was received. + Does not wait for the operation to complete. + """ + + WAIT_COMPLETED = int( + temporalio.bridge.proto.nexus.NexusOperationCancellationType.WAIT_CANCELLATION_COMPLETED + ) + """Send a cancellation request and wait for the operation to complete. + Note that the operation may not complete as cancelled (for example, if it catches the + :py:exc:`asyncio.CancelledError` resulting from the cancellation request).""" + + +class NexusClient(ABC, Generic[ServiceT]): + """A client for invoking Nexus operations. + + Example:: + + nexus_client = workflow.create_nexus_client( + endpoint=my_nexus_endpoint, + service=MyService, + ) + handle = await nexus_client.start_operation( + operation=MyService.my_operation, + input=MyOperationInput(value="hello"), + schedule_to_close_timeout=timedelta(seconds=10), + ) + result = await handle.result() + """ + + # Overload for nexusrpc.Operation + @overload + @abstractmethod + async def start_operation( + self, + operation: nexusrpc.Operation[InputT, OutputT], + input: InputT, + *, + output_type: type[OutputT] | None = None, + schedule_to_close_timeout: timedelta | None = None, + schedule_to_start_timeout: timedelta | None = None, + start_to_close_timeout: timedelta | None = None, + cancellation_type: NexusOperationCancellationType = NexusOperationCancellationType.WAIT_COMPLETED, + headers: Mapping[str, str] | None = None, + summary: str | None = None, + ) -> NexusOperationHandle[OutputT]: ... + + # Overload for string operation name + @overload + @abstractmethod + async def start_operation( + self, + operation: str, + input: Any, + *, + output_type: type[OutputT] | None = None, + schedule_to_close_timeout: timedelta | None = None, + schedule_to_start_timeout: timedelta | None = None, + start_to_close_timeout: timedelta | None = None, + cancellation_type: NexusOperationCancellationType = NexusOperationCancellationType.WAIT_COMPLETED, + headers: Mapping[str, str] | None = None, + summary: str | None = None, + ) -> NexusOperationHandle[OutputT]: ... + + # Overload for workflow_run_operation methods + @overload + @abstractmethod + async def start_operation( + self, + operation: Callable[ + [ServiceHandlerT, temporalio.nexus.WorkflowRunOperationContext, InputT], + Awaitable[temporalio.nexus.WorkflowHandle[OutputT]], + ], + input: InputT, + *, + output_type: type[OutputT] | None = None, + schedule_to_close_timeout: timedelta | None = None, + schedule_to_start_timeout: timedelta | None = None, + start_to_close_timeout: timedelta | None = None, + cancellation_type: NexusOperationCancellationType = NexusOperationCancellationType.WAIT_COMPLETED, + headers: Mapping[str, str] | None = None, + summary: str | None = None, + ) -> NexusOperationHandle[OutputT]: ... + + # Overload for sync_operation methods (async def) + @overload + @abstractmethod + async def start_operation( + self, + operation: Callable[ + [ServiceHandlerT, nexusrpc.handler.StartOperationContext, InputT], + Awaitable[OutputT], + ], + input: InputT, + *, + output_type: type[OutputT] | None = None, + schedule_to_close_timeout: timedelta | None = None, + schedule_to_start_timeout: timedelta | None = None, + start_to_close_timeout: timedelta | None = None, + cancellation_type: NexusOperationCancellationType = NexusOperationCancellationType.WAIT_COMPLETED, + headers: Mapping[str, str] | None = None, + summary: str | None = None, + ) -> NexusOperationHandle[OutputT]: ... + + # Overload for sync_operation methods (def) + @overload + @abstractmethod + async def start_operation( + self, + operation: Callable[ + [ServiceHandlerT, nexusrpc.handler.StartOperationContext, InputT], + OutputT, + ], + input: InputT, + *, + output_type: type[OutputT] | None = None, + schedule_to_close_timeout: timedelta | None = None, + schedule_to_start_timeout: timedelta | None = None, + start_to_close_timeout: timedelta | None = None, + cancellation_type: NexusOperationCancellationType = NexusOperationCancellationType.WAIT_COMPLETED, + headers: Mapping[str, str] | None = None, + summary: str | None = None, + ) -> NexusOperationHandle[OutputT]: ... + + # Overload for operation_handler + @overload + @abstractmethod + async def start_operation( + self, + operation: Callable[ + [ServiceHandlerT], nexusrpc.handler.OperationHandler[InputT, OutputT] + ], + input: InputT, + *, + output_type: type[OutputT] | None = None, + schedule_to_close_timeout: timedelta | None = None, + schedule_to_start_timeout: timedelta | None = None, + start_to_close_timeout: timedelta | None = None, + cancellation_type: NexusOperationCancellationType = NexusOperationCancellationType.WAIT_COMPLETED, + headers: Mapping[str, str] | None = None, + summary: str | None = None, + ) -> NexusOperationHandle[OutputT]: ... + + @abstractmethod + async def start_operation( + self, + operation: Any, + input: Any, + *, + output_type: type[OutputT] | None = None, + schedule_to_close_timeout: timedelta | None = None, + schedule_to_start_timeout: timedelta | None = None, + start_to_close_timeout: timedelta | None = None, + cancellation_type: NexusOperationCancellationType = NexusOperationCancellationType.WAIT_COMPLETED, + headers: Mapping[str, str] | None = None, + summary: str | None = None, + ) -> Any: + """Start a Nexus operation and return its handle. + + Args: + operation: The Nexus operation. + input: The Nexus operation input. + output_type: The Nexus operation output type. + schedule_to_close_timeout: Timeout for the entire operation attempt. + schedule_to_start_timeout: Timeout for the operation to be started. + start_to_close_timeout: Timeout for async operations to complete after starting. + headers: Headers to send with the Nexus HTTP request. + + Returns: + A handle to the Nexus operation. The result can be obtained as + ```python + await handle.result() + ``` + """ + ... + + # Overload for nexusrpc.Operation + @overload + @abstractmethod + async def execute_operation( + self, + operation: nexusrpc.Operation[InputT, OutputT], + input: InputT, + *, + output_type: type[OutputT] | None = None, + schedule_to_close_timeout: timedelta | None = None, + schedule_to_start_timeout: timedelta | None = None, + start_to_close_timeout: timedelta | None = None, + cancellation_type: NexusOperationCancellationType = NexusOperationCancellationType.WAIT_COMPLETED, + headers: Mapping[str, str] | None = None, + summary: str | None = None, + ) -> OutputT: ... + + # Overload for string operation name + @overload + @abstractmethod + async def execute_operation( + self, + operation: str, + input: Any, + *, + output_type: type[OutputT] | None = None, + schedule_to_close_timeout: timedelta | None = None, + schedule_to_start_timeout: timedelta | None = None, + start_to_close_timeout: timedelta | None = None, + cancellation_type: NexusOperationCancellationType = NexusOperationCancellationType.WAIT_COMPLETED, + headers: Mapping[str, str] | None = None, + summary: str | None = None, + ) -> OutputT: ... + + # Overload for workflow_run_operation methods + @overload + @abstractmethod + async def execute_operation( + self, + operation: Callable[ + [ServiceHandlerT, temporalio.nexus.WorkflowRunOperationContext, InputT], + Awaitable[temporalio.nexus.WorkflowHandle[OutputT]], + ], + input: InputT, + *, + output_type: type[OutputT] | None = None, + schedule_to_close_timeout: timedelta | None = None, + schedule_to_start_timeout: timedelta | None = None, + start_to_close_timeout: timedelta | None = None, + cancellation_type: NexusOperationCancellationType = NexusOperationCancellationType.WAIT_COMPLETED, + headers: Mapping[str, str] | None = None, + summary: str | None = None, + ) -> OutputT: ... + + # Overload for sync_operation methods (async def) + @overload + @abstractmethod + async def execute_operation( + self, + operation: Callable[ + [ServiceT, nexusrpc.handler.StartOperationContext, InputT], + Awaitable[OutputT], + ], + input: InputT, + *, + output_type: type[OutputT] | None = None, + schedule_to_close_timeout: timedelta | None = None, + schedule_to_start_timeout: timedelta | None = None, + start_to_close_timeout: timedelta | None = None, + cancellation_type: NexusOperationCancellationType = NexusOperationCancellationType.WAIT_COMPLETED, + headers: Mapping[str, str] | None = None, + summary: str | None = None, + ) -> OutputT: ... + + # Overload for sync_operation methods (def) + @overload + @abstractmethod + async def execute_operation( + self, + operation: Callable[ + [ServiceT, nexusrpc.handler.StartOperationContext, InputT], + OutputT, + ], + input: InputT, + *, + output_type: type[OutputT] | None = None, + schedule_to_close_timeout: timedelta | None = None, + schedule_to_start_timeout: timedelta | None = None, + start_to_close_timeout: timedelta | None = None, + cancellation_type: NexusOperationCancellationType = NexusOperationCancellationType.WAIT_COMPLETED, + headers: Mapping[str, str] | None = None, + summary: str | None = None, + ) -> OutputT: ... + + # Overload for operation_handler + @overload + @abstractmethod + async def execute_operation( + self, + operation: Callable[ + [ServiceT], + nexusrpc.handler.OperationHandler[InputT, OutputT], + ], + input: InputT, + *, + output_type: type[OutputT] | None = None, + schedule_to_close_timeout: timedelta | None = None, + schedule_to_start_timeout: timedelta | None = None, + start_to_close_timeout: timedelta | None = None, + cancellation_type: NexusOperationCancellationType = NexusOperationCancellationType.WAIT_COMPLETED, + headers: Mapping[str, str] | None = None, + summary: str | None = None, + ) -> OutputT: ... + + @abstractmethod + async def execute_operation( + self, + operation: Any, + input: Any, + *, + output_type: type[OutputT] | None = None, + schedule_to_close_timeout: timedelta | None = None, + schedule_to_start_timeout: timedelta | None = None, + start_to_close_timeout: timedelta | None = None, + cancellation_type: NexusOperationCancellationType = NexusOperationCancellationType.WAIT_COMPLETED, + headers: Mapping[str, str] | None = None, + summary: str | None = None, + ) -> Any: + """Execute a Nexus operation and return its result. + + Args: + operation: The Nexus operation. + input: The Nexus operation input. + output_type: The Nexus operation output type. + schedule_to_close_timeout: Timeout for the entire operation attempt. + schedule_to_start_timeout: Timeout for the operation to be started. + start_to_close_timeout: Timeout for async operations to complete after starting. + headers: Headers to send with the Nexus HTTP request. + + Returns: + The operation result. + """ + ... + + +class _NexusClient(NexusClient[ServiceT]): + def __init__( + self, + *, + endpoint: str, + service: type[ServiceT] | str, + ) -> None: + """Create a Nexus client. + + Args: + service: The Nexus service. + endpoint: The Nexus endpoint. + """ + # If service is not a str, then it must be a service interface or implementation + # class. + if isinstance(service, str): + self.service_name = service + elif service_defn := nexusrpc.get_service_definition(service): + self.service_name = service_defn.name + else: + raise ValueError( + f"`service` may be a name (str), or a class decorated with either " + f"@nexusrpc.handler.service_handler or @nexusrpc.service. " + f"Invalid service type: {type(service)}" + ) + self.endpoint = endpoint + + async def start_operation( + self, + operation: Any, + input: Any, + *, + output_type: type[OutputT] | None = None, + schedule_to_close_timeout: timedelta | None = None, + schedule_to_start_timeout: timedelta | None = None, + start_to_close_timeout: timedelta | None = None, + cancellation_type: NexusOperationCancellationType = NexusOperationCancellationType.WAIT_COMPLETED, + headers: Mapping[str, str] | None = None, + summary: str | None = None, + ) -> Any: + return await _Runtime.current().workflow_start_nexus_operation( + endpoint=self.endpoint, + service=self.service_name, + operation=operation, + input=input, + output_type=output_type, + schedule_to_close_timeout=schedule_to_close_timeout, + schedule_to_start_timeout=schedule_to_start_timeout, + start_to_close_timeout=start_to_close_timeout, + cancellation_type=cancellation_type, + headers=headers, + summary=summary, + ) + + async def execute_operation( + self, + operation: Any, + input: Any, + *, + output_type: type[OutputT] | None = None, + schedule_to_close_timeout: timedelta | None = None, + schedule_to_start_timeout: timedelta | None = None, + start_to_close_timeout: timedelta | None = None, + cancellation_type: NexusOperationCancellationType = NexusOperationCancellationType.WAIT_COMPLETED, + headers: Mapping[str, str] | None = None, + summary: str | None = None, + ) -> Any: + handle = await self.start_operation( + operation, + input, + output_type=output_type, + schedule_to_close_timeout=schedule_to_close_timeout, + schedule_to_start_timeout=schedule_to_start_timeout, + start_to_close_timeout=start_to_close_timeout, + cancellation_type=cancellation_type, + headers=headers, + summary=summary, + ) + return await handle + + +@overload +def create_nexus_client( + *, + service: type[ServiceT], + endpoint: str, +) -> NexusClient[ServiceT]: ... + + +@overload +def create_nexus_client( + *, + service: str, + endpoint: str, +) -> NexusClient[Any]: ... + + +def create_nexus_client( + *, + service: type[ServiceT] | str, + endpoint: str, +) -> NexusClient[ServiceT]: + """Create a Nexus client. + + Args: + service: The Nexus service. + endpoint: The Nexus endpoint. + """ + return _NexusClient(endpoint=endpoint, service=service) diff --git a/temporalio/workflow/_sandbox.py b/temporalio/workflow/_sandbox.py new file mode 100644 index 000000000..6f1d4569a --- /dev/null +++ b/temporalio/workflow/_sandbox.py @@ -0,0 +1,321 @@ +from __future__ import annotations + +import logging +import sys +import threading +from collections.abc import Iterator, Mapping, MutableMapping +from contextlib import contextmanager +from enum import Flag, auto +from typing import Any + +from ._context import Info, _Runtime, current_update_info + +__all__ = [ + "LoggerAdapter", + "SandboxImportNotificationPolicy", + "logger", + "unsafe", +] + +_sandbox_unrestricted = threading.local() +_in_sandbox = threading.local() +_imports_passed_through = threading.local() +_sandbox_import_notification_policy_override = threading.local() + + +class SandboxImportNotificationPolicy(Flag): + """Defines the behavior taken when modules are imported into the sandbox after the workflow is initially loaded or unintentionally missing from the passthrough list.""" + + SILENT = auto() + """Allow imports that do not violate sandbox restrictions and no warnings are generated.""" + WARN_ON_DYNAMIC_IMPORT = auto() + """Allows dynamic imports that do not violate sandbox restrictions but issues a warning when an import is triggered in the sandbox after initial workflow load.""" + WARN_ON_UNINTENTIONAL_PASSTHROUGH = auto() + """Allows imports that do not violate sandbox restrictions but issues a warning when an import is triggered in the sandbox that was unintentionally passed through.""" + RAISE_ON_UNINTENTIONAL_PASSTHROUGH = auto() + """Raise an error when an import is triggered in the sandbox that was unintentionally passed through.""" + + +class unsafe: + """Contains static methods that should not normally be called during + workflow execution except in advanced cases. + """ + + def __init__(self) -> None: # noqa: D107 + raise NotImplementedError + + @staticmethod + def in_sandbox() -> bool: + """Whether the code is executing on a sandboxed thread. + + Returns: + True if the code is executing in the sandbox thread. + """ + return getattr(_in_sandbox, "value", False) + + @staticmethod + def _set_in_sandbox(v: bool) -> None: + _in_sandbox.value = v + + @staticmethod + def is_replaying() -> bool: + """Whether the workflow is currently replaying. + + This includes queries and update validators that occur during replay. + + Returns: + True if the workflow is currently replaying + """ + return _Runtime.current().workflow_is_replaying() + + @staticmethod + def is_replaying_history_events() -> bool: + """Whether the workflow is replaying history events. + + This excludes queries and update validators, which are live operations. + + Returns: + True if replaying history events, False otherwise. + """ + return _Runtime.current().workflow_is_replaying_history_events() + + @staticmethod + def is_read_only() -> bool: + """Whether the workflow is currently in read-only mode. + + Read-only mode occurs during queries and update validators where + side effects are not allowed. + + Returns: + True if the workflow is in read-only mode, False otherwise. + """ + return _Runtime.current().workflow_is_read_only() + + @staticmethod + def is_sandbox_unrestricted() -> bool: + """Whether the current block of code is not restricted via sandbox. + + Returns: + True if the current code is not restricted in the sandbox. + """ + # Activations happen in different threads than init and possibly the + # local hasn't been initialized in _that_ thread, so we allow unset here + # instead of just setting value = False globally. + return getattr(_sandbox_unrestricted, "value", False) + + @staticmethod + @contextmanager + def sandbox_unrestricted() -> Iterator[None]: + """A context manager to run code without sandbox restrictions.""" + # Only apply if not already applied. Nested calls just continue + # unrestricted. + if unsafe.is_sandbox_unrestricted(): + yield None + return + _sandbox_unrestricted.value = True + try: + yield None + finally: + _sandbox_unrestricted.value = False + + @staticmethod + def is_imports_passed_through() -> bool: + """Whether the current block of code is in + :py:meth:imports_passed_through. + + Returns: + True if the current code's imports will be passed through + """ + # See comment in is_sandbox_unrestricted for why we allow unset instead + # of just global false. + return getattr(_imports_passed_through, "value", False) + + @staticmethod + @contextmanager + def imports_passed_through() -> Iterator[None]: + """Context manager to mark all imports that occur within it as passed + through (meaning not reloaded by the sandbox). + """ + # Only apply if not already applied. Nested calls just continue + # passed through. + if unsafe.is_imports_passed_through(): + yield None + return + _imports_passed_through.value = True + try: + yield None + finally: + _imports_passed_through.value = False + + @staticmethod + def current_import_notification_policy_override() -> ( + SandboxImportNotificationPolicy | None + ): + """Gets the current import notification policy override if one is set.""" + applied_policy = getattr( + _sandbox_import_notification_policy_override, + "value", + None, + ) + return applied_policy + + @staticmethod + @contextmanager + def sandbox_import_notification_policy( + policy: SandboxImportNotificationPolicy, + ) -> Iterator[None]: + """Context manager to apply the given import notification policy.""" + original_policy = _sandbox_import_notification_policy_override.value = getattr( + _sandbox_import_notification_policy_override, + "value", + None, + ) + _sandbox_import_notification_policy_override.value = policy + try: + yield None + finally: + _sandbox_import_notification_policy_override.value = original_policy + + +def _build_log_context( + workflow_details: Mapping[str, Any] | None, + update_details: Mapping[str, Any] | None = None, + *, + workflow_info_on_message: bool = True, + workflow_info_on_extra: bool = True, + full_workflow_info: Info | None = None, +) -> tuple[dict[str, Any], dict[str, Any]]: + """Build the msg_extra suffix and extra dict entries for a temporal log record. + + Returns: + (msg_extra, extra) where msg_extra should be appended to the log message + and extra should be merged into the log record's extra dict. + """ + msg_extra: dict[str, Any] = {} + extra: dict[str, Any] = {} + + if workflow_details is not None: + if workflow_info_on_message: + msg_extra.update(workflow_details) + if workflow_info_on_extra: + extra["temporal_workflow"] = dict(workflow_details) + + if update_details is not None: + if workflow_info_on_message: + msg_extra.update(update_details) + if workflow_info_on_extra: + extra.setdefault("temporal_workflow", {}).update(update_details) + + if full_workflow_info is not None: + extra["workflow_info"] = full_workflow_info + + return msg_extra, extra + + +class LoggerAdapter(logging.LoggerAdapter): + """Adapter that adds details to the log about the running workflow. + + Attributes: + workflow_info_on_message: Boolean for whether a string representation of + a dict of some workflow info will be appended to each message. + Default is True. + workflow_info_on_extra: Boolean for whether a ``temporal_workflow`` + dictionary value will be added to the ``extra`` dictionary with some + workflow info, making it present on the ``LogRecord.__dict__`` for + use by others. Default is True. + full_workflow_info_on_extra: Boolean for whether a ``workflow_info`` + value will be added to the ``extra`` dictionary with the entire + workflow info, making it present on the ``LogRecord.__dict__`` for + use by others. Default is False. + log_during_replay: Boolean for whether logs should occur during replay. + Default is False. + + Values added to ``extra`` are merged with the ``extra`` dictionary from a + logging call, with values from the logging call taking precedence. I.e. the + behavior is that of ``merge_extra=True`` in Python >= 3.13. + """ + + def __init__(self, logger: logging.Logger, extra: Mapping[str, Any] | None) -> None: + """Create the logger adapter.""" + super().__init__(logger, extra or {}) + self.workflow_info_on_message = True + self.workflow_info_on_extra = True + self.full_workflow_info_on_extra = False + self.log_during_replay = False + self.disable_sandbox = False + + def process( + self, msg: Any, kwargs: MutableMapping[str, Any] + ) -> tuple[Any, MutableMapping[str, Any]]: + """Override to add workflow details.""" + msg_extra: dict[str, Any] = {} + extra: dict[str, Any] = {} + + if ( + self.workflow_info_on_message + or self.workflow_info_on_extra + or self.full_workflow_info_on_extra + ): + runtime = _Runtime.maybe_current() + update_info = current_update_info() + msg_extra, extra = _build_log_context( + runtime.logger_details if runtime else None, + update_info._logger_details if update_info else None, + workflow_info_on_message=self.workflow_info_on_message, + workflow_info_on_extra=self.workflow_info_on_extra, + full_workflow_info=runtime.workflow_info() + if runtime and self.full_workflow_info_on_extra + else None, + ) + + kwargs["extra"] = {**extra, **(kwargs.get("extra") or {})} + if msg_extra: + msg = f"{msg} ({msg_extra})" + return msg, kwargs + + def log( + self, + level: int, + msg: object, + *args: Any, + stacklevel: int = 1, + **kwargs: Any, + ): + """Override to potentially disable the sandbox.""" + if sys.version_info < (3, 11) and stacklevel == 1: + # An additional stacklevel is needed on 3.10 because it doesn't skip internal frames until after stacklevel + # is decremented, so it needs an additional stacklevel to skip the internal frame. + stacklevel += 1 # type: ignore[reportUnreachable] + stacklevel += 1 + if self.disable_sandbox: + with unsafe.sandbox_unrestricted(): + with unsafe.imports_passed_through(): + super().log(level, msg, *args, stacklevel=stacklevel, **kwargs) + else: + super().log(level, msg, *args, stacklevel=stacklevel, **kwargs) + + def isEnabledFor(self, level: int) -> bool: + """Override to ignore replay logs.""" + if not self.log_during_replay and unsafe.is_replaying_history_events(): + return False + return super().isEnabledFor(level) + + @property + def base_logger(self) -> logging.Logger: + """Underlying logger usable for actions such as adding + handlers/formatters. + """ + return self.logger + + def unsafe_disable_sandbox(self, value: bool = True): + """Disable the sandbox during log processing. + Can be turned back on with unsafe_disable_sandbox(False). + """ + self.disable_sandbox = value + + +logger = LoggerAdapter(logging.getLogger("temporalio.workflow"), None) +"""Logger that will have contextual workflow details embedded. + +Logs are skipped during replay by default. +""" diff --git a/temporalio/workflow/_workflow_ops.py b/temporalio/workflow/_workflow_ops.py new file mode 100644 index 000000000..0cd22cb17 --- /dev/null +++ b/temporalio/workflow/_workflow_ops.py @@ -0,0 +1,1010 @@ +from __future__ import annotations + +from collections.abc import Awaitable, Callable, Mapping, Sequence +from datetime import timedelta +from enum import IntEnum +from typing import Any, Concatenate, Generic, NoReturn, TypedDict, overload + +import temporalio.bridge.proto.child_workflow +import temporalio.common + +from ..types import ( + MethodAsyncNoParam, + MethodAsyncSingleParam, + MethodSyncOrAsyncNoParam, + MethodSyncOrAsyncSingleParam, + MultiParamSpec, + ParamType, + ReturnType, + SelfType, +) +from ._activities import _AsyncioTask +from ._context import _Runtime, uuid4 +from ._exceptions import ContinueAsNewVersioningBehavior, VersioningIntent + +__all__ = [ + "ChildWorkflowCancellationType", + "ChildWorkflowConfig", + "ChildWorkflowHandle", + "ContinueAsNewError", + "ExternalWorkflowHandle", + "ParentClosePolicy", + "all_handlers_finished", + "continue_as_new", + "execute_child_workflow", + "get_dynamic_query_handler", + "get_dynamic_signal_handler", + "get_dynamic_update_handler", + "get_external_workflow_handle", + "get_external_workflow_handle_for", + "get_query_handler", + "get_signal_handler", + "get_update_handler", + "set_dynamic_query_handler", + "set_dynamic_signal_handler", + "set_dynamic_update_handler", + "set_query_handler", + "set_signal_handler", + "set_update_handler", + "start_child_workflow", +] + + +class ChildWorkflowHandle(_AsyncioTask[ReturnType], Generic[SelfType, ReturnType]): # type: ignore[type-var] + """Handle for interacting with a child workflow. + + This is created via :py:func:`start_child_workflow`. + + This extends :py:class:`asyncio.Task` and supports all task features. + """ + + @property + def id(self) -> str: + """ID for the workflow.""" + raise NotImplementedError + + @property + def first_execution_run_id(self) -> str | None: + """Run ID for the workflow.""" + raise NotImplementedError + + @overload + async def signal( + self, + signal: MethodSyncOrAsyncNoParam[SelfType, None], + ) -> None: ... + + @overload + async def signal( + self, + signal: MethodSyncOrAsyncSingleParam[SelfType, ParamType, None], + arg: ParamType, + ) -> None: ... + + @overload + async def signal( + self, + signal: Callable[Concatenate[SelfType, MultiParamSpec], Awaitable[None] | None], + *, + args: Sequence[Any], + ) -> None: ... + + @overload + async def signal( + self, + signal: str, + arg: Any = temporalio.common._arg_unset, + *, + args: Sequence[Any] = [], + ) -> None: ... + + async def signal( + self, + signal: str | Callable, # type: ignore[reportUnusedParameter] + arg: Any = temporalio.common._arg_unset, # type: ignore[reportUnusedParameter] + *, + args: Sequence[Any] = [], # type: ignore[reportUnusedParameter] + ) -> None: + """Signal this child workflow. + + Args: + signal: Name or method reference for the signal. + arg: Single argument to the signal. + args: Multiple arguments to the signal. Cannot be set if arg is. + + """ + raise NotImplementedError + + +class ChildWorkflowCancellationType(IntEnum): + """How a child workflow cancellation should be handled.""" + + ABANDON = int( + temporalio.bridge.proto.child_workflow.ChildWorkflowCancellationType.ABANDON + ) + TRY_CANCEL = int( + temporalio.bridge.proto.child_workflow.ChildWorkflowCancellationType.TRY_CANCEL + ) + WAIT_CANCELLATION_COMPLETED = int( + temporalio.bridge.proto.child_workflow.ChildWorkflowCancellationType.WAIT_CANCELLATION_COMPLETED + ) + WAIT_CANCELLATION_REQUESTED = int( + temporalio.bridge.proto.child_workflow.ChildWorkflowCancellationType.WAIT_CANCELLATION_REQUESTED + ) + + +class ParentClosePolicy(IntEnum): + """How a child workflow should be handled when the parent closes.""" + + UNSPECIFIED = int( + temporalio.bridge.proto.child_workflow.ParentClosePolicy.PARENT_CLOSE_POLICY_UNSPECIFIED + ) + TERMINATE = int( + temporalio.bridge.proto.child_workflow.ParentClosePolicy.PARENT_CLOSE_POLICY_TERMINATE + ) + ABANDON = int( + temporalio.bridge.proto.child_workflow.ParentClosePolicy.PARENT_CLOSE_POLICY_ABANDON + ) + REQUEST_CANCEL = int( + temporalio.bridge.proto.child_workflow.ParentClosePolicy.PARENT_CLOSE_POLICY_REQUEST_CANCEL + ) + + +class ChildWorkflowConfig(TypedDict, total=False): + """TypedDict of config that can be used for :py:func:`start_child_workflow` + and :py:func:`execute_child_workflow`. + """ + + id: str | None + task_queue: str | None + cancellation_type: ChildWorkflowCancellationType + parent_close_policy: ParentClosePolicy + execution_timeout: timedelta | None + run_timeout: timedelta | None + task_timeout: timedelta | None + id_reuse_policy: temporalio.common.WorkflowIDReusePolicy + retry_policy: temporalio.common.RetryPolicy | None + cron_schedule: str + memo: Mapping[str, Any] | None + search_attributes: None | ( + temporalio.common.SearchAttributes | temporalio.common.TypedSearchAttributes + ) + versioning_intent: VersioningIntent | None + static_summary: str | None + static_details: str | None + priority: temporalio.common.Priority + + +# Overload for no-param workflow +@overload +async def start_child_workflow( + workflow: MethodAsyncNoParam[SelfType, ReturnType], + *, + id: str | None = None, + task_queue: str | None = None, + cancellation_type: ChildWorkflowCancellationType = ChildWorkflowCancellationType.WAIT_CANCELLATION_COMPLETED, + parent_close_policy: ParentClosePolicy = ParentClosePolicy.TERMINATE, + execution_timeout: timedelta | None = None, + run_timeout: timedelta | None = None, + task_timeout: timedelta | None = None, + id_reuse_policy: temporalio.common.WorkflowIDReusePolicy = temporalio.common.WorkflowIDReusePolicy.ALLOW_DUPLICATE, + retry_policy: temporalio.common.RetryPolicy | None = None, + cron_schedule: str = "", + memo: Mapping[str, Any] | None = None, + search_attributes: None + | ( + temporalio.common.SearchAttributes | temporalio.common.TypedSearchAttributes + ) = None, + versioning_intent: VersioningIntent | None = None, + static_summary: str | None = None, + static_details: str | None = None, + priority: temporalio.common.Priority = temporalio.common.Priority.default, +) -> ChildWorkflowHandle[SelfType, ReturnType]: ... + + +# Overload for single-param workflow +@overload +async def start_child_workflow( + workflow: MethodAsyncSingleParam[SelfType, ParamType, ReturnType], + arg: ParamType, + *, + id: str | None = None, + task_queue: str | None = None, + cancellation_type: ChildWorkflowCancellationType = ChildWorkflowCancellationType.WAIT_CANCELLATION_COMPLETED, + parent_close_policy: ParentClosePolicy = ParentClosePolicy.TERMINATE, + execution_timeout: timedelta | None = None, + run_timeout: timedelta | None = None, + task_timeout: timedelta | None = None, + id_reuse_policy: temporalio.common.WorkflowIDReusePolicy = temporalio.common.WorkflowIDReusePolicy.ALLOW_DUPLICATE, + retry_policy: temporalio.common.RetryPolicy | None = None, + cron_schedule: str = "", + memo: Mapping[str, Any] | None = None, + search_attributes: None + | ( + temporalio.common.SearchAttributes | temporalio.common.TypedSearchAttributes + ) = None, + versioning_intent: VersioningIntent | None = None, + static_summary: str | None = None, + static_details: str | None = None, + priority: temporalio.common.Priority = temporalio.common.Priority.default, +) -> ChildWorkflowHandle[SelfType, ReturnType]: ... + + +# Overload for multi-param workflow +@overload +async def start_child_workflow( + workflow: Callable[Concatenate[SelfType, MultiParamSpec], Awaitable[ReturnType]], + *, + args: Sequence[Any], + id: str | None = None, + task_queue: str | None = None, + cancellation_type: ChildWorkflowCancellationType = ChildWorkflowCancellationType.WAIT_CANCELLATION_COMPLETED, + parent_close_policy: ParentClosePolicy = ParentClosePolicy.TERMINATE, + execution_timeout: timedelta | None = None, + run_timeout: timedelta | None = None, + task_timeout: timedelta | None = None, + id_reuse_policy: temporalio.common.WorkflowIDReusePolicy = temporalio.common.WorkflowIDReusePolicy.ALLOW_DUPLICATE, + retry_policy: temporalio.common.RetryPolicy | None = None, + cron_schedule: str = "", + memo: Mapping[str, Any] | None = None, + search_attributes: None + | ( + temporalio.common.SearchAttributes | temporalio.common.TypedSearchAttributes + ) = None, + versioning_intent: VersioningIntent | None = None, + static_summary: str | None = None, + static_details: str | None = None, + priority: temporalio.common.Priority = temporalio.common.Priority.default, +) -> ChildWorkflowHandle[SelfType, ReturnType]: ... + + +# Overload for string-name workflow +@overload +async def start_child_workflow( + workflow: str, + arg: Any = temporalio.common._arg_unset, + *, + args: Sequence[Any] = [], + id: str | None = None, + task_queue: str | None = None, + result_type: type | None = None, + cancellation_type: ChildWorkflowCancellationType = ChildWorkflowCancellationType.WAIT_CANCELLATION_COMPLETED, + parent_close_policy: ParentClosePolicy = ParentClosePolicy.TERMINATE, + execution_timeout: timedelta | None = None, + run_timeout: timedelta | None = None, + task_timeout: timedelta | None = None, + id_reuse_policy: temporalio.common.WorkflowIDReusePolicy = temporalio.common.WorkflowIDReusePolicy.ALLOW_DUPLICATE, + retry_policy: temporalio.common.RetryPolicy | None = None, + cron_schedule: str = "", + memo: Mapping[str, Any] | None = None, + search_attributes: None + | ( + temporalio.common.SearchAttributes | temporalio.common.TypedSearchAttributes + ) = None, + versioning_intent: VersioningIntent | None = None, + static_summary: str | None = None, + static_details: str | None = None, + priority: temporalio.common.Priority = temporalio.common.Priority.default, +) -> ChildWorkflowHandle[Any, Any]: ... + + +async def start_child_workflow( + workflow: Any, + arg: Any = temporalio.common._arg_unset, + *, + args: Sequence[Any] = [], + id: str | None = None, + task_queue: str | None = None, + result_type: type | None = None, + cancellation_type: ChildWorkflowCancellationType = ChildWorkflowCancellationType.WAIT_CANCELLATION_COMPLETED, + parent_close_policy: ParentClosePolicy = ParentClosePolicy.TERMINATE, + execution_timeout: timedelta | None = None, + run_timeout: timedelta | None = None, + task_timeout: timedelta | None = None, + id_reuse_policy: temporalio.common.WorkflowIDReusePolicy = temporalio.common.WorkflowIDReusePolicy.ALLOW_DUPLICATE, + retry_policy: temporalio.common.RetryPolicy | None = None, + cron_schedule: str = "", + memo: Mapping[str, Any] | None = None, + search_attributes: None + | ( + temporalio.common.SearchAttributes | temporalio.common.TypedSearchAttributes + ) = None, + versioning_intent: VersioningIntent | None = None, + static_summary: str | None = None, + static_details: str | None = None, + priority: temporalio.common.Priority = temporalio.common.Priority.default, +) -> ChildWorkflowHandle[Any, Any]: + """Start a child workflow and return its handle. + + Args: + workflow: String name or class method decorated with ``@workflow.run`` + for the workflow to start. + arg: Single argument to the child workflow. + args: Multiple arguments to the child workflow. Cannot be set if arg is. + id: Optional unique identifier for the workflow execution. If not set, + defaults to :py:func:`uuid4`. + task_queue: Task queue to run the workflow on. Defaults to the current + workflow's task queue. + result_type: For string workflows, this can set the specific result type + hint to deserialize into. + cancellation_type: How the child workflow will react to cancellation. + parent_close_policy: How to handle the child workflow when the parent + workflow closes. + execution_timeout: Total workflow execution timeout including + retries and continue as new. + run_timeout: Timeout of a single workflow run. + task_timeout: Timeout of a single workflow task. + id_reuse_policy: How already-existing IDs are treated. + retry_policy: Retry policy for the workflow. + cron_schedule: See https://docs.temporal.io/docs/content/what-is-a-temporal-cron-job/ + memo: Memo for the workflow. + search_attributes: Search attributes for the workflow. The dictionary + form of this is DEPRECATED. + versioning_intent: When using the Worker Versioning feature, specifies whether this Child + Workflow should run on a worker with a compatible Build Id or not. + Deprecated: Use Worker Deployment versioning instead. + static_summary: A single-line fixed summary for this child workflow execution that may appear + in the UI/CLI. This can be in single-line Temporal markdown format. + static_details: General fixed details for this child workflow execution that may appear in + UI/CLI. This can be in Temporal markdown format and can span multiple lines. This is + a fixed value on the workflow that cannot be updated. For details that can be + updated, use :py:meth:`get_current_details` within the workflow. + priority: Priority to use for this workflow. + + Returns: + A workflow handle to the started/existing workflow. + """ + temporalio.common._warn_on_deprecated_search_attributes(search_attributes) + return await _Runtime.current().workflow_start_child_workflow( + workflow, + *temporalio.common._arg_or_args(arg, args), + id=id or str(uuid4()), + task_queue=task_queue, + result_type=result_type, + cancellation_type=cancellation_type, + parent_close_policy=parent_close_policy, + execution_timeout=execution_timeout, + run_timeout=run_timeout, + task_timeout=task_timeout, + id_reuse_policy=id_reuse_policy, + retry_policy=retry_policy, + cron_schedule=cron_schedule, + memo=memo, + search_attributes=search_attributes, + versioning_intent=versioning_intent, + static_summary=static_summary, + static_details=static_details, + priority=priority, + ) + + +# Overload for no-param workflow +@overload +async def execute_child_workflow( + workflow: MethodAsyncNoParam[SelfType, ReturnType], + *, + id: str | None = None, + task_queue: str | None = None, + cancellation_type: ChildWorkflowCancellationType = ChildWorkflowCancellationType.WAIT_CANCELLATION_COMPLETED, + parent_close_policy: ParentClosePolicy = ParentClosePolicy.TERMINATE, + execution_timeout: timedelta | None = None, + run_timeout: timedelta | None = None, + task_timeout: timedelta | None = None, + id_reuse_policy: temporalio.common.WorkflowIDReusePolicy = temporalio.common.WorkflowIDReusePolicy.ALLOW_DUPLICATE, + retry_policy: temporalio.common.RetryPolicy | None = None, + cron_schedule: str = "", + memo: Mapping[str, Any] | None = None, + search_attributes: None + | ( + temporalio.common.SearchAttributes | temporalio.common.TypedSearchAttributes + ) = None, + versioning_intent: VersioningIntent | None = None, + static_summary: str | None = None, + static_details: str | None = None, + priority: temporalio.common.Priority = temporalio.common.Priority.default, +) -> ReturnType: ... + + +# Overload for single-param workflow +@overload +async def execute_child_workflow( + workflow: MethodAsyncSingleParam[SelfType, ParamType, ReturnType], + arg: ParamType, + *, + id: str | None = None, + task_queue: str | None = None, + cancellation_type: ChildWorkflowCancellationType = ChildWorkflowCancellationType.WAIT_CANCELLATION_COMPLETED, + parent_close_policy: ParentClosePolicy = ParentClosePolicy.TERMINATE, + execution_timeout: timedelta | None = None, + run_timeout: timedelta | None = None, + task_timeout: timedelta | None = None, + id_reuse_policy: temporalio.common.WorkflowIDReusePolicy = temporalio.common.WorkflowIDReusePolicy.ALLOW_DUPLICATE, + retry_policy: temporalio.common.RetryPolicy | None = None, + cron_schedule: str = "", + memo: Mapping[str, Any] | None = None, + search_attributes: None + | ( + temporalio.common.SearchAttributes | temporalio.common.TypedSearchAttributes + ) = None, + versioning_intent: VersioningIntent | None = None, + static_summary: str | None = None, + static_details: str | None = None, + priority: temporalio.common.Priority = temporalio.common.Priority.default, +) -> ReturnType: ... + + +# Overload for multi-param workflow +@overload +async def execute_child_workflow( + workflow: Callable[Concatenate[SelfType, MultiParamSpec], Awaitable[ReturnType]], + *, + args: Sequence[Any], + id: str | None = None, + task_queue: str | None = None, + cancellation_type: ChildWorkflowCancellationType = ChildWorkflowCancellationType.WAIT_CANCELLATION_COMPLETED, + parent_close_policy: ParentClosePolicy = ParentClosePolicy.TERMINATE, + execution_timeout: timedelta | None = None, + run_timeout: timedelta | None = None, + task_timeout: timedelta | None = None, + id_reuse_policy: temporalio.common.WorkflowIDReusePolicy = temporalio.common.WorkflowIDReusePolicy.ALLOW_DUPLICATE, + retry_policy: temporalio.common.RetryPolicy | None = None, + cron_schedule: str = "", + memo: Mapping[str, Any] | None = None, + search_attributes: None + | ( + temporalio.common.SearchAttributes | temporalio.common.TypedSearchAttributes + ) = None, + versioning_intent: VersioningIntent | None = None, + static_summary: str | None = None, + static_details: str | None = None, + priority: temporalio.common.Priority = temporalio.common.Priority.default, +) -> ReturnType: ... + + +# Overload for string-name workflow +@overload +async def execute_child_workflow( + workflow: str, + arg: Any = temporalio.common._arg_unset, + *, + args: Sequence[Any] = [], + id: str | None = None, + task_queue: str | None = None, + result_type: type | None = None, + cancellation_type: ChildWorkflowCancellationType = ChildWorkflowCancellationType.WAIT_CANCELLATION_COMPLETED, + parent_close_policy: ParentClosePolicy = ParentClosePolicy.TERMINATE, + execution_timeout: timedelta | None = None, + run_timeout: timedelta | None = None, + task_timeout: timedelta | None = None, + id_reuse_policy: temporalio.common.WorkflowIDReusePolicy = temporalio.common.WorkflowIDReusePolicy.ALLOW_DUPLICATE, + retry_policy: temporalio.common.RetryPolicy | None = None, + cron_schedule: str = "", + memo: Mapping[str, Any] | None = None, + search_attributes: None + | ( + temporalio.common.SearchAttributes | temporalio.common.TypedSearchAttributes + ) = None, + versioning_intent: VersioningIntent | None = None, + static_summary: str | None = None, + static_details: str | None = None, + priority: temporalio.common.Priority = temporalio.common.Priority.default, +) -> Any: ... + + +async def execute_child_workflow( + workflow: Any, + arg: Any = temporalio.common._arg_unset, + *, + args: Sequence[Any] = [], + id: str | None = None, + task_queue: str | None = None, + result_type: type | None = None, + cancellation_type: ChildWorkflowCancellationType = ChildWorkflowCancellationType.WAIT_CANCELLATION_COMPLETED, + parent_close_policy: ParentClosePolicy = ParentClosePolicy.TERMINATE, + execution_timeout: timedelta | None = None, + run_timeout: timedelta | None = None, + task_timeout: timedelta | None = None, + id_reuse_policy: temporalio.common.WorkflowIDReusePolicy = temporalio.common.WorkflowIDReusePolicy.ALLOW_DUPLICATE, + retry_policy: temporalio.common.RetryPolicy | None = None, + cron_schedule: str = "", + memo: Mapping[str, Any] | None = None, + search_attributes: None + | ( + temporalio.common.SearchAttributes | temporalio.common.TypedSearchAttributes + ) = None, + versioning_intent: VersioningIntent | None = None, + static_summary: str | None = None, + static_details: str | None = None, + priority: temporalio.common.Priority = temporalio.common.Priority.default, +) -> Any: + """Start a child workflow and wait for completion. + + This is a shortcut for ``await (await`` :py:meth:`start_child_workflow` ``)``. + """ + temporalio.common._warn_on_deprecated_search_attributes(search_attributes) + # We call the runtime directly instead of top-level start_child_workflow to + # ensure we don't miss new parameters + handle = await _Runtime.current().workflow_start_child_workflow( + workflow, + *temporalio.common._arg_or_args(arg, args), + id=id or str(uuid4()), + task_queue=task_queue, + result_type=result_type, + cancellation_type=cancellation_type, + parent_close_policy=parent_close_policy, + execution_timeout=execution_timeout, + run_timeout=run_timeout, + task_timeout=task_timeout, + id_reuse_policy=id_reuse_policy, + retry_policy=retry_policy, + cron_schedule=cron_schedule, + memo=memo, + search_attributes=search_attributes, + versioning_intent=versioning_intent, + static_summary=static_summary, + static_details=static_details, + priority=priority, + ) + return await handle + + +class ExternalWorkflowHandle(Generic[SelfType]): + """Handle for interacting with an external workflow. + + This is created via :py:func:`get_external_workflow_handle` or + :py:func:`get_external_workflow_handle_for`. + """ + + @property + def id(self) -> str: + """ID for the workflow.""" + raise NotImplementedError + + @property + def run_id(self) -> str | None: + """Run ID for the workflow if any.""" + raise NotImplementedError + + @overload + async def signal( + self, + signal: MethodSyncOrAsyncNoParam[SelfType, None], + ) -> None: ... + + @overload + async def signal( + self, + signal: MethodSyncOrAsyncSingleParam[SelfType, ParamType, None], + arg: ParamType, + ) -> None: ... + + @overload + async def signal( + self, + signal: str, + arg: Any = temporalio.common._arg_unset, + *, + args: Sequence[Any] = [], + ) -> None: ... + + async def signal( + self, + signal: str | Callable, # type: ignore[reportUnusedParameter] + arg: Any = temporalio.common._arg_unset, # type: ignore[reportUnusedParameter] + *, + args: Sequence[Any] = [], # type: ignore[reportUnusedParameter] + ) -> None: + """Signal this external workflow. + + Args: + signal: Name or method reference for the signal. + arg: Single argument to the signal. + args: Multiple arguments to the signal. Cannot be set if arg is. + + """ + raise NotImplementedError + + async def cancel(self) -> None: + """Send a cancellation request to this external workflow. + + This will fail if the workflow cannot accept the request (e.g. if the + workflow is not found). + """ + raise NotImplementedError + + +def get_external_workflow_handle( + workflow_id: str, + *, + run_id: str | None = None, +) -> ExternalWorkflowHandle[Any]: + """Get a workflow handle to an existing workflow by its ID. + + Args: + workflow_id: Workflow ID to get a handle to. + run_id: Optional run ID for the workflow. + + Returns: + The external workflow handle. + """ + return _Runtime.current().workflow_get_external_workflow_handle( + workflow_id, run_id=run_id + ) + + +def get_external_workflow_handle_for( + workflow: MethodAsyncNoParam[SelfType, Any] # type: ignore[reportUnusedParameter] + | MethodAsyncSingleParam[SelfType, Any, Any], + workflow_id: str, + *, + run_id: str | None = None, +) -> ExternalWorkflowHandle[SelfType]: + """Get a typed workflow handle to an existing workflow by its ID. + + This is the same as :py:func:`get_external_workflow_handle` but typed. Note, + the workflow type given is not validated, it is only for typing. + + Args: + workflow: The workflow run method to use for typing the handle. + workflow_id: Workflow ID to get a handle to. + run_id: Optional run ID for the workflow. + + Returns: + The external workflow handle. + """ + return get_external_workflow_handle(workflow_id, run_id=run_id) + + +class ContinueAsNewError(BaseException): + """Error thrown by :py:func:`continue_as_new`. + + This should not be caught, but instead be allowed to throw out of the + workflow which then triggers the continue as new. This should never be + instantiated directly. + """ + + def __init__(self, *args: object) -> None: + """Direct instantiation is disabled. Use :py:func:`continue_as_new`.""" + if type(self) is ContinueAsNewError: + raise RuntimeError("Cannot instantiate ContinueAsNewError directly") + super().__init__(*args) + + +# Overload for self (unfortunately, cannot type args) +@overload +def continue_as_new( + arg: Any = temporalio.common._arg_unset, + *, + args: Sequence[Any] = [], + task_queue: str | None = None, + run_timeout: timedelta | None = None, + task_timeout: timedelta | None = None, + retry_policy: temporalio.common.RetryPolicy | None = None, + memo: Mapping[str, Any] | None = None, + search_attributes: None + | ( + temporalio.common.SearchAttributes | temporalio.common.TypedSearchAttributes + ) = None, + versioning_intent: VersioningIntent | None = None, + initial_versioning_behavior: ContinueAsNewVersioningBehavior | None = None, +) -> NoReturn: ... + + +# Overload for no-param workflow +@overload +def continue_as_new( + *, + workflow: MethodAsyncNoParam[SelfType, Any], + task_queue: str | None = None, + run_timeout: timedelta | None = None, + task_timeout: timedelta | None = None, + retry_policy: temporalio.common.RetryPolicy | None = None, + memo: Mapping[str, Any] | None = None, + search_attributes: None + | ( + temporalio.common.SearchAttributes | temporalio.common.TypedSearchAttributes + ) = None, + versioning_intent: VersioningIntent | None = None, + initial_versioning_behavior: ContinueAsNewVersioningBehavior | None = None, +) -> NoReturn: ... + + +# Overload for single-param workflow +@overload +def continue_as_new( + arg: ParamType, + *, + workflow: MethodAsyncSingleParam[SelfType, ParamType, Any], + task_queue: str | None = None, + run_timeout: timedelta | None = None, + task_timeout: timedelta | None = None, + retry_policy: temporalio.common.RetryPolicy | None = None, + memo: Mapping[str, Any] | None = None, + search_attributes: None + | ( + temporalio.common.SearchAttributes | temporalio.common.TypedSearchAttributes + ) = None, + versioning_intent: VersioningIntent | None = None, + initial_versioning_behavior: ContinueAsNewVersioningBehavior | None = None, +) -> NoReturn: ... + + +# Overload for multi-param workflow +@overload +def continue_as_new( + *, + workflow: Callable[Concatenate[SelfType, MultiParamSpec], Awaitable[Any]], + args: Sequence[Any], + task_queue: str | None = None, + run_timeout: timedelta | None = None, + task_timeout: timedelta | None = None, + retry_policy: temporalio.common.RetryPolicy | None = None, + memo: Mapping[str, Any] | None = None, + search_attributes: None + | ( + temporalio.common.SearchAttributes | temporalio.common.TypedSearchAttributes + ) = None, + versioning_intent: VersioningIntent | None = None, + initial_versioning_behavior: ContinueAsNewVersioningBehavior | None = None, +) -> NoReturn: ... + + +# Overload for string-name workflow +@overload +def continue_as_new( + *, + workflow: str, + args: Sequence[Any] = [], + task_queue: str | None = None, + run_timeout: timedelta | None = None, + task_timeout: timedelta | None = None, + retry_policy: temporalio.common.RetryPolicy | None = None, + memo: Mapping[str, Any] | None = None, + search_attributes: None + | ( + temporalio.common.SearchAttributes | temporalio.common.TypedSearchAttributes + ) = None, + versioning_intent: VersioningIntent | None = None, + initial_versioning_behavior: ContinueAsNewVersioningBehavior | None = None, +) -> NoReturn: ... + + +def continue_as_new( + arg: Any = temporalio.common._arg_unset, + *, + args: Sequence[Any] = [], + workflow: None | Callable | str = None, + task_queue: str | None = None, + run_timeout: timedelta | None = None, + task_timeout: timedelta | None = None, + retry_policy: temporalio.common.RetryPolicy | None = None, + memo: Mapping[str, Any] | None = None, + search_attributes: None + | ( + temporalio.common.SearchAttributes | temporalio.common.TypedSearchAttributes + ) = None, + versioning_intent: VersioningIntent | None = None, + initial_versioning_behavior: ContinueAsNewVersioningBehavior | None = None, +) -> NoReturn: + """Stop the workflow immediately and continue as new. + + Args: + arg: Single argument to the continued workflow. + args: Multiple arguments to the continued workflow. Cannot be set if arg + is. + workflow: Specific workflow to continue to. Defaults to the current + workflow. + task_queue: Task queue to run the workflow on. Defaults to the current + workflow's task queue. + run_timeout: Timeout of a single workflow run. Defaults to the current + workflow's run timeout. + task_timeout: Timeout of a single workflow task. Defaults to the current + workflow's task timeout. + memo: Memo for the workflow. Defaults to the current workflow's memo. + search_attributes: Search attributes for the workflow. Defaults to the + current workflow's search attributes. The dictionary form of this is + DEPRECATED. + versioning_intent: When using the Worker Versioning feature, specifies whether this Workflow + should Continue-as-New onto a worker with a compatible Build Id or not. + Deprecated: Use Worker Deployment versioning instead. + + Returns: + Never returns, always raises a :py:class:`ContinueAsNewError`. + + Raises: + ContinueAsNewError: Always raised by this function. Should not be caught + but instead be allowed to + """ + temporalio.common._warn_on_deprecated_search_attributes(search_attributes) + _Runtime.current().workflow_continue_as_new( + *temporalio.common._arg_or_args(arg, args), + workflow=workflow, + task_queue=task_queue, + run_timeout=run_timeout, + task_timeout=task_timeout, + retry_policy=retry_policy, + memo=memo, + search_attributes=search_attributes, + versioning_intent=versioning_intent, + initial_versioning_behavior=initial_versioning_behavior, + ) + + +def get_signal_handler(name: str) -> Callable | None: + """Get the signal handler for the given name if any. + + This includes handlers created via the ``@workflow.signal`` decorator. + + Args: + name: Name of the signal. + + Returns: + Callable for the signal if any. If a handler is not found for the name, + this will not return the dynamic handler even if there is one. + """ + return _Runtime.current().workflow_get_signal_handler(name) + + +def set_signal_handler(name: str, handler: Callable | None) -> None: + """Set or unset the signal handler for the given name. + + This overrides any existing handlers for the given name, including handlers + created via the ``@workflow.signal`` decorator. + + When set, all unhandled past signals for the given name are immediately sent + to the handler. + + Args: + name: Name of the signal. + handler: Callable to set or None to unset. + """ + _Runtime.current().workflow_set_signal_handler(name, handler) + + +def get_dynamic_signal_handler() -> Callable | None: + """Get the dynamic signal handler if any. + + This includes dynamic handlers created via the ``@workflow.signal`` + decorator. + + Returns: + Callable for the dynamic signal handler if any. + """ + return _Runtime.current().workflow_get_signal_handler(None) + + +def set_dynamic_signal_handler(handler: Callable | None) -> None: + """Set or unset the dynamic signal handler. + + This overrides the existing dynamic handler even if it was created via the + ``@workflow.signal`` decorator. + + When set, all unhandled past signals are immediately sent to the handler. + + Args: + handler: Callable to set or None to unset. + """ + _Runtime.current().workflow_set_signal_handler(None, handler) + + +def get_query_handler(name: str) -> Callable | None: + """Get the query handler for the given name if any. + + This includes handlers created via the ``@workflow.query`` decorator. + + Args: + name: Name of the query. + + Returns: + Callable for the query if any. If a handler is not found for the name, + this will not return the dynamic handler even if there is one. + """ + return _Runtime.current().workflow_get_query_handler(name) + + +def set_query_handler(name: str, handler: Callable | None) -> None: + """Set or unset the query handler for the given name. + + This overrides any existing handlers for the given name, including handlers + created via the ``@workflow.query`` decorator. + + Args: + name: Name of the query. + handler: Callable to set or None to unset. + """ + _Runtime.current().workflow_set_query_handler(name, handler) + + +def get_dynamic_query_handler() -> Callable | None: + """Get the dynamic query handler if any. + + This includes dynamic handlers created via the ``@workflow.query`` + decorator. + + Returns: + Callable for the dynamic query handler if any. + """ + return _Runtime.current().workflow_get_query_handler(None) + + +def set_dynamic_query_handler(handler: Callable | None) -> None: + """Set or unset the dynamic query handler. + + This overrides the existing dynamic handler even if it was created via the + ``@workflow.query`` decorator. + + Args: + handler: Callable to set or None to unset. + """ + _Runtime.current().workflow_set_query_handler(None, handler) + + +def get_update_handler(name: str) -> Callable | None: + """Get the update handler for the given name if any. + + This includes handlers created via the ``@workflow.update`` decorator. + + Args: + name: Name of the update. + + Returns: + Callable for the update if any. If a handler is not found for the name, + this will not return the dynamic handler even if there is one. + """ + return _Runtime.current().workflow_get_update_handler(name) + + +def set_update_handler( + name: str, handler: Callable | None, *, validator: Callable | None = None +) -> None: + """Set or unset the update handler for the given name. + + This overrides any existing handlers for the given name, including handlers + created via the ``@workflow.update`` decorator. + + Args: + name: Name of the update. + handler: Callable to set or None to unset. + validator: Callable to set or None to unset as the update validator. + """ + _Runtime.current().workflow_set_update_handler(name, handler, validator) + + +def get_dynamic_update_handler() -> Callable | None: + """Get the dynamic update handler if any. + + This includes dynamic handlers created via the ``@workflow.update`` + decorator. + + Returns: + Callable for the dynamic update handler if any. + """ + return _Runtime.current().workflow_get_update_handler(None) + + +def set_dynamic_update_handler( + handler: Callable | None, *, validator: Callable | None = None +) -> None: + """Set or unset the dynamic update handler. + + This overrides the existing dynamic handler even if it was created via the + ``@workflow.update`` decorator. + + Args: + handler: Callable to set or None to unset. + validator: Callable to set or None to unset as the update validator. + """ + _Runtime.current().workflow_set_update_handler(None, handler, validator) + + +def all_handlers_finished() -> bool: + """Whether update and signal handlers have finished executing. + + Consider waiting on this condition before workflow return or continue-as-new, to prevent + interruption of in-progress handlers by workflow exit: + ``await workflow.wait_condition(lambda: workflow.all_handlers_finished())`` + + Returns: + True if there are no in-progress update or signal handler executions. + """ + return _Runtime.current().workflow_all_handlers_finished() diff --git a/tests/test_workflow_exports.py b/tests/test_workflow_exports.py new file mode 100644 index 000000000..5beee5c61 --- /dev/null +++ b/tests/test_workflow_exports.py @@ -0,0 +1,219 @@ +import temporalio.workflow + +# Generated from temporalio.workflow on main +EXPECTED_WORKFLOW_EXPORTS = [ + "ActivityCancellationType", + "ActivityConfig", + "ActivityHandle", + "AnyType", + "CallableAsyncNoParam", + "CallableAsyncSingleParam", + "CallableAsyncType", + "CallableSyncNoParam", + "CallableSyncOrAsyncReturnNoneType", + "CallableSyncOrAsyncType", + "CallableSyncSingleParam", + "CallableType", + "ChildWorkflowCancellationType", + "ChildWorkflowConfig", + "ChildWorkflowHandle", + "ClassType", + "ContinueAsNewError", + "ContinueAsNewVersioningBehavior", + "DynamicWorkflowConfig", + "ExternalWorkflowHandle", + "HandlerUnfinishedPolicy", + "Info", + "LocalActivityConfig", + "LoggerAdapter", + "MethodAsyncNoParam", + "MethodAsyncSingleParam", + "MethodSyncNoParam", + "MethodSyncOrAsyncNoParam", + "MethodSyncOrAsyncSingleParam", + "MethodSyncSingleParam", + "MultiParamSpec", + "NexusClient", + "NexusOperationCancellationType", + "NexusOperationHandle", + "NondeterminismError", + "ParamType", + "ParentClosePolicy", + "ParentInfo", + "ProtocolReturnType", + "ReadOnlyContextError", + "ReturnType", + "RootInfo", + "SandboxImportNotificationPolicy", + "SelfType", + "ServiceHandlerT", + "ServiceT", + "UnfinishedSignalHandlersWarning", + "UnfinishedUpdateHandlersWarning", + "UpdateInfo", + "UpdateMethodMultiParam", + "VersioningIntent", + "_AsyncioTask", + "_Definition", + "_FT", + "_NexusClient", + "_NotInWorkflowEventLoopError", + "_QueryDefinition", + "_Runtime", + "_SignalDefinition", + "_UpdateDefinition", + "_assert_dynamic_handler_args", + "_bind_method", + "_build_log_context", + "_current_update_info", + "_imports_passed_through", + "_in_sandbox", + "_is_unbound_method_on_cls", + "_parameters_identical_up_to_naming", + "_release_waiter", + "_sandbox_import_notification_policy_override", + "_sandbox_unrestricted", + "_set_current_update_info", + "_update_validator", + "_wait", + "all_handlers_finished", + "annotations", + "as_completed", + "continue_as_new", + "create_nexus_client", + "current_update_info", + "defn", + "deprecate_patch", + "dynamic_config", + "execute_activity", + "execute_activity_class", + "execute_activity_method", + "execute_child_workflow", + "execute_local_activity", + "execute_local_activity_class", + "execute_local_activity_method", + "extern_functions", + "get_current_details", + "get_dynamic_query_handler", + "get_dynamic_signal_handler", + "get_dynamic_update_handler", + "get_external_workflow_handle", + "get_external_workflow_handle_for", + "get_last_completion_result", + "get_last_failure", + "get_query_handler", + "get_signal_handler", + "get_update_handler", + "has_last_completion_result", + "in_workflow", + "info", + "init", + "instance", + "is_failure_exception", + "logger", + "memo", + "memo_value", + "metric_meter", + "new_random", + "now", + "patched", + "payload_converter", + "query", + "random", + "random_seed", + "register_random_seed_callback", + "run", + "set_current_details", + "set_dynamic_query_handler", + "set_dynamic_signal_handler", + "set_dynamic_update_handler", + "set_query_handler", + "set_signal_handler", + "set_update_handler", + "signal", + "sleep", + "start_activity", + "start_activity_class", + "start_activity_method", + "start_child_workflow", + "start_local_activity", + "start_local_activity_class", + "start_local_activity_method", + "time", + "time_ns", + "unsafe", + "update", + "upsert_memo", + "upsert_search_attributes", + "uuid4", + "wait", + "wait_condition", +] + + +EXPECTED_INTENTIONALLY_REMOVED_WORKFLOW_EXPORTS = [ + "ABC", + "Any", + "Awaitable", + "Callable", + "Concatenate", + "Enum", + "Flag", + "Generator", + "Generic", + "InputT", + "IntEnum", + "Iterable", + "Iterator", + "Literal", + "Mapping", + "MutableMapping", + "NoReturn", + "OutputT", + "Protocol", + "Random", + "Sequence", + "TYPE_CHECKING", + "TypeVar", + "TypedDict", + "abstractmethod", + "asyncio", + "auto", + "cast", + "contextmanager", + "contextvars", + "dataclass", + "datetime", + "inspect", + "logging", + "nexusrpc", + "overload", + "partial", + "runtime_checkable", + "sys", + "temporalio", + "threading", + "timedelta", + "timezone", + "typing", + "uuid", + "warnings", +] + + +def test_workflow_module_exports_match_main() -> None: + missing = [ + name + for name in EXPECTED_WORKFLOW_EXPORTS + if not hasattr(temporalio.workflow, name) + ] + assert not missing + + +def test_workflow_module_drops_intentionally_removed_import_exports() -> None: + exported = [ + name + for name in EXPECTED_INTENTIONALLY_REMOVED_WORKFLOW_EXPORTS + if hasattr(temporalio.workflow, name) + ] + assert not exported From 91da1edbcc22bd6f4d13b0bdbb52e0bf10e004d9 Mon Sep 17 00:00:00 2001 From: Brian Strauch Date: Mon, 18 May 2026 14:33:06 -0700 Subject: [PATCH 094/226] Fix documentation link for Workflow Streams (#1536) Updated the link to the Workflow Streams documentation for the Python SDK. --- temporalio/contrib/workflow_streams/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/temporalio/contrib/workflow_streams/README.md b/temporalio/contrib/workflow_streams/README.md index ba5582e52..2fb4f9485 100644 --- a/temporalio/contrib/workflow_streams/README.md +++ b/temporalio/contrib/workflow_streams/README.md @@ -22,7 +22,7 @@ that hand stream state across Workflow runs. ## Documentation 📖 **The full guide lives in the Temporal documentation site:** -**[Workflow Streams — Python SDK](https://docs.temporal.io/develop/python/libraries/workflow-streams)** +**[Workflow Streams — Python SDK](https://docs.temporal.io/develop/python/workflows/workflow-streams)** It covers installation, enabling streaming on a Workflow, publishing from Workflows and Activities, subscribing, continue-as-new, delivery semantics, From 75dd80a4e4389004bc2a15152f93f9b75242ab97 Mon Sep 17 00:00:00 2001 From: Edward Amsden Date: Mon, 18 May 2026 17:26:29 -0500 Subject: [PATCH 095/226] Integration test for Standalone Activities delayed-start (#1520) * Integration test for Standalone Activities delayed-start * Bump server version, and de-flake delay assertion. * CI debugging * Remove debugging and warm server download in CI * Fix `test_workflow_caller_cancellation_types_when_cancel_handler_fails` flaking * Remove server download warming --- .github/workflows/ci.yml | 4 -- tests/__init__.py | 2 +- tests/conftest.py | 2 + ...test_workflow_caller_cancellation_types.py | 47 +++++++++++++++---- ...llation_types_when_cancel_handler_fails.py | 40 ++++++++++++++-- tests/test_activity.py | 32 +++++++++++++ 6 files changed, 108 insertions(+), 19 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 59282e249..6294f6d9a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -46,7 +46,6 @@ jobs: components: "clippy" - uses: Swatinem/rust-cache@e18b497796c12c097a38f9edb9d0641fb99eee32 # v2 with: - cache-bin: false workspaces: temporalio/bridge -> target - uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5 with: @@ -112,7 +111,6 @@ jobs: - uses: dtolnay/rust-toolchain@29eef336d9b2848a0b548edc03f92a220660cdb8 # stable - uses: Swatinem/rust-cache@e18b497796c12c097a38f9edb9d0641fb99eee32 # v2 with: - cache-bin: false workspaces: temporalio/bridge -> target - uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5 with: @@ -149,7 +147,6 @@ jobs: components: "clippy" - uses: Swatinem/rust-cache@e18b497796c12c097a38f9edb9d0641fb99eee32 # v2 with: - cache-bin: false workspaces: temporalio/bridge -> target - uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5 with: @@ -188,7 +185,6 @@ jobs: - uses: dtolnay/rust-toolchain@29eef336d9b2848a0b548edc03f92a220660cdb8 # stable - uses: Swatinem/rust-cache@e18b497796c12c097a38f9edb9d0641fb99eee32 # v2 with: - cache-bin: false workspaces: temporalio/bridge -> target - uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5 with: diff --git a/tests/__init__.py b/tests/__init__.py index 86e6edb54..d62129b39 100644 --- a/tests/__init__.py +++ b/tests/__init__.py @@ -1 +1 @@ -DEV_SERVER_DOWNLOAD_VERSION = "v1.7.0" +DEV_SERVER_DOWNLOAD_VERSION = "v1.7.1-standalone-nexus-operations" diff --git a/tests/conftest.py b/tests/conftest.py index 48d5f0669..999f19b1e 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -123,6 +123,8 @@ async def env(env_type: str) -> AsyncGenerator[WorkflowEnvironment, None]: "--dynamic-config-value", "activity.enableStandalone=true", "--dynamic-config-value", + "activity.startDelayEnabled=true", + "--dynamic-config-value", "history.enableChasm=true", "--dynamic-config-value", "history.enableTransitionHistory=true", diff --git a/tests/nexus/test_workflow_caller_cancellation_types.py b/tests/nexus/test_workflow_caller_cancellation_types.py index 6ebba5759..59a989d34 100644 --- a/tests/nexus/test_workflow_caller_cancellation_types.py +++ b/tests/nexus/test_workflow_caller_cancellation_types.py @@ -20,6 +20,7 @@ from temporalio.common import WorkflowIDConflictPolicy from temporalio.testing import WorkflowEnvironment from temporalio.worker import Worker +from tests.helpers import assert_eventually from tests.helpers.nexus import make_nexus_endpoint_name @@ -40,12 +41,15 @@ class TestContext: class HandlerWorkflow: def __init__(self): self.caller_op_future_resolved = asyncio.Event() + self.cancel_requested = False + self.release_cancellation = asyncio.Event() @workflow.run async def run(self) -> None: try: await asyncio.Future() except asyncio.CancelledError: + self.cancel_requested = True if test_context.cancellation_type in [ workflow.NexusOperationCancellationType.TRY_CANCEL, workflow.NexusOperationCancellationType.WAIT_REQUESTED, @@ -53,12 +57,25 @@ async def run(self) -> None: # We want to prove that the caller op future can be resolved before the operation # (i.e. its backing workflow) is cancelled. await self.caller_op_future_resolved.wait() + elif ( + test_context.cancellation_type + == workflow.NexusOperationCancellationType.WAIT_COMPLETED + ): + await self.release_cancellation.wait() raise @workflow.signal def set_caller_op_future_resolved(self) -> None: self.caller_op_future_resolved.set() + @workflow.signal + def set_release_cancellation(self) -> None: + self.release_cancellation.set() + + @workflow.query + def has_cancel_requested(self) -> bool: + return self.cancel_requested + @nexusrpc.service class Service: @@ -151,6 +168,10 @@ async def get_operation_token(self) -> str: async def wait_caller_op_future_resolved(self) -> None: await self.caller_op_future_resolved + @workflow.query + def has_caller_op_future_resolved(self) -> bool: + return self.caller_op_future_resolved.done() + @workflow.run async def run(self, input: Input) -> CancellationResult: op_handle = await ( @@ -408,6 +429,17 @@ async def check_behavior_for_wait_cancellation_completed( Check that a cancellation request is sent and the caller workflow nexus operation future is unblocked after the operation is canceled. """ + + async def assert_handler_cancel_requested() -> None: + assert await handler_wf.query(HandlerWorkflow.has_cancel_requested) + + await assert_eventually(assert_handler_cancel_requested) + + handler_status = (await handler_wf.describe()).status + assert handler_status == WorkflowExecutionStatus.RUNNING + assert not await caller_wf.query(CallerWorkflow.has_caller_op_future_resolved) + + await handler_wf.signal(HandlerWorkflow.set_release_cancellation) try: await handler_wf.result() except WorkflowFailureError as err: @@ -418,8 +450,13 @@ async def check_behavior_for_wait_cancellation_completed( handler_status = (await handler_wf.describe()).status assert handler_status == WorkflowExecutionStatus.CANCELED + async def assert_caller_op_future_resolved() -> None: + assert await caller_wf.query(CallerWorkflow.has_caller_op_future_resolved) + + await assert_eventually(assert_caller_op_future_resolved) + await caller_wf.signal(CallerWorkflow.release) - result = await caller_wf.result() + await caller_wf.result() await assert_event_subsequence( caller_wf, @@ -430,14 +467,6 @@ async def check_behavior_for_wait_cancellation_completed( EventType.EVENT_TYPE_WORKFLOW_EXECUTION_COMPLETED, ], ) - handler_wf_canceled_event = await get_event_time( - handler_wf, - EventType.EVENT_TYPE_WORKFLOW_EXECUTION_CANCELED, - ) - assert handler_wf_canceled_event <= result.caller_op_future_resolved, ( - "expected caller op future resolved after handler workflow canceled, but got " - f"{result.caller_op_future_resolved} before {handler_wf_canceled_event}" - ) async def has_event(wf_handle: WorkflowHandle, event_type: EventType.ValueType): diff --git a/tests/nexus/test_workflow_caller_cancellation_types_when_cancel_handler_fails.py b/tests/nexus/test_workflow_caller_cancellation_types_when_cancel_handler_fails.py index a344f1b5c..3418e290f 100644 --- a/tests/nexus/test_workflow_caller_cancellation_types_when_cancel_handler_fails.py +++ b/tests/nexus/test_workflow_caller_cancellation_types_when_cancel_handler_fails.py @@ -23,6 +23,7 @@ from temporalio.common import WorkflowIDConflictPolicy from temporalio.testing import WorkflowEnvironment from temporalio.worker import Worker +from tests.helpers import assert_eventually from tests.helpers.nexus import make_nexus_endpoint_name from tests.nexus.test_workflow_caller_cancellation_types import ( assert_event_subsequence, @@ -48,6 +49,7 @@ class HandlerWorkflow: def __init__(self): self.cancel_handler_released = asyncio.Event() self.caller_op_future_resolved = asyncio.Event() + self.release_completion = asyncio.Event() @workflow.run async def run(self) -> None: @@ -61,6 +63,11 @@ async def run(self) -> None: # For WAIT_REQUESTED, we want to prove that the future can be unblocked before the # handler workflow completes. await self.caller_op_future_resolved.wait() + elif ( + test_context.cancellation_type + == workflow.NexusOperationCancellationType.WAIT_COMPLETED + ): + await self.release_completion.wait() @workflow.signal def set_cancel_handler_released(self) -> None: @@ -70,6 +77,14 @@ def set_cancel_handler_released(self) -> None: def set_caller_op_future_resolved(self) -> None: self.caller_op_future_resolved.set() + @workflow.signal + def set_release_completion(self) -> None: + self.release_completion.set() + + @workflow.query + def has_cancel_handler_released(self) -> bool: + return self.cancel_handler_released.is_set() + @nexusrpc.service class Service: @@ -153,6 +168,10 @@ async def get_operation_token(self) -> str: assert self.operation_token return self.operation_token + @workflow.query + def has_caller_op_future_resolved(self) -> bool: + return self.caller_op_future_resolved.done() + @workflow.run async def run(self, input: Input) -> CancellationResult: op_handle = await ( @@ -370,7 +389,23 @@ async def check_behavior_for_wait_cancellation_completed( caller_wf: WorkflowHandle[Any, CancellationResult], handler_wf: WorkflowHandle, ) -> None: + async def assert_cancel_handler_released() -> None: + assert await handler_wf.query(HandlerWorkflow.has_cancel_handler_released) + + await assert_eventually(assert_cancel_handler_released) + + handler_status = (await handler_wf.describe()).status + assert handler_status == WorkflowExecutionStatus.RUNNING + assert not await caller_wf.query(CallerWorkflow.has_caller_op_future_resolved) + + await handler_wf.signal(HandlerWorkflow.set_release_completion) await handler_wf.result() + + async def assert_caller_op_future_resolved() -> None: + assert await caller_wf.query(CallerWorkflow.has_caller_op_future_resolved) + + await assert_eventually(assert_caller_op_future_resolved) + await caller_wf.signal(CallerWorkflow.release) result = await caller_wf.result() assert not result.error_type @@ -386,8 +421,3 @@ async def check_behavior_for_wait_cancellation_completed( EventType.EVENT_TYPE_NEXUS_OPERATION_COMPLETED, ], ) - handler_wf_completed = await get_event_time( - handler_wf, - EventType.EVENT_TYPE_WORKFLOW_EXECUTION_COMPLETED, - ) - assert handler_wf_completed <= result.caller_op_future_resolved diff --git a/tests/test_activity.py b/tests/test_activity.py index 172040257..6efa0d644 100644 --- a/tests/test_activity.py +++ b/tests/test_activity.py @@ -461,6 +461,38 @@ async def test_get_result(client: Client, env: WorkflowEnvironment): assert await result_via_execute_activity == 2 +async def test_start_activity_start_delay(client: Client, env: WorkflowEnvironment): + if env.supports_time_skipping: + pytest.skip( + "Java test server: https://github.com/temporalio/sdk-java/issues/2741" + ) + + activity_id = str(uuid.uuid4()) + task_queue = str(uuid.uuid4()) + start_delay = timedelta(seconds=2) + + async with Worker( + client, + task_queue=task_queue, + activities=[increment], + ): + activity_handle = await client.start_activity( + increment, + args=(1,), + id=activity_id, + task_queue=task_queue, + start_to_close_timeout=timedelta(seconds=5), + start_delay=start_delay, + ) + + assert await activity_handle.result() == 2 + desc = await activity_handle.describe() + assert desc.last_started_time is not None + assert ( + desc.last_started_time - desc.scheduled_time + ).total_seconds() >= start_delay.total_seconds() - 0.5 + + async def test_get_activity_handle(client: Client, env: WorkflowEnvironment): if env.supports_time_skipping: pytest.skip( From 8da1ca89f250e10ddc043475580bc693cfa4a4fe Mon Sep 17 00:00:00 2001 From: Spencer Judge Date: Tue, 19 May 2026 09:11:55 -0700 Subject: [PATCH 096/226] Update banner url (#1542) --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 019d6f576..d284fad59 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -![Temporal Python SDK](https://assets.temporal.io/w/py-banner.svg) +![Temporal Python SDK](https://assets.temporal.io/w/py.png) [![Python 3.9+](https://img.shields.io/pypi/pyversions/temporalio.svg?style=for-the-badge)](https://pypi.org/project/temporalio) [![PyPI](https://img.shields.io/pypi/v/temporalio.svg?style=for-the-badge)](https://pypi.org/project/temporalio) From b8688d5963e800ef14e6f62df4f8ff0889088b4b Mon Sep 17 00:00:00 2001 From: Alex Mazzeo Date: Tue, 19 May 2026 11:31:44 -0700 Subject: [PATCH 097/226] Add polling for expected history before sending final signal in test_workflow_history_info (#1545) --- tests/worker/test_workflow.py | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/tests/worker/test_workflow.py b/tests/worker/test_workflow.py index 3b06c8d1d..07d107432 100644 --- a/tests/worker/test_workflow.py +++ b/tests/worker/test_workflow.py @@ -329,6 +329,24 @@ async def test_workflow_history_info( await handle.signal( HistoryInfoWorkflow.bunch_of_events, continue_as_new_suggest_history_count ) + + # Wait for the first signal's timers to be committed so the next + # signal creates a post-timer workflow task with updated workflow.info(). + # This avoids a race where both signals are accepted before the worker + # processes the first one and both make it into the same activation. + # If that occurs, the query will have the stale history that the + # final signal is intended to avoid. + async def timer_events_recorded() -> None: + timer_started_count = 0 + async for event in handle.fetch_history_events(): + if event.HasField("timer_started_event_attributes"): + timer_started_count += 1 + if timer_started_count >= continue_as_new_suggest_history_count: + return + assert timer_started_count >= continue_as_new_suggest_history_count + + await assert_eventually(timer_events_recorded) + # Send one more event to trigger the WFT update. We have to do this # because just a query will have a stale representation of history # counts, but signal forces a new WFT. From ee59538c95d7a601f4e16a9613116aa8ba4b377a Mon Sep 17 00:00:00 2001 From: Thomas Hardy Date: Tue, 19 May 2026 14:32:35 -0400 Subject: [PATCH 098/226] remove stale nightly tps omes test (#1544) --- .../workflows/nightly-throughput-stress.yml | 221 ------------------ 1 file changed, 221 deletions(-) delete mode 100644 .github/workflows/nightly-throughput-stress.yml diff --git a/.github/workflows/nightly-throughput-stress.yml b/.github/workflows/nightly-throughput-stress.yml deleted file mode 100644 index 46d33eb77..000000000 --- a/.github/workflows/nightly-throughput-stress.yml +++ /dev/null @@ -1,221 +0,0 @@ -name: Nightly Throughput Stress - -on: - schedule: - # Run at 3 AM PST (11:00 UTC) - offset from existing nightly - - cron: '00 11 * * *' - workflow_dispatch: - inputs: - duration: - description: 'Test duration (e.g., 6h, 1h)' - required: false - default: '5h' - type: string - timeout: - description: 'Scenario timeout (should always be greater than duration)' - required: false - default: '5h30m' - type: string - job_timeout_minutes: - description: 'GitHub Actions job timeout in minutes' - required: false - default: 360 - type: number - is_experiment: - description: 'Mark this run as an experiment (excluded from nightly dashboards)' - required: false - default: false - type: boolean - -permissions: - contents: read - id-token: write - -env: - # Workflow configuration - TEST_DURATION: ${{ inputs.duration || vars.NIGHTLY_TEST_DURATION || '5h' }} - TEST_TIMEOUT: ${{ inputs.timeout || vars.NIGHTLY_TEST_TIMEOUT || '5h30m' }} - - # AWS S3 metrics upload ARN - AWS_S3_METRICS_UPLOAD_ROLE_ARN: ${{ vars.AWS_S3_METRICS_UPLOAD_ROLE_ARN }} - - # Logging and artifacts - WORKER_LOG_DIR: /tmp/throughput-stress-logs - - # Omes configuration - OMES_REPO: temporalio/omes - OMES_REF: main - RUN_ID: ${{ github.run_id }}-throughput-stress - - # Prometheus version - PROM_VERSION: "3.8.0" - - # Language - SDK_LANG: "python" - -jobs: - throughput-stress: - runs-on: ubuntu-latest-4-cores - timeout-minutes: ${{ fromJSON(inputs.job_timeout_minutes || vars.NIGHTLY_JOB_TIMEOUT_MINUTES || 360) }} - - steps: - - name: Print test configuration - run: | - echo "=== Throughput Stress Test Configuration ===" - echo "Duration: $TEST_DURATION" - echo "Timeout: $TEST_TIMEOUT" - echo "Run ID: $RUN_ID" - echo "==========================================" - - - name: Checkout SDK - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 - with: - submodules: recursive - - - name: Checkout OMES - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 - with: - repository: ${{ env.OMES_REPO }} - ref: ${{ env.OMES_REF }} - path: omes - - - name: Setup Go - uses: actions/setup-go@40f1582b2485089dde7abd97c1529aa768e1baff # v5 - with: - go-version-file: omes/go.mod - cache-dependency-path: omes/go.sum - - - name: Setup Rust - uses: dtolnay/rust-toolchain@29eef336d9b2848a0b548edc03f92a220660cdb8 # stable - - - name: Setup Rust cache - uses: Swatinem/rust-cache@e18b497796c12c097a38f9edb9d0641fb99eee32 # v2 - with: - cache-bin: false - workspaces: temporalio/bridge -> target - - - name: Setup Python - uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5 - with: - python-version: "3.13" - - - name: Install protoc - uses: arduino/setup-protoc@c65c819552d16ad3c9b72d9dfd5ba5237b9c906b # v3 - with: - version: '23.x' - repo-token: ${{ secrets.GITHUB_TOKEN }} - - - name: Setup uv - uses: astral-sh/setup-uv@cec208311dfd045dd5311c1add060b2062131d57 # v8 - - - name: Install poethepoet - run: uv tool install poethepoet - - - name: Install dependencies - run: uv sync --all-extras - - - name: Build SDK - run: poe build-develop - - - name: Install Temporal CLI - uses: temporalio/setup-temporal@1059a504f87e7fa2f385e3fa40d1aa7e62f1c6ca # v0 - - - name: Install Prometheus - run: | - wget -q https://github.com/prometheus/prometheus/releases/download/v${PROM_VERSION}/prometheus-${PROM_VERSION}.linux-amd64.tar.gz - tar xzf prometheus-${PROM_VERSION}.linux-amd64.tar.gz - sudo mv prometheus-${PROM_VERSION}.linux-amd64/prometheus /usr/local/bin/ - prometheus --version - - - name: Setup log directory - run: mkdir -p $WORKER_LOG_DIR - - - name: Start Temporal Server - run: | - temporal server start-dev \ - --db-filename temporal-throughput-stress.sqlite \ - --sqlite-pragma journal_mode=WAL \ - --sqlite-pragma synchronous=OFF \ - --headless &> $WORKER_LOG_DIR/temporal-server.log & - - - name: Run throughput stress scenario with local SDK - working-directory: omes - run: | - # This makes the pipeline return the exit code of the first failing command - # Otherwise the output of the `tee` command will be used - # (which is troublesome when the scenario fails but the `tee` command succeeds) - set -o pipefail - - # Use run-scenario-with-worker to build and run in one step - # Pass the SDK directory as --version for local testing - # Note: The hardcoded values below match OMES defaults, except: - # - visibility-count-timeout: 5m (vs 3m default) - # to give CI a bit more time for visibility consistency - go run ./cmd run-scenario-with-worker \ - --scenario throughput_stress \ - --language $SDK_LANG \ - --version $(pwd)/.. \ - --run-id $RUN_ID \ - --duration $TEST_DURATION \ - --timeout $TEST_TIMEOUT \ - --max-concurrent 10 \ - --prom-listen-address 127.0.0.1:9091 \ - --worker-prom-listen-address 127.0.0.1:9092 \ - --prom-instance-addr 127.0.0.1:9090 \ - --prom-instance-config \ - --prom-export-worker-metrics $RUN_ID.parquet \ - --option internal-iterations=10 \ - --option continue-as-new-after-iterations=3 \ - --option sleep-time=1s \ - --option visibility-count-timeout=5m \ - --option min-throughput-per-hour=1000 \ - 2>&1 | tee $WORKER_LOG_DIR/scenario.log - - - name: Configure AWS credentials - if: always() - uses: aws-actions/configure-aws-credentials@ff717079ee2060e4bcee96c4779b553acc87447c # v4 - with: - role-to-assume: ${{ env.AWS_S3_METRICS_UPLOAD_ROLE_ARN }} - aws-region: us-west-2 - - - name: Upload metrics to S3 - if: always() - run: | - DATE=$(date +%Y-%m-%d) - IS_EXPERIMENT="false" - # Set as an experiment if we are not on the main branch or input as an experiment - if [[ "$GH_REF" != "refs/heads/main" || "$IS_EXPERIMENT_INPUT" == "true" ]]; then - IS_EXPERIMENT="true" - fi - echo "Uploading metrics: is_experiment=$IS_EXPERIMENT, language=$SDK_LANG, date=$DATE" - aws s3 cp omes/$RUN_ID.parquet \ - "s3://cloud-data-ingest-prod/github/sdk_load_test/is_experiment=$IS_EXPERIMENT/language=$SDK_LANG/date=$DATE/$RUN_ID.parquet" - - - name: Upload logs on failure - if: failure() || cancelled() - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4 - with: - name: throughput-stress-logs - path: ${{ env.WORKER_LOG_DIR }} - retention-days: 30 - - - name: Notify Slack on failure - if: failure() || cancelled() - uses: slackapi/slack-github-action@af78098f536edbc4de71162a307590698245be95 # v3 - with: - webhook-type: incoming-webhook - payload: | - { - "text": "Nightly Python throughput stress test failed", - "blocks": [ - { - "type": "section", - "text": { - "type": "mrkdwn", - "text": "*Nightly Throughput Stress Failed* :x:\n\n*Repository:* ${{ github.repository }}\n*Duration:* ${{ env.TEST_DURATION }}\n*Run:* <${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}|View Logs>\n*Triggered by:* ${{ github.event_name == 'schedule' && 'Scheduled' || github.actor }}" - } - } - ] - } - env: - SLACK_WEBHOOK_URL: ${{ secrets.SLACK_SDK_ALERTS_WEBHOOK }} From b270da7a760dcbaff693019639c239176f240805 Mon Sep 17 00:00:00 2001 From: Alex Mazzeo Date: Wed, 20 May 2026 15:07:40 -0700 Subject: [PATCH 099/226] Implement Standalone Nexus Operations (#1461) * implement standalone nexus operations * Move nexus operation polling to an interceptable client method. Add in defaults for id_reuse_policy and id_conflict_policy. Update integration tests with better typing and new assertions for the newly interceptable get_nexus_operation_result * Add test demonstrating error chain. Ensure that failures are wrapped with a NexusOperationFailureError * Run uv sync after rebase * Make result_type take precedence in get_nexus_operation_handle to match start/execute operation. Fix hardcoded retryable=True in fallback error serialization. Add type tests and rename test/nexus/test_type_errors.py to ensure that the type test file properly executes nexus tests. * Add caching of failures for NexusOperationHandle * Consistency pass on models from proto. Expose long_poll_token * expose user metadata. some type fixes * Address findings/suggestions from claude * generate protos. Update bridge dependency to reference the right version of sdk-core. Reference cli prerelease in tests. Add sano required dynamic config values to test server. unskip additional failure details test. * enable start_delay for SAA in test server config * Fix warning spam about invalid workflow event links by filtering nexus links out. Shield task completion to core so we don't drop the rust future that _must_ complete for shutdown to succeed. Add flake finder as dev dependency. * skip sano tests on the time skipping server * Fix typo * Fix typo in docstring * Update docstring to not use parens * Respect service decorator field 'name' in sano client. add test verifying support * Remove dynamic config that isn't ready yet * forward long poll token to describe requests properly * Thread timeouts through sano * Remove overloads that allowed omission of operation input. Add some tests that validate that the arg is required * run formatter * Define NexusServiceType in types.py and use in both workflow and client packages * Fix some docstrings. Remove unecessary check for workflow event link type * Narrow assertions in sano describe test * Update core to the commit that main is pointing at * Remove kwarg requirement for endpoint arg in create_nexus_client * run formatter and address linter * Remove unrelated changes to operation context and link conversion * Revert "Remove unrelated changes to operation context and link conversion" This reverts commit c5243b77177fe8d5e11f40376cc3ab2dbc6e9e85. * Add support for nexus operation links, include temporary filter to avoid sending links the server will reject * Add github issue link in link workaround. Remove long poll token from describe nexus operation --- pyproject.toml | 6 +- temporalio/client/__init__.py | 34 + temporalio/client/_client.py | 169 ++- temporalio/client/_impl.py | 227 +++- temporalio/client/_interceptor.py | 192 +++- temporalio/client/_nexus.py | 1212 ++++++++++++++++++++ temporalio/common.py | 144 +++ temporalio/converter/_failure_converter.py | 2 +- temporalio/exceptions.py | 18 + temporalio/nexus/_link_conversion.py | 147 ++- temporalio/nexus/_operation_context.py | 14 +- temporalio/types.py | 1 + temporalio/worker/_nexus.py | 13 +- temporalio/workflow/__init__.py | 2 - temporalio/workflow/_nexus.py | 27 +- tests/conftest.py | 6 + tests/nexus/test_link_conversion.py | 141 ++- tests/nexus/test_nexus_type_errors.py | 399 +++++++ tests/nexus/test_standalone_operations.py | 951 +++++++++++++++ tests/nexus/test_type_errors.py | 207 ---- tests/test_workflow_exports.py | 1 - uv.lock | 14 + 22 files changed, 3645 insertions(+), 282 deletions(-) create mode 100644 temporalio/client/_nexus.py create mode 100644 tests/nexus/test_nexus_type_errors.py create mode 100644 tests/nexus/test_standalone_operations.py delete mode 100644 tests/nexus/test_type_errors.py diff --git a/pyproject.toml b/pyproject.toml index a5f509227..e59b54ab7 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -39,10 +39,7 @@ lambda-worker-otel = [ "opentelemetry-semantic-conventions>=0.40b0,<1", "opentelemetry-sdk-extension-aws>=2.0.0,<3", ] -aioboto3 = [ - "aioboto3>=10.4.0", - "types-aioboto3[s3]>=10.4.0", -] +aioboto3 = ["aioboto3>=10.4.0", "types-aioboto3[s3]>=10.4.0"] [project.urls] Homepage = "https://github.com/temporalio/sdk-python" @@ -86,6 +83,7 @@ dev = [ "opentelemetry-exporter-otlp-proto-grpc>=1.11.1,<2", "opentelemetry-semantic-conventions>=0.40b0,<1", "opentelemetry-sdk-extension-aws>=2.0.0,<3", + "pytest-flakefinder>=1.1.0", "async-timeout>=4.0,<6; python_version < '3.11'", ] diff --git a/temporalio/client/__init__.py b/temporalio/client/__init__.py index c403b8bcc..2e4609c32 100644 --- a/temporalio/client/__init__.py +++ b/temporalio/client/__init__.py @@ -90,22 +90,27 @@ from ._interceptor import ( BackfillScheduleInput, CancelActivityInput, + CancelNexusOperationInput, CancelWorkflowInput, CompleteAsyncActivityInput, CountActivitiesInput, + CountNexusOperationsInput, CountWorkflowsInput, CreateScheduleInput, DeleteScheduleInput, DescribeActivityInput, + DescribeNexusOperationInput, DescribeScheduleInput, DescribeWorkflowInput, FailAsyncActivityInput, FetchWorkflowHistoryEventsInput, + GetNexusOperationResultInput, GetWorkerBuildIdCompatibilityInput, GetWorkerTaskReachabilityInput, HeartbeatAsyncActivityInput, Interceptor, ListActivitiesInput, + ListNexusOperationsInput, ListSchedulesInput, ListWorkflowsInput, OutboundInterceptor, @@ -114,10 +119,12 @@ ReportCancellationAsyncActivityInput, SignalWorkflowInput, StartActivityInput, + StartNexusOperationInput, StartWorkflowInput, StartWorkflowUpdateInput, StartWorkflowUpdateWithStartInput, TerminateActivityInput, + TerminateNexusOperationInput, TerminateWorkflowInput, TriggerScheduleInput, UnpauseScheduleInput, @@ -126,6 +133,17 @@ UpdateWithStartUpdateWorkflowInput, UpdateWorkerBuildIdCompatibilityInput, ) +from ._nexus import ( + NexusClient, + NexusOperationExecution, + NexusOperationExecutionAsyncIterator, + NexusOperationExecutionCancellationInfo, + NexusOperationExecutionCount, + NexusOperationExecutionCountAggregationGroup, + NexusOperationExecutionDescription, + NexusOperationFailureError, + NexusOperationHandle, +) from ._plugin import ( Plugin, ) @@ -213,6 +231,14 @@ "AsyncActivityIDReference", "AsyncActivityHandle", "ActivityHandle", + "NexusClient", + "NexusOperationExecution", + "NexusOperationExecutionAsyncIterator", + "NexusOperationExecutionCancellationInfo", + "NexusOperationExecutionCount", + "NexusOperationExecutionCountAggregationGroup", + "NexusOperationExecutionDescription", + "NexusOperationHandle", "ScheduleHandle", "ScheduleSpec", "ScheduleRange", @@ -248,6 +274,7 @@ "WorkflowUpdateRPCTimeoutOrCancelledError", "ActivityFailureError", "AsyncActivityCancelledError", + "NexusOperationFailureError", "ScheduleAlreadyRunningError", "StartWorkflowInput", "CancelWorkflowInput", @@ -264,6 +291,13 @@ "DescribeActivityInput", "ListActivitiesInput", "CountActivitiesInput", + "StartNexusOperationInput", + "DescribeNexusOperationInput", + "GetNexusOperationResultInput", + "CancelNexusOperationInput", + "TerminateNexusOperationInput", + "ListNexusOperationsInput", + "CountNexusOperationsInput", "StartWorkflowUpdateInput", "UpdateWithStartUpdateWorkflowInput", "UpdateWithStartStartWorkflowInput", diff --git a/temporalio/client/_client.py b/temporalio/client/_client.py index 437c9f2b2..1d8b8e4f2 100644 --- a/temporalio/client/_client.py +++ b/temporalio/client/_client.py @@ -17,6 +17,8 @@ overload, ) +import nexusrpc +from nexusrpc import OutputT from typing_extensions import Required, Self, TypedDict import temporalio.activity @@ -47,6 +49,7 @@ MethodAsyncNoParam, MethodAsyncSingleParam, MultiParamSpec, + NexusServiceType, ParamType, ReturnType, SelfType, @@ -62,11 +65,13 @@ from ._impl import _ClientImpl from ._interceptor import ( CountActivitiesInput, + CountNexusOperationsInput, CountWorkflowsInput, CreateScheduleInput, GetWorkerBuildIdCompatibilityInput, GetWorkerTaskReachabilityInput, ListActivitiesInput, + ListNexusOperationsInput, ListSchedulesInput, ListWorkflowsInput, OutboundInterceptor, @@ -76,6 +81,13 @@ UpdateWithStartUpdateWorkflowInput, UpdateWorkerBuildIdCompatibilityInput, ) +from ._nexus import ( + NexusClient, + NexusOperationExecutionAsyncIterator, + NexusOperationExecutionCount, + NexusOperationHandle, + _NexusClient, +) from ._schedule import ( Schedule, ScheduleAsyncIterator, @@ -541,9 +553,7 @@ async def start_workflow( # are deliberately not exposed in overloads, and are not subject to any # backwards compatibility guarantees. callbacks: Sequence[Callback] = [], - workflow_event_links: Sequence[ - temporalio.api.common.v1.Link.WorkflowEvent - ] = [], + links: Sequence[temporalio.api.common.v1.Link] = [], request_id: str | None = None, stack_level: int = 2, ) -> WorkflowHandle[Any, Any]: @@ -637,7 +647,7 @@ async def start_workflow( request_eager_start=request_eager_start, priority=priority, callbacks=callbacks, - workflow_event_links=workflow_event_links, + links=links, request_id=request_id, ) ) @@ -2859,6 +2869,157 @@ async def get_worker_task_reachability( ) ) + def create_nexus_client( + self, + service: type[NexusServiceType] | str, + endpoint: str, + ) -> NexusClient[NexusServiceType]: + """Create a client for starting standalone Nexus operations. + + .. warning:: + This API is experimental and unstable. + + Args: + service: The Nexus service type or service name string. + endpoint: Endpoint name, resolved to a URL via the cluster's + endpoint registry. + + Returns: + A Nexus client for the given service and endpoint. + """ + return _NexusClient(client=self, service=service, endpoint=endpoint) + + def list_nexus_operations( + self, + query: str, + *, + limit: int | None = None, + page_size: int = 1000, + next_page_token: bytes | None = None, + rpc_metadata: Mapping[str, str | bytes] = {}, + rpc_timeout: timedelta | None = None, + ) -> NexusOperationExecutionAsyncIterator: + """List standalone Nexus operations. + + .. warning:: + This API is experimental and unstable. + + This does not make a request until the first iteration is attempted. + Therefore any errors will not occur until then. + + Args: + query: A Temporal visibility list filter for nexus operations. Required. + limit: Maximum number of operations to return. If unset, all + operations are returned. Only applies if using the + returned :py:class:`NexusOperationExecutionAsyncIterator` + as an async iterator. + page_size: Maximum number of results for each page. + next_page_token: A previously obtained next page token if doing + pagination. Usually not needed as the iterator automatically + starts from the beginning. + rpc_metadata: Headers used on each RPC call. Keys here override + client-level RPC metadata keys. + rpc_timeout: Optional RPC deadline to set for each RPC call. + + Returns: + An async iterator that can be used with ``async for``. + """ + return self._impl.list_nexus_operations( + ListNexusOperationsInput( + query=query, + page_size=page_size, + next_page_token=next_page_token, + rpc_metadata=rpc_metadata, + rpc_timeout=rpc_timeout, + limit=limit, + ) + ) + + async def count_nexus_operations( + self, + query: str | None = None, + *, + rpc_metadata: Mapping[str, str | bytes] = {}, + rpc_timeout: timedelta | None = None, + ) -> NexusOperationExecutionCount: + """Count standalone Nexus operations. + + .. warning:: + This API is experimental and unstable. + + Args: + query: A Temporal visibility filter for nexus operations. + rpc_metadata: Headers used on the RPC call. Keys here override + client-level RPC metadata keys. + rpc_timeout: Optional RPC deadline to set for the RPC call. + + Returns: + Count of nexus operations. + """ + return await self._impl.count_nexus_operations( + CountNexusOperationsInput( + query=query, rpc_metadata=rpc_metadata, rpc_timeout=rpc_timeout + ) + ) + + @overload + def get_nexus_operation_handle( + self, + operation_id: str, + *, + run_id: str | None = None, + ) -> NexusOperationHandle[Any]: ... + + @overload + def get_nexus_operation_handle( + self, + operation_id: str, + *, + run_id: str | None = None, + result_type: type[ReturnType], + ) -> NexusOperationHandle[ReturnType]: ... + + @overload + def get_nexus_operation_handle( + self, + operation_id: str, + *, + operation: nexusrpc.Operation[Any, OutputT], + run_id: str | None = None, + ) -> NexusOperationHandle[OutputT]: ... + + def get_nexus_operation_handle( + self, + operation_id: str, + *, + operation: nexusrpc.Operation[Any, Any] | None = None, + run_id: str | None = None, + result_type: type | None = None, + ) -> NexusOperationHandle[Any]: + """Get a handle to an existing standalone Nexus operation. + + .. warning:: + This API is experimental and unstable. + + Args: + operation_id: The operation ID. + operation: A ``nexusrpc.Operation`` from which the result type + is extracted. If both ``operation`` and ``result_type`` are + provided, the ``result_type`` takes precedence. + run_id: The operation run ID. If not provided, targets the latest run. + result_type: The result type to deserialize into. + + Returns: + A handle to the operation. + """ + result_type = result_type or (operation.output_type if operation else None) + return NexusOperationHandle( + self, + operation_id, + run_id=run_id, + result_type=result_type, + ) + class ClientConnectConfig(TypedDict, total=False): """TypedDict of keyword arguments for :py:meth:`Client.connect`.""" diff --git a/temporalio/client/_impl.py b/temporalio/client/_impl.py index 0c05a2dd7..af221865a 100644 --- a/temporalio/client/_impl.py +++ b/temporalio/client/_impl.py @@ -64,21 +64,26 @@ from ._interceptor import ( BackfillScheduleInput, CancelActivityInput, + CancelNexusOperationInput, CancelWorkflowInput, CompleteAsyncActivityInput, CountActivitiesInput, + CountNexusOperationsInput, CountWorkflowsInput, CreateScheduleInput, DeleteScheduleInput, DescribeActivityInput, + DescribeNexusOperationInput, DescribeScheduleInput, DescribeWorkflowInput, FailAsyncActivityInput, FetchWorkflowHistoryEventsInput, + GetNexusOperationResultInput, GetWorkerBuildIdCompatibilityInput, GetWorkerTaskReachabilityInput, HeartbeatAsyncActivityInput, ListActivitiesInput, + ListNexusOperationsInput, ListSchedulesInput, ListWorkflowsInput, OutboundInterceptor, @@ -87,10 +92,12 @@ ReportCancellationAsyncActivityInput, SignalWorkflowInput, StartActivityInput, + StartNexusOperationInput, StartWorkflowInput, StartWorkflowUpdateInput, StartWorkflowUpdateWithStartInput, TerminateActivityInput, + TerminateNexusOperationInput, TerminateWorkflowInput, TriggerScheduleInput, UnpauseScheduleInput, @@ -99,6 +106,13 @@ UpdateWithStartUpdateWorkflowInput, UpdateWorkerBuildIdCompatibilityInput, ) +from ._nexus import ( + NexusOperationExecutionAsyncIterator, + NexusOperationExecutionCount, + NexusOperationExecutionDescription, + NexusOperationFailureError, + NexusOperationHandle, +) from ._schedule import ( ScheduleAsyncIterator, ScheduleDescription, @@ -200,10 +214,16 @@ async def _build_start_workflow_execution_request( if input.request_id: req.request_id = input.request_id + # Server currently only supports workflow_event and batch_job + # link types. This filter should be removed or adapted as + # server-side support comes online. + # See https://github.com/temporalio/temporal/issues/10345 links = [ - temporalio.api.common.v1.Link(workflow_event=link) - for link in input.workflow_event_links + link + for link in input.links + if link.HasField("workflow_event") or link.HasField("batch_job") ] + req.completion_callbacks.extend( temporalio.api.common.v1.Callback( nexus=temporalio.api.common.v1.Callback.Nexus( @@ -1396,6 +1416,209 @@ async def get_worker_task_reachability( ) return WorkerTaskReachability._from_proto(resp) + ### Nexus operation calls + + async def start_nexus_operation( + self, input: StartNexusOperationInput + ) -> NexusOperationHandle[Any]: + """Start a nexus operation and return a handle to it.""" + req = temporalio.api.workflowservice.v1.StartNexusOperationExecutionRequest( + namespace=self._client.namespace, + identity=self._client.identity, + request_id=str(uuid.uuid4()), + operation_id=input.id, + endpoint=input.endpoint, + service=input.service, + operation=input.operation, + id_reuse_policy=cast( + "temporalio.api.enums.v1.NexusOperationIdReusePolicy.ValueType", + int(input.id_reuse_policy), + ), + id_conflict_policy=cast( + "temporalio.api.enums.v1.NexusOperationIdConflictPolicy.ValueType", + int(input.id_conflict_policy), + ), + ) + + if input.schedule_to_close_timeout is not None: + req.schedule_to_close_timeout.FromTimedelta(input.schedule_to_close_timeout) + if input.schedule_to_start_timeout is not None: + req.schedule_to_start_timeout.FromTimedelta(input.schedule_to_start_timeout) + if input.start_to_close_timeout is not None: + req.start_to_close_timeout.FromTimedelta(input.start_to_close_timeout) + + # Set input payload + encoded = await self._client.data_converter.encode([input.arg]) + if encoded: + req.input.CopyFrom(encoded[0]) + + # Set search attributes + if input.search_attributes is not None: + temporalio.converter.encode_search_attributes( + input.search_attributes, req.search_attributes + ) + + # Set user metadata + metadata = await _encode_user_metadata( + self._client.data_converter, input.summary, None + ) + if metadata is not None: + req.user_metadata.CopyFrom(metadata) + + # Set nexus headers + if input.headers: + for k, v in input.headers.items(): + req.nexus_header[k] = v + + resp: temporalio.api.workflowservice.v1.StartNexusOperationExecutionResponse + try: + resp = await self._client.workflow_service.start_nexus_operation_execution( + req, + retry=True, + metadata=input.rpc_metadata, + timeout=input.rpc_timeout, + ) + except RPCError as err: + if err.status == RPCStatusCode.ALREADY_EXISTS and err.grpc_status.details: + details = temporalio.api.errordetails.v1.NexusOperationExecutionAlreadyStartedFailure() + if err.grpc_status.details[0].Unpack(details): + raise temporalio.exceptions.NexusOperationAlreadyStartedError( + input.id, run_id=details.run_id + ) + raise + return NexusOperationHandle( + self._client, + input.id, + run_id=resp.run_id or None, + result_type=input.result_type, + endpoint=input.endpoint, + service=input.service, + ) + + async def describe_nexus_operation( + self, input: DescribeNexusOperationInput + ) -> NexusOperationExecutionDescription: + """Describe a nexus operation.""" + req = temporalio.api.workflowservice.v1.DescribeNexusOperationExecutionRequest( + namespace=self._client.namespace, + operation_id=input.operation_id, + run_id=input.run_id or "", + ) + resp = await self._client.workflow_service.describe_nexus_operation_execution( + req=req, + retry=True, + metadata=input.rpc_metadata, + timeout=input.rpc_timeout, + ) + return await NexusOperationExecutionDescription._from_execution_info( + info=resp.info, + data_converter=self._client.data_converter, + ) + + async def get_nexus_operation_result( + self, input: GetNexusOperationResultInput + ) -> Any: + """Poll for nexus operation result until it's available.""" + req = temporalio.api.workflowservice.v1.PollNexusOperationExecutionRequest( + namespace=self._client.namespace, + operation_id=input.operation_id, + run_id=input.run_id or "", + wait_stage=temporalio.api.enums.v1.NexusOperationWaitStage.NEXUS_OPERATION_WAIT_STAGE_CLOSED, + ) + + # Continue polling as long as we have no outcome + while True: + try: + res = ( + await self._client.workflow_service.poll_nexus_operation_execution( + req, + retry=True, + metadata=input.rpc_metadata, + timeout=input.rpc_timeout, + ) + ) + match res.WhichOneof("outcome"): + case "result": + type_hints = [input.result_type] if input.result_type else None + [result] = await self._client.data_converter.decode( + [res.result], type_hints + ) + return result + + case "failure": + raise NexusOperationFailureError( + cause=await self._client.data_converter.decode_failure( + res.failure + ) + ) + + case None: + # poll again + pass + except RPCError as err: + match err.status: + case RPCStatusCode.DEADLINE_EXCEEDED: + # Deadline exceeded is expected with long polling; retry + continue + case RPCStatusCode.CANCELLED: + raise asyncio.CancelledError() from err + case _: + raise + + async def cancel_nexus_operation(self, input: CancelNexusOperationInput) -> None: + """Cancel a nexus operation.""" + await self._client.workflow_service.request_cancel_nexus_operation_execution( + temporalio.api.workflowservice.v1.RequestCancelNexusOperationExecutionRequest( + namespace=self._client.namespace, + operation_id=input.operation_id, + run_id=input.run_id or "", + identity=self._client.identity, + request_id=str(uuid.uuid4()), + reason=input.reason or "", + ), + retry=True, + metadata=input.rpc_metadata, + timeout=input.rpc_timeout, + ) + + async def terminate_nexus_operation( + self, input: TerminateNexusOperationInput + ) -> None: + """Terminate a nexus operation.""" + await self._client.workflow_service.terminate_nexus_operation_execution( + temporalio.api.workflowservice.v1.TerminateNexusOperationExecutionRequest( + namespace=self._client.namespace, + operation_id=input.operation_id, + run_id=input.run_id or "", + reason=input.reason or "", + identity=self._client.identity, + request_id=str(uuid.uuid4()), + ), + retry=True, + metadata=input.rpc_metadata, + timeout=input.rpc_timeout, + ) + + def list_nexus_operations( + self, input: ListNexusOperationsInput + ) -> NexusOperationExecutionAsyncIterator: + return NexusOperationExecutionAsyncIterator(self._client, input) + + async def count_nexus_operations( + self, input: CountNexusOperationsInput + ) -> NexusOperationExecutionCount: + return NexusOperationExecutionCount._from_raw( + await self._client.workflow_service.count_nexus_operation_executions( + temporalio.api.workflowservice.v1.CountNexusOperationExecutionsRequest( + namespace=self._client.namespace, + query=input.query or "", + ), + retry=True, + metadata=input.rpc_metadata, + timeout=input.rpc_timeout, + ) + ) + async def _apply_headers( self, source: Mapping[str, temporalio.api.common.v1.Payload] | None, diff --git a/temporalio/client/_interceptor.py b/temporalio/client/_interceptor.py index 486c9bbd4..587b802d0 100644 --- a/temporalio/client/_interceptor.py +++ b/temporalio/client/_interceptor.py @@ -32,6 +32,12 @@ ActivityHandle, AsyncActivityIDReference, ) + from ._nexus import ( + NexusOperationExecutionAsyncIterator, + NexusOperationExecutionCount, + NexusOperationExecutionDescription, + NexusOperationHandle, + ) from ._schedule import ( Schedule, ScheduleAsyncIterator, @@ -93,7 +99,7 @@ class StartWorkflowInput: priority: temporalio.common.Priority # The following options are experimental and unstable. callbacks: Sequence[Callback] - workflow_event_links: Sequence[temporalio.api.common.v1.Link.WorkflowEvent] + links: Sequence[temporalio.api.common.v1.Link] request_id: str | None versioning_override: temporalio.common.VersioningOverride | None = None @@ -551,6 +557,120 @@ class GetWorkerTaskReachabilityInput: rpc_timeout: timedelta | None +@dataclass +class StartNexusOperationInput: + """Input for :py:meth:`OutboundInterceptor.start_nexus_operation`. + + .. warning:: + This API is experimental and unstable. + """ + + operation: str + arg: Any + id: str + endpoint: str + service: str + result_type: type | None + schedule_to_close_timeout: timedelta | None + schedule_to_start_timeout: timedelta | None + start_to_close_timeout: timedelta | None + id_reuse_policy: temporalio.common.NexusOperationIDReusePolicy + id_conflict_policy: temporalio.common.NexusOperationIDConflictPolicy + search_attributes: temporalio.common.TypedSearchAttributes | None + summary: str | None + headers: Mapping[str, str] + rpc_metadata: Mapping[str, str | bytes] + rpc_timeout: timedelta | None + + +@dataclass +class DescribeNexusOperationInput: + """Input for :py:meth:`OutboundInterceptor.describe_nexus_operation`. + + .. warning:: + This API is experimental and unstable. + """ + + operation_id: str + run_id: str | None + rpc_metadata: Mapping[str, str | bytes] + rpc_timeout: timedelta | None + + +@dataclass +class GetNexusOperationResultInput: + """Input for :py:meth:`OutboundInterceptor.get_nexus_operation_result`. + + .. warning:: + This API is experimental and unstable. + """ + + operation_id: str + run_id: str | None + rpc_metadata: Mapping[str, str | bytes] + rpc_timeout: timedelta | None + result_type: type[Any] | None + + +@dataclass +class CancelNexusOperationInput: + """Input for :py:meth:`OutboundInterceptor.cancel_nexus_operation`. + + .. warning:: + This API is experimental and unstable. + """ + + operation_id: str + run_id: str | None + reason: str | None + rpc_metadata: Mapping[str, str | bytes] + rpc_timeout: timedelta | None + + +@dataclass +class TerminateNexusOperationInput: + """Input for :py:meth:`OutboundInterceptor.terminate_nexus_operation`. + + .. warning:: + This API is experimental and unstable. + """ + + operation_id: str + run_id: str | None + reason: str | None + rpc_metadata: Mapping[str, str | bytes] + rpc_timeout: timedelta | None + + +@dataclass +class ListNexusOperationsInput: + """Input for :py:meth:`OutboundInterceptor.list_nexus_operations`. + + .. warning:: + This API is experimental and unstable. + """ + + query: str | None + page_size: int + next_page_token: bytes | None + rpc_metadata: Mapping[str, str | bytes] + rpc_timeout: timedelta | None + limit: int | None + + +@dataclass +class CountNexusOperationsInput: + """Input for :py:meth:`OutboundInterceptor.count_nexus_operations`. + + .. warning:: + This API is experimental and unstable. + """ + + query: str | None + rpc_metadata: Mapping[str, str | bytes] + rpc_timeout: timedelta | None + + @dataclass class Interceptor: """Interceptor for clients. @@ -781,3 +901,73 @@ async def get_worker_task_reachability( ) -> WorkerTaskReachability: """Called for every :py:meth:`Client.get_worker_task_reachability` call.""" return await self.next.get_worker_task_reachability(input) + + ### Nexus operation calls + + async def start_nexus_operation( + self, input: StartNexusOperationInput + ) -> NexusOperationHandle[Any]: + """Called for every :py:meth:`NexusClient.start_operation` call. + + .. warning:: + This API is experimental and unstable. + """ + return await self.next.start_nexus_operation(input) + + async def describe_nexus_operation( + self, input: DescribeNexusOperationInput + ) -> NexusOperationExecutionDescription: + """Called for every :py:meth:`NexusOperationHandle.describe` call. + + .. warning:: + This API is experimental and unstable. + """ + return await self.next.describe_nexus_operation(input) + + async def get_nexus_operation_result( + self, input: GetNexusOperationResultInput + ) -> Any: + """Called for every :py:meth:`NexusOperationHandle.result` call. + + .. warning:: + This API is experimental and unstable. + """ + return await self.next.get_nexus_operation_result(input) + + async def cancel_nexus_operation(self, input: CancelNexusOperationInput) -> None: + """Called for every :py:meth:`NexusOperationHandle.cancel` call. + + .. warning:: + This API is experimental and unstable. + """ + await self.next.cancel_nexus_operation(input) + + async def terminate_nexus_operation( + self, input: TerminateNexusOperationInput + ) -> None: + """Called for every :py:meth:`NexusOperationHandle.terminate` call. + + .. warning:: + This API is experimental and unstable. + """ + await self.next.terminate_nexus_operation(input) + + def list_nexus_operations( + self, input: ListNexusOperationsInput + ) -> NexusOperationExecutionAsyncIterator: + """Called for every :py:meth:`Client.list_nexus_operations` call. + + .. warning:: + This API is experimental and unstable. + """ + return self.next.list_nexus_operations(input) + + async def count_nexus_operations( + self, input: CountNexusOperationsInput + ) -> NexusOperationExecutionCount: + """Called for every :py:meth:`Client.count_nexus_operations` call. + + .. warning:: + This API is experimental and unstable. + """ + return await self.next.count_nexus_operations(input) diff --git a/temporalio/client/_nexus.py b/temporalio/client/_nexus.py new file mode 100644 index 000000000..991ab34a3 --- /dev/null +++ b/temporalio/client/_nexus.py @@ -0,0 +1,1212 @@ +from __future__ import annotations + +from abc import ABC, abstractmethod +from collections.abc import Callable, Mapping, Sequence +from dataclasses import dataclass, field +from datetime import datetime, timedelta, timezone +from typing import TYPE_CHECKING, Any, Generic, cast, overload + +import nexusrpc +from nexusrpc import InputT, OutputT +from typing_extensions import Self + +import temporalio.api.nexus.v1 +import temporalio.api.workflowservice.v1 +import temporalio.common +import temporalio.converter +import temporalio.converter._search_attributes +import temporalio.exceptions +import temporalio.nexus._util +from temporalio.types import NexusServiceType, ReturnType + +from ._helpers import _decode_user_metadata +from ._interceptor import ( + CancelNexusOperationInput, + DescribeNexusOperationInput, + GetNexusOperationResultInput, + ListNexusOperationsInput, + StartNexusOperationInput, + TerminateNexusOperationInput, +) + +if TYPE_CHECKING: + from ._client import Client + + +@dataclass +class NexusOperationExecutionCancellationInfo: + """Cancellation information for a Nexus Operation. + + .. warning:: + This API is experimental and unstable. + """ + + raw: temporalio.api.nexus.v1.NexusOperationExecutionCancellationInfo + """Underlying protobuf cancellation info.""" + + requested_time: datetime | None + """The time when cancellation was requested.""" + + state: temporalio.common.NexusOperationCancellationState + """The current state of the cancellation request.""" + + attempt: int + """The number of attempts made to deliver the cancel operation request.""" + + last_attempt_complete_time: datetime | None + """The time when the last attempt completed.""" + + next_attempt_schedule_time: datetime | None + """The time when the next attempt is scheduled.""" + + last_attempt_failure: BaseException | None + """The last attempt's failure, if any.""" + + blocked_reason: str + """Blocked reason provides additional information if the cancellation state is BLOCKED.""" + + reason: str + """The reason specified in the cancellation request.""" + + @classmethod + async def _from_cancellation_info( + cls, + info: temporalio.api.nexus.v1.NexusOperationExecutionCancellationInfo, + data_converter: temporalio.converter.DataConverter, + ) -> Self: + """Create from raw proto nexus operation cancellation info.""" + return cls( + raw=info, + requested_time=( + info.requested_time.ToDatetime(tzinfo=timezone.utc) + if info.HasField("requested_time") + else None + ), + state=( + temporalio.common.NexusOperationCancellationState(info.state) + if info.state + else temporalio.common.NexusOperationCancellationState.UNSPECIFIED + ), + attempt=info.attempt, + last_attempt_complete_time=( + info.last_attempt_complete_time.ToDatetime(tzinfo=timezone.utc) + if info.HasField("last_attempt_complete_time") + else None + ), + next_attempt_schedule_time=( + info.next_attempt_schedule_time.ToDatetime(tzinfo=timezone.utc) + if info.HasField("next_attempt_schedule_time") + else None + ), + last_attempt_failure=( + cast( + BaseException | None, + await data_converter.decode_failure(info.last_attempt_failure), + ) + if info.HasField("last_attempt_failure") + else None + ), + blocked_reason=info.blocked_reason, + reason=info.reason, + ) + + +@dataclass +class NexusOperationExecution: + """Info for a standalone Nexus operation execution, from list response. + + .. warning:: + This API is experimental and unstable. + """ + + operation_id: str + """Unique identifier of this operation.""" + + run_id: str + """Run ID of the standalone Nexus operation.""" + + endpoint: str + """Endpoint name.""" + + service: str + """Service name.""" + + operation: str + """Operation name.""" + + schedule_time: datetime | None + """Time the operation was originally scheduled.""" + + close_time: datetime | None + """Time the operation reached a terminal status, if closed.""" + + status: temporalio.common.NexusOperationExecutionStatus + """Current status of the operation.""" + + search_attributes: temporalio.common.TypedSearchAttributes + """Current set of search attributes if any.""" + + state_transition_count: int + """Number of state transitions.""" + + execution_duration: timedelta | None + """Duration from scheduled to close time, only populated if closed.""" + + raw_info: ( + temporalio.api.nexus.v1.NexusOperationExecutionListInfo + | temporalio.api.nexus.v1.NexusOperationExecutionInfo + ) + """Underlying protobuf info.""" + + @classmethod + def _from_raw_info( + cls, info: temporalio.api.nexus.v1.NexusOperationExecutionListInfo + ) -> Self: + """Create from raw proto nexus operation list info.""" + return cls( + operation_id=info.operation_id, + run_id=info.run_id, + endpoint=info.endpoint, + service=info.service, + operation=info.operation, + schedule_time=( + info.schedule_time.ToDatetime(tzinfo=timezone.utc) + if info.HasField("schedule_time") + else None + ), + close_time=( + info.close_time.ToDatetime(tzinfo=timezone.utc) + if info.HasField("close_time") + else None + ), + status=( + temporalio.common.NexusOperationExecutionStatus(info.status) + if info.status + else temporalio.common.NexusOperationExecutionStatus.UNSPECIFIED + ), + search_attributes=temporalio.converter.decode_typed_search_attributes( + info.search_attributes + ), + state_transition_count=info.state_transition_count, + execution_duration=( + info.execution_duration.ToTimedelta() + if info.HasField("execution_duration") + else None + ), + raw_info=info, + ) + + +@dataclass +class NexusOperationExecutionDescription(NexusOperationExecution): + """Detailed information about a standalone Nexus operation execution. + + .. warning:: + This API is experimental and unstable. + """ + + raw_description: temporalio.api.nexus.v1.NexusOperationExecutionInfo + """Underlying protobuf description info.""" + + state: temporalio.common.PendingNexusOperationExecutionState + """More detailed breakdown if status is :py:attr:`NexusOperationExecutionStatus.RUNNING`.""" + + schedule_to_close_timeout: timedelta | None + """Schedule-to-close timeout for this operation.""" + + schedule_to_start_timeout: timedelta | None + """Schedule-to-start timeout for this operation.""" + + start_to_close_timeout: timedelta | None + """Start-to-close timeout for this operation.""" + + attempt: int + """Current attempt number.""" + + expiration_time: datetime | None + """Scheduled time plus schedule_to_close_timeout.""" + + last_attempt_complete_time: datetime | None + """Time when the last attempt completed.""" + + next_attempt_schedule_time: datetime | None + """Time when the next attempt will be scheduled.""" + + last_attempt_failure: BaseException | None + """Failure from the last failed attempt, if any.""" + + blocked_reason: str | None + """Reason the operation is blocked, if any.""" + + request_id: str + """Server-generated request ID used as an idempotency token.""" + + operation_token: str | None + """Operation token is only set for asynchronous operations after a successful start_operation call.""" + + identity: str + """Identity of the client that started this operation.""" + + cancellation_info: NexusOperationExecutionCancellationInfo | None + """Cancellation info if cancellation was requested.""" + + _data_converter: temporalio.converter.DataConverter = field( + kw_only=True, compare=False, repr=False + ) + _static_summary: str | None = field( + kw_only=True, default=None, compare=False, repr=False + ) + _static_details: str | None = field( + kw_only=True, default=None, compare=False, repr=False + ) + _metadata_decoded: bool = field( + kw_only=True, default=False, compare=False, repr=False + ) + + async def static_summary(self) -> str | None: + """Gets the single-line fixed summary for this Nexus operation execution that may appear in + UI/CLI. This can be in single-line Temporal markdown format. + """ + if not self._metadata_decoded: + await self._decode_metadata() + return self._static_summary + + async def static_details(self) -> str | None: + """Gets the general fixed details for this Nexus operation execution that may appear in UI/CLI. + This can be in Temporal markdown format and can span multiple lines. + """ + if not self._metadata_decoded: + await self._decode_metadata() + return self._static_details + + async def _decode_metadata(self) -> None: + """Internal method to decode metadata lazily.""" + self._static_summary, self._static_details = await _decode_user_metadata( + self._data_converter, self.raw_description.user_metadata + ) + self._metadata_decoded = True + + @classmethod + async def _from_execution_info( + cls, + info: temporalio.api.nexus.v1.NexusOperationExecutionInfo, + data_converter: temporalio.converter.DataConverter, + ) -> Self: + """Create from raw proto nexus operation execution info.""" + return cls( + _data_converter=data_converter, + operation_id=info.operation_id, + run_id=info.run_id, + endpoint=info.endpoint, + service=info.service, + operation=info.operation, + schedule_time=( + info.schedule_time.ToDatetime(tzinfo=timezone.utc) + if info.HasField("schedule_time") + else None + ), + close_time=( + info.close_time.ToDatetime(tzinfo=timezone.utc) + if info.HasField("close_time") + else None + ), + status=( + temporalio.common.NexusOperationExecutionStatus(info.status) + if info.status + else temporalio.common.NexusOperationExecutionStatus.UNSPECIFIED + ), + search_attributes=temporalio.converter.decode_typed_search_attributes( + info.search_attributes + ), + state_transition_count=info.state_transition_count, + execution_duration=( + info.execution_duration.ToTimedelta() + if info.HasField("execution_duration") + else None + ), + raw_info=info, + raw_description=info, + state=( + temporalio.common.PendingNexusOperationExecutionState(info.state) + if info.state + else temporalio.common.PendingNexusOperationExecutionState.UNSPECIFIED + ), + schedule_to_close_timeout=( + info.schedule_to_close_timeout.ToTimedelta() + if info.HasField("schedule_to_close_timeout") + else None + ), + schedule_to_start_timeout=( + info.schedule_to_start_timeout.ToTimedelta() + if info.HasField("schedule_to_start_timeout") + else None + ), + start_to_close_timeout=( + info.start_to_close_timeout.ToTimedelta() + if info.HasField("start_to_close_timeout") + else None + ), + attempt=info.attempt, + expiration_time=( + info.expiration_time.ToDatetime(tzinfo=timezone.utc) + if info.HasField("expiration_time") + else None + ), + last_attempt_complete_time=( + info.last_attempt_complete_time.ToDatetime(tzinfo=timezone.utc) + if info.HasField("last_attempt_complete_time") + else None + ), + last_attempt_failure=( + cast( + BaseException | None, + await data_converter.decode_failure(info.last_attempt_failure), + ) + if info.HasField("last_attempt_failure") + else None + ), + next_attempt_schedule_time=( + info.next_attempt_schedule_time.ToDatetime(tzinfo=timezone.utc) + if info.HasField("next_attempt_schedule_time") + else None + ), + blocked_reason=info.blocked_reason if info.blocked_reason else None, + request_id=info.request_id, + operation_token=info.operation_token if info.operation_token else None, + identity=info.identity, + cancellation_info=( + await NexusOperationExecutionCancellationInfo._from_cancellation_info( + info.cancellation_info, data_converter + ) + if info.HasField("cancellation_info") + else None + ), + ) + + +@dataclass(frozen=True) +class NexusOperationExecutionCountAggregationGroup: + """A single aggregation group from a count nexus operations call. + + .. warning:: + This API is experimental and unstable. + """ + + count: int + """Count for this group.""" + + group_values: Sequence[temporalio.common.SearchAttributeValue] + """Values that define this group.""" + + @staticmethod + def _from_raw( + raw: temporalio.api.workflowservice.v1.CountNexusOperationExecutionsResponse.AggregationGroup, + ) -> NexusOperationExecutionCountAggregationGroup: + return NexusOperationExecutionCountAggregationGroup( + count=raw.count, + group_values=[ + temporalio.converter._search_attributes._decode_search_attribute_value( + v + ) + for v in raw.group_values + ], + ) + + +@dataclass +class NexusOperationExecutionCount: + """Representation of a count from a count nexus operations call. + + .. warning:: + This API is experimental and unstable. + """ + + count: int + """Approximate number of operations matching the original query. + + If the query had a group-by clause, this is simply the sum of all the counts + in :py:attr:`groups`. + """ + + groups: Sequence[NexusOperationExecutionCountAggregationGroup] + """Groups if the query had a group-by clause, or empty if not.""" + + @staticmethod + def _from_raw( + resp: temporalio.api.workflowservice.v1.CountNexusOperationExecutionsResponse, + ) -> NexusOperationExecutionCount: + """Create from raw proto response.""" + return NexusOperationExecutionCount( + count=resp.count, + groups=[ + NexusOperationExecutionCountAggregationGroup._from_raw(g) + for g in resp.groups + ], + ) + + +class NexusOperationFailureError(temporalio.exceptions.TemporalError): + """Error that occurs when a Nexus operation is unsuccessful. + + .. warning:: + This API is experimental and unstable. + """ + + def __init__(self, *, cause: BaseException) -> None: + """Create Nexus operation failure error.""" + super().__init__("Nexus operation execution failed") + self.__cause__ = cause + + @property + def cause(self) -> BaseException: + """Cause of the Nexus operation failure.""" + assert self.__cause__ + return self.__cause__ + + +class NexusClient(ABC, Generic[NexusServiceType]): + """Client for starting standalone Nexus operations. + + .. warning:: + This API is experimental and unstable. + + Use :py:meth:`Client.create_nexus_client` to create a client. + """ + + # Overload for nexusrpc.Operation with input + @overload + @abstractmethod + async def start_operation( + self, + operation: nexusrpc.Operation[InputT, OutputT], + arg: InputT, + *, + id: str, + id_reuse_policy: temporalio.common.NexusOperationIDReusePolicy = temporalio.common.NexusOperationIDReusePolicy.ALLOW_DUPLICATE, + id_conflict_policy: temporalio.common.NexusOperationIDConflictPolicy = temporalio.common.NexusOperationIDConflictPolicy.FAIL, + schedule_to_close_timeout: timedelta | None = None, + schedule_to_start_timeout: timedelta | None = None, + start_to_close_timeout: timedelta | None = None, + search_attributes: temporalio.common.TypedSearchAttributes | None = None, + summary: str | None = None, + headers: Mapping[str, str] | None = None, + rpc_metadata: Mapping[str, str | bytes] = {}, + rpc_timeout: timedelta | None = None, + ) -> NexusOperationHandle[OutputT]: ... + + # Overload for Callable with result_type + @overload + @abstractmethod + async def start_operation( + self, + operation: Callable[..., Any], + arg: Any, + *, + id: str, + id_reuse_policy: temporalio.common.NexusOperationIDReusePolicy = temporalio.common.NexusOperationIDReusePolicy.ALLOW_DUPLICATE, + id_conflict_policy: temporalio.common.NexusOperationIDConflictPolicy = temporalio.common.NexusOperationIDConflictPolicy.FAIL, + result_type: type[OutputT], + schedule_to_close_timeout: timedelta | None = None, + schedule_to_start_timeout: timedelta | None = None, + start_to_close_timeout: timedelta | None = None, + search_attributes: temporalio.common.TypedSearchAttributes | None = None, + summary: str | None = None, + headers: Mapping[str, str] | None = None, + rpc_metadata: Mapping[str, str | bytes] = {}, + rpc_timeout: timedelta | None = None, + ) -> NexusOperationHandle[OutputT]: ... + + # Overload for Callable without result_type + @overload + @abstractmethod + async def start_operation( + self, + operation: Callable[..., Any], + arg: Any, + *, + id: str, + id_reuse_policy: temporalio.common.NexusOperationIDReusePolicy = temporalio.common.NexusOperationIDReusePolicy.ALLOW_DUPLICATE, + id_conflict_policy: temporalio.common.NexusOperationIDConflictPolicy = temporalio.common.NexusOperationIDConflictPolicy.FAIL, + schedule_to_close_timeout: timedelta | None = None, + schedule_to_start_timeout: timedelta | None = None, + start_to_close_timeout: timedelta | None = None, + search_attributes: temporalio.common.TypedSearchAttributes | None = None, + summary: str | None = None, + headers: Mapping[str, str] | None = None, + rpc_metadata: Mapping[str, str | bytes] = {}, + rpc_timeout: timedelta | None = None, + ) -> NexusOperationHandle[Any]: ... + + # Overload for str with result_type + @overload + @abstractmethod + async def start_operation( + self, + operation: str, + arg: Any, + *, + id: str, + id_reuse_policy: temporalio.common.NexusOperationIDReusePolicy = temporalio.common.NexusOperationIDReusePolicy.ALLOW_DUPLICATE, + id_conflict_policy: temporalio.common.NexusOperationIDConflictPolicy = temporalio.common.NexusOperationIDConflictPolicy.FAIL, + result_type: type[OutputT], + schedule_to_close_timeout: timedelta | None = None, + schedule_to_start_timeout: timedelta | None = None, + start_to_close_timeout: timedelta | None = None, + search_attributes: temporalio.common.TypedSearchAttributes | None = None, + summary: str | None = None, + headers: Mapping[str, str] | None = None, + rpc_metadata: Mapping[str, str | bytes] = {}, + rpc_timeout: timedelta | None = None, + ) -> NexusOperationHandle[OutputT]: ... + + # Overload for str without result_type + @overload + @abstractmethod + async def start_operation( + self, + operation: str, + arg: Any, + *, + id: str, + id_reuse_policy: temporalio.common.NexusOperationIDReusePolicy = temporalio.common.NexusOperationIDReusePolicy.ALLOW_DUPLICATE, + id_conflict_policy: temporalio.common.NexusOperationIDConflictPolicy = temporalio.common.NexusOperationIDConflictPolicy.FAIL, + schedule_to_close_timeout: timedelta | None = None, + schedule_to_start_timeout: timedelta | None = None, + start_to_close_timeout: timedelta | None = None, + search_attributes: temporalio.common.TypedSearchAttributes | None = None, + summary: str | None = None, + headers: Mapping[str, str] | None = None, + rpc_metadata: Mapping[str, str | bytes] = {}, + rpc_timeout: timedelta | None = None, + ) -> NexusOperationHandle[Any]: ... + + @abstractmethod + async def start_operation( + self, + operation: nexusrpc.Operation[Any, Any] | str | Callable[..., Any], + arg: Any, + *, + id: str, + id_reuse_policy: temporalio.common.NexusOperationIDReusePolicy = temporalio.common.NexusOperationIDReusePolicy.ALLOW_DUPLICATE, + id_conflict_policy: temporalio.common.NexusOperationIDConflictPolicy = temporalio.common.NexusOperationIDConflictPolicy.FAIL, + result_type: type | None = None, + schedule_to_close_timeout: timedelta | None = None, + schedule_to_start_timeout: timedelta | None = None, + start_to_close_timeout: timedelta | None = None, + search_attributes: temporalio.common.TypedSearchAttributes | None = None, + summary: str | None = None, + headers: Mapping[str, str] | None = None, + rpc_metadata: Mapping[str, str | bytes] = {}, + rpc_timeout: timedelta | None = None, + ) -> NexusOperationHandle[Any]: + """Start a Nexus operation and return a handle. + + .. warning:: + This API is experimental and unstable. + + Args: + operation: The operation to start. Can be a ``nexusrpc.Operation``, + a callable operation method, or a string name. + arg: Input argument for the operation. + id: Unique identifier for this operation. + id_reuse_policy: Policy for reusing operation IDs. + id_conflict_policy: Policy for handling ID conflicts. + result_type: The result type to deserialize into. + schedule_to_close_timeout: End-to-end timeout for the Nexus + operation. If unset, defaults to the maximum allowed by the + Temporal server. + schedule_to_start_timeout: Maximum time to wait for the operation + to be started (or completed, if synchronous) by the handler. If + unset, no schedule-to-start timeout is enforced. + start_to_close_timeout: Maximum time to wait for an asynchronous + operation to complete after it has been started. Only applies to + asynchronous operations and is ignored for synchronous + operations. If unset, no start-to-close timeout is enforced. + search_attributes: Search attributes for the operation. + summary: Summary for the operation. + headers: Headers to attach to the Nexus request. + rpc_metadata: Headers used on the RPC call. + rpc_timeout: Optional RPC deadline to set for the RPC call. + + Returns: + A handle to the started operation. + """ + ... + + # Overload for nexusrpc.Operation with input + @overload + @abstractmethod + async def execute_operation( + self, + operation: nexusrpc.Operation[InputT, OutputT], + arg: InputT, + *, + id: str, + id_reuse_policy: temporalio.common.NexusOperationIDReusePolicy = temporalio.common.NexusOperationIDReusePolicy.ALLOW_DUPLICATE, + id_conflict_policy: temporalio.common.NexusOperationIDConflictPolicy = temporalio.common.NexusOperationIDConflictPolicy.FAIL, + schedule_to_close_timeout: timedelta | None = None, + schedule_to_start_timeout: timedelta | None = None, + start_to_close_timeout: timedelta | None = None, + search_attributes: temporalio.common.TypedSearchAttributes | None = None, + summary: str | None = None, + headers: Mapping[str, str] | None = None, + rpc_metadata: Mapping[str, str | bytes] = {}, + rpc_timeout: timedelta | None = None, + ) -> OutputT: ... + + # Overload for Callable with result_type + @overload + @abstractmethod + async def execute_operation( + self, + operation: Callable[..., Any], + arg: Any, + *, + id: str, + id_reuse_policy: temporalio.common.NexusOperationIDReusePolicy = temporalio.common.NexusOperationIDReusePolicy.ALLOW_DUPLICATE, + id_conflict_policy: temporalio.common.NexusOperationIDConflictPolicy = temporalio.common.NexusOperationIDConflictPolicy.FAIL, + result_type: type[OutputT], + schedule_to_close_timeout: timedelta | None = None, + schedule_to_start_timeout: timedelta | None = None, + start_to_close_timeout: timedelta | None = None, + search_attributes: temporalio.common.TypedSearchAttributes | None = None, + summary: str | None = None, + headers: Mapping[str, str] | None = None, + rpc_metadata: Mapping[str, str | bytes] = {}, + rpc_timeout: timedelta | None = None, + ) -> OutputT: ... + + # Overload for Callable without result_type + @overload + @abstractmethod + async def execute_operation( + self, + operation: Callable[..., Any], + arg: Any, + *, + id: str, + id_reuse_policy: temporalio.common.NexusOperationIDReusePolicy = temporalio.common.NexusOperationIDReusePolicy.ALLOW_DUPLICATE, + id_conflict_policy: temporalio.common.NexusOperationIDConflictPolicy = temporalio.common.NexusOperationIDConflictPolicy.FAIL, + schedule_to_close_timeout: timedelta | None = None, + schedule_to_start_timeout: timedelta | None = None, + start_to_close_timeout: timedelta | None = None, + search_attributes: temporalio.common.TypedSearchAttributes | None = None, + summary: str | None = None, + headers: Mapping[str, str] | None = None, + rpc_metadata: Mapping[str, str | bytes] = {}, + rpc_timeout: timedelta | None = None, + ) -> Any: ... + + # Overload for str with result_type + @overload + @abstractmethod + async def execute_operation( + self, + operation: str, + arg: Any, + *, + id: str, + id_reuse_policy: temporalio.common.NexusOperationIDReusePolicy = temporalio.common.NexusOperationIDReusePolicy.ALLOW_DUPLICATE, + id_conflict_policy: temporalio.common.NexusOperationIDConflictPolicy = temporalio.common.NexusOperationIDConflictPolicy.FAIL, + result_type: type[OutputT], + schedule_to_close_timeout: timedelta | None = None, + schedule_to_start_timeout: timedelta | None = None, + start_to_close_timeout: timedelta | None = None, + search_attributes: temporalio.common.TypedSearchAttributes | None = None, + summary: str | None = None, + headers: Mapping[str, str] | None = None, + rpc_metadata: Mapping[str, str | bytes] = {}, + rpc_timeout: timedelta | None = None, + ) -> OutputT: ... + + # Overload for str without result_type + @overload + @abstractmethod + async def execute_operation( + self, + operation: str, + arg: Any, + *, + id: str, + id_reuse_policy: temporalio.common.NexusOperationIDReusePolicy = temporalio.common.NexusOperationIDReusePolicy.ALLOW_DUPLICATE, + id_conflict_policy: temporalio.common.NexusOperationIDConflictPolicy = temporalio.common.NexusOperationIDConflictPolicy.FAIL, + schedule_to_close_timeout: timedelta | None = None, + schedule_to_start_timeout: timedelta | None = None, + start_to_close_timeout: timedelta | None = None, + search_attributes: temporalio.common.TypedSearchAttributes | None = None, + summary: str | None = None, + headers: Mapping[str, str] | None = None, + rpc_metadata: Mapping[str, str | bytes] = {}, + rpc_timeout: timedelta | None = None, + ) -> Any: ... + + @abstractmethod + async def execute_operation( + self, + operation: nexusrpc.Operation[Any, Any] | str | Callable[..., Any], + arg: Any, + *, + id: str, + id_reuse_policy: temporalio.common.NexusOperationIDReusePolicy = temporalio.common.NexusOperationIDReusePolicy.ALLOW_DUPLICATE, + id_conflict_policy: temporalio.common.NexusOperationIDConflictPolicy = temporalio.common.NexusOperationIDConflictPolicy.FAIL, + result_type: type | None = None, + schedule_to_close_timeout: timedelta | None = None, + schedule_to_start_timeout: timedelta | None = None, + start_to_close_timeout: timedelta | None = None, + search_attributes: temporalio.common.TypedSearchAttributes | None = None, + summary: str | None = None, + headers: Mapping[str, str] | None = None, + rpc_metadata: Mapping[str, str | bytes] = {}, + rpc_timeout: timedelta | None = None, + ) -> Any: + """Start a Nexus operation and wait for its result. + + .. warning:: + This API is experimental and unstable. + + This is a shortcut for ``await (await nexus_client.start_operation(...)).result()``. + + Args: + operation: The operation to execute. Can be a ``nexusrpc.Operation``, + a callable operation method, or a string name. + arg: Input argument for the operation. + id: Unique identifier for this operation. + id_reuse_policy: Policy for reusing operation IDs. + id_conflict_policy: Policy for handling ID conflicts. + result_type: The result type to deserialize into. + schedule_to_close_timeout: End-to-end timeout for the Nexus + operation. If unset, defaults to the maximum allowed by the + Temporal server. + schedule_to_start_timeout: Maximum time to wait for the operation + to be started (or completed, if synchronous) by the handler. If + unset, no schedule-to-start timeout is enforced. + start_to_close_timeout: Maximum time to wait for an asynchronous + operation to complete after it has been started. Only applies to + asynchronous operations and is ignored for synchronous + operations. If unset, no start-to-close timeout is enforced. + search_attributes: Search attributes for the operation. + summary: Summary for the operation. + headers: Headers to attach to the Nexus request. + rpc_metadata: Headers used on the RPC call. + rpc_timeout: Optional RPC deadline to set for the RPC call. + + Returns: + The result of the operation. + """ + ... + + +class _NexusClient(NexusClient[NexusServiceType]): # pyright: ignore[reportUnusedClass] + """Concrete implementation of NexusClient.""" + + def __init__( + self, + client: Client, + service: type[NexusServiceType] | str, + endpoint: str, + ) -> None: + self._client = client + if isinstance(service, str): + self._service_name = service + elif service_defn := nexusrpc.get_service_definition(service): + self._service_name = service_defn.name + else: + self._service_name = service.__name__ + self._endpoint = endpoint + + def _resolve_operation( + self, + operation: nexusrpc.Operation[Any, Any] | str | Callable[..., Any], + ) -> tuple[str, type | None]: + """Resolve an operation to its name and output type.""" + if isinstance(operation, str): + return operation, None + elif isinstance(operation, nexusrpc.Operation): + return operation.name, operation.output_type + elif callable(operation): + _, op = temporalio.nexus._util.get_operation_factory(operation) + if isinstance(op, nexusrpc.Operation): + return op.name, op.output_type + else: + raise ValueError( + f"Operation callable is not a Nexus operation: {operation}" + ) + else: + raise ValueError( # pyright: ignore[reportUnreachable] + f"Operation is not resolvable as a Nexus operation: {operation}" + ) + + async def start_operation( + self, + operation: nexusrpc.Operation[Any, Any] | str | Callable[..., Any], + arg: Any, + *, + id: str, + id_reuse_policy: temporalio.common.NexusOperationIDReusePolicy = temporalio.common.NexusOperationIDReusePolicy.ALLOW_DUPLICATE, + id_conflict_policy: temporalio.common.NexusOperationIDConflictPolicy = temporalio.common.NexusOperationIDConflictPolicy.FAIL, + result_type: type | None = None, + schedule_to_close_timeout: timedelta | None = None, + schedule_to_start_timeout: timedelta | None = None, + start_to_close_timeout: timedelta | None = None, + search_attributes: temporalio.common.TypedSearchAttributes | None = None, + summary: str | None = None, + headers: Mapping[str, str] | None = None, + rpc_metadata: Mapping[str, str | bytes] = {}, + rpc_timeout: timedelta | None = None, + ) -> NexusOperationHandle[Any]: + """Start a Nexus operation and return a handle. + + .. warning:: + This API is experimental and unstable. + """ + op_name, output_type = self._resolve_operation(operation) + final_result_type: type | None = result_type or output_type + + return await self._client._impl.start_nexus_operation( + StartNexusOperationInput( + operation=op_name, + arg=arg, + id=id, + endpoint=self._endpoint, + service=self._service_name, + result_type=final_result_type, + schedule_to_close_timeout=schedule_to_close_timeout, + schedule_to_start_timeout=schedule_to_start_timeout, + start_to_close_timeout=start_to_close_timeout, + id_reuse_policy=id_reuse_policy, + id_conflict_policy=id_conflict_policy, + search_attributes=search_attributes, + summary=summary, + headers=dict(headers) if headers else {}, + rpc_metadata=rpc_metadata, + rpc_timeout=rpc_timeout, + ) + ) + + async def execute_operation( + self, + operation: nexusrpc.Operation[Any, Any] | str | Callable[..., Any], + arg: Any, + *, + id: str, + id_reuse_policy: temporalio.common.NexusOperationIDReusePolicy = temporalio.common.NexusOperationIDReusePolicy.ALLOW_DUPLICATE, + id_conflict_policy: temporalio.common.NexusOperationIDConflictPolicy = temporalio.common.NexusOperationIDConflictPolicy.FAIL, + result_type: type | None = None, + schedule_to_close_timeout: timedelta | None = None, + schedule_to_start_timeout: timedelta | None = None, + start_to_close_timeout: timedelta | None = None, + search_attributes: temporalio.common.TypedSearchAttributes | None = None, + summary: str | None = None, + headers: Mapping[str, str] | None = None, + rpc_metadata: Mapping[str, str | bytes] = {}, + rpc_timeout: timedelta | None = None, + ) -> Any: + """Start a Nexus operation and wait for its result. + + .. warning:: + This API is experimental and unstable. + """ + handle = await self.start_operation( + operation, + arg, + id=id, + id_reuse_policy=id_reuse_policy, + id_conflict_policy=id_conflict_policy, + result_type=result_type, + schedule_to_close_timeout=schedule_to_close_timeout, + schedule_to_start_timeout=schedule_to_start_timeout, + start_to_close_timeout=start_to_close_timeout, + search_attributes=search_attributes, + summary=summary, + headers=headers, + rpc_metadata=rpc_metadata, + rpc_timeout=rpc_timeout, + ) + return await handle.result() + + +class NexusOperationHandle(Generic[ReturnType]): + """Handle representing a standalone Nexus operation execution. + + .. warning:: + This API is experimental and unstable. + """ + + def __init__( + self, + client: Client, + operation_id: str, + *, + run_id: str | None = None, + result_type: type | None = None, + endpoint: str = "", + service: str = "", + ) -> None: + """Create nexus operation handle.""" + self._client = client + self._operation_id = operation_id + self._run_id = run_id + self._result_type = result_type + self._endpoint = endpoint + self._service = service + # the default value is `_arg_unset` because ReturnType could be None + self._known_outcome: ReturnType | NexusOperationFailureError | object = ( + temporalio.common._arg_unset + ) + + @property + def operation_id(self) -> str: + """ID of the operation.""" + return self._operation_id + + @property + def run_id(self) -> str | None: + """Run ID of the operation.""" + return self._run_id + + @property + def endpoint(self) -> str: + """Endpoint name.""" + return self._endpoint + + @property + def service(self) -> str: + """Service name.""" + return self._service + + async def result( + self, + *, + rpc_metadata: Mapping[str, str | bytes] = {}, + rpc_timeout: timedelta | None = None, + ) -> ReturnType: + """Wait for result of the Nexus operation. + + .. warning:: + This API is experimental and unstable. + + The result may already be known if this method has been called before, + in which case no network call is made. Otherwise the result will be + polled for until it is available. + + Args: + rpc_metadata: Headers used on the RPC call. Keys here override + client-level RPC metadata keys. + rpc_timeout: Optional RPC deadline to set for each RPC call. Note: + this is the timeout for each RPC call while polling, not a + timeout for the function as a whole. If an individual RPC + times out, it will be retried until the result is available. + + Returns: + The result of the operation. + + Raises: + NexusOperationFailureError: If the operation completed with a failure. + RPCError: Operation result could not be fetched for some reason. + """ + if self._known_outcome is temporalio.common._arg_unset: + try: + self._known_outcome = ( + await self._client._impl.get_nexus_operation_result( + GetNexusOperationResultInput( + operation_id=self._operation_id, + run_id=self._run_id, + result_type=self._result_type, + rpc_metadata=rpc_metadata, + rpc_timeout=rpc_timeout, + ) + ) + ) + return cast(ReturnType, self._known_outcome) + except NexusOperationFailureError as failure: + self._known_outcome = failure + raise + elif isinstance(self._known_outcome, NexusOperationFailureError): + raise self._known_outcome + else: + return cast(ReturnType, self._known_outcome) + + async def describe( + self, + *, + rpc_metadata: Mapping[str, str | bytes] = {}, + rpc_timeout: timedelta | None = None, + ) -> NexusOperationExecutionDescription: + """Describe the Nexus operation execution. + + .. warning:: + This API is experimental and unstable. + + Args: + rpc_metadata: Headers used on the RPC call. + rpc_timeout: Optional RPC deadline to set for the RPC call. + + Returns: + Nexus operation execution description. + """ + return await self._client._impl.describe_nexus_operation( + DescribeNexusOperationInput( + operation_id=self._operation_id, + run_id=self._run_id, + rpc_metadata=rpc_metadata, + rpc_timeout=rpc_timeout, + ) + ) + + async def cancel( + self, + *, + reason: str | None = None, + rpc_metadata: Mapping[str, str | bytes] = {}, + rpc_timeout: timedelta | None = None, + ) -> None: + """Request cancellation of the Nexus operation. + + .. warning:: + This API is experimental and unstable. + + Args: + reason: Reason for the cancellation. + rpc_metadata: Headers used on the RPC call. + rpc_timeout: Optional RPC deadline to set for the RPC call. + """ + await self._client._impl.cancel_nexus_operation( + CancelNexusOperationInput( + operation_id=self._operation_id, + run_id=self._run_id, + reason=reason, + rpc_metadata=rpc_metadata, + rpc_timeout=rpc_timeout, + ) + ) + + async def terminate( + self, + *, + reason: str | None = None, + rpc_metadata: Mapping[str, str | bytes] = {}, + rpc_timeout: timedelta | None = None, + ) -> None: + """Terminate the Nexus operation execution immediately. + + .. warning:: + This API is experimental and unstable. + + Args: + reason: Reason for the termination. + rpc_metadata: Headers used on the RPC call. + rpc_timeout: Optional RPC deadline to set for the RPC call. + """ + await self._client._impl.terminate_nexus_operation( + TerminateNexusOperationInput( + operation_id=self._operation_id, + run_id=self._run_id, + reason=reason, + rpc_metadata=rpc_metadata, + rpc_timeout=rpc_timeout, + ) + ) + + +class NexusOperationExecutionAsyncIterator: + """Asynchronous iterator for Nexus operation execution values. + + You should typically use ``async for`` on this iterator and not call any of its methods. + + .. warning:: + This API is experimental and unstable. + """ + + def __init__( + self, + client: Client, + input: ListNexusOperationsInput, + ) -> None: + """Create an asynchronous iterator for the given input. + + Users should not create this directly, but rather use + :py:meth:`Client.list_nexus_operations`. + """ + self._client = client + self._input = input + self._next_page_token = input.next_page_token + self._current_page: Sequence[NexusOperationExecution] | None = None + self._current_page_index = 0 + self._limit = input.limit + self._yielded = 0 + + @property + def current_page_index(self) -> int: + """Index of the entry in the current page that will be returned from + the next :py:meth:`__anext__` call. + """ + return self._current_page_index + + @property + def current_page(self) -> Sequence[NexusOperationExecution] | None: + """Current page, if it has been fetched yet.""" + return self._current_page + + @property + def next_page_token(self) -> bytes | None: + """Token for the next page request if any.""" + return self._next_page_token + + async def fetch_next_page(self, *, page_size: int | None = None) -> None: + """Fetch the next page of results. + + Args: + page_size: Override the page size this iterator was originally + created with. + """ + page_size = page_size or self._input.page_size + if self._limit is not None and self._limit - self._yielded < page_size: + page_size = self._limit - self._yielded + + resp = await self._client.workflow_service.list_nexus_operation_executions( + temporalio.api.workflowservice.v1.ListNexusOperationExecutionsRequest( + namespace=self._client.namespace, + page_size=page_size, + next_page_token=self._next_page_token or b"", + query=self._input.query or "", + ), + retry=True, + metadata=self._input.rpc_metadata, + timeout=self._input.rpc_timeout, + ) + + self._current_page = [ + NexusOperationExecution._from_raw_info(v) for v in resp.operations + ] + self._current_page_index = 0 + self._next_page_token = resp.next_page_token or None + + def __aiter__(self) -> NexusOperationExecutionAsyncIterator: + """Return self as the iterator.""" + return self + + async def __anext__(self) -> NexusOperationExecution: + """Get the next execution on this iterator, fetching next page if + necessary. + """ + if self._limit is not None and self._yielded >= self._limit: + raise StopAsyncIteration + while True: + # No page? fetch and continue + if self._current_page is None: + await self.fetch_next_page() + continue + # No more left in page? + if self._current_page_index >= len(self._current_page): + # If there is a next page token, try to get another page and try + # again + if self._next_page_token is not None: + await self.fetch_next_page() + continue + # No more pages means we're done + raise StopAsyncIteration + # Get current, increment page index, and return + ret = self._current_page[self._current_page_index] + self._current_page_index += 1 + self._yielded += 1 + return ret diff --git a/temporalio/common.py b/temporalio/common.py index 2f34c6387..ad75b56b9 100644 --- a/temporalio/common.py +++ b/temporalio/common.py @@ -191,6 +191,150 @@ class ActivityIDConflictPolicy(IntEnum): ) +class NexusOperationIDReusePolicy(IntEnum): + """How already-closed Nexus operation IDs are handled on start. + + .. warning:: + This API is experimental and unstable. + + See :py:class:`temporalio.api.enums.v1.NexusOperationIdReusePolicy`. + """ + + UNSPECIFIED = int( + temporalio.api.enums.v1.NexusOperationIdReusePolicy.NEXUS_OPERATION_ID_REUSE_POLICY_UNSPECIFIED + ) + ALLOW_DUPLICATE = int( + temporalio.api.enums.v1.NexusOperationIdReusePolicy.NEXUS_OPERATION_ID_REUSE_POLICY_ALLOW_DUPLICATE + ) + ALLOW_DUPLICATE_FAILED_ONLY = int( + temporalio.api.enums.v1.NexusOperationIdReusePolicy.NEXUS_OPERATION_ID_REUSE_POLICY_ALLOW_DUPLICATE_FAILED_ONLY + ) + REJECT_DUPLICATE = int( + temporalio.api.enums.v1.NexusOperationIdReusePolicy.NEXUS_OPERATION_ID_REUSE_POLICY_REJECT_DUPLICATE + ) + + +class NexusOperationIDConflictPolicy(IntEnum): + """How already-running Nexus operation IDs are handled on start. + + .. warning:: + This API is experimental and unstable. + + See :py:class:`temporalio.api.enums.v1.NexusOperationIdConflictPolicy`. + """ + + UNSPECIFIED = int( + temporalio.api.enums.v1.NexusOperationIdConflictPolicy.NEXUS_OPERATION_ID_CONFLICT_POLICY_UNSPECIFIED + ) + FAIL = int( + temporalio.api.enums.v1.NexusOperationIdConflictPolicy.NEXUS_OPERATION_ID_CONFLICT_POLICY_FAIL + ) + USE_EXISTING = int( + temporalio.api.enums.v1.NexusOperationIdConflictPolicy.NEXUS_OPERATION_ID_CONFLICT_POLICY_USE_EXISTING + ) + + +class NexusOperationExecutionStatus(IntEnum): + """Status of a standalone Nexus operation execution. + + .. warning:: + This API is experimental and unstable. + + See :py:class:`temporalio.api.enums.v1.NexusOperationExecutionStatus`. + """ + + UNSPECIFIED = int( + temporalio.api.enums.v1.NexusOperationExecutionStatus.NEXUS_OPERATION_EXECUTION_STATUS_UNSPECIFIED + ) + RUNNING = int( + temporalio.api.enums.v1.NexusOperationExecutionStatus.NEXUS_OPERATION_EXECUTION_STATUS_RUNNING + ) + COMPLETED = int( + temporalio.api.enums.v1.NexusOperationExecutionStatus.NEXUS_OPERATION_EXECUTION_STATUS_COMPLETED + ) + FAILED = int( + temporalio.api.enums.v1.NexusOperationExecutionStatus.NEXUS_OPERATION_EXECUTION_STATUS_FAILED + ) + CANCELED = int( + temporalio.api.enums.v1.NexusOperationExecutionStatus.NEXUS_OPERATION_EXECUTION_STATUS_CANCELED + ) + TERMINATED = int( + temporalio.api.enums.v1.NexusOperationExecutionStatus.NEXUS_OPERATION_EXECUTION_STATUS_TERMINATED + ) + TIMED_OUT = int( + temporalio.api.enums.v1.NexusOperationExecutionStatus.NEXUS_OPERATION_EXECUTION_STATUS_TIMED_OUT + ) + + +class PendingNexusOperationExecutionState(IntEnum): + """More detailed breakdown of :py:attr:`NexusOperationExecutionStatus.RUNNING`. + + .. warning:: + This API is experimental and unstable. + + See :py:class:`temporalio.api.enums.v1.PendingNexusOperationState`. + """ + + UNSPECIFIED = int( + temporalio.api.enums.v1.PendingNexusOperationState.PENDING_NEXUS_OPERATION_STATE_UNSPECIFIED + ) + SCHEDULED = int( + temporalio.api.enums.v1.PendingNexusOperationState.PENDING_NEXUS_OPERATION_STATE_SCHEDULED + ) + BACKING_OFF = int( + temporalio.api.enums.v1.PendingNexusOperationState.PENDING_NEXUS_OPERATION_STATE_BACKING_OFF + ) + STARTED = int( + temporalio.api.enums.v1.PendingNexusOperationState.PENDING_NEXUS_OPERATION_STATE_STARTED + ) + BLOCKED = int( + temporalio.api.enums.v1.PendingNexusOperationState.PENDING_NEXUS_OPERATION_STATE_BLOCKED + ) + + +class NexusOperationCancellationState(IntEnum): + """State of a Nexus operation cancellation. + + .. warning:: + This API is experimental and unstable. + """ + + UNSPECIFIED = int( + temporalio.api.enums.v1.NexusOperationCancellationState.NEXUS_OPERATION_CANCELLATION_STATE_UNSPECIFIED + ) + """Default value, unspecified state.""" + + SCHEDULED = int( + temporalio.api.enums.v1.NexusOperationCancellationState.NEXUS_OPERATION_CANCELLATION_STATE_SCHEDULED + ) + """Cancellation request is in the queue waiting to be executed or is currently executing.""" + + BACKING_OFF = int( + temporalio.api.enums.v1.NexusOperationCancellationState.NEXUS_OPERATION_CANCELLATION_STATE_BACKING_OFF + ) + """Cancellation request has failed with a retryable error and is backing off before the next attempt.""" + + SUCCEEDED = int( + temporalio.api.enums.v1.NexusOperationCancellationState.NEXUS_OPERATION_CANCELLATION_STATE_SUCCEEDED + ) + """Cancellation request succeeded.""" + + FAILED = int( + temporalio.api.enums.v1.NexusOperationCancellationState.NEXUS_OPERATION_CANCELLATION_STATE_FAILED + ) + """Cancellation request failed with a non-retryable error.""" + + TIMED_OUT = int( + temporalio.api.enums.v1.NexusOperationCancellationState.NEXUS_OPERATION_CANCELLATION_STATE_TIMED_OUT + ) + """The associated operation timed out - exceeded the user supplied schedule-to-close timeout.""" + + BLOCKED = int( + temporalio.api.enums.v1.NexusOperationCancellationState.NEXUS_OPERATION_CANCELLATION_STATE_BLOCKED + ) + """Cancellation request is blocked, eg: by circuit breaker.""" + + class QueryRejectCondition(IntEnum): """Whether a query should be rejected in certain conditions. diff --git a/temporalio/converter/_failure_converter.py b/temporalio/converter/_failure_converter.py index 5b2bf2fdb..b1511b0b0 100644 --- a/temporalio/converter/_failure_converter.py +++ b/temporalio/converter/_failure_converter.py @@ -236,7 +236,7 @@ def _nexus_handler_error_to_failure( ) -> None: if error.original_failure: self._nexus_failure_to_temporal_failure( - error.original_failure, True, failure + error.original_failure, error.retryable, failure ) else: failure.message = error.message diff --git a/temporalio/exceptions.py b/temporalio/exceptions.py index d386d4327..43a2e1bad 100644 --- a/temporalio/exceptions.py +++ b/temporalio/exceptions.py @@ -90,6 +90,24 @@ def __init__( self.run_id = run_id +class NexusOperationAlreadyStartedError(FailureError): + """Thrown by a client when a Nexus operation execution has already started. + + .. warning:: + This API is experimental and unstable. + + Attributes: + operation_id: ID of the already-started operation. + run_id: Run ID of the already-started operation if available. + """ + + def __init__(self, operation_id: str, *, run_id: str | None = None) -> None: + """Initialize a Nexus operation already started error.""" + super().__init__("Nexus operation execution already started") + self.operation_id = operation_id + self.run_id = run_id + + class ApplicationErrorCategory(IntEnum): """Severity category for your application error. Maps to corresponding client-side logging/metrics behaviors""" diff --git a/temporalio/nexus/_link_conversion.py b/temporalio/nexus/_link_conversion.py index a47c002a9..d02b543d9 100644 --- a/temporalio/nexus/_link_conversion.py +++ b/temporalio/nexus/_link_conversion.py @@ -3,6 +3,7 @@ import logging import re import urllib.parse +from enum import Enum from typing import ( TYPE_CHECKING, Any, @@ -18,13 +19,25 @@ logger = logging.getLogger(__name__) -_LINK_URL_PATH_REGEX = re.compile( +_NEXUS_OPERATION_LINK_URL_PATH_REGEX = re.compile( + r"^/namespaces/(?P[^/]+)/nexus-operations/(?P[^/]+)$" +) + +_WORFKLOW_LINK_URL_PATH_REGEX = re.compile( r"^/namespaces/(?P[^/]+)/workflows/(?P[^/]+)/(?P[^/]+)/history$" ) + + +class _LinkType(str, Enum): + WORKFLOW = temporalio.api.common.v1.Link.WorkflowEvent.DESCRIPTOR.full_name + NEXUS_OPERATION = temporalio.api.common.v1.Link.NexusOperation.DESCRIPTOR.full_name + + LINK_EVENT_ID_PARAM_NAME = "eventID" LINK_EVENT_TYPE_PARAM_NAME = "eventType" LINK_REQUEST_ID_PARAM_NAME = "requestID" LINK_REFERENCE_TYPE_PARAM_NAME = "referenceType" +LINK_RUN_ID_PARAM_NAME = "runID" EVENT_REFERENCE_TYPE = "EventReference" REQUEST_ID_REFERENCE_TYPE = "RequestIdReference" @@ -51,6 +64,49 @@ def workflow_execution_started_event_link_from_workflow_handle( ) +def nexus_link_to_temporal_link( + nexus_link: nexusrpc.Link, +) -> temporalio.api.common.v1.Link | None: + """Convert a nexusrpc link into a Temporal API Link. + + Returns None when the Nexus link type is invalid or unknown. + """ + try: + link_type = _LinkType(nexus_link.type) + except ValueError: + logger.warning(f"Invalid Nexus link: unknown link type {nexus_link}") + return None + + match link_type: + case _LinkType.WORKFLOW: + return nexus_link_to_workflow_event_link(nexus_link) + + case _LinkType.NEXUS_OPERATION: + return nexus_link_to_nexus_operation_link(nexus_link) + + +def temporal_link_to_nexus_link( + temporal_link: temporalio.api.common.v1.Link, +) -> nexusrpc.Link | None: + """Convert a Temporal API Link into a nexusrpc link. + + Returns None when the Temporal link variant is missing. + """ + match temporal_link.WhichOneof("variant"): + case "workflow_event": + return workflow_event_to_nexus_link(temporal_link.workflow_event) + + case "nexus_operation": + return nexus_operation_to_nexus_link(temporal_link.nexus_operation) + + case "activity" | "batch_job": + raise NotImplementedError("only workflow links are supported") + + case None: + logger.warning("Invalid Temporal link: missing variant") + return None + + def workflow_event_to_nexus_link( workflow_event: temporalio.api.common.v1.Link.WorkflowEvent, ) -> nexusrpc.Link: @@ -60,9 +116,9 @@ def workflow_event_to_nexus_link( response. """ scheme = "temporal" - namespace = urllib.parse.quote(workflow_event.namespace) - workflow_id = urllib.parse.quote(workflow_event.workflow_id) - run_id = urllib.parse.quote(workflow_event.run_id) + namespace = urllib.parse.quote(workflow_event.namespace, safe="") + workflow_id = urllib.parse.quote(workflow_event.workflow_id, safe="") + run_id = urllib.parse.quote(workflow_event.run_id, safe="") path = f"/namespaces/{namespace}/workflows/{workflow_id}/{run_id}/history" query_params = None @@ -79,25 +135,49 @@ def workflow_event_to_nexus_link( # urllib will omit '//' from the url if netloc is empty so we add the scheme manually url = f"{scheme}://{urllib.parse.urlunparse(('', '', path, '', query_params, ''))}" - return nexusrpc.Link( - url=url, - type=workflow_event.DESCRIPTOR.full_name, - ) + return nexusrpc.Link(url=url, type=_LinkType.WORKFLOW.value) + +def nexus_operation_to_nexus_link( + op_link: temporalio.api.common.v1.Link.NexusOperation, +) -> nexusrpc.Link: + """Convert a NexusOperation link into a nexusrpc link -def nexus_link_to_workflow_event( + Used when propagating links from a StartNexusOperation response to a Nexus start operation + response. + """ + scheme = "temporal" + namespace = urllib.parse.quote(op_link.namespace, safe="") + operation_id = urllib.parse.quote(op_link.operation_id, safe="") + path = f"/namespaces/{namespace}/nexus-operations/{operation_id}" + + query_params = "" + if op_link.run_id: + query_params = urllib.parse.urlencode( + { + LINK_RUN_ID_PARAM_NAME: op_link.run_id, + }, + ) + + # urllib will omit '//' from the url if netloc is empty so we add the scheme manually + url = f"{scheme}://{urllib.parse.urlunparse(('', '', path, '', query_params, ''))}" + + return nexusrpc.Link(url=url, type=_LinkType.NEXUS_OPERATION.value) + + +def nexus_link_to_workflow_event_link( link: nexusrpc.Link, -) -> temporalio.api.common.v1.Link.WorkflowEvent | None: - """Convert a nexus link into a WorkflowEvent link +) -> temporalio.api.common.v1.Link | None: + """Convert a nexus link into a Temporal WorkflowEvent link This is used when propagating links from a Nexus start operation request to a StartWorklow request. """ url = urllib.parse.urlparse(link.url) - match = _LINK_URL_PATH_REGEX.match(url.path) + match = _WORFKLOW_LINK_URL_PATH_REGEX.match(url.path) if not match: logger.warning( - f"Invalid Nexus link: {link}. Expected path to match {_LINK_URL_PATH_REGEX.pattern}" + f"Invalid Nexus link: {link}. Expected path to match {_WORFKLOW_LINK_URL_PATH_REGEX.pattern}" ) return None try: @@ -122,13 +202,52 @@ def nexus_link_to_workflow_event( return None groups = match.groupdict() - return temporalio.api.common.v1.Link.WorkflowEvent( + workflow_event_link = temporalio.api.common.v1.Link.WorkflowEvent( namespace=urllib.parse.unquote(groups["namespace"]), workflow_id=urllib.parse.unquote(groups["workflow_id"]), run_id=urllib.parse.unquote(groups["run_id"]), event_ref=event_ref, request_id_ref=request_id_ref, ) + return temporalio.api.common.v1.Link(workflow_event=workflow_event_link) + + +def nexus_link_to_nexus_operation_link( + nexus_link: nexusrpc.Link, +) -> temporalio.api.common.v1.Link | None: + """Convert a nexus link into a Temporal NexusOperation link + + This is used when propagating links from a Nexus start operation request to a + StartNexusOperation request. + """ + url = urllib.parse.urlparse(nexus_link.url) + match = _NEXUS_OPERATION_LINK_URL_PATH_REGEX.match(url.path) + if not match: + logger.warning( + f"Invalid Nexus link: {nexus_link}. Expected path to match {_NEXUS_OPERATION_LINK_URL_PATH_REGEX.pattern}" + ) + return None + + query_params = urllib.parse.parse_qs(url.query) + + match query_params.get(LINK_RUN_ID_PARAM_NAME): + case [run_id_param]: + run_id = run_id_param + case [] | None: + run_id = "" + case _: + logger.warning( + f"Invalid Nexus link: {nexus_link}. Expected {LINK_RUN_ID_PARAM_NAME} to have at most 1 value" + ) + return None + + groups = match.groupdict() + nexus_op_link = temporalio.api.common.v1.Link.NexusOperation( + namespace=urllib.parse.unquote(groups["namespace"]), + operation_id=urllib.parse.unquote(groups["operation_id"]), + run_id=run_id, + ) + return temporalio.api.common.v1.Link(nexus_operation=nexus_op_link) def _event_reference_to_query_params( diff --git a/temporalio/nexus/_operation_context.py b/temporalio/nexus/_operation_context.py index 04462c900..069fd65d3 100644 --- a/temporalio/nexus/_operation_context.py +++ b/temporalio/nexus/_operation_context.py @@ -42,7 +42,7 @@ ) from ._link_conversion import ( - nexus_link_to_workflow_event, + nexus_link_to_temporal_link, workflow_event_to_nexus_link, workflow_execution_started_event_link_from_workflow_handle, ) @@ -239,12 +239,12 @@ def _get_callbacks( else [] ) - def _get_workflow_event_links( + def _get_links( self, - ) -> list[temporalio.api.common.v1.Link.WorkflowEvent]: - event_links = [] + ) -> list[temporalio.api.common.v1.Link]: + event_links: list[temporalio.api.common.v1.Link] = [] for inbound_link in self.nexus_context.inbound_links: - if link := nexus_link_to_workflow_event(inbound_link): + if link := nexus_link_to_temporal_link(inbound_link): event_links.append(link) return event_links @@ -492,7 +492,7 @@ async def start_workflow( Nexus caller is itself a workflow, this means that the workflow in the caller namespace web UI will contain links to the started workflow, and vice versa. """ - # We must pass nexus_completion_callbacks, workflow_event_links, and request_id, + # We must pass nexus_completion_callbacks, event_links, and request_id, # but these are deliberately not exposed in overloads, hence the type-check # violation. @@ -529,7 +529,7 @@ async def start_workflow( priority=priority, versioning_override=versioning_override, callbacks=self._temporal_context._get_callbacks(), - workflow_event_links=self._temporal_context._get_workflow_event_links(), + links=self._temporal_context._get_links(), request_id=self._temporal_context.nexus_context.request_id, ) diff --git a/temporalio/types.py b/temporalio/types.py index 4b217ea23..f90863d3e 100644 --- a/temporalio/types.py +++ b/temporalio/types.py @@ -11,6 +11,7 @@ ParamType = TypeVar("ParamType") ReturnType = TypeVar("ReturnType", covariant=True) LocalReturnType = TypeVar("LocalReturnType", covariant=True) +NexusServiceType = TypeVar("NexusServiceType") CallableType = TypeVar("CallableType", bound=Callable[..., Any]) CallableAsyncType = TypeVar("CallableAsyncType", bound=Callable[..., Awaitable[Any]]) CallableSyncOrAsyncType = TypeVar( diff --git a/temporalio/worker/_nexus.py b/temporalio/worker/_nexus.py index a189278b8..f35d10fd5 100644 --- a/temporalio/worker/_nexus.py +++ b/temporalio/worker/_nexus.py @@ -216,6 +216,14 @@ async def wait_all_completed(self) -> None: ] await asyncio.gather(*running_tasks, return_exceptions=True) + # Task completion should never be dropped in case of cancellation. + # The Rust future in core must complete for shutdown to happen without + # hanging. + async def _complete_task( + self, completion: temporalio.bridge.proto.nexus.NexusTaskCompletion + ): + await asyncio.shield(self._bridge_worker().complete_nexus_task(completion)) + # TODO(nexus-preview): stack trace pruning. See sdk-typescript NexusHandler.execute # "Any call up to this function and including this one will be trimmed out of stack traces."" @@ -281,8 +289,7 @@ async def _handle_cancel_operation_task( cancel_operation=temporalio.api.nexus.v1.CancelOperationResponse() ), ) - - await self._bridge_worker().complete_nexus_task(completion) + await self._complete_task(completion) except Exception: logger.exception("Failed to send Nexus task completion") finally: @@ -341,7 +348,7 @@ async def _handle_start_operation_task( ), ) - await self._bridge_worker().complete_nexus_task(completion) + await self._complete_task(completion) except Exception: logger.exception("Failed to send Nexus task completion") finally: diff --git a/temporalio/workflow/__init__.py b/temporalio/workflow/__init__.py index 792b4e1e8..f8002366b 100644 --- a/temporalio/workflow/__init__.py +++ b/temporalio/workflow/__init__.py @@ -127,7 +127,6 @@ NexusClient, NexusOperationCancellationType, NexusOperationHandle, - ServiceT, _NexusClient, create_nexus_client, ) @@ -240,7 +239,6 @@ "NexusClient", "NexusOperationCancellationType", "NexusOperationHandle", - "ServiceT", "create_nexus_client", "LoggerAdapter", "SandboxImportNotificationPolicy", diff --git a/temporalio/workflow/_nexus.py b/temporalio/workflow/_nexus.py index 7b3b842fe..0b80e6d91 100644 --- a/temporalio/workflow/_nexus.py +++ b/temporalio/workflow/_nexus.py @@ -4,7 +4,7 @@ from collections.abc import Awaitable, Callable, Generator, Mapping from datetime import timedelta from enum import IntEnum -from typing import Any, Generic, TypeVar, overload +from typing import Any, Generic, overload import nexusrpc import nexusrpc.handler @@ -13,6 +13,7 @@ import temporalio.bridge.proto.nexus import temporalio.nexus from temporalio.nexus._util import ServiceHandlerT +from temporalio.types import NexusServiceType from ._context import _Runtime @@ -20,7 +21,6 @@ "NexusClient", "NexusOperationCancellationType", "NexusOperationHandle", - "ServiceT", "create_nexus_client", ] @@ -44,9 +44,6 @@ def operation_token(self) -> str | None: raise NotImplementedError -ServiceT = TypeVar("ServiceT") - - class NexusOperationCancellationType(IntEnum): """Defines behavior of a Nexus operation when the caller workflow initiates cancellation. @@ -84,7 +81,7 @@ class NexusOperationCancellationType(IntEnum): :py:exc:`asyncio.CancelledError` resulting from the cancellation request).""" -class NexusClient(ABC, Generic[ServiceT]): +class NexusClient(ABC, Generic[NexusServiceType]): """A client for invoking Nexus operations. Example:: @@ -307,7 +304,7 @@ async def execute_operation( async def execute_operation( self, operation: Callable[ - [ServiceT, nexusrpc.handler.StartOperationContext, InputT], + [NexusServiceType, nexusrpc.handler.StartOperationContext, InputT], Awaitable[OutputT], ], input: InputT, @@ -327,7 +324,7 @@ async def execute_operation( async def execute_operation( self, operation: Callable[ - [ServiceT, nexusrpc.handler.StartOperationContext, InputT], + [NexusServiceType, nexusrpc.handler.StartOperationContext, InputT], OutputT, ], input: InputT, @@ -347,7 +344,7 @@ async def execute_operation( async def execute_operation( self, operation: Callable[ - [ServiceT], + [NexusServiceType], nexusrpc.handler.OperationHandler[InputT, OutputT], ], input: InputT, @@ -392,12 +389,12 @@ async def execute_operation( ... -class _NexusClient(NexusClient[ServiceT]): +class _NexusClient(NexusClient[NexusServiceType]): def __init__( self, *, endpoint: str, - service: type[ServiceT] | str, + service: type[NexusServiceType] | str, ) -> None: """Create a Nexus client. @@ -476,9 +473,9 @@ async def execute_operation( @overload def create_nexus_client( *, - service: type[ServiceT], + service: type[NexusServiceType], endpoint: str, -) -> NexusClient[ServiceT]: ... +) -> NexusClient[NexusServiceType]: ... @overload @@ -491,9 +488,9 @@ def create_nexus_client( def create_nexus_client( *, - service: type[ServiceT] | str, + service: type[NexusServiceType] | str, endpoint: str, -) -> NexusClient[ServiceT]: +) -> NexusClient[NexusServiceType]: """Create a Nexus client. Args: diff --git a/tests/conftest.py b/tests/conftest.py index 999f19b1e..2005dbe57 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -128,6 +128,12 @@ async def env(env_type: str) -> AsyncGenerator[WorkflowEnvironment, None]: "history.enableChasm=true", "--dynamic-config-value", "history.enableTransitionHistory=true", + "--dynamic-config-value", + "history.enableChasmCallbacks=true", + "--dynamic-config-value", + "nexusoperation.enableStandalone=true", + "--dynamic-config-value", + 'system.system.refreshNexusEndpointsMinWait="0s"', ], dev_server_download_version=DEV_SERVER_DOWNLOAD_VERSION, ) diff --git a/tests/nexus/test_link_conversion.py b/tests/nexus/test_link_conversion.py index ac130122a..345d4f4e3 100644 --- a/tests/nexus/test_link_conversion.py +++ b/tests/nexus/test_link_conversion.py @@ -140,17 +140,19 @@ def test_request_id_reference_to_query_params( @pytest.mark.parametrize( - ["event", "expected_link"], + ["wf_event_link", "expected_link"], [ ( - temporalio.api.common.v1.Link.WorkflowEvent( - namespace="ns", - workflow_id="wid", - run_id="rid", - request_id_ref=temporalio.api.common.v1.Link.WorkflowEvent.RequestIdReference( - event_type=temporalio.api.enums.v1.event_type_pb2.EVENT_TYPE_WORKFLOW_TASK_COMPLETED, - request_id="req-123", - ), + temporalio.api.common.v1.Link( + workflow_event=temporalio.api.common.v1.Link.WorkflowEvent( + namespace="ns", + workflow_id="wid", + run_id="rid", + request_id_ref=temporalio.api.common.v1.Link.WorkflowEvent.RequestIdReference( + event_type=temporalio.api.enums.v1.event_type_pb2.EVENT_TYPE_WORKFLOW_TASK_COMPLETED, + request_id="req-123", + ), + ) ), nexusrpc.Link( type=temporalio.api.common.v1.Link.WorkflowEvent.DESCRIPTOR.full_name, @@ -158,32 +160,129 @@ def test_request_id_reference_to_query_params( ), ), ( - temporalio.api.common.v1.Link.WorkflowEvent( - namespace="ns2", - workflow_id="wid2", - run_id="rid2", - event_ref=temporalio.api.common.v1.Link.WorkflowEvent.EventReference( - event_id=42, - event_type=temporalio.api.enums.v1.event_type_pb2.EVENT_TYPE_WORKFLOW_EXECUTION_COMPLETED, - ), + temporalio.api.common.v1.Link( + workflow_event=temporalio.api.common.v1.Link.WorkflowEvent( + namespace="ns2", + workflow_id="wid2", + run_id="rid2", + event_ref=temporalio.api.common.v1.Link.WorkflowEvent.EventReference( + event_id=42, + event_type=temporalio.api.enums.v1.event_type_pb2.EVENT_TYPE_WORKFLOW_EXECUTION_COMPLETED, + ), + ) ), nexusrpc.Link( type=temporalio.api.common.v1.Link.WorkflowEvent.DESCRIPTOR.full_name, url="temporal:///namespaces/ns2/workflows/wid2/rid2/history?eventID=42&eventType=WorkflowExecutionCompleted&referenceType=EventReference", ), ), + ( + temporalio.api.common.v1.Link( + workflow_event=temporalio.api.common.v1.Link.WorkflowEvent( + namespace="ns2", + workflow_id="wid/2", + run_id="rid2", + event_ref=temporalio.api.common.v1.Link.WorkflowEvent.EventReference( + event_id=42, + event_type=temporalio.api.enums.v1.event_type_pb2.EVENT_TYPE_WORKFLOW_EXECUTION_COMPLETED, + ), + ) + ), + nexusrpc.Link( + type=temporalio.api.common.v1.Link.WorkflowEvent.DESCRIPTOR.full_name, + url="temporal:///namespaces/ns2/workflows/wid%2F2/rid2/history?eventID=42&eventType=WorkflowExecutionCompleted&referenceType=EventReference", + ), + ), ], ) def test_link_conversion_workflow_event_to_link_and_back( - event: temporalio.api.common.v1.Link.WorkflowEvent, expected_link: nexusrpc.Link + wf_event_link: temporalio.api.common.v1.Link, expected_link: nexusrpc.Link ): - actual_link = temporalio.nexus._link_conversion.workflow_event_to_nexus_link(event) + actual_link = temporalio.nexus._link_conversion.workflow_event_to_nexus_link( + wf_event_link.workflow_event + ) assert expected_link == actual_link - actual_event = temporalio.nexus._link_conversion.nexus_link_to_workflow_event( + actual_event = temporalio.nexus._link_conversion.nexus_link_to_workflow_event_link( actual_link ) - assert event == actual_event + assert wf_event_link == actual_event + + +@pytest.mark.parametrize( + ["operation_link", "expected_link"], + [ + ( + temporalio.api.common.v1.Link( + nexus_operation=temporalio.api.common.v1.Link.NexusOperation( + namespace="ns", + operation_id="op-id", + run_id="run-id", + ) + ), + nexusrpc.Link( + type=temporalio.api.common.v1.Link.NexusOperation.DESCRIPTOR.full_name, + url="temporal:///namespaces/ns/nexus-operations/op-id?runID=run-id", + ), + ), + ( + temporalio.api.common.v1.Link( + nexus_operation=temporalio.api.common.v1.Link.NexusOperation( + namespace="ns", + operation_id="op-id", + ) + ), + nexusrpc.Link( + type=temporalio.api.common.v1.Link.NexusOperation.DESCRIPTOR.full_name, + url="temporal:///namespaces/ns/nexus-operations/op-id", + ), + ), + ( + temporalio.api.common.v1.Link( + nexus_operation=temporalio.api.common.v1.Link.NexusOperation( + namespace="ns", + operation_id="op/id", + ) + ), + nexusrpc.Link( + type=temporalio.api.common.v1.Link.NexusOperation.DESCRIPTOR.full_name, + url="temporal:///namespaces/ns/nexus-operations/op%2Fid", + ), + ), + ], +) +def test_link_conversion_nexus_operation_to_link_and_back( + operation_link: temporalio.api.common.v1.Link, + expected_link: nexusrpc.Link, +): + actual_link = temporalio.nexus._link_conversion.nexus_operation_to_nexus_link( + operation_link.nexus_operation + ) + assert expected_link == actual_link + + actual_operation = ( + temporalio.nexus._link_conversion.nexus_link_to_nexus_operation_link( + actual_link + ) + ) + assert operation_link == actual_operation + + assert ( + expected_link + == temporalio.nexus._link_conversion.temporal_link_to_nexus_link(operation_link) + ) + assert ( + operation_link + == temporalio.nexus._link_conversion.nexus_link_to_temporal_link(expected_link) + ) + + +def test_nexus_operation_link_with_duplicate_run_id_is_ignored(): + link = nexusrpc.Link( + type=temporalio.api.common.v1.Link.NexusOperation.DESCRIPTOR.full_name, + url="temporal:///namespaces/ns/nexus-operations/op-id?runID=one&runID=two", + ) + assert temporalio.nexus._link_conversion.nexus_link_to_temporal_link(link) is None def test_link_conversion_utilities(): diff --git a/tests/nexus/test_nexus_type_errors.py b/tests/nexus/test_nexus_type_errors.py new file mode 100644 index 000000000..c669f8a5b --- /dev/null +++ b/tests/nexus/test_nexus_type_errors.py @@ -0,0 +1,399 @@ +""" +This file exists to test for type-checker false positives and false negatives. +It doesn't contain any test functions. +""" + +from dataclasses import dataclass +from datetime import timedelta +from typing import Any +from unittest.mock import Mock + +import nexusrpc + +import temporalio.nexus +from temporalio import workflow +from temporalio.client import Client, NexusOperationHandle +from temporalio.service import ServiceClient + + +@dataclass +class MyInput: + pass + + +@dataclass +class MyOutput: + pass + + +@nexusrpc.service +class MyService: + my_sync_operation: nexusrpc.Operation[MyInput, MyOutput] + my_workflow_run_operation: nexusrpc.Operation[MyInput, MyOutput] + + +@nexusrpc.service +class MyNoInputService: + my_no_input_operation: nexusrpc.Operation[None, MyOutput] + + +@nexusrpc.handler.service_handler(service=MyService) +class MyServiceHandler: + @nexusrpc.handler.sync_operation + async def my_sync_operation( + self, _ctx: nexusrpc.handler.StartOperationContext, _input: MyInput + ) -> MyOutput: + raise NotImplementedError + + @temporalio.nexus.workflow_run_operation + async def my_workflow_run_operation( + self, _ctx: temporalio.nexus.WorkflowRunOperationContext, _input: MyInput + ) -> temporalio.nexus.WorkflowHandle[MyOutput]: + raise NotImplementedError + + +@nexusrpc.handler.service_handler(service=MyService) +class MyServiceHandler2: + @nexusrpc.handler.sync_operation + async def my_sync_operation( + self, _ctx: nexusrpc.handler.StartOperationContext, _input: MyInput + ) -> MyOutput: + raise NotImplementedError + + @temporalio.nexus.workflow_run_operation + async def my_workflow_run_operation( + self, _ctx: temporalio.nexus.WorkflowRunOperationContext, _input: MyInput + ) -> temporalio.nexus.WorkflowHandle[MyOutput]: + raise NotImplementedError + + +@nexusrpc.handler.service_handler +class MyServiceHandlerWithoutServiceDefinition: + @nexusrpc.handler.sync_operation + async def my_sync_operation( + self, _ctx: nexusrpc.handler.StartOperationContext, _input: MyInput + ) -> MyOutput: + raise NotImplementedError + + @temporalio.nexus.workflow_run_operation + async def my_workflow_run_operation( + self, _ctx: temporalio.nexus.WorkflowRunOperationContext, _input: MyInput + ) -> temporalio.nexus.WorkflowHandle[MyOutput]: + raise NotImplementedError + + +@workflow.defn +class MyWorkflow1: + @workflow.run + async def test_invoke_by_operation_definition_happy_path(self) -> None: + """ + When a nexus client calls an operation by referencing an operation definition on + a service definition, the output type is inferred correctly. + """ + nexus_client = workflow.create_nexus_client( + service=MyService, + endpoint="fake-endpoint", + ) + input = MyInput() + + # sync operation + _output_1: MyOutput = await nexus_client.execute_operation( + MyService.my_sync_operation, input + ) + _handle_1: workflow.NexusOperationHandle[ + MyOutput + ] = await nexus_client.start_operation(MyService.my_sync_operation, input) + _output_1_1: MyOutput = await _handle_1 + + # workflow run operation + _output_2: MyOutput = await nexus_client.execute_operation( + MyService.my_workflow_run_operation, input + ) + _handle_2: workflow.NexusOperationHandle[ + MyOutput + ] = await nexus_client.start_operation( + MyService.my_workflow_run_operation, input + ) + _output_2_1: MyOutput = await _handle_2 + + +@workflow.defn +class MyWorkflow2: + @workflow.run + async def test_invoke_by_operation_handler_happy_path(self) -> None: + """ + When a nexus client calls an operation by referencing an operation handler on a + service handler, the output type is inferred correctly. + """ + nexus_client = workflow.create_nexus_client( + service=MyServiceHandler, # MyService would also work + endpoint="fake-endpoint", + ) + input = MyInput() + + # sync operation + _output_1: MyOutput = await nexus_client.execute_operation( + MyServiceHandler.my_sync_operation, input + ) + _handle_1: workflow.NexusOperationHandle[ + MyOutput + ] = await nexus_client.start_operation( + MyServiceHandler.my_sync_operation, input + ) + _output_1_1: MyOutput = await _handle_1 + + # workflow run operation + _output_2: MyOutput = await nexus_client.execute_operation( + MyServiceHandler.my_workflow_run_operation, input + ) + _handle_2: workflow.NexusOperationHandle[ + MyOutput + ] = await nexus_client.start_operation( + MyServiceHandler.my_workflow_run_operation, input + ) + _output_2_1: MyOutput = await _handle_2 + + +@workflow.defn +class MyWorkflow3: + @workflow.run + async def test_invoke_by_operation_definition_wrong_input_type(self) -> None: + """ + When a nexus client calls an operation by referencing an operation definition on + a service definition, there is a type error if the input type is wrong. + """ + nexus_client = workflow.create_nexus_client( + service=MyService, + endpoint="fake-endpoint", + ) + # assert-type-error-pyright: 'No overloads for "execute_operation" match' + await nexus_client.execute_operation( # type: ignore + MyService.my_sync_operation, + # assert-type-error-pyright: 'Argument of type .+ cannot be assigned to parameter "input"' + "wrong-input-type", # type: ignore + ) + + +@workflow.defn +class MyWorkflow4: + @workflow.run + async def test_invoke_by_operation_handler_wrong_input_type(self) -> None: + """ + When a nexus client calls an operation by referencing an operation handler on a + service handler, there is a type error if the input type is wrong. + """ + nexus_client = workflow.create_nexus_client( + service=MyServiceHandler, + endpoint="fake-endpoint", + ) + # assert-type-error-pyright: 'No overloads for "execute_operation" match' + await nexus_client.execute_operation( # type: ignore + MyServiceHandler.my_sync_operation, # type: ignore[arg-type] + # assert-type-error-pyright: 'Argument of type .+ cannot be assigned to parameter "input"' + "wrong-input-type", # type: ignore + ) + + +@workflow.defn +class MyWorkflow5: + @workflow.run + async def test_invoke_by_operation_handler_method_on_wrong_service(self) -> None: + """ + When a nexus client calls an operation by referencing an operation handler method + on a service handler, there is a type error if the method does not belong to the + service for which the client was created. + + (This form of type safety is not available when referencing an operation definition) + """ + nexus_client = workflow.create_nexus_client( + service=MyServiceHandler, + endpoint="fake-endpoint", + ) + # assert-type-error-pyright: 'No overloads for "execute_operation" match' + await nexus_client.execute_operation( # type: ignore + # assert-type-error-pyright: 'Argument of type .+ cannot be assigned to parameter "operation"' + MyServiceHandler2.my_sync_operation, # type: ignore + MyInput(), + ) + + +# ── Standalone Nexus Operation type tests ── +async def standalone_operation_type_tests(): + client = Client(service_client=Mock(spec=ServiceClient)) + nexus_client = client.create_nexus_client( + MyService, + endpoint="fake-endpoint", + ) + no_input_nexus_client = client.create_nexus_client( + MyNoInputService, + endpoint="fake-endpoint", + ) + + # execute with an operation definition infers output type + _op_defn_output: MyOutput = await nexus_client.execute_operation( + MyService.my_sync_operation, + MyInput(), + id="op-1", + schedule_to_start_timeout=timedelta(seconds=1), + start_to_close_timeout=timedelta(seconds=2), + ) + + # result_type overrides output type from operation definition + # conflicting result_type and annotation on variable cause type error + # assert-type-error-pyright: 'Type "str" is not assignable to declared type "MyOutput"' + _bad_result_type_output: MyOutput = await nexus_client.execute_operation( # type: ignore + MyServiceHandler.my_sync_operation, + MyInput(), + id="op-1", + result_type=str, # type: ignore + ) + + # string operation name and result_type infers output type + _str_op_result_type_output: MyOutput = await nexus_client.execute_operation( + "my_sync_operation", MyInput(), id="op-1", result_type=MyOutput + ) + + # omitting arg for string operation names is not supported + # assert-type-error-pyright: 'No overloads for "execute_operation" match' + await nexus_client.execute_operation( # type: ignore + "my_sync_operation", + id="op-1", + result_type=MyOutput, + ) + # assert-type-error-pyright: 'No overloads for "start_operation" match' + await nexus_client.start_operation( # type: ignore + "my_sync_operation", + id="op-1", + result_type=MyOutput, + ) + + # omitting arg for callable operations is not supported + # assert-type-error-pyright: 'No overloads for "execute_operation" match' + await nexus_client.execute_operation( # type: ignore + MyServiceHandler.my_sync_operation, + id="op-1", + result_type=MyOutput, + ) + # assert-type-error-pyright: 'No overloads for "start_operation" match' + await nexus_client.start_operation( # type: ignore + MyServiceHandler.my_sync_operation, + id="op-1", + result_type=MyOutput, + ) + + # no-input operation definitions must still be called with explicit None + _no_input_op_defn_output: MyOutput = await no_input_nexus_client.execute_operation( + MyNoInputService.my_no_input_operation, + None, + id="op-1", + ) + _no_input_op_defn_handle: NexusOperationHandle[ + MyOutput + ] = await no_input_nexus_client.start_operation( + MyNoInputService.my_no_input_operation, + None, + id="op-1", + ) + _no_input_op_defn_handle_output: MyOutput = await _no_input_op_defn_handle.result() + + # omitting arg for no-input operation definitions is not supported + # assert-type-error-pyright: 'No overloads for "execute_operation" match' + await no_input_nexus_client.execute_operation( # type: ignore + MyNoInputService.my_no_input_operation, + id="op-1", + ) + # assert-type-error-pyright: 'No overloads for "start_operation" match' + await no_input_nexus_client.start_operation( # type: ignore + MyNoInputService.my_no_input_operation, + id="op-1", + ) + + # execute with an operation definition and a wrong input type produces a type error + # assert-type-error-pyright: 'No overloads for "execute_operation" match' + await nexus_client.execute_operation( # type: ignore + MyService.my_sync_operation, + # assert-type-error-pyright: 'Argument of type .+ cannot be assigned to parameter "arg"' + "wrong-input-type", # type: ignore + id="op-1", + ) + + # start with an operation definition and a wrong input type produces a type error + # assert-type-error-pyright: 'No overloads for "start_operation" match' + await nexus_client.start_operation( # type: ignore + MyService.my_sync_operation, + # assert-type-error-pyright: 'Argument of type .+ cannot be assigned to parameter "arg"' + "wrong-input-type", # type: ignore + id="op-1", + ) + + # starting with an operation definition infers output type on the handle and + # result from handle + _defn_handle: NexusOperationHandle[MyOutput] = await nexus_client.start_operation( + MyService.my_sync_operation, + MyInput(), + id="op-1", + schedule_to_start_timeout=timedelta(seconds=1), + start_to_close_timeout=timedelta(seconds=2), + ) + _defn_handle_output: MyOutput = await _defn_handle.result() + + # result_type overrides output type from operation definition + # conflicting result_type and annotation on variable cause type error + _result_type_handle: NexusOperationHandle[ + MyOutput + # assert-type-error-pyright: 'Type "NexusOperationHandle\[str\]" is not assignable to declared type "NexusOperationHandle\[MyOutput\]"' + ] = await nexus_client.start_operation( # type: ignore + MyServiceHandler.my_sync_operation, + MyInput(), + id="op-1", + result_type=str, # type: ignore + ) + # handle still respects type declaration on the variable + _result_type_handle_output: MyOutput = await _result_type_handle.result() + + # starting with string operation name and result_type infers output type on the handle + # and result from the handle + _str_op_result_type_handle: NexusOperationHandle[ + MyOutput + ] = await nexus_client.start_operation( + "my_sync_operation", MyInput(), id="op-1", result_type=MyOutput + ) + _str_op_result_type_handle_output: MyOutput = ( + await _str_op_result_type_handle.result() + ) + + # getting a handle with a string produces a handle to Any + _str_op_handle: NexusOperationHandle[Any] = client.get_nexus_operation_handle( + "op-1" + ) + + # getting a handle with an explicit type produces handle of that type + _result_type_get_handle: NexusOperationHandle[MyOutput] = ( + client.get_nexus_operation_handle("op-1", result_type=MyOutput) + ) + + # getting a handle with an operation defintion produces a handle of the operation + # output type + _op_defn_get_handle: NexusOperationHandle[MyOutput] = ( + client.get_nexus_operation_handle("op-1", operation=MyService.my_sync_operation) + ) + + # providing both operation and result_type to get_nexus_operation_handle + # produces a no overload found error + # assert-type-error-pyright: 'No overloads for "get_nexus_operation_handle" match' + _result_type_op_defn_get_handle: NexusOperationHandle[MyOutput] = ( + client.get_nexus_operation_handle( # type: ignore + "op-1", + operation=MyService.my_sync_operation, + result_type=str, + ) + ) + + # mismatched types on get_nexus_operation_handle produces type error + # assert-type-error-pyright: 'Type "NexusOperationHandle\[str\]" is not assignable to declared type "NexusOperationHandle\[MyOutput\]"' + _mismatch_handle: NexusOperationHandle[MyOutput] = ( + client.get_nexus_operation_handle( # type: ignore + "op-1", + result_type=str, # type: ignore + ) + ) diff --git a/tests/nexus/test_standalone_operations.py b/tests/nexus/test_standalone_operations.py new file mode 100644 index 000000000..10b2f17fa --- /dev/null +++ b/tests/nexus/test_standalone_operations.py @@ -0,0 +1,951 @@ +"""Integration tests for standalone Nexus operations (client-side). + +Tests the client-side Nexus operation API: start, result, describe, cancel, +terminate, list, count, get_nexus_operation_handle, ID conflict policies, +and interceptor integration. +""" + +from __future__ import annotations + +import asyncio +import uuid +from dataclasses import dataclass +from datetime import timedelta +from typing import Any, Literal + +import nexusrpc +import pytest +from nexusrpc.handler import ( + StartOperationContext, + service_handler, + sync_operation, +) + +from temporalio import nexus, workflow +from temporalio.client import ( + CancelNexusOperationInput, + Client, + CountNexusOperationsInput, + DescribeNexusOperationInput, + GetNexusOperationResultInput, + Interceptor, + ListNexusOperationsInput, + NexusOperationExecutionDescription, + NexusOperationFailureError, + NexusOperationHandle, + OutboundInterceptor, + StartNexusOperationInput, + TerminateNexusOperationInput, + WorkflowUpdateStage, +) +from temporalio.common import ( + NexusOperationExecutionStatus, + NexusOperationIDConflictPolicy, + NexusOperationIDReusePolicy, + PendingNexusOperationExecutionState, + WorkflowIDConflictPolicy, + WorkflowIDReusePolicy, +) +from temporalio.exceptions import ( + ApplicationError, + CancelledError, + NexusOperationAlreadyStartedError, + TerminatedError, +) +from temporalio.nexus import WorkflowRunOperationContext, workflow_run_operation +from temporalio.testing import WorkflowEnvironment +from temporalio.worker import Worker +from tests.helpers import assert_eventually +from tests.helpers.nexus import make_nexus_endpoint_name + +# --------------------------------------------------------------------------- +# Data types +# --------------------------------------------------------------------------- + + +@dataclass +class EchoInput: + value: str + + +@dataclass +class EchoOutput: + value: str + + +@dataclass +class RaiseErrInput: + err_type: Literal["handler_err", "application_err"] + + +# --------------------------------------------------------------------------- +# Service definition +# --------------------------------------------------------------------------- + + +@nexusrpc.service +class StandaloneTestService: + echo_sync: nexusrpc.Operation[EchoInput, EchoOutput] + echo_async: nexusrpc.Operation[EchoInput, EchoOutput] + blocking_async: nexusrpc.Operation[EchoInput, EchoOutput] + raise_err: nexusrpc.Operation[RaiseErrInput, None] + + +@nexusrpc.service(name="StandaloneTestService") +class NamedService: + echo_sync: nexusrpc.Operation[EchoInput, EchoOutput] + + +# --------------------------------------------------------------------------- +# Handler workflows +# --------------------------------------------------------------------------- + + +@workflow.defn +class EchoHandlerWorkflow: + @workflow.run + async def run(self, input: EchoInput) -> EchoOutput: + return EchoOutput(value=input.value) + + +@workflow.defn +class BlockingHandlerWorkflow: + """A workflow that blocks until it receives a signal or is cancelled/terminated.""" + + def __init__(self) -> None: + self._proceed = False + + @workflow.run + async def run(self, input: EchoInput) -> EchoOutput: + await workflow.wait_condition(lambda: self._proceed) + return EchoOutput(value=input.value) + + @workflow.update + def unblock(self) -> None: + self._proceed = True + + +# --------------------------------------------------------------------------- +# Service handler +# --------------------------------------------------------------------------- + + +@service_handler(service=StandaloneTestService) +class StandaloneTestServiceHandler: + def __init__(self) -> None: + self.started_blocking = asyncio.Event() + + @sync_operation + async def echo_sync( + self, _ctx: StartOperationContext, input: EchoInput + ) -> EchoOutput: + return EchoOutput(value=input.value) + + @workflow_run_operation + async def echo_async( + self, ctx: WorkflowRunOperationContext, input: EchoInput + ) -> nexus.WorkflowHandle[EchoOutput]: + return await ctx.start_workflow( + EchoHandlerWorkflow.run, + input, + id=str(uuid.uuid4()), + ) + + @workflow_run_operation + async def blocking_async( + self, ctx: WorkflowRunOperationContext, input: EchoInput + ) -> nexus.WorkflowHandle[EchoOutput]: + handle = await ctx.start_workflow( + BlockingHandlerWorkflow.run, + input, + id=f"blocking_async-{input.value}", + id_reuse_policy=WorkflowIDReusePolicy.ALLOW_DUPLICATE, + id_conflict_policy=WorkflowIDConflictPolicy.FAIL, + ) + self.started_blocking.set() + return handle + + @sync_operation + async def raise_err( + self, _ctx: StartOperationContext, input: RaiseErrInput + ) -> None: + match input.err_type: + case "handler_err": + raise nexusrpc.HandlerError( + "test handler error", + type=nexusrpc.HandlerErrorType.INTERNAL, + retryable_override=False, + ) + case "application_err": + raise ApplicationError("test application error", non_retryable=True) + + +# --------------------------------------------------------------------------- +# Tests +# --------------------------------------------------------------------------- + + +async def test_start_sync_operation_and_get_result( + client: Client, env: WorkflowEnvironment +): + """Start a sync nexus operation, call handle.result(), verify return value.""" + if env.supports_time_skipping: + pytest.skip( + "Standalone Nexus Operation tests don't work with time-skipping server" + ) + + task_queue = str(uuid.uuid4()) + endpoint_name = make_nexus_endpoint_name(task_queue) + + async with Worker( + client, + task_queue=task_queue, + nexus_service_handlers=[StandaloneTestServiceHandler()], + workflows=[EchoHandlerWorkflow, BlockingHandlerWorkflow], + ): + await env.create_nexus_endpoint(endpoint_name, task_queue) + + nexus_client = client.create_nexus_client( + service=StandaloneTestService, endpoint=endpoint_name + ) + # Use execute_with_retry to retry the full start+result cycle + # (endpoint propagation may cause the first attempt to time out) + handle = await nexus_client.start_operation( + StandaloneTestService.echo_sync, + EchoInput(value="hello"), + id=str(uuid.uuid4()), + schedule_to_close_timeout=timedelta(seconds=10), + ) + result = await handle.result() + assert isinstance(result, EchoOutput) + assert result.value == "hello" + + # test value is cached + second_result = await handle.result() + assert result is second_result + + +async def test_start_async_operation_and_poll_result( + client: Client, env: WorkflowEnvironment +): + """Start a workflow_run operation, poll result, verify.""" + if env.supports_time_skipping: + pytest.skip( + "Standalone Nexus Operation tests don't work with time-skipping server" + ) + + task_queue = str(uuid.uuid4()) + endpoint_name = make_nexus_endpoint_name(task_queue) + + async with Worker( + client, + task_queue=task_queue, + nexus_service_handlers=[StandaloneTestServiceHandler()], + workflows=[EchoHandlerWorkflow, BlockingHandlerWorkflow], + ): + await env.create_nexus_endpoint(endpoint_name, task_queue) + + nexus_client = client.create_nexus_client( + service=StandaloneTestService, endpoint=endpoint_name + ) + handle = await nexus_client.start_operation( + StandaloneTestService.echo_async, + EchoInput(value="async-hello"), + id=str(uuid.uuid4()), + schedule_to_close_timeout=timedelta(seconds=30), + ) + result = await handle.result() + assert isinstance(result, EchoOutput) + assert result.value == "async-hello" + + +async def test_execute_operation(client: Client, env: WorkflowEnvironment): + """Use execute_operation convenience method, verify it returns result directly.""" + if env.supports_time_skipping: + pytest.skip( + "Standalone Nexus Operation tests don't work with time-skipping server" + ) + + task_queue = str(uuid.uuid4()) + endpoint_name = make_nexus_endpoint_name(task_queue) + + async with Worker( + client, + task_queue=task_queue, + nexus_service_handlers=[StandaloneTestServiceHandler()], + workflows=[EchoHandlerWorkflow, BlockingHandlerWorkflow], + ): + await env.create_nexus_endpoint(endpoint_name, task_queue) + + nexus_client = client.create_nexus_client( + service=StandaloneTestService, endpoint=endpoint_name + ) + result = await nexus_client.execute_operation( + StandaloneTestService.echo_sync, + EchoInput(value="execute"), + id=str(uuid.uuid4()), + id_reuse_policy=NexusOperationIDReusePolicy.REJECT_DUPLICATE, + id_conflict_policy=NexusOperationIDConflictPolicy.FAIL, + schedule_to_close_timeout=timedelta(seconds=10), + ) + assert isinstance(result, EchoOutput) + assert result.value == "execute" + + +async def test_execute_operation_named_service( + client: Client, env: WorkflowEnvironment +): + """Verify that the name on the service decorator is respected by the standalone nexus client""" + if env.supports_time_skipping: + pytest.skip( + "Standalone Nexus Operation tests don't work with time-skipping server" + ) + + task_queue = str(uuid.uuid4()) + endpoint_name = make_nexus_endpoint_name(task_queue) + + async with Worker( + client, + task_queue=task_queue, + # Register the standalone test service handler + nexus_service_handlers=[StandaloneTestServiceHandler()], + workflows=[EchoHandlerWorkflow, BlockingHandlerWorkflow], + ): + await env.create_nexus_endpoint(endpoint_name, task_queue) + + # Create client using the service that is uses the name "StandaloneTestService" + nexus_client = client.create_nexus_client( + service=NamedService, endpoint=endpoint_name + ) + result = await nexus_client.execute_operation( + NamedService.echo_sync, + EchoInput(value="execute"), + id=str(uuid.uuid4()), + id_reuse_policy=NexusOperationIDReusePolicy.REJECT_DUPLICATE, + id_conflict_policy=NexusOperationIDConflictPolicy.FAIL, + schedule_to_close_timeout=timedelta(seconds=10), + ) + assert isinstance(result, EchoOutput) + assert result.value == "execute" + + +async def test_errors(client: Client, env: WorkflowEnvironment): + """Execute operations that raise errors""" + if env.supports_time_skipping: + pytest.skip( + "Standalone Nexus Operation tests don't work with time-skipping server" + ) + + task_queue = str(uuid.uuid4()) + endpoint_name = make_nexus_endpoint_name(task_queue) + + async with Worker( + client, + task_queue=task_queue, + nexus_service_handlers=[StandaloneTestServiceHandler()], + workflows=[EchoHandlerWorkflow, BlockingHandlerWorkflow], + ): + await env.create_nexus_endpoint(endpoint_name, task_queue) + + nexus_client = client.create_nexus_client( + service=StandaloneTestService, endpoint=endpoint_name + ) + + handle = await nexus_client.start_operation( + StandaloneTestService.raise_err, + RaiseErrInput("handler_err"), + id=str(uuid.uuid4()), + id_reuse_policy=NexusOperationIDReusePolicy.REJECT_DUPLICATE, + id_conflict_policy=NexusOperationIDConflictPolicy.FAIL, + schedule_to_close_timeout=timedelta(seconds=30), + ) + + with pytest.raises(NexusOperationFailureError) as err: + await handle.result() + + assert err.value.__cause__ + assert isinstance(err.value.__cause__, nexusrpc.HandlerError) + + # test that the error is cached + with pytest.raises(NexusOperationFailureError) as second_err: + await handle.result() + assert err.value is second_err.value + + handle = await nexus_client.start_operation( + StandaloneTestService.raise_err, + RaiseErrInput("application_err"), + id=str(uuid.uuid4()), + id_reuse_policy=NexusOperationIDReusePolicy.REJECT_DUPLICATE, + id_conflict_policy=NexusOperationIDConflictPolicy.FAIL, + schedule_to_close_timeout=timedelta(seconds=30), + ) + + with pytest.raises(NexusOperationFailureError) as err: + await handle.result() + + assert err.value.__cause__ + assert isinstance(err.value.__cause__, nexusrpc.HandlerError) + assert err.value.__cause__.__cause__ + assert isinstance(err.value.__cause__.__cause__, ApplicationError) + + +async def test_describe_operation(client: Client, env: WorkflowEnvironment): + """Start op, get result first, then describe, verify fields populated.""" + if env.supports_time_skipping: + pytest.skip( + "Standalone Nexus Operation tests don't work with time-skipping server" + ) + + task_queue = str(uuid.uuid4()) + endpoint_name = make_nexus_endpoint_name(task_queue) + + async with Worker( + client, + task_queue=task_queue, + nexus_service_handlers=[StandaloneTestServiceHandler()], + workflows=[EchoHandlerWorkflow, BlockingHandlerWorkflow], + ): + await env.create_nexus_endpoint(endpoint_name, task_queue) + + nexus_client = client.create_nexus_client( + service=StandaloneTestService, endpoint=endpoint_name + ) + # Start an async operation and get its result first, then describe + handle = await nexus_client.start_operation( + StandaloneTestService.echo_async, + EchoInput(value="describe-me"), + id=str(uuid.uuid4()), + id_reuse_policy=NexusOperationIDReusePolicy.REJECT_DUPLICATE, + id_conflict_policy=NexusOperationIDConflictPolicy.FAIL, + schedule_to_close_timeout=timedelta(seconds=30), + summary=StandaloneTestService.echo_async.name, + ) + await handle.result() + + desc = await handle.describe() + assert desc.operation_id == handle.operation_id + assert desc.endpoint == endpoint_name + assert desc.service == "StandaloneTestService" + assert desc.operation == "echo_async" + assert desc.status == NexusOperationExecutionStatus.COMPLETED + assert desc.state == PendingNexusOperationExecutionState.UNSPECIFIED + assert desc.attempt >= 1 + assert desc.blocked_reason is None + assert desc.last_attempt_failure is None + summary = await desc.static_summary() + assert summary == StandaloneTestService.echo_async.name + + +async def test_cancel_operation(client: Client, env: WorkflowEnvironment): + """Start blocking async op, cancel it, verify awaiting result raises NexusOperationFailureError + from a CancelledError. + """ + if env.supports_time_skipping: + pytest.skip( + "Standalone Nexus Operation tests don't work with time-skipping server" + ) + + task_queue = str(uuid.uuid4()) + endpoint_name = make_nexus_endpoint_name(task_queue) + + async with Worker( + client, + task_queue=task_queue, + nexus_service_handlers=[StandaloneTestServiceHandler()], + workflows=[EchoHandlerWorkflow, BlockingHandlerWorkflow], + ): + await env.create_nexus_endpoint(endpoint_name, task_queue) + + nexus_client = client.create_nexus_client( + service=StandaloneTestService, endpoint=endpoint_name + ) + handle = await nexus_client.start_operation( + StandaloneTestService.blocking_async, + EchoInput(value="cancel-me"), + id=str(uuid.uuid4()), + id_reuse_policy=NexusOperationIDReusePolicy.REJECT_DUPLICATE, + id_conflict_policy=NexusOperationIDConflictPolicy.FAIL, + schedule_to_close_timeout=timedelta(seconds=30), + ) + + # Cancel the operation + await handle.cancel() + + with pytest.raises(NexusOperationFailureError) as err: + await handle.result() + + assert err.value.__cause__ + assert isinstance(err.value.__cause__, CancelledError) + + +async def test_terminate_operation(client: Client, env: WorkflowEnvironment): + """Start blocking async op, terminate it, verify awaiting the result raises NexusOperationFailureError + from a TerminatedError. + """ + if env.supports_time_skipping: + pytest.skip( + "Standalone Nexus Operation tests don't work with time-skipping server" + ) + + task_queue = str(uuid.uuid4()) + endpoint_name = make_nexus_endpoint_name(task_queue) + + async with Worker( + client, + task_queue=task_queue, + nexus_service_handlers=[StandaloneTestServiceHandler()], + workflows=[EchoHandlerWorkflow, BlockingHandlerWorkflow], + ): + await env.create_nexus_endpoint(endpoint_name, task_queue) + + nexus_client = client.create_nexus_client( + service=StandaloneTestService, endpoint=endpoint_name + ) + handle = await nexus_client.start_operation( + StandaloneTestService.blocking_async, + EchoInput(value="terminate-me"), + id=str(uuid.uuid4()), + id_reuse_policy=NexusOperationIDReusePolicy.REJECT_DUPLICATE, + id_conflict_policy=NexusOperationIDConflictPolicy.FAIL, + schedule_to_close_timeout=timedelta(seconds=30), + ) + + # Terminate the operation + await handle.terminate(reason="test termination") + + with pytest.raises(NexusOperationFailureError) as err: + await handle.result() + + assert err.value.__cause__ + assert isinstance(err.value.__cause__, TerminatedError) + + +async def test_list_operations(client: Client, env: WorkflowEnvironment): + """Start multiple ops, list them, verify iteration yields correct results.""" + if env.supports_time_skipping: + pytest.skip( + "Standalone Nexus Operation tests don't work with time-skipping server" + ) + + task_queue = str(uuid.uuid4()) + endpoint_name = make_nexus_endpoint_name(task_queue) + + async with Worker( + client, + task_queue=task_queue, + nexus_service_handlers=[StandaloneTestServiceHandler()], + workflows=[EchoHandlerWorkflow, BlockingHandlerWorkflow], + ): + await env.create_nexus_endpoint(endpoint_name, task_queue) + + nexus_client = client.create_nexus_client( + service=StandaloneTestService, endpoint=endpoint_name + ) + + # Start several blocking operations so they remain visible + op_ids: list[str] = [] + for i in range(3): + op_id = str(uuid.uuid4()) + op_ids.append(op_id) + await nexus_client.start_operation( + StandaloneTestService.blocking_async, + EchoInput(value=f"list-{i}"), + id=op_id, + id_reuse_policy=NexusOperationIDReusePolicy.REJECT_DUPLICATE, + id_conflict_policy=NexusOperationIDConflictPolicy.FAIL, + schedule_to_close_timeout=timedelta(seconds=30), + ) + + # Poll until all 3 operations appear (visibility is eventually consistent) + query = f'Endpoint = "{endpoint_name}"' + + async def check_ids() -> None: + found_ids: set[str] = set() + async for op_exec in client.list_nexus_operations(query): + found_ids.add(op_exec.operation_id) + assert all(op_id in found_ids for op_id in op_ids) + + await assert_eventually(check_ids) + + +async def test_count_operations(client: Client, env: WorkflowEnvironment): + """Start ops, count, verify count.""" + if env.supports_time_skipping: + pytest.skip( + "Standalone Nexus Operation tests don't work with time-skipping server" + ) + + task_queue = str(uuid.uuid4()) + endpoint_name = make_nexus_endpoint_name(task_queue) + + async with Worker( + client, + task_queue=task_queue, + nexus_service_handlers=[StandaloneTestServiceHandler()], + workflows=[EchoHandlerWorkflow, BlockingHandlerWorkflow], + ): + await env.create_nexus_endpoint(endpoint_name, task_queue) + + nexus_client = client.create_nexus_client( + service=StandaloneTestService, endpoint=endpoint_name + ) + + # Start some blocking operations + for i in range(2): + await nexus_client.start_operation( + StandaloneTestService.blocking_async, + EchoInput(value=f"count-{i}"), + id=str(uuid.uuid4()), + id_reuse_policy=NexusOperationIDReusePolicy.REJECT_DUPLICATE, + id_conflict_policy=NexusOperationIDConflictPolicy.FAIL, + schedule_to_close_timeout=timedelta(seconds=30), + ) + + # Poll until count >= 2 (visibility is eventually consistent) + query = f'Endpoint = "{endpoint_name}"' + + async def check_count() -> None: + count_result = await client.count_nexus_operations(query) + assert count_result.count >= 2 + + await assert_eventually(check_count) + + +async def test_get_nexus_operation_handle(client: Client, env: WorkflowEnvironment): + """Start op, get result, then get handle by ID and get result again.""" + if env.supports_time_skipping: + pytest.skip( + "Standalone Nexus Operation tests don't work with time-skipping server" + ) + + task_queue = str(uuid.uuid4()) + endpoint_name = make_nexus_endpoint_name(task_queue) + + async with Worker( + client, + task_queue=task_queue, + nexus_service_handlers=[StandaloneTestServiceHandler()], + workflows=[EchoHandlerWorkflow, BlockingHandlerWorkflow], + ): + await env.create_nexus_endpoint(endpoint_name, task_queue) + + nexus_client = client.create_nexus_client( + service=StandaloneTestService, endpoint=endpoint_name + ) + + op_id = str(uuid.uuid4()) + original_handle = await nexus_client.start_operation( + StandaloneTestService.echo_async, + EchoInput(value="handle-test"), + id=op_id, + id_reuse_policy=NexusOperationIDReusePolicy.REJECT_DUPLICATE, + id_conflict_policy=NexusOperationIDConflictPolicy.FAIL, + schedule_to_close_timeout=timedelta(seconds=30), + ) + # Get result from the original handle first + original_result = await original_handle.result() + assert isinstance(original_result, EchoOutput) + assert original_result.value == "handle-test" + + # Get a fresh handle by ID and get result again + handle = client.get_nexus_operation_handle( + op_id, operation=StandaloneTestService.echo_async + ) + result = await handle.result() + assert isinstance(result, EchoOutput) + assert result.value == "handle-test" + + +async def test_id_conflict_policy_use_existing( + client: Client, env: WorkflowEnvironment +): + """Start op, re-start with USE_EXISTING, verify same op/run ID and expected result""" + if env.supports_time_skipping: + pytest.skip( + "Standalone Nexus Operation tests don't work with time-skipping server" + ) + + task_queue = str(uuid.uuid4()) + endpoint_name = make_nexus_endpoint_name(task_queue) + + service_handler = StandaloneTestServiceHandler() + + async with Worker( + client, + task_queue=task_queue, + nexus_service_handlers=[service_handler], + workflows=[EchoHandlerWorkflow, BlockingHandlerWorkflow], + ): + await env.create_nexus_endpoint(endpoint_name, task_queue) + + nexus_client = client.create_nexus_client( + service=StandaloneTestService, endpoint=endpoint_name + ) + + op_id = str(uuid.uuid4()) + + # First start + handle = await nexus_client.start_operation( + StandaloneTestService.blocking_async, + EchoInput(value=task_queue), + id=op_id, + id_reuse_policy=NexusOperationIDReusePolicy.ALLOW_DUPLICATE, + id_conflict_policy=NexusOperationIDConflictPolicy.USE_EXISTING, + schedule_to_close_timeout=timedelta(seconds=30), + ) + + # Second start with same ID and USE_EXISTING + handle2 = await nexus_client.start_operation( + StandaloneTestService.blocking_async, + EchoInput(value="second"), + id=op_id, + id_reuse_policy=NexusOperationIDReusePolicy.ALLOW_DUPLICATE, + id_conflict_policy=NexusOperationIDConflictPolicy.USE_EXISTING, + schedule_to_close_timeout=timedelta(seconds=30), + ) + assert handle.operation_id == handle2.operation_id + assert handle.run_id == handle2.run_id + + # Let the nexus operation run and start the blocking workflow + await service_handler.started_blocking.wait() + + expected_wf_id = f"blocking_async-{task_queue}" + wf_handle = env.client.get_workflow_handle(expected_wf_id) + + await wf_handle.start_update( + BlockingHandlerWorkflow.unblock, + wait_for_stage=WorkflowUpdateStage.COMPLETED, + ) + + first_result = await handle.result() + second_result = await handle2.result() + assert first_result.value == task_queue + assert first_result.value == second_result.value + + +async def test_id_conflict_policy_fail(client: Client, env: WorkflowEnvironment): + """Start op, re-start with FAIL, verify raises NexusOperationAlreadyStartedError.""" + if env.supports_time_skipping: + pytest.skip( + "Standalone Nexus Operation tests don't work with time-skipping server" + ) + + task_queue = str(uuid.uuid4()) + endpoint_name = make_nexus_endpoint_name(task_queue) + + async with Worker( + client, + task_queue=task_queue, + nexus_service_handlers=[StandaloneTestServiceHandler()], + workflows=[EchoHandlerWorkflow, BlockingHandlerWorkflow], + ): + await env.create_nexus_endpoint(endpoint_name, task_queue) + + nexus_client = client.create_nexus_client( + service=StandaloneTestService, endpoint=endpoint_name + ) + + op_id = str(uuid.uuid4()) + + # First start + await nexus_client.start_operation( + StandaloneTestService.blocking_async, + EchoInput(value="first"), + id=op_id, + id_reuse_policy=NexusOperationIDReusePolicy.REJECT_DUPLICATE, + id_conflict_policy=NexusOperationIDConflictPolicy.FAIL, + schedule_to_close_timeout=timedelta(seconds=30), + ) + + # Second start with same ID and FAIL should raise + with pytest.raises(NexusOperationAlreadyStartedError): + await nexus_client.start_operation( + StandaloneTestService.blocking_async, + EchoInput(value="second"), + id=op_id, + id_reuse_policy=NexusOperationIDReusePolicy.REJECT_DUPLICATE, + id_conflict_policy=NexusOperationIDConflictPolicy.FAIL, + schedule_to_close_timeout=timedelta(seconds=30), + ) + + +# --------------------------------------------------------------------------- +# Interceptor test +# --------------------------------------------------------------------------- + + +class _RecordingOutboundInterceptor(OutboundInterceptor): + """Outbound interceptor that records calls to nexus operation methods.""" + + def __init__( + self, next: OutboundInterceptor, parent: _RecordingInterceptor + ) -> None: + super().__init__(next) + self._parent = parent + + async def start_nexus_operation( + self, input: StartNexusOperationInput + ) -> NexusOperationHandle[Any]: + self._parent.start_calls.append(input) + return await super().start_nexus_operation(input) + + async def describe_nexus_operation( + self, input: DescribeNexusOperationInput + ) -> NexusOperationExecutionDescription: + self._parent.describe_calls.append(input) + return await super().describe_nexus_operation(input) + + async def get_nexus_operation_result( + self, input: GetNexusOperationResultInput + ) -> Any: + self._parent.result_calls.append(input) + return await super().get_nexus_operation_result(input) + + async def cancel_nexus_operation(self, input: CancelNexusOperationInput) -> None: + self._parent.cancel_calls.append(input) + return await super().cancel_nexus_operation(input) + + async def terminate_nexus_operation( + self, input: TerminateNexusOperationInput + ) -> None: + self._parent.terminate_calls.append(input) + return await super().terminate_nexus_operation(input) + + def list_nexus_operations(self, input: ListNexusOperationsInput): + self._parent.list_calls.append(input) + return super().list_nexus_operations(input) + + async def count_nexus_operations(self, input: CountNexusOperationsInput): + self._parent.count_calls.append(input) + return await super().count_nexus_operations(input) + + +class _RecordingInterceptor(Interceptor): + """Client interceptor that records nexus operation calls.""" + + def __init__(self) -> None: + super().__init__() + self.start_calls: list[StartNexusOperationInput] = [] + self.describe_calls: list[DescribeNexusOperationInput] = [] + self.result_calls: list[GetNexusOperationResultInput] = [] + self.cancel_calls: list[CancelNexusOperationInput] = [] + self.terminate_calls: list[TerminateNexusOperationInput] = [] + self.list_calls: list[ListNexusOperationsInput] = [] + self.count_calls: list[CountNexusOperationsInput] = [] + + def intercept_client(self, next: OutboundInterceptor) -> OutboundInterceptor: + return _RecordingOutboundInterceptor(next, self) + + +async def test_interceptor_receives_inputs(client: Client, env: WorkflowEnvironment): + """Custom OutboundInterceptor records calls, verify correct input types.""" + if env.supports_time_skipping: + pytest.skip( + "Standalone Nexus Operation tests don't work with time-skipping server" + ) + + task_queue = str(uuid.uuid4()) + endpoint_name = make_nexus_endpoint_name(task_queue) + + interceptor = _RecordingInterceptor() + intercepted_client = Client( + service_client=client.service_client, + namespace=client.namespace, + interceptors=[interceptor], + ) + + async with Worker( + client, + task_queue=task_queue, + nexus_service_handlers=[StandaloneTestServiceHandler()], + workflows=[EchoHandlerWorkflow, BlockingHandlerWorkflow], + ): + await env.create_nexus_endpoint(endpoint_name, task_queue) + + nexus_client = intercepted_client.create_nexus_client( + service=StandaloneTestService, endpoint=endpoint_name + ) + + op_id = str(uuid.uuid4()) + + # Start operation -- should trigger start interceptor (with retry) + handle = await nexus_client.start_operation( + StandaloneTestService.blocking_async, + EchoInput(value=f"interceptor-test-{op_id}"), + id=op_id, + id_reuse_policy=NexusOperationIDReusePolicy.REJECT_DUPLICATE, + id_conflict_policy=NexusOperationIDConflictPolicy.FAIL, + schedule_to_close_timeout=timedelta(seconds=30), + schedule_to_start_timeout=timedelta(seconds=5), + start_to_close_timeout=timedelta(seconds=20), + ) + assert len(interceptor.start_calls) >= 1 + start_input = interceptor.start_calls[-1] + assert isinstance(start_input, StartNexusOperationInput) + assert start_input.id == op_id + assert start_input.operation == "blocking_async" + assert start_input.endpoint == endpoint_name + assert start_input.service == "StandaloneTestService" + assert start_input.schedule_to_start_timeout == timedelta(seconds=5) + assert start_input.start_to_close_timeout == timedelta(seconds=20) + + # Describe + await handle.describe() + assert len(interceptor.describe_calls) == 1 + desc_input = interceptor.describe_calls[0] + assert isinstance(desc_input, DescribeNexusOperationInput) + assert desc_input.operation_id == op_id + + # Cancel + await handle.cancel() + assert len(interceptor.cancel_calls) == 1 + cancel_input = interceptor.cancel_calls[0] + assert isinstance(cancel_input, CancelNexusOperationInput) + assert cancel_input.operation_id == op_id + + # GetResult + with pytest.raises(NexusOperationFailureError): + await handle.result() + assert len(interceptor.result_calls) == 1 + result_input = interceptor.result_calls[0] + assert isinstance(result_input, GetNexusOperationResultInput) + assert result_input.operation_id == op_id + assert result_input.result_type == EchoOutput + + # Start another so we can terminate it + previous_start_count = len(interceptor.start_calls) + op_id = str(uuid.uuid4()) + handle = await nexus_client.start_operation( + StandaloneTestService.blocking_async, + EchoInput(value=f"interceptor-test-{op_id}"), + id=op_id, + id_reuse_policy=NexusOperationIDReusePolicy.REJECT_DUPLICATE, + id_conflict_policy=NexusOperationIDConflictPolicy.FAIL, + schedule_to_close_timeout=timedelta(seconds=30), + ) + assert len(interceptor.start_calls) > previous_start_count + + # Terminate + await handle.terminate() + assert len(interceptor.terminate_calls) == 1 + terminate_input = interceptor.terminate_calls[0] + assert isinstance(terminate_input, TerminateNexusOperationInput) + assert terminate_input.operation_id == op_id + + query = f'`OperationId`="{op_id}"' + + # List Operations + # Iterate over list to ensure call is made + async for _ in intercepted_client.list_nexus_operations(query): + pass + assert len(interceptor.list_calls) >= 1 + list_input = interceptor.list_calls[-1] + assert isinstance(list_input, ListNexusOperationsInput) + assert list_input.query == query + + # Count Operations + await intercepted_client.count_nexus_operations(query) + assert len(interceptor.count_calls) >= 1 + count_input = interceptor.count_calls[-1] + assert isinstance(count_input, CountNexusOperationsInput) + assert count_input.query == query diff --git a/tests/nexus/test_type_errors.py b/tests/nexus/test_type_errors.py deleted file mode 100644 index 1f5d3e2a7..000000000 --- a/tests/nexus/test_type_errors.py +++ /dev/null @@ -1,207 +0,0 @@ -""" -This file exists to test for type-checker false positives and false negatives. -It doesn't contain any test functions. -""" - -from dataclasses import dataclass - -import nexusrpc - -import temporalio.nexus -from temporalio import workflow - - -@dataclass -class MyInput: - pass - - -@dataclass -class MyOutput: - pass - - -@nexusrpc.service -class MyService: - my_sync_operation: nexusrpc.Operation[MyInput, MyOutput] - my_workflow_run_operation: nexusrpc.Operation[MyInput, MyOutput] - - -@nexusrpc.handler.service_handler(service=MyService) -class MyServiceHandler: - @nexusrpc.handler.sync_operation - async def my_sync_operation( - self, _ctx: nexusrpc.handler.StartOperationContext, _input: MyInput - ) -> MyOutput: - raise NotImplementedError - - @temporalio.nexus.workflow_run_operation - async def my_workflow_run_operation( - self, _ctx: temporalio.nexus.WorkflowRunOperationContext, _input: MyInput - ) -> temporalio.nexus.WorkflowHandle[MyOutput]: - raise NotImplementedError - - -@nexusrpc.handler.service_handler(service=MyService) -class MyServiceHandler2: - @nexusrpc.handler.sync_operation - async def my_sync_operation( - self, _ctx: nexusrpc.handler.StartOperationContext, _input: MyInput - ) -> MyOutput: - raise NotImplementedError - - @temporalio.nexus.workflow_run_operation - async def my_workflow_run_operation( - self, _ctx: temporalio.nexus.WorkflowRunOperationContext, _input: MyInput - ) -> temporalio.nexus.WorkflowHandle[MyOutput]: - raise NotImplementedError - - -@nexusrpc.handler.service_handler -class MyServiceHandlerWithoutServiceDefinition: - @nexusrpc.handler.sync_operation - async def my_sync_operation( - self, _ctx: nexusrpc.handler.StartOperationContext, _input: MyInput - ) -> MyOutput: - raise NotImplementedError - - @temporalio.nexus.workflow_run_operation - async def my_workflow_run_operation( - self, _ctx: temporalio.nexus.WorkflowRunOperationContext, _input: MyInput - ) -> temporalio.nexus.WorkflowHandle[MyOutput]: - raise NotImplementedError - - -@workflow.defn -class MyWorkflow1: - @workflow.run - async def test_invoke_by_operation_definition_happy_path(self) -> None: - """ - When a nexus client calls an operation by referencing an operation definition on - a service definition, the output type is inferred correctly. - """ - nexus_client = workflow.create_nexus_client( - service=MyService, - endpoint="fake-endpoint", - ) - input = MyInput() - - # sync operation - _output_1: MyOutput = await nexus_client.execute_operation( - MyService.my_sync_operation, input - ) - _handle_1: workflow.NexusOperationHandle[ - MyOutput - ] = await nexus_client.start_operation(MyService.my_sync_operation, input) - _output_1_1: MyOutput = await _handle_1 - - # workflow run operation - _output_2: MyOutput = await nexus_client.execute_operation( - MyService.my_workflow_run_operation, input - ) - _handle_2: workflow.NexusOperationHandle[ - MyOutput - ] = await nexus_client.start_operation( - MyService.my_workflow_run_operation, input - ) - _output_2_1: MyOutput = await _handle_2 - - -@workflow.defn -class MyWorkflow2: - @workflow.run - async def test_invoke_by_operation_handler_happy_path(self) -> None: - """ - When a nexus client calls an operation by referencing an operation handler on a - service handler, the output type is inferred correctly. - """ - nexus_client = workflow.create_nexus_client( - service=MyServiceHandler, # MyService would also work - endpoint="fake-endpoint", - ) - input = MyInput() - - # sync operation - _output_1: MyOutput = await nexus_client.execute_operation( - MyServiceHandler.my_sync_operation, input - ) - _handle_1: workflow.NexusOperationHandle[ - MyOutput - ] = await nexus_client.start_operation( - MyServiceHandler.my_sync_operation, input - ) - _output_1_1: MyOutput = await _handle_1 - - # workflow run operation - _output_2: MyOutput = await nexus_client.execute_operation( - MyServiceHandler.my_workflow_run_operation, input - ) - _handle_2: workflow.NexusOperationHandle[ - MyOutput - ] = await nexus_client.start_operation( - MyServiceHandler.my_workflow_run_operation, input - ) - _output_2_1: MyOutput = await _handle_2 - - -@workflow.defn -class MyWorkflow3: - @workflow.run - async def test_invoke_by_operation_definition_wrong_input_type(self) -> None: - """ - When a nexus client calls an operation by referencing an operation definition on - a service definition, there is a type error if the input type is wrong. - """ - nexus_client = workflow.create_nexus_client( - service=MyService, - endpoint="fake-endpoint", - ) - # assert-type-error-pyright: 'No overloads for "execute_operation" match' - await nexus_client.execute_operation( # type: ignore - MyService.my_sync_operation, - # assert-type-error-pyright: 'Argument of type .+ cannot be assigned to parameter "input"' - "wrong-input-type", # type: ignore - ) - - -@workflow.defn -class MyWorkflow4: - @workflow.run - async def test_invoke_by_operation_handler_wrong_input_type(self) -> None: - """ - When a nexus client calls an operation by referencing an operation handler on a - service handler, there is a type error if the input type is wrong. - """ - nexus_client = workflow.create_nexus_client( - service=MyServiceHandler, - endpoint="fake-endpoint", - ) - # assert-type-error-pyright: 'No overloads for "execute_operation" match' - await nexus_client.execute_operation( # type: ignore - MyServiceHandler.my_sync_operation, # type: ignore[arg-type] - # assert-type-error-pyright: 'Argument of type .+ cannot be assigned to parameter "input"' - "wrong-input-type", # type: ignore - ) - - -@workflow.defn -class MyWorkflow5: - @workflow.run - async def test_invoke_by_operation_handler_method_on_wrong_service(self) -> None: - """ - When a nexus client calls an operation by referencing an operation handler method - on a service handler, there is a type error if the method does not belong to the - service for which the client was created. - - (This form of type safety is not available when referencing an operation definition) - """ - nexus_client = workflow.create_nexus_client( - service=MyServiceHandler, - endpoint="fake-endpoint", - ) - # assert-type-error-pyright: 'No overloads for "execute_operation" match' - await nexus_client.execute_operation( # type: ignore - # assert-type-error-pyright: 'Argument of type .+ cannot be assigned to parameter "operation"' - MyServiceHandler2.my_sync_operation, # type: ignore - MyInput(), - ) diff --git a/tests/test_workflow_exports.py b/tests/test_workflow_exports.py index 5beee5c61..e67040b64 100644 --- a/tests/test_workflow_exports.py +++ b/tests/test_workflow_exports.py @@ -47,7 +47,6 @@ "SandboxImportNotificationPolicy", "SelfType", "ServiceHandlerT", - "ServiceT", "UnfinishedSignalHandlersWarning", "UnfinishedUpdateHandlersWarning", "UpdateInfo", diff --git a/uv.lock b/uv.lock index f378016db..ab1b9974f 100644 --- a/uv.lock +++ b/uv.lock @@ -4404,6 +4404,18 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/9d/7a/d968e294073affff457b041c2be9868a40c1c71f4a35fcc1e45e5493067b/pytest_cov-7.1.0-py3-none-any.whl", hash = "sha256:a0461110b7865f9a271aa1b51e516c9a95de9d696734a2f71e3e78f46e1d4678", size = 22876, upload-time = "2026-03-21T20:11:14.438Z" }, ] +[[package]] +name = "pytest-flakefinder" +version = "1.1.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "pytest" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/ec/53/69c56a93ea057895b5761c5318455804873a6cd9d796d7c55d41c2358125/pytest-flakefinder-1.1.0.tar.gz", hash = "sha256:e2412a1920bdb8e7908783b20b3d57e9dad590cc39a93e8596ffdd493b403e0e", size = 6795, upload-time = "2022-10-26T18:27:54.243Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/33/8b/06787150d0fd0cbd3a8054262b56f91631c7778c1bc91bf4637e47f909ad/pytest_flakefinder-1.1.0-py2.py3-none-any.whl", hash = "sha256:741e0e8eea427052f5b8c89c2b3c3019a50c39a59ce4df6a305a2c2d9ba2bd13", size = 4644, upload-time = "2022-10-26T18:27:52.128Z" }, +] + [[package]] name = "pytest-pretty" version = "1.3.0" @@ -5219,6 +5231,7 @@ dev = [ { name = "pytest" }, { name = "pytest-asyncio" }, { name = "pytest-cov" }, + { name = "pytest-flakefinder" }, { name = "pytest-pretty" }, { name = "pytest-rerunfailures" }, { name = "pytest-timeout" }, @@ -5284,6 +5297,7 @@ dev = [ { name = "pytest", specifier = "~=9.0" }, { name = "pytest-asyncio", specifier = ">=0.21,<0.22" }, { name = "pytest-cov", specifier = ">=6.1.1" }, + { name = "pytest-flakefinder", specifier = ">=1.1.0" }, { name = "pytest-pretty", specifier = ">=1.3.0" }, { name = "pytest-rerunfailures", specifier = ">=16.1" }, { name = "pytest-timeout", specifier = "~=2.2" }, From ac6d4861902f0b47babffa93dfb5b7da396b2ff7 Mon Sep 17 00:00:00 2001 From: Edward Amsden Date: Thu, 21 May 2026 18:05:35 -0500 Subject: [PATCH 100/226] Drop macos-intel from CI (#1553) * Drop macos-intel from CI * Put back binary build for macos intel --- .github/workflows/ci.yml | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 6294f6d9a..8721ad806 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -21,7 +21,7 @@ jobs: fail-fast: false matrix: python: ["3.10", "3.14"] - os: [ubuntu-latest, ubuntu-arm, macos-intel, macos-arm, windows-latest] + os: [ubuntu-latest, ubuntu-arm, macos-arm, windows-latest] include: - os: ubuntu-latest python: "3.14" @@ -29,11 +29,9 @@ jobs: openaiTestTarget: true clippyLinter: true - python: "3.10" - pytestExtraArgs: "--reruns 3 --only-rerun \"RuntimeError: Failed validating workflow\"" + pytestExtraArgs: '--reruns 3 --only-rerun "RuntimeError: Failed validating workflow"' - os: ubuntu-arm runsOn: ubuntu-24.04-arm64-2-core - - os: macos-intel - runsOn: macos-15-intel - os: macos-arm runsOn: macos-latest runs-on: ${{ matrix.runsOn || matrix.os }} From 595e4dc91f8d3e15ef9cc4dd0fec610f224fafd7 Mon Sep 17 00:00:00 2001 From: Brian Strauch Date: Thu, 21 May 2026 20:35:06 -0700 Subject: [PATCH 101/226] ci: key Rust cache on resolved Python version (#1554) * ci: key Rust cache on resolved Python version The Swatinem/rust-cache key didn't include Python's patch version, so when the runner image bumped Python (e.g. 3.14.4 -> 3.14.5) the restored build artifacts kept absolute LIBPATH entries pointing at the prior install dir and the link step failed with LNK1181 looking for python3.lib in the old 3.14.4 path. Reorder setup-python before rust-cache so its output is available, and append the full python-version to the cache key. * ci: use env.pythonLocation as Rust cache key Replace the steps-output approach with the env var setup-python sets automatically, removing the need to assign each step an id. --- .github/workflows/build-binaries.yml | 1 + .github/workflows/ci.yml | 28 ++++++++++++++++------------ .github/workflows/run-bench.yml | 7 ++++--- 3 files changed, 21 insertions(+), 15 deletions(-) diff --git a/.github/workflows/build-binaries.yml b/.github/workflows/build-binaries.yml index fb565aaf1..eb95216d0 100644 --- a/.github/workflows/build-binaries.yml +++ b/.github/workflows/build-binaries.yml @@ -47,6 +47,7 @@ jobs: with: cache-bin: false workspaces: temporalio/bridge -> target + key: ${{ env.pythonLocation }} - uses: astral-sh/setup-uv@cec208311dfd045dd5311c1add060b2062131d57 # v8 - run: uv sync --all-extras diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8721ad806..2bdc06191 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -42,12 +42,13 @@ jobs: - uses: dtolnay/rust-toolchain@29eef336d9b2848a0b548edc03f92a220660cdb8 # stable with: components: "clippy" - - uses: Swatinem/rust-cache@e18b497796c12c097a38f9edb9d0641fb99eee32 # v2 - with: - workspaces: temporalio/bridge -> target - uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5 with: python-version: ${{ matrix.pythonOverride || matrix.python }} + - uses: Swatinem/rust-cache@e18b497796c12c097a38f9edb9d0641fb99eee32 # v2 + with: + workspaces: temporalio/bridge -> target + key: ${{ env.pythonLocation }} - uses: arduino/setup-protoc@c65c819552d16ad3c9b72d9dfd5ba5237b9c906b # v3 with: # TODO(cretz): Can upgrade proto when https://github.com/arduino/setup-protoc/issues/99 fixed @@ -107,12 +108,13 @@ jobs: with: submodules: recursive - uses: dtolnay/rust-toolchain@29eef336d9b2848a0b548edc03f92a220660cdb8 # stable - - uses: Swatinem/rust-cache@e18b497796c12c097a38f9edb9d0641fb99eee32 # v2 - with: - workspaces: temporalio/bridge -> target - uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5 with: python-version: "3.10" + - uses: Swatinem/rust-cache@e18b497796c12c097a38f9edb9d0641fb99eee32 # v2 + with: + workspaces: temporalio/bridge -> target + key: ${{ env.pythonLocation }} - uses: arduino/setup-protoc@c65c819552d16ad3c9b72d9dfd5ba5237b9c906b # v3 with: # TODO(cretz): Can upgrade proto when https://github.com/arduino/setup-protoc/issues/99 fixed @@ -143,12 +145,13 @@ jobs: - uses: dtolnay/rust-toolchain@29eef336d9b2848a0b548edc03f92a220660cdb8 # stable with: components: "clippy" - - uses: Swatinem/rust-cache@e18b497796c12c097a38f9edb9d0641fb99eee32 # v2 - with: - workspaces: temporalio/bridge -> target - uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5 with: python-version: "3.13" + - uses: Swatinem/rust-cache@e18b497796c12c097a38f9edb9d0641fb99eee32 # v2 + with: + workspaces: temporalio/bridge -> target + key: ${{ env.pythonLocation }} - uses: arduino/setup-protoc@c65c819552d16ad3c9b72d9dfd5ba5237b9c906b # v3 with: # TODO(cretz): Can upgrade proto when https://github.com/arduino/setup-protoc/issues/99 fixed @@ -181,12 +184,13 @@ jobs: with: submodules: recursive - uses: dtolnay/rust-toolchain@29eef336d9b2848a0b548edc03f92a220660cdb8 # stable - - uses: Swatinem/rust-cache@e18b497796c12c097a38f9edb9d0641fb99eee32 # v2 - with: - workspaces: temporalio/bridge -> target - uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5 with: python-version: "3.14" + - uses: Swatinem/rust-cache@e18b497796c12c097a38f9edb9d0641fb99eee32 # v2 + with: + workspaces: temporalio/bridge -> target + key: ${{ env.pythonLocation }} - uses: arduino/setup-protoc@c65c819552d16ad3c9b72d9dfd5ba5237b9c906b # v3 with: # TODO(cretz): Can upgrade proto when https://github.com/arduino/setup-protoc/issues/99 fixed diff --git a/.github/workflows/run-bench.yml b/.github/workflows/run-bench.yml index eb2868bb2..6b9a17da8 100644 --- a/.github/workflows/run-bench.yml +++ b/.github/workflows/run-bench.yml @@ -35,13 +35,14 @@ jobs: - uses: dtolnay/rust-toolchain@29eef336d9b2848a0b548edc03f92a220660cdb8 # stable with: toolchain: stable + - uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5 + with: + python-version: "3.13" - uses: Swatinem/rust-cache@e18b497796c12c097a38f9edb9d0641fb99eee32 # v2 with: cache-bin: false workspaces: temporalio/bridge -> target - - uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5 - with: - python-version: "3.13" + key: ${{ env.pythonLocation }} - uses: arduino/setup-protoc@c65c819552d16ad3c9b72d9dfd5ba5237b9c906b # v3 with: # TODO(cretz): Can upgrade proto when https://github.com/arduino/setup-protoc/issues/99 fixed From f0c6afbf6e81f0fc511c8c1ea7a3d975c44a29e8 Mon Sep 17 00:00:00 2001 From: tconley1428 Date: Fri, 22 May 2026 09:46:19 -0700 Subject: [PATCH 102/226] Enabled frontend.enableCancelWorkerPollsOnShutdown in tests (#1555) * Enabled frontend.enableCancelWorkerPollsOnShutdown in tests * Missed comma --- tests/conftest.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/conftest.py b/tests/conftest.py index 2005dbe57..1e1db3730 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -119,6 +119,8 @@ async def env(env_type: str) -> AsyncGenerator[WorkflowEnvironment, None]: "--dynamic-config-value", "frontend.activityAPIsEnabled=true", "--dynamic-config-value", + "frontend.enableCancelWorkerPollsOnShutdown=true", + "--dynamic-config-value", "component.nexusoperations.recordCancelRequestCompletionEvents=true", "--dynamic-config-value", "activity.enableStandalone=true", From 91abc81a8d703a5ec1db45b0a76ab0580e498d62 Mon Sep 17 00:00:00 2001 From: Alex Mazzeo Date: Fri, 22 May 2026 10:54:37 -0700 Subject: [PATCH 103/226] Narrow overloads on the SANO client (#1552) * Narrow overloads on the sano client. * remove result_type params for overloads that don't need them * Add test to show that invalid functions produce a type error * address linter errors --- temporalio/client/_nexus.py | 139 +++++++++++++++++++------- tests/nexus/test_nexus_type_errors.py | 47 +++++---- 2 files changed, 133 insertions(+), 53 deletions(-) diff --git a/temporalio/client/_nexus.py b/temporalio/client/_nexus.py index 991ab34a3..060235e01 100644 --- a/temporalio/client/_nexus.py +++ b/temporalio/client/_nexus.py @@ -1,7 +1,7 @@ from __future__ import annotations from abc import ABC, abstractmethod -from collections.abc import Callable, Mapping, Sequence +from collections.abc import Awaitable, Callable, Mapping, Sequence from dataclasses import dataclass, field from datetime import datetime, timedelta, timezone from typing import TYPE_CHECKING, Any, Generic, cast, overload @@ -473,7 +473,7 @@ class NexusClient(ABC, Generic[NexusServiceType]): Use :py:meth:`Client.create_nexus_client` to create a client. """ - # Overload for nexusrpc.Operation with input + # Overload for nexusrpc.Operation @overload @abstractmethod async def start_operation( @@ -494,18 +494,18 @@ async def start_operation( rpc_timeout: timedelta | None = None, ) -> NexusOperationHandle[OutputT]: ... - # Overload for Callable with result_type + # Overload for string operation name @overload @abstractmethod async def start_operation( self, - operation: Callable[..., Any], + operation: str, arg: Any, *, id: str, id_reuse_policy: temporalio.common.NexusOperationIDReusePolicy = temporalio.common.NexusOperationIDReusePolicy.ALLOW_DUPLICATE, id_conflict_policy: temporalio.common.NexusOperationIDConflictPolicy = temporalio.common.NexusOperationIDConflictPolicy.FAIL, - result_type: type[OutputT], + result_type: type[OutputT] | None = None, schedule_to_close_timeout: timedelta | None = None, schedule_to_start_timeout: timedelta | None = None, start_to_close_timeout: timedelta | None = None, @@ -516,13 +516,16 @@ async def start_operation( rpc_timeout: timedelta | None = None, ) -> NexusOperationHandle[OutputT]: ... - # Overload for Callable without result_type + # Overload for workflow_run_operation methods @overload @abstractmethod async def start_operation( self, - operation: Callable[..., Any], - arg: Any, + operation: Callable[ + [NexusServiceType, temporalio.nexus.WorkflowRunOperationContext, InputT], + Awaitable[temporalio.nexus.WorkflowHandle[OutputT]], + ], + arg: InputT, *, id: str, id_reuse_policy: temporalio.common.NexusOperationIDReusePolicy = temporalio.common.NexusOperationIDReusePolicy.ALLOW_DUPLICATE, @@ -535,20 +538,22 @@ async def start_operation( headers: Mapping[str, str] | None = None, rpc_metadata: Mapping[str, str | bytes] = {}, rpc_timeout: timedelta | None = None, - ) -> NexusOperationHandle[Any]: ... + ) -> NexusOperationHandle[OutputT]: ... - # Overload for str with result_type + # Overload for sync_operation methods (async def) @overload @abstractmethod async def start_operation( self, - operation: str, - arg: Any, + operation: Callable[ + [NexusServiceType, nexusrpc.handler.StartOperationContext, InputT], + Awaitable[OutputT], + ], + arg: InputT, *, id: str, id_reuse_policy: temporalio.common.NexusOperationIDReusePolicy = temporalio.common.NexusOperationIDReusePolicy.ALLOW_DUPLICATE, id_conflict_policy: temporalio.common.NexusOperationIDConflictPolicy = temporalio.common.NexusOperationIDConflictPolicy.FAIL, - result_type: type[OutputT], schedule_to_close_timeout: timedelta | None = None, schedule_to_start_timeout: timedelta | None = None, start_to_close_timeout: timedelta | None = None, @@ -559,13 +564,16 @@ async def start_operation( rpc_timeout: timedelta | None = None, ) -> NexusOperationHandle[OutputT]: ... - # Overload for str without result_type + # Overload for sync_operation methods (def) @overload @abstractmethod async def start_operation( self, - operation: str, - arg: Any, + operation: Callable[ + [NexusServiceType, nexusrpc.handler.StartOperationContext, InputT], + OutputT, + ], + arg: InputT, *, id: str, id_reuse_policy: temporalio.common.NexusOperationIDReusePolicy = temporalio.common.NexusOperationIDReusePolicy.ALLOW_DUPLICATE, @@ -578,7 +586,30 @@ async def start_operation( headers: Mapping[str, str] | None = None, rpc_metadata: Mapping[str, str | bytes] = {}, rpc_timeout: timedelta | None = None, - ) -> NexusOperationHandle[Any]: ... + ) -> NexusOperationHandle[OutputT]: ... + + # Overload for operation_handler + @overload + @abstractmethod + async def start_operation( + self, + operation: Callable[ + [NexusServiceType], nexusrpc.handler.OperationHandler[InputT, OutputT] + ], + arg: InputT, + *, + id: str, + id_reuse_policy: temporalio.common.NexusOperationIDReusePolicy = temporalio.common.NexusOperationIDReusePolicy.ALLOW_DUPLICATE, + id_conflict_policy: temporalio.common.NexusOperationIDConflictPolicy = temporalio.common.NexusOperationIDConflictPolicy.FAIL, + schedule_to_close_timeout: timedelta | None = None, + schedule_to_start_timeout: timedelta | None = None, + start_to_close_timeout: timedelta | None = None, + search_attributes: temporalio.common.TypedSearchAttributes | None = None, + summary: str | None = None, + headers: Mapping[str, str] | None = None, + rpc_metadata: Mapping[str, str | bytes] = {}, + rpc_timeout: timedelta | None = None, + ) -> NexusOperationHandle[OutputT]: ... @abstractmethod async def start_operation( @@ -611,7 +642,8 @@ async def start_operation( id: Unique identifier for this operation. id_reuse_policy: Policy for reusing operation IDs. id_conflict_policy: Policy for handling ID conflicts. - result_type: The result type to deserialize into. + result_type: For string operation names, this can set the specific + result type hint to deserialize into. schedule_to_close_timeout: End-to-end timeout for the Nexus operation. If unset, defaults to the maximum allowed by the Temporal server. @@ -633,7 +665,7 @@ async def start_operation( """ ... - # Overload for nexusrpc.Operation with input + # Overload for nexusrpc.Operation @overload @abstractmethod async def execute_operation( @@ -654,18 +686,18 @@ async def execute_operation( rpc_timeout: timedelta | None = None, ) -> OutputT: ... - # Overload for Callable with result_type + # Overload for string operation name @overload @abstractmethod async def execute_operation( self, - operation: Callable[..., Any], + operation: str, arg: Any, *, id: str, id_reuse_policy: temporalio.common.NexusOperationIDReusePolicy = temporalio.common.NexusOperationIDReusePolicy.ALLOW_DUPLICATE, id_conflict_policy: temporalio.common.NexusOperationIDConflictPolicy = temporalio.common.NexusOperationIDConflictPolicy.FAIL, - result_type: type[OutputT], + result_type: type[OutputT] | None = None, schedule_to_close_timeout: timedelta | None = None, schedule_to_start_timeout: timedelta | None = None, start_to_close_timeout: timedelta | None = None, @@ -676,13 +708,16 @@ async def execute_operation( rpc_timeout: timedelta | None = None, ) -> OutputT: ... - # Overload for Callable without result_type + # Overload for workflow_run_operation methods @overload @abstractmethod async def execute_operation( self, - operation: Callable[..., Any], - arg: Any, + operation: Callable[ + [NexusServiceType, temporalio.nexus.WorkflowRunOperationContext, InputT], + Awaitable[temporalio.nexus.WorkflowHandle[OutputT]], + ], + arg: InputT, *, id: str, id_reuse_policy: temporalio.common.NexusOperationIDReusePolicy = temporalio.common.NexusOperationIDReusePolicy.ALLOW_DUPLICATE, @@ -695,20 +730,22 @@ async def execute_operation( headers: Mapping[str, str] | None = None, rpc_metadata: Mapping[str, str | bytes] = {}, rpc_timeout: timedelta | None = None, - ) -> Any: ... + ) -> OutputT: ... - # Overload for str with result_type + # Overload for sync_operation methods (async def) @overload @abstractmethod async def execute_operation( self, - operation: str, - arg: Any, + operation: Callable[ + [NexusServiceType, nexusrpc.handler.StartOperationContext, InputT], + Awaitable[OutputT], + ], + arg: InputT, *, id: str, id_reuse_policy: temporalio.common.NexusOperationIDReusePolicy = temporalio.common.NexusOperationIDReusePolicy.ALLOW_DUPLICATE, id_conflict_policy: temporalio.common.NexusOperationIDConflictPolicy = temporalio.common.NexusOperationIDConflictPolicy.FAIL, - result_type: type[OutputT], schedule_to_close_timeout: timedelta | None = None, schedule_to_start_timeout: timedelta | None = None, start_to_close_timeout: timedelta | None = None, @@ -719,13 +756,40 @@ async def execute_operation( rpc_timeout: timedelta | None = None, ) -> OutputT: ... - # Overload for str without result_type + # Overload for sync_operation methods (async def) @overload @abstractmethod async def execute_operation( self, - operation: str, - arg: Any, + operation: Callable[ + [NexusServiceType, nexusrpc.handler.StartOperationContext, InputT], + OutputT, + ], + arg: InputT, + *, + id: str, + id_reuse_policy: temporalio.common.NexusOperationIDReusePolicy = temporalio.common.NexusOperationIDReusePolicy.ALLOW_DUPLICATE, + id_conflict_policy: temporalio.common.NexusOperationIDConflictPolicy = temporalio.common.NexusOperationIDConflictPolicy.FAIL, + schedule_to_close_timeout: timedelta | None = None, + schedule_to_start_timeout: timedelta | None = None, + start_to_close_timeout: timedelta | None = None, + search_attributes: temporalio.common.TypedSearchAttributes | None = None, + summary: str | None = None, + headers: Mapping[str, str] | None = None, + rpc_metadata: Mapping[str, str | bytes] = {}, + rpc_timeout: timedelta | None = None, + ) -> OutputT: ... + + # Overload for operation_handler + @overload + @abstractmethod + async def execute_operation( + self, + operation: Callable[ + [NexusServiceType], + nexusrpc.handler.OperationHandler[InputT, OutputT], + ], + arg: InputT, *, id: str, id_reuse_policy: temporalio.common.NexusOperationIDReusePolicy = temporalio.common.NexusOperationIDReusePolicy.ALLOW_DUPLICATE, @@ -738,7 +802,7 @@ async def execute_operation( headers: Mapping[str, str] | None = None, rpc_metadata: Mapping[str, str | bytes] = {}, rpc_timeout: timedelta | None = None, - ) -> Any: ... + ) -> OutputT: ... @abstractmethod async def execute_operation( @@ -773,7 +837,8 @@ async def execute_operation( id: Unique identifier for this operation. id_reuse_policy: Policy for reusing operation IDs. id_conflict_policy: Policy for handling ID conflicts. - result_type: The result type to deserialize into. + result_type: For string operation names, this can set the specific + result type hint to deserialize into. schedule_to_close_timeout: End-to-end timeout for the Nexus operation. If unset, defaults to the maximum allowed by the Temporal server. @@ -860,7 +925,9 @@ async def start_operation( This API is experimental and unstable. """ op_name, output_type = self._resolve_operation(operation) - final_result_type: type | None = result_type or output_type + final_result_type: type | None = ( + result_type if isinstance(operation, str) else output_type + ) return await self._client._impl.start_nexus_operation( StartNexusOperationInput( diff --git a/tests/nexus/test_nexus_type_errors.py b/tests/nexus/test_nexus_type_errors.py index c669f8a5b..f97aeae42 100644 --- a/tests/nexus/test_nexus_type_errors.py +++ b/tests/nexus/test_nexus_type_errors.py @@ -238,14 +238,13 @@ async def standalone_operation_type_tests(): start_to_close_timeout=timedelta(seconds=2), ) - # result_type overrides output type from operation definition - # conflicting result_type and annotation on variable cause type error - # assert-type-error-pyright: 'Type "str" is not assignable to declared type "MyOutput"' - _bad_result_type_output: MyOutput = await nexus_client.execute_operation( # type: ignore - MyServiceHandler.my_sync_operation, + # result_type is not allowed when an operation is provided + await nexus_client.execute_operation( + # assert-type-error-pyright: 'cannot be assigned to parameter "operation" of type "str"' + MyService.my_sync_operation, # type: ignore MyInput(), id="op-1", - result_type=str, # type: ignore + result_type=str, ) # string operation name and result_type infers output type @@ -337,19 +336,14 @@ async def standalone_operation_type_tests(): ) _defn_handle_output: MyOutput = await _defn_handle.result() - # result_type overrides output type from operation definition - # conflicting result_type and annotation on variable cause type error - _result_type_handle: NexusOperationHandle[ - MyOutput - # assert-type-error-pyright: 'Type "NexusOperationHandle\[str\]" is not assignable to declared type "NexusOperationHandle\[MyOutput\]"' - ] = await nexus_client.start_operation( # type: ignore - MyServiceHandler.my_sync_operation, + # result_type is not allowed when an operation is provided + await nexus_client.start_operation( + # assert-type-error-pyright: 'cannot be assigned to parameter "operation" of type "str"' + MyServiceHandler.my_sync_operation, # type: ignore MyInput(), id="op-1", - result_type=str, # type: ignore + result_type=str, ) - # handle still respects type declaration on the variable - _result_type_handle_output: MyOutput = await _result_type_handle.result() # starting with string operation name and result_type infers output type on the handle # and result from the handle @@ -389,7 +383,7 @@ async def standalone_operation_type_tests(): ) ) - # mismatched types on get_nexus_operation_handle produces type error + # mismatched types on get_nexus_operation_handle produce a type error # assert-type-error-pyright: 'Type "NexusOperationHandle\[str\]" is not assignable to declared type "NexusOperationHandle\[MyOutput\]"' _mismatch_handle: NexusOperationHandle[MyOutput] = ( client.get_nexus_operation_handle( # type: ignore @@ -397,3 +391,22 @@ async def standalone_operation_type_tests(): result_type=str, # type: ignore ) ) + + # functions with invalid signatures produce a type error + class InvalidServiceHandler: + async def invalid(self, _ctx: str, _input: str) -> str: + raise NotImplementedError() + + # assert-type-error-pyright: 'No overloads for "start_operation" match' + _invalid_handle: NexusOperationHandle[str] = await nexus_client.start_operation( + InvalidServiceHandler.invalid, # type: ignore + "foo", + id="invalid", + ) + + # assert-type-error-pyright: 'No overloads for "execute_operation" match' + _invalid_result: str = await nexus_client.execute_operation( + InvalidServiceHandler.invalid, # type: ignore + "foo", + id="invalid", + ) From 4d6348e9105bb54bbfe60be6f93f80fe88bf3b3e Mon Sep 17 00:00:00 2001 From: Kent Gruber Date: Fri, 22 May 2026 13:55:17 -0400 Subject: [PATCH 104/226] VLN-1341: remediate missing-dependency-cooldown (#1551) * VLN-1341: fix missing-dependency-cooldown * bypass exclude-newer for openai-agents openai-agents>=0.17.1 is newer than the 2-week exclude-newer cooldown window, causing uv resolution to fail. --------- Co-authored-by: picatz <14850816+picatz@users.noreply.github.com> --- .github/dependabot.yml | 16 ++++++++++++++++ pyproject.toml | 5 ++++- uv.lock | 7 +++++-- 3 files changed, 25 insertions(+), 3 deletions(-) create mode 100644 .github/dependabot.yml diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 000000000..1f3a19d73 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,16 @@ +version: 2 +updates: + - package-ecosystem: "uv" + directory: "/" + schedule: + interval: "weekly" + cooldown: + default-days: 14 + open-pull-requests-limit: 0 + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "weekly" + cooldown: + default-days: 14 + open-pull-requests-limit: 0 diff --git a/pyproject.toml b/pyproject.toml index e59b54ab7..da9c8bdd3 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -253,4 +253,7 @@ exclude = ["temporalio/bridge/target/**/*"] [tool.uv] # Prevent uv commands from building the package by default package = false -exclude-newer = "1 week" +exclude-newer = "2 weeks" +# openai-agents>=0.17.1 is newer than the exclude-newer cooldown window; +# bypass it since the minimum version pin already constrains the package. +exclude-newer-package = { openai-agents = false } diff --git a/uv.lock b/uv.lock index ab1b9974f..b94b932d5 100644 --- a/uv.lock +++ b/uv.lock @@ -9,8 +9,11 @@ resolution-markers = [ ] [options] -exclude-newer = "2026-05-07T19:04:44.331561Z" -exclude-newer-span = "P1W" +exclude-newer = "0001-01-01T00:00:00Z" # This has no effect and is included for backwards compatibility when using relative exclude-newer values. +exclude-newer-span = "P2W" + +[options.exclude-newer-package] +openai-agents = false [[package]] name = "aioboto3" From 7ea54e6389d56d0935a7cbcadcddecf84cf65a31 Mon Sep 17 00:00:00 2001 From: Brian Strauch Date: Fri, 22 May 2026 11:37:04 -0700 Subject: [PATCH 105/226] LangGraph streaming with workflow streams (#1500) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * first pass at langgraph streaming * Trim obvious comments in langgraph activity/config * Remove unrelated runtime tests * Tidy langgraph streaming tests * don't store workflowstream * remove timeout * fix lint * Make langgraph streaming opt-in via streaming_topic * add streaming support disclaimer * mention streaming in readme * Validate WorkflowStream registration when streaming_topic is set The LangGraph interceptor now checks at workflow start that a WorkflowStream has been registered (via the publish signal handler) when the plugin was configured with streaming_topic. Misconfigured workflows fail fast with a clear error pointing at @workflow.init, instead of silently producing no-op streams. * Stream from workflow-side LangGraph nodes via in-workflow WorkflowStream Wrap execute_in='workflow' nodes with wrap_workflow(), which mirrors wrap_activity() and (when streaming_topic is set) overrides the LangGraph Runtime's stream_writer to publish synchronously to the in-workflow WorkflowStream — no signal round-trip. Parametrized the streaming test over execute_in to cover both paths. * Document streaming feature in README and plugin docstring Expand the README streaming section with a self-contained snippet (plugin, WorkflowStream in __init__, external subscriber loop), an explicit callout that streaming_topic only covers stream_mode='custom' with an astream() bridge example for other modes, and at-least-once retry semantics. Add an Args section to LangGraphPlugin's docstring covering all constructor parameters. * Drop compose-mechanisms paragraph from streaming README * Support sync nodes for streaming and execute_in='workflow' Pick the raw user function from runnable.func instead of LangGraph's async runnable.afunc adapter, which wraps sync nodes in loop.run_in_executor — that's incompatible with the workflow event loop. wrap_activity now schedules sync funcs on a thread via asyncio.to_thread so the activity loop stays free for the streaming flusher, with stream_writer calls marshaled back to the loop thread to keep the workflow_streams client's asyncio.Event safe. Parametrize the streaming test over (execute_in, sync/async). * Fix astream-publish test race with subscriber ack The workflow was publishing chunk_b and the done marker in the same workflow task as its return, leaving no chance for the subscriber's next poll to land on a running workflow. Add an ack_done signal the subscriber sends after seeing done; the workflow waits for it before returning. Also hoist a signature() lookup out of the activity wrapper hot path. * Add CODEOWNERS entries for langgraph contrib * Drop blank line after wrap_activity docstring (D202) * Skip workflow-side streaming tests on Python 3.10 LangGraph's astream uses asyncio.create_task internally, and Python 3.10 doesn't propagate contextvars through new tasks. As a result get_stream_writer() returns "outside of a runnable context" when the node executes in-workflow under streaming_topic. Activity-side streaming is unaffected because the activity wrapper sets the runtime contextvar explicitly within the same task as the user node. This matches the existing 3.10 limitation already documented on the plugin (interrupts and the Functional API are also gated on 3.11+). * Move 3.10 skip onto the parametrize value * Fix streaming-ws test race with subscriber ack In the async-workflow case the node runs inline in the workflow with no awaits, so ainvoke and the workflow return in the same task as the publishes. The subscriber's first poll lands after completion and gets zero items. Add an ack_done signal the subscriber sends after seeing done; the workflow waits for it before returning. Mirrors 32818b1e for AstreamPublishWorkflow. --- .github/CODEOWNERS | 2 + temporalio/contrib/langgraph/README.md | 101 ++++++++++ temporalio/contrib/langgraph/__init__.py | 2 +- temporalio/contrib/langgraph/_activity.py | 63 ++++-- temporalio/contrib/langgraph/_interceptor.py | 16 ++ .../contrib/langgraph/_langgraph_config.py | 10 +- temporalio/contrib/langgraph/_plugin.py | 73 ++++++- temporalio/contrib/langgraph/_workflow.py | 62 ++++++ tests/contrib/langgraph/test_streaming.py | 182 ++++++++++++++++-- 9 files changed, 467 insertions(+), 44 deletions(-) create mode 100644 temporalio/contrib/langgraph/_workflow.py diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index c718b40c0..1a132f1fb 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -11,8 +11,10 @@ # as well as @temporalio/sdk, so the SDK team can continue to # manage repo-wide concerns. /temporalio/contrib/google_adk_agents/ @temporalio/ai-sdk @temporalio/sdk +/temporalio/contrib/langgraph/ @temporalio/ai-sdk @temporalio/sdk /temporalio/contrib/langsmith/ @temporalio/ai-sdk @temporalio/sdk /temporalio/contrib/openai_agents/ @temporalio/ai-sdk @temporalio/sdk /tests/contrib/google_adk_agents/ @temporalio/ai-sdk @temporalio/sdk +/tests/contrib/langgraph/ @temporalio/ai-sdk @temporalio/sdk /tests/contrib/langsmith/ @temporalio/ai-sdk @temporalio/sdk /tests/contrib/openai_agents/ @temporalio/ai-sdk @temporalio/sdk diff --git a/temporalio/contrib/langgraph/README.md b/temporalio/contrib/langgraph/README.md index 7c41b5da7..dafe598b7 100644 --- a/temporalio/contrib/langgraph/README.md +++ b/temporalio/contrib/langgraph/README.md @@ -143,6 +143,107 @@ await g.ainvoke({...}, context=Context(user_id="alice")) Your `context` object must be serializable by the configured Temporal payload converter, since it crosses the Activity boundary. +## Streaming + +When `streaming_topic` is set on `LangGraphPlugin`, calls to `langgraph.config.get_stream_writer()` inside a node publish to the named topic on the workflow's [`WorkflowStream`](https://github.com/temporalio/sdk-python/tree/main/temporalio/contrib/workflow_streams). Activity-side nodes publish via `WorkflowStreamClient` (a signal carrying batched items, controlled by `streaming_batch_interval`); workflow-side nodes publish synchronously to the in-workflow stream (no signal). External subscribers consume the stream with `WorkflowStreamClient.create(...).topic(...).subscribe(...)`. + +The workflow **must** construct `WorkflowStream()` in its `@workflow.init` (i.e. `__init__`) + +```python +from datetime import timedelta +from typing import Any + +from langgraph.config import get_stream_writer +from langgraph.graph import START, StateGraph +from typing_extensions import TypedDict + +from temporalio import workflow +from temporalio.client import Client +from temporalio.contrib.langgraph import LangGraphPlugin, graph +from temporalio.contrib.workflow_streams import WorkflowStream, WorkflowStreamClient +from temporalio.worker import Worker + + +class State(TypedDict): + value: str + + +async def token_node(state: State) -> dict[str, str]: + writer = get_stream_writer() + for token in ["hello", " ", "world"]: + writer({"token": token}) + writer({"done": True}) + return {"value": "hello world"} + + +@workflow.defn +class StreamingWorkflow: + def __init__(self) -> None: + # Required when streaming_topic is set on the plugin. + _ = WorkflowStream() + self.app = graph("streaming").compile() + + @workflow.run + async def run(self) -> str: + result = await self.app.ainvoke({"value": ""}) + return result["value"] + + +async def main(client: Client) -> None: + g = StateGraph(State) + g.add_node("token_node", token_node, metadata={"execute_in": "activity"}) + g.add_edge(START, "token_node") + + async with Worker( + client, + task_queue="streaming-tq", + workflows=[StreamingWorkflow], + plugins=[ + LangGraphPlugin( + graphs={"streaming": g}, + default_activity_options={ + "start_to_close_timeout": timedelta(seconds=10) + }, + streaming_topic="tokens", + ) + ], + ): + handle = await client.start_workflow( + StreamingWorkflow.run, id="streaming-wf", task_queue="streaming-tq" + ) + + ws_client = WorkflowStreamClient.create(client, handle.id) + async for item in ws_client.topic("tokens", type=dict).subscribe(from_offset=0): + print(item.data) + if item.data.get("done"): + break + + print(await handle.result()) +``` + +### What's covered, and what isn't + +`streaming_topic` wires up exactly **one** LangGraph stream mode: `stream_mode="custom"`, i.e. values written through `get_stream_writer()`. The other modes — `"messages"`, `"values"`, `"updates"`, `"debug"` — are **not** captured by `streaming_topic`. They aren't produced by node-side writers; LangGraph's orchestrator emits them as it walks the graph. The documented pattern is to **bridge `astream()` in the workflow** and republish each yielded chunk to a `WorkflowStream` topic yourself: + +```python +@workflow.defn +class AstreamBridge: + def __init__(self) -> None: + self.stream = WorkflowStream() + self.app = graph("g").compile() + + @workflow.run + async def run(self) -> None: + topic = self.stream.topic("astream") + async for chunk in self.app.astream({...}, stream_mode="messages"): + topic.publish(chunk) + topic.publish({"done": True}) +``` + +### Retry semantics + +Streaming has **at-least-once** delivery per activity attempt. When an activity-wrapped node retries (transient failure, worker crash, etc.), the user function re-runs from scratch and re-publishes its writes — earlier publishes from the failed attempt are not rolled back. Subscribers should be ready to see duplicates and recover idempotently (e.g. dedupe on a sequence id you include in each chunk, or treat the stream as advisory and rely on the workflow's final result for state). + ## Tracing We recommend the [Temporal LangSmith Plugin](https://github.com/temporalio/sdk-python/tree/main/temporalio/contrib/langsmith) to trace your LangGraph Workflows and Activities. diff --git a/temporalio/contrib/langgraph/__init__.py b/temporalio/contrib/langgraph/__init__.py index c12d459a6..e9aaf5605 100644 --- a/temporalio/contrib/langgraph/__init__.py +++ b/temporalio/contrib/langgraph/__init__.py @@ -19,7 +19,7 @@ __all__ = [ "LangGraphPlugin", - "entrypoint", "cache", + "entrypoint", "graph", ] diff --git a/temporalio/contrib/langgraph/_activity.py b/temporalio/contrib/langgraph/_activity.py index f1d66a200..d75dbac2e 100644 --- a/temporalio/contrib/langgraph/_activity.py +++ b/temporalio/contrib/langgraph/_activity.py @@ -1,7 +1,9 @@ """Activity wrappers for executing LangGraph nodes and tasks.""" +import asyncio from collections.abc import Awaitable from dataclasses import dataclass +from datetime import timedelta from inspect import iscoroutinefunction, signature from typing import Any, Callable @@ -19,6 +21,7 @@ cache_lookup, cache_put, ) +from temporalio.contrib.workflow_streams import WorkflowStreamClient # Per-run dedupe so we only warn once when a user passes a Store via # graph.compile(store=...) / @entrypoint(store=...). Cleared by @@ -51,28 +54,54 @@ class ActivityOutput: def wrap_activity( func: Callable, + *, + streaming_topic: str | None = None, + streaming_batch_interval: timedelta = timedelta(milliseconds=100), ) -> Callable[[ActivityInput], Awaitable[ActivityOutput]]: """Wrap a function as a Temporal activity that handles LangGraph config and interrupts.""" - # Graph nodes declare `runtime: Runtime[Ctx]` in their signature; tasks - # don't and instead reach for Runtime via get_runtime(). We re-inject the - # reconstructed Runtime only when the user function asks. accepts_runtime = "runtime" in signature(func).parameters async def wrapper(input: ActivityInput) -> ActivityOutput: - runtime = set_langgraph_config(input.langgraph_config) - kwargs = dict(input.kwargs) - if accepts_runtime: - kwargs["runtime"] = runtime - try: - if iscoroutinefunction(func): - result = await func(*input.args, **kwargs) - else: - result = func(*input.args, **kwargs) - if isinstance(result, Command): - return ActivityOutput(langgraph_command=result) - return ActivityOutput(result=result) - except GraphInterrupt as e: - return ActivityOutput(langgraph_interrupts=e.args[0]) + async def run(stream_writer: Callable[[Any], None] | None) -> ActivityOutput: + # Sync funcs run on a thread (so the loop keeps flushing the + # stream client mid-execution); marshal writer calls back to + # the loop thread because the client's flush event is an + # asyncio.Event and isn't safe to set off-thread. + effective_writer = stream_writer + if not iscoroutinefunction(func) and stream_writer is not None: + loop = asyncio.get_running_loop() + inner_writer = stream_writer + + def thread_safe_writer(value: Any) -> None: + loop.call_soon_threadsafe(inner_writer, value) + + effective_writer = thread_safe_writer + + runtime = set_langgraph_config( + input.langgraph_config, stream_writer=effective_writer + ) + kwargs = dict(input.kwargs) + if accepts_runtime: + kwargs["runtime"] = runtime + + try: + if iscoroutinefunction(func): + result = await func(*input.args, **kwargs) + else: + result = await asyncio.to_thread(func, *input.args, **kwargs) + if isinstance(result, Command): + return ActivityOutput(langgraph_command=result) + return ActivityOutput(result=result) + except GraphInterrupt as e: + return ActivityOutput(langgraph_interrupts=e.args[0]) + + if streaming_topic is None: + return await run(stream_writer=None) + async with WorkflowStreamClient.from_within_activity( + batch_interval=streaming_batch_interval, + ) as client: + topic = client.topic(streaming_topic) + return await run(stream_writer=topic.publish) return wrapper diff --git a/temporalio/contrib/langgraph/_interceptor.py b/temporalio/contrib/langgraph/_interceptor.py index fd583c052..f68d9d45d 100644 --- a/temporalio/contrib/langgraph/_interceptor.py +++ b/temporalio/contrib/langgraph/_interceptor.py @@ -11,6 +11,7 @@ from temporalio import workflow from temporalio.contrib.langgraph._activity import clear_store_warning +from temporalio.contrib.workflow_streams._stream import _PUBLISH_SIGNAL from temporalio.worker import ( ExecuteWorkflowInput, Interceptor, @@ -30,10 +31,12 @@ def __init__( self, graphs: dict[str, StateGraph[Any, Any, Any, Any]], entrypoints: dict[str, Pregel[Any, Any, Any, Any]], + streaming_topic: str | None = None, ) -> None: """Initialize with the graphs and entrypoints to scope to each workflow run.""" self._graphs = graphs self._entrypoints = entrypoints + self._streaming_topic = streaming_topic def workflow_interceptor_class( self, input: WorkflowInterceptorClassInput @@ -41,6 +44,7 @@ def workflow_interceptor_class( """Return the inbound interceptor class used to scope graphs per run.""" graphs = self._graphs entrypoints = self._entrypoints + streaming_topic = self._streaming_topic class Inbound(WorkflowInboundInterceptor): def init(self, outbound: WorkflowOutboundInterceptor) -> None: @@ -50,6 +54,18 @@ def init(self, outbound: WorkflowOutboundInterceptor) -> None: super().init(outbound) async def execute_workflow(self, input: ExecuteWorkflowInput) -> Any: + if ( + streaming_topic is not None + and workflow.get_signal_handler(_PUBLISH_SIGNAL) is None + ): + raise RuntimeError( + f"LangGraphPlugin was configured with " + f"streaming_topic={streaming_topic!r}, but workflow " + f"{workflow.info().workflow_type!r} did not register a " + f"WorkflowStream. Construct WorkflowStream() in the " + f"workflow's @workflow.init (i.e. __init__) method so " + f"streaming activities can publish to it." + ) try: return await self.next.execute_workflow(input) finally: diff --git a/temporalio/contrib/langgraph/_langgraph_config.py b/temporalio/contrib/langgraph/_langgraph_config.py index 4cc529477..90c6c810d 100644 --- a/temporalio/contrib/langgraph/_langgraph_config.py +++ b/temporalio/contrib/langgraph/_langgraph_config.py @@ -3,7 +3,7 @@ # pyright: reportMissingTypeStubs=false import dataclasses -from typing import Any +from typing import Any, Callable from langchain_core.runnables.config import var_child_runnable_config from langgraph._internal._constants import ( @@ -93,7 +93,11 @@ def get_langgraph_config() -> dict[str, Any]: } -def set_langgraph_config(config: dict[str, Any]) -> Runtime: +def set_langgraph_config( + config: dict[str, Any], + *, + stream_writer: Callable[[Any], None] | None = None, +) -> Runtime: """Restore a LangGraph runnable config from a serialized dict. Returns the reconstructed Runtime so callers can re-inject it into the @@ -112,7 +116,7 @@ def get_null_resume(consume: bool = False) -> Any: execution_info_dict = config.get("execution_info") runtime = Runtime( context=config.get("context"), - stream_writer=lambda _: None, + stream_writer=stream_writer or (lambda _: None), previous=config.get("previous"), execution_info=( ExecutionInfo(**execution_info_dict) if execution_info_dict else None diff --git a/temporalio/contrib/langgraph/_plugin.py b/temporalio/contrib/langgraph/_plugin.py index a624f62a7..a1320d1a8 100644 --- a/temporalio/contrib/langgraph/_plugin.py +++ b/temporalio/contrib/langgraph/_plugin.py @@ -8,6 +8,7 @@ import sys import warnings from dataclasses import replace +from datetime import timedelta from typing import Any, Callable from langgraph._internal._runnable import RunnableCallable @@ -26,6 +27,7 @@ set_task_cache, task_id, ) +from temporalio.contrib.langgraph._workflow import wrap_workflow from temporalio.plugin import SimplePlugin from temporalio.worker import WorkflowRunner from temporalio.worker.workflow_sandbox import SandboxedWorkflowRunner @@ -46,6 +48,49 @@ class LangGraphPlugin(SimplePlugin): and tasks as Temporal Activities, giving your AI agent workflows durable execution, automatic retries, and timeouts. It supports both the LangGraph Graph API (``StateGraph``) and Functional API (``@entrypoint`` / ``@task``). + + Args: + graphs: Graph API graphs to make available to workflows, keyed by name. + Workflows retrieve them with :func:`graph` and call + ``.compile()`` to get a runnable. Each node's ``metadata`` must + include ``execute_in`` (``"activity"`` or ``"workflow"``) and + may include any kwarg accepted by + :func:`workflow.execute_activity` (e.g. ``start_to_close_timeout``, + ``retry_policy``). + entrypoints: Functional API entrypoints to make available to + workflows, keyed by name. Workflows retrieve them with + :func:`entrypoint`. + tasks: Functional API ``@task`` functions to wrap as Temporal + Activities. + activity_options: Per-task activity options for the Functional + API, keyed by task function name. Each entry must include + ``execute_in`` and may include any + :func:`workflow.execute_activity` kwarg. Used because LangGraph's + Functional API has no per-task ``metadata`` channel. + default_activity_options: Activity options applied to every + activity-bound node and task, overridable per-node (Graph API + ``metadata``) or per-task (``activity_options[name]``). + streaming_topic: When set, ``langgraph.config.get_stream_writer()`` + inside a node publishes to this topic on the workflow's + :class:`WorkflowStream`. The workflow must construct + ``WorkflowStream()`` in its ``@workflow.init`` (the plugin's + interceptor verifies this on workflow start). Nodes with + ``execute_in='activity'`` publish through + :class:`WorkflowStreamClient` (signal); nodes with + ``execute_in='workflow'`` publish synchronously to the + in-workflow stream (no signal). + streaming_batch_interval: How often the activity-side stream + client flushes buffered publishes into a single + ``__temporal_workflow_stream_publish`` signal. Has no effect + on workflow-side nodes (their publishes are synchronous + in-memory log appends). Lower values reduce streaming + latency at the cost of more signals (more workflow history + events); higher values amortize signal cost but make + chunks arrive in larger bursts. Default 100ms suits + interactive token streaming; raise to 250–1000ms for + non-interactive aggregation, lower toward 10–50ms only if + you've measured the latency need and accept the history + cost. """ def __init__( @@ -58,8 +103,15 @@ def __init__( # TODO: Remove activity_options when we have support for @task(metadata=...) activity_options: dict[str, dict[str, Any]] | None = None, default_activity_options: dict[str, Any] | None = None, + streaming_topic: str | None = None, + streaming_batch_interval: timedelta = timedelta(milliseconds=100), ): - """Initialize the LangGraph plugin with graphs, entrypoints, and tasks.""" + """Initialize the LangGraph plugin with graphs, entrypoints, and tasks. + + .. warning:: + Streaming support is experimental and may change in + future versions. + """ if sys.version_info < (3, 11): warnings.warn( # type: ignore[reportUnreachable] "LangGraphPlugin requires Python >= 3.11 for full async support. " @@ -79,6 +131,8 @@ def __init__( ) self.activities: list = [] + self._streaming_topic = streaming_topic + self._streaming_batch_interval = streaming_batch_interval # Graph API: Wrap graph nodes as Temporal Activities. if graphs: @@ -95,7 +149,7 @@ def __init__( runnable = node.runnable if not isinstance(runnable, RunnableCallable): raise ValueError(f"Node {node_name} must be a RunnableCallable") - user_func = runnable.afunc or runnable.func + user_func = runnable.func or runnable.afunc if user_func is None: raise ValueError(f"Node {node_name} must have a function") # Keep 'config' (for metadata/tags) and 'runtime' (for @@ -183,7 +237,11 @@ def workflow_runner(runner: WorkflowRunner | None) -> WorkflowRunner: "langchain.LangGraphPlugin", activities=self.activities, workflow_runner=workflow_runner, - interceptors=[LangGraphInterceptor(graphs or {}, entrypoints or {})], + interceptors=[ + LangGraphInterceptor( + graphs or {}, entrypoints or {}, streaming_topic=streaming_topic + ) + ], ) def execute( @@ -197,11 +255,16 @@ def execute( execute_in = opts.pop("execute_in") if execute_in == "activity": - a = activity.defn(name=activity_name)(wrap_activity(func)) + wrapped = wrap_activity( + func, + streaming_topic=self._streaming_topic, + streaming_batch_interval=self._streaming_batch_interval, + ) + a = activity.defn(name=activity_name)(wrapped) self.activities.append(a) return wrap_execute_activity(a, task_id=task_id(func), **opts) elif execute_in == "workflow": - return func + return wrap_workflow(func, streaming_topic=self._streaming_topic) else: raise ValueError(f"Invalid execute_in value: {execute_in}") diff --git a/temporalio/contrib/langgraph/_workflow.py b/temporalio/contrib/langgraph/_workflow.py new file mode 100644 index 000000000..67bfd4f68 --- /dev/null +++ b/temporalio/contrib/langgraph/_workflow.py @@ -0,0 +1,62 @@ +"""Workflow-side wrappers for executing LangGraph nodes inline in a workflow.""" + +# pyright: reportMissingTypeStubs=false + +from __future__ import annotations + +import dataclasses +from collections.abc import Awaitable +from inspect import iscoroutinefunction +from typing import Any, Callable + +from langchain_core.runnables.config import var_child_runnable_config +from langgraph._internal._constants import CONFIG_KEY_RUNTIME + +from temporalio import workflow +from temporalio.contrib.workflow_streams._stream import _PUBLISH_SIGNAL + + +def wrap_workflow( + func: Callable[..., Any], + *, + streaming_topic: str | None = None, +) -> Callable[..., Awaitable[Any]]: + """Wrap a function as a workflow-side LangGraph node. + + Mirrors :func:`wrap_activity`: the outer wrapper resolves a stream + writer and passes it to an inner ``run`` that invokes the user + function with the writer installed. Workflow-side nodes publish + synchronously to the in-workflow ``WorkflowStream`` (no signal + round-trip); activity-side nodes go through ``WorkflowStreamClient``. + """ + + async def wrapper(*args: Any, **kwargs: Any) -> Any: + async def run(stream_writer: Callable[[Any], None] | None) -> Any: + token = None + if stream_writer is not None: + config = var_child_runnable_config.get() or {} + configurable = dict(config.get("configurable") or {}) + runtime = configurable.get(CONFIG_KEY_RUNTIME) + if runtime is not None: + configurable[CONFIG_KEY_RUNTIME] = dataclasses.replace( + runtime, stream_writer=stream_writer + ) + token = var_child_runnable_config.set( + {**config, "configurable": configurable} + ) + try: + if iscoroutinefunction(func): + return await func(*args, **kwargs) + return func(*args, **kwargs) + finally: + if token is not None: + var_child_runnable_config.reset(token) + + if streaming_topic is None: + return await run(stream_writer=None) + publish_handler = workflow.get_signal_handler(_PUBLISH_SIGNAL) + stream = getattr(publish_handler, "__self__") + topic = stream.topic(streaming_topic) + return await run(stream_writer=topic.publish) + + return wrapper diff --git a/tests/contrib/langgraph/test_streaming.py b/tests/contrib/langgraph/test_streaming.py index f47feffee..5d1e1950a 100644 --- a/tests/contrib/langgraph/test_streaming.py +++ b/tests/contrib/langgraph/test_streaming.py @@ -1,13 +1,19 @@ +import sys from datetime import timedelta from typing import Any from uuid import uuid4 +import pytest +from langgraph.config import ( + get_stream_writer, # pyright: ignore[reportMissingTypeStubs] +) from langgraph.graph import START, StateGraph # pyright: ignore[reportMissingTypeStubs] from typing_extensions import TypedDict from temporalio import workflow from temporalio.client import Client from temporalio.contrib.langgraph import LangGraphPlugin, graph +from temporalio.contrib.workflow_streams import WorkflowStream, WorkflowStreamClient from temporalio.worker import Worker @@ -15,54 +21,194 @@ class State(TypedDict): value: str -async def node_a(state: State) -> dict[str, str]: - return {"value": state["value"] + "a"} +async def async_token_node(state: State) -> dict[str, str]: + tokens = ["a", "b", "c"] + writer = get_stream_writer() + for token in tokens: + writer({"token": token}) + writer({"done": True}) + return {"value": state["value"] + "".join(tokens)} -async def node_b(state: State) -> dict[str, str]: - return {"value": state["value"] + "b"} +def sync_token_node(state: State) -> dict[str, str]: + tokens = ["a", "b", "c"] + writer = get_stream_writer() + for token in tokens: + writer({"token": token}) + writer({"done": True}) + return {"value": state["value"] + "".join(tokens)} + + +@workflow.defn +class StreamingWorkflowStreamsWorkflow: + def __init__(self) -> None: + _ = WorkflowStream() + self.app = graph("streaming-ws").compile() + self._done_acked = False + + @workflow.signal + def ack_done(self) -> None: + self._done_acked = True + + @workflow.run + async def run(self, input: str) -> str: + result = await self.app.ainvoke({"value": input}) + await workflow.wait_condition(lambda: self._done_acked) + return result["value"] + + +@pytest.mark.parametrize( + "execute_in", + [ + "activity", + pytest.param( + "workflow", + marks=pytest.mark.skipif( + sys.version_info < (3, 11), + reason=( + "execute_in='workflow' streaming relies on contextvar " + "propagation through asyncio.create_task, which only " + "works on Python >= 3.11" + ), + ), + ), + ], +) +@pytest.mark.parametrize( + "node", [async_token_node, sync_token_node], ids=["async", "sync"] +) +async def test_streaming_via_workflow_streams( + client: Client, execute_in: str, node: Any +): + g = StateGraph(State) + g.add_node("token_node", node, metadata={"execute_in": execute_in}) + g.add_edge(START, "token_node") + + task_queue = f"streaming-ws-{uuid4()}" + + async with Worker( + client, + task_queue=task_queue, + workflows=[StreamingWorkflowStreamsWorkflow], + plugins=[ + LangGraphPlugin( + graphs={"streaming-ws": g}, + default_activity_options={ + "start_to_close_timeout": timedelta(seconds=10) + }, + streaming_topic="tokens", + ) + ], + ): + handle = await client.start_workflow( + StreamingWorkflowStreamsWorkflow.run, + "", + id=f"test-streaming-ws-{uuid4()}", + task_queue=task_queue, + ) + + ws_client = WorkflowStreamClient.create(client, handle.id) + chunks: list[dict[str, Any]] = [] + async for item in ws_client.topic("tokens", type=dict).subscribe( + from_offset=0, + poll_cooldown=timedelta(milliseconds=10), + ): + chunks.append(item.data) + if chunks[-1].get("done"): + await handle.signal(StreamingWorkflowStreamsWorkflow.ack_done) + break + + result = await handle.result() + + assert result == "abc" + assert chunks == [ + {"token": "a"}, + {"token": "b"}, + {"token": "c"}, + {"done": True}, + ] + + +# --------------------------------------------------------------------------- +# Workflow-side publish: iterate astream() in the workflow and forward each +# chunk via self.stream.topic("astream").publish(...) so external subscribers +# see node-level progress alongside any activity-emitted tokens. +# --------------------------------------------------------------------------- @workflow.defn -class StreamingWorkflow: +class AstreamPublishWorkflow: def __init__(self) -> None: - self.app = graph("streaming").compile() + self.stream = WorkflowStream() + self.app = graph("astream-publish").compile() + self._done_acked = False + + @workflow.signal + def ack_done(self) -> None: + self._done_acked = True @workflow.run - async def run(self, input: str) -> Any: - chunks = [] + async def run(self, input: str) -> str: + topic = self.stream.topic("astream") async for chunk in self.app.astream({"value": input}): - chunks.append(chunk) - return chunks + topic.publish(chunk) + topic.publish({"done": True}) + await workflow.wait_condition(lambda: self._done_acked) + return "done" + + +async def node_a(state: State) -> dict[str, str]: + return {"value": state["value"] + "a"} + + +async def node_b(state: State) -> dict[str, str]: + return {"value": state["value"] + "b"} -async def test_streaming(client: Client): +async def test_workflow_publishes_astream_chunks(client: Client): g = StateGraph(State) g.add_node("node_a", node_a, metadata={"execute_in": "activity"}) g.add_node("node_b", node_b, metadata={"execute_in": "activity"}) g.add_edge(START, "node_a") g.add_edge("node_a", "node_b") - task_queue = f"streaming-{uuid4()}" + task_queue = f"astream-publish-{uuid4()}" async with Worker( client, task_queue=task_queue, - workflows=[StreamingWorkflow], + workflows=[AstreamPublishWorkflow], plugins=[ LangGraphPlugin( - graphs={"streaming": g}, + graphs={"astream-publish": g}, default_activity_options={ "start_to_close_timeout": timedelta(seconds=10) }, ) ], ): - chunks = await client.execute_workflow( - StreamingWorkflow.run, + handle = await client.start_workflow( + AstreamPublishWorkflow.run, "", - id=f"test-streaming-{uuid4()}", + id=f"test-astream-publish-{uuid4()}", task_queue=task_queue, ) - assert chunks == [{"node_a": {"value": "a"}}, {"node_b": {"value": "ab"}}] + ws_client = WorkflowStreamClient.create(client, handle.id) + chunks: list[dict[str, Any]] = [] + async for item in ws_client.topic("astream", type=dict).subscribe( + from_offset=0, + poll_cooldown=timedelta(milliseconds=10), + ): + chunks.append(item.data) + if chunks[-1].get("done"): + await handle.signal(AstreamPublishWorkflow.ack_done) + break + + await handle.result() + + assert chunks == [ + {"node_a": {"value": "a"}}, + {"node_b": {"value": "ab"}}, + {"done": True}, + ] From 346dcc34607c1ebb2e8e0d2b31c7eeaeb79d86bf Mon Sep 17 00:00:00 2001 From: brucearctor <5032356+brucearctor@users.noreply.github.com> Date: Wed, 27 May 2026 13:42:45 -0700 Subject: [PATCH 106/226] fix: call task.uncancel() after catching CancelledError in shield loops (Python 3.11+) (#1523) * fix: call task.uncancel() after catching CancelledError in shield loops On Python 3.11+, asyncio.Task tracks a cancellation counter via Task.cancelling()/Task.uncancel(). When CancelledError is caught inside a while-True/asyncio.shield loop without calling uncancel(), the counter stays elevated and Python re-throws CancelledError at every subsequent await. This causes: 1. Duplicate commands (e.g. RequestCancelExternalWorkflow) sent to the Temporal server 2. Spurious ERROR-level 'exception in shielded future' log lines from temporalio.worker._workflow_instance The fix adds task.uncancel() (guarded by hasattr for Python <=3.10 compatibility) after each CancelledError catch in all 6 affected shield loops: - run_activity() in _outbound_schedule_activity - run_child() in _outbound_start_child_workflow - start-wait loop in _outbound_start_child_workflow - operation_handle_fn() in _outbound_start_nexus_operation - start-wait loop in _outbound_start_nexus_operation - _signal_external_workflow Fixes temporalio/sdk-python#1504 * test: add coverage for task.uncancel() in shield loops Add three integration tests to verify the fix for the elevated cancellation counter issue on Python 3.11+ (cpython#93453): - test_workflow_uncancel_shield_activity: Verifies that cancelling a shielded activity does not produce duplicate cancel commands or spurious 'exception in shielded future' error logs. - test_workflow_uncancel_shield_child_workflow: Verifies that cancelling a shielded child workflow task produces exactly one RequestCancelExternalWorkflowExecution event in history (not duplicates from the elevated cancellation counter). - test_workflow_uncancel_shield_signal_external: Verifies that signalling an external workflow completes without spurious error logs from the shield loop. Addresses review comment on PR #1523. * test: add coverage for nexus operation shield loops * style: apply ruff formatting fixes * fix: use sys.version_info guard for task.uncancel() to satisfy type checkers Replace hasattr(t, 'uncancel') with sys.version_info >= (3, 11) guard, which is the established pattern in this file for version-specific APIs. This satisfies pyright/mypy on Python 3.10 where asyncio.Task lacks uncancel(). --------- Co-authored-by: tconley1428 --- temporalio/worker/_workflow_instance.py | 42 ++++ ...test_workflow_caller_cancellation_types.py | 114 +++++---- tests/worker/test_workflow.py | 219 ++++++++++++++++++ 3 files changed, 328 insertions(+), 47 deletions(-) diff --git a/temporalio/worker/_workflow_instance.py b/temporalio/worker/_workflow_instance.py index fff0a42cd..16c3483d8 100644 --- a/temporalio/worker/_workflow_instance.py +++ b/temporalio/worker/_workflow_instance.py @@ -1924,6 +1924,13 @@ async def run_activity() -> Any: raise # Send a cancel request to the activity handle._apply_cancel_command(self._add_command()) + # Clear the cancellation counter on Python 3.11+ so the + # next await does not immediately re-raise CancelledError + if ( + sys.version_info >= (3, 11) + and (t := asyncio.current_task()) is not None + ): + t.uncancel() # type: ignore[union-attr] # Create the handle and set as pending handle = _ActivityHandle(self, input, run_activity()) @@ -2008,6 +2015,13 @@ async def run_child() -> Any: return await asyncio.shield(handle._result_fut) except asyncio.CancelledError: apply_child_cancel_error() + # Clear the cancellation counter on Python 3.11+ so the + # next await does not immediately re-raise CancelledError + if ( + sys.version_info >= (3, 11) + and (t := asyncio.current_task()) is not None + ): + t.uncancel() # type: ignore[union-attr] # Create the handle and set as pending handle = _ChildWorkflowHandle( @@ -2025,6 +2039,13 @@ async def run_child() -> Any: return handle except asyncio.CancelledError: apply_child_cancel_error() + # Clear the cancellation counter on Python 3.11+ so the + # next await does not immediately re-raise CancelledError + if ( + sys.version_info >= (3, 11) + and (t := asyncio.current_task()) is not None + ): + t.uncancel() # type: ignore[union-attr] if self._cancel_requested: raise @@ -2053,6 +2074,13 @@ async def operation_handle_fn() -> OutputT: except asyncio.CancelledError: cancel_command = self._add_command() handle._apply_cancel_command(cancel_command) + # Clear the cancellation counter on Python 3.11+ so the + # next await does not immediately re-raise CancelledError + if ( + sys.version_info >= (3, 11) + and (t := asyncio.current_task()) is not None + ): + t.uncancel() # type: ignore[union-attr] handle = _NexusOperationHandle( self, self._next_seq("nexus_operation"), input, operation_handle_fn() @@ -2067,6 +2095,13 @@ async def operation_handle_fn() -> OutputT: except asyncio.CancelledError: cancel_command = self._add_command() handle._apply_cancel_command(cancel_command) + # Clear the cancellation counter on Python 3.11+ so the + # next await does not immediately re-raise CancelledError + if ( + sys.version_info >= (3, 11) + and (t := asyncio.current_task()) is not None + ): + t.uncancel() # type: ignore[union-attr] if self._cancel_requested: raise @@ -2599,6 +2634,13 @@ async def _signal_external_workflow( except asyncio.CancelledError: cancel_command = self._add_command() cancel_command.cancel_signal_workflow.seq = seq + # Clear the cancellation counter on Python 3.11+ so the + # next await does not immediately re-raise CancelledError + if ( + sys.version_info >= (3, 11) + and (t := asyncio.current_task()) is not None + ): + t.uncancel() # type: ignore[union-attr] def _stack_trace(self) -> str: stacks = [] diff --git a/tests/nexus/test_workflow_caller_cancellation_types.py b/tests/nexus/test_workflow_caller_cancellation_types.py index 59a989d34..cdce9a99b 100644 --- a/tests/nexus/test_workflow_caller_cancellation_types.py +++ b/tests/nexus/test_workflow_caller_cancellation_types.py @@ -1,4 +1,5 @@ import asyncio +import logging import uuid from dataclasses import dataclass, field from datetime import datetime, timezone @@ -9,6 +10,7 @@ import pytest import temporalio.nexus._operation_handlers +import temporalio.worker._workflow_instance from temporalio import exceptions, nexus, workflow from temporalio.api.enums.v1 import EventType from temporalio.client import ( @@ -20,7 +22,7 @@ from temporalio.common import WorkflowIDConflictPolicy from temporalio.testing import WorkflowEnvironment from temporalio.worker import Worker -from tests.helpers import assert_eventually +from tests.helpers import LogCapturer, assert_eventually from tests.helpers.nexus import make_nexus_endpoint_name @@ -268,54 +270,72 @@ async def test_cancellation_type( client = env.client - async with Worker( - client, - task_queue=str(uuid.uuid4()), - workflows=[CallerWorkflow, HandlerWorkflow], - nexus_service_handlers=[ServiceHandler()], - ) as worker: - await env.create_nexus_endpoint( - make_nexus_endpoint_name(worker.task_queue), worker.task_queue - ) + log_capturer = LogCapturer() + with log_capturer.logs_captured( + temporalio.worker._workflow_instance.logger, level=logging.WARNING + ): + async with Worker( + client, + task_queue=str(uuid.uuid4()), + workflows=[CallerWorkflow, HandlerWorkflow], + nexus_service_handlers=[ServiceHandler()], + ) as worker: + await env.create_nexus_endpoint( + make_nexus_endpoint_name(worker.task_queue), worker.task_queue + ) - # Start the caller workflow, wait for the nexus op to have started and retrieve the nexus op - # token - with_start_workflow = WithStartWorkflowOperation( - CallerWorkflow.run, - Input( - endpoint=make_nexus_endpoint_name(worker.task_queue), - cancellation_type=cancellation_type, - ), - id=test_context.caller_workflow_id, - task_queue=worker.task_queue, - id_conflict_policy=WorkflowIDConflictPolicy.FAIL, - ) + # Start the caller workflow, wait for the nexus op to have started and retrieve the nexus op + # token + with_start_workflow = WithStartWorkflowOperation( + CallerWorkflow.run, + Input( + endpoint=make_nexus_endpoint_name(worker.task_queue), + cancellation_type=cancellation_type, + ), + id=test_context.caller_workflow_id, + task_queue=worker.task_queue, + id_conflict_policy=WorkflowIDConflictPolicy.FAIL, + ) - operation_token = await client.execute_update_with_start_workflow( - CallerWorkflow.get_operation_token, - start_workflow_operation=with_start_workflow, - ) - handler_wf = ( - nexus.WorkflowHandle[None] - .from_token(operation_token) - ._to_client_workflow_handle(client) - ) - caller_wf = await with_start_workflow.workflow_handle() - - if cancellation_type == workflow.NexusOperationCancellationType.ABANDON: - await check_behavior_for_abandon(caller_wf, handler_wf) - elif cancellation_type == workflow.NexusOperationCancellationType.TRY_CANCEL: - await check_behavior_for_try_cancel(caller_wf, handler_wf) - elif ( - cancellation_type == workflow.NexusOperationCancellationType.WAIT_REQUESTED - ): - await check_behavior_for_wait_cancellation_requested(caller_wf, handler_wf) - elif ( - cancellation_type == workflow.NexusOperationCancellationType.WAIT_COMPLETED - ): - await check_behavior_for_wait_cancellation_completed(caller_wf, handler_wf) - else: - pytest.fail(f"Invalid cancellation type: {cancellation_type}") + operation_token = await client.execute_update_with_start_workflow( + CallerWorkflow.get_operation_token, + start_workflow_operation=with_start_workflow, + ) + handler_wf = ( + nexus.WorkflowHandle[None] + .from_token(operation_token) + ._to_client_workflow_handle(client) + ) + caller_wf = await with_start_workflow.workflow_handle() + + if cancellation_type == workflow.NexusOperationCancellationType.ABANDON: + await check_behavior_for_abandon(caller_wf, handler_wf) + elif ( + cancellation_type == workflow.NexusOperationCancellationType.TRY_CANCEL + ): + await check_behavior_for_try_cancel(caller_wf, handler_wf) + elif ( + cancellation_type + == workflow.NexusOperationCancellationType.WAIT_REQUESTED + ): + await check_behavior_for_wait_cancellation_requested( + caller_wf, handler_wf + ) + elif ( + cancellation_type + == workflow.NexusOperationCancellationType.WAIT_COMPLETED + ): + await check_behavior_for_wait_cancellation_completed( + caller_wf, handler_wf + ) + else: + pytest.fail(f"Invalid cancellation type: {cancellation_type}") + + # Verify no spurious "exception in shielded future" error logs + shielded_err = log_capturer.find_log("exception in shielded future") + assert shielded_err is None, ( + f"Unexpected 'exception in shielded future' log: {shielded_err}" + ) async def check_behavior_for_abandon( diff --git a/tests/worker/test_workflow.py b/tests/worker/test_workflow.py index 07d107432..72a5862c7 100644 --- a/tests/worker/test_workflow.py +++ b/tests/worker/test_workflow.py @@ -8790,3 +8790,222 @@ async def ready() -> bool: assert isinstance(result["seed_changes"], list) assert len(result["auto_values"]) == 2 assert len(result["seed_changes"]) == 1 + + +# Tests for task.uncancel() fix in shield loops (Python 3.11+) +# See https://github.com/temporalio/sdk-python/pull/1523 + + +@workflow.defn +class UncancelShieldActivityWorkflow: + """Workflow that cancels a shielded activity and checks for duplicate commands.""" + + def __init__(self) -> None: + self._activity_result = "" + self._cancel_count = 0 + + @workflow.run + async def run(self) -> str: + handle = workflow.start_activity( + wait_cancel, + schedule_to_close_timeout=timedelta(seconds=30), + heartbeat_timeout=timedelta(seconds=2), + cancellation_type=workflow.ActivityCancellationType.WAIT_CANCELLATION_COMPLETED, + ) + # Let activity start + await asyncio.sleep(0.01) + # Cancel the activity task + handle.cancel() + try: + self._activity_result = await handle + except ActivityError as err: + self._activity_result = f"Error: {err.cause.__class__.__name__}" + except CancelledError: + self._activity_result = "CancelledError" + return self._activity_result + + @workflow.query + def activity_result(self) -> str: + return self._activity_result + + +async def test_workflow_uncancel_shield_activity(client: Client): + """Verify that cancelling a shielded activity does not produce duplicate + cancel commands or spurious error logs due to elevated cancellation counter. + """ + log_capturer = LogCapturer() + with log_capturer.logs_captured( + temporalio.worker._workflow_instance.logger, level=logging.WARNING + ): + async with new_worker( + client, + UncancelShieldActivityWorkflow, + activities=[wait_cancel], + ) as worker: + result = await client.execute_workflow( + UncancelShieldActivityWorkflow.run, + id=f"workflow-{uuid.uuid4()}", + task_queue=worker.task_queue, + ) + # The activity should have been cancelled successfully + assert result == "Got cancelled error, cancelled? True" + + # Verify no spurious "exception in shielded future" error logs + shielded_err = log_capturer.find_log("exception in shielded future") + assert shielded_err is None, ( + f"Unexpected 'exception in shielded future' log: {shielded_err}" + ) + + +@workflow.defn +class UncancelShieldChildWorkflow: + """Workflow that starts a child workflow, cancels it via task cancel, + and returns information about the cancellation.""" + + def __init__(self) -> None: + self._ready = False + + @workflow.run + async def run(self) -> str: + # Start a child workflow via execute (which internally uses shield loops) + child_task = asyncio.create_task( + workflow.execute_child_workflow( + LongSleepWorkflow.run, + id=f"{workflow.info().workflow_id}_child", + ) + ) + self._ready = True + # Let the child start + await asyncio.sleep(0.01) + # Cancel the child task — this triggers the shield loop's CancelledError + child_task.cancel() + try: + await child_task + return "completed" + except ChildWorkflowError as err: + if isinstance(err.cause, CancelledError): + return "child_cancelled" + return f"child_error: {err.cause}" + except CancelledError: + return "task_cancelled" + + @workflow.query + def ready(self) -> bool: + return self._ready + + +async def test_workflow_uncancel_shield_child_workflow(client: Client): + """Verify that cancelling a shielded child workflow task does not produce + duplicate RequestCancelExternalWorkflowExecution commands in history. + This was the primary symptom of the bug fixed by task.uncancel(). + """ + log_capturer = LogCapturer() + with log_capturer.logs_captured( + temporalio.worker._workflow_instance.logger, level=logging.WARNING + ): + async with new_worker( + client, + UncancelShieldChildWorkflow, + LongSleepWorkflow, + ) as worker: + handle = await client.start_workflow( + UncancelShieldChildWorkflow.run, + id=f"workflow-{uuid.uuid4()}", + task_queue=worker.task_queue, + ) + result = await handle.result() + + assert result == "child_cancelled" + + # Check history for duplicate cancel commands + resp = await client.workflow_service.get_workflow_execution_history( + GetWorkflowExecutionHistoryRequest( + namespace=client.namespace, + execution=WorkflowExecution(workflow_id=handle.id), + ) + ) + cancel_events = [ + e + for e in resp.history.events + if e.event_type + == EventType.EVENT_TYPE_REQUEST_CANCEL_EXTERNAL_WORKFLOW_EXECUTION_INITIATED + ] + # There should be exactly one cancel request, not duplicates + assert len(cancel_events) == 1, ( + f"Expected exactly 1 RequestCancelExternalWorkflowExecution event, " + f"got {len(cancel_events)}" + ) + + # Verify no spurious "exception in shielded future" error logs + shielded_err = log_capturer.find_log("exception in shielded future") + assert shielded_err is None, ( + f"Unexpected 'exception in shielded future' log: {shielded_err}" + ) + + +@workflow.defn +class UncancelShieldSignalExternalWorkflow: + """Workflow that signals an external workflow from a task that gets + cancelled, exercising the shield loop in _signal_external_workflow.""" + + def __init__(self) -> None: + self._ready = False + + @workflow.run + async def run(self, target_workflow_id: str) -> str: + # Start a signal task + signal_task = asyncio.create_task( + workflow.get_external_workflow_handle(target_workflow_id).signal( + ReturnSignalWorkflow.my_signal, "test_value" + ) + ) + self._ready = True + # The signal should complete quickly, but we test the path where + # the workflow itself gets cancelled while the signal is pending + try: + await signal_task + return "signal_sent" + except CancelledError: + return "signal_cancelled" + + @workflow.query + def ready(self) -> bool: + return self._ready + + +async def test_workflow_uncancel_shield_signal_external(client: Client): + """Verify that signal external workflow completes without spurious errors + when the shield loop properly resets the cancellation counter. + """ + log_capturer = LogCapturer() + with log_capturer.logs_captured( + temporalio.worker._workflow_instance.logger, level=logging.WARNING + ): + async with new_worker( + client, + UncancelShieldSignalExternalWorkflow, + ReturnSignalWorkflow, + ) as worker: + # Start the target workflow that waits for a signal + target_handle = await client.start_workflow( + ReturnSignalWorkflow.run, + id=f"workflow-{uuid.uuid4()}", + task_queue=worker.task_queue, + ) + # Start the signaler workflow + result = await client.execute_workflow( + UncancelShieldSignalExternalWorkflow.run, + target_handle.id, + id=f"workflow-{uuid.uuid4()}", + task_queue=worker.task_queue, + ) + assert result == "signal_sent" + # Confirm the target received the signal + target_result = await target_handle.result() + assert target_result == "test_value" + + # Verify no spurious error logs + shielded_err = log_capturer.find_log("exception in shielded future") + assert shielded_err is None, ( + f"Unexpected 'exception in shielded future' log: {shielded_err}" + ) From 1f1d3e33351d6642b737caee0a1819899dd8687a Mon Sep 17 00:00:00 2001 From: Lingavasan Suresh Kumar Date: Thu, 28 May 2026 09:08:34 -0700 Subject: [PATCH 107/226] Expose JSON type converter unhandled sentinel type (#1556) Co-authored-by: tconley1428 --- README.md | 2 +- temporalio/converter/__init__.py | 2 ++ temporalio/converter/_payload_converter.py | 11 ++++++++--- tests/test_converter.py | 16 ++++++++++++++-- 4 files changed, 25 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index d284fad59..e00de1e84 100644 --- a/README.md +++ b/README.md @@ -432,7 +432,7 @@ class IPv4AddressJSONEncoder(AdvancedJSONEncoder): class IPv4AddressJSONTypeConverter(JSONTypeConverter): def to_typed_value( self, hint: Type, value: Any - ) -> Union[Optional[Any], _JSONTypeConverterUnhandled]: + ) -> Union[Optional[Any], JSONTypeConverterUnhandled]: if issubclass(hint, ipaddress.IPv4Address): return ipaddress.IPv4Address(value) return JSONTypeConverter.Unhandled diff --git a/temporalio/converter/__init__.py b/temporalio/converter/__init__.py index 3ca6a3507..3821cbd68 100644 --- a/temporalio/converter/__init__.py +++ b/temporalio/converter/__init__.py @@ -31,6 +31,7 @@ JSONPlainPayloadConverter, JSONProtoPayloadConverter, JSONTypeConverter, + JSONTypeConverterUnhandled, PayloadConverter, value_to_type, ) @@ -76,6 +77,7 @@ "JSONPlainPayloadConverter", "JSONProtoPayloadConverter", "JSONTypeConverter", + "JSONTypeConverterUnhandled", "PayloadCodec", "PayloadConverter", "PayloadLimitsConfig", diff --git a/temporalio/converter/_payload_converter.py b/temporalio/converter/_payload_converter.py index d2effc9d1..8ee85ef72 100644 --- a/temporalio/converter/_payload_converter.py +++ b/temporalio/converter/_payload_converter.py @@ -548,7 +548,10 @@ def default(self, o: Any) -> Any: return super().default(o) -_JSONTypeConverterUnhandled = NewType("_JSONTypeConverterUnhandled", object) +JSONTypeConverterUnhandled = NewType("JSONTypeConverterUnhandled", object) +"""Type of :py:attr:`JSONTypeConverter.Unhandled`.""" + +_JSONTypeConverterUnhandled = JSONTypeConverterUnhandled class JSONTypeConverter(ABC): @@ -556,7 +559,9 @@ class JSONTypeConverter(ABC): result (e.g. scalar, list, or dict) to a known type. """ - Unhandled = _JSONTypeConverterUnhandled(object()) + Unhandled: ClassVar[JSONTypeConverterUnhandled] = JSONTypeConverterUnhandled( + object() + ) """Sentinel value that must be used as the result of :py:meth:`to_typed_value` to say the given type is not handled by this converter.""" @@ -564,7 +569,7 @@ class JSONTypeConverter(ABC): @abstractmethod def to_typed_value( self, hint: type, value: Any - ) -> Any | None | _JSONTypeConverterUnhandled: + ) -> Any | None | JSONTypeConverterUnhandled: """Convert the given value to a type based on the given hint. Args: diff --git a/tests/test_converter.py b/tests/test_converter.py index dfe8860d1..10365f9c1 100644 --- a/tests/test_converter.py +++ b/tests/test_converter.py @@ -16,6 +16,8 @@ Dict, # type:ignore[reportDeprecated] Literal, NewType, + get_args, + get_type_hints, ) from uuid import UUID, uuid4 @@ -40,12 +42,12 @@ DefaultPayloadConverter, JSONPlainPayloadConverter, JSONTypeConverter, + JSONTypeConverterUnhandled, PayloadCodec, decode_search_attributes, encode_search_attribute_values, value_to_type, ) -from temporalio.converter._payload_converter import _JSONTypeConverterUnhandled from temporalio.exceptions import ( ApplicationError, FailureError, @@ -869,12 +871,22 @@ def default(self, o: Any) -> Any: class IPv4AddressJSONTypeConverter(JSONTypeConverter): def to_typed_value( self, hint: type, value: Any - ) -> Any | None | _JSONTypeConverterUnhandled: + ) -> Any | None | JSONTypeConverterUnhandled: if inspect.isclass(hint) and issubclass(hint, ipaddress.IPv4Address): return ipaddress.IPv4Address(value) return JSONTypeConverter.Unhandled +def test_json_type_converter_unhandled_type_public(): + return_type = get_type_hints(JSONTypeConverter.to_typed_value)["return"] + + assert JSONTypeConverterUnhandled.__name__ == "JSONTypeConverterUnhandled" + assert JSONTypeConverterUnhandled in get_args(return_type) + assert JSONTypeConverterUnhandled(JSONTypeConverter.Unhandled) is ( + JSONTypeConverter.Unhandled + ) + + async def test_json_type_converter(): addr = ipaddress.IPv4Address("1.2.3.4") custom_conv = dataclasses.replace( From bea727c7ec02aed2408ef00659a3aeec1d9f5f06 Mon Sep 17 00:00:00 2001 From: Thomas Hardy Date: Thu, 28 May 2026 15:49:20 -0400 Subject: [PATCH 108/226] remove unused omes job (#1559) --- .github/workflows/omes.yml | 22 ---------------------- 1 file changed, 22 deletions(-) delete mode 100644 .github/workflows/omes.yml diff --git a/.github/workflows/omes.yml b/.github/workflows/omes.yml deleted file mode 100644 index 6afa925e1..000000000 --- a/.github/workflows/omes.yml +++ /dev/null @@ -1,22 +0,0 @@ -name: Omes Testing -on: - push: - branches: - - main - - "releases/*" - -permissions: - contents: read - packages: write - -jobs: - omes-image-build: - uses: temporalio/omes/.github/workflows/docker-images.yml@main - secrets: inherit - with: - lang: python - sdk-repo-url: ${{ github.event.pull_request.head.repo.full_name || 'temporalio/sdk-python' }} - sdk-repo-ref: ${{ github.event.pull_request.head.ref || github.ref }} - # TODO: Remove once we have a good way of cleaning up sha-based pushed images - docker-tag-ext: ci-latest - do-push: true From 28243b9e038f5be323ab80f236dd8f7df1e4a1f0 Mon Sep 17 00:00:00 2001 From: Brian Strauch Date: Thu, 28 May 2026 16:15:27 -0700 Subject: [PATCH 109/226] Tolerate OpenAI model schema drift in the agents payload converter (#1563) * Tolerate OpenAI model schema drift in the agents payload converter The OpenAI SDK response models can drift from live API payloads (e.g. a deprecated-but-required field the API has stopped sending, such as ActionSearch.query on web_search_call results). The SDK tolerates this when parsing responses, but strict TypeAdapter.validate_json on the workflow side does not, which breaks deserializing ModelResponse across the activity boundary. Add a lenient fallback to the OpenAI agents payload converter: try strict pydantic validation first and, only on ValidationError, rebuild via OpenAI's own construct_type (handling the agents dataclass wrapper). The happy path is unchanged; the fallback retires once upstream fixes the field requiredness. * Update research mock to emit web_search action with queries, not query Mirror the current OpenAI API, which returns the search action with the plural `queries` and omits the deprecated singular `query`. Built via model_construct so the required-but-unset `query` is excluded on serialization, exercising the lenient converter fallback in the use_local_model path without needing a live API key. * Sort imports in OpenAI agents overrides * Reimplement OpenAIPayloadConverter as a CompositePayloadConverter Build the converter tuple directly instead of mutating self.converters after super().__init__(). --- .../openai_agents/_temporal_openai_agents.py | 76 ++++++++++++++++++- tests/contrib/openai_agents/test_openai.py | 4 +- 2 files changed, 76 insertions(+), 4 deletions(-) diff --git a/temporalio/contrib/openai_agents/_temporal_openai_agents.py b/temporalio/contrib/openai_agents/_temporal_openai_agents.py index 60b4b36ef..43594657f 100644 --- a/temporalio/contrib/openai_agents/_temporal_openai_agents.py +++ b/temporalio/contrib/openai_agents/_temporal_openai_agents.py @@ -1,16 +1,24 @@ """Initialize Temporal OpenAI Agents overrides.""" import dataclasses +import json import typing from collections.abc import AsyncIterator, Callable, Iterator, Sequence from contextlib import asynccontextmanager, contextmanager from datetime import timedelta +import pydantic from agents import ModelProvider, Trace, set_trace_provider from agents.run import get_default_agent_runner, set_default_agent_runner from agents.tracing import get_trace_provider from agents.tracing.provider import DefaultTraceProvider +# construct_type is OpenAI's lenient (non-validating) model builder, the same +# one the SDK uses to parse live API responses. It is in a private module but +# has no public alias. +from openai._models import construct_type + +import temporalio.api.common.v1 from temporalio.contrib.openai_agents._invoke_model_activity import ModelActivity from temporalio.contrib.openai_agents._model_parameters import ModelActivityParameters from temporalio.contrib.openai_agents._openai_runner import ( @@ -25,12 +33,14 @@ from temporalio.contrib.openai_agents.workflow import AgentsWorkflowError from temporalio.contrib.opentelemetry._tracer_provider import ReplaySafeTracerProvider from temporalio.contrib.pydantic import ( - PydanticPayloadConverter, + PydanticJSONPlainPayloadConverter, ToJsonOptions, ) from temporalio.converter import ( + CompositePayloadConverter, DataConverter, DefaultPayloadConverter, + JSONPlainPayloadConverter, ) from temporalio.plugin import SimplePlugin from temporalio.worker import WorkflowRunner @@ -64,12 +74,72 @@ def _set_open_ai_agent_temporal_overrides( set_trace_provider(previous_trace_provider or DefaultTraceProvider()) -class OpenAIPayloadConverter(PydanticPayloadConverter): +def _lenient_construct(type_: typing.Any, value: typing.Any) -> typing.Any: + """Build ``value`` into ``type_`` without enforcing required fields. + + OpenAI's ``construct_type`` handles its own response models (and the + unions/lists thereof), but not the ``agents`` dataclasses that wrap them + (e.g. ``ModelResponse``), so the dataclass layer is reconstructed here and + each field delegated to ``construct_type``. ``include_extras`` preserves the + ``Annotated`` discriminators the unions rely on. + """ + if ( + isinstance(type_, type) + and dataclasses.is_dataclass(type_) + and isinstance(value, dict) + ): + hints = typing.get_type_hints(type_, include_extras=True) + return type_( + **{ + field.name: _lenient_construct( + hints.get(field.name, object), value[field.name] + ) + for field in dataclasses.fields(type_) + if field.name in value + } + ) + return construct_type(type_=type_, value=value) + + +class _OpenAIJSONPlainPayloadConverter(PydanticJSONPlainPayloadConverter): + """Strict pydantic deserialization with a lenient fallback. + + OpenAI's response models can drift from live API payloads (e.g. a + deprecated-but-required field the API has stopped sending). The SDK tolerates + this when parsing responses, but strict ``validate_json`` on the workflow + side does not, so fall back to lenient construction when validation fails. + """ + + def from_payload( + self, + payload: temporalio.api.common.v1.Payload, + type_hint: type | None = None, + ) -> typing.Any: + """See base class.""" + try: + return super().from_payload(payload, type_hint) + except pydantic.ValidationError: + if type_hint is None: + raise + return _lenient_construct(type_hint, json.loads(payload.data)) + + +class OpenAIPayloadConverter(CompositePayloadConverter): """PayloadConverter for OpenAI agents.""" def __init__(self) -> None: """Initialize a payload converter.""" - super().__init__(ToJsonOptions(exclude_unset=True)) + json_payload_converter = _OpenAIJSONPlainPayloadConverter( + ToJsonOptions(exclude_unset=True) + ) + super().__init__( + *( + c + if not isinstance(c, JSONPlainPayloadConverter) + else json_payload_converter + for c in DefaultPayloadConverter.default_encoding_payload_converters + ) + ) def _data_converter(converter: DataConverter | None) -> DataConverter: diff --git a/tests/contrib/openai_agents/test_openai.py b/tests/contrib/openai_agents/test_openai.py index 294acc1d0..de0af3923 100644 --- a/tests/contrib/openai_agents/test_openai.py +++ b/tests/contrib/openai_agents/test_openai.py @@ -547,7 +547,9 @@ def research_mock_model(): id="", status="completed", type="web_search_call", - action=ActionSearch(query="", type="search"), + action=ActionSearch.model_construct( + type="search", queries=[""] + ), ), ResponseBuilders.response_output_message("Granada"), ], From 43a3c16b01d3fe1fc5fc8dfa15d7aef1205407bb Mon Sep 17 00:00:00 2001 From: Alex Mazzeo Date: Thu, 28 May 2026 17:32:33 -0700 Subject: [PATCH 110/226] Add Temporal Operation Handler (#1503) * Narrow overloads on the sano client. * remove result_type params for overloads that don't need them * Add Temporal Nexus operation handler * Add overloads to sano client and increase type test coverage * Expose customizable Temporal Nexus operation handlers. Rename the Temporal operation start context to TemporalNexusStartOperationContext and add TemporalNexusCancelOperationContext with access to the worker client. Make TemporalNexusOperationHandler a public abstract base with overrideable start_operation and cancel_workflow_run hooks, while keeping the decorator-backed implementation private. Update type annotations, exports, and tests, including coverage for custom Temporal operation cancellation. * Add time-skippping check in test that leverages sano * Address claude/codex review suggestions. Make TemporalNexusClient ABC to prevent users from instantiating. * Add tests for valid token forms. Update namespace check to reflect prior logic of accepting empty strings * Add validation for TemporalOperationResult construction * Add docstring to __post_init__ * run formatter * Address PR feedback. Change TemporalNexus[Start|Cancel]OperationContext to be type aliases. Remove overly cautious _is_subclass helper. Add typedef for TemporalNexusOperationStartHandlerFunc to improve readability * Remove leftover commented code * Swap type aliases back to classes to avoid printing or runtime type checking concerns * move to an options dataclass for cancel_workflow_run to future proof against new options * clean up a docstring * Fix docstring manipulation flagged by opus 4.8 by moving the concrete implementation of _TemporalNexusOperationHandler to the decorator --- temporalio/client/_nexus.py | 58 ++ temporalio/nexus/__init__.py | 21 +- temporalio/nexus/_decorators.py | 151 +++- temporalio/nexus/_operation_context.py | 179 +++-- temporalio/nexus/_operation_handlers.py | 105 ++- temporalio/nexus/_temporal_client.py | 379 ++++++++++ temporalio/nexus/_token.py | 159 ++-- temporalio/nexus/_util.py | 106 ++- temporalio/workflow/__init__.py | 3 - temporalio/workflow/_nexus.py | 61 +- tests/helpers/__init__.py | 38 + .../test_handler_operation_definitions.py | 99 +++ tests/nexus/test_nexus_client_updates.py | 2 +- tests/nexus/test_nexus_type_errors.py | 300 +++++++- tests/nexus/test_operation_token.py | 158 ++++ tests/nexus/test_temporal_operation.py | 689 ++++++++++++++++++ ...test_workflow_caller_cancellation_types.py | 37 +- ...llation_types_when_cancel_handler_fails.py | 3 +- tests/test_workflow_exports.py | 1 - 19 files changed, 2358 insertions(+), 191 deletions(-) create mode 100644 temporalio/nexus/_temporal_client.py create mode 100644 tests/nexus/test_operation_token.py create mode 100644 tests/nexus/test_temporal_operation.py diff --git a/temporalio/client/_nexus.py b/temporalio/client/_nexus.py index 060235e01..8cd95b26f 100644 --- a/temporalio/client/_nexus.py +++ b/temporalio/client/_nexus.py @@ -611,6 +611,35 @@ async def start_operation( rpc_timeout: timedelta | None = None, ) -> NexusOperationHandle[OutputT]: ... + # Overload for temporal_operation methods + @overload + @abstractmethod + async def start_operation( + self, + operation: Callable[ + [ + NexusServiceType, + temporalio.nexus.TemporalNexusStartOperationContext, + temporalio.nexus.TemporalNexusClient, + InputT, + ], + Awaitable[temporalio.nexus.TemporalOperationResult[OutputT]], + ], + arg: InputT, + *, + id: str, + id_reuse_policy: temporalio.common.NexusOperationIDReusePolicy = temporalio.common.NexusOperationIDReusePolicy.ALLOW_DUPLICATE, + id_conflict_policy: temporalio.common.NexusOperationIDConflictPolicy = temporalio.common.NexusOperationIDConflictPolicy.FAIL, + schedule_to_close_timeout: timedelta | None = None, + schedule_to_start_timeout: timedelta | None = None, + start_to_close_timeout: timedelta | None = None, + search_attributes: temporalio.common.TypedSearchAttributes | None = None, + summary: str | None = None, + headers: Mapping[str, str] | None = None, + rpc_metadata: Mapping[str, str | bytes] = {}, + rpc_timeout: timedelta | None = None, + ) -> NexusOperationHandle[OutputT]: ... + @abstractmethod async def start_operation( self, @@ -804,6 +833,35 @@ async def execute_operation( rpc_timeout: timedelta | None = None, ) -> OutputT: ... + # Overload for temporal_operation methods + @overload + @abstractmethod + async def execute_operation( + self, + operation: Callable[ + [ + NexusServiceType, + temporalio.nexus.TemporalNexusStartOperationContext, + temporalio.nexus.TemporalNexusClient, + InputT, + ], + Awaitable[temporalio.nexus.TemporalOperationResult[OutputT]], + ], + arg: InputT, + *, + id: str, + id_reuse_policy: temporalio.common.NexusOperationIDReusePolicy = temporalio.common.NexusOperationIDReusePolicy.ALLOW_DUPLICATE, + id_conflict_policy: temporalio.common.NexusOperationIDConflictPolicy = temporalio.common.NexusOperationIDConflictPolicy.FAIL, + schedule_to_close_timeout: timedelta | None = None, + schedule_to_start_timeout: timedelta | None = None, + start_to_close_timeout: timedelta | None = None, + search_attributes: temporalio.common.TypedSearchAttributes | None = None, + summary: str | None = None, + headers: Mapping[str, str] | None = None, + rpc_metadata: Mapping[str, str | bytes] = {}, + rpc_timeout: timedelta | None = None, + ) -> OutputT: ... + @abstractmethod async def execute_operation( self, diff --git a/temporalio/nexus/__init__.py b/temporalio/nexus/__init__.py index ea049d90e..f1a10767d 100644 --- a/temporalio/nexus/__init__.py +++ b/temporalio/nexus/__init__.py @@ -3,11 +3,17 @@ See https://github.com/temporalio/sdk-python/tree/main#nexus """ -from ._decorators import workflow_run_operation +from ._decorators import ( + TemporalNexusOperationStartHandlerFunc, + temporal_operation, + workflow_run_operation, +) from ._operation_context import ( Info, LoggerAdapter, NexusCallback, + TemporalNexusCancelOperationContext, + TemporalNexusStartOperationContext, WorkflowRunOperationContext, client, in_operation, @@ -18,14 +24,22 @@ wait_for_worker_shutdown, wait_for_worker_shutdown_sync, ) +from ._operation_handlers import ( + CancelWorkflowRunOptions, + TemporalNexusOperationHandler, +) +from ._temporal_client import TemporalNexusClient, TemporalOperationResult from ._token import WorkflowHandle __all__ = ( "workflow_run_operation", + "CancelWorkflowRunOptions", "Info", "LoggerAdapter", "NexusCallback", "WorkflowRunOperationContext", + "TemporalNexusCancelOperationContext", + "TemporalNexusStartOperationContext", "client", "in_operation", "info", @@ -35,4 +49,9 @@ "wait_for_worker_shutdown", "wait_for_worker_shutdown_sync", "WorkflowHandle", + "TemporalNexusClient", + "TemporalNexusOperationStartHandlerFunc", + "TemporalNexusOperationHandler", + "TemporalOperationResult", + "temporal_operation", ) diff --git a/temporalio/nexus/_decorators.py b/temporalio/nexus/_decorators.py index 6dfd3daff..3f1a322e7 100644 --- a/temporalio/nexus/_decorators.py +++ b/temporalio/nexus/_decorators.py @@ -2,7 +2,7 @@ from collections.abc import Awaitable, Callable from typing import ( - TypeVar, + TypeAlias, overload, ) @@ -12,27 +12,40 @@ OperationHandler, StartOperationContext, ) +from typing_extensions import override -from ._operation_context import WorkflowRunOperationContext -from ._operation_handlers import WorkflowRunOperationHandler +from temporalio.nexus._temporal_client import ( + TemporalNexusClient, + TemporalOperationResult, +) +from temporalio.types import NexusServiceType + +from ._operation_context import ( + TemporalNexusStartOperationContext, + WorkflowRunOperationContext, +) +from ._operation_handlers import ( + TemporalNexusOperationHandler, + WorkflowRunOperationHandler, +) from ._token import WorkflowHandle from ._util import ( get_callable_name, + get_temporal_operation_start_method_input_and_output_type_annotations, get_workflow_run_start_method_input_and_output_type_annotations, + is_async_callable, set_operation_factory, ) -ServiceHandlerT = TypeVar("ServiceHandlerT") - @overload def workflow_run_operation( start: Callable[ - [ServiceHandlerT, WorkflowRunOperationContext, InputT], + [NexusServiceType, WorkflowRunOperationContext, InputT], Awaitable[WorkflowHandle[OutputT]], ], ) -> Callable[ - [ServiceHandlerT, WorkflowRunOperationContext, InputT], + [NexusServiceType, WorkflowRunOperationContext, InputT], Awaitable[WorkflowHandle[OutputT]], ]: ... @@ -44,12 +57,12 @@ def workflow_run_operation( ) -> Callable[ [ Callable[ - [ServiceHandlerT, WorkflowRunOperationContext, InputT], + [NexusServiceType, WorkflowRunOperationContext, InputT], Awaitable[WorkflowHandle[OutputT]], ] ], Callable[ - [ServiceHandlerT, WorkflowRunOperationContext, InputT], + [NexusServiceType, WorkflowRunOperationContext, InputT], Awaitable[WorkflowHandle[OutputT]], ], ]: ... @@ -59,7 +72,7 @@ def workflow_run_operation( start: None | ( Callable[ - [ServiceHandlerT, WorkflowRunOperationContext, InputT], + [NexusServiceType, WorkflowRunOperationContext, InputT], Awaitable[WorkflowHandle[OutputT]], ] ) = None, @@ -67,18 +80,18 @@ def workflow_run_operation( name: str | None = None, ) -> ( Callable[ - [ServiceHandlerT, WorkflowRunOperationContext, InputT], + [NexusServiceType, WorkflowRunOperationContext, InputT], Awaitable[WorkflowHandle[OutputT]], ] | Callable[ [ Callable[ - [ServiceHandlerT, WorkflowRunOperationContext, InputT], + [NexusServiceType, WorkflowRunOperationContext, InputT], Awaitable[WorkflowHandle[OutputT]], ] ], Callable[ - [ServiceHandlerT, WorkflowRunOperationContext, InputT], + [NexusServiceType, WorkflowRunOperationContext, InputT], Awaitable[WorkflowHandle[OutputT]], ], ] @@ -87,11 +100,11 @@ def workflow_run_operation( def decorator( start: Callable[ - [ServiceHandlerT, WorkflowRunOperationContext, InputT], + [NexusServiceType, WorkflowRunOperationContext, InputT], Awaitable[WorkflowHandle[OutputT]], ], ) -> Callable[ - [ServiceHandlerT, WorkflowRunOperationContext, InputT], + [NexusServiceType, WorkflowRunOperationContext, InputT], Awaitable[WorkflowHandle[OutputT]], ]: ( @@ -100,7 +113,7 @@ def decorator( ) = get_workflow_run_start_method_input_and_output_type_annotations(start) def operation_handler_factory( - self: ServiceHandlerT, + self: NexusServiceType, ) -> OperationHandler[InputT, OutputT]: async def _start( ctx: StartOperationContext, input: InputT @@ -130,3 +143,109 @@ async def _start( return decorator return decorator(start) + + +TemporalNexusOperationStartHandlerFunc: TypeAlias = Callable[ + [ + NexusServiceType, + TemporalNexusStartOperationContext, + TemporalNexusClient, + InputT, + ], + Awaitable[TemporalOperationResult[OutputT]], +] + + +@overload +def temporal_operation( + start: TemporalNexusOperationStartHandlerFunc[NexusServiceType, InputT, OutputT], +) -> TemporalNexusOperationStartHandlerFunc[NexusServiceType, InputT, OutputT]: ... + + +@overload +def temporal_operation( + *, + name: str | None = None, +) -> Callable[ + [TemporalNexusOperationStartHandlerFunc[NexusServiceType, InputT, OutputT]], + TemporalNexusOperationStartHandlerFunc[NexusServiceType, InputT, OutputT], +]: ... + + +def temporal_operation( + start: None + | TemporalNexusOperationStartHandlerFunc[NexusServiceType, InputT, OutputT] = None, + *, + name: str | None = None, +) -> ( + TemporalNexusOperationStartHandlerFunc[NexusServiceType, InputT, OutputT] + | Callable[ + [TemporalNexusOperationStartHandlerFunc[NexusServiceType, InputT, OutputT]], + TemporalNexusOperationStartHandlerFunc[NexusServiceType, InputT, OutputT], + ] +): + """Decorator marking a method as the start method for an operation that interacts with Temporal. + + .. warning:: + This API is experimental and unstable. + """ + + def decorator( + start: TemporalNexusOperationStartHandlerFunc[ + NexusServiceType, InputT, OutputT + ], + ) -> TemporalNexusOperationStartHandlerFunc[NexusServiceType, InputT, OutputT]: + if not is_async_callable(start): + raise RuntimeError( + f"{start} is not an `async def` method. " + "@temporal_operation must decorate an `async def` start method." + ) + ( + input_type, + output_type, + ) = get_temporal_operation_start_method_input_and_output_type_annotations(start) + + def operation_handler_factory( + self: NexusServiceType, + ) -> OperationHandler[InputT, OutputT]: + async def _start( + ctx: TemporalNexusStartOperationContext, + client: TemporalNexusClient, + input: InputT, + ) -> TemporalOperationResult[OutputT]: + return await start( + self, + ctx, + client, + input, + ) + + class _TemporalNexusOperationHandler(TemporalNexusOperationHandler): + @override + async def start_operation( + self, + ctx: TemporalNexusStartOperationContext, + client: TemporalNexusClient, + input: InputT, + ) -> TemporalOperationResult[OutputT]: + return await _start(ctx, client, input) + + _TemporalNexusOperationHandler.start_operation.__doc__ = start.__doc__ + return _TemporalNexusOperationHandler() + + method_name = get_callable_name(start) + op = nexusrpc.Operation( + name=name or method_name, + input_type=input_type, + output_type=output_type, + ) + op.method_name = method_name + nexusrpc.set_operation(operation_handler_factory, op) + + set_operation_factory(start, operation_handler_factory) + return start + + if start is None: + return decorator + + return decorator(start) diff --git a/temporalio/nexus/_operation_context.py b/temporalio/nexus/_operation_context.py index 069fd65d3..e8ead61fe 100644 --- a/temporalio/nexus/_operation_context.py +++ b/temporalio/nexus/_operation_context.py @@ -28,6 +28,7 @@ OperationContext, StartOperationContext, ) +from typing_extensions import Self import temporalio.api.common.v1 import temporalio.api.workflowservice.v1 @@ -492,50 +493,34 @@ async def start_workflow( Nexus caller is itself a workflow, this means that the workflow in the caller namespace web UI will contain links to the started workflow, and vice versa. """ - # We must pass nexus_completion_callbacks, event_links, and request_id, - # but these are deliberately not exposed in overloads, hence the type-check - # violation. - - # Here we are starting a "nexus-backing" workflow. That means that the StartWorkflow request - # contains nexus-specific data such as a completion callback (used by the handler server - # namespace to deliver the result to the caller namespace when the workflow reaches a - # terminal state) and inbound links to the caller workflow (attached to history events of - # the workflow started in the handler namespace, and displayed in the UI). - with _nexus_backing_workflow_start_context(): - wf_handle = await self._temporal_context.client.start_workflow( # type: ignore - workflow=workflow, - arg=arg, - args=args, - id=id, - task_queue=task_queue or self._temporal_context.info().task_queue, - result_type=result_type, - execution_timeout=execution_timeout, - run_timeout=run_timeout, - task_timeout=task_timeout, - id_reuse_policy=id_reuse_policy, - id_conflict_policy=id_conflict_policy, - retry_policy=retry_policy, - cron_schedule=cron_schedule, - memo=memo, - search_attributes=search_attributes, - static_summary=static_summary, - static_details=static_details, - start_delay=start_delay, - start_signal=start_signal, - start_signal_args=start_signal_args, - rpc_metadata=rpc_metadata, - rpc_timeout=rpc_timeout, - request_eager_start=request_eager_start, - priority=priority, - versioning_override=versioning_override, - callbacks=self._temporal_context._get_callbacks(), - links=self._temporal_context._get_links(), - request_id=self._temporal_context.nexus_context.request_id, - ) - - self._temporal_context._add_outbound_links(wf_handle) - - return WorkflowHandle[ReturnType]._unsafe_from_client_workflow_handle(wf_handle) + return await _start_nexus_backing_workflow( + temporal_context=self._temporal_context, + workflow=workflow, + arg=arg, + args=args, + id=id, + task_queue=task_queue, + result_type=result_type, + execution_timeout=execution_timeout, + run_timeout=run_timeout, + task_timeout=task_timeout, + id_reuse_policy=id_reuse_policy, + id_conflict_policy=id_conflict_policy, + retry_policy=retry_policy, + cron_schedule=cron_schedule, + memo=memo, + search_attributes=search_attributes, + static_summary=static_summary, + static_details=static_details, + start_delay=start_delay, + start_signal=start_signal, + start_signal_args=start_signal_args, + rpc_metadata=rpc_metadata, + rpc_timeout=rpc_timeout, + request_eager_start=request_eager_start, + priority=priority, + versioning_override=versioning_override, + ) @dataclass(frozen=True) @@ -564,6 +549,34 @@ def set(self) -> None: _temporal_cancel_operation_context.set(self) +class TemporalNexusStartOperationContext(StartOperationContext): + """Context received by a Temporal Nexus operation when it is started. + + .. warning:: + This API is experimental and unstable. + """ + + @classmethod + def _from_start_operation_context(cls, ctx: StartOperationContext) -> Self: + return cls( + **{f.name: getattr(ctx, f.name) for f in dataclasses.fields(ctx)}, + ) + + +class TemporalNexusCancelOperationContext(CancelOperationContext): + """Context received by a Temporal Nexus operation when it is canceled. + + .. warning:: + This API is experimental and unstable. + """ + + @classmethod + def _from_cancel_operation_context(cls, ctx: CancelOperationContext) -> Self: + return cls( + **{f.name: getattr(ctx, f.name) for f in dataclasses.fields(ctx)}, + ) + + class LoggerAdapter(logging.LoggerAdapter): """Logger adapter that adds Nexus operation context information.""" @@ -586,3 +599,81 @@ def process( logger = LoggerAdapter(logging.getLogger("temporalio.nexus"), None) """Logger that emits additional data describing the current Nexus operation.""" + + +async def _start_nexus_backing_workflow( + temporal_context: _TemporalStartOperationContext, + workflow: str | Callable[..., Awaitable[ReturnType]], + arg: Any = temporalio.common._arg_unset, + *, + args: Sequence[Any] = [], + id: str, + task_queue: str | None = None, + result_type: type | None = None, + execution_timeout: timedelta | None = None, + run_timeout: timedelta | None = None, + task_timeout: timedelta | None = None, + id_reuse_policy: temporalio.common.WorkflowIDReusePolicy = temporalio.common.WorkflowIDReusePolicy.ALLOW_DUPLICATE, + id_conflict_policy: temporalio.common.WorkflowIDConflictPolicy = temporalio.common.WorkflowIDConflictPolicy.UNSPECIFIED, + retry_policy: temporalio.common.RetryPolicy | None = None, + cron_schedule: str = "", + memo: Mapping[str, Any] | None = None, + search_attributes: None + | ( + temporalio.common.TypedSearchAttributes | temporalio.common.SearchAttributes + ) = None, + static_summary: str | None = None, + static_details: str | None = None, + start_delay: timedelta | None = None, + start_signal: str | None = None, + start_signal_args: Sequence[Any] = [], + rpc_metadata: Mapping[str, str | bytes] = {}, + rpc_timeout: timedelta | None = None, + request_eager_start: bool = False, + priority: temporalio.common.Priority = temporalio.common.Priority.default, + versioning_override: temporalio.common.VersioningOverride | None = None, +) -> WorkflowHandle[ReturnType]: + # We must pass nexus_completion_callbacks, workflow_event_links, and request_id, + # but these are deliberately not exposed in overloads, hence the type-check + # violation. + + # Here we are starting a "nexus-backing" workflow. That means that the StartWorkflow request + # contains nexus-specific data such as a completion callback (used by the handler server + # namespace to deliver the result to the caller namespace when the workflow reaches a + # terminal state) and inbound links to the caller workflow (attached to history events of + # the workflow started in the handler namespace, and displayed in the UI). + with _nexus_backing_workflow_start_context(): + wf_handle = await temporal_context.client.start_workflow( # type: ignore + workflow=workflow, + arg=arg, + args=args, + id=id, + task_queue=task_queue or temporal_context.info().task_queue, + result_type=result_type, + execution_timeout=execution_timeout, + run_timeout=run_timeout, + task_timeout=task_timeout, + id_reuse_policy=id_reuse_policy, + id_conflict_policy=id_conflict_policy, + retry_policy=retry_policy, + cron_schedule=cron_schedule, + memo=memo, + search_attributes=search_attributes, + static_summary=static_summary, + static_details=static_details, + start_delay=start_delay, + start_signal=start_signal, + start_signal_args=start_signal_args, + rpc_metadata=rpc_metadata, + rpc_timeout=rpc_timeout, + request_eager_start=request_eager_start, + priority=priority, + versioning_override=versioning_override, + callbacks=temporal_context._get_callbacks(), + links=temporal_context._get_links(), + request_id=temporal_context.nexus_context.request_id, + ) + + temporal_context._add_outbound_links(wf_handle) + + return WorkflowHandle[ReturnType]._unsafe_from_client_workflow_handle(wf_handle) diff --git a/temporalio/nexus/_operation_handlers.py b/temporalio/nexus/_operation_handlers.py index 68035ca41..c3e4b2e5e 100644 --- a/temporalio/nexus/_operation_handlers.py +++ b/temporalio/nexus/_operation_handlers.py @@ -1,9 +1,9 @@ from __future__ import annotations +from abc import ABC, abstractmethod from collections.abc import Awaitable, Callable -from typing import ( - Any, -) +from dataclasses import dataclass +from typing import Any from nexusrpc import ( HandlerError, @@ -16,12 +16,21 @@ OperationHandler, StartOperationContext, StartOperationResultAsync, + StartOperationResultSync, ) +import temporalio.nexus from temporalio.nexus._operation_context import ( + TemporalNexusCancelOperationContext, + TemporalNexusStartOperationContext, _temporal_cancel_operation_context, ) -from temporalio.nexus._token import WorkflowHandle +from temporalio.nexus._temporal_client import ( + TemporalNexusClient, + TemporalOperationResult, + _TemporalNexusClient, +) +from temporalio.nexus._token import OperationToken, OperationTokenType, WorkflowHandle from ._util import ( is_async_callable, @@ -112,3 +121,91 @@ async def _cancel_workflow( type=HandlerErrorType.NOT_FOUND, ) from err await client_workflow_handle.cancel(**kwargs) + + +@dataclass(frozen=True) +class CancelWorkflowRunOptions: + """Options for cancelling the workflow backing a Nexus operation. + + These options are built by :py:class:`TemporalNexusOperationHandler` and passed to + :py:meth:`TemporalNexusOperationHandler.cancel_workflow_run`. + + .. warning:: + This API is experimental and unstable. + """ + + workflow_id: str + """The ID of the workflow to cancel.""" + + +class TemporalNexusOperationHandler(OperationHandler[InputT, OutputT], ABC): + """Operation handler for Nexus operations that interact with Temporal. + Implementations override the start_operation method. + + .. warning:: + This API is experimental and unstable. + """ + + @abstractmethod + async def start_operation( + self, + ctx: TemporalNexusStartOperationContext, + client: TemporalNexusClient, + input: InputT, + ) -> TemporalOperationResult[OutputT]: + """Start the Temporal-backed Nexus operation.""" + ... + + async def start( + self, ctx: StartOperationContext, input: InputT + ) -> StartOperationResultSync[OutputT] | StartOperationResultAsync: + """Start the Nexus operation using a Nexus-aware Temporal client. + + .. warning:: + This API is experimental and unstable. + """ + nexus_client = _TemporalNexusClient() + start_ctx = TemporalNexusStartOperationContext._from_start_operation_context( + ctx + ) + result = await self.start_operation(start_ctx, nexus_client, input) + return result._to_nexus_result() + + async def cancel(self, ctx: CancelOperationContext, token: str) -> None: + """Cancel a Nexus operation using its operation token. + + .. warning:: + This API is experimental and unstable. + """ + try: + operation_token = OperationToken.decode(token) + except Exception as err: + raise HandlerError( + "Unable to decode operation token to cancel", + type=HandlerErrorType.INTERNAL, + ) from err + + cancel_ctx = TemporalNexusCancelOperationContext._from_cancel_operation_context( + ctx + ) + match operation_token.type: + case OperationTokenType.WORKFLOW: + options = CancelWorkflowRunOptions( + workflow_id=operation_token.workflow_id + ) + await self.cancel_workflow_run(cancel_ctx, options) + + async def cancel_workflow_run( + self, + ctx: TemporalNexusCancelOperationContext, # pyright: ignore[reportUnusedParameter] + options: CancelWorkflowRunOptions, + ) -> None: + """Cancels the workflow backing the Nexus operation. + + .. warning:: + This API is experimental and unstable. + """ + workflow_handle = temporalio.nexus.client().get_workflow_handle( + options.workflow_id + ) + await workflow_handle.cancel() diff --git a/temporalio/nexus/_temporal_client.py b/temporalio/nexus/_temporal_client.py new file mode 100644 index 000000000..08204d89b --- /dev/null +++ b/temporalio/nexus/_temporal_client.py @@ -0,0 +1,379 @@ +from __future__ import annotations + +from abc import ABC, abstractmethod +from collections.abc import Awaitable, Callable, Iterator, Mapping, Sequence +from contextlib import contextmanager +from dataclasses import dataclass +from datetime import timedelta +from typing import ( + TYPE_CHECKING, + Any, + Concatenate, + Generic, + TypeVar, + cast, + overload, +) + +from nexusrpc import HandlerError, HandlerErrorType +from nexusrpc.handler import StartOperationResultAsync, StartOperationResultSync +from typing_extensions import Self + +import temporalio.common +from temporalio.nexus._operation_context import ( + _start_nexus_backing_workflow, + _TemporalStartOperationContext, +) +from temporalio.types import ( + MethodAsyncNoParam, + MethodAsyncSingleParam, + MultiParamSpec, + ParamType, + ReturnType, + SelfType, +) + +if TYPE_CHECKING: + import temporalio.client + + +_ResultT = TypeVar("_ResultT") + + +@dataclass(frozen=True) +class TemporalOperationResult(Generic[_ResultT]): + """Unified result: sync value or async token. + + .. warning:: + This API is experimental and unstable. + """ + + value: _ResultT | object = temporalio.common._arg_unset + token: str | None = None + + def __post_init__(self) -> None: + """Validate that the result represents exactly one completion mode.""" + has_value = self.value is not temporalio.common._arg_unset + has_token = self.token is not None + if has_value == has_token: + raise ValueError( + "TemporalOperationResult must have exactly one of value or token set." + ) + if has_token and (not isinstance(self.token, str) or not self.token): + raise ValueError( + "TemporalOperationResult token must be a non-empty string." + ) + + @classmethod + def sync(cls, value: _ResultT) -> Self: + """Create a result that completes the Nexus operation synchronously.""" + return cls(value=value) + + @classmethod + def async_token(cls, token: str) -> Self: + """Create a result that completes the Nexus operation asynchronously.""" + return cls(token=token) + + def _to_nexus_result( + self, + ) -> StartOperationResultSync[_ResultT] | StartOperationResultAsync: + if self.token is not None: + return StartOperationResultAsync(self.token) + elif self.value is not temporalio.common._arg_unset: + return StartOperationResultSync(cast(_ResultT, self.value)) + else: + raise RuntimeError( + "Invalid TemporalOperationResult. Neither token nor value are set." + ) + + +class TemporalNexusClient(ABC): + """Nexus-aware wrapper around a Temporal Client. + + .. warning:: + This API is experimental and unstable. + """ + + @property + @abstractmethod + def client(self) -> temporalio.client.Client: + """The underlying Temporal Client + + .. warning:: + This API is experimental and unstable. + """ + ... + + # Overload for no-param workflow + @overload + async def start_workflow( + self, + workflow: MethodAsyncNoParam[SelfType, ReturnType], + *, + id: str, + task_queue: str | None = None, + execution_timeout: timedelta | None = None, + run_timeout: timedelta | None = None, + task_timeout: timedelta | None = None, + id_reuse_policy: temporalio.common.WorkflowIDReusePolicy = temporalio.common.WorkflowIDReusePolicy.ALLOW_DUPLICATE, + id_conflict_policy: temporalio.common.WorkflowIDConflictPolicy = temporalio.common.WorkflowIDConflictPolicy.UNSPECIFIED, + retry_policy: temporalio.common.RetryPolicy | None = None, + cron_schedule: str = "", + memo: Mapping[str, Any] | None = None, + search_attributes: None + | ( + temporalio.common.TypedSearchAttributes | temporalio.common.SearchAttributes + ) = None, + static_summary: str | None = None, + static_details: str | None = None, + start_delay: timedelta | None = None, + start_signal: str | None = None, + start_signal_args: Sequence[Any] = [], + rpc_metadata: Mapping[str, str | bytes] = {}, + rpc_timeout: timedelta | None = None, + request_eager_start: bool = False, + priority: temporalio.common.Priority = temporalio.common.Priority.default, + versioning_override: temporalio.common.VersioningOverride | None = None, + ) -> TemporalOperationResult[ReturnType]: ... + + # Overload for single-param workflow + @overload + async def start_workflow( + self, + workflow: MethodAsyncSingleParam[SelfType, ParamType, ReturnType], + arg: ParamType, + *, + id: str, + task_queue: str | None = None, + execution_timeout: timedelta | None = None, + run_timeout: timedelta | None = None, + task_timeout: timedelta | None = None, + id_reuse_policy: temporalio.common.WorkflowIDReusePolicy = temporalio.common.WorkflowIDReusePolicy.ALLOW_DUPLICATE, + id_conflict_policy: temporalio.common.WorkflowIDConflictPolicy = temporalio.common.WorkflowIDConflictPolicy.UNSPECIFIED, + retry_policy: temporalio.common.RetryPolicy | None = None, + cron_schedule: str = "", + memo: Mapping[str, Any] | None = None, + search_attributes: None + | ( + temporalio.common.TypedSearchAttributes | temporalio.common.SearchAttributes + ) = None, + static_summary: str | None = None, + static_details: str | None = None, + start_delay: timedelta | None = None, + start_signal: str | None = None, + start_signal_args: Sequence[Any] = [], + rpc_metadata: Mapping[str, str | bytes] = {}, + rpc_timeout: timedelta | None = None, + request_eager_start: bool = False, + priority: temporalio.common.Priority = temporalio.common.Priority.default, + versioning_override: temporalio.common.VersioningOverride | None = None, + ) -> TemporalOperationResult[ReturnType]: ... + + # Overload for multi-param workflow + @overload + async def start_workflow( + self, + workflow: Callable[ + Concatenate[SelfType, MultiParamSpec], Awaitable[ReturnType] + ], + *, + args: Sequence[Any], + id: str, + task_queue: str | None = None, + execution_timeout: timedelta | None = None, + run_timeout: timedelta | None = None, + task_timeout: timedelta | None = None, + id_reuse_policy: temporalio.common.WorkflowIDReusePolicy = temporalio.common.WorkflowIDReusePolicy.ALLOW_DUPLICATE, + id_conflict_policy: temporalio.common.WorkflowIDConflictPolicy = temporalio.common.WorkflowIDConflictPolicy.UNSPECIFIED, + retry_policy: temporalio.common.RetryPolicy | None = None, + cron_schedule: str = "", + memo: Mapping[str, Any] | None = None, + search_attributes: None + | ( + temporalio.common.TypedSearchAttributes | temporalio.common.SearchAttributes + ) = None, + static_summary: str | None = None, + static_details: str | None = None, + start_delay: timedelta | None = None, + start_signal: str | None = None, + start_signal_args: Sequence[Any] = [], + rpc_metadata: Mapping[str, str | bytes] = {}, + rpc_timeout: timedelta | None = None, + request_eager_start: bool = False, + priority: temporalio.common.Priority = temporalio.common.Priority.default, + versioning_override: temporalio.common.VersioningOverride | None = None, + ) -> TemporalOperationResult[ReturnType]: ... + + # Overload for string-name workflow + @overload + async def start_workflow( + self, + workflow: str, + arg: Any = temporalio.common._arg_unset, + *, + args: Sequence[Any] = [], + id: str, + task_queue: str | None = None, + result_type: type[ReturnType] | None = None, + execution_timeout: timedelta | None = None, + run_timeout: timedelta | None = None, + task_timeout: timedelta | None = None, + id_reuse_policy: temporalio.common.WorkflowIDReusePolicy = temporalio.common.WorkflowIDReusePolicy.ALLOW_DUPLICATE, + id_conflict_policy: temporalio.common.WorkflowIDConflictPolicy = temporalio.common.WorkflowIDConflictPolicy.UNSPECIFIED, + retry_policy: temporalio.common.RetryPolicy | None = None, + cron_schedule: str = "", + memo: Mapping[str, Any] | None = None, + search_attributes: None + | ( + temporalio.common.TypedSearchAttributes | temporalio.common.SearchAttributes + ) = None, + static_summary: str | None = None, + static_details: str | None = None, + start_delay: timedelta | None = None, + start_signal: str | None = None, + start_signal_args: Sequence[Any] = [], + rpc_metadata: Mapping[str, str | bytes] = {}, + rpc_timeout: timedelta | None = None, + request_eager_start: bool = False, + priority: temporalio.common.Priority = temporalio.common.Priority.default, + versioning_override: temporalio.common.VersioningOverride | None = None, + ) -> TemporalOperationResult[ReturnType]: ... + + @abstractmethod + async def start_workflow( + self, + workflow: str | Callable[..., Awaitable[ReturnType]], + arg: Any = temporalio.common._arg_unset, + *, + args: Sequence[Any] = [], + id: str, + task_queue: str | None = None, + result_type: type | None = None, + execution_timeout: timedelta | None = None, + run_timeout: timedelta | None = None, + task_timeout: timedelta | None = None, + id_reuse_policy: temporalio.common.WorkflowIDReusePolicy = temporalio.common.WorkflowIDReusePolicy.ALLOW_DUPLICATE, + id_conflict_policy: temporalio.common.WorkflowIDConflictPolicy = temporalio.common.WorkflowIDConflictPolicy.UNSPECIFIED, + retry_policy: temporalio.common.RetryPolicy | None = None, + cron_schedule: str = "", + memo: Mapping[str, Any] | None = None, + search_attributes: None + | ( + temporalio.common.TypedSearchAttributes | temporalio.common.SearchAttributes + ) = None, + static_summary: str | None = None, + static_details: str | None = None, + start_delay: timedelta | None = None, + start_signal: str | None = None, + start_signal_args: Sequence[Any] = [], + rpc_metadata: Mapping[str, str | bytes] = {}, + rpc_timeout: timedelta | None = None, + request_eager_start: bool = False, + priority: temporalio.common.Priority = temporalio.common.Priority.default, + versioning_override: temporalio.common.VersioningOverride | None = None, + ) -> TemporalOperationResult[ReturnType]: + """Start a workflow as the backing asynchronous Nexus operation. + + .. warning:: + This API is experimental and unstable. + """ + ... + + +class _TemporalNexusClient(TemporalNexusClient): # pyright: ignore[reportUnusedClass] + """Nexus-aware wrapper around a Temporal Client. + + .. warning:: + This API is experimental and unstable. + """ + + def __init__(self) -> None: + """Initialize the client wrapper from the active Nexus operation context.""" + self._temporal_context = _TemporalStartOperationContext.get() + self._started_async = False + + @property + def client(self) -> temporalio.client.Client: + """Return the Temporal client for the active Nexus operation.""" + return self._temporal_context.client + + @contextmanager + def _reserve_async_start(self) -> Iterator[None]: + if self._started_async: + raise HandlerError( + "Only one async operation can be started per operation handler invocation. Use TemporalNexusClient.client for additional workflow interactions", + type=HandlerErrorType.BAD_REQUEST, + ) + + # Reserve the started flag before sending to prevent concurrent starts + self._started_async = True + try: + yield + except BaseException: + self._started_async = False + raise + + async def start_workflow( + self, + workflow: str | Callable[..., Awaitable[ReturnType]], + arg: Any = temporalio.common._arg_unset, + *, + args: Sequence[Any] = [], + id: str, + task_queue: str | None = None, + result_type: type | None = None, + execution_timeout: timedelta | None = None, + run_timeout: timedelta | None = None, + task_timeout: timedelta | None = None, + id_reuse_policy: temporalio.common.WorkflowIDReusePolicy = temporalio.common.WorkflowIDReusePolicy.ALLOW_DUPLICATE, + id_conflict_policy: temporalio.common.WorkflowIDConflictPolicy = temporalio.common.WorkflowIDConflictPolicy.UNSPECIFIED, + retry_policy: temporalio.common.RetryPolicy | None = None, + cron_schedule: str = "", + memo: Mapping[str, Any] | None = None, + search_attributes: None + | ( + temporalio.common.TypedSearchAttributes | temporalio.common.SearchAttributes + ) = None, + static_summary: str | None = None, + static_details: str | None = None, + start_delay: timedelta | None = None, + start_signal: str | None = None, + start_signal_args: Sequence[Any] = [], + rpc_metadata: Mapping[str, str | bytes] = {}, + rpc_timeout: timedelta | None = None, + request_eager_start: bool = False, + priority: temporalio.common.Priority = temporalio.common.Priority.default, + versioning_override: temporalio.common.VersioningOverride | None = None, + ) -> TemporalOperationResult[ReturnType]: + """Start a workflow as the backing asynchronous Nexus operation.""" + with self._reserve_async_start(): + wf_handle = await _start_nexus_backing_workflow( + temporal_context=self._temporal_context, + workflow=workflow, + arg=arg, + args=args, + id=id, + task_queue=task_queue, + result_type=result_type, + execution_timeout=execution_timeout, + run_timeout=run_timeout, + task_timeout=task_timeout, + id_reuse_policy=id_reuse_policy, + id_conflict_policy=id_conflict_policy, + retry_policy=retry_policy, + cron_schedule=cron_schedule, + memo=memo, + search_attributes=search_attributes, + static_summary=static_summary, + static_details=static_details, + start_delay=start_delay, + start_signal=start_signal, + start_signal_args=start_signal_args, + rpc_metadata=rpc_metadata, + rpc_timeout=rpc_timeout, + request_eager_start=request_eager_start, + priority=priority, + versioning_override=versioning_override, + ) + + return TemporalOperationResult.async_token(wf_handle.to_token()) diff --git a/temporalio/nexus/_token.py b/temporalio/nexus/_token.py index 0a3d27375..d52b54180 100644 --- a/temporalio/nexus/_token.py +++ b/temporalio/nexus/_token.py @@ -3,17 +3,111 @@ import base64 import json from dataclasses import dataclass -from typing import TYPE_CHECKING, Any, Generic, Literal +from enum import IntEnum +from typing import TYPE_CHECKING, Any, Generic from nexusrpc import OutputT +from typing_extensions import Self + + +class OperationTokenType(IntEnum): + """Type discriminator for Nexus operation tokens.""" + + WORKFLOW = 1 -OperationTokenType = Literal[1] -OPERATION_TOKEN_TYPE_WORKFLOW: OperationTokenType = 1 if TYPE_CHECKING: import temporalio.client +@dataclass(frozen=True, kw_only=True) +class OperationToken: + """Serializable token identifying a Nexus operation target.""" + + version: int | None = None + type: OperationTokenType + namespace: str + workflow_id: str + + def encode(self) -> str: + """Convert handle to a base64url-encoded token string.""" + token_details: dict[str, Any] = { + "t": self.type, + "ns": self.namespace, + "wid": self.workflow_id, + } + if self.version is not None: + token_details["v"] = self.version + return _base64url_encode_no_padding( + json.dumps( + token_details, + separators=(",", ":"), + ).encode("utf-8") + ) + + @classmethod + def decode(cls, token: str) -> Self: + """Decodes and validates a token from its base64url-encoded string representation.""" + if not token: + raise TypeError("invalid token: token is empty") + try: + decoded_bytes = _base64url_decode_no_padding(token) + except Exception as err: + raise TypeError("failed to decode token as base64url") from err + try: + token_details = json.loads(decoded_bytes.decode("utf-8")) + except Exception as err: + raise TypeError("failed to unmarshal operation token") from err + + if not isinstance(token_details, dict): + raise TypeError(f"invalid token: expected dict, got {type(token_details)}") + + raw_token_type = token_details.get("t") + if not isinstance(raw_token_type, int): + raise TypeError( + f"invalid token: expected token type to be an int, got {type(raw_token_type)}" + ) + + try: + token_type = OperationTokenType(raw_token_type) + except ValueError as err: + raise TypeError( + f"invalid token: unknown token type, got {raw_token_type}.", + f"Valid values: {', '.join([f'{t.value} ({t.name})' for t in OperationTokenType])}", + ) from err + + version = token_details.get("v") + if version is not None and not isinstance(version, int): + raise TypeError( + f"invalid token: expected version to be an int or null, got {type(version)}" + ) + + workflow_id = token_details.get("wid") + if not isinstance(workflow_id, str): + raise TypeError( + f"invalid token: expected workflow id to be a string, got {type(workflow_id)}" + ) + + if token_type == OperationTokenType.WORKFLOW and not workflow_id: + raise TypeError( + "invalid token: expected non-empty workflow id for token type `WORKFLOW`" + ) + + namespace = token_details.get("ns") + if not isinstance(namespace, str): + # Allow empty string for ns, but it must be present and a string + raise TypeError( + f"invalid token: expected namespace to be a string, got {type(namespace)}" + ) + + return cls( + type=OperationTokenType(token_type), + namespace=namespace, + workflow_id=workflow_id, + version=version, + ) + + @dataclass(frozen=True) class WorkflowHandle(Generic[OutputT]): """A handle to a workflow that is backing a Nexus operation. @@ -59,65 +153,30 @@ def _unsafe_from_client_workflow_handle( def to_token(self) -> str: """Convert handle to a base64url-encoded token string.""" - return _base64url_encode_no_padding( - json.dumps( - { - "t": OPERATION_TOKEN_TYPE_WORKFLOW, - "ns": self.namespace, - "wid": self.workflow_id, - }, - separators=(",", ":"), - ).encode("utf-8") - ) + return OperationToken( + type=OperationTokenType.WORKFLOW, + namespace=self.namespace, + workflow_id=self.workflow_id, + ).encode() @classmethod def from_token(cls, token: str) -> WorkflowHandle[OutputT]: """Decodes and validates a token from its base64url-encoded string representation.""" - if not token: - raise TypeError("invalid workflow token: token is empty") - try: - decoded_bytes = _base64url_decode_no_padding(token) - except Exception as err: - raise TypeError("failed to decode token as base64url") from err - try: - workflow_operation_token = json.loads(decoded_bytes.decode("utf-8")) - except Exception as err: - raise TypeError("failed to unmarshal workflow operation token") from err - - if not isinstance(workflow_operation_token, dict): + op_token = OperationToken.decode(token) + if op_token.type != OperationTokenType.WORKFLOW: raise TypeError( - f"invalid workflow token: expected dict, got {type(workflow_operation_token)}" + f"invalid workflow token type: {op_token.type}, expected: {OperationTokenType.WORKFLOW}" ) - token_type = workflow_operation_token.get("t") - if token_type != OPERATION_TOKEN_TYPE_WORKFLOW: - raise TypeError( - f"invalid workflow token type: {token_type}, expected: {OPERATION_TOKEN_TYPE_WORKFLOW}" - ) - - version = workflow_operation_token.get("v") - if version is not None and version != 0: + if op_token.version is not None and op_token.version != 0: raise TypeError( "invalid workflow token: 'v' field, if present, must be 0 or null/absent" ) - workflow_id = workflow_operation_token.get("wid") - if not workflow_id or not isinstance(workflow_id, str): - raise TypeError( - "invalid workflow token: missing, empty, or non-string workflow ID (wid)" - ) - - namespace = workflow_operation_token.get("ns") - if namespace is None or not isinstance(namespace, str): - # Allow empty string for ns, but it must be present and a string - raise TypeError( - "invalid workflow token: missing or non-string namespace (ns)" - ) - return cls( - namespace=namespace, - workflow_id=workflow_id, - version=version, + namespace=op_token.namespace, + workflow_id=op_token.workflow_id, + version=op_token.version, ) diff --git a/temporalio/nexus/_util.py b/temporalio/nexus/_util.py index 48d3ad644..66d8c069c 100644 --- a/temporalio/nexus/_util.py +++ b/temporalio/nexus/_util.py @@ -7,7 +7,6 @@ from collections.abc import Awaitable, Callable from typing import ( Any, - TypeVar, ) import nexusrpc @@ -16,18 +15,24 @@ OutputT, ) -from temporalio.nexus._operation_context import WorkflowRunOperationContext +from temporalio.nexus._operation_context import ( + TemporalNexusStartOperationContext, + WorkflowRunOperationContext, +) +from temporalio.nexus._temporal_client import ( + TemporalNexusClient, + TemporalOperationResult, +) +from temporalio.types import NexusServiceType from ._token import ( WorkflowHandle as WorkflowHandle, ) -ServiceHandlerT = TypeVar("ServiceHandlerT") - def get_workflow_run_start_method_input_and_output_type_annotations( start: Callable[ - [ServiceHandlerT, WorkflowRunOperationContext, InputT], + [NexusServiceType, WorkflowRunOperationContext, InputT], Awaitable[WorkflowHandle[OutputT]], ], ) -> tuple[ @@ -39,13 +44,62 @@ def get_workflow_run_start_method_input_and_output_type_annotations( ``start`` must be a type-annotated start method that returns a :py:class:`temporalio.nexus.WorkflowHandle`. """ - input_type, output_type = _get_start_method_input_and_output_type_annotations(start) + return _get_wrapped_start_method_input_and_output_type_annotations( + start, + expected_param_types=(WorkflowRunOperationContext,), + expected_return_origin=WorkflowHandle, + ) + + +def get_temporal_operation_start_method_input_and_output_type_annotations( + start: Callable[ + [ + NexusServiceType, + TemporalNexusStartOperationContext, + TemporalNexusClient, + InputT, + ], + Awaitable[TemporalOperationResult[OutputT]], + ], +) -> tuple[ + type[InputT] | None, + type[OutputT] | None, +]: + """Return operation input and output types. + + ``start`` must be a type-annotated start method that returns a + :py:class:`temporalio.nexus.TemporalOperationResult`. + """ + return _get_wrapped_start_method_input_and_output_type_annotations( + start, + expected_param_types=( + TemporalNexusStartOperationContext, + TemporalNexusClient, + ), + expected_return_origin=TemporalOperationResult, + ) + + +def _get_wrapped_start_method_input_and_output_type_annotations( + start: Callable[..., Any], + *, + expected_param_types: tuple[type[Any], ...], + expected_return_origin: type[Any], +) -> tuple[ + type[Any] | None, + type[Any] | None, +]: + input_type, output_type = _get_start_method_input_and_output_type_annotations( + start, + expected_param_types=expected_param_types, + ) origin_type = typing.get_origin(output_type) if not origin_type: output_type = None - elif not issubclass(origin_type, WorkflowHandle): + elif not issubclass(origin_type, expected_return_origin): warnings.warn( - f"Expected return type of {start.__name__} to be a subclass of WorkflowHandle, " + f"Expected return type of {start.__name__} to be a subclass of " + f"{expected_return_origin.__name__}, " f"but is {output_type}" ) output_type = None @@ -65,13 +119,12 @@ def get_workflow_run_start_method_input_and_output_type_annotations( def _get_start_method_input_and_output_type_annotations( - start: Callable[ - [ServiceHandlerT, WorkflowRunOperationContext, InputT], - Awaitable[WorkflowHandle[OutputT]], - ], + start: Callable[..., Any], + *, + expected_param_types: tuple[type[Any], ...], ) -> tuple[ - type[InputT] | None, - type[OutputT] | None, + type[Any] | None, + type[Any] | None, ]: try: type_annotations = typing.get_type_hints(start) @@ -81,23 +134,28 @@ def _get_start_method_input_and_output_type_annotations( ) return None, None output_type = type_annotations.pop("return", None) + expected_parameter_count = len(expected_param_types) + 1 - if len(type_annotations) != 2: + if len(type_annotations) != expected_parameter_count: suffix = f": {type_annotations}" if type_annotations else "" warnings.warn( - f"Expected decorated start method {start} to have exactly 2 " - f"type-annotated parameters (ctx and input), but it has {len(type_annotations)}" + f"Expected decorated start method {start} to have exactly " + f"{expected_parameter_count} type-annotated parameters, " + f"but it has {len(type_annotations)}" f"{suffix}." ) input_type = None else: - ctx_type, input_type = type_annotations.values() - if not issubclass(ctx_type, WorkflowRunOperationContext): - warnings.warn( - f"Expected first parameter of {start} to be an instance of " - f"WorkflowRunOperationContext, but is {ctx_type}." - ) - input_type = None + *param_types, input_type = type_annotations.values() + for index, (param_type, expected_param_type) in enumerate( + zip(param_types, expected_param_types), start=1 + ): + if not issubclass(expected_param_type, param_type): + warnings.warn( + f"Expected parameter {index} of {start} to be an instance of " + f"{expected_param_type.__name__}, but is {param_type}." + ) + input_type = None return input_type, output_type diff --git a/temporalio/workflow/__init__.py b/temporalio/workflow/__init__.py index f8002366b..ec74299c2 100644 --- a/temporalio/workflow/__init__.py +++ b/temporalio/workflow/__init__.py @@ -2,8 +2,6 @@ from __future__ import annotations -from temporalio.nexus._util import ServiceHandlerT - from ..types import ( AnyType, CallableAsyncNoParam, @@ -293,7 +291,6 @@ "_sandbox_unrestricted", # Re-export Temporal-owned names that old temporalio/workflow.py imported # at module scope so explicit imports from temporalio.workflow keep working. - "ServiceHandlerT", "AnyType", "CallableAsyncNoParam", "CallableAsyncSingleParam", diff --git a/temporalio/workflow/_nexus.py b/temporalio/workflow/_nexus.py index 0b80e6d91..b8c8e88a1 100644 --- a/temporalio/workflow/_nexus.py +++ b/temporalio/workflow/_nexus.py @@ -12,7 +12,6 @@ import temporalio.bridge.proto.nexus import temporalio.nexus -from temporalio.nexus._util import ServiceHandlerT from temporalio.types import NexusServiceType from ._context import _Runtime @@ -138,7 +137,7 @@ async def start_operation( async def start_operation( self, operation: Callable[ - [ServiceHandlerT, temporalio.nexus.WorkflowRunOperationContext, InputT], + [NexusServiceType, temporalio.nexus.WorkflowRunOperationContext, InputT], Awaitable[temporalio.nexus.WorkflowHandle[OutputT]], ], input: InputT, @@ -158,7 +157,7 @@ async def start_operation( async def start_operation( self, operation: Callable[ - [ServiceHandlerT, nexusrpc.handler.StartOperationContext, InputT], + [NexusServiceType, nexusrpc.handler.StartOperationContext, InputT], Awaitable[OutputT], ], input: InputT, @@ -178,7 +177,7 @@ async def start_operation( async def start_operation( self, operation: Callable[ - [ServiceHandlerT, nexusrpc.handler.StartOperationContext, InputT], + [NexusServiceType, nexusrpc.handler.StartOperationContext, InputT], OutputT, ], input: InputT, @@ -198,7 +197,32 @@ async def start_operation( async def start_operation( self, operation: Callable[ - [ServiceHandlerT], nexusrpc.handler.OperationHandler[InputT, OutputT] + [NexusServiceType], nexusrpc.handler.OperationHandler[InputT, OutputT] + ], + input: InputT, + *, + output_type: type[OutputT] | None = None, + schedule_to_close_timeout: timedelta | None = None, + schedule_to_start_timeout: timedelta | None = None, + start_to_close_timeout: timedelta | None = None, + cancellation_type: NexusOperationCancellationType = NexusOperationCancellationType.WAIT_COMPLETED, + headers: Mapping[str, str] | None = None, + summary: str | None = None, + ) -> NexusOperationHandle[OutputT]: ... + + # Overload for temporal_operation methods + @overload + @abstractmethod + async def start_operation( + self, + operation: Callable[ + [ + NexusServiceType, + temporalio.nexus.TemporalNexusStartOperationContext, + temporalio.nexus.TemporalNexusClient, + InputT, + ], + Awaitable[temporalio.nexus.TemporalOperationResult[OutputT]], ], input: InputT, *, @@ -284,7 +308,7 @@ async def execute_operation( async def execute_operation( self, operation: Callable[ - [ServiceHandlerT, temporalio.nexus.WorkflowRunOperationContext, InputT], + [NexusServiceType, temporalio.nexus.WorkflowRunOperationContext, InputT], Awaitable[temporalio.nexus.WorkflowHandle[OutputT]], ], input: InputT, @@ -358,6 +382,31 @@ async def execute_operation( summary: str | None = None, ) -> OutputT: ... + # Overload for temporal_operation methods + @overload + @abstractmethod + async def execute_operation( + self, + operation: Callable[ + [ + NexusServiceType, + temporalio.nexus.TemporalNexusStartOperationContext, + temporalio.nexus.TemporalNexusClient, + InputT, + ], + Awaitable[temporalio.nexus.TemporalOperationResult[OutputT]], + ], + input: InputT, + *, + output_type: type[OutputT] | None = None, + schedule_to_close_timeout: timedelta | None = None, + schedule_to_start_timeout: timedelta | None = None, + start_to_close_timeout: timedelta | None = None, + cancellation_type: NexusOperationCancellationType = NexusOperationCancellationType.WAIT_COMPLETED, + headers: Mapping[str, str] | None = None, + summary: str | None = None, + ) -> OutputT: ... + @abstractmethod async def execute_operation( self, diff --git a/tests/helpers/__init__.py b/tests/helpers/__init__.py index f467f8aa3..fe37296e9 100644 --- a/tests/helpers/__init__.py +++ b/tests/helpers/__init__.py @@ -254,6 +254,44 @@ async def check() -> PendingActivityInfo: return await assert_eventually(check, timeout=timeout) +async def assert_event_subsequence( + wf_handle: WorkflowHandle, + expected_events: list[EventType.ValueType], + timeout: timedelta = timedelta(seconds=5), +) -> None: + """ + Given a workflow handle and a sequence of event types, assert that the workflow's history + contains that subsequence of events in the order specified. + """ + + async def check(): + history = await wf_handle.fetch_history() + + _all_events = iter(history.events) + _expected_events = iter(expected_events) + + previous_expected_event_type_name = None + for expected_event_type in _expected_events: + expected_event_type_name = EventType.Name(expected_event_type).removeprefix( + "EVENT_TYPE_" + ) + has_expected = next( + (e for e in _all_events if e.event_type == expected_event_type), + None, + ) + if not has_expected: + if previous_expected_event_type_name is not None: + prefix = f"After {previous_expected_event_type_name}, " + else: + prefix = "" + raise AssertionError( + f"{prefix}expected {expected_event_type_name} in workflow {wf_handle.id}" + ) + previous_expected_event_type_name = expected_event_type_name + + await assert_eventually(check, timeout=timeout) + + async def get_pending_activity_info( handle: WorkflowHandle, activity_id: str, diff --git a/tests/nexus/test_handler_operation_definitions.py b/tests/nexus/test_handler_operation_definitions.py index 8a0d6262a..4a6e644b9 100644 --- a/tests/nexus/test_handler_operation_definitions.py +++ b/tests/nexus/test_handler_operation_definitions.py @@ -3,6 +3,7 @@ and input/output types. """ +import warnings from dataclasses import dataclass from typing import Any @@ -99,3 +100,101 @@ async def test_collected_operation_names( assert actual_op.name == expected_op.name assert actual_op.input_type == expected_op.input_type assert actual_op.output_type == expected_op.output_type + + +def test_unsafe_narrow_context_annotations_warn_and_drop_input_type(): + """Unsafe context annotations warn and prevent input type inference. + + Decorators construct a specific context type at runtime. If a handler annotates a + narrower or unrelated context type, the decorator cannot safely call it, so we + should warn and avoid using the handler annotation to infer operation input type. + """ + + with pytest.warns( + UserWarning, + match="Expected parameter 1 .* TemporalNexusStartOperationContext", + ): + + class MyTemporalOpCtx(nexus.TemporalNexusStartOperationContext): + def custom_method(self): + raise NotImplementedError + + class TemporalOperationHandler: + @nexus.temporal_operation # type: ignore[arg-type] + async def op( + self, + _ctx: MyTemporalOpCtx, + _client: nexus.TemporalNexusClient, + _input: Input, + ) -> nexus.TemporalOperationResult[Output]: + raise NotImplementedError + + _, temporal_op = get_operation_factory(TemporalOperationHandler.op) + assert isinstance(temporal_op, nexusrpc.Operation) + assert temporal_op.input_type is None + assert temporal_op.output_type == Output + + with pytest.warns( + UserWarning, + match="Expected parameter 1 .* WorkflowRunOperationContext", + ): + + class MyWorkflowRunOpCtx(nexus.WorkflowRunOperationContext): + def custom_method(self): + raise NotImplementedError + + class WorkflowRunOperationHandler: + @workflow_run_operation # type: ignore[arg-type] + async def op( + self, + _ctx: MyWorkflowRunOpCtx, + _input: Input, + ) -> nexus.WorkflowHandle[Output]: + raise NotImplementedError + + _, workflow_op = get_operation_factory(WorkflowRunOperationHandler.op) + assert isinstance(workflow_op, nexusrpc.Operation) + assert workflow_op.input_type is None + assert workflow_op.output_type == Output + + +def test_safe_broader_context_annotations_preserve_input_type_without_warnings(): + """Safe context annotations preserve input type inference without warnings. + + A handler can safely annotate a context parameter with the exact runtime context + type or a broader base type. These cases should keep handler-derived operation + input metadata intact. + """ + + with warnings.catch_warnings(record=True) as caught: + warnings.simplefilter("always") + + class TemporalOperationHandler: + @nexus.temporal_operation + async def op( + self, + _ctx: nexusrpc.handler.StartOperationContext, + _client: nexus.TemporalNexusClient, + _input: Input, + ) -> nexus.TemporalOperationResult[Output]: + raise NotImplementedError + + class WorkflowRunStartContextHandler: + @workflow_run_operation + async def op( + self, + _ctx: nexusrpc.handler.StartOperationContext, + _input: Input, + ) -> nexus.WorkflowHandle[Output]: + raise NotImplementedError + + assert not caught + + for method in ( + TemporalOperationHandler.op, + WorkflowRunStartContextHandler.op, + ): + _, op = get_operation_factory(method) + assert isinstance(op, nexusrpc.Operation) + assert op.input_type == Input + assert op.output_type == Output diff --git a/tests/nexus/test_nexus_client_updates.py b/tests/nexus/test_nexus_client_updates.py index 323f21f05..f63d5482c 100644 --- a/tests/nexus/test_nexus_client_updates.py +++ b/tests/nexus/test_nexus_client_updates.py @@ -62,7 +62,7 @@ async def test_nexus_client_updates_when_worker_client_changes( handler_task_queue = f"handler-{uuid.uuid4()}" # Create Nexus endpoint - endpoint_name = "test-endpoint" + endpoint_name = f"test-endpoint-{uuid.uuid4()}" await env.create_nexus_endpoint(endpoint_name, handler_task_queue) # Caller worker diff --git a/tests/nexus/test_nexus_type_errors.py b/tests/nexus/test_nexus_type_errors.py index f97aeae42..ffdb60c65 100644 --- a/tests/nexus/test_nexus_type_errors.py +++ b/tests/nexus/test_nexus_type_errors.py @@ -5,7 +5,7 @@ from dataclasses import dataclass from datetime import timedelta -from typing import Any +from typing import Any, TypeAlias from unittest.mock import Mock import nexusrpc @@ -13,6 +13,7 @@ import temporalio.nexus from temporalio import workflow from temporalio.client import Client, NexusOperationHandle +from temporalio.nexus import TemporalNexusOperationStartHandlerFunc from temporalio.service import ServiceClient @@ -26,10 +27,55 @@ class MyOutput: pass +@workflow.defn +class MyNoArgProcWorkflow: + @workflow.run + async def run(self) -> None: + pass + + +@workflow.defn +class MyOneArgProcWorkflow: + @workflow.run + async def run(self, _input: MyInput) -> None: + pass + + +@workflow.defn +class MyTwoArgProcWorkflow: + @workflow.run + async def run(self, _input: MyInput, _arg2: int) -> None: + pass + + +@workflow.defn +class MyThreeArgProcWorkflow: + @workflow.run + async def run(self, _input: MyInput, _arg2: int, _arg3: int) -> None: + pass + + +@workflow.defn +class MyFourArgProcWorkflow: + @workflow.run + async def run(self, _input: MyInput, _arg2: int, _arg3: int, _arg4: int) -> None: + pass + + +@workflow.defn +class MyFiveArgProcWorkflow: + @workflow.run + async def run( + self, _input: MyInput, _arg2: int, _arg3: int, _arg4: int, _arg5: int + ) -> None: + pass + + @nexusrpc.service class MyService: my_sync_operation: nexusrpc.Operation[MyInput, MyOutput] my_workflow_run_operation: nexusrpc.Operation[MyInput, MyOutput] + my_temporal_operation: nexusrpc.Operation[int, None] @nexusrpc.service @@ -51,6 +97,71 @@ async def my_workflow_run_operation( ) -> temporalio.nexus.WorkflowHandle[MyOutput]: raise NotImplementedError + @temporalio.nexus.temporal_operation + async def my_temporal_operation( + self, + _ctx: temporalio.nexus.TemporalNexusStartOperationContext, + client: temporalio.nexus.TemporalNexusClient, + input: int, + ) -> temporalio.nexus.TemporalOperationResult[None]: + """ + Typed proc workflow starts from a generic Temporal Nexus operation handler + infer TemporalOperationResult[None] for 0 to 5 workflow parameters. + """ + if input == 0: + result_0: temporalio.nexus.TemporalOperationResult[ + None + ] = await client.start_workflow(MyNoArgProcWorkflow.run, id="proc-0") + return result_0 + if input == 1: + result_1: temporalio.nexus.TemporalOperationResult[ + None + ] = await client.start_workflow( + MyOneArgProcWorkflow.run, MyInput(), id="proc-1" + ) + return result_1 + if input == 2: + result_2: temporalio.nexus.TemporalOperationResult[ + None + ] = await client.start_workflow( + MyTwoArgProcWorkflow.run, args=[MyInput(), 2], id="proc-2" + ) + return result_2 + if input == 3: + result_3: temporalio.nexus.TemporalOperationResult[ + None + ] = await client.start_workflow( + MyThreeArgProcWorkflow.run, + args=[MyInput(), 2, 3], + id="proc-3", + ) + return result_3 + if input == 4: + result_4: temporalio.nexus.TemporalOperationResult[ + None + ] = await client.start_workflow( + MyFourArgProcWorkflow.run, + args=[MyInput(), 2, 3, 4], + id="proc-4", + ) + return result_4 + if input == 5: + result_5: temporalio.nexus.TemporalOperationResult[ + None + ] = await client.start_workflow( + MyFiveArgProcWorkflow.run, + args=[MyInput(), 2, 3, 4, 5], + id="proc-5", + ) + return result_5 + # assert-type-error-pyright: 'No overloads for "start_workflow" match' + return await client.start_workflow( # type: ignore + MyOneArgProcWorkflow.run, + # assert-type-error-pyright: 'Argument of type .+ cannot be assigned to parameter' + "wrong-input-type", # type: ignore + id="proc-wrong-input", + ) + @nexusrpc.handler.service_handler(service=MyService) class MyServiceHandler2: @@ -66,6 +177,15 @@ async def my_workflow_run_operation( ) -> temporalio.nexus.WorkflowHandle[MyOutput]: raise NotImplementedError + @temporalio.nexus.temporal_operation + async def my_temporal_operation( + self, + _ctx: temporalio.nexus.TemporalNexusStartOperationContext, + _client: temporalio.nexus.TemporalNexusClient, + _input: int, + ) -> temporalio.nexus.TemporalOperationResult[None]: + raise NotImplementedError + @nexusrpc.handler.service_handler class MyServiceHandlerWithoutServiceDefinition: @@ -81,6 +201,72 @@ async def my_workflow_run_operation( ) -> temporalio.nexus.WorkflowHandle[MyOutput]: raise NotImplementedError + @temporalio.nexus.temporal_operation + async def my_temporal_operation( + self, + _ctx: temporalio.nexus.TemporalNexusStartOperationContext, + _client: temporalio.nexus.TemporalNexusClient, + _input: int, + ) -> temporalio.nexus.TemporalOperationResult[None]: + raise NotImplementedError + + +_handler: TemporalNexusOperationStartHandlerFunc[ + MyServiceHandler, + int, + None, +] = MyServiceHandler.my_temporal_operation + +_BadHandler: TypeAlias = temporalio.nexus.TemporalNexusOperationStartHandlerFunc[ + MyServiceHandler, + str, + None, +] + +_bad_handler: TemporalNexusOperationStartHandlerFunc[ + MyServiceHandler, + str, + None, + # assert-type-error-pyright: 'is not assignable to declared type' +] = MyServiceHandler.my_temporal_operation # type: ignore + + +class MyUnsafeContextAnnotationServiceHandler: + # A temporal operation receives TemporalStartOperationContext at runtime, so + # requiring an arbitrary user subclass is not safe. + class MyCustomTemporalStartOperationContext( + temporalio.nexus.TemporalNexusStartOperationContext + ): + def custom_state(self) -> str: + raise NotImplementedError + + # assert-type-error-pyright: 'cannot be assigned to parameter "start".+temporal_operation' + @temporalio.nexus.temporal_operation # type: ignore + async def my_temporal_operation_with_workflow_run_context( + self, + _ctx: MyCustomTemporalStartOperationContext, + _client: temporalio.nexus.TemporalNexusClient, + _input: int, + ) -> temporalio.nexus.TemporalOperationResult[None]: + raise NotImplementedError + + # A workflow run operation receives WorkflowRunOperationContext at runtime, + # so requiring an arbitrary user subclass is not safe. + class MyCustomWorkflowRunOperationContext( + temporalio.nexus.WorkflowRunOperationContext + ): + def custom_state(self) -> str: + raise NotImplementedError + + # assert-type-error-pyright: 'cannot be assigned to parameter "start".+workflow_run_operation' + @temporalio.nexus.workflow_run_operation # type: ignore + async def my_workflow_run_operation_with_custom_context( + self, + _ctx: MyCustomWorkflowRunOperationContext, + _input: MyInput, + ) -> temporalio.nexus.WorkflowHandle[MyOutput]: + raise NotImplementedError + @workflow.defn class MyWorkflow1: @@ -116,6 +302,15 @@ async def test_invoke_by_operation_definition_happy_path(self) -> None: ) _output_2_1: MyOutput = await _handle_2 + # temporal operation + _output_3: None = await nexus_client.execute_operation( # type: ignore + MyService.my_temporal_operation, 0 + ) + _handle_3: workflow.NexusOperationHandle[ + None + ] = await nexus_client.start_operation(MyService.my_temporal_operation, 0) + _output_3_1: None = await _handle_3 # type: ignore + @workflow.defn class MyWorkflow2: @@ -153,6 +348,17 @@ async def test_invoke_by_operation_handler_happy_path(self) -> None: ) _output_2_1: MyOutput = await _handle_2 + # temporal operation + _output_3: None = await nexus_client.execute_operation( # type: ignore + MyServiceHandler.my_temporal_operation, 0 + ) + _handle_3: workflow.NexusOperationHandle[ + None + ] = await nexus_client.start_operation( + MyServiceHandler.my_temporal_operation, 0 + ) + _output_3_1: None = await _handle_3 # type: ignore + @workflow.defn class MyWorkflow3: @@ -172,6 +378,12 @@ async def test_invoke_by_operation_definition_wrong_input_type(self) -> None: # assert-type-error-pyright: 'Argument of type .+ cannot be assigned to parameter "input"' "wrong-input-type", # type: ignore ) + # assert-type-error-pyright: 'No overloads for "execute_operation" match' + await nexus_client.execute_operation( # type: ignore + MyService.my_temporal_operation, + # assert-type-error-pyright: 'Argument of type .+ cannot be assigned to parameter "input"' + "wrong-input-type", # type: ignore + ) @workflow.defn @@ -192,6 +404,12 @@ async def test_invoke_by_operation_handler_wrong_input_type(self) -> None: # assert-type-error-pyright: 'Argument of type .+ cannot be assigned to parameter "input"' "wrong-input-type", # type: ignore ) + # assert-type-error-pyright: 'No overloads for "execute_operation" match' + await nexus_client.execute_operation( # type: ignore + MyServiceHandler.my_temporal_operation, # type: ignore[arg-type] + # assert-type-error-pyright: 'Argument of type .+ cannot be assigned to parameter "input"' + "wrong-input-type", # type: ignore + ) @workflow.defn @@ -216,8 +434,14 @@ async def test_invoke_by_operation_handler_method_on_wrong_service(self) -> None MyInput(), ) + # assert-type-error-pyright: 'No overloads for "execute_operation" match' + await nexus_client.execute_operation( # type: ignore + # assert-type-error-pyright: 'Argument of type .+ cannot be assigned to parameter "operation"' + MyServiceHandler2.my_temporal_operation, # type: ignore + 0, + ) + -# ── Standalone Nexus Operation type tests ── async def standalone_operation_type_tests(): client = Client(service_client=Mock(spec=ServiceClient)) nexus_client = client.create_nexus_client( @@ -228,6 +452,10 @@ async def standalone_operation_type_tests(): MyNoInputService, endpoint="fake-endpoint", ) + handler_nexus_client = client.create_nexus_client( + MyServiceHandler, + endpoint="fake-endpoint", + ) # execute with an operation definition infers output type _op_defn_output: MyOutput = await nexus_client.execute_operation( @@ -252,6 +480,20 @@ async def standalone_operation_type_tests(): "my_sync_operation", MyInput(), id="op-1", result_type=MyOutput ) + # execute with workflow run handler infers output type + _workflow_run_output: MyOutput = await handler_nexus_client.execute_operation( + MyServiceHandler.my_workflow_run_operation, + MyInput(), + id="op-1", + ) + + # execute with temporal operation handler infers output type + _temporal_output: None = await handler_nexus_client.execute_operation( # type: ignore[func-returns-value] + MyServiceHandler.my_temporal_operation, + 0, + id="op-1", + ) + # omitting arg for string operation names is not supported # assert-type-error-pyright: 'No overloads for "execute_operation" match' await nexus_client.execute_operation( # type: ignore @@ -356,6 +598,58 @@ async def standalone_operation_type_tests(): await _str_op_result_type_handle.result() ) + # starting with workflow run handler infers output type on the handle + # and result from the handle + _workflow_run_handle: NexusOperationHandle[ + MyOutput + ] = await handler_nexus_client.start_operation( + MyServiceHandler.my_workflow_run_operation, + MyInput(), + id="op-1", + ) + + # starting with temporal operation handler infers output type on the handle + # and result from the handle + _workflow_run_handle_output: MyOutput = await _workflow_run_handle.result() + _temporal_handle: NexusOperationHandle[ + None + ] = await handler_nexus_client.start_operation( + MyServiceHandler.my_temporal_operation, + 0, + id="op-1", + ) + _temporal_handle_output: None = await _temporal_handle.result() # type: ignore[func-returns-value] + + # workflow run and temporal operation handlers reject wrong input types + # assert-type-error-pyright: 'No overloads for "execute_operation" match' + await handler_nexus_client.execute_operation( # type: ignore + MyServiceHandler.my_workflow_run_operation, # type: ignore[arg-type] + # assert-type-error-pyright: 'Argument of type .+ cannot be assigned to parameter "arg"' + "wrong-input-type", # type: ignore + id="op-1", + ) + # assert-type-error-pyright: 'No overloads for "start_operation" match' + await handler_nexus_client.start_operation( # type: ignore + MyServiceHandler.my_workflow_run_operation, # type: ignore[arg-type] + # assert-type-error-pyright: 'Argument of type .+ cannot be assigned to parameter "arg"' + "wrong-input-type", # type: ignore + id="op-1", + ) + # assert-type-error-pyright: 'No overloads for "execute_operation" match' + await handler_nexus_client.execute_operation( # type: ignore + MyServiceHandler.my_temporal_operation, # type: ignore[arg-type] + # assert-type-error-pyright: 'Argument of type .+ cannot be assigned to parameter "arg"' + "wrong-input-type", # type: ignore + id="op-1", + ) + # assert-type-error-pyright: 'No overloads for "start_operation" match' + await handler_nexus_client.start_operation( # type: ignore + MyServiceHandler.my_temporal_operation, # type: ignore[arg-type] + # assert-type-error-pyright: 'Argument of type .+ cannot be assigned to parameter "arg"' + "wrong-input-type", # type: ignore + id="op-1", + ) + # getting a handle with a string produces a handle to Any _str_op_handle: NexusOperationHandle[Any] = client.get_nexus_operation_handle( "op-1" @@ -366,7 +660,7 @@ async def standalone_operation_type_tests(): client.get_nexus_operation_handle("op-1", result_type=MyOutput) ) - # getting a handle with an operation defintion produces a handle of the operation + # getting a handle with an operation definition produces a handle of the operation # output type _op_defn_get_handle: NexusOperationHandle[MyOutput] = ( client.get_nexus_operation_handle("op-1", operation=MyService.my_sync_operation) diff --git a/tests/nexus/test_operation_token.py b/tests/nexus/test_operation_token.py new file mode 100644 index 000000000..385f4f872 --- /dev/null +++ b/tests/nexus/test_operation_token.py @@ -0,0 +1,158 @@ +import base64 +import json +from typing import Any + +import pytest + +from temporalio.nexus._token import ( + OperationToken, + OperationTokenType, + WorkflowHandle, +) + + +def _encode_json_token(value: Any) -> str: + return _encode_bytes(json.dumps(value, separators=(",", ":")).encode("utf-8")) + + +def _encode_bytes(value: bytes) -> str: + return base64.urlsafe_b64encode(value).decode("utf-8").rstrip("=") + + +def test_operation_token_encode_decode_round_trip(): + token = OperationToken( + type=OperationTokenType.WORKFLOW, + namespace="default", + workflow_id="workflow-id", + version=0, + ).encode() + + assert "=" not in token + assert OperationToken.decode(token) == OperationToken( + type=OperationTokenType.WORKFLOW, + namespace="default", + workflow_id="workflow-id", + version=0, + ) + + +def test_workflow_handle_to_from_token_round_trip(): + handle = WorkflowHandle[str](namespace="default", workflow_id="workflow-id") + + assert WorkflowHandle[str].from_token(handle.to_token()) == handle + + +@pytest.mark.parametrize( + ("token", "expected"), + [ + ( + _encode_json_token({"t": 1, "ns": "default", "wid": "workflow-id"}), + OperationToken( + type=OperationTokenType.WORKFLOW, + namespace="default", + workflow_id="workflow-id", + ), + ), + ( + _encode_json_token({"t": 1, "ns": "", "wid": "workflow-id"}), + OperationToken( + type=OperationTokenType.WORKFLOW, + namespace="", + workflow_id="workflow-id", + ), + ), + ( + _encode_json_token( + {"t": 1, "ns": "default", "wid": "workflow-id", "v": None} + ), + OperationToken( + type=OperationTokenType.WORKFLOW, + namespace="default", + workflow_id="workflow-id", + ), + ), + ( + _encode_json_token({"t": 1, "ns": "default", "wid": "workflow-id", "v": 0}), + OperationToken( + type=OperationTokenType.WORKFLOW, + namespace="default", + workflow_id="workflow-id", + version=0, + ), + ), + ], +) +def test_operation_token_decode_accepts_valid_tokens( + token: str, + expected: OperationToken, +): + assert OperationToken.decode(token) == expected + + +@pytest.mark.parametrize( + ("token", "message"), + [ + ("", "invalid token: token is empty"), + ("not+a-base64url-token", "failed to decode token as base64url"), + (_encode_bytes(b"not json"), "failed to unmarshal operation token"), + (_encode_json_token(["not", "a", "dict"]), "expected dict"), + ( + _encode_json_token({"ns": "default", "wid": "workflow-id"}), + "expected token type to be an int", + ), + ( + _encode_json_token({"t": "1", "ns": "default", "wid": "workflow-id"}), + "expected token type to be an int", + ), + ( + _encode_json_token({"t": 999, "ns": "default", "wid": "workflow-id"}), + "unknown token type", + ), + ( + _encode_json_token({"t": 1, "ns": "default"}), + "expected workflow id to be a string", + ), + ( + _encode_json_token({"t": 1, "ns": "default", "wid": 123}), + "expected workflow id to be a string", + ), + ( + _encode_json_token({"t": 1, "ns": "default", "wid": ""}), + "expected non-empty workflow id", + ), + ( + _encode_json_token({"t": 1, "wid": "workflow-id"}), + "expected namespace to be a string", + ), + ( + _encode_json_token({"t": 1, "ns": 123, "wid": "workflow-id"}), + "expected namespace to be a string", + ), + ( + _encode_json_token( + {"t": 1, "ns": "default", "wid": "workflow-id", "v": "0"} + ), + "expected version to be an int or null", + ), + ], +) +def test_operation_token_decode_rejects_invalid_tokens(token: str, message: str): + with pytest.raises(TypeError, match=message): + OperationToken.decode(token) + + +def test_workflow_handle_from_token_accepts_version_zero(): + token = _encode_json_token({"t": 1, "ns": "default", "wid": "workflow-id", "v": 0}) + + assert WorkflowHandle[str].from_token(token) == WorkflowHandle[str]( + namespace="default", + workflow_id="workflow-id", + version=0, + ) + + +def test_workflow_handle_from_token_rejects_unsupported_version(): + token = _encode_json_token({"t": 1, "ns": "default", "wid": "workflow-id", "v": 1}) + + with pytest.raises(TypeError, match="'v' field, if present, must be 0"): + WorkflowHandle[str].from_token(token) diff --git a/tests/nexus/test_temporal_operation.py b/tests/nexus/test_temporal_operation.py new file mode 100644 index 000000000..8bdfa267e --- /dev/null +++ b/tests/nexus/test_temporal_operation.py @@ -0,0 +1,689 @@ +import asyncio +import uuid +from dataclasses import dataclass + +import nexusrpc +import pytest +from nexusrpc import HandlerErrorType, Operation, service +from nexusrpc.handler import operation_handler, service_handler +from typing_extensions import override + +import temporalio.exceptions +from temporalio import nexus, workflow +from temporalio.client import Client, WorkflowExecutionStatus, WorkflowFailureError +from temporalio.common import NexusOperationExecutionStatus, WorkflowIDConflictPolicy +from temporalio.testing import WorkflowEnvironment +from temporalio.worker import Worker +from tests.helpers import EventType, assert_event_subsequence, assert_eventually +from tests.helpers.nexus import make_nexus_endpoint_name + + +@dataclass +class Input: + value: str + task_queue: str + + +def test_temporal_operation_result_validates_single_result_kind() -> None: + assert nexus.TemporalOperationResult.sync(None).value is None + assert nexus.TemporalOperationResult.async_token("token").token == "token" + + with pytest.raises(ValueError, match="exactly one of value or token"): + nexus.TemporalOperationResult() + + with pytest.raises(ValueError, match="exactly one of value or token"): + nexus.TemporalOperationResult(value="value", token="token") + + +def test_temporal_operation_result_validates_token() -> None: + with pytest.raises(ValueError, match="non-empty string"): + nexus.TemporalOperationResult.async_token("") + + with pytest.raises(ValueError, match="non-empty string"): + nexus.TemporalOperationResult(token="") + + with pytest.raises(ValueError, match="non-empty string"): + nexus.TemporalOperationResult(token=123) # type: ignore + + +@workflow.defn +class EchoWorkflow: + @workflow.run + async def run(self, input: Input) -> str: + return input.value + + +@service +class TestService: + echo: Operation[Input, str] + blocking: Operation[None, None] + double_start: Operation[Input, None] + concurrent_start: Operation[Input, str] + retry_after_failed_start: Operation[Input, str] + sync_result: Operation[Input, str] + custom_cancel: Operation[str, None] + + +@service_handler(service=TestService) +class TestServiceHandler: + # tell Pytest this is not a test class + __test__ = False + + def __init__(self) -> None: + self.started_custom_cancel_workflow = asyncio.Event() + + @nexus.temporal_operation + async def echo( + self, + _ctx: nexus.TemporalNexusStartOperationContext, + client: nexus.TemporalNexusClient, + input: Input, + ) -> nexus.TemporalOperationResult[str]: + return await client.start_workflow( + EchoWorkflow.run, input, id=f"echo-{input.value}" + ) + + @nexus.temporal_operation + async def blocking( + self, + _ctx: nexus.TemporalNexusStartOperationContext, + client: nexus.TemporalNexusClient, + _input: None, + ) -> nexus.TemporalOperationResult[None]: + return await client.start_workflow( + BlockingWorkflow.run, id=f"blocking-{uuid.uuid4()}" + ) + + @nexus.temporal_operation + async def double_start( + self, + _ctx: nexus.TemporalNexusStartOperationContext, + client: nexus.TemporalNexusClient, + input: Input, + ) -> nexus.TemporalOperationResult[None]: + await client.start_workflow( + EchoWorkflow.run, input, id=f"double-start-{uuid.uuid4()}" + ) + await client.start_workflow( + EchoWorkflow.run, input, id=f"double-start-{uuid.uuid4()}" + ) + return nexus.TemporalOperationResult.sync(None) + + @nexus.temporal_operation + async def concurrent_start( + self, + _ctx: nexus.TemporalNexusStartOperationContext, + client: nexus.TemporalNexusClient, + input: Input, + ) -> nexus.TemporalOperationResult[str]: + results = await asyncio.gather( + client.start_workflow( + EchoWorkflow.run, + input, + id=f"concurrent-start-1-{uuid.uuid4()}", + ), + client.start_workflow( + EchoWorkflow.run, + input, + id=f"concurrent-start-2-{uuid.uuid4()}", + ), + return_exceptions=True, + ) + + async_results: list[nexus.TemporalOperationResult[str]] = [] + handler_errors: list[nexusrpc.HandlerError] = [] + for result in results: + if isinstance(result, nexus.TemporalOperationResult): + async_results.append(result) + elif isinstance(result, nexusrpc.HandlerError): + handler_errors.append(result) + elif isinstance(result, BaseException): + raise result + else: + raise RuntimeError(f"Unexpected concurrent start result: {result}") + + if ( + len(async_results) == 1 + and len(handler_errors) == 1 + and handler_errors[0].type == HandlerErrorType.BAD_REQUEST + ): + return async_results[0] + + raise RuntimeError( + "Expected one async workflow start and one BAD_REQUEST HandlerError, " + f"got {len(async_results)} starts and {len(handler_errors)} handler errors" + ) + + @nexus.temporal_operation + async def retry_after_failed_start( + self, + _ctx: nexus.TemporalNexusStartOperationContext, + client: nexus.TemporalNexusClient, + input: Input, + ) -> nexus.TemporalOperationResult[str]: + try: + await client.start_workflow( + BlockingWorkflow.run, + id=input.value, + id_conflict_policy=WorkflowIDConflictPolicy.FAIL, + ) + except temporalio.exceptions.WorkflowAlreadyStartedError: + return await client.start_workflow( + EchoWorkflow.run, + input, + id=f"retry-after-failed-start-{uuid.uuid4()}", + ) + + raise RuntimeError("Expected first workflow start to fail") + + @nexus.temporal_operation + async def sync_result( + self, + _ctx: nexus.TemporalNexusStartOperationContext, + _client: nexus.TemporalNexusClient, + input: Input, + ) -> nexus.TemporalOperationResult[str]: + return nexus.TemporalOperationResult.sync(input.value) + + @operation_handler + def custom_cancel(self) -> nexus.TemporalNexusOperationHandler[str, None]: + event = self.started_custom_cancel_workflow + + class CustomCancelNexusOpHandler( + nexus.TemporalNexusOperationHandler[str, None] + ): + @override + async def start_operation( + self, + ctx: nexus.TemporalNexusStartOperationContext, + client: nexus.TemporalNexusClient, + input: str, + ) -> nexus.TemporalOperationResult[None]: + result = await client.start_workflow(BlockingWorkflow.run, id=input) + event.set() + return result + + @override + async def cancel_workflow_run( + self, + ctx: nexus.TemporalNexusCancelOperationContext, + options: nexus.CancelWorkflowRunOptions, + ): + # get a handle to the workflow + handle = nexus.client().get_workflow_handle(options.workflow_id) + + # cancel the workflow + await handle.cancel() + + return CustomCancelNexusOpHandler() + + +@workflow.defn +class EchoWorkflowCaller: + @workflow.run + async def run(self, input: Input) -> str: + client = workflow.create_nexus_client( + service=TestService, endpoint=make_nexus_endpoint_name(input.task_queue) + ) + return await client.execute_operation(TestService.echo, input) + + +async def test_temporal_operation_start_workflow( + client: Client, env: WorkflowEnvironment +): + task_queue = str(uuid.uuid4()) + endpoint_name = make_nexus_endpoint_name(task_queue) + await env.create_nexus_endpoint(endpoint_name, task_queue) + async with Worker( + env.client, + task_queue=task_queue, + nexus_service_handlers=[TestServiceHandler()], + workflows=[EchoWorkflow, EchoWorkflowCaller], + ): + wf_handle = await client.start_workflow( + EchoWorkflowCaller.run, + Input(value="test", task_queue=task_queue), + task_queue=task_queue, + id=str(uuid.uuid4()), + ) + result = await wf_handle.result() + assert result == "test" + + await assert_event_subsequence( + wf_handle, + [ + EventType.EVENT_TYPE_NEXUS_OPERATION_SCHEDULED, + EventType.EVENT_TYPE_NEXUS_OPERATION_STARTED, + EventType.EVENT_TYPE_NEXUS_OPERATION_COMPLETED, + ], + ) + + +@workflow.defn +class BlockingWorkflow: + def __init__(self) -> None: + self.done: bool = False + + @workflow.run + async def run(self) -> None: + await workflow.wait_condition(lambda: self.done) + + @workflow.update + async def unblock(self): + self.done = True + + +@workflow.defn +class CancelBlockingWorkflowCaller: + op_started = False + + @workflow.run + async def run(self, input: Input) -> None: + client = workflow.create_nexus_client( + service=TestService, endpoint=make_nexus_endpoint_name(input.task_queue) + ) + op_handle = await client.start_operation(TestService.blocking, None) + self.op_started = True + return await op_handle + + @workflow.update + async def wait_operation_started(self): + await workflow.wait_condition(lambda: self.op_started) + + +async def test_temporal_operation_cancel_workflow( + client: Client, env: WorkflowEnvironment +): + task_queue = str(uuid.uuid4()) + endpoint_name = make_nexus_endpoint_name(task_queue) + await env.create_nexus_endpoint(endpoint_name, task_queue) + async with Worker( + env.client, + task_queue=task_queue, + nexus_service_handlers=[TestServiceHandler()], + workflows=[BlockingWorkflow, CancelBlockingWorkflowCaller], + ): + wf_handle = await client.start_workflow( + CancelBlockingWorkflowCaller.run, + Input(value="test", task_queue=task_queue), + task_queue=task_queue, + id=f"blocking-{uuid.uuid4()}", + ) + + await wf_handle.execute_update( + CancelBlockingWorkflowCaller.wait_operation_started + ) + + await wf_handle.cancel() + + await assert_event_subsequence( + wf_handle, + [ + EventType.EVENT_TYPE_NEXUS_OPERATION_CANCEL_REQUESTED, + EventType.EVENT_TYPE_NEXUS_OPERATION_CANCEL_REQUEST_COMPLETED, + EventType.EVENT_TYPE_NEXUS_OPERATION_CANCELED, + ], + ) + + +async def test_customized_temporal_operation_cancel_workflow( + client: Client, env: WorkflowEnvironment +): + if env.supports_time_skipping: + pytest.skip( + "Standalone Nexus Operation tests don't work with time-skipping server" + ) + + task_queue = str(uuid.uuid4()) + endpoint_name = make_nexus_endpoint_name(task_queue) + await env.create_nexus_endpoint(endpoint_name, task_queue) + + service_handler = TestServiceHandler() + async with Worker( + env.client, + task_queue=task_queue, + nexus_service_handlers=[service_handler], + workflows=[BlockingWorkflow, CancelBlockingWorkflowCaller], + ): + nexus_client = client.create_nexus_client(TestService, endpoint_name) + + wf_id = f"custom-cancel-{uuid.uuid4()}" + op_handle = await nexus_client.start_operation( + TestService.custom_cancel, wf_id, id=str(uuid.uuid4()) + ) + + await service_handler.started_custom_cancel_workflow.wait() + + await op_handle.cancel() + + async def check_cancelled(): + wf_handle = client.get_workflow_handle(wf_id) + wf_desc = await wf_handle.describe() + assert wf_desc.status is WorkflowExecutionStatus.CANCELED + op_desc = await op_handle.describe() + assert op_desc.status is NexusOperationExecutionStatus.CANCELED + + await assert_eventually(check_cancelled) + + +@workflow.defn +class DoubleStartWorkflowCaller: + @workflow.run + async def run(self, input: Input) -> None: + client = workflow.create_nexus_client( + service=TestService, endpoint=make_nexus_endpoint_name(input.task_queue) + ) + op_handle = await client.start_operation(TestService.double_start, input) + return await op_handle + + +@workflow.defn +class ConcurrentStartWorkflowCaller: + @workflow.run + async def run(self, input: Input) -> str: + client = workflow.create_nexus_client( + service=TestService, endpoint=make_nexus_endpoint_name(input.task_queue) + ) + return await client.execute_operation(TestService.concurrent_start, input) + + +@workflow.defn +class FailedStartRollbackWorkflowCaller: + @workflow.run + async def run(self, input: Input) -> str: + client = workflow.create_nexus_client( + service=TestService, endpoint=make_nexus_endpoint_name(input.task_queue) + ) + return await client.execute_operation( + TestService.retry_after_failed_start, + input, + ) + + +async def test_temporal_operation_double_start_raises_handler_err( + client: Client, env: WorkflowEnvironment +): + task_queue = str(uuid.uuid4()) + endpoint_name = make_nexus_endpoint_name(task_queue) + await env.create_nexus_endpoint(endpoint_name, task_queue) + async with Worker( + env.client, + task_queue=task_queue, + nexus_service_handlers=[TestServiceHandler()], + workflows=[EchoWorkflow, DoubleStartWorkflowCaller], + ): + with pytest.raises(WorkflowFailureError) as err: + await client.execute_workflow( + DoubleStartWorkflowCaller.run, + Input(value="test", task_queue=task_queue), + task_queue=task_queue, + id=f"double-start-{uuid.uuid4()}", + ) + + assert isinstance(err.value.cause, temporalio.exceptions.NexusOperationError) + assert isinstance(err.value.cause.cause, nexusrpc.HandlerError) + assert err.value.cause.cause.type == HandlerErrorType.BAD_REQUEST + assert ( + "Only one async operation can be started per operation handler invocation" + in err.value.cause.cause.message + ) + + +async def test_temporal_operation_concurrent_start_raises_handler_err( + client: Client, env: WorkflowEnvironment +): + task_queue = str(uuid.uuid4()) + endpoint_name = make_nexus_endpoint_name(task_queue) + await env.create_nexus_endpoint(endpoint_name, task_queue) + async with Worker( + env.client, + task_queue=task_queue, + nexus_service_handlers=[TestServiceHandler()], + workflows=[EchoWorkflow, ConcurrentStartWorkflowCaller], + ): + result = await client.execute_workflow( + ConcurrentStartWorkflowCaller.run, + Input(value="test", task_queue=task_queue), + task_queue=task_queue, + id=f"concurrent-start-{uuid.uuid4()}", + ) + + assert result == "test" + + +async def test_temporal_operation_failed_start_allows_retry( + client: Client, env: WorkflowEnvironment +): + task_queue = str(uuid.uuid4()) + endpoint_name = make_nexus_endpoint_name(task_queue) + conflict_id = f"failed-start-rollback-{uuid.uuid4()}" + await env.create_nexus_endpoint(endpoint_name, task_queue) + async with Worker( + env.client, + task_queue=task_queue, + nexus_service_handlers=[TestServiceHandler()], + workflows=[ + BlockingWorkflow, + EchoWorkflow, + FailedStartRollbackWorkflowCaller, + ], + ): + conflict_handle = await client.start_workflow( + BlockingWorkflow.run, + id=conflict_id, + task_queue=task_queue, + ) + + try: + result = await client.execute_workflow( + FailedStartRollbackWorkflowCaller.run, + Input(value=conflict_id, task_queue=task_queue), + task_queue=task_queue, + id=f"failed-start-rollback-caller-{uuid.uuid4()}", + ) + assert result == conflict_id + finally: + await conflict_handle.cancel() + + +@workflow.defn +class SyncResultCaller: + @workflow.run + async def run(self, input: Input) -> str: + client = workflow.create_nexus_client( + service=TestService, endpoint=make_nexus_endpoint_name(input.task_queue) + ) + return await client.execute_operation(TestService.sync_result, input) + + +async def test_temporal_operation_sync_result(client: Client, env: WorkflowEnvironment): + task_queue = str(uuid.uuid4()) + endpoint_name = make_nexus_endpoint_name(task_queue) + await env.create_nexus_endpoint(endpoint_name, task_queue) + async with Worker( + env.client, + task_queue=task_queue, + nexus_service_handlers=[TestServiceHandler()], + workflows=[SyncResultCaller], + ): + wf_handle = await client.start_workflow( + SyncResultCaller.run, + Input(value="test", task_queue=task_queue), + task_queue=task_queue, + id=str(uuid.uuid4()), + ) + result = await wf_handle.result() + assert result == "test" + + # Sync results do not produce a NEXUS_OPERATION_STARTED event, + await assert_event_subsequence( + wf_handle, + [ + EventType.EVENT_TYPE_NEXUS_OPERATION_SCHEDULED, + EventType.EVENT_TYPE_NEXUS_OPERATION_COMPLETED, + ], + ) + + +@dataclass +class TemporalOperationOverloadTestValue: + value: int + + +@workflow.defn +class TemporalOperationOverloadTestWorkflow: + @workflow.run + async def run( + self, input: TemporalOperationOverloadTestValue + ) -> TemporalOperationOverloadTestValue: + return TemporalOperationOverloadTestValue(value=input.value * 2) + + +@workflow.defn +class TemporalOperationOverloadTestWorkflowNoParam: + @workflow.run + async def run(self) -> TemporalOperationOverloadTestValue: + return TemporalOperationOverloadTestValue(value=0) + + +@service_handler +class TemporalOperationOverloadTestServiceHandler: + @nexus.temporal_operation + async def no_param( + self, + _ctx: nexus.TemporalNexusStartOperationContext, + client: nexus.TemporalNexusClient, + _input: TemporalOperationOverloadTestValue, + ) -> nexus.TemporalOperationResult[TemporalOperationOverloadTestValue]: + return await client.start_workflow( + TemporalOperationOverloadTestWorkflowNoParam.run, + id=str(uuid.uuid4()), + ) + + @nexus.temporal_operation + async def single_param( + self, + _ctx: nexus.TemporalNexusStartOperationContext, + client: nexus.TemporalNexusClient, + input: TemporalOperationOverloadTestValue, + ) -> nexus.TemporalOperationResult[TemporalOperationOverloadTestValue]: + return await client.start_workflow( + TemporalOperationOverloadTestWorkflow.run, + input, + id=str(uuid.uuid4()), + ) + + @nexus.temporal_operation + async def multi_param( + self, + _ctx: nexus.TemporalNexusStartOperationContext, + client: nexus.TemporalNexusClient, + input: TemporalOperationOverloadTestValue, + ) -> nexus.TemporalOperationResult[TemporalOperationOverloadTestValue]: + return await client.start_workflow( + TemporalOperationOverloadTestWorkflow.run, + args=[input], + id=str(uuid.uuid4()), + ) + + @nexus.temporal_operation + async def by_name( + self, + _ctx: nexus.TemporalNexusStartOperationContext, + client: nexus.TemporalNexusClient, + input: TemporalOperationOverloadTestValue, + ) -> nexus.TemporalOperationResult[TemporalOperationOverloadTestValue]: + return await client.start_workflow( + "TemporalOperationOverloadTestWorkflow", + input, + id=str(uuid.uuid4()), + result_type=TemporalOperationOverloadTestValue, + ) + + @nexus.temporal_operation + async def by_name_multi_param( + self, + _ctx: nexus.TemporalNexusStartOperationContext, + client: nexus.TemporalNexusClient, + input: TemporalOperationOverloadTestValue, + ) -> nexus.TemporalOperationResult[TemporalOperationOverloadTestValue]: + return await client.start_workflow( + "TemporalOperationOverloadTestWorkflow", + args=[input], + id=str(uuid.uuid4()), + result_type=TemporalOperationOverloadTestValue, + ) + + +@workflow.defn +class TemporalOperationOverloadTestCallerWorkflow: + @workflow.run + async def run( + self, op: str, input: TemporalOperationOverloadTestValue + ) -> TemporalOperationOverloadTestValue: + client = workflow.create_nexus_client( + service=TemporalOperationOverloadTestServiceHandler, + endpoint=make_nexus_endpoint_name(workflow.info().task_queue), + ) + + if op == "no_param": + return await client.execute_operation( + TemporalOperationOverloadTestServiceHandler.no_param, input + ) + elif op == "single_param": + return await client.execute_operation( + TemporalOperationOverloadTestServiceHandler.single_param, input + ) + elif op == "multi_param": + return await client.execute_operation( + TemporalOperationOverloadTestServiceHandler.multi_param, input + ) + elif op == "by_name": + return await client.execute_operation( + TemporalOperationOverloadTestServiceHandler.by_name, input + ) + elif op == "by_name_multi_param": + return await client.execute_operation( + TemporalOperationOverloadTestServiceHandler.by_name_multi_param, input + ) + else: + raise ValueError(f"Unknown op: {op}") + + +@pytest.mark.parametrize( + "op", + [ + "no_param", + "single_param", + "multi_param", + "by_name", + "by_name_multi_param", + ], +) +async def test_temporal_operation_overloads( + client: Client, env: WorkflowEnvironment, op: str +): + task_queue = str(uuid.uuid4()) + endpoint_name = make_nexus_endpoint_name(task_queue) + await env.create_nexus_endpoint(endpoint_name, task_queue) + async with Worker( + client, + task_queue=task_queue, + workflows=[ + TemporalOperationOverloadTestCallerWorkflow, + TemporalOperationOverloadTestWorkflow, + TemporalOperationOverloadTestWorkflowNoParam, + ], + nexus_service_handlers=[TemporalOperationOverloadTestServiceHandler()], + ): + result = await client.execute_workflow( + TemporalOperationOverloadTestCallerWorkflow.run, + args=[op, TemporalOperationOverloadTestValue(value=2)], + id=str(uuid.uuid4()), + task_queue=task_queue, + ) + assert result == ( + TemporalOperationOverloadTestValue(value=0) + if op == "no_param" + else TemporalOperationOverloadTestValue(value=4) + ) diff --git a/tests/nexus/test_workflow_caller_cancellation_types.py b/tests/nexus/test_workflow_caller_cancellation_types.py index cdce9a99b..bf33983a5 100644 --- a/tests/nexus/test_workflow_caller_cancellation_types.py +++ b/tests/nexus/test_workflow_caller_cancellation_types.py @@ -22,7 +22,7 @@ from temporalio.common import WorkflowIDConflictPolicy from temporalio.testing import WorkflowEnvironment from temporalio.worker import Worker -from tests.helpers import LogCapturer, assert_eventually +from tests.helpers import LogCapturer, assert_event_subsequence, assert_eventually from tests.helpers.nexus import make_nexus_endpoint_name @@ -505,38 +505,3 @@ async def get_event_time( return event.event_time.ToDatetime().replace(tzinfo=timezone.utc) event_type_name = EventType.Name(event_type).removeprefix("EVENT_TYPE_") assert False, f"Event {event_type_name} not found in {wf_handle.id}" - - -async def assert_event_subsequence( - wf_handle: WorkflowHandle, - expected_events: list[EventType.ValueType], -) -> None: - """ - Given a workflow handle and a sequence of event types, assert that the workflow's history - contains that subsequence of events in the order specified. - """ - all_events = [] - async for e in wf_handle.fetch_history_events(): - all_events.append(e) - - _all_events = iter(all_events) - _expected_events = iter(expected_events) - - previous_expected_event_type_name = None - for expected_event_type in _expected_events: - expected_event_type_name = EventType.Name(expected_event_type).removeprefix( - "EVENT_TYPE_" - ) - has_expected = next( - (e for e in _all_events if e.event_type == expected_event_type), - None, - ) - if not has_expected: - if previous_expected_event_type_name is not None: - prefix = f"After {previous_expected_event_type_name}, " - else: - prefix = "" - pytest.fail( - f"{prefix}expected {expected_event_type_name} in workflow {wf_handle.id}" - ) - previous_expected_event_type_name = expected_event_type_name diff --git a/tests/nexus/test_workflow_caller_cancellation_types_when_cancel_handler_fails.py b/tests/nexus/test_workflow_caller_cancellation_types_when_cancel_handler_fails.py index 3418e290f..4cdeeeb15 100644 --- a/tests/nexus/test_workflow_caller_cancellation_types_when_cancel_handler_fails.py +++ b/tests/nexus/test_workflow_caller_cancellation_types_when_cancel_handler_fails.py @@ -23,10 +23,9 @@ from temporalio.common import WorkflowIDConflictPolicy from temporalio.testing import WorkflowEnvironment from temporalio.worker import Worker -from tests.helpers import assert_eventually +from tests.helpers import assert_event_subsequence, assert_eventually from tests.helpers.nexus import make_nexus_endpoint_name from tests.nexus.test_workflow_caller_cancellation_types import ( - assert_event_subsequence, get_event_time, has_event, ) diff --git a/tests/test_workflow_exports.py b/tests/test_workflow_exports.py index e67040b64..8788addc5 100644 --- a/tests/test_workflow_exports.py +++ b/tests/test_workflow_exports.py @@ -46,7 +46,6 @@ "RootInfo", "SandboxImportNotificationPolicy", "SelfType", - "ServiceHandlerT", "UnfinishedSignalHandlersWarning", "UnfinishedUpdateHandlersWarning", "UpdateInfo", From d53a604d694bd5dcef0c4c9da6650aa7bc199be0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 29 May 2026 03:41:30 +0000 Subject: [PATCH 111/226] Bump langsmith from 0.7.38 to 0.8.0 (#1521) Bumps [langsmith](https://github.com/langchain-ai/langsmith-sdk) from 0.7.38 to 0.8.0. - [Release notes](https://github.com/langchain-ai/langsmith-sdk/releases) - [Commits](https://github.com/langchain-ai/langsmith-sdk/compare/v0.7.38...v0.8.0) --- updated-dependencies: - dependency-name: langsmith dependency-version: 0.8.0 dependency-type: direct:development ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pyproject.toml | 4 ++-- uv.lock | 10 +++++----- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index da9c8bdd3..92a2ff556 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -31,7 +31,7 @@ pydantic = ["pydantic>=2.0.0,<3"] openai-agents = ["openai-agents>=0.17.1", "mcp>=1.9.4, <2"] google-adk = ["google-adk>=1.27.0,<2"] langgraph = ["langgraph>=1.1.0"] -langsmith = ["langsmith>=0.7.34,<0.8"] +langsmith = ["langsmith>=0.7.34,<0.9"] lambda-worker-otel = [ "opentelemetry-api>=1.11.1,<2", "opentelemetry-sdk>=1.11.1,<2", @@ -78,7 +78,7 @@ dev = [ "pytest-xdist>=3.6,<4", "moto[s3,server]>=5", "langgraph>=1.1.0", - "langsmith>=0.7.34,<0.8", + "langsmith>=0.7.34,<0.9", "setuptools<82", "opentelemetry-exporter-otlp-proto-grpc>=1.11.1,<2", "opentelemetry-semantic-conventions>=0.40b0,<1", diff --git a/uv.lock b/uv.lock index b94b932d5..e8fe1e0f1 100644 --- a/uv.lock +++ b/uv.lock @@ -2559,7 +2559,7 @@ wheels = [ [[package]] name = "langsmith" -version = "0.7.38" +version = "0.8.4" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "httpx" }, @@ -2572,9 +2572,9 @@ dependencies = [ { name = "xxhash" }, { name = "zstandard" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/af/c9/b3e54cfcb480876dfe33ecfdd64feeb621a86d9e6f4a6b9eb46851807018/langsmith-0.7.38.tar.gz", hash = "sha256:0db529b768d66c45f22fe959a0af7151342704fefafdecf3c60b14097c14fdb1", size = 4431914, upload-time = "2026-04-29T00:21:42.865Z" } +sdist = { url = "https://files.pythonhosted.org/packages/d4/e9/4ceeba766bae47de1a6ecdaa4024d10eff63eed936796b77005742399e8d/langsmith-0.8.4.tar.gz", hash = "sha256:989b387f6ff92ec5f9d14c0edb333e2579590cad5a1ca07042d924b0ec43cd10", size = 4460243, upload-time = "2026-05-13T21:00:59.338Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/86/bc/a19d0a6d5575c637796675831dbef3555568e84d913f14ec579f92162ffa/langsmith-0.7.38-py3-none-any.whl", hash = "sha256:9c400ad508c0e4edc37bd55987047c6b8aac36ddd55f6096e3806f4d6a100618", size = 392310, upload-time = "2026-04-29T00:21:40.534Z" }, + { url = "https://files.pythonhosted.org/packages/db/94/8b872959ea529ecfbbe2c3f91d9ebf98cb8dbd9e3f7487bc134740d3d235/langsmith-0.8.4-py3-none-any.whl", hash = "sha256:4e334ab223d10129c9943c461d95fa9089523638ea29cd048045a7f99b973f50", size = 398701, upload-time = "2026-05-13T21:00:57.393Z" }, ] [[package]] @@ -5251,7 +5251,7 @@ requires-dist = [ { name = "google-adk", marker = "extra == 'google-adk'", specifier = ">=1.27.0,<2" }, { name = "grpcio", marker = "extra == 'grpc'", specifier = ">=1.48.2,<2" }, { name = "langgraph", marker = "extra == 'langgraph'", specifier = ">=1.1.0" }, - { name = "langsmith", marker = "extra == 'langsmith'", specifier = ">=0.7.34,<0.8" }, + { name = "langsmith", marker = "extra == 'langsmith'", specifier = ">=0.7.34,<0.9" }, { name = "mcp", marker = "extra == 'openai-agents'", specifier = ">=1.9.4,<2" }, { name = "nexus-rpc", specifier = "==1.4.0" }, { name = "openai-agents", marker = "extra == 'openai-agents'", specifier = ">=0.17.1" }, @@ -5280,7 +5280,7 @@ dev = [ { name = "grpcio-tools", specifier = ">=1.48.2,<2" }, { name = "httpx", specifier = ">=0.28.1" }, { name = "langgraph", specifier = ">=1.1.0" }, - { name = "langsmith", specifier = ">=0.7.34,<0.8" }, + { name = "langsmith", specifier = ">=0.7.34,<0.9" }, { name = "litellm", specifier = ">=1.83.0" }, { name = "maturin", specifier = ">=1.8.2" }, { name = "moto", extras = ["s3", "server"], specifier = ">=5" }, From 900072546cb30887f346523ed56385c84796176e Mon Sep 17 00:00:00 2001 From: Brian Strauch Date: Mon, 1 Jun 2026 11:24:01 -0700 Subject: [PATCH 112/226] Add Strands Agents plugin (contrib) (#1539) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Bump ruff to 0.15 and reformat Also bump `[tool.ruff] target-version` from py39 to py310 to match `requires-python`; the old setting caused 0.15 to reject `match` statements in the codebase. * contrib/strands: add Strands Agents plugin * contrib/strands: split activity helper into _TemporalActivityTool * contrib/strands: import strands_tools at module level in wrapper * contrib/strands: run models as activities via TemporalModel * contrib/strands: patch Agent.__init__ to route models through activities * contrib/strands: explicit TemporalModel/TemporalMCPClient, drop monkey-patch, add MCP * contrib/strands: rewrite README, default TemporalModel to BedrockModel Restructure the README into Quickstart + per-feature sections (Model, Structured Output, Streaming, Tools, MCP), add an experimental warning, installation instructions, and a link to strandsagents.com. Also default `TemporalModel.model_factory` to `BedrockModel`, matching the Strands `Agent` default, so the common case doesn't need a factory lambda. * contrib/strands: show worker activity registration in Tools snippet * contrib/strands: add activity_as_hook helper, document Hooks Adds activity_as_hook(activity_fn, *, extract, **options): wraps a Temporal activity as a Strands HookCallback so I/O-doing hook callbacks (audit logs, metrics) dispatch off the workflow. Co-locates with activity_as_tool in a new _workflow.py. * contrib/strands: rename activity_as_hook extract to activity_input * contrib/strands: document HITL interrupts, add integration test * contrib/strands: document continue-as-new for long chats * contrib/strands: document OpenTelemetryPlugin compatibility * contrib/strands: fix lint warnings and add missing docstrings * disable tiktoken and other sandbox warnings * contrib/strands: disable Strands retries, route via Temporal RetryPolicy Patch Agent.__init__ at import time to force retry_strategy=None and raise ValueError when a strategy is supplied, so retries happen at the Temporal activity layer (RetryPolicy on activity options) rather than blocking inside the activity body. Documents the behavior in README. * contrib/strands: move activity_as_tool/hook under workflow.* submodule * contrib/strands: disable Agent.take_snapshot/load_snapshot * contrib/strands: add CODEOWNERS entries * contrib/strands: type _InvokeModelInput fields as Any Python < 3.11's get_type_hints leaks NotRequired[...] through TypedDict fields, which the default JSON converter can't deserialize. Strands Message and ToolSpec use NotRequired, so loosen the activity input fields to Any; values pass through unchanged to Model.stream. * contrib/common: extract _heartbeat_decorator for cross-plugin use * contrib/strands: auto-heartbeat model activities, loosen input types Switch invoke_model/_streaming to the _auto_heartbeater pattern (matches openai_agents) so the heartbeat clock doesn't depend on event cadence and the non-streaming activity is covered too. Type _InvokeModelInput fields as Any: strands Message/ToolSpec use NotRequired, which Python < 3.11's get_type_hints leaks through and the default JSON converter then fails to deserialize. Values pass through unchanged to Model.stream. Drop the explicit activity name= override so the activities use their function names (invoke_model, invoke_model_streaming), matching the naming convention used by other contrib model activities. * contrib/strands: clarify tiktoken comment * contrib/common: drop leading underscore from auto_heartbeater Cross-module consumers can't be seen by basedpyright when the function is underscore-prefixed, producing a false unused-function warning. Promote the name and add a package docstring. * contrib/strands: drop redundant passthrough entries `pydantic` and `temporalio.contrib.strands` are already covered by the SDK's default passthrough (via `pydantic` and `temporalio` in `passthrough_modules_with_temporal`). Update the stale comment in _temporal_mcp_client.py that explained the redundant entry. * contrib/strands: support multiple models and MCP servers per worker Replace the singular model= / mcp_clients=[...] plugin args with name-keyed dicts: StrandsPlugin(models={name: factory}, mcp_clients={name: transport}). TemporalModel and TemporalMCPClient become pure workflow-side handles that reference the worker registration by name and carry only per-call activity options. A single pair of model activities now dispatches to any number of backing models by resolving model_name from the activity input. * contrib/strands: introduce TemporalAgent, drop Agent monkey-patches TemporalAgent(Agent) is the primary user-facing class: it takes model="name" to select a factory registered with StrandsPlugin(models=...), accepts the per-call activity options, and forwards all other kwargs to Strands' Agent. Construction-time validation of retry_strategy and overrides of take_snapshot/load_snapshot replace the previous Agent.__init__ and snapshot monkey-patches in StrandsPlugin. TemporalModel is no longer exported; it remains as internal plumbing for TemporalAgent. * contrib/strands: register OpenTelemetryPlugin on the client in the README Per the OpenTelemetry plugin's own guidance, plugins register on the client so workers built from that client pick them up automatically. Update the Observability section accordingly, plus minor wording polish in the Models and Structured Output sections. * contrib/strands: set max_cached_workflows=0 in tests Force every workflow task to replay from full history so the strands tests double as a continuous determinism check on the plugin and TemporalAgent. All 7 tests pass under the stricter setting. Also trims a redundant paragraph from StrandsPlugin's docstring. * contrib/strands: appease poe lint Drop the leading underscore from populate_cache / clear_cache / build_call_tool_activity in _temporal_mcp_client.py — basedpyright flagged them as unused because it doesn't follow cross-module imports for underscore-prefixed names. Add docstrings since pydocstyle now treats them as public. Also pick up a one-line ruff format fix in _model_activity.py. * contrib/strands: propagate InterruptException across activity boundary Install a failure converter on the plugin's data converter that translates strands InterruptException into an ApplicationError carrying the Interrupt payload in details. TemporalActivityTool.stream() catches the matching ApplicationError, reconstructs the Interrupt, and yields ToolInterruptEvent so AgentResult.interrupts is populated just like the in-workflow case. The path requires StrandsPlugin on the client (not just the worker), since _ActivityWorker reads the data converter from client_config. README HITL section is restructured to cover both hook-based and tool-body surfaces, with a note on the client-attachment requirement. New test_interrupt_exception.py exercises both surfaces end-to-end with signal-driven resume. * contrib/strands: forward invocation_state; default StrandsPlugin to BedrockModel Forward agent invocation_state across the model activity boundary so the worker-side model receives it via model.stream(invocation_state=...). Entries that aren't JSON-serializable are dropped before dispatch with a debug log naming the dropped keys. Make model selection optional. StrandsPlugin() with no args registers a single BedrockModel() factory under the name "bedrock" (matching Strands' own implicit default in agent.py:221), and TemporalAgent() with no model resolves to the sole registered factory at activity time. Multi-model setups continue to require an explicit model= on TemporalAgent. README quickstart shrinks accordingly: no BedrockModel import, no models= argument on StrandsPlugin, no model= on TemporalAgent. Model= remains in the multi-model example where it's load-bearing. * contrib/strands: gate implicit model resolution behind the plugin default Drop the single-entry guess for TemporalAgent(model=None). Implicit resolution is now valid only when StrandsPlugin auto-registers its own BedrockModel default; any user-supplied models= forces every TemporalAgent to pass model= explicitly. Track the gate via a default_name field on ModelActivity that the plugin sets only on the auto-registered path. * contrib/strands: mark terminal Strands exceptions non-retryable Extend StrandsFailureConverter.to_failure to translate Strands' terminal model/session exceptions into ApplicationError(non_retryable=True, type=...): MaxTokensReachedException, ContextWindowOverflowException, StructuredOutputException, SessionException. These deterministic failures won't succeed on retry, so the typed annotation stops Temporal's retry policy from churning on them. ModelThrottledException stays retryable. * contrib/strands: accept MCPClient factories in mcp_clients * contrib/strands: drop _get_encoding monkey patch strands-agents 1.39.0 removed _get_encoding and routes count_tokens straight to the chars-per-token heuristic, so the patch is a no-op. Bump the floor pin to 1.39.0 to keep that assumption true. * contrib/strands: swap current_time for shell in demos and tests * contrib/strands: ruff format populate_cache signature * contrib/strands: switch test_structured_output to TemporalAgent Also refresh stale Agent(...) references in _temporal_mcp_client and _temporal_model docstrings to point at TemporalAgent(...). * contrib/strands: rename optional dependency to strands-agents * contrib/strands: fix pydoctor docstring errors `warnings-as-errors = true` was failing CI's gen-docs step on invalid RST inline literals and unresolvable cross-references to the optional strands package. * tests: fix Windows test collection failures * test_type_errors.py: open test files with encoding="utf-8" so the rglob scan doesn't choke on UTF-8 characters (e.g. the strawberry emoji in test_tool.py) when the host's default codec is cp1252. * test_tool.py: skip the module on Windows; strands_tools.shell pulls in pty -> tty -> termios at import time, which is Unix-only. * tests/contrib/strands: swap shell tool for file_read strands_tools.shell imports pty/tty/termios at module load, which is Unix-only and broke Windows test collection. file_read on a tmp_path fixture is also non-deterministic (depends on filesystem state), has no in-workflow equivalent, and imports cleanly on every platform. * Fix Strands MCP client on Python 3.10 * contrib: inline _heartbeat_decorator into strands and openai_agents Removes the temporalio/contrib/common shared module by duplicating _heartbeat_decorator.py into each plugin and updating the two import sites. * contrib/strands: shorten strands import paths * contrib/strands: cache MCP connections across tool calls The per-server {server}-call-tool activity opened a fresh MCP session on every invocation (open transport + initialize + call + teardown), so an agent making several successive MCP calls paid that handshake per call -- and for stdio servers, a subprocess spawn per call. Hold a lazily-opened MCP session per server in the activity worker process so successive call-tool activities reuse one connection. A dedicated owner task enters and exits the anyio transport/ClientSession context managers in the same task (the cancel-scope rule); call-tool activities on the same event loop invoke session.call_tool directly, which MCP multiplexes by request id. Evict on idle timeout, on a call error (so a broken session reconnects), and on worker shutdown -- scoped to the servers the plugin registered rather than every cached connection. A reused session now carries server-side state across workflows sharing a worker, a behavior change from the previous per-call isolation. Co-Authored-By: Claude Opus 4.8 (1M context) * contrib/strands: make MCP connection idle timeout configurable The per-server call-tool activity keeps a worker-process MCP connection open between calls and evicts it after a fixed 5-minute idle window. Expose that window as a `mcp_connection_idle_timeout` plugin option (a timedelta); the 5-minute module default is unchanged. Arm the idle timer only once no calls remain in flight, rather than at the start of each call. The timer now measures genuine idle time between calls, and a call running longer than the timeout is never torn down underneath itself -- which also removes the connection-establishment race a short timeout previously exposed. A record only arms a timer while it is the cached connection, and the timer re-checks for in-flight calls before evicting. --------- Co-authored-by: Claude Opus 4.8 (1M context) --- .github/CODEOWNERS | 7 +- pyproject.toml | 3 + .../openai_agents/_heartbeat_decorator.py | 14 +- .../openai_agents/_invoke_model_activity.py | 8 +- temporalio/contrib/strands/README.md | 446 ++++++++++++++++++ temporalio/contrib/strands/__init__.py | 13 + .../contrib/strands/_failure_converter.py | 69 +++ .../contrib/strands/_heartbeat_decorator.py | 38 ++ temporalio/contrib/strands/_model_activity.py | 106 +++++ temporalio/contrib/strands/_plugin.py | 121 +++++ .../strands/_temporal_activity_tool.py | 95 ++++ temporalio/contrib/strands/_temporal_agent.py | 85 ++++ .../contrib/strands/_temporal_mcp_client.py | 326 +++++++++++++ .../contrib/strands/_temporal_mcp_tool.py | 65 +++ temporalio/contrib/strands/_temporal_model.py | 148 ++++++ temporalio/contrib/strands/workflow.py | 103 ++++ tests/contrib/strands/common.py | 10 + tests/contrib/strands/echo_mcp_server.py | 13 + tests/contrib/strands/mock_model.py | 60 +++ tests/contrib/strands/test_hooks.py | 106 +++++ tests/contrib/strands/test_interrupt.py | 105 +++++ .../strands/test_interrupt_exception.py | 191 ++++++++ .../contrib/strands/test_invocation_state.py | 82 ++++ tests/contrib/strands/test_mcp.py | 252 ++++++++++ tests/contrib/strands/test_model.py | 51 ++ tests/contrib/strands/test_model_streaming.py | 78 +++ .../contrib/strands/test_structured_output.py | 74 +++ tests/contrib/strands/test_tool.py | 118 +++++ tests/test_type_errors.py | 4 +- uv.lock | 277 ++++++++++- 30 files changed, 3048 insertions(+), 20 deletions(-) create mode 100644 temporalio/contrib/strands/README.md create mode 100644 temporalio/contrib/strands/__init__.py create mode 100644 temporalio/contrib/strands/_failure_converter.py create mode 100644 temporalio/contrib/strands/_heartbeat_decorator.py create mode 100644 temporalio/contrib/strands/_model_activity.py create mode 100644 temporalio/contrib/strands/_plugin.py create mode 100644 temporalio/contrib/strands/_temporal_activity_tool.py create mode 100644 temporalio/contrib/strands/_temporal_agent.py create mode 100644 temporalio/contrib/strands/_temporal_mcp_client.py create mode 100644 temporalio/contrib/strands/_temporal_mcp_tool.py create mode 100644 temporalio/contrib/strands/_temporal_model.py create mode 100644 temporalio/contrib/strands/workflow.py create mode 100644 tests/contrib/strands/common.py create mode 100644 tests/contrib/strands/echo_mcp_server.py create mode 100644 tests/contrib/strands/mock_model.py create mode 100644 tests/contrib/strands/test_hooks.py create mode 100644 tests/contrib/strands/test_interrupt.py create mode 100644 tests/contrib/strands/test_interrupt_exception.py create mode 100644 tests/contrib/strands/test_invocation_state.py create mode 100644 tests/contrib/strands/test_mcp.py create mode 100644 tests/contrib/strands/test_model.py create mode 100644 tests/contrib/strands/test_model_streaming.py create mode 100644 tests/contrib/strands/test_structured_output.py create mode 100644 tests/contrib/strands/test_tool.py diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 1a132f1fb..d638fd70e 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -6,15 +6,18 @@ # Below are owners for modules in the temporalio/contrib/ -# and tests/contrib/ directories that are owned by teams -# other than the SDK team. For each one, we add the owning team, +# and tests/contrib/ directories that are owned by teams +# other than the SDK team. For each one, we add the owning team, # as well as @temporalio/sdk, so the SDK team can continue to # manage repo-wide concerns. +/temporalio/contrib/common/ @temporalio/ai-sdk @temporalio/sdk /temporalio/contrib/google_adk_agents/ @temporalio/ai-sdk @temporalio/sdk /temporalio/contrib/langgraph/ @temporalio/ai-sdk @temporalio/sdk /temporalio/contrib/langsmith/ @temporalio/ai-sdk @temporalio/sdk /temporalio/contrib/openai_agents/ @temporalio/ai-sdk @temporalio/sdk +/temporalio/contrib/strands/ @temporalio/ai-sdk @temporalio/sdk /tests/contrib/google_adk_agents/ @temporalio/ai-sdk @temporalio/sdk /tests/contrib/langgraph/ @temporalio/ai-sdk @temporalio/sdk /tests/contrib/langsmith/ @temporalio/ai-sdk @temporalio/sdk /tests/contrib/openai_agents/ @temporalio/ai-sdk @temporalio/sdk +/tests/contrib/strands/ @temporalio/ai-sdk @temporalio/sdk diff --git a/pyproject.toml b/pyproject.toml index 92a2ff556..b44459fa3 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -40,6 +40,7 @@ lambda-worker-otel = [ "opentelemetry-sdk-extension-aws>=2.0.0,<3", ] aioboto3 = ["aioboto3>=10.4.0", "types-aioboto3[s3]>=10.4.0"] +strands-agents = ["strands-agents>=1.39.0"] [project.urls] Homepage = "https://github.com/temporalio/sdk-python" @@ -85,6 +86,8 @@ dev = [ "opentelemetry-sdk-extension-aws>=2.0.0,<3", "pytest-flakefinder>=1.1.0", "async-timeout>=4.0,<6; python_version < '3.11'", + "strands-agents>=1.39.0", + "strands-agents-tools>=0.5.2", ] [tool.poe.tasks] diff --git a/temporalio/contrib/openai_agents/_heartbeat_decorator.py b/temporalio/contrib/openai_agents/_heartbeat_decorator.py index 4baff6706..7c5b9193d 100644 --- a/temporalio/contrib/openai_agents/_heartbeat_decorator.py +++ b/temporalio/contrib/openai_agents/_heartbeat_decorator.py @@ -8,23 +8,22 @@ F = TypeVar("F", bound=Callable[..., Awaitable[Any]]) -def _auto_heartbeater(fn: F) -> F: # type:ignore[reportUnusedClass] - # Propagate type hints from the original callable. +def auto_heartbeater(fn: F) -> F: + """Decorator that heartbeats at half the activity's heartbeat timeout.""" + @wraps(fn) async def wrapper(*args: Any, **kwargs: Any) -> Any: heartbeat_timeout = activity.info().heartbeat_timeout heartbeat_task = None if heartbeat_timeout: - # Heartbeat twice as often as the timeout heartbeat_task = asyncio.create_task( - heartbeat_every(heartbeat_timeout.total_seconds() / 2) + _heartbeat_every(heartbeat_timeout.total_seconds() / 2) ) try: return await fn(*args, **kwargs) finally: if heartbeat_task: heartbeat_task.cancel() - # Wait for heartbeat cancellation to complete try: await heartbeat_task except asyncio.CancelledError: @@ -33,8 +32,7 @@ async def wrapper(*args: Any, **kwargs: Any) -> Any: return cast(F, wrapper) -async def heartbeat_every(delay: float, *details: Any) -> None: - """Heartbeat every so often while not cancelled""" +async def _heartbeat_every(delay: float) -> None: while True: await asyncio.sleep(delay) - activity.heartbeat(*details) + activity.heartbeat() diff --git a/temporalio/contrib/openai_agents/_invoke_model_activity.py b/temporalio/contrib/openai_agents/_invoke_model_activity.py index 1aa836eee..a43f9aeaf 100644 --- a/temporalio/contrib/openai_agents/_invoke_model_activity.py +++ b/temporalio/contrib/openai_agents/_invoke_model_activity.py @@ -43,7 +43,7 @@ from typing_extensions import Required, TypedDict from temporalio import activity -from temporalio.contrib.openai_agents._heartbeat_decorator import _auto_heartbeater +from temporalio.contrib.openai_agents._heartbeat_decorator import auto_heartbeater from temporalio.contrib.workflow_streams import WorkflowStreamClient from temporalio.exceptions import ApplicationError @@ -314,7 +314,7 @@ def __init__(self, model_provider: ModelProvider | None = None): ) @activity.defn - @_auto_heartbeater + @auto_heartbeater async def invoke_model_activity(self, input: ActivityModelInput) -> ModelResponse: """Activity that invokes a model with the given input.""" model = self._model_provider.get_model(input.get("model_name")) @@ -337,7 +337,7 @@ async def invoke_model_activity(self, input: ActivityModelInput) -> ModelRespons _raise_for_openai_status(e) @activity.defn - @_auto_heartbeater + @auto_heartbeater async def invoke_model_activity_streaming( self, input: StreamingActivityModelInput ) -> list[TResponseStreamEvent]: @@ -357,7 +357,7 @@ async def invoke_model_activity_streaming( ``streaming_topic`` so external consumers (UIs, tracing, etc.) can observe events as they arrive. - Heartbeats run on a background task via ``_auto_heartbeater`` so + Heartbeats run on a background task via ``auto_heartbeater`` so long initial-token latency or long pauses between chunks do not trip ``heartbeat_timeout``. """ diff --git a/temporalio/contrib/strands/README.md b/temporalio/contrib/strands/README.md new file mode 100644 index 000000000..fc9c6d74f --- /dev/null +++ b/temporalio/contrib/strands/README.md @@ -0,0 +1,446 @@ +# Strands Agents + +⚠️ **This package is currently at an experimental release stage.** ⚠️ + +This Temporal [Plugin](https://docs.temporal.io/develop/plugins-guide) allows you to run [Strands Agents](https://strandsagents.com/) inside Temporal Workflows, routing model invocations, tool calls, and MCP tool calls through Temporal Activities for durable execution, Temporal-managed retries, and timeouts. + +## Installation + +```sh +uv add temporalio[strands-agents] +``` + +## Quickstart + +`workflow.py` defines the workflow and runs the worker: + +```python +import asyncio +from datetime import timedelta + +from temporalio import workflow +from temporalio.client import Client +from temporalio.contrib.strands import StrandsPlugin, TemporalAgent +from temporalio.worker import Worker + + +@workflow.defn +class MyWorkflow: + def __init__(self) -> None: + self.agent = TemporalAgent(start_to_close_timeout=timedelta(seconds=60)) + + @workflow.run + async def run(self, prompt: str) -> str: + result = await self.agent.invoke_async(prompt) + return str(result) + + +async def main() -> None: + client = await Client.connect("localhost:7233") + worker = Worker( + client, + task_queue="strands", + workflows=[MyWorkflow], + plugins=[StrandsPlugin()], + ) + await worker.run() + + +if __name__ == "__main__": + asyncio.run(main()) +``` + +`client.py` starts the workflow: + +```python +import asyncio + +from temporalio.client import Client + +from workflow import MyWorkflow + + +async def main() -> None: + client = await Client.connect("localhost:7233") + result = await client.execute_workflow( + MyWorkflow.run, + "Hello", + id="strands-quickstart", + task_queue="strands", + ) + print(result) + + +if __name__ == "__main__": + asyncio.run(main()) +``` + +Note: Use `agent.invoke_async(message)` instead of `agent(message)`. The synchronous form spawns a worker thread, which the workflow sandbox blocks. + +## Models + +`StrandsPlugin(models=...)` takes a mapping of `name → factory`. Each factory is called lazily on first use (on the worker, outside the workflow sandbox) and the constructed model is cached for the worker's lifetime. `TemporalAgent(model="name", ...)` selects which factory to invoke and carries the activity options for that agent's model calls. If `models` is omitted, the plugin registers a single `BedrockModel()` factory under the name `"bedrock"`, matching Strands' own implicit default. + +```python +from strands.models.anthropic import AnthropicModel +from strands.models.bedrock import BedrockModel + +# workflow +@workflow.defn +class MultiModelWorkflow: + def __init__(self) -> None: + self.agent_a = TemporalAgent( + model="claude", + start_to_close_timeout=timedelta(seconds=60), + ) + self.agent_b = TemporalAgent( + model="bedrock", + start_to_close_timeout=timedelta(seconds=60), + ) + +# worker +Worker(..., plugins=[StrandsPlugin(models={ + "claude": lambda: AnthropicModel(client_args={"api_key": "..."}), + "bedrock": lambda: BedrockModel(), +})]) +``` + +Each `TemporalAgent` carries its own activity options (timeouts, retry policy, task queue, streaming topic) and dispatches to the shared model activity, which resolves the model name against the registered factories at runtime. A name not present in `models` raises `ValueError` inside the activity. + +## Retries + +`TemporalAgent` disables Strands' built-in `ModelRetryStrategy` so retries are handled exclusively by Temporal. Configure retries via `retry_policy` on `TemporalAgent`, and on the activity options accepted by `workflow.activity_as_tool`, `workflow.activity_as_hook`, and `TemporalMCPClient`: + +```python +from temporalio.common import RetryPolicy + +TemporalAgent( + start_to_close_timeout=timedelta(seconds=60), + retry_policy=RetryPolicy(maximum_attempts=3), +) +``` + +Passing `retry_strategy=...` to `TemporalAgent(...)` raises `ValueError`; remove the argument (or pass `retry_strategy=None`) and put the retry config on the activity options instead. + +## Snapshots + +`TemporalAgent.take_snapshot()` and `TemporalAgent.load_snapshot()` raise `NotImplementedError`. Temporal's event history already persists workflow state durably at a finer granularity than Strands snapshots, so calling either inside a workflow is redundant. + +## Structured Output + +Like Strands `Agent`, `TemporalAgent` supports structured output with `structured_output_model`. The plugin defaults to [`pydantic_data_converter`](../pydantic), so Pydantic types easily serialize across the activity and workflow boundary. + +```python +from pydantic import BaseModel + +class PersonInfo(BaseModel): + name: str + age: int + +@workflow.defn +class MyWorkflow: + def __init__(self) -> None: + self.agent = TemporalAgent( + start_to_close_timeout=timedelta(seconds=60), + structured_output_model=PersonInfo, + ) + + @workflow.run + async def run(self, prompt: str) -> PersonInfo: + result = await self.agent.invoke_async(prompt) + return result.structured_output +``` + +## Streaming + +To forward model chunks to external consumers, pass `streaming_topic="..."` to `TemporalAgent` and host a `WorkflowStream` on the workflow. Each `StreamEvent` is published on the named topic from inside the model activity; subscribers read via `WorkflowStreamClient`. Chunks are batched on `streaming_batch_interval` (default 100ms). + +```python +# workflow +@workflow.defn +class MyWorkflow: + def __init__(self) -> None: + self.stream = WorkflowStream() + self.agent = TemporalAgent(streaming_topic="events") + +# client +async for item in WorkflowStreamClient.create(client, workflow_id).subscribe( + ["events"], result_type=StreamEvent, +): + print(item.data) +``` + +## Tools + +Decorate non-deterministic tools with `@activity.defn`, or if you're importing tools from `strands_tools`, wrap them in a thin async function. Then, register the activity on the worker via `Worker(activities=[...])` and pass it to the agent with `workflow.activity_as_tool(activity, **options)` along with any activity options (e.g. `start_to_close_timeout`): + +```python +from strands_tools import shell +from temporalio.contrib.strands import workflow as strands_workflow + +@activity.defn +async def fetch_user(user_id: str) -> dict: + ... + +@activity.defn(name="shell") +async def shell_activity(command: str) -> dict: + return shell.shell(command=command, non_interactive=True) + +# workflow +agent = TemporalAgent( + start_to_close_timeout=timedelta(seconds=60), + tools=[ + strands_workflow.activity_as_tool(fetch_user, start_to_close_timeout=timedelta(seconds=30)), + strands_workflow.activity_as_tool(shell_activity, start_to_close_timeout=timedelta(seconds=15)), + ], +) + +# worker +Worker( + ..., + activities=[fetch_user, shell_activity], + plugins=[StrandsPlugin(models=MODELS)], +) +``` + +## Hooks + +Strands' [hook system](https://strandsagents.com/) (`strands.hooks`) lets you subscribe callbacks to events in the agent lifecycle — invocation start/end, model call before/after, tool call before/after, message added. Pass `hooks=[MyHookProvider()]` to `TemporalAgent`: every single-agent hook event fires in workflow context, so deterministic callbacks just work. + +```python +from strands.hooks import HookProvider, HookRegistry +from strands.hooks.events import AfterToolCallEvent + +class AuditHook(HookProvider): + def register_hooks(self, registry: HookRegistry) -> None: + registry.add_callback(AfterToolCallEvent, self._on_tool_call) + + def _on_tool_call(self, event: AfterToolCallEvent) -> None: + # Pure local state - deterministic across replay. + workflow.logger.info(f"tool {event.tool_use['name']} finished") + +agent = TemporalAgent(start_to_close_timeout=..., hooks=[AuditHook()]) +``` + +Callbacks run in workflow context, so they must be deterministic: no `time.time()`, `uuid.uuid4()`, or I/O — same rules as workflow code. For callbacks that need I/O (audit logging, metrics, alerting), use `workflow.activity_as_hook()` to dispatch the work as a Temporal activity: + +```python +from temporalio.contrib.strands.workflow import activity_as_hook + +@activity.defn +async def persist_tool_call(tool_name: str) -> None: + # I/O safely in an activity. + ... + +class AuditHook(HookProvider): + def register_hooks(self, registry: HookRegistry) -> None: + registry.add_callback( + AfterToolCallEvent, + activity_as_hook( + persist_tool_call, + activity_input=lambda event: event.tool_use["name"], + start_to_close_timeout=timedelta(seconds=10), + ), + ) +``` + +`activity_input` extracts serializable values from the event to pass as the activity's input. Use a dataclass or Pydantic model for multiple values. This is needed because events hold references to the `Agent`, `AgentTool` instances, etc., none of which cross the activity boundary. + +## Human-in-the-loop interrupts + +Strands offers two HITL surfaces; both work with the plugin. In each case, `agent.invoke_async()` returns `AgentResult(stop_reason="interrupt", interrupts=[...])` instead of raising. Pair this with a signal handler that supplies responses, then resume by calling `agent.invoke_async(responses)`. + +### Hook-based interrupts + +A hook on an interruptible event (e.g. `BeforeToolCallEvent`) can pause the agent by calling `event.interrupt(name, reason=...)`. The hook runs in workflow context, so it must be deterministic — no I/O. + +```python +from strands.hooks import HookProvider, HookRegistry +from strands.hooks.events import BeforeToolCallEvent + +class ApprovalHook(HookProvider): + def register_hooks(self, registry: HookRegistry) -> None: + registry.add_callback(BeforeToolCallEvent, self._gate) + + def _gate(self, event: BeforeToolCallEvent) -> None: + if event.interrupt("approval", reason="confirm delete") != "approve": + event.cancel_tool = "denied" + +@workflow.defn +class MyWorkflow: + def __init__(self) -> None: + self.agent = TemporalAgent( + start_to_close_timeout=timedelta(seconds=60), + tools=[delete_thing], + hooks=[ApprovalHook()], + ) + self._approval: str | None = None + + @workflow.signal + def approve(self, response: str) -> None: + self._approval = response + + @workflow.run + async def run(self, prompt: str) -> str: + result = await self.agent.invoke_async(prompt) + if result.stop_reason == "interrupt": + await workflow.wait_condition(lambda: self._approval is not None) + result = await self.agent.invoke_async([ + {"interruptResponse": {"interruptId": result.interrupts[0].id, "response": self._approval}} + ]) + return str(result) +``` + +### Tool-body interrupts + +A `@strands.tool` function can raise `InterruptException(Interrupt(...))` directly. The agent stops with the interrupt, the workflow handles the resume the same way as for hooks. + +```python +from strands import tool +from strands.interrupt import Interrupt, InterruptException + +@tool +def delete_thing(name: str) -> str: + raise InterruptException( + Interrupt(id=f"delete:{name}", name="approval", reason=f"delete {name}?") + ) +``` + +The same works from an `activity_as_tool`-wrapped activity. The plugin's failure converter preserves the `Interrupt` payload across the activity boundary, so `AgentResult.interrupts` is populated just like the in-workflow case: + +```python +from strands.interrupt import Interrupt, InterruptException +from temporalio.contrib.strands.workflow import activity_as_tool + +@activity.defn +async def delete_thing(name: str) -> str: + if not await policy.is_authorized(name): + raise InterruptException( + Interrupt(id=f"delete:{name}", name="approval", reason=f"delete {name}?") + ) + await storage.delete(name) + return f"deleted {name}" + +@workflow.defn +class MyWorkflow: + def __init__(self) -> None: + self.agent = TemporalAgent( + start_to_close_timeout=timedelta(seconds=60), + tools=[activity_as_tool(delete_thing, start_to_close_timeout=timedelta(seconds=10))], + ) +``` + +This relies on the plugin's failure converter, which is installed via the client's data converter. **Attach `StrandsPlugin` to the client** (not just the worker) for activity-tool interrupts to work — workers built from that client pick up the plugin automatically. + +```python +client = await Client.connect("localhost:7233", plugins=[StrandsPlugin(models=MODELS)]) +Worker(client, task_queue="strands", workflows=[MyWorkflow], activities=[delete_thing]) +``` + +## Continue-as-new + +A chat-style workflow accumulates history with every turn and will eventually hit Temporal's per-workflow history limit. `workflow.info().is_continue_as_new_suggested()` flips true once the server decides history has grown large enough; check it after each turn and hand off to a fresh run, carrying `agent.messages` as input: + +```python +from dataclasses import dataclass, field +from strands.types.content import Messages + +@dataclass +class ChatInput: + messages: Messages = field(default_factory=list) + +@workflow.defn +class ChatWorkflow: + def __init__(self) -> None: + self._pending: list[str] = [] + self._done = False + + @workflow.signal + def user_says(self, prompt: str) -> None: + self._pending.append(prompt) + + @workflow.signal + def end_chat(self) -> None: + self._done = True + + @workflow.run + async def run(self, input: ChatInput) -> None: + agent = TemporalAgent( + start_to_close_timeout=timedelta(seconds=60), + messages=list(input.messages), + ) + while True: + await workflow.wait_condition(lambda: self._pending or self._done) + if self._done: + return + await agent.invoke_async(self._pending.pop(0)) + if workflow.info().is_continue_as_new_suggested(): + workflow.continue_as_new(ChatInput(messages=agent.messages)) +``` + +## MCP + +`StrandsPlugin(mcp_clients=...)` takes a mapping of `name → MCPClient factory`, mirroring the `models=` pattern. The plugin registers a per-server `{name}-call-tool` activity and connects at worker startup to enumerate tools. Workflow-side, `TemporalMCPClient(server="name")` is a pure handle: it references the server by name and carries the per-call activity options. + +```python +from mcp import StdioServerParameters, stdio_client +from strands.tools.mcp.mcp_client import MCPClient +from temporalio.contrib.strands import TemporalMCPClient + +# workflow +@workflow.defn +class MyWorkflow: + def __init__(self) -> None: + echo = TemporalMCPClient(server="echo", start_to_close_timeout=timedelta(seconds=30)) + self.agent = TemporalAgent( + start_to_close_timeout=timedelta(seconds=60), + tools=[echo], + ) + +# worker +Worker( + ..., + plugins=[StrandsPlugin( + mcp_clients={ + "echo": lambda: MCPClient( + lambda: stdio_client( + StdioServerParameters(command="...", args=[...]), + ), + ), + }, + )], +) +``` + +Each factory returns a fully configured `MCPClient`, so you can pass options like `tool_filters`, `prefix`, `elicitation_callback`, or `tasks_config` to it. The plugin connects to each MCP server once at worker startup to enumerate tools. The schema is frozen for the worker's lifetime; restart workers to pick up MCP-server changes. If a server is unavailable at startup, the worker fails to start. + +To amortize connection setup, the `{name}-call-tool` activity keeps a worker-process MCP connection open between calls and reuses it. The connection is disconnected after it sits idle for `mcp_connection_idle_timeout` (default 5 minutes); the timer resets on every reuse: + +```python +StrandsPlugin( + mcp_clients={"echo": lambda: MCPClient(...)}, + mcp_connection_idle_timeout=timedelta(seconds=30), +) +``` + +## Observability + +`StrandsPlugin` composes cleanly with [`OpenTelemetryPlugin`](../opentelemetry). Register `OpenTelemetryPlugin` on the client (workers built from that client pick it up automatically) and `StrandsPlugin` on the worker. You'll get OTel spans around the model, tool, and MCP activities the plugin schedules, plus any spans Strands itself emits inside `invoke_async`: + +```python +import opentelemetry.trace +from temporalio.contrib.opentelemetry import OpenTelemetryPlugin, create_tracer_provider + +opentelemetry.trace.set_tracer_provider(create_tracer_provider()) + +client = await Client.connect("localhost:7233", plugins=[OpenTelemetryPlugin()]) + +Worker( + client, + task_queue="strands", + workflows=[MyWorkflow], + plugins=[StrandsPlugin(models=MODELS)], +) +``` + +Set the tracer provider before connecting the client. See the [OpenTelemetry plugin README](../opentelemetry) for exporter setup. diff --git a/temporalio/contrib/strands/__init__.py b/temporalio/contrib/strands/__init__.py new file mode 100644 index 000000000..39a8e7401 --- /dev/null +++ b/temporalio/contrib/strands/__init__.py @@ -0,0 +1,13 @@ +"""Temporal integration for the Strands Agents SDK.""" + +from . import workflow +from ._plugin import StrandsPlugin +from ._temporal_agent import TemporalAgent +from ._temporal_mcp_client import TemporalMCPClient + +__all__ = [ + "StrandsPlugin", + "TemporalAgent", + "TemporalMCPClient", + "workflow", +] diff --git a/temporalio/contrib/strands/_failure_converter.py b/temporalio/contrib/strands/_failure_converter.py new file mode 100644 index 000000000..c387f47f4 --- /dev/null +++ b/temporalio/contrib/strands/_failure_converter.py @@ -0,0 +1,69 @@ +"""Failure converter for Strands-specific exceptions.""" + +from strands.interrupt import InterruptException +from strands.types.exceptions import ( + ContextWindowOverflowException, + MaxTokensReachedException, + SessionException, + StructuredOutputException, +) + +import temporalio.api.failure.v1 +from temporalio.converter import DefaultFailureConverter, PayloadConverter +from temporalio.exceptions import ApplicationError + +# Activity-side: when a Strands ``InterruptException`` would otherwise be +# serialized by the default converter, the ``Interrupt`` payload on +# ``exc.interrupt`` is dropped (it lives on the instance, not in the +# serialized ApplicationError). We translate to a typed ApplicationError so +# the interrupt data survives the activity boundary and the workflow side +# can rebuild a real ``Interrupt``. +STRANDS_INTERRUPT_TYPE = "StrandsInterrupt" + +# Strands' model/session exceptions that are deterministic failures (token +# limits, context overflow, structured-output validation, session I/O). They +# won't succeed on retry, so they cross the boundary as non-retryable typed +# ApplicationErrors. TemporalAgent.invoke_async rewraps these as +# StrandsWorkflowError on the workflow side so users can `except` cleanly. +_TERMINAL_EXCEPTIONS: tuple[type[BaseException], ...] = ( + MaxTokensReachedException, + ContextWindowOverflowException, + StructuredOutputException, + SessionException, +) + + +class StrandsFailureConverter(DefaultFailureConverter): + """Failure converter that preserves Strands exception payloads and retryability.""" + + def to_failure( + self, + exception: BaseException, + payload_converter: PayloadConverter, + failure: temporalio.api.failure.v1.Failure, + ) -> None: + """Translate Strands exceptions to typed ApplicationErrors.""" + if isinstance(exception, InterruptException): + super().to_failure( + ApplicationError( + f"interrupt:{exception.interrupt.name}", + exception.interrupt.to_dict(), + type=STRANDS_INTERRUPT_TYPE, + non_retryable=True, + ), + payload_converter, + failure, + ) + return + if isinstance(exception, _TERMINAL_EXCEPTIONS): + super().to_failure( + ApplicationError( + str(exception), + type=type(exception).__name__, + non_retryable=True, + ), + payload_converter, + failure, + ) + return + super().to_failure(exception, payload_converter, failure) diff --git a/temporalio/contrib/strands/_heartbeat_decorator.py b/temporalio/contrib/strands/_heartbeat_decorator.py new file mode 100644 index 000000000..7c5b9193d --- /dev/null +++ b/temporalio/contrib/strands/_heartbeat_decorator.py @@ -0,0 +1,38 @@ +import asyncio +from collections.abc import Awaitable, Callable +from functools import wraps +from typing import Any, TypeVar, cast + +from temporalio import activity + +F = TypeVar("F", bound=Callable[..., Awaitable[Any]]) + + +def auto_heartbeater(fn: F) -> F: + """Decorator that heartbeats at half the activity's heartbeat timeout.""" + + @wraps(fn) + async def wrapper(*args: Any, **kwargs: Any) -> Any: + heartbeat_timeout = activity.info().heartbeat_timeout + heartbeat_task = None + if heartbeat_timeout: + heartbeat_task = asyncio.create_task( + _heartbeat_every(heartbeat_timeout.total_seconds() / 2) + ) + try: + return await fn(*args, **kwargs) + finally: + if heartbeat_task: + heartbeat_task.cancel() + try: + await heartbeat_task + except asyncio.CancelledError: + pass + + return cast(F, wrapper) + + +async def _heartbeat_every(delay: float) -> None: + while True: + await asyncio.sleep(delay) + activity.heartbeat() diff --git a/temporalio/contrib/strands/_model_activity.py b/temporalio/contrib/strands/_model_activity.py new file mode 100644 index 000000000..fba30658d --- /dev/null +++ b/temporalio/contrib/strands/_model_activity.py @@ -0,0 +1,106 @@ +from collections.abc import AsyncIterable, Callable +from dataclasses import dataclass, field +from datetime import timedelta +from typing import Any + +from strands.models import Model +from strands.types.streaming import StreamEvent + +from temporalio import activity +from temporalio.contrib.strands._heartbeat_decorator import auto_heartbeater +from temporalio.contrib.workflow_streams import WorkflowStreamClient + + +# Fields are typed as Any because strands TypedDicts (Message, ToolSpec) use +# NotRequired, which Python < 3.11's get_type_hints leaks through unchanged +# and the default JSON converter then fails to deserialize. Values flow +# through unchanged to ``Model.stream`` which accepts the raw dicts. +@dataclass +class _InvokeModelInput: + model_name: str | None + messages: Any + invocation_state: dict[str, Any] = field(default_factory=dict) + tool_specs: Any = None + system_prompt: str | None = None + tool_choice: Any = None + system_prompt_content: Any = None + + +@dataclass +class _StreamingInvokeModelInput(_InvokeModelInput): + streaming_topic: str = "" + streaming_batch_interval_seconds: float = 0.1 + + +class ModelActivity: + """Holds the registered model factories and exposes the model activities.""" + + def __init__( + self, + factories: dict[str, Callable[[], Model]], + *, + default_name: str | None = None, + ) -> None: + """Store the factories; models are constructed lazily on first use. + + ``default_name`` is set only by the plugin's own auto-registered + ``BedrockModel`` default. User-supplied ``models`` leave it ``None``, + which forces every ``TemporalAgent`` to specify ``model=`` explicitly. + """ + self._factories = factories + self._default_name = default_name + self._models: dict[str, Model] = {} + + def _get_model(self, name: str | None) -> Model: + if name is None: + if self._default_name is None: + raise ValueError( + f"TemporalAgent was constructed without an explicit `model`, " + f"but the plugin was configured with user-supplied `models=`. " + f"Pass model='...' to TemporalAgent. " + f"Known: {sorted(self._factories)}" + ) + name = self._default_name + if name not in self._models: + if name not in self._factories: + raise ValueError( + f"Unknown model name {name!r}. Known: {sorted(self._factories)}" + ) + self._models[name] = self._factories[name]() + return self._models[name] + + @activity.defn + @auto_heartbeater + async def invoke_model(self, input: _InvokeModelInput) -> list[StreamEvent]: + """Run the named model and return its stream events as a list.""" + model = self._get_model(input.model_name) + return [event async for event in _stream(model, input)] + + @activity.defn + @auto_heartbeater + async def invoke_model_streaming( + self, input: _StreamingInvokeModelInput + ) -> list[StreamEvent]: + """Run the named model and publish each stream event to a WorkflowStream.""" + model = self._get_model(input.model_name) + events: list[StreamEvent] = [] + stream = WorkflowStreamClient.from_within_activity( + batch_interval=timedelta(seconds=input.streaming_batch_interval_seconds), + ) + topic = stream.topic(input.streaming_topic) + async with stream: + async for event in _stream(model, input): + events.append(event) + topic.publish(event) + return events + + +def _stream(model: Model, input: _InvokeModelInput) -> AsyncIterable[StreamEvent]: + return model.stream( + input.messages, + input.tool_specs, + input.system_prompt, + tool_choice=input.tool_choice, + system_prompt_content=input.system_prompt_content, + invocation_state=input.invocation_state, + ) diff --git a/temporalio/contrib/strands/_plugin.py b/temporalio/contrib/strands/_plugin.py new file mode 100644 index 000000000..b6f7db2ff --- /dev/null +++ b/temporalio/contrib/strands/_plugin.py @@ -0,0 +1,121 @@ +from collections.abc import AsyncGenerator, Callable +from contextlib import asynccontextmanager +from dataclasses import replace +from datetime import timedelta + +from strands.models import BedrockModel, Model +from strands.tools.mcp import MCPClient + +from temporalio.contrib.pydantic import pydantic_data_converter +from temporalio.converter import DataConverter, DefaultPayloadConverter +from temporalio.plugin import SimplePlugin +from temporalio.worker import WorkflowRunner +from temporalio.worker.workflow_sandbox import SandboxedWorkflowRunner + +from ._failure_converter import StrandsFailureConverter +from ._model_activity import ModelActivity +from ._temporal_mcp_client import ( + _evict_connection, + build_call_tool_activity, + clear_cache, + populate_cache, +) + + +class StrandsPlugin(SimplePlugin): + """Temporal Worker plugin for the Strands Agents SDK. + + When ``models`` is supplied, registers a single pair of model invocation + activities; each call carries the chosen ``model_name`` in its input and + the worker resolves it against the factories. Factories are called lazily + on first use, then cached for the worker's lifetime. Use the same name in + ``TemporalAgent(model=...)`` inside the workflow. + + When ``mcp_clients`` is supplied, registers a per-server + ``{server}-call-tool`` activity for each entry and, at worker startup, + connects to each MCP server to cache its tool list. Workflow-side + ``TemporalMCPClient(server="...").load_tools()`` reads from the cache. + + ``mcp_connection_idle_timeout`` controls how long a worker-process MCP + connection is kept open between ``call-tool`` activities before it is + disconnected; the timer resets on every reuse. Defaults to 5 minutes. + """ + + def __init__( + self, + *, + models: dict[str, Callable[[], Model]] | None = None, + mcp_clients: dict[str, Callable[[], MCPClient]] | None = None, + mcp_connection_idle_timeout: timedelta | None = None, + ) -> None: + """Build the plugin from optional model and MCP transport factories. + + If ``models`` is omitted, registers a single ``BedrockModel()`` factory + under the name ``"bedrock"``, matching Strands' own implicit default. + """ + default_name: str | None = None + if models is None: + models = {"bedrock": lambda: BedrockModel()} + default_name = "bedrock" + activities: list[Callable] = [] + if models: + ma = ModelActivity(models, default_name=default_name) + activities.extend([ma.invoke_model, ma.invoke_model_streaming]) + + mcp_clients = mcp_clients or {} + for server, client_factory in mcp_clients.items(): + activities.append( + build_call_tool_activity( + server, client_factory, mcp_connection_idle_timeout + ) + ) + + @asynccontextmanager + async def run_context() -> AsyncGenerator[None, None]: + for server, client_factory in mcp_clients.items(): + await populate_cache(server, client_factory) + try: + yield + finally: + for server in mcp_clients: + await _evict_connection(server) + clear_cache(server) + + super().__init__( + "aws.StrandsPlugin", + workflow_runner=_workflow_runner, + data_converter=_data_converter, + activities=activities or None, + run_context=run_context, + ) + + +def _workflow_runner(runner: WorkflowRunner | None) -> WorkflowRunner: + if not runner: + raise ValueError("No WorkflowRunner provided to the Strands plugin.") + if isinstance(runner, SandboxedWorkflowRunner): + return replace( + runner, + restrictions=runner.restrictions.with_passthrough_modules( + "strands", + "strands_tools", + "mcp", + # ``pydantic`` is already in the SDK default passthrough; extend it + # to its compiled validation core and ``Annotated`` helper. + "pydantic_core", + "annotated_types", + ), + ) + return runner + + +def _data_converter(converter: DataConverter | None) -> DataConverter: + if ( + converter is None + or converter.payload_converter_class is DefaultPayloadConverter + ): + return replace( + pydantic_data_converter, + failure_converter_class=StrandsFailureConverter, + ) + return converter diff --git a/temporalio/contrib/strands/_temporal_activity_tool.py b/temporalio/contrib/strands/_temporal_activity_tool.py new file mode 100644 index 000000000..bb838834e --- /dev/null +++ b/temporalio/contrib/strands/_temporal_activity_tool.py @@ -0,0 +1,95 @@ +import inspect +import json +from collections.abc import Callable +from typing import Any + +from strands.interrupt import Interrupt +from strands.tools.decorator import FunctionToolMetadata +from strands.types._events import ToolInterruptEvent, ToolResultEvent +from strands.types.tools import AgentTool, ToolGenerator, ToolResult, ToolSpec, ToolUse + +from temporalio import activity, workflow +from temporalio.exceptions import ActivityError, ApplicationError + +from ._failure_converter import STRANDS_INTERRUPT_TYPE + + +class TemporalActivityTool(AgentTool): + """Strands ``AgentTool`` whose body dispatches a Temporal activity.""" + + def __init__(self, activity_fn: Callable, options: dict[str, Any]) -> None: + """Capture the target activity and the options to invoke it with.""" + super().__init__() + defn = activity._Definition.from_callable(activity_fn) + if not defn or not defn.name: + raise ValueError("activity_fn must be decorated with @activity.defn") + self._activity_name = defn.name + self._options = options + self._signature = inspect.signature(activity_fn) + spec = FunctionToolMetadata(activity_fn).extract_metadata() + spec["name"] = self._activity_name + self._spec: ToolSpec = spec + + @property + def tool_name(self) -> str: + """Name of the underlying Temporal activity.""" + return self._activity_name + + @property + def tool_spec(self) -> ToolSpec: + """Strands ToolSpec derived from the activity's signature.""" + return self._spec + + @property + def tool_type(self) -> str: + """Tool kind identifier used by Strands.""" + return "temporal_activity" + + async def stream( + self, + tool_use: ToolUse, + invocation_state: dict[str, Any], + **kwargs: Any, + ) -> ToolGenerator: + """Execute the tool by dispatching to the bound Temporal activity.""" + bound = self._signature.bind(**tool_use["input"]) + bound.apply_defaults() + positional = list(bound.arguments.values()) + try: + if not positional: + result = await workflow.execute_activity( + self._activity_name, **self._options + ) + elif len(positional) == 1: + result = await workflow.execute_activity( + self._activity_name, positional[0], **self._options + ) + else: + result = await workflow.execute_activity( + self._activity_name, args=positional, **self._options + ) + except ActivityError as e: + cause = e.__cause__ + if ( + isinstance(cause, ApplicationError) + and cause.type == STRANDS_INTERRUPT_TYPE + ): + yield ToolInterruptEvent(tool_use, [Interrupt(**cause.details[0])]) + return + raise + yield ToolResultEvent( + ToolResult( + toolUseId=tool_use["toolUseId"], + status="success", + content=[{"text": _to_text(result)}], + ) + ) + + +def _to_text(result: Any) -> str: + if isinstance(result, str): + return result + try: + return json.dumps(result) + except (TypeError, ValueError): + return str(result) diff --git a/temporalio/contrib/strands/_temporal_agent.py b/temporalio/contrib/strands/_temporal_agent.py new file mode 100644 index 000000000..9bc1beb31 --- /dev/null +++ b/temporalio/contrib/strands/_temporal_agent.py @@ -0,0 +1,85 @@ +from datetime import timedelta +from typing import Any + +from strands import Agent + +from temporalio.common import Priority, RetryPolicy +from temporalio.workflow import ActivityCancellationType, VersioningIntent + +from ._temporal_model import TemporalModel + +_SNAPSHOT_DISABLED = ( + "TemporalAgent disables take_snapshot()/load_snapshot(). Temporal " + "workflows already persist agent state durably via the event history at " + "a finer granularity than Strands snapshots. Remove the snapshot call " + "and rely on Temporal's durable execution instead." +) + + +class TemporalAgent(Agent): + """A Strands ``Agent`` that routes model calls through a Temporal activity. + + ``model`` is the name of a factory registered in + ``StrandsPlugin(models={...})``. The activity options apply to every model + invocation this agent makes. All other keyword arguments are forwarded to + Strands' ``Agent`` (``tools``, ``hooks``, ``system_prompt``, + ``structured_output_model``, ``messages``, etc.). + + Strands' ``retry_strategy`` is disabled; configure retries via + ``retry_policy`` here and on the activity options accepted by + ``activity_as_tool``, ``activity_as_hook``, and ``TemporalMCPClient``. + """ + + def __init__( + self, + *, + model: str | None = None, + task_queue: str | None = None, + schedule_to_close_timeout: timedelta | None = None, + schedule_to_start_timeout: timedelta | None = None, + start_to_close_timeout: timedelta | None = None, + heartbeat_timeout: timedelta | None = None, + retry_policy: RetryPolicy | None = None, + cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, + versioning_intent: VersioningIntent | None = None, + summary: str | None = None, + priority: Priority = Priority.default, + streaming_topic: str | None = None, + streaming_batch_interval: timedelta = timedelta(milliseconds=100), + **agent_kwargs: Any, + ) -> None: + """Build a TemporalAgent from a registered model name and activity options.""" + if agent_kwargs.get("retry_strategy") is not None: + raise ValueError( + "TemporalAgent disables Strands retries; configure retries via " + "retry_policy on TemporalAgent and on the activity options " + "passed to workflow.activity_as_tool, workflow.activity_as_hook, " + "or TemporalMCPClient. Remove retry_strategy from " + "TemporalAgent(...) or pass retry_strategy=None." + ) + agent_kwargs["retry_strategy"] = None + + temporal_model = TemporalModel( + model_name=model, + task_queue=task_queue, + schedule_to_close_timeout=schedule_to_close_timeout, + schedule_to_start_timeout=schedule_to_start_timeout, + start_to_close_timeout=start_to_close_timeout, + heartbeat_timeout=heartbeat_timeout, + retry_policy=retry_policy, + cancellation_type=cancellation_type, + versioning_intent=versioning_intent, + summary=summary, + priority=priority, + streaming_topic=streaming_topic, + streaming_batch_interval=streaming_batch_interval, + ) + super().__init__(model=temporal_model, **agent_kwargs) + + def take_snapshot(self, *_args: Any, **_kwargs: Any) -> Any: + """Disabled; Temporal's event history is the source of truth.""" + raise NotImplementedError(_SNAPSHOT_DISABLED) + + def load_snapshot(self, *_args: Any, **_kwargs: Any) -> Any: + """Disabled; Temporal's event history is the source of truth.""" + raise NotImplementedError(_SNAPSHOT_DISABLED) diff --git a/temporalio/contrib/strands/_temporal_mcp_client.py b/temporalio/contrib/strands/_temporal_mcp_client.py new file mode 100644 index 000000000..71e1f2f7c --- /dev/null +++ b/temporalio/contrib/strands/_temporal_mcp_client.py @@ -0,0 +1,326 @@ +from __future__ import annotations + +import asyncio +from collections.abc import Callable, Sequence +from dataclasses import dataclass, field +from datetime import timedelta +from typing import Any + +from mcp import ClientSession +from mcp.types import PaginatedRequestParams, Tool +from strands.tools import ToolProvider +from strands.tools.mcp import MCPAgentTool, MCPClient +from strands.tools.mcp.mcp_types import MCPToolResult +from strands.types.tools import AgentTool + +from temporalio import activity +from temporalio.common import Priority, RetryPolicy +from temporalio.workflow import ActivityCancellationType, VersioningIntent + + +@dataclass +class _MCPToolInfo: + name: str + description: str + input_schema: dict[str, Any] + output_schema: dict[str, Any] | None = None + + +@dataclass +class _CallToolArgs: + tool_name: str + arguments: dict[str, Any] = field(default_factory=dict) + tool_use_id: str = "" + + +# Server name -> cached tool list. Populated by ``_populate_cache`` at worker +# startup and read by ``TemporalMCPClient.load_tools()`` inside the workflow +# sandbox. ``temporalio`` is in the SDK's default sandbox passthrough, so this +# dict is shared between worker process and workflow execution. +_TOOL_CACHE: dict[str, list[_MCPToolInfo]] = {} + + +class TemporalMCPClient(ToolProvider): + """Workflow-side handle to an MCP server registered on the worker. + + The transport factory and tool discovery live worker-side via + ``StrandsPlugin(mcp_clients={"server": lambda: ...})``. This handle only + carries the server name (which selects the registered factory) and the + per-call activity options. + + Construct once at module level and pass to ``TemporalAgent(tools=[...])`` + inside the workflow. Multiple handles may reference the same server name + with different activity options. + """ + + def __init__( + self, + server: str, + *, + task_queue: str | None = None, + schedule_to_close_timeout: timedelta | None = None, + schedule_to_start_timeout: timedelta | None = None, + start_to_close_timeout: timedelta | None = None, + heartbeat_timeout: timedelta | None = None, + retry_policy: RetryPolicy | None = None, + cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, + versioning_intent: VersioningIntent | None = None, + summary: str | None = None, + priority: Priority = Priority.default, + ) -> None: + """Configure the server name and activity options.""" + self._server = server + self._options: dict[str, Any] = { + "task_queue": task_queue, + "schedule_to_close_timeout": schedule_to_close_timeout, + "schedule_to_start_timeout": schedule_to_start_timeout, + "start_to_close_timeout": start_to_close_timeout, + "heartbeat_timeout": heartbeat_timeout, + "retry_policy": retry_policy, + "cancellation_type": cancellation_type, + "versioning_intent": versioning_intent, + "summary": summary, + "priority": priority, + } + + @property + def server(self) -> str: + """MCP server name used as the activity prefix.""" + return self._server + + async def load_tools(self, **_kwargs: Any) -> Sequence[AgentTool]: + """Return TemporalMCPTool wrappers for tools cached at worker startup.""" + from ._temporal_mcp_tool import TemporalMCPTool + + infos = _TOOL_CACHE.get(self._server, []) + return [TemporalMCPTool(self._server, info, self._options) for info in infos] + + def add_consumer(self, consumer_id: Any, **_kwargs: Any) -> None: + """No-op; consumer tracking is handled by the underlying MCP client.""" + return None + + def remove_consumer(self, consumer_id: Any, **_kwargs: Any) -> None: + """No-op; consumer tracking is handled by the underlying MCP client.""" + return None + + +# Use MCP sessions directly instead of MCPClient's background-thread helpers. +# Those helpers route calls through cross-loop futures that are unreliable on +# Python 3.10 when invoked from Temporal's async worker/activity event loops. +async def _list_mcp_tools(client: MCPClient) -> Sequence[Tool]: + async with client._transport_callable() as (read_stream, write_stream, *_): + async with ClientSession( + read_stream, + write_stream, + elicitation_callback=client._elicitation_callback, + ) as session: + await session.initialize() + tools: list[Tool] = [] + pagination_token = None + while True: + page = await session.list_tools( + params=PaginatedRequestParams(cursor=pagination_token) + if pagination_token is not None + else None + ) + tools.extend(page.tools) + pagination_token = page.nextCursor + if pagination_token is None: + return tools + + +def _agent_tool_for_filtering(client: MCPClient, tool: Tool) -> MCPAgentTool: + if client._prefix: + return MCPAgentTool(tool, client, name_override=f"{client._prefix}_{tool.name}") + return MCPAgentTool(tool, client) + + +async def populate_cache(server: str, client_factory: Callable[[], MCPClient]) -> None: + """Connect to the MCP server, list tools, fill ``_TOOL_CACHE``.""" + client = client_factory() + infos: list[_MCPToolInfo] = [] + for tool in await _list_mcp_tools(client): + if not client._should_include_tool_with_filters( + _agent_tool_for_filtering(client, tool), + client._tool_filters, + ): + continue + infos.append( + _MCPToolInfo( + name=tool.name, + description=tool.description or "", + input_schema=tool.inputSchema, + output_schema=tool.outputSchema, + ) + ) + _TOOL_CACHE[server] = infos + + +def clear_cache(server: str) -> None: + """Drop the cached tool list for ``server``.""" + _TOOL_CACHE.pop(server, None) + + +# Default for how long an idle MCP connection stays open before it is +# disconnected. The timer resets on every call that reuses the connection. +# Override per worker via ``StrandsPlugin(mcp_connection_idle_timeout=...)``. +_MCP_CONNECTION_IDLE = timedelta(minutes=5) + +# Server name -> live connection held open in the activity worker process. +# Activities run in the worker process , so this module state is shared across activity invocations on the worker +_CONNECTIONS: dict[str, _ConnectionRecord] = {} + + +class _ConnectionRecord: + """A single MCP session held open by a dedicated owner task. + + The MCP transport and ``ClientSession`` are anyio context managers whose + cancel scope is bound to the task that enters them, so they must be entered + and exited in the same task. ``_run`` owns that task for the connection's + whole lifetime; ``call_tool`` activities on the same event loop invoke + ``session.call_tool`` directly (MCP multiplexes concurrent requests by id). + """ + + def __init__( + self, + server: str, + client_factory: Callable[[], MCPClient], + idle_timeout: timedelta, + ) -> None: + loop = asyncio.get_running_loop() + self._server = server + self._idle_timeout = idle_timeout + self._stop = asyncio.Event() + self._ready: asyncio.Future[tuple[MCPClient, ClientSession]] = ( + loop.create_future() + ) + self._idle_handle: asyncio.TimerHandle | None = None + self._idle_task: asyncio.Task[None] | None = None + self._inflight = 0 + self._owner = asyncio.create_task(self._run(client_factory)) + + async def _run(self, client_factory: Callable[[], MCPClient]) -> None: + client = client_factory() + try: + async with client._transport_callable() as (read_stream, write_stream, *_): + async with ClientSession( + read_stream, + write_stream, + elicitation_callback=client._elicitation_callback, + ) as session: + await session.initialize() + self._ready.set_result((client, session)) + await self._stop.wait() + except BaseException as err: + # A failed connect should not be cached; drop it so the next call + # retries instead of awaiting a permanently rejected future. + if not self._ready.done(): + self._ready.set_exception(err) + _CONNECTIONS.pop(self._server, None) + raise + + def acquire(self) -> None: + """Mark a call in flight; pause idle eviction while calls are active.""" + self._inflight += 1 + if self._idle_handle is not None: + self._idle_handle.cancel() + self._idle_handle = None + + def release(self) -> None: + """Mark a call done; arm idle eviction once no calls remain in flight.""" + self._inflight -= 1 + # Only the record still cached under this server arms a timer; a record + # already evicted or never cached must not schedule one, or it could + # later evict a different, healthy connection for the same server. + if self._inflight == 0 and _CONNECTIONS.get(self._server) is self: + loop = asyncio.get_running_loop() + self._idle_handle = loop.call_later( + self._idle_timeout.total_seconds(), self._on_idle + ) + + def _on_idle(self) -> None: + self._idle_task = asyncio.ensure_future(self._maybe_evict()) + + async def _maybe_evict(self) -> None: + # A call may have acquired the connection between the timer firing and + # this task running; only evict if it is still idle. + if self._inflight == 0: + await _evict_connection(self._server) + + async def aclose(self) -> None: + """Signal the owner task to exit its context managers and wait for it.""" + if self._idle_handle is not None: + self._idle_handle.cancel() + self._idle_handle = None + self._stop.set() + try: + await self._owner + except BaseException: + pass + + async def session(self) -> tuple[MCPClient, ClientSession]: + """Return the live client and session, or raise the connect failure.""" + return await self._ready + + +async def get_connection( + server: str, client_factory: Callable[[], MCPClient], idle_timeout: timedelta +) -> tuple[MCPClient, ClientSession, _ConnectionRecord]: + """Return the cached session for ``server``, opening one lazily if needed. + + Concurrent first-callers dedupe onto a single connect handshake by awaiting + the same record. The returned record is acquired; the caller must + ``release()`` it once the call completes so idle eviction can resume. + """ + record = _CONNECTIONS.get(server) + if record is None: + record = _ConnectionRecord(server, client_factory, idle_timeout) + _CONNECTIONS[server] = record + record.acquire() + try: + client, session = await record.session() + except BaseException: + record.release() + raise + return client, session, record + + +async def _evict_connection(server: str) -> None: + record = _CONNECTIONS.pop(server, None) + if record is not None: + await record.aclose() + + +def build_call_tool_activity( + server: str, + client_factory: Callable[[], MCPClient], + idle_timeout: timedelta | None = None, +) -> Callable: + """Return the per-server ``{server}-call-tool`` activity for registration. + + Reuses a worker-process MCP session opened lazily through ``client_factory``. + Idle connections are disconnected after ``idle_timeout`` (defaults to + ``_MCP_CONNECTION_IDLE``). + """ + idle = idle_timeout if idle_timeout is not None else _MCP_CONNECTION_IDLE + + @activity.defn(name=f"{server}-call-tool") + async def call_tool(args: _CallToolArgs) -> MCPToolResult: + try: + client, session, record = await get_connection(server, client_factory, idle) + except Exception as err: + # Connecting failed; map to a tool error result like a call would. + return client_factory()._handle_tool_execution_error(args.tool_use_id, err) + try: + result = await session.call_tool(args.tool_name, args.arguments) + return client._handle_tool_result(args.tool_use_id, result) + except Exception as err: + # The session may be broken; drop it so the next call reconnects. + await _evict_connection(server) + return client._handle_tool_execution_error(args.tool_use_id, err) + finally: + # No more in-flight call on this connection; let idle eviction + # resume (no-op if the connection was just evicted above). + record.release() + + return call_tool diff --git a/temporalio/contrib/strands/_temporal_mcp_tool.py b/temporalio/contrib/strands/_temporal_mcp_tool.py new file mode 100644 index 000000000..885b1a7e2 --- /dev/null +++ b/temporalio/contrib/strands/_temporal_mcp_tool.py @@ -0,0 +1,65 @@ +from typing import Any + +from strands.types._events import ToolResultEvent +from strands.types.tools import AgentTool, ToolGenerator, ToolResult, ToolSpec, ToolUse + +from temporalio import workflow + +from ._temporal_mcp_client import _CallToolArgs, _MCPToolInfo + + +class TemporalMCPTool(AgentTool): + """Workflow-side stub for a single MCP tool; dispatches to an activity.""" + + def __init__( + self, + server: str, + info: _MCPToolInfo, + options: dict[str, Any], + ) -> None: + """Bind this tool to a server, its cached info, and activity options.""" + super().__init__() + self._server = server + self._info = info + self._options = options + + @property + def tool_name(self) -> str: + """Name of the underlying MCP tool.""" + return self._info.name + + @property + def tool_spec(self) -> ToolSpec: + """Strands ToolSpec built from the cached MCP tool info.""" + spec: ToolSpec = { + "name": self._info.name, + "description": self._info.description + or f"Tool which performs {self._info.name}", + "inputSchema": {"json": self._info.input_schema}, + } + if self._info.output_schema: + spec["outputSchema"] = {"json": self._info.output_schema} + return spec + + @property + def tool_type(self) -> str: + """Tool kind identifier used by Strands.""" + return "temporal_mcp" + + async def stream( + self, + tool_use: ToolUse, + invocation_state: dict[str, Any], + **kwargs: Any, + ) -> ToolGenerator: + """Execute the tool by dispatching to the per-server call-tool activity.""" + result: ToolResult = await workflow.execute_activity( + f"{self._server}-call-tool", + _CallToolArgs( + tool_name=self._info.name, + arguments=tool_use["input"], + tool_use_id=tool_use["toolUseId"], + ), + **self._options, + ) + yield ToolResultEvent(result) diff --git a/temporalio/contrib/strands/_temporal_model.py b/temporalio/contrib/strands/_temporal_model.py new file mode 100644 index 000000000..29e5c63a2 --- /dev/null +++ b/temporalio/contrib/strands/_temporal_model.py @@ -0,0 +1,148 @@ +import json +from collections.abc import AsyncIterable +from datetime import timedelta +from typing import Any + +from strands.models import Model +from strands.types.content import Messages, SystemContentBlock +from strands.types.streaming import StreamEvent +from strands.types.tools import ToolChoice, ToolSpec + +from temporalio import workflow +from temporalio.common import Priority, RetryPolicy +from temporalio.workflow import ActivityCancellationType, VersioningIntent + +from ._model_activity import ( + ModelActivity, + _InvokeModelInput, + _StreamingInvokeModelInput, +) + + +def _filter_serializable(state: dict[str, Any]) -> dict[str, Any]: + """Keep invocation_state entries that JSON-serialize; drop the rest with a debug log.""" + clean: dict[str, Any] = {} + dropped: list[str] = [] + for key, value in state.items(): + try: + json.dumps(value) + except (TypeError, ValueError): + dropped.append(key) + continue + clean[key] = value + if dropped: + workflow.logger.debug( + f"Dropping non-serializable invocation_state keys: {dropped}" + ) + return clean + + +class TemporalModel(Model): + """A Strands ``Model`` that runs ``stream()`` as a Temporal activity. + + ``model_name`` selects which factory the plugin will invoke worker-side; it + must match a key in ``StrandsPlugin(models={...})``. Construction of this + ``TemporalModel`` itself does no I/O, so it is safe to instantiate at + module level. + + When ``streaming_topic`` is set, each ``StreamEvent`` is also published to + the named topic on the workflow's + :class:`temporalio.contrib.workflow_streams.WorkflowStream` for external + consumers. + """ + + def __init__( + self, + model_name: str | None = None, + *, + task_queue: str | None = None, + schedule_to_close_timeout: timedelta | None = None, + schedule_to_start_timeout: timedelta | None = None, + start_to_close_timeout: timedelta | None = None, + heartbeat_timeout: timedelta | None = None, + retry_policy: RetryPolicy | None = None, + cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, + versioning_intent: VersioningIntent | None = None, + summary: str | None = None, + priority: Priority = Priority.default, + streaming_topic: str | None = None, + streaming_batch_interval: timedelta = timedelta(milliseconds=100), + ) -> None: + """Configure the model name, activity options, and streaming settings.""" + self._model_name = model_name + self._streaming_topic = streaming_topic + self._streaming_batch_interval = streaming_batch_interval + self._options: dict[str, Any] = { + "task_queue": task_queue, + "schedule_to_close_timeout": schedule_to_close_timeout, + "schedule_to_start_timeout": schedule_to_start_timeout, + "start_to_close_timeout": start_to_close_timeout, + "heartbeat_timeout": heartbeat_timeout, + "retry_policy": retry_policy, + "cancellation_type": cancellation_type, + "versioning_intent": versioning_intent, + "summary": summary, + "priority": priority, + } + + def update_config(self, **_model_config: Any) -> None: + """No-op; the real model is configured worker-side via the plugin's factories.""" + return None + + def get_config(self) -> dict[str, Any]: + """Return an empty config; configuration lives on the worker-side model.""" + return {} + + def structured_output(self, *_args: Any, **_kwargs: Any) -> Any: + """Not supported; use ``TemporalAgent(structured_output_model=...)`` instead.""" + raise NotImplementedError( + "TemporalModel.structured_output is not supported. Use " + "TemporalAgent(structured_output_model=...) which routes structured " + "output through stream() via the structured_output_tool." + ) + + async def stream( + self, + messages: Messages, + tool_specs: list[ToolSpec] | None = None, + system_prompt: str | None = None, + *, + tool_choice: ToolChoice | None = None, + system_prompt_content: list[SystemContentBlock] | None = None, + invocation_state: dict[str, Any] | None = None, + **kwargs: Any, + ) -> AsyncIterable[StreamEvent]: + """Run the model via the registered Temporal activity and yield events.""" + clean_state = _filter_serializable(invocation_state) if invocation_state else {} + if self._streaming_topic is not None: + events = await workflow.execute_activity_method( + ModelActivity.invoke_model_streaming, + _StreamingInvokeModelInput( + model_name=self._model_name, + messages=messages, + invocation_state=clean_state, + tool_specs=tool_specs, + system_prompt=system_prompt, + tool_choice=tool_choice, + system_prompt_content=system_prompt_content, + streaming_topic=self._streaming_topic, + streaming_batch_interval_seconds=self._streaming_batch_interval.total_seconds(), + ), + **self._options, + ) + else: + events = await workflow.execute_activity_method( + ModelActivity.invoke_model, + _InvokeModelInput( + model_name=self._model_name, + messages=messages, + invocation_state=clean_state, + tool_specs=tool_specs, + system_prompt=system_prompt, + tool_choice=tool_choice, + system_prompt_content=system_prompt_content, + ), + **self._options, + ) + for event in events: + yield event diff --git a/temporalio/contrib/strands/workflow.py b/temporalio/contrib/strands/workflow.py new file mode 100644 index 000000000..98dab1cbc --- /dev/null +++ b/temporalio/contrib/strands/workflow.py @@ -0,0 +1,103 @@ +"""Helpers for wiring Temporal activities into Strands' agent and hook surfaces. + +Both ``activity_as_tool`` and ``activity_as_hook`` produce workflow-side objects +that dispatch user activities via :func:`temporalio.workflow.execute_activity`, +so the I/O actually happens off the workflow. +""" + +from collections.abc import Callable +from datetime import timedelta +from typing import Any, TypeVar + +from strands.hooks import BaseHookEvent, HookCallback +from strands.types.tools import AgentTool + +from temporalio import workflow +from temporalio.common import Priority, RetryPolicy +from temporalio.workflow import ActivityCancellationType, VersioningIntent + +from ._temporal_activity_tool import TemporalActivityTool + + +def activity_as_tool( + activity_fn: Callable, + *, + task_queue: str | None = None, + schedule_to_close_timeout: timedelta | None = None, + schedule_to_start_timeout: timedelta | None = None, + start_to_close_timeout: timedelta | None = None, + heartbeat_timeout: timedelta | None = None, + retry_policy: RetryPolicy | None = None, + cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, + activity_id: str | None = None, + versioning_intent: VersioningIntent | None = None, + summary: str | None = None, + priority: Priority = Priority.default, +) -> AgentTool: + """Wrap a Temporal activity as a Strands tool. + + ``activity_fn`` must be decorated by ``@activity.defn``. All keyword + arguments are forwarded to ``workflow.execute_activity``. + """ + options: dict[str, Any] = { + "task_queue": task_queue, + "schedule_to_close_timeout": schedule_to_close_timeout, + "schedule_to_start_timeout": schedule_to_start_timeout, + "start_to_close_timeout": start_to_close_timeout, + "heartbeat_timeout": heartbeat_timeout, + "retry_policy": retry_policy, + "cancellation_type": cancellation_type, + "activity_id": activity_id, + "versioning_intent": versioning_intent, + "summary": summary, + "priority": priority, + } + return TemporalActivityTool(activity_fn, options) + + +TEvent = TypeVar("TEvent", bound=BaseHookEvent) + + +def activity_as_hook( + activity_fn: Callable, + *, + activity_input: Callable[[TEvent], Any], + task_queue: str | None = None, + schedule_to_close_timeout: timedelta | None = None, + schedule_to_start_timeout: timedelta | None = None, + start_to_close_timeout: timedelta | None = None, + heartbeat_timeout: timedelta | None = None, + retry_policy: RetryPolicy | None = None, + cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, + activity_id: str | None = None, + versioning_intent: VersioningIntent | None = None, + summary: str | None = None, + priority: Priority = Priority.default, +) -> HookCallback[TEvent]: + """Wrap a Temporal activity as a Strands hook callback. + + The returned coroutine, when registered with ``HookRegistry.add_callback``, + dispatches ``activity_fn`` as a Temporal activity each time the associated + event fires. ``activity_input`` is called with the event to produce a + serializable activity input — events themselves are not serializable, since + they hold references to the ``Agent`` and other workflow-bound objects. + All other keyword arguments are forwarded to ``workflow.execute_activity``. + """ + options: dict[str, Any] = { + "task_queue": task_queue, + "schedule_to_close_timeout": schedule_to_close_timeout, + "schedule_to_start_timeout": schedule_to_start_timeout, + "start_to_close_timeout": start_to_close_timeout, + "heartbeat_timeout": heartbeat_timeout, + "retry_policy": retry_policy, + "cancellation_type": cancellation_type, + "activity_id": activity_id, + "versioning_intent": versioning_intent, + "summary": summary, + "priority": priority, + } + + async def callback(event: TEvent) -> None: + await workflow.execute_activity(activity_fn, activity_input(event), **options) + + return callback diff --git a/tests/contrib/strands/common.py b/tests/contrib/strands/common.py new file mode 100644 index 000000000..5ece12a1e --- /dev/null +++ b/tests/contrib/strands/common.py @@ -0,0 +1,10 @@ +from temporalio.api.enums.v1 import EventType +from temporalio.client import WorkflowHistory + + +def get_activities(history: WorkflowHistory) -> list[str]: + return [ + event.activity_task_scheduled_event_attributes.activity_type.name + for event in history.events + if event.event_type == EventType.EVENT_TYPE_ACTIVITY_TASK_SCHEDULED + ] diff --git a/tests/contrib/strands/echo_mcp_server.py b/tests/contrib/strands/echo_mcp_server.py new file mode 100644 index 000000000..9f70075ac --- /dev/null +++ b/tests/contrib/strands/echo_mcp_server.py @@ -0,0 +1,13 @@ +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/tests/contrib/strands/mock_model.py b/tests/contrib/strands/mock_model.py new file mode 100644 index 000000000..5cbb0f89f --- /dev/null +++ b/tests/contrib/strands/mock_model.py @@ -0,0 +1,60 @@ +from __future__ import annotations + +import json +from collections.abc import AsyncIterable +from typing import Any + +from strands.models import Model +from strands.types.streaming import StreamEvent + + +class MockModel(Model): + """Scripted Strands ``Model`` for tests. + + Each entry in ``responses`` is consumed by one ``stream()`` call. A ``str`` + yields a text turn; a ``dict`` of ``{name, input}`` yields a tool-use turn. + """ + + def __init__(self, responses: list[str | dict[str, Any]]) -> None: + self._responses = list(responses) + self._tool_call_index = 0 + + def update_config(self, **_model_config: Any) -> None: + return None + + def get_config(self) -> dict[str, Any]: + return {} + + def structured_output(self, *_args: Any, **_kwargs: Any): + raise NotImplementedError + + async def stream(self, *_args: Any, **_kwargs: Any) -> AsyncIterable[StreamEvent]: + if not self._responses: + raise AssertionError("MockModel script exhausted") + response = self._responses.pop(0) + + yield {"messageStart": {"role": "assistant"}} + + if isinstance(response, str): + yield {"contentBlockDelta": {"delta": {"text": response}}} + yield {"contentBlockStop": {}} + yield {"messageStop": {"stopReason": "end_turn"}} + else: + self._tool_call_index += 1 + yield { + "contentBlockStart": { + "start": { + "toolUse": { + "name": response["name"], + "toolUseId": f"mock-tool-{self._tool_call_index}", + }, + }, + }, + } + yield { + "contentBlockDelta": { + "delta": {"toolUse": {"input": json.dumps(response["input"])}}, + }, + } + yield {"contentBlockStop": {}} + yield {"messageStop": {"stopReason": "tool_use"}} diff --git a/tests/contrib/strands/test_hooks.py b/tests/contrib/strands/test_hooks.py new file mode 100644 index 000000000..19976cb44 --- /dev/null +++ b/tests/contrib/strands/test_hooks.py @@ -0,0 +1,106 @@ +from datetime import timedelta +from uuid import uuid4 + +from strands import tool +from strands.hooks import HookProvider, HookRegistry +from strands.hooks.events import AfterToolCallEvent + +from temporalio import activity, workflow +from temporalio.client import Client +from temporalio.contrib.strands import StrandsPlugin, TemporalAgent +from temporalio.contrib.strands.workflow import activity_as_hook +from temporalio.worker import Replayer, Worker +from tests.contrib.strands.common import get_activities +from tests.contrib.strands.mock_model import MockModel + +# Module-level sink: written by the audit activity, read in assertions. +# Activity bodies run in worker context, not the sandbox, so a plain list is fine. +_AUDIT_LOG: list[str] = [] + + +@activity.defn +async def audit_tool(tool_name: str) -> None: + _AUDIT_LOG.append(tool_name) + + +@tool +def echo(text: str) -> str: + return text + + +class AuditHook(HookProvider): + def __init__(self) -> None: + self.fired_events: list[str] = [] + + def register_hooks(self, registry: HookRegistry, **kwargs: object) -> None: + registry.add_callback(AfterToolCallEvent, self._sync_log) + registry.add_callback( + AfterToolCallEvent, + activity_as_hook( + audit_tool, + activity_input=lambda event: event.tool_use["name"], + start_to_close_timeout=timedelta(seconds=10), + ), + ) + + def _sync_log(self, event: AfterToolCallEvent) -> None: + # Deterministic in-workflow mutation: appends to per-workflow state. + self.fired_events.append(event.tool_use["name"]) + + +@workflow.defn +class HooksWorkflow: + def __init__(self) -> None: + self.hook = AuditHook() + self.agent = TemporalAgent( + model="mock", + start_to_close_timeout=timedelta(seconds=15), + tools=[echo], + hooks=[self.hook], + ) + + @workflow.run + async def run(self, prompt: str) -> list[str]: + await self.agent.invoke_async(prompt) + return self.hook.fired_events + + +async def test_hooks(client: Client): + _AUDIT_LOG.clear() + task_queue = "test_hooks" + plugin = StrandsPlugin( + models={ + "mock": lambda: MockModel( + [ + {"name": "echo", "input": {"text": "hi"}}, + "Done!", + ] + ) + } + ) + + async with Worker( + client, + task_queue=task_queue, + workflows=[HooksWorkflow], + activities=[audit_tool], + plugins=[plugin], + max_cached_workflows=0, + ): + handle = await client.start_workflow( + HooksWorkflow.run, + "Say hi", + id=f"test_hooks_{uuid4()}", + task_queue=task_queue, + ) + assert await handle.result() == ["echo"] + + assert _AUDIT_LOG == ["echo"] + + history = await handle.fetch_history() + assert "audit_tool" in get_activities(history) + + await Replayer( + workflows=[HooksWorkflow], + plugins=[plugin], + ).replay_workflow(history) diff --git a/tests/contrib/strands/test_interrupt.py b/tests/contrib/strands/test_interrupt.py new file mode 100644 index 000000000..64f72bc07 --- /dev/null +++ b/tests/contrib/strands/test_interrupt.py @@ -0,0 +1,105 @@ +from datetime import timedelta +from uuid import uuid4 + +from strands import tool +from strands.hooks import HookProvider, HookRegistry +from strands.hooks.events import BeforeToolCallEvent +from strands.types.interrupt import InterruptResponseContent + +from temporalio import workflow +from temporalio.client import Client +from temporalio.contrib.strands import StrandsPlugin, TemporalAgent +from temporalio.worker import Replayer, Worker +from tests.contrib.strands.common import get_activities +from tests.contrib.strands.mock_model import MockModel + + +@tool +def delete_thing(name: str) -> str: + return f"deleted {name}" + + +class ApprovalHook(HookProvider): + def register_hooks(self, registry: HookRegistry, **kwargs: object) -> None: + registry.add_callback(BeforeToolCallEvent, self._gate) + + def _gate(self, event: BeforeToolCallEvent) -> None: + if event.tool_use["name"] != "delete_thing": + return + approval = event.interrupt( + "approval", + reason=f"approve delete of {event.tool_use['input']['name']}?", + ) + if approval != "approve": + event.cancel_tool = "denied" + + +@workflow.defn +class InterruptWorkflow: + def __init__(self) -> None: + self.agent = TemporalAgent( + model="mock", + start_to_close_timeout=timedelta(seconds=15), + tools=[delete_thing], + hooks=[ApprovalHook()], + ) + self._approval: str | None = None + + @workflow.signal + def approve(self, response: str) -> None: + self._approval = response + + @workflow.run + async def run(self, prompt: str) -> str: + result = await self.agent.invoke_async(prompt) + while result.stop_reason == "interrupt": + await workflow.wait_condition(lambda: self._approval is not None) + response = self._approval + self._approval = None + responses: list[InterruptResponseContent] = [ + {"interruptResponse": {"interruptId": i.id, "response": response}} + for i in (result.interrupts or []) + ] + result = await self.agent.invoke_async(responses) + return str(result) + + +async def test_interrupt(client: Client): + task_queue = "test_interrupt" + plugin = StrandsPlugin( + models={ + "mock": lambda: MockModel( + [ + {"name": "delete_thing", "input": {"name": "foo"}}, + "Done!", + ] + ) + } + ) + + async with Worker( + client, + task_queue=task_queue, + workflows=[InterruptWorkflow], + plugins=[plugin], + max_cached_workflows=0, + ): + handle = await client.start_workflow( + InterruptWorkflow.run, + "delete foo", + id=f"test_interrupt_{uuid4()}", + task_queue=task_queue, + ) + await handle.signal(InterruptWorkflow.approve, "approve") + assert await handle.result() == "Done!\n" + + history = await handle.fetch_history() + assert get_activities(history) == [ + "invoke_model", + "invoke_model", + ] + + await Replayer( + workflows=[InterruptWorkflow], + plugins=[plugin], + ).replay_workflow(history) diff --git a/tests/contrib/strands/test_interrupt_exception.py b/tests/contrib/strands/test_interrupt_exception.py new file mode 100644 index 000000000..ed858b32b --- /dev/null +++ b/tests/contrib/strands/test_interrupt_exception.py @@ -0,0 +1,191 @@ +from datetime import timedelta +from uuid import uuid4 + +from strands import tool +from strands.interrupt import Interrupt, InterruptException +from strands.types.interrupt import InterruptResponseContent + +from temporalio import activity, workflow +from temporalio.client import Client +from temporalio.contrib.strands import StrandsPlugin, TemporalAgent +from temporalio.contrib.strands.workflow import activity_as_tool +from temporalio.worker import Replayer, Worker +from tests.contrib.strands.common import get_activities +from tests.contrib.strands.mock_model import MockModel + + +@tool +def in_workflow_delete(name: str) -> str: + raise InterruptException( + Interrupt(id=f"delete:{name}", name="approval", reason=f"delete {name}?") + ) + + +# Counts attempts so the activity raises on the first invocation and succeeds on +# the second — modeling a real "approval flipped an external flag" check. +_activity_delete_calls = 0 + + +@activity.defn +async def activity_delete(name: str) -> str: + global _activity_delete_calls + _activity_delete_calls += 1 + if _activity_delete_calls == 1: + raise InterruptException( + Interrupt(id=f"delete:{name}", name="approval", reason=f"delete {name}?") + ) + return f"deleted {name}" + + +@workflow.defn +class InWorkflowToolInterruptWorkflow: + def __init__(self) -> None: + self.agent = TemporalAgent( + model="mock", + start_to_close_timeout=timedelta(seconds=15), + tools=[in_workflow_delete], + ) + self._approval: str | None = None + + @workflow.signal + def approve(self, response: str) -> None: + self._approval = response + + @workflow.run + async def run(self, prompt: str) -> str: + result = await self.agent.invoke_async(prompt) + while result.stop_reason == "interrupt": + await workflow.wait_condition(lambda: self._approval is not None) + response, self._approval = self._approval, None + responses: list[InterruptResponseContent] = [ + {"interruptResponse": {"interruptId": i.id, "response": response}} + for i in (result.interrupts or []) + ] + result = await self.agent.invoke_async(responses) + return str(result) + + +@workflow.defn +class ActivityToolInterruptWorkflow: + def __init__(self) -> None: + self.agent = TemporalAgent( + model="mock", + start_to_close_timeout=timedelta(seconds=15), + tools=[ + activity_as_tool( + activity_delete, + start_to_close_timeout=timedelta(seconds=15), + ) + ], + ) + self._approval: str | None = None + + @workflow.signal + def approve(self, response: str) -> None: + self._approval = response + + @workflow.run + async def run(self, prompt: str) -> str: + result = await self.agent.invoke_async(prompt) + while result.stop_reason == "interrupt": + await workflow.wait_condition(lambda: self._approval is not None) + response, self._approval = self._approval, None + responses: list[InterruptResponseContent] = [ + {"interruptResponse": {"interruptId": i.id, "response": response}} + for i in (result.interrupts or []) + ] + result = await self.agent.invoke_async(responses) + return str(result) + + +async def test_in_workflow_tool_interrupt(client: Client): + task_queue = "test_in_workflow_tool_interrupt" + plugin = StrandsPlugin( + models={ + "mock": lambda: MockModel( + [ + {"name": "in_workflow_delete", "input": {"name": "foo"}}, + "Done!", + ] + ) + } + ) + + async with Worker( + client, + task_queue=task_queue, + workflows=[InWorkflowToolInterruptWorkflow], + plugins=[plugin], + max_cached_workflows=0, + ): + handle = await client.start_workflow( + InWorkflowToolInterruptWorkflow.run, + "delete foo", + id=f"test_in_workflow_tool_interrupt_{uuid4()}", + task_queue=task_queue, + ) + await handle.signal(InWorkflowToolInterruptWorkflow.approve, "approve") + assert await handle.result() == "Done!\n" + + history = await handle.fetch_history() + # No activity call for the in-workflow @tool — only model calls. + assert get_activities(history) == ["invoke_model", "invoke_model"] + + await Replayer( + workflows=[InWorkflowToolInterruptWorkflow], + plugins=[plugin], + ).replay_workflow(history) + + +async def test_activity_tool_interrupt(client: Client): + global _activity_delete_calls + _activity_delete_calls = 0 + task_queue = "test_activity_tool_interrupt" + plugin = StrandsPlugin( + models={ + "mock": lambda: MockModel( + [ + {"name": "activity_delete", "input": {"name": "foo"}}, + "Done!", + ] + ) + } + ) + + # Activity-side InterruptException relies on the failure converter installed + # via the data converter, which _ActivityWorker reads from the client config. + # Re-create the client with the plugin attached so that converter takes effect. + config = client.config() + config["plugins"] = [*config["plugins"], plugin] + client = Client(**config) + + async with Worker( + client, + task_queue=task_queue, + workflows=[ActivityToolInterruptWorkflow], + activities=[activity_delete], + max_cached_workflows=0, + ): + handle = await client.start_workflow( + ActivityToolInterruptWorkflow.run, + "delete foo", + id=f"test_activity_tool_interrupt_{uuid4()}", + task_queue=task_queue, + ) + await handle.signal(ActivityToolInterruptWorkflow.approve, "approve") + assert await handle.result() == "Done!\n" + + history = await handle.fetch_history() + # activity_delete appears twice: once for the call that raised + # InterruptException, once for the resume call that returned successfully. + assert get_activities(history) == [ + "invoke_model", + "activity_delete", + "activity_delete", + "invoke_model", + ] + + await Replayer( + workflows=[ActivityToolInterruptWorkflow], + plugins=[plugin], + ).replay_workflow(history) diff --git a/tests/contrib/strands/test_invocation_state.py b/tests/contrib/strands/test_invocation_state.py new file mode 100644 index 000000000..01fd4e004 --- /dev/null +++ b/tests/contrib/strands/test_invocation_state.py @@ -0,0 +1,82 @@ +from collections.abc import AsyncIterable +from datetime import timedelta +from typing import Any +from uuid import uuid4 + +from strands.models import Model +from strands.types.streaming import StreamEvent + +from temporalio import workflow +from temporalio.client import Client +from temporalio.contrib.strands import StrandsPlugin, TemporalAgent +from temporalio.worker import Worker + +# Worker-side sink: the recording model writes the invocation_state it +# received here so the test body can inspect it after the workflow completes. +_RECEIVED: list[dict[str, Any]] = [] + + +class _RecordingModel(Model): + def update_config(self, **_model_config: Any) -> None: + return None + + def get_config(self) -> dict[str, Any]: + return {} + + def structured_output(self, *_args: Any, **_kwargs: Any) -> Any: + raise NotImplementedError + + async def stream( + self, + *_args: Any, + invocation_state: dict[str, Any] | None = None, + **_kwargs: Any, + ) -> AsyncIterable[StreamEvent]: + _RECEIVED.append(invocation_state or {}) + yield {"messageStart": {"role": "assistant"}} + yield {"contentBlockDelta": {"delta": {"text": "ok"}}} + yield {"contentBlockStop": {}} + yield {"messageStop": {"stopReason": "end_turn"}} + + +@workflow.defn +class _InvocationStateWorkflow: + def __init__(self) -> None: + self.agent = TemporalAgent( + model="recording", + start_to_close_timeout=timedelta(seconds=15), + ) + + @workflow.run + async def run(self, prompt: str) -> str: + result = await self.agent.invoke_async( + prompt, + invocation_state={"user_key": "user_value", "non_json": object()}, + ) + return str(result) + + +async def test_invocation_state_round_trip(client: Client): + _RECEIVED.clear() + plugin = StrandsPlugin(models={"recording": lambda: _RecordingModel()}) + + async with Worker( + client, + task_queue="test_invocation_state", + workflows=[_InvocationStateWorkflow], + plugins=[plugin], + max_cached_workflows=0, + ): + await client.execute_workflow( + _InvocationStateWorkflow.run, + "hi", + id=f"test_invocation_state_{uuid4()}", + task_queue="test_invocation_state", + ) + + # The serializable key crosses the activity boundary; the non-serializable + # one is dropped before dispatch (with a debug log). + assert _RECEIVED, "model.stream() was not called" + received = _RECEIVED[0] + assert received.get("user_key") == "user_value" + assert "non_json" not in received diff --git a/tests/contrib/strands/test_mcp.py b/tests/contrib/strands/test_mcp.py new file mode 100644 index 000000000..bde857022 --- /dev/null +++ b/tests/contrib/strands/test_mcp.py @@ -0,0 +1,252 @@ +import asyncio +import sys +from datetime import timedelta +from pathlib import Path +from uuid import uuid4 + +from mcp import StdioServerParameters, stdio_client +from strands.tools.mcp.mcp_client import MCPClient + +from temporalio import workflow +from temporalio.client import Client +from temporalio.contrib.strands import ( + StrandsPlugin, + TemporalAgent, + TemporalMCPClient, + _temporal_mcp_client, +) +from temporalio.worker import Replayer, Worker +from tests.contrib.strands.common import get_activities +from tests.contrib.strands.mock_model import MockModel + + +def _echo_client_factory() -> MCPClient: + return MCPClient( + lambda: stdio_client( + StdioServerParameters( + command=sys.executable, + args=[str(Path(__file__).parent / "echo_mcp_server.py")], + ) + ) + ) + + +@workflow.defn +class MCPWorkflow: + def __init__(self) -> None: + echo = TemporalMCPClient( + server="echo", + start_to_close_timeout=timedelta(seconds=30), + ) + self.agent = TemporalAgent( + model="mock", + start_to_close_timeout=timedelta(seconds=30), + tools=[echo], + ) + + @workflow.run + async def run(self, prompt: str) -> str: + result = await self.agent.invoke_async(prompt) + return str(result) + + +async def test_mcp(client: Client): + task_queue = "test_mcp" + plugin = StrandsPlugin( + models={ + "mock": lambda: MockModel( + [ + {"name": "echo", "input": {"message": "hello"}}, + "Done!", + ] + ) + }, + mcp_clients={ + "echo": lambda: MCPClient( + lambda: stdio_client( + StdioServerParameters( + command=sys.executable, + args=[str(Path(__file__).parent / "echo_mcp_server.py")], + ) + ) + ), + }, + ) + + async with Worker( + client, + task_queue=task_queue, + workflows=[MCPWorkflow], + plugins=[plugin], + max_cached_workflows=0, + ): + handle = await client.start_workflow( + MCPWorkflow.run, + "echo hello", + id=f"test_mcp_{uuid4()}", + task_queue=task_queue, + ) + assert await handle.result() == "Done!\n" + + history = await handle.fetch_history() + assert get_activities(history) == [ + "invoke_model", + "echo-call-tool", + "invoke_model", + ] + + await Replayer( + workflows=[MCPWorkflow], + plugins=[plugin], + ).replay_workflow(history) + + +@workflow.defn +class MCPReuseWorkflow: + def __init__(self) -> None: + echo = TemporalMCPClient( + server="echo_cached", + start_to_close_timeout=timedelta(seconds=30), + ) + self.agent = TemporalAgent( + model="mock", + start_to_close_timeout=timedelta(seconds=30), + tools=[echo], + ) + + @workflow.run + async def run(self, prompt: str) -> str: + result = await self.agent.invoke_async(prompt) + return str(result) + + +async def test_mcp_reuses_connection(client: Client): + """Successive MCP tool calls reuse one cached worker-side connection.""" + task_queue = "test_mcp_reuses_connection" + # Count how often the worker opens a connection. With caching this is one + # startup-discovery connection plus one cached call connection serving both + # tool calls (2); reconnecting per call would make it 3. + factory_calls = [0] + + def counting_factory() -> MCPClient: + factory_calls[0] += 1 + return _echo_client_factory() + + plugin = StrandsPlugin( + models={ + "mock": lambda: MockModel( + [ + {"name": "echo", "input": {"message": "one"}}, + {"name": "echo", "input": {"message": "two"}}, + "Done!", + ] + ) + }, + mcp_clients={"echo_cached": counting_factory}, + ) + + async with Worker( + client, + task_queue=task_queue, + workflows=[MCPReuseWorkflow], + plugins=[plugin], + max_cached_workflows=0, + ): + handle = await client.start_workflow( + MCPReuseWorkflow.run, + "echo twice", + id=f"test_mcp_reuses_connection_{uuid4()}", + task_queue=task_queue, + ) + assert await handle.result() == "Done!\n" + + # The worker context has exited, so its run_context finally evicted the + # cached connection. + assert "echo_cached" not in _temporal_mcp_client._CONNECTIONS + assert factory_calls[0] == 2 + + history = await handle.fetch_history() + assert get_activities(history) == [ + "invoke_model", + "echo_cached-call-tool", + "invoke_model", + "echo_cached-call-tool", + "invoke_model", + ] + + await Replayer( + workflows=[MCPReuseWorkflow], + plugins=[plugin], + ).replay_workflow(history) + + +@workflow.defn +class MCPIdleWorkflow: + def __init__(self) -> None: + echo = TemporalMCPClient( + server="echo_idle", + start_to_close_timeout=timedelta(seconds=30), + ) + self.agent = TemporalAgent( + model="mock", + start_to_close_timeout=timedelta(seconds=30), + tools=[echo], + ) + + @workflow.run + async def run(self, prompt: str) -> str: + result = await self.agent.invoke_async(prompt) + return str(result) + + +async def test_mcp_connection_idle_timeout(client: Client): + """A short idle timeout evicts the cached connection while the worker runs.""" + task_queue = "test_mcp_connection_idle_timeout" + factory_calls = [0] + + def counting_factory() -> MCPClient: + factory_calls[0] += 1 + return _echo_client_factory() + + plugin = StrandsPlugin( + models={ + "mock": lambda: MockModel( + [ + {"name": "echo", "input": {"message": "hello"}}, + "Done!", + ] + ) + }, + mcp_clients={"echo_idle": counting_factory}, + # Short window so the cached call connection is evicted mid-run rather + # than only at worker shutdown. The idle timer only arms once the call + # releases the connection, so this can't tear it down mid-call. + mcp_connection_idle_timeout=timedelta(milliseconds=100), + ) + + async with Worker( + client, + task_queue=task_queue, + workflows=[MCPIdleWorkflow], + plugins=[plugin], + max_cached_workflows=0, + ): + handle = await client.start_workflow( + MCPIdleWorkflow.run, + "echo hello", + id=f"test_mcp_connection_idle_timeout_{uuid4()}", + task_queue=task_queue, + ) + assert await handle.result() == "Done!\n" + + # The call opened a second connection (startup discovery was the first). + assert factory_calls[0] == 2 + + # Still inside the worker context: the short idle timer evicts the + # cached call connection on its own. Asserting eviction here -- with the + # worker alive -- proves it came from the idle timer, not shutdown. + for _ in range(100): + if "echo_idle" not in _temporal_mcp_client._CONNECTIONS: + break + await asyncio.sleep(0.1) + assert "echo_idle" not in _temporal_mcp_client._CONNECTIONS diff --git a/tests/contrib/strands/test_model.py b/tests/contrib/strands/test_model.py new file mode 100644 index 000000000..68d578e5c --- /dev/null +++ b/tests/contrib/strands/test_model.py @@ -0,0 +1,51 @@ +from datetime import timedelta +from uuid import uuid4 + +from temporalio import workflow +from temporalio.client import Client +from temporalio.contrib.strands import StrandsPlugin, TemporalAgent +from temporalio.worker import Replayer, Worker +from tests.contrib.strands.common import get_activities +from tests.contrib.strands.mock_model import MockModel + + +@workflow.defn +class ModelWorkflow: + def __init__(self) -> None: + self.agent = TemporalAgent( + model="mock", + start_to_close_timeout=timedelta(seconds=15), + ) + + @workflow.run + async def run(self, prompt: str) -> str: + result = await self.agent.invoke_async(prompt) + return str(result) + + +async def test_model(client: Client): + task_queue = "test_model" + plugin = StrandsPlugin(models={"mock": lambda: MockModel(["Done!"])}) + + async with Worker( + client, + task_queue=task_queue, + workflows=[ModelWorkflow], + plugins=[plugin], + max_cached_workflows=0, + ): + handle = await client.start_workflow( + ModelWorkflow.run, + "Hello", + id=f"test_model_{uuid4()}", + task_queue=task_queue, + ) + assert await handle.result() == "Done!\n" + + history = await handle.fetch_history() + assert get_activities(history) == ["invoke_model"] + + await Replayer( + workflows=[ModelWorkflow], + plugins=[plugin], + ).replay_workflow(history) diff --git a/tests/contrib/strands/test_model_streaming.py b/tests/contrib/strands/test_model_streaming.py new file mode 100644 index 000000000..41f3ff2f1 --- /dev/null +++ b/tests/contrib/strands/test_model_streaming.py @@ -0,0 +1,78 @@ +import asyncio +from datetime import timedelta +from uuid import uuid4 + +from strands.types.streaming import StreamEvent + +from temporalio import workflow +from temporalio.client import Client +from temporalio.contrib.strands import StrandsPlugin, TemporalAgent +from temporalio.contrib.workflow_streams import WorkflowStream, WorkflowStreamClient +from temporalio.worker import Replayer, Worker +from tests.contrib.strands.common import get_activities +from tests.contrib.strands.mock_model import MockModel + + +@workflow.defn +class StreamingModelWorkflow: + def __init__(self) -> None: + self.stream = WorkflowStream() + self.agent = TemporalAgent( + model="mock", + start_to_close_timeout=timedelta(seconds=15), + streaming_topic="events", + ) + + @workflow.run + async def run(self, prompt: str) -> str: + result = await self.agent.invoke_async(prompt) + return str(result) + + +async def test_model_streaming(client: Client): + task_queue = "test_model_streaming" + plugin = StrandsPlugin(models={"mock": lambda: MockModel(["Done!"])}) + workflow_id = f"test_model_streaming_{uuid4()}" + + async with Worker( + client, + task_queue=task_queue, + workflows=[StreamingModelWorkflow], + plugins=[plugin], + max_cached_workflows=0, + ): + handle = await client.start_workflow( + StreamingModelWorkflow.run, + "Hello", + id=workflow_id, + task_queue=task_queue, + ) + + stream = WorkflowStreamClient.create(client, workflow_id) + events: list[StreamEvent] = [] + + async def collect() -> None: + async for item in stream.subscribe( + ["events"], + from_offset=0, + result_type=StreamEvent, + poll_cooldown=timedelta(milliseconds=50), + ): + events.append(item.data) + if len(events) >= 4: + break + + collect_task = asyncio.create_task(collect()) + assert await handle.result() == "Done!\n" + await asyncio.wait_for(collect_task, timeout=10.0) + + history = await handle.fetch_history() + assert get_activities(history) == ["invoke_model_streaming"] + + assert any("messageStart" in e for e in events) + assert any("messageStop" in e for e in events) + + await Replayer( + workflows=[StreamingModelWorkflow], + plugins=[plugin], + ).replay_workflow(history) diff --git a/tests/contrib/strands/test_structured_output.py b/tests/contrib/strands/test_structured_output.py new file mode 100644 index 000000000..18c77c553 --- /dev/null +++ b/tests/contrib/strands/test_structured_output.py @@ -0,0 +1,74 @@ +from datetime import timedelta +from uuid import uuid4 + +from pydantic import BaseModel, Field + +from temporalio import workflow +from temporalio.client import Client +from temporalio.contrib.strands import StrandsPlugin, TemporalAgent +from temporalio.worker import Replayer, Worker +from tests.contrib.strands.mock_model import MockModel + + +class PersonInfo(BaseModel): + name: str = Field(description="Name of the person") + age: int = Field(description="Age of the person") + occupation: str = Field(description="Occupation of the person") + + +@workflow.defn +class StructuredOutputWorkflow: + def __init__(self) -> None: + self.agent = TemporalAgent( + model="mock", + start_to_close_timeout=timedelta(seconds=15), + structured_output_model=PersonInfo, + ) + + @workflow.run + async def run(self, prompt: str) -> PersonInfo: + result = await self.agent.invoke_async(prompt) + assert isinstance(result.structured_output, PersonInfo) + return result.structured_output + + +async def test_structured_output(client: Client): + task_queue = "test_structured_output" + plugin = StrandsPlugin( + models={ + "mock": lambda: MockModel( + [ + { + "name": "PersonInfo", + "input": { + "name": "John Smith", + "age": 30, + "occupation": "software engineer", + }, + }, + ] + ) + } + ) + + async with Worker( + client, + task_queue=task_queue, + workflows=[StructuredOutputWorkflow], + plugins=[plugin], + max_cached_workflows=0, + ): + handle = await client.start_workflow( + StructuredOutputWorkflow.run, + "John Smith is a 30 year-old software engineer", + id=f"test_structured_output_{uuid4()}", + task_queue=task_queue, + ) + assert await handle.result() == PersonInfo( + name="John Smith", age=30, occupation="software engineer" + ) + + await Replayer( + workflows=[StructuredOutputWorkflow], + plugins=[plugin], + ).replay_workflow(await handle.fetch_history()) diff --git a/tests/contrib/strands/test_tool.py b/tests/contrib/strands/test_tool.py new file mode 100644 index 000000000..39985e2df --- /dev/null +++ b/tests/contrib/strands/test_tool.py @@ -0,0 +1,118 @@ +from datetime import timedelta +from pathlib import Path +from uuid import uuid4 + +from strands import tool +from strands_tools import ( # pyright: ignore[reportMissingTypeStubs] + calculator, + file_read, +) + +from temporalio import activity, workflow +from temporalio.client import Client +from temporalio.contrib.strands import StrandsPlugin, TemporalAgent +from temporalio.contrib.strands.workflow import activity_as_tool +from temporalio.worker import Replayer, Worker +from tests.contrib.strands.common import get_activities +from tests.contrib.strands.mock_model import MockModel + + +@tool +def letter_counter(word: str, letter: str) -> int: + return word.lower().count(letter.lower()) + + +@activity.defn(name="read_file") +async def read_file_activity(path: str) -> str: + result = file_read.file_read( + { + "toolUseId": "read_file", + "name": "file_read", + "input": {"path": path, "mode": "view"}, + } + ) + text = result["content"][0].get("text") + assert text is not None + return text + + +@workflow.defn +class ToolWorkflow: + def __init__(self) -> None: + self.agent = TemporalAgent( + model="mock", + start_to_close_timeout=timedelta(seconds=15), + tools=[ + calculator, + activity_as_tool( + read_file_activity, + start_to_close_timeout=timedelta(seconds=15), + ), + letter_counter, + ], + ) + + @workflow.run + async def run(self, prompt: str) -> str: + result = await self.agent.invoke_async(prompt) + return str(result) + + +async def test_tool(client: Client, tmp_path: Path): + task_queue = "test_tool" + fixture = tmp_path / "greeting.txt" + fixture.write_text("hello\n") + + plugin = StrandsPlugin( + models={ + "mock": lambda: MockModel( + [ + {"name": "read_file", "input": {"path": str(fixture)}}, + { + "name": "calculator", + "input": {"expression": "3111696 / 74088"}, + }, + { + "name": "letter_counter", + "input": {"word": "strawberry", "letter": "R"}, + }, + "Done!", + ] + ) + } + ) + + async with Worker( + client, + task_queue=task_queue, + workflows=[ToolWorkflow], + activities=[read_file_activity], + plugins=[plugin], + max_cached_workflows=0, + ): + handle = await client.start_workflow( + ToolWorkflow.run, + "I have 3 requests:\n" + f"1. Read the file at {fixture}\n" + "2. Calculate 3111696 / 74088\n" + '3. Tell me how many letter R\'s are in the word "strawberry"', + id=f"test_tool_{uuid4()}", + task_queue=task_queue, + ) + assert await handle.result() == "Done!\n" + + history = await handle.fetch_history() + assert get_activities(history) == [ + "invoke_model", + "read_file", + "invoke_model", + # calculator (in-workflow) + "invoke_model", + # letter_counter (in-workflow) + "invoke_model", + ] + + await Replayer( + workflows=[ToolWorkflow], + plugins=[plugin], + ).replay_workflow(history) diff --git a/tests/test_type_errors.py b/tests/test_type_errors.py index d8e6e2afb..2b70d7f63 100644 --- a/tests/test_type_errors.py +++ b/tests/test_type_errors.py @@ -86,7 +86,7 @@ def _test_type_errors( def _has_type_error_assertions(test_file: Path) -> bool: """Check if a file contains any type error assertions.""" - with open(test_file) as f: + with open(test_file, encoding="utf-8") as f: return any(re.search(r"# assert-type-error-\w+:", line) for line in f) @@ -94,7 +94,7 @@ def _get_expected_errors(test_file: Path, type_checker: str) -> dict[int, str]: """Parse expected type errors from comments in a file for the specified type checker.""" expected_errors = {} - with open(test_file) as f: + with open(test_file, encoding="utf-8") as f: lines = zip(itertools.count(1), f) for line_num, line in lines: if match := re.search( diff --git a/uv.lock b/uv.lock index e8fe1e0f1..abea4b74c 100644 --- a/uv.lock +++ b/uv.lock @@ -316,6 +316,18 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/02/ff/1175b0b7371e46244032d43a56862d0af455823b5280a50c63d99cc50f18/automat-25.4.16-py3-none-any.whl", hash = "sha256:04e9bce696a8d5671ee698005af6e5a9fa15354140a87f4870744604dcdd3ba1", size = 42842, upload-time = "2025-04-16T20:12:14.447Z" }, ] +[[package]] +name = "aws-requests-auth" +version = "0.4.3" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "requests" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/54/b2/455c0bfcbd772dafd4c9e93c4b713e36790abf9ccbca9b8e661968b29798/aws-requests-auth-0.4.3.tar.gz", hash = "sha256:33593372018b960a31dbbe236f89421678b885c35f0b6a7abfae35bb77e069b2", size = 10096, upload-time = "2020-05-27T23:10:34.742Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/af/11/5dc8be418e1d54bed15eaf3a7461797e5ebb9e6a34869ad750561f35fa5b/aws_requests_auth-0.4.3-py2.py3-none-any.whl", hash = "sha256:646bc37d62140ea1c709d20148f5d43197e6bd2d63909eb36fa4bb2345759977", size = 6838, upload-time = "2020-05-27T23:10:33.658Z" }, +] + [[package]] name = "aws-sam-translator" version = "1.106.0" @@ -374,6 +386,19 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/f4/be/6985abb1011fda8a523cfe21ed9629e397d6e06fb5bae99750402b25c95b/bashlex-0.18-py2.py3-none-any.whl", hash = "sha256:91d73a23a3e51711919c1c899083890cdecffc91d8c088942725ac13e9dcfffa", size = 69539, upload-time = "2023-01-18T15:21:24.167Z" }, ] +[[package]] +name = "beautifulsoup4" +version = "4.14.3" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "soupsieve" }, + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/c3/b0/1c6a16426d389813b48d95e26898aff79abbde42ad353958ad95cc8c9b21/beautifulsoup4-4.14.3.tar.gz", hash = "sha256:6292b1c5186d356bba669ef9f7f051757099565ad9ada5dd630bd9de5fa7fb86", size = 627737, upload-time = "2025-11-30T15:08:26.084Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/1a/39/47f9197bdd44df24d67ac8893641e16f386c984a0619ef2ee4c51fbbc019/beautifulsoup4-4.14.3-py3-none-any.whl", hash = "sha256:0918bfe44902e6ad8d57732ba310582e98da931428d231a5ecb9e7c703a735bb", size = 107721, upload-time = "2025-11-30T15:08:24.087Z" }, +] + [[package]] name = "blinker" version = "1.9.0" @@ -924,6 +949,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/99/c7/d1ec24fb280caa5a79b6b950db565dab30210a66259d17d5bb2b3a9f878d/dependency_groups-1.3.1-py3-none-any.whl", hash = "sha256:51aeaa0dfad72430fcfb7bcdbefbd75f3792e5919563077f30bc0d73f4493030", size = 8664, upload-time = "2025-05-02T00:34:27.085Z" }, ] +[[package]] +name = "dill" +version = "0.4.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/81/e1/56027a71e31b02ddc53c7d65b01e68edf64dea2932122fe7746a516f75d5/dill-0.4.1.tar.gz", hash = "sha256:423092df4182177d4d8ba8290c8a5b640c66ab35ec7da59ccfa00f6fa3eea5fa", size = 187315, upload-time = "2026-01-19T02:36:56.85Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/1e/77/dc8c558f7593132cf8fefec57c4f60c83b16941c574ac5f619abb3ae7933/dill-0.4.1-py3-none-any.whl", hash = "sha256:1e1ce33e978ae97fcfcff5638477032b801c46c7c65cf717f95fbc2248f79a9d", size = 120019, upload-time = "2026-01-19T02:36:55.663Z" }, +] + [[package]] name = "distro" version = "1.9.0" @@ -2678,6 +2712,19 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/94/54/e7d793b573f298e1c9013b8c4dade17d481164aa517d1d7148619c2cedbf/markdown_it_py-4.0.0-py3-none-any.whl", hash = "sha256:87327c59b172c5011896038353a81343b6754500a08cd7a4973bb48c6d578147", size = 87321, upload-time = "2025-08-11T12:57:51.923Z" }, ] +[[package]] +name = "markdownify" +version = "1.2.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "beautifulsoup4" }, + { name = "six" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/3f/bc/c8c8eea5335341306b0fa7e1cb33c5e1c8d24ef70ddd684da65f41c49c92/markdownify-1.2.2.tar.gz", hash = "sha256:b274f1b5943180b031b699b199cbaeb1e2ac938b75851849a31fd0c3d6603d09", size = 18816, upload-time = "2025-11-16T19:21:18.565Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/43/ce/f1e3e9d959db134cedf06825fae8d5b294bd368aacdd0831a3975b7c4d55/markdownify-1.2.2-py3-none-any.whl", hash = "sha256:3f02d3cc52714084d6e589f70397b6fc9f2f3a8531481bf35e8cc39f975e186a", size = 15724, upload-time = "2025-11-16T19:21:17.622Z" }, +] + [[package]] name = "markupsafe" version = "3.0.3" @@ -3616,6 +3663,20 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/10/f5/7a40ff3f62bfe715dad2f633d7f1174ba1a7dd74254c15b2558b3401262a/opentelemetry_instrumentation-0.59b0-py3-none-any.whl", hash = "sha256:44082cc8fe56b0186e87ee8f7c17c327c4c2ce93bdbe86496e600985d74368ee", size = 33020, upload-time = "2025-10-16T08:38:31.463Z" }, ] +[[package]] +name = "opentelemetry-instrumentation-threading" +version = "0.59b0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "opentelemetry-api" }, + { name = "opentelemetry-instrumentation" }, + { name = "wrapt" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/82/7a/84e97d8992808197006e607ae410c2219bdbbc23d1289ba0c244d3220741/opentelemetry_instrumentation_threading-0.59b0.tar.gz", hash = "sha256:ce5658730b697dcbc0e0d6d13643a69fd8aeb1b32fa8db3bade8ce114c7975f3", size = 8770, upload-time = "2025-10-16T08:40:03.587Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b8/50/32d29076aaa1c91983cdd3ca8c6bb4d344830cd7d87a7c0fdc2d98c58509/opentelemetry_instrumentation_threading-0.59b0-py3-none-any.whl", hash = "sha256:76da2fc01fe1dccebff6581080cff9e42ac7b27cc61eb563f3c4435c727e8eca", size = 9313, upload-time = "2025-10-16T08:39:15.876Z" }, +] + [[package]] name = "opentelemetry-proto" version = "1.38.0" @@ -3846,6 +3907,104 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/fa/c9/8eed0486f074e9f1ca7f8ce5ad663e65f12fdab344028d658fa1b03d35e0/pathspec-1.1.0-py3-none-any.whl", hash = "sha256:574b128f7456bd899045ccd142dd446af7e6cfd0072d63ad73fbc55fbb4aaa42", size = 56264, upload-time = "2026-04-23T01:46:20.606Z" }, ] +[[package]] +name = "pillow" +version = "12.2.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/8c/21/c2bcdd5906101a30244eaffc1b6e6ce71a31bd0742a01eb89e660ebfac2d/pillow-12.2.0.tar.gz", hash = "sha256:a830b1a40919539d07806aa58e1b114df53ddd43213d9c8b75847eee6c0182b5", size = 46987819, upload-time = "2026-04-01T14:46:17.687Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/3a/aa/d0b28e1c811cd4d5f5c2bfe2e022292bd255ae5744a3b9ac7d6c8f72dd75/pillow-12.2.0-cp310-cp310-macosx_10_10_x86_64.whl", hash = "sha256:a4e8f36e677d3336f35089648c8955c51c6d386a13cf6ee9c189c5f5bd713a9f", size = 5354355, upload-time = "2026-04-01T14:42:15.402Z" }, + { url = "https://files.pythonhosted.org/packages/27/8e/1d5b39b8ae2bd7650d0c7b6abb9602d16043ead9ebbfef4bc4047454da2a/pillow-12.2.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:2e589959f10d9824d39b350472b92f0ce3b443c0a3442ebf41c40cb8361c5b97", size = 4695871, upload-time = "2026-04-01T14:42:18.234Z" }, + { url = "https://files.pythonhosted.org/packages/f0/c5/dcb7a6ca6b7d3be41a76958e90018d56c8462166b3ef223150360850c8da/pillow-12.2.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:a52edc8bfff4429aaabdf4d9ee0daadbbf8562364f940937b941f87a4290f5ff", size = 6269734, upload-time = "2026-04-01T14:42:20.608Z" }, + { url = "https://files.pythonhosted.org/packages/ea/f1/aa1bb13b2f4eba914e9637893c73f2af8e48d7d4023b9d3750d4c5eb2d0c/pillow-12.2.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:975385f4776fafde056abb318f612ef6285b10a1f12b8570f3647ad0d74b48ec", size = 8076080, upload-time = "2026-04-01T14:42:23.095Z" }, + { url = "https://files.pythonhosted.org/packages/a1/2a/8c79d6a53169937784604a8ae8d77e45888c41537f7f6f65ed1f407fe66d/pillow-12.2.0-cp310-cp310-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:bd9c0c7a0c681a347b3194c500cb1e6ca9cab053ea4d82a5cf45b6b754560136", size = 6382236, upload-time = "2026-04-01T14:42:25.82Z" }, + { url = "https://files.pythonhosted.org/packages/b5/42/bbcb6051030e1e421d103ce7a8ecadf837aa2f39b8f82ef1a8d37c3d4ebc/pillow-12.2.0-cp310-cp310-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:88d387ff40b3ff7c274947ed3125dedf5262ec6919d83946753b5f3d7c67ea4c", size = 7070220, upload-time = "2026-04-01T14:42:28.68Z" }, + { url = "https://files.pythonhosted.org/packages/3f/e1/c2a7d6dd8cfa6b231227da096fd2d58754bab3603b9d73bf609d3c18b64f/pillow-12.2.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:51c4167c34b0d8ba05b547a3bb23578d0ba17b80a5593f93bd8ecb123dd336a3", size = 6493124, upload-time = "2026-04-01T14:42:31.579Z" }, + { url = "https://files.pythonhosted.org/packages/5f/41/7c8617da5d32e1d2f026e509484fdb6f3ad7efaef1749a0c1928adbb099e/pillow-12.2.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:34c0d99ecccea270c04882cb3b86e7b57296079c9a4aff88cb3b33563d95afaa", size = 7194324, upload-time = "2026-04-01T14:42:34.615Z" }, + { url = "https://files.pythonhosted.org/packages/2d/de/a777627e19fd6d62f84070ee1521adde5eeda4855b5cf60fe0b149118bca/pillow-12.2.0-cp310-cp310-win32.whl", hash = "sha256:b85f66ae9eb53e860a873b858b789217ba505e5e405a24b85c0464822fe88032", size = 6376363, upload-time = "2026-04-01T14:42:37.19Z" }, + { url = "https://files.pythonhosted.org/packages/e7/34/fc4cb5204896465842767b96d250c08410f01f2f28afc43b257de842eed5/pillow-12.2.0-cp310-cp310-win_amd64.whl", hash = "sha256:673aa32138f3e7531ccdbca7b3901dba9b70940a19ccecc6a37c77d5fdeb05b5", size = 7083523, upload-time = "2026-04-01T14:42:39.62Z" }, + { url = "https://files.pythonhosted.org/packages/2d/a0/32852d36bc7709f14dc3f64f929a275e958ad8c19a6deba9610d458e28b3/pillow-12.2.0-cp310-cp310-win_arm64.whl", hash = "sha256:3e080565d8d7c671db5802eedfb438e5565ffa40115216eabb8cd52d0ecce024", size = 2463318, upload-time = "2026-04-01T14:42:42.063Z" }, + { url = "https://files.pythonhosted.org/packages/68/e1/748f5663efe6edcfc4e74b2b93edfb9b8b99b67f21a854c3ae416500a2d9/pillow-12.2.0-cp311-cp311-macosx_10_10_x86_64.whl", hash = "sha256:8be29e59487a79f173507c30ddf57e733a357f67881430449bb32614075a40ab", size = 5354347, upload-time = "2026-04-01T14:42:44.255Z" }, + { url = "https://files.pythonhosted.org/packages/47/a1/d5ff69e747374c33a3b53b9f98cca7889fce1fd03d79cdc4e1bccc6c5a87/pillow-12.2.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:71cde9a1e1551df7d34a25462fc60325e8a11a82cc2e2f54578e5e9a1e153d65", size = 4695873, upload-time = "2026-04-01T14:42:46.452Z" }, + { url = "https://files.pythonhosted.org/packages/df/21/e3fbdf54408a973c7f7f89a23b2cb97a7ef30c61ab4142af31eee6aebc88/pillow-12.2.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:f490f9368b6fc026f021db16d7ec2fbf7d89e2edb42e8ec09d2c60505f5729c7", size = 6280168, upload-time = "2026-04-01T14:42:49.228Z" }, + { url = "https://files.pythonhosted.org/packages/d3/f1/00b7278c7dd52b17ad4329153748f87b6756ec195ff786c2bdf12518337d/pillow-12.2.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:8bd7903a5f2a4545f6fd5935c90058b89d30045568985a71c79f5fd6edf9b91e", size = 8088188, upload-time = "2026-04-01T14:42:51.735Z" }, + { url = "https://files.pythonhosted.org/packages/ad/cf/220a5994ef1b10e70e85748b75649d77d506499352be135a4989c957b701/pillow-12.2.0-cp311-cp311-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3997232e10d2920a68d25191392e3a4487d8183039e1c74c2297f00ed1c50705", size = 6394401, upload-time = "2026-04-01T14:42:54.343Z" }, + { url = "https://files.pythonhosted.org/packages/e9/bd/e51a61b1054f09437acfbc2ff9106c30d1eb76bc1453d428399946781253/pillow-12.2.0-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e74473c875d78b8e9d5da2a70f7099549f9eb37ded4e2f6a463e60125bccd176", size = 7079655, upload-time = "2026-04-01T14:42:56.954Z" }, + { url = "https://files.pythonhosted.org/packages/6b/3d/45132c57d5fb4b5744567c3817026480ac7fc3ce5d4c47902bc0e7f6f853/pillow-12.2.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:56a3f9c60a13133a98ecff6197af34d7824de9b7b38c3654861a725c970c197b", size = 6503105, upload-time = "2026-04-01T14:42:59.847Z" }, + { url = "https://files.pythonhosted.org/packages/7d/2e/9df2fc1e82097b1df3dce58dc43286aa01068e918c07574711fcc53e6fb4/pillow-12.2.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:90e6f81de50ad6b534cab6e5aef77ff6e37722b2f5d908686f4a5c9eba17a909", size = 7203402, upload-time = "2026-04-01T14:43:02.664Z" }, + { url = "https://files.pythonhosted.org/packages/bd/2e/2941e42858ebb67e50ae741473de81c2984e6eff7b397017623c676e2e8d/pillow-12.2.0-cp311-cp311-win32.whl", hash = "sha256:8c984051042858021a54926eb597d6ee3012393ce9c181814115df4c60b9a808", size = 6378149, upload-time = "2026-04-01T14:43:05.274Z" }, + { url = "https://files.pythonhosted.org/packages/69/42/836b6f3cd7f3e5fa10a1f1a5420447c17966044c8fbf589cc0452d5502db/pillow-12.2.0-cp311-cp311-win_amd64.whl", hash = "sha256:6e6b2a0c538fc200b38ff9eb6628228b77908c319a005815f2dde585a0664b60", size = 7082626, upload-time = "2026-04-01T14:43:08.557Z" }, + { url = "https://files.pythonhosted.org/packages/c2/88/549194b5d6f1f494b485e493edc6693c0a16f4ada488e5bd974ed1f42fad/pillow-12.2.0-cp311-cp311-win_arm64.whl", hash = "sha256:9a8a34cc89c67a65ea7437ce257cea81a9dad65b29805f3ecee8c8fe8ff25ffe", size = 2463531, upload-time = "2026-04-01T14:43:10.743Z" }, + { url = "https://files.pythonhosted.org/packages/58/be/7482c8a5ebebbc6470b3eb791812fff7d5e0216c2be3827b30b8bb6603ed/pillow-12.2.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:2d192a155bbcec180f8564f693e6fd9bccff5a7af9b32e2e4bf8c9c69dbad6b5", size = 5308279, upload-time = "2026-04-01T14:43:13.246Z" }, + { url = "https://files.pythonhosted.org/packages/d8/95/0a351b9289c2b5cbde0bacd4a83ebc44023e835490a727b2a3bd60ddc0f4/pillow-12.2.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:f3f40b3c5a968281fd507d519e444c35f0ff171237f4fdde090dd60699458421", size = 4695490, upload-time = "2026-04-01T14:43:15.584Z" }, + { url = "https://files.pythonhosted.org/packages/de/af/4e8e6869cbed569d43c416fad3dc4ecb944cb5d9492defaed89ddd6fe871/pillow-12.2.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:03e7e372d5240cc23e9f07deca4d775c0817bffc641b01e9c3af208dbd300987", size = 6284462, upload-time = "2026-04-01T14:43:18.268Z" }, + { url = "https://files.pythonhosted.org/packages/e9/9e/c05e19657fd57841e476be1ab46c4d501bffbadbafdc31a6d665f8b737b6/pillow-12.2.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:b86024e52a1b269467a802258c25521e6d742349d760728092e1bc2d135b4d76", size = 8094744, upload-time = "2026-04-01T14:43:20.716Z" }, + { url = "https://files.pythonhosted.org/packages/2b/54/1789c455ed10176066b6e7e6da1b01e50e36f94ba584dc68d9eebfe9156d/pillow-12.2.0-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:7371b48c4fa448d20d2714c9a1f775a81155050d383333e0a6c15b1123dda005", size = 6398371, upload-time = "2026-04-01T14:43:23.443Z" }, + { url = "https://files.pythonhosted.org/packages/43/e3/fdc657359e919462369869f1c9f0e973f353f9a9ee295a39b1fea8ee1a77/pillow-12.2.0-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:62f5409336adb0663b7caa0da5c7d9e7bdbaae9ce761d34669420c2a801b2780", size = 7087215, upload-time = "2026-04-01T14:43:26.758Z" }, + { url = "https://files.pythonhosted.org/packages/8b/f8/2f6825e441d5b1959d2ca5adec984210f1ec086435b0ed5f52c19b3b8a6e/pillow-12.2.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:01afa7cf67f74f09523699b4e88c73fb55c13346d212a59a2db1f86b0a63e8c5", size = 6509783, upload-time = "2026-04-01T14:43:29.56Z" }, + { url = "https://files.pythonhosted.org/packages/67/f9/029a27095ad20f854f9dba026b3ea6428548316e057e6fc3545409e86651/pillow-12.2.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:fc3d34d4a8fbec3e88a79b92e5465e0f9b842b628675850d860b8bd300b159f5", size = 7212112, upload-time = "2026-04-01T14:43:32.091Z" }, + { url = "https://files.pythonhosted.org/packages/be/42/025cfe05d1be22dbfdb4f264fe9de1ccda83f66e4fc3aac94748e784af04/pillow-12.2.0-cp312-cp312-win32.whl", hash = "sha256:58f62cc0f00fd29e64b29f4fd923ffdb3859c9f9e6105bfc37ba1d08994e8940", size = 6378489, upload-time = "2026-04-01T14:43:34.601Z" }, + { url = "https://files.pythonhosted.org/packages/5d/7b/25a221d2c761c6a8ae21bfa3874988ff2583e19cf8a27bf2fee358df7942/pillow-12.2.0-cp312-cp312-win_amd64.whl", hash = "sha256:7f84204dee22a783350679a0333981df803dac21a0190d706a50475e361c93f5", size = 7084129, upload-time = "2026-04-01T14:43:37.213Z" }, + { url = "https://files.pythonhosted.org/packages/10/e1/542a474affab20fd4a0f1836cb234e8493519da6b76899e30bcc5d990b8b/pillow-12.2.0-cp312-cp312-win_arm64.whl", hash = "sha256:af73337013e0b3b46f175e79492d96845b16126ddf79c438d7ea7ff27783a414", size = 2463612, upload-time = "2026-04-01T14:43:39.421Z" }, + { url = "https://files.pythonhosted.org/packages/4a/01/53d10cf0dbad820a8db274d259a37ba50b88b24768ddccec07355382d5ad/pillow-12.2.0-cp313-cp313-ios_13_0_arm64_iphoneos.whl", hash = "sha256:8297651f5b5679c19968abefd6bb84d95fe30ef712eb1b2d9b2d31ca61267f4c", size = 4100837, upload-time = "2026-04-01T14:43:41.506Z" }, + { url = "https://files.pythonhosted.org/packages/0f/98/f3a6657ecb698c937f6c76ee564882945f29b79bad496abcba0e84659ec5/pillow-12.2.0-cp313-cp313-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:50d8520da2a6ce0af445fa6d648c4273c3eeefbc32d7ce049f22e8b5c3daecc2", size = 4176528, upload-time = "2026-04-01T14:43:43.773Z" }, + { url = "https://files.pythonhosted.org/packages/69/bc/8986948f05e3ea490b8442ea1c1d4d990b24a7e43d8a51b2c7d8b1dced36/pillow-12.2.0-cp313-cp313-ios_13_0_x86_64_iphonesimulator.whl", hash = "sha256:766cef22385fa1091258ad7e6216792b156dc16d8d3fa607e7545b2b72061f1c", size = 3640401, upload-time = "2026-04-01T14:43:45.87Z" }, + { url = "https://files.pythonhosted.org/packages/34/46/6c717baadcd62bc8ed51d238d521ab651eaa74838291bda1f86fe1f864c9/pillow-12.2.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:5d2fd0fa6b5d9d1de415060363433f28da8b1526c1c129020435e186794b3795", size = 5308094, upload-time = "2026-04-01T14:43:48.438Z" }, + { url = "https://files.pythonhosted.org/packages/71/43/905a14a8b17fdb1ccb58d282454490662d2cb89a6bfec26af6d3520da5ec/pillow-12.2.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:56b25336f502b6ed02e889f4ece894a72612fe885889a6e8c4c80239ff6e5f5f", size = 4695402, upload-time = "2026-04-01T14:43:51.292Z" }, + { url = "https://files.pythonhosted.org/packages/73/dd/42107efcb777b16fa0393317eac58f5b5cf30e8392e266e76e51cff28c3d/pillow-12.2.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:f1c943e96e85df3d3478f7b691f229887e143f81fedab9b20205349ab04d73ed", size = 6280005, upload-time = "2026-04-01T14:43:54.242Z" }, + { url = "https://files.pythonhosted.org/packages/a8/68/b93e09e5e8549019e61acf49f65b1a8530765a7f812c77a7461bca7e4494/pillow-12.2.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:03f6fab9219220f041c74aeaa2939ff0062bd5c364ba9ce037197f4c6d498cd9", size = 8090669, upload-time = "2026-04-01T14:43:57.335Z" }, + { url = "https://files.pythonhosted.org/packages/4b/6e/3ccb54ce8ec4ddd1accd2d89004308b7b0b21c4ac3d20fa70af4760a4330/pillow-12.2.0-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5cdfebd752ec52bf5bb4e35d9c64b40826bc5b40a13df7c3cda20a2c03a0f5ed", size = 6395194, upload-time = "2026-04-01T14:43:59.864Z" }, + { url = "https://files.pythonhosted.org/packages/67/ee/21d4e8536afd1a328f01b359b4d3997b291ffd35a237c877b331c1c3b71c/pillow-12.2.0-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:eedf4b74eda2b5a4b2b2fb4c006d6295df3bf29e459e198c90ea48e130dc75c3", size = 7082423, upload-time = "2026-04-01T14:44:02.74Z" }, + { url = "https://files.pythonhosted.org/packages/78/5f/e9f86ab0146464e8c133fe85df987ed9e77e08b29d8d35f9f9f4d6f917ba/pillow-12.2.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:00a2865911330191c0b818c59103b58a5e697cae67042366970a6b6f1b20b7f9", size = 6505667, upload-time = "2026-04-01T14:44:05.381Z" }, + { url = "https://files.pythonhosted.org/packages/ed/1e/409007f56a2fdce61584fd3acbc2bbc259857d555196cedcadc68c015c82/pillow-12.2.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:1e1757442ed87f4912397c6d35a0db6a7b52592156014706f17658ff58bbf795", size = 7208580, upload-time = "2026-04-01T14:44:08.39Z" }, + { url = "https://files.pythonhosted.org/packages/23/c4/7349421080b12fb35414607b8871e9534546c128a11965fd4a7002ccfbee/pillow-12.2.0-cp313-cp313-win32.whl", hash = "sha256:144748b3af2d1b358d41286056d0003f47cb339b8c43a9ea42f5fea4d8c66b6e", size = 6375896, upload-time = "2026-04-01T14:44:11.197Z" }, + { url = "https://files.pythonhosted.org/packages/3f/82/8a3739a5e470b3c6cbb1d21d315800d8e16bff503d1f16b03a4ec3212786/pillow-12.2.0-cp313-cp313-win_amd64.whl", hash = "sha256:390ede346628ccc626e5730107cde16c42d3836b89662a115a921f28440e6a3b", size = 7081266, upload-time = "2026-04-01T14:44:13.947Z" }, + { url = "https://files.pythonhosted.org/packages/c3/25/f968f618a062574294592f668218f8af564830ccebdd1fa6200f598e65c5/pillow-12.2.0-cp313-cp313-win_arm64.whl", hash = "sha256:8023abc91fba39036dbce14a7d6535632f99c0b857807cbbbf21ecc9f4717f06", size = 2463508, upload-time = "2026-04-01T14:44:16.312Z" }, + { url = "https://files.pythonhosted.org/packages/4d/a4/b342930964e3cb4dce5038ae34b0eab4653334995336cd486c5a8c25a00c/pillow-12.2.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:042db20a421b9bafecc4b84a8b6e444686bd9d836c7fd24542db3e7df7baad9b", size = 5309927, upload-time = "2026-04-01T14:44:18.89Z" }, + { url = "https://files.pythonhosted.org/packages/9f/de/23198e0a65a9cf06123f5435a5d95cea62a635697f8f03d134d3f3a96151/pillow-12.2.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:dd025009355c926a84a612fecf58bb315a3f6814b17ead51a8e48d3823d9087f", size = 4698624, upload-time = "2026-04-01T14:44:21.115Z" }, + { url = "https://files.pythonhosted.org/packages/01/a6/1265e977f17d93ea37aa28aa81bad4fa597933879fac2520d24e021c8da3/pillow-12.2.0-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:88ddbc66737e277852913bd1e07c150cc7bb124539f94c4e2df5344494e0a612", size = 6321252, upload-time = "2026-04-01T14:44:23.663Z" }, + { url = "https://files.pythonhosted.org/packages/3c/83/5982eb4a285967baa70340320be9f88e57665a387e3a53a7f0db8231a0cd/pillow-12.2.0-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:d362d1878f00c142b7e1a16e6e5e780f02be8195123f164edf7eddd911eefe7c", size = 8126550, upload-time = "2026-04-01T14:44:26.772Z" }, + { url = "https://files.pythonhosted.org/packages/4e/48/6ffc514adce69f6050d0753b1a18fd920fce8cac87620d5a31231b04bfc5/pillow-12.2.0-cp313-cp313t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:2c727a6d53cb0018aadd8018c2b938376af27914a68a492f59dfcaca650d5eea", size = 6433114, upload-time = "2026-04-01T14:44:29.615Z" }, + { url = "https://files.pythonhosted.org/packages/36/a3/f9a77144231fb8d40ee27107b4463e205fa4677e2ca2548e14da5cf18dce/pillow-12.2.0-cp313-cp313t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:efd8c21c98c5cc60653bcb311bef2ce0401642b7ce9d09e03a7da87c878289d4", size = 7115667, upload-time = "2026-04-01T14:44:32.773Z" }, + { url = "https://files.pythonhosted.org/packages/c1/fc/ac4ee3041e7d5a565e1c4fd72a113f03b6394cc72ab7089d27608f8aaccb/pillow-12.2.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:9f08483a632889536b8139663db60f6724bfcb443c96f1b18855860d7d5c0fd4", size = 6538966, upload-time = "2026-04-01T14:44:35.252Z" }, + { url = "https://files.pythonhosted.org/packages/c0/a8/27fb307055087f3668f6d0a8ccb636e7431d56ed0750e07a60547b1e083e/pillow-12.2.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:dac8d77255a37e81a2efcbd1fc05f1c15ee82200e6c240d7e127e25e365c39ea", size = 7238241, upload-time = "2026-04-01T14:44:37.875Z" }, + { url = "https://files.pythonhosted.org/packages/ad/4b/926ab182c07fccae9fcb120043464e1ff1564775ec8864f21a0ebce6ac25/pillow-12.2.0-cp313-cp313t-win32.whl", hash = "sha256:ee3120ae9dff32f121610bb08e4313be87e03efeadfc6c0d18f89127e24d0c24", size = 6379592, upload-time = "2026-04-01T14:44:40.336Z" }, + { url = "https://files.pythonhosted.org/packages/c2/c4/f9e476451a098181b30050cc4c9a3556b64c02cf6497ea421ac047e89e4b/pillow-12.2.0-cp313-cp313t-win_amd64.whl", hash = "sha256:325ca0528c6788d2a6c3d40e3568639398137346c3d6e66bb61db96b96511c98", size = 7085542, upload-time = "2026-04-01T14:44:43.251Z" }, + { url = "https://files.pythonhosted.org/packages/00/a4/285f12aeacbe2d6dc36c407dfbbe9e96d4a80b0fb710a337f6d2ad978c75/pillow-12.2.0-cp313-cp313t-win_arm64.whl", hash = "sha256:2e5a76d03a6c6dcef67edabda7a52494afa4035021a79c8558e14af25313d453", size = 2465765, upload-time = "2026-04-01T14:44:45.996Z" }, + { url = "https://files.pythonhosted.org/packages/bf/98/4595daa2365416a86cb0d495248a393dfc84e96d62ad080c8546256cb9c0/pillow-12.2.0-cp314-cp314-ios_13_0_arm64_iphoneos.whl", hash = "sha256:3adc9215e8be0448ed6e814966ecf3d9952f0ea40eb14e89a102b87f450660d8", size = 4100848, upload-time = "2026-04-01T14:44:48.48Z" }, + { url = "https://files.pythonhosted.org/packages/0b/79/40184d464cf89f6663e18dfcf7ca21aae2491fff1a16127681bf1fa9b8cf/pillow-12.2.0-cp314-cp314-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:6a9adfc6d24b10f89588096364cc726174118c62130c817c2837c60cf08a392b", size = 4176515, upload-time = "2026-04-01T14:44:51.353Z" }, + { url = "https://files.pythonhosted.org/packages/b0/63/703f86fd4c422a9cf722833670f4f71418fb116b2853ff7da722ea43f184/pillow-12.2.0-cp314-cp314-ios_13_0_x86_64_iphonesimulator.whl", hash = "sha256:6a6e67ea2e6feda684ed370f9a1c52e7a243631c025ba42149a2cc5934dec295", size = 3640159, upload-time = "2026-04-01T14:44:53.588Z" }, + { url = "https://files.pythonhosted.org/packages/71/e0/fb22f797187d0be2270f83500aab851536101b254bfa1eae10795709d283/pillow-12.2.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:2bb4a8d594eacdfc59d9e5ad972aa8afdd48d584ffd5f13a937a664c3e7db0ed", size = 5312185, upload-time = "2026-04-01T14:44:56.039Z" }, + { url = "https://files.pythonhosted.org/packages/ba/8c/1a9e46228571de18f8e28f16fabdfc20212a5d019f3e3303452b3f0a580d/pillow-12.2.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:80b2da48193b2f33ed0c32c38140f9d3186583ce7d516526d462645fd98660ae", size = 4695386, upload-time = "2026-04-01T14:44:58.663Z" }, + { url = "https://files.pythonhosted.org/packages/70/62/98f6b7f0c88b9addd0e87c217ded307b36be024d4ff8869a812b241d1345/pillow-12.2.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:22db17c68434de69d8ecfc2fe821569195c0c373b25cccb9cbdacf2c6e53c601", size = 6280384, upload-time = "2026-04-01T14:45:01.5Z" }, + { url = "https://files.pythonhosted.org/packages/5e/03/688747d2e91cfbe0e64f316cd2e8005698f76ada3130d0194664174fa5de/pillow-12.2.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:7b14cc0106cd9aecda615dd6903840a058b4700fcb817687d0ee4fc8b6e389be", size = 8091599, upload-time = "2026-04-01T14:45:04.5Z" }, + { url = "https://files.pythonhosted.org/packages/f6/35/577e22b936fcdd66537329b33af0b4ccfefaeabd8aec04b266528cddb33c/pillow-12.2.0-cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8cbeb542b2ebc6fcdacabf8aca8c1a97c9b3ad3927d46b8723f9d4f033288a0f", size = 6396021, upload-time = "2026-04-01T14:45:07.117Z" }, + { url = "https://files.pythonhosted.org/packages/11/8d/d2532ad2a603ca2b93ad9f5135732124e57811d0168155852f37fbce2458/pillow-12.2.0-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4bfd07bc812fbd20395212969e41931001fd59eb55a60658b0e5710872e95286", size = 7083360, upload-time = "2026-04-01T14:45:09.763Z" }, + { url = "https://files.pythonhosted.org/packages/5e/26/d325f9f56c7e039034897e7380e9cc202b1e368bfd04d4cbe6a441f02885/pillow-12.2.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:9aba9a17b623ef750a4d11b742cbafffeb48a869821252b30ee21b5e91392c50", size = 6507628, upload-time = "2026-04-01T14:45:12.378Z" }, + { url = "https://files.pythonhosted.org/packages/5f/f7/769d5632ffb0988f1c5e7660b3e731e30f7f8ec4318e94d0a5d674eb65a4/pillow-12.2.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:deede7c263feb25dba4e82ea23058a235dcc2fe1f6021025dc71f2b618e26104", size = 7209321, upload-time = "2026-04-01T14:45:15.122Z" }, + { url = "https://files.pythonhosted.org/packages/6a/7a/c253e3c645cd47f1aceea6a8bacdba9991bf45bb7dfe927f7c893e89c93c/pillow-12.2.0-cp314-cp314-win32.whl", hash = "sha256:632ff19b2778e43162304d50da0181ce24ac5bb8180122cbe1bf4673428328c7", size = 6479723, upload-time = "2026-04-01T14:45:17.797Z" }, + { url = "https://files.pythonhosted.org/packages/cd/8b/601e6566b957ca50e28725cb6c355c59c2c8609751efbecd980db44e0349/pillow-12.2.0-cp314-cp314-win_amd64.whl", hash = "sha256:4e6c62e9d237e9b65fac06857d511e90d8461a32adcc1b9065ea0c0fa3a28150", size = 7217400, upload-time = "2026-04-01T14:45:20.529Z" }, + { url = "https://files.pythonhosted.org/packages/d6/94/220e46c73065c3e2951bb91c11a1fb636c8c9ad427ac3ce7d7f3359b9b2f/pillow-12.2.0-cp314-cp314-win_arm64.whl", hash = "sha256:b1c1fbd8a5a1af3412a0810d060a78b5136ec0836c8a4ef9aa11807f2a22f4e1", size = 2554835, upload-time = "2026-04-01T14:45:23.162Z" }, + { url = "https://files.pythonhosted.org/packages/b6/ab/1b426a3974cb0e7da5c29ccff4807871d48110933a57207b5a676cccc155/pillow-12.2.0-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:57850958fe9c751670e49b2cecf6294acc99e562531f4bd317fa5ddee2068463", size = 5314225, upload-time = "2026-04-01T14:45:25.637Z" }, + { url = "https://files.pythonhosted.org/packages/19/1e/dce46f371be2438eecfee2a1960ee2a243bbe5e961890146d2dee1ff0f12/pillow-12.2.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:d5d38f1411c0ed9f97bcb49b7bd59b6b7c314e0e27420e34d99d844b9ce3b6f3", size = 4698541, upload-time = "2026-04-01T14:45:28.355Z" }, + { url = "https://files.pythonhosted.org/packages/55/c3/7fbecf70adb3a0c33b77a300dc52e424dc22ad8cdc06557a2e49523b703d/pillow-12.2.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:5c0a9f29ca8e79f09de89293f82fc9b0270bb4af1d58bc98f540cc4aedf03166", size = 6322251, upload-time = "2026-04-01T14:45:30.924Z" }, + { url = "https://files.pythonhosted.org/packages/1c/3c/7fbc17cfb7e4fe0ef1642e0abc17fc6c94c9f7a16be41498e12e2ba60408/pillow-12.2.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:1610dd6c61621ae1cf811bef44d77e149ce3f7b95afe66a4512f8c59f25d9ebe", size = 8127807, upload-time = "2026-04-01T14:45:33.908Z" }, + { url = "https://files.pythonhosted.org/packages/ff/c3/a8ae14d6defd2e448493ff512fae903b1e9bd40b72efb6ec55ce0048c8ce/pillow-12.2.0-cp314-cp314t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0a34329707af4f73cf1782a36cd2289c0368880654a2c11f027bcee9052d35dd", size = 6433935, upload-time = "2026-04-01T14:45:36.623Z" }, + { url = "https://files.pythonhosted.org/packages/6e/32/2880fb3a074847ac159d8f902cb43278a61e85f681661e7419e6596803ed/pillow-12.2.0-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8e9c4f5b3c546fa3458a29ab22646c1c6c787ea8f5ef51300e5a60300736905e", size = 7116720, upload-time = "2026-04-01T14:45:39.258Z" }, + { url = "https://files.pythonhosted.org/packages/46/87/495cc9c30e0129501643f24d320076f4cc54f718341df18cc70ec94c44e1/pillow-12.2.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:fb043ee2f06b41473269765c2feae53fc2e2fbf96e5e22ca94fb5ad677856f06", size = 6540498, upload-time = "2026-04-01T14:45:41.879Z" }, + { url = "https://files.pythonhosted.org/packages/18/53/773f5edca692009d883a72211b60fdaf8871cbef075eaa9d577f0a2f989e/pillow-12.2.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:f278f034eb75b4e8a13a54a876cc4a5ab39173d2cdd93a638e1b467fc545ac43", size = 7239413, upload-time = "2026-04-01T14:45:44.705Z" }, + { url = "https://files.pythonhosted.org/packages/c9/e4/4b64a97d71b2a83158134abbb2f5bd3f8a2ea691361282f010998f339ec7/pillow-12.2.0-cp314-cp314t-win32.whl", hash = "sha256:6bb77b2dcb06b20f9f4b4a8454caa581cd4dd0643a08bacf821216a16d9c8354", size = 6482084, upload-time = "2026-04-01T14:45:47.568Z" }, + { url = "https://files.pythonhosted.org/packages/ba/13/306d275efd3a3453f72114b7431c877d10b1154014c1ebbedd067770d629/pillow-12.2.0-cp314-cp314t-win_amd64.whl", hash = "sha256:6562ace0d3fb5f20ed7290f1f929cae41b25ae29528f2af1722966a0a02e2aa1", size = 7225152, upload-time = "2026-04-01T14:45:50.032Z" }, + { url = "https://files.pythonhosted.org/packages/ff/6e/cf826fae916b8658848d7b9f38d88da6396895c676e8086fc0988073aaf8/pillow-12.2.0-cp314-cp314t-win_arm64.whl", hash = "sha256:aa88ccfe4e32d362816319ed727a004423aab09c5cea43c01a4b435643fa34eb", size = 2556579, upload-time = "2026-04-01T14:45:52.529Z" }, + { url = "https://files.pythonhosted.org/packages/4e/b7/2437044fb910f499610356d1352e3423753c98e34f915252aafecc64889f/pillow-12.2.0-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:0538bd5e05efec03ae613fd89c4ce0368ecd2ba239cc25b9f9be7ed426b0af1f", size = 5273969, upload-time = "2026-04-01T14:45:55.538Z" }, + { url = "https://files.pythonhosted.org/packages/f6/f4/8316e31de11b780f4ac08ef3654a75555e624a98db1056ecb2122d008d5a/pillow-12.2.0-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:394167b21da716608eac917c60aa9b969421b5dcbbe02ae7f013e7b85811c69d", size = 4659674, upload-time = "2026-04-01T14:45:58.093Z" }, + { url = "https://files.pythonhosted.org/packages/d4/37/664fca7201f8bb2aa1d20e2c3d5564a62e6ae5111741966c8319ca802361/pillow-12.2.0-pp311-pypy311_pp73-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:5d04bfa02cc2d23b497d1e90a0f927070043f6cbf303e738300532379a4b4e0f", size = 5288479, upload-time = "2026-04-01T14:46:01.141Z" }, + { url = "https://files.pythonhosted.org/packages/49/62/5b0ed78fce87346be7a5cfcfaaad91f6a1f98c26f86bdbafa2066c647ef6/pillow-12.2.0-pp311-pypy311_pp73-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:0c838a5125cee37e68edec915651521191cef1e6aa336b855f495766e77a366e", size = 7032230, upload-time = "2026-04-01T14:46:03.874Z" }, + { url = "https://files.pythonhosted.org/packages/c3/28/ec0fc38107fc32536908034e990c47914c57cd7c5a3ece4d8d8f7ffd7e27/pillow-12.2.0-pp311-pypy311_pp73-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4a6c9fa44005fa37a91ebfc95d081e8079757d2e904b27103f4f5fa6f0bf78c0", size = 5355404, upload-time = "2026-04-01T14:46:06.33Z" }, + { url = "https://files.pythonhosted.org/packages/5e/8b/51b0eddcfa2180d60e41f06bd6d0a62202b20b59c68f5a132e615b75aecf/pillow-12.2.0-pp311-pypy311_pp73-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:25373b66e0dd5905ed63fa3cae13c82fbddf3079f2c8bf15c6fb6a35586324c1", size = 6002215, upload-time = "2026-04-01T14:46:08.83Z" }, + { url = "https://files.pythonhosted.org/packages/bc/60/5382c03e1970de634027cee8e1b7d39776b778b81812aaf45b694dfe9e28/pillow-12.2.0-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:bfa9c230d2fe991bed5318a5f119bd6780cda2915cca595393649fc118ab895e", size = 7080946, upload-time = "2026-04-01T14:46:11.734Z" }, +] + [[package]] name = "pkginfo" version = "1.12.1.2" @@ -3873,6 +4032,18 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/54/20/4d324d65cc6d9205fabedc306948156824eb9f0ee1633355a8f7ec5c66bf/pluggy-1.6.0-py3-none-any.whl", hash = "sha256:e920276dd6813095e9377c0bc5566d94c932c33b27a3e3945d8389c374dd4746", size = 20538, upload-time = "2025-05-15T12:30:06.134Z" }, ] +[[package]] +name = "prompt-toolkit" +version = "3.0.52" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "wcwidth" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/a1/96/06e01a7b38dce6fe1db213e061a4602dd6032a8a97ef6c1a862537732421/prompt_toolkit-3.0.52.tar.gz", hash = "sha256:28cde192929c8e7321de85de1ddbe736f1375148b02f2e17edd840042b1be855", size = 434198, upload-time = "2025-08-27T15:24:02.057Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/84/03/0d3ce49e2505ae70cf43bc5bb3033955d2fc9f932163e84dc0779cc47f48/prompt_toolkit-3.0.52-py3-none-any.whl", hash = "sha256:9aac639a3bbd33284347de5ad8d68ecc044b91a762dc39b7c21095fcd6a19955", size = 391431, upload-time = "2025-08-27T15:23:59.498Z" }, +] + [[package]] name = "propcache" version = "0.4.1" @@ -4808,15 +4979,15 @@ wheels = [ [[package]] name = "rich" -version = "15.0.0" +version = "14.3.4" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "markdown-it-py" }, { name = "pygments" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/c0/8f/0722ca900cc807c13a6a0c696dacf35430f72e0ec571c4275d2371fca3e9/rich-15.0.0.tar.gz", hash = "sha256:edd07a4824c6b40189fb7ac9bc4c52536e9780fbbfbddf6f1e2502c31b068c36", size = 230680, upload-time = "2026-04-12T08:24:00.75Z" } +sdist = { url = "https://files.pythonhosted.org/packages/e9/67/cae617f1351490c25a4b8ac3b8b63a4dda609295d8222bad12242dfdc629/rich-14.3.4.tar.gz", hash = "sha256:817e02727f2b25b40ef56f5aa2217f400c8489f79ca8f46ea2b70dd5e14558a9", size = 230524, upload-time = "2026-04-11T02:57:45.419Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/82/3b/64d4899d73f91ba49a8c18a8ff3f0ea8f1c1d75481760df8c68ef5235bf5/rich-15.0.0-py3-none-any.whl", hash = "sha256:33bd4ef74232fb73fe9279a257718407f169c09b78a87ad3d296f548e27de0bb", size = 310654, upload-time = "2026-04-12T08:24:02.83Z" }, + { url = "https://files.pythonhosted.org/packages/b3/76/6d163cfac87b632216f71879e6b2cf17163f773ff59c00b5ff4900a80fa3/rich-14.3.4-py3-none-any.whl", hash = "sha256:07e7adb4690f68864777b1450859253bed81a99a31ac321ac1817b2313558952", size = 310480, upload-time = "2026-04-11T02:57:47.484Z" }, ] [[package]] @@ -5018,6 +5189,27 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/b7/ce/149a00dd41f10bc29e5921b496af8b574d8413afcd5e30dfa0ed46c2cc5e/six-1.17.0-py2.py3-none-any.whl", hash = "sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274", size = 11050, upload-time = "2024-12-04T17:35:26.475Z" }, ] +[[package]] +name = "slack-bolt" +version = "1.28.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "slack-sdk" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/5c/97/a62dde97e84027b252807f2044bed2edcda2d063a5cb0c535fb2be8d9b5d/slack_bolt-1.28.0.tar.gz", hash = "sha256:bfe367d867e8fb157a057248ebd4ac2d7f43acac6d0700fa31381db1e10f3b0f", size = 130768, upload-time = "2026-04-06T23:24:59.936Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/81/a9/697b6a92c728f09d5ef6b8e83dc6c8a87bc6d59499b2933ed067f11b7e30/slack_bolt-1.28.0-py2.py3-none-any.whl", hash = "sha256:738d1ca5e7c7039b6e18103d29267ced6e18c2517053eff18991fdd593acce5c", size = 234819, upload-time = "2026-04-06T23:24:58.278Z" }, +] + +[[package]] +name = "slack-sdk" +version = "3.41.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/22/35/fc009118a13187dd9731657c60138e5a7c2dea88681a7f04dc406af5da7d/slack_sdk-3.41.0.tar.gz", hash = "sha256:eb61eb12a65bebeca9cb5d36b3f799e836ed2be21b456d15df2627cfe34076ca", size = 250568, upload-time = "2026-03-12T16:10:11.381Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/a1/df/2e4be347ff98281b505cc0ccf141408cdd25eb5ca9f3830deb361b2472d3/slack_sdk-3.41.0-py2.py3-none-any.whl", hash = "sha256:bb18dcdfff1413ec448e759cf807ec3324090993d8ab9111c74081623b692a89", size = 313885, upload-time = "2026-03-12T16:10:09.811Z" }, +] + [[package]] name = "sniffio" version = "1.3.1" @@ -5036,6 +5228,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/c8/78/3565d011c61f5a43488987ee32b6f3f656e7f107ac2782dd57bdd7d91d9a/snowballstemmer-3.0.1-py3-none-any.whl", hash = "sha256:6cd7b3897da8d6c9ffb968a6781fa6532dce9c3618a4b127d920dab764a19064", size = 103274, upload-time = "2025-05-09T16:34:50.371Z" }, ] +[[package]] +name = "soupsieve" +version = "2.8.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/7b/ae/2d9c981590ed9999a0d91755b47fc74f74de286b0f5cee14c9269041e6c4/soupsieve-2.8.3.tar.gz", hash = "sha256:3267f1eeea4251fb42728b6dfb746edc9acaffc4a45b27e19450b676586e8349", size = 118627, upload-time = "2026-01-20T04:27:02.457Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/46/2c/1462b1d0a634697ae9e55b3cecdcb64788e8b7d63f54d923fcd0bb140aed/soupsieve-2.8.3-py3-none-any.whl", hash = "sha256:ed64f2ba4eebeab06cc4962affce381647455978ffc1e36bb79a545b91f45a95", size = 37016, upload-time = "2026-01-20T04:27:01.012Z" }, +] + [[package]] name = "sqlalchemy" version = "2.0.49" @@ -5145,6 +5346,57 @@ 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" }, ] +[[package]] +name = "strands-agents" +version = "1.39.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "boto3" }, + { name = "botocore" }, + { name = "docstring-parser" }, + { name = "jsonschema" }, + { name = "mcp" }, + { name = "opentelemetry-api" }, + { name = "opentelemetry-instrumentation-threading" }, + { name = "opentelemetry-sdk" }, + { name = "pydantic" }, + { name = "pyyaml" }, + { name = "typing-extensions" }, + { name = "watchdog" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/d6/5b/e267a7dab0b4a6d39133c9c0c516f93f33483e29f39e05c03b755f993ef6/strands_agents-1.39.0.tar.gz", hash = "sha256:efff5914323b8b4b472ca3f13c7115a5746935b00bc86dacc40a5d1ab1242817", size = 873258, upload-time = "2026-05-08T13:27:19.661Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/95/41/d054b5a5f54175eb4e775d1e408e169439eba6be63e9e8f2e77ff44e38fc/strands_agents-1.39.0-py3-none-any.whl", hash = "sha256:7369dbfc6be29f59483a6183f5aacf0bdd0e7e5973b4b70f8d0e663880d42f79", size = 430272, upload-time = "2026-05-08T13:27:18.088Z" }, +] + +[[package]] +name = "strands-agents-tools" +version = "0.5.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "aiohttp" }, + { name = "aws-requests-auth" }, + { name = "botocore" }, + { name = "dill" }, + { name = "markdownify" }, + { name = "pillow" }, + { name = "prompt-toolkit" }, + { name = "pyjwt" }, + { name = "requests" }, + { name = "rich" }, + { name = "slack-bolt" }, + { name = "strands-agents" }, + { name = "sympy" }, + { name = "tenacity" }, + { name = "typing-extensions" }, + { name = "tzdata", marker = "sys_platform == 'win32'" }, + { name = "watchdog" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/63/32/710a49ffd32b0a232ec1731620ee6105c045e9a77ecee1f3ecaa1a80a6cd/strands_agents_tools-0.5.2.tar.gz", hash = "sha256:96763c8ae75933c5dd327cca87561f573aed720c9c0f3d17fd20835910d11381", size = 483164, upload-time = "2026-04-30T17:08:13.151Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/59/ef/fe73b6d25d095784d2e1f6f33419265e796143100fb2f32a6e86f8ae68af/strands_agents_tools-0.5.2-py3-none-any.whl", hash = "sha256:8f85e4cb28d9411e62e1f159aa7e300d3a0f4b1d2b878a7cdfd5d746d9333343", size = 316178, upload-time = "2026-04-30T17:08:11.416Z" }, +] + [[package]] name = "sympy" version = "1.14.0" @@ -5204,6 +5456,9 @@ opentelemetry = [ pydantic = [ { name = "pydantic" }, ] +strands-agents = [ + { name = "strands-agents" }, +] [package.dev-dependencies] dev = [ @@ -5241,6 +5496,8 @@ dev = [ { name = "pytest-xdist" }, { name = "ruff" }, { name = "setuptools" }, + { name = "strands-agents" }, + { name = "strands-agents-tools" }, { name = "toml" }, { name = "twine" }, ] @@ -5265,11 +5522,12 @@ requires-dist = [ { name = "protobuf", specifier = ">=3.20,<7.0.0" }, { name = "pydantic", marker = "extra == 'pydantic'", specifier = ">=2.0.0,<3" }, { name = "python-dateutil", marker = "python_full_version < '3.11'", specifier = ">=2.8.2,<3" }, + { name = "strands-agents", marker = "extra == 'strands-agents'", specifier = ">=1.39.0" }, { name = "types-aioboto3", extras = ["s3"], marker = "extra == 'aioboto3'", specifier = ">=10.4.0" }, { name = "types-protobuf", specifier = ">=3.20,<7.0.0" }, { name = "typing-extensions", specifier = ">=4.2.0,<5" }, ] -provides-extras = ["grpc", "opentelemetry", "pydantic", "openai-agents", "google-adk", "langgraph", "langsmith", "lambda-worker-otel", "aioboto3"] +provides-extras = ["grpc", "opentelemetry", "pydantic", "openai-agents", "google-adk", "langgraph", "langsmith", "lambda-worker-otel", "aioboto3", "strands-agents"] [package.metadata.requires-dev] dev = [ @@ -5307,6 +5565,8 @@ dev = [ { name = "pytest-xdist", specifier = ">=3.6,<4" }, { name = "ruff", specifier = ">=0.15.12,<0.16" }, { name = "setuptools", specifier = "<82" }, + { name = "strands-agents", specifier = ">=1.39.0" }, + { name = "strands-agents-tools", specifier = ">=0.5.2" }, { name = "toml", specifier = ">=0.10.2,<0.11" }, { name = "twine", specifier = ">=4.0.1,<5" }, ] @@ -5758,6 +6018,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/33/e8/e40370e6d74ddba47f002a32919d91310d6074130fe4e17dabcafc15cbf1/watchdog-6.0.0-py3-none-win_ia64.whl", hash = "sha256:a1914259fa9e1454315171103c6a30961236f508b9b623eae470268bbcc6a22f", size = 79067, upload-time = "2024-11-01T14:07:11.845Z" }, ] +[[package]] +name = "wcwidth" +version = "0.7.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/2c/ee/afaf0f85a9a18fe47a67f1e4422ed6cf1fe642f0ae0a2f81166231303c52/wcwidth-0.7.0.tar.gz", hash = "sha256:90e3a7ea092341c44b99562e75d09e4d5160fe7a3974c6fb842a101a95e7eed0", size = 182132, upload-time = "2026-05-02T16:04:12.653Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/41/52/e465037f5375f43533d1a80b6923955201596a99142ed524d77b571a1418/wcwidth-0.7.0-py3-none-any.whl", hash = "sha256:5d69154c429a82910e241c738cd0e2976fac8a2dd47a1a805f4afed1c0f136f2", size = 110825, upload-time = "2026-05-02T16:04:11.033Z" }, +] + [[package]] name = "websockets" version = "15.0.1" From 40481e622898e047db2dc15ef8ccf99ae03aea4f Mon Sep 17 00:00:00 2001 From: Spencer Judge Date: Mon, 1 Jun 2026 15:35:37 -0700 Subject: [PATCH 113/226] Update Core (#1564) --- scripts/gen_protos.py | 2 +- .../api/cloud/billing/v1/message_pb2.py | 25 +- .../api/cloud/billing/v1/message_pb2.pyi | 49 + .../api/cloud/cloudservice/v1/__init__.py | 20 + .../cloudservice/v1/request_response_pb2.py | 142 +- .../cloudservice/v1/request_response_pb2.pyi | 295 ++++ .../api/cloud/cloudservice/v1/service_pb2.py | 30 +- .../cloud/cloudservice/v1/service_pb2_grpc.py | 233 ++- .../cloudservice/v1/service_pb2_grpc.pyi | 80 +- .../cloud/connectivityrule/v1/message_pb2.py | 8 +- .../cloud/connectivityrule/v1/message_pb2.pyi | 13 + temporalio/api/cloud/identity/v1/__init__.py | 4 + .../api/cloud/identity/v1/message_pb2.py | 144 +- .../api/cloud/identity/v1/message_pb2.pyi | 211 ++- temporalio/api/cloud/namespace/v1/__init__.py | 6 + .../api/cloud/namespace/v1/message_pb2.py | 173 ++- .../api/cloud/namespace/v1/message_pb2.pyi | 175 ++- temporalio/api/namespace/v1/message_pb2.py | 38 +- temporalio/api/namespace/v1/message_pb2.pyi | 6 + temporalio/api/workflow/v1/message_pb2.py | 40 +- temporalio/api/workflow/v1/message_pb2.pyi | 43 +- temporalio/api/workflowservice/v1/__init__.py | 16 + .../v1/request_response_pb2.py | 1180 ++++++++------- .../v1/request_response_pb2.pyi | 429 +++++- .../api/workflowservice/v1/service_pb2.py | 22 +- .../workflowservice/v1/service_pb2_grpc.py | 215 +++ .../workflowservice/v1/service_pb2_grpc.pyi | 118 ++ temporalio/bridge/Cargo.lock | 1331 ++++++++--------- temporalio/bridge/Cargo.toml | 6 +- temporalio/bridge/sdk-core | 2 +- temporalio/bridge/services_generated.py | 162 ++ temporalio/bridge/src/client.rs | 1 + temporalio/bridge/src/client_rpc_generated.rs | 81 + tests/worker/test_workflow.py | 3 - 34 files changed, 3848 insertions(+), 1455 deletions(-) diff --git a/scripts/gen_protos.py b/scripts/gen_protos.py index e2be3975b..080bfe7f3 100644 --- a/scripts/gen_protos.py +++ b/scripts/gen_protos.py @@ -10,7 +10,7 @@ base_dir = Path(__file__).parent.parent proto_dir = ( - base_dir / "temporalio" / "bridge" / "sdk-core" / "crates" / "common" / "protos" + base_dir / "temporalio" / "bridge" / "sdk-core" / "crates" / "protos" / "protos" ) api_proto_dir = proto_dir / "api_upstream" api_cloud_proto_dir = proto_dir / "api_cloud_upstream" diff --git a/temporalio/api/cloud/billing/v1/message_pb2.py b/temporalio/api/cloud/billing/v1/message_pb2.py index 541831f83..4cbf846f5 100644 --- a/temporalio/api/cloud/billing/v1/message_pb2.py +++ b/temporalio/api/cloud/billing/v1/message_pb2.py @@ -18,13 +18,16 @@ from google.protobuf import timestamp_pb2 as google_dot_protobuf_dot_timestamp__pb2 DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile( - b'\n+temporal/api/cloud/billing/v1/message.proto\x12\x1dtemporal.api.cloud.billing.v1\x1a\x1egoogle/protobuf/duration.proto\x1a\x1fgoogle/protobuf/timestamp.proto"\xdf\x01\n\x11\x42illingReportSpec\x12\x38\n\x14start_time_inclusive\x18\x01 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x36\n\x12\x65nd_time_exclusive\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x43\n download_url_expiration_duration\x18\x03 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x13\n\x0b\x64\x65scription\x18\x04 \x01(\t"\xa8\x06\n\rBillingReport\x12\n\n\x02id\x18\x01 \x01(\t\x12N\n\x05state\x18\x02 \x01(\x0e\x32?.temporal.api.cloud.billing.v1.BillingReport.BillingReportState\x12>\n\x04spec\x18\x03 \x01(\x0b\x32\x30.temporal.api.cloud.billing.v1.BillingReportSpec\x12L\n\rdownload_info\x18\x04 \x03(\x0b\x32\x35.temporal.api.cloud.billing.v1.BillingReport.Download\x12\x32\n\x0erequested_time\x18\x05 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x32\n\x0egenerated_time\x18\x06 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x1a\n\x12\x61sync_operation_id\x18\x07 \x01(\t\x1a\x80\x02\n\x08\x44ownload\x12\x0b\n\x03url\x18\x01 \x01(\t\x12\x37\n\x13url_expiration_time\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12U\n\x0b\x66ile_format\x18\x03 \x01(\x0e\x32@.temporal.api.cloud.billing.v1.BillingReport.Download.FileFormat\x12\x17\n\x0f\x66ile_size_bytes\x18\x04 \x01(\x03">\n\nFileFormat\x12\x1b\n\x17\x46ILE_FORMAT_UNSPECIFIED\x10\x00\x12\x13\n\x0f\x46ILE_FORMAT_CSV\x10\x01"\xa5\x01\n\x12\x42illingReportState\x12$\n BILLING_REPORT_STATE_UNSPECIFIED\x10\x00\x12$\n BILLING_REPORT_STATE_IN_PROGRESS\x10\x01\x12"\n\x1e\x42ILLING_REPORT_STATE_GENERATED\x10\x02\x12\x1f\n\x1b\x42ILLING_REPORT_STATE_FAILED\x10\x03\x42\xa7\x01\n io.temporal.api.cloud.billing.v1B\x0cMessageProtoP\x01Z+go.temporal.io/api/cloud/billing/v1;billing\xaa\x02\x1fTemporalio.Api.Cloud.Billing.V1\xea\x02#Temporalio::Api::Cloud::Billing::V1b\x06proto3' + b'\n+temporal/api/cloud/billing/v1/message.proto\x12\x1dtemporal.api.cloud.billing.v1\x1a\x1egoogle/protobuf/duration.proto\x1a\x1fgoogle/protobuf/timestamp.proto"\xfd\x03\n\x11\x42illingReportSpec\x12\x38\n\x14start_time_inclusive\x18\x01 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x36\n\x12\x65nd_time_exclusive\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x43\n download_url_expiration_duration\x18\x03 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x13\n\x0b\x64\x65scription\x18\x04 \x01(\t\x12^\n\x0bgranularity\x18\x05 \x01(\x0e\x32I.temporal.api.cloud.billing.v1.BillingReportSpec.BillingReportGranularity"\xbb\x01\n\x18\x42illingReportGranularity\x12*\n&BILLING_REPORT_GRANULARITY_UNSPECIFIED\x10\x00\x12%\n!BILLING_REPORT_GRANULARITY_HOURLY\x10\x01\x12$\n BILLING_REPORT_GRANULARITY_DAILY\x10\x02\x12&\n"BILLING_REPORT_GRANULARITY_MONTHLY\x10\x03"\xa8\x06\n\rBillingReport\x12\n\n\x02id\x18\x01 \x01(\t\x12N\n\x05state\x18\x02 \x01(\x0e\x32?.temporal.api.cloud.billing.v1.BillingReport.BillingReportState\x12>\n\x04spec\x18\x03 \x01(\x0b\x32\x30.temporal.api.cloud.billing.v1.BillingReportSpec\x12L\n\rdownload_info\x18\x04 \x03(\x0b\x32\x35.temporal.api.cloud.billing.v1.BillingReport.Download\x12\x32\n\x0erequested_time\x18\x05 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x32\n\x0egenerated_time\x18\x06 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x1a\n\x12\x61sync_operation_id\x18\x07 \x01(\t\x1a\x80\x02\n\x08\x44ownload\x12\x0b\n\x03url\x18\x01 \x01(\t\x12\x37\n\x13url_expiration_time\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12U\n\x0b\x66ile_format\x18\x03 \x01(\x0e\x32@.temporal.api.cloud.billing.v1.BillingReport.Download.FileFormat\x12\x17\n\x0f\x66ile_size_bytes\x18\x04 \x01(\x03">\n\nFileFormat\x12\x1b\n\x17\x46ILE_FORMAT_UNSPECIFIED\x10\x00\x12\x13\n\x0f\x46ILE_FORMAT_CSV\x10\x01"\xa5\x01\n\x12\x42illingReportState\x12$\n BILLING_REPORT_STATE_UNSPECIFIED\x10\x00\x12$\n BILLING_REPORT_STATE_IN_PROGRESS\x10\x01\x12"\n\x1e\x42ILLING_REPORT_STATE_GENERATED\x10\x02\x12\x1f\n\x1b\x42ILLING_REPORT_STATE_FAILED\x10\x03\x42\xa7\x01\n io.temporal.api.cloud.billing.v1B\x0cMessageProtoP\x01Z+go.temporal.io/api/cloud/billing/v1;billing\xaa\x02\x1fTemporalio.Api.Cloud.Billing.V1\xea\x02#Temporalio::Api::Cloud::Billing::V1b\x06proto3' ) _BILLINGREPORTSPEC = DESCRIPTOR.message_types_by_name["BillingReportSpec"] _BILLINGREPORT = DESCRIPTOR.message_types_by_name["BillingReport"] _BILLINGREPORT_DOWNLOAD = _BILLINGREPORT.nested_types_by_name["Download"] +_BILLINGREPORTSPEC_BILLINGREPORTGRANULARITY = _BILLINGREPORTSPEC.enum_types_by_name[ + "BillingReportGranularity" +] _BILLINGREPORT_DOWNLOAD_FILEFORMAT = _BILLINGREPORT_DOWNLOAD.enum_types_by_name[ "FileFormat" ] @@ -67,13 +70,15 @@ DESCRIPTOR._options = None DESCRIPTOR._serialized_options = b"\n io.temporal.api.cloud.billing.v1B\014MessageProtoP\001Z+go.temporal.io/api/cloud/billing/v1;billing\252\002\037Temporalio.Api.Cloud.Billing.V1\352\002#Temporalio::Api::Cloud::Billing::V1" _BILLINGREPORTSPEC._serialized_start = 144 - _BILLINGREPORTSPEC._serialized_end = 367 - _BILLINGREPORT._serialized_start = 370 - _BILLINGREPORT._serialized_end = 1178 - _BILLINGREPORT_DOWNLOAD._serialized_start = 754 - _BILLINGREPORT_DOWNLOAD._serialized_end = 1010 - _BILLINGREPORT_DOWNLOAD_FILEFORMAT._serialized_start = 948 - _BILLINGREPORT_DOWNLOAD_FILEFORMAT._serialized_end = 1010 - _BILLINGREPORT_BILLINGREPORTSTATE._serialized_start = 1013 - _BILLINGREPORT_BILLINGREPORTSTATE._serialized_end = 1178 + _BILLINGREPORTSPEC._serialized_end = 653 + _BILLINGREPORTSPEC_BILLINGREPORTGRANULARITY._serialized_start = 466 + _BILLINGREPORTSPEC_BILLINGREPORTGRANULARITY._serialized_end = 653 + _BILLINGREPORT._serialized_start = 656 + _BILLINGREPORT._serialized_end = 1464 + _BILLINGREPORT_DOWNLOAD._serialized_start = 1040 + _BILLINGREPORT_DOWNLOAD._serialized_end = 1296 + _BILLINGREPORT_DOWNLOAD_FILEFORMAT._serialized_start = 1234 + _BILLINGREPORT_DOWNLOAD_FILEFORMAT._serialized_end = 1296 + _BILLINGREPORT_BILLINGREPORTSTATE._serialized_start = 1299 + _BILLINGREPORT_BILLINGREPORTSTATE._serialized_end = 1464 # @@protoc_insertion_point(module_scope) diff --git a/temporalio/api/cloud/billing/v1/message_pb2.pyi b/temporalio/api/cloud/billing/v1/message_pb2.pyi index 8a9f262b1..7828afffa 100644 --- a/temporalio/api/cloud/billing/v1/message_pb2.pyi +++ b/temporalio/api/cloud/billing/v1/message_pb2.pyi @@ -25,10 +25,51 @@ DESCRIPTOR: google.protobuf.descriptor.FileDescriptor class BillingReportSpec(google.protobuf.message.Message): DESCRIPTOR: google.protobuf.descriptor.Descriptor + class _BillingReportGranularity: + ValueType = typing.NewType("ValueType", builtins.int) + V: typing_extensions.TypeAlias = ValueType + + class _BillingReportGranularityEnumTypeWrapper( + google.protobuf.internal.enum_type_wrapper._EnumTypeWrapper[ + BillingReportSpec._BillingReportGranularity.ValueType + ], + builtins.type, + ): # noqa: F821 + DESCRIPTOR: google.protobuf.descriptor.EnumDescriptor + BILLING_REPORT_GRANULARITY_UNSPECIFIED: ( + BillingReportSpec._BillingReportGranularity.ValueType + ) # 0 + BILLING_REPORT_GRANULARITY_HOURLY: ( + BillingReportSpec._BillingReportGranularity.ValueType + ) # 1 + BILLING_REPORT_GRANULARITY_DAILY: ( + BillingReportSpec._BillingReportGranularity.ValueType + ) # 2 + BILLING_REPORT_GRANULARITY_MONTHLY: ( + BillingReportSpec._BillingReportGranularity.ValueType + ) # 3 + + class BillingReportGranularity( + _BillingReportGranularity, metaclass=_BillingReportGranularityEnumTypeWrapper + ): ... + BILLING_REPORT_GRANULARITY_UNSPECIFIED: ( + BillingReportSpec.BillingReportGranularity.ValueType + ) # 0 + BILLING_REPORT_GRANULARITY_HOURLY: ( + BillingReportSpec.BillingReportGranularity.ValueType + ) # 1 + BILLING_REPORT_GRANULARITY_DAILY: ( + BillingReportSpec.BillingReportGranularity.ValueType + ) # 2 + BILLING_REPORT_GRANULARITY_MONTHLY: ( + BillingReportSpec.BillingReportGranularity.ValueType + ) # 3 + START_TIME_INCLUSIVE_FIELD_NUMBER: builtins.int END_TIME_EXCLUSIVE_FIELD_NUMBER: builtins.int DOWNLOAD_URL_EXPIRATION_DURATION_FIELD_NUMBER: builtins.int DESCRIPTION_FIELD_NUMBER: builtins.int + GRANULARITY_FIELD_NUMBER: builtins.int @property def start_time_inclusive(self) -> google.protobuf.timestamp_pb2.Timestamp: """The start time of the billing report (in UTC).""" @@ -44,6 +85,11 @@ class BillingReportSpec(google.protobuf.message.Message): """The description for the billing report. Optional, default is empty. """ + granularity: global___BillingReportSpec.BillingReportGranularity.ValueType + """The data granularity of the billing report. + Optional, default is hourly. + temporal:versioning:min_version=v0.16.0 + """ def __init__( self, *, @@ -52,6 +98,7 @@ class BillingReportSpec(google.protobuf.message.Message): download_url_expiration_duration: google.protobuf.duration_pb2.Duration | None = ..., description: builtins.str = ..., + granularity: global___BillingReportSpec.BillingReportGranularity.ValueType = ..., ) -> None: ... def HasField( self, @@ -73,6 +120,8 @@ class BillingReportSpec(google.protobuf.message.Message): b"download_url_expiration_duration", "end_time_exclusive", b"end_time_exclusive", + "granularity", + b"granularity", "start_time_inclusive", b"start_time_inclusive", ], diff --git a/temporalio/api/cloud/cloudservice/v1/__init__.py b/temporalio/api/cloud/cloudservice/v1/__init__.py index 022ee05cb..31e4e7753 100644 --- a/temporalio/api/cloud/cloudservice/v1/__init__.py +++ b/temporalio/api/cloud/cloudservice/v1/__init__.py @@ -11,6 +11,8 @@ CreateBillingReportResponse, CreateConnectivityRuleRequest, CreateConnectivityRuleResponse, + CreateCustomRoleRequest, + CreateCustomRoleResponse, CreateNamespaceExportSinkRequest, CreateNamespaceExportSinkResponse, CreateNamespaceRequest, @@ -29,6 +31,8 @@ DeleteApiKeyResponse, DeleteConnectivityRuleRequest, DeleteConnectivityRuleResponse, + DeleteCustomRoleRequest, + DeleteCustomRoleResponse, DeleteNamespaceExportSinkRequest, DeleteNamespaceExportSinkResponse, DeleteNamespaceRegionRequest, @@ -67,6 +71,10 @@ GetConnectivityRulesResponse, GetCurrentIdentityRequest, GetCurrentIdentityResponse, + GetCustomRoleRequest, + GetCustomRoleResponse, + GetCustomRolesRequest, + GetCustomRolesResponse, GetNamespaceCapacityInfoRequest, GetNamespaceCapacityInfoResponse, GetNamespaceExportSinkRequest, @@ -117,6 +125,8 @@ UpdateAccountResponse, UpdateApiKeyRequest, UpdateApiKeyResponse, + UpdateCustomRoleRequest, + UpdateCustomRoleResponse, UpdateNamespaceExportSinkRequest, UpdateNamespaceExportSinkResponse, UpdateNamespaceRequest, @@ -150,6 +160,8 @@ "CreateBillingReportResponse", "CreateConnectivityRuleRequest", "CreateConnectivityRuleResponse", + "CreateCustomRoleRequest", + "CreateCustomRoleResponse", "CreateNamespaceExportSinkRequest", "CreateNamespaceExportSinkResponse", "CreateNamespaceRequest", @@ -168,6 +180,8 @@ "DeleteApiKeyResponse", "DeleteConnectivityRuleRequest", "DeleteConnectivityRuleResponse", + "DeleteCustomRoleRequest", + "DeleteCustomRoleResponse", "DeleteNamespaceExportSinkRequest", "DeleteNamespaceExportSinkResponse", "DeleteNamespaceRegionRequest", @@ -206,6 +220,10 @@ "GetConnectivityRulesResponse", "GetCurrentIdentityRequest", "GetCurrentIdentityResponse", + "GetCustomRoleRequest", + "GetCustomRoleResponse", + "GetCustomRolesRequest", + "GetCustomRolesResponse", "GetNamespaceCapacityInfoRequest", "GetNamespaceCapacityInfoResponse", "GetNamespaceExportSinkRequest", @@ -256,6 +274,8 @@ "UpdateAccountResponse", "UpdateApiKeyRequest", "UpdateApiKeyResponse", + "UpdateCustomRoleRequest", + "UpdateCustomRoleResponse", "UpdateNamespaceExportSinkRequest", "UpdateNamespaceExportSinkResponse", "UpdateNamespaceRequest", diff --git a/temporalio/api/cloud/cloudservice/v1/request_response_pb2.py b/temporalio/api/cloud/cloudservice/v1/request_response_pb2.py index 23f1b7fad..b1874c825 100644 --- a/temporalio/api/cloud/cloudservice/v1/request_response_pb2.py +++ b/temporalio/api/cloud/cloudservice/v1/request_response_pb2.py @@ -48,7 +48,7 @@ ) DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile( - b'\n9temporal/api/cloud/cloudservice/v1/request_response.proto\x12"temporal.api.cloud.cloudservice.v1\x1a\x1fgoogle/protobuf/timestamp.proto\x1a-temporal/api/cloud/operation/v1/message.proto\x1a,temporal/api/cloud/identity/v1/message.proto\x1a-temporal/api/cloud/namespace/v1/message.proto\x1a)temporal/api/cloud/nexus/v1/message.proto\x1a*temporal/api/cloud/region/v1/message.proto\x1a+temporal/api/cloud/account/v1/message.proto\x1a)temporal/api/cloud/usage/v1/message.proto\x1a\x34temporal/api/cloud/connectivityrule/v1/message.proto\x1a,temporal/api/cloud/auditlog/v1/message.proto\x1a+temporal/api/cloud/billing/v1/message.proto"\x1b\n\x19GetCurrentIdentityRequest"\xed\x01\n\x1aGetCurrentIdentityResponse\x12\x34\n\x04user\x18\x01 \x01(\x0b\x32$.temporal.api.cloud.identity.v1.UserH\x00\x12I\n\x0fservice_account\x18\x02 \x01(\x0b\x32..temporal.api.cloud.identity.v1.ServiceAccountH\x00\x12\x41\n\x11principal_api_key\x18\x03 \x01(\x0b\x32&.temporal.api.cloud.identity.v1.ApiKeyB\x0b\n\tprincipal"Z\n\x0fGetUsersRequest\x12\x11\n\tpage_size\x18\x01 \x01(\x05\x12\x12\n\npage_token\x18\x02 \x01(\t\x12\r\n\x05\x65mail\x18\x03 \x01(\t\x12\x11\n\tnamespace\x18\x04 \x01(\t"`\n\x10GetUsersResponse\x12\x33\n\x05users\x18\x01 \x03(\x0b\x32$.temporal.api.cloud.identity.v1.User\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\t"!\n\x0eGetUserRequest\x12\x0f\n\x07user_id\x18\x01 \x01(\t"E\n\x0fGetUserResponse\x12\x32\n\x04user\x18\x01 \x01(\x0b\x32$.temporal.api.cloud.identity.v1.User"g\n\x11\x43reateUserRequest\x12\x36\n\x04spec\x18\x01 \x01(\x0b\x32(.temporal.api.cloud.identity.v1.UserSpec\x12\x1a\n\x12\x61sync_operation_id\x18\x02 \x01(\t"o\n\x12\x43reateUserResponse\x12\x0f\n\x07user_id\x18\x01 \x01(\t\x12H\n\x0f\x61sync_operation\x18\x02 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"\x92\x01\n\x11UpdateUserRequest\x12\x0f\n\x07user_id\x18\x01 \x01(\t\x12\x36\n\x04spec\x18\x02 \x01(\x0b\x32(.temporal.api.cloud.identity.v1.UserSpec\x12\x18\n\x10resource_version\x18\x03 \x01(\t\x12\x1a\n\x12\x61sync_operation_id\x18\x04 \x01(\t"^\n\x12UpdateUserResponse\x12H\n\x0f\x61sync_operation\x18\x01 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"Z\n\x11\x44\x65leteUserRequest\x12\x0f\n\x07user_id\x18\x01 \x01(\t\x12\x18\n\x10resource_version\x18\x02 \x01(\t\x12\x1a\n\x12\x61sync_operation_id\x18\x03 \x01(\t"^\n\x12\x44\x65leteUserResponse\x12H\n\x0f\x61sync_operation\x18\x01 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"\xba\x01\n\x1dSetUserNamespaceAccessRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x0f\n\x07user_id\x18\x02 \x01(\t\x12?\n\x06\x61\x63\x63\x65ss\x18\x03 \x01(\x0b\x32/.temporal.api.cloud.identity.v1.NamespaceAccess\x12\x18\n\x10resource_version\x18\x04 \x01(\t\x12\x1a\n\x12\x61sync_operation_id\x18\x05 \x01(\t"j\n\x1eSetUserNamespaceAccessResponse\x12H\n\x0f\x61sync_operation\x18\x01 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"6\n\x18GetAsyncOperationRequest\x12\x1a\n\x12\x61sync_operation_id\x18\x01 \x01(\t"e\n\x19GetAsyncOperationResponse\x12H\n\x0f\x61sync_operation\x18\x01 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"\xf3\x01\n\x16\x43reateNamespaceRequest\x12<\n\x04spec\x18\x02 \x01(\x0b\x32..temporal.api.cloud.namespace.v1.NamespaceSpec\x12\x1a\n\x12\x61sync_operation_id\x18\x03 \x01(\t\x12R\n\x04tags\x18\x04 \x03(\x0b\x32\x44.temporal.api.cloud.cloudservice.v1.CreateNamespaceRequest.TagsEntry\x1a+\n\tTagsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01"v\n\x17\x43reateNamespaceResponse\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12H\n\x0f\x61sync_operation\x18\x02 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"K\n\x14GetNamespacesRequest\x12\x11\n\tpage_size\x18\x01 \x01(\x05\x12\x12\n\npage_token\x18\x02 \x01(\t\x12\x0c\n\x04name\x18\x03 \x01(\t"p\n\x15GetNamespacesResponse\x12>\n\nnamespaces\x18\x01 \x03(\x0b\x32*.temporal.api.cloud.namespace.v1.Namespace\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\t"(\n\x13GetNamespaceRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t"U\n\x14GetNamespaceResponse\x12=\n\tnamespace\x18\x01 \x01(\x0b\x32*.temporal.api.cloud.namespace.v1.Namespace"\x9f\x01\n\x16UpdateNamespaceRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12<\n\x04spec\x18\x02 \x01(\x0b\x32..temporal.api.cloud.namespace.v1.NamespaceSpec\x12\x18\n\x10resource_version\x18\x03 \x01(\t\x12\x1a\n\x12\x61sync_operation_id\x18\x04 \x01(\t"c\n\x17UpdateNamespaceResponse\x12H\n\x0f\x61sync_operation\x18\x01 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"\xc6\x01\n"RenameCustomSearchAttributeRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12-\n%existing_custom_search_attribute_name\x18\x02 \x01(\t\x12(\n new_custom_search_attribute_name\x18\x03 \x01(\t\x12\x18\n\x10resource_version\x18\x04 \x01(\t\x12\x1a\n\x12\x61sync_operation_id\x18\x05 \x01(\t"o\n#RenameCustomSearchAttributeResponse\x12H\n\x0f\x61sync_operation\x18\x01 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"a\n\x16\x44\x65leteNamespaceRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x18\n\x10resource_version\x18\x02 \x01(\t\x12\x1a\n\x12\x61sync_operation_id\x18\x03 \x01(\t"c\n\x17\x44\x65leteNamespaceResponse\x12H\n\x0f\x61sync_operation\x18\x01 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"_\n\x1e\x46\x61iloverNamespaceRegionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x0e\n\x06region\x18\x02 \x01(\t\x12\x1a\n\x12\x61sync_operation_id\x18\x03 \x01(\t"k\n\x1f\x46\x61iloverNamespaceRegionResponse\x12H\n\x0f\x61sync_operation\x18\x01 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"t\n\x19\x41\x64\x64NamespaceRegionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x0e\n\x06region\x18\x02 \x01(\t\x12\x18\n\x10resource_version\x18\x03 \x01(\t\x12\x1a\n\x12\x61sync_operation_id\x18\x04 \x01(\t"f\n\x1a\x41\x64\x64NamespaceRegionResponse\x12H\n\x0f\x61sync_operation\x18\x01 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"w\n\x1c\x44\x65leteNamespaceRegionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x0e\n\x06region\x18\x02 \x01(\t\x12\x18\n\x10resource_version\x18\x03 \x01(\t\x12\x1a\n\x12\x61sync_operation_id\x18\x04 \x01(\t"i\n\x1d\x44\x65leteNamespaceRegionResponse\x12H\n\x0f\x61sync_operation\x18\x01 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"\x13\n\x11GetRegionsRequest"K\n\x12GetRegionsResponse\x12\x35\n\x07regions\x18\x01 \x03(\x0b\x32$.temporal.api.cloud.region.v1.Region""\n\x10GetRegionRequest\x12\x0e\n\x06region\x18\x01 \x01(\t"I\n\x11GetRegionResponse\x12\x34\n\x06region\x18\x01 \x01(\x0b\x32$.temporal.api.cloud.region.v1.Region"\xae\x01\n\x11GetApiKeysRequest\x12\x11\n\tpage_size\x18\x01 \x01(\x05\x12\x12\n\npage_token\x18\x02 \x01(\t\x12\x10\n\x08owner_id\x18\x03 \x01(\t\x12!\n\x15owner_type_deprecated\x18\x04 \x01(\tB\x02\x18\x01\x12=\n\nowner_type\x18\x05 \x01(\x0e\x32).temporal.api.cloud.identity.v1.OwnerType"g\n\x12GetApiKeysResponse\x12\x38\n\x08\x61pi_keys\x18\x01 \x03(\x0b\x32&.temporal.api.cloud.identity.v1.ApiKey\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\t""\n\x10GetApiKeyRequest\x12\x0e\n\x06key_id\x18\x01 \x01(\t"L\n\x11GetApiKeyResponse\x12\x37\n\x07\x61pi_key\x18\x01 \x01(\x0b\x32&.temporal.api.cloud.identity.v1.ApiKey"k\n\x13\x43reateApiKeyRequest\x12\x38\n\x04spec\x18\x01 \x01(\x0b\x32*.temporal.api.cloud.identity.v1.ApiKeySpec\x12\x1a\n\x12\x61sync_operation_id\x18\x02 \x01(\t"\x7f\n\x14\x43reateApiKeyResponse\x12\x0e\n\x06key_id\x18\x01 \x01(\t\x12\r\n\x05token\x18\x02 \x01(\t\x12H\n\x0f\x61sync_operation\x18\x03 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"\x95\x01\n\x13UpdateApiKeyRequest\x12\x0e\n\x06key_id\x18\x01 \x01(\t\x12\x38\n\x04spec\x18\x02 \x01(\x0b\x32*.temporal.api.cloud.identity.v1.ApiKeySpec\x12\x18\n\x10resource_version\x18\x03 \x01(\t\x12\x1a\n\x12\x61sync_operation_id\x18\x04 \x01(\t"`\n\x14UpdateApiKeyResponse\x12H\n\x0f\x61sync_operation\x18\x01 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"[\n\x13\x44\x65leteApiKeyRequest\x12\x0e\n\x06key_id\x18\x01 \x01(\t\x12\x18\n\x10resource_version\x18\x02 \x01(\t\x12\x1a\n\x12\x61sync_operation_id\x18\x03 \x01(\t"`\n\x14\x44\x65leteApiKeyResponse\x12H\n\x0f\x61sync_operation\x18\x01 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"\x87\x01\n\x18GetNexusEndpointsRequest\x12\x11\n\tpage_size\x18\x01 \x01(\x05\x12\x12\n\npage_token\x18\x02 \x01(\t\x12\x1b\n\x13target_namespace_id\x18\x03 \x01(\t\x12\x19\n\x11target_task_queue\x18\x04 \x01(\t\x12\x0c\n\x04name\x18\x05 \x01(\t"n\n\x19GetNexusEndpointsResponse\x12\x38\n\tendpoints\x18\x01 \x03(\x0b\x32%.temporal.api.cloud.nexus.v1.Endpoint\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\t".\n\x17GetNexusEndpointRequest\x12\x13\n\x0b\x65ndpoint_id\x18\x01 \x01(\t"S\n\x18GetNexusEndpointResponse\x12\x37\n\x08\x65ndpoint\x18\x01 \x01(\x0b\x32%.temporal.api.cloud.nexus.v1.Endpoint"q\n\x1a\x43reateNexusEndpointRequest\x12\x37\n\x04spec\x18\x01 \x01(\x0b\x32).temporal.api.cloud.nexus.v1.EndpointSpec\x12\x1a\n\x12\x61sync_operation_id\x18\x02 \x01(\t"|\n\x1b\x43reateNexusEndpointResponse\x12\x13\n\x0b\x65ndpoint_id\x18\x01 \x01(\t\x12H\n\x0f\x61sync_operation\x18\x02 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"\xa0\x01\n\x1aUpdateNexusEndpointRequest\x12\x13\n\x0b\x65ndpoint_id\x18\x01 \x01(\t\x12\x37\n\x04spec\x18\x02 \x01(\x0b\x32).temporal.api.cloud.nexus.v1.EndpointSpec\x12\x18\n\x10resource_version\x18\x03 \x01(\t\x12\x1a\n\x12\x61sync_operation_id\x18\x04 \x01(\t"g\n\x1bUpdateNexusEndpointResponse\x12H\n\x0f\x61sync_operation\x18\x01 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"g\n\x1a\x44\x65leteNexusEndpointRequest\x12\x13\n\x0b\x65ndpoint_id\x18\x01 \x01(\t\x12\x18\n\x10resource_version\x18\x02 \x01(\t\x12\x1a\n\x12\x61sync_operation_id\x18\x03 \x01(\t"g\n\x1b\x44\x65leteNexusEndpointResponse\x12H\n\x0f\x61sync_operation\x18\x01 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"\xf5\x02\n\x14GetUserGroupsRequest\x12\x11\n\tpage_size\x18\x01 \x01(\x05\x12\x12\n\npage_token\x18\x02 \x01(\t\x12\x11\n\tnamespace\x18\x03 \x01(\t\x12\x14\n\x0c\x64isplay_name\x18\x04 \x01(\t\x12`\n\x0cgoogle_group\x18\x05 \x01(\x0b\x32J.temporal.api.cloud.cloudservice.v1.GetUserGroupsRequest.GoogleGroupFilter\x12\\\n\nscim_group\x18\x06 \x01(\x0b\x32H.temporal.api.cloud.cloudservice.v1.GetUserGroupsRequest.SCIMGroupFilter\x1a*\n\x11GoogleGroupFilter\x12\x15\n\remail_address\x18\x01 \x01(\t\x1a!\n\x0fSCIMGroupFilter\x12\x0e\n\x06idp_id\x18\x01 \x01(\t"k\n\x15GetUserGroupsResponse\x12\x39\n\x06groups\x18\x01 \x03(\x0b\x32).temporal.api.cloud.identity.v1.UserGroup\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\t"\'\n\x13GetUserGroupRequest\x12\x10\n\x08group_id\x18\x01 \x01(\t"P\n\x14GetUserGroupResponse\x12\x38\n\x05group\x18\x01 \x01(\x0b\x32).temporal.api.cloud.identity.v1.UserGroup"q\n\x16\x43reateUserGroupRequest\x12;\n\x04spec\x18\x01 \x01(\x0b\x32-.temporal.api.cloud.identity.v1.UserGroupSpec\x12\x1a\n\x12\x61sync_operation_id\x18\x02 \x01(\t"u\n\x17\x43reateUserGroupResponse\x12\x10\n\x08group_id\x18\x01 \x01(\t\x12H\n\x0f\x61sync_operation\x18\x02 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"\x9d\x01\n\x16UpdateUserGroupRequest\x12\x10\n\x08group_id\x18\x01 \x01(\t\x12;\n\x04spec\x18\x02 \x01(\x0b\x32-.temporal.api.cloud.identity.v1.UserGroupSpec\x12\x18\n\x10resource_version\x18\x03 \x01(\t\x12\x1a\n\x12\x61sync_operation_id\x18\x04 \x01(\t"c\n\x17UpdateUserGroupResponse\x12H\n\x0f\x61sync_operation\x18\x01 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"`\n\x16\x44\x65leteUserGroupRequest\x12\x10\n\x08group_id\x18\x01 \x01(\t\x12\x18\n\x10resource_version\x18\x02 \x01(\t\x12\x1a\n\x12\x61sync_operation_id\x18\x03 \x01(\t"c\n\x17\x44\x65leteUserGroupResponse\x12H\n\x0f\x61sync_operation\x18\x01 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"\xc0\x01\n"SetUserGroupNamespaceAccessRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x10\n\x08group_id\x18\x02 \x01(\t\x12?\n\x06\x61\x63\x63\x65ss\x18\x03 \x01(\x0b\x32/.temporal.api.cloud.identity.v1.NamespaceAccess\x12\x18\n\x10resource_version\x18\x04 \x01(\t\x12\x1a\n\x12\x61sync_operation_id\x18\x05 \x01(\t"o\n#SetUserGroupNamespaceAccessResponse\x12H\n\x0f\x61sync_operation\x18\x01 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"\x8f\x01\n\x19\x41\x64\x64UserGroupMemberRequest\x12\x10\n\x08group_id\x18\x01 \x01(\t\x12\x44\n\tmember_id\x18\x02 \x01(\x0b\x32\x31.temporal.api.cloud.identity.v1.UserGroupMemberId\x12\x1a\n\x12\x61sync_operation_id\x18\x03 \x01(\t"f\n\x1a\x41\x64\x64UserGroupMemberResponse\x12H\n\x0f\x61sync_operation\x18\x01 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"\x92\x01\n\x1cRemoveUserGroupMemberRequest\x12\x10\n\x08group_id\x18\x01 \x01(\t\x12\x44\n\tmember_id\x18\x02 \x01(\x0b\x32\x31.temporal.api.cloud.identity.v1.UserGroupMemberId\x12\x1a\n\x12\x61sync_operation_id\x18\x03 \x01(\t"i\n\x1dRemoveUserGroupMemberResponse\x12H\n\x0f\x61sync_operation\x18\x01 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"U\n\x1aGetUserGroupMembersRequest\x12\x11\n\tpage_size\x18\x01 \x01(\x05\x12\x12\n\npage_token\x18\x02 \x01(\t\x12\x10\n\x08group_id\x18\x03 \x01(\t"x\n\x1bGetUserGroupMembersResponse\x12@\n\x07members\x18\x01 \x03(\x0b\x32/.temporal.api.cloud.identity.v1.UserGroupMember\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\t"{\n\x1b\x43reateServiceAccountRequest\x12@\n\x04spec\x18\x01 \x01(\x0b\x32\x32.temporal.api.cloud.identity.v1.ServiceAccountSpec\x12\x1a\n\x12\x61sync_operation_id\x18\x02 \x01(\t"\x84\x01\n\x1c\x43reateServiceAccountResponse\x12\x1a\n\x12service_account_id\x18\x01 \x01(\t\x12H\n\x0f\x61sync_operation\x18\x02 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"6\n\x18GetServiceAccountRequest\x12\x1a\n\x12service_account_id\x18\x01 \x01(\t"d\n\x19GetServiceAccountResponse\x12G\n\x0fservice_account\x18\x01 \x01(\x0b\x32..temporal.api.cloud.identity.v1.ServiceAccount"B\n\x19GetServiceAccountsRequest\x12\x11\n\tpage_size\x18\x01 \x01(\x05\x12\x12\n\npage_token\x18\x02 \x01(\t"~\n\x1aGetServiceAccountsResponse\x12G\n\x0fservice_account\x18\x01 \x03(\x0b\x32..temporal.api.cloud.identity.v1.ServiceAccount\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\t"\xb1\x01\n\x1bUpdateServiceAccountRequest\x12\x1a\n\x12service_account_id\x18\x01 \x01(\t\x12@\n\x04spec\x18\x02 \x01(\x0b\x32\x32.temporal.api.cloud.identity.v1.ServiceAccountSpec\x12\x18\n\x10resource_version\x18\x03 \x01(\t\x12\x1a\n\x12\x61sync_operation_id\x18\x04 \x01(\t"h\n\x1cUpdateServiceAccountResponse\x12H\n\x0f\x61sync_operation\x18\x01 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"\xcf\x01\n\'SetServiceAccountNamespaceAccessRequest\x12\x1a\n\x12service_account_id\x18\x01 \x01(\t\x12\x11\n\tnamespace\x18\x02 \x01(\t\x12?\n\x06\x61\x63\x63\x65ss\x18\x03 \x01(\x0b\x32/.temporal.api.cloud.identity.v1.NamespaceAccess\x12\x18\n\x10resource_version\x18\x04 \x01(\t\x12\x1a\n\x12\x61sync_operation_id\x18\x05 \x01(\t"t\n(SetServiceAccountNamespaceAccessResponse\x12H\n\x0f\x61sync_operation\x18\x01 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"o\n\x1b\x44\x65leteServiceAccountRequest\x12\x1a\n\x12service_account_id\x18\x01 \x01(\t\x12\x18\n\x10resource_version\x18\x02 \x01(\t\x12\x1a\n\x12\x61sync_operation_id\x18\x03 \x01(\t"h\n\x1c\x44\x65leteServiceAccountResponse\x12H\n\x0f\x61sync_operation\x18\x01 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"\xaa\x01\n\x0fGetUsageRequest\x12\x38\n\x14start_time_inclusive\x18\x01 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x36\n\x12\x65nd_time_exclusive\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x11\n\tpage_size\x18\x03 \x01(\x05\x12\x12\n\npage_token\x18\x04 \x01(\t"d\n\x10GetUsageResponse\x12\x37\n\tsummaries\x18\x01 \x03(\x0b\x32$.temporal.api.cloud.usage.v1.Summary\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\t"\x13\n\x11GetAccountRequest"M\n\x12GetAccountResponse\x12\x37\n\x07\x61\x63\x63ount\x18\x01 \x01(\x0b\x32&.temporal.api.cloud.account.v1.Account"\x86\x01\n\x14UpdateAccountRequest\x12\x38\n\x04spec\x18\x01 \x01(\x0b\x32*.temporal.api.cloud.account.v1.AccountSpec\x12\x18\n\x10resource_version\x18\x02 \x01(\t\x12\x1a\n\x12\x61sync_operation_id\x18\x03 \x01(\t"a\n\x15UpdateAccountResponse\x12H\n\x0f\x61sync_operation\x18\x01 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"\x90\x01\n CreateNamespaceExportSinkRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12=\n\x04spec\x18\x02 \x01(\x0b\x32/.temporal.api.cloud.namespace.v1.ExportSinkSpec\x12\x1a\n\x12\x61sync_operation_id\x18\x03 \x01(\t"m\n!CreateNamespaceExportSinkResponse\x12H\n\x0f\x61sync_operation\x18\x01 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"@\n\x1dGetNamespaceExportSinkRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x0c\n\x04name\x18\x02 \x01(\t"[\n\x1eGetNamespaceExportSinkResponse\x12\x39\n\x04sink\x18\x01 \x01(\x0b\x32+.temporal.api.cloud.namespace.v1.ExportSink"Z\n\x1eGetNamespaceExportSinksRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x11\n\tpage_size\x18\x02 \x01(\x05\x12\x12\n\npage_token\x18\x03 \x01(\t"v\n\x1fGetNamespaceExportSinksResponse\x12:\n\x05sinks\x18\x01 \x03(\x0b\x32+.temporal.api.cloud.namespace.v1.ExportSink\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\t"\xaa\x01\n UpdateNamespaceExportSinkRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12=\n\x04spec\x18\x02 \x01(\x0b\x32/.temporal.api.cloud.namespace.v1.ExportSinkSpec\x12\x18\n\x10resource_version\x18\x03 \x01(\t\x12\x1a\n\x12\x61sync_operation_id\x18\x04 \x01(\t"m\n!UpdateNamespaceExportSinkResponse\x12H\n\x0f\x61sync_operation\x18\x01 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"y\n DeleteNamespaceExportSinkRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x0c\n\x04name\x18\x02 \x01(\t\x12\x18\n\x10resource_version\x18\x03 \x01(\t\x12\x1a\n\x12\x61sync_operation_id\x18\x04 \x01(\t"m\n!DeleteNamespaceExportSinkResponse\x12H\n\x0f\x61sync_operation\x18\x01 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"v\n"ValidateNamespaceExportSinkRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12=\n\x04spec\x18\x02 \x01(\x0b\x32/.temporal.api.cloud.namespace.v1.ExportSinkSpec"%\n#ValidateNamespaceExportSinkResponse"\x82\x02\n\x1aUpdateNamespaceTagsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12h\n\x0etags_to_upsert\x18\x02 \x03(\x0b\x32P.temporal.api.cloud.cloudservice.v1.UpdateNamespaceTagsRequest.TagsToUpsertEntry\x12\x16\n\x0etags_to_remove\x18\x03 \x03(\t\x12\x1a\n\x12\x61sync_operation_id\x18\x04 \x01(\t\x1a\x33\n\x11TagsToUpsertEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01"g\n\x1bUpdateNamespaceTagsResponse\x12H\n\x0f\x61sync_operation\x18\x01 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"\x87\x01\n\x1d\x43reateConnectivityRuleRequest\x12J\n\x04spec\x18\x01 \x01(\x0b\x32<.temporal.api.cloud.connectivityrule.v1.ConnectivityRuleSpec\x12\x1a\n\x12\x61sync_operation_id\x18\x02 \x01(\t"\x88\x01\n\x1e\x43reateConnectivityRuleResponse\x12\x1c\n\x14\x63onnectivity_rule_id\x18\x01 \x01(\t\x12H\n\x0f\x61sync_operation\x18\x02 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation":\n\x1aGetConnectivityRuleRequest\x12\x1c\n\x14\x63onnectivity_rule_id\x18\x01 \x01(\t"r\n\x1bGetConnectivityRuleResponse\x12S\n\x11\x63onnectivity_rule\x18\x01 \x01(\x0b\x32\x38.temporal.api.cloud.connectivityrule.v1.ConnectivityRule"W\n\x1bGetConnectivityRulesRequest\x12\x11\n\tpage_size\x18\x01 \x01(\x05\x12\x12\n\npage_token\x18\x02 \x01(\t\x12\x11\n\tnamespace\x18\x03 \x01(\t"\x8d\x01\n\x1cGetConnectivityRulesResponse\x12T\n\x12\x63onnectivity_rules\x18\x01 \x03(\x0b\x32\x38.temporal.api.cloud.connectivityrule.v1.ConnectivityRule\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\t"s\n\x1d\x44\x65leteConnectivityRuleRequest\x12\x1c\n\x14\x63onnectivity_rule_id\x18\x01 \x01(\t\x12\x18\n\x10resource_version\x18\x02 \x01(\t\x12\x1a\n\x12\x61sync_operation_id\x18\x03 \x01(\t"j\n\x1e\x44\x65leteConnectivityRuleResponse\x12H\n\x0f\x61sync_operation\x18\x01 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"\xae\x01\n\x13GetAuditLogsRequest\x12\x11\n\tpage_size\x18\x01 \x01(\x05\x12\x12\n\npage_token\x18\x02 \x01(\t\x12\x38\n\x14start_time_inclusive\x18\x03 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x36\n\x12\x65nd_time_exclusive\x18\x04 \x01(\x0b\x32\x1a.google.protobuf.Timestamp"h\n\x14GetAuditLogsResponse\x12\x37\n\x04logs\x18\x01 \x03(\x0b\x32).temporal.api.cloud.auditlog.v1.LogRecord\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\t"c\n"ValidateAccountAuditLogSinkRequest\x12=\n\x04spec\x18\x01 \x01(\x0b\x32/.temporal.api.cloud.account.v1.AuditLogSinkSpec"%\n#ValidateAccountAuditLogSinkResponse"}\n CreateAccountAuditLogSinkRequest\x12=\n\x04spec\x18\x01 \x01(\x0b\x32/.temporal.api.cloud.account.v1.AuditLogSinkSpec\x12\x1a\n\x12\x61sync_operation_id\x18\x02 \x01(\t"m\n!CreateAccountAuditLogSinkResponse\x12H\n\x0f\x61sync_operation\x18\x01 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"-\n\x1dGetAccountAuditLogSinkRequest\x12\x0c\n\x04name\x18\x01 \x01(\t"[\n\x1eGetAccountAuditLogSinkResponse\x12\x39\n\x04sink\x18\x01 \x01(\x0b\x32+.temporal.api.cloud.account.v1.AuditLogSink"G\n\x1eGetAccountAuditLogSinksRequest\x12\x11\n\tpage_size\x18\x01 \x01(\x05\x12\x12\n\npage_token\x18\x02 \x01(\t"v\n\x1fGetAccountAuditLogSinksResponse\x12:\n\x05sinks\x18\x01 \x03(\x0b\x32+.temporal.api.cloud.account.v1.AuditLogSink\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\t"\x97\x01\n UpdateAccountAuditLogSinkRequest\x12=\n\x04spec\x18\x01 \x01(\x0b\x32/.temporal.api.cloud.account.v1.AuditLogSinkSpec\x12\x18\n\x10resource_version\x18\x02 \x01(\t\x12\x1a\n\x12\x61sync_operation_id\x18\x03 \x01(\t"m\n!UpdateAccountAuditLogSinkResponse\x12H\n\x0f\x61sync_operation\x18\x01 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"f\n DeleteAccountAuditLogSinkRequest\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x18\n\x10resource_version\x18\x02 \x01(\t\x12\x1a\n\x12\x61sync_operation_id\x18\x03 \x01(\t"m\n!DeleteAccountAuditLogSinkResponse\x12H\n\x0f\x61sync_operation\x18\x01 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"4\n\x1fGetNamespaceCapacityInfoRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t"q\n GetNamespaceCapacityInfoResponse\x12M\n\rcapacity_info\x18\x01 \x01(\x0b\x32\x36.temporal.api.cloud.namespace.v1.NamespaceCapacityInfo"x\n\x1a\x43reateBillingReportRequest\x12>\n\x04spec\x18\x01 \x01(\x0b\x32\x30.temporal.api.cloud.billing.v1.BillingReportSpec\x12\x1a\n\x12\x61sync_operation_id\x18\x02 \x01(\t"\x82\x01\n\x1b\x43reateBillingReportResponse\x12\x19\n\x11\x62illing_report_id\x18\x01 \x01(\t\x12H\n\x0f\x61sync_operation\x18\x02 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"4\n\x17GetBillingReportRequest\x12\x19\n\x11\x62illing_report_id\x18\x01 \x01(\t"`\n\x18GetBillingReportResponse\x12\x44\n\x0e\x62illing_report\x18\x01 \x01(\x0b\x32,.temporal.api.cloud.billing.v1.BillingReportB\xc8\x01\n%io.temporal.api.cloud.cloudservice.v1B\x14RequestResponseProtoP\x01Z5go.temporal.io/api/cloud/cloudservice/v1;cloudservice\xaa\x02$Temporalio.Api.Cloud.CloudService.V1\xea\x02(Temporalio::Api::Cloud::CloudService::V1b\x06proto3' + b'\n9temporal/api/cloud/cloudservice/v1/request_response.proto\x12"temporal.api.cloud.cloudservice.v1\x1a\x1fgoogle/protobuf/timestamp.proto\x1a-temporal/api/cloud/operation/v1/message.proto\x1a,temporal/api/cloud/identity/v1/message.proto\x1a-temporal/api/cloud/namespace/v1/message.proto\x1a)temporal/api/cloud/nexus/v1/message.proto\x1a*temporal/api/cloud/region/v1/message.proto\x1a+temporal/api/cloud/account/v1/message.proto\x1a)temporal/api/cloud/usage/v1/message.proto\x1a\x34temporal/api/cloud/connectivityrule/v1/message.proto\x1a,temporal/api/cloud/auditlog/v1/message.proto\x1a+temporal/api/cloud/billing/v1/message.proto"\x1b\n\x19GetCurrentIdentityRequest"\xed\x01\n\x1aGetCurrentIdentityResponse\x12\x34\n\x04user\x18\x01 \x01(\x0b\x32$.temporal.api.cloud.identity.v1.UserH\x00\x12I\n\x0fservice_account\x18\x02 \x01(\x0b\x32..temporal.api.cloud.identity.v1.ServiceAccountH\x00\x12\x41\n\x11principal_api_key\x18\x03 \x01(\x0b\x32&.temporal.api.cloud.identity.v1.ApiKeyB\x0b\n\tprincipal"Z\n\x0fGetUsersRequest\x12\x11\n\tpage_size\x18\x01 \x01(\x05\x12\x12\n\npage_token\x18\x02 \x01(\t\x12\r\n\x05\x65mail\x18\x03 \x01(\t\x12\x11\n\tnamespace\x18\x04 \x01(\t"`\n\x10GetUsersResponse\x12\x33\n\x05users\x18\x01 \x03(\x0b\x32$.temporal.api.cloud.identity.v1.User\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\t"!\n\x0eGetUserRequest\x12\x0f\n\x07user_id\x18\x01 \x01(\t"E\n\x0fGetUserResponse\x12\x32\n\x04user\x18\x01 \x01(\x0b\x32$.temporal.api.cloud.identity.v1.User"g\n\x11\x43reateUserRequest\x12\x36\n\x04spec\x18\x01 \x01(\x0b\x32(.temporal.api.cloud.identity.v1.UserSpec\x12\x1a\n\x12\x61sync_operation_id\x18\x02 \x01(\t"o\n\x12\x43reateUserResponse\x12\x0f\n\x07user_id\x18\x01 \x01(\t\x12H\n\x0f\x61sync_operation\x18\x02 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"\x92\x01\n\x11UpdateUserRequest\x12\x0f\n\x07user_id\x18\x01 \x01(\t\x12\x36\n\x04spec\x18\x02 \x01(\x0b\x32(.temporal.api.cloud.identity.v1.UserSpec\x12\x18\n\x10resource_version\x18\x03 \x01(\t\x12\x1a\n\x12\x61sync_operation_id\x18\x04 \x01(\t"^\n\x12UpdateUserResponse\x12H\n\x0f\x61sync_operation\x18\x01 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"Z\n\x11\x44\x65leteUserRequest\x12\x0f\n\x07user_id\x18\x01 \x01(\t\x12\x18\n\x10resource_version\x18\x02 \x01(\t\x12\x1a\n\x12\x61sync_operation_id\x18\x03 \x01(\t"^\n\x12\x44\x65leteUserResponse\x12H\n\x0f\x61sync_operation\x18\x01 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"\xba\x01\n\x1dSetUserNamespaceAccessRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x0f\n\x07user_id\x18\x02 \x01(\t\x12?\n\x06\x61\x63\x63\x65ss\x18\x03 \x01(\x0b\x32/.temporal.api.cloud.identity.v1.NamespaceAccess\x12\x18\n\x10resource_version\x18\x04 \x01(\t\x12\x1a\n\x12\x61sync_operation_id\x18\x05 \x01(\t"j\n\x1eSetUserNamespaceAccessResponse\x12H\n\x0f\x61sync_operation\x18\x01 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"6\n\x18GetAsyncOperationRequest\x12\x1a\n\x12\x61sync_operation_id\x18\x01 \x01(\t"e\n\x19GetAsyncOperationResponse\x12H\n\x0f\x61sync_operation\x18\x01 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"\xf3\x01\n\x16\x43reateNamespaceRequest\x12<\n\x04spec\x18\x02 \x01(\x0b\x32..temporal.api.cloud.namespace.v1.NamespaceSpec\x12\x1a\n\x12\x61sync_operation_id\x18\x03 \x01(\t\x12R\n\x04tags\x18\x04 \x03(\x0b\x32\x44.temporal.api.cloud.cloudservice.v1.CreateNamespaceRequest.TagsEntry\x1a+\n\tTagsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01"v\n\x17\x43reateNamespaceResponse\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12H\n\x0f\x61sync_operation\x18\x02 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"K\n\x14GetNamespacesRequest\x12\x11\n\tpage_size\x18\x01 \x01(\x05\x12\x12\n\npage_token\x18\x02 \x01(\t\x12\x0c\n\x04name\x18\x03 \x01(\t"p\n\x15GetNamespacesResponse\x12>\n\nnamespaces\x18\x01 \x03(\x0b\x32*.temporal.api.cloud.namespace.v1.Namespace\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\t"(\n\x13GetNamespaceRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t"U\n\x14GetNamespaceResponse\x12=\n\tnamespace\x18\x01 \x01(\x0b\x32*.temporal.api.cloud.namespace.v1.Namespace"\x9f\x01\n\x16UpdateNamespaceRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12<\n\x04spec\x18\x02 \x01(\x0b\x32..temporal.api.cloud.namespace.v1.NamespaceSpec\x12\x18\n\x10resource_version\x18\x03 \x01(\t\x12\x1a\n\x12\x61sync_operation_id\x18\x04 \x01(\t"c\n\x17UpdateNamespaceResponse\x12H\n\x0f\x61sync_operation\x18\x01 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"\xc6\x01\n"RenameCustomSearchAttributeRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12-\n%existing_custom_search_attribute_name\x18\x02 \x01(\t\x12(\n new_custom_search_attribute_name\x18\x03 \x01(\t\x12\x18\n\x10resource_version\x18\x04 \x01(\t\x12\x1a\n\x12\x61sync_operation_id\x18\x05 \x01(\t"o\n#RenameCustomSearchAttributeResponse\x12H\n\x0f\x61sync_operation\x18\x01 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"a\n\x16\x44\x65leteNamespaceRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x18\n\x10resource_version\x18\x02 \x01(\t\x12\x1a\n\x12\x61sync_operation_id\x18\x03 \x01(\t"c\n\x17\x44\x65leteNamespaceResponse\x12H\n\x0f\x61sync_operation\x18\x01 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"_\n\x1e\x46\x61iloverNamespaceRegionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x0e\n\x06region\x18\x02 \x01(\t\x12\x1a\n\x12\x61sync_operation_id\x18\x03 \x01(\t"k\n\x1f\x46\x61iloverNamespaceRegionResponse\x12H\n\x0f\x61sync_operation\x18\x01 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"t\n\x19\x41\x64\x64NamespaceRegionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x0e\n\x06region\x18\x02 \x01(\t\x12\x18\n\x10resource_version\x18\x03 \x01(\t\x12\x1a\n\x12\x61sync_operation_id\x18\x04 \x01(\t"f\n\x1a\x41\x64\x64NamespaceRegionResponse\x12H\n\x0f\x61sync_operation\x18\x01 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"w\n\x1c\x44\x65leteNamespaceRegionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x0e\n\x06region\x18\x02 \x01(\t\x12\x18\n\x10resource_version\x18\x03 \x01(\t\x12\x1a\n\x12\x61sync_operation_id\x18\x04 \x01(\t"i\n\x1d\x44\x65leteNamespaceRegionResponse\x12H\n\x0f\x61sync_operation\x18\x01 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"\x13\n\x11GetRegionsRequest"K\n\x12GetRegionsResponse\x12\x35\n\x07regions\x18\x01 \x03(\x0b\x32$.temporal.api.cloud.region.v1.Region""\n\x10GetRegionRequest\x12\x0e\n\x06region\x18\x01 \x01(\t"I\n\x11GetRegionResponse\x12\x34\n\x06region\x18\x01 \x01(\x0b\x32$.temporal.api.cloud.region.v1.Region"\xae\x01\n\x11GetApiKeysRequest\x12\x11\n\tpage_size\x18\x01 \x01(\x05\x12\x12\n\npage_token\x18\x02 \x01(\t\x12\x10\n\x08owner_id\x18\x03 \x01(\t\x12!\n\x15owner_type_deprecated\x18\x04 \x01(\tB\x02\x18\x01\x12=\n\nowner_type\x18\x05 \x01(\x0e\x32).temporal.api.cloud.identity.v1.OwnerType"g\n\x12GetApiKeysResponse\x12\x38\n\x08\x61pi_keys\x18\x01 \x03(\x0b\x32&.temporal.api.cloud.identity.v1.ApiKey\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\t""\n\x10GetApiKeyRequest\x12\x0e\n\x06key_id\x18\x01 \x01(\t"L\n\x11GetApiKeyResponse\x12\x37\n\x07\x61pi_key\x18\x01 \x01(\x0b\x32&.temporal.api.cloud.identity.v1.ApiKey"k\n\x13\x43reateApiKeyRequest\x12\x38\n\x04spec\x18\x01 \x01(\x0b\x32*.temporal.api.cloud.identity.v1.ApiKeySpec\x12\x1a\n\x12\x61sync_operation_id\x18\x02 \x01(\t"\x7f\n\x14\x43reateApiKeyResponse\x12\x0e\n\x06key_id\x18\x01 \x01(\t\x12\r\n\x05token\x18\x02 \x01(\t\x12H\n\x0f\x61sync_operation\x18\x03 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"\x95\x01\n\x13UpdateApiKeyRequest\x12\x0e\n\x06key_id\x18\x01 \x01(\t\x12\x38\n\x04spec\x18\x02 \x01(\x0b\x32*.temporal.api.cloud.identity.v1.ApiKeySpec\x12\x18\n\x10resource_version\x18\x03 \x01(\t\x12\x1a\n\x12\x61sync_operation_id\x18\x04 \x01(\t"`\n\x14UpdateApiKeyResponse\x12H\n\x0f\x61sync_operation\x18\x01 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"[\n\x13\x44\x65leteApiKeyRequest\x12\x0e\n\x06key_id\x18\x01 \x01(\t\x12\x18\n\x10resource_version\x18\x02 \x01(\t\x12\x1a\n\x12\x61sync_operation_id\x18\x03 \x01(\t"`\n\x14\x44\x65leteApiKeyResponse\x12H\n\x0f\x61sync_operation\x18\x01 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"\x87\x01\n\x18GetNexusEndpointsRequest\x12\x11\n\tpage_size\x18\x01 \x01(\x05\x12\x12\n\npage_token\x18\x02 \x01(\t\x12\x1b\n\x13target_namespace_id\x18\x03 \x01(\t\x12\x19\n\x11target_task_queue\x18\x04 \x01(\t\x12\x0c\n\x04name\x18\x05 \x01(\t"n\n\x19GetNexusEndpointsResponse\x12\x38\n\tendpoints\x18\x01 \x03(\x0b\x32%.temporal.api.cloud.nexus.v1.Endpoint\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\t".\n\x17GetNexusEndpointRequest\x12\x13\n\x0b\x65ndpoint_id\x18\x01 \x01(\t"S\n\x18GetNexusEndpointResponse\x12\x37\n\x08\x65ndpoint\x18\x01 \x01(\x0b\x32%.temporal.api.cloud.nexus.v1.Endpoint"q\n\x1a\x43reateNexusEndpointRequest\x12\x37\n\x04spec\x18\x01 \x01(\x0b\x32).temporal.api.cloud.nexus.v1.EndpointSpec\x12\x1a\n\x12\x61sync_operation_id\x18\x02 \x01(\t"|\n\x1b\x43reateNexusEndpointResponse\x12\x13\n\x0b\x65ndpoint_id\x18\x01 \x01(\t\x12H\n\x0f\x61sync_operation\x18\x02 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"\xa0\x01\n\x1aUpdateNexusEndpointRequest\x12\x13\n\x0b\x65ndpoint_id\x18\x01 \x01(\t\x12\x37\n\x04spec\x18\x02 \x01(\x0b\x32).temporal.api.cloud.nexus.v1.EndpointSpec\x12\x18\n\x10resource_version\x18\x03 \x01(\t\x12\x1a\n\x12\x61sync_operation_id\x18\x04 \x01(\t"g\n\x1bUpdateNexusEndpointResponse\x12H\n\x0f\x61sync_operation\x18\x01 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"g\n\x1a\x44\x65leteNexusEndpointRequest\x12\x13\n\x0b\x65ndpoint_id\x18\x01 \x01(\t\x12\x18\n\x10resource_version\x18\x02 \x01(\t\x12\x1a\n\x12\x61sync_operation_id\x18\x03 \x01(\t"g\n\x1b\x44\x65leteNexusEndpointResponse\x12H\n\x0f\x61sync_operation\x18\x01 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"\xf5\x02\n\x14GetUserGroupsRequest\x12\x11\n\tpage_size\x18\x01 \x01(\x05\x12\x12\n\npage_token\x18\x02 \x01(\t\x12\x11\n\tnamespace\x18\x03 \x01(\t\x12\x14\n\x0c\x64isplay_name\x18\x04 \x01(\t\x12`\n\x0cgoogle_group\x18\x05 \x01(\x0b\x32J.temporal.api.cloud.cloudservice.v1.GetUserGroupsRequest.GoogleGroupFilter\x12\\\n\nscim_group\x18\x06 \x01(\x0b\x32H.temporal.api.cloud.cloudservice.v1.GetUserGroupsRequest.SCIMGroupFilter\x1a*\n\x11GoogleGroupFilter\x12\x15\n\remail_address\x18\x01 \x01(\t\x1a!\n\x0fSCIMGroupFilter\x12\x0e\n\x06idp_id\x18\x01 \x01(\t"k\n\x15GetUserGroupsResponse\x12\x39\n\x06groups\x18\x01 \x03(\x0b\x32).temporal.api.cloud.identity.v1.UserGroup\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\t"\'\n\x13GetUserGroupRequest\x12\x10\n\x08group_id\x18\x01 \x01(\t"P\n\x14GetUserGroupResponse\x12\x38\n\x05group\x18\x01 \x01(\x0b\x32).temporal.api.cloud.identity.v1.UserGroup"q\n\x16\x43reateUserGroupRequest\x12;\n\x04spec\x18\x01 \x01(\x0b\x32-.temporal.api.cloud.identity.v1.UserGroupSpec\x12\x1a\n\x12\x61sync_operation_id\x18\x02 \x01(\t"u\n\x17\x43reateUserGroupResponse\x12\x10\n\x08group_id\x18\x01 \x01(\t\x12H\n\x0f\x61sync_operation\x18\x02 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"\x9d\x01\n\x16UpdateUserGroupRequest\x12\x10\n\x08group_id\x18\x01 \x01(\t\x12;\n\x04spec\x18\x02 \x01(\x0b\x32-.temporal.api.cloud.identity.v1.UserGroupSpec\x12\x18\n\x10resource_version\x18\x03 \x01(\t\x12\x1a\n\x12\x61sync_operation_id\x18\x04 \x01(\t"c\n\x17UpdateUserGroupResponse\x12H\n\x0f\x61sync_operation\x18\x01 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"`\n\x16\x44\x65leteUserGroupRequest\x12\x10\n\x08group_id\x18\x01 \x01(\t\x12\x18\n\x10resource_version\x18\x02 \x01(\t\x12\x1a\n\x12\x61sync_operation_id\x18\x03 \x01(\t"c\n\x17\x44\x65leteUserGroupResponse\x12H\n\x0f\x61sync_operation\x18\x01 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"\xc0\x01\n"SetUserGroupNamespaceAccessRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x10\n\x08group_id\x18\x02 \x01(\t\x12?\n\x06\x61\x63\x63\x65ss\x18\x03 \x01(\x0b\x32/.temporal.api.cloud.identity.v1.NamespaceAccess\x12\x18\n\x10resource_version\x18\x04 \x01(\t\x12\x1a\n\x12\x61sync_operation_id\x18\x05 \x01(\t"o\n#SetUserGroupNamespaceAccessResponse\x12H\n\x0f\x61sync_operation\x18\x01 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"\x8f\x01\n\x19\x41\x64\x64UserGroupMemberRequest\x12\x10\n\x08group_id\x18\x01 \x01(\t\x12\x44\n\tmember_id\x18\x02 \x01(\x0b\x32\x31.temporal.api.cloud.identity.v1.UserGroupMemberId\x12\x1a\n\x12\x61sync_operation_id\x18\x03 \x01(\t"f\n\x1a\x41\x64\x64UserGroupMemberResponse\x12H\n\x0f\x61sync_operation\x18\x01 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"\x92\x01\n\x1cRemoveUserGroupMemberRequest\x12\x10\n\x08group_id\x18\x01 \x01(\t\x12\x44\n\tmember_id\x18\x02 \x01(\x0b\x32\x31.temporal.api.cloud.identity.v1.UserGroupMemberId\x12\x1a\n\x12\x61sync_operation_id\x18\x03 \x01(\t"i\n\x1dRemoveUserGroupMemberResponse\x12H\n\x0f\x61sync_operation\x18\x01 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"U\n\x1aGetUserGroupMembersRequest\x12\x11\n\tpage_size\x18\x01 \x01(\x05\x12\x12\n\npage_token\x18\x02 \x01(\t\x12\x10\n\x08group_id\x18\x03 \x01(\t"x\n\x1bGetUserGroupMembersResponse\x12@\n\x07members\x18\x01 \x03(\x0b\x32/.temporal.api.cloud.identity.v1.UserGroupMember\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\t"{\n\x1b\x43reateServiceAccountRequest\x12@\n\x04spec\x18\x01 \x01(\x0b\x32\x32.temporal.api.cloud.identity.v1.ServiceAccountSpec\x12\x1a\n\x12\x61sync_operation_id\x18\x02 \x01(\t"\x84\x01\n\x1c\x43reateServiceAccountResponse\x12\x1a\n\x12service_account_id\x18\x01 \x01(\t\x12H\n\x0f\x61sync_operation\x18\x02 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"6\n\x18GetServiceAccountRequest\x12\x1a\n\x12service_account_id\x18\x01 \x01(\t"d\n\x19GetServiceAccountResponse\x12G\n\x0fservice_account\x18\x01 \x01(\x0b\x32..temporal.api.cloud.identity.v1.ServiceAccount"B\n\x19GetServiceAccountsRequest\x12\x11\n\tpage_size\x18\x01 \x01(\x05\x12\x12\n\npage_token\x18\x02 \x01(\t"~\n\x1aGetServiceAccountsResponse\x12G\n\x0fservice_account\x18\x01 \x03(\x0b\x32..temporal.api.cloud.identity.v1.ServiceAccount\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\t"\xb1\x01\n\x1bUpdateServiceAccountRequest\x12\x1a\n\x12service_account_id\x18\x01 \x01(\t\x12@\n\x04spec\x18\x02 \x01(\x0b\x32\x32.temporal.api.cloud.identity.v1.ServiceAccountSpec\x12\x18\n\x10resource_version\x18\x03 \x01(\t\x12\x1a\n\x12\x61sync_operation_id\x18\x04 \x01(\t"h\n\x1cUpdateServiceAccountResponse\x12H\n\x0f\x61sync_operation\x18\x01 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"\xcf\x01\n\'SetServiceAccountNamespaceAccessRequest\x12\x1a\n\x12service_account_id\x18\x01 \x01(\t\x12\x11\n\tnamespace\x18\x02 \x01(\t\x12?\n\x06\x61\x63\x63\x65ss\x18\x03 \x01(\x0b\x32/.temporal.api.cloud.identity.v1.NamespaceAccess\x12\x18\n\x10resource_version\x18\x04 \x01(\t\x12\x1a\n\x12\x61sync_operation_id\x18\x05 \x01(\t"t\n(SetServiceAccountNamespaceAccessResponse\x12H\n\x0f\x61sync_operation\x18\x01 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"o\n\x1b\x44\x65leteServiceAccountRequest\x12\x1a\n\x12service_account_id\x18\x01 \x01(\t\x12\x18\n\x10resource_version\x18\x02 \x01(\t\x12\x1a\n\x12\x61sync_operation_id\x18\x03 \x01(\t"h\n\x1c\x44\x65leteServiceAccountResponse\x12H\n\x0f\x61sync_operation\x18\x01 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"\xaa\x01\n\x0fGetUsageRequest\x12\x38\n\x14start_time_inclusive\x18\x01 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x36\n\x12\x65nd_time_exclusive\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x11\n\tpage_size\x18\x03 \x01(\x05\x12\x12\n\npage_token\x18\x04 \x01(\t"d\n\x10GetUsageResponse\x12\x37\n\tsummaries\x18\x01 \x03(\x0b\x32$.temporal.api.cloud.usage.v1.Summary\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\t"\x13\n\x11GetAccountRequest"M\n\x12GetAccountResponse\x12\x37\n\x07\x61\x63\x63ount\x18\x01 \x01(\x0b\x32&.temporal.api.cloud.account.v1.Account"\x86\x01\n\x14UpdateAccountRequest\x12\x38\n\x04spec\x18\x01 \x01(\x0b\x32*.temporal.api.cloud.account.v1.AccountSpec\x12\x18\n\x10resource_version\x18\x02 \x01(\t\x12\x1a\n\x12\x61sync_operation_id\x18\x03 \x01(\t"a\n\x15UpdateAccountResponse\x12H\n\x0f\x61sync_operation\x18\x01 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"\x90\x01\n CreateNamespaceExportSinkRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12=\n\x04spec\x18\x02 \x01(\x0b\x32/.temporal.api.cloud.namespace.v1.ExportSinkSpec\x12\x1a\n\x12\x61sync_operation_id\x18\x03 \x01(\t"m\n!CreateNamespaceExportSinkResponse\x12H\n\x0f\x61sync_operation\x18\x01 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"@\n\x1dGetNamespaceExportSinkRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x0c\n\x04name\x18\x02 \x01(\t"[\n\x1eGetNamespaceExportSinkResponse\x12\x39\n\x04sink\x18\x01 \x01(\x0b\x32+.temporal.api.cloud.namespace.v1.ExportSink"Z\n\x1eGetNamespaceExportSinksRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x11\n\tpage_size\x18\x02 \x01(\x05\x12\x12\n\npage_token\x18\x03 \x01(\t"v\n\x1fGetNamespaceExportSinksResponse\x12:\n\x05sinks\x18\x01 \x03(\x0b\x32+.temporal.api.cloud.namespace.v1.ExportSink\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\t"\xaa\x01\n UpdateNamespaceExportSinkRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12=\n\x04spec\x18\x02 \x01(\x0b\x32/.temporal.api.cloud.namespace.v1.ExportSinkSpec\x12\x18\n\x10resource_version\x18\x03 \x01(\t\x12\x1a\n\x12\x61sync_operation_id\x18\x04 \x01(\t"m\n!UpdateNamespaceExportSinkResponse\x12H\n\x0f\x61sync_operation\x18\x01 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"y\n DeleteNamespaceExportSinkRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x0c\n\x04name\x18\x02 \x01(\t\x12\x18\n\x10resource_version\x18\x03 \x01(\t\x12\x1a\n\x12\x61sync_operation_id\x18\x04 \x01(\t"m\n!DeleteNamespaceExportSinkResponse\x12H\n\x0f\x61sync_operation\x18\x01 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"v\n"ValidateNamespaceExportSinkRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12=\n\x04spec\x18\x02 \x01(\x0b\x32/.temporal.api.cloud.namespace.v1.ExportSinkSpec"%\n#ValidateNamespaceExportSinkResponse"\x82\x02\n\x1aUpdateNamespaceTagsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12h\n\x0etags_to_upsert\x18\x02 \x03(\x0b\x32P.temporal.api.cloud.cloudservice.v1.UpdateNamespaceTagsRequest.TagsToUpsertEntry\x12\x16\n\x0etags_to_remove\x18\x03 \x03(\t\x12\x1a\n\x12\x61sync_operation_id\x18\x04 \x01(\t\x1a\x33\n\x11TagsToUpsertEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01"g\n\x1bUpdateNamespaceTagsResponse\x12H\n\x0f\x61sync_operation\x18\x01 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"\x87\x01\n\x1d\x43reateConnectivityRuleRequest\x12J\n\x04spec\x18\x01 \x01(\x0b\x32<.temporal.api.cloud.connectivityrule.v1.ConnectivityRuleSpec\x12\x1a\n\x12\x61sync_operation_id\x18\x02 \x01(\t"\x88\x01\n\x1e\x43reateConnectivityRuleResponse\x12\x1c\n\x14\x63onnectivity_rule_id\x18\x01 \x01(\t\x12H\n\x0f\x61sync_operation\x18\x02 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation":\n\x1aGetConnectivityRuleRequest\x12\x1c\n\x14\x63onnectivity_rule_id\x18\x01 \x01(\t"r\n\x1bGetConnectivityRuleResponse\x12S\n\x11\x63onnectivity_rule\x18\x01 \x01(\x0b\x32\x38.temporal.api.cloud.connectivityrule.v1.ConnectivityRule"W\n\x1bGetConnectivityRulesRequest\x12\x11\n\tpage_size\x18\x01 \x01(\x05\x12\x12\n\npage_token\x18\x02 \x01(\t\x12\x11\n\tnamespace\x18\x03 \x01(\t"\x8d\x01\n\x1cGetConnectivityRulesResponse\x12T\n\x12\x63onnectivity_rules\x18\x01 \x03(\x0b\x32\x38.temporal.api.cloud.connectivityrule.v1.ConnectivityRule\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\t"s\n\x1d\x44\x65leteConnectivityRuleRequest\x12\x1c\n\x14\x63onnectivity_rule_id\x18\x01 \x01(\t\x12\x18\n\x10resource_version\x18\x02 \x01(\t\x12\x1a\n\x12\x61sync_operation_id\x18\x03 \x01(\t"j\n\x1e\x44\x65leteConnectivityRuleResponse\x12H\n\x0f\x61sync_operation\x18\x01 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"\xae\x01\n\x13GetAuditLogsRequest\x12\x11\n\tpage_size\x18\x01 \x01(\x05\x12\x12\n\npage_token\x18\x02 \x01(\t\x12\x38\n\x14start_time_inclusive\x18\x03 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x36\n\x12\x65nd_time_exclusive\x18\x04 \x01(\x0b\x32\x1a.google.protobuf.Timestamp"h\n\x14GetAuditLogsResponse\x12\x37\n\x04logs\x18\x01 \x03(\x0b\x32).temporal.api.cloud.auditlog.v1.LogRecord\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\t"c\n"ValidateAccountAuditLogSinkRequest\x12=\n\x04spec\x18\x01 \x01(\x0b\x32/.temporal.api.cloud.account.v1.AuditLogSinkSpec"%\n#ValidateAccountAuditLogSinkResponse"}\n CreateAccountAuditLogSinkRequest\x12=\n\x04spec\x18\x01 \x01(\x0b\x32/.temporal.api.cloud.account.v1.AuditLogSinkSpec\x12\x1a\n\x12\x61sync_operation_id\x18\x02 \x01(\t"m\n!CreateAccountAuditLogSinkResponse\x12H\n\x0f\x61sync_operation\x18\x01 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"-\n\x1dGetAccountAuditLogSinkRequest\x12\x0c\n\x04name\x18\x01 \x01(\t"[\n\x1eGetAccountAuditLogSinkResponse\x12\x39\n\x04sink\x18\x01 \x01(\x0b\x32+.temporal.api.cloud.account.v1.AuditLogSink"G\n\x1eGetAccountAuditLogSinksRequest\x12\x11\n\tpage_size\x18\x01 \x01(\x05\x12\x12\n\npage_token\x18\x02 \x01(\t"v\n\x1fGetAccountAuditLogSinksResponse\x12:\n\x05sinks\x18\x01 \x03(\x0b\x32+.temporal.api.cloud.account.v1.AuditLogSink\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\t"\x97\x01\n UpdateAccountAuditLogSinkRequest\x12=\n\x04spec\x18\x01 \x01(\x0b\x32/.temporal.api.cloud.account.v1.AuditLogSinkSpec\x12\x18\n\x10resource_version\x18\x02 \x01(\t\x12\x1a\n\x12\x61sync_operation_id\x18\x03 \x01(\t"m\n!UpdateAccountAuditLogSinkResponse\x12H\n\x0f\x61sync_operation\x18\x01 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"f\n DeleteAccountAuditLogSinkRequest\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x18\n\x10resource_version\x18\x02 \x01(\t\x12\x1a\n\x12\x61sync_operation_id\x18\x03 \x01(\t"m\n!DeleteAccountAuditLogSinkResponse\x12H\n\x0f\x61sync_operation\x18\x01 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"4\n\x1fGetNamespaceCapacityInfoRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t"q\n GetNamespaceCapacityInfoResponse\x12M\n\rcapacity_info\x18\x01 \x01(\x0b\x32\x36.temporal.api.cloud.namespace.v1.NamespaceCapacityInfo"x\n\x1a\x43reateBillingReportRequest\x12>\n\x04spec\x18\x01 \x01(\x0b\x32\x30.temporal.api.cloud.billing.v1.BillingReportSpec\x12\x1a\n\x12\x61sync_operation_id\x18\x02 \x01(\t"\x82\x01\n\x1b\x43reateBillingReportResponse\x12\x19\n\x11\x62illing_report_id\x18\x01 \x01(\t\x12H\n\x0f\x61sync_operation\x18\x02 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"4\n\x17GetBillingReportRequest\x12\x19\n\x11\x62illing_report_id\x18\x01 \x01(\t"`\n\x18GetBillingReportResponse\x12\x44\n\x0e\x62illing_report\x18\x01 \x01(\x0b\x32,.temporal.api.cloud.billing.v1.BillingReport">\n\x15GetCustomRolesRequest\x12\x11\n\tpage_size\x18\x01 \x01(\x05\x12\x12\n\npage_token\x18\x02 \x01(\t"s\n\x16GetCustomRolesResponse\x12@\n\x0c\x63ustom_roles\x18\x01 \x03(\x0b\x32*.temporal.api.cloud.identity.v1.CustomRole\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\t"\'\n\x14GetCustomRoleRequest\x12\x0f\n\x07role_id\x18\x01 \x01(\t"X\n\x15GetCustomRoleResponse\x12?\n\x0b\x63ustom_role\x18\x01 \x01(\x0b\x32*.temporal.api.cloud.identity.v1.CustomRole"s\n\x17\x43reateCustomRoleRequest\x12<\n\x04spec\x18\x01 \x01(\x0b\x32..temporal.api.cloud.identity.v1.CustomRoleSpec\x12\x1a\n\x12\x61sync_operation_id\x18\x02 \x01(\t"u\n\x18\x43reateCustomRoleResponse\x12\x0f\n\x07role_id\x18\x01 \x01(\t\x12H\n\x0f\x61sync_operation\x18\x02 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"\x9e\x01\n\x17UpdateCustomRoleRequest\x12\x0f\n\x07role_id\x18\x01 \x01(\t\x12<\n\x04spec\x18\x02 \x01(\x0b\x32..temporal.api.cloud.identity.v1.CustomRoleSpec\x12\x18\n\x10resource_version\x18\x03 \x01(\t\x12\x1a\n\x12\x61sync_operation_id\x18\x04 \x01(\t"d\n\x18UpdateCustomRoleResponse\x12H\n\x0f\x61sync_operation\x18\x01 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"`\n\x17\x44\x65leteCustomRoleRequest\x12\x0f\n\x07role_id\x18\x01 \x01(\t\x12\x18\n\x10resource_version\x18\x02 \x01(\t\x12\x1a\n\x12\x61sync_operation_id\x18\x03 \x01(\t"d\n\x18\x44\x65leteCustomRoleResponse\x12H\n\x0f\x61sync_operation\x18\x01 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperationB\xc8\x01\n%io.temporal.api.cloud.cloudservice.v1B\x14RequestResponseProtoP\x01Z5go.temporal.io/api/cloud/cloudservice/v1;cloudservice\xaa\x02$Temporalio.Api.Cloud.CloudService.V1\xea\x02(Temporalio::Api::Cloud::CloudService::V1b\x06proto3' ) @@ -354,6 +354,16 @@ ] _GETBILLINGREPORTREQUEST = DESCRIPTOR.message_types_by_name["GetBillingReportRequest"] _GETBILLINGREPORTRESPONSE = DESCRIPTOR.message_types_by_name["GetBillingReportResponse"] +_GETCUSTOMROLESREQUEST = DESCRIPTOR.message_types_by_name["GetCustomRolesRequest"] +_GETCUSTOMROLESRESPONSE = DESCRIPTOR.message_types_by_name["GetCustomRolesResponse"] +_GETCUSTOMROLEREQUEST = DESCRIPTOR.message_types_by_name["GetCustomRoleRequest"] +_GETCUSTOMROLERESPONSE = DESCRIPTOR.message_types_by_name["GetCustomRoleResponse"] +_CREATECUSTOMROLEREQUEST = DESCRIPTOR.message_types_by_name["CreateCustomRoleRequest"] +_CREATECUSTOMROLERESPONSE = DESCRIPTOR.message_types_by_name["CreateCustomRoleResponse"] +_UPDATECUSTOMROLEREQUEST = DESCRIPTOR.message_types_by_name["UpdateCustomRoleRequest"] +_UPDATECUSTOMROLERESPONSE = DESCRIPTOR.message_types_by_name["UpdateCustomRoleResponse"] +_DELETECUSTOMROLEREQUEST = DESCRIPTOR.message_types_by_name["DeleteCustomRoleRequest"] +_DELETECUSTOMROLERESPONSE = DESCRIPTOR.message_types_by_name["DeleteCustomRoleResponse"] GetCurrentIdentityRequest = _reflection.GeneratedProtocolMessageType( "GetCurrentIdentityRequest", (_message.Message,), @@ -1890,6 +1900,116 @@ ) _sym_db.RegisterMessage(GetBillingReportResponse) +GetCustomRolesRequest = _reflection.GeneratedProtocolMessageType( + "GetCustomRolesRequest", + (_message.Message,), + { + "DESCRIPTOR": _GETCUSTOMROLESREQUEST, + "__module__": "temporalio.api.cloud.cloudservice.v1.request_response_pb2", + # @@protoc_insertion_point(class_scope:temporal.api.cloud.cloudservice.v1.GetCustomRolesRequest) + }, +) +_sym_db.RegisterMessage(GetCustomRolesRequest) + +GetCustomRolesResponse = _reflection.GeneratedProtocolMessageType( + "GetCustomRolesResponse", + (_message.Message,), + { + "DESCRIPTOR": _GETCUSTOMROLESRESPONSE, + "__module__": "temporalio.api.cloud.cloudservice.v1.request_response_pb2", + # @@protoc_insertion_point(class_scope:temporal.api.cloud.cloudservice.v1.GetCustomRolesResponse) + }, +) +_sym_db.RegisterMessage(GetCustomRolesResponse) + +GetCustomRoleRequest = _reflection.GeneratedProtocolMessageType( + "GetCustomRoleRequest", + (_message.Message,), + { + "DESCRIPTOR": _GETCUSTOMROLEREQUEST, + "__module__": "temporalio.api.cloud.cloudservice.v1.request_response_pb2", + # @@protoc_insertion_point(class_scope:temporal.api.cloud.cloudservice.v1.GetCustomRoleRequest) + }, +) +_sym_db.RegisterMessage(GetCustomRoleRequest) + +GetCustomRoleResponse = _reflection.GeneratedProtocolMessageType( + "GetCustomRoleResponse", + (_message.Message,), + { + "DESCRIPTOR": _GETCUSTOMROLERESPONSE, + "__module__": "temporalio.api.cloud.cloudservice.v1.request_response_pb2", + # @@protoc_insertion_point(class_scope:temporal.api.cloud.cloudservice.v1.GetCustomRoleResponse) + }, +) +_sym_db.RegisterMessage(GetCustomRoleResponse) + +CreateCustomRoleRequest = _reflection.GeneratedProtocolMessageType( + "CreateCustomRoleRequest", + (_message.Message,), + { + "DESCRIPTOR": _CREATECUSTOMROLEREQUEST, + "__module__": "temporalio.api.cloud.cloudservice.v1.request_response_pb2", + # @@protoc_insertion_point(class_scope:temporal.api.cloud.cloudservice.v1.CreateCustomRoleRequest) + }, +) +_sym_db.RegisterMessage(CreateCustomRoleRequest) + +CreateCustomRoleResponse = _reflection.GeneratedProtocolMessageType( + "CreateCustomRoleResponse", + (_message.Message,), + { + "DESCRIPTOR": _CREATECUSTOMROLERESPONSE, + "__module__": "temporalio.api.cloud.cloudservice.v1.request_response_pb2", + # @@protoc_insertion_point(class_scope:temporal.api.cloud.cloudservice.v1.CreateCustomRoleResponse) + }, +) +_sym_db.RegisterMessage(CreateCustomRoleResponse) + +UpdateCustomRoleRequest = _reflection.GeneratedProtocolMessageType( + "UpdateCustomRoleRequest", + (_message.Message,), + { + "DESCRIPTOR": _UPDATECUSTOMROLEREQUEST, + "__module__": "temporalio.api.cloud.cloudservice.v1.request_response_pb2", + # @@protoc_insertion_point(class_scope:temporal.api.cloud.cloudservice.v1.UpdateCustomRoleRequest) + }, +) +_sym_db.RegisterMessage(UpdateCustomRoleRequest) + +UpdateCustomRoleResponse = _reflection.GeneratedProtocolMessageType( + "UpdateCustomRoleResponse", + (_message.Message,), + { + "DESCRIPTOR": _UPDATECUSTOMROLERESPONSE, + "__module__": "temporalio.api.cloud.cloudservice.v1.request_response_pb2", + # @@protoc_insertion_point(class_scope:temporal.api.cloud.cloudservice.v1.UpdateCustomRoleResponse) + }, +) +_sym_db.RegisterMessage(UpdateCustomRoleResponse) + +DeleteCustomRoleRequest = _reflection.GeneratedProtocolMessageType( + "DeleteCustomRoleRequest", + (_message.Message,), + { + "DESCRIPTOR": _DELETECUSTOMROLEREQUEST, + "__module__": "temporalio.api.cloud.cloudservice.v1.request_response_pb2", + # @@protoc_insertion_point(class_scope:temporal.api.cloud.cloudservice.v1.DeleteCustomRoleRequest) + }, +) +_sym_db.RegisterMessage(DeleteCustomRoleRequest) + +DeleteCustomRoleResponse = _reflection.GeneratedProtocolMessageType( + "DeleteCustomRoleResponse", + (_message.Message,), + { + "DESCRIPTOR": _DELETECUSTOMROLERESPONSE, + "__module__": "temporalio.api.cloud.cloudservice.v1.request_response_pb2", + # @@protoc_insertion_point(class_scope:temporal.api.cloud.cloudservice.v1.DeleteCustomRoleResponse) + }, +) +_sym_db.RegisterMessage(DeleteCustomRoleResponse) + if _descriptor._USE_C_DESCRIPTORS == False: DESCRIPTOR._options = None DESCRIPTOR._serialized_options = b"\n%io.temporal.api.cloud.cloudservice.v1B\024RequestResponseProtoP\001Z5go.temporal.io/api/cloud/cloudservice/v1;cloudservice\252\002$Temporalio.Api.Cloud.CloudService.V1\352\002(Temporalio::Api::Cloud::CloudService::V1" @@ -2181,4 +2301,24 @@ _GETBILLINGREPORTREQUEST._serialized_end = 15683 _GETBILLINGREPORTRESPONSE._serialized_start = 15685 _GETBILLINGREPORTRESPONSE._serialized_end = 15781 + _GETCUSTOMROLESREQUEST._serialized_start = 15783 + _GETCUSTOMROLESREQUEST._serialized_end = 15845 + _GETCUSTOMROLESRESPONSE._serialized_start = 15847 + _GETCUSTOMROLESRESPONSE._serialized_end = 15962 + _GETCUSTOMROLEREQUEST._serialized_start = 15964 + _GETCUSTOMROLEREQUEST._serialized_end = 16003 + _GETCUSTOMROLERESPONSE._serialized_start = 16005 + _GETCUSTOMROLERESPONSE._serialized_end = 16093 + _CREATECUSTOMROLEREQUEST._serialized_start = 16095 + _CREATECUSTOMROLEREQUEST._serialized_end = 16210 + _CREATECUSTOMROLERESPONSE._serialized_start = 16212 + _CREATECUSTOMROLERESPONSE._serialized_end = 16329 + _UPDATECUSTOMROLEREQUEST._serialized_start = 16332 + _UPDATECUSTOMROLEREQUEST._serialized_end = 16490 + _UPDATECUSTOMROLERESPONSE._serialized_start = 16492 + _UPDATECUSTOMROLERESPONSE._serialized_end = 16592 + _DELETECUSTOMROLEREQUEST._serialized_start = 16594 + _DELETECUSTOMROLEREQUEST._serialized_end = 16690 + _DELETECUSTOMROLERESPONSE._serialized_start = 16692 + _DELETECUSTOMROLERESPONSE._serialized_end = 16792 # @@protoc_insertion_point(module_scope) diff --git a/temporalio/api/cloud/cloudservice/v1/request_response_pb2.pyi b/temporalio/api/cloud/cloudservice/v1/request_response_pb2.pyi index 9de8a7930..404554099 100644 --- a/temporalio/api/cloud/cloudservice/v1/request_response_pb2.pyi +++ b/temporalio/api/cloud/cloudservice/v1/request_response_pb2.pyi @@ -4298,3 +4298,298 @@ class GetBillingReportResponse(google.protobuf.message.Message): ) -> None: ... global___GetBillingReportResponse = GetBillingReportResponse + +class GetCustomRolesRequest(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + PAGE_SIZE_FIELD_NUMBER: builtins.int + PAGE_TOKEN_FIELD_NUMBER: builtins.int + page_size: builtins.int + """The requested size of the page to retrieve. + Cannot exceed 1000. Defaults to 100. + """ + page_token: builtins.str + """The page token if this is continuing from another response.""" + def __init__( + self, + *, + page_size: builtins.int = ..., + page_token: builtins.str = ..., + ) -> None: ... + def ClearField( + self, + field_name: typing_extensions.Literal[ + "page_size", b"page_size", "page_token", b"page_token" + ], + ) -> None: ... + +global___GetCustomRolesRequest = GetCustomRolesRequest + +class GetCustomRolesResponse(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + CUSTOM_ROLES_FIELD_NUMBER: builtins.int + NEXT_PAGE_TOKEN_FIELD_NUMBER: builtins.int + @property + def custom_roles( + self, + ) -> google.protobuf.internal.containers.RepeatedCompositeFieldContainer[ + temporalio.api.cloud.identity.v1.message_pb2.CustomRole + ]: + """The list of custom roles in ascending ID order.""" + next_page_token: builtins.str + """The next page token.""" + def __init__( + self, + *, + custom_roles: collections.abc.Iterable[ + temporalio.api.cloud.identity.v1.message_pb2.CustomRole + ] + | None = ..., + next_page_token: builtins.str = ..., + ) -> None: ... + def ClearField( + self, + field_name: typing_extensions.Literal[ + "custom_roles", b"custom_roles", "next_page_token", b"next_page_token" + ], + ) -> None: ... + +global___GetCustomRolesResponse = GetCustomRolesResponse + +class GetCustomRoleRequest(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + ROLE_ID_FIELD_NUMBER: builtins.int + role_id: builtins.str + """The ID of the custom role to retrieve.""" + def __init__( + self, + *, + role_id: builtins.str = ..., + ) -> None: ... + def ClearField( + self, field_name: typing_extensions.Literal["role_id", b"role_id"] + ) -> None: ... + +global___GetCustomRoleRequest = GetCustomRoleRequest + +class GetCustomRoleResponse(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + CUSTOM_ROLE_FIELD_NUMBER: builtins.int + @property + def custom_role(self) -> temporalio.api.cloud.identity.v1.message_pb2.CustomRole: + """The custom role retrieved.""" + def __init__( + self, + *, + custom_role: temporalio.api.cloud.identity.v1.message_pb2.CustomRole + | None = ..., + ) -> None: ... + def HasField( + self, field_name: typing_extensions.Literal["custom_role", b"custom_role"] + ) -> builtins.bool: ... + def ClearField( + self, field_name: typing_extensions.Literal["custom_role", b"custom_role"] + ) -> None: ... + +global___GetCustomRoleResponse = GetCustomRoleResponse + +class CreateCustomRoleRequest(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + SPEC_FIELD_NUMBER: builtins.int + ASYNC_OPERATION_ID_FIELD_NUMBER: builtins.int + @property + def spec(self) -> temporalio.api.cloud.identity.v1.message_pb2.CustomRoleSpec: + """The specification for the custom role to create.""" + async_operation_id: builtins.str + """The ID to use for this async operation. + Optional, if not provided a random ID will be generated. + """ + def __init__( + self, + *, + spec: temporalio.api.cloud.identity.v1.message_pb2.CustomRoleSpec | None = ..., + async_operation_id: builtins.str = ..., + ) -> None: ... + def HasField( + self, field_name: typing_extensions.Literal["spec", b"spec"] + ) -> builtins.bool: ... + def ClearField( + self, + field_name: typing_extensions.Literal[ + "async_operation_id", b"async_operation_id", "spec", b"spec" + ], + ) -> None: ... + +global___CreateCustomRoleRequest = CreateCustomRoleRequest + +class CreateCustomRoleResponse(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + ROLE_ID_FIELD_NUMBER: builtins.int + ASYNC_OPERATION_FIELD_NUMBER: builtins.int + role_id: builtins.str + """The ID of the custom role created.""" + @property + def async_operation( + self, + ) -> temporalio.api.cloud.operation.v1.message_pb2.AsyncOperation: + """The async operation.""" + def __init__( + self, + *, + role_id: builtins.str = ..., + async_operation: temporalio.api.cloud.operation.v1.message_pb2.AsyncOperation + | None = ..., + ) -> None: ... + def HasField( + self, + field_name: typing_extensions.Literal["async_operation", b"async_operation"], + ) -> builtins.bool: ... + def ClearField( + self, + field_name: typing_extensions.Literal[ + "async_operation", b"async_operation", "role_id", b"role_id" + ], + ) -> None: ... + +global___CreateCustomRoleResponse = CreateCustomRoleResponse + +class UpdateCustomRoleRequest(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + ROLE_ID_FIELD_NUMBER: builtins.int + SPEC_FIELD_NUMBER: builtins.int + RESOURCE_VERSION_FIELD_NUMBER: builtins.int + ASYNC_OPERATION_ID_FIELD_NUMBER: builtins.int + role_id: builtins.str + """The ID of the custom role to update.""" + @property + def spec(self) -> temporalio.api.cloud.identity.v1.message_pb2.CustomRoleSpec: + """The new custom role specification.""" + resource_version: builtins.str + """The version of the custom role for which this update is intended. + The latest version can be found in the GetCustomRole operation response. + """ + async_operation_id: builtins.str + """The ID to use for this async operation. + Optional, if not provided a random ID will be generated. + """ + def __init__( + self, + *, + role_id: builtins.str = ..., + spec: temporalio.api.cloud.identity.v1.message_pb2.CustomRoleSpec | None = ..., + resource_version: builtins.str = ..., + async_operation_id: builtins.str = ..., + ) -> None: ... + def HasField( + self, field_name: typing_extensions.Literal["spec", b"spec"] + ) -> builtins.bool: ... + def ClearField( + self, + field_name: typing_extensions.Literal[ + "async_operation_id", + b"async_operation_id", + "resource_version", + b"resource_version", + "role_id", + b"role_id", + "spec", + b"spec", + ], + ) -> None: ... + +global___UpdateCustomRoleRequest = UpdateCustomRoleRequest + +class UpdateCustomRoleResponse(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + ASYNC_OPERATION_FIELD_NUMBER: builtins.int + @property + def async_operation( + self, + ) -> temporalio.api.cloud.operation.v1.message_pb2.AsyncOperation: + """The async operation.""" + def __init__( + self, + *, + async_operation: temporalio.api.cloud.operation.v1.message_pb2.AsyncOperation + | None = ..., + ) -> None: ... + def HasField( + self, + field_name: typing_extensions.Literal["async_operation", b"async_operation"], + ) -> builtins.bool: ... + def ClearField( + self, + field_name: typing_extensions.Literal["async_operation", b"async_operation"], + ) -> None: ... + +global___UpdateCustomRoleResponse = UpdateCustomRoleResponse + +class DeleteCustomRoleRequest(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + ROLE_ID_FIELD_NUMBER: builtins.int + RESOURCE_VERSION_FIELD_NUMBER: builtins.int + ASYNC_OPERATION_ID_FIELD_NUMBER: builtins.int + role_id: builtins.str + """The ID of the custom role to delete.""" + resource_version: builtins.str + """The version of the custom role for which this delete is intended. + The latest version can be found in the GetCustomRole operation response. + """ + async_operation_id: builtins.str + """The ID to use for this async operation. + Optional, if not provided a random ID will be generated. + """ + def __init__( + self, + *, + role_id: builtins.str = ..., + resource_version: builtins.str = ..., + async_operation_id: builtins.str = ..., + ) -> None: ... + def ClearField( + self, + field_name: typing_extensions.Literal[ + "async_operation_id", + b"async_operation_id", + "resource_version", + b"resource_version", + "role_id", + b"role_id", + ], + ) -> None: ... + +global___DeleteCustomRoleRequest = DeleteCustomRoleRequest + +class DeleteCustomRoleResponse(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + ASYNC_OPERATION_FIELD_NUMBER: builtins.int + @property + def async_operation( + self, + ) -> temporalio.api.cloud.operation.v1.message_pb2.AsyncOperation: + """The async operation.""" + def __init__( + self, + *, + async_operation: temporalio.api.cloud.operation.v1.message_pb2.AsyncOperation + | None = ..., + ) -> None: ... + def HasField( + self, + field_name: typing_extensions.Literal["async_operation", b"async_operation"], + ) -> builtins.bool: ... + def ClearField( + self, + field_name: typing_extensions.Literal["async_operation", b"async_operation"], + ) -> None: ... + +global___DeleteCustomRoleResponse = DeleteCustomRoleResponse diff --git a/temporalio/api/cloud/cloudservice/v1/service_pb2.py b/temporalio/api/cloud/cloudservice/v1/service_pb2.py index c7c772860..4223fb03d 100644 --- a/temporalio/api/cloud/cloudservice/v1/service_pb2.py +++ b/temporalio/api/cloud/cloudservice/v1/service_pb2.py @@ -24,14 +24,14 @@ ) DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile( - b'\n0temporal/api/cloud/cloudservice/v1/service.proto\x12"temporal.api.cloud.cloudservice.v1\x1a\x39temporal/api/cloud/cloudservice/v1/request_response.proto\x1a\x1cgoogle/api/annotations.proto\x1a.protoc-gen-openapiv2/options/annotations.proto2\xb6\xbe\x01\n\x0c\x43loudService\x12\xb0\x02\n\x12GetCurrentIdentity\x12=.temporal.api.cloud.cloudservice.v1.GetCurrentIdentityRequest\x1a>.temporal.api.cloud.cloudservice.v1.GetCurrentIdentityResponse"\x9a\x01\x82\xd3\xe4\x93\x02\x19\x12\x17/cloud/current-identity\x92\x41x\n\x07\x41\x63\x63ount\x12\x14Get current identity\x1aWReturns information about the currently authenticated user or service account principal\x12\xa5\x02\n\x08GetUsers\x12\x33.temporal.api.cloud.cloudservice.v1.GetUsersRequest\x1a\x34.temporal.api.cloud.cloudservice.v1.GetUsersResponse"\xad\x01\x82\xd3\xe4\x93\x02\x0e\x12\x0c/cloud/users\x92\x41\x95\x01\n\x05Users\x12\x0eList all users\x1a*Returns a list of all users in the account"E\n\x1dUser management documentation\x12$https://docs.temporal.io/cloud/users*\tlistUsers\x12\x9c\x02\n\x07GetUser\x12\x32.temporal.api.cloud.cloudservice.v1.GetUserRequest\x1a\x33.temporal.api.cloud.cloudservice.v1.GetUserResponse"\xa7\x01\x82\xd3\xe4\x93\x02\x18\x12\x16/cloud/users/{user_id}\x92\x41\x85\x01\n\x05Users\x12\x0eGet user by ID\x1a%Takes a user ID, returns user details"E\n\x1dUser management documentation\x12$https://docs.temporal.io/cloud/users\x12\xd0\x01\n\nCreateUser\x12\x35.temporal.api.cloud.cloudservice.v1.CreateUserRequest\x1a\x36.temporal.api.cloud.cloudservice.v1.CreateUserResponse"S\x82\xd3\xe4\x93\x02\x11"\x0c/cloud/users:\x01*\x92\x41\x39\n\x05Users\x12\rCreate a user\x1a!Creates a new user in the account\x12\xdb\x01\n\nUpdateUser\x12\x35.temporal.api.cloud.cloudservice.v1.UpdateUserRequest\x1a\x36.temporal.api.cloud.cloudservice.v1.UpdateUserResponse"^\x82\xd3\xe4\x93\x02\x1b"\x16/cloud/users/{user_id}:\x01*\x92\x41:\n\x05Users\x12\rUpdate a user\x1a"Updates an existing user\'s details\x12\xd5\x01\n\nDeleteUser\x12\x35.temporal.api.cloud.cloudservice.v1.DeleteUserRequest\x1a\x36.temporal.api.cloud.cloudservice.v1.DeleteUserResponse"X\x82\xd3\xe4\x93\x02\x18*\x16/cloud/users/{user_id}\x92\x41\x37\n\x05Users\x12\rDelete a user\x1a\x1fRemoves a user from the account\x12\xaa\x03\n\x16SetUserNamespaceAccess\x12\x41.temporal.api.cloud.cloudservice.v1.SetUserNamespaceAccessRequest\x1a\x42.temporal.api.cloud.cloudservice.v1.SetUserNamespaceAccessResponse"\x88\x02\x82\xd3\xe4\x93\x02\x39"4/cloud/namespaces/{namespace}/users/{user_id}/access:\x01*\x92\x41\xc5\x01\n\x05Users\x12\x19Set user namespace access\x1a\x38\x43onfigures a user\'s permissions for a specific namespace"g\n#Namespace permissions documentation\x12@https://docs.temporal.io/cloud/users-namespace-level-permissions\x12\xb1\x02\n\x11GetAsyncOperation\x12<.temporal.api.cloud.cloudservice.v1.GetAsyncOperationRequest\x1a=.temporal.api.cloud.cloudservice.v1.GetAsyncOperationResponse"\x9e\x01\x82\xd3\xe4\x93\x02(\x12&/cloud/operations/{async_operation_id}\x92\x41m\n\nOperations\x12\x1aGet async operation status\x1a\x43Returns the current status and details of an asynchronous operation\x12\xc6\x02\n\x0f\x43reateNamespace\x12:.temporal.api.cloud.cloudservice.v1.CreateNamespaceRequest\x1a;.temporal.api.cloud.cloudservice.v1.CreateNamespaceResponse"\xb9\x01\x82\xd3\xe4\x93\x02\x16"\x11/cloud/namespaces:\x01*\x92\x41\x99\x01\n\nNamespaces\x12\x12\x43reate a namespace\x1a&Creates a new namespace in the account"O\n"Namespace management documentation\x12)https://docs.temporal.io/cloud/namespaces\x12\xc7\x02\n\rGetNamespaces\x12\x38.temporal.api.cloud.cloudservice.v1.GetNamespacesRequest\x1a\x39.temporal.api.cloud.cloudservice.v1.GetNamespacesResponse"\xc0\x01\x82\xd3\xe4\x93\x02\x13\x12\x11/cloud/namespaces\x92\x41\xa3\x01\n\nNamespaces\x12\x13List all namespaces\x1a/Returns a list of all namespaces in the account"O\n"Namespace management documentation\x12)https://docs.temporal.io/cloud/namespaces\x12\xda\x02\n\x0cGetNamespace\x12\x37.temporal.api.cloud.cloudservice.v1.GetNamespaceRequest\x1a\x38.temporal.api.cloud.cloudservice.v1.GetNamespaceResponse"\xd6\x01\x82\xd3\xe4\x93\x02\x1f\x12\x1d/cloud/namespaces/{namespace}\x92\x41\xad\x01\n\nNamespaces\x12\x15Get namespace details\x1a\x37Returns detailed information about a specific namespace"O\n"Namespace management documentation\x12)https://docs.temporal.io/cloud/namespaces\x12\xdb\x02\n\x0fUpdateNamespace\x12:.temporal.api.cloud.cloudservice.v1.UpdateNamespaceRequest\x1a;.temporal.api.cloud.cloudservice.v1.UpdateNamespaceResponse"\xce\x01\x82\xd3\xe4\x93\x02""\x1d/cloud/namespaces/{namespace}:\x01*\x92\x41\xa2\x01\n\nNamespaces\x12\x12Update a namespace\x1a/Updates configuration for an existing namespace"O\n"Namespace management documentation\x12)https://docs.temporal.io/cloud/namespaces\x12\xc7\x03\n\x1bRenameCustomSearchAttribute\x12\x46.temporal.api.cloud.cloudservice.v1.RenameCustomSearchAttributeRequest\x1aG.temporal.api.cloud.cloudservice.v1.RenameCustomSearchAttributeResponse"\x96\x02\x82\xd3\xe4\x93\x02\x41".temporal.api.cloud.cloudservice.v1.AddNamespaceRegionResponse"\xed\x01\x82\xd3\xe4\x93\x02-"(/cloud/namespaces/{namespace}/add-region:\x01*\x92\x41\xb6\x01\n\x11High Availability\x12\x15\x41\x64\x64 namespace replica\x1a+Adds a new replica to an existing namespace"]\n)High availability namespace documentation\x12\x30https://docs.temporal.io/cloud/high-availability\x12\x9b\x03\n\x15\x44\x65leteNamespaceRegion\x12@.temporal.api.cloud.cloudservice.v1.DeleteNamespaceRegionRequest\x1a\x41.temporal.api.cloud.cloudservice.v1.DeleteNamespaceRegionResponse"\xfc\x01\x82\xd3\xe4\x93\x02\x30*./cloud/namespaces/{namespace}/regions/{region}\x92\x41\xc2\x01\n\x11High Availability\x12\x18Remove namespace replica\x1a\x34Removes a replica from a high availability namespace"]\n)High availability namespace documentation\x12\x30https://docs.temporal.io/cloud/high-availability\x12\xa3\x02\n\nGetRegions\x12\x35.temporal.api.cloud.cloudservice.v1.GetRegionsRequest\x1a\x36.temporal.api.cloud.cloudservice.v1.GetRegionsResponse"\xa5\x01\x82\xd3\xe4\x93\x02\x10\x12\x0e/cloud/regions\x92\x41\x8b\x01\n\x07Regions\x12\x10List all regions\x1a-Returns a list of all available cloud regions"?\n\x15Regions documentation\x12&https://docs.temporal.io/cloud/regions\x12\xb2\x02\n\tGetRegion\x12\x34.temporal.api.cloud.cloudservice.v1.GetRegionRequest\x1a\x35.temporal.api.cloud.cloudservice.v1.GetRegionResponse"\xb7\x01\x82\xd3\xe4\x93\x02\x19\x12\x17/cloud/regions/{region}\x92\x41\x94\x01\n\x07Regions\x12\x12Get region details\x1a\x34Returns detailed information about a specific region"?\n\x15Regions documentation\x12&https://docs.temporal.io/cloud/regions\x12\xa8\x02\n\nGetApiKeys\x12\x35.temporal.api.cloud.cloudservice.v1.GetApiKeysRequest\x1a\x36.temporal.api.cloud.cloudservice.v1.GetApiKeysResponse"\xaa\x01\x82\xd3\xe4\x93\x02\x11\x12\x0f/cloud/api-keys\x92\x41\x8f\x01\n\x08\x41PI Keys\x12\x11List all API keys\x1a-Returns a list of all API keys in the account"A\n\x16\x41PI Keys documentation\x12\'https://docs.temporal.io/cloud/api-keys\x12\xb8\x02\n\tGetApiKey\x12\x34.temporal.api.cloud.cloudservice.v1.GetApiKeyRequest\x1a\x35.temporal.api.cloud.cloudservice.v1.GetApiKeyResponse"\xbd\x01\x82\xd3\xe4\x93\x02\x1a\x12\x18/cloud/api-keys/{key_id}\x92\x41\x99\x01\n\x08\x41PI Keys\x12\x13Get API key details\x1a\x35Returns detailed information about a specific API key"A\n\x16\x41PI Keys documentation\x12\'https://docs.temporal.io/cloud/api-keys\x12\xb1\x02\n\x0c\x43reateApiKey\x12\x37.temporal.api.cloud.cloudservice.v1.CreateApiKeyRequest\x1a\x38.temporal.api.cloud.cloudservice.v1.CreateApiKeyResponse"\xad\x01\x82\xd3\xe4\x93\x02\x14"\x0f/cloud/api-keys:\x01*\x92\x41\x8f\x01\n\x08\x41PI Keys\x12\x11\x43reate an API key\x1a-Creates a new API key for programmatic access"A\n\x16\x41PI Keys documentation\x12\'https://docs.temporal.io/cloud/api-keys\x12\xb5\x02\n\x0cUpdateApiKey\x12\x37.temporal.api.cloud.cloudservice.v1.UpdateApiKeyRequest\x1a\x38.temporal.api.cloud.cloudservice.v1.UpdateApiKeyResponse"\xb1\x01\x82\xd3\xe4\x93\x02\x1d"\x18/cloud/api-keys/{key_id}:\x01*\x92\x41\x8a\x01\n\x08\x41PI Keys\x12\x11Update an API key\x1a(Updates an existing API key\'s properties"A\n\x16\x41PI Keys documentation\x12\'https://docs.temporal.io/cloud/api-keys\x12\xa8\x02\n\x0c\x44\x65leteApiKey\x12\x37.temporal.api.cloud.cloudservice.v1.DeleteApiKeyRequest\x1a\x38.temporal.api.cloud.cloudservice.v1.DeleteApiKeyResponse"\xa4\x01\x82\xd3\xe4\x93\x02\x1a*\x18/cloud/api-keys/{key_id}\x92\x41\x80\x01\n\x08\x41PI Keys\x12\x11\x44\x65lete an API key\x1a\x1eRevokes and deletes an API key"A\n\x16\x41PI Keys documentation\x12\'https://docs.temporal.io/cloud/api-keys\x12\xc3\x02\n\x11GetNexusEndpoints\x12<.temporal.api.cloud.cloudservice.v1.GetNexusEndpointsRequest\x1a=.temporal.api.cloud.cloudservice.v1.GetNexusEndpointsResponse"\xb0\x01\x82\xd3\xe4\x93\x02\x18\x12\x16/cloud/nexus/endpoints\x92\x41\x8e\x01\n\x05Nexus\x12\x18List all Nexus endpoints\x1a\x34Returns a list of all Nexus endpoints in the account"5\n\x13Nexus documentation\x12\x1ehttps://docs.temporal.io/nexus\x12\xd8\x02\n\x10GetNexusEndpoint\x12;.temporal.api.cloud.cloudservice.v1.GetNexusEndpointRequest\x1a<.temporal.api.cloud.cloudservice.v1.GetNexusEndpointResponse"\xc8\x01\x82\xd3\xe4\x93\x02&\x12$/cloud/nexus/endpoints/{endpoint_id}\x92\x41\x98\x01\n\x05Nexus\x12\x1aGet Nexus endpoint details\x1a.temporal.api.cloud.cloudservice.v1.CreateNexusEndpointRequest\x1a?.temporal.api.cloud.cloudservice.v1.CreateNexusEndpointResponse"\xbc\x01\x82\xd3\xe4\x93\x02\x1b"\x16/cloud/nexus/endpoints:\x01*\x92\x41\x97\x01\n\x05Nexus\x12\x17\x43reate a Nexus endpoint\x1a>Creates a new Nexus endpoint for cross-namespace communication"5\n\x13Nexus documentation\x12\x1ehttps://docs.temporal.io/nexus\x12\xd7\x02\n\x13UpdateNexusEndpoint\x12>.temporal.api.cloud.cloudservice.v1.UpdateNexusEndpointRequest\x1a?.temporal.api.cloud.cloudservice.v1.UpdateNexusEndpointResponse"\xbe\x01\x82\xd3\xe4\x93\x02)"$/cloud/nexus/endpoints/{endpoint_id}:\x01*\x92\x41\x8b\x01\n\x05Nexus\x12\x17Update a Nexus endpoint\x1a\x32Updates an existing Nexus endpoint\'s configuration"5\n\x13Nexus documentation\x12\x1ehttps://docs.temporal.io/nexus\x12\xcb\x02\n\x13\x44\x65leteNexusEndpoint\x12>.temporal.api.cloud.cloudservice.v1.DeleteNexusEndpointRequest\x1a?.temporal.api.cloud.cloudservice.v1.DeleteNexusEndpointResponse"\xb2\x01\x82\xd3\xe4\x93\x02&*$/cloud/nexus/endpoints/{endpoint_id}\x92\x41\x82\x01\n\x05Nexus\x12\x17\x44\x65lete a Nexus endpoint\x1a)Removes a Nexus endpoint from the account"5\n\x13Nexus documentation\x12\x1ehttps://docs.temporal.io/nexus\x12\xcc\x02\n\rGetUserGroups\x12\x38.temporal.api.cloud.cloudservice.v1.GetUserGroupsRequest\x1a\x39.temporal.api.cloud.cloudservice.v1.GetUserGroupsResponse"\xc5\x01\x82\xd3\xe4\x93\x02\x14\x12\x12/cloud/user-groups\x92\x41\xa7\x01\n\x06Groups\x12\x14List all user groups\x1a\x30Returns a list of all user groups in the account"U\n\x19User groups documentation\x12\x38https://docs.temporal.io/cloud/users-account-level-roles\x12\xd0\x02\n\x0cGetUserGroup\x12\x37.temporal.api.cloud.cloudservice.v1.GetUserGroupRequest\x1a\x38.temporal.api.cloud.cloudservice.v1.GetUserGroupResponse"\xcc\x01\x82\xd3\xe4\x93\x02\x1f\x12\x1d/cloud/user-groups/{group_id}\x92\x41\xa3\x01\n\x06Groups\x12\x16Get user group details\x1a\x38Returns detailed information about a specific user group"G\n\x19User groups documentation\x12*https://docs.temporal.io/cloud/user-groups\x12\xc7\x02\n\x0f\x43reateUserGroup\x12:.temporal.api.cloud.cloudservice.v1.CreateUserGroupRequest\x1a;.temporal.api.cloud.cloudservice.v1.CreateUserGroupResponse"\xba\x01\x82\xd3\xe4\x93\x02\x17"\x12/cloud/user-groups:\x01*\x92\x41\x99\x01\n\x06Groups\x12\x13\x43reate a user group\x1a\x31\x43reates a new user group for managing permissions"G\n\x19User groups documentation\x12*https://docs.temporal.io/cloud/user-groups\x12\xcc\x02\n\x0fUpdateUserGroup\x12:.temporal.api.cloud.cloudservice.v1.UpdateUserGroupRequest\x1a;.temporal.api.cloud.cloudservice.v1.UpdateUserGroupResponse"\xbf\x01\x82\xd3\xe4\x93\x02""\x1d/cloud/user-groups/{group_id}:\x01*\x92\x41\x93\x01\n\x06Groups\x12\x13Update a user group\x1a+Updates an existing user group\'s properties"G\n\x19User groups documentation\x12*https://docs.temporal.io/cloud/user-groups\x12\xc3\x02\n\x0f\x44\x65leteUserGroup\x12:.temporal.api.cloud.cloudservice.v1.DeleteUserGroupRequest\x1a;.temporal.api.cloud.cloudservice.v1.DeleteUserGroupResponse"\xb6\x01\x82\xd3\xe4\x93\x02\x1f*\x1d/cloud/user-groups/{group_id}\x92\x41\x8d\x01\n\x06Groups\x12\x13\x44\x65lete a user group\x1a%Removes a user group from the account"G\n\x19User groups documentation\x12*https://docs.temporal.io/cloud/user-groups\x12\xad\x03\n\x1bSetUserGroupNamespaceAccess\x12\x46.temporal.api.cloud.cloudservice.v1.SetUserGroupNamespaceAccessRequest\x1aG.temporal.api.cloud.cloudservice.v1.SetUserGroupNamespaceAccessResponse"\xfc\x01\x82\xd3\xe4\x93\x02@";/cloud/namespaces/{namespace}/user-groups/{group_id}/access:\x01*\x92\x41\xb2\x01\n\x06Groups\x12\x1fSet user group namespace access\x1a>Configures a user group\'s permissions for a specific namespace"G\n\x19User groups documentation\x12*https://docs.temporal.io/cloud/user-groups\x12\xdf\x02\n\x12\x41\x64\x64UserGroupMember\x12=.temporal.api.cloud.cloudservice.v1.AddUserGroupMemberRequest\x1a>.temporal.api.cloud.cloudservice.v1.AddUserGroupMemberResponse"\xc9\x01\x82\xd3\xe4\x93\x02*"%/cloud/user-groups/{group_id}/members:\x01*\x92\x41\x95\x01\n\x06Groups\x12\x11\x41\x64\x64 user to group\x1a/Adds a user to a user group (Cloud groups only)"G\n\x19User groups documentation\x12*https://docs.temporal.io/cloud/user-groups\x12\xf8\x02\n\x15RemoveUserGroupMember\x12@.temporal.api.cloud.cloudservice.v1.RemoveUserGroupMemberRequest\x1a\x41.temporal.api.cloud.cloudservice.v1.RemoveUserGroupMemberResponse"\xd9\x01\x82\xd3\xe4\x93\x02\x30"+/cloud/user-groups/{group_id}/remove-member:\x01*\x92\x41\x9f\x01\n\x06Groups\x12\x16Remove user from group\x1a\x34Removes a user from a user group (Cloud groups only)"G\n\x19User groups documentation\x12*https://docs.temporal.io/cloud/user-groups\x12\xdf\x02\n\x13GetUserGroupMembers\x12>.temporal.api.cloud.cloudservice.v1.GetUserGroupMembersRequest\x1a?.temporal.api.cloud.cloudservice.v1.GetUserGroupMembersResponse"\xc6\x01\x82\xd3\xe4\x93\x02\'\x12%/cloud/user-groups/{group_id}/members\x92\x41\x95\x01\n\x06Groups\x12\x15List users in a group\x1a+Returns a list of all users in a user group"G\n\x19User groups documentation\x12*https://docs.temporal.io/cloud/user-groups\x12\xf5\x02\n\x14\x43reateServiceAccount\x12?.temporal.api.cloud.cloudservice.v1.CreateServiceAccountRequest\x1a@.temporal.api.cloud.cloudservice.v1.CreateServiceAccountResponse"\xd9\x01\x82\xd3\xe4\x93\x02\x1c"\x17/cloud/service-accounts:\x01*\x92\x41\xb3\x01\n\x10Service Accounts\x12\x18\x43reate a service account\x1a\x32\x43reates a new service account for automated access"Q\n\x1eService Accounts documentation\x12/https://docs.temporal.io/cloud/service-accounts\x12\x8c\x03\n\x11GetServiceAccount\x12<.temporal.api.cloud.cloudservice.v1.GetServiceAccountRequest\x1a=.temporal.api.cloud.cloudservice.v1.GetServiceAccountResponse"\xf9\x01\x82\xd3\xe4\x93\x02.\x12,/cloud/service-accounts/{service_account_id}\x92\x41\xc1\x01\n\x10Service Accounts\x12\x1bGet service account details\x1a=Returns detailed information about a specific service account"Q\n\x1eService Accounts documentation\x12/https://docs.temporal.io/cloud/service-accounts\x12\xf0\x02\n\x12GetServiceAccounts\x12=.temporal.api.cloud.cloudservice.v1.GetServiceAccountsRequest\x1a>.temporal.api.cloud.cloudservice.v1.GetServiceAccountsResponse"\xda\x01\x82\xd3\xe4\x93\x02\x19\x12\x17/cloud/service-accounts\x92\x41\xb7\x01\n\x10Service Accounts\x12\x19List all service accounts\x1a\x35Returns a list of all service accounts in the account"Q\n\x1eService Accounts documentation\x12/https://docs.temporal.io/cloud/service-accounts\x12\x88\x03\n\x14UpdateServiceAccount\x12?.temporal.api.cloud.cloudservice.v1.UpdateServiceAccountRequest\x1a@.temporal.api.cloud.cloudservice.v1.UpdateServiceAccountResponse"\xec\x01\x82\xd3\xe4\x93\x02\x31",/cloud/service-accounts/{service_account_id}:\x01*\x92\x41\xb1\x01\n\x10Service Accounts\x12\x18Update a service account\x1a\x30Updates an existing service account\'s properties"Q\n\x1eService Accounts documentation\x12/https://docs.temporal.io/cloud/service-accounts\x12\xe9\x03\n SetServiceAccountNamespaceAccess\x12K.temporal.api.cloud.cloudservice.v1.SetServiceAccountNamespaceAccessRequest\x1aL.temporal.api.cloud.cloudservice.v1.SetServiceAccountNamespaceAccessResponse"\xa9\x02\x82\xd3\xe4\x93\x02O"J/cloud/namespaces/{namespace}/service-accounts/{service_account_id}/access:\x01*\x92\x41\xd0\x01\n\x10Service Accounts\x12$Set service account namespace access\x1a\x43\x43onfigures a service account\'s permissions for a specific namespace"Q\n\x1eService Accounts documentation\x12/https://docs.temporal.io/cloud/service-accounts\x12\xff\x02\n\x14\x44\x65leteServiceAccount\x12?.temporal.api.cloud.cloudservice.v1.DeleteServiceAccountRequest\x1a@.temporal.api.cloud.cloudservice.v1.DeleteServiceAccountResponse"\xe3\x01\x82\xd3\xe4\x93\x02.*,/cloud/service-accounts/{service_account_id}\x92\x41\xab\x01\n\x10Service Accounts\x12\x18\x44\x65lete a service account\x1a*Removes a service account from the account"Q\n\x1eService Accounts documentation\x12/https://docs.temporal.io/cloud/service-accounts\x12\xcb\x01\n\x08GetUsage\x12\x33.temporal.api.cloud.cloudservice.v1.GetUsageRequest\x1a\x34.temporal.api.cloud.cloudservice.v1.GetUsageResponse"T\x82\xd3\xe4\x93\x02\x0e\x12\x0c/cloud/usage\x92\x41=\n\x07\x41\x63\x63ount\x12\x0eGet usage data\x1a Get usage data across namespacesX\x01\x12\xb0\x02\n\nGetAccount\x12\x35.temporal.api.cloud.cloudservice.v1.GetAccountRequest\x1a\x36.temporal.api.cloud.cloudservice.v1.GetAccountResponse"\xb2\x01\x82\xd3\xe4\x93\x02\x10\x12\x0e/cloud/account\x92\x41\x98\x01\n\x07\x41\x63\x63ount\x12\x13Get account details\x1a.Returns detailed information about the account"H\n\x15\x42illing documentation\x12/https://docs.temporal.io/cloud/billing-and-cost\x12\xbb\x02\n\rUpdateAccount\x12\x38.temporal.api.cloud.cloudservice.v1.UpdateAccountRequest\x1a\x39.temporal.api.cloud.cloudservice.v1.UpdateAccountResponse"\xb4\x01\x82\xd3\xe4\x93\x02\x13"\x0e/cloud/account:\x01*\x92\x41\x97\x01\n\x07\x41\x63\x63ount\x12\x16Update account details\x1a*Updates account configuration and settings"H\n\x15\x42illing documentation\x12/https://docs.temporal.io/cloud/billing-and-cost\x12\xf3\x02\n\x19\x43reateNamespaceExportSink\x12\x44.temporal.api.cloud.cloudservice.v1.CreateNamespaceExportSinkRequest\x1a\x45.temporal.api.cloud.cloudservice.v1.CreateNamespaceExportSinkResponse"\xc8\x01\x82\xd3\xe4\x93\x02/"*/cloud/namespaces/{namespace}/export-sinks:\x01*\x92\x41\x8f\x01\n\x06\x45xport\x12\x1a\x43reate history export sink\x1a*Creates a new workflow history export sink"=\n\x14\x45xport documentation\x12%https://docs.temporal.io/cloud/export\x12\x8c\x03\n\x16GetNamespaceExportSink\x12\x41.temporal.api.cloud.cloudservice.v1.GetNamespaceExportSinkRequest\x1a\x42.temporal.api.cloud.cloudservice.v1.GetNamespaceExportSinkResponse"\xea\x01\x82\xd3\xe4\x93\x02\x33\x12\x31/cloud/namespaces/{namespace}/export-sinks/{name}\x92\x41\xad\x01\n\x06\x45xport\x12\x18Get history sink details\x1aJReturns detailed information about a specific workflow history export sink"=\n\x14\x45xport documentation\x12%https://docs.temporal.io/cloud/export\x12\x82\x03\n\x17GetNamespaceExportSinks\x12\x42.temporal.api.cloud.cloudservice.v1.GetNamespaceExportSinksRequest\x1a\x43.temporal.api.cloud.cloudservice.v1.GetNamespaceExportSinksResponse"\xdd\x01\x82\xd3\xe4\x93\x02,\x12*/cloud/namespaces/{namespace}/export-sinks\x92\x41\xa7\x01\n\x06\x45xport\x12\x19List history export sinks\x1a\x43Returns a list of all workflow history export sinks for a namespace"=\n\x14\x45xport documentation\x12%https://docs.temporal.io/cloud/export\x12\x95\x03\n\x19UpdateNamespaceExportSink\x12\x44.temporal.api.cloud.cloudservice.v1.UpdateNamespaceExportSinkRequest\x1a\x45.temporal.api.cloud.cloudservice.v1.UpdateNamespaceExportSinkResponse"\xea\x01\x82\xd3\xe4\x93\x02;"6/cloud/namespaces/{namespace}/export-sinks/{spec.name}:\x01*\x92\x41\xa5\x01\n\x06\x45xport\x12\x1aUpdate history export sink\x1a@Updates an existing workflow history export sink\'s configuration"=\n\x14\x45xport documentation\x12%https://docs.temporal.io/cloud/export\x12\x84\x03\n\x19\x44\x65leteNamespaceExportSink\x12\x44.temporal.api.cloud.cloudservice.v1.DeleteNamespaceExportSinkRequest\x1a\x45.temporal.api.cloud.cloudservice.v1.DeleteNamespaceExportSinkResponse"\xd9\x01\x82\xd3\xe4\x93\x02\x33*1/cloud/namespaces/{namespace}/export-sinks/{name}\x92\x41\x9c\x01\n\x06\x45xport\x12\x1a\x44\x65lete history export sink\x1a\x37Removes a workflow history export sink from a namespace"=\n\x14\x45xport documentation\x12%https://docs.temporal.io/cloud/export\x12\xc9\x03\n\x1bValidateNamespaceExportSink\x12\x46.temporal.api.cloud.cloudservice.v1.ValidateNamespaceExportSinkRequest\x1aG.temporal.api.cloud.cloudservice.v1.ValidateNamespaceExportSinkResponse"\x98\x02\x82\xd3\xe4\x93\x02\x37"2/cloud/namespaces/{namespace}/export-sink-validate:\x01*\x92\x41\xd7\x01\n\x06\x45xport\x12*Validate history export sink configuration\x1a\x62Tests workflow history export sink configuration by delivering a test file to verify accessibility"=\n\x14\x45xport documentation\x12%https://docs.temporal.io/cloud/export\x12\xfc\x02\n\x13UpdateNamespaceTags\x12>.temporal.api.cloud.cloudservice.v1.UpdateNamespaceTagsRequest\x1a?.temporal.api.cloud.cloudservice.v1.UpdateNamespaceTagsResponse"\xe3\x01\x82\xd3\xe4\x93\x02.")/cloud/namespaces/{namespace}/update-tags:\x01*\x92\x41\xab\x01\n\nNamespaces\x12\x15Update namespace tags\x1a,Updates the tags associated with a namespace"X\n\x1bNamespace tag documentation\x12\x39https://docs.temporal.io/cloud/namespaces#tag-a-namespace\x12\xff\x02\n\x16\x43reateConnectivityRule\x12\x41.temporal.api.cloud.cloudservice.v1.CreateConnectivityRuleRequest\x1a\x42.temporal.api.cloud.cloudservice.v1.CreateConnectivityRuleResponse"\xdd\x01\x82\xd3\xe4\x93\x02\x1e"\x19/cloud/connectivity-rules:\x01*\x92\x41\xb5\x01\n\x12\x43onnectivity Rules\x12\x18\x43reate connectivity rule\x1a:Creates a new connectivity rule for network access control"I\n\x1a\x43onnectivity documentation\x12+https://docs.temporal.io/cloud/connectivity\x12\x94\x03\n\x13GetConnectivityRule\x12>.temporal.api.cloud.cloudservice.v1.GetConnectivityRuleRequest\x1a?.temporal.api.cloud.cloudservice.v1.GetConnectivityRuleResponse"\xfb\x01\x82\xd3\xe4\x93\x02\x32\x12\x30/cloud/connectivity-rules/{connectivity_rule_id}\x92\x41\xbf\x01\n\x12\x43onnectivity Rules\x12\x1dGet connectivity rule details\x1a?Returns detailed information about a specific connectivity rule"I\n\x1a\x43onnectivity documentation\x12+https://docs.temporal.io/cloud/connectivity\x12\xf6\x02\n\x14GetConnectivityRules\x12?.temporal.api.cloud.cloudservice.v1.GetConnectivityRulesRequest\x1a@.temporal.api.cloud.cloudservice.v1.GetConnectivityRulesResponse"\xda\x01\x82\xd3\xe4\x93\x02\x1b\x12\x19/cloud/connectivity-rules\x92\x41\xb5\x01\n\x12\x43onnectivity Rules\x12\x1bList all connectivity rules\x1a\x37Returns a list of all connectivity rules in the account"I\n\x1a\x43onnectivity documentation\x12+https://docs.temporal.io/cloud/connectivity\x12\x85\x03\n\x16\x44\x65leteConnectivityRule\x12\x41.temporal.api.cloud.cloudservice.v1.DeleteConnectivityRuleRequest\x1a\x42.temporal.api.cloud.cloudservice.v1.DeleteConnectivityRuleResponse"\xe3\x01\x82\xd3\xe4\x93\x02\x32*0/cloud/connectivity-rules/{connectivity_rule_id}\x92\x41\xa7\x01\n\x12\x43onnectivity Rules\x12\x18\x44\x65lete connectivity rule\x1a,Removes a connectivity rule from the account"I\n\x1a\x43onnectivity documentation\x12+https://docs.temporal.io/cloud/connectivity\x12\xe2\x02\n\x0cGetAuditLogs\x12\x37.temporal.api.cloud.cloudservice.v1.GetAuditLogsRequest\x1a\x38.temporal.api.cloud.cloudservice.v1.GetAuditLogsResponse"\xde\x01\x82\xd3\xe4\x93\x02\x13\x12\x11/cloud/audit-logs\x92\x41\xc1\x01\n\x07\x41\x63\x63ount\x12\x0eGet audit logs\x1aYReturns a paginated list of audit logs for the account, optionally filtered by time range"K\n\x1b\x41udit logging documentation\x12,https://docs.temporal.io/cloud/audit-logging\x12\xb4\x04\n\x1bValidateAccountAuditLogSink\x12\x46.temporal.api.cloud.cloudservice.v1.ValidateAccountAuditLogSinkRequest\x1aG.temporal.api.cloud.cloudservice.v1.ValidateAccountAuditLogSinkResponse"\x83\x03\x82\xd3\xe4\x93\x02#"\x1e/cloud/audit-log-sink-validate:\x01*\x92\x41\xd6\x02\n\x07\x41\x63\x63ount\x12\x17Validate audit log sink\x1a\xe4\x01Validate customer audit log sink is accessible from Temporal\'s workflow by delivering an empty file to the specified sink. The operation verifies that the sink is correctly configured, accessible and ready to receive audit logs."K\n\x1b\x41udit logging documentation\x12,https://docs.temporal.io/cloud/audit-logging\x12\xf4\x02\n\x19\x43reateAccountAuditLogSink\x12\x44.temporal.api.cloud.cloudservice.v1.CreateAccountAuditLogSinkRequest\x1a\x45.temporal.api.cloud.cloudservice.v1.CreateAccountAuditLogSinkResponse"\xc9\x01\x82\xd3\xe4\x93\x02\x1b"\x16/cloud/audit-log-sinks:\x01*\x92\x41\xa4\x01\n\x07\x41\x63\x63ount\x12\x15\x43reate audit log sink\x1a\x35\x43reates a new audit log sink for exporting audit logs"K\n\x1b\x41udit logging documentation\x12,https://docs.temporal.io/cloud/audit-logging\x12\xfb\x02\n\x16GetAccountAuditLogSink\x12\x41.temporal.api.cloud.cloudservice.v1.GetAccountAuditLogSinkRequest\x1a\x42.temporal.api.cloud.cloudservice.v1.GetAccountAuditLogSinkResponse"\xd9\x01\x82\xd3\xe4\x93\x02\x1f\x12\x1d/cloud/audit-log-sinks/{name}\x92\x41\xb0\x01\n\x07\x41\x63\x63ount\x12\x1aGet audit log sink details\x1a.temporal.api.cloud.cloudservice.v1.CreateBillingReportRequest\x1a?.temporal.api.cloud.cloudservice.v1.CreateBillingReportResponse"\xc1\x01\x82\xd3\xe4\x93\x02\x1b"\x16/cloud/billing-reports:\x01*\x92\x41\x9c\x01\n\x07\x41\x63\x63ount\x12\x17\x43reate a billing report\x1a(Creates a billing report for the account"N\n\x1c\x42illing report documentation\x12.https://docs.temporal.io/cloud/billing-reports\x12\xe6\x02\n\x10GetBillingReport\x12;.temporal.api.cloud.cloudservice.v1.GetBillingReportRequest\x1a<.temporal.api.cloud.cloudservice.v1.GetBillingReportResponse"\xd6\x01\x82\xd3\xe4\x93\x02,\x12*/cloud/billing-reports/{billing_report_id}\x92\x41\xa0\x01\n\x07\x41\x63\x63ount\x12\x14Get a billing report\x1a/Gets an existing billing report for the account"N\n\x1c\x42illing report documentation\x12.https://docs.temporal.io/cloud/billing-reportsB\x86\x15\n%io.temporal.api.cloud.cloudservice.v1B\x0cServiceProtoP\x01Z5go.temporal.io/api/cloud/cloudservice/v1;cloudservice\xaa\x02$Temporalio.Api.Cloud.CloudService.V1\xea\x02(Temporalio::Api::Cloud::CloudService::V1\x92\x41\xc2\x13\x12\xe0\r\n\x16Temporal Cloud Ops API\x12\x96\x0cProgrammatic access to manage Temporal Cloud control plane resources including namespaces, users, service accounts, and more.\n\n## Authentication\n\nAll API requests require authentication using an API Key. Include your API key in the `Authorization` header using the Bearer scheme:\n\n```\nAuthorization: Bearer YOUR_API_KEY\n```\n\nAPI keys can be created and managed through the [API Keys endpoints](#tag/API-Keys) or via the Temporal Cloud UI. For more information, see [API Keys Documentation](https://docs.temporal.io/cloud/api-keys).\n\n## Authorization\n\nThe API uses Role-Based Access Control (RBAC) to manage permissions. Each operation requires specific role-based permissions in addition to a valid API key.\n\n### Account-Level Roles\n\n- **Account Owner** - Full account administration access\n- **Account Admin** - Manage namespaces, users, and service accounts \n- **Account Developer** - Create namespaces and manage Nexus endpoints\n- **Finance Admin** - View usage and billing information\n- **Account Read** - Read-only access to account resources\n\n### Namespace-Level Roles\n\n- **Namespace Admin** - Full access to namespace configuration and data\n- **Namespace Write** - Execute workflows and modify workflow data\n- **Namespace Read** - Read-only access to namespace data\n\nNamespace-level permissions are scoped to specific namespaces. A user or service account may have different permission levels across different namespaces.\n\nFor detailed information about roles and permissions, see [Access Control Documentation](https://docs.temporal.io/cloud/users).2\x03\x31.0:\xa7\x01\n\x06x-logo\x12\x9c\x01*\x99\x01\n\x96\x01\n\x03url\x12\x8e\x01\x1a\x8b\x01https://images.ctfassets.net/0uuz8ydxyd9p/4YGUnEoCaH9SyoUDhlJkau/e1600205d17eeee3033d926ef06664a9/Temporal_LogoLockup_Horizontal_dark_1.svgj.\n\nNamespaces\x12 Manage Temporal Cloud namespacesj0\n\x05Users\x12\'Manage users and their namespace accessjF\n\x10Service Accounts\x12\x32Manage service accounts and their namespace accessj.\n\x08\x41PI Keys\x12"Manage API keys for authenticationj1\n\x06Groups\x12\'Manage user groups and group membershipj\x1f\n\x05Nexus\x12\x16Manage Nexus endpointsj\x7f\n\x11High Availability\x12jManage high availability (multi-region, multi-cloud, and same-region replication) namespace configurationsj7\n\x06\x45xport\x12-Manage workflow history export configurationsj7\n\x12\x43onnectivity Rules\x12!Manage network connectivity rulesj"\n\x07Regions\x12\x17Query available regionsj,\n\x07\x41\x63\x63ount\x12!Manage account settings and usagej*\n\nOperations\x12\x1cQuery async operation statusr>\n\x1cTemporal Cloud Documentation\x12\x1ehttps://docs.temporal.io/cloudb\x06proto3' + b'\n0temporal/api/cloud/cloudservice/v1/service.proto\x12"temporal.api.cloud.cloudservice.v1\x1a\x39temporal/api/cloud/cloudservice/v1/request_response.proto\x1a\x1cgoogle/api/annotations.proto\x1a.protoc-gen-openapiv2/options/annotations.proto2\xc2\xcb\x01\n\x0c\x43loudService\x12\xb0\x02\n\x12GetCurrentIdentity\x12=.temporal.api.cloud.cloudservice.v1.GetCurrentIdentityRequest\x1a>.temporal.api.cloud.cloudservice.v1.GetCurrentIdentityResponse"\x9a\x01\x82\xd3\xe4\x93\x02\x19\x12\x17/cloud/current-identity\x92\x41x\n\x07\x41\x63\x63ount\x12\x14Get current identity\x1aWReturns information about the currently authenticated user or service account principal\x12\xa5\x02\n\x08GetUsers\x12\x33.temporal.api.cloud.cloudservice.v1.GetUsersRequest\x1a\x34.temporal.api.cloud.cloudservice.v1.GetUsersResponse"\xad\x01\x82\xd3\xe4\x93\x02\x0e\x12\x0c/cloud/users\x92\x41\x95\x01\n\x05Users\x12\x0eList all users\x1a*Returns a list of all users in the account"E\n\x1dUser management documentation\x12$https://docs.temporal.io/cloud/users*\tlistUsers\x12\x9c\x02\n\x07GetUser\x12\x32.temporal.api.cloud.cloudservice.v1.GetUserRequest\x1a\x33.temporal.api.cloud.cloudservice.v1.GetUserResponse"\xa7\x01\x82\xd3\xe4\x93\x02\x18\x12\x16/cloud/users/{user_id}\x92\x41\x85\x01\n\x05Users\x12\x0eGet user by ID\x1a%Takes a user ID, returns user details"E\n\x1dUser management documentation\x12$https://docs.temporal.io/cloud/users\x12\xd0\x01\n\nCreateUser\x12\x35.temporal.api.cloud.cloudservice.v1.CreateUserRequest\x1a\x36.temporal.api.cloud.cloudservice.v1.CreateUserResponse"S\x82\xd3\xe4\x93\x02\x11"\x0c/cloud/users:\x01*\x92\x41\x39\n\x05Users\x12\rCreate a user\x1a!Creates a new user in the account\x12\xdb\x01\n\nUpdateUser\x12\x35.temporal.api.cloud.cloudservice.v1.UpdateUserRequest\x1a\x36.temporal.api.cloud.cloudservice.v1.UpdateUserResponse"^\x82\xd3\xe4\x93\x02\x1b"\x16/cloud/users/{user_id}:\x01*\x92\x41:\n\x05Users\x12\rUpdate a user\x1a"Updates an existing user\'s details\x12\xd5\x01\n\nDeleteUser\x12\x35.temporal.api.cloud.cloudservice.v1.DeleteUserRequest\x1a\x36.temporal.api.cloud.cloudservice.v1.DeleteUserResponse"X\x82\xd3\xe4\x93\x02\x18*\x16/cloud/users/{user_id}\x92\x41\x37\n\x05Users\x12\rDelete a user\x1a\x1fRemoves a user from the account\x12\xaa\x03\n\x16SetUserNamespaceAccess\x12\x41.temporal.api.cloud.cloudservice.v1.SetUserNamespaceAccessRequest\x1a\x42.temporal.api.cloud.cloudservice.v1.SetUserNamespaceAccessResponse"\x88\x02\x82\xd3\xe4\x93\x02\x39"4/cloud/namespaces/{namespace}/users/{user_id}/access:\x01*\x92\x41\xc5\x01\n\x05Users\x12\x19Set user namespace access\x1a\x38\x43onfigures a user\'s permissions for a specific namespace"g\n#Namespace permissions documentation\x12@https://docs.temporal.io/cloud/users-namespace-level-permissions\x12\xb1\x02\n\x11GetAsyncOperation\x12<.temporal.api.cloud.cloudservice.v1.GetAsyncOperationRequest\x1a=.temporal.api.cloud.cloudservice.v1.GetAsyncOperationResponse"\x9e\x01\x82\xd3\xe4\x93\x02(\x12&/cloud/operations/{async_operation_id}\x92\x41m\n\nOperations\x12\x1aGet async operation status\x1a\x43Returns the current status and details of an asynchronous operation\x12\xc6\x02\n\x0f\x43reateNamespace\x12:.temporal.api.cloud.cloudservice.v1.CreateNamespaceRequest\x1a;.temporal.api.cloud.cloudservice.v1.CreateNamespaceResponse"\xb9\x01\x82\xd3\xe4\x93\x02\x16"\x11/cloud/namespaces:\x01*\x92\x41\x99\x01\n\nNamespaces\x12\x12\x43reate a namespace\x1a&Creates a new namespace in the account"O\n"Namespace management documentation\x12)https://docs.temporal.io/cloud/namespaces\x12\xc7\x02\n\rGetNamespaces\x12\x38.temporal.api.cloud.cloudservice.v1.GetNamespacesRequest\x1a\x39.temporal.api.cloud.cloudservice.v1.GetNamespacesResponse"\xc0\x01\x82\xd3\xe4\x93\x02\x13\x12\x11/cloud/namespaces\x92\x41\xa3\x01\n\nNamespaces\x12\x13List all namespaces\x1a/Returns a list of all namespaces in the account"O\n"Namespace management documentation\x12)https://docs.temporal.io/cloud/namespaces\x12\xda\x02\n\x0cGetNamespace\x12\x37.temporal.api.cloud.cloudservice.v1.GetNamespaceRequest\x1a\x38.temporal.api.cloud.cloudservice.v1.GetNamespaceResponse"\xd6\x01\x82\xd3\xe4\x93\x02\x1f\x12\x1d/cloud/namespaces/{namespace}\x92\x41\xad\x01\n\nNamespaces\x12\x15Get namespace details\x1a\x37Returns detailed information about a specific namespace"O\n"Namespace management documentation\x12)https://docs.temporal.io/cloud/namespaces\x12\xdb\x02\n\x0fUpdateNamespace\x12:.temporal.api.cloud.cloudservice.v1.UpdateNamespaceRequest\x1a;.temporal.api.cloud.cloudservice.v1.UpdateNamespaceResponse"\xce\x01\x82\xd3\xe4\x93\x02""\x1d/cloud/namespaces/{namespace}:\x01*\x92\x41\xa2\x01\n\nNamespaces\x12\x12Update a namespace\x1a/Updates configuration for an existing namespace"O\n"Namespace management documentation\x12)https://docs.temporal.io/cloud/namespaces\x12\xc7\x03\n\x1bRenameCustomSearchAttribute\x12\x46.temporal.api.cloud.cloudservice.v1.RenameCustomSearchAttributeRequest\x1aG.temporal.api.cloud.cloudservice.v1.RenameCustomSearchAttributeResponse"\x96\x02\x82\xd3\xe4\x93\x02\x41".temporal.api.cloud.cloudservice.v1.AddNamespaceRegionResponse"\xf0\x01\x88\x02\x01\x82\xd3\xe4\x93\x02-"(/cloud/namespaces/{namespace}/add-region:\x01*\x92\x41\xb6\x01\n\x11High Availability\x12\x15\x41\x64\x64 namespace replica\x1a+Adds a new replica to an existing namespace"]\n)High availability namespace documentation\x12\x30https://docs.temporal.io/cloud/high-availability\x12\x9e\x03\n\x15\x44\x65leteNamespaceRegion\x12@.temporal.api.cloud.cloudservice.v1.DeleteNamespaceRegionRequest\x1a\x41.temporal.api.cloud.cloudservice.v1.DeleteNamespaceRegionResponse"\xff\x01\x88\x02\x01\x82\xd3\xe4\x93\x02\x30*./cloud/namespaces/{namespace}/regions/{region}\x92\x41\xc2\x01\n\x11High Availability\x12\x18Remove namespace replica\x1a\x34Removes a replica from a high availability namespace"]\n)High availability namespace documentation\x12\x30https://docs.temporal.io/cloud/high-availability\x12\xa3\x02\n\nGetRegions\x12\x35.temporal.api.cloud.cloudservice.v1.GetRegionsRequest\x1a\x36.temporal.api.cloud.cloudservice.v1.GetRegionsResponse"\xa5\x01\x82\xd3\xe4\x93\x02\x10\x12\x0e/cloud/regions\x92\x41\x8b\x01\n\x07Regions\x12\x10List all regions\x1a-Returns a list of all available cloud regions"?\n\x15Regions documentation\x12&https://docs.temporal.io/cloud/regions\x12\xb2\x02\n\tGetRegion\x12\x34.temporal.api.cloud.cloudservice.v1.GetRegionRequest\x1a\x35.temporal.api.cloud.cloudservice.v1.GetRegionResponse"\xb7\x01\x82\xd3\xe4\x93\x02\x19\x12\x17/cloud/regions/{region}\x92\x41\x94\x01\n\x07Regions\x12\x12Get region details\x1a\x34Returns detailed information about a specific region"?\n\x15Regions documentation\x12&https://docs.temporal.io/cloud/regions\x12\xa8\x02\n\nGetApiKeys\x12\x35.temporal.api.cloud.cloudservice.v1.GetApiKeysRequest\x1a\x36.temporal.api.cloud.cloudservice.v1.GetApiKeysResponse"\xaa\x01\x82\xd3\xe4\x93\x02\x11\x12\x0f/cloud/api-keys\x92\x41\x8f\x01\n\x08\x41PI Keys\x12\x11List all API keys\x1a-Returns a list of all API keys in the account"A\n\x16\x41PI Keys documentation\x12\'https://docs.temporal.io/cloud/api-keys\x12\xb8\x02\n\tGetApiKey\x12\x34.temporal.api.cloud.cloudservice.v1.GetApiKeyRequest\x1a\x35.temporal.api.cloud.cloudservice.v1.GetApiKeyResponse"\xbd\x01\x82\xd3\xe4\x93\x02\x1a\x12\x18/cloud/api-keys/{key_id}\x92\x41\x99\x01\n\x08\x41PI Keys\x12\x13Get API key details\x1a\x35Returns detailed information about a specific API key"A\n\x16\x41PI Keys documentation\x12\'https://docs.temporal.io/cloud/api-keys\x12\xb1\x02\n\x0c\x43reateApiKey\x12\x37.temporal.api.cloud.cloudservice.v1.CreateApiKeyRequest\x1a\x38.temporal.api.cloud.cloudservice.v1.CreateApiKeyResponse"\xad\x01\x82\xd3\xe4\x93\x02\x14"\x0f/cloud/api-keys:\x01*\x92\x41\x8f\x01\n\x08\x41PI Keys\x12\x11\x43reate an API key\x1a-Creates a new API key for programmatic access"A\n\x16\x41PI Keys documentation\x12\'https://docs.temporal.io/cloud/api-keys\x12\xb5\x02\n\x0cUpdateApiKey\x12\x37.temporal.api.cloud.cloudservice.v1.UpdateApiKeyRequest\x1a\x38.temporal.api.cloud.cloudservice.v1.UpdateApiKeyResponse"\xb1\x01\x82\xd3\xe4\x93\x02\x1d"\x18/cloud/api-keys/{key_id}:\x01*\x92\x41\x8a\x01\n\x08\x41PI Keys\x12\x11Update an API key\x1a(Updates an existing API key\'s properties"A\n\x16\x41PI Keys documentation\x12\'https://docs.temporal.io/cloud/api-keys\x12\xa8\x02\n\x0c\x44\x65leteApiKey\x12\x37.temporal.api.cloud.cloudservice.v1.DeleteApiKeyRequest\x1a\x38.temporal.api.cloud.cloudservice.v1.DeleteApiKeyResponse"\xa4\x01\x82\xd3\xe4\x93\x02\x1a*\x18/cloud/api-keys/{key_id}\x92\x41\x80\x01\n\x08\x41PI Keys\x12\x11\x44\x65lete an API key\x1a\x1eRevokes and deletes an API key"A\n\x16\x41PI Keys documentation\x12\'https://docs.temporal.io/cloud/api-keys\x12\xc3\x02\n\x11GetNexusEndpoints\x12<.temporal.api.cloud.cloudservice.v1.GetNexusEndpointsRequest\x1a=.temporal.api.cloud.cloudservice.v1.GetNexusEndpointsResponse"\xb0\x01\x82\xd3\xe4\x93\x02\x18\x12\x16/cloud/nexus/endpoints\x92\x41\x8e\x01\n\x05Nexus\x12\x18List all Nexus endpoints\x1a\x34Returns a list of all Nexus endpoints in the account"5\n\x13Nexus documentation\x12\x1ehttps://docs.temporal.io/nexus\x12\xd8\x02\n\x10GetNexusEndpoint\x12;.temporal.api.cloud.cloudservice.v1.GetNexusEndpointRequest\x1a<.temporal.api.cloud.cloudservice.v1.GetNexusEndpointResponse"\xc8\x01\x82\xd3\xe4\x93\x02&\x12$/cloud/nexus/endpoints/{endpoint_id}\x92\x41\x98\x01\n\x05Nexus\x12\x1aGet Nexus endpoint details\x1a.temporal.api.cloud.cloudservice.v1.CreateNexusEndpointRequest\x1a?.temporal.api.cloud.cloudservice.v1.CreateNexusEndpointResponse"\xbc\x01\x82\xd3\xe4\x93\x02\x1b"\x16/cloud/nexus/endpoints:\x01*\x92\x41\x97\x01\n\x05Nexus\x12\x17\x43reate a Nexus endpoint\x1a>Creates a new Nexus endpoint for cross-namespace communication"5\n\x13Nexus documentation\x12\x1ehttps://docs.temporal.io/nexus\x12\xd7\x02\n\x13UpdateNexusEndpoint\x12>.temporal.api.cloud.cloudservice.v1.UpdateNexusEndpointRequest\x1a?.temporal.api.cloud.cloudservice.v1.UpdateNexusEndpointResponse"\xbe\x01\x82\xd3\xe4\x93\x02)"$/cloud/nexus/endpoints/{endpoint_id}:\x01*\x92\x41\x8b\x01\n\x05Nexus\x12\x17Update a Nexus endpoint\x1a\x32Updates an existing Nexus endpoint\'s configuration"5\n\x13Nexus documentation\x12\x1ehttps://docs.temporal.io/nexus\x12\xcb\x02\n\x13\x44\x65leteNexusEndpoint\x12>.temporal.api.cloud.cloudservice.v1.DeleteNexusEndpointRequest\x1a?.temporal.api.cloud.cloudservice.v1.DeleteNexusEndpointResponse"\xb2\x01\x82\xd3\xe4\x93\x02&*$/cloud/nexus/endpoints/{endpoint_id}\x92\x41\x82\x01\n\x05Nexus\x12\x17\x44\x65lete a Nexus endpoint\x1a)Removes a Nexus endpoint from the account"5\n\x13Nexus documentation\x12\x1ehttps://docs.temporal.io/nexus\x12\xcc\x02\n\rGetUserGroups\x12\x38.temporal.api.cloud.cloudservice.v1.GetUserGroupsRequest\x1a\x39.temporal.api.cloud.cloudservice.v1.GetUserGroupsResponse"\xc5\x01\x82\xd3\xe4\x93\x02\x14\x12\x12/cloud/user-groups\x92\x41\xa7\x01\n\x06Groups\x12\x14List all user groups\x1a\x30Returns a list of all user groups in the account"U\n\x19User groups documentation\x12\x38https://docs.temporal.io/cloud/users-account-level-roles\x12\xd0\x02\n\x0cGetUserGroup\x12\x37.temporal.api.cloud.cloudservice.v1.GetUserGroupRequest\x1a\x38.temporal.api.cloud.cloudservice.v1.GetUserGroupResponse"\xcc\x01\x82\xd3\xe4\x93\x02\x1f\x12\x1d/cloud/user-groups/{group_id}\x92\x41\xa3\x01\n\x06Groups\x12\x16Get user group details\x1a\x38Returns detailed information about a specific user group"G\n\x19User groups documentation\x12*https://docs.temporal.io/cloud/user-groups\x12\xc7\x02\n\x0f\x43reateUserGroup\x12:.temporal.api.cloud.cloudservice.v1.CreateUserGroupRequest\x1a;.temporal.api.cloud.cloudservice.v1.CreateUserGroupResponse"\xba\x01\x82\xd3\xe4\x93\x02\x17"\x12/cloud/user-groups:\x01*\x92\x41\x99\x01\n\x06Groups\x12\x13\x43reate a user group\x1a\x31\x43reates a new user group for managing permissions"G\n\x19User groups documentation\x12*https://docs.temporal.io/cloud/user-groups\x12\xcc\x02\n\x0fUpdateUserGroup\x12:.temporal.api.cloud.cloudservice.v1.UpdateUserGroupRequest\x1a;.temporal.api.cloud.cloudservice.v1.UpdateUserGroupResponse"\xbf\x01\x82\xd3\xe4\x93\x02""\x1d/cloud/user-groups/{group_id}:\x01*\x92\x41\x93\x01\n\x06Groups\x12\x13Update a user group\x1a+Updates an existing user group\'s properties"G\n\x19User groups documentation\x12*https://docs.temporal.io/cloud/user-groups\x12\xc3\x02\n\x0f\x44\x65leteUserGroup\x12:.temporal.api.cloud.cloudservice.v1.DeleteUserGroupRequest\x1a;.temporal.api.cloud.cloudservice.v1.DeleteUserGroupResponse"\xb6\x01\x82\xd3\xe4\x93\x02\x1f*\x1d/cloud/user-groups/{group_id}\x92\x41\x8d\x01\n\x06Groups\x12\x13\x44\x65lete a user group\x1a%Removes a user group from the account"G\n\x19User groups documentation\x12*https://docs.temporal.io/cloud/user-groups\x12\xad\x03\n\x1bSetUserGroupNamespaceAccess\x12\x46.temporal.api.cloud.cloudservice.v1.SetUserGroupNamespaceAccessRequest\x1aG.temporal.api.cloud.cloudservice.v1.SetUserGroupNamespaceAccessResponse"\xfc\x01\x82\xd3\xe4\x93\x02@";/cloud/namespaces/{namespace}/user-groups/{group_id}/access:\x01*\x92\x41\xb2\x01\n\x06Groups\x12\x1fSet user group namespace access\x1a>Configures a user group\'s permissions for a specific namespace"G\n\x19User groups documentation\x12*https://docs.temporal.io/cloud/user-groups\x12\xdf\x02\n\x12\x41\x64\x64UserGroupMember\x12=.temporal.api.cloud.cloudservice.v1.AddUserGroupMemberRequest\x1a>.temporal.api.cloud.cloudservice.v1.AddUserGroupMemberResponse"\xc9\x01\x82\xd3\xe4\x93\x02*"%/cloud/user-groups/{group_id}/members:\x01*\x92\x41\x95\x01\n\x06Groups\x12\x11\x41\x64\x64 user to group\x1a/Adds a user to a user group (Cloud groups only)"G\n\x19User groups documentation\x12*https://docs.temporal.io/cloud/user-groups\x12\xf8\x02\n\x15RemoveUserGroupMember\x12@.temporal.api.cloud.cloudservice.v1.RemoveUserGroupMemberRequest\x1a\x41.temporal.api.cloud.cloudservice.v1.RemoveUserGroupMemberResponse"\xd9\x01\x82\xd3\xe4\x93\x02\x30"+/cloud/user-groups/{group_id}/remove-member:\x01*\x92\x41\x9f\x01\n\x06Groups\x12\x16Remove user from group\x1a\x34Removes a user from a user group (Cloud groups only)"G\n\x19User groups documentation\x12*https://docs.temporal.io/cloud/user-groups\x12\xdf\x02\n\x13GetUserGroupMembers\x12>.temporal.api.cloud.cloudservice.v1.GetUserGroupMembersRequest\x1a?.temporal.api.cloud.cloudservice.v1.GetUserGroupMembersResponse"\xc6\x01\x82\xd3\xe4\x93\x02\'\x12%/cloud/user-groups/{group_id}/members\x92\x41\x95\x01\n\x06Groups\x12\x15List users in a group\x1a+Returns a list of all users in a user group"G\n\x19User groups documentation\x12*https://docs.temporal.io/cloud/user-groups\x12\xf5\x02\n\x14\x43reateServiceAccount\x12?.temporal.api.cloud.cloudservice.v1.CreateServiceAccountRequest\x1a@.temporal.api.cloud.cloudservice.v1.CreateServiceAccountResponse"\xd9\x01\x82\xd3\xe4\x93\x02\x1c"\x17/cloud/service-accounts:\x01*\x92\x41\xb3\x01\n\x10Service Accounts\x12\x18\x43reate a service account\x1a\x32\x43reates a new service account for automated access"Q\n\x1eService Accounts documentation\x12/https://docs.temporal.io/cloud/service-accounts\x12\x8c\x03\n\x11GetServiceAccount\x12<.temporal.api.cloud.cloudservice.v1.GetServiceAccountRequest\x1a=.temporal.api.cloud.cloudservice.v1.GetServiceAccountResponse"\xf9\x01\x82\xd3\xe4\x93\x02.\x12,/cloud/service-accounts/{service_account_id}\x92\x41\xc1\x01\n\x10Service Accounts\x12\x1bGet service account details\x1a=Returns detailed information about a specific service account"Q\n\x1eService Accounts documentation\x12/https://docs.temporal.io/cloud/service-accounts\x12\xf0\x02\n\x12GetServiceAccounts\x12=.temporal.api.cloud.cloudservice.v1.GetServiceAccountsRequest\x1a>.temporal.api.cloud.cloudservice.v1.GetServiceAccountsResponse"\xda\x01\x82\xd3\xe4\x93\x02\x19\x12\x17/cloud/service-accounts\x92\x41\xb7\x01\n\x10Service Accounts\x12\x19List all service accounts\x1a\x35Returns a list of all service accounts in the account"Q\n\x1eService Accounts documentation\x12/https://docs.temporal.io/cloud/service-accounts\x12\x88\x03\n\x14UpdateServiceAccount\x12?.temporal.api.cloud.cloudservice.v1.UpdateServiceAccountRequest\x1a@.temporal.api.cloud.cloudservice.v1.UpdateServiceAccountResponse"\xec\x01\x82\xd3\xe4\x93\x02\x31",/cloud/service-accounts/{service_account_id}:\x01*\x92\x41\xb1\x01\n\x10Service Accounts\x12\x18Update a service account\x1a\x30Updates an existing service account\'s properties"Q\n\x1eService Accounts documentation\x12/https://docs.temporal.io/cloud/service-accounts\x12\xe9\x03\n SetServiceAccountNamespaceAccess\x12K.temporal.api.cloud.cloudservice.v1.SetServiceAccountNamespaceAccessRequest\x1aL.temporal.api.cloud.cloudservice.v1.SetServiceAccountNamespaceAccessResponse"\xa9\x02\x82\xd3\xe4\x93\x02O"J/cloud/namespaces/{namespace}/service-accounts/{service_account_id}/access:\x01*\x92\x41\xd0\x01\n\x10Service Accounts\x12$Set service account namespace access\x1a\x43\x43onfigures a service account\'s permissions for a specific namespace"Q\n\x1eService Accounts documentation\x12/https://docs.temporal.io/cloud/service-accounts\x12\xff\x02\n\x14\x44\x65leteServiceAccount\x12?.temporal.api.cloud.cloudservice.v1.DeleteServiceAccountRequest\x1a@.temporal.api.cloud.cloudservice.v1.DeleteServiceAccountResponse"\xe3\x01\x82\xd3\xe4\x93\x02.*,/cloud/service-accounts/{service_account_id}\x92\x41\xab\x01\n\x10Service Accounts\x12\x18\x44\x65lete a service account\x1a*Removes a service account from the account"Q\n\x1eService Accounts documentation\x12/https://docs.temporal.io/cloud/service-accounts\x12\xcb\x01\n\x08GetUsage\x12\x33.temporal.api.cloud.cloudservice.v1.GetUsageRequest\x1a\x34.temporal.api.cloud.cloudservice.v1.GetUsageResponse"T\x82\xd3\xe4\x93\x02\x0e\x12\x0c/cloud/usage\x92\x41=\n\x07\x41\x63\x63ount\x12\x0eGet usage data\x1a Get usage data across namespacesX\x01\x12\xb0\x02\n\nGetAccount\x12\x35.temporal.api.cloud.cloudservice.v1.GetAccountRequest\x1a\x36.temporal.api.cloud.cloudservice.v1.GetAccountResponse"\xb2\x01\x82\xd3\xe4\x93\x02\x10\x12\x0e/cloud/account\x92\x41\x98\x01\n\x07\x41\x63\x63ount\x12\x13Get account details\x1a.Returns detailed information about the account"H\n\x15\x42illing documentation\x12/https://docs.temporal.io/cloud/billing-and-cost\x12\xbb\x02\n\rUpdateAccount\x12\x38.temporal.api.cloud.cloudservice.v1.UpdateAccountRequest\x1a\x39.temporal.api.cloud.cloudservice.v1.UpdateAccountResponse"\xb4\x01\x82\xd3\xe4\x93\x02\x13"\x0e/cloud/account:\x01*\x92\x41\x97\x01\n\x07\x41\x63\x63ount\x12\x16Update account details\x1a*Updates account configuration and settings"H\n\x15\x42illing documentation\x12/https://docs.temporal.io/cloud/billing-and-cost\x12\xf3\x02\n\x19\x43reateNamespaceExportSink\x12\x44.temporal.api.cloud.cloudservice.v1.CreateNamespaceExportSinkRequest\x1a\x45.temporal.api.cloud.cloudservice.v1.CreateNamespaceExportSinkResponse"\xc8\x01\x82\xd3\xe4\x93\x02/"*/cloud/namespaces/{namespace}/export-sinks:\x01*\x92\x41\x8f\x01\n\x06\x45xport\x12\x1a\x43reate history export sink\x1a*Creates a new workflow history export sink"=\n\x14\x45xport documentation\x12%https://docs.temporal.io/cloud/export\x12\x8c\x03\n\x16GetNamespaceExportSink\x12\x41.temporal.api.cloud.cloudservice.v1.GetNamespaceExportSinkRequest\x1a\x42.temporal.api.cloud.cloudservice.v1.GetNamespaceExportSinkResponse"\xea\x01\x82\xd3\xe4\x93\x02\x33\x12\x31/cloud/namespaces/{namespace}/export-sinks/{name}\x92\x41\xad\x01\n\x06\x45xport\x12\x18Get history sink details\x1aJReturns detailed information about a specific workflow history export sink"=\n\x14\x45xport documentation\x12%https://docs.temporal.io/cloud/export\x12\x82\x03\n\x17GetNamespaceExportSinks\x12\x42.temporal.api.cloud.cloudservice.v1.GetNamespaceExportSinksRequest\x1a\x43.temporal.api.cloud.cloudservice.v1.GetNamespaceExportSinksResponse"\xdd\x01\x82\xd3\xe4\x93\x02,\x12*/cloud/namespaces/{namespace}/export-sinks\x92\x41\xa7\x01\n\x06\x45xport\x12\x19List history export sinks\x1a\x43Returns a list of all workflow history export sinks for a namespace"=\n\x14\x45xport documentation\x12%https://docs.temporal.io/cloud/export\x12\x95\x03\n\x19UpdateNamespaceExportSink\x12\x44.temporal.api.cloud.cloudservice.v1.UpdateNamespaceExportSinkRequest\x1a\x45.temporal.api.cloud.cloudservice.v1.UpdateNamespaceExportSinkResponse"\xea\x01\x82\xd3\xe4\x93\x02;"6/cloud/namespaces/{namespace}/export-sinks/{spec.name}:\x01*\x92\x41\xa5\x01\n\x06\x45xport\x12\x1aUpdate history export sink\x1a@Updates an existing workflow history export sink\'s configuration"=\n\x14\x45xport documentation\x12%https://docs.temporal.io/cloud/export\x12\x84\x03\n\x19\x44\x65leteNamespaceExportSink\x12\x44.temporal.api.cloud.cloudservice.v1.DeleteNamespaceExportSinkRequest\x1a\x45.temporal.api.cloud.cloudservice.v1.DeleteNamespaceExportSinkResponse"\xd9\x01\x82\xd3\xe4\x93\x02\x33*1/cloud/namespaces/{namespace}/export-sinks/{name}\x92\x41\x9c\x01\n\x06\x45xport\x12\x1a\x44\x65lete history export sink\x1a\x37Removes a workflow history export sink from a namespace"=\n\x14\x45xport documentation\x12%https://docs.temporal.io/cloud/export\x12\xc9\x03\n\x1bValidateNamespaceExportSink\x12\x46.temporal.api.cloud.cloudservice.v1.ValidateNamespaceExportSinkRequest\x1aG.temporal.api.cloud.cloudservice.v1.ValidateNamespaceExportSinkResponse"\x98\x02\x82\xd3\xe4\x93\x02\x37"2/cloud/namespaces/{namespace}/export-sink-validate:\x01*\x92\x41\xd7\x01\n\x06\x45xport\x12*Validate history export sink configuration\x1a\x62Tests workflow history export sink configuration by delivering a test file to verify accessibility"=\n\x14\x45xport documentation\x12%https://docs.temporal.io/cloud/export\x12\xfc\x02\n\x13UpdateNamespaceTags\x12>.temporal.api.cloud.cloudservice.v1.UpdateNamespaceTagsRequest\x1a?.temporal.api.cloud.cloudservice.v1.UpdateNamespaceTagsResponse"\xe3\x01\x82\xd3\xe4\x93\x02.")/cloud/namespaces/{namespace}/update-tags:\x01*\x92\x41\xab\x01\n\nNamespaces\x12\x15Update namespace tags\x1a,Updates the tags associated with a namespace"X\n\x1bNamespace tag documentation\x12\x39https://docs.temporal.io/cloud/namespaces#tag-a-namespace\x12\xff\x02\n\x16\x43reateConnectivityRule\x12\x41.temporal.api.cloud.cloudservice.v1.CreateConnectivityRuleRequest\x1a\x42.temporal.api.cloud.cloudservice.v1.CreateConnectivityRuleResponse"\xdd\x01\x82\xd3\xe4\x93\x02\x1e"\x19/cloud/connectivity-rules:\x01*\x92\x41\xb5\x01\n\x12\x43onnectivity Rules\x12\x18\x43reate connectivity rule\x1a:Creates a new connectivity rule for network access control"I\n\x1a\x43onnectivity documentation\x12+https://docs.temporal.io/cloud/connectivity\x12\x94\x03\n\x13GetConnectivityRule\x12>.temporal.api.cloud.cloudservice.v1.GetConnectivityRuleRequest\x1a?.temporal.api.cloud.cloudservice.v1.GetConnectivityRuleResponse"\xfb\x01\x82\xd3\xe4\x93\x02\x32\x12\x30/cloud/connectivity-rules/{connectivity_rule_id}\x92\x41\xbf\x01\n\x12\x43onnectivity Rules\x12\x1dGet connectivity rule details\x1a?Returns detailed information about a specific connectivity rule"I\n\x1a\x43onnectivity documentation\x12+https://docs.temporal.io/cloud/connectivity\x12\xf6\x02\n\x14GetConnectivityRules\x12?.temporal.api.cloud.cloudservice.v1.GetConnectivityRulesRequest\x1a@.temporal.api.cloud.cloudservice.v1.GetConnectivityRulesResponse"\xda\x01\x82\xd3\xe4\x93\x02\x1b\x12\x19/cloud/connectivity-rules\x92\x41\xb5\x01\n\x12\x43onnectivity Rules\x12\x1bList all connectivity rules\x1a\x37Returns a list of all connectivity rules in the account"I\n\x1a\x43onnectivity documentation\x12+https://docs.temporal.io/cloud/connectivity\x12\x85\x03\n\x16\x44\x65leteConnectivityRule\x12\x41.temporal.api.cloud.cloudservice.v1.DeleteConnectivityRuleRequest\x1a\x42.temporal.api.cloud.cloudservice.v1.DeleteConnectivityRuleResponse"\xe3\x01\x82\xd3\xe4\x93\x02\x32*0/cloud/connectivity-rules/{connectivity_rule_id}\x92\x41\xa7\x01\n\x12\x43onnectivity Rules\x12\x18\x44\x65lete connectivity rule\x1a,Removes a connectivity rule from the account"I\n\x1a\x43onnectivity documentation\x12+https://docs.temporal.io/cloud/connectivity\x12\xe2\x02\n\x0cGetAuditLogs\x12\x37.temporal.api.cloud.cloudservice.v1.GetAuditLogsRequest\x1a\x38.temporal.api.cloud.cloudservice.v1.GetAuditLogsResponse"\xde\x01\x82\xd3\xe4\x93\x02\x13\x12\x11/cloud/audit-logs\x92\x41\xc1\x01\n\x07\x41\x63\x63ount\x12\x0eGet audit logs\x1aYReturns a paginated list of audit logs for the account, optionally filtered by time range"K\n\x1b\x41udit logging documentation\x12,https://docs.temporal.io/cloud/audit-logging\x12\xb4\x04\n\x1bValidateAccountAuditLogSink\x12\x46.temporal.api.cloud.cloudservice.v1.ValidateAccountAuditLogSinkRequest\x1aG.temporal.api.cloud.cloudservice.v1.ValidateAccountAuditLogSinkResponse"\x83\x03\x82\xd3\xe4\x93\x02#"\x1e/cloud/audit-log-sink-validate:\x01*\x92\x41\xd6\x02\n\x07\x41\x63\x63ount\x12\x17Validate audit log sink\x1a\xe4\x01Validate customer audit log sink is accessible from Temporal\'s workflow by delivering an empty file to the specified sink. The operation verifies that the sink is correctly configured, accessible and ready to receive audit logs."K\n\x1b\x41udit logging documentation\x12,https://docs.temporal.io/cloud/audit-logging\x12\xf4\x02\n\x19\x43reateAccountAuditLogSink\x12\x44.temporal.api.cloud.cloudservice.v1.CreateAccountAuditLogSinkRequest\x1a\x45.temporal.api.cloud.cloudservice.v1.CreateAccountAuditLogSinkResponse"\xc9\x01\x82\xd3\xe4\x93\x02\x1b"\x16/cloud/audit-log-sinks:\x01*\x92\x41\xa4\x01\n\x07\x41\x63\x63ount\x12\x15\x43reate audit log sink\x1a\x35\x43reates a new audit log sink for exporting audit logs"K\n\x1b\x41udit logging documentation\x12,https://docs.temporal.io/cloud/audit-logging\x12\xfb\x02\n\x16GetAccountAuditLogSink\x12\x41.temporal.api.cloud.cloudservice.v1.GetAccountAuditLogSinkRequest\x1a\x42.temporal.api.cloud.cloudservice.v1.GetAccountAuditLogSinkResponse"\xd9\x01\x82\xd3\xe4\x93\x02\x1f\x12\x1d/cloud/audit-log-sinks/{name}\x92\x41\xb0\x01\n\x07\x41\x63\x63ount\x12\x1aGet audit log sink details\x1a.temporal.api.cloud.cloudservice.v1.CreateBillingReportRequest\x1a?.temporal.api.cloud.cloudservice.v1.CreateBillingReportResponse"\xc1\x01\x82\xd3\xe4\x93\x02\x1b"\x16/cloud/billing-reports:\x01*\x92\x41\x9c\x01\n\x07\x41\x63\x63ount\x12\x17\x43reate a billing report\x1a(Creates a billing report for the account"N\n\x1c\x42illing report documentation\x12.https://docs.temporal.io/cloud/billing-reports\x12\xe6\x02\n\x10GetBillingReport\x12;.temporal.api.cloud.cloudservice.v1.GetBillingReportRequest\x1a<.temporal.api.cloud.cloudservice.v1.GetBillingReportResponse"\xd6\x01\x82\xd3\xe4\x93\x02,\x12*/cloud/billing-reports/{billing_report_id}\x92\x41\xa0\x01\n\x07\x41\x63\x63ount\x12\x14Get a billing report\x1a/Gets an existing billing report for the account"N\n\x1c\x42illing report documentation\x12.https://docs.temporal.io/cloud/billing-reports\x12\xc4\x02\n\x0eGetCustomRoles\x12\x39.temporal.api.cloud.cloudservice.v1.GetCustomRolesRequest\x1a:.temporal.api.cloud.cloudservice.v1.GetCustomRolesResponse"\xba\x01\x82\xd3\xe4\x93\x02\x15\x12\x13/cloud/custom-roles\x92\x41\x9b\x01\n\x0c\x43ustom Roles\x12\x11List custom roles\x1a-Returns a list of custom roles in the account"I\n\x1a\x43ustom roles documentation\x12+https://docs.temporal.io/cloud/custom-roles\x12\xcc\x02\n\rGetCustomRole\x12\x38.temporal.api.cloud.cloudservice.v1.GetCustomRoleRequest\x1a\x39.temporal.api.cloud.cloudservice.v1.GetCustomRoleResponse"\xc5\x01\x82\xd3\xe4\x93\x02\x1f\x12\x1d/cloud/custom-roles/{role_id}\x92\x41\x9c\x01\n\x0c\x43ustom Roles\x12\x15Get custom role by ID\x1a*Returns details for a specific custom role"I\n\x1a\x43ustom roles documentation\x12+https://docs.temporal.io/cloud/custom-roles\x12\xcb\x02\n\x10\x43reateCustomRole\x12;.temporal.api.cloud.cloudservice.v1.CreateCustomRoleRequest\x1a<.temporal.api.cloud.cloudservice.v1.CreateCustomRoleResponse"\xbb\x01\x82\xd3\xe4\x93\x02\x18"\x13/cloud/custom-roles:\x01*\x92\x41\x99\x01\n\x0c\x43ustom Roles\x12\x14\x43reate a custom role\x1a(Creates a new custom role in the account"I\n\x1a\x43ustom roles documentation\x12+https://docs.temporal.io/cloud/custom-roles\x12\xcc\x02\n\x10UpdateCustomRole\x12;.temporal.api.cloud.cloudservice.v1.UpdateCustomRoleRequest\x1a<.temporal.api.cloud.cloudservice.v1.UpdateCustomRoleResponse"\xbc\x01\x82\xd3\xe4\x93\x02""\x1d/cloud/custom-roles/{role_id}:\x01*\x92\x41\x90\x01\n\x0c\x43ustom Roles\x12\x14Update a custom role\x1a\x1fUpdates an existing custom role"I\n\x1a\x43ustom roles documentation\x12+https://docs.temporal.io/cloud/custom-roles\x12\xd0\x02\n\x10\x44\x65leteCustomRole\x12;.temporal.api.cloud.cloudservice.v1.DeleteCustomRoleRequest\x1a<.temporal.api.cloud.cloudservice.v1.DeleteCustomRoleResponse"\xc0\x01\x82\xd3\xe4\x93\x02\x1f*\x1d/cloud/custom-roles/{role_id}\x92\x41\x97\x01\n\x0c\x43ustom Roles\x12\x14\x44\x65lete a custom role\x1a&Deletes a custom role from the account"I\n\x1a\x43ustom roles documentation\x12+https://docs.temporal.io/cloud/custom-rolesB\xc1\x15\n%io.temporal.api.cloud.cloudservice.v1B\x0cServiceProtoP\x01Z5go.temporal.io/api/cloud/cloudservice/v1;cloudservice\xaa\x02$Temporalio.Api.Cloud.CloudService.V1\xea\x02(Temporalio::Api::Cloud::CloudService::V1\x92\x41\xfd\x13\x12\xe0\r\n\x16Temporal Cloud Ops API\x12\x96\x0cProgrammatic access to manage Temporal Cloud control plane resources including namespaces, users, service accounts, and more.\n\n## Authentication\n\nAll API requests require authentication using an API Key. Include your API key in the `Authorization` header using the Bearer scheme:\n\n```\nAuthorization: Bearer YOUR_API_KEY\n```\n\nAPI keys can be created and managed through the [API Keys endpoints](#tag/API-Keys) or via the Temporal Cloud UI. For more information, see [API Keys Documentation](https://docs.temporal.io/cloud/api-keys).\n\n## Authorization\n\nThe API uses Role-Based Access Control (RBAC) to manage permissions. Each operation requires specific role-based permissions in addition to a valid API key.\n\n### Account-Level Roles\n\n- **Account Owner** - Full account administration access\n- **Account Admin** - Manage namespaces, users, and service accounts \n- **Account Developer** - Create namespaces and manage Nexus endpoints\n- **Finance Admin** - View usage and billing information\n- **Account Read** - Read-only access to account resources\n\n### Namespace-Level Roles\n\n- **Namespace Admin** - Full access to namespace configuration and data\n- **Namespace Write** - Execute workflows and modify workflow data\n- **Namespace Read** - Read-only access to namespace data\n\nNamespace-level permissions are scoped to specific namespaces. A user or service account may have different permission levels across different namespaces.\n\nFor detailed information about roles and permissions, see [Access Control Documentation](https://docs.temporal.io/cloud/users).2\x03\x31.0:\xa7\x01\n\x06x-logo\x12\x9c\x01*\x99\x01\n\x96\x01\n\x03url\x12\x8e\x01\x1a\x8b\x01https://images.ctfassets.net/0uuz8ydxyd9p/4YGUnEoCaH9SyoUDhlJkau/e1600205d17eeee3033d926ef06664a9/Temporal_LogoLockup_Horizontal_dark_1.svgj.\n\nNamespaces\x12 Manage Temporal Cloud namespacesj0\n\x05Users\x12\'Manage users and their namespace accessjF\n\x10Service Accounts\x12\x32Manage service accounts and their namespace accessj.\n\x08\x41PI Keys\x12"Manage API keys for authenticationj1\n\x06Groups\x12\'Manage user groups and group membershipj\x1f\n\x05Nexus\x12\x16Manage Nexus endpointsj\x7f\n\x11High Availability\x12jManage high availability (multi-region, multi-cloud, and same-region replication) namespace configurationsj7\n\x06\x45xport\x12-Manage workflow history export configurationsj7\n\x12\x43onnectivity Rules\x12!Manage network connectivity rulesj"\n\x07Regions\x12\x17Query available regionsj,\n\x07\x41\x63\x63ount\x12!Manage account settings and usagej9\n\x0c\x43ustom Roles\x12)Manage custom roles and their permissionsj*\n\nOperations\x12\x1cQuery async operation statusr>\n\x1cTemporal Cloud Documentation\x12\x1ehttps://docs.temporal.io/cloudb\x06proto3' ) _CLOUDSERVICE = DESCRIPTOR.services_by_name["CloudService"] if _descriptor._USE_C_DESCRIPTORS == False: DESCRIPTOR._options = None - DESCRIPTOR._serialized_options = b"\n%io.temporal.api.cloud.cloudservice.v1B\014ServiceProtoP\001Z5go.temporal.io/api/cloud/cloudservice/v1;cloudservice\252\002$Temporalio.Api.Cloud.CloudService.V1\352\002(Temporalio::Api::Cloud::CloudService::V1\222A\302\023\022\340\r\n\026Temporal Cloud Ops API\022\226\014Programmatic access to manage Temporal Cloud control plane resources including namespaces, users, service accounts, and more.\n\n## Authentication\n\nAll API requests require authentication using an API Key. Include your API key in the `Authorization` header using the Bearer scheme:\n\n```\nAuthorization: Bearer YOUR_API_KEY\n```\n\nAPI keys can be created and managed through the [API Keys endpoints](#tag/API-Keys) or via the Temporal Cloud UI. For more information, see [API Keys Documentation](https://docs.temporal.io/cloud/api-keys).\n\n## Authorization\n\nThe API uses Role-Based Access Control (RBAC) to manage permissions. Each operation requires specific role-based permissions in addition to a valid API key.\n\n### Account-Level Roles\n\n- **Account Owner** - Full account administration access\n- **Account Admin** - Manage namespaces, users, and service accounts \n- **Account Developer** - Create namespaces and manage Nexus endpoints\n- **Finance Admin** - View usage and billing information\n- **Account Read** - Read-only access to account resources\n\n### Namespace-Level Roles\n\n- **Namespace Admin** - Full access to namespace configuration and data\n- **Namespace Write** - Execute workflows and modify workflow data\n- **Namespace Read** - Read-only access to namespace data\n\nNamespace-level permissions are scoped to specific namespaces. A user or service account may have different permission levels across different namespaces.\n\nFor detailed information about roles and permissions, see [Access Control Documentation](https://docs.temporal.io/cloud/users).2\0031.0:\247\001\n\006x-logo\022\234\001*\231\001\n\226\001\n\003url\022\216\001\032\213\001https://images.ctfassets.net/0uuz8ydxyd9p/4YGUnEoCaH9SyoUDhlJkau/e1600205d17eeee3033d926ef06664a9/Temporal_LogoLockup_Horizontal_dark_1.svgj.\n\nNamespaces\022 Manage Temporal Cloud namespacesj0\n\005Users\022'Manage users and their namespace accessjF\n\020Service Accounts\0222Manage service accounts and their namespace accessj.\n\010API Keys\022\"Manage API keys for authenticationj1\n\006Groups\022'Manage user groups and group membershipj\037\n\005Nexus\022\026Manage Nexus endpointsj\177\n\021High Availability\022jManage high availability (multi-region, multi-cloud, and same-region replication) namespace configurationsj7\n\006Export\022-Manage workflow history export configurationsj7\n\022Connectivity Rules\022!Manage network connectivity rulesj\"\n\007Regions\022\027Query available regionsj,\n\007Account\022!Manage account settings and usagej*\n\nOperations\022\034Query async operation statusr>\n\034Temporal Cloud Documentation\022\036https://docs.temporal.io/cloud" + DESCRIPTOR._serialized_options = b"\n%io.temporal.api.cloud.cloudservice.v1B\014ServiceProtoP\001Z5go.temporal.io/api/cloud/cloudservice/v1;cloudservice\252\002$Temporalio.Api.Cloud.CloudService.V1\352\002(Temporalio::Api::Cloud::CloudService::V1\222A\375\023\022\340\r\n\026Temporal Cloud Ops API\022\226\014Programmatic access to manage Temporal Cloud control plane resources including namespaces, users, service accounts, and more.\n\n## Authentication\n\nAll API requests require authentication using an API Key. Include your API key in the `Authorization` header using the Bearer scheme:\n\n```\nAuthorization: Bearer YOUR_API_KEY\n```\n\nAPI keys can be created and managed through the [API Keys endpoints](#tag/API-Keys) or via the Temporal Cloud UI. For more information, see [API Keys Documentation](https://docs.temporal.io/cloud/api-keys).\n\n## Authorization\n\nThe API uses Role-Based Access Control (RBAC) to manage permissions. Each operation requires specific role-based permissions in addition to a valid API key.\n\n### Account-Level Roles\n\n- **Account Owner** - Full account administration access\n- **Account Admin** - Manage namespaces, users, and service accounts \n- **Account Developer** - Create namespaces and manage Nexus endpoints\n- **Finance Admin** - View usage and billing information\n- **Account Read** - Read-only access to account resources\n\n### Namespace-Level Roles\n\n- **Namespace Admin** - Full access to namespace configuration and data\n- **Namespace Write** - Execute workflows and modify workflow data\n- **Namespace Read** - Read-only access to namespace data\n\nNamespace-level permissions are scoped to specific namespaces. A user or service account may have different permission levels across different namespaces.\n\nFor detailed information about roles and permissions, see [Access Control Documentation](https://docs.temporal.io/cloud/users).2\0031.0:\247\001\n\006x-logo\022\234\001*\231\001\n\226\001\n\003url\022\216\001\032\213\001https://images.ctfassets.net/0uuz8ydxyd9p/4YGUnEoCaH9SyoUDhlJkau/e1600205d17eeee3033d926ef06664a9/Temporal_LogoLockup_Horizontal_dark_1.svgj.\n\nNamespaces\022 Manage Temporal Cloud namespacesj0\n\005Users\022'Manage users and their namespace accessjF\n\020Service Accounts\0222Manage service accounts and their namespace accessj.\n\010API Keys\022\"Manage API keys for authenticationj1\n\006Groups\022'Manage user groups and group membershipj\037\n\005Nexus\022\026Manage Nexus endpointsj\177\n\021High Availability\022jManage high availability (multi-region, multi-cloud, and same-region replication) namespace configurationsj7\n\006Export\022-Manage workflow history export configurationsj7\n\022Connectivity Rules\022!Manage network connectivity rulesj\"\n\007Regions\022\027Query available regionsj,\n\007Account\022!Manage account settings and usagej9\n\014Custom Roles\022)Manage custom roles and their permissionsj*\n\nOperations\022\034Query async operation statusr>\n\034Temporal Cloud Documentation\022\036https://docs.temporal.io/cloud" _CLOUDSERVICE.methods_by_name["GetCurrentIdentity"]._options = None _CLOUDSERVICE.methods_by_name[ "GetCurrentIdentity" @@ -95,11 +95,11 @@ _CLOUDSERVICE.methods_by_name["AddNamespaceRegion"]._options = None _CLOUDSERVICE.methods_by_name[ "AddNamespaceRegion" - ]._serialized_options = b'\202\323\344\223\002-"(/cloud/namespaces/{namespace}/add-region:\001*\222A\266\001\n\021High Availability\022\025Add namespace replica\032+Adds a new replica to an existing namespace"]\n)High availability namespace documentation\0220https://docs.temporal.io/cloud/high-availability' + ]._serialized_options = b'\210\002\001\202\323\344\223\002-"(/cloud/namespaces/{namespace}/add-region:\001*\222A\266\001\n\021High Availability\022\025Add namespace replica\032+Adds a new replica to an existing namespace"]\n)High availability namespace documentation\0220https://docs.temporal.io/cloud/high-availability' _CLOUDSERVICE.methods_by_name["DeleteNamespaceRegion"]._options = None _CLOUDSERVICE.methods_by_name[ "DeleteNamespaceRegion" - ]._serialized_options = b'\202\323\344\223\0020*./cloud/namespaces/{namespace}/regions/{region}\222A\302\001\n\021High Availability\022\030Remove namespace replica\0324Removes a replica from a high availability namespace"]\n)High availability namespace documentation\0220https://docs.temporal.io/cloud/high-availability' + ]._serialized_options = b'\210\002\001\202\323\344\223\0020*./cloud/namespaces/{namespace}/regions/{region}\222A\302\001\n\021High Availability\022\030Remove namespace replica\0324Removes a replica from a high availability namespace"]\n)High availability namespace documentation\0220https://docs.temporal.io/cloud/high-availability' _CLOUDSERVICE.methods_by_name["GetRegions"]._options = None _CLOUDSERVICE.methods_by_name[ "GetRegions" @@ -304,6 +304,26 @@ _CLOUDSERVICE.methods_by_name[ "GetBillingReport" ]._serialized_options = b'\202\323\344\223\002,\022*/cloud/billing-reports/{billing_report_id}\222A\240\001\n\007Account\022\024Get a billing report\032/Gets an existing billing report for the account"N\n\034Billing report documentation\022.https://docs.temporal.io/cloud/billing-reports' + _CLOUDSERVICE.methods_by_name["GetCustomRoles"]._options = None + _CLOUDSERVICE.methods_by_name[ + "GetCustomRoles" + ]._serialized_options = b'\202\323\344\223\002\025\022\023/cloud/custom-roles\222A\233\001\n\014Custom Roles\022\021List custom roles\032-Returns a list of custom roles in the account"I\n\032Custom roles documentation\022+https://docs.temporal.io/cloud/custom-roles' + _CLOUDSERVICE.methods_by_name["GetCustomRole"]._options = None + _CLOUDSERVICE.methods_by_name[ + "GetCustomRole" + ]._serialized_options = b'\202\323\344\223\002\037\022\035/cloud/custom-roles/{role_id}\222A\234\001\n\014Custom Roles\022\025Get custom role by ID\032*Returns details for a specific custom role"I\n\032Custom roles documentation\022+https://docs.temporal.io/cloud/custom-roles' + _CLOUDSERVICE.methods_by_name["CreateCustomRole"]._options = None + _CLOUDSERVICE.methods_by_name[ + "CreateCustomRole" + ]._serialized_options = b'\202\323\344\223\002\030"\023/cloud/custom-roles:\001*\222A\231\001\n\014Custom Roles\022\024Create a custom role\032(Creates a new custom role in the account"I\n\032Custom roles documentation\022+https://docs.temporal.io/cloud/custom-roles' + _CLOUDSERVICE.methods_by_name["UpdateCustomRole"]._options = None + _CLOUDSERVICE.methods_by_name[ + "UpdateCustomRole" + ]._serialized_options = b'\202\323\344\223\002""\035/cloud/custom-roles/{role_id}:\001*\222A\220\001\n\014Custom Roles\022\024Update a custom role\032\037Updates an existing custom role"I\n\032Custom roles documentation\022+https://docs.temporal.io/cloud/custom-roles' + _CLOUDSERVICE.methods_by_name["DeleteCustomRole"]._options = None + _CLOUDSERVICE.methods_by_name[ + "DeleteCustomRole" + ]._serialized_options = b'\202\323\344\223\002\037*\035/cloud/custom-roles/{role_id}\222A\227\001\n\014Custom Roles\022\024Delete a custom role\032&Deletes a custom role from the account"I\n\032Custom roles documentation\022+https://docs.temporal.io/cloud/custom-roles' _CLOUDSERVICE._serialized_start = 227 - _CLOUDSERVICE._serialized_end = 24601 + _CLOUDSERVICE._serialized_end = 26277 # @@protoc_insertion_point(module_scope) diff --git a/temporalio/api/cloud/cloudservice/v1/service_pb2_grpc.py b/temporalio/api/cloud/cloudservice/v1/service_pb2_grpc.py index cf2755c84..4888d7186 100644 --- a/temporalio/api/cloud/cloudservice/v1/service_pb2_grpc.py +++ b/temporalio/api/cloud/cloudservice/v1/service_pb2_grpc.py @@ -359,6 +359,31 @@ def __init__(self, channel): request_serializer=temporal_dot_api_dot_cloud_dot_cloudservice_dot_v1_dot_request__response__pb2.GetBillingReportRequest.SerializeToString, response_deserializer=temporal_dot_api_dot_cloud_dot_cloudservice_dot_v1_dot_request__response__pb2.GetBillingReportResponse.FromString, ) + self.GetCustomRoles = channel.unary_unary( + "/temporal.api.cloud.cloudservice.v1.CloudService/GetCustomRoles", + request_serializer=temporal_dot_api_dot_cloud_dot_cloudservice_dot_v1_dot_request__response__pb2.GetCustomRolesRequest.SerializeToString, + response_deserializer=temporal_dot_api_dot_cloud_dot_cloudservice_dot_v1_dot_request__response__pb2.GetCustomRolesResponse.FromString, + ) + self.GetCustomRole = channel.unary_unary( + "/temporal.api.cloud.cloudservice.v1.CloudService/GetCustomRole", + request_serializer=temporal_dot_api_dot_cloud_dot_cloudservice_dot_v1_dot_request__response__pb2.GetCustomRoleRequest.SerializeToString, + response_deserializer=temporal_dot_api_dot_cloud_dot_cloudservice_dot_v1_dot_request__response__pb2.GetCustomRoleResponse.FromString, + ) + self.CreateCustomRole = channel.unary_unary( + "/temporal.api.cloud.cloudservice.v1.CloudService/CreateCustomRole", + request_serializer=temporal_dot_api_dot_cloud_dot_cloudservice_dot_v1_dot_request__response__pb2.CreateCustomRoleRequest.SerializeToString, + response_deserializer=temporal_dot_api_dot_cloud_dot_cloudservice_dot_v1_dot_request__response__pb2.CreateCustomRoleResponse.FromString, + ) + self.UpdateCustomRole = channel.unary_unary( + "/temporal.api.cloud.cloudservice.v1.CloudService/UpdateCustomRole", + request_serializer=temporal_dot_api_dot_cloud_dot_cloudservice_dot_v1_dot_request__response__pb2.UpdateCustomRoleRequest.SerializeToString, + response_deserializer=temporal_dot_api_dot_cloud_dot_cloudservice_dot_v1_dot_request__response__pb2.UpdateCustomRoleResponse.FromString, + ) + self.DeleteCustomRole = channel.unary_unary( + "/temporal.api.cloud.cloudservice.v1.CloudService/DeleteCustomRole", + request_serializer=temporal_dot_api_dot_cloud_dot_cloudservice_dot_v1_dot_request__response__pb2.DeleteCustomRoleRequest.SerializeToString, + response_deserializer=temporal_dot_api_dot_cloud_dot_cloudservice_dot_v1_dot_request__response__pb2.DeleteCustomRoleResponse.FromString, + ) class CloudServiceServicer(object): @@ -457,13 +482,17 @@ def FailoverNamespaceRegion(self, request, context): raise NotImplementedError("Method not implemented!") def AddNamespaceRegion(self, request, context): - """Add a new region to a namespace""" + """Add a new region to a namespace + Deprecated: Use the UpdateNamespace() to add new replica in the namespace spec instead. + """ context.set_code(grpc.StatusCode.UNIMPLEMENTED) context.set_details("Method not implemented!") raise NotImplementedError("Method not implemented!") def DeleteNamespaceRegion(self, request, context): - """Delete a region from a namespace""" + """Delete a region from a namespace + Deprecated: Use the UpdateNamespace() to delete a replica in the namespace spec instead. + """ context.set_code(grpc.StatusCode.UNIMPLEMENTED) context.set_details("Method not implemented!") raise NotImplementedError("Method not implemented!") @@ -780,6 +809,36 @@ def GetBillingReport(self, request, context): context.set_details("Method not implemented!") raise NotImplementedError("Method not implemented!") + def GetCustomRoles(self, request, context): + """Get custom roles""" + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details("Method not implemented!") + raise NotImplementedError("Method not implemented!") + + def GetCustomRole(self, request, context): + """Get a custom role""" + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details("Method not implemented!") + raise NotImplementedError("Method not implemented!") + + def CreateCustomRole(self, request, context): + """Create a custom role""" + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details("Method not implemented!") + raise NotImplementedError("Method not implemented!") + + def UpdateCustomRole(self, request, context): + """Update a custom role""" + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details("Method not implemented!") + raise NotImplementedError("Method not implemented!") + + def DeleteCustomRole(self, request, context): + """Delete a custom role""" + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details("Method not implemented!") + raise NotImplementedError("Method not implemented!") + def add_CloudServiceServicer_to_server(servicer, server): rpc_method_handlers = { @@ -1123,6 +1182,31 @@ def add_CloudServiceServicer_to_server(servicer, server): request_deserializer=temporal_dot_api_dot_cloud_dot_cloudservice_dot_v1_dot_request__response__pb2.GetBillingReportRequest.FromString, response_serializer=temporal_dot_api_dot_cloud_dot_cloudservice_dot_v1_dot_request__response__pb2.GetBillingReportResponse.SerializeToString, ), + "GetCustomRoles": grpc.unary_unary_rpc_method_handler( + servicer.GetCustomRoles, + request_deserializer=temporal_dot_api_dot_cloud_dot_cloudservice_dot_v1_dot_request__response__pb2.GetCustomRolesRequest.FromString, + response_serializer=temporal_dot_api_dot_cloud_dot_cloudservice_dot_v1_dot_request__response__pb2.GetCustomRolesResponse.SerializeToString, + ), + "GetCustomRole": grpc.unary_unary_rpc_method_handler( + servicer.GetCustomRole, + request_deserializer=temporal_dot_api_dot_cloud_dot_cloudservice_dot_v1_dot_request__response__pb2.GetCustomRoleRequest.FromString, + response_serializer=temporal_dot_api_dot_cloud_dot_cloudservice_dot_v1_dot_request__response__pb2.GetCustomRoleResponse.SerializeToString, + ), + "CreateCustomRole": grpc.unary_unary_rpc_method_handler( + servicer.CreateCustomRole, + request_deserializer=temporal_dot_api_dot_cloud_dot_cloudservice_dot_v1_dot_request__response__pb2.CreateCustomRoleRequest.FromString, + response_serializer=temporal_dot_api_dot_cloud_dot_cloudservice_dot_v1_dot_request__response__pb2.CreateCustomRoleResponse.SerializeToString, + ), + "UpdateCustomRole": grpc.unary_unary_rpc_method_handler( + servicer.UpdateCustomRole, + request_deserializer=temporal_dot_api_dot_cloud_dot_cloudservice_dot_v1_dot_request__response__pb2.UpdateCustomRoleRequest.FromString, + response_serializer=temporal_dot_api_dot_cloud_dot_cloudservice_dot_v1_dot_request__response__pb2.UpdateCustomRoleResponse.SerializeToString, + ), + "DeleteCustomRole": grpc.unary_unary_rpc_method_handler( + servicer.DeleteCustomRole, + request_deserializer=temporal_dot_api_dot_cloud_dot_cloudservice_dot_v1_dot_request__response__pb2.DeleteCustomRoleRequest.FromString, + response_serializer=temporal_dot_api_dot_cloud_dot_cloudservice_dot_v1_dot_request__response__pb2.DeleteCustomRoleResponse.SerializeToString, + ), } generic_handler = grpc.method_handlers_generic_handler( "temporal.api.cloud.cloudservice.v1.CloudService", rpc_method_handlers @@ -3107,3 +3191,148 @@ def GetBillingReport( timeout, metadata, ) + + @staticmethod + def GetCustomRoles( + request, + target, + options=(), + channel_credentials=None, + call_credentials=None, + insecure=False, + compression=None, + wait_for_ready=None, + timeout=None, + metadata=None, + ): + return grpc.experimental.unary_unary( + request, + target, + "/temporal.api.cloud.cloudservice.v1.CloudService/GetCustomRoles", + temporal_dot_api_dot_cloud_dot_cloudservice_dot_v1_dot_request__response__pb2.GetCustomRolesRequest.SerializeToString, + temporal_dot_api_dot_cloud_dot_cloudservice_dot_v1_dot_request__response__pb2.GetCustomRolesResponse.FromString, + options, + channel_credentials, + insecure, + call_credentials, + compression, + wait_for_ready, + timeout, + metadata, + ) + + @staticmethod + def GetCustomRole( + request, + target, + options=(), + channel_credentials=None, + call_credentials=None, + insecure=False, + compression=None, + wait_for_ready=None, + timeout=None, + metadata=None, + ): + return grpc.experimental.unary_unary( + request, + target, + "/temporal.api.cloud.cloudservice.v1.CloudService/GetCustomRole", + temporal_dot_api_dot_cloud_dot_cloudservice_dot_v1_dot_request__response__pb2.GetCustomRoleRequest.SerializeToString, + temporal_dot_api_dot_cloud_dot_cloudservice_dot_v1_dot_request__response__pb2.GetCustomRoleResponse.FromString, + options, + channel_credentials, + insecure, + call_credentials, + compression, + wait_for_ready, + timeout, + metadata, + ) + + @staticmethod + def CreateCustomRole( + request, + target, + options=(), + channel_credentials=None, + call_credentials=None, + insecure=False, + compression=None, + wait_for_ready=None, + timeout=None, + metadata=None, + ): + return grpc.experimental.unary_unary( + request, + target, + "/temporal.api.cloud.cloudservice.v1.CloudService/CreateCustomRole", + temporal_dot_api_dot_cloud_dot_cloudservice_dot_v1_dot_request__response__pb2.CreateCustomRoleRequest.SerializeToString, + temporal_dot_api_dot_cloud_dot_cloudservice_dot_v1_dot_request__response__pb2.CreateCustomRoleResponse.FromString, + options, + channel_credentials, + insecure, + call_credentials, + compression, + wait_for_ready, + timeout, + metadata, + ) + + @staticmethod + def UpdateCustomRole( + request, + target, + options=(), + channel_credentials=None, + call_credentials=None, + insecure=False, + compression=None, + wait_for_ready=None, + timeout=None, + metadata=None, + ): + return grpc.experimental.unary_unary( + request, + target, + "/temporal.api.cloud.cloudservice.v1.CloudService/UpdateCustomRole", + temporal_dot_api_dot_cloud_dot_cloudservice_dot_v1_dot_request__response__pb2.UpdateCustomRoleRequest.SerializeToString, + temporal_dot_api_dot_cloud_dot_cloudservice_dot_v1_dot_request__response__pb2.UpdateCustomRoleResponse.FromString, + options, + channel_credentials, + insecure, + call_credentials, + compression, + wait_for_ready, + timeout, + metadata, + ) + + @staticmethod + def DeleteCustomRole( + request, + target, + options=(), + channel_credentials=None, + call_credentials=None, + insecure=False, + compression=None, + wait_for_ready=None, + timeout=None, + metadata=None, + ): + return grpc.experimental.unary_unary( + request, + target, + "/temporal.api.cloud.cloudservice.v1.CloudService/DeleteCustomRole", + temporal_dot_api_dot_cloud_dot_cloudservice_dot_v1_dot_request__response__pb2.DeleteCustomRoleRequest.SerializeToString, + temporal_dot_api_dot_cloud_dot_cloudservice_dot_v1_dot_request__response__pb2.DeleteCustomRoleResponse.FromString, + options, + channel_credentials, + insecure, + call_credentials, + compression, + wait_for_ready, + timeout, + metadata, + ) diff --git a/temporalio/api/cloud/cloudservice/v1/service_pb2_grpc.pyi b/temporalio/api/cloud/cloudservice/v1/service_pb2_grpc.pyi index 5cd60b88a..0d8e642f4 100644 --- a/temporalio/api/cloud/cloudservice/v1/service_pb2_grpc.pyi +++ b/temporalio/api/cloud/cloudservice/v1/service_pb2_grpc.pyi @@ -94,12 +94,16 @@ class CloudServiceStub: temporalio.api.cloud.cloudservice.v1.request_response_pb2.AddNamespaceRegionRequest, temporalio.api.cloud.cloudservice.v1.request_response_pb2.AddNamespaceRegionResponse, ] - """Add a new region to a namespace""" + """Add a new region to a namespace + Deprecated: Use the UpdateNamespace() to add new replica in the namespace spec instead. + """ DeleteNamespaceRegion: grpc.UnaryUnaryMultiCallable[ temporalio.api.cloud.cloudservice.v1.request_response_pb2.DeleteNamespaceRegionRequest, temporalio.api.cloud.cloudservice.v1.request_response_pb2.DeleteNamespaceRegionResponse, ] - """Delete a region from a namespace""" + """Delete a region from a namespace + Deprecated: Use the UpdateNamespace() to delete a replica in the namespace spec instead. + """ GetRegions: grpc.UnaryUnaryMultiCallable[ temporalio.api.cloud.cloudservice.v1.request_response_pb2.GetRegionsRequest, temporalio.api.cloud.cloudservice.v1.request_response_pb2.GetRegionsResponse, @@ -360,6 +364,31 @@ class CloudServiceStub: temporalio.api.cloud.cloudservice.v1.request_response_pb2.GetBillingReportResponse, ] """Get a billing report""" + GetCustomRoles: grpc.UnaryUnaryMultiCallable[ + temporalio.api.cloud.cloudservice.v1.request_response_pb2.GetCustomRolesRequest, + temporalio.api.cloud.cloudservice.v1.request_response_pb2.GetCustomRolesResponse, + ] + """Get custom roles""" + GetCustomRole: grpc.UnaryUnaryMultiCallable[ + temporalio.api.cloud.cloudservice.v1.request_response_pb2.GetCustomRoleRequest, + temporalio.api.cloud.cloudservice.v1.request_response_pb2.GetCustomRoleResponse, + ] + """Get a custom role""" + CreateCustomRole: grpc.UnaryUnaryMultiCallable[ + temporalio.api.cloud.cloudservice.v1.request_response_pb2.CreateCustomRoleRequest, + temporalio.api.cloud.cloudservice.v1.request_response_pb2.CreateCustomRoleResponse, + ] + """Create a custom role""" + UpdateCustomRole: grpc.UnaryUnaryMultiCallable[ + temporalio.api.cloud.cloudservice.v1.request_response_pb2.UpdateCustomRoleRequest, + temporalio.api.cloud.cloudservice.v1.request_response_pb2.UpdateCustomRoleResponse, + ] + """Update a custom role""" + DeleteCustomRole: grpc.UnaryUnaryMultiCallable[ + temporalio.api.cloud.cloudservice.v1.request_response_pb2.DeleteCustomRoleRequest, + temporalio.api.cloud.cloudservice.v1.request_response_pb2.DeleteCustomRoleResponse, + ] + """Delete a custom role""" class CloudServiceServicer(metaclass=abc.ABCMeta): """WARNING: This service is currently experimental and may change in @@ -479,14 +508,18 @@ class CloudServiceServicer(metaclass=abc.ABCMeta): request: temporalio.api.cloud.cloudservice.v1.request_response_pb2.AddNamespaceRegionRequest, context: grpc.ServicerContext, ) -> temporalio.api.cloud.cloudservice.v1.request_response_pb2.AddNamespaceRegionResponse: - """Add a new region to a namespace""" + """Add a new region to a namespace + Deprecated: Use the UpdateNamespace() to add new replica in the namespace spec instead. + """ @abc.abstractmethod def DeleteNamespaceRegion( self, request: temporalio.api.cloud.cloudservice.v1.request_response_pb2.DeleteNamespaceRegionRequest, context: grpc.ServicerContext, ) -> temporalio.api.cloud.cloudservice.v1.request_response_pb2.DeleteNamespaceRegionResponse: - """Delete a region from a namespace""" + """Delete a region from a namespace + Deprecated: Use the UpdateNamespace() to delete a replica in the namespace spec instead. + """ @abc.abstractmethod def GetRegions( self, @@ -853,6 +886,45 @@ class CloudServiceServicer(metaclass=abc.ABCMeta): context: grpc.ServicerContext, ) -> temporalio.api.cloud.cloudservice.v1.request_response_pb2.GetBillingReportResponse: """Get a billing report""" + @abc.abstractmethod + def GetCustomRoles( + self, + request: temporalio.api.cloud.cloudservice.v1.request_response_pb2.GetCustomRolesRequest, + context: grpc.ServicerContext, + ) -> ( + temporalio.api.cloud.cloudservice.v1.request_response_pb2.GetCustomRolesResponse + ): + """Get custom roles""" + @abc.abstractmethod + def GetCustomRole( + self, + request: temporalio.api.cloud.cloudservice.v1.request_response_pb2.GetCustomRoleRequest, + context: grpc.ServicerContext, + ) -> ( + temporalio.api.cloud.cloudservice.v1.request_response_pb2.GetCustomRoleResponse + ): + """Get a custom role""" + @abc.abstractmethod + def CreateCustomRole( + self, + request: temporalio.api.cloud.cloudservice.v1.request_response_pb2.CreateCustomRoleRequest, + context: grpc.ServicerContext, + ) -> temporalio.api.cloud.cloudservice.v1.request_response_pb2.CreateCustomRoleResponse: + """Create a custom role""" + @abc.abstractmethod + def UpdateCustomRole( + self, + request: temporalio.api.cloud.cloudservice.v1.request_response_pb2.UpdateCustomRoleRequest, + context: grpc.ServicerContext, + ) -> temporalio.api.cloud.cloudservice.v1.request_response_pb2.UpdateCustomRoleResponse: + """Update a custom role""" + @abc.abstractmethod + def DeleteCustomRole( + self, + request: temporalio.api.cloud.cloudservice.v1.request_response_pb2.DeleteCustomRoleRequest, + context: grpc.ServicerContext, + ) -> temporalio.api.cloud.cloudservice.v1.request_response_pb2.DeleteCustomRoleResponse: + """Delete a custom role""" def add_CloudServiceServicer_to_server( servicer: CloudServiceServicer, server: grpc.Server diff --git a/temporalio/api/cloud/connectivityrule/v1/message_pb2.py b/temporalio/api/cloud/connectivityrule/v1/message_pb2.py index 6737fdcae..2d39aec83 100644 --- a/temporalio/api/cloud/connectivityrule/v1/message_pb2.py +++ b/temporalio/api/cloud/connectivityrule/v1/message_pb2.py @@ -21,7 +21,7 @@ ) DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile( - b'\n4temporal/api/cloud/connectivityrule/v1/message.proto\x12&temporal.api.cloud.connectivityrule.v1\x1a,temporal/api/cloud/resource/v1/message.proto\x1a\x1fgoogle/protobuf/timestamp.proto"\x96\x02\n\x10\x43onnectivityRule\x12\n\n\x02id\x18\x01 \x01(\t\x12J\n\x04spec\x18\x02 \x01(\x0b\x32<.temporal.api.cloud.connectivityrule.v1.ConnectivityRuleSpec\x12\x18\n\x10resource_version\x18\x04 \x01(\t\x12<\n\x05state\x18\x05 \x01(\x0e\x32-.temporal.api.cloud.resource.v1.ResourceState\x12\x1a\n\x12\x61sync_operation_id\x18\x06 \x01(\t\x12\x30\n\x0c\x63reated_time\x18\x07 \x01(\x0b\x32\x1a.google.protobuf.TimestampJ\x04\x08\x03\x10\x04"\xd9\x01\n\x14\x43onnectivityRuleSpec\x12U\n\x0bpublic_rule\x18\x01 \x01(\x0b\x32>.temporal.api.cloud.connectivityrule.v1.PublicConnectivityRuleH\x00\x12W\n\x0cprivate_rule\x18\x02 \x01(\x0b\x32?.temporal.api.cloud.connectivityrule.v1.PrivateConnectivityRuleH\x00\x42\x11\n\x0f\x63onnection_type"\x18\n\x16PublicConnectivityRule"^\n\x17PrivateConnectivityRule\x12\x15\n\rconnection_id\x18\x01 \x01(\t\x12\x16\n\x0egcp_project_id\x18\x02 \x01(\t\x12\x0e\n\x06region\x18\x03 \x01(\tJ\x04\x08\x04\x10\x05\x42\xd4\x01\n)io.temporal.api.cloud.connectivityrule.v1B\x0cMessageProtoP\x01Z=go.temporal.io/api/cloud/connectivityrule/v1;connectivityrule\xaa\x02(Temporalio.Api.Cloud.ConnectivityRule.V1\xea\x02,Temporalio::Api::Cloud::ConnectivityRule::V1b\x06proto3' + b'\n4temporal/api/cloud/connectivityrule/v1/message.proto\x12&temporal.api.cloud.connectivityrule.v1\x1a,temporal/api/cloud/resource/v1/message.proto\x1a\x1fgoogle/protobuf/timestamp.proto"\x96\x02\n\x10\x43onnectivityRule\x12\n\n\x02id\x18\x01 \x01(\t\x12J\n\x04spec\x18\x02 \x01(\x0b\x32<.temporal.api.cloud.connectivityrule.v1.ConnectivityRuleSpec\x12\x18\n\x10resource_version\x18\x04 \x01(\t\x12<\n\x05state\x18\x05 \x01(\x0e\x32-.temporal.api.cloud.resource.v1.ResourceState\x12\x1a\n\x12\x61sync_operation_id\x18\x06 \x01(\t\x12\x30\n\x0c\x63reated_time\x18\x07 \x01(\x0b\x32\x1a.google.protobuf.TimestampJ\x04\x08\x03\x10\x04"\xd9\x01\n\x14\x43onnectivityRuleSpec\x12U\n\x0bpublic_rule\x18\x01 \x01(\x0b\x32>.temporal.api.cloud.connectivityrule.v1.PublicConnectivityRuleH\x00\x12W\n\x0cprivate_rule\x18\x02 \x01(\x0b\x32?.temporal.api.cloud.connectivityrule.v1.PrivateConnectivityRuleH\x00\x42\x11\n\x0f\x63onnection_type"3\n\x16PublicConnectivityRule\x12\x19\n\x11\x65nable_stable_ips\x18\x01 \x01(\x08"^\n\x17PrivateConnectivityRule\x12\x15\n\rconnection_id\x18\x01 \x01(\t\x12\x16\n\x0egcp_project_id\x18\x02 \x01(\t\x12\x0e\n\x06region\x18\x03 \x01(\tJ\x04\x08\x04\x10\x05\x42\xd4\x01\n)io.temporal.api.cloud.connectivityrule.v1B\x0cMessageProtoP\x01Z=go.temporal.io/api/cloud/connectivityrule/v1;connectivityrule\xaa\x02(Temporalio.Api.Cloud.ConnectivityRule.V1\xea\x02,Temporalio::Api::Cloud::ConnectivityRule::V1b\x06proto3' ) @@ -81,7 +81,7 @@ _CONNECTIVITYRULESPEC._serialized_start = 457 _CONNECTIVITYRULESPEC._serialized_end = 674 _PUBLICCONNECTIVITYRULE._serialized_start = 676 - _PUBLICCONNECTIVITYRULE._serialized_end = 700 - _PRIVATECONNECTIVITYRULE._serialized_start = 702 - _PRIVATECONNECTIVITYRULE._serialized_end = 796 + _PUBLICCONNECTIVITYRULE._serialized_end = 727 + _PRIVATECONNECTIVITYRULE._serialized_start = 729 + _PRIVATECONNECTIVITYRULE._serialized_end = 823 # @@protoc_insertion_point(module_scope) diff --git a/temporalio/api/cloud/connectivityrule/v1/message_pb2.pyi b/temporalio/api/cloud/connectivityrule/v1/message_pb2.pyi index 06d8850d4..629704d6f 100644 --- a/temporalio/api/cloud/connectivityrule/v1/message_pb2.pyi +++ b/temporalio/api/cloud/connectivityrule/v1/message_pb2.pyi @@ -132,8 +132,21 @@ class PublicConnectivityRule(google.protobuf.message.Message): DESCRIPTOR: google.protobuf.descriptor.Descriptor + ENABLE_STABLE_IPS_FIELD_NUMBER: builtins.int + enable_stable_ips: builtins.bool + """Flag to determine namespace is connected via a predictable set of IPs on public internet + temporal:versioning:min_version=v0.15.0 + """ def __init__( self, + *, + enable_stable_ips: builtins.bool = ..., + ) -> None: ... + def ClearField( + self, + field_name: typing_extensions.Literal[ + "enable_stable_ips", b"enable_stable_ips" + ], ) -> None: ... global___PublicConnectivityRule = PublicConnectivityRule diff --git a/temporalio/api/cloud/identity/v1/__init__.py b/temporalio/api/cloud/identity/v1/__init__.py index 6b477fbef..38954f384 100644 --- a/temporalio/api/cloud/identity/v1/__init__.py +++ b/temporalio/api/cloud/identity/v1/__init__.py @@ -4,6 +4,8 @@ ApiKey, ApiKeySpec, CloudGroupSpec, + CustomRole, + CustomRoleSpec, GoogleGroupSpec, Invitation, NamespaceAccess, @@ -26,6 +28,8 @@ "ApiKey", "ApiKeySpec", "CloudGroupSpec", + "CustomRole", + "CustomRoleSpec", "GoogleGroupSpec", "Invitation", "NamespaceAccess", diff --git a/temporalio/api/cloud/identity/v1/message_pb2.py b/temporalio/api/cloud/identity/v1/message_pb2.py index 892468506..b7036cd3f 100644 --- a/temporalio/api/cloud/identity/v1/message_pb2.py +++ b/temporalio/api/cloud/identity/v1/message_pb2.py @@ -22,7 +22,7 @@ ) DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile( - b'\n,temporal/api/cloud/identity/v1/message.proto\x12\x1etemporal.api.cloud.identity.v1\x1a,temporal/api/cloud/resource/v1/message.proto\x1a\x1fgoogle/protobuf/timestamp.proto"\xff\x01\n\rAccountAccess\x12\x1b\n\x0frole_deprecated\x18\x01 \x01(\tB\x02\x18\x01\x12@\n\x04role\x18\x02 \x01(\x0e\x32\x32.temporal.api.cloud.identity.v1.AccountAccess.Role"\x8e\x01\n\x04Role\x12\x14\n\x10ROLE_UNSPECIFIED\x10\x00\x12\x0e\n\nROLE_OWNER\x10\x01\x12\x0e\n\nROLE_ADMIN\x10\x02\x12\x12\n\x0eROLE_DEVELOPER\x10\x03\x12\x16\n\x12ROLE_FINANCE_ADMIN\x10\x04\x12\r\n\tROLE_READ\x10\x05\x12\x15\n\x11ROLE_METRICS_READ\x10\x06"\xef\x01\n\x0fNamespaceAccess\x12!\n\x15permission_deprecated\x18\x01 \x01(\tB\x02\x18\x01\x12N\n\npermission\x18\x02 \x01(\x0e\x32:.temporal.api.cloud.identity.v1.NamespaceAccess.Permission"i\n\nPermission\x12\x1a\n\x16PERMISSION_UNSPECIFIED\x10\x00\x12\x14\n\x10PERMISSION_ADMIN\x10\x01\x12\x14\n\x10PERMISSION_WRITE\x10\x02\x12\x13\n\x0fPERMISSION_READ\x10\x03"\x95\x02\n\x06\x41\x63\x63\x65ss\x12\x45\n\x0e\x61\x63\x63ount_access\x18\x01 \x01(\x0b\x32-.temporal.api.cloud.identity.v1.AccountAccess\x12Y\n\x12namespace_accesses\x18\x02 \x03(\x0b\x32=.temporal.api.cloud.identity.v1.Access.NamespaceAccessesEntry\x1ai\n\x16NamespaceAccessesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12>\n\x05value\x18\x02 \x01(\x0b\x32/.temporal.api.cloud.identity.v1.NamespaceAccess:\x02\x38\x01"k\n\x15NamespaceScopedAccess\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12?\n\x06\x61\x63\x63\x65ss\x18\x02 \x01(\x0b\x32/.temporal.api.cloud.identity.v1.NamespaceAccess"Q\n\x08UserSpec\x12\r\n\x05\x65mail\x18\x01 \x01(\t\x12\x36\n\x06\x61\x63\x63\x65ss\x18\x02 \x01(\x0b\x32&.temporal.api.cloud.identity.v1.Access"p\n\nInvitation\x12\x30\n\x0c\x63reated_time\x18\x01 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x30\n\x0c\x65xpired_time\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.Timestamp"\x86\x03\n\x04User\x12\n\n\x02id\x18\x01 \x01(\t\x12\x18\n\x10resource_version\x18\x02 \x01(\t\x12\x36\n\x04spec\x18\x03 \x01(\x0b\x32(.temporal.api.cloud.identity.v1.UserSpec\x12\x1c\n\x10state_deprecated\x18\x04 \x01(\tB\x02\x18\x01\x12<\n\x05state\x18\t \x01(\x0e\x32-.temporal.api.cloud.resource.v1.ResourceState\x12\x1a\n\x12\x61sync_operation_id\x18\x05 \x01(\t\x12>\n\ninvitation\x18\x06 \x01(\x0b\x32*.temporal.api.cloud.identity.v1.Invitation\x12\x30\n\x0c\x63reated_time\x18\x07 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x36\n\x12last_modified_time\x18\x08 \x01(\x0b\x32\x1a.google.protobuf.Timestamp"(\n\x0fGoogleGroupSpec\x12\x15\n\remail_address\x18\x01 \x01(\t"\x1f\n\rSCIMGroupSpec\x12\x0e\n\x06idp_id\x18\x01 \x01(\t"\x10\n\x0e\x43loudGroupSpec"\xc0\x02\n\rUserGroupSpec\x12\x14\n\x0c\x64isplay_name\x18\x01 \x01(\t\x12\x36\n\x06\x61\x63\x63\x65ss\x18\x02 \x01(\x0b\x32&.temporal.api.cloud.identity.v1.Access\x12G\n\x0cgoogle_group\x18\x03 \x01(\x0b\x32/.temporal.api.cloud.identity.v1.GoogleGroupSpecH\x00\x12\x43\n\nscim_group\x18\x04 \x01(\x0b\x32-.temporal.api.cloud.identity.v1.SCIMGroupSpecH\x00\x12\x45\n\x0b\x63loud_group\x18\x05 \x01(\x0b\x32..temporal.api.cloud.identity.v1.CloudGroupSpecH\x00\x42\x0c\n\ngroup_type"\xd0\x02\n\tUserGroup\x12\n\n\x02id\x18\x01 \x01(\t\x12\x18\n\x10resource_version\x18\x02 \x01(\t\x12;\n\x04spec\x18\x03 \x01(\x0b\x32-.temporal.api.cloud.identity.v1.UserGroupSpec\x12\x1c\n\x10state_deprecated\x18\x04 \x01(\tB\x02\x18\x01\x12<\n\x05state\x18\x08 \x01(\x0e\x32-.temporal.api.cloud.resource.v1.ResourceState\x12\x1a\n\x12\x61sync_operation_id\x18\x05 \x01(\t\x12\x30\n\x0c\x63reated_time\x18\x06 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x36\n\x12last_modified_time\x18\x07 \x01(\x0b\x32\x1a.google.protobuf.Timestamp"5\n\x11UserGroupMemberId\x12\x11\n\x07user_id\x18\x01 \x01(\tH\x00\x42\r\n\x0bmember_type"\x89\x01\n\x0fUserGroupMember\x12\x44\n\tmember_id\x18\x01 \x01(\x0b\x32\x31.temporal.api.cloud.identity.v1.UserGroupMemberId\x12\x30\n\x0c\x63reated_time\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.Timestamp"\xda\x02\n\x0eServiceAccount\x12\n\n\x02id\x18\x01 \x01(\t\x12\x18\n\x10resource_version\x18\x02 \x01(\t\x12@\n\x04spec\x18\x03 \x01(\x0b\x32\x32.temporal.api.cloud.identity.v1.ServiceAccountSpec\x12\x1c\n\x10state_deprecated\x18\x04 \x01(\tB\x02\x18\x01\x12<\n\x05state\x18\x08 \x01(\x0e\x32-.temporal.api.cloud.resource.v1.ResourceState\x12\x1a\n\x12\x61sync_operation_id\x18\x05 \x01(\t\x12\x30\n\x0c\x63reated_time\x18\x06 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x36\n\x12last_modified_time\x18\x07 \x01(\x0b\x32\x1a.google.protobuf.Timestamp"\xc7\x01\n\x12ServiceAccountSpec\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x36\n\x06\x61\x63\x63\x65ss\x18\x02 \x01(\x0b\x32&.temporal.api.cloud.identity.v1.Access\x12V\n\x17namespace_scoped_access\x18\x04 \x01(\x0b\x32\x35.temporal.api.cloud.identity.v1.NamespaceScopedAccess\x12\x13\n\x0b\x64\x65scription\x18\x03 \x01(\t"\xca\x02\n\x06\x41piKey\x12\n\n\x02id\x18\x01 \x01(\t\x12\x18\n\x10resource_version\x18\x02 \x01(\t\x12\x38\n\x04spec\x18\x03 \x01(\x0b\x32*.temporal.api.cloud.identity.v1.ApiKeySpec\x12\x1c\n\x10state_deprecated\x18\x04 \x01(\tB\x02\x18\x01\x12<\n\x05state\x18\x08 \x01(\x0e\x32-.temporal.api.cloud.resource.v1.ResourceState\x12\x1a\n\x12\x61sync_operation_id\x18\x05 \x01(\t\x12\x30\n\x0c\x63reated_time\x18\x06 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x36\n\x12last_modified_time\x18\x07 \x01(\x0b\x32\x1a.google.protobuf.Timestamp"\xee\x01\n\nApiKeySpec\x12\x10\n\x08owner_id\x18\x01 \x01(\t\x12!\n\x15owner_type_deprecated\x18\x02 \x01(\tB\x02\x18\x01\x12=\n\nowner_type\x18\x07 \x01(\x0e\x32).temporal.api.cloud.identity.v1.OwnerType\x12\x14\n\x0c\x64isplay_name\x18\x03 \x01(\t\x12\x13\n\x0b\x64\x65scription\x18\x04 \x01(\t\x12/\n\x0b\x65xpiry_time\x18\x05 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x10\n\x08\x64isabled\x18\x06 \x01(\x08*\\\n\tOwnerType\x12\x1a\n\x16OWNER_TYPE_UNSPECIFIED\x10\x00\x12\x13\n\x0fOWNER_TYPE_USER\x10\x01\x12\x1e\n\x1aOWNER_TYPE_SERVICE_ACCOUNT\x10\x02\x42\xac\x01\n!io.temporal.api.cloud.identity.v1B\x0cMessageProtoP\x01Z-go.temporal.io/api/cloud/identity/v1;identity\xaa\x02 Temporalio.Api.Cloud.Identity.V1\xea\x02$Temporalio::Api::Cloud::Identity::V1b\x06proto3' + b'\n,temporal/api/cloud/identity/v1/message.proto\x12\x1etemporal.api.cloud.identity.v1\x1a,temporal/api/cloud/resource/v1/message.proto\x1a\x1fgoogle/protobuf/timestamp.proto"\x95\x02\n\rAccountAccess\x12\x1b\n\x0frole_deprecated\x18\x01 \x01(\tB\x02\x18\x01\x12@\n\x04role\x18\x02 \x01(\x0e\x32\x32.temporal.api.cloud.identity.v1.AccountAccess.Role\x12\x14\n\x0c\x63ustom_roles\x18\x03 \x03(\t"\x8e\x01\n\x04Role\x12\x14\n\x10ROLE_UNSPECIFIED\x10\x00\x12\x0e\n\nROLE_OWNER\x10\x01\x12\x0e\n\nROLE_ADMIN\x10\x02\x12\x12\n\x0eROLE_DEVELOPER\x10\x03\x12\x16\n\x12ROLE_FINANCE_ADMIN\x10\x04\x12\r\n\tROLE_READ\x10\x05\x12\x15\n\x11ROLE_METRICS_READ\x10\x06"\xef\x01\n\x0fNamespaceAccess\x12!\n\x15permission_deprecated\x18\x01 \x01(\tB\x02\x18\x01\x12N\n\npermission\x18\x02 \x01(\x0e\x32:.temporal.api.cloud.identity.v1.NamespaceAccess.Permission"i\n\nPermission\x12\x1a\n\x16PERMISSION_UNSPECIFIED\x10\x00\x12\x14\n\x10PERMISSION_ADMIN\x10\x01\x12\x14\n\x10PERMISSION_WRITE\x10\x02\x12\x13\n\x0fPERMISSION_READ\x10\x03"\xba\x02\n\x06\x41\x63\x63\x65ss\x12\x45\n\x0e\x61\x63\x63ount_access\x18\x01 \x01(\x0b\x32-.temporal.api.cloud.identity.v1.AccountAccess\x12Y\n\x12namespace_accesses\x18\x02 \x03(\x0b\x32=.temporal.api.cloud.identity.v1.Access.NamespaceAccessesEntry\x12#\n\x17\x63ustom_roles_deprecated\x18\x04 \x03(\tB\x02\x18\x01\x1ai\n\x16NamespaceAccessesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12>\n\x05value\x18\x02 \x01(\x0b\x32/.temporal.api.cloud.identity.v1.NamespaceAccess:\x02\x38\x01"k\n\x15NamespaceScopedAccess\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12?\n\x06\x61\x63\x63\x65ss\x18\x02 \x01(\x0b\x32/.temporal.api.cloud.identity.v1.NamespaceAccess"Q\n\x08UserSpec\x12\r\n\x05\x65mail\x18\x01 \x01(\t\x12\x36\n\x06\x61\x63\x63\x65ss\x18\x02 \x01(\x0b\x32&.temporal.api.cloud.identity.v1.Access"p\n\nInvitation\x12\x30\n\x0c\x63reated_time\x18\x01 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x30\n\x0c\x65xpired_time\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.Timestamp"\x86\x03\n\x04User\x12\n\n\x02id\x18\x01 \x01(\t\x12\x18\n\x10resource_version\x18\x02 \x01(\t\x12\x36\n\x04spec\x18\x03 \x01(\x0b\x32(.temporal.api.cloud.identity.v1.UserSpec\x12\x1c\n\x10state_deprecated\x18\x04 \x01(\tB\x02\x18\x01\x12<\n\x05state\x18\t \x01(\x0e\x32-.temporal.api.cloud.resource.v1.ResourceState\x12\x1a\n\x12\x61sync_operation_id\x18\x05 \x01(\t\x12>\n\ninvitation\x18\x06 \x01(\x0b\x32*.temporal.api.cloud.identity.v1.Invitation\x12\x30\n\x0c\x63reated_time\x18\x07 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x36\n\x12last_modified_time\x18\x08 \x01(\x0b\x32\x1a.google.protobuf.Timestamp"(\n\x0fGoogleGroupSpec\x12\x15\n\remail_address\x18\x01 \x01(\t"\x1f\n\rSCIMGroupSpec\x12\x0e\n\x06idp_id\x18\x01 \x01(\t"\x10\n\x0e\x43loudGroupSpec"\xc0\x02\n\rUserGroupSpec\x12\x14\n\x0c\x64isplay_name\x18\x01 \x01(\t\x12\x36\n\x06\x61\x63\x63\x65ss\x18\x02 \x01(\x0b\x32&.temporal.api.cloud.identity.v1.Access\x12G\n\x0cgoogle_group\x18\x03 \x01(\x0b\x32/.temporal.api.cloud.identity.v1.GoogleGroupSpecH\x00\x12\x43\n\nscim_group\x18\x04 \x01(\x0b\x32-.temporal.api.cloud.identity.v1.SCIMGroupSpecH\x00\x12\x45\n\x0b\x63loud_group\x18\x05 \x01(\x0b\x32..temporal.api.cloud.identity.v1.CloudGroupSpecH\x00\x42\x0c\n\ngroup_type"\xd0\x02\n\tUserGroup\x12\n\n\x02id\x18\x01 \x01(\t\x12\x18\n\x10resource_version\x18\x02 \x01(\t\x12;\n\x04spec\x18\x03 \x01(\x0b\x32-.temporal.api.cloud.identity.v1.UserGroupSpec\x12\x1c\n\x10state_deprecated\x18\x04 \x01(\tB\x02\x18\x01\x12<\n\x05state\x18\x08 \x01(\x0e\x32-.temporal.api.cloud.resource.v1.ResourceState\x12\x1a\n\x12\x61sync_operation_id\x18\x05 \x01(\t\x12\x30\n\x0c\x63reated_time\x18\x06 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x36\n\x12last_modified_time\x18\x07 \x01(\x0b\x32\x1a.google.protobuf.Timestamp"5\n\x11UserGroupMemberId\x12\x11\n\x07user_id\x18\x01 \x01(\tH\x00\x42\r\n\x0bmember_type"\x89\x01\n\x0fUserGroupMember\x12\x44\n\tmember_id\x18\x01 \x01(\x0b\x32\x31.temporal.api.cloud.identity.v1.UserGroupMemberId\x12\x30\n\x0c\x63reated_time\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.Timestamp"\xda\x02\n\x0eServiceAccount\x12\n\n\x02id\x18\x01 \x01(\t\x12\x18\n\x10resource_version\x18\x02 \x01(\t\x12@\n\x04spec\x18\x03 \x01(\x0b\x32\x32.temporal.api.cloud.identity.v1.ServiceAccountSpec\x12\x1c\n\x10state_deprecated\x18\x04 \x01(\tB\x02\x18\x01\x12<\n\x05state\x18\x08 \x01(\x0e\x32-.temporal.api.cloud.resource.v1.ResourceState\x12\x1a\n\x12\x61sync_operation_id\x18\x05 \x01(\t\x12\x30\n\x0c\x63reated_time\x18\x06 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x36\n\x12last_modified_time\x18\x07 \x01(\x0b\x32\x1a.google.protobuf.Timestamp"\xc7\x01\n\x12ServiceAccountSpec\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x36\n\x06\x61\x63\x63\x65ss\x18\x02 \x01(\x0b\x32&.temporal.api.cloud.identity.v1.Access\x12V\n\x17namespace_scoped_access\x18\x04 \x01(\x0b\x32\x35.temporal.api.cloud.identity.v1.NamespaceScopedAccess\x12\x13\n\x0b\x64\x65scription\x18\x03 \x01(\t"\xca\x02\n\x06\x41piKey\x12\n\n\x02id\x18\x01 \x01(\t\x12\x18\n\x10resource_version\x18\x02 \x01(\t\x12\x38\n\x04spec\x18\x03 \x01(\x0b\x32*.temporal.api.cloud.identity.v1.ApiKeySpec\x12\x1c\n\x10state_deprecated\x18\x04 \x01(\tB\x02\x18\x01\x12<\n\x05state\x18\x08 \x01(\x0e\x32-.temporal.api.cloud.resource.v1.ResourceState\x12\x1a\n\x12\x61sync_operation_id\x18\x05 \x01(\t\x12\x30\n\x0c\x63reated_time\x18\x06 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x36\n\x12last_modified_time\x18\x07 \x01(\x0b\x32\x1a.google.protobuf.Timestamp"\xee\x01\n\nApiKeySpec\x12\x10\n\x08owner_id\x18\x01 \x01(\t\x12!\n\x15owner_type_deprecated\x18\x02 \x01(\tB\x02\x18\x01\x12=\n\nowner_type\x18\x07 \x01(\x0e\x32).temporal.api.cloud.identity.v1.OwnerType\x12\x14\n\x0c\x64isplay_name\x18\x03 \x01(\t\x12\x13\n\x0b\x64\x65scription\x18\x04 \x01(\t\x12/\n\x0b\x65xpiry_time\x18\x05 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x10\n\x08\x64isabled\x18\x06 \x01(\x08"\xbc\x02\n\x0e\x43ustomRoleSpec\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x13\n\x0b\x64\x65scription\x18\x02 \x01(\t\x12N\n\x0bpermissions\x18\x03 \x03(\x0b\x32\x39.temporal.api.cloud.identity.v1.CustomRoleSpec.Permission\x1aK\n\tResources\x12\x15\n\rresource_type\x18\x01 \x01(\t\x12\x14\n\x0cresource_ids\x18\x02 \x03(\t\x12\x11\n\tallow_all\x18\x03 \x01(\x08\x1aj\n\nPermission\x12K\n\tresources\x18\x01 \x01(\x0b\x32\x38.temporal.api.cloud.identity.v1.CustomRoleSpec.Resources\x12\x0f\n\x07\x61\x63tions\x18\x02 \x03(\t"\xb4\x02\n\nCustomRole\x12\n\n\x02id\x18\x01 \x01(\t\x12\x18\n\x10resource_version\x18\x02 \x01(\t\x12<\n\x04spec\x18\x03 \x01(\x0b\x32..temporal.api.cloud.identity.v1.CustomRoleSpec\x12<\n\x05state\x18\x04 \x01(\x0e\x32-.temporal.api.cloud.resource.v1.ResourceState\x12\x1a\n\x12\x61sync_operation_id\x18\x05 \x01(\t\x12\x30\n\x0c\x63reated_time\x18\x06 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x36\n\x12last_modified_time\x18\x07 \x01(\x0b\x32\x1a.google.protobuf.Timestamp*\\\n\tOwnerType\x12\x1a\n\x16OWNER_TYPE_UNSPECIFIED\x10\x00\x12\x13\n\x0fOWNER_TYPE_USER\x10\x01\x12\x1e\n\x1aOWNER_TYPE_SERVICE_ACCOUNT\x10\x02\x42\xac\x01\n!io.temporal.api.cloud.identity.v1B\x0cMessageProtoP\x01Z-go.temporal.io/api/cloud/identity/v1;identity\xaa\x02 Temporalio.Api.Cloud.Identity.V1\xea\x02$Temporalio::Api::Cloud::Identity::V1b\x06proto3' ) _OWNERTYPE = DESCRIPTOR.enum_types_by_name["OwnerType"] @@ -51,6 +51,10 @@ _SERVICEACCOUNTSPEC = DESCRIPTOR.message_types_by_name["ServiceAccountSpec"] _APIKEY = DESCRIPTOR.message_types_by_name["ApiKey"] _APIKEYSPEC = DESCRIPTOR.message_types_by_name["ApiKeySpec"] +_CUSTOMROLESPEC = DESCRIPTOR.message_types_by_name["CustomRoleSpec"] +_CUSTOMROLESPEC_RESOURCES = _CUSTOMROLESPEC.nested_types_by_name["Resources"] +_CUSTOMROLESPEC_PERMISSION = _CUSTOMROLESPEC.nested_types_by_name["Permission"] +_CUSTOMROLE = DESCRIPTOR.message_types_by_name["CustomRole"] _ACCOUNTACCESS_ROLE = _ACCOUNTACCESS.enum_types_by_name["Role"] _NAMESPACEACCESS_PERMISSION = _NAMESPACEACCESS.enum_types_by_name["Permission"] AccountAccess = _reflection.GeneratedProtocolMessageType( @@ -261,6 +265,48 @@ ) _sym_db.RegisterMessage(ApiKeySpec) +CustomRoleSpec = _reflection.GeneratedProtocolMessageType( + "CustomRoleSpec", + (_message.Message,), + { + "Resources": _reflection.GeneratedProtocolMessageType( + "Resources", + (_message.Message,), + { + "DESCRIPTOR": _CUSTOMROLESPEC_RESOURCES, + "__module__": "temporalio.api.cloud.identity.v1.message_pb2", + # @@protoc_insertion_point(class_scope:temporal.api.cloud.identity.v1.CustomRoleSpec.Resources) + }, + ), + "Permission": _reflection.GeneratedProtocolMessageType( + "Permission", + (_message.Message,), + { + "DESCRIPTOR": _CUSTOMROLESPEC_PERMISSION, + "__module__": "temporalio.api.cloud.identity.v1.message_pb2", + # @@protoc_insertion_point(class_scope:temporal.api.cloud.identity.v1.CustomRoleSpec.Permission) + }, + ), + "DESCRIPTOR": _CUSTOMROLESPEC, + "__module__": "temporalio.api.cloud.identity.v1.message_pb2", + # @@protoc_insertion_point(class_scope:temporal.api.cloud.identity.v1.CustomRoleSpec) + }, +) +_sym_db.RegisterMessage(CustomRoleSpec) +_sym_db.RegisterMessage(CustomRoleSpec.Resources) +_sym_db.RegisterMessage(CustomRoleSpec.Permission) + +CustomRole = _reflection.GeneratedProtocolMessageType( + "CustomRole", + (_message.Message,), + { + "DESCRIPTOR": _CUSTOMROLE, + "__module__": "temporalio.api.cloud.identity.v1.message_pb2", + # @@protoc_insertion_point(class_scope:temporal.api.cloud.identity.v1.CustomRole) + }, +) +_sym_db.RegisterMessage(CustomRole) + if _descriptor._USE_C_DESCRIPTORS == False: DESCRIPTOR._options = None DESCRIPTOR._serialized_options = b"\n!io.temporal.api.cloud.identity.v1B\014MessageProtoP\001Z-go.temporal.io/api/cloud/identity/v1;identity\252\002 Temporalio.Api.Cloud.Identity.V1\352\002$Temporalio::Api::Cloud::Identity::V1" @@ -272,6 +318,8 @@ ]._serialized_options = b"\030\001" _ACCESS_NAMESPACEACCESSESENTRY._options = None _ACCESS_NAMESPACEACCESSESENTRY._serialized_options = b"8\001" + _ACCESS.fields_by_name["custom_roles_deprecated"]._options = None + _ACCESS.fields_by_name["custom_roles_deprecated"]._serialized_options = b"\030\001" _USER.fields_by_name["state_deprecated"]._options = None _USER.fields_by_name["state_deprecated"]._serialized_options = b"\030\001" _USERGROUP.fields_by_name["state_deprecated"]._options = None @@ -284,48 +332,56 @@ _APIKEYSPEC.fields_by_name[ "owner_type_deprecated" ]._serialized_options = b"\030\001" - _OWNERTYPE._serialized_start = 3713 - _OWNERTYPE._serialized_end = 3805 + _OWNERTYPE._serialized_start = 4402 + _OWNERTYPE._serialized_end = 4494 _ACCOUNTACCESS._serialized_start = 160 - _ACCOUNTACCESS._serialized_end = 415 - _ACCOUNTACCESS_ROLE._serialized_start = 273 - _ACCOUNTACCESS_ROLE._serialized_end = 415 - _NAMESPACEACCESS._serialized_start = 418 - _NAMESPACEACCESS._serialized_end = 657 - _NAMESPACEACCESS_PERMISSION._serialized_start = 552 - _NAMESPACEACCESS_PERMISSION._serialized_end = 657 - _ACCESS._serialized_start = 660 - _ACCESS._serialized_end = 937 - _ACCESS_NAMESPACEACCESSESENTRY._serialized_start = 832 - _ACCESS_NAMESPACEACCESSESENTRY._serialized_end = 937 - _NAMESPACESCOPEDACCESS._serialized_start = 939 - _NAMESPACESCOPEDACCESS._serialized_end = 1046 - _USERSPEC._serialized_start = 1048 - _USERSPEC._serialized_end = 1129 - _INVITATION._serialized_start = 1131 - _INVITATION._serialized_end = 1243 - _USER._serialized_start = 1246 - _USER._serialized_end = 1636 - _GOOGLEGROUPSPEC._serialized_start = 1638 - _GOOGLEGROUPSPEC._serialized_end = 1678 - _SCIMGROUPSPEC._serialized_start = 1680 - _SCIMGROUPSPEC._serialized_end = 1711 - _CLOUDGROUPSPEC._serialized_start = 1713 - _CLOUDGROUPSPEC._serialized_end = 1729 - _USERGROUPSPEC._serialized_start = 1732 - _USERGROUPSPEC._serialized_end = 2052 - _USERGROUP._serialized_start = 2055 - _USERGROUP._serialized_end = 2391 - _USERGROUPMEMBERID._serialized_start = 2393 - _USERGROUPMEMBERID._serialized_end = 2446 - _USERGROUPMEMBER._serialized_start = 2449 - _USERGROUPMEMBER._serialized_end = 2586 - _SERVICEACCOUNT._serialized_start = 2589 - _SERVICEACCOUNT._serialized_end = 2935 - _SERVICEACCOUNTSPEC._serialized_start = 2938 - _SERVICEACCOUNTSPEC._serialized_end = 3137 - _APIKEY._serialized_start = 3140 - _APIKEY._serialized_end = 3470 - _APIKEYSPEC._serialized_start = 3473 - _APIKEYSPEC._serialized_end = 3711 + _ACCOUNTACCESS._serialized_end = 437 + _ACCOUNTACCESS_ROLE._serialized_start = 295 + _ACCOUNTACCESS_ROLE._serialized_end = 437 + _NAMESPACEACCESS._serialized_start = 440 + _NAMESPACEACCESS._serialized_end = 679 + _NAMESPACEACCESS_PERMISSION._serialized_start = 574 + _NAMESPACEACCESS_PERMISSION._serialized_end = 679 + _ACCESS._serialized_start = 682 + _ACCESS._serialized_end = 996 + _ACCESS_NAMESPACEACCESSESENTRY._serialized_start = 891 + _ACCESS_NAMESPACEACCESSESENTRY._serialized_end = 996 + _NAMESPACESCOPEDACCESS._serialized_start = 998 + _NAMESPACESCOPEDACCESS._serialized_end = 1105 + _USERSPEC._serialized_start = 1107 + _USERSPEC._serialized_end = 1188 + _INVITATION._serialized_start = 1190 + _INVITATION._serialized_end = 1302 + _USER._serialized_start = 1305 + _USER._serialized_end = 1695 + _GOOGLEGROUPSPEC._serialized_start = 1697 + _GOOGLEGROUPSPEC._serialized_end = 1737 + _SCIMGROUPSPEC._serialized_start = 1739 + _SCIMGROUPSPEC._serialized_end = 1770 + _CLOUDGROUPSPEC._serialized_start = 1772 + _CLOUDGROUPSPEC._serialized_end = 1788 + _USERGROUPSPEC._serialized_start = 1791 + _USERGROUPSPEC._serialized_end = 2111 + _USERGROUP._serialized_start = 2114 + _USERGROUP._serialized_end = 2450 + _USERGROUPMEMBERID._serialized_start = 2452 + _USERGROUPMEMBERID._serialized_end = 2505 + _USERGROUPMEMBER._serialized_start = 2508 + _USERGROUPMEMBER._serialized_end = 2645 + _SERVICEACCOUNT._serialized_start = 2648 + _SERVICEACCOUNT._serialized_end = 2994 + _SERVICEACCOUNTSPEC._serialized_start = 2997 + _SERVICEACCOUNTSPEC._serialized_end = 3196 + _APIKEY._serialized_start = 3199 + _APIKEY._serialized_end = 3529 + _APIKEYSPEC._serialized_start = 3532 + _APIKEYSPEC._serialized_end = 3770 + _CUSTOMROLESPEC._serialized_start = 3773 + _CUSTOMROLESPEC._serialized_end = 4089 + _CUSTOMROLESPEC_RESOURCES._serialized_start = 3906 + _CUSTOMROLESPEC_RESOURCES._serialized_end = 3981 + _CUSTOMROLESPEC_PERMISSION._serialized_start = 3983 + _CUSTOMROLESPEC_PERMISSION._serialized_end = 4089 + _CUSTOMROLE._serialized_start = 4092 + _CUSTOMROLE._serialized_end = 4400 # @@protoc_insertion_point(module_scope) diff --git a/temporalio/api/cloud/identity/v1/message_pb2.pyi b/temporalio/api/cloud/identity/v1/message_pb2.pyi index ced77ff78..0427542bf 100644 --- a/temporalio/api/cloud/identity/v1/message_pb2.pyi +++ b/temporalio/api/cloud/identity/v1/message_pb2.pyi @@ -92,6 +92,7 @@ class AccountAccess(google.protobuf.message.Message): ROLE_DEPRECATED_FIELD_NUMBER: builtins.int ROLE_FIELD_NUMBER: builtins.int + CUSTOM_ROLES_FIELD_NUMBER: builtins.int role_deprecated: builtins.str """The role on the account, should be one of [owner, admin, developer, financeadmin, read, metricsread] owner - gives full access to the account, including users, namespaces, and billing @@ -108,16 +109,29 @@ class AccountAccess(google.protobuf.message.Message): temporal:versioning:min_version=v0.3.0 temporal:enums:replaces=role_deprecated """ + @property + def custom_roles( + self, + ) -> google.protobuf.internal.containers.RepeatedScalarFieldContainer[builtins.str]: + """List of custom role IDs assigned to the user or service account. + temporal:versioning:min_version=v0.13.0 + """ def __init__( self, *, role_deprecated: builtins.str = ..., role: global___AccountAccess.Role.ValueType = ..., + custom_roles: collections.abc.Iterable[builtins.str] | None = ..., ) -> None: ... def ClearField( self, field_name: typing_extensions.Literal[ - "role", b"role", "role_deprecated", b"role_deprecated" + "custom_roles", + b"custom_roles", + "role", + b"role", + "role_deprecated", + b"role_deprecated", ], ) -> None: ... @@ -214,6 +228,7 @@ class Access(google.protobuf.message.Message): ACCOUNT_ACCESS_FIELD_NUMBER: builtins.int NAMESPACE_ACCESSES_FIELD_NUMBER: builtins.int + CUSTOM_ROLES_DEPRECATED_FIELD_NUMBER: builtins.int @property def account_access(self) -> global___AccountAccess: """The account access""" @@ -226,6 +241,14 @@ class Access(google.protobuf.message.Message): """The map of namespace accesses The key is the namespace name and the value is the access to the namespace """ + @property + def custom_roles_deprecated( + self, + ) -> google.protobuf.internal.containers.RepeatedScalarFieldContainer[builtins.str]: + """List of custom role IDs assigned to the user or service account. + Deprecated: Not supported after v0.12.0 api version. Use account_access.custom_roles instead. + temporal:versioning:max_version=v0.12.0 + """ def __init__( self, *, @@ -234,6 +257,7 @@ class Access(google.protobuf.message.Message): builtins.str, global___NamespaceAccess ] | None = ..., + custom_roles_deprecated: collections.abc.Iterable[builtins.str] | None = ..., ) -> None: ... def HasField( self, field_name: typing_extensions.Literal["account_access", b"account_access"] @@ -243,6 +267,8 @@ class Access(google.protobuf.message.Message): field_name: typing_extensions.Literal[ "account_access", b"account_access", + "custom_roles_deprecated", + b"custom_roles_deprecated", "namespace_accesses", b"namespace_accesses", ], @@ -1009,3 +1035,186 @@ class ApiKeySpec(google.protobuf.message.Message): ) -> None: ... global___ApiKeySpec = ApiKeySpec + +class CustomRoleSpec(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + class Resources(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + RESOURCE_TYPE_FIELD_NUMBER: builtins.int + RESOURCE_IDS_FIELD_NUMBER: builtins.int + ALLOW_ALL_FIELD_NUMBER: builtins.int + resource_type: builtins.str + """The resource type the permission applies to.""" + @property + def resource_ids( + self, + ) -> google.protobuf.internal.containers.RepeatedScalarFieldContainer[ + builtins.str + ]: + """The resource IDs the permission applies to. Can be empty if allow_all is true.""" + allow_all: builtins.bool + """Whether the permission applies to all resources of the given type.""" + def __init__( + self, + *, + resource_type: builtins.str = ..., + resource_ids: collections.abc.Iterable[builtins.str] | None = ..., + allow_all: builtins.bool = ..., + ) -> None: ... + def ClearField( + self, + field_name: typing_extensions.Literal[ + "allow_all", + b"allow_all", + "resource_ids", + b"resource_ids", + "resource_type", + b"resource_type", + ], + ) -> None: ... + + class Permission(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + RESOURCES_FIELD_NUMBER: builtins.int + ACTIONS_FIELD_NUMBER: builtins.int + @property + def resources(self) -> global___CustomRoleSpec.Resources: + """The resources the permission applies to.""" + @property + def actions( + self, + ) -> google.protobuf.internal.containers.RepeatedScalarFieldContainer[ + builtins.str + ]: + """The actions allowed by the permission.""" + def __init__( + self, + *, + resources: global___CustomRoleSpec.Resources | None = ..., + actions: collections.abc.Iterable[builtins.str] | None = ..., + ) -> None: ... + def HasField( + self, field_name: typing_extensions.Literal["resources", b"resources"] + ) -> builtins.bool: ... + def ClearField( + self, + field_name: typing_extensions.Literal[ + "actions", b"actions", "resources", b"resources" + ], + ) -> None: ... + + NAME_FIELD_NUMBER: builtins.int + DESCRIPTION_FIELD_NUMBER: builtins.int + PERMISSIONS_FIELD_NUMBER: builtins.int + name: builtins.str + """The name of the custom role.""" + description: builtins.str + """The description of the custom role.""" + @property + def permissions( + self, + ) -> google.protobuf.internal.containers.RepeatedCompositeFieldContainer[ + global___CustomRoleSpec.Permission + ]: + """The permissions assigned to the custom role.""" + def __init__( + self, + *, + name: builtins.str = ..., + description: builtins.str = ..., + permissions: collections.abc.Iterable[global___CustomRoleSpec.Permission] + | None = ..., + ) -> None: ... + def ClearField( + self, + field_name: typing_extensions.Literal[ + "description", + b"description", + "name", + b"name", + "permissions", + b"permissions", + ], + ) -> None: ... + +global___CustomRoleSpec = CustomRoleSpec + +class CustomRole(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + ID_FIELD_NUMBER: builtins.int + RESOURCE_VERSION_FIELD_NUMBER: builtins.int + SPEC_FIELD_NUMBER: builtins.int + STATE_FIELD_NUMBER: builtins.int + ASYNC_OPERATION_ID_FIELD_NUMBER: builtins.int + CREATED_TIME_FIELD_NUMBER: builtins.int + LAST_MODIFIED_TIME_FIELD_NUMBER: builtins.int + id: builtins.str + """The id of the custom role.""" + resource_version: builtins.str + """The current version of the custom role specification. + The next update operation will have to include this version. + """ + @property + def spec(self) -> global___CustomRoleSpec: + """The custom role specification.""" + state: temporalio.api.cloud.resource.v1.message_pb2.ResourceState.ValueType + """The current state of the custom role. + For any failed state, reach out to Temporal Cloud support for remediation. + """ + async_operation_id: builtins.str + """The id of the async operation that is creating/updating/deleting the custom role, if any.""" + @property + def created_time(self) -> google.protobuf.timestamp_pb2.Timestamp: + """The date and time when the custom role was created.""" + @property + def last_modified_time(self) -> google.protobuf.timestamp_pb2.Timestamp: + """The date and time when the custom role was last modified. + Will not be set if the custom role has never been modified. + """ + def __init__( + self, + *, + id: builtins.str = ..., + resource_version: builtins.str = ..., + spec: global___CustomRoleSpec | None = ..., + state: temporalio.api.cloud.resource.v1.message_pb2.ResourceState.ValueType = ..., + async_operation_id: builtins.str = ..., + created_time: google.protobuf.timestamp_pb2.Timestamp | None = ..., + last_modified_time: google.protobuf.timestamp_pb2.Timestamp | None = ..., + ) -> None: ... + def HasField( + self, + field_name: typing_extensions.Literal[ + "created_time", + b"created_time", + "last_modified_time", + b"last_modified_time", + "spec", + b"spec", + ], + ) -> builtins.bool: ... + def ClearField( + self, + field_name: typing_extensions.Literal[ + "async_operation_id", + b"async_operation_id", + "created_time", + b"created_time", + "id", + b"id", + "last_modified_time", + b"last_modified_time", + "resource_version", + b"resource_version", + "spec", + b"spec", + "state", + b"state", + ], + ) -> None: ... + +global___CustomRole = CustomRole diff --git a/temporalio/api/cloud/namespace/v1/__init__.py b/temporalio/api/cloud/namespace/v1/__init__.py index 7bf5d0446..04e5e98f8 100644 --- a/temporalio/api/cloud/namespace/v1/__init__.py +++ b/temporalio/api/cloud/namespace/v1/__init__.py @@ -8,6 +8,7 @@ Endpoints, ExportSink, ExportSinkSpec, + FairnessSpec, HighAvailabilitySpec, LifecycleSpec, Limits, @@ -17,6 +18,8 @@ NamespaceRegionStatus, NamespaceSpec, PrivateConnectivity, + Replica, + ReplicaSpec, ) __all__ = [ @@ -29,6 +32,7 @@ "Endpoints", "ExportSink", "ExportSinkSpec", + "FairnessSpec", "HighAvailabilitySpec", "LifecycleSpec", "Limits", @@ -38,4 +42,6 @@ "NamespaceRegionStatus", "NamespaceSpec", "PrivateConnectivity", + "Replica", + "ReplicaSpec", ] diff --git a/temporalio/api/cloud/namespace/v1/message_pb2.py b/temporalio/api/cloud/namespace/v1/message_pb2.py index 5cd6c00c2..33eb2f789 100644 --- a/temporalio/api/cloud/namespace/v1/message_pb2.py +++ b/temporalio/api/cloud/namespace/v1/message_pb2.py @@ -27,7 +27,7 @@ ) DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile( - b'\n-temporal/api/cloud/namespace/v1/message.proto\x12\x1ftemporal.api.cloud.namespace.v1\x1a,temporal/api/cloud/resource/v1/message.proto\x1a\x1fgoogle/protobuf/timestamp.proto\x1a(temporal/api/cloud/sink/v1/message.proto\x1a\x34temporal/api/cloud/connectivityrule/v1/message.proto"\x81\x01\n\x15\x43\x65rtificateFilterSpec\x12\x13\n\x0b\x63ommon_name\x18\x01 \x01(\t\x12\x14\n\x0corganization\x18\x02 \x01(\t\x12\x1b\n\x13organizational_unit\x18\x03 \x01(\t\x12 \n\x18subject_alternative_name\x18\x04 \x01(\t"\xbb\x01\n\x0cMtlsAuthSpec\x12)\n\x1d\x61\x63\x63\x65pted_client_ca_deprecated\x18\x01 \x01(\tB\x02\x18\x01\x12\x1a\n\x12\x61\x63\x63\x65pted_client_ca\x18\x04 \x01(\x0c\x12S\n\x13\x63\x65rtificate_filters\x18\x02 \x03(\x0b\x32\x36.temporal.api.cloud.namespace.v1.CertificateFilterSpec\x12\x0f\n\x07\x65nabled\x18\x03 \x01(\x08"!\n\x0e\x41piKeyAuthSpec\x12\x0f\n\x07\x65nabled\x18\x01 \x01(\x08"1\n\rLifecycleSpec\x12 \n\x18\x65nable_delete_protection\x18\x01 \x01(\x08"\xf4\x02\n\x0f\x43odecServerSpec\x12\x10\n\x08\x65ndpoint\x18\x01 \x01(\t\x12\x19\n\x11pass_access_token\x18\x02 \x01(\x08\x12(\n include_cross_origin_credentials\x18\x03 \x01(\x08\x12\x61\n\x14\x63ustom_error_message\x18\x04 \x01(\x0b\x32\x43.temporal.api.cloud.namespace.v1.CodecServerSpec.CustomErrorMessage\x1a\xa6\x01\n\x12\x43ustomErrorMessage\x12\x61\n\x07\x64\x65\x66\x61ult\x18\x01 \x01(\x0b\x32P.temporal.api.cloud.namespace.v1.CodecServerSpec.CustomErrorMessage.ErrorMessage\x1a-\n\x0c\x45rrorMessage\x12\x0f\n\x07message\x18\x01 \x01(\t\x12\x0c\n\x04link\x18\x02 \x01(\t"8\n\x14HighAvailabilitySpec\x12 \n\x18\x64isable_managed_failover\x18\x01 \x01(\x08"\xdf\x01\n\x0c\x43\x61pacitySpec\x12K\n\ton_demand\x18\x01 \x01(\x0b\x32\x36.temporal.api.cloud.namespace.v1.CapacitySpec.OnDemandH\x00\x12P\n\x0bprovisioned\x18\x02 \x01(\x0b\x32\x39.temporal.api.cloud.namespace.v1.CapacitySpec.ProvisionedH\x00\x1a\n\n\x08OnDemand\x1a\x1c\n\x0bProvisioned\x12\r\n\x05value\x18\x01 \x01(\x01\x42\x06\n\x04spec"\xdc\x05\n\x08\x43\x61pacity\x12G\n\ton_demand\x18\x01 \x01(\x0b\x32\x32.temporal.api.cloud.namespace.v1.Capacity.OnDemandH\x00\x12L\n\x0bprovisioned\x18\x02 \x01(\x0b\x32\x35.temporal.api.cloud.namespace.v1.Capacity.ProvisionedH\x00\x12I\n\x0elatest_request\x18\x03 \x01(\x0b\x32\x31.temporal.api.cloud.namespace.v1.Capacity.Request\x1a\n\n\x08OnDemand\x1a$\n\x0bProvisioned\x12\x15\n\rcurrent_value\x18\x01 \x01(\x01\x1a\xab\x03\n\x07Request\x12\x46\n\x05state\x18\x01 \x01(\x0e\x32\x37.temporal.api.cloud.namespace.v1.Capacity.Request.State\x12.\n\nstart_time\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12,\n\x08\x65nd_time\x18\x03 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x1a\n\x12\x61sync_operation_id\x18\x04 \x01(\t\x12;\n\x04spec\x18\x05 \x01(\x0b\x32-.temporal.api.cloud.namespace.v1.CapacitySpec"\xa0\x01\n\x05State\x12&\n"STATE_CAPACITY_REQUEST_UNSPECIFIED\x10\x00\x12$\n STATE_CAPACITY_REQUEST_COMPLETED\x10\x01\x12&\n"STATE_CAPACITY_REQUEST_IN_PROGRESS\x10\x02\x12!\n\x1dSTATE_CAPACITY_REQUEST_FAILED\x10\x03\x42\x0e\n\x0c\x63urrent_mode"\xcf\t\n\rNamespaceSpec\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x0f\n\x07regions\x18\x02 \x03(\t\x12\x16\n\x0eretention_days\x18\x03 \x01(\x05\x12@\n\tmtls_auth\x18\x04 \x01(\x0b\x32-.temporal.api.cloud.namespace.v1.MtlsAuthSpec\x12\x45\n\x0c\x61pi_key_auth\x18\x07 \x01(\x0b\x32/.temporal.api.cloud.namespace.v1.ApiKeyAuthSpec\x12p\n\x18\x63ustom_search_attributes\x18\x05 \x03(\x0b\x32J.temporal.api.cloud.namespace.v1.NamespaceSpec.CustomSearchAttributesEntryB\x02\x18\x01\x12_\n\x11search_attributes\x18\x08 \x03(\x0b\x32\x44.temporal.api.cloud.namespace.v1.NamespaceSpec.SearchAttributesEntry\x12\x46\n\x0c\x63odec_server\x18\x06 \x01(\x0b\x32\x30.temporal.api.cloud.namespace.v1.CodecServerSpec\x12\x41\n\tlifecycle\x18\t \x01(\x0b\x32..temporal.api.cloud.namespace.v1.LifecycleSpec\x12P\n\x11high_availability\x18\n \x01(\x0b\x32\x35.temporal.api.cloud.namespace.v1.HighAvailabilitySpec\x12\x1d\n\x15\x63onnectivity_rule_ids\x18\x0b \x03(\t\x12\x44\n\rcapacity_spec\x18\x0c \x01(\x0b\x32-.temporal.api.cloud.namespace.v1.CapacitySpec\x1a=\n\x1b\x43ustomSearchAttributesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x1a{\n\x15SearchAttributesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12Q\n\x05value\x18\x02 \x01(\x0e\x32\x42.temporal.api.cloud.namespace.v1.NamespaceSpec.SearchAttributeType:\x02\x38\x01"\xac\x02\n\x13SearchAttributeType\x12%\n!SEARCH_ATTRIBUTE_TYPE_UNSPECIFIED\x10\x00\x12\x1e\n\x1aSEARCH_ATTRIBUTE_TYPE_TEXT\x10\x01\x12!\n\x1dSEARCH_ATTRIBUTE_TYPE_KEYWORD\x10\x02\x12\x1d\n\x19SEARCH_ATTRIBUTE_TYPE_INT\x10\x03\x12 \n\x1cSEARCH_ATTRIBUTE_TYPE_DOUBLE\x10\x04\x12\x1e\n\x1aSEARCH_ATTRIBUTE_TYPE_BOOL\x10\x05\x12"\n\x1eSEARCH_ATTRIBUTE_TYPE_DATETIME\x10\x06\x12&\n"SEARCH_ATTRIBUTE_TYPE_KEYWORD_LIST\x10\x07"Q\n\tEndpoints\x12\x13\n\x0bweb_address\x18\x01 \x01(\t\x12\x19\n\x11mtls_grpc_address\x18\x02 \x01(\t\x12\x14\n\x0cgrpc_address\x18\x03 \x01(\t"*\n\x06Limits\x12 \n\x18\x61\x63tions_per_second_limit\x18\x01 \x01(\x05"X\n\x12\x41WSPrivateLinkInfo\x12\x1e\n\x16\x61llowed_principal_arns\x18\x01 \x03(\t\x12"\n\x1avpc_endpoint_service_names\x18\x02 \x03(\t"t\n\x13PrivateConnectivity\x12\x0e\n\x06region\x18\x01 \x01(\t\x12M\n\x10\x61ws_private_link\x18\x02 \x01(\x0b\x32\x33.temporal.api.cloud.namespace.v1.AWSPrivateLinkInfo"\x83\x08\n\tNamespace\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x18\n\x10resource_version\x18\x02 \x01(\t\x12<\n\x04spec\x18\x03 \x01(\x0b\x32..temporal.api.cloud.namespace.v1.NamespaceSpec\x12\x1c\n\x10state_deprecated\x18\x04 \x01(\tB\x02\x18\x01\x12<\n\x05state\x18\r \x01(\x0e\x32-.temporal.api.cloud.resource.v1.ResourceState\x12\x1a\n\x12\x61sync_operation_id\x18\x05 \x01(\t\x12=\n\tendpoints\x18\x06 \x01(\x0b\x32*.temporal.api.cloud.namespace.v1.Endpoints\x12\x15\n\ractive_region\x18\x07 \x01(\t\x12\x37\n\x06limits\x18\x08 \x01(\x0b\x32\'.temporal.api.cloud.namespace.v1.Limits\x12T\n\x16private_connectivities\x18\t \x03(\x0b\x32\x34.temporal.api.cloud.namespace.v1.PrivateConnectivity\x12\x30\n\x0c\x63reated_time\x18\n \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x36\n\x12last_modified_time\x18\x0b \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12S\n\rregion_status\x18\x0c \x03(\x0b\x32<.temporal.api.cloud.namespace.v1.Namespace.RegionStatusEntry\x12T\n\x12\x63onnectivity_rules\x18\x0e \x03(\x0b\x32\x38.temporal.api.cloud.connectivityrule.v1.ConnectivityRule\x12\x42\n\x04tags\x18\x0f \x03(\x0b\x32\x34.temporal.api.cloud.namespace.v1.Namespace.TagsEntry\x12;\n\x08\x63\x61pacity\x18\x10 \x01(\x0b\x32).temporal.api.cloud.namespace.v1.Capacity\x1ak\n\x11RegionStatusEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x45\n\x05value\x18\x02 \x01(\x0b\x32\x36.temporal.api.cloud.namespace.v1.NamespaceRegionStatus:\x02\x38\x01\x1a+\n\tTagsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01"\x9b\x02\n\x15NamespaceRegionStatus\x12\x1c\n\x10state_deprecated\x18\x01 \x01(\tB\x02\x18\x01\x12K\n\x05state\x18\x03 \x01(\x0e\x32<.temporal.api.cloud.namespace.v1.NamespaceRegionStatus.State\x12\x1a\n\x12\x61sync_operation_id\x18\x02 \x01(\t"{\n\x05State\x12\x15\n\x11STATE_UNSPECIFIED\x10\x00\x12\x10\n\x0cSTATE_ADDING\x10\x01\x12\x10\n\x0cSTATE_ACTIVE\x10\x02\x12\x11\n\rSTATE_PASSIVE\x10\x03\x12\x12\n\x0eSTATE_REMOVING\x10\x04\x12\x10\n\x0cSTATE_FAILED\x10\x05"\x91\x01\n\x0e\x45xportSinkSpec\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x0f\n\x07\x65nabled\x18\x02 \x01(\x08\x12.\n\x02s3\x18\x03 \x01(\x0b\x32".temporal.api.cloud.sink.v1.S3Spec\x12\x30\n\x03gcs\x18\x04 \x01(\x0b\x32#.temporal.api.cloud.sink.v1.GCSSpec"\xf6\x03\n\nExportSink\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x18\n\x10resource_version\x18\x02 \x01(\t\x12<\n\x05state\x18\x03 \x01(\x0e\x32-.temporal.api.cloud.resource.v1.ResourceState\x12=\n\x04spec\x18\x04 \x01(\x0b\x32/.temporal.api.cloud.namespace.v1.ExportSinkSpec\x12\x42\n\x06health\x18\x05 \x01(\x0e\x32\x32.temporal.api.cloud.namespace.v1.ExportSink.Health\x12\x15\n\rerror_message\x18\x06 \x01(\t\x12;\n\x17latest_data_export_time\x18\x07 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12:\n\x16last_health_check_time\x18\x08 \x01(\x0b\x32\x1a.google.protobuf.Timestamp"o\n\x06Health\x12\x16\n\x12HEALTH_UNSPECIFIED\x10\x00\x12\r\n\tHEALTH_OK\x10\x01\x12\x19\n\x15HEALTH_ERROR_INTERNAL\x10\x02\x12#\n\x1fHEALTH_ERROR_USER_CONFIGURATION\x10\x03"\x9f\x06\n\x15NamespaceCapacityInfo\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x19\n\x11has_legacy_limits\x18\x02 \x01(\x08\x12\x43\n\x10\x63urrent_capacity\x18\x03 \x01(\x0b\x32).temporal.api.cloud.namespace.v1.Capacity\x12`\n\x0cmode_options\x18\x04 \x01(\x0b\x32J.temporal.api.cloud.namespace.v1.NamespaceCapacityInfo.CapacityModeOptions\x12K\n\x05stats\x18\x05 \x01(\x0b\x32<.temporal.api.cloud.namespace.v1.NamespaceCapacityInfo.Stats\x1a\xd3\x02\n\x13\x43\x61pacityModeOptions\x12k\n\x0bprovisioned\x18\x01 \x01(\x0b\x32V.temporal.api.cloud.namespace.v1.NamespaceCapacityInfo.CapacityModeOptions.Provisioned\x12\x66\n\ton_demand\x18\x02 \x01(\x0b\x32S.temporal.api.cloud.namespace.v1.NamespaceCapacityInfo.CapacityModeOptions.OnDemand\x1aH\n\x0bProvisioned\x12\x18\n\x10valid_tru_values\x18\x01 \x03(\x01\x12\x1f\n\x17max_available_tru_value\x18\x02 \x01(\x01\x1a\x1d\n\x08OnDemand\x12\x11\n\taps_limit\x18\x01 \x01(\x01\x1a\x8d\x01\n\x05Stats\x12Q\n\x03\x61ps\x18\x01 \x01(\x0b\x32\x44.temporal.api.cloud.namespace.v1.NamespaceCapacityInfo.Stats.Summary\x1a\x31\n\x07Summary\x12\x0c\n\x04mean\x18\x01 \x01(\x01\x12\x0b\n\x03p90\x18\x02 \x01(\x01\x12\x0b\n\x03p99\x18\x03 \x01(\x01\x42\xb1\x01\n"io.temporal.api.cloud.namespace.v1B\x0cMessageProtoP\x01Z/go.temporal.io/api/cloud/namespace/v1;namespace\xaa\x02!Temporalio.Api.Cloud.Namespace.V1\xea\x02%Temporalio::Api::Cloud::Namespace::V1b\x06proto3' + b'\n-temporal/api/cloud/namespace/v1/message.proto\x12\x1ftemporal.api.cloud.namespace.v1\x1a,temporal/api/cloud/resource/v1/message.proto\x1a\x1fgoogle/protobuf/timestamp.proto\x1a(temporal/api/cloud/sink/v1/message.proto\x1a\x34temporal/api/cloud/connectivityrule/v1/message.proto"\x81\x01\n\x15\x43\x65rtificateFilterSpec\x12\x13\n\x0b\x63ommon_name\x18\x01 \x01(\t\x12\x14\n\x0corganization\x18\x02 \x01(\t\x12\x1b\n\x13organizational_unit\x18\x03 \x01(\t\x12 \n\x18subject_alternative_name\x18\x04 \x01(\t"\xbb\x01\n\x0cMtlsAuthSpec\x12)\n\x1d\x61\x63\x63\x65pted_client_ca_deprecated\x18\x01 \x01(\tB\x02\x18\x01\x12\x1a\n\x12\x61\x63\x63\x65pted_client_ca\x18\x04 \x01(\x0c\x12S\n\x13\x63\x65rtificate_filters\x18\x02 \x03(\x0b\x32\x36.temporal.api.cloud.namespace.v1.CertificateFilterSpec\x12\x0f\n\x07\x65nabled\x18\x03 \x01(\x08"!\n\x0e\x41piKeyAuthSpec\x12\x0f\n\x07\x65nabled\x18\x01 \x01(\x08"1\n\rLifecycleSpec\x12 \n\x18\x65nable_delete_protection\x18\x01 \x01(\x08"\xf4\x02\n\x0f\x43odecServerSpec\x12\x10\n\x08\x65ndpoint\x18\x01 \x01(\t\x12\x19\n\x11pass_access_token\x18\x02 \x01(\x08\x12(\n include_cross_origin_credentials\x18\x03 \x01(\x08\x12\x61\n\x14\x63ustom_error_message\x18\x04 \x01(\x0b\x32\x43.temporal.api.cloud.namespace.v1.CodecServerSpec.CustomErrorMessage\x1a\xa6\x01\n\x12\x43ustomErrorMessage\x12\x61\n\x07\x64\x65\x66\x61ult\x18\x01 \x01(\x0b\x32P.temporal.api.cloud.namespace.v1.CodecServerSpec.CustomErrorMessage.ErrorMessage\x1a-\n\x0c\x45rrorMessage\x12\x0f\n\x07message\x18\x01 \x01(\t\x12\x0c\n\x04link\x18\x02 \x01(\t"c\n\x14HighAvailabilitySpec\x12 \n\x18\x64isable_managed_failover\x18\x01 \x01(\x08\x12)\n!disable_passive_poller_forwarding\x18\x02 \x01(\x08"\x1d\n\x0bReplicaSpec\x12\x0e\n\x06region\x18\x01 \x01(\t"\x99\x02\n\x07Replica\x12\n\n\x02id\x18\x01 \x01(\t\x12\x12\n\nis_primary\x18\x02 \x01(\x08\x12\x44\n\x05state\x18\x03 \x01(\x0e\x32\x35.temporal.api.cloud.namespace.v1.Replica.ReplicaState\x12\x0e\n\x06region\x18\x04 \x01(\t"\x97\x01\n\x0cReplicaState\x12\x1d\n\x19REPLICA_STATE_UNSPECIFIED\x10\x00\x12\x18\n\x14REPLICA_STATE_ADDING\x10\x01\x12\x18\n\x14REPLICA_STATE_ACTIVE\x10\x02\x12\x1a\n\x16REPLICA_STATE_REMOVING\x10\x03\x12\x18\n\x14REPLICA_STATE_FAILED\x10\x05"\xdf\x01\n\x0c\x43\x61pacitySpec\x12K\n\ton_demand\x18\x01 \x01(\x0b\x32\x36.temporal.api.cloud.namespace.v1.CapacitySpec.OnDemandH\x00\x12P\n\x0bprovisioned\x18\x02 \x01(\x0b\x32\x39.temporal.api.cloud.namespace.v1.CapacitySpec.ProvisionedH\x00\x1a\n\n\x08OnDemand\x1a\x1c\n\x0bProvisioned\x12\r\n\x05value\x18\x01 \x01(\x01\x42\x06\n\x04spec"\xdc\x05\n\x08\x43\x61pacity\x12G\n\ton_demand\x18\x01 \x01(\x0b\x32\x32.temporal.api.cloud.namespace.v1.Capacity.OnDemandH\x00\x12L\n\x0bprovisioned\x18\x02 \x01(\x0b\x32\x35.temporal.api.cloud.namespace.v1.Capacity.ProvisionedH\x00\x12I\n\x0elatest_request\x18\x03 \x01(\x0b\x32\x31.temporal.api.cloud.namespace.v1.Capacity.Request\x1a\n\n\x08OnDemand\x1a$\n\x0bProvisioned\x12\x15\n\rcurrent_value\x18\x01 \x01(\x01\x1a\xab\x03\n\x07Request\x12\x46\n\x05state\x18\x01 \x01(\x0e\x32\x37.temporal.api.cloud.namespace.v1.Capacity.Request.State\x12.\n\nstart_time\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12,\n\x08\x65nd_time\x18\x03 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x1a\n\x12\x61sync_operation_id\x18\x04 \x01(\t\x12;\n\x04spec\x18\x05 \x01(\x0b\x32-.temporal.api.cloud.namespace.v1.CapacitySpec"\xa0\x01\n\x05State\x12&\n"STATE_CAPACITY_REQUEST_UNSPECIFIED\x10\x00\x12$\n STATE_CAPACITY_REQUEST_COMPLETED\x10\x01\x12&\n"STATE_CAPACITY_REQUEST_IN_PROGRESS\x10\x02\x12!\n\x1dSTATE_CAPACITY_REQUEST_FAILED\x10\x03\x42\x0e\n\x0c\x63urrent_mode"3\n\x0c\x46\x61irnessSpec\x12#\n\x1btask_queue_fairness_enabled\x18\x01 \x01(\x08"\xd4\n\n\rNamespaceSpec\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x13\n\x07regions\x18\x02 \x03(\tB\x02\x18\x01\x12\x16\n\x0eretention_days\x18\x03 \x01(\x05\x12@\n\tmtls_auth\x18\x04 \x01(\x0b\x32-.temporal.api.cloud.namespace.v1.MtlsAuthSpec\x12\x45\n\x0c\x61pi_key_auth\x18\x07 \x01(\x0b\x32/.temporal.api.cloud.namespace.v1.ApiKeyAuthSpec\x12p\n\x18\x63ustom_search_attributes\x18\x05 \x03(\x0b\x32J.temporal.api.cloud.namespace.v1.NamespaceSpec.CustomSearchAttributesEntryB\x02\x18\x01\x12_\n\x11search_attributes\x18\x08 \x03(\x0b\x32\x44.temporal.api.cloud.namespace.v1.NamespaceSpec.SearchAttributesEntry\x12\x46\n\x0c\x63odec_server\x18\x06 \x01(\x0b\x32\x30.temporal.api.cloud.namespace.v1.CodecServerSpec\x12\x41\n\tlifecycle\x18\t \x01(\x0b\x32..temporal.api.cloud.namespace.v1.LifecycleSpec\x12P\n\x11high_availability\x18\n \x01(\x0b\x32\x35.temporal.api.cloud.namespace.v1.HighAvailabilitySpec\x12\x1d\n\x15\x63onnectivity_rule_ids\x18\x0b \x03(\t\x12\x44\n\rcapacity_spec\x18\x0c \x01(\x0b\x32-.temporal.api.cloud.namespace.v1.CapacitySpec\x12>\n\x08replicas\x18\r \x03(\x0b\x32,.temporal.api.cloud.namespace.v1.ReplicaSpec\x12?\n\x08\x66\x61irness\x18\x0e \x01(\x0b\x32-.temporal.api.cloud.namespace.v1.FairnessSpec\x1a=\n\x1b\x43ustomSearchAttributesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x1a{\n\x15SearchAttributesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12Q\n\x05value\x18\x02 \x01(\x0e\x32\x42.temporal.api.cloud.namespace.v1.NamespaceSpec.SearchAttributeType:\x02\x38\x01"\xac\x02\n\x13SearchAttributeType\x12%\n!SEARCH_ATTRIBUTE_TYPE_UNSPECIFIED\x10\x00\x12\x1e\n\x1aSEARCH_ATTRIBUTE_TYPE_TEXT\x10\x01\x12!\n\x1dSEARCH_ATTRIBUTE_TYPE_KEYWORD\x10\x02\x12\x1d\n\x19SEARCH_ATTRIBUTE_TYPE_INT\x10\x03\x12 \n\x1cSEARCH_ATTRIBUTE_TYPE_DOUBLE\x10\x04\x12\x1e\n\x1aSEARCH_ATTRIBUTE_TYPE_BOOL\x10\x05\x12"\n\x1eSEARCH_ATTRIBUTE_TYPE_DATETIME\x10\x06\x12&\n"SEARCH_ATTRIBUTE_TYPE_KEYWORD_LIST\x10\x07"Q\n\tEndpoints\x12\x13\n\x0bweb_address\x18\x01 \x01(\t\x12\x19\n\x11mtls_grpc_address\x18\x02 \x01(\t\x12\x14\n\x0cgrpc_address\x18\x03 \x01(\t"*\n\x06Limits\x12 \n\x18\x61\x63tions_per_second_limit\x18\x01 \x01(\x05"X\n\x12\x41WSPrivateLinkInfo\x12\x1e\n\x16\x61llowed_principal_arns\x18\x01 \x03(\t\x12"\n\x1avpc_endpoint_service_names\x18\x02 \x03(\t"t\n\x13PrivateConnectivity\x12\x0e\n\x06region\x18\x01 \x01(\t\x12M\n\x10\x61ws_private_link\x18\x02 \x01(\x0b\x32\x33.temporal.api.cloud.namespace.v1.AWSPrivateLinkInfo"\xc3\x08\n\tNamespace\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x18\n\x10resource_version\x18\x02 \x01(\t\x12<\n\x04spec\x18\x03 \x01(\x0b\x32..temporal.api.cloud.namespace.v1.NamespaceSpec\x12\x1c\n\x10state_deprecated\x18\x04 \x01(\tB\x02\x18\x01\x12<\n\x05state\x18\r \x01(\x0e\x32-.temporal.api.cloud.resource.v1.ResourceState\x12\x1a\n\x12\x61sync_operation_id\x18\x05 \x01(\t\x12=\n\tendpoints\x18\x06 \x01(\x0b\x32*.temporal.api.cloud.namespace.v1.Endpoints\x12\x15\n\ractive_region\x18\x07 \x01(\t\x12\x37\n\x06limits\x18\x08 \x01(\x0b\x32\'.temporal.api.cloud.namespace.v1.Limits\x12T\n\x16private_connectivities\x18\t \x03(\x0b\x32\x34.temporal.api.cloud.namespace.v1.PrivateConnectivity\x12\x30\n\x0c\x63reated_time\x18\n \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x36\n\x12last_modified_time\x18\x0b \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12W\n\rregion_status\x18\x0c \x03(\x0b\x32<.temporal.api.cloud.namespace.v1.Namespace.RegionStatusEntryB\x02\x18\x01\x12T\n\x12\x63onnectivity_rules\x18\x0e \x03(\x0b\x32\x38.temporal.api.cloud.connectivityrule.v1.ConnectivityRule\x12\x42\n\x04tags\x18\x0f \x03(\x0b\x32\x34.temporal.api.cloud.namespace.v1.Namespace.TagsEntry\x12;\n\x08\x63\x61pacity\x18\x10 \x01(\x0b\x32).temporal.api.cloud.namespace.v1.Capacity\x12:\n\x08replicas\x18\x12 \x03(\x0b\x32(.temporal.api.cloud.namespace.v1.Replica\x1ak\n\x11RegionStatusEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x45\n\x05value\x18\x02 \x01(\x0b\x32\x36.temporal.api.cloud.namespace.v1.NamespaceRegionStatus:\x02\x38\x01\x1a+\n\tTagsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01"\x9b\x02\n\x15NamespaceRegionStatus\x12\x1c\n\x10state_deprecated\x18\x01 \x01(\tB\x02\x18\x01\x12K\n\x05state\x18\x03 \x01(\x0e\x32<.temporal.api.cloud.namespace.v1.NamespaceRegionStatus.State\x12\x1a\n\x12\x61sync_operation_id\x18\x02 \x01(\t"{\n\x05State\x12\x15\n\x11STATE_UNSPECIFIED\x10\x00\x12\x10\n\x0cSTATE_ADDING\x10\x01\x12\x10\n\x0cSTATE_ACTIVE\x10\x02\x12\x11\n\rSTATE_PASSIVE\x10\x03\x12\x12\n\x0eSTATE_REMOVING\x10\x04\x12\x10\n\x0cSTATE_FAILED\x10\x05"\x91\x01\n\x0e\x45xportSinkSpec\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x0f\n\x07\x65nabled\x18\x02 \x01(\x08\x12.\n\x02s3\x18\x03 \x01(\x0b\x32".temporal.api.cloud.sink.v1.S3Spec\x12\x30\n\x03gcs\x18\x04 \x01(\x0b\x32#.temporal.api.cloud.sink.v1.GCSSpec"\xf6\x03\n\nExportSink\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x18\n\x10resource_version\x18\x02 \x01(\t\x12<\n\x05state\x18\x03 \x01(\x0e\x32-.temporal.api.cloud.resource.v1.ResourceState\x12=\n\x04spec\x18\x04 \x01(\x0b\x32/.temporal.api.cloud.namespace.v1.ExportSinkSpec\x12\x42\n\x06health\x18\x05 \x01(\x0e\x32\x32.temporal.api.cloud.namespace.v1.ExportSink.Health\x12\x15\n\rerror_message\x18\x06 \x01(\t\x12;\n\x17latest_data_export_time\x18\x07 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12:\n\x16last_health_check_time\x18\x08 \x01(\x0b\x32\x1a.google.protobuf.Timestamp"o\n\x06Health\x12\x16\n\x12HEALTH_UNSPECIFIED\x10\x00\x12\r\n\tHEALTH_OK\x10\x01\x12\x19\n\x15HEALTH_ERROR_INTERNAL\x10\x02\x12#\n\x1fHEALTH_ERROR_USER_CONFIGURATION\x10\x03"\x9f\x06\n\x15NamespaceCapacityInfo\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x19\n\x11has_legacy_limits\x18\x02 \x01(\x08\x12\x43\n\x10\x63urrent_capacity\x18\x03 \x01(\x0b\x32).temporal.api.cloud.namespace.v1.Capacity\x12`\n\x0cmode_options\x18\x04 \x01(\x0b\x32J.temporal.api.cloud.namespace.v1.NamespaceCapacityInfo.CapacityModeOptions\x12K\n\x05stats\x18\x05 \x01(\x0b\x32<.temporal.api.cloud.namespace.v1.NamespaceCapacityInfo.Stats\x1a\xd3\x02\n\x13\x43\x61pacityModeOptions\x12k\n\x0bprovisioned\x18\x01 \x01(\x0b\x32V.temporal.api.cloud.namespace.v1.NamespaceCapacityInfo.CapacityModeOptions.Provisioned\x12\x66\n\ton_demand\x18\x02 \x01(\x0b\x32S.temporal.api.cloud.namespace.v1.NamespaceCapacityInfo.CapacityModeOptions.OnDemand\x1aH\n\x0bProvisioned\x12\x18\n\x10valid_tru_values\x18\x01 \x03(\x01\x12\x1f\n\x17max_available_tru_value\x18\x02 \x01(\x01\x1a\x1d\n\x08OnDemand\x12\x11\n\taps_limit\x18\x01 \x01(\x01\x1a\x8d\x01\n\x05Stats\x12Q\n\x03\x61ps\x18\x01 \x01(\x0b\x32\x44.temporal.api.cloud.namespace.v1.NamespaceCapacityInfo.Stats.Summary\x1a\x31\n\x07Summary\x12\x0c\n\x04mean\x18\x01 \x01(\x01\x12\x0b\n\x03p90\x18\x02 \x01(\x01\x12\x0b\n\x03p99\x18\x03 \x01(\x01\x42\xb1\x01\n"io.temporal.api.cloud.namespace.v1B\x0cMessageProtoP\x01Z/go.temporal.io/api/cloud/namespace/v1;namespace\xaa\x02!Temporalio.Api.Cloud.Namespace.V1\xea\x02%Temporalio::Api::Cloud::Namespace::V1b\x06proto3' ) @@ -43,6 +43,8 @@ _CODECSERVERSPEC_CUSTOMERRORMESSAGE.nested_types_by_name["ErrorMessage"] ) _HIGHAVAILABILITYSPEC = DESCRIPTOR.message_types_by_name["HighAvailabilitySpec"] +_REPLICASPEC = DESCRIPTOR.message_types_by_name["ReplicaSpec"] +_REPLICA = DESCRIPTOR.message_types_by_name["Replica"] _CAPACITYSPEC = DESCRIPTOR.message_types_by_name["CapacitySpec"] _CAPACITYSPEC_ONDEMAND = _CAPACITYSPEC.nested_types_by_name["OnDemand"] _CAPACITYSPEC_PROVISIONED = _CAPACITYSPEC.nested_types_by_name["Provisioned"] @@ -50,6 +52,7 @@ _CAPACITY_ONDEMAND = _CAPACITY.nested_types_by_name["OnDemand"] _CAPACITY_PROVISIONED = _CAPACITY.nested_types_by_name["Provisioned"] _CAPACITY_REQUEST = _CAPACITY.nested_types_by_name["Request"] +_FAIRNESSSPEC = DESCRIPTOR.message_types_by_name["FairnessSpec"] _NAMESPACESPEC = DESCRIPTOR.message_types_by_name["NamespaceSpec"] _NAMESPACESPEC_CUSTOMSEARCHATTRIBUTESENTRY = _NAMESPACESPEC.nested_types_by_name[ "CustomSearchAttributesEntry" @@ -81,6 +84,7 @@ _NAMESPACECAPACITYINFO_STATS_SUMMARY = ( _NAMESPACECAPACITYINFO_STATS.nested_types_by_name["Summary"] ) +_REPLICA_REPLICASTATE = _REPLICA.enum_types_by_name["ReplicaState"] _CAPACITY_REQUEST_STATE = _CAPACITY_REQUEST.enum_types_by_name["State"] _NAMESPACESPEC_SEARCHATTRIBUTETYPE = _NAMESPACESPEC.enum_types_by_name[ "SearchAttributeType" @@ -173,6 +177,28 @@ ) _sym_db.RegisterMessage(HighAvailabilitySpec) +ReplicaSpec = _reflection.GeneratedProtocolMessageType( + "ReplicaSpec", + (_message.Message,), + { + "DESCRIPTOR": _REPLICASPEC, + "__module__": "temporalio.api.cloud.namespace.v1.message_pb2", + # @@protoc_insertion_point(class_scope:temporal.api.cloud.namespace.v1.ReplicaSpec) + }, +) +_sym_db.RegisterMessage(ReplicaSpec) + +Replica = _reflection.GeneratedProtocolMessageType( + "Replica", + (_message.Message,), + { + "DESCRIPTOR": _REPLICA, + "__module__": "temporalio.api.cloud.namespace.v1.message_pb2", + # @@protoc_insertion_point(class_scope:temporal.api.cloud.namespace.v1.Replica) + }, +) +_sym_db.RegisterMessage(Replica) + CapacitySpec = _reflection.GeneratedProtocolMessageType( "CapacitySpec", (_message.Message,), @@ -245,6 +271,17 @@ _sym_db.RegisterMessage(Capacity.Provisioned) _sym_db.RegisterMessage(Capacity.Request) +FairnessSpec = _reflection.GeneratedProtocolMessageType( + "FairnessSpec", + (_message.Message,), + { + "DESCRIPTOR": _FAIRNESSSPEC, + "__module__": "temporalio.api.cloud.namespace.v1.message_pb2", + # @@protoc_insertion_point(class_scope:temporal.api.cloud.namespace.v1.FairnessSpec) + }, +) +_sym_db.RegisterMessage(FairnessSpec) + NamespaceSpec = _reflection.GeneratedProtocolMessageType( "NamespaceSpec", (_message.Message,), @@ -456,6 +493,8 @@ _NAMESPACESPEC_CUSTOMSEARCHATTRIBUTESENTRY._serialized_options = b"8\001" _NAMESPACESPEC_SEARCHATTRIBUTESENTRY._options = None _NAMESPACESPEC_SEARCHATTRIBUTESENTRY._serialized_options = b"8\001" + _NAMESPACESPEC.fields_by_name["regions"]._options = None + _NAMESPACESPEC.fields_by_name["regions"]._serialized_options = b"\030\001" _NAMESPACESPEC.fields_by_name["custom_search_attributes"]._options = None _NAMESPACESPEC.fields_by_name[ "custom_search_attributes" @@ -466,6 +505,8 @@ _NAMESPACE_TAGSENTRY._serialized_options = b"8\001" _NAMESPACE.fields_by_name["state_deprecated"]._options = None _NAMESPACE.fields_by_name["state_deprecated"]._serialized_options = b"\030\001" + _NAMESPACE.fields_by_name["region_status"]._options = None + _NAMESPACE.fields_by_name["region_status"]._serialized_options = b"\030\001" _NAMESPACEREGIONSTATUS.fields_by_name["state_deprecated"]._options = None _NAMESPACEREGIONSTATUS.fields_by_name[ "state_deprecated" @@ -485,65 +526,73 @@ _CODECSERVERSPEC_CUSTOMERRORMESSAGE_ERRORMESSAGE._serialized_start = 993 _CODECSERVERSPEC_CUSTOMERRORMESSAGE_ERRORMESSAGE._serialized_end = 1038 _HIGHAVAILABILITYSPEC._serialized_start = 1040 - _HIGHAVAILABILITYSPEC._serialized_end = 1096 - _CAPACITYSPEC._serialized_start = 1099 - _CAPACITYSPEC._serialized_end = 1322 - _CAPACITYSPEC_ONDEMAND._serialized_start = 1274 - _CAPACITYSPEC_ONDEMAND._serialized_end = 1284 - _CAPACITYSPEC_PROVISIONED._serialized_start = 1286 - _CAPACITYSPEC_PROVISIONED._serialized_end = 1314 - _CAPACITY._serialized_start = 1325 - _CAPACITY._serialized_end = 2057 - _CAPACITY_ONDEMAND._serialized_start = 1274 - _CAPACITY_ONDEMAND._serialized_end = 1284 - _CAPACITY_PROVISIONED._serialized_start = 1575 - _CAPACITY_PROVISIONED._serialized_end = 1611 - _CAPACITY_REQUEST._serialized_start = 1614 - _CAPACITY_REQUEST._serialized_end = 2041 - _CAPACITY_REQUEST_STATE._serialized_start = 1881 - _CAPACITY_REQUEST_STATE._serialized_end = 2041 - _NAMESPACESPEC._serialized_start = 2060 - _NAMESPACESPEC._serialized_end = 3291 - _NAMESPACESPEC_CUSTOMSEARCHATTRIBUTESENTRY._serialized_start = 2802 - _NAMESPACESPEC_CUSTOMSEARCHATTRIBUTESENTRY._serialized_end = 2863 - _NAMESPACESPEC_SEARCHATTRIBUTESENTRY._serialized_start = 2865 - _NAMESPACESPEC_SEARCHATTRIBUTESENTRY._serialized_end = 2988 - _NAMESPACESPEC_SEARCHATTRIBUTETYPE._serialized_start = 2991 - _NAMESPACESPEC_SEARCHATTRIBUTETYPE._serialized_end = 3291 - _ENDPOINTS._serialized_start = 3293 - _ENDPOINTS._serialized_end = 3374 - _LIMITS._serialized_start = 3376 - _LIMITS._serialized_end = 3418 - _AWSPRIVATELINKINFO._serialized_start = 3420 - _AWSPRIVATELINKINFO._serialized_end = 3508 - _PRIVATECONNECTIVITY._serialized_start = 3510 - _PRIVATECONNECTIVITY._serialized_end = 3626 - _NAMESPACE._serialized_start = 3629 - _NAMESPACE._serialized_end = 4656 - _NAMESPACE_REGIONSTATUSENTRY._serialized_start = 4504 - _NAMESPACE_REGIONSTATUSENTRY._serialized_end = 4611 - _NAMESPACE_TAGSENTRY._serialized_start = 4613 - _NAMESPACE_TAGSENTRY._serialized_end = 4656 - _NAMESPACEREGIONSTATUS._serialized_start = 4659 - _NAMESPACEREGIONSTATUS._serialized_end = 4942 - _NAMESPACEREGIONSTATUS_STATE._serialized_start = 4819 - _NAMESPACEREGIONSTATUS_STATE._serialized_end = 4942 - _EXPORTSINKSPEC._serialized_start = 4945 - _EXPORTSINKSPEC._serialized_end = 5090 - _EXPORTSINK._serialized_start = 5093 - _EXPORTSINK._serialized_end = 5595 - _EXPORTSINK_HEALTH._serialized_start = 5484 - _EXPORTSINK_HEALTH._serialized_end = 5595 - _NAMESPACECAPACITYINFO._serialized_start = 5598 - _NAMESPACECAPACITYINFO._serialized_end = 6397 - _NAMESPACECAPACITYINFO_CAPACITYMODEOPTIONS._serialized_start = 5914 - _NAMESPACECAPACITYINFO_CAPACITYMODEOPTIONS._serialized_end = 6253 - _NAMESPACECAPACITYINFO_CAPACITYMODEOPTIONS_PROVISIONED._serialized_start = 6150 - _NAMESPACECAPACITYINFO_CAPACITYMODEOPTIONS_PROVISIONED._serialized_end = 6222 - _NAMESPACECAPACITYINFO_CAPACITYMODEOPTIONS_ONDEMAND._serialized_start = 6224 - _NAMESPACECAPACITYINFO_CAPACITYMODEOPTIONS_ONDEMAND._serialized_end = 6253 - _NAMESPACECAPACITYINFO_STATS._serialized_start = 6256 - _NAMESPACECAPACITYINFO_STATS._serialized_end = 6397 - _NAMESPACECAPACITYINFO_STATS_SUMMARY._serialized_start = 6348 - _NAMESPACECAPACITYINFO_STATS_SUMMARY._serialized_end = 6397 + _HIGHAVAILABILITYSPEC._serialized_end = 1139 + _REPLICASPEC._serialized_start = 1141 + _REPLICASPEC._serialized_end = 1170 + _REPLICA._serialized_start = 1173 + _REPLICA._serialized_end = 1454 + _REPLICA_REPLICASTATE._serialized_start = 1303 + _REPLICA_REPLICASTATE._serialized_end = 1454 + _CAPACITYSPEC._serialized_start = 1457 + _CAPACITYSPEC._serialized_end = 1680 + _CAPACITYSPEC_ONDEMAND._serialized_start = 1632 + _CAPACITYSPEC_ONDEMAND._serialized_end = 1642 + _CAPACITYSPEC_PROVISIONED._serialized_start = 1644 + _CAPACITYSPEC_PROVISIONED._serialized_end = 1672 + _CAPACITY._serialized_start = 1683 + _CAPACITY._serialized_end = 2415 + _CAPACITY_ONDEMAND._serialized_start = 1632 + _CAPACITY_ONDEMAND._serialized_end = 1642 + _CAPACITY_PROVISIONED._serialized_start = 1933 + _CAPACITY_PROVISIONED._serialized_end = 1969 + _CAPACITY_REQUEST._serialized_start = 1972 + _CAPACITY_REQUEST._serialized_end = 2399 + _CAPACITY_REQUEST_STATE._serialized_start = 2239 + _CAPACITY_REQUEST_STATE._serialized_end = 2399 + _FAIRNESSSPEC._serialized_start = 2417 + _FAIRNESSSPEC._serialized_end = 2468 + _NAMESPACESPEC._serialized_start = 2471 + _NAMESPACESPEC._serialized_end = 3835 + _NAMESPACESPEC_CUSTOMSEARCHATTRIBUTESENTRY._serialized_start = 3346 + _NAMESPACESPEC_CUSTOMSEARCHATTRIBUTESENTRY._serialized_end = 3407 + _NAMESPACESPEC_SEARCHATTRIBUTESENTRY._serialized_start = 3409 + _NAMESPACESPEC_SEARCHATTRIBUTESENTRY._serialized_end = 3532 + _NAMESPACESPEC_SEARCHATTRIBUTETYPE._serialized_start = 3535 + _NAMESPACESPEC_SEARCHATTRIBUTETYPE._serialized_end = 3835 + _ENDPOINTS._serialized_start = 3837 + _ENDPOINTS._serialized_end = 3918 + _LIMITS._serialized_start = 3920 + _LIMITS._serialized_end = 3962 + _AWSPRIVATELINKINFO._serialized_start = 3964 + _AWSPRIVATELINKINFO._serialized_end = 4052 + _PRIVATECONNECTIVITY._serialized_start = 4054 + _PRIVATECONNECTIVITY._serialized_end = 4170 + _NAMESPACE._serialized_start = 4173 + _NAMESPACE._serialized_end = 5264 + _NAMESPACE_REGIONSTATUSENTRY._serialized_start = 5112 + _NAMESPACE_REGIONSTATUSENTRY._serialized_end = 5219 + _NAMESPACE_TAGSENTRY._serialized_start = 5221 + _NAMESPACE_TAGSENTRY._serialized_end = 5264 + _NAMESPACEREGIONSTATUS._serialized_start = 5267 + _NAMESPACEREGIONSTATUS._serialized_end = 5550 + _NAMESPACEREGIONSTATUS_STATE._serialized_start = 5427 + _NAMESPACEREGIONSTATUS_STATE._serialized_end = 5550 + _EXPORTSINKSPEC._serialized_start = 5553 + _EXPORTSINKSPEC._serialized_end = 5698 + _EXPORTSINK._serialized_start = 5701 + _EXPORTSINK._serialized_end = 6203 + _EXPORTSINK_HEALTH._serialized_start = 6092 + _EXPORTSINK_HEALTH._serialized_end = 6203 + _NAMESPACECAPACITYINFO._serialized_start = 6206 + _NAMESPACECAPACITYINFO._serialized_end = 7005 + _NAMESPACECAPACITYINFO_CAPACITYMODEOPTIONS._serialized_start = 6522 + _NAMESPACECAPACITYINFO_CAPACITYMODEOPTIONS._serialized_end = 6861 + _NAMESPACECAPACITYINFO_CAPACITYMODEOPTIONS_PROVISIONED._serialized_start = 6758 + _NAMESPACECAPACITYINFO_CAPACITYMODEOPTIONS_PROVISIONED._serialized_end = 6830 + _NAMESPACECAPACITYINFO_CAPACITYMODEOPTIONS_ONDEMAND._serialized_start = 6832 + _NAMESPACECAPACITYINFO_CAPACITYMODEOPTIONS_ONDEMAND._serialized_end = 6861 + _NAMESPACECAPACITYINFO_STATS._serialized_start = 6864 + _NAMESPACECAPACITYINFO_STATS._serialized_end = 7005 + _NAMESPACECAPACITYINFO_STATS_SUMMARY._serialized_start = 6956 + _NAMESPACECAPACITYINFO_STATS_SUMMARY._serialized_end = 7005 # @@protoc_insertion_point(module_scope) diff --git a/temporalio/api/cloud/namespace/v1/message_pb2.pyi b/temporalio/api/cloud/namespace/v1/message_pb2.pyi index 147e50616..b2cbe49d8 100644 --- a/temporalio/api/cloud/namespace/v1/message_pb2.pyi +++ b/temporalio/api/cloud/namespace/v1/message_pb2.pyi @@ -265,22 +265,128 @@ class HighAvailabilitySpec(google.protobuf.message.Message): DESCRIPTOR: google.protobuf.descriptor.Descriptor DISABLE_MANAGED_FAILOVER_FIELD_NUMBER: builtins.int + DISABLE_PASSIVE_POLLER_FORWARDING_FIELD_NUMBER: builtins.int disable_managed_failover: builtins.bool """Flag to disable managed failover for the namespace.""" + disable_passive_poller_forwarding: builtins.bool + """Flag to disable passive poller forwarding for this namespace. + temporal:versioning:min_version=v0.13.0 + """ def __init__( self, *, disable_managed_failover: builtins.bool = ..., + disable_passive_poller_forwarding: builtins.bool = ..., ) -> None: ... def ClearField( self, field_name: typing_extensions.Literal[ - "disable_managed_failover", b"disable_managed_failover" + "disable_managed_failover", + b"disable_managed_failover", + "disable_passive_poller_forwarding", + b"disable_passive_poller_forwarding", ], ) -> None: ... global___HighAvailabilitySpec = HighAvailabilitySpec +class ReplicaSpec(google.protobuf.message.Message): + """temporal:versioning:min_version=v0.13.0""" + + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + REGION_FIELD_NUMBER: builtins.int + region: builtins.str + """The id of the region where the replica should be placed. + The GetRegions API can be used to get the list of valid region ids. + All the replicas must adhere to the region's max_in_region_replicas limit and connectable_region_ids. + Required. Immutable. + Example: "aws-us-west-2". + """ + def __init__( + self, + *, + region: builtins.str = ..., + ) -> None: ... + def ClearField( + self, field_name: typing_extensions.Literal["region", b"region"] + ) -> None: ... + +global___ReplicaSpec = ReplicaSpec + +class Replica(google.protobuf.message.Message): + """temporal:versioning:min_version=v0.13.0""" + + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + class _ReplicaState: + ValueType = typing.NewType("ValueType", builtins.int) + V: typing_extensions.TypeAlias = ValueType + + class _ReplicaStateEnumTypeWrapper( + google.protobuf.internal.enum_type_wrapper._EnumTypeWrapper[ + Replica._ReplicaState.ValueType + ], + builtins.type, + ): # noqa: F821 + DESCRIPTOR: google.protobuf.descriptor.EnumDescriptor + REPLICA_STATE_UNSPECIFIED: Replica._ReplicaState.ValueType # 0 + REPLICA_STATE_ADDING: Replica._ReplicaState.ValueType # 1 + """This replica is currently being added to the namespace.""" + REPLICA_STATE_ACTIVE: Replica._ReplicaState.ValueType # 2 + """This replica is healthy and active.""" + REPLICA_STATE_REMOVING: Replica._ReplicaState.ValueType # 3 + """This replica is currently being removed from the namespace.""" + REPLICA_STATE_FAILED: Replica._ReplicaState.ValueType # 5 + """This replica is in a failed state, reach out to Temporal Cloud support for remediation.""" + + class ReplicaState(_ReplicaState, metaclass=_ReplicaStateEnumTypeWrapper): ... + REPLICA_STATE_UNSPECIFIED: Replica.ReplicaState.ValueType # 0 + REPLICA_STATE_ADDING: Replica.ReplicaState.ValueType # 1 + """This replica is currently being added to the namespace.""" + REPLICA_STATE_ACTIVE: Replica.ReplicaState.ValueType # 2 + """This replica is healthy and active.""" + REPLICA_STATE_REMOVING: Replica.ReplicaState.ValueType # 3 + """This replica is currently being removed from the namespace.""" + REPLICA_STATE_FAILED: Replica.ReplicaState.ValueType # 5 + """This replica is in a failed state, reach out to Temporal Cloud support for remediation.""" + + ID_FIELD_NUMBER: builtins.int + IS_PRIMARY_FIELD_NUMBER: builtins.int + STATE_FIELD_NUMBER: builtins.int + REGION_FIELD_NUMBER: builtins.int + id: builtins.str + """The id of the replica. This is generated by Temporal after a replica is created.""" + is_primary: builtins.bool + """Whether this replica is currently the primary one.""" + state: global___Replica.ReplicaState.ValueType + """The current state of this replica.""" + region: builtins.str + """The cloud provider and region of this replica.""" + def __init__( + self, + *, + id: builtins.str = ..., + is_primary: builtins.bool = ..., + state: global___Replica.ReplicaState.ValueType = ..., + region: builtins.str = ..., + ) -> None: ... + def ClearField( + self, + field_name: typing_extensions.Literal[ + "id", + b"id", + "is_primary", + b"is_primary", + "region", + b"region", + "state", + b"state", + ], + ) -> None: ... + +global___Replica = Replica + class CapacitySpec(google.protobuf.message.Message): """temporal:versioning:min_version=v0.10.0""" @@ -495,6 +601,26 @@ class Capacity(google.protobuf.message.Message): global___Capacity = Capacity +class FairnessSpec(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + TASK_QUEUE_FAIRNESS_ENABLED_FIELD_NUMBER: builtins.int + task_queue_fairness_enabled: builtins.bool + """Flag to enable task queue fairness for the namespace (default: disabled).""" + def __init__( + self, + *, + task_queue_fairness_enabled: builtins.bool = ..., + ) -> None: ... + def ClearField( + self, + field_name: typing_extensions.Literal[ + "task_queue_fairness_enabled", b"task_queue_fairness_enabled" + ], + ) -> None: ... + +global___FairnessSpec = FairnessSpec + class NamespaceSpec(google.protobuf.message.Message): DESCRIPTOR: google.protobuf.descriptor.Descriptor @@ -584,6 +710,8 @@ class NamespaceSpec(google.protobuf.message.Message): HIGH_AVAILABILITY_FIELD_NUMBER: builtins.int CONNECTIVITY_RULE_IDS_FIELD_NUMBER: builtins.int CAPACITY_SPEC_FIELD_NUMBER: builtins.int + REPLICAS_FIELD_NUMBER: builtins.int + FAIRNESS_FIELD_NUMBER: builtins.int name: builtins.str """The name to use for the namespace. This will create a namespace that's available at '..tmprl.cloud:7233'. @@ -601,6 +729,8 @@ class NamespaceSpec(google.protobuf.message.Message): Number of supported regions is 2. The regions is immutable. Once set, it cannot be changed. Example: ["aws-us-west-2"]. + Deprecated: Use replicas field instead. + temporal:versioning:max_version=v0.15.0 """ retention_days: builtins.int """The number of days the workflows data will be retained for. @@ -675,6 +805,26 @@ class NamespaceSpec(google.protobuf.message.Message): Can be changed only when the last capacity request is not in progress. temporal:versioning:min_version=v0.10.0 """ + @property + def replicas( + self, + ) -> google.protobuf.internal.containers.RepeatedCompositeFieldContainer[ + global___ReplicaSpec + ]: + """The replication configuration for the namespace. + At least one replica must be specified. + Only one replica can be marked to be the desired active one. + The status of each replica is available in the Namespace.replicas field. + Use HighAvailabilitySpec to set the preferred primary replica ID. + If the preferred primary replica ID is not set, the first replica in this replicas list will be the preferred primary. + temporal:versioning:min_version=v0.13.0 + """ + @property + def fairness(self) -> global___FairnessSpec: + """The fairness configuration for the namespace. + If unspecified, fairness features will be disabled. + temporal:versioning:min_version=v0.14.0 + """ def __init__( self, *, @@ -694,6 +844,8 @@ class NamespaceSpec(google.protobuf.message.Message): high_availability: global___HighAvailabilitySpec | None = ..., connectivity_rule_ids: collections.abc.Iterable[builtins.str] | None = ..., capacity_spec: global___CapacitySpec | None = ..., + replicas: collections.abc.Iterable[global___ReplicaSpec] | None = ..., + fairness: global___FairnessSpec | None = ..., ) -> None: ... def HasField( self, @@ -704,6 +856,8 @@ class NamespaceSpec(google.protobuf.message.Message): b"capacity_spec", "codec_server", b"codec_server", + "fairness", + b"fairness", "high_availability", b"high_availability", "lifecycle", @@ -725,6 +879,8 @@ class NamespaceSpec(google.protobuf.message.Message): b"connectivity_rule_ids", "custom_search_attributes", b"custom_search_attributes", + "fairness", + b"fairness", "high_availability", b"high_availability", "lifecycle", @@ -735,6 +891,8 @@ class NamespaceSpec(google.protobuf.message.Message): b"name", "regions", b"regions", + "replicas", + b"replicas", "retention_days", b"retention_days", "search_attributes", @@ -922,6 +1080,7 @@ class Namespace(google.protobuf.message.Message): CONNECTIVITY_RULES_FIELD_NUMBER: builtins.int TAGS_FIELD_NUMBER: builtins.int CAPACITY_FIELD_NUMBER: builtins.int + REPLICAS_FIELD_NUMBER: builtins.int namespace: builtins.str """The namespace identifier.""" resource_version: builtins.str @@ -975,6 +1134,8 @@ class Namespace(google.protobuf.message.Message): ]: """The status of each region where the namespace is available. The id of the region is the key and the status is the value of the map. + deprecated: Use replicas field instead. + temporal:versioning:max_version=v0.15.0 """ @property def connectivity_rules( @@ -991,6 +1152,15 @@ class Namespace(google.protobuf.message.Message): @property def capacity(self) -> global___Capacity: """The status of namespace's capacity, if any.""" + @property + def replicas( + self, + ) -> google.protobuf.internal.containers.RepeatedCompositeFieldContainer[ + global___Replica + ]: + """The status of each replica where the namespace is available. + temporal:versioning:min_version=v0.13.0 + """ def __init__( self, *, @@ -1017,6 +1187,7 @@ class Namespace(google.protobuf.message.Message): | None = ..., tags: collections.abc.Mapping[builtins.str, builtins.str] | None = ..., capacity: global___Capacity | None = ..., + replicas: collections.abc.Iterable[global___Replica] | None = ..., ) -> None: ... def HasField( self, @@ -1060,6 +1231,8 @@ class Namespace(google.protobuf.message.Message): b"private_connectivities", "region_status", b"region_status", + "replicas", + b"replicas", "resource_version", b"resource_version", "spec", diff --git a/temporalio/api/namespace/v1/message_pb2.py b/temporalio/api/namespace/v1/message_pb2.py index 31f6941f2..b0f0b6bff 100644 --- a/temporalio/api/namespace/v1/message_pb2.py +++ b/temporalio/api/namespace/v1/message_pb2.py @@ -22,7 +22,7 @@ ) DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile( - b'\n\'temporal/api/namespace/v1/message.proto\x12\x19temporal.api.namespace.v1\x1a\x1egoogle/protobuf/duration.proto\x1a\x1fgoogle/protobuf/timestamp.proto\x1a%temporal/api/enums/v1/namespace.proto"\x88\x06\n\rNamespaceInfo\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x34\n\x05state\x18\x02 \x01(\x0e\x32%.temporal.api.enums.v1.NamespaceState\x12\x13\n\x0b\x64\x65scription\x18\x03 \x01(\t\x12\x13\n\x0bowner_email\x18\x04 \x01(\t\x12@\n\x04\x64\x61ta\x18\x05 \x03(\x0b\x32\x32.temporal.api.namespace.v1.NamespaceInfo.DataEntry\x12\n\n\x02id\x18\x06 \x01(\t\x12K\n\x0c\x63\x61pabilities\x18\x07 \x01(\x0b\x32\x35.temporal.api.namespace.v1.NamespaceInfo.Capabilities\x12?\n\x06limits\x18\x08 \x01(\x0b\x32/.temporal.api.namespace.v1.NamespaceInfo.Limits\x12\x1a\n\x12supports_schedules\x18\x64 \x01(\x08\x1a+\n\tDataEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x1a\x9b\x02\n\x0c\x43\x61pabilities\x12\x1c\n\x14\x65\x61ger_workflow_start\x18\x01 \x01(\x08\x12\x13\n\x0bsync_update\x18\x02 \x01(\x08\x12\x14\n\x0c\x61sync_update\x18\x03 \x01(\x08\x12\x19\n\x11worker_heartbeats\x18\x04 \x01(\x08\x12*\n"reported_problems_search_attribute\x18\x05 \x01(\x08\x12\x16\n\x0eworkflow_pause\x18\x06 \x01(\x08\x12\x1d\n\x15standalone_activities\x18\x07 \x01(\x08\x12(\n worker_poll_complete_on_shutdown\x18\x08 \x01(\x08\x12\x1a\n\x12poller_autoscaling\x18\t \x01(\x08\x1a\x46\n\x06Limits\x12\x1d\n\x15\x62lob_size_limit_error\x18\x01 \x01(\x03\x12\x1d\n\x15memo_size_limit_error\x18\x02 \x01(\x03"\x9e\x04\n\x0fNamespaceConfig\x12\x43\n workflow_execution_retention_ttl\x18\x01 \x01(\x0b\x32\x19.google.protobuf.Duration\x12<\n\x0c\x62\x61\x64_binaries\x18\x02 \x01(\x0b\x32&.temporal.api.namespace.v1.BadBinaries\x12\x44\n\x16history_archival_state\x18\x03 \x01(\x0e\x32$.temporal.api.enums.v1.ArchivalState\x12\x1c\n\x14history_archival_uri\x18\x04 \x01(\t\x12G\n\x19visibility_archival_state\x18\x05 \x01(\x0e\x32$.temporal.api.enums.v1.ArchivalState\x12\x1f\n\x17visibility_archival_uri\x18\x06 \x01(\t\x12u\n\x1f\x63ustom_search_attribute_aliases\x18\x07 \x03(\x0b\x32L.temporal.api.namespace.v1.NamespaceConfig.CustomSearchAttributeAliasesEntry\x1a\x43\n!CustomSearchAttributeAliasesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01"\xb0\x01\n\x0b\x42\x61\x64\x42inaries\x12\x46\n\x08\x62inaries\x18\x01 \x03(\x0b\x32\x34.temporal.api.namespace.v1.BadBinaries.BinariesEntry\x1aY\n\rBinariesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x37\n\x05value\x18\x02 \x01(\x0b\x32(.temporal.api.namespace.v1.BadBinaryInfo:\x02\x38\x01"b\n\rBadBinaryInfo\x12\x0e\n\x06reason\x18\x01 \x01(\t\x12\x10\n\x08operator\x18\x02 \x01(\t\x12/\n\x0b\x63reate_time\x18\x03 \x01(\x0b\x32\x1a.google.protobuf.Timestamp"\xea\x01\n\x13UpdateNamespaceInfo\x12\x13\n\x0b\x64\x65scription\x18\x01 \x01(\t\x12\x13\n\x0bowner_email\x18\x02 \x01(\t\x12\x46\n\x04\x64\x61ta\x18\x03 \x03(\x0b\x32\x38.temporal.api.namespace.v1.UpdateNamespaceInfo.DataEntry\x12\x34\n\x05state\x18\x04 \x01(\x0e\x32%.temporal.api.enums.v1.NamespaceState\x1a+\n\tDataEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01"*\n\x0fNamespaceFilter\x12\x17\n\x0finclude_deleted\x18\x01 \x01(\x08\x42\x98\x01\n\x1cio.temporal.api.namespace.v1B\x0cMessageProtoP\x01Z)go.temporal.io/api/namespace/v1;namespace\xaa\x02\x1bTemporalio.Api.Namespace.V1\xea\x02\x1eTemporalio::Api::Namespace::V1b\x06proto3' + b'\n\'temporal/api/namespace/v1/message.proto\x12\x19temporal.api.namespace.v1\x1a\x1egoogle/protobuf/duration.proto\x1a\x1fgoogle/protobuf/timestamp.proto\x1a%temporal/api/enums/v1/namespace.proto"\xa1\x06\n\rNamespaceInfo\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x34\n\x05state\x18\x02 \x01(\x0e\x32%.temporal.api.enums.v1.NamespaceState\x12\x13\n\x0b\x64\x65scription\x18\x03 \x01(\t\x12\x13\n\x0bowner_email\x18\x04 \x01(\t\x12@\n\x04\x64\x61ta\x18\x05 \x03(\x0b\x32\x32.temporal.api.namespace.v1.NamespaceInfo.DataEntry\x12\n\n\x02id\x18\x06 \x01(\t\x12K\n\x0c\x63\x61pabilities\x18\x07 \x01(\x0b\x32\x35.temporal.api.namespace.v1.NamespaceInfo.Capabilities\x12?\n\x06limits\x18\x08 \x01(\x0b\x32/.temporal.api.namespace.v1.NamespaceInfo.Limits\x12\x1a\n\x12supports_schedules\x18\x64 \x01(\x08\x1a+\n\tDataEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x1a\xb4\x02\n\x0c\x43\x61pabilities\x12\x1c\n\x14\x65\x61ger_workflow_start\x18\x01 \x01(\x08\x12\x13\n\x0bsync_update\x18\x02 \x01(\x08\x12\x14\n\x0c\x61sync_update\x18\x03 \x01(\x08\x12\x19\n\x11worker_heartbeats\x18\x04 \x01(\x08\x12*\n"reported_problems_search_attribute\x18\x05 \x01(\x08\x12\x16\n\x0eworkflow_pause\x18\x06 \x01(\x08\x12\x1d\n\x15standalone_activities\x18\x07 \x01(\x08\x12(\n worker_poll_complete_on_shutdown\x18\x08 \x01(\x08\x12\x1a\n\x12poller_autoscaling\x18\t \x01(\x08\x12\x17\n\x0fworker_commands\x18\n \x01(\x08\x1a\x46\n\x06Limits\x12\x1d\n\x15\x62lob_size_limit_error\x18\x01 \x01(\x03\x12\x1d\n\x15memo_size_limit_error\x18\x02 \x01(\x03"\x9e\x04\n\x0fNamespaceConfig\x12\x43\n workflow_execution_retention_ttl\x18\x01 \x01(\x0b\x32\x19.google.protobuf.Duration\x12<\n\x0c\x62\x61\x64_binaries\x18\x02 \x01(\x0b\x32&.temporal.api.namespace.v1.BadBinaries\x12\x44\n\x16history_archival_state\x18\x03 \x01(\x0e\x32$.temporal.api.enums.v1.ArchivalState\x12\x1c\n\x14history_archival_uri\x18\x04 \x01(\t\x12G\n\x19visibility_archival_state\x18\x05 \x01(\x0e\x32$.temporal.api.enums.v1.ArchivalState\x12\x1f\n\x17visibility_archival_uri\x18\x06 \x01(\t\x12u\n\x1f\x63ustom_search_attribute_aliases\x18\x07 \x03(\x0b\x32L.temporal.api.namespace.v1.NamespaceConfig.CustomSearchAttributeAliasesEntry\x1a\x43\n!CustomSearchAttributeAliasesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01"\xb0\x01\n\x0b\x42\x61\x64\x42inaries\x12\x46\n\x08\x62inaries\x18\x01 \x03(\x0b\x32\x34.temporal.api.namespace.v1.BadBinaries.BinariesEntry\x1aY\n\rBinariesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x37\n\x05value\x18\x02 \x01(\x0b\x32(.temporal.api.namespace.v1.BadBinaryInfo:\x02\x38\x01"b\n\rBadBinaryInfo\x12\x0e\n\x06reason\x18\x01 \x01(\t\x12\x10\n\x08operator\x18\x02 \x01(\t\x12/\n\x0b\x63reate_time\x18\x03 \x01(\x0b\x32\x1a.google.protobuf.Timestamp"\xea\x01\n\x13UpdateNamespaceInfo\x12\x13\n\x0b\x64\x65scription\x18\x01 \x01(\t\x12\x13\n\x0bowner_email\x18\x02 \x01(\t\x12\x46\n\x04\x64\x61ta\x18\x03 \x03(\x0b\x32\x38.temporal.api.namespace.v1.UpdateNamespaceInfo.DataEntry\x12\x34\n\x05state\x18\x04 \x01(\x0e\x32%.temporal.api.enums.v1.NamespaceState\x1a+\n\tDataEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01"*\n\x0fNamespaceFilter\x12\x17\n\x0finclude_deleted\x18\x01 \x01(\x08\x42\x98\x01\n\x1cio.temporal.api.namespace.v1B\x0cMessageProtoP\x01Z)go.temporal.io/api/namespace/v1;namespace\xaa\x02\x1bTemporalio.Api.Namespace.V1\xea\x02\x1eTemporalio::Api::Namespace::V1b\x06proto3' ) @@ -178,27 +178,27 @@ _UPDATENAMESPACEINFO_DATAENTRY._options = None _UPDATENAMESPACEINFO_DATAENTRY._serialized_options = b"8\001" _NAMESPACEINFO._serialized_start = 175 - _NAMESPACEINFO._serialized_end = 951 + _NAMESPACEINFO._serialized_end = 976 _NAMESPACEINFO_DATAENTRY._serialized_start = 550 _NAMESPACEINFO_DATAENTRY._serialized_end = 593 _NAMESPACEINFO_CAPABILITIES._serialized_start = 596 - _NAMESPACEINFO_CAPABILITIES._serialized_end = 879 - _NAMESPACEINFO_LIMITS._serialized_start = 881 - _NAMESPACEINFO_LIMITS._serialized_end = 951 - _NAMESPACECONFIG._serialized_start = 954 - _NAMESPACECONFIG._serialized_end = 1496 - _NAMESPACECONFIG_CUSTOMSEARCHATTRIBUTEALIASESENTRY._serialized_start = 1429 - _NAMESPACECONFIG_CUSTOMSEARCHATTRIBUTEALIASESENTRY._serialized_end = 1496 - _BADBINARIES._serialized_start = 1499 - _BADBINARIES._serialized_end = 1675 - _BADBINARIES_BINARIESENTRY._serialized_start = 1586 - _BADBINARIES_BINARIESENTRY._serialized_end = 1675 - _BADBINARYINFO._serialized_start = 1677 - _BADBINARYINFO._serialized_end = 1775 - _UPDATENAMESPACEINFO._serialized_start = 1778 - _UPDATENAMESPACEINFO._serialized_end = 2012 + _NAMESPACEINFO_CAPABILITIES._serialized_end = 904 + _NAMESPACEINFO_LIMITS._serialized_start = 906 + _NAMESPACEINFO_LIMITS._serialized_end = 976 + _NAMESPACECONFIG._serialized_start = 979 + _NAMESPACECONFIG._serialized_end = 1521 + _NAMESPACECONFIG_CUSTOMSEARCHATTRIBUTEALIASESENTRY._serialized_start = 1454 + _NAMESPACECONFIG_CUSTOMSEARCHATTRIBUTEALIASESENTRY._serialized_end = 1521 + _BADBINARIES._serialized_start = 1524 + _BADBINARIES._serialized_end = 1700 + _BADBINARIES_BINARIESENTRY._serialized_start = 1611 + _BADBINARIES_BINARIESENTRY._serialized_end = 1700 + _BADBINARYINFO._serialized_start = 1702 + _BADBINARYINFO._serialized_end = 1800 + _UPDATENAMESPACEINFO._serialized_start = 1803 + _UPDATENAMESPACEINFO._serialized_end = 2037 _UPDATENAMESPACEINFO_DATAENTRY._serialized_start = 550 _UPDATENAMESPACEINFO_DATAENTRY._serialized_end = 593 - _NAMESPACEFILTER._serialized_start = 2014 - _NAMESPACEFILTER._serialized_end = 2056 + _NAMESPACEFILTER._serialized_start = 2039 + _NAMESPACEFILTER._serialized_end = 2081 # @@protoc_insertion_point(module_scope) diff --git a/temporalio/api/namespace/v1/message_pb2.pyi b/temporalio/api/namespace/v1/message_pb2.pyi index 951b2cb81..ff258076d 100644 --- a/temporalio/api/namespace/v1/message_pb2.pyi +++ b/temporalio/api/namespace/v1/message_pb2.pyi @@ -57,6 +57,7 @@ class NamespaceInfo(google.protobuf.message.Message): STANDALONE_ACTIVITIES_FIELD_NUMBER: builtins.int WORKER_POLL_COMPLETE_ON_SHUTDOWN_FIELD_NUMBER: builtins.int POLLER_AUTOSCALING_FIELD_NUMBER: builtins.int + WORKER_COMMANDS_FIELD_NUMBER: builtins.int eager_workflow_start: builtins.bool """True if the namespace supports eager workflow start.""" sync_update: builtins.bool @@ -80,6 +81,8 @@ class NamespaceInfo(google.protobuf.message.Message): """ poller_autoscaling: builtins.bool """True if the namespace supports poller autoscaling""" + worker_commands: builtins.bool + """True if the namespace supports worker commands (server-to-worker communication via control queues).""" def __init__( self, *, @@ -92,6 +95,7 @@ class NamespaceInfo(google.protobuf.message.Message): standalone_activities: builtins.bool = ..., worker_poll_complete_on_shutdown: builtins.bool = ..., poller_autoscaling: builtins.bool = ..., + worker_commands: builtins.bool = ..., ) -> None: ... def ClearField( self, @@ -108,6 +112,8 @@ class NamespaceInfo(google.protobuf.message.Message): b"standalone_activities", "sync_update", b"sync_update", + "worker_commands", + b"worker_commands", "worker_heartbeats", b"worker_heartbeats", "worker_poll_complete_on_shutdown", diff --git a/temporalio/api/workflow/v1/message_pb2.py b/temporalio/api/workflow/v1/message_pb2.py index 8455f8875..f88688df8 100644 --- a/temporalio/api/workflow/v1/message_pb2.py +++ b/temporalio/api/workflow/v1/message_pb2.py @@ -48,7 +48,7 @@ ) DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile( - b'\n&temporal/api/workflow/v1/message.proto\x12\x18temporal.api.workflow.v1\x1a\x1egoogle/protobuf/duration.proto\x1a\x1bgoogle/protobuf/empty.proto\x1a\x1fgoogle/protobuf/timestamp.proto\x1a google/protobuf/field_mask.proto\x1a&temporal/api/activity/v1/message.proto\x1a"temporal/api/enums/v1/common.proto\x1a&temporal/api/enums/v1/event_type.proto\x1a$temporal/api/enums/v1/workflow.proto\x1a$temporal/api/common/v1/message.proto\x1a(temporal/api/deployment/v1/message.proto\x1a%temporal/api/failure/v1/message.proto\x1a\'temporal/api/taskqueue/v1/message.proto\x1a\'temporal/api/sdk/v1/user_metadata.proto"\xf0\t\n\x15WorkflowExecutionInfo\x12<\n\texecution\x18\x01 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x32\n\x04type\x18\x02 \x01(\x0b\x32$.temporal.api.common.v1.WorkflowType\x12.\n\nstart_time\x18\x03 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12.\n\nclose_time\x18\x04 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12>\n\x06status\x18\x05 \x01(\x0e\x32..temporal.api.enums.v1.WorkflowExecutionStatus\x12\x16\n\x0ehistory_length\x18\x06 \x01(\x03\x12\x1b\n\x13parent_namespace_id\x18\x07 \x01(\t\x12\x43\n\x10parent_execution\x18\x08 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x32\n\x0e\x65xecution_time\x18\t \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12*\n\x04memo\x18\n \x01(\x0b\x32\x1c.temporal.api.common.v1.Memo\x12\x43\n\x11search_attributes\x18\x0b \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes\x12@\n\x11\x61uto_reset_points\x18\x0c \x01(\x0b\x32%.temporal.api.workflow.v1.ResetPoints\x12\x12\n\ntask_queue\x18\r \x01(\t\x12\x1e\n\x16state_transition_count\x18\x0e \x01(\x03\x12\x1a\n\x12history_size_bytes\x18\x0f \x01(\x03\x12X\n most_recent_worker_version_stamp\x18\x10 \x01(\x0b\x32*.temporal.api.common.v1.WorkerVersionStampB\x02\x18\x01\x12\x35\n\x12\x65xecution_duration\x18\x11 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x41\n\x0eroot_execution\x18\x12 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x1d\n\x11\x61ssigned_build_id\x18\x13 \x01(\tB\x02\x18\x01\x12\x1e\n\x12inherited_build_id\x18\x14 \x01(\tB\x02\x18\x01\x12\x14\n\x0c\x66irst_run_id\x18\x15 \x01(\t\x12R\n\x0fversioning_info\x18\x16 \x01(\x0b\x32\x39.temporal.api.workflow.v1.WorkflowExecutionVersioningInfo\x12\x1e\n\x16worker_deployment_name\x18\x17 \x01(\t\x12\x32\n\x08priority\x18\x18 \x01(\x0b\x32 .temporal.api.common.v1.Priority\x12#\n\x1b\x65xternal_payload_size_bytes\x18\x19 \x01(\x03\x12\x1e\n\x16\x65xternal_payload_count\x18\x1a \x01(\x03"\xc6\x04\n\x1dWorkflowExecutionExtendedInfo\x12=\n\x19\x65xecution_expiration_time\x18\x01 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x37\n\x13run_expiration_time\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x18\n\x10\x63\x61ncel_requested\x18\x03 \x01(\x08\x12\x33\n\x0flast_reset_time\x18\x04 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x37\n\x13original_start_time\x18\x05 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x14\n\x0creset_run_id\x18\x06 \x01(\t\x12\x65\n\x10request_id_infos\x18\x07 \x03(\x0b\x32K.temporal.api.workflow.v1.WorkflowExecutionExtendedInfo.RequestIdInfosEntry\x12H\n\npause_info\x18\x08 \x01(\x0b\x32\x34.temporal.api.workflow.v1.WorkflowExecutionPauseInfo\x1a^\n\x13RequestIdInfosEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x36\n\x05value\x18\x02 \x01(\x0b\x32\'.temporal.api.workflow.v1.RequestIdInfo:\x02\x38\x01"\xfb\x04\n\x1fWorkflowExecutionVersioningInfo\x12;\n\x08\x62\x65havior\x18\x01 \x01(\x0e\x32).temporal.api.enums.v1.VersioningBehavior\x12>\n\ndeployment\x18\x02 \x01(\x0b\x32&.temporal.api.deployment.v1.DeploymentB\x02\x18\x01\x12\x13\n\x07version\x18\x05 \x01(\tB\x02\x18\x01\x12O\n\x12\x64\x65ployment_version\x18\x07 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersion\x12I\n\x13versioning_override\x18\x03 \x01(\x0b\x32,.temporal.api.workflow.v1.VersioningOverride\x12Q\n\x15\x64\x65ployment_transition\x18\x04 \x01(\x0b\x32..temporal.api.workflow.v1.DeploymentTransitionB\x02\x18\x01\x12Q\n\x12version_transition\x18\x06 \x01(\x0b\x32\x35.temporal.api.workflow.v1.DeploymentVersionTransition\x12\x17\n\x0frevision_number\x18\x08 \x01(\x03\x12k\n+continue_as_new_initial_versioning_behavior\x18\t \x01(\x0e\x32\x36.temporal.api.enums.v1.ContinueAsNewVersioningBehavior"R\n\x14\x44\x65ploymentTransition\x12:\n\ndeployment\x18\x01 \x01(\x0b\x32&.temporal.api.deployment.v1.Deployment"\x83\x01\n\x1b\x44\x65ploymentVersionTransition\x12\x13\n\x07version\x18\x01 \x01(\tB\x02\x18\x01\x12O\n\x12\x64\x65ployment_version\x18\x02 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersion"\xc7\x02\n\x17WorkflowExecutionConfig\x12\x38\n\ntask_queue\x18\x01 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12=\n\x1aworkflow_execution_timeout\x18\x02 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x37\n\x14workflow_run_timeout\x18\x03 \x01(\x0b\x32\x19.google.protobuf.Duration\x12@\n\x1d\x64\x65\x66\x61ult_workflow_task_timeout\x18\x04 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x38\n\ruser_metadata\x18\x05 \x01(\x0b\x32!.temporal.api.sdk.v1.UserMetadata"\xbd\r\n\x13PendingActivityInfo\x12\x13\n\x0b\x61\x63tivity_id\x18\x01 \x01(\t\x12;\n\ractivity_type\x18\x02 \x01(\x0b\x32$.temporal.api.common.v1.ActivityType\x12:\n\x05state\x18\x03 \x01(\x0e\x32+.temporal.api.enums.v1.PendingActivityState\x12;\n\x11heartbeat_details\x18\x04 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x37\n\x13last_heartbeat_time\x18\x05 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x35\n\x11last_started_time\x18\x06 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x0f\n\x07\x61ttempt\x18\x07 \x01(\x05\x12\x18\n\x10maximum_attempts\x18\x08 \x01(\x05\x12\x32\n\x0escheduled_time\x18\t \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x33\n\x0f\x65xpiration_time\x18\n \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x36\n\x0clast_failure\x18\x0b \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12\x1c\n\x14last_worker_identity\x18\x0c \x01(\t\x12;\n\x15use_workflow_build_id\x18\r \x01(\x0b\x32\x16.google.protobuf.EmptyB\x02\x18\x01H\x00\x12\x32\n$last_independently_assigned_build_id\x18\x0e \x01(\tB\x02\x18\x01H\x00\x12Q\n\x19last_worker_version_stamp\x18\x0f \x01(\x0b\x32*.temporal.api.common.v1.WorkerVersionStampB\x02\x18\x01\x12\x39\n\x16\x63urrent_retry_interval\x18\x10 \x01(\x0b\x32\x19.google.protobuf.Duration\x12>\n\x1alast_attempt_complete_time\x18\x11 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12>\n\x1anext_attempt_schedule_time\x18\x12 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x0e\n\x06paused\x18\x13 \x01(\x08\x12\x43\n\x0flast_deployment\x18\x14 \x01(\x0b\x32&.temporal.api.deployment.v1.DeploymentB\x02\x18\x01\x12*\n\x1elast_worker_deployment_version\x18\x15 \x01(\tB\x02\x18\x01\x12T\n\x17last_deployment_version\x18\x19 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersion\x12\x32\n\x08priority\x18\x16 \x01(\x0b\x32 .temporal.api.common.v1.Priority\x12K\n\npause_info\x18\x17 \x01(\x0b\x32\x37.temporal.api.workflow.v1.PendingActivityInfo.PauseInfo\x12\x43\n\x10\x61\x63tivity_options\x18\x18 \x01(\x0b\x32).temporal.api.activity.v1.ActivityOptions\x1a\xcf\x02\n\tPauseInfo\x12.\n\npause_time\x18\x01 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12P\n\x06manual\x18\x02 \x01(\x0b\x32>.temporal.api.workflow.v1.PendingActivityInfo.PauseInfo.ManualH\x00\x12L\n\x04rule\x18\x04 \x01(\x0b\x32<.temporal.api.workflow.v1.PendingActivityInfo.PauseInfo.RuleH\x00\x1a*\n\x06Manual\x12\x10\n\x08identity\x18\x01 \x01(\t\x12\x0e\n\x06reason\x18\x02 \x01(\t\x1a\x39\n\x04Rule\x12\x0f\n\x07rule_id\x18\x01 \x01(\t\x12\x10\n\x08identity\x18\x02 \x01(\t\x12\x0e\n\x06reason\x18\x03 \x01(\tB\x0b\n\tpaused_byB\x13\n\x11\x61ssigned_build_id"\xb9\x01\n\x19PendingChildExecutionInfo\x12\x13\n\x0bworkflow_id\x18\x01 \x01(\t\x12\x0e\n\x06run_id\x18\x02 \x01(\t\x12\x1a\n\x12workflow_type_name\x18\x03 \x01(\t\x12\x14\n\x0cinitiated_id\x18\x04 \x01(\x03\x12\x45\n\x13parent_close_policy\x18\x05 \x01(\x0e\x32(.temporal.api.enums.v1.ParentClosePolicy"\x8d\x02\n\x17PendingWorkflowTaskInfo\x12>\n\x05state\x18\x01 \x01(\x0e\x32/.temporal.api.enums.v1.PendingWorkflowTaskState\x12\x32\n\x0escheduled_time\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12;\n\x17original_scheduled_time\x18\x03 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x30\n\x0cstarted_time\x18\x04 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x0f\n\x07\x61ttempt\x18\x05 \x01(\x05"G\n\x0bResetPoints\x12\x38\n\x06points\x18\x01 \x03(\x0b\x32(.temporal.api.workflow.v1.ResetPointInfo"\xef\x01\n\x0eResetPointInfo\x12\x10\n\x08\x62uild_id\x18\x07 \x01(\t\x12\x1b\n\x0f\x62inary_checksum\x18\x01 \x01(\tB\x02\x18\x01\x12\x0e\n\x06run_id\x18\x02 \x01(\t\x12(\n first_workflow_task_completed_id\x18\x03 \x01(\x03\x12/\n\x0b\x63reate_time\x18\x04 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12/\n\x0b\x65xpire_time\x18\x05 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x12\n\nresettable\x18\x06 \x01(\x08"\x85\x07\n\x18NewWorkflowExecutionInfo\x12\x13\n\x0bworkflow_id\x18\x01 \x01(\t\x12;\n\rworkflow_type\x18\x02 \x01(\x0b\x32$.temporal.api.common.v1.WorkflowType\x12\x38\n\ntask_queue\x18\x03 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12/\n\x05input\x18\x04 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12=\n\x1aworkflow_execution_timeout\x18\x05 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x37\n\x14workflow_run_timeout\x18\x06 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x38\n\x15workflow_task_timeout\x18\x07 \x01(\x0b\x32\x19.google.protobuf.Duration\x12N\n\x18workflow_id_reuse_policy\x18\x08 \x01(\x0e\x32,.temporal.api.enums.v1.WorkflowIdReusePolicy\x12\x39\n\x0cretry_policy\x18\t \x01(\x0b\x32#.temporal.api.common.v1.RetryPolicy\x12\x15\n\rcron_schedule\x18\n \x01(\t\x12*\n\x04memo\x18\x0b \x01(\x0b\x32\x1c.temporal.api.common.v1.Memo\x12\x43\n\x11search_attributes\x18\x0c \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes\x12.\n\x06header\x18\r \x01(\x0b\x32\x1e.temporal.api.common.v1.Header\x12\x38\n\ruser_metadata\x18\x0e \x01(\x0b\x32!.temporal.api.sdk.v1.UserMetadata\x12I\n\x13versioning_override\x18\x0f \x01(\x0b\x32,.temporal.api.workflow.v1.VersioningOverride\x12\x32\n\x08priority\x18\x10 \x01(\x0b\x32 .temporal.api.common.v1.Priority"\xd2\x04\n\x0c\x43\x61llbackInfo\x12\x32\n\x08\x63\x61llback\x18\x01 \x01(\x0b\x32 .temporal.api.common.v1.Callback\x12?\n\x07trigger\x18\x02 \x01(\x0b\x32..temporal.api.workflow.v1.CallbackInfo.Trigger\x12\x35\n\x11registration_time\x18\x03 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x33\n\x05state\x18\x04 \x01(\x0e\x32$.temporal.api.enums.v1.CallbackState\x12\x0f\n\x07\x61ttempt\x18\x05 \x01(\x05\x12>\n\x1alast_attempt_complete_time\x18\x06 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12>\n\x14last_attempt_failure\x18\x07 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12>\n\x1anext_attempt_schedule_time\x18\x08 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x16\n\x0e\x62locked_reason\x18\t \x01(\t\x1a\x10\n\x0eWorkflowClosed\x1a\x66\n\x07Trigger\x12P\n\x0fworkflow_closed\x18\x01 \x01(\x0b\x32\x35.temporal.api.workflow.v1.CallbackInfo.WorkflowClosedH\x00\x42\t\n\x07variant"\x8b\x06\n\x19PendingNexusOperationInfo\x12\x10\n\x08\x65ndpoint\x18\x01 \x01(\t\x12\x0f\n\x07service\x18\x02 \x01(\t\x12\x11\n\toperation\x18\x03 \x01(\t\x12\x18\n\x0coperation_id\x18\x04 \x01(\tB\x02\x18\x01\x12<\n\x19schedule_to_close_timeout\x18\x05 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x32\n\x0escheduled_time\x18\x06 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12@\n\x05state\x18\x07 \x01(\x0e\x32\x31.temporal.api.enums.v1.PendingNexusOperationState\x12\x0f\n\x07\x61ttempt\x18\x08 \x01(\x05\x12>\n\x1alast_attempt_complete_time\x18\t \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12>\n\x14last_attempt_failure\x18\n \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12>\n\x1anext_attempt_schedule_time\x18\x0b \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12S\n\x11\x63\x61ncellation_info\x18\x0c \x01(\x0b\x32\x38.temporal.api.workflow.v1.NexusOperationCancellationInfo\x12\x1a\n\x12scheduled_event_id\x18\r \x01(\x03\x12\x16\n\x0e\x62locked_reason\x18\x0e \x01(\t\x12\x17\n\x0foperation_token\x18\x0f \x01(\t\x12<\n\x19schedule_to_start_timeout\x18\x10 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x39\n\x16start_to_close_timeout\x18\x11 \x01(\x0b\x32\x19.google.protobuf.Duration"\x84\x03\n\x1eNexusOperationCancellationInfo\x12\x32\n\x0erequested_time\x18\x01 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x45\n\x05state\x18\x02 \x01(\x0e\x32\x36.temporal.api.enums.v1.NexusOperationCancellationState\x12\x0f\n\x07\x61ttempt\x18\x03 \x01(\x05\x12>\n\x1alast_attempt_complete_time\x18\x04 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12>\n\x14last_attempt_failure\x18\x05 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12>\n\x1anext_attempt_schedule_time\x18\x06 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x16\n\x0e\x62locked_reason\x18\x07 \x01(\t"\xe5\x01\n\x18WorkflowExecutionOptions\x12I\n\x13versioning_override\x18\x01 \x01(\x0b\x32,.temporal.api.workflow.v1.VersioningOverride\x12\x32\n\x08priority\x18\x02 \x01(\x0b\x32 .temporal.api.common.v1.Priority\x12J\n\x14time_skipping_config\x18\x03 \x01(\x0b\x32,.temporal.api.workflow.v1.TimeSkippingConfig"\xd6\x01\n\x12TimeSkippingConfig\x12\x0f\n\x07\x65nabled\x18\x01 \x01(\x08\x12\x39\n\x14max_skipped_duration\x18\x04 \x01(\x0b\x32\x19.google.protobuf.DurationH\x00\x12\x39\n\x14max_elapsed_duration\x18\x05 \x01(\x0b\x32\x19.google.protobuf.DurationH\x00\x42\x07\n\x05\x62oundJ\x04\x08\x02\x10\x03J\x04\x08\x06\x10\x07R\x13\x64isable_propagationR\x0fmax_target_time"\xbd\x04\n\x12VersioningOverride\x12M\n\x06pinned\x18\x03 \x01(\x0b\x32;.temporal.api.workflow.v1.VersioningOverride.PinnedOverrideH\x00\x12\x16\n\x0c\x61uto_upgrade\x18\x04 \x01(\x08H\x00\x12?\n\x08\x62\x65havior\x18\x01 \x01(\x0e\x32).temporal.api.enums.v1.VersioningBehaviorB\x02\x18\x01\x12>\n\ndeployment\x18\x02 \x01(\x0b\x32&.temporal.api.deployment.v1.DeploymentB\x02\x18\x01\x12\x1a\n\x0epinned_version\x18\t \x01(\tB\x02\x18\x01\x1a\xad\x01\n\x0ePinnedOverride\x12U\n\x08\x62\x65havior\x18\x01 \x01(\x0e\x32\x43.temporal.api.workflow.v1.VersioningOverride.PinnedOverrideBehavior\x12\x44\n\x07version\x18\x02 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersion"g\n\x16PinnedOverrideBehavior\x12(\n$PINNED_OVERRIDE_BEHAVIOR_UNSPECIFIED\x10\x00\x12#\n\x1fPINNED_OVERRIDE_BEHAVIOR_PINNED\x10\x01\x42\n\n\x08override"i\n\x11OnConflictOptions\x12\x19\n\x11\x61ttach_request_id\x18\x01 \x01(\x08\x12#\n\x1b\x61ttach_completion_callbacks\x18\x02 \x01(\x08\x12\x14\n\x0c\x61ttach_links\x18\x03 \x01(\x08"i\n\rRequestIdInfo\x12\x34\n\nevent_type\x18\x01 \x01(\x0e\x32 .temporal.api.enums.v1.EventType\x12\x10\n\x08\x65vent_id\x18\x02 \x01(\x03\x12\x10\n\x08\x62uffered\x18\x03 \x01(\x08"\xb7\x04\n\x12PostResetOperation\x12V\n\x0fsignal_workflow\x18\x01 \x01(\x0b\x32;.temporal.api.workflow.v1.PostResetOperation.SignalWorkflowH\x00\x12\x65\n\x17update_workflow_options\x18\x02 \x01(\x0b\x32\x42.temporal.api.workflow.v1.PostResetOperation.UpdateWorkflowOptionsH\x00\x1a\xb3\x01\n\x0eSignalWorkflow\x12\x13\n\x0bsignal_name\x18\x01 \x01(\t\x12/\n\x05input\x18\x02 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12.\n\x06header\x18\x03 \x01(\x0b\x32\x1e.temporal.api.common.v1.Header\x12+\n\x05links\x18\x04 \x03(\x0b\x32\x1c.temporal.api.common.v1.Link\x1a\xa0\x01\n\x15UpdateWorkflowOptions\x12V\n\x1aworkflow_execution_options\x18\x01 \x01(\x0b\x32\x32.temporal.api.workflow.v1.WorkflowExecutionOptions\x12/\n\x0bupdate_mask\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.FieldMaskB\t\n\x07variant"o\n\x1aWorkflowExecutionPauseInfo\x12\x10\n\x08identity\x18\x01 \x01(\t\x12/\n\x0bpaused_time\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x0e\n\x06reason\x18\x03 \x01(\tB\x93\x01\n\x1bio.temporal.api.workflow.v1B\x0cMessageProtoP\x01Z\'go.temporal.io/api/workflow/v1;workflow\xaa\x02\x1aTemporalio.Api.Workflow.V1\xea\x02\x1dTemporalio::Api::Workflow::V1b\x06proto3' + b'\n&temporal/api/workflow/v1/message.proto\x12\x18temporal.api.workflow.v1\x1a\x1egoogle/protobuf/duration.proto\x1a\x1bgoogle/protobuf/empty.proto\x1a\x1fgoogle/protobuf/timestamp.proto\x1a google/protobuf/field_mask.proto\x1a&temporal/api/activity/v1/message.proto\x1a"temporal/api/enums/v1/common.proto\x1a&temporal/api/enums/v1/event_type.proto\x1a$temporal/api/enums/v1/workflow.proto\x1a$temporal/api/common/v1/message.proto\x1a(temporal/api/deployment/v1/message.proto\x1a%temporal/api/failure/v1/message.proto\x1a\'temporal/api/taskqueue/v1/message.proto\x1a\'temporal/api/sdk/v1/user_metadata.proto"\xf0\t\n\x15WorkflowExecutionInfo\x12<\n\texecution\x18\x01 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x32\n\x04type\x18\x02 \x01(\x0b\x32$.temporal.api.common.v1.WorkflowType\x12.\n\nstart_time\x18\x03 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12.\n\nclose_time\x18\x04 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12>\n\x06status\x18\x05 \x01(\x0e\x32..temporal.api.enums.v1.WorkflowExecutionStatus\x12\x16\n\x0ehistory_length\x18\x06 \x01(\x03\x12\x1b\n\x13parent_namespace_id\x18\x07 \x01(\t\x12\x43\n\x10parent_execution\x18\x08 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x32\n\x0e\x65xecution_time\x18\t \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12*\n\x04memo\x18\n \x01(\x0b\x32\x1c.temporal.api.common.v1.Memo\x12\x43\n\x11search_attributes\x18\x0b \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes\x12@\n\x11\x61uto_reset_points\x18\x0c \x01(\x0b\x32%.temporal.api.workflow.v1.ResetPoints\x12\x12\n\ntask_queue\x18\r \x01(\t\x12\x1e\n\x16state_transition_count\x18\x0e \x01(\x03\x12\x1a\n\x12history_size_bytes\x18\x0f \x01(\x03\x12X\n most_recent_worker_version_stamp\x18\x10 \x01(\x0b\x32*.temporal.api.common.v1.WorkerVersionStampB\x02\x18\x01\x12\x35\n\x12\x65xecution_duration\x18\x11 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x41\n\x0eroot_execution\x18\x12 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x1d\n\x11\x61ssigned_build_id\x18\x13 \x01(\tB\x02\x18\x01\x12\x1e\n\x12inherited_build_id\x18\x14 \x01(\tB\x02\x18\x01\x12\x14\n\x0c\x66irst_run_id\x18\x15 \x01(\t\x12R\n\x0fversioning_info\x18\x16 \x01(\x0b\x32\x39.temporal.api.workflow.v1.WorkflowExecutionVersioningInfo\x12\x1e\n\x16worker_deployment_name\x18\x17 \x01(\t\x12\x32\n\x08priority\x18\x18 \x01(\x0b\x32 .temporal.api.common.v1.Priority\x12#\n\x1b\x65xternal_payload_size_bytes\x18\x19 \x01(\x03\x12\x1e\n\x16\x65xternal_payload_count\x18\x1a \x01(\x03"\xc6\x04\n\x1dWorkflowExecutionExtendedInfo\x12=\n\x19\x65xecution_expiration_time\x18\x01 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x37\n\x13run_expiration_time\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x18\n\x10\x63\x61ncel_requested\x18\x03 \x01(\x08\x12\x33\n\x0flast_reset_time\x18\x04 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x37\n\x13original_start_time\x18\x05 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x14\n\x0creset_run_id\x18\x06 \x01(\t\x12\x65\n\x10request_id_infos\x18\x07 \x03(\x0b\x32K.temporal.api.workflow.v1.WorkflowExecutionExtendedInfo.RequestIdInfosEntry\x12H\n\npause_info\x18\x08 \x01(\x0b\x32\x34.temporal.api.workflow.v1.WorkflowExecutionPauseInfo\x1a^\n\x13RequestIdInfosEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x36\n\x05value\x18\x02 \x01(\x0b\x32\'.temporal.api.workflow.v1.RequestIdInfo:\x02\x38\x01"\xfb\x04\n\x1fWorkflowExecutionVersioningInfo\x12;\n\x08\x62\x65havior\x18\x01 \x01(\x0e\x32).temporal.api.enums.v1.VersioningBehavior\x12>\n\ndeployment\x18\x02 \x01(\x0b\x32&.temporal.api.deployment.v1.DeploymentB\x02\x18\x01\x12\x13\n\x07version\x18\x05 \x01(\tB\x02\x18\x01\x12O\n\x12\x64\x65ployment_version\x18\x07 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersion\x12I\n\x13versioning_override\x18\x03 \x01(\x0b\x32,.temporal.api.workflow.v1.VersioningOverride\x12Q\n\x15\x64\x65ployment_transition\x18\x04 \x01(\x0b\x32..temporal.api.workflow.v1.DeploymentTransitionB\x02\x18\x01\x12Q\n\x12version_transition\x18\x06 \x01(\x0b\x32\x35.temporal.api.workflow.v1.DeploymentVersionTransition\x12\x17\n\x0frevision_number\x18\x08 \x01(\x03\x12k\n+continue_as_new_initial_versioning_behavior\x18\t \x01(\x0e\x32\x36.temporal.api.enums.v1.ContinueAsNewVersioningBehavior"R\n\x14\x44\x65ploymentTransition\x12:\n\ndeployment\x18\x01 \x01(\x0b\x32&.temporal.api.deployment.v1.Deployment"\x83\x01\n\x1b\x44\x65ploymentVersionTransition\x12\x13\n\x07version\x18\x01 \x01(\tB\x02\x18\x01\x12O\n\x12\x64\x65ployment_version\x18\x02 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersion"\xc7\x02\n\x17WorkflowExecutionConfig\x12\x38\n\ntask_queue\x18\x01 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12=\n\x1aworkflow_execution_timeout\x18\x02 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x37\n\x14workflow_run_timeout\x18\x03 \x01(\x0b\x32\x19.google.protobuf.Duration\x12@\n\x1d\x64\x65\x66\x61ult_workflow_task_timeout\x18\x04 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x38\n\ruser_metadata\x18\x05 \x01(\x0b\x32!.temporal.api.sdk.v1.UserMetadata"\xbd\r\n\x13PendingActivityInfo\x12\x13\n\x0b\x61\x63tivity_id\x18\x01 \x01(\t\x12;\n\ractivity_type\x18\x02 \x01(\x0b\x32$.temporal.api.common.v1.ActivityType\x12:\n\x05state\x18\x03 \x01(\x0e\x32+.temporal.api.enums.v1.PendingActivityState\x12;\n\x11heartbeat_details\x18\x04 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x37\n\x13last_heartbeat_time\x18\x05 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x35\n\x11last_started_time\x18\x06 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x0f\n\x07\x61ttempt\x18\x07 \x01(\x05\x12\x18\n\x10maximum_attempts\x18\x08 \x01(\x05\x12\x32\n\x0escheduled_time\x18\t \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x33\n\x0f\x65xpiration_time\x18\n \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x36\n\x0clast_failure\x18\x0b \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12\x1c\n\x14last_worker_identity\x18\x0c \x01(\t\x12;\n\x15use_workflow_build_id\x18\r \x01(\x0b\x32\x16.google.protobuf.EmptyB\x02\x18\x01H\x00\x12\x32\n$last_independently_assigned_build_id\x18\x0e \x01(\tB\x02\x18\x01H\x00\x12Q\n\x19last_worker_version_stamp\x18\x0f \x01(\x0b\x32*.temporal.api.common.v1.WorkerVersionStampB\x02\x18\x01\x12\x39\n\x16\x63urrent_retry_interval\x18\x10 \x01(\x0b\x32\x19.google.protobuf.Duration\x12>\n\x1alast_attempt_complete_time\x18\x11 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12>\n\x1anext_attempt_schedule_time\x18\x12 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x0e\n\x06paused\x18\x13 \x01(\x08\x12\x43\n\x0flast_deployment\x18\x14 \x01(\x0b\x32&.temporal.api.deployment.v1.DeploymentB\x02\x18\x01\x12*\n\x1elast_worker_deployment_version\x18\x15 \x01(\tB\x02\x18\x01\x12T\n\x17last_deployment_version\x18\x19 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersion\x12\x32\n\x08priority\x18\x16 \x01(\x0b\x32 .temporal.api.common.v1.Priority\x12K\n\npause_info\x18\x17 \x01(\x0b\x32\x37.temporal.api.workflow.v1.PendingActivityInfo.PauseInfo\x12\x43\n\x10\x61\x63tivity_options\x18\x18 \x01(\x0b\x32).temporal.api.activity.v1.ActivityOptions\x1a\xcf\x02\n\tPauseInfo\x12.\n\npause_time\x18\x01 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12P\n\x06manual\x18\x02 \x01(\x0b\x32>.temporal.api.workflow.v1.PendingActivityInfo.PauseInfo.ManualH\x00\x12L\n\x04rule\x18\x04 \x01(\x0b\x32<.temporal.api.workflow.v1.PendingActivityInfo.PauseInfo.RuleH\x00\x1a*\n\x06Manual\x12\x10\n\x08identity\x18\x01 \x01(\t\x12\x0e\n\x06reason\x18\x02 \x01(\t\x1a\x39\n\x04Rule\x12\x0f\n\x07rule_id\x18\x01 \x01(\t\x12\x10\n\x08identity\x18\x02 \x01(\t\x12\x0e\n\x06reason\x18\x03 \x01(\tB\x0b\n\tpaused_byB\x13\n\x11\x61ssigned_build_id"\xb9\x01\n\x19PendingChildExecutionInfo\x12\x13\n\x0bworkflow_id\x18\x01 \x01(\t\x12\x0e\n\x06run_id\x18\x02 \x01(\t\x12\x1a\n\x12workflow_type_name\x18\x03 \x01(\t\x12\x14\n\x0cinitiated_id\x18\x04 \x01(\x03\x12\x45\n\x13parent_close_policy\x18\x05 \x01(\x0e\x32(.temporal.api.enums.v1.ParentClosePolicy"\x8d\x02\n\x17PendingWorkflowTaskInfo\x12>\n\x05state\x18\x01 \x01(\x0e\x32/.temporal.api.enums.v1.PendingWorkflowTaskState\x12\x32\n\x0escheduled_time\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12;\n\x17original_scheduled_time\x18\x03 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x30\n\x0cstarted_time\x18\x04 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x0f\n\x07\x61ttempt\x18\x05 \x01(\x05"G\n\x0bResetPoints\x12\x38\n\x06points\x18\x01 \x03(\x0b\x32(.temporal.api.workflow.v1.ResetPointInfo"\xef\x01\n\x0eResetPointInfo\x12\x10\n\x08\x62uild_id\x18\x07 \x01(\t\x12\x1b\n\x0f\x62inary_checksum\x18\x01 \x01(\tB\x02\x18\x01\x12\x0e\n\x06run_id\x18\x02 \x01(\t\x12(\n first_workflow_task_completed_id\x18\x03 \x01(\x03\x12/\n\x0b\x63reate_time\x18\x04 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12/\n\x0b\x65xpire_time\x18\x05 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x12\n\nresettable\x18\x06 \x01(\x08"\x85\x07\n\x18NewWorkflowExecutionInfo\x12\x13\n\x0bworkflow_id\x18\x01 \x01(\t\x12;\n\rworkflow_type\x18\x02 \x01(\x0b\x32$.temporal.api.common.v1.WorkflowType\x12\x38\n\ntask_queue\x18\x03 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12/\n\x05input\x18\x04 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12=\n\x1aworkflow_execution_timeout\x18\x05 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x37\n\x14workflow_run_timeout\x18\x06 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x38\n\x15workflow_task_timeout\x18\x07 \x01(\x0b\x32\x19.google.protobuf.Duration\x12N\n\x18workflow_id_reuse_policy\x18\x08 \x01(\x0e\x32,.temporal.api.enums.v1.WorkflowIdReusePolicy\x12\x39\n\x0cretry_policy\x18\t \x01(\x0b\x32#.temporal.api.common.v1.RetryPolicy\x12\x15\n\rcron_schedule\x18\n \x01(\t\x12*\n\x04memo\x18\x0b \x01(\x0b\x32\x1c.temporal.api.common.v1.Memo\x12\x43\n\x11search_attributes\x18\x0c \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes\x12.\n\x06header\x18\r \x01(\x0b\x32\x1e.temporal.api.common.v1.Header\x12\x38\n\ruser_metadata\x18\x0e \x01(\x0b\x32!.temporal.api.sdk.v1.UserMetadata\x12I\n\x13versioning_override\x18\x0f \x01(\x0b\x32,.temporal.api.workflow.v1.VersioningOverride\x12\x32\n\x08priority\x18\x10 \x01(\x0b\x32 .temporal.api.common.v1.Priority"\xd2\x04\n\x0c\x43\x61llbackInfo\x12\x32\n\x08\x63\x61llback\x18\x01 \x01(\x0b\x32 .temporal.api.common.v1.Callback\x12?\n\x07trigger\x18\x02 \x01(\x0b\x32..temporal.api.workflow.v1.CallbackInfo.Trigger\x12\x35\n\x11registration_time\x18\x03 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x33\n\x05state\x18\x04 \x01(\x0e\x32$.temporal.api.enums.v1.CallbackState\x12\x0f\n\x07\x61ttempt\x18\x05 \x01(\x05\x12>\n\x1alast_attempt_complete_time\x18\x06 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12>\n\x14last_attempt_failure\x18\x07 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12>\n\x1anext_attempt_schedule_time\x18\x08 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x16\n\x0e\x62locked_reason\x18\t \x01(\t\x1a\x10\n\x0eWorkflowClosed\x1a\x66\n\x07Trigger\x12P\n\x0fworkflow_closed\x18\x01 \x01(\x0b\x32\x35.temporal.api.workflow.v1.CallbackInfo.WorkflowClosedH\x00\x42\t\n\x07variant"\x8b\x06\n\x19PendingNexusOperationInfo\x12\x10\n\x08\x65ndpoint\x18\x01 \x01(\t\x12\x0f\n\x07service\x18\x02 \x01(\t\x12\x11\n\toperation\x18\x03 \x01(\t\x12\x18\n\x0coperation_id\x18\x04 \x01(\tB\x02\x18\x01\x12<\n\x19schedule_to_close_timeout\x18\x05 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x32\n\x0escheduled_time\x18\x06 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12@\n\x05state\x18\x07 \x01(\x0e\x32\x31.temporal.api.enums.v1.PendingNexusOperationState\x12\x0f\n\x07\x61ttempt\x18\x08 \x01(\x05\x12>\n\x1alast_attempt_complete_time\x18\t \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12>\n\x14last_attempt_failure\x18\n \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12>\n\x1anext_attempt_schedule_time\x18\x0b \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12S\n\x11\x63\x61ncellation_info\x18\x0c \x01(\x0b\x32\x38.temporal.api.workflow.v1.NexusOperationCancellationInfo\x12\x1a\n\x12scheduled_event_id\x18\r \x01(\x03\x12\x16\n\x0e\x62locked_reason\x18\x0e \x01(\t\x12\x17\n\x0foperation_token\x18\x0f \x01(\t\x12<\n\x19schedule_to_start_timeout\x18\x10 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x39\n\x16start_to_close_timeout\x18\x11 \x01(\x0b\x32\x19.google.protobuf.Duration"\x84\x03\n\x1eNexusOperationCancellationInfo\x12\x32\n\x0erequested_time\x18\x01 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x45\n\x05state\x18\x02 \x01(\x0e\x32\x36.temporal.api.enums.v1.NexusOperationCancellationState\x12\x0f\n\x07\x61ttempt\x18\x03 \x01(\x05\x12>\n\x1alast_attempt_complete_time\x18\x04 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12>\n\x14last_attempt_failure\x18\x05 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12>\n\x1anext_attempt_schedule_time\x18\x06 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x16\n\x0e\x62locked_reason\x18\x07 \x01(\t"\xe5\x01\n\x18WorkflowExecutionOptions\x12I\n\x13versioning_override\x18\x01 \x01(\x0b\x32,.temporal.api.workflow.v1.VersioningOverride\x12\x32\n\x08priority\x18\x02 \x01(\x0b\x32 .temporal.api.common.v1.Priority\x12J\n\x14time_skipping_config\x18\x03 \x01(\x0b\x32,.temporal.api.workflow.v1.TimeSkippingConfig"\xf8\x01\n\x12TimeSkippingConfig\x12\x0f\n\x07\x65nabled\x18\x01 \x01(\x08\x12\x1b\n\x13\x64isable_propagation\x18\x02 \x01(\x08\x12\x39\n\x14max_skipped_duration\x18\x04 \x01(\x0b\x32\x19.google.protobuf.DurationH\x00\x12\x39\n\x14max_elapsed_duration\x18\x05 \x01(\x0b\x32\x19.google.protobuf.DurationH\x00\x12\x35\n\x0fmax_target_time\x18\x06 \x01(\x0b\x32\x1a.google.protobuf.TimestampH\x00\x42\x07\n\x05\x62ound"\xbd\x04\n\x12VersioningOverride\x12M\n\x06pinned\x18\x03 \x01(\x0b\x32;.temporal.api.workflow.v1.VersioningOverride.PinnedOverrideH\x00\x12\x16\n\x0c\x61uto_upgrade\x18\x04 \x01(\x08H\x00\x12?\n\x08\x62\x65havior\x18\x01 \x01(\x0e\x32).temporal.api.enums.v1.VersioningBehaviorB\x02\x18\x01\x12>\n\ndeployment\x18\x02 \x01(\x0b\x32&.temporal.api.deployment.v1.DeploymentB\x02\x18\x01\x12\x1a\n\x0epinned_version\x18\t \x01(\tB\x02\x18\x01\x1a\xad\x01\n\x0ePinnedOverride\x12U\n\x08\x62\x65havior\x18\x01 \x01(\x0e\x32\x43.temporal.api.workflow.v1.VersioningOverride.PinnedOverrideBehavior\x12\x44\n\x07version\x18\x02 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersion"g\n\x16PinnedOverrideBehavior\x12(\n$PINNED_OVERRIDE_BEHAVIOR_UNSPECIFIED\x10\x00\x12#\n\x1fPINNED_OVERRIDE_BEHAVIOR_PINNED\x10\x01\x42\n\n\x08override"i\n\x11OnConflictOptions\x12\x19\n\x11\x61ttach_request_id\x18\x01 \x01(\x08\x12#\n\x1b\x61ttach_completion_callbacks\x18\x02 \x01(\x08\x12\x14\n\x0c\x61ttach_links\x18\x03 \x01(\x08"i\n\rRequestIdInfo\x12\x34\n\nevent_type\x18\x01 \x01(\x0e\x32 .temporal.api.enums.v1.EventType\x12\x10\n\x08\x65vent_id\x18\x02 \x01(\x03\x12\x10\n\x08\x62uffered\x18\x03 \x01(\x08"\xb7\x04\n\x12PostResetOperation\x12V\n\x0fsignal_workflow\x18\x01 \x01(\x0b\x32;.temporal.api.workflow.v1.PostResetOperation.SignalWorkflowH\x00\x12\x65\n\x17update_workflow_options\x18\x02 \x01(\x0b\x32\x42.temporal.api.workflow.v1.PostResetOperation.UpdateWorkflowOptionsH\x00\x1a\xb3\x01\n\x0eSignalWorkflow\x12\x13\n\x0bsignal_name\x18\x01 \x01(\t\x12/\n\x05input\x18\x02 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12.\n\x06header\x18\x03 \x01(\x0b\x32\x1e.temporal.api.common.v1.Header\x12+\n\x05links\x18\x04 \x03(\x0b\x32\x1c.temporal.api.common.v1.Link\x1a\xa0\x01\n\x15UpdateWorkflowOptions\x12V\n\x1aworkflow_execution_options\x18\x01 \x01(\x0b\x32\x32.temporal.api.workflow.v1.WorkflowExecutionOptions\x12/\n\x0bupdate_mask\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.FieldMaskB\t\n\x07variant"o\n\x1aWorkflowExecutionPauseInfo\x12\x10\n\x08identity\x18\x01 \x01(\t\x12/\n\x0bpaused_time\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x0e\n\x06reason\x18\x03 \x01(\tB\x93\x01\n\x1bio.temporal.api.workflow.v1B\x0cMessageProtoP\x01Z\'go.temporal.io/api/workflow/v1;workflow\xaa\x02\x1aTemporalio.Api.Workflow.V1\xea\x02\x1dTemporalio::Api::Workflow::V1b\x06proto3' ) @@ -564,23 +564,23 @@ _WORKFLOWEXECUTIONOPTIONS._serialized_start = 8767 _WORKFLOWEXECUTIONOPTIONS._serialized_end = 8996 _TIMESKIPPINGCONFIG._serialized_start = 8999 - _TIMESKIPPINGCONFIG._serialized_end = 9213 - _VERSIONINGOVERRIDE._serialized_start = 9216 - _VERSIONINGOVERRIDE._serialized_end = 9789 - _VERSIONINGOVERRIDE_PINNEDOVERRIDE._serialized_start = 9499 - _VERSIONINGOVERRIDE_PINNEDOVERRIDE._serialized_end = 9672 - _VERSIONINGOVERRIDE_PINNEDOVERRIDEBEHAVIOR._serialized_start = 9674 - _VERSIONINGOVERRIDE_PINNEDOVERRIDEBEHAVIOR._serialized_end = 9777 - _ONCONFLICTOPTIONS._serialized_start = 9791 - _ONCONFLICTOPTIONS._serialized_end = 9896 - _REQUESTIDINFO._serialized_start = 9898 - _REQUESTIDINFO._serialized_end = 10003 - _POSTRESETOPERATION._serialized_start = 10006 - _POSTRESETOPERATION._serialized_end = 10573 - _POSTRESETOPERATION_SIGNALWORKFLOW._serialized_start = 10220 - _POSTRESETOPERATION_SIGNALWORKFLOW._serialized_end = 10399 - _POSTRESETOPERATION_UPDATEWORKFLOWOPTIONS._serialized_start = 10402 - _POSTRESETOPERATION_UPDATEWORKFLOWOPTIONS._serialized_end = 10562 - _WORKFLOWEXECUTIONPAUSEINFO._serialized_start = 10575 - _WORKFLOWEXECUTIONPAUSEINFO._serialized_end = 10686 + _TIMESKIPPINGCONFIG._serialized_end = 9247 + _VERSIONINGOVERRIDE._serialized_start = 9250 + _VERSIONINGOVERRIDE._serialized_end = 9823 + _VERSIONINGOVERRIDE_PINNEDOVERRIDE._serialized_start = 9533 + _VERSIONINGOVERRIDE_PINNEDOVERRIDE._serialized_end = 9706 + _VERSIONINGOVERRIDE_PINNEDOVERRIDEBEHAVIOR._serialized_start = 9708 + _VERSIONINGOVERRIDE_PINNEDOVERRIDEBEHAVIOR._serialized_end = 9811 + _ONCONFLICTOPTIONS._serialized_start = 9825 + _ONCONFLICTOPTIONS._serialized_end = 9930 + _REQUESTIDINFO._serialized_start = 9932 + _REQUESTIDINFO._serialized_end = 10037 + _POSTRESETOPERATION._serialized_start = 10040 + _POSTRESETOPERATION._serialized_end = 10607 + _POSTRESETOPERATION_SIGNALWORKFLOW._serialized_start = 10254 + _POSTRESETOPERATION_SIGNALWORKFLOW._serialized_end = 10433 + _POSTRESETOPERATION_UPDATEWORKFLOWOPTIONS._serialized_start = 10436 + _POSTRESETOPERATION_UPDATEWORKFLOWOPTIONS._serialized_end = 10596 + _WORKFLOWEXECUTIONPAUSEINFO._serialized_start = 10609 + _WORKFLOWEXECUTIONPAUSEINFO._serialized_end = 10720 # @@protoc_insertion_point(module_scope) diff --git a/temporalio/api/workflow/v1/message_pb2.pyi b/temporalio/api/workflow/v1/message_pb2.pyi index 2dbc5c48a..451147563 100644 --- a/temporalio/api/workflow/v1/message_pb2.pyi +++ b/temporalio/api/workflow/v1/message_pb2.pyi @@ -1850,8 +1850,8 @@ class WorkflowExecutionOptions(google.protobuf.message.Message): @property def time_skipping_config(self) -> global___TimeSkippingConfig: """Time-skipping configuration for this workflow execution. - If not set, the time-skipping configuration is not updated by this request; - the existing configuration is preserved. + If not set, the time-skipping conf will not get updated upon request, + i.e. the existing time-skipping conf will be preserved. """ def __init__( self, @@ -1892,26 +1892,23 @@ class TimeSkippingConfig(google.protobuf.message.Message): and possibly other features added in the future. User timers are not classified as in-flight work and will be skipped over. When time advances, it skips to the earlier of the next user timer or the configured bound, if either exists. - - Propagation behavior of time skipping: - The enabled flag, bound fields, and accumulated skipped duration are propagated to related executions as follows: - (1) Child workflows and continue-as-new: both the configuration and the accumulated skipped duration are - inherited from the current execution. The configured bound is shared between the inherited skipped - duration and any additional duration skipped by the new run. - (2) Retry and cron: the configuration and accumulated skipped duration are inherited as recorded when the - current workflow started; the accumulated skipped duration of the current run is not propagated. - (3) Reset: the new run retains the time-skipping configuration of the current execution. Because reset replays - all events up to the reset point and re-applies any UpdateWorkflowExecutionOptions changes made after that - point, the resulting run ends up with the same final time-skipping configuration as the previous run. """ DESCRIPTOR: google.protobuf.descriptor.Descriptor ENABLED_FIELD_NUMBER: builtins.int + DISABLE_PROPAGATION_FIELD_NUMBER: builtins.int MAX_SKIPPED_DURATION_FIELD_NUMBER: builtins.int MAX_ELAPSED_DURATION_FIELD_NUMBER: builtins.int + MAX_TARGET_TIME_FIELD_NUMBER: builtins.int enabled: builtins.bool - """Enables or disables time skipping for this workflow execution.""" + """Enables or disables time skipping for this workflow execution. + By default, this field is propagated to transitively related workflows (child workflows/start-as-new/reset) + at the time they are started. + Changes made after a transitively related workflow has started are not propagated. + """ + disable_propagation: builtins.bool + """If set, the enabled field is not propagated to transitively related workflows.""" @property def max_skipped_duration(self) -> google.protobuf.duration_pb2.Duration: """Maximum total virtual time that can be skipped.""" @@ -1921,12 +1918,19 @@ class TimeSkippingConfig(google.protobuf.message.Message): This includes both skipped time and real time elapsing. (-- api-linter: core::0142::time-field-names=disabled --) """ + @property + def max_target_time(self) -> google.protobuf.timestamp_pb2.Timestamp: + """Absolute virtual timestamp at which time skipping is disabled. + Time skipping will not advance beyond this point. + """ def __init__( self, *, enabled: builtins.bool = ..., + disable_propagation: builtins.bool = ..., max_skipped_duration: google.protobuf.duration_pb2.Duration | None = ..., max_elapsed_duration: google.protobuf.duration_pb2.Duration | None = ..., + max_target_time: google.protobuf.timestamp_pb2.Timestamp | None = ..., ) -> None: ... def HasField( self, @@ -1937,6 +1941,8 @@ class TimeSkippingConfig(google.protobuf.message.Message): b"max_elapsed_duration", "max_skipped_duration", b"max_skipped_duration", + "max_target_time", + b"max_target_time", ], ) -> builtins.bool: ... def ClearField( @@ -1944,18 +1950,25 @@ class TimeSkippingConfig(google.protobuf.message.Message): field_name: typing_extensions.Literal[ "bound", b"bound", + "disable_propagation", + b"disable_propagation", "enabled", b"enabled", "max_elapsed_duration", b"max_elapsed_duration", "max_skipped_duration", b"max_skipped_duration", + "max_target_time", + b"max_target_time", ], ) -> None: ... def WhichOneof( self, oneof_group: typing_extensions.Literal["bound", b"bound"] ) -> ( - typing_extensions.Literal["max_skipped_duration", "max_elapsed_duration"] | None + typing_extensions.Literal[ + "max_skipped_duration", "max_elapsed_duration", "max_target_time" + ] + | None ): ... global___TimeSkippingConfig = TimeSkippingConfig diff --git a/temporalio/api/workflowservice/v1/__init__.py b/temporalio/api/workflowservice/v1/__init__.py index 1039e5769..771e4655c 100644 --- a/temporalio/api/workflowservice/v1/__init__.py +++ b/temporalio/api/workflowservice/v1/__init__.py @@ -111,6 +111,8 @@ ListWorkflowRulesResponse, PatchScheduleRequest, PatchScheduleResponse, + PauseActivityExecutionRequest, + PauseActivityExecutionResponse, PauseActivityRequest, PauseActivityResponse, PauseWorkflowExecutionRequest, @@ -143,6 +145,8 @@ RequestCancelNexusOperationExecutionResponse, RequestCancelWorkflowExecutionRequest, RequestCancelWorkflowExecutionResponse, + ResetActivityExecutionRequest, + ResetActivityExecutionResponse, ResetActivityRequest, ResetActivityResponse, ResetStickyTaskQueueRequest, @@ -205,10 +209,14 @@ TerminateWorkflowExecutionResponse, TriggerWorkflowRuleRequest, TriggerWorkflowRuleResponse, + UnpauseActivityExecutionRequest, + UnpauseActivityExecutionResponse, UnpauseActivityRequest, UnpauseActivityResponse, UnpauseWorkflowExecutionRequest, UnpauseWorkflowExecutionResponse, + UpdateActivityExecutionOptionsRequest, + UpdateActivityExecutionOptionsResponse, UpdateActivityOptionsRequest, UpdateActivityOptionsResponse, UpdateNamespaceRequest, @@ -348,6 +356,8 @@ "ListWorkflowRulesResponse", "PatchScheduleRequest", "PatchScheduleResponse", + "PauseActivityExecutionRequest", + "PauseActivityExecutionResponse", "PauseActivityRequest", "PauseActivityResponse", "PauseWorkflowExecutionRequest", @@ -380,6 +390,8 @@ "RequestCancelNexusOperationExecutionResponse", "RequestCancelWorkflowExecutionRequest", "RequestCancelWorkflowExecutionResponse", + "ResetActivityExecutionRequest", + "ResetActivityExecutionResponse", "ResetActivityRequest", "ResetActivityResponse", "ResetStickyTaskQueueRequest", @@ -442,10 +454,14 @@ "TerminateWorkflowExecutionResponse", "TriggerWorkflowRuleRequest", "TriggerWorkflowRuleResponse", + "UnpauseActivityExecutionRequest", + "UnpauseActivityExecutionResponse", "UnpauseActivityRequest", "UnpauseActivityResponse", "UnpauseWorkflowExecutionRequest", "UnpauseWorkflowExecutionResponse", + "UpdateActivityExecutionOptionsRequest", + "UpdateActivityExecutionOptionsResponse", "UpdateActivityOptionsRequest", "UpdateActivityOptionsResponse", "UpdateNamespaceRequest", diff --git a/temporalio/api/workflowservice/v1/request_response_pb2.py b/temporalio/api/workflowservice/v1/request_response_pb2.py index 71e1a6a0f..2f3b090ee 100644 --- a/temporalio/api/workflowservice/v1/request_response_pb2.py +++ b/temporalio/api/workflowservice/v1/request_response_pb2.py @@ -128,7 +128,7 @@ ) DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile( - b'\n6temporal/api/workflowservice/v1/request_response.proto\x12\x1ftemporal.api.workflowservice.v1\x1a+temporal/api/enums/v1/batch_operation.proto\x1a"temporal/api/enums/v1/common.proto\x1a$temporal/api/enums/v1/workflow.proto\x1a%temporal/api/enums/v1/namespace.proto\x1a(temporal/api/enums/v1/failed_cause.proto\x1a!temporal/api/enums/v1/query.proto\x1a!temporal/api/enums/v1/reset.proto\x1a&temporal/api/enums/v1/task_queue.proto\x1a&temporal/api/enums/v1/deployment.proto\x1a"temporal/api/enums/v1/update.proto\x1a$temporal/api/enums/v1/activity.proto\x1a!temporal/api/enums/v1/nexus.proto\x1a&temporal/api/activity/v1/message.proto\x1a$temporal/api/common/v1/message.proto\x1a%temporal/api/history/v1/message.proto\x1a&temporal/api/workflow/v1/message.proto\x1a%temporal/api/command/v1/message.proto\x1a$temporal/api/compute/v1/config.proto\x1a(temporal/api/deployment/v1/message.proto\x1a%temporal/api/failure/v1/message.proto\x1a$temporal/api/filter/v1/message.proto\x1a&temporal/api/protocol/v1/message.proto\x1a\'temporal/api/namespace/v1/message.proto\x1a#temporal/api/query/v1/message.proto\x1a)temporal/api/replication/v1/message.proto\x1a#temporal/api/rules/v1/message.proto\x1a\'temporal/api/sdk/v1/worker_config.proto\x1a&temporal/api/schedule/v1/message.proto\x1a\'temporal/api/taskqueue/v1/message.proto\x1a$temporal/api/update/v1/message.proto\x1a%temporal/api/version/v1/message.proto\x1a#temporal/api/batch/v1/message.proto\x1a\x30temporal/api/sdk/v1/task_complete_metadata.proto\x1a\'temporal/api/sdk/v1/user_metadata.proto\x1a#temporal/api/nexus/v1/message.proto\x1a$temporal/api/worker/v1/message.proto\x1a\x1egoogle/protobuf/duration.proto\x1a google/protobuf/field_mask.proto\x1a\x1fgoogle/protobuf/timestamp.proto"\x88\x05\n\x18RegisterNamespaceRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0b\x64\x65scription\x18\x02 \x01(\t\x12\x13\n\x0bowner_email\x18\x03 \x01(\t\x12\x46\n#workflow_execution_retention_period\x18\x04 \x01(\x0b\x32\x19.google.protobuf.Duration\x12G\n\x08\x63lusters\x18\x05 \x03(\x0b\x32\x35.temporal.api.replication.v1.ClusterReplicationConfig\x12\x1b\n\x13\x61\x63tive_cluster_name\x18\x06 \x01(\t\x12Q\n\x04\x64\x61ta\x18\x07 \x03(\x0b\x32\x43.temporal.api.workflowservice.v1.RegisterNamespaceRequest.DataEntry\x12\x16\n\x0esecurity_token\x18\x08 \x01(\t\x12\x1b\n\x13is_global_namespace\x18\t \x01(\x08\x12\x44\n\x16history_archival_state\x18\n \x01(\x0e\x32$.temporal.api.enums.v1.ArchivalState\x12\x1c\n\x14history_archival_uri\x18\x0b \x01(\t\x12G\n\x19visibility_archival_state\x18\x0c \x01(\x0e\x32$.temporal.api.enums.v1.ArchivalState\x12\x1f\n\x17visibility_archival_uri\x18\r \x01(\t\x1a+\n\tDataEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01"\x1b\n\x19RegisterNamespaceResponse"\x89\x01\n\x15ListNamespacesRequest\x12\x11\n\tpage_size\x18\x01 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c\x12\x44\n\x10namespace_filter\x18\x03 \x01(\x0b\x32*.temporal.api.namespace.v1.NamespaceFilter"\x81\x01\n\x16ListNamespacesResponse\x12N\n\nnamespaces\x18\x01 \x03(\x0b\x32:.temporal.api.workflowservice.v1.DescribeNamespaceResponse\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c"9\n\x18\x44\x65scribeNamespaceRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\n\n\x02id\x18\x02 \x01(\t"\xec\x02\n\x19\x44\x65scribeNamespaceResponse\x12@\n\x0enamespace_info\x18\x01 \x01(\x0b\x32(.temporal.api.namespace.v1.NamespaceInfo\x12:\n\x06\x63onfig\x18\x02 \x01(\x0b\x32*.temporal.api.namespace.v1.NamespaceConfig\x12S\n\x12replication_config\x18\x03 \x01(\x0b\x32\x37.temporal.api.replication.v1.NamespaceReplicationConfig\x12\x18\n\x10\x66\x61ilover_version\x18\x04 \x01(\x03\x12\x1b\n\x13is_global_namespace\x18\x05 \x01(\x08\x12\x45\n\x10\x66\x61ilover_history\x18\x06 \x03(\x0b\x32+.temporal.api.replication.v1.FailoverStatus"\xcf\x02\n\x16UpdateNamespaceRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x43\n\x0bupdate_info\x18\x02 \x01(\x0b\x32..temporal.api.namespace.v1.UpdateNamespaceInfo\x12:\n\x06\x63onfig\x18\x03 \x01(\x0b\x32*.temporal.api.namespace.v1.NamespaceConfig\x12S\n\x12replication_config\x18\x04 \x01(\x0b\x32\x37.temporal.api.replication.v1.NamespaceReplicationConfig\x12\x16\n\x0esecurity_token\x18\x05 \x01(\t\x12\x19\n\x11\x64\x65lete_bad_binary\x18\x06 \x01(\t\x12\x19\n\x11promote_namespace\x18\x07 \x01(\x08"\xa3\x02\n\x17UpdateNamespaceResponse\x12@\n\x0enamespace_info\x18\x01 \x01(\x0b\x32(.temporal.api.namespace.v1.NamespaceInfo\x12:\n\x06\x63onfig\x18\x02 \x01(\x0b\x32*.temporal.api.namespace.v1.NamespaceConfig\x12S\n\x12replication_config\x18\x03 \x01(\x0b\x32\x37.temporal.api.replication.v1.NamespaceReplicationConfig\x12\x18\n\x10\x66\x61ilover_version\x18\x04 \x01(\x03\x12\x1b\n\x13is_global_namespace\x18\x05 \x01(\x08"F\n\x19\x44\x65precateNamespaceRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x16\n\x0esecurity_token\x18\x02 \x01(\t"\x1c\n\x1a\x44\x65precateNamespaceResponse"\xd3\x0c\n\x1dStartWorkflowExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12;\n\rworkflow_type\x18\x03 \x01(\x0b\x32$.temporal.api.common.v1.WorkflowType\x12\x38\n\ntask_queue\x18\x04 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12/\n\x05input\x18\x05 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12=\n\x1aworkflow_execution_timeout\x18\x06 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x37\n\x14workflow_run_timeout\x18\x07 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x38\n\x15workflow_task_timeout\x18\x08 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x10\n\x08identity\x18\t \x01(\t\x12\x12\n\nrequest_id\x18\n \x01(\t\x12N\n\x18workflow_id_reuse_policy\x18\x0b \x01(\x0e\x32,.temporal.api.enums.v1.WorkflowIdReusePolicy\x12T\n\x1bworkflow_id_conflict_policy\x18\x16 \x01(\x0e\x32/.temporal.api.enums.v1.WorkflowIdConflictPolicy\x12\x39\n\x0cretry_policy\x18\x0c \x01(\x0b\x32#.temporal.api.common.v1.RetryPolicy\x12\x15\n\rcron_schedule\x18\r \x01(\t\x12*\n\x04memo\x18\x0e \x01(\x0b\x32\x1c.temporal.api.common.v1.Memo\x12\x43\n\x11search_attributes\x18\x0f \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes\x12.\n\x06header\x18\x10 \x01(\x0b\x32\x1e.temporal.api.common.v1.Header\x12\x1f\n\x17request_eager_execution\x18\x11 \x01(\x08\x12;\n\x11\x63ontinued_failure\x18\x12 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12@\n\x16last_completion_result\x18\x13 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x37\n\x14workflow_start_delay\x18\x14 \x01(\x0b\x32\x19.google.protobuf.Duration\x12>\n\x14\x63ompletion_callbacks\x18\x15 \x03(\x0b\x32 .temporal.api.common.v1.Callback\x12\x38\n\ruser_metadata\x18\x17 \x01(\x0b\x32!.temporal.api.sdk.v1.UserMetadata\x12+\n\x05links\x18\x18 \x03(\x0b\x32\x1c.temporal.api.common.v1.Link\x12I\n\x13versioning_override\x18\x19 \x01(\x0b\x32,.temporal.api.workflow.v1.VersioningOverride\x12H\n\x13on_conflict_options\x18\x1a \x01(\x0b\x32+.temporal.api.workflow.v1.OnConflictOptions\x12\x32\n\x08priority\x18\x1b \x01(\x0b\x32 .temporal.api.common.v1.Priority\x12\\\n\x1f\x65\x61ger_worker_deployment_options\x18\x1c \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentOptions\x12J\n\x14time_skipping_config\x18\x1d \x01(\x0b\x32,.temporal.api.workflow.v1.TimeSkippingConfig"\x8a\x02\n\x1eStartWorkflowExecutionResponse\x12\x0e\n\x06run_id\x18\x01 \x01(\t\x12\x0f\n\x07started\x18\x03 \x01(\x08\x12>\n\x06status\x18\x05 \x01(\x0e\x32..temporal.api.enums.v1.WorkflowExecutionStatus\x12[\n\x13\x65\x61ger_workflow_task\x18\x02 \x01(\x0b\x32>.temporal.api.workflowservice.v1.PollWorkflowTaskQueueResponse\x12*\n\x04link\x18\x04 \x01(\x0b\x32\x1c.temporal.api.common.v1.Link"\xaa\x02\n"GetWorkflowExecutionHistoryRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12<\n\texecution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x19\n\x11maximum_page_size\x18\x03 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x04 \x01(\x0c\x12\x16\n\x0ewait_new_event\x18\x05 \x01(\x08\x12P\n\x19history_event_filter_type\x18\x06 \x01(\x0e\x32-.temporal.api.enums.v1.HistoryEventFilterType\x12\x15\n\rskip_archival\x18\x07 \x01(\x08"\xba\x01\n#GetWorkflowExecutionHistoryResponse\x12\x31\n\x07history\x18\x01 \x01(\x0b\x32 .temporal.api.history.v1.History\x12\x35\n\x0braw_history\x18\x02 \x03(\x0b\x32 .temporal.api.common.v1.DataBlob\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c\x12\x10\n\x08\x61rchived\x18\x04 \x01(\x08"\xb0\x01\n)GetWorkflowExecutionHistoryReverseRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12<\n\texecution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x19\n\x11maximum_page_size\x18\x03 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x04 \x01(\x0c"x\n*GetWorkflowExecutionHistoryReverseResponse\x12\x31\n\x07history\x18\x01 \x01(\x0b\x32 .temporal.api.history.v1.History\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c"\xb8\x03\n\x1cPollWorkflowTaskQueueRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x38\n\ntask_queue\x18\x02 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12\x17\n\x0fpoller_group_id\x18\n \x01(\t\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x1b\n\x13worker_instance_key\x18\x08 \x01(\t\x12!\n\x19worker_control_task_queue\x18\t \x01(\t\x12\x1b\n\x0f\x62inary_checksum\x18\x04 \x01(\tB\x02\x18\x01\x12Z\n\x1bworker_version_capabilities\x18\x05 \x01(\x0b\x32\x31.temporal.api.common.v1.WorkerVersionCapabilitiesB\x02\x18\x01\x12O\n\x12\x64\x65ployment_options\x18\x06 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentOptionsJ\x04\x08\x07\x10\x08R\x10worker_heartbeat"\xf2\x07\n\x1dPollWorkflowTaskQueueResponse\x12\x12\n\ntask_token\x18\x01 \x01(\x0c\x12\x45\n\x12workflow_execution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12;\n\rworkflow_type\x18\x03 \x01(\x0b\x32$.temporal.api.common.v1.WorkflowType\x12!\n\x19previous_started_event_id\x18\x04 \x01(\x03\x12\x18\n\x10started_event_id\x18\x05 \x01(\x03\x12\x0f\n\x07\x61ttempt\x18\x06 \x01(\x05\x12\x1a\n\x12\x62\x61\x63klog_count_hint\x18\x07 \x01(\x03\x12\x31\n\x07history\x18\x08 \x01(\x0b\x32 .temporal.api.history.v1.History\x12\x17\n\x0fnext_page_token\x18\t \x01(\x0c\x12\x33\n\x05query\x18\n \x01(\x0b\x32$.temporal.api.query.v1.WorkflowQuery\x12K\n\x1dworkflow_execution_task_queue\x18\x0b \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12\x32\n\x0escheduled_time\x18\x0c \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x30\n\x0cstarted_time\x18\r \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\\\n\x07queries\x18\x0e \x03(\x0b\x32K.temporal.api.workflowservice.v1.PollWorkflowTaskQueueResponse.QueriesEntry\x12\x33\n\x08messages\x18\x0f \x03(\x0b\x32!.temporal.api.protocol.v1.Message\x12Q\n\x17poller_scaling_decision\x18\x10 \x01(\x0b\x32\x30.temporal.api.taskqueue.v1.PollerScalingDecision\x12\x17\n\x0fpoller_group_id\x18\x11 \x01(\t\x12\x46\n\x12poller_group_infos\x18\x12 \x03(\x0b\x32*.temporal.api.taskqueue.v1.PollerGroupInfo\x1aT\n\x0cQueriesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x33\n\x05value\x18\x02 \x01(\x0b\x32$.temporal.api.query.v1.WorkflowQuery:\x02\x38\x01"\x8a\n\n#RespondWorkflowTaskCompletedRequest\x12\x12\n\ntask_token\x18\x01 \x01(\x0c\x12\x32\n\x08\x63ommands\x18\x02 \x03(\x0b\x32 .temporal.api.command.v1.Command\x12\x10\n\x08identity\x18\x03 \x01(\t\x12O\n\x11sticky_attributes\x18\x04 \x01(\x0b\x32\x34.temporal.api.taskqueue.v1.StickyExecutionAttributes\x12 \n\x18return_new_workflow_task\x18\x05 \x01(\x08\x12&\n\x1e\x66orce_create_new_workflow_task\x18\x06 \x01(\x08\x12\x1b\n\x0f\x62inary_checksum\x18\x07 \x01(\tB\x02\x18\x01\x12m\n\rquery_results\x18\x08 \x03(\x0b\x32V.temporal.api.workflowservice.v1.RespondWorkflowTaskCompletedRequest.QueryResultsEntry\x12\x11\n\tnamespace\x18\t \x01(\t\x12\x13\n\x0bresource_id\x18\x12 \x01(\t\x12L\n\x14worker_version_stamp\x18\n \x01(\x0b\x32*.temporal.api.common.v1.WorkerVersionStampB\x02\x18\x01\x12\x33\n\x08messages\x18\x0b \x03(\x0b\x32!.temporal.api.protocol.v1.Message\x12H\n\x0csdk_metadata\x18\x0c \x01(\x0b\x32\x32.temporal.api.sdk.v1.WorkflowTaskCompletedMetadata\x12\x43\n\x11metering_metadata\x18\r \x01(\x0b\x32(.temporal.api.common.v1.MeteringMetadata\x12g\n\x0c\x63\x61pabilities\x18\x0e \x01(\x0b\x32Q.temporal.api.workflowservice.v1.RespondWorkflowTaskCompletedRequest.Capabilities\x12>\n\ndeployment\x18\x0f \x01(\x0b\x32&.temporal.api.deployment.v1.DeploymentB\x02\x18\x01\x12\x46\n\x13versioning_behavior\x18\x10 \x01(\x0e\x32).temporal.api.enums.v1.VersioningBehavior\x12O\n\x12\x64\x65ployment_options\x18\x11 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentOptions\x12\x1b\n\x13worker_instance_key\x18\x13 \x01(\t\x12!\n\x19worker_control_task_queue\x18\x14 \x01(\t\x1a_\n\x11QueryResultsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x39\n\x05value\x18\x02 \x01(\x0b\x32*.temporal.api.query.v1.WorkflowQueryResult:\x02\x38\x01\x1a\x45\n\x0c\x43\x61pabilities\x12\x35\n-discard_speculative_workflow_task_with_events\x18\x01 \x01(\x08"\xf5\x01\n$RespondWorkflowTaskCompletedResponse\x12U\n\rworkflow_task\x18\x01 \x01(\x0b\x32>.temporal.api.workflowservice.v1.PollWorkflowTaskQueueResponse\x12V\n\x0e\x61\x63tivity_tasks\x18\x02 \x03(\x0b\x32>.temporal.api.workflowservice.v1.PollActivityTaskQueueResponse\x12\x1e\n\x16reset_history_event_id\x18\x03 \x01(\x03"\x8d\x04\n RespondWorkflowTaskFailedRequest\x12\x12\n\ntask_token\x18\x01 \x01(\x0c\x12=\n\x05\x63\x61use\x18\x02 \x01(\x0e\x32..temporal.api.enums.v1.WorkflowTaskFailedCause\x12\x31\n\x07\x66\x61ilure\x18\x03 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12\x10\n\x08identity\x18\x04 \x01(\t\x12\x1b\n\x0f\x62inary_checksum\x18\x05 \x01(\tB\x02\x18\x01\x12\x11\n\tnamespace\x18\x06 \x01(\t\x12\x13\n\x0bresource_id\x18\x0b \x01(\t\x12\x33\n\x08messages\x18\x07 \x03(\x0b\x32!.temporal.api.protocol.v1.Message\x12\x46\n\x0eworker_version\x18\x08 \x01(\x0b\x32*.temporal.api.common.v1.WorkerVersionStampB\x02\x18\x01\x12>\n\ndeployment\x18\t \x01(\x0b\x32&.temporal.api.deployment.v1.DeploymentB\x02\x18\x01\x12O\n\x12\x64\x65ployment_options\x18\n \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentOptions"#\n!RespondWorkflowTaskFailedResponse"\xe6\x03\n\x1cPollActivityTaskQueueRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x38\n\ntask_queue\x18\x02 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12\x17\n\x0fpoller_group_id\x18\n \x01(\t\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x1b\n\x13worker_instance_key\x18\x08 \x01(\t\x12!\n\x19worker_control_task_queue\x18\t \x01(\t\x12I\n\x13task_queue_metadata\x18\x04 \x01(\x0b\x32,.temporal.api.taskqueue.v1.TaskQueueMetadata\x12Z\n\x1bworker_version_capabilities\x18\x05 \x01(\x0b\x32\x31.temporal.api.common.v1.WorkerVersionCapabilitiesB\x02\x18\x01\x12O\n\x12\x64\x65ployment_options\x18\x06 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentOptionsJ\x04\x08\x07\x10\x08R\x10worker_heartbeat"\xd0\x08\n\x1dPollActivityTaskQueueResponse\x12\x12\n\ntask_token\x18\x01 \x01(\x0c\x12\x1a\n\x12workflow_namespace\x18\x02 \x01(\t\x12;\n\rworkflow_type\x18\x03 \x01(\x0b\x32$.temporal.api.common.v1.WorkflowType\x12\x45\n\x12workflow_execution\x18\x04 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12;\n\ractivity_type\x18\x05 \x01(\x0b\x32$.temporal.api.common.v1.ActivityType\x12\x13\n\x0b\x61\x63tivity_id\x18\x06 \x01(\t\x12.\n\x06header\x18\x07 \x01(\x0b\x32\x1e.temporal.api.common.v1.Header\x12/\n\x05input\x18\x08 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12;\n\x11heartbeat_details\x18\t \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x32\n\x0escheduled_time\x18\n \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x42\n\x1e\x63urrent_attempt_scheduled_time\x18\x0b \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x30\n\x0cstarted_time\x18\x0c \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x0f\n\x07\x61ttempt\x18\r \x01(\x05\x12<\n\x19schedule_to_close_timeout\x18\x0e \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x39\n\x16start_to_close_timeout\x18\x0f \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x34\n\x11heartbeat_timeout\x18\x10 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x39\n\x0cretry_policy\x18\x11 \x01(\x0b\x32#.temporal.api.common.v1.RetryPolicy\x12Q\n\x17poller_scaling_decision\x18\x12 \x01(\x0b\x32\x30.temporal.api.taskqueue.v1.PollerScalingDecision\x12\x32\n\x08priority\x18\x13 \x01(\x0b\x32 .temporal.api.common.v1.Priority\x12\x17\n\x0f\x61\x63tivity_run_id\x18\x14 \x01(\t\x12\x46\n\x12poller_group_infos\x18\x15 \x03(\x0b\x32*.temporal.api.taskqueue.v1.PollerGroupInfo"\xa5\x01\n"RecordActivityTaskHeartbeatRequest\x12\x12\n\ntask_token\x18\x01 \x01(\x0c\x12\x31\n\x07\x64\x65tails\x18\x02 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x11\n\tnamespace\x18\x04 \x01(\t\x12\x13\n\x0bresource_id\x18\x05 \x01(\t"p\n#RecordActivityTaskHeartbeatResponse\x12\x18\n\x10\x63\x61ncel_requested\x18\x01 \x01(\x08\x12\x17\n\x0f\x61\x63tivity_paused\x18\x02 \x01(\x08\x12\x16\n\x0e\x61\x63tivity_reset\x18\x03 \x01(\x08"\xcf\x01\n&RecordActivityTaskHeartbeatByIdRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x12\x13\n\x0b\x61\x63tivity_id\x18\x04 \x01(\t\x12\x31\n\x07\x64\x65tails\x18\x05 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x10\n\x08identity\x18\x06 \x01(\t\x12\x13\n\x0bresource_id\x18\x07 \x01(\t"t\n\'RecordActivityTaskHeartbeatByIdResponse\x12\x18\n\x10\x63\x61ncel_requested\x18\x01 \x01(\x08\x12\x17\n\x0f\x61\x63tivity_paused\x18\x02 \x01(\x08\x12\x16\n\x0e\x61\x63tivity_reset\x18\x03 \x01(\x08"\xfe\x02\n#RespondActivityTaskCompletedRequest\x12\x12\n\ntask_token\x18\x01 \x01(\x0c\x12\x30\n\x06result\x18\x02 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x11\n\tnamespace\x18\x04 \x01(\t\x12\x13\n\x0bresource_id\x18\x08 \x01(\t\x12\x46\n\x0eworker_version\x18\x05 \x01(\x0b\x32*.temporal.api.common.v1.WorkerVersionStampB\x02\x18\x01\x12>\n\ndeployment\x18\x06 \x01(\x0b\x32&.temporal.api.deployment.v1.DeploymentB\x02\x18\x01\x12O\n\x12\x64\x65ployment_options\x18\x07 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentOptions"&\n$RespondActivityTaskCompletedResponse"\xcf\x01\n\'RespondActivityTaskCompletedByIdRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x12\x13\n\x0b\x61\x63tivity_id\x18\x04 \x01(\t\x12\x30\n\x06result\x18\x05 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x10\n\x08identity\x18\x06 \x01(\t\x12\x13\n\x0bresource_id\x18\x07 \x01(\t"*\n(RespondActivityTaskCompletedByIdResponse"\xbe\x03\n RespondActivityTaskFailedRequest\x12\x12\n\ntask_token\x18\x01 \x01(\x0c\x12\x31\n\x07\x66\x61ilure\x18\x02 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x11\n\tnamespace\x18\x04 \x01(\t\x12\x13\n\x0bresource_id\x18\t \x01(\t\x12@\n\x16last_heartbeat_details\x18\x05 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x46\n\x0eworker_version\x18\x06 \x01(\x0b\x32*.temporal.api.common.v1.WorkerVersionStampB\x02\x18\x01\x12>\n\ndeployment\x18\x07 \x01(\x0b\x32&.temporal.api.deployment.v1.DeploymentB\x02\x18\x01\x12O\n\x12\x64\x65ployment_options\x18\x08 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentOptions"W\n!RespondActivityTaskFailedResponse\x12\x32\n\x08\x66\x61ilures\x18\x01 \x03(\x0b\x32 .temporal.api.failure.v1.Failure"\x8f\x02\n$RespondActivityTaskFailedByIdRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x12\x13\n\x0b\x61\x63tivity_id\x18\x04 \x01(\t\x12\x31\n\x07\x66\x61ilure\x18\x05 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12\x10\n\x08identity\x18\x06 \x01(\t\x12@\n\x16last_heartbeat_details\x18\x07 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x13\n\x0bresource_id\x18\x08 \x01(\t"[\n%RespondActivityTaskFailedByIdResponse\x12\x32\n\x08\x66\x61ilures\x18\x01 \x03(\x0b\x32 .temporal.api.failure.v1.Failure"\xfe\x02\n"RespondActivityTaskCanceledRequest\x12\x12\n\ntask_token\x18\x01 \x01(\x0c\x12\x31\n\x07\x64\x65tails\x18\x02 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x11\n\tnamespace\x18\x04 \x01(\t\x12\x13\n\x0bresource_id\x18\x08 \x01(\t\x12\x46\n\x0eworker_version\x18\x05 \x01(\x0b\x32*.temporal.api.common.v1.WorkerVersionStampB\x02\x18\x01\x12>\n\ndeployment\x18\x06 \x01(\x0b\x32&.temporal.api.deployment.v1.DeploymentB\x02\x18\x01\x12O\n\x12\x64\x65ployment_options\x18\x07 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentOptions"%\n#RespondActivityTaskCanceledResponse"\xa0\x02\n&RespondActivityTaskCanceledByIdRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x12\x13\n\x0b\x61\x63tivity_id\x18\x04 \x01(\t\x12\x31\n\x07\x64\x65tails\x18\x05 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x10\n\x08identity\x18\x06 \x01(\t\x12O\n\x12\x64\x65ployment_options\x18\x07 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentOptions\x12\x13\n\x0bresource_id\x18\x08 \x01(\t")\n\'RespondActivityTaskCanceledByIdResponse"\x84\x02\n%RequestCancelWorkflowExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x45\n\x12workflow_execution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x12\n\nrequest_id\x18\x04 \x01(\t\x12\x1e\n\x16\x66irst_execution_run_id\x18\x05 \x01(\t\x12\x0e\n\x06reason\x18\x06 \x01(\t\x12+\n\x05links\x18\x07 \x03(\x0b\x32\x1c.temporal.api.common.v1.Link"(\n&RequestCancelWorkflowExecutionResponse"\xde\x02\n\x1eSignalWorkflowExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x45\n\x12workflow_execution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x13\n\x0bsignal_name\x18\x03 \x01(\t\x12/\n\x05input\x18\x04 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x10\n\x08identity\x18\x05 \x01(\t\x12\x12\n\nrequest_id\x18\x06 \x01(\t\x12\x13\n\x07\x63ontrol\x18\x07 \x01(\tB\x02\x18\x01\x12.\n\x06header\x18\x08 \x01(\x0b\x32\x1e.temporal.api.common.v1.Header\x12+\n\x05links\x18\n \x03(\x0b\x32\x1c.temporal.api.common.v1.LinkJ\x04\x08\t\x10\n"M\n\x1fSignalWorkflowExecutionResponse\x12*\n\x04link\x18\x01 \x01(\x0b\x32\x1c.temporal.api.common.v1.Link"\xbd\n\n\'SignalWithStartWorkflowExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12;\n\rworkflow_type\x18\x03 \x01(\x0b\x32$.temporal.api.common.v1.WorkflowType\x12\x38\n\ntask_queue\x18\x04 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12/\n\x05input\x18\x05 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12=\n\x1aworkflow_execution_timeout\x18\x06 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x37\n\x14workflow_run_timeout\x18\x07 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x38\n\x15workflow_task_timeout\x18\x08 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x10\n\x08identity\x18\t \x01(\t\x12\x12\n\nrequest_id\x18\n \x01(\t\x12N\n\x18workflow_id_reuse_policy\x18\x0b \x01(\x0e\x32,.temporal.api.enums.v1.WorkflowIdReusePolicy\x12T\n\x1bworkflow_id_conflict_policy\x18\x16 \x01(\x0e\x32/.temporal.api.enums.v1.WorkflowIdConflictPolicy\x12\x13\n\x0bsignal_name\x18\x0c \x01(\t\x12\x36\n\x0csignal_input\x18\r \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x13\n\x07\x63ontrol\x18\x0e \x01(\tB\x02\x18\x01\x12\x39\n\x0cretry_policy\x18\x0f \x01(\x0b\x32#.temporal.api.common.v1.RetryPolicy\x12\x15\n\rcron_schedule\x18\x10 \x01(\t\x12*\n\x04memo\x18\x11 \x01(\x0b\x32\x1c.temporal.api.common.v1.Memo\x12\x43\n\x11search_attributes\x18\x12 \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes\x12.\n\x06header\x18\x13 \x01(\x0b\x32\x1e.temporal.api.common.v1.Header\x12\x37\n\x14workflow_start_delay\x18\x14 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x38\n\ruser_metadata\x18\x17 \x01(\x0b\x32!.temporal.api.sdk.v1.UserMetadata\x12+\n\x05links\x18\x18 \x03(\x0b\x32\x1c.temporal.api.common.v1.Link\x12I\n\x13versioning_override\x18\x19 \x01(\x0b\x32,.temporal.api.workflow.v1.VersioningOverride\x12\x32\n\x08priority\x18\x1a \x01(\x0b\x32 .temporal.api.common.v1.Priority\x12J\n\x14time_skipping_config\x18\x1b \x01(\x0b\x32,.temporal.api.workflow.v1.TimeSkippingConfigJ\x04\x08\x15\x10\x16"~\n(SignalWithStartWorkflowExecutionResponse\x12\x0e\n\x06run_id\x18\x01 \x01(\t\x12\x0f\n\x07started\x18\x02 \x01(\x08\x12\x31\n\x0bsignal_link\x18\x03 \x01(\x0b\x32\x1c.temporal.api.common.v1.Link"\xc1\x03\n\x1dResetWorkflowExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x45\n\x12workflow_execution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x0e\n\x06reason\x18\x03 \x01(\t\x12%\n\x1dworkflow_task_finish_event_id\x18\x04 \x01(\x03\x12\x12\n\nrequest_id\x18\x05 \x01(\t\x12G\n\x12reset_reapply_type\x18\x06 \x01(\x0e\x32\'.temporal.api.enums.v1.ResetReapplyTypeB\x02\x18\x01\x12S\n\x1breset_reapply_exclude_types\x18\x07 \x03(\x0e\x32..temporal.api.enums.v1.ResetReapplyExcludeType\x12K\n\x15post_reset_operations\x18\x08 \x03(\x0b\x32,.temporal.api.workflow.v1.PostResetOperation\x12\x10\n\x08identity\x18\t \x01(\t"0\n\x1eResetWorkflowExecutionResponse\x12\x0e\n\x06run_id\x18\x01 \x01(\t"\x9f\x02\n!TerminateWorkflowExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x45\n\x12workflow_execution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x0e\n\x06reason\x18\x03 \x01(\t\x12\x31\n\x07\x64\x65tails\x18\x04 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x10\n\x08identity\x18\x05 \x01(\t\x12\x1e\n\x16\x66irst_execution_run_id\x18\x06 \x01(\t\x12+\n\x05links\x18\x07 \x03(\x0b\x32\x1c.temporal.api.common.v1.Link"$\n"TerminateWorkflowExecutionResponse"z\n\x1e\x44\x65leteWorkflowExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x45\n\x12workflow_execution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution"!\n\x1f\x44\x65leteWorkflowExecutionResponse"\xc9\x02\n!ListOpenWorkflowExecutionsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x19\n\x11maximum_page_size\x18\x02 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c\x12\x42\n\x11start_time_filter\x18\x04 \x01(\x0b\x32\'.temporal.api.filter.v1.StartTimeFilter\x12K\n\x10\x65xecution_filter\x18\x05 \x01(\x0b\x32/.temporal.api.filter.v1.WorkflowExecutionFilterH\x00\x12\x41\n\x0btype_filter\x18\x06 \x01(\x0b\x32*.temporal.api.filter.v1.WorkflowTypeFilterH\x00\x42\t\n\x07\x66ilters"\x82\x01\n"ListOpenWorkflowExecutionsResponse\x12\x43\n\nexecutions\x18\x01 \x03(\x0b\x32/.temporal.api.workflow.v1.WorkflowExecutionInfo\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c"\x8a\x03\n#ListClosedWorkflowExecutionsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x19\n\x11maximum_page_size\x18\x02 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c\x12\x42\n\x11start_time_filter\x18\x04 \x01(\x0b\x32\'.temporal.api.filter.v1.StartTimeFilter\x12K\n\x10\x65xecution_filter\x18\x05 \x01(\x0b\x32/.temporal.api.filter.v1.WorkflowExecutionFilterH\x00\x12\x41\n\x0btype_filter\x18\x06 \x01(\x0b\x32*.temporal.api.filter.v1.WorkflowTypeFilterH\x00\x12=\n\rstatus_filter\x18\x07 \x01(\x0b\x32$.temporal.api.filter.v1.StatusFilterH\x00\x42\t\n\x07\x66ilters"\x84\x01\n$ListClosedWorkflowExecutionsResponse\x12\x43\n\nexecutions\x18\x01 \x03(\x0b\x32/.temporal.api.workflow.v1.WorkflowExecutionInfo\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c"m\n\x1dListWorkflowExecutionsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x11\n\tpage_size\x18\x02 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c\x12\r\n\x05query\x18\x04 \x01(\t"~\n\x1eListWorkflowExecutionsResponse\x12\x43\n\nexecutions\x18\x01 \x03(\x0b\x32/.temporal.api.workflow.v1.WorkflowExecutionInfo\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c"u\n%ListArchivedWorkflowExecutionsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x11\n\tpage_size\x18\x02 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c\x12\r\n\x05query\x18\x04 \x01(\t"\x86\x01\n&ListArchivedWorkflowExecutionsResponse\x12\x43\n\nexecutions\x18\x01 \x03(\x0b\x32/.temporal.api.workflow.v1.WorkflowExecutionInfo\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c"m\n\x1dScanWorkflowExecutionsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x11\n\tpage_size\x18\x02 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c\x12\r\n\x05query\x18\x04 \x01(\t"~\n\x1eScanWorkflowExecutionsResponse\x12\x43\n\nexecutions\x18\x01 \x03(\x0b\x32/.temporal.api.workflow.v1.WorkflowExecutionInfo\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c"B\n\x1e\x43ountWorkflowExecutionsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\r\n\x05query\x18\x02 \x01(\t"\xed\x01\n\x1f\x43ountWorkflowExecutionsResponse\x12\r\n\x05\x63ount\x18\x01 \x01(\x03\x12\x61\n\x06groups\x18\x02 \x03(\x0b\x32Q.temporal.api.workflowservice.v1.CountWorkflowExecutionsResponse.AggregationGroup\x1aX\n\x10\x41ggregationGroup\x12\x35\n\x0cgroup_values\x18\x01 \x03(\x0b\x32\x1f.temporal.api.common.v1.Payload\x12\r\n\x05\x63ount\x18\x02 \x01(\x03"\x1c\n\x1aGetSearchAttributesRequest"\xc9\x01\n\x1bGetSearchAttributesResponse\x12T\n\x04keys\x18\x01 \x03(\x0b\x32\x46.temporal.api.workflowservice.v1.GetSearchAttributesResponse.KeysEntry\x1aT\n\tKeysEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x36\n\x05value\x18\x02 \x01(\x0e\x32\'.temporal.api.enums.v1.IndexedValueType:\x02\x38\x01"\xe9\x02\n RespondQueryTaskCompletedRequest\x12\x12\n\ntask_token\x18\x01 \x01(\x0c\x12>\n\x0e\x63ompleted_type\x18\x02 \x01(\x0e\x32&.temporal.api.enums.v1.QueryResultType\x12\x36\n\x0cquery_result\x18\x03 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x15\n\rerror_message\x18\x04 \x01(\t\x12\x11\n\tnamespace\x18\x06 \x01(\t\x12\x31\n\x07\x66\x61ilure\x18\x07 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12=\n\x05\x63\x61use\x18\x08 \x01(\x0e\x32..temporal.api.enums.v1.WorkflowTaskFailedCause\x12\x17\n\x0fpoller_group_id\x18\t \x01(\tJ\x04\x08\x05\x10\x06"#\n!RespondQueryTaskCompletedResponse"n\n\x1bResetStickyTaskQueueRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12<\n\texecution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution"\x1e\n\x1cResetStickyTaskQueueResponse"\x9b\x02\n\x15ShutdownWorkerRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x19\n\x11sticky_task_queue\x18\x02 \x01(\t\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x0e\n\x06reason\x18\x04 \x01(\t\x12\x41\n\x10worker_heartbeat\x18\x05 \x01(\x0b\x32\'.temporal.api.worker.v1.WorkerHeartbeat\x12\x1b\n\x13worker_instance_key\x18\x06 \x01(\t\x12\x12\n\ntask_queue\x18\x07 \x01(\t\x12>\n\x10task_queue_types\x18\x08 \x03(\x0e\x32$.temporal.api.enums.v1.TaskQueueType"\x18\n\x16ShutdownWorkerResponse"\xe9\x01\n\x14QueryWorkflowRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12<\n\texecution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x33\n\x05query\x18\x03 \x01(\x0b\x32$.temporal.api.query.v1.WorkflowQuery\x12K\n\x16query_reject_condition\x18\x04 \x01(\x0e\x32+.temporal.api.enums.v1.QueryRejectCondition"\x8d\x01\n\x15QueryWorkflowResponse\x12\x36\n\x0cquery_result\x18\x01 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12<\n\x0equery_rejected\x18\x02 \x01(\x0b\x32$.temporal.api.query.v1.QueryRejected"s\n DescribeWorkflowExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12<\n\texecution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution"\x99\x05\n!DescribeWorkflowExecutionResponse\x12K\n\x10\x65xecution_config\x18\x01 \x01(\x0b\x32\x31.temporal.api.workflow.v1.WorkflowExecutionConfig\x12P\n\x17workflow_execution_info\x18\x02 \x01(\x0b\x32/.temporal.api.workflow.v1.WorkflowExecutionInfo\x12I\n\x12pending_activities\x18\x03 \x03(\x0b\x32-.temporal.api.workflow.v1.PendingActivityInfo\x12M\n\x10pending_children\x18\x04 \x03(\x0b\x32\x33.temporal.api.workflow.v1.PendingChildExecutionInfo\x12P\n\x15pending_workflow_task\x18\x05 \x01(\x0b\x32\x31.temporal.api.workflow.v1.PendingWorkflowTaskInfo\x12\x39\n\tcallbacks\x18\x06 \x03(\x0b\x32&.temporal.api.workflow.v1.CallbackInfo\x12U\n\x18pending_nexus_operations\x18\x07 \x03(\x0b\x32\x33.temporal.api.workflow.v1.PendingNexusOperationInfo\x12W\n\x16workflow_extended_info\x18\x08 \x01(\x0b\x32\x37.temporal.api.workflow.v1.WorkflowExecutionExtendedInfo"\x90\x04\n\x18\x44\x65scribeTaskQueueRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x38\n\ntask_queue\x18\x02 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12=\n\x0ftask_queue_type\x18\x03 \x01(\x0e\x32$.temporal.api.enums.v1.TaskQueueType\x12\x14\n\x0creport_stats\x18\x08 \x01(\x08\x12\x15\n\rreport_config\x18\x0b \x01(\x08\x12%\n\x19include_task_queue_status\x18\x04 \x01(\x08\x42\x02\x18\x01\x12\x42\n\x08\x61pi_mode\x18\x05 \x01(\x0e\x32,.temporal.api.enums.v1.DescribeTaskQueueModeB\x02\x18\x01\x12J\n\x08versions\x18\x06 \x01(\x0b\x32\x34.temporal.api.taskqueue.v1.TaskQueueVersionSelectionB\x02\x18\x01\x12\x42\n\x10task_queue_types\x18\x07 \x03(\x0e\x32$.temporal.api.enums.v1.TaskQueueTypeB\x02\x18\x01\x12\x1a\n\x0ereport_pollers\x18\t \x01(\x08\x42\x02\x18\x01\x12$\n\x18report_task_reachability\x18\n \x01(\x08\x42\x02\x18\x01"\xec\x07\n\x19\x44\x65scribeTaskQueueResponse\x12\x36\n\x07pollers\x18\x01 \x03(\x0b\x32%.temporal.api.taskqueue.v1.PollerInfo\x12\x38\n\x05stats\x18\x05 \x01(\x0b\x32).temporal.api.taskqueue.v1.TaskQueueStats\x12q\n\x15stats_by_priority_key\x18\x08 \x03(\x0b\x32R.temporal.api.workflowservice.v1.DescribeTaskQueueResponse.StatsByPriorityKeyEntry\x12K\n\x0fversioning_info\x18\x04 \x01(\x0b\x32\x32.temporal.api.taskqueue.v1.TaskQueueVersioningInfo\x12:\n\x06\x63onfig\x18\x06 \x01(\x0b\x32*.temporal.api.taskqueue.v1.TaskQueueConfig\x12k\n\x14\x65\x66\x66\x65\x63tive_rate_limit\x18\x07 \x01(\x0b\x32M.temporal.api.workflowservice.v1.DescribeTaskQueueResponse.EffectiveRateLimit\x12I\n\x11task_queue_status\x18\x02 \x01(\x0b\x32*.temporal.api.taskqueue.v1.TaskQueueStatusB\x02\x18\x01\x12g\n\rversions_info\x18\x03 \x03(\x0b\x32L.temporal.api.workflowservice.v1.DescribeTaskQueueResponse.VersionsInfoEntryB\x02\x18\x01\x1a\x64\n\x17StatsByPriorityKeyEntry\x12\x0b\n\x03key\x18\x01 \x01(\x05\x12\x38\n\x05value\x18\x02 \x01(\x0b\x32).temporal.api.taskqueue.v1.TaskQueueStats:\x02\x38\x01\x1at\n\x12\x45\x66\x66\x65\x63tiveRateLimit\x12\x1b\n\x13requests_per_second\x18\x01 \x01(\x02\x12\x41\n\x11rate_limit_source\x18\x02 \x01(\x0e\x32&.temporal.api.enums.v1.RateLimitSource\x1a\x64\n\x11VersionsInfoEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12>\n\x05value\x18\x02 \x01(\x0b\x32/.temporal.api.taskqueue.v1.TaskQueueVersionInfo:\x02\x38\x01"\x17\n\x15GetClusterInfoRequest"\xd1\x03\n\x16GetClusterInfoResponse\x12h\n\x11supported_clients\x18\x01 \x03(\x0b\x32M.temporal.api.workflowservice.v1.GetClusterInfoResponse.SupportedClientsEntry\x12\x16\n\x0eserver_version\x18\x02 \x01(\t\x12\x12\n\ncluster_id\x18\x03 \x01(\t\x12:\n\x0cversion_info\x18\x04 \x01(\x0b\x32$.temporal.api.version.v1.VersionInfo\x12\x14\n\x0c\x63luster_name\x18\x05 \x01(\t\x12\x1b\n\x13history_shard_count\x18\x06 \x01(\x05\x12\x19\n\x11persistence_store\x18\x07 \x01(\t\x12\x18\n\x10visibility_store\x18\x08 \x01(\t\x12 \n\x18initial_failover_version\x18\t \x01(\x03\x12"\n\x1a\x66\x61ilover_version_increment\x18\n \x01(\x03\x1a\x37\n\x15SupportedClientsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01"\x16\n\x14GetSystemInfoRequest"\x97\x04\n\x15GetSystemInfoResponse\x12\x16\n\x0eserver_version\x18\x01 \x01(\t\x12Y\n\x0c\x63\x61pabilities\x18\x02 \x01(\x0b\x32\x43.temporal.api.workflowservice.v1.GetSystemInfoResponse.Capabilities\x1a\x8a\x03\n\x0c\x43\x61pabilities\x12\x1f\n\x17signal_and_query_header\x18\x01 \x01(\x08\x12&\n\x1einternal_error_differentiation\x18\x02 \x01(\x08\x12*\n"activity_failure_include_heartbeat\x18\x03 \x01(\x08\x12\x1a\n\x12supports_schedules\x18\x04 \x01(\x08\x12"\n\x1a\x65ncoded_failure_attributes\x18\x05 \x01(\x08\x12!\n\x19\x62uild_id_based_versioning\x18\x06 \x01(\x08\x12\x13\n\x0bupsert_memo\x18\x07 \x01(\x08\x12\x1c\n\x14\x65\x61ger_workflow_start\x18\x08 \x01(\x08\x12\x14\n\x0csdk_metadata\x18\t \x01(\x08\x12\'\n\x1f\x63ount_group_by_execution_status\x18\n \x01(\x08\x12\r\n\x05nexus\x18\x0b \x01(\x08\x12!\n\x19server_scaled_deployments\x18\x0c \x01(\x08"m\n\x1eListTaskQueuePartitionsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x38\n\ntask_queue\x18\x02 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue"\xdf\x01\n\x1fListTaskQueuePartitionsResponse\x12]\n\x1e\x61\x63tivity_task_queue_partitions\x18\x01 \x03(\x0b\x32\x35.temporal.api.taskqueue.v1.TaskQueuePartitionMetadata\x12]\n\x1eworkflow_task_queue_partitions\x18\x02 \x03(\x0b\x32\x35.temporal.api.taskqueue.v1.TaskQueuePartitionMetadata"\xcc\x02\n\x15\x43reateScheduleRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bschedule_id\x18\x02 \x01(\t\x12\x34\n\x08schedule\x18\x03 \x01(\x0b\x32".temporal.api.schedule.v1.Schedule\x12>\n\rinitial_patch\x18\x04 \x01(\x0b\x32\'.temporal.api.schedule.v1.SchedulePatch\x12\x10\n\x08identity\x18\x05 \x01(\t\x12\x12\n\nrequest_id\x18\x06 \x01(\t\x12*\n\x04memo\x18\x07 \x01(\x0b\x32\x1c.temporal.api.common.v1.Memo\x12\x43\n\x11search_attributes\x18\x08 \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes"0\n\x16\x43reateScheduleResponse\x12\x16\n\x0e\x63onflict_token\x18\x01 \x01(\x0c"A\n\x17\x44\x65scribeScheduleRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bschedule_id\x18\x02 \x01(\t"\x8f\x02\n\x18\x44\x65scribeScheduleResponse\x12\x34\n\x08schedule\x18\x01 \x01(\x0b\x32".temporal.api.schedule.v1.Schedule\x12\x34\n\x04info\x18\x02 \x01(\x0b\x32&.temporal.api.schedule.v1.ScheduleInfo\x12*\n\x04memo\x18\x03 \x01(\x0b\x32\x1c.temporal.api.common.v1.Memo\x12\x43\n\x11search_attributes\x18\x04 \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes\x12\x16\n\x0e\x63onflict_token\x18\x05 \x01(\x0c"\xa4\x02\n\x15UpdateScheduleRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bschedule_id\x18\x02 \x01(\t\x12\x34\n\x08schedule\x18\x03 \x01(\x0b\x32".temporal.api.schedule.v1.Schedule\x12\x16\n\x0e\x63onflict_token\x18\x04 \x01(\x0c\x12\x10\n\x08identity\x18\x05 \x01(\t\x12\x12\n\nrequest_id\x18\x06 \x01(\t\x12\x43\n\x11search_attributes\x18\x07 \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes\x12*\n\x04memo\x18\x08 \x01(\x0b\x32\x1c.temporal.api.common.v1.Memo"\x18\n\x16UpdateScheduleResponse"\x9c\x01\n\x14PatchScheduleRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bschedule_id\x18\x02 \x01(\t\x12\x36\n\x05patch\x18\x03 \x01(\x0b\x32\'.temporal.api.schedule.v1.SchedulePatch\x12\x10\n\x08identity\x18\x04 \x01(\t\x12\x12\n\nrequest_id\x18\x05 \x01(\t"\x17\n\x15PatchScheduleResponse"\xa8\x01\n ListScheduleMatchingTimesRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bschedule_id\x18\x02 \x01(\t\x12.\n\nstart_time\x18\x03 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12,\n\x08\x65nd_time\x18\x04 \x01(\x0b\x32\x1a.google.protobuf.Timestamp"S\n!ListScheduleMatchingTimesResponse\x12.\n\nstart_time\x18\x01 \x03(\x0b\x32\x1a.google.protobuf.Timestamp"Q\n\x15\x44\x65leteScheduleRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bschedule_id\x18\x02 \x01(\t\x12\x10\n\x08identity\x18\x03 \x01(\t"\x18\n\x16\x44\x65leteScheduleResponse"l\n\x14ListSchedulesRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x19\n\x11maximum_page_size\x18\x02 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c\x12\r\n\x05query\x18\x04 \x01(\t"p\n\x15ListSchedulesResponse\x12>\n\tschedules\x18\x01 \x03(\x0b\x32+.temporal.api.schedule.v1.ScheduleListEntry\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c"9\n\x15\x43ountSchedulesRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\r\n\x05query\x18\x02 \x01(\t"\xdb\x01\n\x16\x43ountSchedulesResponse\x12\r\n\x05\x63ount\x18\x01 \x01(\x03\x12X\n\x06groups\x18\x02 \x03(\x0b\x32H.temporal.api.workflowservice.v1.CountSchedulesResponse.AggregationGroup\x1aX\n\x10\x41ggregationGroup\x12\x35\n\x0cgroup_values\x18\x01 \x03(\x0b\x32\x1f.temporal.api.common.v1.Payload\x12\r\n\x05\x63ount\x18\x02 \x01(\x03"\x86\x05\n\'UpdateWorkerBuildIdCompatibilityRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x12\n\ntask_queue\x18\x02 \x01(\t\x12-\n#add_new_build_id_in_new_default_set\x18\x03 \x01(\tH\x00\x12\x87\x01\n\x1b\x61\x64\x64_new_compatible_build_id\x18\x04 \x01(\x0b\x32`.temporal.api.workflowservice.v1.UpdateWorkerBuildIdCompatibilityRequest.AddNewCompatibleVersionH\x00\x12!\n\x17promote_set_by_build_id\x18\x05 \x01(\tH\x00\x12%\n\x1bpromote_build_id_within_set\x18\x06 \x01(\tH\x00\x12h\n\nmerge_sets\x18\x07 \x01(\x0b\x32R.temporal.api.workflowservice.v1.UpdateWorkerBuildIdCompatibilityRequest.MergeSetsH\x00\x1ao\n\x17\x41\x64\x64NewCompatibleVersion\x12\x14\n\x0cnew_build_id\x18\x01 \x01(\t\x12$\n\x1c\x65xisting_compatible_build_id\x18\x02 \x01(\t\x12\x18\n\x10make_set_default\x18\x03 \x01(\x08\x1aI\n\tMergeSets\x12\x1c\n\x14primary_set_build_id\x18\x01 \x01(\t\x12\x1e\n\x16secondary_set_build_id\x18\x02 \x01(\tB\x0b\n\toperation"@\n(UpdateWorkerBuildIdCompatibilityResponseJ\x04\x08\x01\x10\x02R\x0eversion_set_id"_\n$GetWorkerBuildIdCompatibilityRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x12\n\ntask_queue\x18\x02 \x01(\t\x12\x10\n\x08max_sets\x18\x03 \x01(\x05"t\n%GetWorkerBuildIdCompatibilityResponse\x12K\n\x12major_version_sets\x18\x01 \x03(\x0b\x32/.temporal.api.taskqueue.v1.CompatibleVersionSet"\xb5\r\n"UpdateWorkerVersioningRulesRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x12\n\ntask_queue\x18\x02 \x01(\t\x12\x16\n\x0e\x63onflict_token\x18\x03 \x01(\x0c\x12\x81\x01\n\x16insert_assignment_rule\x18\x04 \x01(\x0b\x32_.temporal.api.workflowservice.v1.UpdateWorkerVersioningRulesRequest.InsertBuildIdAssignmentRuleH\x00\x12\x83\x01\n\x17replace_assignment_rule\x18\x05 \x01(\x0b\x32`.temporal.api.workflowservice.v1.UpdateWorkerVersioningRulesRequest.ReplaceBuildIdAssignmentRuleH\x00\x12\x81\x01\n\x16\x64\x65lete_assignment_rule\x18\x06 \x01(\x0b\x32_.temporal.api.workflowservice.v1.UpdateWorkerVersioningRulesRequest.DeleteBuildIdAssignmentRuleH\x00\x12\x8c\x01\n\x1c\x61\x64\x64_compatible_redirect_rule\x18\x07 \x01(\x0b\x32\x64.temporal.api.workflowservice.v1.UpdateWorkerVersioningRulesRequest.AddCompatibleBuildIdRedirectRuleH\x00\x12\x94\x01\n replace_compatible_redirect_rule\x18\x08 \x01(\x0b\x32h.temporal.api.workflowservice.v1.UpdateWorkerVersioningRulesRequest.ReplaceCompatibleBuildIdRedirectRuleH\x00\x12\x92\x01\n\x1f\x64\x65lete_compatible_redirect_rule\x18\t \x01(\x0b\x32g.temporal.api.workflowservice.v1.UpdateWorkerVersioningRulesRequest.DeleteCompatibleBuildIdRedirectRuleH\x00\x12l\n\x0f\x63ommit_build_id\x18\n \x01(\x0b\x32Q.temporal.api.workflowservice.v1.UpdateWorkerVersioningRulesRequest.CommitBuildIdH\x00\x1aq\n\x1bInsertBuildIdAssignmentRule\x12\x12\n\nrule_index\x18\x01 \x01(\x05\x12>\n\x04rule\x18\x02 \x01(\x0b\x32\x30.temporal.api.taskqueue.v1.BuildIdAssignmentRule\x1a\x81\x01\n\x1cReplaceBuildIdAssignmentRule\x12\x12\n\nrule_index\x18\x01 \x01(\x05\x12>\n\x04rule\x18\x02 \x01(\x0b\x32\x30.temporal.api.taskqueue.v1.BuildIdAssignmentRule\x12\r\n\x05\x66orce\x18\x03 \x01(\x08\x1a@\n\x1b\x44\x65leteBuildIdAssignmentRule\x12\x12\n\nrule_index\x18\x01 \x01(\x05\x12\r\n\x05\x66orce\x18\x02 \x01(\x08\x1aj\n AddCompatibleBuildIdRedirectRule\x12\x46\n\x04rule\x18\x01 \x01(\x0b\x32\x38.temporal.api.taskqueue.v1.CompatibleBuildIdRedirectRule\x1an\n$ReplaceCompatibleBuildIdRedirectRule\x12\x46\n\x04rule\x18\x01 \x01(\x0b\x32\x38.temporal.api.taskqueue.v1.CompatibleBuildIdRedirectRule\x1a>\n#DeleteCompatibleBuildIdRedirectRule\x12\x17\n\x0fsource_build_id\x18\x01 \x01(\t\x1a\x37\n\rCommitBuildId\x12\x17\n\x0ftarget_build_id\x18\x01 \x01(\t\x12\r\n\x05\x66orce\x18\x02 \x01(\x08\x42\x0b\n\toperation"\xfc\x01\n#UpdateWorkerVersioningRulesResponse\x12U\n\x10\x61ssignment_rules\x18\x01 \x03(\x0b\x32;.temporal.api.taskqueue.v1.TimestampedBuildIdAssignmentRule\x12\x66\n\x19\x63ompatible_redirect_rules\x18\x02 \x03(\x0b\x32\x43.temporal.api.taskqueue.v1.TimestampedCompatibleBuildIdRedirectRule\x12\x16\n\x0e\x63onflict_token\x18\x03 \x01(\x0c"H\n\x1fGetWorkerVersioningRulesRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x12\n\ntask_queue\x18\x02 \x01(\t"\xf9\x01\n GetWorkerVersioningRulesResponse\x12U\n\x10\x61ssignment_rules\x18\x01 \x03(\x0b\x32;.temporal.api.taskqueue.v1.TimestampedBuildIdAssignmentRule\x12\x66\n\x19\x63ompatible_redirect_rules\x18\x02 \x03(\x0b\x32\x43.temporal.api.taskqueue.v1.TimestampedCompatibleBuildIdRedirectRule\x12\x16\n\x0e\x63onflict_token\x18\x03 \x01(\x0c"\x9c\x01\n GetWorkerTaskReachabilityRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x11\n\tbuild_ids\x18\x02 \x03(\t\x12\x13\n\x0btask_queues\x18\x03 \x03(\t\x12=\n\x0creachability\x18\x04 \x01(\x0e\x32\'.temporal.api.enums.v1.TaskReachability"r\n!GetWorkerTaskReachabilityResponse\x12M\n\x15\x62uild_id_reachability\x18\x01 \x03(\x0b\x32..temporal.api.taskqueue.v1.BuildIdReachability"\x85\x02\n\x1eUpdateWorkflowExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x45\n\x12workflow_execution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x1e\n\x16\x66irst_execution_run_id\x18\x03 \x01(\t\x12\x37\n\x0bwait_policy\x18\x04 \x01(\x0b\x32".temporal.api.update.v1.WaitPolicy\x12\x30\n\x07request\x18\x05 \x01(\x0b\x32\x1f.temporal.api.update.v1.Request"\xd7\x01\n\x1fUpdateWorkflowExecutionResponse\x12\x35\n\nupdate_ref\x18\x01 \x01(\x0b\x32!.temporal.api.update.v1.UpdateRef\x12\x30\n\x07outcome\x18\x02 \x01(\x0b\x32\x1f.temporal.api.update.v1.Outcome\x12K\n\x05stage\x18\x03 \x01(\x0e\x32<.temporal.api.enums.v1.UpdateWorkflowExecutionLifecycleStage"\xf4\x07\n\x1aStartBatchOperationRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x18\n\x10visibility_query\x18\x02 \x01(\t\x12\x0e\n\x06job_id\x18\x03 \x01(\t\x12\x0e\n\x06reason\x18\x04 \x01(\t\x12=\n\nexecutions\x18\x05 \x03(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12!\n\x19max_operations_per_second\x18\x06 \x01(\x02\x12Q\n\x15termination_operation\x18\n \x01(\x0b\x32\x30.temporal.api.batch.v1.BatchOperationTerminationH\x00\x12G\n\x10signal_operation\x18\x0b \x01(\x0b\x32+.temporal.api.batch.v1.BatchOperationSignalH\x00\x12S\n\x16\x63\x61ncellation_operation\x18\x0c \x01(\x0b\x32\x31.temporal.api.batch.v1.BatchOperationCancellationH\x00\x12K\n\x12\x64\x65letion_operation\x18\r \x01(\x0b\x32-.temporal.api.batch.v1.BatchOperationDeletionH\x00\x12\x45\n\x0freset_operation\x18\x0e \x01(\x0b\x32*.temporal.api.batch.v1.BatchOperationResetH\x00\x12p\n!update_workflow_options_operation\x18\x0f \x01(\x0b\x32\x43.temporal.api.batch.v1.BatchOperationUpdateWorkflowExecutionOptionsH\x00\x12^\n\x1cunpause_activities_operation\x18\x10 \x01(\x0b\x32\x36.temporal.api.batch.v1.BatchOperationUnpauseActivitiesH\x00\x12Z\n\x1areset_activities_operation\x18\x11 \x01(\x0b\x32\x34.temporal.api.batch.v1.BatchOperationResetActivitiesH\x00\x12g\n!update_activity_options_operation\x18\x12 \x01(\x0b\x32:.temporal.api.batch.v1.BatchOperationUpdateActivityOptionsH\x00\x42\x0b\n\toperation"\x1d\n\x1bStartBatchOperationResponse"`\n\x19StopBatchOperationRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x0e\n\x06job_id\x18\x02 \x01(\t\x12\x0e\n\x06reason\x18\x03 \x01(\t\x12\x10\n\x08identity\x18\x04 \x01(\t"\x1c\n\x1aStopBatchOperationResponse"B\n\x1d\x44\x65scribeBatchOperationRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x0e\n\x06job_id\x18\x02 \x01(\t"\x92\x03\n\x1e\x44\x65scribeBatchOperationResponse\x12\x41\n\x0eoperation_type\x18\x01 \x01(\x0e\x32).temporal.api.enums.v1.BatchOperationType\x12\x0e\n\x06job_id\x18\x02 \x01(\t\x12\x39\n\x05state\x18\x03 \x01(\x0e\x32*.temporal.api.enums.v1.BatchOperationState\x12.\n\nstart_time\x18\x04 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12.\n\nclose_time\x18\x05 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x1d\n\x15total_operation_count\x18\x06 \x01(\x03\x12 \n\x18\x63omplete_operation_count\x18\x07 \x01(\x03\x12\x1f\n\x17\x66\x61ilure_operation_count\x18\x08 \x01(\x03\x12\x10\n\x08identity\x18\t \x01(\t\x12\x0e\n\x06reason\x18\n \x01(\t"[\n\x1aListBatchOperationsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x11\n\tpage_size\x18\x02 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c"y\n\x1bListBatchOperationsResponse\x12\x41\n\x0eoperation_info\x18\x01 \x03(\x0b\x32).temporal.api.batch.v1.BatchOperationInfo\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c"\xb9\x01\n"PollWorkflowExecutionUpdateRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x35\n\nupdate_ref\x18\x02 \x01(\x0b\x32!.temporal.api.update.v1.UpdateRef\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x37\n\x0bwait_policy\x18\x04 \x01(\x0b\x32".temporal.api.update.v1.WaitPolicy"\xdb\x01\n#PollWorkflowExecutionUpdateResponse\x12\x30\n\x07outcome\x18\x01 \x01(\x0b\x32\x1f.temporal.api.update.v1.Outcome\x12K\n\x05stage\x18\x02 \x01(\x0e\x32<.temporal.api.enums.v1.UpdateWorkflowExecutionLifecycleStage\x12\x35\n\nupdate_ref\x18\x03 \x01(\x0b\x32!.temporal.api.update.v1.UpdateRef"\xa0\x03\n\x19PollNexusTaskQueueRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x38\n\ntask_queue\x18\x03 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12\x17\n\x0fpoller_group_id\x18\t \x01(\t\x12\x10\n\x08identity\x18\x02 \x01(\t\x12\x1b\n\x13worker_instance_key\x18\x08 \x01(\t\x12Z\n\x1bworker_version_capabilities\x18\x04 \x01(\x0b\x32\x31.temporal.api.common.v1.WorkerVersionCapabilitiesB\x02\x18\x01\x12O\n\x12\x64\x65ployment_options\x18\x06 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentOptions\x12\x41\n\x10worker_heartbeat\x18\x07 \x03(\x0b\x32\'.temporal.api.worker.v1.WorkerHeartbeat"\x95\x02\n\x1aPollNexusTaskQueueResponse\x12\x12\n\ntask_token\x18\x01 \x01(\x0c\x12/\n\x07request\x18\x02 \x01(\x0b\x32\x1e.temporal.api.nexus.v1.Request\x12Q\n\x17poller_scaling_decision\x18\x03 \x01(\x0b\x32\x30.temporal.api.taskqueue.v1.PollerScalingDecision\x12\x17\n\x0fpoller_group_id\x18\x04 \x01(\t\x12\x46\n\x12poller_group_infos\x18\x05 \x03(\x0b\x32*.temporal.api.taskqueue.v1.PollerGroupInfo"\xa7\x01\n RespondNexusTaskCompletedRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x10\n\x08identity\x18\x02 \x01(\t\x12\x12\n\ntask_token\x18\x03 \x01(\x0c\x12\x31\n\x08response\x18\x04 \x01(\x0b\x32\x1f.temporal.api.nexus.v1.Response\x12\x17\n\x0fpoller_group_id\x18\x05 \x01(\t"#\n!RespondNexusTaskCompletedResponse"\xdc\x01\n\x1dRespondNexusTaskFailedRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x10\n\x08identity\x18\x02 \x01(\t\x12\x12\n\ntask_token\x18\x03 \x01(\x0c\x12\x36\n\x05\x65rror\x18\x04 \x01(\x0b\x32#.temporal.api.nexus.v1.HandlerErrorB\x02\x18\x01\x12\x31\n\x07\x66\x61ilure\x18\x05 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12\x17\n\x0fpoller_group_id\x18\x06 \x01(\t" \n\x1eRespondNexusTaskFailedResponse"\xf4\x02\n\x1c\x45xecuteMultiOperationRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12[\n\noperations\x18\x02 \x03(\x0b\x32G.temporal.api.workflowservice.v1.ExecuteMultiOperationRequest.Operation\x12\x13\n\x0bresource_id\x18\x03 \x01(\t\x1a\xce\x01\n\tOperation\x12X\n\x0estart_workflow\x18\x01 \x01(\x0b\x32>.temporal.api.workflowservice.v1.StartWorkflowExecutionRequestH\x00\x12Z\n\x0fupdate_workflow\x18\x02 \x01(\x0b\x32?.temporal.api.workflowservice.v1.UpdateWorkflowExecutionRequestH\x00\x42\x0b\n\toperation"\xcc\x02\n\x1d\x45xecuteMultiOperationResponse\x12Z\n\tresponses\x18\x01 \x03(\x0b\x32G.temporal.api.workflowservice.v1.ExecuteMultiOperationResponse.Response\x1a\xce\x01\n\x08Response\x12Y\n\x0estart_workflow\x18\x01 \x01(\x0b\x32?.temporal.api.workflowservice.v1.StartWorkflowExecutionResponseH\x00\x12[\n\x0fupdate_workflow\x18\x02 \x01(\x0b\x32@.temporal.api.workflowservice.v1.UpdateWorkflowExecutionResponseH\x00\x42\n\n\x08response"\xd0\x02\n\x1cUpdateActivityOptionsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12<\n\texecution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x43\n\x10\x61\x63tivity_options\x18\x04 \x01(\x0b\x32).temporal.api.activity.v1.ActivityOptions\x12/\n\x0bupdate_mask\x18\x05 \x01(\x0b\x32\x1a.google.protobuf.FieldMask\x12\x0c\n\x02id\x18\x06 \x01(\tH\x00\x12\x0e\n\x04type\x18\x07 \x01(\tH\x00\x12\x13\n\tmatch_all\x18\t \x01(\x08H\x00\x12\x18\n\x10restore_original\x18\x08 \x01(\x08\x42\n\n\x08\x61\x63tivity"d\n\x1dUpdateActivityOptionsResponse\x12\x43\n\x10\x61\x63tivity_options\x18\x01 \x01(\x0b\x32).temporal.api.activity.v1.ActivityOptions"\xb3\x01\n\x14PauseActivityRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12<\n\texecution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x0c\n\x02id\x18\x04 \x01(\tH\x00\x12\x0e\n\x04type\x18\x05 \x01(\tH\x00\x12\x0e\n\x06reason\x18\x06 \x01(\tB\n\n\x08\x61\x63tivity"\x17\n\x15PauseActivityResponse"\x98\x02\n\x16UnpauseActivityRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12<\n\texecution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x0c\n\x02id\x18\x04 \x01(\tH\x00\x12\x0e\n\x04type\x18\x05 \x01(\tH\x00\x12\x15\n\x0bunpause_all\x18\x06 \x01(\x08H\x00\x12\x16\n\x0ereset_attempts\x18\x07 \x01(\x08\x12\x17\n\x0freset_heartbeat\x18\x08 \x01(\x08\x12)\n\x06jitter\x18\t \x01(\x0b\x32\x19.google.protobuf.DurationB\n\n\x08\x61\x63tivity"\x19\n\x17UnpauseActivityResponse"\xb3\x02\n\x14ResetActivityRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12<\n\texecution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x0c\n\x02id\x18\x04 \x01(\tH\x00\x12\x0e\n\x04type\x18\x05 \x01(\tH\x00\x12\x13\n\tmatch_all\x18\n \x01(\x08H\x00\x12\x17\n\x0freset_heartbeat\x18\x06 \x01(\x08\x12\x13\n\x0bkeep_paused\x18\x07 \x01(\x08\x12)\n\x06jitter\x18\x08 \x01(\x0b\x32\x19.google.protobuf.Duration\x12 \n\x18restore_original_options\x18\t \x01(\x08\x42\n\n\x08\x61\x63tivity"\x17\n\x15ResetActivityResponse"\x9c\x02\n%UpdateWorkflowExecutionOptionsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x45\n\x12workflow_execution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12V\n\x1aworkflow_execution_options\x18\x03 \x01(\x0b\x32\x32.temporal.api.workflow.v1.WorkflowExecutionOptions\x12/\n\x0bupdate_mask\x18\x04 \x01(\x0b\x32\x1a.google.protobuf.FieldMask\x12\x10\n\x08identity\x18\x05 \x01(\t"\x80\x01\n&UpdateWorkflowExecutionOptionsResponse\x12V\n\x1aworkflow_execution_options\x18\x01 \x01(\x0b\x32\x32.temporal.api.workflow.v1.WorkflowExecutionOptions"j\n\x19\x44\x65scribeDeploymentRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12:\n\ndeployment\x18\x02 \x01(\x0b\x32&.temporal.api.deployment.v1.Deployment"a\n\x1a\x44\x65scribeDeploymentResponse\x12\x43\n\x0f\x64\x65ployment_info\x18\x01 \x01(\x0b\x32*.temporal.api.deployment.v1.DeploymentInfo"\xc2\x01\n&DescribeWorkerDeploymentVersionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x07version\x18\x02 \x01(\tB\x02\x18\x01\x12O\n\x12\x64\x65ployment_version\x18\x03 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersion\x12\x1f\n\x17report_task_queue_stats\x18\x04 \x01(\x08"\x8c\x05\n\'DescribeWorkerDeploymentVersionResponse\x12_\n\x1eworker_deployment_version_info\x18\x01 \x01(\x0b\x32\x37.temporal.api.deployment.v1.WorkerDeploymentVersionInfo\x12v\n\x13version_task_queues\x18\x02 \x03(\x0b\x32Y.temporal.api.workflowservice.v1.DescribeWorkerDeploymentVersionResponse.VersionTaskQueue\x1a\x87\x03\n\x10VersionTaskQueue\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x32\n\x04type\x18\x02 \x01(\x0e\x32$.temporal.api.enums.v1.TaskQueueType\x12\x38\n\x05stats\x18\x03 \x01(\x0b\x32).temporal.api.taskqueue.v1.TaskQueueStats\x12\x90\x01\n\x15stats_by_priority_key\x18\x04 \x03(\x0b\x32q.temporal.api.workflowservice.v1.DescribeWorkerDeploymentVersionResponse.VersionTaskQueue.StatsByPriorityKeyEntry\x1a\x64\n\x17StatsByPriorityKeyEntry\x12\x0b\n\x03key\x18\x01 \x01(\x05\x12\x38\n\x05value\x18\x02 \x01(\x0b\x32).temporal.api.taskqueue.v1.TaskQueueStats:\x02\x38\x01"M\n\x1f\x44\x65scribeWorkerDeploymentRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x17\n\x0f\x64\x65ployment_name\x18\x02 \x01(\t"\x8c\x01\n DescribeWorkerDeploymentResponse\x12\x16\n\x0e\x63onflict_token\x18\x01 \x01(\x0c\x12P\n\x16worker_deployment_info\x18\x02 \x01(\x0b\x32\x30.temporal.api.deployment.v1.WorkerDeploymentInfo"l\n\x16ListDeploymentsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x11\n\tpage_size\x18\x02 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c\x12\x13\n\x0bseries_name\x18\x04 \x01(\t"w\n\x17ListDeploymentsResponse\x12\x17\n\x0fnext_page_token\x18\x01 \x01(\x0c\x12\x43\n\x0b\x64\x65ployments\x18\x02 \x03(\x0b\x32..temporal.api.deployment.v1.DeploymentListInfo"\xcd\x01\n\x1bSetCurrentDeploymentRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12:\n\ndeployment\x18\x02 \x01(\x0b\x32&.temporal.api.deployment.v1.Deployment\x12\x10\n\x08identity\x18\x03 \x01(\t\x12M\n\x0fupdate_metadata\x18\x04 \x01(\x0b\x32\x34.temporal.api.deployment.v1.UpdateDeploymentMetadata"\xb9\x01\n\x1cSetCurrentDeploymentResponse\x12K\n\x17\x63urrent_deployment_info\x18\x01 \x01(\x0b\x32*.temporal.api.deployment.v1.DeploymentInfo\x12L\n\x18previous_deployment_info\x18\x02 \x01(\x0b\x32*.temporal.api.deployment.v1.DeploymentInfo"\xe5\x01\n(SetWorkerDeploymentCurrentVersionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x17\n\x0f\x64\x65ployment_name\x18\x02 \x01(\t\x12\x13\n\x07version\x18\x03 \x01(\tB\x02\x18\x01\x12\x10\n\x08\x62uild_id\x18\x07 \x01(\t\x12\x16\n\x0e\x63onflict_token\x18\x04 \x01(\x0c\x12\x10\n\x08identity\x18\x05 \x01(\t\x12"\n\x1aignore_missing_task_queues\x18\x06 \x01(\x08\x12\x18\n\x10\x61llow_no_pollers\x18\t \x01(\x08"\xbf\x01\n)SetWorkerDeploymentCurrentVersionResponse\x12\x16\n\x0e\x63onflict_token\x18\x01 \x01(\x0c\x12\x1c\n\x10previous_version\x18\x02 \x01(\tB\x02\x18\x01\x12\\\n\x1bprevious_deployment_version\x18\x03 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersionB\x02\x18\x01"\xf9\x01\n(SetWorkerDeploymentRampingVersionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x17\n\x0f\x64\x65ployment_name\x18\x02 \x01(\t\x12\x13\n\x07version\x18\x03 \x01(\tB\x02\x18\x01\x12\x10\n\x08\x62uild_id\x18\x08 \x01(\t\x12\x12\n\npercentage\x18\x04 \x01(\x02\x12\x16\n\x0e\x63onflict_token\x18\x05 \x01(\x0c\x12\x10\n\x08identity\x18\x06 \x01(\t\x12"\n\x1aignore_missing_task_queues\x18\x07 \x01(\x08\x12\x18\n\x10\x61llow_no_pollers\x18\n \x01(\x08"\xe0\x01\n)SetWorkerDeploymentRampingVersionResponse\x12\x16\n\x0e\x63onflict_token\x18\x01 \x01(\x0c\x12\x1c\n\x10previous_version\x18\x02 \x01(\tB\x02\x18\x01\x12\\\n\x1bprevious_deployment_version\x18\x04 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersionB\x02\x18\x01\x12\x1f\n\x13previous_percentage\x18\x03 \x01(\x02\x42\x02\x18\x01"q\n\x1d\x43reateWorkerDeploymentRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x17\n\x0f\x64\x65ployment_name\x18\x02 \x01(\t\x12\x10\n\x08identity\x18\x04 \x01(\t\x12\x12\n\nrequest_id\x18\x05 \x01(\t"8\n\x1e\x43reateWorkerDeploymentResponse\x12\x16\n\x0e\x63onflict_token\x18\x01 \x01(\x0c"]\n\x1cListWorkerDeploymentsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x11\n\tpage_size\x18\x02 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c"\x9f\x05\n\x1dListWorkerDeploymentsResponse\x12\x17\n\x0fnext_page_token\x18\x01 \x01(\x0c\x12r\n\x12worker_deployments\x18\x02 \x03(\x0b\x32V.temporal.api.workflowservice.v1.ListWorkerDeploymentsResponse.WorkerDeploymentSummary\x1a\xf0\x03\n\x17WorkerDeploymentSummary\x12\x0c\n\x04name\x18\x01 \x01(\t\x12/\n\x0b\x63reate_time\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x41\n\x0erouting_config\x18\x03 \x01(\x0b\x32).temporal.api.deployment.v1.RoutingConfig\x12o\n\x16latest_version_summary\x18\x04 \x01(\x0b\x32O.temporal.api.deployment.v1.WorkerDeploymentInfo.WorkerDeploymentVersionSummary\x12p\n\x17\x63urrent_version_summary\x18\x05 \x01(\x0b\x32O.temporal.api.deployment.v1.WorkerDeploymentInfo.WorkerDeploymentVersionSummary\x12p\n\x17ramping_version_summary\x18\x06 \x01(\x0b\x32O.temporal.api.deployment.v1.WorkerDeploymentInfo.WorkerDeploymentVersionSummary"\xf0\x01\n$CreateWorkerDeploymentVersionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12O\n\x12\x64\x65ployment_version\x18\x02 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersion\x12>\n\x0e\x63ompute_config\x18\x04 \x01(\x0b\x32&.temporal.api.compute.v1.ComputeConfig\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x12\n\nrequest_id\x18\x05 \x01(\t"\'\n%CreateWorkerDeploymentVersionResponse"\xc8\x01\n$DeleteWorkerDeploymentVersionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x07version\x18\x02 \x01(\tB\x02\x18\x01\x12O\n\x12\x64\x65ployment_version\x18\x05 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersion\x12\x15\n\rskip_drainage\x18\x03 \x01(\x08\x12\x10\n\x08identity\x18\x04 \x01(\t"\'\n%DeleteWorkerDeploymentVersionResponse"]\n\x1d\x44\x65leteWorkerDeploymentRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x17\n\x0f\x64\x65ployment_name\x18\x02 \x01(\t\x12\x10\n\x08identity\x18\x03 \x01(\t" \n\x1e\x44\x65leteWorkerDeploymentResponse"\x84\x04\n1UpdateWorkerDeploymentVersionComputeConfigRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12O\n\x12\x64\x65ployment_version\x18\x02 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersion\x12\x99\x01\n\x1d\x63ompute_config_scaling_groups\x18\x06 \x03(\x0b\x32r.temporal.api.workflowservice.v1.UpdateWorkerDeploymentVersionComputeConfigRequest.ComputeConfigScalingGroupsEntry\x12,\n$remove_compute_config_scaling_groups\x18\x07 \x03(\t\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x12\n\nrequest_id\x18\x04 \x01(\t\x1a{\n\x1f\x43omputeConfigScalingGroupsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12G\n\x05value\x18\x02 \x01(\x0b\x32\x38.temporal.api.compute.v1.ComputeConfigScalingGroupUpdate:\x02\x38\x01"4\n2UpdateWorkerDeploymentVersionComputeConfigResponse"\xf4\x03\n3ValidateWorkerDeploymentVersionComputeConfigRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12O\n\x12\x64\x65ployment_version\x18\x02 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersion\x12\x9b\x01\n\x1d\x63ompute_config_scaling_groups\x18\x06 \x03(\x0b\x32t.temporal.api.workflowservice.v1.ValidateWorkerDeploymentVersionComputeConfigRequest.ComputeConfigScalingGroupsEntry\x12,\n$remove_compute_config_scaling_groups\x18\x07 \x03(\t\x12\x10\n\x08identity\x18\x03 \x01(\t\x1a{\n\x1f\x43omputeConfigScalingGroupsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12G\n\x05value\x18\x02 \x01(\x0b\x32\x38.temporal.api.compute.v1.ComputeConfigScalingGroupUpdate:\x02\x38\x01"6\n4ValidateWorkerDeploymentVersionComputeConfigResponse"\xa2\x03\n,UpdateWorkerDeploymentVersionMetadataRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x07version\x18\x02 \x01(\tB\x02\x18\x01\x12O\n\x12\x64\x65ployment_version\x18\x05 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersion\x12x\n\x0eupsert_entries\x18\x03 \x03(\x0b\x32`.temporal.api.workflowservice.v1.UpdateWorkerDeploymentVersionMetadataRequest.UpsertEntriesEntry\x12\x16\n\x0eremove_entries\x18\x04 \x03(\t\x12\x10\n\x08identity\x18\x06 \x01(\t\x1aU\n\x12UpsertEntriesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12.\n\x05value\x18\x02 \x01(\x0b\x32\x1f.temporal.api.common.v1.Payload:\x02\x38\x01"n\n-UpdateWorkerDeploymentVersionMetadataResponse\x12=\n\x08metadata\x18\x01 \x01(\x0b\x32+.temporal.api.deployment.v1.VersionMetadata"\xbd\x01\n!SetWorkerDeploymentManagerRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x17\n\x0f\x64\x65ployment_name\x18\x02 \x01(\t\x12\x1a\n\x10manager_identity\x18\x03 \x01(\tH\x00\x12\x0e\n\x04self\x18\x04 \x01(\x08H\x00\x12\x16\n\x0e\x63onflict_token\x18\x05 \x01(\x0c\x12\x10\n\x08identity\x18\x06 \x01(\tB\x16\n\x14new_manager_identity"c\n"SetWorkerDeploymentManagerResponse\x12\x16\n\x0e\x63onflict_token\x18\x01 \x01(\x0c\x12%\n\x19previous_manager_identity\x18\x02 \x01(\tB\x02\x18\x01"E\n\x1bGetCurrentDeploymentRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bseries_name\x18\x02 \x01(\t"k\n\x1cGetCurrentDeploymentResponse\x12K\n\x17\x63urrent_deployment_info\x18\x01 \x01(\x0b\x32*.temporal.api.deployment.v1.DeploymentInfo"q\n GetDeploymentReachabilityRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12:\n\ndeployment\x18\x02 \x01(\x0b\x32&.temporal.api.deployment.v1.Deployment"\xe3\x01\n!GetDeploymentReachabilityResponse\x12\x43\n\x0f\x64\x65ployment_info\x18\x01 \x01(\x0b\x32*.temporal.api.deployment.v1.DeploymentInfo\x12\x43\n\x0creachability\x18\x02 \x01(\x0e\x32-.temporal.api.enums.v1.DeploymentReachability\x12\x34\n\x10last_update_time\x18\x03 \x01(\x0b\x32\x1a.google.protobuf.Timestamp"\xb4\x01\n\x19\x43reateWorkflowRuleRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x35\n\x04spec\x18\x02 \x01(\x0b\x32\'.temporal.api.rules.v1.WorkflowRuleSpec\x12\x12\n\nforce_scan\x18\x03 \x01(\x08\x12\x12\n\nrequest_id\x18\x04 \x01(\t\x12\x10\n\x08identity\x18\x05 \x01(\t\x12\x13\n\x0b\x64\x65scription\x18\x06 \x01(\t"_\n\x1a\x43reateWorkflowRuleResponse\x12\x31\n\x04rule\x18\x01 \x01(\x0b\x32#.temporal.api.rules.v1.WorkflowRule\x12\x0e\n\x06job_id\x18\x02 \x01(\t"A\n\x1b\x44\x65scribeWorkflowRuleRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x0f\n\x07rule_id\x18\x02 \x01(\t"Q\n\x1c\x44\x65scribeWorkflowRuleResponse\x12\x31\n\x04rule\x18\x01 \x01(\x0b\x32#.temporal.api.rules.v1.WorkflowRule"?\n\x19\x44\x65leteWorkflowRuleRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x0f\n\x07rule_id\x18\x02 \x01(\t"\x1c\n\x1a\x44\x65leteWorkflowRuleResponse"F\n\x18ListWorkflowRulesRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c"h\n\x19ListWorkflowRulesResponse\x12\x32\n\x05rules\x18\x01 \x03(\x0b\x32#.temporal.api.rules.v1.WorkflowRule\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c"\xce\x01\n\x1aTriggerWorkflowRuleRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12<\n\texecution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x0c\n\x02id\x18\x04 \x01(\tH\x00\x12\x37\n\x04spec\x18\x05 \x01(\x0b\x32\'.temporal.api.rules.v1.WorkflowRuleSpecH\x00\x12\x10\n\x08identity\x18\x03 \x01(\tB\x06\n\x04rule".\n\x1bTriggerWorkflowRuleResponse\x12\x0f\n\x07\x61pplied\x18\x01 \x01(\x08"\x9b\x01\n\x1cRecordWorkerHeartbeatRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x10\n\x08identity\x18\x02 \x01(\t\x12\x41\n\x10worker_heartbeat\x18\x03 \x03(\x0b\x32\'.temporal.api.worker.v1.WorkerHeartbeat\x12\x13\n\x0bresource_id\x18\x04 \x01(\t"\x1f\n\x1dRecordWorkerHeartbeatResponse"b\n\x12ListWorkersRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x11\n\tpage_size\x18\x02 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c\x12\r\n\x05query\x18\x04 \x01(\t"\xa5\x01\n\x13ListWorkersResponse\x12<\n\x0cworkers_info\x18\x01 \x03(\x0b\x32".temporal.api.worker.v1.WorkerInfoB\x02\x18\x01\x12\x37\n\x07workers\x18\x03 \x03(\x0b\x32&.temporal.api.worker.v1.WorkerListInfo\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c"\xd5\x05\n\x1cUpdateTaskQueueConfigRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x10\n\x08identity\x18\x02 \x01(\t\x12\x12\n\ntask_queue\x18\x03 \x01(\t\x12=\n\x0ftask_queue_type\x18\x04 \x01(\x0e\x32$.temporal.api.enums.v1.TaskQueueType\x12n\n\x17update_queue_rate_limit\x18\x05 \x01(\x0b\x32M.temporal.api.workflowservice.v1.UpdateTaskQueueConfigRequest.RateLimitUpdate\x12}\n&update_fairness_key_rate_limit_default\x18\x06 \x01(\x0b\x32M.temporal.api.workflowservice.v1.UpdateTaskQueueConfigRequest.RateLimitUpdate\x12\x84\x01\n\x1dset_fairness_weight_overrides\x18\x07 \x03(\x0b\x32].temporal.api.workflowservice.v1.UpdateTaskQueueConfigRequest.SetFairnessWeightOverridesEntry\x12\'\n\x1funset_fairness_weight_overrides\x18\x08 \x03(\t\x1a[\n\x0fRateLimitUpdate\x12\x38\n\nrate_limit\x18\x01 \x01(\x0b\x32$.temporal.api.taskqueue.v1.RateLimit\x12\x0e\n\x06reason\x18\x02 \x01(\t\x1a\x41\n\x1fSetFairnessWeightOverridesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\x02:\x02\x38\x01"[\n\x1dUpdateTaskQueueConfigResponse\x12:\n\x06\x63onfig\x18\x01 \x01(\x0b\x32*.temporal.api.taskqueue.v1.TaskQueueConfig"\x9e\x01\n\x18\x46\x65tchWorkerConfigRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x10\n\x08identity\x18\x02 \x01(\t\x12\x0e\n\x06reason\x18\x03 \x01(\t\x12\x38\n\x08selector\x18\x06 \x01(\x0b\x32&.temporal.api.common.v1.WorkerSelector\x12\x13\n\x0bresource_id\x18\x07 \x01(\t"U\n\x19\x46\x65tchWorkerConfigResponse\x12\x38\n\rworker_config\x18\x01 \x01(\x0b\x32!.temporal.api.sdk.v1.WorkerConfig"\x8a\x02\n\x19UpdateWorkerConfigRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x10\n\x08identity\x18\x02 \x01(\t\x12\x0e\n\x06reason\x18\x03 \x01(\t\x12\x38\n\rworker_config\x18\x04 \x01(\x0b\x32!.temporal.api.sdk.v1.WorkerConfig\x12/\n\x0bupdate_mask\x18\x05 \x01(\x0b\x32\x1a.google.protobuf.FieldMask\x12\x38\n\x08selector\x18\x06 \x01(\x0b\x32&.temporal.api.common.v1.WorkerSelector\x12\x13\n\x0bresource_id\x18\x07 \x01(\t"d\n\x1aUpdateWorkerConfigResponse\x12:\n\rworker_config\x18\x01 \x01(\x0b\x32!.temporal.api.sdk.v1.WorkerConfigH\x00\x42\n\n\x08response"G\n\x15\x44\x65scribeWorkerRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x1b\n\x13worker_instance_key\x18\x02 \x01(\t"Q\n\x16\x44\x65scribeWorkerResponse\x12\x37\n\x0bworker_info\x18\x01 \x01(\x0b\x32".temporal.api.worker.v1.WorkerInfo"\x8d\x01\n\x1dPauseWorkflowExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x12\x10\n\x08identity\x18\x04 \x01(\t\x12\x0e\n\x06reason\x18\x05 \x01(\t\x12\x12\n\nrequest_id\x18\x06 \x01(\t" \n\x1ePauseWorkflowExecutionResponse"\x8f\x01\n\x1fUnpauseWorkflowExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x12\x10\n\x08identity\x18\x04 \x01(\t\x12\x0e\n\x06reason\x18\x05 \x01(\t\x12\x12\n\nrequest_id\x18\x06 \x01(\t""\n UnpauseWorkflowExecutionResponse"\x99\t\n\x1dStartActivityExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x10\n\x08identity\x18\x02 \x01(\t\x12\x12\n\nrequest_id\x18\x03 \x01(\t\x12\x13\n\x0b\x61\x63tivity_id\x18\x04 \x01(\t\x12;\n\ractivity_type\x18\x05 \x01(\x0b\x32$.temporal.api.common.v1.ActivityType\x12\x38\n\ntask_queue\x18\x06 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12<\n\x19schedule_to_close_timeout\x18\x07 \x01(\x0b\x32\x19.google.protobuf.Duration\x12<\n\x19schedule_to_start_timeout\x18\x08 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x39\n\x16start_to_close_timeout\x18\t \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x34\n\x11heartbeat_timeout\x18\n \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x39\n\x0cretry_policy\x18\x0b \x01(\x0b\x32#.temporal.api.common.v1.RetryPolicy\x12/\n\x05input\x18\x0c \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x45\n\x0fid_reuse_policy\x18\r \x01(\x0e\x32,.temporal.api.enums.v1.ActivityIdReusePolicy\x12K\n\x12id_conflict_policy\x18\x0e \x01(\x0e\x32/.temporal.api.enums.v1.ActivityIdConflictPolicy\x12\x43\n\x11search_attributes\x18\x0f \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes\x12.\n\x06header\x18\x10 \x01(\x0b\x32\x1e.temporal.api.common.v1.Header\x12\x38\n\ruser_metadata\x18\x11 \x01(\x0b\x32!.temporal.api.sdk.v1.UserMetadata\x12\x32\n\x08priority\x18\x12 \x01(\x0b\x32 .temporal.api.common.v1.Priority\x12>\n\x14\x63ompletion_callbacks\x18\x13 \x03(\x0b\x32 .temporal.api.common.v1.Callback\x12+\n\x05links\x18\x14 \x03(\x0b\x32\x1c.temporal.api.common.v1.Link\x12\x46\n\x13on_conflict_options\x18\x15 \x01(\x0b\x32).temporal.api.common.v1.OnConflictOptions\x12.\n\x0bstart_delay\x18\x16 \x01(\x0b\x32\x19.google.protobuf.Duration"m\n\x1eStartActivityExecutionResponse\x12\x0e\n\x06run_id\x18\x01 \x01(\t\x12\x0f\n\x07started\x18\x02 \x01(\x08\x12*\n\x04link\x18\x03 \x01(\x0b\x32\x1c.temporal.api.common.v1.Link"\xa3\x01\n DescribeActivityExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0b\x61\x63tivity_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x12\x15\n\rinclude_input\x18\x04 \x01(\x08\x12\x17\n\x0finclude_outcome\x18\x05 \x01(\x08\x12\x17\n\x0flong_poll_token\x18\x06 \x01(\x0c"\xbc\x02\n!DescribeActivityExecutionResponse\x12\x0e\n\x06run_id\x18\x01 \x01(\t\x12=\n\x04info\x18\x02 \x01(\x0b\x32/.temporal.api.activity.v1.ActivityExecutionInfo\x12/\n\x05input\x18\x03 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x43\n\x07outcome\x18\x04 \x01(\x0b\x32\x32.temporal.api.activity.v1.ActivityExecutionOutcome\x12\x17\n\x0flong_poll_token\x18\x05 \x01(\x0c\x12\x39\n\tcallbacks\x18\x06 \x03(\x0b\x32&.temporal.api.activity.v1.CallbackInfo"V\n\x1cPollActivityExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0b\x61\x63tivity_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t"t\n\x1dPollActivityExecutionResponse\x12\x0e\n\x06run_id\x18\x01 \x01(\t\x12\x43\n\x07outcome\x18\x02 \x01(\x0b\x32\x32.temporal.api.activity.v1.ActivityExecutionOutcome"m\n\x1dListActivityExecutionsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x11\n\tpage_size\x18\x02 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c\x12\r\n\x05query\x18\x04 \x01(\t"\x82\x01\n\x1eListActivityExecutionsResponse\x12G\n\nexecutions\x18\x01 \x03(\x0b\x32\x33.temporal.api.activity.v1.ActivityExecutionListInfo\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c"\xd1\x06\n#StartNexusOperationExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x10\n\x08identity\x18\x02 \x01(\t\x12\x12\n\nrequest_id\x18\x03 \x01(\t\x12\x14\n\x0coperation_id\x18\x04 \x01(\t\x12\x10\n\x08\x65ndpoint\x18\x05 \x01(\t\x12\x0f\n\x07service\x18\x06 \x01(\t\x12\x11\n\toperation\x18\x07 \x01(\t\x12<\n\x19schedule_to_close_timeout\x18\x08 \x01(\x0b\x32\x19.google.protobuf.Duration\x12<\n\x19schedule_to_start_timeout\x18\t \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x39\n\x16start_to_close_timeout\x18\n \x01(\x0b\x32\x19.google.protobuf.Duration\x12.\n\x05input\x18\x0b \x01(\x0b\x32\x1f.temporal.api.common.v1.Payload\x12K\n\x0fid_reuse_policy\x18\x0c \x01(\x0e\x32\x32.temporal.api.enums.v1.NexusOperationIdReusePolicy\x12Q\n\x12id_conflict_policy\x18\r \x01(\x0e\x32\x35.temporal.api.enums.v1.NexusOperationIdConflictPolicy\x12\x43\n\x11search_attributes\x18\x0e \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes\x12k\n\x0cnexus_header\x18\x0f \x03(\x0b\x32U.temporal.api.workflowservice.v1.StartNexusOperationExecutionRequest.NexusHeaderEntry\x12\x38\n\ruser_metadata\x18\x10 \x01(\x0b\x32!.temporal.api.sdk.v1.UserMetadata\x1a\x32\n\x10NexusHeaderEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01"G\n$StartNexusOperationExecutionResponse\x12\x0e\n\x06run_id\x18\x01 \x01(\t\x12\x0f\n\x07started\x18\x02 \x01(\x08"\xaa\x01\n&DescribeNexusOperationExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x14\n\x0coperation_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x12\x15\n\rinclude_input\x18\x04 \x01(\x08\x12\x17\n\x0finclude_outcome\x18\x05 \x01(\x08\x12\x17\n\x0flong_poll_token\x18\x06 \x01(\x0c"\xb7\x02\n\'DescribeNexusOperationExecutionResponse\x12\x0e\n\x06run_id\x18\x01 \x01(\t\x12@\n\x04info\x18\x02 \x01(\x0b\x32\x32.temporal.api.nexus.v1.NexusOperationExecutionInfo\x12.\n\x05input\x18\x03 \x01(\x0b\x32\x1f.temporal.api.common.v1.Payload\x12\x31\n\x06result\x18\x04 \x01(\x0b\x32\x1f.temporal.api.common.v1.PayloadH\x00\x12\x33\n\x07\x66\x61ilure\x18\x05 \x01(\x0b\x32 .temporal.api.failure.v1.FailureH\x00\x12\x17\n\x0flong_poll_token\x18\x06 \x01(\x0c\x42\t\n\x07outcome"\xa1\x01\n"PollNexusOperationExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x14\n\x0coperation_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x12\x42\n\nwait_stage\x18\x04 \x01(\x0e\x32..temporal.api.enums.v1.NexusOperationWaitStage"\x85\x02\n#PollNexusOperationExecutionResponse\x12\x0e\n\x06run_id\x18\x01 \x01(\t\x12\x42\n\nwait_stage\x18\x02 \x01(\x0e\x32..temporal.api.enums.v1.NexusOperationWaitStage\x12\x17\n\x0foperation_token\x18\x03 \x01(\t\x12\x31\n\x06result\x18\x04 \x01(\x0b\x32\x1f.temporal.api.common.v1.PayloadH\x00\x12\x33\n\x07\x66\x61ilure\x18\x05 \x01(\x0b\x32 .temporal.api.failure.v1.FailureH\x00\x42\t\n\x07outcome"s\n#ListNexusOperationExecutionsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x11\n\tpage_size\x18\x02 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c\x12\r\n\x05query\x18\x04 \x01(\t"\x8b\x01\n$ListNexusOperationExecutionsResponse\x12J\n\noperations\x18\x01 \x03(\x0b\x32\x36.temporal.api.nexus.v1.NexusOperationExecutionListInfo\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c"B\n\x1e\x43ountActivityExecutionsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\r\n\x05query\x18\x02 \x01(\t"\xed\x01\n\x1f\x43ountActivityExecutionsResponse\x12\r\n\x05\x63ount\x18\x01 \x01(\x03\x12\x61\n\x06groups\x18\x02 \x03(\x0b\x32Q.temporal.api.workflowservice.v1.CountActivityExecutionsResponse.AggregationGroup\x1aX\n\x10\x41ggregationGroup\x12\x35\n\x0cgroup_values\x18\x01 \x03(\x0b\x32\x1f.temporal.api.common.v1.Payload\x12\r\n\x05\x63ount\x18\x02 \x01(\x03"H\n$CountNexusOperationExecutionsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\r\n\x05query\x18\x02 \x01(\t"\xf9\x01\n%CountNexusOperationExecutionsResponse\x12\r\n\x05\x63ount\x18\x01 \x01(\x03\x12g\n\x06groups\x18\x02 \x03(\x0b\x32W.temporal.api.workflowservice.v1.CountNexusOperationExecutionsResponse.AggregationGroup\x1aX\n\x10\x41ggregationGroup\x12\x35\n\x0cgroup_values\x18\x01 \x03(\x0b\x32\x1f.temporal.api.common.v1.Payload\x12\r\n\x05\x63ount\x18\x02 \x01(\x03"\x95\x01\n%RequestCancelActivityExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0b\x61\x63tivity_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x12\x10\n\x08identity\x18\x04 \x01(\t\x12\x12\n\nrequest_id\x18\x05 \x01(\t\x12\x0e\n\x06reason\x18\x06 \x01(\t"(\n&RequestCancelActivityExecutionResponse"\x91\x01\n!TerminateActivityExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0b\x61\x63tivity_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x12\x10\n\x08identity\x18\x04 \x01(\t\x12\x12\n\nrequest_id\x18\x05 \x01(\t\x12\x0e\n\x06reason\x18\x06 \x01(\t"$\n"TerminateActivityExecutionResponse"X\n\x1e\x44\x65leteActivityExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0b\x61\x63tivity_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t"!\n\x1f\x44\x65leteActivityExecutionResponse"\x9c\x01\n+RequestCancelNexusOperationExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x14\n\x0coperation_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x12\x10\n\x08identity\x18\x04 \x01(\t\x12\x12\n\nrequest_id\x18\x05 \x01(\t\x12\x0e\n\x06reason\x18\x06 \x01(\t".\n,RequestCancelNexusOperationExecutionResponse"\x98\x01\n\'TerminateNexusOperationExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x14\n\x0coperation_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x12\x10\n\x08identity\x18\x04 \x01(\t\x12\x12\n\nrequest_id\x18\x05 \x01(\t\x12\x0e\n\x06reason\x18\x06 \x01(\t"*\n(TerminateNexusOperationExecutionResponse"_\n$DeleteNexusOperationExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x14\n\x0coperation_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t"\'\n%DeleteNexusOperationExecutionResponseB\xbe\x01\n"io.temporal.api.workflowservice.v1B\x14RequestResponseProtoP\x01Z5go.temporal.io/api/workflowservice/v1;workflowservice\xaa\x02!Temporalio.Api.WorkflowService.V1\xea\x02$Temporalio::Api::WorkflowService::V1b\x06proto3' + b'\n6temporal/api/workflowservice/v1/request_response.proto\x12\x1ftemporal.api.workflowservice.v1\x1a+temporal/api/enums/v1/batch_operation.proto\x1a"temporal/api/enums/v1/common.proto\x1a$temporal/api/enums/v1/workflow.proto\x1a%temporal/api/enums/v1/namespace.proto\x1a(temporal/api/enums/v1/failed_cause.proto\x1a!temporal/api/enums/v1/query.proto\x1a!temporal/api/enums/v1/reset.proto\x1a&temporal/api/enums/v1/task_queue.proto\x1a&temporal/api/enums/v1/deployment.proto\x1a"temporal/api/enums/v1/update.proto\x1a$temporal/api/enums/v1/activity.proto\x1a!temporal/api/enums/v1/nexus.proto\x1a&temporal/api/activity/v1/message.proto\x1a$temporal/api/common/v1/message.proto\x1a%temporal/api/history/v1/message.proto\x1a&temporal/api/workflow/v1/message.proto\x1a%temporal/api/command/v1/message.proto\x1a$temporal/api/compute/v1/config.proto\x1a(temporal/api/deployment/v1/message.proto\x1a%temporal/api/failure/v1/message.proto\x1a$temporal/api/filter/v1/message.proto\x1a&temporal/api/protocol/v1/message.proto\x1a\'temporal/api/namespace/v1/message.proto\x1a#temporal/api/query/v1/message.proto\x1a)temporal/api/replication/v1/message.proto\x1a#temporal/api/rules/v1/message.proto\x1a\'temporal/api/sdk/v1/worker_config.proto\x1a&temporal/api/schedule/v1/message.proto\x1a\'temporal/api/taskqueue/v1/message.proto\x1a$temporal/api/update/v1/message.proto\x1a%temporal/api/version/v1/message.proto\x1a#temporal/api/batch/v1/message.proto\x1a\x30temporal/api/sdk/v1/task_complete_metadata.proto\x1a\'temporal/api/sdk/v1/user_metadata.proto\x1a#temporal/api/nexus/v1/message.proto\x1a$temporal/api/worker/v1/message.proto\x1a\x1egoogle/protobuf/duration.proto\x1a google/protobuf/field_mask.proto\x1a\x1fgoogle/protobuf/timestamp.proto"\x88\x05\n\x18RegisterNamespaceRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0b\x64\x65scription\x18\x02 \x01(\t\x12\x13\n\x0bowner_email\x18\x03 \x01(\t\x12\x46\n#workflow_execution_retention_period\x18\x04 \x01(\x0b\x32\x19.google.protobuf.Duration\x12G\n\x08\x63lusters\x18\x05 \x03(\x0b\x32\x35.temporal.api.replication.v1.ClusterReplicationConfig\x12\x1b\n\x13\x61\x63tive_cluster_name\x18\x06 \x01(\t\x12Q\n\x04\x64\x61ta\x18\x07 \x03(\x0b\x32\x43.temporal.api.workflowservice.v1.RegisterNamespaceRequest.DataEntry\x12\x16\n\x0esecurity_token\x18\x08 \x01(\t\x12\x1b\n\x13is_global_namespace\x18\t \x01(\x08\x12\x44\n\x16history_archival_state\x18\n \x01(\x0e\x32$.temporal.api.enums.v1.ArchivalState\x12\x1c\n\x14history_archival_uri\x18\x0b \x01(\t\x12G\n\x19visibility_archival_state\x18\x0c \x01(\x0e\x32$.temporal.api.enums.v1.ArchivalState\x12\x1f\n\x17visibility_archival_uri\x18\r \x01(\t\x1a+\n\tDataEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01"\x1b\n\x19RegisterNamespaceResponse"\x89\x01\n\x15ListNamespacesRequest\x12\x11\n\tpage_size\x18\x01 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c\x12\x44\n\x10namespace_filter\x18\x03 \x01(\x0b\x32*.temporal.api.namespace.v1.NamespaceFilter"\x81\x01\n\x16ListNamespacesResponse\x12N\n\nnamespaces\x18\x01 \x03(\x0b\x32:.temporal.api.workflowservice.v1.DescribeNamespaceResponse\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c"S\n\x18\x44\x65scribeNamespaceRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\n\n\x02id\x18\x02 \x01(\t\x12\x18\n\x10weak_consistency\x18\x03 \x01(\x08"\xec\x02\n\x19\x44\x65scribeNamespaceResponse\x12@\n\x0enamespace_info\x18\x01 \x01(\x0b\x32(.temporal.api.namespace.v1.NamespaceInfo\x12:\n\x06\x63onfig\x18\x02 \x01(\x0b\x32*.temporal.api.namespace.v1.NamespaceConfig\x12S\n\x12replication_config\x18\x03 \x01(\x0b\x32\x37.temporal.api.replication.v1.NamespaceReplicationConfig\x12\x18\n\x10\x66\x61ilover_version\x18\x04 \x01(\x03\x12\x1b\n\x13is_global_namespace\x18\x05 \x01(\x08\x12\x45\n\x10\x66\x61ilover_history\x18\x06 \x03(\x0b\x32+.temporal.api.replication.v1.FailoverStatus"\xcf\x02\n\x16UpdateNamespaceRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x43\n\x0bupdate_info\x18\x02 \x01(\x0b\x32..temporal.api.namespace.v1.UpdateNamespaceInfo\x12:\n\x06\x63onfig\x18\x03 \x01(\x0b\x32*.temporal.api.namespace.v1.NamespaceConfig\x12S\n\x12replication_config\x18\x04 \x01(\x0b\x32\x37.temporal.api.replication.v1.NamespaceReplicationConfig\x12\x16\n\x0esecurity_token\x18\x05 \x01(\t\x12\x19\n\x11\x64\x65lete_bad_binary\x18\x06 \x01(\t\x12\x19\n\x11promote_namespace\x18\x07 \x01(\x08"\xa3\x02\n\x17UpdateNamespaceResponse\x12@\n\x0enamespace_info\x18\x01 \x01(\x0b\x32(.temporal.api.namespace.v1.NamespaceInfo\x12:\n\x06\x63onfig\x18\x02 \x01(\x0b\x32*.temporal.api.namespace.v1.NamespaceConfig\x12S\n\x12replication_config\x18\x03 \x01(\x0b\x32\x37.temporal.api.replication.v1.NamespaceReplicationConfig\x12\x18\n\x10\x66\x61ilover_version\x18\x04 \x01(\x03\x12\x1b\n\x13is_global_namespace\x18\x05 \x01(\x08"F\n\x19\x44\x65precateNamespaceRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x16\n\x0esecurity_token\x18\x02 \x01(\t"\x1c\n\x1a\x44\x65precateNamespaceResponse"\xd3\x0c\n\x1dStartWorkflowExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12;\n\rworkflow_type\x18\x03 \x01(\x0b\x32$.temporal.api.common.v1.WorkflowType\x12\x38\n\ntask_queue\x18\x04 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12/\n\x05input\x18\x05 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12=\n\x1aworkflow_execution_timeout\x18\x06 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x37\n\x14workflow_run_timeout\x18\x07 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x38\n\x15workflow_task_timeout\x18\x08 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x10\n\x08identity\x18\t \x01(\t\x12\x12\n\nrequest_id\x18\n \x01(\t\x12N\n\x18workflow_id_reuse_policy\x18\x0b \x01(\x0e\x32,.temporal.api.enums.v1.WorkflowIdReusePolicy\x12T\n\x1bworkflow_id_conflict_policy\x18\x16 \x01(\x0e\x32/.temporal.api.enums.v1.WorkflowIdConflictPolicy\x12\x39\n\x0cretry_policy\x18\x0c \x01(\x0b\x32#.temporal.api.common.v1.RetryPolicy\x12\x15\n\rcron_schedule\x18\r \x01(\t\x12*\n\x04memo\x18\x0e \x01(\x0b\x32\x1c.temporal.api.common.v1.Memo\x12\x43\n\x11search_attributes\x18\x0f \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes\x12.\n\x06header\x18\x10 \x01(\x0b\x32\x1e.temporal.api.common.v1.Header\x12\x1f\n\x17request_eager_execution\x18\x11 \x01(\x08\x12;\n\x11\x63ontinued_failure\x18\x12 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12@\n\x16last_completion_result\x18\x13 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x37\n\x14workflow_start_delay\x18\x14 \x01(\x0b\x32\x19.google.protobuf.Duration\x12>\n\x14\x63ompletion_callbacks\x18\x15 \x03(\x0b\x32 .temporal.api.common.v1.Callback\x12\x38\n\ruser_metadata\x18\x17 \x01(\x0b\x32!.temporal.api.sdk.v1.UserMetadata\x12+\n\x05links\x18\x18 \x03(\x0b\x32\x1c.temporal.api.common.v1.Link\x12I\n\x13versioning_override\x18\x19 \x01(\x0b\x32,.temporal.api.workflow.v1.VersioningOverride\x12H\n\x13on_conflict_options\x18\x1a \x01(\x0b\x32+.temporal.api.workflow.v1.OnConflictOptions\x12\x32\n\x08priority\x18\x1b \x01(\x0b\x32 .temporal.api.common.v1.Priority\x12\\\n\x1f\x65\x61ger_worker_deployment_options\x18\x1c \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentOptions\x12J\n\x14time_skipping_config\x18\x1d \x01(\x0b\x32,.temporal.api.workflow.v1.TimeSkippingConfig"\x8a\x02\n\x1eStartWorkflowExecutionResponse\x12\x0e\n\x06run_id\x18\x01 \x01(\t\x12\x0f\n\x07started\x18\x03 \x01(\x08\x12>\n\x06status\x18\x05 \x01(\x0e\x32..temporal.api.enums.v1.WorkflowExecutionStatus\x12[\n\x13\x65\x61ger_workflow_task\x18\x02 \x01(\x0b\x32>.temporal.api.workflowservice.v1.PollWorkflowTaskQueueResponse\x12*\n\x04link\x18\x04 \x01(\x0b\x32\x1c.temporal.api.common.v1.Link"\xaa\x02\n"GetWorkflowExecutionHistoryRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12<\n\texecution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x19\n\x11maximum_page_size\x18\x03 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x04 \x01(\x0c\x12\x16\n\x0ewait_new_event\x18\x05 \x01(\x08\x12P\n\x19history_event_filter_type\x18\x06 \x01(\x0e\x32-.temporal.api.enums.v1.HistoryEventFilterType\x12\x15\n\rskip_archival\x18\x07 \x01(\x08"\xba\x01\n#GetWorkflowExecutionHistoryResponse\x12\x31\n\x07history\x18\x01 \x01(\x0b\x32 .temporal.api.history.v1.History\x12\x35\n\x0braw_history\x18\x02 \x03(\x0b\x32 .temporal.api.common.v1.DataBlob\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c\x12\x10\n\x08\x61rchived\x18\x04 \x01(\x08"\xb0\x01\n)GetWorkflowExecutionHistoryReverseRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12<\n\texecution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x19\n\x11maximum_page_size\x18\x03 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x04 \x01(\x0c"x\n*GetWorkflowExecutionHistoryReverseResponse\x12\x31\n\x07history\x18\x01 \x01(\x0b\x32 .temporal.api.history.v1.History\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c"\xb8\x03\n\x1cPollWorkflowTaskQueueRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x38\n\ntask_queue\x18\x02 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12\x17\n\x0fpoller_group_id\x18\n \x01(\t\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x1b\n\x13worker_instance_key\x18\x08 \x01(\t\x12!\n\x19worker_control_task_queue\x18\t \x01(\t\x12\x1b\n\x0f\x62inary_checksum\x18\x04 \x01(\tB\x02\x18\x01\x12Z\n\x1bworker_version_capabilities\x18\x05 \x01(\x0b\x32\x31.temporal.api.common.v1.WorkerVersionCapabilitiesB\x02\x18\x01\x12O\n\x12\x64\x65ployment_options\x18\x06 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentOptionsJ\x04\x08\x07\x10\x08R\x10worker_heartbeat"\xf2\x07\n\x1dPollWorkflowTaskQueueResponse\x12\x12\n\ntask_token\x18\x01 \x01(\x0c\x12\x45\n\x12workflow_execution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12;\n\rworkflow_type\x18\x03 \x01(\x0b\x32$.temporal.api.common.v1.WorkflowType\x12!\n\x19previous_started_event_id\x18\x04 \x01(\x03\x12\x18\n\x10started_event_id\x18\x05 \x01(\x03\x12\x0f\n\x07\x61ttempt\x18\x06 \x01(\x05\x12\x1a\n\x12\x62\x61\x63klog_count_hint\x18\x07 \x01(\x03\x12\x31\n\x07history\x18\x08 \x01(\x0b\x32 .temporal.api.history.v1.History\x12\x17\n\x0fnext_page_token\x18\t \x01(\x0c\x12\x33\n\x05query\x18\n \x01(\x0b\x32$.temporal.api.query.v1.WorkflowQuery\x12K\n\x1dworkflow_execution_task_queue\x18\x0b \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12\x32\n\x0escheduled_time\x18\x0c \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x30\n\x0cstarted_time\x18\r \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\\\n\x07queries\x18\x0e \x03(\x0b\x32K.temporal.api.workflowservice.v1.PollWorkflowTaskQueueResponse.QueriesEntry\x12\x33\n\x08messages\x18\x0f \x03(\x0b\x32!.temporal.api.protocol.v1.Message\x12Q\n\x17poller_scaling_decision\x18\x10 \x01(\x0b\x32\x30.temporal.api.taskqueue.v1.PollerScalingDecision\x12\x17\n\x0fpoller_group_id\x18\x11 \x01(\t\x12\x46\n\x12poller_group_infos\x18\x12 \x03(\x0b\x32*.temporal.api.taskqueue.v1.PollerGroupInfo\x1aT\n\x0cQueriesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x33\n\x05value\x18\x02 \x01(\x0b\x32$.temporal.api.query.v1.WorkflowQuery:\x02\x38\x01"\x8a\n\n#RespondWorkflowTaskCompletedRequest\x12\x12\n\ntask_token\x18\x01 \x01(\x0c\x12\x32\n\x08\x63ommands\x18\x02 \x03(\x0b\x32 .temporal.api.command.v1.Command\x12\x10\n\x08identity\x18\x03 \x01(\t\x12O\n\x11sticky_attributes\x18\x04 \x01(\x0b\x32\x34.temporal.api.taskqueue.v1.StickyExecutionAttributes\x12 \n\x18return_new_workflow_task\x18\x05 \x01(\x08\x12&\n\x1e\x66orce_create_new_workflow_task\x18\x06 \x01(\x08\x12\x1b\n\x0f\x62inary_checksum\x18\x07 \x01(\tB\x02\x18\x01\x12m\n\rquery_results\x18\x08 \x03(\x0b\x32V.temporal.api.workflowservice.v1.RespondWorkflowTaskCompletedRequest.QueryResultsEntry\x12\x11\n\tnamespace\x18\t \x01(\t\x12\x13\n\x0bresource_id\x18\x12 \x01(\t\x12L\n\x14worker_version_stamp\x18\n \x01(\x0b\x32*.temporal.api.common.v1.WorkerVersionStampB\x02\x18\x01\x12\x33\n\x08messages\x18\x0b \x03(\x0b\x32!.temporal.api.protocol.v1.Message\x12H\n\x0csdk_metadata\x18\x0c \x01(\x0b\x32\x32.temporal.api.sdk.v1.WorkflowTaskCompletedMetadata\x12\x43\n\x11metering_metadata\x18\r \x01(\x0b\x32(.temporal.api.common.v1.MeteringMetadata\x12g\n\x0c\x63\x61pabilities\x18\x0e \x01(\x0b\x32Q.temporal.api.workflowservice.v1.RespondWorkflowTaskCompletedRequest.Capabilities\x12>\n\ndeployment\x18\x0f \x01(\x0b\x32&.temporal.api.deployment.v1.DeploymentB\x02\x18\x01\x12\x46\n\x13versioning_behavior\x18\x10 \x01(\x0e\x32).temporal.api.enums.v1.VersioningBehavior\x12O\n\x12\x64\x65ployment_options\x18\x11 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentOptions\x12\x1b\n\x13worker_instance_key\x18\x13 \x01(\t\x12!\n\x19worker_control_task_queue\x18\x14 \x01(\t\x1a_\n\x11QueryResultsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x39\n\x05value\x18\x02 \x01(\x0b\x32*.temporal.api.query.v1.WorkflowQueryResult:\x02\x38\x01\x1a\x45\n\x0c\x43\x61pabilities\x12\x35\n-discard_speculative_workflow_task_with_events\x18\x01 \x01(\x08"\xf5\x01\n$RespondWorkflowTaskCompletedResponse\x12U\n\rworkflow_task\x18\x01 \x01(\x0b\x32>.temporal.api.workflowservice.v1.PollWorkflowTaskQueueResponse\x12V\n\x0e\x61\x63tivity_tasks\x18\x02 \x03(\x0b\x32>.temporal.api.workflowservice.v1.PollActivityTaskQueueResponse\x12\x1e\n\x16reset_history_event_id\x18\x03 \x01(\x03"\x8d\x04\n RespondWorkflowTaskFailedRequest\x12\x12\n\ntask_token\x18\x01 \x01(\x0c\x12=\n\x05\x63\x61use\x18\x02 \x01(\x0e\x32..temporal.api.enums.v1.WorkflowTaskFailedCause\x12\x31\n\x07\x66\x61ilure\x18\x03 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12\x10\n\x08identity\x18\x04 \x01(\t\x12\x1b\n\x0f\x62inary_checksum\x18\x05 \x01(\tB\x02\x18\x01\x12\x11\n\tnamespace\x18\x06 \x01(\t\x12\x13\n\x0bresource_id\x18\x0b \x01(\t\x12\x33\n\x08messages\x18\x07 \x03(\x0b\x32!.temporal.api.protocol.v1.Message\x12\x46\n\x0eworker_version\x18\x08 \x01(\x0b\x32*.temporal.api.common.v1.WorkerVersionStampB\x02\x18\x01\x12>\n\ndeployment\x18\t \x01(\x0b\x32&.temporal.api.deployment.v1.DeploymentB\x02\x18\x01\x12O\n\x12\x64\x65ployment_options\x18\n \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentOptions"#\n!RespondWorkflowTaskFailedResponse"\xe6\x03\n\x1cPollActivityTaskQueueRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x38\n\ntask_queue\x18\x02 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12\x17\n\x0fpoller_group_id\x18\n \x01(\t\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x1b\n\x13worker_instance_key\x18\x08 \x01(\t\x12!\n\x19worker_control_task_queue\x18\t \x01(\t\x12I\n\x13task_queue_metadata\x18\x04 \x01(\x0b\x32,.temporal.api.taskqueue.v1.TaskQueueMetadata\x12Z\n\x1bworker_version_capabilities\x18\x05 \x01(\x0b\x32\x31.temporal.api.common.v1.WorkerVersionCapabilitiesB\x02\x18\x01\x12O\n\x12\x64\x65ployment_options\x18\x06 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentOptionsJ\x04\x08\x07\x10\x08R\x10worker_heartbeat"\xd0\x08\n\x1dPollActivityTaskQueueResponse\x12\x12\n\ntask_token\x18\x01 \x01(\x0c\x12\x1a\n\x12workflow_namespace\x18\x02 \x01(\t\x12;\n\rworkflow_type\x18\x03 \x01(\x0b\x32$.temporal.api.common.v1.WorkflowType\x12\x45\n\x12workflow_execution\x18\x04 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12;\n\ractivity_type\x18\x05 \x01(\x0b\x32$.temporal.api.common.v1.ActivityType\x12\x13\n\x0b\x61\x63tivity_id\x18\x06 \x01(\t\x12.\n\x06header\x18\x07 \x01(\x0b\x32\x1e.temporal.api.common.v1.Header\x12/\n\x05input\x18\x08 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12;\n\x11heartbeat_details\x18\t \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x32\n\x0escheduled_time\x18\n \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x42\n\x1e\x63urrent_attempt_scheduled_time\x18\x0b \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x30\n\x0cstarted_time\x18\x0c \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x0f\n\x07\x61ttempt\x18\r \x01(\x05\x12<\n\x19schedule_to_close_timeout\x18\x0e \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x39\n\x16start_to_close_timeout\x18\x0f \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x34\n\x11heartbeat_timeout\x18\x10 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x39\n\x0cretry_policy\x18\x11 \x01(\x0b\x32#.temporal.api.common.v1.RetryPolicy\x12Q\n\x17poller_scaling_decision\x18\x12 \x01(\x0b\x32\x30.temporal.api.taskqueue.v1.PollerScalingDecision\x12\x32\n\x08priority\x18\x13 \x01(\x0b\x32 .temporal.api.common.v1.Priority\x12\x17\n\x0f\x61\x63tivity_run_id\x18\x14 \x01(\t\x12\x46\n\x12poller_group_infos\x18\x15 \x03(\x0b\x32*.temporal.api.taskqueue.v1.PollerGroupInfo"\xa5\x01\n"RecordActivityTaskHeartbeatRequest\x12\x12\n\ntask_token\x18\x01 \x01(\x0c\x12\x31\n\x07\x64\x65tails\x18\x02 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x11\n\tnamespace\x18\x04 \x01(\t\x12\x13\n\x0bresource_id\x18\x05 \x01(\t"p\n#RecordActivityTaskHeartbeatResponse\x12\x18\n\x10\x63\x61ncel_requested\x18\x01 \x01(\x08\x12\x17\n\x0f\x61\x63tivity_paused\x18\x02 \x01(\x08\x12\x16\n\x0e\x61\x63tivity_reset\x18\x03 \x01(\x08"\xcf\x01\n&RecordActivityTaskHeartbeatByIdRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x12\x13\n\x0b\x61\x63tivity_id\x18\x04 \x01(\t\x12\x31\n\x07\x64\x65tails\x18\x05 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x10\n\x08identity\x18\x06 \x01(\t\x12\x13\n\x0bresource_id\x18\x07 \x01(\t"t\n\'RecordActivityTaskHeartbeatByIdResponse\x12\x18\n\x10\x63\x61ncel_requested\x18\x01 \x01(\x08\x12\x17\n\x0f\x61\x63tivity_paused\x18\x02 \x01(\x08\x12\x16\n\x0e\x61\x63tivity_reset\x18\x03 \x01(\x08"\xfe\x02\n#RespondActivityTaskCompletedRequest\x12\x12\n\ntask_token\x18\x01 \x01(\x0c\x12\x30\n\x06result\x18\x02 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x11\n\tnamespace\x18\x04 \x01(\t\x12\x13\n\x0bresource_id\x18\x08 \x01(\t\x12\x46\n\x0eworker_version\x18\x05 \x01(\x0b\x32*.temporal.api.common.v1.WorkerVersionStampB\x02\x18\x01\x12>\n\ndeployment\x18\x06 \x01(\x0b\x32&.temporal.api.deployment.v1.DeploymentB\x02\x18\x01\x12O\n\x12\x64\x65ployment_options\x18\x07 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentOptions"&\n$RespondActivityTaskCompletedResponse"\xcf\x01\n\'RespondActivityTaskCompletedByIdRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x12\x13\n\x0b\x61\x63tivity_id\x18\x04 \x01(\t\x12\x30\n\x06result\x18\x05 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x10\n\x08identity\x18\x06 \x01(\t\x12\x13\n\x0bresource_id\x18\x07 \x01(\t"*\n(RespondActivityTaskCompletedByIdResponse"\xbe\x03\n RespondActivityTaskFailedRequest\x12\x12\n\ntask_token\x18\x01 \x01(\x0c\x12\x31\n\x07\x66\x61ilure\x18\x02 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x11\n\tnamespace\x18\x04 \x01(\t\x12\x13\n\x0bresource_id\x18\t \x01(\t\x12@\n\x16last_heartbeat_details\x18\x05 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x46\n\x0eworker_version\x18\x06 \x01(\x0b\x32*.temporal.api.common.v1.WorkerVersionStampB\x02\x18\x01\x12>\n\ndeployment\x18\x07 \x01(\x0b\x32&.temporal.api.deployment.v1.DeploymentB\x02\x18\x01\x12O\n\x12\x64\x65ployment_options\x18\x08 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentOptions"W\n!RespondActivityTaskFailedResponse\x12\x32\n\x08\x66\x61ilures\x18\x01 \x03(\x0b\x32 .temporal.api.failure.v1.Failure"\x8f\x02\n$RespondActivityTaskFailedByIdRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x12\x13\n\x0b\x61\x63tivity_id\x18\x04 \x01(\t\x12\x31\n\x07\x66\x61ilure\x18\x05 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12\x10\n\x08identity\x18\x06 \x01(\t\x12@\n\x16last_heartbeat_details\x18\x07 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x13\n\x0bresource_id\x18\x08 \x01(\t"[\n%RespondActivityTaskFailedByIdResponse\x12\x32\n\x08\x66\x61ilures\x18\x01 \x03(\x0b\x32 .temporal.api.failure.v1.Failure"\xfe\x02\n"RespondActivityTaskCanceledRequest\x12\x12\n\ntask_token\x18\x01 \x01(\x0c\x12\x31\n\x07\x64\x65tails\x18\x02 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x11\n\tnamespace\x18\x04 \x01(\t\x12\x13\n\x0bresource_id\x18\x08 \x01(\t\x12\x46\n\x0eworker_version\x18\x05 \x01(\x0b\x32*.temporal.api.common.v1.WorkerVersionStampB\x02\x18\x01\x12>\n\ndeployment\x18\x06 \x01(\x0b\x32&.temporal.api.deployment.v1.DeploymentB\x02\x18\x01\x12O\n\x12\x64\x65ployment_options\x18\x07 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentOptions"%\n#RespondActivityTaskCanceledResponse"\xa0\x02\n&RespondActivityTaskCanceledByIdRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x12\x13\n\x0b\x61\x63tivity_id\x18\x04 \x01(\t\x12\x31\n\x07\x64\x65tails\x18\x05 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x10\n\x08identity\x18\x06 \x01(\t\x12O\n\x12\x64\x65ployment_options\x18\x07 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentOptions\x12\x13\n\x0bresource_id\x18\x08 \x01(\t")\n\'RespondActivityTaskCanceledByIdResponse"\x84\x02\n%RequestCancelWorkflowExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x45\n\x12workflow_execution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x12\n\nrequest_id\x18\x04 \x01(\t\x12\x1e\n\x16\x66irst_execution_run_id\x18\x05 \x01(\t\x12\x0e\n\x06reason\x18\x06 \x01(\t\x12+\n\x05links\x18\x07 \x03(\x0b\x32\x1c.temporal.api.common.v1.Link"(\n&RequestCancelWorkflowExecutionResponse"\xde\x02\n\x1eSignalWorkflowExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x45\n\x12workflow_execution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x13\n\x0bsignal_name\x18\x03 \x01(\t\x12/\n\x05input\x18\x04 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x10\n\x08identity\x18\x05 \x01(\t\x12\x12\n\nrequest_id\x18\x06 \x01(\t\x12\x13\n\x07\x63ontrol\x18\x07 \x01(\tB\x02\x18\x01\x12.\n\x06header\x18\x08 \x01(\x0b\x32\x1e.temporal.api.common.v1.Header\x12+\n\x05links\x18\n \x03(\x0b\x32\x1c.temporal.api.common.v1.LinkJ\x04\x08\t\x10\n"M\n\x1fSignalWorkflowExecutionResponse\x12*\n\x04link\x18\x01 \x01(\x0b\x32\x1c.temporal.api.common.v1.Link"\xbd\n\n\'SignalWithStartWorkflowExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12;\n\rworkflow_type\x18\x03 \x01(\x0b\x32$.temporal.api.common.v1.WorkflowType\x12\x38\n\ntask_queue\x18\x04 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12/\n\x05input\x18\x05 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12=\n\x1aworkflow_execution_timeout\x18\x06 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x37\n\x14workflow_run_timeout\x18\x07 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x38\n\x15workflow_task_timeout\x18\x08 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x10\n\x08identity\x18\t \x01(\t\x12\x12\n\nrequest_id\x18\n \x01(\t\x12N\n\x18workflow_id_reuse_policy\x18\x0b \x01(\x0e\x32,.temporal.api.enums.v1.WorkflowIdReusePolicy\x12T\n\x1bworkflow_id_conflict_policy\x18\x16 \x01(\x0e\x32/.temporal.api.enums.v1.WorkflowIdConflictPolicy\x12\x13\n\x0bsignal_name\x18\x0c \x01(\t\x12\x36\n\x0csignal_input\x18\r \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x13\n\x07\x63ontrol\x18\x0e \x01(\tB\x02\x18\x01\x12\x39\n\x0cretry_policy\x18\x0f \x01(\x0b\x32#.temporal.api.common.v1.RetryPolicy\x12\x15\n\rcron_schedule\x18\x10 \x01(\t\x12*\n\x04memo\x18\x11 \x01(\x0b\x32\x1c.temporal.api.common.v1.Memo\x12\x43\n\x11search_attributes\x18\x12 \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes\x12.\n\x06header\x18\x13 \x01(\x0b\x32\x1e.temporal.api.common.v1.Header\x12\x37\n\x14workflow_start_delay\x18\x14 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x38\n\ruser_metadata\x18\x17 \x01(\x0b\x32!.temporal.api.sdk.v1.UserMetadata\x12+\n\x05links\x18\x18 \x03(\x0b\x32\x1c.temporal.api.common.v1.Link\x12I\n\x13versioning_override\x18\x19 \x01(\x0b\x32,.temporal.api.workflow.v1.VersioningOverride\x12\x32\n\x08priority\x18\x1a \x01(\x0b\x32 .temporal.api.common.v1.Priority\x12J\n\x14time_skipping_config\x18\x1b \x01(\x0b\x32,.temporal.api.workflow.v1.TimeSkippingConfigJ\x04\x08\x15\x10\x16"~\n(SignalWithStartWorkflowExecutionResponse\x12\x0e\n\x06run_id\x18\x01 \x01(\t\x12\x0f\n\x07started\x18\x02 \x01(\x08\x12\x31\n\x0bsignal_link\x18\x03 \x01(\x0b\x32\x1c.temporal.api.common.v1.Link"\xc1\x03\n\x1dResetWorkflowExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x45\n\x12workflow_execution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x0e\n\x06reason\x18\x03 \x01(\t\x12%\n\x1dworkflow_task_finish_event_id\x18\x04 \x01(\x03\x12\x12\n\nrequest_id\x18\x05 \x01(\t\x12G\n\x12reset_reapply_type\x18\x06 \x01(\x0e\x32\'.temporal.api.enums.v1.ResetReapplyTypeB\x02\x18\x01\x12S\n\x1breset_reapply_exclude_types\x18\x07 \x03(\x0e\x32..temporal.api.enums.v1.ResetReapplyExcludeType\x12K\n\x15post_reset_operations\x18\x08 \x03(\x0b\x32,.temporal.api.workflow.v1.PostResetOperation\x12\x10\n\x08identity\x18\t \x01(\t"0\n\x1eResetWorkflowExecutionResponse\x12\x0e\n\x06run_id\x18\x01 \x01(\t"\x9f\x02\n!TerminateWorkflowExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x45\n\x12workflow_execution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x0e\n\x06reason\x18\x03 \x01(\t\x12\x31\n\x07\x64\x65tails\x18\x04 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x10\n\x08identity\x18\x05 \x01(\t\x12\x1e\n\x16\x66irst_execution_run_id\x18\x06 \x01(\t\x12+\n\x05links\x18\x07 \x03(\x0b\x32\x1c.temporal.api.common.v1.Link"$\n"TerminateWorkflowExecutionResponse"z\n\x1e\x44\x65leteWorkflowExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x45\n\x12workflow_execution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution"!\n\x1f\x44\x65leteWorkflowExecutionResponse"\xc9\x02\n!ListOpenWorkflowExecutionsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x19\n\x11maximum_page_size\x18\x02 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c\x12\x42\n\x11start_time_filter\x18\x04 \x01(\x0b\x32\'.temporal.api.filter.v1.StartTimeFilter\x12K\n\x10\x65xecution_filter\x18\x05 \x01(\x0b\x32/.temporal.api.filter.v1.WorkflowExecutionFilterH\x00\x12\x41\n\x0btype_filter\x18\x06 \x01(\x0b\x32*.temporal.api.filter.v1.WorkflowTypeFilterH\x00\x42\t\n\x07\x66ilters"\x82\x01\n"ListOpenWorkflowExecutionsResponse\x12\x43\n\nexecutions\x18\x01 \x03(\x0b\x32/.temporal.api.workflow.v1.WorkflowExecutionInfo\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c"\x8a\x03\n#ListClosedWorkflowExecutionsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x19\n\x11maximum_page_size\x18\x02 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c\x12\x42\n\x11start_time_filter\x18\x04 \x01(\x0b\x32\'.temporal.api.filter.v1.StartTimeFilter\x12K\n\x10\x65xecution_filter\x18\x05 \x01(\x0b\x32/.temporal.api.filter.v1.WorkflowExecutionFilterH\x00\x12\x41\n\x0btype_filter\x18\x06 \x01(\x0b\x32*.temporal.api.filter.v1.WorkflowTypeFilterH\x00\x12=\n\rstatus_filter\x18\x07 \x01(\x0b\x32$.temporal.api.filter.v1.StatusFilterH\x00\x42\t\n\x07\x66ilters"\x84\x01\n$ListClosedWorkflowExecutionsResponse\x12\x43\n\nexecutions\x18\x01 \x03(\x0b\x32/.temporal.api.workflow.v1.WorkflowExecutionInfo\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c"m\n\x1dListWorkflowExecutionsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x11\n\tpage_size\x18\x02 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c\x12\r\n\x05query\x18\x04 \x01(\t"~\n\x1eListWorkflowExecutionsResponse\x12\x43\n\nexecutions\x18\x01 \x03(\x0b\x32/.temporal.api.workflow.v1.WorkflowExecutionInfo\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c"u\n%ListArchivedWorkflowExecutionsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x11\n\tpage_size\x18\x02 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c\x12\r\n\x05query\x18\x04 \x01(\t"\x86\x01\n&ListArchivedWorkflowExecutionsResponse\x12\x43\n\nexecutions\x18\x01 \x03(\x0b\x32/.temporal.api.workflow.v1.WorkflowExecutionInfo\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c"m\n\x1dScanWorkflowExecutionsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x11\n\tpage_size\x18\x02 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c\x12\r\n\x05query\x18\x04 \x01(\t"~\n\x1eScanWorkflowExecutionsResponse\x12\x43\n\nexecutions\x18\x01 \x03(\x0b\x32/.temporal.api.workflow.v1.WorkflowExecutionInfo\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c"B\n\x1e\x43ountWorkflowExecutionsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\r\n\x05query\x18\x02 \x01(\t"\xed\x01\n\x1f\x43ountWorkflowExecutionsResponse\x12\r\n\x05\x63ount\x18\x01 \x01(\x03\x12\x61\n\x06groups\x18\x02 \x03(\x0b\x32Q.temporal.api.workflowservice.v1.CountWorkflowExecutionsResponse.AggregationGroup\x1aX\n\x10\x41ggregationGroup\x12\x35\n\x0cgroup_values\x18\x01 \x03(\x0b\x32\x1f.temporal.api.common.v1.Payload\x12\r\n\x05\x63ount\x18\x02 \x01(\x03"\x1c\n\x1aGetSearchAttributesRequest"\xc9\x01\n\x1bGetSearchAttributesResponse\x12T\n\x04keys\x18\x01 \x03(\x0b\x32\x46.temporal.api.workflowservice.v1.GetSearchAttributesResponse.KeysEntry\x1aT\n\tKeysEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x36\n\x05value\x18\x02 \x01(\x0e\x32\'.temporal.api.enums.v1.IndexedValueType:\x02\x38\x01"\xe9\x02\n RespondQueryTaskCompletedRequest\x12\x12\n\ntask_token\x18\x01 \x01(\x0c\x12>\n\x0e\x63ompleted_type\x18\x02 \x01(\x0e\x32&.temporal.api.enums.v1.QueryResultType\x12\x36\n\x0cquery_result\x18\x03 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x15\n\rerror_message\x18\x04 \x01(\t\x12\x11\n\tnamespace\x18\x06 \x01(\t\x12\x31\n\x07\x66\x61ilure\x18\x07 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12=\n\x05\x63\x61use\x18\x08 \x01(\x0e\x32..temporal.api.enums.v1.WorkflowTaskFailedCause\x12\x17\n\x0fpoller_group_id\x18\t \x01(\tJ\x04\x08\x05\x10\x06"#\n!RespondQueryTaskCompletedResponse"n\n\x1bResetStickyTaskQueueRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12<\n\texecution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution"\x1e\n\x1cResetStickyTaskQueueResponse"\x9b\x02\n\x15ShutdownWorkerRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x19\n\x11sticky_task_queue\x18\x02 \x01(\t\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x0e\n\x06reason\x18\x04 \x01(\t\x12\x41\n\x10worker_heartbeat\x18\x05 \x01(\x0b\x32\'.temporal.api.worker.v1.WorkerHeartbeat\x12\x1b\n\x13worker_instance_key\x18\x06 \x01(\t\x12\x12\n\ntask_queue\x18\x07 \x01(\t\x12>\n\x10task_queue_types\x18\x08 \x03(\x0e\x32$.temporal.api.enums.v1.TaskQueueType"\x18\n\x16ShutdownWorkerResponse"\xe9\x01\n\x14QueryWorkflowRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12<\n\texecution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x33\n\x05query\x18\x03 \x01(\x0b\x32$.temporal.api.query.v1.WorkflowQuery\x12K\n\x16query_reject_condition\x18\x04 \x01(\x0e\x32+.temporal.api.enums.v1.QueryRejectCondition"\x8d\x01\n\x15QueryWorkflowResponse\x12\x36\n\x0cquery_result\x18\x01 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12<\n\x0equery_rejected\x18\x02 \x01(\x0b\x32$.temporal.api.query.v1.QueryRejected"s\n DescribeWorkflowExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12<\n\texecution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution"\x99\x05\n!DescribeWorkflowExecutionResponse\x12K\n\x10\x65xecution_config\x18\x01 \x01(\x0b\x32\x31.temporal.api.workflow.v1.WorkflowExecutionConfig\x12P\n\x17workflow_execution_info\x18\x02 \x01(\x0b\x32/.temporal.api.workflow.v1.WorkflowExecutionInfo\x12I\n\x12pending_activities\x18\x03 \x03(\x0b\x32-.temporal.api.workflow.v1.PendingActivityInfo\x12M\n\x10pending_children\x18\x04 \x03(\x0b\x32\x33.temporal.api.workflow.v1.PendingChildExecutionInfo\x12P\n\x15pending_workflow_task\x18\x05 \x01(\x0b\x32\x31.temporal.api.workflow.v1.PendingWorkflowTaskInfo\x12\x39\n\tcallbacks\x18\x06 \x03(\x0b\x32&.temporal.api.workflow.v1.CallbackInfo\x12U\n\x18pending_nexus_operations\x18\x07 \x03(\x0b\x32\x33.temporal.api.workflow.v1.PendingNexusOperationInfo\x12W\n\x16workflow_extended_info\x18\x08 \x01(\x0b\x32\x37.temporal.api.workflow.v1.WorkflowExecutionExtendedInfo"\x90\x04\n\x18\x44\x65scribeTaskQueueRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x38\n\ntask_queue\x18\x02 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12=\n\x0ftask_queue_type\x18\x03 \x01(\x0e\x32$.temporal.api.enums.v1.TaskQueueType\x12\x14\n\x0creport_stats\x18\x08 \x01(\x08\x12\x15\n\rreport_config\x18\x0b \x01(\x08\x12%\n\x19include_task_queue_status\x18\x04 \x01(\x08\x42\x02\x18\x01\x12\x42\n\x08\x61pi_mode\x18\x05 \x01(\x0e\x32,.temporal.api.enums.v1.DescribeTaskQueueModeB\x02\x18\x01\x12J\n\x08versions\x18\x06 \x01(\x0b\x32\x34.temporal.api.taskqueue.v1.TaskQueueVersionSelectionB\x02\x18\x01\x12\x42\n\x10task_queue_types\x18\x07 \x03(\x0e\x32$.temporal.api.enums.v1.TaskQueueTypeB\x02\x18\x01\x12\x1a\n\x0ereport_pollers\x18\t \x01(\x08\x42\x02\x18\x01\x12$\n\x18report_task_reachability\x18\n \x01(\x08\x42\x02\x18\x01"\xec\x07\n\x19\x44\x65scribeTaskQueueResponse\x12\x36\n\x07pollers\x18\x01 \x03(\x0b\x32%.temporal.api.taskqueue.v1.PollerInfo\x12\x38\n\x05stats\x18\x05 \x01(\x0b\x32).temporal.api.taskqueue.v1.TaskQueueStats\x12q\n\x15stats_by_priority_key\x18\x08 \x03(\x0b\x32R.temporal.api.workflowservice.v1.DescribeTaskQueueResponse.StatsByPriorityKeyEntry\x12K\n\x0fversioning_info\x18\x04 \x01(\x0b\x32\x32.temporal.api.taskqueue.v1.TaskQueueVersioningInfo\x12:\n\x06\x63onfig\x18\x06 \x01(\x0b\x32*.temporal.api.taskqueue.v1.TaskQueueConfig\x12k\n\x14\x65\x66\x66\x65\x63tive_rate_limit\x18\x07 \x01(\x0b\x32M.temporal.api.workflowservice.v1.DescribeTaskQueueResponse.EffectiveRateLimit\x12I\n\x11task_queue_status\x18\x02 \x01(\x0b\x32*.temporal.api.taskqueue.v1.TaskQueueStatusB\x02\x18\x01\x12g\n\rversions_info\x18\x03 \x03(\x0b\x32L.temporal.api.workflowservice.v1.DescribeTaskQueueResponse.VersionsInfoEntryB\x02\x18\x01\x1a\x64\n\x17StatsByPriorityKeyEntry\x12\x0b\n\x03key\x18\x01 \x01(\x05\x12\x38\n\x05value\x18\x02 \x01(\x0b\x32).temporal.api.taskqueue.v1.TaskQueueStats:\x02\x38\x01\x1at\n\x12\x45\x66\x66\x65\x63tiveRateLimit\x12\x1b\n\x13requests_per_second\x18\x01 \x01(\x02\x12\x41\n\x11rate_limit_source\x18\x02 \x01(\x0e\x32&.temporal.api.enums.v1.RateLimitSource\x1a\x64\n\x11VersionsInfoEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12>\n\x05value\x18\x02 \x01(\x0b\x32/.temporal.api.taskqueue.v1.TaskQueueVersionInfo:\x02\x38\x01"\x17\n\x15GetClusterInfoRequest"\xd1\x03\n\x16GetClusterInfoResponse\x12h\n\x11supported_clients\x18\x01 \x03(\x0b\x32M.temporal.api.workflowservice.v1.GetClusterInfoResponse.SupportedClientsEntry\x12\x16\n\x0eserver_version\x18\x02 \x01(\t\x12\x12\n\ncluster_id\x18\x03 \x01(\t\x12:\n\x0cversion_info\x18\x04 \x01(\x0b\x32$.temporal.api.version.v1.VersionInfo\x12\x14\n\x0c\x63luster_name\x18\x05 \x01(\t\x12\x1b\n\x13history_shard_count\x18\x06 \x01(\x05\x12\x19\n\x11persistence_store\x18\x07 \x01(\t\x12\x18\n\x10visibility_store\x18\x08 \x01(\t\x12 \n\x18initial_failover_version\x18\t \x01(\x03\x12"\n\x1a\x66\x61ilover_version_increment\x18\n \x01(\x03\x1a\x37\n\x15SupportedClientsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01"\x16\n\x14GetSystemInfoRequest"\x97\x04\n\x15GetSystemInfoResponse\x12\x16\n\x0eserver_version\x18\x01 \x01(\t\x12Y\n\x0c\x63\x61pabilities\x18\x02 \x01(\x0b\x32\x43.temporal.api.workflowservice.v1.GetSystemInfoResponse.Capabilities\x1a\x8a\x03\n\x0c\x43\x61pabilities\x12\x1f\n\x17signal_and_query_header\x18\x01 \x01(\x08\x12&\n\x1einternal_error_differentiation\x18\x02 \x01(\x08\x12*\n"activity_failure_include_heartbeat\x18\x03 \x01(\x08\x12\x1a\n\x12supports_schedules\x18\x04 \x01(\x08\x12"\n\x1a\x65ncoded_failure_attributes\x18\x05 \x01(\x08\x12!\n\x19\x62uild_id_based_versioning\x18\x06 \x01(\x08\x12\x13\n\x0bupsert_memo\x18\x07 \x01(\x08\x12\x1c\n\x14\x65\x61ger_workflow_start\x18\x08 \x01(\x08\x12\x14\n\x0csdk_metadata\x18\t \x01(\x08\x12\'\n\x1f\x63ount_group_by_execution_status\x18\n \x01(\x08\x12\r\n\x05nexus\x18\x0b \x01(\x08\x12!\n\x19server_scaled_deployments\x18\x0c \x01(\x08"m\n\x1eListTaskQueuePartitionsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x38\n\ntask_queue\x18\x02 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue"\xdf\x01\n\x1fListTaskQueuePartitionsResponse\x12]\n\x1e\x61\x63tivity_task_queue_partitions\x18\x01 \x03(\x0b\x32\x35.temporal.api.taskqueue.v1.TaskQueuePartitionMetadata\x12]\n\x1eworkflow_task_queue_partitions\x18\x02 \x03(\x0b\x32\x35.temporal.api.taskqueue.v1.TaskQueuePartitionMetadata"\xcc\x02\n\x15\x43reateScheduleRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bschedule_id\x18\x02 \x01(\t\x12\x34\n\x08schedule\x18\x03 \x01(\x0b\x32".temporal.api.schedule.v1.Schedule\x12>\n\rinitial_patch\x18\x04 \x01(\x0b\x32\'.temporal.api.schedule.v1.SchedulePatch\x12\x10\n\x08identity\x18\x05 \x01(\t\x12\x12\n\nrequest_id\x18\x06 \x01(\t\x12*\n\x04memo\x18\x07 \x01(\x0b\x32\x1c.temporal.api.common.v1.Memo\x12\x43\n\x11search_attributes\x18\x08 \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes"0\n\x16\x43reateScheduleResponse\x12\x16\n\x0e\x63onflict_token\x18\x01 \x01(\x0c"A\n\x17\x44\x65scribeScheduleRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bschedule_id\x18\x02 \x01(\t"\x8f\x02\n\x18\x44\x65scribeScheduleResponse\x12\x34\n\x08schedule\x18\x01 \x01(\x0b\x32".temporal.api.schedule.v1.Schedule\x12\x34\n\x04info\x18\x02 \x01(\x0b\x32&.temporal.api.schedule.v1.ScheduleInfo\x12*\n\x04memo\x18\x03 \x01(\x0b\x32\x1c.temporal.api.common.v1.Memo\x12\x43\n\x11search_attributes\x18\x04 \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes\x12\x16\n\x0e\x63onflict_token\x18\x05 \x01(\x0c"\xa4\x02\n\x15UpdateScheduleRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bschedule_id\x18\x02 \x01(\t\x12\x34\n\x08schedule\x18\x03 \x01(\x0b\x32".temporal.api.schedule.v1.Schedule\x12\x16\n\x0e\x63onflict_token\x18\x04 \x01(\x0c\x12\x10\n\x08identity\x18\x05 \x01(\t\x12\x12\n\nrequest_id\x18\x06 \x01(\t\x12\x43\n\x11search_attributes\x18\x07 \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes\x12*\n\x04memo\x18\x08 \x01(\x0b\x32\x1c.temporal.api.common.v1.Memo"\x18\n\x16UpdateScheduleResponse"\x9c\x01\n\x14PatchScheduleRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bschedule_id\x18\x02 \x01(\t\x12\x36\n\x05patch\x18\x03 \x01(\x0b\x32\'.temporal.api.schedule.v1.SchedulePatch\x12\x10\n\x08identity\x18\x04 \x01(\t\x12\x12\n\nrequest_id\x18\x05 \x01(\t"\x17\n\x15PatchScheduleResponse"\xa8\x01\n ListScheduleMatchingTimesRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bschedule_id\x18\x02 \x01(\t\x12.\n\nstart_time\x18\x03 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12,\n\x08\x65nd_time\x18\x04 \x01(\x0b\x32\x1a.google.protobuf.Timestamp"S\n!ListScheduleMatchingTimesResponse\x12.\n\nstart_time\x18\x01 \x03(\x0b\x32\x1a.google.protobuf.Timestamp"Q\n\x15\x44\x65leteScheduleRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bschedule_id\x18\x02 \x01(\t\x12\x10\n\x08identity\x18\x03 \x01(\t"\x18\n\x16\x44\x65leteScheduleResponse"l\n\x14ListSchedulesRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x19\n\x11maximum_page_size\x18\x02 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c\x12\r\n\x05query\x18\x04 \x01(\t"p\n\x15ListSchedulesResponse\x12>\n\tschedules\x18\x01 \x03(\x0b\x32+.temporal.api.schedule.v1.ScheduleListEntry\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c"9\n\x15\x43ountSchedulesRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\r\n\x05query\x18\x02 \x01(\t"\xdb\x01\n\x16\x43ountSchedulesResponse\x12\r\n\x05\x63ount\x18\x01 \x01(\x03\x12X\n\x06groups\x18\x02 \x03(\x0b\x32H.temporal.api.workflowservice.v1.CountSchedulesResponse.AggregationGroup\x1aX\n\x10\x41ggregationGroup\x12\x35\n\x0cgroup_values\x18\x01 \x03(\x0b\x32\x1f.temporal.api.common.v1.Payload\x12\r\n\x05\x63ount\x18\x02 \x01(\x03"\x86\x05\n\'UpdateWorkerBuildIdCompatibilityRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x12\n\ntask_queue\x18\x02 \x01(\t\x12-\n#add_new_build_id_in_new_default_set\x18\x03 \x01(\tH\x00\x12\x87\x01\n\x1b\x61\x64\x64_new_compatible_build_id\x18\x04 \x01(\x0b\x32`.temporal.api.workflowservice.v1.UpdateWorkerBuildIdCompatibilityRequest.AddNewCompatibleVersionH\x00\x12!\n\x17promote_set_by_build_id\x18\x05 \x01(\tH\x00\x12%\n\x1bpromote_build_id_within_set\x18\x06 \x01(\tH\x00\x12h\n\nmerge_sets\x18\x07 \x01(\x0b\x32R.temporal.api.workflowservice.v1.UpdateWorkerBuildIdCompatibilityRequest.MergeSetsH\x00\x1ao\n\x17\x41\x64\x64NewCompatibleVersion\x12\x14\n\x0cnew_build_id\x18\x01 \x01(\t\x12$\n\x1c\x65xisting_compatible_build_id\x18\x02 \x01(\t\x12\x18\n\x10make_set_default\x18\x03 \x01(\x08\x1aI\n\tMergeSets\x12\x1c\n\x14primary_set_build_id\x18\x01 \x01(\t\x12\x1e\n\x16secondary_set_build_id\x18\x02 \x01(\tB\x0b\n\toperation"@\n(UpdateWorkerBuildIdCompatibilityResponseJ\x04\x08\x01\x10\x02R\x0eversion_set_id"_\n$GetWorkerBuildIdCompatibilityRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x12\n\ntask_queue\x18\x02 \x01(\t\x12\x10\n\x08max_sets\x18\x03 \x01(\x05"t\n%GetWorkerBuildIdCompatibilityResponse\x12K\n\x12major_version_sets\x18\x01 \x03(\x0b\x32/.temporal.api.taskqueue.v1.CompatibleVersionSet"\xb5\r\n"UpdateWorkerVersioningRulesRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x12\n\ntask_queue\x18\x02 \x01(\t\x12\x16\n\x0e\x63onflict_token\x18\x03 \x01(\x0c\x12\x81\x01\n\x16insert_assignment_rule\x18\x04 \x01(\x0b\x32_.temporal.api.workflowservice.v1.UpdateWorkerVersioningRulesRequest.InsertBuildIdAssignmentRuleH\x00\x12\x83\x01\n\x17replace_assignment_rule\x18\x05 \x01(\x0b\x32`.temporal.api.workflowservice.v1.UpdateWorkerVersioningRulesRequest.ReplaceBuildIdAssignmentRuleH\x00\x12\x81\x01\n\x16\x64\x65lete_assignment_rule\x18\x06 \x01(\x0b\x32_.temporal.api.workflowservice.v1.UpdateWorkerVersioningRulesRequest.DeleteBuildIdAssignmentRuleH\x00\x12\x8c\x01\n\x1c\x61\x64\x64_compatible_redirect_rule\x18\x07 \x01(\x0b\x32\x64.temporal.api.workflowservice.v1.UpdateWorkerVersioningRulesRequest.AddCompatibleBuildIdRedirectRuleH\x00\x12\x94\x01\n replace_compatible_redirect_rule\x18\x08 \x01(\x0b\x32h.temporal.api.workflowservice.v1.UpdateWorkerVersioningRulesRequest.ReplaceCompatibleBuildIdRedirectRuleH\x00\x12\x92\x01\n\x1f\x64\x65lete_compatible_redirect_rule\x18\t \x01(\x0b\x32g.temporal.api.workflowservice.v1.UpdateWorkerVersioningRulesRequest.DeleteCompatibleBuildIdRedirectRuleH\x00\x12l\n\x0f\x63ommit_build_id\x18\n \x01(\x0b\x32Q.temporal.api.workflowservice.v1.UpdateWorkerVersioningRulesRequest.CommitBuildIdH\x00\x1aq\n\x1bInsertBuildIdAssignmentRule\x12\x12\n\nrule_index\x18\x01 \x01(\x05\x12>\n\x04rule\x18\x02 \x01(\x0b\x32\x30.temporal.api.taskqueue.v1.BuildIdAssignmentRule\x1a\x81\x01\n\x1cReplaceBuildIdAssignmentRule\x12\x12\n\nrule_index\x18\x01 \x01(\x05\x12>\n\x04rule\x18\x02 \x01(\x0b\x32\x30.temporal.api.taskqueue.v1.BuildIdAssignmentRule\x12\r\n\x05\x66orce\x18\x03 \x01(\x08\x1a@\n\x1b\x44\x65leteBuildIdAssignmentRule\x12\x12\n\nrule_index\x18\x01 \x01(\x05\x12\r\n\x05\x66orce\x18\x02 \x01(\x08\x1aj\n AddCompatibleBuildIdRedirectRule\x12\x46\n\x04rule\x18\x01 \x01(\x0b\x32\x38.temporal.api.taskqueue.v1.CompatibleBuildIdRedirectRule\x1an\n$ReplaceCompatibleBuildIdRedirectRule\x12\x46\n\x04rule\x18\x01 \x01(\x0b\x32\x38.temporal.api.taskqueue.v1.CompatibleBuildIdRedirectRule\x1a>\n#DeleteCompatibleBuildIdRedirectRule\x12\x17\n\x0fsource_build_id\x18\x01 \x01(\t\x1a\x37\n\rCommitBuildId\x12\x17\n\x0ftarget_build_id\x18\x01 \x01(\t\x12\r\n\x05\x66orce\x18\x02 \x01(\x08\x42\x0b\n\toperation"\xfc\x01\n#UpdateWorkerVersioningRulesResponse\x12U\n\x10\x61ssignment_rules\x18\x01 \x03(\x0b\x32;.temporal.api.taskqueue.v1.TimestampedBuildIdAssignmentRule\x12\x66\n\x19\x63ompatible_redirect_rules\x18\x02 \x03(\x0b\x32\x43.temporal.api.taskqueue.v1.TimestampedCompatibleBuildIdRedirectRule\x12\x16\n\x0e\x63onflict_token\x18\x03 \x01(\x0c"H\n\x1fGetWorkerVersioningRulesRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x12\n\ntask_queue\x18\x02 \x01(\t"\xf9\x01\n GetWorkerVersioningRulesResponse\x12U\n\x10\x61ssignment_rules\x18\x01 \x03(\x0b\x32;.temporal.api.taskqueue.v1.TimestampedBuildIdAssignmentRule\x12\x66\n\x19\x63ompatible_redirect_rules\x18\x02 \x03(\x0b\x32\x43.temporal.api.taskqueue.v1.TimestampedCompatibleBuildIdRedirectRule\x12\x16\n\x0e\x63onflict_token\x18\x03 \x01(\x0c"\x9c\x01\n GetWorkerTaskReachabilityRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x11\n\tbuild_ids\x18\x02 \x03(\t\x12\x13\n\x0btask_queues\x18\x03 \x03(\t\x12=\n\x0creachability\x18\x04 \x01(\x0e\x32\'.temporal.api.enums.v1.TaskReachability"r\n!GetWorkerTaskReachabilityResponse\x12M\n\x15\x62uild_id_reachability\x18\x01 \x03(\x0b\x32..temporal.api.taskqueue.v1.BuildIdReachability"\x85\x02\n\x1eUpdateWorkflowExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x45\n\x12workflow_execution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x1e\n\x16\x66irst_execution_run_id\x18\x03 \x01(\t\x12\x37\n\x0bwait_policy\x18\x04 \x01(\x0b\x32".temporal.api.update.v1.WaitPolicy\x12\x30\n\x07request\x18\x05 \x01(\x0b\x32\x1f.temporal.api.update.v1.Request"\xd7\x01\n\x1fUpdateWorkflowExecutionResponse\x12\x35\n\nupdate_ref\x18\x01 \x01(\x0b\x32!.temporal.api.update.v1.UpdateRef\x12\x30\n\x07outcome\x18\x02 \x01(\x0b\x32\x1f.temporal.api.update.v1.Outcome\x12K\n\x05stage\x18\x03 \x01(\x0e\x32<.temporal.api.enums.v1.UpdateWorkflowExecutionLifecycleStage"\xf4\x07\n\x1aStartBatchOperationRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x18\n\x10visibility_query\x18\x02 \x01(\t\x12\x0e\n\x06job_id\x18\x03 \x01(\t\x12\x0e\n\x06reason\x18\x04 \x01(\t\x12=\n\nexecutions\x18\x05 \x03(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12!\n\x19max_operations_per_second\x18\x06 \x01(\x02\x12Q\n\x15termination_operation\x18\n \x01(\x0b\x32\x30.temporal.api.batch.v1.BatchOperationTerminationH\x00\x12G\n\x10signal_operation\x18\x0b \x01(\x0b\x32+.temporal.api.batch.v1.BatchOperationSignalH\x00\x12S\n\x16\x63\x61ncellation_operation\x18\x0c \x01(\x0b\x32\x31.temporal.api.batch.v1.BatchOperationCancellationH\x00\x12K\n\x12\x64\x65letion_operation\x18\r \x01(\x0b\x32-.temporal.api.batch.v1.BatchOperationDeletionH\x00\x12\x45\n\x0freset_operation\x18\x0e \x01(\x0b\x32*.temporal.api.batch.v1.BatchOperationResetH\x00\x12p\n!update_workflow_options_operation\x18\x0f \x01(\x0b\x32\x43.temporal.api.batch.v1.BatchOperationUpdateWorkflowExecutionOptionsH\x00\x12^\n\x1cunpause_activities_operation\x18\x10 \x01(\x0b\x32\x36.temporal.api.batch.v1.BatchOperationUnpauseActivitiesH\x00\x12Z\n\x1areset_activities_operation\x18\x11 \x01(\x0b\x32\x34.temporal.api.batch.v1.BatchOperationResetActivitiesH\x00\x12g\n!update_activity_options_operation\x18\x12 \x01(\x0b\x32:.temporal.api.batch.v1.BatchOperationUpdateActivityOptionsH\x00\x42\x0b\n\toperation"\x1d\n\x1bStartBatchOperationResponse"`\n\x19StopBatchOperationRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x0e\n\x06job_id\x18\x02 \x01(\t\x12\x0e\n\x06reason\x18\x03 \x01(\t\x12\x10\n\x08identity\x18\x04 \x01(\t"\x1c\n\x1aStopBatchOperationResponse"B\n\x1d\x44\x65scribeBatchOperationRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x0e\n\x06job_id\x18\x02 \x01(\t"\x92\x03\n\x1e\x44\x65scribeBatchOperationResponse\x12\x41\n\x0eoperation_type\x18\x01 \x01(\x0e\x32).temporal.api.enums.v1.BatchOperationType\x12\x0e\n\x06job_id\x18\x02 \x01(\t\x12\x39\n\x05state\x18\x03 \x01(\x0e\x32*.temporal.api.enums.v1.BatchOperationState\x12.\n\nstart_time\x18\x04 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12.\n\nclose_time\x18\x05 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x1d\n\x15total_operation_count\x18\x06 \x01(\x03\x12 \n\x18\x63omplete_operation_count\x18\x07 \x01(\x03\x12\x1f\n\x17\x66\x61ilure_operation_count\x18\x08 \x01(\x03\x12\x10\n\x08identity\x18\t \x01(\t\x12\x0e\n\x06reason\x18\n \x01(\t"[\n\x1aListBatchOperationsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x11\n\tpage_size\x18\x02 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c"y\n\x1bListBatchOperationsResponse\x12\x41\n\x0eoperation_info\x18\x01 \x03(\x0b\x32).temporal.api.batch.v1.BatchOperationInfo\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c"\xb9\x01\n"PollWorkflowExecutionUpdateRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x35\n\nupdate_ref\x18\x02 \x01(\x0b\x32!.temporal.api.update.v1.UpdateRef\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x37\n\x0bwait_policy\x18\x04 \x01(\x0b\x32".temporal.api.update.v1.WaitPolicy"\xdb\x01\n#PollWorkflowExecutionUpdateResponse\x12\x30\n\x07outcome\x18\x01 \x01(\x0b\x32\x1f.temporal.api.update.v1.Outcome\x12K\n\x05stage\x18\x02 \x01(\x0e\x32<.temporal.api.enums.v1.UpdateWorkflowExecutionLifecycleStage\x12\x35\n\nupdate_ref\x18\x03 \x01(\x0b\x32!.temporal.api.update.v1.UpdateRef"\xa0\x03\n\x19PollNexusTaskQueueRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x38\n\ntask_queue\x18\x03 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12\x17\n\x0fpoller_group_id\x18\t \x01(\t\x12\x10\n\x08identity\x18\x02 \x01(\t\x12\x1b\n\x13worker_instance_key\x18\x08 \x01(\t\x12Z\n\x1bworker_version_capabilities\x18\x04 \x01(\x0b\x32\x31.temporal.api.common.v1.WorkerVersionCapabilitiesB\x02\x18\x01\x12O\n\x12\x64\x65ployment_options\x18\x06 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentOptions\x12\x41\n\x10worker_heartbeat\x18\x07 \x03(\x0b\x32\'.temporal.api.worker.v1.WorkerHeartbeat"\x95\x02\n\x1aPollNexusTaskQueueResponse\x12\x12\n\ntask_token\x18\x01 \x01(\x0c\x12/\n\x07request\x18\x02 \x01(\x0b\x32\x1e.temporal.api.nexus.v1.Request\x12Q\n\x17poller_scaling_decision\x18\x03 \x01(\x0b\x32\x30.temporal.api.taskqueue.v1.PollerScalingDecision\x12\x17\n\x0fpoller_group_id\x18\x04 \x01(\t\x12\x46\n\x12poller_group_infos\x18\x05 \x03(\x0b\x32*.temporal.api.taskqueue.v1.PollerGroupInfo"\xa7\x01\n RespondNexusTaskCompletedRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x10\n\x08identity\x18\x02 \x01(\t\x12\x12\n\ntask_token\x18\x03 \x01(\x0c\x12\x31\n\x08response\x18\x04 \x01(\x0b\x32\x1f.temporal.api.nexus.v1.Response\x12\x17\n\x0fpoller_group_id\x18\x05 \x01(\t"#\n!RespondNexusTaskCompletedResponse"\xdc\x01\n\x1dRespondNexusTaskFailedRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x10\n\x08identity\x18\x02 \x01(\t\x12\x12\n\ntask_token\x18\x03 \x01(\x0c\x12\x36\n\x05\x65rror\x18\x04 \x01(\x0b\x32#.temporal.api.nexus.v1.HandlerErrorB\x02\x18\x01\x12\x31\n\x07\x66\x61ilure\x18\x05 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12\x17\n\x0fpoller_group_id\x18\x06 \x01(\t" \n\x1eRespondNexusTaskFailedResponse"\xf4\x02\n\x1c\x45xecuteMultiOperationRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12[\n\noperations\x18\x02 \x03(\x0b\x32G.temporal.api.workflowservice.v1.ExecuteMultiOperationRequest.Operation\x12\x13\n\x0bresource_id\x18\x03 \x01(\t\x1a\xce\x01\n\tOperation\x12X\n\x0estart_workflow\x18\x01 \x01(\x0b\x32>.temporal.api.workflowservice.v1.StartWorkflowExecutionRequestH\x00\x12Z\n\x0fupdate_workflow\x18\x02 \x01(\x0b\x32?.temporal.api.workflowservice.v1.UpdateWorkflowExecutionRequestH\x00\x42\x0b\n\toperation"\xcc\x02\n\x1d\x45xecuteMultiOperationResponse\x12Z\n\tresponses\x18\x01 \x03(\x0b\x32G.temporal.api.workflowservice.v1.ExecuteMultiOperationResponse.Response\x1a\xce\x01\n\x08Response\x12Y\n\x0estart_workflow\x18\x01 \x01(\x0b\x32?.temporal.api.workflowservice.v1.StartWorkflowExecutionResponseH\x00\x12[\n\x0fupdate_workflow\x18\x02 \x01(\x0b\x32@.temporal.api.workflowservice.v1.UpdateWorkflowExecutionResponseH\x00\x42\n\n\x08response"\xd0\x02\n\x1cUpdateActivityOptionsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12<\n\texecution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x43\n\x10\x61\x63tivity_options\x18\x04 \x01(\x0b\x32).temporal.api.activity.v1.ActivityOptions\x12/\n\x0bupdate_mask\x18\x05 \x01(\x0b\x32\x1a.google.protobuf.FieldMask\x12\x0c\n\x02id\x18\x06 \x01(\tH\x00\x12\x0e\n\x04type\x18\x07 \x01(\tH\x00\x12\x13\n\tmatch_all\x18\t \x01(\x08H\x00\x12\x18\n\x10restore_original\x18\x08 \x01(\x08\x42\n\n\x08\x61\x63tivity"\xab\x02\n%UpdateActivityExecutionOptionsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12\x13\n\x0b\x61\x63tivity_id\x18\x03 \x01(\t\x12\x0e\n\x06run_id\x18\x04 \x01(\t\x12\x10\n\x08identity\x18\x05 \x01(\t\x12\x43\n\x10\x61\x63tivity_options\x18\x06 \x01(\x0b\x32).temporal.api.activity.v1.ActivityOptions\x12/\n\x0bupdate_mask\x18\x07 \x01(\x0b\x32\x1a.google.protobuf.FieldMask\x12\x18\n\x10restore_original\x18\x08 \x01(\x08\x12\x13\n\x0bresource_id\x18\t \x01(\t"d\n\x1dUpdateActivityOptionsResponse\x12\x43\n\x10\x61\x63tivity_options\x18\x01 \x01(\x0b\x32).temporal.api.activity.v1.ActivityOptions"m\n&UpdateActivityExecutionOptionsResponse\x12\x43\n\x10\x61\x63tivity_options\x18\x01 \x01(\x0b\x32).temporal.api.activity.v1.ActivityOptions"\xc7\x01\n\x14PauseActivityRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12<\n\texecution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x0c\n\x02id\x18\x04 \x01(\tH\x00\x12\x0e\n\x04type\x18\x05 \x01(\tH\x00\x12\x0e\n\x06reason\x18\x06 \x01(\t\x12\x12\n\nrequest_id\x18\x07 \x01(\tB\n\n\x08\x61\x63tivity"\xb7\x01\n\x1dPauseActivityExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12\x13\n\x0b\x61\x63tivity_id\x18\x03 \x01(\t\x12\x0e\n\x06run_id\x18\x04 \x01(\t\x12\x10\n\x08identity\x18\x05 \x01(\t\x12\x0e\n\x06reason\x18\x06 \x01(\t\x12\x13\n\x0bresource_id\x18\x07 \x01(\t\x12\x12\n\nrequest_id\x18\x08 \x01(\t"\x17\n\x15PauseActivityResponse" \n\x1ePauseActivityExecutionResponse"\x98\x02\n\x16UnpauseActivityRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12<\n\texecution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x0c\n\x02id\x18\x04 \x01(\tH\x00\x12\x0e\n\x04type\x18\x05 \x01(\tH\x00\x12\x15\n\x0bunpause_all\x18\x06 \x01(\x08H\x00\x12\x16\n\x0ereset_attempts\x18\x07 \x01(\x08\x12\x17\n\x0freset_heartbeat\x18\x08 \x01(\x08\x12)\n\x06jitter\x18\t \x01(\x0b\x32\x19.google.protobuf.DurationB\n\n\x08\x61\x63tivity"\x81\x02\n\x1fUnpauseActivityExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12\x13\n\x0b\x61\x63tivity_id\x18\x03 \x01(\t\x12\x0e\n\x06run_id\x18\x04 \x01(\t\x12\x10\n\x08identity\x18\x05 \x01(\t\x12\x16\n\x0ereset_attempts\x18\x06 \x01(\x08\x12\x17\n\x0freset_heartbeat\x18\x07 \x01(\x08\x12\x0e\n\x06reason\x18\x08 \x01(\t\x12)\n\x06jitter\x18\t \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x13\n\x0bresource_id\x18\n \x01(\t"\x19\n\x17UnpauseActivityResponse""\n UnpauseActivityExecutionResponse"\xb3\x02\n\x14ResetActivityRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12<\n\texecution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x0c\n\x02id\x18\x04 \x01(\tH\x00\x12\x0e\n\x04type\x18\x05 \x01(\tH\x00\x12\x13\n\tmatch_all\x18\n \x01(\x08H\x00\x12\x17\n\x0freset_heartbeat\x18\x06 \x01(\x08\x12\x13\n\x0bkeep_paused\x18\x07 \x01(\x08\x12)\n\x06jitter\x18\x08 \x01(\x0b\x32\x19.google.protobuf.Duration\x12 \n\x18restore_original_options\x18\t \x01(\x08\x42\n\n\x08\x61\x63tivity"\x8e\x02\n\x1dResetActivityExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12\x13\n\x0b\x61\x63tivity_id\x18\x03 \x01(\t\x12\x0e\n\x06run_id\x18\x04 \x01(\t\x12\x10\n\x08identity\x18\x05 \x01(\t\x12\x17\n\x0freset_heartbeat\x18\x06 \x01(\x08\x12\x13\n\x0bkeep_paused\x18\x07 \x01(\x08\x12)\n\x06jitter\x18\x08 \x01(\x0b\x32\x19.google.protobuf.Duration\x12 \n\x18restore_original_options\x18\t \x01(\x08\x12\x13\n\x0bresource_id\x18\n \x01(\t"\x17\n\x15ResetActivityResponse" \n\x1eResetActivityExecutionResponse"\x9c\x02\n%UpdateWorkflowExecutionOptionsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x45\n\x12workflow_execution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12V\n\x1aworkflow_execution_options\x18\x03 \x01(\x0b\x32\x32.temporal.api.workflow.v1.WorkflowExecutionOptions\x12/\n\x0bupdate_mask\x18\x04 \x01(\x0b\x32\x1a.google.protobuf.FieldMask\x12\x10\n\x08identity\x18\x05 \x01(\t"\x80\x01\n&UpdateWorkflowExecutionOptionsResponse\x12V\n\x1aworkflow_execution_options\x18\x01 \x01(\x0b\x32\x32.temporal.api.workflow.v1.WorkflowExecutionOptions"j\n\x19\x44\x65scribeDeploymentRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12:\n\ndeployment\x18\x02 \x01(\x0b\x32&.temporal.api.deployment.v1.Deployment"a\n\x1a\x44\x65scribeDeploymentResponse\x12\x43\n\x0f\x64\x65ployment_info\x18\x01 \x01(\x0b\x32*.temporal.api.deployment.v1.DeploymentInfo"\xc2\x01\n&DescribeWorkerDeploymentVersionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x07version\x18\x02 \x01(\tB\x02\x18\x01\x12O\n\x12\x64\x65ployment_version\x18\x03 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersion\x12\x1f\n\x17report_task_queue_stats\x18\x04 \x01(\x08"\x8c\x05\n\'DescribeWorkerDeploymentVersionResponse\x12_\n\x1eworker_deployment_version_info\x18\x01 \x01(\x0b\x32\x37.temporal.api.deployment.v1.WorkerDeploymentVersionInfo\x12v\n\x13version_task_queues\x18\x02 \x03(\x0b\x32Y.temporal.api.workflowservice.v1.DescribeWorkerDeploymentVersionResponse.VersionTaskQueue\x1a\x87\x03\n\x10VersionTaskQueue\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x32\n\x04type\x18\x02 \x01(\x0e\x32$.temporal.api.enums.v1.TaskQueueType\x12\x38\n\x05stats\x18\x03 \x01(\x0b\x32).temporal.api.taskqueue.v1.TaskQueueStats\x12\x90\x01\n\x15stats_by_priority_key\x18\x04 \x03(\x0b\x32q.temporal.api.workflowservice.v1.DescribeWorkerDeploymentVersionResponse.VersionTaskQueue.StatsByPriorityKeyEntry\x1a\x64\n\x17StatsByPriorityKeyEntry\x12\x0b\n\x03key\x18\x01 \x01(\x05\x12\x38\n\x05value\x18\x02 \x01(\x0b\x32).temporal.api.taskqueue.v1.TaskQueueStats:\x02\x38\x01"M\n\x1f\x44\x65scribeWorkerDeploymentRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x17\n\x0f\x64\x65ployment_name\x18\x02 \x01(\t"\x8c\x01\n DescribeWorkerDeploymentResponse\x12\x16\n\x0e\x63onflict_token\x18\x01 \x01(\x0c\x12P\n\x16worker_deployment_info\x18\x02 \x01(\x0b\x32\x30.temporal.api.deployment.v1.WorkerDeploymentInfo"l\n\x16ListDeploymentsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x11\n\tpage_size\x18\x02 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c\x12\x13\n\x0bseries_name\x18\x04 \x01(\t"w\n\x17ListDeploymentsResponse\x12\x17\n\x0fnext_page_token\x18\x01 \x01(\x0c\x12\x43\n\x0b\x64\x65ployments\x18\x02 \x03(\x0b\x32..temporal.api.deployment.v1.DeploymentListInfo"\xcd\x01\n\x1bSetCurrentDeploymentRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12:\n\ndeployment\x18\x02 \x01(\x0b\x32&.temporal.api.deployment.v1.Deployment\x12\x10\n\x08identity\x18\x03 \x01(\t\x12M\n\x0fupdate_metadata\x18\x04 \x01(\x0b\x32\x34.temporal.api.deployment.v1.UpdateDeploymentMetadata"\xb9\x01\n\x1cSetCurrentDeploymentResponse\x12K\n\x17\x63urrent_deployment_info\x18\x01 \x01(\x0b\x32*.temporal.api.deployment.v1.DeploymentInfo\x12L\n\x18previous_deployment_info\x18\x02 \x01(\x0b\x32*.temporal.api.deployment.v1.DeploymentInfo"\xe5\x01\n(SetWorkerDeploymentCurrentVersionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x17\n\x0f\x64\x65ployment_name\x18\x02 \x01(\t\x12\x13\n\x07version\x18\x03 \x01(\tB\x02\x18\x01\x12\x10\n\x08\x62uild_id\x18\x07 \x01(\t\x12\x16\n\x0e\x63onflict_token\x18\x04 \x01(\x0c\x12\x10\n\x08identity\x18\x05 \x01(\t\x12"\n\x1aignore_missing_task_queues\x18\x06 \x01(\x08\x12\x18\n\x10\x61llow_no_pollers\x18\t \x01(\x08"\xbf\x01\n)SetWorkerDeploymentCurrentVersionResponse\x12\x16\n\x0e\x63onflict_token\x18\x01 \x01(\x0c\x12\x1c\n\x10previous_version\x18\x02 \x01(\tB\x02\x18\x01\x12\\\n\x1bprevious_deployment_version\x18\x03 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersionB\x02\x18\x01"\xf9\x01\n(SetWorkerDeploymentRampingVersionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x17\n\x0f\x64\x65ployment_name\x18\x02 \x01(\t\x12\x13\n\x07version\x18\x03 \x01(\tB\x02\x18\x01\x12\x10\n\x08\x62uild_id\x18\x08 \x01(\t\x12\x12\n\npercentage\x18\x04 \x01(\x02\x12\x16\n\x0e\x63onflict_token\x18\x05 \x01(\x0c\x12\x10\n\x08identity\x18\x06 \x01(\t\x12"\n\x1aignore_missing_task_queues\x18\x07 \x01(\x08\x12\x18\n\x10\x61llow_no_pollers\x18\n \x01(\x08"\xe0\x01\n)SetWorkerDeploymentRampingVersionResponse\x12\x16\n\x0e\x63onflict_token\x18\x01 \x01(\x0c\x12\x1c\n\x10previous_version\x18\x02 \x01(\tB\x02\x18\x01\x12\\\n\x1bprevious_deployment_version\x18\x04 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersionB\x02\x18\x01\x12\x1f\n\x13previous_percentage\x18\x03 \x01(\x02\x42\x02\x18\x01"q\n\x1d\x43reateWorkerDeploymentRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x17\n\x0f\x64\x65ployment_name\x18\x02 \x01(\t\x12\x10\n\x08identity\x18\x04 \x01(\t\x12\x12\n\nrequest_id\x18\x05 \x01(\t"8\n\x1e\x43reateWorkerDeploymentResponse\x12\x16\n\x0e\x63onflict_token\x18\x01 \x01(\x0c"]\n\x1cListWorkerDeploymentsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x11\n\tpage_size\x18\x02 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c"\x9f\x05\n\x1dListWorkerDeploymentsResponse\x12\x17\n\x0fnext_page_token\x18\x01 \x01(\x0c\x12r\n\x12worker_deployments\x18\x02 \x03(\x0b\x32V.temporal.api.workflowservice.v1.ListWorkerDeploymentsResponse.WorkerDeploymentSummary\x1a\xf0\x03\n\x17WorkerDeploymentSummary\x12\x0c\n\x04name\x18\x01 \x01(\t\x12/\n\x0b\x63reate_time\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x41\n\x0erouting_config\x18\x03 \x01(\x0b\x32).temporal.api.deployment.v1.RoutingConfig\x12o\n\x16latest_version_summary\x18\x04 \x01(\x0b\x32O.temporal.api.deployment.v1.WorkerDeploymentInfo.WorkerDeploymentVersionSummary\x12p\n\x17\x63urrent_version_summary\x18\x05 \x01(\x0b\x32O.temporal.api.deployment.v1.WorkerDeploymentInfo.WorkerDeploymentVersionSummary\x12p\n\x17ramping_version_summary\x18\x06 \x01(\x0b\x32O.temporal.api.deployment.v1.WorkerDeploymentInfo.WorkerDeploymentVersionSummary"\xf0\x01\n$CreateWorkerDeploymentVersionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12O\n\x12\x64\x65ployment_version\x18\x02 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersion\x12>\n\x0e\x63ompute_config\x18\x04 \x01(\x0b\x32&.temporal.api.compute.v1.ComputeConfig\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x12\n\nrequest_id\x18\x05 \x01(\t"\'\n%CreateWorkerDeploymentVersionResponse"\xc8\x01\n$DeleteWorkerDeploymentVersionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x07version\x18\x02 \x01(\tB\x02\x18\x01\x12O\n\x12\x64\x65ployment_version\x18\x05 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersion\x12\x15\n\rskip_drainage\x18\x03 \x01(\x08\x12\x10\n\x08identity\x18\x04 \x01(\t"\'\n%DeleteWorkerDeploymentVersionResponse"]\n\x1d\x44\x65leteWorkerDeploymentRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x17\n\x0f\x64\x65ployment_name\x18\x02 \x01(\t\x12\x10\n\x08identity\x18\x03 \x01(\t" \n\x1e\x44\x65leteWorkerDeploymentResponse"\x84\x04\n1UpdateWorkerDeploymentVersionComputeConfigRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12O\n\x12\x64\x65ployment_version\x18\x02 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersion\x12\x99\x01\n\x1d\x63ompute_config_scaling_groups\x18\x06 \x03(\x0b\x32r.temporal.api.workflowservice.v1.UpdateWorkerDeploymentVersionComputeConfigRequest.ComputeConfigScalingGroupsEntry\x12,\n$remove_compute_config_scaling_groups\x18\x07 \x03(\t\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x12\n\nrequest_id\x18\x04 \x01(\t\x1a{\n\x1f\x43omputeConfigScalingGroupsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12G\n\x05value\x18\x02 \x01(\x0b\x32\x38.temporal.api.compute.v1.ComputeConfigScalingGroupUpdate:\x02\x38\x01"4\n2UpdateWorkerDeploymentVersionComputeConfigResponse"\xf4\x03\n3ValidateWorkerDeploymentVersionComputeConfigRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12O\n\x12\x64\x65ployment_version\x18\x02 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersion\x12\x9b\x01\n\x1d\x63ompute_config_scaling_groups\x18\x06 \x03(\x0b\x32t.temporal.api.workflowservice.v1.ValidateWorkerDeploymentVersionComputeConfigRequest.ComputeConfigScalingGroupsEntry\x12,\n$remove_compute_config_scaling_groups\x18\x07 \x03(\t\x12\x10\n\x08identity\x18\x03 \x01(\t\x1a{\n\x1f\x43omputeConfigScalingGroupsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12G\n\x05value\x18\x02 \x01(\x0b\x32\x38.temporal.api.compute.v1.ComputeConfigScalingGroupUpdate:\x02\x38\x01"6\n4ValidateWorkerDeploymentVersionComputeConfigResponse"\xa2\x03\n,UpdateWorkerDeploymentVersionMetadataRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x07version\x18\x02 \x01(\tB\x02\x18\x01\x12O\n\x12\x64\x65ployment_version\x18\x05 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersion\x12x\n\x0eupsert_entries\x18\x03 \x03(\x0b\x32`.temporal.api.workflowservice.v1.UpdateWorkerDeploymentVersionMetadataRequest.UpsertEntriesEntry\x12\x16\n\x0eremove_entries\x18\x04 \x03(\t\x12\x10\n\x08identity\x18\x06 \x01(\t\x1aU\n\x12UpsertEntriesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12.\n\x05value\x18\x02 \x01(\x0b\x32\x1f.temporal.api.common.v1.Payload:\x02\x38\x01"n\n-UpdateWorkerDeploymentVersionMetadataResponse\x12=\n\x08metadata\x18\x01 \x01(\x0b\x32+.temporal.api.deployment.v1.VersionMetadata"\xbd\x01\n!SetWorkerDeploymentManagerRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x17\n\x0f\x64\x65ployment_name\x18\x02 \x01(\t\x12\x1a\n\x10manager_identity\x18\x03 \x01(\tH\x00\x12\x0e\n\x04self\x18\x04 \x01(\x08H\x00\x12\x16\n\x0e\x63onflict_token\x18\x05 \x01(\x0c\x12\x10\n\x08identity\x18\x06 \x01(\tB\x16\n\x14new_manager_identity"c\n"SetWorkerDeploymentManagerResponse\x12\x16\n\x0e\x63onflict_token\x18\x01 \x01(\x0c\x12%\n\x19previous_manager_identity\x18\x02 \x01(\tB\x02\x18\x01"E\n\x1bGetCurrentDeploymentRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bseries_name\x18\x02 \x01(\t"k\n\x1cGetCurrentDeploymentResponse\x12K\n\x17\x63urrent_deployment_info\x18\x01 \x01(\x0b\x32*.temporal.api.deployment.v1.DeploymentInfo"q\n GetDeploymentReachabilityRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12:\n\ndeployment\x18\x02 \x01(\x0b\x32&.temporal.api.deployment.v1.Deployment"\xe3\x01\n!GetDeploymentReachabilityResponse\x12\x43\n\x0f\x64\x65ployment_info\x18\x01 \x01(\x0b\x32*.temporal.api.deployment.v1.DeploymentInfo\x12\x43\n\x0creachability\x18\x02 \x01(\x0e\x32-.temporal.api.enums.v1.DeploymentReachability\x12\x34\n\x10last_update_time\x18\x03 \x01(\x0b\x32\x1a.google.protobuf.Timestamp"\xb4\x01\n\x19\x43reateWorkflowRuleRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x35\n\x04spec\x18\x02 \x01(\x0b\x32\'.temporal.api.rules.v1.WorkflowRuleSpec\x12\x12\n\nforce_scan\x18\x03 \x01(\x08\x12\x12\n\nrequest_id\x18\x04 \x01(\t\x12\x10\n\x08identity\x18\x05 \x01(\t\x12\x13\n\x0b\x64\x65scription\x18\x06 \x01(\t"_\n\x1a\x43reateWorkflowRuleResponse\x12\x31\n\x04rule\x18\x01 \x01(\x0b\x32#.temporal.api.rules.v1.WorkflowRule\x12\x0e\n\x06job_id\x18\x02 \x01(\t"A\n\x1b\x44\x65scribeWorkflowRuleRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x0f\n\x07rule_id\x18\x02 \x01(\t"Q\n\x1c\x44\x65scribeWorkflowRuleResponse\x12\x31\n\x04rule\x18\x01 \x01(\x0b\x32#.temporal.api.rules.v1.WorkflowRule"?\n\x19\x44\x65leteWorkflowRuleRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x0f\n\x07rule_id\x18\x02 \x01(\t"\x1c\n\x1a\x44\x65leteWorkflowRuleResponse"F\n\x18ListWorkflowRulesRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c"h\n\x19ListWorkflowRulesResponse\x12\x32\n\x05rules\x18\x01 \x03(\x0b\x32#.temporal.api.rules.v1.WorkflowRule\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c"\xce\x01\n\x1aTriggerWorkflowRuleRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12<\n\texecution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x0c\n\x02id\x18\x04 \x01(\tH\x00\x12\x37\n\x04spec\x18\x05 \x01(\x0b\x32\'.temporal.api.rules.v1.WorkflowRuleSpecH\x00\x12\x10\n\x08identity\x18\x03 \x01(\tB\x06\n\x04rule".\n\x1bTriggerWorkflowRuleResponse\x12\x0f\n\x07\x61pplied\x18\x01 \x01(\x08"\x9b\x01\n\x1cRecordWorkerHeartbeatRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x10\n\x08identity\x18\x02 \x01(\t\x12\x41\n\x10worker_heartbeat\x18\x03 \x03(\x0b\x32\'.temporal.api.worker.v1.WorkerHeartbeat\x12\x13\n\x0bresource_id\x18\x04 \x01(\t"\x1f\n\x1dRecordWorkerHeartbeatResponse"\x82\x01\n\x12ListWorkersRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x11\n\tpage_size\x18\x02 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c\x12\r\n\x05query\x18\x04 \x01(\t\x12\x1e\n\x16include_system_workers\x18\x05 \x01(\x08"\xa5\x01\n\x13ListWorkersResponse\x12<\n\x0cworkers_info\x18\x01 \x03(\x0b\x32".temporal.api.worker.v1.WorkerInfoB\x02\x18\x01\x12\x37\n\x07workers\x18\x03 \x03(\x0b\x32&.temporal.api.worker.v1.WorkerListInfo\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c"\xd5\x05\n\x1cUpdateTaskQueueConfigRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x10\n\x08identity\x18\x02 \x01(\t\x12\x12\n\ntask_queue\x18\x03 \x01(\t\x12=\n\x0ftask_queue_type\x18\x04 \x01(\x0e\x32$.temporal.api.enums.v1.TaskQueueType\x12n\n\x17update_queue_rate_limit\x18\x05 \x01(\x0b\x32M.temporal.api.workflowservice.v1.UpdateTaskQueueConfigRequest.RateLimitUpdate\x12}\n&update_fairness_key_rate_limit_default\x18\x06 \x01(\x0b\x32M.temporal.api.workflowservice.v1.UpdateTaskQueueConfigRequest.RateLimitUpdate\x12\x84\x01\n\x1dset_fairness_weight_overrides\x18\x07 \x03(\x0b\x32].temporal.api.workflowservice.v1.UpdateTaskQueueConfigRequest.SetFairnessWeightOverridesEntry\x12\'\n\x1funset_fairness_weight_overrides\x18\x08 \x03(\t\x1a[\n\x0fRateLimitUpdate\x12\x38\n\nrate_limit\x18\x01 \x01(\x0b\x32$.temporal.api.taskqueue.v1.RateLimit\x12\x0e\n\x06reason\x18\x02 \x01(\t\x1a\x41\n\x1fSetFairnessWeightOverridesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\x02:\x02\x38\x01"[\n\x1dUpdateTaskQueueConfigResponse\x12:\n\x06\x63onfig\x18\x01 \x01(\x0b\x32*.temporal.api.taskqueue.v1.TaskQueueConfig"\x9e\x01\n\x18\x46\x65tchWorkerConfigRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x10\n\x08identity\x18\x02 \x01(\t\x12\x0e\n\x06reason\x18\x03 \x01(\t\x12\x38\n\x08selector\x18\x06 \x01(\x0b\x32&.temporal.api.common.v1.WorkerSelector\x12\x13\n\x0bresource_id\x18\x07 \x01(\t"U\n\x19\x46\x65tchWorkerConfigResponse\x12\x38\n\rworker_config\x18\x01 \x01(\x0b\x32!.temporal.api.sdk.v1.WorkerConfig"\x8a\x02\n\x19UpdateWorkerConfigRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x10\n\x08identity\x18\x02 \x01(\t\x12\x0e\n\x06reason\x18\x03 \x01(\t\x12\x38\n\rworker_config\x18\x04 \x01(\x0b\x32!.temporal.api.sdk.v1.WorkerConfig\x12/\n\x0bupdate_mask\x18\x05 \x01(\x0b\x32\x1a.google.protobuf.FieldMask\x12\x38\n\x08selector\x18\x06 \x01(\x0b\x32&.temporal.api.common.v1.WorkerSelector\x12\x13\n\x0bresource_id\x18\x07 \x01(\t"d\n\x1aUpdateWorkerConfigResponse\x12:\n\rworker_config\x18\x01 \x01(\x0b\x32!.temporal.api.sdk.v1.WorkerConfigH\x00\x42\n\n\x08response"G\n\x15\x44\x65scribeWorkerRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x1b\n\x13worker_instance_key\x18\x02 \x01(\t"Q\n\x16\x44\x65scribeWorkerResponse\x12\x37\n\x0bworker_info\x18\x01 \x01(\x0b\x32".temporal.api.worker.v1.WorkerInfo"\x8d\x01\n\x1dPauseWorkflowExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x12\x10\n\x08identity\x18\x04 \x01(\t\x12\x0e\n\x06reason\x18\x05 \x01(\t\x12\x12\n\nrequest_id\x18\x06 \x01(\t" \n\x1ePauseWorkflowExecutionResponse"\x8f\x01\n\x1fUnpauseWorkflowExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x12\x10\n\x08identity\x18\x04 \x01(\t\x12\x0e\n\x06reason\x18\x05 \x01(\t\x12\x12\n\nrequest_id\x18\x06 \x01(\t""\n UnpauseWorkflowExecutionResponse"\x99\t\n\x1dStartActivityExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x10\n\x08identity\x18\x02 \x01(\t\x12\x12\n\nrequest_id\x18\x03 \x01(\t\x12\x13\n\x0b\x61\x63tivity_id\x18\x04 \x01(\t\x12;\n\ractivity_type\x18\x05 \x01(\x0b\x32$.temporal.api.common.v1.ActivityType\x12\x38\n\ntask_queue\x18\x06 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12<\n\x19schedule_to_close_timeout\x18\x07 \x01(\x0b\x32\x19.google.protobuf.Duration\x12<\n\x19schedule_to_start_timeout\x18\x08 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x39\n\x16start_to_close_timeout\x18\t \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x34\n\x11heartbeat_timeout\x18\n \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x39\n\x0cretry_policy\x18\x0b \x01(\x0b\x32#.temporal.api.common.v1.RetryPolicy\x12/\n\x05input\x18\x0c \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x45\n\x0fid_reuse_policy\x18\r \x01(\x0e\x32,.temporal.api.enums.v1.ActivityIdReusePolicy\x12K\n\x12id_conflict_policy\x18\x0e \x01(\x0e\x32/.temporal.api.enums.v1.ActivityIdConflictPolicy\x12\x43\n\x11search_attributes\x18\x0f \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes\x12.\n\x06header\x18\x10 \x01(\x0b\x32\x1e.temporal.api.common.v1.Header\x12\x38\n\ruser_metadata\x18\x11 \x01(\x0b\x32!.temporal.api.sdk.v1.UserMetadata\x12\x32\n\x08priority\x18\x12 \x01(\x0b\x32 .temporal.api.common.v1.Priority\x12>\n\x14\x63ompletion_callbacks\x18\x13 \x03(\x0b\x32 .temporal.api.common.v1.Callback\x12+\n\x05links\x18\x14 \x03(\x0b\x32\x1c.temporal.api.common.v1.Link\x12\x46\n\x13on_conflict_options\x18\x15 \x01(\x0b\x32).temporal.api.common.v1.OnConflictOptions\x12.\n\x0bstart_delay\x18\x16 \x01(\x0b\x32\x19.google.protobuf.Duration"m\n\x1eStartActivityExecutionResponse\x12\x0e\n\x06run_id\x18\x01 \x01(\t\x12\x0f\n\x07started\x18\x02 \x01(\x08\x12*\n\x04link\x18\x03 \x01(\x0b\x32\x1c.temporal.api.common.v1.Link"\xa3\x01\n DescribeActivityExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0b\x61\x63tivity_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x12\x15\n\rinclude_input\x18\x04 \x01(\x08\x12\x17\n\x0finclude_outcome\x18\x05 \x01(\x08\x12\x17\n\x0flong_poll_token\x18\x06 \x01(\x0c"\xbc\x02\n!DescribeActivityExecutionResponse\x12\x0e\n\x06run_id\x18\x01 \x01(\t\x12=\n\x04info\x18\x02 \x01(\x0b\x32/.temporal.api.activity.v1.ActivityExecutionInfo\x12/\n\x05input\x18\x03 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x43\n\x07outcome\x18\x04 \x01(\x0b\x32\x32.temporal.api.activity.v1.ActivityExecutionOutcome\x12\x17\n\x0flong_poll_token\x18\x05 \x01(\x0c\x12\x39\n\tcallbacks\x18\x06 \x03(\x0b\x32&.temporal.api.activity.v1.CallbackInfo"V\n\x1cPollActivityExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0b\x61\x63tivity_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t"t\n\x1dPollActivityExecutionResponse\x12\x0e\n\x06run_id\x18\x01 \x01(\t\x12\x43\n\x07outcome\x18\x02 \x01(\x0b\x32\x32.temporal.api.activity.v1.ActivityExecutionOutcome"m\n\x1dListActivityExecutionsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x11\n\tpage_size\x18\x02 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c\x12\r\n\x05query\x18\x04 \x01(\t"\x82\x01\n\x1eListActivityExecutionsResponse\x12G\n\nexecutions\x18\x01 \x03(\x0b\x32\x33.temporal.api.activity.v1.ActivityExecutionListInfo\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c"\xd1\x06\n#StartNexusOperationExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x10\n\x08identity\x18\x02 \x01(\t\x12\x12\n\nrequest_id\x18\x03 \x01(\t\x12\x14\n\x0coperation_id\x18\x04 \x01(\t\x12\x10\n\x08\x65ndpoint\x18\x05 \x01(\t\x12\x0f\n\x07service\x18\x06 \x01(\t\x12\x11\n\toperation\x18\x07 \x01(\t\x12<\n\x19schedule_to_close_timeout\x18\x08 \x01(\x0b\x32\x19.google.protobuf.Duration\x12<\n\x19schedule_to_start_timeout\x18\t \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x39\n\x16start_to_close_timeout\x18\n \x01(\x0b\x32\x19.google.protobuf.Duration\x12.\n\x05input\x18\x0b \x01(\x0b\x32\x1f.temporal.api.common.v1.Payload\x12K\n\x0fid_reuse_policy\x18\x0c \x01(\x0e\x32\x32.temporal.api.enums.v1.NexusOperationIdReusePolicy\x12Q\n\x12id_conflict_policy\x18\r \x01(\x0e\x32\x35.temporal.api.enums.v1.NexusOperationIdConflictPolicy\x12\x43\n\x11search_attributes\x18\x0e \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes\x12k\n\x0cnexus_header\x18\x0f \x03(\x0b\x32U.temporal.api.workflowservice.v1.StartNexusOperationExecutionRequest.NexusHeaderEntry\x12\x38\n\ruser_metadata\x18\x10 \x01(\x0b\x32!.temporal.api.sdk.v1.UserMetadata\x1a\x32\n\x10NexusHeaderEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01"G\n$StartNexusOperationExecutionResponse\x12\x0e\n\x06run_id\x18\x01 \x01(\t\x12\x0f\n\x07started\x18\x02 \x01(\x08"\xaa\x01\n&DescribeNexusOperationExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x14\n\x0coperation_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x12\x15\n\rinclude_input\x18\x04 \x01(\x08\x12\x17\n\x0finclude_outcome\x18\x05 \x01(\x08\x12\x17\n\x0flong_poll_token\x18\x06 \x01(\x0c"\xb7\x02\n\'DescribeNexusOperationExecutionResponse\x12\x0e\n\x06run_id\x18\x01 \x01(\t\x12@\n\x04info\x18\x02 \x01(\x0b\x32\x32.temporal.api.nexus.v1.NexusOperationExecutionInfo\x12.\n\x05input\x18\x03 \x01(\x0b\x32\x1f.temporal.api.common.v1.Payload\x12\x31\n\x06result\x18\x04 \x01(\x0b\x32\x1f.temporal.api.common.v1.PayloadH\x00\x12\x33\n\x07\x66\x61ilure\x18\x05 \x01(\x0b\x32 .temporal.api.failure.v1.FailureH\x00\x12\x17\n\x0flong_poll_token\x18\x06 \x01(\x0c\x42\t\n\x07outcome"\xa1\x01\n"PollNexusOperationExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x14\n\x0coperation_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x12\x42\n\nwait_stage\x18\x04 \x01(\x0e\x32..temporal.api.enums.v1.NexusOperationWaitStage"\x85\x02\n#PollNexusOperationExecutionResponse\x12\x0e\n\x06run_id\x18\x01 \x01(\t\x12\x42\n\nwait_stage\x18\x02 \x01(\x0e\x32..temporal.api.enums.v1.NexusOperationWaitStage\x12\x17\n\x0foperation_token\x18\x03 \x01(\t\x12\x31\n\x06result\x18\x04 \x01(\x0b\x32\x1f.temporal.api.common.v1.PayloadH\x00\x12\x33\n\x07\x66\x61ilure\x18\x05 \x01(\x0b\x32 .temporal.api.failure.v1.FailureH\x00\x42\t\n\x07outcome"s\n#ListNexusOperationExecutionsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x11\n\tpage_size\x18\x02 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c\x12\r\n\x05query\x18\x04 \x01(\t"\x8b\x01\n$ListNexusOperationExecutionsResponse\x12J\n\noperations\x18\x01 \x03(\x0b\x32\x36.temporal.api.nexus.v1.NexusOperationExecutionListInfo\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c"B\n\x1e\x43ountActivityExecutionsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\r\n\x05query\x18\x02 \x01(\t"\xed\x01\n\x1f\x43ountActivityExecutionsResponse\x12\r\n\x05\x63ount\x18\x01 \x01(\x03\x12\x61\n\x06groups\x18\x02 \x03(\x0b\x32Q.temporal.api.workflowservice.v1.CountActivityExecutionsResponse.AggregationGroup\x1aX\n\x10\x41ggregationGroup\x12\x35\n\x0cgroup_values\x18\x01 \x03(\x0b\x32\x1f.temporal.api.common.v1.Payload\x12\r\n\x05\x63ount\x18\x02 \x01(\x03"H\n$CountNexusOperationExecutionsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\r\n\x05query\x18\x02 \x01(\t"\xf9\x01\n%CountNexusOperationExecutionsResponse\x12\r\n\x05\x63ount\x18\x01 \x01(\x03\x12g\n\x06groups\x18\x02 \x03(\x0b\x32W.temporal.api.workflowservice.v1.CountNexusOperationExecutionsResponse.AggregationGroup\x1aX\n\x10\x41ggregationGroup\x12\x35\n\x0cgroup_values\x18\x01 \x03(\x0b\x32\x1f.temporal.api.common.v1.Payload\x12\r\n\x05\x63ount\x18\x02 \x01(\x03"\x95\x01\n%RequestCancelActivityExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0b\x61\x63tivity_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x12\x10\n\x08identity\x18\x04 \x01(\t\x12\x12\n\nrequest_id\x18\x05 \x01(\t\x12\x0e\n\x06reason\x18\x06 \x01(\t"(\n&RequestCancelActivityExecutionResponse"\x91\x01\n!TerminateActivityExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0b\x61\x63tivity_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x12\x10\n\x08identity\x18\x04 \x01(\t\x12\x12\n\nrequest_id\x18\x05 \x01(\t\x12\x0e\n\x06reason\x18\x06 \x01(\t"$\n"TerminateActivityExecutionResponse"X\n\x1e\x44\x65leteActivityExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0b\x61\x63tivity_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t"!\n\x1f\x44\x65leteActivityExecutionResponse"\x9c\x01\n+RequestCancelNexusOperationExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x14\n\x0coperation_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x12\x10\n\x08identity\x18\x04 \x01(\t\x12\x12\n\nrequest_id\x18\x05 \x01(\t\x12\x0e\n\x06reason\x18\x06 \x01(\t".\n,RequestCancelNexusOperationExecutionResponse"\x98\x01\n\'TerminateNexusOperationExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x14\n\x0coperation_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x12\x10\n\x08identity\x18\x04 \x01(\t\x12\x12\n\nrequest_id\x18\x05 \x01(\t\x12\x0e\n\x06reason\x18\x06 \x01(\t"*\n(TerminateNexusOperationExecutionResponse"_\n$DeleteNexusOperationExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x14\n\x0coperation_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t"\'\n%DeleteNexusOperationExecutionResponseB\xbe\x01\n"io.temporal.api.workflowservice.v1B\x14RequestResponseProtoP\x01Z5go.temporal.io/api/workflowservice/v1;workflowservice\xaa\x02!Temporalio.Api.WorkflowService.V1\xea\x02$Temporalio::Api::WorkflowService::V1b\x06proto3' ) @@ -550,15 +550,39 @@ _UPDATEACTIVITYOPTIONSREQUEST = DESCRIPTOR.message_types_by_name[ "UpdateActivityOptionsRequest" ] +_UPDATEACTIVITYEXECUTIONOPTIONSREQUEST = DESCRIPTOR.message_types_by_name[ + "UpdateActivityExecutionOptionsRequest" +] _UPDATEACTIVITYOPTIONSRESPONSE = DESCRIPTOR.message_types_by_name[ "UpdateActivityOptionsResponse" ] +_UPDATEACTIVITYEXECUTIONOPTIONSRESPONSE = DESCRIPTOR.message_types_by_name[ + "UpdateActivityExecutionOptionsResponse" +] _PAUSEACTIVITYREQUEST = DESCRIPTOR.message_types_by_name["PauseActivityRequest"] +_PAUSEACTIVITYEXECUTIONREQUEST = DESCRIPTOR.message_types_by_name[ + "PauseActivityExecutionRequest" +] _PAUSEACTIVITYRESPONSE = DESCRIPTOR.message_types_by_name["PauseActivityResponse"] +_PAUSEACTIVITYEXECUTIONRESPONSE = DESCRIPTOR.message_types_by_name[ + "PauseActivityExecutionResponse" +] _UNPAUSEACTIVITYREQUEST = DESCRIPTOR.message_types_by_name["UnpauseActivityRequest"] +_UNPAUSEACTIVITYEXECUTIONREQUEST = DESCRIPTOR.message_types_by_name[ + "UnpauseActivityExecutionRequest" +] _UNPAUSEACTIVITYRESPONSE = DESCRIPTOR.message_types_by_name["UnpauseActivityResponse"] +_UNPAUSEACTIVITYEXECUTIONRESPONSE = DESCRIPTOR.message_types_by_name[ + "UnpauseActivityExecutionResponse" +] _RESETACTIVITYREQUEST = DESCRIPTOR.message_types_by_name["ResetActivityRequest"] +_RESETACTIVITYEXECUTIONREQUEST = DESCRIPTOR.message_types_by_name[ + "ResetActivityExecutionRequest" +] _RESETACTIVITYRESPONSE = DESCRIPTOR.message_types_by_name["ResetActivityResponse"] +_RESETACTIVITYEXECUTIONRESPONSE = DESCRIPTOR.message_types_by_name[ + "ResetActivityExecutionResponse" +] _UPDATEWORKFLOWEXECUTIONOPTIONSREQUEST = DESCRIPTOR.message_types_by_name[ "UpdateWorkflowExecutionOptionsRequest" ] @@ -2553,6 +2577,17 @@ ) _sym_db.RegisterMessage(UpdateActivityOptionsRequest) +UpdateActivityExecutionOptionsRequest = _reflection.GeneratedProtocolMessageType( + "UpdateActivityExecutionOptionsRequest", + (_message.Message,), + { + "DESCRIPTOR": _UPDATEACTIVITYEXECUTIONOPTIONSREQUEST, + "__module__": "temporalio.api.workflowservice.v1.request_response_pb2", + # @@protoc_insertion_point(class_scope:temporal.api.workflowservice.v1.UpdateActivityExecutionOptionsRequest) + }, +) +_sym_db.RegisterMessage(UpdateActivityExecutionOptionsRequest) + UpdateActivityOptionsResponse = _reflection.GeneratedProtocolMessageType( "UpdateActivityOptionsResponse", (_message.Message,), @@ -2564,6 +2599,17 @@ ) _sym_db.RegisterMessage(UpdateActivityOptionsResponse) +UpdateActivityExecutionOptionsResponse = _reflection.GeneratedProtocolMessageType( + "UpdateActivityExecutionOptionsResponse", + (_message.Message,), + { + "DESCRIPTOR": _UPDATEACTIVITYEXECUTIONOPTIONSRESPONSE, + "__module__": "temporalio.api.workflowservice.v1.request_response_pb2", + # @@protoc_insertion_point(class_scope:temporal.api.workflowservice.v1.UpdateActivityExecutionOptionsResponse) + }, +) +_sym_db.RegisterMessage(UpdateActivityExecutionOptionsResponse) + PauseActivityRequest = _reflection.GeneratedProtocolMessageType( "PauseActivityRequest", (_message.Message,), @@ -2575,6 +2621,17 @@ ) _sym_db.RegisterMessage(PauseActivityRequest) +PauseActivityExecutionRequest = _reflection.GeneratedProtocolMessageType( + "PauseActivityExecutionRequest", + (_message.Message,), + { + "DESCRIPTOR": _PAUSEACTIVITYEXECUTIONREQUEST, + "__module__": "temporalio.api.workflowservice.v1.request_response_pb2", + # @@protoc_insertion_point(class_scope:temporal.api.workflowservice.v1.PauseActivityExecutionRequest) + }, +) +_sym_db.RegisterMessage(PauseActivityExecutionRequest) + PauseActivityResponse = _reflection.GeneratedProtocolMessageType( "PauseActivityResponse", (_message.Message,), @@ -2586,6 +2643,17 @@ ) _sym_db.RegisterMessage(PauseActivityResponse) +PauseActivityExecutionResponse = _reflection.GeneratedProtocolMessageType( + "PauseActivityExecutionResponse", + (_message.Message,), + { + "DESCRIPTOR": _PAUSEACTIVITYEXECUTIONRESPONSE, + "__module__": "temporalio.api.workflowservice.v1.request_response_pb2", + # @@protoc_insertion_point(class_scope:temporal.api.workflowservice.v1.PauseActivityExecutionResponse) + }, +) +_sym_db.RegisterMessage(PauseActivityExecutionResponse) + UnpauseActivityRequest = _reflection.GeneratedProtocolMessageType( "UnpauseActivityRequest", (_message.Message,), @@ -2597,6 +2665,17 @@ ) _sym_db.RegisterMessage(UnpauseActivityRequest) +UnpauseActivityExecutionRequest = _reflection.GeneratedProtocolMessageType( + "UnpauseActivityExecutionRequest", + (_message.Message,), + { + "DESCRIPTOR": _UNPAUSEACTIVITYEXECUTIONREQUEST, + "__module__": "temporalio.api.workflowservice.v1.request_response_pb2", + # @@protoc_insertion_point(class_scope:temporal.api.workflowservice.v1.UnpauseActivityExecutionRequest) + }, +) +_sym_db.RegisterMessage(UnpauseActivityExecutionRequest) + UnpauseActivityResponse = _reflection.GeneratedProtocolMessageType( "UnpauseActivityResponse", (_message.Message,), @@ -2608,6 +2687,17 @@ ) _sym_db.RegisterMessage(UnpauseActivityResponse) +UnpauseActivityExecutionResponse = _reflection.GeneratedProtocolMessageType( + "UnpauseActivityExecutionResponse", + (_message.Message,), + { + "DESCRIPTOR": _UNPAUSEACTIVITYEXECUTIONRESPONSE, + "__module__": "temporalio.api.workflowservice.v1.request_response_pb2", + # @@protoc_insertion_point(class_scope:temporal.api.workflowservice.v1.UnpauseActivityExecutionResponse) + }, +) +_sym_db.RegisterMessage(UnpauseActivityExecutionResponse) + ResetActivityRequest = _reflection.GeneratedProtocolMessageType( "ResetActivityRequest", (_message.Message,), @@ -2619,6 +2709,17 @@ ) _sym_db.RegisterMessage(ResetActivityRequest) +ResetActivityExecutionRequest = _reflection.GeneratedProtocolMessageType( + "ResetActivityExecutionRequest", + (_message.Message,), + { + "DESCRIPTOR": _RESETACTIVITYEXECUTIONREQUEST, + "__module__": "temporalio.api.workflowservice.v1.request_response_pb2", + # @@protoc_insertion_point(class_scope:temporal.api.workflowservice.v1.ResetActivityExecutionRequest) + }, +) +_sym_db.RegisterMessage(ResetActivityExecutionRequest) + ResetActivityResponse = _reflection.GeneratedProtocolMessageType( "ResetActivityResponse", (_message.Message,), @@ -2630,6 +2731,17 @@ ) _sym_db.RegisterMessage(ResetActivityResponse) +ResetActivityExecutionResponse = _reflection.GeneratedProtocolMessageType( + "ResetActivityExecutionResponse", + (_message.Message,), + { + "DESCRIPTOR": _RESETACTIVITYEXECUTIONRESPONSE, + "__module__": "temporalio.api.workflowservice.v1.request_response_pb2", + # @@protoc_insertion_point(class_scope:temporal.api.workflowservice.v1.ResetActivityExecutionResponse) + }, +) +_sym_db.RegisterMessage(ResetActivityExecutionResponse) + UpdateWorkflowExecutionOptionsRequest = _reflection.GeneratedProtocolMessageType( "UpdateWorkflowExecutionOptionsRequest", (_message.Message,), @@ -4038,543 +4150,559 @@ _LISTNAMESPACESRESPONSE._serialized_start = 2423 _LISTNAMESPACESRESPONSE._serialized_end = 2552 _DESCRIBENAMESPACEREQUEST._serialized_start = 2554 - _DESCRIBENAMESPACEREQUEST._serialized_end = 2611 - _DESCRIBENAMESPACERESPONSE._serialized_start = 2614 - _DESCRIBENAMESPACERESPONSE._serialized_end = 2978 - _UPDATENAMESPACEREQUEST._serialized_start = 2981 - _UPDATENAMESPACEREQUEST._serialized_end = 3316 - _UPDATENAMESPACERESPONSE._serialized_start = 3319 - _UPDATENAMESPACERESPONSE._serialized_end = 3610 - _DEPRECATENAMESPACEREQUEST._serialized_start = 3612 - _DEPRECATENAMESPACEREQUEST._serialized_end = 3682 - _DEPRECATENAMESPACERESPONSE._serialized_start = 3684 - _DEPRECATENAMESPACERESPONSE._serialized_end = 3712 - _STARTWORKFLOWEXECUTIONREQUEST._serialized_start = 3715 - _STARTWORKFLOWEXECUTIONREQUEST._serialized_end = 5334 - _STARTWORKFLOWEXECUTIONRESPONSE._serialized_start = 5337 - _STARTWORKFLOWEXECUTIONRESPONSE._serialized_end = 5603 - _GETWORKFLOWEXECUTIONHISTORYREQUEST._serialized_start = 5606 - _GETWORKFLOWEXECUTIONHISTORYREQUEST._serialized_end = 5904 - _GETWORKFLOWEXECUTIONHISTORYRESPONSE._serialized_start = 5907 - _GETWORKFLOWEXECUTIONHISTORYRESPONSE._serialized_end = 6093 - _GETWORKFLOWEXECUTIONHISTORYREVERSEREQUEST._serialized_start = 6096 - _GETWORKFLOWEXECUTIONHISTORYREVERSEREQUEST._serialized_end = 6272 - _GETWORKFLOWEXECUTIONHISTORYREVERSERESPONSE._serialized_start = 6274 - _GETWORKFLOWEXECUTIONHISTORYREVERSERESPONSE._serialized_end = 6394 - _POLLWORKFLOWTASKQUEUEREQUEST._serialized_start = 6397 - _POLLWORKFLOWTASKQUEUEREQUEST._serialized_end = 6837 - _POLLWORKFLOWTASKQUEUERESPONSE._serialized_start = 6840 - _POLLWORKFLOWTASKQUEUERESPONSE._serialized_end = 7850 - _POLLWORKFLOWTASKQUEUERESPONSE_QUERIESENTRY._serialized_start = 7766 - _POLLWORKFLOWTASKQUEUERESPONSE_QUERIESENTRY._serialized_end = 7850 - _RESPONDWORKFLOWTASKCOMPLETEDREQUEST._serialized_start = 7853 - _RESPONDWORKFLOWTASKCOMPLETEDREQUEST._serialized_end = 9143 - _RESPONDWORKFLOWTASKCOMPLETEDREQUEST_QUERYRESULTSENTRY._serialized_start = 8977 - _RESPONDWORKFLOWTASKCOMPLETEDREQUEST_QUERYRESULTSENTRY._serialized_end = 9072 - _RESPONDWORKFLOWTASKCOMPLETEDREQUEST_CAPABILITIES._serialized_start = 9074 - _RESPONDWORKFLOWTASKCOMPLETEDREQUEST_CAPABILITIES._serialized_end = 9143 - _RESPONDWORKFLOWTASKCOMPLETEDRESPONSE._serialized_start = 9146 - _RESPONDWORKFLOWTASKCOMPLETEDRESPONSE._serialized_end = 9391 - _RESPONDWORKFLOWTASKFAILEDREQUEST._serialized_start = 9394 - _RESPONDWORKFLOWTASKFAILEDREQUEST._serialized_end = 9919 - _RESPONDWORKFLOWTASKFAILEDRESPONSE._serialized_start = 9921 - _RESPONDWORKFLOWTASKFAILEDRESPONSE._serialized_end = 9956 - _POLLACTIVITYTASKQUEUEREQUEST._serialized_start = 9959 - _POLLACTIVITYTASKQUEUEREQUEST._serialized_end = 10445 - _POLLACTIVITYTASKQUEUERESPONSE._serialized_start = 10448 - _POLLACTIVITYTASKQUEUERESPONSE._serialized_end = 11552 - _RECORDACTIVITYTASKHEARTBEATREQUEST._serialized_start = 11555 - _RECORDACTIVITYTASKHEARTBEATREQUEST._serialized_end = 11720 - _RECORDACTIVITYTASKHEARTBEATRESPONSE._serialized_start = 11722 - _RECORDACTIVITYTASKHEARTBEATRESPONSE._serialized_end = 11834 - _RECORDACTIVITYTASKHEARTBEATBYIDREQUEST._serialized_start = 11837 - _RECORDACTIVITYTASKHEARTBEATBYIDREQUEST._serialized_end = 12044 - _RECORDACTIVITYTASKHEARTBEATBYIDRESPONSE._serialized_start = 12046 - _RECORDACTIVITYTASKHEARTBEATBYIDRESPONSE._serialized_end = 12162 - _RESPONDACTIVITYTASKCOMPLETEDREQUEST._serialized_start = 12165 - _RESPONDACTIVITYTASKCOMPLETEDREQUEST._serialized_end = 12547 - _RESPONDACTIVITYTASKCOMPLETEDRESPONSE._serialized_start = 12549 - _RESPONDACTIVITYTASKCOMPLETEDRESPONSE._serialized_end = 12587 - _RESPONDACTIVITYTASKCOMPLETEDBYIDREQUEST._serialized_start = 12590 - _RESPONDACTIVITYTASKCOMPLETEDBYIDREQUEST._serialized_end = 12797 - _RESPONDACTIVITYTASKCOMPLETEDBYIDRESPONSE._serialized_start = 12799 - _RESPONDACTIVITYTASKCOMPLETEDBYIDRESPONSE._serialized_end = 12841 - _RESPONDACTIVITYTASKFAILEDREQUEST._serialized_start = 12844 - _RESPONDACTIVITYTASKFAILEDREQUEST._serialized_end = 13290 - _RESPONDACTIVITYTASKFAILEDRESPONSE._serialized_start = 13292 - _RESPONDACTIVITYTASKFAILEDRESPONSE._serialized_end = 13379 - _RESPONDACTIVITYTASKFAILEDBYIDREQUEST._serialized_start = 13382 - _RESPONDACTIVITYTASKFAILEDBYIDREQUEST._serialized_end = 13653 - _RESPONDACTIVITYTASKFAILEDBYIDRESPONSE._serialized_start = 13655 - _RESPONDACTIVITYTASKFAILEDBYIDRESPONSE._serialized_end = 13746 - _RESPONDACTIVITYTASKCANCELEDREQUEST._serialized_start = 13749 - _RESPONDACTIVITYTASKCANCELEDREQUEST._serialized_end = 14131 - _RESPONDACTIVITYTASKCANCELEDRESPONSE._serialized_start = 14133 - _RESPONDACTIVITYTASKCANCELEDRESPONSE._serialized_end = 14170 - _RESPONDACTIVITYTASKCANCELEDBYIDREQUEST._serialized_start = 14173 - _RESPONDACTIVITYTASKCANCELEDBYIDREQUEST._serialized_end = 14461 - _RESPONDACTIVITYTASKCANCELEDBYIDRESPONSE._serialized_start = 14463 - _RESPONDACTIVITYTASKCANCELEDBYIDRESPONSE._serialized_end = 14504 - _REQUESTCANCELWORKFLOWEXECUTIONREQUEST._serialized_start = 14507 - _REQUESTCANCELWORKFLOWEXECUTIONREQUEST._serialized_end = 14767 - _REQUESTCANCELWORKFLOWEXECUTIONRESPONSE._serialized_start = 14769 - _REQUESTCANCELWORKFLOWEXECUTIONRESPONSE._serialized_end = 14809 - _SIGNALWORKFLOWEXECUTIONREQUEST._serialized_start = 14812 - _SIGNALWORKFLOWEXECUTIONREQUEST._serialized_end = 15162 - _SIGNALWORKFLOWEXECUTIONRESPONSE._serialized_start = 15164 - _SIGNALWORKFLOWEXECUTIONRESPONSE._serialized_end = 15241 - _SIGNALWITHSTARTWORKFLOWEXECUTIONREQUEST._serialized_start = 15244 - _SIGNALWITHSTARTWORKFLOWEXECUTIONREQUEST._serialized_end = 16585 - _SIGNALWITHSTARTWORKFLOWEXECUTIONRESPONSE._serialized_start = 16587 - _SIGNALWITHSTARTWORKFLOWEXECUTIONRESPONSE._serialized_end = 16713 - _RESETWORKFLOWEXECUTIONREQUEST._serialized_start = 16716 - _RESETWORKFLOWEXECUTIONREQUEST._serialized_end = 17165 - _RESETWORKFLOWEXECUTIONRESPONSE._serialized_start = 17167 - _RESETWORKFLOWEXECUTIONRESPONSE._serialized_end = 17215 - _TERMINATEWORKFLOWEXECUTIONREQUEST._serialized_start = 17218 - _TERMINATEWORKFLOWEXECUTIONREQUEST._serialized_end = 17505 - _TERMINATEWORKFLOWEXECUTIONRESPONSE._serialized_start = 17507 - _TERMINATEWORKFLOWEXECUTIONRESPONSE._serialized_end = 17543 - _DELETEWORKFLOWEXECUTIONREQUEST._serialized_start = 17545 - _DELETEWORKFLOWEXECUTIONREQUEST._serialized_end = 17667 - _DELETEWORKFLOWEXECUTIONRESPONSE._serialized_start = 17669 - _DELETEWORKFLOWEXECUTIONRESPONSE._serialized_end = 17702 - _LISTOPENWORKFLOWEXECUTIONSREQUEST._serialized_start = 17705 - _LISTOPENWORKFLOWEXECUTIONSREQUEST._serialized_end = 18034 - _LISTOPENWORKFLOWEXECUTIONSRESPONSE._serialized_start = 18037 - _LISTOPENWORKFLOWEXECUTIONSRESPONSE._serialized_end = 18167 - _LISTCLOSEDWORKFLOWEXECUTIONSREQUEST._serialized_start = 18170 - _LISTCLOSEDWORKFLOWEXECUTIONSREQUEST._serialized_end = 18564 - _LISTCLOSEDWORKFLOWEXECUTIONSRESPONSE._serialized_start = 18567 - _LISTCLOSEDWORKFLOWEXECUTIONSRESPONSE._serialized_end = 18699 - _LISTWORKFLOWEXECUTIONSREQUEST._serialized_start = 18701 - _LISTWORKFLOWEXECUTIONSREQUEST._serialized_end = 18810 - _LISTWORKFLOWEXECUTIONSRESPONSE._serialized_start = 18812 - _LISTWORKFLOWEXECUTIONSRESPONSE._serialized_end = 18938 - _LISTARCHIVEDWORKFLOWEXECUTIONSREQUEST._serialized_start = 18940 - _LISTARCHIVEDWORKFLOWEXECUTIONSREQUEST._serialized_end = 19057 - _LISTARCHIVEDWORKFLOWEXECUTIONSRESPONSE._serialized_start = 19060 - _LISTARCHIVEDWORKFLOWEXECUTIONSRESPONSE._serialized_end = 19194 - _SCANWORKFLOWEXECUTIONSREQUEST._serialized_start = 19196 - _SCANWORKFLOWEXECUTIONSREQUEST._serialized_end = 19305 - _SCANWORKFLOWEXECUTIONSRESPONSE._serialized_start = 19307 - _SCANWORKFLOWEXECUTIONSRESPONSE._serialized_end = 19433 - _COUNTWORKFLOWEXECUTIONSREQUEST._serialized_start = 19435 - _COUNTWORKFLOWEXECUTIONSREQUEST._serialized_end = 19501 - _COUNTWORKFLOWEXECUTIONSRESPONSE._serialized_start = 19504 - _COUNTWORKFLOWEXECUTIONSRESPONSE._serialized_end = 19741 - _COUNTWORKFLOWEXECUTIONSRESPONSE_AGGREGATIONGROUP._serialized_start = 19653 - _COUNTWORKFLOWEXECUTIONSRESPONSE_AGGREGATIONGROUP._serialized_end = 19741 - _GETSEARCHATTRIBUTESREQUEST._serialized_start = 19743 - _GETSEARCHATTRIBUTESREQUEST._serialized_end = 19771 - _GETSEARCHATTRIBUTESRESPONSE._serialized_start = 19774 - _GETSEARCHATTRIBUTESRESPONSE._serialized_end = 19975 - _GETSEARCHATTRIBUTESRESPONSE_KEYSENTRY._serialized_start = 19891 - _GETSEARCHATTRIBUTESRESPONSE_KEYSENTRY._serialized_end = 19975 - _RESPONDQUERYTASKCOMPLETEDREQUEST._serialized_start = 19978 - _RESPONDQUERYTASKCOMPLETEDREQUEST._serialized_end = 20339 - _RESPONDQUERYTASKCOMPLETEDRESPONSE._serialized_start = 20341 - _RESPONDQUERYTASKCOMPLETEDRESPONSE._serialized_end = 20376 - _RESETSTICKYTASKQUEUEREQUEST._serialized_start = 20378 - _RESETSTICKYTASKQUEUEREQUEST._serialized_end = 20488 - _RESETSTICKYTASKQUEUERESPONSE._serialized_start = 20490 - _RESETSTICKYTASKQUEUERESPONSE._serialized_end = 20520 - _SHUTDOWNWORKERREQUEST._serialized_start = 20523 - _SHUTDOWNWORKERREQUEST._serialized_end = 20806 - _SHUTDOWNWORKERRESPONSE._serialized_start = 20808 - _SHUTDOWNWORKERRESPONSE._serialized_end = 20832 - _QUERYWORKFLOWREQUEST._serialized_start = 20835 - _QUERYWORKFLOWREQUEST._serialized_end = 21068 - _QUERYWORKFLOWRESPONSE._serialized_start = 21071 - _QUERYWORKFLOWRESPONSE._serialized_end = 21212 - _DESCRIBEWORKFLOWEXECUTIONREQUEST._serialized_start = 21214 - _DESCRIBEWORKFLOWEXECUTIONREQUEST._serialized_end = 21329 - _DESCRIBEWORKFLOWEXECUTIONRESPONSE._serialized_start = 21332 - _DESCRIBEWORKFLOWEXECUTIONRESPONSE._serialized_end = 21997 - _DESCRIBETASKQUEUEREQUEST._serialized_start = 22000 - _DESCRIBETASKQUEUEREQUEST._serialized_end = 22528 - _DESCRIBETASKQUEUERESPONSE._serialized_start = 22531 - _DESCRIBETASKQUEUERESPONSE._serialized_end = 23535 - _DESCRIBETASKQUEUERESPONSE_STATSBYPRIORITYKEYENTRY._serialized_start = 23215 - _DESCRIBETASKQUEUERESPONSE_STATSBYPRIORITYKEYENTRY._serialized_end = 23315 - _DESCRIBETASKQUEUERESPONSE_EFFECTIVERATELIMIT._serialized_start = 23317 - _DESCRIBETASKQUEUERESPONSE_EFFECTIVERATELIMIT._serialized_end = 23433 - _DESCRIBETASKQUEUERESPONSE_VERSIONSINFOENTRY._serialized_start = 23435 - _DESCRIBETASKQUEUERESPONSE_VERSIONSINFOENTRY._serialized_end = 23535 - _GETCLUSTERINFOREQUEST._serialized_start = 23537 - _GETCLUSTERINFOREQUEST._serialized_end = 23560 - _GETCLUSTERINFORESPONSE._serialized_start = 23563 - _GETCLUSTERINFORESPONSE._serialized_end = 24028 - _GETCLUSTERINFORESPONSE_SUPPORTEDCLIENTSENTRY._serialized_start = 23973 - _GETCLUSTERINFORESPONSE_SUPPORTEDCLIENTSENTRY._serialized_end = 24028 - _GETSYSTEMINFOREQUEST._serialized_start = 24030 - _GETSYSTEMINFOREQUEST._serialized_end = 24052 - _GETSYSTEMINFORESPONSE._serialized_start = 24055 - _GETSYSTEMINFORESPONSE._serialized_end = 24590 - _GETSYSTEMINFORESPONSE_CAPABILITIES._serialized_start = 24196 - _GETSYSTEMINFORESPONSE_CAPABILITIES._serialized_end = 24590 - _LISTTASKQUEUEPARTITIONSREQUEST._serialized_start = 24592 - _LISTTASKQUEUEPARTITIONSREQUEST._serialized_end = 24701 - _LISTTASKQUEUEPARTITIONSRESPONSE._serialized_start = 24704 - _LISTTASKQUEUEPARTITIONSRESPONSE._serialized_end = 24927 - _CREATESCHEDULEREQUEST._serialized_start = 24930 - _CREATESCHEDULEREQUEST._serialized_end = 25262 - _CREATESCHEDULERESPONSE._serialized_start = 25264 - _CREATESCHEDULERESPONSE._serialized_end = 25312 - _DESCRIBESCHEDULEREQUEST._serialized_start = 25314 - _DESCRIBESCHEDULEREQUEST._serialized_end = 25379 - _DESCRIBESCHEDULERESPONSE._serialized_start = 25382 - _DESCRIBESCHEDULERESPONSE._serialized_end = 25653 - _UPDATESCHEDULEREQUEST._serialized_start = 25656 - _UPDATESCHEDULEREQUEST._serialized_end = 25948 - _UPDATESCHEDULERESPONSE._serialized_start = 25950 - _UPDATESCHEDULERESPONSE._serialized_end = 25974 - _PATCHSCHEDULEREQUEST._serialized_start = 25977 - _PATCHSCHEDULEREQUEST._serialized_end = 26133 - _PATCHSCHEDULERESPONSE._serialized_start = 26135 - _PATCHSCHEDULERESPONSE._serialized_end = 26158 - _LISTSCHEDULEMATCHINGTIMESREQUEST._serialized_start = 26161 - _LISTSCHEDULEMATCHINGTIMESREQUEST._serialized_end = 26329 - _LISTSCHEDULEMATCHINGTIMESRESPONSE._serialized_start = 26331 - _LISTSCHEDULEMATCHINGTIMESRESPONSE._serialized_end = 26414 - _DELETESCHEDULEREQUEST._serialized_start = 26416 - _DELETESCHEDULEREQUEST._serialized_end = 26497 - _DELETESCHEDULERESPONSE._serialized_start = 26499 - _DELETESCHEDULERESPONSE._serialized_end = 26523 - _LISTSCHEDULESREQUEST._serialized_start = 26525 - _LISTSCHEDULESREQUEST._serialized_end = 26633 - _LISTSCHEDULESRESPONSE._serialized_start = 26635 - _LISTSCHEDULESRESPONSE._serialized_end = 26747 - _COUNTSCHEDULESREQUEST._serialized_start = 26749 - _COUNTSCHEDULESREQUEST._serialized_end = 26806 - _COUNTSCHEDULESRESPONSE._serialized_start = 26809 - _COUNTSCHEDULESRESPONSE._serialized_end = 27028 - _COUNTSCHEDULESRESPONSE_AGGREGATIONGROUP._serialized_start = 19653 - _COUNTSCHEDULESRESPONSE_AGGREGATIONGROUP._serialized_end = 19741 - _UPDATEWORKERBUILDIDCOMPATIBILITYREQUEST._serialized_start = 27031 - _UPDATEWORKERBUILDIDCOMPATIBILITYREQUEST._serialized_end = 27677 - _UPDATEWORKERBUILDIDCOMPATIBILITYREQUEST_ADDNEWCOMPATIBLEVERSION._serialized_start = 27478 + _DESCRIBENAMESPACEREQUEST._serialized_end = 2637 + _DESCRIBENAMESPACERESPONSE._serialized_start = 2640 + _DESCRIBENAMESPACERESPONSE._serialized_end = 3004 + _UPDATENAMESPACEREQUEST._serialized_start = 3007 + _UPDATENAMESPACEREQUEST._serialized_end = 3342 + _UPDATENAMESPACERESPONSE._serialized_start = 3345 + _UPDATENAMESPACERESPONSE._serialized_end = 3636 + _DEPRECATENAMESPACEREQUEST._serialized_start = 3638 + _DEPRECATENAMESPACEREQUEST._serialized_end = 3708 + _DEPRECATENAMESPACERESPONSE._serialized_start = 3710 + _DEPRECATENAMESPACERESPONSE._serialized_end = 3738 + _STARTWORKFLOWEXECUTIONREQUEST._serialized_start = 3741 + _STARTWORKFLOWEXECUTIONREQUEST._serialized_end = 5360 + _STARTWORKFLOWEXECUTIONRESPONSE._serialized_start = 5363 + _STARTWORKFLOWEXECUTIONRESPONSE._serialized_end = 5629 + _GETWORKFLOWEXECUTIONHISTORYREQUEST._serialized_start = 5632 + _GETWORKFLOWEXECUTIONHISTORYREQUEST._serialized_end = 5930 + _GETWORKFLOWEXECUTIONHISTORYRESPONSE._serialized_start = 5933 + _GETWORKFLOWEXECUTIONHISTORYRESPONSE._serialized_end = 6119 + _GETWORKFLOWEXECUTIONHISTORYREVERSEREQUEST._serialized_start = 6122 + _GETWORKFLOWEXECUTIONHISTORYREVERSEREQUEST._serialized_end = 6298 + _GETWORKFLOWEXECUTIONHISTORYREVERSERESPONSE._serialized_start = 6300 + _GETWORKFLOWEXECUTIONHISTORYREVERSERESPONSE._serialized_end = 6420 + _POLLWORKFLOWTASKQUEUEREQUEST._serialized_start = 6423 + _POLLWORKFLOWTASKQUEUEREQUEST._serialized_end = 6863 + _POLLWORKFLOWTASKQUEUERESPONSE._serialized_start = 6866 + _POLLWORKFLOWTASKQUEUERESPONSE._serialized_end = 7876 + _POLLWORKFLOWTASKQUEUERESPONSE_QUERIESENTRY._serialized_start = 7792 + _POLLWORKFLOWTASKQUEUERESPONSE_QUERIESENTRY._serialized_end = 7876 + _RESPONDWORKFLOWTASKCOMPLETEDREQUEST._serialized_start = 7879 + _RESPONDWORKFLOWTASKCOMPLETEDREQUEST._serialized_end = 9169 + _RESPONDWORKFLOWTASKCOMPLETEDREQUEST_QUERYRESULTSENTRY._serialized_start = 9003 + _RESPONDWORKFLOWTASKCOMPLETEDREQUEST_QUERYRESULTSENTRY._serialized_end = 9098 + _RESPONDWORKFLOWTASKCOMPLETEDREQUEST_CAPABILITIES._serialized_start = 9100 + _RESPONDWORKFLOWTASKCOMPLETEDREQUEST_CAPABILITIES._serialized_end = 9169 + _RESPONDWORKFLOWTASKCOMPLETEDRESPONSE._serialized_start = 9172 + _RESPONDWORKFLOWTASKCOMPLETEDRESPONSE._serialized_end = 9417 + _RESPONDWORKFLOWTASKFAILEDREQUEST._serialized_start = 9420 + _RESPONDWORKFLOWTASKFAILEDREQUEST._serialized_end = 9945 + _RESPONDWORKFLOWTASKFAILEDRESPONSE._serialized_start = 9947 + _RESPONDWORKFLOWTASKFAILEDRESPONSE._serialized_end = 9982 + _POLLACTIVITYTASKQUEUEREQUEST._serialized_start = 9985 + _POLLACTIVITYTASKQUEUEREQUEST._serialized_end = 10471 + _POLLACTIVITYTASKQUEUERESPONSE._serialized_start = 10474 + _POLLACTIVITYTASKQUEUERESPONSE._serialized_end = 11578 + _RECORDACTIVITYTASKHEARTBEATREQUEST._serialized_start = 11581 + _RECORDACTIVITYTASKHEARTBEATREQUEST._serialized_end = 11746 + _RECORDACTIVITYTASKHEARTBEATRESPONSE._serialized_start = 11748 + _RECORDACTIVITYTASKHEARTBEATRESPONSE._serialized_end = 11860 + _RECORDACTIVITYTASKHEARTBEATBYIDREQUEST._serialized_start = 11863 + _RECORDACTIVITYTASKHEARTBEATBYIDREQUEST._serialized_end = 12070 + _RECORDACTIVITYTASKHEARTBEATBYIDRESPONSE._serialized_start = 12072 + _RECORDACTIVITYTASKHEARTBEATBYIDRESPONSE._serialized_end = 12188 + _RESPONDACTIVITYTASKCOMPLETEDREQUEST._serialized_start = 12191 + _RESPONDACTIVITYTASKCOMPLETEDREQUEST._serialized_end = 12573 + _RESPONDACTIVITYTASKCOMPLETEDRESPONSE._serialized_start = 12575 + _RESPONDACTIVITYTASKCOMPLETEDRESPONSE._serialized_end = 12613 + _RESPONDACTIVITYTASKCOMPLETEDBYIDREQUEST._serialized_start = 12616 + _RESPONDACTIVITYTASKCOMPLETEDBYIDREQUEST._serialized_end = 12823 + _RESPONDACTIVITYTASKCOMPLETEDBYIDRESPONSE._serialized_start = 12825 + _RESPONDACTIVITYTASKCOMPLETEDBYIDRESPONSE._serialized_end = 12867 + _RESPONDACTIVITYTASKFAILEDREQUEST._serialized_start = 12870 + _RESPONDACTIVITYTASKFAILEDREQUEST._serialized_end = 13316 + _RESPONDACTIVITYTASKFAILEDRESPONSE._serialized_start = 13318 + _RESPONDACTIVITYTASKFAILEDRESPONSE._serialized_end = 13405 + _RESPONDACTIVITYTASKFAILEDBYIDREQUEST._serialized_start = 13408 + _RESPONDACTIVITYTASKFAILEDBYIDREQUEST._serialized_end = 13679 + _RESPONDACTIVITYTASKFAILEDBYIDRESPONSE._serialized_start = 13681 + _RESPONDACTIVITYTASKFAILEDBYIDRESPONSE._serialized_end = 13772 + _RESPONDACTIVITYTASKCANCELEDREQUEST._serialized_start = 13775 + _RESPONDACTIVITYTASKCANCELEDREQUEST._serialized_end = 14157 + _RESPONDACTIVITYTASKCANCELEDRESPONSE._serialized_start = 14159 + _RESPONDACTIVITYTASKCANCELEDRESPONSE._serialized_end = 14196 + _RESPONDACTIVITYTASKCANCELEDBYIDREQUEST._serialized_start = 14199 + _RESPONDACTIVITYTASKCANCELEDBYIDREQUEST._serialized_end = 14487 + _RESPONDACTIVITYTASKCANCELEDBYIDRESPONSE._serialized_start = 14489 + _RESPONDACTIVITYTASKCANCELEDBYIDRESPONSE._serialized_end = 14530 + _REQUESTCANCELWORKFLOWEXECUTIONREQUEST._serialized_start = 14533 + _REQUESTCANCELWORKFLOWEXECUTIONREQUEST._serialized_end = 14793 + _REQUESTCANCELWORKFLOWEXECUTIONRESPONSE._serialized_start = 14795 + _REQUESTCANCELWORKFLOWEXECUTIONRESPONSE._serialized_end = 14835 + _SIGNALWORKFLOWEXECUTIONREQUEST._serialized_start = 14838 + _SIGNALWORKFLOWEXECUTIONREQUEST._serialized_end = 15188 + _SIGNALWORKFLOWEXECUTIONRESPONSE._serialized_start = 15190 + _SIGNALWORKFLOWEXECUTIONRESPONSE._serialized_end = 15267 + _SIGNALWITHSTARTWORKFLOWEXECUTIONREQUEST._serialized_start = 15270 + _SIGNALWITHSTARTWORKFLOWEXECUTIONREQUEST._serialized_end = 16611 + _SIGNALWITHSTARTWORKFLOWEXECUTIONRESPONSE._serialized_start = 16613 + _SIGNALWITHSTARTWORKFLOWEXECUTIONRESPONSE._serialized_end = 16739 + _RESETWORKFLOWEXECUTIONREQUEST._serialized_start = 16742 + _RESETWORKFLOWEXECUTIONREQUEST._serialized_end = 17191 + _RESETWORKFLOWEXECUTIONRESPONSE._serialized_start = 17193 + _RESETWORKFLOWEXECUTIONRESPONSE._serialized_end = 17241 + _TERMINATEWORKFLOWEXECUTIONREQUEST._serialized_start = 17244 + _TERMINATEWORKFLOWEXECUTIONREQUEST._serialized_end = 17531 + _TERMINATEWORKFLOWEXECUTIONRESPONSE._serialized_start = 17533 + _TERMINATEWORKFLOWEXECUTIONRESPONSE._serialized_end = 17569 + _DELETEWORKFLOWEXECUTIONREQUEST._serialized_start = 17571 + _DELETEWORKFLOWEXECUTIONREQUEST._serialized_end = 17693 + _DELETEWORKFLOWEXECUTIONRESPONSE._serialized_start = 17695 + _DELETEWORKFLOWEXECUTIONRESPONSE._serialized_end = 17728 + _LISTOPENWORKFLOWEXECUTIONSREQUEST._serialized_start = 17731 + _LISTOPENWORKFLOWEXECUTIONSREQUEST._serialized_end = 18060 + _LISTOPENWORKFLOWEXECUTIONSRESPONSE._serialized_start = 18063 + _LISTOPENWORKFLOWEXECUTIONSRESPONSE._serialized_end = 18193 + _LISTCLOSEDWORKFLOWEXECUTIONSREQUEST._serialized_start = 18196 + _LISTCLOSEDWORKFLOWEXECUTIONSREQUEST._serialized_end = 18590 + _LISTCLOSEDWORKFLOWEXECUTIONSRESPONSE._serialized_start = 18593 + _LISTCLOSEDWORKFLOWEXECUTIONSRESPONSE._serialized_end = 18725 + _LISTWORKFLOWEXECUTIONSREQUEST._serialized_start = 18727 + _LISTWORKFLOWEXECUTIONSREQUEST._serialized_end = 18836 + _LISTWORKFLOWEXECUTIONSRESPONSE._serialized_start = 18838 + _LISTWORKFLOWEXECUTIONSRESPONSE._serialized_end = 18964 + _LISTARCHIVEDWORKFLOWEXECUTIONSREQUEST._serialized_start = 18966 + _LISTARCHIVEDWORKFLOWEXECUTIONSREQUEST._serialized_end = 19083 + _LISTARCHIVEDWORKFLOWEXECUTIONSRESPONSE._serialized_start = 19086 + _LISTARCHIVEDWORKFLOWEXECUTIONSRESPONSE._serialized_end = 19220 + _SCANWORKFLOWEXECUTIONSREQUEST._serialized_start = 19222 + _SCANWORKFLOWEXECUTIONSREQUEST._serialized_end = 19331 + _SCANWORKFLOWEXECUTIONSRESPONSE._serialized_start = 19333 + _SCANWORKFLOWEXECUTIONSRESPONSE._serialized_end = 19459 + _COUNTWORKFLOWEXECUTIONSREQUEST._serialized_start = 19461 + _COUNTWORKFLOWEXECUTIONSREQUEST._serialized_end = 19527 + _COUNTWORKFLOWEXECUTIONSRESPONSE._serialized_start = 19530 + _COUNTWORKFLOWEXECUTIONSRESPONSE._serialized_end = 19767 + _COUNTWORKFLOWEXECUTIONSRESPONSE_AGGREGATIONGROUP._serialized_start = 19679 + _COUNTWORKFLOWEXECUTIONSRESPONSE_AGGREGATIONGROUP._serialized_end = 19767 + _GETSEARCHATTRIBUTESREQUEST._serialized_start = 19769 + _GETSEARCHATTRIBUTESREQUEST._serialized_end = 19797 + _GETSEARCHATTRIBUTESRESPONSE._serialized_start = 19800 + _GETSEARCHATTRIBUTESRESPONSE._serialized_end = 20001 + _GETSEARCHATTRIBUTESRESPONSE_KEYSENTRY._serialized_start = 19917 + _GETSEARCHATTRIBUTESRESPONSE_KEYSENTRY._serialized_end = 20001 + _RESPONDQUERYTASKCOMPLETEDREQUEST._serialized_start = 20004 + _RESPONDQUERYTASKCOMPLETEDREQUEST._serialized_end = 20365 + _RESPONDQUERYTASKCOMPLETEDRESPONSE._serialized_start = 20367 + _RESPONDQUERYTASKCOMPLETEDRESPONSE._serialized_end = 20402 + _RESETSTICKYTASKQUEUEREQUEST._serialized_start = 20404 + _RESETSTICKYTASKQUEUEREQUEST._serialized_end = 20514 + _RESETSTICKYTASKQUEUERESPONSE._serialized_start = 20516 + _RESETSTICKYTASKQUEUERESPONSE._serialized_end = 20546 + _SHUTDOWNWORKERREQUEST._serialized_start = 20549 + _SHUTDOWNWORKERREQUEST._serialized_end = 20832 + _SHUTDOWNWORKERRESPONSE._serialized_start = 20834 + _SHUTDOWNWORKERRESPONSE._serialized_end = 20858 + _QUERYWORKFLOWREQUEST._serialized_start = 20861 + _QUERYWORKFLOWREQUEST._serialized_end = 21094 + _QUERYWORKFLOWRESPONSE._serialized_start = 21097 + _QUERYWORKFLOWRESPONSE._serialized_end = 21238 + _DESCRIBEWORKFLOWEXECUTIONREQUEST._serialized_start = 21240 + _DESCRIBEWORKFLOWEXECUTIONREQUEST._serialized_end = 21355 + _DESCRIBEWORKFLOWEXECUTIONRESPONSE._serialized_start = 21358 + _DESCRIBEWORKFLOWEXECUTIONRESPONSE._serialized_end = 22023 + _DESCRIBETASKQUEUEREQUEST._serialized_start = 22026 + _DESCRIBETASKQUEUEREQUEST._serialized_end = 22554 + _DESCRIBETASKQUEUERESPONSE._serialized_start = 22557 + _DESCRIBETASKQUEUERESPONSE._serialized_end = 23561 + _DESCRIBETASKQUEUERESPONSE_STATSBYPRIORITYKEYENTRY._serialized_start = 23241 + _DESCRIBETASKQUEUERESPONSE_STATSBYPRIORITYKEYENTRY._serialized_end = 23341 + _DESCRIBETASKQUEUERESPONSE_EFFECTIVERATELIMIT._serialized_start = 23343 + _DESCRIBETASKQUEUERESPONSE_EFFECTIVERATELIMIT._serialized_end = 23459 + _DESCRIBETASKQUEUERESPONSE_VERSIONSINFOENTRY._serialized_start = 23461 + _DESCRIBETASKQUEUERESPONSE_VERSIONSINFOENTRY._serialized_end = 23561 + _GETCLUSTERINFOREQUEST._serialized_start = 23563 + _GETCLUSTERINFOREQUEST._serialized_end = 23586 + _GETCLUSTERINFORESPONSE._serialized_start = 23589 + _GETCLUSTERINFORESPONSE._serialized_end = 24054 + _GETCLUSTERINFORESPONSE_SUPPORTEDCLIENTSENTRY._serialized_start = 23999 + _GETCLUSTERINFORESPONSE_SUPPORTEDCLIENTSENTRY._serialized_end = 24054 + _GETSYSTEMINFOREQUEST._serialized_start = 24056 + _GETSYSTEMINFOREQUEST._serialized_end = 24078 + _GETSYSTEMINFORESPONSE._serialized_start = 24081 + _GETSYSTEMINFORESPONSE._serialized_end = 24616 + _GETSYSTEMINFORESPONSE_CAPABILITIES._serialized_start = 24222 + _GETSYSTEMINFORESPONSE_CAPABILITIES._serialized_end = 24616 + _LISTTASKQUEUEPARTITIONSREQUEST._serialized_start = 24618 + _LISTTASKQUEUEPARTITIONSREQUEST._serialized_end = 24727 + _LISTTASKQUEUEPARTITIONSRESPONSE._serialized_start = 24730 + _LISTTASKQUEUEPARTITIONSRESPONSE._serialized_end = 24953 + _CREATESCHEDULEREQUEST._serialized_start = 24956 + _CREATESCHEDULEREQUEST._serialized_end = 25288 + _CREATESCHEDULERESPONSE._serialized_start = 25290 + _CREATESCHEDULERESPONSE._serialized_end = 25338 + _DESCRIBESCHEDULEREQUEST._serialized_start = 25340 + _DESCRIBESCHEDULEREQUEST._serialized_end = 25405 + _DESCRIBESCHEDULERESPONSE._serialized_start = 25408 + _DESCRIBESCHEDULERESPONSE._serialized_end = 25679 + _UPDATESCHEDULEREQUEST._serialized_start = 25682 + _UPDATESCHEDULEREQUEST._serialized_end = 25974 + _UPDATESCHEDULERESPONSE._serialized_start = 25976 + _UPDATESCHEDULERESPONSE._serialized_end = 26000 + _PATCHSCHEDULEREQUEST._serialized_start = 26003 + _PATCHSCHEDULEREQUEST._serialized_end = 26159 + _PATCHSCHEDULERESPONSE._serialized_start = 26161 + _PATCHSCHEDULERESPONSE._serialized_end = 26184 + _LISTSCHEDULEMATCHINGTIMESREQUEST._serialized_start = 26187 + _LISTSCHEDULEMATCHINGTIMESREQUEST._serialized_end = 26355 + _LISTSCHEDULEMATCHINGTIMESRESPONSE._serialized_start = 26357 + _LISTSCHEDULEMATCHINGTIMESRESPONSE._serialized_end = 26440 + _DELETESCHEDULEREQUEST._serialized_start = 26442 + _DELETESCHEDULEREQUEST._serialized_end = 26523 + _DELETESCHEDULERESPONSE._serialized_start = 26525 + _DELETESCHEDULERESPONSE._serialized_end = 26549 + _LISTSCHEDULESREQUEST._serialized_start = 26551 + _LISTSCHEDULESREQUEST._serialized_end = 26659 + _LISTSCHEDULESRESPONSE._serialized_start = 26661 + _LISTSCHEDULESRESPONSE._serialized_end = 26773 + _COUNTSCHEDULESREQUEST._serialized_start = 26775 + _COUNTSCHEDULESREQUEST._serialized_end = 26832 + _COUNTSCHEDULESRESPONSE._serialized_start = 26835 + _COUNTSCHEDULESRESPONSE._serialized_end = 27054 + _COUNTSCHEDULESRESPONSE_AGGREGATIONGROUP._serialized_start = 19679 + _COUNTSCHEDULESRESPONSE_AGGREGATIONGROUP._serialized_end = 19767 + _UPDATEWORKERBUILDIDCOMPATIBILITYREQUEST._serialized_start = 27057 + _UPDATEWORKERBUILDIDCOMPATIBILITYREQUEST._serialized_end = 27703 + _UPDATEWORKERBUILDIDCOMPATIBILITYREQUEST_ADDNEWCOMPATIBLEVERSION._serialized_start = 27504 _UPDATEWORKERBUILDIDCOMPATIBILITYREQUEST_ADDNEWCOMPATIBLEVERSION._serialized_end = ( - 27589 + 27615 ) - _UPDATEWORKERBUILDIDCOMPATIBILITYREQUEST_MERGESETS._serialized_start = 27591 - _UPDATEWORKERBUILDIDCOMPATIBILITYREQUEST_MERGESETS._serialized_end = 27664 - _UPDATEWORKERBUILDIDCOMPATIBILITYRESPONSE._serialized_start = 27679 - _UPDATEWORKERBUILDIDCOMPATIBILITYRESPONSE._serialized_end = 27743 - _GETWORKERBUILDIDCOMPATIBILITYREQUEST._serialized_start = 27745 - _GETWORKERBUILDIDCOMPATIBILITYREQUEST._serialized_end = 27840 - _GETWORKERBUILDIDCOMPATIBILITYRESPONSE._serialized_start = 27842 - _GETWORKERBUILDIDCOMPATIBILITYRESPONSE._serialized_end = 27958 - _UPDATEWORKERVERSIONINGRULESREQUEST._serialized_start = 27961 - _UPDATEWORKERVERSIONINGRULESREQUEST._serialized_end = 29678 - _UPDATEWORKERVERSIONINGRULESREQUEST_INSERTBUILDIDASSIGNMENTRULE._serialized_start = 29013 + _UPDATEWORKERBUILDIDCOMPATIBILITYREQUEST_MERGESETS._serialized_start = 27617 + _UPDATEWORKERBUILDIDCOMPATIBILITYREQUEST_MERGESETS._serialized_end = 27690 + _UPDATEWORKERBUILDIDCOMPATIBILITYRESPONSE._serialized_start = 27705 + _UPDATEWORKERBUILDIDCOMPATIBILITYRESPONSE._serialized_end = 27769 + _GETWORKERBUILDIDCOMPATIBILITYREQUEST._serialized_start = 27771 + _GETWORKERBUILDIDCOMPATIBILITYREQUEST._serialized_end = 27866 + _GETWORKERBUILDIDCOMPATIBILITYRESPONSE._serialized_start = 27868 + _GETWORKERBUILDIDCOMPATIBILITYRESPONSE._serialized_end = 27984 + _UPDATEWORKERVERSIONINGRULESREQUEST._serialized_start = 27987 + _UPDATEWORKERVERSIONINGRULESREQUEST._serialized_end = 29704 + _UPDATEWORKERVERSIONINGRULESREQUEST_INSERTBUILDIDASSIGNMENTRULE._serialized_start = 29039 _UPDATEWORKERVERSIONINGRULESREQUEST_INSERTBUILDIDASSIGNMENTRULE._serialized_end = ( - 29126 + 29152 ) - _UPDATEWORKERVERSIONINGRULESREQUEST_REPLACEBUILDIDASSIGNMENTRULE._serialized_start = 29129 + _UPDATEWORKERVERSIONINGRULESREQUEST_REPLACEBUILDIDASSIGNMENTRULE._serialized_start = 29155 _UPDATEWORKERVERSIONINGRULESREQUEST_REPLACEBUILDIDASSIGNMENTRULE._serialized_end = ( - 29258 + 29284 ) - _UPDATEWORKERVERSIONINGRULESREQUEST_DELETEBUILDIDASSIGNMENTRULE._serialized_start = 29260 + _UPDATEWORKERVERSIONINGRULESREQUEST_DELETEBUILDIDASSIGNMENTRULE._serialized_start = 29286 _UPDATEWORKERVERSIONINGRULESREQUEST_DELETEBUILDIDASSIGNMENTRULE._serialized_end = ( - 29324 + 29350 ) - _UPDATEWORKERVERSIONINGRULESREQUEST_ADDCOMPATIBLEBUILDIDREDIRECTRULE._serialized_start = 29326 - _UPDATEWORKERVERSIONINGRULESREQUEST_ADDCOMPATIBLEBUILDIDREDIRECTRULE._serialized_end = 29432 - _UPDATEWORKERVERSIONINGRULESREQUEST_REPLACECOMPATIBLEBUILDIDREDIRECTRULE._serialized_start = 29434 - _UPDATEWORKERVERSIONINGRULESREQUEST_REPLACECOMPATIBLEBUILDIDREDIRECTRULE._serialized_end = 29544 - _UPDATEWORKERVERSIONINGRULESREQUEST_DELETECOMPATIBLEBUILDIDREDIRECTRULE._serialized_start = 29546 - _UPDATEWORKERVERSIONINGRULESREQUEST_DELETECOMPATIBLEBUILDIDREDIRECTRULE._serialized_end = 29608 - _UPDATEWORKERVERSIONINGRULESREQUEST_COMMITBUILDID._serialized_start = 29610 - _UPDATEWORKERVERSIONINGRULESREQUEST_COMMITBUILDID._serialized_end = 29665 - _UPDATEWORKERVERSIONINGRULESRESPONSE._serialized_start = 29681 - _UPDATEWORKERVERSIONINGRULESRESPONSE._serialized_end = 29933 - _GETWORKERVERSIONINGRULESREQUEST._serialized_start = 29935 - _GETWORKERVERSIONINGRULESREQUEST._serialized_end = 30007 - _GETWORKERVERSIONINGRULESRESPONSE._serialized_start = 30010 - _GETWORKERVERSIONINGRULESRESPONSE._serialized_end = 30259 - _GETWORKERTASKREACHABILITYREQUEST._serialized_start = 30262 - _GETWORKERTASKREACHABILITYREQUEST._serialized_end = 30418 - _GETWORKERTASKREACHABILITYRESPONSE._serialized_start = 30420 - _GETWORKERTASKREACHABILITYRESPONSE._serialized_end = 30534 - _UPDATEWORKFLOWEXECUTIONREQUEST._serialized_start = 30537 - _UPDATEWORKFLOWEXECUTIONREQUEST._serialized_end = 30798 - _UPDATEWORKFLOWEXECUTIONRESPONSE._serialized_start = 30801 - _UPDATEWORKFLOWEXECUTIONRESPONSE._serialized_end = 31016 - _STARTBATCHOPERATIONREQUEST._serialized_start = 31019 - _STARTBATCHOPERATIONREQUEST._serialized_end = 32031 - _STARTBATCHOPERATIONRESPONSE._serialized_start = 32033 - _STARTBATCHOPERATIONRESPONSE._serialized_end = 32062 - _STOPBATCHOPERATIONREQUEST._serialized_start = 32064 - _STOPBATCHOPERATIONREQUEST._serialized_end = 32160 - _STOPBATCHOPERATIONRESPONSE._serialized_start = 32162 - _STOPBATCHOPERATIONRESPONSE._serialized_end = 32190 - _DESCRIBEBATCHOPERATIONREQUEST._serialized_start = 32192 - _DESCRIBEBATCHOPERATIONREQUEST._serialized_end = 32258 - _DESCRIBEBATCHOPERATIONRESPONSE._serialized_start = 32261 - _DESCRIBEBATCHOPERATIONRESPONSE._serialized_end = 32663 - _LISTBATCHOPERATIONSREQUEST._serialized_start = 32665 - _LISTBATCHOPERATIONSREQUEST._serialized_end = 32756 - _LISTBATCHOPERATIONSRESPONSE._serialized_start = 32758 - _LISTBATCHOPERATIONSRESPONSE._serialized_end = 32879 - _POLLWORKFLOWEXECUTIONUPDATEREQUEST._serialized_start = 32882 - _POLLWORKFLOWEXECUTIONUPDATEREQUEST._serialized_end = 33067 - _POLLWORKFLOWEXECUTIONUPDATERESPONSE._serialized_start = 33070 - _POLLWORKFLOWEXECUTIONUPDATERESPONSE._serialized_end = 33289 - _POLLNEXUSTASKQUEUEREQUEST._serialized_start = 33292 - _POLLNEXUSTASKQUEUEREQUEST._serialized_end = 33708 - _POLLNEXUSTASKQUEUERESPONSE._serialized_start = 33711 - _POLLNEXUSTASKQUEUERESPONSE._serialized_end = 33988 - _RESPONDNEXUSTASKCOMPLETEDREQUEST._serialized_start = 33991 - _RESPONDNEXUSTASKCOMPLETEDREQUEST._serialized_end = 34158 - _RESPONDNEXUSTASKCOMPLETEDRESPONSE._serialized_start = 34160 - _RESPONDNEXUSTASKCOMPLETEDRESPONSE._serialized_end = 34195 - _RESPONDNEXUSTASKFAILEDREQUEST._serialized_start = 34198 - _RESPONDNEXUSTASKFAILEDREQUEST._serialized_end = 34418 - _RESPONDNEXUSTASKFAILEDRESPONSE._serialized_start = 34420 - _RESPONDNEXUSTASKFAILEDRESPONSE._serialized_end = 34452 - _EXECUTEMULTIOPERATIONREQUEST._serialized_start = 34455 - _EXECUTEMULTIOPERATIONREQUEST._serialized_end = 34827 - _EXECUTEMULTIOPERATIONREQUEST_OPERATION._serialized_start = 34621 - _EXECUTEMULTIOPERATIONREQUEST_OPERATION._serialized_end = 34827 - _EXECUTEMULTIOPERATIONRESPONSE._serialized_start = 34830 - _EXECUTEMULTIOPERATIONRESPONSE._serialized_end = 35162 - _EXECUTEMULTIOPERATIONRESPONSE_RESPONSE._serialized_start = 34956 - _EXECUTEMULTIOPERATIONRESPONSE_RESPONSE._serialized_end = 35162 - _UPDATEACTIVITYOPTIONSREQUEST._serialized_start = 35165 - _UPDATEACTIVITYOPTIONSREQUEST._serialized_end = 35501 - _UPDATEACTIVITYOPTIONSRESPONSE._serialized_start = 35503 - _UPDATEACTIVITYOPTIONSRESPONSE._serialized_end = 35603 - _PAUSEACTIVITYREQUEST._serialized_start = 35606 - _PAUSEACTIVITYREQUEST._serialized_end = 35785 - _PAUSEACTIVITYRESPONSE._serialized_start = 35787 - _PAUSEACTIVITYRESPONSE._serialized_end = 35810 - _UNPAUSEACTIVITYREQUEST._serialized_start = 35813 - _UNPAUSEACTIVITYREQUEST._serialized_end = 36093 - _UNPAUSEACTIVITYRESPONSE._serialized_start = 36095 - _UNPAUSEACTIVITYRESPONSE._serialized_end = 36120 - _RESETACTIVITYREQUEST._serialized_start = 36123 - _RESETACTIVITYREQUEST._serialized_end = 36430 - _RESETACTIVITYRESPONSE._serialized_start = 36432 - _RESETACTIVITYRESPONSE._serialized_end = 36455 - _UPDATEWORKFLOWEXECUTIONOPTIONSREQUEST._serialized_start = 36458 - _UPDATEWORKFLOWEXECUTIONOPTIONSREQUEST._serialized_end = 36742 - _UPDATEWORKFLOWEXECUTIONOPTIONSRESPONSE._serialized_start = 36745 - _UPDATEWORKFLOWEXECUTIONOPTIONSRESPONSE._serialized_end = 36873 - _DESCRIBEDEPLOYMENTREQUEST._serialized_start = 36875 - _DESCRIBEDEPLOYMENTREQUEST._serialized_end = 36981 - _DESCRIBEDEPLOYMENTRESPONSE._serialized_start = 36983 - _DESCRIBEDEPLOYMENTRESPONSE._serialized_end = 37080 - _DESCRIBEWORKERDEPLOYMENTVERSIONREQUEST._serialized_start = 37083 - _DESCRIBEWORKERDEPLOYMENTVERSIONREQUEST._serialized_end = 37277 - _DESCRIBEWORKERDEPLOYMENTVERSIONRESPONSE._serialized_start = 37280 - _DESCRIBEWORKERDEPLOYMENTVERSIONRESPONSE._serialized_end = 37932 - _DESCRIBEWORKERDEPLOYMENTVERSIONRESPONSE_VERSIONTASKQUEUE._serialized_start = 37541 - _DESCRIBEWORKERDEPLOYMENTVERSIONRESPONSE_VERSIONTASKQUEUE._serialized_end = 37932 - _DESCRIBEWORKERDEPLOYMENTVERSIONRESPONSE_VERSIONTASKQUEUE_STATSBYPRIORITYKEYENTRY._serialized_start = 23215 - _DESCRIBEWORKERDEPLOYMENTVERSIONRESPONSE_VERSIONTASKQUEUE_STATSBYPRIORITYKEYENTRY._serialized_end = 23315 - _DESCRIBEWORKERDEPLOYMENTREQUEST._serialized_start = 37934 - _DESCRIBEWORKERDEPLOYMENTREQUEST._serialized_end = 38011 - _DESCRIBEWORKERDEPLOYMENTRESPONSE._serialized_start = 38014 - _DESCRIBEWORKERDEPLOYMENTRESPONSE._serialized_end = 38154 - _LISTDEPLOYMENTSREQUEST._serialized_start = 38156 - _LISTDEPLOYMENTSREQUEST._serialized_end = 38264 - _LISTDEPLOYMENTSRESPONSE._serialized_start = 38266 - _LISTDEPLOYMENTSRESPONSE._serialized_end = 38385 - _SETCURRENTDEPLOYMENTREQUEST._serialized_start = 38388 - _SETCURRENTDEPLOYMENTREQUEST._serialized_end = 38593 - _SETCURRENTDEPLOYMENTRESPONSE._serialized_start = 38596 - _SETCURRENTDEPLOYMENTRESPONSE._serialized_end = 38781 - _SETWORKERDEPLOYMENTCURRENTVERSIONREQUEST._serialized_start = 38784 - _SETWORKERDEPLOYMENTCURRENTVERSIONREQUEST._serialized_end = 39013 - _SETWORKERDEPLOYMENTCURRENTVERSIONRESPONSE._serialized_start = 39016 - _SETWORKERDEPLOYMENTCURRENTVERSIONRESPONSE._serialized_end = 39207 - _SETWORKERDEPLOYMENTRAMPINGVERSIONREQUEST._serialized_start = 39210 - _SETWORKERDEPLOYMENTRAMPINGVERSIONREQUEST._serialized_end = 39459 - _SETWORKERDEPLOYMENTRAMPINGVERSIONRESPONSE._serialized_start = 39462 - _SETWORKERDEPLOYMENTRAMPINGVERSIONRESPONSE._serialized_end = 39686 - _CREATEWORKERDEPLOYMENTREQUEST._serialized_start = 39688 - _CREATEWORKERDEPLOYMENTREQUEST._serialized_end = 39801 - _CREATEWORKERDEPLOYMENTRESPONSE._serialized_start = 39803 - _CREATEWORKERDEPLOYMENTRESPONSE._serialized_end = 39859 - _LISTWORKERDEPLOYMENTSREQUEST._serialized_start = 39861 - _LISTWORKERDEPLOYMENTSREQUEST._serialized_end = 39954 - _LISTWORKERDEPLOYMENTSRESPONSE._serialized_start = 39957 - _LISTWORKERDEPLOYMENTSRESPONSE._serialized_end = 40628 - _LISTWORKERDEPLOYMENTSRESPONSE_WORKERDEPLOYMENTSUMMARY._serialized_start = 40132 - _LISTWORKERDEPLOYMENTSRESPONSE_WORKERDEPLOYMENTSUMMARY._serialized_end = 40628 - _CREATEWORKERDEPLOYMENTVERSIONREQUEST._serialized_start = 40631 - _CREATEWORKERDEPLOYMENTVERSIONREQUEST._serialized_end = 40871 - _CREATEWORKERDEPLOYMENTVERSIONRESPONSE._serialized_start = 40873 - _CREATEWORKERDEPLOYMENTVERSIONRESPONSE._serialized_end = 40912 - _DELETEWORKERDEPLOYMENTVERSIONREQUEST._serialized_start = 40915 - _DELETEWORKERDEPLOYMENTVERSIONREQUEST._serialized_end = 41115 - _DELETEWORKERDEPLOYMENTVERSIONRESPONSE._serialized_start = 41117 - _DELETEWORKERDEPLOYMENTVERSIONRESPONSE._serialized_end = 41156 - _DELETEWORKERDEPLOYMENTREQUEST._serialized_start = 41158 - _DELETEWORKERDEPLOYMENTREQUEST._serialized_end = 41251 - _DELETEWORKERDEPLOYMENTRESPONSE._serialized_start = 41253 - _DELETEWORKERDEPLOYMENTRESPONSE._serialized_end = 41285 - _UPDATEWORKERDEPLOYMENTVERSIONCOMPUTECONFIGREQUEST._serialized_start = 41288 - _UPDATEWORKERDEPLOYMENTVERSIONCOMPUTECONFIGREQUEST._serialized_end = 41804 - _UPDATEWORKERDEPLOYMENTVERSIONCOMPUTECONFIGREQUEST_COMPUTECONFIGSCALINGGROUPSENTRY._serialized_start = 41681 - _UPDATEWORKERDEPLOYMENTVERSIONCOMPUTECONFIGREQUEST_COMPUTECONFIGSCALINGGROUPSENTRY._serialized_end = 41804 - _UPDATEWORKERDEPLOYMENTVERSIONCOMPUTECONFIGRESPONSE._serialized_start = 41806 - _UPDATEWORKERDEPLOYMENTVERSIONCOMPUTECONFIGRESPONSE._serialized_end = 41858 - _VALIDATEWORKERDEPLOYMENTVERSIONCOMPUTECONFIGREQUEST._serialized_start = 41861 - _VALIDATEWORKERDEPLOYMENTVERSIONCOMPUTECONFIGREQUEST._serialized_end = 42361 - _VALIDATEWORKERDEPLOYMENTVERSIONCOMPUTECONFIGREQUEST_COMPUTECONFIGSCALINGGROUPSENTRY._serialized_start = 41681 - _VALIDATEWORKERDEPLOYMENTVERSIONCOMPUTECONFIGREQUEST_COMPUTECONFIGSCALINGGROUPSENTRY._serialized_end = 41804 - _VALIDATEWORKERDEPLOYMENTVERSIONCOMPUTECONFIGRESPONSE._serialized_start = 42363 - _VALIDATEWORKERDEPLOYMENTVERSIONCOMPUTECONFIGRESPONSE._serialized_end = 42417 - _UPDATEWORKERDEPLOYMENTVERSIONMETADATAREQUEST._serialized_start = 42420 - _UPDATEWORKERDEPLOYMENTVERSIONMETADATAREQUEST._serialized_end = 42838 - _UPDATEWORKERDEPLOYMENTVERSIONMETADATAREQUEST_UPSERTENTRIESENTRY._serialized_start = 42753 + _UPDATEWORKERVERSIONINGRULESREQUEST_ADDCOMPATIBLEBUILDIDREDIRECTRULE._serialized_start = 29352 + _UPDATEWORKERVERSIONINGRULESREQUEST_ADDCOMPATIBLEBUILDIDREDIRECTRULE._serialized_end = 29458 + _UPDATEWORKERVERSIONINGRULESREQUEST_REPLACECOMPATIBLEBUILDIDREDIRECTRULE._serialized_start = 29460 + _UPDATEWORKERVERSIONINGRULESREQUEST_REPLACECOMPATIBLEBUILDIDREDIRECTRULE._serialized_end = 29570 + _UPDATEWORKERVERSIONINGRULESREQUEST_DELETECOMPATIBLEBUILDIDREDIRECTRULE._serialized_start = 29572 + _UPDATEWORKERVERSIONINGRULESREQUEST_DELETECOMPATIBLEBUILDIDREDIRECTRULE._serialized_end = 29634 + _UPDATEWORKERVERSIONINGRULESREQUEST_COMMITBUILDID._serialized_start = 29636 + _UPDATEWORKERVERSIONINGRULESREQUEST_COMMITBUILDID._serialized_end = 29691 + _UPDATEWORKERVERSIONINGRULESRESPONSE._serialized_start = 29707 + _UPDATEWORKERVERSIONINGRULESRESPONSE._serialized_end = 29959 + _GETWORKERVERSIONINGRULESREQUEST._serialized_start = 29961 + _GETWORKERVERSIONINGRULESREQUEST._serialized_end = 30033 + _GETWORKERVERSIONINGRULESRESPONSE._serialized_start = 30036 + _GETWORKERVERSIONINGRULESRESPONSE._serialized_end = 30285 + _GETWORKERTASKREACHABILITYREQUEST._serialized_start = 30288 + _GETWORKERTASKREACHABILITYREQUEST._serialized_end = 30444 + _GETWORKERTASKREACHABILITYRESPONSE._serialized_start = 30446 + _GETWORKERTASKREACHABILITYRESPONSE._serialized_end = 30560 + _UPDATEWORKFLOWEXECUTIONREQUEST._serialized_start = 30563 + _UPDATEWORKFLOWEXECUTIONREQUEST._serialized_end = 30824 + _UPDATEWORKFLOWEXECUTIONRESPONSE._serialized_start = 30827 + _UPDATEWORKFLOWEXECUTIONRESPONSE._serialized_end = 31042 + _STARTBATCHOPERATIONREQUEST._serialized_start = 31045 + _STARTBATCHOPERATIONREQUEST._serialized_end = 32057 + _STARTBATCHOPERATIONRESPONSE._serialized_start = 32059 + _STARTBATCHOPERATIONRESPONSE._serialized_end = 32088 + _STOPBATCHOPERATIONREQUEST._serialized_start = 32090 + _STOPBATCHOPERATIONREQUEST._serialized_end = 32186 + _STOPBATCHOPERATIONRESPONSE._serialized_start = 32188 + _STOPBATCHOPERATIONRESPONSE._serialized_end = 32216 + _DESCRIBEBATCHOPERATIONREQUEST._serialized_start = 32218 + _DESCRIBEBATCHOPERATIONREQUEST._serialized_end = 32284 + _DESCRIBEBATCHOPERATIONRESPONSE._serialized_start = 32287 + _DESCRIBEBATCHOPERATIONRESPONSE._serialized_end = 32689 + _LISTBATCHOPERATIONSREQUEST._serialized_start = 32691 + _LISTBATCHOPERATIONSREQUEST._serialized_end = 32782 + _LISTBATCHOPERATIONSRESPONSE._serialized_start = 32784 + _LISTBATCHOPERATIONSRESPONSE._serialized_end = 32905 + _POLLWORKFLOWEXECUTIONUPDATEREQUEST._serialized_start = 32908 + _POLLWORKFLOWEXECUTIONUPDATEREQUEST._serialized_end = 33093 + _POLLWORKFLOWEXECUTIONUPDATERESPONSE._serialized_start = 33096 + _POLLWORKFLOWEXECUTIONUPDATERESPONSE._serialized_end = 33315 + _POLLNEXUSTASKQUEUEREQUEST._serialized_start = 33318 + _POLLNEXUSTASKQUEUEREQUEST._serialized_end = 33734 + _POLLNEXUSTASKQUEUERESPONSE._serialized_start = 33737 + _POLLNEXUSTASKQUEUERESPONSE._serialized_end = 34014 + _RESPONDNEXUSTASKCOMPLETEDREQUEST._serialized_start = 34017 + _RESPONDNEXUSTASKCOMPLETEDREQUEST._serialized_end = 34184 + _RESPONDNEXUSTASKCOMPLETEDRESPONSE._serialized_start = 34186 + _RESPONDNEXUSTASKCOMPLETEDRESPONSE._serialized_end = 34221 + _RESPONDNEXUSTASKFAILEDREQUEST._serialized_start = 34224 + _RESPONDNEXUSTASKFAILEDREQUEST._serialized_end = 34444 + _RESPONDNEXUSTASKFAILEDRESPONSE._serialized_start = 34446 + _RESPONDNEXUSTASKFAILEDRESPONSE._serialized_end = 34478 + _EXECUTEMULTIOPERATIONREQUEST._serialized_start = 34481 + _EXECUTEMULTIOPERATIONREQUEST._serialized_end = 34853 + _EXECUTEMULTIOPERATIONREQUEST_OPERATION._serialized_start = 34647 + _EXECUTEMULTIOPERATIONREQUEST_OPERATION._serialized_end = 34853 + _EXECUTEMULTIOPERATIONRESPONSE._serialized_start = 34856 + _EXECUTEMULTIOPERATIONRESPONSE._serialized_end = 35188 + _EXECUTEMULTIOPERATIONRESPONSE_RESPONSE._serialized_start = 34982 + _EXECUTEMULTIOPERATIONRESPONSE_RESPONSE._serialized_end = 35188 + _UPDATEACTIVITYOPTIONSREQUEST._serialized_start = 35191 + _UPDATEACTIVITYOPTIONSREQUEST._serialized_end = 35527 + _UPDATEACTIVITYEXECUTIONOPTIONSREQUEST._serialized_start = 35530 + _UPDATEACTIVITYEXECUTIONOPTIONSREQUEST._serialized_end = 35829 + _UPDATEACTIVITYOPTIONSRESPONSE._serialized_start = 35831 + _UPDATEACTIVITYOPTIONSRESPONSE._serialized_end = 35931 + _UPDATEACTIVITYEXECUTIONOPTIONSRESPONSE._serialized_start = 35933 + _UPDATEACTIVITYEXECUTIONOPTIONSRESPONSE._serialized_end = 36042 + _PAUSEACTIVITYREQUEST._serialized_start = 36045 + _PAUSEACTIVITYREQUEST._serialized_end = 36244 + _PAUSEACTIVITYEXECUTIONREQUEST._serialized_start = 36247 + _PAUSEACTIVITYEXECUTIONREQUEST._serialized_end = 36430 + _PAUSEACTIVITYRESPONSE._serialized_start = 36432 + _PAUSEACTIVITYRESPONSE._serialized_end = 36455 + _PAUSEACTIVITYEXECUTIONRESPONSE._serialized_start = 36457 + _PAUSEACTIVITYEXECUTIONRESPONSE._serialized_end = 36489 + _UNPAUSEACTIVITYREQUEST._serialized_start = 36492 + _UNPAUSEACTIVITYREQUEST._serialized_end = 36772 + _UNPAUSEACTIVITYEXECUTIONREQUEST._serialized_start = 36775 + _UNPAUSEACTIVITYEXECUTIONREQUEST._serialized_end = 37032 + _UNPAUSEACTIVITYRESPONSE._serialized_start = 37034 + _UNPAUSEACTIVITYRESPONSE._serialized_end = 37059 + _UNPAUSEACTIVITYEXECUTIONRESPONSE._serialized_start = 37061 + _UNPAUSEACTIVITYEXECUTIONRESPONSE._serialized_end = 37095 + _RESETACTIVITYREQUEST._serialized_start = 37098 + _RESETACTIVITYREQUEST._serialized_end = 37405 + _RESETACTIVITYEXECUTIONREQUEST._serialized_start = 37408 + _RESETACTIVITYEXECUTIONREQUEST._serialized_end = 37678 + _RESETACTIVITYRESPONSE._serialized_start = 37680 + _RESETACTIVITYRESPONSE._serialized_end = 37703 + _RESETACTIVITYEXECUTIONRESPONSE._serialized_start = 37705 + _RESETACTIVITYEXECUTIONRESPONSE._serialized_end = 37737 + _UPDATEWORKFLOWEXECUTIONOPTIONSREQUEST._serialized_start = 37740 + _UPDATEWORKFLOWEXECUTIONOPTIONSREQUEST._serialized_end = 38024 + _UPDATEWORKFLOWEXECUTIONOPTIONSRESPONSE._serialized_start = 38027 + _UPDATEWORKFLOWEXECUTIONOPTIONSRESPONSE._serialized_end = 38155 + _DESCRIBEDEPLOYMENTREQUEST._serialized_start = 38157 + _DESCRIBEDEPLOYMENTREQUEST._serialized_end = 38263 + _DESCRIBEDEPLOYMENTRESPONSE._serialized_start = 38265 + _DESCRIBEDEPLOYMENTRESPONSE._serialized_end = 38362 + _DESCRIBEWORKERDEPLOYMENTVERSIONREQUEST._serialized_start = 38365 + _DESCRIBEWORKERDEPLOYMENTVERSIONREQUEST._serialized_end = 38559 + _DESCRIBEWORKERDEPLOYMENTVERSIONRESPONSE._serialized_start = 38562 + _DESCRIBEWORKERDEPLOYMENTVERSIONRESPONSE._serialized_end = 39214 + _DESCRIBEWORKERDEPLOYMENTVERSIONRESPONSE_VERSIONTASKQUEUE._serialized_start = 38823 + _DESCRIBEWORKERDEPLOYMENTVERSIONRESPONSE_VERSIONTASKQUEUE._serialized_end = 39214 + _DESCRIBEWORKERDEPLOYMENTVERSIONRESPONSE_VERSIONTASKQUEUE_STATSBYPRIORITYKEYENTRY._serialized_start = 23241 + _DESCRIBEWORKERDEPLOYMENTVERSIONRESPONSE_VERSIONTASKQUEUE_STATSBYPRIORITYKEYENTRY._serialized_end = 23341 + _DESCRIBEWORKERDEPLOYMENTREQUEST._serialized_start = 39216 + _DESCRIBEWORKERDEPLOYMENTREQUEST._serialized_end = 39293 + _DESCRIBEWORKERDEPLOYMENTRESPONSE._serialized_start = 39296 + _DESCRIBEWORKERDEPLOYMENTRESPONSE._serialized_end = 39436 + _LISTDEPLOYMENTSREQUEST._serialized_start = 39438 + _LISTDEPLOYMENTSREQUEST._serialized_end = 39546 + _LISTDEPLOYMENTSRESPONSE._serialized_start = 39548 + _LISTDEPLOYMENTSRESPONSE._serialized_end = 39667 + _SETCURRENTDEPLOYMENTREQUEST._serialized_start = 39670 + _SETCURRENTDEPLOYMENTREQUEST._serialized_end = 39875 + _SETCURRENTDEPLOYMENTRESPONSE._serialized_start = 39878 + _SETCURRENTDEPLOYMENTRESPONSE._serialized_end = 40063 + _SETWORKERDEPLOYMENTCURRENTVERSIONREQUEST._serialized_start = 40066 + _SETWORKERDEPLOYMENTCURRENTVERSIONREQUEST._serialized_end = 40295 + _SETWORKERDEPLOYMENTCURRENTVERSIONRESPONSE._serialized_start = 40298 + _SETWORKERDEPLOYMENTCURRENTVERSIONRESPONSE._serialized_end = 40489 + _SETWORKERDEPLOYMENTRAMPINGVERSIONREQUEST._serialized_start = 40492 + _SETWORKERDEPLOYMENTRAMPINGVERSIONREQUEST._serialized_end = 40741 + _SETWORKERDEPLOYMENTRAMPINGVERSIONRESPONSE._serialized_start = 40744 + _SETWORKERDEPLOYMENTRAMPINGVERSIONRESPONSE._serialized_end = 40968 + _CREATEWORKERDEPLOYMENTREQUEST._serialized_start = 40970 + _CREATEWORKERDEPLOYMENTREQUEST._serialized_end = 41083 + _CREATEWORKERDEPLOYMENTRESPONSE._serialized_start = 41085 + _CREATEWORKERDEPLOYMENTRESPONSE._serialized_end = 41141 + _LISTWORKERDEPLOYMENTSREQUEST._serialized_start = 41143 + _LISTWORKERDEPLOYMENTSREQUEST._serialized_end = 41236 + _LISTWORKERDEPLOYMENTSRESPONSE._serialized_start = 41239 + _LISTWORKERDEPLOYMENTSRESPONSE._serialized_end = 41910 + _LISTWORKERDEPLOYMENTSRESPONSE_WORKERDEPLOYMENTSUMMARY._serialized_start = 41414 + _LISTWORKERDEPLOYMENTSRESPONSE_WORKERDEPLOYMENTSUMMARY._serialized_end = 41910 + _CREATEWORKERDEPLOYMENTVERSIONREQUEST._serialized_start = 41913 + _CREATEWORKERDEPLOYMENTVERSIONREQUEST._serialized_end = 42153 + _CREATEWORKERDEPLOYMENTVERSIONRESPONSE._serialized_start = 42155 + _CREATEWORKERDEPLOYMENTVERSIONRESPONSE._serialized_end = 42194 + _DELETEWORKERDEPLOYMENTVERSIONREQUEST._serialized_start = 42197 + _DELETEWORKERDEPLOYMENTVERSIONREQUEST._serialized_end = 42397 + _DELETEWORKERDEPLOYMENTVERSIONRESPONSE._serialized_start = 42399 + _DELETEWORKERDEPLOYMENTVERSIONRESPONSE._serialized_end = 42438 + _DELETEWORKERDEPLOYMENTREQUEST._serialized_start = 42440 + _DELETEWORKERDEPLOYMENTREQUEST._serialized_end = 42533 + _DELETEWORKERDEPLOYMENTRESPONSE._serialized_start = 42535 + _DELETEWORKERDEPLOYMENTRESPONSE._serialized_end = 42567 + _UPDATEWORKERDEPLOYMENTVERSIONCOMPUTECONFIGREQUEST._serialized_start = 42570 + _UPDATEWORKERDEPLOYMENTVERSIONCOMPUTECONFIGREQUEST._serialized_end = 43086 + _UPDATEWORKERDEPLOYMENTVERSIONCOMPUTECONFIGREQUEST_COMPUTECONFIGSCALINGGROUPSENTRY._serialized_start = 42963 + _UPDATEWORKERDEPLOYMENTVERSIONCOMPUTECONFIGREQUEST_COMPUTECONFIGSCALINGGROUPSENTRY._serialized_end = 43086 + _UPDATEWORKERDEPLOYMENTVERSIONCOMPUTECONFIGRESPONSE._serialized_start = 43088 + _UPDATEWORKERDEPLOYMENTVERSIONCOMPUTECONFIGRESPONSE._serialized_end = 43140 + _VALIDATEWORKERDEPLOYMENTVERSIONCOMPUTECONFIGREQUEST._serialized_start = 43143 + _VALIDATEWORKERDEPLOYMENTVERSIONCOMPUTECONFIGREQUEST._serialized_end = 43643 + _VALIDATEWORKERDEPLOYMENTVERSIONCOMPUTECONFIGREQUEST_COMPUTECONFIGSCALINGGROUPSENTRY._serialized_start = 42963 + _VALIDATEWORKERDEPLOYMENTVERSIONCOMPUTECONFIGREQUEST_COMPUTECONFIGSCALINGGROUPSENTRY._serialized_end = 43086 + _VALIDATEWORKERDEPLOYMENTVERSIONCOMPUTECONFIGRESPONSE._serialized_start = 43645 + _VALIDATEWORKERDEPLOYMENTVERSIONCOMPUTECONFIGRESPONSE._serialized_end = 43699 + _UPDATEWORKERDEPLOYMENTVERSIONMETADATAREQUEST._serialized_start = 43702 + _UPDATEWORKERDEPLOYMENTVERSIONMETADATAREQUEST._serialized_end = 44120 + _UPDATEWORKERDEPLOYMENTVERSIONMETADATAREQUEST_UPSERTENTRIESENTRY._serialized_start = 44035 _UPDATEWORKERDEPLOYMENTVERSIONMETADATAREQUEST_UPSERTENTRIESENTRY._serialized_end = ( - 42838 + 44120 ) - _UPDATEWORKERDEPLOYMENTVERSIONMETADATARESPONSE._serialized_start = 42840 - _UPDATEWORKERDEPLOYMENTVERSIONMETADATARESPONSE._serialized_end = 42950 - _SETWORKERDEPLOYMENTMANAGERREQUEST._serialized_start = 42953 - _SETWORKERDEPLOYMENTMANAGERREQUEST._serialized_end = 43142 - _SETWORKERDEPLOYMENTMANAGERRESPONSE._serialized_start = 43144 - _SETWORKERDEPLOYMENTMANAGERRESPONSE._serialized_end = 43243 - _GETCURRENTDEPLOYMENTREQUEST._serialized_start = 43245 - _GETCURRENTDEPLOYMENTREQUEST._serialized_end = 43314 - _GETCURRENTDEPLOYMENTRESPONSE._serialized_start = 43316 - _GETCURRENTDEPLOYMENTRESPONSE._serialized_end = 43423 - _GETDEPLOYMENTREACHABILITYREQUEST._serialized_start = 43425 - _GETDEPLOYMENTREACHABILITYREQUEST._serialized_end = 43538 - _GETDEPLOYMENTREACHABILITYRESPONSE._serialized_start = 43541 - _GETDEPLOYMENTREACHABILITYRESPONSE._serialized_end = 43768 - _CREATEWORKFLOWRULEREQUEST._serialized_start = 43771 - _CREATEWORKFLOWRULEREQUEST._serialized_end = 43951 - _CREATEWORKFLOWRULERESPONSE._serialized_start = 43953 - _CREATEWORKFLOWRULERESPONSE._serialized_end = 44048 - _DESCRIBEWORKFLOWRULEREQUEST._serialized_start = 44050 - _DESCRIBEWORKFLOWRULEREQUEST._serialized_end = 44115 - _DESCRIBEWORKFLOWRULERESPONSE._serialized_start = 44117 - _DESCRIBEWORKFLOWRULERESPONSE._serialized_end = 44198 - _DELETEWORKFLOWRULEREQUEST._serialized_start = 44200 - _DELETEWORKFLOWRULEREQUEST._serialized_end = 44263 - _DELETEWORKFLOWRULERESPONSE._serialized_start = 44265 - _DELETEWORKFLOWRULERESPONSE._serialized_end = 44293 - _LISTWORKFLOWRULESREQUEST._serialized_start = 44295 - _LISTWORKFLOWRULESREQUEST._serialized_end = 44365 - _LISTWORKFLOWRULESRESPONSE._serialized_start = 44367 - _LISTWORKFLOWRULESRESPONSE._serialized_end = 44471 - _TRIGGERWORKFLOWRULEREQUEST._serialized_start = 44474 - _TRIGGERWORKFLOWRULEREQUEST._serialized_end = 44680 - _TRIGGERWORKFLOWRULERESPONSE._serialized_start = 44682 - _TRIGGERWORKFLOWRULERESPONSE._serialized_end = 44728 - _RECORDWORKERHEARTBEATREQUEST._serialized_start = 44731 - _RECORDWORKERHEARTBEATREQUEST._serialized_end = 44886 - _RECORDWORKERHEARTBEATRESPONSE._serialized_start = 44888 - _RECORDWORKERHEARTBEATRESPONSE._serialized_end = 44919 - _LISTWORKERSREQUEST._serialized_start = 44921 - _LISTWORKERSREQUEST._serialized_end = 45019 - _LISTWORKERSRESPONSE._serialized_start = 45022 - _LISTWORKERSRESPONSE._serialized_end = 45187 - _UPDATETASKQUEUECONFIGREQUEST._serialized_start = 45190 - _UPDATETASKQUEUECONFIGREQUEST._serialized_end = 45915 - _UPDATETASKQUEUECONFIGREQUEST_RATELIMITUPDATE._serialized_start = 45757 - _UPDATETASKQUEUECONFIGREQUEST_RATELIMITUPDATE._serialized_end = 45848 + _UPDATEWORKERDEPLOYMENTVERSIONMETADATARESPONSE._serialized_start = 44122 + _UPDATEWORKERDEPLOYMENTVERSIONMETADATARESPONSE._serialized_end = 44232 + _SETWORKERDEPLOYMENTMANAGERREQUEST._serialized_start = 44235 + _SETWORKERDEPLOYMENTMANAGERREQUEST._serialized_end = 44424 + _SETWORKERDEPLOYMENTMANAGERRESPONSE._serialized_start = 44426 + _SETWORKERDEPLOYMENTMANAGERRESPONSE._serialized_end = 44525 + _GETCURRENTDEPLOYMENTREQUEST._serialized_start = 44527 + _GETCURRENTDEPLOYMENTREQUEST._serialized_end = 44596 + _GETCURRENTDEPLOYMENTRESPONSE._serialized_start = 44598 + _GETCURRENTDEPLOYMENTRESPONSE._serialized_end = 44705 + _GETDEPLOYMENTREACHABILITYREQUEST._serialized_start = 44707 + _GETDEPLOYMENTREACHABILITYREQUEST._serialized_end = 44820 + _GETDEPLOYMENTREACHABILITYRESPONSE._serialized_start = 44823 + _GETDEPLOYMENTREACHABILITYRESPONSE._serialized_end = 45050 + _CREATEWORKFLOWRULEREQUEST._serialized_start = 45053 + _CREATEWORKFLOWRULEREQUEST._serialized_end = 45233 + _CREATEWORKFLOWRULERESPONSE._serialized_start = 45235 + _CREATEWORKFLOWRULERESPONSE._serialized_end = 45330 + _DESCRIBEWORKFLOWRULEREQUEST._serialized_start = 45332 + _DESCRIBEWORKFLOWRULEREQUEST._serialized_end = 45397 + _DESCRIBEWORKFLOWRULERESPONSE._serialized_start = 45399 + _DESCRIBEWORKFLOWRULERESPONSE._serialized_end = 45480 + _DELETEWORKFLOWRULEREQUEST._serialized_start = 45482 + _DELETEWORKFLOWRULEREQUEST._serialized_end = 45545 + _DELETEWORKFLOWRULERESPONSE._serialized_start = 45547 + _DELETEWORKFLOWRULERESPONSE._serialized_end = 45575 + _LISTWORKFLOWRULESREQUEST._serialized_start = 45577 + _LISTWORKFLOWRULESREQUEST._serialized_end = 45647 + _LISTWORKFLOWRULESRESPONSE._serialized_start = 45649 + _LISTWORKFLOWRULESRESPONSE._serialized_end = 45753 + _TRIGGERWORKFLOWRULEREQUEST._serialized_start = 45756 + _TRIGGERWORKFLOWRULEREQUEST._serialized_end = 45962 + _TRIGGERWORKFLOWRULERESPONSE._serialized_start = 45964 + _TRIGGERWORKFLOWRULERESPONSE._serialized_end = 46010 + _RECORDWORKERHEARTBEATREQUEST._serialized_start = 46013 + _RECORDWORKERHEARTBEATREQUEST._serialized_end = 46168 + _RECORDWORKERHEARTBEATRESPONSE._serialized_start = 46170 + _RECORDWORKERHEARTBEATRESPONSE._serialized_end = 46201 + _LISTWORKERSREQUEST._serialized_start = 46204 + _LISTWORKERSREQUEST._serialized_end = 46334 + _LISTWORKERSRESPONSE._serialized_start = 46337 + _LISTWORKERSRESPONSE._serialized_end = 46502 + _UPDATETASKQUEUECONFIGREQUEST._serialized_start = 46505 + _UPDATETASKQUEUECONFIGREQUEST._serialized_end = 47230 + _UPDATETASKQUEUECONFIGREQUEST_RATELIMITUPDATE._serialized_start = 47072 + _UPDATETASKQUEUECONFIGREQUEST_RATELIMITUPDATE._serialized_end = 47163 _UPDATETASKQUEUECONFIGREQUEST_SETFAIRNESSWEIGHTOVERRIDESENTRY._serialized_start = ( - 45850 + 47165 ) _UPDATETASKQUEUECONFIGREQUEST_SETFAIRNESSWEIGHTOVERRIDESENTRY._serialized_end = ( - 45915 + 47230 ) - _UPDATETASKQUEUECONFIGRESPONSE._serialized_start = 45917 - _UPDATETASKQUEUECONFIGRESPONSE._serialized_end = 46008 - _FETCHWORKERCONFIGREQUEST._serialized_start = 46011 - _FETCHWORKERCONFIGREQUEST._serialized_end = 46169 - _FETCHWORKERCONFIGRESPONSE._serialized_start = 46171 - _FETCHWORKERCONFIGRESPONSE._serialized_end = 46256 - _UPDATEWORKERCONFIGREQUEST._serialized_start = 46259 - _UPDATEWORKERCONFIGREQUEST._serialized_end = 46525 - _UPDATEWORKERCONFIGRESPONSE._serialized_start = 46527 - _UPDATEWORKERCONFIGRESPONSE._serialized_end = 46627 - _DESCRIBEWORKERREQUEST._serialized_start = 46629 - _DESCRIBEWORKERREQUEST._serialized_end = 46700 - _DESCRIBEWORKERRESPONSE._serialized_start = 46702 - _DESCRIBEWORKERRESPONSE._serialized_end = 46783 - _PAUSEWORKFLOWEXECUTIONREQUEST._serialized_start = 46786 - _PAUSEWORKFLOWEXECUTIONREQUEST._serialized_end = 46927 - _PAUSEWORKFLOWEXECUTIONRESPONSE._serialized_start = 46929 - _PAUSEWORKFLOWEXECUTIONRESPONSE._serialized_end = 46961 - _UNPAUSEWORKFLOWEXECUTIONREQUEST._serialized_start = 46964 - _UNPAUSEWORKFLOWEXECUTIONREQUEST._serialized_end = 47107 - _UNPAUSEWORKFLOWEXECUTIONRESPONSE._serialized_start = 47109 - _UNPAUSEWORKFLOWEXECUTIONRESPONSE._serialized_end = 47143 - _STARTACTIVITYEXECUTIONREQUEST._serialized_start = 47146 - _STARTACTIVITYEXECUTIONREQUEST._serialized_end = 48323 - _STARTACTIVITYEXECUTIONRESPONSE._serialized_start = 48325 - _STARTACTIVITYEXECUTIONRESPONSE._serialized_end = 48434 - _DESCRIBEACTIVITYEXECUTIONREQUEST._serialized_start = 48437 - _DESCRIBEACTIVITYEXECUTIONREQUEST._serialized_end = 48600 - _DESCRIBEACTIVITYEXECUTIONRESPONSE._serialized_start = 48603 - _DESCRIBEACTIVITYEXECUTIONRESPONSE._serialized_end = 48919 - _POLLACTIVITYEXECUTIONREQUEST._serialized_start = 48921 - _POLLACTIVITYEXECUTIONREQUEST._serialized_end = 49007 - _POLLACTIVITYEXECUTIONRESPONSE._serialized_start = 49009 - _POLLACTIVITYEXECUTIONRESPONSE._serialized_end = 49125 - _LISTACTIVITYEXECUTIONSREQUEST._serialized_start = 49127 - _LISTACTIVITYEXECUTIONSREQUEST._serialized_end = 49236 - _LISTACTIVITYEXECUTIONSRESPONSE._serialized_start = 49239 - _LISTACTIVITYEXECUTIONSRESPONSE._serialized_end = 49369 - _STARTNEXUSOPERATIONEXECUTIONREQUEST._serialized_start = 49372 - _STARTNEXUSOPERATIONEXECUTIONREQUEST._serialized_end = 50221 - _STARTNEXUSOPERATIONEXECUTIONREQUEST_NEXUSHEADERENTRY._serialized_start = 50171 - _STARTNEXUSOPERATIONEXECUTIONREQUEST_NEXUSHEADERENTRY._serialized_end = 50221 - _STARTNEXUSOPERATIONEXECUTIONRESPONSE._serialized_start = 50223 - _STARTNEXUSOPERATIONEXECUTIONRESPONSE._serialized_end = 50294 - _DESCRIBENEXUSOPERATIONEXECUTIONREQUEST._serialized_start = 50297 - _DESCRIBENEXUSOPERATIONEXECUTIONREQUEST._serialized_end = 50467 - _DESCRIBENEXUSOPERATIONEXECUTIONRESPONSE._serialized_start = 50470 - _DESCRIBENEXUSOPERATIONEXECUTIONRESPONSE._serialized_end = 50781 - _POLLNEXUSOPERATIONEXECUTIONREQUEST._serialized_start = 50784 - _POLLNEXUSOPERATIONEXECUTIONREQUEST._serialized_end = 50945 - _POLLNEXUSOPERATIONEXECUTIONRESPONSE._serialized_start = 50948 - _POLLNEXUSOPERATIONEXECUTIONRESPONSE._serialized_end = 51209 - _LISTNEXUSOPERATIONEXECUTIONSREQUEST._serialized_start = 51211 - _LISTNEXUSOPERATIONEXECUTIONSREQUEST._serialized_end = 51326 - _LISTNEXUSOPERATIONEXECUTIONSRESPONSE._serialized_start = 51329 - _LISTNEXUSOPERATIONEXECUTIONSRESPONSE._serialized_end = 51468 - _COUNTACTIVITYEXECUTIONSREQUEST._serialized_start = 51470 - _COUNTACTIVITYEXECUTIONSREQUEST._serialized_end = 51536 - _COUNTACTIVITYEXECUTIONSRESPONSE._serialized_start = 51539 - _COUNTACTIVITYEXECUTIONSRESPONSE._serialized_end = 51776 - _COUNTACTIVITYEXECUTIONSRESPONSE_AGGREGATIONGROUP._serialized_start = 19653 - _COUNTACTIVITYEXECUTIONSRESPONSE_AGGREGATIONGROUP._serialized_end = 19741 - _COUNTNEXUSOPERATIONEXECUTIONSREQUEST._serialized_start = 51778 - _COUNTNEXUSOPERATIONEXECUTIONSREQUEST._serialized_end = 51850 - _COUNTNEXUSOPERATIONEXECUTIONSRESPONSE._serialized_start = 51853 - _COUNTNEXUSOPERATIONEXECUTIONSRESPONSE._serialized_end = 52102 - _COUNTNEXUSOPERATIONEXECUTIONSRESPONSE_AGGREGATIONGROUP._serialized_start = 19653 - _COUNTNEXUSOPERATIONEXECUTIONSRESPONSE_AGGREGATIONGROUP._serialized_end = 19741 - _REQUESTCANCELACTIVITYEXECUTIONREQUEST._serialized_start = 52105 - _REQUESTCANCELACTIVITYEXECUTIONREQUEST._serialized_end = 52254 - _REQUESTCANCELACTIVITYEXECUTIONRESPONSE._serialized_start = 52256 - _REQUESTCANCELACTIVITYEXECUTIONRESPONSE._serialized_end = 52296 - _TERMINATEACTIVITYEXECUTIONREQUEST._serialized_start = 52299 - _TERMINATEACTIVITYEXECUTIONREQUEST._serialized_end = 52444 - _TERMINATEACTIVITYEXECUTIONRESPONSE._serialized_start = 52446 - _TERMINATEACTIVITYEXECUTIONRESPONSE._serialized_end = 52482 - _DELETEACTIVITYEXECUTIONREQUEST._serialized_start = 52484 - _DELETEACTIVITYEXECUTIONREQUEST._serialized_end = 52572 - _DELETEACTIVITYEXECUTIONRESPONSE._serialized_start = 52574 - _DELETEACTIVITYEXECUTIONRESPONSE._serialized_end = 52607 - _REQUESTCANCELNEXUSOPERATIONEXECUTIONREQUEST._serialized_start = 52610 - _REQUESTCANCELNEXUSOPERATIONEXECUTIONREQUEST._serialized_end = 52766 - _REQUESTCANCELNEXUSOPERATIONEXECUTIONRESPONSE._serialized_start = 52768 - _REQUESTCANCELNEXUSOPERATIONEXECUTIONRESPONSE._serialized_end = 52814 - _TERMINATENEXUSOPERATIONEXECUTIONREQUEST._serialized_start = 52817 - _TERMINATENEXUSOPERATIONEXECUTIONREQUEST._serialized_end = 52969 - _TERMINATENEXUSOPERATIONEXECUTIONRESPONSE._serialized_start = 52971 - _TERMINATENEXUSOPERATIONEXECUTIONRESPONSE._serialized_end = 53013 - _DELETENEXUSOPERATIONEXECUTIONREQUEST._serialized_start = 53015 - _DELETENEXUSOPERATIONEXECUTIONREQUEST._serialized_end = 53110 - _DELETENEXUSOPERATIONEXECUTIONRESPONSE._serialized_start = 53112 - _DELETENEXUSOPERATIONEXECUTIONRESPONSE._serialized_end = 53151 + _UPDATETASKQUEUECONFIGRESPONSE._serialized_start = 47232 + _UPDATETASKQUEUECONFIGRESPONSE._serialized_end = 47323 + _FETCHWORKERCONFIGREQUEST._serialized_start = 47326 + _FETCHWORKERCONFIGREQUEST._serialized_end = 47484 + _FETCHWORKERCONFIGRESPONSE._serialized_start = 47486 + _FETCHWORKERCONFIGRESPONSE._serialized_end = 47571 + _UPDATEWORKERCONFIGREQUEST._serialized_start = 47574 + _UPDATEWORKERCONFIGREQUEST._serialized_end = 47840 + _UPDATEWORKERCONFIGRESPONSE._serialized_start = 47842 + _UPDATEWORKERCONFIGRESPONSE._serialized_end = 47942 + _DESCRIBEWORKERREQUEST._serialized_start = 47944 + _DESCRIBEWORKERREQUEST._serialized_end = 48015 + _DESCRIBEWORKERRESPONSE._serialized_start = 48017 + _DESCRIBEWORKERRESPONSE._serialized_end = 48098 + _PAUSEWORKFLOWEXECUTIONREQUEST._serialized_start = 48101 + _PAUSEWORKFLOWEXECUTIONREQUEST._serialized_end = 48242 + _PAUSEWORKFLOWEXECUTIONRESPONSE._serialized_start = 48244 + _PAUSEWORKFLOWEXECUTIONRESPONSE._serialized_end = 48276 + _UNPAUSEWORKFLOWEXECUTIONREQUEST._serialized_start = 48279 + _UNPAUSEWORKFLOWEXECUTIONREQUEST._serialized_end = 48422 + _UNPAUSEWORKFLOWEXECUTIONRESPONSE._serialized_start = 48424 + _UNPAUSEWORKFLOWEXECUTIONRESPONSE._serialized_end = 48458 + _STARTACTIVITYEXECUTIONREQUEST._serialized_start = 48461 + _STARTACTIVITYEXECUTIONREQUEST._serialized_end = 49638 + _STARTACTIVITYEXECUTIONRESPONSE._serialized_start = 49640 + _STARTACTIVITYEXECUTIONRESPONSE._serialized_end = 49749 + _DESCRIBEACTIVITYEXECUTIONREQUEST._serialized_start = 49752 + _DESCRIBEACTIVITYEXECUTIONREQUEST._serialized_end = 49915 + _DESCRIBEACTIVITYEXECUTIONRESPONSE._serialized_start = 49918 + _DESCRIBEACTIVITYEXECUTIONRESPONSE._serialized_end = 50234 + _POLLACTIVITYEXECUTIONREQUEST._serialized_start = 50236 + _POLLACTIVITYEXECUTIONREQUEST._serialized_end = 50322 + _POLLACTIVITYEXECUTIONRESPONSE._serialized_start = 50324 + _POLLACTIVITYEXECUTIONRESPONSE._serialized_end = 50440 + _LISTACTIVITYEXECUTIONSREQUEST._serialized_start = 50442 + _LISTACTIVITYEXECUTIONSREQUEST._serialized_end = 50551 + _LISTACTIVITYEXECUTIONSRESPONSE._serialized_start = 50554 + _LISTACTIVITYEXECUTIONSRESPONSE._serialized_end = 50684 + _STARTNEXUSOPERATIONEXECUTIONREQUEST._serialized_start = 50687 + _STARTNEXUSOPERATIONEXECUTIONREQUEST._serialized_end = 51536 + _STARTNEXUSOPERATIONEXECUTIONREQUEST_NEXUSHEADERENTRY._serialized_start = 51486 + _STARTNEXUSOPERATIONEXECUTIONREQUEST_NEXUSHEADERENTRY._serialized_end = 51536 + _STARTNEXUSOPERATIONEXECUTIONRESPONSE._serialized_start = 51538 + _STARTNEXUSOPERATIONEXECUTIONRESPONSE._serialized_end = 51609 + _DESCRIBENEXUSOPERATIONEXECUTIONREQUEST._serialized_start = 51612 + _DESCRIBENEXUSOPERATIONEXECUTIONREQUEST._serialized_end = 51782 + _DESCRIBENEXUSOPERATIONEXECUTIONRESPONSE._serialized_start = 51785 + _DESCRIBENEXUSOPERATIONEXECUTIONRESPONSE._serialized_end = 52096 + _POLLNEXUSOPERATIONEXECUTIONREQUEST._serialized_start = 52099 + _POLLNEXUSOPERATIONEXECUTIONREQUEST._serialized_end = 52260 + _POLLNEXUSOPERATIONEXECUTIONRESPONSE._serialized_start = 52263 + _POLLNEXUSOPERATIONEXECUTIONRESPONSE._serialized_end = 52524 + _LISTNEXUSOPERATIONEXECUTIONSREQUEST._serialized_start = 52526 + _LISTNEXUSOPERATIONEXECUTIONSREQUEST._serialized_end = 52641 + _LISTNEXUSOPERATIONEXECUTIONSRESPONSE._serialized_start = 52644 + _LISTNEXUSOPERATIONEXECUTIONSRESPONSE._serialized_end = 52783 + _COUNTACTIVITYEXECUTIONSREQUEST._serialized_start = 52785 + _COUNTACTIVITYEXECUTIONSREQUEST._serialized_end = 52851 + _COUNTACTIVITYEXECUTIONSRESPONSE._serialized_start = 52854 + _COUNTACTIVITYEXECUTIONSRESPONSE._serialized_end = 53091 + _COUNTACTIVITYEXECUTIONSRESPONSE_AGGREGATIONGROUP._serialized_start = 19679 + _COUNTACTIVITYEXECUTIONSRESPONSE_AGGREGATIONGROUP._serialized_end = 19767 + _COUNTNEXUSOPERATIONEXECUTIONSREQUEST._serialized_start = 53093 + _COUNTNEXUSOPERATIONEXECUTIONSREQUEST._serialized_end = 53165 + _COUNTNEXUSOPERATIONEXECUTIONSRESPONSE._serialized_start = 53168 + _COUNTNEXUSOPERATIONEXECUTIONSRESPONSE._serialized_end = 53417 + _COUNTNEXUSOPERATIONEXECUTIONSRESPONSE_AGGREGATIONGROUP._serialized_start = 19679 + _COUNTNEXUSOPERATIONEXECUTIONSRESPONSE_AGGREGATIONGROUP._serialized_end = 19767 + _REQUESTCANCELACTIVITYEXECUTIONREQUEST._serialized_start = 53420 + _REQUESTCANCELACTIVITYEXECUTIONREQUEST._serialized_end = 53569 + _REQUESTCANCELACTIVITYEXECUTIONRESPONSE._serialized_start = 53571 + _REQUESTCANCELACTIVITYEXECUTIONRESPONSE._serialized_end = 53611 + _TERMINATEACTIVITYEXECUTIONREQUEST._serialized_start = 53614 + _TERMINATEACTIVITYEXECUTIONREQUEST._serialized_end = 53759 + _TERMINATEACTIVITYEXECUTIONRESPONSE._serialized_start = 53761 + _TERMINATEACTIVITYEXECUTIONRESPONSE._serialized_end = 53797 + _DELETEACTIVITYEXECUTIONREQUEST._serialized_start = 53799 + _DELETEACTIVITYEXECUTIONREQUEST._serialized_end = 53887 + _DELETEACTIVITYEXECUTIONRESPONSE._serialized_start = 53889 + _DELETEACTIVITYEXECUTIONRESPONSE._serialized_end = 53922 + _REQUESTCANCELNEXUSOPERATIONEXECUTIONREQUEST._serialized_start = 53925 + _REQUESTCANCELNEXUSOPERATIONEXECUTIONREQUEST._serialized_end = 54081 + _REQUESTCANCELNEXUSOPERATIONEXECUTIONRESPONSE._serialized_start = 54083 + _REQUESTCANCELNEXUSOPERATIONEXECUTIONRESPONSE._serialized_end = 54129 + _TERMINATENEXUSOPERATIONEXECUTIONREQUEST._serialized_start = 54132 + _TERMINATENEXUSOPERATIONEXECUTIONREQUEST._serialized_end = 54284 + _TERMINATENEXUSOPERATIONEXECUTIONRESPONSE._serialized_start = 54286 + _TERMINATENEXUSOPERATIONEXECUTIONRESPONSE._serialized_end = 54328 + _DELETENEXUSOPERATIONEXECUTIONREQUEST._serialized_start = 54330 + _DELETENEXUSOPERATIONEXECUTIONREQUEST._serialized_end = 54425 + _DELETENEXUSOPERATIONEXECUTIONRESPONSE._serialized_start = 54427 + _DELETENEXUSOPERATIONEXECUTIONRESPONSE._serialized_end = 54466 # @@protoc_insertion_point(module_scope) diff --git a/temporalio/api/workflowservice/v1/request_response_pb2.pyi b/temporalio/api/workflowservice/v1/request_response_pb2.pyi index 98b0c046e..726d9567f 100644 --- a/temporalio/api/workflowservice/v1/request_response_pb2.pyi +++ b/temporalio/api/workflowservice/v1/request_response_pb2.pyi @@ -265,17 +265,32 @@ class DescribeNamespaceRequest(google.protobuf.message.Message): NAMESPACE_FIELD_NUMBER: builtins.int ID_FIELD_NUMBER: builtins.int + WEAK_CONSISTENCY_FIELD_NUMBER: builtins.int namespace: builtins.str id: builtins.str + weak_consistency: builtins.bool + """If true, the server may serve the response from an eventually-consistent + source instead of reading through to persistence. Defaults to false, + which preserves read-after-write consistency. SDKs should set this when + fetching namespace capabilities on worker/client startup. + """ def __init__( self, *, namespace: builtins.str = ..., id: builtins.str = ..., + weak_consistency: builtins.bool = ..., ) -> None: ... def ClearField( self, - field_name: typing_extensions.Literal["id", b"id", "namespace", b"namespace"], + field_name: typing_extensions.Literal[ + "id", + b"id", + "namespace", + b"namespace", + "weak_consistency", + b"weak_consistency", + ], ) -> None: ... global___DescribeNamespaceRequest = DescribeNamespaceRequest @@ -7977,7 +7992,9 @@ class ExecuteMultiOperationResponse(google.protobuf.message.Message): global___ExecuteMultiOperationResponse = ExecuteMultiOperationResponse class UpdateActivityOptionsRequest(google.protobuf.message.Message): - """NOTE: keep in sync with temporalio.api.batch.v1.BatchOperationUpdateActivityOptions""" + """NOTE: keep in sync with temporalio.api.batch.v1.BatchOperationUpdateActivityOptions + Deprecated. Use `UpdateActivityExecutionOptionsRequest`. + """ DESCRIPTOR: google.protobuf.descriptor.Descriptor @@ -8014,7 +8031,7 @@ class UpdateActivityOptionsRequest(google.protobuf.message.Message): restore_original: builtins.bool """If set, the activity options will be restored to the default. Default options are then options activity was created with. - They are part of the first SCHEDULE event. + They are part of the first schedule event. This flag cannot be combined with any other option; if you supply restore_original together with other options, the request will be rejected. """ @@ -8082,7 +8099,96 @@ class UpdateActivityOptionsRequest(google.protobuf.message.Message): global___UpdateActivityOptionsRequest = UpdateActivityOptionsRequest +class UpdateActivityExecutionOptionsRequest(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + NAMESPACE_FIELD_NUMBER: builtins.int + WORKFLOW_ID_FIELD_NUMBER: builtins.int + ACTIVITY_ID_FIELD_NUMBER: builtins.int + RUN_ID_FIELD_NUMBER: builtins.int + IDENTITY_FIELD_NUMBER: builtins.int + ACTIVITY_OPTIONS_FIELD_NUMBER: builtins.int + UPDATE_MASK_FIELD_NUMBER: builtins.int + RESTORE_ORIGINAL_FIELD_NUMBER: builtins.int + RESOURCE_ID_FIELD_NUMBER: builtins.int + namespace: builtins.str + """Namespace of the workflow which scheduled this activity""" + workflow_id: builtins.str + """If provided, targets a workflow activity for the given workflow ID. + If empty, targets a standalone activity. + """ + activity_id: builtins.str + """The ID of the activity to target.""" + run_id: builtins.str + """Run ID of the workflow or standalone activity.""" + identity: builtins.str + """The identity of the client who initiated this request""" + @property + def activity_options( + self, + ) -> temporalio.api.activity.v1.message_pb2.ActivityOptions: + """Activity options. Partial updates are accepted and controlled by update_mask""" + @property + def update_mask(self) -> google.protobuf.field_mask_pb2.FieldMask: + """Controls which fields from `activity_options` will be applied""" + restore_original: builtins.bool + """If set, the activity options will be restored to the default. + Default options are then options activity was created with. + They are part of the first schedule event. + This flag cannot be combined with any other option; if you supply + restore_original together with other options, the request will be rejected. + """ + resource_id: builtins.str + """Resource ID for routing. Contains "workflow:{workflow_id}" for workflow activities or "activity:{activity_id}" for standalone activities.""" + def __init__( + self, + *, + namespace: builtins.str = ..., + workflow_id: builtins.str = ..., + activity_id: builtins.str = ..., + run_id: builtins.str = ..., + identity: builtins.str = ..., + activity_options: temporalio.api.activity.v1.message_pb2.ActivityOptions + | None = ..., + update_mask: google.protobuf.field_mask_pb2.FieldMask | None = ..., + restore_original: builtins.bool = ..., + resource_id: builtins.str = ..., + ) -> None: ... + def HasField( + self, + field_name: typing_extensions.Literal[ + "activity_options", b"activity_options", "update_mask", b"update_mask" + ], + ) -> builtins.bool: ... + def ClearField( + self, + field_name: typing_extensions.Literal[ + "activity_id", + b"activity_id", + "activity_options", + b"activity_options", + "identity", + b"identity", + "namespace", + b"namespace", + "resource_id", + b"resource_id", + "restore_original", + b"restore_original", + "run_id", + b"run_id", + "update_mask", + b"update_mask", + "workflow_id", + b"workflow_id", + ], + ) -> None: ... + +global___UpdateActivityExecutionOptionsRequest = UpdateActivityExecutionOptionsRequest + class UpdateActivityOptionsResponse(google.protobuf.message.Message): + """Deprecated. Use `UpdateActivityExecutionOptionsResponse`.""" + DESCRIPTOR: google.protobuf.descriptor.Descriptor ACTIVITY_OPTIONS_FIELD_NUMBER: builtins.int @@ -8108,7 +8214,35 @@ class UpdateActivityOptionsResponse(google.protobuf.message.Message): global___UpdateActivityOptionsResponse = UpdateActivityOptionsResponse +class UpdateActivityExecutionOptionsResponse(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + ACTIVITY_OPTIONS_FIELD_NUMBER: builtins.int + @property + def activity_options( + self, + ) -> temporalio.api.activity.v1.message_pb2.ActivityOptions: + """Activity options after an update""" + def __init__( + self, + *, + activity_options: temporalio.api.activity.v1.message_pb2.ActivityOptions + | None = ..., + ) -> None: ... + def HasField( + self, + field_name: typing_extensions.Literal["activity_options", b"activity_options"], + ) -> builtins.bool: ... + def ClearField( + self, + field_name: typing_extensions.Literal["activity_options", b"activity_options"], + ) -> None: ... + +global___UpdateActivityExecutionOptionsResponse = UpdateActivityExecutionOptionsResponse + class PauseActivityRequest(google.protobuf.message.Message): + """Deprecated. Use `PauseActivityExecutionRequest`.""" + DESCRIPTOR: google.protobuf.descriptor.Descriptor NAMESPACE_FIELD_NUMBER: builtins.int @@ -8117,6 +8251,7 @@ class PauseActivityRequest(google.protobuf.message.Message): ID_FIELD_NUMBER: builtins.int TYPE_FIELD_NUMBER: builtins.int REASON_FIELD_NUMBER: builtins.int + REQUEST_ID_FIELD_NUMBER: builtins.int namespace: builtins.str """Namespace of the workflow which scheduled this activity.""" @property @@ -8132,6 +8267,8 @@ class PauseActivityRequest(google.protobuf.message.Message): """ reason: builtins.str """Reason to pause the activity.""" + request_id: builtins.str + """Used to de-dupe pause requests.""" def __init__( self, *, @@ -8141,6 +8278,7 @@ class PauseActivityRequest(google.protobuf.message.Message): id: builtins.str = ..., type: builtins.str = ..., reason: builtins.str = ..., + request_id: builtins.str = ..., ) -> None: ... def HasField( self, @@ -8170,6 +8308,8 @@ class PauseActivityRequest(google.protobuf.message.Message): b"namespace", "reason", b"reason", + "request_id", + b"request_id", "type", b"type", ], @@ -8180,7 +8320,74 @@ class PauseActivityRequest(google.protobuf.message.Message): global___PauseActivityRequest = PauseActivityRequest +class PauseActivityExecutionRequest(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + NAMESPACE_FIELD_NUMBER: builtins.int + WORKFLOW_ID_FIELD_NUMBER: builtins.int + ACTIVITY_ID_FIELD_NUMBER: builtins.int + RUN_ID_FIELD_NUMBER: builtins.int + IDENTITY_FIELD_NUMBER: builtins.int + REASON_FIELD_NUMBER: builtins.int + RESOURCE_ID_FIELD_NUMBER: builtins.int + REQUEST_ID_FIELD_NUMBER: builtins.int + namespace: builtins.str + """Namespace of the workflow which scheduled this activity.""" + workflow_id: builtins.str + """If provided, pause a workflow activity (or activities) for the given workflow ID. + If empty, targets a standalone activity. + """ + activity_id: builtins.str + """The ID of the activity to target.""" + run_id: builtins.str + """Run ID of the workflow or standalone activity.""" + identity: builtins.str + """The identity of the client who initiated this request.""" + reason: builtins.str + """Reason to pause the activity.""" + resource_id: builtins.str + """Resource ID for routing. Contains "workflow:{workflow_id}" for workflow activities or "activity:{activity_id}" for standalone activities.""" + request_id: builtins.str + """Used to de-dupe pause requests.""" + def __init__( + self, + *, + namespace: builtins.str = ..., + workflow_id: builtins.str = ..., + activity_id: builtins.str = ..., + run_id: builtins.str = ..., + identity: builtins.str = ..., + reason: builtins.str = ..., + resource_id: builtins.str = ..., + request_id: builtins.str = ..., + ) -> None: ... + def ClearField( + self, + field_name: typing_extensions.Literal[ + "activity_id", + b"activity_id", + "identity", + b"identity", + "namespace", + b"namespace", + "reason", + b"reason", + "request_id", + b"request_id", + "resource_id", + b"resource_id", + "run_id", + b"run_id", + "workflow_id", + b"workflow_id", + ], + ) -> None: ... + +global___PauseActivityExecutionRequest = PauseActivityExecutionRequest + class PauseActivityResponse(google.protobuf.message.Message): + """Deprecated. Use `PauseActivityExecutionResponse`.""" + DESCRIPTOR: google.protobuf.descriptor.Descriptor def __init__( @@ -8189,7 +8396,18 @@ class PauseActivityResponse(google.protobuf.message.Message): global___PauseActivityResponse = PauseActivityResponse +class PauseActivityExecutionResponse(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + def __init__( + self, + ) -> None: ... + +global___PauseActivityExecutionResponse = PauseActivityExecutionResponse + class UnpauseActivityRequest(google.protobuf.message.Message): + """Deprecated. Use `UnpauseActivityExecutionRequest`.""" + DESCRIPTOR: google.protobuf.descriptor.Descriptor NAMESPACE_FIELD_NUMBER: builtins.int @@ -8282,7 +8500,90 @@ class UnpauseActivityRequest(google.protobuf.message.Message): global___UnpauseActivityRequest = UnpauseActivityRequest +class UnpauseActivityExecutionRequest(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + NAMESPACE_FIELD_NUMBER: builtins.int + WORKFLOW_ID_FIELD_NUMBER: builtins.int + ACTIVITY_ID_FIELD_NUMBER: builtins.int + RUN_ID_FIELD_NUMBER: builtins.int + IDENTITY_FIELD_NUMBER: builtins.int + RESET_ATTEMPTS_FIELD_NUMBER: builtins.int + RESET_HEARTBEAT_FIELD_NUMBER: builtins.int + REASON_FIELD_NUMBER: builtins.int + JITTER_FIELD_NUMBER: builtins.int + RESOURCE_ID_FIELD_NUMBER: builtins.int + namespace: builtins.str + """Namespace of the workflow which scheduled this activity.""" + workflow_id: builtins.str + """If provided, targets a workflow activity for the given workflow ID. + If empty, targets a standalone activity. + """ + activity_id: builtins.str + """The ID of the activity to target.""" + run_id: builtins.str + """Run ID of the workflow or standalone activity.""" + identity: builtins.str + """The identity of the client who initiated this request.""" + reset_attempts: builtins.bool + """Providing this flag will also reset the number of attempts.""" + reset_heartbeat: builtins.bool + """Providing this flag will also reset the heartbeat details.""" + reason: builtins.str + """Reason to unpause the activity.""" + @property + def jitter(self) -> google.protobuf.duration_pb2.Duration: + """If set, the activity will start at a random time within the specified jitter duration.""" + resource_id: builtins.str + """Resource ID for routing. Contains "workflow:{workflow_id}" for workflow activities or "activity:{activity_id}" for standalone activities.""" + def __init__( + self, + *, + namespace: builtins.str = ..., + workflow_id: builtins.str = ..., + activity_id: builtins.str = ..., + run_id: builtins.str = ..., + identity: builtins.str = ..., + reset_attempts: builtins.bool = ..., + reset_heartbeat: builtins.bool = ..., + reason: builtins.str = ..., + jitter: google.protobuf.duration_pb2.Duration | None = ..., + resource_id: builtins.str = ..., + ) -> None: ... + def HasField( + self, field_name: typing_extensions.Literal["jitter", b"jitter"] + ) -> builtins.bool: ... + def ClearField( + self, + field_name: typing_extensions.Literal[ + "activity_id", + b"activity_id", + "identity", + b"identity", + "jitter", + b"jitter", + "namespace", + b"namespace", + "reason", + b"reason", + "reset_attempts", + b"reset_attempts", + "reset_heartbeat", + b"reset_heartbeat", + "resource_id", + b"resource_id", + "run_id", + b"run_id", + "workflow_id", + b"workflow_id", + ], + ) -> None: ... + +global___UnpauseActivityExecutionRequest = UnpauseActivityExecutionRequest + class UnpauseActivityResponse(google.protobuf.message.Message): + """Deprecated. Use `UnpauseActivityExecutionResponse`.""" + DESCRIPTOR: google.protobuf.descriptor.Descriptor def __init__( @@ -8291,8 +8592,19 @@ class UnpauseActivityResponse(google.protobuf.message.Message): global___UnpauseActivityResponse = UnpauseActivityResponse +class UnpauseActivityExecutionResponse(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + def __init__( + self, + ) -> None: ... + +global___UnpauseActivityExecutionResponse = UnpauseActivityExecutionResponse + class ResetActivityRequest(google.protobuf.message.Message): - """NOTE: keep in sync with temporalio.api.batch.v1.BatchOperationResetActivities""" + """NOTE: keep in sync with temporalio.api.batch.v1.BatchOperationResetActivities + Deprecated. Use `ResetActivityExecutionRequest`. + """ DESCRIPTOR: google.protobuf.descriptor.Descriptor @@ -8333,7 +8645,7 @@ class ResetActivityRequest(google.protobuf.message.Message): restore_original_options: builtins.bool """If set, the activity options will be restored to the defaults. Default options are then options activity was created with. - They are part of the first SCHEDULE event. + They are part of the first schedule event. """ def __init__( self, @@ -8399,7 +8711,97 @@ class ResetActivityRequest(google.protobuf.message.Message): global___ResetActivityRequest = ResetActivityRequest +class ResetActivityExecutionRequest(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + NAMESPACE_FIELD_NUMBER: builtins.int + WORKFLOW_ID_FIELD_NUMBER: builtins.int + ACTIVITY_ID_FIELD_NUMBER: builtins.int + RUN_ID_FIELD_NUMBER: builtins.int + IDENTITY_FIELD_NUMBER: builtins.int + RESET_HEARTBEAT_FIELD_NUMBER: builtins.int + KEEP_PAUSED_FIELD_NUMBER: builtins.int + JITTER_FIELD_NUMBER: builtins.int + RESTORE_ORIGINAL_OPTIONS_FIELD_NUMBER: builtins.int + RESOURCE_ID_FIELD_NUMBER: builtins.int + namespace: builtins.str + """Namespace of the workflow which scheduled this activity.""" + workflow_id: builtins.str + """If provided, targets a workflow activity for the given workflow ID. + If empty, targets a standalone activity. + """ + activity_id: builtins.str + """The ID of the activity to target.""" + run_id: builtins.str + """Run ID of the workflow or standalone activity.""" + identity: builtins.str + """The identity of the client who initiated this request.""" + reset_heartbeat: builtins.bool + """Indicates that activity should reset heartbeat details. + This flag will be applied only to the new instance of the activity. + """ + keep_paused: builtins.bool + """If activity is paused, it will remain paused after reset""" + @property + def jitter(self) -> google.protobuf.duration_pb2.Duration: + """If set, and activity is in backoff, the activity will start at a random time within the specified jitter duration. + (unless it is paused and keep_paused is set) + """ + restore_original_options: builtins.bool + """If set, the activity options will be restored to the defaults. + Default options are then options activity was created with. + They are part of the first schedule event. + """ + resource_id: builtins.str + """Resource ID for routing. Contains "workflow:{workflow_id}" for workflow activities or "activity:{activity_id}" for standalone activities.""" + def __init__( + self, + *, + namespace: builtins.str = ..., + workflow_id: builtins.str = ..., + activity_id: builtins.str = ..., + run_id: builtins.str = ..., + identity: builtins.str = ..., + reset_heartbeat: builtins.bool = ..., + keep_paused: builtins.bool = ..., + jitter: google.protobuf.duration_pb2.Duration | None = ..., + restore_original_options: builtins.bool = ..., + resource_id: builtins.str = ..., + ) -> None: ... + def HasField( + self, field_name: typing_extensions.Literal["jitter", b"jitter"] + ) -> builtins.bool: ... + def ClearField( + self, + field_name: typing_extensions.Literal[ + "activity_id", + b"activity_id", + "identity", + b"identity", + "jitter", + b"jitter", + "keep_paused", + b"keep_paused", + "namespace", + b"namespace", + "reset_heartbeat", + b"reset_heartbeat", + "resource_id", + b"resource_id", + "restore_original_options", + b"restore_original_options", + "run_id", + b"run_id", + "workflow_id", + b"workflow_id", + ], + ) -> None: ... + +global___ResetActivityExecutionRequest = ResetActivityExecutionRequest + class ResetActivityResponse(google.protobuf.message.Message): + """Deprecated. Use `ResetActivityExecutionRequest`.""" + DESCRIPTOR: google.protobuf.descriptor.Descriptor def __init__( @@ -8408,6 +8810,15 @@ class ResetActivityResponse(google.protobuf.message.Message): global___ResetActivityResponse = ResetActivityResponse +class ResetActivityExecutionResponse(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + def __init__( + self, + ) -> None: ... + +global___ResetActivityExecutionResponse = ResetActivityExecutionResponse + class UpdateWorkflowExecutionOptionsRequest(google.protobuf.message.Message): """Keep the parameters in sync with: - temporalio.api.batch.v1.BatchOperationUpdateWorkflowExecutionOptions. @@ -10620,6 +11031,7 @@ class ListWorkersRequest(google.protobuf.message.Message): PAGE_SIZE_FIELD_NUMBER: builtins.int NEXT_PAGE_TOKEN_FIELD_NUMBER: builtins.int QUERY_FIELD_NUMBER: builtins.int + INCLUDE_SYSTEM_WORKERS_FIELD_NUMBER: builtins.int namespace: builtins.str page_size: builtins.int next_page_token: builtins.bytes @@ -10637,6 +11049,10 @@ class ListWorkersRequest(google.protobuf.message.Message): * StartTime * Status """ + include_system_workers: builtins.bool + """When true, the response will include system workers that are created implicitly + by the server and not by the user. By default, system workers are excluded. + """ def __init__( self, *, @@ -10644,10 +11060,13 @@ class ListWorkersRequest(google.protobuf.message.Message): page_size: builtins.int = ..., next_page_token: builtins.bytes = ..., query: builtins.str = ..., + include_system_workers: builtins.bool = ..., ) -> None: ... def ClearField( self, field_name: typing_extensions.Literal[ + "include_system_workers", + b"include_system_workers", "namespace", b"namespace", "next_page_token", diff --git a/temporalio/api/workflowservice/v1/service_pb2.py b/temporalio/api/workflowservice/v1/service_pb2.py index d49923458..3e123e9cf 100644 --- a/temporalio/api/workflowservice/v1/service_pb2.py +++ b/temporalio/api/workflowservice/v1/service_pb2.py @@ -24,7 +24,7 @@ ) DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile( - b'\n-temporal/api/workflowservice/v1/service.proto\x12\x1ftemporal.api.workflowservice.v1\x1a\x36temporal/api/workflowservice/v1/request_response.proto\x1a\x1cgoogle/api/annotations.proto\x1a+temporal/api/protometa/v1/annotations.proto2\xa9\x9c\x02\n\x0fWorkflowService\x12\xc3\x01\n\x11RegisterNamespace\x12\x39.temporal.api.workflowservice.v1.RegisterNamespaceRequest\x1a:.temporal.api.workflowservice.v1.RegisterNamespaceResponse"7\x82\xd3\xe4\x93\x02\x31"\x13/cluster/namespaces:\x01*Z\x17"\x12/api/v1/namespaces:\x01*\x12\xd5\x01\n\x11\x44\x65scribeNamespace\x12\x39.temporal.api.workflowservice.v1.DescribeNamespaceRequest\x1a:.temporal.api.workflowservice.v1.DescribeNamespaceResponse"I\x82\xd3\xe4\x93\x02\x43\x12\x1f/cluster/namespaces/{namespace}Z \x12\x1e/api/v1/namespaces/{namespace}\x12\xb4\x01\n\x0eListNamespaces\x12\x36.temporal.api.workflowservice.v1.ListNamespacesRequest\x1a\x37.temporal.api.workflowservice.v1.ListNamespacesResponse"1\x82\xd3\xe4\x93\x02+\x12\x13/cluster/namespacesZ\x14\x12\x12/api/v1/namespaces\x12\xe3\x01\n\x0fUpdateNamespace\x12\x37.temporal.api.workflowservice.v1.UpdateNamespaceRequest\x1a\x38.temporal.api.workflowservice.v1.UpdateNamespaceResponse"]\x82\xd3\xe4\x93\x02W"&/cluster/namespaces/{namespace}/update:\x01*Z*"%/api/v1/namespaces/{namespace}/update:\x01*\x12\x8f\x01\n\x12\x44\x65precateNamespace\x12:.temporal.api.workflowservice.v1.DeprecateNamespaceRequest\x1a;.temporal.api.workflowservice.v1.DeprecateNamespaceResponse"\x00\x12\xc6\x02\n\x16StartWorkflowExecution\x12>.temporal.api.workflowservice.v1.StartWorkflowExecutionRequest\x1a?.temporal.api.workflowservice.v1.StartWorkflowExecutionResponse"\xaa\x01\x82\xd3\xe4\x93\x02q"//namespaces/{namespace}/workflows/{workflow_id}:\x01*Z;"6/api/v1/namespaces/{namespace}/workflows/{workflow_id}:\x01*\x8a\x9d\xcc\x1b.\n\x14temporal-resource-id\x12\x16workflow:{workflow_id}\x12\xc2\x01\n\x15\x45xecuteMultiOperation\x12=.temporal.api.workflowservice.v1.ExecuteMultiOperationRequest\x1a>.temporal.api.workflowservice.v1.ExecuteMultiOperationResponse"*\x8a\x9d\xcc\x1b%\n\x14temporal-resource-id\x12\r{resource_id}\x12\xfe\x02\n\x1bGetWorkflowExecutionHistory\x12\x43.temporal.api.workflowservice.v1.GetWorkflowExecutionHistoryRequest\x1a\x44.temporal.api.workflowservice.v1.GetWorkflowExecutionHistoryResponse"\xd3\x01\x82\xd3\xe4\x93\x02\x8f\x01\x12\x41/namespaces/{namespace}/workflows/{execution.workflow_id}/historyZJ\x12H/api/v1/namespaces/{namespace}/workflows/{execution.workflow_id}/history\x8a\x9d\xcc\x1b\x38\n\x14temporal-resource-id\x12 workflow:{execution.workflow_id}\x12\xa3\x03\n"GetWorkflowExecutionHistoryReverse\x12J.temporal.api.workflowservice.v1.GetWorkflowExecutionHistoryReverseRequest\x1aK.temporal.api.workflowservice.v1.GetWorkflowExecutionHistoryReverseResponse"\xe3\x01\x82\xd3\xe4\x93\x02\x9f\x01\x12I/namespaces/{namespace}/workflows/{execution.workflow_id}/history-reverseZR\x12P/api/v1/namespaces/{namespace}/workflows/{execution.workflow_id}/history-reverse\x8a\x9d\xcc\x1b\x38\n\x14temporal-resource-id\x12 workflow:{execution.workflow_id}\x12\xcd\x01\n\x15PollWorkflowTaskQueue\x12=.temporal.api.workflowservice.v1.PollWorkflowTaskQueueRequest\x1a>.temporal.api.workflowservice.v1.PollWorkflowTaskQueueResponse"5\x8a\x9d\xcc\x1b\x30\n\x14temporal-resource-id\x12\x18poller:{poller_group_id}\x12\xd7\x01\n\x1cRespondWorkflowTaskCompleted\x12\x44.temporal.api.workflowservice.v1.RespondWorkflowTaskCompletedRequest\x1a\x45.temporal.api.workflowservice.v1.RespondWorkflowTaskCompletedResponse"*\x8a\x9d\xcc\x1b%\n\x14temporal-resource-id\x12\r{resource_id}\x12\xce\x01\n\x19RespondWorkflowTaskFailed\x12\x41.temporal.api.workflowservice.v1.RespondWorkflowTaskFailedRequest\x1a\x42.temporal.api.workflowservice.v1.RespondWorkflowTaskFailedResponse"*\x8a\x9d\xcc\x1b%\n\x14temporal-resource-id\x12\r{resource_id}\x12\xcd\x01\n\x15PollActivityTaskQueue\x12=.temporal.api.workflowservice.v1.PollActivityTaskQueueRequest\x1a>.temporal.api.workflowservice.v1.PollActivityTaskQueueResponse"5\x8a\x9d\xcc\x1b\x30\n\x14temporal-resource-id\x12\x18poller:{poller_group_id}\x12\xc2\x02\n\x1bRecordActivityTaskHeartbeat\x12\x43.temporal.api.workflowservice.v1.RecordActivityTaskHeartbeatRequest\x1a\x44.temporal.api.workflowservice.v1.RecordActivityTaskHeartbeatResponse"\x97\x01\x82\xd3\xe4\x93\x02g"*/namespaces/{namespace}/activity-heartbeat:\x01*Z6"1/api/v1/namespaces/{namespace}/activity-heartbeat:\x01*\x8a\x9d\xcc\x1b%\n\x14temporal-resource-id\x12\r{resource_id}\x12\xa8\x04\n\x1fRecordActivityTaskHeartbeatById\x12G.temporal.api.workflowservice.v1.RecordActivityTaskHeartbeatByIdRequest\x1aH.temporal.api.workflowservice.v1.RecordActivityTaskHeartbeatByIdResponse"\xf1\x02\x82\xd3\xe4\x93\x02\xc0\x02":/namespaces/{namespace}/activities/{activity_id}/heartbeat:\x01*ZF"A/api/v1/namespaces/{namespace}/activities/{activity_id}/heartbeat:\x01*ZW"R/namespaces/{namespace}/workflows/{workflow_id}/activities/{activity_id}/heartbeat:\x01*Z^"Y/api/v1/namespaces/{namespace}/workflows/{workflow_id}/activities/{activity_id}/heartbeat:\x01*\x8a\x9d\xcc\x1b%\n\x14temporal-resource-id\x12\r{resource_id}\x12\xc3\x02\n\x1cRespondActivityTaskCompleted\x12\x44.temporal.api.workflowservice.v1.RespondActivityTaskCompletedRequest\x1a\x45.temporal.api.workflowservice.v1.RespondActivityTaskCompletedResponse"\x95\x01\x82\xd3\xe4\x93\x02\x65")/namespaces/{namespace}/activity-complete:\x01*Z5"0/api/v1/namespaces/{namespace}/activity-complete:\x01*\x8a\x9d\xcc\x1b%\n\x14temporal-resource-id\x12\r{resource_id}\x12\xa7\x04\n RespondActivityTaskCompletedById\x12H.temporal.api.workflowservice.v1.RespondActivityTaskCompletedByIdRequest\x1aI.temporal.api.workflowservice.v1.RespondActivityTaskCompletedByIdResponse"\xed\x02\x82\xd3\xe4\x93\x02\xbc\x02"9/namespaces/{namespace}/activities/{activity_id}/complete:\x01*ZE"@/api/v1/namespaces/{namespace}/activities/{activity_id}/complete:\x01*ZV"Q/namespaces/{namespace}/workflows/{workflow_id}/activities/{activity_id}/complete:\x01*Z]"X/api/v1/namespaces/{namespace}/workflows/{workflow_id}/activities/{activity_id}/complete:\x01*\x8a\x9d\xcc\x1b%\n\x14temporal-resource-id\x12\r{resource_id}\x12\xb2\x02\n\x19RespondActivityTaskFailed\x12\x41.temporal.api.workflowservice.v1.RespondActivityTaskFailedRequest\x1a\x42.temporal.api.workflowservice.v1.RespondActivityTaskFailedResponse"\x8d\x01\x82\xd3\xe4\x93\x02]"%/namespaces/{namespace}/activity-fail:\x01*Z1",/api/v1/namespaces/{namespace}/activity-fail:\x01*\x8a\x9d\xcc\x1b%\n\x14temporal-resource-id\x12\r{resource_id}\x12\x8e\x04\n\x1dRespondActivityTaskFailedById\x12\x45.temporal.api.workflowservice.v1.RespondActivityTaskFailedByIdRequest\x1a\x46.temporal.api.workflowservice.v1.RespondActivityTaskFailedByIdResponse"\xdd\x02\x82\xd3\xe4\x93\x02\xac\x02"5/namespaces/{namespace}/activities/{activity_id}/fail:\x01*ZA".temporal.api.workflowservice.v1.ResetWorkflowExecutionRequest\x1a?.temporal.api.workflowservice.v1.ResetWorkflowExecutionResponse"\xf0\x01\x82\xd3\xe4\x93\x02\xa3\x01"H/namespaces/{namespace}/workflows/{workflow_execution.workflow_id}/reset:\x01*ZT"O/api/v1/namespaces/{namespace}/workflows/{workflow_execution.workflow_id}/reset:\x01*\x8a\x9d\xcc\x1b\x41\n\x14temporal-resource-id\x12)workflow:{workflow_execution.workflow_id}\x12\xa0\x03\n\x1aTerminateWorkflowExecution\x12\x42.temporal.api.workflowservice.v1.TerminateWorkflowExecutionRequest\x1a\x43.temporal.api.workflowservice.v1.TerminateWorkflowExecutionResponse"\xf8\x01\x82\xd3\xe4\x93\x02\xab\x01"L/namespaces/{namespace}/workflows/{workflow_execution.workflow_id}/terminate:\x01*ZX"S/api/v1/namespaces/{namespace}/workflows/{workflow_execution.workflow_id}/terminate:\x01*\x8a\x9d\xcc\x1b\x41\n\x14temporal-resource-id\x12)workflow:{workflow_execution.workflow_id}\x12\xe4\x01\n\x17\x44\x65leteWorkflowExecution\x12?.temporal.api.workflowservice.v1.DeleteWorkflowExecutionRequest\x1a@.temporal.api.workflowservice.v1.DeleteWorkflowExecutionResponse"F\x8a\x9d\xcc\x1b\x41\n\x14temporal-resource-id\x12)workflow:{workflow_execution.workflow_id}\x12\xa7\x01\n\x1aListOpenWorkflowExecutions\x12\x42.temporal.api.workflowservice.v1.ListOpenWorkflowExecutionsRequest\x1a\x43.temporal.api.workflowservice.v1.ListOpenWorkflowExecutionsResponse"\x00\x12\xad\x01\n\x1cListClosedWorkflowExecutions\x12\x44.temporal.api.workflowservice.v1.ListClosedWorkflowExecutionsRequest\x1a\x45.temporal.api.workflowservice.v1.ListClosedWorkflowExecutionsResponse"\x00\x12\xf0\x01\n\x16ListWorkflowExecutions\x12>.temporal.api.workflowservice.v1.ListWorkflowExecutionsRequest\x1a?.temporal.api.workflowservice.v1.ListWorkflowExecutionsResponse"U\x82\xd3\xe4\x93\x02O\x12!/namespaces/{namespace}/workflowsZ*\x12(/api/v1/namespaces/{namespace}/workflows\x12\x9a\x02\n\x1eListArchivedWorkflowExecutions\x12\x46.temporal.api.workflowservice.v1.ListArchivedWorkflowExecutionsRequest\x1aG.temporal.api.workflowservice.v1.ListArchivedWorkflowExecutionsResponse"g\x82\xd3\xe4\x93\x02\x61\x12*/namespaces/{namespace}/archived-workflowsZ3\x12\x31/api/v1/namespaces/{namespace}/archived-workflows\x12\x9b\x01\n\x16ScanWorkflowExecutions\x12>.temporal.api.workflowservice.v1.ScanWorkflowExecutionsRequest\x1a?.temporal.api.workflowservice.v1.ScanWorkflowExecutionsResponse"\x00\x12\xfd\x01\n\x17\x43ountWorkflowExecutions\x12?.temporal.api.workflowservice.v1.CountWorkflowExecutionsRequest\x1a@.temporal.api.workflowservice.v1.CountWorkflowExecutionsResponse"_\x82\xd3\xe4\x93\x02Y\x12&/namespaces/{namespace}/workflow-countZ/\x12-/api/v1/namespaces/{namespace}/workflow-count\x12\x92\x01\n\x13GetSearchAttributes\x12;.temporal.api.workflowservice.v1.GetSearchAttributesRequest\x1a<.temporal.api.workflowservice.v1.GetSearchAttributesResponse"\x00\x12\xd9\x01\n\x19RespondQueryTaskCompleted\x12\x41.temporal.api.workflowservice.v1.RespondQueryTaskCompletedRequest\x1a\x42.temporal.api.workflowservice.v1.RespondQueryTaskCompletedResponse"5\x8a\x9d\xcc\x1b\x30\n\x14temporal-resource-id\x12\x18poller:{poller_group_id}\x12\xd2\x01\n\x14ResetStickyTaskQueue\x12<.temporal.api.workflowservice.v1.ResetStickyTaskQueueRequest\x1a=.temporal.api.workflowservice.v1.ResetStickyTaskQueueResponse"=\x8a\x9d\xcc\x1b\x38\n\x14temporal-resource-id\x12 workflow:{execution.workflow_id}\x12\x83\x01\n\x0eShutdownWorker\x12\x36.temporal.api.workflowservice.v1.ShutdownWorkerRequest\x1a\x37.temporal.api.workflowservice.v1.ShutdownWorkerResponse"\x00\x12\xfc\x02\n\rQueryWorkflow\x12\x35.temporal.api.workflowservice.v1.QueryWorkflowRequest\x1a\x36.temporal.api.workflowservice.v1.QueryWorkflowResponse"\xfb\x01\x82\xd3\xe4\x93\x02\xb7\x01"R/namespaces/{namespace}/workflows/{execution.workflow_id}/query/{query.query_type}:\x01*Z^"Y/api/v1/namespaces/{namespace}/workflows/{execution.workflow_id}/query/{query.query_type}:\x01*\x8a\x9d\xcc\x1b\x38\n\x14temporal-resource-id\x12 workflow:{execution.workflow_id}\x12\xe7\x02\n\x19\x44\x65scribeWorkflowExecution\x12\x41.temporal.api.workflowservice.v1.DescribeWorkflowExecutionRequest\x1a\x42.temporal.api.workflowservice.v1.DescribeWorkflowExecutionResponse"\xc2\x01\x82\xd3\xe4\x93\x02\x7f\x12\x39/namespaces/{namespace}/workflows/{execution.workflow_id}ZB\x12@/api/v1/namespaces/{namespace}/workflows/{execution.workflow_id}\x8a\x9d\xcc\x1b\x38\n\x14temporal-resource-id\x12 workflow:{execution.workflow_id}\x12\xc2\x02\n\x11\x44\x65scribeTaskQueue\x12\x39.temporal.api.workflowservice.v1.DescribeTaskQueueRequest\x1a:.temporal.api.workflowservice.v1.DescribeTaskQueueResponse"\xb5\x01\x82\xd3\xe4\x93\x02w\x12\x35/namespaces/{namespace}/task-queues/{task_queue.name}Z>\x12/namespaces/{namespace}/schedules/{schedule_id}/matching-timesZG\x12\x45/api/v1/namespaces/{namespace}/schedules/{schedule_id}/matching-times\x8a\x9d\xcc\x1b.\n\x14temporal-resource-id\x12\x16schedule:{schedule_id}\x12\xa8\x02\n\x0e\x44\x65leteSchedule\x12\x36.temporal.api.workflowservice.v1.DeleteScheduleRequest\x1a\x37.temporal.api.workflowservice.v1.DeleteScheduleResponse"\xa4\x01\x82\xd3\xe4\x93\x02k*//namespaces/{namespace}/schedules/{schedule_id}Z8*6/api/v1/namespaces/{namespace}/schedules/{schedule_id}\x8a\x9d\xcc\x1b.\n\x14temporal-resource-id\x12\x16schedule:{schedule_id}\x12\xd5\x01\n\rListSchedules\x12\x35.temporal.api.workflowservice.v1.ListSchedulesRequest\x1a\x36.temporal.api.workflowservice.v1.ListSchedulesResponse"U\x82\xd3\xe4\x93\x02O\x12!/namespaces/{namespace}/schedulesZ*\x12(/api/v1/namespaces/{namespace}/schedules\x12\xe2\x01\n\x0e\x43ountSchedules\x12\x36.temporal.api.workflowservice.v1.CountSchedulesRequest\x1a\x37.temporal.api.workflowservice.v1.CountSchedulesResponse"_\x82\xd3\xe4\x93\x02Y\x12&/namespaces/{namespace}/schedule-countZ/\x12-/api/v1/namespaces/{namespace}/schedule-count\x12\xb9\x01\n UpdateWorkerBuildIdCompatibility\x12H.temporal.api.workflowservice.v1.UpdateWorkerBuildIdCompatibilityRequest\x1aI.temporal.api.workflowservice.v1.UpdateWorkerBuildIdCompatibilityResponse"\x00\x12\xe1\x02\n\x1dGetWorkerBuildIdCompatibility\x12\x45.temporal.api.workflowservice.v1.GetWorkerBuildIdCompatibilityRequest\x1a\x46.temporal.api.workflowservice.v1.GetWorkerBuildIdCompatibilityResponse"\xb0\x01\x82\xd3\xe4\x93\x02\xa9\x01\x12N/namespaces/{namespace}/task-queues/{task_queue}/worker-build-id-compatibilityZW\x12U/api/v1/namespaces/{namespace}/task-queues/{task_queue}/worker-build-id-compatibility\x12\xaa\x01\n\x1bUpdateWorkerVersioningRules\x12\x43.temporal.api.workflowservice.v1.UpdateWorkerVersioningRulesRequest\x1a\x44.temporal.api.workflowservice.v1.UpdateWorkerVersioningRulesResponse"\x00\x12\xc6\x02\n\x18GetWorkerVersioningRules\x12@.temporal.api.workflowservice.v1.GetWorkerVersioningRulesRequest\x1a\x41.temporal.api.workflowservice.v1.GetWorkerVersioningRulesResponse"\xa4\x01\x82\xd3\xe4\x93\x02\x9d\x01\x12H/namespaces/{namespace}/task-queues/{task_queue}/worker-versioning-rulesZQ\x12O/api/v1/namespaces/{namespace}/task-queues/{task_queue}/worker-versioning-rules\x12\x97\x02\n\x19GetWorkerTaskReachability\x12\x41.temporal.api.workflowservice.v1.GetWorkerTaskReachabilityRequest\x1a\x42.temporal.api.workflowservice.v1.GetWorkerTaskReachabilityResponse"s\x82\xd3\xe4\x93\x02m\x12\x30/namespaces/{namespace}/worker-task-reachabilityZ9\x12\x37/api/v1/namespaces/{namespace}/worker-task-reachability\x12\xc8\x02\n\x12\x44\x65scribeDeployment\x12:.temporal.api.workflowservice.v1.DescribeDeploymentRequest\x1a;.temporal.api.workflowservice.v1.DescribeDeploymentResponse"\xb8\x01\x82\xd3\xe4\x93\x02\xb1\x01\x12R/namespaces/{namespace}/deployments/{deployment.series_name}/{deployment.build_id}Z[\x12Y/api/v1/namespaces/{namespace}/deployments/{deployment.series_name}/{deployment.build_id}\x12\x81\x04\n\x1f\x44\x65scribeWorkerDeploymentVersion\x12G.temporal.api.workflowservice.v1.DescribeWorkerDeploymentVersionRequest\x1aH.temporal.api.workflowservice.v1.DescribeWorkerDeploymentVersionResponse"\xca\x02\x82\xd3\xe4\x93\x02\xf7\x01\x12u/namespaces/{namespace}/worker-deployment-versions/{deployment_version.deployment_name}/{deployment_version.build_id}Z~\x12|/api/v1/namespaces/{namespace}/worker-deployment-versions/{deployment_version.deployment_name}/{deployment_version.build_id}\x8a\x9d\xcc\x1bG\n\x14temporal-resource-id\x12/deployment:{deployment_version.deployment_name}\x12\xdf\x01\n\x0fListDeployments\x12\x37.temporal.api.workflowservice.v1.ListDeploymentsRequest\x1a\x38.temporal.api.workflowservice.v1.ListDeploymentsResponse"Y\x82\xd3\xe4\x93\x02S\x12#/namespaces/{namespace}/deploymentsZ,\x12*/api/v1/namespaces/{namespace}/deployments\x12\xf7\x02\n\x19GetDeploymentReachability\x12\x41.temporal.api.workflowservice.v1.GetDeploymentReachabilityRequest\x1a\x42.temporal.api.workflowservice.v1.GetDeploymentReachabilityResponse"\xd2\x01\x82\xd3\xe4\x93\x02\xcb\x01\x12_/namespaces/{namespace}/deployments/{deployment.series_name}/{deployment.build_id}/reachabilityZh\x12\x66/api/v1/namespaces/{namespace}/deployments/{deployment.series_name}/{deployment.build_id}/reachability\x12\x99\x02\n\x14GetCurrentDeployment\x12<.temporal.api.workflowservice.v1.GetCurrentDeploymentRequest\x1a=.temporal.api.workflowservice.v1.GetCurrentDeploymentResponse"\x83\x01\x82\xd3\xe4\x93\x02}\x12\x38/namespaces/{namespace}/current-deployment/{series_name}ZA\x12?/api/v1/namespaces/{namespace}/current-deployment/{series_name}\x12\xb6\x02\n\x14SetCurrentDeployment\x12<.temporal.api.workflowservice.v1.SetCurrentDeploymentRequest\x1a=.temporal.api.workflowservice.v1.SetCurrentDeploymentResponse"\xa0\x01\x82\xd3\xe4\x93\x02\x99\x01"C/namespaces/{namespace}/current-deployment/{deployment.series_name}:\x01*ZO"J/api/v1/namespaces/{namespace}/current-deployment/{deployment.series_name}:\x01*\x12\xb0\x03\n!SetWorkerDeploymentCurrentVersion\x12I.temporal.api.workflowservice.v1.SetWorkerDeploymentCurrentVersionRequest\x1aJ.temporal.api.workflowservice.v1.SetWorkerDeploymentCurrentVersionResponse"\xf3\x01\x82\xd3\xe4\x93\x02\xb3\x01"P/namespaces/{namespace}/worker-deployments/{deployment_name}/set-current-version:\x01*Z\\"W/api/v1/namespaces/{namespace}/worker-deployments/{deployment_name}/set-current-version:\x01*\x8a\x9d\xcc\x1b\x34\n\x14temporal-resource-id\x12\x1c\x64\x65ployment:{deployment_name}\x12\xe7\x02\n\x18\x44\x65scribeWorkerDeployment\x12@.temporal.api.workflowservice.v1.DescribeWorkerDeploymentRequest\x1a\x41.temporal.api.workflowservice.v1.DescribeWorkerDeploymentResponse"\xc5\x01\x82\xd3\xe4\x93\x02\x85\x01\x12.temporal.api.workflowservice.v1.DeleteWorkerDeploymentRequest\x1a?.temporal.api.workflowservice.v1.DeleteWorkerDeploymentResponse"\xc5\x01\x82\xd3\xe4\x93\x02\x85\x01*.temporal.api.workflowservice.v1.ListWorkerDeploymentsResponse"g\x82\xd3\xe4\x93\x02\x61\x12*/namespaces/{namespace}/worker-deploymentsZ3\x12\x31/api/v1/namespaces/{namespace}/worker-deployments\x12\xae\x02\n\x16\x43reateWorkerDeployment\x12>.temporal.api.workflowservice.v1.CreateWorkerDeploymentRequest\x1a?.temporal.api.workflowservice.v1.CreateWorkerDeploymentResponse"\x92\x01\x82\xd3\xe4\x93\x02\x8b\x01".temporal.api.workflowservice.v1.DescribeBatchOperationRequest\x1a?.temporal.api.workflowservice.v1.DescribeBatchOperationResponse"\xa0\x01\x82\xd3\xe4\x93\x02o\x12\x31/namespaces/{namespace}/batch-operations/{job_id}Z:\x12\x38/api/v1/namespaces/{namespace}/batch-operations/{job_id}\x8a\x9d\xcc\x1b&\n\x14temporal-resource-id\x12\x0e\x62\x61tch:{job_id}\x12\xf5\x01\n\x13ListBatchOperations\x12;.temporal.api.workflowservice.v1.ListBatchOperationsRequest\x1a<.temporal.api.workflowservice.v1.ListBatchOperationsResponse"c\x82\xd3\xe4\x93\x02]\x12(/namespaces/{namespace}/batch-operationsZ1\x12//api/v1/namespaces/{namespace}/batch-operations\x12\xc4\x01\n\x12PollNexusTaskQueue\x12:.temporal.api.workflowservice.v1.PollNexusTaskQueueRequest\x1a;.temporal.api.workflowservice.v1.PollNexusTaskQueueResponse"5\x8a\x9d\xcc\x1b\x30\n\x14temporal-resource-id\x12\x18poller:{poller_group_id}\x12\xd9\x01\n\x19RespondNexusTaskCompleted\x12\x41.temporal.api.workflowservice.v1.RespondNexusTaskCompletedRequest\x1a\x42.temporal.api.workflowservice.v1.RespondNexusTaskCompletedResponse"5\x8a\x9d\xcc\x1b\x30\n\x14temporal-resource-id\x12\x18poller:{poller_group_id}\x12\xd0\x01\n\x16RespondNexusTaskFailed\x12>.temporal.api.workflowservice.v1.RespondNexusTaskFailedRequest\x1a?.temporal.api.workflowservice.v1.RespondNexusTaskFailedResponse"5\x8a\x9d\xcc\x1b\x30\n\x14temporal-resource-id\x12\x18poller:{poller_group_id}\x12\xe8\x02\n\x15UpdateActivityOptions\x12=.temporal.api.workflowservice.v1.UpdateActivityOptionsRequest\x1a>.temporal.api.workflowservice.v1.UpdateActivityOptionsResponse"\xcf\x01\x82\xd3\xe4\x93\x02\x8b\x01".temporal.api.workflowservice.v1.RecordWorkerHeartbeatResponse"\x95\x01\x82\xd3\xe4\x93\x02\x65")/namespaces/{namespace}/workers/heartbeat:\x01*Z5"0/api/v1/namespaces/{namespace}/workers/heartbeat:\x01*\x8a\x9d\xcc\x1b%\n\x14temporal-resource-id\x12\r{resource_id}\x12\xcb\x01\n\x0bListWorkers\x12\x33.temporal.api.workflowservice.v1.ListWorkersRequest\x1a\x34.temporal.api.workflowservice.v1.ListWorkersResponse"Q\x82\xd3\xe4\x93\x02K\x12\x1f/namespaces/{namespace}/workersZ(\x12&/api/v1/namespaces/{namespace}/workers\x12\xe2\x02\n\x15UpdateTaskQueueConfig\x12=.temporal.api.workflowservice.v1.UpdateTaskQueueConfigRequest\x1a>.temporal.api.workflowservice.v1.UpdateTaskQueueConfigResponse"\xc9\x01\x82\xd3\xe4\x93\x02\x8f\x01">/namespaces/{namespace}/task-queues/{task_queue}/update-config:\x01*ZJ"E/api/v1/namespaces/{namespace}/task-queues/{task_queue}/update-config:\x01*\x8a\x9d\xcc\x1b.\n\x14temporal-resource-id\x12\x16taskqueue:{task_queue}\x12\xa8\x02\n\x11\x46\x65tchWorkerConfig\x12\x39.temporal.api.workflowservice.v1.FetchWorkerConfigRequest\x1a:.temporal.api.workflowservice.v1.FetchWorkerConfigResponse"\x9b\x01\x82\xd3\xe4\x93\x02k",/namespaces/{namespace}/workers/fetch-config:\x01*Z8"3/api/v1/namespaces/{namespace}/workers/fetch-config:\x01*\x8a\x9d\xcc\x1b%\n\x14temporal-resource-id\x12\r{resource_id}\x12\xad\x02\n\x12UpdateWorkerConfig\x12:.temporal.api.workflowservice.v1.UpdateWorkerConfigRequest\x1a;.temporal.api.workflowservice.v1.UpdateWorkerConfigResponse"\x9d\x01\x82\xd3\xe4\x93\x02m"-/namespaces/{namespace}/workers/update-config:\x01*Z9"4/api/v1/namespaces/{namespace}/workers/update-config:\x01*\x8a\x9d\xcc\x1b%\n\x14temporal-resource-id\x12\r{resource_id}\x12\xcd\x02\n\x0e\x44\x65scribeWorker\x12\x36.temporal.api.workflowservice.v1.DescribeWorkerRequest\x1a\x37.temporal.api.workflowservice.v1.DescribeWorkerResponse"\xc9\x01\x82\xd3\xe4\x93\x02\x89\x01\x12>/namespaces/{namespace}/workers/describe/{worker_instance_key}ZG\x12\x45/api/v1/namespaces/{namespace}/workers/describe/{worker_instance_key}\x8a\x9d\xcc\x1b\x34\n\x14temporal-resource-id\x12\x1cworker:{worker_instance_key}\x12\xd2\x02\n\x16PauseWorkflowExecution\x12>.temporal.api.workflowservice.v1.PauseWorkflowExecutionRequest\x1a?.temporal.api.workflowservice.v1.PauseWorkflowExecutionResponse"\xb6\x01\x82\xd3\xe4\x93\x02}"5/namespaces/{namespace}/workflows/{workflow_id}/pause:\x01*ZA"/api/v1/namespaces/{namespace}/workflows/{workflow_id}/unpause:\x01*\x8a\x9d\xcc\x1b.\n\x14temporal-resource-id\x12\x16workflow:{workflow_id}\x12\xc8\x02\n\x16StartActivityExecution\x12>.temporal.api.workflowservice.v1.StartActivityExecutionRequest\x1a?.temporal.api.workflowservice.v1.StartActivityExecutionResponse"\xac\x01\x82\xd3\xe4\x93\x02s"0/namespaces/{namespace}/activities/{activity_id}:\x01*Z<"7/api/v1/namespaces/{namespace}/activities/{activity_id}:\x01*\x8a\x9d\xcc\x1b.\n\x14temporal-resource-id\x12\x16\x61\x63tivity:{activity_id}\x12\xb6\x02\n\x1cStartNexusOperationExecution\x12\x44.temporal.api.workflowservice.v1.StartNexusOperationExecutionRequest\x1a\x45.temporal.api.workflowservice.v1.StartNexusOperationExecutionResponse"\x88\x01\x82\xd3\xe4\x93\x02\x81\x01"7/namespaces/{namespace}/nexus-operations/{operation_id}:\x01*ZC">/api/v1/namespaces/{namespace}/nexus-operations/{operation_id}:\x01*\x12\xcb\x02\n\x19\x44\x65scribeActivityExecution\x12\x41.temporal.api.workflowservice.v1.DescribeActivityExecutionRequest\x1a\x42.temporal.api.workflowservice.v1.DescribeActivityExecutionResponse"\xa6\x01\x82\xd3\xe4\x93\x02m\x12\x30/namespaces/{namespace}/activities/{activity_id}Z9\x12\x37/api/v1/namespaces/{namespace}/activities/{activity_id}\x8a\x9d\xcc\x1b.\n\x14temporal-resource-id\x12\x16\x61\x63tivity:{activity_id}\x12\xb8\x02\n\x1f\x44\x65scribeNexusOperationExecution\x12G.temporal.api.workflowservice.v1.DescribeNexusOperationExecutionRequest\x1aH.temporal.api.workflowservice.v1.DescribeNexusOperationExecutionResponse"\x81\x01\x82\xd3\xe4\x93\x02{\x12\x37/namespaces/{namespace}/nexus-operations/{operation_id}Z@\x12>/api/v1/namespaces/{namespace}/nexus-operations/{operation_id}\x12\xcf\x02\n\x15PollActivityExecution\x12=.temporal.api.workflowservice.v1.PollActivityExecutionRequest\x1a>.temporal.api.workflowservice.v1.PollActivityExecutionResponse"\xb6\x01\x82\xd3\xe4\x93\x02}\x12\x38/namespaces/{namespace}/activities/{activity_id}/outcomeZA\x12?/api/v1/namespaces/{namespace}/activities/{activity_id}/outcome\x8a\x9d\xcc\x1b.\n\x14temporal-resource-id\x12\x16\x61\x63tivity:{activity_id}\x12\xb7\x02\n\x1bPollNexusOperationExecution\x12\x43.temporal.api.workflowservice.v1.PollNexusOperationExecutionRequest\x1a\x44.temporal.api.workflowservice.v1.PollNexusOperationExecutionResponse"\x8c\x01\x82\xd3\xe4\x93\x02\x85\x01\x12.temporal.api.workflowservice.v1.ListActivityExecutionsRequest\x1a?.temporal.api.workflowservice.v1.ListActivityExecutionsResponse"W\x82\xd3\xe4\x93\x02Q\x12"/namespaces/{namespace}/activitiesZ+\x12)/api/v1/namespaces/{namespace}/activities\x12\x90\x02\n\x1cListNexusOperationExecutions\x12\x44.temporal.api.workflowservice.v1.ListNexusOperationExecutionsRequest\x1a\x45.temporal.api.workflowservice.v1.ListNexusOperationExecutionsResponse"c\x82\xd3\xe4\x93\x02]\x12(/namespaces/{namespace}/nexus-operationsZ1\x12//api/v1/namespaces/{namespace}/nexus-operations\x12\xfd\x01\n\x17\x43ountActivityExecutions\x12?.temporal.api.workflowservice.v1.CountActivityExecutionsRequest\x1a@.temporal.api.workflowservice.v1.CountActivityExecutionsResponse"_\x82\xd3\xe4\x93\x02Y\x12&/namespaces/{namespace}/activity-countZ/\x12-/api/v1/namespaces/{namespace}/activity-count\x12\x9d\x02\n\x1d\x43ountNexusOperationExecutions\x12\x45.temporal.api.workflowservice.v1.CountNexusOperationExecutionsRequest\x1a\x46.temporal.api.workflowservice.v1.CountNexusOperationExecutionsResponse"m\x82\xd3\xe4\x93\x02g\x12-/namespaces/{namespace}/nexus-operation-countZ6\x12\x34/api/v1/namespaces/{namespace}/nexus-operation-count\x12\xef\x02\n\x1eRequestCancelActivityExecution\x12\x46.temporal.api.workflowservice.v1.RequestCancelActivityExecutionRequest\x1aG.temporal.api.workflowservice.v1.RequestCancelActivityExecutionResponse"\xbb\x01\x82\xd3\xe4\x93\x02\x81\x01"7/namespaces/{namespace}/activities/{activity_id}/cancel:\x01*ZC">/api/v1/namespaces/{namespace}/activities/{activity_id}/cancel:\x01*\x8a\x9d\xcc\x1b.\n\x14temporal-resource-id\x12\x16\x61\x63tivity:{activity_id}\x12\xdc\x02\n$RequestCancelNexusOperationExecution\x12L.temporal.api.workflowservice.v1.RequestCancelNexusOperationExecutionRequest\x1aM.temporal.api.workflowservice.v1.RequestCancelNexusOperationExecutionResponse"\x96\x01\x82\xd3\xe4\x93\x02\x8f\x01">/namespaces/{namespace}/nexus-operations/{operation_id}/cancel:\x01*ZJ"E/api/v1/namespaces/{namespace}/nexus-operations/{operation_id}/cancel:\x01*\x12\xe9\x02\n\x1aTerminateActivityExecution\x12\x42.temporal.api.workflowservice.v1.TerminateActivityExecutionRequest\x1a\x43.temporal.api.workflowservice.v1.TerminateActivityExecutionResponse"\xc1\x01\x82\xd3\xe4\x93\x02\x87\x01":/namespaces/{namespace}/activities/{activity_id}/terminate:\x01*ZF"A/api/v1/namespaces/{namespace}/activities/{activity_id}/terminate:\x01*\x8a\x9d\xcc\x1b.\n\x14temporal-resource-id\x12\x16\x61\x63tivity:{activity_id}\x12\x9e\x01\n\x17\x44\x65leteActivityExecution\x12?.temporal.api.workflowservice.v1.DeleteActivityExecutionRequest\x1a@.temporal.api.workflowservice.v1.DeleteActivityExecutionResponse"\x00\x12\xd6\x02\n TerminateNexusOperationExecution\x12H.temporal.api.workflowservice.v1.TerminateNexusOperationExecutionRequest\x1aI.temporal.api.workflowservice.v1.TerminateNexusOperationExecutionResponse"\x9c\x01\x82\xd3\xe4\x93\x02\x95\x01"A/namespaces/{namespace}/nexus-operations/{operation_id}/terminate:\x01*ZM"H/api/v1/namespaces/{namespace}/nexus-operations/{operation_id}/terminate:\x01*\x12\xb0\x01\n\x1d\x44\x65leteNexusOperationExecution\x12\x45.temporal.api.workflowservice.v1.DeleteNexusOperationExecutionRequest\x1a\x46.temporal.api.workflowservice.v1.DeleteNexusOperationExecutionResponse"\x00\x42\xb6\x01\n"io.temporal.api.workflowservice.v1B\x0cServiceProtoP\x01Z5go.temporal.io/api/workflowservice/v1;workflowservice\xaa\x02!Temporalio.Api.WorkflowService.V1\xea\x02$Temporalio::Api::WorkflowService::V1b\x06proto3' + b'\n-temporal/api/workflowservice/v1/service.proto\x12\x1ftemporal.api.workflowservice.v1\x1a\x36temporal/api/workflowservice/v1/request_response.proto\x1a\x1cgoogle/api/annotations.proto\x1a+temporal/api/protometa/v1/annotations.proto2\xb0\xad\x02\n\x0fWorkflowService\x12\xc3\x01\n\x11RegisterNamespace\x12\x39.temporal.api.workflowservice.v1.RegisterNamespaceRequest\x1a:.temporal.api.workflowservice.v1.RegisterNamespaceResponse"7\x82\xd3\xe4\x93\x02\x31"\x13/cluster/namespaces:\x01*Z\x17"\x12/api/v1/namespaces:\x01*\x12\xd5\x01\n\x11\x44\x65scribeNamespace\x12\x39.temporal.api.workflowservice.v1.DescribeNamespaceRequest\x1a:.temporal.api.workflowservice.v1.DescribeNamespaceResponse"I\x82\xd3\xe4\x93\x02\x43\x12\x1f/cluster/namespaces/{namespace}Z \x12\x1e/api/v1/namespaces/{namespace}\x12\xb4\x01\n\x0eListNamespaces\x12\x36.temporal.api.workflowservice.v1.ListNamespacesRequest\x1a\x37.temporal.api.workflowservice.v1.ListNamespacesResponse"1\x82\xd3\xe4\x93\x02+\x12\x13/cluster/namespacesZ\x14\x12\x12/api/v1/namespaces\x12\xe3\x01\n\x0fUpdateNamespace\x12\x37.temporal.api.workflowservice.v1.UpdateNamespaceRequest\x1a\x38.temporal.api.workflowservice.v1.UpdateNamespaceResponse"]\x82\xd3\xe4\x93\x02W"&/cluster/namespaces/{namespace}/update:\x01*Z*"%/api/v1/namespaces/{namespace}/update:\x01*\x12\x8f\x01\n\x12\x44\x65precateNamespace\x12:.temporal.api.workflowservice.v1.DeprecateNamespaceRequest\x1a;.temporal.api.workflowservice.v1.DeprecateNamespaceResponse"\x00\x12\xc6\x02\n\x16StartWorkflowExecution\x12>.temporal.api.workflowservice.v1.StartWorkflowExecutionRequest\x1a?.temporal.api.workflowservice.v1.StartWorkflowExecutionResponse"\xaa\x01\x82\xd3\xe4\x93\x02q"//namespaces/{namespace}/workflows/{workflow_id}:\x01*Z;"6/api/v1/namespaces/{namespace}/workflows/{workflow_id}:\x01*\x8a\x9d\xcc\x1b.\n\x14temporal-resource-id\x12\x16workflow:{workflow_id}\x12\xc2\x01\n\x15\x45xecuteMultiOperation\x12=.temporal.api.workflowservice.v1.ExecuteMultiOperationRequest\x1a>.temporal.api.workflowservice.v1.ExecuteMultiOperationResponse"*\x8a\x9d\xcc\x1b%\n\x14temporal-resource-id\x12\r{resource_id}\x12\xfe\x02\n\x1bGetWorkflowExecutionHistory\x12\x43.temporal.api.workflowservice.v1.GetWorkflowExecutionHistoryRequest\x1a\x44.temporal.api.workflowservice.v1.GetWorkflowExecutionHistoryResponse"\xd3\x01\x82\xd3\xe4\x93\x02\x8f\x01\x12\x41/namespaces/{namespace}/workflows/{execution.workflow_id}/historyZJ\x12H/api/v1/namespaces/{namespace}/workflows/{execution.workflow_id}/history\x8a\x9d\xcc\x1b\x38\n\x14temporal-resource-id\x12 workflow:{execution.workflow_id}\x12\xa3\x03\n"GetWorkflowExecutionHistoryReverse\x12J.temporal.api.workflowservice.v1.GetWorkflowExecutionHistoryReverseRequest\x1aK.temporal.api.workflowservice.v1.GetWorkflowExecutionHistoryReverseResponse"\xe3\x01\x82\xd3\xe4\x93\x02\x9f\x01\x12I/namespaces/{namespace}/workflows/{execution.workflow_id}/history-reverseZR\x12P/api/v1/namespaces/{namespace}/workflows/{execution.workflow_id}/history-reverse\x8a\x9d\xcc\x1b\x38\n\x14temporal-resource-id\x12 workflow:{execution.workflow_id}\x12\xcd\x01\n\x15PollWorkflowTaskQueue\x12=.temporal.api.workflowservice.v1.PollWorkflowTaskQueueRequest\x1a>.temporal.api.workflowservice.v1.PollWorkflowTaskQueueResponse"5\x8a\x9d\xcc\x1b\x30\n\x14temporal-resource-id\x12\x18poller:{poller_group_id}\x12\xd7\x01\n\x1cRespondWorkflowTaskCompleted\x12\x44.temporal.api.workflowservice.v1.RespondWorkflowTaskCompletedRequest\x1a\x45.temporal.api.workflowservice.v1.RespondWorkflowTaskCompletedResponse"*\x8a\x9d\xcc\x1b%\n\x14temporal-resource-id\x12\r{resource_id}\x12\xce\x01\n\x19RespondWorkflowTaskFailed\x12\x41.temporal.api.workflowservice.v1.RespondWorkflowTaskFailedRequest\x1a\x42.temporal.api.workflowservice.v1.RespondWorkflowTaskFailedResponse"*\x8a\x9d\xcc\x1b%\n\x14temporal-resource-id\x12\r{resource_id}\x12\xcd\x01\n\x15PollActivityTaskQueue\x12=.temporal.api.workflowservice.v1.PollActivityTaskQueueRequest\x1a>.temporal.api.workflowservice.v1.PollActivityTaskQueueResponse"5\x8a\x9d\xcc\x1b\x30\n\x14temporal-resource-id\x12\x18poller:{poller_group_id}\x12\xc2\x02\n\x1bRecordActivityTaskHeartbeat\x12\x43.temporal.api.workflowservice.v1.RecordActivityTaskHeartbeatRequest\x1a\x44.temporal.api.workflowservice.v1.RecordActivityTaskHeartbeatResponse"\x97\x01\x82\xd3\xe4\x93\x02g"*/namespaces/{namespace}/activity-heartbeat:\x01*Z6"1/api/v1/namespaces/{namespace}/activity-heartbeat:\x01*\x8a\x9d\xcc\x1b%\n\x14temporal-resource-id\x12\r{resource_id}\x12\xa8\x04\n\x1fRecordActivityTaskHeartbeatById\x12G.temporal.api.workflowservice.v1.RecordActivityTaskHeartbeatByIdRequest\x1aH.temporal.api.workflowservice.v1.RecordActivityTaskHeartbeatByIdResponse"\xf1\x02\x82\xd3\xe4\x93\x02\xc0\x02":/namespaces/{namespace}/activities/{activity_id}/heartbeat:\x01*ZF"A/api/v1/namespaces/{namespace}/activities/{activity_id}/heartbeat:\x01*ZW"R/namespaces/{namespace}/workflows/{workflow_id}/activities/{activity_id}/heartbeat:\x01*Z^"Y/api/v1/namespaces/{namespace}/workflows/{workflow_id}/activities/{activity_id}/heartbeat:\x01*\x8a\x9d\xcc\x1b%\n\x14temporal-resource-id\x12\r{resource_id}\x12\xc3\x02\n\x1cRespondActivityTaskCompleted\x12\x44.temporal.api.workflowservice.v1.RespondActivityTaskCompletedRequest\x1a\x45.temporal.api.workflowservice.v1.RespondActivityTaskCompletedResponse"\x95\x01\x82\xd3\xe4\x93\x02\x65")/namespaces/{namespace}/activity-complete:\x01*Z5"0/api/v1/namespaces/{namespace}/activity-complete:\x01*\x8a\x9d\xcc\x1b%\n\x14temporal-resource-id\x12\r{resource_id}\x12\xa7\x04\n RespondActivityTaskCompletedById\x12H.temporal.api.workflowservice.v1.RespondActivityTaskCompletedByIdRequest\x1aI.temporal.api.workflowservice.v1.RespondActivityTaskCompletedByIdResponse"\xed\x02\x82\xd3\xe4\x93\x02\xbc\x02"9/namespaces/{namespace}/activities/{activity_id}/complete:\x01*ZE"@/api/v1/namespaces/{namespace}/activities/{activity_id}/complete:\x01*ZV"Q/namespaces/{namespace}/workflows/{workflow_id}/activities/{activity_id}/complete:\x01*Z]"X/api/v1/namespaces/{namespace}/workflows/{workflow_id}/activities/{activity_id}/complete:\x01*\x8a\x9d\xcc\x1b%\n\x14temporal-resource-id\x12\r{resource_id}\x12\xb2\x02\n\x19RespondActivityTaskFailed\x12\x41.temporal.api.workflowservice.v1.RespondActivityTaskFailedRequest\x1a\x42.temporal.api.workflowservice.v1.RespondActivityTaskFailedResponse"\x8d\x01\x82\xd3\xe4\x93\x02]"%/namespaces/{namespace}/activity-fail:\x01*Z1",/api/v1/namespaces/{namespace}/activity-fail:\x01*\x8a\x9d\xcc\x1b%\n\x14temporal-resource-id\x12\r{resource_id}\x12\x8e\x04\n\x1dRespondActivityTaskFailedById\x12\x45.temporal.api.workflowservice.v1.RespondActivityTaskFailedByIdRequest\x1a\x46.temporal.api.workflowservice.v1.RespondActivityTaskFailedByIdResponse"\xdd\x02\x82\xd3\xe4\x93\x02\xac\x02"5/namespaces/{namespace}/activities/{activity_id}/fail:\x01*ZA".temporal.api.workflowservice.v1.ResetWorkflowExecutionRequest\x1a?.temporal.api.workflowservice.v1.ResetWorkflowExecutionResponse"\xf0\x01\x82\xd3\xe4\x93\x02\xa3\x01"H/namespaces/{namespace}/workflows/{workflow_execution.workflow_id}/reset:\x01*ZT"O/api/v1/namespaces/{namespace}/workflows/{workflow_execution.workflow_id}/reset:\x01*\x8a\x9d\xcc\x1b\x41\n\x14temporal-resource-id\x12)workflow:{workflow_execution.workflow_id}\x12\xa0\x03\n\x1aTerminateWorkflowExecution\x12\x42.temporal.api.workflowservice.v1.TerminateWorkflowExecutionRequest\x1a\x43.temporal.api.workflowservice.v1.TerminateWorkflowExecutionResponse"\xf8\x01\x82\xd3\xe4\x93\x02\xab\x01"L/namespaces/{namespace}/workflows/{workflow_execution.workflow_id}/terminate:\x01*ZX"S/api/v1/namespaces/{namespace}/workflows/{workflow_execution.workflow_id}/terminate:\x01*\x8a\x9d\xcc\x1b\x41\n\x14temporal-resource-id\x12)workflow:{workflow_execution.workflow_id}\x12\xe4\x01\n\x17\x44\x65leteWorkflowExecution\x12?.temporal.api.workflowservice.v1.DeleteWorkflowExecutionRequest\x1a@.temporal.api.workflowservice.v1.DeleteWorkflowExecutionResponse"F\x8a\x9d\xcc\x1b\x41\n\x14temporal-resource-id\x12)workflow:{workflow_execution.workflow_id}\x12\xa7\x01\n\x1aListOpenWorkflowExecutions\x12\x42.temporal.api.workflowservice.v1.ListOpenWorkflowExecutionsRequest\x1a\x43.temporal.api.workflowservice.v1.ListOpenWorkflowExecutionsResponse"\x00\x12\xad\x01\n\x1cListClosedWorkflowExecutions\x12\x44.temporal.api.workflowservice.v1.ListClosedWorkflowExecutionsRequest\x1a\x45.temporal.api.workflowservice.v1.ListClosedWorkflowExecutionsResponse"\x00\x12\xf0\x01\n\x16ListWorkflowExecutions\x12>.temporal.api.workflowservice.v1.ListWorkflowExecutionsRequest\x1a?.temporal.api.workflowservice.v1.ListWorkflowExecutionsResponse"U\x82\xd3\xe4\x93\x02O\x12!/namespaces/{namespace}/workflowsZ*\x12(/api/v1/namespaces/{namespace}/workflows\x12\x9a\x02\n\x1eListArchivedWorkflowExecutions\x12\x46.temporal.api.workflowservice.v1.ListArchivedWorkflowExecutionsRequest\x1aG.temporal.api.workflowservice.v1.ListArchivedWorkflowExecutionsResponse"g\x82\xd3\xe4\x93\x02\x61\x12*/namespaces/{namespace}/archived-workflowsZ3\x12\x31/api/v1/namespaces/{namespace}/archived-workflows\x12\x9b\x01\n\x16ScanWorkflowExecutions\x12>.temporal.api.workflowservice.v1.ScanWorkflowExecutionsRequest\x1a?.temporal.api.workflowservice.v1.ScanWorkflowExecutionsResponse"\x00\x12\xfd\x01\n\x17\x43ountWorkflowExecutions\x12?.temporal.api.workflowservice.v1.CountWorkflowExecutionsRequest\x1a@.temporal.api.workflowservice.v1.CountWorkflowExecutionsResponse"_\x82\xd3\xe4\x93\x02Y\x12&/namespaces/{namespace}/workflow-countZ/\x12-/api/v1/namespaces/{namespace}/workflow-count\x12\x92\x01\n\x13GetSearchAttributes\x12;.temporal.api.workflowservice.v1.GetSearchAttributesRequest\x1a<.temporal.api.workflowservice.v1.GetSearchAttributesResponse"\x00\x12\xd9\x01\n\x19RespondQueryTaskCompleted\x12\x41.temporal.api.workflowservice.v1.RespondQueryTaskCompletedRequest\x1a\x42.temporal.api.workflowservice.v1.RespondQueryTaskCompletedResponse"5\x8a\x9d\xcc\x1b\x30\n\x14temporal-resource-id\x12\x18poller:{poller_group_id}\x12\xd2\x01\n\x14ResetStickyTaskQueue\x12<.temporal.api.workflowservice.v1.ResetStickyTaskQueueRequest\x1a=.temporal.api.workflowservice.v1.ResetStickyTaskQueueResponse"=\x8a\x9d\xcc\x1b\x38\n\x14temporal-resource-id\x12 workflow:{execution.workflow_id}\x12\x83\x01\n\x0eShutdownWorker\x12\x36.temporal.api.workflowservice.v1.ShutdownWorkerRequest\x1a\x37.temporal.api.workflowservice.v1.ShutdownWorkerResponse"\x00\x12\xfc\x02\n\rQueryWorkflow\x12\x35.temporal.api.workflowservice.v1.QueryWorkflowRequest\x1a\x36.temporal.api.workflowservice.v1.QueryWorkflowResponse"\xfb\x01\x82\xd3\xe4\x93\x02\xb7\x01"R/namespaces/{namespace}/workflows/{execution.workflow_id}/query/{query.query_type}:\x01*Z^"Y/api/v1/namespaces/{namespace}/workflows/{execution.workflow_id}/query/{query.query_type}:\x01*\x8a\x9d\xcc\x1b\x38\n\x14temporal-resource-id\x12 workflow:{execution.workflow_id}\x12\xe7\x02\n\x19\x44\x65scribeWorkflowExecution\x12\x41.temporal.api.workflowservice.v1.DescribeWorkflowExecutionRequest\x1a\x42.temporal.api.workflowservice.v1.DescribeWorkflowExecutionResponse"\xc2\x01\x82\xd3\xe4\x93\x02\x7f\x12\x39/namespaces/{namespace}/workflows/{execution.workflow_id}ZB\x12@/api/v1/namespaces/{namespace}/workflows/{execution.workflow_id}\x8a\x9d\xcc\x1b\x38\n\x14temporal-resource-id\x12 workflow:{execution.workflow_id}\x12\xc2\x02\n\x11\x44\x65scribeTaskQueue\x12\x39.temporal.api.workflowservice.v1.DescribeTaskQueueRequest\x1a:.temporal.api.workflowservice.v1.DescribeTaskQueueResponse"\xb5\x01\x82\xd3\xe4\x93\x02w\x12\x35/namespaces/{namespace}/task-queues/{task_queue.name}Z>\x12/namespaces/{namespace}/schedules/{schedule_id}/matching-timesZG\x12\x45/api/v1/namespaces/{namespace}/schedules/{schedule_id}/matching-times\x8a\x9d\xcc\x1b.\n\x14temporal-resource-id\x12\x16schedule:{schedule_id}\x12\xa8\x02\n\x0e\x44\x65leteSchedule\x12\x36.temporal.api.workflowservice.v1.DeleteScheduleRequest\x1a\x37.temporal.api.workflowservice.v1.DeleteScheduleResponse"\xa4\x01\x82\xd3\xe4\x93\x02k*//namespaces/{namespace}/schedules/{schedule_id}Z8*6/api/v1/namespaces/{namespace}/schedules/{schedule_id}\x8a\x9d\xcc\x1b.\n\x14temporal-resource-id\x12\x16schedule:{schedule_id}\x12\xd5\x01\n\rListSchedules\x12\x35.temporal.api.workflowservice.v1.ListSchedulesRequest\x1a\x36.temporal.api.workflowservice.v1.ListSchedulesResponse"U\x82\xd3\xe4\x93\x02O\x12!/namespaces/{namespace}/schedulesZ*\x12(/api/v1/namespaces/{namespace}/schedules\x12\xe2\x01\n\x0e\x43ountSchedules\x12\x36.temporal.api.workflowservice.v1.CountSchedulesRequest\x1a\x37.temporal.api.workflowservice.v1.CountSchedulesResponse"_\x82\xd3\xe4\x93\x02Y\x12&/namespaces/{namespace}/schedule-countZ/\x12-/api/v1/namespaces/{namespace}/schedule-count\x12\xb9\x01\n UpdateWorkerBuildIdCompatibility\x12H.temporal.api.workflowservice.v1.UpdateWorkerBuildIdCompatibilityRequest\x1aI.temporal.api.workflowservice.v1.UpdateWorkerBuildIdCompatibilityResponse"\x00\x12\xe1\x02\n\x1dGetWorkerBuildIdCompatibility\x12\x45.temporal.api.workflowservice.v1.GetWorkerBuildIdCompatibilityRequest\x1a\x46.temporal.api.workflowservice.v1.GetWorkerBuildIdCompatibilityResponse"\xb0\x01\x82\xd3\xe4\x93\x02\xa9\x01\x12N/namespaces/{namespace}/task-queues/{task_queue}/worker-build-id-compatibilityZW\x12U/api/v1/namespaces/{namespace}/task-queues/{task_queue}/worker-build-id-compatibility\x12\xaa\x01\n\x1bUpdateWorkerVersioningRules\x12\x43.temporal.api.workflowservice.v1.UpdateWorkerVersioningRulesRequest\x1a\x44.temporal.api.workflowservice.v1.UpdateWorkerVersioningRulesResponse"\x00\x12\xc6\x02\n\x18GetWorkerVersioningRules\x12@.temporal.api.workflowservice.v1.GetWorkerVersioningRulesRequest\x1a\x41.temporal.api.workflowservice.v1.GetWorkerVersioningRulesResponse"\xa4\x01\x82\xd3\xe4\x93\x02\x9d\x01\x12H/namespaces/{namespace}/task-queues/{task_queue}/worker-versioning-rulesZQ\x12O/api/v1/namespaces/{namespace}/task-queues/{task_queue}/worker-versioning-rules\x12\x97\x02\n\x19GetWorkerTaskReachability\x12\x41.temporal.api.workflowservice.v1.GetWorkerTaskReachabilityRequest\x1a\x42.temporal.api.workflowservice.v1.GetWorkerTaskReachabilityResponse"s\x82\xd3\xe4\x93\x02m\x12\x30/namespaces/{namespace}/worker-task-reachabilityZ9\x12\x37/api/v1/namespaces/{namespace}/worker-task-reachability\x12\xc8\x02\n\x12\x44\x65scribeDeployment\x12:.temporal.api.workflowservice.v1.DescribeDeploymentRequest\x1a;.temporal.api.workflowservice.v1.DescribeDeploymentResponse"\xb8\x01\x82\xd3\xe4\x93\x02\xb1\x01\x12R/namespaces/{namespace}/deployments/{deployment.series_name}/{deployment.build_id}Z[\x12Y/api/v1/namespaces/{namespace}/deployments/{deployment.series_name}/{deployment.build_id}\x12\x81\x04\n\x1f\x44\x65scribeWorkerDeploymentVersion\x12G.temporal.api.workflowservice.v1.DescribeWorkerDeploymentVersionRequest\x1aH.temporal.api.workflowservice.v1.DescribeWorkerDeploymentVersionResponse"\xca\x02\x82\xd3\xe4\x93\x02\xf7\x01\x12u/namespaces/{namespace}/worker-deployment-versions/{deployment_version.deployment_name}/{deployment_version.build_id}Z~\x12|/api/v1/namespaces/{namespace}/worker-deployment-versions/{deployment_version.deployment_name}/{deployment_version.build_id}\x8a\x9d\xcc\x1bG\n\x14temporal-resource-id\x12/deployment:{deployment_version.deployment_name}\x12\xdf\x01\n\x0fListDeployments\x12\x37.temporal.api.workflowservice.v1.ListDeploymentsRequest\x1a\x38.temporal.api.workflowservice.v1.ListDeploymentsResponse"Y\x82\xd3\xe4\x93\x02S\x12#/namespaces/{namespace}/deploymentsZ,\x12*/api/v1/namespaces/{namespace}/deployments\x12\xf7\x02\n\x19GetDeploymentReachability\x12\x41.temporal.api.workflowservice.v1.GetDeploymentReachabilityRequest\x1a\x42.temporal.api.workflowservice.v1.GetDeploymentReachabilityResponse"\xd2\x01\x82\xd3\xe4\x93\x02\xcb\x01\x12_/namespaces/{namespace}/deployments/{deployment.series_name}/{deployment.build_id}/reachabilityZh\x12\x66/api/v1/namespaces/{namespace}/deployments/{deployment.series_name}/{deployment.build_id}/reachability\x12\x99\x02\n\x14GetCurrentDeployment\x12<.temporal.api.workflowservice.v1.GetCurrentDeploymentRequest\x1a=.temporal.api.workflowservice.v1.GetCurrentDeploymentResponse"\x83\x01\x82\xd3\xe4\x93\x02}\x12\x38/namespaces/{namespace}/current-deployment/{series_name}ZA\x12?/api/v1/namespaces/{namespace}/current-deployment/{series_name}\x12\xb6\x02\n\x14SetCurrentDeployment\x12<.temporal.api.workflowservice.v1.SetCurrentDeploymentRequest\x1a=.temporal.api.workflowservice.v1.SetCurrentDeploymentResponse"\xa0\x01\x82\xd3\xe4\x93\x02\x99\x01"C/namespaces/{namespace}/current-deployment/{deployment.series_name}:\x01*ZO"J/api/v1/namespaces/{namespace}/current-deployment/{deployment.series_name}:\x01*\x12\xb0\x03\n!SetWorkerDeploymentCurrentVersion\x12I.temporal.api.workflowservice.v1.SetWorkerDeploymentCurrentVersionRequest\x1aJ.temporal.api.workflowservice.v1.SetWorkerDeploymentCurrentVersionResponse"\xf3\x01\x82\xd3\xe4\x93\x02\xb3\x01"P/namespaces/{namespace}/worker-deployments/{deployment_name}/set-current-version:\x01*Z\\"W/api/v1/namespaces/{namespace}/worker-deployments/{deployment_name}/set-current-version:\x01*\x8a\x9d\xcc\x1b\x34\n\x14temporal-resource-id\x12\x1c\x64\x65ployment:{deployment_name}\x12\xe7\x02\n\x18\x44\x65scribeWorkerDeployment\x12@.temporal.api.workflowservice.v1.DescribeWorkerDeploymentRequest\x1a\x41.temporal.api.workflowservice.v1.DescribeWorkerDeploymentResponse"\xc5\x01\x82\xd3\xe4\x93\x02\x85\x01\x12.temporal.api.workflowservice.v1.DeleteWorkerDeploymentRequest\x1a?.temporal.api.workflowservice.v1.DeleteWorkerDeploymentResponse"\xc5\x01\x82\xd3\xe4\x93\x02\x85\x01*.temporal.api.workflowservice.v1.ListWorkerDeploymentsResponse"g\x82\xd3\xe4\x93\x02\x61\x12*/namespaces/{namespace}/worker-deploymentsZ3\x12\x31/api/v1/namespaces/{namespace}/worker-deployments\x12\xae\x02\n\x16\x43reateWorkerDeployment\x12>.temporal.api.workflowservice.v1.CreateWorkerDeploymentRequest\x1a?.temporal.api.workflowservice.v1.CreateWorkerDeploymentResponse"\x92\x01\x82\xd3\xe4\x93\x02\x8b\x01".temporal.api.workflowservice.v1.DescribeBatchOperationRequest\x1a?.temporal.api.workflowservice.v1.DescribeBatchOperationResponse"\xa0\x01\x82\xd3\xe4\x93\x02o\x12\x31/namespaces/{namespace}/batch-operations/{job_id}Z:\x12\x38/api/v1/namespaces/{namespace}/batch-operations/{job_id}\x8a\x9d\xcc\x1b&\n\x14temporal-resource-id\x12\x0e\x62\x61tch:{job_id}\x12\xf5\x01\n\x13ListBatchOperations\x12;.temporal.api.workflowservice.v1.ListBatchOperationsRequest\x1a<.temporal.api.workflowservice.v1.ListBatchOperationsResponse"c\x82\xd3\xe4\x93\x02]\x12(/namespaces/{namespace}/batch-operationsZ1\x12//api/v1/namespaces/{namespace}/batch-operations\x12\xc4\x01\n\x12PollNexusTaskQueue\x12:.temporal.api.workflowservice.v1.PollNexusTaskQueueRequest\x1a;.temporal.api.workflowservice.v1.PollNexusTaskQueueResponse"5\x8a\x9d\xcc\x1b\x30\n\x14temporal-resource-id\x12\x18poller:{poller_group_id}\x12\xd9\x01\n\x19RespondNexusTaskCompleted\x12\x41.temporal.api.workflowservice.v1.RespondNexusTaskCompletedRequest\x1a\x42.temporal.api.workflowservice.v1.RespondNexusTaskCompletedResponse"5\x8a\x9d\xcc\x1b\x30\n\x14temporal-resource-id\x12\x18poller:{poller_group_id}\x12\xd0\x01\n\x16RespondNexusTaskFailed\x12>.temporal.api.workflowservice.v1.RespondNexusTaskFailedRequest\x1a?.temporal.api.workflowservice.v1.RespondNexusTaskFailedResponse"5\x8a\x9d\xcc\x1b\x30\n\x14temporal-resource-id\x12\x18poller:{poller_group_id}\x12\xe8\x02\n\x15UpdateActivityOptions\x12=.temporal.api.workflowservice.v1.UpdateActivityOptionsRequest\x1a>.temporal.api.workflowservice.v1.UpdateActivityOptionsResponse"\xcf\x01\x82\xd3\xe4\x93\x02\x8b\x01".temporal.api.workflowservice.v1.RecordWorkerHeartbeatResponse"\x95\x01\x82\xd3\xe4\x93\x02\x65")/namespaces/{namespace}/workers/heartbeat:\x01*Z5"0/api/v1/namespaces/{namespace}/workers/heartbeat:\x01*\x8a\x9d\xcc\x1b%\n\x14temporal-resource-id\x12\r{resource_id}\x12\xcb\x01\n\x0bListWorkers\x12\x33.temporal.api.workflowservice.v1.ListWorkersRequest\x1a\x34.temporal.api.workflowservice.v1.ListWorkersResponse"Q\x82\xd3\xe4\x93\x02K\x12\x1f/namespaces/{namespace}/workersZ(\x12&/api/v1/namespaces/{namespace}/workers\x12\xe2\x02\n\x15UpdateTaskQueueConfig\x12=.temporal.api.workflowservice.v1.UpdateTaskQueueConfigRequest\x1a>.temporal.api.workflowservice.v1.UpdateTaskQueueConfigResponse"\xc9\x01\x82\xd3\xe4\x93\x02\x8f\x01">/namespaces/{namespace}/task-queues/{task_queue}/update-config:\x01*ZJ"E/api/v1/namespaces/{namespace}/task-queues/{task_queue}/update-config:\x01*\x8a\x9d\xcc\x1b.\n\x14temporal-resource-id\x12\x16taskqueue:{task_queue}\x12\xa8\x02\n\x11\x46\x65tchWorkerConfig\x12\x39.temporal.api.workflowservice.v1.FetchWorkerConfigRequest\x1a:.temporal.api.workflowservice.v1.FetchWorkerConfigResponse"\x9b\x01\x82\xd3\xe4\x93\x02k",/namespaces/{namespace}/workers/fetch-config:\x01*Z8"3/api/v1/namespaces/{namespace}/workers/fetch-config:\x01*\x8a\x9d\xcc\x1b%\n\x14temporal-resource-id\x12\r{resource_id}\x12\xad\x02\n\x12UpdateWorkerConfig\x12:.temporal.api.workflowservice.v1.UpdateWorkerConfigRequest\x1a;.temporal.api.workflowservice.v1.UpdateWorkerConfigResponse"\x9d\x01\x82\xd3\xe4\x93\x02m"-/namespaces/{namespace}/workers/update-config:\x01*Z9"4/api/v1/namespaces/{namespace}/workers/update-config:\x01*\x8a\x9d\xcc\x1b%\n\x14temporal-resource-id\x12\r{resource_id}\x12\xcd\x02\n\x0e\x44\x65scribeWorker\x12\x36.temporal.api.workflowservice.v1.DescribeWorkerRequest\x1a\x37.temporal.api.workflowservice.v1.DescribeWorkerResponse"\xc9\x01\x82\xd3\xe4\x93\x02\x89\x01\x12>/namespaces/{namespace}/workers/describe/{worker_instance_key}ZG\x12\x45/api/v1/namespaces/{namespace}/workers/describe/{worker_instance_key}\x8a\x9d\xcc\x1b\x34\n\x14temporal-resource-id\x12\x1cworker:{worker_instance_key}\x12\xd2\x02\n\x16PauseWorkflowExecution\x12>.temporal.api.workflowservice.v1.PauseWorkflowExecutionRequest\x1a?.temporal.api.workflowservice.v1.PauseWorkflowExecutionResponse"\xb6\x01\x82\xd3\xe4\x93\x02}"5/namespaces/{namespace}/workflows/{workflow_id}/pause:\x01*ZA"/api/v1/namespaces/{namespace}/workflows/{workflow_id}/unpause:\x01*\x8a\x9d\xcc\x1b.\n\x14temporal-resource-id\x12\x16workflow:{workflow_id}\x12\xc8\x02\n\x16StartActivityExecution\x12>.temporal.api.workflowservice.v1.StartActivityExecutionRequest\x1a?.temporal.api.workflowservice.v1.StartActivityExecutionResponse"\xac\x01\x82\xd3\xe4\x93\x02s"0/namespaces/{namespace}/activities/{activity_id}:\x01*Z<"7/api/v1/namespaces/{namespace}/activities/{activity_id}:\x01*\x8a\x9d\xcc\x1b.\n\x14temporal-resource-id\x12\x16\x61\x63tivity:{activity_id}\x12\xb6\x02\n\x1cStartNexusOperationExecution\x12\x44.temporal.api.workflowservice.v1.StartNexusOperationExecutionRequest\x1a\x45.temporal.api.workflowservice.v1.StartNexusOperationExecutionResponse"\x88\x01\x82\xd3\xe4\x93\x02\x81\x01"7/namespaces/{namespace}/nexus-operations/{operation_id}:\x01*ZC">/api/v1/namespaces/{namespace}/nexus-operations/{operation_id}:\x01*\x12\xcb\x02\n\x19\x44\x65scribeActivityExecution\x12\x41.temporal.api.workflowservice.v1.DescribeActivityExecutionRequest\x1a\x42.temporal.api.workflowservice.v1.DescribeActivityExecutionResponse"\xa6\x01\x82\xd3\xe4\x93\x02m\x12\x30/namespaces/{namespace}/activities/{activity_id}Z9\x12\x37/api/v1/namespaces/{namespace}/activities/{activity_id}\x8a\x9d\xcc\x1b.\n\x14temporal-resource-id\x12\x16\x61\x63tivity:{activity_id}\x12\xb8\x02\n\x1f\x44\x65scribeNexusOperationExecution\x12G.temporal.api.workflowservice.v1.DescribeNexusOperationExecutionRequest\x1aH.temporal.api.workflowservice.v1.DescribeNexusOperationExecutionResponse"\x81\x01\x82\xd3\xe4\x93\x02{\x12\x37/namespaces/{namespace}/nexus-operations/{operation_id}Z@\x12>/api/v1/namespaces/{namespace}/nexus-operations/{operation_id}\x12\xcf\x02\n\x15PollActivityExecution\x12=.temporal.api.workflowservice.v1.PollActivityExecutionRequest\x1a>.temporal.api.workflowservice.v1.PollActivityExecutionResponse"\xb6\x01\x82\xd3\xe4\x93\x02}\x12\x38/namespaces/{namespace}/activities/{activity_id}/outcomeZA\x12?/api/v1/namespaces/{namespace}/activities/{activity_id}/outcome\x8a\x9d\xcc\x1b.\n\x14temporal-resource-id\x12\x16\x61\x63tivity:{activity_id}\x12\xb7\x02\n\x1bPollNexusOperationExecution\x12\x43.temporal.api.workflowservice.v1.PollNexusOperationExecutionRequest\x1a\x44.temporal.api.workflowservice.v1.PollNexusOperationExecutionResponse"\x8c\x01\x82\xd3\xe4\x93\x02\x85\x01\x12.temporal.api.workflowservice.v1.ListActivityExecutionsRequest\x1a?.temporal.api.workflowservice.v1.ListActivityExecutionsResponse"W\x82\xd3\xe4\x93\x02Q\x12"/namespaces/{namespace}/activitiesZ+\x12)/api/v1/namespaces/{namespace}/activities\x12\x90\x02\n\x1cListNexusOperationExecutions\x12\x44.temporal.api.workflowservice.v1.ListNexusOperationExecutionsRequest\x1a\x45.temporal.api.workflowservice.v1.ListNexusOperationExecutionsResponse"c\x82\xd3\xe4\x93\x02]\x12(/namespaces/{namespace}/nexus-operationsZ1\x12//api/v1/namespaces/{namespace}/nexus-operations\x12\xfd\x01\n\x17\x43ountActivityExecutions\x12?.temporal.api.workflowservice.v1.CountActivityExecutionsRequest\x1a@.temporal.api.workflowservice.v1.CountActivityExecutionsResponse"_\x82\xd3\xe4\x93\x02Y\x12&/namespaces/{namespace}/activity-countZ/\x12-/api/v1/namespaces/{namespace}/activity-count\x12\x9d\x02\n\x1d\x43ountNexusOperationExecutions\x12\x45.temporal.api.workflowservice.v1.CountNexusOperationExecutionsRequest\x1a\x46.temporal.api.workflowservice.v1.CountNexusOperationExecutionsResponse"m\x82\xd3\xe4\x93\x02g\x12-/namespaces/{namespace}/nexus-operation-countZ6\x12\x34/api/v1/namespaces/{namespace}/nexus-operation-count\x12\xef\x02\n\x1eRequestCancelActivityExecution\x12\x46.temporal.api.workflowservice.v1.RequestCancelActivityExecutionRequest\x1aG.temporal.api.workflowservice.v1.RequestCancelActivityExecutionResponse"\xbb\x01\x82\xd3\xe4\x93\x02\x81\x01"7/namespaces/{namespace}/activities/{activity_id}/cancel:\x01*ZC">/api/v1/namespaces/{namespace}/activities/{activity_id}/cancel:\x01*\x8a\x9d\xcc\x1b.\n\x14temporal-resource-id\x12\x16\x61\x63tivity:{activity_id}\x12\xdc\x02\n$RequestCancelNexusOperationExecution\x12L.temporal.api.workflowservice.v1.RequestCancelNexusOperationExecutionRequest\x1aM.temporal.api.workflowservice.v1.RequestCancelNexusOperationExecutionResponse"\x96\x01\x82\xd3\xe4\x93\x02\x8f\x01">/namespaces/{namespace}/nexus-operations/{operation_id}/cancel:\x01*ZJ"E/api/v1/namespaces/{namespace}/nexus-operations/{operation_id}/cancel:\x01*\x12\xe9\x02\n\x1aTerminateActivityExecution\x12\x42.temporal.api.workflowservice.v1.TerminateActivityExecutionRequest\x1a\x43.temporal.api.workflowservice.v1.TerminateActivityExecutionResponse"\xc1\x01\x82\xd3\xe4\x93\x02\x87\x01":/namespaces/{namespace}/activities/{activity_id}/terminate:\x01*ZF"A/api/v1/namespaces/{namespace}/activities/{activity_id}/terminate:\x01*\x8a\x9d\xcc\x1b.\n\x14temporal-resource-id\x12\x16\x61\x63tivity:{activity_id}\x12\x9e\x01\n\x17\x44\x65leteActivityExecution\x12?.temporal.api.workflowservice.v1.DeleteActivityExecutionRequest\x1a@.temporal.api.workflowservice.v1.DeleteActivityExecutionResponse"\x00\x12\xfd\x03\n\x16PauseActivityExecution\x12>.temporal.api.workflowservice.v1.PauseActivityExecutionRequest\x1a?.temporal.api.workflowservice.v1.PauseActivityExecutionResponse"\xe1\x02\x82\xd3\xe4\x93\x02\xb0\x02"6/namespaces/{namespace}/activities/{activity_id}/pause:\x01*ZB"=/api/v1/namespaces/{namespace}/activities/{activity_id}/pause:\x01*ZS"N/namespaces/{namespace}/workflows/{workflow_id}/activities/{activity_id}/pause:\x01*ZZ"U/api/v1/namespaces/{namespace}/workflows/{workflow_id}/activities/{activity_id}/pause:\x01*\x8a\x9d\xcc\x1b%\n\x14temporal-resource-id\x12\r{resource_id}\x12\xfd\x03\n\x16ResetActivityExecution\x12>.temporal.api.workflowservice.v1.ResetActivityExecutionRequest\x1a?.temporal.api.workflowservice.v1.ResetActivityExecutionResponse"\xe1\x02\x82\xd3\xe4\x93\x02\xb0\x02"6/namespaces/{namespace}/activities/{activity_id}/reset:\x01*ZB"=/api/v1/namespaces/{namespace}/activities/{activity_id}/reset:\x01*ZS"N/namespaces/{namespace}/workflows/{workflow_id}/activities/{activity_id}/reset:\x01*ZZ"U/api/v1/namespaces/{namespace}/workflows/{workflow_id}/activities/{activity_id}/reset:\x01*\x8a\x9d\xcc\x1b%\n\x14temporal-resource-id\x12\r{resource_id}\x12\x8b\x04\n\x18UnpauseActivityExecution\x12@.temporal.api.workflowservice.v1.UnpauseActivityExecutionRequest\x1a\x41.temporal.api.workflowservice.v1.UnpauseActivityExecutionResponse"\xe9\x02\x82\xd3\xe4\x93\x02\xb8\x02"8/namespaces/{namespace}/activities/{activity_id}/unpause:\x01*ZD"?/api/v1/namespaces/{namespace}/activities/{activity_id}/unpause:\x01*ZU"P/namespaces/{namespace}/workflows/{workflow_id}/activities/{activity_id}/unpause:\x01*Z\\"W/api/v1/namespaces/{namespace}/workflows/{workflow_id}/activities/{activity_id}/unpause:\x01*\x8a\x9d\xcc\x1b%\n\x14temporal-resource-id\x12\r{resource_id}\x12\xb9\x04\n\x1eUpdateActivityExecutionOptions\x12\x46.temporal.api.workflowservice.v1.UpdateActivityExecutionOptionsRequest\x1aG.temporal.api.workflowservice.v1.UpdateActivityExecutionOptionsResponse"\x85\x03\x82\xd3\xe4\x93\x02\xd4\x02"?/namespaces/{namespace}/activities/{activity_id}/update-options:\x01*ZK"F/api/v1/namespaces/{namespace}/activities/{activity_id}/update-options:\x01*Z\\"W/namespaces/{namespace}/workflows/{workflow_id}/activities/{activity_id}/update-options:\x01*Zc"^/api/v1/namespaces/{namespace}/workflows/{workflow_id}/activities/{activity_id}/update-options:\x01*\x8a\x9d\xcc\x1b%\n\x14temporal-resource-id\x12\r{resource_id}\x12\xd6\x02\n TerminateNexusOperationExecution\x12H.temporal.api.workflowservice.v1.TerminateNexusOperationExecutionRequest\x1aI.temporal.api.workflowservice.v1.TerminateNexusOperationExecutionResponse"\x9c\x01\x82\xd3\xe4\x93\x02\x95\x01"A/namespaces/{namespace}/nexus-operations/{operation_id}/terminate:\x01*ZM"H/api/v1/namespaces/{namespace}/nexus-operations/{operation_id}/terminate:\x01*\x12\xb0\x01\n\x1d\x44\x65leteNexusOperationExecution\x12\x45.temporal.api.workflowservice.v1.DeleteNexusOperationExecutionRequest\x1a\x46.temporal.api.workflowservice.v1.DeleteNexusOperationExecutionResponse"\x00\x42\xb6\x01\n"io.temporal.api.workflowservice.v1B\x0cServiceProtoP\x01Z5go.temporal.io/api/workflowservice/v1;workflowservice\xaa\x02!Temporalio.Api.WorkflowService.V1\xea\x02$Temporalio::Api::WorkflowService::V1b\x06proto3' ) @@ -405,7 +405,7 @@ _WORKFLOWSERVICE.methods_by_name["TriggerWorkflowRule"]._options = None _WORKFLOWSERVICE.methods_by_name[ "TriggerWorkflowRule" - ]._serialized_options = b'\202\323\344\223\002\237\001"F/namespaces/{namespace}/workflows/{execution.workflow_id}/trigger-rule:\001*ZR"M/api/v1/namespaces/{namespace}/workflows/{execution.workflow_id}/trigger-rule:\001*' + ]._serialized_options = b'\202\323\344\223\002\237\001"F/namespaces/{namespace}/workflows/{execution.workflow_id}/trigger-rule:\001*ZR"M/api/v1/namespaces/{namespace}/workflows/{execution.workflow_id}/trigger-rule:\001*\212\235\314\0338\n\024temporal-resource-id\022 workflow:{execution.workflow_id}' _WORKFLOWSERVICE.methods_by_name["RecordWorkerHeartbeat"]._options = None _WORKFLOWSERVICE.methods_by_name[ "RecordWorkerHeartbeat" @@ -492,10 +492,26 @@ _WORKFLOWSERVICE.methods_by_name[ "TerminateActivityExecution" ]._serialized_options = b'\202\323\344\223\002\207\001":/namespaces/{namespace}/activities/{activity_id}/terminate:\001*ZF"A/api/v1/namespaces/{namespace}/activities/{activity_id}/terminate:\001*\212\235\314\033.\n\024temporal-resource-id\022\026activity:{activity_id}' + _WORKFLOWSERVICE.methods_by_name["PauseActivityExecution"]._options = None + _WORKFLOWSERVICE.methods_by_name[ + "PauseActivityExecution" + ]._serialized_options = b'\202\323\344\223\002\260\002"6/namespaces/{namespace}/activities/{activity_id}/pause:\001*ZB"=/api/v1/namespaces/{namespace}/activities/{activity_id}/pause:\001*ZS"N/namespaces/{namespace}/workflows/{workflow_id}/activities/{activity_id}/pause:\001*ZZ"U/api/v1/namespaces/{namespace}/workflows/{workflow_id}/activities/{activity_id}/pause:\001*\212\235\314\033%\n\024temporal-resource-id\022\r{resource_id}' + _WORKFLOWSERVICE.methods_by_name["ResetActivityExecution"]._options = None + _WORKFLOWSERVICE.methods_by_name[ + "ResetActivityExecution" + ]._serialized_options = b'\202\323\344\223\002\260\002"6/namespaces/{namespace}/activities/{activity_id}/reset:\001*ZB"=/api/v1/namespaces/{namespace}/activities/{activity_id}/reset:\001*ZS"N/namespaces/{namespace}/workflows/{workflow_id}/activities/{activity_id}/reset:\001*ZZ"U/api/v1/namespaces/{namespace}/workflows/{workflow_id}/activities/{activity_id}/reset:\001*\212\235\314\033%\n\024temporal-resource-id\022\r{resource_id}' + _WORKFLOWSERVICE.methods_by_name["UnpauseActivityExecution"]._options = None + _WORKFLOWSERVICE.methods_by_name[ + "UnpauseActivityExecution" + ]._serialized_options = b'\202\323\344\223\002\270\002"8/namespaces/{namespace}/activities/{activity_id}/unpause:\001*ZD"?/api/v1/namespaces/{namespace}/activities/{activity_id}/unpause:\001*ZU"P/namespaces/{namespace}/workflows/{workflow_id}/activities/{activity_id}/unpause:\001*Z\\"W/api/v1/namespaces/{namespace}/workflows/{workflow_id}/activities/{activity_id}/unpause:\001*\212\235\314\033%\n\024temporal-resource-id\022\r{resource_id}' + _WORKFLOWSERVICE.methods_by_name["UpdateActivityExecutionOptions"]._options = None + _WORKFLOWSERVICE.methods_by_name[ + "UpdateActivityExecutionOptions" + ]._serialized_options = b'\202\323\344\223\002\324\002"?/namespaces/{namespace}/activities/{activity_id}/update-options:\001*ZK"F/api/v1/namespaces/{namespace}/activities/{activity_id}/update-options:\001*Z\\"W/namespaces/{namespace}/workflows/{workflow_id}/activities/{activity_id}/update-options:\001*Zc"^/api/v1/namespaces/{namespace}/workflows/{workflow_id}/activities/{activity_id}/update-options:\001*\212\235\314\033%\n\024temporal-resource-id\022\r{resource_id}' _WORKFLOWSERVICE.methods_by_name["TerminateNexusOperationExecution"]._options = None _WORKFLOWSERVICE.methods_by_name[ "TerminateNexusOperationExecution" ]._serialized_options = b'\202\323\344\223\002\225\001"A/namespaces/{namespace}/nexus-operations/{operation_id}/terminate:\001*ZM"H/api/v1/namespaces/{namespace}/nexus-operations/{operation_id}/terminate:\001*' _WORKFLOWSERVICE._serialized_start = 215 - _WORKFLOWSERVICE._serialized_end = 36608 + _WORKFLOWSERVICE._serialized_end = 38791 # @@protoc_insertion_point(module_scope) diff --git a/temporalio/api/workflowservice/v1/service_pb2_grpc.py b/temporalio/api/workflowservice/v1/service_pb2_grpc.py index 3190ce460..feaaf4dde 100644 --- a/temporalio/api/workflowservice/v1/service_pb2_grpc.py +++ b/temporalio/api/workflowservice/v1/service_pb2_grpc.py @@ -603,6 +603,26 @@ def __init__(self, channel): request_serializer=temporal_dot_api_dot_workflowservice_dot_v1_dot_request__response__pb2.DeleteActivityExecutionRequest.SerializeToString, response_deserializer=temporal_dot_api_dot_workflowservice_dot_v1_dot_request__response__pb2.DeleteActivityExecutionResponse.FromString, ) + self.PauseActivityExecution = channel.unary_unary( + "/temporal.api.workflowservice.v1.WorkflowService/PauseActivityExecution", + request_serializer=temporal_dot_api_dot_workflowservice_dot_v1_dot_request__response__pb2.PauseActivityExecutionRequest.SerializeToString, + response_deserializer=temporal_dot_api_dot_workflowservice_dot_v1_dot_request__response__pb2.PauseActivityExecutionResponse.FromString, + ) + self.ResetActivityExecution = channel.unary_unary( + "/temporal.api.workflowservice.v1.WorkflowService/ResetActivityExecution", + request_serializer=temporal_dot_api_dot_workflowservice_dot_v1_dot_request__response__pb2.ResetActivityExecutionRequest.SerializeToString, + response_deserializer=temporal_dot_api_dot_workflowservice_dot_v1_dot_request__response__pb2.ResetActivityExecutionResponse.FromString, + ) + self.UnpauseActivityExecution = channel.unary_unary( + "/temporal.api.workflowservice.v1.WorkflowService/UnpauseActivityExecution", + request_serializer=temporal_dot_api_dot_workflowservice_dot_v1_dot_request__response__pb2.UnpauseActivityExecutionRequest.SerializeToString, + response_deserializer=temporal_dot_api_dot_workflowservice_dot_v1_dot_request__response__pb2.UnpauseActivityExecutionResponse.FromString, + ) + self.UpdateActivityExecutionOptions = channel.unary_unary( + "/temporal.api.workflowservice.v1.WorkflowService/UpdateActivityExecutionOptions", + request_serializer=temporal_dot_api_dot_workflowservice_dot_v1_dot_request__response__pb2.UpdateActivityExecutionOptionsRequest.SerializeToString, + response_deserializer=temporal_dot_api_dot_workflowservice_dot_v1_dot_request__response__pb2.UpdateActivityExecutionOptionsResponse.FromString, + ) self.TerminateNexusOperationExecution = channel.unary_unary( "/temporal.api.workflowservice.v1.WorkflowService/TerminateNexusOperationExecution", request_serializer=temporal_dot_api_dot_workflowservice_dot_v1_dot_request__response__pb2.TerminateNexusOperationExecutionRequest.SerializeToString, @@ -1811,6 +1831,65 @@ def DeleteActivityExecution(self, request, context): context.set_details("Method not implemented!") raise NotImplementedError("Method not implemented!") + def PauseActivityExecution(self, request, context): + """PauseActivityExecution pauses the execution of an activity specified by its ID. + This API can be used to target a workflow activity or a standalone activity + + Pausing an activity means: + - If the activity is currently waiting for a retry or is running and subsequently fails, + it will not be rescheduled until it is unpaused. + - If the activity is already paused, calling this method will have no effect. + - If the activity is running and finishes successfully, the activity will be completed. + - If the activity is running and finishes with failure: + * if there is no retry left - the activity will be completed. + * if there are more retries left - the activity will be paused. + For long-running activities: + - activities in paused state will send a cancellation with "activity_paused" set to 'true' in response to 'RecordActivityTaskHeartbeat'. + + Returns a `NotFound` error if there is no pending activity with the provided ID + """ + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details("Method not implemented!") + raise NotImplementedError("Method not implemented!") + + def ResetActivityExecution(self, request, context): + """ResetActivityExecution resets the execution of an activity specified by its ID. + This API can be used to target a workflow activity or a standalone activity. + + Resetting an activity means: + * number of attempts will be reset to 0. + * activity timeouts will be reset. + * if the activity is waiting for retry, and it is not paused or 'keep_paused' is not provided: + it will be scheduled immediately (* see 'jitter' flag) + + Returns a `NotFound` error if there is no pending activity with the provided ID or type. + """ + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details("Method not implemented!") + raise NotImplementedError("Method not implemented!") + + def UnpauseActivityExecution(self, request, context): + """UnpauseActivityExecution unpauses the execution of an activity specified by its ID. + This API can be used to target a workflow activity or a standalone activity. + + If activity is not paused, this call will have no effect. + If the activity was paused while waiting for retry, it will be scheduled immediately (* see 'jitter' flag). + Once the activity is unpaused, all timeout timers will be regenerated. + + Returns a `NotFound` error if there is no pending activity with the provided ID + """ + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details("Method not implemented!") + raise NotImplementedError("Method not implemented!") + + def UpdateActivityExecutionOptions(self, request, context): + """UpdateActivityExecutionOptions is called by the client to update the options of an activity by its ID. + This API can be used to target a workflow activity or a standalone activity. + """ + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details("Method not implemented!") + raise NotImplementedError("Method not implemented!") + def TerminateNexusOperationExecution(self, request, context): """TerminateNexusOperationExecution terminates an existing Nexus operation immediately. @@ -2411,6 +2490,26 @@ def add_WorkflowServiceServicer_to_server(servicer, server): request_deserializer=temporal_dot_api_dot_workflowservice_dot_v1_dot_request__response__pb2.DeleteActivityExecutionRequest.FromString, response_serializer=temporal_dot_api_dot_workflowservice_dot_v1_dot_request__response__pb2.DeleteActivityExecutionResponse.SerializeToString, ), + "PauseActivityExecution": grpc.unary_unary_rpc_method_handler( + servicer.PauseActivityExecution, + request_deserializer=temporal_dot_api_dot_workflowservice_dot_v1_dot_request__response__pb2.PauseActivityExecutionRequest.FromString, + response_serializer=temporal_dot_api_dot_workflowservice_dot_v1_dot_request__response__pb2.PauseActivityExecutionResponse.SerializeToString, + ), + "ResetActivityExecution": grpc.unary_unary_rpc_method_handler( + servicer.ResetActivityExecution, + request_deserializer=temporal_dot_api_dot_workflowservice_dot_v1_dot_request__response__pb2.ResetActivityExecutionRequest.FromString, + response_serializer=temporal_dot_api_dot_workflowservice_dot_v1_dot_request__response__pb2.ResetActivityExecutionResponse.SerializeToString, + ), + "UnpauseActivityExecution": grpc.unary_unary_rpc_method_handler( + servicer.UnpauseActivityExecution, + request_deserializer=temporal_dot_api_dot_workflowservice_dot_v1_dot_request__response__pb2.UnpauseActivityExecutionRequest.FromString, + response_serializer=temporal_dot_api_dot_workflowservice_dot_v1_dot_request__response__pb2.UnpauseActivityExecutionResponse.SerializeToString, + ), + "UpdateActivityExecutionOptions": grpc.unary_unary_rpc_method_handler( + servicer.UpdateActivityExecutionOptions, + request_deserializer=temporal_dot_api_dot_workflowservice_dot_v1_dot_request__response__pb2.UpdateActivityExecutionOptionsRequest.FromString, + response_serializer=temporal_dot_api_dot_workflowservice_dot_v1_dot_request__response__pb2.UpdateActivityExecutionOptionsResponse.SerializeToString, + ), "TerminateNexusOperationExecution": grpc.unary_unary_rpc_method_handler( servicer.TerminateNexusOperationExecution, request_deserializer=temporal_dot_api_dot_workflowservice_dot_v1_dot_request__response__pb2.TerminateNexusOperationExecutionRequest.FromString, @@ -5778,6 +5877,122 @@ def DeleteActivityExecution( metadata, ) + @staticmethod + def PauseActivityExecution( + request, + target, + options=(), + channel_credentials=None, + call_credentials=None, + insecure=False, + compression=None, + wait_for_ready=None, + timeout=None, + metadata=None, + ): + return grpc.experimental.unary_unary( + request, + target, + "/temporal.api.workflowservice.v1.WorkflowService/PauseActivityExecution", + temporal_dot_api_dot_workflowservice_dot_v1_dot_request__response__pb2.PauseActivityExecutionRequest.SerializeToString, + temporal_dot_api_dot_workflowservice_dot_v1_dot_request__response__pb2.PauseActivityExecutionResponse.FromString, + options, + channel_credentials, + insecure, + call_credentials, + compression, + wait_for_ready, + timeout, + metadata, + ) + + @staticmethod + def ResetActivityExecution( + request, + target, + options=(), + channel_credentials=None, + call_credentials=None, + insecure=False, + compression=None, + wait_for_ready=None, + timeout=None, + metadata=None, + ): + return grpc.experimental.unary_unary( + request, + target, + "/temporal.api.workflowservice.v1.WorkflowService/ResetActivityExecution", + temporal_dot_api_dot_workflowservice_dot_v1_dot_request__response__pb2.ResetActivityExecutionRequest.SerializeToString, + temporal_dot_api_dot_workflowservice_dot_v1_dot_request__response__pb2.ResetActivityExecutionResponse.FromString, + options, + channel_credentials, + insecure, + call_credentials, + compression, + wait_for_ready, + timeout, + metadata, + ) + + @staticmethod + def UnpauseActivityExecution( + request, + target, + options=(), + channel_credentials=None, + call_credentials=None, + insecure=False, + compression=None, + wait_for_ready=None, + timeout=None, + metadata=None, + ): + return grpc.experimental.unary_unary( + request, + target, + "/temporal.api.workflowservice.v1.WorkflowService/UnpauseActivityExecution", + temporal_dot_api_dot_workflowservice_dot_v1_dot_request__response__pb2.UnpauseActivityExecutionRequest.SerializeToString, + temporal_dot_api_dot_workflowservice_dot_v1_dot_request__response__pb2.UnpauseActivityExecutionResponse.FromString, + options, + channel_credentials, + insecure, + call_credentials, + compression, + wait_for_ready, + timeout, + metadata, + ) + + @staticmethod + def UpdateActivityExecutionOptions( + request, + target, + options=(), + channel_credentials=None, + call_credentials=None, + insecure=False, + compression=None, + wait_for_ready=None, + timeout=None, + metadata=None, + ): + return grpc.experimental.unary_unary( + request, + target, + "/temporal.api.workflowservice.v1.WorkflowService/UpdateActivityExecutionOptions", + temporal_dot_api_dot_workflowservice_dot_v1_dot_request__response__pb2.UpdateActivityExecutionOptionsRequest.SerializeToString, + temporal_dot_api_dot_workflowservice_dot_v1_dot_request__response__pb2.UpdateActivityExecutionOptionsResponse.FromString, + options, + channel_credentials, + insecure, + call_credentials, + compression, + wait_for_ready, + timeout, + metadata, + ) + @staticmethod def TerminateNexusOperationExecution( request, diff --git a/temporalio/api/workflowservice/v1/service_pb2_grpc.pyi b/temporalio/api/workflowservice/v1/service_pb2_grpc.pyi index caaf0d52e..4d5753d14 100644 --- a/temporalio/api/workflowservice/v1/service_pb2_grpc.pyi +++ b/temporalio/api/workflowservice/v1/service_pb2_grpc.pyi @@ -1091,6 +1091,61 @@ class WorkflowServiceStub: (-- api-linter: core::0127::http-annotation=disabled aip.dev/not-precedent: Activity deletion not exposed to HTTP, users should use cancel or terminate. --) """ + PauseActivityExecution: grpc.UnaryUnaryMultiCallable[ + temporalio.api.workflowservice.v1.request_response_pb2.PauseActivityExecutionRequest, + temporalio.api.workflowservice.v1.request_response_pb2.PauseActivityExecutionResponse, + ] + """PauseActivityExecution pauses the execution of an activity specified by its ID. + This API can be used to target a workflow activity or a standalone activity + + Pausing an activity means: + - If the activity is currently waiting for a retry or is running and subsequently fails, + it will not be rescheduled until it is unpaused. + - If the activity is already paused, calling this method will have no effect. + - If the activity is running and finishes successfully, the activity will be completed. + - If the activity is running and finishes with failure: + * if there is no retry left - the activity will be completed. + * if there are more retries left - the activity will be paused. + For long-running activities: + - activities in paused state will send a cancellation with "activity_paused" set to 'true' in response to 'RecordActivityTaskHeartbeat'. + + Returns a `NotFound` error if there is no pending activity with the provided ID + """ + ResetActivityExecution: grpc.UnaryUnaryMultiCallable[ + temporalio.api.workflowservice.v1.request_response_pb2.ResetActivityExecutionRequest, + temporalio.api.workflowservice.v1.request_response_pb2.ResetActivityExecutionResponse, + ] + """ResetActivityExecution resets the execution of an activity specified by its ID. + This API can be used to target a workflow activity or a standalone activity. + + Resetting an activity means: + * number of attempts will be reset to 0. + * activity timeouts will be reset. + * if the activity is waiting for retry, and it is not paused or 'keep_paused' is not provided: + it will be scheduled immediately (* see 'jitter' flag) + + Returns a `NotFound` error if there is no pending activity with the provided ID or type. + """ + UnpauseActivityExecution: grpc.UnaryUnaryMultiCallable[ + temporalio.api.workflowservice.v1.request_response_pb2.UnpauseActivityExecutionRequest, + temporalio.api.workflowservice.v1.request_response_pb2.UnpauseActivityExecutionResponse, + ] + """UnpauseActivityExecution unpauses the execution of an activity specified by its ID. + This API can be used to target a workflow activity or a standalone activity. + + If activity is not paused, this call will have no effect. + If the activity was paused while waiting for retry, it will be scheduled immediately (* see 'jitter' flag). + Once the activity is unpaused, all timeout timers will be regenerated. + + Returns a `NotFound` error if there is no pending activity with the provided ID + """ + UpdateActivityExecutionOptions: grpc.UnaryUnaryMultiCallable[ + temporalio.api.workflowservice.v1.request_response_pb2.UpdateActivityExecutionOptionsRequest, + temporalio.api.workflowservice.v1.request_response_pb2.UpdateActivityExecutionOptionsResponse, + ] + """UpdateActivityExecutionOptions is called by the client to update the options of an activity by its ID. + This API can be used to target a workflow activity or a standalone activity. + """ TerminateNexusOperationExecution: grpc.UnaryUnaryMultiCallable[ temporalio.api.workflowservice.v1.request_response_pb2.TerminateNexusOperationExecutionRequest, temporalio.api.workflowservice.v1.request_response_pb2.TerminateNexusOperationExecutionResponse, @@ -2436,6 +2491,69 @@ class WorkflowServiceServicer(metaclass=abc.ABCMeta): aip.dev/not-precedent: Activity deletion not exposed to HTTP, users should use cancel or terminate. --) """ @abc.abstractmethod + def PauseActivityExecution( + self, + request: temporalio.api.workflowservice.v1.request_response_pb2.PauseActivityExecutionRequest, + context: grpc.ServicerContext, + ) -> temporalio.api.workflowservice.v1.request_response_pb2.PauseActivityExecutionResponse: + """PauseActivityExecution pauses the execution of an activity specified by its ID. + This API can be used to target a workflow activity or a standalone activity + + Pausing an activity means: + - If the activity is currently waiting for a retry or is running and subsequently fails, + it will not be rescheduled until it is unpaused. + - If the activity is already paused, calling this method will have no effect. + - If the activity is running and finishes successfully, the activity will be completed. + - If the activity is running and finishes with failure: + * if there is no retry left - the activity will be completed. + * if there are more retries left - the activity will be paused. + For long-running activities: + - activities in paused state will send a cancellation with "activity_paused" set to 'true' in response to 'RecordActivityTaskHeartbeat'. + + Returns a `NotFound` error if there is no pending activity with the provided ID + """ + @abc.abstractmethod + def ResetActivityExecution( + self, + request: temporalio.api.workflowservice.v1.request_response_pb2.ResetActivityExecutionRequest, + context: grpc.ServicerContext, + ) -> temporalio.api.workflowservice.v1.request_response_pb2.ResetActivityExecutionResponse: + """ResetActivityExecution resets the execution of an activity specified by its ID. + This API can be used to target a workflow activity or a standalone activity. + + Resetting an activity means: + * number of attempts will be reset to 0. + * activity timeouts will be reset. + * if the activity is waiting for retry, and it is not paused or 'keep_paused' is not provided: + it will be scheduled immediately (* see 'jitter' flag) + + Returns a `NotFound` error if there is no pending activity with the provided ID or type. + """ + @abc.abstractmethod + def UnpauseActivityExecution( + self, + request: temporalio.api.workflowservice.v1.request_response_pb2.UnpauseActivityExecutionRequest, + context: grpc.ServicerContext, + ) -> temporalio.api.workflowservice.v1.request_response_pb2.UnpauseActivityExecutionResponse: + """UnpauseActivityExecution unpauses the execution of an activity specified by its ID. + This API can be used to target a workflow activity or a standalone activity. + + If activity is not paused, this call will have no effect. + If the activity was paused while waiting for retry, it will be scheduled immediately (* see 'jitter' flag). + Once the activity is unpaused, all timeout timers will be regenerated. + + Returns a `NotFound` error if there is no pending activity with the provided ID + """ + @abc.abstractmethod + def UpdateActivityExecutionOptions( + self, + request: temporalio.api.workflowservice.v1.request_response_pb2.UpdateActivityExecutionOptionsRequest, + context: grpc.ServicerContext, + ) -> temporalio.api.workflowservice.v1.request_response_pb2.UpdateActivityExecutionOptionsResponse: + """UpdateActivityExecutionOptions is called by the client to update the options of an activity by its ID. + This API can be used to target a workflow activity or a standalone activity. + """ + @abc.abstractmethod def TerminateNexusOperationExecution( self, request: temporalio.api.workflowservice.v1.request_response_pb2.TerminateNexusOperationExecutionRequest, diff --git a/temporalio/bridge/Cargo.lock b/temporalio/bridge/Cargo.lock index 39403b364..7f22a2a9c 100644 --- a/temporalio/bridge/Cargo.lock +++ b/temporalio/bridge/Cargo.lock @@ -2,15 +2,6 @@ # It is not intended for manual editing. version = 4 -[[package]] -name = "addr2line" -version = "0.24.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1" -dependencies = [ - "gimli", -] - [[package]] name = "adler2" version = "2.0.1" @@ -19,9 +10,9 @@ checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" [[package]] name = "aho-corasick" -version = "1.1.3" +version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" +checksum = "ddd31a130427c27518df266943a5308ed92d4b226cc639f5a8f1002816174301" dependencies = [ "memchr", ] @@ -34,15 +25,15 @@ checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" [[package]] name = "anstyle" -version = "1.0.11" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "862ed96ca487e809f1c8e5a8447f6ee2cf102f846893800b20cebdf541fc6bbd" +checksum = "940b3a0ca603d1eade50a4846a2afffd5ef57a9feac2c0e2ec2e14f9ead76000" [[package]] name = "anyhow" -version = "1.0.99" +version = "1.0.102" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0674a1ddeecb70197781e945de4b3b8ffb61fa939a5597bcf48503737663100" +checksum = "7f202df86484c868dbad7eaa557ef785d5c66295e41b460ef922eca0723b842c" [[package]] name = "async-trait" @@ -63,15 +54,15 @@ checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" [[package]] name = "autocfg" -version = "1.5.0" +version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" +checksum = "f2032f911046de80f0a198e0901378627c33f59ea0ac00e363d481118bd70a53" [[package]] name = "aws-lc-rs" -version = "1.16.2" +version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a054912289d18629dc78375ba2c3726a3afe3ff71b4edba9dedfca0e3446d1fc" +checksum = "5ec2f1fc3ec205783a5da9a7e6c1509cc69dedf09a1949e412c1e18469326d00" dependencies = [ "aws-lc-sys", "zeroize", @@ -79,9 +70,9 @@ dependencies = [ [[package]] name = "aws-lc-sys" -version = "0.39.1" +version = "0.41.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83a25cf98105baa966497416dbd42565ce3a8cf8dbfd59803ec9ad46f3126399" +checksum = "1a2f9779ce85b93ab6170dd940ad0169b5766ff848247aff13bb788b832fe3f4" dependencies = [ "cc", "cmake", @@ -91,9 +82,9 @@ dependencies = [ [[package]] name = "axum" -version = "0.8.4" +version = "0.8.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "021e862c184ae977658b36c4500f7feac3221ca5da43e3f25bd04ab6c79a29b5" +checksum = "31b698c5f9a010f6573133b09e0de5408834d0c82f8d7475a89fc1867a71cd90" dependencies = [ "axum-core", "bytes", @@ -107,8 +98,7 @@ dependencies = [ "mime", "percent-encoding", "pin-project-lite", - "rustversion", - "serde", + "serde_core", "sync_wrapper", "tower", "tower-layer", @@ -117,9 +107,9 @@ dependencies = [ [[package]] name = "axum-core" -version = "0.5.2" +version = "0.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68464cd0412f486726fb3373129ef5d2993f90c34bc2bc1c1e9943b2f4fc7ca6" +checksum = "08c78f31d7b1291f7ee735c1c6780ccde7785daae9a9206026862dab7d8792d1" dependencies = [ "bytes", "futures-core", @@ -128,7 +118,6 @@ dependencies = [ "http-body-util", "mime", "pin-project-lite", - "rustversion", "sync_wrapper", "tower-layer", "tower-service", @@ -140,24 +129,9 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b62ddb9cb1ec0a098ad4bbf9344d0713fa193ae1a80af55febcff2627b6a00c1" dependencies = [ - "getrandom 0.2.16", + "getrandom 0.2.17", "instant", - "rand 0.8.5", -] - -[[package]] -name = "backtrace" -version = "0.3.75" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6806a6321ec58106fea15becdad98371e28d92ccbc7c8f1b3b6dd724fe8f1002" -dependencies = [ - "addr2line", - "cfg-if", - "libc", - "miniz_oxide", - "object", - "rustc-demangle", - "windows-targets 0.52.6", + "rand 0.8.6", ] [[package]] @@ -168,15 +142,15 @@ checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" [[package]] name = "bitflags" -version = "2.11.0" +version = "2.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "843867be96c8daad0d758b57df9392b6d8d271134fce549de6ce169ff98a92af" +checksum = "c4512299f36f043ab09a583e57bceb5a5aab7a73db1805848e8fef3c9e8c78b3" [[package]] name = "bon" -version = "3.8.1" +version = "3.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ebeb9aaf9329dff6ceb65c689ca3db33dbf15f324909c60e4e5eef5701ce31b1" +checksum = "f47dbe92550676ee653353c310dfb9cf6ba17ee70396e1f7cf0a2020ad49b2fe" dependencies = [ "bon-macros", "rustversion", @@ -184,9 +158,9 @@ dependencies = [ [[package]] name = "bon-macros" -version = "3.8.1" +version = "3.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77e9d642a7e3a318e37c2c9427b5a6a48aa1ad55dcd986f3034ab2239045a645" +checksum = "519bd3116aeeb42d5372c29d982d16d0170d3d4a5ed85fc7dd91642ffff3c67c" dependencies = [ "darling", "ident_case", @@ -199,9 +173,9 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.19.0" +version = "3.20.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46c5e41b57b8bba42a04676d81cb89e9ee8e859a1a66f80a5a72e1cb76b34d43" +checksum = "72f5acc6cb2ba439de613abc23857ec3d78374d8ed5ac84e9d11336e87da8649" [[package]] name = "bytes" @@ -211,18 +185,18 @@ checksum = "1e748733b7cbc798e1434b6ac524f0c1ff2ab456fe201501e6497c8417a4fc33" [[package]] name = "bzip2" -version = "0.6.0" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bea8dcd42434048e4f7a304411d9273a411f647446c1234a65ce0554923f4cff" +checksum = "f3a53fac24f34a81bc9954b5d6cfce0c21e18ec6959f44f56e8e90e4bb7c346c" dependencies = [ "libbz2-rs-sys", ] [[package]] name = "cc" -version = "1.2.59" +version = "1.2.63" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7a4d3ec6524d28a329fc53654bbadc9bdd7b0431f5d65f1a56ffb28a1ee5283" +checksum = "556e016178bb5662a08681bbe0f00f8e17631781a4dfc8c45e466e4b185ec27f" dependencies = [ "find-msvc-tools", "jobserver", @@ -230,17 +204,11 @@ dependencies = [ "shlex", ] -[[package]] -name = "cesu8" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d43a04d8753f35258c91f8ec639f792891f748a1edbd759cf1dcea3382ad83c" - [[package]] name = "cfg-if" -version = "1.0.1" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9555578bc9e57714c812a1f84e4fc5b4d21fcb063490c624de019f7464c91268" +checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" [[package]] name = "cfg_aliases" @@ -256,14 +224,14 @@ checksum = "6f8d983286843e49675a4b7a2d174efe136dc93a18d69130dd18198a6c167601" dependencies = [ "cfg-if", "cpufeatures", - "rand_core 0.10.0", + "rand_core 0.10.1", ] [[package]] name = "chrono" -version = "0.4.41" +version = "0.4.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c469d952047f47f91b68d1cba3f10d63c11d73e4636f24f08daf0278abf01c4d" +checksum = "c673075a2e0e5f4a1dde27ce9dee1ea4558c7ffe648f576438a20ca1d2acc4b0" dependencies = [ "num-traits", "serde", @@ -288,6 +256,15 @@ dependencies = [ "memchr", ] +[[package]] +name = "convert_case" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "633458d4ef8c78b72454de2d54fd6ab2e60f9e02be22f3c6104cdc8a4e0fceb9" +dependencies = [ + "unicode-segmentation", +] + [[package]] name = "core-foundation" version = "0.10.1" @@ -339,9 +316,9 @@ checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" [[package]] name = "darling" -version = "0.21.3" +version = "0.23.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9cdf337090841a411e2a7f3deb9187445851f91b309c0c0a29e05f74a00a48c0" +checksum = "25ae13da2f202d56bd7f91c25fba009e7717a1e4a1cc98a76d844b65ae912e9d" dependencies = [ "darling_core", "darling_macro", @@ -349,11 +326,10 @@ dependencies = [ [[package]] name = "darling_core" -version = "0.21.3" +version = "0.23.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1247195ecd7e3c85f83c8d2a366e4210d588e802133e1e355180a9870b517ea4" +checksum = "9865a50f7c335f53564bb694ef660825eb8610e0a53d3e11bf1b0d3df31e03b0" dependencies = [ - "fnv", "ident_case", "proc-macro2", "quote", @@ -363,9 +339,9 @@ dependencies = [ [[package]] name = "darling_macro" -version = "0.21.3" +version = "0.23.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d38308df82d1080de0afee5d069fa14b0326a88c14f15c5ccda35b4a6c414c81" +checksum = "ac3984ec7bd6cfa798e62b4a642426a5be0e68f9401cfc2a01e3fa9ea2fcdb8d" dependencies = [ "darling_core", "quote", @@ -374,21 +350,23 @@ dependencies = [ [[package]] name = "derive_more" -version = "2.0.1" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "093242cf7570c207c83073cf82f79706fe7b8317e98620a47d5be7c3d8497678" +checksum = "d751e9e49156b02b44f9c1815bcb94b984cdcc4396ecc32521c739452808b134" dependencies = [ "derive_more-impl", ] [[package]] name = "derive_more-impl" -version = "2.0.1" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bda628edc44c4bb645fbe0f758797143e4e07926f7ebf4e9bdfbd3d2ce621df3" +checksum = "799a97264921d8623a957f6c3b9011f3b5492f557bbb7a5a19b7fa6d06ba8dcb" dependencies = [ + "convert_case", "proc-macro2", "quote", + "rustc_version", "syn", "unicode-xid", ] @@ -411,14 +389,14 @@ dependencies = [ "libc", "option-ext", "redox_users", - "windows-sys 0.60.2", + "windows-sys 0.61.2", ] [[package]] name = "displaydoc" -version = "0.2.5" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" +checksum = "1ac70aa55017e108007fbaf5aa0f54b021c98f92ff8af59d42eda9da96e3dd4f" dependencies = [ "proc-macro2", "quote", @@ -445,24 +423,24 @@ checksum = "d0881ea181b1df73ff77ffaaf9c7544ecc11e82fba9b5f27b262a3c73a332555" [[package]] name = "either" -version = "1.15.0" +version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" +checksum = "91622ff5e7162018101f2fea40d6ebf4a78bbe5a49736a2020649edf9693679e" [[package]] name = "enum-iterator" -version = "2.1.0" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c280b9e6b3ae19e152d8e31cf47f18389781e119d4013a2a2bb0180e5facc635" +checksum = "a4549325971814bda7a44061bf3fe7e487d447cba01e4220a4b454d630d7a016" dependencies = [ "enum-iterator-derive", ] [[package]] name = "enum-iterator-derive" -version = "1.4.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1ab991c1362ac86c61ab6f556cff143daa22e5a15e4e189df818b2fd19fe65b" +checksum = "685adfa4d6f3d765a26bc5dbc936577de9abf756c1feeb3089b01dd395034842" dependencies = [ "proc-macro2", "quote", @@ -489,40 +467,39 @@ checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" [[package]] name = "erased-serde" -version = "0.4.6" +version = "0.4.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e004d887f51fcb9fef17317a2f3525c887d8aa3f4f50fed920816a688284a5b7" +checksum = "d2add8a07dd6a8d93ff627029c51de145e12686fbc36ecb298ac22e74cf02dec" dependencies = [ "serde", + "serde_core", "typeid", ] [[package]] name = "errno" -version = "0.3.13" +version = "0.3.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "778e2ac28f6c47af28e4907f13ffd1e1ddbd400980a9abd7c8df189bf578a5ad" +checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" dependencies = [ "libc", - "windows-sys 0.60.2", + "windows-sys 0.61.2", ] [[package]] name = "fastrand" -version = "2.3.0" +version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" +checksum = "9f1f227452a390804cdb637b74a86990f2a7d7ba4b7d5693aac9b4dd6defd8d6" [[package]] name = "filetime" -version = "0.2.25" +version = "0.2.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35c0522e981e68cbfa8c3f978441a5f34b30b96e146b33cd3359176b50fe8586" +checksum = "5c287a33c7f0a620c38e641e7f60827713987b3c0f26e8ddc9462cc69cf75759" dependencies = [ "cfg-if", "libc", - "libredox", - "windows-sys 0.59.0", ] [[package]] @@ -539,13 +516,13 @@ checksum = "1d674e81391d1e1ab681a28d99df07927c6d4aa5b027d7da16ba32d1d21ecd99" [[package]] name = "flate2" -version = "1.1.2" +version = "1.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a3d7db9596fecd151c5f638c0ee5d5bd487b6e0ea232e5dc96d5250f6f94b1d" +checksum = "843fba2746e448b37e26a819579957415c8cef339bf08564fe8b7ddbd959573c" dependencies = [ "crc32fast", - "libz-rs-sys", "miniz_oxide", + "zlib-rs", ] [[package]] @@ -568,18 +545,21 @@ checksum = "77ce24cb58228fbb8aa041425bb1050850ac19177686ea6e0f41a70416f56fdb" [[package]] name = "form_urlencoded" -version = "1.2.1" +version = "1.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" +checksum = "cb4cb245038516f5f85277875cdaa4f7d2c9a0fa0468de06ed190163b1581fcf" dependencies = [ "percent-encoding", ] [[package]] name = "fragile" -version = "2.0.1" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28dd6caf6059519a65843af8fe2a3ae298b14b80179855aeb4adc2c1934ee619" +checksum = "8878864ba14bb86e818a412bfd6f18f9eabd4ec0f008a28e8f7eb61db532fcf9" +dependencies = [ + "futures-core", +] [[package]] name = "fs_extra" @@ -589,9 +569,9 @@ checksum = "42703706b716c37f96a77aea830392ad231f44c9e9a67872fa5548707e11b11c" [[package]] name = "futures" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876" +checksum = "8b147ee9d1f6d097cef9ce628cd2ee62288d963e16fb287bd9286455b241382d" dependencies = [ "futures-channel", "futures-core", @@ -604,9 +584,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" +checksum = "07bbe89c50d7a535e539b8c17bc0b49bdb77747034daa8087407d655f3f7cc1d" dependencies = [ "futures-core", "futures-sink", @@ -614,15 +594,15 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" +checksum = "7e3450815272ef58cec6d564423f6e755e25379b217b0bc688e295ba24df6b1d" [[package]] name = "futures-executor" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e28d1d997f585e54aebc3f97d39e72338912123a67330d723fdbb564d646c9f" +checksum = "baf29c38818342a3b26b5b923639e7b1f4a61fc5e76102d4b1981c6dc7a7579d" dependencies = [ "futures-core", "futures-task", @@ -631,15 +611,15 @@ dependencies = [ [[package]] name = "futures-io" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" +checksum = "cecba35d7ad927e23624b22ad55235f2239cfa44fd10428eecbeba6d6a717718" [[package]] name = "futures-macro" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" +checksum = "e835b70203e41293343137df5c0664546da5745f82ec9b84d40be8336958447b" dependencies = [ "proc-macro2", "quote", @@ -659,21 +639,21 @@ dependencies = [ [[package]] name = "futures-sink" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" +checksum = "c39754e157331b013978ec91992bde1ac089843443c49cbc7f46150b0fad0893" [[package]] name = "futures-task" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" +checksum = "037711b3d59c33004d3856fbdc83b99d4ff37a24768fa1be9ce3538a1cde4393" [[package]] name = "futures-util" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" +checksum = "389ca41296e6190b48053de0321d02a77f32f8a5d2461dd38762c0593805c6d6" dependencies = [ "futures-channel", "futures-core", @@ -683,44 +663,43 @@ dependencies = [ "futures-task", "memchr", "pin-project-lite", - "pin-utils", "slab", ] [[package]] name = "gethostname" -version = "1.0.2" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc257fdb4038301ce4b9cd1b3b51704509692bb3ff716a410cbd07925d9dae55" +checksum = "1bd49230192a3797a9a4d6abe9b3eed6f7fa4c8a8a4947977c6f80025f92cbd8" dependencies = [ "rustix", - "windows-targets 0.52.6", + "windows-link", ] [[package]] name = "getrandom" -version = "0.2.16" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592" +checksum = "ff2abc00be7fca6ebc474524697ae276ad847ad0a6b3faa4bcb027e9a4614ad0" dependencies = [ "cfg-if", "js-sys", "libc", - "wasi 0.11.1+wasi-snapshot-preview1", + "wasi", "wasm-bindgen", ] [[package]] name = "getrandom" -version = "0.3.3" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26145e563e54f2cadc477553f1ec5ee650b00862f0a58bcd12cbdc5f0ea2d2f4" +checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd" dependencies = [ "cfg-if", "js-sys", "libc", "r-efi 5.3.0", - "wasi 0.14.2+wasi-0.2.4", + "wasip2", "wasm-bindgen", ] @@ -733,22 +712,16 @@ dependencies = [ "cfg-if", "libc", "r-efi 6.0.0", - "rand_core 0.10.0", + "rand_core 0.10.1", "wasip2", "wasip3", ] -[[package]] -name = "gimli" -version = "0.31.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" - [[package]] name = "h2" -version = "0.4.12" +version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3c0b69cfcb4e1b9f1bf2f53f95f766e4661169728ec61cd3fe5a0166f2d1386" +checksum = "171fefbc92fe4a4de27e0698d6a5b392d6a0e333506bc49133760b3bcf948733" dependencies = [ "atomic-waker", "bytes", @@ -774,9 +747,9 @@ dependencies = [ [[package]] name = "hashbrown" -version = "0.16.1" +version = "0.17.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100" +checksum = "ed5909b6e89a2db4456e54cd5f673791d7eca6732202bbf2a9cc504fe2f9b84a" dependencies = [ "allocator-api2", "equivalent", @@ -791,12 +764,11 @@ checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" [[package]] name = "http" -version = "1.3.1" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4a85d31aea989eead29a3aaf9e1115a180df8282431156e533de47660892565" +checksum = "8be7462df143984c4598a256ef469b251d7d7f9e271135073e78fc535414f3d0" dependencies = [ "bytes", - "fnv", "itoa", ] @@ -837,9 +809,9 @@ checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" [[package]] name = "hyper" -version = "1.7.0" +version = "1.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb3aa54a13a0dfe7fbe3a59e0c76093041720fdc77b110cc0fc260fafb4dc51e" +checksum = "55281c53a1894c864990125767da440a4e630446785086f52523b20033b74498" dependencies = [ "atomic-waker", "bytes", @@ -852,7 +824,6 @@ dependencies = [ "httpdate", "itoa", "pin-project-lite", - "pin-utils", "smallvec", "tokio", "want", @@ -860,16 +831,15 @@ dependencies = [ [[package]] name = "hyper-rustls" -version = "0.27.7" +version = "0.27.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3c93eb611681b207e1fe55d5a71ecf91572ec8a6705cdb6857f7d8d5242cf58" +checksum = "33ca68d021ef39cf6463ab54c1d0f5daf03377b70561305bb89a8f83aab66e0f" dependencies = [ "http", "hyper", "hyper-util", "rustls", "rustls-native-certs", - "rustls-pki-types", "tokio", "tokio-rustls", "tower-service", @@ -890,14 +860,13 @@ dependencies = [ [[package]] name = "hyper-util" -version = "0.1.16" +version = "0.1.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d9b05277c7e8da2c93a568989bb6207bef0112e8d17df7a6eda4a3cf143bc5e" +checksum = "96547c2556ec9d12fb1578c4eaf448b04993e7fb79cbaad930a656880a6bdfa0" dependencies = [ "base64", "bytes", "futures-channel", - "futures-core", "futures-util", "http", "http-body", @@ -906,7 +875,7 @@ dependencies = [ "libc", "percent-encoding", "pin-project-lite", - "socket2 0.6.0", + "socket2", "tokio", "tower-service", "tracing", @@ -914,12 +883,13 @@ dependencies = [ [[package]] name = "icu_collections" -version = "2.0.0" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "200072f5d0e3614556f94a9930d5dc3e0662a652823904c3a75dc3b0af7fee47" +checksum = "2984d1cd16c883d7935b9e07e44071dca8d917fd52ecc02c04d5fa0b5a3f191c" dependencies = [ "displaydoc", "potential_utf", + "utf8_iter", "yoke", "zerofrom", "zerovec", @@ -927,9 +897,9 @@ dependencies = [ [[package]] name = "icu_locale_core" -version = "2.0.0" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0cde2700ccaed3872079a65fb1a78f6c0a36c91570f28755dda67bc8f7d9f00a" +checksum = "92219b62b3e2b4d88ac5119f8904c10f8f61bf7e95b640d25ba3075e6cac2c29" dependencies = [ "displaydoc", "litemap", @@ -940,11 +910,10 @@ dependencies = [ [[package]] name = "icu_normalizer" -version = "2.0.0" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "436880e8e18df4d7bbc06d58432329d6458cc84531f7ac5f024e93deadb37979" +checksum = "c56e5ee99d6e3d33bd91c5d85458b6005a22140021cc324cea84dd0e72cff3b4" dependencies = [ - "displaydoc", "icu_collections", "icu_normalizer_data", "icu_properties", @@ -955,42 +924,38 @@ dependencies = [ [[package]] name = "icu_normalizer_data" -version = "2.0.0" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00210d6893afc98edb752b664b8890f0ef174c8adbb8d0be9710fa66fbbf72d3" +checksum = "da3be0ae77ea334f4da67c12f149704f19f81d1adf7c51cf482943e84a2bad38" [[package]] name = "icu_properties" -version = "2.0.1" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "016c619c1eeb94efb86809b015c58f479963de65bdb6253345c1a1276f22e32b" +checksum = "bee3b67d0ea5c2cca5003417989af8996f8604e34fb9ddf96208a033901e70de" dependencies = [ - "displaydoc", "icu_collections", "icu_locale_core", "icu_properties_data", "icu_provider", - "potential_utf", "zerotrie", "zerovec", ] [[package]] name = "icu_properties_data" -version = "2.0.1" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "298459143998310acd25ffe6810ed544932242d3f07083eee1084d83a71bd632" +checksum = "8e2bbb201e0c04f7b4b3e14382af113e17ba4f63e2c9d2ee626b720cbce54a14" [[package]] name = "icu_provider" -version = "2.0.0" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03c80da27b5f4187909049ee2d72f276f0d9f99a42c306bd0131ecfe04d8e5af" +checksum = "139c4cf31c8b5f33d7e199446eff9c1e02decfc2f0eec2c8d71f65befa45b421" dependencies = [ "displaydoc", "icu_locale_core", - "stable_deref_trait", - "tinystr", "writeable", "yoke", "zerofrom", @@ -1012,9 +977,9 @@ checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" [[package]] name = "idna" -version = "1.0.3" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "686f825264d630750a544639377bae737628043f20d38bbc029e8f29ea968a7e" +checksum = "3b0875f23caa03898994f6ddc501886a45c7d3d62d04d2d90788d47be1b1e4de" dependencies = [ "idna_adapter", "smallvec", @@ -1023,9 +988,9 @@ dependencies = [ [[package]] name = "idna_adapter" -version = "1.2.1" +version = "1.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3acae9609540aa318d1bc588455225fb2085b9ed0c4f6bd0d9d5bcd86f1a0344" +checksum = "cb68373c0d6620ef8105e855e7745e18b0d00d3bdb07fb532e434244cdb9a714" dependencies = [ "icu_normalizer", "icu_properties", @@ -1033,21 +998,24 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.13.1" +version = "2.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45a8a2b9cb3e0b0c1803dbb0758ffac5de2f425b23c28f518faabd9d805342ff" +checksum = "d466e9454f08e4a911e14806c24e16fba1b4c121d1ea474396f396069cf949d9" dependencies = [ "equivalent", - "hashbrown 0.16.1", + "hashbrown 0.17.1", "serde", "serde_core", ] [[package]] name = "indoc" -version = "2.0.6" +version = "2.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4c7245a08504955605670dbf141fceab975f15ca21570696aebe9d2e71576bd" +checksum = "79cf5c93f93228cf8efb3ba362535fb11199ac548a09ce117c9b1adc3030d706" +dependencies = [ + "rustversion", +] [[package]] name = "instant" @@ -1060,39 +1028,18 @@ dependencies = [ [[package]] name = "inventory" -version = "0.3.20" +version = "0.3.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab08d7cd2c5897f2c949e5383ea7c7db03fb19130ffcfbf7eda795137ae3cb83" +checksum = "a4f0c30c76f2f4ccee3fe55a2435f691ca00c0e4bd87abe4f4a851b1d4dac39b" dependencies = [ "rustversion", ] -[[package]] -name = "io-uring" -version = "0.7.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d93587f37623a1a17d94ef2bc9ada592f5465fe7732084ab7beefabe5c77c0c4" -dependencies = [ - "bitflags", - "cfg-if", - "libc", -] - [[package]] name = "ipnet" -version = "2.11.0" +version = "2.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "469fb0b9cefa57e3ef31275ee7cacb78f2fdca44e4765491884a2b119d4eb130" - -[[package]] -name = "iri-string" -version = "0.7.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dbc5ebe9c3a1a7a5127f920a418f7585e9e758e911d0466ed004f393b0e380b2" -dependencies = [ - "memchr", - "serde", -] +checksum = "d98f6fed1fde3f8c21bc40a1abb88dd75e67924f9cffc3ef95607bad8017f8e2" [[package]] name = "itertools" @@ -1105,33 +1052,38 @@ dependencies = [ [[package]] name = "itoa" -version = "1.0.15" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" +checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" [[package]] name = "jni" -version = "0.21.1" +version = "0.22.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a87aa2bb7d2af34197c04845522473242e1aa17c12f4935d5856491a7fb8c97" +checksum = "5efd9a482cf3a427f00d6b35f14332adc7902ce91efb778580e180ff90fa3498" dependencies = [ - "cesu8", "cfg-if", "combine", - "jni-sys 0.3.1", + "jni-macros", + "jni-sys", "log", - "thiserror 1.0.69", + "simd_cesu8", + "thiserror", "walkdir", - "windows-sys 0.45.0", + "windows-link", ] [[package]] -name = "jni-sys" -version = "0.3.1" +name = "jni-macros" +version = "0.22.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41a652e1f9b6e0275df1f15b32661cf0d4b78d4d87ddec5e0c3c20f097433258" +checksum = "a00109accc170f0bdb141fed3e393c565b6f5e072365c3bd58f5b062591560a3" dependencies = [ - "jni-sys 0.4.1", + "proc-macro2", + "quote", + "rustc_version", + "simd_cesu8", + "syn", ] [[package]] @@ -1155,19 +1107,19 @@ dependencies = [ [[package]] name = "jobserver" -version = "0.1.33" +version = "0.1.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38f262f097c174adebe41eb73d66ae9c06b2844fb0da69969647bbddd9b0538a" +checksum = "9afb3de4395d6b3e67a780b6de64b51c978ecf11cb9a462c66be7d4ca9039d33" dependencies = [ - "getrandom 0.3.3", + "getrandom 0.3.4", "libc", ] [[package]] name = "js-sys" -version = "0.3.94" +version = "0.3.99" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e04e2ef80ce82e13552136fabeef8a5ed1f985a96805761cbb9a2c34e7664d9" +checksum = "142bc4740e452c1e57ade0cbc129f139c9093e354346f0872ef985f4f5cf5f11" dependencies = [ "cfg-if", "futures-util", @@ -1189,71 +1141,59 @@ checksum = "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2" [[package]] name = "libbz2-rs-sys" -version = "0.2.2" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c4a545a15244c7d945065b5d392b2d2d7f21526fba56ce51467b06ed445e8f7" +checksum = "34b357333733e8260735ba5894eb928c02ecc69c78715f01a8019e7fa7f2db4c" [[package]] name = "libc" -version = "0.2.175" +version = "0.2.186" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a82ae493e598baaea5209805c49bbf2ea7de956d50d7da0da1164f9c6d28543" +checksum = "68ab91017fe16c622486840e4c83c9a37afeff978bd239b5293d61ece587de66" [[package]] name = "libredox" -version = "0.1.9" +version = "0.1.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "391290121bad3d37fbddad76d8f5d1c1c314cfc646d143d7e07a3086ddff0ce3" +checksum = "f02ab6bace2054fb888a3c16f990117b579d14a3088e472d63c6011fa185c9d3" dependencies = [ - "bitflags", "libc", - "redox_syscall", -] - -[[package]] -name = "libz-rs-sys" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "840db8cf39d9ec4dd794376f38acc40d0fc65eec2a8f484f7fd375b84602becd" -dependencies = [ - "zlib-rs", ] [[package]] name = "linux-raw-sys" -version = "0.9.4" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd945864f07fe9f5371a27ad7b52a172b4b499999f1d97574c9fa68373937e12" +checksum = "32a66949e030da00e8c7d4434b251670a91556f4144941d37452769c25d58a53" [[package]] name = "litemap" -version = "0.8.0" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "241eaef5fd12c88705a01fc1066c48c4b36e0dd4377dcdc7ec3942cea7a69956" +checksum = "92daf443525c4cce67b150400bc2316076100ce0b3686209eb8cf3c31612e6f0" [[package]] name = "lock_api" -version = "0.4.13" +version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96936507f153605bddfcda068dd804796c84324ed2510809e5b2a624c81da765" +checksum = "224399e74b87b5f3557511d98dff8b14089b3dadafcab6bb93eab67d3aace965" dependencies = [ - "autocfg", "scopeguard", ] [[package]] name = "log" -version = "0.4.29" +version = "0.4.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897" +checksum = "616ec5685824bcc94416c6d4a7a446eea774a31efd7062c8480ba6fd06d7a6e5" [[package]] name = "lru" -version = "0.16.3" +version = "0.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1dc47f592c06f33f8e3aea9591776ec7c9f9e4124778ff8a3c3b87159f7e593" +checksum = "8a860605968fce16869fd239cf4237a82f3ac470723415db603b0e8b6c8d4fb9" dependencies = [ - "hashbrown 0.16.1", + "hashbrown 0.17.1", ] [[package]] @@ -1279,9 +1219,9 @@ checksum = "47e1ffaa40ddd1f3ed91f717a33c8c0ee23fff369e3aa8772b9605cc1d22f4c3" [[package]] name = "memchr" -version = "2.7.5" +version = "2.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32a282da65faaf38286cf3be983213fcf1d2e2a58700e808f83f4ea9a4804bc0" +checksum = "6b947ae49db0d222b1dbc6b113ce7248a3fc3a6ca21b696717bfc000ba4484d8" [[package]] name = "memoffset" @@ -1305,17 +1245,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316" dependencies = [ "adler2", + "simd-adler32", ] [[package]] name = "mio" -version = "1.0.4" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78bed444cc8a2160f01cbcf811ef18cac863ad68ae8ca62092e8db51d51c761c" +checksum = "02bd0af71c67b473010cbbc60715ee815645a4dc942899111f494b4b737d6fda" dependencies = [ "libc", - "wasi 0.11.1+wasi-snapshot-preview1", - "windows-sys 0.59.0", + "wasi", + "windows-sys 0.61.2", ] [[package]] @@ -1352,20 +1293,20 @@ checksum = "1d87ecb2933e8aeadb3e3a02b828fed80a7528047e68b4f424523a0981a3a084" [[package]] name = "ntapi" -version = "0.4.1" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8a3895c6391c39d7fe7ebc444a87eb2991b2a0bc718fdabd071eec617fc68e4" +checksum = "c3b335231dfd352ffb0f8017f3b6027a4917f7df785ea2143d8af2adc66980ae" dependencies = [ "winapi", ] [[package]] name = "nu-ansi-term" -version = "0.50.1" +version = "0.50.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4a28e057d01f97e61255210fcff094d74ed0466038633e95017f5beb68e4399" +checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5" dependencies = [ - "windows-sys 0.52.0", + "windows-sys 0.61.2", ] [[package]] @@ -1396,26 +1337,17 @@ dependencies = [ "objc2-core-foundation", ] -[[package]] -name = "object" -version = "0.36.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62948e14d923ea95ea2c7c86c71013138b66525b86bdc08d2dcc262bdb497b87" -dependencies = [ - "memchr", -] - [[package]] name = "once_cell" -version = "1.21.3" +version = "1.21.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" +checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "openssl-probe" -version = "0.1.6" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e" +checksum = "7c87def4c32ab89d880effc9e097653c8da5d6ef28e6b539d313baaacfbafcbe" [[package]] name = "opentelemetry" @@ -1427,7 +1359,7 @@ dependencies = [ "futures-sink", "js-sys", "pin-project-lite", - "thiserror 2.0.15", + "thiserror", ] [[package]] @@ -1456,7 +1388,7 @@ dependencies = [ "opentelemetry_sdk", "prost", "reqwest 0.12.28", - "thiserror 2.0.15", + "thiserror", "tokio", "tonic", ] @@ -1485,8 +1417,8 @@ dependencies = [ "futures-util", "opentelemetry", "percent-encoding", - "rand 0.9.2", - "thiserror 2.0.15", + "rand 0.9.4", + "thiserror", "tokio", "tokio-stream", ] @@ -1499,9 +1431,9 @@ checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" [[package]] name = "parking_lot" -version = "0.12.4" +version = "0.12.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70d58bf43669b5795d1576d0641cfb6fbb2057bf629506267a92807158584a13" +checksum = "93857453250e3077bd71ff98b6a65ea6621a19bb0f559a85248955ac12c45a1a" dependencies = [ "lock_api", "parking_lot_core", @@ -1509,15 +1441,15 @@ dependencies = [ [[package]] name = "parking_lot_core" -version = "0.9.11" +version = "0.9.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc838d2a56b5b1a6c25f55575dfc605fabb63bb2365f6c2353ef9159aa69e4a5" +checksum = "2621685985a2ebf1c516881c026032ac7deafcda1a2c9b7850dc81e3dfcb64c1" dependencies = [ "cfg-if", "libc", "redox_syscall", "smallvec", - "windows-targets 0.52.6", + "windows-link", ] [[package]] @@ -1544,17 +1476,18 @@ dependencies = [ [[package]] name = "percent-encoding" -version = "2.3.1" +version = "2.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" +checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" [[package]] name = "petgraph" -version = "0.7.1" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3672b37090dbd86368a4145bc067582552b29c27377cad4e0a306c97f9bd7772" +checksum = "8701b58ea97060d5e5b155d383a69952a60943f0e6dfe30b04c287beb0b27455" dependencies = [ "fixedbitset", + "hashbrown 0.15.5", "indexmap", ] @@ -1569,18 +1502,18 @@ dependencies = [ [[package]] name = "pin-project" -version = "1.1.10" +version = "1.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "677f1add503faace112b9f1373e43e9e054bfdd22ff1a63c1bc485eaec6a6a8a" +checksum = "2466b2336ed02bcdca6b294417127b90ec92038d1d5c4fbeac971a922e0e0924" dependencies = [ "pin-project-internal", ] [[package]] name = "pin-project-internal" -version = "1.1.10" +version = "1.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e918e4ff8c4549eb882f14b3a4bc8c8bc93de829416eacf579f1207a8fbf861" +checksum = "c96395f0a926bc13b1c17622aaddda1ecb55d49c8f1bf9777e4d877800a43f8b" dependencies = [ "proc-macro2", "quote", @@ -1589,42 +1522,36 @@ dependencies = [ [[package]] name = "pin-project-lite" -version = "0.2.16" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" - -[[package]] -name = "pin-utils" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" +checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd" [[package]] name = "pkg-config" -version = "0.3.32" +version = "0.3.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" +checksum = "19f132c84eca552bf34cab8ec81f1c1dcc229b811638f9d283dceabe58c5569e" [[package]] name = "portable-atomic" -version = "1.11.1" +version = "1.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f84267b20a16ea918e43c6a88433c2d54fa145c92a811b5b047ccbe153674483" +checksum = "c33a9471896f1c69cecef8d20cbe2f7accd12527ce60845ff44c153bb2a21b49" [[package]] name = "portable-atomic-util" -version = "0.2.4" +version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8a2f0d8d040d7848a709caf78912debcc3f33ee4b3cac47d73d1e1069e83507" +checksum = "c2a106d1259c23fac8e543272398ae0e3c0b8d33c88ed73d0cc71b0f1d902618" dependencies = [ "portable-atomic", ] [[package]] name = "potential_utf" -version = "0.1.2" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5a7c30837279ca13e7c867e9e40053bc68740f988cb07f7ca6df43cc734b585" +checksum = "0103b1cef7ec0cf76490e969665504990193874ea05c85ff9bab8b911d0a0564" dependencies = [ "zerovec", ] @@ -1640,9 +1567,9 @@ dependencies = [ [[package]] name = "predicates" -version = "3.1.3" +version = "3.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a5d19ee57562043d37e82899fade9a22ebab7be9cef5026b07fda9cdd4293573" +checksum = "ada8f2932f28a27ee7b70dd6c1c39ea0675c55a36879ab92f3a715eaa1e63cfe" dependencies = [ "anstyle", "predicates-core", @@ -1650,15 +1577,15 @@ dependencies = [ [[package]] name = "predicates-core" -version = "1.0.9" +version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "727e462b119fe9c93fd0eb1429a5f7647394014cf3c04ab2c0350eeb09095ffa" +checksum = "cad38746f3166b4031b1a0d39ad9f954dd291e7854fcc0eed52ee41a0b50d144" [[package]] name = "predicates-tree" -version = "1.0.12" +version = "1.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72dd2d6d381dfb73a193c7fca536518d7caee39fc8503f74e7dc0be0531b425c" +checksum = "d0de1b847b39c8131db0467e9df1ff60e6d0562ab8e9a16e568ad0fdb372e2f2" dependencies = [ "predicates-core", "termtree", @@ -1676,9 +1603,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.101" +version = "1.0.106" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89ae43fd86e4158d6db51ad8e2b80f313af9cc74f5c0e03ccb87de09998732de" +checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934" dependencies = [ "unicode-ident", ] @@ -1694,14 +1621,14 @@ dependencies = [ "lazy_static", "memchr", "parking_lot", - "thiserror 2.0.15", + "thiserror", ] [[package]] name = "prost" -version = "0.14.1" +version = "0.14.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7231bd9b3d3d33c86b58adbac74b5ec0ad9f496b19d22801d773636feaa95f3d" +checksum = "d2ea70524a2f82d518bce41317d0fae74151505651af45faf1ffbd6fd33f0568" dependencies = [ "bytes", "prost-derive", @@ -1709,15 +1636,14 @@ dependencies = [ [[package]] name = "prost-build" -version = "0.14.1" +version = "0.14.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac6c3320f9abac597dcbc668774ef006702672474aad53c6d596b62e487b40b1" +checksum = "343d3bd7056eda839b03204e68deff7d1b13aba7af2b2fd16890697274262ee7" dependencies = [ "heck", "itertools", "log", "multimap", - "once_cell", "petgraph", "prettyplease", "prost", @@ -1731,9 +1657,9 @@ dependencies = [ [[package]] name = "prost-derive" -version = "0.14.1" +version = "0.14.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9120690fafc389a67ba3803df527d0ec9cbbc9cc45e4cc20b332996dfb672425" +checksum = "27c6023962132f4b30eb4c172c91ce92d933da334c59c23cddee82358ddafb0b" dependencies = [ "anyhow", "itertools", @@ -1744,18 +1670,18 @@ dependencies = [ [[package]] name = "prost-types" -version = "0.14.1" +version = "0.14.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9b4db3d6da204ed77bb26ba83b6122a73aeb2e87e25fbf7ad2e84c4ccbf8f72" +checksum = "8991c4cbdb8bc5b11f0b074ffe286c30e523de90fee5ba8132f1399f23cb3dd7" dependencies = [ "prost", ] [[package]] name = "prost-wkt" -version = "0.7.0" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "655944d0ce015e71b3ec21279437e6a09e58433e50c7b0677901f3d5235e74f5" +checksum = "cd3de5e9c9e84fcb5efa204b8e283d23e615a8bc8c777bf1d6622bb01dc61445" dependencies = [ "chrono", "inventory", @@ -1768,9 +1694,9 @@ dependencies = [ [[package]] name = "prost-wkt-build" -version = "0.7.0" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f869f1443fee474b785e935d92e1007f57443e485f51668ed41943fc01a321a2" +checksum = "fe500dc80e757a75e1e8fb7290e448d62dfba3105ece1d058579cb00b58151cd" dependencies = [ "heck", "prost", @@ -1781,9 +1707,9 @@ dependencies = [ [[package]] name = "prost-wkt-types" -version = "0.7.0" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eeeffd6b9becd4600dd461399f3f71aeda2ff0848802a9ed526cf12e8f42902a" +checksum = "13807eaa7e15833d06e899008371926201cdcd11d74b6d490f49130cdb3f415e" dependencies = [ "chrono", "prost", @@ -1799,9 +1725,9 @@ dependencies = [ [[package]] name = "pulldown-cmark" -version = "0.13.0" +version = "0.13.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e8bbe1a966bd2f362681a44f6edce3c2310ac21e4d5067a6e7ec396297a6ea0" +checksum = "e9f068eba8e7071c5f9511831b44f32c740d5adf574e990f946ddb53db2f314e" dependencies = [ "bitflags", "memchr", @@ -1810,9 +1736,9 @@ dependencies = [ [[package]] name = "pulldown-cmark-to-cmark" -version = "21.0.0" +version = "22.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5b6a0769a491a08b31ea5c62494a8f144ee0987d86d670a8af4df1e1b7cde75" +checksum = "50793def1b900256624a709439404384204a5dc3a6ec580281bfaac35e882e90" dependencies = [ "pulldown-cmark", ] @@ -1906,9 +1832,9 @@ dependencies = [ [[package]] name = "quinn" -version = "0.11.8" +version = "0.11.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "626214629cda6781b6dc1d316ba307189c85ba657213ce642d9c77670f8202c8" +checksum = "b9e20a958963c291dc322d98411f541009df2ced7b5a4f2bd52337638cfccf20" dependencies = [ "bytes", "cfg_aliases", @@ -1917,8 +1843,8 @@ dependencies = [ "quinn-udp", "rustc-hash", "rustls", - "socket2 0.5.10", - "thiserror 2.0.15", + "socket2", + "thiserror", "tokio", "tracing", "web-time", @@ -1932,15 +1858,15 @@ checksum = "434b42fec591c96ef50e21e886936e66d3cc3f737104fdb9b737c40ffb94c098" dependencies = [ "aws-lc-rs", "bytes", - "getrandom 0.3.3", + "getrandom 0.3.4", "lru-slab", - "rand 0.9.2", + "rand 0.9.4", "ring", "rustc-hash", "rustls", "rustls-pki-types", "slab", - "thiserror 2.0.15", + "thiserror", "tinyvec", "tracing", "web-time", @@ -1948,23 +1874,23 @@ dependencies = [ [[package]] name = "quinn-udp" -version = "0.5.13" +version = "0.5.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fcebb1209ee276352ef14ff8732e24cc2b02bbac986cd74a4c81bcb2f9881970" +checksum = "addec6a0dcad8a8d96a771f815f0eaf55f9d1805756410b39f5fa81332574cbd" dependencies = [ "cfg_aliases", "libc", "once_cell", - "socket2 0.5.10", + "socket2", "tracing", - "windows-sys 0.59.0", + "windows-sys 0.60.2", ] [[package]] name = "quote" -version = "1.0.40" +version = "1.0.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" +checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924" dependencies = [ "proc-macro2", ] @@ -1983,9 +1909,9 @@ checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf" [[package]] name = "rand" -version = "0.8.5" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +checksum = "5ca0ecfa931c29007047d1bc58e623ab12e5590e8c7cc53200d5202b69266d8a" dependencies = [ "libc", "rand_chacha 0.3.1", @@ -1994,23 +1920,23 @@ dependencies = [ [[package]] name = "rand" -version = "0.9.2" +version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6db2770f06117d490610c7488547d543617b21bfa07796d7a12f6f1bd53850d1" +checksum = "44c5af06bb1b7d3216d91932aed5265164bf384dc89cd6ba05cf59a35f5f76ea" dependencies = [ "rand_chacha 0.9.0", - "rand_core 0.9.3", + "rand_core 0.9.5", ] [[package]] name = "rand" -version = "0.10.0" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc266eb313df6c5c09c1c7b1fbe2510961e5bcd3add930c1e31f7ed9da0feff8" +checksum = "d2e8e8bcc7961af1fdac401278c6a831614941f6164ee3bf4ce61b7edb162207" dependencies = [ "chacha20", "getrandom 0.4.2", - "rand_core 0.10.0", + "rand_core 0.10.1", ] [[package]] @@ -2030,7 +1956,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" dependencies = [ "ppv-lite86", - "rand_core 0.9.3", + "rand_core 0.9.5", ] [[package]] @@ -2039,29 +1965,29 @@ version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" dependencies = [ - "getrandom 0.2.16", + "getrandom 0.2.17", ] [[package]] name = "rand_core" -version = "0.9.3" +version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38" +checksum = "76afc826de14238e6e8c374ddcc1fa19e374fd8dd986b0d2af0d02377261d83c" dependencies = [ - "getrandom 0.3.3", + "getrandom 0.3.4", ] [[package]] name = "rand_core" -version = "0.10.0" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c8d0fd677905edcbeedbf2edb6494d676f0e98d54d5cf9bda0b061cb8fb8aba" +checksum = "63b8176103e19a2643978565ca18b50549f6101881c443590420e4dc998a3c69" [[package]] name = "redox_syscall" -version = "0.5.17" +version = "0.5.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5407465600fb0548f1442edf71dd20683c6ed326200ace4b1ef0763521bb3b77" +checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d" dependencies = [ "bitflags", ] @@ -2072,16 +1998,16 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a4e608c6638b9c18977b00b475ac1f28d14e84b27d8d42f70e0bf1e3dec127ac" dependencies = [ - "getrandom 0.2.16", + "getrandom 0.2.17", "libredox", - "thiserror 2.0.15", + "thiserror", ] [[package]] name = "regex" -version = "1.11.1" +version = "1.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" +checksum = "e10754a14b9137dd7b1e3e5b0493cc9171fdd105e0ab477f51b72e7f3ac0e276" dependencies = [ "aho-corasick", "memchr", @@ -2091,9 +2017,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.9" +version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" +checksum = "6e1dd4122fc1595e8162618945476892eefca7b88c52820e74af6262213cae8f" dependencies = [ "aho-corasick", "memchr", @@ -2102,9 +2028,9 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.8.5" +version = "0.8.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" +checksum = "dc897dd8d9e8bd1ed8cdad82b5966c3e0ecae09fb1907d58efaa013543185d0a" [[package]] name = "reqwest" @@ -2148,9 +2074,9 @@ dependencies = [ [[package]] name = "reqwest" -version = "0.13.2" +version = "0.13.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab3f43e3283ab1488b624b44b0e988d0acea0b3214e694730a055cb6b2efa801" +checksum = "219c5811de6525e5416c7d5d53bb656d3afdbc6c5af816e0802bcfa42dbdc1c3" dependencies = [ "base64", "bytes", @@ -2195,7 +2121,7 @@ checksum = "a4689e6c2294d81e88dc6261c768b63bc4fcdb852be6d1352498b114f61383b7" dependencies = [ "cc", "cfg-if", - "getrandom 0.2.16", + "getrandom 0.2.17", "libc", "untrusted", "windows-sys 0.52.0", @@ -2203,9 +2129,9 @@ dependencies = [ [[package]] name = "ringbuf" -version = "0.4.8" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe47b720588c8702e34b5979cb3271a8b1842c7cb6f57408efa70c779363488c" +checksum = "2d3ecbcab081b935fb9c618b07654924f27686b4aac8818e700580a83eedcb7f" dependencies = [ "crossbeam-utils", "portable-atomic", @@ -2213,35 +2139,38 @@ dependencies = [ ] [[package]] -name = "rustc-demangle" -version = "0.1.26" +name = "rustc-hash" +version = "2.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56f7d92ca342cea22a06f2121d944b4fd82af56988c270852495420f961d4ace" +checksum = "94300abf3f1ae2e2b8ffb7b58043de3d399c73fa6f4b73826402a5c457614dbe" [[package]] -name = "rustc-hash" -version = "2.1.1" +name = "rustc_version" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d" +checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" +dependencies = [ + "semver", +] [[package]] name = "rustix" -version = "1.0.8" +version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11181fbabf243db407ef8df94a6ce0b2f9a733bd8be4ad02b4eda9602296cac8" +checksum = "b6fe4565b9518b83ef4f91bb47ce29620ca828bd32cb7e408f0062e9930ba190" dependencies = [ "bitflags", "errno", "libc", "linux-raw-sys", - "windows-sys 0.60.2", + "windows-sys 0.61.2", ] [[package]] name = "rustls" -version = "0.23.31" +version = "0.23.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0ebcbd2f03de0fc1122ad9bb24b127a5a6cd51d72604a3f3c50ac459762b6cc" +checksum = "ef86cd5876211988985292b91c96a8f2d298df24e75989a43a3c73f2d4d8168b" dependencies = [ "aws-lc-rs", "log", @@ -2255,9 +2184,9 @@ dependencies = [ [[package]] name = "rustls-native-certs" -version = "0.8.1" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fcff2dd52b58a8d98a70243663a0d234c4e2b79235637849d15913394a247d3" +checksum = "612460d5f7bea540c490b2b6395d8e34a953e52b491accd6c86c8164c5932a63" dependencies = [ "openssl-probe", "rustls-pki-types", @@ -2267,9 +2196,9 @@ dependencies = [ [[package]] name = "rustls-pki-types" -version = "1.12.0" +version = "1.14.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "229a4a4c221013e7e1f1a043678c5cc39fe5171437c88fb47151a21e6f5b5c79" +checksum = "30a7197ae7eb376e574fe940d068c30fe0462554a3ddbe4eca7838e049c937a9" dependencies = [ "web-time", "zeroize", @@ -2277,9 +2206,9 @@ dependencies = [ [[package]] name = "rustls-platform-verifier" -version = "0.6.2" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d99feebc72bae7ab76ba994bb5e121b8d83d910ca40b36e0921f53becc41784" +checksum = "26d1e2536ce4f35f4846aa13bff16bd0ff40157cdb14cc056c7b14ba41233ba0" dependencies = [ "core-foundation", "core-foundation-sys", @@ -2293,7 +2222,7 @@ dependencies = [ "security-framework", "security-framework-sys", "webpki-root-certs", - "windows-sys 0.60.2", + "windows-sys 0.61.2", ] [[package]] @@ -2322,9 +2251,9 @@ checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" [[package]] name = "ryu" -version = "1.0.20" +version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" +checksum = "9774ba4a74de5f7b1c1451ed6cd5285a32eddb5cccb8cc655a4e50009e06477f" [[package]] name = "same-file" @@ -2337,11 +2266,11 @@ dependencies = [ [[package]] name = "schannel" -version = "0.1.27" +version = "0.1.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f29ebaa345f945cec9fbbc532eb307f0fdad8161f281b6369539c8d84876b3d" +checksum = "91c1b7e4904c873ef0710c1f407dde2e6287de2bebc1bbbf7d430bb7cbffd939" dependencies = [ - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -2411,14 +2340,15 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.143" +version = "1.0.150" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d401abef1d108fbd9cbaebc3e46611f4b1021f714a0597a71f41ee463f5f4a5a" +checksum = "e8014e44b4736ed0538adeecded0fce2a272f22dc9578a7eb6b2d9993c74cfb9" dependencies = [ "itoa", "memchr", - "ryu", "serde", + "serde_core", + "zmij", ] [[package]] @@ -2453,42 +2383,59 @@ dependencies = [ [[package]] name = "shlex" -version = "1.3.0" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" +checksum = "f8fadd59c855ef2080decdef8ff161eb6661b86933c9d82e5ba29dc602a55aba" [[package]] name = "signal-hook-registry" -version = "1.4.6" +version = "1.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2a4719bff48cee6b39d12c020eeb490953ad2443b7055bd0b21fca26bd8c28b" +checksum = "c4db69cba1110affc0e9f7bcd48bbf87b3f4fc7c61fc9155afd4c469eb3d6c1b" dependencies = [ + "errno", "libc", ] [[package]] name = "simd-adler32" -version = "0.3.7" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe" +checksum = "703d5c7ef118737c72f1af64ad2f6f8c5e1921f818cdcb97b8fe6fc69bf66214" + +[[package]] +name = "simd_cesu8" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94f90157bb87cddf702797c5dadfa0be7d266cdf49e22da2fcaa32eff75b2c33" +dependencies = [ + "rustc_version", + "simdutf8", +] + +[[package]] +name = "simdutf8" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3a9fe34e3e7a50316060351f37187a3f546bce95496156754b601a5fa71b76e" [[package]] name = "siphasher" -version = "1.0.1" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56199f7ddabf13fe5074ce809e7d3f42b42ae711800501b5b16ea82ad029c39d" +checksum = "8ee5873ec9cce0195efcb7a4e9507a04cd49aec9c83d0389df45b1ef7ba2e649" [[package]] name = "slab" -version = "0.4.11" +version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a2ae44ef20feb57a68b23d846850f861394c2e02dc425a50098ae8c90267589" +checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5" [[package]] name = "slotmap" -version = "1.0.7" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dbff4acf519f630b3a3ddcfaea6c06b42174d9a44bc70c620e9ed1649d58b82a" +checksum = "bdd58c3c93c3d278ca835519292445cb4b0d4dc59ccfdf7ceadaab3f8aeb4038" dependencies = [ "version_check", ] @@ -2501,29 +2448,19 @@ checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" [[package]] name = "socket2" -version = "0.5.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e22376abed350d73dd1cd119b57ffccad95b4e585a7cda43e286245ce23c0678" -dependencies = [ - "libc", - "windows-sys 0.52.0", -] - -[[package]] -name = "socket2" -version = "0.6.0" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "233504af464074f9d066d7b5416c5f9b894a5862a6506e306f7b816cdd6f1807" +checksum = "52d1cfed4120b4d927bf7c0f86d2087a4a7d6027c906d9f9d525a80573b9be51" dependencies = [ "libc", - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] name = "stable_deref_trait" -version = "1.2.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" +checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596" [[package]] name = "strsim" @@ -2539,9 +2476,9 @@ checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" [[package]] name = "syn" -version = "2.0.106" +version = "2.0.117" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ede7c438028d4436d71104916910f5bb611972c5cfd7f89b8300a8186e6fada6" +checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99" dependencies = [ "proc-macro2", "quote", @@ -2584,9 +2521,9 @@ dependencies = [ [[package]] name = "tar" -version = "0.4.45" +version = "0.4.46" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22692a6476a21fa75fdfc11d452fda482af402c008cdbaf3476414e122040973" +checksum = "3f6221d9a6003c78398e3b239969f352578258df48c8eb051caadae0015bc840" dependencies = [ "filetime", "libc", @@ -2595,21 +2532,21 @@ dependencies = [ [[package]] name = "target-lexicon" -version = "0.13.2" +version = "0.13.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e502f78cdbb8ba4718f566c418c52bc729126ffd16baee5baa718cf25dd5a69a" +checksum = "adb6935a6f5c20170eeceb1a3835a49e12e19d792f6dd344ccc76a985ca5a6ca" [[package]] name = "tempfile" -version = "3.20.0" +version = "3.27.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8a64e3985349f2441a1a9ef0b853f869006c3855f2cda6862a94d26ebb9d6a1" +checksum = "32497e9a4c7b38532efcdebeef879707aa9f794296a4f0244f6f69e9bc8574bd" dependencies = [ "fastrand", - "getrandom 0.3.3", + "getrandom 0.4.2", "once_cell", "rustix", - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -2635,7 +2572,7 @@ dependencies = [ [[package]] name = "temporalio-client" -version = "0.3.0" +version = "0.4.0" dependencies = [ "anyhow", "async-trait", @@ -2652,10 +2589,11 @@ dependencies = [ "hyper", "hyper-util", "parking_lot", - "rand 0.10.0", + "rand 0.10.1", "temporalio-common", - "thiserror 2.0.15", + "thiserror", "tokio", + "tokio-rustls", "tonic", "tower", "tracing", @@ -2665,11 +2603,10 @@ dependencies = [ [[package]] name = "temporalio-common" -version = "0.3.0" +version = "0.4.0" dependencies = [ "anyhow", "async-trait", - "base64", "bon", "crc32fast", "derive_more", @@ -2684,23 +2621,18 @@ dependencies = [ "opentelemetry-otlp", "opentelemetry_sdk", "parking_lot", - "pbjson", - "pbjson-build", "prometheus", "prost", "prost-types", - "prost-wkt", - "prost-wkt-types", - "rand 0.10.0", "ringbuf", "serde", "serde_json", - "thiserror 2.0.15", + "temporalio-common-wasm", + "temporalio-protos", + "thiserror", "tokio", "toml", "tonic", - "tonic-prost", - "tonic-prost-build", "tracing", "tracing-core", "tracing-subscriber", @@ -2708,18 +2640,62 @@ dependencies = [ "uuid", ] +[[package]] +name = "temporalio-common-wasm" +version = "0.4.0" +dependencies = [ + "anyhow", + "async-trait", + "bon", + "crc32fast", + "derive_more", + "erased-serde", + "futures", + "parking_lot", + "prost", + "serde", + "serde_json", + "temporalio-protos", + "thiserror", + "tracing", + "tracing-core", + "tracing-subscriber", + "url", +] + [[package]] name = "temporalio-macros" -version = "0.3.0" +version = "0.4.0" dependencies = [ "proc-macro2", "quote", "syn", ] +[[package]] +name = "temporalio-protos" +version = "0.4.0" +dependencies = [ + "anyhow", + "base64", + "derive_more", + "http", + "pbjson", + "pbjson-build", + "prost", + "prost-types", + "prost-wkt-types", + "serde", + "serde_json", + "thiserror", + "tonic", + "tonic-prost", + "tonic-prost-build", +] + [[package]] name = "temporalio-sdk-core" -version = "0.3.0" +version = "0.4.0" dependencies = [ "anyhow", "async-trait", @@ -2742,8 +2718,8 @@ dependencies = [ "pin-project", "prost", "prost-wkt-types", - "rand 0.10.0", - "reqwest 0.13.2", + "rand 0.10.1", + "reqwest 0.13.4", "serde", "serde_json", "siphasher", @@ -2753,7 +2729,7 @@ dependencies = [ "temporalio-client", "temporalio-common", "temporalio-macros", - "thiserror 2.0.15", + "thiserror", "tokio", "tokio-stream", "tokio-util", @@ -2772,38 +2748,18 @@ checksum = "8f50febec83f5ee1df3015341d8bd429f2d1cc62bcba7ea2076759d315084683" [[package]] name = "thiserror" -version = "1.0.69" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" -dependencies = [ - "thiserror-impl 1.0.69", -] - -[[package]] -name = "thiserror" -version = "2.0.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80d76d3f064b981389ecb4b6b7f45a0bf9fdac1d5b9204c7bd6714fecc302850" -dependencies = [ - "thiserror-impl 2.0.15", -] - -[[package]] -name = "thiserror-impl" -version = "1.0.69" +version = "2.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" +checksum = "4288b5bcbc7920c07a1149a35cf9590a2aa808e0bc1eafaade0b80947865fbc4" dependencies = [ - "proc-macro2", - "quote", - "syn", + "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "2.0.15" +version = "2.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44d29feb33e986b6ea906bd9c3559a856983f92371b3eaa5e83782a351623de0" +checksum = "ebc4ee7f67670e9b64d05fa4253e753e016c6c95ff35b89b7941d6b856dec1d5" dependencies = [ "proc-macro2", "quote", @@ -2821,9 +2777,9 @@ dependencies = [ [[package]] name = "tinystr" -version = "0.8.1" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d4f6d1145dcb577acf783d4e601bc1d76a13337bb54e6233add580b07344c8b" +checksum = "c8323304221c2a851516f22236c5722a72eaa19749016521d6dff0824447d96d" dependencies = [ "displaydoc", "zerovec", @@ -2831,9 +2787,9 @@ dependencies = [ [[package]] name = "tinyvec" -version = "1.10.0" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa5fdc3bce6191a1dbc8c02d5c8bffcf557bafa17c124c5264a458f1b0613fa" +checksum = "3e61e67053d25a4e82c844e8424039d9745781b3fc4f32b8d55ed50f5f667ef3" dependencies = [ "tinyvec_macros", ] @@ -2846,29 +2802,26 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.47.1" +version = "1.52.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89e49afdadebb872d3145a5638b59eb0691ea23e46ca484037cfab3b76b95038" +checksum = "8fc7f01b389ac15039e4dc9531aa973a135d7a4135281b12d7c1bc79fd57fffe" dependencies = [ - "backtrace", "bytes", - "io-uring", "libc", "mio", "parking_lot", "pin-project-lite", "signal-hook-registry", - "slab", - "socket2 0.6.0", + "socket2", "tokio-macros", - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] name = "tokio-macros" -version = "2.5.0" +version = "2.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e06d43f1345a3bcd39f6a56dbb7dcab2ba47e68e8ac134855e7e2bdbaf8cab8" +checksum = "385a6cb71ab9ab790c5fe8d67f1645e6c450a7ce006a33de03daa956cf70a496" dependencies = [ "proc-macro2", "quote", @@ -2877,9 +2830,9 @@ dependencies = [ [[package]] name = "tokio-rustls" -version = "0.26.2" +version = "0.26.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e727b36a1a0e8b74c376ac2211e40c2c8af09fb4013c60d910495810f008e9b" +checksum = "1729aa945f29d91ba541258c8df89027d5792d85a8841fb65e8bf0f4ede4ef61" dependencies = [ "rustls", "tokio", @@ -2887,9 +2840,9 @@ dependencies = [ [[package]] name = "tokio-stream" -version = "0.1.17" +version = "0.1.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eca58d7bba4a75707817a2c44174253f9236b2d5fbd055602e9d5c07c139a047" +checksum = "32da49809aab5c3bc678af03902d4ccddea2a87d028d86392a4b1560c6906c70" dependencies = [ "futures-core", "pin-project-lite", @@ -2898,9 +2851,9 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.7.16" +version = "0.7.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14307c986784f72ef81c89db7d9e28d6ac26d16213b109ea501696195e6e3ce5" +checksum = "9ae9cec805b01e8fc3fd2fe289f89149a9b66dd16786abd8b19cfa7b48cb0098" dependencies = [ "bytes", "futures-core", @@ -2950,9 +2903,9 @@ checksum = "756daf9b1013ebe47a8776667b466417e2d4c5679d441c26230efd9ef78692db" [[package]] name = "tonic" -version = "0.14.2" +version = "0.14.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb7613188ce9f7df5bfe185db26c5814347d110db17920415cf2fbcad85e7203" +checksum = "ac2a5518c70fa84342385732db33fb3f44bc4cc748936eb5833d2df34d6445ef" dependencies = [ "async-trait", "axum", @@ -2968,7 +2921,7 @@ dependencies = [ "percent-encoding", "pin-project", "rustls-native-certs", - "socket2 0.6.0", + "socket2", "sync_wrapper", "tokio", "tokio-rustls", @@ -2981,9 +2934,9 @@ dependencies = [ [[package]] name = "tonic-build" -version = "0.14.2" +version = "0.14.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c40aaccc9f9eccf2cd82ebc111adc13030d23e887244bc9cfa5d1d636049de3" +checksum = "c68f61875ac5293cf72e6c8cf0158086428c82c37229e98c840878f1706b0322" dependencies = [ "prettyplease", "proc-macro2", @@ -2993,9 +2946,9 @@ dependencies = [ [[package]] name = "tonic-prost" -version = "0.14.2" +version = "0.14.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "66bd50ad6ce1252d87ef024b3d64fe4c3cf54a86fb9ef4c631fdd0ded7aeaa67" +checksum = "50849f68853be452acf590cde0b146665b8d507b3b8af17261df47e02c209ea0" dependencies = [ "bytes", "prost", @@ -3004,9 +2957,9 @@ dependencies = [ [[package]] name = "tonic-prost-build" -version = "0.14.2" +version = "0.14.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4a16cba4043dc3ff43fcb3f96b4c5c154c64cbd18ca8dce2ab2c6a451d058a2" +checksum = "654e5643eff75d7f8c99197ce1440ed19a3474eada74c12bbac488b2cafdae27" dependencies = [ "prettyplease", "proc-macro2", @@ -3020,9 +2973,9 @@ dependencies = [ [[package]] name = "tower" -version = "0.5.2" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d039ad9159c98b70ecfd540b2573b97f7f52c3e8d9f8ad57a24b916a536975f9" +checksum = "ebe5ef63511595f1344e2d5cfa636d973292adc0eec1f0ad45fae9f0851ab1d4" dependencies = [ "futures-core", "futures-util", @@ -3039,20 +2992,20 @@ dependencies = [ [[package]] name = "tower-http" -version = "0.6.8" +version = "0.6.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4e6559d53cc268e5031cd8429d05415bc4cb4aefc4aa5d6cc35fbf5b924a1f8" +checksum = "4cfcf7e2740e6fc6d4d688b4ef00650406bb94adf4731e43c096c3a19fe40840" dependencies = [ "bitflags", "bytes", "futures-util", "http", "http-body", - "iri-string", "pin-project-lite", "tower", "tower-layer", "tower-service", + "url", ] [[package]] @@ -3069,9 +3022,9 @@ checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" [[package]] name = "tracing" -version = "0.1.41" +version = "0.1.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0" +checksum = "63e71662fa4b2a2c3a26f570f037eb95bb1f85397f3cd8076caed2f026a6d100" dependencies = [ "pin-project-lite", "tracing-attributes", @@ -3080,9 +3033,9 @@ dependencies = [ [[package]] name = "tracing-attributes" -version = "0.1.30" +version = "0.1.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81383ab64e72a7a8b8e13130c49e3dab29def6d0c7d76a03087b3cf71c5c6903" +checksum = "7490cfa5ec963746568740651ac6781f701c9c5ea257c58e057f3ba8cf69e8da" dependencies = [ "proc-macro2", "quote", @@ -3091,9 +3044,9 @@ dependencies = [ [[package]] name = "tracing-core" -version = "0.1.34" +version = "0.1.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9d12581f227e93f094d3af2ae690a574abb8a2b9b7a96e7cfe9647b2b617678" +checksum = "db97caf9d906fbde555dd62fa95ddba9eecfd14cb388e4f491a66d74cd5fb79a" dependencies = [ "once_cell", "valuable", @@ -3101,9 +3054,9 @@ dependencies = [ [[package]] name = "tracing-subscriber" -version = "0.3.20" +version = "0.3.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2054a14f5307d601f88daf0553e1cbf472acc4f2c51afab632431cdcd72124d5" +checksum = "cb7f578e5945fb242538965c2d0b04418d38ec25c79d160cd279bf0731c8d319" dependencies = [ "matchers", "nu-ansi-term", @@ -3136,9 +3089,9 @@ checksum = "bc7d623258602320d5c55d1bc22793b57daff0ec7efc270ea7d55ce1d5f5471c" [[package]] name = "typetag" -version = "0.2.20" +version = "0.2.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73f22b40dd7bfe8c14230cf9702081366421890435b2d625fa92b4acc4c3de6f" +checksum = "c5a897b12c6c1151ad0b138b8db50252dc301f93bc3b027db05eec82aeed298c" dependencies = [ "erased-serde", "inventory", @@ -3149,9 +3102,9 @@ dependencies = [ [[package]] name = "typetag-impl" -version = "0.2.20" +version = "0.2.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35f5380909ffc31b4de4f4bdf96b877175a016aa2ca98cee39fcfd8c4d53d952" +checksum = "cf808357c6ed7e13ba0f3277ec8d8f21b2d501274895104263985330c726c1c5" dependencies = [ "proc-macro2", "quote", @@ -3160,15 +3113,21 @@ dependencies = [ [[package]] name = "unicase" -version = "2.8.1" +version = "2.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75b844d17643ee918803943289730bec8aac480150456169e647ed0b576ba539" +checksum = "dbc4bc3a9f746d862c45cb89d705aa10f187bb96c76001afab07a0d35ce60142" [[package]] name = "unicode-ident" -version = "1.0.18" +version = "1.0.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" +checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" + +[[package]] +name = "unicode-segmentation" +version = "1.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9629274872b2bfaf8d66f5f15725007f635594914870f65218920345aa11aa8c" [[package]] name = "unicode-xid" @@ -3190,13 +3149,14 @@ checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" [[package]] name = "url" -version = "2.5.4" +version = "2.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32f8b686cadd1473f4bd0117a5d28d36b1ade384ea9b5069a1c40aefed7fda60" +checksum = "ff67a8a4397373c3ef660812acab3268222035010ab8680ec4215f38ba3d0eed" dependencies = [ "form_urlencoded", "idna", "percent-encoding", + "serde", ] [[package]] @@ -3207,11 +3167,11 @@ checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" [[package]] name = "uuid" -version = "1.18.1" +version = "1.23.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f87b8aa10b915a06587d0dec516c282ff295b475d94abf425d62b57710070a2" +checksum = "d258b83ceec21034727ecee8c382cfa6c3e133699b0742c64571814fb420c9f7" dependencies = [ - "getrandom 0.3.3", + "getrandom 0.4.2", ] [[package]] @@ -3251,22 +3211,13 @@ version = "0.11.1+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" -[[package]] -name = "wasi" -version = "0.14.2+wasi-0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9683f9a5a998d873c0d21fcbe3c083009670149a8fab228644b8bd36b2c48cb3" -dependencies = [ - "wit-bindgen-rt", -] - [[package]] name = "wasip2" -version = "1.0.2+wasi-0.2.9" +version = "1.0.3+wasi-0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9517f9239f02c069db75e65f174b3da828fe5f5b945c4dd26bd25d89c03ebcf5" +checksum = "20064672db26d7cdc89c7798c48a0fdfac8213434a1186e5ef29fd560ae223d6" dependencies = [ - "wit-bindgen", + "wit-bindgen 0.57.1", ] [[package]] @@ -3275,14 +3226,14 @@ version = "0.4.0+wasi-0.3.0-rc-2026-01-06" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5428f8bf88ea5ddc08faddef2ac4a67e390b88186c703ce6dbd955e1c145aca5" dependencies = [ - "wit-bindgen", + "wit-bindgen 0.51.0", ] [[package]] name = "wasm-bindgen" -version = "0.2.117" +version = "0.2.122" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0551fc1bb415591e3372d0bc4780db7e587d84e2a7e79da121051c5c4b89d0b0" +checksum = "3ed04576f974d2b2fba0f38c51dbc5518011e38c36bf1143164be765528fd409" dependencies = [ "cfg-if", "once_cell", @@ -3293,9 +3244,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-futures" -version = "0.4.67" +version = "0.4.72" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03623de6905b7206edd0a75f69f747f134b7f0a2323392d664448bf2d3c5d87e" +checksum = "9473dbd2991ae90b6291c3c32c30c6187ac49aa32f9905d1cce280ec1e110b0f" dependencies = [ "js-sys", "wasm-bindgen", @@ -3303,9 +3254,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.117" +version = "0.2.122" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fbdf9a35adf44786aecd5ff89b4563a90325f9da0923236f6104e603c7e86be" +checksum = "916151b09da36bd82f6615cbf3a419e2f0ba23a03c6160e8e92eb6bd4aa1dec6" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -3313,9 +3264,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.117" +version = "0.2.122" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dca9693ef2bab6d4e6707234500350d8dad079eb508dca05530c85dc3a529ff2" +checksum = "299047362ccbfce148b67ab7e73349f77748e00c8296f9542adfad2ad82c5c5e" dependencies = [ "bumpalo", "proc-macro2", @@ -3326,9 +3277,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.117" +version = "0.2.122" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39129a682a6d2d841b6c429d0c51e5cb0ed1a03829d8b3d1e69a011e62cb3d3b" +checksum = "9a929b2c61f11ba3e9bc35b50c1f25cb38e0e892c0c231ae2b8cf78d5dad4437" dependencies = [ "unicode-ident", ] @@ -3382,9 +3333,9 @@ dependencies = [ [[package]] name = "web-sys" -version = "0.3.94" +version = "0.3.99" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd70027e39b12f0849461e08ffc50b9cd7688d942c1c8e3c7b22273236b4dd0a" +checksum = "6d621441cfc37b84979402712047321980c178f299193a3589d05b99e8763436" dependencies = [ "js-sys", "wasm-bindgen", @@ -3402,9 +3353,9 @@ dependencies = [ [[package]] name = "webpki-root-certs" -version = "1.0.6" +version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "804f18a4ac2676ffb4e8b5b5fa9ae38af06df08162314f96a68d2a363e21a8ca" +checksum = "f31141ce3fc3e300ae89b78c0dd67f9708061d1d2eda54b8209346fd6be9a92c" dependencies = [ "rustls-pki-types", ] @@ -3431,7 +3382,7 @@ version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" dependencies = [ - "windows-sys 0.60.2", + "windows-sys 0.61.2", ] [[package]] @@ -3469,7 +3420,7 @@ checksum = "b8e83a14d34d0623b51dce9581199302a221863196a1dde71a7663a4c2be9deb" dependencies = [ "windows-implement", "windows-interface", - "windows-link 0.2.1", + "windows-link", "windows-result", "windows-strings", ] @@ -3481,7 +3432,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e1d6f90251fe18a279739e78025bd6ddc52a7e22f921070ccdc67dde84c605cb" dependencies = [ "windows-core", - "windows-link 0.2.1", + "windows-link", "windows-threading", ] @@ -3507,12 +3458,6 @@ dependencies = [ "syn", ] -[[package]] -name = "windows-link" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e6ad25900d524eaabdbbb96d20b4311e1e7ae1699af4fb28c17ae66c80d798a" - [[package]] name = "windows-link" version = "0.2.1" @@ -3526,7 +3471,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6e2e40844ac143cdb44aead537bbf727de9b044e107a0f1220392177d15b0f26" dependencies = [ "windows-core", - "windows-link 0.2.1", + "windows-link", ] [[package]] @@ -3535,7 +3480,7 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7781fa89eaf60850ac3d2da7af8e5242a5ea78d1a11c49bf2910bb5a73853eb5" dependencies = [ - "windows-link 0.2.1", + "windows-link", ] [[package]] @@ -3544,16 +3489,7 @@ version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7837d08f69c77cf6b07689544538e017c1bfcf57e34b4c0ff58e6c2cd3b37091" dependencies = [ - "windows-link 0.2.1", -] - -[[package]] -name = "windows-sys" -version = "0.45.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" -dependencies = [ - "windows-targets 0.42.2", + "windows-link", ] [[package]] @@ -3565,37 +3501,22 @@ dependencies = [ "windows-targets 0.52.6", ] -[[package]] -name = "windows-sys" -version = "0.59.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" -dependencies = [ - "windows-targets 0.52.6", -] - [[package]] name = "windows-sys" version = "0.60.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb" dependencies = [ - "windows-targets 0.53.3", + "windows-targets 0.53.5", ] [[package]] -name = "windows-targets" -version = "0.42.2" +name = "windows-sys" +version = "0.61.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071" +checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" dependencies = [ - "windows_aarch64_gnullvm 0.42.2", - "windows_aarch64_msvc 0.42.2", - "windows_i686_gnu 0.42.2", - "windows_i686_msvc 0.42.2", - "windows_x86_64_gnu 0.42.2", - "windows_x86_64_gnullvm 0.42.2", - "windows_x86_64_msvc 0.42.2", + "windows-link", ] [[package]] @@ -3616,19 +3537,19 @@ dependencies = [ [[package]] name = "windows-targets" -version = "0.53.3" +version = "0.53.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5fe6031c4041849d7c496a8ded650796e7b6ecc19df1a431c1a363342e5dc91" +checksum = "4945f9f551b88e0d65f3db0bc25c33b8acea4d9e41163edf90dcd0b19f9069f3" dependencies = [ - "windows-link 0.1.3", - "windows_aarch64_gnullvm 0.53.0", - "windows_aarch64_msvc 0.53.0", - "windows_i686_gnu 0.53.0", - "windows_i686_gnullvm 0.53.0", - "windows_i686_msvc 0.53.0", - "windows_x86_64_gnu 0.53.0", - "windows_x86_64_gnullvm 0.53.0", - "windows_x86_64_msvc 0.53.0", + "windows-link", + "windows_aarch64_gnullvm 0.53.1", + "windows_aarch64_msvc 0.53.1", + "windows_i686_gnu 0.53.1", + "windows_i686_gnullvm 0.53.1", + "windows_i686_msvc 0.53.1", + "windows_x86_64_gnu 0.53.1", + "windows_x86_64_gnullvm 0.53.1", + "windows_x86_64_msvc 0.53.1", ] [[package]] @@ -3637,15 +3558,9 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3949bd5b99cafdf1c7ca86b43ca564028dfe27d66958f2470940f73d86d75b37" dependencies = [ - "windows-link 0.2.1", + "windows-link", ] -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" - [[package]] name = "windows_aarch64_gnullvm" version = "0.52.6" @@ -3654,15 +3569,9 @@ checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" [[package]] name = "windows_aarch64_gnullvm" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86b8d5f90ddd19cb4a147a5fa63ca848db3df085e25fee3cc10b39b6eebae764" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.42.2" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" +checksum = "a9d8416fa8b42f5c947f8482c43e7d89e73a173cead56d044f6a56104a6d1b53" [[package]] name = "windows_aarch64_msvc" @@ -3672,15 +3581,9 @@ checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" [[package]] name = "windows_aarch64_msvc" -version = "0.53.0" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7651a1f62a11b8cbd5e0d42526e55f2c99886c77e007179efff86c2b137e66c" - -[[package]] -name = "windows_i686_gnu" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" +checksum = "b9d782e804c2f632e395708e99a94275910eb9100b2114651e04744e9b125006" [[package]] name = "windows_i686_gnu" @@ -3690,9 +3593,9 @@ checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" [[package]] name = "windows_i686_gnu" -version = "0.53.0" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1dc67659d35f387f5f6c479dc4e28f1d4bb90ddd1a5d3da2e5d97b42d6272c3" +checksum = "960e6da069d81e09becb0ca57a65220ddff016ff2d6af6a223cf372a506593a3" [[package]] name = "windows_i686_gnullvm" @@ -3702,15 +3605,9 @@ checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" [[package]] name = "windows_i686_gnullvm" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ce6ccbdedbf6d6354471319e781c0dfef054c81fbc7cf83f338a4296c0cae11" - -[[package]] -name = "windows_i686_msvc" -version = "0.42.2" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" +checksum = "fa7359d10048f68ab8b09fa71c3daccfb0e9b559aed648a8f95469c27057180c" [[package]] name = "windows_i686_msvc" @@ -3720,15 +3617,9 @@ checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" [[package]] name = "windows_i686_msvc" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "581fee95406bb13382d2f65cd4a908ca7b1e4c2f1917f143ba16efe98a589b5d" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.42.2" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" +checksum = "1e7ac75179f18232fe9c285163565a57ef8d3c89254a30685b57d83a38d326c2" [[package]] name = "windows_x86_64_gnu" @@ -3738,15 +3629,9 @@ checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" [[package]] name = "windows_x86_64_gnu" -version = "0.53.0" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e55b5ac9ea33f2fc1716d1742db15574fd6fc8dadc51caab1c16a3d3b4190ba" - -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" +checksum = "9c3842cdd74a865a8066ab39c8a7a473c0778a3f29370b5fd6b4b9aa7df4a499" [[package]] name = "windows_x86_64_gnullvm" @@ -3756,15 +3641,9 @@ checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" [[package]] name = "windows_x86_64_gnullvm" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a6e035dd0599267ce1ee132e51c27dd29437f63325753051e71dd9e42406c57" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.42.2" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" +checksum = "0ffa179e2d07eee8ad8f57493436566c7cc30ac536a3379fdf008f47f6bb7ae1" [[package]] name = "windows_x86_64_msvc" @@ -3774,15 +3653,15 @@ checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" [[package]] name = "windows_x86_64_msvc" -version = "0.53.0" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486" +checksum = "d6bbff5f0aada427a1e5a6da5f1f98158182f26556f345ac9e04d36d0ebed650" [[package]] name = "winnow" -version = "1.0.1" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09dac053f1cd375980747450bfc7250c264eaae0583872e845c0c7cd578872b5" +checksum = "0592e1c9d151f854e6fd382574c3a0855250e1d9b2f99d9281c6e6391af352f1" [[package]] name = "wit-bindgen" @@ -3793,6 +3672,12 @@ dependencies = [ "wit-bindgen-rust-macro", ] +[[package]] +name = "wit-bindgen" +version = "0.57.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ebf944e87a7c253233ad6766e082e3cd714b5d03812acc24c318f549614536e" + [[package]] name = "wit-bindgen-core" version = "0.51.0" @@ -3804,15 +3689,6 @@ dependencies = [ "wit-parser", ] -[[package]] -name = "wit-bindgen-rt" -version = "0.39.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f42320e61fe2cfd34354ecb597f86f413484a798ba44a8ca1165c58d42da6c1" -dependencies = [ - "bitflags", -] - [[package]] name = "wit-bindgen-rust" version = "0.51.0" @@ -3883,15 +3759,15 @@ dependencies = [ [[package]] name = "writeable" -version = "0.6.1" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea2f10b9bb0928dfb1b42b65e1f9e36f7f54dbdf08457afefb38afcdec4fa2bb" +checksum = "1ffae5123b2d3fc086436f8834ae3ab053a283cfac8fe0a0b8eaae044768a4c4" [[package]] name = "xattr" -version = "1.5.1" +version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af3a19837351dc82ba89f8a125e22a3c475f05aba604acc023d62b2739ae2909" +checksum = "32e45ad4206f6d2479085147f02bc2ef834ac85886624a23575ae137c8aa8156" dependencies = [ "libc", "rustix", @@ -3899,11 +3775,10 @@ dependencies = [ [[package]] name = "yoke" -version = "0.8.0" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f41bb01b8226ef4bfd589436a297c53d118f65921786300e427be8d487695cc" +checksum = "abe8c5fda708d9ca3df187cae8bfb9ceda00dd96231bed36e445a1a48e66f9ca" dependencies = [ - "serde", "stable_deref_trait", "yoke-derive", "zerofrom", @@ -3911,9 +3786,9 @@ dependencies = [ [[package]] name = "yoke-derive" -version = "0.8.0" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38da3c9736e16c5d3c8c597a9aaa5d1fa565d0532ae05e27c24aa62fb32c0ab6" +checksum = "de844c262c8848816172cef550288e7dc6c7b7814b4ee56b3e1553f275f1858e" dependencies = [ "proc-macro2", "quote", @@ -3923,18 +3798,18 @@ dependencies = [ [[package]] name = "zerocopy" -version = "0.8.26" +version = "0.8.50" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1039dd0d3c310cf05de012d8a39ff557cb0d23087fd44cad61df08fc31907a2f" +checksum = "3b065d4f0e55f82fae73202e189638116a87c55ab6b8e6c2721e13dd9d854ad1" dependencies = [ "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.8.26" +version = "0.8.50" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ecf5b4cc5364572d7f4c329661bcc82724222973f2cab6f050a4e5c22f75181" +checksum = "0b631b19d36a892ab55420c92dbc83ccd79274f25be714855d3074aa71cab639" dependencies = [ "proc-macro2", "quote", @@ -3943,18 +3818,18 @@ dependencies = [ [[package]] name = "zerofrom" -version = "0.1.6" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50cc42e0333e05660c3587f3bf9d0478688e15d870fab3346451ce7f8c9fbea5" +checksum = "0ec05a11813ea801ff6d75110ad09cd0824ddba17dfe17128ea0d5f68e6c5272" dependencies = [ "zerofrom-derive", ] [[package]] name = "zerofrom-derive" -version = "0.1.6" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502" +checksum = "11532158c46691caf0f2593ea8358fed6bbf68a0315e80aae9bd41fbade684a1" dependencies = [ "proc-macro2", "quote", @@ -3964,15 +3839,15 @@ dependencies = [ [[package]] name = "zeroize" -version = "1.8.1" +version = "1.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" +checksum = "b97154e67e32c85465826e8bcc1c59429aaaf107c1e4a9e53c8d8ccd5eff88d0" [[package]] name = "zerotrie" -version = "0.2.2" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "36f0bbd478583f79edad978b407914f61b2972f5af6fa089686016be8f9af595" +checksum = "0f9152d31db0792fa83f70fb2f83148effb5c1f5b8c7686c3459e361d9bc20bf" dependencies = [ "displaydoc", "yoke", @@ -3981,9 +3856,9 @@ dependencies = [ [[package]] name = "zerovec" -version = "0.11.4" +version = "0.11.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7aa2bd55086f1ab526693ecbe444205da57e25f4489879da80635a46d90e73b" +checksum = "90f911cbc359ab6af17377d242225f4d75119aec87ea711a880987b18cd7b239" dependencies = [ "yoke", "zerofrom", @@ -3992,9 +3867,9 @@ dependencies = [ [[package]] name = "zerovec-derive" -version = "0.11.1" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b96237efa0c878c64bd89c436f661be4e46b2f3eff1ebb976f7ef2321d2f58f" +checksum = "625dc425cab0dca6dc3c3319506e6593dcb08a9f387ea3b284dbd52a92c40555" dependencies = [ "proc-macro2", "quote", @@ -4003,9 +3878,9 @@ dependencies = [ [[package]] name = "zip" -version = "8.5.0" +version = "8.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2726508a48f38dceb22b35ecbbd2430efe34ff05c62bd3285f965d7911b33464" +checksum = "2d04a6b5381502aa6087c94c669499eb1602eb9c5e8198e534de571f7154809b" dependencies = [ "bzip2", "crc32fast", @@ -4019,9 +3894,15 @@ dependencies = [ [[package]] name = "zlib-rs" -version = "0.5.2" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3be3d40e40a133f9c916ee3f9f4fa2d9d63435b5fbe1bfc6d9dae0aa0ada1513" + +[[package]] +name = "zmij" +version = "1.0.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f06ae92f42f5e5c42443fd094f245eb656abf56dd7cce9b8b263236565e00f2" +checksum = "b8848ee67ecc8aedbaf3e4122217aff892639231befc6a1b58d29fff4c2cabaa" [[package]] name = "zopfli" @@ -4055,9 +3936,9 @@ dependencies = [ [[package]] name = "zstd-sys" -version = "2.0.15+zstd.1.5.7" +version = "2.0.16+zstd.1.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb81183ddd97d0c74cedf1d50d85c8d08c1b8b68ee863bdee9e706eedba1a237" +checksum = "91e19ebc2adc8f83e43039e79776e3fda8ca919132d68a1fed6a5faca2683748" dependencies = [ "cc", "pkg-config", diff --git a/temporalio/bridge/Cargo.toml b/temporalio/bridge/Cargo.toml index 31e8ee633..ade771d73 100644 --- a/temporalio/bridge/Cargo.toml +++ b/temporalio/bridge/Cargo.toml @@ -28,11 +28,11 @@ pyo3 = { version = "0.25", features = [ ] } pyo3-async-runtimes = { version = "0.25", features = ["tokio-runtime"] } pythonize = "0.25" -temporalio-client = { version = "0.3.0", path = "./sdk-core/crates/client" } -temporalio-common = { version = "0.3.0", path = "./sdk-core/crates/common", features = [ +temporalio-client = { version = "0.4", path = "./sdk-core/crates/client" } +temporalio-common = { version = "0.4", path = "./sdk-core/crates/common", features = [ "envconfig", "otel" ]} -temporalio-sdk-core = { version = "0.3.0", path = "./sdk-core/crates/sdk-core", features = [ +temporalio-sdk-core = { version = "0.4", path = "./sdk-core/crates/sdk-core", features = [ "ephemeral-server", ] } tokio = "1.26" diff --git a/temporalio/bridge/sdk-core b/temporalio/bridge/sdk-core index 2872b5363..6a8355ac4 160000 --- a/temporalio/bridge/sdk-core +++ b/temporalio/bridge/sdk-core @@ -1 +1 @@ -Subproject commit 2872b5363e1b745cfb90313ebc7a507c5d25c398 +Subproject commit 6a8355ac4c49884433b0502f31bddace0c6ce884 diff --git a/temporalio/bridge/services_generated.py b/temporalio/bridge/services_generated.py index f483c318a..ff988d1a4 100644 --- a/temporalio/bridge/services_generated.py +++ b/temporalio/bridge/services_generated.py @@ -1053,6 +1053,24 @@ async def pause_activity( timeout=timeout, ) + async def pause_activity_execution( + self, + req: temporalio.api.workflowservice.v1.PauseActivityExecutionRequest, + retry: bool = False, + metadata: Mapping[str, str | bytes] = {}, + timeout: timedelta | None = None, + ) -> temporalio.api.workflowservice.v1.PauseActivityExecutionResponse: + """Invokes the WorkflowService.pause_activity_execution rpc method.""" + return await self._client._rpc_call( + rpc="pause_activity_execution", + req=req, + service=self._service, + resp_type=temporalio.api.workflowservice.v1.PauseActivityExecutionResponse, + retry=retry, + metadata=metadata, + timeout=timeout, + ) + async def pause_workflow_execution( self, req: temporalio.api.workflowservice.v1.PauseWorkflowExecutionRequest, @@ -1341,6 +1359,24 @@ async def reset_activity( timeout=timeout, ) + async def reset_activity_execution( + self, + req: temporalio.api.workflowservice.v1.ResetActivityExecutionRequest, + retry: bool = False, + metadata: Mapping[str, str | bytes] = {}, + timeout: timedelta | None = None, + ) -> temporalio.api.workflowservice.v1.ResetActivityExecutionResponse: + """Invokes the WorkflowService.reset_activity_execution rpc method.""" + return await self._client._rpc_call( + rpc="reset_activity_execution", + req=req, + service=self._service, + resp_type=temporalio.api.workflowservice.v1.ResetActivityExecutionResponse, + retry=retry, + metadata=metadata, + timeout=timeout, + ) + async def reset_sticky_task_queue( self, req: temporalio.api.workflowservice.v1.ResetStickyTaskQueueRequest, @@ -1899,6 +1935,24 @@ async def unpause_activity( timeout=timeout, ) + async def unpause_activity_execution( + self, + req: temporalio.api.workflowservice.v1.UnpauseActivityExecutionRequest, + retry: bool = False, + metadata: Mapping[str, str | bytes] = {}, + timeout: timedelta | None = None, + ) -> temporalio.api.workflowservice.v1.UnpauseActivityExecutionResponse: + """Invokes the WorkflowService.unpause_activity_execution rpc method.""" + return await self._client._rpc_call( + rpc="unpause_activity_execution", + req=req, + service=self._service, + resp_type=temporalio.api.workflowservice.v1.UnpauseActivityExecutionResponse, + retry=retry, + metadata=metadata, + timeout=timeout, + ) + async def unpause_workflow_execution( self, req: temporalio.api.workflowservice.v1.UnpauseWorkflowExecutionRequest, @@ -1917,6 +1971,24 @@ async def unpause_workflow_execution( timeout=timeout, ) + async def update_activity_execution_options( + self, + req: temporalio.api.workflowservice.v1.UpdateActivityExecutionOptionsRequest, + retry: bool = False, + metadata: Mapping[str, str | bytes] = {}, + timeout: timedelta | None = None, + ) -> temporalio.api.workflowservice.v1.UpdateActivityExecutionOptionsResponse: + """Invokes the WorkflowService.update_activity_execution_options rpc method.""" + return await self._client._rpc_call( + rpc="update_activity_execution_options", + req=req, + service=self._service, + resp_type=temporalio.api.workflowservice.v1.UpdateActivityExecutionOptionsResponse, + retry=retry, + metadata=metadata, + timeout=timeout, + ) + async def update_activity_options( self, req: temporalio.api.workflowservice.v1.UpdateActivityOptionsRequest, @@ -2477,6 +2549,24 @@ async def create_connectivity_rule( timeout=timeout, ) + async def create_custom_role( + self, + req: temporalio.api.cloud.cloudservice.v1.CreateCustomRoleRequest, + retry: bool = False, + metadata: Mapping[str, str | bytes] = {}, + timeout: timedelta | None = None, + ) -> temporalio.api.cloud.cloudservice.v1.CreateCustomRoleResponse: + """Invokes the CloudService.create_custom_role rpc method.""" + return await self._client._rpc_call( + rpc="create_custom_role", + req=req, + service=self._service, + resp_type=temporalio.api.cloud.cloudservice.v1.CreateCustomRoleResponse, + retry=retry, + metadata=metadata, + timeout=timeout, + ) + async def create_namespace( self, req: temporalio.api.cloud.cloudservice.v1.CreateNamespaceRequest, @@ -2639,6 +2729,24 @@ async def delete_connectivity_rule( timeout=timeout, ) + async def delete_custom_role( + self, + req: temporalio.api.cloud.cloudservice.v1.DeleteCustomRoleRequest, + retry: bool = False, + metadata: Mapping[str, str | bytes] = {}, + timeout: timedelta | None = None, + ) -> temporalio.api.cloud.cloudservice.v1.DeleteCustomRoleResponse: + """Invokes the CloudService.delete_custom_role rpc method.""" + return await self._client._rpc_call( + rpc="delete_custom_role", + req=req, + service=self._service, + resp_type=temporalio.api.cloud.cloudservice.v1.DeleteCustomRoleResponse, + retry=retry, + metadata=metadata, + timeout=timeout, + ) + async def delete_namespace( self, req: temporalio.api.cloud.cloudservice.v1.DeleteNamespaceRequest, @@ -2981,6 +3089,42 @@ async def get_current_identity( timeout=timeout, ) + async def get_custom_role( + self, + req: temporalio.api.cloud.cloudservice.v1.GetCustomRoleRequest, + retry: bool = False, + metadata: Mapping[str, str | bytes] = {}, + timeout: timedelta | None = None, + ) -> temporalio.api.cloud.cloudservice.v1.GetCustomRoleResponse: + """Invokes the CloudService.get_custom_role rpc method.""" + return await self._client._rpc_call( + rpc="get_custom_role", + req=req, + service=self._service, + resp_type=temporalio.api.cloud.cloudservice.v1.GetCustomRoleResponse, + retry=retry, + metadata=metadata, + timeout=timeout, + ) + + async def get_custom_roles( + self, + req: temporalio.api.cloud.cloudservice.v1.GetCustomRolesRequest, + retry: bool = False, + metadata: Mapping[str, str | bytes] = {}, + timeout: timedelta | None = None, + ) -> temporalio.api.cloud.cloudservice.v1.GetCustomRolesResponse: + """Invokes the CloudService.get_custom_roles rpc method.""" + return await self._client._rpc_call( + rpc="get_custom_roles", + req=req, + service=self._service, + resp_type=temporalio.api.cloud.cloudservice.v1.GetCustomRolesResponse, + retry=retry, + metadata=metadata, + timeout=timeout, + ) + async def get_namespace( self, req: temporalio.api.cloud.cloudservice.v1.GetNamespaceRequest, @@ -3431,6 +3575,24 @@ async def update_api_key( timeout=timeout, ) + async def update_custom_role( + self, + req: temporalio.api.cloud.cloudservice.v1.UpdateCustomRoleRequest, + retry: bool = False, + metadata: Mapping[str, str | bytes] = {}, + timeout: timedelta | None = None, + ) -> temporalio.api.cloud.cloudservice.v1.UpdateCustomRoleResponse: + """Invokes the CloudService.update_custom_role rpc method.""" + return await self._client._rpc_call( + rpc="update_custom_role", + req=req, + service=self._service, + resp_type=temporalio.api.cloud.cloudservice.v1.UpdateCustomRoleResponse, + retry=retry, + metadata=metadata, + timeout=timeout, + ) + async def update_namespace( self, req: temporalio.api.cloud.cloudservice.v1.UpdateNamespaceRequest, diff --git a/temporalio/bridge/src/client.rs b/temporalio/bridge/src/client.rs index 8da620a74..369df0795 100644 --- a/temporalio/bridge/src/client.rs +++ b/temporalio/bridge/src/client.rs @@ -300,6 +300,7 @@ impl TryFrom for temporalio_client::TlsOptions { )) } }, + server_cert_verifier: None, }) } } diff --git a/temporalio/bridge/src/client_rpc_generated.rs b/temporalio/bridge/src/client_rpc_generated.rs index 85c537225..c44fbcb1b 100644 --- a/temporalio/bridge/src/client_rpc_generated.rs +++ b/temporalio/bridge/src/client_rpc_generated.rs @@ -533,6 +533,15 @@ impl ClientRef { pause_activity ) } + "pause_activity_execution" => { + rpc_call!( + connection, + call, + WorkflowService, + workflow_service, + pause_activity_execution + ) + } "pause_workflow_execution" => { rpc_call!( connection, @@ -677,6 +686,15 @@ impl ClientRef { reset_activity ) } + "reset_activity_execution" => { + rpc_call!( + connection, + call, + WorkflowService, + workflow_service, + reset_activity_execution + ) + } "reset_sticky_task_queue" => { rpc_call!( connection, @@ -956,6 +974,15 @@ impl ClientRef { unpause_activity ) } + "unpause_activity_execution" => { + rpc_call!( + connection, + call, + WorkflowService, + workflow_service, + unpause_activity_execution + ) + } "unpause_workflow_execution" => { rpc_call!( connection, @@ -965,6 +992,15 @@ impl ClientRef { unpause_workflow_execution ) } + "update_activity_execution_options" => { + rpc_call!( + connection, + call, + WorkflowService, + workflow_service, + update_activity_execution_options + ) + } "update_activity_options" => { rpc_call!( connection, @@ -1273,6 +1309,15 @@ impl ClientRef { create_connectivity_rule ) } + "create_custom_role" => { + rpc_call!( + connection, + call, + CloudService, + cloud_service, + create_custom_role + ) + } "create_namespace" => { rpc_call!( connection, @@ -1348,6 +1393,15 @@ impl ClientRef { delete_connectivity_rule ) } + "delete_custom_role" => { + rpc_call!( + connection, + call, + CloudService, + cloud_service, + delete_custom_role + ) + } "delete_namespace" => { rpc_call!( connection, @@ -1495,6 +1549,24 @@ impl ClientRef { get_current_identity ) } + "get_custom_role" => { + rpc_call!( + connection, + call, + CloudService, + cloud_service, + get_custom_role + ) + } + "get_custom_roles" => { + rpc_call!( + connection, + call, + CloudService, + cloud_service, + get_custom_roles + ) + } "get_namespace" => { rpc_call!(connection, call, CloudService, cloud_service, get_namespace) } @@ -1684,6 +1756,15 @@ impl ClientRef { update_api_key ) } + "update_custom_role" => { + rpc_call!( + connection, + call, + CloudService, + cloud_service, + update_custom_role + ) + } "update_namespace" => { rpc_call!( connection, diff --git a/tests/worker/test_workflow.py b/tests/worker/test_workflow.py index 72a5862c7..cb5bb8067 100644 --- a/tests/worker/test_workflow.py +++ b/tests/worker/test_workflow.py @@ -963,9 +963,6 @@ async def run(self, params: CancelActivityWorkflowParams) -> None: self._activity_result = await handle except ActivityError as err: self._activity_result = f"Error: {err.cause.__class__.__name__}" - # TODO(cretz): Remove when https://github.com/temporalio/sdk-rust/issues/323 is fixed - except CancelledError as err: - self._activity_result = f"Error: {err.__class__.__name__}" # Wait forever await asyncio.Future() From cb9c06fa9b3133483cc44384d792f8d7b174ba01 Mon Sep 17 00:00:00 2001 From: Alex Mazzeo Date: Tue, 2 Jun 2026 09:17:28 -0700 Subject: [PATCH 114/226] Swap from TemporalNexus prefix to Temporal (#1569) * Swap from TemporalNexus prefix to Temporal * Swap one more prefix * Fix broken docs links --- temporalio/client/_nexus.py | 4 +- temporalio/nexus/__init__.py | 16 ++++---- temporalio/nexus/_decorators.py | 40 +++++++++---------- temporalio/nexus/_operation_context.py | 4 +- temporalio/nexus/_operation_handlers.py | 22 +++++----- temporalio/nexus/_util.py | 6 +-- temporalio/workflow/_nexus.py | 4 +- .../test_handler_operation_definitions.py | 4 +- tests/nexus/test_nexus_type_errors.py | 16 ++++---- tests/nexus/test_temporal_operation.py | 32 +++++++-------- 10 files changed, 70 insertions(+), 78 deletions(-) diff --git a/temporalio/client/_nexus.py b/temporalio/client/_nexus.py index 8cd95b26f..7eea155a9 100644 --- a/temporalio/client/_nexus.py +++ b/temporalio/client/_nexus.py @@ -619,7 +619,7 @@ async def start_operation( operation: Callable[ [ NexusServiceType, - temporalio.nexus.TemporalNexusStartOperationContext, + temporalio.nexus.TemporalStartOperationContext, temporalio.nexus.TemporalNexusClient, InputT, ], @@ -841,7 +841,7 @@ async def execute_operation( operation: Callable[ [ NexusServiceType, - temporalio.nexus.TemporalNexusStartOperationContext, + temporalio.nexus.TemporalStartOperationContext, temporalio.nexus.TemporalNexusClient, InputT, ], diff --git a/temporalio/nexus/__init__.py b/temporalio/nexus/__init__.py index f1a10767d..402e4b04e 100644 --- a/temporalio/nexus/__init__.py +++ b/temporalio/nexus/__init__.py @@ -4,7 +4,7 @@ """ from ._decorators import ( - TemporalNexusOperationStartHandlerFunc, + TemporalOperationStartHandlerFunc, temporal_operation, workflow_run_operation, ) @@ -12,8 +12,8 @@ Info, LoggerAdapter, NexusCallback, - TemporalNexusCancelOperationContext, - TemporalNexusStartOperationContext, + TemporalCancelOperationContext, + TemporalStartOperationContext, WorkflowRunOperationContext, client, in_operation, @@ -26,7 +26,7 @@ ) from ._operation_handlers import ( CancelWorkflowRunOptions, - TemporalNexusOperationHandler, + TemporalOperationHandler, ) from ._temporal_client import TemporalNexusClient, TemporalOperationResult from ._token import WorkflowHandle @@ -38,8 +38,8 @@ "LoggerAdapter", "NexusCallback", "WorkflowRunOperationContext", - "TemporalNexusCancelOperationContext", - "TemporalNexusStartOperationContext", + "TemporalCancelOperationContext", + "TemporalStartOperationContext", "client", "in_operation", "info", @@ -50,8 +50,8 @@ "wait_for_worker_shutdown_sync", "WorkflowHandle", "TemporalNexusClient", - "TemporalNexusOperationStartHandlerFunc", - "TemporalNexusOperationHandler", + "TemporalOperationStartHandlerFunc", + "TemporalOperationHandler", "TemporalOperationResult", "temporal_operation", ) diff --git a/temporalio/nexus/_decorators.py b/temporalio/nexus/_decorators.py index 3f1a322e7..2dd2b3554 100644 --- a/temporalio/nexus/_decorators.py +++ b/temporalio/nexus/_decorators.py @@ -21,11 +21,11 @@ from temporalio.types import NexusServiceType from ._operation_context import ( - TemporalNexusStartOperationContext, + TemporalStartOperationContext, WorkflowRunOperationContext, ) from ._operation_handlers import ( - TemporalNexusOperationHandler, + TemporalOperationHandler, WorkflowRunOperationHandler, ) from ._token import WorkflowHandle @@ -145,10 +145,10 @@ async def _start( return decorator(start) -TemporalNexusOperationStartHandlerFunc: TypeAlias = Callable[ +TemporalOperationStartHandlerFunc: TypeAlias = Callable[ [ NexusServiceType, - TemporalNexusStartOperationContext, + TemporalStartOperationContext, TemporalNexusClient, InputT, ], @@ -158,8 +158,8 @@ async def _start( @overload def temporal_operation( - start: TemporalNexusOperationStartHandlerFunc[NexusServiceType, InputT, OutputT], -) -> TemporalNexusOperationStartHandlerFunc[NexusServiceType, InputT, OutputT]: ... + start: TemporalOperationStartHandlerFunc[NexusServiceType, InputT, OutputT], +) -> TemporalOperationStartHandlerFunc[NexusServiceType, InputT, OutputT]: ... @overload @@ -167,21 +167,21 @@ def temporal_operation( *, name: str | None = None, ) -> Callable[ - [TemporalNexusOperationStartHandlerFunc[NexusServiceType, InputT, OutputT]], - TemporalNexusOperationStartHandlerFunc[NexusServiceType, InputT, OutputT], + [TemporalOperationStartHandlerFunc[NexusServiceType, InputT, OutputT]], + TemporalOperationStartHandlerFunc[NexusServiceType, InputT, OutputT], ]: ... def temporal_operation( start: None - | TemporalNexusOperationStartHandlerFunc[NexusServiceType, InputT, OutputT] = None, + | TemporalOperationStartHandlerFunc[NexusServiceType, InputT, OutputT] = None, *, name: str | None = None, ) -> ( - TemporalNexusOperationStartHandlerFunc[NexusServiceType, InputT, OutputT] + TemporalOperationStartHandlerFunc[NexusServiceType, InputT, OutputT] | Callable[ - [TemporalNexusOperationStartHandlerFunc[NexusServiceType, InputT, OutputT]], - TemporalNexusOperationStartHandlerFunc[NexusServiceType, InputT, OutputT], + [TemporalOperationStartHandlerFunc[NexusServiceType, InputT, OutputT]], + TemporalOperationStartHandlerFunc[NexusServiceType, InputT, OutputT], ] ): """Decorator marking a method as the start method for an operation that interacts with Temporal. @@ -191,10 +191,8 @@ def temporal_operation( """ def decorator( - start: TemporalNexusOperationStartHandlerFunc[ - NexusServiceType, InputT, OutputT - ], - ) -> TemporalNexusOperationStartHandlerFunc[NexusServiceType, InputT, OutputT]: + start: TemporalOperationStartHandlerFunc[NexusServiceType, InputT, OutputT], + ) -> TemporalOperationStartHandlerFunc[NexusServiceType, InputT, OutputT]: if not is_async_callable(start): raise RuntimeError( f"{start} is not an `async def` method. " @@ -209,7 +207,7 @@ def operation_handler_factory( self: NexusServiceType, ) -> OperationHandler[InputT, OutputT]: async def _start( - ctx: TemporalNexusStartOperationContext, + ctx: TemporalStartOperationContext, client: TemporalNexusClient, input: InputT, ) -> TemporalOperationResult[OutputT]: @@ -220,18 +218,18 @@ async def _start( input, ) - class _TemporalNexusOperationHandler(TemporalNexusOperationHandler): + class _TemporalOperationHandler(TemporalOperationHandler): @override async def start_operation( self, - ctx: TemporalNexusStartOperationContext, + ctx: TemporalStartOperationContext, client: TemporalNexusClient, input: InputT, ) -> TemporalOperationResult[OutputT]: return await _start(ctx, client, input) - _TemporalNexusOperationHandler.start_operation.__doc__ = start.__doc__ - return _TemporalNexusOperationHandler() + _TemporalOperationHandler.start_operation.__doc__ = start.__doc__ + return _TemporalOperationHandler() method_name = get_callable_name(start) op = nexusrpc.Operation( diff --git a/temporalio/nexus/_operation_context.py b/temporalio/nexus/_operation_context.py index e8ead61fe..01d209a9f 100644 --- a/temporalio/nexus/_operation_context.py +++ b/temporalio/nexus/_operation_context.py @@ -549,7 +549,7 @@ def set(self) -> None: _temporal_cancel_operation_context.set(self) -class TemporalNexusStartOperationContext(StartOperationContext): +class TemporalStartOperationContext(StartOperationContext): """Context received by a Temporal Nexus operation when it is started. .. warning:: @@ -563,7 +563,7 @@ def _from_start_operation_context(cls, ctx: StartOperationContext) -> Self: ) -class TemporalNexusCancelOperationContext(CancelOperationContext): +class TemporalCancelOperationContext(CancelOperationContext): """Context received by a Temporal Nexus operation when it is canceled. .. warning:: diff --git a/temporalio/nexus/_operation_handlers.py b/temporalio/nexus/_operation_handlers.py index c3e4b2e5e..e5c3bd762 100644 --- a/temporalio/nexus/_operation_handlers.py +++ b/temporalio/nexus/_operation_handlers.py @@ -21,8 +21,8 @@ import temporalio.nexus from temporalio.nexus._operation_context import ( - TemporalNexusCancelOperationContext, - TemporalNexusStartOperationContext, + TemporalCancelOperationContext, + TemporalStartOperationContext, _temporal_cancel_operation_context, ) from temporalio.nexus._temporal_client import ( @@ -127,8 +127,8 @@ async def _cancel_workflow( class CancelWorkflowRunOptions: """Options for cancelling the workflow backing a Nexus operation. - These options are built by :py:class:`TemporalNexusOperationHandler` and passed to - :py:meth:`TemporalNexusOperationHandler.cancel_workflow_run`. + These options are built by :py:class:`TemporalOperationHandler` and passed to + :py:meth:`TemporalOperationHandler.cancel_workflow_run`. .. warning:: This API is experimental and unstable. @@ -138,7 +138,7 @@ class CancelWorkflowRunOptions: """The ID of the workflow to cancel.""" -class TemporalNexusOperationHandler(OperationHandler[InputT, OutputT], ABC): +class TemporalOperationHandler(OperationHandler[InputT, OutputT], ABC): """Operation handler for Nexus operations that interact with Temporal. Implementations override the start_operation method. @@ -149,7 +149,7 @@ class TemporalNexusOperationHandler(OperationHandler[InputT, OutputT], ABC): @abstractmethod async def start_operation( self, - ctx: TemporalNexusStartOperationContext, + ctx: TemporalStartOperationContext, client: TemporalNexusClient, input: InputT, ) -> TemporalOperationResult[OutputT]: @@ -165,9 +165,7 @@ async def start( This API is experimental and unstable. """ nexus_client = _TemporalNexusClient() - start_ctx = TemporalNexusStartOperationContext._from_start_operation_context( - ctx - ) + start_ctx = TemporalStartOperationContext._from_start_operation_context(ctx) result = await self.start_operation(start_ctx, nexus_client, input) return result._to_nexus_result() @@ -185,9 +183,7 @@ async def cancel(self, ctx: CancelOperationContext, token: str) -> None: type=HandlerErrorType.INTERNAL, ) from err - cancel_ctx = TemporalNexusCancelOperationContext._from_cancel_operation_context( - ctx - ) + cancel_ctx = TemporalCancelOperationContext._from_cancel_operation_context(ctx) match operation_token.type: case OperationTokenType.WORKFLOW: options = CancelWorkflowRunOptions( @@ -197,7 +193,7 @@ async def cancel(self, ctx: CancelOperationContext, token: str) -> None: async def cancel_workflow_run( self, - ctx: TemporalNexusCancelOperationContext, # pyright: ignore[reportUnusedParameter] + ctx: TemporalCancelOperationContext, # pyright: ignore[reportUnusedParameter] options: CancelWorkflowRunOptions, ) -> None: """Cancels the workflow backing the Nexus operation. diff --git a/temporalio/nexus/_util.py b/temporalio/nexus/_util.py index 66d8c069c..f129dda2b 100644 --- a/temporalio/nexus/_util.py +++ b/temporalio/nexus/_util.py @@ -16,7 +16,7 @@ ) from temporalio.nexus._operation_context import ( - TemporalNexusStartOperationContext, + TemporalStartOperationContext, WorkflowRunOperationContext, ) from temporalio.nexus._temporal_client import ( @@ -55,7 +55,7 @@ def get_temporal_operation_start_method_input_and_output_type_annotations( start: Callable[ [ NexusServiceType, - TemporalNexusStartOperationContext, + TemporalStartOperationContext, TemporalNexusClient, InputT, ], @@ -73,7 +73,7 @@ def get_temporal_operation_start_method_input_and_output_type_annotations( return _get_wrapped_start_method_input_and_output_type_annotations( start, expected_param_types=( - TemporalNexusStartOperationContext, + TemporalStartOperationContext, TemporalNexusClient, ), expected_return_origin=TemporalOperationResult, diff --git a/temporalio/workflow/_nexus.py b/temporalio/workflow/_nexus.py index b8c8e88a1..29bd10715 100644 --- a/temporalio/workflow/_nexus.py +++ b/temporalio/workflow/_nexus.py @@ -218,7 +218,7 @@ async def start_operation( operation: Callable[ [ NexusServiceType, - temporalio.nexus.TemporalNexusStartOperationContext, + temporalio.nexus.TemporalStartOperationContext, temporalio.nexus.TemporalNexusClient, InputT, ], @@ -390,7 +390,7 @@ async def execute_operation( operation: Callable[ [ NexusServiceType, - temporalio.nexus.TemporalNexusStartOperationContext, + temporalio.nexus.TemporalStartOperationContext, temporalio.nexus.TemporalNexusClient, InputT, ], diff --git a/tests/nexus/test_handler_operation_definitions.py b/tests/nexus/test_handler_operation_definitions.py index 4a6e644b9..f47e3f47f 100644 --- a/tests/nexus/test_handler_operation_definitions.py +++ b/tests/nexus/test_handler_operation_definitions.py @@ -112,10 +112,10 @@ def test_unsafe_narrow_context_annotations_warn_and_drop_input_type(): with pytest.warns( UserWarning, - match="Expected parameter 1 .* TemporalNexusStartOperationContext", + match="Expected parameter 1 .* TemporalStartOperationContext", ): - class MyTemporalOpCtx(nexus.TemporalNexusStartOperationContext): + class MyTemporalOpCtx(nexus.TemporalStartOperationContext): def custom_method(self): raise NotImplementedError diff --git a/tests/nexus/test_nexus_type_errors.py b/tests/nexus/test_nexus_type_errors.py index ffdb60c65..1486f9791 100644 --- a/tests/nexus/test_nexus_type_errors.py +++ b/tests/nexus/test_nexus_type_errors.py @@ -13,7 +13,7 @@ import temporalio.nexus from temporalio import workflow from temporalio.client import Client, NexusOperationHandle -from temporalio.nexus import TemporalNexusOperationStartHandlerFunc +from temporalio.nexus import TemporalOperationStartHandlerFunc from temporalio.service import ServiceClient @@ -100,7 +100,7 @@ async def my_workflow_run_operation( @temporalio.nexus.temporal_operation async def my_temporal_operation( self, - _ctx: temporalio.nexus.TemporalNexusStartOperationContext, + _ctx: temporalio.nexus.TemporalStartOperationContext, client: temporalio.nexus.TemporalNexusClient, input: int, ) -> temporalio.nexus.TemporalOperationResult[None]: @@ -180,7 +180,7 @@ async def my_workflow_run_operation( @temporalio.nexus.temporal_operation async def my_temporal_operation( self, - _ctx: temporalio.nexus.TemporalNexusStartOperationContext, + _ctx: temporalio.nexus.TemporalStartOperationContext, _client: temporalio.nexus.TemporalNexusClient, _input: int, ) -> temporalio.nexus.TemporalOperationResult[None]: @@ -204,26 +204,26 @@ async def my_workflow_run_operation( @temporalio.nexus.temporal_operation async def my_temporal_operation( self, - _ctx: temporalio.nexus.TemporalNexusStartOperationContext, + _ctx: temporalio.nexus.TemporalStartOperationContext, _client: temporalio.nexus.TemporalNexusClient, _input: int, ) -> temporalio.nexus.TemporalOperationResult[None]: raise NotImplementedError -_handler: TemporalNexusOperationStartHandlerFunc[ +_handler: TemporalOperationStartHandlerFunc[ MyServiceHandler, int, None, ] = MyServiceHandler.my_temporal_operation -_BadHandler: TypeAlias = temporalio.nexus.TemporalNexusOperationStartHandlerFunc[ +_BadHandler: TypeAlias = temporalio.nexus.TemporalOperationStartHandlerFunc[ MyServiceHandler, str, None, ] -_bad_handler: TemporalNexusOperationStartHandlerFunc[ +_bad_handler: TemporalOperationStartHandlerFunc[ MyServiceHandler, str, None, @@ -235,7 +235,7 @@ class MyUnsafeContextAnnotationServiceHandler: # A temporal operation receives TemporalStartOperationContext at runtime, so # requiring an arbitrary user subclass is not safe. class MyCustomTemporalStartOperationContext( - temporalio.nexus.TemporalNexusStartOperationContext + temporalio.nexus.TemporalStartOperationContext ): def custom_state(self) -> str: raise NotImplementedError diff --git a/tests/nexus/test_temporal_operation.py b/tests/nexus/test_temporal_operation.py index 8bdfa267e..c101ede3b 100644 --- a/tests/nexus/test_temporal_operation.py +++ b/tests/nexus/test_temporal_operation.py @@ -75,7 +75,7 @@ def __init__(self) -> None: @nexus.temporal_operation async def echo( self, - _ctx: nexus.TemporalNexusStartOperationContext, + _ctx: nexus.TemporalStartOperationContext, client: nexus.TemporalNexusClient, input: Input, ) -> nexus.TemporalOperationResult[str]: @@ -86,7 +86,7 @@ async def echo( @nexus.temporal_operation async def blocking( self, - _ctx: nexus.TemporalNexusStartOperationContext, + _ctx: nexus.TemporalStartOperationContext, client: nexus.TemporalNexusClient, _input: None, ) -> nexus.TemporalOperationResult[None]: @@ -97,7 +97,7 @@ async def blocking( @nexus.temporal_operation async def double_start( self, - _ctx: nexus.TemporalNexusStartOperationContext, + _ctx: nexus.TemporalStartOperationContext, client: nexus.TemporalNexusClient, input: Input, ) -> nexus.TemporalOperationResult[None]: @@ -112,7 +112,7 @@ async def double_start( @nexus.temporal_operation async def concurrent_start( self, - _ctx: nexus.TemporalNexusStartOperationContext, + _ctx: nexus.TemporalStartOperationContext, client: nexus.TemporalNexusClient, input: Input, ) -> nexus.TemporalOperationResult[str]: @@ -157,7 +157,7 @@ async def concurrent_start( @nexus.temporal_operation async def retry_after_failed_start( self, - _ctx: nexus.TemporalNexusStartOperationContext, + _ctx: nexus.TemporalStartOperationContext, client: nexus.TemporalNexusClient, input: Input, ) -> nexus.TemporalOperationResult[str]: @@ -179,23 +179,21 @@ async def retry_after_failed_start( @nexus.temporal_operation async def sync_result( self, - _ctx: nexus.TemporalNexusStartOperationContext, + _ctx: nexus.TemporalStartOperationContext, _client: nexus.TemporalNexusClient, input: Input, ) -> nexus.TemporalOperationResult[str]: return nexus.TemporalOperationResult.sync(input.value) @operation_handler - def custom_cancel(self) -> nexus.TemporalNexusOperationHandler[str, None]: + def custom_cancel(self) -> nexus.TemporalOperationHandler[str, None]: event = self.started_custom_cancel_workflow - class CustomCancelNexusOpHandler( - nexus.TemporalNexusOperationHandler[str, None] - ): + class CustomCancelNexusOpHandler(nexus.TemporalOperationHandler[str, None]): @override async def start_operation( self, - ctx: nexus.TemporalNexusStartOperationContext, + ctx: nexus.TemporalStartOperationContext, client: nexus.TemporalNexusClient, input: str, ) -> nexus.TemporalOperationResult[None]: @@ -206,7 +204,7 @@ async def start_operation( @override async def cancel_workflow_run( self, - ctx: nexus.TemporalNexusCancelOperationContext, + ctx: nexus.TemporalCancelOperationContext, options: nexus.CancelWorkflowRunOptions, ): # get a handle to the workflow @@ -551,7 +549,7 @@ class TemporalOperationOverloadTestServiceHandler: @nexus.temporal_operation async def no_param( self, - _ctx: nexus.TemporalNexusStartOperationContext, + _ctx: nexus.TemporalStartOperationContext, client: nexus.TemporalNexusClient, _input: TemporalOperationOverloadTestValue, ) -> nexus.TemporalOperationResult[TemporalOperationOverloadTestValue]: @@ -563,7 +561,7 @@ async def no_param( @nexus.temporal_operation async def single_param( self, - _ctx: nexus.TemporalNexusStartOperationContext, + _ctx: nexus.TemporalStartOperationContext, client: nexus.TemporalNexusClient, input: TemporalOperationOverloadTestValue, ) -> nexus.TemporalOperationResult[TemporalOperationOverloadTestValue]: @@ -576,7 +574,7 @@ async def single_param( @nexus.temporal_operation async def multi_param( self, - _ctx: nexus.TemporalNexusStartOperationContext, + _ctx: nexus.TemporalStartOperationContext, client: nexus.TemporalNexusClient, input: TemporalOperationOverloadTestValue, ) -> nexus.TemporalOperationResult[TemporalOperationOverloadTestValue]: @@ -589,7 +587,7 @@ async def multi_param( @nexus.temporal_operation async def by_name( self, - _ctx: nexus.TemporalNexusStartOperationContext, + _ctx: nexus.TemporalStartOperationContext, client: nexus.TemporalNexusClient, input: TemporalOperationOverloadTestValue, ) -> nexus.TemporalOperationResult[TemporalOperationOverloadTestValue]: @@ -603,7 +601,7 @@ async def by_name( @nexus.temporal_operation async def by_name_multi_param( self, - _ctx: nexus.TemporalNexusStartOperationContext, + _ctx: nexus.TemporalStartOperationContext, client: nexus.TemporalNexusClient, input: TemporalOperationOverloadTestValue, ) -> nexus.TemporalOperationResult[TemporalOperationOverloadTestValue]: From 9a95feff4eb5f71e58cd855b7201f80931e341df Mon Sep 17 00:00:00 2001 From: Alex Mazzeo Date: Tue, 2 Jun 2026 10:17:28 -0700 Subject: [PATCH 115/226] Add debugpy bundle import passthrough when debug mode is enabled. debugpy is used by the Microsoft authored VSCode python debugger (#1249) --- temporalio/worker/_workflow.py | 24 +++++++++++--- tests/worker/test_worker.py | 57 ++++++++++++++++++++++++++++++++++ 2 files changed, 76 insertions(+), 5 deletions(-) diff --git a/temporalio/worker/_workflow.py b/temporalio/worker/_workflow.py index bb489329a..9e2ac9c7b 100644 --- a/temporalio/worker/_workflow.py +++ b/temporalio/worker/_workflow.py @@ -29,6 +29,7 @@ from temporalio.api.enums.v1 import WorkflowTaskFailedCause from temporalio.bridge.worker import PollShutdownError from temporalio.converter import StorageDriverStoreContext, StorageDriverWorkflowInfo +from temporalio.worker.workflow_sandbox._runner import SandboxedWorkflowRunner from . import _command_aware_visitor from ._interceptor import ( @@ -85,6 +86,9 @@ def __init__( encode_headers: bool, max_workflow_task_external_storage_concurrency: int, ) -> None: + # Debug mode is enabled if specified or if the TEMPORAL_DEBUG env var is truthy + debug_mode = debug_mode or bool(os.environ.get("TEMPORAL_DEBUG")) + self._bridge_worker = bridge_worker self._namespace = namespace self._task_queue = task_queue @@ -96,7 +100,19 @@ def __init__( ) ) self._workflow_task_executor_user_provided = workflow_task_executor is not None + + # If debug mode is enabled, ensure that the debugpy (https://github.com/microsoft/debugpy) + # import is added as a passthrough + if debug_mode and isinstance(workflow_runner, SandboxedWorkflowRunner): + workflow_runner = dataclasses.replace( + workflow_runner, + restrictions=workflow_runner.restrictions.with_passthrough_modules( + "_pydevd_bundle" + ), + ) + self._workflow_runner = workflow_runner + self._unsandboxed_workflow_runner = unsandboxed_workflow_runner self._data_converter = data_converter # Build the interceptor classes and collect extern functions @@ -127,11 +143,9 @@ def __init__( ) self._throw_after_activation: Exception | None = None - # If there's a debug mode or a truthy TEMPORAL_DEBUG env var, disable - # deadlock detection, otherwise set to 2 seconds - self._deadlock_timeout_seconds = ( - None if debug_mode or os.environ.get("TEMPORAL_DEBUG") else 2 - ) + # If debug mode is enabled, disable deadlock detection + # otherwise set to 2 seconds + self._deadlock_timeout_seconds = None if debug_mode else 2 # Keep track of workflows that could not be evicted self._could_not_evict_count = 0 diff --git a/tests/worker/test_worker.py b/tests/worker/test_worker.py index bd9d9b898..dda754a5b 100644 --- a/tests/worker/test_worker.py +++ b/tests/worker/test_worker.py @@ -4,8 +4,10 @@ import concurrent.futures import multiprocessing import multiprocessing.context +import os import uuid from collections.abc import Awaitable, Callable, Sequence +from contextlib import contextmanager from datetime import timedelta from typing import Any from urllib.request import urlopen @@ -57,6 +59,7 @@ WorkerTuner, WorkflowSlotInfo, ) +from temporalio.worker.workflow_sandbox import SandboxedWorkflowRunner from temporalio.workflow import DynamicWorkflowConfig, VersioningIntent from tests.helpers import ( assert_eventually, @@ -1650,3 +1653,57 @@ def test_worker_config_matches_init_params(): f"Missing from config: {init_params - config_keys}. " f"Extra in config: {config_keys - init_params}." ) + + +async def test_worker_debug_mode(client: Client): + worker = Worker( + client, + workflows=[SimpleWorkflow], + task_queue=f"task-queue-{uuid.uuid4()}", + ) + assert worker._workflow_worker + assert worker._workflow_worker._deadlock_timeout_seconds == 2 + assert isinstance(worker._workflow_worker._workflow_runner, SandboxedWorkflowRunner) + assert ( + "_pydevd_bundle" + not in worker._workflow_worker._workflow_runner.restrictions.passthrough_modules + ) + + worker = Worker( + client, + workflows=[SimpleWorkflow], + task_queue=f"task-queue-{uuid.uuid4()}", + debug_mode=True, + ) + assert worker._workflow_worker + assert worker._workflow_worker._deadlock_timeout_seconds is None + assert isinstance(worker._workflow_worker._workflow_runner, SandboxedWorkflowRunner) + assert ( + "_pydevd_bundle" + in worker._workflow_worker._workflow_runner.restrictions.passthrough_modules + ) + + @contextmanager + def debug_envvar(): + os.environ["TEMPORAL_DEBUG"] = "true" + try: + yield + finally: + os.environ.pop("TEMPORAL_DEBUG") + + with debug_envvar(): + worker = Worker( + client, + workflows=[SimpleWorkflow], + task_queue=f"task-queue-{uuid.uuid4()}", + ) + assert worker._workflow_worker + assert worker._workflow_worker._deadlock_timeout_seconds is None + assert isinstance( + worker._workflow_worker._workflow_runner, + SandboxedWorkflowRunner, + ) + assert ( + "_pydevd_bundle" + in worker._workflow_worker._workflow_runner.restrictions.passthrough_modules + ) From c8a052c2ccab0190a21031637d809e97fcbb19e7 Mon Sep 17 00:00:00 2001 From: Brian Strauch Date: Tue, 2 Jun 2026 12:50:28 -0700 Subject: [PATCH 116/226] contrib/strands: add cache_tools toggle to TemporalMCPClient (#1571) * contrib/strands: add cache_tools toggle to TemporalMCPClient Replace worker-startup tool discovery with a per-server {server}-list-tools activity executed from inside the workflow. TemporalMCPClient.cache_tools (default True) lists tools once at the start of the workflow; cache_tools=False re-lists on every agent turn so a mid-workflow MCP server restart is picked up. Strands calls load_tools() once at agent construction on a separate run_async thread with no workflow runtime, so the activity is dispatched from a BeforeModelCallEvent hook (which runs on the workflow loop before the registry is read each turn) that reconciles added/removed/renamed tools. * contrib/strands: default cache_tools to False --- temporalio/contrib/strands/README.md | 12 +- temporalio/contrib/strands/_plugin.py | 20 ++- temporalio/contrib/strands/_temporal_agent.py | 47 ++++++ .../contrib/strands/_temporal_mcp_client.py | 158 +++++++++++------- tests/contrib/strands/test_mcp.py | 86 +++++++++- 5 files changed, 247 insertions(+), 76 deletions(-) diff --git a/temporalio/contrib/strands/README.md b/temporalio/contrib/strands/README.md index fc9c6d74f..126f4bd95 100644 --- a/temporalio/contrib/strands/README.md +++ b/temporalio/contrib/strands/README.md @@ -380,7 +380,7 @@ class ChatWorkflow: ## MCP -`StrandsPlugin(mcp_clients=...)` takes a mapping of `name → MCPClient factory`, mirroring the `models=` pattern. The plugin registers a per-server `{name}-call-tool` activity and connects at worker startup to enumerate tools. Workflow-side, `TemporalMCPClient(server="name")` is a pure handle: it references the server by name and carries the per-call activity options. +`StrandsPlugin(mcp_clients=...)` takes a mapping of `name → MCPClient factory`, mirroring the `models=` pattern. The plugin registers per-server `{name}-call-tool` and `{name}-list-tools` activities. Workflow-side, `TemporalMCPClient(server="name")` is a pure handle: it references the server by name, discovers tools by running `{name}-list-tools`, and carries the per-call activity options. ```python from mcp import StdioServerParameters, stdio_client @@ -412,9 +412,15 @@ Worker( ) ``` -Each factory returns a fully configured `MCPClient`, so you can pass options like `tool_filters`, `prefix`, `elicitation_callback`, or `tasks_config` to it. The plugin connects to each MCP server once at worker startup to enumerate tools. The schema is frozen for the worker's lifetime; restart workers to pick up MCP-server changes. If a server is unavailable at startup, the worker fails to start. +Each factory returns a fully configured `MCPClient`, so you can pass options like `tool_filters`, `prefix`, `elicitation_callback`, or `tasks_config` to it. -To amortize connection setup, the `{name}-call-tool` activity keeps a worker-process MCP connection open between calls and reuses it. The connection is disconnected after it sits idle for `mcp_connection_idle_timeout` (default 5 minutes); the timer resets on every reuse: +By default, `TemporalMCPClient` re-lists the server's tools (via `{name}-list-tools`) on every agent turn, so an MCP server that is restarted mid-workflow — with tools added, removed, or renamed — is picked up. To list the tools just once at the beginning of the workflow and reuse that schema for the workflow's lifetime (one fewer activity per turn), set `cache_tools=True`: + +```python +echo = TemporalMCPClient(server="echo", cache_tools=True, start_to_close_timeout=timedelta(seconds=30)) +``` + +To amortize connection setup, the `{name}-call-tool` and `{name}-list-tools` activities share a worker-process MCP connection that is opened lazily and reused across calls. The connection is disconnected after it sits idle for `mcp_connection_idle_timeout` (default 5 minutes); the timer resets on every reuse: ```python StrandsPlugin( diff --git a/temporalio/contrib/strands/_plugin.py b/temporalio/contrib/strands/_plugin.py index b6f7db2ff..0f1972666 100644 --- a/temporalio/contrib/strands/_plugin.py +++ b/temporalio/contrib/strands/_plugin.py @@ -17,8 +17,7 @@ from ._temporal_mcp_client import ( _evict_connection, build_call_tool_activity, - clear_cache, - populate_cache, + build_list_tools_activity, ) @@ -31,10 +30,11 @@ class StrandsPlugin(SimplePlugin): on first use, then cached for the worker's lifetime. Use the same name in ``TemporalAgent(model=...)`` inside the workflow. - When ``mcp_clients`` is supplied, registers a per-server - ``{server}-call-tool`` activity for each entry and, at worker startup, - connects to each MCP server to cache its tool list. Workflow-side - ``TemporalMCPClient(server="...").load_tools()`` reads from the cache. + When ``mcp_clients`` is supplied, registers per-server + ``{server}-call-tool`` and ``{server}-list-tools`` activities for each + entry. Workflow-side ``TemporalMCPClient(server="...")`` discovers tools by + running ``{server}-list-tools``; whether it lists once per workflow or once + per agent turn is controlled by its ``cache_tools`` option. ``mcp_connection_idle_timeout`` controls how long a worker-process MCP connection is kept open between ``call-tool`` activities before it is @@ -69,17 +69,19 @@ def __init__( server, client_factory, mcp_connection_idle_timeout ) ) + activities.append( + build_list_tools_activity( + server, client_factory, mcp_connection_idle_timeout + ) + ) @asynccontextmanager async def run_context() -> AsyncGenerator[None, None]: - for server, client_factory in mcp_clients.items(): - await populate_cache(server, client_factory) try: yield finally: for server in mcp_clients: await _evict_connection(server) - clear_cache(server) super().__init__( "aws.StrandsPlugin", diff --git a/temporalio/contrib/strands/_temporal_agent.py b/temporalio/contrib/strands/_temporal_agent.py index 9bc1beb31..c2f9f14c7 100644 --- a/temporalio/contrib/strands/_temporal_agent.py +++ b/temporalio/contrib/strands/_temporal_agent.py @@ -2,10 +2,12 @@ from typing import Any from strands import Agent +from strands.hooks import BeforeModelCallEvent, HookCallback from temporalio.common import Priority, RetryPolicy from temporalio.workflow import ActivityCancellationType, VersioningIntent +from ._temporal_mcp_client import TemporalMCPClient from ._temporal_model import TemporalModel _SNAPSHOT_DISABLED = ( @@ -76,6 +78,51 @@ def __init__( ) super().__init__(model=temporal_model, **agent_kwargs) + # Strands invokes ToolProvider.load_tools() once at construction on a + # separate run_async thread that has no workflow runtime, so a + # TemporalMCPClient cannot list its tools there. Instead refresh from a + # BeforeModelCallEvent hook, which runs on the workflow loop just before + # the registry is read each turn. cache_tools=True lists once (guarded + # by _fetched); cache_tools=False re-lists every turn. + for provider in self.tool_registry._tool_providers: + if isinstance(provider, TemporalMCPClient): + self.hooks.add_callback( + BeforeModelCallEvent, self._make_mcp_refresh_hook(provider) + ) + + def _make_mcp_refresh_hook( + self, provider: TemporalMCPClient + ) -> HookCallback[BeforeModelCallEvent]: + async def hook(event: BeforeModelCallEvent) -> None: + if provider._cache_tools and provider._fetched: + return + old_names = {tool.tool_name for tool in provider._tools} + await provider._refresh() + self._reconcile_mcp_tools(event, provider, old_names) + + return hook + + def _reconcile_mcp_tools( + self, + event: BeforeModelCallEvent, + provider: TemporalMCPClient, + old_names: set[str], + ) -> None: + reg = event.agent.tool_registry + new = {tool.tool_name: tool for tool in provider._tools} + # Tools the server dropped or renamed since the last listing. There is + # no public unregister, so remove them from the registry directly. + for name in old_names - set(new): + reg.registry.pop(name, None) + reg.dynamic_tools.pop(name, None) + # replace() swaps an existing tool in place (no hot-reload guard); + # register_tool() adds a newly-discovered one. + for name, tool in new.items(): + if name in reg.registry: + reg.replace(tool) + else: + reg.register_tool(tool) + def take_snapshot(self, *_args: Any, **_kwargs: Any) -> Any: """Disabled; Temporal's event history is the source of truth.""" raise NotImplementedError(_SNAPSHOT_DISABLED) diff --git a/temporalio/contrib/strands/_temporal_mcp_client.py b/temporalio/contrib/strands/_temporal_mcp_client.py index 71e1f2f7c..bb096956e 100644 --- a/temporalio/contrib/strands/_temporal_mcp_client.py +++ b/temporalio/contrib/strands/_temporal_mcp_client.py @@ -13,7 +13,7 @@ from strands.tools.mcp.mcp_types import MCPToolResult from strands.types.tools import AgentTool -from temporalio import activity +from temporalio import activity, workflow from temporalio.common import Priority, RetryPolicy from temporalio.workflow import ActivityCancellationType, VersioningIntent @@ -33,20 +33,21 @@ class _CallToolArgs: tool_use_id: str = "" -# Server name -> cached tool list. Populated by ``_populate_cache`` at worker -# startup and read by ``TemporalMCPClient.load_tools()`` inside the workflow -# sandbox. ``temporalio`` is in the SDK's default sandbox passthrough, so this -# dict is shared between worker process and workflow execution. -_TOOL_CACHE: dict[str, list[_MCPToolInfo]] = {} - - class TemporalMCPClient(ToolProvider): """Workflow-side handle to an MCP server registered on the worker. - The transport factory and tool discovery live worker-side via - ``StrandsPlugin(mcp_clients={"server": lambda: ...})``. This handle only - carries the server name (which selects the registered factory) and the - per-call activity options. + The transport factory lives worker-side via + ``StrandsPlugin(mcp_clients={"server": lambda: ...})``. This handle carries + the server name (which selects the registered factory) and the per-call + activity options. Tool discovery runs as the ``{server}-list-tools`` + activity, dispatched from inside the workflow by ``TemporalAgent`` before + each model call. + + ``cache_tools`` controls how often that listing happens. When ``False`` + (the default) the tools are re-listed on every agent turn, so an MCP server + restarted mid-workflow (with tools added, removed, or renamed) is picked up. + When ``True`` the tools are listed once at the beginning of the workflow and + reused for its lifetime. Construct once at module level and pass to ``TemporalAgent(tools=[...])`` inside the workflow. Multiple handles may reference the same server name @@ -57,6 +58,7 @@ def __init__( self, server: str, *, + cache_tools: bool = False, task_queue: str | None = None, schedule_to_close_timeout: timedelta | None = None, schedule_to_start_timeout: timedelta | None = None, @@ -70,6 +72,9 @@ def __init__( ) -> None: """Configure the server name and activity options.""" self._server = server + self._cache_tools = cache_tools + self._tools: list[AgentTool] = [] + self._fetched = False self._options: dict[str, Any] = { "task_queue": task_queue, "schedule_to_close_timeout": schedule_to_close_timeout, @@ -89,11 +94,33 @@ def server(self) -> str: return self._server async def load_tools(self, **_kwargs: Any) -> Sequence[AgentTool]: - """Return TemporalMCPTool wrappers for tools cached at worker startup.""" + """Return the tools fetched by the most recent ``_refresh``. + + This must stay free of any ``workflow`` API: Strands invokes it once at + ``Agent`` construction on a separate ``run_async`` thread that has no + workflow runtime. ``TemporalAgent`` populates the tools by calling + ``_refresh`` from a ``BeforeModelCallEvent`` hook before the registry is + first read. + """ + return list(self._tools) + + async def _refresh(self) -> None: + """List the server's tools via the ``{server}-list-tools`` activity. + + Runs on the workflow event loop (dispatched from ``TemporalAgent``'s + hook), so the activity result is recorded in history and replay-safe. + """ from ._temporal_mcp_tool import TemporalMCPTool - infos = _TOOL_CACHE.get(self._server, []) - return [TemporalMCPTool(self._server, info, self._options) for info in infos] + infos: list[_MCPToolInfo] = await workflow.execute_activity( + f"{self._server}-list-tools", + result_type=list[_MCPToolInfo], + **self._options, + ) + self._tools = [ + TemporalMCPTool(self._server, info, self._options) for info in infos + ] + self._fetched = True def add_consumer(self, consumer_id: Any, **_kwargs: Any) -> None: """No-op; consumer tracking is handled by the underlying MCP client.""" @@ -104,45 +131,37 @@ def remove_consumer(self, consumer_id: Any, **_kwargs: Any) -> None: return None -# Use MCP sessions directly instead of MCPClient's background-thread helpers. -# Those helpers route calls through cross-loop futures that are unreliable on -# Python 3.10 when invoked from Temporal's async worker/activity event loops. -async def _list_mcp_tools(client: MCPClient) -> Sequence[Tool]: - async with client._transport_callable() as (read_stream, write_stream, *_): - async with ClientSession( - read_stream, - write_stream, - elicitation_callback=client._elicitation_callback, - ) as session: - await session.initialize() - tools: list[Tool] = [] - pagination_token = None - while True: - page = await session.list_tools( - params=PaginatedRequestParams(cursor=pagination_token) - if pagination_token is not None - else None - ) - tools.extend(page.tools) - pagination_token = page.nextCursor - if pagination_token is None: - return tools - - -def _agent_tool_for_filtering(client: MCPClient, tool: Tool) -> MCPAgentTool: - if client._prefix: - return MCPAgentTool(tool, client, name_override=f"{client._prefix}_{tool.name}") - return MCPAgentTool(tool, client) - - -async def populate_cache(server: str, client_factory: Callable[[], MCPClient]) -> None: - """Connect to the MCP server, list tools, fill ``_TOOL_CACHE``.""" - client = client_factory() +# Use the MCP session directly instead of MCPClient's background-thread +# helpers. Those helpers route calls through cross-loop futures that are +# unreliable on Python 3.10 when invoked from Temporal's async worker/activity +# event loops. +async def _paginate_list_tools(session: ClientSession) -> list[Tool]: + tools: list[Tool] = [] + pagination_token = None + while True: + page = await session.list_tools( + params=PaginatedRequestParams(cursor=pagination_token) + if pagination_token is not None + else None + ) + tools.extend(page.tools) + pagination_token = page.nextCursor + if pagination_token is None: + return tools + + +def _tool_infos(client: MCPClient, tools: Sequence[Tool]) -> list[_MCPToolInfo]: + """Apply the client's tool filters and project to serializable records.""" infos: list[_MCPToolInfo] = [] - for tool in await _list_mcp_tools(client): + for tool in tools: + if client._prefix: + agent_tool = MCPAgentTool( + tool, client, name_override=f"{client._prefix}_{tool.name}" + ) + else: + agent_tool = MCPAgentTool(tool, client) if not client._should_include_tool_with_filters( - _agent_tool_for_filtering(client, tool), - client._tool_filters, + agent_tool, client._tool_filters ): continue infos.append( @@ -153,12 +172,7 @@ async def populate_cache(server: str, client_factory: Callable[[], MCPClient]) - output_schema=tool.outputSchema, ) ) - _TOOL_CACHE[server] = infos - - -def clear_cache(server: str) -> None: - """Drop the cached tool list for ``server``.""" - _TOOL_CACHE.pop(server, None) + return infos # Default for how long an idle MCP connection stays open before it is @@ -324,3 +338,31 @@ async def call_tool(args: _CallToolArgs) -> MCPToolResult: record.release() return call_tool + + +def build_list_tools_activity( + server: str, + client_factory: Callable[[], MCPClient], + idle_timeout: timedelta | None = None, +) -> Callable: + """Return the per-server ``{server}-list-tools`` activity for registration. + + Lists the server's tools (applying the client's tool filters) and reuses + the same lazily-opened, idle-evicted worker-process MCP session as + ``{server}-call-tool``. + """ + idle = idle_timeout if idle_timeout is not None else _MCP_CONNECTION_IDLE + + @activity.defn(name=f"{server}-list-tools") + async def list_tools() -> list[_MCPToolInfo]: + client, session, record = await get_connection(server, client_factory, idle) + try: + return _tool_infos(client, await _paginate_list_tools(session)) + except Exception: + # The session may be broken; drop it so the next call reconnects. + await _evict_connection(server) + raise + finally: + record.release() + + return list_tools diff --git a/tests/contrib/strands/test_mcp.py b/tests/contrib/strands/test_mcp.py index bde857022..0f989cd83 100644 --- a/tests/contrib/strands/test_mcp.py +++ b/tests/contrib/strands/test_mcp.py @@ -36,6 +36,7 @@ class MCPWorkflow: def __init__(self) -> None: echo = TemporalMCPClient( server="echo", + cache_tools=True, start_to_close_timeout=timedelta(seconds=30), ) self.agent = TemporalAgent( @@ -90,6 +91,7 @@ async def test_mcp(client: Client): history = await handle.fetch_history() assert get_activities(history) == [ + "echo-list-tools", "invoke_model", "echo-call-tool", "invoke_model", @@ -106,6 +108,7 @@ class MCPReuseWorkflow: def __init__(self) -> None: echo = TemporalMCPClient( server="echo_cached", + cache_tools=True, start_to_close_timeout=timedelta(seconds=30), ) self.agent = TemporalAgent( @@ -123,9 +126,9 @@ async def run(self, prompt: str) -> str: async def test_mcp_reuses_connection(client: Client): """Successive MCP tool calls reuse one cached worker-side connection.""" task_queue = "test_mcp_reuses_connection" - # Count how often the worker opens a connection. With caching this is one - # startup-discovery connection plus one cached call connection serving both - # tool calls (2); reconnecting per call would make it 3. + # Count how often the worker opens a connection. One lazily-opened + # connection serves the list-tools discovery and both tool calls (1); + # reconnecting per call would make it more. factory_calls = [0] def counting_factory() -> MCPClient: @@ -163,10 +166,11 @@ def counting_factory() -> MCPClient: # The worker context has exited, so its run_context finally evicted the # cached connection. assert "echo_cached" not in _temporal_mcp_client._CONNECTIONS - assert factory_calls[0] == 2 + assert factory_calls[0] == 1 history = await handle.fetch_history() assert get_activities(history) == [ + "echo_cached-list-tools", "invoke_model", "echo_cached-call-tool", "invoke_model", @@ -185,6 +189,7 @@ class MCPIdleWorkflow: def __init__(self) -> None: echo = TemporalMCPClient( server="echo_idle", + cache_tools=True, start_to_close_timeout=timedelta(seconds=30), ) self.agent = TemporalAgent( @@ -239,8 +244,11 @@ def counting_factory() -> MCPClient: ) assert await handle.result() == "Done!\n" - # The call opened a second connection (startup discovery was the first). - assert factory_calls[0] == 2 + # A connection was opened lazily (on the first list-tools/call-tool). + # How many times depends on whether the short idle timer fires between + # activities, so this only asserts that at least one was opened; the + # eviction-while-alive behavior is what the polling loop below checks. + assert factory_calls[0] >= 1 # Still inside the worker context: the short idle timer evicts the # cached call connection on its own. Asserting eviction here -- with the @@ -250,3 +258,69 @@ def counting_factory() -> MCPClient: break await asyncio.sleep(0.1) assert "echo_idle" not in _temporal_mcp_client._CONNECTIONS + + +@workflow.defn +class MCPNoCacheWorkflow: + def __init__(self) -> None: + echo = TemporalMCPClient( + server="echo_nocache", + cache_tools=False, + start_to_close_timeout=timedelta(seconds=30), + ) + self.agent = TemporalAgent( + model="mock", + start_to_close_timeout=timedelta(seconds=30), + tools=[echo], + ) + + @workflow.run + async def run(self, prompt: str) -> str: + result = await self.agent.invoke_async(prompt) + return str(result) + + +async def test_mcp_lists_tools_each_turn_when_uncached(client: Client): + """With cache_tools=False the tool list is re-fetched on every model call.""" + task_queue = "test_mcp_lists_tools_each_turn_when_uncached" + plugin = StrandsPlugin( + models={ + "mock": lambda: MockModel( + [ + {"name": "echo", "input": {"message": "one"}}, + {"name": "echo", "input": {"message": "two"}}, + "Done!", + ] + ) + }, + mcp_clients={"echo_nocache": _echo_client_factory}, + ) + + async with Worker( + client, + task_queue=task_queue, + workflows=[MCPNoCacheWorkflow], + plugins=[plugin], + max_cached_workflows=0, + ): + handle = await client.start_workflow( + MCPNoCacheWorkflow.run, + "echo twice", + id=f"test_mcp_lists_tools_each_turn_when_uncached_{uuid4()}", + task_queue=task_queue, + ) + assert await handle.result() == "Done!\n" + + history = await handle.fetch_history() + activities = get_activities(history) + # One list-tools per model call -- the tools are re-listed every turn rather + # than once for the workflow. + assert activities.count("echo_nocache-list-tools") == activities.count( + "invoke_model" + ) + assert activities.count("echo_nocache-list-tools") == 3 + + await Replayer( + workflows=[MCPNoCacheWorkflow], + plugins=[plugin], + ).replay_workflow(history) From b133ed9dacb5b8fee5c57df1f4c40736a488832f Mon Sep 17 00:00:00 2001 From: Spencer Judge Date: Wed, 3 Jun 2026 09:39:25 -0700 Subject: [PATCH 117/226] Add workflow cancellation reason (#1574) * Add workflow cancellation reason * Add cancel reasons on caller side * Add test proving reason isn't none * Lint fix --- temporalio/client/_impl.py | 1 + temporalio/client/_interceptor.py | 1 + temporalio/client/_workflow.py | 4 + temporalio/worker/_workflow_instance.py | 45 +++++--- temporalio/workflow/__init__.py | 2 + temporalio/workflow/_context.py | 25 +++++ temporalio/workflow/_workflow_ops.py | 6 +- tests/worker/test_workflow.py | 142 ++++++++++++++++++++++++ 8 files changed, 207 insertions(+), 19 deletions(-) diff --git a/temporalio/client/_impl.py b/temporalio/client/_impl.py index af221865a..0f3667b19 100644 --- a/temporalio/client/_impl.py +++ b/temporalio/client/_impl.py @@ -352,6 +352,7 @@ async def cancel_workflow(self, input: CancelWorkflowInput) -> None: identity=self._client.identity, request_id=str(uuid.uuid4()), first_execution_run_id=input.first_execution_run_id or "", + reason=input.reason, ), retry=True, metadata=input.rpc_metadata, diff --git a/temporalio/client/_interceptor.py b/temporalio/client/_interceptor.py index 587b802d0..0e780146d 100644 --- a/temporalio/client/_interceptor.py +++ b/temporalio/client/_interceptor.py @@ -111,6 +111,7 @@ class CancelWorkflowInput: id: str run_id: str | None first_execution_run_id: str | None + reason: str rpc_metadata: Mapping[str, str | bytes] rpc_timeout: timedelta | None diff --git a/temporalio/client/_workflow.py b/temporalio/client/_workflow.py index 22ac00d84..e82006580 100644 --- a/temporalio/client/_workflow.py +++ b/temporalio/client/_workflow.py @@ -318,6 +318,7 @@ async def result( async def cancel( self, *, + reason: str = "", rpc_metadata: Mapping[str, str | bytes] = {}, rpc_timeout: timedelta | None = None, ) -> None: @@ -334,6 +335,8 @@ async def cancel( workflow ID even if it is unrelated to the started workflow. Args: + reason: Reason recorded with the cancellation request. Available + inside the workflow via :py:func:`temporalio.workflow.cancellation_reason`. rpc_metadata: Headers used on the RPC call. Keys here override client-level RPC metadata keys. rpc_timeout: Optional RPC deadline to set for the RPC call. @@ -346,6 +349,7 @@ async def cancel( id=self._id, run_id=self._run_id, first_execution_run_id=self._first_execution_run_id, + reason=reason, rpc_metadata=rpc_metadata, rpc_timeout=rpc_timeout, ) diff --git a/temporalio/worker/_workflow_instance.py b/temporalio/worker/_workflow_instance.py index 16c3483d8..76ccdb2e3 100644 --- a/temporalio/worker/_workflow_instance.py +++ b/temporalio/worker/_workflow_instance.py @@ -265,7 +265,7 @@ def __init__(self, det: WorkflowInstanceDetails) -> None: ) self._primary_task: asyncio.Task[None] | None = None self._time_ns = 0 - self._cancel_requested = False + self._cancel_reason: str | None = None self._deployment_version_for_current_task: None | ( temporalio.bridge.proto.common.WorkerDeploymentVersion ) = None @@ -595,10 +595,9 @@ def _apply( raise RuntimeError(f"Unrecognized job: {job.WhichOneof('variant')}") def _apply_cancel_workflow( - self, _job: temporalio.bridge.proto.workflow_activation.CancelWorkflow + self, job: temporalio.bridge.proto.workflow_activation.CancelWorkflow ) -> None: - self._cancel_requested = True - # TODO(cretz): Details or cancel message or whatever? + self._cancel_reason = job.reason if self._primary_task: # The primary task may not have started yet and we want to give the # workflow the ability to receive the cancellation, so we must defer @@ -799,7 +798,6 @@ def _apply_remove_from_cache( self, _job: temporalio.bridge.proto.workflow_activation.RemoveFromCache ) -> None: self._deleting = True - self._cancel_requested = True # We consider eviction to be under replay so that certain code like # logging that avoids replaying doesn't run during eviction either self._is_replaying = True @@ -1189,6 +1187,9 @@ def workflow_continue_as_new( ) ) + def workflow_cancellation_reason(self) -> str | None: + return self._cancel_reason + def workflow_extern_functions(self) -> Mapping[str, Callable]: return self._extern_functions @@ -1987,10 +1988,12 @@ async def _outbound_start_child_workflow( handle: _ChildWorkflowHandle # Common code for handling cancel for start and run - def apply_child_cancel_error() -> None: - # Send a cancel request to the child + def apply_child_cancel_error(err: asyncio.CancelledError) -> None: + # Send a cancel request to the child, forwarding the msg passed to + # Task.cancel(msg) (if any) as the cancellation reason. + reason = err.args[0] if err.args and isinstance(err.args[0], str) else "" cancel_command = self._add_command() - handle._apply_cancel_command(cancel_command) + handle._apply_cancel_command(cancel_command, reason=reason) # If the cancel command is for external workflow, we # have to add a seq and mark it pending if cancel_command.HasField("request_cancel_external_workflow_execution"): @@ -2013,8 +2016,8 @@ async def run_child() -> Any: # We have to shield because we don't want the future itself # to be cancelled return await asyncio.shield(handle._result_fut) - except asyncio.CancelledError: - apply_child_cancel_error() + except asyncio.CancelledError as err: + apply_child_cancel_error(err) # Clear the cancellation counter on Python 3.11+ so the # next await does not immediately re-raise CancelledError if ( @@ -2037,8 +2040,8 @@ async def run_child() -> Any: # to be cancelled await asyncio.shield(handle._start_fut) return handle - except asyncio.CancelledError: - apply_child_cancel_error() + except asyncio.CancelledError as err: + apply_child_cancel_error(err) # Clear the cancellation counter on Python 3.11+ so the # next await does not immediately re-raise CancelledError if ( @@ -2046,7 +2049,7 @@ async def run_child() -> Any: and (t := asyncio.current_task()) is not None ): t.uncancel() # type: ignore[union-attr] - if self._cancel_requested: + if self._cancel_reason is not None or self._deleting: raise async def _outbound_start_nexus_operation( @@ -2102,7 +2105,7 @@ async def operation_handle_fn() -> OutputT: and (t := asyncio.current_task()) is not None ): t.uncancel() # type: ignore[union-attr] - if self._cancel_requested: + if self._cancel_reason is not None or self._deleting: raise #### Miscellaneous helpers #### @@ -2588,8 +2591,9 @@ async def _run_top_level_workflow_function(self, coro: Awaitable[None]) -> None: # cancel later on will show the workflow as cancelled. But this is # a Temporal limitation in that cancellation is a state not an # event. - if self._cancel_requested and temporalio.exceptions.is_cancelled_exception( - err + if ( + self._cancel_reason is not None + and temporalio.exceptions.is_cancelled_exception(err) ): self._add_command().cancel_workflow_execution.SetInParent() elif self.workflow_is_failure_exception(err): @@ -3381,8 +3385,12 @@ def _apply_start_command(self) -> None: def _apply_cancel_command( self, command: temporalio.bridge.proto.workflow_commands.WorkflowCommand, + *, + reason: str = "", ) -> None: - command.cancel_child_workflow_execution.child_workflow_seq = self._seq + v = command.cancel_child_workflow_execution + v.child_workflow_seq = self._seq + v.reason = reason class _ExternalWorkflowHandle(temporalio.workflow.ExternalWorkflowHandle[Any]): @@ -3426,7 +3434,7 @@ async def signal( ) ) - async def cancel(self) -> None: + async def cancel(self, *, reason: str = "") -> None: self._instance._assert_not_read_only("cancel external handle") command = self._instance._add_command() v = command.request_cancel_external_workflow_execution @@ -3434,6 +3442,7 @@ async def cancel(self) -> None: v.workflow_execution.workflow_id = self._id if self._run_id: v.workflow_execution.run_id = self._run_id + v.reason = reason await self._instance._cancel_external_workflow(command) diff --git a/temporalio/workflow/__init__.py b/temporalio/workflow/__init__.py index ec74299c2..8b8b0fb6f 100644 --- a/temporalio/workflow/__init__.py +++ b/temporalio/workflow/__init__.py @@ -59,6 +59,7 @@ _current_update_info, _Runtime, _set_current_update_info, + cancellation_reason, current_update_info, deprecate_patch, extern_functions, @@ -196,6 +197,7 @@ "get_last_completion_result", "get_last_failure", "has_last_completion_result", + "cancellation_reason", "in_workflow", "info", "instance", diff --git a/temporalio/workflow/_context.py b/temporalio/workflow/_context.py index 5c3f22cc9..297a8bf30 100644 --- a/temporalio/workflow/_context.py +++ b/temporalio/workflow/_context.py @@ -36,6 +36,7 @@ "ParentInfo", "RootInfo", "UpdateInfo", + "cancellation_reason", "current_update_info", "deprecate_patch", "extern_functions", @@ -295,6 +296,9 @@ def workflow_continue_as_new( initial_versioning_behavior: ContinueAsNewVersioningBehavior | None, ) -> NoReturn: ... + @abstractmethod + def workflow_cancellation_reason(self) -> str | None: ... + @abstractmethod def workflow_extern_functions(self) -> Mapping[str, Callable]: ... @@ -591,6 +595,27 @@ def in_workflow() -> bool: return _Runtime.maybe_current() is not None +def cancellation_reason() -> str | None: + """Reason the workflow was cancelled, or None if no external cancellation + request has been received. + + A non-None value (including an empty string) indicates that the workflow + received an explicit cancellation request from the server. This can be used + when catching an :py:class:`asyncio.CancelledError` to distinguish a + workflow-level cancel from a cancel that originated from inner asyncio task + cancellation. + + Note, this only reflects cancellation requested via the server; it is not + set for cache eviction or for cancels of inner tasks/scopes. + + Returns: + The reason string sent with the workflow cancellation request (which + may be empty), or ``None`` if the workflow has not been cancelled via + an external request. + """ + return _Runtime.current().workflow_cancellation_reason() + + def memo() -> Mapping[str, Any]: """Current workflow's memo values, converted without type hints. diff --git a/temporalio/workflow/_workflow_ops.py b/temporalio/workflow/_workflow_ops.py index 0cd22cb17..b877be585 100644 --- a/temporalio/workflow/_workflow_ops.py +++ b/temporalio/workflow/_workflow_ops.py @@ -604,11 +604,15 @@ async def signal( """ raise NotImplementedError - async def cancel(self) -> None: + async def cancel(self, *, reason: str = "") -> None: # pyright: ignore[reportUnusedParameter] """Send a cancellation request to this external workflow. This will fail if the workflow cannot accept the request (e.g. if the workflow is not found). + + Args: + reason: Reason recorded with the cancellation request. Available in + the target workflow via :py:func:`cancellation_reason`. """ raise NotImplementedError diff --git a/tests/worker/test_workflow.py b/tests/worker/test_workflow.py index cb5bb8067..4cd070cc8 100644 --- a/tests/worker/test_workflow.py +++ b/tests/worker/test_workflow.py @@ -1093,6 +1093,148 @@ async def started() -> bool: assert (await handle.describe()).status == WorkflowExecutionStatus.CANCELED +@workflow.defn +class CancelReasonWorkflow: + def __init__(self) -> None: + self._started = False + # Reason observed when the inner task was cancelled (no external + # workflow cancel has happened yet at that point). + self._reason_inner: str | None = "unset" + # Reason observed in the outer CancelledError handler after the + # external workflow cancel has been delivered. + self._reason_outer: str | None = "unset" + + @workflow.run + async def run(self) -> NoReturn: + self._started = True + task = asyncio.create_task(asyncio.sleep(1000)) + try: + task.cancel() + await task + except asyncio.CancelledError: + self._reason_inner = workflow.cancellation_reason() + try: + await asyncio.sleep(1000) + except asyncio.CancelledError: + self._reason_outer = workflow.cancellation_reason() + raise + raise RuntimeError("unreachable") + + @workflow.query + def started(self) -> bool: + return self._started + + @workflow.query + def reason_inner(self) -> str | None: + return self._reason_inner + + @workflow.query + def reason_outer(self) -> str | None: + return self._reason_outer + + +@pytest.mark.parametrize("reason", ["user-supplied reason", ""]) +async def test_workflow_cancellation_reason(client: Client, reason: str): + async with new_worker(client, CancelReasonWorkflow) as worker: + handle = await client.start_workflow( + CancelReasonWorkflow.run, + id=f"workflow-{uuid.uuid4()}", + task_queue=worker.task_queue, + ) + + async def started() -> bool: + return await handle.query(CancelReasonWorkflow.started) + + await assert_eq_eventually(True, started) + # Before any external cancel, reason is None even though an inner task + # cancel has already been observed. + assert await handle.query(CancelReasonWorkflow.reason_inner) is None + + # When reason is "", cancel without providing the kwarg at all to + # exercise the default path. + if reason: + await handle.cancel(reason=reason) + else: + await handle.cancel() + with pytest.raises(WorkflowFailureError) as err: + await handle.result() + assert isinstance(err.value.cause, CancelledError) + + outer = await handle.query(CancelReasonWorkflow.reason_outer) + # Load-bearing: a cancel with no reason still produces an empty string, + # not None — None means "no external cancel happened". + assert outer is not None + assert outer == reason + + +@workflow.defn +class CancelReasonReporter: + """Workflow that swallows a cancel and returns the observed reason.""" + + @workflow.run + async def run(self) -> str: + try: + await asyncio.sleep(1000) + except asyncio.CancelledError: + return workflow.cancellation_reason() or "" + raise RuntimeError("unreachable") + + +@workflow.defn +class ChildCancelReasonWorkflow: + @workflow.run + async def run(self, msg: str) -> str: + child = await workflow.start_child_workflow( + CancelReasonReporter.run, + id=f"{workflow.info().workflow_id}_child", + ) + child.cancel(msg) + return await child + + +async def test_workflow_child_cancel_reason(client: Client): + async with new_worker( + client, ChildCancelReasonWorkflow, CancelReasonReporter + ) as worker: + result = await client.execute_workflow( + ChildCancelReasonWorkflow.run, + "from-parent", + id=f"workflow-{uuid.uuid4()}", + task_queue=worker.task_queue, + ) + assert result == "from-parent" + + +@workflow.defn +class ExternalCancelReasonWorkflow: + @workflow.run + async def run(self, target_id: str) -> None: + await workflow.get_external_workflow_handle(target_id).cancel( + reason="from-external-caller" + ) + + +async def test_workflow_external_cancel_reason(client: Client): + async with new_worker( + client, ExternalCancelReasonWorkflow, CancelReasonReporter + ) as worker: + target_id = f"workflow-{uuid.uuid4()}" + target = await client.start_workflow( + CancelReasonReporter.run, + id=target_id, + task_queue=worker.task_queue, + ) + await client.execute_workflow( + ExternalCancelReasonWorkflow.run, + target_id, + id=f"workflow-{uuid.uuid4()}", + task_queue=worker.task_queue, + ) + # Server wraps the user-supplied reason with metadata about the caller + # when one workflow cancels another, so check for substring. + assert "from-external-caller" in await target.result() + + @workflow.defn class TrapCancelWorkflow: @workflow.run From d2110271b38798e5ecb67b4946f6ac4e149d96d1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 3 Jun 2026 20:43:15 +0000 Subject: [PATCH 118/226] Bump litellm to 1.86.2 and openai-agents to 0.17.4 (#1478) * Bump litellm from 1.83.0 to 1.83.7 Bumps [litellm](https://github.com/BerriAI/litellm) from 1.83.0 to 1.83.7. - [Release notes](https://github.com/BerriAI/litellm/releases) - [Commits](https://github.com/BerriAI/litellm/commits) --- updated-dependencies: - dependency-name: litellm dependency-version: 1.83.7 dependency-type: direct:development ... Signed-off-by: dependabot[bot] * Bump litellm to 1.86.2 and openai-agents to 0.17.4, drop exclude-newer overrides litellm 1.83.7 pinned its deps to exact versions, forcing downgrades of click, openai, pydantic, jsonschema, and others. Bumping litellm to 1.86.2 relaxes those pins and restores the downgraded packages. Also bump openai-agents to 0.17.4 and remove the now-unnecessary exclude-newer-package overrides. * Remove openai-agents exclude-newer override The openai-agents>=0.17.1 minimum pin no longer requires bypassing the exclude-newer cooldown: 0.17.1 through 0.17.3 are now older than the 2-week window. Drop the override so dependency selection is governed solely by the 2-week policy. openai-agents resolves to 0.17.3 (0.17.4 is still inside the window). --------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Brian Strauch --- pyproject.toml | 3 - uv.lock | 280 ++++++++++++++++++++++++------------------------- 2 files changed, 139 insertions(+), 144 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index b44459fa3..596003480 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -257,6 +257,3 @@ exclude = ["temporalio/bridge/target/**/*"] # Prevent uv commands from building the package by default package = false exclude-newer = "2 weeks" -# openai-agents>=0.17.1 is newer than the exclude-newer cooldown window; -# bypass it since the minimum version pin already constrains the package. -exclude-newer-package = { openai-agents = false } diff --git a/uv.lock b/uv.lock index abea4b74c..d7c4f3c50 100644 --- a/uv.lock +++ b/uv.lock @@ -12,9 +12,6 @@ resolution-markers = [ exclude-newer = "0001-01-01T00:00:00Z" # This has no effect and is included for backwards compatibility when using relative exclude-newer values. exclude-newer-span = "P2W" -[options.exclude-newer-package] -openai-agents = false - [[package]] name = "aioboto3" version = "15.5.0" @@ -712,14 +709,14 @@ wheels = [ [[package]] name = "click" -version = "8.3.3" +version = "8.4.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "colorama", marker = "sys_platform == 'win32'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/bb/63/f9e1ea081ce35720d8b92acde70daaedace594dc93b693c869e0d5910718/click-8.3.3.tar.gz", hash = "sha256:398329ad4837b2ff7cbe1dd166a4c0f8900c3ca3a218de04466f38f6497f18a2", size = 328061, upload-time = "2026-04-22T15:11:27.506Z" } +sdist = { url = "https://files.pythonhosted.org/packages/23/e4/796662cd90cf80e3a363c99db2b88e0e394b988a575f60a17e16440cd011/click-8.4.0.tar.gz", hash = "sha256:638f1338fe1235c8f4e008e4a8a254fb5c5fbdcbb40ece3c9142ebb78e792973", size = 350843, upload-time = "2026-05-17T00:47:58.425Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/ae/44/c1221527f6a71a01ec6fbad7fa78f1d50dfa02217385cf0fa3eec7087d59/click-8.3.3-py3-none-any.whl", hash = "sha256:a2bf429bb3033c89fa4936ffb35d5cb471e3719e1f3c8a7c3fff0b8314305613", size = 110502, upload-time = "2026-04-22T15:11:25.044Z" }, + { 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]] @@ -2459,7 +2456,7 @@ wheels = [ [[package]] name = "jsonschema" -version = "4.24.1" +version = "4.26.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "attrs" }, @@ -2467,23 +2464,24 @@ dependencies = [ { name = "referencing" }, { name = "rpds-py" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/f1/6e/35174c1d3f30560848c82d3c233c01420e047d70925c897a4d6e932b4898/jsonschema-4.24.1.tar.gz", hash = "sha256:fe45a130cc7f67cd0d67640b4e7e3e2e666919462ae355eda238296eafeb4b5d", size = 356635, upload-time = "2025-07-17T14:40:01.05Z" } +sdist = { url = "https://files.pythonhosted.org/packages/b3/fc/e067678238fa451312d4c62bf6e6cf5ec56375422aee02f9cb5f909b3047/jsonschema-4.26.0.tar.gz", hash = "sha256:0c26707e2efad8aa1bfc5b7ce170f3fccc2e4918ff85989ba9ffa9facb2be326", size = 366583, upload-time = "2026-01-07T13:41:07.246Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/85/7f/ea48ffb58f9791f9d97ccb35e42fea1ebc81c67ce36dc4b8b2eee60e8661/jsonschema-4.24.1-py3-none-any.whl", hash = "sha256:6b916866aa0b61437785f1277aa2cbd63512e8d4b47151072ef13292049b4627", size = 89060, upload-time = "2025-07-17T14:39:59.471Z" }, + { url = "https://files.pythonhosted.org/packages/69/90/f63fb5873511e014207a475e2bb4e8b2e570d655b00ac19a9a0ca0a385ee/jsonschema-4.26.0-py3-none-any.whl", hash = "sha256:d489f15263b8d200f8387e64b4c3a75f06629559fb73deb8fdfb525f2dab50ce", size = 90630, upload-time = "2026-01-07T13:41:05.306Z" }, ] [[package]] name = "jsonschema-path" -version = "0.4.5" +version = "0.5.0" source = { registry = "https://pypi.org/simple" } dependencies = [ + { name = "attrs" }, { name = "pathable" }, { name = "pyyaml" }, { name = "referencing" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/5b/8a/7e6102f2b8bdc6705a9eb5294f8f6f9ccd3a8420e8e8e19671d1dd773251/jsonschema_path-0.4.5.tar.gz", hash = "sha256:c6cd7d577ae290c7defd4f4029e86fdb248ca1bd41a07557795b3c95e5144918", size = 15113, upload-time = "2026-03-03T09:56:46.87Z" } +sdist = { url = "https://files.pythonhosted.org/packages/39/79/cd02a4df6d9270efdc7d3feefe6edd730b0820c39eeaa107a2faee8322d5/jsonschema_path-0.5.0.tar.gz", hash = "sha256:493b156ba895c97602655b620a8456caa2ce08c1aa389f5a7addec065e6e855c", size = 19597, upload-time = "2026-05-19T20:45:00.971Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/04/d5/4e96c44f6c1ea3d812cf5391d81a4f5abaa540abf8d04ecd7f66e0ed11df/jsonschema_path-0.4.5-py3-none-any.whl", hash = "sha256:7d77a2c3f3ec569a40efe5c5f942c44c1af2a6f96fe0866794c9ef5b8f87fd65", size = 19368, upload-time = "2026-03-03T09:56:45.39Z" }, + { url = "https://files.pythonhosted.org/packages/04/2c/9e69d73c4297508be9e3b64a970ea3971b3eb8db64ffc5802d40bd25981f/jsonschema_path-0.5.0-py3-none-any.whl", hash = "sha256:2790a070bc7abb08ea3dbe4d340ece4efadf639223001f020c7503229ba068e2", size = 24077, upload-time = "2026-05-19T20:44:59.225Z" }, ] [[package]] @@ -2658,7 +2656,7 @@ wheels = [ [[package]] name = "litellm" -version = "1.83.0" +version = "1.85.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "aiohttp" }, @@ -2674,9 +2672,9 @@ dependencies = [ { name = "tiktoken" }, { name = "tokenizers" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/22/92/6ce9737554994ca8e536e5f4f6a87cc7c4774b656c9eb9add071caf7d54b/litellm-1.83.0.tar.gz", hash = "sha256:860bebc76c4bb27b4cf90b4a77acd66dba25aced37e3db98750de8a1766bfb7a", size = 17333062, upload-time = "2026-03-31T05:08:25.331Z" } +sdist = { url = "https://files.pythonhosted.org/packages/3b/d5/3c9b560db2ffa9e498655d0dfd74f408bc5b32ede858b5731c2a5fa4c752/litellm-1.85.0.tar.gz", hash = "sha256:babdd569809af913d08a08a7eb55df1ed3e6a3960ee365c6cef4ad031c9bc72a", size = 15344387, upload-time = "2026-05-17T01:59:15.97Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/19/2c/a670cc050fcd6f45c6199eb99e259c73aea92edba8d5c2fc1b3686d36217/litellm-1.83.0-py3-none-any.whl", hash = "sha256:88c536d339248f3987571493015784671ba3f193a328e1ea6780dbebaa2094a8", size = 15610306, upload-time = "2026-03-31T05:08:21.987Z" }, + { 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]] @@ -3407,7 +3405,7 @@ wheels = [ [[package]] name = "openai" -version = "2.32.0" +version = "2.37.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "anyio" }, @@ -3419,14 +3417,14 @@ dependencies = [ { name = "tqdm" }, { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/ed/59/bdcc6b759b8c42dd73afaf5bf8f902c04b37987a5514dbc1c64dba390fef/openai-2.32.0.tar.gz", hash = "sha256:c54b27a9e4cb8d51f0dd94972ffd1a04437efeb259a9e60d8922b8bd26fe55e0", size = 693286, upload-time = "2026-04-15T22:28:19.434Z" } +sdist = { url = "https://files.pythonhosted.org/packages/32/50/5901f01ef14e6c27788beb91e54fef5d6204fb5fb9e97402fc8a14de2e32/openai-2.37.0.tar.gz", hash = "sha256:f4bc562cc5f3a43d40d678105572d9d44765f6e0f50c125f63055419b72f4bd9", size = 754706, upload-time = "2026-05-15T22:30:35.428Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/1e/c1/d6e64ccd0536bf616556f0cad2b6d94a8125f508d25cfd814b1d2db4e2f1/openai-2.32.0-py3-none-any.whl", hash = "sha256:4dcc9badeb4bf54ad0d187453742f290226d30150890b7890711bda4f32f192f", size = 1162570, upload-time = "2026-04-15T22:28:17.714Z" }, + { url = "https://files.pythonhosted.org/packages/ed/4c/bce61680d0699a78a405fd9a67989b175ba020590428831aab2ab1d2be7c/openai-2.37.0-py3-none-any.whl", hash = "sha256:814633888b8f3b1ffd6615697c6e4ef93632d08b7c2e28c8c5ef3556e5a10107", size = 1303238, upload-time = "2026-05-15T22:30:32.767Z" }, ] [[package]] name = "openai-agents" -version = "0.17.1" +version = "0.17.3" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "griffelib" }, @@ -3438,9 +3436,9 @@ dependencies = [ { name = "typing-extensions" }, { name = "websockets" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/04/c9/a0a5a5fad76710f0c77fd104f868bdf0360e0e58bc37a89238c6c6410a92/openai_agents-0.17.1.tar.gz", hash = "sha256:6d5e77956a2804ff6f230d57bcc2bc315364a796f7aced0ecfa43440686c096c", size = 5400291, upload-time = "2026-05-11T06:57:01.385Z" } +sdist = { url = "https://files.pythonhosted.org/packages/fd/16/b79c1849125eb6d19cae98c21ff35caa2e55b5ec8d7a02b354b711917ef7/openai_agents-0.17.3.tar.gz", hash = "sha256:63b6dda6bd4fb51169e2a2cbd5d187a4e5ce823bbd15f965c8ed1d3b89072eec", size = 5406135, upload-time = "2026-05-19T01:28:15.971Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/c3/0c/13c87bcf2510a761767094bc103818d1d676f24ad2f48406c9e74c82fd76/openai_agents-0.17.1-py3-none-any.whl", hash = "sha256:41598c98969d972d46a5028b9a79ca62a563a2b85ebb829ccc48b5daa2e34960", size = 837555, upload-time = "2026-05-11T06:56:59.247Z" }, + { url = "https://files.pythonhosted.org/packages/80/ec/775a14cfd5f12f4ffe458c7ac9527831093c72e8c1aef682898fc6394106/openai_agents-0.17.3-py3-none-any.whl", hash = "sha256:a048bb0752d40913d18bccf6562f56260b603bb57c972597b6da58f60123f4bd", size = 841541, upload-time = "2026-05-19T01:28:13.334Z" }, ] [package.optional-dependencies] @@ -3450,7 +3448,7 @@ litellm = [ [[package]] name = "openapi-schema-validator" -version = "0.8.1" +version = "0.9.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "jsonschema" }, @@ -3460,14 +3458,14 @@ dependencies = [ { name = "referencing" }, { name = "rfc3339-validator" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/21/4b/67b24b2b23d96ea862be2cca3632a546f67a22461200831213e80c3c6011/openapi_schema_validator-0.8.1.tar.gz", hash = "sha256:4c57266ce8cbfa37bb4eb4d62cdb7d19356c3a468e3535743c4562863e1790da", size = 23134, upload-time = "2026-03-02T08:46:29.807Z" } +sdist = { url = "https://files.pythonhosted.org/packages/98/e8/ab3f27dbca54ec645f7fab714b640907d5d36c2ebb07e87eebd30bd5c81b/openapi_schema_validator-0.9.0.tar.gz", hash = "sha256:b72db64315b89d21834cd3ffef37e3e6893bc876327be2d366e8424b1029afd3", size = 24686, upload-time = "2026-04-27T17:31:27.606Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/6f/87/e9f29f463b230d4b47d65e17858c595153a8ca8c1775f16e406aa82d455d/openapi_schema_validator-0.8.1-py3-none-any.whl", hash = "sha256:0f5859794c5bfa433d478dc5ac5e5768d50adc56b14380c8a6fd3a8113e89c9b", size = 19211, upload-time = "2026-03-02T08:46:28.154Z" }, + { url = "https://files.pythonhosted.org/packages/90/c0/5467967d95378b2cfce312e09cbd0c9ab64354a0922379b734f793edd04f/openapi_schema_validator-0.9.0-py3-none-any.whl", hash = "sha256:faa3bbe7c3aa8ca2087ad83f709dc3b7d920283153a570c03e24ea182558aa25", size = 19980, upload-time = "2026-04-27T17:31:25.965Z" }, ] [[package]] name = "openapi-spec-validator" -version = "0.8.4" +version = "0.9.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "jsonschema" }, @@ -3477,9 +3475,9 @@ dependencies = [ { name = "pydantic" }, { name = "pydantic-settings" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/10/de/0199b15f5dde3ca61df6e6b3987420bfd424db077998f0162e8ffe12e4f5/openapi_spec_validator-0.8.4.tar.gz", hash = "sha256:8bb324b9b08b9b368b1359dec14610c60a8f3a3dd63237184eb04456d4546f49", size = 1756847, upload-time = "2026-03-01T15:48:19.499Z" } +sdist = { url = "https://files.pythonhosted.org/packages/8f/d2/640b5149cd5688bc0ad1fdbb4df6a2f7b84a093c8d787c27d566132f8b8b/openapi_spec_validator-0.9.0.tar.gz", hash = "sha256:6d648cff6490ebb799dcfe273792f2941c050158854c721f086599d845da78b8", size = 1756839, upload-time = "2026-05-20T09:23:18.871Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/cb/70/52310f9ece5f4eb02e0b31d538b51f729169517767a8d0100a25db31d67f/openapi_spec_validator-0.8.4-py3-none-any.whl", hash = "sha256:cf905117063d7c4d495c8a5a167a1f2a8006da6ffa8ba234a7ed0d0f11454d51", size = 50330, upload-time = "2026-03-01T15:48:17.668Z" }, + { url = "https://files.pythonhosted.org/packages/95/d8/321ff889330acca2e3097f3d4f80a40bcc41b6d34d302978ab32c449520b/openapi_spec_validator-0.9.0-py3-none-any.whl", hash = "sha256:222fecffc7714f6d0a6ad62c0e4b66cc2b7dbfafb7b93acfc6c308abbdb51af8", size = 50328, upload-time = "2026-05-20T09:23:17.017Z" }, ] [[package]] @@ -3891,11 +3889,11 @@ wheels = [ [[package]] name = "pathable" -version = "0.5.0" +version = "0.6.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/72/55/b748445cb4ea6b125626f15379be7c96d1035d4fa3e8fee362fa92298abf/pathable-0.5.0.tar.gz", hash = "sha256:d81938348a1cacb525e7c75166270644782c0fb9c8cecc16be033e71427e0ef1", size = 16655, upload-time = "2026-02-20T08:47:00.748Z" } +sdist = { url = "https://files.pythonhosted.org/packages/66/f3/5a20387de9bcd0607871bfc2198ee0e15836da7baa4592ccd7f24c27c986/pathable-0.6.0.tar.gz", hash = "sha256:6404b8b82aef5ff0fd478934137128b99b12212ba35afdde5525ca4f8388ea58", size = 18970, upload-time = "2026-05-19T18:15:11.911Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/52/96/5a770e5c461462575474468e5af931cff9de036e7c2b4fea23c1c58d2cbe/pathable-0.5.0-py3-none-any.whl", hash = "sha256:646e3d09491a6351a0c82632a09c02cdf70a252e73196b36d8a15ba0a114f0a6", size = 16867, upload-time = "2026-02-20T08:46:59.536Z" }, + { url = "https://files.pythonhosted.org/packages/a2/e8/6d75ffd9784bce2e93d1ae4415649427e39a53bb172d4672b2b59c6f0a7b/pathable-0.6.0-py3-none-any.whl", hash = "sha256:82c4ca6c98c502ad12e0d4e9779b6210afee93c38990988c8c5d1b49bdcdf566", size = 18983, upload-time = "2026-05-19T18:15:10.728Z" }, ] [[package]] @@ -4297,7 +4295,7 @@ wheels = [ [[package]] name = "pydantic" -version = "2.13.3" +version = "2.13.4" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "annotated-types" }, @@ -4305,125 +4303,125 @@ dependencies = [ { name = "typing-extensions" }, { name = "typing-inspection" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/d9/e4/40d09941a2cebcb20609b86a559817d5b9291c49dd6f8c87e5feffbe703a/pydantic-2.13.3.tar.gz", hash = "sha256:af09e9d1d09f4e7fe37145c1f577e1d61ceb9a41924bf0094a36506285d0a84d", size = 844068, upload-time = "2026-04-20T14:46:43.632Z" } +sdist = { url = "https://files.pythonhosted.org/packages/18/a5/b60d21ac674192f8ab0ba4e9fd860690f9b4a6e51ca5df118733b487d8d6/pydantic-2.13.4.tar.gz", hash = "sha256:c40756b57adaa8b1efeeced5c196f3f3b7c435f90e84ea7f443901bec8099ef6", size = 844775, upload-time = "2026-05-06T13:43:05.343Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/f3/0a/fd7d723f8f8153418fb40cf9c940e82004fce7e987026b08a68a36dd3fe7/pydantic-2.13.3-py3-none-any.whl", hash = "sha256:6db14ac8dfc9a1e57f87ea2c0de670c251240f43cb0c30a5130e9720dc612927", size = 471981, upload-time = "2026-04-20T14:46:41.402Z" }, + { url = "https://files.pythonhosted.org/packages/fd/7b/122376b1fd3c62c1ed9dc80c931ace4844b3c55407b6fb2d199377c9736f/pydantic-2.13.4-py3-none-any.whl", hash = "sha256:45a282cde31d808236fd7ea9d919b128653c8b38b393d1c4ab335c62924d9aba", size = 472262, upload-time = "2026-05-06T13:43:02.641Z" }, ] [[package]] name = "pydantic-core" -version = "2.46.3" +version = "2.46.4" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/2a/ef/f7abb56c49382a246fd2ce9c799691e3c3e7175ec74b14d99e798bcddb1a/pydantic_core-2.46.3.tar.gz", hash = "sha256:41c178f65b8c29807239d47e6050262eb6bf84eb695e41101e62e38df4a5bc2c", size = 471412, upload-time = "2026-04-20T14:40:56.672Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/22/98/b50eb9a411e87483b5c65dba4fa430a06bac4234d3403a40e5a9905ebcd0/pydantic_core-2.46.3-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:1da3786b8018e60349680720158cc19161cc3b4bdd815beb0a321cd5ce1ad5b1", size = 2108971, upload-time = "2026-04-20T14:43:51.945Z" }, - { url = "https://files.pythonhosted.org/packages/08/4b/f364b9d161718ff2217160a4b5d41ce38de60aed91c3689ebffa1c939d23/pydantic_core-2.46.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:cc0988cb29d21bf4a9d5cf2ef970b5c0e38d8d8e107a493278c05dc6c1dda69f", size = 1949588, upload-time = "2026-04-20T14:44:10.386Z" }, - { url = "https://files.pythonhosted.org/packages/8f/8b/30bd03ee83b2f5e29f5ba8e647ab3c456bf56f2ec72fdbcc0215484a0854/pydantic_core-2.46.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:27f9067c3bfadd04c55484b89c0d267981b2f3512850f6f66e1e74204a4e4ce3", size = 1975986, upload-time = "2026-04-20T14:43:57.106Z" }, - { url = "https://files.pythonhosted.org/packages/3c/54/13ccf954d84ec275d5d023d5786e4aa48840bc9f161f2838dc98e1153518/pydantic_core-2.46.3-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:a642ac886ecf6402d9882d10c405dcf4b902abeb2972cd5fb4a48c83cd59279a", size = 2055830, upload-time = "2026-04-20T14:44:15.499Z" }, - { url = "https://files.pythonhosted.org/packages/be/0e/65f38125e660fdbd72aa858e7dfae893645cfa0e7b13d333e174a367cd23/pydantic_core-2.46.3-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:79f561438481f28681584b89e2effb22855e2179880314bcddbf5968e935e807", size = 2222340, upload-time = "2026-04-20T14:41:51.353Z" }, - { url = "https://files.pythonhosted.org/packages/d1/88/f3ab7739efe0e7e80777dbb84c59eb98518e3f57ea433206194c2e425272/pydantic_core-2.46.3-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:57a973eae4665352a47cf1a99b4ee864620f2fe663a217d7a8da68a1f3a5bfda", size = 2280727, upload-time = "2026-04-20T14:41:30.461Z" }, - { url = "https://files.pythonhosted.org/packages/2a/6d/c228219080817bec4982f9531cadb18da6aaa770fdeb114f49c237ac2c9f/pydantic_core-2.46.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:83d002b97072a53ea150d63e0a3adfae5670cef5aa8a6e490240e482d3b22e57", size = 2092158, upload-time = "2026-04-20T14:44:07.305Z" }, - { url = "https://files.pythonhosted.org/packages/0f/b1/525a16711e7c6d61635fac3b0bd54600b5c5d9f60c6fc5aaab26b64a2297/pydantic_core-2.46.3-cp310-cp310-manylinux_2_31_riscv64.whl", hash = "sha256:b40ddd51e7c44b28cfaef746c9d3c506d658885e0a46f9eeef2ee815cbf8e045", size = 2116626, upload-time = "2026-04-20T14:42:34.118Z" }, - { url = "https://files.pythonhosted.org/packages/ef/7c/17d30673351439a6951bf54f564cf2443ab00ae264ec9df00e2efd710eb5/pydantic_core-2.46.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:ac5ec7fb9b87f04ee839af2d53bcadea57ded7d229719f56c0ed895bff987943", size = 2160691, upload-time = "2026-04-20T14:41:14.023Z" }, - { url = "https://files.pythonhosted.org/packages/86/66/af8adbcbc0886ead7f1a116606a534d75a307e71e6e08226000d51b880d2/pydantic_core-2.46.3-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:a3b11c812f61b3129c4905781a2601dfdfdea5fe1e6c1cfb696b55d14e9c054f", size = 2182543, upload-time = "2026-04-20T14:40:48.886Z" }, - { url = "https://files.pythonhosted.org/packages/b0/37/6de71e0f54c54a4190010f57deb749e1ddf75c568ada3b1320b70067f121/pydantic_core-2.46.3-cp310-cp310-musllinux_1_1_armv7l.whl", hash = "sha256:1108da631e602e5b3c38d6d04fe5bb3bfa54349e6918e3ca6cf570b2e2b2f9d4", size = 2324513, upload-time = "2026-04-20T14:42:36.121Z" }, - { url = "https://files.pythonhosted.org/packages/51/b1/9fc74ce94f603d5ef59ff258ca9c2c8fb902fb548d340a96f77f4d1c3b7f/pydantic_core-2.46.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:de885175515bcfa98ae618c1df7a072f13d179f81376c8007112af20567fd08a", size = 2361853, upload-time = "2026-04-20T14:43:24.886Z" }, - { url = "https://files.pythonhosted.org/packages/40/d0/4c652fc592db35f100279ee751d5a145aca1b9a7984b9684ba7c1b5b0535/pydantic_core-2.46.3-cp310-cp310-win32.whl", hash = "sha256:d11058e3201527d41bc6b545c79187c9e4bf85e15a236a6007f0e991518882b7", size = 1980465, upload-time = "2026-04-20T14:44:46.239Z" }, - { url = "https://files.pythonhosted.org/packages/27/b8/a920453c38afbe1f355e1ea0b0d94a0a3e0b0879d32d793108755fa171d5/pydantic_core-2.46.3-cp310-cp310-win_amd64.whl", hash = "sha256:3612edf65c8ea67ac13616c4d23af12faef1ae435a8a93e5934c2a0cbbdd1fd6", size = 2073884, upload-time = "2026-04-20T14:43:01.201Z" }, - { url = "https://files.pythonhosted.org/packages/22/a2/1ba90a83e85a3f94c796b184f3efde9c72f2830dcda493eea8d59ba78e6d/pydantic_core-2.46.3-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:ab124d49d0459b2373ecf54118a45c28a1e6d4192a533fbc915e70f556feb8e5", size = 2106740, upload-time = "2026-04-20T14:41:20.932Z" }, - { url = "https://files.pythonhosted.org/packages/b6/f6/99ae893c89a0b9d3daec9f95487aa676709aa83f67643b3f0abaf4ab628a/pydantic_core-2.46.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:cca67d52a5c7a16aed2b3999e719c4bcf644074eac304a5d3d62dd70ae7d4b2c", size = 1948293, upload-time = "2026-04-20T14:43:42.115Z" }, - { url = "https://files.pythonhosted.org/packages/3e/b8/2e8e636dc9e3f16c2e16bf0849e24be82c5ee82c603c65fc0326666328fc/pydantic_core-2.46.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5c024e08c0ba23e6fd68c771a521e9d6a792f2ebb0fa734296b36394dc30390e", size = 1973222, upload-time = "2026-04-20T14:41:57.841Z" }, - { url = "https://files.pythonhosted.org/packages/34/36/0e730beec4d83c5306f417afbd82ff237d9a21e83c5edf675f31ed84c1fe/pydantic_core-2.46.3-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:6645ce7eec4928e29a1e3b3d5c946621d105d3e79f0c9cddf07c2a9770949287", size = 2053852, upload-time = "2026-04-20T14:40:43.077Z" }, - { url = "https://files.pythonhosted.org/packages/4b/f0/3071131f47e39136a17814576e0fada9168569f7f8c0e6ac4d1ede6a4958/pydantic_core-2.46.3-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a712c7118e6c5ea96562f7b488435172abb94a3c53c22c9efc1412264a45cbbe", size = 2221134, upload-time = "2026-04-20T14:43:03.349Z" }, - { url = "https://files.pythonhosted.org/packages/2f/a9/a2dc023eec5aa4b02a467874bad32e2446957d2adcab14e107eab502e978/pydantic_core-2.46.3-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:69a868ef3ff206343579021c40faf3b1edc64b1cc508ff243a28b0a514ccb050", size = 2279785, upload-time = "2026-04-20T14:41:19.285Z" }, - { url = "https://files.pythonhosted.org/packages/0a/44/93f489d16fb63fbd41c670441536541f6e8cfa1e5a69f40bc9c5d30d8c90/pydantic_core-2.46.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cc7e8c32db809aa0f6ea1d6869ebc8518a65d5150fdfad8bcae6a49ae32a22e2", size = 2089404, upload-time = "2026-04-20T14:43:10.108Z" }, - { url = "https://files.pythonhosted.org/packages/2a/78/8692e3aa72b2d004f7a5d937f1dfdc8552ba26caf0bec75f342c40f00dec/pydantic_core-2.46.3-cp311-cp311-manylinux_2_31_riscv64.whl", hash = "sha256:3481bd1341dc85779ee506bc8e1196a277ace359d89d28588a9468c3ecbe63fa", size = 2114898, upload-time = "2026-04-20T14:44:51.475Z" }, - { url = "https://files.pythonhosted.org/packages/6a/62/e83133f2e7832532060175cebf1f13748f4c7e7e7165cdd1f611f174494b/pydantic_core-2.46.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:8690eba565c6d68ffd3a8655525cbdd5246510b44a637ee2c6c03a7ebfe64d3c", size = 2157856, upload-time = "2026-04-20T14:43:46.64Z" }, - { url = "https://files.pythonhosted.org/packages/6d/ec/6a500e3ad7718ee50583fae79c8651f5d37e3abce1fa9ae177ae65842c53/pydantic_core-2.46.3-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:4de88889d7e88d50d40ee5b39d5dac0bcaef9ba91f7e536ac064e6b2834ecccf", size = 2180168, upload-time = "2026-04-20T14:42:00.302Z" }, - { url = "https://files.pythonhosted.org/packages/d8/53/8267811054b1aa7fc1dc7ded93812372ef79a839f5e23558136a6afbfde1/pydantic_core-2.46.3-cp311-cp311-musllinux_1_1_armv7l.whl", hash = "sha256:e480080975c1ef7f780b8f99ed72337e7cc5efea2e518a20a692e8e7b278eb8b", size = 2322885, upload-time = "2026-04-20T14:41:05.253Z" }, - { url = "https://files.pythonhosted.org/packages/c8/c1/1c0acdb3aa0856ddc4ecc55214578f896f2de16f400cf51627eb3c26c1c4/pydantic_core-2.46.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:de3a5c376f8cd94da9a1b8fd3dd1c16c7a7b216ed31dc8ce9fd7a22bf13b836e", size = 2360328, upload-time = "2026-04-20T14:41:43.991Z" }, - { url = "https://files.pythonhosted.org/packages/f0/d0/ef39cd0f4a926814f360e71c1adeab48ad214d9727e4deb48eedfb5bce1a/pydantic_core-2.46.3-cp311-cp311-win32.whl", hash = "sha256:fc331a5314ffddd5385b9ee9d0d2fee0b13c27e0e02dad71b1ae5d6561f51eeb", size = 1979464, upload-time = "2026-04-20T14:43:12.215Z" }, - { url = "https://files.pythonhosted.org/packages/18/9c/f41951b0d858e343f1cf09398b2a7b3014013799744f2c4a8ad6a3eec4f2/pydantic_core-2.46.3-cp311-cp311-win_amd64.whl", hash = "sha256:b5b9c6cf08a8a5e502698f5e153056d12c34b8fb30317e0c5fd06f45162a6346", size = 2070837, upload-time = "2026-04-20T14:41:47.707Z" }, - { url = "https://files.pythonhosted.org/packages/9f/1e/264a17cd582f6ed50950d4d03dd5fefd84e570e238afe1cb3e25cf238769/pydantic_core-2.46.3-cp311-cp311-win_arm64.whl", hash = "sha256:5dfd51cf457482f04ec49491811a2b8fd5b843b64b11eecd2d7a1ee596ea78a6", size = 2053647, upload-time = "2026-04-20T14:42:27.535Z" }, - { url = "https://files.pythonhosted.org/packages/4b/cb/5b47425556ecc1f3fe18ed2a0083188aa46e1dd812b06e406475b3a5d536/pydantic_core-2.46.3-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:b11b59b3eee90a80a36701ddb4576d9ae31f93f05cb9e277ceaa09e6bf074a67", size = 2101946, upload-time = "2026-04-20T14:40:52.581Z" }, - { url = "https://files.pythonhosted.org/packages/a1/4f/2fb62c2267cae99b815bbf4a7b9283812c88ca3153ef29f7707200f1d4e5/pydantic_core-2.46.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:af8653713055ea18a3abc1537fe2ebc42f5b0bbb768d1eb79fd74eb47c0ac089", size = 1951612, upload-time = "2026-04-20T14:42:42.996Z" }, - { url = "https://files.pythonhosted.org/packages/50/6e/b7348fd30d6556d132cddd5bd79f37f96f2601fe0608afac4f5fb01ec0b3/pydantic_core-2.46.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:75a519dab6d63c514f3a81053e5266c549679e4aa88f6ec57f2b7b854aceb1b0", size = 1977027, upload-time = "2026-04-20T14:42:02.001Z" }, - { url = "https://files.pythonhosted.org/packages/82/11/31d60ee2b45540d3fb0b29302a393dbc01cd771c473f5b5147bcd353e593/pydantic_core-2.46.3-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:a6cd87cb1575b1ad05ba98894c5b5c96411ef678fa2f6ed2576607095b8d9789", size = 2063008, upload-time = "2026-04-20T14:44:17.952Z" }, - { url = "https://files.pythonhosted.org/packages/8a/db/3a9d1957181b59258f44a2300ab0f0be9d1e12d662a4f57bb31250455c52/pydantic_core-2.46.3-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f80a55484b8d843c8ada81ebf70a682f3f00a3d40e378c06cf17ecb44d280d7d", size = 2233082, upload-time = "2026-04-20T14:40:57.934Z" }, - { url = "https://files.pythonhosted.org/packages/9c/e1/3277c38792aeb5cfb18c2f0c5785a221d9ff4e149abbe1184d53d5f72273/pydantic_core-2.46.3-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3861f1731b90c50a3266316b9044f5c9b405eecb8e299b0a7120596334e4fe9c", size = 2304615, upload-time = "2026-04-20T14:42:12.584Z" }, - { url = "https://files.pythonhosted.org/packages/5e/d5/e3d9717c9eba10855325650afd2a9cba8e607321697f18953af9d562da2f/pydantic_core-2.46.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fb528e295ed31570ac3dcc9bfdd6e0150bc11ce6168ac87a8082055cf1a67395", size = 2094380, upload-time = "2026-04-20T14:43:05.522Z" }, - { url = "https://files.pythonhosted.org/packages/a1/20/abac35dedcbfd66c6f0b03e4e3564511771d6c9b7ede10a362d03e110d9b/pydantic_core-2.46.3-cp312-cp312-manylinux_2_31_riscv64.whl", hash = "sha256:367508faa4973b992b271ba1494acaab36eb7e8739d1e47be5035fb1ea225396", size = 2135429, upload-time = "2026-04-20T14:41:55.549Z" }, - { url = "https://files.pythonhosted.org/packages/6c/a5/41bfd1df69afad71b5cf0535055bccc73022715ad362edbc124bc1e021d7/pydantic_core-2.46.3-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:5ad3c826fe523e4becf4fe39baa44286cff85ef137c729a2c5e269afbfd0905d", size = 2174582, upload-time = "2026-04-20T14:41:45.96Z" }, - { url = "https://files.pythonhosted.org/packages/79/65/38d86ea056b29b2b10734eb23329b7a7672ca604df4f2b6e9c02d4ee22fe/pydantic_core-2.46.3-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:ec638c5d194ef8af27db69f16c954a09797c0dc25015ad6123eb2c73a4d271ca", size = 2187533, upload-time = "2026-04-20T14:40:55.367Z" }, - { url = "https://files.pythonhosted.org/packages/b6/55/a1129141678a2026badc539ad1dee0a71d06f54c2f06a4bd68c030ac781b/pydantic_core-2.46.3-cp312-cp312-musllinux_1_1_armv7l.whl", hash = "sha256:28ed528c45446062ee66edb1d33df5d88828ae167de76e773a3c7f64bd14e976", size = 2332985, upload-time = "2026-04-20T14:44:13.05Z" }, - { url = "https://files.pythonhosted.org/packages/d7/60/cb26f4077719f709e54819f4e8e1d43f4091f94e285eb6bd21e1190a7b7c/pydantic_core-2.46.3-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:aed19d0c783886d5bd86d80ae5030006b45e28464218747dcf83dabfdd092c7b", size = 2373670, upload-time = "2026-04-20T14:41:53.421Z" }, - { url = "https://files.pythonhosted.org/packages/6b/7e/c3f21882bdf1d8d086876f81b5e296206c69c6082551d776895de7801fa0/pydantic_core-2.46.3-cp312-cp312-win32.whl", hash = "sha256:06d5d8820cbbdb4147578c1fe7ffcd5b83f34508cb9f9ab76e807be7db6ff0a4", size = 1966722, upload-time = "2026-04-20T14:44:30.588Z" }, - { url = "https://files.pythonhosted.org/packages/57/be/6b5e757b859013ebfbd7adba02f23b428f37c86dcbf78b5bb0b4ffd36e99/pydantic_core-2.46.3-cp312-cp312-win_amd64.whl", hash = "sha256:c3212fda0ee959c1dd04c60b601ec31097aaa893573a3a1abd0a47bcac2968c1", size = 2072970, upload-time = "2026-04-20T14:42:54.248Z" }, - { url = "https://files.pythonhosted.org/packages/bf/f8/a989b21cc75e9a32d24192ef700eea606521221a89faa40c919ce884f2b1/pydantic_core-2.46.3-cp312-cp312-win_arm64.whl", hash = "sha256:f1f8338dd7a7f31761f1f1a3c47503a9a3b34eea3c8b01fa6ee96408affb5e72", size = 2035963, upload-time = "2026-04-20T14:44:20.4Z" }, - { url = "https://files.pythonhosted.org/packages/9b/3c/9b5e8eb9821936d065439c3b0fb1490ffa64163bfe7e1595985a47896073/pydantic_core-2.46.3-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:12bc98de041458b80c86c56b24df1d23832f3e166cbaff011f25d187f5c62c37", size = 2102109, upload-time = "2026-04-20T14:41:24.219Z" }, - { url = "https://files.pythonhosted.org/packages/91/97/1c41d1f5a19f241d8069f1e249853bcce378cdb76eec8ab636d7bc426280/pydantic_core-2.46.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:85348b8f89d2c3508b65b16c3c33a4da22b8215138d8b996912bb1532868885f", size = 1951820, upload-time = "2026-04-20T14:42:14.236Z" }, - { url = "https://files.pythonhosted.org/packages/30/b4/d03a7ae14571bc2b6b3c7b122441154720619afe9a336fa3a95434df5e2f/pydantic_core-2.46.3-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1105677a6df914b1fb71a81b96c8cce7726857e1717d86001f29be06a25ee6f8", size = 1977785, upload-time = "2026-04-20T14:42:31.648Z" }, - { url = "https://files.pythonhosted.org/packages/ae/0c/4086f808834b59e3c8f1aa26df8f4b6d998cdcf354a143d18ef41529d1fe/pydantic_core-2.46.3-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:87082cd65669a33adeba5470769e9704c7cf026cc30afb9cc77fd865578ebaad", size = 2062761, upload-time = "2026-04-20T14:40:37.093Z" }, - { url = "https://files.pythonhosted.org/packages/fa/71/a649be5a5064c2df0db06e0a512c2281134ed2fcc981f52a657936a7527c/pydantic_core-2.46.3-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:60e5f66e12c4f5212d08522963380eaaeac5ebd795826cfd19b2dfb0c7a52b9c", size = 2232989, upload-time = "2026-04-20T14:42:59.254Z" }, - { url = "https://files.pythonhosted.org/packages/a2/84/7756e75763e810b3a710f4724441d1ecc5883b94aacb07ca71c5fb5cfb69/pydantic_core-2.46.3-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b6cdf19bf84128d5e7c37e8a73a0c5c10d51103a650ac585d42dd6ae233f2b7f", size = 2303975, upload-time = "2026-04-20T14:41:32.287Z" }, - { url = "https://files.pythonhosted.org/packages/6c/35/68a762e0c1e31f35fa0dac733cbd9f5b118042853698de9509c8e5bf128b/pydantic_core-2.46.3-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:031bb17f4885a43773c8c763089499f242aee2ea85cf17154168775dccdecf35", size = 2095325, upload-time = "2026-04-20T14:42:47.685Z" }, - { url = "https://files.pythonhosted.org/packages/77/bf/1bf8c9a8e91836c926eae5e3e51dce009bf495a60ca56060689d3df3f340/pydantic_core-2.46.3-cp313-cp313-manylinux_2_31_riscv64.whl", hash = "sha256:bcf2a8b2982a6673693eae7348ef3d8cf3979c1d63b54fca7c397a635cc68687", size = 2133368, upload-time = "2026-04-20T14:41:22.766Z" }, - { url = "https://files.pythonhosted.org/packages/e5/50/87d818d6bab915984995157ceb2380f5aac4e563dddbed6b56f0ed057aba/pydantic_core-2.46.3-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:28e8cf2f52d72ced402a137145923a762cbb5081e48b34312f7a0c8f55928ec3", size = 2173908, upload-time = "2026-04-20T14:42:52.044Z" }, - { url = "https://files.pythonhosted.org/packages/91/88/a311fb306d0bd6185db41fa14ae888fb81d0baf648a761ae760d30819d33/pydantic_core-2.46.3-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:17eaface65d9fc5abb940003020309c1bf7a211f5f608d7870297c367e6f9022", size = 2186422, upload-time = "2026-04-20T14:43:29.55Z" }, - { url = "https://files.pythonhosted.org/packages/8f/79/28fd0d81508525ab2054fef7c77a638c8b5b0afcbbaeee493cf7c3fef7e1/pydantic_core-2.46.3-cp313-cp313-musllinux_1_1_armv7l.whl", hash = "sha256:93fd339f23408a07e98950a89644f92c54d8729719a40b30c0a30bb9ebc55d23", size = 2332709, upload-time = "2026-04-20T14:42:16.134Z" }, - { url = "https://files.pythonhosted.org/packages/b3/21/795bf5fe5c0f379308b8ef19c50dedab2e7711dbc8d0c2acf08f1c7daa05/pydantic_core-2.46.3-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:23cbdb3aaa74dfe0837975dbf69b469753bbde8eacace524519ffdb6b6e89eb7", size = 2372428, upload-time = "2026-04-20T14:41:10.974Z" }, - { url = "https://files.pythonhosted.org/packages/45/b3/ed14c659cbe7605e3ef063077680a64680aec81eb1a04763a05190d49b7f/pydantic_core-2.46.3-cp313-cp313-win32.whl", hash = "sha256:610eda2e3838f401105e6326ca304f5da1e15393ae25dacae5c5c63f2c275b13", size = 1965601, upload-time = "2026-04-20T14:41:42.128Z" }, - { url = "https://files.pythonhosted.org/packages/ef/bb/adb70d9a762ddd002d723fbf1bd492244d37da41e3af7b74ad212609027e/pydantic_core-2.46.3-cp313-cp313-win_amd64.whl", hash = "sha256:68cc7866ed863db34351294187f9b729964c371ba33e31c26f478471c52e1ed0", size = 2071517, upload-time = "2026-04-20T14:43:36.096Z" }, - { url = "https://files.pythonhosted.org/packages/52/eb/66faefabebfe68bd7788339c9c9127231e680b11906368c67ce112fdb47f/pydantic_core-2.46.3-cp313-cp313-win_arm64.whl", hash = "sha256:f64b5537ac62b231572879cd08ec05600308636a5d63bcbdb15063a466977bec", size = 2035802, upload-time = "2026-04-20T14:43:38.507Z" }, - { url = "https://files.pythonhosted.org/packages/7f/db/a7bcb4940183fda36022cd18ba8dd12f2dff40740ec7b58ce7457befa416/pydantic_core-2.46.3-cp314-cp314-macosx_10_12_x86_64.whl", hash = "sha256:afa3aa644f74e290cdede48a7b0bee37d1c35e71b05105f6b340d484af536d9b", size = 2097614, upload-time = "2026-04-20T14:44:38.374Z" }, - { url = "https://files.pythonhosted.org/packages/24/35/e4066358a22e3e99519db370494c7528f5a2aa1367370e80e27e20283543/pydantic_core-2.46.3-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:ced3310e51aa425f7f77da8bbbb5212616655bedbe82c70944320bc1dbe5e018", size = 1951896, upload-time = "2026-04-20T14:40:53.996Z" }, - { url = "https://files.pythonhosted.org/packages/87/92/37cf4049d1636996e4b888c05a501f40a43ff218983a551d57f9d5e14f0d/pydantic_core-2.46.3-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e29908922ce9da1a30b4da490bd1d3d82c01dcfdf864d2a74aacee674d0bfa34", size = 1979314, upload-time = "2026-04-20T14:41:49.446Z" }, - { url = "https://files.pythonhosted.org/packages/d8/36/9ff4d676dfbdfb2d591cf43f3d90ded01e15b1404fd101180ed2d62a2fd3/pydantic_core-2.46.3-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:0c9ff69140423eea8ed2d5477df3ba037f671f5e897d206d921bc9fdc39613e7", size = 2056133, upload-time = "2026-04-20T14:42:23.574Z" }, - { url = "https://files.pythonhosted.org/packages/bc/f0/405b442a4d7ba855b06eec8b2bf9c617d43b8432d099dfdc7bf999293495/pydantic_core-2.46.3-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b675ab0a0d5b1c8fdb81195dc5bcefea3f3c240871cdd7ff9a2de8aa50772eb2", size = 2228726, upload-time = "2026-04-20T14:44:22.816Z" }, - { url = "https://files.pythonhosted.org/packages/e7/f8/65cd92dd5a0bd89ba277a98ecbfaf6fc36bbd3300973c7a4b826d6ab1391/pydantic_core-2.46.3-cp314-cp314-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0087084960f209a9a4af50ecd1fb063d9ad3658c07bb81a7a53f452dacbfb2ba", size = 2301214, upload-time = "2026-04-20T14:44:48.792Z" }, - { url = "https://files.pythonhosted.org/packages/fd/86/ef96a4c6e79e7a2d0410826a68fbc0eccc0fd44aa733be199d5fcac3bb87/pydantic_core-2.46.3-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ed42e6cc8e1b0e2b9b96e2276bad70ae625d10d6d524aed0c93de974ae029f9f", size = 2099927, upload-time = "2026-04-20T14:41:40.196Z" }, - { url = "https://files.pythonhosted.org/packages/6d/53/269caf30e0096e0a8a8f929d1982a27b3879872cca2d917d17c2f9fdf4fe/pydantic_core-2.46.3-cp314-cp314-manylinux_2_31_riscv64.whl", hash = "sha256:f1771ce258afb3e4201e67d154edbbae712a76a6081079fe247c2f53c6322c22", size = 2128789, upload-time = "2026-04-20T14:41:15.868Z" }, - { url = "https://files.pythonhosted.org/packages/00/b0/1a6d9b6a587e118482910c244a1c5acf4d192604174132efd12bf0ac486f/pydantic_core-2.46.3-cp314-cp314-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:a7610b6a5242a6c736d8ad47fd5fff87fcfe8f833b281b1c409c3d6835d9227f", size = 2173815, upload-time = "2026-04-20T14:44:25.152Z" }, - { url = "https://files.pythonhosted.org/packages/87/56/e7e00d4041a7e62b5a40815590114db3b535bf3ca0bf4dca9f16cef25246/pydantic_core-2.46.3-cp314-cp314-musllinux_1_1_aarch64.whl", hash = "sha256:ff5e7783bcc5476e1db448bf268f11cb257b1c276d3e89f00b5727be86dd0127", size = 2181608, upload-time = "2026-04-20T14:41:28.933Z" }, - { url = "https://files.pythonhosted.org/packages/e8/22/4bd23c3d41f7c185d60808a1de83c76cf5aeabf792f6c636a55c3b1ec7f9/pydantic_core-2.46.3-cp314-cp314-musllinux_1_1_armv7l.whl", hash = "sha256:9d2e32edcc143bc01e95300671915d9ca052d4f745aa0a49c48d4803f8a85f2c", size = 2326968, upload-time = "2026-04-20T14:42:03.962Z" }, - { url = "https://files.pythonhosted.org/packages/24/ac/66cd45129e3915e5ade3b292cb3bc7fd537f58f8f8dbdaba6170f7cabb74/pydantic_core-2.46.3-cp314-cp314-musllinux_1_1_x86_64.whl", hash = "sha256:6e42d83d1c6b87fa56b521479cff237e626a292f3b31b6345c15a99121b454c1", size = 2369842, upload-time = "2026-04-20T14:41:35.52Z" }, - { url = "https://files.pythonhosted.org/packages/a2/51/dd4248abb84113615473aa20d5545b7c4cd73c8644003b5259686f93996c/pydantic_core-2.46.3-cp314-cp314-win32.whl", hash = "sha256:07bc6d2a28c3adb4f7c6ae46aa4f2d2929af127f587ed44057af50bf1ce0f505", size = 1959661, upload-time = "2026-04-20T14:41:00.042Z" }, - { url = "https://files.pythonhosted.org/packages/20/eb/59980e5f1ae54a3b86372bd9f0fa373ea2d402e8cdcd3459334430f91e91/pydantic_core-2.46.3-cp314-cp314-win_amd64.whl", hash = "sha256:8940562319bc621da30714617e6a7eaa6b98c84e8c685bcdc02d7ed5e7c7c44e", size = 2071686, upload-time = "2026-04-20T14:43:16.471Z" }, - { url = "https://files.pythonhosted.org/packages/8c/db/1cf77e5247047dfee34bc01fa9bca134854f528c8eb053e144298893d370/pydantic_core-2.46.3-cp314-cp314-win_arm64.whl", hash = "sha256:5dcbbcf4d22210ced8f837c96db941bdb078f419543472aca5d9a0bb7cddc7df", size = 2026907, upload-time = "2026-04-20T14:43:31.732Z" }, - { url = "https://files.pythonhosted.org/packages/57/c0/b3df9f6a543276eadba0a48487b082ca1f201745329d97dbfa287034a230/pydantic_core-2.46.3-cp314-cp314t-macosx_10_12_x86_64.whl", hash = "sha256:d0fe3dce1e836e418f912c1ad91c73357d03e556a4d286f441bf34fed2dbeecf", size = 2095047, upload-time = "2026-04-20T14:42:37.982Z" }, - { url = "https://files.pythonhosted.org/packages/66/57/886a938073b97556c168fd99e1a7305bb363cd30a6d2c76086bf0587b32a/pydantic_core-2.46.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:9ce92e58abc722dac1bf835a6798a60b294e48eb0e625ec9fd994b932ac5feee", size = 1934329, upload-time = "2026-04-20T14:43:49.655Z" }, - { url = "https://files.pythonhosted.org/packages/0b/7c/b42eaa5c34b13b07ecb51da21761297a9b8eb43044c864a035999998f328/pydantic_core-2.46.3-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a03e6467f0f5ab796a486146d1b887b2dc5e5f9b3288898c1b1c3ad974e53e4a", size = 1974847, upload-time = "2026-04-20T14:42:10.737Z" }, - { url = "https://files.pythonhosted.org/packages/e6/9b/92b42db6543e7de4f99ae977101a2967b63122d4b6cf7773812da2d7d5b5/pydantic_core-2.46.3-cp314-cp314t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:2798b6ba041b9d70acfb9071a2ea13c8456dd1e6a5555798e41ba7b0790e329c", size = 2041742, upload-time = "2026-04-20T14:40:44.262Z" }, - { url = "https://files.pythonhosted.org/packages/0f/19/46fbe1efabb5aa2834b43b9454e70f9a83ad9c338c1291e48bdc4fecf167/pydantic_core-2.46.3-cp314-cp314t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9be3e221bdc6d69abf294dcf7aff6af19c31a5cdcc8f0aa3b14be29df4bd03b1", size = 2236235, upload-time = "2026-04-20T14:41:27.307Z" }, - { url = "https://files.pythonhosted.org/packages/77/da/b3f95bc009ad60ec53120f5d16c6faa8cabdbe8a20d83849a1f2b8728148/pydantic_core-2.46.3-cp314-cp314t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f13936129ce841f2a5ddf6f126fea3c43cd128807b5a59588c37cf10178c2e64", size = 2282633, upload-time = "2026-04-20T14:44:33.271Z" }, - { url = "https://files.pythonhosted.org/packages/cc/6e/401336117722e28f32fb8220df676769d28ebdf08f2f4469646d404c43a3/pydantic_core-2.46.3-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:28b5f2ef03416facccb1c6ef744c69793175fd27e44ef15669201601cf423acb", size = 2109679, upload-time = "2026-04-20T14:44:41.065Z" }, - { url = "https://files.pythonhosted.org/packages/fc/53/b289f9bc8756a32fe718c46f55afaeaf8d489ee18d1a1e7be1db73f42cc4/pydantic_core-2.46.3-cp314-cp314t-manylinux_2_31_riscv64.whl", hash = "sha256:830d1247d77ad23852314f069e9d7ddafeec5f684baf9d7e7065ed46a049c4e6", size = 2108342, upload-time = "2026-04-20T14:42:50.144Z" }, - { url = "https://files.pythonhosted.org/packages/10/5b/8292fc7c1f9111f1b2b7c1b0dcf1179edcd014fc3ea4517499f50b829d71/pydantic_core-2.46.3-cp314-cp314t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d0793c90c1a3c74966e7975eaef3ed30ebdff3260a0f815a62a22adc17e4c01c", size = 2157208, upload-time = "2026-04-20T14:42:08.133Z" }, - { url = "https://files.pythonhosted.org/packages/2b/9e/f80044e9ec07580f057a89fc131f78dda7a58751ddf52bbe05eaf31db50f/pydantic_core-2.46.3-cp314-cp314t-musllinux_1_1_aarch64.whl", hash = "sha256:d2d0aead851b66f5245ec0c4fb2612ef457f8bbafefdf65a2bf9d6bac6140f47", size = 2167237, upload-time = "2026-04-20T14:42:25.412Z" }, - { url = "https://files.pythonhosted.org/packages/f8/84/6781a1b037f3b96be9227edbd1101f6d3946746056231bf4ac48cdff1a8d/pydantic_core-2.46.3-cp314-cp314t-musllinux_1_1_armv7l.whl", hash = "sha256:2f40e4246676beb31c5ce77c38a55ca4e465c6b38d11ea1bd935420568e0b1ab", size = 2312540, upload-time = "2026-04-20T14:40:40.313Z" }, - { url = "https://files.pythonhosted.org/packages/3e/db/19c0839feeb728e7df03255581f198dfdf1c2aeb1e174a8420b63c5252e5/pydantic_core-2.46.3-cp314-cp314t-musllinux_1_1_x86_64.whl", hash = "sha256:cf489cf8986c543939aeee17a09c04d6ffb43bfef8ca16fcbcc5cfdcbed24dba", size = 2369556, upload-time = "2026-04-20T14:41:09.427Z" }, - { url = "https://files.pythonhosted.org/packages/e0/15/3228774cb7cd45f5f721ddf1b2242747f4eb834d0c491f0c02d606f09fed/pydantic_core-2.46.3-cp314-cp314t-win32.whl", hash = "sha256:ffe0883b56cfc05798bf994164d2b2ff03efe2d22022a2bb080f3b626176dd56", size = 1949756, upload-time = "2026-04-20T14:41:25.717Z" }, - { url = "https://files.pythonhosted.org/packages/b8/2a/c79cf53fd91e5a87e30d481809f52f9a60dd221e39de66455cf04deaad37/pydantic_core-2.46.3-cp314-cp314t-win_amd64.whl", hash = "sha256:706d9d0ce9cf4593d07270d8e9f53b161f90c57d315aeec4fb4fd7a8b10240d8", size = 2051305, upload-time = "2026-04-20T14:43:18.627Z" }, - { url = "https://files.pythonhosted.org/packages/0b/db/d8182a7f1d9343a032265aae186eb063fe26ca4c40f256b21e8da4498e89/pydantic_core-2.46.3-cp314-cp314t-win_arm64.whl", hash = "sha256:77706aeb41df6a76568434701e0917da10692da28cb69d5fb6919ce5fdb07374", size = 2026310, upload-time = "2026-04-20T14:41:01.778Z" }, - { url = "https://files.pythonhosted.org/packages/66/7f/03dbad45cd3aa9083fbc93c210ae8b005af67e4136a14186950a747c6874/pydantic_core-2.46.3-graalpy311-graalpy242_311_native-macosx_10_12_x86_64.whl", hash = "sha256:9715525891ed524a0a1eb6d053c74d4d4ad5017677fb00af0b7c2644a31bae46", size = 2105683, upload-time = "2026-04-20T14:42:19.779Z" }, - { url = "https://files.pythonhosted.org/packages/26/22/4dc186ac8ea6b257e9855031f51b62a9637beac4d68ac06bee02f046f836/pydantic_core-2.46.3-graalpy311-graalpy242_311_native-macosx_11_0_arm64.whl", hash = "sha256:9d2f400712a99a013aff420ef1eb9be077f8189a36c1e3ef87660b4e1088a874", size = 1940052, upload-time = "2026-04-20T14:43:59.274Z" }, - { url = "https://files.pythonhosted.org/packages/0d/ca/d376391a5aff1f2e8188960d7873543608130a870961c2b6b5236627c116/pydantic_core-2.46.3-graalpy311-graalpy242_311_native-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bd2aab0e2e9dc2daf36bd2686c982535d5e7b1d930a1344a7bb6e82baab42a76", size = 1988172, upload-time = "2026-04-20T14:41:17.469Z" }, - { url = "https://files.pythonhosted.org/packages/0e/6b/523b9f85c23788755d6ab949329de692a2e3a584bc6beb67fef5e035aa9d/pydantic_core-2.46.3-graalpy311-graalpy242_311_native-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4e9d76736da5f362fabfeea6a69b13b7f2be405c6d6966f06b2f6bfff7e64531", size = 2128596, upload-time = "2026-04-20T14:40:41.707Z" }, - { url = "https://files.pythonhosted.org/packages/34/42/f426db557e8ab2791bc7562052299944a118655496fbff99914e564c0a94/pydantic_core-2.46.3-graalpy312-graalpy250_312_native-macosx_10_12_x86_64.whl", hash = "sha256:b12dd51f1187c2eb489af8e20f880362db98e954b54ab792fa5d92e8bcc6b803", size = 2091877, upload-time = "2026-04-20T14:43:27.091Z" }, - { url = "https://files.pythonhosted.org/packages/5c/4f/86a832a9d14df58e663bfdf4627dc00d3317c2bd583c4fb23390b0f04b8e/pydantic_core-2.46.3-graalpy312-graalpy250_312_native-macosx_11_0_arm64.whl", hash = "sha256:f00a0961b125f1a47af7bcc17f00782e12f4cd056f83416006b30111d941dfa3", size = 1932428, upload-time = "2026-04-20T14:40:45.781Z" }, - { url = "https://files.pythonhosted.org/packages/11/1a/fe857968954d93fb78e0d4b6df5c988c74c4aaa67181c60be7cfe327c0ca/pydantic_core-2.46.3-graalpy312-graalpy250_312_native-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:57697d7c056aca4bbb680200f96563e841a6386ac1129370a0102592f4dddff5", size = 1997550, upload-time = "2026-04-20T14:44:02.425Z" }, - { url = "https://files.pythonhosted.org/packages/17/eb/9d89ad2d9b0ba8cd65393d434471621b98912abb10fbe1df08e480ba57b5/pydantic_core-2.46.3-graalpy312-graalpy250_312_native-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fd35aa21299def8db7ef4fe5c4ff862941a9a158ca7b63d61e66fe67d30416b4", size = 2137657, upload-time = "2026-04-20T14:42:45.149Z" }, - { url = "https://files.pythonhosted.org/packages/1f/da/99d40830684f81dec901cac521b5b91c095394cc1084b9433393cde1c2df/pydantic_core-2.46.3-pp311-pypy311_pp73-macosx_10_12_x86_64.whl", hash = "sha256:13afdd885f3d71280cf286b13b310ee0f7ccfefd1dbbb661514a474b726e2f25", size = 2107973, upload-time = "2026-04-20T14:42:06.175Z" }, - { url = "https://files.pythonhosted.org/packages/99/a5/87024121818d75bbb2a98ddbaf638e40e7a18b5e0f5492c9ca4b1b316107/pydantic_core-2.46.3-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:f91c0aff3e3ee0928edd1232c57f643a7a003e6edf1860bc3afcdc749cb513f3", size = 1947191, upload-time = "2026-04-20T14:43:14.319Z" }, - { url = "https://files.pythonhosted.org/packages/60/62/0c1acfe10945b83a6a59d19fbaa92f48825381509e5701b855c08f13db76/pydantic_core-2.46.3-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6529d1d128321a58d30afcc97b49e98836542f68dd41b33c2e972bb9e5290536", size = 2123791, upload-time = "2026-04-20T14:43:22.766Z" }, - { url = "https://files.pythonhosted.org/packages/75/3e/3b2393b4c8f44285561dc30b00cf307a56a2eff7c483a824db3b8221ca51/pydantic_core-2.46.3-pp311-pypy311_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:975c267cff4f7e7272eacbe50f6cc03ca9a3da4c4fbd66fffd89c94c1e311aa1", size = 2153197, upload-time = "2026-04-20T14:44:27.932Z" }, - { url = "https://files.pythonhosted.org/packages/ba/75/5af02fb35505051eee727c061f2881c555ab4f8ddb2d42da715a42c9731b/pydantic_core-2.46.3-pp311-pypy311_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:2b8e4f2bbdf71415c544b4b1138b8060db7b6611bc927e8064c769f64bed651c", size = 2181073, upload-time = "2026-04-20T14:43:20.729Z" }, - { url = "https://files.pythonhosted.org/packages/10/92/7e0e1bd9ca3c68305db037560ca2876f89b2647deb2f8b6319005de37505/pydantic_core-2.46.3-pp311-pypy311_pp73-musllinux_1_1_armv7l.whl", hash = "sha256:e61ea8e9fff9606d09178f577ff8ccdd7206ff73d6552bcec18e1033c4254b85", size = 2315886, upload-time = "2026-04-20T14:44:04.826Z" }, - { url = "https://files.pythonhosted.org/packages/b8/d8/101655f27eaf3e44558ead736b2795d12500598beed4683f279396fa186e/pydantic_core-2.46.3-pp311-pypy311_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:b504bda01bafc69b6d3c7a0c7f039dcf60f47fab70e06fe23f57b5c75bdc82b8", size = 2360528, upload-time = "2026-04-20T14:40:47.431Z" }, - { url = "https://files.pythonhosted.org/packages/07/0f/1c34a74c8d07136f0d729ffe5e1fdab04fbdaa7684f61a92f92511a84a15/pydantic_core-2.46.3-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:b00b76f7142fc60c762ce579bd29c8fa44aaa56592dd3c54fab3928d0d4ca6ff", size = 2184144, upload-time = "2026-04-20T14:42:57Z" }, +sdist = { url = "https://files.pythonhosted.org/packages/9d/56/921726b776ace8d8f5db44c4ef961006580d91dc52b803c489fafd1aa249/pydantic_core-2.46.4.tar.gz", hash = "sha256:62f875393d7f270851f20523dd2e29f082bcc82292d66db2b64ea71f64b6e1c1", size = 471464, upload-time = "2026-05-06T13:37:06.98Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e7/08/f1ba952f1c8ae5581c70fa9c6da89f247b83e3dd8c09c035d5d7931fc23d/pydantic_core-2.46.4-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:a396dcc17e5a0b164dbe026896245a4fa9ff402edca1dff0be3d53a517f74de4", size = 2113146, upload-time = "2026-05-06T13:37:36.537Z" }, + { url = "https://files.pythonhosted.org/packages/56/c6/65f646c7ff09bd257f660434adb45c4dfcbbcebcc030562fecf6f5bf887d/pydantic_core-2.46.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:da4b951fe36dc7c3a1ccb4e3cd1747c3542b8c9ceede8fc86cae054e764485f5", size = 1949769, upload-time = "2026-05-06T13:37:46.365Z" }, + { url = "https://files.pythonhosted.org/packages/64/ba/bfb1d928fd5b49e1258935ff104ae356e9fd89384a55bf9f847e9193ad40/pydantic_core-2.46.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bb63e0198ca18aad131c089b9204c23079c3afa95487e561f4c522d519e55aba", size = 1974958, upload-time = "2026-05-06T13:37:28.611Z" }, + { url = "https://files.pythonhosted.org/packages/4e/74/76223bfb117b64af743c9b6670d1364516f5c0604f96b48f3272f6af6cc6/pydantic_core-2.46.4-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:f47286a97f0bc9b8859519809077b91b2cefe4ae47fcbf5e466a009c1c5d742b", size = 2042118, upload-time = "2026-05-06T13:36:55.216Z" }, + { url = "https://files.pythonhosted.org/packages/cb/7b/848732968bc8f48f3187542f08358b9d842db564147b256669426ebb1652/pydantic_core-2.46.4-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:905a0ed8ea6f2d61c1738835f99b699348d7857379083e5fc497fa0c967a407c", size = 2222876, upload-time = "2026-05-06T13:38:25.455Z" }, + { url = "https://files.pythonhosted.org/packages/b5/2f/e90b63ee2e14bd8d3db8f705a6d75d64e6ee1b7c2c8833747ce706e1e0ce/pydantic_core-2.46.4-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ea793e075b70290d89d8142074262885d3f7da19634845135751bd6344f73b50", size = 2286703, upload-time = "2026-05-06T13:37:53.304Z" }, + { url = "https://files.pythonhosted.org/packages/ba/1e/acc4d70f88a0a277e4a1fa77ebb985ceabaf900430f875bf9338e11c9420/pydantic_core-2.46.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:395aebd9183f9d112f569aeb5b2214d1a10a33bec8456447f7fbdfa51d38d4cd", size = 2092042, upload-time = "2026-05-06T13:38:46.981Z" }, + { url = "https://files.pythonhosted.org/packages/a9/da/0a422b57bf8504102bf3c4ccea9c41bab5a5cee6a54650acf8faf67f5a24/pydantic_core-2.46.4-cp310-cp310-manylinux_2_31_riscv64.whl", hash = "sha256:b078afbc25f3a1436c7a1d2cd3e322497ee99615ba97c563566fdf46aff1ee01", size = 2117231, upload-time = "2026-05-06T13:39:23.146Z" }, + { url = "https://files.pythonhosted.org/packages/bd/2a/2ac13c3af305843e23c5078c53d135656b3f05a2fd78cb7bbbb12e97b473/pydantic_core-2.46.4-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:f747929cf940cddb5b3668a390056ddd5ba2e5010615ea2dcf4f9c4f3ab8791d", size = 2168388, upload-time = "2026-05-06T13:40:08.06Z" }, + { url = "https://files.pythonhosted.org/packages/72/04/2beacf7e1607e93eefe4aed1b4709f079b905fb77530179d4f7c71745f22/pydantic_core-2.46.4-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:daa27d92c36f24388fe3ad306b174781c747627f134452e4f128ea00ce1fe8c4", size = 2184769, upload-time = "2026-05-06T13:38:13.901Z" }, + { url = "https://files.pythonhosted.org/packages/9e/29/d2b9fd9f539133548eaf622c06a4ce176cb46ac59f32d0359c4abc0de047/pydantic_core-2.46.4-cp310-cp310-musllinux_1_1_armv7l.whl", hash = "sha256:19e51f073cd3df251856a8a4189fbdf1de4012c3ebacfb1884f94f1eb406079f", size = 2319312, upload-time = "2026-05-06T13:39:08.24Z" }, + { url = "https://files.pythonhosted.org/packages/7c/af/0f7a5b85fec6075bea96e3ef9187de38fccced0de92c1e7feda8d5cc7bb9/pydantic_core-2.46.4-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:c1747f85cee84c26985853c6f3d9bd3e75da5212912443fa111c113b9c246f39", size = 2361817, upload-time = "2026-05-06T13:38:43.2Z" }, + { url = "https://files.pythonhosted.org/packages/25/a4/73363fec545fd3ec025490bdda2743c56d0dd5b6266b1a53bbe9e4265375/pydantic_core-2.46.4-cp310-cp310-win32.whl", hash = "sha256:2f84c03c8607173d16b5a854ec68a2f9079ae03237a54fb506d13af47e1d018d", size = 1987085, upload-time = "2026-05-06T13:39:25.497Z" }, + { url = "https://files.pythonhosted.org/packages/01/aa/62f082da2c91fac1c234bc9ee0066257ce83f0604abd72e4c9d5991f2d84/pydantic_core-2.46.4-cp310-cp310-win_amd64.whl", hash = "sha256:8358a950c8909158e3df31538a7e4edc2d7265a7c54b47f0864d9e5bae9dcebf", size = 2074311, upload-time = "2026-05-06T13:39:59.922Z" }, + { url = "https://files.pythonhosted.org/packages/5c/fa/6d7708d2cfc1a832acb6aeb0cd16e801902df8a0f583bb3b4b527fde022e/pydantic_core-2.46.4-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:0e96592440881c74a213e5ad528e2b24d3d4f940de2766bed9010ab1d9e51594", size = 2111872, upload-time = "2026-05-06T13:40:27.596Z" }, + { url = "https://files.pythonhosted.org/packages/ae/6f/aa064a3e74b5745afbdf250594f38e7ead05e2d651bcb35994b9417a0d4d/pydantic_core-2.46.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:e0d65b8c354be7fb5f720c3caa8bc940bc2d20ce749c8e06135f07f8ed95dd7c", size = 1948255, upload-time = "2026-05-06T13:39:12.574Z" }, + { url = "https://files.pythonhosted.org/packages/43/3a/41114a9f7569b84b4d84e7a018c57c56347dac30c0d4a872946ec4e36c46/pydantic_core-2.46.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7bfb192b3f4b9e8a89b6277b6ce787564f62cfd272055f6e685726b111dc7826", size = 1972827, upload-time = "2026-05-06T13:38:19.841Z" }, + { url = "https://files.pythonhosted.org/packages/ef/25/1ab42e8048fe551934d9884e8d64daa7e990ad386f310a15981aeb6a5b08/pydantic_core-2.46.4-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:9037063db01f09b09e237c282b6792bd4da634b5402c4e7f0c61effed7701a04", size = 2041051, upload-time = "2026-05-06T13:38:10.447Z" }, + { url = "https://files.pythonhosted.org/packages/94/c2/1a934597ddf08da410385b3b7aae91956a5a76c635effef456074fad7e88/pydantic_core-2.46.4-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:fc010ab034c8c7452522748bf937df58020d256ccae0874463d1f4d01758af8e", size = 2221314, upload-time = "2026-05-06T13:40:13.089Z" }, + { url = "https://files.pythonhosted.org/packages/02/6d/9e8ad178c9c4df27ad3c8f25d1fe2a7ab0d2ba0559fad4aee5d3d1f16771/pydantic_core-2.46.4-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8c5dac79fa1614d1e06ca695109c6105923bd9c7d1d6c918d4e637b7e6b32fd3", size = 2285146, upload-time = "2026-05-06T13:38:59.224Z" }, + { url = "https://files.pythonhosted.org/packages/80/50/540cd3aeefc041beb111125c4bff779831a2111fc6b15a9138cda277d32c/pydantic_core-2.46.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f9fa868638bf362d3d138ea55829cefb3d5f4b0d7f142234382a15e2485dbec4", size = 2089685, upload-time = "2026-05-06T13:38:17.762Z" }, + { url = "https://files.pythonhosted.org/packages/6b/a4/b440ad35f05f6a38f89fa0f149accb3f0e02be94ca5e15f3c449a61b4bc9/pydantic_core-2.46.4-cp311-cp311-manylinux_2_31_riscv64.whl", hash = "sha256:17299feefe090f2caa5b8e37222bb5f663e4935a8bfa6931d4102e5df1a9f398", size = 2115420, upload-time = "2026-05-06T13:37:58.195Z" }, + { url = "https://files.pythonhosted.org/packages/99/61/de4f55db8dfd57bfdfa9a12ec90fe1b57c4f41062f7ca86f08586b3e0ac0/pydantic_core-2.46.4-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:4c63ebc82684aa89d9a3bcbd13d515b3be44250dc68dd3bd81526c1cb31286c3", size = 2165122, upload-time = "2026-05-06T13:37:01.167Z" }, + { url = "https://files.pythonhosted.org/packages/f7/52/7c529d7bdb2d1068bd52f51fe32572c8301f9a4febf1948f10639f1436f5/pydantic_core-2.46.4-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:aaa2a54443eff1950ba5ddc6b6ccda0d9c84a364276a62f969bdf2a390650848", size = 2182573, upload-time = "2026-05-06T13:38:45.04Z" }, + { url = "https://files.pythonhosted.org/packages/37/b3/7c40325848ba78247f2812dcf9c7274e38cd801820ca6dd9fe63bcfb0eb4/pydantic_core-2.46.4-cp311-cp311-musllinux_1_1_armv7l.whl", hash = "sha256:18e5ceec2ab67e6d5f1a9085e5a24c9c4e2ac4545730bfe668680bca05e555f3", size = 2317139, upload-time = "2026-05-06T13:37:15.539Z" }, + { url = "https://files.pythonhosted.org/packages/d9/37/f913f81a657c865b75da6c0dbed79876073c2a43b5bd9edbe8da785e4d49/pydantic_core-2.46.4-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:a0f62d0a58f4e7da165457e995725421e0064f2255d8eccebc49f41bbc23b109", size = 2360433, upload-time = "2026-05-06T13:37:30.099Z" }, + { url = "https://files.pythonhosted.org/packages/c4/67/6acaa1be2567f9256b056d8477158cac7240813956ce86e49deae8e173b4/pydantic_core-2.46.4-cp311-cp311-win32.whl", hash = "sha256:041bde0a48fd37cf71cab1c9d56d3e8625a3793fef1f7dd232b3ff37e978ecda", size = 1985513, upload-time = "2026-05-06T13:38:15.669Z" }, + { url = "https://files.pythonhosted.org/packages/aa/e6/c505f83dfeda9a2e5c995cfd872949e4d05e12f7feb3dca72f633daefa94/pydantic_core-2.46.4-cp311-cp311-win_amd64.whl", hash = "sha256:6f2eeda33a839975441c86a4119e1383c50b47faf0cbb5176985565c6bb02c33", size = 2071114, upload-time = "2026-05-06T13:40:35.416Z" }, + { url = "https://files.pythonhosted.org/packages/0f/da/7a263a96d965d9d0df5e8de8a475f33495451117035b09acb110288c381f/pydantic_core-2.46.4-cp311-cp311-win_arm64.whl", hash = "sha256:14f4c5d6db102bd796a627bbb3a17b4cf4574b9ae861d8b7c9a9661c6dd3362d", size = 2044298, upload-time = "2026-05-06T13:38:29.754Z" }, + { url = "https://files.pythonhosted.org/packages/ce/8c/af022f0af448d7747c5154288d46b5f2bc5f17366eaa0e23e9aa04d59f3b/pydantic_core-2.46.4-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:3245406455a5d98187ec35530fd772b1d799b26667980872c8d4614991e2c4a2", size = 2106158, upload-time = "2026-05-06T13:38:57.215Z" }, + { url = "https://files.pythonhosted.org/packages/19/95/6195171e385007300f0f5574592e467c568becce2d937a0b6804f218bc49/pydantic_core-2.46.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:962ccbab7b642487b1d8b7df90ef677e03134cf1fd8880bf698649b22a69371f", size = 1951724, upload-time = "2026-05-06T13:37:02.697Z" }, + { url = "https://files.pythonhosted.org/packages/8e/bc/f47d1ff9cbb1620e1b5b697eef06010035735f07820180e74178226b27b3/pydantic_core-2.46.4-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8233f2947cf85404441fd7e0085f53b10c93e0ee78611099b5c7237e36aacbf7", size = 1975742, upload-time = "2026-05-06T13:37:09.448Z" }, + { url = "https://files.pythonhosted.org/packages/5b/11/9b9a5b0306345664a2da6410877af6e8082481b5884b3ddd78d47c6013ce/pydantic_core-2.46.4-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:3a233125ac121aa3ffba9a2b59edfc4a985a76092dc8279586ab4b71390875e7", size = 2052418, upload-time = "2026-05-06T13:37:38.234Z" }, + { url = "https://files.pythonhosted.org/packages/f1/b7/a65fec226f5d78fc39f4a13c4cc0c768c22b113438f60c14adc9d2865038/pydantic_core-2.46.4-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5b712b53160b79a5850310b912a5ef8e57e56947c8ad690c227f5c9d7e561712", size = 2232274, upload-time = "2026-05-06T13:38:27.753Z" }, + { url = "https://files.pythonhosted.org/packages/68/f0/92039db98b907ef49269a8271f67db9cb78ae2fc68062ef7e4e77adb5f61/pydantic_core-2.46.4-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9401557acd873c3a7f3eb9383edef8ac4968f9510e340f4808d427e75667e7b4", size = 2309940, upload-time = "2026-05-06T13:38:05.353Z" }, + { url = "https://files.pythonhosted.org/packages/5f/97/2aab507d3d00ca626e8e57c1eac6a79e4e5fbcc63eb99733ff55d1717f65/pydantic_core-2.46.4-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:926c9541b14b12b1681dca8a0b75feb510b06c6341b70a8e500c2fdcff837cce", size = 2094516, upload-time = "2026-05-06T13:39:10.577Z" }, + { url = "https://files.pythonhosted.org/packages/22/37/a8aca44d40d737dde2bc05b3c6c07dff0de07ce6f82e9f3167aeaf4d5dea/pydantic_core-2.46.4-cp312-cp312-manylinux_2_31_riscv64.whl", hash = "sha256:56cb4851bcaf3d117eddcef4fe66afd750a50274b0da8e22be256d10e5611987", size = 2136854, upload-time = "2026-05-06T13:40:22.59Z" }, + { url = "https://files.pythonhosted.org/packages/24/99/fcef1b79238c06a8cbec70819ac722ba76e02bc8ada9b0fd66eba40da01b/pydantic_core-2.46.4-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:c68fcd102d71ea85c5b2dfac3f4f8476eff42a9e078fd5faefff6d145063536b", size = 2180306, upload-time = "2026-05-06T13:40:10.666Z" }, + { url = "https://files.pythonhosted.org/packages/ae/6c/fc44000918855b42779d007ae63b0532794739027b2f417321cddbc44f6a/pydantic_core-2.46.4-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:b2f69dec1725e79a012d920df1707de5caf7ed5e08f3be4435e25803efc47458", size = 2190044, upload-time = "2026-05-06T13:40:43.231Z" }, + { url = "https://files.pythonhosted.org/packages/6b/65/d9cadc9f1920d7a127ad2edba16c1db7916e59719285cd6c94600b0080ba/pydantic_core-2.46.4-cp312-cp312-musllinux_1_1_armv7l.whl", hash = "sha256:8d0820e8192167f80d88d64038e609c31452eeca865b4e1d9950a27a4609b00b", size = 2329133, upload-time = "2026-05-06T13:39:57.365Z" }, + { url = "https://files.pythonhosted.org/packages/d0/cf/c873d91679f3a30bcf5e7ac280ce5573483e72295307685120d0d5ad3416/pydantic_core-2.46.4-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:fbdb89b3e1c94a30cc5edfce477c6e6a5dc4d8f84665b455c27582f211a1c72c", size = 2374464, upload-time = "2026-05-06T13:38:06.976Z" }, + { url = "https://files.pythonhosted.org/packages/47/bd/6f2fc8188f31bf10590f1e98e7b306336161fac930a8c514cd7bd828c7dc/pydantic_core-2.46.4-cp312-cp312-win32.whl", hash = "sha256:9aa768456404a8bf48a4406685ac2bec8e72b62c69313734fa3b73cf33b3a894", size = 1974823, upload-time = "2026-05-06T13:40:47.985Z" }, + { url = "https://files.pythonhosted.org/packages/40/8c/985c1d41ea1107c2534abd9870e4ed5c8e7669b5c308297835c001e7a1c4/pydantic_core-2.46.4-cp312-cp312-win_amd64.whl", hash = "sha256:e9c26f834c65f5752f3f06cb08cb86a913ceb7274d0db6e267808a708b46bc89", size = 2072919, upload-time = "2026-05-06T13:39:21.153Z" }, + { url = "https://files.pythonhosted.org/packages/c4/ba/f463d006e0c47373ca7ec5e1a261c59dc01ef4d62b2657af925fb0deee3a/pydantic_core-2.46.4-cp312-cp312-win_arm64.whl", hash = "sha256:4fc73cb559bdb54b1134a706a2802a4cddd27a0633f5abb7e53056268751ac6a", size = 2027604, upload-time = "2026-05-06T13:39:03.753Z" }, + { url = "https://files.pythonhosted.org/packages/51/a2/5d30b469c5267a17b39dec53208222f76a8d351dfac4af661888c5aee77d/pydantic_core-2.46.4-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:5d5902252db0d3cedf8d4a1bc68f70eeb430f7e4c7104c8c476753519b423008", size = 2106306, upload-time = "2026-05-06T13:37:48.029Z" }, + { url = "https://files.pythonhosted.org/packages/c1/81/4fa520eaffa8bd7d1525e644cd6d39e7d60b1592bc5b516693c7340b50f1/pydantic_core-2.46.4-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:c94f0688e7b8d0a67abf40e57a7eaaecd17cc9586706a31b76c031f63df052b4", size = 1951906, upload-time = "2026-05-06T13:37:17.012Z" }, + { url = "https://files.pythonhosted.org/packages/03/d5/fd02da45b659668b05923b17ba3a0100a0a3d5541e3bd8fcc4ecb711309e/pydantic_core-2.46.4-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f027324c56cd5406ca49c124b0db10e56c69064fec039acc571c29020cc87c76", size = 1976802, upload-time = "2026-05-06T13:37:35.113Z" }, + { url = "https://files.pythonhosted.org/packages/21/f2/95727e1368be3d3ed485eaab7adbd7dda408f33f7a36e8b48e0144002b91/pydantic_core-2.46.4-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e739fee756ba1010f8bcccb534252e85a35fe45ae92c295a06059ce58b74ccd3", size = 2052446, upload-time = "2026-05-06T13:37:12.313Z" }, + { url = "https://files.pythonhosted.org/packages/9c/86/5d99feea3f77c7234b8718075b23db11532773c1a0dbd9b9490215dc2eeb/pydantic_core-2.46.4-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9d56801be94b86a9da183e5f3766e6310752b99ff647e38b09a9500d88e46e76", size = 2232757, upload-time = "2026-05-06T13:39:01.149Z" }, + { url = "https://files.pythonhosted.org/packages/d2/3a/508ac615935ef7588cf6d9e9b91309fdc2da751af865e02a9098de88258c/pydantic_core-2.46.4-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2412e734dcb48da14d4e4006b82b46b74f2518b8a26ee7e58c6844a6cd6d03c4", size = 2309275, upload-time = "2026-05-06T13:37:41.406Z" }, + { url = "https://files.pythonhosted.org/packages/07/f8/41db9de19d7987d6b04715a02b3b40aea467000275d9d758ffaa31af7d50/pydantic_core-2.46.4-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9551187363ffc0de2a00b2e47c25aeaeb1020b69b668762966df15fc5659dd5a", size = 2094467, upload-time = "2026-05-06T13:39:18.847Z" }, + { url = "https://files.pythonhosted.org/packages/2c/e2/f35033184cb11d0052daf4416e8e10a502ea2ac006fc4f459aee872727d1/pydantic_core-2.46.4-cp313-cp313-manylinux_2_31_riscv64.whl", hash = "sha256:0186750b482eefa11d7f435892b09c5c606193ef3375bcf94aa00ae6bfb66262", size = 2134417, upload-time = "2026-05-06T13:40:17.944Z" }, + { url = "https://files.pythonhosted.org/packages/7e/7b/6ceeb1cc90e193862f444ebe373d8fdf613f0a82572dde03fb10734c6c71/pydantic_core-2.46.4-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:5855698a4856556d86e8e6cd8434bc3ac0314ee8e12089ae0e143f64c6256e4e", size = 2179782, upload-time = "2026-05-06T13:40:32.618Z" }, + { url = "https://files.pythonhosted.org/packages/5a/f2/c8d7773ede6af08036423a00ae0ceffce266c3c52a096c435d68c896083f/pydantic_core-2.46.4-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:cbaf13819775b7f769bf4a1f066cb6df7a28d4480081a589828ef190226881cd", size = 2188782, upload-time = "2026-05-06T13:36:51.018Z" }, + { url = "https://files.pythonhosted.org/packages/59/31/0c864784e31f09f05cdd87606f08923b9c9e7f6e51dd27f20f62f975ce9f/pydantic_core-2.46.4-cp313-cp313-musllinux_1_1_armv7l.whl", hash = "sha256:633147d34cf4550417f12e2b1a0383973bdf5cdfde212cb09e9a581cf10820be", size = 2328334, upload-time = "2026-05-06T13:40:37.764Z" }, + { url = "https://files.pythonhosted.org/packages/c2/eb/4f6c8a41efa30baa755590f4141abf3a8c370fab610915733e74134a7270/pydantic_core-2.46.4-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:82cf5301172168103724d49a1444d3378cb20cdee30b116a1bd6031236298a5d", size = 2372986, upload-time = "2026-05-06T13:39:34.152Z" }, + { url = "https://files.pythonhosted.org/packages/5b/24/b375a480d53113860c299764bfe9f349a3dc9108b3adc0d7f0d786492ebf/pydantic_core-2.46.4-cp313-cp313-win32.whl", hash = "sha256:9fa8ae11da9e2b3126c6426f147e0fba88d96d65921799bb30c6abd1cb2c97fb", size = 1973693, upload-time = "2026-05-06T13:37:55.072Z" }, + { url = "https://files.pythonhosted.org/packages/7e/e8/cff247591966f2d22ec8c003cd7587e27b7ba7b81ab2fb888e3ab75dc285/pydantic_core-2.46.4-cp313-cp313-win_amd64.whl", hash = "sha256:6b3ace8194b0e5204818c92802dcdca7fc6d88aabbb799d7c795540d9cd6d292", size = 2071819, upload-time = "2026-05-06T13:38:49.139Z" }, + { url = "https://files.pythonhosted.org/packages/c6/1a/f4aee670d5670e9e148e0c82c7db98d780be566c6e6a97ee8035528ca0b3/pydantic_core-2.46.4-cp313-cp313-win_arm64.whl", hash = "sha256:184c081504d17f1c1066e430e117142b2c77d9448a97f7b65c6ac9fd9aee238d", size = 2027411, upload-time = "2026-05-06T13:40:45.796Z" }, + { url = "https://files.pythonhosted.org/packages/8d/74/228a26ddad29c6672b805d9fd78e8d251cd04004fa7eed0e622096cd0250/pydantic_core-2.46.4-cp314-cp314-macosx_10_12_x86_64.whl", hash = "sha256:428e04521a40150c85216fc8b85e8d39fece235a9cf5e383761238c7fa9b96fb", size = 2102079, upload-time = "2026-05-06T13:38:41.019Z" }, + { url = "https://files.pythonhosted.org/packages/ad/1f/8970b150a4b4365623ae00fc88603491f763c627311ae8031e3111356d6e/pydantic_core-2.46.4-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:23ace664830ee0bfe014a0c7bc248b1f7f25ed7ad103852c317624a1083af462", size = 1952179, upload-time = "2026-05-06T13:36:59.812Z" }, + { url = "https://files.pythonhosted.org/packages/95/30/5211a831ae054928054b2f79731661087a2bc5c01e825c672b3a4a8f1b3e/pydantic_core-2.46.4-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ce5c1d2a8b27468f433ca974829c44060b8097eedc39933e3c206a90ee49c4a9", size = 1978926, upload-time = "2026-05-06T13:37:39.933Z" }, + { url = "https://files.pythonhosted.org/packages/57/e9/689668733b1eb67adeef047db3c2e8788fcf65a7fd9c9e2b46b7744fe245/pydantic_core-2.46.4-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:7283d57845ecf5a163403eb0702dfc220cc4fbdd18919cb5ccea4f95ee1cdab4", size = 2046785, upload-time = "2026-05-06T13:38:01.995Z" }, + { url = "https://files.pythonhosted.org/packages/60/d9/6715260422ff50a2109878fd24d948a6c3446bb2664f34ee78cd972b3acd/pydantic_core-2.46.4-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8daafc69c93ee8a0204506a3b6b30f586ef54028f52aeeeb5c4cfc5184fd5914", size = 2228733, upload-time = "2026-05-06T13:40:50.371Z" }, + { url = "https://files.pythonhosted.org/packages/18/ae/fdb2f64316afca925640f8e70bb1a564b0ec2721c1389e25b8eb4bf9a299/pydantic_core-2.46.4-cp314-cp314-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cd2213145bcc2ba85884d0ac63d222fece9209678f77b9b4d76f054c561adb28", size = 2307534, upload-time = "2026-05-06T13:37:21.531Z" }, + { url = "https://files.pythonhosted.org/packages/89/1d/8eff589b45bb8190a9d12c49cfad0f176a5cbd1534908a6b5125e2886239/pydantic_core-2.46.4-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7a5f930472650a82629163023e630d160863fce524c616f4e5186e5de9d9a49b", size = 2099732, upload-time = "2026-05-06T13:39:31.942Z" }, + { url = "https://files.pythonhosted.org/packages/06/d5/ee5a3366637fee41dee51a1fc91562dcf12ddbc68fda34e6b253da2324bb/pydantic_core-2.46.4-cp314-cp314-manylinux_2_31_riscv64.whl", hash = "sha256:c1b3f518abeca3aa13c712fd202306e145abf59a18b094a6bafb2d2bbf59192c", size = 2129627, upload-time = "2026-05-06T13:37:25.033Z" }, + { url = "https://files.pythonhosted.org/packages/94/33/2414be571d2c6a6c4d08be21f9292b6d3fdb08949a97b6dfe985017821db/pydantic_core-2.46.4-cp314-cp314-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:1a7dd0b3ee80d90150e3495a3a13ac34dbcbfd4f012996a6a1d8900e91b5c0fb", size = 2179141, upload-time = "2026-05-06T13:37:14.046Z" }, + { url = "https://files.pythonhosted.org/packages/7b/79/7daa95be995be0eecc4cf75064cb33f9bbbfe3fe0158caf2f0d4a996a5c7/pydantic_core-2.46.4-cp314-cp314-musllinux_1_1_aarch64.whl", hash = "sha256:3fb702cd90b0446a3a1c5e470bfa0dd23c0233b676a9099ddcc964fa6ca13898", size = 2184325, upload-time = "2026-05-06T13:36:53.615Z" }, + { url = "https://files.pythonhosted.org/packages/9f/cb/d0a382f5c0de8a222dc61c65348e0ce831b1f68e0a018450d31c2cace3a5/pydantic_core-2.46.4-cp314-cp314-musllinux_1_1_armv7l.whl", hash = "sha256:b8458003118a712e66286df6a707db01c52c0f52f7db8e4a38f0da1d3b94fc4e", size = 2323990, upload-time = "2026-05-06T13:40:29.971Z" }, + { url = "https://files.pythonhosted.org/packages/05/db/d9ba624cc4a5aced1598e88c04fdbd8310c8a69b9d38b9a3d39ce3a61ed7/pydantic_core-2.46.4-cp314-cp314-musllinux_1_1_x86_64.whl", hash = "sha256:372429a130e469c9cd698925ce5fc50940b7a1336b0d82038e63d5bbc4edc519", size = 2369978, upload-time = "2026-05-06T13:37:23.027Z" }, + { url = "https://files.pythonhosted.org/packages/f2/20/d15df15ba918c423461905802bfd2981c3af0bfa0e40d05e13edbfa48bc3/pydantic_core-2.46.4-cp314-cp314-win32.whl", hash = "sha256:85bb3611ff1802f3ee7fdd7dbff26b56f343fb432d57a4728fdd49b6ef35e2f4", size = 1966354, upload-time = "2026-05-06T13:38:03.499Z" }, + { url = "https://files.pythonhosted.org/packages/fc/b6/6b8de4c0a7d7ab3004c439c80c5c1e0a3e8d78bbae19379b01960383d9e5/pydantic_core-2.46.4-cp314-cp314-win_amd64.whl", hash = "sha256:811ff8e9c313ab425368bcbb36e5c4ebd7108c2bbf4e4089cfbb0b01eff63fac", size = 2072238, upload-time = "2026-05-06T13:39:40.807Z" }, + { url = "https://files.pythonhosted.org/packages/32/36/51eb763beec1f4cf59b1db243a7dcc39cbb41230f050a09b9d69faaf0a48/pydantic_core-2.46.4-cp314-cp314-win_arm64.whl", hash = "sha256:bfec22eab3c8cc2ceec0248aec886624116dc079afa027ecc8ad4a7e62010f8a", size = 2018251, upload-time = "2026-05-06T13:37:26.72Z" }, + { url = "https://files.pythonhosted.org/packages/e8/91/855af51d625b23aa987116a19e231d2aaef9c4a415273ddc189b79a45fee/pydantic_core-2.46.4-cp314-cp314t-macosx_10_12_x86_64.whl", hash = "sha256:af8244b2bef6aaad6d92cda81372de7f8c8d36c9f0c3ea36e827c60e7d9467a0", size = 2099593, upload-time = "2026-05-06T13:39:47.682Z" }, + { url = "https://files.pythonhosted.org/packages/fb/1b/8784a54c65edb5f49f0a14d6977cf1b209bba85a4c77445b255c2de58ab3/pydantic_core-2.46.4-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:5a4330cdbc57162e4b3aa303f588ba752257694c9c9be3e7ebb11b4aca659b5d", size = 1935226, upload-time = "2026-05-06T13:40:40.428Z" }, + { url = "https://files.pythonhosted.org/packages/e8/e7/1955d28d1afc56dd4b3ad7cc0cf39df1b9852964cf16e5d13912756d6d6b/pydantic_core-2.46.4-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:29c61fc04a3d840155ff08e475a04809278972fe6aef51e2720554e96367e34b", size = 1974605, upload-time = "2026-05-06T13:37:32.029Z" }, + { url = "https://files.pythonhosted.org/packages/93/e2/3fedbf0ba7a22850e6e9fd78117f1c0f10f950182344d8a6c535d468fdd8/pydantic_core-2.46.4-cp314-cp314t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:c50f2528cf200c5eed56faf3f4e22fcd5f38c157a8b78576e6ba3168ec35f000", size = 2030777, upload-time = "2026-05-06T13:38:55.239Z" }, + { url = "https://files.pythonhosted.org/packages/f8/61/46be275fcaaba0b4f5b9669dd852267ce1ff616592dccf7a7845588df091/pydantic_core-2.46.4-cp314-cp314t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0cbe8b01f948de4286c74cdd6c667aceb38f5c1e26f0693b3983d9d74887c65e", size = 2236641, upload-time = "2026-05-06T13:37:08.096Z" }, + { url = "https://files.pythonhosted.org/packages/60/db/12e93e46a8bac9988be3c016860f83293daea8c716c029c9ace279036f2f/pydantic_core-2.46.4-cp314-cp314t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:617d7e2ca7dcb8c5cf6bcb8c59b8832c94b36196bbf1cbd1bfb56ed341905edd", size = 2286404, upload-time = "2026-05-06T13:40:20.221Z" }, + { url = "https://files.pythonhosted.org/packages/e2/4a/4d8b19008f38d31c53b8219cfedc2e3d5de5fe99d90076b7e767de29274f/pydantic_core-2.46.4-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7027560ee92211647d0d34e3f7cd6f50da56399d26a9c8ad0da286d3869a53f3", size = 2109219, upload-time = "2026-05-06T13:38:12.153Z" }, + { url = "https://files.pythonhosted.org/packages/88/70/3cbc40978fefb7bb09c6708d40d4ad1a5d70fd7213c3d17f971de868ec1f/pydantic_core-2.46.4-cp314-cp314t-manylinux_2_31_riscv64.whl", hash = "sha256:f99626688942fb746e545232e7726926f3be91b5975f8b55327665fafda991c7", size = 2110594, upload-time = "2026-05-06T13:40:02.971Z" }, + { url = "https://files.pythonhosted.org/packages/9d/20/b8d36736216e29491125531685b2f9e61aa5b4b2599893f8268551da3338/pydantic_core-2.46.4-cp314-cp314t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:fc3e9034a63de20e15e8ade85358bc6efc614008cab72898b4b4952bea0509ff", size = 2159542, upload-time = "2026-05-06T13:39:27.506Z" }, + { url = "https://files.pythonhosted.org/packages/1d/a2/367df868eb584dacf6bf82a389272406d7178e301c4ac82545ab98bc2dd9/pydantic_core-2.46.4-cp314-cp314t-musllinux_1_1_aarch64.whl", hash = "sha256:97e7cf2be5c77b7d1a9713a05605d49460d02c6078d38d8bef3cbe323c548424", size = 2168146, upload-time = "2026-05-06T13:38:31.93Z" }, + { url = "https://files.pythonhosted.org/packages/c1/b8/4460f77f7e201893f649a29ab355dddd3beee8a97bcb1a320db414f9a06e/pydantic_core-2.46.4-cp314-cp314t-musllinux_1_1_armv7l.whl", hash = "sha256:3bf92c5d0e00fefaab325a4d27828fe6b6e2a21848686b5b60d2d9eeb09d76c6", size = 2306309, upload-time = "2026-05-06T13:37:44.717Z" }, + { url = "https://files.pythonhosted.org/packages/64/c4/be2639293acd87dc8ddbcec41a73cee9b2ebf996fe6d892a1a74e88ad3f7/pydantic_core-2.46.4-cp314-cp314t-musllinux_1_1_x86_64.whl", hash = "sha256:3ecbc122d18468d06ca279dc26a8c2e2d5acb10943bb35e36ae92096dc3b5565", size = 2369736, upload-time = "2026-05-06T13:37:05.645Z" }, + { url = "https://files.pythonhosted.org/packages/30/a6/9f9f380dbb301f67023bf8f707aaa75daadf84f7152d95c410fd7e81d994/pydantic_core-2.46.4-cp314-cp314t-win32.whl", hash = "sha256:e846ae7835bf0703ae43f534ab79a867146dadd59dc9ca5c8b53d5c8f7c9ef02", size = 1955575, upload-time = "2026-05-06T13:38:51.116Z" }, + { url = "https://files.pythonhosted.org/packages/40/1f/f1eb9eb350e795d1af8586289746f5c5677d16043040d63710e22abc43c9/pydantic_core-2.46.4-cp314-cp314t-win_amd64.whl", hash = "sha256:2108ba5c1c1eca18030634489dc544844144ee36357f2f9f780b93e7ddbb44b5", size = 2051624, upload-time = "2026-05-06T13:38:21.672Z" }, + { url = "https://files.pythonhosted.org/packages/f6/d2/42dd53d0a85c27606f316d3aa5d2869c4e8470a5ed6dec30e4a1abe19192/pydantic_core-2.46.4-cp314-cp314t-win_arm64.whl", hash = "sha256:4fcbe087dbc2068af7eda3aa87634eba216dbda64d1ae73c8684b621d33f6596", size = 2017325, upload-time = "2026-05-06T13:40:52.723Z" }, + { url = "https://files.pythonhosted.org/packages/ee/a4/73995fd4ebbb46ba0ee51e6fa049b8f02c40daebb762208feda8a6b7894d/pydantic_core-2.46.4-graalpy311-graalpy242_311_native-macosx_10_12_x86_64.whl", hash = "sha256:14d4edf427bdcf950a8a02d7cb44a08614388dd6e1bdcbf4f67504fa7887da9c", size = 2111589, upload-time = "2026-05-06T13:37:10.817Z" }, + { url = "https://files.pythonhosted.org/packages/fb/7f/f37d3a5e8bfcc2e403f5c57a730f2d815693fb42119e8ea48b3789335af1/pydantic_core-2.46.4-graalpy311-graalpy242_311_native-macosx_11_0_arm64.whl", hash = "sha256:0ce40cd7b21210e99342afafbd4d0f76d784eb5b1d60f3bdc566be4983c6c73b", size = 1944552, upload-time = "2026-05-06T13:36:56.717Z" }, + { url = "https://files.pythonhosted.org/packages/15/3c/d7eb777b3ff43e8433a4efb39a17aa8fd98a4ee8561a24a67ef5db07b2d6/pydantic_core-2.46.4-graalpy311-graalpy242_311_native-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:90884113d8b48f760e9587002789ddd741e76ab9f89518cd1e43b1f1a52ec44b", size = 1982984, upload-time = "2026-05-06T13:39:06.207Z" }, + { url = "https://files.pythonhosted.org/packages/63/87/70b9f40170a81afd55ca26c9b2acb25c20d64bcfbf888fafecb3ba077d4c/pydantic_core-2.46.4-graalpy311-graalpy242_311_native-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:66ce7632c22d837c95301830e111ad0128a32b8207533b60896a96c4915192ea", size = 2138417, upload-time = "2026-05-06T13:39:45.476Z" }, + { url = "https://files.pythonhosted.org/packages/9d/1d/8987ad40f65ae1432753072f214fb5c74fe47ffbd0698bb9cbbb585664f8/pydantic_core-2.46.4-graalpy312-graalpy250_312_native-macosx_10_12_x86_64.whl", hash = "sha256:1d8ba486450b14f3b1d63bc521d410ec7565e52f887b9fb671791886436a42f7", size = 2095527, upload-time = "2026-05-06T13:39:52.283Z" }, + { url = "https://files.pythonhosted.org/packages/64/d3/84c282a7eee1d3ac4c0377546ef5a1ea436ce26840d9ac3b7ed54a377507/pydantic_core-2.46.4-graalpy312-graalpy250_312_native-macosx_11_0_arm64.whl", hash = "sha256:3009f12e4e90b7f88b4f9adb1b0c4a3d58fe7820f3238c190047209d148026df", size = 1936024, upload-time = "2026-05-06T13:40:15.671Z" }, + { url = "https://files.pythonhosted.org/packages/d7/ca/eac61596cdeb4d7e174d3dc0bd8a6238f14f75f97a24e7b7db4c7e7340a0/pydantic_core-2.46.4-graalpy312-graalpy250_312_native-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ad785e92e6dc634c21555edc8bd6b64957ab844541bcb96a1366c202951ae526", size = 1990696, upload-time = "2026-05-06T13:38:34.717Z" }, + { url = "https://files.pythonhosted.org/packages/fa/c3/7c8b240552251faf6b3a957db200fcfbbcec36763c050428b601e0c9b83b/pydantic_core-2.46.4-graalpy312-graalpy250_312_native-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:00c603d540afdd6b80eb39f078f33ebd46211f02f33e34a32d9f053bba711de0", size = 2147590, upload-time = "2026-05-06T13:39:29.883Z" }, + { url = "https://files.pythonhosted.org/packages/11/cb/428de0385b6c8d44b716feba566abfacfbd23ee3c4439faa789a1456242f/pydantic_core-2.46.4-pp311-pypy311_pp73-macosx_10_12_x86_64.whl", hash = "sha256:0c563b08bca408dc7f65f700633d8442fffb2421fc47b8101377e9fd65051ff0", size = 2112782, upload-time = "2026-05-06T13:37:04.016Z" }, + { url = "https://files.pythonhosted.org/packages/0b/b5/6a17bdadd0fc1f170adfd05a20d37c832f52b117b4d9131da1f41bb097ce/pydantic_core-2.46.4-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:db06ffe51636ffe9ca531fe9023dd64bdd794be8754cb5df57c5498ae5b518a7", size = 1952146, upload-time = "2026-05-06T13:39:43.092Z" }, + { url = "https://files.pythonhosted.org/packages/2a/dc/03734d80e362cd43ef65428e9de77c730ce7f2f11c60d2b1e1b39f0fbf99/pydantic_core-2.46.4-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:133878133d271ade3d41d1bfb2a45ec38dbdbda40bc065921c6b04e4630127e2", size = 2134492, upload-time = "2026-05-06T13:36:58.124Z" }, + { url = "https://files.pythonhosted.org/packages/de/df/5e5ffc085ed07cc22d298134d3d911c63e91f6a0eb91fe646750a3209910/pydantic_core-2.46.4-pp311-pypy311_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:9bc519fbf2b7578398853d815009ae5e4d4603d12f4e3f91da8c06852d3da3e9", size = 2156604, upload-time = "2026-05-06T13:37:49.88Z" }, + { url = "https://files.pythonhosted.org/packages/81/44/6e112a4253e56f5705467cbab7ab5e91ee7398ba3d56d358635958893d3e/pydantic_core-2.46.4-pp311-pypy311_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:c7a7bd4e39e8e4c12c39cd480356842b6a8a06e41b23a55a5e3e191718838ddf", size = 2183828, upload-time = "2026-05-06T13:37:43.053Z" }, + { url = "https://files.pythonhosted.org/packages/ac/ad/5565071e937d8e752842ac241463944c9eb14c87e2d269f2658a5bd05e98/pydantic_core-2.46.4-pp311-pypy311_pp73-musllinux_1_1_armv7l.whl", hash = "sha256:d396ec2b979760aaf3218e76c24e65bd0aca24983298653b3a9d7a45f9e47b30", size = 2310000, upload-time = "2026-05-06T13:37:56.694Z" }, + { url = "https://files.pythonhosted.org/packages/4f/c3/66883a5cec183e7fba4d024b4cbbe61851a63750ef606b0afecc46d1f2bf/pydantic_core-2.46.4-pp311-pypy311_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:86e1a4418c6cd97d60c95c71164158eaf7324fae7b0923264016baa993eba6fc", size = 2361286, upload-time = "2026-05-06T13:40:05.667Z" }, + { url = "https://files.pythonhosted.org/packages/4b/2d/69abac8f838090bbecd5df894befb2c2619e7996a98ddb949db9f3b93225/pydantic_core-2.46.4-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:d51026d73fcfd93610abc7b27789c26b313920fcfb20e27462d74a7f8b06e983", size = 2193071, upload-time = "2026-05-06T13:38:08.682Z" }, ] [[package]] From 05aef6bc357775f53dc31be94ce26348798d9ebd Mon Sep 17 00:00:00 2001 From: tconley1428 Date: Wed, 3 Jun 2026 16:24:35 -0700 Subject: [PATCH 119/226] Add trusted publishing release workflow (#1575) * Add trusted publishing release workflow * Format release verification script * Harden release smoke package install --- .../actions/release-smoke-package/action.yml | 43 +++ .github/scripts/install_release_package.py | 54 ++++ .github/scripts/release_smoke_package.py | 59 ++++ .github/scripts/release_verify.py | 130 +++++++++ .github/workflows/build-binaries.yml | 81 ------ .github/workflows/release-publish.yml | 264 ++++++++++++++++++ 6 files changed, 550 insertions(+), 81 deletions(-) create mode 100644 .github/actions/release-smoke-package/action.yml create mode 100644 .github/scripts/install_release_package.py create mode 100644 .github/scripts/release_smoke_package.py create mode 100644 .github/scripts/release_verify.py delete mode 100644 .github/workflows/build-binaries.yml create mode 100644 .github/workflows/release-publish.yml diff --git a/.github/actions/release-smoke-package/action.yml b/.github/actions/release-smoke-package/action.yml new file mode 100644 index 000000000..bd557cd2b --- /dev/null +++ b/.github/actions/release-smoke-package/action.yml @@ -0,0 +1,43 @@ +name: Release package smoke test +description: Install a published temporalio package and run a minimal SDK workflow. +inputs: + version: + description: "Package version to install and verify" + required: true + index-url: + description: "Primary package index URL" + required: true + dependency-index-url: + description: "Optional dependency package index URL" + required: false + default: "" +runs: + using: composite + steps: + - uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5 + with: + python-version: "3.10" + - name: Install package + shell: bash + env: + VERSION: ${{ inputs.version }} + INDEX_URL: ${{ inputs.index-url }} + DEPENDENCY_INDEX_URL: ${{ inputs.dependency-index-url }} + run: | + set -euo pipefail + python -m venv .venv + .venv/bin/python -m pip install --upgrade pip + + install_args=(--version "$VERSION" --index-url "$INDEX_URL") + if [[ -n "$DEPENDENCY_INDEX_URL" ]]; then + install_args+=(--dependency-index-url "$DEPENDENCY_INDEX_URL") + fi + + .venv/bin/python .github/scripts/install_release_package.py "${install_args[@]}" + - name: Run SDK smoke test + shell: bash + env: + VERSION: ${{ inputs.version }} + run: | + set -euo pipefail + .venv/bin/python .github/scripts/release_smoke_package.py diff --git a/.github/scripts/install_release_package.py b/.github/scripts/install_release_package.py new file mode 100644 index 000000000..723267e2b --- /dev/null +++ b/.github/scripts/install_release_package.py @@ -0,0 +1,54 @@ +"""Install a release package for smoke testing.""" + +from __future__ import annotations + +import argparse +import importlib.metadata +import subprocess +import sys +from collections.abc import Sequence + + +def _pip_install(args: Sequence[str]) -> None: + subprocess.check_call([sys.executable, "-m", "pip", "install", *args]) + + +def install_package(args: argparse.Namespace) -> None: + package = f"temporalio=={args.version}" + if args.dependency_index_url: + _pip_install( + [ + "--prefer-binary", + "--index-url", + args.index_url, + "--no-deps", + package, + ] + ) + + requirements = importlib.metadata.requires("temporalio") or [] + if requirements: + _pip_install( + [ + "--prefer-binary", + "--index-url", + args.dependency_index_url, + *requirements, + ] + ) + else: + _pip_install(["--prefer-binary", "--index-url", args.index_url, package]) + + subprocess.check_call([sys.executable, "-m", "pip", "check"]) + + +def main(argv: Sequence[str] | None = None) -> None: + parser = argparse.ArgumentParser() + parser.add_argument("--version", required=True) + parser.add_argument("--index-url", required=True) + parser.add_argument("--dependency-index-url") + install_package(parser.parse_args(argv)) + + +if __name__ == "__main__": + main() diff --git a/.github/scripts/release_smoke_package.py b/.github/scripts/release_smoke_package.py new file mode 100644 index 000000000..00a192e85 --- /dev/null +++ b/.github/scripts/release_smoke_package.py @@ -0,0 +1,59 @@ +"""Smoke test an installed temporalio release package.""" + +from __future__ import annotations + +import asyncio +import os +import uuid +from datetime import timedelta + +import temporalio +from temporalio import activity, workflow +from temporalio.testing import WorkflowEnvironment +from temporalio.worker import UnsandboxedWorkflowRunner, Worker + + +@activity.defn +async def say_hello(name: str) -> str: + return f"Hello, {name}!" + + +@workflow.defn +class SmokeWorkflow: + @workflow.run + async def run(self, name: str) -> str: + return await workflow.execute_activity( + say_hello, + name, + start_to_close_timeout=timedelta(seconds=10), + ) + + +async def main() -> None: + expected_version = os.environ["VERSION"] + if temporalio.__version__ != expected_version: + raise RuntimeError( + f"Expected temporalio {expected_version}, got {temporalio.__version__}" + ) + + task_queue = f"release-smoke-{uuid.uuid4()}" + async with await WorkflowEnvironment.start_local() as env: + async with Worker( + env.client, + task_queue=task_queue, + workflows=[SmokeWorkflow], + activities=[say_hello], + workflow_runner=UnsandboxedWorkflowRunner(), + ): + result = await env.client.execute_workflow( + SmokeWorkflow.run, + "trusted publishing", + id=task_queue, + task_queue=task_queue, + ) + if result != "Hello, trusted publishing!": + raise RuntimeError(f"Unexpected workflow result: {result!r}") + + +if __name__ == "__main__": + asyncio.run(main()) diff --git a/.github/scripts/release_verify.py b/.github/scripts/release_verify.py new file mode 100644 index 000000000..7f69f2408 --- /dev/null +++ b/.github/scripts/release_verify.py @@ -0,0 +1,130 @@ +"""Release workflow validation helpers.""" + +from __future__ import annotations + +import argparse +import ast +import pathlib +import re +from collections.abc import Sequence + +try: + import tomllib +except ModuleNotFoundError: + import toml as tomllib # type: ignore[no-redef] + + +def _checked_in_version() -> str: + pyproject_version = tomllib.loads(pathlib.Path("pyproject.toml").read_text())[ + "project" + ]["version"] + service_tree = ast.parse(pathlib.Path("temporalio/service.py").read_text()) + service_version = None + for stmt in service_tree.body: + if ( + isinstance(stmt, ast.Assign) + and any( + isinstance(target, ast.Name) and target.id == "__version__" + for target in stmt.targets + ) + and isinstance(stmt.value, ast.Constant) + and isinstance(stmt.value.value, str) + ): + service_version = stmt.value.value + break + + if pyproject_version != service_version: + raise RuntimeError( + f"pyproject.toml version {pyproject_version!r} does not match " + f"temporalio/service.py version {service_version!r}" + ) + if pyproject_version.startswith("v"): + raise RuntimeError("Checked-in version must not start with 'v'") + if not re.fullmatch(r"[0-9]+(?:\.[0-9]+)+(?:[a-zA-Z0-9_.+-]+)?", pyproject_version): + raise RuntimeError(f"Invalid checked-in version: {pyproject_version!r}") + return pyproject_version + + +def _write_github_output(path: pathlib.Path, *, version: str, sha: str) -> None: + with path.open("a", encoding="utf-8") as output: + print(f"version={version}", file=output) + print(f"sha={sha}", file=output) + + +def validate_version(args: argparse.Namespace) -> None: + version = _checked_in_version() + if args.github_output: + _write_github_output( + pathlib.Path(args.github_output), + version=version, + sha=args.sha, + ) + else: + print(version) + + +def verify_dist(args: argparse.Namespace) -> None: + dist_dir = pathlib.Path(args.dist_dir) + files = sorted(path.name for path in dist_dir.iterdir() if path.is_file()) + wheels = [name for name in files if name.endswith(".whl")] + sdists = [name for name in files if name.endswith(".tar.gz")] + + if len(files) != len(set(files)): + raise RuntimeError("Duplicate distribution filenames found") + expected_sdist = f"temporalio-{args.version}.tar.gz" + if sdists != [expected_sdist]: + raise RuntimeError(f"Expected only sdist {expected_sdist!r}, found {sdists!r}") + if len(wheels) != 5: + raise RuntimeError( + f"Expected 5 platform wheels, found {len(wheels)}: {wheels!r}" + ) + + for name in files: + if not name.startswith(f"temporalio-{args.version}"): + raise RuntimeError( + f"Distribution filename does not match requested version " + f"{args.version!r}: {name}" + ) + + expected_platforms = { + "linux-x86_64": lambda name: "manylinux" in name and "x86_64" in name, + "linux-aarch64": lambda name: "manylinux" in name and "aarch64" in name, + "macos-x86_64": lambda name: "macosx" in name and "x86_64" in name, + "macos-arm64": lambda name: "macosx" in name and "arm64" in name, + "windows-amd64": lambda name: "win_amd64" in name, + } + missing = [ + platform + for platform, predicate in expected_platforms.items() + if not any(predicate(name) for name in wheels) + ] + if missing: + raise RuntimeError( + f"Missing expected platform wheels: {missing!r}; found {wheels!r}" + ) + + print("Verified release artifacts:") + for name in files: + print(f" {name}") + + +def main(argv: Sequence[str] | None = None) -> None: + parser = argparse.ArgumentParser() + subparsers = parser.add_subparsers(required=True) + + validate_parser = subparsers.add_parser("validate-version") + validate_parser.add_argument("--sha", required=True) + validate_parser.add_argument("--github-output") + validate_parser.set_defaults(func=validate_version) + + verify_parser = subparsers.add_parser("verify-dist") + verify_parser.add_argument("--version", required=True) + verify_parser.add_argument("--dist-dir", default="dist") + verify_parser.set_defaults(func=verify_dist) + + args = parser.parse_args(argv) + args.func(args) + + +if __name__ == "__main__": + main() diff --git a/.github/workflows/build-binaries.yml b/.github/workflows/build-binaries.yml deleted file mode 100644 index eb95216d0..000000000 --- a/.github/workflows/build-binaries.yml +++ /dev/null @@ -1,81 +0,0 @@ -name: Build Binaries -on: - push: - branches: - - main - - "releases/*" - - build_binaries_otel -permissions: - contents: read - -jobs: - # Compile the binaries and upload artifacts - compile-binaries: - strategy: - fail-fast: false - matrix: - include: - - os: ubuntu-latest - package-suffix: linux-amd64 - - os: ubuntu-arm - package-suffix: linux-aarch64 - runsOn: ubuntu-24.04-arm64-2-core - - os: macos-intel - package-suffix: macos-amd64 - runsOn: macos-15-intel - - os: macos-arm - package-suffix: macos-aarch64 - runsOn: macos-14 - - os: windows-latest - package-suffix: windows-amd64 - runs-on: ${{ matrix.runsOn || matrix.os }} - steps: - - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 - with: - submodules: recursive - - uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5 - with: - python-version: "3.14" - - # Install Rust locally for non-Linux (Linux uses an internal docker - # command to build with cibuildwheel which uses rustup install defined - # in pyproject.toml) - - if: ${{ runner.os != 'Linux' }} - uses: dtolnay/rust-toolchain@29eef336d9b2848a0b548edc03f92a220660cdb8 # stable - - if: ${{ runner.os != 'Linux' }} - uses: Swatinem/rust-cache@e18b497796c12c097a38f9edb9d0641fb99eee32 # v2 - with: - cache-bin: false - workspaces: temporalio/bridge -> target - key: ${{ env.pythonLocation }} - - uses: astral-sh/setup-uv@cec208311dfd045dd5311c1add060b2062131d57 # v8 - - run: uv sync --all-extras - - # Add the source dist only for Linux x64 for now - - if: ${{ matrix.package-suffix == 'linux-amd64' }} - run: uv build --sdist - - # Build the wheel - - run: uv run cibuildwheel --output-dir dist - - # Install the wheel in a new venv and run a test - - name: Test wheel - shell: bash - run: | - mkdir __test_wheel__ - cd __test_wheel__ - cp -r ../tests . - python -m venv .venv - bindir=bin - if [ "$RUNNER_OS" = "Windows" ]; then - bindir=Scripts - fi - ./.venv/$bindir/pip install pytest pytest_asyncio grpcio pydantic opentelemetry-api opentelemetry-sdk - ./.venv/$bindir/pip install --prefer-binary ../dist/*.whl - ./.venv/$bindir/python -m pytest -s tests/worker/test_workflow.py -k test_workflow_hello - - # Upload dist - - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4 - with: - name: packages-${{ matrix.package-suffix }} - path: dist diff --git a/.github/workflows/release-publish.yml b/.github/workflows/release-publish.yml new file mode 100644 index 000000000..5c8d54196 --- /dev/null +++ b/.github/workflows/release-publish.yml @@ -0,0 +1,264 @@ +name: Release Publish +run-name: Release from main + +on: + workflow_dispatch: + +permissions: + contents: read + +concurrency: + group: release-publish-${{ github.ref }} + cancel-in-progress: false + +jobs: + build_binaries: + name: Build binaries (${{ matrix.package-suffix }}) + strategy: + fail-fast: false + matrix: + include: + - os: ubuntu-latest + package-suffix: linux-amd64 + - os: ubuntu-arm + package-suffix: linux-aarch64 + runsOn: ubuntu-24.04-arm64-2-core + - os: macos-intel + package-suffix: macos-amd64 + runsOn: macos-15-intel + - os: macos-arm + package-suffix: macos-aarch64 + runsOn: macos-14 + - os: windows-latest + package-suffix: windows-amd64 + runs-on: ${{ matrix.runsOn || matrix.os }} + permissions: + contents: read + steps: + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 + with: + ref: ${{ github.sha }} + submodules: recursive + - uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5 + with: + python-version: "3.14" + + # Install Rust locally for non-Linux (Linux uses an internal docker + # command to build with cibuildwheel which uses rustup install defined + # in pyproject.toml) + - if: ${{ runner.os != 'Linux' }} + uses: dtolnay/rust-toolchain@29eef336d9b2848a0b548edc03f92a220660cdb8 # stable + - if: ${{ runner.os != 'Linux' }} + uses: Swatinem/rust-cache@e18b497796c12c097a38f9edb9d0641fb99eee32 # v2 + with: + cache-bin: false + workspaces: temporalio/bridge -> target + key: ${{ env.pythonLocation }} + - uses: astral-sh/setup-uv@cec208311dfd045dd5311c1add060b2062131d57 # v8 + - run: uv sync --all-extras + + # Add the source dist only for Linux x64 for now + - if: ${{ matrix.package-suffix == 'linux-amd64' }} + run: uv build --sdist + + # Build the wheel + - run: uv run cibuildwheel --output-dir dist + + # Install the wheel in a new venv and run a test + - name: Test wheel + shell: bash + run: | + mkdir __test_wheel__ + cd __test_wheel__ + cp -r ../tests . + python -m venv .venv + bindir=bin + if [ "$RUNNER_OS" = "Windows" ]; then + bindir=Scripts + fi + ./.venv/$bindir/pip install pytest pytest_asyncio grpcio pydantic opentelemetry-api opentelemetry-sdk + ./.venv/$bindir/pip install --prefer-binary ../dist/*.whl + ./.venv/$bindir/python -m pytest -s tests/worker/test_workflow.py -k test_workflow_hello + + # Upload dist + - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4 + with: + name: packages-${{ matrix.package-suffix }} + path: dist + + verify_artifacts: + name: Verify release artifacts + needs: build_binaries + runs-on: ubuntu-latest + timeout-minutes: 10 + permissions: + actions: read + contents: read + outputs: + release_sha: ${{ steps.validate_versions.outputs.sha }} + version: ${{ steps.validate_versions.outputs.version }} + steps: + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 + with: + ref: ${{ github.sha }} + - uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5 + with: + python-version: "3.11" + - name: Validate checked-in versions + id: validate_versions + run: | + set -euo pipefail + python .github/scripts/release_verify.py validate-version \ + --sha "$(git rev-parse HEAD)" \ + --github-output "$GITHUB_OUTPUT" + - name: Download and flatten artifacts + env: + GH_TOKEN: ${{ github.token }} + run: | + set -euo pipefail + mkdir artifacts dist + gh run download "$GITHUB_RUN_ID" \ + --repo "$GITHUB_REPOSITORY" \ + --dir artifacts \ + --pattern 'packages-*' + + while IFS= read -r -d '' file; do + dest="dist/$(basename "$file")" + if [[ -e "$dest" ]]; then + echo "Duplicate distribution filename: $(basename "$file")" >&2 + exit 1 + fi + cp "$file" "$dest" + done < <(find artifacts -type f \( -name '*.whl' -o -name '*.tar.gz' \) -print0) + - name: Verify release artifacts + env: + VERSION: ${{ steps.validate_versions.outputs.version }} + run: | + set -euo pipefail + python .github/scripts/release_verify.py verify-dist --version "$VERSION" + - name: Upload verified release artifact + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4 + with: + name: release-dist-${{ steps.validate_versions.outputs.version }} + path: dist + if-no-files-found: error + retention-days: 14 + + publish_testpypi: + name: Publish to TestPyPI + needs: verify_artifacts + runs-on: ubuntu-latest + timeout-minutes: 10 + environment: testpypi + permissions: + actions: read + contents: read + id-token: write + steps: + - name: Download verified release artifact + env: + GH_TOKEN: ${{ github.token }} + VERSION: ${{ needs.verify_artifacts.outputs.version }} + run: | + set -euo pipefail + mkdir downloaded dist + gh run download "$GITHUB_RUN_ID" \ + --repo "$GITHUB_REPOSITORY" \ + --name "release-dist-$VERSION" \ + --dir downloaded + while IFS= read -r -d '' file; do + cp "$file" "dist/$(basename "$file")" + done < <(find downloaded -type f \( -name '*.whl' -o -name '*.tar.gz' \) -print0) + test "$(find dist -type f | wc -l)" -gt 0 + - name: Publish to TestPyPI + uses: pypa/gh-action-pypi-publish@cef221092ed1bacb1cc03d23a2d87d1d172e277b # release/v1 + with: + packages-dir: dist/ + repository-url: https://test.pypi.org/legacy/ + skip-existing: true + + smoke_testpypi: + name: Smoke test TestPyPI package + needs: + - verify_artifacts + - publish_testpypi + runs-on: ubuntu-latest + timeout-minutes: 10 + steps: + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 + - uses: ./.github/actions/release-smoke-package + with: + version: ${{ needs.verify_artifacts.outputs.version }} + index-url: https://test.pypi.org/simple/ + dependency-index-url: https://pypi.org/simple/ + + publish_pypi: + name: Publish to PyPI + needs: + - verify_artifacts + - smoke_testpypi + runs-on: ubuntu-latest + timeout-minutes: 10 + environment: pypi + permissions: + actions: read + contents: read + id-token: write + steps: + - name: Download verified release artifact + env: + GH_TOKEN: ${{ github.token }} + VERSION: ${{ needs.verify_artifacts.outputs.version }} + run: | + set -euo pipefail + mkdir downloaded dist + gh run download "$GITHUB_RUN_ID" \ + --repo "$GITHUB_REPOSITORY" \ + --name "release-dist-$VERSION" \ + --dir downloaded + while IFS= read -r -d '' file; do + cp "$file" "dist/$(basename "$file")" + done < <(find downloaded -type f \( -name '*.whl' -o -name '*.tar.gz' \) -print0) + test "$(find dist -type f | wc -l)" -gt 0 + - name: Publish to PyPI + uses: pypa/gh-action-pypi-publish@cef221092ed1bacb1cc03d23a2d87d1d172e277b # release/v1 + with: + packages-dir: dist/ + + smoke_pypi: + name: Smoke test PyPI package + needs: + - verify_artifacts + - publish_pypi + runs-on: ubuntu-latest + timeout-minutes: 10 + steps: + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 + - uses: ./.github/actions/release-smoke-package + with: + version: ${{ needs.verify_artifacts.outputs.version }} + index-url: https://pypi.org/simple/ + + create_draft_release: + name: Create draft GitHub Release + needs: + - verify_artifacts + - smoke_pypi + runs-on: ubuntu-latest + timeout-minutes: 5 + permissions: + contents: write + steps: + - name: Create draft release with generated notes + env: + GH_TOKEN: ${{ github.token }} + RELEASE_SHA: ${{ needs.verify_artifacts.outputs.release_sha }} + VERSION: ${{ needs.verify_artifacts.outputs.version }} + run: | + set -euo pipefail + gh release create "$VERSION" \ + --repo "$GITHUB_REPOSITORY" \ + --target "$RELEASE_SHA" \ + --title "$VERSION" \ + --draft \ + --generate-notes From 3c0b12248242c6806dad6279339460393e7b3a79 Mon Sep 17 00:00:00 2001 From: Alex Mazzeo Date: Thu, 4 Jun 2026 08:32:43 -0700 Subject: [PATCH 120/226] Add nexus-operation-token header to nexus callback headers for TemporalOperationHandler and WorkflowRunOperationHandler (#1576) --- temporalio/nexus/_operation_context.py | 16 ++++--- tests/nexus/test_temporal_operation.py | 39 ++++++++++++++++ tests/nexus/test_workflow_run_operation.py | 53 ++++++++++++++++++++-- 3 files changed, 97 insertions(+), 11 deletions(-) diff --git a/temporalio/nexus/_operation_context.py b/temporalio/nexus/_operation_context.py index 01d209a9f..0d9d11449 100644 --- a/temporalio/nexus/_operation_context.py +++ b/temporalio/nexus/_operation_context.py @@ -47,7 +47,7 @@ workflow_event_to_nexus_link, workflow_execution_started_event_link_from_workflow_handle, ) -from ._token import WorkflowHandle +from ._token import OperationToken, OperationTokenType, WorkflowHandle if TYPE_CHECKING: import temporalio.client @@ -225,15 +225,14 @@ def get(cls) -> _TemporalStartOperationContext: def set(self) -> None: _temporal_start_operation_context.set(self) - def _get_callbacks( - self, - ) -> list[temporalio.client.Callback]: + def _get_callbacks(self, token: str) -> list[temporalio.client.Callback]: ctx = self.nexus_context + callback_headers = {**ctx.callback_headers, "nexus-operation-token": token} return ( [ NexusCallback( url=ctx.callback_url, - headers=ctx.callback_headers, + headers=callback_headers, ) ] if ctx.callback_url @@ -643,6 +642,11 @@ async def _start_nexus_backing_workflow( # terminal state) and inbound links to the caller workflow (attached to history events of # the workflow started in the handler namespace, and displayed in the UI). with _nexus_backing_workflow_start_context(): + token = OperationToken( + type=OperationTokenType.WORKFLOW, + namespace=temporal_context.client.namespace, + workflow_id=id, + ).encode() wf_handle = await temporal_context.client.start_workflow( # type: ignore workflow=workflow, arg=arg, @@ -669,7 +673,7 @@ async def _start_nexus_backing_workflow( request_eager_start=request_eager_start, priority=priority, versioning_override=versioning_override, - callbacks=temporal_context._get_callbacks(), + callbacks=temporal_context._get_callbacks(token), links=temporal_context._get_links(), request_id=temporal_context.nexus_context.request_id, ) diff --git a/tests/nexus/test_temporal_operation.py b/tests/nexus/test_temporal_operation.py index c101ede3b..c97792c8d 100644 --- a/tests/nexus/test_temporal_operation.py +++ b/tests/nexus/test_temporal_operation.py @@ -12,6 +12,7 @@ from temporalio import nexus, workflow from temporalio.client import Client, WorkflowExecutionStatus, WorkflowFailureError from temporalio.common import NexusOperationExecutionStatus, WorkflowIDConflictPolicy +from temporalio.nexus._token import OperationToken, OperationTokenType from temporalio.testing import WorkflowEnvironment from temporalio.worker import Worker from tests.helpers import EventType, assert_event_subsequence, assert_eventually @@ -685,3 +686,41 @@ async def test_temporal_operation_overloads( if op == "no_param" else TemporalOperationOverloadTestValue(value=4) ) + + +async def test_temporal_operation_includes_token_in_callback( + client: Client, env: WorkflowEnvironment +): + task_queue = str(uuid.uuid4()) + endpoint_name = make_nexus_endpoint_name(task_queue) + await env.create_nexus_endpoint(endpoint_name, task_queue) + async with Worker( + env.client, + task_queue=task_queue, + nexus_service_handlers=[TestServiceHandler()], + workflows=[EchoWorkflow, EchoWorkflowCaller], + ): + input_value = f"test-{uuid.uuid4()}" + wf_handle = await client.start_workflow( + EchoWorkflowCaller.run, + Input(value=input_value, task_queue=task_queue), + task_queue=task_queue, + id=str(uuid.uuid4()), + ) + result = await wf_handle.result() + assert result == input_value + + target_handle = client.get_workflow_handle(f"echo-{input_value}") + + desc = await target_handle.describe() + token = desc.raw_description.callbacks[0].callback.nexus.header[ + "nexus-operation-token" + ] + + expected_token = OperationToken( + type=OperationTokenType.WORKFLOW, + namespace=client.namespace, + workflow_id=target_handle.id, + ).encode() + + assert token == expected_token diff --git a/tests/nexus/test_workflow_run_operation.py b/tests/nexus/test_workflow_run_operation.py index 3ba9545fc..851f408ec 100644 --- a/tests/nexus/test_workflow_run_operation.py +++ b/tests/nexus/test_workflow_run_operation.py @@ -18,6 +18,7 @@ from temporalio.client import Client from temporalio.nexus import WorkflowRunOperationContext, workflow_run_operation from temporalio.nexus._operation_handlers import WorkflowRunOperationHandler +from temporalio.nexus._token import OperationToken, OperationTokenType from temporalio.testing import WorkflowEnvironment from temporalio.worker import Worker from tests.helpers.nexus import make_nexus_endpoint_name @@ -48,7 +49,7 @@ async def start( handle = await tctx.start_workflow( EchoWorkflow.run, input.value, - id=str(uuid.uuid4()), + id=input.value, ) return StartOperationResultAsync(handle.to_token()) @@ -78,7 +79,7 @@ async def op( return await ctx.start_workflow( EchoWorkflow.run, input.value, - id=str(uuid.uuid4()), + id=input.value, ) @@ -146,13 +147,14 @@ async def test_workflow_run_operation( nexus_service_handlers=[service_handler_cls()], workflows=[CallerWorkflow, EchoWorkflow], ): + input_value = str(uuid.uuid4()) result = await client.execute_workflow( CallerWorkflow.run, - args=[Input(value="test"), service_defn.name, task_queue], + args=[Input(value=input_value), service_defn.name, task_queue], id=str(uuid.uuid4()), task_queue=task_queue, ) - assert result == "test" + assert result == input_value async def test_request_deadline_is_accessible_in_workflow_run_operation( @@ -173,9 +175,10 @@ async def test_request_deadline_is_accessible_in_workflow_run_operation( nexus_service_handlers=[service_handler], workflows=[RequestDeadlineWorkflow, EchoWorkflow], ): + input_value = str(uuid.uuid4()) await client.execute_workflow( RequestDeadlineWorkflow.run, - args=[Input(value="test"), task_queue], + args=[Input(value=input_value), task_queue], task_queue=task_queue, id=str(uuid.uuid4()), ) @@ -186,3 +189,43 @@ async def test_request_deadline_is_accessible_in_workflow_run_operation( "request_deadline should be set in WorkflowRunOperationContext" ) assert deadline.tzinfo is timezone.utc, "request_deadline should be in utc" + + +async def test_workflow_run_operation_includes_token_in_callback( + client: Client, + env: WorkflowEnvironment, +): + if env.supports_time_skipping: + pytest.skip("Nexus tests don't work with time-skipping server") + + task_queue = str(uuid.uuid4()) + await env.create_nexus_endpoint(make_nexus_endpoint_name(task_queue), task_queue) + async with Worker( + client, + task_queue=task_queue, + nexus_service_handlers=[SubclassingHappyPath()], + workflows=[CallerWorkflow, EchoWorkflow], + ): + input_value = str(uuid.uuid4()) + result = await client.execute_workflow( + CallerWorkflow.run, + args=[Input(value=input_value), "SubclassingHappyPath", task_queue], + id=str(uuid.uuid4()), + task_queue=task_queue, + ) + assert result == input_value + + target_handle = client.get_workflow_handle(input_value) + + desc = await target_handle.describe() + token = desc.raw_description.callbacks[0].callback.nexus.header[ + "nexus-operation-token" + ] + + expected_token = OperationToken( + type=OperationTokenType.WORKFLOW, + namespace=client.namespace, + workflow_id=target_handle.id, + ).encode() + + assert token == expected_token From bda846f9748c14bd58443fd9458602f9a6647311 Mon Sep 17 00:00:00 2001 From: tconley1428 Date: Thu, 4 Jun 2026 09:59:18 -0700 Subject: [PATCH 121/226] Bump version to 1.28.0 (#1577) --- pyproject.toml | 2 +- temporalio/service.py | 2 +- uv.lock | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 596003480..317b378cb 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "temporalio" -version = "1.27.2" +version = "1.28.0" description = "Temporal.io Python SDK" authors = [{ name = "Temporal Technologies Inc", email = "sdk@temporal.io" }] requires-python = ">=3.10" diff --git a/temporalio/service.py b/temporalio/service.py index f3583c1ee..1ab1e9cc4 100644 --- a/temporalio/service.py +++ b/temporalio/service.py @@ -24,7 +24,7 @@ import temporalio.runtime from temporalio.bridge.client import RPCError as BridgeRPCError -__version__ = "1.27.2" +__version__ = "1.28.0" ServiceRequest = TypeVar("ServiceRequest", bound=google.protobuf.message.Message) ServiceResponse = TypeVar("ServiceResponse", bound=google.protobuf.message.Message) diff --git a/uv.lock b/uv.lock index d7c4f3c50..1f46fc241 100644 --- a/uv.lock +++ b/uv.lock @@ -9,7 +9,7 @@ resolution-markers = [ ] [options] -exclude-newer = "0001-01-01T00:00:00Z" # This has no effect and is included for backwards compatibility when using relative exclude-newer values. +exclude-newer = "2026-05-20T23:41:58.595699Z" exclude-newer-span = "P2W" [[package]] @@ -5409,7 +5409,7 @@ wheels = [ [[package]] name = "temporalio" -version = "1.27.2" +version = "1.28.0" source = { virtual = "." } dependencies = [ { name = "nexus-rpc" }, From b217b3698dfc6a07bcc7b05ee6784e46263a71c3 Mon Sep 17 00:00:00 2001 From: Christopher Constable Date: Fri, 5 Jun 2026 12:12:50 -0400 Subject: [PATCH 122/226] Add CHANGELOG and document the update process (#1580) * Add CHANGELOG and document the update process Add a CHANGELOG.md with an Unreleased section, set CHANGELOG.md to merge=union via .gitattributes, and document in CONTRIBUTING.md when and how to add entries. * Move changelog comments to top of file for better readability. --- .gitattributes | 1 + CHANGELOG.md | 20 ++++++++++++++++++++ CONTRIBUTING.md | 21 +++++++++++++++++++++ 3 files changed, 42 insertions(+) create mode 100644 .gitattributes create mode 100644 CHANGELOG.md create mode 100644 CONTRIBUTING.md diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 000000000..a19ade077 --- /dev/null +++ b/.gitattributes @@ -0,0 +1 @@ +CHANGELOG.md merge=union diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 000000000..074191972 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,20 @@ + + +# Changelog + +## [Unreleased] diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 000000000..83b27f007 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,21 @@ +# Contributing to the Temporal Python SDK + +Thanks for your interest in contributing! + +All contributors must complete the Temporal Contributor License Agreement (CLA) before changes +can be merged. A link to the CLA will be posted in the PR. + +See the [README](README.md) for build and development instructions. + +## Changelog + +User-facing changes are recorded in [`CHANGELOG.md`](CHANGELOG.md), loosely following the +[Keep a Changelog](https://keepachangelog.com/en/1.1.0/) format. + +If your PR includes a user-facing change (new feature, behavior change, deprecation, breaking +change, notable bug fix, or security fix), add a short, high-level entry to the `## [Unreleased]` +section at the top of `CHANGELOG.md` under the appropriate heading, creating it if needed: +Added, Changed, Deprecated, Breaking Changes, Fixed, or Security. + +Keep entries high-level and written for users. The full commit log is appended at release time, +so internal-only changes (refactors, tests, CI, docs) don't need an entry. From 8d667248d9e43ec3511f6711a59c543ef3f5d7a2 Mon Sep 17 00:00:00 2001 From: Alex Mazzeo Date: Fri, 5 Jun 2026 10:18:48 -0700 Subject: [PATCH 123/226] Use ActivitySerializationContext when describing a Standalone Activity (#1583) * Use ActivitySerializationContext when describing a Standalone Activity * remove unnecessary check --- temporalio/client/_impl.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/temporalio/client/_impl.py b/temporalio/client/_impl.py index 0f3667b19..e62f0b4a2 100644 --- a/temporalio/client/_impl.py +++ b/temporalio/client/_impl.py @@ -698,9 +698,14 @@ async def describe_activity( long_poll_token=resp.long_poll_token or None, namespace=self._client.namespace, data_converter=self._client.data_converter.with_context( - WorkflowSerializationContext( + ActivitySerializationContext( namespace=self._client.namespace, - workflow_id=input.activity_id, # Using activity_id as workflow_id for activities not started by a workflow + activity_id=resp.info.activity_id, + activity_task_queue=resp.info.task_queue, + activity_type=resp.info.activity_type.name, + workflow_id=None, + workflow_type=None, + is_local=False, ) ), ) From dbc6023487cfbc8cd1c162da65552e29e41ef9b3 Mon Sep 17 00:00:00 2001 From: Brian Strauch Date: Mon, 8 Jun 2026 09:40:31 -0700 Subject: [PATCH 124/226] Build streamed OpenAI events before serializing them (#1586) * Fall back to model_dump_json for OpenAI payload serialization OpenAI response and stream event types whose pydantic serializer is a lazily-built MockValSer cannot be serialized by the generic any-schema serializer, raising PydanticSerializationError (e.g. when streaming via WorkflowStreamClient). The model's own model_dump_json() handles them. Fixes #1585 * Dispatch pydantic models to their own serializer OpenAI's BaseModel sets defer_build=True, so a model's serializer is a MockValSer placeholder until pydantic's lazy build runs. The generic any-schema serializer reaches for that placeholder directly without triggering the build and raises PydanticSerializationError. Route pydantic models through their own model_dump_json (which triggers the build) by type instead of catching the error; non-model values continue through the generic serializer unchanged. * Build streamed events at the source instead of in the converter Force the deferred pydantic build on each streamed event before it is published or returned, so it serializes regardless of build state. This also covers the activity's list return value, which the payload converter serializes generically and cannot build on its own. Drop the now-redundant to_payload override. --- temporalio/contrib/openai_agents/_invoke_model_activity.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/temporalio/contrib/openai_agents/_invoke_model_activity.py b/temporalio/contrib/openai_agents/_invoke_model_activity.py index a43f9aeaf..3f7a639dd 100644 --- a/temporalio/contrib/openai_agents/_invoke_model_activity.py +++ b/temporalio/contrib/openai_agents/_invoke_model_activity.py @@ -393,6 +393,9 @@ async def invoke_model_activity_streaming( conversation_id=input.get("conversation_id"), prompt=input.get("prompt"), ): + # OpenAI models set defer_build=True, so an event's pydantic + # schema may still be an unbuilt placeholder. + type(event).model_rebuild() events.append(event) events_topic.publish(event) except APIStatusError as e: From d8675f5896258ce6e2b13059c4fa53562c614ab6 Mon Sep 17 00:00:00 2001 From: tconley1428 Date: Mon, 8 Jun 2026 15:55:44 -0700 Subject: [PATCH 125/226] Update core submodule (#1590) * Update core submodule * Handle nexus annotation protos * Fix link conversion lint * Update temporalio/nexus/_link_conversion.py Co-authored-by: Alex Mazzeo --------- Co-authored-by: Alex Mazzeo --- scripts/gen_protos.py | 15 +- temporalio/api/activity/v1/message_pb2.py | 20 +- temporalio/api/activity/v1/message_pb2.pyi | 33 +- .../api/cloud/cloudservice/v1/__init__.py | 12 + .../cloudservice/v1/request_response_pb2.py | 100 +- .../cloudservice/v1/request_response_pb2.pyi | 212 ++++ .../api/cloud/cloudservice/v1/service_pb2.py | 22 +- .../cloud/cloudservice/v1/service_pb2_grpc.py | 135 +++ .../cloudservice/v1/service_pb2_grpc.pyi | 36 + temporalio/api/cloud/identity/v1/__init__.py | 6 + .../api/cloud/identity/v1/message_pb2.py | 52 +- .../api/cloud/identity/v1/message_pb2.pyi | 150 +++ temporalio/api/common/v1/message_pb2.py | 57 +- temporalio/api/common/v1/message_pb2.pyi | 48 +- .../dependencies/nexusannotations/__init__.py | 0 .../nexusannotations/v1/__init__.py | 6 + .../nexusannotations/v1/options_pb2.py | 65 + .../nexusannotations/v1/options_pb2.pyi | 78 ++ temporalio/api/history/v1/message_pb2.py | 125 +- temporalio/api/history/v1/message_pb2.pyi | 55 + temporalio/api/namespace/v1/message_pb2.py | 38 +- temporalio/api/namespace/v1/message_pb2.pyi | 12 + temporalio/api/nexus/v1/message_pb2.py | 12 +- temporalio/api/nexus/v1/message_pb2.pyi | 12 + temporalio/api/schedule/v1/message_pb2.py | 16 +- temporalio/api/schedule/v1/message_pb2.pyi | 12 + temporalio/api/update/v1/message_pb2.py | 18 +- temporalio/api/update/v1/message_pb2.pyi | 42 +- temporalio/api/workflow/v1/message_pb2.py | 75 +- temporalio/api/workflow/v1/message_pb2.pyi | 87 +- .../v1/request_response_pb2.py | 1080 ++++++++--------- .../v1/request_response_pb2.pyi | 55 +- .../api/workflowservice/v1/service_pb2.py | 11 +- .../workflowservice/v1/service_pb2_grpc.py | 7 +- .../workflowservice/v1/service_pb2_grpc.pyi | 14 +- temporalio/bridge/Cargo.lock | 1 + temporalio/bridge/sdk-core | 2 +- temporalio/bridge/services_generated.py | 54 + temporalio/bridge/src/client_rpc_generated.rs | 27 + temporalio/nexus/_link_conversion.py | 6 +- 40 files changed, 2045 insertions(+), 763 deletions(-) create mode 100644 temporalio/api/dependencies/nexusannotations/__init__.py create mode 100644 temporalio/api/dependencies/nexusannotations/v1/__init__.py create mode 100644 temporalio/api/dependencies/nexusannotations/v1/options_pb2.py create mode 100644 temporalio/api/dependencies/nexusannotations/v1/options_pb2.pyi diff --git a/scripts/gen_protos.py b/scripts/gen_protos.py index 080bfe7f3..867d8fc0e 100644 --- a/scripts/gen_protos.py +++ b/scripts/gen_protos.py @@ -43,6 +43,10 @@ re.compile(r"from protoc_gen_openapiv2\.").sub, r"from temporalio.api.dependencies.protoc_gen_openapiv2.", ), + partial( + re.compile(r"from nexusannotations\.").sub, + r"from temporalio.api.dependencies.nexusannotations.", + ), partial( re.compile(r"from temporal\.sdk\.core\.").sub, r"from temporalio.bridge.proto." ), @@ -58,6 +62,10 @@ re.compile(r"protoc_gen_openapiv2\.").sub, r"temporalio.api.dependencies.protoc_gen_openapiv2.", ), + partial( + re.compile(r"nexusannotations\.").sub, + r"temporalio.api.dependencies.nexusannotations.", + ), partial(re.compile(r"temporal\.sdk\.core\.").sub, r"temporalio.bridge.proto."), ] @@ -191,11 +199,12 @@ def generate_protos(output_dir: Path): grpc_file.unlink() # Apply fixes before moving code fix_generated_output(output_dir) - # Move openapiv2 dependency protos + # Move dependency protos deps_out_dir = api_out_dir / "dependencies" - shutil.rmtree(deps_out_dir / "protoc_gen_openapiv2", ignore_errors=True) deps_out_dir.mkdir(exist_ok=True) - (output_dir / "protoc_gen_openapiv2").replace(deps_out_dir / "protoc_gen_openapiv2") + for dep in ["protoc_gen_openapiv2", "nexusannotations"]: + shutil.rmtree(deps_out_dir / dep, ignore_errors=True) + (output_dir / dep).replace(deps_out_dir / dep) (deps_out_dir / "__init__.py").touch() # Move protos for p in (output_dir / "temporal" / "api").iterdir(): diff --git a/temporalio/api/activity/v1/message_pb2.py b/temporalio/api/activity/v1/message_pb2.py index 4b039faff..4f0a4b164 100644 --- a/temporalio/api/activity/v1/message_pb2.py +++ b/temporalio/api/activity/v1/message_pb2.py @@ -43,7 +43,7 @@ ) DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile( - b'\n&temporal/api/activity/v1/message.proto\x12\x18temporal.api.activity.v1\x1a\x1egoogle/protobuf/duration.proto\x1a\x1fgoogle/protobuf/timestamp.proto\x1a$temporal/api/common/v1/message.proto\x1a(temporal/api/deployment/v1/message.proto\x1a$temporal/api/enums/v1/activity.proto\x1a&temporal/api/callback/v1/message.proto\x1a$temporal/api/enums/v1/workflow.proto\x1a%temporal/api/failure/v1/message.proto\x1a\'temporal/api/taskqueue/v1/message.proto\x1a\'temporal/api/sdk/v1/user_metadata.proto"\x8c\x01\n\x18\x41\x63tivityExecutionOutcome\x12\x32\n\x06result\x18\x01 \x01(\x0b\x32 .temporal.api.common.v1.PayloadsH\x00\x12\x33\n\x07\x66\x61ilure\x18\x02 \x01(\x0b\x32 .temporal.api.failure.v1.FailureH\x00\x42\x07\n\x05value"\xa7\x03\n\x0f\x41\x63tivityOptions\x12\x38\n\ntask_queue\x18\x01 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12<\n\x19schedule_to_close_timeout\x18\x02 \x01(\x0b\x32\x19.google.protobuf.Duration\x12<\n\x19schedule_to_start_timeout\x18\x03 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x39\n\x16start_to_close_timeout\x18\x04 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x34\n\x11heartbeat_timeout\x18\x05 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x39\n\x0cretry_policy\x18\x06 \x01(\x0b\x32#.temporal.api.common.v1.RetryPolicy\x12\x32\n\x08priority\x18\x07 \x01(\x0b\x32 .temporal.api.common.v1.Priority"\xab\r\n\x15\x41\x63tivityExecutionInfo\x12\x13\n\x0b\x61\x63tivity_id\x18\x01 \x01(\t\x12\x0e\n\x06run_id\x18\x02 \x01(\t\x12;\n\ractivity_type\x18\x03 \x01(\x0b\x32$.temporal.api.common.v1.ActivityType\x12>\n\x06status\x18\x04 \x01(\x0e\x32..temporal.api.enums.v1.ActivityExecutionStatus\x12>\n\trun_state\x18\x05 \x01(\x0e\x32+.temporal.api.enums.v1.PendingActivityState\x12\x12\n\ntask_queue\x18\x06 \x01(\t\x12<\n\x19schedule_to_close_timeout\x18\x07 \x01(\x0b\x32\x19.google.protobuf.Duration\x12<\n\x19schedule_to_start_timeout\x18\x08 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x39\n\x16start_to_close_timeout\x18\t \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x34\n\x11heartbeat_timeout\x18\n \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x39\n\x0cretry_policy\x18\x0b \x01(\x0b\x32#.temporal.api.common.v1.RetryPolicy\x12;\n\x11heartbeat_details\x18\x0c \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x37\n\x13last_heartbeat_time\x18\r \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x35\n\x11last_started_time\x18\x0e \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x0f\n\x07\x61ttempt\x18\x0f \x01(\x05\x12\x35\n\x12\x65xecution_duration\x18\x10 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x31\n\rschedule_time\x18\x11 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x33\n\x0f\x65xpiration_time\x18\x12 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12.\n\nclose_time\x18\x13 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x36\n\x0clast_failure\x18\x14 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12\x1c\n\x14last_worker_identity\x18\x15 \x01(\t\x12\x39\n\x16\x63urrent_retry_interval\x18\x16 \x01(\x0b\x32\x19.google.protobuf.Duration\x12>\n\x1alast_attempt_complete_time\x18\x17 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12>\n\x1anext_attempt_schedule_time\x18\x18 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12T\n\x17last_deployment_version\x18\x19 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersion\x12\x32\n\x08priority\x18\x1a \x01(\x0b\x32 .temporal.api.common.v1.Priority\x12\x1e\n\x16state_transition_count\x18\x1b \x01(\x03\x12\x18\n\x10state_size_bytes\x18\x1c \x01(\x03\x12\x43\n\x11search_attributes\x18\x1d \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes\x12.\n\x06header\x18\x1e \x01(\x0b\x32\x1e.temporal.api.common.v1.Header\x12\x38\n\ruser_metadata\x18\x1f \x01(\x0b\x32!.temporal.api.sdk.v1.UserMetadata\x12\x17\n\x0f\x63\x61nceled_reason\x18 \x01(\t\x12+\n\x05links\x18! \x03(\x0b\x32\x1c.temporal.api.common.v1.Link\x12\x1d\n\x15total_heartbeat_count\x18" \x01(\x03"\xea\x03\n\x19\x41\x63tivityExecutionListInfo\x12\x13\n\x0b\x61\x63tivity_id\x18\x01 \x01(\t\x12\x0e\n\x06run_id\x18\x02 \x01(\t\x12;\n\ractivity_type\x18\x03 \x01(\x0b\x32$.temporal.api.common.v1.ActivityType\x12\x31\n\rschedule_time\x18\x04 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12.\n\nclose_time\x18\x05 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12>\n\x06status\x18\x06 \x01(\x0e\x32..temporal.api.enums.v1.ActivityExecutionStatus\x12\x43\n\x11search_attributes\x18\x07 \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes\x12\x12\n\ntask_queue\x18\x08 \x01(\t\x12\x1e\n\x16state_transition_count\x18\t \x01(\x03\x12\x18\n\x10state_size_bytes\x18\n \x01(\x03\x12\x35\n\x12\x65xecution_duration\x18\x0b \x01(\x0b\x32\x19.google.protobuf.Duration"\xff\x01\n\x0c\x43\x61llbackInfo\x12?\n\x07trigger\x18\x01 \x01(\x0b\x32..temporal.api.activity.v1.CallbackInfo.Trigger\x12\x34\n\x04info\x18\x02 \x01(\x0b\x32&.temporal.api.callback.v1.CallbackInfo\x1a\x10\n\x0e\x41\x63tivityClosed\x1a\x66\n\x07Trigger\x12P\n\x0f\x61\x63tivity_closed\x18\x01 \x01(\x0b\x32\x35.temporal.api.activity.v1.CallbackInfo.ActivityClosedH\x00\x42\t\n\x07variantB\x93\x01\n\x1bio.temporal.api.activity.v1B\x0cMessageProtoP\x01Z\'go.temporal.io/api/activity/v1;activity\xaa\x02\x1aTemporalio.Api.Activity.V1\xea\x02\x1dTemporalio::Api::Activity::V1b\x06proto3' + b'\n&temporal/api/activity/v1/message.proto\x12\x18temporal.api.activity.v1\x1a\x1egoogle/protobuf/duration.proto\x1a\x1fgoogle/protobuf/timestamp.proto\x1a$temporal/api/common/v1/message.proto\x1a(temporal/api/deployment/v1/message.proto\x1a$temporal/api/enums/v1/activity.proto\x1a&temporal/api/callback/v1/message.proto\x1a$temporal/api/enums/v1/workflow.proto\x1a%temporal/api/failure/v1/message.proto\x1a\'temporal/api/taskqueue/v1/message.proto\x1a\'temporal/api/sdk/v1/user_metadata.proto"\x8c\x01\n\x18\x41\x63tivityExecutionOutcome\x12\x32\n\x06result\x18\x01 \x01(\x0b\x32 .temporal.api.common.v1.PayloadsH\x00\x12\x33\n\x07\x66\x61ilure\x18\x02 \x01(\x0b\x32 .temporal.api.failure.v1.FailureH\x00\x42\x07\n\x05value"\xa7\x03\n\x0f\x41\x63tivityOptions\x12\x38\n\ntask_queue\x18\x01 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12<\n\x19schedule_to_close_timeout\x18\x02 \x01(\x0b\x32\x19.google.protobuf.Duration\x12<\n\x19schedule_to_start_timeout\x18\x03 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x39\n\x16start_to_close_timeout\x18\x04 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x34\n\x11heartbeat_timeout\x18\x05 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x39\n\x0cretry_policy\x18\x06 \x01(\x0b\x32#.temporal.api.common.v1.RetryPolicy\x12\x32\n\x08priority\x18\x07 \x01(\x0b\x32 .temporal.api.common.v1.Priority"\x82\x0e\n\x15\x41\x63tivityExecutionInfo\x12\x13\n\x0b\x61\x63tivity_id\x18\x01 \x01(\t\x12\x0e\n\x06run_id\x18\x02 \x01(\t\x12;\n\ractivity_type\x18\x03 \x01(\x0b\x32$.temporal.api.common.v1.ActivityType\x12>\n\x06status\x18\x04 \x01(\x0e\x32..temporal.api.enums.v1.ActivityExecutionStatus\x12>\n\trun_state\x18\x05 \x01(\x0e\x32+.temporal.api.enums.v1.PendingActivityState\x12\x12\n\ntask_queue\x18\x06 \x01(\t\x12<\n\x19schedule_to_close_timeout\x18\x07 \x01(\x0b\x32\x19.google.protobuf.Duration\x12<\n\x19schedule_to_start_timeout\x18\x08 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x39\n\x16start_to_close_timeout\x18\t \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x34\n\x11heartbeat_timeout\x18\n \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x39\n\x0cretry_policy\x18\x0b \x01(\x0b\x32#.temporal.api.common.v1.RetryPolicy\x12;\n\x11heartbeat_details\x18\x0c \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x37\n\x13last_heartbeat_time\x18\r \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x35\n\x11last_started_time\x18\x0e \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x0f\n\x07\x61ttempt\x18\x0f \x01(\x05\x12\x35\n\x12\x65xecution_duration\x18\x10 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x31\n\rschedule_time\x18\x11 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x33\n\x0f\x65xpiration_time\x18\x12 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12.\n\nclose_time\x18\x13 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x36\n\x0clast_failure\x18\x14 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12\x1c\n\x14last_worker_identity\x18\x15 \x01(\t\x12\x39\n\x16\x63urrent_retry_interval\x18\x16 \x01(\x0b\x32\x19.google.protobuf.Duration\x12>\n\x1alast_attempt_complete_time\x18\x17 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12>\n\x1anext_attempt_schedule_time\x18\x18 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12T\n\x17last_deployment_version\x18\x19 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersion\x12\x32\n\x08priority\x18\x1a \x01(\x0b\x32 .temporal.api.common.v1.Priority\x12\x1e\n\x16state_transition_count\x18\x1b \x01(\x03\x12\x18\n\x10state_size_bytes\x18\x1c \x01(\x03\x12\x43\n\x11search_attributes\x18\x1d \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes\x12.\n\x06header\x18\x1e \x01(\x0b\x32\x1e.temporal.api.common.v1.Header\x12\x38\n\ruser_metadata\x18\x1f \x01(\x0b\x32!.temporal.api.sdk.v1.UserMetadata\x12\x17\n\x0f\x63\x61nceled_reason\x18 \x01(\t\x12+\n\x05links\x18! \x03(\x0b\x32\x1c.temporal.api.common.v1.Link\x12\x1d\n\x15total_heartbeat_count\x18" \x01(\x03\x12\x10\n\x08sdk_name\x18# \x01(\t\x12\x13\n\x0bsdk_version\x18$ \x01(\t\x12.\n\x0bstart_delay\x18% \x01(\x0b\x32\x19.google.protobuf.Duration"\xea\x03\n\x19\x41\x63tivityExecutionListInfo\x12\x13\n\x0b\x61\x63tivity_id\x18\x01 \x01(\t\x12\x0e\n\x06run_id\x18\x02 \x01(\t\x12;\n\ractivity_type\x18\x03 \x01(\x0b\x32$.temporal.api.common.v1.ActivityType\x12\x31\n\rschedule_time\x18\x04 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12.\n\nclose_time\x18\x05 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12>\n\x06status\x18\x06 \x01(\x0e\x32..temporal.api.enums.v1.ActivityExecutionStatus\x12\x43\n\x11search_attributes\x18\x07 \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes\x12\x12\n\ntask_queue\x18\x08 \x01(\t\x12\x1e\n\x16state_transition_count\x18\t \x01(\x03\x12\x18\n\x10state_size_bytes\x18\n \x01(\x03\x12\x35\n\x12\x65xecution_duration\x18\x0b \x01(\x0b\x32\x19.google.protobuf.Duration"\xff\x01\n\x0c\x43\x61llbackInfo\x12?\n\x07trigger\x18\x01 \x01(\x0b\x32..temporal.api.activity.v1.CallbackInfo.Trigger\x12\x34\n\x04info\x18\x02 \x01(\x0b\x32&.temporal.api.callback.v1.CallbackInfo\x1a\x10\n\x0e\x41\x63tivityClosed\x1a\x66\n\x07Trigger\x12P\n\x0f\x61\x63tivity_closed\x18\x01 \x01(\x0b\x32\x35.temporal.api.activity.v1.CallbackInfo.ActivityClosedH\x00\x42\t\n\x07variantB\x93\x01\n\x1bio.temporal.api.activity.v1B\x0cMessageProtoP\x01Z\'go.temporal.io/api/activity/v1;activity\xaa\x02\x1aTemporalio.Api.Activity.V1\xea\x02\x1dTemporalio::Api::Activity::V1b\x06proto3' ) @@ -139,13 +139,13 @@ _ACTIVITYOPTIONS._serialized_start = 594 _ACTIVITYOPTIONS._serialized_end = 1017 _ACTIVITYEXECUTIONINFO._serialized_start = 1020 - _ACTIVITYEXECUTIONINFO._serialized_end = 2727 - _ACTIVITYEXECUTIONLISTINFO._serialized_start = 2730 - _ACTIVITYEXECUTIONLISTINFO._serialized_end = 3220 - _CALLBACKINFO._serialized_start = 3223 - _CALLBACKINFO._serialized_end = 3478 - _CALLBACKINFO_ACTIVITYCLOSED._serialized_start = 3358 - _CALLBACKINFO_ACTIVITYCLOSED._serialized_end = 3374 - _CALLBACKINFO_TRIGGER._serialized_start = 3376 - _CALLBACKINFO_TRIGGER._serialized_end = 3478 + _ACTIVITYEXECUTIONINFO._serialized_end = 2814 + _ACTIVITYEXECUTIONLISTINFO._serialized_start = 2817 + _ACTIVITYEXECUTIONLISTINFO._serialized_end = 3307 + _CALLBACKINFO._serialized_start = 3310 + _CALLBACKINFO._serialized_end = 3565 + _CALLBACKINFO_ACTIVITYCLOSED._serialized_start = 3445 + _CALLBACKINFO_ACTIVITYCLOSED._serialized_end = 3461 + _CALLBACKINFO_TRIGGER._serialized_start = 3463 + _CALLBACKINFO_TRIGGER._serialized_end = 3565 # @@protoc_insertion_point(module_scope) diff --git a/temporalio/api/activity/v1/message_pb2.pyi b/temporalio/api/activity/v1/message_pb2.pyi index a5770f03a..e57f3860c 100644 --- a/temporalio/api/activity/v1/message_pb2.pyi +++ b/temporalio/api/activity/v1/message_pb2.pyi @@ -207,6 +207,9 @@ class ActivityExecutionInfo(google.protobuf.message.Message): CANCELED_REASON_FIELD_NUMBER: builtins.int LINKS_FIELD_NUMBER: builtins.int TOTAL_HEARTBEAT_COUNT_FIELD_NUMBER: builtins.int + SDK_NAME_FIELD_NUMBER: builtins.int + SDK_VERSION_FIELD_NUMBER: builtins.int + START_DELAY_FIELD_NUMBER: builtins.int activity_id: builtins.str """Unique identifier of this activity within its namespace along with run ID (below).""" run_id: builtins.str @@ -251,7 +254,9 @@ class ActivityExecutionInfo(google.protobuf.message.Message): """The retry policy for the activity. Will never exceed `schedule_to_close_timeout`.""" @property def heartbeat_details(self) -> temporalio.api.common.v1.message_pb2.Payloads: - """Details provided in the last recorded activity heartbeat.""" + """Details provided in the last recorded activity heartbeat. + DescribeActivityExecution does not set this field unless include_heartbeat_details was true in the request. + """ @property def last_heartbeat_time(self) -> google.protobuf.timestamp_pb2.Timestamp: """Time the last heartbeat was recorded.""" @@ -274,7 +279,9 @@ class ActivityExecutionInfo(google.protobuf.message.Message): """Time when the activity transitioned to a closed state.""" @property def last_failure(self) -> temporalio.api.failure.v1.message_pb2.Failure: - """Failure details from the last failed attempt.""" + """Failure details from the last failed attempt. + DescribeActivityExecution does not set this field unless include_last_failure was true in the request. + """ last_worker_identity: builtins.str @property def current_retry_interval(self) -> google.protobuf.duration_pb2.Duration: @@ -327,6 +334,17 @@ class ActivityExecutionInfo(google.protobuf.message.Message): """Links to related entities, such as the entity that started this activity.""" total_heartbeat_count: builtins.int """Total number of heartbeats recorded across all attempts of this activity, including retries.""" + sdk_name: builtins.str + """The name of the SDK of the worker that most recently picked up an attempt of this activity. + Overwritten on each new attempt. Empty if unknown. + """ + sdk_version: builtins.str + """The version of the SDK of the worker that most recently picked up an attempt of this activity. + Overwritten on each new attempt. Empty if unknown. + """ + @property + def start_delay(self) -> google.protobuf.duration_pb2.Duration: + """Time to wait before dispatching the first activity task. This delay is not applied to retry attempts.""" def __init__( self, *, @@ -370,6 +388,9 @@ class ActivityExecutionInfo(google.protobuf.message.Message): links: collections.abc.Iterable[temporalio.api.common.v1.message_pb2.Link] | None = ..., total_heartbeat_count: builtins.int = ..., + sdk_name: builtins.str = ..., + sdk_version: builtins.str = ..., + start_delay: google.protobuf.duration_pb2.Duration | None = ..., ) -> None: ... def HasField( self, @@ -414,6 +435,8 @@ class ActivityExecutionInfo(google.protobuf.message.Message): b"schedule_to_start_timeout", "search_attributes", b"search_attributes", + "start_delay", + b"start_delay", "start_to_close_timeout", b"start_to_close_timeout", "user_metadata", @@ -475,8 +498,14 @@ class ActivityExecutionInfo(google.protobuf.message.Message): b"schedule_to_close_timeout", "schedule_to_start_timeout", b"schedule_to_start_timeout", + "sdk_name", + b"sdk_name", + "sdk_version", + b"sdk_version", "search_attributes", b"search_attributes", + "start_delay", + b"start_delay", "start_to_close_timeout", b"start_to_close_timeout", "state_size_bytes", diff --git a/temporalio/api/cloud/cloudservice/v1/__init__.py b/temporalio/api/cloud/cloudservice/v1/__init__.py index 31e4e7753..0586a752b 100644 --- a/temporalio/api/cloud/cloudservice/v1/__init__.py +++ b/temporalio/api/cloud/cloudservice/v1/__init__.py @@ -93,6 +93,8 @@ GetRegionResponse, GetRegionsRequest, GetRegionsResponse, + GetServiceAccountNamespaceAssignmentsRequest, + GetServiceAccountNamespaceAssignmentsResponse, GetServiceAccountRequest, GetServiceAccountResponse, GetServiceAccountsRequest, @@ -101,10 +103,14 @@ GetUsageResponse, GetUserGroupMembersRequest, GetUserGroupMembersResponse, + GetUserGroupNamespaceAssignmentsRequest, + GetUserGroupNamespaceAssignmentsResponse, GetUserGroupRequest, GetUserGroupResponse, GetUserGroupsRequest, GetUserGroupsResponse, + GetUserNamespaceAssignmentsRequest, + GetUserNamespaceAssignmentsResponse, GetUserRequest, GetUserResponse, GetUsersRequest, @@ -242,6 +248,8 @@ "GetRegionResponse", "GetRegionsRequest", "GetRegionsResponse", + "GetServiceAccountNamespaceAssignmentsRequest", + "GetServiceAccountNamespaceAssignmentsResponse", "GetServiceAccountRequest", "GetServiceAccountResponse", "GetServiceAccountsRequest", @@ -250,10 +258,14 @@ "GetUsageResponse", "GetUserGroupMembersRequest", "GetUserGroupMembersResponse", + "GetUserGroupNamespaceAssignmentsRequest", + "GetUserGroupNamespaceAssignmentsResponse", "GetUserGroupRequest", "GetUserGroupResponse", "GetUserGroupsRequest", "GetUserGroupsResponse", + "GetUserNamespaceAssignmentsRequest", + "GetUserNamespaceAssignmentsResponse", "GetUserRequest", "GetUserResponse", "GetUsersRequest", diff --git a/temporalio/api/cloud/cloudservice/v1/request_response_pb2.py b/temporalio/api/cloud/cloudservice/v1/request_response_pb2.py index b1874c825..5d7a6a28a 100644 --- a/temporalio/api/cloud/cloudservice/v1/request_response_pb2.py +++ b/temporalio/api/cloud/cloudservice/v1/request_response_pb2.py @@ -48,7 +48,7 @@ ) DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile( - b'\n9temporal/api/cloud/cloudservice/v1/request_response.proto\x12"temporal.api.cloud.cloudservice.v1\x1a\x1fgoogle/protobuf/timestamp.proto\x1a-temporal/api/cloud/operation/v1/message.proto\x1a,temporal/api/cloud/identity/v1/message.proto\x1a-temporal/api/cloud/namespace/v1/message.proto\x1a)temporal/api/cloud/nexus/v1/message.proto\x1a*temporal/api/cloud/region/v1/message.proto\x1a+temporal/api/cloud/account/v1/message.proto\x1a)temporal/api/cloud/usage/v1/message.proto\x1a\x34temporal/api/cloud/connectivityrule/v1/message.proto\x1a,temporal/api/cloud/auditlog/v1/message.proto\x1a+temporal/api/cloud/billing/v1/message.proto"\x1b\n\x19GetCurrentIdentityRequest"\xed\x01\n\x1aGetCurrentIdentityResponse\x12\x34\n\x04user\x18\x01 \x01(\x0b\x32$.temporal.api.cloud.identity.v1.UserH\x00\x12I\n\x0fservice_account\x18\x02 \x01(\x0b\x32..temporal.api.cloud.identity.v1.ServiceAccountH\x00\x12\x41\n\x11principal_api_key\x18\x03 \x01(\x0b\x32&.temporal.api.cloud.identity.v1.ApiKeyB\x0b\n\tprincipal"Z\n\x0fGetUsersRequest\x12\x11\n\tpage_size\x18\x01 \x01(\x05\x12\x12\n\npage_token\x18\x02 \x01(\t\x12\r\n\x05\x65mail\x18\x03 \x01(\t\x12\x11\n\tnamespace\x18\x04 \x01(\t"`\n\x10GetUsersResponse\x12\x33\n\x05users\x18\x01 \x03(\x0b\x32$.temporal.api.cloud.identity.v1.User\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\t"!\n\x0eGetUserRequest\x12\x0f\n\x07user_id\x18\x01 \x01(\t"E\n\x0fGetUserResponse\x12\x32\n\x04user\x18\x01 \x01(\x0b\x32$.temporal.api.cloud.identity.v1.User"g\n\x11\x43reateUserRequest\x12\x36\n\x04spec\x18\x01 \x01(\x0b\x32(.temporal.api.cloud.identity.v1.UserSpec\x12\x1a\n\x12\x61sync_operation_id\x18\x02 \x01(\t"o\n\x12\x43reateUserResponse\x12\x0f\n\x07user_id\x18\x01 \x01(\t\x12H\n\x0f\x61sync_operation\x18\x02 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"\x92\x01\n\x11UpdateUserRequest\x12\x0f\n\x07user_id\x18\x01 \x01(\t\x12\x36\n\x04spec\x18\x02 \x01(\x0b\x32(.temporal.api.cloud.identity.v1.UserSpec\x12\x18\n\x10resource_version\x18\x03 \x01(\t\x12\x1a\n\x12\x61sync_operation_id\x18\x04 \x01(\t"^\n\x12UpdateUserResponse\x12H\n\x0f\x61sync_operation\x18\x01 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"Z\n\x11\x44\x65leteUserRequest\x12\x0f\n\x07user_id\x18\x01 \x01(\t\x12\x18\n\x10resource_version\x18\x02 \x01(\t\x12\x1a\n\x12\x61sync_operation_id\x18\x03 \x01(\t"^\n\x12\x44\x65leteUserResponse\x12H\n\x0f\x61sync_operation\x18\x01 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"\xba\x01\n\x1dSetUserNamespaceAccessRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x0f\n\x07user_id\x18\x02 \x01(\t\x12?\n\x06\x61\x63\x63\x65ss\x18\x03 \x01(\x0b\x32/.temporal.api.cloud.identity.v1.NamespaceAccess\x12\x18\n\x10resource_version\x18\x04 \x01(\t\x12\x1a\n\x12\x61sync_operation_id\x18\x05 \x01(\t"j\n\x1eSetUserNamespaceAccessResponse\x12H\n\x0f\x61sync_operation\x18\x01 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"6\n\x18GetAsyncOperationRequest\x12\x1a\n\x12\x61sync_operation_id\x18\x01 \x01(\t"e\n\x19GetAsyncOperationResponse\x12H\n\x0f\x61sync_operation\x18\x01 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"\xf3\x01\n\x16\x43reateNamespaceRequest\x12<\n\x04spec\x18\x02 \x01(\x0b\x32..temporal.api.cloud.namespace.v1.NamespaceSpec\x12\x1a\n\x12\x61sync_operation_id\x18\x03 \x01(\t\x12R\n\x04tags\x18\x04 \x03(\x0b\x32\x44.temporal.api.cloud.cloudservice.v1.CreateNamespaceRequest.TagsEntry\x1a+\n\tTagsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01"v\n\x17\x43reateNamespaceResponse\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12H\n\x0f\x61sync_operation\x18\x02 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"K\n\x14GetNamespacesRequest\x12\x11\n\tpage_size\x18\x01 \x01(\x05\x12\x12\n\npage_token\x18\x02 \x01(\t\x12\x0c\n\x04name\x18\x03 \x01(\t"p\n\x15GetNamespacesResponse\x12>\n\nnamespaces\x18\x01 \x03(\x0b\x32*.temporal.api.cloud.namespace.v1.Namespace\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\t"(\n\x13GetNamespaceRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t"U\n\x14GetNamespaceResponse\x12=\n\tnamespace\x18\x01 \x01(\x0b\x32*.temporal.api.cloud.namespace.v1.Namespace"\x9f\x01\n\x16UpdateNamespaceRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12<\n\x04spec\x18\x02 \x01(\x0b\x32..temporal.api.cloud.namespace.v1.NamespaceSpec\x12\x18\n\x10resource_version\x18\x03 \x01(\t\x12\x1a\n\x12\x61sync_operation_id\x18\x04 \x01(\t"c\n\x17UpdateNamespaceResponse\x12H\n\x0f\x61sync_operation\x18\x01 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"\xc6\x01\n"RenameCustomSearchAttributeRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12-\n%existing_custom_search_attribute_name\x18\x02 \x01(\t\x12(\n new_custom_search_attribute_name\x18\x03 \x01(\t\x12\x18\n\x10resource_version\x18\x04 \x01(\t\x12\x1a\n\x12\x61sync_operation_id\x18\x05 \x01(\t"o\n#RenameCustomSearchAttributeResponse\x12H\n\x0f\x61sync_operation\x18\x01 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"a\n\x16\x44\x65leteNamespaceRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x18\n\x10resource_version\x18\x02 \x01(\t\x12\x1a\n\x12\x61sync_operation_id\x18\x03 \x01(\t"c\n\x17\x44\x65leteNamespaceResponse\x12H\n\x0f\x61sync_operation\x18\x01 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"_\n\x1e\x46\x61iloverNamespaceRegionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x0e\n\x06region\x18\x02 \x01(\t\x12\x1a\n\x12\x61sync_operation_id\x18\x03 \x01(\t"k\n\x1f\x46\x61iloverNamespaceRegionResponse\x12H\n\x0f\x61sync_operation\x18\x01 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"t\n\x19\x41\x64\x64NamespaceRegionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x0e\n\x06region\x18\x02 \x01(\t\x12\x18\n\x10resource_version\x18\x03 \x01(\t\x12\x1a\n\x12\x61sync_operation_id\x18\x04 \x01(\t"f\n\x1a\x41\x64\x64NamespaceRegionResponse\x12H\n\x0f\x61sync_operation\x18\x01 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"w\n\x1c\x44\x65leteNamespaceRegionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x0e\n\x06region\x18\x02 \x01(\t\x12\x18\n\x10resource_version\x18\x03 \x01(\t\x12\x1a\n\x12\x61sync_operation_id\x18\x04 \x01(\t"i\n\x1d\x44\x65leteNamespaceRegionResponse\x12H\n\x0f\x61sync_operation\x18\x01 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"\x13\n\x11GetRegionsRequest"K\n\x12GetRegionsResponse\x12\x35\n\x07regions\x18\x01 \x03(\x0b\x32$.temporal.api.cloud.region.v1.Region""\n\x10GetRegionRequest\x12\x0e\n\x06region\x18\x01 \x01(\t"I\n\x11GetRegionResponse\x12\x34\n\x06region\x18\x01 \x01(\x0b\x32$.temporal.api.cloud.region.v1.Region"\xae\x01\n\x11GetApiKeysRequest\x12\x11\n\tpage_size\x18\x01 \x01(\x05\x12\x12\n\npage_token\x18\x02 \x01(\t\x12\x10\n\x08owner_id\x18\x03 \x01(\t\x12!\n\x15owner_type_deprecated\x18\x04 \x01(\tB\x02\x18\x01\x12=\n\nowner_type\x18\x05 \x01(\x0e\x32).temporal.api.cloud.identity.v1.OwnerType"g\n\x12GetApiKeysResponse\x12\x38\n\x08\x61pi_keys\x18\x01 \x03(\x0b\x32&.temporal.api.cloud.identity.v1.ApiKey\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\t""\n\x10GetApiKeyRequest\x12\x0e\n\x06key_id\x18\x01 \x01(\t"L\n\x11GetApiKeyResponse\x12\x37\n\x07\x61pi_key\x18\x01 \x01(\x0b\x32&.temporal.api.cloud.identity.v1.ApiKey"k\n\x13\x43reateApiKeyRequest\x12\x38\n\x04spec\x18\x01 \x01(\x0b\x32*.temporal.api.cloud.identity.v1.ApiKeySpec\x12\x1a\n\x12\x61sync_operation_id\x18\x02 \x01(\t"\x7f\n\x14\x43reateApiKeyResponse\x12\x0e\n\x06key_id\x18\x01 \x01(\t\x12\r\n\x05token\x18\x02 \x01(\t\x12H\n\x0f\x61sync_operation\x18\x03 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"\x95\x01\n\x13UpdateApiKeyRequest\x12\x0e\n\x06key_id\x18\x01 \x01(\t\x12\x38\n\x04spec\x18\x02 \x01(\x0b\x32*.temporal.api.cloud.identity.v1.ApiKeySpec\x12\x18\n\x10resource_version\x18\x03 \x01(\t\x12\x1a\n\x12\x61sync_operation_id\x18\x04 \x01(\t"`\n\x14UpdateApiKeyResponse\x12H\n\x0f\x61sync_operation\x18\x01 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"[\n\x13\x44\x65leteApiKeyRequest\x12\x0e\n\x06key_id\x18\x01 \x01(\t\x12\x18\n\x10resource_version\x18\x02 \x01(\t\x12\x1a\n\x12\x61sync_operation_id\x18\x03 \x01(\t"`\n\x14\x44\x65leteApiKeyResponse\x12H\n\x0f\x61sync_operation\x18\x01 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"\x87\x01\n\x18GetNexusEndpointsRequest\x12\x11\n\tpage_size\x18\x01 \x01(\x05\x12\x12\n\npage_token\x18\x02 \x01(\t\x12\x1b\n\x13target_namespace_id\x18\x03 \x01(\t\x12\x19\n\x11target_task_queue\x18\x04 \x01(\t\x12\x0c\n\x04name\x18\x05 \x01(\t"n\n\x19GetNexusEndpointsResponse\x12\x38\n\tendpoints\x18\x01 \x03(\x0b\x32%.temporal.api.cloud.nexus.v1.Endpoint\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\t".\n\x17GetNexusEndpointRequest\x12\x13\n\x0b\x65ndpoint_id\x18\x01 \x01(\t"S\n\x18GetNexusEndpointResponse\x12\x37\n\x08\x65ndpoint\x18\x01 \x01(\x0b\x32%.temporal.api.cloud.nexus.v1.Endpoint"q\n\x1a\x43reateNexusEndpointRequest\x12\x37\n\x04spec\x18\x01 \x01(\x0b\x32).temporal.api.cloud.nexus.v1.EndpointSpec\x12\x1a\n\x12\x61sync_operation_id\x18\x02 \x01(\t"|\n\x1b\x43reateNexusEndpointResponse\x12\x13\n\x0b\x65ndpoint_id\x18\x01 \x01(\t\x12H\n\x0f\x61sync_operation\x18\x02 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"\xa0\x01\n\x1aUpdateNexusEndpointRequest\x12\x13\n\x0b\x65ndpoint_id\x18\x01 \x01(\t\x12\x37\n\x04spec\x18\x02 \x01(\x0b\x32).temporal.api.cloud.nexus.v1.EndpointSpec\x12\x18\n\x10resource_version\x18\x03 \x01(\t\x12\x1a\n\x12\x61sync_operation_id\x18\x04 \x01(\t"g\n\x1bUpdateNexusEndpointResponse\x12H\n\x0f\x61sync_operation\x18\x01 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"g\n\x1a\x44\x65leteNexusEndpointRequest\x12\x13\n\x0b\x65ndpoint_id\x18\x01 \x01(\t\x12\x18\n\x10resource_version\x18\x02 \x01(\t\x12\x1a\n\x12\x61sync_operation_id\x18\x03 \x01(\t"g\n\x1b\x44\x65leteNexusEndpointResponse\x12H\n\x0f\x61sync_operation\x18\x01 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"\xf5\x02\n\x14GetUserGroupsRequest\x12\x11\n\tpage_size\x18\x01 \x01(\x05\x12\x12\n\npage_token\x18\x02 \x01(\t\x12\x11\n\tnamespace\x18\x03 \x01(\t\x12\x14\n\x0c\x64isplay_name\x18\x04 \x01(\t\x12`\n\x0cgoogle_group\x18\x05 \x01(\x0b\x32J.temporal.api.cloud.cloudservice.v1.GetUserGroupsRequest.GoogleGroupFilter\x12\\\n\nscim_group\x18\x06 \x01(\x0b\x32H.temporal.api.cloud.cloudservice.v1.GetUserGroupsRequest.SCIMGroupFilter\x1a*\n\x11GoogleGroupFilter\x12\x15\n\remail_address\x18\x01 \x01(\t\x1a!\n\x0fSCIMGroupFilter\x12\x0e\n\x06idp_id\x18\x01 \x01(\t"k\n\x15GetUserGroupsResponse\x12\x39\n\x06groups\x18\x01 \x03(\x0b\x32).temporal.api.cloud.identity.v1.UserGroup\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\t"\'\n\x13GetUserGroupRequest\x12\x10\n\x08group_id\x18\x01 \x01(\t"P\n\x14GetUserGroupResponse\x12\x38\n\x05group\x18\x01 \x01(\x0b\x32).temporal.api.cloud.identity.v1.UserGroup"q\n\x16\x43reateUserGroupRequest\x12;\n\x04spec\x18\x01 \x01(\x0b\x32-.temporal.api.cloud.identity.v1.UserGroupSpec\x12\x1a\n\x12\x61sync_operation_id\x18\x02 \x01(\t"u\n\x17\x43reateUserGroupResponse\x12\x10\n\x08group_id\x18\x01 \x01(\t\x12H\n\x0f\x61sync_operation\x18\x02 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"\x9d\x01\n\x16UpdateUserGroupRequest\x12\x10\n\x08group_id\x18\x01 \x01(\t\x12;\n\x04spec\x18\x02 \x01(\x0b\x32-.temporal.api.cloud.identity.v1.UserGroupSpec\x12\x18\n\x10resource_version\x18\x03 \x01(\t\x12\x1a\n\x12\x61sync_operation_id\x18\x04 \x01(\t"c\n\x17UpdateUserGroupResponse\x12H\n\x0f\x61sync_operation\x18\x01 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"`\n\x16\x44\x65leteUserGroupRequest\x12\x10\n\x08group_id\x18\x01 \x01(\t\x12\x18\n\x10resource_version\x18\x02 \x01(\t\x12\x1a\n\x12\x61sync_operation_id\x18\x03 \x01(\t"c\n\x17\x44\x65leteUserGroupResponse\x12H\n\x0f\x61sync_operation\x18\x01 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"\xc0\x01\n"SetUserGroupNamespaceAccessRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x10\n\x08group_id\x18\x02 \x01(\t\x12?\n\x06\x61\x63\x63\x65ss\x18\x03 \x01(\x0b\x32/.temporal.api.cloud.identity.v1.NamespaceAccess\x12\x18\n\x10resource_version\x18\x04 \x01(\t\x12\x1a\n\x12\x61sync_operation_id\x18\x05 \x01(\t"o\n#SetUserGroupNamespaceAccessResponse\x12H\n\x0f\x61sync_operation\x18\x01 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"\x8f\x01\n\x19\x41\x64\x64UserGroupMemberRequest\x12\x10\n\x08group_id\x18\x01 \x01(\t\x12\x44\n\tmember_id\x18\x02 \x01(\x0b\x32\x31.temporal.api.cloud.identity.v1.UserGroupMemberId\x12\x1a\n\x12\x61sync_operation_id\x18\x03 \x01(\t"f\n\x1a\x41\x64\x64UserGroupMemberResponse\x12H\n\x0f\x61sync_operation\x18\x01 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"\x92\x01\n\x1cRemoveUserGroupMemberRequest\x12\x10\n\x08group_id\x18\x01 \x01(\t\x12\x44\n\tmember_id\x18\x02 \x01(\x0b\x32\x31.temporal.api.cloud.identity.v1.UserGroupMemberId\x12\x1a\n\x12\x61sync_operation_id\x18\x03 \x01(\t"i\n\x1dRemoveUserGroupMemberResponse\x12H\n\x0f\x61sync_operation\x18\x01 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"U\n\x1aGetUserGroupMembersRequest\x12\x11\n\tpage_size\x18\x01 \x01(\x05\x12\x12\n\npage_token\x18\x02 \x01(\t\x12\x10\n\x08group_id\x18\x03 \x01(\t"x\n\x1bGetUserGroupMembersResponse\x12@\n\x07members\x18\x01 \x03(\x0b\x32/.temporal.api.cloud.identity.v1.UserGroupMember\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\t"{\n\x1b\x43reateServiceAccountRequest\x12@\n\x04spec\x18\x01 \x01(\x0b\x32\x32.temporal.api.cloud.identity.v1.ServiceAccountSpec\x12\x1a\n\x12\x61sync_operation_id\x18\x02 \x01(\t"\x84\x01\n\x1c\x43reateServiceAccountResponse\x12\x1a\n\x12service_account_id\x18\x01 \x01(\t\x12H\n\x0f\x61sync_operation\x18\x02 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"6\n\x18GetServiceAccountRequest\x12\x1a\n\x12service_account_id\x18\x01 \x01(\t"d\n\x19GetServiceAccountResponse\x12G\n\x0fservice_account\x18\x01 \x01(\x0b\x32..temporal.api.cloud.identity.v1.ServiceAccount"B\n\x19GetServiceAccountsRequest\x12\x11\n\tpage_size\x18\x01 \x01(\x05\x12\x12\n\npage_token\x18\x02 \x01(\t"~\n\x1aGetServiceAccountsResponse\x12G\n\x0fservice_account\x18\x01 \x03(\x0b\x32..temporal.api.cloud.identity.v1.ServiceAccount\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\t"\xb1\x01\n\x1bUpdateServiceAccountRequest\x12\x1a\n\x12service_account_id\x18\x01 \x01(\t\x12@\n\x04spec\x18\x02 \x01(\x0b\x32\x32.temporal.api.cloud.identity.v1.ServiceAccountSpec\x12\x18\n\x10resource_version\x18\x03 \x01(\t\x12\x1a\n\x12\x61sync_operation_id\x18\x04 \x01(\t"h\n\x1cUpdateServiceAccountResponse\x12H\n\x0f\x61sync_operation\x18\x01 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"\xcf\x01\n\'SetServiceAccountNamespaceAccessRequest\x12\x1a\n\x12service_account_id\x18\x01 \x01(\t\x12\x11\n\tnamespace\x18\x02 \x01(\t\x12?\n\x06\x61\x63\x63\x65ss\x18\x03 \x01(\x0b\x32/.temporal.api.cloud.identity.v1.NamespaceAccess\x12\x18\n\x10resource_version\x18\x04 \x01(\t\x12\x1a\n\x12\x61sync_operation_id\x18\x05 \x01(\t"t\n(SetServiceAccountNamespaceAccessResponse\x12H\n\x0f\x61sync_operation\x18\x01 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"o\n\x1b\x44\x65leteServiceAccountRequest\x12\x1a\n\x12service_account_id\x18\x01 \x01(\t\x12\x18\n\x10resource_version\x18\x02 \x01(\t\x12\x1a\n\x12\x61sync_operation_id\x18\x03 \x01(\t"h\n\x1c\x44\x65leteServiceAccountResponse\x12H\n\x0f\x61sync_operation\x18\x01 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"\xaa\x01\n\x0fGetUsageRequest\x12\x38\n\x14start_time_inclusive\x18\x01 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x36\n\x12\x65nd_time_exclusive\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x11\n\tpage_size\x18\x03 \x01(\x05\x12\x12\n\npage_token\x18\x04 \x01(\t"d\n\x10GetUsageResponse\x12\x37\n\tsummaries\x18\x01 \x03(\x0b\x32$.temporal.api.cloud.usage.v1.Summary\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\t"\x13\n\x11GetAccountRequest"M\n\x12GetAccountResponse\x12\x37\n\x07\x61\x63\x63ount\x18\x01 \x01(\x0b\x32&.temporal.api.cloud.account.v1.Account"\x86\x01\n\x14UpdateAccountRequest\x12\x38\n\x04spec\x18\x01 \x01(\x0b\x32*.temporal.api.cloud.account.v1.AccountSpec\x12\x18\n\x10resource_version\x18\x02 \x01(\t\x12\x1a\n\x12\x61sync_operation_id\x18\x03 \x01(\t"a\n\x15UpdateAccountResponse\x12H\n\x0f\x61sync_operation\x18\x01 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"\x90\x01\n CreateNamespaceExportSinkRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12=\n\x04spec\x18\x02 \x01(\x0b\x32/.temporal.api.cloud.namespace.v1.ExportSinkSpec\x12\x1a\n\x12\x61sync_operation_id\x18\x03 \x01(\t"m\n!CreateNamespaceExportSinkResponse\x12H\n\x0f\x61sync_operation\x18\x01 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"@\n\x1dGetNamespaceExportSinkRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x0c\n\x04name\x18\x02 \x01(\t"[\n\x1eGetNamespaceExportSinkResponse\x12\x39\n\x04sink\x18\x01 \x01(\x0b\x32+.temporal.api.cloud.namespace.v1.ExportSink"Z\n\x1eGetNamespaceExportSinksRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x11\n\tpage_size\x18\x02 \x01(\x05\x12\x12\n\npage_token\x18\x03 \x01(\t"v\n\x1fGetNamespaceExportSinksResponse\x12:\n\x05sinks\x18\x01 \x03(\x0b\x32+.temporal.api.cloud.namespace.v1.ExportSink\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\t"\xaa\x01\n UpdateNamespaceExportSinkRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12=\n\x04spec\x18\x02 \x01(\x0b\x32/.temporal.api.cloud.namespace.v1.ExportSinkSpec\x12\x18\n\x10resource_version\x18\x03 \x01(\t\x12\x1a\n\x12\x61sync_operation_id\x18\x04 \x01(\t"m\n!UpdateNamespaceExportSinkResponse\x12H\n\x0f\x61sync_operation\x18\x01 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"y\n DeleteNamespaceExportSinkRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x0c\n\x04name\x18\x02 \x01(\t\x12\x18\n\x10resource_version\x18\x03 \x01(\t\x12\x1a\n\x12\x61sync_operation_id\x18\x04 \x01(\t"m\n!DeleteNamespaceExportSinkResponse\x12H\n\x0f\x61sync_operation\x18\x01 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"v\n"ValidateNamespaceExportSinkRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12=\n\x04spec\x18\x02 \x01(\x0b\x32/.temporal.api.cloud.namespace.v1.ExportSinkSpec"%\n#ValidateNamespaceExportSinkResponse"\x82\x02\n\x1aUpdateNamespaceTagsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12h\n\x0etags_to_upsert\x18\x02 \x03(\x0b\x32P.temporal.api.cloud.cloudservice.v1.UpdateNamespaceTagsRequest.TagsToUpsertEntry\x12\x16\n\x0etags_to_remove\x18\x03 \x03(\t\x12\x1a\n\x12\x61sync_operation_id\x18\x04 \x01(\t\x1a\x33\n\x11TagsToUpsertEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01"g\n\x1bUpdateNamespaceTagsResponse\x12H\n\x0f\x61sync_operation\x18\x01 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"\x87\x01\n\x1d\x43reateConnectivityRuleRequest\x12J\n\x04spec\x18\x01 \x01(\x0b\x32<.temporal.api.cloud.connectivityrule.v1.ConnectivityRuleSpec\x12\x1a\n\x12\x61sync_operation_id\x18\x02 \x01(\t"\x88\x01\n\x1e\x43reateConnectivityRuleResponse\x12\x1c\n\x14\x63onnectivity_rule_id\x18\x01 \x01(\t\x12H\n\x0f\x61sync_operation\x18\x02 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation":\n\x1aGetConnectivityRuleRequest\x12\x1c\n\x14\x63onnectivity_rule_id\x18\x01 \x01(\t"r\n\x1bGetConnectivityRuleResponse\x12S\n\x11\x63onnectivity_rule\x18\x01 \x01(\x0b\x32\x38.temporal.api.cloud.connectivityrule.v1.ConnectivityRule"W\n\x1bGetConnectivityRulesRequest\x12\x11\n\tpage_size\x18\x01 \x01(\x05\x12\x12\n\npage_token\x18\x02 \x01(\t\x12\x11\n\tnamespace\x18\x03 \x01(\t"\x8d\x01\n\x1cGetConnectivityRulesResponse\x12T\n\x12\x63onnectivity_rules\x18\x01 \x03(\x0b\x32\x38.temporal.api.cloud.connectivityrule.v1.ConnectivityRule\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\t"s\n\x1d\x44\x65leteConnectivityRuleRequest\x12\x1c\n\x14\x63onnectivity_rule_id\x18\x01 \x01(\t\x12\x18\n\x10resource_version\x18\x02 \x01(\t\x12\x1a\n\x12\x61sync_operation_id\x18\x03 \x01(\t"j\n\x1e\x44\x65leteConnectivityRuleResponse\x12H\n\x0f\x61sync_operation\x18\x01 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"\xae\x01\n\x13GetAuditLogsRequest\x12\x11\n\tpage_size\x18\x01 \x01(\x05\x12\x12\n\npage_token\x18\x02 \x01(\t\x12\x38\n\x14start_time_inclusive\x18\x03 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x36\n\x12\x65nd_time_exclusive\x18\x04 \x01(\x0b\x32\x1a.google.protobuf.Timestamp"h\n\x14GetAuditLogsResponse\x12\x37\n\x04logs\x18\x01 \x03(\x0b\x32).temporal.api.cloud.auditlog.v1.LogRecord\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\t"c\n"ValidateAccountAuditLogSinkRequest\x12=\n\x04spec\x18\x01 \x01(\x0b\x32/.temporal.api.cloud.account.v1.AuditLogSinkSpec"%\n#ValidateAccountAuditLogSinkResponse"}\n CreateAccountAuditLogSinkRequest\x12=\n\x04spec\x18\x01 \x01(\x0b\x32/.temporal.api.cloud.account.v1.AuditLogSinkSpec\x12\x1a\n\x12\x61sync_operation_id\x18\x02 \x01(\t"m\n!CreateAccountAuditLogSinkResponse\x12H\n\x0f\x61sync_operation\x18\x01 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"-\n\x1dGetAccountAuditLogSinkRequest\x12\x0c\n\x04name\x18\x01 \x01(\t"[\n\x1eGetAccountAuditLogSinkResponse\x12\x39\n\x04sink\x18\x01 \x01(\x0b\x32+.temporal.api.cloud.account.v1.AuditLogSink"G\n\x1eGetAccountAuditLogSinksRequest\x12\x11\n\tpage_size\x18\x01 \x01(\x05\x12\x12\n\npage_token\x18\x02 \x01(\t"v\n\x1fGetAccountAuditLogSinksResponse\x12:\n\x05sinks\x18\x01 \x03(\x0b\x32+.temporal.api.cloud.account.v1.AuditLogSink\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\t"\x97\x01\n UpdateAccountAuditLogSinkRequest\x12=\n\x04spec\x18\x01 \x01(\x0b\x32/.temporal.api.cloud.account.v1.AuditLogSinkSpec\x12\x18\n\x10resource_version\x18\x02 \x01(\t\x12\x1a\n\x12\x61sync_operation_id\x18\x03 \x01(\t"m\n!UpdateAccountAuditLogSinkResponse\x12H\n\x0f\x61sync_operation\x18\x01 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"f\n DeleteAccountAuditLogSinkRequest\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x18\n\x10resource_version\x18\x02 \x01(\t\x12\x1a\n\x12\x61sync_operation_id\x18\x03 \x01(\t"m\n!DeleteAccountAuditLogSinkResponse\x12H\n\x0f\x61sync_operation\x18\x01 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"4\n\x1fGetNamespaceCapacityInfoRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t"q\n GetNamespaceCapacityInfoResponse\x12M\n\rcapacity_info\x18\x01 \x01(\x0b\x32\x36.temporal.api.cloud.namespace.v1.NamespaceCapacityInfo"x\n\x1a\x43reateBillingReportRequest\x12>\n\x04spec\x18\x01 \x01(\x0b\x32\x30.temporal.api.cloud.billing.v1.BillingReportSpec\x12\x1a\n\x12\x61sync_operation_id\x18\x02 \x01(\t"\x82\x01\n\x1b\x43reateBillingReportResponse\x12\x19\n\x11\x62illing_report_id\x18\x01 \x01(\t\x12H\n\x0f\x61sync_operation\x18\x02 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"4\n\x17GetBillingReportRequest\x12\x19\n\x11\x62illing_report_id\x18\x01 \x01(\t"`\n\x18GetBillingReportResponse\x12\x44\n\x0e\x62illing_report\x18\x01 \x01(\x0b\x32,.temporal.api.cloud.billing.v1.BillingReport">\n\x15GetCustomRolesRequest\x12\x11\n\tpage_size\x18\x01 \x01(\x05\x12\x12\n\npage_token\x18\x02 \x01(\t"s\n\x16GetCustomRolesResponse\x12@\n\x0c\x63ustom_roles\x18\x01 \x03(\x0b\x32*.temporal.api.cloud.identity.v1.CustomRole\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\t"\'\n\x14GetCustomRoleRequest\x12\x0f\n\x07role_id\x18\x01 \x01(\t"X\n\x15GetCustomRoleResponse\x12?\n\x0b\x63ustom_role\x18\x01 \x01(\x0b\x32*.temporal.api.cloud.identity.v1.CustomRole"s\n\x17\x43reateCustomRoleRequest\x12<\n\x04spec\x18\x01 \x01(\x0b\x32..temporal.api.cloud.identity.v1.CustomRoleSpec\x12\x1a\n\x12\x61sync_operation_id\x18\x02 \x01(\t"u\n\x18\x43reateCustomRoleResponse\x12\x0f\n\x07role_id\x18\x01 \x01(\t\x12H\n\x0f\x61sync_operation\x18\x02 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"\x9e\x01\n\x17UpdateCustomRoleRequest\x12\x0f\n\x07role_id\x18\x01 \x01(\t\x12<\n\x04spec\x18\x02 \x01(\x0b\x32..temporal.api.cloud.identity.v1.CustomRoleSpec\x12\x18\n\x10resource_version\x18\x03 \x01(\t\x12\x1a\n\x12\x61sync_operation_id\x18\x04 \x01(\t"d\n\x18UpdateCustomRoleResponse\x12H\n\x0f\x61sync_operation\x18\x01 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"`\n\x17\x44\x65leteCustomRoleRequest\x12\x0f\n\x07role_id\x18\x01 \x01(\t\x12\x18\n\x10resource_version\x18\x02 \x01(\t\x12\x1a\n\x12\x61sync_operation_id\x18\x03 \x01(\t"d\n\x18\x44\x65leteCustomRoleResponse\x12H\n\x0f\x61sync_operation\x18\x01 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperationB\xc8\x01\n%io.temporal.api.cloud.cloudservice.v1B\x14RequestResponseProtoP\x01Z5go.temporal.io/api/cloud/cloudservice/v1;cloudservice\xaa\x02$Temporalio.Api.Cloud.CloudService.V1\xea\x02(Temporalio::Api::Cloud::CloudService::V1b\x06proto3' + b'\n9temporal/api/cloud/cloudservice/v1/request_response.proto\x12"temporal.api.cloud.cloudservice.v1\x1a\x1fgoogle/protobuf/timestamp.proto\x1a-temporal/api/cloud/operation/v1/message.proto\x1a,temporal/api/cloud/identity/v1/message.proto\x1a-temporal/api/cloud/namespace/v1/message.proto\x1a)temporal/api/cloud/nexus/v1/message.proto\x1a*temporal/api/cloud/region/v1/message.proto\x1a+temporal/api/cloud/account/v1/message.proto\x1a)temporal/api/cloud/usage/v1/message.proto\x1a\x34temporal/api/cloud/connectivityrule/v1/message.proto\x1a,temporal/api/cloud/auditlog/v1/message.proto\x1a+temporal/api/cloud/billing/v1/message.proto"\x1b\n\x19GetCurrentIdentityRequest"\xed\x01\n\x1aGetCurrentIdentityResponse\x12\x34\n\x04user\x18\x01 \x01(\x0b\x32$.temporal.api.cloud.identity.v1.UserH\x00\x12I\n\x0fservice_account\x18\x02 \x01(\x0b\x32..temporal.api.cloud.identity.v1.ServiceAccountH\x00\x12\x41\n\x11principal_api_key\x18\x03 \x01(\x0b\x32&.temporal.api.cloud.identity.v1.ApiKeyB\x0b\n\tprincipal"Z\n\x0fGetUsersRequest\x12\x11\n\tpage_size\x18\x01 \x01(\x05\x12\x12\n\npage_token\x18\x02 \x01(\t\x12\r\n\x05\x65mail\x18\x03 \x01(\t\x12\x11\n\tnamespace\x18\x04 \x01(\t"`\n\x10GetUsersResponse\x12\x33\n\x05users\x18\x01 \x03(\x0b\x32$.temporal.api.cloud.identity.v1.User\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\t"!\n\x0eGetUserRequest\x12\x0f\n\x07user_id\x18\x01 \x01(\t"E\n\x0fGetUserResponse\x12\x32\n\x04user\x18\x01 \x01(\x0b\x32$.temporal.api.cloud.identity.v1.User"g\n\x11\x43reateUserRequest\x12\x36\n\x04spec\x18\x01 \x01(\x0b\x32(.temporal.api.cloud.identity.v1.UserSpec\x12\x1a\n\x12\x61sync_operation_id\x18\x02 \x01(\t"o\n\x12\x43reateUserResponse\x12\x0f\n\x07user_id\x18\x01 \x01(\t\x12H\n\x0f\x61sync_operation\x18\x02 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"\x92\x01\n\x11UpdateUserRequest\x12\x0f\n\x07user_id\x18\x01 \x01(\t\x12\x36\n\x04spec\x18\x02 \x01(\x0b\x32(.temporal.api.cloud.identity.v1.UserSpec\x12\x18\n\x10resource_version\x18\x03 \x01(\t\x12\x1a\n\x12\x61sync_operation_id\x18\x04 \x01(\t"^\n\x12UpdateUserResponse\x12H\n\x0f\x61sync_operation\x18\x01 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"Z\n\x11\x44\x65leteUserRequest\x12\x0f\n\x07user_id\x18\x01 \x01(\t\x12\x18\n\x10resource_version\x18\x02 \x01(\t\x12\x1a\n\x12\x61sync_operation_id\x18\x03 \x01(\t"^\n\x12\x44\x65leteUserResponse\x12H\n\x0f\x61sync_operation\x18\x01 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"\xba\x01\n\x1dSetUserNamespaceAccessRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x0f\n\x07user_id\x18\x02 \x01(\t\x12?\n\x06\x61\x63\x63\x65ss\x18\x03 \x01(\x0b\x32/.temporal.api.cloud.identity.v1.NamespaceAccess\x12\x18\n\x10resource_version\x18\x04 \x01(\t\x12\x1a\n\x12\x61sync_operation_id\x18\x05 \x01(\t"j\n\x1eSetUserNamespaceAccessResponse\x12H\n\x0f\x61sync_operation\x18\x01 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"6\n\x18GetAsyncOperationRequest\x12\x1a\n\x12\x61sync_operation_id\x18\x01 \x01(\t"e\n\x19GetAsyncOperationResponse\x12H\n\x0f\x61sync_operation\x18\x01 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"\xf3\x01\n\x16\x43reateNamespaceRequest\x12<\n\x04spec\x18\x02 \x01(\x0b\x32..temporal.api.cloud.namespace.v1.NamespaceSpec\x12\x1a\n\x12\x61sync_operation_id\x18\x03 \x01(\t\x12R\n\x04tags\x18\x04 \x03(\x0b\x32\x44.temporal.api.cloud.cloudservice.v1.CreateNamespaceRequest.TagsEntry\x1a+\n\tTagsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01"v\n\x17\x43reateNamespaceResponse\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12H\n\x0f\x61sync_operation\x18\x02 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"K\n\x14GetNamespacesRequest\x12\x11\n\tpage_size\x18\x01 \x01(\x05\x12\x12\n\npage_token\x18\x02 \x01(\t\x12\x0c\n\x04name\x18\x03 \x01(\t"p\n\x15GetNamespacesResponse\x12>\n\nnamespaces\x18\x01 \x03(\x0b\x32*.temporal.api.cloud.namespace.v1.Namespace\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\t"(\n\x13GetNamespaceRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t"U\n\x14GetNamespaceResponse\x12=\n\tnamespace\x18\x01 \x01(\x0b\x32*.temporal.api.cloud.namespace.v1.Namespace"\x9f\x01\n\x16UpdateNamespaceRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12<\n\x04spec\x18\x02 \x01(\x0b\x32..temporal.api.cloud.namespace.v1.NamespaceSpec\x12\x18\n\x10resource_version\x18\x03 \x01(\t\x12\x1a\n\x12\x61sync_operation_id\x18\x04 \x01(\t"c\n\x17UpdateNamespaceResponse\x12H\n\x0f\x61sync_operation\x18\x01 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"\xc6\x01\n"RenameCustomSearchAttributeRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12-\n%existing_custom_search_attribute_name\x18\x02 \x01(\t\x12(\n new_custom_search_attribute_name\x18\x03 \x01(\t\x12\x18\n\x10resource_version\x18\x04 \x01(\t\x12\x1a\n\x12\x61sync_operation_id\x18\x05 \x01(\t"o\n#RenameCustomSearchAttributeResponse\x12H\n\x0f\x61sync_operation\x18\x01 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"a\n\x16\x44\x65leteNamespaceRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x18\n\x10resource_version\x18\x02 \x01(\t\x12\x1a\n\x12\x61sync_operation_id\x18\x03 \x01(\t"c\n\x17\x44\x65leteNamespaceResponse\x12H\n\x0f\x61sync_operation\x18\x01 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"_\n\x1e\x46\x61iloverNamespaceRegionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x0e\n\x06region\x18\x02 \x01(\t\x12\x1a\n\x12\x61sync_operation_id\x18\x03 \x01(\t"k\n\x1f\x46\x61iloverNamespaceRegionResponse\x12H\n\x0f\x61sync_operation\x18\x01 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"t\n\x19\x41\x64\x64NamespaceRegionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x0e\n\x06region\x18\x02 \x01(\t\x12\x18\n\x10resource_version\x18\x03 \x01(\t\x12\x1a\n\x12\x61sync_operation_id\x18\x04 \x01(\t"f\n\x1a\x41\x64\x64NamespaceRegionResponse\x12H\n\x0f\x61sync_operation\x18\x01 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"w\n\x1c\x44\x65leteNamespaceRegionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x0e\n\x06region\x18\x02 \x01(\t\x12\x18\n\x10resource_version\x18\x03 \x01(\t\x12\x1a\n\x12\x61sync_operation_id\x18\x04 \x01(\t"i\n\x1d\x44\x65leteNamespaceRegionResponse\x12H\n\x0f\x61sync_operation\x18\x01 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"\x13\n\x11GetRegionsRequest"K\n\x12GetRegionsResponse\x12\x35\n\x07regions\x18\x01 \x03(\x0b\x32$.temporal.api.cloud.region.v1.Region""\n\x10GetRegionRequest\x12\x0e\n\x06region\x18\x01 \x01(\t"I\n\x11GetRegionResponse\x12\x34\n\x06region\x18\x01 \x01(\x0b\x32$.temporal.api.cloud.region.v1.Region"\xae\x01\n\x11GetApiKeysRequest\x12\x11\n\tpage_size\x18\x01 \x01(\x05\x12\x12\n\npage_token\x18\x02 \x01(\t\x12\x10\n\x08owner_id\x18\x03 \x01(\t\x12!\n\x15owner_type_deprecated\x18\x04 \x01(\tB\x02\x18\x01\x12=\n\nowner_type\x18\x05 \x01(\x0e\x32).temporal.api.cloud.identity.v1.OwnerType"g\n\x12GetApiKeysResponse\x12\x38\n\x08\x61pi_keys\x18\x01 \x03(\x0b\x32&.temporal.api.cloud.identity.v1.ApiKey\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\t""\n\x10GetApiKeyRequest\x12\x0e\n\x06key_id\x18\x01 \x01(\t"L\n\x11GetApiKeyResponse\x12\x37\n\x07\x61pi_key\x18\x01 \x01(\x0b\x32&.temporal.api.cloud.identity.v1.ApiKey"k\n\x13\x43reateApiKeyRequest\x12\x38\n\x04spec\x18\x01 \x01(\x0b\x32*.temporal.api.cloud.identity.v1.ApiKeySpec\x12\x1a\n\x12\x61sync_operation_id\x18\x02 \x01(\t"\x7f\n\x14\x43reateApiKeyResponse\x12\x0e\n\x06key_id\x18\x01 \x01(\t\x12\r\n\x05token\x18\x02 \x01(\t\x12H\n\x0f\x61sync_operation\x18\x03 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"\x95\x01\n\x13UpdateApiKeyRequest\x12\x0e\n\x06key_id\x18\x01 \x01(\t\x12\x38\n\x04spec\x18\x02 \x01(\x0b\x32*.temporal.api.cloud.identity.v1.ApiKeySpec\x12\x18\n\x10resource_version\x18\x03 \x01(\t\x12\x1a\n\x12\x61sync_operation_id\x18\x04 \x01(\t"`\n\x14UpdateApiKeyResponse\x12H\n\x0f\x61sync_operation\x18\x01 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"[\n\x13\x44\x65leteApiKeyRequest\x12\x0e\n\x06key_id\x18\x01 \x01(\t\x12\x18\n\x10resource_version\x18\x02 \x01(\t\x12\x1a\n\x12\x61sync_operation_id\x18\x03 \x01(\t"`\n\x14\x44\x65leteApiKeyResponse\x12H\n\x0f\x61sync_operation\x18\x01 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"\x87\x01\n\x18GetNexusEndpointsRequest\x12\x11\n\tpage_size\x18\x01 \x01(\x05\x12\x12\n\npage_token\x18\x02 \x01(\t\x12\x1b\n\x13target_namespace_id\x18\x03 \x01(\t\x12\x19\n\x11target_task_queue\x18\x04 \x01(\t\x12\x0c\n\x04name\x18\x05 \x01(\t"n\n\x19GetNexusEndpointsResponse\x12\x38\n\tendpoints\x18\x01 \x03(\x0b\x32%.temporal.api.cloud.nexus.v1.Endpoint\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\t".\n\x17GetNexusEndpointRequest\x12\x13\n\x0b\x65ndpoint_id\x18\x01 \x01(\t"S\n\x18GetNexusEndpointResponse\x12\x37\n\x08\x65ndpoint\x18\x01 \x01(\x0b\x32%.temporal.api.cloud.nexus.v1.Endpoint"q\n\x1a\x43reateNexusEndpointRequest\x12\x37\n\x04spec\x18\x01 \x01(\x0b\x32).temporal.api.cloud.nexus.v1.EndpointSpec\x12\x1a\n\x12\x61sync_operation_id\x18\x02 \x01(\t"|\n\x1b\x43reateNexusEndpointResponse\x12\x13\n\x0b\x65ndpoint_id\x18\x01 \x01(\t\x12H\n\x0f\x61sync_operation\x18\x02 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"\xa0\x01\n\x1aUpdateNexusEndpointRequest\x12\x13\n\x0b\x65ndpoint_id\x18\x01 \x01(\t\x12\x37\n\x04spec\x18\x02 \x01(\x0b\x32).temporal.api.cloud.nexus.v1.EndpointSpec\x12\x18\n\x10resource_version\x18\x03 \x01(\t\x12\x1a\n\x12\x61sync_operation_id\x18\x04 \x01(\t"g\n\x1bUpdateNexusEndpointResponse\x12H\n\x0f\x61sync_operation\x18\x01 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"g\n\x1a\x44\x65leteNexusEndpointRequest\x12\x13\n\x0b\x65ndpoint_id\x18\x01 \x01(\t\x12\x18\n\x10resource_version\x18\x02 \x01(\t\x12\x1a\n\x12\x61sync_operation_id\x18\x03 \x01(\t"g\n\x1b\x44\x65leteNexusEndpointResponse\x12H\n\x0f\x61sync_operation\x18\x01 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"\xf5\x02\n\x14GetUserGroupsRequest\x12\x11\n\tpage_size\x18\x01 \x01(\x05\x12\x12\n\npage_token\x18\x02 \x01(\t\x12\x11\n\tnamespace\x18\x03 \x01(\t\x12\x14\n\x0c\x64isplay_name\x18\x04 \x01(\t\x12`\n\x0cgoogle_group\x18\x05 \x01(\x0b\x32J.temporal.api.cloud.cloudservice.v1.GetUserGroupsRequest.GoogleGroupFilter\x12\\\n\nscim_group\x18\x06 \x01(\x0b\x32H.temporal.api.cloud.cloudservice.v1.GetUserGroupsRequest.SCIMGroupFilter\x1a*\n\x11GoogleGroupFilter\x12\x15\n\remail_address\x18\x01 \x01(\t\x1a!\n\x0fSCIMGroupFilter\x12\x0e\n\x06idp_id\x18\x01 \x01(\t"k\n\x15GetUserGroupsResponse\x12\x39\n\x06groups\x18\x01 \x03(\x0b\x32).temporal.api.cloud.identity.v1.UserGroup\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\t"\'\n\x13GetUserGroupRequest\x12\x10\n\x08group_id\x18\x01 \x01(\t"P\n\x14GetUserGroupResponse\x12\x38\n\x05group\x18\x01 \x01(\x0b\x32).temporal.api.cloud.identity.v1.UserGroup"q\n\x16\x43reateUserGroupRequest\x12;\n\x04spec\x18\x01 \x01(\x0b\x32-.temporal.api.cloud.identity.v1.UserGroupSpec\x12\x1a\n\x12\x61sync_operation_id\x18\x02 \x01(\t"u\n\x17\x43reateUserGroupResponse\x12\x10\n\x08group_id\x18\x01 \x01(\t\x12H\n\x0f\x61sync_operation\x18\x02 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"\x9d\x01\n\x16UpdateUserGroupRequest\x12\x10\n\x08group_id\x18\x01 \x01(\t\x12;\n\x04spec\x18\x02 \x01(\x0b\x32-.temporal.api.cloud.identity.v1.UserGroupSpec\x12\x18\n\x10resource_version\x18\x03 \x01(\t\x12\x1a\n\x12\x61sync_operation_id\x18\x04 \x01(\t"c\n\x17UpdateUserGroupResponse\x12H\n\x0f\x61sync_operation\x18\x01 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"`\n\x16\x44\x65leteUserGroupRequest\x12\x10\n\x08group_id\x18\x01 \x01(\t\x12\x18\n\x10resource_version\x18\x02 \x01(\t\x12\x1a\n\x12\x61sync_operation_id\x18\x03 \x01(\t"c\n\x17\x44\x65leteUserGroupResponse\x12H\n\x0f\x61sync_operation\x18\x01 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"\xc0\x01\n"SetUserGroupNamespaceAccessRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x10\n\x08group_id\x18\x02 \x01(\t\x12?\n\x06\x61\x63\x63\x65ss\x18\x03 \x01(\x0b\x32/.temporal.api.cloud.identity.v1.NamespaceAccess\x12\x18\n\x10resource_version\x18\x04 \x01(\t\x12\x1a\n\x12\x61sync_operation_id\x18\x05 \x01(\t"o\n#SetUserGroupNamespaceAccessResponse\x12H\n\x0f\x61sync_operation\x18\x01 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"\x8f\x01\n\x19\x41\x64\x64UserGroupMemberRequest\x12\x10\n\x08group_id\x18\x01 \x01(\t\x12\x44\n\tmember_id\x18\x02 \x01(\x0b\x32\x31.temporal.api.cloud.identity.v1.UserGroupMemberId\x12\x1a\n\x12\x61sync_operation_id\x18\x03 \x01(\t"f\n\x1a\x41\x64\x64UserGroupMemberResponse\x12H\n\x0f\x61sync_operation\x18\x01 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"\x92\x01\n\x1cRemoveUserGroupMemberRequest\x12\x10\n\x08group_id\x18\x01 \x01(\t\x12\x44\n\tmember_id\x18\x02 \x01(\x0b\x32\x31.temporal.api.cloud.identity.v1.UserGroupMemberId\x12\x1a\n\x12\x61sync_operation_id\x18\x03 \x01(\t"i\n\x1dRemoveUserGroupMemberResponse\x12H\n\x0f\x61sync_operation\x18\x01 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"U\n\x1aGetUserGroupMembersRequest\x12\x11\n\tpage_size\x18\x01 \x01(\x05\x12\x12\n\npage_token\x18\x02 \x01(\t\x12\x10\n\x08group_id\x18\x03 \x01(\t"x\n\x1bGetUserGroupMembersResponse\x12@\n\x07members\x18\x01 \x03(\x0b\x32/.temporal.api.cloud.identity.v1.UserGroupMember\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\t"{\n\x1b\x43reateServiceAccountRequest\x12@\n\x04spec\x18\x01 \x01(\x0b\x32\x32.temporal.api.cloud.identity.v1.ServiceAccountSpec\x12\x1a\n\x12\x61sync_operation_id\x18\x02 \x01(\t"\x84\x01\n\x1c\x43reateServiceAccountResponse\x12\x1a\n\x12service_account_id\x18\x01 \x01(\t\x12H\n\x0f\x61sync_operation\x18\x02 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"6\n\x18GetServiceAccountRequest\x12\x1a\n\x12service_account_id\x18\x01 \x01(\t"d\n\x19GetServiceAccountResponse\x12G\n\x0fservice_account\x18\x01 \x01(\x0b\x32..temporal.api.cloud.identity.v1.ServiceAccount"B\n\x19GetServiceAccountsRequest\x12\x11\n\tpage_size\x18\x01 \x01(\x05\x12\x12\n\npage_token\x18\x02 \x01(\t"~\n\x1aGetServiceAccountsResponse\x12G\n\x0fservice_account\x18\x01 \x03(\x0b\x32..temporal.api.cloud.identity.v1.ServiceAccount\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\t"\xb1\x01\n\x1bUpdateServiceAccountRequest\x12\x1a\n\x12service_account_id\x18\x01 \x01(\t\x12@\n\x04spec\x18\x02 \x01(\x0b\x32\x32.temporal.api.cloud.identity.v1.ServiceAccountSpec\x12\x18\n\x10resource_version\x18\x03 \x01(\t\x12\x1a\n\x12\x61sync_operation_id\x18\x04 \x01(\t"h\n\x1cUpdateServiceAccountResponse\x12H\n\x0f\x61sync_operation\x18\x01 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"\xcf\x01\n\'SetServiceAccountNamespaceAccessRequest\x12\x1a\n\x12service_account_id\x18\x01 \x01(\t\x12\x11\n\tnamespace\x18\x02 \x01(\t\x12?\n\x06\x61\x63\x63\x65ss\x18\x03 \x01(\x0b\x32/.temporal.api.cloud.identity.v1.NamespaceAccess\x12\x18\n\x10resource_version\x18\x04 \x01(\t\x12\x1a\n\x12\x61sync_operation_id\x18\x05 \x01(\t"t\n(SetServiceAccountNamespaceAccessResponse\x12H\n\x0f\x61sync_operation\x18\x01 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"o\n\x1b\x44\x65leteServiceAccountRequest\x12\x1a\n\x12service_account_id\x18\x01 \x01(\t\x12\x18\n\x10resource_version\x18\x02 \x01(\t\x12\x1a\n\x12\x61sync_operation_id\x18\x03 \x01(\t"h\n\x1c\x44\x65leteServiceAccountResponse\x12H\n\x0f\x61sync_operation\x18\x01 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"\xaa\x01\n\x0fGetUsageRequest\x12\x38\n\x14start_time_inclusive\x18\x01 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x36\n\x12\x65nd_time_exclusive\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x11\n\tpage_size\x18\x03 \x01(\x05\x12\x12\n\npage_token\x18\x04 \x01(\t"d\n\x10GetUsageResponse\x12\x37\n\tsummaries\x18\x01 \x03(\x0b\x32$.temporal.api.cloud.usage.v1.Summary\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\t"\x13\n\x11GetAccountRequest"M\n\x12GetAccountResponse\x12\x37\n\x07\x61\x63\x63ount\x18\x01 \x01(\x0b\x32&.temporal.api.cloud.account.v1.Account"\x86\x01\n\x14UpdateAccountRequest\x12\x38\n\x04spec\x18\x01 \x01(\x0b\x32*.temporal.api.cloud.account.v1.AccountSpec\x12\x18\n\x10resource_version\x18\x02 \x01(\t\x12\x1a\n\x12\x61sync_operation_id\x18\x03 \x01(\t"a\n\x15UpdateAccountResponse\x12H\n\x0f\x61sync_operation\x18\x01 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"\x90\x01\n CreateNamespaceExportSinkRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12=\n\x04spec\x18\x02 \x01(\x0b\x32/.temporal.api.cloud.namespace.v1.ExportSinkSpec\x12\x1a\n\x12\x61sync_operation_id\x18\x03 \x01(\t"m\n!CreateNamespaceExportSinkResponse\x12H\n\x0f\x61sync_operation\x18\x01 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"@\n\x1dGetNamespaceExportSinkRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x0c\n\x04name\x18\x02 \x01(\t"[\n\x1eGetNamespaceExportSinkResponse\x12\x39\n\x04sink\x18\x01 \x01(\x0b\x32+.temporal.api.cloud.namespace.v1.ExportSink"Z\n\x1eGetNamespaceExportSinksRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x11\n\tpage_size\x18\x02 \x01(\x05\x12\x12\n\npage_token\x18\x03 \x01(\t"v\n\x1fGetNamespaceExportSinksResponse\x12:\n\x05sinks\x18\x01 \x03(\x0b\x32+.temporal.api.cloud.namespace.v1.ExportSink\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\t"\xaa\x01\n UpdateNamespaceExportSinkRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12=\n\x04spec\x18\x02 \x01(\x0b\x32/.temporal.api.cloud.namespace.v1.ExportSinkSpec\x12\x18\n\x10resource_version\x18\x03 \x01(\t\x12\x1a\n\x12\x61sync_operation_id\x18\x04 \x01(\t"m\n!UpdateNamespaceExportSinkResponse\x12H\n\x0f\x61sync_operation\x18\x01 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"y\n DeleteNamespaceExportSinkRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x0c\n\x04name\x18\x02 \x01(\t\x12\x18\n\x10resource_version\x18\x03 \x01(\t\x12\x1a\n\x12\x61sync_operation_id\x18\x04 \x01(\t"m\n!DeleteNamespaceExportSinkResponse\x12H\n\x0f\x61sync_operation\x18\x01 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"v\n"ValidateNamespaceExportSinkRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12=\n\x04spec\x18\x02 \x01(\x0b\x32/.temporal.api.cloud.namespace.v1.ExportSinkSpec"%\n#ValidateNamespaceExportSinkResponse"\x82\x02\n\x1aUpdateNamespaceTagsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12h\n\x0etags_to_upsert\x18\x02 \x03(\x0b\x32P.temporal.api.cloud.cloudservice.v1.UpdateNamespaceTagsRequest.TagsToUpsertEntry\x12\x16\n\x0etags_to_remove\x18\x03 \x03(\t\x12\x1a\n\x12\x61sync_operation_id\x18\x04 \x01(\t\x1a\x33\n\x11TagsToUpsertEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01"g\n\x1bUpdateNamespaceTagsResponse\x12H\n\x0f\x61sync_operation\x18\x01 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"\x87\x01\n\x1d\x43reateConnectivityRuleRequest\x12J\n\x04spec\x18\x01 \x01(\x0b\x32<.temporal.api.cloud.connectivityrule.v1.ConnectivityRuleSpec\x12\x1a\n\x12\x61sync_operation_id\x18\x02 \x01(\t"\x88\x01\n\x1e\x43reateConnectivityRuleResponse\x12\x1c\n\x14\x63onnectivity_rule_id\x18\x01 \x01(\t\x12H\n\x0f\x61sync_operation\x18\x02 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation":\n\x1aGetConnectivityRuleRequest\x12\x1c\n\x14\x63onnectivity_rule_id\x18\x01 \x01(\t"r\n\x1bGetConnectivityRuleResponse\x12S\n\x11\x63onnectivity_rule\x18\x01 \x01(\x0b\x32\x38.temporal.api.cloud.connectivityrule.v1.ConnectivityRule"W\n\x1bGetConnectivityRulesRequest\x12\x11\n\tpage_size\x18\x01 \x01(\x05\x12\x12\n\npage_token\x18\x02 \x01(\t\x12\x11\n\tnamespace\x18\x03 \x01(\t"\x8d\x01\n\x1cGetConnectivityRulesResponse\x12T\n\x12\x63onnectivity_rules\x18\x01 \x03(\x0b\x32\x38.temporal.api.cloud.connectivityrule.v1.ConnectivityRule\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\t"s\n\x1d\x44\x65leteConnectivityRuleRequest\x12\x1c\n\x14\x63onnectivity_rule_id\x18\x01 \x01(\t\x12\x18\n\x10resource_version\x18\x02 \x01(\t\x12\x1a\n\x12\x61sync_operation_id\x18\x03 \x01(\t"j\n\x1e\x44\x65leteConnectivityRuleResponse\x12H\n\x0f\x61sync_operation\x18\x01 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"\xae\x01\n\x13GetAuditLogsRequest\x12\x11\n\tpage_size\x18\x01 \x01(\x05\x12\x12\n\npage_token\x18\x02 \x01(\t\x12\x38\n\x14start_time_inclusive\x18\x03 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x36\n\x12\x65nd_time_exclusive\x18\x04 \x01(\x0b\x32\x1a.google.protobuf.Timestamp"h\n\x14GetAuditLogsResponse\x12\x37\n\x04logs\x18\x01 \x03(\x0b\x32).temporal.api.cloud.auditlog.v1.LogRecord\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\t"c\n"ValidateAccountAuditLogSinkRequest\x12=\n\x04spec\x18\x01 \x01(\x0b\x32/.temporal.api.cloud.account.v1.AuditLogSinkSpec"%\n#ValidateAccountAuditLogSinkResponse"}\n CreateAccountAuditLogSinkRequest\x12=\n\x04spec\x18\x01 \x01(\x0b\x32/.temporal.api.cloud.account.v1.AuditLogSinkSpec\x12\x1a\n\x12\x61sync_operation_id\x18\x02 \x01(\t"m\n!CreateAccountAuditLogSinkResponse\x12H\n\x0f\x61sync_operation\x18\x01 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"-\n\x1dGetAccountAuditLogSinkRequest\x12\x0c\n\x04name\x18\x01 \x01(\t"[\n\x1eGetAccountAuditLogSinkResponse\x12\x39\n\x04sink\x18\x01 \x01(\x0b\x32+.temporal.api.cloud.account.v1.AuditLogSink"G\n\x1eGetAccountAuditLogSinksRequest\x12\x11\n\tpage_size\x18\x01 \x01(\x05\x12\x12\n\npage_token\x18\x02 \x01(\t"v\n\x1fGetAccountAuditLogSinksResponse\x12:\n\x05sinks\x18\x01 \x03(\x0b\x32+.temporal.api.cloud.account.v1.AuditLogSink\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\t"\x97\x01\n UpdateAccountAuditLogSinkRequest\x12=\n\x04spec\x18\x01 \x01(\x0b\x32/.temporal.api.cloud.account.v1.AuditLogSinkSpec\x12\x18\n\x10resource_version\x18\x02 \x01(\t\x12\x1a\n\x12\x61sync_operation_id\x18\x03 \x01(\t"m\n!UpdateAccountAuditLogSinkResponse\x12H\n\x0f\x61sync_operation\x18\x01 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"f\n DeleteAccountAuditLogSinkRequest\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x18\n\x10resource_version\x18\x02 \x01(\t\x12\x1a\n\x12\x61sync_operation_id\x18\x03 \x01(\t"m\n!DeleteAccountAuditLogSinkResponse\x12H\n\x0f\x61sync_operation\x18\x01 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"4\n\x1fGetNamespaceCapacityInfoRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t"q\n GetNamespaceCapacityInfoResponse\x12M\n\rcapacity_info\x18\x01 \x01(\x0b\x32\x36.temporal.api.cloud.namespace.v1.NamespaceCapacityInfo"x\n\x1a\x43reateBillingReportRequest\x12>\n\x04spec\x18\x01 \x01(\x0b\x32\x30.temporal.api.cloud.billing.v1.BillingReportSpec\x12\x1a\n\x12\x61sync_operation_id\x18\x02 \x01(\t"\x82\x01\n\x1b\x43reateBillingReportResponse\x12\x19\n\x11\x62illing_report_id\x18\x01 \x01(\t\x12H\n\x0f\x61sync_operation\x18\x02 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"4\n\x17GetBillingReportRequest\x12\x19\n\x11\x62illing_report_id\x18\x01 \x01(\t"`\n\x18GetBillingReportResponse\x12\x44\n\x0e\x62illing_report\x18\x01 \x01(\x0b\x32,.temporal.api.cloud.billing.v1.BillingReport">\n\x15GetCustomRolesRequest\x12\x11\n\tpage_size\x18\x01 \x01(\x05\x12\x12\n\npage_token\x18\x02 \x01(\t"s\n\x16GetCustomRolesResponse\x12@\n\x0c\x63ustom_roles\x18\x01 \x03(\x0b\x32*.temporal.api.cloud.identity.v1.CustomRole\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\t"\'\n\x14GetCustomRoleRequest\x12\x0f\n\x07role_id\x18\x01 \x01(\t"X\n\x15GetCustomRoleResponse\x12?\n\x0b\x63ustom_role\x18\x01 \x01(\x0b\x32*.temporal.api.cloud.identity.v1.CustomRole"s\n\x17\x43reateCustomRoleRequest\x12<\n\x04spec\x18\x01 \x01(\x0b\x32..temporal.api.cloud.identity.v1.CustomRoleSpec\x12\x1a\n\x12\x61sync_operation_id\x18\x02 \x01(\t"u\n\x18\x43reateCustomRoleResponse\x12\x0f\n\x07role_id\x18\x01 \x01(\t\x12H\n\x0f\x61sync_operation\x18\x02 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"\x9e\x01\n\x17UpdateCustomRoleRequest\x12\x0f\n\x07role_id\x18\x01 \x01(\t\x12<\n\x04spec\x18\x02 \x01(\x0b\x32..temporal.api.cloud.identity.v1.CustomRoleSpec\x12\x18\n\x10resource_version\x18\x03 \x01(\t\x12\x1a\n\x12\x61sync_operation_id\x18\x04 \x01(\t"d\n\x18UpdateCustomRoleResponse\x12H\n\x0f\x61sync_operation\x18\x01 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"`\n\x17\x44\x65leteCustomRoleRequest\x12\x0f\n\x07role_id\x18\x01 \x01(\t\x12\x18\n\x10resource_version\x18\x02 \x01(\t\x12\x1a\n\x12\x61sync_operation_id\x18\x03 \x01(\t"d\n\x18\x44\x65leteCustomRoleResponse\x12H\n\x0f\x61sync_operation\x18\x01 \x01(\x0b\x32/.temporal.api.cloud.operation.v1.AsyncOperation"^\n"GetUserNamespaceAssignmentsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x11\n\tpage_size\x18\x02 \x01(\x05\x12\x12\n\npage_token\x18\x03 \x01(\t"\x86\x01\n#GetUserNamespaceAssignmentsResponse\x12\x46\n\x05users\x18\x01 \x03(\x0b\x32\x37.temporal.api.cloud.identity.v1.UserNamespaceAssignment\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\t"h\n,GetServiceAccountNamespaceAssignmentsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x11\n\tpage_size\x18\x02 \x01(\x05\x12\x12\n\npage_token\x18\x03 \x01(\t"\xa5\x01\n-GetServiceAccountNamespaceAssignmentsResponse\x12[\n\x10service_accounts\x18\x01 \x03(\x0b\x32\x41.temporal.api.cloud.identity.v1.ServiceAccountNamespaceAssignment\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\t"c\n\'GetUserGroupNamespaceAssignmentsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x11\n\tpage_size\x18\x02 \x01(\x05\x12\x12\n\npage_token\x18\x03 \x01(\t"\x91\x01\n(GetUserGroupNamespaceAssignmentsResponse\x12L\n\x06groups\x18\x01 \x03(\x0b\x32<.temporal.api.cloud.identity.v1.UserGroupNamespaceAssignment\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\tB\xc8\x01\n%io.temporal.api.cloud.cloudservice.v1B\x14RequestResponseProtoP\x01Z5go.temporal.io/api/cloud/cloudservice/v1;cloudservice\xaa\x02$Temporalio.Api.Cloud.CloudService.V1\xea\x02(Temporalio::Api::Cloud::CloudService::V1b\x06proto3' ) @@ -364,6 +364,24 @@ _UPDATECUSTOMROLERESPONSE = DESCRIPTOR.message_types_by_name["UpdateCustomRoleResponse"] _DELETECUSTOMROLEREQUEST = DESCRIPTOR.message_types_by_name["DeleteCustomRoleRequest"] _DELETECUSTOMROLERESPONSE = DESCRIPTOR.message_types_by_name["DeleteCustomRoleResponse"] +_GETUSERNAMESPACEASSIGNMENTSREQUEST = DESCRIPTOR.message_types_by_name[ + "GetUserNamespaceAssignmentsRequest" +] +_GETUSERNAMESPACEASSIGNMENTSRESPONSE = DESCRIPTOR.message_types_by_name[ + "GetUserNamespaceAssignmentsResponse" +] +_GETSERVICEACCOUNTNAMESPACEASSIGNMENTSREQUEST = DESCRIPTOR.message_types_by_name[ + "GetServiceAccountNamespaceAssignmentsRequest" +] +_GETSERVICEACCOUNTNAMESPACEASSIGNMENTSRESPONSE = DESCRIPTOR.message_types_by_name[ + "GetServiceAccountNamespaceAssignmentsResponse" +] +_GETUSERGROUPNAMESPACEASSIGNMENTSREQUEST = DESCRIPTOR.message_types_by_name[ + "GetUserGroupNamespaceAssignmentsRequest" +] +_GETUSERGROUPNAMESPACEASSIGNMENTSRESPONSE = DESCRIPTOR.message_types_by_name[ + "GetUserGroupNamespaceAssignmentsResponse" +] GetCurrentIdentityRequest = _reflection.GeneratedProtocolMessageType( "GetCurrentIdentityRequest", (_message.Message,), @@ -2010,6 +2028,74 @@ ) _sym_db.RegisterMessage(DeleteCustomRoleResponse) +GetUserNamespaceAssignmentsRequest = _reflection.GeneratedProtocolMessageType( + "GetUserNamespaceAssignmentsRequest", + (_message.Message,), + { + "DESCRIPTOR": _GETUSERNAMESPACEASSIGNMENTSREQUEST, + "__module__": "temporalio.api.cloud.cloudservice.v1.request_response_pb2", + # @@protoc_insertion_point(class_scope:temporal.api.cloud.cloudservice.v1.GetUserNamespaceAssignmentsRequest) + }, +) +_sym_db.RegisterMessage(GetUserNamespaceAssignmentsRequest) + +GetUserNamespaceAssignmentsResponse = _reflection.GeneratedProtocolMessageType( + "GetUserNamespaceAssignmentsResponse", + (_message.Message,), + { + "DESCRIPTOR": _GETUSERNAMESPACEASSIGNMENTSRESPONSE, + "__module__": "temporalio.api.cloud.cloudservice.v1.request_response_pb2", + # @@protoc_insertion_point(class_scope:temporal.api.cloud.cloudservice.v1.GetUserNamespaceAssignmentsResponse) + }, +) +_sym_db.RegisterMessage(GetUserNamespaceAssignmentsResponse) + +GetServiceAccountNamespaceAssignmentsRequest = _reflection.GeneratedProtocolMessageType( + "GetServiceAccountNamespaceAssignmentsRequest", + (_message.Message,), + { + "DESCRIPTOR": _GETSERVICEACCOUNTNAMESPACEASSIGNMENTSREQUEST, + "__module__": "temporalio.api.cloud.cloudservice.v1.request_response_pb2", + # @@protoc_insertion_point(class_scope:temporal.api.cloud.cloudservice.v1.GetServiceAccountNamespaceAssignmentsRequest) + }, +) +_sym_db.RegisterMessage(GetServiceAccountNamespaceAssignmentsRequest) + +GetServiceAccountNamespaceAssignmentsResponse = ( + _reflection.GeneratedProtocolMessageType( + "GetServiceAccountNamespaceAssignmentsResponse", + (_message.Message,), + { + "DESCRIPTOR": _GETSERVICEACCOUNTNAMESPACEASSIGNMENTSRESPONSE, + "__module__": "temporalio.api.cloud.cloudservice.v1.request_response_pb2", + # @@protoc_insertion_point(class_scope:temporal.api.cloud.cloudservice.v1.GetServiceAccountNamespaceAssignmentsResponse) + }, + ) +) +_sym_db.RegisterMessage(GetServiceAccountNamespaceAssignmentsResponse) + +GetUserGroupNamespaceAssignmentsRequest = _reflection.GeneratedProtocolMessageType( + "GetUserGroupNamespaceAssignmentsRequest", + (_message.Message,), + { + "DESCRIPTOR": _GETUSERGROUPNAMESPACEASSIGNMENTSREQUEST, + "__module__": "temporalio.api.cloud.cloudservice.v1.request_response_pb2", + # @@protoc_insertion_point(class_scope:temporal.api.cloud.cloudservice.v1.GetUserGroupNamespaceAssignmentsRequest) + }, +) +_sym_db.RegisterMessage(GetUserGroupNamespaceAssignmentsRequest) + +GetUserGroupNamespaceAssignmentsResponse = _reflection.GeneratedProtocolMessageType( + "GetUserGroupNamespaceAssignmentsResponse", + (_message.Message,), + { + "DESCRIPTOR": _GETUSERGROUPNAMESPACEASSIGNMENTSRESPONSE, + "__module__": "temporalio.api.cloud.cloudservice.v1.request_response_pb2", + # @@protoc_insertion_point(class_scope:temporal.api.cloud.cloudservice.v1.GetUserGroupNamespaceAssignmentsResponse) + }, +) +_sym_db.RegisterMessage(GetUserGroupNamespaceAssignmentsResponse) + if _descriptor._USE_C_DESCRIPTORS == False: DESCRIPTOR._options = None DESCRIPTOR._serialized_options = b"\n%io.temporal.api.cloud.cloudservice.v1B\024RequestResponseProtoP\001Z5go.temporal.io/api/cloud/cloudservice/v1;cloudservice\252\002$Temporalio.Api.Cloud.CloudService.V1\352\002(Temporalio::Api::Cloud::CloudService::V1" @@ -2321,4 +2407,16 @@ _DELETECUSTOMROLEREQUEST._serialized_end = 16690 _DELETECUSTOMROLERESPONSE._serialized_start = 16692 _DELETECUSTOMROLERESPONSE._serialized_end = 16792 + _GETUSERNAMESPACEASSIGNMENTSREQUEST._serialized_start = 16794 + _GETUSERNAMESPACEASSIGNMENTSREQUEST._serialized_end = 16888 + _GETUSERNAMESPACEASSIGNMENTSRESPONSE._serialized_start = 16891 + _GETUSERNAMESPACEASSIGNMENTSRESPONSE._serialized_end = 17025 + _GETSERVICEACCOUNTNAMESPACEASSIGNMENTSREQUEST._serialized_start = 17027 + _GETSERVICEACCOUNTNAMESPACEASSIGNMENTSREQUEST._serialized_end = 17131 + _GETSERVICEACCOUNTNAMESPACEASSIGNMENTSRESPONSE._serialized_start = 17134 + _GETSERVICEACCOUNTNAMESPACEASSIGNMENTSRESPONSE._serialized_end = 17299 + _GETUSERGROUPNAMESPACEASSIGNMENTSREQUEST._serialized_start = 17301 + _GETUSERGROUPNAMESPACEASSIGNMENTSREQUEST._serialized_end = 17400 + _GETUSERGROUPNAMESPACEASSIGNMENTSRESPONSE._serialized_start = 17403 + _GETUSERGROUPNAMESPACEASSIGNMENTSRESPONSE._serialized_end = 17548 # @@protoc_insertion_point(module_scope) diff --git a/temporalio/api/cloud/cloudservice/v1/request_response_pb2.pyi b/temporalio/api/cloud/cloudservice/v1/request_response_pb2.pyi index 404554099..149020039 100644 --- a/temporalio/api/cloud/cloudservice/v1/request_response_pb2.pyi +++ b/temporalio/api/cloud/cloudservice/v1/request_response_pb2.pyi @@ -4593,3 +4593,215 @@ class DeleteCustomRoleResponse(google.protobuf.message.Message): ) -> None: ... global___DeleteCustomRoleResponse = DeleteCustomRoleResponse + +class GetUserNamespaceAssignmentsRequest(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + NAMESPACE_FIELD_NUMBER: builtins.int + PAGE_SIZE_FIELD_NUMBER: builtins.int + PAGE_TOKEN_FIELD_NUMBER: builtins.int + namespace: builtins.str + """The namespace to get users for.""" + page_size: builtins.int + """The requested size of the page to retrieve - optional. + Cannot exceed 1000. Defaults to 100. + """ + page_token: builtins.str + """The page token if this is continuing from another response - optional.""" + def __init__( + self, + *, + namespace: builtins.str = ..., + page_size: builtins.int = ..., + page_token: builtins.str = ..., + ) -> None: ... + def ClearField( + self, + field_name: typing_extensions.Literal[ + "namespace", + b"namespace", + "page_size", + b"page_size", + "page_token", + b"page_token", + ], + ) -> None: ... + +global___GetUserNamespaceAssignmentsRequest = GetUserNamespaceAssignmentsRequest + +class GetUserNamespaceAssignmentsResponse(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + USERS_FIELD_NUMBER: builtins.int + NEXT_PAGE_TOKEN_FIELD_NUMBER: builtins.int + @property + def users( + self, + ) -> google.protobuf.internal.containers.RepeatedCompositeFieldContainer[ + temporalio.api.cloud.identity.v1.message_pb2.UserNamespaceAssignment + ]: + """The list of users with access to the namespace.""" + next_page_token: builtins.str + """The next page's token.""" + def __init__( + self, + *, + users: collections.abc.Iterable[ + temporalio.api.cloud.identity.v1.message_pb2.UserNamespaceAssignment + ] + | None = ..., + next_page_token: builtins.str = ..., + ) -> None: ... + def ClearField( + self, + field_name: typing_extensions.Literal[ + "next_page_token", b"next_page_token", "users", b"users" + ], + ) -> None: ... + +global___GetUserNamespaceAssignmentsResponse = GetUserNamespaceAssignmentsResponse + +class GetServiceAccountNamespaceAssignmentsRequest(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + NAMESPACE_FIELD_NUMBER: builtins.int + PAGE_SIZE_FIELD_NUMBER: builtins.int + PAGE_TOKEN_FIELD_NUMBER: builtins.int + namespace: builtins.str + """The namespace to get service accounts for.""" + page_size: builtins.int + """The requested size of the page to retrieve - optional. + Cannot exceed 1000. Defaults to 100. + """ + page_token: builtins.str + """The page token if this is continuing from another response - optional.""" + def __init__( + self, + *, + namespace: builtins.str = ..., + page_size: builtins.int = ..., + page_token: builtins.str = ..., + ) -> None: ... + def ClearField( + self, + field_name: typing_extensions.Literal[ + "namespace", + b"namespace", + "page_size", + b"page_size", + "page_token", + b"page_token", + ], + ) -> None: ... + +global___GetServiceAccountNamespaceAssignmentsRequest = ( + GetServiceAccountNamespaceAssignmentsRequest +) + +class GetServiceAccountNamespaceAssignmentsResponse(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + SERVICE_ACCOUNTS_FIELD_NUMBER: builtins.int + NEXT_PAGE_TOKEN_FIELD_NUMBER: builtins.int + @property + def service_accounts( + self, + ) -> google.protobuf.internal.containers.RepeatedCompositeFieldContainer[ + temporalio.api.cloud.identity.v1.message_pb2.ServiceAccountNamespaceAssignment + ]: + """The list of service accounts with access to the namespace.""" + next_page_token: builtins.str + """The next page's token.""" + def __init__( + self, + *, + service_accounts: collections.abc.Iterable[ + temporalio.api.cloud.identity.v1.message_pb2.ServiceAccountNamespaceAssignment + ] + | None = ..., + next_page_token: builtins.str = ..., + ) -> None: ... + def ClearField( + self, + field_name: typing_extensions.Literal[ + "next_page_token", + b"next_page_token", + "service_accounts", + b"service_accounts", + ], + ) -> None: ... + +global___GetServiceAccountNamespaceAssignmentsResponse = ( + GetServiceAccountNamespaceAssignmentsResponse +) + +class GetUserGroupNamespaceAssignmentsRequest(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + NAMESPACE_FIELD_NUMBER: builtins.int + PAGE_SIZE_FIELD_NUMBER: builtins.int + PAGE_TOKEN_FIELD_NUMBER: builtins.int + namespace: builtins.str + """The namespace to get user groups for.""" + page_size: builtins.int + """The requested size of the page to retrieve - optional. + Cannot exceed 1000. Defaults to 100. + """ + page_token: builtins.str + """The page token if this is continuing from another response - optional.""" + def __init__( + self, + *, + namespace: builtins.str = ..., + page_size: builtins.int = ..., + page_token: builtins.str = ..., + ) -> None: ... + def ClearField( + self, + field_name: typing_extensions.Literal[ + "namespace", + b"namespace", + "page_size", + b"page_size", + "page_token", + b"page_token", + ], + ) -> None: ... + +global___GetUserGroupNamespaceAssignmentsRequest = ( + GetUserGroupNamespaceAssignmentsRequest +) + +class GetUserGroupNamespaceAssignmentsResponse(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + GROUPS_FIELD_NUMBER: builtins.int + NEXT_PAGE_TOKEN_FIELD_NUMBER: builtins.int + @property + def groups( + self, + ) -> google.protobuf.internal.containers.RepeatedCompositeFieldContainer[ + temporalio.api.cloud.identity.v1.message_pb2.UserGroupNamespaceAssignment + ]: + """The list of user groups with access to the namespace.""" + next_page_token: builtins.str + """The next page's token.""" + def __init__( + self, + *, + groups: collections.abc.Iterable[ + temporalio.api.cloud.identity.v1.message_pb2.UserGroupNamespaceAssignment + ] + | None = ..., + next_page_token: builtins.str = ..., + ) -> None: ... + def ClearField( + self, + field_name: typing_extensions.Literal[ + "groups", b"groups", "next_page_token", b"next_page_token" + ], + ) -> None: ... + +global___GetUserGroupNamespaceAssignmentsResponse = ( + GetUserGroupNamespaceAssignmentsResponse +) diff --git a/temporalio/api/cloud/cloudservice/v1/service_pb2.py b/temporalio/api/cloud/cloudservice/v1/service_pb2.py index 4223fb03d..aca6662c2 100644 --- a/temporalio/api/cloud/cloudservice/v1/service_pb2.py +++ b/temporalio/api/cloud/cloudservice/v1/service_pb2.py @@ -24,7 +24,7 @@ ) DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile( - b'\n0temporal/api/cloud/cloudservice/v1/service.proto\x12"temporal.api.cloud.cloudservice.v1\x1a\x39temporal/api/cloud/cloudservice/v1/request_response.proto\x1a\x1cgoogle/api/annotations.proto\x1a.protoc-gen-openapiv2/options/annotations.proto2\xc2\xcb\x01\n\x0c\x43loudService\x12\xb0\x02\n\x12GetCurrentIdentity\x12=.temporal.api.cloud.cloudservice.v1.GetCurrentIdentityRequest\x1a>.temporal.api.cloud.cloudservice.v1.GetCurrentIdentityResponse"\x9a\x01\x82\xd3\xe4\x93\x02\x19\x12\x17/cloud/current-identity\x92\x41x\n\x07\x41\x63\x63ount\x12\x14Get current identity\x1aWReturns information about the currently authenticated user or service account principal\x12\xa5\x02\n\x08GetUsers\x12\x33.temporal.api.cloud.cloudservice.v1.GetUsersRequest\x1a\x34.temporal.api.cloud.cloudservice.v1.GetUsersResponse"\xad\x01\x82\xd3\xe4\x93\x02\x0e\x12\x0c/cloud/users\x92\x41\x95\x01\n\x05Users\x12\x0eList all users\x1a*Returns a list of all users in the account"E\n\x1dUser management documentation\x12$https://docs.temporal.io/cloud/users*\tlistUsers\x12\x9c\x02\n\x07GetUser\x12\x32.temporal.api.cloud.cloudservice.v1.GetUserRequest\x1a\x33.temporal.api.cloud.cloudservice.v1.GetUserResponse"\xa7\x01\x82\xd3\xe4\x93\x02\x18\x12\x16/cloud/users/{user_id}\x92\x41\x85\x01\n\x05Users\x12\x0eGet user by ID\x1a%Takes a user ID, returns user details"E\n\x1dUser management documentation\x12$https://docs.temporal.io/cloud/users\x12\xd0\x01\n\nCreateUser\x12\x35.temporal.api.cloud.cloudservice.v1.CreateUserRequest\x1a\x36.temporal.api.cloud.cloudservice.v1.CreateUserResponse"S\x82\xd3\xe4\x93\x02\x11"\x0c/cloud/users:\x01*\x92\x41\x39\n\x05Users\x12\rCreate a user\x1a!Creates a new user in the account\x12\xdb\x01\n\nUpdateUser\x12\x35.temporal.api.cloud.cloudservice.v1.UpdateUserRequest\x1a\x36.temporal.api.cloud.cloudservice.v1.UpdateUserResponse"^\x82\xd3\xe4\x93\x02\x1b"\x16/cloud/users/{user_id}:\x01*\x92\x41:\n\x05Users\x12\rUpdate a user\x1a"Updates an existing user\'s details\x12\xd5\x01\n\nDeleteUser\x12\x35.temporal.api.cloud.cloudservice.v1.DeleteUserRequest\x1a\x36.temporal.api.cloud.cloudservice.v1.DeleteUserResponse"X\x82\xd3\xe4\x93\x02\x18*\x16/cloud/users/{user_id}\x92\x41\x37\n\x05Users\x12\rDelete a user\x1a\x1fRemoves a user from the account\x12\xaa\x03\n\x16SetUserNamespaceAccess\x12\x41.temporal.api.cloud.cloudservice.v1.SetUserNamespaceAccessRequest\x1a\x42.temporal.api.cloud.cloudservice.v1.SetUserNamespaceAccessResponse"\x88\x02\x82\xd3\xe4\x93\x02\x39"4/cloud/namespaces/{namespace}/users/{user_id}/access:\x01*\x92\x41\xc5\x01\n\x05Users\x12\x19Set user namespace access\x1a\x38\x43onfigures a user\'s permissions for a specific namespace"g\n#Namespace permissions documentation\x12@https://docs.temporal.io/cloud/users-namespace-level-permissions\x12\xb1\x02\n\x11GetAsyncOperation\x12<.temporal.api.cloud.cloudservice.v1.GetAsyncOperationRequest\x1a=.temporal.api.cloud.cloudservice.v1.GetAsyncOperationResponse"\x9e\x01\x82\xd3\xe4\x93\x02(\x12&/cloud/operations/{async_operation_id}\x92\x41m\n\nOperations\x12\x1aGet async operation status\x1a\x43Returns the current status and details of an asynchronous operation\x12\xc6\x02\n\x0f\x43reateNamespace\x12:.temporal.api.cloud.cloudservice.v1.CreateNamespaceRequest\x1a;.temporal.api.cloud.cloudservice.v1.CreateNamespaceResponse"\xb9\x01\x82\xd3\xe4\x93\x02\x16"\x11/cloud/namespaces:\x01*\x92\x41\x99\x01\n\nNamespaces\x12\x12\x43reate a namespace\x1a&Creates a new namespace in the account"O\n"Namespace management documentation\x12)https://docs.temporal.io/cloud/namespaces\x12\xc7\x02\n\rGetNamespaces\x12\x38.temporal.api.cloud.cloudservice.v1.GetNamespacesRequest\x1a\x39.temporal.api.cloud.cloudservice.v1.GetNamespacesResponse"\xc0\x01\x82\xd3\xe4\x93\x02\x13\x12\x11/cloud/namespaces\x92\x41\xa3\x01\n\nNamespaces\x12\x13List all namespaces\x1a/Returns a list of all namespaces in the account"O\n"Namespace management documentation\x12)https://docs.temporal.io/cloud/namespaces\x12\xda\x02\n\x0cGetNamespace\x12\x37.temporal.api.cloud.cloudservice.v1.GetNamespaceRequest\x1a\x38.temporal.api.cloud.cloudservice.v1.GetNamespaceResponse"\xd6\x01\x82\xd3\xe4\x93\x02\x1f\x12\x1d/cloud/namespaces/{namespace}\x92\x41\xad\x01\n\nNamespaces\x12\x15Get namespace details\x1a\x37Returns detailed information about a specific namespace"O\n"Namespace management documentation\x12)https://docs.temporal.io/cloud/namespaces\x12\xdb\x02\n\x0fUpdateNamespace\x12:.temporal.api.cloud.cloudservice.v1.UpdateNamespaceRequest\x1a;.temporal.api.cloud.cloudservice.v1.UpdateNamespaceResponse"\xce\x01\x82\xd3\xe4\x93\x02""\x1d/cloud/namespaces/{namespace}:\x01*\x92\x41\xa2\x01\n\nNamespaces\x12\x12Update a namespace\x1a/Updates configuration for an existing namespace"O\n"Namespace management documentation\x12)https://docs.temporal.io/cloud/namespaces\x12\xc7\x03\n\x1bRenameCustomSearchAttribute\x12\x46.temporal.api.cloud.cloudservice.v1.RenameCustomSearchAttributeRequest\x1aG.temporal.api.cloud.cloudservice.v1.RenameCustomSearchAttributeResponse"\x96\x02\x82\xd3\xe4\x93\x02\x41".temporal.api.cloud.cloudservice.v1.AddNamespaceRegionResponse"\xf0\x01\x88\x02\x01\x82\xd3\xe4\x93\x02-"(/cloud/namespaces/{namespace}/add-region:\x01*\x92\x41\xb6\x01\n\x11High Availability\x12\x15\x41\x64\x64 namespace replica\x1a+Adds a new replica to an existing namespace"]\n)High availability namespace documentation\x12\x30https://docs.temporal.io/cloud/high-availability\x12\x9e\x03\n\x15\x44\x65leteNamespaceRegion\x12@.temporal.api.cloud.cloudservice.v1.DeleteNamespaceRegionRequest\x1a\x41.temporal.api.cloud.cloudservice.v1.DeleteNamespaceRegionResponse"\xff\x01\x88\x02\x01\x82\xd3\xe4\x93\x02\x30*./cloud/namespaces/{namespace}/regions/{region}\x92\x41\xc2\x01\n\x11High Availability\x12\x18Remove namespace replica\x1a\x34Removes a replica from a high availability namespace"]\n)High availability namespace documentation\x12\x30https://docs.temporal.io/cloud/high-availability\x12\xa3\x02\n\nGetRegions\x12\x35.temporal.api.cloud.cloudservice.v1.GetRegionsRequest\x1a\x36.temporal.api.cloud.cloudservice.v1.GetRegionsResponse"\xa5\x01\x82\xd3\xe4\x93\x02\x10\x12\x0e/cloud/regions\x92\x41\x8b\x01\n\x07Regions\x12\x10List all regions\x1a-Returns a list of all available cloud regions"?\n\x15Regions documentation\x12&https://docs.temporal.io/cloud/regions\x12\xb2\x02\n\tGetRegion\x12\x34.temporal.api.cloud.cloudservice.v1.GetRegionRequest\x1a\x35.temporal.api.cloud.cloudservice.v1.GetRegionResponse"\xb7\x01\x82\xd3\xe4\x93\x02\x19\x12\x17/cloud/regions/{region}\x92\x41\x94\x01\n\x07Regions\x12\x12Get region details\x1a\x34Returns detailed information about a specific region"?\n\x15Regions documentation\x12&https://docs.temporal.io/cloud/regions\x12\xa8\x02\n\nGetApiKeys\x12\x35.temporal.api.cloud.cloudservice.v1.GetApiKeysRequest\x1a\x36.temporal.api.cloud.cloudservice.v1.GetApiKeysResponse"\xaa\x01\x82\xd3\xe4\x93\x02\x11\x12\x0f/cloud/api-keys\x92\x41\x8f\x01\n\x08\x41PI Keys\x12\x11List all API keys\x1a-Returns a list of all API keys in the account"A\n\x16\x41PI Keys documentation\x12\'https://docs.temporal.io/cloud/api-keys\x12\xb8\x02\n\tGetApiKey\x12\x34.temporal.api.cloud.cloudservice.v1.GetApiKeyRequest\x1a\x35.temporal.api.cloud.cloudservice.v1.GetApiKeyResponse"\xbd\x01\x82\xd3\xe4\x93\x02\x1a\x12\x18/cloud/api-keys/{key_id}\x92\x41\x99\x01\n\x08\x41PI Keys\x12\x13Get API key details\x1a\x35Returns detailed information about a specific API key"A\n\x16\x41PI Keys documentation\x12\'https://docs.temporal.io/cloud/api-keys\x12\xb1\x02\n\x0c\x43reateApiKey\x12\x37.temporal.api.cloud.cloudservice.v1.CreateApiKeyRequest\x1a\x38.temporal.api.cloud.cloudservice.v1.CreateApiKeyResponse"\xad\x01\x82\xd3\xe4\x93\x02\x14"\x0f/cloud/api-keys:\x01*\x92\x41\x8f\x01\n\x08\x41PI Keys\x12\x11\x43reate an API key\x1a-Creates a new API key for programmatic access"A\n\x16\x41PI Keys documentation\x12\'https://docs.temporal.io/cloud/api-keys\x12\xb5\x02\n\x0cUpdateApiKey\x12\x37.temporal.api.cloud.cloudservice.v1.UpdateApiKeyRequest\x1a\x38.temporal.api.cloud.cloudservice.v1.UpdateApiKeyResponse"\xb1\x01\x82\xd3\xe4\x93\x02\x1d"\x18/cloud/api-keys/{key_id}:\x01*\x92\x41\x8a\x01\n\x08\x41PI Keys\x12\x11Update an API key\x1a(Updates an existing API key\'s properties"A\n\x16\x41PI Keys documentation\x12\'https://docs.temporal.io/cloud/api-keys\x12\xa8\x02\n\x0c\x44\x65leteApiKey\x12\x37.temporal.api.cloud.cloudservice.v1.DeleteApiKeyRequest\x1a\x38.temporal.api.cloud.cloudservice.v1.DeleteApiKeyResponse"\xa4\x01\x82\xd3\xe4\x93\x02\x1a*\x18/cloud/api-keys/{key_id}\x92\x41\x80\x01\n\x08\x41PI Keys\x12\x11\x44\x65lete an API key\x1a\x1eRevokes and deletes an API key"A\n\x16\x41PI Keys documentation\x12\'https://docs.temporal.io/cloud/api-keys\x12\xc3\x02\n\x11GetNexusEndpoints\x12<.temporal.api.cloud.cloudservice.v1.GetNexusEndpointsRequest\x1a=.temporal.api.cloud.cloudservice.v1.GetNexusEndpointsResponse"\xb0\x01\x82\xd3\xe4\x93\x02\x18\x12\x16/cloud/nexus/endpoints\x92\x41\x8e\x01\n\x05Nexus\x12\x18List all Nexus endpoints\x1a\x34Returns a list of all Nexus endpoints in the account"5\n\x13Nexus documentation\x12\x1ehttps://docs.temporal.io/nexus\x12\xd8\x02\n\x10GetNexusEndpoint\x12;.temporal.api.cloud.cloudservice.v1.GetNexusEndpointRequest\x1a<.temporal.api.cloud.cloudservice.v1.GetNexusEndpointResponse"\xc8\x01\x82\xd3\xe4\x93\x02&\x12$/cloud/nexus/endpoints/{endpoint_id}\x92\x41\x98\x01\n\x05Nexus\x12\x1aGet Nexus endpoint details\x1a.temporal.api.cloud.cloudservice.v1.CreateNexusEndpointRequest\x1a?.temporal.api.cloud.cloudservice.v1.CreateNexusEndpointResponse"\xbc\x01\x82\xd3\xe4\x93\x02\x1b"\x16/cloud/nexus/endpoints:\x01*\x92\x41\x97\x01\n\x05Nexus\x12\x17\x43reate a Nexus endpoint\x1a>Creates a new Nexus endpoint for cross-namespace communication"5\n\x13Nexus documentation\x12\x1ehttps://docs.temporal.io/nexus\x12\xd7\x02\n\x13UpdateNexusEndpoint\x12>.temporal.api.cloud.cloudservice.v1.UpdateNexusEndpointRequest\x1a?.temporal.api.cloud.cloudservice.v1.UpdateNexusEndpointResponse"\xbe\x01\x82\xd3\xe4\x93\x02)"$/cloud/nexus/endpoints/{endpoint_id}:\x01*\x92\x41\x8b\x01\n\x05Nexus\x12\x17Update a Nexus endpoint\x1a\x32Updates an existing Nexus endpoint\'s configuration"5\n\x13Nexus documentation\x12\x1ehttps://docs.temporal.io/nexus\x12\xcb\x02\n\x13\x44\x65leteNexusEndpoint\x12>.temporal.api.cloud.cloudservice.v1.DeleteNexusEndpointRequest\x1a?.temporal.api.cloud.cloudservice.v1.DeleteNexusEndpointResponse"\xb2\x01\x82\xd3\xe4\x93\x02&*$/cloud/nexus/endpoints/{endpoint_id}\x92\x41\x82\x01\n\x05Nexus\x12\x17\x44\x65lete a Nexus endpoint\x1a)Removes a Nexus endpoint from the account"5\n\x13Nexus documentation\x12\x1ehttps://docs.temporal.io/nexus\x12\xcc\x02\n\rGetUserGroups\x12\x38.temporal.api.cloud.cloudservice.v1.GetUserGroupsRequest\x1a\x39.temporal.api.cloud.cloudservice.v1.GetUserGroupsResponse"\xc5\x01\x82\xd3\xe4\x93\x02\x14\x12\x12/cloud/user-groups\x92\x41\xa7\x01\n\x06Groups\x12\x14List all user groups\x1a\x30Returns a list of all user groups in the account"U\n\x19User groups documentation\x12\x38https://docs.temporal.io/cloud/users-account-level-roles\x12\xd0\x02\n\x0cGetUserGroup\x12\x37.temporal.api.cloud.cloudservice.v1.GetUserGroupRequest\x1a\x38.temporal.api.cloud.cloudservice.v1.GetUserGroupResponse"\xcc\x01\x82\xd3\xe4\x93\x02\x1f\x12\x1d/cloud/user-groups/{group_id}\x92\x41\xa3\x01\n\x06Groups\x12\x16Get user group details\x1a\x38Returns detailed information about a specific user group"G\n\x19User groups documentation\x12*https://docs.temporal.io/cloud/user-groups\x12\xc7\x02\n\x0f\x43reateUserGroup\x12:.temporal.api.cloud.cloudservice.v1.CreateUserGroupRequest\x1a;.temporal.api.cloud.cloudservice.v1.CreateUserGroupResponse"\xba\x01\x82\xd3\xe4\x93\x02\x17"\x12/cloud/user-groups:\x01*\x92\x41\x99\x01\n\x06Groups\x12\x13\x43reate a user group\x1a\x31\x43reates a new user group for managing permissions"G\n\x19User groups documentation\x12*https://docs.temporal.io/cloud/user-groups\x12\xcc\x02\n\x0fUpdateUserGroup\x12:.temporal.api.cloud.cloudservice.v1.UpdateUserGroupRequest\x1a;.temporal.api.cloud.cloudservice.v1.UpdateUserGroupResponse"\xbf\x01\x82\xd3\xe4\x93\x02""\x1d/cloud/user-groups/{group_id}:\x01*\x92\x41\x93\x01\n\x06Groups\x12\x13Update a user group\x1a+Updates an existing user group\'s properties"G\n\x19User groups documentation\x12*https://docs.temporal.io/cloud/user-groups\x12\xc3\x02\n\x0f\x44\x65leteUserGroup\x12:.temporal.api.cloud.cloudservice.v1.DeleteUserGroupRequest\x1a;.temporal.api.cloud.cloudservice.v1.DeleteUserGroupResponse"\xb6\x01\x82\xd3\xe4\x93\x02\x1f*\x1d/cloud/user-groups/{group_id}\x92\x41\x8d\x01\n\x06Groups\x12\x13\x44\x65lete a user group\x1a%Removes a user group from the account"G\n\x19User groups documentation\x12*https://docs.temporal.io/cloud/user-groups\x12\xad\x03\n\x1bSetUserGroupNamespaceAccess\x12\x46.temporal.api.cloud.cloudservice.v1.SetUserGroupNamespaceAccessRequest\x1aG.temporal.api.cloud.cloudservice.v1.SetUserGroupNamespaceAccessResponse"\xfc\x01\x82\xd3\xe4\x93\x02@";/cloud/namespaces/{namespace}/user-groups/{group_id}/access:\x01*\x92\x41\xb2\x01\n\x06Groups\x12\x1fSet user group namespace access\x1a>Configures a user group\'s permissions for a specific namespace"G\n\x19User groups documentation\x12*https://docs.temporal.io/cloud/user-groups\x12\xdf\x02\n\x12\x41\x64\x64UserGroupMember\x12=.temporal.api.cloud.cloudservice.v1.AddUserGroupMemberRequest\x1a>.temporal.api.cloud.cloudservice.v1.AddUserGroupMemberResponse"\xc9\x01\x82\xd3\xe4\x93\x02*"%/cloud/user-groups/{group_id}/members:\x01*\x92\x41\x95\x01\n\x06Groups\x12\x11\x41\x64\x64 user to group\x1a/Adds a user to a user group (Cloud groups only)"G\n\x19User groups documentation\x12*https://docs.temporal.io/cloud/user-groups\x12\xf8\x02\n\x15RemoveUserGroupMember\x12@.temporal.api.cloud.cloudservice.v1.RemoveUserGroupMemberRequest\x1a\x41.temporal.api.cloud.cloudservice.v1.RemoveUserGroupMemberResponse"\xd9\x01\x82\xd3\xe4\x93\x02\x30"+/cloud/user-groups/{group_id}/remove-member:\x01*\x92\x41\x9f\x01\n\x06Groups\x12\x16Remove user from group\x1a\x34Removes a user from a user group (Cloud groups only)"G\n\x19User groups documentation\x12*https://docs.temporal.io/cloud/user-groups\x12\xdf\x02\n\x13GetUserGroupMembers\x12>.temporal.api.cloud.cloudservice.v1.GetUserGroupMembersRequest\x1a?.temporal.api.cloud.cloudservice.v1.GetUserGroupMembersResponse"\xc6\x01\x82\xd3\xe4\x93\x02\'\x12%/cloud/user-groups/{group_id}/members\x92\x41\x95\x01\n\x06Groups\x12\x15List users in a group\x1a+Returns a list of all users in a user group"G\n\x19User groups documentation\x12*https://docs.temporal.io/cloud/user-groups\x12\xf5\x02\n\x14\x43reateServiceAccount\x12?.temporal.api.cloud.cloudservice.v1.CreateServiceAccountRequest\x1a@.temporal.api.cloud.cloudservice.v1.CreateServiceAccountResponse"\xd9\x01\x82\xd3\xe4\x93\x02\x1c"\x17/cloud/service-accounts:\x01*\x92\x41\xb3\x01\n\x10Service Accounts\x12\x18\x43reate a service account\x1a\x32\x43reates a new service account for automated access"Q\n\x1eService Accounts documentation\x12/https://docs.temporal.io/cloud/service-accounts\x12\x8c\x03\n\x11GetServiceAccount\x12<.temporal.api.cloud.cloudservice.v1.GetServiceAccountRequest\x1a=.temporal.api.cloud.cloudservice.v1.GetServiceAccountResponse"\xf9\x01\x82\xd3\xe4\x93\x02.\x12,/cloud/service-accounts/{service_account_id}\x92\x41\xc1\x01\n\x10Service Accounts\x12\x1bGet service account details\x1a=Returns detailed information about a specific service account"Q\n\x1eService Accounts documentation\x12/https://docs.temporal.io/cloud/service-accounts\x12\xf0\x02\n\x12GetServiceAccounts\x12=.temporal.api.cloud.cloudservice.v1.GetServiceAccountsRequest\x1a>.temporal.api.cloud.cloudservice.v1.GetServiceAccountsResponse"\xda\x01\x82\xd3\xe4\x93\x02\x19\x12\x17/cloud/service-accounts\x92\x41\xb7\x01\n\x10Service Accounts\x12\x19List all service accounts\x1a\x35Returns a list of all service accounts in the account"Q\n\x1eService Accounts documentation\x12/https://docs.temporal.io/cloud/service-accounts\x12\x88\x03\n\x14UpdateServiceAccount\x12?.temporal.api.cloud.cloudservice.v1.UpdateServiceAccountRequest\x1a@.temporal.api.cloud.cloudservice.v1.UpdateServiceAccountResponse"\xec\x01\x82\xd3\xe4\x93\x02\x31",/cloud/service-accounts/{service_account_id}:\x01*\x92\x41\xb1\x01\n\x10Service Accounts\x12\x18Update a service account\x1a\x30Updates an existing service account\'s properties"Q\n\x1eService Accounts documentation\x12/https://docs.temporal.io/cloud/service-accounts\x12\xe9\x03\n SetServiceAccountNamespaceAccess\x12K.temporal.api.cloud.cloudservice.v1.SetServiceAccountNamespaceAccessRequest\x1aL.temporal.api.cloud.cloudservice.v1.SetServiceAccountNamespaceAccessResponse"\xa9\x02\x82\xd3\xe4\x93\x02O"J/cloud/namespaces/{namespace}/service-accounts/{service_account_id}/access:\x01*\x92\x41\xd0\x01\n\x10Service Accounts\x12$Set service account namespace access\x1a\x43\x43onfigures a service account\'s permissions for a specific namespace"Q\n\x1eService Accounts documentation\x12/https://docs.temporal.io/cloud/service-accounts\x12\xff\x02\n\x14\x44\x65leteServiceAccount\x12?.temporal.api.cloud.cloudservice.v1.DeleteServiceAccountRequest\x1a@.temporal.api.cloud.cloudservice.v1.DeleteServiceAccountResponse"\xe3\x01\x82\xd3\xe4\x93\x02.*,/cloud/service-accounts/{service_account_id}\x92\x41\xab\x01\n\x10Service Accounts\x12\x18\x44\x65lete a service account\x1a*Removes a service account from the account"Q\n\x1eService Accounts documentation\x12/https://docs.temporal.io/cloud/service-accounts\x12\xcb\x01\n\x08GetUsage\x12\x33.temporal.api.cloud.cloudservice.v1.GetUsageRequest\x1a\x34.temporal.api.cloud.cloudservice.v1.GetUsageResponse"T\x82\xd3\xe4\x93\x02\x0e\x12\x0c/cloud/usage\x92\x41=\n\x07\x41\x63\x63ount\x12\x0eGet usage data\x1a Get usage data across namespacesX\x01\x12\xb0\x02\n\nGetAccount\x12\x35.temporal.api.cloud.cloudservice.v1.GetAccountRequest\x1a\x36.temporal.api.cloud.cloudservice.v1.GetAccountResponse"\xb2\x01\x82\xd3\xe4\x93\x02\x10\x12\x0e/cloud/account\x92\x41\x98\x01\n\x07\x41\x63\x63ount\x12\x13Get account details\x1a.Returns detailed information about the account"H\n\x15\x42illing documentation\x12/https://docs.temporal.io/cloud/billing-and-cost\x12\xbb\x02\n\rUpdateAccount\x12\x38.temporal.api.cloud.cloudservice.v1.UpdateAccountRequest\x1a\x39.temporal.api.cloud.cloudservice.v1.UpdateAccountResponse"\xb4\x01\x82\xd3\xe4\x93\x02\x13"\x0e/cloud/account:\x01*\x92\x41\x97\x01\n\x07\x41\x63\x63ount\x12\x16Update account details\x1a*Updates account configuration and settings"H\n\x15\x42illing documentation\x12/https://docs.temporal.io/cloud/billing-and-cost\x12\xf3\x02\n\x19\x43reateNamespaceExportSink\x12\x44.temporal.api.cloud.cloudservice.v1.CreateNamespaceExportSinkRequest\x1a\x45.temporal.api.cloud.cloudservice.v1.CreateNamespaceExportSinkResponse"\xc8\x01\x82\xd3\xe4\x93\x02/"*/cloud/namespaces/{namespace}/export-sinks:\x01*\x92\x41\x8f\x01\n\x06\x45xport\x12\x1a\x43reate history export sink\x1a*Creates a new workflow history export sink"=\n\x14\x45xport documentation\x12%https://docs.temporal.io/cloud/export\x12\x8c\x03\n\x16GetNamespaceExportSink\x12\x41.temporal.api.cloud.cloudservice.v1.GetNamespaceExportSinkRequest\x1a\x42.temporal.api.cloud.cloudservice.v1.GetNamespaceExportSinkResponse"\xea\x01\x82\xd3\xe4\x93\x02\x33\x12\x31/cloud/namespaces/{namespace}/export-sinks/{name}\x92\x41\xad\x01\n\x06\x45xport\x12\x18Get history sink details\x1aJReturns detailed information about a specific workflow history export sink"=\n\x14\x45xport documentation\x12%https://docs.temporal.io/cloud/export\x12\x82\x03\n\x17GetNamespaceExportSinks\x12\x42.temporal.api.cloud.cloudservice.v1.GetNamespaceExportSinksRequest\x1a\x43.temporal.api.cloud.cloudservice.v1.GetNamespaceExportSinksResponse"\xdd\x01\x82\xd3\xe4\x93\x02,\x12*/cloud/namespaces/{namespace}/export-sinks\x92\x41\xa7\x01\n\x06\x45xport\x12\x19List history export sinks\x1a\x43Returns a list of all workflow history export sinks for a namespace"=\n\x14\x45xport documentation\x12%https://docs.temporal.io/cloud/export\x12\x95\x03\n\x19UpdateNamespaceExportSink\x12\x44.temporal.api.cloud.cloudservice.v1.UpdateNamespaceExportSinkRequest\x1a\x45.temporal.api.cloud.cloudservice.v1.UpdateNamespaceExportSinkResponse"\xea\x01\x82\xd3\xe4\x93\x02;"6/cloud/namespaces/{namespace}/export-sinks/{spec.name}:\x01*\x92\x41\xa5\x01\n\x06\x45xport\x12\x1aUpdate history export sink\x1a@Updates an existing workflow history export sink\'s configuration"=\n\x14\x45xport documentation\x12%https://docs.temporal.io/cloud/export\x12\x84\x03\n\x19\x44\x65leteNamespaceExportSink\x12\x44.temporal.api.cloud.cloudservice.v1.DeleteNamespaceExportSinkRequest\x1a\x45.temporal.api.cloud.cloudservice.v1.DeleteNamespaceExportSinkResponse"\xd9\x01\x82\xd3\xe4\x93\x02\x33*1/cloud/namespaces/{namespace}/export-sinks/{name}\x92\x41\x9c\x01\n\x06\x45xport\x12\x1a\x44\x65lete history export sink\x1a\x37Removes a workflow history export sink from a namespace"=\n\x14\x45xport documentation\x12%https://docs.temporal.io/cloud/export\x12\xc9\x03\n\x1bValidateNamespaceExportSink\x12\x46.temporal.api.cloud.cloudservice.v1.ValidateNamespaceExportSinkRequest\x1aG.temporal.api.cloud.cloudservice.v1.ValidateNamespaceExportSinkResponse"\x98\x02\x82\xd3\xe4\x93\x02\x37"2/cloud/namespaces/{namespace}/export-sink-validate:\x01*\x92\x41\xd7\x01\n\x06\x45xport\x12*Validate history export sink configuration\x1a\x62Tests workflow history export sink configuration by delivering a test file to verify accessibility"=\n\x14\x45xport documentation\x12%https://docs.temporal.io/cloud/export\x12\xfc\x02\n\x13UpdateNamespaceTags\x12>.temporal.api.cloud.cloudservice.v1.UpdateNamespaceTagsRequest\x1a?.temporal.api.cloud.cloudservice.v1.UpdateNamespaceTagsResponse"\xe3\x01\x82\xd3\xe4\x93\x02.")/cloud/namespaces/{namespace}/update-tags:\x01*\x92\x41\xab\x01\n\nNamespaces\x12\x15Update namespace tags\x1a,Updates the tags associated with a namespace"X\n\x1bNamespace tag documentation\x12\x39https://docs.temporal.io/cloud/namespaces#tag-a-namespace\x12\xff\x02\n\x16\x43reateConnectivityRule\x12\x41.temporal.api.cloud.cloudservice.v1.CreateConnectivityRuleRequest\x1a\x42.temporal.api.cloud.cloudservice.v1.CreateConnectivityRuleResponse"\xdd\x01\x82\xd3\xe4\x93\x02\x1e"\x19/cloud/connectivity-rules:\x01*\x92\x41\xb5\x01\n\x12\x43onnectivity Rules\x12\x18\x43reate connectivity rule\x1a:Creates a new connectivity rule for network access control"I\n\x1a\x43onnectivity documentation\x12+https://docs.temporal.io/cloud/connectivity\x12\x94\x03\n\x13GetConnectivityRule\x12>.temporal.api.cloud.cloudservice.v1.GetConnectivityRuleRequest\x1a?.temporal.api.cloud.cloudservice.v1.GetConnectivityRuleResponse"\xfb\x01\x82\xd3\xe4\x93\x02\x32\x12\x30/cloud/connectivity-rules/{connectivity_rule_id}\x92\x41\xbf\x01\n\x12\x43onnectivity Rules\x12\x1dGet connectivity rule details\x1a?Returns detailed information about a specific connectivity rule"I\n\x1a\x43onnectivity documentation\x12+https://docs.temporal.io/cloud/connectivity\x12\xf6\x02\n\x14GetConnectivityRules\x12?.temporal.api.cloud.cloudservice.v1.GetConnectivityRulesRequest\x1a@.temporal.api.cloud.cloudservice.v1.GetConnectivityRulesResponse"\xda\x01\x82\xd3\xe4\x93\x02\x1b\x12\x19/cloud/connectivity-rules\x92\x41\xb5\x01\n\x12\x43onnectivity Rules\x12\x1bList all connectivity rules\x1a\x37Returns a list of all connectivity rules in the account"I\n\x1a\x43onnectivity documentation\x12+https://docs.temporal.io/cloud/connectivity\x12\x85\x03\n\x16\x44\x65leteConnectivityRule\x12\x41.temporal.api.cloud.cloudservice.v1.DeleteConnectivityRuleRequest\x1a\x42.temporal.api.cloud.cloudservice.v1.DeleteConnectivityRuleResponse"\xe3\x01\x82\xd3\xe4\x93\x02\x32*0/cloud/connectivity-rules/{connectivity_rule_id}\x92\x41\xa7\x01\n\x12\x43onnectivity Rules\x12\x18\x44\x65lete connectivity rule\x1a,Removes a connectivity rule from the account"I\n\x1a\x43onnectivity documentation\x12+https://docs.temporal.io/cloud/connectivity\x12\xe2\x02\n\x0cGetAuditLogs\x12\x37.temporal.api.cloud.cloudservice.v1.GetAuditLogsRequest\x1a\x38.temporal.api.cloud.cloudservice.v1.GetAuditLogsResponse"\xde\x01\x82\xd3\xe4\x93\x02\x13\x12\x11/cloud/audit-logs\x92\x41\xc1\x01\n\x07\x41\x63\x63ount\x12\x0eGet audit logs\x1aYReturns a paginated list of audit logs for the account, optionally filtered by time range"K\n\x1b\x41udit logging documentation\x12,https://docs.temporal.io/cloud/audit-logging\x12\xb4\x04\n\x1bValidateAccountAuditLogSink\x12\x46.temporal.api.cloud.cloudservice.v1.ValidateAccountAuditLogSinkRequest\x1aG.temporal.api.cloud.cloudservice.v1.ValidateAccountAuditLogSinkResponse"\x83\x03\x82\xd3\xe4\x93\x02#"\x1e/cloud/audit-log-sink-validate:\x01*\x92\x41\xd6\x02\n\x07\x41\x63\x63ount\x12\x17Validate audit log sink\x1a\xe4\x01Validate customer audit log sink is accessible from Temporal\'s workflow by delivering an empty file to the specified sink. The operation verifies that the sink is correctly configured, accessible and ready to receive audit logs."K\n\x1b\x41udit logging documentation\x12,https://docs.temporal.io/cloud/audit-logging\x12\xf4\x02\n\x19\x43reateAccountAuditLogSink\x12\x44.temporal.api.cloud.cloudservice.v1.CreateAccountAuditLogSinkRequest\x1a\x45.temporal.api.cloud.cloudservice.v1.CreateAccountAuditLogSinkResponse"\xc9\x01\x82\xd3\xe4\x93\x02\x1b"\x16/cloud/audit-log-sinks:\x01*\x92\x41\xa4\x01\n\x07\x41\x63\x63ount\x12\x15\x43reate audit log sink\x1a\x35\x43reates a new audit log sink for exporting audit logs"K\n\x1b\x41udit logging documentation\x12,https://docs.temporal.io/cloud/audit-logging\x12\xfb\x02\n\x16GetAccountAuditLogSink\x12\x41.temporal.api.cloud.cloudservice.v1.GetAccountAuditLogSinkRequest\x1a\x42.temporal.api.cloud.cloudservice.v1.GetAccountAuditLogSinkResponse"\xd9\x01\x82\xd3\xe4\x93\x02\x1f\x12\x1d/cloud/audit-log-sinks/{name}\x92\x41\xb0\x01\n\x07\x41\x63\x63ount\x12\x1aGet audit log sink details\x1a.temporal.api.cloud.cloudservice.v1.CreateBillingReportRequest\x1a?.temporal.api.cloud.cloudservice.v1.CreateBillingReportResponse"\xc1\x01\x82\xd3\xe4\x93\x02\x1b"\x16/cloud/billing-reports:\x01*\x92\x41\x9c\x01\n\x07\x41\x63\x63ount\x12\x17\x43reate a billing report\x1a(Creates a billing report for the account"N\n\x1c\x42illing report documentation\x12.https://docs.temporal.io/cloud/billing-reports\x12\xe6\x02\n\x10GetBillingReport\x12;.temporal.api.cloud.cloudservice.v1.GetBillingReportRequest\x1a<.temporal.api.cloud.cloudservice.v1.GetBillingReportResponse"\xd6\x01\x82\xd3\xe4\x93\x02,\x12*/cloud/billing-reports/{billing_report_id}\x92\x41\xa0\x01\n\x07\x41\x63\x63ount\x12\x14Get a billing report\x1a/Gets an existing billing report for the account"N\n\x1c\x42illing report documentation\x12.https://docs.temporal.io/cloud/billing-reports\x12\xc4\x02\n\x0eGetCustomRoles\x12\x39.temporal.api.cloud.cloudservice.v1.GetCustomRolesRequest\x1a:.temporal.api.cloud.cloudservice.v1.GetCustomRolesResponse"\xba\x01\x82\xd3\xe4\x93\x02\x15\x12\x13/cloud/custom-roles\x92\x41\x9b\x01\n\x0c\x43ustom Roles\x12\x11List custom roles\x1a-Returns a list of custom roles in the account"I\n\x1a\x43ustom roles documentation\x12+https://docs.temporal.io/cloud/custom-roles\x12\xcc\x02\n\rGetCustomRole\x12\x38.temporal.api.cloud.cloudservice.v1.GetCustomRoleRequest\x1a\x39.temporal.api.cloud.cloudservice.v1.GetCustomRoleResponse"\xc5\x01\x82\xd3\xe4\x93\x02\x1f\x12\x1d/cloud/custom-roles/{role_id}\x92\x41\x9c\x01\n\x0c\x43ustom Roles\x12\x15Get custom role by ID\x1a*Returns details for a specific custom role"I\n\x1a\x43ustom roles documentation\x12+https://docs.temporal.io/cloud/custom-roles\x12\xcb\x02\n\x10\x43reateCustomRole\x12;.temporal.api.cloud.cloudservice.v1.CreateCustomRoleRequest\x1a<.temporal.api.cloud.cloudservice.v1.CreateCustomRoleResponse"\xbb\x01\x82\xd3\xe4\x93\x02\x18"\x13/cloud/custom-roles:\x01*\x92\x41\x99\x01\n\x0c\x43ustom Roles\x12\x14\x43reate a custom role\x1a(Creates a new custom role in the account"I\n\x1a\x43ustom roles documentation\x12+https://docs.temporal.io/cloud/custom-roles\x12\xcc\x02\n\x10UpdateCustomRole\x12;.temporal.api.cloud.cloudservice.v1.UpdateCustomRoleRequest\x1a<.temporal.api.cloud.cloudservice.v1.UpdateCustomRoleResponse"\xbc\x01\x82\xd3\xe4\x93\x02""\x1d/cloud/custom-roles/{role_id}:\x01*\x92\x41\x90\x01\n\x0c\x43ustom Roles\x12\x14Update a custom role\x1a\x1fUpdates an existing custom role"I\n\x1a\x43ustom roles documentation\x12+https://docs.temporal.io/cloud/custom-roles\x12\xd0\x02\n\x10\x44\x65leteCustomRole\x12;.temporal.api.cloud.cloudservice.v1.DeleteCustomRoleRequest\x1a<.temporal.api.cloud.cloudservice.v1.DeleteCustomRoleResponse"\xc0\x01\x82\xd3\xe4\x93\x02\x1f*\x1d/cloud/custom-roles/{role_id}\x92\x41\x97\x01\n\x0c\x43ustom Roles\x12\x14\x44\x65lete a custom role\x1a&Deletes a custom role from the account"I\n\x1a\x43ustom roles documentation\x12+https://docs.temporal.io/cloud/custom-rolesB\xc1\x15\n%io.temporal.api.cloud.cloudservice.v1B\x0cServiceProtoP\x01Z5go.temporal.io/api/cloud/cloudservice/v1;cloudservice\xaa\x02$Temporalio.Api.Cloud.CloudService.V1\xea\x02(Temporalio::Api::Cloud::CloudService::V1\x92\x41\xfd\x13\x12\xe0\r\n\x16Temporal Cloud Ops API\x12\x96\x0cProgrammatic access to manage Temporal Cloud control plane resources including namespaces, users, service accounts, and more.\n\n## Authentication\n\nAll API requests require authentication using an API Key. Include your API key in the `Authorization` header using the Bearer scheme:\n\n```\nAuthorization: Bearer YOUR_API_KEY\n```\n\nAPI keys can be created and managed through the [API Keys endpoints](#tag/API-Keys) or via the Temporal Cloud UI. For more information, see [API Keys Documentation](https://docs.temporal.io/cloud/api-keys).\n\n## Authorization\n\nThe API uses Role-Based Access Control (RBAC) to manage permissions. Each operation requires specific role-based permissions in addition to a valid API key.\n\n### Account-Level Roles\n\n- **Account Owner** - Full account administration access\n- **Account Admin** - Manage namespaces, users, and service accounts \n- **Account Developer** - Create namespaces and manage Nexus endpoints\n- **Finance Admin** - View usage and billing information\n- **Account Read** - Read-only access to account resources\n\n### Namespace-Level Roles\n\n- **Namespace Admin** - Full access to namespace configuration and data\n- **Namespace Write** - Execute workflows and modify workflow data\n- **Namespace Read** - Read-only access to namespace data\n\nNamespace-level permissions are scoped to specific namespaces. A user or service account may have different permission levels across different namespaces.\n\nFor detailed information about roles and permissions, see [Access Control Documentation](https://docs.temporal.io/cloud/users).2\x03\x31.0:\xa7\x01\n\x06x-logo\x12\x9c\x01*\x99\x01\n\x96\x01\n\x03url\x12\x8e\x01\x1a\x8b\x01https://images.ctfassets.net/0uuz8ydxyd9p/4YGUnEoCaH9SyoUDhlJkau/e1600205d17eeee3033d926ef06664a9/Temporal_LogoLockup_Horizontal_dark_1.svgj.\n\nNamespaces\x12 Manage Temporal Cloud namespacesj0\n\x05Users\x12\'Manage users and their namespace accessjF\n\x10Service Accounts\x12\x32Manage service accounts and their namespace accessj.\n\x08\x41PI Keys\x12"Manage API keys for authenticationj1\n\x06Groups\x12\'Manage user groups and group membershipj\x1f\n\x05Nexus\x12\x16Manage Nexus endpointsj\x7f\n\x11High Availability\x12jManage high availability (multi-region, multi-cloud, and same-region replication) namespace configurationsj7\n\x06\x45xport\x12-Manage workflow history export configurationsj7\n\x12\x43onnectivity Rules\x12!Manage network connectivity rulesj"\n\x07Regions\x12\x17Query available regionsj,\n\x07\x41\x63\x63ount\x12!Manage account settings and usagej9\n\x0c\x43ustom Roles\x12)Manage custom roles and their permissionsj*\n\nOperations\x12\x1cQuery async operation statusr>\n\x1cTemporal Cloud Documentation\x12\x1ehttps://docs.temporal.io/cloudb\x06proto3' + b'\n0temporal/api/cloud/cloudservice/v1/service.proto\x12"temporal.api.cloud.cloudservice.v1\x1a\x39temporal/api/cloud/cloudservice/v1/request_response.proto\x1a\x1cgoogle/api/annotations.proto\x1a.protoc-gen-openapiv2/options/annotations.proto2\x92\xd7\x01\n\x0c\x43loudService\x12\xb0\x02\n\x12GetCurrentIdentity\x12=.temporal.api.cloud.cloudservice.v1.GetCurrentIdentityRequest\x1a>.temporal.api.cloud.cloudservice.v1.GetCurrentIdentityResponse"\x9a\x01\x82\xd3\xe4\x93\x02\x19\x12\x17/cloud/current-identity\x92\x41x\n\x07\x41\x63\x63ount\x12\x14Get current identity\x1aWReturns information about the currently authenticated user or service account principal\x12\xa5\x02\n\x08GetUsers\x12\x33.temporal.api.cloud.cloudservice.v1.GetUsersRequest\x1a\x34.temporal.api.cloud.cloudservice.v1.GetUsersResponse"\xad\x01\x82\xd3\xe4\x93\x02\x0e\x12\x0c/cloud/users\x92\x41\x95\x01\n\x05Users\x12\x0eList all users\x1a*Returns a list of all users in the account"E\n\x1dUser management documentation\x12$https://docs.temporal.io/cloud/users*\tlistUsers\x12\x9c\x02\n\x07GetUser\x12\x32.temporal.api.cloud.cloudservice.v1.GetUserRequest\x1a\x33.temporal.api.cloud.cloudservice.v1.GetUserResponse"\xa7\x01\x82\xd3\xe4\x93\x02\x18\x12\x16/cloud/users/{user_id}\x92\x41\x85\x01\n\x05Users\x12\x0eGet user by ID\x1a%Takes a user ID, returns user details"E\n\x1dUser management documentation\x12$https://docs.temporal.io/cloud/users\x12\xd0\x01\n\nCreateUser\x12\x35.temporal.api.cloud.cloudservice.v1.CreateUserRequest\x1a\x36.temporal.api.cloud.cloudservice.v1.CreateUserResponse"S\x82\xd3\xe4\x93\x02\x11"\x0c/cloud/users:\x01*\x92\x41\x39\n\x05Users\x12\rCreate a user\x1a!Creates a new user in the account\x12\xdb\x01\n\nUpdateUser\x12\x35.temporal.api.cloud.cloudservice.v1.UpdateUserRequest\x1a\x36.temporal.api.cloud.cloudservice.v1.UpdateUserResponse"^\x82\xd3\xe4\x93\x02\x1b"\x16/cloud/users/{user_id}:\x01*\x92\x41:\n\x05Users\x12\rUpdate a user\x1a"Updates an existing user\'s details\x12\xd5\x01\n\nDeleteUser\x12\x35.temporal.api.cloud.cloudservice.v1.DeleteUserRequest\x1a\x36.temporal.api.cloud.cloudservice.v1.DeleteUserResponse"X\x82\xd3\xe4\x93\x02\x18*\x16/cloud/users/{user_id}\x92\x41\x37\n\x05Users\x12\rDelete a user\x1a\x1fRemoves a user from the account\x12\xaa\x03\n\x16SetUserNamespaceAccess\x12\x41.temporal.api.cloud.cloudservice.v1.SetUserNamespaceAccessRequest\x1a\x42.temporal.api.cloud.cloudservice.v1.SetUserNamespaceAccessResponse"\x88\x02\x82\xd3\xe4\x93\x02\x39"4/cloud/namespaces/{namespace}/users/{user_id}/access:\x01*\x92\x41\xc5\x01\n\x05Users\x12\x19Set user namespace access\x1a\x38\x43onfigures a user\'s permissions for a specific namespace"g\n#Namespace permissions documentation\x12@https://docs.temporal.io/cloud/users-namespace-level-permissions\x12\xb1\x02\n\x11GetAsyncOperation\x12<.temporal.api.cloud.cloudservice.v1.GetAsyncOperationRequest\x1a=.temporal.api.cloud.cloudservice.v1.GetAsyncOperationResponse"\x9e\x01\x82\xd3\xe4\x93\x02(\x12&/cloud/operations/{async_operation_id}\x92\x41m\n\nOperations\x12\x1aGet async operation status\x1a\x43Returns the current status and details of an asynchronous operation\x12\xc6\x02\n\x0f\x43reateNamespace\x12:.temporal.api.cloud.cloudservice.v1.CreateNamespaceRequest\x1a;.temporal.api.cloud.cloudservice.v1.CreateNamespaceResponse"\xb9\x01\x82\xd3\xe4\x93\x02\x16"\x11/cloud/namespaces:\x01*\x92\x41\x99\x01\n\nNamespaces\x12\x12\x43reate a namespace\x1a&Creates a new namespace in the account"O\n"Namespace management documentation\x12)https://docs.temporal.io/cloud/namespaces\x12\xc7\x02\n\rGetNamespaces\x12\x38.temporal.api.cloud.cloudservice.v1.GetNamespacesRequest\x1a\x39.temporal.api.cloud.cloudservice.v1.GetNamespacesResponse"\xc0\x01\x82\xd3\xe4\x93\x02\x13\x12\x11/cloud/namespaces\x92\x41\xa3\x01\n\nNamespaces\x12\x13List all namespaces\x1a/Returns a list of all namespaces in the account"O\n"Namespace management documentation\x12)https://docs.temporal.io/cloud/namespaces\x12\xda\x02\n\x0cGetNamespace\x12\x37.temporal.api.cloud.cloudservice.v1.GetNamespaceRequest\x1a\x38.temporal.api.cloud.cloudservice.v1.GetNamespaceResponse"\xd6\x01\x82\xd3\xe4\x93\x02\x1f\x12\x1d/cloud/namespaces/{namespace}\x92\x41\xad\x01\n\nNamespaces\x12\x15Get namespace details\x1a\x37Returns detailed information about a specific namespace"O\n"Namespace management documentation\x12)https://docs.temporal.io/cloud/namespaces\x12\xdb\x02\n\x0fUpdateNamespace\x12:.temporal.api.cloud.cloudservice.v1.UpdateNamespaceRequest\x1a;.temporal.api.cloud.cloudservice.v1.UpdateNamespaceResponse"\xce\x01\x82\xd3\xe4\x93\x02""\x1d/cloud/namespaces/{namespace}:\x01*\x92\x41\xa2\x01\n\nNamespaces\x12\x12Update a namespace\x1a/Updates configuration for an existing namespace"O\n"Namespace management documentation\x12)https://docs.temporal.io/cloud/namespaces\x12\xc7\x03\n\x1bRenameCustomSearchAttribute\x12\x46.temporal.api.cloud.cloudservice.v1.RenameCustomSearchAttributeRequest\x1aG.temporal.api.cloud.cloudservice.v1.RenameCustomSearchAttributeResponse"\x96\x02\x82\xd3\xe4\x93\x02\x41".temporal.api.cloud.cloudservice.v1.AddNamespaceRegionResponse"\xf0\x01\x88\x02\x01\x82\xd3\xe4\x93\x02-"(/cloud/namespaces/{namespace}/add-region:\x01*\x92\x41\xb6\x01\n\x11High Availability\x12\x15\x41\x64\x64 namespace replica\x1a+Adds a new replica to an existing namespace"]\n)High availability namespace documentation\x12\x30https://docs.temporal.io/cloud/high-availability\x12\x9e\x03\n\x15\x44\x65leteNamespaceRegion\x12@.temporal.api.cloud.cloudservice.v1.DeleteNamespaceRegionRequest\x1a\x41.temporal.api.cloud.cloudservice.v1.DeleteNamespaceRegionResponse"\xff\x01\x88\x02\x01\x82\xd3\xe4\x93\x02\x30*./cloud/namespaces/{namespace}/regions/{region}\x92\x41\xc2\x01\n\x11High Availability\x12\x18Remove namespace replica\x1a\x34Removes a replica from a high availability namespace"]\n)High availability namespace documentation\x12\x30https://docs.temporal.io/cloud/high-availability\x12\xa3\x02\n\nGetRegions\x12\x35.temporal.api.cloud.cloudservice.v1.GetRegionsRequest\x1a\x36.temporal.api.cloud.cloudservice.v1.GetRegionsResponse"\xa5\x01\x82\xd3\xe4\x93\x02\x10\x12\x0e/cloud/regions\x92\x41\x8b\x01\n\x07Regions\x12\x10List all regions\x1a-Returns a list of all available cloud regions"?\n\x15Regions documentation\x12&https://docs.temporal.io/cloud/regions\x12\xb2\x02\n\tGetRegion\x12\x34.temporal.api.cloud.cloudservice.v1.GetRegionRequest\x1a\x35.temporal.api.cloud.cloudservice.v1.GetRegionResponse"\xb7\x01\x82\xd3\xe4\x93\x02\x19\x12\x17/cloud/regions/{region}\x92\x41\x94\x01\n\x07Regions\x12\x12Get region details\x1a\x34Returns detailed information about a specific region"?\n\x15Regions documentation\x12&https://docs.temporal.io/cloud/regions\x12\xa8\x02\n\nGetApiKeys\x12\x35.temporal.api.cloud.cloudservice.v1.GetApiKeysRequest\x1a\x36.temporal.api.cloud.cloudservice.v1.GetApiKeysResponse"\xaa\x01\x82\xd3\xe4\x93\x02\x11\x12\x0f/cloud/api-keys\x92\x41\x8f\x01\n\x08\x41PI Keys\x12\x11List all API keys\x1a-Returns a list of all API keys in the account"A\n\x16\x41PI Keys documentation\x12\'https://docs.temporal.io/cloud/api-keys\x12\xb8\x02\n\tGetApiKey\x12\x34.temporal.api.cloud.cloudservice.v1.GetApiKeyRequest\x1a\x35.temporal.api.cloud.cloudservice.v1.GetApiKeyResponse"\xbd\x01\x82\xd3\xe4\x93\x02\x1a\x12\x18/cloud/api-keys/{key_id}\x92\x41\x99\x01\n\x08\x41PI Keys\x12\x13Get API key details\x1a\x35Returns detailed information about a specific API key"A\n\x16\x41PI Keys documentation\x12\'https://docs.temporal.io/cloud/api-keys\x12\xb1\x02\n\x0c\x43reateApiKey\x12\x37.temporal.api.cloud.cloudservice.v1.CreateApiKeyRequest\x1a\x38.temporal.api.cloud.cloudservice.v1.CreateApiKeyResponse"\xad\x01\x82\xd3\xe4\x93\x02\x14"\x0f/cloud/api-keys:\x01*\x92\x41\x8f\x01\n\x08\x41PI Keys\x12\x11\x43reate an API key\x1a-Creates a new API key for programmatic access"A\n\x16\x41PI Keys documentation\x12\'https://docs.temporal.io/cloud/api-keys\x12\xb5\x02\n\x0cUpdateApiKey\x12\x37.temporal.api.cloud.cloudservice.v1.UpdateApiKeyRequest\x1a\x38.temporal.api.cloud.cloudservice.v1.UpdateApiKeyResponse"\xb1\x01\x82\xd3\xe4\x93\x02\x1d"\x18/cloud/api-keys/{key_id}:\x01*\x92\x41\x8a\x01\n\x08\x41PI Keys\x12\x11Update an API key\x1a(Updates an existing API key\'s properties"A\n\x16\x41PI Keys documentation\x12\'https://docs.temporal.io/cloud/api-keys\x12\xa8\x02\n\x0c\x44\x65leteApiKey\x12\x37.temporal.api.cloud.cloudservice.v1.DeleteApiKeyRequest\x1a\x38.temporal.api.cloud.cloudservice.v1.DeleteApiKeyResponse"\xa4\x01\x82\xd3\xe4\x93\x02\x1a*\x18/cloud/api-keys/{key_id}\x92\x41\x80\x01\n\x08\x41PI Keys\x12\x11\x44\x65lete an API key\x1a\x1eRevokes and deletes an API key"A\n\x16\x41PI Keys documentation\x12\'https://docs.temporal.io/cloud/api-keys\x12\xc3\x02\n\x11GetNexusEndpoints\x12<.temporal.api.cloud.cloudservice.v1.GetNexusEndpointsRequest\x1a=.temporal.api.cloud.cloudservice.v1.GetNexusEndpointsResponse"\xb0\x01\x82\xd3\xe4\x93\x02\x18\x12\x16/cloud/nexus/endpoints\x92\x41\x8e\x01\n\x05Nexus\x12\x18List all Nexus endpoints\x1a\x34Returns a list of all Nexus endpoints in the account"5\n\x13Nexus documentation\x12\x1ehttps://docs.temporal.io/nexus\x12\xd8\x02\n\x10GetNexusEndpoint\x12;.temporal.api.cloud.cloudservice.v1.GetNexusEndpointRequest\x1a<.temporal.api.cloud.cloudservice.v1.GetNexusEndpointResponse"\xc8\x01\x82\xd3\xe4\x93\x02&\x12$/cloud/nexus/endpoints/{endpoint_id}\x92\x41\x98\x01\n\x05Nexus\x12\x1aGet Nexus endpoint details\x1a.temporal.api.cloud.cloudservice.v1.CreateNexusEndpointRequest\x1a?.temporal.api.cloud.cloudservice.v1.CreateNexusEndpointResponse"\xbc\x01\x82\xd3\xe4\x93\x02\x1b"\x16/cloud/nexus/endpoints:\x01*\x92\x41\x97\x01\n\x05Nexus\x12\x17\x43reate a Nexus endpoint\x1a>Creates a new Nexus endpoint for cross-namespace communication"5\n\x13Nexus documentation\x12\x1ehttps://docs.temporal.io/nexus\x12\xd7\x02\n\x13UpdateNexusEndpoint\x12>.temporal.api.cloud.cloudservice.v1.UpdateNexusEndpointRequest\x1a?.temporal.api.cloud.cloudservice.v1.UpdateNexusEndpointResponse"\xbe\x01\x82\xd3\xe4\x93\x02)"$/cloud/nexus/endpoints/{endpoint_id}:\x01*\x92\x41\x8b\x01\n\x05Nexus\x12\x17Update a Nexus endpoint\x1a\x32Updates an existing Nexus endpoint\'s configuration"5\n\x13Nexus documentation\x12\x1ehttps://docs.temporal.io/nexus\x12\xcb\x02\n\x13\x44\x65leteNexusEndpoint\x12>.temporal.api.cloud.cloudservice.v1.DeleteNexusEndpointRequest\x1a?.temporal.api.cloud.cloudservice.v1.DeleteNexusEndpointResponse"\xb2\x01\x82\xd3\xe4\x93\x02&*$/cloud/nexus/endpoints/{endpoint_id}\x92\x41\x82\x01\n\x05Nexus\x12\x17\x44\x65lete a Nexus endpoint\x1a)Removes a Nexus endpoint from the account"5\n\x13Nexus documentation\x12\x1ehttps://docs.temporal.io/nexus\x12\xcc\x02\n\rGetUserGroups\x12\x38.temporal.api.cloud.cloudservice.v1.GetUserGroupsRequest\x1a\x39.temporal.api.cloud.cloudservice.v1.GetUserGroupsResponse"\xc5\x01\x82\xd3\xe4\x93\x02\x14\x12\x12/cloud/user-groups\x92\x41\xa7\x01\n\x06Groups\x12\x14List all user groups\x1a\x30Returns a list of all user groups in the account"U\n\x19User groups documentation\x12\x38https://docs.temporal.io/cloud/users-account-level-roles\x12\xd0\x02\n\x0cGetUserGroup\x12\x37.temporal.api.cloud.cloudservice.v1.GetUserGroupRequest\x1a\x38.temporal.api.cloud.cloudservice.v1.GetUserGroupResponse"\xcc\x01\x82\xd3\xe4\x93\x02\x1f\x12\x1d/cloud/user-groups/{group_id}\x92\x41\xa3\x01\n\x06Groups\x12\x16Get user group details\x1a\x38Returns detailed information about a specific user group"G\n\x19User groups documentation\x12*https://docs.temporal.io/cloud/user-groups\x12\xc7\x02\n\x0f\x43reateUserGroup\x12:.temporal.api.cloud.cloudservice.v1.CreateUserGroupRequest\x1a;.temporal.api.cloud.cloudservice.v1.CreateUserGroupResponse"\xba\x01\x82\xd3\xe4\x93\x02\x17"\x12/cloud/user-groups:\x01*\x92\x41\x99\x01\n\x06Groups\x12\x13\x43reate a user group\x1a\x31\x43reates a new user group for managing permissions"G\n\x19User groups documentation\x12*https://docs.temporal.io/cloud/user-groups\x12\xcc\x02\n\x0fUpdateUserGroup\x12:.temporal.api.cloud.cloudservice.v1.UpdateUserGroupRequest\x1a;.temporal.api.cloud.cloudservice.v1.UpdateUserGroupResponse"\xbf\x01\x82\xd3\xe4\x93\x02""\x1d/cloud/user-groups/{group_id}:\x01*\x92\x41\x93\x01\n\x06Groups\x12\x13Update a user group\x1a+Updates an existing user group\'s properties"G\n\x19User groups documentation\x12*https://docs.temporal.io/cloud/user-groups\x12\xc3\x02\n\x0f\x44\x65leteUserGroup\x12:.temporal.api.cloud.cloudservice.v1.DeleteUserGroupRequest\x1a;.temporal.api.cloud.cloudservice.v1.DeleteUserGroupResponse"\xb6\x01\x82\xd3\xe4\x93\x02\x1f*\x1d/cloud/user-groups/{group_id}\x92\x41\x8d\x01\n\x06Groups\x12\x13\x44\x65lete a user group\x1a%Removes a user group from the account"G\n\x19User groups documentation\x12*https://docs.temporal.io/cloud/user-groups\x12\xad\x03\n\x1bSetUserGroupNamespaceAccess\x12\x46.temporal.api.cloud.cloudservice.v1.SetUserGroupNamespaceAccessRequest\x1aG.temporal.api.cloud.cloudservice.v1.SetUserGroupNamespaceAccessResponse"\xfc\x01\x82\xd3\xe4\x93\x02@";/cloud/namespaces/{namespace}/user-groups/{group_id}/access:\x01*\x92\x41\xb2\x01\n\x06Groups\x12\x1fSet user group namespace access\x1a>Configures a user group\'s permissions for a specific namespace"G\n\x19User groups documentation\x12*https://docs.temporal.io/cloud/user-groups\x12\xdf\x02\n\x12\x41\x64\x64UserGroupMember\x12=.temporal.api.cloud.cloudservice.v1.AddUserGroupMemberRequest\x1a>.temporal.api.cloud.cloudservice.v1.AddUserGroupMemberResponse"\xc9\x01\x82\xd3\xe4\x93\x02*"%/cloud/user-groups/{group_id}/members:\x01*\x92\x41\x95\x01\n\x06Groups\x12\x11\x41\x64\x64 user to group\x1a/Adds a user to a user group (Cloud groups only)"G\n\x19User groups documentation\x12*https://docs.temporal.io/cloud/user-groups\x12\xf8\x02\n\x15RemoveUserGroupMember\x12@.temporal.api.cloud.cloudservice.v1.RemoveUserGroupMemberRequest\x1a\x41.temporal.api.cloud.cloudservice.v1.RemoveUserGroupMemberResponse"\xd9\x01\x82\xd3\xe4\x93\x02\x30"+/cloud/user-groups/{group_id}/remove-member:\x01*\x92\x41\x9f\x01\n\x06Groups\x12\x16Remove user from group\x1a\x34Removes a user from a user group (Cloud groups only)"G\n\x19User groups documentation\x12*https://docs.temporal.io/cloud/user-groups\x12\xdf\x02\n\x13GetUserGroupMembers\x12>.temporal.api.cloud.cloudservice.v1.GetUserGroupMembersRequest\x1a?.temporal.api.cloud.cloudservice.v1.GetUserGroupMembersResponse"\xc6\x01\x82\xd3\xe4\x93\x02\'\x12%/cloud/user-groups/{group_id}/members\x92\x41\x95\x01\n\x06Groups\x12\x15List users in a group\x1a+Returns a list of all users in a user group"G\n\x19User groups documentation\x12*https://docs.temporal.io/cloud/user-groups\x12\xf5\x02\n\x14\x43reateServiceAccount\x12?.temporal.api.cloud.cloudservice.v1.CreateServiceAccountRequest\x1a@.temporal.api.cloud.cloudservice.v1.CreateServiceAccountResponse"\xd9\x01\x82\xd3\xe4\x93\x02\x1c"\x17/cloud/service-accounts:\x01*\x92\x41\xb3\x01\n\x10Service Accounts\x12\x18\x43reate a service account\x1a\x32\x43reates a new service account for automated access"Q\n\x1eService Accounts documentation\x12/https://docs.temporal.io/cloud/service-accounts\x12\x8c\x03\n\x11GetServiceAccount\x12<.temporal.api.cloud.cloudservice.v1.GetServiceAccountRequest\x1a=.temporal.api.cloud.cloudservice.v1.GetServiceAccountResponse"\xf9\x01\x82\xd3\xe4\x93\x02.\x12,/cloud/service-accounts/{service_account_id}\x92\x41\xc1\x01\n\x10Service Accounts\x12\x1bGet service account details\x1a=Returns detailed information about a specific service account"Q\n\x1eService Accounts documentation\x12/https://docs.temporal.io/cloud/service-accounts\x12\xf0\x02\n\x12GetServiceAccounts\x12=.temporal.api.cloud.cloudservice.v1.GetServiceAccountsRequest\x1a>.temporal.api.cloud.cloudservice.v1.GetServiceAccountsResponse"\xda\x01\x82\xd3\xe4\x93\x02\x19\x12\x17/cloud/service-accounts\x92\x41\xb7\x01\n\x10Service Accounts\x12\x19List all service accounts\x1a\x35Returns a list of all service accounts in the account"Q\n\x1eService Accounts documentation\x12/https://docs.temporal.io/cloud/service-accounts\x12\x88\x03\n\x14UpdateServiceAccount\x12?.temporal.api.cloud.cloudservice.v1.UpdateServiceAccountRequest\x1a@.temporal.api.cloud.cloudservice.v1.UpdateServiceAccountResponse"\xec\x01\x82\xd3\xe4\x93\x02\x31",/cloud/service-accounts/{service_account_id}:\x01*\x92\x41\xb1\x01\n\x10Service Accounts\x12\x18Update a service account\x1a\x30Updates an existing service account\'s properties"Q\n\x1eService Accounts documentation\x12/https://docs.temporal.io/cloud/service-accounts\x12\xe9\x03\n SetServiceAccountNamespaceAccess\x12K.temporal.api.cloud.cloudservice.v1.SetServiceAccountNamespaceAccessRequest\x1aL.temporal.api.cloud.cloudservice.v1.SetServiceAccountNamespaceAccessResponse"\xa9\x02\x82\xd3\xe4\x93\x02O"J/cloud/namespaces/{namespace}/service-accounts/{service_account_id}/access:\x01*\x92\x41\xd0\x01\n\x10Service Accounts\x12$Set service account namespace access\x1a\x43\x43onfigures a service account\'s permissions for a specific namespace"Q\n\x1eService Accounts documentation\x12/https://docs.temporal.io/cloud/service-accounts\x12\xff\x02\n\x14\x44\x65leteServiceAccount\x12?.temporal.api.cloud.cloudservice.v1.DeleteServiceAccountRequest\x1a@.temporal.api.cloud.cloudservice.v1.DeleteServiceAccountResponse"\xe3\x01\x82\xd3\xe4\x93\x02.*,/cloud/service-accounts/{service_account_id}\x92\x41\xab\x01\n\x10Service Accounts\x12\x18\x44\x65lete a service account\x1a*Removes a service account from the account"Q\n\x1eService Accounts documentation\x12/https://docs.temporal.io/cloud/service-accounts\x12\xcb\x01\n\x08GetUsage\x12\x33.temporal.api.cloud.cloudservice.v1.GetUsageRequest\x1a\x34.temporal.api.cloud.cloudservice.v1.GetUsageResponse"T\x82\xd3\xe4\x93\x02\x0e\x12\x0c/cloud/usage\x92\x41=\n\x07\x41\x63\x63ount\x12\x0eGet usage data\x1a Get usage data across namespacesX\x01\x12\xb0\x02\n\nGetAccount\x12\x35.temporal.api.cloud.cloudservice.v1.GetAccountRequest\x1a\x36.temporal.api.cloud.cloudservice.v1.GetAccountResponse"\xb2\x01\x82\xd3\xe4\x93\x02\x10\x12\x0e/cloud/account\x92\x41\x98\x01\n\x07\x41\x63\x63ount\x12\x13Get account details\x1a.Returns detailed information about the account"H\n\x15\x42illing documentation\x12/https://docs.temporal.io/cloud/billing-and-cost\x12\xbb\x02\n\rUpdateAccount\x12\x38.temporal.api.cloud.cloudservice.v1.UpdateAccountRequest\x1a\x39.temporal.api.cloud.cloudservice.v1.UpdateAccountResponse"\xb4\x01\x82\xd3\xe4\x93\x02\x13"\x0e/cloud/account:\x01*\x92\x41\x97\x01\n\x07\x41\x63\x63ount\x12\x16Update account details\x1a*Updates account configuration and settings"H\n\x15\x42illing documentation\x12/https://docs.temporal.io/cloud/billing-and-cost\x12\xf3\x02\n\x19\x43reateNamespaceExportSink\x12\x44.temporal.api.cloud.cloudservice.v1.CreateNamespaceExportSinkRequest\x1a\x45.temporal.api.cloud.cloudservice.v1.CreateNamespaceExportSinkResponse"\xc8\x01\x82\xd3\xe4\x93\x02/"*/cloud/namespaces/{namespace}/export-sinks:\x01*\x92\x41\x8f\x01\n\x06\x45xport\x12\x1a\x43reate history export sink\x1a*Creates a new workflow history export sink"=\n\x14\x45xport documentation\x12%https://docs.temporal.io/cloud/export\x12\x8c\x03\n\x16GetNamespaceExportSink\x12\x41.temporal.api.cloud.cloudservice.v1.GetNamespaceExportSinkRequest\x1a\x42.temporal.api.cloud.cloudservice.v1.GetNamespaceExportSinkResponse"\xea\x01\x82\xd3\xe4\x93\x02\x33\x12\x31/cloud/namespaces/{namespace}/export-sinks/{name}\x92\x41\xad\x01\n\x06\x45xport\x12\x18Get history sink details\x1aJReturns detailed information about a specific workflow history export sink"=\n\x14\x45xport documentation\x12%https://docs.temporal.io/cloud/export\x12\x82\x03\n\x17GetNamespaceExportSinks\x12\x42.temporal.api.cloud.cloudservice.v1.GetNamespaceExportSinksRequest\x1a\x43.temporal.api.cloud.cloudservice.v1.GetNamespaceExportSinksResponse"\xdd\x01\x82\xd3\xe4\x93\x02,\x12*/cloud/namespaces/{namespace}/export-sinks\x92\x41\xa7\x01\n\x06\x45xport\x12\x19List history export sinks\x1a\x43Returns a list of all workflow history export sinks for a namespace"=\n\x14\x45xport documentation\x12%https://docs.temporal.io/cloud/export\x12\x95\x03\n\x19UpdateNamespaceExportSink\x12\x44.temporal.api.cloud.cloudservice.v1.UpdateNamespaceExportSinkRequest\x1a\x45.temporal.api.cloud.cloudservice.v1.UpdateNamespaceExportSinkResponse"\xea\x01\x82\xd3\xe4\x93\x02;"6/cloud/namespaces/{namespace}/export-sinks/{spec.name}:\x01*\x92\x41\xa5\x01\n\x06\x45xport\x12\x1aUpdate history export sink\x1a@Updates an existing workflow history export sink\'s configuration"=\n\x14\x45xport documentation\x12%https://docs.temporal.io/cloud/export\x12\x84\x03\n\x19\x44\x65leteNamespaceExportSink\x12\x44.temporal.api.cloud.cloudservice.v1.DeleteNamespaceExportSinkRequest\x1a\x45.temporal.api.cloud.cloudservice.v1.DeleteNamespaceExportSinkResponse"\xd9\x01\x82\xd3\xe4\x93\x02\x33*1/cloud/namespaces/{namespace}/export-sinks/{name}\x92\x41\x9c\x01\n\x06\x45xport\x12\x1a\x44\x65lete history export sink\x1a\x37Removes a workflow history export sink from a namespace"=\n\x14\x45xport documentation\x12%https://docs.temporal.io/cloud/export\x12\xc9\x03\n\x1bValidateNamespaceExportSink\x12\x46.temporal.api.cloud.cloudservice.v1.ValidateNamespaceExportSinkRequest\x1aG.temporal.api.cloud.cloudservice.v1.ValidateNamespaceExportSinkResponse"\x98\x02\x82\xd3\xe4\x93\x02\x37"2/cloud/namespaces/{namespace}/export-sink-validate:\x01*\x92\x41\xd7\x01\n\x06\x45xport\x12*Validate history export sink configuration\x1a\x62Tests workflow history export sink configuration by delivering a test file to verify accessibility"=\n\x14\x45xport documentation\x12%https://docs.temporal.io/cloud/export\x12\xfc\x02\n\x13UpdateNamespaceTags\x12>.temporal.api.cloud.cloudservice.v1.UpdateNamespaceTagsRequest\x1a?.temporal.api.cloud.cloudservice.v1.UpdateNamespaceTagsResponse"\xe3\x01\x82\xd3\xe4\x93\x02.")/cloud/namespaces/{namespace}/update-tags:\x01*\x92\x41\xab\x01\n\nNamespaces\x12\x15Update namespace tags\x1a,Updates the tags associated with a namespace"X\n\x1bNamespace tag documentation\x12\x39https://docs.temporal.io/cloud/namespaces#tag-a-namespace\x12\xff\x02\n\x16\x43reateConnectivityRule\x12\x41.temporal.api.cloud.cloudservice.v1.CreateConnectivityRuleRequest\x1a\x42.temporal.api.cloud.cloudservice.v1.CreateConnectivityRuleResponse"\xdd\x01\x82\xd3\xe4\x93\x02\x1e"\x19/cloud/connectivity-rules:\x01*\x92\x41\xb5\x01\n\x12\x43onnectivity Rules\x12\x18\x43reate connectivity rule\x1a:Creates a new connectivity rule for network access control"I\n\x1a\x43onnectivity documentation\x12+https://docs.temporal.io/cloud/connectivity\x12\x94\x03\n\x13GetConnectivityRule\x12>.temporal.api.cloud.cloudservice.v1.GetConnectivityRuleRequest\x1a?.temporal.api.cloud.cloudservice.v1.GetConnectivityRuleResponse"\xfb\x01\x82\xd3\xe4\x93\x02\x32\x12\x30/cloud/connectivity-rules/{connectivity_rule_id}\x92\x41\xbf\x01\n\x12\x43onnectivity Rules\x12\x1dGet connectivity rule details\x1a?Returns detailed information about a specific connectivity rule"I\n\x1a\x43onnectivity documentation\x12+https://docs.temporal.io/cloud/connectivity\x12\xf6\x02\n\x14GetConnectivityRules\x12?.temporal.api.cloud.cloudservice.v1.GetConnectivityRulesRequest\x1a@.temporal.api.cloud.cloudservice.v1.GetConnectivityRulesResponse"\xda\x01\x82\xd3\xe4\x93\x02\x1b\x12\x19/cloud/connectivity-rules\x92\x41\xb5\x01\n\x12\x43onnectivity Rules\x12\x1bList all connectivity rules\x1a\x37Returns a list of all connectivity rules in the account"I\n\x1a\x43onnectivity documentation\x12+https://docs.temporal.io/cloud/connectivity\x12\x85\x03\n\x16\x44\x65leteConnectivityRule\x12\x41.temporal.api.cloud.cloudservice.v1.DeleteConnectivityRuleRequest\x1a\x42.temporal.api.cloud.cloudservice.v1.DeleteConnectivityRuleResponse"\xe3\x01\x82\xd3\xe4\x93\x02\x32*0/cloud/connectivity-rules/{connectivity_rule_id}\x92\x41\xa7\x01\n\x12\x43onnectivity Rules\x12\x18\x44\x65lete connectivity rule\x1a,Removes a connectivity rule from the account"I\n\x1a\x43onnectivity documentation\x12+https://docs.temporal.io/cloud/connectivity\x12\xe2\x02\n\x0cGetAuditLogs\x12\x37.temporal.api.cloud.cloudservice.v1.GetAuditLogsRequest\x1a\x38.temporal.api.cloud.cloudservice.v1.GetAuditLogsResponse"\xde\x01\x82\xd3\xe4\x93\x02\x13\x12\x11/cloud/audit-logs\x92\x41\xc1\x01\n\x07\x41\x63\x63ount\x12\x0eGet audit logs\x1aYReturns a paginated list of audit logs for the account, optionally filtered by time range"K\n\x1b\x41udit logging documentation\x12,https://docs.temporal.io/cloud/audit-logging\x12\xb4\x04\n\x1bValidateAccountAuditLogSink\x12\x46.temporal.api.cloud.cloudservice.v1.ValidateAccountAuditLogSinkRequest\x1aG.temporal.api.cloud.cloudservice.v1.ValidateAccountAuditLogSinkResponse"\x83\x03\x82\xd3\xe4\x93\x02#"\x1e/cloud/audit-log-sink-validate:\x01*\x92\x41\xd6\x02\n\x07\x41\x63\x63ount\x12\x17Validate audit log sink\x1a\xe4\x01Validate customer audit log sink is accessible from Temporal\'s workflow by delivering an empty file to the specified sink. The operation verifies that the sink is correctly configured, accessible and ready to receive audit logs."K\n\x1b\x41udit logging documentation\x12,https://docs.temporal.io/cloud/audit-logging\x12\xf4\x02\n\x19\x43reateAccountAuditLogSink\x12\x44.temporal.api.cloud.cloudservice.v1.CreateAccountAuditLogSinkRequest\x1a\x45.temporal.api.cloud.cloudservice.v1.CreateAccountAuditLogSinkResponse"\xc9\x01\x82\xd3\xe4\x93\x02\x1b"\x16/cloud/audit-log-sinks:\x01*\x92\x41\xa4\x01\n\x07\x41\x63\x63ount\x12\x15\x43reate audit log sink\x1a\x35\x43reates a new audit log sink for exporting audit logs"K\n\x1b\x41udit logging documentation\x12,https://docs.temporal.io/cloud/audit-logging\x12\xfb\x02\n\x16GetAccountAuditLogSink\x12\x41.temporal.api.cloud.cloudservice.v1.GetAccountAuditLogSinkRequest\x1a\x42.temporal.api.cloud.cloudservice.v1.GetAccountAuditLogSinkResponse"\xd9\x01\x82\xd3\xe4\x93\x02\x1f\x12\x1d/cloud/audit-log-sinks/{name}\x92\x41\xb0\x01\n\x07\x41\x63\x63ount\x12\x1aGet audit log sink details\x1a.temporal.api.cloud.cloudservice.v1.CreateBillingReportRequest\x1a?.temporal.api.cloud.cloudservice.v1.CreateBillingReportResponse"\xc1\x01\x82\xd3\xe4\x93\x02\x1b"\x16/cloud/billing-reports:\x01*\x92\x41\x9c\x01\n\x07\x42illing\x12\x17\x43reate a billing report\x1a(Creates a billing report for the account"N\n\x1c\x42illing report documentation\x12.https://docs.temporal.io/cloud/billing-reports\x12\xe6\x02\n\x10GetBillingReport\x12;.temporal.api.cloud.cloudservice.v1.GetBillingReportRequest\x1a<.temporal.api.cloud.cloudservice.v1.GetBillingReportResponse"\xd6\x01\x82\xd3\xe4\x93\x02,\x12*/cloud/billing-reports/{billing_report_id}\x92\x41\xa0\x01\n\x07\x42illing\x12\x14Get a billing report\x1a/Gets an existing billing report for the account"N\n\x1c\x42illing report documentation\x12.https://docs.temporal.io/cloud/billing-reports\x12\xc4\x02\n\x0eGetCustomRoles\x12\x39.temporal.api.cloud.cloudservice.v1.GetCustomRolesRequest\x1a:.temporal.api.cloud.cloudservice.v1.GetCustomRolesResponse"\xba\x01\x82\xd3\xe4\x93\x02\x15\x12\x13/cloud/custom-roles\x92\x41\x9b\x01\n\x0c\x43ustom Roles\x12\x11List custom roles\x1a-Returns a list of custom roles in the account"I\n\x1a\x43ustom roles documentation\x12+https://docs.temporal.io/cloud/custom-roles\x12\xcc\x02\n\rGetCustomRole\x12\x38.temporal.api.cloud.cloudservice.v1.GetCustomRoleRequest\x1a\x39.temporal.api.cloud.cloudservice.v1.GetCustomRoleResponse"\xc5\x01\x82\xd3\xe4\x93\x02\x1f\x12\x1d/cloud/custom-roles/{role_id}\x92\x41\x9c\x01\n\x0c\x43ustom Roles\x12\x15Get custom role by ID\x1a*Returns details for a specific custom role"I\n\x1a\x43ustom roles documentation\x12+https://docs.temporal.io/cloud/custom-roles\x12\xcb\x02\n\x10\x43reateCustomRole\x12;.temporal.api.cloud.cloudservice.v1.CreateCustomRoleRequest\x1a<.temporal.api.cloud.cloudservice.v1.CreateCustomRoleResponse"\xbb\x01\x82\xd3\xe4\x93\x02\x18"\x13/cloud/custom-roles:\x01*\x92\x41\x99\x01\n\x0c\x43ustom Roles\x12\x14\x43reate a custom role\x1a(Creates a new custom role in the account"I\n\x1a\x43ustom roles documentation\x12+https://docs.temporal.io/cloud/custom-roles\x12\xcc\x02\n\x10UpdateCustomRole\x12;.temporal.api.cloud.cloudservice.v1.UpdateCustomRoleRequest\x1a<.temporal.api.cloud.cloudservice.v1.UpdateCustomRoleResponse"\xbc\x01\x82\xd3\xe4\x93\x02""\x1d/cloud/custom-roles/{role_id}:\x01*\x92\x41\x90\x01\n\x0c\x43ustom Roles\x12\x14Update a custom role\x1a\x1fUpdates an existing custom role"I\n\x1a\x43ustom roles documentation\x12+https://docs.temporal.io/cloud/custom-roles\x12\xd0\x02\n\x10\x44\x65leteCustomRole\x12;.temporal.api.cloud.cloudservice.v1.DeleteCustomRoleRequest\x1a<.temporal.api.cloud.cloudservice.v1.DeleteCustomRoleResponse"\xc0\x01\x82\xd3\xe4\x93\x02\x1f*\x1d/cloud/custom-roles/{role_id}\x92\x41\x97\x01\n\x0c\x43ustom Roles\x12\x14\x44\x65lete a custom role\x1a&Deletes a custom role from the account"I\n\x1a\x43ustom roles documentation\x12+https://docs.temporal.io/cloud/custom-roles\x12\xb9\x03\n\x1bGetUserNamespaceAssignments\x12\x46.temporal.api.cloud.cloudservice.v1.GetUserNamespaceAssignmentsRequest\x1aG.temporal.api.cloud.cloudservice.v1.GetUserNamespaceAssignmentsResponse"\x88\x02\x82\xd3\xe4\x93\x02\x30\x12./cloud/namespaces/{namespace}/user-assignments\x92\x41\xce\x01\n\x05Users\x12$Get users with access to a namespace\x1a\x62Returns the users that have access to the namespace, including each user\'s namespace-level access.";\n\x13Users documentation\x12$https://docs.temporal.io/cloud/users\x12\xa5\x04\n%GetServiceAccountNamespaceAssignments\x12P.temporal.api.cloud.cloudservice.v1.GetServiceAccountNamespaceAssignmentsRequest\x1aQ.temporal.api.cloud.cloudservice.v1.GetServiceAccountNamespaceAssignmentsResponse"\xd6\x02\x82\xd3\xe4\x93\x02;\x12\x39/cloud/namespaces/{namespace}/service-account-assignments\x92\x41\x91\x02\n\x10Service Accounts\x12\x30List service accounts with access to a namespace\x1axReturns the service accounts that have access to the namespace, including each service account\'s namespace-level access."Q\n\x1eService Accounts documentation\x12/https://docs.temporal.io/cloud/service-accounts\x12\xe9\x03\n GetUserGroupNamespaceAssignments\x12K.temporal.api.cloud.cloudservice.v1.GetUserGroupNamespaceAssignmentsRequest\x1aL.temporal.api.cloud.cloudservice.v1.GetUserGroupNamespaceAssignmentsResponse"\xa9\x02\x82\xd3\xe4\x93\x02\x36\x12\x34/cloud/namespaces/{namespace}/user-group-assignments\x92\x41\xe9\x01\n\x06Groups\x12+List user groups with access to a namespace\x1aiReturns the user groups that have access to the namespace, including each group\'s namespace-level access."G\n\x19User groups documentation\x12*https://docs.temporal.io/cloud/user-groupsB\xc1\x15\n%io.temporal.api.cloud.cloudservice.v1B\x0cServiceProtoP\x01Z5go.temporal.io/api/cloud/cloudservice/v1;cloudservice\xaa\x02$Temporalio.Api.Cloud.CloudService.V1\xea\x02(Temporalio::Api::Cloud::CloudService::V1\x92\x41\xfd\x13\x12\xe0\r\n\x16Temporal Cloud Ops API\x12\x96\x0cProgrammatic access to manage Temporal Cloud control plane resources including namespaces, users, service accounts, and more.\n\n## Authentication\n\nAll API requests require authentication using an API Key. Include your API key in the `Authorization` header using the Bearer scheme:\n\n```\nAuthorization: Bearer YOUR_API_KEY\n```\n\nAPI keys can be created and managed through the [API Keys endpoints](#tag/API-Keys) or via the Temporal Cloud UI. For more information, see [API Keys Documentation](https://docs.temporal.io/cloud/api-keys).\n\n## Authorization\n\nThe API uses Role-Based Access Control (RBAC) to manage permissions. Each operation requires specific role-based permissions in addition to a valid API key.\n\n### Account-Level Roles\n\n- **Account Owner** - Full account administration access\n- **Account Admin** - Manage namespaces, users, and service accounts \n- **Account Developer** - Create namespaces and manage Nexus endpoints\n- **Finance Admin** - View usage and billing information\n- **Account Read** - Read-only access to account resources\n\n### Namespace-Level Roles\n\n- **Namespace Admin** - Full access to namespace configuration and data\n- **Namespace Write** - Execute workflows and modify workflow data\n- **Namespace Read** - Read-only access to namespace data\n\nNamespace-level permissions are scoped to specific namespaces. A user or service account may have different permission levels across different namespaces.\n\nFor detailed information about roles and permissions, see [Access Control Documentation](https://docs.temporal.io/cloud/users).2\x03\x31.0:\xa7\x01\n\x06x-logo\x12\x9c\x01*\x99\x01\n\x96\x01\n\x03url\x12\x8e\x01\x1a\x8b\x01https://images.ctfassets.net/0uuz8ydxyd9p/4YGUnEoCaH9SyoUDhlJkau/e1600205d17eeee3033d926ef06664a9/Temporal_LogoLockup_Horizontal_dark_1.svgj.\n\nNamespaces\x12 Manage Temporal Cloud namespacesj0\n\x05Users\x12\'Manage users and their namespace accessjF\n\x10Service Accounts\x12\x32Manage service accounts and their namespace accessj.\n\x08\x41PI Keys\x12"Manage API keys for authenticationj1\n\x06Groups\x12\'Manage user groups and group membershipj\x1f\n\x05Nexus\x12\x16Manage Nexus endpointsj\x7f\n\x11High Availability\x12jManage high availability (multi-region, multi-cloud, and same-region replication) namespace configurationsj7\n\x06\x45xport\x12-Manage workflow history export configurationsj7\n\x12\x43onnectivity Rules\x12!Manage network connectivity rulesj"\n\x07Regions\x12\x17Query available regionsj,\n\x07\x41\x63\x63ount\x12!Manage account settings and usagej9\n\x0c\x43ustom Roles\x12)Manage custom roles and their permissionsj*\n\nOperations\x12\x1cQuery async operation statusr>\n\x1cTemporal Cloud Documentation\x12\x1ehttps://docs.temporal.io/cloudb\x06proto3' ) @@ -299,11 +299,11 @@ _CLOUDSERVICE.methods_by_name["CreateBillingReport"]._options = None _CLOUDSERVICE.methods_by_name[ "CreateBillingReport" - ]._serialized_options = b'\202\323\344\223\002\033"\026/cloud/billing-reports:\001*\222A\234\001\n\007Account\022\027Create a billing report\032(Creates a billing report for the account"N\n\034Billing report documentation\022.https://docs.temporal.io/cloud/billing-reports' + ]._serialized_options = b'\202\323\344\223\002\033"\026/cloud/billing-reports:\001*\222A\234\001\n\007Billing\022\027Create a billing report\032(Creates a billing report for the account"N\n\034Billing report documentation\022.https://docs.temporal.io/cloud/billing-reports' _CLOUDSERVICE.methods_by_name["GetBillingReport"]._options = None _CLOUDSERVICE.methods_by_name[ "GetBillingReport" - ]._serialized_options = b'\202\323\344\223\002,\022*/cloud/billing-reports/{billing_report_id}\222A\240\001\n\007Account\022\024Get a billing report\032/Gets an existing billing report for the account"N\n\034Billing report documentation\022.https://docs.temporal.io/cloud/billing-reports' + ]._serialized_options = b'\202\323\344\223\002,\022*/cloud/billing-reports/{billing_report_id}\222A\240\001\n\007Billing\022\024Get a billing report\032/Gets an existing billing report for the account"N\n\034Billing report documentation\022.https://docs.temporal.io/cloud/billing-reports' _CLOUDSERVICE.methods_by_name["GetCustomRoles"]._options = None _CLOUDSERVICE.methods_by_name[ "GetCustomRoles" @@ -324,6 +324,20 @@ _CLOUDSERVICE.methods_by_name[ "DeleteCustomRole" ]._serialized_options = b'\202\323\344\223\002\037*\035/cloud/custom-roles/{role_id}\222A\227\001\n\014Custom Roles\022\024Delete a custom role\032&Deletes a custom role from the account"I\n\032Custom roles documentation\022+https://docs.temporal.io/cloud/custom-roles' + _CLOUDSERVICE.methods_by_name["GetUserNamespaceAssignments"]._options = None + _CLOUDSERVICE.methods_by_name[ + "GetUserNamespaceAssignments" + ]._serialized_options = b"\202\323\344\223\0020\022./cloud/namespaces/{namespace}/user-assignments\222A\316\001\n\005Users\022$Get users with access to a namespace\032bReturns the users that have access to the namespace, including each user's namespace-level access.\";\n\023Users documentation\022$https://docs.temporal.io/cloud/users" + _CLOUDSERVICE.methods_by_name[ + "GetServiceAccountNamespaceAssignments" + ]._options = None + _CLOUDSERVICE.methods_by_name[ + "GetServiceAccountNamespaceAssignments" + ]._serialized_options = b"\202\323\344\223\002;\0229/cloud/namespaces/{namespace}/service-account-assignments\222A\221\002\n\020Service Accounts\0220List service accounts with access to a namespace\032xReturns the service accounts that have access to the namespace, including each service account's namespace-level access.\"Q\n\036Service Accounts documentation\022/https://docs.temporal.io/cloud/service-accounts" + _CLOUDSERVICE.methods_by_name["GetUserGroupNamespaceAssignments"]._options = None + _CLOUDSERVICE.methods_by_name[ + "GetUserGroupNamespaceAssignments" + ]._serialized_options = b"\202\323\344\223\0026\0224/cloud/namespaces/{namespace}/user-group-assignments\222A\351\001\n\006Groups\022+List user groups with access to a namespace\032iReturns the user groups that have access to the namespace, including each group's namespace-level access.\"G\n\031User groups documentation\022*https://docs.temporal.io/cloud/user-groups" _CLOUDSERVICE._serialized_start = 227 - _CLOUDSERVICE._serialized_end = 26277 + _CLOUDSERVICE._serialized_end = 27765 # @@protoc_insertion_point(module_scope) diff --git a/temporalio/api/cloud/cloudservice/v1/service_pb2_grpc.py b/temporalio/api/cloud/cloudservice/v1/service_pb2_grpc.py index 4888d7186..6366673ca 100644 --- a/temporalio/api/cloud/cloudservice/v1/service_pb2_grpc.py +++ b/temporalio/api/cloud/cloudservice/v1/service_pb2_grpc.py @@ -384,6 +384,21 @@ def __init__(self, channel): request_serializer=temporal_dot_api_dot_cloud_dot_cloudservice_dot_v1_dot_request__response__pb2.DeleteCustomRoleRequest.SerializeToString, response_deserializer=temporal_dot_api_dot_cloud_dot_cloudservice_dot_v1_dot_request__response__pb2.DeleteCustomRoleResponse.FromString, ) + self.GetUserNamespaceAssignments = channel.unary_unary( + "/temporal.api.cloud.cloudservice.v1.CloudService/GetUserNamespaceAssignments", + request_serializer=temporal_dot_api_dot_cloud_dot_cloudservice_dot_v1_dot_request__response__pb2.GetUserNamespaceAssignmentsRequest.SerializeToString, + response_deserializer=temporal_dot_api_dot_cloud_dot_cloudservice_dot_v1_dot_request__response__pb2.GetUserNamespaceAssignmentsResponse.FromString, + ) + self.GetServiceAccountNamespaceAssignments = channel.unary_unary( + "/temporal.api.cloud.cloudservice.v1.CloudService/GetServiceAccountNamespaceAssignments", + request_serializer=temporal_dot_api_dot_cloud_dot_cloudservice_dot_v1_dot_request__response__pb2.GetServiceAccountNamespaceAssignmentsRequest.SerializeToString, + response_deserializer=temporal_dot_api_dot_cloud_dot_cloudservice_dot_v1_dot_request__response__pb2.GetServiceAccountNamespaceAssignmentsResponse.FromString, + ) + self.GetUserGroupNamespaceAssignments = channel.unary_unary( + "/temporal.api.cloud.cloudservice.v1.CloudService/GetUserGroupNamespaceAssignments", + request_serializer=temporal_dot_api_dot_cloud_dot_cloudservice_dot_v1_dot_request__response__pb2.GetUserGroupNamespaceAssignmentsRequest.SerializeToString, + response_deserializer=temporal_dot_api_dot_cloud_dot_cloudservice_dot_v1_dot_request__response__pb2.GetUserGroupNamespaceAssignmentsResponse.FromString, + ) class CloudServiceServicer(object): @@ -839,6 +854,24 @@ def DeleteCustomRole(self, request, context): context.set_details("Method not implemented!") raise NotImplementedError("Method not implemented!") + def GetUserNamespaceAssignments(self, request, context): + """Get users with access to a namespace""" + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details("Method not implemented!") + raise NotImplementedError("Method not implemented!") + + def GetServiceAccountNamespaceAssignments(self, request, context): + """Get service accounts with access to a namespace""" + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details("Method not implemented!") + raise NotImplementedError("Method not implemented!") + + def GetUserGroupNamespaceAssignments(self, request, context): + """Get user groups with access to a namespace""" + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details("Method not implemented!") + raise NotImplementedError("Method not implemented!") + def add_CloudServiceServicer_to_server(servicer, server): rpc_method_handlers = { @@ -1207,6 +1240,21 @@ def add_CloudServiceServicer_to_server(servicer, server): request_deserializer=temporal_dot_api_dot_cloud_dot_cloudservice_dot_v1_dot_request__response__pb2.DeleteCustomRoleRequest.FromString, response_serializer=temporal_dot_api_dot_cloud_dot_cloudservice_dot_v1_dot_request__response__pb2.DeleteCustomRoleResponse.SerializeToString, ), + "GetUserNamespaceAssignments": grpc.unary_unary_rpc_method_handler( + servicer.GetUserNamespaceAssignments, + request_deserializer=temporal_dot_api_dot_cloud_dot_cloudservice_dot_v1_dot_request__response__pb2.GetUserNamespaceAssignmentsRequest.FromString, + response_serializer=temporal_dot_api_dot_cloud_dot_cloudservice_dot_v1_dot_request__response__pb2.GetUserNamespaceAssignmentsResponse.SerializeToString, + ), + "GetServiceAccountNamespaceAssignments": grpc.unary_unary_rpc_method_handler( + servicer.GetServiceAccountNamespaceAssignments, + request_deserializer=temporal_dot_api_dot_cloud_dot_cloudservice_dot_v1_dot_request__response__pb2.GetServiceAccountNamespaceAssignmentsRequest.FromString, + response_serializer=temporal_dot_api_dot_cloud_dot_cloudservice_dot_v1_dot_request__response__pb2.GetServiceAccountNamespaceAssignmentsResponse.SerializeToString, + ), + "GetUserGroupNamespaceAssignments": grpc.unary_unary_rpc_method_handler( + servicer.GetUserGroupNamespaceAssignments, + request_deserializer=temporal_dot_api_dot_cloud_dot_cloudservice_dot_v1_dot_request__response__pb2.GetUserGroupNamespaceAssignmentsRequest.FromString, + response_serializer=temporal_dot_api_dot_cloud_dot_cloudservice_dot_v1_dot_request__response__pb2.GetUserGroupNamespaceAssignmentsResponse.SerializeToString, + ), } generic_handler = grpc.method_handlers_generic_handler( "temporal.api.cloud.cloudservice.v1.CloudService", rpc_method_handlers @@ -3336,3 +3384,90 @@ def DeleteCustomRole( timeout, metadata, ) + + @staticmethod + def GetUserNamespaceAssignments( + request, + target, + options=(), + channel_credentials=None, + call_credentials=None, + insecure=False, + compression=None, + wait_for_ready=None, + timeout=None, + metadata=None, + ): + return grpc.experimental.unary_unary( + request, + target, + "/temporal.api.cloud.cloudservice.v1.CloudService/GetUserNamespaceAssignments", + temporal_dot_api_dot_cloud_dot_cloudservice_dot_v1_dot_request__response__pb2.GetUserNamespaceAssignmentsRequest.SerializeToString, + temporal_dot_api_dot_cloud_dot_cloudservice_dot_v1_dot_request__response__pb2.GetUserNamespaceAssignmentsResponse.FromString, + options, + channel_credentials, + insecure, + call_credentials, + compression, + wait_for_ready, + timeout, + metadata, + ) + + @staticmethod + def GetServiceAccountNamespaceAssignments( + request, + target, + options=(), + channel_credentials=None, + call_credentials=None, + insecure=False, + compression=None, + wait_for_ready=None, + timeout=None, + metadata=None, + ): + return grpc.experimental.unary_unary( + request, + target, + "/temporal.api.cloud.cloudservice.v1.CloudService/GetServiceAccountNamespaceAssignments", + temporal_dot_api_dot_cloud_dot_cloudservice_dot_v1_dot_request__response__pb2.GetServiceAccountNamespaceAssignmentsRequest.SerializeToString, + temporal_dot_api_dot_cloud_dot_cloudservice_dot_v1_dot_request__response__pb2.GetServiceAccountNamespaceAssignmentsResponse.FromString, + options, + channel_credentials, + insecure, + call_credentials, + compression, + wait_for_ready, + timeout, + metadata, + ) + + @staticmethod + def GetUserGroupNamespaceAssignments( + request, + target, + options=(), + channel_credentials=None, + call_credentials=None, + insecure=False, + compression=None, + wait_for_ready=None, + timeout=None, + metadata=None, + ): + return grpc.experimental.unary_unary( + request, + target, + "/temporal.api.cloud.cloudservice.v1.CloudService/GetUserGroupNamespaceAssignments", + temporal_dot_api_dot_cloud_dot_cloudservice_dot_v1_dot_request__response__pb2.GetUserGroupNamespaceAssignmentsRequest.SerializeToString, + temporal_dot_api_dot_cloud_dot_cloudservice_dot_v1_dot_request__response__pb2.GetUserGroupNamespaceAssignmentsResponse.FromString, + options, + channel_credentials, + insecure, + call_credentials, + compression, + wait_for_ready, + timeout, + metadata, + ) diff --git a/temporalio/api/cloud/cloudservice/v1/service_pb2_grpc.pyi b/temporalio/api/cloud/cloudservice/v1/service_pb2_grpc.pyi index 0d8e642f4..a56b33db4 100644 --- a/temporalio/api/cloud/cloudservice/v1/service_pb2_grpc.pyi +++ b/temporalio/api/cloud/cloudservice/v1/service_pb2_grpc.pyi @@ -389,6 +389,21 @@ class CloudServiceStub: temporalio.api.cloud.cloudservice.v1.request_response_pb2.DeleteCustomRoleResponse, ] """Delete a custom role""" + GetUserNamespaceAssignments: grpc.UnaryUnaryMultiCallable[ + temporalio.api.cloud.cloudservice.v1.request_response_pb2.GetUserNamespaceAssignmentsRequest, + temporalio.api.cloud.cloudservice.v1.request_response_pb2.GetUserNamespaceAssignmentsResponse, + ] + """Get users with access to a namespace""" + GetServiceAccountNamespaceAssignments: grpc.UnaryUnaryMultiCallable[ + temporalio.api.cloud.cloudservice.v1.request_response_pb2.GetServiceAccountNamespaceAssignmentsRequest, + temporalio.api.cloud.cloudservice.v1.request_response_pb2.GetServiceAccountNamespaceAssignmentsResponse, + ] + """Get service accounts with access to a namespace""" + GetUserGroupNamespaceAssignments: grpc.UnaryUnaryMultiCallable[ + temporalio.api.cloud.cloudservice.v1.request_response_pb2.GetUserGroupNamespaceAssignmentsRequest, + temporalio.api.cloud.cloudservice.v1.request_response_pb2.GetUserGroupNamespaceAssignmentsResponse, + ] + """Get user groups with access to a namespace""" class CloudServiceServicer(metaclass=abc.ABCMeta): """WARNING: This service is currently experimental and may change in @@ -925,6 +940,27 @@ class CloudServiceServicer(metaclass=abc.ABCMeta): context: grpc.ServicerContext, ) -> temporalio.api.cloud.cloudservice.v1.request_response_pb2.DeleteCustomRoleResponse: """Delete a custom role""" + @abc.abstractmethod + def GetUserNamespaceAssignments( + self, + request: temporalio.api.cloud.cloudservice.v1.request_response_pb2.GetUserNamespaceAssignmentsRequest, + context: grpc.ServicerContext, + ) -> temporalio.api.cloud.cloudservice.v1.request_response_pb2.GetUserNamespaceAssignmentsResponse: + """Get users with access to a namespace""" + @abc.abstractmethod + def GetServiceAccountNamespaceAssignments( + self, + request: temporalio.api.cloud.cloudservice.v1.request_response_pb2.GetServiceAccountNamespaceAssignmentsRequest, + context: grpc.ServicerContext, + ) -> temporalio.api.cloud.cloudservice.v1.request_response_pb2.GetServiceAccountNamespaceAssignmentsResponse: + """Get service accounts with access to a namespace""" + @abc.abstractmethod + def GetUserGroupNamespaceAssignments( + self, + request: temporalio.api.cloud.cloudservice.v1.request_response_pb2.GetUserGroupNamespaceAssignmentsRequest, + context: grpc.ServicerContext, + ) -> temporalio.api.cloud.cloudservice.v1.request_response_pb2.GetUserGroupNamespaceAssignmentsResponse: + """Get user groups with access to a namespace""" def add_CloudServiceServicer_to_server( servicer: CloudServiceServicer, server: grpc.Server diff --git a/temporalio/api/cloud/identity/v1/__init__.py b/temporalio/api/cloud/identity/v1/__init__.py index 38954f384..48e9ad21d 100644 --- a/temporalio/api/cloud/identity/v1/__init__.py +++ b/temporalio/api/cloud/identity/v1/__init__.py @@ -13,12 +13,15 @@ OwnerType, SCIMGroupSpec, ServiceAccount, + ServiceAccountNamespaceAssignment, ServiceAccountSpec, User, UserGroup, UserGroupMember, UserGroupMemberId, + UserGroupNamespaceAssignment, UserGroupSpec, + UserNamespaceAssignment, UserSpec, ) @@ -37,11 +40,14 @@ "OwnerType", "SCIMGroupSpec", "ServiceAccount", + "ServiceAccountNamespaceAssignment", "ServiceAccountSpec", "User", "UserGroup", "UserGroupMember", "UserGroupMemberId", + "UserGroupNamespaceAssignment", "UserGroupSpec", + "UserNamespaceAssignment", "UserSpec", ] diff --git a/temporalio/api/cloud/identity/v1/message_pb2.py b/temporalio/api/cloud/identity/v1/message_pb2.py index b7036cd3f..439a22202 100644 --- a/temporalio/api/cloud/identity/v1/message_pb2.py +++ b/temporalio/api/cloud/identity/v1/message_pb2.py @@ -22,7 +22,7 @@ ) DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile( - b'\n,temporal/api/cloud/identity/v1/message.proto\x12\x1etemporal.api.cloud.identity.v1\x1a,temporal/api/cloud/resource/v1/message.proto\x1a\x1fgoogle/protobuf/timestamp.proto"\x95\x02\n\rAccountAccess\x12\x1b\n\x0frole_deprecated\x18\x01 \x01(\tB\x02\x18\x01\x12@\n\x04role\x18\x02 \x01(\x0e\x32\x32.temporal.api.cloud.identity.v1.AccountAccess.Role\x12\x14\n\x0c\x63ustom_roles\x18\x03 \x03(\t"\x8e\x01\n\x04Role\x12\x14\n\x10ROLE_UNSPECIFIED\x10\x00\x12\x0e\n\nROLE_OWNER\x10\x01\x12\x0e\n\nROLE_ADMIN\x10\x02\x12\x12\n\x0eROLE_DEVELOPER\x10\x03\x12\x16\n\x12ROLE_FINANCE_ADMIN\x10\x04\x12\r\n\tROLE_READ\x10\x05\x12\x15\n\x11ROLE_METRICS_READ\x10\x06"\xef\x01\n\x0fNamespaceAccess\x12!\n\x15permission_deprecated\x18\x01 \x01(\tB\x02\x18\x01\x12N\n\npermission\x18\x02 \x01(\x0e\x32:.temporal.api.cloud.identity.v1.NamespaceAccess.Permission"i\n\nPermission\x12\x1a\n\x16PERMISSION_UNSPECIFIED\x10\x00\x12\x14\n\x10PERMISSION_ADMIN\x10\x01\x12\x14\n\x10PERMISSION_WRITE\x10\x02\x12\x13\n\x0fPERMISSION_READ\x10\x03"\xba\x02\n\x06\x41\x63\x63\x65ss\x12\x45\n\x0e\x61\x63\x63ount_access\x18\x01 \x01(\x0b\x32-.temporal.api.cloud.identity.v1.AccountAccess\x12Y\n\x12namespace_accesses\x18\x02 \x03(\x0b\x32=.temporal.api.cloud.identity.v1.Access.NamespaceAccessesEntry\x12#\n\x17\x63ustom_roles_deprecated\x18\x04 \x03(\tB\x02\x18\x01\x1ai\n\x16NamespaceAccessesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12>\n\x05value\x18\x02 \x01(\x0b\x32/.temporal.api.cloud.identity.v1.NamespaceAccess:\x02\x38\x01"k\n\x15NamespaceScopedAccess\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12?\n\x06\x61\x63\x63\x65ss\x18\x02 \x01(\x0b\x32/.temporal.api.cloud.identity.v1.NamespaceAccess"Q\n\x08UserSpec\x12\r\n\x05\x65mail\x18\x01 \x01(\t\x12\x36\n\x06\x61\x63\x63\x65ss\x18\x02 \x01(\x0b\x32&.temporal.api.cloud.identity.v1.Access"p\n\nInvitation\x12\x30\n\x0c\x63reated_time\x18\x01 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x30\n\x0c\x65xpired_time\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.Timestamp"\x86\x03\n\x04User\x12\n\n\x02id\x18\x01 \x01(\t\x12\x18\n\x10resource_version\x18\x02 \x01(\t\x12\x36\n\x04spec\x18\x03 \x01(\x0b\x32(.temporal.api.cloud.identity.v1.UserSpec\x12\x1c\n\x10state_deprecated\x18\x04 \x01(\tB\x02\x18\x01\x12<\n\x05state\x18\t \x01(\x0e\x32-.temporal.api.cloud.resource.v1.ResourceState\x12\x1a\n\x12\x61sync_operation_id\x18\x05 \x01(\t\x12>\n\ninvitation\x18\x06 \x01(\x0b\x32*.temporal.api.cloud.identity.v1.Invitation\x12\x30\n\x0c\x63reated_time\x18\x07 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x36\n\x12last_modified_time\x18\x08 \x01(\x0b\x32\x1a.google.protobuf.Timestamp"(\n\x0fGoogleGroupSpec\x12\x15\n\remail_address\x18\x01 \x01(\t"\x1f\n\rSCIMGroupSpec\x12\x0e\n\x06idp_id\x18\x01 \x01(\t"\x10\n\x0e\x43loudGroupSpec"\xc0\x02\n\rUserGroupSpec\x12\x14\n\x0c\x64isplay_name\x18\x01 \x01(\t\x12\x36\n\x06\x61\x63\x63\x65ss\x18\x02 \x01(\x0b\x32&.temporal.api.cloud.identity.v1.Access\x12G\n\x0cgoogle_group\x18\x03 \x01(\x0b\x32/.temporal.api.cloud.identity.v1.GoogleGroupSpecH\x00\x12\x43\n\nscim_group\x18\x04 \x01(\x0b\x32-.temporal.api.cloud.identity.v1.SCIMGroupSpecH\x00\x12\x45\n\x0b\x63loud_group\x18\x05 \x01(\x0b\x32..temporal.api.cloud.identity.v1.CloudGroupSpecH\x00\x42\x0c\n\ngroup_type"\xd0\x02\n\tUserGroup\x12\n\n\x02id\x18\x01 \x01(\t\x12\x18\n\x10resource_version\x18\x02 \x01(\t\x12;\n\x04spec\x18\x03 \x01(\x0b\x32-.temporal.api.cloud.identity.v1.UserGroupSpec\x12\x1c\n\x10state_deprecated\x18\x04 \x01(\tB\x02\x18\x01\x12<\n\x05state\x18\x08 \x01(\x0e\x32-.temporal.api.cloud.resource.v1.ResourceState\x12\x1a\n\x12\x61sync_operation_id\x18\x05 \x01(\t\x12\x30\n\x0c\x63reated_time\x18\x06 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x36\n\x12last_modified_time\x18\x07 \x01(\x0b\x32\x1a.google.protobuf.Timestamp"5\n\x11UserGroupMemberId\x12\x11\n\x07user_id\x18\x01 \x01(\tH\x00\x42\r\n\x0bmember_type"\x89\x01\n\x0fUserGroupMember\x12\x44\n\tmember_id\x18\x01 \x01(\x0b\x32\x31.temporal.api.cloud.identity.v1.UserGroupMemberId\x12\x30\n\x0c\x63reated_time\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.Timestamp"\xda\x02\n\x0eServiceAccount\x12\n\n\x02id\x18\x01 \x01(\t\x12\x18\n\x10resource_version\x18\x02 \x01(\t\x12@\n\x04spec\x18\x03 \x01(\x0b\x32\x32.temporal.api.cloud.identity.v1.ServiceAccountSpec\x12\x1c\n\x10state_deprecated\x18\x04 \x01(\tB\x02\x18\x01\x12<\n\x05state\x18\x08 \x01(\x0e\x32-.temporal.api.cloud.resource.v1.ResourceState\x12\x1a\n\x12\x61sync_operation_id\x18\x05 \x01(\t\x12\x30\n\x0c\x63reated_time\x18\x06 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x36\n\x12last_modified_time\x18\x07 \x01(\x0b\x32\x1a.google.protobuf.Timestamp"\xc7\x01\n\x12ServiceAccountSpec\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x36\n\x06\x61\x63\x63\x65ss\x18\x02 \x01(\x0b\x32&.temporal.api.cloud.identity.v1.Access\x12V\n\x17namespace_scoped_access\x18\x04 \x01(\x0b\x32\x35.temporal.api.cloud.identity.v1.NamespaceScopedAccess\x12\x13\n\x0b\x64\x65scription\x18\x03 \x01(\t"\xca\x02\n\x06\x41piKey\x12\n\n\x02id\x18\x01 \x01(\t\x12\x18\n\x10resource_version\x18\x02 \x01(\t\x12\x38\n\x04spec\x18\x03 \x01(\x0b\x32*.temporal.api.cloud.identity.v1.ApiKeySpec\x12\x1c\n\x10state_deprecated\x18\x04 \x01(\tB\x02\x18\x01\x12<\n\x05state\x18\x08 \x01(\x0e\x32-.temporal.api.cloud.resource.v1.ResourceState\x12\x1a\n\x12\x61sync_operation_id\x18\x05 \x01(\t\x12\x30\n\x0c\x63reated_time\x18\x06 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x36\n\x12last_modified_time\x18\x07 \x01(\x0b\x32\x1a.google.protobuf.Timestamp"\xee\x01\n\nApiKeySpec\x12\x10\n\x08owner_id\x18\x01 \x01(\t\x12!\n\x15owner_type_deprecated\x18\x02 \x01(\tB\x02\x18\x01\x12=\n\nowner_type\x18\x07 \x01(\x0e\x32).temporal.api.cloud.identity.v1.OwnerType\x12\x14\n\x0c\x64isplay_name\x18\x03 \x01(\t\x12\x13\n\x0b\x64\x65scription\x18\x04 \x01(\t\x12/\n\x0b\x65xpiry_time\x18\x05 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x10\n\x08\x64isabled\x18\x06 \x01(\x08"\xbc\x02\n\x0e\x43ustomRoleSpec\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x13\n\x0b\x64\x65scription\x18\x02 \x01(\t\x12N\n\x0bpermissions\x18\x03 \x03(\x0b\x32\x39.temporal.api.cloud.identity.v1.CustomRoleSpec.Permission\x1aK\n\tResources\x12\x15\n\rresource_type\x18\x01 \x01(\t\x12\x14\n\x0cresource_ids\x18\x02 \x03(\t\x12\x11\n\tallow_all\x18\x03 \x01(\x08\x1aj\n\nPermission\x12K\n\tresources\x18\x01 \x01(\x0b\x32\x38.temporal.api.cloud.identity.v1.CustomRoleSpec.Resources\x12\x0f\n\x07\x61\x63tions\x18\x02 \x03(\t"\xb4\x02\n\nCustomRole\x12\n\n\x02id\x18\x01 \x01(\t\x12\x18\n\x10resource_version\x18\x02 \x01(\t\x12<\n\x04spec\x18\x03 \x01(\x0b\x32..temporal.api.cloud.identity.v1.CustomRoleSpec\x12<\n\x05state\x18\x04 \x01(\x0e\x32-.temporal.api.cloud.resource.v1.ResourceState\x12\x1a\n\x12\x61sync_operation_id\x18\x05 \x01(\t\x12\x30\n\x0c\x63reated_time\x18\x06 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x36\n\x12last_modified_time\x18\x07 \x01(\x0b\x32\x1a.google.protobuf.Timestamp*\\\n\tOwnerType\x12\x1a\n\x16OWNER_TYPE_UNSPECIFIED\x10\x00\x12\x13\n\x0fOWNER_TYPE_USER\x10\x01\x12\x1e\n\x1aOWNER_TYPE_SERVICE_ACCOUNT\x10\x02\x42\xac\x01\n!io.temporal.api.cloud.identity.v1B\x0cMessageProtoP\x01Z-go.temporal.io/api/cloud/identity/v1;identity\xaa\x02 Temporalio.Api.Cloud.Identity.V1\xea\x02$Temporalio::Api::Cloud::Identity::V1b\x06proto3' + b'\n,temporal/api/cloud/identity/v1/message.proto\x12\x1etemporal.api.cloud.identity.v1\x1a,temporal/api/cloud/resource/v1/message.proto\x1a\x1fgoogle/protobuf/timestamp.proto"\x95\x02\n\rAccountAccess\x12\x1b\n\x0frole_deprecated\x18\x01 \x01(\tB\x02\x18\x01\x12@\n\x04role\x18\x02 \x01(\x0e\x32\x32.temporal.api.cloud.identity.v1.AccountAccess.Role\x12\x14\n\x0c\x63ustom_roles\x18\x03 \x03(\t"\x8e\x01\n\x04Role\x12\x14\n\x10ROLE_UNSPECIFIED\x10\x00\x12\x0e\n\nROLE_OWNER\x10\x01\x12\x0e\n\nROLE_ADMIN\x10\x02\x12\x12\n\x0eROLE_DEVELOPER\x10\x03\x12\x16\n\x12ROLE_FINANCE_ADMIN\x10\x04\x12\r\n\tROLE_READ\x10\x05\x12\x15\n\x11ROLE_METRICS_READ\x10\x06"\xef\x01\n\x0fNamespaceAccess\x12!\n\x15permission_deprecated\x18\x01 \x01(\tB\x02\x18\x01\x12N\n\npermission\x18\x02 \x01(\x0e\x32:.temporal.api.cloud.identity.v1.NamespaceAccess.Permission"i\n\nPermission\x12\x1a\n\x16PERMISSION_UNSPECIFIED\x10\x00\x12\x14\n\x10PERMISSION_ADMIN\x10\x01\x12\x14\n\x10PERMISSION_WRITE\x10\x02\x12\x13\n\x0fPERMISSION_READ\x10\x03"\xba\x02\n\x06\x41\x63\x63\x65ss\x12\x45\n\x0e\x61\x63\x63ount_access\x18\x01 \x01(\x0b\x32-.temporal.api.cloud.identity.v1.AccountAccess\x12Y\n\x12namespace_accesses\x18\x02 \x03(\x0b\x32=.temporal.api.cloud.identity.v1.Access.NamespaceAccessesEntry\x12#\n\x17\x63ustom_roles_deprecated\x18\x04 \x03(\tB\x02\x18\x01\x1ai\n\x16NamespaceAccessesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12>\n\x05value\x18\x02 \x01(\x0b\x32/.temporal.api.cloud.identity.v1.NamespaceAccess:\x02\x38\x01"k\n\x15NamespaceScopedAccess\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12?\n\x06\x61\x63\x63\x65ss\x18\x02 \x01(\x0b\x32/.temporal.api.cloud.identity.v1.NamespaceAccess"Q\n\x08UserSpec\x12\r\n\x05\x65mail\x18\x01 \x01(\t\x12\x36\n\x06\x61\x63\x63\x65ss\x18\x02 \x01(\x0b\x32&.temporal.api.cloud.identity.v1.Access"p\n\nInvitation\x12\x30\n\x0c\x63reated_time\x18\x01 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x30\n\x0c\x65xpired_time\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.Timestamp"\x86\x03\n\x04User\x12\n\n\x02id\x18\x01 \x01(\t\x12\x18\n\x10resource_version\x18\x02 \x01(\t\x12\x36\n\x04spec\x18\x03 \x01(\x0b\x32(.temporal.api.cloud.identity.v1.UserSpec\x12\x1c\n\x10state_deprecated\x18\x04 \x01(\tB\x02\x18\x01\x12<\n\x05state\x18\t \x01(\x0e\x32-.temporal.api.cloud.resource.v1.ResourceState\x12\x1a\n\x12\x61sync_operation_id\x18\x05 \x01(\t\x12>\n\ninvitation\x18\x06 \x01(\x0b\x32*.temporal.api.cloud.identity.v1.Invitation\x12\x30\n\x0c\x63reated_time\x18\x07 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x36\n\x12last_modified_time\x18\x08 \x01(\x0b\x32\x1a.google.protobuf.Timestamp"(\n\x0fGoogleGroupSpec\x12\x15\n\remail_address\x18\x01 \x01(\t"\x1f\n\rSCIMGroupSpec\x12\x0e\n\x06idp_id\x18\x01 \x01(\t"\x10\n\x0e\x43loudGroupSpec"\xc0\x02\n\rUserGroupSpec\x12\x14\n\x0c\x64isplay_name\x18\x01 \x01(\t\x12\x36\n\x06\x61\x63\x63\x65ss\x18\x02 \x01(\x0b\x32&.temporal.api.cloud.identity.v1.Access\x12G\n\x0cgoogle_group\x18\x03 \x01(\x0b\x32/.temporal.api.cloud.identity.v1.GoogleGroupSpecH\x00\x12\x43\n\nscim_group\x18\x04 \x01(\x0b\x32-.temporal.api.cloud.identity.v1.SCIMGroupSpecH\x00\x12\x45\n\x0b\x63loud_group\x18\x05 \x01(\x0b\x32..temporal.api.cloud.identity.v1.CloudGroupSpecH\x00\x42\x0c\n\ngroup_type"\xd0\x02\n\tUserGroup\x12\n\n\x02id\x18\x01 \x01(\t\x12\x18\n\x10resource_version\x18\x02 \x01(\t\x12;\n\x04spec\x18\x03 \x01(\x0b\x32-.temporal.api.cloud.identity.v1.UserGroupSpec\x12\x1c\n\x10state_deprecated\x18\x04 \x01(\tB\x02\x18\x01\x12<\n\x05state\x18\x08 \x01(\x0e\x32-.temporal.api.cloud.resource.v1.ResourceState\x12\x1a\n\x12\x61sync_operation_id\x18\x05 \x01(\t\x12\x30\n\x0c\x63reated_time\x18\x06 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x36\n\x12last_modified_time\x18\x07 \x01(\x0b\x32\x1a.google.protobuf.Timestamp"5\n\x11UserGroupMemberId\x12\x11\n\x07user_id\x18\x01 \x01(\tH\x00\x42\r\n\x0bmember_type"\x89\x01\n\x0fUserGroupMember\x12\x44\n\tmember_id\x18\x01 \x01(\x0b\x32\x31.temporal.api.cloud.identity.v1.UserGroupMemberId\x12\x30\n\x0c\x63reated_time\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.Timestamp"\xda\x02\n\x0eServiceAccount\x12\n\n\x02id\x18\x01 \x01(\t\x12\x18\n\x10resource_version\x18\x02 \x01(\t\x12@\n\x04spec\x18\x03 \x01(\x0b\x32\x32.temporal.api.cloud.identity.v1.ServiceAccountSpec\x12\x1c\n\x10state_deprecated\x18\x04 \x01(\tB\x02\x18\x01\x12<\n\x05state\x18\x08 \x01(\x0e\x32-.temporal.api.cloud.resource.v1.ResourceState\x12\x1a\n\x12\x61sync_operation_id\x18\x05 \x01(\t\x12\x30\n\x0c\x63reated_time\x18\x06 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x36\n\x12last_modified_time\x18\x07 \x01(\x0b\x32\x1a.google.protobuf.Timestamp"\xc7\x01\n\x12ServiceAccountSpec\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x36\n\x06\x61\x63\x63\x65ss\x18\x02 \x01(\x0b\x32&.temporal.api.cloud.identity.v1.Access\x12V\n\x17namespace_scoped_access\x18\x04 \x01(\x0b\x32\x35.temporal.api.cloud.identity.v1.NamespaceScopedAccess\x12\x13\n\x0b\x64\x65scription\x18\x03 \x01(\t"\xca\x02\n\x06\x41piKey\x12\n\n\x02id\x18\x01 \x01(\t\x12\x18\n\x10resource_version\x18\x02 \x01(\t\x12\x38\n\x04spec\x18\x03 \x01(\x0b\x32*.temporal.api.cloud.identity.v1.ApiKeySpec\x12\x1c\n\x10state_deprecated\x18\x04 \x01(\tB\x02\x18\x01\x12<\n\x05state\x18\x08 \x01(\x0e\x32-.temporal.api.cloud.resource.v1.ResourceState\x12\x1a\n\x12\x61sync_operation_id\x18\x05 \x01(\t\x12\x30\n\x0c\x63reated_time\x18\x06 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x36\n\x12last_modified_time\x18\x07 \x01(\x0b\x32\x1a.google.protobuf.Timestamp"\xee\x01\n\nApiKeySpec\x12\x10\n\x08owner_id\x18\x01 \x01(\t\x12!\n\x15owner_type_deprecated\x18\x02 \x01(\tB\x02\x18\x01\x12=\n\nowner_type\x18\x07 \x01(\x0e\x32).temporal.api.cloud.identity.v1.OwnerType\x12\x14\n\x0c\x64isplay_name\x18\x03 \x01(\t\x12\x13\n\x0b\x64\x65scription\x18\x04 \x01(\t\x12/\n\x0b\x65xpiry_time\x18\x05 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x10\n\x08\x64isabled\x18\x06 \x01(\x08"\xbc\x02\n\x0e\x43ustomRoleSpec\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x13\n\x0b\x64\x65scription\x18\x02 \x01(\t\x12N\n\x0bpermissions\x18\x03 \x03(\x0b\x32\x39.temporal.api.cloud.identity.v1.CustomRoleSpec.Permission\x1aK\n\tResources\x12\x15\n\rresource_type\x18\x01 \x01(\t\x12\x14\n\x0cresource_ids\x18\x02 \x03(\t\x12\x11\n\tallow_all\x18\x03 \x01(\x08\x1aj\n\nPermission\x12K\n\tresources\x18\x01 \x01(\x0b\x32\x38.temporal.api.cloud.identity.v1.CustomRoleSpec.Resources\x12\x0f\n\x07\x61\x63tions\x18\x02 \x03(\t"\xb4\x02\n\nCustomRole\x12\n\n\x02id\x18\x01 \x01(\t\x12\x18\n\x10resource_version\x18\x02 \x01(\t\x12<\n\x04spec\x18\x03 \x01(\x0b\x32..temporal.api.cloud.identity.v1.CustomRoleSpec\x12<\n\x05state\x18\x04 \x01(\x0e\x32-.temporal.api.cloud.resource.v1.ResourceState\x12\x1a\n\x12\x61sync_operation_id\x18\x05 \x01(\t\x12\x30\n\x0c\x63reated_time\x18\x06 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x36\n\x12last_modified_time\x18\x07 \x01(\x0b\x32\x1a.google.protobuf.Timestamp"\xb3\x01\n\x17UserNamespaceAssignment\x12\n\n\x02id\x18\x01 \x01(\t\x12\r\n\x05\x65mail\x18\x02 \x01(\t\x12I\n\x10namespace_access\x18\x03 \x01(\x0b\x32/.temporal.api.cloud.identity.v1.NamespaceAccess\x12\x18\n\x10inherited_access\x18\x04 \x01(\x08\x12\x18\n\x10resource_version\x18\x05 \x01(\t"\xbc\x01\n!ServiceAccountNamespaceAssignment\x12\n\n\x02id\x18\x01 \x01(\t\x12\x0c\n\x04name\x18\x02 \x01(\t\x12I\n\x10namespace_access\x18\x03 \x01(\x0b\x32/.temporal.api.cloud.identity.v1.NamespaceAccess\x12\x18\n\x10inherited_access\x18\x04 \x01(\x08\x12\x18\n\x10resource_version\x18\x05 \x01(\t"\xbf\x01\n\x1cUserGroupNamespaceAssignment\x12\n\n\x02id\x18\x01 \x01(\t\x12\x14\n\x0c\x64isplay_name\x18\x02 \x01(\t\x12I\n\x10namespace_access\x18\x03 \x01(\x0b\x32/.temporal.api.cloud.identity.v1.NamespaceAccess\x12\x18\n\x10inherited_access\x18\x04 \x01(\x08\x12\x18\n\x10resource_version\x18\x05 \x01(\t*\\\n\tOwnerType\x12\x1a\n\x16OWNER_TYPE_UNSPECIFIED\x10\x00\x12\x13\n\x0fOWNER_TYPE_USER\x10\x01\x12\x1e\n\x1aOWNER_TYPE_SERVICE_ACCOUNT\x10\x02\x42\xac\x01\n!io.temporal.api.cloud.identity.v1B\x0cMessageProtoP\x01Z-go.temporal.io/api/cloud/identity/v1;identity\xaa\x02 Temporalio.Api.Cloud.Identity.V1\xea\x02$Temporalio::Api::Cloud::Identity::V1b\x06proto3' ) _OWNERTYPE = DESCRIPTOR.enum_types_by_name["OwnerType"] @@ -55,6 +55,13 @@ _CUSTOMROLESPEC_RESOURCES = _CUSTOMROLESPEC.nested_types_by_name["Resources"] _CUSTOMROLESPEC_PERMISSION = _CUSTOMROLESPEC.nested_types_by_name["Permission"] _CUSTOMROLE = DESCRIPTOR.message_types_by_name["CustomRole"] +_USERNAMESPACEASSIGNMENT = DESCRIPTOR.message_types_by_name["UserNamespaceAssignment"] +_SERVICEACCOUNTNAMESPACEASSIGNMENT = DESCRIPTOR.message_types_by_name[ + "ServiceAccountNamespaceAssignment" +] +_USERGROUPNAMESPACEASSIGNMENT = DESCRIPTOR.message_types_by_name[ + "UserGroupNamespaceAssignment" +] _ACCOUNTACCESS_ROLE = _ACCOUNTACCESS.enum_types_by_name["Role"] _NAMESPACEACCESS_PERMISSION = _NAMESPACEACCESS.enum_types_by_name["Permission"] AccountAccess = _reflection.GeneratedProtocolMessageType( @@ -307,6 +314,39 @@ ) _sym_db.RegisterMessage(CustomRole) +UserNamespaceAssignment = _reflection.GeneratedProtocolMessageType( + "UserNamespaceAssignment", + (_message.Message,), + { + "DESCRIPTOR": _USERNAMESPACEASSIGNMENT, + "__module__": "temporalio.api.cloud.identity.v1.message_pb2", + # @@protoc_insertion_point(class_scope:temporal.api.cloud.identity.v1.UserNamespaceAssignment) + }, +) +_sym_db.RegisterMessage(UserNamespaceAssignment) + +ServiceAccountNamespaceAssignment = _reflection.GeneratedProtocolMessageType( + "ServiceAccountNamespaceAssignment", + (_message.Message,), + { + "DESCRIPTOR": _SERVICEACCOUNTNAMESPACEASSIGNMENT, + "__module__": "temporalio.api.cloud.identity.v1.message_pb2", + # @@protoc_insertion_point(class_scope:temporal.api.cloud.identity.v1.ServiceAccountNamespaceAssignment) + }, +) +_sym_db.RegisterMessage(ServiceAccountNamespaceAssignment) + +UserGroupNamespaceAssignment = _reflection.GeneratedProtocolMessageType( + "UserGroupNamespaceAssignment", + (_message.Message,), + { + "DESCRIPTOR": _USERGROUPNAMESPACEASSIGNMENT, + "__module__": "temporalio.api.cloud.identity.v1.message_pb2", + # @@protoc_insertion_point(class_scope:temporal.api.cloud.identity.v1.UserGroupNamespaceAssignment) + }, +) +_sym_db.RegisterMessage(UserGroupNamespaceAssignment) + if _descriptor._USE_C_DESCRIPTORS == False: DESCRIPTOR._options = None DESCRIPTOR._serialized_options = b"\n!io.temporal.api.cloud.identity.v1B\014MessageProtoP\001Z-go.temporal.io/api/cloud/identity/v1;identity\252\002 Temporalio.Api.Cloud.Identity.V1\352\002$Temporalio::Api::Cloud::Identity::V1" @@ -332,8 +372,8 @@ _APIKEYSPEC.fields_by_name[ "owner_type_deprecated" ]._serialized_options = b"\030\001" - _OWNERTYPE._serialized_start = 4402 - _OWNERTYPE._serialized_end = 4494 + _OWNERTYPE._serialized_start = 4969 + _OWNERTYPE._serialized_end = 5061 _ACCOUNTACCESS._serialized_start = 160 _ACCOUNTACCESS._serialized_end = 437 _ACCOUNTACCESS_ROLE._serialized_start = 295 @@ -384,4 +424,10 @@ _CUSTOMROLESPEC_PERMISSION._serialized_end = 4089 _CUSTOMROLE._serialized_start = 4092 _CUSTOMROLE._serialized_end = 4400 + _USERNAMESPACEASSIGNMENT._serialized_start = 4403 + _USERNAMESPACEASSIGNMENT._serialized_end = 4582 + _SERVICEACCOUNTNAMESPACEASSIGNMENT._serialized_start = 4585 + _SERVICEACCOUNTNAMESPACEASSIGNMENT._serialized_end = 4773 + _USERGROUPNAMESPACEASSIGNMENT._serialized_start = 4776 + _USERGROUPNAMESPACEASSIGNMENT._serialized_end = 4967 # @@protoc_insertion_point(module_scope) diff --git a/temporalio/api/cloud/identity/v1/message_pb2.pyi b/temporalio/api/cloud/identity/v1/message_pb2.pyi index 0427542bf..5471475f6 100644 --- a/temporalio/api/cloud/identity/v1/message_pb2.pyi +++ b/temporalio/api/cloud/identity/v1/message_pb2.pyi @@ -1218,3 +1218,153 @@ class CustomRole(google.protobuf.message.Message): ) -> None: ... global___CustomRole = CustomRole + +class UserNamespaceAssignment(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + ID_FIELD_NUMBER: builtins.int + EMAIL_FIELD_NUMBER: builtins.int + NAMESPACE_ACCESS_FIELD_NUMBER: builtins.int + INHERITED_ACCESS_FIELD_NUMBER: builtins.int + RESOURCE_VERSION_FIELD_NUMBER: builtins.int + id: builtins.str + """The ID of the user.""" + email: builtins.str + """The email of the user.""" + @property + def namespace_access(self) -> global___NamespaceAccess: + """The access assigned to the user at the namespace level.""" + inherited_access: builtins.bool + """True if the user has inherited access to the namespace through an account or project role.""" + resource_version: builtins.str + """The current resource version of the user.""" + def __init__( + self, + *, + id: builtins.str = ..., + email: builtins.str = ..., + namespace_access: global___NamespaceAccess | None = ..., + inherited_access: builtins.bool = ..., + resource_version: builtins.str = ..., + ) -> None: ... + def HasField( + self, + field_name: typing_extensions.Literal["namespace_access", b"namespace_access"], + ) -> builtins.bool: ... + def ClearField( + self, + field_name: typing_extensions.Literal[ + "email", + b"email", + "id", + b"id", + "inherited_access", + b"inherited_access", + "namespace_access", + b"namespace_access", + "resource_version", + b"resource_version", + ], + ) -> None: ... + +global___UserNamespaceAssignment = UserNamespaceAssignment + +class ServiceAccountNamespaceAssignment(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + ID_FIELD_NUMBER: builtins.int + NAME_FIELD_NUMBER: builtins.int + NAMESPACE_ACCESS_FIELD_NUMBER: builtins.int + INHERITED_ACCESS_FIELD_NUMBER: builtins.int + RESOURCE_VERSION_FIELD_NUMBER: builtins.int + id: builtins.str + """The ID of the service account.""" + name: builtins.str + """The name of the service account.""" + @property + def namespace_access(self) -> global___NamespaceAccess: + """The access assigned to the service account at the namespace level.""" + inherited_access: builtins.bool + """True if the service account has inherited access to the namespace through an account or project role.""" + resource_version: builtins.str + """The current resource version of the service account.""" + def __init__( + self, + *, + id: builtins.str = ..., + name: builtins.str = ..., + namespace_access: global___NamespaceAccess | None = ..., + inherited_access: builtins.bool = ..., + resource_version: builtins.str = ..., + ) -> None: ... + def HasField( + self, + field_name: typing_extensions.Literal["namespace_access", b"namespace_access"], + ) -> builtins.bool: ... + def ClearField( + self, + field_name: typing_extensions.Literal[ + "id", + b"id", + "inherited_access", + b"inherited_access", + "name", + b"name", + "namespace_access", + b"namespace_access", + "resource_version", + b"resource_version", + ], + ) -> None: ... + +global___ServiceAccountNamespaceAssignment = ServiceAccountNamespaceAssignment + +class UserGroupNamespaceAssignment(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + ID_FIELD_NUMBER: builtins.int + DISPLAY_NAME_FIELD_NUMBER: builtins.int + NAMESPACE_ACCESS_FIELD_NUMBER: builtins.int + INHERITED_ACCESS_FIELD_NUMBER: builtins.int + RESOURCE_VERSION_FIELD_NUMBER: builtins.int + id: builtins.str + """The ID of the group.""" + display_name: builtins.str + """The display name of the group.""" + @property + def namespace_access(self) -> global___NamespaceAccess: + """The access assigned to the group at the namespace level.""" + inherited_access: builtins.bool + """True if the group has inherited access to the namespace through an account or project role.""" + resource_version: builtins.str + """The current resource version of the group.""" + def __init__( + self, + *, + id: builtins.str = ..., + display_name: builtins.str = ..., + namespace_access: global___NamespaceAccess | None = ..., + inherited_access: builtins.bool = ..., + resource_version: builtins.str = ..., + ) -> None: ... + def HasField( + self, + field_name: typing_extensions.Literal["namespace_access", b"namespace_access"], + ) -> builtins.bool: ... + def ClearField( + self, + field_name: typing_extensions.Literal[ + "display_name", + b"display_name", + "id", + b"id", + "inherited_access", + b"inherited_access", + "namespace_access", + b"namespace_access", + "resource_version", + b"resource_version", + ], + ) -> None: ... + +global___UserGroupNamespaceAssignment = UserGroupNamespaceAssignment diff --git a/temporalio/api/common/v1/message_pb2.py b/temporalio/api/common/v1/message_pb2.py index 86a0c18fc..aed909611 100644 --- a/temporalio/api/common/v1/message_pb2.py +++ b/temporalio/api/common/v1/message_pb2.py @@ -28,7 +28,7 @@ ) DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile( - b'\n$temporal/api/common/v1/message.proto\x12\x16temporal.api.common.v1\x1a\x1egoogle/protobuf/duration.proto\x1a\x1bgoogle/protobuf/empty.proto\x1a"temporal/api/enums/v1/common.proto\x1a&temporal/api/enums/v1/event_type.proto\x1a!temporal/api/enums/v1/reset.proto"T\n\x08\x44\x61taBlob\x12:\n\rencoding_type\x18\x01 \x01(\x0e\x32#.temporal.api.enums.v1.EncodingType\x12\x0c\n\x04\x64\x61ta\x18\x02 \x01(\x0c"=\n\x08Payloads\x12\x31\n\x08payloads\x18\x01 \x03(\x0b\x32\x1f.temporal.api.common.v1.Payload"\x8a\x02\n\x07Payload\x12?\n\x08metadata\x18\x01 \x03(\x0b\x32-.temporal.api.common.v1.Payload.MetadataEntry\x12\x0c\n\x04\x64\x61ta\x18\x02 \x01(\x0c\x12Q\n\x11\x65xternal_payloads\x18\x03 \x03(\x0b\x32\x36.temporal.api.common.v1.Payload.ExternalPayloadDetails\x1a/\n\rMetadataEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\x0c:\x02\x38\x01\x1a,\n\x16\x45xternalPayloadDetails\x12\x12\n\nsize_bytes\x18\x01 \x01(\x03"\xbe\x01\n\x10SearchAttributes\x12S\n\x0eindexed_fields\x18\x01 \x03(\x0b\x32;.temporal.api.common.v1.SearchAttributes.IndexedFieldsEntry\x1aU\n\x12IndexedFieldsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12.\n\x05value\x18\x02 \x01(\x0b\x32\x1f.temporal.api.common.v1.Payload:\x02\x38\x01"\x90\x01\n\x04Memo\x12\x38\n\x06\x66ields\x18\x01 \x03(\x0b\x32(.temporal.api.common.v1.Memo.FieldsEntry\x1aN\n\x0b\x46ieldsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12.\n\x05value\x18\x02 \x01(\x0b\x32\x1f.temporal.api.common.v1.Payload:\x02\x38\x01"\x94\x01\n\x06Header\x12:\n\x06\x66ields\x18\x01 \x03(\x0b\x32*.temporal.api.common.v1.Header.FieldsEntry\x1aN\n\x0b\x46ieldsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12.\n\x05value\x18\x02 \x01(\x0b\x32\x1f.temporal.api.common.v1.Payload:\x02\x38\x01"8\n\x11WorkflowExecution\x12\x13\n\x0bworkflow_id\x18\x01 \x01(\t\x12\x0e\n\x06run_id\x18\x02 \x01(\t"\x1c\n\x0cWorkflowType\x12\x0c\n\x04name\x18\x01 \x01(\t"\x1c\n\x0c\x41\x63tivityType\x12\x0c\n\x04name\x18\x01 \x01(\t"\xd1\x01\n\x0bRetryPolicy\x12\x33\n\x10initial_interval\x18\x01 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x1b\n\x13\x62\x61\x63koff_coefficient\x18\x02 \x01(\x01\x12\x33\n\x10maximum_interval\x18\x03 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x18\n\x10maximum_attempts\x18\x04 \x01(\x05\x12!\n\x19non_retryable_error_types\x18\x05 \x03(\t"F\n\x10MeteringMetadata\x12\x32\n*nonfirst_local_activity_execution_attempts\x18\r \x01(\r">\n\x12WorkerVersionStamp\x12\x10\n\x08\x62uild_id\x18\x01 \x01(\t\x12\x16\n\x0euse_versioning\x18\x03 \x01(\x08"e\n\x19WorkerVersionCapabilities\x12\x10\n\x08\x62uild_id\x18\x01 \x01(\t\x12\x16\n\x0euse_versioning\x18\x02 \x01(\x08\x12\x1e\n\x16\x64\x65ployment_series_name\x18\x04 \x01(\t"\xed\x02\n\x0cResetOptions\x12\x35\n\x13\x66irst_workflow_task\x18\x01 \x01(\x0b\x32\x16.google.protobuf.EmptyH\x00\x12\x34\n\x12last_workflow_task\x18\x02 \x01(\x0b\x32\x16.google.protobuf.EmptyH\x00\x12\x1a\n\x10workflow_task_id\x18\x03 \x01(\x03H\x00\x12\x12\n\x08\x62uild_id\x18\x04 \x01(\tH\x00\x12G\n\x12reset_reapply_type\x18\n \x01(\x0e\x32\'.temporal.api.enums.v1.ResetReapplyTypeB\x02\x18\x01\x12\x18\n\x10\x63urrent_run_only\x18\x0b \x01(\x08\x12S\n\x1breset_reapply_exclude_types\x18\x0c \x03(\x0e\x32..temporal.api.enums.v1.ResetReapplyExcludeTypeB\x08\n\x06target"\xe4\x02\n\x08\x43\x61llback\x12\x37\n\x05nexus\x18\x02 \x01(\x0b\x32&.temporal.api.common.v1.Callback.NexusH\x00\x12=\n\x08internal\x18\x03 \x01(\x0b\x32).temporal.api.common.v1.Callback.InternalH\x00\x12+\n\x05links\x18\x64 \x03(\x0b\x32\x1c.temporal.api.common.v1.Link\x1a\x87\x01\n\x05Nexus\x12\x0b\n\x03url\x18\x01 \x01(\t\x12\x42\n\x06header\x18\x02 \x03(\x0b\x32\x32.temporal.api.common.v1.Callback.Nexus.HeaderEntry\x1a-\n\x0bHeaderEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x1a\x18\n\x08Internal\x12\x0c\n\x04\x64\x61ta\x18\x01 \x01(\x0c\x42\t\n\x07variantJ\x04\x08\x01\x10\x02"\xfb\x06\n\x04Link\x12\x44\n\x0eworkflow_event\x18\x01 \x01(\x0b\x32*.temporal.api.common.v1.Link.WorkflowEventH\x00\x12:\n\tbatch_job\x18\x02 \x01(\x0b\x32%.temporal.api.common.v1.Link.BatchJobH\x00\x12\x39\n\x08\x61\x63tivity\x18\x03 \x01(\x0b\x32%.temporal.api.common.v1.Link.ActivityH\x00\x12\x46\n\x0fnexus_operation\x18\x04 \x01(\x0b\x32+.temporal.api.common.v1.Link.NexusOperationH\x00\x1a\xb7\x03\n\rWorkflowEvent\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x12N\n\tevent_ref\x18\x64 \x01(\x0b\x32\x39.temporal.api.common.v1.Link.WorkflowEvent.EventReferenceH\x00\x12W\n\x0erequest_id_ref\x18\x65 \x01(\x0b\x32=.temporal.api.common.v1.Link.WorkflowEvent.RequestIdReferenceH\x00\x1aX\n\x0e\x45ventReference\x12\x10\n\x08\x65vent_id\x18\x01 \x01(\x03\x12\x34\n\nevent_type\x18\x02 \x01(\x0e\x32 .temporal.api.enums.v1.EventType\x1a^\n\x12RequestIdReference\x12\x12\n\nrequest_id\x18\x01 \x01(\t\x12\x34\n\nevent_type\x18\x02 \x01(\x0e\x32 .temporal.api.enums.v1.EventTypeB\x0b\n\treference\x1a\x1a\n\x08\x42\x61tchJob\x12\x0e\n\x06job_id\x18\x01 \x01(\t\x1a\x42\n\x08\x41\x63tivity\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0b\x61\x63tivity_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x1aI\n\x0eNexusOperation\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x14\n\x0coperation_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\tB\t\n\x07variant"\'\n\tPrincipal\x12\x0c\n\x04type\x18\x01 \x01(\t\x12\x0c\n\x04name\x18\x02 \x01(\t"O\n\x08Priority\x12\x14\n\x0cpriority_key\x18\x01 \x01(\x05\x12\x14\n\x0c\x66\x61irness_key\x18\x02 \x01(\t\x12\x17\n\x0f\x66\x61irness_weight\x18\x03 \x01(\x02";\n\x0eWorkerSelector\x12\x1d\n\x13worker_instance_key\x18\x01 \x01(\tH\x00\x42\n\n\x08selector"i\n\x11OnConflictOptions\x12\x19\n\x11\x61ttach_request_id\x18\x01 \x01(\x08\x12#\n\x1b\x61ttach_completion_callbacks\x18\x02 \x01(\x08\x12\x14\n\x0c\x61ttach_links\x18\x03 \x01(\x08\x42\x89\x01\n\x19io.temporal.api.common.v1B\x0cMessageProtoP\x01Z#go.temporal.io/api/common/v1;common\xaa\x02\x18Temporalio.Api.Common.V1\xea\x02\x1bTemporalio::Api::Common::V1b\x06proto3' + b'\n$temporal/api/common/v1/message.proto\x12\x16temporal.api.common.v1\x1a\x1egoogle/protobuf/duration.proto\x1a\x1bgoogle/protobuf/empty.proto\x1a"temporal/api/enums/v1/common.proto\x1a&temporal/api/enums/v1/event_type.proto\x1a!temporal/api/enums/v1/reset.proto"T\n\x08\x44\x61taBlob\x12:\n\rencoding_type\x18\x01 \x01(\x0e\x32#.temporal.api.enums.v1.EncodingType\x12\x0c\n\x04\x64\x61ta\x18\x02 \x01(\x0c"=\n\x08Payloads\x12\x31\n\x08payloads\x18\x01 \x03(\x0b\x32\x1f.temporal.api.common.v1.Payload"\x8a\x02\n\x07Payload\x12?\n\x08metadata\x18\x01 \x03(\x0b\x32-.temporal.api.common.v1.Payload.MetadataEntry\x12\x0c\n\x04\x64\x61ta\x18\x02 \x01(\x0c\x12Q\n\x11\x65xternal_payloads\x18\x03 \x03(\x0b\x32\x36.temporal.api.common.v1.Payload.ExternalPayloadDetails\x1a/\n\rMetadataEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\x0c:\x02\x38\x01\x1a,\n\x16\x45xternalPayloadDetails\x12\x12\n\nsize_bytes\x18\x01 \x01(\x03"\xbe\x01\n\x10SearchAttributes\x12S\n\x0eindexed_fields\x18\x01 \x03(\x0b\x32;.temporal.api.common.v1.SearchAttributes.IndexedFieldsEntry\x1aU\n\x12IndexedFieldsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12.\n\x05value\x18\x02 \x01(\x0b\x32\x1f.temporal.api.common.v1.Payload:\x02\x38\x01"\x90\x01\n\x04Memo\x12\x38\n\x06\x66ields\x18\x01 \x03(\x0b\x32(.temporal.api.common.v1.Memo.FieldsEntry\x1aN\n\x0b\x46ieldsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12.\n\x05value\x18\x02 \x01(\x0b\x32\x1f.temporal.api.common.v1.Payload:\x02\x38\x01"\x94\x01\n\x06Header\x12:\n\x06\x66ields\x18\x01 \x03(\x0b\x32*.temporal.api.common.v1.Header.FieldsEntry\x1aN\n\x0b\x46ieldsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12.\n\x05value\x18\x02 \x01(\x0b\x32\x1f.temporal.api.common.v1.Payload:\x02\x38\x01"8\n\x11WorkflowExecution\x12\x13\n\x0bworkflow_id\x18\x01 \x01(\t\x12\x0e\n\x06run_id\x18\x02 \x01(\t"\x1c\n\x0cWorkflowType\x12\x0c\n\x04name\x18\x01 \x01(\t"\x1c\n\x0c\x41\x63tivityType\x12\x0c\n\x04name\x18\x01 \x01(\t"\xd1\x01\n\x0bRetryPolicy\x12\x33\n\x10initial_interval\x18\x01 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x1b\n\x13\x62\x61\x63koff_coefficient\x18\x02 \x01(\x01\x12\x33\n\x10maximum_interval\x18\x03 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x18\n\x10maximum_attempts\x18\x04 \x01(\x05\x12!\n\x19non_retryable_error_types\x18\x05 \x03(\t"F\n\x10MeteringMetadata\x12\x32\n*nonfirst_local_activity_execution_attempts\x18\r \x01(\r">\n\x12WorkerVersionStamp\x12\x10\n\x08\x62uild_id\x18\x01 \x01(\t\x12\x16\n\x0euse_versioning\x18\x03 \x01(\x08"e\n\x19WorkerVersionCapabilities\x12\x10\n\x08\x62uild_id\x18\x01 \x01(\t\x12\x16\n\x0euse_versioning\x18\x02 \x01(\x08\x12\x1e\n\x16\x64\x65ployment_series_name\x18\x04 \x01(\t"\xed\x02\n\x0cResetOptions\x12\x35\n\x13\x66irst_workflow_task\x18\x01 \x01(\x0b\x32\x16.google.protobuf.EmptyH\x00\x12\x34\n\x12last_workflow_task\x18\x02 \x01(\x0b\x32\x16.google.protobuf.EmptyH\x00\x12\x1a\n\x10workflow_task_id\x18\x03 \x01(\x03H\x00\x12\x12\n\x08\x62uild_id\x18\x04 \x01(\tH\x00\x12G\n\x12reset_reapply_type\x18\n \x01(\x0e\x32\'.temporal.api.enums.v1.ResetReapplyTypeB\x02\x18\x01\x12\x18\n\x10\x63urrent_run_only\x18\x0b \x01(\x08\x12S\n\x1breset_reapply_exclude_types\x18\x0c \x03(\x0e\x32..temporal.api.enums.v1.ResetReapplyExcludeTypeB\x08\n\x06target"\xe4\x02\n\x08\x43\x61llback\x12\x37\n\x05nexus\x18\x02 \x01(\x0b\x32&.temporal.api.common.v1.Callback.NexusH\x00\x12=\n\x08internal\x18\x03 \x01(\x0b\x32).temporal.api.common.v1.Callback.InternalH\x00\x12+\n\x05links\x18\x64 \x03(\x0b\x32\x1c.temporal.api.common.v1.Link\x1a\x87\x01\n\x05Nexus\x12\x0b\n\x03url\x18\x01 \x01(\t\x12\x42\n\x06header\x18\x02 \x03(\x0b\x32\x32.temporal.api.common.v1.Callback.Nexus.HeaderEntry\x1a-\n\x0bHeaderEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x1a\x18\n\x08Internal\x12\x0c\n\x04\x64\x61ta\x18\x01 \x01(\x0c\x42\t\n\x07variantJ\x04\x08\x01\x10\x02"\x8a\x08\n\x04Link\x12\x44\n\x0eworkflow_event\x18\x01 \x01(\x0b\x32*.temporal.api.common.v1.Link.WorkflowEventH\x00\x12:\n\tbatch_job\x18\x02 \x01(\x0b\x32%.temporal.api.common.v1.Link.BatchJobH\x00\x12\x39\n\x08\x61\x63tivity\x18\x03 \x01(\x0b\x32%.temporal.api.common.v1.Link.ActivityH\x00\x12\x46\n\x0fnexus_operation\x18\x04 \x01(\x0b\x32+.temporal.api.common.v1.Link.NexusOperationH\x00\x12\x39\n\x08workflow\x18\x05 \x01(\x0b\x32%.temporal.api.common.v1.Link.WorkflowH\x00\x1a\xb7\x03\n\rWorkflowEvent\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x12N\n\tevent_ref\x18\x64 \x01(\x0b\x32\x39.temporal.api.common.v1.Link.WorkflowEvent.EventReferenceH\x00\x12W\n\x0erequest_id_ref\x18\x65 \x01(\x0b\x32=.temporal.api.common.v1.Link.WorkflowEvent.RequestIdReferenceH\x00\x1aX\n\x0e\x45ventReference\x12\x10\n\x08\x65vent_id\x18\x01 \x01(\x03\x12\x34\n\nevent_type\x18\x02 \x01(\x0e\x32 .temporal.api.enums.v1.EventType\x1a^\n\x12RequestIdReference\x12\x12\n\nrequest_id\x18\x01 \x01(\t\x12\x34\n\nevent_type\x18\x02 \x01(\x0e\x32 .temporal.api.enums.v1.EventTypeB\x0b\n\treference\x1a\x1a\n\x08\x42\x61tchJob\x12\x0e\n\x06job_id\x18\x01 \x01(\t\x1a\x42\n\x08\x41\x63tivity\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0b\x61\x63tivity_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x1aI\n\x0eNexusOperation\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x14\n\x0coperation_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x1aR\n\x08Workflow\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x12\x0e\n\x06reason\x18\x04 \x01(\tB\t\n\x07variant"\'\n\tPrincipal\x12\x0c\n\x04type\x18\x01 \x01(\t\x12\x0c\n\x04name\x18\x02 \x01(\t"O\n\x08Priority\x12\x14\n\x0cpriority_key\x18\x01 \x01(\x05\x12\x14\n\x0c\x66\x61irness_key\x18\x02 \x01(\t\x12\x17\n\x0f\x66\x61irness_weight\x18\x03 \x01(\x02";\n\x0eWorkerSelector\x12\x1d\n\x13worker_instance_key\x18\x01 \x01(\tH\x00\x42\n\n\x08selector"i\n\x11OnConflictOptions\x12\x19\n\x11\x61ttach_request_id\x18\x01 \x01(\x08\x12#\n\x1b\x61ttach_completion_callbacks\x18\x02 \x01(\x08\x12\x14\n\x0c\x61ttach_links\x18\x03 \x01(\x08\x42\x89\x01\n\x19io.temporal.api.common.v1B\x0cMessageProtoP\x01Z#go.temporal.io/api/common/v1;common\xaa\x02\x18Temporalio.Api.Common.V1\xea\x02\x1bTemporalio::Api::Common::V1b\x06proto3' ) @@ -72,6 +72,7 @@ _LINK_BATCHJOB = _LINK.nested_types_by_name["BatchJob"] _LINK_ACTIVITY = _LINK.nested_types_by_name["Activity"] _LINK_NEXUSOPERATION = _LINK.nested_types_by_name["NexusOperation"] +_LINK_WORKFLOW = _LINK.nested_types_by_name["Workflow"] _PRINCIPAL = DESCRIPTOR.message_types_by_name["Principal"] _PRIORITY = DESCRIPTOR.message_types_by_name["Priority"] _WORKERSELECTOR = DESCRIPTOR.message_types_by_name["WorkerSelector"] @@ -379,6 +380,15 @@ # @@protoc_insertion_point(class_scope:temporal.api.common.v1.Link.NexusOperation) }, ), + "Workflow": _reflection.GeneratedProtocolMessageType( + "Workflow", + (_message.Message,), + { + "DESCRIPTOR": _LINK_WORKFLOW, + "__module__": "temporalio.api.common.v1.message_pb2", + # @@protoc_insertion_point(class_scope:temporal.api.common.v1.Link.Workflow) + }, + ), "DESCRIPTOR": _LINK, "__module__": "temporalio.api.common.v1.message_pb2", # @@protoc_insertion_point(class_scope:temporal.api.common.v1.Link) @@ -391,6 +401,7 @@ _sym_db.RegisterMessage(Link.BatchJob) _sym_db.RegisterMessage(Link.Activity) _sym_db.RegisterMessage(Link.NexusOperation) +_sym_db.RegisterMessage(Link.Workflow) Principal = _reflection.GeneratedProtocolMessageType( "Principal", @@ -498,25 +509,27 @@ _CALLBACK_INTERNAL._serialized_start = 2398 _CALLBACK_INTERNAL._serialized_end = 2422 _LINK._serialized_start = 2442 - _LINK._serialized_end = 3333 - _LINK_WORKFLOWEVENT._serialized_start = 2712 - _LINK_WORKFLOWEVENT._serialized_end = 3151 - _LINK_WORKFLOWEVENT_EVENTREFERENCE._serialized_start = 2954 - _LINK_WORKFLOWEVENT_EVENTREFERENCE._serialized_end = 3042 - _LINK_WORKFLOWEVENT_REQUESTIDREFERENCE._serialized_start = 3044 - _LINK_WORKFLOWEVENT_REQUESTIDREFERENCE._serialized_end = 3138 - _LINK_BATCHJOB._serialized_start = 3153 - _LINK_BATCHJOB._serialized_end = 3179 - _LINK_ACTIVITY._serialized_start = 3181 - _LINK_ACTIVITY._serialized_end = 3247 - _LINK_NEXUSOPERATION._serialized_start = 3249 - _LINK_NEXUSOPERATION._serialized_end = 3322 - _PRINCIPAL._serialized_start = 3335 - _PRINCIPAL._serialized_end = 3374 - _PRIORITY._serialized_start = 3376 - _PRIORITY._serialized_end = 3455 - _WORKERSELECTOR._serialized_start = 3457 - _WORKERSELECTOR._serialized_end = 3516 - _ONCONFLICTOPTIONS._serialized_start = 3518 - _ONCONFLICTOPTIONS._serialized_end = 3623 + _LINK._serialized_end = 3476 + _LINK_WORKFLOWEVENT._serialized_start = 2771 + _LINK_WORKFLOWEVENT._serialized_end = 3210 + _LINK_WORKFLOWEVENT_EVENTREFERENCE._serialized_start = 3013 + _LINK_WORKFLOWEVENT_EVENTREFERENCE._serialized_end = 3101 + _LINK_WORKFLOWEVENT_REQUESTIDREFERENCE._serialized_start = 3103 + _LINK_WORKFLOWEVENT_REQUESTIDREFERENCE._serialized_end = 3197 + _LINK_BATCHJOB._serialized_start = 3212 + _LINK_BATCHJOB._serialized_end = 3238 + _LINK_ACTIVITY._serialized_start = 3240 + _LINK_ACTIVITY._serialized_end = 3306 + _LINK_NEXUSOPERATION._serialized_start = 3308 + _LINK_NEXUSOPERATION._serialized_end = 3381 + _LINK_WORKFLOW._serialized_start = 3383 + _LINK_WORKFLOW._serialized_end = 3465 + _PRINCIPAL._serialized_start = 3478 + _PRINCIPAL._serialized_end = 3517 + _PRIORITY._serialized_start = 3519 + _PRIORITY._serialized_end = 3598 + _WORKERSELECTOR._serialized_start = 3600 + _WORKERSELECTOR._serialized_end = 3659 + _ONCONFLICTOPTIONS._serialized_start = 3661 + _ONCONFLICTOPTIONS._serialized_end = 3766 # @@protoc_insertion_point(module_scope) diff --git a/temporalio/api/common/v1/message_pb2.pyi b/temporalio/api/common/v1/message_pb2.pyi index 36685f976..76e87fd56 100644 --- a/temporalio/api/common/v1/message_pb2.pyi +++ b/temporalio/api/common/v1/message_pb2.pyi @@ -943,10 +943,49 @@ class Link(google.protobuf.message.Message): ], ) -> None: ... + class Workflow(google.protobuf.message.Message): + """A link to a workflow execution. This is a more general version of WorkflowEvent that doesn't specify a + particular event within the workflow, useful when you want to link to a workflow but there is no particular event to link to, + such as a Query or a Rejected Update. + """ + + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + NAMESPACE_FIELD_NUMBER: builtins.int + WORKFLOW_ID_FIELD_NUMBER: builtins.int + RUN_ID_FIELD_NUMBER: builtins.int + REASON_FIELD_NUMBER: builtins.int + namespace: builtins.str + workflow_id: builtins.str + run_id: builtins.str + reason: builtins.str + def __init__( + self, + *, + namespace: builtins.str = ..., + workflow_id: builtins.str = ..., + run_id: builtins.str = ..., + reason: builtins.str = ..., + ) -> None: ... + def ClearField( + self, + field_name: typing_extensions.Literal[ + "namespace", + b"namespace", + "reason", + b"reason", + "run_id", + b"run_id", + "workflow_id", + b"workflow_id", + ], + ) -> None: ... + WORKFLOW_EVENT_FIELD_NUMBER: builtins.int BATCH_JOB_FIELD_NUMBER: builtins.int ACTIVITY_FIELD_NUMBER: builtins.int NEXUS_OPERATION_FIELD_NUMBER: builtins.int + WORKFLOW_FIELD_NUMBER: builtins.int @property def workflow_event(self) -> global___Link.WorkflowEvent: ... @property @@ -955,6 +994,8 @@ class Link(google.protobuf.message.Message): def activity(self) -> global___Link.Activity: ... @property def nexus_operation(self) -> global___Link.NexusOperation: ... + @property + def workflow(self) -> global___Link.Workflow: ... def __init__( self, *, @@ -962,6 +1003,7 @@ class Link(google.protobuf.message.Message): batch_job: global___Link.BatchJob | None = ..., activity: global___Link.Activity | None = ..., nexus_operation: global___Link.NexusOperation | None = ..., + workflow: global___Link.Workflow | None = ..., ) -> None: ... def HasField( self, @@ -974,6 +1016,8 @@ class Link(google.protobuf.message.Message): b"nexus_operation", "variant", b"variant", + "workflow", + b"workflow", "workflow_event", b"workflow_event", ], @@ -989,6 +1033,8 @@ class Link(google.protobuf.message.Message): b"nexus_operation", "variant", b"variant", + "workflow", + b"workflow", "workflow_event", b"workflow_event", ], @@ -997,7 +1043,7 @@ class Link(google.protobuf.message.Message): self, oneof_group: typing_extensions.Literal["variant", b"variant"] ) -> ( typing_extensions.Literal[ - "workflow_event", "batch_job", "activity", "nexus_operation" + "workflow_event", "batch_job", "activity", "nexus_operation", "workflow" ] | None ): ... diff --git a/temporalio/api/dependencies/nexusannotations/__init__.py b/temporalio/api/dependencies/nexusannotations/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/temporalio/api/dependencies/nexusannotations/v1/__init__.py b/temporalio/api/dependencies/nexusannotations/v1/__init__.py new file mode 100644 index 000000000..5cb684914 --- /dev/null +++ b/temporalio/api/dependencies/nexusannotations/v1/__init__.py @@ -0,0 +1,6 @@ +from .options_pb2 import OperationOptions, ServiceOptions + +__all__ = [ + "OperationOptions", + "ServiceOptions", +] diff --git a/temporalio/api/dependencies/nexusannotations/v1/options_pb2.py b/temporalio/api/dependencies/nexusannotations/v1/options_pb2.py new file mode 100644 index 000000000..c104009e3 --- /dev/null +++ b/temporalio/api/dependencies/nexusannotations/v1/options_pb2.py @@ -0,0 +1,65 @@ +# -*- coding: utf-8 -*- +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: nexusannotations/v1/options.proto +"""Generated protocol buffer code.""" + +from google.protobuf import descriptor as _descriptor +from google.protobuf import descriptor_pool as _descriptor_pool +from google.protobuf import message as _message +from google.protobuf import reflection as _reflection +from google.protobuf import symbol_database as _symbol_database + +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + +from google.protobuf import descriptor_pb2 as google_dot_protobuf_dot_descriptor__pb2 + +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile( + b'\n!nexusannotations/v1/options.proto\x12\x13nexusannotations.v1\x1a google/protobuf/descriptor.proto".\n\x10OperationOptions\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x0c\n\x04tags\x18\x02 \x03(\t",\n\x0eServiceOptions\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x0c\n\x04tags\x18\x02 \x03(\t:Y\n\x07service\x12\x1f.google.protobuf.ServiceOptions\x18\xa9@ \x01(\x0b\x32#.nexusannotations.v1.ServiceOptions\x88\x01\x01:\\\n\toperation\x12\x1e.google.protobuf.MethodOptions\x18\xaa@ \x01(\x0b\x32%.nexusannotations.v1.OperationOptions\x88\x01\x01\x42\x45ZCgithub.com/nexus-rpc/nexus-proto-annotations/go/nexusannotations/v1b\x06proto3' +) + + +SERVICE_FIELD_NUMBER = 8233 +service = DESCRIPTOR.extensions_by_name["service"] +OPERATION_FIELD_NUMBER = 8234 +operation = DESCRIPTOR.extensions_by_name["operation"] + +_OPERATIONOPTIONS = DESCRIPTOR.message_types_by_name["OperationOptions"] +_SERVICEOPTIONS = DESCRIPTOR.message_types_by_name["ServiceOptions"] +OperationOptions = _reflection.GeneratedProtocolMessageType( + "OperationOptions", + (_message.Message,), + { + "DESCRIPTOR": _OPERATIONOPTIONS, + "__module__": "nexusannotations.v1.options_pb2", + # @@protoc_insertion_point(class_scope:nexusannotations.v1.OperationOptions) + }, +) +_sym_db.RegisterMessage(OperationOptions) + +ServiceOptions = _reflection.GeneratedProtocolMessageType( + "ServiceOptions", + (_message.Message,), + { + "DESCRIPTOR": _SERVICEOPTIONS, + "__module__": "nexusannotations.v1.options_pb2", + # @@protoc_insertion_point(class_scope:nexusannotations.v1.ServiceOptions) + }, +) +_sym_db.RegisterMessage(ServiceOptions) + +if _descriptor._USE_C_DESCRIPTORS == False: + google_dot_protobuf_dot_descriptor__pb2.ServiceOptions.RegisterExtension(service) + google_dot_protobuf_dot_descriptor__pb2.MethodOptions.RegisterExtension(operation) + + DESCRIPTOR._options = None + DESCRIPTOR._serialized_options = ( + b"ZCgithub.com/nexus-rpc/nexus-proto-annotations/go/nexusannotations/v1" + ) + _OPERATIONOPTIONS._serialized_start = 92 + _OPERATIONOPTIONS._serialized_end = 138 + _SERVICEOPTIONS._serialized_start = 140 + _SERVICEOPTIONS._serialized_end = 184 +# @@protoc_insertion_point(module_scope) diff --git a/temporalio/api/dependencies/nexusannotations/v1/options_pb2.pyi b/temporalio/api/dependencies/nexusannotations/v1/options_pb2.pyi new file mode 100644 index 000000000..3c440fb75 --- /dev/null +++ b/temporalio/api/dependencies/nexusannotations/v1/options_pb2.pyi @@ -0,0 +1,78 @@ +""" +@generated by mypy-protobuf. Do not edit manually! +isort:skip_file +""" + +import builtins +import collections.abc +import sys + +import google.protobuf.descriptor +import google.protobuf.descriptor_pb2 +import google.protobuf.internal.containers +import google.protobuf.internal.extension_dict +import google.protobuf.message + +if sys.version_info >= (3, 8): + import typing as typing_extensions +else: + import typing_extensions + +DESCRIPTOR: google.protobuf.descriptor.FileDescriptor + +class OperationOptions(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + NAME_FIELD_NUMBER: builtins.int + TAGS_FIELD_NUMBER: builtins.int + name: builtins.str + """Nexus operation name (defaults to proto method name).""" + @property + def tags( + self, + ) -> google.protobuf.internal.containers.RepeatedScalarFieldContainer[builtins.str]: + """Tags to attach to the operation. Used by code generators to include and exclude operations.""" + def __init__( + self, + *, + name: builtins.str = ..., + tags: collections.abc.Iterable[builtins.str] | None = ..., + ) -> None: ... + def ClearField( + self, field_name: typing_extensions.Literal["name", b"name", "tags", b"tags"] + ) -> None: ... + +global___OperationOptions = OperationOptions + +class ServiceOptions(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + NAME_FIELD_NUMBER: builtins.int + TAGS_FIELD_NUMBER: builtins.int + name: builtins.str + """Nexus service name (defaults to proto service full name).""" + @property + def tags( + self, + ) -> google.protobuf.internal.containers.RepeatedScalarFieldContainer[builtins.str]: + """Tags to attach to the service. Used by code generators to include and exclude services.""" + def __init__( + self, + *, + name: builtins.str = ..., + tags: collections.abc.Iterable[builtins.str] | None = ..., + ) -> None: ... + def ClearField( + self, field_name: typing_extensions.Literal["name", b"name", "tags", b"tags"] + ) -> None: ... + +global___ServiceOptions = ServiceOptions + +SERVICE_FIELD_NUMBER: builtins.int +OPERATION_FIELD_NUMBER: builtins.int +service: google.protobuf.internal.extension_dict._ExtensionFieldDescriptor[ + google.protobuf.descriptor_pb2.ServiceOptions, global___ServiceOptions +] +operation: google.protobuf.internal.extension_dict._ExtensionFieldDescriptor[ + google.protobuf.descriptor_pb2.MethodOptions, global___OperationOptions +] diff --git a/temporalio/api/history/v1/message_pb2.py b/temporalio/api/history/v1/message_pb2.py index 0c22ff973..3d3cd5132 100644 --- a/temporalio/api/history/v1/message_pb2.py +++ b/temporalio/api/history/v1/message_pb2.py @@ -55,7 +55,7 @@ ) DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile( - b'\n%temporal/api/history/v1/message.proto\x12\x17temporal.api.history.v1\x1a\x1egoogle/protobuf/duration.proto\x1a\x1fgoogle/protobuf/timestamp.proto\x1a&temporal/api/enums/v1/event_type.proto\x1a(temporal/api/enums/v1/failed_cause.proto\x1a"temporal/api/enums/v1/update.proto\x1a$temporal/api/enums/v1/workflow.proto\x1a$temporal/api/common/v1/message.proto\x1a(temporal/api/deployment/v1/message.proto\x1a%temporal/api/failure/v1/message.proto\x1a\'temporal/api/taskqueue/v1/message.proto\x1a$temporal/api/update/v1/message.proto\x1a&temporal/api/workflow/v1/message.proto\x1a\x30temporal/api/sdk/v1/task_complete_metadata.proto\x1a\'temporal/api/sdk/v1/user_metadata.proto"\x9a\x12\n\'WorkflowExecutionStartedEventAttributes\x12;\n\rworkflow_type\x18\x01 \x01(\x0b\x32$.temporal.api.common.v1.WorkflowType\x12!\n\x19parent_workflow_namespace\x18\x02 \x01(\t\x12$\n\x1cparent_workflow_namespace_id\x18\x1b \x01(\t\x12L\n\x19parent_workflow_execution\x18\x03 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12!\n\x19parent_initiated_event_id\x18\x04 \x01(\x03\x12\x38\n\ntask_queue\x18\x05 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12/\n\x05input\x18\x06 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12=\n\x1aworkflow_execution_timeout\x18\x07 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x37\n\x14workflow_run_timeout\x18\x08 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x38\n\x15workflow_task_timeout\x18\t \x01(\x0b\x32\x19.google.protobuf.Duration\x12"\n\x1a\x63ontinued_execution_run_id\x18\n \x01(\t\x12@\n\tinitiator\x18\x0b \x01(\x0e\x32-.temporal.api.enums.v1.ContinueAsNewInitiator\x12;\n\x11\x63ontinued_failure\x18\x0c \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12@\n\x16last_completion_result\x18\r \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12!\n\x19original_execution_run_id\x18\x0e \x01(\t\x12\x10\n\x08identity\x18\x0f \x01(\t\x12\x1e\n\x16\x66irst_execution_run_id\x18\x10 \x01(\t\x12\x39\n\x0cretry_policy\x18\x11 \x01(\x0b\x32#.temporal.api.common.v1.RetryPolicy\x12\x0f\n\x07\x61ttempt\x18\x12 \x01(\x05\x12\x46\n"workflow_execution_expiration_time\x18\x13 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x15\n\rcron_schedule\x18\x14 \x01(\t\x12>\n\x1b\x66irst_workflow_task_backoff\x18\x15 \x01(\x0b\x32\x19.google.protobuf.Duration\x12*\n\x04memo\x18\x16 \x01(\x0b\x32\x1c.temporal.api.common.v1.Memo\x12\x43\n\x11search_attributes\x18\x17 \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes\x12\x45\n\x16prev_auto_reset_points\x18\x18 \x01(\x0b\x32%.temporal.api.workflow.v1.ResetPoints\x12.\n\x06header\x18\x19 \x01(\x0b\x32\x1e.temporal.api.common.v1.Header\x12&\n\x1eparent_initiated_event_version\x18\x1a \x01(\x03\x12\x13\n\x0bworkflow_id\x18\x1c \x01(\t\x12L\n\x14source_version_stamp\x18\x1d \x01(\x0b\x32*.temporal.api.common.v1.WorkerVersionStampB\x02\x18\x01\x12>\n\x14\x63ompletion_callbacks\x18\x1e \x03(\x0b\x32 .temporal.api.common.v1.Callback\x12J\n\x17root_workflow_execution\x18\x1f \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x1e\n\x12inherited_build_id\x18 \x01(\tB\x02\x18\x01\x12I\n\x13versioning_override\x18! \x01(\x0b\x32,.temporal.api.workflow.v1.VersioningOverride\x12\x33\n\'parent_pinned_worker_deployment_version\x18" \x01(\tB\x02\x18\x01\x12\x32\n\x08priority\x18# \x01(\x0b\x32 .temporal.api.common.v1.Priority\x12U\n\x18inherited_pinned_version\x18% \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersion\x12Y\n\x1binherited_auto_upgrade_info\x18\' \x01(\x0b\x32\x34.temporal.api.deployment.v1.InheritedAutoUpgradeInfo\x12 \n\x18\x65\x61ger_execution_accepted\x18& \x01(\x08\x12^\n\x1f\x64\x65\x63lined_target_version_upgrade\x18( \x01(\x0b\x32\x35.temporal.api.history.v1.DeclinedTargetVersionUpgrade\x12J\n\x14time_skipping_config\x18) \x01(\x0b\x32,.temporal.api.workflow.v1.TimeSkippingConfig\x12;\n\x18initial_skipped_duration\x18* \x01(\x0b\x32\x19.google.protobuf.DurationJ\x04\x08$\x10%R parent_pinned_deployment_version"\x88\x01\n\x1c\x44\x65\x63linedTargetVersionUpgrade\x12O\n\x12\x64\x65ployment_version\x18\x01 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersion\x12\x17\n\x0frevision_number\x18\x02 \x01(\x03"\xa5\x01\n)WorkflowExecutionCompletedEventAttributes\x12\x30\n\x06result\x18\x01 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12(\n workflow_task_completed_event_id\x18\x02 \x01(\x03\x12\x1c\n\x14new_execution_run_id\x18\x03 \x01(\t"\xdb\x01\n&WorkflowExecutionFailedEventAttributes\x12\x31\n\x07\x66\x61ilure\x18\x01 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12\x36\n\x0bretry_state\x18\x02 \x01(\x0e\x32!.temporal.api.enums.v1.RetryState\x12(\n workflow_task_completed_event_id\x18\x03 \x01(\x03\x12\x1c\n\x14new_execution_run_id\x18\x04 \x01(\t"\x80\x01\n(WorkflowExecutionTimedOutEventAttributes\x12\x36\n\x0bretry_state\x18\x01 \x01(\x0e\x32!.temporal.api.enums.v1.RetryState\x12\x1c\n\x14new_execution_run_id\x18\x02 \x01(\t"\xa5\x07\n.WorkflowExecutionContinuedAsNewEventAttributes\x12\x1c\n\x14new_execution_run_id\x18\x01 \x01(\t\x12;\n\rworkflow_type\x18\x02 \x01(\x0b\x32$.temporal.api.common.v1.WorkflowType\x12\x38\n\ntask_queue\x18\x03 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12/\n\x05input\x18\x04 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x37\n\x14workflow_run_timeout\x18\x05 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x38\n\x15workflow_task_timeout\x18\x06 \x01(\x0b\x32\x19.google.protobuf.Duration\x12(\n workflow_task_completed_event_id\x18\x07 \x01(\x03\x12\x39\n\x16\x62\x61\x63koff_start_interval\x18\x08 \x01(\x0b\x32\x19.google.protobuf.Duration\x12@\n\tinitiator\x18\t \x01(\x0e\x32-.temporal.api.enums.v1.ContinueAsNewInitiator\x12\x35\n\x07\x66\x61ilure\x18\n \x01(\x0b\x32 .temporal.api.failure.v1.FailureB\x02\x18\x01\x12@\n\x16last_completion_result\x18\x0b \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12.\n\x06header\x18\x0c \x01(\x0b\x32\x1e.temporal.api.common.v1.Header\x12*\n\x04memo\x18\r \x01(\x0b\x32\x1c.temporal.api.common.v1.Memo\x12\x43\n\x11search_attributes\x18\x0e \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes\x12\x1c\n\x10inherit_build_id\x18\x0f \x01(\x08\x42\x02\x18\x01\x12[\n\x1binitial_versioning_behavior\x18\x10 \x01(\x0e\x32\x36.temporal.api.enums.v1.ContinueAsNewVersioningBehavior"\xac\x01\n$WorkflowTaskScheduledEventAttributes\x12\x38\n\ntask_queue\x18\x01 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12\x39\n\x16start_to_close_timeout\x18\x02 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x0f\n\x07\x61ttempt\x18\x03 \x01(\x05"\xa0\x03\n"WorkflowTaskStartedEventAttributes\x12\x1a\n\x12scheduled_event_id\x18\x01 \x01(\x03\x12\x10\n\x08identity\x18\x02 \x01(\t\x12\x12\n\nrequest_id\x18\x03 \x01(\t\x12\x1f\n\x17suggest_continue_as_new\x18\x04 \x01(\x08\x12Z\n\x1fsuggest_continue_as_new_reasons\x18\x08 \x03(\x0e\x32\x31.temporal.api.enums.v1.SuggestContinueAsNewReason\x12\x30\n(target_worker_deployment_version_changed\x18\t \x01(\x08\x12\x1a\n\x12history_size_bytes\x18\x05 \x01(\x03\x12\x46\n\x0eworker_version\x18\x06 \x01(\x0b\x32*.temporal.api.common.v1.WorkerVersionStampB\x02\x18\x01\x12%\n\x19\x62uild_id_redirect_counter\x18\x07 \x01(\x03\x42\x02\x18\x01"\x82\x05\n$WorkflowTaskCompletedEventAttributes\x12\x1a\n\x12scheduled_event_id\x18\x01 \x01(\x03\x12\x18\n\x10started_event_id\x18\x02 \x01(\x03\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x1b\n\x0f\x62inary_checksum\x18\x04 \x01(\tB\x02\x18\x01\x12\x46\n\x0eworker_version\x18\x05 \x01(\x0b\x32*.temporal.api.common.v1.WorkerVersionStampB\x02\x18\x01\x12H\n\x0csdk_metadata\x18\x06 \x01(\x0b\x32\x32.temporal.api.sdk.v1.WorkflowTaskCompletedMetadata\x12\x43\n\x11metering_metadata\x18\r \x01(\x0b\x32(.temporal.api.common.v1.MeteringMetadata\x12>\n\ndeployment\x18\x07 \x01(\x0b\x32&.temporal.api.deployment.v1.DeploymentB\x02\x18\x01\x12\x46\n\x13versioning_behavior\x18\x08 \x01(\x0e\x32).temporal.api.enums.v1.VersioningBehavior\x12%\n\x19worker_deployment_version\x18\t \x01(\tB\x02\x18\x01\x12\x1e\n\x16worker_deployment_name\x18\n \x01(\t\x12O\n\x12\x64\x65ployment_version\x18\x0b \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersion"\x95\x01\n#WorkflowTaskTimedOutEventAttributes\x12\x1a\n\x12scheduled_event_id\x18\x01 \x01(\x03\x12\x18\n\x10started_event_id\x18\x02 \x01(\x03\x12\x38\n\x0ctimeout_type\x18\x03 \x01(\x0e\x32".temporal.api.enums.v1.TimeoutType"\x87\x03\n!WorkflowTaskFailedEventAttributes\x12\x1a\n\x12scheduled_event_id\x18\x01 \x01(\x03\x12\x18\n\x10started_event_id\x18\x02 \x01(\x03\x12=\n\x05\x63\x61use\x18\x03 \x01(\x0e\x32..temporal.api.enums.v1.WorkflowTaskFailedCause\x12\x31\n\x07\x66\x61ilure\x18\x04 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12\x10\n\x08identity\x18\x05 \x01(\t\x12\x13\n\x0b\x62\x61se_run_id\x18\x06 \x01(\t\x12\x12\n\nnew_run_id\x18\x07 \x01(\t\x12\x1a\n\x12\x66ork_event_version\x18\x08 \x01(\x03\x12\x1b\n\x0f\x62inary_checksum\x18\t \x01(\tB\x02\x18\x01\x12\x46\n\x0eworker_version\x18\n \x01(\x0b\x32*.temporal.api.common.v1.WorkerVersionStampB\x02\x18\x01"\xc2\x05\n$ActivityTaskScheduledEventAttributes\x12\x13\n\x0b\x61\x63tivity_id\x18\x01 \x01(\t\x12;\n\ractivity_type\x18\x02 \x01(\x0b\x32$.temporal.api.common.v1.ActivityType\x12\x38\n\ntask_queue\x18\x04 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12.\n\x06header\x18\x05 \x01(\x0b\x32\x1e.temporal.api.common.v1.Header\x12/\n\x05input\x18\x06 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12<\n\x19schedule_to_close_timeout\x18\x07 \x01(\x0b\x32\x19.google.protobuf.Duration\x12<\n\x19schedule_to_start_timeout\x18\x08 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x39\n\x16start_to_close_timeout\x18\t \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x34\n\x11heartbeat_timeout\x18\n \x01(\x0b\x32\x19.google.protobuf.Duration\x12(\n workflow_task_completed_event_id\x18\x0b \x01(\x03\x12\x39\n\x0cretry_policy\x18\x0c \x01(\x0b\x32#.temporal.api.common.v1.RetryPolicy\x12!\n\x15use_workflow_build_id\x18\r \x01(\x08\x42\x02\x18\x01\x12\x32\n\x08priority\x18\x0e \x01(\x0b\x32 .temporal.api.common.v1.PriorityJ\x04\x08\x03\x10\x04"\x9e\x02\n"ActivityTaskStartedEventAttributes\x12\x1a\n\x12scheduled_event_id\x18\x01 \x01(\x03\x12\x10\n\x08identity\x18\x02 \x01(\t\x12\x12\n\nrequest_id\x18\x03 \x01(\t\x12\x0f\n\x07\x61ttempt\x18\x04 \x01(\x05\x12\x36\n\x0clast_failure\x18\x05 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12\x46\n\x0eworker_version\x18\x06 \x01(\x0b\x32*.temporal.api.common.v1.WorkerVersionStampB\x02\x18\x01\x12%\n\x19\x62uild_id_redirect_counter\x18\x07 \x01(\x03\x42\x02\x18\x01"\xe8\x01\n$ActivityTaskCompletedEventAttributes\x12\x30\n\x06result\x18\x01 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x1a\n\x12scheduled_event_id\x18\x02 \x01(\x03\x12\x18\n\x10started_event_id\x18\x03 \x01(\x03\x12\x10\n\x08identity\x18\x04 \x01(\t\x12\x46\n\x0eworker_version\x18\x05 \x01(\x0b\x32*.temporal.api.common.v1.WorkerVersionStampB\x02\x18\x01"\x9e\x02\n!ActivityTaskFailedEventAttributes\x12\x31\n\x07\x66\x61ilure\x18\x01 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12\x1a\n\x12scheduled_event_id\x18\x02 \x01(\x03\x12\x18\n\x10started_event_id\x18\x03 \x01(\x03\x12\x10\n\x08identity\x18\x04 \x01(\t\x12\x36\n\x0bretry_state\x18\x05 \x01(\x0e\x32!.temporal.api.enums.v1.RetryState\x12\x46\n\x0eworker_version\x18\x06 \x01(\x0b\x32*.temporal.api.common.v1.WorkerVersionStampB\x02\x18\x01"\xc6\x01\n#ActivityTaskTimedOutEventAttributes\x12\x31\n\x07\x66\x61ilure\x18\x01 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12\x1a\n\x12scheduled_event_id\x18\x02 \x01(\x03\x12\x18\n\x10started_event_id\x18\x03 \x01(\x03\x12\x36\n\x0bretry_state\x18\x04 \x01(\x0e\x32!.temporal.api.enums.v1.RetryState"r\n*ActivityTaskCancelRequestedEventAttributes\x12\x1a\n\x12scheduled_event_id\x18\x01 \x01(\x03\x12(\n workflow_task_completed_event_id\x18\x02 \x01(\x03"\x92\x02\n#ActivityTaskCanceledEventAttributes\x12\x31\n\x07\x64\x65tails\x18\x01 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12(\n latest_cancel_requested_event_id\x18\x02 \x01(\x03\x12\x1a\n\x12scheduled_event_id\x18\x03 \x01(\x03\x12\x18\n\x10started_event_id\x18\x04 \x01(\x03\x12\x10\n\x08identity\x18\x05 \x01(\t\x12\x46\n\x0eworker_version\x18\x06 \x01(\x0b\x32*.temporal.api.common.v1.WorkerVersionStampB\x02\x18\x01"\x93\x01\n\x1bTimerStartedEventAttributes\x12\x10\n\x08timer_id\x18\x01 \x01(\t\x12\x38\n\x15start_to_fire_timeout\x18\x02 \x01(\x0b\x32\x19.google.protobuf.Duration\x12(\n workflow_task_completed_event_id\x18\x03 \x01(\x03"G\n\x19TimerFiredEventAttributes\x12\x10\n\x08timer_id\x18\x01 \x01(\t\x12\x18\n\x10started_event_id\x18\x02 \x01(\x03"\x86\x01\n\x1cTimerCanceledEventAttributes\x12\x10\n\x08timer_id\x18\x01 \x01(\t\x12\x18\n\x10started_event_id\x18\x02 \x01(\x03\x12(\n workflow_task_completed_event_id\x18\x03 \x01(\x03\x12\x10\n\x08identity\x18\x04 \x01(\t"\xc7\x01\n/WorkflowExecutionCancelRequestedEventAttributes\x12\r\n\x05\x63\x61use\x18\x01 \x01(\t\x12#\n\x1b\x65xternal_initiated_event_id\x18\x02 \x01(\x03\x12N\n\x1b\x65xternal_workflow_execution\x18\x03 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x10\n\x08identity\x18\x04 \x01(\t"\x87\x01\n(WorkflowExecutionCanceledEventAttributes\x12(\n workflow_task_completed_event_id\x18\x01 \x01(\x03\x12\x31\n\x07\x64\x65tails\x18\x02 \x01(\x0b\x32 .temporal.api.common.v1.Payloads"\xe9\x02\n\x1dMarkerRecordedEventAttributes\x12\x13\n\x0bmarker_name\x18\x01 \x01(\t\x12T\n\x07\x64\x65tails\x18\x02 \x03(\x0b\x32\x43.temporal.api.history.v1.MarkerRecordedEventAttributes.DetailsEntry\x12(\n workflow_task_completed_event_id\x18\x03 \x01(\x03\x12.\n\x06header\x18\x04 \x01(\x0b\x32\x1e.temporal.api.common.v1.Header\x12\x31\n\x07\x66\x61ilure\x18\x05 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x1aP\n\x0c\x44\x65tailsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12/\n\x05value\x18\x02 \x01(\x0b\x32 .temporal.api.common.v1.Payloads:\x02\x38\x01"\xbf\x02\n(WorkflowExecutionSignaledEventAttributes\x12\x13\n\x0bsignal_name\x18\x01 \x01(\t\x12/\n\x05input\x18\x02 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x10\n\x08identity\x18\x03 \x01(\t\x12.\n\x06header\x18\x04 \x01(\x0b\x32\x1e.temporal.api.common.v1.Header\x12\'\n\x1bskip_generate_workflow_task\x18\x05 \x01(\x08\x42\x02\x18\x01\x12N\n\x1b\x65xternal_workflow_execution\x18\x06 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x12\n\nrequest_id\x18\x07 \x01(\t"\x81\x01\n*WorkflowExecutionTerminatedEventAttributes\x12\x0e\n\x06reason\x18\x01 \x01(\t\x12\x31\n\x07\x64\x65tails\x18\x02 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x10\n\x08identity\x18\x03 \x01(\t"\x9c\x02\n>RequestCancelExternalWorkflowExecutionInitiatedEventAttributes\x12(\n workflow_task_completed_event_id\x18\x01 \x01(\x03\x12\x11\n\tnamespace\x18\x02 \x01(\t\x12\x14\n\x0cnamespace_id\x18\x07 \x01(\t\x12\x45\n\x12workflow_execution\x18\x03 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x13\n\x07\x63ontrol\x18\x04 \x01(\tB\x02\x18\x01\x12\x1b\n\x13\x63hild_workflow_only\x18\x05 \x01(\x08\x12\x0e\n\x06reason\x18\x06 \x01(\t"\xda\x02\n;RequestCancelExternalWorkflowExecutionFailedEventAttributes\x12P\n\x05\x63\x61use\x18\x01 \x01(\x0e\x32\x41.temporal.api.enums.v1.CancelExternalWorkflowExecutionFailedCause\x12(\n workflow_task_completed_event_id\x18\x02 \x01(\x03\x12\x11\n\tnamespace\x18\x03 \x01(\t\x12\x14\n\x0cnamespace_id\x18\x07 \x01(\t\x12\x45\n\x12workflow_execution\x18\x04 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x1a\n\x12initiated_event_id\x18\x05 \x01(\x03\x12\x13\n\x07\x63ontrol\x18\x06 \x01(\tB\x02\x18\x01"\xc5\x01\n7ExternalWorkflowExecutionCancelRequestedEventAttributes\x12\x1a\n\x12initiated_event_id\x18\x01 \x01(\x03\x12\x11\n\tnamespace\x18\x02 \x01(\t\x12\x14\n\x0cnamespace_id\x18\x04 \x01(\t\x12\x45\n\x12workflow_execution\x18\x03 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution"\xfb\x02\n7SignalExternalWorkflowExecutionInitiatedEventAttributes\x12(\n workflow_task_completed_event_id\x18\x01 \x01(\x03\x12\x11\n\tnamespace\x18\x02 \x01(\t\x12\x14\n\x0cnamespace_id\x18\t \x01(\t\x12\x45\n\x12workflow_execution\x18\x03 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x13\n\x0bsignal_name\x18\x04 \x01(\t\x12/\n\x05input\x18\x05 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x13\n\x07\x63ontrol\x18\x06 \x01(\tB\x02\x18\x01\x12\x1b\n\x13\x63hild_workflow_only\x18\x07 \x01(\x08\x12.\n\x06header\x18\x08 \x01(\x0b\x32\x1e.temporal.api.common.v1.Header"\xd3\x02\n4SignalExternalWorkflowExecutionFailedEventAttributes\x12P\n\x05\x63\x61use\x18\x01 \x01(\x0e\x32\x41.temporal.api.enums.v1.SignalExternalWorkflowExecutionFailedCause\x12(\n workflow_task_completed_event_id\x18\x02 \x01(\x03\x12\x11\n\tnamespace\x18\x03 \x01(\t\x12\x14\n\x0cnamespace_id\x18\x07 \x01(\t\x12\x45\n\x12workflow_execution\x18\x04 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x1a\n\x12initiated_event_id\x18\x05 \x01(\x03\x12\x13\n\x07\x63ontrol\x18\x06 \x01(\tB\x02\x18\x01"\xd3\x01\n0ExternalWorkflowExecutionSignaledEventAttributes\x12\x1a\n\x12initiated_event_id\x18\x01 \x01(\x03\x12\x11\n\tnamespace\x18\x02 \x01(\t\x12\x14\n\x0cnamespace_id\x18\x05 \x01(\t\x12\x45\n\x12workflow_execution\x18\x03 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x13\n\x07\x63ontrol\x18\x04 \x01(\tB\x02\x18\x01"\x9e\x01\n-UpsertWorkflowSearchAttributesEventAttributes\x12(\n workflow_task_completed_event_id\x18\x01 \x01(\x03\x12\x43\n\x11search_attributes\x18\x02 \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes"\x8a\x01\n)WorkflowPropertiesModifiedEventAttributes\x12(\n workflow_task_completed_event_id\x18\x01 \x01(\x03\x12\x33\n\rupserted_memo\x18\x02 \x01(\x0b\x32\x1c.temporal.api.common.v1.Memo"\xf1\x08\n3StartChildWorkflowExecutionInitiatedEventAttributes\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x14\n\x0cnamespace_id\x18\x12 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12;\n\rworkflow_type\x18\x03 \x01(\x0b\x32$.temporal.api.common.v1.WorkflowType\x12\x38\n\ntask_queue\x18\x04 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12/\n\x05input\x18\x05 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12=\n\x1aworkflow_execution_timeout\x18\x06 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x37\n\x14workflow_run_timeout\x18\x07 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x38\n\x15workflow_task_timeout\x18\x08 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x45\n\x13parent_close_policy\x18\t \x01(\x0e\x32(.temporal.api.enums.v1.ParentClosePolicy\x12\x13\n\x07\x63ontrol\x18\n \x01(\tB\x02\x18\x01\x12(\n workflow_task_completed_event_id\x18\x0b \x01(\x03\x12N\n\x18workflow_id_reuse_policy\x18\x0c \x01(\x0e\x32,.temporal.api.enums.v1.WorkflowIdReusePolicy\x12\x39\n\x0cretry_policy\x18\r \x01(\x0b\x32#.temporal.api.common.v1.RetryPolicy\x12\x15\n\rcron_schedule\x18\x0e \x01(\t\x12.\n\x06header\x18\x0f \x01(\x0b\x32\x1e.temporal.api.common.v1.Header\x12*\n\x04memo\x18\x10 \x01(\x0b\x32\x1c.temporal.api.common.v1.Memo\x12\x43\n\x11search_attributes\x18\x11 \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes\x12\x1c\n\x10inherit_build_id\x18\x13 \x01(\x08\x42\x02\x18\x01\x12\x32\n\x08priority\x18\x14 \x01(\x0b\x32 .temporal.api.common.v1.Priority\x12J\n\x14time_skipping_config\x18\x15 \x01(\x0b\x32,.temporal.api.workflow.v1.TimeSkippingConfig\x12;\n\x18initial_skipped_duration\x18\x1e \x01(\x0b\x32\x19.google.protobuf.Duration"\xd6\x02\n0StartChildWorkflowExecutionFailedEventAttributes\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x14\n\x0cnamespace_id\x18\x08 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12;\n\rworkflow_type\x18\x03 \x01(\x0b\x32$.temporal.api.common.v1.WorkflowType\x12L\n\x05\x63\x61use\x18\x04 \x01(\x0e\x32=.temporal.api.enums.v1.StartChildWorkflowExecutionFailedCause\x12\x13\n\x07\x63ontrol\x18\x05 \x01(\tB\x02\x18\x01\x12\x1a\n\x12initiated_event_id\x18\x06 \x01(\x03\x12(\n workflow_task_completed_event_id\x18\x07 \x01(\x03"\xa7\x02\n,ChildWorkflowExecutionStartedEventAttributes\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x14\n\x0cnamespace_id\x18\x06 \x01(\t\x12\x1a\n\x12initiated_event_id\x18\x02 \x01(\x03\x12\x45\n\x12workflow_execution\x18\x03 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12;\n\rworkflow_type\x18\x04 \x01(\x0b\x32$.temporal.api.common.v1.WorkflowType\x12.\n\x06header\x18\x05 \x01(\x0b\x32\x1e.temporal.api.common.v1.Header"\xc5\x02\n.ChildWorkflowExecutionCompletedEventAttributes\x12\x30\n\x06result\x18\x01 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x11\n\tnamespace\x18\x02 \x01(\t\x12\x14\n\x0cnamespace_id\x18\x07 \x01(\t\x12\x45\n\x12workflow_execution\x18\x03 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12;\n\rworkflow_type\x18\x04 \x01(\x0b\x32$.temporal.api.common.v1.WorkflowType\x12\x1a\n\x12initiated_event_id\x18\x05 \x01(\x03\x12\x18\n\x10started_event_id\x18\x06 \x01(\x03"\xfb\x02\n+ChildWorkflowExecutionFailedEventAttributes\x12\x31\n\x07\x66\x61ilure\x18\x01 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12\x11\n\tnamespace\x18\x02 \x01(\t\x12\x14\n\x0cnamespace_id\x18\x08 \x01(\t\x12\x45\n\x12workflow_execution\x18\x03 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12;\n\rworkflow_type\x18\x04 \x01(\x0b\x32$.temporal.api.common.v1.WorkflowType\x12\x1a\n\x12initiated_event_id\x18\x05 \x01(\x03\x12\x18\n\x10started_event_id\x18\x06 \x01(\x03\x12\x36\n\x0bretry_state\x18\x07 \x01(\x0e\x32!.temporal.api.enums.v1.RetryState"\xc5\x02\n-ChildWorkflowExecutionCanceledEventAttributes\x12\x31\n\x07\x64\x65tails\x18\x01 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x11\n\tnamespace\x18\x02 \x01(\t\x12\x14\n\x0cnamespace_id\x18\x07 \x01(\t\x12\x45\n\x12workflow_execution\x18\x03 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12;\n\rworkflow_type\x18\x04 \x01(\x0b\x32$.temporal.api.common.v1.WorkflowType\x12\x1a\n\x12initiated_event_id\x18\x05 \x01(\x03\x12\x18\n\x10started_event_id\x18\x06 \x01(\x03"\xca\x02\n-ChildWorkflowExecutionTimedOutEventAttributes\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x14\n\x0cnamespace_id\x18\x07 \x01(\t\x12\x45\n\x12workflow_execution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12;\n\rworkflow_type\x18\x03 \x01(\x0b\x32$.temporal.api.common.v1.WorkflowType\x12\x1a\n\x12initiated_event_id\x18\x04 \x01(\x03\x12\x18\n\x10started_event_id\x18\x05 \x01(\x03\x12\x36\n\x0bretry_state\x18\x06 \x01(\x0e\x32!.temporal.api.enums.v1.RetryState"\x94\x02\n/ChildWorkflowExecutionTerminatedEventAttributes\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x14\n\x0cnamespace_id\x18\x06 \x01(\t\x12\x45\n\x12workflow_execution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12;\n\rworkflow_type\x18\x03 \x01(\x0b\x32$.temporal.api.common.v1.WorkflowType\x12\x1a\n\x12initiated_event_id\x18\x04 \x01(\x03\x12\x18\n\x10started_event_id\x18\x05 \x01(\x03"\x96\x03\n.WorkflowExecutionOptionsUpdatedEventAttributes\x12I\n\x13versioning_override\x18\x01 \x01(\x0b\x32,.temporal.api.workflow.v1.VersioningOverride\x12!\n\x19unset_versioning_override\x18\x02 \x01(\x08\x12\x1b\n\x13\x61ttached_request_id\x18\x03 \x01(\t\x12G\n\x1d\x61ttached_completion_callbacks\x18\x04 \x03(\x0b\x32 .temporal.api.common.v1.Callback\x12\x10\n\x08identity\x18\x05 \x01(\t\x12\x32\n\x08priority\x18\x06 \x01(\x0b\x32 .temporal.api.common.v1.Priority\x12J\n\x14time_skipping_config\x18\x07 \x01(\x0b\x32,.temporal.api.workflow.v1.TimeSkippingConfig"\xc0\x02\n3WorkflowPropertiesModifiedExternallyEventAttributes\x12\x16\n\x0enew_task_queue\x18\x01 \x01(\t\x12<\n\x19new_workflow_task_timeout\x18\x02 \x01(\x0b\x32\x19.google.protobuf.Duration\x12;\n\x18new_workflow_run_timeout\x18\x03 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x41\n\x1enew_workflow_execution_timeout\x18\x04 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x33\n\rupserted_memo\x18\x05 \x01(\x0b\x32\x1c.temporal.api.common.v1.Memo"\x90\x01\n3ActivityPropertiesModifiedExternallyEventAttributes\x12\x1a\n\x12scheduled_event_id\x18\x01 \x01(\x03\x12=\n\x10new_retry_policy\x18\x02 \x01(\x0b\x32#.temporal.api.common.v1.RetryPolicy"\xdc\x01\n.WorkflowExecutionUpdateAcceptedEventAttributes\x12\x1c\n\x14protocol_instance_id\x18\x01 \x01(\t\x12#\n\x1b\x61\x63\x63\x65pted_request_message_id\x18\x02 \x01(\t\x12,\n$accepted_request_sequencing_event_id\x18\x03 \x01(\x03\x12\x39\n\x10\x61\x63\x63\x65pted_request\x18\x04 \x01(\x0b\x32\x1f.temporal.api.update.v1.Request"\xaa\x01\n/WorkflowExecutionUpdateCompletedEventAttributes\x12*\n\x04meta\x18\x01 \x01(\x0b\x32\x1c.temporal.api.update.v1.Meta\x12\x19\n\x11\x61\x63\x63\x65pted_event_id\x18\x03 \x01(\x03\x12\x30\n\x07outcome\x18\x02 \x01(\x0b\x32\x1f.temporal.api.update.v1.Outcome"\x8f\x02\n.WorkflowExecutionUpdateRejectedEventAttributes\x12\x1c\n\x14protocol_instance_id\x18\x01 \x01(\t\x12#\n\x1brejected_request_message_id\x18\x02 \x01(\t\x12,\n$rejected_request_sequencing_event_id\x18\x03 \x01(\x03\x12\x39\n\x10rejected_request\x18\x04 \x01(\x0b\x32\x1f.temporal.api.update.v1.Request\x12\x31\n\x07\x66\x61ilure\x18\x05 \x01(\x0b\x32 .temporal.api.failure.v1.Failure"\xa4\x01\n.WorkflowExecutionUpdateAdmittedEventAttributes\x12\x30\n\x07request\x18\x01 \x01(\x0b\x32\x1f.temporal.api.update.v1.Request\x12@\n\x06origin\x18\x02 \x01(\x0e\x32\x30.temporal.api.enums.v1.UpdateAdmittedEventOrigin"^\n&WorkflowExecutionPausedEventAttributes\x12\x10\n\x08identity\x18\x01 \x01(\t\x12\x0e\n\x06reason\x18\x02 \x01(\t\x12\x12\n\nrequest_id\x18\x03 \x01(\t"`\n(WorkflowExecutionUnpausedEventAttributes\x12\x10\n\x08identity\x18\x01 \x01(\t\x12\x0e\n\x06reason\x18\x02 \x01(\t\x12\x12\n\nrequest_id\x18\x03 \x01(\t"\xbe\x01\n8WorkflowExecutionTimeSkippingTransitionedEventAttributes\x12/\n\x0btarget_time\x18\x01 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x1c\n\x14\x64isabled_after_bound\x18\x02 \x01(\x08\x12\x33\n\x0fwall_clock_time\x18\x03 \x01(\x0b\x32\x1a.google.protobuf.Timestamp"\xb4\x04\n&NexusOperationScheduledEventAttributes\x12\x10\n\x08\x65ndpoint\x18\x01 \x01(\t\x12\x0f\n\x07service\x18\x02 \x01(\t\x12\x11\n\toperation\x18\x03 \x01(\t\x12.\n\x05input\x18\x04 \x01(\x0b\x32\x1f.temporal.api.common.v1.Payload\x12<\n\x19schedule_to_close_timeout\x18\x05 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x66\n\x0cnexus_header\x18\x06 \x03(\x0b\x32P.temporal.api.history.v1.NexusOperationScheduledEventAttributes.NexusHeaderEntry\x12(\n workflow_task_completed_event_id\x18\x07 \x01(\x03\x12\x12\n\nrequest_id\x18\x08 \x01(\t\x12\x13\n\x0b\x65ndpoint_id\x18\t \x01(\t\x12<\n\x19schedule_to_start_timeout\x18\n \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x39\n\x16start_to_close_timeout\x18\x0b \x01(\x0b\x32\x19.google.protobuf.Duration\x1a\x32\n\x10NexusHeaderEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01"\x89\x01\n$NexusOperationStartedEventAttributes\x12\x1a\n\x12scheduled_event_id\x18\x01 \x01(\x03\x12\x18\n\x0coperation_id\x18\x03 \x01(\tB\x02\x18\x01\x12\x12\n\nrequest_id\x18\x04 \x01(\t\x12\x17\n\x0foperation_token\x18\x05 \x01(\t"\x89\x01\n&NexusOperationCompletedEventAttributes\x12\x1a\n\x12scheduled_event_id\x18\x01 \x01(\x03\x12/\n\x06result\x18\x02 \x01(\x0b\x32\x1f.temporal.api.common.v1.Payload\x12\x12\n\nrequest_id\x18\x03 \x01(\t"\x88\x01\n#NexusOperationFailedEventAttributes\x12\x1a\n\x12scheduled_event_id\x18\x01 \x01(\x03\x12\x31\n\x07\x66\x61ilure\x18\x02 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12\x12\n\nrequest_id\x18\x03 \x01(\t"\x8a\x01\n%NexusOperationTimedOutEventAttributes\x12\x1a\n\x12scheduled_event_id\x18\x01 \x01(\x03\x12\x31\n\x07\x66\x61ilure\x18\x02 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12\x12\n\nrequest_id\x18\x03 \x01(\t"\x8a\x01\n%NexusOperationCanceledEventAttributes\x12\x1a\n\x12scheduled_event_id\x18\x01 \x01(\x03\x12\x31\n\x07\x66\x61ilure\x18\x02 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12\x12\n\nrequest_id\x18\x03 \x01(\t"t\n,NexusOperationCancelRequestedEventAttributes\x12\x1a\n\x12scheduled_event_id\x18\x01 \x01(\x03\x12(\n workflow_task_completed_event_id\x18\x02 \x01(\x03"\x97\x01\n3NexusOperationCancelRequestCompletedEventAttributes\x12\x1a\n\x12requested_event_id\x18\x01 \x01(\x03\x12(\n workflow_task_completed_event_id\x18\x02 \x01(\x03\x12\x1a\n\x12scheduled_event_id\x18\x03 \x01(\x03"\xc7\x01\n0NexusOperationCancelRequestFailedEventAttributes\x12\x1a\n\x12requested_event_id\x18\x01 \x01(\x03\x12(\n workflow_task_completed_event_id\x18\x02 \x01(\x03\x12\x31\n\x07\x66\x61ilure\x18\x03 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12\x1a\n\x12scheduled_event_id\x18\x04 \x01(\x03"\x85?\n\x0cHistoryEvent\x12\x10\n\x08\x65vent_id\x18\x01 \x01(\x03\x12.\n\nevent_time\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x34\n\nevent_type\x18\x03 \x01(\x0e\x32 .temporal.api.enums.v1.EventType\x12\x0f\n\x07version\x18\x04 \x01(\x03\x12\x0f\n\x07task_id\x18\x05 \x01(\x03\x12\x1a\n\x11worker_may_ignore\x18\xac\x02 \x01(\x08\x12\x39\n\ruser_metadata\x18\xad\x02 \x01(\x0b\x32!.temporal.api.sdk.v1.UserMetadata\x12,\n\x05links\x18\xae\x02 \x03(\x0b\x32\x1c.temporal.api.common.v1.Link\x12\x35\n\tprincipal\x18\xaf\x02 \x01(\x0b\x32!.temporal.api.common.v1.Principal\x12w\n+workflow_execution_started_event_attributes\x18\x06 \x01(\x0b\x32@.temporal.api.history.v1.WorkflowExecutionStartedEventAttributesH\x00\x12{\n-workflow_execution_completed_event_attributes\x18\x07 \x01(\x0b\x32\x42.temporal.api.history.v1.WorkflowExecutionCompletedEventAttributesH\x00\x12u\n*workflow_execution_failed_event_attributes\x18\x08 \x01(\x0b\x32?.temporal.api.history.v1.WorkflowExecutionFailedEventAttributesH\x00\x12z\n-workflow_execution_timed_out_event_attributes\x18\t \x01(\x0b\x32\x41.temporal.api.history.v1.WorkflowExecutionTimedOutEventAttributesH\x00\x12q\n(workflow_task_scheduled_event_attributes\x18\n \x01(\x0b\x32=.temporal.api.history.v1.WorkflowTaskScheduledEventAttributesH\x00\x12m\n&workflow_task_started_event_attributes\x18\x0b \x01(\x0b\x32;.temporal.api.history.v1.WorkflowTaskStartedEventAttributesH\x00\x12q\n(workflow_task_completed_event_attributes\x18\x0c \x01(\x0b\x32=.temporal.api.history.v1.WorkflowTaskCompletedEventAttributesH\x00\x12p\n(workflow_task_timed_out_event_attributes\x18\r \x01(\x0b\x32<.temporal.api.history.v1.WorkflowTaskTimedOutEventAttributesH\x00\x12k\n%workflow_task_failed_event_attributes\x18\x0e \x01(\x0b\x32:.temporal.api.history.v1.WorkflowTaskFailedEventAttributesH\x00\x12q\n(activity_task_scheduled_event_attributes\x18\x0f \x01(\x0b\x32=.temporal.api.history.v1.ActivityTaskScheduledEventAttributesH\x00\x12m\n&activity_task_started_event_attributes\x18\x10 \x01(\x0b\x32;.temporal.api.history.v1.ActivityTaskStartedEventAttributesH\x00\x12q\n(activity_task_completed_event_attributes\x18\x11 \x01(\x0b\x32=.temporal.api.history.v1.ActivityTaskCompletedEventAttributesH\x00\x12k\n%activity_task_failed_event_attributes\x18\x12 \x01(\x0b\x32:.temporal.api.history.v1.ActivityTaskFailedEventAttributesH\x00\x12p\n(activity_task_timed_out_event_attributes\x18\x13 \x01(\x0b\x32<.temporal.api.history.v1.ActivityTaskTimedOutEventAttributesH\x00\x12^\n\x1etimer_started_event_attributes\x18\x14 \x01(\x0b\x32\x34.temporal.api.history.v1.TimerStartedEventAttributesH\x00\x12Z\n\x1ctimer_fired_event_attributes\x18\x15 \x01(\x0b\x32\x32.temporal.api.history.v1.TimerFiredEventAttributesH\x00\x12~\n/activity_task_cancel_requested_event_attributes\x18\x16 \x01(\x0b\x32\x43.temporal.api.history.v1.ActivityTaskCancelRequestedEventAttributesH\x00\x12o\n\'activity_task_canceled_event_attributes\x18\x17 \x01(\x0b\x32<.temporal.api.history.v1.ActivityTaskCanceledEventAttributesH\x00\x12`\n\x1ftimer_canceled_event_attributes\x18\x18 \x01(\x0b\x32\x35.temporal.api.history.v1.TimerCanceledEventAttributesH\x00\x12\x62\n marker_recorded_event_attributes\x18\x19 \x01(\x0b\x32\x36.temporal.api.history.v1.MarkerRecordedEventAttributesH\x00\x12y\n,workflow_execution_signaled_event_attributes\x18\x1a \x01(\x0b\x32\x41.temporal.api.history.v1.WorkflowExecutionSignaledEventAttributesH\x00\x12}\n.workflow_execution_terminated_event_attributes\x18\x1b \x01(\x0b\x32\x43.temporal.api.history.v1.WorkflowExecutionTerminatedEventAttributesH\x00\x12\x88\x01\n4workflow_execution_cancel_requested_event_attributes\x18\x1c \x01(\x0b\x32H.temporal.api.history.v1.WorkflowExecutionCancelRequestedEventAttributesH\x00\x12y\n,workflow_execution_canceled_event_attributes\x18\x1d \x01(\x0b\x32\x41.temporal.api.history.v1.WorkflowExecutionCanceledEventAttributesH\x00\x12\xa8\x01\nErequest_cancel_external_workflow_execution_initiated_event_attributes\x18\x1e \x01(\x0b\x32W.temporal.api.history.v1.RequestCancelExternalWorkflowExecutionInitiatedEventAttributesH\x00\x12\xa2\x01\nBrequest_cancel_external_workflow_execution_failed_event_attributes\x18\x1f \x01(\x0b\x32T.temporal.api.history.v1.RequestCancelExternalWorkflowExecutionFailedEventAttributesH\x00\x12\x99\x01\n=external_workflow_execution_cancel_requested_event_attributes\x18 \x01(\x0b\x32P.temporal.api.history.v1.ExternalWorkflowExecutionCancelRequestedEventAttributesH\x00\x12\x87\x01\n4workflow_execution_continued_as_new_event_attributes\x18! \x01(\x0b\x32G.temporal.api.history.v1.WorkflowExecutionContinuedAsNewEventAttributesH\x00\x12\x91\x01\n9start_child_workflow_execution_initiated_event_attributes\x18" \x01(\x0b\x32L.temporal.api.history.v1.StartChildWorkflowExecutionInitiatedEventAttributesH\x00\x12\x8b\x01\n6start_child_workflow_execution_failed_event_attributes\x18# \x01(\x0b\x32I.temporal.api.history.v1.StartChildWorkflowExecutionFailedEventAttributesH\x00\x12\x82\x01\n1child_workflow_execution_started_event_attributes\x18$ \x01(\x0b\x32\x45.temporal.api.history.v1.ChildWorkflowExecutionStartedEventAttributesH\x00\x12\x86\x01\n3child_workflow_execution_completed_event_attributes\x18% \x01(\x0b\x32G.temporal.api.history.v1.ChildWorkflowExecutionCompletedEventAttributesH\x00\x12\x80\x01\n0child_workflow_execution_failed_event_attributes\x18& \x01(\x0b\x32\x44.temporal.api.history.v1.ChildWorkflowExecutionFailedEventAttributesH\x00\x12\x84\x01\n2child_workflow_execution_canceled_event_attributes\x18\' \x01(\x0b\x32\x46.temporal.api.history.v1.ChildWorkflowExecutionCanceledEventAttributesH\x00\x12\x85\x01\n3child_workflow_execution_timed_out_event_attributes\x18( \x01(\x0b\x32\x46.temporal.api.history.v1.ChildWorkflowExecutionTimedOutEventAttributesH\x00\x12\x88\x01\n4child_workflow_execution_terminated_event_attributes\x18) \x01(\x0b\x32H.temporal.api.history.v1.ChildWorkflowExecutionTerminatedEventAttributesH\x00\x12\x99\x01\n=signal_external_workflow_execution_initiated_event_attributes\x18* \x01(\x0b\x32P.temporal.api.history.v1.SignalExternalWorkflowExecutionInitiatedEventAttributesH\x00\x12\x93\x01\n:signal_external_workflow_execution_failed_event_attributes\x18+ \x01(\x0b\x32M.temporal.api.history.v1.SignalExternalWorkflowExecutionFailedEventAttributesH\x00\x12\x8a\x01\n5external_workflow_execution_signaled_event_attributes\x18, \x01(\x0b\x32I.temporal.api.history.v1.ExternalWorkflowExecutionSignaledEventAttributesH\x00\x12\x84\x01\n2upsert_workflow_search_attributes_event_attributes\x18- \x01(\x0b\x32\x46.temporal.api.history.v1.UpsertWorkflowSearchAttributesEventAttributesH\x00\x12\x86\x01\n3workflow_execution_update_accepted_event_attributes\x18. \x01(\x0b\x32G.temporal.api.history.v1.WorkflowExecutionUpdateAcceptedEventAttributesH\x00\x12\x86\x01\n3workflow_execution_update_rejected_event_attributes\x18/ \x01(\x0b\x32G.temporal.api.history.v1.WorkflowExecutionUpdateRejectedEventAttributesH\x00\x12\x88\x01\n4workflow_execution_update_completed_event_attributes\x18\x30 \x01(\x0b\x32H.temporal.api.history.v1.WorkflowExecutionUpdateCompletedEventAttributesH\x00\x12\x90\x01\n8workflow_properties_modified_externally_event_attributes\x18\x31 \x01(\x0b\x32L.temporal.api.history.v1.WorkflowPropertiesModifiedExternallyEventAttributesH\x00\x12\x90\x01\n8activity_properties_modified_externally_event_attributes\x18\x32 \x01(\x0b\x32L.temporal.api.history.v1.ActivityPropertiesModifiedExternallyEventAttributesH\x00\x12{\n-workflow_properties_modified_event_attributes\x18\x33 \x01(\x0b\x32\x42.temporal.api.history.v1.WorkflowPropertiesModifiedEventAttributesH\x00\x12\x86\x01\n3workflow_execution_update_admitted_event_attributes\x18\x34 \x01(\x0b\x32G.temporal.api.history.v1.WorkflowExecutionUpdateAdmittedEventAttributesH\x00\x12u\n*nexus_operation_scheduled_event_attributes\x18\x35 \x01(\x0b\x32?.temporal.api.history.v1.NexusOperationScheduledEventAttributesH\x00\x12q\n(nexus_operation_started_event_attributes\x18\x36 \x01(\x0b\x32=.temporal.api.history.v1.NexusOperationStartedEventAttributesH\x00\x12u\n*nexus_operation_completed_event_attributes\x18\x37 \x01(\x0b\x32?.temporal.api.history.v1.NexusOperationCompletedEventAttributesH\x00\x12o\n\'nexus_operation_failed_event_attributes\x18\x38 \x01(\x0b\x32<.temporal.api.history.v1.NexusOperationFailedEventAttributesH\x00\x12s\n)nexus_operation_canceled_event_attributes\x18\x39 \x01(\x0b\x32>.temporal.api.history.v1.NexusOperationCanceledEventAttributesH\x00\x12t\n*nexus_operation_timed_out_event_attributes\x18: \x01(\x0b\x32>.temporal.api.history.v1.NexusOperationTimedOutEventAttributesH\x00\x12\x82\x01\n1nexus_operation_cancel_requested_event_attributes\x18; \x01(\x0b\x32\x45.temporal.api.history.v1.NexusOperationCancelRequestedEventAttributesH\x00\x12\x86\x01\n3workflow_execution_options_updated_event_attributes\x18< \x01(\x0b\x32G.temporal.api.history.v1.WorkflowExecutionOptionsUpdatedEventAttributesH\x00\x12\x91\x01\n9nexus_operation_cancel_request_completed_event_attributes\x18= \x01(\x0b\x32L.temporal.api.history.v1.NexusOperationCancelRequestCompletedEventAttributesH\x00\x12\x8b\x01\n6nexus_operation_cancel_request_failed_event_attributes\x18> \x01(\x0b\x32I.temporal.api.history.v1.NexusOperationCancelRequestFailedEventAttributesH\x00\x12u\n*workflow_execution_paused_event_attributes\x18? \x01(\x0b\x32?.temporal.api.history.v1.WorkflowExecutionPausedEventAttributesH\x00\x12y\n,workflow_execution_unpaused_event_attributes\x18@ \x01(\x0b\x32\x41.temporal.api.history.v1.WorkflowExecutionUnpausedEventAttributesH\x00\x12\x9b\x01\n>workflow_execution_time_skipping_transitioned_event_attributes\x18\x41 \x01(\x0b\x32Q.temporal.api.history.v1.WorkflowExecutionTimeSkippingTransitionedEventAttributesH\x00\x42\x0c\n\nattributes"@\n\x07History\x12\x35\n\x06\x65vents\x18\x01 \x03(\x0b\x32%.temporal.api.history.v1.HistoryEventB\x8e\x01\n\x1aio.temporal.api.history.v1B\x0cMessageProtoP\x01Z%go.temporal.io/api/history/v1;history\xaa\x02\x19Temporalio.Api.History.V1\xea\x02\x1cTemporalio::Api::History::V1b\x06proto3' + b'\n%temporal/api/history/v1/message.proto\x12\x17temporal.api.history.v1\x1a\x1egoogle/protobuf/duration.proto\x1a\x1fgoogle/protobuf/timestamp.proto\x1a&temporal/api/enums/v1/event_type.proto\x1a(temporal/api/enums/v1/failed_cause.proto\x1a"temporal/api/enums/v1/update.proto\x1a$temporal/api/enums/v1/workflow.proto\x1a$temporal/api/common/v1/message.proto\x1a(temporal/api/deployment/v1/message.proto\x1a%temporal/api/failure/v1/message.proto\x1a\'temporal/api/taskqueue/v1/message.proto\x1a$temporal/api/update/v1/message.proto\x1a&temporal/api/workflow/v1/message.proto\x1a\x30temporal/api/sdk/v1/task_complete_metadata.proto\x1a\'temporal/api/sdk/v1/user_metadata.proto"\x9a\x12\n\'WorkflowExecutionStartedEventAttributes\x12;\n\rworkflow_type\x18\x01 \x01(\x0b\x32$.temporal.api.common.v1.WorkflowType\x12!\n\x19parent_workflow_namespace\x18\x02 \x01(\t\x12$\n\x1cparent_workflow_namespace_id\x18\x1b \x01(\t\x12L\n\x19parent_workflow_execution\x18\x03 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12!\n\x19parent_initiated_event_id\x18\x04 \x01(\x03\x12\x38\n\ntask_queue\x18\x05 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12/\n\x05input\x18\x06 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12=\n\x1aworkflow_execution_timeout\x18\x07 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x37\n\x14workflow_run_timeout\x18\x08 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x38\n\x15workflow_task_timeout\x18\t \x01(\x0b\x32\x19.google.protobuf.Duration\x12"\n\x1a\x63ontinued_execution_run_id\x18\n \x01(\t\x12@\n\tinitiator\x18\x0b \x01(\x0e\x32-.temporal.api.enums.v1.ContinueAsNewInitiator\x12;\n\x11\x63ontinued_failure\x18\x0c \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12@\n\x16last_completion_result\x18\r \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12!\n\x19original_execution_run_id\x18\x0e \x01(\t\x12\x10\n\x08identity\x18\x0f \x01(\t\x12\x1e\n\x16\x66irst_execution_run_id\x18\x10 \x01(\t\x12\x39\n\x0cretry_policy\x18\x11 \x01(\x0b\x32#.temporal.api.common.v1.RetryPolicy\x12\x0f\n\x07\x61ttempt\x18\x12 \x01(\x05\x12\x46\n"workflow_execution_expiration_time\x18\x13 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x15\n\rcron_schedule\x18\x14 \x01(\t\x12>\n\x1b\x66irst_workflow_task_backoff\x18\x15 \x01(\x0b\x32\x19.google.protobuf.Duration\x12*\n\x04memo\x18\x16 \x01(\x0b\x32\x1c.temporal.api.common.v1.Memo\x12\x43\n\x11search_attributes\x18\x17 \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes\x12\x45\n\x16prev_auto_reset_points\x18\x18 \x01(\x0b\x32%.temporal.api.workflow.v1.ResetPoints\x12.\n\x06header\x18\x19 \x01(\x0b\x32\x1e.temporal.api.common.v1.Header\x12&\n\x1eparent_initiated_event_version\x18\x1a \x01(\x03\x12\x13\n\x0bworkflow_id\x18\x1c \x01(\t\x12L\n\x14source_version_stamp\x18\x1d \x01(\x0b\x32*.temporal.api.common.v1.WorkerVersionStampB\x02\x18\x01\x12>\n\x14\x63ompletion_callbacks\x18\x1e \x03(\x0b\x32 .temporal.api.common.v1.Callback\x12J\n\x17root_workflow_execution\x18\x1f \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x1e\n\x12inherited_build_id\x18 \x01(\tB\x02\x18\x01\x12I\n\x13versioning_override\x18! \x01(\x0b\x32,.temporal.api.workflow.v1.VersioningOverride\x12\x33\n\'parent_pinned_worker_deployment_version\x18" \x01(\tB\x02\x18\x01\x12\x32\n\x08priority\x18# \x01(\x0b\x32 .temporal.api.common.v1.Priority\x12U\n\x18inherited_pinned_version\x18% \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersion\x12Y\n\x1binherited_auto_upgrade_info\x18\' \x01(\x0b\x32\x34.temporal.api.deployment.v1.InheritedAutoUpgradeInfo\x12 \n\x18\x65\x61ger_execution_accepted\x18& \x01(\x08\x12^\n\x1f\x64\x65\x63lined_target_version_upgrade\x18( \x01(\x0b\x32\x35.temporal.api.history.v1.DeclinedTargetVersionUpgrade\x12J\n\x14time_skipping_config\x18) \x01(\x0b\x32,.temporal.api.workflow.v1.TimeSkippingConfig\x12;\n\x18initial_skipped_duration\x18* \x01(\x0b\x32\x19.google.protobuf.DurationJ\x04\x08$\x10%R parent_pinned_deployment_version"\x88\x01\n\x1c\x44\x65\x63linedTargetVersionUpgrade\x12O\n\x12\x64\x65ployment_version\x18\x01 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersion\x12\x17\n\x0frevision_number\x18\x02 \x01(\x03"\xa5\x01\n)WorkflowExecutionCompletedEventAttributes\x12\x30\n\x06result\x18\x01 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12(\n workflow_task_completed_event_id\x18\x02 \x01(\x03\x12\x1c\n\x14new_execution_run_id\x18\x03 \x01(\t"\xdb\x01\n&WorkflowExecutionFailedEventAttributes\x12\x31\n\x07\x66\x61ilure\x18\x01 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12\x36\n\x0bretry_state\x18\x02 \x01(\x0e\x32!.temporal.api.enums.v1.RetryState\x12(\n workflow_task_completed_event_id\x18\x03 \x01(\x03\x12\x1c\n\x14new_execution_run_id\x18\x04 \x01(\t"\x80\x01\n(WorkflowExecutionTimedOutEventAttributes\x12\x36\n\x0bretry_state\x18\x01 \x01(\x0e\x32!.temporal.api.enums.v1.RetryState\x12\x1c\n\x14new_execution_run_id\x18\x02 \x01(\t"\xa5\x07\n.WorkflowExecutionContinuedAsNewEventAttributes\x12\x1c\n\x14new_execution_run_id\x18\x01 \x01(\t\x12;\n\rworkflow_type\x18\x02 \x01(\x0b\x32$.temporal.api.common.v1.WorkflowType\x12\x38\n\ntask_queue\x18\x03 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12/\n\x05input\x18\x04 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x37\n\x14workflow_run_timeout\x18\x05 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x38\n\x15workflow_task_timeout\x18\x06 \x01(\x0b\x32\x19.google.protobuf.Duration\x12(\n workflow_task_completed_event_id\x18\x07 \x01(\x03\x12\x39\n\x16\x62\x61\x63koff_start_interval\x18\x08 \x01(\x0b\x32\x19.google.protobuf.Duration\x12@\n\tinitiator\x18\t \x01(\x0e\x32-.temporal.api.enums.v1.ContinueAsNewInitiator\x12\x35\n\x07\x66\x61ilure\x18\n \x01(\x0b\x32 .temporal.api.failure.v1.FailureB\x02\x18\x01\x12@\n\x16last_completion_result\x18\x0b \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12.\n\x06header\x18\x0c \x01(\x0b\x32\x1e.temporal.api.common.v1.Header\x12*\n\x04memo\x18\r \x01(\x0b\x32\x1c.temporal.api.common.v1.Memo\x12\x43\n\x11search_attributes\x18\x0e \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes\x12\x1c\n\x10inherit_build_id\x18\x0f \x01(\x08\x42\x02\x18\x01\x12[\n\x1binitial_versioning_behavior\x18\x10 \x01(\x0e\x32\x36.temporal.api.enums.v1.ContinueAsNewVersioningBehavior"\xac\x01\n$WorkflowTaskScheduledEventAttributes\x12\x38\n\ntask_queue\x18\x01 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12\x39\n\x16start_to_close_timeout\x18\x02 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x0f\n\x07\x61ttempt\x18\x03 \x01(\x05"\xa0\x03\n"WorkflowTaskStartedEventAttributes\x12\x1a\n\x12scheduled_event_id\x18\x01 \x01(\x03\x12\x10\n\x08identity\x18\x02 \x01(\t\x12\x12\n\nrequest_id\x18\x03 \x01(\t\x12\x1f\n\x17suggest_continue_as_new\x18\x04 \x01(\x08\x12Z\n\x1fsuggest_continue_as_new_reasons\x18\x08 \x03(\x0e\x32\x31.temporal.api.enums.v1.SuggestContinueAsNewReason\x12\x30\n(target_worker_deployment_version_changed\x18\t \x01(\x08\x12\x1a\n\x12history_size_bytes\x18\x05 \x01(\x03\x12\x46\n\x0eworker_version\x18\x06 \x01(\x0b\x32*.temporal.api.common.v1.WorkerVersionStampB\x02\x18\x01\x12%\n\x19\x62uild_id_redirect_counter\x18\x07 \x01(\x03\x42\x02\x18\x01"\x82\x05\n$WorkflowTaskCompletedEventAttributes\x12\x1a\n\x12scheduled_event_id\x18\x01 \x01(\x03\x12\x18\n\x10started_event_id\x18\x02 \x01(\x03\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x1b\n\x0f\x62inary_checksum\x18\x04 \x01(\tB\x02\x18\x01\x12\x46\n\x0eworker_version\x18\x05 \x01(\x0b\x32*.temporal.api.common.v1.WorkerVersionStampB\x02\x18\x01\x12H\n\x0csdk_metadata\x18\x06 \x01(\x0b\x32\x32.temporal.api.sdk.v1.WorkflowTaskCompletedMetadata\x12\x43\n\x11metering_metadata\x18\r \x01(\x0b\x32(.temporal.api.common.v1.MeteringMetadata\x12>\n\ndeployment\x18\x07 \x01(\x0b\x32&.temporal.api.deployment.v1.DeploymentB\x02\x18\x01\x12\x46\n\x13versioning_behavior\x18\x08 \x01(\x0e\x32).temporal.api.enums.v1.VersioningBehavior\x12%\n\x19worker_deployment_version\x18\t \x01(\tB\x02\x18\x01\x12\x1e\n\x16worker_deployment_name\x18\n \x01(\t\x12O\n\x12\x64\x65ployment_version\x18\x0b \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersion"\x95\x01\n#WorkflowTaskTimedOutEventAttributes\x12\x1a\n\x12scheduled_event_id\x18\x01 \x01(\x03\x12\x18\n\x10started_event_id\x18\x02 \x01(\x03\x12\x38\n\x0ctimeout_type\x18\x03 \x01(\x0e\x32".temporal.api.enums.v1.TimeoutType"\x87\x03\n!WorkflowTaskFailedEventAttributes\x12\x1a\n\x12scheduled_event_id\x18\x01 \x01(\x03\x12\x18\n\x10started_event_id\x18\x02 \x01(\x03\x12=\n\x05\x63\x61use\x18\x03 \x01(\x0e\x32..temporal.api.enums.v1.WorkflowTaskFailedCause\x12\x31\n\x07\x66\x61ilure\x18\x04 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12\x10\n\x08identity\x18\x05 \x01(\t\x12\x13\n\x0b\x62\x61se_run_id\x18\x06 \x01(\t\x12\x12\n\nnew_run_id\x18\x07 \x01(\t\x12\x1a\n\x12\x66ork_event_version\x18\x08 \x01(\x03\x12\x1b\n\x0f\x62inary_checksum\x18\t \x01(\tB\x02\x18\x01\x12\x46\n\x0eworker_version\x18\n \x01(\x0b\x32*.temporal.api.common.v1.WorkerVersionStampB\x02\x18\x01"\xc2\x05\n$ActivityTaskScheduledEventAttributes\x12\x13\n\x0b\x61\x63tivity_id\x18\x01 \x01(\t\x12;\n\ractivity_type\x18\x02 \x01(\x0b\x32$.temporal.api.common.v1.ActivityType\x12\x38\n\ntask_queue\x18\x04 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12.\n\x06header\x18\x05 \x01(\x0b\x32\x1e.temporal.api.common.v1.Header\x12/\n\x05input\x18\x06 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12<\n\x19schedule_to_close_timeout\x18\x07 \x01(\x0b\x32\x19.google.protobuf.Duration\x12<\n\x19schedule_to_start_timeout\x18\x08 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x39\n\x16start_to_close_timeout\x18\t \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x34\n\x11heartbeat_timeout\x18\n \x01(\x0b\x32\x19.google.protobuf.Duration\x12(\n workflow_task_completed_event_id\x18\x0b \x01(\x03\x12\x39\n\x0cretry_policy\x18\x0c \x01(\x0b\x32#.temporal.api.common.v1.RetryPolicy\x12!\n\x15use_workflow_build_id\x18\r \x01(\x08\x42\x02\x18\x01\x12\x32\n\x08priority\x18\x0e \x01(\x0b\x32 .temporal.api.common.v1.PriorityJ\x04\x08\x03\x10\x04"\x9e\x02\n"ActivityTaskStartedEventAttributes\x12\x1a\n\x12scheduled_event_id\x18\x01 \x01(\x03\x12\x10\n\x08identity\x18\x02 \x01(\t\x12\x12\n\nrequest_id\x18\x03 \x01(\t\x12\x0f\n\x07\x61ttempt\x18\x04 \x01(\x05\x12\x36\n\x0clast_failure\x18\x05 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12\x46\n\x0eworker_version\x18\x06 \x01(\x0b\x32*.temporal.api.common.v1.WorkerVersionStampB\x02\x18\x01\x12%\n\x19\x62uild_id_redirect_counter\x18\x07 \x01(\x03\x42\x02\x18\x01"\xe8\x01\n$ActivityTaskCompletedEventAttributes\x12\x30\n\x06result\x18\x01 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x1a\n\x12scheduled_event_id\x18\x02 \x01(\x03\x12\x18\n\x10started_event_id\x18\x03 \x01(\x03\x12\x10\n\x08identity\x18\x04 \x01(\t\x12\x46\n\x0eworker_version\x18\x05 \x01(\x0b\x32*.temporal.api.common.v1.WorkerVersionStampB\x02\x18\x01"\x9e\x02\n!ActivityTaskFailedEventAttributes\x12\x31\n\x07\x66\x61ilure\x18\x01 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12\x1a\n\x12scheduled_event_id\x18\x02 \x01(\x03\x12\x18\n\x10started_event_id\x18\x03 \x01(\x03\x12\x10\n\x08identity\x18\x04 \x01(\t\x12\x36\n\x0bretry_state\x18\x05 \x01(\x0e\x32!.temporal.api.enums.v1.RetryState\x12\x46\n\x0eworker_version\x18\x06 \x01(\x0b\x32*.temporal.api.common.v1.WorkerVersionStampB\x02\x18\x01"\xc6\x01\n#ActivityTaskTimedOutEventAttributes\x12\x31\n\x07\x66\x61ilure\x18\x01 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12\x1a\n\x12scheduled_event_id\x18\x02 \x01(\x03\x12\x18\n\x10started_event_id\x18\x03 \x01(\x03\x12\x36\n\x0bretry_state\x18\x04 \x01(\x0e\x32!.temporal.api.enums.v1.RetryState"r\n*ActivityTaskCancelRequestedEventAttributes\x12\x1a\n\x12scheduled_event_id\x18\x01 \x01(\x03\x12(\n workflow_task_completed_event_id\x18\x02 \x01(\x03"\x92\x02\n#ActivityTaskCanceledEventAttributes\x12\x31\n\x07\x64\x65tails\x18\x01 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12(\n latest_cancel_requested_event_id\x18\x02 \x01(\x03\x12\x1a\n\x12scheduled_event_id\x18\x03 \x01(\x03\x12\x18\n\x10started_event_id\x18\x04 \x01(\x03\x12\x10\n\x08identity\x18\x05 \x01(\t\x12\x46\n\x0eworker_version\x18\x06 \x01(\x0b\x32*.temporal.api.common.v1.WorkerVersionStampB\x02\x18\x01"\x93\x01\n\x1bTimerStartedEventAttributes\x12\x10\n\x08timer_id\x18\x01 \x01(\t\x12\x38\n\x15start_to_fire_timeout\x18\x02 \x01(\x0b\x32\x19.google.protobuf.Duration\x12(\n workflow_task_completed_event_id\x18\x03 \x01(\x03"G\n\x19TimerFiredEventAttributes\x12\x10\n\x08timer_id\x18\x01 \x01(\t\x12\x18\n\x10started_event_id\x18\x02 \x01(\x03"\x86\x01\n\x1cTimerCanceledEventAttributes\x12\x10\n\x08timer_id\x18\x01 \x01(\t\x12\x18\n\x10started_event_id\x18\x02 \x01(\x03\x12(\n workflow_task_completed_event_id\x18\x03 \x01(\x03\x12\x10\n\x08identity\x18\x04 \x01(\t"\xc7\x01\n/WorkflowExecutionCancelRequestedEventAttributes\x12\r\n\x05\x63\x61use\x18\x01 \x01(\t\x12#\n\x1b\x65xternal_initiated_event_id\x18\x02 \x01(\x03\x12N\n\x1b\x65xternal_workflow_execution\x18\x03 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x10\n\x08identity\x18\x04 \x01(\t"\x87\x01\n(WorkflowExecutionCanceledEventAttributes\x12(\n workflow_task_completed_event_id\x18\x01 \x01(\x03\x12\x31\n\x07\x64\x65tails\x18\x02 \x01(\x0b\x32 .temporal.api.common.v1.Payloads"\xe9\x02\n\x1dMarkerRecordedEventAttributes\x12\x13\n\x0bmarker_name\x18\x01 \x01(\t\x12T\n\x07\x64\x65tails\x18\x02 \x03(\x0b\x32\x43.temporal.api.history.v1.MarkerRecordedEventAttributes.DetailsEntry\x12(\n workflow_task_completed_event_id\x18\x03 \x01(\x03\x12.\n\x06header\x18\x04 \x01(\x0b\x32\x1e.temporal.api.common.v1.Header\x12\x31\n\x07\x66\x61ilure\x18\x05 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x1aP\n\x0c\x44\x65tailsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12/\n\x05value\x18\x02 \x01(\x0b\x32 .temporal.api.common.v1.Payloads:\x02\x38\x01"\xbf\x02\n(WorkflowExecutionSignaledEventAttributes\x12\x13\n\x0bsignal_name\x18\x01 \x01(\t\x12/\n\x05input\x18\x02 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x10\n\x08identity\x18\x03 \x01(\t\x12.\n\x06header\x18\x04 \x01(\x0b\x32\x1e.temporal.api.common.v1.Header\x12\'\n\x1bskip_generate_workflow_task\x18\x05 \x01(\x08\x42\x02\x18\x01\x12N\n\x1b\x65xternal_workflow_execution\x18\x06 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x12\n\nrequest_id\x18\x07 \x01(\t"\x81\x01\n*WorkflowExecutionTerminatedEventAttributes\x12\x0e\n\x06reason\x18\x01 \x01(\t\x12\x31\n\x07\x64\x65tails\x18\x02 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x10\n\x08identity\x18\x03 \x01(\t"\x9c\x02\n>RequestCancelExternalWorkflowExecutionInitiatedEventAttributes\x12(\n workflow_task_completed_event_id\x18\x01 \x01(\x03\x12\x11\n\tnamespace\x18\x02 \x01(\t\x12\x14\n\x0cnamespace_id\x18\x07 \x01(\t\x12\x45\n\x12workflow_execution\x18\x03 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x13\n\x07\x63ontrol\x18\x04 \x01(\tB\x02\x18\x01\x12\x1b\n\x13\x63hild_workflow_only\x18\x05 \x01(\x08\x12\x0e\n\x06reason\x18\x06 \x01(\t"\xda\x02\n;RequestCancelExternalWorkflowExecutionFailedEventAttributes\x12P\n\x05\x63\x61use\x18\x01 \x01(\x0e\x32\x41.temporal.api.enums.v1.CancelExternalWorkflowExecutionFailedCause\x12(\n workflow_task_completed_event_id\x18\x02 \x01(\x03\x12\x11\n\tnamespace\x18\x03 \x01(\t\x12\x14\n\x0cnamespace_id\x18\x07 \x01(\t\x12\x45\n\x12workflow_execution\x18\x04 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x1a\n\x12initiated_event_id\x18\x05 \x01(\x03\x12\x13\n\x07\x63ontrol\x18\x06 \x01(\tB\x02\x18\x01"\xc5\x01\n7ExternalWorkflowExecutionCancelRequestedEventAttributes\x12\x1a\n\x12initiated_event_id\x18\x01 \x01(\x03\x12\x11\n\tnamespace\x18\x02 \x01(\t\x12\x14\n\x0cnamespace_id\x18\x04 \x01(\t\x12\x45\n\x12workflow_execution\x18\x03 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution"\xfb\x02\n7SignalExternalWorkflowExecutionInitiatedEventAttributes\x12(\n workflow_task_completed_event_id\x18\x01 \x01(\x03\x12\x11\n\tnamespace\x18\x02 \x01(\t\x12\x14\n\x0cnamespace_id\x18\t \x01(\t\x12\x45\n\x12workflow_execution\x18\x03 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x13\n\x0bsignal_name\x18\x04 \x01(\t\x12/\n\x05input\x18\x05 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x13\n\x07\x63ontrol\x18\x06 \x01(\tB\x02\x18\x01\x12\x1b\n\x13\x63hild_workflow_only\x18\x07 \x01(\x08\x12.\n\x06header\x18\x08 \x01(\x0b\x32\x1e.temporal.api.common.v1.Header"\xd3\x02\n4SignalExternalWorkflowExecutionFailedEventAttributes\x12P\n\x05\x63\x61use\x18\x01 \x01(\x0e\x32\x41.temporal.api.enums.v1.SignalExternalWorkflowExecutionFailedCause\x12(\n workflow_task_completed_event_id\x18\x02 \x01(\x03\x12\x11\n\tnamespace\x18\x03 \x01(\t\x12\x14\n\x0cnamespace_id\x18\x07 \x01(\t\x12\x45\n\x12workflow_execution\x18\x04 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x1a\n\x12initiated_event_id\x18\x05 \x01(\x03\x12\x13\n\x07\x63ontrol\x18\x06 \x01(\tB\x02\x18\x01"\xd3\x01\n0ExternalWorkflowExecutionSignaledEventAttributes\x12\x1a\n\x12initiated_event_id\x18\x01 \x01(\x03\x12\x11\n\tnamespace\x18\x02 \x01(\t\x12\x14\n\x0cnamespace_id\x18\x05 \x01(\t\x12\x45\n\x12workflow_execution\x18\x03 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x13\n\x07\x63ontrol\x18\x04 \x01(\tB\x02\x18\x01"\x9e\x01\n-UpsertWorkflowSearchAttributesEventAttributes\x12(\n workflow_task_completed_event_id\x18\x01 \x01(\x03\x12\x43\n\x11search_attributes\x18\x02 \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes"\x8a\x01\n)WorkflowPropertiesModifiedEventAttributes\x12(\n workflow_task_completed_event_id\x18\x01 \x01(\x03\x12\x33\n\rupserted_memo\x18\x02 \x01(\x0b\x32\x1c.temporal.api.common.v1.Memo"\xf1\x08\n3StartChildWorkflowExecutionInitiatedEventAttributes\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x14\n\x0cnamespace_id\x18\x12 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12;\n\rworkflow_type\x18\x03 \x01(\x0b\x32$.temporal.api.common.v1.WorkflowType\x12\x38\n\ntask_queue\x18\x04 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12/\n\x05input\x18\x05 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12=\n\x1aworkflow_execution_timeout\x18\x06 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x37\n\x14workflow_run_timeout\x18\x07 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x38\n\x15workflow_task_timeout\x18\x08 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x45\n\x13parent_close_policy\x18\t \x01(\x0e\x32(.temporal.api.enums.v1.ParentClosePolicy\x12\x13\n\x07\x63ontrol\x18\n \x01(\tB\x02\x18\x01\x12(\n workflow_task_completed_event_id\x18\x0b \x01(\x03\x12N\n\x18workflow_id_reuse_policy\x18\x0c \x01(\x0e\x32,.temporal.api.enums.v1.WorkflowIdReusePolicy\x12\x39\n\x0cretry_policy\x18\r \x01(\x0b\x32#.temporal.api.common.v1.RetryPolicy\x12\x15\n\rcron_schedule\x18\x0e \x01(\t\x12.\n\x06header\x18\x0f \x01(\x0b\x32\x1e.temporal.api.common.v1.Header\x12*\n\x04memo\x18\x10 \x01(\x0b\x32\x1c.temporal.api.common.v1.Memo\x12\x43\n\x11search_attributes\x18\x11 \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes\x12\x1c\n\x10inherit_build_id\x18\x13 \x01(\x08\x42\x02\x18\x01\x12\x32\n\x08priority\x18\x14 \x01(\x0b\x32 .temporal.api.common.v1.Priority\x12J\n\x14time_skipping_config\x18\x15 \x01(\x0b\x32,.temporal.api.workflow.v1.TimeSkippingConfig\x12;\n\x18initial_skipped_duration\x18\x1e \x01(\x0b\x32\x19.google.protobuf.Duration"\xd6\x02\n0StartChildWorkflowExecutionFailedEventAttributes\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x14\n\x0cnamespace_id\x18\x08 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12;\n\rworkflow_type\x18\x03 \x01(\x0b\x32$.temporal.api.common.v1.WorkflowType\x12L\n\x05\x63\x61use\x18\x04 \x01(\x0e\x32=.temporal.api.enums.v1.StartChildWorkflowExecutionFailedCause\x12\x13\n\x07\x63ontrol\x18\x05 \x01(\tB\x02\x18\x01\x12\x1a\n\x12initiated_event_id\x18\x06 \x01(\x03\x12(\n workflow_task_completed_event_id\x18\x07 \x01(\x03"\xa7\x02\n,ChildWorkflowExecutionStartedEventAttributes\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x14\n\x0cnamespace_id\x18\x06 \x01(\t\x12\x1a\n\x12initiated_event_id\x18\x02 \x01(\x03\x12\x45\n\x12workflow_execution\x18\x03 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12;\n\rworkflow_type\x18\x04 \x01(\x0b\x32$.temporal.api.common.v1.WorkflowType\x12.\n\x06header\x18\x05 \x01(\x0b\x32\x1e.temporal.api.common.v1.Header"\xc5\x02\n.ChildWorkflowExecutionCompletedEventAttributes\x12\x30\n\x06result\x18\x01 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x11\n\tnamespace\x18\x02 \x01(\t\x12\x14\n\x0cnamespace_id\x18\x07 \x01(\t\x12\x45\n\x12workflow_execution\x18\x03 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12;\n\rworkflow_type\x18\x04 \x01(\x0b\x32$.temporal.api.common.v1.WorkflowType\x12\x1a\n\x12initiated_event_id\x18\x05 \x01(\x03\x12\x18\n\x10started_event_id\x18\x06 \x01(\x03"\xfb\x02\n+ChildWorkflowExecutionFailedEventAttributes\x12\x31\n\x07\x66\x61ilure\x18\x01 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12\x11\n\tnamespace\x18\x02 \x01(\t\x12\x14\n\x0cnamespace_id\x18\x08 \x01(\t\x12\x45\n\x12workflow_execution\x18\x03 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12;\n\rworkflow_type\x18\x04 \x01(\x0b\x32$.temporal.api.common.v1.WorkflowType\x12\x1a\n\x12initiated_event_id\x18\x05 \x01(\x03\x12\x18\n\x10started_event_id\x18\x06 \x01(\x03\x12\x36\n\x0bretry_state\x18\x07 \x01(\x0e\x32!.temporal.api.enums.v1.RetryState"\xc5\x02\n-ChildWorkflowExecutionCanceledEventAttributes\x12\x31\n\x07\x64\x65tails\x18\x01 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x11\n\tnamespace\x18\x02 \x01(\t\x12\x14\n\x0cnamespace_id\x18\x07 \x01(\t\x12\x45\n\x12workflow_execution\x18\x03 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12;\n\rworkflow_type\x18\x04 \x01(\x0b\x32$.temporal.api.common.v1.WorkflowType\x12\x1a\n\x12initiated_event_id\x18\x05 \x01(\x03\x12\x18\n\x10started_event_id\x18\x06 \x01(\x03"\xca\x02\n-ChildWorkflowExecutionTimedOutEventAttributes\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x14\n\x0cnamespace_id\x18\x07 \x01(\t\x12\x45\n\x12workflow_execution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12;\n\rworkflow_type\x18\x03 \x01(\x0b\x32$.temporal.api.common.v1.WorkflowType\x12\x1a\n\x12initiated_event_id\x18\x04 \x01(\x03\x12\x18\n\x10started_event_id\x18\x05 \x01(\x03\x12\x36\n\x0bretry_state\x18\x06 \x01(\x0e\x32!.temporal.api.enums.v1.RetryState"\x94\x02\n/ChildWorkflowExecutionTerminatedEventAttributes\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x14\n\x0cnamespace_id\x18\x06 \x01(\t\x12\x45\n\x12workflow_execution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12;\n\rworkflow_type\x18\x03 \x01(\x0b\x32$.temporal.api.common.v1.WorkflowType\x12\x1a\n\x12initiated_event_id\x18\x04 \x01(\x03\x12\x18\n\x10started_event_id\x18\x05 \x01(\x03"\xb6\x05\n.WorkflowExecutionOptionsUpdatedEventAttributes\x12I\n\x13versioning_override\x18\x01 \x01(\x0b\x32,.temporal.api.workflow.v1.VersioningOverride\x12!\n\x19unset_versioning_override\x18\x02 \x01(\x08\x12\x1b\n\x13\x61ttached_request_id\x18\x03 \x01(\t\x12G\n\x1d\x61ttached_completion_callbacks\x18\x04 \x03(\x0b\x32 .temporal.api.common.v1.Callback\x12\x10\n\x08identity\x18\x05 \x01(\t\x12\x32\n\x08priority\x18\x06 \x01(\x0b\x32 .temporal.api.common.v1.Priority\x12J\n\x14time_skipping_config\x18\x07 \x01(\x0b\x32,.temporal.api.workflow.v1.TimeSkippingConfig\x12\x84\x01\n\x17workflow_update_options\x18\x08 \x03(\x0b\x32\x63.temporal.api.history.v1.WorkflowExecutionOptionsUpdatedEventAttributes.WorkflowUpdateOptionsUpdate\x1a\x96\x01\n\x1bWorkflowUpdateOptionsUpdate\x12\x11\n\tupdate_id\x18\x01 \x01(\t\x12\x1b\n\x13\x61ttached_request_id\x18\x02 \x01(\t\x12G\n\x1d\x61ttached_completion_callbacks\x18\x03 \x03(\x0b\x32 .temporal.api.common.v1.Callback"\xc0\x02\n3WorkflowPropertiesModifiedExternallyEventAttributes\x12\x16\n\x0enew_task_queue\x18\x01 \x01(\t\x12<\n\x19new_workflow_task_timeout\x18\x02 \x01(\x0b\x32\x19.google.protobuf.Duration\x12;\n\x18new_workflow_run_timeout\x18\x03 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x41\n\x1enew_workflow_execution_timeout\x18\x04 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x33\n\rupserted_memo\x18\x05 \x01(\x0b\x32\x1c.temporal.api.common.v1.Memo"\x90\x01\n3ActivityPropertiesModifiedExternallyEventAttributes\x12\x1a\n\x12scheduled_event_id\x18\x01 \x01(\x03\x12=\n\x10new_retry_policy\x18\x02 \x01(\x0b\x32#.temporal.api.common.v1.RetryPolicy"\xdc\x01\n.WorkflowExecutionUpdateAcceptedEventAttributes\x12\x1c\n\x14protocol_instance_id\x18\x01 \x01(\t\x12#\n\x1b\x61\x63\x63\x65pted_request_message_id\x18\x02 \x01(\t\x12,\n$accepted_request_sequencing_event_id\x18\x03 \x01(\x03\x12\x39\n\x10\x61\x63\x63\x65pted_request\x18\x04 \x01(\x0b\x32\x1f.temporal.api.update.v1.Request"\xaa\x01\n/WorkflowExecutionUpdateCompletedEventAttributes\x12*\n\x04meta\x18\x01 \x01(\x0b\x32\x1c.temporal.api.update.v1.Meta\x12\x19\n\x11\x61\x63\x63\x65pted_event_id\x18\x03 \x01(\x03\x12\x30\n\x07outcome\x18\x02 \x01(\x0b\x32\x1f.temporal.api.update.v1.Outcome"\x8f\x02\n.WorkflowExecutionUpdateRejectedEventAttributes\x12\x1c\n\x14protocol_instance_id\x18\x01 \x01(\t\x12#\n\x1brejected_request_message_id\x18\x02 \x01(\t\x12,\n$rejected_request_sequencing_event_id\x18\x03 \x01(\x03\x12\x39\n\x10rejected_request\x18\x04 \x01(\x0b\x32\x1f.temporal.api.update.v1.Request\x12\x31\n\x07\x66\x61ilure\x18\x05 \x01(\x0b\x32 .temporal.api.failure.v1.Failure"\xa4\x01\n.WorkflowExecutionUpdateAdmittedEventAttributes\x12\x30\n\x07request\x18\x01 \x01(\x0b\x32\x1f.temporal.api.update.v1.Request\x12@\n\x06origin\x18\x02 \x01(\x0e\x32\x30.temporal.api.enums.v1.UpdateAdmittedEventOrigin"^\n&WorkflowExecutionPausedEventAttributes\x12\x10\n\x08identity\x18\x01 \x01(\t\x12\x0e\n\x06reason\x18\x02 \x01(\t\x12\x12\n\nrequest_id\x18\x03 \x01(\t"`\n(WorkflowExecutionUnpausedEventAttributes\x12\x10\n\x08identity\x18\x01 \x01(\t\x12\x0e\n\x06reason\x18\x02 \x01(\t\x12\x12\n\nrequest_id\x18\x03 \x01(\t"\xbe\x01\n8WorkflowExecutionTimeSkippingTransitionedEventAttributes\x12/\n\x0btarget_time\x18\x01 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x1c\n\x14\x64isabled_after_bound\x18\x02 \x01(\x08\x12\x33\n\x0fwall_clock_time\x18\x03 \x01(\x0b\x32\x1a.google.protobuf.Timestamp"\xb4\x04\n&NexusOperationScheduledEventAttributes\x12\x10\n\x08\x65ndpoint\x18\x01 \x01(\t\x12\x0f\n\x07service\x18\x02 \x01(\t\x12\x11\n\toperation\x18\x03 \x01(\t\x12.\n\x05input\x18\x04 \x01(\x0b\x32\x1f.temporal.api.common.v1.Payload\x12<\n\x19schedule_to_close_timeout\x18\x05 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x66\n\x0cnexus_header\x18\x06 \x03(\x0b\x32P.temporal.api.history.v1.NexusOperationScheduledEventAttributes.NexusHeaderEntry\x12(\n workflow_task_completed_event_id\x18\x07 \x01(\x03\x12\x12\n\nrequest_id\x18\x08 \x01(\t\x12\x13\n\x0b\x65ndpoint_id\x18\t \x01(\t\x12<\n\x19schedule_to_start_timeout\x18\n \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x39\n\x16start_to_close_timeout\x18\x0b \x01(\x0b\x32\x19.google.protobuf.Duration\x1a\x32\n\x10NexusHeaderEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01"\x89\x01\n$NexusOperationStartedEventAttributes\x12\x1a\n\x12scheduled_event_id\x18\x01 \x01(\x03\x12\x18\n\x0coperation_id\x18\x03 \x01(\tB\x02\x18\x01\x12\x12\n\nrequest_id\x18\x04 \x01(\t\x12\x17\n\x0foperation_token\x18\x05 \x01(\t"\x89\x01\n&NexusOperationCompletedEventAttributes\x12\x1a\n\x12scheduled_event_id\x18\x01 \x01(\x03\x12/\n\x06result\x18\x02 \x01(\x0b\x32\x1f.temporal.api.common.v1.Payload\x12\x12\n\nrequest_id\x18\x03 \x01(\t"\x88\x01\n#NexusOperationFailedEventAttributes\x12\x1a\n\x12scheduled_event_id\x18\x01 \x01(\x03\x12\x31\n\x07\x66\x61ilure\x18\x02 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12\x12\n\nrequest_id\x18\x03 \x01(\t"\x8a\x01\n%NexusOperationTimedOutEventAttributes\x12\x1a\n\x12scheduled_event_id\x18\x01 \x01(\x03\x12\x31\n\x07\x66\x61ilure\x18\x02 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12\x12\n\nrequest_id\x18\x03 \x01(\t"\x8a\x01\n%NexusOperationCanceledEventAttributes\x12\x1a\n\x12scheduled_event_id\x18\x01 \x01(\x03\x12\x31\n\x07\x66\x61ilure\x18\x02 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12\x12\n\nrequest_id\x18\x03 \x01(\t"t\n,NexusOperationCancelRequestedEventAttributes\x12\x1a\n\x12scheduled_event_id\x18\x01 \x01(\x03\x12(\n workflow_task_completed_event_id\x18\x02 \x01(\x03"\x97\x01\n3NexusOperationCancelRequestCompletedEventAttributes\x12\x1a\n\x12requested_event_id\x18\x01 \x01(\x03\x12(\n workflow_task_completed_event_id\x18\x02 \x01(\x03\x12\x1a\n\x12scheduled_event_id\x18\x03 \x01(\x03"\xc7\x01\n0NexusOperationCancelRequestFailedEventAttributes\x12\x1a\n\x12requested_event_id\x18\x01 \x01(\x03\x12(\n workflow_task_completed_event_id\x18\x02 \x01(\x03\x12\x31\n\x07\x66\x61ilure\x18\x03 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12\x1a\n\x12scheduled_event_id\x18\x04 \x01(\x03"\x85?\n\x0cHistoryEvent\x12\x10\n\x08\x65vent_id\x18\x01 \x01(\x03\x12.\n\nevent_time\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x34\n\nevent_type\x18\x03 \x01(\x0e\x32 .temporal.api.enums.v1.EventType\x12\x0f\n\x07version\x18\x04 \x01(\x03\x12\x0f\n\x07task_id\x18\x05 \x01(\x03\x12\x1a\n\x11worker_may_ignore\x18\xac\x02 \x01(\x08\x12\x39\n\ruser_metadata\x18\xad\x02 \x01(\x0b\x32!.temporal.api.sdk.v1.UserMetadata\x12,\n\x05links\x18\xae\x02 \x03(\x0b\x32\x1c.temporal.api.common.v1.Link\x12\x35\n\tprincipal\x18\xaf\x02 \x01(\x0b\x32!.temporal.api.common.v1.Principal\x12w\n+workflow_execution_started_event_attributes\x18\x06 \x01(\x0b\x32@.temporal.api.history.v1.WorkflowExecutionStartedEventAttributesH\x00\x12{\n-workflow_execution_completed_event_attributes\x18\x07 \x01(\x0b\x32\x42.temporal.api.history.v1.WorkflowExecutionCompletedEventAttributesH\x00\x12u\n*workflow_execution_failed_event_attributes\x18\x08 \x01(\x0b\x32?.temporal.api.history.v1.WorkflowExecutionFailedEventAttributesH\x00\x12z\n-workflow_execution_timed_out_event_attributes\x18\t \x01(\x0b\x32\x41.temporal.api.history.v1.WorkflowExecutionTimedOutEventAttributesH\x00\x12q\n(workflow_task_scheduled_event_attributes\x18\n \x01(\x0b\x32=.temporal.api.history.v1.WorkflowTaskScheduledEventAttributesH\x00\x12m\n&workflow_task_started_event_attributes\x18\x0b \x01(\x0b\x32;.temporal.api.history.v1.WorkflowTaskStartedEventAttributesH\x00\x12q\n(workflow_task_completed_event_attributes\x18\x0c \x01(\x0b\x32=.temporal.api.history.v1.WorkflowTaskCompletedEventAttributesH\x00\x12p\n(workflow_task_timed_out_event_attributes\x18\r \x01(\x0b\x32<.temporal.api.history.v1.WorkflowTaskTimedOutEventAttributesH\x00\x12k\n%workflow_task_failed_event_attributes\x18\x0e \x01(\x0b\x32:.temporal.api.history.v1.WorkflowTaskFailedEventAttributesH\x00\x12q\n(activity_task_scheduled_event_attributes\x18\x0f \x01(\x0b\x32=.temporal.api.history.v1.ActivityTaskScheduledEventAttributesH\x00\x12m\n&activity_task_started_event_attributes\x18\x10 \x01(\x0b\x32;.temporal.api.history.v1.ActivityTaskStartedEventAttributesH\x00\x12q\n(activity_task_completed_event_attributes\x18\x11 \x01(\x0b\x32=.temporal.api.history.v1.ActivityTaskCompletedEventAttributesH\x00\x12k\n%activity_task_failed_event_attributes\x18\x12 \x01(\x0b\x32:.temporal.api.history.v1.ActivityTaskFailedEventAttributesH\x00\x12p\n(activity_task_timed_out_event_attributes\x18\x13 \x01(\x0b\x32<.temporal.api.history.v1.ActivityTaskTimedOutEventAttributesH\x00\x12^\n\x1etimer_started_event_attributes\x18\x14 \x01(\x0b\x32\x34.temporal.api.history.v1.TimerStartedEventAttributesH\x00\x12Z\n\x1ctimer_fired_event_attributes\x18\x15 \x01(\x0b\x32\x32.temporal.api.history.v1.TimerFiredEventAttributesH\x00\x12~\n/activity_task_cancel_requested_event_attributes\x18\x16 \x01(\x0b\x32\x43.temporal.api.history.v1.ActivityTaskCancelRequestedEventAttributesH\x00\x12o\n\'activity_task_canceled_event_attributes\x18\x17 \x01(\x0b\x32<.temporal.api.history.v1.ActivityTaskCanceledEventAttributesH\x00\x12`\n\x1ftimer_canceled_event_attributes\x18\x18 \x01(\x0b\x32\x35.temporal.api.history.v1.TimerCanceledEventAttributesH\x00\x12\x62\n marker_recorded_event_attributes\x18\x19 \x01(\x0b\x32\x36.temporal.api.history.v1.MarkerRecordedEventAttributesH\x00\x12y\n,workflow_execution_signaled_event_attributes\x18\x1a \x01(\x0b\x32\x41.temporal.api.history.v1.WorkflowExecutionSignaledEventAttributesH\x00\x12}\n.workflow_execution_terminated_event_attributes\x18\x1b \x01(\x0b\x32\x43.temporal.api.history.v1.WorkflowExecutionTerminatedEventAttributesH\x00\x12\x88\x01\n4workflow_execution_cancel_requested_event_attributes\x18\x1c \x01(\x0b\x32H.temporal.api.history.v1.WorkflowExecutionCancelRequestedEventAttributesH\x00\x12y\n,workflow_execution_canceled_event_attributes\x18\x1d \x01(\x0b\x32\x41.temporal.api.history.v1.WorkflowExecutionCanceledEventAttributesH\x00\x12\xa8\x01\nErequest_cancel_external_workflow_execution_initiated_event_attributes\x18\x1e \x01(\x0b\x32W.temporal.api.history.v1.RequestCancelExternalWorkflowExecutionInitiatedEventAttributesH\x00\x12\xa2\x01\nBrequest_cancel_external_workflow_execution_failed_event_attributes\x18\x1f \x01(\x0b\x32T.temporal.api.history.v1.RequestCancelExternalWorkflowExecutionFailedEventAttributesH\x00\x12\x99\x01\n=external_workflow_execution_cancel_requested_event_attributes\x18 \x01(\x0b\x32P.temporal.api.history.v1.ExternalWorkflowExecutionCancelRequestedEventAttributesH\x00\x12\x87\x01\n4workflow_execution_continued_as_new_event_attributes\x18! \x01(\x0b\x32G.temporal.api.history.v1.WorkflowExecutionContinuedAsNewEventAttributesH\x00\x12\x91\x01\n9start_child_workflow_execution_initiated_event_attributes\x18" \x01(\x0b\x32L.temporal.api.history.v1.StartChildWorkflowExecutionInitiatedEventAttributesH\x00\x12\x8b\x01\n6start_child_workflow_execution_failed_event_attributes\x18# \x01(\x0b\x32I.temporal.api.history.v1.StartChildWorkflowExecutionFailedEventAttributesH\x00\x12\x82\x01\n1child_workflow_execution_started_event_attributes\x18$ \x01(\x0b\x32\x45.temporal.api.history.v1.ChildWorkflowExecutionStartedEventAttributesH\x00\x12\x86\x01\n3child_workflow_execution_completed_event_attributes\x18% \x01(\x0b\x32G.temporal.api.history.v1.ChildWorkflowExecutionCompletedEventAttributesH\x00\x12\x80\x01\n0child_workflow_execution_failed_event_attributes\x18& \x01(\x0b\x32\x44.temporal.api.history.v1.ChildWorkflowExecutionFailedEventAttributesH\x00\x12\x84\x01\n2child_workflow_execution_canceled_event_attributes\x18\' \x01(\x0b\x32\x46.temporal.api.history.v1.ChildWorkflowExecutionCanceledEventAttributesH\x00\x12\x85\x01\n3child_workflow_execution_timed_out_event_attributes\x18( \x01(\x0b\x32\x46.temporal.api.history.v1.ChildWorkflowExecutionTimedOutEventAttributesH\x00\x12\x88\x01\n4child_workflow_execution_terminated_event_attributes\x18) \x01(\x0b\x32H.temporal.api.history.v1.ChildWorkflowExecutionTerminatedEventAttributesH\x00\x12\x99\x01\n=signal_external_workflow_execution_initiated_event_attributes\x18* \x01(\x0b\x32P.temporal.api.history.v1.SignalExternalWorkflowExecutionInitiatedEventAttributesH\x00\x12\x93\x01\n:signal_external_workflow_execution_failed_event_attributes\x18+ \x01(\x0b\x32M.temporal.api.history.v1.SignalExternalWorkflowExecutionFailedEventAttributesH\x00\x12\x8a\x01\n5external_workflow_execution_signaled_event_attributes\x18, \x01(\x0b\x32I.temporal.api.history.v1.ExternalWorkflowExecutionSignaledEventAttributesH\x00\x12\x84\x01\n2upsert_workflow_search_attributes_event_attributes\x18- \x01(\x0b\x32\x46.temporal.api.history.v1.UpsertWorkflowSearchAttributesEventAttributesH\x00\x12\x86\x01\n3workflow_execution_update_accepted_event_attributes\x18. \x01(\x0b\x32G.temporal.api.history.v1.WorkflowExecutionUpdateAcceptedEventAttributesH\x00\x12\x86\x01\n3workflow_execution_update_rejected_event_attributes\x18/ \x01(\x0b\x32G.temporal.api.history.v1.WorkflowExecutionUpdateRejectedEventAttributesH\x00\x12\x88\x01\n4workflow_execution_update_completed_event_attributes\x18\x30 \x01(\x0b\x32H.temporal.api.history.v1.WorkflowExecutionUpdateCompletedEventAttributesH\x00\x12\x90\x01\n8workflow_properties_modified_externally_event_attributes\x18\x31 \x01(\x0b\x32L.temporal.api.history.v1.WorkflowPropertiesModifiedExternallyEventAttributesH\x00\x12\x90\x01\n8activity_properties_modified_externally_event_attributes\x18\x32 \x01(\x0b\x32L.temporal.api.history.v1.ActivityPropertiesModifiedExternallyEventAttributesH\x00\x12{\n-workflow_properties_modified_event_attributes\x18\x33 \x01(\x0b\x32\x42.temporal.api.history.v1.WorkflowPropertiesModifiedEventAttributesH\x00\x12\x86\x01\n3workflow_execution_update_admitted_event_attributes\x18\x34 \x01(\x0b\x32G.temporal.api.history.v1.WorkflowExecutionUpdateAdmittedEventAttributesH\x00\x12u\n*nexus_operation_scheduled_event_attributes\x18\x35 \x01(\x0b\x32?.temporal.api.history.v1.NexusOperationScheduledEventAttributesH\x00\x12q\n(nexus_operation_started_event_attributes\x18\x36 \x01(\x0b\x32=.temporal.api.history.v1.NexusOperationStartedEventAttributesH\x00\x12u\n*nexus_operation_completed_event_attributes\x18\x37 \x01(\x0b\x32?.temporal.api.history.v1.NexusOperationCompletedEventAttributesH\x00\x12o\n\'nexus_operation_failed_event_attributes\x18\x38 \x01(\x0b\x32<.temporal.api.history.v1.NexusOperationFailedEventAttributesH\x00\x12s\n)nexus_operation_canceled_event_attributes\x18\x39 \x01(\x0b\x32>.temporal.api.history.v1.NexusOperationCanceledEventAttributesH\x00\x12t\n*nexus_operation_timed_out_event_attributes\x18: \x01(\x0b\x32>.temporal.api.history.v1.NexusOperationTimedOutEventAttributesH\x00\x12\x82\x01\n1nexus_operation_cancel_requested_event_attributes\x18; \x01(\x0b\x32\x45.temporal.api.history.v1.NexusOperationCancelRequestedEventAttributesH\x00\x12\x86\x01\n3workflow_execution_options_updated_event_attributes\x18< \x01(\x0b\x32G.temporal.api.history.v1.WorkflowExecutionOptionsUpdatedEventAttributesH\x00\x12\x91\x01\n9nexus_operation_cancel_request_completed_event_attributes\x18= \x01(\x0b\x32L.temporal.api.history.v1.NexusOperationCancelRequestCompletedEventAttributesH\x00\x12\x8b\x01\n6nexus_operation_cancel_request_failed_event_attributes\x18> \x01(\x0b\x32I.temporal.api.history.v1.NexusOperationCancelRequestFailedEventAttributesH\x00\x12u\n*workflow_execution_paused_event_attributes\x18? \x01(\x0b\x32?.temporal.api.history.v1.WorkflowExecutionPausedEventAttributesH\x00\x12y\n,workflow_execution_unpaused_event_attributes\x18@ \x01(\x0b\x32\x41.temporal.api.history.v1.WorkflowExecutionUnpausedEventAttributesH\x00\x12\x9b\x01\n>workflow_execution_time_skipping_transitioned_event_attributes\x18\x41 \x01(\x0b\x32Q.temporal.api.history.v1.WorkflowExecutionTimeSkippingTransitionedEventAttributesH\x00\x42\x0c\n\nattributes"@\n\x07History\x12\x35\n\x06\x65vents\x18\x01 \x03(\x0b\x32%.temporal.api.history.v1.HistoryEventB\x8e\x01\n\x1aio.temporal.api.history.v1B\x0cMessageProtoP\x01Z%go.temporal.io/api/history/v1;history\xaa\x02\x19Temporalio.Api.History.V1\xea\x02\x1cTemporalio::Api::History::V1b\x06proto3' ) @@ -201,6 +201,11 @@ _WORKFLOWEXECUTIONOPTIONSUPDATEDEVENTATTRIBUTES = DESCRIPTOR.message_types_by_name[ "WorkflowExecutionOptionsUpdatedEventAttributes" ] +_WORKFLOWEXECUTIONOPTIONSUPDATEDEVENTATTRIBUTES_WORKFLOWUPDATEOPTIONSUPDATE = ( + _WORKFLOWEXECUTIONOPTIONSUPDATEDEVENTATTRIBUTES.nested_types_by_name[ + "WorkflowUpdateOptionsUpdate" + ] +) _WORKFLOWPROPERTIESMODIFIEDEXTERNALLYEVENTATTRIBUTES = DESCRIPTOR.message_types_by_name[ "WorkflowPropertiesModifiedExternallyEventAttributes" ] @@ -762,18 +767,28 @@ ) _sym_db.RegisterMessage(ChildWorkflowExecutionTerminatedEventAttributes) -WorkflowExecutionOptionsUpdatedEventAttributes = ( - _reflection.GeneratedProtocolMessageType( - "WorkflowExecutionOptionsUpdatedEventAttributes", - (_message.Message,), - { - "DESCRIPTOR": _WORKFLOWEXECUTIONOPTIONSUPDATEDEVENTATTRIBUTES, - "__module__": "temporalio.api.history.v1.message_pb2", - # @@protoc_insertion_point(class_scope:temporal.api.history.v1.WorkflowExecutionOptionsUpdatedEventAttributes) - }, - ) +WorkflowExecutionOptionsUpdatedEventAttributes = _reflection.GeneratedProtocolMessageType( + "WorkflowExecutionOptionsUpdatedEventAttributes", + (_message.Message,), + { + "WorkflowUpdateOptionsUpdate": _reflection.GeneratedProtocolMessageType( + "WorkflowUpdateOptionsUpdate", + (_message.Message,), + { + "DESCRIPTOR": _WORKFLOWEXECUTIONOPTIONSUPDATEDEVENTATTRIBUTES_WORKFLOWUPDATEOPTIONSUPDATE, + "__module__": "temporalio.api.history.v1.message_pb2", + # @@protoc_insertion_point(class_scope:temporal.api.history.v1.WorkflowExecutionOptionsUpdatedEventAttributes.WorkflowUpdateOptionsUpdate) + }, + ), + "DESCRIPTOR": _WORKFLOWEXECUTIONOPTIONSUPDATEDEVENTATTRIBUTES, + "__module__": "temporalio.api.history.v1.message_pb2", + # @@protoc_insertion_point(class_scope:temporal.api.history.v1.WorkflowExecutionOptionsUpdatedEventAttributes) + }, ) _sym_db.RegisterMessage(WorkflowExecutionOptionsUpdatedEventAttributes) +_sym_db.RegisterMessage( + WorkflowExecutionOptionsUpdatedEventAttributes.WorkflowUpdateOptionsUpdate +) WorkflowPropertiesModifiedExternallyEventAttributes = ( _reflection.GeneratedProtocolMessageType( @@ -1283,47 +1298,49 @@ _CHILDWORKFLOWEXECUTIONTERMINATEDEVENTATTRIBUTES._serialized_start = 15195 _CHILDWORKFLOWEXECUTIONTERMINATEDEVENTATTRIBUTES._serialized_end = 15471 _WORKFLOWEXECUTIONOPTIONSUPDATEDEVENTATTRIBUTES._serialized_start = 15474 - _WORKFLOWEXECUTIONOPTIONSUPDATEDEVENTATTRIBUTES._serialized_end = 15880 - _WORKFLOWPROPERTIESMODIFIEDEXTERNALLYEVENTATTRIBUTES._serialized_start = 15883 - _WORKFLOWPROPERTIESMODIFIEDEXTERNALLYEVENTATTRIBUTES._serialized_end = 16203 - _ACTIVITYPROPERTIESMODIFIEDEXTERNALLYEVENTATTRIBUTES._serialized_start = 16206 - _ACTIVITYPROPERTIESMODIFIEDEXTERNALLYEVENTATTRIBUTES._serialized_end = 16350 - _WORKFLOWEXECUTIONUPDATEACCEPTEDEVENTATTRIBUTES._serialized_start = 16353 - _WORKFLOWEXECUTIONUPDATEACCEPTEDEVENTATTRIBUTES._serialized_end = 16573 - _WORKFLOWEXECUTIONUPDATECOMPLETEDEVENTATTRIBUTES._serialized_start = 16576 - _WORKFLOWEXECUTIONUPDATECOMPLETEDEVENTATTRIBUTES._serialized_end = 16746 - _WORKFLOWEXECUTIONUPDATEREJECTEDEVENTATTRIBUTES._serialized_start = 16749 - _WORKFLOWEXECUTIONUPDATEREJECTEDEVENTATTRIBUTES._serialized_end = 17020 - _WORKFLOWEXECUTIONUPDATEADMITTEDEVENTATTRIBUTES._serialized_start = 17023 - _WORKFLOWEXECUTIONUPDATEADMITTEDEVENTATTRIBUTES._serialized_end = 17187 - _WORKFLOWEXECUTIONPAUSEDEVENTATTRIBUTES._serialized_start = 17189 - _WORKFLOWEXECUTIONPAUSEDEVENTATTRIBUTES._serialized_end = 17283 - _WORKFLOWEXECUTIONUNPAUSEDEVENTATTRIBUTES._serialized_start = 17285 - _WORKFLOWEXECUTIONUNPAUSEDEVENTATTRIBUTES._serialized_end = 17381 - _WORKFLOWEXECUTIONTIMESKIPPINGTRANSITIONEDEVENTATTRIBUTES._serialized_start = 17384 - _WORKFLOWEXECUTIONTIMESKIPPINGTRANSITIONEDEVENTATTRIBUTES._serialized_end = 17574 - _NEXUSOPERATIONSCHEDULEDEVENTATTRIBUTES._serialized_start = 17577 - _NEXUSOPERATIONSCHEDULEDEVENTATTRIBUTES._serialized_end = 18141 - _NEXUSOPERATIONSCHEDULEDEVENTATTRIBUTES_NEXUSHEADERENTRY._serialized_start = 18091 - _NEXUSOPERATIONSCHEDULEDEVENTATTRIBUTES_NEXUSHEADERENTRY._serialized_end = 18141 - _NEXUSOPERATIONSTARTEDEVENTATTRIBUTES._serialized_start = 18144 - _NEXUSOPERATIONSTARTEDEVENTATTRIBUTES._serialized_end = 18281 - _NEXUSOPERATIONCOMPLETEDEVENTATTRIBUTES._serialized_start = 18284 - _NEXUSOPERATIONCOMPLETEDEVENTATTRIBUTES._serialized_end = 18421 - _NEXUSOPERATIONFAILEDEVENTATTRIBUTES._serialized_start = 18424 - _NEXUSOPERATIONFAILEDEVENTATTRIBUTES._serialized_end = 18560 - _NEXUSOPERATIONTIMEDOUTEVENTATTRIBUTES._serialized_start = 18563 - _NEXUSOPERATIONTIMEDOUTEVENTATTRIBUTES._serialized_end = 18701 - _NEXUSOPERATIONCANCELEDEVENTATTRIBUTES._serialized_start = 18704 - _NEXUSOPERATIONCANCELEDEVENTATTRIBUTES._serialized_end = 18842 - _NEXUSOPERATIONCANCELREQUESTEDEVENTATTRIBUTES._serialized_start = 18844 - _NEXUSOPERATIONCANCELREQUESTEDEVENTATTRIBUTES._serialized_end = 18960 - _NEXUSOPERATIONCANCELREQUESTCOMPLETEDEVENTATTRIBUTES._serialized_start = 18963 - _NEXUSOPERATIONCANCELREQUESTCOMPLETEDEVENTATTRIBUTES._serialized_end = 19114 - _NEXUSOPERATIONCANCELREQUESTFAILEDEVENTATTRIBUTES._serialized_start = 19117 - _NEXUSOPERATIONCANCELREQUESTFAILEDEVENTATTRIBUTES._serialized_end = 19316 - _HISTORYEVENT._serialized_start = 19319 - _HISTORYEVENT._serialized_end = 27388 - _HISTORY._serialized_start = 27390 - _HISTORY._serialized_end = 27454 + _WORKFLOWEXECUTIONOPTIONSUPDATEDEVENTATTRIBUTES._serialized_end = 16168 + _WORKFLOWEXECUTIONOPTIONSUPDATEDEVENTATTRIBUTES_WORKFLOWUPDATEOPTIONSUPDATE._serialized_start = 16018 + _WORKFLOWEXECUTIONOPTIONSUPDATEDEVENTATTRIBUTES_WORKFLOWUPDATEOPTIONSUPDATE._serialized_end = 16168 + _WORKFLOWPROPERTIESMODIFIEDEXTERNALLYEVENTATTRIBUTES._serialized_start = 16171 + _WORKFLOWPROPERTIESMODIFIEDEXTERNALLYEVENTATTRIBUTES._serialized_end = 16491 + _ACTIVITYPROPERTIESMODIFIEDEXTERNALLYEVENTATTRIBUTES._serialized_start = 16494 + _ACTIVITYPROPERTIESMODIFIEDEXTERNALLYEVENTATTRIBUTES._serialized_end = 16638 + _WORKFLOWEXECUTIONUPDATEACCEPTEDEVENTATTRIBUTES._serialized_start = 16641 + _WORKFLOWEXECUTIONUPDATEACCEPTEDEVENTATTRIBUTES._serialized_end = 16861 + _WORKFLOWEXECUTIONUPDATECOMPLETEDEVENTATTRIBUTES._serialized_start = 16864 + _WORKFLOWEXECUTIONUPDATECOMPLETEDEVENTATTRIBUTES._serialized_end = 17034 + _WORKFLOWEXECUTIONUPDATEREJECTEDEVENTATTRIBUTES._serialized_start = 17037 + _WORKFLOWEXECUTIONUPDATEREJECTEDEVENTATTRIBUTES._serialized_end = 17308 + _WORKFLOWEXECUTIONUPDATEADMITTEDEVENTATTRIBUTES._serialized_start = 17311 + _WORKFLOWEXECUTIONUPDATEADMITTEDEVENTATTRIBUTES._serialized_end = 17475 + _WORKFLOWEXECUTIONPAUSEDEVENTATTRIBUTES._serialized_start = 17477 + _WORKFLOWEXECUTIONPAUSEDEVENTATTRIBUTES._serialized_end = 17571 + _WORKFLOWEXECUTIONUNPAUSEDEVENTATTRIBUTES._serialized_start = 17573 + _WORKFLOWEXECUTIONUNPAUSEDEVENTATTRIBUTES._serialized_end = 17669 + _WORKFLOWEXECUTIONTIMESKIPPINGTRANSITIONEDEVENTATTRIBUTES._serialized_start = 17672 + _WORKFLOWEXECUTIONTIMESKIPPINGTRANSITIONEDEVENTATTRIBUTES._serialized_end = 17862 + _NEXUSOPERATIONSCHEDULEDEVENTATTRIBUTES._serialized_start = 17865 + _NEXUSOPERATIONSCHEDULEDEVENTATTRIBUTES._serialized_end = 18429 + _NEXUSOPERATIONSCHEDULEDEVENTATTRIBUTES_NEXUSHEADERENTRY._serialized_start = 18379 + _NEXUSOPERATIONSCHEDULEDEVENTATTRIBUTES_NEXUSHEADERENTRY._serialized_end = 18429 + _NEXUSOPERATIONSTARTEDEVENTATTRIBUTES._serialized_start = 18432 + _NEXUSOPERATIONSTARTEDEVENTATTRIBUTES._serialized_end = 18569 + _NEXUSOPERATIONCOMPLETEDEVENTATTRIBUTES._serialized_start = 18572 + _NEXUSOPERATIONCOMPLETEDEVENTATTRIBUTES._serialized_end = 18709 + _NEXUSOPERATIONFAILEDEVENTATTRIBUTES._serialized_start = 18712 + _NEXUSOPERATIONFAILEDEVENTATTRIBUTES._serialized_end = 18848 + _NEXUSOPERATIONTIMEDOUTEVENTATTRIBUTES._serialized_start = 18851 + _NEXUSOPERATIONTIMEDOUTEVENTATTRIBUTES._serialized_end = 18989 + _NEXUSOPERATIONCANCELEDEVENTATTRIBUTES._serialized_start = 18992 + _NEXUSOPERATIONCANCELEDEVENTATTRIBUTES._serialized_end = 19130 + _NEXUSOPERATIONCANCELREQUESTEDEVENTATTRIBUTES._serialized_start = 19132 + _NEXUSOPERATIONCANCELREQUESTEDEVENTATTRIBUTES._serialized_end = 19248 + _NEXUSOPERATIONCANCELREQUESTCOMPLETEDEVENTATTRIBUTES._serialized_start = 19251 + _NEXUSOPERATIONCANCELREQUESTCOMPLETEDEVENTATTRIBUTES._serialized_end = 19402 + _NEXUSOPERATIONCANCELREQUESTFAILEDEVENTATTRIBUTES._serialized_start = 19405 + _NEXUSOPERATIONCANCELREQUESTFAILEDEVENTATTRIBUTES._serialized_end = 19604 + _HISTORYEVENT._serialized_start = 19607 + _HISTORYEVENT._serialized_end = 27676 + _HISTORY._serialized_start = 27678 + _HISTORY._serialized_end = 27742 # @@protoc_insertion_point(module_scope) diff --git a/temporalio/api/history/v1/message_pb2.pyi b/temporalio/api/history/v1/message_pb2.pyi index a8f57b30c..26a4aa8a7 100644 --- a/temporalio/api/history/v1/message_pb2.pyi +++ b/temporalio/api/history/v1/message_pb2.pyi @@ -3320,6 +3320,47 @@ global___ChildWorkflowExecutionTerminatedEventAttributes = ( class WorkflowExecutionOptionsUpdatedEventAttributes(google.protobuf.message.Message): DESCRIPTOR: google.protobuf.descriptor.Descriptor + class WorkflowUpdateOptionsUpdate(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + UPDATE_ID_FIELD_NUMBER: builtins.int + ATTACHED_REQUEST_ID_FIELD_NUMBER: builtins.int + ATTACHED_COMPLETION_CALLBACKS_FIELD_NUMBER: builtins.int + update_id: builtins.str + """The ID of the workflow update this update options update corresponds to.""" + attached_request_id: builtins.str + """Request ID attached to the running workflow update so that subsequent requests with same + request ID will be deduped + """ + @property + def attached_completion_callbacks( + self, + ) -> google.protobuf.internal.containers.RepeatedCompositeFieldContainer[ + temporalio.api.common.v1.message_pb2.Callback + ]: + """Completion callbacks attached to the running workflow update.""" + def __init__( + self, + *, + update_id: builtins.str = ..., + attached_request_id: builtins.str = ..., + attached_completion_callbacks: collections.abc.Iterable[ + temporalio.api.common.v1.message_pb2.Callback + ] + | None = ..., + ) -> None: ... + def ClearField( + self, + field_name: typing_extensions.Literal[ + "attached_completion_callbacks", + b"attached_completion_callbacks", + "attached_request_id", + b"attached_request_id", + "update_id", + b"update_id", + ], + ) -> None: ... + VERSIONING_OVERRIDE_FIELD_NUMBER: builtins.int UNSET_VERSIONING_OVERRIDE_FIELD_NUMBER: builtins.int ATTACHED_REQUEST_ID_FIELD_NUMBER: builtins.int @@ -3327,6 +3368,7 @@ class WorkflowExecutionOptionsUpdatedEventAttributes(google.protobuf.message.Mes IDENTITY_FIELD_NUMBER: builtins.int PRIORITY_FIELD_NUMBER: builtins.int TIME_SKIPPING_CONFIG_FIELD_NUMBER: builtins.int + WORKFLOW_UPDATE_OPTIONS_FIELD_NUMBER: builtins.int @property def versioning_override( self, @@ -3359,6 +3401,13 @@ class WorkflowExecutionOptionsUpdatedEventAttributes(google.protobuf.message.Mes self, ) -> temporalio.api.workflow.v1.message_pb2.TimeSkippingConfig: """If set, the time-skipping configuration was changed. Contains the full updated configuration.""" + @property + def workflow_update_options( + self, + ) -> google.protobuf.internal.containers.RepeatedCompositeFieldContainer[ + global___WorkflowExecutionOptionsUpdatedEventAttributes.WorkflowUpdateOptionsUpdate + ]: + """Updates to workflow updates options.""" def __init__( self, *, @@ -3374,6 +3423,10 @@ class WorkflowExecutionOptionsUpdatedEventAttributes(google.protobuf.message.Mes priority: temporalio.api.common.v1.message_pb2.Priority | None = ..., time_skipping_config: temporalio.api.workflow.v1.message_pb2.TimeSkippingConfig | None = ..., + workflow_update_options: collections.abc.Iterable[ + global___WorkflowExecutionOptionsUpdatedEventAttributes.WorkflowUpdateOptionsUpdate + ] + | None = ..., ) -> None: ... def HasField( self, @@ -3403,6 +3456,8 @@ class WorkflowExecutionOptionsUpdatedEventAttributes(google.protobuf.message.Mes b"unset_versioning_override", "versioning_override", b"versioning_override", + "workflow_update_options", + b"workflow_update_options", ], ) -> None: ... diff --git a/temporalio/api/namespace/v1/message_pb2.py b/temporalio/api/namespace/v1/message_pb2.py index b0f0b6bff..4c7018307 100644 --- a/temporalio/api/namespace/v1/message_pb2.py +++ b/temporalio/api/namespace/v1/message_pb2.py @@ -22,7 +22,7 @@ ) DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile( - b'\n\'temporal/api/namespace/v1/message.proto\x12\x19temporal.api.namespace.v1\x1a\x1egoogle/protobuf/duration.proto\x1a\x1fgoogle/protobuf/timestamp.proto\x1a%temporal/api/enums/v1/namespace.proto"\xa1\x06\n\rNamespaceInfo\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x34\n\x05state\x18\x02 \x01(\x0e\x32%.temporal.api.enums.v1.NamespaceState\x12\x13\n\x0b\x64\x65scription\x18\x03 \x01(\t\x12\x13\n\x0bowner_email\x18\x04 \x01(\t\x12@\n\x04\x64\x61ta\x18\x05 \x03(\x0b\x32\x32.temporal.api.namespace.v1.NamespaceInfo.DataEntry\x12\n\n\x02id\x18\x06 \x01(\t\x12K\n\x0c\x63\x61pabilities\x18\x07 \x01(\x0b\x32\x35.temporal.api.namespace.v1.NamespaceInfo.Capabilities\x12?\n\x06limits\x18\x08 \x01(\x0b\x32/.temporal.api.namespace.v1.NamespaceInfo.Limits\x12\x1a\n\x12supports_schedules\x18\x64 \x01(\x08\x1a+\n\tDataEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x1a\xb4\x02\n\x0c\x43\x61pabilities\x12\x1c\n\x14\x65\x61ger_workflow_start\x18\x01 \x01(\x08\x12\x13\n\x0bsync_update\x18\x02 \x01(\x08\x12\x14\n\x0c\x61sync_update\x18\x03 \x01(\x08\x12\x19\n\x11worker_heartbeats\x18\x04 \x01(\x08\x12*\n"reported_problems_search_attribute\x18\x05 \x01(\x08\x12\x16\n\x0eworkflow_pause\x18\x06 \x01(\x08\x12\x1d\n\x15standalone_activities\x18\x07 \x01(\x08\x12(\n worker_poll_complete_on_shutdown\x18\x08 \x01(\x08\x12\x1a\n\x12poller_autoscaling\x18\t \x01(\x08\x12\x17\n\x0fworker_commands\x18\n \x01(\x08\x1a\x46\n\x06Limits\x12\x1d\n\x15\x62lob_size_limit_error\x18\x01 \x01(\x03\x12\x1d\n\x15memo_size_limit_error\x18\x02 \x01(\x03"\x9e\x04\n\x0fNamespaceConfig\x12\x43\n workflow_execution_retention_ttl\x18\x01 \x01(\x0b\x32\x19.google.protobuf.Duration\x12<\n\x0c\x62\x61\x64_binaries\x18\x02 \x01(\x0b\x32&.temporal.api.namespace.v1.BadBinaries\x12\x44\n\x16history_archival_state\x18\x03 \x01(\x0e\x32$.temporal.api.enums.v1.ArchivalState\x12\x1c\n\x14history_archival_uri\x18\x04 \x01(\t\x12G\n\x19visibility_archival_state\x18\x05 \x01(\x0e\x32$.temporal.api.enums.v1.ArchivalState\x12\x1f\n\x17visibility_archival_uri\x18\x06 \x01(\t\x12u\n\x1f\x63ustom_search_attribute_aliases\x18\x07 \x03(\x0b\x32L.temporal.api.namespace.v1.NamespaceConfig.CustomSearchAttributeAliasesEntry\x1a\x43\n!CustomSearchAttributeAliasesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01"\xb0\x01\n\x0b\x42\x61\x64\x42inaries\x12\x46\n\x08\x62inaries\x18\x01 \x03(\x0b\x32\x34.temporal.api.namespace.v1.BadBinaries.BinariesEntry\x1aY\n\rBinariesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x37\n\x05value\x18\x02 \x01(\x0b\x32(.temporal.api.namespace.v1.BadBinaryInfo:\x02\x38\x01"b\n\rBadBinaryInfo\x12\x0e\n\x06reason\x18\x01 \x01(\t\x12\x10\n\x08operator\x18\x02 \x01(\t\x12/\n\x0b\x63reate_time\x18\x03 \x01(\x0b\x32\x1a.google.protobuf.Timestamp"\xea\x01\n\x13UpdateNamespaceInfo\x12\x13\n\x0b\x64\x65scription\x18\x01 \x01(\t\x12\x13\n\x0bowner_email\x18\x02 \x01(\t\x12\x46\n\x04\x64\x61ta\x18\x03 \x03(\x0b\x32\x38.temporal.api.namespace.v1.UpdateNamespaceInfo.DataEntry\x12\x34\n\x05state\x18\x04 \x01(\x0e\x32%.temporal.api.enums.v1.NamespaceState\x1a+\n\tDataEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01"*\n\x0fNamespaceFilter\x12\x17\n\x0finclude_deleted\x18\x01 \x01(\x08\x42\x98\x01\n\x1cio.temporal.api.namespace.v1B\x0cMessageProtoP\x01Z)go.temporal.io/api/namespace/v1;namespace\xaa\x02\x1bTemporalio.Api.Namespace.V1\xea\x02\x1eTemporalio::Api::Namespace::V1b\x06proto3' + b'\n\'temporal/api/namespace/v1/message.proto\x12\x19temporal.api.namespace.v1\x1a\x1egoogle/protobuf/duration.proto\x1a\x1fgoogle/protobuf/timestamp.proto\x1a%temporal/api/enums/v1/namespace.proto"\xe8\x06\n\rNamespaceInfo\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x34\n\x05state\x18\x02 \x01(\x0e\x32%.temporal.api.enums.v1.NamespaceState\x12\x13\n\x0b\x64\x65scription\x18\x03 \x01(\t\x12\x13\n\x0bowner_email\x18\x04 \x01(\t\x12@\n\x04\x64\x61ta\x18\x05 \x03(\x0b\x32\x32.temporal.api.namespace.v1.NamespaceInfo.DataEntry\x12\n\n\x02id\x18\x06 \x01(\t\x12K\n\x0c\x63\x61pabilities\x18\x07 \x01(\x0b\x32\x35.temporal.api.namespace.v1.NamespaceInfo.Capabilities\x12?\n\x06limits\x18\x08 \x01(\x0b\x32/.temporal.api.namespace.v1.NamespaceInfo.Limits\x12\x1a\n\x12supports_schedules\x18\x64 \x01(\x08\x1a+\n\tDataEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x1a\xfb\x02\n\x0c\x43\x61pabilities\x12\x1c\n\x14\x65\x61ger_workflow_start\x18\x01 \x01(\x08\x12\x13\n\x0bsync_update\x18\x02 \x01(\x08\x12\x14\n\x0c\x61sync_update\x18\x03 \x01(\x08\x12\x19\n\x11worker_heartbeats\x18\x04 \x01(\x08\x12*\n"reported_problems_search_attribute\x18\x05 \x01(\x08\x12\x16\n\x0eworkflow_pause\x18\x06 \x01(\x08\x12\x1d\n\x15standalone_activities\x18\x07 \x01(\x08\x12(\n worker_poll_complete_on_shutdown\x18\x08 \x01(\x08\x12\x1a\n\x12poller_autoscaling\x18\t \x01(\x08\x12\x17\n\x0fworker_commands\x18\n \x01(\x08\x12"\n\x1astandalone_nexus_operation\x18\x0b \x01(\x08\x12!\n\x19workflow_update_callbacks\x18\x0c \x01(\x08\x1a\x46\n\x06Limits\x12\x1d\n\x15\x62lob_size_limit_error\x18\x01 \x01(\x03\x12\x1d\n\x15memo_size_limit_error\x18\x02 \x01(\x03"\x9e\x04\n\x0fNamespaceConfig\x12\x43\n workflow_execution_retention_ttl\x18\x01 \x01(\x0b\x32\x19.google.protobuf.Duration\x12<\n\x0c\x62\x61\x64_binaries\x18\x02 \x01(\x0b\x32&.temporal.api.namespace.v1.BadBinaries\x12\x44\n\x16history_archival_state\x18\x03 \x01(\x0e\x32$.temporal.api.enums.v1.ArchivalState\x12\x1c\n\x14history_archival_uri\x18\x04 \x01(\t\x12G\n\x19visibility_archival_state\x18\x05 \x01(\x0e\x32$.temporal.api.enums.v1.ArchivalState\x12\x1f\n\x17visibility_archival_uri\x18\x06 \x01(\t\x12u\n\x1f\x63ustom_search_attribute_aliases\x18\x07 \x03(\x0b\x32L.temporal.api.namespace.v1.NamespaceConfig.CustomSearchAttributeAliasesEntry\x1a\x43\n!CustomSearchAttributeAliasesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01"\xb0\x01\n\x0b\x42\x61\x64\x42inaries\x12\x46\n\x08\x62inaries\x18\x01 \x03(\x0b\x32\x34.temporal.api.namespace.v1.BadBinaries.BinariesEntry\x1aY\n\rBinariesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x37\n\x05value\x18\x02 \x01(\x0b\x32(.temporal.api.namespace.v1.BadBinaryInfo:\x02\x38\x01"b\n\rBadBinaryInfo\x12\x0e\n\x06reason\x18\x01 \x01(\t\x12\x10\n\x08operator\x18\x02 \x01(\t\x12/\n\x0b\x63reate_time\x18\x03 \x01(\x0b\x32\x1a.google.protobuf.Timestamp"\xea\x01\n\x13UpdateNamespaceInfo\x12\x13\n\x0b\x64\x65scription\x18\x01 \x01(\t\x12\x13\n\x0bowner_email\x18\x02 \x01(\t\x12\x46\n\x04\x64\x61ta\x18\x03 \x03(\x0b\x32\x38.temporal.api.namespace.v1.UpdateNamespaceInfo.DataEntry\x12\x34\n\x05state\x18\x04 \x01(\x0e\x32%.temporal.api.enums.v1.NamespaceState\x1a+\n\tDataEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01"*\n\x0fNamespaceFilter\x12\x17\n\x0finclude_deleted\x18\x01 \x01(\x08\x42\x98\x01\n\x1cio.temporal.api.namespace.v1B\x0cMessageProtoP\x01Z)go.temporal.io/api/namespace/v1;namespace\xaa\x02\x1bTemporalio.Api.Namespace.V1\xea\x02\x1eTemporalio::Api::Namespace::V1b\x06proto3' ) @@ -178,27 +178,27 @@ _UPDATENAMESPACEINFO_DATAENTRY._options = None _UPDATENAMESPACEINFO_DATAENTRY._serialized_options = b"8\001" _NAMESPACEINFO._serialized_start = 175 - _NAMESPACEINFO._serialized_end = 976 + _NAMESPACEINFO._serialized_end = 1047 _NAMESPACEINFO_DATAENTRY._serialized_start = 550 _NAMESPACEINFO_DATAENTRY._serialized_end = 593 _NAMESPACEINFO_CAPABILITIES._serialized_start = 596 - _NAMESPACEINFO_CAPABILITIES._serialized_end = 904 - _NAMESPACEINFO_LIMITS._serialized_start = 906 - _NAMESPACEINFO_LIMITS._serialized_end = 976 - _NAMESPACECONFIG._serialized_start = 979 - _NAMESPACECONFIG._serialized_end = 1521 - _NAMESPACECONFIG_CUSTOMSEARCHATTRIBUTEALIASESENTRY._serialized_start = 1454 - _NAMESPACECONFIG_CUSTOMSEARCHATTRIBUTEALIASESENTRY._serialized_end = 1521 - _BADBINARIES._serialized_start = 1524 - _BADBINARIES._serialized_end = 1700 - _BADBINARIES_BINARIESENTRY._serialized_start = 1611 - _BADBINARIES_BINARIESENTRY._serialized_end = 1700 - _BADBINARYINFO._serialized_start = 1702 - _BADBINARYINFO._serialized_end = 1800 - _UPDATENAMESPACEINFO._serialized_start = 1803 - _UPDATENAMESPACEINFO._serialized_end = 2037 + _NAMESPACEINFO_CAPABILITIES._serialized_end = 975 + _NAMESPACEINFO_LIMITS._serialized_start = 977 + _NAMESPACEINFO_LIMITS._serialized_end = 1047 + _NAMESPACECONFIG._serialized_start = 1050 + _NAMESPACECONFIG._serialized_end = 1592 + _NAMESPACECONFIG_CUSTOMSEARCHATTRIBUTEALIASESENTRY._serialized_start = 1525 + _NAMESPACECONFIG_CUSTOMSEARCHATTRIBUTEALIASESENTRY._serialized_end = 1592 + _BADBINARIES._serialized_start = 1595 + _BADBINARIES._serialized_end = 1771 + _BADBINARIES_BINARIESENTRY._serialized_start = 1682 + _BADBINARIES_BINARIESENTRY._serialized_end = 1771 + _BADBINARYINFO._serialized_start = 1773 + _BADBINARYINFO._serialized_end = 1871 + _UPDATENAMESPACEINFO._serialized_start = 1874 + _UPDATENAMESPACEINFO._serialized_end = 2108 _UPDATENAMESPACEINFO_DATAENTRY._serialized_start = 550 _UPDATENAMESPACEINFO_DATAENTRY._serialized_end = 593 - _NAMESPACEFILTER._serialized_start = 2039 - _NAMESPACEFILTER._serialized_end = 2081 + _NAMESPACEFILTER._serialized_start = 2110 + _NAMESPACEFILTER._serialized_end = 2152 # @@protoc_insertion_point(module_scope) diff --git a/temporalio/api/namespace/v1/message_pb2.pyi b/temporalio/api/namespace/v1/message_pb2.pyi index ff258076d..a01a58c72 100644 --- a/temporalio/api/namespace/v1/message_pb2.pyi +++ b/temporalio/api/namespace/v1/message_pb2.pyi @@ -58,6 +58,8 @@ class NamespaceInfo(google.protobuf.message.Message): WORKER_POLL_COMPLETE_ON_SHUTDOWN_FIELD_NUMBER: builtins.int POLLER_AUTOSCALING_FIELD_NUMBER: builtins.int WORKER_COMMANDS_FIELD_NUMBER: builtins.int + STANDALONE_NEXUS_OPERATION_FIELD_NUMBER: builtins.int + WORKFLOW_UPDATE_CALLBACKS_FIELD_NUMBER: builtins.int eager_workflow_start: builtins.bool """True if the namespace supports eager workflow start.""" sync_update: builtins.bool @@ -83,6 +85,10 @@ class NamespaceInfo(google.protobuf.message.Message): """True if the namespace supports poller autoscaling""" worker_commands: builtins.bool """True if the namespace supports worker commands (server-to-worker communication via control queues).""" + standalone_nexus_operation: builtins.bool + """True if the namespace supports standalone Nexus operations.""" + workflow_update_callbacks: builtins.bool + """True if the namespace supports attaching callbacks on workflow updates""" def __init__( self, *, @@ -96,6 +102,8 @@ class NamespaceInfo(google.protobuf.message.Message): worker_poll_complete_on_shutdown: builtins.bool = ..., poller_autoscaling: builtins.bool = ..., worker_commands: builtins.bool = ..., + standalone_nexus_operation: builtins.bool = ..., + workflow_update_callbacks: builtins.bool = ..., ) -> None: ... def ClearField( self, @@ -110,6 +118,8 @@ class NamespaceInfo(google.protobuf.message.Message): b"reported_problems_search_attribute", "standalone_activities", b"standalone_activities", + "standalone_nexus_operation", + b"standalone_nexus_operation", "sync_update", b"sync_update", "worker_commands", @@ -120,6 +130,8 @@ class NamespaceInfo(google.protobuf.message.Message): b"worker_poll_complete_on_shutdown", "workflow_pause", b"workflow_pause", + "workflow_update_callbacks", + b"workflow_update_callbacks", ], ) -> None: ... diff --git a/temporalio/api/nexus/v1/message_pb2.py b/temporalio/api/nexus/v1/message_pb2.py index c8cff60b0..d607eb9c8 100644 --- a/temporalio/api/nexus/v1/message_pb2.py +++ b/temporalio/api/nexus/v1/message_pb2.py @@ -34,7 +34,7 @@ ) DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile( - b'\n#temporal/api/nexus/v1/message.proto\x12\x15temporal.api.nexus.v1\x1a\x1egoogle/protobuf/duration.proto\x1a\x1fgoogle/protobuf/timestamp.proto\x1a$temporal/api/common/v1/message.proto\x1a"temporal/api/enums/v1/common.proto\x1a!temporal/api/enums/v1/nexus.proto\x1a%temporal/api/failure/v1/message.proto\x1a\'temporal/api/sdk/v1/user_metadata.proto"\xe0\x01\n\x07\x46\x61ilure\x12\x0f\n\x07message\x18\x01 \x01(\t\x12\x13\n\x0bstack_trace\x18\x04 \x01(\t\x12>\n\x08metadata\x18\x02 \x03(\x0b\x32,.temporal.api.nexus.v1.Failure.MetadataEntry\x12\x0f\n\x07\x64\x65tails\x18\x03 \x01(\x0c\x12-\n\x05\x63\x61use\x18\x05 \x01(\x0b\x32\x1e.temporal.api.nexus.v1.Failure\x1a/\n\rMetadataEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01"\xa2\x01\n\x0cHandlerError\x12\x12\n\nerror_type\x18\x01 \x01(\t\x12/\n\x07\x66\x61ilure\x18\x02 \x01(\x0b\x32\x1e.temporal.api.nexus.v1.Failure\x12M\n\x0eretry_behavior\x18\x03 \x01(\x0e\x32\x35.temporal.api.enums.v1.NexusHandlerErrorRetryBehavior"f\n\x1aUnsuccessfulOperationError\x12\x17\n\x0foperation_state\x18\x01 \x01(\t\x12/\n\x07\x66\x61ilure\x18\x02 \x01(\x0b\x32\x1e.temporal.api.nexus.v1.Failure"!\n\x04Link\x12\x0b\n\x03url\x18\x01 \x01(\t\x12\x0c\n\x04type\x18\x02 \x01(\t"\xd1\x02\n\x15StartOperationRequest\x12\x0f\n\x07service\x18\x01 \x01(\t\x12\x11\n\toperation\x18\x02 \x01(\t\x12\x12\n\nrequest_id\x18\x03 \x01(\t\x12\x10\n\x08\x63\x61llback\x18\x04 \x01(\t\x12\x30\n\x07payload\x18\x05 \x01(\x0b\x32\x1f.temporal.api.common.v1.Payload\x12Y\n\x0f\x63\x61llback_header\x18\x06 \x03(\x0b\x32@.temporal.api.nexus.v1.StartOperationRequest.CallbackHeaderEntry\x12*\n\x05links\x18\x07 \x03(\x0b\x32\x1b.temporal.api.nexus.v1.Link\x1a\x35\n\x13\x43\x61llbackHeaderEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01"o\n\x16\x43\x61ncelOperationRequest\x12\x0f\n\x07service\x18\x01 \x01(\t\x12\x11\n\toperation\x18\x02 \x01(\t\x12\x18\n\x0coperation_id\x18\x03 \x01(\tB\x02\x18\x01\x12\x17\n\x0foperation_token\x18\x04 \x01(\t"\xd0\x03\n\x07Request\x12:\n\x06header\x18\x01 \x03(\x0b\x32*.temporal.api.nexus.v1.Request.HeaderEntry\x12\x32\n\x0escheduled_time\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x41\n\x0c\x63\x61pabilities\x18\x64 \x01(\x0b\x32+.temporal.api.nexus.v1.Request.Capabilities\x12G\n\x0fstart_operation\x18\x03 \x01(\x0b\x32,.temporal.api.nexus.v1.StartOperationRequestH\x00\x12I\n\x10\x63\x61ncel_operation\x18\x04 \x01(\x0b\x32-.temporal.api.nexus.v1.CancelOperationRequestH\x00\x12\x10\n\x08\x65ndpoint\x18\n \x01(\t\x1a\x32\n\x0c\x43\x61pabilities\x12"\n\x1atemporal_failure_responses\x18\x01 \x01(\x08\x1a-\n\x0bHeaderEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x42\t\n\x07variant"\x92\x04\n\x16StartOperationResponse\x12J\n\x0csync_success\x18\x01 \x01(\x0b\x32\x32.temporal.api.nexus.v1.StartOperationResponse.SyncH\x00\x12L\n\rasync_success\x18\x02 \x01(\x0b\x32\x33.temporal.api.nexus.v1.StartOperationResponse.AsyncH\x00\x12P\n\x0foperation_error\x18\x03 \x01(\x0b\x32\x31.temporal.api.nexus.v1.UnsuccessfulOperationErrorB\x02\x18\x01H\x00\x12\x33\n\x07\x66\x61ilure\x18\x04 \x01(\x0b\x32 .temporal.api.failure.v1.FailureH\x00\x1a\x64\n\x04Sync\x12\x30\n\x07payload\x18\x01 \x01(\x0b\x32\x1f.temporal.api.common.v1.Payload\x12*\n\x05links\x18\x02 \x03(\x0b\x32\x1b.temporal.api.nexus.v1.Link\x1a\x66\n\x05\x41sync\x12\x18\n\x0coperation_id\x18\x01 \x01(\tB\x02\x18\x01\x12*\n\x05links\x18\x02 \x03(\x0b\x32\x1b.temporal.api.nexus.v1.Link\x12\x17\n\x0foperation_token\x18\x03 \x01(\tB\t\n\x07variant"\x19\n\x17\x43\x61ncelOperationResponse"\xab\x01\n\x08Response\x12H\n\x0fstart_operation\x18\x01 \x01(\x0b\x32-.temporal.api.nexus.v1.StartOperationResponseH\x00\x12J\n\x10\x63\x61ncel_operation\x18\x02 \x01(\x0b\x32..temporal.api.nexus.v1.CancelOperationResponseH\x00\x42\t\n\x07variant"\xd8\x01\n\x08\x45ndpoint\x12\x0f\n\x07version\x18\x01 \x01(\x03\x12\n\n\x02id\x18\x02 \x01(\t\x12\x31\n\x04spec\x18\x03 \x01(\x0b\x32#.temporal.api.nexus.v1.EndpointSpec\x12\x30\n\x0c\x63reated_time\x18\x04 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x36\n\x12last_modified_time\x18\x05 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x12\n\nurl_prefix\x18\x06 \x01(\t"\x89\x01\n\x0c\x45ndpointSpec\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x34\n\x0b\x64\x65scription\x18\x02 \x01(\x0b\x32\x1f.temporal.api.common.v1.Payload\x12\x35\n\x06target\x18\x03 \x01(\x0b\x32%.temporal.api.nexus.v1.EndpointTarget"\xe9\x01\n\x0e\x45ndpointTarget\x12>\n\x06worker\x18\x01 \x01(\x0b\x32,.temporal.api.nexus.v1.EndpointTarget.WorkerH\x00\x12\x42\n\x08\x65xternal\x18\x02 \x01(\x0b\x32..temporal.api.nexus.v1.EndpointTarget.ExternalH\x00\x1a/\n\x06Worker\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x12\n\ntask_queue\x18\x02 \x01(\t\x1a\x17\n\x08\x45xternal\x12\x0b\n\x03url\x18\x01 \x01(\tB\t\n\x07variant"\x9d\x03\n\'NexusOperationExecutionCancellationInfo\x12\x32\n\x0erequested_time\x18\x01 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x45\n\x05state\x18\x02 \x01(\x0e\x32\x36.temporal.api.enums.v1.NexusOperationCancellationState\x12\x0f\n\x07\x61ttempt\x18\x03 \x01(\x05\x12>\n\x1alast_attempt_complete_time\x18\x04 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12>\n\x14last_attempt_failure\x18\x05 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12>\n\x1anext_attempt_schedule_time\x18\x06 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x16\n\x0e\x62locked_reason\x18\x07 \x01(\t\x12\x0e\n\x06reason\x18\x08 \x01(\t"\xe5\n\n\x1bNexusOperationExecutionInfo\x12\x14\n\x0coperation_id\x18\x01 \x01(\t\x12\x0e\n\x06run_id\x18\x02 \x01(\t\x12\x10\n\x08\x65ndpoint\x18\x03 \x01(\t\x12\x0f\n\x07service\x18\x04 \x01(\t\x12\x11\n\toperation\x18\x05 \x01(\t\x12\x44\n\x06status\x18\x06 \x01(\x0e\x32\x34.temporal.api.enums.v1.NexusOperationExecutionStatus\x12@\n\x05state\x18\x07 \x01(\x0e\x32\x31.temporal.api.enums.v1.PendingNexusOperationState\x12<\n\x19schedule_to_close_timeout\x18\x08 \x01(\x0b\x32\x19.google.protobuf.Duration\x12<\n\x19schedule_to_start_timeout\x18\t \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x39\n\x16start_to_close_timeout\x18\n \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x0f\n\x07\x61ttempt\x18\x0b \x01(\x05\x12\x31\n\rschedule_time\x18\x0c \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x33\n\x0f\x65xpiration_time\x18\r \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12.\n\nclose_time\x18\x0e \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12>\n\x1alast_attempt_complete_time\x18\x0f \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12>\n\x14last_attempt_failure\x18\x10 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12>\n\x1anext_attempt_schedule_time\x18\x11 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x35\n\x12\x65xecution_duration\x18\x12 \x01(\x0b\x32\x19.google.protobuf.Duration\x12Y\n\x11\x63\x61ncellation_info\x18\x13 \x01(\x0b\x32>.temporal.api.nexus.v1.NexusOperationExecutionCancellationInfo\x12\x16\n\x0e\x62locked_reason\x18\x14 \x01(\t\x12\x12\n\nrequest_id\x18\x15 \x01(\t\x12\x17\n\x0foperation_token\x18\x16 \x01(\t\x12\x1e\n\x16state_transition_count\x18\x17 \x01(\x03\x12\x43\n\x11search_attributes\x18\x18 \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes\x12Y\n\x0cnexus_header\x18\x19 \x03(\x0b\x32\x43.temporal.api.nexus.v1.NexusOperationExecutionInfo.NexusHeaderEntry\x12\x38\n\ruser_metadata\x18\x1a \x01(\x0b\x32!.temporal.api.sdk.v1.UserMetadata\x12+\n\x05links\x18\x1b \x03(\x0b\x32\x1c.temporal.api.common.v1.Link\x12\x10\n\x08identity\x18\x1c \x01(\t\x1a\x32\n\x10NexusHeaderEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01"\xc2\x03\n\x1fNexusOperationExecutionListInfo\x12\x14\n\x0coperation_id\x18\x01 \x01(\t\x12\x0e\n\x06run_id\x18\x02 \x01(\t\x12\x10\n\x08\x65ndpoint\x18\x03 \x01(\t\x12\x0f\n\x07service\x18\x04 \x01(\t\x12\x11\n\toperation\x18\x05 \x01(\t\x12\x31\n\rschedule_time\x18\x06 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12.\n\nclose_time\x18\x07 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x44\n\x06status\x18\x08 \x01(\x0e\x32\x34.temporal.api.enums.v1.NexusOperationExecutionStatus\x12\x43\n\x11search_attributes\x18\t \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes\x12\x1e\n\x16state_transition_count\x18\n \x01(\x03\x12\x35\n\x12\x65xecution_duration\x18\x0b \x01(\x0b\x32\x19.google.protobuf.DurationB\x84\x01\n\x18io.temporal.api.nexus.v1B\x0cMessageProtoP\x01Z!go.temporal.io/api/nexus/v1;nexus\xaa\x02\x17Temporalio.Api.Nexus.V1\xea\x02\x1aTemporalio::Api::Nexus::V1b\x06proto3' + b'\n#temporal/api/nexus/v1/message.proto\x12\x15temporal.api.nexus.v1\x1a\x1egoogle/protobuf/duration.proto\x1a\x1fgoogle/protobuf/timestamp.proto\x1a$temporal/api/common/v1/message.proto\x1a"temporal/api/enums/v1/common.proto\x1a!temporal/api/enums/v1/nexus.proto\x1a%temporal/api/failure/v1/message.proto\x1a\'temporal/api/sdk/v1/user_metadata.proto"\xe0\x01\n\x07\x46\x61ilure\x12\x0f\n\x07message\x18\x01 \x01(\t\x12\x13\n\x0bstack_trace\x18\x04 \x01(\t\x12>\n\x08metadata\x18\x02 \x03(\x0b\x32,.temporal.api.nexus.v1.Failure.MetadataEntry\x12\x0f\n\x07\x64\x65tails\x18\x03 \x01(\x0c\x12-\n\x05\x63\x61use\x18\x05 \x01(\x0b\x32\x1e.temporal.api.nexus.v1.Failure\x1a/\n\rMetadataEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01"\xa2\x01\n\x0cHandlerError\x12\x12\n\nerror_type\x18\x01 \x01(\t\x12/\n\x07\x66\x61ilure\x18\x02 \x01(\x0b\x32\x1e.temporal.api.nexus.v1.Failure\x12M\n\x0eretry_behavior\x18\x03 \x01(\x0e\x32\x35.temporal.api.enums.v1.NexusHandlerErrorRetryBehavior"f\n\x1aUnsuccessfulOperationError\x12\x17\n\x0foperation_state\x18\x01 \x01(\t\x12/\n\x07\x66\x61ilure\x18\x02 \x01(\x0b\x32\x1e.temporal.api.nexus.v1.Failure"!\n\x04Link\x12\x0b\n\x03url\x18\x01 \x01(\t\x12\x0c\n\x04type\x18\x02 \x01(\t"\xd1\x02\n\x15StartOperationRequest\x12\x0f\n\x07service\x18\x01 \x01(\t\x12\x11\n\toperation\x18\x02 \x01(\t\x12\x12\n\nrequest_id\x18\x03 \x01(\t\x12\x10\n\x08\x63\x61llback\x18\x04 \x01(\t\x12\x30\n\x07payload\x18\x05 \x01(\x0b\x32\x1f.temporal.api.common.v1.Payload\x12Y\n\x0f\x63\x61llback_header\x18\x06 \x03(\x0b\x32@.temporal.api.nexus.v1.StartOperationRequest.CallbackHeaderEntry\x12*\n\x05links\x18\x07 \x03(\x0b\x32\x1b.temporal.api.nexus.v1.Link\x1a\x35\n\x13\x43\x61llbackHeaderEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01"o\n\x16\x43\x61ncelOperationRequest\x12\x0f\n\x07service\x18\x01 \x01(\t\x12\x11\n\toperation\x18\x02 \x01(\t\x12\x18\n\x0coperation_id\x18\x03 \x01(\tB\x02\x18\x01\x12\x17\n\x0foperation_token\x18\x04 \x01(\t"\xd0\x03\n\x07Request\x12:\n\x06header\x18\x01 \x03(\x0b\x32*.temporal.api.nexus.v1.Request.HeaderEntry\x12\x32\n\x0escheduled_time\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x41\n\x0c\x63\x61pabilities\x18\x64 \x01(\x0b\x32+.temporal.api.nexus.v1.Request.Capabilities\x12G\n\x0fstart_operation\x18\x03 \x01(\x0b\x32,.temporal.api.nexus.v1.StartOperationRequestH\x00\x12I\n\x10\x63\x61ncel_operation\x18\x04 \x01(\x0b\x32-.temporal.api.nexus.v1.CancelOperationRequestH\x00\x12\x10\n\x08\x65ndpoint\x18\n \x01(\t\x1a\x32\n\x0c\x43\x61pabilities\x12"\n\x1atemporal_failure_responses\x18\x01 \x01(\x08\x1a-\n\x0bHeaderEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x42\t\n\x07variant"\x92\x04\n\x16StartOperationResponse\x12J\n\x0csync_success\x18\x01 \x01(\x0b\x32\x32.temporal.api.nexus.v1.StartOperationResponse.SyncH\x00\x12L\n\rasync_success\x18\x02 \x01(\x0b\x32\x33.temporal.api.nexus.v1.StartOperationResponse.AsyncH\x00\x12P\n\x0foperation_error\x18\x03 \x01(\x0b\x32\x31.temporal.api.nexus.v1.UnsuccessfulOperationErrorB\x02\x18\x01H\x00\x12\x33\n\x07\x66\x61ilure\x18\x04 \x01(\x0b\x32 .temporal.api.failure.v1.FailureH\x00\x1a\x64\n\x04Sync\x12\x30\n\x07payload\x18\x01 \x01(\x0b\x32\x1f.temporal.api.common.v1.Payload\x12*\n\x05links\x18\x02 \x03(\x0b\x32\x1b.temporal.api.nexus.v1.Link\x1a\x66\n\x05\x41sync\x12\x18\n\x0coperation_id\x18\x01 \x01(\tB\x02\x18\x01\x12*\n\x05links\x18\x02 \x03(\x0b\x32\x1b.temporal.api.nexus.v1.Link\x12\x17\n\x0foperation_token\x18\x03 \x01(\tB\t\n\x07variant"\x19\n\x17\x43\x61ncelOperationResponse"\xab\x01\n\x08Response\x12H\n\x0fstart_operation\x18\x01 \x01(\x0b\x32-.temporal.api.nexus.v1.StartOperationResponseH\x00\x12J\n\x10\x63\x61ncel_operation\x18\x02 \x01(\x0b\x32..temporal.api.nexus.v1.CancelOperationResponseH\x00\x42\t\n\x07variant"\xd8\x01\n\x08\x45ndpoint\x12\x0f\n\x07version\x18\x01 \x01(\x03\x12\n\n\x02id\x18\x02 \x01(\t\x12\x31\n\x04spec\x18\x03 \x01(\x0b\x32#.temporal.api.nexus.v1.EndpointSpec\x12\x30\n\x0c\x63reated_time\x18\x04 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x36\n\x12last_modified_time\x18\x05 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x12\n\nurl_prefix\x18\x06 \x01(\t"\x89\x01\n\x0c\x45ndpointSpec\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x34\n\x0b\x64\x65scription\x18\x02 \x01(\x0b\x32\x1f.temporal.api.common.v1.Payload\x12\x35\n\x06target\x18\x03 \x01(\x0b\x32%.temporal.api.nexus.v1.EndpointTarget"\xe9\x01\n\x0e\x45ndpointTarget\x12>\n\x06worker\x18\x01 \x01(\x0b\x32,.temporal.api.nexus.v1.EndpointTarget.WorkerH\x00\x12\x42\n\x08\x65xternal\x18\x02 \x01(\x0b\x32..temporal.api.nexus.v1.EndpointTarget.ExternalH\x00\x1a/\n\x06Worker\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x12\n\ntask_queue\x18\x02 \x01(\t\x1a\x17\n\x08\x45xternal\x12\x0b\n\x03url\x18\x01 \x01(\tB\t\n\x07variant"\x9d\x03\n\'NexusOperationExecutionCancellationInfo\x12\x32\n\x0erequested_time\x18\x01 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x45\n\x05state\x18\x02 \x01(\x0e\x32\x36.temporal.api.enums.v1.NexusOperationCancellationState\x12\x0f\n\x07\x61ttempt\x18\x03 \x01(\x05\x12>\n\x1alast_attempt_complete_time\x18\x04 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12>\n\x14last_attempt_failure\x18\x05 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12>\n\x1anext_attempt_schedule_time\x18\x06 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x16\n\x0e\x62locked_reason\x18\x07 \x01(\t\x12\x0e\n\x06reason\x18\x08 \x01(\t"\xff\n\n\x1bNexusOperationExecutionInfo\x12\x14\n\x0coperation_id\x18\x01 \x01(\t\x12\x0e\n\x06run_id\x18\x02 \x01(\t\x12\x10\n\x08\x65ndpoint\x18\x03 \x01(\t\x12\x0f\n\x07service\x18\x04 \x01(\t\x12\x11\n\toperation\x18\x05 \x01(\t\x12\x44\n\x06status\x18\x06 \x01(\x0e\x32\x34.temporal.api.enums.v1.NexusOperationExecutionStatus\x12@\n\x05state\x18\x07 \x01(\x0e\x32\x31.temporal.api.enums.v1.PendingNexusOperationState\x12<\n\x19schedule_to_close_timeout\x18\x08 \x01(\x0b\x32\x19.google.protobuf.Duration\x12<\n\x19schedule_to_start_timeout\x18\t \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x39\n\x16start_to_close_timeout\x18\n \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x0f\n\x07\x61ttempt\x18\x0b \x01(\x05\x12\x31\n\rschedule_time\x18\x0c \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x33\n\x0f\x65xpiration_time\x18\r \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12.\n\nclose_time\x18\x0e \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12>\n\x1alast_attempt_complete_time\x18\x0f \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12>\n\x14last_attempt_failure\x18\x10 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12>\n\x1anext_attempt_schedule_time\x18\x11 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x35\n\x12\x65xecution_duration\x18\x12 \x01(\x0b\x32\x19.google.protobuf.Duration\x12Y\n\x11\x63\x61ncellation_info\x18\x13 \x01(\x0b\x32>.temporal.api.nexus.v1.NexusOperationExecutionCancellationInfo\x12\x16\n\x0e\x62locked_reason\x18\x14 \x01(\t\x12\x12\n\nrequest_id\x18\x15 \x01(\t\x12\x17\n\x0foperation_token\x18\x16 \x01(\t\x12\x1e\n\x16state_transition_count\x18\x17 \x01(\x03\x12\x43\n\x11search_attributes\x18\x18 \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes\x12Y\n\x0cnexus_header\x18\x19 \x03(\x0b\x32\x43.temporal.api.nexus.v1.NexusOperationExecutionInfo.NexusHeaderEntry\x12\x38\n\ruser_metadata\x18\x1a \x01(\x0b\x32!.temporal.api.sdk.v1.UserMetadata\x12+\n\x05links\x18\x1b \x03(\x0b\x32\x1c.temporal.api.common.v1.Link\x12\x10\n\x08identity\x18\x1c \x01(\t\x12\x18\n\x10state_size_bytes\x18\x1d \x01(\x03\x1a\x32\n\x10NexusHeaderEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01"\xdc\x03\n\x1fNexusOperationExecutionListInfo\x12\x14\n\x0coperation_id\x18\x01 \x01(\t\x12\x0e\n\x06run_id\x18\x02 \x01(\t\x12\x10\n\x08\x65ndpoint\x18\x03 \x01(\t\x12\x0f\n\x07service\x18\x04 \x01(\t\x12\x11\n\toperation\x18\x05 \x01(\t\x12\x31\n\rschedule_time\x18\x06 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12.\n\nclose_time\x18\x07 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x44\n\x06status\x18\x08 \x01(\x0e\x32\x34.temporal.api.enums.v1.NexusOperationExecutionStatus\x12\x43\n\x11search_attributes\x18\t \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes\x12\x1e\n\x16state_transition_count\x18\n \x01(\x03\x12\x35\n\x12\x65xecution_duration\x18\x0b \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x18\n\x10state_size_bytes\x18\x0c \x01(\x03\x42\x84\x01\n\x18io.temporal.api.nexus.v1B\x0cMessageProtoP\x01Z!go.temporal.io/api/nexus/v1;nexus\xaa\x02\x17Temporalio.Api.Nexus.V1\xea\x02\x1aTemporalio::Api::Nexus::V1b\x06proto3' ) @@ -409,9 +409,9 @@ _NEXUSOPERATIONEXECUTIONCANCELLATIONINFO._serialized_start = 3097 _NEXUSOPERATIONEXECUTIONCANCELLATIONINFO._serialized_end = 3510 _NEXUSOPERATIONEXECUTIONINFO._serialized_start = 3513 - _NEXUSOPERATIONEXECUTIONINFO._serialized_end = 4894 - _NEXUSOPERATIONEXECUTIONINFO_NEXUSHEADERENTRY._serialized_start = 4844 - _NEXUSOPERATIONEXECUTIONINFO_NEXUSHEADERENTRY._serialized_end = 4894 - _NEXUSOPERATIONEXECUTIONLISTINFO._serialized_start = 4897 - _NEXUSOPERATIONEXECUTIONLISTINFO._serialized_end = 5347 + _NEXUSOPERATIONEXECUTIONINFO._serialized_end = 4920 + _NEXUSOPERATIONEXECUTIONINFO_NEXUSHEADERENTRY._serialized_start = 4870 + _NEXUSOPERATIONEXECUTIONINFO_NEXUSHEADERENTRY._serialized_end = 4920 + _NEXUSOPERATIONEXECUTIONLISTINFO._serialized_start = 4923 + _NEXUSOPERATIONEXECUTIONLISTINFO._serialized_end = 5399 # @@protoc_insertion_point(module_scope) diff --git a/temporalio/api/nexus/v1/message_pb2.pyi b/temporalio/api/nexus/v1/message_pb2.pyi index f3b5e4d7e..ecdd004e2 100644 --- a/temporalio/api/nexus/v1/message_pb2.pyi +++ b/temporalio/api/nexus/v1/message_pb2.pyi @@ -972,6 +972,7 @@ class NexusOperationExecutionInfo(google.protobuf.message.Message): USER_METADATA_FIELD_NUMBER: builtins.int LINKS_FIELD_NUMBER: builtins.int IDENTITY_FIELD_NUMBER: builtins.int + STATE_SIZE_BYTES_FIELD_NUMBER: builtins.int operation_id: builtins.str """Unique identifier of this Nexus operation within its namespace along with run ID (below).""" run_id: builtins.str @@ -1068,6 +1069,8 @@ class NexusOperationExecutionInfo(google.protobuf.message.Message): """Links attached by the handler of this operation on start or completion.""" identity: builtins.str """The identity of the client who started this operation.""" + state_size_bytes: builtins.int + """Updated once on scheduled and once on terminal status.""" def __init__( self, *, @@ -1106,6 +1109,7 @@ class NexusOperationExecutionInfo(google.protobuf.message.Message): links: collections.abc.Iterable[temporalio.api.common.v1.message_pb2.Link] | None = ..., identity: builtins.str = ..., + state_size_bytes: builtins.int = ..., ) -> None: ... def HasField( self, @@ -1191,6 +1195,8 @@ class NexusOperationExecutionInfo(google.protobuf.message.Message): b"start_to_close_timeout", "state", b"state", + "state_size_bytes", + b"state_size_bytes", "state_transition_count", b"state_transition_count", "status", @@ -1221,6 +1227,7 @@ class NexusOperationExecutionListInfo(google.protobuf.message.Message): SEARCH_ATTRIBUTES_FIELD_NUMBER: builtins.int STATE_TRANSITION_COUNT_FIELD_NUMBER: builtins.int EXECUTION_DURATION_FIELD_NUMBER: builtins.int + STATE_SIZE_BYTES_FIELD_NUMBER: builtins.int operation_id: builtins.str """A unique identifier of this operation within its namespace along with run ID (below).""" run_id: builtins.str @@ -1251,6 +1258,8 @@ class NexusOperationExecutionListInfo(google.protobuf.message.Message): """The difference between close time and scheduled time. This field is only populated if the operation is closed. """ + state_size_bytes: builtins.int + """Updated once on scheduled and once on terminal status.""" def __init__( self, *, @@ -1266,6 +1275,7 @@ class NexusOperationExecutionListInfo(google.protobuf.message.Message): | None = ..., state_transition_count: builtins.int = ..., execution_duration: google.protobuf.duration_pb2.Duration | None = ..., + state_size_bytes: builtins.int = ..., ) -> None: ... def HasField( self, @@ -1301,6 +1311,8 @@ class NexusOperationExecutionListInfo(google.protobuf.message.Message): b"search_attributes", "service", b"service", + "state_size_bytes", + b"state_size_bytes", "state_transition_count", b"state_transition_count", "status", diff --git a/temporalio/api/schedule/v1/message_pb2.py b/temporalio/api/schedule/v1/message_pb2.py index 77fc3ce57..de57c94ed 100644 --- a/temporalio/api/schedule/v1/message_pb2.py +++ b/temporalio/api/schedule/v1/message_pb2.py @@ -31,7 +31,7 @@ ) DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile( - b'\n&temporal/api/schedule/v1/message.proto\x12\x18temporal.api.schedule.v1\x1a\x1egoogle/protobuf/duration.proto\x1a\x1fgoogle/protobuf/timestamp.proto\x1a$temporal/api/common/v1/message.proto\x1a$temporal/api/enums/v1/schedule.proto\x1a$temporal/api/enums/v1/workflow.proto\x1a&temporal/api/workflow/v1/message.proto"\x95\x01\n\x0c\x43\x61lendarSpec\x12\x0e\n\x06second\x18\x01 \x01(\t\x12\x0e\n\x06minute\x18\x02 \x01(\t\x12\x0c\n\x04hour\x18\x03 \x01(\t\x12\x14\n\x0c\x64\x61y_of_month\x18\x04 \x01(\t\x12\r\n\x05month\x18\x05 \x01(\t\x12\x0c\n\x04year\x18\x06 \x01(\t\x12\x13\n\x0b\x64\x61y_of_week\x18\x07 \x01(\t\x12\x0f\n\x07\x63omment\x18\x08 \x01(\t"1\n\x05Range\x12\r\n\x05start\x18\x01 \x01(\x05\x12\x0b\n\x03\x65nd\x18\x02 \x01(\x05\x12\x0c\n\x04step\x18\x03 \x01(\x05"\x86\x03\n\x16StructuredCalendarSpec\x12/\n\x06second\x18\x01 \x03(\x0b\x32\x1f.temporal.api.schedule.v1.Range\x12/\n\x06minute\x18\x02 \x03(\x0b\x32\x1f.temporal.api.schedule.v1.Range\x12-\n\x04hour\x18\x03 \x03(\x0b\x32\x1f.temporal.api.schedule.v1.Range\x12\x35\n\x0c\x64\x61y_of_month\x18\x04 \x03(\x0b\x32\x1f.temporal.api.schedule.v1.Range\x12.\n\x05month\x18\x05 \x03(\x0b\x32\x1f.temporal.api.schedule.v1.Range\x12-\n\x04year\x18\x06 \x03(\x0b\x32\x1f.temporal.api.schedule.v1.Range\x12\x34\n\x0b\x64\x61y_of_week\x18\x07 \x03(\x0b\x32\x1f.temporal.api.schedule.v1.Range\x12\x0f\n\x07\x63omment\x18\x08 \x01(\t"e\n\x0cIntervalSpec\x12+\n\x08interval\x18\x01 \x01(\x0b\x32\x19.google.protobuf.Duration\x12(\n\x05phase\x18\x02 \x01(\x0b\x32\x19.google.protobuf.Duration"\xba\x04\n\x0cScheduleSpec\x12M\n\x13structured_calendar\x18\x07 \x03(\x0b\x32\x30.temporal.api.schedule.v1.StructuredCalendarSpec\x12\x13\n\x0b\x63ron_string\x18\x08 \x03(\t\x12\x38\n\x08\x63\x61lendar\x18\x01 \x03(\x0b\x32&.temporal.api.schedule.v1.CalendarSpec\x12\x38\n\x08interval\x18\x02 \x03(\x0b\x32&.temporal.api.schedule.v1.IntervalSpec\x12\x44\n\x10\x65xclude_calendar\x18\x03 \x03(\x0b\x32&.temporal.api.schedule.v1.CalendarSpecB\x02\x18\x01\x12U\n\x1b\x65xclude_structured_calendar\x18\t \x03(\x0b\x32\x30.temporal.api.schedule.v1.StructuredCalendarSpec\x12.\n\nstart_time\x18\x04 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12,\n\x08\x65nd_time\x18\x05 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12)\n\x06jitter\x18\x06 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x15\n\rtimezone_name\x18\n \x01(\t\x12\x15\n\rtimezone_data\x18\x0b \x01(\x0c"\xc8\x01\n\x10SchedulePolicies\x12\x44\n\x0eoverlap_policy\x18\x01 \x01(\x0e\x32,.temporal.api.enums.v1.ScheduleOverlapPolicy\x12\x31\n\x0e\x63\x61tchup_window\x18\x02 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x18\n\x10pause_on_failure\x18\x03 \x01(\x08\x12!\n\x19keep_original_workflow_id\x18\x04 \x01(\x08"h\n\x0eScheduleAction\x12L\n\x0estart_workflow\x18\x01 \x01(\x0b\x32\x32.temporal.api.workflow.v1.NewWorkflowExecutionInfoH\x00\x42\x08\n\x06\x61\x63tion"\x93\x02\n\x14ScheduleActionResult\x12\x31\n\rschedule_time\x18\x01 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12/\n\x0b\x61\x63tual_time\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12H\n\x15start_workflow_result\x18\x0b \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12M\n\x15start_workflow_status\x18\x0c \x01(\x0e\x32..temporal.api.enums.v1.WorkflowExecutionStatus"b\n\rScheduleState\x12\r\n\x05notes\x18\x01 \x01(\t\x12\x0e\n\x06paused\x18\x02 \x01(\x08\x12\x17\n\x0flimited_actions\x18\x03 \x01(\x08\x12\x19\n\x11remaining_actions\x18\x04 \x01(\x03"\x95\x01\n\x19TriggerImmediatelyRequest\x12\x44\n\x0eoverlap_policy\x18\x01 \x01(\x0e\x32,.temporal.api.enums.v1.ScheduleOverlapPolicy\x12\x32\n\x0escheduled_time\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.Timestamp"\xb5\x01\n\x0f\x42\x61\x63kfillRequest\x12.\n\nstart_time\x18\x01 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12,\n\x08\x65nd_time\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x44\n\x0eoverlap_policy\x18\x03 \x01(\x0e\x32,.temporal.api.enums.v1.ScheduleOverlapPolicy"\xc6\x01\n\rSchedulePatch\x12P\n\x13trigger_immediately\x18\x01 \x01(\x0b\x32\x33.temporal.api.schedule.v1.TriggerImmediatelyRequest\x12\x43\n\x10\x62\x61\x63kfill_request\x18\x02 \x03(\x0b\x32).temporal.api.schedule.v1.BackfillRequest\x12\r\n\x05pause\x18\x03 \x01(\t\x12\x0f\n\x07unpause\x18\x04 \x01(\t"\xd6\x03\n\x0cScheduleInfo\x12\x14\n\x0c\x61\x63tion_count\x18\x01 \x01(\x03\x12\x1d\n\x15missed_catchup_window\x18\x02 \x01(\x03\x12\x17\n\x0foverlap_skipped\x18\x03 \x01(\x03\x12\x16\n\x0e\x62uffer_dropped\x18\n \x01(\x03\x12\x13\n\x0b\x62uffer_size\x18\x0b \x01(\x03\x12\x44\n\x11running_workflows\x18\t \x03(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x46\n\x0erecent_actions\x18\x04 \x03(\x0b\x32..temporal.api.schedule.v1.ScheduleActionResult\x12\x37\n\x13\x66uture_action_times\x18\x05 \x03(\x0b\x32\x1a.google.protobuf.Timestamp\x12/\n\x0b\x63reate_time\x18\x06 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12/\n\x0bupdate_time\x18\x07 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12"\n\x16invalid_schedule_error\x18\x08 \x01(\tB\x02\x18\x01"\xf0\x01\n\x08Schedule\x12\x34\n\x04spec\x18\x01 \x01(\x0b\x32&.temporal.api.schedule.v1.ScheduleSpec\x12\x38\n\x06\x61\x63tion\x18\x02 \x01(\x0b\x32(.temporal.api.schedule.v1.ScheduleAction\x12<\n\x08policies\x18\x03 \x01(\x0b\x32*.temporal.api.schedule.v1.SchedulePolicies\x12\x36\n\x05state\x18\x04 \x01(\x0b\x32\'.temporal.api.schedule.v1.ScheduleState"\xa5\x02\n\x10ScheduleListInfo\x12\x34\n\x04spec\x18\x01 \x01(\x0b\x32&.temporal.api.schedule.v1.ScheduleSpec\x12;\n\rworkflow_type\x18\x02 \x01(\x0b\x32$.temporal.api.common.v1.WorkflowType\x12\r\n\x05notes\x18\x03 \x01(\t\x12\x0e\n\x06paused\x18\x04 \x01(\x08\x12\x46\n\x0erecent_actions\x18\x05 \x03(\x0b\x32..temporal.api.schedule.v1.ScheduleActionResult\x12\x37\n\x13\x66uture_action_times\x18\x06 \x03(\x0b\x32\x1a.google.protobuf.Timestamp"\xd3\x01\n\x11ScheduleListEntry\x12\x13\n\x0bschedule_id\x18\x01 \x01(\t\x12*\n\x04memo\x18\x02 \x01(\x0b\x32\x1c.temporal.api.common.v1.Memo\x12\x43\n\x11search_attributes\x18\x03 \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes\x12\x38\n\x04info\x18\x04 \x01(\x0b\x32*.temporal.api.schedule.v1.ScheduleListInfoB\x93\x01\n\x1bio.temporal.api.schedule.v1B\x0cMessageProtoP\x01Z\'go.temporal.io/api/schedule/v1;schedule\xaa\x02\x1aTemporalio.Api.Schedule.V1\xea\x02\x1dTemporalio::Api::Schedule::V1b\x06proto3' + b'\n&temporal/api/schedule/v1/message.proto\x12\x18temporal.api.schedule.v1\x1a\x1egoogle/protobuf/duration.proto\x1a\x1fgoogle/protobuf/timestamp.proto\x1a$temporal/api/common/v1/message.proto\x1a$temporal/api/enums/v1/schedule.proto\x1a$temporal/api/enums/v1/workflow.proto\x1a&temporal/api/workflow/v1/message.proto"\x95\x01\n\x0c\x43\x61lendarSpec\x12\x0e\n\x06second\x18\x01 \x01(\t\x12\x0e\n\x06minute\x18\x02 \x01(\t\x12\x0c\n\x04hour\x18\x03 \x01(\t\x12\x14\n\x0c\x64\x61y_of_month\x18\x04 \x01(\t\x12\r\n\x05month\x18\x05 \x01(\t\x12\x0c\n\x04year\x18\x06 \x01(\t\x12\x13\n\x0b\x64\x61y_of_week\x18\x07 \x01(\t\x12\x0f\n\x07\x63omment\x18\x08 \x01(\t"1\n\x05Range\x12\r\n\x05start\x18\x01 \x01(\x05\x12\x0b\n\x03\x65nd\x18\x02 \x01(\x05\x12\x0c\n\x04step\x18\x03 \x01(\x05"\x86\x03\n\x16StructuredCalendarSpec\x12/\n\x06second\x18\x01 \x03(\x0b\x32\x1f.temporal.api.schedule.v1.Range\x12/\n\x06minute\x18\x02 \x03(\x0b\x32\x1f.temporal.api.schedule.v1.Range\x12-\n\x04hour\x18\x03 \x03(\x0b\x32\x1f.temporal.api.schedule.v1.Range\x12\x35\n\x0c\x64\x61y_of_month\x18\x04 \x03(\x0b\x32\x1f.temporal.api.schedule.v1.Range\x12.\n\x05month\x18\x05 \x03(\x0b\x32\x1f.temporal.api.schedule.v1.Range\x12-\n\x04year\x18\x06 \x03(\x0b\x32\x1f.temporal.api.schedule.v1.Range\x12\x34\n\x0b\x64\x61y_of_week\x18\x07 \x03(\x0b\x32\x1f.temporal.api.schedule.v1.Range\x12\x0f\n\x07\x63omment\x18\x08 \x01(\t"e\n\x0cIntervalSpec\x12+\n\x08interval\x18\x01 \x01(\x0b\x32\x19.google.protobuf.Duration\x12(\n\x05phase\x18\x02 \x01(\x0b\x32\x19.google.protobuf.Duration"\xba\x04\n\x0cScheduleSpec\x12M\n\x13structured_calendar\x18\x07 \x03(\x0b\x32\x30.temporal.api.schedule.v1.StructuredCalendarSpec\x12\x13\n\x0b\x63ron_string\x18\x08 \x03(\t\x12\x38\n\x08\x63\x61lendar\x18\x01 \x03(\x0b\x32&.temporal.api.schedule.v1.CalendarSpec\x12\x38\n\x08interval\x18\x02 \x03(\x0b\x32&.temporal.api.schedule.v1.IntervalSpec\x12\x44\n\x10\x65xclude_calendar\x18\x03 \x03(\x0b\x32&.temporal.api.schedule.v1.CalendarSpecB\x02\x18\x01\x12U\n\x1b\x65xclude_structured_calendar\x18\t \x03(\x0b\x32\x30.temporal.api.schedule.v1.StructuredCalendarSpec\x12.\n\nstart_time\x18\x04 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12,\n\x08\x65nd_time\x18\x05 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12)\n\x06jitter\x18\x06 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x15\n\rtimezone_name\x18\n \x01(\t\x12\x15\n\rtimezone_data\x18\x0b \x01(\x0c"\xc8\x01\n\x10SchedulePolicies\x12\x44\n\x0eoverlap_policy\x18\x01 \x01(\x0e\x32,.temporal.api.enums.v1.ScheduleOverlapPolicy\x12\x31\n\x0e\x63\x61tchup_window\x18\x02 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x18\n\x10pause_on_failure\x18\x03 \x01(\x08\x12!\n\x19keep_original_workflow_id\x18\x04 \x01(\x08"h\n\x0eScheduleAction\x12L\n\x0estart_workflow\x18\x01 \x01(\x0b\x32\x32.temporal.api.workflow.v1.NewWorkflowExecutionInfoH\x00\x42\x08\n\x06\x61\x63tion"\x93\x02\n\x14ScheduleActionResult\x12\x31\n\rschedule_time\x18\x01 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12/\n\x0b\x61\x63tual_time\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12H\n\x15start_workflow_result\x18\x0b \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12M\n\x15start_workflow_status\x18\x0c \x01(\x0e\x32..temporal.api.enums.v1.WorkflowExecutionStatus"b\n\rScheduleState\x12\r\n\x05notes\x18\x01 \x01(\t\x12\x0e\n\x06paused\x18\x02 \x01(\x08\x12\x17\n\x0flimited_actions\x18\x03 \x01(\x08\x12\x19\n\x11remaining_actions\x18\x04 \x01(\x03"\x95\x01\n\x19TriggerImmediatelyRequest\x12\x44\n\x0eoverlap_policy\x18\x01 \x01(\x0e\x32,.temporal.api.enums.v1.ScheduleOverlapPolicy\x12\x32\n\x0escheduled_time\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.Timestamp"\xb5\x01\n\x0f\x42\x61\x63kfillRequest\x12.\n\nstart_time\x18\x01 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12,\n\x08\x65nd_time\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x44\n\x0eoverlap_policy\x18\x03 \x01(\x0e\x32,.temporal.api.enums.v1.ScheduleOverlapPolicy"\xc6\x01\n\rSchedulePatch\x12P\n\x13trigger_immediately\x18\x01 \x01(\x0b\x32\x33.temporal.api.schedule.v1.TriggerImmediatelyRequest\x12\x43\n\x10\x62\x61\x63kfill_request\x18\x02 \x03(\x0b\x32).temporal.api.schedule.v1.BackfillRequest\x12\r\n\x05pause\x18\x03 \x01(\t\x12\x0f\n\x07unpause\x18\x04 \x01(\t"\xf0\x03\n\x0cScheduleInfo\x12\x14\n\x0c\x61\x63tion_count\x18\x01 \x01(\x03\x12\x1d\n\x15missed_catchup_window\x18\x02 \x01(\x03\x12\x17\n\x0foverlap_skipped\x18\x03 \x01(\x03\x12\x16\n\x0e\x62uffer_dropped\x18\n \x01(\x03\x12\x13\n\x0b\x62uffer_size\x18\x0b \x01(\x03\x12\x44\n\x11running_workflows\x18\t \x03(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x46\n\x0erecent_actions\x18\x04 \x03(\x0b\x32..temporal.api.schedule.v1.ScheduleActionResult\x12\x37\n\x13\x66uture_action_times\x18\x05 \x03(\x0b\x32\x1a.google.protobuf.Timestamp\x12/\n\x0b\x63reate_time\x18\x06 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12/\n\x0bupdate_time\x18\x07 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12"\n\x16invalid_schedule_error\x18\x08 \x01(\tB\x02\x18\x01\x12\x18\n\x10state_size_bytes\x18\x0c \x01(\x03"\xf0\x01\n\x08Schedule\x12\x34\n\x04spec\x18\x01 \x01(\x0b\x32&.temporal.api.schedule.v1.ScheduleSpec\x12\x38\n\x06\x61\x63tion\x18\x02 \x01(\x0b\x32(.temporal.api.schedule.v1.ScheduleAction\x12<\n\x08policies\x18\x03 \x01(\x0b\x32*.temporal.api.schedule.v1.SchedulePolicies\x12\x36\n\x05state\x18\x04 \x01(\x0b\x32\'.temporal.api.schedule.v1.ScheduleState"\xbf\x02\n\x10ScheduleListInfo\x12\x34\n\x04spec\x18\x01 \x01(\x0b\x32&.temporal.api.schedule.v1.ScheduleSpec\x12;\n\rworkflow_type\x18\x02 \x01(\x0b\x32$.temporal.api.common.v1.WorkflowType\x12\r\n\x05notes\x18\x03 \x01(\t\x12\x0e\n\x06paused\x18\x04 \x01(\x08\x12\x46\n\x0erecent_actions\x18\x05 \x03(\x0b\x32..temporal.api.schedule.v1.ScheduleActionResult\x12\x37\n\x13\x66uture_action_times\x18\x06 \x03(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x18\n\x10state_size_bytes\x18\x07 \x01(\x03"\xd3\x01\n\x11ScheduleListEntry\x12\x13\n\x0bschedule_id\x18\x01 \x01(\t\x12*\n\x04memo\x18\x02 \x01(\x0b\x32\x1c.temporal.api.common.v1.Memo\x12\x43\n\x11search_attributes\x18\x03 \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes\x12\x38\n\x04info\x18\x04 \x01(\x0b\x32*.temporal.api.schedule.v1.ScheduleListInfoB\x93\x01\n\x1bio.temporal.api.schedule.v1B\x0cMessageProtoP\x01Z\'go.temporal.io/api/schedule/v1;schedule\xaa\x02\x1aTemporalio.Api.Schedule.V1\xea\x02\x1dTemporalio::Api::Schedule::V1b\x06proto3' ) @@ -263,11 +263,11 @@ _SCHEDULEPATCH._serialized_start = 2583 _SCHEDULEPATCH._serialized_end = 2781 _SCHEDULEINFO._serialized_start = 2784 - _SCHEDULEINFO._serialized_end = 3254 - _SCHEDULE._serialized_start = 3257 - _SCHEDULE._serialized_end = 3497 - _SCHEDULELISTINFO._serialized_start = 3500 - _SCHEDULELISTINFO._serialized_end = 3793 - _SCHEDULELISTENTRY._serialized_start = 3796 - _SCHEDULELISTENTRY._serialized_end = 4007 + _SCHEDULEINFO._serialized_end = 3280 + _SCHEDULE._serialized_start = 3283 + _SCHEDULE._serialized_end = 3523 + _SCHEDULELISTINFO._serialized_start = 3526 + _SCHEDULELISTINFO._serialized_end = 3845 + _SCHEDULELISTENTRY._serialized_start = 3848 + _SCHEDULELISTENTRY._serialized_end = 4059 # @@protoc_insertion_point(module_scope) diff --git a/temporalio/api/schedule/v1/message_pb2.pyi b/temporalio/api/schedule/v1/message_pb2.pyi index 76f6cccf3..fe7c1e900 100644 --- a/temporalio/api/schedule/v1/message_pb2.pyi +++ b/temporalio/api/schedule/v1/message_pb2.pyi @@ -841,6 +841,7 @@ class ScheduleInfo(google.protobuf.message.Message): CREATE_TIME_FIELD_NUMBER: builtins.int UPDATE_TIME_FIELD_NUMBER: builtins.int INVALID_SCHEDULE_ERROR_FIELD_NUMBER: builtins.int + STATE_SIZE_BYTES_FIELD_NUMBER: builtins.int action_count: builtins.int """Number of actions taken so far.""" missed_catchup_window: builtins.int @@ -887,6 +888,8 @@ class ScheduleInfo(google.protobuf.message.Message): def update_time(self) -> google.protobuf.timestamp_pb2.Timestamp: ... invalid_schedule_error: builtins.str """Deprecated.""" + state_size_bytes: builtins.int + """Size of the schedule's internal state (including payloads) in bytes.""" def __init__( self, *, @@ -908,6 +911,7 @@ class ScheduleInfo(google.protobuf.message.Message): create_time: google.protobuf.timestamp_pb2.Timestamp | None = ..., update_time: google.protobuf.timestamp_pb2.Timestamp | None = ..., invalid_schedule_error: builtins.str = ..., + state_size_bytes: builtins.int = ..., ) -> None: ... def HasField( self, @@ -938,6 +942,8 @@ class ScheduleInfo(google.protobuf.message.Message): b"recent_actions", "running_workflows", b"running_workflows", + "state_size_bytes", + b"state_size_bytes", "update_time", b"update_time", ], @@ -1010,6 +1016,7 @@ class ScheduleListInfo(google.protobuf.message.Message): PAUSED_FIELD_NUMBER: builtins.int RECENT_ACTIONS_FIELD_NUMBER: builtins.int FUTURE_ACTION_TIMES_FIELD_NUMBER: builtins.int + STATE_SIZE_BYTES_FIELD_NUMBER: builtins.int @property def spec(self) -> global___ScheduleSpec: """From spec: @@ -1037,6 +1044,8 @@ class ScheduleListInfo(google.protobuf.message.Message): ) -> google.protobuf.internal.containers.RepeatedCompositeFieldContainer[ google.protobuf.timestamp_pb2.Timestamp ]: ... + state_size_bytes: builtins.int + """Size of the schedule's internal state (including payloads) in bytes.""" def __init__( self, *, @@ -1050,6 +1059,7 @@ class ScheduleListInfo(google.protobuf.message.Message): google.protobuf.timestamp_pb2.Timestamp ] | None = ..., + state_size_bytes: builtins.int = ..., ) -> None: ... def HasField( self, @@ -1070,6 +1080,8 @@ class ScheduleListInfo(google.protobuf.message.Message): b"recent_actions", "spec", b"spec", + "state_size_bytes", + b"state_size_bytes", "workflow_type", b"workflow_type", ], diff --git a/temporalio/api/update/v1/message_pb2.py b/temporalio/api/update/v1/message_pb2.py index b0517a662..d136516bc 100644 --- a/temporalio/api/update/v1/message_pb2.py +++ b/temporalio/api/update/v1/message_pb2.py @@ -25,7 +25,7 @@ ) DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile( - b'\n$temporal/api/update/v1/message.proto\x12\x16temporal.api.update.v1\x1a$temporal/api/common/v1/message.proto\x1a"temporal/api/enums/v1/update.proto\x1a%temporal/api/failure/v1/message.proto"c\n\nWaitPolicy\x12U\n\x0flifecycle_stage\x18\x01 \x01(\x0e\x32<.temporal.api.enums.v1.UpdateWorkflowExecutionLifecycleStage"e\n\tUpdateRef\x12\x45\n\x12workflow_execution\x18\x01 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x11\n\tupdate_id\x18\x02 \x01(\t"|\n\x07Outcome\x12\x33\n\x07success\x18\x01 \x01(\x0b\x32 .temporal.api.common.v1.PayloadsH\x00\x12\x33\n\x07\x66\x61ilure\x18\x02 \x01(\x0b\x32 .temporal.api.failure.v1.FailureH\x00\x42\x07\n\x05value"+\n\x04Meta\x12\x11\n\tupdate_id\x18\x01 \x01(\t\x12\x10\n\x08identity\x18\x02 \x01(\t"u\n\x05Input\x12.\n\x06header\x18\x01 \x01(\x0b\x32\x1e.temporal.api.common.v1.Header\x12\x0c\n\x04name\x18\x02 \x01(\t\x12.\n\x04\x61rgs\x18\x03 \x01(\x0b\x32 .temporal.api.common.v1.Payloads"c\n\x07Request\x12*\n\x04meta\x18\x01 \x01(\x0b\x32\x1c.temporal.api.update.v1.Meta\x12,\n\x05input\x18\x02 \x01(\x0b\x32\x1d.temporal.api.update.v1.Input"\xcc\x01\n\tRejection\x12#\n\x1brejected_request_message_id\x18\x01 \x01(\t\x12,\n$rejected_request_sequencing_event_id\x18\x02 \x01(\x03\x12\x39\n\x10rejected_request\x18\x03 \x01(\x0b\x32\x1f.temporal.api.update.v1.Request\x12\x31\n\x07\x66\x61ilure\x18\x04 \x01(\x0b\x32 .temporal.api.failure.v1.Failure"\x9a\x01\n\nAcceptance\x12#\n\x1b\x61\x63\x63\x65pted_request_message_id\x18\x01 \x01(\t\x12,\n$accepted_request_sequencing_event_id\x18\x02 \x01(\x03\x12\x39\n\x10\x61\x63\x63\x65pted_request\x18\x03 \x01(\x0b\x32\x1f.temporal.api.update.v1.Request"h\n\x08Response\x12*\n\x04meta\x18\x01 \x01(\x0b\x32\x1c.temporal.api.update.v1.Meta\x12\x30\n\x07outcome\x18\x02 \x01(\x0b\x32\x1f.temporal.api.update.v1.OutcomeB\x89\x01\n\x19io.temporal.api.update.v1B\x0cMessageProtoP\x01Z#go.temporal.io/api/update/v1;update\xaa\x02\x18Temporalio.Api.Update.V1\xea\x02\x1bTemporalio::Api::Update::V1b\x06proto3' + b'\n$temporal/api/update/v1/message.proto\x12\x16temporal.api.update.v1\x1a$temporal/api/common/v1/message.proto\x1a"temporal/api/enums/v1/update.proto\x1a%temporal/api/failure/v1/message.proto"c\n\nWaitPolicy\x12U\n\x0flifecycle_stage\x18\x01 \x01(\x0e\x32<.temporal.api.enums.v1.UpdateWorkflowExecutionLifecycleStage"e\n\tUpdateRef\x12\x45\n\x12workflow_execution\x18\x01 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x11\n\tupdate_id\x18\x02 \x01(\t"|\n\x07Outcome\x12\x33\n\x07success\x18\x01 \x01(\x0b\x32 .temporal.api.common.v1.PayloadsH\x00\x12\x33\n\x07\x66\x61ilure\x18\x02 \x01(\x0b\x32 .temporal.api.failure.v1.FailureH\x00\x42\x07\n\x05value"+\n\x04Meta\x12\x11\n\tupdate_id\x18\x01 \x01(\t\x12\x10\n\x08identity\x18\x02 \x01(\t"u\n\x05Input\x12.\n\x06header\x18\x01 \x01(\x0b\x32\x1e.temporal.api.common.v1.Header\x12\x0c\n\x04name\x18\x02 \x01(\t\x12.\n\x04\x61rgs\x18\x03 \x01(\x0b\x32 .temporal.api.common.v1.Payloads"\xe4\x01\n\x07Request\x12*\n\x04meta\x18\x01 \x01(\x0b\x32\x1c.temporal.api.update.v1.Meta\x12,\n\x05input\x18\x02 \x01(\x0b\x32\x1d.temporal.api.update.v1.Input\x12\x12\n\nrequest_id\x18\x03 \x01(\t\x12>\n\x14\x63ompletion_callbacks\x18\x04 \x03(\x0b\x32 .temporal.api.common.v1.Callback\x12+\n\x05links\x18\x05 \x03(\x0b\x32\x1c.temporal.api.common.v1.Link"\xcc\x01\n\tRejection\x12#\n\x1brejected_request_message_id\x18\x01 \x01(\t\x12,\n$rejected_request_sequencing_event_id\x18\x02 \x01(\x03\x12\x39\n\x10rejected_request\x18\x03 \x01(\x0b\x32\x1f.temporal.api.update.v1.Request\x12\x31\n\x07\x66\x61ilure\x18\x04 \x01(\x0b\x32 .temporal.api.failure.v1.Failure"\x9a\x01\n\nAcceptance\x12#\n\x1b\x61\x63\x63\x65pted_request_message_id\x18\x01 \x01(\t\x12,\n$accepted_request_sequencing_event_id\x18\x02 \x01(\x03\x12\x39\n\x10\x61\x63\x63\x65pted_request\x18\x03 \x01(\x0b\x32\x1f.temporal.api.update.v1.Request"h\n\x08Response\x12*\n\x04meta\x18\x01 \x01(\x0b\x32\x1c.temporal.api.update.v1.Meta\x12\x30\n\x07outcome\x18\x02 \x01(\x0b\x32\x1f.temporal.api.update.v1.OutcomeB\x89\x01\n\x19io.temporal.api.update.v1B\x0cMessageProtoP\x01Z#go.temporal.io/api/update/v1;update\xaa\x02\x18Temporalio.Api.Update.V1\xea\x02\x1bTemporalio::Api::Update::V1b\x06proto3' ) @@ -150,12 +150,12 @@ _META._serialized_end = 550 _INPUT._serialized_start = 552 _INPUT._serialized_end = 669 - _REQUEST._serialized_start = 671 - _REQUEST._serialized_end = 770 - _REJECTION._serialized_start = 773 - _REJECTION._serialized_end = 977 - _ACCEPTANCE._serialized_start = 980 - _ACCEPTANCE._serialized_end = 1134 - _RESPONSE._serialized_start = 1136 - _RESPONSE._serialized_end = 1240 + _REQUEST._serialized_start = 672 + _REQUEST._serialized_end = 900 + _REJECTION._serialized_start = 903 + _REJECTION._serialized_end = 1107 + _ACCEPTANCE._serialized_start = 1110 + _ACCEPTANCE._serialized_end = 1264 + _RESPONSE._serialized_start = 1266 + _RESPONSE._serialized_end = 1370 # @@protoc_insertion_point(module_scope) diff --git a/temporalio/api/update/v1/message_pb2.pyi b/temporalio/api/update/v1/message_pb2.pyi index 072821a0c..de3c6682c 100644 --- a/temporalio/api/update/v1/message_pb2.pyi +++ b/temporalio/api/update/v1/message_pb2.pyi @@ -4,9 +4,11 @@ isort:skip_file """ import builtins +import collections.abc import sys import google.protobuf.descriptor +import google.protobuf.internal.containers import google.protobuf.message import temporalio.api.common.v1.message_pb2 @@ -183,21 +185,59 @@ class Request(google.protobuf.message.Message): META_FIELD_NUMBER: builtins.int INPUT_FIELD_NUMBER: builtins.int + REQUEST_ID_FIELD_NUMBER: builtins.int + COMPLETION_CALLBACKS_FIELD_NUMBER: builtins.int + LINKS_FIELD_NUMBER: builtins.int @property def meta(self) -> global___Meta: ... @property def input(self) -> global___Input: ... + request_id: builtins.str + """The request ID of the request.""" + @property + def completion_callbacks( + self, + ) -> google.protobuf.internal.containers.RepeatedCompositeFieldContainer[ + temporalio.api.common.v1.message_pb2.Callback + ]: + """Callbacks to be called by the server when this update reaches a terminal state.""" + @property + def links( + self, + ) -> google.protobuf.internal.containers.RepeatedCompositeFieldContainer[ + temporalio.api.common.v1.message_pb2.Link + ]: + """Links to be associated with this update.""" def __init__( self, *, meta: global___Meta | None = ..., input: global___Input | None = ..., + request_id: builtins.str = ..., + completion_callbacks: collections.abc.Iterable[ + temporalio.api.common.v1.message_pb2.Callback + ] + | None = ..., + links: collections.abc.Iterable[temporalio.api.common.v1.message_pb2.Link] + | None = ..., ) -> None: ... def HasField( self, field_name: typing_extensions.Literal["input", b"input", "meta", b"meta"] ) -> builtins.bool: ... def ClearField( - self, field_name: typing_extensions.Literal["input", b"input", "meta", b"meta"] + self, + field_name: typing_extensions.Literal[ + "completion_callbacks", + b"completion_callbacks", + "input", + b"input", + "links", + b"links", + "meta", + b"meta", + "request_id", + b"request_id", + ], ) -> None: ... global___Request = Request diff --git a/temporalio/api/workflow/v1/message_pb2.py b/temporalio/api/workflow/v1/message_pb2.py index f88688df8..70d909746 100644 --- a/temporalio/api/workflow/v1/message_pb2.py +++ b/temporalio/api/workflow/v1/message_pb2.py @@ -48,7 +48,7 @@ ) DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile( - b'\n&temporal/api/workflow/v1/message.proto\x12\x18temporal.api.workflow.v1\x1a\x1egoogle/protobuf/duration.proto\x1a\x1bgoogle/protobuf/empty.proto\x1a\x1fgoogle/protobuf/timestamp.proto\x1a google/protobuf/field_mask.proto\x1a&temporal/api/activity/v1/message.proto\x1a"temporal/api/enums/v1/common.proto\x1a&temporal/api/enums/v1/event_type.proto\x1a$temporal/api/enums/v1/workflow.proto\x1a$temporal/api/common/v1/message.proto\x1a(temporal/api/deployment/v1/message.proto\x1a%temporal/api/failure/v1/message.proto\x1a\'temporal/api/taskqueue/v1/message.proto\x1a\'temporal/api/sdk/v1/user_metadata.proto"\xf0\t\n\x15WorkflowExecutionInfo\x12<\n\texecution\x18\x01 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x32\n\x04type\x18\x02 \x01(\x0b\x32$.temporal.api.common.v1.WorkflowType\x12.\n\nstart_time\x18\x03 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12.\n\nclose_time\x18\x04 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12>\n\x06status\x18\x05 \x01(\x0e\x32..temporal.api.enums.v1.WorkflowExecutionStatus\x12\x16\n\x0ehistory_length\x18\x06 \x01(\x03\x12\x1b\n\x13parent_namespace_id\x18\x07 \x01(\t\x12\x43\n\x10parent_execution\x18\x08 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x32\n\x0e\x65xecution_time\x18\t \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12*\n\x04memo\x18\n \x01(\x0b\x32\x1c.temporal.api.common.v1.Memo\x12\x43\n\x11search_attributes\x18\x0b \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes\x12@\n\x11\x61uto_reset_points\x18\x0c \x01(\x0b\x32%.temporal.api.workflow.v1.ResetPoints\x12\x12\n\ntask_queue\x18\r \x01(\t\x12\x1e\n\x16state_transition_count\x18\x0e \x01(\x03\x12\x1a\n\x12history_size_bytes\x18\x0f \x01(\x03\x12X\n most_recent_worker_version_stamp\x18\x10 \x01(\x0b\x32*.temporal.api.common.v1.WorkerVersionStampB\x02\x18\x01\x12\x35\n\x12\x65xecution_duration\x18\x11 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x41\n\x0eroot_execution\x18\x12 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x1d\n\x11\x61ssigned_build_id\x18\x13 \x01(\tB\x02\x18\x01\x12\x1e\n\x12inherited_build_id\x18\x14 \x01(\tB\x02\x18\x01\x12\x14\n\x0c\x66irst_run_id\x18\x15 \x01(\t\x12R\n\x0fversioning_info\x18\x16 \x01(\x0b\x32\x39.temporal.api.workflow.v1.WorkflowExecutionVersioningInfo\x12\x1e\n\x16worker_deployment_name\x18\x17 \x01(\t\x12\x32\n\x08priority\x18\x18 \x01(\x0b\x32 .temporal.api.common.v1.Priority\x12#\n\x1b\x65xternal_payload_size_bytes\x18\x19 \x01(\x03\x12\x1e\n\x16\x65xternal_payload_count\x18\x1a \x01(\x03"\xc6\x04\n\x1dWorkflowExecutionExtendedInfo\x12=\n\x19\x65xecution_expiration_time\x18\x01 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x37\n\x13run_expiration_time\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x18\n\x10\x63\x61ncel_requested\x18\x03 \x01(\x08\x12\x33\n\x0flast_reset_time\x18\x04 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x37\n\x13original_start_time\x18\x05 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x14\n\x0creset_run_id\x18\x06 \x01(\t\x12\x65\n\x10request_id_infos\x18\x07 \x03(\x0b\x32K.temporal.api.workflow.v1.WorkflowExecutionExtendedInfo.RequestIdInfosEntry\x12H\n\npause_info\x18\x08 \x01(\x0b\x32\x34.temporal.api.workflow.v1.WorkflowExecutionPauseInfo\x1a^\n\x13RequestIdInfosEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x36\n\x05value\x18\x02 \x01(\x0b\x32\'.temporal.api.workflow.v1.RequestIdInfo:\x02\x38\x01"\xfb\x04\n\x1fWorkflowExecutionVersioningInfo\x12;\n\x08\x62\x65havior\x18\x01 \x01(\x0e\x32).temporal.api.enums.v1.VersioningBehavior\x12>\n\ndeployment\x18\x02 \x01(\x0b\x32&.temporal.api.deployment.v1.DeploymentB\x02\x18\x01\x12\x13\n\x07version\x18\x05 \x01(\tB\x02\x18\x01\x12O\n\x12\x64\x65ployment_version\x18\x07 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersion\x12I\n\x13versioning_override\x18\x03 \x01(\x0b\x32,.temporal.api.workflow.v1.VersioningOverride\x12Q\n\x15\x64\x65ployment_transition\x18\x04 \x01(\x0b\x32..temporal.api.workflow.v1.DeploymentTransitionB\x02\x18\x01\x12Q\n\x12version_transition\x18\x06 \x01(\x0b\x32\x35.temporal.api.workflow.v1.DeploymentVersionTransition\x12\x17\n\x0frevision_number\x18\x08 \x01(\x03\x12k\n+continue_as_new_initial_versioning_behavior\x18\t \x01(\x0e\x32\x36.temporal.api.enums.v1.ContinueAsNewVersioningBehavior"R\n\x14\x44\x65ploymentTransition\x12:\n\ndeployment\x18\x01 \x01(\x0b\x32&.temporal.api.deployment.v1.Deployment"\x83\x01\n\x1b\x44\x65ploymentVersionTransition\x12\x13\n\x07version\x18\x01 \x01(\tB\x02\x18\x01\x12O\n\x12\x64\x65ployment_version\x18\x02 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersion"\xc7\x02\n\x17WorkflowExecutionConfig\x12\x38\n\ntask_queue\x18\x01 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12=\n\x1aworkflow_execution_timeout\x18\x02 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x37\n\x14workflow_run_timeout\x18\x03 \x01(\x0b\x32\x19.google.protobuf.Duration\x12@\n\x1d\x64\x65\x66\x61ult_workflow_task_timeout\x18\x04 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x38\n\ruser_metadata\x18\x05 \x01(\x0b\x32!.temporal.api.sdk.v1.UserMetadata"\xbd\r\n\x13PendingActivityInfo\x12\x13\n\x0b\x61\x63tivity_id\x18\x01 \x01(\t\x12;\n\ractivity_type\x18\x02 \x01(\x0b\x32$.temporal.api.common.v1.ActivityType\x12:\n\x05state\x18\x03 \x01(\x0e\x32+.temporal.api.enums.v1.PendingActivityState\x12;\n\x11heartbeat_details\x18\x04 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x37\n\x13last_heartbeat_time\x18\x05 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x35\n\x11last_started_time\x18\x06 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x0f\n\x07\x61ttempt\x18\x07 \x01(\x05\x12\x18\n\x10maximum_attempts\x18\x08 \x01(\x05\x12\x32\n\x0escheduled_time\x18\t \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x33\n\x0f\x65xpiration_time\x18\n \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x36\n\x0clast_failure\x18\x0b \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12\x1c\n\x14last_worker_identity\x18\x0c \x01(\t\x12;\n\x15use_workflow_build_id\x18\r \x01(\x0b\x32\x16.google.protobuf.EmptyB\x02\x18\x01H\x00\x12\x32\n$last_independently_assigned_build_id\x18\x0e \x01(\tB\x02\x18\x01H\x00\x12Q\n\x19last_worker_version_stamp\x18\x0f \x01(\x0b\x32*.temporal.api.common.v1.WorkerVersionStampB\x02\x18\x01\x12\x39\n\x16\x63urrent_retry_interval\x18\x10 \x01(\x0b\x32\x19.google.protobuf.Duration\x12>\n\x1alast_attempt_complete_time\x18\x11 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12>\n\x1anext_attempt_schedule_time\x18\x12 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x0e\n\x06paused\x18\x13 \x01(\x08\x12\x43\n\x0flast_deployment\x18\x14 \x01(\x0b\x32&.temporal.api.deployment.v1.DeploymentB\x02\x18\x01\x12*\n\x1elast_worker_deployment_version\x18\x15 \x01(\tB\x02\x18\x01\x12T\n\x17last_deployment_version\x18\x19 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersion\x12\x32\n\x08priority\x18\x16 \x01(\x0b\x32 .temporal.api.common.v1.Priority\x12K\n\npause_info\x18\x17 \x01(\x0b\x32\x37.temporal.api.workflow.v1.PendingActivityInfo.PauseInfo\x12\x43\n\x10\x61\x63tivity_options\x18\x18 \x01(\x0b\x32).temporal.api.activity.v1.ActivityOptions\x1a\xcf\x02\n\tPauseInfo\x12.\n\npause_time\x18\x01 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12P\n\x06manual\x18\x02 \x01(\x0b\x32>.temporal.api.workflow.v1.PendingActivityInfo.PauseInfo.ManualH\x00\x12L\n\x04rule\x18\x04 \x01(\x0b\x32<.temporal.api.workflow.v1.PendingActivityInfo.PauseInfo.RuleH\x00\x1a*\n\x06Manual\x12\x10\n\x08identity\x18\x01 \x01(\t\x12\x0e\n\x06reason\x18\x02 \x01(\t\x1a\x39\n\x04Rule\x12\x0f\n\x07rule_id\x18\x01 \x01(\t\x12\x10\n\x08identity\x18\x02 \x01(\t\x12\x0e\n\x06reason\x18\x03 \x01(\tB\x0b\n\tpaused_byB\x13\n\x11\x61ssigned_build_id"\xb9\x01\n\x19PendingChildExecutionInfo\x12\x13\n\x0bworkflow_id\x18\x01 \x01(\t\x12\x0e\n\x06run_id\x18\x02 \x01(\t\x12\x1a\n\x12workflow_type_name\x18\x03 \x01(\t\x12\x14\n\x0cinitiated_id\x18\x04 \x01(\x03\x12\x45\n\x13parent_close_policy\x18\x05 \x01(\x0e\x32(.temporal.api.enums.v1.ParentClosePolicy"\x8d\x02\n\x17PendingWorkflowTaskInfo\x12>\n\x05state\x18\x01 \x01(\x0e\x32/.temporal.api.enums.v1.PendingWorkflowTaskState\x12\x32\n\x0escheduled_time\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12;\n\x17original_scheduled_time\x18\x03 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x30\n\x0cstarted_time\x18\x04 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x0f\n\x07\x61ttempt\x18\x05 \x01(\x05"G\n\x0bResetPoints\x12\x38\n\x06points\x18\x01 \x03(\x0b\x32(.temporal.api.workflow.v1.ResetPointInfo"\xef\x01\n\x0eResetPointInfo\x12\x10\n\x08\x62uild_id\x18\x07 \x01(\t\x12\x1b\n\x0f\x62inary_checksum\x18\x01 \x01(\tB\x02\x18\x01\x12\x0e\n\x06run_id\x18\x02 \x01(\t\x12(\n first_workflow_task_completed_id\x18\x03 \x01(\x03\x12/\n\x0b\x63reate_time\x18\x04 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12/\n\x0b\x65xpire_time\x18\x05 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x12\n\nresettable\x18\x06 \x01(\x08"\x85\x07\n\x18NewWorkflowExecutionInfo\x12\x13\n\x0bworkflow_id\x18\x01 \x01(\t\x12;\n\rworkflow_type\x18\x02 \x01(\x0b\x32$.temporal.api.common.v1.WorkflowType\x12\x38\n\ntask_queue\x18\x03 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12/\n\x05input\x18\x04 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12=\n\x1aworkflow_execution_timeout\x18\x05 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x37\n\x14workflow_run_timeout\x18\x06 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x38\n\x15workflow_task_timeout\x18\x07 \x01(\x0b\x32\x19.google.protobuf.Duration\x12N\n\x18workflow_id_reuse_policy\x18\x08 \x01(\x0e\x32,.temporal.api.enums.v1.WorkflowIdReusePolicy\x12\x39\n\x0cretry_policy\x18\t \x01(\x0b\x32#.temporal.api.common.v1.RetryPolicy\x12\x15\n\rcron_schedule\x18\n \x01(\t\x12*\n\x04memo\x18\x0b \x01(\x0b\x32\x1c.temporal.api.common.v1.Memo\x12\x43\n\x11search_attributes\x18\x0c \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes\x12.\n\x06header\x18\r \x01(\x0b\x32\x1e.temporal.api.common.v1.Header\x12\x38\n\ruser_metadata\x18\x0e \x01(\x0b\x32!.temporal.api.sdk.v1.UserMetadata\x12I\n\x13versioning_override\x18\x0f \x01(\x0b\x32,.temporal.api.workflow.v1.VersioningOverride\x12\x32\n\x08priority\x18\x10 \x01(\x0b\x32 .temporal.api.common.v1.Priority"\xd2\x04\n\x0c\x43\x61llbackInfo\x12\x32\n\x08\x63\x61llback\x18\x01 \x01(\x0b\x32 .temporal.api.common.v1.Callback\x12?\n\x07trigger\x18\x02 \x01(\x0b\x32..temporal.api.workflow.v1.CallbackInfo.Trigger\x12\x35\n\x11registration_time\x18\x03 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x33\n\x05state\x18\x04 \x01(\x0e\x32$.temporal.api.enums.v1.CallbackState\x12\x0f\n\x07\x61ttempt\x18\x05 \x01(\x05\x12>\n\x1alast_attempt_complete_time\x18\x06 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12>\n\x14last_attempt_failure\x18\x07 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12>\n\x1anext_attempt_schedule_time\x18\x08 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x16\n\x0e\x62locked_reason\x18\t \x01(\t\x1a\x10\n\x0eWorkflowClosed\x1a\x66\n\x07Trigger\x12P\n\x0fworkflow_closed\x18\x01 \x01(\x0b\x32\x35.temporal.api.workflow.v1.CallbackInfo.WorkflowClosedH\x00\x42\t\n\x07variant"\x8b\x06\n\x19PendingNexusOperationInfo\x12\x10\n\x08\x65ndpoint\x18\x01 \x01(\t\x12\x0f\n\x07service\x18\x02 \x01(\t\x12\x11\n\toperation\x18\x03 \x01(\t\x12\x18\n\x0coperation_id\x18\x04 \x01(\tB\x02\x18\x01\x12<\n\x19schedule_to_close_timeout\x18\x05 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x32\n\x0escheduled_time\x18\x06 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12@\n\x05state\x18\x07 \x01(\x0e\x32\x31.temporal.api.enums.v1.PendingNexusOperationState\x12\x0f\n\x07\x61ttempt\x18\x08 \x01(\x05\x12>\n\x1alast_attempt_complete_time\x18\t \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12>\n\x14last_attempt_failure\x18\n \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12>\n\x1anext_attempt_schedule_time\x18\x0b \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12S\n\x11\x63\x61ncellation_info\x18\x0c \x01(\x0b\x32\x38.temporal.api.workflow.v1.NexusOperationCancellationInfo\x12\x1a\n\x12scheduled_event_id\x18\r \x01(\x03\x12\x16\n\x0e\x62locked_reason\x18\x0e \x01(\t\x12\x17\n\x0foperation_token\x18\x0f \x01(\t\x12<\n\x19schedule_to_start_timeout\x18\x10 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x39\n\x16start_to_close_timeout\x18\x11 \x01(\x0b\x32\x19.google.protobuf.Duration"\x84\x03\n\x1eNexusOperationCancellationInfo\x12\x32\n\x0erequested_time\x18\x01 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x45\n\x05state\x18\x02 \x01(\x0e\x32\x36.temporal.api.enums.v1.NexusOperationCancellationState\x12\x0f\n\x07\x61ttempt\x18\x03 \x01(\x05\x12>\n\x1alast_attempt_complete_time\x18\x04 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12>\n\x14last_attempt_failure\x18\x05 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12>\n\x1anext_attempt_schedule_time\x18\x06 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x16\n\x0e\x62locked_reason\x18\x07 \x01(\t"\xe5\x01\n\x18WorkflowExecutionOptions\x12I\n\x13versioning_override\x18\x01 \x01(\x0b\x32,.temporal.api.workflow.v1.VersioningOverride\x12\x32\n\x08priority\x18\x02 \x01(\x0b\x32 .temporal.api.common.v1.Priority\x12J\n\x14time_skipping_config\x18\x03 \x01(\x0b\x32,.temporal.api.workflow.v1.TimeSkippingConfig"\xf8\x01\n\x12TimeSkippingConfig\x12\x0f\n\x07\x65nabled\x18\x01 \x01(\x08\x12\x1b\n\x13\x64isable_propagation\x18\x02 \x01(\x08\x12\x39\n\x14max_skipped_duration\x18\x04 \x01(\x0b\x32\x19.google.protobuf.DurationH\x00\x12\x39\n\x14max_elapsed_duration\x18\x05 \x01(\x0b\x32\x19.google.protobuf.DurationH\x00\x12\x35\n\x0fmax_target_time\x18\x06 \x01(\x0b\x32\x1a.google.protobuf.TimestampH\x00\x42\x07\n\x05\x62ound"\xbd\x04\n\x12VersioningOverride\x12M\n\x06pinned\x18\x03 \x01(\x0b\x32;.temporal.api.workflow.v1.VersioningOverride.PinnedOverrideH\x00\x12\x16\n\x0c\x61uto_upgrade\x18\x04 \x01(\x08H\x00\x12?\n\x08\x62\x65havior\x18\x01 \x01(\x0e\x32).temporal.api.enums.v1.VersioningBehaviorB\x02\x18\x01\x12>\n\ndeployment\x18\x02 \x01(\x0b\x32&.temporal.api.deployment.v1.DeploymentB\x02\x18\x01\x12\x1a\n\x0epinned_version\x18\t \x01(\tB\x02\x18\x01\x1a\xad\x01\n\x0ePinnedOverride\x12U\n\x08\x62\x65havior\x18\x01 \x01(\x0e\x32\x43.temporal.api.workflow.v1.VersioningOverride.PinnedOverrideBehavior\x12\x44\n\x07version\x18\x02 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersion"g\n\x16PinnedOverrideBehavior\x12(\n$PINNED_OVERRIDE_BEHAVIOR_UNSPECIFIED\x10\x00\x12#\n\x1fPINNED_OVERRIDE_BEHAVIOR_PINNED\x10\x01\x42\n\n\x08override"i\n\x11OnConflictOptions\x12\x19\n\x11\x61ttach_request_id\x18\x01 \x01(\x08\x12#\n\x1b\x61ttach_completion_callbacks\x18\x02 \x01(\x08\x12\x14\n\x0c\x61ttach_links\x18\x03 \x01(\x08"i\n\rRequestIdInfo\x12\x34\n\nevent_type\x18\x01 \x01(\x0e\x32 .temporal.api.enums.v1.EventType\x12\x10\n\x08\x65vent_id\x18\x02 \x01(\x03\x12\x10\n\x08\x62uffered\x18\x03 \x01(\x08"\xb7\x04\n\x12PostResetOperation\x12V\n\x0fsignal_workflow\x18\x01 \x01(\x0b\x32;.temporal.api.workflow.v1.PostResetOperation.SignalWorkflowH\x00\x12\x65\n\x17update_workflow_options\x18\x02 \x01(\x0b\x32\x42.temporal.api.workflow.v1.PostResetOperation.UpdateWorkflowOptionsH\x00\x1a\xb3\x01\n\x0eSignalWorkflow\x12\x13\n\x0bsignal_name\x18\x01 \x01(\t\x12/\n\x05input\x18\x02 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12.\n\x06header\x18\x03 \x01(\x0b\x32\x1e.temporal.api.common.v1.Header\x12+\n\x05links\x18\x04 \x03(\x0b\x32\x1c.temporal.api.common.v1.Link\x1a\xa0\x01\n\x15UpdateWorkflowOptions\x12V\n\x1aworkflow_execution_options\x18\x01 \x01(\x0b\x32\x32.temporal.api.workflow.v1.WorkflowExecutionOptions\x12/\n\x0bupdate_mask\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.FieldMaskB\t\n\x07variant"o\n\x1aWorkflowExecutionPauseInfo\x12\x10\n\x08identity\x18\x01 \x01(\t\x12/\n\x0bpaused_time\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x0e\n\x06reason\x18\x03 \x01(\tB\x93\x01\n\x1bio.temporal.api.workflow.v1B\x0cMessageProtoP\x01Z\'go.temporal.io/api/workflow/v1;workflow\xaa\x02\x1aTemporalio.Api.Workflow.V1\xea\x02\x1dTemporalio::Api::Workflow::V1b\x06proto3' + b'\n&temporal/api/workflow/v1/message.proto\x12\x18temporal.api.workflow.v1\x1a\x1egoogle/protobuf/duration.proto\x1a\x1bgoogle/protobuf/empty.proto\x1a\x1fgoogle/protobuf/timestamp.proto\x1a google/protobuf/field_mask.proto\x1a&temporal/api/activity/v1/message.proto\x1a"temporal/api/enums/v1/common.proto\x1a&temporal/api/enums/v1/event_type.proto\x1a$temporal/api/enums/v1/workflow.proto\x1a$temporal/api/common/v1/message.proto\x1a(temporal/api/deployment/v1/message.proto\x1a%temporal/api/failure/v1/message.proto\x1a\'temporal/api/taskqueue/v1/message.proto\x1a\'temporal/api/sdk/v1/user_metadata.proto"\xf0\t\n\x15WorkflowExecutionInfo\x12<\n\texecution\x18\x01 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x32\n\x04type\x18\x02 \x01(\x0b\x32$.temporal.api.common.v1.WorkflowType\x12.\n\nstart_time\x18\x03 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12.\n\nclose_time\x18\x04 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12>\n\x06status\x18\x05 \x01(\x0e\x32..temporal.api.enums.v1.WorkflowExecutionStatus\x12\x16\n\x0ehistory_length\x18\x06 \x01(\x03\x12\x1b\n\x13parent_namespace_id\x18\x07 \x01(\t\x12\x43\n\x10parent_execution\x18\x08 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x32\n\x0e\x65xecution_time\x18\t \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12*\n\x04memo\x18\n \x01(\x0b\x32\x1c.temporal.api.common.v1.Memo\x12\x43\n\x11search_attributes\x18\x0b \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes\x12@\n\x11\x61uto_reset_points\x18\x0c \x01(\x0b\x32%.temporal.api.workflow.v1.ResetPoints\x12\x12\n\ntask_queue\x18\r \x01(\t\x12\x1e\n\x16state_transition_count\x18\x0e \x01(\x03\x12\x1a\n\x12history_size_bytes\x18\x0f \x01(\x03\x12X\n most_recent_worker_version_stamp\x18\x10 \x01(\x0b\x32*.temporal.api.common.v1.WorkerVersionStampB\x02\x18\x01\x12\x35\n\x12\x65xecution_duration\x18\x11 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x41\n\x0eroot_execution\x18\x12 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x1d\n\x11\x61ssigned_build_id\x18\x13 \x01(\tB\x02\x18\x01\x12\x1e\n\x12inherited_build_id\x18\x14 \x01(\tB\x02\x18\x01\x12\x14\n\x0c\x66irst_run_id\x18\x15 \x01(\t\x12R\n\x0fversioning_info\x18\x16 \x01(\x0b\x32\x39.temporal.api.workflow.v1.WorkflowExecutionVersioningInfo\x12\x1e\n\x16worker_deployment_name\x18\x17 \x01(\t\x12\x32\n\x08priority\x18\x18 \x01(\x0b\x32 .temporal.api.common.v1.Priority\x12#\n\x1b\x65xternal_payload_size_bytes\x18\x19 \x01(\x03\x12\x1e\n\x16\x65xternal_payload_count\x18\x1a \x01(\x03"\xc6\x04\n\x1dWorkflowExecutionExtendedInfo\x12=\n\x19\x65xecution_expiration_time\x18\x01 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x37\n\x13run_expiration_time\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x18\n\x10\x63\x61ncel_requested\x18\x03 \x01(\x08\x12\x33\n\x0flast_reset_time\x18\x04 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x37\n\x13original_start_time\x18\x05 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x14\n\x0creset_run_id\x18\x06 \x01(\t\x12\x65\n\x10request_id_infos\x18\x07 \x03(\x0b\x32K.temporal.api.workflow.v1.WorkflowExecutionExtendedInfo.RequestIdInfosEntry\x12H\n\npause_info\x18\x08 \x01(\x0b\x32\x34.temporal.api.workflow.v1.WorkflowExecutionPauseInfo\x1a^\n\x13RequestIdInfosEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x36\n\x05value\x18\x02 \x01(\x0b\x32\'.temporal.api.workflow.v1.RequestIdInfo:\x02\x38\x01"\xfb\x04\n\x1fWorkflowExecutionVersioningInfo\x12;\n\x08\x62\x65havior\x18\x01 \x01(\x0e\x32).temporal.api.enums.v1.VersioningBehavior\x12>\n\ndeployment\x18\x02 \x01(\x0b\x32&.temporal.api.deployment.v1.DeploymentB\x02\x18\x01\x12\x13\n\x07version\x18\x05 \x01(\tB\x02\x18\x01\x12O\n\x12\x64\x65ployment_version\x18\x07 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersion\x12I\n\x13versioning_override\x18\x03 \x01(\x0b\x32,.temporal.api.workflow.v1.VersioningOverride\x12Q\n\x15\x64\x65ployment_transition\x18\x04 \x01(\x0b\x32..temporal.api.workflow.v1.DeploymentTransitionB\x02\x18\x01\x12Q\n\x12version_transition\x18\x06 \x01(\x0b\x32\x35.temporal.api.workflow.v1.DeploymentVersionTransition\x12\x17\n\x0frevision_number\x18\x08 \x01(\x03\x12k\n+continue_as_new_initial_versioning_behavior\x18\t \x01(\x0e\x32\x36.temporal.api.enums.v1.ContinueAsNewVersioningBehavior"R\n\x14\x44\x65ploymentTransition\x12:\n\ndeployment\x18\x01 \x01(\x0b\x32&.temporal.api.deployment.v1.Deployment"\x83\x01\n\x1b\x44\x65ploymentVersionTransition\x12\x13\n\x07version\x18\x01 \x01(\tB\x02\x18\x01\x12O\n\x12\x64\x65ployment_version\x18\x02 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersion"\xc7\x02\n\x17WorkflowExecutionConfig\x12\x38\n\ntask_queue\x18\x01 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12=\n\x1aworkflow_execution_timeout\x18\x02 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x37\n\x14workflow_run_timeout\x18\x03 \x01(\x0b\x32\x19.google.protobuf.Duration\x12@\n\x1d\x64\x65\x66\x61ult_workflow_task_timeout\x18\x04 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x38\n\ruser_metadata\x18\x05 \x01(\x0b\x32!.temporal.api.sdk.v1.UserMetadata"\xbd\r\n\x13PendingActivityInfo\x12\x13\n\x0b\x61\x63tivity_id\x18\x01 \x01(\t\x12;\n\ractivity_type\x18\x02 \x01(\x0b\x32$.temporal.api.common.v1.ActivityType\x12:\n\x05state\x18\x03 \x01(\x0e\x32+.temporal.api.enums.v1.PendingActivityState\x12;\n\x11heartbeat_details\x18\x04 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x37\n\x13last_heartbeat_time\x18\x05 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x35\n\x11last_started_time\x18\x06 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x0f\n\x07\x61ttempt\x18\x07 \x01(\x05\x12\x18\n\x10maximum_attempts\x18\x08 \x01(\x05\x12\x32\n\x0escheduled_time\x18\t \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x33\n\x0f\x65xpiration_time\x18\n \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x36\n\x0clast_failure\x18\x0b \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12\x1c\n\x14last_worker_identity\x18\x0c \x01(\t\x12;\n\x15use_workflow_build_id\x18\r \x01(\x0b\x32\x16.google.protobuf.EmptyB\x02\x18\x01H\x00\x12\x32\n$last_independently_assigned_build_id\x18\x0e \x01(\tB\x02\x18\x01H\x00\x12Q\n\x19last_worker_version_stamp\x18\x0f \x01(\x0b\x32*.temporal.api.common.v1.WorkerVersionStampB\x02\x18\x01\x12\x39\n\x16\x63urrent_retry_interval\x18\x10 \x01(\x0b\x32\x19.google.protobuf.Duration\x12>\n\x1alast_attempt_complete_time\x18\x11 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12>\n\x1anext_attempt_schedule_time\x18\x12 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x0e\n\x06paused\x18\x13 \x01(\x08\x12\x43\n\x0flast_deployment\x18\x14 \x01(\x0b\x32&.temporal.api.deployment.v1.DeploymentB\x02\x18\x01\x12*\n\x1elast_worker_deployment_version\x18\x15 \x01(\tB\x02\x18\x01\x12T\n\x17last_deployment_version\x18\x19 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersion\x12\x32\n\x08priority\x18\x16 \x01(\x0b\x32 .temporal.api.common.v1.Priority\x12K\n\npause_info\x18\x17 \x01(\x0b\x32\x37.temporal.api.workflow.v1.PendingActivityInfo.PauseInfo\x12\x43\n\x10\x61\x63tivity_options\x18\x18 \x01(\x0b\x32).temporal.api.activity.v1.ActivityOptions\x1a\xcf\x02\n\tPauseInfo\x12.\n\npause_time\x18\x01 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12P\n\x06manual\x18\x02 \x01(\x0b\x32>.temporal.api.workflow.v1.PendingActivityInfo.PauseInfo.ManualH\x00\x12L\n\x04rule\x18\x04 \x01(\x0b\x32<.temporal.api.workflow.v1.PendingActivityInfo.PauseInfo.RuleH\x00\x1a*\n\x06Manual\x12\x10\n\x08identity\x18\x01 \x01(\t\x12\x0e\n\x06reason\x18\x02 \x01(\t\x1a\x39\n\x04Rule\x12\x0f\n\x07rule_id\x18\x01 \x01(\t\x12\x10\n\x08identity\x18\x02 \x01(\t\x12\x0e\n\x06reason\x18\x03 \x01(\tB\x0b\n\tpaused_byB\x13\n\x11\x61ssigned_build_id"\xb9\x01\n\x19PendingChildExecutionInfo\x12\x13\n\x0bworkflow_id\x18\x01 \x01(\t\x12\x0e\n\x06run_id\x18\x02 \x01(\t\x12\x1a\n\x12workflow_type_name\x18\x03 \x01(\t\x12\x14\n\x0cinitiated_id\x18\x04 \x01(\x03\x12\x45\n\x13parent_close_policy\x18\x05 \x01(\x0e\x32(.temporal.api.enums.v1.ParentClosePolicy"\x8d\x02\n\x17PendingWorkflowTaskInfo\x12>\n\x05state\x18\x01 \x01(\x0e\x32/.temporal.api.enums.v1.PendingWorkflowTaskState\x12\x32\n\x0escheduled_time\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12;\n\x17original_scheduled_time\x18\x03 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x30\n\x0cstarted_time\x18\x04 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x0f\n\x07\x61ttempt\x18\x05 \x01(\x05"G\n\x0bResetPoints\x12\x38\n\x06points\x18\x01 \x03(\x0b\x32(.temporal.api.workflow.v1.ResetPointInfo"\xef\x01\n\x0eResetPointInfo\x12\x10\n\x08\x62uild_id\x18\x07 \x01(\t\x12\x1b\n\x0f\x62inary_checksum\x18\x01 \x01(\tB\x02\x18\x01\x12\x0e\n\x06run_id\x18\x02 \x01(\t\x12(\n first_workflow_task_completed_id\x18\x03 \x01(\x03\x12/\n\x0b\x63reate_time\x18\x04 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12/\n\x0b\x65xpire_time\x18\x05 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x12\n\nresettable\x18\x06 \x01(\x08"\x85\x07\n\x18NewWorkflowExecutionInfo\x12\x13\n\x0bworkflow_id\x18\x01 \x01(\t\x12;\n\rworkflow_type\x18\x02 \x01(\x0b\x32$.temporal.api.common.v1.WorkflowType\x12\x38\n\ntask_queue\x18\x03 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12/\n\x05input\x18\x04 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12=\n\x1aworkflow_execution_timeout\x18\x05 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x37\n\x14workflow_run_timeout\x18\x06 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x38\n\x15workflow_task_timeout\x18\x07 \x01(\x0b\x32\x19.google.protobuf.Duration\x12N\n\x18workflow_id_reuse_policy\x18\x08 \x01(\x0e\x32,.temporal.api.enums.v1.WorkflowIdReusePolicy\x12\x39\n\x0cretry_policy\x18\t \x01(\x0b\x32#.temporal.api.common.v1.RetryPolicy\x12\x15\n\rcron_schedule\x18\n \x01(\t\x12*\n\x04memo\x18\x0b \x01(\x0b\x32\x1c.temporal.api.common.v1.Memo\x12\x43\n\x11search_attributes\x18\x0c \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes\x12.\n\x06header\x18\r \x01(\x0b\x32\x1e.temporal.api.common.v1.Header\x12\x38\n\ruser_metadata\x18\x0e \x01(\x0b\x32!.temporal.api.sdk.v1.UserMetadata\x12I\n\x13versioning_override\x18\x0f \x01(\x0b\x32,.temporal.api.workflow.v1.VersioningOverride\x12\x32\n\x08priority\x18\x10 \x01(\x0b\x32 .temporal.api.common.v1.Priority"\x82\x06\n\x0c\x43\x61llbackInfo\x12\x32\n\x08\x63\x61llback\x18\x01 \x01(\x0b\x32 .temporal.api.common.v1.Callback\x12?\n\x07trigger\x18\x02 \x01(\x0b\x32..temporal.api.workflow.v1.CallbackInfo.Trigger\x12\x35\n\x11registration_time\x18\x03 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x33\n\x05state\x18\x04 \x01(\x0e\x32$.temporal.api.enums.v1.CallbackState\x12\x0f\n\x07\x61ttempt\x18\x05 \x01(\x05\x12>\n\x1alast_attempt_complete_time\x18\x06 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12>\n\x14last_attempt_failure\x18\x07 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12>\n\x1anext_attempt_schedule_time\x18\x08 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x16\n\x0e\x62locked_reason\x18\t \x01(\t\x1a\x10\n\x0eWorkflowClosed\x1a\x35\n UpdateWorkflowExecutionCompleted\x12\x11\n\tupdate_id\x18\x01 \x01(\t\x1a\xde\x01\n\x07Trigger\x12P\n\x0fworkflow_closed\x18\x01 \x01(\x0b\x32\x35.temporal.api.workflow.v1.CallbackInfo.WorkflowClosedH\x00\x12v\n#update_workflow_execution_completed\x18\x02 \x01(\x0b\x32G.temporal.api.workflow.v1.CallbackInfo.UpdateWorkflowExecutionCompletedH\x00\x42\t\n\x07variant"\x8b\x06\n\x19PendingNexusOperationInfo\x12\x10\n\x08\x65ndpoint\x18\x01 \x01(\t\x12\x0f\n\x07service\x18\x02 \x01(\t\x12\x11\n\toperation\x18\x03 \x01(\t\x12\x18\n\x0coperation_id\x18\x04 \x01(\tB\x02\x18\x01\x12<\n\x19schedule_to_close_timeout\x18\x05 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x32\n\x0escheduled_time\x18\x06 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12@\n\x05state\x18\x07 \x01(\x0e\x32\x31.temporal.api.enums.v1.PendingNexusOperationState\x12\x0f\n\x07\x61ttempt\x18\x08 \x01(\x05\x12>\n\x1alast_attempt_complete_time\x18\t \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12>\n\x14last_attempt_failure\x18\n \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12>\n\x1anext_attempt_schedule_time\x18\x0b \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12S\n\x11\x63\x61ncellation_info\x18\x0c \x01(\x0b\x32\x38.temporal.api.workflow.v1.NexusOperationCancellationInfo\x12\x1a\n\x12scheduled_event_id\x18\r \x01(\x03\x12\x16\n\x0e\x62locked_reason\x18\x0e \x01(\t\x12\x17\n\x0foperation_token\x18\x0f \x01(\t\x12<\n\x19schedule_to_start_timeout\x18\x10 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x39\n\x16start_to_close_timeout\x18\x11 \x01(\x0b\x32\x19.google.protobuf.Duration"\x84\x03\n\x1eNexusOperationCancellationInfo\x12\x32\n\x0erequested_time\x18\x01 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x45\n\x05state\x18\x02 \x01(\x0e\x32\x36.temporal.api.enums.v1.NexusOperationCancellationState\x12\x0f\n\x07\x61ttempt\x18\x03 \x01(\x05\x12>\n\x1alast_attempt_complete_time\x18\x04 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12>\n\x14last_attempt_failure\x18\x05 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12>\n\x1anext_attempt_schedule_time\x18\x06 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x16\n\x0e\x62locked_reason\x18\x07 \x01(\t"\xe5\x01\n\x18WorkflowExecutionOptions\x12I\n\x13versioning_override\x18\x01 \x01(\x0b\x32,.temporal.api.workflow.v1.VersioningOverride\x12\x32\n\x08priority\x18\x02 \x01(\x0b\x32 .temporal.api.common.v1.Priority\x12J\n\x14time_skipping_config\x18\x03 \x01(\x0b\x32,.temporal.api.workflow.v1.TimeSkippingConfig"\xd6\x01\n\x12TimeSkippingConfig\x12\x0f\n\x07\x65nabled\x18\x01 \x01(\x08\x12\x39\n\x14max_skipped_duration\x18\x04 \x01(\x0b\x32\x19.google.protobuf.DurationH\x00\x12\x39\n\x14max_elapsed_duration\x18\x05 \x01(\x0b\x32\x19.google.protobuf.DurationH\x00\x42\x07\n\x05\x62oundJ\x04\x08\x02\x10\x03J\x04\x08\x06\x10\x07R\x13\x64isable_propagationR\x0fmax_target_time"\xbd\x04\n\x12VersioningOverride\x12M\n\x06pinned\x18\x03 \x01(\x0b\x32;.temporal.api.workflow.v1.VersioningOverride.PinnedOverrideH\x00\x12\x16\n\x0c\x61uto_upgrade\x18\x04 \x01(\x08H\x00\x12?\n\x08\x62\x65havior\x18\x01 \x01(\x0e\x32).temporal.api.enums.v1.VersioningBehaviorB\x02\x18\x01\x12>\n\ndeployment\x18\x02 \x01(\x0b\x32&.temporal.api.deployment.v1.DeploymentB\x02\x18\x01\x12\x1a\n\x0epinned_version\x18\t \x01(\tB\x02\x18\x01\x1a\xad\x01\n\x0ePinnedOverride\x12U\n\x08\x62\x65havior\x18\x01 \x01(\x0e\x32\x43.temporal.api.workflow.v1.VersioningOverride.PinnedOverrideBehavior\x12\x44\n\x07version\x18\x02 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersion"g\n\x16PinnedOverrideBehavior\x12(\n$PINNED_OVERRIDE_BEHAVIOR_UNSPECIFIED\x10\x00\x12#\n\x1fPINNED_OVERRIDE_BEHAVIOR_PINNED\x10\x01\x42\n\n\x08override"i\n\x11OnConflictOptions\x12\x19\n\x11\x61ttach_request_id\x18\x01 \x01(\x08\x12#\n\x1b\x61ttach_completion_callbacks\x18\x02 \x01(\x08\x12\x14\n\x0c\x61ttach_links\x18\x03 \x01(\x08"i\n\rRequestIdInfo\x12\x34\n\nevent_type\x18\x01 \x01(\x0e\x32 .temporal.api.enums.v1.EventType\x12\x10\n\x08\x65vent_id\x18\x02 \x01(\x03\x12\x10\n\x08\x62uffered\x18\x03 \x01(\x08"\xb7\x04\n\x12PostResetOperation\x12V\n\x0fsignal_workflow\x18\x01 \x01(\x0b\x32;.temporal.api.workflow.v1.PostResetOperation.SignalWorkflowH\x00\x12\x65\n\x17update_workflow_options\x18\x02 \x01(\x0b\x32\x42.temporal.api.workflow.v1.PostResetOperation.UpdateWorkflowOptionsH\x00\x1a\xb3\x01\n\x0eSignalWorkflow\x12\x13\n\x0bsignal_name\x18\x01 \x01(\t\x12/\n\x05input\x18\x02 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12.\n\x06header\x18\x03 \x01(\x0b\x32\x1e.temporal.api.common.v1.Header\x12+\n\x05links\x18\x04 \x03(\x0b\x32\x1c.temporal.api.common.v1.Link\x1a\xa0\x01\n\x15UpdateWorkflowOptions\x12V\n\x1aworkflow_execution_options\x18\x01 \x01(\x0b\x32\x32.temporal.api.workflow.v1.WorkflowExecutionOptions\x12/\n\x0bupdate_mask\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.FieldMaskB\t\n\x07variant"o\n\x1aWorkflowExecutionPauseInfo\x12\x10\n\x08identity\x18\x01 \x01(\t\x12/\n\x0bpaused_time\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x0e\n\x06reason\x18\x03 \x01(\tB\x93\x01\n\x1bio.temporal.api.workflow.v1B\x0cMessageProtoP\x01Z\'go.temporal.io/api/workflow/v1;workflow\xaa\x02\x1aTemporalio.Api.Workflow.V1\xea\x02\x1dTemporalio::Api::Workflow::V1b\x06proto3' ) @@ -84,6 +84,9 @@ _NEWWORKFLOWEXECUTIONINFO = DESCRIPTOR.message_types_by_name["NewWorkflowExecutionInfo"] _CALLBACKINFO = DESCRIPTOR.message_types_by_name["CallbackInfo"] _CALLBACKINFO_WORKFLOWCLOSED = _CALLBACKINFO.nested_types_by_name["WorkflowClosed"] +_CALLBACKINFO_UPDATEWORKFLOWEXECUTIONCOMPLETED = _CALLBACKINFO.nested_types_by_name[ + "UpdateWorkflowExecutionCompleted" +] _CALLBACKINFO_TRIGGER = _CALLBACKINFO.nested_types_by_name["Trigger"] _PENDINGNEXUSOPERATIONINFO = DESCRIPTOR.message_types_by_name[ "PendingNexusOperationInfo" @@ -297,6 +300,15 @@ # @@protoc_insertion_point(class_scope:temporal.api.workflow.v1.CallbackInfo.WorkflowClosed) }, ), + "UpdateWorkflowExecutionCompleted": _reflection.GeneratedProtocolMessageType( + "UpdateWorkflowExecutionCompleted", + (_message.Message,), + { + "DESCRIPTOR": _CALLBACKINFO_UPDATEWORKFLOWEXECUTIONCOMPLETED, + "__module__": "temporalio.api.workflow.v1.message_pb2", + # @@protoc_insertion_point(class_scope:temporal.api.workflow.v1.CallbackInfo.UpdateWorkflowExecutionCompleted) + }, + ), "Trigger": _reflection.GeneratedProtocolMessageType( "Trigger", (_message.Message,), @@ -313,6 +325,7 @@ ) _sym_db.RegisterMessage(CallbackInfo) _sym_db.RegisterMessage(CallbackInfo.WorkflowClosed) +_sym_db.RegisterMessage(CallbackInfo.UpdateWorkflowExecutionCompleted) _sym_db.RegisterMessage(CallbackInfo.Trigger) PendingNexusOperationInfo = _reflection.GeneratedProtocolMessageType( @@ -552,35 +565,37 @@ _NEWWORKFLOWEXECUTIONINFO._serialized_start = 6093 _NEWWORKFLOWEXECUTIONINFO._serialized_end = 6994 _CALLBACKINFO._serialized_start = 6997 - _CALLBACKINFO._serialized_end = 7591 + _CALLBACKINFO._serialized_end = 7767 _CALLBACKINFO_WORKFLOWCLOSED._serialized_start = 7471 _CALLBACKINFO_WORKFLOWCLOSED._serialized_end = 7487 - _CALLBACKINFO_TRIGGER._serialized_start = 7489 - _CALLBACKINFO_TRIGGER._serialized_end = 7591 - _PENDINGNEXUSOPERATIONINFO._serialized_start = 7594 - _PENDINGNEXUSOPERATIONINFO._serialized_end = 8373 - _NEXUSOPERATIONCANCELLATIONINFO._serialized_start = 8376 - _NEXUSOPERATIONCANCELLATIONINFO._serialized_end = 8764 - _WORKFLOWEXECUTIONOPTIONS._serialized_start = 8767 - _WORKFLOWEXECUTIONOPTIONS._serialized_end = 8996 - _TIMESKIPPINGCONFIG._serialized_start = 8999 - _TIMESKIPPINGCONFIG._serialized_end = 9247 - _VERSIONINGOVERRIDE._serialized_start = 9250 - _VERSIONINGOVERRIDE._serialized_end = 9823 - _VERSIONINGOVERRIDE_PINNEDOVERRIDE._serialized_start = 9533 - _VERSIONINGOVERRIDE_PINNEDOVERRIDE._serialized_end = 9706 - _VERSIONINGOVERRIDE_PINNEDOVERRIDEBEHAVIOR._serialized_start = 9708 - _VERSIONINGOVERRIDE_PINNEDOVERRIDEBEHAVIOR._serialized_end = 9811 - _ONCONFLICTOPTIONS._serialized_start = 9825 - _ONCONFLICTOPTIONS._serialized_end = 9930 - _REQUESTIDINFO._serialized_start = 9932 - _REQUESTIDINFO._serialized_end = 10037 - _POSTRESETOPERATION._serialized_start = 10040 - _POSTRESETOPERATION._serialized_end = 10607 - _POSTRESETOPERATION_SIGNALWORKFLOW._serialized_start = 10254 - _POSTRESETOPERATION_SIGNALWORKFLOW._serialized_end = 10433 - _POSTRESETOPERATION_UPDATEWORKFLOWOPTIONS._serialized_start = 10436 - _POSTRESETOPERATION_UPDATEWORKFLOWOPTIONS._serialized_end = 10596 - _WORKFLOWEXECUTIONPAUSEINFO._serialized_start = 10609 - _WORKFLOWEXECUTIONPAUSEINFO._serialized_end = 10720 + _CALLBACKINFO_UPDATEWORKFLOWEXECUTIONCOMPLETED._serialized_start = 7489 + _CALLBACKINFO_UPDATEWORKFLOWEXECUTIONCOMPLETED._serialized_end = 7542 + _CALLBACKINFO_TRIGGER._serialized_start = 7545 + _CALLBACKINFO_TRIGGER._serialized_end = 7767 + _PENDINGNEXUSOPERATIONINFO._serialized_start = 7770 + _PENDINGNEXUSOPERATIONINFO._serialized_end = 8549 + _NEXUSOPERATIONCANCELLATIONINFO._serialized_start = 8552 + _NEXUSOPERATIONCANCELLATIONINFO._serialized_end = 8940 + _WORKFLOWEXECUTIONOPTIONS._serialized_start = 8943 + _WORKFLOWEXECUTIONOPTIONS._serialized_end = 9172 + _TIMESKIPPINGCONFIG._serialized_start = 9175 + _TIMESKIPPINGCONFIG._serialized_end = 9389 + _VERSIONINGOVERRIDE._serialized_start = 9392 + _VERSIONINGOVERRIDE._serialized_end = 9965 + _VERSIONINGOVERRIDE_PINNEDOVERRIDE._serialized_start = 9675 + _VERSIONINGOVERRIDE_PINNEDOVERRIDE._serialized_end = 9848 + _VERSIONINGOVERRIDE_PINNEDOVERRIDEBEHAVIOR._serialized_start = 9850 + _VERSIONINGOVERRIDE_PINNEDOVERRIDEBEHAVIOR._serialized_end = 9953 + _ONCONFLICTOPTIONS._serialized_start = 9967 + _ONCONFLICTOPTIONS._serialized_end = 10072 + _REQUESTIDINFO._serialized_start = 10074 + _REQUESTIDINFO._serialized_end = 10179 + _POSTRESETOPERATION._serialized_start = 10182 + _POSTRESETOPERATION._serialized_end = 10749 + _POSTRESETOPERATION_SIGNALWORKFLOW._serialized_start = 10396 + _POSTRESETOPERATION_SIGNALWORKFLOW._serialized_end = 10575 + _POSTRESETOPERATION_UPDATEWORKFLOWOPTIONS._serialized_start = 10578 + _POSTRESETOPERATION_UPDATEWORKFLOWOPTIONS._serialized_end = 10738 + _WORKFLOWEXECUTIONPAUSEINFO._serialized_start = 10751 + _WORKFLOWEXECUTIONPAUSEINFO._serialized_end = 10862 # @@protoc_insertion_point(module_scope) diff --git a/temporalio/api/workflow/v1/message_pb2.pyi b/temporalio/api/workflow/v1/message_pb2.pyi index 451147563..e9491a87c 100644 --- a/temporalio/api/workflow/v1/message_pb2.pyi +++ b/temporalio/api/workflow/v1/message_pb2.pyi @@ -1465,32 +1465,70 @@ class CallbackInfo(google.protobuf.message.Message): self, ) -> None: ... + class UpdateWorkflowExecutionCompleted(google.protobuf.message.Message): + """Trigger for when a workflow update is completed.""" + + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + UPDATE_ID_FIELD_NUMBER: builtins.int + update_id: builtins.str + def __init__( + self, + *, + update_id: builtins.str = ..., + ) -> None: ... + def ClearField( + self, field_name: typing_extensions.Literal["update_id", b"update_id"] + ) -> None: ... + class Trigger(google.protobuf.message.Message): DESCRIPTOR: google.protobuf.descriptor.Descriptor WORKFLOW_CLOSED_FIELD_NUMBER: builtins.int + UPDATE_WORKFLOW_EXECUTION_COMPLETED_FIELD_NUMBER: builtins.int @property def workflow_closed(self) -> global___CallbackInfo.WorkflowClosed: ... + @property + def update_workflow_execution_completed( + self, + ) -> global___CallbackInfo.UpdateWorkflowExecutionCompleted: ... def __init__( self, *, workflow_closed: global___CallbackInfo.WorkflowClosed | None = ..., + update_workflow_execution_completed: global___CallbackInfo.UpdateWorkflowExecutionCompleted + | None = ..., ) -> None: ... def HasField( self, field_name: typing_extensions.Literal[ - "variant", b"variant", "workflow_closed", b"workflow_closed" + "update_workflow_execution_completed", + b"update_workflow_execution_completed", + "variant", + b"variant", + "workflow_closed", + b"workflow_closed", ], ) -> builtins.bool: ... def ClearField( self, field_name: typing_extensions.Literal[ - "variant", b"variant", "workflow_closed", b"workflow_closed" + "update_workflow_execution_completed", + b"update_workflow_execution_completed", + "variant", + b"variant", + "workflow_closed", + b"workflow_closed", ], ) -> None: ... def WhichOneof( self, oneof_group: typing_extensions.Literal["variant", b"variant"] - ) -> typing_extensions.Literal["workflow_closed"] | None: ... + ) -> ( + typing_extensions.Literal[ + "workflow_closed", "update_workflow_execution_completed" + ] + | None + ): ... CALLBACK_FIELD_NUMBER: builtins.int TRIGGER_FIELD_NUMBER: builtins.int @@ -1850,8 +1888,8 @@ class WorkflowExecutionOptions(google.protobuf.message.Message): @property def time_skipping_config(self) -> global___TimeSkippingConfig: """Time-skipping configuration for this workflow execution. - If not set, the time-skipping conf will not get updated upon request, - i.e. the existing time-skipping conf will be preserved. + If not set, the time-skipping configuration is not updated by this request; + the existing configuration is preserved. """ def __init__( self, @@ -1892,23 +1930,26 @@ class TimeSkippingConfig(google.protobuf.message.Message): and possibly other features added in the future. User timers are not classified as in-flight work and will be skipped over. When time advances, it skips to the earlier of the next user timer or the configured bound, if either exists. + + Propagation behavior of time skipping: + The enabled flag, bound fields, and accumulated skipped duration are propagated to related executions as follows: + (1) Child workflows and continue-as-new: both the configuration and the accumulated skipped duration are + inherited from the current execution. The configured bound is shared between the inherited skipped + duration and any additional duration skipped by the new run. + (2) Retry and cron: the configuration and accumulated skipped duration are inherited as recorded when the + current workflow started; the accumulated skipped duration of the current run is not propagated. + (3) Reset: the new run retains the time-skipping configuration of the current execution. Because reset replays + all events up to the reset point and re-applies any UpdateWorkflowExecutionOptions changes made after that + point, the resulting run ends up with the same final time-skipping configuration as the previous run. """ DESCRIPTOR: google.protobuf.descriptor.Descriptor ENABLED_FIELD_NUMBER: builtins.int - DISABLE_PROPAGATION_FIELD_NUMBER: builtins.int MAX_SKIPPED_DURATION_FIELD_NUMBER: builtins.int MAX_ELAPSED_DURATION_FIELD_NUMBER: builtins.int - MAX_TARGET_TIME_FIELD_NUMBER: builtins.int enabled: builtins.bool - """Enables or disables time skipping for this workflow execution. - By default, this field is propagated to transitively related workflows (child workflows/start-as-new/reset) - at the time they are started. - Changes made after a transitively related workflow has started are not propagated. - """ - disable_propagation: builtins.bool - """If set, the enabled field is not propagated to transitively related workflows.""" + """Enables or disables time skipping for this workflow execution.""" @property def max_skipped_duration(self) -> google.protobuf.duration_pb2.Duration: """Maximum total virtual time that can be skipped.""" @@ -1918,19 +1959,12 @@ class TimeSkippingConfig(google.protobuf.message.Message): This includes both skipped time and real time elapsing. (-- api-linter: core::0142::time-field-names=disabled --) """ - @property - def max_target_time(self) -> google.protobuf.timestamp_pb2.Timestamp: - """Absolute virtual timestamp at which time skipping is disabled. - Time skipping will not advance beyond this point. - """ def __init__( self, *, enabled: builtins.bool = ..., - disable_propagation: builtins.bool = ..., max_skipped_duration: google.protobuf.duration_pb2.Duration | None = ..., max_elapsed_duration: google.protobuf.duration_pb2.Duration | None = ..., - max_target_time: google.protobuf.timestamp_pb2.Timestamp | None = ..., ) -> None: ... def HasField( self, @@ -1941,8 +1975,6 @@ class TimeSkippingConfig(google.protobuf.message.Message): b"max_elapsed_duration", "max_skipped_duration", b"max_skipped_duration", - "max_target_time", - b"max_target_time", ], ) -> builtins.bool: ... def ClearField( @@ -1950,25 +1982,18 @@ class TimeSkippingConfig(google.protobuf.message.Message): field_name: typing_extensions.Literal[ "bound", b"bound", - "disable_propagation", - b"disable_propagation", "enabled", b"enabled", "max_elapsed_duration", b"max_elapsed_duration", "max_skipped_duration", b"max_skipped_duration", - "max_target_time", - b"max_target_time", ], ) -> None: ... def WhichOneof( self, oneof_group: typing_extensions.Literal["bound", b"bound"] ) -> ( - typing_extensions.Literal[ - "max_skipped_duration", "max_elapsed_duration", "max_target_time" - ] - | None + typing_extensions.Literal["max_skipped_duration", "max_elapsed_duration"] | None ): ... global___TimeSkippingConfig = TimeSkippingConfig diff --git a/temporalio/api/workflowservice/v1/request_response_pb2.py b/temporalio/api/workflowservice/v1/request_response_pb2.py index 2f3b090ee..32469c030 100644 --- a/temporalio/api/workflowservice/v1/request_response_pb2.py +++ b/temporalio/api/workflowservice/v1/request_response_pb2.py @@ -128,7 +128,7 @@ ) DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile( - b'\n6temporal/api/workflowservice/v1/request_response.proto\x12\x1ftemporal.api.workflowservice.v1\x1a+temporal/api/enums/v1/batch_operation.proto\x1a"temporal/api/enums/v1/common.proto\x1a$temporal/api/enums/v1/workflow.proto\x1a%temporal/api/enums/v1/namespace.proto\x1a(temporal/api/enums/v1/failed_cause.proto\x1a!temporal/api/enums/v1/query.proto\x1a!temporal/api/enums/v1/reset.proto\x1a&temporal/api/enums/v1/task_queue.proto\x1a&temporal/api/enums/v1/deployment.proto\x1a"temporal/api/enums/v1/update.proto\x1a$temporal/api/enums/v1/activity.proto\x1a!temporal/api/enums/v1/nexus.proto\x1a&temporal/api/activity/v1/message.proto\x1a$temporal/api/common/v1/message.proto\x1a%temporal/api/history/v1/message.proto\x1a&temporal/api/workflow/v1/message.proto\x1a%temporal/api/command/v1/message.proto\x1a$temporal/api/compute/v1/config.proto\x1a(temporal/api/deployment/v1/message.proto\x1a%temporal/api/failure/v1/message.proto\x1a$temporal/api/filter/v1/message.proto\x1a&temporal/api/protocol/v1/message.proto\x1a\'temporal/api/namespace/v1/message.proto\x1a#temporal/api/query/v1/message.proto\x1a)temporal/api/replication/v1/message.proto\x1a#temporal/api/rules/v1/message.proto\x1a\'temporal/api/sdk/v1/worker_config.proto\x1a&temporal/api/schedule/v1/message.proto\x1a\'temporal/api/taskqueue/v1/message.proto\x1a$temporal/api/update/v1/message.proto\x1a%temporal/api/version/v1/message.proto\x1a#temporal/api/batch/v1/message.proto\x1a\x30temporal/api/sdk/v1/task_complete_metadata.proto\x1a\'temporal/api/sdk/v1/user_metadata.proto\x1a#temporal/api/nexus/v1/message.proto\x1a$temporal/api/worker/v1/message.proto\x1a\x1egoogle/protobuf/duration.proto\x1a google/protobuf/field_mask.proto\x1a\x1fgoogle/protobuf/timestamp.proto"\x88\x05\n\x18RegisterNamespaceRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0b\x64\x65scription\x18\x02 \x01(\t\x12\x13\n\x0bowner_email\x18\x03 \x01(\t\x12\x46\n#workflow_execution_retention_period\x18\x04 \x01(\x0b\x32\x19.google.protobuf.Duration\x12G\n\x08\x63lusters\x18\x05 \x03(\x0b\x32\x35.temporal.api.replication.v1.ClusterReplicationConfig\x12\x1b\n\x13\x61\x63tive_cluster_name\x18\x06 \x01(\t\x12Q\n\x04\x64\x61ta\x18\x07 \x03(\x0b\x32\x43.temporal.api.workflowservice.v1.RegisterNamespaceRequest.DataEntry\x12\x16\n\x0esecurity_token\x18\x08 \x01(\t\x12\x1b\n\x13is_global_namespace\x18\t \x01(\x08\x12\x44\n\x16history_archival_state\x18\n \x01(\x0e\x32$.temporal.api.enums.v1.ArchivalState\x12\x1c\n\x14history_archival_uri\x18\x0b \x01(\t\x12G\n\x19visibility_archival_state\x18\x0c \x01(\x0e\x32$.temporal.api.enums.v1.ArchivalState\x12\x1f\n\x17visibility_archival_uri\x18\r \x01(\t\x1a+\n\tDataEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01"\x1b\n\x19RegisterNamespaceResponse"\x89\x01\n\x15ListNamespacesRequest\x12\x11\n\tpage_size\x18\x01 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c\x12\x44\n\x10namespace_filter\x18\x03 \x01(\x0b\x32*.temporal.api.namespace.v1.NamespaceFilter"\x81\x01\n\x16ListNamespacesResponse\x12N\n\nnamespaces\x18\x01 \x03(\x0b\x32:.temporal.api.workflowservice.v1.DescribeNamespaceResponse\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c"S\n\x18\x44\x65scribeNamespaceRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\n\n\x02id\x18\x02 \x01(\t\x12\x18\n\x10weak_consistency\x18\x03 \x01(\x08"\xec\x02\n\x19\x44\x65scribeNamespaceResponse\x12@\n\x0enamespace_info\x18\x01 \x01(\x0b\x32(.temporal.api.namespace.v1.NamespaceInfo\x12:\n\x06\x63onfig\x18\x02 \x01(\x0b\x32*.temporal.api.namespace.v1.NamespaceConfig\x12S\n\x12replication_config\x18\x03 \x01(\x0b\x32\x37.temporal.api.replication.v1.NamespaceReplicationConfig\x12\x18\n\x10\x66\x61ilover_version\x18\x04 \x01(\x03\x12\x1b\n\x13is_global_namespace\x18\x05 \x01(\x08\x12\x45\n\x10\x66\x61ilover_history\x18\x06 \x03(\x0b\x32+.temporal.api.replication.v1.FailoverStatus"\xcf\x02\n\x16UpdateNamespaceRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x43\n\x0bupdate_info\x18\x02 \x01(\x0b\x32..temporal.api.namespace.v1.UpdateNamespaceInfo\x12:\n\x06\x63onfig\x18\x03 \x01(\x0b\x32*.temporal.api.namespace.v1.NamespaceConfig\x12S\n\x12replication_config\x18\x04 \x01(\x0b\x32\x37.temporal.api.replication.v1.NamespaceReplicationConfig\x12\x16\n\x0esecurity_token\x18\x05 \x01(\t\x12\x19\n\x11\x64\x65lete_bad_binary\x18\x06 \x01(\t\x12\x19\n\x11promote_namespace\x18\x07 \x01(\x08"\xa3\x02\n\x17UpdateNamespaceResponse\x12@\n\x0enamespace_info\x18\x01 \x01(\x0b\x32(.temporal.api.namespace.v1.NamespaceInfo\x12:\n\x06\x63onfig\x18\x02 \x01(\x0b\x32*.temporal.api.namespace.v1.NamespaceConfig\x12S\n\x12replication_config\x18\x03 \x01(\x0b\x32\x37.temporal.api.replication.v1.NamespaceReplicationConfig\x12\x18\n\x10\x66\x61ilover_version\x18\x04 \x01(\x03\x12\x1b\n\x13is_global_namespace\x18\x05 \x01(\x08"F\n\x19\x44\x65precateNamespaceRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x16\n\x0esecurity_token\x18\x02 \x01(\t"\x1c\n\x1a\x44\x65precateNamespaceResponse"\xd3\x0c\n\x1dStartWorkflowExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12;\n\rworkflow_type\x18\x03 \x01(\x0b\x32$.temporal.api.common.v1.WorkflowType\x12\x38\n\ntask_queue\x18\x04 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12/\n\x05input\x18\x05 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12=\n\x1aworkflow_execution_timeout\x18\x06 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x37\n\x14workflow_run_timeout\x18\x07 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x38\n\x15workflow_task_timeout\x18\x08 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x10\n\x08identity\x18\t \x01(\t\x12\x12\n\nrequest_id\x18\n \x01(\t\x12N\n\x18workflow_id_reuse_policy\x18\x0b \x01(\x0e\x32,.temporal.api.enums.v1.WorkflowIdReusePolicy\x12T\n\x1bworkflow_id_conflict_policy\x18\x16 \x01(\x0e\x32/.temporal.api.enums.v1.WorkflowIdConflictPolicy\x12\x39\n\x0cretry_policy\x18\x0c \x01(\x0b\x32#.temporal.api.common.v1.RetryPolicy\x12\x15\n\rcron_schedule\x18\r \x01(\t\x12*\n\x04memo\x18\x0e \x01(\x0b\x32\x1c.temporal.api.common.v1.Memo\x12\x43\n\x11search_attributes\x18\x0f \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes\x12.\n\x06header\x18\x10 \x01(\x0b\x32\x1e.temporal.api.common.v1.Header\x12\x1f\n\x17request_eager_execution\x18\x11 \x01(\x08\x12;\n\x11\x63ontinued_failure\x18\x12 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12@\n\x16last_completion_result\x18\x13 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x37\n\x14workflow_start_delay\x18\x14 \x01(\x0b\x32\x19.google.protobuf.Duration\x12>\n\x14\x63ompletion_callbacks\x18\x15 \x03(\x0b\x32 .temporal.api.common.v1.Callback\x12\x38\n\ruser_metadata\x18\x17 \x01(\x0b\x32!.temporal.api.sdk.v1.UserMetadata\x12+\n\x05links\x18\x18 \x03(\x0b\x32\x1c.temporal.api.common.v1.Link\x12I\n\x13versioning_override\x18\x19 \x01(\x0b\x32,.temporal.api.workflow.v1.VersioningOverride\x12H\n\x13on_conflict_options\x18\x1a \x01(\x0b\x32+.temporal.api.workflow.v1.OnConflictOptions\x12\x32\n\x08priority\x18\x1b \x01(\x0b\x32 .temporal.api.common.v1.Priority\x12\\\n\x1f\x65\x61ger_worker_deployment_options\x18\x1c \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentOptions\x12J\n\x14time_skipping_config\x18\x1d \x01(\x0b\x32,.temporal.api.workflow.v1.TimeSkippingConfig"\x8a\x02\n\x1eStartWorkflowExecutionResponse\x12\x0e\n\x06run_id\x18\x01 \x01(\t\x12\x0f\n\x07started\x18\x03 \x01(\x08\x12>\n\x06status\x18\x05 \x01(\x0e\x32..temporal.api.enums.v1.WorkflowExecutionStatus\x12[\n\x13\x65\x61ger_workflow_task\x18\x02 \x01(\x0b\x32>.temporal.api.workflowservice.v1.PollWorkflowTaskQueueResponse\x12*\n\x04link\x18\x04 \x01(\x0b\x32\x1c.temporal.api.common.v1.Link"\xaa\x02\n"GetWorkflowExecutionHistoryRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12<\n\texecution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x19\n\x11maximum_page_size\x18\x03 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x04 \x01(\x0c\x12\x16\n\x0ewait_new_event\x18\x05 \x01(\x08\x12P\n\x19history_event_filter_type\x18\x06 \x01(\x0e\x32-.temporal.api.enums.v1.HistoryEventFilterType\x12\x15\n\rskip_archival\x18\x07 \x01(\x08"\xba\x01\n#GetWorkflowExecutionHistoryResponse\x12\x31\n\x07history\x18\x01 \x01(\x0b\x32 .temporal.api.history.v1.History\x12\x35\n\x0braw_history\x18\x02 \x03(\x0b\x32 .temporal.api.common.v1.DataBlob\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c\x12\x10\n\x08\x61rchived\x18\x04 \x01(\x08"\xb0\x01\n)GetWorkflowExecutionHistoryReverseRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12<\n\texecution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x19\n\x11maximum_page_size\x18\x03 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x04 \x01(\x0c"x\n*GetWorkflowExecutionHistoryReverseResponse\x12\x31\n\x07history\x18\x01 \x01(\x0b\x32 .temporal.api.history.v1.History\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c"\xb8\x03\n\x1cPollWorkflowTaskQueueRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x38\n\ntask_queue\x18\x02 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12\x17\n\x0fpoller_group_id\x18\n \x01(\t\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x1b\n\x13worker_instance_key\x18\x08 \x01(\t\x12!\n\x19worker_control_task_queue\x18\t \x01(\t\x12\x1b\n\x0f\x62inary_checksum\x18\x04 \x01(\tB\x02\x18\x01\x12Z\n\x1bworker_version_capabilities\x18\x05 \x01(\x0b\x32\x31.temporal.api.common.v1.WorkerVersionCapabilitiesB\x02\x18\x01\x12O\n\x12\x64\x65ployment_options\x18\x06 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentOptionsJ\x04\x08\x07\x10\x08R\x10worker_heartbeat"\xf2\x07\n\x1dPollWorkflowTaskQueueResponse\x12\x12\n\ntask_token\x18\x01 \x01(\x0c\x12\x45\n\x12workflow_execution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12;\n\rworkflow_type\x18\x03 \x01(\x0b\x32$.temporal.api.common.v1.WorkflowType\x12!\n\x19previous_started_event_id\x18\x04 \x01(\x03\x12\x18\n\x10started_event_id\x18\x05 \x01(\x03\x12\x0f\n\x07\x61ttempt\x18\x06 \x01(\x05\x12\x1a\n\x12\x62\x61\x63klog_count_hint\x18\x07 \x01(\x03\x12\x31\n\x07history\x18\x08 \x01(\x0b\x32 .temporal.api.history.v1.History\x12\x17\n\x0fnext_page_token\x18\t \x01(\x0c\x12\x33\n\x05query\x18\n \x01(\x0b\x32$.temporal.api.query.v1.WorkflowQuery\x12K\n\x1dworkflow_execution_task_queue\x18\x0b \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12\x32\n\x0escheduled_time\x18\x0c \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x30\n\x0cstarted_time\x18\r \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\\\n\x07queries\x18\x0e \x03(\x0b\x32K.temporal.api.workflowservice.v1.PollWorkflowTaskQueueResponse.QueriesEntry\x12\x33\n\x08messages\x18\x0f \x03(\x0b\x32!.temporal.api.protocol.v1.Message\x12Q\n\x17poller_scaling_decision\x18\x10 \x01(\x0b\x32\x30.temporal.api.taskqueue.v1.PollerScalingDecision\x12\x17\n\x0fpoller_group_id\x18\x11 \x01(\t\x12\x46\n\x12poller_group_infos\x18\x12 \x03(\x0b\x32*.temporal.api.taskqueue.v1.PollerGroupInfo\x1aT\n\x0cQueriesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x33\n\x05value\x18\x02 \x01(\x0b\x32$.temporal.api.query.v1.WorkflowQuery:\x02\x38\x01"\x8a\n\n#RespondWorkflowTaskCompletedRequest\x12\x12\n\ntask_token\x18\x01 \x01(\x0c\x12\x32\n\x08\x63ommands\x18\x02 \x03(\x0b\x32 .temporal.api.command.v1.Command\x12\x10\n\x08identity\x18\x03 \x01(\t\x12O\n\x11sticky_attributes\x18\x04 \x01(\x0b\x32\x34.temporal.api.taskqueue.v1.StickyExecutionAttributes\x12 \n\x18return_new_workflow_task\x18\x05 \x01(\x08\x12&\n\x1e\x66orce_create_new_workflow_task\x18\x06 \x01(\x08\x12\x1b\n\x0f\x62inary_checksum\x18\x07 \x01(\tB\x02\x18\x01\x12m\n\rquery_results\x18\x08 \x03(\x0b\x32V.temporal.api.workflowservice.v1.RespondWorkflowTaskCompletedRequest.QueryResultsEntry\x12\x11\n\tnamespace\x18\t \x01(\t\x12\x13\n\x0bresource_id\x18\x12 \x01(\t\x12L\n\x14worker_version_stamp\x18\n \x01(\x0b\x32*.temporal.api.common.v1.WorkerVersionStampB\x02\x18\x01\x12\x33\n\x08messages\x18\x0b \x03(\x0b\x32!.temporal.api.protocol.v1.Message\x12H\n\x0csdk_metadata\x18\x0c \x01(\x0b\x32\x32.temporal.api.sdk.v1.WorkflowTaskCompletedMetadata\x12\x43\n\x11metering_metadata\x18\r \x01(\x0b\x32(.temporal.api.common.v1.MeteringMetadata\x12g\n\x0c\x63\x61pabilities\x18\x0e \x01(\x0b\x32Q.temporal.api.workflowservice.v1.RespondWorkflowTaskCompletedRequest.Capabilities\x12>\n\ndeployment\x18\x0f \x01(\x0b\x32&.temporal.api.deployment.v1.DeploymentB\x02\x18\x01\x12\x46\n\x13versioning_behavior\x18\x10 \x01(\x0e\x32).temporal.api.enums.v1.VersioningBehavior\x12O\n\x12\x64\x65ployment_options\x18\x11 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentOptions\x12\x1b\n\x13worker_instance_key\x18\x13 \x01(\t\x12!\n\x19worker_control_task_queue\x18\x14 \x01(\t\x1a_\n\x11QueryResultsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x39\n\x05value\x18\x02 \x01(\x0b\x32*.temporal.api.query.v1.WorkflowQueryResult:\x02\x38\x01\x1a\x45\n\x0c\x43\x61pabilities\x12\x35\n-discard_speculative_workflow_task_with_events\x18\x01 \x01(\x08"\xf5\x01\n$RespondWorkflowTaskCompletedResponse\x12U\n\rworkflow_task\x18\x01 \x01(\x0b\x32>.temporal.api.workflowservice.v1.PollWorkflowTaskQueueResponse\x12V\n\x0e\x61\x63tivity_tasks\x18\x02 \x03(\x0b\x32>.temporal.api.workflowservice.v1.PollActivityTaskQueueResponse\x12\x1e\n\x16reset_history_event_id\x18\x03 \x01(\x03"\x8d\x04\n RespondWorkflowTaskFailedRequest\x12\x12\n\ntask_token\x18\x01 \x01(\x0c\x12=\n\x05\x63\x61use\x18\x02 \x01(\x0e\x32..temporal.api.enums.v1.WorkflowTaskFailedCause\x12\x31\n\x07\x66\x61ilure\x18\x03 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12\x10\n\x08identity\x18\x04 \x01(\t\x12\x1b\n\x0f\x62inary_checksum\x18\x05 \x01(\tB\x02\x18\x01\x12\x11\n\tnamespace\x18\x06 \x01(\t\x12\x13\n\x0bresource_id\x18\x0b \x01(\t\x12\x33\n\x08messages\x18\x07 \x03(\x0b\x32!.temporal.api.protocol.v1.Message\x12\x46\n\x0eworker_version\x18\x08 \x01(\x0b\x32*.temporal.api.common.v1.WorkerVersionStampB\x02\x18\x01\x12>\n\ndeployment\x18\t \x01(\x0b\x32&.temporal.api.deployment.v1.DeploymentB\x02\x18\x01\x12O\n\x12\x64\x65ployment_options\x18\n \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentOptions"#\n!RespondWorkflowTaskFailedResponse"\xe6\x03\n\x1cPollActivityTaskQueueRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x38\n\ntask_queue\x18\x02 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12\x17\n\x0fpoller_group_id\x18\n \x01(\t\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x1b\n\x13worker_instance_key\x18\x08 \x01(\t\x12!\n\x19worker_control_task_queue\x18\t \x01(\t\x12I\n\x13task_queue_metadata\x18\x04 \x01(\x0b\x32,.temporal.api.taskqueue.v1.TaskQueueMetadata\x12Z\n\x1bworker_version_capabilities\x18\x05 \x01(\x0b\x32\x31.temporal.api.common.v1.WorkerVersionCapabilitiesB\x02\x18\x01\x12O\n\x12\x64\x65ployment_options\x18\x06 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentOptionsJ\x04\x08\x07\x10\x08R\x10worker_heartbeat"\xd0\x08\n\x1dPollActivityTaskQueueResponse\x12\x12\n\ntask_token\x18\x01 \x01(\x0c\x12\x1a\n\x12workflow_namespace\x18\x02 \x01(\t\x12;\n\rworkflow_type\x18\x03 \x01(\x0b\x32$.temporal.api.common.v1.WorkflowType\x12\x45\n\x12workflow_execution\x18\x04 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12;\n\ractivity_type\x18\x05 \x01(\x0b\x32$.temporal.api.common.v1.ActivityType\x12\x13\n\x0b\x61\x63tivity_id\x18\x06 \x01(\t\x12.\n\x06header\x18\x07 \x01(\x0b\x32\x1e.temporal.api.common.v1.Header\x12/\n\x05input\x18\x08 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12;\n\x11heartbeat_details\x18\t \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x32\n\x0escheduled_time\x18\n \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x42\n\x1e\x63urrent_attempt_scheduled_time\x18\x0b \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x30\n\x0cstarted_time\x18\x0c \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x0f\n\x07\x61ttempt\x18\r \x01(\x05\x12<\n\x19schedule_to_close_timeout\x18\x0e \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x39\n\x16start_to_close_timeout\x18\x0f \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x34\n\x11heartbeat_timeout\x18\x10 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x39\n\x0cretry_policy\x18\x11 \x01(\x0b\x32#.temporal.api.common.v1.RetryPolicy\x12Q\n\x17poller_scaling_decision\x18\x12 \x01(\x0b\x32\x30.temporal.api.taskqueue.v1.PollerScalingDecision\x12\x32\n\x08priority\x18\x13 \x01(\x0b\x32 .temporal.api.common.v1.Priority\x12\x17\n\x0f\x61\x63tivity_run_id\x18\x14 \x01(\t\x12\x46\n\x12poller_group_infos\x18\x15 \x03(\x0b\x32*.temporal.api.taskqueue.v1.PollerGroupInfo"\xa5\x01\n"RecordActivityTaskHeartbeatRequest\x12\x12\n\ntask_token\x18\x01 \x01(\x0c\x12\x31\n\x07\x64\x65tails\x18\x02 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x11\n\tnamespace\x18\x04 \x01(\t\x12\x13\n\x0bresource_id\x18\x05 \x01(\t"p\n#RecordActivityTaskHeartbeatResponse\x12\x18\n\x10\x63\x61ncel_requested\x18\x01 \x01(\x08\x12\x17\n\x0f\x61\x63tivity_paused\x18\x02 \x01(\x08\x12\x16\n\x0e\x61\x63tivity_reset\x18\x03 \x01(\x08"\xcf\x01\n&RecordActivityTaskHeartbeatByIdRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x12\x13\n\x0b\x61\x63tivity_id\x18\x04 \x01(\t\x12\x31\n\x07\x64\x65tails\x18\x05 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x10\n\x08identity\x18\x06 \x01(\t\x12\x13\n\x0bresource_id\x18\x07 \x01(\t"t\n\'RecordActivityTaskHeartbeatByIdResponse\x12\x18\n\x10\x63\x61ncel_requested\x18\x01 \x01(\x08\x12\x17\n\x0f\x61\x63tivity_paused\x18\x02 \x01(\x08\x12\x16\n\x0e\x61\x63tivity_reset\x18\x03 \x01(\x08"\xfe\x02\n#RespondActivityTaskCompletedRequest\x12\x12\n\ntask_token\x18\x01 \x01(\x0c\x12\x30\n\x06result\x18\x02 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x11\n\tnamespace\x18\x04 \x01(\t\x12\x13\n\x0bresource_id\x18\x08 \x01(\t\x12\x46\n\x0eworker_version\x18\x05 \x01(\x0b\x32*.temporal.api.common.v1.WorkerVersionStampB\x02\x18\x01\x12>\n\ndeployment\x18\x06 \x01(\x0b\x32&.temporal.api.deployment.v1.DeploymentB\x02\x18\x01\x12O\n\x12\x64\x65ployment_options\x18\x07 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentOptions"&\n$RespondActivityTaskCompletedResponse"\xcf\x01\n\'RespondActivityTaskCompletedByIdRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x12\x13\n\x0b\x61\x63tivity_id\x18\x04 \x01(\t\x12\x30\n\x06result\x18\x05 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x10\n\x08identity\x18\x06 \x01(\t\x12\x13\n\x0bresource_id\x18\x07 \x01(\t"*\n(RespondActivityTaskCompletedByIdResponse"\xbe\x03\n RespondActivityTaskFailedRequest\x12\x12\n\ntask_token\x18\x01 \x01(\x0c\x12\x31\n\x07\x66\x61ilure\x18\x02 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x11\n\tnamespace\x18\x04 \x01(\t\x12\x13\n\x0bresource_id\x18\t \x01(\t\x12@\n\x16last_heartbeat_details\x18\x05 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x46\n\x0eworker_version\x18\x06 \x01(\x0b\x32*.temporal.api.common.v1.WorkerVersionStampB\x02\x18\x01\x12>\n\ndeployment\x18\x07 \x01(\x0b\x32&.temporal.api.deployment.v1.DeploymentB\x02\x18\x01\x12O\n\x12\x64\x65ployment_options\x18\x08 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentOptions"W\n!RespondActivityTaskFailedResponse\x12\x32\n\x08\x66\x61ilures\x18\x01 \x03(\x0b\x32 .temporal.api.failure.v1.Failure"\x8f\x02\n$RespondActivityTaskFailedByIdRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x12\x13\n\x0b\x61\x63tivity_id\x18\x04 \x01(\t\x12\x31\n\x07\x66\x61ilure\x18\x05 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12\x10\n\x08identity\x18\x06 \x01(\t\x12@\n\x16last_heartbeat_details\x18\x07 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x13\n\x0bresource_id\x18\x08 \x01(\t"[\n%RespondActivityTaskFailedByIdResponse\x12\x32\n\x08\x66\x61ilures\x18\x01 \x03(\x0b\x32 .temporal.api.failure.v1.Failure"\xfe\x02\n"RespondActivityTaskCanceledRequest\x12\x12\n\ntask_token\x18\x01 \x01(\x0c\x12\x31\n\x07\x64\x65tails\x18\x02 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x11\n\tnamespace\x18\x04 \x01(\t\x12\x13\n\x0bresource_id\x18\x08 \x01(\t\x12\x46\n\x0eworker_version\x18\x05 \x01(\x0b\x32*.temporal.api.common.v1.WorkerVersionStampB\x02\x18\x01\x12>\n\ndeployment\x18\x06 \x01(\x0b\x32&.temporal.api.deployment.v1.DeploymentB\x02\x18\x01\x12O\n\x12\x64\x65ployment_options\x18\x07 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentOptions"%\n#RespondActivityTaskCanceledResponse"\xa0\x02\n&RespondActivityTaskCanceledByIdRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x12\x13\n\x0b\x61\x63tivity_id\x18\x04 \x01(\t\x12\x31\n\x07\x64\x65tails\x18\x05 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x10\n\x08identity\x18\x06 \x01(\t\x12O\n\x12\x64\x65ployment_options\x18\x07 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentOptions\x12\x13\n\x0bresource_id\x18\x08 \x01(\t")\n\'RespondActivityTaskCanceledByIdResponse"\x84\x02\n%RequestCancelWorkflowExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x45\n\x12workflow_execution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x12\n\nrequest_id\x18\x04 \x01(\t\x12\x1e\n\x16\x66irst_execution_run_id\x18\x05 \x01(\t\x12\x0e\n\x06reason\x18\x06 \x01(\t\x12+\n\x05links\x18\x07 \x03(\x0b\x32\x1c.temporal.api.common.v1.Link"(\n&RequestCancelWorkflowExecutionResponse"\xde\x02\n\x1eSignalWorkflowExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x45\n\x12workflow_execution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x13\n\x0bsignal_name\x18\x03 \x01(\t\x12/\n\x05input\x18\x04 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x10\n\x08identity\x18\x05 \x01(\t\x12\x12\n\nrequest_id\x18\x06 \x01(\t\x12\x13\n\x07\x63ontrol\x18\x07 \x01(\tB\x02\x18\x01\x12.\n\x06header\x18\x08 \x01(\x0b\x32\x1e.temporal.api.common.v1.Header\x12+\n\x05links\x18\n \x03(\x0b\x32\x1c.temporal.api.common.v1.LinkJ\x04\x08\t\x10\n"M\n\x1fSignalWorkflowExecutionResponse\x12*\n\x04link\x18\x01 \x01(\x0b\x32\x1c.temporal.api.common.v1.Link"\xbd\n\n\'SignalWithStartWorkflowExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12;\n\rworkflow_type\x18\x03 \x01(\x0b\x32$.temporal.api.common.v1.WorkflowType\x12\x38\n\ntask_queue\x18\x04 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12/\n\x05input\x18\x05 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12=\n\x1aworkflow_execution_timeout\x18\x06 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x37\n\x14workflow_run_timeout\x18\x07 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x38\n\x15workflow_task_timeout\x18\x08 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x10\n\x08identity\x18\t \x01(\t\x12\x12\n\nrequest_id\x18\n \x01(\t\x12N\n\x18workflow_id_reuse_policy\x18\x0b \x01(\x0e\x32,.temporal.api.enums.v1.WorkflowIdReusePolicy\x12T\n\x1bworkflow_id_conflict_policy\x18\x16 \x01(\x0e\x32/.temporal.api.enums.v1.WorkflowIdConflictPolicy\x12\x13\n\x0bsignal_name\x18\x0c \x01(\t\x12\x36\n\x0csignal_input\x18\r \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x13\n\x07\x63ontrol\x18\x0e \x01(\tB\x02\x18\x01\x12\x39\n\x0cretry_policy\x18\x0f \x01(\x0b\x32#.temporal.api.common.v1.RetryPolicy\x12\x15\n\rcron_schedule\x18\x10 \x01(\t\x12*\n\x04memo\x18\x11 \x01(\x0b\x32\x1c.temporal.api.common.v1.Memo\x12\x43\n\x11search_attributes\x18\x12 \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes\x12.\n\x06header\x18\x13 \x01(\x0b\x32\x1e.temporal.api.common.v1.Header\x12\x37\n\x14workflow_start_delay\x18\x14 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x38\n\ruser_metadata\x18\x17 \x01(\x0b\x32!.temporal.api.sdk.v1.UserMetadata\x12+\n\x05links\x18\x18 \x03(\x0b\x32\x1c.temporal.api.common.v1.Link\x12I\n\x13versioning_override\x18\x19 \x01(\x0b\x32,.temporal.api.workflow.v1.VersioningOverride\x12\x32\n\x08priority\x18\x1a \x01(\x0b\x32 .temporal.api.common.v1.Priority\x12J\n\x14time_skipping_config\x18\x1b \x01(\x0b\x32,.temporal.api.workflow.v1.TimeSkippingConfigJ\x04\x08\x15\x10\x16"~\n(SignalWithStartWorkflowExecutionResponse\x12\x0e\n\x06run_id\x18\x01 \x01(\t\x12\x0f\n\x07started\x18\x02 \x01(\x08\x12\x31\n\x0bsignal_link\x18\x03 \x01(\x0b\x32\x1c.temporal.api.common.v1.Link"\xc1\x03\n\x1dResetWorkflowExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x45\n\x12workflow_execution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x0e\n\x06reason\x18\x03 \x01(\t\x12%\n\x1dworkflow_task_finish_event_id\x18\x04 \x01(\x03\x12\x12\n\nrequest_id\x18\x05 \x01(\t\x12G\n\x12reset_reapply_type\x18\x06 \x01(\x0e\x32\'.temporal.api.enums.v1.ResetReapplyTypeB\x02\x18\x01\x12S\n\x1breset_reapply_exclude_types\x18\x07 \x03(\x0e\x32..temporal.api.enums.v1.ResetReapplyExcludeType\x12K\n\x15post_reset_operations\x18\x08 \x03(\x0b\x32,.temporal.api.workflow.v1.PostResetOperation\x12\x10\n\x08identity\x18\t \x01(\t"0\n\x1eResetWorkflowExecutionResponse\x12\x0e\n\x06run_id\x18\x01 \x01(\t"\x9f\x02\n!TerminateWorkflowExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x45\n\x12workflow_execution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x0e\n\x06reason\x18\x03 \x01(\t\x12\x31\n\x07\x64\x65tails\x18\x04 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x10\n\x08identity\x18\x05 \x01(\t\x12\x1e\n\x16\x66irst_execution_run_id\x18\x06 \x01(\t\x12+\n\x05links\x18\x07 \x03(\x0b\x32\x1c.temporal.api.common.v1.Link"$\n"TerminateWorkflowExecutionResponse"z\n\x1e\x44\x65leteWorkflowExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x45\n\x12workflow_execution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution"!\n\x1f\x44\x65leteWorkflowExecutionResponse"\xc9\x02\n!ListOpenWorkflowExecutionsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x19\n\x11maximum_page_size\x18\x02 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c\x12\x42\n\x11start_time_filter\x18\x04 \x01(\x0b\x32\'.temporal.api.filter.v1.StartTimeFilter\x12K\n\x10\x65xecution_filter\x18\x05 \x01(\x0b\x32/.temporal.api.filter.v1.WorkflowExecutionFilterH\x00\x12\x41\n\x0btype_filter\x18\x06 \x01(\x0b\x32*.temporal.api.filter.v1.WorkflowTypeFilterH\x00\x42\t\n\x07\x66ilters"\x82\x01\n"ListOpenWorkflowExecutionsResponse\x12\x43\n\nexecutions\x18\x01 \x03(\x0b\x32/.temporal.api.workflow.v1.WorkflowExecutionInfo\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c"\x8a\x03\n#ListClosedWorkflowExecutionsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x19\n\x11maximum_page_size\x18\x02 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c\x12\x42\n\x11start_time_filter\x18\x04 \x01(\x0b\x32\'.temporal.api.filter.v1.StartTimeFilter\x12K\n\x10\x65xecution_filter\x18\x05 \x01(\x0b\x32/.temporal.api.filter.v1.WorkflowExecutionFilterH\x00\x12\x41\n\x0btype_filter\x18\x06 \x01(\x0b\x32*.temporal.api.filter.v1.WorkflowTypeFilterH\x00\x12=\n\rstatus_filter\x18\x07 \x01(\x0b\x32$.temporal.api.filter.v1.StatusFilterH\x00\x42\t\n\x07\x66ilters"\x84\x01\n$ListClosedWorkflowExecutionsResponse\x12\x43\n\nexecutions\x18\x01 \x03(\x0b\x32/.temporal.api.workflow.v1.WorkflowExecutionInfo\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c"m\n\x1dListWorkflowExecutionsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x11\n\tpage_size\x18\x02 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c\x12\r\n\x05query\x18\x04 \x01(\t"~\n\x1eListWorkflowExecutionsResponse\x12\x43\n\nexecutions\x18\x01 \x03(\x0b\x32/.temporal.api.workflow.v1.WorkflowExecutionInfo\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c"u\n%ListArchivedWorkflowExecutionsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x11\n\tpage_size\x18\x02 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c\x12\r\n\x05query\x18\x04 \x01(\t"\x86\x01\n&ListArchivedWorkflowExecutionsResponse\x12\x43\n\nexecutions\x18\x01 \x03(\x0b\x32/.temporal.api.workflow.v1.WorkflowExecutionInfo\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c"m\n\x1dScanWorkflowExecutionsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x11\n\tpage_size\x18\x02 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c\x12\r\n\x05query\x18\x04 \x01(\t"~\n\x1eScanWorkflowExecutionsResponse\x12\x43\n\nexecutions\x18\x01 \x03(\x0b\x32/.temporal.api.workflow.v1.WorkflowExecutionInfo\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c"B\n\x1e\x43ountWorkflowExecutionsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\r\n\x05query\x18\x02 \x01(\t"\xed\x01\n\x1f\x43ountWorkflowExecutionsResponse\x12\r\n\x05\x63ount\x18\x01 \x01(\x03\x12\x61\n\x06groups\x18\x02 \x03(\x0b\x32Q.temporal.api.workflowservice.v1.CountWorkflowExecutionsResponse.AggregationGroup\x1aX\n\x10\x41ggregationGroup\x12\x35\n\x0cgroup_values\x18\x01 \x03(\x0b\x32\x1f.temporal.api.common.v1.Payload\x12\r\n\x05\x63ount\x18\x02 \x01(\x03"\x1c\n\x1aGetSearchAttributesRequest"\xc9\x01\n\x1bGetSearchAttributesResponse\x12T\n\x04keys\x18\x01 \x03(\x0b\x32\x46.temporal.api.workflowservice.v1.GetSearchAttributesResponse.KeysEntry\x1aT\n\tKeysEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x36\n\x05value\x18\x02 \x01(\x0e\x32\'.temporal.api.enums.v1.IndexedValueType:\x02\x38\x01"\xe9\x02\n RespondQueryTaskCompletedRequest\x12\x12\n\ntask_token\x18\x01 \x01(\x0c\x12>\n\x0e\x63ompleted_type\x18\x02 \x01(\x0e\x32&.temporal.api.enums.v1.QueryResultType\x12\x36\n\x0cquery_result\x18\x03 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x15\n\rerror_message\x18\x04 \x01(\t\x12\x11\n\tnamespace\x18\x06 \x01(\t\x12\x31\n\x07\x66\x61ilure\x18\x07 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12=\n\x05\x63\x61use\x18\x08 \x01(\x0e\x32..temporal.api.enums.v1.WorkflowTaskFailedCause\x12\x17\n\x0fpoller_group_id\x18\t \x01(\tJ\x04\x08\x05\x10\x06"#\n!RespondQueryTaskCompletedResponse"n\n\x1bResetStickyTaskQueueRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12<\n\texecution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution"\x1e\n\x1cResetStickyTaskQueueResponse"\x9b\x02\n\x15ShutdownWorkerRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x19\n\x11sticky_task_queue\x18\x02 \x01(\t\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x0e\n\x06reason\x18\x04 \x01(\t\x12\x41\n\x10worker_heartbeat\x18\x05 \x01(\x0b\x32\'.temporal.api.worker.v1.WorkerHeartbeat\x12\x1b\n\x13worker_instance_key\x18\x06 \x01(\t\x12\x12\n\ntask_queue\x18\x07 \x01(\t\x12>\n\x10task_queue_types\x18\x08 \x03(\x0e\x32$.temporal.api.enums.v1.TaskQueueType"\x18\n\x16ShutdownWorkerResponse"\xe9\x01\n\x14QueryWorkflowRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12<\n\texecution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x33\n\x05query\x18\x03 \x01(\x0b\x32$.temporal.api.query.v1.WorkflowQuery\x12K\n\x16query_reject_condition\x18\x04 \x01(\x0e\x32+.temporal.api.enums.v1.QueryRejectCondition"\x8d\x01\n\x15QueryWorkflowResponse\x12\x36\n\x0cquery_result\x18\x01 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12<\n\x0equery_rejected\x18\x02 \x01(\x0b\x32$.temporal.api.query.v1.QueryRejected"s\n DescribeWorkflowExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12<\n\texecution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution"\x99\x05\n!DescribeWorkflowExecutionResponse\x12K\n\x10\x65xecution_config\x18\x01 \x01(\x0b\x32\x31.temporal.api.workflow.v1.WorkflowExecutionConfig\x12P\n\x17workflow_execution_info\x18\x02 \x01(\x0b\x32/.temporal.api.workflow.v1.WorkflowExecutionInfo\x12I\n\x12pending_activities\x18\x03 \x03(\x0b\x32-.temporal.api.workflow.v1.PendingActivityInfo\x12M\n\x10pending_children\x18\x04 \x03(\x0b\x32\x33.temporal.api.workflow.v1.PendingChildExecutionInfo\x12P\n\x15pending_workflow_task\x18\x05 \x01(\x0b\x32\x31.temporal.api.workflow.v1.PendingWorkflowTaskInfo\x12\x39\n\tcallbacks\x18\x06 \x03(\x0b\x32&.temporal.api.workflow.v1.CallbackInfo\x12U\n\x18pending_nexus_operations\x18\x07 \x03(\x0b\x32\x33.temporal.api.workflow.v1.PendingNexusOperationInfo\x12W\n\x16workflow_extended_info\x18\x08 \x01(\x0b\x32\x37.temporal.api.workflow.v1.WorkflowExecutionExtendedInfo"\x90\x04\n\x18\x44\x65scribeTaskQueueRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x38\n\ntask_queue\x18\x02 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12=\n\x0ftask_queue_type\x18\x03 \x01(\x0e\x32$.temporal.api.enums.v1.TaskQueueType\x12\x14\n\x0creport_stats\x18\x08 \x01(\x08\x12\x15\n\rreport_config\x18\x0b \x01(\x08\x12%\n\x19include_task_queue_status\x18\x04 \x01(\x08\x42\x02\x18\x01\x12\x42\n\x08\x61pi_mode\x18\x05 \x01(\x0e\x32,.temporal.api.enums.v1.DescribeTaskQueueModeB\x02\x18\x01\x12J\n\x08versions\x18\x06 \x01(\x0b\x32\x34.temporal.api.taskqueue.v1.TaskQueueVersionSelectionB\x02\x18\x01\x12\x42\n\x10task_queue_types\x18\x07 \x03(\x0e\x32$.temporal.api.enums.v1.TaskQueueTypeB\x02\x18\x01\x12\x1a\n\x0ereport_pollers\x18\t \x01(\x08\x42\x02\x18\x01\x12$\n\x18report_task_reachability\x18\n \x01(\x08\x42\x02\x18\x01"\xec\x07\n\x19\x44\x65scribeTaskQueueResponse\x12\x36\n\x07pollers\x18\x01 \x03(\x0b\x32%.temporal.api.taskqueue.v1.PollerInfo\x12\x38\n\x05stats\x18\x05 \x01(\x0b\x32).temporal.api.taskqueue.v1.TaskQueueStats\x12q\n\x15stats_by_priority_key\x18\x08 \x03(\x0b\x32R.temporal.api.workflowservice.v1.DescribeTaskQueueResponse.StatsByPriorityKeyEntry\x12K\n\x0fversioning_info\x18\x04 \x01(\x0b\x32\x32.temporal.api.taskqueue.v1.TaskQueueVersioningInfo\x12:\n\x06\x63onfig\x18\x06 \x01(\x0b\x32*.temporal.api.taskqueue.v1.TaskQueueConfig\x12k\n\x14\x65\x66\x66\x65\x63tive_rate_limit\x18\x07 \x01(\x0b\x32M.temporal.api.workflowservice.v1.DescribeTaskQueueResponse.EffectiveRateLimit\x12I\n\x11task_queue_status\x18\x02 \x01(\x0b\x32*.temporal.api.taskqueue.v1.TaskQueueStatusB\x02\x18\x01\x12g\n\rversions_info\x18\x03 \x03(\x0b\x32L.temporal.api.workflowservice.v1.DescribeTaskQueueResponse.VersionsInfoEntryB\x02\x18\x01\x1a\x64\n\x17StatsByPriorityKeyEntry\x12\x0b\n\x03key\x18\x01 \x01(\x05\x12\x38\n\x05value\x18\x02 \x01(\x0b\x32).temporal.api.taskqueue.v1.TaskQueueStats:\x02\x38\x01\x1at\n\x12\x45\x66\x66\x65\x63tiveRateLimit\x12\x1b\n\x13requests_per_second\x18\x01 \x01(\x02\x12\x41\n\x11rate_limit_source\x18\x02 \x01(\x0e\x32&.temporal.api.enums.v1.RateLimitSource\x1a\x64\n\x11VersionsInfoEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12>\n\x05value\x18\x02 \x01(\x0b\x32/.temporal.api.taskqueue.v1.TaskQueueVersionInfo:\x02\x38\x01"\x17\n\x15GetClusterInfoRequest"\xd1\x03\n\x16GetClusterInfoResponse\x12h\n\x11supported_clients\x18\x01 \x03(\x0b\x32M.temporal.api.workflowservice.v1.GetClusterInfoResponse.SupportedClientsEntry\x12\x16\n\x0eserver_version\x18\x02 \x01(\t\x12\x12\n\ncluster_id\x18\x03 \x01(\t\x12:\n\x0cversion_info\x18\x04 \x01(\x0b\x32$.temporal.api.version.v1.VersionInfo\x12\x14\n\x0c\x63luster_name\x18\x05 \x01(\t\x12\x1b\n\x13history_shard_count\x18\x06 \x01(\x05\x12\x19\n\x11persistence_store\x18\x07 \x01(\t\x12\x18\n\x10visibility_store\x18\x08 \x01(\t\x12 \n\x18initial_failover_version\x18\t \x01(\x03\x12"\n\x1a\x66\x61ilover_version_increment\x18\n \x01(\x03\x1a\x37\n\x15SupportedClientsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01"\x16\n\x14GetSystemInfoRequest"\x97\x04\n\x15GetSystemInfoResponse\x12\x16\n\x0eserver_version\x18\x01 \x01(\t\x12Y\n\x0c\x63\x61pabilities\x18\x02 \x01(\x0b\x32\x43.temporal.api.workflowservice.v1.GetSystemInfoResponse.Capabilities\x1a\x8a\x03\n\x0c\x43\x61pabilities\x12\x1f\n\x17signal_and_query_header\x18\x01 \x01(\x08\x12&\n\x1einternal_error_differentiation\x18\x02 \x01(\x08\x12*\n"activity_failure_include_heartbeat\x18\x03 \x01(\x08\x12\x1a\n\x12supports_schedules\x18\x04 \x01(\x08\x12"\n\x1a\x65ncoded_failure_attributes\x18\x05 \x01(\x08\x12!\n\x19\x62uild_id_based_versioning\x18\x06 \x01(\x08\x12\x13\n\x0bupsert_memo\x18\x07 \x01(\x08\x12\x1c\n\x14\x65\x61ger_workflow_start\x18\x08 \x01(\x08\x12\x14\n\x0csdk_metadata\x18\t \x01(\x08\x12\'\n\x1f\x63ount_group_by_execution_status\x18\n \x01(\x08\x12\r\n\x05nexus\x18\x0b \x01(\x08\x12!\n\x19server_scaled_deployments\x18\x0c \x01(\x08"m\n\x1eListTaskQueuePartitionsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x38\n\ntask_queue\x18\x02 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue"\xdf\x01\n\x1fListTaskQueuePartitionsResponse\x12]\n\x1e\x61\x63tivity_task_queue_partitions\x18\x01 \x03(\x0b\x32\x35.temporal.api.taskqueue.v1.TaskQueuePartitionMetadata\x12]\n\x1eworkflow_task_queue_partitions\x18\x02 \x03(\x0b\x32\x35.temporal.api.taskqueue.v1.TaskQueuePartitionMetadata"\xcc\x02\n\x15\x43reateScheduleRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bschedule_id\x18\x02 \x01(\t\x12\x34\n\x08schedule\x18\x03 \x01(\x0b\x32".temporal.api.schedule.v1.Schedule\x12>\n\rinitial_patch\x18\x04 \x01(\x0b\x32\'.temporal.api.schedule.v1.SchedulePatch\x12\x10\n\x08identity\x18\x05 \x01(\t\x12\x12\n\nrequest_id\x18\x06 \x01(\t\x12*\n\x04memo\x18\x07 \x01(\x0b\x32\x1c.temporal.api.common.v1.Memo\x12\x43\n\x11search_attributes\x18\x08 \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes"0\n\x16\x43reateScheduleResponse\x12\x16\n\x0e\x63onflict_token\x18\x01 \x01(\x0c"A\n\x17\x44\x65scribeScheduleRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bschedule_id\x18\x02 \x01(\t"\x8f\x02\n\x18\x44\x65scribeScheduleResponse\x12\x34\n\x08schedule\x18\x01 \x01(\x0b\x32".temporal.api.schedule.v1.Schedule\x12\x34\n\x04info\x18\x02 \x01(\x0b\x32&.temporal.api.schedule.v1.ScheduleInfo\x12*\n\x04memo\x18\x03 \x01(\x0b\x32\x1c.temporal.api.common.v1.Memo\x12\x43\n\x11search_attributes\x18\x04 \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes\x12\x16\n\x0e\x63onflict_token\x18\x05 \x01(\x0c"\xa4\x02\n\x15UpdateScheduleRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bschedule_id\x18\x02 \x01(\t\x12\x34\n\x08schedule\x18\x03 \x01(\x0b\x32".temporal.api.schedule.v1.Schedule\x12\x16\n\x0e\x63onflict_token\x18\x04 \x01(\x0c\x12\x10\n\x08identity\x18\x05 \x01(\t\x12\x12\n\nrequest_id\x18\x06 \x01(\t\x12\x43\n\x11search_attributes\x18\x07 \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes\x12*\n\x04memo\x18\x08 \x01(\x0b\x32\x1c.temporal.api.common.v1.Memo"\x18\n\x16UpdateScheduleResponse"\x9c\x01\n\x14PatchScheduleRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bschedule_id\x18\x02 \x01(\t\x12\x36\n\x05patch\x18\x03 \x01(\x0b\x32\'.temporal.api.schedule.v1.SchedulePatch\x12\x10\n\x08identity\x18\x04 \x01(\t\x12\x12\n\nrequest_id\x18\x05 \x01(\t"\x17\n\x15PatchScheduleResponse"\xa8\x01\n ListScheduleMatchingTimesRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bschedule_id\x18\x02 \x01(\t\x12.\n\nstart_time\x18\x03 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12,\n\x08\x65nd_time\x18\x04 \x01(\x0b\x32\x1a.google.protobuf.Timestamp"S\n!ListScheduleMatchingTimesResponse\x12.\n\nstart_time\x18\x01 \x03(\x0b\x32\x1a.google.protobuf.Timestamp"Q\n\x15\x44\x65leteScheduleRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bschedule_id\x18\x02 \x01(\t\x12\x10\n\x08identity\x18\x03 \x01(\t"\x18\n\x16\x44\x65leteScheduleResponse"l\n\x14ListSchedulesRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x19\n\x11maximum_page_size\x18\x02 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c\x12\r\n\x05query\x18\x04 \x01(\t"p\n\x15ListSchedulesResponse\x12>\n\tschedules\x18\x01 \x03(\x0b\x32+.temporal.api.schedule.v1.ScheduleListEntry\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c"9\n\x15\x43ountSchedulesRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\r\n\x05query\x18\x02 \x01(\t"\xdb\x01\n\x16\x43ountSchedulesResponse\x12\r\n\x05\x63ount\x18\x01 \x01(\x03\x12X\n\x06groups\x18\x02 \x03(\x0b\x32H.temporal.api.workflowservice.v1.CountSchedulesResponse.AggregationGroup\x1aX\n\x10\x41ggregationGroup\x12\x35\n\x0cgroup_values\x18\x01 \x03(\x0b\x32\x1f.temporal.api.common.v1.Payload\x12\r\n\x05\x63ount\x18\x02 \x01(\x03"\x86\x05\n\'UpdateWorkerBuildIdCompatibilityRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x12\n\ntask_queue\x18\x02 \x01(\t\x12-\n#add_new_build_id_in_new_default_set\x18\x03 \x01(\tH\x00\x12\x87\x01\n\x1b\x61\x64\x64_new_compatible_build_id\x18\x04 \x01(\x0b\x32`.temporal.api.workflowservice.v1.UpdateWorkerBuildIdCompatibilityRequest.AddNewCompatibleVersionH\x00\x12!\n\x17promote_set_by_build_id\x18\x05 \x01(\tH\x00\x12%\n\x1bpromote_build_id_within_set\x18\x06 \x01(\tH\x00\x12h\n\nmerge_sets\x18\x07 \x01(\x0b\x32R.temporal.api.workflowservice.v1.UpdateWorkerBuildIdCompatibilityRequest.MergeSetsH\x00\x1ao\n\x17\x41\x64\x64NewCompatibleVersion\x12\x14\n\x0cnew_build_id\x18\x01 \x01(\t\x12$\n\x1c\x65xisting_compatible_build_id\x18\x02 \x01(\t\x12\x18\n\x10make_set_default\x18\x03 \x01(\x08\x1aI\n\tMergeSets\x12\x1c\n\x14primary_set_build_id\x18\x01 \x01(\t\x12\x1e\n\x16secondary_set_build_id\x18\x02 \x01(\tB\x0b\n\toperation"@\n(UpdateWorkerBuildIdCompatibilityResponseJ\x04\x08\x01\x10\x02R\x0eversion_set_id"_\n$GetWorkerBuildIdCompatibilityRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x12\n\ntask_queue\x18\x02 \x01(\t\x12\x10\n\x08max_sets\x18\x03 \x01(\x05"t\n%GetWorkerBuildIdCompatibilityResponse\x12K\n\x12major_version_sets\x18\x01 \x03(\x0b\x32/.temporal.api.taskqueue.v1.CompatibleVersionSet"\xb5\r\n"UpdateWorkerVersioningRulesRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x12\n\ntask_queue\x18\x02 \x01(\t\x12\x16\n\x0e\x63onflict_token\x18\x03 \x01(\x0c\x12\x81\x01\n\x16insert_assignment_rule\x18\x04 \x01(\x0b\x32_.temporal.api.workflowservice.v1.UpdateWorkerVersioningRulesRequest.InsertBuildIdAssignmentRuleH\x00\x12\x83\x01\n\x17replace_assignment_rule\x18\x05 \x01(\x0b\x32`.temporal.api.workflowservice.v1.UpdateWorkerVersioningRulesRequest.ReplaceBuildIdAssignmentRuleH\x00\x12\x81\x01\n\x16\x64\x65lete_assignment_rule\x18\x06 \x01(\x0b\x32_.temporal.api.workflowservice.v1.UpdateWorkerVersioningRulesRequest.DeleteBuildIdAssignmentRuleH\x00\x12\x8c\x01\n\x1c\x61\x64\x64_compatible_redirect_rule\x18\x07 \x01(\x0b\x32\x64.temporal.api.workflowservice.v1.UpdateWorkerVersioningRulesRequest.AddCompatibleBuildIdRedirectRuleH\x00\x12\x94\x01\n replace_compatible_redirect_rule\x18\x08 \x01(\x0b\x32h.temporal.api.workflowservice.v1.UpdateWorkerVersioningRulesRequest.ReplaceCompatibleBuildIdRedirectRuleH\x00\x12\x92\x01\n\x1f\x64\x65lete_compatible_redirect_rule\x18\t \x01(\x0b\x32g.temporal.api.workflowservice.v1.UpdateWorkerVersioningRulesRequest.DeleteCompatibleBuildIdRedirectRuleH\x00\x12l\n\x0f\x63ommit_build_id\x18\n \x01(\x0b\x32Q.temporal.api.workflowservice.v1.UpdateWorkerVersioningRulesRequest.CommitBuildIdH\x00\x1aq\n\x1bInsertBuildIdAssignmentRule\x12\x12\n\nrule_index\x18\x01 \x01(\x05\x12>\n\x04rule\x18\x02 \x01(\x0b\x32\x30.temporal.api.taskqueue.v1.BuildIdAssignmentRule\x1a\x81\x01\n\x1cReplaceBuildIdAssignmentRule\x12\x12\n\nrule_index\x18\x01 \x01(\x05\x12>\n\x04rule\x18\x02 \x01(\x0b\x32\x30.temporal.api.taskqueue.v1.BuildIdAssignmentRule\x12\r\n\x05\x66orce\x18\x03 \x01(\x08\x1a@\n\x1b\x44\x65leteBuildIdAssignmentRule\x12\x12\n\nrule_index\x18\x01 \x01(\x05\x12\r\n\x05\x66orce\x18\x02 \x01(\x08\x1aj\n AddCompatibleBuildIdRedirectRule\x12\x46\n\x04rule\x18\x01 \x01(\x0b\x32\x38.temporal.api.taskqueue.v1.CompatibleBuildIdRedirectRule\x1an\n$ReplaceCompatibleBuildIdRedirectRule\x12\x46\n\x04rule\x18\x01 \x01(\x0b\x32\x38.temporal.api.taskqueue.v1.CompatibleBuildIdRedirectRule\x1a>\n#DeleteCompatibleBuildIdRedirectRule\x12\x17\n\x0fsource_build_id\x18\x01 \x01(\t\x1a\x37\n\rCommitBuildId\x12\x17\n\x0ftarget_build_id\x18\x01 \x01(\t\x12\r\n\x05\x66orce\x18\x02 \x01(\x08\x42\x0b\n\toperation"\xfc\x01\n#UpdateWorkerVersioningRulesResponse\x12U\n\x10\x61ssignment_rules\x18\x01 \x03(\x0b\x32;.temporal.api.taskqueue.v1.TimestampedBuildIdAssignmentRule\x12\x66\n\x19\x63ompatible_redirect_rules\x18\x02 \x03(\x0b\x32\x43.temporal.api.taskqueue.v1.TimestampedCompatibleBuildIdRedirectRule\x12\x16\n\x0e\x63onflict_token\x18\x03 \x01(\x0c"H\n\x1fGetWorkerVersioningRulesRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x12\n\ntask_queue\x18\x02 \x01(\t"\xf9\x01\n GetWorkerVersioningRulesResponse\x12U\n\x10\x61ssignment_rules\x18\x01 \x03(\x0b\x32;.temporal.api.taskqueue.v1.TimestampedBuildIdAssignmentRule\x12\x66\n\x19\x63ompatible_redirect_rules\x18\x02 \x03(\x0b\x32\x43.temporal.api.taskqueue.v1.TimestampedCompatibleBuildIdRedirectRule\x12\x16\n\x0e\x63onflict_token\x18\x03 \x01(\x0c"\x9c\x01\n GetWorkerTaskReachabilityRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x11\n\tbuild_ids\x18\x02 \x03(\t\x12\x13\n\x0btask_queues\x18\x03 \x03(\t\x12=\n\x0creachability\x18\x04 \x01(\x0e\x32\'.temporal.api.enums.v1.TaskReachability"r\n!GetWorkerTaskReachabilityResponse\x12M\n\x15\x62uild_id_reachability\x18\x01 \x03(\x0b\x32..temporal.api.taskqueue.v1.BuildIdReachability"\x85\x02\n\x1eUpdateWorkflowExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x45\n\x12workflow_execution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x1e\n\x16\x66irst_execution_run_id\x18\x03 \x01(\t\x12\x37\n\x0bwait_policy\x18\x04 \x01(\x0b\x32".temporal.api.update.v1.WaitPolicy\x12\x30\n\x07request\x18\x05 \x01(\x0b\x32\x1f.temporal.api.update.v1.Request"\xd7\x01\n\x1fUpdateWorkflowExecutionResponse\x12\x35\n\nupdate_ref\x18\x01 \x01(\x0b\x32!.temporal.api.update.v1.UpdateRef\x12\x30\n\x07outcome\x18\x02 \x01(\x0b\x32\x1f.temporal.api.update.v1.Outcome\x12K\n\x05stage\x18\x03 \x01(\x0e\x32<.temporal.api.enums.v1.UpdateWorkflowExecutionLifecycleStage"\xf4\x07\n\x1aStartBatchOperationRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x18\n\x10visibility_query\x18\x02 \x01(\t\x12\x0e\n\x06job_id\x18\x03 \x01(\t\x12\x0e\n\x06reason\x18\x04 \x01(\t\x12=\n\nexecutions\x18\x05 \x03(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12!\n\x19max_operations_per_second\x18\x06 \x01(\x02\x12Q\n\x15termination_operation\x18\n \x01(\x0b\x32\x30.temporal.api.batch.v1.BatchOperationTerminationH\x00\x12G\n\x10signal_operation\x18\x0b \x01(\x0b\x32+.temporal.api.batch.v1.BatchOperationSignalH\x00\x12S\n\x16\x63\x61ncellation_operation\x18\x0c \x01(\x0b\x32\x31.temporal.api.batch.v1.BatchOperationCancellationH\x00\x12K\n\x12\x64\x65letion_operation\x18\r \x01(\x0b\x32-.temporal.api.batch.v1.BatchOperationDeletionH\x00\x12\x45\n\x0freset_operation\x18\x0e \x01(\x0b\x32*.temporal.api.batch.v1.BatchOperationResetH\x00\x12p\n!update_workflow_options_operation\x18\x0f \x01(\x0b\x32\x43.temporal.api.batch.v1.BatchOperationUpdateWorkflowExecutionOptionsH\x00\x12^\n\x1cunpause_activities_operation\x18\x10 \x01(\x0b\x32\x36.temporal.api.batch.v1.BatchOperationUnpauseActivitiesH\x00\x12Z\n\x1areset_activities_operation\x18\x11 \x01(\x0b\x32\x34.temporal.api.batch.v1.BatchOperationResetActivitiesH\x00\x12g\n!update_activity_options_operation\x18\x12 \x01(\x0b\x32:.temporal.api.batch.v1.BatchOperationUpdateActivityOptionsH\x00\x42\x0b\n\toperation"\x1d\n\x1bStartBatchOperationResponse"`\n\x19StopBatchOperationRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x0e\n\x06job_id\x18\x02 \x01(\t\x12\x0e\n\x06reason\x18\x03 \x01(\t\x12\x10\n\x08identity\x18\x04 \x01(\t"\x1c\n\x1aStopBatchOperationResponse"B\n\x1d\x44\x65scribeBatchOperationRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x0e\n\x06job_id\x18\x02 \x01(\t"\x92\x03\n\x1e\x44\x65scribeBatchOperationResponse\x12\x41\n\x0eoperation_type\x18\x01 \x01(\x0e\x32).temporal.api.enums.v1.BatchOperationType\x12\x0e\n\x06job_id\x18\x02 \x01(\t\x12\x39\n\x05state\x18\x03 \x01(\x0e\x32*.temporal.api.enums.v1.BatchOperationState\x12.\n\nstart_time\x18\x04 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12.\n\nclose_time\x18\x05 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x1d\n\x15total_operation_count\x18\x06 \x01(\x03\x12 \n\x18\x63omplete_operation_count\x18\x07 \x01(\x03\x12\x1f\n\x17\x66\x61ilure_operation_count\x18\x08 \x01(\x03\x12\x10\n\x08identity\x18\t \x01(\t\x12\x0e\n\x06reason\x18\n \x01(\t"[\n\x1aListBatchOperationsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x11\n\tpage_size\x18\x02 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c"y\n\x1bListBatchOperationsResponse\x12\x41\n\x0eoperation_info\x18\x01 \x03(\x0b\x32).temporal.api.batch.v1.BatchOperationInfo\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c"\xb9\x01\n"PollWorkflowExecutionUpdateRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x35\n\nupdate_ref\x18\x02 \x01(\x0b\x32!.temporal.api.update.v1.UpdateRef\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x37\n\x0bwait_policy\x18\x04 \x01(\x0b\x32".temporal.api.update.v1.WaitPolicy"\xdb\x01\n#PollWorkflowExecutionUpdateResponse\x12\x30\n\x07outcome\x18\x01 \x01(\x0b\x32\x1f.temporal.api.update.v1.Outcome\x12K\n\x05stage\x18\x02 \x01(\x0e\x32<.temporal.api.enums.v1.UpdateWorkflowExecutionLifecycleStage\x12\x35\n\nupdate_ref\x18\x03 \x01(\x0b\x32!.temporal.api.update.v1.UpdateRef"\xa0\x03\n\x19PollNexusTaskQueueRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x38\n\ntask_queue\x18\x03 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12\x17\n\x0fpoller_group_id\x18\t \x01(\t\x12\x10\n\x08identity\x18\x02 \x01(\t\x12\x1b\n\x13worker_instance_key\x18\x08 \x01(\t\x12Z\n\x1bworker_version_capabilities\x18\x04 \x01(\x0b\x32\x31.temporal.api.common.v1.WorkerVersionCapabilitiesB\x02\x18\x01\x12O\n\x12\x64\x65ployment_options\x18\x06 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentOptions\x12\x41\n\x10worker_heartbeat\x18\x07 \x03(\x0b\x32\'.temporal.api.worker.v1.WorkerHeartbeat"\x95\x02\n\x1aPollNexusTaskQueueResponse\x12\x12\n\ntask_token\x18\x01 \x01(\x0c\x12/\n\x07request\x18\x02 \x01(\x0b\x32\x1e.temporal.api.nexus.v1.Request\x12Q\n\x17poller_scaling_decision\x18\x03 \x01(\x0b\x32\x30.temporal.api.taskqueue.v1.PollerScalingDecision\x12\x17\n\x0fpoller_group_id\x18\x04 \x01(\t\x12\x46\n\x12poller_group_infos\x18\x05 \x03(\x0b\x32*.temporal.api.taskqueue.v1.PollerGroupInfo"\xa7\x01\n RespondNexusTaskCompletedRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x10\n\x08identity\x18\x02 \x01(\t\x12\x12\n\ntask_token\x18\x03 \x01(\x0c\x12\x31\n\x08response\x18\x04 \x01(\x0b\x32\x1f.temporal.api.nexus.v1.Response\x12\x17\n\x0fpoller_group_id\x18\x05 \x01(\t"#\n!RespondNexusTaskCompletedResponse"\xdc\x01\n\x1dRespondNexusTaskFailedRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x10\n\x08identity\x18\x02 \x01(\t\x12\x12\n\ntask_token\x18\x03 \x01(\x0c\x12\x36\n\x05\x65rror\x18\x04 \x01(\x0b\x32#.temporal.api.nexus.v1.HandlerErrorB\x02\x18\x01\x12\x31\n\x07\x66\x61ilure\x18\x05 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12\x17\n\x0fpoller_group_id\x18\x06 \x01(\t" \n\x1eRespondNexusTaskFailedResponse"\xf4\x02\n\x1c\x45xecuteMultiOperationRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12[\n\noperations\x18\x02 \x03(\x0b\x32G.temporal.api.workflowservice.v1.ExecuteMultiOperationRequest.Operation\x12\x13\n\x0bresource_id\x18\x03 \x01(\t\x1a\xce\x01\n\tOperation\x12X\n\x0estart_workflow\x18\x01 \x01(\x0b\x32>.temporal.api.workflowservice.v1.StartWorkflowExecutionRequestH\x00\x12Z\n\x0fupdate_workflow\x18\x02 \x01(\x0b\x32?.temporal.api.workflowservice.v1.UpdateWorkflowExecutionRequestH\x00\x42\x0b\n\toperation"\xcc\x02\n\x1d\x45xecuteMultiOperationResponse\x12Z\n\tresponses\x18\x01 \x03(\x0b\x32G.temporal.api.workflowservice.v1.ExecuteMultiOperationResponse.Response\x1a\xce\x01\n\x08Response\x12Y\n\x0estart_workflow\x18\x01 \x01(\x0b\x32?.temporal.api.workflowservice.v1.StartWorkflowExecutionResponseH\x00\x12[\n\x0fupdate_workflow\x18\x02 \x01(\x0b\x32@.temporal.api.workflowservice.v1.UpdateWorkflowExecutionResponseH\x00\x42\n\n\x08response"\xd0\x02\n\x1cUpdateActivityOptionsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12<\n\texecution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x43\n\x10\x61\x63tivity_options\x18\x04 \x01(\x0b\x32).temporal.api.activity.v1.ActivityOptions\x12/\n\x0bupdate_mask\x18\x05 \x01(\x0b\x32\x1a.google.protobuf.FieldMask\x12\x0c\n\x02id\x18\x06 \x01(\tH\x00\x12\x0e\n\x04type\x18\x07 \x01(\tH\x00\x12\x13\n\tmatch_all\x18\t \x01(\x08H\x00\x12\x18\n\x10restore_original\x18\x08 \x01(\x08\x42\n\n\x08\x61\x63tivity"\xab\x02\n%UpdateActivityExecutionOptionsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12\x13\n\x0b\x61\x63tivity_id\x18\x03 \x01(\t\x12\x0e\n\x06run_id\x18\x04 \x01(\t\x12\x10\n\x08identity\x18\x05 \x01(\t\x12\x43\n\x10\x61\x63tivity_options\x18\x06 \x01(\x0b\x32).temporal.api.activity.v1.ActivityOptions\x12/\n\x0bupdate_mask\x18\x07 \x01(\x0b\x32\x1a.google.protobuf.FieldMask\x12\x18\n\x10restore_original\x18\x08 \x01(\x08\x12\x13\n\x0bresource_id\x18\t \x01(\t"d\n\x1dUpdateActivityOptionsResponse\x12\x43\n\x10\x61\x63tivity_options\x18\x01 \x01(\x0b\x32).temporal.api.activity.v1.ActivityOptions"m\n&UpdateActivityExecutionOptionsResponse\x12\x43\n\x10\x61\x63tivity_options\x18\x01 \x01(\x0b\x32).temporal.api.activity.v1.ActivityOptions"\xc7\x01\n\x14PauseActivityRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12<\n\texecution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x0c\n\x02id\x18\x04 \x01(\tH\x00\x12\x0e\n\x04type\x18\x05 \x01(\tH\x00\x12\x0e\n\x06reason\x18\x06 \x01(\t\x12\x12\n\nrequest_id\x18\x07 \x01(\tB\n\n\x08\x61\x63tivity"\xb7\x01\n\x1dPauseActivityExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12\x13\n\x0b\x61\x63tivity_id\x18\x03 \x01(\t\x12\x0e\n\x06run_id\x18\x04 \x01(\t\x12\x10\n\x08identity\x18\x05 \x01(\t\x12\x0e\n\x06reason\x18\x06 \x01(\t\x12\x13\n\x0bresource_id\x18\x07 \x01(\t\x12\x12\n\nrequest_id\x18\x08 \x01(\t"\x17\n\x15PauseActivityResponse" \n\x1ePauseActivityExecutionResponse"\x98\x02\n\x16UnpauseActivityRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12<\n\texecution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x0c\n\x02id\x18\x04 \x01(\tH\x00\x12\x0e\n\x04type\x18\x05 \x01(\tH\x00\x12\x15\n\x0bunpause_all\x18\x06 \x01(\x08H\x00\x12\x16\n\x0ereset_attempts\x18\x07 \x01(\x08\x12\x17\n\x0freset_heartbeat\x18\x08 \x01(\x08\x12)\n\x06jitter\x18\t \x01(\x0b\x32\x19.google.protobuf.DurationB\n\n\x08\x61\x63tivity"\x81\x02\n\x1fUnpauseActivityExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12\x13\n\x0b\x61\x63tivity_id\x18\x03 \x01(\t\x12\x0e\n\x06run_id\x18\x04 \x01(\t\x12\x10\n\x08identity\x18\x05 \x01(\t\x12\x16\n\x0ereset_attempts\x18\x06 \x01(\x08\x12\x17\n\x0freset_heartbeat\x18\x07 \x01(\x08\x12\x0e\n\x06reason\x18\x08 \x01(\t\x12)\n\x06jitter\x18\t \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x13\n\x0bresource_id\x18\n \x01(\t"\x19\n\x17UnpauseActivityResponse""\n UnpauseActivityExecutionResponse"\xb3\x02\n\x14ResetActivityRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12<\n\texecution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x0c\n\x02id\x18\x04 \x01(\tH\x00\x12\x0e\n\x04type\x18\x05 \x01(\tH\x00\x12\x13\n\tmatch_all\x18\n \x01(\x08H\x00\x12\x17\n\x0freset_heartbeat\x18\x06 \x01(\x08\x12\x13\n\x0bkeep_paused\x18\x07 \x01(\x08\x12)\n\x06jitter\x18\x08 \x01(\x0b\x32\x19.google.protobuf.Duration\x12 \n\x18restore_original_options\x18\t \x01(\x08\x42\n\n\x08\x61\x63tivity"\x8e\x02\n\x1dResetActivityExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12\x13\n\x0b\x61\x63tivity_id\x18\x03 \x01(\t\x12\x0e\n\x06run_id\x18\x04 \x01(\t\x12\x10\n\x08identity\x18\x05 \x01(\t\x12\x17\n\x0freset_heartbeat\x18\x06 \x01(\x08\x12\x13\n\x0bkeep_paused\x18\x07 \x01(\x08\x12)\n\x06jitter\x18\x08 \x01(\x0b\x32\x19.google.protobuf.Duration\x12 \n\x18restore_original_options\x18\t \x01(\x08\x12\x13\n\x0bresource_id\x18\n \x01(\t"\x17\n\x15ResetActivityResponse" \n\x1eResetActivityExecutionResponse"\x9c\x02\n%UpdateWorkflowExecutionOptionsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x45\n\x12workflow_execution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12V\n\x1aworkflow_execution_options\x18\x03 \x01(\x0b\x32\x32.temporal.api.workflow.v1.WorkflowExecutionOptions\x12/\n\x0bupdate_mask\x18\x04 \x01(\x0b\x32\x1a.google.protobuf.FieldMask\x12\x10\n\x08identity\x18\x05 \x01(\t"\x80\x01\n&UpdateWorkflowExecutionOptionsResponse\x12V\n\x1aworkflow_execution_options\x18\x01 \x01(\x0b\x32\x32.temporal.api.workflow.v1.WorkflowExecutionOptions"j\n\x19\x44\x65scribeDeploymentRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12:\n\ndeployment\x18\x02 \x01(\x0b\x32&.temporal.api.deployment.v1.Deployment"a\n\x1a\x44\x65scribeDeploymentResponse\x12\x43\n\x0f\x64\x65ployment_info\x18\x01 \x01(\x0b\x32*.temporal.api.deployment.v1.DeploymentInfo"\xc2\x01\n&DescribeWorkerDeploymentVersionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x07version\x18\x02 \x01(\tB\x02\x18\x01\x12O\n\x12\x64\x65ployment_version\x18\x03 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersion\x12\x1f\n\x17report_task_queue_stats\x18\x04 \x01(\x08"\x8c\x05\n\'DescribeWorkerDeploymentVersionResponse\x12_\n\x1eworker_deployment_version_info\x18\x01 \x01(\x0b\x32\x37.temporal.api.deployment.v1.WorkerDeploymentVersionInfo\x12v\n\x13version_task_queues\x18\x02 \x03(\x0b\x32Y.temporal.api.workflowservice.v1.DescribeWorkerDeploymentVersionResponse.VersionTaskQueue\x1a\x87\x03\n\x10VersionTaskQueue\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x32\n\x04type\x18\x02 \x01(\x0e\x32$.temporal.api.enums.v1.TaskQueueType\x12\x38\n\x05stats\x18\x03 \x01(\x0b\x32).temporal.api.taskqueue.v1.TaskQueueStats\x12\x90\x01\n\x15stats_by_priority_key\x18\x04 \x03(\x0b\x32q.temporal.api.workflowservice.v1.DescribeWorkerDeploymentVersionResponse.VersionTaskQueue.StatsByPriorityKeyEntry\x1a\x64\n\x17StatsByPriorityKeyEntry\x12\x0b\n\x03key\x18\x01 \x01(\x05\x12\x38\n\x05value\x18\x02 \x01(\x0b\x32).temporal.api.taskqueue.v1.TaskQueueStats:\x02\x38\x01"M\n\x1f\x44\x65scribeWorkerDeploymentRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x17\n\x0f\x64\x65ployment_name\x18\x02 \x01(\t"\x8c\x01\n DescribeWorkerDeploymentResponse\x12\x16\n\x0e\x63onflict_token\x18\x01 \x01(\x0c\x12P\n\x16worker_deployment_info\x18\x02 \x01(\x0b\x32\x30.temporal.api.deployment.v1.WorkerDeploymentInfo"l\n\x16ListDeploymentsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x11\n\tpage_size\x18\x02 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c\x12\x13\n\x0bseries_name\x18\x04 \x01(\t"w\n\x17ListDeploymentsResponse\x12\x17\n\x0fnext_page_token\x18\x01 \x01(\x0c\x12\x43\n\x0b\x64\x65ployments\x18\x02 \x03(\x0b\x32..temporal.api.deployment.v1.DeploymentListInfo"\xcd\x01\n\x1bSetCurrentDeploymentRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12:\n\ndeployment\x18\x02 \x01(\x0b\x32&.temporal.api.deployment.v1.Deployment\x12\x10\n\x08identity\x18\x03 \x01(\t\x12M\n\x0fupdate_metadata\x18\x04 \x01(\x0b\x32\x34.temporal.api.deployment.v1.UpdateDeploymentMetadata"\xb9\x01\n\x1cSetCurrentDeploymentResponse\x12K\n\x17\x63urrent_deployment_info\x18\x01 \x01(\x0b\x32*.temporal.api.deployment.v1.DeploymentInfo\x12L\n\x18previous_deployment_info\x18\x02 \x01(\x0b\x32*.temporal.api.deployment.v1.DeploymentInfo"\xe5\x01\n(SetWorkerDeploymentCurrentVersionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x17\n\x0f\x64\x65ployment_name\x18\x02 \x01(\t\x12\x13\n\x07version\x18\x03 \x01(\tB\x02\x18\x01\x12\x10\n\x08\x62uild_id\x18\x07 \x01(\t\x12\x16\n\x0e\x63onflict_token\x18\x04 \x01(\x0c\x12\x10\n\x08identity\x18\x05 \x01(\t\x12"\n\x1aignore_missing_task_queues\x18\x06 \x01(\x08\x12\x18\n\x10\x61llow_no_pollers\x18\t \x01(\x08"\xbf\x01\n)SetWorkerDeploymentCurrentVersionResponse\x12\x16\n\x0e\x63onflict_token\x18\x01 \x01(\x0c\x12\x1c\n\x10previous_version\x18\x02 \x01(\tB\x02\x18\x01\x12\\\n\x1bprevious_deployment_version\x18\x03 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersionB\x02\x18\x01"\xf9\x01\n(SetWorkerDeploymentRampingVersionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x17\n\x0f\x64\x65ployment_name\x18\x02 \x01(\t\x12\x13\n\x07version\x18\x03 \x01(\tB\x02\x18\x01\x12\x10\n\x08\x62uild_id\x18\x08 \x01(\t\x12\x12\n\npercentage\x18\x04 \x01(\x02\x12\x16\n\x0e\x63onflict_token\x18\x05 \x01(\x0c\x12\x10\n\x08identity\x18\x06 \x01(\t\x12"\n\x1aignore_missing_task_queues\x18\x07 \x01(\x08\x12\x18\n\x10\x61llow_no_pollers\x18\n \x01(\x08"\xe0\x01\n)SetWorkerDeploymentRampingVersionResponse\x12\x16\n\x0e\x63onflict_token\x18\x01 \x01(\x0c\x12\x1c\n\x10previous_version\x18\x02 \x01(\tB\x02\x18\x01\x12\\\n\x1bprevious_deployment_version\x18\x04 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersionB\x02\x18\x01\x12\x1f\n\x13previous_percentage\x18\x03 \x01(\x02\x42\x02\x18\x01"q\n\x1d\x43reateWorkerDeploymentRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x17\n\x0f\x64\x65ployment_name\x18\x02 \x01(\t\x12\x10\n\x08identity\x18\x04 \x01(\t\x12\x12\n\nrequest_id\x18\x05 \x01(\t"8\n\x1e\x43reateWorkerDeploymentResponse\x12\x16\n\x0e\x63onflict_token\x18\x01 \x01(\x0c"]\n\x1cListWorkerDeploymentsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x11\n\tpage_size\x18\x02 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c"\x9f\x05\n\x1dListWorkerDeploymentsResponse\x12\x17\n\x0fnext_page_token\x18\x01 \x01(\x0c\x12r\n\x12worker_deployments\x18\x02 \x03(\x0b\x32V.temporal.api.workflowservice.v1.ListWorkerDeploymentsResponse.WorkerDeploymentSummary\x1a\xf0\x03\n\x17WorkerDeploymentSummary\x12\x0c\n\x04name\x18\x01 \x01(\t\x12/\n\x0b\x63reate_time\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x41\n\x0erouting_config\x18\x03 \x01(\x0b\x32).temporal.api.deployment.v1.RoutingConfig\x12o\n\x16latest_version_summary\x18\x04 \x01(\x0b\x32O.temporal.api.deployment.v1.WorkerDeploymentInfo.WorkerDeploymentVersionSummary\x12p\n\x17\x63urrent_version_summary\x18\x05 \x01(\x0b\x32O.temporal.api.deployment.v1.WorkerDeploymentInfo.WorkerDeploymentVersionSummary\x12p\n\x17ramping_version_summary\x18\x06 \x01(\x0b\x32O.temporal.api.deployment.v1.WorkerDeploymentInfo.WorkerDeploymentVersionSummary"\xf0\x01\n$CreateWorkerDeploymentVersionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12O\n\x12\x64\x65ployment_version\x18\x02 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersion\x12>\n\x0e\x63ompute_config\x18\x04 \x01(\x0b\x32&.temporal.api.compute.v1.ComputeConfig\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x12\n\nrequest_id\x18\x05 \x01(\t"\'\n%CreateWorkerDeploymentVersionResponse"\xc8\x01\n$DeleteWorkerDeploymentVersionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x07version\x18\x02 \x01(\tB\x02\x18\x01\x12O\n\x12\x64\x65ployment_version\x18\x05 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersion\x12\x15\n\rskip_drainage\x18\x03 \x01(\x08\x12\x10\n\x08identity\x18\x04 \x01(\t"\'\n%DeleteWorkerDeploymentVersionResponse"]\n\x1d\x44\x65leteWorkerDeploymentRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x17\n\x0f\x64\x65ployment_name\x18\x02 \x01(\t\x12\x10\n\x08identity\x18\x03 \x01(\t" \n\x1e\x44\x65leteWorkerDeploymentResponse"\x84\x04\n1UpdateWorkerDeploymentVersionComputeConfigRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12O\n\x12\x64\x65ployment_version\x18\x02 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersion\x12\x99\x01\n\x1d\x63ompute_config_scaling_groups\x18\x06 \x03(\x0b\x32r.temporal.api.workflowservice.v1.UpdateWorkerDeploymentVersionComputeConfigRequest.ComputeConfigScalingGroupsEntry\x12,\n$remove_compute_config_scaling_groups\x18\x07 \x03(\t\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x12\n\nrequest_id\x18\x04 \x01(\t\x1a{\n\x1f\x43omputeConfigScalingGroupsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12G\n\x05value\x18\x02 \x01(\x0b\x32\x38.temporal.api.compute.v1.ComputeConfigScalingGroupUpdate:\x02\x38\x01"4\n2UpdateWorkerDeploymentVersionComputeConfigResponse"\xf4\x03\n3ValidateWorkerDeploymentVersionComputeConfigRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12O\n\x12\x64\x65ployment_version\x18\x02 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersion\x12\x9b\x01\n\x1d\x63ompute_config_scaling_groups\x18\x06 \x03(\x0b\x32t.temporal.api.workflowservice.v1.ValidateWorkerDeploymentVersionComputeConfigRequest.ComputeConfigScalingGroupsEntry\x12,\n$remove_compute_config_scaling_groups\x18\x07 \x03(\t\x12\x10\n\x08identity\x18\x03 \x01(\t\x1a{\n\x1f\x43omputeConfigScalingGroupsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12G\n\x05value\x18\x02 \x01(\x0b\x32\x38.temporal.api.compute.v1.ComputeConfigScalingGroupUpdate:\x02\x38\x01"6\n4ValidateWorkerDeploymentVersionComputeConfigResponse"\xa2\x03\n,UpdateWorkerDeploymentVersionMetadataRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x07version\x18\x02 \x01(\tB\x02\x18\x01\x12O\n\x12\x64\x65ployment_version\x18\x05 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersion\x12x\n\x0eupsert_entries\x18\x03 \x03(\x0b\x32`.temporal.api.workflowservice.v1.UpdateWorkerDeploymentVersionMetadataRequest.UpsertEntriesEntry\x12\x16\n\x0eremove_entries\x18\x04 \x03(\t\x12\x10\n\x08identity\x18\x06 \x01(\t\x1aU\n\x12UpsertEntriesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12.\n\x05value\x18\x02 \x01(\x0b\x32\x1f.temporal.api.common.v1.Payload:\x02\x38\x01"n\n-UpdateWorkerDeploymentVersionMetadataResponse\x12=\n\x08metadata\x18\x01 \x01(\x0b\x32+.temporal.api.deployment.v1.VersionMetadata"\xbd\x01\n!SetWorkerDeploymentManagerRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x17\n\x0f\x64\x65ployment_name\x18\x02 \x01(\t\x12\x1a\n\x10manager_identity\x18\x03 \x01(\tH\x00\x12\x0e\n\x04self\x18\x04 \x01(\x08H\x00\x12\x16\n\x0e\x63onflict_token\x18\x05 \x01(\x0c\x12\x10\n\x08identity\x18\x06 \x01(\tB\x16\n\x14new_manager_identity"c\n"SetWorkerDeploymentManagerResponse\x12\x16\n\x0e\x63onflict_token\x18\x01 \x01(\x0c\x12%\n\x19previous_manager_identity\x18\x02 \x01(\tB\x02\x18\x01"E\n\x1bGetCurrentDeploymentRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bseries_name\x18\x02 \x01(\t"k\n\x1cGetCurrentDeploymentResponse\x12K\n\x17\x63urrent_deployment_info\x18\x01 \x01(\x0b\x32*.temporal.api.deployment.v1.DeploymentInfo"q\n GetDeploymentReachabilityRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12:\n\ndeployment\x18\x02 \x01(\x0b\x32&.temporal.api.deployment.v1.Deployment"\xe3\x01\n!GetDeploymentReachabilityResponse\x12\x43\n\x0f\x64\x65ployment_info\x18\x01 \x01(\x0b\x32*.temporal.api.deployment.v1.DeploymentInfo\x12\x43\n\x0creachability\x18\x02 \x01(\x0e\x32-.temporal.api.enums.v1.DeploymentReachability\x12\x34\n\x10last_update_time\x18\x03 \x01(\x0b\x32\x1a.google.protobuf.Timestamp"\xb4\x01\n\x19\x43reateWorkflowRuleRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x35\n\x04spec\x18\x02 \x01(\x0b\x32\'.temporal.api.rules.v1.WorkflowRuleSpec\x12\x12\n\nforce_scan\x18\x03 \x01(\x08\x12\x12\n\nrequest_id\x18\x04 \x01(\t\x12\x10\n\x08identity\x18\x05 \x01(\t\x12\x13\n\x0b\x64\x65scription\x18\x06 \x01(\t"_\n\x1a\x43reateWorkflowRuleResponse\x12\x31\n\x04rule\x18\x01 \x01(\x0b\x32#.temporal.api.rules.v1.WorkflowRule\x12\x0e\n\x06job_id\x18\x02 \x01(\t"A\n\x1b\x44\x65scribeWorkflowRuleRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x0f\n\x07rule_id\x18\x02 \x01(\t"Q\n\x1c\x44\x65scribeWorkflowRuleResponse\x12\x31\n\x04rule\x18\x01 \x01(\x0b\x32#.temporal.api.rules.v1.WorkflowRule"?\n\x19\x44\x65leteWorkflowRuleRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x0f\n\x07rule_id\x18\x02 \x01(\t"\x1c\n\x1a\x44\x65leteWorkflowRuleResponse"F\n\x18ListWorkflowRulesRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c"h\n\x19ListWorkflowRulesResponse\x12\x32\n\x05rules\x18\x01 \x03(\x0b\x32#.temporal.api.rules.v1.WorkflowRule\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c"\xce\x01\n\x1aTriggerWorkflowRuleRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12<\n\texecution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x0c\n\x02id\x18\x04 \x01(\tH\x00\x12\x37\n\x04spec\x18\x05 \x01(\x0b\x32\'.temporal.api.rules.v1.WorkflowRuleSpecH\x00\x12\x10\n\x08identity\x18\x03 \x01(\tB\x06\n\x04rule".\n\x1bTriggerWorkflowRuleResponse\x12\x0f\n\x07\x61pplied\x18\x01 \x01(\x08"\x9b\x01\n\x1cRecordWorkerHeartbeatRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x10\n\x08identity\x18\x02 \x01(\t\x12\x41\n\x10worker_heartbeat\x18\x03 \x03(\x0b\x32\'.temporal.api.worker.v1.WorkerHeartbeat\x12\x13\n\x0bresource_id\x18\x04 \x01(\t"\x1f\n\x1dRecordWorkerHeartbeatResponse"\x82\x01\n\x12ListWorkersRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x11\n\tpage_size\x18\x02 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c\x12\r\n\x05query\x18\x04 \x01(\t\x12\x1e\n\x16include_system_workers\x18\x05 \x01(\x08"\xa5\x01\n\x13ListWorkersResponse\x12<\n\x0cworkers_info\x18\x01 \x03(\x0b\x32".temporal.api.worker.v1.WorkerInfoB\x02\x18\x01\x12\x37\n\x07workers\x18\x03 \x03(\x0b\x32&.temporal.api.worker.v1.WorkerListInfo\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c"\xd5\x05\n\x1cUpdateTaskQueueConfigRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x10\n\x08identity\x18\x02 \x01(\t\x12\x12\n\ntask_queue\x18\x03 \x01(\t\x12=\n\x0ftask_queue_type\x18\x04 \x01(\x0e\x32$.temporal.api.enums.v1.TaskQueueType\x12n\n\x17update_queue_rate_limit\x18\x05 \x01(\x0b\x32M.temporal.api.workflowservice.v1.UpdateTaskQueueConfigRequest.RateLimitUpdate\x12}\n&update_fairness_key_rate_limit_default\x18\x06 \x01(\x0b\x32M.temporal.api.workflowservice.v1.UpdateTaskQueueConfigRequest.RateLimitUpdate\x12\x84\x01\n\x1dset_fairness_weight_overrides\x18\x07 \x03(\x0b\x32].temporal.api.workflowservice.v1.UpdateTaskQueueConfigRequest.SetFairnessWeightOverridesEntry\x12\'\n\x1funset_fairness_weight_overrides\x18\x08 \x03(\t\x1a[\n\x0fRateLimitUpdate\x12\x38\n\nrate_limit\x18\x01 \x01(\x0b\x32$.temporal.api.taskqueue.v1.RateLimit\x12\x0e\n\x06reason\x18\x02 \x01(\t\x1a\x41\n\x1fSetFairnessWeightOverridesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\x02:\x02\x38\x01"[\n\x1dUpdateTaskQueueConfigResponse\x12:\n\x06\x63onfig\x18\x01 \x01(\x0b\x32*.temporal.api.taskqueue.v1.TaskQueueConfig"\x9e\x01\n\x18\x46\x65tchWorkerConfigRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x10\n\x08identity\x18\x02 \x01(\t\x12\x0e\n\x06reason\x18\x03 \x01(\t\x12\x38\n\x08selector\x18\x06 \x01(\x0b\x32&.temporal.api.common.v1.WorkerSelector\x12\x13\n\x0bresource_id\x18\x07 \x01(\t"U\n\x19\x46\x65tchWorkerConfigResponse\x12\x38\n\rworker_config\x18\x01 \x01(\x0b\x32!.temporal.api.sdk.v1.WorkerConfig"\x8a\x02\n\x19UpdateWorkerConfigRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x10\n\x08identity\x18\x02 \x01(\t\x12\x0e\n\x06reason\x18\x03 \x01(\t\x12\x38\n\rworker_config\x18\x04 \x01(\x0b\x32!.temporal.api.sdk.v1.WorkerConfig\x12/\n\x0bupdate_mask\x18\x05 \x01(\x0b\x32\x1a.google.protobuf.FieldMask\x12\x38\n\x08selector\x18\x06 \x01(\x0b\x32&.temporal.api.common.v1.WorkerSelector\x12\x13\n\x0bresource_id\x18\x07 \x01(\t"d\n\x1aUpdateWorkerConfigResponse\x12:\n\rworker_config\x18\x01 \x01(\x0b\x32!.temporal.api.sdk.v1.WorkerConfigH\x00\x42\n\n\x08response"G\n\x15\x44\x65scribeWorkerRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x1b\n\x13worker_instance_key\x18\x02 \x01(\t"Q\n\x16\x44\x65scribeWorkerResponse\x12\x37\n\x0bworker_info\x18\x01 \x01(\x0b\x32".temporal.api.worker.v1.WorkerInfo"\x8d\x01\n\x1dPauseWorkflowExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x12\x10\n\x08identity\x18\x04 \x01(\t\x12\x0e\n\x06reason\x18\x05 \x01(\t\x12\x12\n\nrequest_id\x18\x06 \x01(\t" \n\x1ePauseWorkflowExecutionResponse"\x8f\x01\n\x1fUnpauseWorkflowExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x12\x10\n\x08identity\x18\x04 \x01(\t\x12\x0e\n\x06reason\x18\x05 \x01(\t\x12\x12\n\nrequest_id\x18\x06 \x01(\t""\n UnpauseWorkflowExecutionResponse"\x99\t\n\x1dStartActivityExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x10\n\x08identity\x18\x02 \x01(\t\x12\x12\n\nrequest_id\x18\x03 \x01(\t\x12\x13\n\x0b\x61\x63tivity_id\x18\x04 \x01(\t\x12;\n\ractivity_type\x18\x05 \x01(\x0b\x32$.temporal.api.common.v1.ActivityType\x12\x38\n\ntask_queue\x18\x06 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12<\n\x19schedule_to_close_timeout\x18\x07 \x01(\x0b\x32\x19.google.protobuf.Duration\x12<\n\x19schedule_to_start_timeout\x18\x08 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x39\n\x16start_to_close_timeout\x18\t \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x34\n\x11heartbeat_timeout\x18\n \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x39\n\x0cretry_policy\x18\x0b \x01(\x0b\x32#.temporal.api.common.v1.RetryPolicy\x12/\n\x05input\x18\x0c \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x45\n\x0fid_reuse_policy\x18\r \x01(\x0e\x32,.temporal.api.enums.v1.ActivityIdReusePolicy\x12K\n\x12id_conflict_policy\x18\x0e \x01(\x0e\x32/.temporal.api.enums.v1.ActivityIdConflictPolicy\x12\x43\n\x11search_attributes\x18\x0f \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes\x12.\n\x06header\x18\x10 \x01(\x0b\x32\x1e.temporal.api.common.v1.Header\x12\x38\n\ruser_metadata\x18\x11 \x01(\x0b\x32!.temporal.api.sdk.v1.UserMetadata\x12\x32\n\x08priority\x18\x12 \x01(\x0b\x32 .temporal.api.common.v1.Priority\x12>\n\x14\x63ompletion_callbacks\x18\x13 \x03(\x0b\x32 .temporal.api.common.v1.Callback\x12+\n\x05links\x18\x14 \x03(\x0b\x32\x1c.temporal.api.common.v1.Link\x12\x46\n\x13on_conflict_options\x18\x15 \x01(\x0b\x32).temporal.api.common.v1.OnConflictOptions\x12.\n\x0bstart_delay\x18\x16 \x01(\x0b\x32\x19.google.protobuf.Duration"m\n\x1eStartActivityExecutionResponse\x12\x0e\n\x06run_id\x18\x01 \x01(\t\x12\x0f\n\x07started\x18\x02 \x01(\x08\x12*\n\x04link\x18\x03 \x01(\x0b\x32\x1c.temporal.api.common.v1.Link"\xa3\x01\n DescribeActivityExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0b\x61\x63tivity_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x12\x15\n\rinclude_input\x18\x04 \x01(\x08\x12\x17\n\x0finclude_outcome\x18\x05 \x01(\x08\x12\x17\n\x0flong_poll_token\x18\x06 \x01(\x0c"\xbc\x02\n!DescribeActivityExecutionResponse\x12\x0e\n\x06run_id\x18\x01 \x01(\t\x12=\n\x04info\x18\x02 \x01(\x0b\x32/.temporal.api.activity.v1.ActivityExecutionInfo\x12/\n\x05input\x18\x03 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x43\n\x07outcome\x18\x04 \x01(\x0b\x32\x32.temporal.api.activity.v1.ActivityExecutionOutcome\x12\x17\n\x0flong_poll_token\x18\x05 \x01(\x0c\x12\x39\n\tcallbacks\x18\x06 \x03(\x0b\x32&.temporal.api.activity.v1.CallbackInfo"V\n\x1cPollActivityExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0b\x61\x63tivity_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t"t\n\x1dPollActivityExecutionResponse\x12\x0e\n\x06run_id\x18\x01 \x01(\t\x12\x43\n\x07outcome\x18\x02 \x01(\x0b\x32\x32.temporal.api.activity.v1.ActivityExecutionOutcome"m\n\x1dListActivityExecutionsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x11\n\tpage_size\x18\x02 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c\x12\r\n\x05query\x18\x04 \x01(\t"\x82\x01\n\x1eListActivityExecutionsResponse\x12G\n\nexecutions\x18\x01 \x03(\x0b\x32\x33.temporal.api.activity.v1.ActivityExecutionListInfo\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c"\xd1\x06\n#StartNexusOperationExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x10\n\x08identity\x18\x02 \x01(\t\x12\x12\n\nrequest_id\x18\x03 \x01(\t\x12\x14\n\x0coperation_id\x18\x04 \x01(\t\x12\x10\n\x08\x65ndpoint\x18\x05 \x01(\t\x12\x0f\n\x07service\x18\x06 \x01(\t\x12\x11\n\toperation\x18\x07 \x01(\t\x12<\n\x19schedule_to_close_timeout\x18\x08 \x01(\x0b\x32\x19.google.protobuf.Duration\x12<\n\x19schedule_to_start_timeout\x18\t \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x39\n\x16start_to_close_timeout\x18\n \x01(\x0b\x32\x19.google.protobuf.Duration\x12.\n\x05input\x18\x0b \x01(\x0b\x32\x1f.temporal.api.common.v1.Payload\x12K\n\x0fid_reuse_policy\x18\x0c \x01(\x0e\x32\x32.temporal.api.enums.v1.NexusOperationIdReusePolicy\x12Q\n\x12id_conflict_policy\x18\r \x01(\x0e\x32\x35.temporal.api.enums.v1.NexusOperationIdConflictPolicy\x12\x43\n\x11search_attributes\x18\x0e \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes\x12k\n\x0cnexus_header\x18\x0f \x03(\x0b\x32U.temporal.api.workflowservice.v1.StartNexusOperationExecutionRequest.NexusHeaderEntry\x12\x38\n\ruser_metadata\x18\x10 \x01(\x0b\x32!.temporal.api.sdk.v1.UserMetadata\x1a\x32\n\x10NexusHeaderEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01"G\n$StartNexusOperationExecutionResponse\x12\x0e\n\x06run_id\x18\x01 \x01(\t\x12\x0f\n\x07started\x18\x02 \x01(\x08"\xaa\x01\n&DescribeNexusOperationExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x14\n\x0coperation_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x12\x15\n\rinclude_input\x18\x04 \x01(\x08\x12\x17\n\x0finclude_outcome\x18\x05 \x01(\x08\x12\x17\n\x0flong_poll_token\x18\x06 \x01(\x0c"\xb7\x02\n\'DescribeNexusOperationExecutionResponse\x12\x0e\n\x06run_id\x18\x01 \x01(\t\x12@\n\x04info\x18\x02 \x01(\x0b\x32\x32.temporal.api.nexus.v1.NexusOperationExecutionInfo\x12.\n\x05input\x18\x03 \x01(\x0b\x32\x1f.temporal.api.common.v1.Payload\x12\x31\n\x06result\x18\x04 \x01(\x0b\x32\x1f.temporal.api.common.v1.PayloadH\x00\x12\x33\n\x07\x66\x61ilure\x18\x05 \x01(\x0b\x32 .temporal.api.failure.v1.FailureH\x00\x12\x17\n\x0flong_poll_token\x18\x06 \x01(\x0c\x42\t\n\x07outcome"\xa1\x01\n"PollNexusOperationExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x14\n\x0coperation_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x12\x42\n\nwait_stage\x18\x04 \x01(\x0e\x32..temporal.api.enums.v1.NexusOperationWaitStage"\x85\x02\n#PollNexusOperationExecutionResponse\x12\x0e\n\x06run_id\x18\x01 \x01(\t\x12\x42\n\nwait_stage\x18\x02 \x01(\x0e\x32..temporal.api.enums.v1.NexusOperationWaitStage\x12\x17\n\x0foperation_token\x18\x03 \x01(\t\x12\x31\n\x06result\x18\x04 \x01(\x0b\x32\x1f.temporal.api.common.v1.PayloadH\x00\x12\x33\n\x07\x66\x61ilure\x18\x05 \x01(\x0b\x32 .temporal.api.failure.v1.FailureH\x00\x42\t\n\x07outcome"s\n#ListNexusOperationExecutionsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x11\n\tpage_size\x18\x02 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c\x12\r\n\x05query\x18\x04 \x01(\t"\x8b\x01\n$ListNexusOperationExecutionsResponse\x12J\n\noperations\x18\x01 \x03(\x0b\x32\x36.temporal.api.nexus.v1.NexusOperationExecutionListInfo\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c"B\n\x1e\x43ountActivityExecutionsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\r\n\x05query\x18\x02 \x01(\t"\xed\x01\n\x1f\x43ountActivityExecutionsResponse\x12\r\n\x05\x63ount\x18\x01 \x01(\x03\x12\x61\n\x06groups\x18\x02 \x03(\x0b\x32Q.temporal.api.workflowservice.v1.CountActivityExecutionsResponse.AggregationGroup\x1aX\n\x10\x41ggregationGroup\x12\x35\n\x0cgroup_values\x18\x01 \x03(\x0b\x32\x1f.temporal.api.common.v1.Payload\x12\r\n\x05\x63ount\x18\x02 \x01(\x03"H\n$CountNexusOperationExecutionsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\r\n\x05query\x18\x02 \x01(\t"\xf9\x01\n%CountNexusOperationExecutionsResponse\x12\r\n\x05\x63ount\x18\x01 \x01(\x03\x12g\n\x06groups\x18\x02 \x03(\x0b\x32W.temporal.api.workflowservice.v1.CountNexusOperationExecutionsResponse.AggregationGroup\x1aX\n\x10\x41ggregationGroup\x12\x35\n\x0cgroup_values\x18\x01 \x03(\x0b\x32\x1f.temporal.api.common.v1.Payload\x12\r\n\x05\x63ount\x18\x02 \x01(\x03"\x95\x01\n%RequestCancelActivityExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0b\x61\x63tivity_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x12\x10\n\x08identity\x18\x04 \x01(\t\x12\x12\n\nrequest_id\x18\x05 \x01(\t\x12\x0e\n\x06reason\x18\x06 \x01(\t"(\n&RequestCancelActivityExecutionResponse"\x91\x01\n!TerminateActivityExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0b\x61\x63tivity_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x12\x10\n\x08identity\x18\x04 \x01(\t\x12\x12\n\nrequest_id\x18\x05 \x01(\t\x12\x0e\n\x06reason\x18\x06 \x01(\t"$\n"TerminateActivityExecutionResponse"X\n\x1e\x44\x65leteActivityExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0b\x61\x63tivity_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t"!\n\x1f\x44\x65leteActivityExecutionResponse"\x9c\x01\n+RequestCancelNexusOperationExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x14\n\x0coperation_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x12\x10\n\x08identity\x18\x04 \x01(\t\x12\x12\n\nrequest_id\x18\x05 \x01(\t\x12\x0e\n\x06reason\x18\x06 \x01(\t".\n,RequestCancelNexusOperationExecutionResponse"\x98\x01\n\'TerminateNexusOperationExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x14\n\x0coperation_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x12\x10\n\x08identity\x18\x04 \x01(\t\x12\x12\n\nrequest_id\x18\x05 \x01(\t\x12\x0e\n\x06reason\x18\x06 \x01(\t"*\n(TerminateNexusOperationExecutionResponse"_\n$DeleteNexusOperationExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x14\n\x0coperation_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t"\'\n%DeleteNexusOperationExecutionResponseB\xbe\x01\n"io.temporal.api.workflowservice.v1B\x14RequestResponseProtoP\x01Z5go.temporal.io/api/workflowservice/v1;workflowservice\xaa\x02!Temporalio.Api.WorkflowService.V1\xea\x02$Temporalio::Api::WorkflowService::V1b\x06proto3' + b'\n6temporal/api/workflowservice/v1/request_response.proto\x12\x1ftemporal.api.workflowservice.v1\x1a+temporal/api/enums/v1/batch_operation.proto\x1a"temporal/api/enums/v1/common.proto\x1a$temporal/api/enums/v1/workflow.proto\x1a%temporal/api/enums/v1/namespace.proto\x1a(temporal/api/enums/v1/failed_cause.proto\x1a!temporal/api/enums/v1/query.proto\x1a!temporal/api/enums/v1/reset.proto\x1a&temporal/api/enums/v1/task_queue.proto\x1a&temporal/api/enums/v1/deployment.proto\x1a"temporal/api/enums/v1/update.proto\x1a$temporal/api/enums/v1/activity.proto\x1a!temporal/api/enums/v1/nexus.proto\x1a&temporal/api/activity/v1/message.proto\x1a$temporal/api/common/v1/message.proto\x1a%temporal/api/history/v1/message.proto\x1a&temporal/api/workflow/v1/message.proto\x1a%temporal/api/command/v1/message.proto\x1a$temporal/api/compute/v1/config.proto\x1a(temporal/api/deployment/v1/message.proto\x1a%temporal/api/failure/v1/message.proto\x1a$temporal/api/filter/v1/message.proto\x1a&temporal/api/protocol/v1/message.proto\x1a\'temporal/api/namespace/v1/message.proto\x1a#temporal/api/query/v1/message.proto\x1a)temporal/api/replication/v1/message.proto\x1a#temporal/api/rules/v1/message.proto\x1a\'temporal/api/sdk/v1/worker_config.proto\x1a&temporal/api/schedule/v1/message.proto\x1a\'temporal/api/taskqueue/v1/message.proto\x1a$temporal/api/update/v1/message.proto\x1a%temporal/api/version/v1/message.proto\x1a#temporal/api/batch/v1/message.proto\x1a\x30temporal/api/sdk/v1/task_complete_metadata.proto\x1a\'temporal/api/sdk/v1/user_metadata.proto\x1a#temporal/api/nexus/v1/message.proto\x1a$temporal/api/worker/v1/message.proto\x1a\x1egoogle/protobuf/duration.proto\x1a google/protobuf/field_mask.proto\x1a\x1fgoogle/protobuf/timestamp.proto"\x88\x05\n\x18RegisterNamespaceRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0b\x64\x65scription\x18\x02 \x01(\t\x12\x13\n\x0bowner_email\x18\x03 \x01(\t\x12\x46\n#workflow_execution_retention_period\x18\x04 \x01(\x0b\x32\x19.google.protobuf.Duration\x12G\n\x08\x63lusters\x18\x05 \x03(\x0b\x32\x35.temporal.api.replication.v1.ClusterReplicationConfig\x12\x1b\n\x13\x61\x63tive_cluster_name\x18\x06 \x01(\t\x12Q\n\x04\x64\x61ta\x18\x07 \x03(\x0b\x32\x43.temporal.api.workflowservice.v1.RegisterNamespaceRequest.DataEntry\x12\x16\n\x0esecurity_token\x18\x08 \x01(\t\x12\x1b\n\x13is_global_namespace\x18\t \x01(\x08\x12\x44\n\x16history_archival_state\x18\n \x01(\x0e\x32$.temporal.api.enums.v1.ArchivalState\x12\x1c\n\x14history_archival_uri\x18\x0b \x01(\t\x12G\n\x19visibility_archival_state\x18\x0c \x01(\x0e\x32$.temporal.api.enums.v1.ArchivalState\x12\x1f\n\x17visibility_archival_uri\x18\r \x01(\t\x1a+\n\tDataEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01"\x1b\n\x19RegisterNamespaceResponse"\x89\x01\n\x15ListNamespacesRequest\x12\x11\n\tpage_size\x18\x01 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c\x12\x44\n\x10namespace_filter\x18\x03 \x01(\x0b\x32*.temporal.api.namespace.v1.NamespaceFilter"\x81\x01\n\x16ListNamespacesResponse\x12N\n\nnamespaces\x18\x01 \x03(\x0b\x32:.temporal.api.workflowservice.v1.DescribeNamespaceResponse\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c"S\n\x18\x44\x65scribeNamespaceRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\n\n\x02id\x18\x02 \x01(\t\x12\x18\n\x10weak_consistency\x18\x03 \x01(\x08"\xb4\x03\n\x19\x44\x65scribeNamespaceResponse\x12@\n\x0enamespace_info\x18\x01 \x01(\x0b\x32(.temporal.api.namespace.v1.NamespaceInfo\x12:\n\x06\x63onfig\x18\x02 \x01(\x0b\x32*.temporal.api.namespace.v1.NamespaceConfig\x12S\n\x12replication_config\x18\x03 \x01(\x0b\x32\x37.temporal.api.replication.v1.NamespaceReplicationConfig\x12\x18\n\x10\x66\x61ilover_version\x18\x04 \x01(\x03\x12\x1b\n\x13is_global_namespace\x18\x05 \x01(\x08\x12\x45\n\x10\x66\x61ilover_history\x18\x06 \x03(\x0b\x32+.temporal.api.replication.v1.FailoverStatus\x12\x46\n\x12poller_group_infos\x18\x07 \x03(\x0b\x32*.temporal.api.taskqueue.v1.PollerGroupInfo"\xcf\x02\n\x16UpdateNamespaceRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x43\n\x0bupdate_info\x18\x02 \x01(\x0b\x32..temporal.api.namespace.v1.UpdateNamespaceInfo\x12:\n\x06\x63onfig\x18\x03 \x01(\x0b\x32*.temporal.api.namespace.v1.NamespaceConfig\x12S\n\x12replication_config\x18\x04 \x01(\x0b\x32\x37.temporal.api.replication.v1.NamespaceReplicationConfig\x12\x16\n\x0esecurity_token\x18\x05 \x01(\t\x12\x19\n\x11\x64\x65lete_bad_binary\x18\x06 \x01(\t\x12\x19\n\x11promote_namespace\x18\x07 \x01(\x08"\xa3\x02\n\x17UpdateNamespaceResponse\x12@\n\x0enamespace_info\x18\x01 \x01(\x0b\x32(.temporal.api.namespace.v1.NamespaceInfo\x12:\n\x06\x63onfig\x18\x02 \x01(\x0b\x32*.temporal.api.namespace.v1.NamespaceConfig\x12S\n\x12replication_config\x18\x03 \x01(\x0b\x32\x37.temporal.api.replication.v1.NamespaceReplicationConfig\x12\x18\n\x10\x66\x61ilover_version\x18\x04 \x01(\x03\x12\x1b\n\x13is_global_namespace\x18\x05 \x01(\x08"F\n\x19\x44\x65precateNamespaceRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x16\n\x0esecurity_token\x18\x02 \x01(\t"\x1c\n\x1a\x44\x65precateNamespaceResponse"\xd3\x0c\n\x1dStartWorkflowExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12;\n\rworkflow_type\x18\x03 \x01(\x0b\x32$.temporal.api.common.v1.WorkflowType\x12\x38\n\ntask_queue\x18\x04 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12/\n\x05input\x18\x05 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12=\n\x1aworkflow_execution_timeout\x18\x06 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x37\n\x14workflow_run_timeout\x18\x07 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x38\n\x15workflow_task_timeout\x18\x08 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x10\n\x08identity\x18\t \x01(\t\x12\x12\n\nrequest_id\x18\n \x01(\t\x12N\n\x18workflow_id_reuse_policy\x18\x0b \x01(\x0e\x32,.temporal.api.enums.v1.WorkflowIdReusePolicy\x12T\n\x1bworkflow_id_conflict_policy\x18\x16 \x01(\x0e\x32/.temporal.api.enums.v1.WorkflowIdConflictPolicy\x12\x39\n\x0cretry_policy\x18\x0c \x01(\x0b\x32#.temporal.api.common.v1.RetryPolicy\x12\x15\n\rcron_schedule\x18\r \x01(\t\x12*\n\x04memo\x18\x0e \x01(\x0b\x32\x1c.temporal.api.common.v1.Memo\x12\x43\n\x11search_attributes\x18\x0f \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes\x12.\n\x06header\x18\x10 \x01(\x0b\x32\x1e.temporal.api.common.v1.Header\x12\x1f\n\x17request_eager_execution\x18\x11 \x01(\x08\x12;\n\x11\x63ontinued_failure\x18\x12 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12@\n\x16last_completion_result\x18\x13 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x37\n\x14workflow_start_delay\x18\x14 \x01(\x0b\x32\x19.google.protobuf.Duration\x12>\n\x14\x63ompletion_callbacks\x18\x15 \x03(\x0b\x32 .temporal.api.common.v1.Callback\x12\x38\n\ruser_metadata\x18\x17 \x01(\x0b\x32!.temporal.api.sdk.v1.UserMetadata\x12+\n\x05links\x18\x18 \x03(\x0b\x32\x1c.temporal.api.common.v1.Link\x12I\n\x13versioning_override\x18\x19 \x01(\x0b\x32,.temporal.api.workflow.v1.VersioningOverride\x12H\n\x13on_conflict_options\x18\x1a \x01(\x0b\x32+.temporal.api.workflow.v1.OnConflictOptions\x12\x32\n\x08priority\x18\x1b \x01(\x0b\x32 .temporal.api.common.v1.Priority\x12\\\n\x1f\x65\x61ger_worker_deployment_options\x18\x1c \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentOptions\x12J\n\x14time_skipping_config\x18\x1d \x01(\x0b\x32,.temporal.api.workflow.v1.TimeSkippingConfig"\x8a\x02\n\x1eStartWorkflowExecutionResponse\x12\x0e\n\x06run_id\x18\x01 \x01(\t\x12\x0f\n\x07started\x18\x03 \x01(\x08\x12>\n\x06status\x18\x05 \x01(\x0e\x32..temporal.api.enums.v1.WorkflowExecutionStatus\x12[\n\x13\x65\x61ger_workflow_task\x18\x02 \x01(\x0b\x32>.temporal.api.workflowservice.v1.PollWorkflowTaskQueueResponse\x12*\n\x04link\x18\x04 \x01(\x0b\x32\x1c.temporal.api.common.v1.Link"\xaa\x02\n"GetWorkflowExecutionHistoryRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12<\n\texecution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x19\n\x11maximum_page_size\x18\x03 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x04 \x01(\x0c\x12\x16\n\x0ewait_new_event\x18\x05 \x01(\x08\x12P\n\x19history_event_filter_type\x18\x06 \x01(\x0e\x32-.temporal.api.enums.v1.HistoryEventFilterType\x12\x15\n\rskip_archival\x18\x07 \x01(\x08"\xba\x01\n#GetWorkflowExecutionHistoryResponse\x12\x31\n\x07history\x18\x01 \x01(\x0b\x32 .temporal.api.history.v1.History\x12\x35\n\x0braw_history\x18\x02 \x03(\x0b\x32 .temporal.api.common.v1.DataBlob\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c\x12\x10\n\x08\x61rchived\x18\x04 \x01(\x08"\xb0\x01\n)GetWorkflowExecutionHistoryReverseRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12<\n\texecution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x19\n\x11maximum_page_size\x18\x03 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x04 \x01(\x0c"x\n*GetWorkflowExecutionHistoryReverseResponse\x12\x31\n\x07history\x18\x01 \x01(\x0b\x32 .temporal.api.history.v1.History\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c"\xb8\x03\n\x1cPollWorkflowTaskQueueRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x38\n\ntask_queue\x18\x02 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12\x17\n\x0fpoller_group_id\x18\n \x01(\t\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x1b\n\x13worker_instance_key\x18\x08 \x01(\t\x12!\n\x19worker_control_task_queue\x18\t \x01(\t\x12\x1b\n\x0f\x62inary_checksum\x18\x04 \x01(\tB\x02\x18\x01\x12Z\n\x1bworker_version_capabilities\x18\x05 \x01(\x0b\x32\x31.temporal.api.common.v1.WorkerVersionCapabilitiesB\x02\x18\x01\x12O\n\x12\x64\x65ployment_options\x18\x06 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentOptionsJ\x04\x08\x07\x10\x08R\x10worker_heartbeat"\xf2\x07\n\x1dPollWorkflowTaskQueueResponse\x12\x12\n\ntask_token\x18\x01 \x01(\x0c\x12\x45\n\x12workflow_execution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12;\n\rworkflow_type\x18\x03 \x01(\x0b\x32$.temporal.api.common.v1.WorkflowType\x12!\n\x19previous_started_event_id\x18\x04 \x01(\x03\x12\x18\n\x10started_event_id\x18\x05 \x01(\x03\x12\x0f\n\x07\x61ttempt\x18\x06 \x01(\x05\x12\x1a\n\x12\x62\x61\x63klog_count_hint\x18\x07 \x01(\x03\x12\x31\n\x07history\x18\x08 \x01(\x0b\x32 .temporal.api.history.v1.History\x12\x17\n\x0fnext_page_token\x18\t \x01(\x0c\x12\x33\n\x05query\x18\n \x01(\x0b\x32$.temporal.api.query.v1.WorkflowQuery\x12K\n\x1dworkflow_execution_task_queue\x18\x0b \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12\x32\n\x0escheduled_time\x18\x0c \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x30\n\x0cstarted_time\x18\r \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\\\n\x07queries\x18\x0e \x03(\x0b\x32K.temporal.api.workflowservice.v1.PollWorkflowTaskQueueResponse.QueriesEntry\x12\x33\n\x08messages\x18\x0f \x03(\x0b\x32!.temporal.api.protocol.v1.Message\x12Q\n\x17poller_scaling_decision\x18\x10 \x01(\x0b\x32\x30.temporal.api.taskqueue.v1.PollerScalingDecision\x12\x17\n\x0fpoller_group_id\x18\x11 \x01(\t\x12\x46\n\x12poller_group_infos\x18\x12 \x03(\x0b\x32*.temporal.api.taskqueue.v1.PollerGroupInfo\x1aT\n\x0cQueriesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x33\n\x05value\x18\x02 \x01(\x0b\x32$.temporal.api.query.v1.WorkflowQuery:\x02\x38\x01"\x8a\n\n#RespondWorkflowTaskCompletedRequest\x12\x12\n\ntask_token\x18\x01 \x01(\x0c\x12\x32\n\x08\x63ommands\x18\x02 \x03(\x0b\x32 .temporal.api.command.v1.Command\x12\x10\n\x08identity\x18\x03 \x01(\t\x12O\n\x11sticky_attributes\x18\x04 \x01(\x0b\x32\x34.temporal.api.taskqueue.v1.StickyExecutionAttributes\x12 \n\x18return_new_workflow_task\x18\x05 \x01(\x08\x12&\n\x1e\x66orce_create_new_workflow_task\x18\x06 \x01(\x08\x12\x1b\n\x0f\x62inary_checksum\x18\x07 \x01(\tB\x02\x18\x01\x12m\n\rquery_results\x18\x08 \x03(\x0b\x32V.temporal.api.workflowservice.v1.RespondWorkflowTaskCompletedRequest.QueryResultsEntry\x12\x11\n\tnamespace\x18\t \x01(\t\x12\x13\n\x0bresource_id\x18\x12 \x01(\t\x12L\n\x14worker_version_stamp\x18\n \x01(\x0b\x32*.temporal.api.common.v1.WorkerVersionStampB\x02\x18\x01\x12\x33\n\x08messages\x18\x0b \x03(\x0b\x32!.temporal.api.protocol.v1.Message\x12H\n\x0csdk_metadata\x18\x0c \x01(\x0b\x32\x32.temporal.api.sdk.v1.WorkflowTaskCompletedMetadata\x12\x43\n\x11metering_metadata\x18\r \x01(\x0b\x32(.temporal.api.common.v1.MeteringMetadata\x12g\n\x0c\x63\x61pabilities\x18\x0e \x01(\x0b\x32Q.temporal.api.workflowservice.v1.RespondWorkflowTaskCompletedRequest.Capabilities\x12>\n\ndeployment\x18\x0f \x01(\x0b\x32&.temporal.api.deployment.v1.DeploymentB\x02\x18\x01\x12\x46\n\x13versioning_behavior\x18\x10 \x01(\x0e\x32).temporal.api.enums.v1.VersioningBehavior\x12O\n\x12\x64\x65ployment_options\x18\x11 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentOptions\x12\x1b\n\x13worker_instance_key\x18\x13 \x01(\t\x12!\n\x19worker_control_task_queue\x18\x14 \x01(\t\x1a_\n\x11QueryResultsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x39\n\x05value\x18\x02 \x01(\x0b\x32*.temporal.api.query.v1.WorkflowQueryResult:\x02\x38\x01\x1a\x45\n\x0c\x43\x61pabilities\x12\x35\n-discard_speculative_workflow_task_with_events\x18\x01 \x01(\x08"\xf5\x01\n$RespondWorkflowTaskCompletedResponse\x12U\n\rworkflow_task\x18\x01 \x01(\x0b\x32>.temporal.api.workflowservice.v1.PollWorkflowTaskQueueResponse\x12V\n\x0e\x61\x63tivity_tasks\x18\x02 \x03(\x0b\x32>.temporal.api.workflowservice.v1.PollActivityTaskQueueResponse\x12\x1e\n\x16reset_history_event_id\x18\x03 \x01(\x03"\x8d\x04\n RespondWorkflowTaskFailedRequest\x12\x12\n\ntask_token\x18\x01 \x01(\x0c\x12=\n\x05\x63\x61use\x18\x02 \x01(\x0e\x32..temporal.api.enums.v1.WorkflowTaskFailedCause\x12\x31\n\x07\x66\x61ilure\x18\x03 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12\x10\n\x08identity\x18\x04 \x01(\t\x12\x1b\n\x0f\x62inary_checksum\x18\x05 \x01(\tB\x02\x18\x01\x12\x11\n\tnamespace\x18\x06 \x01(\t\x12\x13\n\x0bresource_id\x18\x0b \x01(\t\x12\x33\n\x08messages\x18\x07 \x03(\x0b\x32!.temporal.api.protocol.v1.Message\x12\x46\n\x0eworker_version\x18\x08 \x01(\x0b\x32*.temporal.api.common.v1.WorkerVersionStampB\x02\x18\x01\x12>\n\ndeployment\x18\t \x01(\x0b\x32&.temporal.api.deployment.v1.DeploymentB\x02\x18\x01\x12O\n\x12\x64\x65ployment_options\x18\n \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentOptions"#\n!RespondWorkflowTaskFailedResponse"\xe6\x03\n\x1cPollActivityTaskQueueRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x38\n\ntask_queue\x18\x02 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12\x17\n\x0fpoller_group_id\x18\n \x01(\t\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x1b\n\x13worker_instance_key\x18\x08 \x01(\t\x12!\n\x19worker_control_task_queue\x18\t \x01(\t\x12I\n\x13task_queue_metadata\x18\x04 \x01(\x0b\x32,.temporal.api.taskqueue.v1.TaskQueueMetadata\x12Z\n\x1bworker_version_capabilities\x18\x05 \x01(\x0b\x32\x31.temporal.api.common.v1.WorkerVersionCapabilitiesB\x02\x18\x01\x12O\n\x12\x64\x65ployment_options\x18\x06 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentOptionsJ\x04\x08\x07\x10\x08R\x10worker_heartbeat"\xd0\x08\n\x1dPollActivityTaskQueueResponse\x12\x12\n\ntask_token\x18\x01 \x01(\x0c\x12\x1a\n\x12workflow_namespace\x18\x02 \x01(\t\x12;\n\rworkflow_type\x18\x03 \x01(\x0b\x32$.temporal.api.common.v1.WorkflowType\x12\x45\n\x12workflow_execution\x18\x04 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12;\n\ractivity_type\x18\x05 \x01(\x0b\x32$.temporal.api.common.v1.ActivityType\x12\x13\n\x0b\x61\x63tivity_id\x18\x06 \x01(\t\x12.\n\x06header\x18\x07 \x01(\x0b\x32\x1e.temporal.api.common.v1.Header\x12/\n\x05input\x18\x08 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12;\n\x11heartbeat_details\x18\t \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x32\n\x0escheduled_time\x18\n \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x42\n\x1e\x63urrent_attempt_scheduled_time\x18\x0b \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x30\n\x0cstarted_time\x18\x0c \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x0f\n\x07\x61ttempt\x18\r \x01(\x05\x12<\n\x19schedule_to_close_timeout\x18\x0e \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x39\n\x16start_to_close_timeout\x18\x0f \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x34\n\x11heartbeat_timeout\x18\x10 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x39\n\x0cretry_policy\x18\x11 \x01(\x0b\x32#.temporal.api.common.v1.RetryPolicy\x12Q\n\x17poller_scaling_decision\x18\x12 \x01(\x0b\x32\x30.temporal.api.taskqueue.v1.PollerScalingDecision\x12\x32\n\x08priority\x18\x13 \x01(\x0b\x32 .temporal.api.common.v1.Priority\x12\x17\n\x0f\x61\x63tivity_run_id\x18\x14 \x01(\t\x12\x46\n\x12poller_group_infos\x18\x15 \x03(\x0b\x32*.temporal.api.taskqueue.v1.PollerGroupInfo"\xa5\x01\n"RecordActivityTaskHeartbeatRequest\x12\x12\n\ntask_token\x18\x01 \x01(\x0c\x12\x31\n\x07\x64\x65tails\x18\x02 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x11\n\tnamespace\x18\x04 \x01(\t\x12\x13\n\x0bresource_id\x18\x05 \x01(\t"p\n#RecordActivityTaskHeartbeatResponse\x12\x18\n\x10\x63\x61ncel_requested\x18\x01 \x01(\x08\x12\x17\n\x0f\x61\x63tivity_paused\x18\x02 \x01(\x08\x12\x16\n\x0e\x61\x63tivity_reset\x18\x03 \x01(\x08"\xcf\x01\n&RecordActivityTaskHeartbeatByIdRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x12\x13\n\x0b\x61\x63tivity_id\x18\x04 \x01(\t\x12\x31\n\x07\x64\x65tails\x18\x05 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x10\n\x08identity\x18\x06 \x01(\t\x12\x13\n\x0bresource_id\x18\x07 \x01(\t"t\n\'RecordActivityTaskHeartbeatByIdResponse\x12\x18\n\x10\x63\x61ncel_requested\x18\x01 \x01(\x08\x12\x17\n\x0f\x61\x63tivity_paused\x18\x02 \x01(\x08\x12\x16\n\x0e\x61\x63tivity_reset\x18\x03 \x01(\x08"\xfe\x02\n#RespondActivityTaskCompletedRequest\x12\x12\n\ntask_token\x18\x01 \x01(\x0c\x12\x30\n\x06result\x18\x02 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x11\n\tnamespace\x18\x04 \x01(\t\x12\x13\n\x0bresource_id\x18\x08 \x01(\t\x12\x46\n\x0eworker_version\x18\x05 \x01(\x0b\x32*.temporal.api.common.v1.WorkerVersionStampB\x02\x18\x01\x12>\n\ndeployment\x18\x06 \x01(\x0b\x32&.temporal.api.deployment.v1.DeploymentB\x02\x18\x01\x12O\n\x12\x64\x65ployment_options\x18\x07 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentOptions"&\n$RespondActivityTaskCompletedResponse"\xcf\x01\n\'RespondActivityTaskCompletedByIdRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x12\x13\n\x0b\x61\x63tivity_id\x18\x04 \x01(\t\x12\x30\n\x06result\x18\x05 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x10\n\x08identity\x18\x06 \x01(\t\x12\x13\n\x0bresource_id\x18\x07 \x01(\t"*\n(RespondActivityTaskCompletedByIdResponse"\xbe\x03\n RespondActivityTaskFailedRequest\x12\x12\n\ntask_token\x18\x01 \x01(\x0c\x12\x31\n\x07\x66\x61ilure\x18\x02 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x11\n\tnamespace\x18\x04 \x01(\t\x12\x13\n\x0bresource_id\x18\t \x01(\t\x12@\n\x16last_heartbeat_details\x18\x05 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x46\n\x0eworker_version\x18\x06 \x01(\x0b\x32*.temporal.api.common.v1.WorkerVersionStampB\x02\x18\x01\x12>\n\ndeployment\x18\x07 \x01(\x0b\x32&.temporal.api.deployment.v1.DeploymentB\x02\x18\x01\x12O\n\x12\x64\x65ployment_options\x18\x08 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentOptions"W\n!RespondActivityTaskFailedResponse\x12\x32\n\x08\x66\x61ilures\x18\x01 \x03(\x0b\x32 .temporal.api.failure.v1.Failure"\x8f\x02\n$RespondActivityTaskFailedByIdRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x12\x13\n\x0b\x61\x63tivity_id\x18\x04 \x01(\t\x12\x31\n\x07\x66\x61ilure\x18\x05 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12\x10\n\x08identity\x18\x06 \x01(\t\x12@\n\x16last_heartbeat_details\x18\x07 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x13\n\x0bresource_id\x18\x08 \x01(\t"[\n%RespondActivityTaskFailedByIdResponse\x12\x32\n\x08\x66\x61ilures\x18\x01 \x03(\x0b\x32 .temporal.api.failure.v1.Failure"\xfe\x02\n"RespondActivityTaskCanceledRequest\x12\x12\n\ntask_token\x18\x01 \x01(\x0c\x12\x31\n\x07\x64\x65tails\x18\x02 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x11\n\tnamespace\x18\x04 \x01(\t\x12\x13\n\x0bresource_id\x18\x08 \x01(\t\x12\x46\n\x0eworker_version\x18\x05 \x01(\x0b\x32*.temporal.api.common.v1.WorkerVersionStampB\x02\x18\x01\x12>\n\ndeployment\x18\x06 \x01(\x0b\x32&.temporal.api.deployment.v1.DeploymentB\x02\x18\x01\x12O\n\x12\x64\x65ployment_options\x18\x07 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentOptions"%\n#RespondActivityTaskCanceledResponse"\xa0\x02\n&RespondActivityTaskCanceledByIdRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x12\x13\n\x0b\x61\x63tivity_id\x18\x04 \x01(\t\x12\x31\n\x07\x64\x65tails\x18\x05 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x10\n\x08identity\x18\x06 \x01(\t\x12O\n\x12\x64\x65ployment_options\x18\x07 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentOptions\x12\x13\n\x0bresource_id\x18\x08 \x01(\t")\n\'RespondActivityTaskCanceledByIdResponse"\x84\x02\n%RequestCancelWorkflowExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x45\n\x12workflow_execution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x12\n\nrequest_id\x18\x04 \x01(\t\x12\x1e\n\x16\x66irst_execution_run_id\x18\x05 \x01(\t\x12\x0e\n\x06reason\x18\x06 \x01(\t\x12+\n\x05links\x18\x07 \x03(\x0b\x32\x1c.temporal.api.common.v1.Link"(\n&RequestCancelWorkflowExecutionResponse"\xde\x02\n\x1eSignalWorkflowExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x45\n\x12workflow_execution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x13\n\x0bsignal_name\x18\x03 \x01(\t\x12/\n\x05input\x18\x04 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x10\n\x08identity\x18\x05 \x01(\t\x12\x12\n\nrequest_id\x18\x06 \x01(\t\x12\x13\n\x07\x63ontrol\x18\x07 \x01(\tB\x02\x18\x01\x12.\n\x06header\x18\x08 \x01(\x0b\x32\x1e.temporal.api.common.v1.Header\x12+\n\x05links\x18\n \x03(\x0b\x32\x1c.temporal.api.common.v1.LinkJ\x04\x08\t\x10\n"M\n\x1fSignalWorkflowExecutionResponse\x12*\n\x04link\x18\x01 \x01(\x0b\x32\x1c.temporal.api.common.v1.Link"\xbd\n\n\'SignalWithStartWorkflowExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12;\n\rworkflow_type\x18\x03 \x01(\x0b\x32$.temporal.api.common.v1.WorkflowType\x12\x38\n\ntask_queue\x18\x04 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12/\n\x05input\x18\x05 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12=\n\x1aworkflow_execution_timeout\x18\x06 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x37\n\x14workflow_run_timeout\x18\x07 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x38\n\x15workflow_task_timeout\x18\x08 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x10\n\x08identity\x18\t \x01(\t\x12\x12\n\nrequest_id\x18\n \x01(\t\x12N\n\x18workflow_id_reuse_policy\x18\x0b \x01(\x0e\x32,.temporal.api.enums.v1.WorkflowIdReusePolicy\x12T\n\x1bworkflow_id_conflict_policy\x18\x16 \x01(\x0e\x32/.temporal.api.enums.v1.WorkflowIdConflictPolicy\x12\x13\n\x0bsignal_name\x18\x0c \x01(\t\x12\x36\n\x0csignal_input\x18\r \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x13\n\x07\x63ontrol\x18\x0e \x01(\tB\x02\x18\x01\x12\x39\n\x0cretry_policy\x18\x0f \x01(\x0b\x32#.temporal.api.common.v1.RetryPolicy\x12\x15\n\rcron_schedule\x18\x10 \x01(\t\x12*\n\x04memo\x18\x11 \x01(\x0b\x32\x1c.temporal.api.common.v1.Memo\x12\x43\n\x11search_attributes\x18\x12 \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes\x12.\n\x06header\x18\x13 \x01(\x0b\x32\x1e.temporal.api.common.v1.Header\x12\x37\n\x14workflow_start_delay\x18\x14 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x38\n\ruser_metadata\x18\x17 \x01(\x0b\x32!.temporal.api.sdk.v1.UserMetadata\x12+\n\x05links\x18\x18 \x03(\x0b\x32\x1c.temporal.api.common.v1.Link\x12I\n\x13versioning_override\x18\x19 \x01(\x0b\x32,.temporal.api.workflow.v1.VersioningOverride\x12\x32\n\x08priority\x18\x1a \x01(\x0b\x32 .temporal.api.common.v1.Priority\x12J\n\x14time_skipping_config\x18\x1b \x01(\x0b\x32,.temporal.api.workflow.v1.TimeSkippingConfigJ\x04\x08\x15\x10\x16"~\n(SignalWithStartWorkflowExecutionResponse\x12\x0e\n\x06run_id\x18\x01 \x01(\t\x12\x0f\n\x07started\x18\x02 \x01(\x08\x12\x31\n\x0bsignal_link\x18\x03 \x01(\x0b\x32\x1c.temporal.api.common.v1.Link"\xc1\x03\n\x1dResetWorkflowExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x45\n\x12workflow_execution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x0e\n\x06reason\x18\x03 \x01(\t\x12%\n\x1dworkflow_task_finish_event_id\x18\x04 \x01(\x03\x12\x12\n\nrequest_id\x18\x05 \x01(\t\x12G\n\x12reset_reapply_type\x18\x06 \x01(\x0e\x32\'.temporal.api.enums.v1.ResetReapplyTypeB\x02\x18\x01\x12S\n\x1breset_reapply_exclude_types\x18\x07 \x03(\x0e\x32..temporal.api.enums.v1.ResetReapplyExcludeType\x12K\n\x15post_reset_operations\x18\x08 \x03(\x0b\x32,.temporal.api.workflow.v1.PostResetOperation\x12\x10\n\x08identity\x18\t \x01(\t"0\n\x1eResetWorkflowExecutionResponse\x12\x0e\n\x06run_id\x18\x01 \x01(\t"\x9f\x02\n!TerminateWorkflowExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x45\n\x12workflow_execution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x0e\n\x06reason\x18\x03 \x01(\t\x12\x31\n\x07\x64\x65tails\x18\x04 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x10\n\x08identity\x18\x05 \x01(\t\x12\x1e\n\x16\x66irst_execution_run_id\x18\x06 \x01(\t\x12+\n\x05links\x18\x07 \x03(\x0b\x32\x1c.temporal.api.common.v1.Link"$\n"TerminateWorkflowExecutionResponse"z\n\x1e\x44\x65leteWorkflowExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x45\n\x12workflow_execution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution"!\n\x1f\x44\x65leteWorkflowExecutionResponse"\xc9\x02\n!ListOpenWorkflowExecutionsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x19\n\x11maximum_page_size\x18\x02 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c\x12\x42\n\x11start_time_filter\x18\x04 \x01(\x0b\x32\'.temporal.api.filter.v1.StartTimeFilter\x12K\n\x10\x65xecution_filter\x18\x05 \x01(\x0b\x32/.temporal.api.filter.v1.WorkflowExecutionFilterH\x00\x12\x41\n\x0btype_filter\x18\x06 \x01(\x0b\x32*.temporal.api.filter.v1.WorkflowTypeFilterH\x00\x42\t\n\x07\x66ilters"\x82\x01\n"ListOpenWorkflowExecutionsResponse\x12\x43\n\nexecutions\x18\x01 \x03(\x0b\x32/.temporal.api.workflow.v1.WorkflowExecutionInfo\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c"\x8a\x03\n#ListClosedWorkflowExecutionsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x19\n\x11maximum_page_size\x18\x02 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c\x12\x42\n\x11start_time_filter\x18\x04 \x01(\x0b\x32\'.temporal.api.filter.v1.StartTimeFilter\x12K\n\x10\x65xecution_filter\x18\x05 \x01(\x0b\x32/.temporal.api.filter.v1.WorkflowExecutionFilterH\x00\x12\x41\n\x0btype_filter\x18\x06 \x01(\x0b\x32*.temporal.api.filter.v1.WorkflowTypeFilterH\x00\x12=\n\rstatus_filter\x18\x07 \x01(\x0b\x32$.temporal.api.filter.v1.StatusFilterH\x00\x42\t\n\x07\x66ilters"\x84\x01\n$ListClosedWorkflowExecutionsResponse\x12\x43\n\nexecutions\x18\x01 \x03(\x0b\x32/.temporal.api.workflow.v1.WorkflowExecutionInfo\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c"m\n\x1dListWorkflowExecutionsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x11\n\tpage_size\x18\x02 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c\x12\r\n\x05query\x18\x04 \x01(\t"~\n\x1eListWorkflowExecutionsResponse\x12\x43\n\nexecutions\x18\x01 \x03(\x0b\x32/.temporal.api.workflow.v1.WorkflowExecutionInfo\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c"u\n%ListArchivedWorkflowExecutionsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x11\n\tpage_size\x18\x02 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c\x12\r\n\x05query\x18\x04 \x01(\t"\x86\x01\n&ListArchivedWorkflowExecutionsResponse\x12\x43\n\nexecutions\x18\x01 \x03(\x0b\x32/.temporal.api.workflow.v1.WorkflowExecutionInfo\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c"m\n\x1dScanWorkflowExecutionsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x11\n\tpage_size\x18\x02 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c\x12\r\n\x05query\x18\x04 \x01(\t"~\n\x1eScanWorkflowExecutionsResponse\x12\x43\n\nexecutions\x18\x01 \x03(\x0b\x32/.temporal.api.workflow.v1.WorkflowExecutionInfo\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c"B\n\x1e\x43ountWorkflowExecutionsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\r\n\x05query\x18\x02 \x01(\t"\xed\x01\n\x1f\x43ountWorkflowExecutionsResponse\x12\r\n\x05\x63ount\x18\x01 \x01(\x03\x12\x61\n\x06groups\x18\x02 \x03(\x0b\x32Q.temporal.api.workflowservice.v1.CountWorkflowExecutionsResponse.AggregationGroup\x1aX\n\x10\x41ggregationGroup\x12\x35\n\x0cgroup_values\x18\x01 \x03(\x0b\x32\x1f.temporal.api.common.v1.Payload\x12\r\n\x05\x63ount\x18\x02 \x01(\x03"\x1c\n\x1aGetSearchAttributesRequest"\xc9\x01\n\x1bGetSearchAttributesResponse\x12T\n\x04keys\x18\x01 \x03(\x0b\x32\x46.temporal.api.workflowservice.v1.GetSearchAttributesResponse.KeysEntry\x1aT\n\tKeysEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x36\n\x05value\x18\x02 \x01(\x0e\x32\'.temporal.api.enums.v1.IndexedValueType:\x02\x38\x01"\xe9\x02\n RespondQueryTaskCompletedRequest\x12\x12\n\ntask_token\x18\x01 \x01(\x0c\x12>\n\x0e\x63ompleted_type\x18\x02 \x01(\x0e\x32&.temporal.api.enums.v1.QueryResultType\x12\x36\n\x0cquery_result\x18\x03 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x15\n\rerror_message\x18\x04 \x01(\t\x12\x11\n\tnamespace\x18\x06 \x01(\t\x12\x31\n\x07\x66\x61ilure\x18\x07 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12=\n\x05\x63\x61use\x18\x08 \x01(\x0e\x32..temporal.api.enums.v1.WorkflowTaskFailedCause\x12\x17\n\x0fpoller_group_id\x18\t \x01(\tJ\x04\x08\x05\x10\x06"#\n!RespondQueryTaskCompletedResponse"n\n\x1bResetStickyTaskQueueRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12<\n\texecution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution"\x1e\n\x1cResetStickyTaskQueueResponse"\x9b\x02\n\x15ShutdownWorkerRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x19\n\x11sticky_task_queue\x18\x02 \x01(\t\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x0e\n\x06reason\x18\x04 \x01(\t\x12\x41\n\x10worker_heartbeat\x18\x05 \x01(\x0b\x32\'.temporal.api.worker.v1.WorkerHeartbeat\x12\x1b\n\x13worker_instance_key\x18\x06 \x01(\t\x12\x12\n\ntask_queue\x18\x07 \x01(\t\x12>\n\x10task_queue_types\x18\x08 \x03(\x0e\x32$.temporal.api.enums.v1.TaskQueueType"\x18\n\x16ShutdownWorkerResponse"\xe9\x01\n\x14QueryWorkflowRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12<\n\texecution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x33\n\x05query\x18\x03 \x01(\x0b\x32$.temporal.api.query.v1.WorkflowQuery\x12K\n\x16query_reject_condition\x18\x04 \x01(\x0e\x32+.temporal.api.enums.v1.QueryRejectCondition"\x8d\x01\n\x15QueryWorkflowResponse\x12\x36\n\x0cquery_result\x18\x01 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12<\n\x0equery_rejected\x18\x02 \x01(\x0b\x32$.temporal.api.query.v1.QueryRejected"s\n DescribeWorkflowExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12<\n\texecution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution"\x99\x05\n!DescribeWorkflowExecutionResponse\x12K\n\x10\x65xecution_config\x18\x01 \x01(\x0b\x32\x31.temporal.api.workflow.v1.WorkflowExecutionConfig\x12P\n\x17workflow_execution_info\x18\x02 \x01(\x0b\x32/.temporal.api.workflow.v1.WorkflowExecutionInfo\x12I\n\x12pending_activities\x18\x03 \x03(\x0b\x32-.temporal.api.workflow.v1.PendingActivityInfo\x12M\n\x10pending_children\x18\x04 \x03(\x0b\x32\x33.temporal.api.workflow.v1.PendingChildExecutionInfo\x12P\n\x15pending_workflow_task\x18\x05 \x01(\x0b\x32\x31.temporal.api.workflow.v1.PendingWorkflowTaskInfo\x12\x39\n\tcallbacks\x18\x06 \x03(\x0b\x32&.temporal.api.workflow.v1.CallbackInfo\x12U\n\x18pending_nexus_operations\x18\x07 \x03(\x0b\x32\x33.temporal.api.workflow.v1.PendingNexusOperationInfo\x12W\n\x16workflow_extended_info\x18\x08 \x01(\x0b\x32\x37.temporal.api.workflow.v1.WorkflowExecutionExtendedInfo"\x90\x04\n\x18\x44\x65scribeTaskQueueRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x38\n\ntask_queue\x18\x02 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12=\n\x0ftask_queue_type\x18\x03 \x01(\x0e\x32$.temporal.api.enums.v1.TaskQueueType\x12\x14\n\x0creport_stats\x18\x08 \x01(\x08\x12\x15\n\rreport_config\x18\x0b \x01(\x08\x12%\n\x19include_task_queue_status\x18\x04 \x01(\x08\x42\x02\x18\x01\x12\x42\n\x08\x61pi_mode\x18\x05 \x01(\x0e\x32,.temporal.api.enums.v1.DescribeTaskQueueModeB\x02\x18\x01\x12J\n\x08versions\x18\x06 \x01(\x0b\x32\x34.temporal.api.taskqueue.v1.TaskQueueVersionSelectionB\x02\x18\x01\x12\x42\n\x10task_queue_types\x18\x07 \x03(\x0e\x32$.temporal.api.enums.v1.TaskQueueTypeB\x02\x18\x01\x12\x1a\n\x0ereport_pollers\x18\t \x01(\x08\x42\x02\x18\x01\x12$\n\x18report_task_reachability\x18\n \x01(\x08\x42\x02\x18\x01"\xec\x07\n\x19\x44\x65scribeTaskQueueResponse\x12\x36\n\x07pollers\x18\x01 \x03(\x0b\x32%.temporal.api.taskqueue.v1.PollerInfo\x12\x38\n\x05stats\x18\x05 \x01(\x0b\x32).temporal.api.taskqueue.v1.TaskQueueStats\x12q\n\x15stats_by_priority_key\x18\x08 \x03(\x0b\x32R.temporal.api.workflowservice.v1.DescribeTaskQueueResponse.StatsByPriorityKeyEntry\x12K\n\x0fversioning_info\x18\x04 \x01(\x0b\x32\x32.temporal.api.taskqueue.v1.TaskQueueVersioningInfo\x12:\n\x06\x63onfig\x18\x06 \x01(\x0b\x32*.temporal.api.taskqueue.v1.TaskQueueConfig\x12k\n\x14\x65\x66\x66\x65\x63tive_rate_limit\x18\x07 \x01(\x0b\x32M.temporal.api.workflowservice.v1.DescribeTaskQueueResponse.EffectiveRateLimit\x12I\n\x11task_queue_status\x18\x02 \x01(\x0b\x32*.temporal.api.taskqueue.v1.TaskQueueStatusB\x02\x18\x01\x12g\n\rversions_info\x18\x03 \x03(\x0b\x32L.temporal.api.workflowservice.v1.DescribeTaskQueueResponse.VersionsInfoEntryB\x02\x18\x01\x1a\x64\n\x17StatsByPriorityKeyEntry\x12\x0b\n\x03key\x18\x01 \x01(\x05\x12\x38\n\x05value\x18\x02 \x01(\x0b\x32).temporal.api.taskqueue.v1.TaskQueueStats:\x02\x38\x01\x1at\n\x12\x45\x66\x66\x65\x63tiveRateLimit\x12\x1b\n\x13requests_per_second\x18\x01 \x01(\x02\x12\x41\n\x11rate_limit_source\x18\x02 \x01(\x0e\x32&.temporal.api.enums.v1.RateLimitSource\x1a\x64\n\x11VersionsInfoEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12>\n\x05value\x18\x02 \x01(\x0b\x32/.temporal.api.taskqueue.v1.TaskQueueVersionInfo:\x02\x38\x01"\x17\n\x15GetClusterInfoRequest"\xd1\x03\n\x16GetClusterInfoResponse\x12h\n\x11supported_clients\x18\x01 \x03(\x0b\x32M.temporal.api.workflowservice.v1.GetClusterInfoResponse.SupportedClientsEntry\x12\x16\n\x0eserver_version\x18\x02 \x01(\t\x12\x12\n\ncluster_id\x18\x03 \x01(\t\x12:\n\x0cversion_info\x18\x04 \x01(\x0b\x32$.temporal.api.version.v1.VersionInfo\x12\x14\n\x0c\x63luster_name\x18\x05 \x01(\t\x12\x1b\n\x13history_shard_count\x18\x06 \x01(\x05\x12\x19\n\x11persistence_store\x18\x07 \x01(\t\x12\x18\n\x10visibility_store\x18\x08 \x01(\t\x12 \n\x18initial_failover_version\x18\t \x01(\x03\x12"\n\x1a\x66\x61ilover_version_increment\x18\n \x01(\x03\x1a\x37\n\x15SupportedClientsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01"\x16\n\x14GetSystemInfoRequest"\x97\x04\n\x15GetSystemInfoResponse\x12\x16\n\x0eserver_version\x18\x01 \x01(\t\x12Y\n\x0c\x63\x61pabilities\x18\x02 \x01(\x0b\x32\x43.temporal.api.workflowservice.v1.GetSystemInfoResponse.Capabilities\x1a\x8a\x03\n\x0c\x43\x61pabilities\x12\x1f\n\x17signal_and_query_header\x18\x01 \x01(\x08\x12&\n\x1einternal_error_differentiation\x18\x02 \x01(\x08\x12*\n"activity_failure_include_heartbeat\x18\x03 \x01(\x08\x12\x1a\n\x12supports_schedules\x18\x04 \x01(\x08\x12"\n\x1a\x65ncoded_failure_attributes\x18\x05 \x01(\x08\x12!\n\x19\x62uild_id_based_versioning\x18\x06 \x01(\x08\x12\x13\n\x0bupsert_memo\x18\x07 \x01(\x08\x12\x1c\n\x14\x65\x61ger_workflow_start\x18\x08 \x01(\x08\x12\x14\n\x0csdk_metadata\x18\t \x01(\x08\x12\'\n\x1f\x63ount_group_by_execution_status\x18\n \x01(\x08\x12\r\n\x05nexus\x18\x0b \x01(\x08\x12!\n\x19server_scaled_deployments\x18\x0c \x01(\x08"m\n\x1eListTaskQueuePartitionsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x38\n\ntask_queue\x18\x02 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue"\xdf\x01\n\x1fListTaskQueuePartitionsResponse\x12]\n\x1e\x61\x63tivity_task_queue_partitions\x18\x01 \x03(\x0b\x32\x35.temporal.api.taskqueue.v1.TaskQueuePartitionMetadata\x12]\n\x1eworkflow_task_queue_partitions\x18\x02 \x03(\x0b\x32\x35.temporal.api.taskqueue.v1.TaskQueuePartitionMetadata"\xcc\x02\n\x15\x43reateScheduleRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bschedule_id\x18\x02 \x01(\t\x12\x34\n\x08schedule\x18\x03 \x01(\x0b\x32".temporal.api.schedule.v1.Schedule\x12>\n\rinitial_patch\x18\x04 \x01(\x0b\x32\'.temporal.api.schedule.v1.SchedulePatch\x12\x10\n\x08identity\x18\x05 \x01(\t\x12\x12\n\nrequest_id\x18\x06 \x01(\t\x12*\n\x04memo\x18\x07 \x01(\x0b\x32\x1c.temporal.api.common.v1.Memo\x12\x43\n\x11search_attributes\x18\x08 \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes"0\n\x16\x43reateScheduleResponse\x12\x16\n\x0e\x63onflict_token\x18\x01 \x01(\x0c"A\n\x17\x44\x65scribeScheduleRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bschedule_id\x18\x02 \x01(\t"\x8f\x02\n\x18\x44\x65scribeScheduleResponse\x12\x34\n\x08schedule\x18\x01 \x01(\x0b\x32".temporal.api.schedule.v1.Schedule\x12\x34\n\x04info\x18\x02 \x01(\x0b\x32&.temporal.api.schedule.v1.ScheduleInfo\x12*\n\x04memo\x18\x03 \x01(\x0b\x32\x1c.temporal.api.common.v1.Memo\x12\x43\n\x11search_attributes\x18\x04 \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes\x12\x16\n\x0e\x63onflict_token\x18\x05 \x01(\x0c"\xa4\x02\n\x15UpdateScheduleRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bschedule_id\x18\x02 \x01(\t\x12\x34\n\x08schedule\x18\x03 \x01(\x0b\x32".temporal.api.schedule.v1.Schedule\x12\x16\n\x0e\x63onflict_token\x18\x04 \x01(\x0c\x12\x10\n\x08identity\x18\x05 \x01(\t\x12\x12\n\nrequest_id\x18\x06 \x01(\t\x12\x43\n\x11search_attributes\x18\x07 \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes\x12*\n\x04memo\x18\x08 \x01(\x0b\x32\x1c.temporal.api.common.v1.Memo"\x18\n\x16UpdateScheduleResponse"\x9c\x01\n\x14PatchScheduleRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bschedule_id\x18\x02 \x01(\t\x12\x36\n\x05patch\x18\x03 \x01(\x0b\x32\'.temporal.api.schedule.v1.SchedulePatch\x12\x10\n\x08identity\x18\x04 \x01(\t\x12\x12\n\nrequest_id\x18\x05 \x01(\t"\x17\n\x15PatchScheduleResponse"\xa8\x01\n ListScheduleMatchingTimesRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bschedule_id\x18\x02 \x01(\t\x12.\n\nstart_time\x18\x03 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12,\n\x08\x65nd_time\x18\x04 \x01(\x0b\x32\x1a.google.protobuf.Timestamp"S\n!ListScheduleMatchingTimesResponse\x12.\n\nstart_time\x18\x01 \x03(\x0b\x32\x1a.google.protobuf.Timestamp"Q\n\x15\x44\x65leteScheduleRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bschedule_id\x18\x02 \x01(\t\x12\x10\n\x08identity\x18\x03 \x01(\t"\x18\n\x16\x44\x65leteScheduleResponse"l\n\x14ListSchedulesRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x19\n\x11maximum_page_size\x18\x02 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c\x12\r\n\x05query\x18\x04 \x01(\t"p\n\x15ListSchedulesResponse\x12>\n\tschedules\x18\x01 \x03(\x0b\x32+.temporal.api.schedule.v1.ScheduleListEntry\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c"9\n\x15\x43ountSchedulesRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\r\n\x05query\x18\x02 \x01(\t"\xdb\x01\n\x16\x43ountSchedulesResponse\x12\r\n\x05\x63ount\x18\x01 \x01(\x03\x12X\n\x06groups\x18\x02 \x03(\x0b\x32H.temporal.api.workflowservice.v1.CountSchedulesResponse.AggregationGroup\x1aX\n\x10\x41ggregationGroup\x12\x35\n\x0cgroup_values\x18\x01 \x03(\x0b\x32\x1f.temporal.api.common.v1.Payload\x12\r\n\x05\x63ount\x18\x02 \x01(\x03"\x86\x05\n\'UpdateWorkerBuildIdCompatibilityRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x12\n\ntask_queue\x18\x02 \x01(\t\x12-\n#add_new_build_id_in_new_default_set\x18\x03 \x01(\tH\x00\x12\x87\x01\n\x1b\x61\x64\x64_new_compatible_build_id\x18\x04 \x01(\x0b\x32`.temporal.api.workflowservice.v1.UpdateWorkerBuildIdCompatibilityRequest.AddNewCompatibleVersionH\x00\x12!\n\x17promote_set_by_build_id\x18\x05 \x01(\tH\x00\x12%\n\x1bpromote_build_id_within_set\x18\x06 \x01(\tH\x00\x12h\n\nmerge_sets\x18\x07 \x01(\x0b\x32R.temporal.api.workflowservice.v1.UpdateWorkerBuildIdCompatibilityRequest.MergeSetsH\x00\x1ao\n\x17\x41\x64\x64NewCompatibleVersion\x12\x14\n\x0cnew_build_id\x18\x01 \x01(\t\x12$\n\x1c\x65xisting_compatible_build_id\x18\x02 \x01(\t\x12\x18\n\x10make_set_default\x18\x03 \x01(\x08\x1aI\n\tMergeSets\x12\x1c\n\x14primary_set_build_id\x18\x01 \x01(\t\x12\x1e\n\x16secondary_set_build_id\x18\x02 \x01(\tB\x0b\n\toperation"@\n(UpdateWorkerBuildIdCompatibilityResponseJ\x04\x08\x01\x10\x02R\x0eversion_set_id"_\n$GetWorkerBuildIdCompatibilityRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x12\n\ntask_queue\x18\x02 \x01(\t\x12\x10\n\x08max_sets\x18\x03 \x01(\x05"t\n%GetWorkerBuildIdCompatibilityResponse\x12K\n\x12major_version_sets\x18\x01 \x03(\x0b\x32/.temporal.api.taskqueue.v1.CompatibleVersionSet"\xb5\r\n"UpdateWorkerVersioningRulesRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x12\n\ntask_queue\x18\x02 \x01(\t\x12\x16\n\x0e\x63onflict_token\x18\x03 \x01(\x0c\x12\x81\x01\n\x16insert_assignment_rule\x18\x04 \x01(\x0b\x32_.temporal.api.workflowservice.v1.UpdateWorkerVersioningRulesRequest.InsertBuildIdAssignmentRuleH\x00\x12\x83\x01\n\x17replace_assignment_rule\x18\x05 \x01(\x0b\x32`.temporal.api.workflowservice.v1.UpdateWorkerVersioningRulesRequest.ReplaceBuildIdAssignmentRuleH\x00\x12\x81\x01\n\x16\x64\x65lete_assignment_rule\x18\x06 \x01(\x0b\x32_.temporal.api.workflowservice.v1.UpdateWorkerVersioningRulesRequest.DeleteBuildIdAssignmentRuleH\x00\x12\x8c\x01\n\x1c\x61\x64\x64_compatible_redirect_rule\x18\x07 \x01(\x0b\x32\x64.temporal.api.workflowservice.v1.UpdateWorkerVersioningRulesRequest.AddCompatibleBuildIdRedirectRuleH\x00\x12\x94\x01\n replace_compatible_redirect_rule\x18\x08 \x01(\x0b\x32h.temporal.api.workflowservice.v1.UpdateWorkerVersioningRulesRequest.ReplaceCompatibleBuildIdRedirectRuleH\x00\x12\x92\x01\n\x1f\x64\x65lete_compatible_redirect_rule\x18\t \x01(\x0b\x32g.temporal.api.workflowservice.v1.UpdateWorkerVersioningRulesRequest.DeleteCompatibleBuildIdRedirectRuleH\x00\x12l\n\x0f\x63ommit_build_id\x18\n \x01(\x0b\x32Q.temporal.api.workflowservice.v1.UpdateWorkerVersioningRulesRequest.CommitBuildIdH\x00\x1aq\n\x1bInsertBuildIdAssignmentRule\x12\x12\n\nrule_index\x18\x01 \x01(\x05\x12>\n\x04rule\x18\x02 \x01(\x0b\x32\x30.temporal.api.taskqueue.v1.BuildIdAssignmentRule\x1a\x81\x01\n\x1cReplaceBuildIdAssignmentRule\x12\x12\n\nrule_index\x18\x01 \x01(\x05\x12>\n\x04rule\x18\x02 \x01(\x0b\x32\x30.temporal.api.taskqueue.v1.BuildIdAssignmentRule\x12\r\n\x05\x66orce\x18\x03 \x01(\x08\x1a@\n\x1b\x44\x65leteBuildIdAssignmentRule\x12\x12\n\nrule_index\x18\x01 \x01(\x05\x12\r\n\x05\x66orce\x18\x02 \x01(\x08\x1aj\n AddCompatibleBuildIdRedirectRule\x12\x46\n\x04rule\x18\x01 \x01(\x0b\x32\x38.temporal.api.taskqueue.v1.CompatibleBuildIdRedirectRule\x1an\n$ReplaceCompatibleBuildIdRedirectRule\x12\x46\n\x04rule\x18\x01 \x01(\x0b\x32\x38.temporal.api.taskqueue.v1.CompatibleBuildIdRedirectRule\x1a>\n#DeleteCompatibleBuildIdRedirectRule\x12\x17\n\x0fsource_build_id\x18\x01 \x01(\t\x1a\x37\n\rCommitBuildId\x12\x17\n\x0ftarget_build_id\x18\x01 \x01(\t\x12\r\n\x05\x66orce\x18\x02 \x01(\x08\x42\x0b\n\toperation"\xfc\x01\n#UpdateWorkerVersioningRulesResponse\x12U\n\x10\x61ssignment_rules\x18\x01 \x03(\x0b\x32;.temporal.api.taskqueue.v1.TimestampedBuildIdAssignmentRule\x12\x66\n\x19\x63ompatible_redirect_rules\x18\x02 \x03(\x0b\x32\x43.temporal.api.taskqueue.v1.TimestampedCompatibleBuildIdRedirectRule\x12\x16\n\x0e\x63onflict_token\x18\x03 \x01(\x0c"H\n\x1fGetWorkerVersioningRulesRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x12\n\ntask_queue\x18\x02 \x01(\t"\xf9\x01\n GetWorkerVersioningRulesResponse\x12U\n\x10\x61ssignment_rules\x18\x01 \x03(\x0b\x32;.temporal.api.taskqueue.v1.TimestampedBuildIdAssignmentRule\x12\x66\n\x19\x63ompatible_redirect_rules\x18\x02 \x03(\x0b\x32\x43.temporal.api.taskqueue.v1.TimestampedCompatibleBuildIdRedirectRule\x12\x16\n\x0e\x63onflict_token\x18\x03 \x01(\x0c"\x9c\x01\n GetWorkerTaskReachabilityRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x11\n\tbuild_ids\x18\x02 \x03(\t\x12\x13\n\x0btask_queues\x18\x03 \x03(\t\x12=\n\x0creachability\x18\x04 \x01(\x0e\x32\'.temporal.api.enums.v1.TaskReachability"r\n!GetWorkerTaskReachabilityResponse\x12M\n\x15\x62uild_id_reachability\x18\x01 \x03(\x0b\x32..temporal.api.taskqueue.v1.BuildIdReachability"\x85\x02\n\x1eUpdateWorkflowExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x45\n\x12workflow_execution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x1e\n\x16\x66irst_execution_run_id\x18\x03 \x01(\t\x12\x37\n\x0bwait_policy\x18\x04 \x01(\x0b\x32".temporal.api.update.v1.WaitPolicy\x12\x30\n\x07request\x18\x05 \x01(\x0b\x32\x1f.temporal.api.update.v1.Request"\x83\x02\n\x1fUpdateWorkflowExecutionResponse\x12\x35\n\nupdate_ref\x18\x01 \x01(\x0b\x32!.temporal.api.update.v1.UpdateRef\x12\x30\n\x07outcome\x18\x02 \x01(\x0b\x32\x1f.temporal.api.update.v1.Outcome\x12K\n\x05stage\x18\x03 \x01(\x0e\x32<.temporal.api.enums.v1.UpdateWorkflowExecutionLifecycleStage\x12*\n\x04link\x18\x04 \x01(\x0b\x32\x1c.temporal.api.common.v1.Link"\xf4\x07\n\x1aStartBatchOperationRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x18\n\x10visibility_query\x18\x02 \x01(\t\x12\x0e\n\x06job_id\x18\x03 \x01(\t\x12\x0e\n\x06reason\x18\x04 \x01(\t\x12=\n\nexecutions\x18\x05 \x03(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12!\n\x19max_operations_per_second\x18\x06 \x01(\x02\x12Q\n\x15termination_operation\x18\n \x01(\x0b\x32\x30.temporal.api.batch.v1.BatchOperationTerminationH\x00\x12G\n\x10signal_operation\x18\x0b \x01(\x0b\x32+.temporal.api.batch.v1.BatchOperationSignalH\x00\x12S\n\x16\x63\x61ncellation_operation\x18\x0c \x01(\x0b\x32\x31.temporal.api.batch.v1.BatchOperationCancellationH\x00\x12K\n\x12\x64\x65letion_operation\x18\r \x01(\x0b\x32-.temporal.api.batch.v1.BatchOperationDeletionH\x00\x12\x45\n\x0freset_operation\x18\x0e \x01(\x0b\x32*.temporal.api.batch.v1.BatchOperationResetH\x00\x12p\n!update_workflow_options_operation\x18\x0f \x01(\x0b\x32\x43.temporal.api.batch.v1.BatchOperationUpdateWorkflowExecutionOptionsH\x00\x12^\n\x1cunpause_activities_operation\x18\x10 \x01(\x0b\x32\x36.temporal.api.batch.v1.BatchOperationUnpauseActivitiesH\x00\x12Z\n\x1areset_activities_operation\x18\x11 \x01(\x0b\x32\x34.temporal.api.batch.v1.BatchOperationResetActivitiesH\x00\x12g\n!update_activity_options_operation\x18\x12 \x01(\x0b\x32:.temporal.api.batch.v1.BatchOperationUpdateActivityOptionsH\x00\x42\x0b\n\toperation"\x1d\n\x1bStartBatchOperationResponse"`\n\x19StopBatchOperationRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x0e\n\x06job_id\x18\x02 \x01(\t\x12\x0e\n\x06reason\x18\x03 \x01(\t\x12\x10\n\x08identity\x18\x04 \x01(\t"\x1c\n\x1aStopBatchOperationResponse"B\n\x1d\x44\x65scribeBatchOperationRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x0e\n\x06job_id\x18\x02 \x01(\t"\x92\x03\n\x1e\x44\x65scribeBatchOperationResponse\x12\x41\n\x0eoperation_type\x18\x01 \x01(\x0e\x32).temporal.api.enums.v1.BatchOperationType\x12\x0e\n\x06job_id\x18\x02 \x01(\t\x12\x39\n\x05state\x18\x03 \x01(\x0e\x32*.temporal.api.enums.v1.BatchOperationState\x12.\n\nstart_time\x18\x04 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12.\n\nclose_time\x18\x05 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x1d\n\x15total_operation_count\x18\x06 \x01(\x03\x12 \n\x18\x63omplete_operation_count\x18\x07 \x01(\x03\x12\x1f\n\x17\x66\x61ilure_operation_count\x18\x08 \x01(\x03\x12\x10\n\x08identity\x18\t \x01(\t\x12\x0e\n\x06reason\x18\n \x01(\t"[\n\x1aListBatchOperationsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x11\n\tpage_size\x18\x02 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c"y\n\x1bListBatchOperationsResponse\x12\x41\n\x0eoperation_info\x18\x01 \x03(\x0b\x32).temporal.api.batch.v1.BatchOperationInfo\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c"\xb9\x01\n"PollWorkflowExecutionUpdateRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x35\n\nupdate_ref\x18\x02 \x01(\x0b\x32!.temporal.api.update.v1.UpdateRef\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x37\n\x0bwait_policy\x18\x04 \x01(\x0b\x32".temporal.api.update.v1.WaitPolicy"\xdb\x01\n#PollWorkflowExecutionUpdateResponse\x12\x30\n\x07outcome\x18\x01 \x01(\x0b\x32\x1f.temporal.api.update.v1.Outcome\x12K\n\x05stage\x18\x02 \x01(\x0e\x32<.temporal.api.enums.v1.UpdateWorkflowExecutionLifecycleStage\x12\x35\n\nupdate_ref\x18\x03 \x01(\x0b\x32!.temporal.api.update.v1.UpdateRef"\xa0\x03\n\x19PollNexusTaskQueueRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x38\n\ntask_queue\x18\x03 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12\x17\n\x0fpoller_group_id\x18\t \x01(\t\x12\x10\n\x08identity\x18\x02 \x01(\t\x12\x1b\n\x13worker_instance_key\x18\x08 \x01(\t\x12Z\n\x1bworker_version_capabilities\x18\x04 \x01(\x0b\x32\x31.temporal.api.common.v1.WorkerVersionCapabilitiesB\x02\x18\x01\x12O\n\x12\x64\x65ployment_options\x18\x06 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentOptions\x12\x41\n\x10worker_heartbeat\x18\x07 \x03(\x0b\x32\'.temporal.api.worker.v1.WorkerHeartbeat"\x95\x02\n\x1aPollNexusTaskQueueResponse\x12\x12\n\ntask_token\x18\x01 \x01(\x0c\x12/\n\x07request\x18\x02 \x01(\x0b\x32\x1e.temporal.api.nexus.v1.Request\x12Q\n\x17poller_scaling_decision\x18\x03 \x01(\x0b\x32\x30.temporal.api.taskqueue.v1.PollerScalingDecision\x12\x17\n\x0fpoller_group_id\x18\x04 \x01(\t\x12\x46\n\x12poller_group_infos\x18\x05 \x03(\x0b\x32*.temporal.api.taskqueue.v1.PollerGroupInfo"\xa7\x01\n RespondNexusTaskCompletedRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x10\n\x08identity\x18\x02 \x01(\t\x12\x12\n\ntask_token\x18\x03 \x01(\x0c\x12\x31\n\x08response\x18\x04 \x01(\x0b\x32\x1f.temporal.api.nexus.v1.Response\x12\x17\n\x0fpoller_group_id\x18\x05 \x01(\t"#\n!RespondNexusTaskCompletedResponse"\xdc\x01\n\x1dRespondNexusTaskFailedRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x10\n\x08identity\x18\x02 \x01(\t\x12\x12\n\ntask_token\x18\x03 \x01(\x0c\x12\x36\n\x05\x65rror\x18\x04 \x01(\x0b\x32#.temporal.api.nexus.v1.HandlerErrorB\x02\x18\x01\x12\x31\n\x07\x66\x61ilure\x18\x05 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12\x17\n\x0fpoller_group_id\x18\x06 \x01(\t" \n\x1eRespondNexusTaskFailedResponse"\xf4\x02\n\x1c\x45xecuteMultiOperationRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12[\n\noperations\x18\x02 \x03(\x0b\x32G.temporal.api.workflowservice.v1.ExecuteMultiOperationRequest.Operation\x12\x13\n\x0bresource_id\x18\x03 \x01(\t\x1a\xce\x01\n\tOperation\x12X\n\x0estart_workflow\x18\x01 \x01(\x0b\x32>.temporal.api.workflowservice.v1.StartWorkflowExecutionRequestH\x00\x12Z\n\x0fupdate_workflow\x18\x02 \x01(\x0b\x32?.temporal.api.workflowservice.v1.UpdateWorkflowExecutionRequestH\x00\x42\x0b\n\toperation"\xcc\x02\n\x1d\x45xecuteMultiOperationResponse\x12Z\n\tresponses\x18\x01 \x03(\x0b\x32G.temporal.api.workflowservice.v1.ExecuteMultiOperationResponse.Response\x1a\xce\x01\n\x08Response\x12Y\n\x0estart_workflow\x18\x01 \x01(\x0b\x32?.temporal.api.workflowservice.v1.StartWorkflowExecutionResponseH\x00\x12[\n\x0fupdate_workflow\x18\x02 \x01(\x0b\x32@.temporal.api.workflowservice.v1.UpdateWorkflowExecutionResponseH\x00\x42\n\n\x08response"\xd0\x02\n\x1cUpdateActivityOptionsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12<\n\texecution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x43\n\x10\x61\x63tivity_options\x18\x04 \x01(\x0b\x32).temporal.api.activity.v1.ActivityOptions\x12/\n\x0bupdate_mask\x18\x05 \x01(\x0b\x32\x1a.google.protobuf.FieldMask\x12\x0c\n\x02id\x18\x06 \x01(\tH\x00\x12\x0e\n\x04type\x18\x07 \x01(\tH\x00\x12\x13\n\tmatch_all\x18\t \x01(\x08H\x00\x12\x18\n\x10restore_original\x18\x08 \x01(\x08\x42\n\n\x08\x61\x63tivity"\xab\x02\n%UpdateActivityExecutionOptionsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12\x13\n\x0b\x61\x63tivity_id\x18\x03 \x01(\t\x12\x0e\n\x06run_id\x18\x04 \x01(\t\x12\x10\n\x08identity\x18\x05 \x01(\t\x12\x43\n\x10\x61\x63tivity_options\x18\x06 \x01(\x0b\x32).temporal.api.activity.v1.ActivityOptions\x12/\n\x0bupdate_mask\x18\x07 \x01(\x0b\x32\x1a.google.protobuf.FieldMask\x12\x18\n\x10restore_original\x18\x08 \x01(\x08\x12\x13\n\x0bresource_id\x18\t \x01(\t"d\n\x1dUpdateActivityOptionsResponse\x12\x43\n\x10\x61\x63tivity_options\x18\x01 \x01(\x0b\x32).temporal.api.activity.v1.ActivityOptions"m\n&UpdateActivityExecutionOptionsResponse\x12\x43\n\x10\x61\x63tivity_options\x18\x01 \x01(\x0b\x32).temporal.api.activity.v1.ActivityOptions"\xc7\x01\n\x14PauseActivityRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12<\n\texecution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x0c\n\x02id\x18\x04 \x01(\tH\x00\x12\x0e\n\x04type\x18\x05 \x01(\tH\x00\x12\x0e\n\x06reason\x18\x06 \x01(\t\x12\x12\n\nrequest_id\x18\x07 \x01(\tB\n\n\x08\x61\x63tivity"\xb7\x01\n\x1dPauseActivityExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12\x13\n\x0b\x61\x63tivity_id\x18\x03 \x01(\t\x12\x0e\n\x06run_id\x18\x04 \x01(\t\x12\x10\n\x08identity\x18\x05 \x01(\t\x12\x0e\n\x06reason\x18\x06 \x01(\t\x12\x13\n\x0bresource_id\x18\x07 \x01(\t\x12\x12\n\nrequest_id\x18\x08 \x01(\t"\x17\n\x15PauseActivityResponse" \n\x1ePauseActivityExecutionResponse"\x98\x02\n\x16UnpauseActivityRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12<\n\texecution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x0c\n\x02id\x18\x04 \x01(\tH\x00\x12\x0e\n\x04type\x18\x05 \x01(\tH\x00\x12\x15\n\x0bunpause_all\x18\x06 \x01(\x08H\x00\x12\x16\n\x0ereset_attempts\x18\x07 \x01(\x08\x12\x17\n\x0freset_heartbeat\x18\x08 \x01(\x08\x12)\n\x06jitter\x18\t \x01(\x0b\x32\x19.google.protobuf.DurationB\n\n\x08\x61\x63tivity"\x81\x02\n\x1fUnpauseActivityExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12\x13\n\x0b\x61\x63tivity_id\x18\x03 \x01(\t\x12\x0e\n\x06run_id\x18\x04 \x01(\t\x12\x10\n\x08identity\x18\x05 \x01(\t\x12\x16\n\x0ereset_attempts\x18\x06 \x01(\x08\x12\x17\n\x0freset_heartbeat\x18\x07 \x01(\x08\x12\x0e\n\x06reason\x18\x08 \x01(\t\x12)\n\x06jitter\x18\t \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x13\n\x0bresource_id\x18\n \x01(\t"\x19\n\x17UnpauseActivityResponse""\n UnpauseActivityExecutionResponse"\xb3\x02\n\x14ResetActivityRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12<\n\texecution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x0c\n\x02id\x18\x04 \x01(\tH\x00\x12\x0e\n\x04type\x18\x05 \x01(\tH\x00\x12\x13\n\tmatch_all\x18\n \x01(\x08H\x00\x12\x17\n\x0freset_heartbeat\x18\x06 \x01(\x08\x12\x13\n\x0bkeep_paused\x18\x07 \x01(\x08\x12)\n\x06jitter\x18\x08 \x01(\x0b\x32\x19.google.protobuf.Duration\x12 \n\x18restore_original_options\x18\t \x01(\x08\x42\n\n\x08\x61\x63tivity"\x8e\x02\n\x1dResetActivityExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12\x13\n\x0b\x61\x63tivity_id\x18\x03 \x01(\t\x12\x0e\n\x06run_id\x18\x04 \x01(\t\x12\x10\n\x08identity\x18\x05 \x01(\t\x12\x17\n\x0freset_heartbeat\x18\x06 \x01(\x08\x12\x13\n\x0bkeep_paused\x18\x07 \x01(\x08\x12)\n\x06jitter\x18\x08 \x01(\x0b\x32\x19.google.protobuf.Duration\x12 \n\x18restore_original_options\x18\t \x01(\x08\x12\x13\n\x0bresource_id\x18\n \x01(\t"\x17\n\x15ResetActivityResponse" \n\x1eResetActivityExecutionResponse"\x9c\x02\n%UpdateWorkflowExecutionOptionsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x45\n\x12workflow_execution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12V\n\x1aworkflow_execution_options\x18\x03 \x01(\x0b\x32\x32.temporal.api.workflow.v1.WorkflowExecutionOptions\x12/\n\x0bupdate_mask\x18\x04 \x01(\x0b\x32\x1a.google.protobuf.FieldMask\x12\x10\n\x08identity\x18\x05 \x01(\t"\x80\x01\n&UpdateWorkflowExecutionOptionsResponse\x12V\n\x1aworkflow_execution_options\x18\x01 \x01(\x0b\x32\x32.temporal.api.workflow.v1.WorkflowExecutionOptions"j\n\x19\x44\x65scribeDeploymentRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12:\n\ndeployment\x18\x02 \x01(\x0b\x32&.temporal.api.deployment.v1.Deployment"a\n\x1a\x44\x65scribeDeploymentResponse\x12\x43\n\x0f\x64\x65ployment_info\x18\x01 \x01(\x0b\x32*.temporal.api.deployment.v1.DeploymentInfo"\xc2\x01\n&DescribeWorkerDeploymentVersionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x07version\x18\x02 \x01(\tB\x02\x18\x01\x12O\n\x12\x64\x65ployment_version\x18\x03 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersion\x12\x1f\n\x17report_task_queue_stats\x18\x04 \x01(\x08"\x8c\x05\n\'DescribeWorkerDeploymentVersionResponse\x12_\n\x1eworker_deployment_version_info\x18\x01 \x01(\x0b\x32\x37.temporal.api.deployment.v1.WorkerDeploymentVersionInfo\x12v\n\x13version_task_queues\x18\x02 \x03(\x0b\x32Y.temporal.api.workflowservice.v1.DescribeWorkerDeploymentVersionResponse.VersionTaskQueue\x1a\x87\x03\n\x10VersionTaskQueue\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x32\n\x04type\x18\x02 \x01(\x0e\x32$.temporal.api.enums.v1.TaskQueueType\x12\x38\n\x05stats\x18\x03 \x01(\x0b\x32).temporal.api.taskqueue.v1.TaskQueueStats\x12\x90\x01\n\x15stats_by_priority_key\x18\x04 \x03(\x0b\x32q.temporal.api.workflowservice.v1.DescribeWorkerDeploymentVersionResponse.VersionTaskQueue.StatsByPriorityKeyEntry\x1a\x64\n\x17StatsByPriorityKeyEntry\x12\x0b\n\x03key\x18\x01 \x01(\x05\x12\x38\n\x05value\x18\x02 \x01(\x0b\x32).temporal.api.taskqueue.v1.TaskQueueStats:\x02\x38\x01"M\n\x1f\x44\x65scribeWorkerDeploymentRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x17\n\x0f\x64\x65ployment_name\x18\x02 \x01(\t"\x8c\x01\n DescribeWorkerDeploymentResponse\x12\x16\n\x0e\x63onflict_token\x18\x01 \x01(\x0c\x12P\n\x16worker_deployment_info\x18\x02 \x01(\x0b\x32\x30.temporal.api.deployment.v1.WorkerDeploymentInfo"l\n\x16ListDeploymentsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x11\n\tpage_size\x18\x02 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c\x12\x13\n\x0bseries_name\x18\x04 \x01(\t"w\n\x17ListDeploymentsResponse\x12\x17\n\x0fnext_page_token\x18\x01 \x01(\x0c\x12\x43\n\x0b\x64\x65ployments\x18\x02 \x03(\x0b\x32..temporal.api.deployment.v1.DeploymentListInfo"\xcd\x01\n\x1bSetCurrentDeploymentRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12:\n\ndeployment\x18\x02 \x01(\x0b\x32&.temporal.api.deployment.v1.Deployment\x12\x10\n\x08identity\x18\x03 \x01(\t\x12M\n\x0fupdate_metadata\x18\x04 \x01(\x0b\x32\x34.temporal.api.deployment.v1.UpdateDeploymentMetadata"\xb9\x01\n\x1cSetCurrentDeploymentResponse\x12K\n\x17\x63urrent_deployment_info\x18\x01 \x01(\x0b\x32*.temporal.api.deployment.v1.DeploymentInfo\x12L\n\x18previous_deployment_info\x18\x02 \x01(\x0b\x32*.temporal.api.deployment.v1.DeploymentInfo"\xe5\x01\n(SetWorkerDeploymentCurrentVersionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x17\n\x0f\x64\x65ployment_name\x18\x02 \x01(\t\x12\x13\n\x07version\x18\x03 \x01(\tB\x02\x18\x01\x12\x10\n\x08\x62uild_id\x18\x07 \x01(\t\x12\x16\n\x0e\x63onflict_token\x18\x04 \x01(\x0c\x12\x10\n\x08identity\x18\x05 \x01(\t\x12"\n\x1aignore_missing_task_queues\x18\x06 \x01(\x08\x12\x18\n\x10\x61llow_no_pollers\x18\t \x01(\x08"\xbf\x01\n)SetWorkerDeploymentCurrentVersionResponse\x12\x16\n\x0e\x63onflict_token\x18\x01 \x01(\x0c\x12\x1c\n\x10previous_version\x18\x02 \x01(\tB\x02\x18\x01\x12\\\n\x1bprevious_deployment_version\x18\x03 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersionB\x02\x18\x01"\xf9\x01\n(SetWorkerDeploymentRampingVersionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x17\n\x0f\x64\x65ployment_name\x18\x02 \x01(\t\x12\x13\n\x07version\x18\x03 \x01(\tB\x02\x18\x01\x12\x10\n\x08\x62uild_id\x18\x08 \x01(\t\x12\x12\n\npercentage\x18\x04 \x01(\x02\x12\x16\n\x0e\x63onflict_token\x18\x05 \x01(\x0c\x12\x10\n\x08identity\x18\x06 \x01(\t\x12"\n\x1aignore_missing_task_queues\x18\x07 \x01(\x08\x12\x18\n\x10\x61llow_no_pollers\x18\n \x01(\x08"\xe0\x01\n)SetWorkerDeploymentRampingVersionResponse\x12\x16\n\x0e\x63onflict_token\x18\x01 \x01(\x0c\x12\x1c\n\x10previous_version\x18\x02 \x01(\tB\x02\x18\x01\x12\\\n\x1bprevious_deployment_version\x18\x04 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersionB\x02\x18\x01\x12\x1f\n\x13previous_percentage\x18\x03 \x01(\x02\x42\x02\x18\x01"q\n\x1d\x43reateWorkerDeploymentRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x17\n\x0f\x64\x65ployment_name\x18\x02 \x01(\t\x12\x10\n\x08identity\x18\x04 \x01(\t\x12\x12\n\nrequest_id\x18\x05 \x01(\t"8\n\x1e\x43reateWorkerDeploymentResponse\x12\x16\n\x0e\x63onflict_token\x18\x01 \x01(\x0c"]\n\x1cListWorkerDeploymentsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x11\n\tpage_size\x18\x02 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c"\x9f\x05\n\x1dListWorkerDeploymentsResponse\x12\x17\n\x0fnext_page_token\x18\x01 \x01(\x0c\x12r\n\x12worker_deployments\x18\x02 \x03(\x0b\x32V.temporal.api.workflowservice.v1.ListWorkerDeploymentsResponse.WorkerDeploymentSummary\x1a\xf0\x03\n\x17WorkerDeploymentSummary\x12\x0c\n\x04name\x18\x01 \x01(\t\x12/\n\x0b\x63reate_time\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x41\n\x0erouting_config\x18\x03 \x01(\x0b\x32).temporal.api.deployment.v1.RoutingConfig\x12o\n\x16latest_version_summary\x18\x04 \x01(\x0b\x32O.temporal.api.deployment.v1.WorkerDeploymentInfo.WorkerDeploymentVersionSummary\x12p\n\x17\x63urrent_version_summary\x18\x05 \x01(\x0b\x32O.temporal.api.deployment.v1.WorkerDeploymentInfo.WorkerDeploymentVersionSummary\x12p\n\x17ramping_version_summary\x18\x06 \x01(\x0b\x32O.temporal.api.deployment.v1.WorkerDeploymentInfo.WorkerDeploymentVersionSummary"\xf0\x01\n$CreateWorkerDeploymentVersionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12O\n\x12\x64\x65ployment_version\x18\x02 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersion\x12>\n\x0e\x63ompute_config\x18\x04 \x01(\x0b\x32&.temporal.api.compute.v1.ComputeConfig\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x12\n\nrequest_id\x18\x05 \x01(\t"\'\n%CreateWorkerDeploymentVersionResponse"\xc8\x01\n$DeleteWorkerDeploymentVersionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x07version\x18\x02 \x01(\tB\x02\x18\x01\x12O\n\x12\x64\x65ployment_version\x18\x05 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersion\x12\x15\n\rskip_drainage\x18\x03 \x01(\x08\x12\x10\n\x08identity\x18\x04 \x01(\t"\'\n%DeleteWorkerDeploymentVersionResponse"]\n\x1d\x44\x65leteWorkerDeploymentRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x17\n\x0f\x64\x65ployment_name\x18\x02 \x01(\t\x12\x10\n\x08identity\x18\x03 \x01(\t" \n\x1e\x44\x65leteWorkerDeploymentResponse"\x84\x04\n1UpdateWorkerDeploymentVersionComputeConfigRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12O\n\x12\x64\x65ployment_version\x18\x02 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersion\x12\x99\x01\n\x1d\x63ompute_config_scaling_groups\x18\x06 \x03(\x0b\x32r.temporal.api.workflowservice.v1.UpdateWorkerDeploymentVersionComputeConfigRequest.ComputeConfigScalingGroupsEntry\x12,\n$remove_compute_config_scaling_groups\x18\x07 \x03(\t\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x12\n\nrequest_id\x18\x04 \x01(\t\x1a{\n\x1f\x43omputeConfigScalingGroupsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12G\n\x05value\x18\x02 \x01(\x0b\x32\x38.temporal.api.compute.v1.ComputeConfigScalingGroupUpdate:\x02\x38\x01"4\n2UpdateWorkerDeploymentVersionComputeConfigResponse"\xf4\x03\n3ValidateWorkerDeploymentVersionComputeConfigRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12O\n\x12\x64\x65ployment_version\x18\x02 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersion\x12\x9b\x01\n\x1d\x63ompute_config_scaling_groups\x18\x06 \x03(\x0b\x32t.temporal.api.workflowservice.v1.ValidateWorkerDeploymentVersionComputeConfigRequest.ComputeConfigScalingGroupsEntry\x12,\n$remove_compute_config_scaling_groups\x18\x07 \x03(\t\x12\x10\n\x08identity\x18\x03 \x01(\t\x1a{\n\x1f\x43omputeConfigScalingGroupsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12G\n\x05value\x18\x02 \x01(\x0b\x32\x38.temporal.api.compute.v1.ComputeConfigScalingGroupUpdate:\x02\x38\x01"6\n4ValidateWorkerDeploymentVersionComputeConfigResponse"\xa2\x03\n,UpdateWorkerDeploymentVersionMetadataRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x07version\x18\x02 \x01(\tB\x02\x18\x01\x12O\n\x12\x64\x65ployment_version\x18\x05 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersion\x12x\n\x0eupsert_entries\x18\x03 \x03(\x0b\x32`.temporal.api.workflowservice.v1.UpdateWorkerDeploymentVersionMetadataRequest.UpsertEntriesEntry\x12\x16\n\x0eremove_entries\x18\x04 \x03(\t\x12\x10\n\x08identity\x18\x06 \x01(\t\x1aU\n\x12UpsertEntriesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12.\n\x05value\x18\x02 \x01(\x0b\x32\x1f.temporal.api.common.v1.Payload:\x02\x38\x01"n\n-UpdateWorkerDeploymentVersionMetadataResponse\x12=\n\x08metadata\x18\x01 \x01(\x0b\x32+.temporal.api.deployment.v1.VersionMetadata"\xbd\x01\n!SetWorkerDeploymentManagerRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x17\n\x0f\x64\x65ployment_name\x18\x02 \x01(\t\x12\x1a\n\x10manager_identity\x18\x03 \x01(\tH\x00\x12\x0e\n\x04self\x18\x04 \x01(\x08H\x00\x12\x16\n\x0e\x63onflict_token\x18\x05 \x01(\x0c\x12\x10\n\x08identity\x18\x06 \x01(\tB\x16\n\x14new_manager_identity"c\n"SetWorkerDeploymentManagerResponse\x12\x16\n\x0e\x63onflict_token\x18\x01 \x01(\x0c\x12%\n\x19previous_manager_identity\x18\x02 \x01(\tB\x02\x18\x01"E\n\x1bGetCurrentDeploymentRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bseries_name\x18\x02 \x01(\t"k\n\x1cGetCurrentDeploymentResponse\x12K\n\x17\x63urrent_deployment_info\x18\x01 \x01(\x0b\x32*.temporal.api.deployment.v1.DeploymentInfo"q\n GetDeploymentReachabilityRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12:\n\ndeployment\x18\x02 \x01(\x0b\x32&.temporal.api.deployment.v1.Deployment"\xe3\x01\n!GetDeploymentReachabilityResponse\x12\x43\n\x0f\x64\x65ployment_info\x18\x01 \x01(\x0b\x32*.temporal.api.deployment.v1.DeploymentInfo\x12\x43\n\x0creachability\x18\x02 \x01(\x0e\x32-.temporal.api.enums.v1.DeploymentReachability\x12\x34\n\x10last_update_time\x18\x03 \x01(\x0b\x32\x1a.google.protobuf.Timestamp"\xb4\x01\n\x19\x43reateWorkflowRuleRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x35\n\x04spec\x18\x02 \x01(\x0b\x32\'.temporal.api.rules.v1.WorkflowRuleSpec\x12\x12\n\nforce_scan\x18\x03 \x01(\x08\x12\x12\n\nrequest_id\x18\x04 \x01(\t\x12\x10\n\x08identity\x18\x05 \x01(\t\x12\x13\n\x0b\x64\x65scription\x18\x06 \x01(\t"_\n\x1a\x43reateWorkflowRuleResponse\x12\x31\n\x04rule\x18\x01 \x01(\x0b\x32#.temporal.api.rules.v1.WorkflowRule\x12\x0e\n\x06job_id\x18\x02 \x01(\t"A\n\x1b\x44\x65scribeWorkflowRuleRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x0f\n\x07rule_id\x18\x02 \x01(\t"Q\n\x1c\x44\x65scribeWorkflowRuleResponse\x12\x31\n\x04rule\x18\x01 \x01(\x0b\x32#.temporal.api.rules.v1.WorkflowRule"?\n\x19\x44\x65leteWorkflowRuleRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x0f\n\x07rule_id\x18\x02 \x01(\t"\x1c\n\x1a\x44\x65leteWorkflowRuleResponse"F\n\x18ListWorkflowRulesRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c"h\n\x19ListWorkflowRulesResponse\x12\x32\n\x05rules\x18\x01 \x03(\x0b\x32#.temporal.api.rules.v1.WorkflowRule\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c"\xce\x01\n\x1aTriggerWorkflowRuleRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12<\n\texecution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x0c\n\x02id\x18\x04 \x01(\tH\x00\x12\x37\n\x04spec\x18\x05 \x01(\x0b\x32\'.temporal.api.rules.v1.WorkflowRuleSpecH\x00\x12\x10\n\x08identity\x18\x03 \x01(\tB\x06\n\x04rule".\n\x1bTriggerWorkflowRuleResponse\x12\x0f\n\x07\x61pplied\x18\x01 \x01(\x08"\x9b\x01\n\x1cRecordWorkerHeartbeatRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x10\n\x08identity\x18\x02 \x01(\t\x12\x41\n\x10worker_heartbeat\x18\x03 \x03(\x0b\x32\'.temporal.api.worker.v1.WorkerHeartbeat\x12\x13\n\x0bresource_id\x18\x04 \x01(\t"\x1f\n\x1dRecordWorkerHeartbeatResponse"\x82\x01\n\x12ListWorkersRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x11\n\tpage_size\x18\x02 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c\x12\r\n\x05query\x18\x04 \x01(\t\x12\x1e\n\x16include_system_workers\x18\x05 \x01(\x08"\xa5\x01\n\x13ListWorkersResponse\x12<\n\x0cworkers_info\x18\x01 \x03(\x0b\x32".temporal.api.worker.v1.WorkerInfoB\x02\x18\x01\x12\x37\n\x07workers\x18\x03 \x03(\x0b\x32&.temporal.api.worker.v1.WorkerListInfo\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c"\xd5\x05\n\x1cUpdateTaskQueueConfigRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x10\n\x08identity\x18\x02 \x01(\t\x12\x12\n\ntask_queue\x18\x03 \x01(\t\x12=\n\x0ftask_queue_type\x18\x04 \x01(\x0e\x32$.temporal.api.enums.v1.TaskQueueType\x12n\n\x17update_queue_rate_limit\x18\x05 \x01(\x0b\x32M.temporal.api.workflowservice.v1.UpdateTaskQueueConfigRequest.RateLimitUpdate\x12}\n&update_fairness_key_rate_limit_default\x18\x06 \x01(\x0b\x32M.temporal.api.workflowservice.v1.UpdateTaskQueueConfigRequest.RateLimitUpdate\x12\x84\x01\n\x1dset_fairness_weight_overrides\x18\x07 \x03(\x0b\x32].temporal.api.workflowservice.v1.UpdateTaskQueueConfigRequest.SetFairnessWeightOverridesEntry\x12\'\n\x1funset_fairness_weight_overrides\x18\x08 \x03(\t\x1a[\n\x0fRateLimitUpdate\x12\x38\n\nrate_limit\x18\x01 \x01(\x0b\x32$.temporal.api.taskqueue.v1.RateLimit\x12\x0e\n\x06reason\x18\x02 \x01(\t\x1a\x41\n\x1fSetFairnessWeightOverridesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\x02:\x02\x38\x01"[\n\x1dUpdateTaskQueueConfigResponse\x12:\n\x06\x63onfig\x18\x01 \x01(\x0b\x32*.temporal.api.taskqueue.v1.TaskQueueConfig"\x9e\x01\n\x18\x46\x65tchWorkerConfigRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x10\n\x08identity\x18\x02 \x01(\t\x12\x0e\n\x06reason\x18\x03 \x01(\t\x12\x38\n\x08selector\x18\x06 \x01(\x0b\x32&.temporal.api.common.v1.WorkerSelector\x12\x13\n\x0bresource_id\x18\x07 \x01(\t"U\n\x19\x46\x65tchWorkerConfigResponse\x12\x38\n\rworker_config\x18\x01 \x01(\x0b\x32!.temporal.api.sdk.v1.WorkerConfig"\x8a\x02\n\x19UpdateWorkerConfigRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x10\n\x08identity\x18\x02 \x01(\t\x12\x0e\n\x06reason\x18\x03 \x01(\t\x12\x38\n\rworker_config\x18\x04 \x01(\x0b\x32!.temporal.api.sdk.v1.WorkerConfig\x12/\n\x0bupdate_mask\x18\x05 \x01(\x0b\x32\x1a.google.protobuf.FieldMask\x12\x38\n\x08selector\x18\x06 \x01(\x0b\x32&.temporal.api.common.v1.WorkerSelector\x12\x13\n\x0bresource_id\x18\x07 \x01(\t"d\n\x1aUpdateWorkerConfigResponse\x12:\n\rworker_config\x18\x01 \x01(\x0b\x32!.temporal.api.sdk.v1.WorkerConfigH\x00\x42\n\n\x08response"G\n\x15\x44\x65scribeWorkerRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x1b\n\x13worker_instance_key\x18\x02 \x01(\t"Q\n\x16\x44\x65scribeWorkerResponse\x12\x37\n\x0bworker_info\x18\x01 \x01(\x0b\x32".temporal.api.worker.v1.WorkerInfo"\x8d\x01\n\x1dPauseWorkflowExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x12\x10\n\x08identity\x18\x04 \x01(\t\x12\x0e\n\x06reason\x18\x05 \x01(\t\x12\x12\n\nrequest_id\x18\x06 \x01(\t" \n\x1ePauseWorkflowExecutionResponse"\x8f\x01\n\x1fUnpauseWorkflowExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x12\x10\n\x08identity\x18\x04 \x01(\t\x12\x0e\n\x06reason\x18\x05 \x01(\t\x12\x12\n\nrequest_id\x18\x06 \x01(\t""\n UnpauseWorkflowExecutionResponse"\x99\t\n\x1dStartActivityExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x10\n\x08identity\x18\x02 \x01(\t\x12\x12\n\nrequest_id\x18\x03 \x01(\t\x12\x13\n\x0b\x61\x63tivity_id\x18\x04 \x01(\t\x12;\n\ractivity_type\x18\x05 \x01(\x0b\x32$.temporal.api.common.v1.ActivityType\x12\x38\n\ntask_queue\x18\x06 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12<\n\x19schedule_to_close_timeout\x18\x07 \x01(\x0b\x32\x19.google.protobuf.Duration\x12<\n\x19schedule_to_start_timeout\x18\x08 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x39\n\x16start_to_close_timeout\x18\t \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x34\n\x11heartbeat_timeout\x18\n \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x39\n\x0cretry_policy\x18\x0b \x01(\x0b\x32#.temporal.api.common.v1.RetryPolicy\x12/\n\x05input\x18\x0c \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x45\n\x0fid_reuse_policy\x18\r \x01(\x0e\x32,.temporal.api.enums.v1.ActivityIdReusePolicy\x12K\n\x12id_conflict_policy\x18\x0e \x01(\x0e\x32/.temporal.api.enums.v1.ActivityIdConflictPolicy\x12\x43\n\x11search_attributes\x18\x0f \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes\x12.\n\x06header\x18\x10 \x01(\x0b\x32\x1e.temporal.api.common.v1.Header\x12\x38\n\ruser_metadata\x18\x11 \x01(\x0b\x32!.temporal.api.sdk.v1.UserMetadata\x12\x32\n\x08priority\x18\x12 \x01(\x0b\x32 .temporal.api.common.v1.Priority\x12>\n\x14\x63ompletion_callbacks\x18\x13 \x03(\x0b\x32 .temporal.api.common.v1.Callback\x12+\n\x05links\x18\x14 \x03(\x0b\x32\x1c.temporal.api.common.v1.Link\x12\x46\n\x13on_conflict_options\x18\x15 \x01(\x0b\x32).temporal.api.common.v1.OnConflictOptions\x12.\n\x0bstart_delay\x18\x16 \x01(\x0b\x32\x19.google.protobuf.Duration"m\n\x1eStartActivityExecutionResponse\x12\x0e\n\x06run_id\x18\x01 \x01(\t\x12\x0f\n\x07started\x18\x02 \x01(\x08\x12*\n\x04link\x18\x03 \x01(\x0b\x32\x1c.temporal.api.common.v1.Link"\xe4\x01\n DescribeActivityExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0b\x61\x63tivity_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x12\x15\n\rinclude_input\x18\x04 \x01(\x08\x12\x17\n\x0finclude_outcome\x18\x05 \x01(\x08\x12\x17\n\x0flong_poll_token\x18\x06 \x01(\x0c\x12!\n\x19include_heartbeat_details\x18\x07 \x01(\x08\x12\x1c\n\x14include_last_failure\x18\x08 \x01(\x08"\xbc\x02\n!DescribeActivityExecutionResponse\x12\x0e\n\x06run_id\x18\x01 \x01(\t\x12=\n\x04info\x18\x02 \x01(\x0b\x32/.temporal.api.activity.v1.ActivityExecutionInfo\x12/\n\x05input\x18\x03 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x43\n\x07outcome\x18\x04 \x01(\x0b\x32\x32.temporal.api.activity.v1.ActivityExecutionOutcome\x12\x17\n\x0flong_poll_token\x18\x05 \x01(\x0c\x12\x39\n\tcallbacks\x18\x06 \x03(\x0b\x32&.temporal.api.activity.v1.CallbackInfo"V\n\x1cPollActivityExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0b\x61\x63tivity_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t"t\n\x1dPollActivityExecutionResponse\x12\x0e\n\x06run_id\x18\x01 \x01(\t\x12\x43\n\x07outcome\x18\x02 \x01(\x0b\x32\x32.temporal.api.activity.v1.ActivityExecutionOutcome"m\n\x1dListActivityExecutionsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x11\n\tpage_size\x18\x02 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c\x12\r\n\x05query\x18\x04 \x01(\t"\x82\x01\n\x1eListActivityExecutionsResponse\x12G\n\nexecutions\x18\x01 \x03(\x0b\x32\x33.temporal.api.activity.v1.ActivityExecutionListInfo\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c"\xd1\x06\n#StartNexusOperationExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x10\n\x08identity\x18\x02 \x01(\t\x12\x12\n\nrequest_id\x18\x03 \x01(\t\x12\x14\n\x0coperation_id\x18\x04 \x01(\t\x12\x10\n\x08\x65ndpoint\x18\x05 \x01(\t\x12\x0f\n\x07service\x18\x06 \x01(\t\x12\x11\n\toperation\x18\x07 \x01(\t\x12<\n\x19schedule_to_close_timeout\x18\x08 \x01(\x0b\x32\x19.google.protobuf.Duration\x12<\n\x19schedule_to_start_timeout\x18\t \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x39\n\x16start_to_close_timeout\x18\n \x01(\x0b\x32\x19.google.protobuf.Duration\x12.\n\x05input\x18\x0b \x01(\x0b\x32\x1f.temporal.api.common.v1.Payload\x12K\n\x0fid_reuse_policy\x18\x0c \x01(\x0e\x32\x32.temporal.api.enums.v1.NexusOperationIdReusePolicy\x12Q\n\x12id_conflict_policy\x18\r \x01(\x0e\x32\x35.temporal.api.enums.v1.NexusOperationIdConflictPolicy\x12\x43\n\x11search_attributes\x18\x0e \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes\x12k\n\x0cnexus_header\x18\x0f \x03(\x0b\x32U.temporal.api.workflowservice.v1.StartNexusOperationExecutionRequest.NexusHeaderEntry\x12\x38\n\ruser_metadata\x18\x10 \x01(\x0b\x32!.temporal.api.sdk.v1.UserMetadata\x1a\x32\n\x10NexusHeaderEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01"G\n$StartNexusOperationExecutionResponse\x12\x0e\n\x06run_id\x18\x01 \x01(\t\x12\x0f\n\x07started\x18\x02 \x01(\x08"\xaa\x01\n&DescribeNexusOperationExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x14\n\x0coperation_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x12\x15\n\rinclude_input\x18\x04 \x01(\x08\x12\x17\n\x0finclude_outcome\x18\x05 \x01(\x08\x12\x17\n\x0flong_poll_token\x18\x06 \x01(\x0c"\xb7\x02\n\'DescribeNexusOperationExecutionResponse\x12\x0e\n\x06run_id\x18\x01 \x01(\t\x12@\n\x04info\x18\x02 \x01(\x0b\x32\x32.temporal.api.nexus.v1.NexusOperationExecutionInfo\x12.\n\x05input\x18\x03 \x01(\x0b\x32\x1f.temporal.api.common.v1.Payload\x12\x31\n\x06result\x18\x04 \x01(\x0b\x32\x1f.temporal.api.common.v1.PayloadH\x00\x12\x33\n\x07\x66\x61ilure\x18\x05 \x01(\x0b\x32 .temporal.api.failure.v1.FailureH\x00\x12\x17\n\x0flong_poll_token\x18\x06 \x01(\x0c\x42\t\n\x07outcome"\xa1\x01\n"PollNexusOperationExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x14\n\x0coperation_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x12\x42\n\nwait_stage\x18\x04 \x01(\x0e\x32..temporal.api.enums.v1.NexusOperationWaitStage"\x85\x02\n#PollNexusOperationExecutionResponse\x12\x0e\n\x06run_id\x18\x01 \x01(\t\x12\x42\n\nwait_stage\x18\x02 \x01(\x0e\x32..temporal.api.enums.v1.NexusOperationWaitStage\x12\x17\n\x0foperation_token\x18\x03 \x01(\t\x12\x31\n\x06result\x18\x04 \x01(\x0b\x32\x1f.temporal.api.common.v1.PayloadH\x00\x12\x33\n\x07\x66\x61ilure\x18\x05 \x01(\x0b\x32 .temporal.api.failure.v1.FailureH\x00\x42\t\n\x07outcome"s\n#ListNexusOperationExecutionsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x11\n\tpage_size\x18\x02 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c\x12\r\n\x05query\x18\x04 \x01(\t"\x8b\x01\n$ListNexusOperationExecutionsResponse\x12J\n\noperations\x18\x01 \x03(\x0b\x32\x36.temporal.api.nexus.v1.NexusOperationExecutionListInfo\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c"B\n\x1e\x43ountActivityExecutionsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\r\n\x05query\x18\x02 \x01(\t"\xed\x01\n\x1f\x43ountActivityExecutionsResponse\x12\r\n\x05\x63ount\x18\x01 \x01(\x03\x12\x61\n\x06groups\x18\x02 \x03(\x0b\x32Q.temporal.api.workflowservice.v1.CountActivityExecutionsResponse.AggregationGroup\x1aX\n\x10\x41ggregationGroup\x12\x35\n\x0cgroup_values\x18\x01 \x03(\x0b\x32\x1f.temporal.api.common.v1.Payload\x12\r\n\x05\x63ount\x18\x02 \x01(\x03"H\n$CountNexusOperationExecutionsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\r\n\x05query\x18\x02 \x01(\t"\xf9\x01\n%CountNexusOperationExecutionsResponse\x12\r\n\x05\x63ount\x18\x01 \x01(\x03\x12g\n\x06groups\x18\x02 \x03(\x0b\x32W.temporal.api.workflowservice.v1.CountNexusOperationExecutionsResponse.AggregationGroup\x1aX\n\x10\x41ggregationGroup\x12\x35\n\x0cgroup_values\x18\x01 \x03(\x0b\x32\x1f.temporal.api.common.v1.Payload\x12\r\n\x05\x63ount\x18\x02 \x01(\x03"\x95\x01\n%RequestCancelActivityExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0b\x61\x63tivity_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x12\x10\n\x08identity\x18\x04 \x01(\t\x12\x12\n\nrequest_id\x18\x05 \x01(\t\x12\x0e\n\x06reason\x18\x06 \x01(\t"(\n&RequestCancelActivityExecutionResponse"\x91\x01\n!TerminateActivityExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0b\x61\x63tivity_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x12\x10\n\x08identity\x18\x04 \x01(\t\x12\x12\n\nrequest_id\x18\x05 \x01(\t\x12\x0e\n\x06reason\x18\x06 \x01(\t"$\n"TerminateActivityExecutionResponse"X\n\x1e\x44\x65leteActivityExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0b\x61\x63tivity_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t"!\n\x1f\x44\x65leteActivityExecutionResponse"\x9c\x01\n+RequestCancelNexusOperationExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x14\n\x0coperation_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x12\x10\n\x08identity\x18\x04 \x01(\t\x12\x12\n\nrequest_id\x18\x05 \x01(\t\x12\x0e\n\x06reason\x18\x06 \x01(\t".\n,RequestCancelNexusOperationExecutionResponse"\x98\x01\n\'TerminateNexusOperationExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x14\n\x0coperation_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x12\x10\n\x08identity\x18\x04 \x01(\t\x12\x12\n\nrequest_id\x18\x05 \x01(\t\x12\x0e\n\x06reason\x18\x06 \x01(\t"*\n(TerminateNexusOperationExecutionResponse"_\n$DeleteNexusOperationExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x14\n\x0coperation_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t"\'\n%DeleteNexusOperationExecutionResponseB\xbe\x01\n"io.temporal.api.workflowservice.v1B\x14RequestResponseProtoP\x01Z5go.temporal.io/api/workflowservice/v1;workflowservice\xaa\x02!Temporalio.Api.WorkflowService.V1\xea\x02$Temporalio::Api::WorkflowService::V1b\x06proto3' ) @@ -4152,557 +4152,557 @@ _DESCRIBENAMESPACEREQUEST._serialized_start = 2554 _DESCRIBENAMESPACEREQUEST._serialized_end = 2637 _DESCRIBENAMESPACERESPONSE._serialized_start = 2640 - _DESCRIBENAMESPACERESPONSE._serialized_end = 3004 - _UPDATENAMESPACEREQUEST._serialized_start = 3007 - _UPDATENAMESPACEREQUEST._serialized_end = 3342 - _UPDATENAMESPACERESPONSE._serialized_start = 3345 - _UPDATENAMESPACERESPONSE._serialized_end = 3636 - _DEPRECATENAMESPACEREQUEST._serialized_start = 3638 - _DEPRECATENAMESPACEREQUEST._serialized_end = 3708 - _DEPRECATENAMESPACERESPONSE._serialized_start = 3710 - _DEPRECATENAMESPACERESPONSE._serialized_end = 3738 - _STARTWORKFLOWEXECUTIONREQUEST._serialized_start = 3741 - _STARTWORKFLOWEXECUTIONREQUEST._serialized_end = 5360 - _STARTWORKFLOWEXECUTIONRESPONSE._serialized_start = 5363 - _STARTWORKFLOWEXECUTIONRESPONSE._serialized_end = 5629 - _GETWORKFLOWEXECUTIONHISTORYREQUEST._serialized_start = 5632 - _GETWORKFLOWEXECUTIONHISTORYREQUEST._serialized_end = 5930 - _GETWORKFLOWEXECUTIONHISTORYRESPONSE._serialized_start = 5933 - _GETWORKFLOWEXECUTIONHISTORYRESPONSE._serialized_end = 6119 - _GETWORKFLOWEXECUTIONHISTORYREVERSEREQUEST._serialized_start = 6122 - _GETWORKFLOWEXECUTIONHISTORYREVERSEREQUEST._serialized_end = 6298 - _GETWORKFLOWEXECUTIONHISTORYREVERSERESPONSE._serialized_start = 6300 - _GETWORKFLOWEXECUTIONHISTORYREVERSERESPONSE._serialized_end = 6420 - _POLLWORKFLOWTASKQUEUEREQUEST._serialized_start = 6423 - _POLLWORKFLOWTASKQUEUEREQUEST._serialized_end = 6863 - _POLLWORKFLOWTASKQUEUERESPONSE._serialized_start = 6866 - _POLLWORKFLOWTASKQUEUERESPONSE._serialized_end = 7876 - _POLLWORKFLOWTASKQUEUERESPONSE_QUERIESENTRY._serialized_start = 7792 - _POLLWORKFLOWTASKQUEUERESPONSE_QUERIESENTRY._serialized_end = 7876 - _RESPONDWORKFLOWTASKCOMPLETEDREQUEST._serialized_start = 7879 - _RESPONDWORKFLOWTASKCOMPLETEDREQUEST._serialized_end = 9169 - _RESPONDWORKFLOWTASKCOMPLETEDREQUEST_QUERYRESULTSENTRY._serialized_start = 9003 - _RESPONDWORKFLOWTASKCOMPLETEDREQUEST_QUERYRESULTSENTRY._serialized_end = 9098 - _RESPONDWORKFLOWTASKCOMPLETEDREQUEST_CAPABILITIES._serialized_start = 9100 - _RESPONDWORKFLOWTASKCOMPLETEDREQUEST_CAPABILITIES._serialized_end = 9169 - _RESPONDWORKFLOWTASKCOMPLETEDRESPONSE._serialized_start = 9172 - _RESPONDWORKFLOWTASKCOMPLETEDRESPONSE._serialized_end = 9417 - _RESPONDWORKFLOWTASKFAILEDREQUEST._serialized_start = 9420 - _RESPONDWORKFLOWTASKFAILEDREQUEST._serialized_end = 9945 - _RESPONDWORKFLOWTASKFAILEDRESPONSE._serialized_start = 9947 - _RESPONDWORKFLOWTASKFAILEDRESPONSE._serialized_end = 9982 - _POLLACTIVITYTASKQUEUEREQUEST._serialized_start = 9985 - _POLLACTIVITYTASKQUEUEREQUEST._serialized_end = 10471 - _POLLACTIVITYTASKQUEUERESPONSE._serialized_start = 10474 - _POLLACTIVITYTASKQUEUERESPONSE._serialized_end = 11578 - _RECORDACTIVITYTASKHEARTBEATREQUEST._serialized_start = 11581 - _RECORDACTIVITYTASKHEARTBEATREQUEST._serialized_end = 11746 - _RECORDACTIVITYTASKHEARTBEATRESPONSE._serialized_start = 11748 - _RECORDACTIVITYTASKHEARTBEATRESPONSE._serialized_end = 11860 - _RECORDACTIVITYTASKHEARTBEATBYIDREQUEST._serialized_start = 11863 - _RECORDACTIVITYTASKHEARTBEATBYIDREQUEST._serialized_end = 12070 - _RECORDACTIVITYTASKHEARTBEATBYIDRESPONSE._serialized_start = 12072 - _RECORDACTIVITYTASKHEARTBEATBYIDRESPONSE._serialized_end = 12188 - _RESPONDACTIVITYTASKCOMPLETEDREQUEST._serialized_start = 12191 - _RESPONDACTIVITYTASKCOMPLETEDREQUEST._serialized_end = 12573 - _RESPONDACTIVITYTASKCOMPLETEDRESPONSE._serialized_start = 12575 - _RESPONDACTIVITYTASKCOMPLETEDRESPONSE._serialized_end = 12613 - _RESPONDACTIVITYTASKCOMPLETEDBYIDREQUEST._serialized_start = 12616 - _RESPONDACTIVITYTASKCOMPLETEDBYIDREQUEST._serialized_end = 12823 - _RESPONDACTIVITYTASKCOMPLETEDBYIDRESPONSE._serialized_start = 12825 - _RESPONDACTIVITYTASKCOMPLETEDBYIDRESPONSE._serialized_end = 12867 - _RESPONDACTIVITYTASKFAILEDREQUEST._serialized_start = 12870 - _RESPONDACTIVITYTASKFAILEDREQUEST._serialized_end = 13316 - _RESPONDACTIVITYTASKFAILEDRESPONSE._serialized_start = 13318 - _RESPONDACTIVITYTASKFAILEDRESPONSE._serialized_end = 13405 - _RESPONDACTIVITYTASKFAILEDBYIDREQUEST._serialized_start = 13408 - _RESPONDACTIVITYTASKFAILEDBYIDREQUEST._serialized_end = 13679 - _RESPONDACTIVITYTASKFAILEDBYIDRESPONSE._serialized_start = 13681 - _RESPONDACTIVITYTASKFAILEDBYIDRESPONSE._serialized_end = 13772 - _RESPONDACTIVITYTASKCANCELEDREQUEST._serialized_start = 13775 - _RESPONDACTIVITYTASKCANCELEDREQUEST._serialized_end = 14157 - _RESPONDACTIVITYTASKCANCELEDRESPONSE._serialized_start = 14159 - _RESPONDACTIVITYTASKCANCELEDRESPONSE._serialized_end = 14196 - _RESPONDACTIVITYTASKCANCELEDBYIDREQUEST._serialized_start = 14199 - _RESPONDACTIVITYTASKCANCELEDBYIDREQUEST._serialized_end = 14487 - _RESPONDACTIVITYTASKCANCELEDBYIDRESPONSE._serialized_start = 14489 - _RESPONDACTIVITYTASKCANCELEDBYIDRESPONSE._serialized_end = 14530 - _REQUESTCANCELWORKFLOWEXECUTIONREQUEST._serialized_start = 14533 - _REQUESTCANCELWORKFLOWEXECUTIONREQUEST._serialized_end = 14793 - _REQUESTCANCELWORKFLOWEXECUTIONRESPONSE._serialized_start = 14795 - _REQUESTCANCELWORKFLOWEXECUTIONRESPONSE._serialized_end = 14835 - _SIGNALWORKFLOWEXECUTIONREQUEST._serialized_start = 14838 - _SIGNALWORKFLOWEXECUTIONREQUEST._serialized_end = 15188 - _SIGNALWORKFLOWEXECUTIONRESPONSE._serialized_start = 15190 - _SIGNALWORKFLOWEXECUTIONRESPONSE._serialized_end = 15267 - _SIGNALWITHSTARTWORKFLOWEXECUTIONREQUEST._serialized_start = 15270 - _SIGNALWITHSTARTWORKFLOWEXECUTIONREQUEST._serialized_end = 16611 - _SIGNALWITHSTARTWORKFLOWEXECUTIONRESPONSE._serialized_start = 16613 - _SIGNALWITHSTARTWORKFLOWEXECUTIONRESPONSE._serialized_end = 16739 - _RESETWORKFLOWEXECUTIONREQUEST._serialized_start = 16742 - _RESETWORKFLOWEXECUTIONREQUEST._serialized_end = 17191 - _RESETWORKFLOWEXECUTIONRESPONSE._serialized_start = 17193 - _RESETWORKFLOWEXECUTIONRESPONSE._serialized_end = 17241 - _TERMINATEWORKFLOWEXECUTIONREQUEST._serialized_start = 17244 - _TERMINATEWORKFLOWEXECUTIONREQUEST._serialized_end = 17531 - _TERMINATEWORKFLOWEXECUTIONRESPONSE._serialized_start = 17533 - _TERMINATEWORKFLOWEXECUTIONRESPONSE._serialized_end = 17569 - _DELETEWORKFLOWEXECUTIONREQUEST._serialized_start = 17571 - _DELETEWORKFLOWEXECUTIONREQUEST._serialized_end = 17693 - _DELETEWORKFLOWEXECUTIONRESPONSE._serialized_start = 17695 - _DELETEWORKFLOWEXECUTIONRESPONSE._serialized_end = 17728 - _LISTOPENWORKFLOWEXECUTIONSREQUEST._serialized_start = 17731 - _LISTOPENWORKFLOWEXECUTIONSREQUEST._serialized_end = 18060 - _LISTOPENWORKFLOWEXECUTIONSRESPONSE._serialized_start = 18063 - _LISTOPENWORKFLOWEXECUTIONSRESPONSE._serialized_end = 18193 - _LISTCLOSEDWORKFLOWEXECUTIONSREQUEST._serialized_start = 18196 - _LISTCLOSEDWORKFLOWEXECUTIONSREQUEST._serialized_end = 18590 - _LISTCLOSEDWORKFLOWEXECUTIONSRESPONSE._serialized_start = 18593 - _LISTCLOSEDWORKFLOWEXECUTIONSRESPONSE._serialized_end = 18725 - _LISTWORKFLOWEXECUTIONSREQUEST._serialized_start = 18727 - _LISTWORKFLOWEXECUTIONSREQUEST._serialized_end = 18836 - _LISTWORKFLOWEXECUTIONSRESPONSE._serialized_start = 18838 - _LISTWORKFLOWEXECUTIONSRESPONSE._serialized_end = 18964 - _LISTARCHIVEDWORKFLOWEXECUTIONSREQUEST._serialized_start = 18966 - _LISTARCHIVEDWORKFLOWEXECUTIONSREQUEST._serialized_end = 19083 - _LISTARCHIVEDWORKFLOWEXECUTIONSRESPONSE._serialized_start = 19086 - _LISTARCHIVEDWORKFLOWEXECUTIONSRESPONSE._serialized_end = 19220 - _SCANWORKFLOWEXECUTIONSREQUEST._serialized_start = 19222 - _SCANWORKFLOWEXECUTIONSREQUEST._serialized_end = 19331 - _SCANWORKFLOWEXECUTIONSRESPONSE._serialized_start = 19333 - _SCANWORKFLOWEXECUTIONSRESPONSE._serialized_end = 19459 - _COUNTWORKFLOWEXECUTIONSREQUEST._serialized_start = 19461 - _COUNTWORKFLOWEXECUTIONSREQUEST._serialized_end = 19527 - _COUNTWORKFLOWEXECUTIONSRESPONSE._serialized_start = 19530 - _COUNTWORKFLOWEXECUTIONSRESPONSE._serialized_end = 19767 - _COUNTWORKFLOWEXECUTIONSRESPONSE_AGGREGATIONGROUP._serialized_start = 19679 - _COUNTWORKFLOWEXECUTIONSRESPONSE_AGGREGATIONGROUP._serialized_end = 19767 - _GETSEARCHATTRIBUTESREQUEST._serialized_start = 19769 - _GETSEARCHATTRIBUTESREQUEST._serialized_end = 19797 - _GETSEARCHATTRIBUTESRESPONSE._serialized_start = 19800 - _GETSEARCHATTRIBUTESRESPONSE._serialized_end = 20001 - _GETSEARCHATTRIBUTESRESPONSE_KEYSENTRY._serialized_start = 19917 - _GETSEARCHATTRIBUTESRESPONSE_KEYSENTRY._serialized_end = 20001 - _RESPONDQUERYTASKCOMPLETEDREQUEST._serialized_start = 20004 - _RESPONDQUERYTASKCOMPLETEDREQUEST._serialized_end = 20365 - _RESPONDQUERYTASKCOMPLETEDRESPONSE._serialized_start = 20367 - _RESPONDQUERYTASKCOMPLETEDRESPONSE._serialized_end = 20402 - _RESETSTICKYTASKQUEUEREQUEST._serialized_start = 20404 - _RESETSTICKYTASKQUEUEREQUEST._serialized_end = 20514 - _RESETSTICKYTASKQUEUERESPONSE._serialized_start = 20516 - _RESETSTICKYTASKQUEUERESPONSE._serialized_end = 20546 - _SHUTDOWNWORKERREQUEST._serialized_start = 20549 - _SHUTDOWNWORKERREQUEST._serialized_end = 20832 - _SHUTDOWNWORKERRESPONSE._serialized_start = 20834 - _SHUTDOWNWORKERRESPONSE._serialized_end = 20858 - _QUERYWORKFLOWREQUEST._serialized_start = 20861 - _QUERYWORKFLOWREQUEST._serialized_end = 21094 - _QUERYWORKFLOWRESPONSE._serialized_start = 21097 - _QUERYWORKFLOWRESPONSE._serialized_end = 21238 - _DESCRIBEWORKFLOWEXECUTIONREQUEST._serialized_start = 21240 - _DESCRIBEWORKFLOWEXECUTIONREQUEST._serialized_end = 21355 - _DESCRIBEWORKFLOWEXECUTIONRESPONSE._serialized_start = 21358 - _DESCRIBEWORKFLOWEXECUTIONRESPONSE._serialized_end = 22023 - _DESCRIBETASKQUEUEREQUEST._serialized_start = 22026 - _DESCRIBETASKQUEUEREQUEST._serialized_end = 22554 - _DESCRIBETASKQUEUERESPONSE._serialized_start = 22557 - _DESCRIBETASKQUEUERESPONSE._serialized_end = 23561 - _DESCRIBETASKQUEUERESPONSE_STATSBYPRIORITYKEYENTRY._serialized_start = 23241 - _DESCRIBETASKQUEUERESPONSE_STATSBYPRIORITYKEYENTRY._serialized_end = 23341 - _DESCRIBETASKQUEUERESPONSE_EFFECTIVERATELIMIT._serialized_start = 23343 - _DESCRIBETASKQUEUERESPONSE_EFFECTIVERATELIMIT._serialized_end = 23459 - _DESCRIBETASKQUEUERESPONSE_VERSIONSINFOENTRY._serialized_start = 23461 - _DESCRIBETASKQUEUERESPONSE_VERSIONSINFOENTRY._serialized_end = 23561 - _GETCLUSTERINFOREQUEST._serialized_start = 23563 - _GETCLUSTERINFOREQUEST._serialized_end = 23586 - _GETCLUSTERINFORESPONSE._serialized_start = 23589 - _GETCLUSTERINFORESPONSE._serialized_end = 24054 - _GETCLUSTERINFORESPONSE_SUPPORTEDCLIENTSENTRY._serialized_start = 23999 - _GETCLUSTERINFORESPONSE_SUPPORTEDCLIENTSENTRY._serialized_end = 24054 - _GETSYSTEMINFOREQUEST._serialized_start = 24056 - _GETSYSTEMINFOREQUEST._serialized_end = 24078 - _GETSYSTEMINFORESPONSE._serialized_start = 24081 - _GETSYSTEMINFORESPONSE._serialized_end = 24616 - _GETSYSTEMINFORESPONSE_CAPABILITIES._serialized_start = 24222 - _GETSYSTEMINFORESPONSE_CAPABILITIES._serialized_end = 24616 - _LISTTASKQUEUEPARTITIONSREQUEST._serialized_start = 24618 - _LISTTASKQUEUEPARTITIONSREQUEST._serialized_end = 24727 - _LISTTASKQUEUEPARTITIONSRESPONSE._serialized_start = 24730 - _LISTTASKQUEUEPARTITIONSRESPONSE._serialized_end = 24953 - _CREATESCHEDULEREQUEST._serialized_start = 24956 - _CREATESCHEDULEREQUEST._serialized_end = 25288 - _CREATESCHEDULERESPONSE._serialized_start = 25290 - _CREATESCHEDULERESPONSE._serialized_end = 25338 - _DESCRIBESCHEDULEREQUEST._serialized_start = 25340 - _DESCRIBESCHEDULEREQUEST._serialized_end = 25405 - _DESCRIBESCHEDULERESPONSE._serialized_start = 25408 - _DESCRIBESCHEDULERESPONSE._serialized_end = 25679 - _UPDATESCHEDULEREQUEST._serialized_start = 25682 - _UPDATESCHEDULEREQUEST._serialized_end = 25974 - _UPDATESCHEDULERESPONSE._serialized_start = 25976 - _UPDATESCHEDULERESPONSE._serialized_end = 26000 - _PATCHSCHEDULEREQUEST._serialized_start = 26003 - _PATCHSCHEDULEREQUEST._serialized_end = 26159 - _PATCHSCHEDULERESPONSE._serialized_start = 26161 - _PATCHSCHEDULERESPONSE._serialized_end = 26184 - _LISTSCHEDULEMATCHINGTIMESREQUEST._serialized_start = 26187 - _LISTSCHEDULEMATCHINGTIMESREQUEST._serialized_end = 26355 - _LISTSCHEDULEMATCHINGTIMESRESPONSE._serialized_start = 26357 - _LISTSCHEDULEMATCHINGTIMESRESPONSE._serialized_end = 26440 - _DELETESCHEDULEREQUEST._serialized_start = 26442 - _DELETESCHEDULEREQUEST._serialized_end = 26523 - _DELETESCHEDULERESPONSE._serialized_start = 26525 - _DELETESCHEDULERESPONSE._serialized_end = 26549 - _LISTSCHEDULESREQUEST._serialized_start = 26551 - _LISTSCHEDULESREQUEST._serialized_end = 26659 - _LISTSCHEDULESRESPONSE._serialized_start = 26661 - _LISTSCHEDULESRESPONSE._serialized_end = 26773 - _COUNTSCHEDULESREQUEST._serialized_start = 26775 - _COUNTSCHEDULESREQUEST._serialized_end = 26832 - _COUNTSCHEDULESRESPONSE._serialized_start = 26835 - _COUNTSCHEDULESRESPONSE._serialized_end = 27054 - _COUNTSCHEDULESRESPONSE_AGGREGATIONGROUP._serialized_start = 19679 - _COUNTSCHEDULESRESPONSE_AGGREGATIONGROUP._serialized_end = 19767 - _UPDATEWORKERBUILDIDCOMPATIBILITYREQUEST._serialized_start = 27057 - _UPDATEWORKERBUILDIDCOMPATIBILITYREQUEST._serialized_end = 27703 - _UPDATEWORKERBUILDIDCOMPATIBILITYREQUEST_ADDNEWCOMPATIBLEVERSION._serialized_start = 27504 + _DESCRIBENAMESPACERESPONSE._serialized_end = 3076 + _UPDATENAMESPACEREQUEST._serialized_start = 3079 + _UPDATENAMESPACEREQUEST._serialized_end = 3414 + _UPDATENAMESPACERESPONSE._serialized_start = 3417 + _UPDATENAMESPACERESPONSE._serialized_end = 3708 + _DEPRECATENAMESPACEREQUEST._serialized_start = 3710 + _DEPRECATENAMESPACEREQUEST._serialized_end = 3780 + _DEPRECATENAMESPACERESPONSE._serialized_start = 3782 + _DEPRECATENAMESPACERESPONSE._serialized_end = 3810 + _STARTWORKFLOWEXECUTIONREQUEST._serialized_start = 3813 + _STARTWORKFLOWEXECUTIONREQUEST._serialized_end = 5432 + _STARTWORKFLOWEXECUTIONRESPONSE._serialized_start = 5435 + _STARTWORKFLOWEXECUTIONRESPONSE._serialized_end = 5701 + _GETWORKFLOWEXECUTIONHISTORYREQUEST._serialized_start = 5704 + _GETWORKFLOWEXECUTIONHISTORYREQUEST._serialized_end = 6002 + _GETWORKFLOWEXECUTIONHISTORYRESPONSE._serialized_start = 6005 + _GETWORKFLOWEXECUTIONHISTORYRESPONSE._serialized_end = 6191 + _GETWORKFLOWEXECUTIONHISTORYREVERSEREQUEST._serialized_start = 6194 + _GETWORKFLOWEXECUTIONHISTORYREVERSEREQUEST._serialized_end = 6370 + _GETWORKFLOWEXECUTIONHISTORYREVERSERESPONSE._serialized_start = 6372 + _GETWORKFLOWEXECUTIONHISTORYREVERSERESPONSE._serialized_end = 6492 + _POLLWORKFLOWTASKQUEUEREQUEST._serialized_start = 6495 + _POLLWORKFLOWTASKQUEUEREQUEST._serialized_end = 6935 + _POLLWORKFLOWTASKQUEUERESPONSE._serialized_start = 6938 + _POLLWORKFLOWTASKQUEUERESPONSE._serialized_end = 7948 + _POLLWORKFLOWTASKQUEUERESPONSE_QUERIESENTRY._serialized_start = 7864 + _POLLWORKFLOWTASKQUEUERESPONSE_QUERIESENTRY._serialized_end = 7948 + _RESPONDWORKFLOWTASKCOMPLETEDREQUEST._serialized_start = 7951 + _RESPONDWORKFLOWTASKCOMPLETEDREQUEST._serialized_end = 9241 + _RESPONDWORKFLOWTASKCOMPLETEDREQUEST_QUERYRESULTSENTRY._serialized_start = 9075 + _RESPONDWORKFLOWTASKCOMPLETEDREQUEST_QUERYRESULTSENTRY._serialized_end = 9170 + _RESPONDWORKFLOWTASKCOMPLETEDREQUEST_CAPABILITIES._serialized_start = 9172 + _RESPONDWORKFLOWTASKCOMPLETEDREQUEST_CAPABILITIES._serialized_end = 9241 + _RESPONDWORKFLOWTASKCOMPLETEDRESPONSE._serialized_start = 9244 + _RESPONDWORKFLOWTASKCOMPLETEDRESPONSE._serialized_end = 9489 + _RESPONDWORKFLOWTASKFAILEDREQUEST._serialized_start = 9492 + _RESPONDWORKFLOWTASKFAILEDREQUEST._serialized_end = 10017 + _RESPONDWORKFLOWTASKFAILEDRESPONSE._serialized_start = 10019 + _RESPONDWORKFLOWTASKFAILEDRESPONSE._serialized_end = 10054 + _POLLACTIVITYTASKQUEUEREQUEST._serialized_start = 10057 + _POLLACTIVITYTASKQUEUEREQUEST._serialized_end = 10543 + _POLLACTIVITYTASKQUEUERESPONSE._serialized_start = 10546 + _POLLACTIVITYTASKQUEUERESPONSE._serialized_end = 11650 + _RECORDACTIVITYTASKHEARTBEATREQUEST._serialized_start = 11653 + _RECORDACTIVITYTASKHEARTBEATREQUEST._serialized_end = 11818 + _RECORDACTIVITYTASKHEARTBEATRESPONSE._serialized_start = 11820 + _RECORDACTIVITYTASKHEARTBEATRESPONSE._serialized_end = 11932 + _RECORDACTIVITYTASKHEARTBEATBYIDREQUEST._serialized_start = 11935 + _RECORDACTIVITYTASKHEARTBEATBYIDREQUEST._serialized_end = 12142 + _RECORDACTIVITYTASKHEARTBEATBYIDRESPONSE._serialized_start = 12144 + _RECORDACTIVITYTASKHEARTBEATBYIDRESPONSE._serialized_end = 12260 + _RESPONDACTIVITYTASKCOMPLETEDREQUEST._serialized_start = 12263 + _RESPONDACTIVITYTASKCOMPLETEDREQUEST._serialized_end = 12645 + _RESPONDACTIVITYTASKCOMPLETEDRESPONSE._serialized_start = 12647 + _RESPONDACTIVITYTASKCOMPLETEDRESPONSE._serialized_end = 12685 + _RESPONDACTIVITYTASKCOMPLETEDBYIDREQUEST._serialized_start = 12688 + _RESPONDACTIVITYTASKCOMPLETEDBYIDREQUEST._serialized_end = 12895 + _RESPONDACTIVITYTASKCOMPLETEDBYIDRESPONSE._serialized_start = 12897 + _RESPONDACTIVITYTASKCOMPLETEDBYIDRESPONSE._serialized_end = 12939 + _RESPONDACTIVITYTASKFAILEDREQUEST._serialized_start = 12942 + _RESPONDACTIVITYTASKFAILEDREQUEST._serialized_end = 13388 + _RESPONDACTIVITYTASKFAILEDRESPONSE._serialized_start = 13390 + _RESPONDACTIVITYTASKFAILEDRESPONSE._serialized_end = 13477 + _RESPONDACTIVITYTASKFAILEDBYIDREQUEST._serialized_start = 13480 + _RESPONDACTIVITYTASKFAILEDBYIDREQUEST._serialized_end = 13751 + _RESPONDACTIVITYTASKFAILEDBYIDRESPONSE._serialized_start = 13753 + _RESPONDACTIVITYTASKFAILEDBYIDRESPONSE._serialized_end = 13844 + _RESPONDACTIVITYTASKCANCELEDREQUEST._serialized_start = 13847 + _RESPONDACTIVITYTASKCANCELEDREQUEST._serialized_end = 14229 + _RESPONDACTIVITYTASKCANCELEDRESPONSE._serialized_start = 14231 + _RESPONDACTIVITYTASKCANCELEDRESPONSE._serialized_end = 14268 + _RESPONDACTIVITYTASKCANCELEDBYIDREQUEST._serialized_start = 14271 + _RESPONDACTIVITYTASKCANCELEDBYIDREQUEST._serialized_end = 14559 + _RESPONDACTIVITYTASKCANCELEDBYIDRESPONSE._serialized_start = 14561 + _RESPONDACTIVITYTASKCANCELEDBYIDRESPONSE._serialized_end = 14602 + _REQUESTCANCELWORKFLOWEXECUTIONREQUEST._serialized_start = 14605 + _REQUESTCANCELWORKFLOWEXECUTIONREQUEST._serialized_end = 14865 + _REQUESTCANCELWORKFLOWEXECUTIONRESPONSE._serialized_start = 14867 + _REQUESTCANCELWORKFLOWEXECUTIONRESPONSE._serialized_end = 14907 + _SIGNALWORKFLOWEXECUTIONREQUEST._serialized_start = 14910 + _SIGNALWORKFLOWEXECUTIONREQUEST._serialized_end = 15260 + _SIGNALWORKFLOWEXECUTIONRESPONSE._serialized_start = 15262 + _SIGNALWORKFLOWEXECUTIONRESPONSE._serialized_end = 15339 + _SIGNALWITHSTARTWORKFLOWEXECUTIONREQUEST._serialized_start = 15342 + _SIGNALWITHSTARTWORKFLOWEXECUTIONREQUEST._serialized_end = 16683 + _SIGNALWITHSTARTWORKFLOWEXECUTIONRESPONSE._serialized_start = 16685 + _SIGNALWITHSTARTWORKFLOWEXECUTIONRESPONSE._serialized_end = 16811 + _RESETWORKFLOWEXECUTIONREQUEST._serialized_start = 16814 + _RESETWORKFLOWEXECUTIONREQUEST._serialized_end = 17263 + _RESETWORKFLOWEXECUTIONRESPONSE._serialized_start = 17265 + _RESETWORKFLOWEXECUTIONRESPONSE._serialized_end = 17313 + _TERMINATEWORKFLOWEXECUTIONREQUEST._serialized_start = 17316 + _TERMINATEWORKFLOWEXECUTIONREQUEST._serialized_end = 17603 + _TERMINATEWORKFLOWEXECUTIONRESPONSE._serialized_start = 17605 + _TERMINATEWORKFLOWEXECUTIONRESPONSE._serialized_end = 17641 + _DELETEWORKFLOWEXECUTIONREQUEST._serialized_start = 17643 + _DELETEWORKFLOWEXECUTIONREQUEST._serialized_end = 17765 + _DELETEWORKFLOWEXECUTIONRESPONSE._serialized_start = 17767 + _DELETEWORKFLOWEXECUTIONRESPONSE._serialized_end = 17800 + _LISTOPENWORKFLOWEXECUTIONSREQUEST._serialized_start = 17803 + _LISTOPENWORKFLOWEXECUTIONSREQUEST._serialized_end = 18132 + _LISTOPENWORKFLOWEXECUTIONSRESPONSE._serialized_start = 18135 + _LISTOPENWORKFLOWEXECUTIONSRESPONSE._serialized_end = 18265 + _LISTCLOSEDWORKFLOWEXECUTIONSREQUEST._serialized_start = 18268 + _LISTCLOSEDWORKFLOWEXECUTIONSREQUEST._serialized_end = 18662 + _LISTCLOSEDWORKFLOWEXECUTIONSRESPONSE._serialized_start = 18665 + _LISTCLOSEDWORKFLOWEXECUTIONSRESPONSE._serialized_end = 18797 + _LISTWORKFLOWEXECUTIONSREQUEST._serialized_start = 18799 + _LISTWORKFLOWEXECUTIONSREQUEST._serialized_end = 18908 + _LISTWORKFLOWEXECUTIONSRESPONSE._serialized_start = 18910 + _LISTWORKFLOWEXECUTIONSRESPONSE._serialized_end = 19036 + _LISTARCHIVEDWORKFLOWEXECUTIONSREQUEST._serialized_start = 19038 + _LISTARCHIVEDWORKFLOWEXECUTIONSREQUEST._serialized_end = 19155 + _LISTARCHIVEDWORKFLOWEXECUTIONSRESPONSE._serialized_start = 19158 + _LISTARCHIVEDWORKFLOWEXECUTIONSRESPONSE._serialized_end = 19292 + _SCANWORKFLOWEXECUTIONSREQUEST._serialized_start = 19294 + _SCANWORKFLOWEXECUTIONSREQUEST._serialized_end = 19403 + _SCANWORKFLOWEXECUTIONSRESPONSE._serialized_start = 19405 + _SCANWORKFLOWEXECUTIONSRESPONSE._serialized_end = 19531 + _COUNTWORKFLOWEXECUTIONSREQUEST._serialized_start = 19533 + _COUNTWORKFLOWEXECUTIONSREQUEST._serialized_end = 19599 + _COUNTWORKFLOWEXECUTIONSRESPONSE._serialized_start = 19602 + _COUNTWORKFLOWEXECUTIONSRESPONSE._serialized_end = 19839 + _COUNTWORKFLOWEXECUTIONSRESPONSE_AGGREGATIONGROUP._serialized_start = 19751 + _COUNTWORKFLOWEXECUTIONSRESPONSE_AGGREGATIONGROUP._serialized_end = 19839 + _GETSEARCHATTRIBUTESREQUEST._serialized_start = 19841 + _GETSEARCHATTRIBUTESREQUEST._serialized_end = 19869 + _GETSEARCHATTRIBUTESRESPONSE._serialized_start = 19872 + _GETSEARCHATTRIBUTESRESPONSE._serialized_end = 20073 + _GETSEARCHATTRIBUTESRESPONSE_KEYSENTRY._serialized_start = 19989 + _GETSEARCHATTRIBUTESRESPONSE_KEYSENTRY._serialized_end = 20073 + _RESPONDQUERYTASKCOMPLETEDREQUEST._serialized_start = 20076 + _RESPONDQUERYTASKCOMPLETEDREQUEST._serialized_end = 20437 + _RESPONDQUERYTASKCOMPLETEDRESPONSE._serialized_start = 20439 + _RESPONDQUERYTASKCOMPLETEDRESPONSE._serialized_end = 20474 + _RESETSTICKYTASKQUEUEREQUEST._serialized_start = 20476 + _RESETSTICKYTASKQUEUEREQUEST._serialized_end = 20586 + _RESETSTICKYTASKQUEUERESPONSE._serialized_start = 20588 + _RESETSTICKYTASKQUEUERESPONSE._serialized_end = 20618 + _SHUTDOWNWORKERREQUEST._serialized_start = 20621 + _SHUTDOWNWORKERREQUEST._serialized_end = 20904 + _SHUTDOWNWORKERRESPONSE._serialized_start = 20906 + _SHUTDOWNWORKERRESPONSE._serialized_end = 20930 + _QUERYWORKFLOWREQUEST._serialized_start = 20933 + _QUERYWORKFLOWREQUEST._serialized_end = 21166 + _QUERYWORKFLOWRESPONSE._serialized_start = 21169 + _QUERYWORKFLOWRESPONSE._serialized_end = 21310 + _DESCRIBEWORKFLOWEXECUTIONREQUEST._serialized_start = 21312 + _DESCRIBEWORKFLOWEXECUTIONREQUEST._serialized_end = 21427 + _DESCRIBEWORKFLOWEXECUTIONRESPONSE._serialized_start = 21430 + _DESCRIBEWORKFLOWEXECUTIONRESPONSE._serialized_end = 22095 + _DESCRIBETASKQUEUEREQUEST._serialized_start = 22098 + _DESCRIBETASKQUEUEREQUEST._serialized_end = 22626 + _DESCRIBETASKQUEUERESPONSE._serialized_start = 22629 + _DESCRIBETASKQUEUERESPONSE._serialized_end = 23633 + _DESCRIBETASKQUEUERESPONSE_STATSBYPRIORITYKEYENTRY._serialized_start = 23313 + _DESCRIBETASKQUEUERESPONSE_STATSBYPRIORITYKEYENTRY._serialized_end = 23413 + _DESCRIBETASKQUEUERESPONSE_EFFECTIVERATELIMIT._serialized_start = 23415 + _DESCRIBETASKQUEUERESPONSE_EFFECTIVERATELIMIT._serialized_end = 23531 + _DESCRIBETASKQUEUERESPONSE_VERSIONSINFOENTRY._serialized_start = 23533 + _DESCRIBETASKQUEUERESPONSE_VERSIONSINFOENTRY._serialized_end = 23633 + _GETCLUSTERINFOREQUEST._serialized_start = 23635 + _GETCLUSTERINFOREQUEST._serialized_end = 23658 + _GETCLUSTERINFORESPONSE._serialized_start = 23661 + _GETCLUSTERINFORESPONSE._serialized_end = 24126 + _GETCLUSTERINFORESPONSE_SUPPORTEDCLIENTSENTRY._serialized_start = 24071 + _GETCLUSTERINFORESPONSE_SUPPORTEDCLIENTSENTRY._serialized_end = 24126 + _GETSYSTEMINFOREQUEST._serialized_start = 24128 + _GETSYSTEMINFOREQUEST._serialized_end = 24150 + _GETSYSTEMINFORESPONSE._serialized_start = 24153 + _GETSYSTEMINFORESPONSE._serialized_end = 24688 + _GETSYSTEMINFORESPONSE_CAPABILITIES._serialized_start = 24294 + _GETSYSTEMINFORESPONSE_CAPABILITIES._serialized_end = 24688 + _LISTTASKQUEUEPARTITIONSREQUEST._serialized_start = 24690 + _LISTTASKQUEUEPARTITIONSREQUEST._serialized_end = 24799 + _LISTTASKQUEUEPARTITIONSRESPONSE._serialized_start = 24802 + _LISTTASKQUEUEPARTITIONSRESPONSE._serialized_end = 25025 + _CREATESCHEDULEREQUEST._serialized_start = 25028 + _CREATESCHEDULEREQUEST._serialized_end = 25360 + _CREATESCHEDULERESPONSE._serialized_start = 25362 + _CREATESCHEDULERESPONSE._serialized_end = 25410 + _DESCRIBESCHEDULEREQUEST._serialized_start = 25412 + _DESCRIBESCHEDULEREQUEST._serialized_end = 25477 + _DESCRIBESCHEDULERESPONSE._serialized_start = 25480 + _DESCRIBESCHEDULERESPONSE._serialized_end = 25751 + _UPDATESCHEDULEREQUEST._serialized_start = 25754 + _UPDATESCHEDULEREQUEST._serialized_end = 26046 + _UPDATESCHEDULERESPONSE._serialized_start = 26048 + _UPDATESCHEDULERESPONSE._serialized_end = 26072 + _PATCHSCHEDULEREQUEST._serialized_start = 26075 + _PATCHSCHEDULEREQUEST._serialized_end = 26231 + _PATCHSCHEDULERESPONSE._serialized_start = 26233 + _PATCHSCHEDULERESPONSE._serialized_end = 26256 + _LISTSCHEDULEMATCHINGTIMESREQUEST._serialized_start = 26259 + _LISTSCHEDULEMATCHINGTIMESREQUEST._serialized_end = 26427 + _LISTSCHEDULEMATCHINGTIMESRESPONSE._serialized_start = 26429 + _LISTSCHEDULEMATCHINGTIMESRESPONSE._serialized_end = 26512 + _DELETESCHEDULEREQUEST._serialized_start = 26514 + _DELETESCHEDULEREQUEST._serialized_end = 26595 + _DELETESCHEDULERESPONSE._serialized_start = 26597 + _DELETESCHEDULERESPONSE._serialized_end = 26621 + _LISTSCHEDULESREQUEST._serialized_start = 26623 + _LISTSCHEDULESREQUEST._serialized_end = 26731 + _LISTSCHEDULESRESPONSE._serialized_start = 26733 + _LISTSCHEDULESRESPONSE._serialized_end = 26845 + _COUNTSCHEDULESREQUEST._serialized_start = 26847 + _COUNTSCHEDULESREQUEST._serialized_end = 26904 + _COUNTSCHEDULESRESPONSE._serialized_start = 26907 + _COUNTSCHEDULESRESPONSE._serialized_end = 27126 + _COUNTSCHEDULESRESPONSE_AGGREGATIONGROUP._serialized_start = 19751 + _COUNTSCHEDULESRESPONSE_AGGREGATIONGROUP._serialized_end = 19839 + _UPDATEWORKERBUILDIDCOMPATIBILITYREQUEST._serialized_start = 27129 + _UPDATEWORKERBUILDIDCOMPATIBILITYREQUEST._serialized_end = 27775 + _UPDATEWORKERBUILDIDCOMPATIBILITYREQUEST_ADDNEWCOMPATIBLEVERSION._serialized_start = 27576 _UPDATEWORKERBUILDIDCOMPATIBILITYREQUEST_ADDNEWCOMPATIBLEVERSION._serialized_end = ( - 27615 + 27687 ) - _UPDATEWORKERBUILDIDCOMPATIBILITYREQUEST_MERGESETS._serialized_start = 27617 - _UPDATEWORKERBUILDIDCOMPATIBILITYREQUEST_MERGESETS._serialized_end = 27690 - _UPDATEWORKERBUILDIDCOMPATIBILITYRESPONSE._serialized_start = 27705 - _UPDATEWORKERBUILDIDCOMPATIBILITYRESPONSE._serialized_end = 27769 - _GETWORKERBUILDIDCOMPATIBILITYREQUEST._serialized_start = 27771 - _GETWORKERBUILDIDCOMPATIBILITYREQUEST._serialized_end = 27866 - _GETWORKERBUILDIDCOMPATIBILITYRESPONSE._serialized_start = 27868 - _GETWORKERBUILDIDCOMPATIBILITYRESPONSE._serialized_end = 27984 - _UPDATEWORKERVERSIONINGRULESREQUEST._serialized_start = 27987 - _UPDATEWORKERVERSIONINGRULESREQUEST._serialized_end = 29704 - _UPDATEWORKERVERSIONINGRULESREQUEST_INSERTBUILDIDASSIGNMENTRULE._serialized_start = 29039 + _UPDATEWORKERBUILDIDCOMPATIBILITYREQUEST_MERGESETS._serialized_start = 27689 + _UPDATEWORKERBUILDIDCOMPATIBILITYREQUEST_MERGESETS._serialized_end = 27762 + _UPDATEWORKERBUILDIDCOMPATIBILITYRESPONSE._serialized_start = 27777 + _UPDATEWORKERBUILDIDCOMPATIBILITYRESPONSE._serialized_end = 27841 + _GETWORKERBUILDIDCOMPATIBILITYREQUEST._serialized_start = 27843 + _GETWORKERBUILDIDCOMPATIBILITYREQUEST._serialized_end = 27938 + _GETWORKERBUILDIDCOMPATIBILITYRESPONSE._serialized_start = 27940 + _GETWORKERBUILDIDCOMPATIBILITYRESPONSE._serialized_end = 28056 + _UPDATEWORKERVERSIONINGRULESREQUEST._serialized_start = 28059 + _UPDATEWORKERVERSIONINGRULESREQUEST._serialized_end = 29776 + _UPDATEWORKERVERSIONINGRULESREQUEST_INSERTBUILDIDASSIGNMENTRULE._serialized_start = 29111 _UPDATEWORKERVERSIONINGRULESREQUEST_INSERTBUILDIDASSIGNMENTRULE._serialized_end = ( - 29152 + 29224 ) - _UPDATEWORKERVERSIONINGRULESREQUEST_REPLACEBUILDIDASSIGNMENTRULE._serialized_start = 29155 + _UPDATEWORKERVERSIONINGRULESREQUEST_REPLACEBUILDIDASSIGNMENTRULE._serialized_start = 29227 _UPDATEWORKERVERSIONINGRULESREQUEST_REPLACEBUILDIDASSIGNMENTRULE._serialized_end = ( - 29284 + 29356 ) - _UPDATEWORKERVERSIONINGRULESREQUEST_DELETEBUILDIDASSIGNMENTRULE._serialized_start = 29286 + _UPDATEWORKERVERSIONINGRULESREQUEST_DELETEBUILDIDASSIGNMENTRULE._serialized_start = 29358 _UPDATEWORKERVERSIONINGRULESREQUEST_DELETEBUILDIDASSIGNMENTRULE._serialized_end = ( - 29350 + 29422 ) - _UPDATEWORKERVERSIONINGRULESREQUEST_ADDCOMPATIBLEBUILDIDREDIRECTRULE._serialized_start = 29352 - _UPDATEWORKERVERSIONINGRULESREQUEST_ADDCOMPATIBLEBUILDIDREDIRECTRULE._serialized_end = 29458 - _UPDATEWORKERVERSIONINGRULESREQUEST_REPLACECOMPATIBLEBUILDIDREDIRECTRULE._serialized_start = 29460 - _UPDATEWORKERVERSIONINGRULESREQUEST_REPLACECOMPATIBLEBUILDIDREDIRECTRULE._serialized_end = 29570 - _UPDATEWORKERVERSIONINGRULESREQUEST_DELETECOMPATIBLEBUILDIDREDIRECTRULE._serialized_start = 29572 - _UPDATEWORKERVERSIONINGRULESREQUEST_DELETECOMPATIBLEBUILDIDREDIRECTRULE._serialized_end = 29634 - _UPDATEWORKERVERSIONINGRULESREQUEST_COMMITBUILDID._serialized_start = 29636 - _UPDATEWORKERVERSIONINGRULESREQUEST_COMMITBUILDID._serialized_end = 29691 - _UPDATEWORKERVERSIONINGRULESRESPONSE._serialized_start = 29707 - _UPDATEWORKERVERSIONINGRULESRESPONSE._serialized_end = 29959 - _GETWORKERVERSIONINGRULESREQUEST._serialized_start = 29961 - _GETWORKERVERSIONINGRULESREQUEST._serialized_end = 30033 - _GETWORKERVERSIONINGRULESRESPONSE._serialized_start = 30036 - _GETWORKERVERSIONINGRULESRESPONSE._serialized_end = 30285 - _GETWORKERTASKREACHABILITYREQUEST._serialized_start = 30288 - _GETWORKERTASKREACHABILITYREQUEST._serialized_end = 30444 - _GETWORKERTASKREACHABILITYRESPONSE._serialized_start = 30446 - _GETWORKERTASKREACHABILITYRESPONSE._serialized_end = 30560 - _UPDATEWORKFLOWEXECUTIONREQUEST._serialized_start = 30563 - _UPDATEWORKFLOWEXECUTIONREQUEST._serialized_end = 30824 - _UPDATEWORKFLOWEXECUTIONRESPONSE._serialized_start = 30827 - _UPDATEWORKFLOWEXECUTIONRESPONSE._serialized_end = 31042 - _STARTBATCHOPERATIONREQUEST._serialized_start = 31045 - _STARTBATCHOPERATIONREQUEST._serialized_end = 32057 - _STARTBATCHOPERATIONRESPONSE._serialized_start = 32059 - _STARTBATCHOPERATIONRESPONSE._serialized_end = 32088 - _STOPBATCHOPERATIONREQUEST._serialized_start = 32090 - _STOPBATCHOPERATIONREQUEST._serialized_end = 32186 - _STOPBATCHOPERATIONRESPONSE._serialized_start = 32188 - _STOPBATCHOPERATIONRESPONSE._serialized_end = 32216 - _DESCRIBEBATCHOPERATIONREQUEST._serialized_start = 32218 - _DESCRIBEBATCHOPERATIONREQUEST._serialized_end = 32284 - _DESCRIBEBATCHOPERATIONRESPONSE._serialized_start = 32287 - _DESCRIBEBATCHOPERATIONRESPONSE._serialized_end = 32689 - _LISTBATCHOPERATIONSREQUEST._serialized_start = 32691 - _LISTBATCHOPERATIONSREQUEST._serialized_end = 32782 - _LISTBATCHOPERATIONSRESPONSE._serialized_start = 32784 - _LISTBATCHOPERATIONSRESPONSE._serialized_end = 32905 - _POLLWORKFLOWEXECUTIONUPDATEREQUEST._serialized_start = 32908 - _POLLWORKFLOWEXECUTIONUPDATEREQUEST._serialized_end = 33093 - _POLLWORKFLOWEXECUTIONUPDATERESPONSE._serialized_start = 33096 - _POLLWORKFLOWEXECUTIONUPDATERESPONSE._serialized_end = 33315 - _POLLNEXUSTASKQUEUEREQUEST._serialized_start = 33318 - _POLLNEXUSTASKQUEUEREQUEST._serialized_end = 33734 - _POLLNEXUSTASKQUEUERESPONSE._serialized_start = 33737 - _POLLNEXUSTASKQUEUERESPONSE._serialized_end = 34014 - _RESPONDNEXUSTASKCOMPLETEDREQUEST._serialized_start = 34017 - _RESPONDNEXUSTASKCOMPLETEDREQUEST._serialized_end = 34184 - _RESPONDNEXUSTASKCOMPLETEDRESPONSE._serialized_start = 34186 - _RESPONDNEXUSTASKCOMPLETEDRESPONSE._serialized_end = 34221 - _RESPONDNEXUSTASKFAILEDREQUEST._serialized_start = 34224 - _RESPONDNEXUSTASKFAILEDREQUEST._serialized_end = 34444 - _RESPONDNEXUSTASKFAILEDRESPONSE._serialized_start = 34446 - _RESPONDNEXUSTASKFAILEDRESPONSE._serialized_end = 34478 - _EXECUTEMULTIOPERATIONREQUEST._serialized_start = 34481 - _EXECUTEMULTIOPERATIONREQUEST._serialized_end = 34853 - _EXECUTEMULTIOPERATIONREQUEST_OPERATION._serialized_start = 34647 - _EXECUTEMULTIOPERATIONREQUEST_OPERATION._serialized_end = 34853 - _EXECUTEMULTIOPERATIONRESPONSE._serialized_start = 34856 - _EXECUTEMULTIOPERATIONRESPONSE._serialized_end = 35188 - _EXECUTEMULTIOPERATIONRESPONSE_RESPONSE._serialized_start = 34982 - _EXECUTEMULTIOPERATIONRESPONSE_RESPONSE._serialized_end = 35188 - _UPDATEACTIVITYOPTIONSREQUEST._serialized_start = 35191 - _UPDATEACTIVITYOPTIONSREQUEST._serialized_end = 35527 - _UPDATEACTIVITYEXECUTIONOPTIONSREQUEST._serialized_start = 35530 - _UPDATEACTIVITYEXECUTIONOPTIONSREQUEST._serialized_end = 35829 - _UPDATEACTIVITYOPTIONSRESPONSE._serialized_start = 35831 - _UPDATEACTIVITYOPTIONSRESPONSE._serialized_end = 35931 - _UPDATEACTIVITYEXECUTIONOPTIONSRESPONSE._serialized_start = 35933 - _UPDATEACTIVITYEXECUTIONOPTIONSRESPONSE._serialized_end = 36042 - _PAUSEACTIVITYREQUEST._serialized_start = 36045 - _PAUSEACTIVITYREQUEST._serialized_end = 36244 - _PAUSEACTIVITYEXECUTIONREQUEST._serialized_start = 36247 - _PAUSEACTIVITYEXECUTIONREQUEST._serialized_end = 36430 - _PAUSEACTIVITYRESPONSE._serialized_start = 36432 - _PAUSEACTIVITYRESPONSE._serialized_end = 36455 - _PAUSEACTIVITYEXECUTIONRESPONSE._serialized_start = 36457 - _PAUSEACTIVITYEXECUTIONRESPONSE._serialized_end = 36489 - _UNPAUSEACTIVITYREQUEST._serialized_start = 36492 - _UNPAUSEACTIVITYREQUEST._serialized_end = 36772 - _UNPAUSEACTIVITYEXECUTIONREQUEST._serialized_start = 36775 - _UNPAUSEACTIVITYEXECUTIONREQUEST._serialized_end = 37032 - _UNPAUSEACTIVITYRESPONSE._serialized_start = 37034 - _UNPAUSEACTIVITYRESPONSE._serialized_end = 37059 - _UNPAUSEACTIVITYEXECUTIONRESPONSE._serialized_start = 37061 - _UNPAUSEACTIVITYEXECUTIONRESPONSE._serialized_end = 37095 - _RESETACTIVITYREQUEST._serialized_start = 37098 - _RESETACTIVITYREQUEST._serialized_end = 37405 - _RESETACTIVITYEXECUTIONREQUEST._serialized_start = 37408 - _RESETACTIVITYEXECUTIONREQUEST._serialized_end = 37678 - _RESETACTIVITYRESPONSE._serialized_start = 37680 - _RESETACTIVITYRESPONSE._serialized_end = 37703 - _RESETACTIVITYEXECUTIONRESPONSE._serialized_start = 37705 - _RESETACTIVITYEXECUTIONRESPONSE._serialized_end = 37737 - _UPDATEWORKFLOWEXECUTIONOPTIONSREQUEST._serialized_start = 37740 - _UPDATEWORKFLOWEXECUTIONOPTIONSREQUEST._serialized_end = 38024 - _UPDATEWORKFLOWEXECUTIONOPTIONSRESPONSE._serialized_start = 38027 - _UPDATEWORKFLOWEXECUTIONOPTIONSRESPONSE._serialized_end = 38155 - _DESCRIBEDEPLOYMENTREQUEST._serialized_start = 38157 - _DESCRIBEDEPLOYMENTREQUEST._serialized_end = 38263 - _DESCRIBEDEPLOYMENTRESPONSE._serialized_start = 38265 - _DESCRIBEDEPLOYMENTRESPONSE._serialized_end = 38362 - _DESCRIBEWORKERDEPLOYMENTVERSIONREQUEST._serialized_start = 38365 - _DESCRIBEWORKERDEPLOYMENTVERSIONREQUEST._serialized_end = 38559 - _DESCRIBEWORKERDEPLOYMENTVERSIONRESPONSE._serialized_start = 38562 - _DESCRIBEWORKERDEPLOYMENTVERSIONRESPONSE._serialized_end = 39214 - _DESCRIBEWORKERDEPLOYMENTVERSIONRESPONSE_VERSIONTASKQUEUE._serialized_start = 38823 - _DESCRIBEWORKERDEPLOYMENTVERSIONRESPONSE_VERSIONTASKQUEUE._serialized_end = 39214 - _DESCRIBEWORKERDEPLOYMENTVERSIONRESPONSE_VERSIONTASKQUEUE_STATSBYPRIORITYKEYENTRY._serialized_start = 23241 - _DESCRIBEWORKERDEPLOYMENTVERSIONRESPONSE_VERSIONTASKQUEUE_STATSBYPRIORITYKEYENTRY._serialized_end = 23341 - _DESCRIBEWORKERDEPLOYMENTREQUEST._serialized_start = 39216 - _DESCRIBEWORKERDEPLOYMENTREQUEST._serialized_end = 39293 - _DESCRIBEWORKERDEPLOYMENTRESPONSE._serialized_start = 39296 - _DESCRIBEWORKERDEPLOYMENTRESPONSE._serialized_end = 39436 - _LISTDEPLOYMENTSREQUEST._serialized_start = 39438 - _LISTDEPLOYMENTSREQUEST._serialized_end = 39546 - _LISTDEPLOYMENTSRESPONSE._serialized_start = 39548 - _LISTDEPLOYMENTSRESPONSE._serialized_end = 39667 - _SETCURRENTDEPLOYMENTREQUEST._serialized_start = 39670 - _SETCURRENTDEPLOYMENTREQUEST._serialized_end = 39875 - _SETCURRENTDEPLOYMENTRESPONSE._serialized_start = 39878 - _SETCURRENTDEPLOYMENTRESPONSE._serialized_end = 40063 - _SETWORKERDEPLOYMENTCURRENTVERSIONREQUEST._serialized_start = 40066 - _SETWORKERDEPLOYMENTCURRENTVERSIONREQUEST._serialized_end = 40295 - _SETWORKERDEPLOYMENTCURRENTVERSIONRESPONSE._serialized_start = 40298 - _SETWORKERDEPLOYMENTCURRENTVERSIONRESPONSE._serialized_end = 40489 - _SETWORKERDEPLOYMENTRAMPINGVERSIONREQUEST._serialized_start = 40492 - _SETWORKERDEPLOYMENTRAMPINGVERSIONREQUEST._serialized_end = 40741 - _SETWORKERDEPLOYMENTRAMPINGVERSIONRESPONSE._serialized_start = 40744 - _SETWORKERDEPLOYMENTRAMPINGVERSIONRESPONSE._serialized_end = 40968 - _CREATEWORKERDEPLOYMENTREQUEST._serialized_start = 40970 - _CREATEWORKERDEPLOYMENTREQUEST._serialized_end = 41083 - _CREATEWORKERDEPLOYMENTRESPONSE._serialized_start = 41085 - _CREATEWORKERDEPLOYMENTRESPONSE._serialized_end = 41141 - _LISTWORKERDEPLOYMENTSREQUEST._serialized_start = 41143 - _LISTWORKERDEPLOYMENTSREQUEST._serialized_end = 41236 - _LISTWORKERDEPLOYMENTSRESPONSE._serialized_start = 41239 - _LISTWORKERDEPLOYMENTSRESPONSE._serialized_end = 41910 - _LISTWORKERDEPLOYMENTSRESPONSE_WORKERDEPLOYMENTSUMMARY._serialized_start = 41414 - _LISTWORKERDEPLOYMENTSRESPONSE_WORKERDEPLOYMENTSUMMARY._serialized_end = 41910 - _CREATEWORKERDEPLOYMENTVERSIONREQUEST._serialized_start = 41913 - _CREATEWORKERDEPLOYMENTVERSIONREQUEST._serialized_end = 42153 - _CREATEWORKERDEPLOYMENTVERSIONRESPONSE._serialized_start = 42155 - _CREATEWORKERDEPLOYMENTVERSIONRESPONSE._serialized_end = 42194 - _DELETEWORKERDEPLOYMENTVERSIONREQUEST._serialized_start = 42197 - _DELETEWORKERDEPLOYMENTVERSIONREQUEST._serialized_end = 42397 - _DELETEWORKERDEPLOYMENTVERSIONRESPONSE._serialized_start = 42399 - _DELETEWORKERDEPLOYMENTVERSIONRESPONSE._serialized_end = 42438 - _DELETEWORKERDEPLOYMENTREQUEST._serialized_start = 42440 - _DELETEWORKERDEPLOYMENTREQUEST._serialized_end = 42533 - _DELETEWORKERDEPLOYMENTRESPONSE._serialized_start = 42535 - _DELETEWORKERDEPLOYMENTRESPONSE._serialized_end = 42567 - _UPDATEWORKERDEPLOYMENTVERSIONCOMPUTECONFIGREQUEST._serialized_start = 42570 - _UPDATEWORKERDEPLOYMENTVERSIONCOMPUTECONFIGREQUEST._serialized_end = 43086 - _UPDATEWORKERDEPLOYMENTVERSIONCOMPUTECONFIGREQUEST_COMPUTECONFIGSCALINGGROUPSENTRY._serialized_start = 42963 - _UPDATEWORKERDEPLOYMENTVERSIONCOMPUTECONFIGREQUEST_COMPUTECONFIGSCALINGGROUPSENTRY._serialized_end = 43086 - _UPDATEWORKERDEPLOYMENTVERSIONCOMPUTECONFIGRESPONSE._serialized_start = 43088 - _UPDATEWORKERDEPLOYMENTVERSIONCOMPUTECONFIGRESPONSE._serialized_end = 43140 - _VALIDATEWORKERDEPLOYMENTVERSIONCOMPUTECONFIGREQUEST._serialized_start = 43143 - _VALIDATEWORKERDEPLOYMENTVERSIONCOMPUTECONFIGREQUEST._serialized_end = 43643 - _VALIDATEWORKERDEPLOYMENTVERSIONCOMPUTECONFIGREQUEST_COMPUTECONFIGSCALINGGROUPSENTRY._serialized_start = 42963 - _VALIDATEWORKERDEPLOYMENTVERSIONCOMPUTECONFIGREQUEST_COMPUTECONFIGSCALINGGROUPSENTRY._serialized_end = 43086 - _VALIDATEWORKERDEPLOYMENTVERSIONCOMPUTECONFIGRESPONSE._serialized_start = 43645 - _VALIDATEWORKERDEPLOYMENTVERSIONCOMPUTECONFIGRESPONSE._serialized_end = 43699 - _UPDATEWORKERDEPLOYMENTVERSIONMETADATAREQUEST._serialized_start = 43702 - _UPDATEWORKERDEPLOYMENTVERSIONMETADATAREQUEST._serialized_end = 44120 - _UPDATEWORKERDEPLOYMENTVERSIONMETADATAREQUEST_UPSERTENTRIESENTRY._serialized_start = 44035 + _UPDATEWORKERVERSIONINGRULESREQUEST_ADDCOMPATIBLEBUILDIDREDIRECTRULE._serialized_start = 29424 + _UPDATEWORKERVERSIONINGRULESREQUEST_ADDCOMPATIBLEBUILDIDREDIRECTRULE._serialized_end = 29530 + _UPDATEWORKERVERSIONINGRULESREQUEST_REPLACECOMPATIBLEBUILDIDREDIRECTRULE._serialized_start = 29532 + _UPDATEWORKERVERSIONINGRULESREQUEST_REPLACECOMPATIBLEBUILDIDREDIRECTRULE._serialized_end = 29642 + _UPDATEWORKERVERSIONINGRULESREQUEST_DELETECOMPATIBLEBUILDIDREDIRECTRULE._serialized_start = 29644 + _UPDATEWORKERVERSIONINGRULESREQUEST_DELETECOMPATIBLEBUILDIDREDIRECTRULE._serialized_end = 29706 + _UPDATEWORKERVERSIONINGRULESREQUEST_COMMITBUILDID._serialized_start = 29708 + _UPDATEWORKERVERSIONINGRULESREQUEST_COMMITBUILDID._serialized_end = 29763 + _UPDATEWORKERVERSIONINGRULESRESPONSE._serialized_start = 29779 + _UPDATEWORKERVERSIONINGRULESRESPONSE._serialized_end = 30031 + _GETWORKERVERSIONINGRULESREQUEST._serialized_start = 30033 + _GETWORKERVERSIONINGRULESREQUEST._serialized_end = 30105 + _GETWORKERVERSIONINGRULESRESPONSE._serialized_start = 30108 + _GETWORKERVERSIONINGRULESRESPONSE._serialized_end = 30357 + _GETWORKERTASKREACHABILITYREQUEST._serialized_start = 30360 + _GETWORKERTASKREACHABILITYREQUEST._serialized_end = 30516 + _GETWORKERTASKREACHABILITYRESPONSE._serialized_start = 30518 + _GETWORKERTASKREACHABILITYRESPONSE._serialized_end = 30632 + _UPDATEWORKFLOWEXECUTIONREQUEST._serialized_start = 30635 + _UPDATEWORKFLOWEXECUTIONREQUEST._serialized_end = 30896 + _UPDATEWORKFLOWEXECUTIONRESPONSE._serialized_start = 30899 + _UPDATEWORKFLOWEXECUTIONRESPONSE._serialized_end = 31158 + _STARTBATCHOPERATIONREQUEST._serialized_start = 31161 + _STARTBATCHOPERATIONREQUEST._serialized_end = 32173 + _STARTBATCHOPERATIONRESPONSE._serialized_start = 32175 + _STARTBATCHOPERATIONRESPONSE._serialized_end = 32204 + _STOPBATCHOPERATIONREQUEST._serialized_start = 32206 + _STOPBATCHOPERATIONREQUEST._serialized_end = 32302 + _STOPBATCHOPERATIONRESPONSE._serialized_start = 32304 + _STOPBATCHOPERATIONRESPONSE._serialized_end = 32332 + _DESCRIBEBATCHOPERATIONREQUEST._serialized_start = 32334 + _DESCRIBEBATCHOPERATIONREQUEST._serialized_end = 32400 + _DESCRIBEBATCHOPERATIONRESPONSE._serialized_start = 32403 + _DESCRIBEBATCHOPERATIONRESPONSE._serialized_end = 32805 + _LISTBATCHOPERATIONSREQUEST._serialized_start = 32807 + _LISTBATCHOPERATIONSREQUEST._serialized_end = 32898 + _LISTBATCHOPERATIONSRESPONSE._serialized_start = 32900 + _LISTBATCHOPERATIONSRESPONSE._serialized_end = 33021 + _POLLWORKFLOWEXECUTIONUPDATEREQUEST._serialized_start = 33024 + _POLLWORKFLOWEXECUTIONUPDATEREQUEST._serialized_end = 33209 + _POLLWORKFLOWEXECUTIONUPDATERESPONSE._serialized_start = 33212 + _POLLWORKFLOWEXECUTIONUPDATERESPONSE._serialized_end = 33431 + _POLLNEXUSTASKQUEUEREQUEST._serialized_start = 33434 + _POLLNEXUSTASKQUEUEREQUEST._serialized_end = 33850 + _POLLNEXUSTASKQUEUERESPONSE._serialized_start = 33853 + _POLLNEXUSTASKQUEUERESPONSE._serialized_end = 34130 + _RESPONDNEXUSTASKCOMPLETEDREQUEST._serialized_start = 34133 + _RESPONDNEXUSTASKCOMPLETEDREQUEST._serialized_end = 34300 + _RESPONDNEXUSTASKCOMPLETEDRESPONSE._serialized_start = 34302 + _RESPONDNEXUSTASKCOMPLETEDRESPONSE._serialized_end = 34337 + _RESPONDNEXUSTASKFAILEDREQUEST._serialized_start = 34340 + _RESPONDNEXUSTASKFAILEDREQUEST._serialized_end = 34560 + _RESPONDNEXUSTASKFAILEDRESPONSE._serialized_start = 34562 + _RESPONDNEXUSTASKFAILEDRESPONSE._serialized_end = 34594 + _EXECUTEMULTIOPERATIONREQUEST._serialized_start = 34597 + _EXECUTEMULTIOPERATIONREQUEST._serialized_end = 34969 + _EXECUTEMULTIOPERATIONREQUEST_OPERATION._serialized_start = 34763 + _EXECUTEMULTIOPERATIONREQUEST_OPERATION._serialized_end = 34969 + _EXECUTEMULTIOPERATIONRESPONSE._serialized_start = 34972 + _EXECUTEMULTIOPERATIONRESPONSE._serialized_end = 35304 + _EXECUTEMULTIOPERATIONRESPONSE_RESPONSE._serialized_start = 35098 + _EXECUTEMULTIOPERATIONRESPONSE_RESPONSE._serialized_end = 35304 + _UPDATEACTIVITYOPTIONSREQUEST._serialized_start = 35307 + _UPDATEACTIVITYOPTIONSREQUEST._serialized_end = 35643 + _UPDATEACTIVITYEXECUTIONOPTIONSREQUEST._serialized_start = 35646 + _UPDATEACTIVITYEXECUTIONOPTIONSREQUEST._serialized_end = 35945 + _UPDATEACTIVITYOPTIONSRESPONSE._serialized_start = 35947 + _UPDATEACTIVITYOPTIONSRESPONSE._serialized_end = 36047 + _UPDATEACTIVITYEXECUTIONOPTIONSRESPONSE._serialized_start = 36049 + _UPDATEACTIVITYEXECUTIONOPTIONSRESPONSE._serialized_end = 36158 + _PAUSEACTIVITYREQUEST._serialized_start = 36161 + _PAUSEACTIVITYREQUEST._serialized_end = 36360 + _PAUSEACTIVITYEXECUTIONREQUEST._serialized_start = 36363 + _PAUSEACTIVITYEXECUTIONREQUEST._serialized_end = 36546 + _PAUSEACTIVITYRESPONSE._serialized_start = 36548 + _PAUSEACTIVITYRESPONSE._serialized_end = 36571 + _PAUSEACTIVITYEXECUTIONRESPONSE._serialized_start = 36573 + _PAUSEACTIVITYEXECUTIONRESPONSE._serialized_end = 36605 + _UNPAUSEACTIVITYREQUEST._serialized_start = 36608 + _UNPAUSEACTIVITYREQUEST._serialized_end = 36888 + _UNPAUSEACTIVITYEXECUTIONREQUEST._serialized_start = 36891 + _UNPAUSEACTIVITYEXECUTIONREQUEST._serialized_end = 37148 + _UNPAUSEACTIVITYRESPONSE._serialized_start = 37150 + _UNPAUSEACTIVITYRESPONSE._serialized_end = 37175 + _UNPAUSEACTIVITYEXECUTIONRESPONSE._serialized_start = 37177 + _UNPAUSEACTIVITYEXECUTIONRESPONSE._serialized_end = 37211 + _RESETACTIVITYREQUEST._serialized_start = 37214 + _RESETACTIVITYREQUEST._serialized_end = 37521 + _RESETACTIVITYEXECUTIONREQUEST._serialized_start = 37524 + _RESETACTIVITYEXECUTIONREQUEST._serialized_end = 37794 + _RESETACTIVITYRESPONSE._serialized_start = 37796 + _RESETACTIVITYRESPONSE._serialized_end = 37819 + _RESETACTIVITYEXECUTIONRESPONSE._serialized_start = 37821 + _RESETACTIVITYEXECUTIONRESPONSE._serialized_end = 37853 + _UPDATEWORKFLOWEXECUTIONOPTIONSREQUEST._serialized_start = 37856 + _UPDATEWORKFLOWEXECUTIONOPTIONSREQUEST._serialized_end = 38140 + _UPDATEWORKFLOWEXECUTIONOPTIONSRESPONSE._serialized_start = 38143 + _UPDATEWORKFLOWEXECUTIONOPTIONSRESPONSE._serialized_end = 38271 + _DESCRIBEDEPLOYMENTREQUEST._serialized_start = 38273 + _DESCRIBEDEPLOYMENTREQUEST._serialized_end = 38379 + _DESCRIBEDEPLOYMENTRESPONSE._serialized_start = 38381 + _DESCRIBEDEPLOYMENTRESPONSE._serialized_end = 38478 + _DESCRIBEWORKERDEPLOYMENTVERSIONREQUEST._serialized_start = 38481 + _DESCRIBEWORKERDEPLOYMENTVERSIONREQUEST._serialized_end = 38675 + _DESCRIBEWORKERDEPLOYMENTVERSIONRESPONSE._serialized_start = 38678 + _DESCRIBEWORKERDEPLOYMENTVERSIONRESPONSE._serialized_end = 39330 + _DESCRIBEWORKERDEPLOYMENTVERSIONRESPONSE_VERSIONTASKQUEUE._serialized_start = 38939 + _DESCRIBEWORKERDEPLOYMENTVERSIONRESPONSE_VERSIONTASKQUEUE._serialized_end = 39330 + _DESCRIBEWORKERDEPLOYMENTVERSIONRESPONSE_VERSIONTASKQUEUE_STATSBYPRIORITYKEYENTRY._serialized_start = 23313 + _DESCRIBEWORKERDEPLOYMENTVERSIONRESPONSE_VERSIONTASKQUEUE_STATSBYPRIORITYKEYENTRY._serialized_end = 23413 + _DESCRIBEWORKERDEPLOYMENTREQUEST._serialized_start = 39332 + _DESCRIBEWORKERDEPLOYMENTREQUEST._serialized_end = 39409 + _DESCRIBEWORKERDEPLOYMENTRESPONSE._serialized_start = 39412 + _DESCRIBEWORKERDEPLOYMENTRESPONSE._serialized_end = 39552 + _LISTDEPLOYMENTSREQUEST._serialized_start = 39554 + _LISTDEPLOYMENTSREQUEST._serialized_end = 39662 + _LISTDEPLOYMENTSRESPONSE._serialized_start = 39664 + _LISTDEPLOYMENTSRESPONSE._serialized_end = 39783 + _SETCURRENTDEPLOYMENTREQUEST._serialized_start = 39786 + _SETCURRENTDEPLOYMENTREQUEST._serialized_end = 39991 + _SETCURRENTDEPLOYMENTRESPONSE._serialized_start = 39994 + _SETCURRENTDEPLOYMENTRESPONSE._serialized_end = 40179 + _SETWORKERDEPLOYMENTCURRENTVERSIONREQUEST._serialized_start = 40182 + _SETWORKERDEPLOYMENTCURRENTVERSIONREQUEST._serialized_end = 40411 + _SETWORKERDEPLOYMENTCURRENTVERSIONRESPONSE._serialized_start = 40414 + _SETWORKERDEPLOYMENTCURRENTVERSIONRESPONSE._serialized_end = 40605 + _SETWORKERDEPLOYMENTRAMPINGVERSIONREQUEST._serialized_start = 40608 + _SETWORKERDEPLOYMENTRAMPINGVERSIONREQUEST._serialized_end = 40857 + _SETWORKERDEPLOYMENTRAMPINGVERSIONRESPONSE._serialized_start = 40860 + _SETWORKERDEPLOYMENTRAMPINGVERSIONRESPONSE._serialized_end = 41084 + _CREATEWORKERDEPLOYMENTREQUEST._serialized_start = 41086 + _CREATEWORKERDEPLOYMENTREQUEST._serialized_end = 41199 + _CREATEWORKERDEPLOYMENTRESPONSE._serialized_start = 41201 + _CREATEWORKERDEPLOYMENTRESPONSE._serialized_end = 41257 + _LISTWORKERDEPLOYMENTSREQUEST._serialized_start = 41259 + _LISTWORKERDEPLOYMENTSREQUEST._serialized_end = 41352 + _LISTWORKERDEPLOYMENTSRESPONSE._serialized_start = 41355 + _LISTWORKERDEPLOYMENTSRESPONSE._serialized_end = 42026 + _LISTWORKERDEPLOYMENTSRESPONSE_WORKERDEPLOYMENTSUMMARY._serialized_start = 41530 + _LISTWORKERDEPLOYMENTSRESPONSE_WORKERDEPLOYMENTSUMMARY._serialized_end = 42026 + _CREATEWORKERDEPLOYMENTVERSIONREQUEST._serialized_start = 42029 + _CREATEWORKERDEPLOYMENTVERSIONREQUEST._serialized_end = 42269 + _CREATEWORKERDEPLOYMENTVERSIONRESPONSE._serialized_start = 42271 + _CREATEWORKERDEPLOYMENTVERSIONRESPONSE._serialized_end = 42310 + _DELETEWORKERDEPLOYMENTVERSIONREQUEST._serialized_start = 42313 + _DELETEWORKERDEPLOYMENTVERSIONREQUEST._serialized_end = 42513 + _DELETEWORKERDEPLOYMENTVERSIONRESPONSE._serialized_start = 42515 + _DELETEWORKERDEPLOYMENTVERSIONRESPONSE._serialized_end = 42554 + _DELETEWORKERDEPLOYMENTREQUEST._serialized_start = 42556 + _DELETEWORKERDEPLOYMENTREQUEST._serialized_end = 42649 + _DELETEWORKERDEPLOYMENTRESPONSE._serialized_start = 42651 + _DELETEWORKERDEPLOYMENTRESPONSE._serialized_end = 42683 + _UPDATEWORKERDEPLOYMENTVERSIONCOMPUTECONFIGREQUEST._serialized_start = 42686 + _UPDATEWORKERDEPLOYMENTVERSIONCOMPUTECONFIGREQUEST._serialized_end = 43202 + _UPDATEWORKERDEPLOYMENTVERSIONCOMPUTECONFIGREQUEST_COMPUTECONFIGSCALINGGROUPSENTRY._serialized_start = 43079 + _UPDATEWORKERDEPLOYMENTVERSIONCOMPUTECONFIGREQUEST_COMPUTECONFIGSCALINGGROUPSENTRY._serialized_end = 43202 + _UPDATEWORKERDEPLOYMENTVERSIONCOMPUTECONFIGRESPONSE._serialized_start = 43204 + _UPDATEWORKERDEPLOYMENTVERSIONCOMPUTECONFIGRESPONSE._serialized_end = 43256 + _VALIDATEWORKERDEPLOYMENTVERSIONCOMPUTECONFIGREQUEST._serialized_start = 43259 + _VALIDATEWORKERDEPLOYMENTVERSIONCOMPUTECONFIGREQUEST._serialized_end = 43759 + _VALIDATEWORKERDEPLOYMENTVERSIONCOMPUTECONFIGREQUEST_COMPUTECONFIGSCALINGGROUPSENTRY._serialized_start = 43079 + _VALIDATEWORKERDEPLOYMENTVERSIONCOMPUTECONFIGREQUEST_COMPUTECONFIGSCALINGGROUPSENTRY._serialized_end = 43202 + _VALIDATEWORKERDEPLOYMENTVERSIONCOMPUTECONFIGRESPONSE._serialized_start = 43761 + _VALIDATEWORKERDEPLOYMENTVERSIONCOMPUTECONFIGRESPONSE._serialized_end = 43815 + _UPDATEWORKERDEPLOYMENTVERSIONMETADATAREQUEST._serialized_start = 43818 + _UPDATEWORKERDEPLOYMENTVERSIONMETADATAREQUEST._serialized_end = 44236 + _UPDATEWORKERDEPLOYMENTVERSIONMETADATAREQUEST_UPSERTENTRIESENTRY._serialized_start = 44151 _UPDATEWORKERDEPLOYMENTVERSIONMETADATAREQUEST_UPSERTENTRIESENTRY._serialized_end = ( - 44120 + 44236 ) - _UPDATEWORKERDEPLOYMENTVERSIONMETADATARESPONSE._serialized_start = 44122 - _UPDATEWORKERDEPLOYMENTVERSIONMETADATARESPONSE._serialized_end = 44232 - _SETWORKERDEPLOYMENTMANAGERREQUEST._serialized_start = 44235 - _SETWORKERDEPLOYMENTMANAGERREQUEST._serialized_end = 44424 - _SETWORKERDEPLOYMENTMANAGERRESPONSE._serialized_start = 44426 - _SETWORKERDEPLOYMENTMANAGERRESPONSE._serialized_end = 44525 - _GETCURRENTDEPLOYMENTREQUEST._serialized_start = 44527 - _GETCURRENTDEPLOYMENTREQUEST._serialized_end = 44596 - _GETCURRENTDEPLOYMENTRESPONSE._serialized_start = 44598 - _GETCURRENTDEPLOYMENTRESPONSE._serialized_end = 44705 - _GETDEPLOYMENTREACHABILITYREQUEST._serialized_start = 44707 - _GETDEPLOYMENTREACHABILITYREQUEST._serialized_end = 44820 - _GETDEPLOYMENTREACHABILITYRESPONSE._serialized_start = 44823 - _GETDEPLOYMENTREACHABILITYRESPONSE._serialized_end = 45050 - _CREATEWORKFLOWRULEREQUEST._serialized_start = 45053 - _CREATEWORKFLOWRULEREQUEST._serialized_end = 45233 - _CREATEWORKFLOWRULERESPONSE._serialized_start = 45235 - _CREATEWORKFLOWRULERESPONSE._serialized_end = 45330 - _DESCRIBEWORKFLOWRULEREQUEST._serialized_start = 45332 - _DESCRIBEWORKFLOWRULEREQUEST._serialized_end = 45397 - _DESCRIBEWORKFLOWRULERESPONSE._serialized_start = 45399 - _DESCRIBEWORKFLOWRULERESPONSE._serialized_end = 45480 - _DELETEWORKFLOWRULEREQUEST._serialized_start = 45482 - _DELETEWORKFLOWRULEREQUEST._serialized_end = 45545 - _DELETEWORKFLOWRULERESPONSE._serialized_start = 45547 - _DELETEWORKFLOWRULERESPONSE._serialized_end = 45575 - _LISTWORKFLOWRULESREQUEST._serialized_start = 45577 - _LISTWORKFLOWRULESREQUEST._serialized_end = 45647 - _LISTWORKFLOWRULESRESPONSE._serialized_start = 45649 - _LISTWORKFLOWRULESRESPONSE._serialized_end = 45753 - _TRIGGERWORKFLOWRULEREQUEST._serialized_start = 45756 - _TRIGGERWORKFLOWRULEREQUEST._serialized_end = 45962 - _TRIGGERWORKFLOWRULERESPONSE._serialized_start = 45964 - _TRIGGERWORKFLOWRULERESPONSE._serialized_end = 46010 - _RECORDWORKERHEARTBEATREQUEST._serialized_start = 46013 - _RECORDWORKERHEARTBEATREQUEST._serialized_end = 46168 - _RECORDWORKERHEARTBEATRESPONSE._serialized_start = 46170 - _RECORDWORKERHEARTBEATRESPONSE._serialized_end = 46201 - _LISTWORKERSREQUEST._serialized_start = 46204 - _LISTWORKERSREQUEST._serialized_end = 46334 - _LISTWORKERSRESPONSE._serialized_start = 46337 - _LISTWORKERSRESPONSE._serialized_end = 46502 - _UPDATETASKQUEUECONFIGREQUEST._serialized_start = 46505 - _UPDATETASKQUEUECONFIGREQUEST._serialized_end = 47230 - _UPDATETASKQUEUECONFIGREQUEST_RATELIMITUPDATE._serialized_start = 47072 - _UPDATETASKQUEUECONFIGREQUEST_RATELIMITUPDATE._serialized_end = 47163 + _UPDATEWORKERDEPLOYMENTVERSIONMETADATARESPONSE._serialized_start = 44238 + _UPDATEWORKERDEPLOYMENTVERSIONMETADATARESPONSE._serialized_end = 44348 + _SETWORKERDEPLOYMENTMANAGERREQUEST._serialized_start = 44351 + _SETWORKERDEPLOYMENTMANAGERREQUEST._serialized_end = 44540 + _SETWORKERDEPLOYMENTMANAGERRESPONSE._serialized_start = 44542 + _SETWORKERDEPLOYMENTMANAGERRESPONSE._serialized_end = 44641 + _GETCURRENTDEPLOYMENTREQUEST._serialized_start = 44643 + _GETCURRENTDEPLOYMENTREQUEST._serialized_end = 44712 + _GETCURRENTDEPLOYMENTRESPONSE._serialized_start = 44714 + _GETCURRENTDEPLOYMENTRESPONSE._serialized_end = 44821 + _GETDEPLOYMENTREACHABILITYREQUEST._serialized_start = 44823 + _GETDEPLOYMENTREACHABILITYREQUEST._serialized_end = 44936 + _GETDEPLOYMENTREACHABILITYRESPONSE._serialized_start = 44939 + _GETDEPLOYMENTREACHABILITYRESPONSE._serialized_end = 45166 + _CREATEWORKFLOWRULEREQUEST._serialized_start = 45169 + _CREATEWORKFLOWRULEREQUEST._serialized_end = 45349 + _CREATEWORKFLOWRULERESPONSE._serialized_start = 45351 + _CREATEWORKFLOWRULERESPONSE._serialized_end = 45446 + _DESCRIBEWORKFLOWRULEREQUEST._serialized_start = 45448 + _DESCRIBEWORKFLOWRULEREQUEST._serialized_end = 45513 + _DESCRIBEWORKFLOWRULERESPONSE._serialized_start = 45515 + _DESCRIBEWORKFLOWRULERESPONSE._serialized_end = 45596 + _DELETEWORKFLOWRULEREQUEST._serialized_start = 45598 + _DELETEWORKFLOWRULEREQUEST._serialized_end = 45661 + _DELETEWORKFLOWRULERESPONSE._serialized_start = 45663 + _DELETEWORKFLOWRULERESPONSE._serialized_end = 45691 + _LISTWORKFLOWRULESREQUEST._serialized_start = 45693 + _LISTWORKFLOWRULESREQUEST._serialized_end = 45763 + _LISTWORKFLOWRULESRESPONSE._serialized_start = 45765 + _LISTWORKFLOWRULESRESPONSE._serialized_end = 45869 + _TRIGGERWORKFLOWRULEREQUEST._serialized_start = 45872 + _TRIGGERWORKFLOWRULEREQUEST._serialized_end = 46078 + _TRIGGERWORKFLOWRULERESPONSE._serialized_start = 46080 + _TRIGGERWORKFLOWRULERESPONSE._serialized_end = 46126 + _RECORDWORKERHEARTBEATREQUEST._serialized_start = 46129 + _RECORDWORKERHEARTBEATREQUEST._serialized_end = 46284 + _RECORDWORKERHEARTBEATRESPONSE._serialized_start = 46286 + _RECORDWORKERHEARTBEATRESPONSE._serialized_end = 46317 + _LISTWORKERSREQUEST._serialized_start = 46320 + _LISTWORKERSREQUEST._serialized_end = 46450 + _LISTWORKERSRESPONSE._serialized_start = 46453 + _LISTWORKERSRESPONSE._serialized_end = 46618 + _UPDATETASKQUEUECONFIGREQUEST._serialized_start = 46621 + _UPDATETASKQUEUECONFIGREQUEST._serialized_end = 47346 + _UPDATETASKQUEUECONFIGREQUEST_RATELIMITUPDATE._serialized_start = 47188 + _UPDATETASKQUEUECONFIGREQUEST_RATELIMITUPDATE._serialized_end = 47279 _UPDATETASKQUEUECONFIGREQUEST_SETFAIRNESSWEIGHTOVERRIDESENTRY._serialized_start = ( - 47165 + 47281 ) _UPDATETASKQUEUECONFIGREQUEST_SETFAIRNESSWEIGHTOVERRIDESENTRY._serialized_end = ( - 47230 + 47346 ) - _UPDATETASKQUEUECONFIGRESPONSE._serialized_start = 47232 - _UPDATETASKQUEUECONFIGRESPONSE._serialized_end = 47323 - _FETCHWORKERCONFIGREQUEST._serialized_start = 47326 - _FETCHWORKERCONFIGREQUEST._serialized_end = 47484 - _FETCHWORKERCONFIGRESPONSE._serialized_start = 47486 - _FETCHWORKERCONFIGRESPONSE._serialized_end = 47571 - _UPDATEWORKERCONFIGREQUEST._serialized_start = 47574 - _UPDATEWORKERCONFIGREQUEST._serialized_end = 47840 - _UPDATEWORKERCONFIGRESPONSE._serialized_start = 47842 - _UPDATEWORKERCONFIGRESPONSE._serialized_end = 47942 - _DESCRIBEWORKERREQUEST._serialized_start = 47944 - _DESCRIBEWORKERREQUEST._serialized_end = 48015 - _DESCRIBEWORKERRESPONSE._serialized_start = 48017 - _DESCRIBEWORKERRESPONSE._serialized_end = 48098 - _PAUSEWORKFLOWEXECUTIONREQUEST._serialized_start = 48101 - _PAUSEWORKFLOWEXECUTIONREQUEST._serialized_end = 48242 - _PAUSEWORKFLOWEXECUTIONRESPONSE._serialized_start = 48244 - _PAUSEWORKFLOWEXECUTIONRESPONSE._serialized_end = 48276 - _UNPAUSEWORKFLOWEXECUTIONREQUEST._serialized_start = 48279 - _UNPAUSEWORKFLOWEXECUTIONREQUEST._serialized_end = 48422 - _UNPAUSEWORKFLOWEXECUTIONRESPONSE._serialized_start = 48424 - _UNPAUSEWORKFLOWEXECUTIONRESPONSE._serialized_end = 48458 - _STARTACTIVITYEXECUTIONREQUEST._serialized_start = 48461 - _STARTACTIVITYEXECUTIONREQUEST._serialized_end = 49638 - _STARTACTIVITYEXECUTIONRESPONSE._serialized_start = 49640 - _STARTACTIVITYEXECUTIONRESPONSE._serialized_end = 49749 - _DESCRIBEACTIVITYEXECUTIONREQUEST._serialized_start = 49752 - _DESCRIBEACTIVITYEXECUTIONREQUEST._serialized_end = 49915 - _DESCRIBEACTIVITYEXECUTIONRESPONSE._serialized_start = 49918 - _DESCRIBEACTIVITYEXECUTIONRESPONSE._serialized_end = 50234 - _POLLACTIVITYEXECUTIONREQUEST._serialized_start = 50236 - _POLLACTIVITYEXECUTIONREQUEST._serialized_end = 50322 - _POLLACTIVITYEXECUTIONRESPONSE._serialized_start = 50324 - _POLLACTIVITYEXECUTIONRESPONSE._serialized_end = 50440 - _LISTACTIVITYEXECUTIONSREQUEST._serialized_start = 50442 - _LISTACTIVITYEXECUTIONSREQUEST._serialized_end = 50551 - _LISTACTIVITYEXECUTIONSRESPONSE._serialized_start = 50554 - _LISTACTIVITYEXECUTIONSRESPONSE._serialized_end = 50684 - _STARTNEXUSOPERATIONEXECUTIONREQUEST._serialized_start = 50687 - _STARTNEXUSOPERATIONEXECUTIONREQUEST._serialized_end = 51536 - _STARTNEXUSOPERATIONEXECUTIONREQUEST_NEXUSHEADERENTRY._serialized_start = 51486 - _STARTNEXUSOPERATIONEXECUTIONREQUEST_NEXUSHEADERENTRY._serialized_end = 51536 - _STARTNEXUSOPERATIONEXECUTIONRESPONSE._serialized_start = 51538 - _STARTNEXUSOPERATIONEXECUTIONRESPONSE._serialized_end = 51609 - _DESCRIBENEXUSOPERATIONEXECUTIONREQUEST._serialized_start = 51612 - _DESCRIBENEXUSOPERATIONEXECUTIONREQUEST._serialized_end = 51782 - _DESCRIBENEXUSOPERATIONEXECUTIONRESPONSE._serialized_start = 51785 - _DESCRIBENEXUSOPERATIONEXECUTIONRESPONSE._serialized_end = 52096 - _POLLNEXUSOPERATIONEXECUTIONREQUEST._serialized_start = 52099 - _POLLNEXUSOPERATIONEXECUTIONREQUEST._serialized_end = 52260 - _POLLNEXUSOPERATIONEXECUTIONRESPONSE._serialized_start = 52263 - _POLLNEXUSOPERATIONEXECUTIONRESPONSE._serialized_end = 52524 - _LISTNEXUSOPERATIONEXECUTIONSREQUEST._serialized_start = 52526 - _LISTNEXUSOPERATIONEXECUTIONSREQUEST._serialized_end = 52641 - _LISTNEXUSOPERATIONEXECUTIONSRESPONSE._serialized_start = 52644 - _LISTNEXUSOPERATIONEXECUTIONSRESPONSE._serialized_end = 52783 - _COUNTACTIVITYEXECUTIONSREQUEST._serialized_start = 52785 - _COUNTACTIVITYEXECUTIONSREQUEST._serialized_end = 52851 - _COUNTACTIVITYEXECUTIONSRESPONSE._serialized_start = 52854 - _COUNTACTIVITYEXECUTIONSRESPONSE._serialized_end = 53091 - _COUNTACTIVITYEXECUTIONSRESPONSE_AGGREGATIONGROUP._serialized_start = 19679 - _COUNTACTIVITYEXECUTIONSRESPONSE_AGGREGATIONGROUP._serialized_end = 19767 - _COUNTNEXUSOPERATIONEXECUTIONSREQUEST._serialized_start = 53093 - _COUNTNEXUSOPERATIONEXECUTIONSREQUEST._serialized_end = 53165 - _COUNTNEXUSOPERATIONEXECUTIONSRESPONSE._serialized_start = 53168 - _COUNTNEXUSOPERATIONEXECUTIONSRESPONSE._serialized_end = 53417 - _COUNTNEXUSOPERATIONEXECUTIONSRESPONSE_AGGREGATIONGROUP._serialized_start = 19679 - _COUNTNEXUSOPERATIONEXECUTIONSRESPONSE_AGGREGATIONGROUP._serialized_end = 19767 - _REQUESTCANCELACTIVITYEXECUTIONREQUEST._serialized_start = 53420 - _REQUESTCANCELACTIVITYEXECUTIONREQUEST._serialized_end = 53569 - _REQUESTCANCELACTIVITYEXECUTIONRESPONSE._serialized_start = 53571 - _REQUESTCANCELACTIVITYEXECUTIONRESPONSE._serialized_end = 53611 - _TERMINATEACTIVITYEXECUTIONREQUEST._serialized_start = 53614 - _TERMINATEACTIVITYEXECUTIONREQUEST._serialized_end = 53759 - _TERMINATEACTIVITYEXECUTIONRESPONSE._serialized_start = 53761 - _TERMINATEACTIVITYEXECUTIONRESPONSE._serialized_end = 53797 - _DELETEACTIVITYEXECUTIONREQUEST._serialized_start = 53799 - _DELETEACTIVITYEXECUTIONREQUEST._serialized_end = 53887 - _DELETEACTIVITYEXECUTIONRESPONSE._serialized_start = 53889 - _DELETEACTIVITYEXECUTIONRESPONSE._serialized_end = 53922 - _REQUESTCANCELNEXUSOPERATIONEXECUTIONREQUEST._serialized_start = 53925 - _REQUESTCANCELNEXUSOPERATIONEXECUTIONREQUEST._serialized_end = 54081 - _REQUESTCANCELNEXUSOPERATIONEXECUTIONRESPONSE._serialized_start = 54083 - _REQUESTCANCELNEXUSOPERATIONEXECUTIONRESPONSE._serialized_end = 54129 - _TERMINATENEXUSOPERATIONEXECUTIONREQUEST._serialized_start = 54132 - _TERMINATENEXUSOPERATIONEXECUTIONREQUEST._serialized_end = 54284 - _TERMINATENEXUSOPERATIONEXECUTIONRESPONSE._serialized_start = 54286 - _TERMINATENEXUSOPERATIONEXECUTIONRESPONSE._serialized_end = 54328 - _DELETENEXUSOPERATIONEXECUTIONREQUEST._serialized_start = 54330 - _DELETENEXUSOPERATIONEXECUTIONREQUEST._serialized_end = 54425 - _DELETENEXUSOPERATIONEXECUTIONRESPONSE._serialized_start = 54427 - _DELETENEXUSOPERATIONEXECUTIONRESPONSE._serialized_end = 54466 + _UPDATETASKQUEUECONFIGRESPONSE._serialized_start = 47348 + _UPDATETASKQUEUECONFIGRESPONSE._serialized_end = 47439 + _FETCHWORKERCONFIGREQUEST._serialized_start = 47442 + _FETCHWORKERCONFIGREQUEST._serialized_end = 47600 + _FETCHWORKERCONFIGRESPONSE._serialized_start = 47602 + _FETCHWORKERCONFIGRESPONSE._serialized_end = 47687 + _UPDATEWORKERCONFIGREQUEST._serialized_start = 47690 + _UPDATEWORKERCONFIGREQUEST._serialized_end = 47956 + _UPDATEWORKERCONFIGRESPONSE._serialized_start = 47958 + _UPDATEWORKERCONFIGRESPONSE._serialized_end = 48058 + _DESCRIBEWORKERREQUEST._serialized_start = 48060 + _DESCRIBEWORKERREQUEST._serialized_end = 48131 + _DESCRIBEWORKERRESPONSE._serialized_start = 48133 + _DESCRIBEWORKERRESPONSE._serialized_end = 48214 + _PAUSEWORKFLOWEXECUTIONREQUEST._serialized_start = 48217 + _PAUSEWORKFLOWEXECUTIONREQUEST._serialized_end = 48358 + _PAUSEWORKFLOWEXECUTIONRESPONSE._serialized_start = 48360 + _PAUSEWORKFLOWEXECUTIONRESPONSE._serialized_end = 48392 + _UNPAUSEWORKFLOWEXECUTIONREQUEST._serialized_start = 48395 + _UNPAUSEWORKFLOWEXECUTIONREQUEST._serialized_end = 48538 + _UNPAUSEWORKFLOWEXECUTIONRESPONSE._serialized_start = 48540 + _UNPAUSEWORKFLOWEXECUTIONRESPONSE._serialized_end = 48574 + _STARTACTIVITYEXECUTIONREQUEST._serialized_start = 48577 + _STARTACTIVITYEXECUTIONREQUEST._serialized_end = 49754 + _STARTACTIVITYEXECUTIONRESPONSE._serialized_start = 49756 + _STARTACTIVITYEXECUTIONRESPONSE._serialized_end = 49865 + _DESCRIBEACTIVITYEXECUTIONREQUEST._serialized_start = 49868 + _DESCRIBEACTIVITYEXECUTIONREQUEST._serialized_end = 50096 + _DESCRIBEACTIVITYEXECUTIONRESPONSE._serialized_start = 50099 + _DESCRIBEACTIVITYEXECUTIONRESPONSE._serialized_end = 50415 + _POLLACTIVITYEXECUTIONREQUEST._serialized_start = 50417 + _POLLACTIVITYEXECUTIONREQUEST._serialized_end = 50503 + _POLLACTIVITYEXECUTIONRESPONSE._serialized_start = 50505 + _POLLACTIVITYEXECUTIONRESPONSE._serialized_end = 50621 + _LISTACTIVITYEXECUTIONSREQUEST._serialized_start = 50623 + _LISTACTIVITYEXECUTIONSREQUEST._serialized_end = 50732 + _LISTACTIVITYEXECUTIONSRESPONSE._serialized_start = 50735 + _LISTACTIVITYEXECUTIONSRESPONSE._serialized_end = 50865 + _STARTNEXUSOPERATIONEXECUTIONREQUEST._serialized_start = 50868 + _STARTNEXUSOPERATIONEXECUTIONREQUEST._serialized_end = 51717 + _STARTNEXUSOPERATIONEXECUTIONREQUEST_NEXUSHEADERENTRY._serialized_start = 51667 + _STARTNEXUSOPERATIONEXECUTIONREQUEST_NEXUSHEADERENTRY._serialized_end = 51717 + _STARTNEXUSOPERATIONEXECUTIONRESPONSE._serialized_start = 51719 + _STARTNEXUSOPERATIONEXECUTIONRESPONSE._serialized_end = 51790 + _DESCRIBENEXUSOPERATIONEXECUTIONREQUEST._serialized_start = 51793 + _DESCRIBENEXUSOPERATIONEXECUTIONREQUEST._serialized_end = 51963 + _DESCRIBENEXUSOPERATIONEXECUTIONRESPONSE._serialized_start = 51966 + _DESCRIBENEXUSOPERATIONEXECUTIONRESPONSE._serialized_end = 52277 + _POLLNEXUSOPERATIONEXECUTIONREQUEST._serialized_start = 52280 + _POLLNEXUSOPERATIONEXECUTIONREQUEST._serialized_end = 52441 + _POLLNEXUSOPERATIONEXECUTIONRESPONSE._serialized_start = 52444 + _POLLNEXUSOPERATIONEXECUTIONRESPONSE._serialized_end = 52705 + _LISTNEXUSOPERATIONEXECUTIONSREQUEST._serialized_start = 52707 + _LISTNEXUSOPERATIONEXECUTIONSREQUEST._serialized_end = 52822 + _LISTNEXUSOPERATIONEXECUTIONSRESPONSE._serialized_start = 52825 + _LISTNEXUSOPERATIONEXECUTIONSRESPONSE._serialized_end = 52964 + _COUNTACTIVITYEXECUTIONSREQUEST._serialized_start = 52966 + _COUNTACTIVITYEXECUTIONSREQUEST._serialized_end = 53032 + _COUNTACTIVITYEXECUTIONSRESPONSE._serialized_start = 53035 + _COUNTACTIVITYEXECUTIONSRESPONSE._serialized_end = 53272 + _COUNTACTIVITYEXECUTIONSRESPONSE_AGGREGATIONGROUP._serialized_start = 19751 + _COUNTACTIVITYEXECUTIONSRESPONSE_AGGREGATIONGROUP._serialized_end = 19839 + _COUNTNEXUSOPERATIONEXECUTIONSREQUEST._serialized_start = 53274 + _COUNTNEXUSOPERATIONEXECUTIONSREQUEST._serialized_end = 53346 + _COUNTNEXUSOPERATIONEXECUTIONSRESPONSE._serialized_start = 53349 + _COUNTNEXUSOPERATIONEXECUTIONSRESPONSE._serialized_end = 53598 + _COUNTNEXUSOPERATIONEXECUTIONSRESPONSE_AGGREGATIONGROUP._serialized_start = 19751 + _COUNTNEXUSOPERATIONEXECUTIONSRESPONSE_AGGREGATIONGROUP._serialized_end = 19839 + _REQUESTCANCELACTIVITYEXECUTIONREQUEST._serialized_start = 53601 + _REQUESTCANCELACTIVITYEXECUTIONREQUEST._serialized_end = 53750 + _REQUESTCANCELACTIVITYEXECUTIONRESPONSE._serialized_start = 53752 + _REQUESTCANCELACTIVITYEXECUTIONRESPONSE._serialized_end = 53792 + _TERMINATEACTIVITYEXECUTIONREQUEST._serialized_start = 53795 + _TERMINATEACTIVITYEXECUTIONREQUEST._serialized_end = 53940 + _TERMINATEACTIVITYEXECUTIONRESPONSE._serialized_start = 53942 + _TERMINATEACTIVITYEXECUTIONRESPONSE._serialized_end = 53978 + _DELETEACTIVITYEXECUTIONREQUEST._serialized_start = 53980 + _DELETEACTIVITYEXECUTIONREQUEST._serialized_end = 54068 + _DELETEACTIVITYEXECUTIONRESPONSE._serialized_start = 54070 + _DELETEACTIVITYEXECUTIONRESPONSE._serialized_end = 54103 + _REQUESTCANCELNEXUSOPERATIONEXECUTIONREQUEST._serialized_start = 54106 + _REQUESTCANCELNEXUSOPERATIONEXECUTIONREQUEST._serialized_end = 54262 + _REQUESTCANCELNEXUSOPERATIONEXECUTIONRESPONSE._serialized_start = 54264 + _REQUESTCANCELNEXUSOPERATIONEXECUTIONRESPONSE._serialized_end = 54310 + _TERMINATENEXUSOPERATIONEXECUTIONREQUEST._serialized_start = 54313 + _TERMINATENEXUSOPERATIONEXECUTIONREQUEST._serialized_end = 54465 + _TERMINATENEXUSOPERATIONEXECUTIONRESPONSE._serialized_start = 54467 + _TERMINATENEXUSOPERATIONEXECUTIONRESPONSE._serialized_end = 54509 + _DELETENEXUSOPERATIONEXECUTIONREQUEST._serialized_start = 54511 + _DELETENEXUSOPERATIONEXECUTIONREQUEST._serialized_end = 54606 + _DELETENEXUSOPERATIONEXECUTIONRESPONSE._serialized_start = 54608 + _DELETENEXUSOPERATIONEXECUTIONRESPONSE._serialized_end = 54647 # @@protoc_insertion_point(module_scope) diff --git a/temporalio/api/workflowservice/v1/request_response_pb2.pyi b/temporalio/api/workflowservice/v1/request_response_pb2.pyi index 726d9567f..1e92d50e1 100644 --- a/temporalio/api/workflowservice/v1/request_response_pb2.pyi +++ b/temporalio/api/workflowservice/v1/request_response_pb2.pyi @@ -304,6 +304,7 @@ class DescribeNamespaceResponse(google.protobuf.message.Message): FAILOVER_VERSION_FIELD_NUMBER: builtins.int IS_GLOBAL_NAMESPACE_FIELD_NUMBER: builtins.int FAILOVER_HISTORY_FIELD_NUMBER: builtins.int + POLLER_GROUP_INFOS_FIELD_NUMBER: builtins.int @property def namespace_info( self, @@ -325,6 +326,16 @@ class DescribeNamespaceResponse(google.protobuf.message.Message): """Contains the historical state of failover_versions for the cluster, truncated to contain only the last N states to ensure that the list does not grow unbounded. """ + @property + def poller_group_infos( + self, + ) -> google.protobuf.internal.containers.RepeatedCompositeFieldContainer[ + temporalio.api.taskqueue.v1.message_pb2.PollerGroupInfo + ]: + """The initial info that client should use for poller group assignment. This information is + updated through poll response. Client is supposed to use the info received in the latest + poll response. + """ def __init__( self, *, @@ -339,6 +350,10 @@ class DescribeNamespaceResponse(google.protobuf.message.Message): temporalio.api.replication.v1.message_pb2.FailoverStatus ] | None = ..., + poller_group_infos: collections.abc.Iterable[ + temporalio.api.taskqueue.v1.message_pb2.PollerGroupInfo + ] + | None = ..., ) -> None: ... def HasField( self, @@ -364,6 +379,8 @@ class DescribeNamespaceResponse(google.protobuf.message.Message): b"is_global_namespace", "namespace_info", b"namespace_info", + "poller_group_infos", + b"poller_group_infos", "replication_config", b"replication_config", ], @@ -1110,7 +1127,7 @@ class PollWorkflowTaskQueueRequest(google.protobuf.message.Message): poller_group_id: builtins.str """Unless this is the first poll, the client must pass one of the poller group IDs received in `poller_group_infos` of the last the PollWorkflowTaskQueueResponse according to the - instructions. If not set, the poll is routed randomly which can cause it being blocked + instructions. If not set, the poll is routed randomly which can cause it to be blocked without receiving a task while the queue actually has tasks in another server location. """ identity: builtins.str @@ -1904,7 +1921,7 @@ class PollActivityTaskQueueRequest(google.protobuf.message.Message): poller_group_id: builtins.str """Unless this is the first poll, the client must pass one of the poller group IDs received in `poller_group_infos` of the last the PollActivityTaskQueueResponse according to the - instructions. If not set, the poll is routed randomly which can cause it being blocked + instructions. If not set, the poll is routed randomly which can cause it to be blocked without receiving a task while the queue actually has tasks in another server location. """ identity: builtins.str @@ -6952,6 +6969,7 @@ class UpdateWorkflowExecutionResponse(google.protobuf.message.Message): UPDATE_REF_FIELD_NUMBER: builtins.int OUTCOME_FIELD_NUMBER: builtins.int STAGE_FIELD_NUMBER: builtins.int + LINK_FIELD_NUMBER: builtins.int @property def update_ref(self) -> temporalio.api.update.v1.message_pb2.UpdateRef: """Enough information for subsequent poll calls if needed. Never null.""" @@ -6973,23 +6991,34 @@ class UpdateWorkflowExecutionResponse(google.protobuf.message.Message): request WaitPolicy, and before the context deadline expired; clients may may then retry the call as needed. """ + @property + def link(self) -> temporalio.api.common.v1.message_pb2.Link: + """Link to the update event. May be null if the update has not yet been accepted.""" def __init__( self, *, update_ref: temporalio.api.update.v1.message_pb2.UpdateRef | None = ..., outcome: temporalio.api.update.v1.message_pb2.Outcome | None = ..., stage: temporalio.api.enums.v1.update_pb2.UpdateWorkflowExecutionLifecycleStage.ValueType = ..., + link: temporalio.api.common.v1.message_pb2.Link | None = ..., ) -> None: ... def HasField( self, field_name: typing_extensions.Literal[ - "outcome", b"outcome", "update_ref", b"update_ref" + "link", b"link", "outcome", b"outcome", "update_ref", b"update_ref" ], ) -> builtins.bool: ... def ClearField( self, field_name: typing_extensions.Literal[ - "outcome", b"outcome", "stage", b"stage", "update_ref", b"update_ref" + "link", + b"link", + "outcome", + b"outcome", + "stage", + b"stage", + "update_ref", + b"update_ref", ], ) -> None: ... @@ -7539,7 +7568,7 @@ class PollNexusTaskQueueRequest(google.protobuf.message.Message): poller_group_id: builtins.str """Unless this is the first poll, the client must pass one of the poller group IDs received in `poller_group_infos` of the last the PollNexusTaskQueueResponse according to the - instructions. If not set, the poll is routed randomly which can cause it being blocked + instructions. If not set, the poll is routed randomly which can cause it to be blocked without receiving a task while the queue actually has tasks in another server location. """ identity: builtins.str @@ -11929,6 +11958,8 @@ class DescribeActivityExecutionRequest(google.protobuf.message.Message): INCLUDE_INPUT_FIELD_NUMBER: builtins.int INCLUDE_OUTCOME_FIELD_NUMBER: builtins.int LONG_POLL_TOKEN_FIELD_NUMBER: builtins.int + INCLUDE_HEARTBEAT_DETAILS_FIELD_NUMBER: builtins.int + INCLUDE_LAST_FAILURE_FIELD_NUMBER: builtins.int namespace: builtins.str activity_id: builtins.str run_id: builtins.str @@ -11945,6 +11976,10 @@ class DescribeActivityExecutionRequest(google.protobuf.message.Message): guaranteed that a client making a sequence of long-poll requests will see a complete sequence of state changes. """ + include_heartbeat_details: builtins.bool + """Include the heartbeat_details field inside info in the response if available.""" + include_last_failure: builtins.bool + """Include the last_failure field inside info in the response if available.""" def __init__( self, *, @@ -11954,14 +11989,20 @@ class DescribeActivityExecutionRequest(google.protobuf.message.Message): include_input: builtins.bool = ..., include_outcome: builtins.bool = ..., long_poll_token: builtins.bytes = ..., + include_heartbeat_details: builtins.bool = ..., + include_last_failure: builtins.bool = ..., ) -> None: ... def ClearField( self, field_name: typing_extensions.Literal[ "activity_id", b"activity_id", + "include_heartbeat_details", + b"include_heartbeat_details", "include_input", b"include_input", + "include_last_failure", + b"include_last_failure", "include_outcome", b"include_outcome", "long_poll_token", @@ -11988,7 +12029,9 @@ class DescribeActivityExecutionResponse(google.protobuf.message.Message): """The run ID of the activity, useful when run_id was not specified in the request.""" @property def info(self) -> temporalio.api.activity.v1.message_pb2.ActivityExecutionInfo: - """Information about the activity execution.""" + """Information about the activity execution. Fields heartbeat_details and last_failure are omitted unless + the request has include_heartbeat_details or include_last_failure set to true, respectively. + """ @property def input(self) -> temporalio.api.common.v1.message_pb2.Payloads: """Serialized activity input, passed as arguments to the activity function. diff --git a/temporalio/api/workflowservice/v1/service_pb2.py b/temporalio/api/workflowservice/v1/service_pb2.py index 3e123e9cf..bc9ca40a4 100644 --- a/temporalio/api/workflowservice/v1/service_pb2.py +++ b/temporalio/api/workflowservice/v1/service_pb2.py @@ -16,6 +16,9 @@ from google.api import annotations_pb2 as google_dot_api_dot_annotations__pb2 +from temporalio.api.dependencies.nexusannotations.v1 import ( + options_pb2 as nexusannotations_dot_v1_dot_options__pb2, +) from temporalio.api.protometa.v1 import ( annotations_pb2 as temporal_dot_api_dot_protometa_dot_v1_dot_annotations__pb2, ) @@ -24,7 +27,7 @@ ) DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile( - b'\n-temporal/api/workflowservice/v1/service.proto\x12\x1ftemporal.api.workflowservice.v1\x1a\x36temporal/api/workflowservice/v1/request_response.proto\x1a\x1cgoogle/api/annotations.proto\x1a+temporal/api/protometa/v1/annotations.proto2\xb0\xad\x02\n\x0fWorkflowService\x12\xc3\x01\n\x11RegisterNamespace\x12\x39.temporal.api.workflowservice.v1.RegisterNamespaceRequest\x1a:.temporal.api.workflowservice.v1.RegisterNamespaceResponse"7\x82\xd3\xe4\x93\x02\x31"\x13/cluster/namespaces:\x01*Z\x17"\x12/api/v1/namespaces:\x01*\x12\xd5\x01\n\x11\x44\x65scribeNamespace\x12\x39.temporal.api.workflowservice.v1.DescribeNamespaceRequest\x1a:.temporal.api.workflowservice.v1.DescribeNamespaceResponse"I\x82\xd3\xe4\x93\x02\x43\x12\x1f/cluster/namespaces/{namespace}Z \x12\x1e/api/v1/namespaces/{namespace}\x12\xb4\x01\n\x0eListNamespaces\x12\x36.temporal.api.workflowservice.v1.ListNamespacesRequest\x1a\x37.temporal.api.workflowservice.v1.ListNamespacesResponse"1\x82\xd3\xe4\x93\x02+\x12\x13/cluster/namespacesZ\x14\x12\x12/api/v1/namespaces\x12\xe3\x01\n\x0fUpdateNamespace\x12\x37.temporal.api.workflowservice.v1.UpdateNamespaceRequest\x1a\x38.temporal.api.workflowservice.v1.UpdateNamespaceResponse"]\x82\xd3\xe4\x93\x02W"&/cluster/namespaces/{namespace}/update:\x01*Z*"%/api/v1/namespaces/{namespace}/update:\x01*\x12\x8f\x01\n\x12\x44\x65precateNamespace\x12:.temporal.api.workflowservice.v1.DeprecateNamespaceRequest\x1a;.temporal.api.workflowservice.v1.DeprecateNamespaceResponse"\x00\x12\xc6\x02\n\x16StartWorkflowExecution\x12>.temporal.api.workflowservice.v1.StartWorkflowExecutionRequest\x1a?.temporal.api.workflowservice.v1.StartWorkflowExecutionResponse"\xaa\x01\x82\xd3\xe4\x93\x02q"//namespaces/{namespace}/workflows/{workflow_id}:\x01*Z;"6/api/v1/namespaces/{namespace}/workflows/{workflow_id}:\x01*\x8a\x9d\xcc\x1b.\n\x14temporal-resource-id\x12\x16workflow:{workflow_id}\x12\xc2\x01\n\x15\x45xecuteMultiOperation\x12=.temporal.api.workflowservice.v1.ExecuteMultiOperationRequest\x1a>.temporal.api.workflowservice.v1.ExecuteMultiOperationResponse"*\x8a\x9d\xcc\x1b%\n\x14temporal-resource-id\x12\r{resource_id}\x12\xfe\x02\n\x1bGetWorkflowExecutionHistory\x12\x43.temporal.api.workflowservice.v1.GetWorkflowExecutionHistoryRequest\x1a\x44.temporal.api.workflowservice.v1.GetWorkflowExecutionHistoryResponse"\xd3\x01\x82\xd3\xe4\x93\x02\x8f\x01\x12\x41/namespaces/{namespace}/workflows/{execution.workflow_id}/historyZJ\x12H/api/v1/namespaces/{namespace}/workflows/{execution.workflow_id}/history\x8a\x9d\xcc\x1b\x38\n\x14temporal-resource-id\x12 workflow:{execution.workflow_id}\x12\xa3\x03\n"GetWorkflowExecutionHistoryReverse\x12J.temporal.api.workflowservice.v1.GetWorkflowExecutionHistoryReverseRequest\x1aK.temporal.api.workflowservice.v1.GetWorkflowExecutionHistoryReverseResponse"\xe3\x01\x82\xd3\xe4\x93\x02\x9f\x01\x12I/namespaces/{namespace}/workflows/{execution.workflow_id}/history-reverseZR\x12P/api/v1/namespaces/{namespace}/workflows/{execution.workflow_id}/history-reverse\x8a\x9d\xcc\x1b\x38\n\x14temporal-resource-id\x12 workflow:{execution.workflow_id}\x12\xcd\x01\n\x15PollWorkflowTaskQueue\x12=.temporal.api.workflowservice.v1.PollWorkflowTaskQueueRequest\x1a>.temporal.api.workflowservice.v1.PollWorkflowTaskQueueResponse"5\x8a\x9d\xcc\x1b\x30\n\x14temporal-resource-id\x12\x18poller:{poller_group_id}\x12\xd7\x01\n\x1cRespondWorkflowTaskCompleted\x12\x44.temporal.api.workflowservice.v1.RespondWorkflowTaskCompletedRequest\x1a\x45.temporal.api.workflowservice.v1.RespondWorkflowTaskCompletedResponse"*\x8a\x9d\xcc\x1b%\n\x14temporal-resource-id\x12\r{resource_id}\x12\xce\x01\n\x19RespondWorkflowTaskFailed\x12\x41.temporal.api.workflowservice.v1.RespondWorkflowTaskFailedRequest\x1a\x42.temporal.api.workflowservice.v1.RespondWorkflowTaskFailedResponse"*\x8a\x9d\xcc\x1b%\n\x14temporal-resource-id\x12\r{resource_id}\x12\xcd\x01\n\x15PollActivityTaskQueue\x12=.temporal.api.workflowservice.v1.PollActivityTaskQueueRequest\x1a>.temporal.api.workflowservice.v1.PollActivityTaskQueueResponse"5\x8a\x9d\xcc\x1b\x30\n\x14temporal-resource-id\x12\x18poller:{poller_group_id}\x12\xc2\x02\n\x1bRecordActivityTaskHeartbeat\x12\x43.temporal.api.workflowservice.v1.RecordActivityTaskHeartbeatRequest\x1a\x44.temporal.api.workflowservice.v1.RecordActivityTaskHeartbeatResponse"\x97\x01\x82\xd3\xe4\x93\x02g"*/namespaces/{namespace}/activity-heartbeat:\x01*Z6"1/api/v1/namespaces/{namespace}/activity-heartbeat:\x01*\x8a\x9d\xcc\x1b%\n\x14temporal-resource-id\x12\r{resource_id}\x12\xa8\x04\n\x1fRecordActivityTaskHeartbeatById\x12G.temporal.api.workflowservice.v1.RecordActivityTaskHeartbeatByIdRequest\x1aH.temporal.api.workflowservice.v1.RecordActivityTaskHeartbeatByIdResponse"\xf1\x02\x82\xd3\xe4\x93\x02\xc0\x02":/namespaces/{namespace}/activities/{activity_id}/heartbeat:\x01*ZF"A/api/v1/namespaces/{namespace}/activities/{activity_id}/heartbeat:\x01*ZW"R/namespaces/{namespace}/workflows/{workflow_id}/activities/{activity_id}/heartbeat:\x01*Z^"Y/api/v1/namespaces/{namespace}/workflows/{workflow_id}/activities/{activity_id}/heartbeat:\x01*\x8a\x9d\xcc\x1b%\n\x14temporal-resource-id\x12\r{resource_id}\x12\xc3\x02\n\x1cRespondActivityTaskCompleted\x12\x44.temporal.api.workflowservice.v1.RespondActivityTaskCompletedRequest\x1a\x45.temporal.api.workflowservice.v1.RespondActivityTaskCompletedResponse"\x95\x01\x82\xd3\xe4\x93\x02\x65")/namespaces/{namespace}/activity-complete:\x01*Z5"0/api/v1/namespaces/{namespace}/activity-complete:\x01*\x8a\x9d\xcc\x1b%\n\x14temporal-resource-id\x12\r{resource_id}\x12\xa7\x04\n RespondActivityTaskCompletedById\x12H.temporal.api.workflowservice.v1.RespondActivityTaskCompletedByIdRequest\x1aI.temporal.api.workflowservice.v1.RespondActivityTaskCompletedByIdResponse"\xed\x02\x82\xd3\xe4\x93\x02\xbc\x02"9/namespaces/{namespace}/activities/{activity_id}/complete:\x01*ZE"@/api/v1/namespaces/{namespace}/activities/{activity_id}/complete:\x01*ZV"Q/namespaces/{namespace}/workflows/{workflow_id}/activities/{activity_id}/complete:\x01*Z]"X/api/v1/namespaces/{namespace}/workflows/{workflow_id}/activities/{activity_id}/complete:\x01*\x8a\x9d\xcc\x1b%\n\x14temporal-resource-id\x12\r{resource_id}\x12\xb2\x02\n\x19RespondActivityTaskFailed\x12\x41.temporal.api.workflowservice.v1.RespondActivityTaskFailedRequest\x1a\x42.temporal.api.workflowservice.v1.RespondActivityTaskFailedResponse"\x8d\x01\x82\xd3\xe4\x93\x02]"%/namespaces/{namespace}/activity-fail:\x01*Z1",/api/v1/namespaces/{namespace}/activity-fail:\x01*\x8a\x9d\xcc\x1b%\n\x14temporal-resource-id\x12\r{resource_id}\x12\x8e\x04\n\x1dRespondActivityTaskFailedById\x12\x45.temporal.api.workflowservice.v1.RespondActivityTaskFailedByIdRequest\x1a\x46.temporal.api.workflowservice.v1.RespondActivityTaskFailedByIdResponse"\xdd\x02\x82\xd3\xe4\x93\x02\xac\x02"5/namespaces/{namespace}/activities/{activity_id}/fail:\x01*ZA".temporal.api.workflowservice.v1.ResetWorkflowExecutionRequest\x1a?.temporal.api.workflowservice.v1.ResetWorkflowExecutionResponse"\xf0\x01\x82\xd3\xe4\x93\x02\xa3\x01"H/namespaces/{namespace}/workflows/{workflow_execution.workflow_id}/reset:\x01*ZT"O/api/v1/namespaces/{namespace}/workflows/{workflow_execution.workflow_id}/reset:\x01*\x8a\x9d\xcc\x1b\x41\n\x14temporal-resource-id\x12)workflow:{workflow_execution.workflow_id}\x12\xa0\x03\n\x1aTerminateWorkflowExecution\x12\x42.temporal.api.workflowservice.v1.TerminateWorkflowExecutionRequest\x1a\x43.temporal.api.workflowservice.v1.TerminateWorkflowExecutionResponse"\xf8\x01\x82\xd3\xe4\x93\x02\xab\x01"L/namespaces/{namespace}/workflows/{workflow_execution.workflow_id}/terminate:\x01*ZX"S/api/v1/namespaces/{namespace}/workflows/{workflow_execution.workflow_id}/terminate:\x01*\x8a\x9d\xcc\x1b\x41\n\x14temporal-resource-id\x12)workflow:{workflow_execution.workflow_id}\x12\xe4\x01\n\x17\x44\x65leteWorkflowExecution\x12?.temporal.api.workflowservice.v1.DeleteWorkflowExecutionRequest\x1a@.temporal.api.workflowservice.v1.DeleteWorkflowExecutionResponse"F\x8a\x9d\xcc\x1b\x41\n\x14temporal-resource-id\x12)workflow:{workflow_execution.workflow_id}\x12\xa7\x01\n\x1aListOpenWorkflowExecutions\x12\x42.temporal.api.workflowservice.v1.ListOpenWorkflowExecutionsRequest\x1a\x43.temporal.api.workflowservice.v1.ListOpenWorkflowExecutionsResponse"\x00\x12\xad\x01\n\x1cListClosedWorkflowExecutions\x12\x44.temporal.api.workflowservice.v1.ListClosedWorkflowExecutionsRequest\x1a\x45.temporal.api.workflowservice.v1.ListClosedWorkflowExecutionsResponse"\x00\x12\xf0\x01\n\x16ListWorkflowExecutions\x12>.temporal.api.workflowservice.v1.ListWorkflowExecutionsRequest\x1a?.temporal.api.workflowservice.v1.ListWorkflowExecutionsResponse"U\x82\xd3\xe4\x93\x02O\x12!/namespaces/{namespace}/workflowsZ*\x12(/api/v1/namespaces/{namespace}/workflows\x12\x9a\x02\n\x1eListArchivedWorkflowExecutions\x12\x46.temporal.api.workflowservice.v1.ListArchivedWorkflowExecutionsRequest\x1aG.temporal.api.workflowservice.v1.ListArchivedWorkflowExecutionsResponse"g\x82\xd3\xe4\x93\x02\x61\x12*/namespaces/{namespace}/archived-workflowsZ3\x12\x31/api/v1/namespaces/{namespace}/archived-workflows\x12\x9b\x01\n\x16ScanWorkflowExecutions\x12>.temporal.api.workflowservice.v1.ScanWorkflowExecutionsRequest\x1a?.temporal.api.workflowservice.v1.ScanWorkflowExecutionsResponse"\x00\x12\xfd\x01\n\x17\x43ountWorkflowExecutions\x12?.temporal.api.workflowservice.v1.CountWorkflowExecutionsRequest\x1a@.temporal.api.workflowservice.v1.CountWorkflowExecutionsResponse"_\x82\xd3\xe4\x93\x02Y\x12&/namespaces/{namespace}/workflow-countZ/\x12-/api/v1/namespaces/{namespace}/workflow-count\x12\x92\x01\n\x13GetSearchAttributes\x12;.temporal.api.workflowservice.v1.GetSearchAttributesRequest\x1a<.temporal.api.workflowservice.v1.GetSearchAttributesResponse"\x00\x12\xd9\x01\n\x19RespondQueryTaskCompleted\x12\x41.temporal.api.workflowservice.v1.RespondQueryTaskCompletedRequest\x1a\x42.temporal.api.workflowservice.v1.RespondQueryTaskCompletedResponse"5\x8a\x9d\xcc\x1b\x30\n\x14temporal-resource-id\x12\x18poller:{poller_group_id}\x12\xd2\x01\n\x14ResetStickyTaskQueue\x12<.temporal.api.workflowservice.v1.ResetStickyTaskQueueRequest\x1a=.temporal.api.workflowservice.v1.ResetStickyTaskQueueResponse"=\x8a\x9d\xcc\x1b\x38\n\x14temporal-resource-id\x12 workflow:{execution.workflow_id}\x12\x83\x01\n\x0eShutdownWorker\x12\x36.temporal.api.workflowservice.v1.ShutdownWorkerRequest\x1a\x37.temporal.api.workflowservice.v1.ShutdownWorkerResponse"\x00\x12\xfc\x02\n\rQueryWorkflow\x12\x35.temporal.api.workflowservice.v1.QueryWorkflowRequest\x1a\x36.temporal.api.workflowservice.v1.QueryWorkflowResponse"\xfb\x01\x82\xd3\xe4\x93\x02\xb7\x01"R/namespaces/{namespace}/workflows/{execution.workflow_id}/query/{query.query_type}:\x01*Z^"Y/api/v1/namespaces/{namespace}/workflows/{execution.workflow_id}/query/{query.query_type}:\x01*\x8a\x9d\xcc\x1b\x38\n\x14temporal-resource-id\x12 workflow:{execution.workflow_id}\x12\xe7\x02\n\x19\x44\x65scribeWorkflowExecution\x12\x41.temporal.api.workflowservice.v1.DescribeWorkflowExecutionRequest\x1a\x42.temporal.api.workflowservice.v1.DescribeWorkflowExecutionResponse"\xc2\x01\x82\xd3\xe4\x93\x02\x7f\x12\x39/namespaces/{namespace}/workflows/{execution.workflow_id}ZB\x12@/api/v1/namespaces/{namespace}/workflows/{execution.workflow_id}\x8a\x9d\xcc\x1b\x38\n\x14temporal-resource-id\x12 workflow:{execution.workflow_id}\x12\xc2\x02\n\x11\x44\x65scribeTaskQueue\x12\x39.temporal.api.workflowservice.v1.DescribeTaskQueueRequest\x1a:.temporal.api.workflowservice.v1.DescribeTaskQueueResponse"\xb5\x01\x82\xd3\xe4\x93\x02w\x12\x35/namespaces/{namespace}/task-queues/{task_queue.name}Z>\x12/namespaces/{namespace}/schedules/{schedule_id}/matching-timesZG\x12\x45/api/v1/namespaces/{namespace}/schedules/{schedule_id}/matching-times\x8a\x9d\xcc\x1b.\n\x14temporal-resource-id\x12\x16schedule:{schedule_id}\x12\xa8\x02\n\x0e\x44\x65leteSchedule\x12\x36.temporal.api.workflowservice.v1.DeleteScheduleRequest\x1a\x37.temporal.api.workflowservice.v1.DeleteScheduleResponse"\xa4\x01\x82\xd3\xe4\x93\x02k*//namespaces/{namespace}/schedules/{schedule_id}Z8*6/api/v1/namespaces/{namespace}/schedules/{schedule_id}\x8a\x9d\xcc\x1b.\n\x14temporal-resource-id\x12\x16schedule:{schedule_id}\x12\xd5\x01\n\rListSchedules\x12\x35.temporal.api.workflowservice.v1.ListSchedulesRequest\x1a\x36.temporal.api.workflowservice.v1.ListSchedulesResponse"U\x82\xd3\xe4\x93\x02O\x12!/namespaces/{namespace}/schedulesZ*\x12(/api/v1/namespaces/{namespace}/schedules\x12\xe2\x01\n\x0e\x43ountSchedules\x12\x36.temporal.api.workflowservice.v1.CountSchedulesRequest\x1a\x37.temporal.api.workflowservice.v1.CountSchedulesResponse"_\x82\xd3\xe4\x93\x02Y\x12&/namespaces/{namespace}/schedule-countZ/\x12-/api/v1/namespaces/{namespace}/schedule-count\x12\xb9\x01\n UpdateWorkerBuildIdCompatibility\x12H.temporal.api.workflowservice.v1.UpdateWorkerBuildIdCompatibilityRequest\x1aI.temporal.api.workflowservice.v1.UpdateWorkerBuildIdCompatibilityResponse"\x00\x12\xe1\x02\n\x1dGetWorkerBuildIdCompatibility\x12\x45.temporal.api.workflowservice.v1.GetWorkerBuildIdCompatibilityRequest\x1a\x46.temporal.api.workflowservice.v1.GetWorkerBuildIdCompatibilityResponse"\xb0\x01\x82\xd3\xe4\x93\x02\xa9\x01\x12N/namespaces/{namespace}/task-queues/{task_queue}/worker-build-id-compatibilityZW\x12U/api/v1/namespaces/{namespace}/task-queues/{task_queue}/worker-build-id-compatibility\x12\xaa\x01\n\x1bUpdateWorkerVersioningRules\x12\x43.temporal.api.workflowservice.v1.UpdateWorkerVersioningRulesRequest\x1a\x44.temporal.api.workflowservice.v1.UpdateWorkerVersioningRulesResponse"\x00\x12\xc6\x02\n\x18GetWorkerVersioningRules\x12@.temporal.api.workflowservice.v1.GetWorkerVersioningRulesRequest\x1a\x41.temporal.api.workflowservice.v1.GetWorkerVersioningRulesResponse"\xa4\x01\x82\xd3\xe4\x93\x02\x9d\x01\x12H/namespaces/{namespace}/task-queues/{task_queue}/worker-versioning-rulesZQ\x12O/api/v1/namespaces/{namespace}/task-queues/{task_queue}/worker-versioning-rules\x12\x97\x02\n\x19GetWorkerTaskReachability\x12\x41.temporal.api.workflowservice.v1.GetWorkerTaskReachabilityRequest\x1a\x42.temporal.api.workflowservice.v1.GetWorkerTaskReachabilityResponse"s\x82\xd3\xe4\x93\x02m\x12\x30/namespaces/{namespace}/worker-task-reachabilityZ9\x12\x37/api/v1/namespaces/{namespace}/worker-task-reachability\x12\xc8\x02\n\x12\x44\x65scribeDeployment\x12:.temporal.api.workflowservice.v1.DescribeDeploymentRequest\x1a;.temporal.api.workflowservice.v1.DescribeDeploymentResponse"\xb8\x01\x82\xd3\xe4\x93\x02\xb1\x01\x12R/namespaces/{namespace}/deployments/{deployment.series_name}/{deployment.build_id}Z[\x12Y/api/v1/namespaces/{namespace}/deployments/{deployment.series_name}/{deployment.build_id}\x12\x81\x04\n\x1f\x44\x65scribeWorkerDeploymentVersion\x12G.temporal.api.workflowservice.v1.DescribeWorkerDeploymentVersionRequest\x1aH.temporal.api.workflowservice.v1.DescribeWorkerDeploymentVersionResponse"\xca\x02\x82\xd3\xe4\x93\x02\xf7\x01\x12u/namespaces/{namespace}/worker-deployment-versions/{deployment_version.deployment_name}/{deployment_version.build_id}Z~\x12|/api/v1/namespaces/{namespace}/worker-deployment-versions/{deployment_version.deployment_name}/{deployment_version.build_id}\x8a\x9d\xcc\x1bG\n\x14temporal-resource-id\x12/deployment:{deployment_version.deployment_name}\x12\xdf\x01\n\x0fListDeployments\x12\x37.temporal.api.workflowservice.v1.ListDeploymentsRequest\x1a\x38.temporal.api.workflowservice.v1.ListDeploymentsResponse"Y\x82\xd3\xe4\x93\x02S\x12#/namespaces/{namespace}/deploymentsZ,\x12*/api/v1/namespaces/{namespace}/deployments\x12\xf7\x02\n\x19GetDeploymentReachability\x12\x41.temporal.api.workflowservice.v1.GetDeploymentReachabilityRequest\x1a\x42.temporal.api.workflowservice.v1.GetDeploymentReachabilityResponse"\xd2\x01\x82\xd3\xe4\x93\x02\xcb\x01\x12_/namespaces/{namespace}/deployments/{deployment.series_name}/{deployment.build_id}/reachabilityZh\x12\x66/api/v1/namespaces/{namespace}/deployments/{deployment.series_name}/{deployment.build_id}/reachability\x12\x99\x02\n\x14GetCurrentDeployment\x12<.temporal.api.workflowservice.v1.GetCurrentDeploymentRequest\x1a=.temporal.api.workflowservice.v1.GetCurrentDeploymentResponse"\x83\x01\x82\xd3\xe4\x93\x02}\x12\x38/namespaces/{namespace}/current-deployment/{series_name}ZA\x12?/api/v1/namespaces/{namespace}/current-deployment/{series_name}\x12\xb6\x02\n\x14SetCurrentDeployment\x12<.temporal.api.workflowservice.v1.SetCurrentDeploymentRequest\x1a=.temporal.api.workflowservice.v1.SetCurrentDeploymentResponse"\xa0\x01\x82\xd3\xe4\x93\x02\x99\x01"C/namespaces/{namespace}/current-deployment/{deployment.series_name}:\x01*ZO"J/api/v1/namespaces/{namespace}/current-deployment/{deployment.series_name}:\x01*\x12\xb0\x03\n!SetWorkerDeploymentCurrentVersion\x12I.temporal.api.workflowservice.v1.SetWorkerDeploymentCurrentVersionRequest\x1aJ.temporal.api.workflowservice.v1.SetWorkerDeploymentCurrentVersionResponse"\xf3\x01\x82\xd3\xe4\x93\x02\xb3\x01"P/namespaces/{namespace}/worker-deployments/{deployment_name}/set-current-version:\x01*Z\\"W/api/v1/namespaces/{namespace}/worker-deployments/{deployment_name}/set-current-version:\x01*\x8a\x9d\xcc\x1b\x34\n\x14temporal-resource-id\x12\x1c\x64\x65ployment:{deployment_name}\x12\xe7\x02\n\x18\x44\x65scribeWorkerDeployment\x12@.temporal.api.workflowservice.v1.DescribeWorkerDeploymentRequest\x1a\x41.temporal.api.workflowservice.v1.DescribeWorkerDeploymentResponse"\xc5\x01\x82\xd3\xe4\x93\x02\x85\x01\x12.temporal.api.workflowservice.v1.DeleteWorkerDeploymentRequest\x1a?.temporal.api.workflowservice.v1.DeleteWorkerDeploymentResponse"\xc5\x01\x82\xd3\xe4\x93\x02\x85\x01*.temporal.api.workflowservice.v1.ListWorkerDeploymentsResponse"g\x82\xd3\xe4\x93\x02\x61\x12*/namespaces/{namespace}/worker-deploymentsZ3\x12\x31/api/v1/namespaces/{namespace}/worker-deployments\x12\xae\x02\n\x16\x43reateWorkerDeployment\x12>.temporal.api.workflowservice.v1.CreateWorkerDeploymentRequest\x1a?.temporal.api.workflowservice.v1.CreateWorkerDeploymentResponse"\x92\x01\x82\xd3\xe4\x93\x02\x8b\x01".temporal.api.workflowservice.v1.DescribeBatchOperationRequest\x1a?.temporal.api.workflowservice.v1.DescribeBatchOperationResponse"\xa0\x01\x82\xd3\xe4\x93\x02o\x12\x31/namespaces/{namespace}/batch-operations/{job_id}Z:\x12\x38/api/v1/namespaces/{namespace}/batch-operations/{job_id}\x8a\x9d\xcc\x1b&\n\x14temporal-resource-id\x12\x0e\x62\x61tch:{job_id}\x12\xf5\x01\n\x13ListBatchOperations\x12;.temporal.api.workflowservice.v1.ListBatchOperationsRequest\x1a<.temporal.api.workflowservice.v1.ListBatchOperationsResponse"c\x82\xd3\xe4\x93\x02]\x12(/namespaces/{namespace}/batch-operationsZ1\x12//api/v1/namespaces/{namespace}/batch-operations\x12\xc4\x01\n\x12PollNexusTaskQueue\x12:.temporal.api.workflowservice.v1.PollNexusTaskQueueRequest\x1a;.temporal.api.workflowservice.v1.PollNexusTaskQueueResponse"5\x8a\x9d\xcc\x1b\x30\n\x14temporal-resource-id\x12\x18poller:{poller_group_id}\x12\xd9\x01\n\x19RespondNexusTaskCompleted\x12\x41.temporal.api.workflowservice.v1.RespondNexusTaskCompletedRequest\x1a\x42.temporal.api.workflowservice.v1.RespondNexusTaskCompletedResponse"5\x8a\x9d\xcc\x1b\x30\n\x14temporal-resource-id\x12\x18poller:{poller_group_id}\x12\xd0\x01\n\x16RespondNexusTaskFailed\x12>.temporal.api.workflowservice.v1.RespondNexusTaskFailedRequest\x1a?.temporal.api.workflowservice.v1.RespondNexusTaskFailedResponse"5\x8a\x9d\xcc\x1b\x30\n\x14temporal-resource-id\x12\x18poller:{poller_group_id}\x12\xe8\x02\n\x15UpdateActivityOptions\x12=.temporal.api.workflowservice.v1.UpdateActivityOptionsRequest\x1a>.temporal.api.workflowservice.v1.UpdateActivityOptionsResponse"\xcf\x01\x82\xd3\xe4\x93\x02\x8b\x01".temporal.api.workflowservice.v1.RecordWorkerHeartbeatResponse"\x95\x01\x82\xd3\xe4\x93\x02\x65")/namespaces/{namespace}/workers/heartbeat:\x01*Z5"0/api/v1/namespaces/{namespace}/workers/heartbeat:\x01*\x8a\x9d\xcc\x1b%\n\x14temporal-resource-id\x12\r{resource_id}\x12\xcb\x01\n\x0bListWorkers\x12\x33.temporal.api.workflowservice.v1.ListWorkersRequest\x1a\x34.temporal.api.workflowservice.v1.ListWorkersResponse"Q\x82\xd3\xe4\x93\x02K\x12\x1f/namespaces/{namespace}/workersZ(\x12&/api/v1/namespaces/{namespace}/workers\x12\xe2\x02\n\x15UpdateTaskQueueConfig\x12=.temporal.api.workflowservice.v1.UpdateTaskQueueConfigRequest\x1a>.temporal.api.workflowservice.v1.UpdateTaskQueueConfigResponse"\xc9\x01\x82\xd3\xe4\x93\x02\x8f\x01">/namespaces/{namespace}/task-queues/{task_queue}/update-config:\x01*ZJ"E/api/v1/namespaces/{namespace}/task-queues/{task_queue}/update-config:\x01*\x8a\x9d\xcc\x1b.\n\x14temporal-resource-id\x12\x16taskqueue:{task_queue}\x12\xa8\x02\n\x11\x46\x65tchWorkerConfig\x12\x39.temporal.api.workflowservice.v1.FetchWorkerConfigRequest\x1a:.temporal.api.workflowservice.v1.FetchWorkerConfigResponse"\x9b\x01\x82\xd3\xe4\x93\x02k",/namespaces/{namespace}/workers/fetch-config:\x01*Z8"3/api/v1/namespaces/{namespace}/workers/fetch-config:\x01*\x8a\x9d\xcc\x1b%\n\x14temporal-resource-id\x12\r{resource_id}\x12\xad\x02\n\x12UpdateWorkerConfig\x12:.temporal.api.workflowservice.v1.UpdateWorkerConfigRequest\x1a;.temporal.api.workflowservice.v1.UpdateWorkerConfigResponse"\x9d\x01\x82\xd3\xe4\x93\x02m"-/namespaces/{namespace}/workers/update-config:\x01*Z9"4/api/v1/namespaces/{namespace}/workers/update-config:\x01*\x8a\x9d\xcc\x1b%\n\x14temporal-resource-id\x12\r{resource_id}\x12\xcd\x02\n\x0e\x44\x65scribeWorker\x12\x36.temporal.api.workflowservice.v1.DescribeWorkerRequest\x1a\x37.temporal.api.workflowservice.v1.DescribeWorkerResponse"\xc9\x01\x82\xd3\xe4\x93\x02\x89\x01\x12>/namespaces/{namespace}/workers/describe/{worker_instance_key}ZG\x12\x45/api/v1/namespaces/{namespace}/workers/describe/{worker_instance_key}\x8a\x9d\xcc\x1b\x34\n\x14temporal-resource-id\x12\x1cworker:{worker_instance_key}\x12\xd2\x02\n\x16PauseWorkflowExecution\x12>.temporal.api.workflowservice.v1.PauseWorkflowExecutionRequest\x1a?.temporal.api.workflowservice.v1.PauseWorkflowExecutionResponse"\xb6\x01\x82\xd3\xe4\x93\x02}"5/namespaces/{namespace}/workflows/{workflow_id}/pause:\x01*ZA"/api/v1/namespaces/{namespace}/workflows/{workflow_id}/unpause:\x01*\x8a\x9d\xcc\x1b.\n\x14temporal-resource-id\x12\x16workflow:{workflow_id}\x12\xc8\x02\n\x16StartActivityExecution\x12>.temporal.api.workflowservice.v1.StartActivityExecutionRequest\x1a?.temporal.api.workflowservice.v1.StartActivityExecutionResponse"\xac\x01\x82\xd3\xe4\x93\x02s"0/namespaces/{namespace}/activities/{activity_id}:\x01*Z<"7/api/v1/namespaces/{namespace}/activities/{activity_id}:\x01*\x8a\x9d\xcc\x1b.\n\x14temporal-resource-id\x12\x16\x61\x63tivity:{activity_id}\x12\xb6\x02\n\x1cStartNexusOperationExecution\x12\x44.temporal.api.workflowservice.v1.StartNexusOperationExecutionRequest\x1a\x45.temporal.api.workflowservice.v1.StartNexusOperationExecutionResponse"\x88\x01\x82\xd3\xe4\x93\x02\x81\x01"7/namespaces/{namespace}/nexus-operations/{operation_id}:\x01*ZC">/api/v1/namespaces/{namespace}/nexus-operations/{operation_id}:\x01*\x12\xcb\x02\n\x19\x44\x65scribeActivityExecution\x12\x41.temporal.api.workflowservice.v1.DescribeActivityExecutionRequest\x1a\x42.temporal.api.workflowservice.v1.DescribeActivityExecutionResponse"\xa6\x01\x82\xd3\xe4\x93\x02m\x12\x30/namespaces/{namespace}/activities/{activity_id}Z9\x12\x37/api/v1/namespaces/{namespace}/activities/{activity_id}\x8a\x9d\xcc\x1b.\n\x14temporal-resource-id\x12\x16\x61\x63tivity:{activity_id}\x12\xb8\x02\n\x1f\x44\x65scribeNexusOperationExecution\x12G.temporal.api.workflowservice.v1.DescribeNexusOperationExecutionRequest\x1aH.temporal.api.workflowservice.v1.DescribeNexusOperationExecutionResponse"\x81\x01\x82\xd3\xe4\x93\x02{\x12\x37/namespaces/{namespace}/nexus-operations/{operation_id}Z@\x12>/api/v1/namespaces/{namespace}/nexus-operations/{operation_id}\x12\xcf\x02\n\x15PollActivityExecution\x12=.temporal.api.workflowservice.v1.PollActivityExecutionRequest\x1a>.temporal.api.workflowservice.v1.PollActivityExecutionResponse"\xb6\x01\x82\xd3\xe4\x93\x02}\x12\x38/namespaces/{namespace}/activities/{activity_id}/outcomeZA\x12?/api/v1/namespaces/{namespace}/activities/{activity_id}/outcome\x8a\x9d\xcc\x1b.\n\x14temporal-resource-id\x12\x16\x61\x63tivity:{activity_id}\x12\xb7\x02\n\x1bPollNexusOperationExecution\x12\x43.temporal.api.workflowservice.v1.PollNexusOperationExecutionRequest\x1a\x44.temporal.api.workflowservice.v1.PollNexusOperationExecutionResponse"\x8c\x01\x82\xd3\xe4\x93\x02\x85\x01\x12.temporal.api.workflowservice.v1.ListActivityExecutionsRequest\x1a?.temporal.api.workflowservice.v1.ListActivityExecutionsResponse"W\x82\xd3\xe4\x93\x02Q\x12"/namespaces/{namespace}/activitiesZ+\x12)/api/v1/namespaces/{namespace}/activities\x12\x90\x02\n\x1cListNexusOperationExecutions\x12\x44.temporal.api.workflowservice.v1.ListNexusOperationExecutionsRequest\x1a\x45.temporal.api.workflowservice.v1.ListNexusOperationExecutionsResponse"c\x82\xd3\xe4\x93\x02]\x12(/namespaces/{namespace}/nexus-operationsZ1\x12//api/v1/namespaces/{namespace}/nexus-operations\x12\xfd\x01\n\x17\x43ountActivityExecutions\x12?.temporal.api.workflowservice.v1.CountActivityExecutionsRequest\x1a@.temporal.api.workflowservice.v1.CountActivityExecutionsResponse"_\x82\xd3\xe4\x93\x02Y\x12&/namespaces/{namespace}/activity-countZ/\x12-/api/v1/namespaces/{namespace}/activity-count\x12\x9d\x02\n\x1d\x43ountNexusOperationExecutions\x12\x45.temporal.api.workflowservice.v1.CountNexusOperationExecutionsRequest\x1a\x46.temporal.api.workflowservice.v1.CountNexusOperationExecutionsResponse"m\x82\xd3\xe4\x93\x02g\x12-/namespaces/{namespace}/nexus-operation-countZ6\x12\x34/api/v1/namespaces/{namespace}/nexus-operation-count\x12\xef\x02\n\x1eRequestCancelActivityExecution\x12\x46.temporal.api.workflowservice.v1.RequestCancelActivityExecutionRequest\x1aG.temporal.api.workflowservice.v1.RequestCancelActivityExecutionResponse"\xbb\x01\x82\xd3\xe4\x93\x02\x81\x01"7/namespaces/{namespace}/activities/{activity_id}/cancel:\x01*ZC">/api/v1/namespaces/{namespace}/activities/{activity_id}/cancel:\x01*\x8a\x9d\xcc\x1b.\n\x14temporal-resource-id\x12\x16\x61\x63tivity:{activity_id}\x12\xdc\x02\n$RequestCancelNexusOperationExecution\x12L.temporal.api.workflowservice.v1.RequestCancelNexusOperationExecutionRequest\x1aM.temporal.api.workflowservice.v1.RequestCancelNexusOperationExecutionResponse"\x96\x01\x82\xd3\xe4\x93\x02\x8f\x01">/namespaces/{namespace}/nexus-operations/{operation_id}/cancel:\x01*ZJ"E/api/v1/namespaces/{namespace}/nexus-operations/{operation_id}/cancel:\x01*\x12\xe9\x02\n\x1aTerminateActivityExecution\x12\x42.temporal.api.workflowservice.v1.TerminateActivityExecutionRequest\x1a\x43.temporal.api.workflowservice.v1.TerminateActivityExecutionResponse"\xc1\x01\x82\xd3\xe4\x93\x02\x87\x01":/namespaces/{namespace}/activities/{activity_id}/terminate:\x01*ZF"A/api/v1/namespaces/{namespace}/activities/{activity_id}/terminate:\x01*\x8a\x9d\xcc\x1b.\n\x14temporal-resource-id\x12\x16\x61\x63tivity:{activity_id}\x12\x9e\x01\n\x17\x44\x65leteActivityExecution\x12?.temporal.api.workflowservice.v1.DeleteActivityExecutionRequest\x1a@.temporal.api.workflowservice.v1.DeleteActivityExecutionResponse"\x00\x12\xfd\x03\n\x16PauseActivityExecution\x12>.temporal.api.workflowservice.v1.PauseActivityExecutionRequest\x1a?.temporal.api.workflowservice.v1.PauseActivityExecutionResponse"\xe1\x02\x82\xd3\xe4\x93\x02\xb0\x02"6/namespaces/{namespace}/activities/{activity_id}/pause:\x01*ZB"=/api/v1/namespaces/{namespace}/activities/{activity_id}/pause:\x01*ZS"N/namespaces/{namespace}/workflows/{workflow_id}/activities/{activity_id}/pause:\x01*ZZ"U/api/v1/namespaces/{namespace}/workflows/{workflow_id}/activities/{activity_id}/pause:\x01*\x8a\x9d\xcc\x1b%\n\x14temporal-resource-id\x12\r{resource_id}\x12\xfd\x03\n\x16ResetActivityExecution\x12>.temporal.api.workflowservice.v1.ResetActivityExecutionRequest\x1a?.temporal.api.workflowservice.v1.ResetActivityExecutionResponse"\xe1\x02\x82\xd3\xe4\x93\x02\xb0\x02"6/namespaces/{namespace}/activities/{activity_id}/reset:\x01*ZB"=/api/v1/namespaces/{namespace}/activities/{activity_id}/reset:\x01*ZS"N/namespaces/{namespace}/workflows/{workflow_id}/activities/{activity_id}/reset:\x01*ZZ"U/api/v1/namespaces/{namespace}/workflows/{workflow_id}/activities/{activity_id}/reset:\x01*\x8a\x9d\xcc\x1b%\n\x14temporal-resource-id\x12\r{resource_id}\x12\x8b\x04\n\x18UnpauseActivityExecution\x12@.temporal.api.workflowservice.v1.UnpauseActivityExecutionRequest\x1a\x41.temporal.api.workflowservice.v1.UnpauseActivityExecutionResponse"\xe9\x02\x82\xd3\xe4\x93\x02\xb8\x02"8/namespaces/{namespace}/activities/{activity_id}/unpause:\x01*ZD"?/api/v1/namespaces/{namespace}/activities/{activity_id}/unpause:\x01*ZU"P/namespaces/{namespace}/workflows/{workflow_id}/activities/{activity_id}/unpause:\x01*Z\\"W/api/v1/namespaces/{namespace}/workflows/{workflow_id}/activities/{activity_id}/unpause:\x01*\x8a\x9d\xcc\x1b%\n\x14temporal-resource-id\x12\r{resource_id}\x12\xb9\x04\n\x1eUpdateActivityExecutionOptions\x12\x46.temporal.api.workflowservice.v1.UpdateActivityExecutionOptionsRequest\x1aG.temporal.api.workflowservice.v1.UpdateActivityExecutionOptionsResponse"\x85\x03\x82\xd3\xe4\x93\x02\xd4\x02"?/namespaces/{namespace}/activities/{activity_id}/update-options:\x01*ZK"F/api/v1/namespaces/{namespace}/activities/{activity_id}/update-options:\x01*Z\\"W/namespaces/{namespace}/workflows/{workflow_id}/activities/{activity_id}/update-options:\x01*Zc"^/api/v1/namespaces/{namespace}/workflows/{workflow_id}/activities/{activity_id}/update-options:\x01*\x8a\x9d\xcc\x1b%\n\x14temporal-resource-id\x12\r{resource_id}\x12\xd6\x02\n TerminateNexusOperationExecution\x12H.temporal.api.workflowservice.v1.TerminateNexusOperationExecutionRequest\x1aI.temporal.api.workflowservice.v1.TerminateNexusOperationExecutionResponse"\x9c\x01\x82\xd3\xe4\x93\x02\x95\x01"A/namespaces/{namespace}/nexus-operations/{operation_id}/terminate:\x01*ZM"H/api/v1/namespaces/{namespace}/nexus-operations/{operation_id}/terminate:\x01*\x12\xb0\x01\n\x1d\x44\x65leteNexusOperationExecution\x12\x45.temporal.api.workflowservice.v1.DeleteNexusOperationExecutionRequest\x1a\x46.temporal.api.workflowservice.v1.DeleteNexusOperationExecutionResponse"\x00\x42\xb6\x01\n"io.temporal.api.workflowservice.v1B\x0cServiceProtoP\x01Z5go.temporal.io/api/workflowservice/v1;workflowservice\xaa\x02!Temporalio.Api.WorkflowService.V1\xea\x02$Temporalio::Api::WorkflowService::V1b\x06proto3' + b'\n-temporal/api/workflowservice/v1/service.proto\x12\x1ftemporal.api.workflowservice.v1\x1a\x1cgoogle/api/annotations.proto\x1a!nexusannotations/v1/options.proto\x1a+temporal/api/protometa/v1/annotations.proto\x1a\x36temporal/api/workflowservice/v1/request_response.proto2\xbd\xad\x02\n\x0fWorkflowService\x12\xc3\x01\n\x11RegisterNamespace\x12\x39.temporal.api.workflowservice.v1.RegisterNamespaceRequest\x1a:.temporal.api.workflowservice.v1.RegisterNamespaceResponse"7\x82\xd3\xe4\x93\x02\x31"\x13/cluster/namespaces:\x01*Z\x17"\x12/api/v1/namespaces:\x01*\x12\xd5\x01\n\x11\x44\x65scribeNamespace\x12\x39.temporal.api.workflowservice.v1.DescribeNamespaceRequest\x1a:.temporal.api.workflowservice.v1.DescribeNamespaceResponse"I\x82\xd3\xe4\x93\x02\x43\x12\x1f/cluster/namespaces/{namespace}Z \x12\x1e/api/v1/namespaces/{namespace}\x12\xb4\x01\n\x0eListNamespaces\x12\x36.temporal.api.workflowservice.v1.ListNamespacesRequest\x1a\x37.temporal.api.workflowservice.v1.ListNamespacesResponse"1\x82\xd3\xe4\x93\x02+\x12\x13/cluster/namespacesZ\x14\x12\x12/api/v1/namespaces\x12\xe3\x01\n\x0fUpdateNamespace\x12\x37.temporal.api.workflowservice.v1.UpdateNamespaceRequest\x1a\x38.temporal.api.workflowservice.v1.UpdateNamespaceResponse"]\x82\xd3\xe4\x93\x02W"&/cluster/namespaces/{namespace}/update:\x01*Z*"%/api/v1/namespaces/{namespace}/update:\x01*\x12\x8f\x01\n\x12\x44\x65precateNamespace\x12:.temporal.api.workflowservice.v1.DeprecateNamespaceRequest\x1a;.temporal.api.workflowservice.v1.DeprecateNamespaceResponse"\x00\x12\xc6\x02\n\x16StartWorkflowExecution\x12>.temporal.api.workflowservice.v1.StartWorkflowExecutionRequest\x1a?.temporal.api.workflowservice.v1.StartWorkflowExecutionResponse"\xaa\x01\x82\xd3\xe4\x93\x02q"//namespaces/{namespace}/workflows/{workflow_id}:\x01*Z;"6/api/v1/namespaces/{namespace}/workflows/{workflow_id}:\x01*\x8a\x9d\xcc\x1b.\n\x14temporal-resource-id\x12\x16workflow:{workflow_id}\x12\xc2\x01\n\x15\x45xecuteMultiOperation\x12=.temporal.api.workflowservice.v1.ExecuteMultiOperationRequest\x1a>.temporal.api.workflowservice.v1.ExecuteMultiOperationResponse"*\x8a\x9d\xcc\x1b%\n\x14temporal-resource-id\x12\r{resource_id}\x12\xfe\x02\n\x1bGetWorkflowExecutionHistory\x12\x43.temporal.api.workflowservice.v1.GetWorkflowExecutionHistoryRequest\x1a\x44.temporal.api.workflowservice.v1.GetWorkflowExecutionHistoryResponse"\xd3\x01\x82\xd3\xe4\x93\x02\x8f\x01\x12\x41/namespaces/{namespace}/workflows/{execution.workflow_id}/historyZJ\x12H/api/v1/namespaces/{namespace}/workflows/{execution.workflow_id}/history\x8a\x9d\xcc\x1b\x38\n\x14temporal-resource-id\x12 workflow:{execution.workflow_id}\x12\xa3\x03\n"GetWorkflowExecutionHistoryReverse\x12J.temporal.api.workflowservice.v1.GetWorkflowExecutionHistoryReverseRequest\x1aK.temporal.api.workflowservice.v1.GetWorkflowExecutionHistoryReverseResponse"\xe3\x01\x82\xd3\xe4\x93\x02\x9f\x01\x12I/namespaces/{namespace}/workflows/{execution.workflow_id}/history-reverseZR\x12P/api/v1/namespaces/{namespace}/workflows/{execution.workflow_id}/history-reverse\x8a\x9d\xcc\x1b\x38\n\x14temporal-resource-id\x12 workflow:{execution.workflow_id}\x12\xcd\x01\n\x15PollWorkflowTaskQueue\x12=.temporal.api.workflowservice.v1.PollWorkflowTaskQueueRequest\x1a>.temporal.api.workflowservice.v1.PollWorkflowTaskQueueResponse"5\x8a\x9d\xcc\x1b\x30\n\x14temporal-resource-id\x12\x18poller:{poller_group_id}\x12\xd7\x01\n\x1cRespondWorkflowTaskCompleted\x12\x44.temporal.api.workflowservice.v1.RespondWorkflowTaskCompletedRequest\x1a\x45.temporal.api.workflowservice.v1.RespondWorkflowTaskCompletedResponse"*\x8a\x9d\xcc\x1b%\n\x14temporal-resource-id\x12\r{resource_id}\x12\xce\x01\n\x19RespondWorkflowTaskFailed\x12\x41.temporal.api.workflowservice.v1.RespondWorkflowTaskFailedRequest\x1a\x42.temporal.api.workflowservice.v1.RespondWorkflowTaskFailedResponse"*\x8a\x9d\xcc\x1b%\n\x14temporal-resource-id\x12\r{resource_id}\x12\xcd\x01\n\x15PollActivityTaskQueue\x12=.temporal.api.workflowservice.v1.PollActivityTaskQueueRequest\x1a>.temporal.api.workflowservice.v1.PollActivityTaskQueueResponse"5\x8a\x9d\xcc\x1b\x30\n\x14temporal-resource-id\x12\x18poller:{poller_group_id}\x12\xc2\x02\n\x1bRecordActivityTaskHeartbeat\x12\x43.temporal.api.workflowservice.v1.RecordActivityTaskHeartbeatRequest\x1a\x44.temporal.api.workflowservice.v1.RecordActivityTaskHeartbeatResponse"\x97\x01\x82\xd3\xe4\x93\x02g"*/namespaces/{namespace}/activity-heartbeat:\x01*Z6"1/api/v1/namespaces/{namespace}/activity-heartbeat:\x01*\x8a\x9d\xcc\x1b%\n\x14temporal-resource-id\x12\r{resource_id}\x12\xa8\x04\n\x1fRecordActivityTaskHeartbeatById\x12G.temporal.api.workflowservice.v1.RecordActivityTaskHeartbeatByIdRequest\x1aH.temporal.api.workflowservice.v1.RecordActivityTaskHeartbeatByIdResponse"\xf1\x02\x82\xd3\xe4\x93\x02\xc0\x02":/namespaces/{namespace}/activities/{activity_id}/heartbeat:\x01*ZF"A/api/v1/namespaces/{namespace}/activities/{activity_id}/heartbeat:\x01*ZW"R/namespaces/{namespace}/workflows/{workflow_id}/activities/{activity_id}/heartbeat:\x01*Z^"Y/api/v1/namespaces/{namespace}/workflows/{workflow_id}/activities/{activity_id}/heartbeat:\x01*\x8a\x9d\xcc\x1b%\n\x14temporal-resource-id\x12\r{resource_id}\x12\xc3\x02\n\x1cRespondActivityTaskCompleted\x12\x44.temporal.api.workflowservice.v1.RespondActivityTaskCompletedRequest\x1a\x45.temporal.api.workflowservice.v1.RespondActivityTaskCompletedResponse"\x95\x01\x82\xd3\xe4\x93\x02\x65")/namespaces/{namespace}/activity-complete:\x01*Z5"0/api/v1/namespaces/{namespace}/activity-complete:\x01*\x8a\x9d\xcc\x1b%\n\x14temporal-resource-id\x12\r{resource_id}\x12\xa7\x04\n RespondActivityTaskCompletedById\x12H.temporal.api.workflowservice.v1.RespondActivityTaskCompletedByIdRequest\x1aI.temporal.api.workflowservice.v1.RespondActivityTaskCompletedByIdResponse"\xed\x02\x82\xd3\xe4\x93\x02\xbc\x02"9/namespaces/{namespace}/activities/{activity_id}/complete:\x01*ZE"@/api/v1/namespaces/{namespace}/activities/{activity_id}/complete:\x01*ZV"Q/namespaces/{namespace}/workflows/{workflow_id}/activities/{activity_id}/complete:\x01*Z]"X/api/v1/namespaces/{namespace}/workflows/{workflow_id}/activities/{activity_id}/complete:\x01*\x8a\x9d\xcc\x1b%\n\x14temporal-resource-id\x12\r{resource_id}\x12\xb2\x02\n\x19RespondActivityTaskFailed\x12\x41.temporal.api.workflowservice.v1.RespondActivityTaskFailedRequest\x1a\x42.temporal.api.workflowservice.v1.RespondActivityTaskFailedResponse"\x8d\x01\x82\xd3\xe4\x93\x02]"%/namespaces/{namespace}/activity-fail:\x01*Z1",/api/v1/namespaces/{namespace}/activity-fail:\x01*\x8a\x9d\xcc\x1b%\n\x14temporal-resource-id\x12\r{resource_id}\x12\x8e\x04\n\x1dRespondActivityTaskFailedById\x12\x45.temporal.api.workflowservice.v1.RespondActivityTaskFailedByIdRequest\x1a\x46.temporal.api.workflowservice.v1.RespondActivityTaskFailedByIdResponse"\xdd\x02\x82\xd3\xe4\x93\x02\xac\x02"5/namespaces/{namespace}/activities/{activity_id}/fail:\x01*ZA".temporal.api.workflowservice.v1.ResetWorkflowExecutionRequest\x1a?.temporal.api.workflowservice.v1.ResetWorkflowExecutionResponse"\xf0\x01\x82\xd3\xe4\x93\x02\xa3\x01"H/namespaces/{namespace}/workflows/{workflow_execution.workflow_id}/reset:\x01*ZT"O/api/v1/namespaces/{namespace}/workflows/{workflow_execution.workflow_id}/reset:\x01*\x8a\x9d\xcc\x1b\x41\n\x14temporal-resource-id\x12)workflow:{workflow_execution.workflow_id}\x12\xa0\x03\n\x1aTerminateWorkflowExecution\x12\x42.temporal.api.workflowservice.v1.TerminateWorkflowExecutionRequest\x1a\x43.temporal.api.workflowservice.v1.TerminateWorkflowExecutionResponse"\xf8\x01\x82\xd3\xe4\x93\x02\xab\x01"L/namespaces/{namespace}/workflows/{workflow_execution.workflow_id}/terminate:\x01*ZX"S/api/v1/namespaces/{namespace}/workflows/{workflow_execution.workflow_id}/terminate:\x01*\x8a\x9d\xcc\x1b\x41\n\x14temporal-resource-id\x12)workflow:{workflow_execution.workflow_id}\x12\xe4\x01\n\x17\x44\x65leteWorkflowExecution\x12?.temporal.api.workflowservice.v1.DeleteWorkflowExecutionRequest\x1a@.temporal.api.workflowservice.v1.DeleteWorkflowExecutionResponse"F\x8a\x9d\xcc\x1b\x41\n\x14temporal-resource-id\x12)workflow:{workflow_execution.workflow_id}\x12\xa7\x01\n\x1aListOpenWorkflowExecutions\x12\x42.temporal.api.workflowservice.v1.ListOpenWorkflowExecutionsRequest\x1a\x43.temporal.api.workflowservice.v1.ListOpenWorkflowExecutionsResponse"\x00\x12\xad\x01\n\x1cListClosedWorkflowExecutions\x12\x44.temporal.api.workflowservice.v1.ListClosedWorkflowExecutionsRequest\x1a\x45.temporal.api.workflowservice.v1.ListClosedWorkflowExecutionsResponse"\x00\x12\xf0\x01\n\x16ListWorkflowExecutions\x12>.temporal.api.workflowservice.v1.ListWorkflowExecutionsRequest\x1a?.temporal.api.workflowservice.v1.ListWorkflowExecutionsResponse"U\x82\xd3\xe4\x93\x02O\x12!/namespaces/{namespace}/workflowsZ*\x12(/api/v1/namespaces/{namespace}/workflows\x12\x9a\x02\n\x1eListArchivedWorkflowExecutions\x12\x46.temporal.api.workflowservice.v1.ListArchivedWorkflowExecutionsRequest\x1aG.temporal.api.workflowservice.v1.ListArchivedWorkflowExecutionsResponse"g\x82\xd3\xe4\x93\x02\x61\x12*/namespaces/{namespace}/archived-workflowsZ3\x12\x31/api/v1/namespaces/{namespace}/archived-workflows\x12\x9b\x01\n\x16ScanWorkflowExecutions\x12>.temporal.api.workflowservice.v1.ScanWorkflowExecutionsRequest\x1a?.temporal.api.workflowservice.v1.ScanWorkflowExecutionsResponse"\x00\x12\xfd\x01\n\x17\x43ountWorkflowExecutions\x12?.temporal.api.workflowservice.v1.CountWorkflowExecutionsRequest\x1a@.temporal.api.workflowservice.v1.CountWorkflowExecutionsResponse"_\x82\xd3\xe4\x93\x02Y\x12&/namespaces/{namespace}/workflow-countZ/\x12-/api/v1/namespaces/{namespace}/workflow-count\x12\x92\x01\n\x13GetSearchAttributes\x12;.temporal.api.workflowservice.v1.GetSearchAttributesRequest\x1a<.temporal.api.workflowservice.v1.GetSearchAttributesResponse"\x00\x12\xd9\x01\n\x19RespondQueryTaskCompleted\x12\x41.temporal.api.workflowservice.v1.RespondQueryTaskCompletedRequest\x1a\x42.temporal.api.workflowservice.v1.RespondQueryTaskCompletedResponse"5\x8a\x9d\xcc\x1b\x30\n\x14temporal-resource-id\x12\x18poller:{poller_group_id}\x12\xd2\x01\n\x14ResetStickyTaskQueue\x12<.temporal.api.workflowservice.v1.ResetStickyTaskQueueRequest\x1a=.temporal.api.workflowservice.v1.ResetStickyTaskQueueResponse"=\x8a\x9d\xcc\x1b\x38\n\x14temporal-resource-id\x12 workflow:{execution.workflow_id}\x12\x83\x01\n\x0eShutdownWorker\x12\x36.temporal.api.workflowservice.v1.ShutdownWorkerRequest\x1a\x37.temporal.api.workflowservice.v1.ShutdownWorkerResponse"\x00\x12\xfc\x02\n\rQueryWorkflow\x12\x35.temporal.api.workflowservice.v1.QueryWorkflowRequest\x1a\x36.temporal.api.workflowservice.v1.QueryWorkflowResponse"\xfb\x01\x82\xd3\xe4\x93\x02\xb7\x01"R/namespaces/{namespace}/workflows/{execution.workflow_id}/query/{query.query_type}:\x01*Z^"Y/api/v1/namespaces/{namespace}/workflows/{execution.workflow_id}/query/{query.query_type}:\x01*\x8a\x9d\xcc\x1b\x38\n\x14temporal-resource-id\x12 workflow:{execution.workflow_id}\x12\xe7\x02\n\x19\x44\x65scribeWorkflowExecution\x12\x41.temporal.api.workflowservice.v1.DescribeWorkflowExecutionRequest\x1a\x42.temporal.api.workflowservice.v1.DescribeWorkflowExecutionResponse"\xc2\x01\x82\xd3\xe4\x93\x02\x7f\x12\x39/namespaces/{namespace}/workflows/{execution.workflow_id}ZB\x12@/api/v1/namespaces/{namespace}/workflows/{execution.workflow_id}\x8a\x9d\xcc\x1b\x38\n\x14temporal-resource-id\x12 workflow:{execution.workflow_id}\x12\xc2\x02\n\x11\x44\x65scribeTaskQueue\x12\x39.temporal.api.workflowservice.v1.DescribeTaskQueueRequest\x1a:.temporal.api.workflowservice.v1.DescribeTaskQueueResponse"\xb5\x01\x82\xd3\xe4\x93\x02w\x12\x35/namespaces/{namespace}/task-queues/{task_queue.name}Z>\x12/namespaces/{namespace}/schedules/{schedule_id}/matching-timesZG\x12\x45/api/v1/namespaces/{namespace}/schedules/{schedule_id}/matching-times\x8a\x9d\xcc\x1b.\n\x14temporal-resource-id\x12\x16schedule:{schedule_id}\x12\xa8\x02\n\x0e\x44\x65leteSchedule\x12\x36.temporal.api.workflowservice.v1.DeleteScheduleRequest\x1a\x37.temporal.api.workflowservice.v1.DeleteScheduleResponse"\xa4\x01\x82\xd3\xe4\x93\x02k*//namespaces/{namespace}/schedules/{schedule_id}Z8*6/api/v1/namespaces/{namespace}/schedules/{schedule_id}\x8a\x9d\xcc\x1b.\n\x14temporal-resource-id\x12\x16schedule:{schedule_id}\x12\xd5\x01\n\rListSchedules\x12\x35.temporal.api.workflowservice.v1.ListSchedulesRequest\x1a\x36.temporal.api.workflowservice.v1.ListSchedulesResponse"U\x82\xd3\xe4\x93\x02O\x12!/namespaces/{namespace}/schedulesZ*\x12(/api/v1/namespaces/{namespace}/schedules\x12\xe2\x01\n\x0e\x43ountSchedules\x12\x36.temporal.api.workflowservice.v1.CountSchedulesRequest\x1a\x37.temporal.api.workflowservice.v1.CountSchedulesResponse"_\x82\xd3\xe4\x93\x02Y\x12&/namespaces/{namespace}/schedule-countZ/\x12-/api/v1/namespaces/{namespace}/schedule-count\x12\xb9\x01\n UpdateWorkerBuildIdCompatibility\x12H.temporal.api.workflowservice.v1.UpdateWorkerBuildIdCompatibilityRequest\x1aI.temporal.api.workflowservice.v1.UpdateWorkerBuildIdCompatibilityResponse"\x00\x12\xe1\x02\n\x1dGetWorkerBuildIdCompatibility\x12\x45.temporal.api.workflowservice.v1.GetWorkerBuildIdCompatibilityRequest\x1a\x46.temporal.api.workflowservice.v1.GetWorkerBuildIdCompatibilityResponse"\xb0\x01\x82\xd3\xe4\x93\x02\xa9\x01\x12N/namespaces/{namespace}/task-queues/{task_queue}/worker-build-id-compatibilityZW\x12U/api/v1/namespaces/{namespace}/task-queues/{task_queue}/worker-build-id-compatibility\x12\xaa\x01\n\x1bUpdateWorkerVersioningRules\x12\x43.temporal.api.workflowservice.v1.UpdateWorkerVersioningRulesRequest\x1a\x44.temporal.api.workflowservice.v1.UpdateWorkerVersioningRulesResponse"\x00\x12\xc6\x02\n\x18GetWorkerVersioningRules\x12@.temporal.api.workflowservice.v1.GetWorkerVersioningRulesRequest\x1a\x41.temporal.api.workflowservice.v1.GetWorkerVersioningRulesResponse"\xa4\x01\x82\xd3\xe4\x93\x02\x9d\x01\x12H/namespaces/{namespace}/task-queues/{task_queue}/worker-versioning-rulesZQ\x12O/api/v1/namespaces/{namespace}/task-queues/{task_queue}/worker-versioning-rules\x12\x97\x02\n\x19GetWorkerTaskReachability\x12\x41.temporal.api.workflowservice.v1.GetWorkerTaskReachabilityRequest\x1a\x42.temporal.api.workflowservice.v1.GetWorkerTaskReachabilityResponse"s\x82\xd3\xe4\x93\x02m\x12\x30/namespaces/{namespace}/worker-task-reachabilityZ9\x12\x37/api/v1/namespaces/{namespace}/worker-task-reachability\x12\xc8\x02\n\x12\x44\x65scribeDeployment\x12:.temporal.api.workflowservice.v1.DescribeDeploymentRequest\x1a;.temporal.api.workflowservice.v1.DescribeDeploymentResponse"\xb8\x01\x82\xd3\xe4\x93\x02\xb1\x01\x12R/namespaces/{namespace}/deployments/{deployment.series_name}/{deployment.build_id}Z[\x12Y/api/v1/namespaces/{namespace}/deployments/{deployment.series_name}/{deployment.build_id}\x12\x81\x04\n\x1f\x44\x65scribeWorkerDeploymentVersion\x12G.temporal.api.workflowservice.v1.DescribeWorkerDeploymentVersionRequest\x1aH.temporal.api.workflowservice.v1.DescribeWorkerDeploymentVersionResponse"\xca\x02\x82\xd3\xe4\x93\x02\xf7\x01\x12u/namespaces/{namespace}/worker-deployment-versions/{deployment_version.deployment_name}/{deployment_version.build_id}Z~\x12|/api/v1/namespaces/{namespace}/worker-deployment-versions/{deployment_version.deployment_name}/{deployment_version.build_id}\x8a\x9d\xcc\x1bG\n\x14temporal-resource-id\x12/deployment:{deployment_version.deployment_name}\x12\xdf\x01\n\x0fListDeployments\x12\x37.temporal.api.workflowservice.v1.ListDeploymentsRequest\x1a\x38.temporal.api.workflowservice.v1.ListDeploymentsResponse"Y\x82\xd3\xe4\x93\x02S\x12#/namespaces/{namespace}/deploymentsZ,\x12*/api/v1/namespaces/{namespace}/deployments\x12\xf7\x02\n\x19GetDeploymentReachability\x12\x41.temporal.api.workflowservice.v1.GetDeploymentReachabilityRequest\x1a\x42.temporal.api.workflowservice.v1.GetDeploymentReachabilityResponse"\xd2\x01\x82\xd3\xe4\x93\x02\xcb\x01\x12_/namespaces/{namespace}/deployments/{deployment.series_name}/{deployment.build_id}/reachabilityZh\x12\x66/api/v1/namespaces/{namespace}/deployments/{deployment.series_name}/{deployment.build_id}/reachability\x12\x99\x02\n\x14GetCurrentDeployment\x12<.temporal.api.workflowservice.v1.GetCurrentDeploymentRequest\x1a=.temporal.api.workflowservice.v1.GetCurrentDeploymentResponse"\x83\x01\x82\xd3\xe4\x93\x02}\x12\x38/namespaces/{namespace}/current-deployment/{series_name}ZA\x12?/api/v1/namespaces/{namespace}/current-deployment/{series_name}\x12\xb6\x02\n\x14SetCurrentDeployment\x12<.temporal.api.workflowservice.v1.SetCurrentDeploymentRequest\x1a=.temporal.api.workflowservice.v1.SetCurrentDeploymentResponse"\xa0\x01\x82\xd3\xe4\x93\x02\x99\x01"C/namespaces/{namespace}/current-deployment/{deployment.series_name}:\x01*ZO"J/api/v1/namespaces/{namespace}/current-deployment/{deployment.series_name}:\x01*\x12\xb0\x03\n!SetWorkerDeploymentCurrentVersion\x12I.temporal.api.workflowservice.v1.SetWorkerDeploymentCurrentVersionRequest\x1aJ.temporal.api.workflowservice.v1.SetWorkerDeploymentCurrentVersionResponse"\xf3\x01\x82\xd3\xe4\x93\x02\xb3\x01"P/namespaces/{namespace}/worker-deployments/{deployment_name}/set-current-version:\x01*Z\\"W/api/v1/namespaces/{namespace}/worker-deployments/{deployment_name}/set-current-version:\x01*\x8a\x9d\xcc\x1b\x34\n\x14temporal-resource-id\x12\x1c\x64\x65ployment:{deployment_name}\x12\xe7\x02\n\x18\x44\x65scribeWorkerDeployment\x12@.temporal.api.workflowservice.v1.DescribeWorkerDeploymentRequest\x1a\x41.temporal.api.workflowservice.v1.DescribeWorkerDeploymentResponse"\xc5\x01\x82\xd3\xe4\x93\x02\x85\x01\x12.temporal.api.workflowservice.v1.DeleteWorkerDeploymentRequest\x1a?.temporal.api.workflowservice.v1.DeleteWorkerDeploymentResponse"\xc5\x01\x82\xd3\xe4\x93\x02\x85\x01*.temporal.api.workflowservice.v1.ListWorkerDeploymentsResponse"g\x82\xd3\xe4\x93\x02\x61\x12*/namespaces/{namespace}/worker-deploymentsZ3\x12\x31/api/v1/namespaces/{namespace}/worker-deployments\x12\xae\x02\n\x16\x43reateWorkerDeployment\x12>.temporal.api.workflowservice.v1.CreateWorkerDeploymentRequest\x1a?.temporal.api.workflowservice.v1.CreateWorkerDeploymentResponse"\x92\x01\x82\xd3\xe4\x93\x02\x8b\x01".temporal.api.workflowservice.v1.DescribeBatchOperationRequest\x1a?.temporal.api.workflowservice.v1.DescribeBatchOperationResponse"\xa0\x01\x82\xd3\xe4\x93\x02o\x12\x31/namespaces/{namespace}/batch-operations/{job_id}Z:\x12\x38/api/v1/namespaces/{namespace}/batch-operations/{job_id}\x8a\x9d\xcc\x1b&\n\x14temporal-resource-id\x12\x0e\x62\x61tch:{job_id}\x12\xf5\x01\n\x13ListBatchOperations\x12;.temporal.api.workflowservice.v1.ListBatchOperationsRequest\x1a<.temporal.api.workflowservice.v1.ListBatchOperationsResponse"c\x82\xd3\xe4\x93\x02]\x12(/namespaces/{namespace}/batch-operationsZ1\x12//api/v1/namespaces/{namespace}/batch-operations\x12\xc4\x01\n\x12PollNexusTaskQueue\x12:.temporal.api.workflowservice.v1.PollNexusTaskQueueRequest\x1a;.temporal.api.workflowservice.v1.PollNexusTaskQueueResponse"5\x8a\x9d\xcc\x1b\x30\n\x14temporal-resource-id\x12\x18poller:{poller_group_id}\x12\xd9\x01\n\x19RespondNexusTaskCompleted\x12\x41.temporal.api.workflowservice.v1.RespondNexusTaskCompletedRequest\x1a\x42.temporal.api.workflowservice.v1.RespondNexusTaskCompletedResponse"5\x8a\x9d\xcc\x1b\x30\n\x14temporal-resource-id\x12\x18poller:{poller_group_id}\x12\xd0\x01\n\x16RespondNexusTaskFailed\x12>.temporal.api.workflowservice.v1.RespondNexusTaskFailedRequest\x1a?.temporal.api.workflowservice.v1.RespondNexusTaskFailedResponse"5\x8a\x9d\xcc\x1b\x30\n\x14temporal-resource-id\x12\x18poller:{poller_group_id}\x12\xe8\x02\n\x15UpdateActivityOptions\x12=.temporal.api.workflowservice.v1.UpdateActivityOptionsRequest\x1a>.temporal.api.workflowservice.v1.UpdateActivityOptionsResponse"\xcf\x01\x82\xd3\xe4\x93\x02\x8b\x01".temporal.api.workflowservice.v1.RecordWorkerHeartbeatResponse"\x95\x01\x82\xd3\xe4\x93\x02\x65")/namespaces/{namespace}/workers/heartbeat:\x01*Z5"0/api/v1/namespaces/{namespace}/workers/heartbeat:\x01*\x8a\x9d\xcc\x1b%\n\x14temporal-resource-id\x12\r{resource_id}\x12\xcb\x01\n\x0bListWorkers\x12\x33.temporal.api.workflowservice.v1.ListWorkersRequest\x1a\x34.temporal.api.workflowservice.v1.ListWorkersResponse"Q\x82\xd3\xe4\x93\x02K\x12\x1f/namespaces/{namespace}/workersZ(\x12&/api/v1/namespaces/{namespace}/workers\x12\xe2\x02\n\x15UpdateTaskQueueConfig\x12=.temporal.api.workflowservice.v1.UpdateTaskQueueConfigRequest\x1a>.temporal.api.workflowservice.v1.UpdateTaskQueueConfigResponse"\xc9\x01\x82\xd3\xe4\x93\x02\x8f\x01">/namespaces/{namespace}/task-queues/{task_queue}/update-config:\x01*ZJ"E/api/v1/namespaces/{namespace}/task-queues/{task_queue}/update-config:\x01*\x8a\x9d\xcc\x1b.\n\x14temporal-resource-id\x12\x16taskqueue:{task_queue}\x12\xa8\x02\n\x11\x46\x65tchWorkerConfig\x12\x39.temporal.api.workflowservice.v1.FetchWorkerConfigRequest\x1a:.temporal.api.workflowservice.v1.FetchWorkerConfigResponse"\x9b\x01\x82\xd3\xe4\x93\x02k",/namespaces/{namespace}/workers/fetch-config:\x01*Z8"3/api/v1/namespaces/{namespace}/workers/fetch-config:\x01*\x8a\x9d\xcc\x1b%\n\x14temporal-resource-id\x12\r{resource_id}\x12\xad\x02\n\x12UpdateWorkerConfig\x12:.temporal.api.workflowservice.v1.UpdateWorkerConfigRequest\x1a;.temporal.api.workflowservice.v1.UpdateWorkerConfigResponse"\x9d\x01\x82\xd3\xe4\x93\x02m"-/namespaces/{namespace}/workers/update-config:\x01*Z9"4/api/v1/namespaces/{namespace}/workers/update-config:\x01*\x8a\x9d\xcc\x1b%\n\x14temporal-resource-id\x12\r{resource_id}\x12\xcd\x02\n\x0e\x44\x65scribeWorker\x12\x36.temporal.api.workflowservice.v1.DescribeWorkerRequest\x1a\x37.temporal.api.workflowservice.v1.DescribeWorkerResponse"\xc9\x01\x82\xd3\xe4\x93\x02\x89\x01\x12>/namespaces/{namespace}/workers/describe/{worker_instance_key}ZG\x12\x45/api/v1/namespaces/{namespace}/workers/describe/{worker_instance_key}\x8a\x9d\xcc\x1b\x34\n\x14temporal-resource-id\x12\x1cworker:{worker_instance_key}\x12\xd2\x02\n\x16PauseWorkflowExecution\x12>.temporal.api.workflowservice.v1.PauseWorkflowExecutionRequest\x1a?.temporal.api.workflowservice.v1.PauseWorkflowExecutionResponse"\xb6\x01\x82\xd3\xe4\x93\x02}"5/namespaces/{namespace}/workflows/{workflow_id}/pause:\x01*ZA"/api/v1/namespaces/{namespace}/workflows/{workflow_id}/unpause:\x01*\x8a\x9d\xcc\x1b.\n\x14temporal-resource-id\x12\x16workflow:{workflow_id}\x12\xc8\x02\n\x16StartActivityExecution\x12>.temporal.api.workflowservice.v1.StartActivityExecutionRequest\x1a?.temporal.api.workflowservice.v1.StartActivityExecutionResponse"\xac\x01\x82\xd3\xe4\x93\x02s"0/namespaces/{namespace}/activities/{activity_id}:\x01*Z<"7/api/v1/namespaces/{namespace}/activities/{activity_id}:\x01*\x8a\x9d\xcc\x1b.\n\x14temporal-resource-id\x12\x16\x61\x63tivity:{activity_id}\x12\xb6\x02\n\x1cStartNexusOperationExecution\x12\x44.temporal.api.workflowservice.v1.StartNexusOperationExecutionRequest\x1a\x45.temporal.api.workflowservice.v1.StartNexusOperationExecutionResponse"\x88\x01\x82\xd3\xe4\x93\x02\x81\x01"7/namespaces/{namespace}/nexus-operations/{operation_id}:\x01*ZC">/api/v1/namespaces/{namespace}/nexus-operations/{operation_id}:\x01*\x12\xcb\x02\n\x19\x44\x65scribeActivityExecution\x12\x41.temporal.api.workflowservice.v1.DescribeActivityExecutionRequest\x1a\x42.temporal.api.workflowservice.v1.DescribeActivityExecutionResponse"\xa6\x01\x82\xd3\xe4\x93\x02m\x12\x30/namespaces/{namespace}/activities/{activity_id}Z9\x12\x37/api/v1/namespaces/{namespace}/activities/{activity_id}\x8a\x9d\xcc\x1b.\n\x14temporal-resource-id\x12\x16\x61\x63tivity:{activity_id}\x12\xb8\x02\n\x1f\x44\x65scribeNexusOperationExecution\x12G.temporal.api.workflowservice.v1.DescribeNexusOperationExecutionRequest\x1aH.temporal.api.workflowservice.v1.DescribeNexusOperationExecutionResponse"\x81\x01\x82\xd3\xe4\x93\x02{\x12\x37/namespaces/{namespace}/nexus-operations/{operation_id}Z@\x12>/api/v1/namespaces/{namespace}/nexus-operations/{operation_id}\x12\xcf\x02\n\x15PollActivityExecution\x12=.temporal.api.workflowservice.v1.PollActivityExecutionRequest\x1a>.temporal.api.workflowservice.v1.PollActivityExecutionResponse"\xb6\x01\x82\xd3\xe4\x93\x02}\x12\x38/namespaces/{namespace}/activities/{activity_id}/outcomeZA\x12?/api/v1/namespaces/{namespace}/activities/{activity_id}/outcome\x8a\x9d\xcc\x1b.\n\x14temporal-resource-id\x12\x16\x61\x63tivity:{activity_id}\x12\xb7\x02\n\x1bPollNexusOperationExecution\x12\x43.temporal.api.workflowservice.v1.PollNexusOperationExecutionRequest\x1a\x44.temporal.api.workflowservice.v1.PollNexusOperationExecutionResponse"\x8c\x01\x82\xd3\xe4\x93\x02\x85\x01\x12.temporal.api.workflowservice.v1.ListActivityExecutionsRequest\x1a?.temporal.api.workflowservice.v1.ListActivityExecutionsResponse"W\x82\xd3\xe4\x93\x02Q\x12"/namespaces/{namespace}/activitiesZ+\x12)/api/v1/namespaces/{namespace}/activities\x12\x90\x02\n\x1cListNexusOperationExecutions\x12\x44.temporal.api.workflowservice.v1.ListNexusOperationExecutionsRequest\x1a\x45.temporal.api.workflowservice.v1.ListNexusOperationExecutionsResponse"c\x82\xd3\xe4\x93\x02]\x12(/namespaces/{namespace}/nexus-operationsZ1\x12//api/v1/namespaces/{namespace}/nexus-operations\x12\xfd\x01\n\x17\x43ountActivityExecutions\x12?.temporal.api.workflowservice.v1.CountActivityExecutionsRequest\x1a@.temporal.api.workflowservice.v1.CountActivityExecutionsResponse"_\x82\xd3\xe4\x93\x02Y\x12&/namespaces/{namespace}/activity-countZ/\x12-/api/v1/namespaces/{namespace}/activity-count\x12\x9d\x02\n\x1d\x43ountNexusOperationExecutions\x12\x45.temporal.api.workflowservice.v1.CountNexusOperationExecutionsRequest\x1a\x46.temporal.api.workflowservice.v1.CountNexusOperationExecutionsResponse"m\x82\xd3\xe4\x93\x02g\x12-/namespaces/{namespace}/nexus-operation-countZ6\x12\x34/api/v1/namespaces/{namespace}/nexus-operation-count\x12\xef\x02\n\x1eRequestCancelActivityExecution\x12\x46.temporal.api.workflowservice.v1.RequestCancelActivityExecutionRequest\x1aG.temporal.api.workflowservice.v1.RequestCancelActivityExecutionResponse"\xbb\x01\x82\xd3\xe4\x93\x02\x81\x01"7/namespaces/{namespace}/activities/{activity_id}/cancel:\x01*ZC">/api/v1/namespaces/{namespace}/activities/{activity_id}/cancel:\x01*\x8a\x9d\xcc\x1b.\n\x14temporal-resource-id\x12\x16\x61\x63tivity:{activity_id}\x12\xdc\x02\n$RequestCancelNexusOperationExecution\x12L.temporal.api.workflowservice.v1.RequestCancelNexusOperationExecutionRequest\x1aM.temporal.api.workflowservice.v1.RequestCancelNexusOperationExecutionResponse"\x96\x01\x82\xd3\xe4\x93\x02\x8f\x01">/namespaces/{namespace}/nexus-operations/{operation_id}/cancel:\x01*ZJ"E/api/v1/namespaces/{namespace}/nexus-operations/{operation_id}/cancel:\x01*\x12\xe9\x02\n\x1aTerminateActivityExecution\x12\x42.temporal.api.workflowservice.v1.TerminateActivityExecutionRequest\x1a\x43.temporal.api.workflowservice.v1.TerminateActivityExecutionResponse"\xc1\x01\x82\xd3\xe4\x93\x02\x87\x01":/namespaces/{namespace}/activities/{activity_id}/terminate:\x01*ZF"A/api/v1/namespaces/{namespace}/activities/{activity_id}/terminate:\x01*\x8a\x9d\xcc\x1b.\n\x14temporal-resource-id\x12\x16\x61\x63tivity:{activity_id}\x12\x9e\x01\n\x17\x44\x65leteActivityExecution\x12?.temporal.api.workflowservice.v1.DeleteActivityExecutionRequest\x1a@.temporal.api.workflowservice.v1.DeleteActivityExecutionResponse"\x00\x12\xfd\x03\n\x16PauseActivityExecution\x12>.temporal.api.workflowservice.v1.PauseActivityExecutionRequest\x1a?.temporal.api.workflowservice.v1.PauseActivityExecutionResponse"\xe1\x02\x82\xd3\xe4\x93\x02\xb0\x02"6/namespaces/{namespace}/activities/{activity_id}/pause:\x01*ZB"=/api/v1/namespaces/{namespace}/activities/{activity_id}/pause:\x01*ZS"N/namespaces/{namespace}/workflows/{workflow_id}/activities/{activity_id}/pause:\x01*ZZ"U/api/v1/namespaces/{namespace}/workflows/{workflow_id}/activities/{activity_id}/pause:\x01*\x8a\x9d\xcc\x1b%\n\x14temporal-resource-id\x12\r{resource_id}\x12\xfd\x03\n\x16ResetActivityExecution\x12>.temporal.api.workflowservice.v1.ResetActivityExecutionRequest\x1a?.temporal.api.workflowservice.v1.ResetActivityExecutionResponse"\xe1\x02\x82\xd3\xe4\x93\x02\xb0\x02"6/namespaces/{namespace}/activities/{activity_id}/reset:\x01*ZB"=/api/v1/namespaces/{namespace}/activities/{activity_id}/reset:\x01*ZS"N/namespaces/{namespace}/workflows/{workflow_id}/activities/{activity_id}/reset:\x01*ZZ"U/api/v1/namespaces/{namespace}/workflows/{workflow_id}/activities/{activity_id}/reset:\x01*\x8a\x9d\xcc\x1b%\n\x14temporal-resource-id\x12\r{resource_id}\x12\x8b\x04\n\x18UnpauseActivityExecution\x12@.temporal.api.workflowservice.v1.UnpauseActivityExecutionRequest\x1a\x41.temporal.api.workflowservice.v1.UnpauseActivityExecutionResponse"\xe9\x02\x82\xd3\xe4\x93\x02\xb8\x02"8/namespaces/{namespace}/activities/{activity_id}/unpause:\x01*ZD"?/api/v1/namespaces/{namespace}/activities/{activity_id}/unpause:\x01*ZU"P/namespaces/{namespace}/workflows/{workflow_id}/activities/{activity_id}/unpause:\x01*Z\\"W/api/v1/namespaces/{namespace}/workflows/{workflow_id}/activities/{activity_id}/unpause:\x01*\x8a\x9d\xcc\x1b%\n\x14temporal-resource-id\x12\r{resource_id}\x12\xb9\x04\n\x1eUpdateActivityExecutionOptions\x12\x46.temporal.api.workflowservice.v1.UpdateActivityExecutionOptionsRequest\x1aG.temporal.api.workflowservice.v1.UpdateActivityExecutionOptionsResponse"\x85\x03\x82\xd3\xe4\x93\x02\xd4\x02"?/namespaces/{namespace}/activities/{activity_id}/update-options:\x01*ZK"F/api/v1/namespaces/{namespace}/activities/{activity_id}/update-options:\x01*Z\\"W/namespaces/{namespace}/workflows/{workflow_id}/activities/{activity_id}/update-options:\x01*Zc"^/api/v1/namespaces/{namespace}/workflows/{workflow_id}/activities/{activity_id}/update-options:\x01*\x8a\x9d\xcc\x1b%\n\x14temporal-resource-id\x12\r{resource_id}\x12\xd6\x02\n TerminateNexusOperationExecution\x12H.temporal.api.workflowservice.v1.TerminateNexusOperationExecutionRequest\x1aI.temporal.api.workflowservice.v1.TerminateNexusOperationExecutionResponse"\x9c\x01\x82\xd3\xe4\x93\x02\x95\x01"A/namespaces/{namespace}/nexus-operations/{operation_id}/terminate:\x01*ZM"H/api/v1/namespaces/{namespace}/nexus-operations/{operation_id}/terminate:\x01*\x12\xb0\x01\n\x1d\x44\x65leteNexusOperationExecution\x12\x45.temporal.api.workflowservice.v1.DeleteNexusOperationExecutionRequest\x1a\x46.temporal.api.workflowservice.v1.DeleteNexusOperationExecutionResponse"\x00\x42\xb6\x01\n"io.temporal.api.workflowservice.v1B\x0cServiceProtoP\x01Z5go.temporal.io/api/workflowservice/v1;workflowservice\xaa\x02!Temporalio.Api.WorkflowService.V1\xea\x02$Temporalio::Api::WorkflowService::V1b\x06proto3' ) @@ -135,7 +138,7 @@ _WORKFLOWSERVICE.methods_by_name["SignalWithStartWorkflowExecution"]._options = None _WORKFLOWSERVICE.methods_by_name[ "SignalWithStartWorkflowExecution" - ]._serialized_options = b'\202\323\344\223\002\261\001"O/namespaces/{namespace}/workflows/{workflow_id}/signal-with-start/{signal_name}:\001*Z["V/api/v1/namespaces/{namespace}/workflows/{workflow_id}/signal-with-start/{signal_name}:\001*\212\235\314\033.\n\024temporal-resource-id\022\026workflow:{workflow_id}' + ]._serialized_options = b'\322\202\004\t\022\007exposed\202\323\344\223\002\261\001"O/namespaces/{namespace}/workflows/{workflow_id}/signal-with-start/{signal_name}:\001*Z["V/api/v1/namespaces/{namespace}/workflows/{workflow_id}/signal-with-start/{signal_name}:\001*\212\235\314\033.\n\024temporal-resource-id\022\026workflow:{workflow_id}' _WORKFLOWSERVICE.methods_by_name["ResetWorkflowExecution"]._options = None _WORKFLOWSERVICE.methods_by_name[ "ResetWorkflowExecution" @@ -512,6 +515,6 @@ _WORKFLOWSERVICE.methods_by_name[ "TerminateNexusOperationExecution" ]._serialized_options = b'\202\323\344\223\002\225\001"A/namespaces/{namespace}/nexus-operations/{operation_id}/terminate:\001*ZM"H/api/v1/namespaces/{namespace}/nexus-operations/{operation_id}/terminate:\001*' - _WORKFLOWSERVICE._serialized_start = 215 - _WORKFLOWSERVICE._serialized_end = 38791 + _WORKFLOWSERVICE._serialized_start = 250 + _WORKFLOWSERVICE._serialized_end = 38839 # @@protoc_insertion_point(module_scope) diff --git a/temporalio/api/workflowservice/v1/service_pb2_grpc.py b/temporalio/api/workflowservice/v1/service_pb2_grpc.py index feaaf4dde..f0fcc6730 100644 --- a/temporalio/api/workflowservice/v1/service_pb2_grpc.py +++ b/temporalio/api/workflowservice/v1/service_pb2_grpc.py @@ -1183,6 +1183,7 @@ def CountSchedules(self, request, context): def UpdateWorkerBuildIdCompatibility(self, request, context): """Deprecated. Use `UpdateWorkerVersioningRules`. + Will be removed in server version v1.32.0. Allows users to specify sets of worker build id versions on a per task queue basis. Versions are ordered, and may be either compatible with some extant version, or a new incompatible @@ -1206,6 +1207,7 @@ def UpdateWorkerBuildIdCompatibility(self, request, context): def GetWorkerBuildIdCompatibility(self, request, context): """Deprecated. Use `GetWorkerVersioningRules`. + Will be removed in server version v1.32.0. Fetches the worker build id versioning sets for a task queue. """ context.set_code(grpc.StatusCode.UNIMPLEMENTED) @@ -1234,7 +1236,7 @@ def UpdateWorkerVersioningRules(self, request, context): the target Build ID of a redirect rule is able to process event histories made by the source Build ID by using [Patching](https://docs.temporal.io/workflows#patching) or other means. - WARNING: Worker Versioning is not yet stable and the API and behavior may change incompatibly. + Will be removed in server version v1.32.0. (-- api-linter: core::0127::http-annotation=disabled aip.dev/not-precedent: We do yet expose versioning API to HTTP. --) """ @@ -1244,7 +1246,7 @@ def UpdateWorkerVersioningRules(self, request, context): def GetWorkerVersioningRules(self, request, context): """Fetches the Build ID assignment and redirect rules for a Task Queue. - WARNING: Worker Versioning is not yet stable and the API and behavior may change incompatibly. + Will be removed in server version v1.32.0. """ context.set_code(grpc.StatusCode.UNIMPLEMENTED) context.set_details("Method not implemented!") @@ -1252,6 +1254,7 @@ def GetWorkerVersioningRules(self, request, context): def GetWorkerTaskReachability(self, request, context): """Deprecated. Use `DescribeTaskQueue`. + Will be removed in server version v1.32.0. Fetches task reachability to determine whether a worker may be retired. The request may specify task queues to query for or let the server fetch all task queues mapped to the given diff --git a/temporalio/api/workflowservice/v1/service_pb2_grpc.pyi b/temporalio/api/workflowservice/v1/service_pb2_grpc.pyi index 4d5753d14..d6d94abb3 100644 --- a/temporalio/api/workflowservice/v1/service_pb2_grpc.pyi +++ b/temporalio/api/workflowservice/v1/service_pb2_grpc.pyi @@ -510,6 +510,7 @@ class WorkflowServiceStub: temporalio.api.workflowservice.v1.request_response_pb2.UpdateWorkerBuildIdCompatibilityResponse, ] """Deprecated. Use `UpdateWorkerVersioningRules`. + Will be removed in server version v1.32.0. Allows users to specify sets of worker build id versions on a per task queue basis. Versions are ordered, and may be either compatible with some extant version, or a new incompatible @@ -532,6 +533,7 @@ class WorkflowServiceStub: temporalio.api.workflowservice.v1.request_response_pb2.GetWorkerBuildIdCompatibilityResponse, ] """Deprecated. Use `GetWorkerVersioningRules`. + Will be removed in server version v1.32.0. Fetches the worker build id versioning sets for a task queue. """ UpdateWorkerVersioningRules: grpc.UnaryUnaryMultiCallable[ @@ -559,7 +561,7 @@ class WorkflowServiceStub: the target Build ID of a redirect rule is able to process event histories made by the source Build ID by using [Patching](https://docs.temporal.io/workflows#patching) or other means. - WARNING: Worker Versioning is not yet stable and the API and behavior may change incompatibly. + Will be removed in server version v1.32.0. (-- api-linter: core::0127::http-annotation=disabled aip.dev/not-precedent: We do yet expose versioning API to HTTP. --) """ @@ -568,13 +570,14 @@ class WorkflowServiceStub: temporalio.api.workflowservice.v1.request_response_pb2.GetWorkerVersioningRulesResponse, ] """Fetches the Build ID assignment and redirect rules for a Task Queue. - WARNING: Worker Versioning is not yet stable and the API and behavior may change incompatibly. + Will be removed in server version v1.32.0. """ GetWorkerTaskReachability: grpc.UnaryUnaryMultiCallable[ temporalio.api.workflowservice.v1.request_response_pb2.GetWorkerTaskReachabilityRequest, temporalio.api.workflowservice.v1.request_response_pb2.GetWorkerTaskReachabilityResponse, ] """Deprecated. Use `DescribeTaskQueue`. + Will be removed in server version v1.32.0. Fetches task reachability to determine whether a worker may be retired. The request may specify task queues to query for or let the server fetch all task queues mapped to the given @@ -1779,6 +1782,7 @@ class WorkflowServiceServicer(metaclass=abc.ABCMeta): context: grpc.ServicerContext, ) -> temporalio.api.workflowservice.v1.request_response_pb2.UpdateWorkerBuildIdCompatibilityResponse: """Deprecated. Use `UpdateWorkerVersioningRules`. + Will be removed in server version v1.32.0. Allows users to specify sets of worker build id versions on a per task queue basis. Versions are ordered, and may be either compatible with some extant version, or a new incompatible @@ -1803,6 +1807,7 @@ class WorkflowServiceServicer(metaclass=abc.ABCMeta): context: grpc.ServicerContext, ) -> temporalio.api.workflowservice.v1.request_response_pb2.GetWorkerBuildIdCompatibilityResponse: """Deprecated. Use `GetWorkerVersioningRules`. + Will be removed in server version v1.32.0. Fetches the worker build id versioning sets for a task queue. """ @abc.abstractmethod @@ -1832,7 +1837,7 @@ class WorkflowServiceServicer(metaclass=abc.ABCMeta): the target Build ID of a redirect rule is able to process event histories made by the source Build ID by using [Patching](https://docs.temporal.io/workflows#patching) or other means. - WARNING: Worker Versioning is not yet stable and the API and behavior may change incompatibly. + Will be removed in server version v1.32.0. (-- api-linter: core::0127::http-annotation=disabled aip.dev/not-precedent: We do yet expose versioning API to HTTP. --) """ @@ -1843,7 +1848,7 @@ class WorkflowServiceServicer(metaclass=abc.ABCMeta): context: grpc.ServicerContext, ) -> temporalio.api.workflowservice.v1.request_response_pb2.GetWorkerVersioningRulesResponse: """Fetches the Build ID assignment and redirect rules for a Task Queue. - WARNING: Worker Versioning is not yet stable and the API and behavior may change incompatibly. + Will be removed in server version v1.32.0. """ @abc.abstractmethod def GetWorkerTaskReachability( @@ -1852,6 +1857,7 @@ class WorkflowServiceServicer(metaclass=abc.ABCMeta): context: grpc.ServicerContext, ) -> temporalio.api.workflowservice.v1.request_response_pb2.GetWorkerTaskReachabilityResponse: """Deprecated. Use `DescribeTaskQueue`. + Will be removed in server version v1.32.0. Fetches task reachability to determine whether a worker may be retired. The request may specify task queues to query for or let the server fetch all task queues mapped to the given diff --git a/temporalio/bridge/Cargo.lock b/temporalio/bridge/Cargo.lock index 7f22a2a9c..ec71c46c9 100644 --- a/temporalio/bridge/Cargo.lock +++ b/temporalio/bridge/Cargo.lock @@ -2911,6 +2911,7 @@ dependencies = [ "axum", "base64", "bytes", + "flate2", "h2", "http", "http-body", diff --git a/temporalio/bridge/sdk-core b/temporalio/bridge/sdk-core index 6a8355ac4..c5a6646e9 160000 --- a/temporalio/bridge/sdk-core +++ b/temporalio/bridge/sdk-core @@ -1 +1 @@ -Subproject commit 6a8355ac4c49884433b0502f31bddace0c6ce884 +Subproject commit c5a6646e96fd7f202dd91805c7d53f2cdd03c544 diff --git a/temporalio/bridge/services_generated.py b/temporalio/bridge/services_generated.py index ff988d1a4..301c218cf 100644 --- a/temporalio/bridge/services_generated.py +++ b/temporalio/bridge/services_generated.py @@ -3305,6 +3305,24 @@ async def get_service_account( timeout=timeout, ) + async def get_service_account_namespace_assignments( + self, + req: temporalio.api.cloud.cloudservice.v1.GetServiceAccountNamespaceAssignmentsRequest, + retry: bool = False, + metadata: Mapping[str, str | bytes] = {}, + timeout: timedelta | None = None, + ) -> temporalio.api.cloud.cloudservice.v1.GetServiceAccountNamespaceAssignmentsResponse: + """Invokes the CloudService.get_service_account_namespace_assignments rpc method.""" + return await self._client._rpc_call( + rpc="get_service_account_namespace_assignments", + req=req, + service=self._service, + resp_type=temporalio.api.cloud.cloudservice.v1.GetServiceAccountNamespaceAssignmentsResponse, + retry=retry, + metadata=metadata, + timeout=timeout, + ) + async def get_service_accounts( self, req: temporalio.api.cloud.cloudservice.v1.GetServiceAccountsRequest, @@ -3395,6 +3413,24 @@ async def get_user_group_members( timeout=timeout, ) + async def get_user_group_namespace_assignments( + self, + req: temporalio.api.cloud.cloudservice.v1.GetUserGroupNamespaceAssignmentsRequest, + retry: bool = False, + metadata: Mapping[str, str | bytes] = {}, + timeout: timedelta | None = None, + ) -> temporalio.api.cloud.cloudservice.v1.GetUserGroupNamespaceAssignmentsResponse: + """Invokes the CloudService.get_user_group_namespace_assignments rpc method.""" + return await self._client._rpc_call( + rpc="get_user_group_namespace_assignments", + req=req, + service=self._service, + resp_type=temporalio.api.cloud.cloudservice.v1.GetUserGroupNamespaceAssignmentsResponse, + retry=retry, + metadata=metadata, + timeout=timeout, + ) + async def get_user_groups( self, req: temporalio.api.cloud.cloudservice.v1.GetUserGroupsRequest, @@ -3413,6 +3449,24 @@ async def get_user_groups( timeout=timeout, ) + async def get_user_namespace_assignments( + self, + req: temporalio.api.cloud.cloudservice.v1.GetUserNamespaceAssignmentsRequest, + retry: bool = False, + metadata: Mapping[str, str | bytes] = {}, + timeout: timedelta | None = None, + ) -> temporalio.api.cloud.cloudservice.v1.GetUserNamespaceAssignmentsResponse: + """Invokes the CloudService.get_user_namespace_assignments rpc method.""" + return await self._client._rpc_call( + rpc="get_user_namespace_assignments", + req=req, + service=self._service, + resp_type=temporalio.api.cloud.cloudservice.v1.GetUserNamespaceAssignmentsResponse, + retry=retry, + metadata=metadata, + timeout=timeout, + ) + async def get_users( self, req: temporalio.api.cloud.cloudservice.v1.GetUsersRequest, diff --git a/temporalio/bridge/src/client_rpc_generated.rs b/temporalio/bridge/src/client_rpc_generated.rs index c44fbcb1b..931b77a32 100644 --- a/temporalio/bridge/src/client_rpc_generated.rs +++ b/temporalio/bridge/src/client_rpc_generated.rs @@ -1639,6 +1639,15 @@ impl ClientRef { get_service_account ) } + "get_service_account_namespace_assignments" => { + rpc_call!( + connection, + call, + CloudService, + cloud_service, + get_service_account_namespace_assignments + ) + } "get_service_accounts" => { rpc_call!( connection, @@ -1672,6 +1681,15 @@ impl ClientRef { get_user_group_members ) } + "get_user_group_namespace_assignments" => { + rpc_call!( + connection, + call, + CloudService, + cloud_service, + get_user_group_namespace_assignments + ) + } "get_user_groups" => { rpc_call!( connection, @@ -1681,6 +1699,15 @@ impl ClientRef { get_user_groups ) } + "get_user_namespace_assignments" => { + rpc_call!( + connection, + call, + CloudService, + cloud_service, + get_user_namespace_assignments + ) + } "get_users" => { rpc_call!(connection, call, CloudService, cloud_service, get_users) } diff --git a/temporalio/nexus/_link_conversion.py b/temporalio/nexus/_link_conversion.py index d02b543d9..acb5a0e1d 100644 --- a/temporalio/nexus/_link_conversion.py +++ b/temporalio/nexus/_link_conversion.py @@ -99,8 +99,10 @@ def temporal_link_to_nexus_link( case "nexus_operation": return nexus_operation_to_nexus_link(temporal_link.nexus_operation) - case "activity" | "batch_job": - raise NotImplementedError("only workflow links are supported") + case "activity" | "batch_job" | "workflow": + raise NotImplementedError( + "only workflow_event and nexus operation links are supported" + ) case None: logger.warning("Invalid Temporal link: missing variant") From 24badcfd8095312a67269c4b31fee09897ac4d79 Mon Sep 17 00:00:00 2001 From: xumaple <45406854+xumaple@users.noreply.github.com> Date: Wed, 10 Jun 2026 13:16:43 -0400 Subject: [PATCH 126/226] AI-249: Support CustomTool in OpenAI Agents plugin tool dispatch (#1570) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * TDD: failing test * AI-249: Support CustomTool in OpenAI Agents plugin tool dispatch Fixes #1561. Adds a CustomToolInput dataclass and CustomTool dispatch branch (mirroring the existing HostedMCPTool precedent), so Workflows exposing any CustomTool subclass — notably SandboxApplyPatchTool, which the default Filesystem capability registers on every SandboxAgent — no longer fail with `ValueError: Unsupported tool type: apply_patch` at Activity input construction. Also round-trips `defer_loading` through `tool_config`, so direct `CustomTool(defer_loading=True)` callers continue to work with `ToolSearchTool()` lazy tool discovery. Co-Authored-By: Claude Opus 4.7 (1M context) * AI-249: Type-annotate defer_loading test stub basedpyright in CI flagged the inline async stub callable for missing type annotations and unused-parameter warnings. Adds Any/str annotations and underscore-prefixes the params. Co-Authored-By: Claude Opus 4.7 (1M context) * PR comments --------- Co-authored-by: Claude Opus 4.7 (1M context) --- .../openai_agents/_invoke_model_activity.py | 20 +++ .../openai_agents/_temporal_model_stub.py | 11 +- tests/contrib/openai_agents/test_openai.py | 138 ++++++++++++++++++ 3 files changed, 168 insertions(+), 1 deletion(-) diff --git a/temporalio/contrib/openai_agents/_invoke_model_activity.py b/temporalio/contrib/openai_agents/_invoke_model_activity.py index 3f7a639dd..5435b6369 100644 --- a/temporalio/contrib/openai_agents/_invoke_model_activity.py +++ b/temporalio/contrib/openai_agents/_invoke_model_activity.py @@ -30,6 +30,7 @@ from agents.items import TResponseStreamEvent from agents.tool import ( ApplyPatchTool, + CustomTool, LocalShellTool, ShellTool, ShellToolEnvironment, @@ -39,6 +40,7 @@ APIStatusError, AsyncOpenAI, ) +from openai.types.responses import CustomToolParam from openai.types.responses.tool_param import Mcp from typing_extensions import Required, TypedDict @@ -112,6 +114,15 @@ class ApplyPatchToolInput: name: str = "apply_patch" +@dataclass +class CustomToolInput: + """Data conversion friendly representation of a CustomTool. Contains only the fields which are needed by the model + execution to determine what tool to call, not the actual tool invocation, which remains in the workflow context. + """ + + tool_config: CustomToolParam + + ToolInput = ( FunctionToolInput | FileSearchTool @@ -122,6 +133,7 @@ class ApplyPatchToolInput: | ShellToolInput | LocalShellTool | ApplyPatchToolInput + | CustomToolInput | ToolSearchTool ) @@ -235,6 +247,14 @@ def _build_tool(tool: ToolInput) -> Tool: return ApplyPatchTool(name=tool.name, editor=_NoopApplyPatchEditor()) elif isinstance(tool, HostedMCPToolInput): return HostedMCPTool(tool_config=tool.tool_config) + elif isinstance(tool, CustomToolInput): + return CustomTool( + name=tool.tool_config["name"], + description=tool.tool_config.get("description", ""), + on_invoke_tool=_empty_on_invoke_tool, + format=tool.tool_config.get("format"), + defer_loading=tool.tool_config.get("defer_loading", False), + ) elif isinstance(tool, FunctionToolInput): return FunctionTool( name=tool.name, diff --git a/temporalio/contrib/openai_agents/_temporal_model_stub.py b/temporalio/contrib/openai_agents/_temporal_model_stub.py index 7f9ab11d9..d184daa4a 100644 --- a/temporalio/contrib/openai_agents/_temporal_model_stub.py +++ b/temporalio/contrib/openai_agents/_temporal_model_stub.py @@ -22,7 +22,13 @@ WebSearchTool, ) from agents.items import TResponseStreamEvent -from agents.tool import ApplyPatchTool, LocalShellTool, ShellTool, ToolSearchTool +from agents.tool import ( + ApplyPatchTool, + CustomTool, + LocalShellTool, + ShellTool, + ToolSearchTool, +) from openai.types.responses.response_prompt_param import ResponsePromptParam from temporalio import workflow @@ -30,6 +36,7 @@ ActivityModelInput, AgentOutputSchemaInput, ApplyPatchToolInput, + CustomToolInput, FunctionToolInput, HandoffInput, HostedMCPToolInput, @@ -92,6 +99,8 @@ def make_tool_info(tool: Tool) -> ToolInput: return ApplyPatchToolInput(name=tool.name) elif isinstance(tool, HostedMCPTool): return HostedMCPToolInput(tool_config=tool.tool_config) + elif isinstance(tool, CustomTool): + return CustomToolInput(tool_config=tool.tool_config) elif isinstance(tool, FunctionTool): return FunctionToolInput( name=tool.name, diff --git a/tests/contrib/openai_agents/test_openai.py b/tests/contrib/openai_agents/test_openai.py index de0af3923..96cc25133 100644 --- a/tests/contrib/openai_agents/test_openai.py +++ b/tests/contrib/openai_agents/test_openai.py @@ -58,9 +58,13 @@ TResponseStreamEvent, ) from agents.mcp import MCPServer, MCPServerStdio +from agents.sandbox.capabilities.tools import SandboxApplyPatchTool +from agents.tool import CustomTool +from agents.tool_context import ToolContext from openai import APIStatusError, AsyncOpenAI, BaseModel from openai.types.responses import ( ResponseCodeInterpreterToolCall, + ResponseCustomToolCall, ResponseFileSearchToolCall, ResponseFunctionWebSearch, ) @@ -83,6 +87,7 @@ StatefulMCPServerProvider, StatelessMCPServerProvider, ) +from temporalio.contrib.openai_agents._invoke_model_activity import _build_tool from temporalio.contrib.openai_agents._model_parameters import ModelSummaryProvider from temporalio.contrib.openai_agents._openai_runner import _convert_agent from temporalio.contrib.openai_agents._temporal_model_stub import ( @@ -1996,6 +2001,66 @@ async def test_hosted_mcp_tool(client: Client): assert result == "Some language" +def custom_tool_mock_model(): + return TestModel.returning_responses( + [ + ModelResponse( + output=[ + ResponseCustomToolCall( + call_id="c1", + input="ping", + name="echo", + type="custom_tool_call", + ) + ], + usage=Usage(), + response_id=None, + ), + ResponseBuilders.output_message("done"), + ] + ) + + +@workflow.defn +class CustomToolWorkflow: + @workflow.run + async def run(self) -> str: + captured: list[str] = [] + + async def echo(ctx: ToolContext[Any], input: str) -> str: # type: ignore[reportUnusedParameter] + captured.append(input) + return input + + agent = Agent[str]( + name="custom-tool-agent", + instructions="Use the echo tool.", + tools=[ + CustomTool( + name="echo", + description="Echo the input string back.", + on_invoke_tool=echo, + ) + ], + ) + result = await Runner.run(starting_agent=agent, input="say something") + return f"{result.final_output}:{captured[0]}" + + +async def test_custom_tool_workflow(client: Client): + async with AgentEnvironment(model=custom_tool_mock_model()) as env: + client = env.applied_on_client(client) + + async with new_worker(client, CustomToolWorkflow) as worker: + workflow_handle = await client.start_workflow( + CustomToolWorkflow.run, + id=f"custom-tool-workflow-{uuid.uuid4()}", + task_queue=worker.task_queue, + execution_timeout=timedelta(seconds=30), + ) + result = await workflow_handle.result() + assert result == "done:ping" + + class AssertDifferentModelProvider(ModelProvider): model_names: set[str | None] @@ -2538,6 +2603,79 @@ async def test_model_conversion_loops(): assert isinstance(triage_agent.model, _TemporalModelStub) +def test_sandbox_apply_patch_tool_round_trips_through_activity_input(): + class FakeSandboxSession: + pass + + tool = SandboxApplyPatchTool(session=FakeSandboxSession()) # type: ignore[arg-type] + + stub = _TemporalModelStub( + model_name="gpt-5", + model_params=ModelActivityParameters(), + agent=None, + ) + + activity_input, _summary = stub._build_activity_input( + system_instructions=None, + input="hi", + model_settings=ModelSettings(), + tools=[tool], + output_schema=None, + handoffs=[], + tracing=ModelTracing.DISABLED, + previous_response_id=None, + conversation_id=None, + prompt=None, + ) + + tool_inputs = activity_input.get("tools") or [] + assert len(tool_inputs) == 1 + rebuilt = _build_tool(tool_inputs[0]) + assert isinstance(rebuilt, CustomTool) + assert rebuilt.name == tool.name + assert rebuilt.description == tool.description + assert rebuilt.format == tool.format + assert rebuilt.tool_config == tool.tool_config + + +def test_custom_tool_with_defer_loading_round_trips_through_activity_input(): + async def stub(_ctx: Any, _payload: str) -> str: + return "" + + tool = CustomTool( + name="deferred_tool", + description="A custom tool with defer_loading enabled", + on_invoke_tool=stub, + defer_loading=True, + ) + + stub_model = _TemporalModelStub( + model_name="gpt-5", + model_params=ModelActivityParameters(), + agent=None, + ) + + activity_input, _summary = stub_model._build_activity_input( + system_instructions=None, + input="hi", + model_settings=ModelSettings(), + tools=[tool], + output_schema=None, + handoffs=[], + tracing=ModelTracing.DISABLED, + previous_response_id=None, + conversation_id=None, + prompt=None, + ) + + tool_inputs = activity_input.get("tools") or [] + assert len(tool_inputs) == 1 + rebuilt = _build_tool(tool_inputs[0]) + assert isinstance(rebuilt, CustomTool) + assert rebuilt.tool_config == tool.tool_config + assert rebuilt.defer_loading is True + + async def test_local_hello_world_agent(client: Client): async with AgentEnvironment( model=hello_mock_model(), From b9b2cc31db8fd85b23a81dd065da70a8bbab2616 Mon Sep 17 00:00:00 2001 From: brucearctor <5032356+brucearctor@users.noreply.github.com> Date: Thu, 11 Jun 2026 09:43:59 -0700 Subject: [PATCH 127/226] Fix interceptor contract inconsistency for start_update_with_start_workflow (#1588) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Fix interceptor contract inconsistency for start_update_with_start_workflow Add top-level rpc_metadata and rpc_timeout fields to StartWorkflowUpdateWithStartInput, making it consistent with every other OutboundInterceptor input dataclass. Previously this composite input lacked these fields, forcing interceptors to special-case it. Also fix the _ClientImpl to actually pass rpc_metadata and rpc_timeout to the execute_multi_operation gRPC call, which were previously silently dropped. Add a test verifying that rpc_metadata set by an interceptor on StartWorkflowUpdateWithStartInput is forwarded to the gRPC call. Fixes temporalio/sdk-python#1582 * Remove unused rpc_metadata/rpc_timeout from child interceptor inputs Remove rpc_metadata and rpc_timeout fields from UpdateWithStartUpdateWorkflowInput and UpdateWithStartStartWorkflowInput. These fields were never forwarded to the underlying execute_multi_operation gRPC call — only the top-level StartWorkflowUpdateWithStartInput fields are authoritative. Also remove the corresponding parameters from WithStartWorkflowOperation since they only served to populate the (now-removed) child input fields. This is a breaking change for interceptors that accessed rpc_metadata or rpc_timeout on the child input objects. --- temporalio/client/_client.py | 4 +- temporalio/client/_impl.py | 15 ++++- temporalio/client/_interceptor.py | 13 +++-- temporalio/client/_workflow.py | 12 ---- tests/worker/test_update_with_start.py | 81 ++++++++++++++++++++++++++ 5 files changed, 104 insertions(+), 21 deletions(-) diff --git a/temporalio/client/_client.py b/temporalio/client/_client.py index 1d8b8e4f2..3542efc60 100644 --- a/temporalio/client/_client.py +++ b/temporalio/client/_client.py @@ -1190,8 +1190,6 @@ async def _start_update_with_start( args=temporalio.common._arg_or_args(arg, args), headers={}, ret_type=result_type or result_type_from_type_hint, - rpc_metadata=rpc_metadata, - rpc_timeout=rpc_timeout, wait_for_stage=wait_for_stage, ) @@ -1216,6 +1214,8 @@ def on_start_error( input = StartWorkflowUpdateWithStartInput( start_workflow_input=start_workflow_operation._start_workflow_input, update_workflow_input=update_input, + rpc_metadata=rpc_metadata, + rpc_timeout=rpc_timeout, _on_start=on_start, _on_start_error=on_start_error, ) diff --git a/temporalio/client/_impl.py b/temporalio/client/_impl.py index e62f0b4a2..1481c8327 100644 --- a/temporalio/client/_impl.py +++ b/temporalio/client/_impl.py @@ -852,7 +852,11 @@ def on_start( try: return await self._start_workflow_update_with_start( - input.start_workflow_input, input.update_workflow_input, on_start + input.start_workflow_input, + input.update_workflow_input, + input.rpc_metadata, + input.rpc_timeout, + on_start, ) except asyncio.CancelledError as _err: err = _err @@ -914,6 +918,8 @@ async def _start_workflow_update_with_start( self, start_input: UpdateWithStartStartWorkflowInput, update_input: UpdateWithStartUpdateWorkflowInput, + rpc_metadata: Mapping[str, str | bytes], + rpc_timeout: timedelta | None, on_start: Callable[ [temporalio.api.workflowservice.v1.StartWorkflowExecutionResponse], None ], @@ -941,7 +947,12 @@ async def _start_workflow_update_with_start( # Repeatedly try to invoke ExecuteMultiOperation until the update is durable while True: multiop_response = ( - await self._client.workflow_service.execute_multi_operation(multiop_req) + await self._client.workflow_service.execute_multi_operation( + multiop_req, + retry=True, + metadata=rpc_metadata, + timeout=rpc_timeout, + ) ) start_response = multiop_response.responses[0].start_workflow update_response = multiop_response.responses[1].update_workflow diff --git a/temporalio/client/_interceptor.py b/temporalio/client/_interceptor.py index 0e780146d..5333d487f 100644 --- a/temporalio/client/_interceptor.py +++ b/temporalio/client/_interceptor.py @@ -334,8 +334,6 @@ class UpdateWithStartUpdateWorkflowInput: wait_for_stage: WorkflowUpdateStage headers: Mapping[str, temporalio.api.common.v1.Payload] ret_type: type | None - rpc_metadata: Mapping[str, str | bytes] - rpc_timeout: timedelta | None @dataclass @@ -366,18 +364,23 @@ class UpdateWithStartStartWorkflowInput: static_details: str | None # Type may be absent ret_type: type | None - rpc_metadata: Mapping[str, str | bytes] - rpc_timeout: timedelta | None priority: temporalio.common.Priority versioning_override: temporalio.common.VersioningOverride | None = None @dataclass class StartWorkflowUpdateWithStartInput: - """Input for :py:meth:`OutboundInterceptor.start_update_with_start_workflow`.""" + """Input for :py:meth:`OutboundInterceptor.start_update_with_start_workflow`. + + The ``rpc_metadata`` and ``rpc_timeout`` fields are authoritative for the + ``execute_multi_operation`` gRPC call. Interceptors that wish to set RPC + metadata should modify :py:attr:`rpc_metadata` on this object. + """ start_workflow_input: UpdateWithStartStartWorkflowInput update_workflow_input: UpdateWithStartUpdateWorkflowInput + rpc_metadata: Mapping[str, str | bytes] + rpc_timeout: timedelta | None _on_start: Callable[ [temporalio.api.workflowservice.v1.StartWorkflowExecutionResponse], None ] diff --git a/temporalio/client/_workflow.py b/temporalio/client/_workflow.py index e82006580..8579e8433 100644 --- a/temporalio/client/_workflow.py +++ b/temporalio/client/_workflow.py @@ -1065,8 +1065,6 @@ def __init__( static_summary: str | None = None, static_details: str | None = None, start_delay: timedelta | None = None, - rpc_metadata: Mapping[str, str | bytes] = {}, - rpc_timeout: timedelta | None = None, priority: temporalio.common.Priority = temporalio.common.Priority.default, versioning_override: temporalio.common.VersioningOverride | None = None, ) -> None: ... @@ -1095,8 +1093,6 @@ def __init__( static_summary: str | None = None, static_details: str | None = None, start_delay: timedelta | None = None, - rpc_metadata: Mapping[str, str | bytes] = {}, - rpc_timeout: timedelta | None = None, priority: temporalio.common.Priority = temporalio.common.Priority.default, versioning_override: temporalio.common.VersioningOverride | None = None, ) -> None: ... @@ -1127,8 +1123,6 @@ def __init__( static_summary: str | None = None, static_details: str | None = None, start_delay: timedelta | None = None, - rpc_metadata: Mapping[str, str | bytes] = {}, - rpc_timeout: timedelta | None = None, priority: temporalio.common.Priority = temporalio.common.Priority.default, versioning_override: temporalio.common.VersioningOverride | None = None, ) -> None: ... @@ -1159,8 +1153,6 @@ def __init__( static_summary: str | None = None, static_details: str | None = None, start_delay: timedelta | None = None, - rpc_metadata: Mapping[str, str | bytes] = {}, - rpc_timeout: timedelta | None = None, priority: temporalio.common.Priority = temporalio.common.Priority.default, versioning_override: temporalio.common.VersioningOverride | None = None, ) -> None: ... @@ -1189,8 +1181,6 @@ def __init__( static_summary: str | None = None, static_details: str | None = None, start_delay: timedelta | None = None, - rpc_metadata: Mapping[str, str | bytes] = {}, - rpc_timeout: timedelta | None = None, priority: temporalio.common.Priority = temporalio.common.Priority.default, versioning_override: temporalio.common.VersioningOverride | None = None, stack_level: int = 2, @@ -1228,8 +1218,6 @@ def __init__( start_delay=start_delay, headers={}, ret_type=result_type or result_type_from_run_fn, - rpc_metadata=rpc_metadata, - rpc_timeout=rpc_timeout, priority=priority, versioning_override=versioning_override, ) diff --git a/tests/worker/test_update_with_start.py b/tests/worker/test_update_with_start.py index 4ed625960..2ceb5e91b 100644 --- a/tests/worker/test_update_with_start.py +++ b/tests/worker/test_update_with_start.py @@ -1104,3 +1104,84 @@ async def _do_update() -> Any: elif id_reuse_policy == WorkflowIDReusePolicy.REJECT_DUPLICATE: with pytest.raises(WorkflowAlreadyStartedError): await _do_update() + + +class MetadataCapturingInterceptor(Interceptor): + """Interceptor that sets rpc_metadata on update-with-start calls.""" + + def intercept_client(self, next: OutboundInterceptor) -> OutboundInterceptor: + return MetadataCapturingOutboundInterceptor(super().intercept_client(next)) + + +class MetadataCapturingOutboundInterceptor(OutboundInterceptor): + def __init__(self, next: OutboundInterceptor) -> None: + super().__init__(next) + + async def start_update_with_start_workflow( + self, input: StartWorkflowUpdateWithStartInput + ) -> WorkflowUpdateHandle[Any]: + input.rpc_metadata = { + **input.rpc_metadata, + "test-header-key": "test-header-value", + } + return await super().start_update_with_start_workflow(input) + + +# Verify fix for https://github.com/temporalio/sdk-python/issues/1582 +async def test_update_with_start_rpc_metadata_and_timeout_forwarded(client: Client): + """Test that rpc_metadata and rpc_timeout on StartWorkflowUpdateWithStartInput + are forwarded to the execute_multi_operation gRPC call.""" + captured_metadata: dict[str, str | bytes] = {} + captured_timeout: list[timedelta | None] = [] + + class execute_multi_operation: + err = RPCError("intentional", RPCStatusCode.INTERNAL, b"") + err._grpc_status = temporalio.api.common.v1.GrpcStatus(details=[]) + + def __init__(self) -> None: # type: ignore[reportMissingSuperCall] + pass + + async def __call__( + self, + req: temporalio.api.workflowservice.v1.ExecuteMultiOperationRequest, + *, + retry: bool = False, + metadata: Mapping[str, str | bytes] = {}, + timeout: timedelta | None = None, + ) -> temporalio.api.workflowservice.v1.ExecuteMultiOperationResponse: + captured_metadata.update(metadata) + captured_timeout.append(timeout) + raise self.err + + interceptor = MetadataCapturingInterceptor() + intercepted_client = Client( + **{**client.config(), "interceptors": [interceptor]} # type: ignore + ) + + with patch.object( + intercepted_client.workflow_service, + "execute_multi_operation", + execute_multi_operation(), + ): + start_workflow_operation = WithStartWorkflowOperation( + UpdateWithStartInterceptorWorkflow.run, + "wf-arg", + id=f"wf-{uuid.uuid4()}", + task_queue="tq", + id_conflict_policy=WorkflowIDConflictPolicy.FAIL, + ) + with pytest.raises(RPCError): + await intercepted_client.start_update_with_start_workflow( + UpdateWithStartInterceptorWorkflow.my_update, + "update-arg", + start_workflow_operation=start_workflow_operation, + wait_for_stage=WorkflowUpdateStage.ACCEPTED, + rpc_metadata={"original-key": "original-value"}, + rpc_timeout=timedelta(seconds=42), + ) + + # The interceptor should have added its metadata on top of the caller's + assert captured_metadata.get("test-header-key") == "test-header-value" + assert captured_metadata.get("original-key") == "original-value" + # The caller's timeout should have been forwarded + assert captured_timeout == [timedelta(seconds=42)] From 53ae9fc7cf66794d1d56fa5fdd75f01a7653ff13 Mon Sep 17 00:00:00 2001 From: tconley1428 Date: Thu, 11 Jun 2026 09:44:25 -0700 Subject: [PATCH 128/226] Fix error message for tracer provider initialization (#1584) --- temporalio/contrib/opentelemetry/_otel_interceptor.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/temporalio/contrib/opentelemetry/_otel_interceptor.py b/temporalio/contrib/opentelemetry/_otel_interceptor.py index 6062f5022..c120fcd03 100644 --- a/temporalio/contrib/opentelemetry/_otel_interceptor.py +++ b/temporalio/contrib/opentelemetry/_otel_interceptor.py @@ -200,7 +200,7 @@ def workflow_interceptor_class( provider = get_tracer_provider() if not isinstance(provider, ReplaySafeTracerProvider): raise ValueError( - "When using OpenTelemetryPlugin, the global trace provider must be a ReplaySafeTracerProvider. Use init_tracer_provider to create one." + "When using OpenTelemetryPlugin, the global trace provider must be a ReplaySafeTracerProvider. Use create_tracer_provider to create one." ) class InterceptorWithState(_TracingWorkflowInboundInterceptor): From 0cf8b3e3cc8d33fc22ee9b069e638f030fccdc9f Mon Sep 17 00:00:00 2001 From: tconley1428 Date: Fri, 12 Jun 2026 09:32:09 -0700 Subject: [PATCH 129/226] System Nexus payload handling from WIT (#1572) * Early draft integration of nex-gen into python * Update Nexus system API generation * Port system Nexus payload handling to WIT generation * Use fully qualified system Nexus service registry keys * Update endpoint name and remove handler test in prep for actual server support * Update CLI version and lint fixes * Enable signal with start DC * Remove stale workflow Nexus import * Use sdk-core system Nexus WIT input * Use nex-gen support file option * Clarify optional system Nexus payload visitation * Remove generated pyright directive stripping * Move bounded visitor functions out of generated code * Add bounded visitor docstrings * Regenerate Nexus system API with nex-gen 0.1.4 * Move nex-gen support input out of package --- pyproject.toml | 5 +- scripts/gen_nexus_system_api.py | 163 +++++ scripts/gen_payload_visitor.py | 216 ++++-- scripts/nex_gen_support.py | 195 +++++ temporalio/bridge/_visitor.py | 284 ++++---- temporalio/bridge/_visitor_functions.py | 91 +++ temporalio/bridge/worker.py | 37 +- temporalio/nexus/system/__init__.py | 74 ++ temporalio/nexus/system/_payload_visitor.py | 133 ++++ .../nexus/system/workflow_service/__init__.py | 18 + .../workflow_service/_resources/__init__.py | 5 + .../workflow_service/_support/__init__.py | 5 + .../_support/nex_gen_support.py | 195 +++++ .../nexus/system/workflow_service/models.py | 141 ++++ .../workflow_service/operations/__init__.py | 3 + .../operations/signal_with_start_workflow.py | 674 ++++++++++++++++++ .../nexus/system/workflow_service/service.py | 21 + temporalio/worker/_command_aware_visitor.py | 3 +- temporalio/worker/_workflow_instance.py | 17 +- temporalio/workflow/__init__.py | 9 + tests/__init__.py | 2 +- tests/conftest.py | 2 + tests/nexus/test_temporal_system_nexus.py | 302 ++++++++ tests/worker/test_visitor.py | 68 +- 24 files changed, 2448 insertions(+), 215 deletions(-) create mode 100644 scripts/gen_nexus_system_api.py create mode 100644 scripts/nex_gen_support.py create mode 100644 temporalio/bridge/_visitor_functions.py create mode 100644 temporalio/nexus/system/__init__.py create mode 100644 temporalio/nexus/system/_payload_visitor.py create mode 100644 temporalio/nexus/system/workflow_service/__init__.py create mode 100644 temporalio/nexus/system/workflow_service/_resources/__init__.py create mode 100644 temporalio/nexus/system/workflow_service/_support/__init__.py create mode 100644 temporalio/nexus/system/workflow_service/_support/nex_gen_support.py create mode 100644 temporalio/nexus/system/workflow_service/models.py create mode 100644 temporalio/nexus/system/workflow_service/operations/__init__.py create mode 100644 temporalio/nexus/system/workflow_service/operations/signal_with_start_workflow.py create mode 100644 temporalio/nexus/system/workflow_service/service.py create mode 100644 tests/nexus/test_temporal_system_nexus.py diff --git a/pyproject.toml b/pyproject.toml index 317b378cb..99b86cfcb 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -99,14 +99,17 @@ format = [ { cmd = "cargo fmt", cwd = "temporalio/bridge" }, ] gen-docs = "uv run scripts/gen_docs.py" +gen-nexus-system-api = "uv run scripts/gen_nexus_system_api.py" gen-protos = [ { cmd = "uv run scripts/gen_protos.py" }, + { ref = "gen-nexus-system-api" }, { cmd = "uv run scripts/gen_payload_visitor.py" }, { cmd = "uv run scripts/gen_bridge_client.py" }, { ref = "format" }, ] gen-protos-docker = [ { cmd = "uv run scripts/gen_protos_docker.py" }, + { ref = "gen-nexus-system-api" }, { cmd = "uv run scripts/gen_payload_visitor.py" }, { cmd = "uv run scripts/gen_bridge_client.py" }, { ref = "format" }, @@ -170,7 +173,7 @@ exclude = [ [tool.pydocstyle] convention = "google" # https://github.com/PyCQA/pydocstyle/issues/363#issuecomment-625563088 -match_dir = "^(?!(docs|scripts|tests|api|proto|\\.)).*" +match_dir = "^(?!(docs|scripts|tests|api|proto|system|\\.)).*" add_ignore = [ # We like to wrap at a certain number of chars, even long summary sentences. # https://github.com/PyCQA/pydocstyle/issues/184 diff --git a/scripts/gen_nexus_system_api.py b/scripts/gen_nexus_system_api.py new file mode 100644 index 000000000..7ac1bd2de --- /dev/null +++ b/scripts/gen_nexus_system_api.py @@ -0,0 +1,163 @@ +import os +import shutil +import subprocess +import sys +import tempfile +from importlib.util import module_from_spec, spec_from_file_location +from pathlib import Path +from typing import cast + +import gen_protos + +base_dir = Path(__file__).parent.parent +sys.path.insert(0, str(base_dir)) +wit_input_dir = ( + base_dir + / "temporalio" + / "bridge" + / "sdk-core" + / "crates" + / "protos" + / "protos" + / "api_upstream" + / "nexus" +) +wit_path = wit_input_dir / "workflow-service.wit" +wit_deps_dir = wit_input_dir / "deps" +python_support_path = base_dir / "scripts" / "nex_gen_support.py" +output_dir = base_dir / "temporalio" / "nexus" / "system" / "workflow_service" +workflow_init_path = base_dir / "temporalio" / "workflow" / "__init__.py" +workflowservice_request_response_proto = ( + gen_protos.api_proto_dir + / "temporal" + / "api" + / "workflowservice" + / "v1" + / "request_response.proto" +) + + +def nex_gen_command() -> list[str]: + if bin_path := os.environ.get("NEX_GEN_BIN"): + return [bin_path] + + if shutil.which("nex-gen") is None: + subprocess.check_call(["cargo", "install", "--locked", "nex-gen", "--force"]) + return ["nex-gen"] + + +def build_descriptor_set(descriptor_path: Path) -> None: + subprocess.check_call( + [ + sys.executable, + "-mgrpc_tools.protoc", + f"--proto_path={gen_protos.api_proto_dir}", + f"--proto_path={gen_protos.proto_dir}", + "--include_imports", + f"--descriptor_set_out={descriptor_path}", + str(workflowservice_request_response_proto), + ] + ) + + +def generate_workflow_exports() -> None: + spec = spec_from_file_location( + "temporalio_nexus_system_workflow_service_exports", + output_dir / "__init__.py", + submodule_search_locations=[str(output_dir)], + ) + if spec is None or spec.loader is None: + raise RuntimeError(f"Cannot load generated workflow service from {output_dir}") + module = module_from_spec(spec) + sys.modules[spec.name] = module + spec.loader.exec_module(module) + exports = cast(list[str], module.__all__) + + import_block = [ + "# BEGIN GENERATED NEXUS SYSTEM EXPORTS\n", + "from temporalio.nexus.system.workflow_service import (\n", + *[f" {export},\n" for export in exports], + ")\n", + "# END GENERATED NEXUS SYSTEM EXPORTS\n", + ] + all_block = [ + " # BEGIN GENERATED NEXUS SYSTEM __ALL__\n", + *[f' "{export}",\n' for export in exports], + " # END GENERATED NEXUS SYSTEM __ALL__\n", + ] + content = workflow_init_path.read_text() + start = content.index("# BEGIN GENERATED NEXUS SYSTEM EXPORTS") + end = content.index("# END GENERATED NEXUS SYSTEM EXPORTS", start) + end = content.index("\n", end) + 1 + content = content[:start] + "".join(import_block) + content[end:] + start = content.index(" # BEGIN GENERATED NEXUS SYSTEM __ALL__") + end = content.index(" # END GENERATED NEXUS SYSTEM __ALL__", start) + end = content.index("\n", end) + 1 + workflow_init_path.write_text(content[:start] + "".join(all_block) + content[end:]) + + +def generate_nexus_system_api() -> None: + if not wit_path.exists(): + raise RuntimeError(f"missing WIT source: {wit_path}") + if not wit_deps_dir.exists(): + raise RuntimeError(f"missing WIT dependency directory: {wit_deps_dir}") + if not python_support_path.exists(): + raise RuntimeError(f"missing Python support source: {python_support_path}") + + with tempfile.TemporaryDirectory(dir=base_dir) as temp_dir: + descriptor_path = Path(temp_dir) / "temporal_api.bin" + build_descriptor_set(descriptor_path) + command = nex_gen_command() + + shutil.rmtree(output_dir, ignore_errors=True) + output_dir.parent.mkdir(parents=True, exist_ok=True) + subprocess.check_call( + [ + *command, + "generate", + "--lang", + "python", + "--input", + str(wit_path), + "--input", + str(wit_deps_dir), + "--support-file", + str(python_support_path), + "--descriptors", + str(descriptor_path), + "--output", + str(output_dir), + ] + ) + + (output_dir.parent / "__init__.py").touch() + generate_workflow_exports() + subprocess.check_call( + [ + sys.executable, + "-m", + "ruff", + "check", + "--select", + "I", + "--fix", + str(output_dir), + str(workflow_init_path), + ] + ) + subprocess.check_call( + [ + sys.executable, + "-m", + "ruff", + "format", + str(output_dir), + str(workflow_init_path), + ] + ) + + +if __name__ == "__main__": + print("Generating Nexus system API...", file=sys.stderr) + generate_nexus_system_api() + print("Done", file=sys.stderr) diff --git a/scripts/gen_payload_visitor.py b/scripts/gen_payload_visitor.py index 928be03e5..e3b988ca9 100644 --- a/scripts/gen_payload_visitor.py +++ b/scripts/gen_payload_visitor.py @@ -1,9 +1,16 @@ import subprocess import sys +from importlib.util import module_from_spec, spec_from_file_location from pathlib import Path +from typing import cast +import google.protobuf.message +import nexusrpc from google.protobuf.descriptor import Descriptor, FieldDescriptor +base_dir = Path(__file__).parent.parent +sys.path.insert(0, str(base_dir)) + from temporalio.api.common.v1.message_pb2 import Payload, Payloads, SearchAttributes from temporalio.bridge.proto.workflow_activation.workflow_activation_pb2 import ( WorkflowActivation, @@ -12,7 +19,36 @@ WorkflowActivationCompletion, ) -base_dir = Path(__file__).parent.parent + +def discover_system_nexus_roots() -> list[Descriptor]: + module_path = ( + base_dir / "temporalio" / "nexus" / "system" / "workflow_service" / "service.py" + ) + spec = spec_from_file_location( + "temporalio_nexus_system_workflow_service", module_path + ) + if spec is None or spec.loader is None: + raise RuntimeError(f"Cannot load generated system service from {module_path}") + module = module_from_spec(spec) + sys.modules[spec.name] = module + spec.loader.exec_module(module) + + roots: list[Descriptor] = [] + for operation in vars(module.WorkflowService).values(): + if not isinstance(operation, nexusrpc.Operation): + continue + for proto_type in (operation.input_type, operation.output_type): + if isinstance(proto_type, type) and issubclass( + proto_type, google.protobuf.message.Message + ): + roots.append(cast(Descriptor, proto_type.DESCRIPTOR)) + deduped: list[Descriptor] = [] + seen: set[str] = set() + for root in roots: + if root.full_name not in seen: + seen.add(root.full_name) + deduped.append(root) + return deduped def name_for(desc: Descriptor) -> str: @@ -80,78 +116,18 @@ def generate(self, roots: list[Descriptor]) -> str: self.walk(r) header = """ +from __future__ import annotations + # This file is generated by gen_payload_visitor.py. Changes should be made there. -import abc -import asyncio -from typing import Any, MutableSequence +from typing import Any +import temporalio.nexus.system from temporalio.api.common.v1.message_pb2 import Payload - - -class VisitorFunctions(abc.ABC): - \"\"\"Set of functions which can be called by the visitor. - Allows handling payloads as a sequence. - \"\"\" - - @abc.abstractmethod - async def visit_payload(self, payload: Payload) -> None: - \"\"\"Called when encountering a single payload.\"\"\" - raise NotImplementedError() - - @abc.abstractmethod - async def visit_payloads(self, payloads: MutableSequence[Payload]) -> None: - \"\"\"Called when encountering multiple payloads together.\"\"\" - raise NotImplementedError() - - -class _BoundedVisitorFunctions(VisitorFunctions): - \"\"\"Wraps VisitorFunctions to cap concurrent payload visits via a semaphore. - - After the full traversal, call drain() to await all in-flight tasks. - \"\"\" - - def __init__(self, inner: VisitorFunctions, sem: asyncio.Semaphore) -> None: - self._inner = inner - self._sem = sem - self._tasks: list[asyncio.Task[None]] = [] - - async def visit_payload(self, payload: Payload) -> None: - await self._sem.acquire() - - async def _run() -> None: - try: - await self._inner.visit_payload(payload) - finally: - self._sem.release() - - self._tasks.append(asyncio.create_task(_run())) - - async def visit_payloads(self, payloads: MutableSequence[Payload]) -> None: - await self._sem.acquire() - - async def _run() -> None: - try: - await self._inner.visit_payloads(payloads) - finally: - self._sem.release() - - self._tasks.append(asyncio.create_task(_run())) - - async def drain(self) -> None: - \"\"\"Wait for all in-flight background tasks to complete. - - On cancellation or error, cancels all remaining tasks and awaits - them so their finally blocks run before this coroutine returns. - \"\"\" - if not self._tasks: - return - try: - await asyncio.gather(*self._tasks) - except BaseException: - for task in self._tasks: - task.cancel() - await asyncio.gather(*self._tasks, return_exceptions=True) - raise +from temporalio.bridge._visitor_functions import ( + BoundedVisitorFunctions, + PayloadSequence, + VisitorFunctions, +) class PayloadVisitor: @@ -193,12 +169,34 @@ async def visit( await method(fs, root) return - bounded = _BoundedVisitorFunctions(fs, asyncio.Semaphore(self._concurrency_limit)) + bounded = BoundedVisitorFunctions(fs, self._concurrency_limit) try: await method(bounded, root) finally: await bounded.drain() + async def _visit_nexus_operation_input_payload( + self, + fs: VisitorFunctions, + service: str, + operation: str, + payload: Payload, + ) -> None: + new_payload = await temporalio.nexus.system.maybe_visit_payload( + service, + operation, + payload, + fs, + self.skip_search_attributes, + ) + if new_payload is None: + await self._visit_temporal_api_common_v1_Payload(fs, payload) + return + + if new_payload is not payload: + payload.CopyFrom(new_payload) + await fs.visit_system_nexus_envelope(payload) + """ return header + "\n".join(self.methods) @@ -212,15 +210,15 @@ def __init__(self): self.in_progress: set[str] = set() self.methods: list[str] = [ """\ - async def _visit_temporal_api_common_v1_Payload(self, fs, o): + async def _visit_temporal_api_common_v1_Payload(self, fs: VisitorFunctions, o: Payload): await fs.visit_payload(o) """, """\ - async def _visit_temporal_api_common_v1_Payloads(self, fs, o): + async def _visit_temporal_api_common_v1_Payloads(self, fs: VisitorFunctions, o: Any): await fs.visit_payloads(o.payloads) """, """\ - async def _visit_payload_container(self, fs, o): + async def _visit_payload_container(self, fs: VisitorFunctions, o: PayloadSequence): await fs.visit_payloads(o) """, ] @@ -275,6 +273,22 @@ def walk(self, desc: Descriptor) -> bool: # Process regular fields first for field in regular_fields: + if ( + desc.full_name == "coresdk.workflow_commands.ScheduleNexusOperation" + and field.name == "input" + ): + has_payload = True + emit_items.append( + ( + "system_nexus", + field.name, + "o.service", + "o.operation", + "o.input", + ) + ) + continue + # Repeated fields (including maps which are represented as repeated messages) if field.label == FieldDescriptor.LABEL_REPEATED: if ( @@ -359,7 +373,10 @@ def walk(self, desc: Descriptor) -> bool: self.in_progress.discard(key) if has_payload: - lines: list[str] = [f" async def _visit_{name_for(desc)}(self, fs, o):"] + lines: list[str] = [ + f" async def _visit_{name_for(desc)}" + "(self, fs: VisitorFunctions, o: Any):" + ] if is_search_attrs: lines.append(" if self.skip_search_attributes:") lines.append(" return") @@ -375,6 +392,14 @@ def walk(self, desc: Descriptor) -> bool: field_name, access_expr, child_method, presence_word ) ) + elif item[0] == "system_nexus": + _, field_name, service_expr, operation_expr, payload_expr = item + lines.append( + f' if o.HasField("{field_name}"):\n' + " await self._visit_nexus_operation_input_payload(\n" + f" fs, {service_expr}, {operation_expr}, {payload_expr}\n" + " )" + ) else: # oneof_group for field_name, access_expr, child_method, presence_word in item[1]: lines.append( @@ -387,8 +412,7 @@ def walk(self, desc: Descriptor) -> bool: return has_payload -def write_generated_visitors_into_visitor_generated_py() -> None: - """Write the generated visitor code into _visitor.py.""" +def write_bridge_visitors() -> None: out_path = base_dir / "temporalio" / "bridge" / "_visitor.py" # Build root descriptors: WorkflowActivation, WorkflowActivationCompletion, @@ -402,7 +426,41 @@ def write_generated_visitors_into_visitor_generated_py() -> None: out_path.write_text(code) +def write_system_nexus_payload_visitors() -> None: + out_path = base_dir / "temporalio" / "nexus" / "system" / "_payload_visitor.py" + code = VisitorGenerator().generate(discover_system_nexus_roots()) + out_path.write_text(code) + + if __name__ == "__main__": print("Generating temporalio/bridge/_visitor.py...", file=sys.stderr) - write_generated_visitors_into_visitor_generated_py() - subprocess.run(["uv", "run", "ruff", "format", "temporalio/bridge/_visitor.py"]) + write_bridge_visitors() + print("Generating temporalio/nexus/system/_payload_visitor.py...", file=sys.stderr) + write_system_nexus_payload_visitors() + subprocess.run( + [ + "uv", + "run", + "ruff", + "check", + "--select", + "I", + "--fix", + "temporalio/bridge/_visitor.py", + "temporalio/nexus/system/_payload_visitor.py", + ], + cwd=base_dir, + check=True, + ) + subprocess.run( + [ + "uv", + "run", + "ruff", + "format", + "temporalio/bridge/_visitor.py", + "temporalio/nexus/system/_payload_visitor.py", + ], + cwd=base_dir, + check=True, + ) diff --git a/scripts/nex_gen_support.py b/scripts/nex_gen_support.py new file mode 100644 index 000000000..58b51e263 --- /dev/null +++ b/scripts/nex_gen_support.py @@ -0,0 +1,195 @@ +import collections.abc +import typing +from datetime import timedelta + +import google.protobuf.duration_pb2 + +import temporalio.api.common.v1.message_pb2 as common_pb2 +import temporalio.api.enums.v1.workflow_pb2 as workflow_enums_pb2 +import temporalio.api.taskqueue.v1.message_pb2 as taskqueue_pb2 +import temporalio.api.workflow.v1 +import temporalio.common +import temporalio.converter + + +def retry_policy_from_proto( + proto: common_pb2.RetryPolicy, +) -> temporalio.common.RetryPolicy: + return temporalio.common.RetryPolicy.from_proto(proto) + + +def retry_policy_to_proto( + retry_policy: temporalio.common.RetryPolicy, +) -> common_pb2.RetryPolicy: + proto = common_pb2.RetryPolicy() + retry_policy.apply_to_proto(proto) + return proto + + +def workflow_function_name( + value: str | collections.abc.Callable[..., collections.abc.Awaitable[object]], +) -> str: + from temporalio.workflow import _Definition # pyright: ignore[reportPrivateUsage] + + name, _result_type = _Definition.get_name_and_result_type(value) + return name + + +def signal_function_to_proto( + value: str | collections.abc.Callable[..., typing.Any], +) -> str: + from temporalio.workflow import ( + _SignalDefinition, # pyright: ignore[reportPrivateUsage] + ) + + return _SignalDefinition.must_name_from_fn_or_str(value) # pyright: ignore[reportUnknownMemberType] + + +def workflow_type_to_proto( + workflow_type: str + | collections.abc.Callable[..., collections.abc.Awaitable[object]], +) -> common_pb2.WorkflowType: + return common_pb2.WorkflowType(name=workflow_function_name(workflow_type)) + + +def task_queue_from_proto( + proto: taskqueue_pb2.TaskQueue, +) -> str: + return proto.name + + +def task_queue_to_proto( + task_queue: str, +) -> taskqueue_pb2.TaskQueue: + return taskqueue_pb2.TaskQueue(name=task_queue) + + +def workflow_namespace() -> str: + from temporalio.workflow import info + + return info().namespace + + +def payloads_to_proto( + values: collections.abc.Sequence[typing.Any], +) -> common_pb2.Payloads: + from temporalio.workflow import payload_converter + + return payload_converter().to_payloads_wrapper(values) + + +def _clone_payload(payload: common_pb2.Payload) -> common_pb2.Payload: + clone = common_pb2.Payload() + clone.CopyFrom(payload) + return clone + + +def _value_to_payload(value: object | common_pb2.Payload) -> common_pb2.Payload: + if isinstance(value, common_pb2.Payload): + return _clone_payload(value) + from temporalio.workflow import payload_converter + + payloads = payload_converter().to_payloads_wrapper([value]) + return _clone_payload(payloads.payloads[0]) + + +def _payload_to_value(payload: common_pb2.Payload) -> object: + wrapper = common_pb2.Payloads() + wrapper.payloads.add().CopyFrom(payload) + from temporalio.workflow import payload_converter + + return typing.cast( + object, + payload_converter().from_payloads_wrapper(wrapper)[0], + ) + + +def payload_from_proto( + proto: common_pb2.Payload, +) -> object: + return _payload_to_value(proto) + + +def payload_to_proto( + payload: object, +) -> common_pb2.Payload: + return _value_to_payload(payload) + + +def memo_from_proto( + proto: common_pb2.Memo, +) -> collections.abc.Mapping[str, object]: + return {key: _payload_to_value(value) for key, value in proto.fields.items()} + + +def memo_to_proto( + memo: collections.abc.Mapping[str, object], +) -> common_pb2.Memo: + message = common_pb2.Memo() + for key, value in memo.items(): + message.fields[key].CopyFrom(_value_to_payload(value)) + return message + + +def duration_from_proto(proto: google.protobuf.duration_pb2.Duration) -> timedelta: + return proto.ToTimedelta() + + +def duration_to_proto( + duration: timedelta, +) -> google.protobuf.duration_pb2.Duration: + proto = google.protobuf.duration_pb2.Duration() + proto.FromTimedelta(duration) + return proto + + +def workflow_id_reuse_policy_from_proto( + policy: workflow_enums_pb2.WorkflowIdReusePolicy.ValueType, +) -> temporalio.common.WorkflowIDReusePolicy: + return temporalio.common.WorkflowIDReusePolicy(int(policy)) + + +def workflow_id_reuse_policy_to_proto( + policy: temporalio.common.WorkflowIDReusePolicy, +) -> workflow_enums_pb2.WorkflowIdReusePolicy.ValueType: + return typing.cast(workflow_enums_pb2.WorkflowIdReusePolicy.ValueType, int(policy)) + + +def workflow_id_conflict_policy_from_proto( + policy: workflow_enums_pb2.WorkflowIdConflictPolicy.ValueType, +) -> temporalio.common.WorkflowIDConflictPolicy: + return temporalio.common.WorkflowIDConflictPolicy(int(policy)) + + +def workflow_id_conflict_policy_to_proto( + policy: temporalio.common.WorkflowIDConflictPolicy, +) -> workflow_enums_pb2.WorkflowIdConflictPolicy.ValueType: + return typing.cast( + workflow_enums_pb2.WorkflowIdConflictPolicy.ValueType, int(policy) + ) + + +def search_attributes_to_proto( + search_attributes: temporalio.common.TypedSearchAttributes, +) -> common_pb2.SearchAttributes: + proto = common_pb2.SearchAttributes() + temporalio.converter.encode_search_attributes(search_attributes, proto) + return proto + + +def priority_from_proto( + proto: common_pb2.Priority, +) -> temporalio.common.Priority: + return temporalio.common.Priority._from_proto(proto) # pyright: ignore[reportPrivateUsage] + + +def priority_to_proto( + priority: temporalio.common.Priority, +) -> common_pb2.Priority: + return priority._to_proto() # pyright: ignore[reportPrivateUsage] + + +def versioning_override_to_proto( + versioning_override: temporalio.common.VersioningOverride, +) -> temporalio.api.workflow.v1.VersioningOverride: + return versioning_override._to_proto() # pyright: ignore[reportPrivateUsage] diff --git a/temporalio/bridge/_visitor.py b/temporalio/bridge/_visitor.py index 0f030ac01..5ec2b0547 100644 --- a/temporalio/bridge/_visitor.py +++ b/temporalio/bridge/_visitor.py @@ -1,75 +1,15 @@ +from __future__ import annotations + # This file is generated by gen_payload_visitor.py. Changes should be made there. -import abc -import asyncio -from typing import Any, MutableSequence +from typing import Any +import temporalio.nexus.system from temporalio.api.common.v1.message_pb2 import Payload - - -class VisitorFunctions(abc.ABC): - """Set of functions which can be called by the visitor. - Allows handling payloads as a sequence. - """ - - @abc.abstractmethod - async def visit_payload(self, payload: Payload) -> None: - """Called when encountering a single payload.""" - raise NotImplementedError() - - @abc.abstractmethod - async def visit_payloads(self, payloads: MutableSequence[Payload]) -> None: - """Called when encountering multiple payloads together.""" - raise NotImplementedError() - - -class _BoundedVisitorFunctions(VisitorFunctions): - """Wraps VisitorFunctions to cap concurrent payload visits via a semaphore. - - After the full traversal, call drain() to await all in-flight tasks. - """ - - def __init__(self, inner: VisitorFunctions, sem: asyncio.Semaphore) -> None: - self._inner = inner - self._sem = sem - self._tasks: list[asyncio.Task[None]] = [] - - async def visit_payload(self, payload: Payload) -> None: - await self._sem.acquire() - - async def _run() -> None: - try: - await self._inner.visit_payload(payload) - finally: - self._sem.release() - - self._tasks.append(asyncio.create_task(_run())) - - async def visit_payloads(self, payloads: MutableSequence[Payload]) -> None: - await self._sem.acquire() - - async def _run() -> None: - try: - await self._inner.visit_payloads(payloads) - finally: - self._sem.release() - - self._tasks.append(asyncio.create_task(_run())) - - async def drain(self) -> None: - """Wait for all in-flight background tasks to complete. - - On cancellation or error, cancels all remaining tasks and awaits - them so their finally blocks run before this coroutine returns. - """ - if not self._tasks: - return - try: - await asyncio.gather(*self._tasks) - except BaseException: - for task in self._tasks: - task.cancel() - await asyncio.gather(*self._tasks, return_exceptions=True) - raise +from temporalio.bridge._visitor_functions import ( + BoundedVisitorFunctions, + PayloadSequence, + VisitorFunctions, +) class PayloadVisitor: @@ -109,44 +49,78 @@ async def visit(self, fs: VisitorFunctions, root: Any) -> None: await method(fs, root) return - bounded = _BoundedVisitorFunctions( - fs, asyncio.Semaphore(self._concurrency_limit) - ) + bounded = BoundedVisitorFunctions(fs, self._concurrency_limit) try: await method(bounded, root) finally: await bounded.drain() - async def _visit_temporal_api_common_v1_Payload(self, fs, o): + async def _visit_nexus_operation_input_payload( + self, + fs: VisitorFunctions, + service: str, + operation: str, + payload: Payload, + ) -> None: + new_payload = await temporalio.nexus.system.maybe_visit_payload( + service, + operation, + payload, + fs, + self.skip_search_attributes, + ) + if new_payload is None: + await self._visit_temporal_api_common_v1_Payload(fs, payload) + return + + if new_payload is not payload: + payload.CopyFrom(new_payload) + await fs.visit_system_nexus_envelope(payload) + + async def _visit_temporal_api_common_v1_Payload( + self, fs: VisitorFunctions, o: Payload + ): await fs.visit_payload(o) - async def _visit_temporal_api_common_v1_Payloads(self, fs, o): + async def _visit_temporal_api_common_v1_Payloads( + self, fs: VisitorFunctions, o: Any + ): await fs.visit_payloads(o.payloads) - async def _visit_payload_container(self, fs, o): + async def _visit_payload_container(self, fs: VisitorFunctions, o: PayloadSequence): await fs.visit_payloads(o) - async def _visit_temporal_api_failure_v1_ApplicationFailureInfo(self, fs, o): + async def _visit_temporal_api_failure_v1_ApplicationFailureInfo( + self, fs: VisitorFunctions, o: Any + ): if o.HasField("details"): await self._visit_temporal_api_common_v1_Payloads(fs, o.details) - async def _visit_temporal_api_failure_v1_TimeoutFailureInfo(self, fs, o): + async def _visit_temporal_api_failure_v1_TimeoutFailureInfo( + self, fs: VisitorFunctions, o: Any + ): if o.HasField("last_heartbeat_details"): await self._visit_temporal_api_common_v1_Payloads( fs, o.last_heartbeat_details ) - async def _visit_temporal_api_failure_v1_CanceledFailureInfo(self, fs, o): + async def _visit_temporal_api_failure_v1_CanceledFailureInfo( + self, fs: VisitorFunctions, o: Any + ): if o.HasField("details"): await self._visit_temporal_api_common_v1_Payloads(fs, o.details) - async def _visit_temporal_api_failure_v1_ResetWorkflowFailureInfo(self, fs, o): + async def _visit_temporal_api_failure_v1_ResetWorkflowFailureInfo( + self, fs: VisitorFunctions, o: Any + ): if o.HasField("last_heartbeat_details"): await self._visit_temporal_api_common_v1_Payloads( fs, o.last_heartbeat_details ) - async def _visit_temporal_api_failure_v1_Failure(self, fs, o): + async def _visit_temporal_api_failure_v1_Failure( + self, fs: VisitorFunctions, o: Any + ): if o.HasField("encoded_attributes"): await self._visit_temporal_api_common_v1_Payload(fs, o.encoded_attributes) if o.HasField("cause"): @@ -168,17 +142,21 @@ async def _visit_temporal_api_failure_v1_Failure(self, fs, o): fs, o.reset_workflow_failure_info ) - async def _visit_temporal_api_common_v1_Memo(self, fs, o): + async def _visit_temporal_api_common_v1_Memo(self, fs: VisitorFunctions, o: Any): for v in o.fields.values(): await self._visit_temporal_api_common_v1_Payload(fs, v) - async def _visit_temporal_api_common_v1_SearchAttributes(self, fs, o): + async def _visit_temporal_api_common_v1_SearchAttributes( + self, fs: VisitorFunctions, o: Any + ): if self.skip_search_attributes: return for v in o.indexed_fields.values(): await self._visit_temporal_api_common_v1_Payload(fs, v) - async def _visit_coresdk_workflow_activation_InitializeWorkflow(self, fs, o): + async def _visit_coresdk_workflow_activation_InitializeWorkflow( + self, fs: VisitorFunctions, o: Any + ): await self._visit_payload_container(fs, o.arguments) if not self.skip_headers: for v in o.headers.values(): @@ -196,31 +174,43 @@ async def _visit_coresdk_workflow_activation_InitializeWorkflow(self, fs, o): fs, o.search_attributes ) - async def _visit_coresdk_workflow_activation_QueryWorkflow(self, fs, o): + async def _visit_coresdk_workflow_activation_QueryWorkflow( + self, fs: VisitorFunctions, o: Any + ): await self._visit_payload_container(fs, o.arguments) if not self.skip_headers: for v in o.headers.values(): await self._visit_temporal_api_common_v1_Payload(fs, v) - async def _visit_coresdk_workflow_activation_SignalWorkflow(self, fs, o): + async def _visit_coresdk_workflow_activation_SignalWorkflow( + self, fs: VisitorFunctions, o: Any + ): await self._visit_payload_container(fs, o.input) if not self.skip_headers: for v in o.headers.values(): await self._visit_temporal_api_common_v1_Payload(fs, v) - async def _visit_coresdk_activity_result_Success(self, fs, o): + async def _visit_coresdk_activity_result_Success( + self, fs: VisitorFunctions, o: Any + ): if o.HasField("result"): await self._visit_temporal_api_common_v1_Payload(fs, o.result) - async def _visit_coresdk_activity_result_Failure(self, fs, o): + async def _visit_coresdk_activity_result_Failure( + self, fs: VisitorFunctions, o: Any + ): if o.HasField("failure"): await self._visit_temporal_api_failure_v1_Failure(fs, o.failure) - async def _visit_coresdk_activity_result_Cancellation(self, fs, o): + async def _visit_coresdk_activity_result_Cancellation( + self, fs: VisitorFunctions, o: Any + ): if o.HasField("failure"): await self._visit_temporal_api_failure_v1_Failure(fs, o.failure) - async def _visit_coresdk_activity_result_ActivityResolution(self, fs, o): + async def _visit_coresdk_activity_result_ActivityResolution( + self, fs: VisitorFunctions, o: Any + ): if o.HasField("completed"): await self._visit_coresdk_activity_result_Success(fs, o.completed) elif o.HasField("failed"): @@ -228,37 +218,43 @@ async def _visit_coresdk_activity_result_ActivityResolution(self, fs, o): elif o.HasField("cancelled"): await self._visit_coresdk_activity_result_Cancellation(fs, o.cancelled) - async def _visit_coresdk_workflow_activation_ResolveActivity(self, fs, o): + async def _visit_coresdk_workflow_activation_ResolveActivity( + self, fs: VisitorFunctions, o: Any + ): if o.HasField("result"): await self._visit_coresdk_activity_result_ActivityResolution(fs, o.result) async def _visit_coresdk_workflow_activation_ResolveChildWorkflowExecutionStartCancelled( - self, fs, o + self, fs: VisitorFunctions, o: Any ): if o.HasField("failure"): await self._visit_temporal_api_failure_v1_Failure(fs, o.failure) async def _visit_coresdk_workflow_activation_ResolveChildWorkflowExecutionStart( - self, fs, o + self, fs: VisitorFunctions, o: Any ): if o.HasField("cancelled"): await self._visit_coresdk_workflow_activation_ResolveChildWorkflowExecutionStartCancelled( fs, o.cancelled ) - async def _visit_coresdk_child_workflow_Success(self, fs, o): + async def _visit_coresdk_child_workflow_Success(self, fs: VisitorFunctions, o: Any): if o.HasField("result"): await self._visit_temporal_api_common_v1_Payload(fs, o.result) - async def _visit_coresdk_child_workflow_Failure(self, fs, o): + async def _visit_coresdk_child_workflow_Failure(self, fs: VisitorFunctions, o: Any): if o.HasField("failure"): await self._visit_temporal_api_failure_v1_Failure(fs, o.failure) - async def _visit_coresdk_child_workflow_Cancellation(self, fs, o): + async def _visit_coresdk_child_workflow_Cancellation( + self, fs: VisitorFunctions, o: Any + ): if o.HasField("failure"): await self._visit_temporal_api_failure_v1_Failure(fs, o.failure) - async def _visit_coresdk_child_workflow_ChildWorkflowResult(self, fs, o): + async def _visit_coresdk_child_workflow_ChildWorkflowResult( + self, fs: VisitorFunctions, o: Any + ): if o.HasField("completed"): await self._visit_coresdk_child_workflow_Success(fs, o.completed) elif o.HasField("failed"): @@ -267,36 +263,40 @@ async def _visit_coresdk_child_workflow_ChildWorkflowResult(self, fs, o): await self._visit_coresdk_child_workflow_Cancellation(fs, o.cancelled) async def _visit_coresdk_workflow_activation_ResolveChildWorkflowExecution( - self, fs, o + self, fs: VisitorFunctions, o: Any ): if o.HasField("result"): await self._visit_coresdk_child_workflow_ChildWorkflowResult(fs, o.result) async def _visit_coresdk_workflow_activation_ResolveSignalExternalWorkflow( - self, fs, o + self, fs: VisitorFunctions, o: Any ): if o.HasField("failure"): await self._visit_temporal_api_failure_v1_Failure(fs, o.failure) async def _visit_coresdk_workflow_activation_ResolveRequestCancelExternalWorkflow( - self, fs, o + self, fs: VisitorFunctions, o: Any ): if o.HasField("failure"): await self._visit_temporal_api_failure_v1_Failure(fs, o.failure) - async def _visit_coresdk_workflow_activation_DoUpdate(self, fs, o): + async def _visit_coresdk_workflow_activation_DoUpdate( + self, fs: VisitorFunctions, o: Any + ): await self._visit_payload_container(fs, o.input) if not self.skip_headers: for v in o.headers.values(): await self._visit_temporal_api_common_v1_Payload(fs, v) async def _visit_coresdk_workflow_activation_ResolveNexusOperationStart( - self, fs, o + self, fs: VisitorFunctions, o: Any ): if o.HasField("failed"): await self._visit_temporal_api_failure_v1_Failure(fs, o.failed) - async def _visit_coresdk_nexus_NexusOperationResult(self, fs, o): + async def _visit_coresdk_nexus_NexusOperationResult( + self, fs: VisitorFunctions, o: Any + ): if o.HasField("completed"): await self._visit_temporal_api_common_v1_Payload(fs, o.completed) elif o.HasField("failed"): @@ -306,11 +306,15 @@ async def _visit_coresdk_nexus_NexusOperationResult(self, fs, o): elif o.HasField("timed_out"): await self._visit_temporal_api_failure_v1_Failure(fs, o.timed_out) - async def _visit_coresdk_workflow_activation_ResolveNexusOperation(self, fs, o): + async def _visit_coresdk_workflow_activation_ResolveNexusOperation( + self, fs: VisitorFunctions, o: Any + ): if o.HasField("result"): await self._visit_coresdk_nexus_NexusOperationResult(fs, o.result) - async def _visit_coresdk_workflow_activation_WorkflowActivationJob(self, fs, o): + async def _visit_coresdk_workflow_activation_WorkflowActivationJob( + self, fs: VisitorFunctions, o: Any + ): if o.HasField("initialize_workflow"): await self._visit_coresdk_workflow_activation_InitializeWorkflow( fs, o.initialize_workflow @@ -354,42 +358,56 @@ async def _visit_coresdk_workflow_activation_WorkflowActivationJob(self, fs, o): fs, o.resolve_nexus_operation ) - async def _visit_coresdk_workflow_activation_WorkflowActivation(self, fs, o): + async def _visit_coresdk_workflow_activation_WorkflowActivation( + self, fs: VisitorFunctions, o: Any + ): for v in o.jobs: await self._visit_coresdk_workflow_activation_WorkflowActivationJob(fs, v) - async def _visit_temporal_api_sdk_v1_UserMetadata(self, fs, o): + async def _visit_temporal_api_sdk_v1_UserMetadata( + self, fs: VisitorFunctions, o: Any + ): if o.HasField("summary"): await self._visit_temporal_api_common_v1_Payload(fs, o.summary) if o.HasField("details"): await self._visit_temporal_api_common_v1_Payload(fs, o.details) - async def _visit_coresdk_workflow_commands_ScheduleActivity(self, fs, o): + async def _visit_coresdk_workflow_commands_ScheduleActivity( + self, fs: VisitorFunctions, o: Any + ): if not self.skip_headers: for v in o.headers.values(): await self._visit_temporal_api_common_v1_Payload(fs, v) await self._visit_payload_container(fs, o.arguments) - async def _visit_coresdk_workflow_commands_QuerySuccess(self, fs, o): + async def _visit_coresdk_workflow_commands_QuerySuccess( + self, fs: VisitorFunctions, o: Any + ): if o.HasField("response"): await self._visit_temporal_api_common_v1_Payload(fs, o.response) - async def _visit_coresdk_workflow_commands_QueryResult(self, fs, o): + async def _visit_coresdk_workflow_commands_QueryResult( + self, fs: VisitorFunctions, o: Any + ): if o.HasField("succeeded"): await self._visit_coresdk_workflow_commands_QuerySuccess(fs, o.succeeded) elif o.HasField("failed"): await self._visit_temporal_api_failure_v1_Failure(fs, o.failed) - async def _visit_coresdk_workflow_commands_CompleteWorkflowExecution(self, fs, o): + async def _visit_coresdk_workflow_commands_CompleteWorkflowExecution( + self, fs: VisitorFunctions, o: Any + ): if o.HasField("result"): await self._visit_temporal_api_common_v1_Payload(fs, o.result) - async def _visit_coresdk_workflow_commands_FailWorkflowExecution(self, fs, o): + async def _visit_coresdk_workflow_commands_FailWorkflowExecution( + self, fs: VisitorFunctions, o: Any + ): if o.HasField("failure"): await self._visit_temporal_api_failure_v1_Failure(fs, o.failure) async def _visit_coresdk_workflow_commands_ContinueAsNewWorkflowExecution( - self, fs, o + self, fs: VisitorFunctions, o: Any ): await self._visit_payload_container(fs, o.arguments) for v in o.memo.values(): @@ -402,7 +420,9 @@ async def _visit_coresdk_workflow_commands_ContinueAsNewWorkflowExecution( fs, o.search_attributes ) - async def _visit_coresdk_workflow_commands_StartChildWorkflowExecution(self, fs, o): + async def _visit_coresdk_workflow_commands_StartChildWorkflowExecution( + self, fs: VisitorFunctions, o: Any + ): await self._visit_payload_container(fs, o.input) if not self.skip_headers: for v in o.headers.values(): @@ -415,42 +435,54 @@ async def _visit_coresdk_workflow_commands_StartChildWorkflowExecution(self, fs, ) async def _visit_coresdk_workflow_commands_SignalExternalWorkflowExecution( - self, fs, o + self, fs: VisitorFunctions, o: Any ): await self._visit_payload_container(fs, o.args) if not self.skip_headers: for v in o.headers.values(): await self._visit_temporal_api_common_v1_Payload(fs, v) - async def _visit_coresdk_workflow_commands_ScheduleLocalActivity(self, fs, o): + async def _visit_coresdk_workflow_commands_ScheduleLocalActivity( + self, fs: VisitorFunctions, o: Any + ): if not self.skip_headers: for v in o.headers.values(): await self._visit_temporal_api_common_v1_Payload(fs, v) await self._visit_payload_container(fs, o.arguments) async def _visit_coresdk_workflow_commands_UpsertWorkflowSearchAttributes( - self, fs, o + self, fs: VisitorFunctions, o: Any ): if o.HasField("search_attributes"): await self._visit_temporal_api_common_v1_SearchAttributes( fs, o.search_attributes ) - async def _visit_coresdk_workflow_commands_ModifyWorkflowProperties(self, fs, o): + async def _visit_coresdk_workflow_commands_ModifyWorkflowProperties( + self, fs: VisitorFunctions, o: Any + ): if o.HasField("upserted_memo"): await self._visit_temporal_api_common_v1_Memo(fs, o.upserted_memo) - async def _visit_coresdk_workflow_commands_UpdateResponse(self, fs, o): + async def _visit_coresdk_workflow_commands_UpdateResponse( + self, fs: VisitorFunctions, o: Any + ): if o.HasField("rejected"): await self._visit_temporal_api_failure_v1_Failure(fs, o.rejected) elif o.HasField("completed"): await self._visit_temporal_api_common_v1_Payload(fs, o.completed) - async def _visit_coresdk_workflow_commands_ScheduleNexusOperation(self, fs, o): + async def _visit_coresdk_workflow_commands_ScheduleNexusOperation( + self, fs: VisitorFunctions, o: Any + ): if o.HasField("input"): - await self._visit_temporal_api_common_v1_Payload(fs, o.input) + await self._visit_nexus_operation_input_payload( + fs, o.service, o.operation, o.input + ) - async def _visit_coresdk_workflow_commands_WorkflowCommand(self, fs, o): + async def _visit_coresdk_workflow_commands_WorkflowCommand( + self, fs: VisitorFunctions, o: Any + ): if o.HasField("user_metadata"): await self._visit_temporal_api_sdk_v1_UserMetadata(fs, o.user_metadata) if o.HasField("schedule_activity"): @@ -502,16 +534,20 @@ async def _visit_coresdk_workflow_commands_WorkflowCommand(self, fs, o): fs, o.schedule_nexus_operation ) - async def _visit_coresdk_workflow_completion_Success(self, fs, o): + async def _visit_coresdk_workflow_completion_Success( + self, fs: VisitorFunctions, o: Any + ): for v in o.commands: await self._visit_coresdk_workflow_commands_WorkflowCommand(fs, v) - async def _visit_coresdk_workflow_completion_Failure(self, fs, o): + async def _visit_coresdk_workflow_completion_Failure( + self, fs: VisitorFunctions, o: Any + ): if o.HasField("failure"): await self._visit_temporal_api_failure_v1_Failure(fs, o.failure) async def _visit_coresdk_workflow_completion_WorkflowActivationCompletion( - self, fs, o + self, fs: VisitorFunctions, o: Any ): if o.HasField("successful"): await self._visit_coresdk_workflow_completion_Success(fs, o.successful) diff --git a/temporalio/bridge/_visitor_functions.py b/temporalio/bridge/_visitor_functions.py new file mode 100644 index 000000000..548a0ea94 --- /dev/null +++ b/temporalio/bridge/_visitor_functions.py @@ -0,0 +1,91 @@ +from __future__ import annotations + +import asyncio +from typing import Protocol + +from google.protobuf.internal.containers import RepeatedCompositeFieldContainer + +from temporalio.api.common.v1.message_pb2 import Payload + +PayloadSequence = list[Payload] | RepeatedCompositeFieldContainer[Payload] + + +class VisitorFunctions(Protocol): + """Functions invoked by generated payload visitors.""" + + async def visit_payload(self, payload: Payload) -> None: + """Visit a single payload.""" + ... + + async def visit_payloads(self, payloads: PayloadSequence) -> None: + """Visit a sequence of payloads together.""" + ... + + async def visit_system_nexus_envelope(self, payload: Payload) -> None: + """Visit a recognized system Nexus envelope payload.""" + return None + + +class BoundedVisitorFunctions(VisitorFunctions): + """Wraps VisitorFunctions to cap concurrent payload visits via a semaphore. + + After the full traversal, call drain() to await all in-flight tasks. + """ + + def __init__(self, inner: VisitorFunctions, concurrency_limit: int) -> None: + """Create a bounded wrapper around the given visitor functions.""" + self._inner = inner + self._sem = asyncio.Semaphore(concurrency_limit) + self._tasks: list[asyncio.Task[None]] = [] + + async def visit_payload(self, payload: Payload) -> None: + """Visit a single payload once capacity is available.""" + await self._sem.acquire() + + async def _run() -> None: + try: + await self._inner.visit_payload(payload) + finally: + self._sem.release() + + self._tasks.append(asyncio.create_task(_run())) + + async def visit_payloads(self, payloads: PayloadSequence) -> None: + """Visit a sequence of payloads once capacity is available.""" + await self._sem.acquire() + + async def _run() -> None: + try: + await self._inner.visit_payloads(payloads) + finally: + self._sem.release() + + self._tasks.append(asyncio.create_task(_run())) + + async def visit_system_nexus_envelope(self, payload: Payload) -> None: + """Visit a system Nexus envelope payload once capacity is available.""" + await self._sem.acquire() + + async def _run() -> None: + try: + await self._inner.visit_system_nexus_envelope(payload) + finally: + self._sem.release() + + self._tasks.append(asyncio.create_task(_run())) + + async def drain(self) -> None: + """Wait for all in-flight background tasks to complete. + + On cancellation or error, cancels all remaining tasks and awaits + them so their finally blocks run before this coroutine returns. + """ + if not self._tasks: + return + try: + await asyncio.gather(*self._tasks) + except BaseException: + for task in self._tasks: + task.cancel() + await asyncio.gather(*self._tasks, return_exceptions=True) + raise diff --git a/temporalio/bridge/worker.py b/temporalio/bridge/worker.py index a9c857373..e1e23dd89 100644 --- a/temporalio/bridge/worker.py +++ b/temporalio/bridge/worker.py @@ -5,7 +5,7 @@ from __future__ import annotations -from collections.abc import Awaitable, Callable, MutableSequence, Sequence +from collections.abc import Awaitable, Callable, Sequence from dataclasses import dataclass from typing import ( TypeAlias, @@ -22,7 +22,7 @@ import temporalio.converter import temporalio.converter._extstore from temporalio.api.common.v1.message_pb2 import Payload -from temporalio.bridge._visitor import VisitorFunctions +from temporalio.bridge._visitor_functions import PayloadSequence, VisitorFunctions from temporalio.bridge.temporal_sdk_bridge import ( CustomSlotSupplier as BridgeCustomSlotSupplier, ) @@ -281,15 +281,20 @@ async def finalize_shutdown(self) -> None: class _Visitor(VisitorFunctions): - def __init__(self, f: Callable[[Sequence[Payload]], Awaitable[list[Payload]]]): + def __init__( + self, + f: Callable[[Sequence[Payload]], Awaitable[list[Payload]]], + visit_system_nexus_envelope: Callable[[Payload], Awaitable[None]] | None = None, + ): self._f = f + self._visit_system_nexus_envelope = visit_system_nexus_envelope async def visit_payload(self, payload: Payload) -> None: new_payload = (await self._f([payload]))[0] if new_payload is not payload: payload.CopyFrom(new_payload) - async def visit_payloads(self, payloads: MutableSequence[Payload]) -> None: + async def visit_payloads(self, payloads: PayloadSequence) -> None: if len(payloads) == 0: return new_payloads = await self._f(payloads) @@ -298,6 +303,10 @@ async def visit_payloads(self, payloads: MutableSequence[Payload]) -> None: del payloads[:] payloads.extend(new_payloads) + async def visit_system_nexus_envelope(self, payload: Payload) -> None: + if self._visit_system_nexus_envelope is not None: + await self._visit_system_nexus_envelope(payload) + async def decode_activation( activation: temporalio.bridge.proto.workflow_activation.WorkflowActivation, @@ -339,10 +348,20 @@ async def encode_completion( Returns: Metrics from any external storage store operations that occurred. """ + + async def _validate_system_nexus_envelope(payload: Payload) -> None: + data_converter._validate_payload_limits([payload]) + await CommandAwarePayloadVisitor( skip_search_attributes=True, skip_headers=not encode_headers, - ).visit(_Visitor(data_converter._encode_payload_sequence), completion) + ).visit( + _Visitor( + data_converter._encode_payload_sequence, + visit_system_nexus_envelope=_validate_system_nexus_envelope, + ), + completion, + ) async def _store_and_validate( payloads: Sequence[Payload], @@ -357,6 +376,12 @@ async def _store_and_validate( skip_search_attributes=True, skip_headers=not encode_headers, concurrency_limit=storage_concurrency_limit, - ).visit(_Visitor(_store_and_validate), completion) + ).visit( + _Visitor( + _store_and_validate, + visit_system_nexus_envelope=_validate_system_nexus_envelope, + ), + completion, + ) return metrics diff --git a/temporalio/nexus/system/__init__.py b/temporalio/nexus/system/__init__.py new file mode 100644 index 000000000..d4ab868c4 --- /dev/null +++ b/temporalio/nexus/system/__init__.py @@ -0,0 +1,74 @@ +"""System Nexus operation helpers.""" + +from __future__ import annotations + +import typing + +import google.protobuf.message +import nexusrpc + +import temporalio.api.common.v1 +import temporalio.converter +from temporalio.bridge._visitor_functions import VisitorFunctions +from temporalio.converter import BinaryProtoPayloadConverter, CompositePayloadConverter +from temporalio.nexus.system import workflow_service + + +class SystemNexusPayloadConverter(CompositePayloadConverter): + """Payload converter for system Nexus outer envelopes.""" + + def __init__(self) -> None: + """Create a payload converter for system Nexus outer envelopes.""" + super().__init__(BinaryProtoPayloadConverter()) + + +def _operation( + service: str, operation: str +) -> nexusrpc.Operation[typing.Any, typing.Any] | None: + return workflow_service.__nexus_operation_registry__.get((service, operation)) + + +async def maybe_visit_payload( + service: str, + operation: str, + payload: temporalio.api.common.v1.Payload, + visitor_functions: VisitorFunctions, + skip_search_attributes: bool, +) -> temporalio.api.common.v1.Payload | None: + """Visit nested payloads if the payload is a recognized system Nexus envelope.""" + operation_def = _operation(service, operation) + if operation_def is None: + return None + input_type = operation_def.input_type + if not ( + isinstance(input_type, type) + and issubclass(input_type, google.protobuf.message.Message) + ): + return None + + payload_converter = get_payload_converter() + value = payload_converter.from_payload(payload, input_type) + from ._payload_visitor import PayloadVisitor + + await PayloadVisitor(skip_search_attributes=skip_search_attributes).visit( + visitor_functions, value + ) + return payload_converter.to_payload(value) + + +def is_system_operation(service: str, operation: str) -> bool: + """Return whether a Nexus operation uses a generated system envelope.""" + return _operation(service, operation) is not None + + +def get_payload_converter() -> temporalio.converter.PayloadConverter: + """Return the fixed payload converter for system Nexus outer envelopes.""" + return SystemNexusPayloadConverter() + + +__all__ = [ + "get_payload_converter", + "is_system_operation", + "maybe_visit_payload", + "SystemNexusPayloadConverter", +] diff --git a/temporalio/nexus/system/_payload_visitor.py b/temporalio/nexus/system/_payload_visitor.py new file mode 100644 index 000000000..b569e2c19 --- /dev/null +++ b/temporalio/nexus/system/_payload_visitor.py @@ -0,0 +1,133 @@ +from __future__ import annotations + +# This file is generated by gen_payload_visitor.py. Changes should be made there. +from typing import Any + +import temporalio.nexus.system +from temporalio.api.common.v1.message_pb2 import Payload +from temporalio.bridge._visitor_functions import ( + BoundedVisitorFunctions, + PayloadSequence, + VisitorFunctions, +) + + +class PayloadVisitor: + """A visitor for payloads. + Applies a function to every payload in a tree of messages. + """ + + def __init__( + self, + *, + skip_search_attributes: bool = False, + skip_headers: bool = False, + concurrency_limit: int = 1, + ): + """Creates a new payload visitor. + + Args: + skip_search_attributes: If True, search attributes are not visited. + skip_headers: If True, headers are not visited. + concurrency_limit: Maximum number of payload visits that may run + concurrently during a single call to visit(). Defaults to 1 + (sequential). + """ + if concurrency_limit < 1: + raise ValueError("concurrency_limit must be positive") + self.skip_search_attributes = skip_search_attributes + self.skip_headers = skip_headers + self._concurrency_limit = concurrency_limit + + async def visit(self, fs: VisitorFunctions, root: Any) -> None: + """Visits the given root message with the given function.""" + method_name = "_visit_" + root.DESCRIPTOR.full_name.replace(".", "_") + method = getattr(self, method_name, None) + if method is None: + raise ValueError(f"Unknown root message type: {root.DESCRIPTOR.full_name}") + if self._concurrency_limit == 1: + await method(fs, root) + return + + bounded = BoundedVisitorFunctions(fs, self._concurrency_limit) + try: + await method(bounded, root) + finally: + await bounded.drain() + + async def _visit_nexus_operation_input_payload( + self, + fs: VisitorFunctions, + service: str, + operation: str, + payload: Payload, + ) -> None: + new_payload = await temporalio.nexus.system.maybe_visit_payload( + service, + operation, + payload, + fs, + self.skip_search_attributes, + ) + if new_payload is None: + await self._visit_temporal_api_common_v1_Payload(fs, payload) + return + + if new_payload is not payload: + payload.CopyFrom(new_payload) + await fs.visit_system_nexus_envelope(payload) + + async def _visit_temporal_api_common_v1_Payload( + self, fs: VisitorFunctions, o: Payload + ): + await fs.visit_payload(o) + + async def _visit_temporal_api_common_v1_Payloads( + self, fs: VisitorFunctions, o: Any + ): + await fs.visit_payloads(o.payloads) + + async def _visit_payload_container(self, fs: VisitorFunctions, o: PayloadSequence): + await fs.visit_payloads(o) + + async def _visit_temporal_api_common_v1_Memo(self, fs: VisitorFunctions, o: Any): + for v in o.fields.values(): + await self._visit_temporal_api_common_v1_Payload(fs, v) + + async def _visit_temporal_api_common_v1_SearchAttributes( + self, fs: VisitorFunctions, o: Any + ): + if self.skip_search_attributes: + return + for v in o.indexed_fields.values(): + await self._visit_temporal_api_common_v1_Payload(fs, v) + + async def _visit_temporal_api_common_v1_Header(self, fs: VisitorFunctions, o: Any): + for v in o.fields.values(): + await self._visit_temporal_api_common_v1_Payload(fs, v) + + async def _visit_temporal_api_sdk_v1_UserMetadata( + self, fs: VisitorFunctions, o: Any + ): + if o.HasField("summary"): + await self._visit_temporal_api_common_v1_Payload(fs, o.summary) + if o.HasField("details"): + await self._visit_temporal_api_common_v1_Payload(fs, o.details) + + async def _visit_temporal_api_workflowservice_v1_SignalWithStartWorkflowExecutionRequest( + self, fs: VisitorFunctions, o: Any + ): + if o.HasField("input"): + await self._visit_temporal_api_common_v1_Payloads(fs, o.input) + if o.HasField("signal_input"): + await self._visit_temporal_api_common_v1_Payloads(fs, o.signal_input) + if o.HasField("memo"): + await self._visit_temporal_api_common_v1_Memo(fs, o.memo) + if o.HasField("search_attributes"): + await self._visit_temporal_api_common_v1_SearchAttributes( + fs, o.search_attributes + ) + if o.HasField("header"): + await self._visit_temporal_api_common_v1_Header(fs, o.header) + if o.HasField("user_metadata"): + await self._visit_temporal_api_sdk_v1_UserMetadata(fs, o.user_metadata) diff --git a/temporalio/nexus/system/workflow_service/__init__.py b/temporalio/nexus/system/workflow_service/__init__.py new file mode 100644 index 000000000..7c24fa125 --- /dev/null +++ b/temporalio/nexus/system/workflow_service/__init__.py @@ -0,0 +1,18 @@ +# Generated by nex-gen. DO NOT EDIT! + +from __future__ import annotations + +from . import service as _service +from .operations.signal_with_start_workflow import signal_with_start_workflow + +__all__ = [ + "signal_with_start_workflow", +] + + +__nexus_operation_registry__ = { + ( + "temporal.api.workflowservice.v1.WorkflowService", + "SignalWithStartWorkflowExecution", + ): _service.WorkflowService.signal_with_start_workflow, +} diff --git a/temporalio/nexus/system/workflow_service/_resources/__init__.py b/temporalio/nexus/system/workflow_service/_resources/__init__.py new file mode 100644 index 000000000..373efbd33 --- /dev/null +++ b/temporalio/nexus/system/workflow_service/_resources/__init__.py @@ -0,0 +1,5 @@ +# Generated by nex-gen. DO NOT EDIT! + +from __future__ import annotations + +__all__ = [] diff --git a/temporalio/nexus/system/workflow_service/_support/__init__.py b/temporalio/nexus/system/workflow_service/_support/__init__.py new file mode 100644 index 000000000..530c33e80 --- /dev/null +++ b/temporalio/nexus/system/workflow_service/_support/__init__.py @@ -0,0 +1,5 @@ +# Generated by nex-gen. DO NOT EDIT! + +from __future__ import annotations + +from .nex_gen_support import * # noqa: F401,F403 diff --git a/temporalio/nexus/system/workflow_service/_support/nex_gen_support.py b/temporalio/nexus/system/workflow_service/_support/nex_gen_support.py new file mode 100644 index 000000000..58b51e263 --- /dev/null +++ b/temporalio/nexus/system/workflow_service/_support/nex_gen_support.py @@ -0,0 +1,195 @@ +import collections.abc +import typing +from datetime import timedelta + +import google.protobuf.duration_pb2 + +import temporalio.api.common.v1.message_pb2 as common_pb2 +import temporalio.api.enums.v1.workflow_pb2 as workflow_enums_pb2 +import temporalio.api.taskqueue.v1.message_pb2 as taskqueue_pb2 +import temporalio.api.workflow.v1 +import temporalio.common +import temporalio.converter + + +def retry_policy_from_proto( + proto: common_pb2.RetryPolicy, +) -> temporalio.common.RetryPolicy: + return temporalio.common.RetryPolicy.from_proto(proto) + + +def retry_policy_to_proto( + retry_policy: temporalio.common.RetryPolicy, +) -> common_pb2.RetryPolicy: + proto = common_pb2.RetryPolicy() + retry_policy.apply_to_proto(proto) + return proto + + +def workflow_function_name( + value: str | collections.abc.Callable[..., collections.abc.Awaitable[object]], +) -> str: + from temporalio.workflow import _Definition # pyright: ignore[reportPrivateUsage] + + name, _result_type = _Definition.get_name_and_result_type(value) + return name + + +def signal_function_to_proto( + value: str | collections.abc.Callable[..., typing.Any], +) -> str: + from temporalio.workflow import ( + _SignalDefinition, # pyright: ignore[reportPrivateUsage] + ) + + return _SignalDefinition.must_name_from_fn_or_str(value) # pyright: ignore[reportUnknownMemberType] + + +def workflow_type_to_proto( + workflow_type: str + | collections.abc.Callable[..., collections.abc.Awaitable[object]], +) -> common_pb2.WorkflowType: + return common_pb2.WorkflowType(name=workflow_function_name(workflow_type)) + + +def task_queue_from_proto( + proto: taskqueue_pb2.TaskQueue, +) -> str: + return proto.name + + +def task_queue_to_proto( + task_queue: str, +) -> taskqueue_pb2.TaskQueue: + return taskqueue_pb2.TaskQueue(name=task_queue) + + +def workflow_namespace() -> str: + from temporalio.workflow import info + + return info().namespace + + +def payloads_to_proto( + values: collections.abc.Sequence[typing.Any], +) -> common_pb2.Payloads: + from temporalio.workflow import payload_converter + + return payload_converter().to_payloads_wrapper(values) + + +def _clone_payload(payload: common_pb2.Payload) -> common_pb2.Payload: + clone = common_pb2.Payload() + clone.CopyFrom(payload) + return clone + + +def _value_to_payload(value: object | common_pb2.Payload) -> common_pb2.Payload: + if isinstance(value, common_pb2.Payload): + return _clone_payload(value) + from temporalio.workflow import payload_converter + + payloads = payload_converter().to_payloads_wrapper([value]) + return _clone_payload(payloads.payloads[0]) + + +def _payload_to_value(payload: common_pb2.Payload) -> object: + wrapper = common_pb2.Payloads() + wrapper.payloads.add().CopyFrom(payload) + from temporalio.workflow import payload_converter + + return typing.cast( + object, + payload_converter().from_payloads_wrapper(wrapper)[0], + ) + + +def payload_from_proto( + proto: common_pb2.Payload, +) -> object: + return _payload_to_value(proto) + + +def payload_to_proto( + payload: object, +) -> common_pb2.Payload: + return _value_to_payload(payload) + + +def memo_from_proto( + proto: common_pb2.Memo, +) -> collections.abc.Mapping[str, object]: + return {key: _payload_to_value(value) for key, value in proto.fields.items()} + + +def memo_to_proto( + memo: collections.abc.Mapping[str, object], +) -> common_pb2.Memo: + message = common_pb2.Memo() + for key, value in memo.items(): + message.fields[key].CopyFrom(_value_to_payload(value)) + return message + + +def duration_from_proto(proto: google.protobuf.duration_pb2.Duration) -> timedelta: + return proto.ToTimedelta() + + +def duration_to_proto( + duration: timedelta, +) -> google.protobuf.duration_pb2.Duration: + proto = google.protobuf.duration_pb2.Duration() + proto.FromTimedelta(duration) + return proto + + +def workflow_id_reuse_policy_from_proto( + policy: workflow_enums_pb2.WorkflowIdReusePolicy.ValueType, +) -> temporalio.common.WorkflowIDReusePolicy: + return temporalio.common.WorkflowIDReusePolicy(int(policy)) + + +def workflow_id_reuse_policy_to_proto( + policy: temporalio.common.WorkflowIDReusePolicy, +) -> workflow_enums_pb2.WorkflowIdReusePolicy.ValueType: + return typing.cast(workflow_enums_pb2.WorkflowIdReusePolicy.ValueType, int(policy)) + + +def workflow_id_conflict_policy_from_proto( + policy: workflow_enums_pb2.WorkflowIdConflictPolicy.ValueType, +) -> temporalio.common.WorkflowIDConflictPolicy: + return temporalio.common.WorkflowIDConflictPolicy(int(policy)) + + +def workflow_id_conflict_policy_to_proto( + policy: temporalio.common.WorkflowIDConflictPolicy, +) -> workflow_enums_pb2.WorkflowIdConflictPolicy.ValueType: + return typing.cast( + workflow_enums_pb2.WorkflowIdConflictPolicy.ValueType, int(policy) + ) + + +def search_attributes_to_proto( + search_attributes: temporalio.common.TypedSearchAttributes, +) -> common_pb2.SearchAttributes: + proto = common_pb2.SearchAttributes() + temporalio.converter.encode_search_attributes(search_attributes, proto) + return proto + + +def priority_from_proto( + proto: common_pb2.Priority, +) -> temporalio.common.Priority: + return temporalio.common.Priority._from_proto(proto) # pyright: ignore[reportPrivateUsage] + + +def priority_to_proto( + priority: temporalio.common.Priority, +) -> common_pb2.Priority: + return priority._to_proto() # pyright: ignore[reportPrivateUsage] + + +def versioning_override_to_proto( + versioning_override: temporalio.common.VersioningOverride, +) -> temporalio.api.workflow.v1.VersioningOverride: + return versioning_override._to_proto() # pyright: ignore[reportPrivateUsage] diff --git a/temporalio/nexus/system/workflow_service/models.py b/temporalio/nexus/system/workflow_service/models.py new file mode 100644 index 000000000..05e1e3088 --- /dev/null +++ b/temporalio/nexus/system/workflow_service/models.py @@ -0,0 +1,141 @@ +# Generated by nex-gen. DO NOT EDIT! + +from __future__ import annotations + +import collections.abc +import dataclasses +import datetime +import typing + +import temporalio.api.sdk.v1.user_metadata_pb2 +import temporalio.api.workflowservice.v1.request_response_pb2 +import temporalio.common + +from ._support import ( + duration_to_proto, + memo_to_proto, + payload_from_proto, + payload_to_proto, + payloads_to_proto, + priority_to_proto, + retry_policy_to_proto, + search_attributes_to_proto, + signal_function_to_proto, + task_queue_to_proto, + versioning_override_to_proto, + workflow_id_conflict_policy_to_proto, + workflow_id_reuse_policy_to_proto, + workflow_namespace, + workflow_type_to_proto, +) + + +@dataclasses.dataclass(slots=True, kw_only=True) +class SignalWithStartWorkflowRequest: + """ + .. warning:: + This API is experimental and subject to change. + """ + + workflow: str | collections.abc.Callable[..., collections.abc.Awaitable[object]] + args: list[typing.Any] | None = None + id: str + task_queue: str + signal: str | collections.abc.Callable[..., None | collections.abc.Awaitable[None]] + signal_args: list[typing.Any] | None = None + execution_timeout: datetime.timedelta | None = None + run_timeout: datetime.timedelta | None = None + task_timeout: datetime.timedelta | None = None + request_id: str | None = None + id_reuse_policy: temporalio.common.WorkflowIDReusePolicy = ( + temporalio.common.WorkflowIDReusePolicy.ALLOW_DUPLICATE + ) + id_conflict_policy: temporalio.common.WorkflowIDConflictPolicy | None = None + retry_policy: temporalio.common.RetryPolicy | None = None + cron_schedule: str | None = None + memo: collections.abc.Mapping[str, typing.Any] | None = None + search_attributes: temporalio.common.TypedSearchAttributes | None = None + priority: temporalio.common.Priority | None = None + versioning_override: temporalio.common.VersioningOverride | None = None + start_delay: datetime.timedelta | None = None + user_metadata: UserMetadata | None = None + + def to_proto( + self, + ) -> temporalio.api.workflowservice.v1.request_response_pb2.SignalWithStartWorkflowExecutionRequest: + message = temporalio.api.workflowservice.v1.request_response_pb2.SignalWithStartWorkflowExecutionRequest() + message.workflow_type.CopyFrom(workflow_type_to_proto(self.workflow)) + if self.args is not None: + message.input.CopyFrom(payloads_to_proto(self.args)) + message.workflow_id = self.id + message.task_queue.CopyFrom(task_queue_to_proto(self.task_queue)) + message.signal_name = signal_function_to_proto(self.signal) + if self.signal_args is not None: + message.signal_input.CopyFrom(payloads_to_proto(self.signal_args)) + if self.execution_timeout is not None: + message.workflow_execution_timeout.CopyFrom( + duration_to_proto(self.execution_timeout) + ) + if self.run_timeout is not None: + message.workflow_run_timeout.CopyFrom(duration_to_proto(self.run_timeout)) + if self.task_timeout is not None: + message.workflow_task_timeout.CopyFrom(duration_to_proto(self.task_timeout)) + if self.request_id is not None: + message.request_id = self.request_id + message.workflow_id_reuse_policy = workflow_id_reuse_policy_to_proto( + self.id_reuse_policy + ) + if self.id_conflict_policy is not None: + message.workflow_id_conflict_policy = workflow_id_conflict_policy_to_proto( + self.id_conflict_policy + ) + if self.retry_policy is not None: + message.retry_policy.CopyFrom(retry_policy_to_proto(self.retry_policy)) + if self.cron_schedule is not None: + message.cron_schedule = self.cron_schedule + if self.memo is not None: + message.memo.CopyFrom(memo_to_proto(self.memo)) + if self.search_attributes is not None: + message.search_attributes.CopyFrom( + search_attributes_to_proto(self.search_attributes) + ) + if self.priority is not None: + message.priority.CopyFrom(priority_to_proto(self.priority)) + if self.versioning_override is not None: + message.versioning_override.CopyFrom( + versioning_override_to_proto(self.versioning_override) + ) + if self.start_delay is not None: + message.workflow_start_delay.CopyFrom(duration_to_proto(self.start_delay)) + if self.user_metadata is not None: + message.user_metadata.CopyFrom(self.user_metadata.to_proto()) + message.namespace = workflow_namespace() + return message + + +@dataclasses.dataclass(slots=True) +class UserMetadata: + static_summary: typing.Any | None = None + static_details: typing.Any | None = None + + @classmethod + def from_proto( + cls, + proto: temporalio.api.sdk.v1.user_metadata_pb2.UserMetadata, + ) -> UserMetadata: + return cls( + static_summary=payload_from_proto(proto.summary) + if proto.HasField("summary") + else None, + static_details=payload_from_proto(proto.details) + if proto.HasField("details") + else None, + ) + + def to_proto(self) -> temporalio.api.sdk.v1.user_metadata_pb2.UserMetadata: + message = temporalio.api.sdk.v1.user_metadata_pb2.UserMetadata() + if self.static_summary is not None: + message.summary.CopyFrom(payload_to_proto(self.static_summary)) + if self.static_details is not None: + message.details.CopyFrom(payload_to_proto(self.static_details)) + return message diff --git a/temporalio/nexus/system/workflow_service/operations/__init__.py b/temporalio/nexus/system/workflow_service/operations/__init__.py new file mode 100644 index 000000000..67c9cc56b --- /dev/null +++ b/temporalio/nexus/system/workflow_service/operations/__init__.py @@ -0,0 +1,3 @@ +# Generated by nex-gen. DO NOT EDIT! + +from __future__ import annotations diff --git a/temporalio/nexus/system/workflow_service/operations/signal_with_start_workflow.py b/temporalio/nexus/system/workflow_service/operations/signal_with_start_workflow.py new file mode 100644 index 000000000..0865e5a88 --- /dev/null +++ b/temporalio/nexus/system/workflow_service/operations/signal_with_start_workflow.py @@ -0,0 +1,674 @@ +# Generated by nex-gen. DO NOT EDIT! + +from __future__ import annotations + +import collections.abc +import datetime +import typing + +import typing_extensions + +import temporalio.api.workflowservice.v1.request_response_pb2 +import temporalio.common + +if typing.TYPE_CHECKING: + from temporalio.workflow import ExternalWorkflowHandle + +from ..models import ( + SignalWithStartWorkflowRequest, + UserMetadata, +) + +SelfType = typing.TypeVar("SelfType") +SignalArg = typing.TypeVar("SignalArg") +WorkflowResult = typing.TypeVar("WorkflowResult") +WorkflowArgs = typing_extensions.TypeVarTuple("WorkflowArgs") + + +async def _signal_with_start_workflow( + request: SignalWithStartWorkflowRequest, +) -> ExternalWorkflowHandle[typing.Any]: + from temporalio.workflow import ( + create_nexus_client, + get_external_workflow_handle, + ) + + request_proto = request.to_proto() + nexus_client = create_nexus_client( + service="temporal.api.workflowservice.v1.WorkflowService", + endpoint="__temporal_system", + ) + handle = await nexus_client.start_operation( + operation="SignalWithStartWorkflowExecution", + input=request_proto, + output_type=temporalio.api.workflowservice.v1.request_response_pb2.SignalWithStartWorkflowExecutionResponse, + ) + result = await handle + return get_external_workflow_handle(request.id, run_id=result.run_id) + + +# Overload case: +# - workflow name with positional workflow arguments +# - signal name with optional list-form signal arguments +@typing.overload +async def signal_with_start_workflow( + workflow: str, + *args: object, + id: str, + task_queue: str, + signal: str, + signal_args: list[typing.Any] | None = ..., + execution_timeout: datetime.timedelta | None = ..., + run_timeout: datetime.timedelta | None = ..., + task_timeout: datetime.timedelta | None = ..., + request_id: str | None = ..., + id_reuse_policy: temporalio.common.WorkflowIDReusePolicy = ..., + id_conflict_policy: temporalio.common.WorkflowIDConflictPolicy | None = ..., + retry_policy: temporalio.common.RetryPolicy | None = ..., + cron_schedule: str | None = ..., + memo: collections.abc.Mapping[str, typing.Any] | None = ..., + search_attributes: temporalio.common.TypedSearchAttributes | None = ..., + priority: temporalio.common.Priority | None = ..., + versioning_override: temporalio.common.VersioningOverride | None = ..., + start_delay: datetime.timedelta | None = ..., + static_summary: str | None = ..., + static_details: str | None = ..., +) -> ExternalWorkflowHandle[object]: ... + + +# Overload case: +# - workflow name with optional list-form workflow arguments +# - signal name with optional list-form signal arguments +@typing.overload +async def signal_with_start_workflow( + workflow: str, + *, + args: list[typing.Any] | None = ..., + id: str, + task_queue: str, + signal: str, + signal_args: list[typing.Any] | None = ..., + execution_timeout: datetime.timedelta | None = ..., + run_timeout: datetime.timedelta | None = ..., + task_timeout: datetime.timedelta | None = ..., + request_id: str | None = ..., + id_reuse_policy: temporalio.common.WorkflowIDReusePolicy = ..., + id_conflict_policy: temporalio.common.WorkflowIDConflictPolicy | None = ..., + retry_policy: temporalio.common.RetryPolicy | None = ..., + cron_schedule: str | None = ..., + memo: collections.abc.Mapping[str, typing.Any] | None = ..., + search_attributes: temporalio.common.TypedSearchAttributes | None = ..., + priority: temporalio.common.Priority | None = ..., + versioning_override: temporalio.common.VersioningOverride | None = ..., + start_delay: datetime.timedelta | None = ..., + static_summary: str | None = ..., + static_details: str | None = ..., +) -> ExternalWorkflowHandle[object]: ... + + +# Overload case: +# - workflow method callable with typed positional workflow arguments +# - signal name with optional list-form signal arguments +@typing.overload +async def signal_with_start_workflow( + workflow: collections.abc.Callable[ + [SelfType, typing_extensions.Unpack[WorkflowArgs]], + collections.abc.Awaitable[WorkflowResult], + ], + *args: typing_extensions.Unpack[WorkflowArgs], + id: str, + task_queue: str, + signal: str, + signal_args: list[typing.Any] | None = ..., + execution_timeout: datetime.timedelta | None = ..., + run_timeout: datetime.timedelta | None = ..., + task_timeout: datetime.timedelta | None = ..., + request_id: str | None = ..., + id_reuse_policy: temporalio.common.WorkflowIDReusePolicy = ..., + id_conflict_policy: temporalio.common.WorkflowIDConflictPolicy | None = ..., + retry_policy: temporalio.common.RetryPolicy | None = ..., + cron_schedule: str | None = ..., + memo: collections.abc.Mapping[str, typing.Any] | None = ..., + search_attributes: temporalio.common.TypedSearchAttributes | None = ..., + priority: temporalio.common.Priority | None = ..., + versioning_override: temporalio.common.VersioningOverride | None = ..., + start_delay: datetime.timedelta | None = ..., + static_summary: str | None = ..., + static_details: str | None = ..., +) -> ExternalWorkflowHandle[SelfType]: ... + + +# Overload case: +# - workflow method callable with list-form workflow arguments +# - signal name with optional list-form signal arguments +@typing.overload +async def signal_with_start_workflow( + workflow: collections.abc.Callable[ + [SelfType, typing_extensions.Unpack[WorkflowArgs]], + collections.abc.Awaitable[WorkflowResult], + ], + *, + args: list[typing.Any], + id: str, + task_queue: str, + signal: str, + signal_args: list[typing.Any] | None = ..., + execution_timeout: datetime.timedelta | None = ..., + run_timeout: datetime.timedelta | None = ..., + task_timeout: datetime.timedelta | None = ..., + request_id: str | None = ..., + id_reuse_policy: temporalio.common.WorkflowIDReusePolicy = ..., + id_conflict_policy: temporalio.common.WorkflowIDConflictPolicy | None = ..., + retry_policy: temporalio.common.RetryPolicy | None = ..., + cron_schedule: str | None = ..., + memo: collections.abc.Mapping[str, typing.Any] | None = ..., + search_attributes: temporalio.common.TypedSearchAttributes | None = ..., + priority: temporalio.common.Priority | None = ..., + versioning_override: temporalio.common.VersioningOverride | None = ..., + start_delay: datetime.timedelta | None = ..., + static_summary: str | None = ..., + static_details: str | None = ..., +) -> ExternalWorkflowHandle[SelfType]: ... + + +# Overload case: +# - workflow name with positional workflow arguments +# - signal method callable with no signal arguments +@typing.overload +async def signal_with_start_workflow( + workflow: str, + *args: object, + id: str, + task_queue: str, + signal: collections.abc.Callable[ + [SelfType], None | collections.abc.Awaitable[None] + ], + execution_timeout: datetime.timedelta | None = ..., + run_timeout: datetime.timedelta | None = ..., + task_timeout: datetime.timedelta | None = ..., + request_id: str | None = ..., + id_reuse_policy: temporalio.common.WorkflowIDReusePolicy = ..., + id_conflict_policy: temporalio.common.WorkflowIDConflictPolicy | None = ..., + retry_policy: temporalio.common.RetryPolicy | None = ..., + cron_schedule: str | None = ..., + memo: collections.abc.Mapping[str, typing.Any] | None = ..., + search_attributes: temporalio.common.TypedSearchAttributes | None = ..., + priority: temporalio.common.Priority | None = ..., + versioning_override: temporalio.common.VersioningOverride | None = ..., + start_delay: datetime.timedelta | None = ..., + static_summary: str | None = ..., + static_details: str | None = ..., +) -> ExternalWorkflowHandle[SelfType]: ... + + +# Overload case: +# - workflow name with optional list-form workflow arguments +# - signal method callable with no signal arguments +@typing.overload +async def signal_with_start_workflow( + workflow: str, + *, + args: list[typing.Any] | None = ..., + id: str, + task_queue: str, + signal: collections.abc.Callable[ + [SelfType], None | collections.abc.Awaitable[None] + ], + execution_timeout: datetime.timedelta | None = ..., + run_timeout: datetime.timedelta | None = ..., + task_timeout: datetime.timedelta | None = ..., + request_id: str | None = ..., + id_reuse_policy: temporalio.common.WorkflowIDReusePolicy = ..., + id_conflict_policy: temporalio.common.WorkflowIDConflictPolicy | None = ..., + retry_policy: temporalio.common.RetryPolicy | None = ..., + cron_schedule: str | None = ..., + memo: collections.abc.Mapping[str, typing.Any] | None = ..., + search_attributes: temporalio.common.TypedSearchAttributes | None = ..., + priority: temporalio.common.Priority | None = ..., + versioning_override: temporalio.common.VersioningOverride | None = ..., + start_delay: datetime.timedelta | None = ..., + static_summary: str | None = ..., + static_details: str | None = ..., +) -> ExternalWorkflowHandle[SelfType]: ... + + +# Overload case: +# - workflow method callable with typed positional workflow arguments +# - signal method callable with no signal arguments +@typing.overload +async def signal_with_start_workflow( + workflow: collections.abc.Callable[ + [SelfType, typing_extensions.Unpack[WorkflowArgs]], + collections.abc.Awaitable[WorkflowResult], + ], + *args: typing_extensions.Unpack[WorkflowArgs], + id: str, + task_queue: str, + signal: collections.abc.Callable[ + [SelfType], None | collections.abc.Awaitable[None] + ], + execution_timeout: datetime.timedelta | None = ..., + run_timeout: datetime.timedelta | None = ..., + task_timeout: datetime.timedelta | None = ..., + request_id: str | None = ..., + id_reuse_policy: temporalio.common.WorkflowIDReusePolicy = ..., + id_conflict_policy: temporalio.common.WorkflowIDConflictPolicy | None = ..., + retry_policy: temporalio.common.RetryPolicy | None = ..., + cron_schedule: str | None = ..., + memo: collections.abc.Mapping[str, typing.Any] | None = ..., + search_attributes: temporalio.common.TypedSearchAttributes | None = ..., + priority: temporalio.common.Priority | None = ..., + versioning_override: temporalio.common.VersioningOverride | None = ..., + start_delay: datetime.timedelta | None = ..., + static_summary: str | None = ..., + static_details: str | None = ..., +) -> ExternalWorkflowHandle[SelfType]: ... + + +# Overload case: +# - workflow method callable with list-form workflow arguments +# - signal method callable with no signal arguments +@typing.overload +async def signal_with_start_workflow( + workflow: collections.abc.Callable[ + [SelfType, typing_extensions.Unpack[WorkflowArgs]], + collections.abc.Awaitable[WorkflowResult], + ], + *, + args: list[typing.Any], + id: str, + task_queue: str, + signal: collections.abc.Callable[ + [SelfType], None | collections.abc.Awaitable[None] + ], + execution_timeout: datetime.timedelta | None = ..., + run_timeout: datetime.timedelta | None = ..., + task_timeout: datetime.timedelta | None = ..., + request_id: str | None = ..., + id_reuse_policy: temporalio.common.WorkflowIDReusePolicy = ..., + id_conflict_policy: temporalio.common.WorkflowIDConflictPolicy | None = ..., + retry_policy: temporalio.common.RetryPolicy | None = ..., + cron_schedule: str | None = ..., + memo: collections.abc.Mapping[str, typing.Any] | None = ..., + search_attributes: temporalio.common.TypedSearchAttributes | None = ..., + priority: temporalio.common.Priority | None = ..., + versioning_override: temporalio.common.VersioningOverride | None = ..., + start_delay: datetime.timedelta | None = ..., + static_summary: str | None = ..., + static_details: str | None = ..., +) -> ExternalWorkflowHandle[SelfType]: ... + + +# Overload case: +# - workflow name with positional workflow arguments +# - signal method callable with a typed single signal arguments +@typing.overload +async def signal_with_start_workflow( + workflow: str, + *args: object, + id: str, + task_queue: str, + signal: collections.abc.Callable[ + [SelfType, SignalArg], None | collections.abc.Awaitable[None] + ], + signal_args: SignalArg, + execution_timeout: datetime.timedelta | None = ..., + run_timeout: datetime.timedelta | None = ..., + task_timeout: datetime.timedelta | None = ..., + request_id: str | None = ..., + id_reuse_policy: temporalio.common.WorkflowIDReusePolicy = ..., + id_conflict_policy: temporalio.common.WorkflowIDConflictPolicy | None = ..., + retry_policy: temporalio.common.RetryPolicy | None = ..., + cron_schedule: str | None = ..., + memo: collections.abc.Mapping[str, typing.Any] | None = ..., + search_attributes: temporalio.common.TypedSearchAttributes | None = ..., + priority: temporalio.common.Priority | None = ..., + versioning_override: temporalio.common.VersioningOverride | None = ..., + start_delay: datetime.timedelta | None = ..., + static_summary: str | None = ..., + static_details: str | None = ..., +) -> ExternalWorkflowHandle[SelfType]: ... + + +# Overload case: +# - workflow name with optional list-form workflow arguments +# - signal method callable with a typed single signal arguments +@typing.overload +async def signal_with_start_workflow( + workflow: str, + *, + args: list[typing.Any] | None = ..., + id: str, + task_queue: str, + signal: collections.abc.Callable[ + [SelfType, SignalArg], None | collections.abc.Awaitable[None] + ], + signal_args: SignalArg, + execution_timeout: datetime.timedelta | None = ..., + run_timeout: datetime.timedelta | None = ..., + task_timeout: datetime.timedelta | None = ..., + request_id: str | None = ..., + id_reuse_policy: temporalio.common.WorkflowIDReusePolicy = ..., + id_conflict_policy: temporalio.common.WorkflowIDConflictPolicy | None = ..., + retry_policy: temporalio.common.RetryPolicy | None = ..., + cron_schedule: str | None = ..., + memo: collections.abc.Mapping[str, typing.Any] | None = ..., + search_attributes: temporalio.common.TypedSearchAttributes | None = ..., + priority: temporalio.common.Priority | None = ..., + versioning_override: temporalio.common.VersioningOverride | None = ..., + start_delay: datetime.timedelta | None = ..., + static_summary: str | None = ..., + static_details: str | None = ..., +) -> ExternalWorkflowHandle[SelfType]: ... + + +# Overload case: +# - workflow method callable with typed positional workflow arguments +# - signal method callable with a typed single signal arguments +@typing.overload +async def signal_with_start_workflow( + workflow: collections.abc.Callable[ + [SelfType, typing_extensions.Unpack[WorkflowArgs]], + collections.abc.Awaitable[WorkflowResult], + ], + *args: typing_extensions.Unpack[WorkflowArgs], + id: str, + task_queue: str, + signal: collections.abc.Callable[ + [SelfType, SignalArg], None | collections.abc.Awaitable[None] + ], + signal_args: SignalArg, + execution_timeout: datetime.timedelta | None = ..., + run_timeout: datetime.timedelta | None = ..., + task_timeout: datetime.timedelta | None = ..., + request_id: str | None = ..., + id_reuse_policy: temporalio.common.WorkflowIDReusePolicy = ..., + id_conflict_policy: temporalio.common.WorkflowIDConflictPolicy | None = ..., + retry_policy: temporalio.common.RetryPolicy | None = ..., + cron_schedule: str | None = ..., + memo: collections.abc.Mapping[str, typing.Any] | None = ..., + search_attributes: temporalio.common.TypedSearchAttributes | None = ..., + priority: temporalio.common.Priority | None = ..., + versioning_override: temporalio.common.VersioningOverride | None = ..., + start_delay: datetime.timedelta | None = ..., + static_summary: str | None = ..., + static_details: str | None = ..., +) -> ExternalWorkflowHandle[SelfType]: ... + + +# Overload case: +# - workflow method callable with list-form workflow arguments +# - signal method callable with a typed single signal arguments +@typing.overload +async def signal_with_start_workflow( + workflow: collections.abc.Callable[ + [SelfType, typing_extensions.Unpack[WorkflowArgs]], + collections.abc.Awaitable[WorkflowResult], + ], + *, + args: list[typing.Any], + id: str, + task_queue: str, + signal: collections.abc.Callable[ + [SelfType, SignalArg], None | collections.abc.Awaitable[None] + ], + signal_args: SignalArg, + execution_timeout: datetime.timedelta | None = ..., + run_timeout: datetime.timedelta | None = ..., + task_timeout: datetime.timedelta | None = ..., + request_id: str | None = ..., + id_reuse_policy: temporalio.common.WorkflowIDReusePolicy = ..., + id_conflict_policy: temporalio.common.WorkflowIDConflictPolicy | None = ..., + retry_policy: temporalio.common.RetryPolicy | None = ..., + cron_schedule: str | None = ..., + memo: collections.abc.Mapping[str, typing.Any] | None = ..., + search_attributes: temporalio.common.TypedSearchAttributes | None = ..., + priority: temporalio.common.Priority | None = ..., + versioning_override: temporalio.common.VersioningOverride | None = ..., + start_delay: datetime.timedelta | None = ..., + static_summary: str | None = ..., + static_details: str | None = ..., +) -> ExternalWorkflowHandle[SelfType]: ... + + +# Overload case: +# - workflow name with positional workflow arguments +# - signal callable with list-form signal arguments +@typing.overload +async def signal_with_start_workflow( + workflow: str, + *args: object, + id: str, + task_queue: str, + signal: collections.abc.Callable[..., None | collections.abc.Awaitable[None]], + signal_args: list[typing.Any], + execution_timeout: datetime.timedelta | None = ..., + run_timeout: datetime.timedelta | None = ..., + task_timeout: datetime.timedelta | None = ..., + request_id: str | None = ..., + id_reuse_policy: temporalio.common.WorkflowIDReusePolicy = ..., + id_conflict_policy: temporalio.common.WorkflowIDConflictPolicy | None = ..., + retry_policy: temporalio.common.RetryPolicy | None = ..., + cron_schedule: str | None = ..., + memo: collections.abc.Mapping[str, typing.Any] | None = ..., + search_attributes: temporalio.common.TypedSearchAttributes | None = ..., + priority: temporalio.common.Priority | None = ..., + versioning_override: temporalio.common.VersioningOverride | None = ..., + start_delay: datetime.timedelta | None = ..., + static_summary: str | None = ..., + static_details: str | None = ..., +) -> ExternalWorkflowHandle[object]: ... + + +# Overload case: +# - workflow name with optional list-form workflow arguments +# - signal callable with list-form signal arguments +@typing.overload +async def signal_with_start_workflow( + workflow: str, + *, + args: list[typing.Any] | None = ..., + id: str, + task_queue: str, + signal: collections.abc.Callable[..., None | collections.abc.Awaitable[None]], + signal_args: list[typing.Any], + execution_timeout: datetime.timedelta | None = ..., + run_timeout: datetime.timedelta | None = ..., + task_timeout: datetime.timedelta | None = ..., + request_id: str | None = ..., + id_reuse_policy: temporalio.common.WorkflowIDReusePolicy = ..., + id_conflict_policy: temporalio.common.WorkflowIDConflictPolicy | None = ..., + retry_policy: temporalio.common.RetryPolicy | None = ..., + cron_schedule: str | None = ..., + memo: collections.abc.Mapping[str, typing.Any] | None = ..., + search_attributes: temporalio.common.TypedSearchAttributes | None = ..., + priority: temporalio.common.Priority | None = ..., + versioning_override: temporalio.common.VersioningOverride | None = ..., + start_delay: datetime.timedelta | None = ..., + static_summary: str | None = ..., + static_details: str | None = ..., +) -> ExternalWorkflowHandle[object]: ... + + +# Overload case: +# - workflow method callable with typed positional workflow arguments +# - signal callable with list-form signal arguments +@typing.overload +async def signal_with_start_workflow( + workflow: collections.abc.Callable[ + [SelfType, typing_extensions.Unpack[WorkflowArgs]], + collections.abc.Awaitable[WorkflowResult], + ], + *args: typing_extensions.Unpack[WorkflowArgs], + id: str, + task_queue: str, + signal: collections.abc.Callable[..., None | collections.abc.Awaitable[None]], + signal_args: list[typing.Any], + execution_timeout: datetime.timedelta | None = ..., + run_timeout: datetime.timedelta | None = ..., + task_timeout: datetime.timedelta | None = ..., + request_id: str | None = ..., + id_reuse_policy: temporalio.common.WorkflowIDReusePolicy = ..., + id_conflict_policy: temporalio.common.WorkflowIDConflictPolicy | None = ..., + retry_policy: temporalio.common.RetryPolicy | None = ..., + cron_schedule: str | None = ..., + memo: collections.abc.Mapping[str, typing.Any] | None = ..., + search_attributes: temporalio.common.TypedSearchAttributes | None = ..., + priority: temporalio.common.Priority | None = ..., + versioning_override: temporalio.common.VersioningOverride | None = ..., + start_delay: datetime.timedelta | None = ..., + static_summary: str | None = ..., + static_details: str | None = ..., +) -> ExternalWorkflowHandle[SelfType]: ... + + +# Overload case: +# - workflow method callable with list-form workflow arguments +# - signal callable with list-form signal arguments +@typing.overload +async def signal_with_start_workflow( + workflow: collections.abc.Callable[ + [SelfType, typing_extensions.Unpack[WorkflowArgs]], + collections.abc.Awaitable[WorkflowResult], + ], + *, + args: list[typing.Any], + id: str, + task_queue: str, + signal: collections.abc.Callable[..., None | collections.abc.Awaitable[None]], + signal_args: list[typing.Any], + execution_timeout: datetime.timedelta | None = ..., + run_timeout: datetime.timedelta | None = ..., + task_timeout: datetime.timedelta | None = ..., + request_id: str | None = ..., + id_reuse_policy: temporalio.common.WorkflowIDReusePolicy = ..., + id_conflict_policy: temporalio.common.WorkflowIDConflictPolicy | None = ..., + retry_policy: temporalio.common.RetryPolicy | None = ..., + cron_schedule: str | None = ..., + memo: collections.abc.Mapping[str, typing.Any] | None = ..., + search_attributes: temporalio.common.TypedSearchAttributes | None = ..., + priority: temporalio.common.Priority | None = ..., + versioning_override: temporalio.common.VersioningOverride | None = ..., + start_delay: datetime.timedelta | None = ..., + static_summary: str | None = ..., + static_details: str | None = ..., +) -> ExternalWorkflowHandle[SelfType]: ... + + +async def signal_with_start_workflow( + workflow: str | collections.abc.Callable[..., collections.abc.Awaitable[object]], + *positional_args: object, + args: list[typing.Any] | None = None, + id: str, + task_queue: str, + signal: str | collections.abc.Callable[..., None | collections.abc.Awaitable[None]], + signal_args: object | list[typing.Any] | None = None, + execution_timeout: datetime.timedelta | None = None, + run_timeout: datetime.timedelta | None = None, + task_timeout: datetime.timedelta | None = None, + request_id: str | None = None, + id_reuse_policy: temporalio.common.WorkflowIDReusePolicy = ( + temporalio.common.WorkflowIDReusePolicy.ALLOW_DUPLICATE + ), + id_conflict_policy: temporalio.common.WorkflowIDConflictPolicy | None = None, + retry_policy: temporalio.common.RetryPolicy | None = None, + cron_schedule: str | None = None, + memo: collections.abc.Mapping[str, typing.Any] | None = None, + search_attributes: temporalio.common.TypedSearchAttributes | None = None, + priority: temporalio.common.Priority | None = None, + versioning_override: temporalio.common.VersioningOverride | None = None, + start_delay: datetime.timedelta | None = None, + static_summary: str | None = None, + static_details: str | None = None, +) -> ExternalWorkflowHandle[typing.Any]: + """Signal a workflow, starting it first if needed. + + .. warning:: + This API is experimental and subject to change. + + Args: + workflow: Workflow type name or callable identifying the workflow to start. + positional_args: Positional arguments for workflow. Cannot be set if args is + set. + args: List-form arguments for workflow. Cannot be set if positional_args are + set. For typed workflow callables, list contents are not statically + typechecked; pass workflow arguments positionally for precise typechecking. + id: Unique identifier for the workflow execution. + task_queue: Task queue to run the workflow on. + signal: Signal name or callable to send with the start request. + signal_args: Argument value, or list of argument values, for signal. For typed + single-argument signals, scalar signal_args values are statically + typechecked. List-form signal_args values are not precisely typechecked. To + pass a single signal argument that is itself a list, wrap it in another + list; otherwise the list is interpreted as multiple signal arguments. + execution_timeout: Total workflow execution timeout, including retries and + continue-as-new. + run_timeout: Timeout of a single workflow run. + task_timeout: Timeout of a single workflow task. + request_id: Request ID used to deduplicate workflow start requests. + id_reuse_policy: Behavior when a closed workflow with the same ID exists. + Default is allow-duplicate. + id_conflict_policy: Behavior when a workflow is currently running with the same + ID. Set to use-existing for idempotent deduplication on workflow ID. Cannot + be set if id-reuse-policy is terminate-if-running. + retry_policy: Retry policy for the workflow. + cron_schedule: Cron schedule for recurring workflow executions. See + https://docs.temporal.io/cron-job. + memo: Memo for the workflow. + search_attributes: Typed search attributes for the workflow. + priority: Priority of the workflow execution. + versioning_override: Override for workflow versioning behavior. + start_delay: Amount of time to wait before starting the workflow. This does not + work with cron-schedule. + static_summary: Single-line fixed summary for the workflow execution that may + appear in UI and CLI. This can be in single-line Temporal Markdown format. + static_details: General fixed details for the workflow execution that may appear + in UI and CLI. This can be in Temporal Markdown format and can span multiple + lines. This value is fixed on the workflow execution and cannot be updated. + + Returns: + A workflow handle to the started workflow. + """ + normalized_signal_args: list[typing.Any] | None + if signal_args is None: + normalized_signal_args = None + elif isinstance(signal_args, list): + normalized_signal_args = typing.cast(list[typing.Any], signal_args) + else: + normalized_signal_args = [signal_args] + if positional_args and args is not None: + raise TypeError("cannot specify both positional arguments and args") + normalized_args: list[typing.Any] | None = ( + list(positional_args) if positional_args else args + ) + user_metadata = ( + None + if static_summary is None and static_details is None + else UserMetadata( + static_summary=static_summary, + static_details=static_details, + ) + ) + request = SignalWithStartWorkflowRequest( + workflow=workflow, + args=normalized_args, + id=id, + task_queue=task_queue, + signal=signal, + signal_args=normalized_signal_args, + execution_timeout=execution_timeout, + run_timeout=run_timeout, + task_timeout=task_timeout, + request_id=request_id, + id_reuse_policy=id_reuse_policy, + id_conflict_policy=id_conflict_policy, + retry_policy=retry_policy, + cron_schedule=cron_schedule, + memo=memo, + search_attributes=search_attributes, + priority=priority, + versioning_override=versioning_override, + start_delay=start_delay, + user_metadata=user_metadata, + ) + return await _signal_with_start_workflow(request) diff --git a/temporalio/nexus/system/workflow_service/service.py b/temporalio/nexus/system/workflow_service/service.py new file mode 100644 index 000000000..7ce5849ca --- /dev/null +++ b/temporalio/nexus/system/workflow_service/service.py @@ -0,0 +1,21 @@ +# Generated by nex-gen. DO NOT EDIT! + +from __future__ import annotations + +from nexusrpc import Operation, service + +import temporalio.api.workflowservice.v1.request_response_pb2 + + +@service(name="temporal.api.workflowservice.v1.WorkflowService") +class WorkflowService: + """ + .. warning:: + This API is experimental and subject to change. + """ + + # .. warning:: This API is experimental and subject to change. + signal_with_start_workflow: Operation[ + temporalio.api.workflowservice.v1.request_response_pb2.SignalWithStartWorkflowExecutionRequest, + temporalio.api.workflowservice.v1.request_response_pb2.SignalWithStartWorkflowExecutionResponse, + ] = Operation(name="SignalWithStartWorkflowExecution") diff --git a/temporalio/worker/_command_aware_visitor.py b/temporalio/worker/_command_aware_visitor.py index f77bea042..500fc4db5 100644 --- a/temporalio/worker/_command_aware_visitor.py +++ b/temporalio/worker/_command_aware_visitor.py @@ -6,7 +6,8 @@ from dataclasses import dataclass from temporalio.api.enums.v1.command_type_pb2 import CommandType -from temporalio.bridge._visitor import PayloadVisitor, VisitorFunctions +from temporalio.bridge._visitor import PayloadVisitor +from temporalio.bridge._visitor_functions import VisitorFunctions from temporalio.bridge.proto.workflow_activation.workflow_activation_pb2 import ( ResolveActivity, ResolveChildWorkflowExecution, diff --git a/temporalio/worker/_workflow_instance.py b/temporalio/worker/_workflow_instance.py index 76ccdb2e3..deefb5ad3 100644 --- a/temporalio/worker/_workflow_instance.py +++ b/temporalio/worker/_workflow_instance.py @@ -57,6 +57,7 @@ import temporalio.common import temporalio.converter import temporalio.exceptions +import temporalio.nexus.system import temporalio.workflow from temporalio.converter import StorageDriverStoreContext, StorageDriverWorkflowInfo from temporalio.service import __version__ @@ -2085,8 +2086,19 @@ async def operation_handle_fn() -> OutputT: ): t.uncancel() # type: ignore[union-attr] + payload_converter = ( + temporalio.nexus.system.get_payload_converter() + if temporalio.nexus.system.is_system_operation( + input.service, input.operation_name + ) + else self._context_free_payload_converter + ) handle = _NexusOperationHandle( - self, self._next_seq("nexus_operation"), input, operation_handle_fn() + self, + self._next_seq("nexus_operation"), + input, + operation_handle_fn(), + payload_converter, ) handle._apply_schedule_command() self._pending_nexus_operations[handle._seq] = handle @@ -3453,6 +3465,7 @@ def __init__( seq: int, input: StartNexusOperationInput[Any, OutputT], fn: Coroutine[Any, Any, OutputT], + payload_converter: temporalio.converter.PayloadConverter, ): self._instance = instance self._seq = seq @@ -3460,7 +3473,7 @@ def __init__( self._task = asyncio.Task(fn) self._start_fut: asyncio.Future[str | None] = instance.create_future() self._result_fut: asyncio.Future[OutputT | None] = instance.create_future() - self._payload_converter = self._instance._context_free_payload_converter + self._payload_converter = payload_converter self._failure_converter = self._instance._context_free_failure_converter @property diff --git a/temporalio/workflow/__init__.py b/temporalio/workflow/__init__.py index 8b8b0fb6f..3d5a65c77 100644 --- a/temporalio/workflow/__init__.py +++ b/temporalio/workflow/__init__.py @@ -2,6 +2,12 @@ from __future__ import annotations +# BEGIN GENERATED NEXUS SYSTEM EXPORTS +from temporalio.nexus.system.workflow_service import ( + signal_with_start_workflow, +) + +# END GENERATED NEXUS SYSTEM EXPORTS from ..types import ( AnyType, CallableAsyncNoParam, @@ -314,4 +320,7 @@ "ProtocolReturnType", "ReturnType", "SelfType", + # BEGIN GENERATED NEXUS SYSTEM __ALL__ + "signal_with_start_workflow", + # END GENERATED NEXUS SYSTEM __ALL__ ] diff --git a/tests/__init__.py b/tests/__init__.py index d62129b39..4725d3a7e 100644 --- a/tests/__init__.py +++ b/tests/__init__.py @@ -1 +1 @@ -DEV_SERVER_DOWNLOAD_VERSION = "v1.7.1-standalone-nexus-operations" +DEV_SERVER_DOWNLOAD_VERSION = "v1.7.1-system-nexus-operations" diff --git a/tests/conftest.py b/tests/conftest.py index 1e1db3730..9eaa1ff47 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -136,6 +136,8 @@ async def env(env_type: str) -> AsyncGenerator[WorkflowEnvironment, None]: "nexusoperation.enableStandalone=true", "--dynamic-config-value", 'system.system.refreshNexusEndpointsMinWait="0s"', + "--dynamic-config-value", + "history.enableSignalWithStartFromWorkflow=true", ], dev_server_download_version=DEV_SERVER_DOWNLOAD_VERSION, ) diff --git a/tests/nexus/test_temporal_system_nexus.py b/tests/nexus/test_temporal_system_nexus.py new file mode 100644 index 000000000..c7d9319ca --- /dev/null +++ b/tests/nexus/test_temporal_system_nexus.py @@ -0,0 +1,302 @@ +from __future__ import annotations + +import dataclasses +import uuid +from collections.abc import Sequence +from datetime import timedelta +from typing import Any, cast + +import pytest +from google.protobuf.descriptor import FieldDescriptor +from google.protobuf.message import Message + +import temporalio.api.common.v1 +import temporalio.api.workflowservice.v1.request_response_pb2 as workflowservice_pb2 +import temporalio.converter +import temporalio.nexus.system as nexus_system +from temporalio import workflow +from temporalio.client import Client +from temporalio.converter import ExternalStorage, PayloadCodec +from temporalio.testing import WorkflowEnvironment +from temporalio.worker import ( + Interceptor, + StartNexusOperationInput, + Worker, + WorkflowInboundInterceptor, + WorkflowInterceptorClassInput, + WorkflowOutboundInterceptor, +) +from temporalio.worker._workflow_instance import UnsandboxedWorkflowRunner +from tests.test_extstore import InMemoryTestDriver + +interceptor_traces: list[tuple[str, object]] = [] + + +@workflow.defn +class ExternalHandleSignalWithStartWorkflowCaller: + @workflow.run + async def run(self, task_queue: str) -> str: + started_handle = await workflow.signal_with_start_workflow( + "test-workflow", + "workflow-input", + id="system-nexus-workflow-id", + task_queue=task_queue, + signal="test-signal", + signal_args=["signal-input"], + memo={"memo-key": "memo-value"}, + static_summary="summary-value", + static_details="details-value", + ) + return started_handle.id + + +class RejectOuterSystemNexusCodec(PayloadCodec): + def __init__(self) -> None: + self.encode_count = 0 + + async def encode( + self, payloads: Sequence[temporalio.api.common.v1.Payload] + ) -> list[temporalio.api.common.v1.Payload]: + encoded: list[temporalio.api.common.v1.Payload] = [] + for payload in payloads: + if ( + payload.metadata.get("encoding") == b"binary/protobuf" + and payload.metadata.get("messageType") + == b"temporal.api.workflowservice.v1.SignalWithStartWorkflowExecutionRequest" + ): + raise RuntimeError( + "outer system nexus envelope should not be codec encoded" + ) + self.encode_count += 1 + encoded.append( + temporalio.api.common.v1.Payload( + metadata={**payload.metadata, "test-codec": b"true"}, + data=payload.data, + ) + ) + return encoded + + async def decode( + self, payloads: Sequence[temporalio.api.common.v1.Payload] + ) -> list[temporalio.api.common.v1.Payload]: + decoded: list[temporalio.api.common.v1.Payload] = [] + for payload in payloads: + if ( + payload.metadata.get("encoding") == b"binary/protobuf" + and payload.metadata.get("messageType") + == b"temporal.api.workflowservice.v1.SignalWithStartWorkflowExecutionRequest" + ): + raise RuntimeError( + "outer system nexus envelope should not be codec decoded" + ) + decoded.append(payload) + return decoded + + +class TracingWorkflowInterceptor(Interceptor): + def workflow_interceptor_class( + self, input: WorkflowInterceptorClassInput + ) -> type[WorkflowInboundInterceptor] | None: + return _TracingWorkflowInboundInterceptor + + +class _TracingWorkflowInboundInterceptor(WorkflowInboundInterceptor): + def init(self, outbound: WorkflowOutboundInterceptor) -> None: + super().init(_TracingWorkflowOutboundInterceptor(outbound)) + + +class _TracingWorkflowOutboundInterceptor(WorkflowOutboundInterceptor): + async def start_nexus_operation( + self, input: StartNexusOperationInput[Any, Any] + ) -> workflow.NexusOperationHandle[Any]: + interceptor_traces.append(("workflow.start_nexus_operation", input)) + return await super().start_nexus_operation(input) + + +def _assert_stored_payloads_include( + driver: InMemoryTestDriver, expected_payload_data: set[bytes] +) -> None: + stored_payload_data: set[bytes] = set() + for stored_payload_bytes in driver._storage.values(): + stored_payload = temporalio.api.common.v1.Payload() + stored_payload.ParseFromString(stored_payload_bytes) + assert stored_payload.metadata["test-codec"] == b"true" + stored_payload_data.add(stored_payload.data) + assert expected_payload_data.issubset(stored_payload_data) + + +def _assert_start_nexus_operation_interceptor_trace() -> None: + assert len(interceptor_traces) == 1 + trace_name, trace_value = interceptor_traces.pop() + assert trace_name == "workflow.start_nexus_operation" + trace_input = cast(StartNexusOperationInput[Any, Any], trace_value) + request = cast( + workflowservice_pb2.SignalWithStartWorkflowExecutionRequest, + trace_input.input, + ) + assert request.workflow_id == "system-nexus-workflow-id" + assert request.signal_name == "test-signal" + assert request.workflow_type.name == "test-workflow" + + +def _build_proto_sample(message_type: type[Message]) -> Message: + message = message_type() + _populate_proto_sample(message) + return message + + +def _populate_proto_sample(message: Message, *, path: str = "value") -> None: + seen_oneofs: set[str] = set() + for field in message.DESCRIPTOR.fields: + if field.containing_oneof is not None: + if field.containing_oneof.name in seen_oneofs: + continue + seen_oneofs.add(field.containing_oneof.name) + if field.label == FieldDescriptor.LABEL_REPEATED: + if ( + field.message_type is not None + and field.message_type.GetOptions().map_entry + ): + _populate_proto_map_entry(message, field, path=path) + elif field.cpp_type == FieldDescriptor.CPPTYPE_MESSAGE: + _populate_proto_sample( + getattr(message, field.name).add(), + path=f"{path}.{field.name}[0]", + ) + else: + getattr(message, field.name).append( + _proto_scalar_sample(field, path=f"{path}.{field.name}[0]") + ) + elif field.cpp_type == FieldDescriptor.CPPTYPE_MESSAGE: + _populate_proto_sample( + getattr(message, field.name), + path=f"{path}.{field.name}", + ) + else: + setattr( + message, + field.name, + _proto_scalar_sample(field, path=f"{path}.{field.name}"), + ) + + +def _populate_proto_map_entry( + message: Message, + field: FieldDescriptor, + *, + path: str, +) -> None: + key_field = field.message_type.fields_by_name["key"] + value_field = field.message_type.fields_by_name["value"] + key = _proto_scalar_sample(key_field, path=f"{path}.{field.name}.key") + container = getattr(message, field.name) + if value_field.cpp_type == FieldDescriptor.CPPTYPE_MESSAGE: + _populate_proto_sample( + container[key], + path=f"{path}.{field.name}[{key!r}]", + ) + else: + container[key] = _proto_scalar_sample( + value_field, + path=f"{path}.{field.name}[{key!r}]", + ) + + +def _proto_scalar_sample(field: FieldDescriptor, *, path: str) -> Any: + if field.type == FieldDescriptor.TYPE_BYTES: + return b"test" + if field.cpp_type == FieldDescriptor.CPPTYPE_STRING: + return f"{path}-value" + if field.cpp_type == FieldDescriptor.CPPTYPE_BOOL: + return True + if field.cpp_type in ( + FieldDescriptor.CPPTYPE_INT32, + FieldDescriptor.CPPTYPE_INT64, + FieldDescriptor.CPPTYPE_UINT32, + FieldDescriptor.CPPTYPE_UINT64, + ): + return 1 + if field.cpp_type in ( + FieldDescriptor.CPPTYPE_FLOAT, + FieldDescriptor.CPPTYPE_DOUBLE, + ): + return 1.5 + if field.cpp_type == FieldDescriptor.CPPTYPE_ENUM: + for enum_value in field.enum_type.values: + if enum_value.number != 0: + return enum_value.number + return field.enum_type.values[0].number + raise TypeError(f"Unhandled proto scalar sample at {path}: {field!r}") + + +@pytest.mark.parametrize( + "message_type", + [ + workflowservice_pb2.SignalWithStartWorkflowExecutionRequest, + workflowservice_pb2.SignalWithStartWorkflowExecutionResponse, + ], +) +def test_system_nexus_proto_roundtrip(message_type: type[Message]) -> None: + payload_converter = nexus_system.get_payload_converter() + proto_value = _build_proto_sample(message_type) + payload = payload_converter.to_payload(proto_value) + assert payload is not None + assert payload.metadata["encoding"] == b"binary/protobuf" + assert payload.metadata["messageType"] == message_type.DESCRIPTOR.full_name.encode() + roundtripped = payload_converter.from_payload(payload, message_type) + assert isinstance(roundtripped, message_type) + assert roundtripped == proto_value + + +async def test_external_workflow_handle_signal_with_start_workflow_uses_system_nexus( + env: WorkflowEnvironment, +): + if env.supports_time_skipping: + pytest.skip("Nexus tests don't work with the Java test server") + + codec = RejectOuterSystemNexusCodec() + interceptor_traces.clear() + driver = InMemoryTestDriver() + caller_config = env.client.config() + caller_config["data_converter"] = dataclasses.replace( + temporalio.converter.default(), + payload_codec=codec, + external_storage=ExternalStorage( + drivers=[driver], + payload_size_threshold=1, + ), + ) + caller_client = Client(**caller_config) + caller_task_queue = str(uuid.uuid4()) + handler_task_queue = str(uuid.uuid4()) + + caller_worker = Worker( + caller_client, + task_queue=caller_task_queue, + workflows=[ExternalHandleSignalWithStartWorkflowCaller], + workflow_runner=UnsandboxedWorkflowRunner(), + interceptors=[TracingWorkflowInterceptor()], + ) + + async with caller_worker: + result = await caller_client.execute_workflow( + ExternalHandleSignalWithStartWorkflowCaller.run, + args=[handler_task_queue], + id=str(uuid.uuid4()), + task_queue=caller_task_queue, + execution_timeout=timedelta(seconds=5), + ) + + assert result == "system-nexus-workflow-id" + assert codec.encode_count >= 5 + _assert_stored_payloads_include( + driver, + { + b'"workflow-input"', + b'"signal-input"', + b'"memo-value"', + b'"summary-value"', + b'"details-value"', + }, + ) + _assert_start_nexus_operation_interceptor_trace() diff --git a/tests/worker/test_visitor.py b/tests/worker/test_visitor.py index 876387393..7c06aa199 100644 --- a/tests/worker/test_visitor.py +++ b/tests/worker/test_visitor.py @@ -6,8 +6,10 @@ import pytest from google.protobuf.duration_pb2 import Duration +import temporalio.api.workflowservice.v1.request_response_pb2 as workflowservice_pb2 import temporalio.bridge.worker import temporalio.converter +import temporalio.nexus.system as nexus_system from temporalio.api.common.v1.message_pb2 import ( Payload, Payloads, @@ -15,7 +17,8 @@ SearchAttributes, ) from temporalio.api.sdk.v1.user_metadata_pb2 import UserMetadata -from temporalio.bridge._visitor import PayloadVisitor, VisitorFunctions +from temporalio.bridge._visitor import PayloadVisitor +from temporalio.bridge._visitor_functions import VisitorFunctions from temporalio.bridge.proto.workflow_activation.workflow_activation_pb2 import ( InitializeWorkflow, WorkflowActivation, @@ -25,6 +28,7 @@ ContinueAsNewWorkflowExecution, ScheduleActivity, ScheduleLocalActivity, + ScheduleNexusOperation, SignalExternalWorkflowExecution, StartChildWorkflowExecution, UpdateResponse, @@ -326,6 +330,68 @@ async def visit_payloads(self, payloads: MutableSequence[Payload]) -> None: assert tasks_cleaned_up == tasks_started +async def test_system_nexus_envelope_visit_is_bounded(): + active_visits = 0 + max_active_visits = 0 + two_visits_started = asyncio.Event() + release_visits = asyncio.Event() + + class SlowVisitor(VisitorFunctions): + async def visit_payload(self, payload: Payload) -> None: + await self._visit() + + async def visit_payloads(self, payloads: MutableSequence[Payload]) -> None: + await self._visit() + + async def visit_system_nexus_envelope(self, payload: Payload) -> None: + await self._visit() + + async def _visit(self) -> None: + nonlocal active_visits, max_active_visits + active_visits += 1 + max_active_visits = max(max_active_visits, active_visits) + if active_visits == 2: + two_visits_started.set() + try: + await release_visits.wait() + finally: + active_visits -= 1 + + payload_converter = nexus_system.get_payload_converter() + system_request = workflowservice_pb2.SignalWithStartWorkflowExecutionRequest( + input=Payloads(payloads=[Payload(data=b"workflow-input")]), + signal_input=Payloads(payloads=[Payload(data=b"signal-input")]), + ) + payload = payload_converter.to_payload(system_request) + assert payload is not None + completion = WorkflowActivationCompletion( + run_id="1", + successful=Success( + commands=[ + WorkflowCommand( + schedule_nexus_operation=ScheduleNexusOperation( + seq=1, + service="temporal.api.workflowservice.v1.WorkflowService", + operation="SignalWithStartWorkflowExecution", + input=payload, + ), + ) + ], + ), + ) + + task = asyncio.create_task( + PayloadVisitor(concurrency_limit=2).visit(SlowVisitor(), completion) + ) + await two_visits_started.wait() + await asyncio.sleep(0) + assert max_active_visits == 2 + + release_visits.set() + await task + assert max_active_visits == 2 + + async def test_bridge_encoding(): comp = WorkflowActivationCompletion( run_id="1", From 7ab0e9d8e7ae864d378ec511bac021060dc9fbd0 Mon Sep 17 00:00:00 2001 From: Spencer Judge Date: Fri, 12 Jun 2026 09:43:46 -0700 Subject: [PATCH 130/226] Gzip compression options (#1587) * Update core to branch w/ compression * Add option for gzip * Ensure we can support a not-just-int enum variant later * Proto regen * Deal with new Nexus link type * Fix merge --- scripts/gen_protos.py | 11 +- scripts/gen_protos_docker.py | 22 ++- .../nexusannotations/v1/options_pb2.py | 4 +- temporalio/bridge/Cargo.lock | 73 ++++---- temporalio/bridge/client.py | 1 + temporalio/bridge/src/client.rs | 14 +- temporalio/client/__init__.py | 2 + temporalio/client/_client.py | 7 + temporalio/client/_cloud.py | 6 + temporalio/nexus/_link_conversion.py | 176 ++++++++++++++---- temporalio/service.py | 36 ++++ tests/nexus/test_link_conversion.py | 55 ++++++ tests/test_client_exports.py | 1 + tests/test_service.py | 18 ++ 14 files changed, 339 insertions(+), 87 deletions(-) diff --git a/scripts/gen_protos.py b/scripts/gen_protos.py index 867d8fc0e..4b2ea0456 100644 --- a/scripts/gen_protos.py +++ b/scripts/gen_protos.py @@ -54,6 +54,10 @@ re.compile(r"'__module__' : 'temporal\.api\.").sub, r"'__module__' : 'temporalio.api.", ), + partial( + re.compile(r"'__module__' : 'nexusannotations\.").sub, + r"'__module__' : 'temporalio.api.dependencies.nexusannotations.", + ), ] pyi_fixes = [ @@ -201,10 +205,11 @@ def generate_protos(output_dir: Path): fix_generated_output(output_dir) # Move dependency protos deps_out_dir = api_out_dir / "dependencies" + shutil.rmtree(deps_out_dir / "protoc_gen_openapiv2", ignore_errors=True) + shutil.rmtree(deps_out_dir / "nexusannotations", ignore_errors=True) deps_out_dir.mkdir(exist_ok=True) - for dep in ["protoc_gen_openapiv2", "nexusannotations"]: - shutil.rmtree(deps_out_dir / dep, ignore_errors=True) - (output_dir / dep).replace(deps_out_dir / dep) + (output_dir / "protoc_gen_openapiv2").replace(deps_out_dir / "protoc_gen_openapiv2") + (output_dir / "nexusannotations").replace(deps_out_dir / "nexusannotations") (deps_out_dir / "__init__.py").touch() # Move protos for p in (output_dir / "temporal" / "api").iterdir(): diff --git a/scripts/gen_protos_docker.py b/scripts/gen_protos_docker.py index 819897901..500fb0cbd 100644 --- a/scripts/gen_protos_docker.py +++ b/scripts/gen_protos_docker.py @@ -17,16 +17,28 @@ ) image_id = result.stdout.strip() -subprocess.run( +docker_run_command = [ + "docker", + "run", + "--rm", +] + +getuid = getattr(os, "getuid", None) +getgid = getattr(os, "getgid", None) +if callable(getuid) and callable(getgid): + docker_run_command.extend(["--user", f"{getuid()}:{getgid()}"]) + +docker_run_command.extend( [ - "docker", - "run", - "--rm", "-v", os.path.join(os.getcwd(), "temporalio", "api") + ":/api_new", "-v", os.path.join(os.getcwd(), "temporalio", "bridge", "proto") + ":/bridge_new", image_id, - ], + ] +) + +subprocess.run( + docker_run_command, check=True, ) diff --git a/temporalio/api/dependencies/nexusannotations/v1/options_pb2.py b/temporalio/api/dependencies/nexusannotations/v1/options_pb2.py index c104009e3..deb7869f3 100644 --- a/temporalio/api/dependencies/nexusannotations/v1/options_pb2.py +++ b/temporalio/api/dependencies/nexusannotations/v1/options_pb2.py @@ -33,7 +33,7 @@ (_message.Message,), { "DESCRIPTOR": _OPERATIONOPTIONS, - "__module__": "nexusannotations.v1.options_pb2", + "__module__": "temporalio.api.dependencies.nexusannotations.v1.options_pb2", # @@protoc_insertion_point(class_scope:nexusannotations.v1.OperationOptions) }, ) @@ -44,7 +44,7 @@ (_message.Message,), { "DESCRIPTOR": _SERVICEOPTIONS, - "__module__": "nexusannotations.v1.options_pb2", + "__module__": "temporalio.api.dependencies.nexusannotations.v1.options_pb2", # @@protoc_insertion_point(class_scope:nexusannotations.v1.ServiceOptions) }, ) diff --git a/temporalio/bridge/Cargo.lock b/temporalio/bridge/Cargo.lock index ec71c46c9..616722968 100644 --- a/temporalio/bridge/Cargo.lock +++ b/temporalio/bridge/Cargo.lock @@ -142,9 +142,9 @@ checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" [[package]] name = "bitflags" -version = "2.11.1" +version = "2.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4512299f36f043ab09a583e57bceb5a5aab7a73db1805848e8fef3c9e8c78b3" +checksum = "b4388bee8683e3d04af747c73422af53102d2bd24d9eadb6cbc100baef4b43f8" [[package]] name = "bon" @@ -229,9 +229,9 @@ dependencies = [ [[package]] name = "chrono" -version = "0.4.44" +version = "0.4.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c673075a2e0e5f4a1dde27ce9dee1ea4558c7ffe648f576438a20ca1d2acc4b0" +checksum = "1aa79e62e7697b8e29b513a68abacf485adcd1fe8284a4316c5ae868e6633327" dependencies = [ "num-traits", "serde", @@ -764,9 +764,9 @@ checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" [[package]] name = "http" -version = "1.4.1" +version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8be7462df143984c4598a256ef469b251d7d7f9e271135073e78fc535414f3d0" +checksum = "6970f50e31d6fc17d3fa27329444bfa74e196cf62e95052a3f6fee181dba6425" dependencies = [ "bytes", "itoa", @@ -1117,13 +1117,12 @@ dependencies = [ [[package]] name = "js-sys" -version = "0.3.99" +version = "0.3.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "142bc4740e452c1e57ade0cbc129f139c9093e354346f0872ef985f4f5cf5f11" +checksum = "f2025f20d7a4fa7785846e7b63d10a76d3f1cee98ee5cb79ea59703f95e42162" dependencies = [ "cfg-if", "futures-util", - "once_cell", "wasm-bindgen", ] @@ -1183,9 +1182,9 @@ dependencies = [ [[package]] name = "log" -version = "0.4.30" +version = "0.4.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "616ec5685824bcc94416c6d4a7a446eea774a31efd7062c8480ba6fd06d7a6e5" +checksum = "953f07c43838f8e6f9758cab68bf5bed85465e7587ebe0b823f1bcd81978ad3a" [[package]] name = "lru" @@ -1626,9 +1625,9 @@ dependencies = [ [[package]] name = "prost" -version = "0.14.3" +version = "0.14.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2ea70524a2f82d518bce41317d0fae74151505651af45faf1ffbd6fd33f0568" +checksum = "528ac67416ff8646872a3c02cad9cc4ee5dc9f9540c9b10771855c95cb2e5ae1" dependencies = [ "bytes", "prost-derive", @@ -1636,9 +1635,9 @@ dependencies = [ [[package]] name = "prost-build" -version = "0.14.3" +version = "0.14.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "343d3bd7056eda839b03204e68deff7d1b13aba7af2b2fd16890697274262ee7" +checksum = "03da047801ff44bb6a4d407d4860c05fd70bb81714e6b2f3812603d5b145b042" dependencies = [ "heck", "itertools", @@ -1657,9 +1656,9 @@ dependencies = [ [[package]] name = "prost-derive" -version = "0.14.3" +version = "0.14.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "27c6023962132f4b30eb4c172c91ce92d933da334c59c23cddee82358ddafb0b" +checksum = "b570b25f7617e43d59005d0990ccb79e950a423952cea19671b7a876da390adf" dependencies = [ "anyhow", "itertools", @@ -1670,9 +1669,9 @@ dependencies = [ [[package]] name = "prost-types" -version = "0.14.3" +version = "0.14.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8991c4cbdb8bc5b11f0b074ffe286c30e523de90fee5ba8132f1399f23cb3dd7" +checksum = "f94967dc7688f3054c7fac87473ffae4cc4c3904800e2d9f5b857246d8963b0a" dependencies = [ "prost", ] @@ -2184,9 +2183,9 @@ dependencies = [ [[package]] name = "rustls-native-certs" -version = "0.8.3" +version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "612460d5f7bea540c490b2b6395d8e34a953e52b491accd6c86c8164c5932a63" +checksum = "dab5152771c58876a2146916e53e35057e1a4dfa2b9df0f0305b07f611fdea4d" dependencies = [ "openssl-probe", "rustls-pki-types", @@ -3126,9 +3125,9 @@ checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" [[package]] name = "unicode-segmentation" -version = "1.13.2" +version = "1.13.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9629274872b2bfaf8d66f5f15725007f635594914870f65218920345aa11aa8c" +checksum = "c6f5d3c3b1bf09027a88a6bc961fc00497d651009560b5463668dc81b0fa87a8" [[package]] name = "unicode-xid" @@ -3232,9 +3231,9 @@ dependencies = [ [[package]] name = "wasm-bindgen" -version = "0.2.122" +version = "0.2.123" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ed04576f974d2b2fba0f38c51dbc5518011e38c36bf1143164be765528fd409" +checksum = "a254a4b10c19a76f09a27640e7ffbf9bc30bf67e16a3bf28aaefa4920fe81563" dependencies = [ "cfg-if", "once_cell", @@ -3245,9 +3244,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-futures" -version = "0.4.72" +version = "0.4.73" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9473dbd2991ae90b6291c3c32c30c6187ac49aa32f9905d1cce280ec1e110b0f" +checksum = "54568702fabf5d4849ce2b90fadfa64168a097eaf4b351ce9df8b687a0086aaf" dependencies = [ "js-sys", "wasm-bindgen", @@ -3255,9 +3254,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.122" +version = "0.2.123" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "916151b09da36bd82f6615cbf3a419e2f0ba23a03c6160e8e92eb6bd4aa1dec6" +checksum = "24a40fc75b0ec6f3746ceb10d36f53a93dcd68a93b11b6445983945d79eba0dc" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -3265,9 +3264,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.122" +version = "0.2.123" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "299047362ccbfce148b67ab7e73349f77748e00c8296f9542adfad2ad82c5c5e" +checksum = "908f34bd9b9ce3d4caf07b72dfab63d61504d156856c6bd3cd87fa350cf3985b" dependencies = [ "bumpalo", "proc-macro2", @@ -3278,9 +3277,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.122" +version = "0.2.123" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a929b2c61f11ba3e9bc35b50c1f25cb38e0e892c0c231ae2b8cf78d5dad4437" +checksum = "7acbf7616c27b194bbb550bf77ed0c2c3e5b7fd1260a93082b95fb7f47959b92" dependencies = [ "unicode-ident", ] @@ -3334,9 +3333,9 @@ dependencies = [ [[package]] name = "web-sys" -version = "0.3.99" +version = "0.3.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d621441cfc37b84979402712047321980c178f299193a3589d05b99e8763436" +checksum = "6e0871acf327f283dc6da28a1696cdc64fb355ba9f935d052021fa77f35cce69" dependencies = [ "js-sys", "wasm-bindgen", @@ -3776,9 +3775,9 @@ dependencies = [ [[package]] name = "yoke" -version = "0.8.2" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "abe8c5fda708d9ca3df187cae8bfb9ceda00dd96231bed36e445a1a48e66f9ca" +checksum = "709fe23a0424b6a435d82152b1bd3fdfb0833487d5fa90d05d42762a9891fef5" dependencies = [ "stable_deref_trait", "yoke-derive", diff --git a/temporalio/bridge/client.py b/temporalio/bridge/client.py index 9941010de..c2c5bef6e 100644 --- a/temporalio/bridge/client.py +++ b/temporalio/bridge/client.py @@ -81,6 +81,7 @@ class ClientConfig: client_version: str http_connect_proxy_config: ClientHttpConnectProxyConfig | None dns_load_balancing_config: ClientDnsLoadBalancingConfig | None + grpc_compression: str @dataclass diff --git a/temporalio/bridge/src/client.rs b/temporalio/bridge/src/client.rs index 369df0795..906da5287 100644 --- a/temporalio/bridge/src/client.rs +++ b/temporalio/bridge/src/client.rs @@ -9,7 +9,7 @@ use temporalio_client::tonic::{ }; use temporalio_client::{ ClientKeepAliveOptions as CoreClientKeepAliveConfig, Connection, ConnectionOptions, - DnsLoadBalancingOptions, HttpConnectProxyOptions, RetryOptions, + DnsLoadBalancingOptions, GrpcCompression, HttpConnectProxyOptions, RetryOptions, }; use tracing::warn; use url::Url; @@ -37,6 +37,7 @@ pub struct ClientConfig { keep_alive_config: Option, http_connect_proxy_config: Option, dns_load_balancing_config: Option, + grpc_compression: String, } #[derive(FromPyObject)] @@ -266,6 +267,7 @@ impl ClientConfig { .keep_alive(self.keep_alive_config.map(Into::into)) .maybe_http_connect_proxy(self.http_connect_proxy_config.map(Into::into)) .dns_load_balancing(dns_load_balancing) + .grpc_compression(grpc_compression_from_str(&self.grpc_compression)?) .headers(ascii_headers) .binary_headers(binary_headers) .maybe_api_key(self.api_key) @@ -279,6 +281,16 @@ impl ClientConfig { } } +fn grpc_compression_from_str(value: &str) -> PyResult { + match value { + "none" => Ok(GrpcCompression::None), + "gzip" => Ok(GrpcCompression::Gzip), + _ => Err(PyValueError::new_err(format!( + "invalid grpc_compression: {value}" + ))), + } +} + impl TryFrom for temporalio_client::TlsOptions { type Error = PyErr; diff --git a/temporalio/client/__init__.py b/temporalio/client/__init__.py index 2e4609c32..030f9a542 100644 --- a/temporalio/client/__init__.py +++ b/temporalio/client/__init__.py @@ -16,6 +16,7 @@ from temporalio.service import ( ConnectConfig, DnsLoadBalancingConfig, + GrpcCompression, HttpConnectProxyConfig, KeepAliveConfig, RetryConfig, @@ -355,6 +356,7 @@ "WorkflowSerializationContext", "ConnectConfig", "DnsLoadBalancingConfig", + "GrpcCompression", "HttpConnectProxyConfig", "KeepAliveConfig", "RetryConfig", diff --git a/temporalio/client/_client.py b/temporalio/client/_client.py index 3542efc60..5efca9702 100644 --- a/temporalio/client/_client.py +++ b/temporalio/client/_client.py @@ -32,6 +32,7 @@ from temporalio.service import ( ConnectConfig, DnsLoadBalancingConfig, + GrpcCompression, HttpConnectProxyConfig, KeepAliveConfig, RetryConfig, @@ -152,6 +153,7 @@ async def connect( runtime: temporalio.runtime.Runtime | None = None, http_connect_proxy_config: HttpConnectProxyConfig | None = None, dns_load_balancing_config: DnsLoadBalancingConfig | None = None, + grpc_compression: GrpcCompression = GrpcCompression.GZIP, header_codec_behavior: HeaderCodecBehavior = HeaderCodecBehavior.NO_CODEC, ) -> Self: """Connect to a Temporal server. @@ -212,6 +214,9 @@ async def connect( be set to ``None`` to disable. Silently disabled when ``http_connect_proxy_config`` is set, since the two are mutually exclusive. + grpc_compression: Transport-level gRPC compression for the client + connection. Default is gzip. Set to + :py:attr:`GrpcCompression.NONE` to disable compression. header_codec_behavior: Encoding behavior for headers sent by the client. """ connect_config = temporalio.service.ConnectConfig( @@ -226,6 +231,7 @@ async def connect( runtime=runtime, http_connect_proxy_config=http_connect_proxy_config, dns_load_balancing_config=dns_load_balancing_config, + grpc_compression=grpc_compression, ) def make_lambda( @@ -3042,6 +3048,7 @@ class ClientConnectConfig(TypedDict, total=False): runtime: temporalio.runtime.Runtime | None http_connect_proxy_config: HttpConnectProxyConfig | None dns_load_balancing_config: DnsLoadBalancingConfig | None + grpc_compression: GrpcCompression header_codec_behavior: HeaderCodecBehavior diff --git a/temporalio/client/_cloud.py b/temporalio/client/_cloud.py index 51966666d..5394f8ca9 100644 --- a/temporalio/client/_cloud.py +++ b/temporalio/client/_cloud.py @@ -10,6 +10,7 @@ import temporalio.service from temporalio.service import ( DnsLoadBalancingConfig, + GrpcCompression, HttpConnectProxyConfig, KeepAliveConfig, RetryConfig, @@ -51,6 +52,7 @@ async def connect( runtime: temporalio.runtime.Runtime | None = None, http_connect_proxy_config: HttpConnectProxyConfig | None = None, dns_load_balancing_config: DnsLoadBalancingConfig | None = None, + grpc_compression: GrpcCompression = GrpcCompression.GZIP, ) -> CloudOperationsClient: """Connect to a Temporal Cloud Operations API. @@ -91,6 +93,9 @@ async def connect( client connection. Default is disabled. Silently disabled when ``http_connect_proxy_config`` is set, since the two are mutually exclusive. + grpc_compression: Transport-level gRPC compression for the client + connection. Default is gzip. Set to + :py:attr:`GrpcCompression.NONE` to disable compression. """ # Add version if given if version: @@ -108,6 +113,7 @@ async def connect( runtime=runtime, http_connect_proxy_config=http_connect_proxy_config, dns_load_balancing_config=dns_load_balancing_config, + grpc_compression=grpc_compression, ) return CloudOperationsClient( await temporalio.service.ServiceClient.connect(connect_config) diff --git a/temporalio/nexus/_link_conversion.py b/temporalio/nexus/_link_conversion.py index acb5a0e1d..9958fd718 100644 --- a/temporalio/nexus/_link_conversion.py +++ b/temporalio/nexus/_link_conversion.py @@ -23,13 +23,14 @@ r"^/namespaces/(?P[^/]+)/nexus-operations/(?P[^/]+)$" ) -_WORFKLOW_LINK_URL_PATH_REGEX = re.compile( - r"^/namespaces/(?P[^/]+)/workflows/(?P[^/]+)/(?P[^/]+)/history$" +_WORKFLOW_LINK_URL_PATH_REGEX = re.compile( + r"^/namespaces/(?P[^/]+)/workflows/(?P[^/]+)/(?P[^/]+)(?P/history)?$" ) class _LinkType(str, Enum): - WORKFLOW = temporalio.api.common.v1.Link.WorkflowEvent.DESCRIPTOR.full_name + WORKFLOW_EVENT = temporalio.api.common.v1.Link.WorkflowEvent.DESCRIPTOR.full_name + WORKFLOW = temporalio.api.common.v1.Link.Workflow.DESCRIPTOR.full_name NEXUS_OPERATION = temporalio.api.common.v1.Link.NexusOperation.DESCRIPTOR.full_name @@ -38,6 +39,7 @@ class _LinkType(str, Enum): LINK_REQUEST_ID_PARAM_NAME = "requestID" LINK_REFERENCE_TYPE_PARAM_NAME = "referenceType" LINK_RUN_ID_PARAM_NAME = "runID" +LINK_REASON_PARAM_NAME = "reason" EVENT_REFERENCE_TYPE = "EventReference" REQUEST_ID_REFERENCE_TYPE = "RequestIdReference" @@ -78,9 +80,12 @@ def nexus_link_to_temporal_link( return None match link_type: - case _LinkType.WORKFLOW: + case _LinkType.WORKFLOW_EVENT: return nexus_link_to_workflow_event_link(nexus_link) + case _LinkType.WORKFLOW: + return nexus_link_to_workflow_link(nexus_link) + case _LinkType.NEXUS_OPERATION: return nexus_link_to_nexus_operation_link(nexus_link) @@ -96,10 +101,13 @@ def temporal_link_to_nexus_link( case "workflow_event": return workflow_event_to_nexus_link(temporal_link.workflow_event) + case "workflow": + return workflow_to_nexus_link(temporal_link.workflow) + case "nexus_operation": return nexus_operation_to_nexus_link(temporal_link.nexus_operation) - case "activity" | "batch_job" | "workflow": + case "activity" | "batch_job": raise NotImplementedError( "only workflow_event and nexus operation links are supported" ) @@ -117,12 +125,6 @@ def workflow_event_to_nexus_link( Used when propagating links from a StartWorkflow response to a Nexus start operation response. """ - scheme = "temporal" - namespace = urllib.parse.quote(workflow_event.namespace, safe="") - workflow_id = urllib.parse.quote(workflow_event.workflow_id, safe="") - run_id = urllib.parse.quote(workflow_event.run_id, safe="") - path = f"/namespaces/{namespace}/workflows/{workflow_id}/{run_id}/history" - query_params = None match workflow_event.WhichOneof("reference"): case "event_ref": @@ -134,10 +136,40 @@ def workflow_event_to_nexus_link( case _: pass - # urllib will omit '//' from the url if netloc is empty so we add the scheme manually - url = f"{scheme}://{urllib.parse.urlunparse(('', '', path, '', query_params, ''))}" + return nexusrpc.Link( + url=_workflow_nexus_url( + workflow_event.namespace, + workflow_event.workflow_id, + workflow_event.run_id, + history=True, + query_params=query_params, + ), + type=_LinkType.WORKFLOW_EVENT.value, + ) + + +def workflow_to_nexus_link( + workflow: temporalio.api.common.v1.Link.Workflow, +) -> nexusrpc.Link: + """Convert a Workflow link into a nexusrpc link.""" + query_params = "" + if workflow.reason: + query_params = urllib.parse.urlencode( + { + LINK_REASON_PARAM_NAME: workflow.reason, + }, + ) - return nexusrpc.Link(url=url, type=_LinkType.WORKFLOW.value) + return nexusrpc.Link( + url=_workflow_nexus_url( + workflow.namespace, + workflow.workflow_id, + workflow.run_id, + history=False, + query_params=query_params, + ), + type=_LinkType.WORKFLOW.value, + ) def nexus_operation_to_nexus_link( @@ -148,7 +180,6 @@ def nexus_operation_to_nexus_link( Used when propagating links from a StartNexusOperation response to a Nexus start operation response. """ - scheme = "temporal" namespace = urllib.parse.quote(op_link.namespace, safe="") operation_id = urllib.parse.quote(op_link.operation_id, safe="") path = f"/namespaces/{namespace}/nexus-operations/{operation_id}" @@ -161,10 +192,65 @@ def nexus_operation_to_nexus_link( }, ) + return nexusrpc.Link( + url=_temporal_nexus_url(path, query_params=query_params), + type=_LinkType.NEXUS_OPERATION.value, + ) + + +def _workflow_nexus_url( + namespace: str, + workflow_id: str, + run_id: str, + *, + history: bool, + query_params: str | None = "", +) -> str: + namespace = urllib.parse.quote(namespace, safe="") + workflow_id = urllib.parse.quote(workflow_id, safe="") + run_id = urllib.parse.quote(run_id, safe="") + path = f"/namespaces/{namespace}/workflows/{workflow_id}/{run_id}" + if history: + path += "/history" + return _temporal_nexus_url(path, query_params=query_params) + + +def _temporal_nexus_url(path: str, *, query_params: str | None = "") -> str: # urllib will omit '//' from the url if netloc is empty so we add the scheme manually - url = f"{scheme}://{urllib.parse.urlunparse(('', '', path, '', query_params, ''))}" + return f"temporal://{urllib.parse.urlunparse(('', '', path, '', query_params or '', ''))}" + + +def _parse_workflow_nexus_url( + link: nexusrpc.Link, *, history: bool +) -> tuple[dict[str, str], dict[str, list[str]]] | None: + url = urllib.parse.urlparse(link.url) + match = _WORKFLOW_LINK_URL_PATH_REGEX.match(url.path) + if not match or bool(match.group("history")) != history: + expected_suffix = "/history" if history else "" + logger.warning( + f"Invalid Nexus link: {link}. Expected path to match " + f"/namespaces/{{namespace}}/workflows/{{workflow_id}}/{{run_id}}{expected_suffix}" + ) + return None - return nexusrpc.Link(url=url, type=_LinkType.NEXUS_OPERATION.value) + groups = { + name: urllib.parse.unquote(value) + for name, value in match.groupdict().items() + if name != "history" and value is not None + } + return groups, urllib.parse.parse_qs(url.query) + + +def _optional_single_query_param( + query_params: dict[str, list[str]], param_name: str +) -> str: + match query_params.get(param_name): + case [param]: + return param + case [] | None: + return "" + case _: + raise ValueError(f"Expected {param_name} to have at most 1 value") def nexus_link_to_workflow_event_link( @@ -175,16 +261,11 @@ def nexus_link_to_workflow_event_link( This is used when propagating links from a Nexus start operation request to a StartWorklow request. """ - url = urllib.parse.urlparse(link.url) - match = _WORFKLOW_LINK_URL_PATH_REGEX.match(url.path) - if not match: - logger.warning( - f"Invalid Nexus link: {link}. Expected path to match {_WORFKLOW_LINK_URL_PATH_REGEX.pattern}" - ) + parsed = _parse_workflow_nexus_url(link, history=True) + if parsed is None: return None + groups, query_params = parsed try: - query_params = urllib.parse.parse_qs(url.query) - request_id_ref = None event_ref = None match query_params.get(LINK_REFERENCE_TYPE_PARAM_NAME): @@ -203,17 +284,39 @@ def nexus_link_to_workflow_event_link( ) return None - groups = match.groupdict() workflow_event_link = temporalio.api.common.v1.Link.WorkflowEvent( - namespace=urllib.parse.unquote(groups["namespace"]), - workflow_id=urllib.parse.unquote(groups["workflow_id"]), - run_id=urllib.parse.unquote(groups["run_id"]), + namespace=groups["namespace"], + workflow_id=groups["workflow_id"], + run_id=groups["run_id"], event_ref=event_ref, request_id_ref=request_id_ref, ) return temporalio.api.common.v1.Link(workflow_event=workflow_event_link) +def nexus_link_to_workflow_link( + link: nexusrpc.Link, +) -> temporalio.api.common.v1.Link | None: + """Convert a nexus link into a Temporal Workflow link.""" + parsed = _parse_workflow_nexus_url(link, history=False) + if parsed is None: + return None + groups, query_params = parsed + try: + reason = _optional_single_query_param(query_params, LINK_REASON_PARAM_NAME) + except ValueError as err: + logger.warning(f"Invalid Nexus link: {link}. {err}") + return None + + workflow_link = temporalio.api.common.v1.Link.Workflow( + namespace=groups["namespace"], + workflow_id=groups["workflow_id"], + run_id=groups["run_id"], + reason=reason, + ) + return temporalio.api.common.v1.Link(workflow=workflow_link) + + def nexus_link_to_nexus_operation_link( nexus_link: nexusrpc.Link, ) -> temporalio.api.common.v1.Link | None: @@ -232,16 +335,11 @@ def nexus_link_to_nexus_operation_link( query_params = urllib.parse.parse_qs(url.query) - match query_params.get(LINK_RUN_ID_PARAM_NAME): - case [run_id_param]: - run_id = run_id_param - case [] | None: - run_id = "" - case _: - logger.warning( - f"Invalid Nexus link: {nexus_link}. Expected {LINK_RUN_ID_PARAM_NAME} to have at most 1 value" - ) - return None + try: + run_id = _optional_single_query_param(query_params, LINK_RUN_ID_PARAM_NAME) + except ValueError as err: + logger.warning(f"Invalid Nexus link: {nexus_link}. {err}") + return None groups = match.groupdict() nexus_op_link = temporalio.api.common.v1.Link.NexusOperation( diff --git a/temporalio/service.py b/temporalio/service.py index 1ab1e9cc4..5492abb92 100644 --- a/temporalio/service.py +++ b/temporalio/service.py @@ -158,6 +158,40 @@ def _to_bridge_config( DnsLoadBalancingConfig.default = DnsLoadBalancingConfig() +class GrpcCompression(ABC): + """Transport-level gRPC compression mode. + + This is a base type for concrete compression modes. Current modes are + available as singleton constants on this class. + """ + + NONE: ClassVar[GrpcCompression] + """Do not compress gRPC requests or advertise support for compressed responses.""" + + GZIP: ClassVar[GrpcCompression] + """Gzip-compress gRPC requests and accept gzip-compressed responses.""" + + @abstractmethod + def _to_bridge_config(self) -> str: + raise NotImplementedError + + +@dataclass(frozen=True) +class _NoGrpcCompression(GrpcCompression): + def _to_bridge_config(self) -> str: + return "none" + + +@dataclass(frozen=True) +class _GzipGrpcCompression(GrpcCompression): + def _to_bridge_config(self) -> str: + return "gzip" + + +GrpcCompression.NONE = _NoGrpcCompression() +GrpcCompression.GZIP = _GzipGrpcCompression() + + @dataclass class ConnectConfig: """Config for connecting to the server.""" @@ -173,6 +207,7 @@ class ConnectConfig: runtime: temporalio.runtime.Runtime | None = None http_connect_proxy_config: HttpConnectProxyConfig | None = None dns_load_balancing_config: DnsLoadBalancingConfig | None = None + grpc_compression: GrpcCompression = GrpcCompression.GZIP def __post_init__(self) -> None: """Set extra defaults on unset properties.""" @@ -235,6 +270,7 @@ def _to_bridge_config(self) -> temporalio.bridge.client.ClientConfig: if self.dns_load_balancing_config else None ), + grpc_compression=self.grpc_compression._to_bridge_config(), ) diff --git a/tests/nexus/test_link_conversion.py b/tests/nexus/test_link_conversion.py index 345d4f4e3..d324f16d6 100644 --- a/tests/nexus/test_link_conversion.py +++ b/tests/nexus/test_link_conversion.py @@ -209,6 +209,61 @@ def test_link_conversion_workflow_event_to_link_and_back( assert wf_event_link == actual_event +@pytest.mark.parametrize( + ["workflow_link", "expected_link"], + [ + ( + temporalio.api.common.v1.Link( + workflow=temporalio.api.common.v1.Link.Workflow( + namespace="ns", + workflow_id="wid", + run_id="rid", + reason="query", + ) + ), + nexusrpc.Link( + type=temporalio.api.common.v1.Link.Workflow.DESCRIPTOR.full_name, + url="temporal:///namespaces/ns/workflows/wid/rid?reason=query", + ), + ), + ( + temporalio.api.common.v1.Link( + workflow=temporalio.api.common.v1.Link.Workflow( + namespace="ns2", + workflow_id="wid/2", + run_id="rid2", + ) + ), + nexusrpc.Link( + type=temporalio.api.common.v1.Link.Workflow.DESCRIPTOR.full_name, + url="temporal:///namespaces/ns2/workflows/wid%2F2/rid2", + ), + ), + ], +) +def test_link_conversion_workflow_to_link_and_back( + workflow_link: temporalio.api.common.v1.Link, expected_link: nexusrpc.Link +): + actual_link = temporalio.nexus._link_conversion.workflow_to_nexus_link( + workflow_link.workflow + ) + assert expected_link == actual_link + + actual_workflow = temporalio.nexus._link_conversion.nexus_link_to_workflow_link( + actual_link + ) + assert workflow_link == actual_workflow + + assert ( + expected_link + == temporalio.nexus._link_conversion.temporal_link_to_nexus_link(workflow_link) + ) + assert ( + workflow_link + == temporalio.nexus._link_conversion.nexus_link_to_temporal_link(expected_link) + ) + + @pytest.mark.parametrize( ["operation_link", "expected_link"], [ diff --git a/tests/test_client_exports.py b/tests/test_client_exports.py index 6f4a6eb04..5317e53c4 100644 --- a/tests/test_client_exports.py +++ b/tests/test_client_exports.py @@ -51,6 +51,7 @@ "FetchWorkflowHistoryEventsInput", "GetWorkerBuildIdCompatibilityInput", "GetWorkerTaskReachabilityInput", + "GrpcCompression", "HeaderCodecBehavior", "HeartbeatAsyncActivityInput", "HttpConnectProxyConfig", diff --git a/tests/test_service.py b/tests/test_service.py index 8de337308..0cf06fae0 100644 --- a/tests/test_service.py +++ b/tests/test_service.py @@ -242,6 +242,24 @@ def test_connect_config_dns_load_balancing_disabled(): assert bridge_config.dns_load_balancing_config is None +def test_connect_config_grpc_compression_default(): + """gRPC compression defaults to gzip and is forwarded to the bridge.""" + config = temporalio.service.ConnectConfig(target_host="localhost:7233") + bridge_config = config._to_bridge_config() + assert config.grpc_compression == temporalio.service.GrpcCompression.GZIP + assert bridge_config.grpc_compression == "gzip" + + +def test_connect_config_grpc_compression_none(): + """gRPC compression can be disabled and is forwarded to the bridge.""" + config = temporalio.service.ConnectConfig( + target_host="localhost:7233", + grpc_compression=temporalio.service.GrpcCompression.NONE, + ) + bridge_config = config._to_bridge_config() + assert bridge_config.grpc_compression == "none" + + async def test_rpc_execution_not_unknown(client: Client): """ Execute each rpc method and expect a failure, but ensure the failure is not that the rpc method is unknown From 29dc19c2ea3f3a5a218b775a0883d5bdca2f9e7b Mon Sep 17 00:00:00 2001 From: elidlocke Date: Mon, 15 Jun 2026 13:08:23 -0400 Subject: [PATCH 131/226] Fix pdb / breakpoint() hang in workflow code (#1104) (#1568) When debug_mode=True (or TEMPORAL_DEBUG=1), breakpoint() inside workflow code now opens an interactive pdb prompt -- including from a sandboxed workflow run under pytest. Four pieces: - Inline dispatch on the asyncio main thread (via loop.call_soon to avoid nesting inside the dispatch task's __step() and tripping Python 3.14's task-entry validation). - breakpoint removed from the sandbox's invalid builtins so the call reaches the worker hook. Nothing else is relaxed. - A Pdb subclass that lands at the workflow's own frame, suspends sandbox checks during each REPL interaction, and overrides q/Ctrl-D to continue the workflow instead of failing it with BdbQuit. - A defensive sys.breakpointhook that raises a clear RuntimeError when breakpoint() is called from a workflow worker thread without debug_mode, replacing the previous silent hang. When debug_mode is not set, the worker's dispatch and sandbox config are unchanged. Adds a README subsection on debugging workflows and five tests at tests/worker/test_breakpoint_hang.py. Verified on Python 3.13 and 3.14. Closes #1104. --- README.md | 75 ++++++ temporalio/worker/_debugger.py | 158 +++++++++++++ temporalio/worker/_workflow.py | 137 +++++++---- .../worker/workflow_sandbox/_importer.py | 10 +- .../worker/workflow_sandbox/_restrictions.py | 16 +- tests/worker/test_breakpoint_hang.py | 223 ++++++++++++++++++ 6 files changed, 572 insertions(+), 47 deletions(-) create mode 100644 temporalio/worker/_debugger.py create mode 100644 tests/worker/test_breakpoint_hang.py diff --git a/README.md b/README.md index e00de1e84..03ed87d51 100644 --- a/README.md +++ b/README.md @@ -82,6 +82,7 @@ informal introduction to the features and their implementation. - [Customizing the Sandbox](#customizing-the-sandbox) - [Passthrough Modules](#passthrough-modules) - [Invalid Module Members](#invalid-module-members) + - [Debugging Workflows with `breakpoint()` / `pdb`](#debugging-workflows-with-breakpoint--pdb) - [Known Sandbox Issues](#known-sandbox-issues) - [Global Import/Builtins](#global-importbuiltins) - [Sandbox is not Secure](#sandbox-is-not-secure) @@ -1241,6 +1242,80 @@ my_worker = Worker(..., workflow_runner=SandboxedWorkflowRunner(restrictions=my_ See the API for more details on exact fields and their meaning. +##### Debugging Workflows with `breakpoint()` / `pdb` + +Setting `debug_mode=True` on the `Worker` (or `TEMPORAL_DEBUG=1` in the environment) routes workflow activations +onto the asyncio main thread instead of a worker thread pool. This lets `breakpoint()` and `pdb.set_trace()` +inside workflow code open an interactive REPL — without it, pdb hangs because its `input()` call would run on a +thread that does not own the controlling TTY. + +A minimal runnable example: + +```python +import asyncio +from datetime import timedelta + +from temporalio import workflow +from temporalio.client import Client +from temporalio.worker import Worker + + +@workflow.defn +class DebugMeWorkflow: + @workflow.run + async def run(self) -> str: + x = 42 + breakpoint() # interactive pdb prompt opens at this line + return f"x was {x}" + + +async def main() -> None: + client = await Client.connect("localhost:7233") + async with Worker( + client, + task_queue="debug-me", + workflows=[DebugMeWorkflow], + debug_mode=True, + ): + result = await client.execute_workflow( + DebugMeWorkflow.run, + id="debug-me-wf", + task_queue="debug-me", + task_timeout=timedelta(minutes=10), # see caveat below + ) + print(result) + + +if __name__ == "__main__": + asyncio.run(main()) +``` + +Run with `python debug_me.py`, or under pytest with `pytest -s` (the `-s` flag disables pytest's stdin +capture). At the `(Pdb)` prompt you'll land at the line where `breakpoint()` was called, with workflow +locals in scope. Try `p x`, `n`, `c`, `q`. + +**Quitting cleanly.** Typing `q` or hitting Ctrl-D continues the workflow rather than raising `BdbQuit` +(which would fail the workflow task). To genuinely abort, kill the outer process with Ctrl-C. + +Two caveats when pausing at a breakpoint inside a workflow: + +1. **Workflow task timeout.** Temporal expires a workflow task after ~10 seconds by default. If you sit at the + `(Pdb)` prompt longer than that, the server reassigns the task and your workflow replays from the start when + you continue — re-hitting the breakpoint. Pass `task_timeout=timedelta(minutes=N)` to `execute_workflow` / + `start_workflow` to give yourself debugging headroom: + + ```python + await client.execute_workflow(MyWorkflow.run, ..., task_timeout=timedelta(minutes=10)) + ``` + +2. **Deterministic replay.** Workflows are deterministic and replay from history; any wall-clock pause violates + that contract. For post-mortem debugging without these caveats, use the [Replayer](#replayer) on a recorded + history instead of live debugging. + +Calling `breakpoint()` from sandboxed workflow code without `debug_mode` raises a sandbox +`RestrictedWorkflowAccessError` with a message pointing at `debug_mode=True`, so the failure mode is loud +and the fix is obvious. + ##### Known Sandbox Issues Below are known sandbox issues. As the sandbox is developed and matures, some may be resolved. diff --git a/temporalio/worker/_debugger.py b/temporalio/worker/_debugger.py new file mode 100644 index 000000000..6f64da5c4 --- /dev/null +++ b/temporalio/worker/_debugger.py @@ -0,0 +1,158 @@ +from __future__ import annotations + +import dataclasses +import sys +from types import FrameType, TracebackType + +import temporalio.workflow +from temporalio.worker.workflow_sandbox._runner import SandboxedWorkflowRunner + +from ._workflow_instance import WorkflowRunner + +__all__ = [ + "_install_workflow_breakpoint_hook", + "_relax_sandbox_for_debugger", + "_temporal_workflow_breakpoint_hook", +] + +_ORIGINAL_BREAKPOINTHOOK = sys.breakpointhook + + +def _build_workflow_pdb_class() -> type: + """Build a Pdb subclass that suspends sandbox restrictions during the REPL. + + pdb's cmdloop touches ``readline.get_completer`` and other + sandbox-restricted internals each time it interacts with the user; we + bracket each interaction with ``_sandbox_unrestricted.value = True`` and + restore the previous value afterwards. Outside the REPL the sandbox + stays intact. + + ``pdb`` is imported lazily because it's a debug-only dependency that + pulls in ``cmd``/``bdb``/``linecache``; no reason to pay that cost at + worker import time. + """ + import pdb + + from temporalio.workflow._sandbox import _sandbox_unrestricted + + class _WorkflowPdb(pdb.Pdb): + # The `interaction` signature differs across Python versions: 3.10-3.12 + # typeshed names the second parameter `traceback: TracebackType | None`, + # while 3.13+ renames it `tb_or_exc` and widens the type to include + # `BaseException`. No single signature satisfies both stubs, so we + # suppress the override check. + def interaction( # type: ignore[override] + self, + frame: FrameType | None, + tb_or_exc: TracebackType | BaseException | None, + ) -> None: + prev = getattr(_sandbox_unrestricted, "value", False) + _sandbox_unrestricted.value = True + try: + super().interaction(frame, tb_or_exc) # type: ignore[arg-type] + finally: + _sandbox_unrestricted.value = prev + + # Override `q`/`quit`/`exit`/EOF (Ctrl-D) to behave like `continue`. + # Default pdb raises `BdbQuit`, which propagates as an uncaught + # exception out of workflow.run, fails the workflow task, and + # triggers a server retry storm during teardown. For a debug + # session the user almost always wants "stop debugging and let the + # workflow finish" — that's `continue`. Users who truly want to + # abort can Ctrl-C the outer shell. + def do_quit(self, arg: str) -> bool | None: + self.message( + "[Temporal] 'q'/Ctrl-D continues the workflow. " + "Ctrl-C the outer shell to abort." + ) + return self.do_continue(arg) + + do_q = do_exit = do_quit + do_EOF = do_quit + + return _WorkflowPdb + + +def _temporal_workflow_breakpoint_hook(*args: object, **kwargs: object) -> object: + """``sys.breakpointhook`` that handles ``breakpoint()`` inside workflows. + + Only installed when ``debug_mode`` is enabled on the Worker. From inside + a workflow activation: drops the user into a custom Pdb at the workflow's + own frame, with sandbox restrictions suspended during the REPL. From + anywhere else (test code, helpers, etc.): delegates to whatever hook was + previously installed. + """ + if not temporalio.workflow.in_workflow(): + # Not inside a workflow activation — let pytest's wrapper, ipdb, or + # whatever else is configured handle it. + return _ORIGINAL_BREAKPOINTHOOK(*args, **kwargs) + # Inside a workflow: drop the user into pdb at the caller's frame (the + # workflow's `run` method, where breakpoint() was actually written) rather + # than landing inside this hook. Bypassing the configured breakpoint hook + # also avoids pytest's pdb wrapper, which assumes a test-code context and + # touches sandbox-restricted internals during its terminal-writer setup. + # `sandbox_unrestricted()` lifts member checks for the duration of the + # REPL so pdb's own initialization (readline, etc.) isn't blocked. + # `skip` tells pdb not to stop in our hook frame or the contextlib + # plumbing — without it pdb's first step lands at the `with` teardown + # instead of the user's next workflow line. + caller_frame = sys._getframe(1) + with temporalio.workflow.unsafe.sandbox_unrestricted(): + pdb_cls = _build_workflow_pdb_class() + pdb_cls( + skip=[ + "temporalio.worker._debugger", + "temporalio.workflow._sandbox", + "contextlib", + ] + ).set_trace(caller_frame) + return None + + +def _install_workflow_breakpoint_hook() -> None: + """Set ``sys.breakpointhook`` to the workflow hook if it isn't already.""" + if sys.breakpointhook is not _temporal_workflow_breakpoint_hook: + sys.breakpointhook = _temporal_workflow_breakpoint_hook + + +def _relax_sandbox_for_debugger(workflow_runner: WorkflowRunner) -> WorkflowRunner: + """Allow ``breakpoint()`` past the sandbox so it can reach the worker hook. + + The sandbox flags ``breakpoint`` as non-deterministic by default; without + this relaxation the call raises before our breakpoint hook can run. + Once inside the hook, the hook itself enters ``sandbox_unrestricted()`` + for the duration of the debugger session, so pdb's internals (readline, + os.environ, etc.) aren't blocked either — without permanently dropping + sandbox checks for the rest of workflow execution. + """ + if not isinstance(workflow_runner, SandboxedWorkflowRunner): + return workflow_runner + + restrictions = workflow_runner.restrictions + invalid = restrictions.invalid_module_members + builtins_matcher = invalid.children.get("__builtins__") + if builtins_matcher is None: + return workflow_runner + + # `breakpoint` may sit either in `children` (as a leaf matcher with a + # custom error message) or in `use` (the legacy flat form). Strip from + # whichever shape is present. + has_child = "breakpoint" in builtins_matcher.children + has_use = "breakpoint" in builtins_matcher.use + if not (has_child or has_use): + return workflow_runner + + new_children = { + k: v for k, v in builtins_matcher.children.items() if k != "breakpoint" + } + new_use = set(builtins_matcher.use) - {"breakpoint"} + new_builtins = dataclasses.replace( + builtins_matcher, children=new_children, use=new_use + ) + new_invalid = dataclasses.replace( + invalid, children={**invalid.children, "__builtins__": new_builtins} + ) + new_restrictions = dataclasses.replace( + restrictions, invalid_module_members=new_invalid + ) + return dataclasses.replace(workflow_runner, restrictions=new_restrictions) diff --git a/temporalio/worker/_workflow.py b/temporalio/worker/_workflow.py index 9e2ac9c7b..9ca802c40 100644 --- a/temporalio/worker/_workflow.py +++ b/temporalio/worker/_workflow.py @@ -32,6 +32,10 @@ from temporalio.worker.workflow_sandbox._runner import SandboxedWorkflowRunner from . import _command_aware_visitor +from ._debugger import ( + _install_workflow_breakpoint_hook, + _relax_sandbox_for_debugger, +) from ._interceptor import ( Interceptor, WorkflowInboundInterceptor, @@ -49,6 +53,7 @@ # Set to true to log all activations and completions LOG_PROTOS = False + # Value was chosen abitrarily as a small number that allows some concurrency and prevents # large numbers of concurrent external storage operations causing resource contention. # This default limit is per workflow task activation and does not limit the total number @@ -111,6 +116,13 @@ def __init__( ), ) + # In debug mode, also lift the sandbox restriction on breakpoint() + # and install the workflow-aware breakpoint hook so pdb works in + # workflow code. Outside of debug mode neither happens. + self._debug_mode = debug_mode + if self._debug_mode: + workflow_runner = _relax_sandbox_for_debugger(workflow_runner) + _install_workflow_breakpoint_hook() self._workflow_runner = workflow_runner self._unsandboxed_workflow_runner = unsandboxed_workflow_runner @@ -145,7 +157,7 @@ def __init__( # If debug mode is enabled, disable deadlock detection # otherwise set to 2 seconds - self._deadlock_timeout_seconds = None if debug_mode else 2 + self._deadlock_timeout_seconds = None if self._debug_mode else 2 # Keep track of workflows that could not be evicted self._could_not_evict_count = 0 @@ -255,6 +267,34 @@ async def drain_poll_queue(self) -> None: except PollShutdownError: return + async def _activate_inline_for_debug( + self, + loop: asyncio.AbstractEventLoop, + workflow: _RunningWorkflow, + act: temporalio.bridge.proto.workflow_activation.WorkflowActivation, + ) -> temporalio.bridge.proto.workflow_completion.WorkflowActivationCompletion: + # Indirect through call_soon + a future so the activation runs outside + # the dispatch task's __step() context. Python 3.14 refuses to enter a + # task while another on the same thread is mid-step; suspending at the + # await below clears that state so workflow.activate can step its own + # task without collision. + future: asyncio.Future = loop.create_future() + + def run_inline() -> None: + # _run_once clears the running-loop registration on exit; restore + # the main loop so later code sees the right one. + main_loop = asyncio._get_running_loop() + try: + completion = workflow.activate(act) + future.set_result(completion) + except BaseException as e: + future.set_exception(e) + finally: + asyncio._set_running_loop(main_loop) + + loop.call_soon(run_inline) + return await future + async def _handle_activation( self, act: temporalio.bridge.proto.workflow_activation.WorkflowActivation ) -> None: @@ -344,35 +384,43 @@ async def _handle_activation( ) self._running_workflows[act.run_id] = workflow - # Run activation in separate thread so we can check if it's - # deadlocked - activate_task = asyncio.get_running_loop().run_in_executor( - self._workflow_task_executor, - workflow.activate, - act, - ) - - # Run activation task with deadlock timeout - try: - completion = await asyncio.wait_for( - activate_task, self._deadlock_timeout_seconds + if self._debug_mode: + # Inline on the main thread so pdb / breakpoint() can read + # stdin. The loop blocks during the activation — that's the + # intended single-stepping semantic. + completion = await self._activate_inline_for_debug( + asyncio.get_running_loop(), workflow, act ) - except asyncio.TimeoutError: - # Need to create the deadlock exception up here so it - # captures the trace now instead of later after we may have - # interrupted it - deadlock_exc = _DeadlockError.from_deadlocked_workflow( - workflow.instance, self._deadlock_timeout_seconds + else: + # Run activation in separate thread so we can check if it's + # deadlocked + activate_task = asyncio.get_running_loop().run_in_executor( + self._workflow_task_executor, + workflow.activate, + act, ) - # When we deadlock, we will raise an exception to fail - # the task. But before we do that, we want to try to - # interrupt the thread and put this activation task on - # the workflow so that the successive eviction can wait - # on it before trying to evict. - workflow.attempt_deadlock_interruption() - # Set the task and raise - workflow.deadlocked_activation_task = activate_task - raise deadlock_exc from None + + # Run activation task with deadlock timeout + try: + completion = await asyncio.wait_for( + activate_task, self._deadlock_timeout_seconds + ) + except asyncio.TimeoutError: + # Need to create the deadlock exception up here so it + # captures the trace now instead of later after we may have + # interrupted it + deadlock_exc = _DeadlockError.from_deadlocked_workflow( + workflow.instance, self._deadlock_timeout_seconds + ) + # When we deadlock, we will raise an exception to fail + # the task. But before we do that, we want to try to + # interrupt the thread and put this activation task on + # the workflow so that the successive eviction can wait + # on it before trying to evict. + workflow.attempt_deadlock_interruption() + # Set the task and raise + workflow.deadlocked_activation_task = activate_task + raise deadlock_exc from None except Exception as err: if isinstance(err, _DeadlockError): @@ -590,22 +638,27 @@ async def _handle_cache_eviction( handle_eviction_task: asyncio.Future | None = None while True: try: - # We only create the eviction task if we haven't already or - # it is done. This is because if it already is running and - # timed out, it's still running (and holding on to a - # thread). But if did complete running but failed with - # another error, we want to re-create the task. - if not handle_eviction_task or handle_eviction_task.done(): - handle_eviction_task = ( - asyncio.get_running_loop().run_in_executor( - self._workflow_task_executor, - workflow.activate, - act, + if self._debug_mode: + await self._activate_inline_for_debug( + asyncio.get_running_loop(), workflow, act + ) + else: + # We only create the eviction task if we haven't already or + # it is done. This is because if it already is running and + # timed out, it's still running (and holding on to a + # thread). But if did complete running but failed with + # another error, we want to re-create the task. + if not handle_eviction_task or handle_eviction_task.done(): + handle_eviction_task = ( + asyncio.get_running_loop().run_in_executor( + self._workflow_task_executor, + workflow.activate, + act, + ) ) + await asyncio.wait_for( + handle_eviction_task, self._deadlock_timeout_seconds ) - await asyncio.wait_for( - handle_eviction_task, self._deadlock_timeout_seconds - ) # Break if it succeeds break except BaseException as err: diff --git a/temporalio/worker/workflow_sandbox/_importer.py b/temporalio/worker/workflow_sandbox/_importer.py index 42f0e06b2..1ab0a1dd6 100644 --- a/temporalio/worker/workflow_sandbox/_importer.py +++ b/temporalio/worker/workflow_sandbox/_importer.py @@ -83,7 +83,15 @@ def restrict_built_in(name: str, orig: Any, *args: Any, **kwargs: Any): ) and not temporalio.workflow.unsafe.is_sandbox_unrestricted() ): - raise RestrictedWorkflowAccessError(f"__builtins__.{name}") + # If a per-builtin child matcher carries a custom + # leaf_message (e.g. directing the user to debug_mode for + # breakpoint()), surface that instead of the generic + # pass-through-modules advice. + child = builtin_matcher.children.get(name) + override_message = child.leaf_message if child else None + raise RestrictedWorkflowAccessError( + f"__builtins__.{name}", override_message=override_message + ) return orig(*args, **kwargs) for k in dir(builtins): diff --git a/temporalio/worker/workflow_sandbox/_restrictions.py b/temporalio/worker/workflow_sandbox/_restrictions.py index d53ceabd6..78b7a0363 100644 --- a/temporalio/worker/workflow_sandbox/_restrictions.py +++ b/temporalio/worker/workflow_sandbox/_restrictions.py @@ -551,11 +551,19 @@ def _public_callables(parent: Any, *, exclude: set[str] = set()) -> set[str]: SandboxRestrictions.invalid_module_members_default = SandboxMatcher( children={ "__builtins__": SandboxMatcher( - use={ - "breakpoint", - "input", - "open", + children={ + "breakpoint": SandboxMatcher( + match_self=True, + only_runtime=True, + leaf_message=( + "breakpoint() inside workflow code requires " + "debug_mode=True on the Worker (or the " + "TEMPORAL_DEBUG environment variable). Without it, " + "the call cannot reach the debugger." + ), + ), }, + use={"input", "open"}, # Too many things use open() at import time, e.g. pytest's assertion # rewriter only_runtime=True, diff --git a/tests/worker/test_breakpoint_hang.py b/tests/worker/test_breakpoint_hang.py new file mode 100644 index 000000000..29f3cb3f7 --- /dev/null +++ b/tests/worker/test_breakpoint_hang.py @@ -0,0 +1,223 @@ +from __future__ import annotations + +import pdb +import threading +import uuid +from types import FrameType +from typing import Any +from unittest.mock import patch + +import pytest + +from temporalio import workflow +from temporalio.client import Client, WorkflowFailureError +from temporalio.worker import Worker +from temporalio.worker.workflow_sandbox._restrictions import ( + RestrictedWorkflowAccessError, +) + + +@workflow.defn(sandboxed=False) +class ThreadCaptureWorkflow: + """Returns the name of the thread the workflow runs on. + + `sandboxed=False` so `threading.current_thread()` isn't intercepted — + these tests are about thread placement, not sandbox behavior. + """ + + @workflow.run + async def run(self) -> str: + return threading.current_thread().name + + +async def test_workflow_runs_on_pool_thread_without_debug_mode(client: Client): + """Production behavior unchanged: workflows run on `temporal_workflow_*`.""" + task_queue = f"tq-{uuid.uuid4()}" + async with Worker( + client, + task_queue=task_queue, + workflows=[ThreadCaptureWorkflow], + ): + thread_name = await client.execute_workflow( + ThreadCaptureWorkflow.run, + id=f"wf-{uuid.uuid4()}", + task_queue=task_queue, + ) + + main_name = threading.main_thread().name + assert thread_name != main_name, ( + f"workflow ran on the main thread ({main_name!r}) — production behavior changed" + ) + assert thread_name.startswith("temporal_workflow_"), ( + f"expected pool thread, got {thread_name!r}" + ) + + +async def test_workflow_runs_on_main_thread_in_debug_mode(client: Client): + """debug_mode=True moves workflow activation to the asyncio main thread + so pdb's input() reaches the controlling TTY.""" + task_queue = f"tq-{uuid.uuid4()}" + async with Worker( + client, + task_queue=task_queue, + workflows=[ThreadCaptureWorkflow], + debug_mode=True, + ): + thread_name = await client.execute_workflow( + ThreadCaptureWorkflow.run, + id=f"wf-{uuid.uuid4()}", + task_queue=task_queue, + ) + + main_name = threading.main_thread().name + assert thread_name == main_name, ( + f"expected workflow on main thread ({main_name!r}) in debug mode; " + f"got {thread_name!r}" + ) + + +@workflow.defn +class SandboxedBreakpointWorkflow: + """Sandboxed workflow that calls breakpoint() — verifies the fix works + without requiring users to switch to UnsandboxedWorkflowRunner.""" + + @workflow.run + async def run(self) -> str: + bird = "chicken" + breakpoint() + return f"bird was {bird}" + + +async def test_breakpoint_works_in_sandboxed_workflow_in_debug_mode(client: Client): + """breakpoint() inside a sandboxed workflow reaches the debugger when + debug_mode=True — no need to switch to UnsandboxedWorkflowRunner. + + Patches `pdb.Pdb.set_trace` with a stub so CI doesn't hang on an + interactive prompt. Reaching the stub on `MainThread` with the + workflow's `run` frame proves the full path (sandbox relaxation -> + our hook -> pdb) works through the sandbox. Also verifies workflow + locals (`bird`) are visible in the captured frame. + """ + captured: dict[str, object] = {} + + def stub_set_trace(_self: pdb.Pdb, frame: FrameType | None = None) -> None: + captured["thread"] = threading.current_thread().name + captured["frame_name"] = frame.f_code.co_name if frame else None + captured["bird"] = frame.f_locals.get("bird") if frame else None + captured["called"] = True + + task_queue = f"tq-{uuid.uuid4()}" + with patch.object(pdb.Pdb, "set_trace", stub_set_trace): + async with Worker( + client, + task_queue=task_queue, + workflows=[SandboxedBreakpointWorkflow], + debug_mode=True, + ): + result = await client.execute_workflow( + SandboxedBreakpointWorkflow.run, + id=f"wf-{uuid.uuid4()}", + task_queue=task_queue, + ) + + assert result == "bird was chicken", ( + f"workflow did not complete; breakpoint() likely raised inside the sandbox: " + f"result={result!r}" + ) + assert captured.get("called"), "pdb.Pdb.set_trace was never reached" + assert captured["thread"] == threading.main_thread().name, ( + f"breakpoint landed on {captured['thread']!r}, not the main thread" + ) + assert captured["frame_name"] == "run", ( + f"breakpoint stopped at frame {captured['frame_name']!r}, " + f"expected the workflow's `run` method" + ) + assert captured["bird"] == "chicken", ( + f"workflow local `bird` not visible in pdb frame: got {captured['bird']!r}" + ) + + +async def test_breakpoint_quit_continues_workflow_in_debug_mode(client: Client): + """Typing `q` (or hitting Ctrl-D) in a workflow pdb session should + continue the workflow rather than failing the workflow task with + BdbQuit. The hook overrides `do_quit`/`do_EOF` to call `do_continue` + instead, so a debug session ends cleanly. + + Drives pdb via `cmdqueue` so no real stdin is needed. The first + iteration of cmdloop sees `q`, which dispatches to our overridden + `do_quit` -> `do_continue`. The workflow then completes normally. + """ + captured: dict[str, object] = {} + + class _AutoQuitPdb(pdb.Pdb): + """Pdb subclass that pre-queues `q` and captures frame state on + entry to `interaction`.""" + + def __init__(self, *args: Any, **kwargs: Any) -> None: + super().__init__(*args, **kwargs) + self.cmdqueue = ["q"] + + def interaction( # type: ignore[override] + self, frame: FrameType | None, traceback: Any + ) -> Any: + if frame is not None: + captured["frame_name"] = frame.f_code.co_name + captured["bird"] = frame.f_locals.get("bird") + return super().interaction(frame, traceback) + + task_queue = f"tq-{uuid.uuid4()}" + with patch("pdb.Pdb", _AutoQuitPdb): + async with Worker( + client, + task_queue=task_queue, + workflows=[SandboxedBreakpointWorkflow], + debug_mode=True, + ): + result = await client.execute_workflow( + SandboxedBreakpointWorkflow.run, + id=f"wf-{uuid.uuid4()}", + task_queue=task_queue, + ) + + assert result == "bird was chicken", ( + f"workflow did not complete after `q`; `BdbQuit` likely propagated: " + f"result={result!r}" + ) + assert captured.get("frame_name") == "run", ( + f"pdb didn't stop in workflow.run frame: got {captured.get('frame_name')!r}" + ) + assert captured.get("bird") == "chicken", ( + f"workflow local `bird` not visible at pdb breakpoint: " + f"got {captured.get('bird')!r}" + ) + + +async def test_sandboxed_breakpoint_points_at_debug_mode(client: Client): + """Without `debug_mode`, calling `breakpoint()` in a sandboxed workflow + should raise the sandbox's restricted-access error with a message that + directs the user at `debug_mode=True` (rather than the generic + pass-through advice that doesn't apply here). + + `workflow_failure_exception_types=[RestrictedWorkflowAccessError]` makes + the sandbox error terminal for the workflow execution instead of + triggering Temporal's normal task-retry loop, so the test gets the + failure surfaced promptly without waiting on a timeout. + """ + task_queue = f"tq-{uuid.uuid4()}" + with pytest.raises(WorkflowFailureError) as exc_info: + async with Worker( + client, + task_queue=task_queue, + workflows=[SandboxedBreakpointWorkflow], + workflow_failure_exception_types=[RestrictedWorkflowAccessError], + ): + await client.execute_workflow( + SandboxedBreakpointWorkflow.run, + id=f"wf-{uuid.uuid4()}", + task_queue=task_queue, + ) + + cause_msg = str(exc_info.value.cause) + assert "debug_mode=True" in cause_msg, ( + f"sandbox error didn't point at debug_mode: {cause_msg!r}" + ) From 6886d34070c3fc78d8e55d90d81097c4158fabe3 Mon Sep 17 00:00:00 2001 From: tconley1428 Date: Mon, 15 Jun 2026 12:30:40 -0700 Subject: [PATCH 132/226] Upgrade PyO3 to 0.29 (#1599) --- temporalio/bridge/Cargo.lock | 60 ++++++++---------------------- temporalio/bridge/Cargo.toml | 6 +-- temporalio/bridge/src/client.rs | 2 +- temporalio/bridge/src/envconfig.rs | 18 ++++----- temporalio/bridge/src/metric.rs | 6 +-- temporalio/bridge/src/runtime.rs | 22 ++++++----- temporalio/bridge/src/worker.rs | 38 +++++++++---------- 7 files changed, 64 insertions(+), 88 deletions(-) diff --git a/temporalio/bridge/Cargo.lock b/temporalio/bridge/Cargo.lock index 616722968..8b37057f4 100644 --- a/temporalio/bridge/Cargo.lock +++ b/temporalio/bridge/Cargo.lock @@ -1008,15 +1008,6 @@ dependencies = [ "serde_core", ] -[[package]] -name = "indoc" -version = "2.0.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79cf5c93f93228cf8efb3ba362535fb11199ac548a09ce117c9b1adc3030d706" -dependencies = [ - "rustversion", -] - [[package]] name = "instant" version = "0.1.13" @@ -1222,15 +1213,6 @@ version = "2.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6b947ae49db0d222b1dbc6b113ce7248a3fc3a6ca21b696717bfc000ba4484d8" -[[package]] -name = "memoffset" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "488016bfae457b036d996092f6cb448677611ce4449e970ceaf42695203f218a" -dependencies = [ - "autocfg", -] - [[package]] name = "mime" version = "0.3.17" @@ -1744,30 +1726,28 @@ dependencies = [ [[package]] name = "pyo3" -version = "0.25.1" +version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8970a78afe0628a3e3430376fc5fd76b6b45c4d43360ffd6cdd40bdde72b682a" +checksum = "cd274650b21d4bfc26a0a47587962c1edb425f69287324355cd040c3ea66071c" dependencies = [ "anyhow", - "indoc", "inventory", "libc", - "memoffset", "once_cell", "portable-atomic", "pyo3-build-config", "pyo3-ffi", "pyo3-macros", - "unindent", ] [[package]] name = "pyo3-async-runtimes" -version = "0.25.0" +version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d73cc6b1b7d8b3cef02101d37390dbdfe7e450dfea14921cae80a9534ba59ef2" +checksum = "b3ef68daa7316a3fac65e5e18b2203f010346de1c1c53456811a2624673ab046" dependencies = [ - "futures", + "futures-channel", + "futures-util", "once_cell", "pin-project-lite", "pyo3", @@ -1776,19 +1756,18 @@ dependencies = [ [[package]] name = "pyo3-build-config" -version = "0.25.1" +version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "458eb0c55e7ece017adeba38f2248ff3ac615e53660d7c71a238d7d2a01c7598" +checksum = "c5e2a7d2f0d013342f295c048ad19237add5154a55b1c5a254c0ec93d4109078" dependencies = [ - "once_cell", "target-lexicon", ] [[package]] name = "pyo3-ffi" -version = "0.25.1" +version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7114fe5457c61b276ab77c5055f206295b812608083644a5c5b2640c3102565c" +checksum = "ca85c467da1bbc8d866eea5deff9cf29ea5f7785054a17da36e65bda9c05845b" dependencies = [ "libc", "pyo3-build-config", @@ -1796,9 +1775,9 @@ dependencies = [ [[package]] name = "pyo3-macros" -version = "0.25.1" +version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8725c0a622b374d6cb051d11a0983786448f7785336139c3c94f5aa6bef7e50" +checksum = "9ac53762fd065daa3194dd09337a38bd793a188100fd1a9304c4ab312d901771" dependencies = [ "proc-macro2", "pyo3-macros-backend", @@ -1808,22 +1787,21 @@ dependencies = [ [[package]] name = "pyo3-macros-backend" -version = "0.25.1" +version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4109984c22491085343c05b0dbc54ddc405c3cf7b4374fc533f5c3313a572ccc" +checksum = "4ca3a1557399783172dc5bf39cfca835157732532cba56b71d2292161e53b362" dependencies = [ "heck", "proc-macro2", - "pyo3-build-config", "quote", "syn", ] [[package]] name = "pythonize" -version = "0.25.0" +version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "597907139a488b22573158793aa7539df36ae863eba300c75f3a0d65fc475e27" +checksum = "6ec376e1216e0c929a74964ce2020012a1a39f32d80e78aa688721219ea7fb89" dependencies = [ "pyo3", "serde", @@ -3135,12 +3113,6 @@ version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" -[[package]] -name = "unindent" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7264e107f553ccae879d21fbea1d6724ac785e8c3bfc762137959b5802826ef3" - [[package]] name = "untrusted" version = "0.9.0" diff --git a/temporalio/bridge/Cargo.toml b/temporalio/bridge/Cargo.toml index ade771d73..1e21e136d 100644 --- a/temporalio/bridge/Cargo.toml +++ b/temporalio/bridge/Cargo.toml @@ -20,14 +20,14 @@ anyhow = "1.0" async-trait = "0.1" futures = "0.3" prost = "0.14" -pyo3 = { version = "0.25", features = [ +pyo3 = { version = "0.29", features = [ "extension-module", "abi3-py310", "anyhow", "multiple-pymethods", ] } -pyo3-async-runtimes = { version = "0.25", features = ["tokio-runtime"] } -pythonize = "0.25" +pyo3-async-runtimes = { version = "0.29", features = ["tokio-runtime"] } +pythonize = "0.29" temporalio-client = { version = "0.4", path = "./sdk-core/crates/client" } temporalio-common = { version = "0.4", path = "./sdk-core/crates/common", features = [ "envconfig", "otel" diff --git a/temporalio/bridge/src/client.rs b/temporalio/bridge/src/client.rs index 906da5287..85dedef94 100644 --- a/temporalio/bridge/src/client.rs +++ b/temporalio/bridge/src/client.rs @@ -197,7 +197,7 @@ where match res { Ok(resp) => Ok(resp.get_ref().encode_to_vec()), Err(err) => { - Python::with_gil(move |py| { + Python::attach(move |py| { // Create tuple of "status", "message", and optional "details" let code = err.code() as u32; let message = err.message().to_owned(); diff --git a/temporalio/bridge/src/envconfig.rs b/temporalio/bridge/src/envconfig.rs index fb0da290c..40ef9b638 100644 --- a/temporalio/bridge/src/envconfig.rs +++ b/temporalio/bridge/src/envconfig.rs @@ -14,7 +14,7 @@ use temporalio_common::envconfig::{ pyo3::create_exception!(temporal_sdk_bridge, ConfigError, PyRuntimeError); -fn data_source_to_dict(py: Python, ds: &DataSource) -> PyResult { +fn data_source_to_dict(py: Python, ds: &DataSource) -> PyResult> { let dict = PyDict::new(py); match ds { DataSource::Path(p) => dict.set_item("path", p)?, @@ -23,7 +23,7 @@ fn data_source_to_dict(py: Python, ds: &DataSource) -> PyResult { Ok(dict.into()) } -fn tls_to_dict(py: Python, tls: &CoreClientConfigTLS) -> PyResult { +fn tls_to_dict(py: Python, tls: &CoreClientConfigTLS) -> PyResult> { let dict = PyDict::new(py); dict.set_item("disabled", tls.disabled)?; if let Some(v) = &tls.client_cert { @@ -42,7 +42,7 @@ fn tls_to_dict(py: Python, tls: &CoreClientConfigTLS) -> PyResult { Ok(dict.into()) } -fn codec_to_dict(py: Python, codec: &ClientConfigCodec) -> PyResult { +fn codec_to_dict(py: Python, codec: &ClientConfigCodec) -> PyResult> { let dict = PyDict::new(py); if let Some(v) = &codec.endpoint { dict.set_item("endpoint", v)?; @@ -53,7 +53,7 @@ fn codec_to_dict(py: Python, codec: &ClientConfigCodec) -> PyResult { Ok(dict.into()) } -fn profile_to_dict(py: Python, profile: &CoreClientConfigProfile) -> PyResult { +fn profile_to_dict(py: Python, profile: &CoreClientConfigProfile) -> PyResult> { let dict = PyDict::new(py); if let Some(v) = &profile.address { dict.set_item("address", v)?; @@ -76,7 +76,7 @@ fn profile_to_dict(py: Python, profile: &CoreClientConfigProfile) -> PyResult PyResult { +fn core_config_to_dict(py: Python, core_config: &CoreClientConfig) -> PyResult> { let profiles_dict = PyDict::new(py); for (name, profile) in &core_config.profiles { let connect_dict = profile_to_dict(py, profile)?; @@ -90,7 +90,7 @@ fn load_client_config_inner( config_source: Option, config_file_strict: bool, env_vars: Option>, -) -> PyResult { +) -> PyResult> { let options = LoadClientConfigOptions { config_source, config_file_strict, @@ -109,7 +109,7 @@ fn load_client_connect_config_inner( disable_env: bool, config_file_strict: bool, env_vars: Option>, -) -> PyResult { +) -> PyResult> { let options = LoadClientConfigProfileOptions { config_source, config_file_profile: profile, @@ -132,7 +132,7 @@ pub fn load_client_config( data: Option>, config_file_strict: bool, env_vars: Option>, -) -> PyResult { +) -> PyResult> { let config_source = match (path, data) { (Some(p), None) => Some(DataSource::Path(p)), (None, Some(d)) => Some(DataSource::Data(d)), @@ -158,7 +158,7 @@ pub fn load_client_connect_config( disable_env: bool, config_file_strict: bool, env_vars: Option>, -) -> PyResult { +) -> PyResult> { let config_source = match (path, data) { (Some(p), None) => Some(DataSource::Path(p)), (None, Some(d)) => Some(DataSource::Data(d)), diff --git a/temporalio/bridge/src/metric.rs b/temporalio/bridge/src/metric.rs index 445adfea9..276933f6d 100644 --- a/temporalio/bridge/src/metric.rs +++ b/temporalio/bridge/src/metric.rs @@ -19,7 +19,7 @@ pub struct MetricMeterRef { default_attributes: MetricAttributesRef, } -#[pyclass] +#[pyclass(from_py_object)] #[derive(Clone)] pub struct MetricAttributesRef { attrs: metrics::MetricAttributes, @@ -216,7 +216,7 @@ impl MetricAttributesRef { &self, py: Python, meter: &MetricMeterRef, - new_attrs: HashMap, + new_attrs: HashMap>, ) -> PyResult { let attrs = meter.meter.extend_attributes( self.attrs.clone(), @@ -234,7 +234,7 @@ impl MetricAttributesRef { fn metric_key_value_from_py( py: Python, k: String, - obj: PyObject, + obj: Py, ) -> PyResult { let val = if let Ok(v) = obj.extract::(py) { metrics::MetricValue::String(v) diff --git a/temporalio/bridge/src/runtime.rs b/temporalio/bridge/src/runtime.rs index 94cf5a025..26fd3482b 100644 --- a/temporalio/bridge/src/runtime.rs +++ b/temporalio/bridge/src/runtime.rs @@ -47,7 +47,7 @@ pub struct TelemetryConfig { #[derive(FromPyObject)] pub struct LoggingConfig { filter: String, - forward_to: Option, + forward_to: Option>, } #[pyclass] @@ -105,7 +105,7 @@ pub fn init_runtime(options: RuntimeOptions) -> PyResult { let telemetry_build = TelemetryOptions::builder(); // Build logging config, capturing forwarding info to start later - let mut log_forwarding: Option<(Receiver, PyObject)> = None; + let mut log_forwarding: Option<(Receiver, Py)> = None; let maybe_logging = if let Some(logging_conf) = logging { Some(if let Some(forward_to) = logging_conf.forward_to { // Note, actual log forwarding is started later @@ -177,7 +177,7 @@ pub fn init_runtime(options: RuntimeOptions) -> PyResult { .collect::>(); // We silently swallow errors here because logging them could // cause a bad loop and we don't want to assume console presence - let _ = Python::with_gil(|py| callback.call1(py, (entries,))); + let _ = Python::attach(|py| callback.call1(py, (entries,))); } })) }); @@ -204,7 +204,7 @@ impl Runtime { pub fn future_into_py<'a, F, T>(&self, py: Python<'a>, fut: F) -> PyResult> where F: Future> + Send + 'static, - T: for<'py> IntoPyObject<'py>, + T: for<'py> IntoPyObject<'py> + Send + 'static, { let _guard = self.core.tokio_handle().enter(); pyo3_async_runtimes::generic::future_into_py::(py, fut) @@ -310,7 +310,7 @@ impl BufferedLogEntry { } #[getter] - fn fields(&self, py: Python<'_>) -> PyResult> { + fn fields(&self, py: Python<'_>) -> PyResult>> { self.core_log .fields .iter() @@ -413,6 +413,13 @@ impl pyo3_async_runtimes::generic::Runtime for TokioRuntime { { tokio::runtime::Handle::current().spawn(fut) } + + fn spawn_blocking(f: F) -> Self::JoinHandle + where + F: FnOnce() + Send + 'static, + { + tokio::runtime::Handle::current().spawn_blocking(f) + } } impl pyo3_async_runtimes::generic::ContextExt for TokioRuntime { @@ -431,10 +438,7 @@ impl pyo3_async_runtimes::generic::ContextExt for TokioRuntime { fn get_task_locals() -> Option { TASK_LOCALS - .try_with(|c| { - c.get() - .map(|locals| Python::with_gil(|py| locals.clone_ref(py))) - }) + .try_with(|c| c.get().cloned()) .unwrap_or_default() } } diff --git a/temporalio/bridge/src/worker.rs b/temporalio/bridge/src/worker.rs index d37226614..e530e89bb 100644 --- a/temporalio/bridge/src/worker.rs +++ b/temporalio/bridge/src/worker.rs @@ -231,9 +231,9 @@ impl SlotReserveCtx { #[pyclass] pub struct SlotMarkUsedCtx { #[pyo3(get)] - slot_info: PyObject, + slot_info: Py, #[pyo3(get)] - permit: PyObject, + permit: Py, } // NOTE: this is dumb because we already have the generated proto code, we just can't use @@ -268,9 +268,9 @@ pub struct NexusSlotInfo { #[pyclass] pub struct SlotReleaseCtx { #[pyo3(get)] - slot_info: Option, + slot_info: Option>, #[pyo3(get)] - permit: PyObject, + permit: Py, } fn slot_info_to_py_obj<'py>(py: Python<'py>, info: SlotInfo) -> PyResult> { @@ -300,14 +300,14 @@ fn slot_info_to_py_obj<'py>(py: Python<'py>, info: SlotInfo) -> PyResult, + inner: Arc>, } struct CustomSlotSupplierOfType { - inner: Arc, + inner: Arc>, event_loop_task_locals: Arc>, _phantom: PhantomData, } @@ -315,7 +315,7 @@ struct CustomSlotSupplierOfType { #[pymethods] impl CustomSlotSupplier { #[new] - fn new(inner: PyObject) -> Self { + fn new(inner: Py) -> Self { CustomSlotSupplier { inner: Arc::new(inner), } @@ -329,23 +329,23 @@ impl CustomSlotSupplier { #[pyclass] struct CreatedTaskForSlotCallback { - stored_task: Arc>, + stored_task: Arc>>, } #[pymethods] impl CreatedTaskForSlotCallback { - fn __call__(&self, task: PyObject) -> PyResult<()> { + fn __call__(&self, task: Py) -> PyResult<()> { self.stored_task.set(task).expect("must only be set once"); Ok(()) } } struct TaskCanceller { - stored_task: Arc>, + stored_task: Arc>>, } impl TaskCanceller { - fn new(stored_task: Arc>) -> Self { + fn new(stored_task: Arc>>) -> Self { TaskCanceller { stored_task } } } @@ -353,7 +353,7 @@ impl TaskCanceller { impl Drop for TaskCanceller { fn drop(&mut self) { if let Some(task) = self.stored_task.get() { - Python::with_gil(|py| { + Python::attach(|py| { task.call_method0(py, "cancel") .expect("Failed to cancel task"); }); @@ -369,7 +369,7 @@ impl SlotSupplierTrait for CustomSlotSupplierOfType< loop { let stored_task = Arc::new(OnceLock::new()); let _task_canceller = TaskCanceller::new(stored_task.clone()); - let pypermit = match Python::with_gil(|py| { + let pypermit = match Python::attach(|py| { let py_obj = self.inner.bind(py); let called = py_obj.call_method1( "reserve_slot", @@ -404,7 +404,7 @@ impl SlotSupplierTrait for CustomSlotSupplierOfType< } fn try_reserve_slot(&self, ctx: &dyn SlotReservationContext) -> Option { - Python::with_gil(|py| { + Python::attach(|py| { let py_obj = self.inner.bind(py); let pa = py_obj.call_method1( "try_reserve_slot", @@ -425,10 +425,10 @@ impl SlotSupplierTrait for CustomSlotSupplierOfType< } fn mark_slot_used(&self, ctx: &dyn SlotMarkUsedContext) { - if let Err(e) = Python::with_gil(|py| { + if let Err(e) = Python::attach(|py| { let permit = ctx .permit() - .user_data::() + .user_data::>() .map(|o| o.clone_ref(py)) .unwrap_or_else(|| py.None()); let py_obj = self.inner.bind(py); @@ -446,10 +446,10 @@ impl SlotSupplierTrait for CustomSlotSupplierOfType< } fn release_slot(&self, ctx: &dyn SlotReleaseContext) { - if let Err(e) = Python::with_gil(|py| { + if let Err(e) = Python::attach(|py| { let permit = ctx .permit() - .user_data::() + .user_data::>() .map(|o| o.clone_ref(py)) .unwrap_or_else(|| py.None()); let py_obj = self.inner.bind(py); From 3c211b332eafe2cad136cc9bd4d69ea7e16562bf Mon Sep 17 00:00:00 2001 From: xumaple <45406854+xumaple@users.noreply.github.com> Date: Tue, 16 Jun 2026 15:04:15 -0400 Subject: [PATCH 133/226] Translate terminal sandbox errors to non-retryable ApplicationError (#1595) * Translate terminal sandbox errors to non-retryable ApplicationError Sandbox integration activities in the OpenAI Agents contrib passed every exception from the agents.sandbox library through as-is, so Temporal treated them all as retryable. A terminal failure (e.g. the sandbox was stopped externally) would retry forever and wedge the workflow. openai-agents 0.17.5 exposes SandboxError.retryable. Wrap each sandbox activity so a SandboxError the library has classified as terminal (retryable is False) is re-raised as a non-retryable ApplicationError; transient and unclassified errors (retryable True or None) still propagate and retry by default. Fixes #1548 Co-Authored-By: Claude Opus 4.8 (1M context) * address copilot's PR comment * Exempt openai-agents from the uv dependency cooldown openai-agents 0.17.5 is required for SandboxError.retryable but was published inside the repo's 2-week exclude-newer cooldown, so uv resolved to "only openai-agents<=0.17.4 available" and every CI job failed at dependency install. Exempt openai-agents via exclude-newer-package and regenerate the lock; the >=0.17.5 floor bounds the exemption and the cooldown still applies to all other dependencies. Co-Authored-By: Claude Opus 4.8 (1M context) --------- Co-authored-by: Claude Opus 4.8 (1M context) --- pyproject.toml | 3 +- .../sandbox/_sandbox_client_provider.py | 202 +++++++++++------- .../openai_agents/test_openai_sandbox.py | 149 +++++++++++++ uv.lock | 13 +- 4 files changed, 280 insertions(+), 87 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 99b86cfcb..943e56018 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -28,7 +28,7 @@ classifiers = [ grpc = ["grpcio>=1.48.2,<2"] opentelemetry = ["opentelemetry-api>=1.11.1,<2", "opentelemetry-sdk>=1.11.1,<2"] pydantic = ["pydantic>=2.0.0,<3"] -openai-agents = ["openai-agents>=0.17.1", "mcp>=1.9.4, <2"] +openai-agents = ["openai-agents>=0.17.5", "mcp>=1.9.4, <2"] google-adk = ["google-adk>=1.27.0,<2"] langgraph = ["langgraph>=1.1.0"] langsmith = ["langsmith>=0.7.34,<0.9"] @@ -260,3 +260,4 @@ exclude = ["temporalio/bridge/target/**/*"] # Prevent uv commands from building the package by default package = false exclude-newer = "2 weeks" +exclude-newer-package = { openai-agents = false } diff --git a/temporalio/contrib/openai_agents/sandbox/_sandbox_client_provider.py b/temporalio/contrib/openai_agents/sandbox/_sandbox_client_provider.py index 9e4d67644..4aa6fd38e 100644 --- a/temporalio/contrib/openai_agents/sandbox/_sandbox_client_provider.py +++ b/temporalio/contrib/openai_agents/sandbox/_sandbox_client_provider.py @@ -3,10 +3,12 @@ from __future__ import annotations import io -from collections.abc import Callable, Sequence +from collections.abc import Callable, Iterator, Sequence +from contextlib import contextmanager from pathlib import Path from typing import Any +from agents.sandbox.errors import SandboxError from agents.sandbox.session.sandbox_client import BaseSandboxClient from agents.sandbox.session.sandbox_session import SandboxSession @@ -34,6 +36,22 @@ from temporalio.contrib.openai_agents.sandbox._temporal_activity_models import ( ExecResult as ExecResultModel, ) +from temporalio.exceptions import ApplicationError + + +@contextmanager +def _translate_sandbox_errors() -> Iterator[None]: + # Temporal retries every activity exception by default, so only a SandboxError + # the library has classified as terminal (retryable is False) is turned into a + # non-retryable ApplicationError. + try: + yield + except SandboxError as e: + if e.retryable is False: + raise ApplicationError( + str(e), type=str(e.error_code), non_retryable=True + ) from e + raise class SandboxClientProvider: @@ -99,132 +117,154 @@ def _get_activities(self) -> Sequence[Callable[..., Any]]: @activity.defn(name=f"{prefix}-sandbox_client_create") async def create_session(args: CreateSessionArgs) -> SessionResult: - session = await self._client.create( - snapshot=args.snapshot_spec, - manifest=args.manifest, - options=args.client_options, - ) - self._sessions[str(session.state.session_id)] = session - return SessionResult( - state=session.state, supports_pty=session.supports_pty() - ) + with _translate_sandbox_errors(): + session = await self._client.create( + snapshot=args.snapshot_spec, + manifest=args.manifest, + options=args.client_options, + ) + self._sessions[str(session.state.session_id)] = session + return SessionResult( + state=session.state, supports_pty=session.supports_pty() + ) @activity.defn(name=f"{prefix}-sandbox_client_resume") async def resume_session(args: ResumeSessionArgs) -> SessionResult: - session = await self._client.resume(args.state) - self._sessions[str(session.state.session_id)] = session - return SessionResult( - state=session.state, supports_pty=session.supports_pty() - ) + with _translate_sandbox_errors(): + session = await self._client.resume(args.state) + self._sessions[str(session.state.session_id)] = session + return SessionResult( + state=session.state, supports_pty=session.supports_pty() + ) @activity.defn(name=f"{prefix}-sandbox_client_delete") async def delete_session(args: StopArgs) -> None: - session = await self._session(args) - await self._client.delete(session) - return None + with _translate_sandbox_errors(): + session = await self._session(args) + await self._client.delete(session) + return None # -- Session-level operations (I/O and lifecycle) -- @activity.defn(name=f"{prefix}-sandbox_session_exec") async def exec_(args: ExecArgs) -> ExecResultModel: - session = await self._session(args) - result = await session.exec( - *args.command, - timeout=args.timeout, - shell=args.shell, - user=args.user, - ) - return ExecResultModel( - stdout=result.stdout, - stderr=result.stderr, - exit_code=result.exit_code, - ) + with _translate_sandbox_errors(): + session = await self._session(args) + result = await session.exec( + *args.command, + timeout=args.timeout, + shell=args.shell, + user=args.user, + ) + return ExecResultModel( + stdout=result.stdout, + stderr=result.stderr, + exit_code=result.exit_code, + ) @activity.defn(name=f"{prefix}-sandbox_session_read") async def read(args: ReadArgs) -> ReadResult: - session = await self._session(args) - handle = await session.read(Path(args.path)) - return ReadResult(data=handle.read()) + with _translate_sandbox_errors(): + session = await self._session(args) + handle = await session.read(Path(args.path)) + return ReadResult(data=handle.read()) @activity.defn(name=f"{prefix}-sandbox_session_write") async def write(args: WriteArgs) -> None: - session = await self._session(args) - await session.write(Path(args.path), io.BytesIO(args.data)) - return None + with _translate_sandbox_errors(): + session = await self._session(args) + await session.write(Path(args.path), io.BytesIO(args.data)) + return None @activity.defn(name=f"{prefix}-sandbox_session_running") async def running(args: RunningArgs) -> RunningResult: - session = await self._session(args) - return RunningResult(is_running=await session.running()) + with _translate_sandbox_errors(): + session = await self._session(args) + return RunningResult(is_running=await session.running()) @activity.defn(name=f"{prefix}-sandbox_session_persist_workspace") async def persist_workspace( args: PersistWorkspaceArgs, ) -> PersistWorkspaceResult: - session = await self._session(args) - stream = await session.persist_workspace() - return PersistWorkspaceResult(data=stream.read()) + with _translate_sandbox_errors(): + session = await self._session(args) + stream = await session.persist_workspace() + return PersistWorkspaceResult(data=stream.read()) @activity.defn(name=f"{prefix}-sandbox_session_hydrate_workspace") async def hydrate_workspace(args: HydrateWorkspaceArgs) -> None: - session = await self._session(args) - await session.hydrate_workspace(io.BytesIO(args.data)) - return None + with _translate_sandbox_errors(): + session = await self._session(args) + await session.hydrate_workspace(io.BytesIO(args.data)) + return None @activity.defn(name=f"{prefix}-sandbox_session_pty_exec_start") async def pty_exec_start(args: PtyExecStartArgs) -> PtyExecUpdateResult: - session = await self._session(args) - update = await session.pty_exec_start( - *args.command, - timeout=args.timeout, - shell=args.shell, - user=args.user, - tty=args.tty, - yield_time_s=args.yield_time_s, - max_output_tokens=args.max_output_tokens, - ) - return PtyExecUpdateResult( - process_id=update.process_id, - output=update.output, - exit_code=update.exit_code, - original_token_count=update.original_token_count, - ) + with _translate_sandbox_errors(): + session = await self._session(args) + update = await session.pty_exec_start( + *args.command, + timeout=args.timeout, + shell=args.shell, + user=args.user, + tty=args.tty, + yield_time_s=args.yield_time_s, + max_output_tokens=args.max_output_tokens, + ) + return PtyExecUpdateResult( + process_id=update.process_id, + output=update.output, + exit_code=update.exit_code, + original_token_count=update.original_token_count, + ) @activity.defn(name=f"{prefix}-sandbox_session_pty_write_stdin") async def pty_write_stdin(args: PtyWriteStdinArgs) -> PtyExecUpdateResult: - session = await self._session(args) - update = await session.pty_write_stdin( - session_id=args.session_id, - chars=args.chars, - yield_time_s=args.yield_time_s, - max_output_tokens=args.max_output_tokens, - ) - return PtyExecUpdateResult( - process_id=update.process_id, - output=update.output, - exit_code=update.exit_code, - original_token_count=update.original_token_count, - ) + with _translate_sandbox_errors(): + session = await self._session(args) + update = await session.pty_write_stdin( + session_id=args.session_id, + chars=args.chars, + yield_time_s=args.yield_time_s, + max_output_tokens=args.max_output_tokens, + ) + return PtyExecUpdateResult( + process_id=update.process_id, + output=update.output, + exit_code=update.exit_code, + original_token_count=update.original_token_count, + ) @activity.defn(name=f"{prefix}-sandbox_session_start") async def start(args: StartArgs) -> None: - session = await self._session(args) - await session.start() - return None + with _translate_sandbox_errors(): + session = await self._session(args) + await session.start() + return None @activity.defn(name=f"{prefix}-sandbox_session_stop") async def session_stop(args: StopArgs) -> None: - session = await self._session(args) - await session.stop() - return None + with _translate_sandbox_errors(): + session = await self._session(args) + await session.stop() + return None @activity.defn(name=f"{prefix}-sandbox_session_shutdown") async def session_shutdown(args: StopArgs) -> None: key = str(args.state.session_id) session = self._sessions.get(key) - if session is not None: - await session.shutdown() + if session is None: + return None + try: + with _translate_sandbox_errors(): + await session.shutdown() + except ApplicationError: + # Terminal failure: the session is dead, so evict it before + # re-raising. A retryable error instead propagates with the + # entry kept so the activity's retry can still shut it down. del self._sessions[key] + raise + del self._sessions[key] return None return [ diff --git a/tests/contrib/openai_agents/test_openai_sandbox.py b/tests/contrib/openai_agents/test_openai_sandbox.py index 74ff80e85..3338f8d64 100644 --- a/tests/contrib/openai_agents/test_openai_sandbox.py +++ b/tests/contrib/openai_agents/test_openai_sandbox.py @@ -9,6 +9,11 @@ import pytest from agents import Agent, FunctionTool, RunConfig, Runner, Tool from agents.sandbox import Capability, Manifest, SandboxAgent, SandboxRunConfig +from agents.sandbox.errors import ( + ExecTransportError, + SandboxError, + WorkspaceArchiveReadError, +) from agents.sandbox.session.base_sandbox_session import BaseSandboxSession from agents.sandbox.session.sandbox_client import ( BaseSandboxClient, @@ -55,6 +60,7 @@ TestModelProvider, ) from temporalio.contrib.openai_agents.workflow import temporal_sandbox_client +from temporalio.exceptions import ApplicationError from temporalio.workflow import ActivityConfig from tests.helpers import new_worker @@ -569,6 +575,149 @@ async def test_multiple_providers_register_distinct_activities(): ) +# ── SandboxError retryable mapping tests ── + + +class _ExecRaisingSession(_MockSandboxSession): + """Mock session whose exec() raises a chosen SandboxError.""" + + def __init__(self, error: SandboxError) -> None: + super().__init__() + self._error = error + + async def _exec_internal( + self, + *command: str | Path, # type: ignore[reportUnusedParameter] + timeout: float | None = None, # type: ignore[reportUnusedParameter] + ) -> ExecResult: + raise self._error + + +async def _exec_with_error(error: SandboxError) -> None: + provider = SandboxClientProvider( + "mock", _MockSandboxClient(_ExecRaisingSession(error)) + ) + acts = _activity_map(provider) + state = ( + await acts["mock-sandbox_client_create"]( + CreateSessionArgs( + snapshot_spec=None, manifest=Manifest(), client_options=None + ) + ) + ).state + await acts["mock-sandbox_session_exec"]( + ExecArgs(state=state, command=["boom"], shell=True) + ) + + +async def test_exec_terminal_error_becomes_non_retryable_application_error(): + """retryable is False should map to a non-retryable ApplicationError.""" + with pytest.raises(ApplicationError) as exc_info: + await _exec_with_error(ExecTransportError(command=["boom"], retryable=False)) + assert exc_info.value.non_retryable is True + assert exc_info.value.type == "exec_transport_error" + + +async def test_exec_transient_error_propagates_unchanged(): + """retryable is True should let the original SandboxError propagate.""" + with pytest.raises(ExecTransportError): + await _exec_with_error(ExecTransportError(command=["boom"], retryable=True)) + + +async def test_exec_unclassified_error_propagates_unchanged(): + """retryable is None should let the original SandboxError propagate (not converted).""" + with pytest.raises(ExecTransportError): + await _exec_with_error(ExecTransportError(command=["boom"], retryable=None)) + + +class _ShutdownRaisingSession(_MockSandboxSession): + """Mock session whose shutdown() raises a chosen SandboxError.""" + + def __init__(self, error: SandboxError) -> None: + super().__init__() + self._error = error + + async def shutdown(self) -> None: + raise self._error + + +async def _create_shutdown_raising( + error: SandboxError, +) -> tuple[dict[str, Any], SandboxClientProvider, StopArgs, str]: + provider = SandboxClientProvider( + "mock", _MockSandboxClient(_ShutdownRaisingSession(error)) + ) + acts = _activity_map(provider) + state = ( + await acts["mock-sandbox_client_create"]( + CreateSessionArgs( + snapshot_spec=None, manifest=Manifest(), client_options=None + ) + ) + ).state + key = str(state.session_id) + assert key in provider._sessions + return acts, provider, StopArgs(state=state), key + + +async def test_shutdown_terminal_error_evicts_session_and_raises(): + """A terminal shutdown error maps to a non-retryable ApplicationError and + evicts the dead session from the cache.""" + acts, provider, args, key = await _create_shutdown_raising( + ExecTransportError(command=["shutdown"], retryable=False) + ) + + with pytest.raises(ApplicationError) as exc_info: + await acts["mock-sandbox_session_shutdown"](args) + assert exc_info.value.non_retryable is True + assert key not in provider._sessions + + +async def test_shutdown_retryable_error_keeps_session_cached(): + """A retryable shutdown error propagates unchanged and leaves the session + cached so the activity's retry can still shut it down.""" + acts, provider, args, key = await _create_shutdown_raising( + ExecTransportError(command=["shutdown"], retryable=True) + ) + + with pytest.raises(ExecTransportError): + await acts["mock-sandbox_session_shutdown"](args) + assert key in provider._sessions + + +class _RunningRaisingSession(_MockSandboxSession): + """Mock session whose running() raises a chosen SandboxError.""" + + def __init__(self, error: SandboxError) -> None: + super().__init__() + self._error = error + + async def running(self) -> bool: + raise self._error + + +async def test_running_terminal_error_becomes_non_retryable_application_error(): + """A terminal SandboxError from a non-exec activity also maps to a + non-retryable ApplicationError, with type set to its error_code.""" + error = WorkspaceArchiveReadError(path=Path("/workspace"), retryable=False) + provider = SandboxClientProvider( + "mock", _MockSandboxClient(_RunningRaisingSession(error)) + ) + acts = _activity_map(provider) + state = ( + await acts["mock-sandbox_client_create"]( + CreateSessionArgs( + snapshot_spec=None, manifest=Manifest(), client_options=None + ) + ) + ).state + + with pytest.raises(ApplicationError) as exc_info: + await acts["mock-sandbox_session_running"](RunningArgs(state=state)) + assert exc_info.value.non_retryable is True + assert exc_info.value.type == "workspace_archive_read_error" + + # ── End-to-end test: Runner + SandboxAgent through Temporal activities ── diff --git a/uv.lock b/uv.lock index 1f46fc241..15a79011a 100644 --- a/uv.lock +++ b/uv.lock @@ -9,9 +9,12 @@ resolution-markers = [ ] [options] -exclude-newer = "2026-05-20T23:41:58.595699Z" +exclude-newer = "2026-06-01T18:36:48.998335583Z" exclude-newer-span = "P2W" +[options.exclude-newer-package] +openai-agents = false + [[package]] name = "aioboto3" version = "15.5.0" @@ -3424,7 +3427,7 @@ wheels = [ [[package]] name = "openai-agents" -version = "0.17.3" +version = "0.17.5" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "griffelib" }, @@ -3436,9 +3439,9 @@ dependencies = [ { name = "typing-extensions" }, { name = "websockets" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/fd/16/b79c1849125eb6d19cae98c21ff35caa2e55b5ec8d7a02b354b711917ef7/openai_agents-0.17.3.tar.gz", hash = "sha256:63b6dda6bd4fb51169e2a2cbd5d187a4e5ce823bbd15f965c8ed1d3b89072eec", size = 5406135, upload-time = "2026-05-19T01:28:15.971Z" } +sdist = { url = "https://files.pythonhosted.org/packages/72/fe/ef185f2a21f2fba1b0b107f72a7646bb51369d4c4025e2ab4d1ec65764f3/openai_agents-0.17.5.tar.gz", hash = "sha256:5dd46943b993e1a68a78acd254fc6a00cf0455fc3dcc802078ea26964b14278c", size = 5420036, upload-time = "2026-06-11T04:12:35.775Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/80/ec/775a14cfd5f12f4ffe458c7ac9527831093c72e8c1aef682898fc6394106/openai_agents-0.17.3-py3-none-any.whl", hash = "sha256:a048bb0752d40913d18bccf6562f56260b603bb57c972597b6da58f60123f4bd", size = 841541, upload-time = "2026-05-19T01:28:13.334Z" }, + { url = "https://files.pythonhosted.org/packages/b9/f0/9184cd6d3d089a568fc544f1c7f0965d63818fa310c912b30abd333ea138/openai_agents-0.17.5-py3-none-any.whl", hash = "sha256:9afa8a67f0b9fbcdfd2d1545b38d3c52d47e4182921cb79952ad61580d950973", size = 846844, upload-time = "2026-06-11T04:12:32.485Z" }, ] [package.optional-dependencies] @@ -5509,7 +5512,7 @@ requires-dist = [ { name = "langsmith", marker = "extra == 'langsmith'", specifier = ">=0.7.34,<0.9" }, { name = "mcp", marker = "extra == 'openai-agents'", specifier = ">=1.9.4,<2" }, { name = "nexus-rpc", specifier = "==1.4.0" }, - { name = "openai-agents", marker = "extra == 'openai-agents'", specifier = ">=0.17.1" }, + { name = "openai-agents", marker = "extra == 'openai-agents'", specifier = ">=0.17.5" }, { name = "opentelemetry-api", marker = "extra == 'lambda-worker-otel'", specifier = ">=1.11.1,<2" }, { name = "opentelemetry-api", marker = "extra == 'opentelemetry'", specifier = ">=1.11.1,<2" }, { name = "opentelemetry-exporter-otlp-proto-grpc", marker = "extra == 'lambda-worker-otel'", specifier = ">=1.11.1,<2" }, From 530777ee9bed79e4eb8a4fb54c3d2c09efa2803b Mon Sep 17 00:00:00 2001 From: Spencer Judge Date: Wed, 17 Jun 2026 11:04:44 -0700 Subject: [PATCH 134/226] Fix asyncio lock contention in client calls (#1606) --- CHANGELOG.md | 11 +++++++ temporalio/service.py | 6 ++++ tests/test_client.py | 71 ++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 87 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 074191972..346a0bcb3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,3 +18,14 @@ to docs, or any other relevant information. # Changelog ## [Unreleased] + +### Fixed + +- Removed the lazy-connect lock from the per-RPC hot path. It was previously + acquired on every RPC, putting an event-loop-bound primitive on the hot path; + it is now skipped once the client is connected. This reduces the client's + coupling to the event loop it connected on, which can help when reusing a + single long-lived `Client` across event loops or threads (e.g. the + dedicated-loop pattern used with gevent/gunicorn and synchronous services). + Note this does not make a `Client` fully thread- or loop-agnostic; reusing one + long-lived loop is still the recommended pattern. diff --git a/temporalio/service.py b/temporalio/service.py index 5492abb92..3d8702ed1 100644 --- a/temporalio/service.py +++ b/temporalio/service.py @@ -387,6 +387,12 @@ def __init__(self, config: ConnectConfig) -> None: self._bridge_client_connect_lock = asyncio.Lock() async def _connected_client(self) -> temporalio.bridge.client.Client: + # Fast path avoids touching the lock once connected. This keeps the + # lock off the per-RPC hot path so it never binds to (or is contended + # across) an event loop, letting a connected client be reused from any + # loop. + if self._bridge_client is not None: + return self._bridge_client async with self._bridge_client_connect_lock: if not self._bridge_client: runtime = self.config.runtime or temporalio.runtime.Runtime.default() diff --git a/tests/test_client.py b/tests/test_client.py index d3749b665..d611eda3a 100644 --- a/tests/test_client.py +++ b/tests/test_client.py @@ -1,12 +1,14 @@ +import asyncio import dataclasses import json import multiprocessing import multiprocessing.context import os +import threading import uuid from collections.abc import Mapping from datetime import datetime, timedelta, timezone -from typing import Any, cast +from typing import Any, Literal, cast from unittest import mock import google.protobuf.any_pb2 @@ -572,6 +574,73 @@ async def test_lazy_client(client: Client, env: WorkflowEnvironment): assert lazy_client.service_client.worker_service_client._bridge_client +async def test_client_connected_skips_connect_lock(client: Client): + # Once connected, RPCs must not touch the lazy-connect lock. Acquiring it + # per-RPC put an event-loop-bound primitive on the hot path, pinning a + # connected client to the loop it connected on. + other = await Client.connect( + client.service_client.config.target_host, namespace=client.namespace + ) + svc = other.service_client.worker_service_client + assert svc._bridge_client + + class CountingLock(asyncio.Lock): + def __init__(self) -> None: + super().__init__() + self.acquire_count = 0 + + async def acquire(self) -> Literal[True]: + self.acquire_count += 1 + return await super().acquire() + + counting = CountingLock() + svc._bridge_client_connect_lock = counting + await other.workflow_service.get_system_info(GetSystemInfoRequest()) + assert counting.acquire_count == 0 + + +def test_client_reuse_across_event_loops(client: Client): + # A connected client must not be pinned to the loop (or thread) it + # connected on. This mirrors the long-lived-loop reuse pattern used by + # gevent/gunicorn and synchronous services. + target_host = client.service_client.config.target_host + namespace = client.namespace + + connect_loop = asyncio.new_event_loop() + try: + reused_client = connect_loop.run_until_complete( + Client.connect(target_host, namespace=namespace) + ) + finally: + connect_loop.close() + + errors: list[BaseException] = [] + + async def hammer() -> None: + await asyncio.gather( + *( + reused_client.workflow_service.get_system_info(GetSystemInfoRequest()) + for _ in range(10) + ) + ) + + def reuse_on_new_loop() -> None: + loop = asyncio.new_event_loop() + asyncio.set_event_loop(loop) + try: + loop.run_until_complete(hammer()) + except BaseException as err: + errors.append(err) + finally: + asyncio.set_event_loop(None) + loop.close() + + thread = threading.Thread(target=reuse_on_new_loop) + thread.start() + thread.join() + assert not errors, f"cross-loop reuse failed: {errors[0]!r}" + + @workflow.defn class ListableWorkflow: @workflow.run From 4b4e34ef5e26f81230bedfca79c8eb827f5b20ae Mon Sep 17 00:00:00 2001 From: tconley1428 Date: Wed, 17 Jun 2026 12:42:15 -0700 Subject: [PATCH 135/226] Bump version to 1.29.0 (#1607) --- .github/scripts/release_verify.py | 42 +++++++++++++++++++++++++++ .github/workflows/release-publish.yml | 18 ++++++++++++ CHANGELOG.md | 33 +++++++++++++++++++++ pyproject.toml | 2 +- temporalio/service.py | 2 +- uv.lock | 2 +- 6 files changed, 96 insertions(+), 3 deletions(-) diff --git a/.github/scripts/release_verify.py b/.github/scripts/release_verify.py index 7f69f2408..dcfbd5ad5 100644 --- a/.github/scripts/release_verify.py +++ b/.github/scripts/release_verify.py @@ -108,6 +108,42 @@ def verify_dist(args: argparse.Namespace) -> None: print(f" {name}") +def changelog_notes(args: argparse.Namespace) -> None: + changelog_path = pathlib.Path(args.changelog) + lines = changelog_path.read_text(encoding="utf-8").splitlines() + heading = re.compile(r"^## \[(?P[^\]]+)\](?:\s+-\s+.*)?\s*$") + + start = None + for index, line in enumerate(lines): + match = heading.match(line) + if match and match.group("version") == args.version: + start = index + 1 + break + + if start is None: + raise RuntimeError( + f"Could not find changelog section for version {args.version!r}" + ) + + end = len(lines) + for index in range(start, len(lines)): + if lines[index].startswith("## "): + end = index + break + + section_lines = lines[start:end] + while section_lines and not section_lines[0].strip(): + section_lines.pop(0) + while section_lines and not section_lines[-1].strip(): + section_lines.pop() + + if not section_lines: + raise RuntimeError(f"Changelog section for {args.version!r} is empty") + + notes = "## Changelog\n\n" + "\n".join(section_lines) + "\n" + pathlib.Path(args.output).write_text(notes, encoding="utf-8") + + def main(argv: Sequence[str] | None = None) -> None: parser = argparse.ArgumentParser() subparsers = parser.add_subparsers(required=True) @@ -122,6 +158,12 @@ def main(argv: Sequence[str] | None = None) -> None: verify_parser.add_argument("--dist-dir", default="dist") verify_parser.set_defaults(func=verify_dist) + changelog_parser = subparsers.add_parser("changelog-notes") + changelog_parser.add_argument("--version", required=True) + changelog_parser.add_argument("--changelog", default="CHANGELOG.md") + changelog_parser.add_argument("--output", required=True) + changelog_parser.set_defaults(func=changelog_notes) + args = parser.parse_args(argv) args.func(args) diff --git a/.github/workflows/release-publish.yml b/.github/workflows/release-publish.yml index 5c8d54196..5f4cdfc74 100644 --- a/.github/workflows/release-publish.yml +++ b/.github/workflows/release-publish.yml @@ -111,6 +111,12 @@ jobs: python .github/scripts/release_verify.py validate-version \ --sha "$(git rev-parse HEAD)" \ --github-output "$GITHUB_OUTPUT" + - name: Validate changelog release notes + run: | + set -euo pipefail + python .github/scripts/release_verify.py changelog-notes \ + --version "${{ steps.validate_versions.outputs.version }}" \ + --output /tmp/release-notes.md - name: Download and flatten artifacts env: GH_TOKEN: ${{ github.token }} @@ -249,6 +255,17 @@ jobs: permissions: contents: write steps: + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 + with: + ref: ${{ needs.verify_artifacts.outputs.release_sha }} + - name: Build changelog release notes + env: + VERSION: ${{ needs.verify_artifacts.outputs.version }} + run: | + set -euo pipefail + python3 .github/scripts/release_verify.py changelog-notes \ + --version "$VERSION" \ + --output release-notes.md - name: Create draft release with generated notes env: GH_TOKEN: ${{ github.token }} @@ -261,4 +278,5 @@ jobs: --target "$RELEASE_SHA" \ --title "$VERSION" \ --draft \ + --notes-file release-notes.md \ --generate-notes diff --git a/CHANGELOG.md b/CHANGELOG.md index 346a0bcb3..9c975cfec 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,8 +19,41 @@ to docs, or any other relevant information. ## [Unreleased] +## [1.29.0] - 2026-06-17 + +### Added + +- Added experimental `temporalio.workflow.signal_with_start_workflow`, backed by + generated system Nexus bindings for + `WorkflowService.SignalWithStartWorkflowExecution`. +- Added OpenAI Agents plugin support for `CustomTool` dispatch, including lazy + tool discovery through `defer_loading`. + +### Changed + +- Client connections now use gzip transport-level gRPC compression by default. + Pass `grpc_compression=GrpcCompression.NONE` to `Client.connect` or + `CloudOperationsClient.connect` to disable it. + +### Breaking Changes + +- `StartWorkflowUpdateWithStartInput` now owns the authoritative + `rpc_metadata` and `rpc_timeout` fields for + `OutboundInterceptor.start_update_with_start_workflow`. These fields were + removed from the nested update-with-start input objects, so custom + interceptors that accessed them there should read or update the top-level + fields instead. + ### Fixed +- Fixed `breakpoint()` and `pdb.set_trace()` inside workflow code when a worker + runs with `debug_mode=True` or `TEMPORAL_DEBUG=1`; sandboxed workflows without + debug mode now get a clearer error pointing to `debug_mode=True`. +- Fixed `start_update_with_start_workflow` interceptor handling so RPC metadata + and timeouts are forwarded to the underlying `execute_multi_operation` call. +- Fixed OpenAI Agents plugin streamed event serialization when pydantic had not + yet built deferred schemas, and fixed terminal sandbox errors retrying + forever. - Removed the lazy-connect lock from the per-RPC hot path. It was previously acquired on every RPC, putting an event-loop-bound primitive on the hot path; it is now skipped once the client is connected. This reduces the client's diff --git a/pyproject.toml b/pyproject.toml index 943e56018..299c03df9 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "temporalio" -version = "1.28.0" +version = "1.29.0" description = "Temporal.io Python SDK" authors = [{ name = "Temporal Technologies Inc", email = "sdk@temporal.io" }] requires-python = ">=3.10" diff --git a/temporalio/service.py b/temporalio/service.py index 3d8702ed1..2d3829c08 100644 --- a/temporalio/service.py +++ b/temporalio/service.py @@ -24,7 +24,7 @@ import temporalio.runtime from temporalio.bridge.client import RPCError as BridgeRPCError -__version__ = "1.28.0" +__version__ = "1.29.0" ServiceRequest = TypeVar("ServiceRequest", bound=google.protobuf.message.Message) ServiceResponse = TypeVar("ServiceResponse", bound=google.protobuf.message.Message) diff --git a/uv.lock b/uv.lock index 15a79011a..3e48e3df7 100644 --- a/uv.lock +++ b/uv.lock @@ -5412,7 +5412,7 @@ wheels = [ [[package]] name = "temporalio" -version = "1.28.0" +version = "1.29.0" source = { virtual = "." } dependencies = [ { name = "nexus-rpc" }, From b51be68d70188a11a2e13e8463c5b031de20a52b Mon Sep 17 00:00:00 2001 From: tconley1428 Date: Thu, 18 Jun 2026 08:40:34 -0700 Subject: [PATCH 136/226] Retry release smoke package install (#1608) --- .github/scripts/install_release_package.py | 34 ++++++++++++++++++++-- 1 file changed, 32 insertions(+), 2 deletions(-) diff --git a/.github/scripts/install_release_package.py b/.github/scripts/install_release_package.py index 723267e2b..45f407c7f 100644 --- a/.github/scripts/install_release_package.py +++ b/.github/scripts/install_release_package.py @@ -6,19 +6,41 @@ import importlib.metadata import subprocess import sys +import time from collections.abc import Sequence +RELEASE_INSTALL_ATTEMPTS = 31 +RELEASE_INSTALL_RETRY_SECONDS = 30 + def _pip_install(args: Sequence[str]) -> None: subprocess.check_call([sys.executable, "-m", "pip", "install", *args]) +def _pip_install_with_retries(args: Sequence[str]) -> None: + for attempt in range(1, RELEASE_INSTALL_ATTEMPTS + 1): + try: + _pip_install(args) + return + except subprocess.CalledProcessError: + if attempt == RELEASE_INSTALL_ATTEMPTS: + raise + print( + "Package was not installable yet; retrying in " + f"{RELEASE_INSTALL_RETRY_SECONDS}s " + f"({attempt}/{RELEASE_INSTALL_ATTEMPTS})", + flush=True, + ) + time.sleep(RELEASE_INSTALL_RETRY_SECONDS) + + def install_package(args: argparse.Namespace) -> None: package = f"temporalio=={args.version}" if args.dependency_index_url: - _pip_install( + _pip_install_with_retries( [ "--prefer-binary", + "--no-cache-dir", "--index-url", args.index_url, "--no-deps", @@ -37,7 +59,15 @@ def install_package(args: argparse.Namespace) -> None: ] ) else: - _pip_install(["--prefer-binary", "--index-url", args.index_url, package]) + _pip_install_with_retries( + [ + "--prefer-binary", + "--no-cache-dir", + "--index-url", + args.index_url, + package, + ] + ) subprocess.check_call([sys.executable, "-m", "pip", "check"]) From 5067ce5d074043ca6dce7170b424987923949ecc Mon Sep 17 00:00:00 2001 From: tconley1428 Date: Thu, 18 Jun 2026 08:40:46 -0700 Subject: [PATCH 137/226] Generate release note additions (#1609) --- .github/scripts/release_verify.py | 103 +++++++++++++++++++++++++- .github/workflows/release-publish.yml | 4 + 2 files changed, 106 insertions(+), 1 deletion(-) diff --git a/.github/scripts/release_verify.py b/.github/scripts/release_verify.py index dcfbd5ad5..390252854 100644 --- a/.github/scripts/release_verify.py +++ b/.github/scripts/release_verify.py @@ -6,6 +6,7 @@ import ast import pathlib import re +import subprocess from collections.abc import Sequence try: @@ -108,6 +109,98 @@ def verify_dist(args: argparse.Namespace) -> None: print(f" {name}") +def _git(args: Sequence[str], *, cwd: pathlib.Path | None = None) -> str: + return subprocess.check_output( + ["git", *args], + cwd=cwd, + encoding="utf-8", + stderr=subprocess.STDOUT, + ).strip() + + +def _version_tuple(version: str) -> tuple[int, ...] | None: + match = re.fullmatch(r"([0-9]+(?:\.[0-9]+)+)(?:[a-zA-Z0-9_.+-]+)?", version) + if not match: + return None + return tuple(int(part) for part in match.group(1).split(".")) + + +def _previous_release_tag(version: str) -> str: + current = _version_tuple(version) + if current is None: + raise RuntimeError(f"Cannot determine previous release for {version!r}") + + candidates: list[tuple[int, ...]] = [] + for tag in _git(["tag"]).splitlines(): + tag_version = _version_tuple(tag) + if tag_version is not None and tag_version < current: + candidates.append(tag_version) + if not candidates: + raise RuntimeError(f"Could not find a previous release tag before {version!r}") + return ".".join(str(part) for part in max(candidates)) + + +def _gitlink(rev: str, path: str) -> str: + output = _git(["ls-tree", rev, path]) + parts = output.split() + if len(parts) < 3 or parts[0] != "160000": + raise RuntimeError(f"Could not find submodule gitlink {path!r} at {rev!r}") + return parts[2] + + +def _clean_commit_subject(subject: str) -> str: + subject = subject.encode("ascii", "ignore").decode("ascii") + subject = re.sub(r"\s+", " ", subject).strip() + subject = re.sub(r"^:[a-z0-9_+-]+:\s*", "", subject) + return subject.replace(" : ", ": ") + + +def _link_sdk_core_prs(subject: str) -> str: + return re.sub( + r"\(#([0-9]+)\)", + r"([#\1](https://github.com/temporalio/sdk-rust/pull/\1))", + subject, + ) + + +def _sdk_core_release_notes(version: str, path: str) -> list[str]: + previous_tag = _previous_release_tag(version) + previous_commit = _gitlink(previous_tag, path) + current_commit = _gitlink("HEAD", path) + if previous_commit == current_commit: + return [] + + submodule_path = pathlib.Path(path) + if not (submodule_path / ".git").exists(): + raise RuntimeError( + f"Submodule {path!r} is not initialized; checkout with submodules" + ) + + log_args = [ + "log", + "--format=%H%x00%h%x00%s", + "--reverse", + f"{previous_commit}..{current_commit}", + ] + try: + log_output = _git(log_args, cwd=submodule_path) + except subprocess.CalledProcessError: + _git(["fetch", "--quiet", "origin", "main"], cwd=submodule_path) + log_output = _git(log_args, cwd=submodule_path) + if not log_output: + return [] + + lines = ["### SDK Core", ""] + for line in log_output.splitlines(): + full_hash, short_hash, subject = line.split("\0", 2) + subject = _link_sdk_core_prs(_clean_commit_subject(subject)) + lines.append( + f"- [`{short_hash}`](https://github.com/temporalio/sdk-rust/commit/" + f"{full_hash}) {subject}" + ) + return lines + + def changelog_notes(args: argparse.Namespace) -> None: changelog_path = pathlib.Path(args.changelog) lines = changelog_path.read_text(encoding="utf-8").splitlines() @@ -140,7 +233,12 @@ def changelog_notes(args: argparse.Namespace) -> None: if not section_lines: raise RuntimeError(f"Changelog section for {args.version!r} is empty") - notes = "## Changelog\n\n" + "\n".join(section_lines) + "\n" + note_lines = ["## Notable Changes", "", *section_lines] + sdk_core_notes = _sdk_core_release_notes(args.version, args.sdk_core_path) + if sdk_core_notes: + note_lines.extend(["", *sdk_core_notes]) + + notes = "\n".join(note_lines) + "\n" pathlib.Path(args.output).write_text(notes, encoding="utf-8") @@ -162,6 +260,9 @@ def main(argv: Sequence[str] | None = None) -> None: changelog_parser.add_argument("--version", required=True) changelog_parser.add_argument("--changelog", default="CHANGELOG.md") changelog_parser.add_argument("--output", required=True) + changelog_parser.add_argument( + "--sdk-core-path", default="temporalio/bridge/sdk-core" + ) changelog_parser.set_defaults(func=changelog_notes) args = parser.parse_args(argv) diff --git a/.github/workflows/release-publish.yml b/.github/workflows/release-publish.yml index 5f4cdfc74..9996e2fef 100644 --- a/.github/workflows/release-publish.yml +++ b/.github/workflows/release-publish.yml @@ -101,6 +101,8 @@ jobs: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 with: ref: ${{ github.sha }} + fetch-depth: 0 + submodules: recursive - uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5 with: python-version: "3.11" @@ -258,6 +260,8 @@ jobs: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 with: ref: ${{ needs.verify_artifacts.outputs.release_sha }} + fetch-depth: 0 + submodules: recursive - name: Build changelog release notes env: VERSION: ${{ needs.verify_artifacts.outputs.version }} From 26df51e2d638a13419ef3b54556e3f724bb66d52 Mon Sep 17 00:00:00 2001 From: Justin Anderson <44687433+jmaeagle99@users.noreply.github.com> Date: Thu, 18 Jun 2026 12:14:06 -0700 Subject: [PATCH 138/226] =?UTF-8?q?=F0=9F=92=A5=20Enable=20lambda=20worker?= =?UTF-8?q?=20async=20configure=20callback=20(#1604)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * :boom: enable lambda worker async configure * example adjustment * comment updates * update changelog --- CHANGELOG.md | 13 + .../contrib/aws/lambda_worker/README.md | 18 + .../contrib/aws/lambda_worker/_run_worker.py | 354 ++++++++++++------ .../aws/lambda_worker/test_lambda_worker.py | 156 +++++++- 4 files changed, 413 insertions(+), 128 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9c975cfec..0183a74a4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,6 +19,19 @@ to docs, or any other relevant information. ## [Unreleased] +### Changed + +- AWS Lambda worker `configure` parameter supports sync, async, and async + generator style functions. This callback is invoked on the asyncio event + loop. + +### Breaking Changes + +- AWS Lambda worker `configure` parameter has been changed to be invoked + per-invocation of the worker instead of only at startup. It is advised that + any shared, heavy-weight operations are performed outside of the callback + before `run_worker` is invoked. + ## [1.29.0] - 2026-06-17 ### Added diff --git a/temporalio/contrib/aws/lambda_worker/README.md b/temporalio/contrib/aws/lambda_worker/README.md index f9166b13d..c12e7037d 100644 --- a/temporalio/contrib/aws/lambda_worker/README.md +++ b/temporalio/contrib/aws/lambda_worker/README.md @@ -48,6 +48,24 @@ pre-populated with Lambda-appropriate defaults. Override any field directly in the callback. The `task_queue` key in `worker_config` is pre-populated from the `TEMPORAL_TASK_QUEUE` environment variable if set. +### Sync, async, and async-generator configure + +The configure callback runs **once per invocation, inside that invocation's +event loop**, before the client connects. It may be: + +- a plain function `def configure(config) -> None`; +- an `async def configure(config) -> None` coroutine — awaited for setup (pair + with `shutdown_hooks` for teardown); +- an `async def configure(config): ...; yield; ...` async generator — statements + before the single `yield` run before the client connects, the worker runs + while the generator is suspended at the `yield`, and statements after the + `yield` run as teardown once the worker has stopped. + +The callback runs per invocation (rather than once at process start) because +event-loop-bound resources cannot be created before an event loop exists and +cannot be shared across invocations — each invocation runs under a fresh +`asyncio.run` loop. + ## Lambda-tuned worker defaults The package applies conservative concurrency limits suited to Lambda's resource diff --git a/temporalio/contrib/aws/lambda_worker/_run_worker.py b/temporalio/contrib/aws/lambda_worker/_run_worker.py index 6a2cc75a3..f384fb954 100644 --- a/temporalio/contrib/aws/lambda_worker/_run_worker.py +++ b/temporalio/contrib/aws/lambda_worker/_run_worker.py @@ -1,13 +1,15 @@ from __future__ import annotations import asyncio +import inspect import logging import os import sys -from collections.abc import Awaitable, Callable +from collections.abc import AsyncGenerator, Awaitable, Callable +from contextlib import AbstractAsyncContextManager, asynccontextmanager from dataclasses import dataclass, field from datetime import timedelta -from typing import Any +from typing import Any, TypeAlias import temporalio.client import temporalio.worker @@ -28,6 +30,16 @@ logger = logging.getLogger(__name__) +# A plain, ``async def`` coroutine, ``async def`` generator, or async-context-manager +# callback. See run_worker. +ConfigureCallback: TypeAlias = Callable[ + [LambdaWorkerConfig], + None + | Awaitable[None] + | AsyncGenerator[None, None] + | AbstractAsyncContextManager[None], +] + @dataclass class _WorkerDeps: @@ -62,54 +74,123 @@ def _default_extract_lambda_ctx( return None +def _validate_task_queue(config: LambdaWorkerConfig) -> None: + """Raise if no task queue has been configured.""" + if not config.worker_config.get("task_queue"): + raise ValueError( + "task queue not configured: set " + 'worker_config["task_queue"] or the ' + "TEMPORAL_TASK_QUEUE environment variable" + ) + + def run_worker( version: WorkerDeploymentVersion, - configure: Callable[[LambdaWorkerConfig], None], + configure: ConfigureCallback, ) -> Callable[[Any, Any], None]: """Create a Temporal worker Lambda handler. - Calls the *configure* callback to collect workflow/activity registrations and option overrides, - then returns a Lambda handler function. On each invocation the handler connects to the Temporal - server, starts a worker with Lambda-tuned defaults, polls for tasks until the invocation - deadline approaches, and then gracefully shuts down. - - The *version* parameter identifies this worker's deployment version. ``run_worker`` always - enables Worker Deployment Versioning (``use_worker_versioning=True``). To provide a default - versioning behavior for workflows that do not specify one at registration time, set - ``deployment_config`` in ``worker_config`` in the configure callback. - - The returned handler has the signature ``handler(event, context)`` and should be set as your - Lambda function's handler entry point. + Calls the *configure* callback to collect workflow/activity registrations and option + overrides, then returns a Lambda handler function. On each invocation the handler + connects to the Temporal server, starts a worker with Lambda-tuned defaults, polls for + tasks until the invocation deadline approaches, and then gracefully shuts down. + + The *configure* callback is invoked **once per invocation** and may be synchronous or + asynchronous: + + * **Synchronous** ``def configure(config) -> None`` — runs per invocation. Use for + static worker definition (task queue, registrations, option tuning) and resources + that are not bound to an event loop. + * **Async** ``async def configure(config) -> None`` — awaited per invocation. Use when + setup must ``await`` (for example, opening an async client). Pair with + ``shutdown_hooks`` for teardown. + * **Async generator** ``async def configure(config): ...; yield; ...`` (or an + equivalent ``@contextlib.asynccontextmanager``-decorated function) — entered per + invocation. Statements before the single ``yield`` run before the client connects; + the worker runs while the generator is suspended at the ``yield``; statements after + the ``yield`` run as teardown once the worker has stopped. Any ``shutdown_hooks`` + registered before the ``yield`` run after the worker stops but *before* the + post-``yield`` teardown, so this resource outlives the hooks (e.g. a telemetry + flush hook can still emit before the resource is closed). This is the recommended + shape for event-loop-bound resources that must live for the duration of the + invocation, such as an ``aioboto3`` S3 client backing the external-storage data + converter (see the async example below). + + The callback runs per invocation (not once at cold start) because event-loop-bound + resources cannot be created at cold start (there is no running loop) and cannot be + shared across invocations (each invocation runs under a fresh ``asyncio.run`` loop). + + The *version* parameter identifies this worker's deployment version. ``run_worker`` + always enables Worker Deployment Versioning (``use_worker_versioning=True``). To + provide a default versioning behavior for workflows that do not specify one at + registration time, set ``deployment_config`` in ``worker_config`` in the configure + callback. + + The returned handler has the signature ``handler(event, context)`` and should be set as + your Lambda function's handler entry point. Args: version: The worker deployment version. Required. configure: A callback that receives a :py:class:`LambdaWorkerConfig` (pre-populated with Lambda defaults) and configures workflows, - activities, and options on it. + activities, and options on it. May be sync, async, or an async + generator (see above). Returns: A Lambda handler function. - Example:: + Example: + Synchronous configure (static worker definition):: - from temporalio.common import WorkerDeploymentVersion - from temporalio.contrib.aws.lambda_worker import ( - LambdaWorkerConfig, - run_worker, - ) + from temporalio.common import WorkerDeploymentVersion + from temporalio.contrib.aws.lambda_worker import ( + LambdaWorkerConfig, + run_worker, + ) - def configure(config: LambdaWorkerConfig) -> None: - config.worker_config["task_queue"] = "my-task-queue" - config.worker_config["workflows"] = [MyWorkflow] - config.worker_config["activities"] = [my_activity] - - lambda_handler = run_worker( - WorkerDeploymentVersion( - deployment_name="my-service", - build_id="v1.0", - ), - configure, - ) + def configure(config: LambdaWorkerConfig) -> None: + config.worker_config["task_queue"] = "my-task-queue" + config.worker_config["workflows"] = [MyWorkflow] + config.worker_config["activities"] = [my_activity] + + lambda_handler = run_worker( + WorkerDeploymentVersion( + deployment_name="my-service", + build_id="v1.0"), + configure, + ) + + Async generator configure, bracketing an ``aioboto3`` S3 client. The session + lives at module scope (it is not event-loop-bound and caches credentials across + warm invocations); only the loop-bound client is opened per invocation:: + + import aioboto3 + import dataclasses + from temporalio.contrib.aws.s3driver import S3StorageDriver + from temporalio.contrib.aws.s3driver.aioboto3 import new_aioboto3_client + from temporalio.converter import DataConverter, ExternalStorage + + session = aioboto3.Session() + + async def configure(config: LambdaWorkerConfig): + config.worker_config["task_queue"] = "my-task-queue" + config.worker_config["workflows"] = [MyWorkflow] + async with session.client("s3") as s3_client: + driver = S3StorageDriver( + client=new_aioboto3_client(s3_client), bucket="my-payloads", + ) + config.client_connect_config["data_converter"] = dataclasses.replace( + DataConverter.default, + external_storage=ExternalStorage(drivers=[driver]), + ) + yield + + lambda_handler = run_worker( + WorkerDeploymentVersion( + deployment_name="my-service", + build_id="v1.0"), + configure, + ) """ deps = _WorkerDeps() try: @@ -121,7 +202,7 @@ def configure(config: LambdaWorkerConfig) -> None: def _run_worker_internal( version: WorkerDeploymentVersion, - configure: Callable[[LambdaWorkerConfig], None], + configure: ConfigureCallback, deps: _WorkerDeps, ) -> Callable[[Any, Any], None]: """Core logic with injected dependencies for testability.""" @@ -133,46 +214,38 @@ def _run_worker_internal( # Load client config from envconfig / TOML. load_config = deps.load_config or (lambda: _default_load_config(deps.getenv)) profile = load_config() - connect_config: ClientConnectConfig = {**profile.to_client_connect_config()} + base_connect_config: ClientConnectConfig = {**profile.to_client_connect_config()} - # Build worker config with Lambda defaults. - worker_config: WorkerConfig = {} - apply_lambda_worker_defaults(worker_config) + # Build base worker config with Lambda defaults. + base_worker_config: WorkerConfig = {} + apply_lambda_worker_defaults(base_worker_config) # Always enable deployment versioning. - worker_config["deployment_config"] = WorkerDeploymentConfig( + base_worker_config["deployment_config"] = WorkerDeploymentConfig( version=version, use_worker_versioning=True, ) # Calculate default shutdown buffer. - graceful_timeout = worker_config.get( + graceful_timeout = base_worker_config.get( "graceful_shutdown_timeout", timedelta(seconds=5) ) shutdown_buffer = graceful_timeout + DEFAULT_SHUTDOWN_HOOK_BUFFER - # Pre-populate config with defaults. - config = LambdaWorkerConfig( - client_connect_config=connect_config, - worker_config=worker_config, - shutdown_deadline_buffer=shutdown_buffer, - ) - - # Pre-populate task queue from environment if available. env_tq = deps.getenv("TEMPORAL_TASK_QUEUE") - if env_tq: - config.worker_config["task_queue"] = env_tq - - # Call user configure callback with pre-populated config. - configure(config) - # Validate task queue. - if not config.worker_config.get("task_queue"): - raise ValueError( - "task queue not configured: set " - 'worker_config["task_queue"] or the ' - "TEMPORAL_TASK_QUEUE environment variable" + def _new_config() -> LambdaWorkerConfig: + """Fresh config per invocation; dicts/hooks are copied so nothing leaks across + invocations. + """ + config = LambdaWorkerConfig( + client_connect_config={**base_connect_config}, + worker_config={**base_worker_config}, + shutdown_deadline_buffer=shutdown_buffer, ) + if env_tq: + config.worker_config["task_queue"] = env_tq + return config extract_lambda_ctx = deps.extract_lambda_ctx or _default_extract_lambda_ctx @@ -180,7 +253,8 @@ def _handler(_event: Any, lambda_context: Any) -> None: asyncio.run( _invocation_handler( lambda_context=lambda_context, - config=config, + configure=configure, + new_config=_new_config, deps=deps, extract_lambda_ctx=extract_lambda_ctx, ) @@ -189,71 +263,107 @@ def _handler(_event: Any, lambda_context: Any) -> None: return _handler +@asynccontextmanager +async def _invocation_config_scope( + configure: ConfigureCallback, + new_config: Callable[[], LambdaWorkerConfig], +) -> AsyncGenerator[LambdaWorkerConfig, None]: + """Run *configure* (see run_worker for the forms) against a fresh per-invocation config + and yield it. For the generator / context-manager forms, post-``yield`` teardown runs + when the caller's block exits, including on error. Task queue is validated after + setup. + """ + config = new_config() + if inspect.isasyncgenfunction(configure): + # Wrap the bare async generator so it drives like a context manager: setup on + # enter, teardown on exit. + cm: Any = asynccontextmanager(configure)(config) + else: + result = configure(config) + if inspect.isawaitable(result): + await result + # A @asynccontextmanager-decorated callback returns the context manager directly. + cm = result if result is not None and hasattr(result, "__aenter__") else None + + if cm is not None: + async with cm: + _validate_task_queue(config) + yield config + else: + _validate_task_queue(config) + yield config + + async def _invocation_handler( *, lambda_context: Any, - config: LambdaWorkerConfig, + configure: ConfigureCallback, + new_config: Callable[[], LambdaWorkerConfig], deps: _WorkerDeps, extract_lambda_ctx: Callable[[Any], tuple[str, str] | None], ) -> None: """Handle a single Lambda invocation.""" - shutdown_buffer = config.shutdown_deadline_buffer - - # Check deadline feasibility. - remaining_ms_fn = getattr(lambda_context, "get_remaining_time_in_millis", None) - deadline_available = remaining_ms_fn is not None - if deadline_available: - assert remaining_ms_fn is not None - remaining = timedelta(milliseconds=remaining_ms_fn()) - work_time = remaining - shutdown_buffer - if work_time <= timedelta(seconds=1): - raise RuntimeError( - f"Lambda timeout is too short: {remaining.total_seconds():.1f}s " - f"remaining but {shutdown_buffer.total_seconds():.1f}s is " - f"reserved for shutdown, leaving no time for work. " - f"Increase the function timeout or decrease the shutdown " - f"deadline buffer" - ) - elif work_time < timedelta(seconds=5): - logger.warning( - "Lambda timeout leaves less than 5s for work after " - "shutdown buffer; consider increasing the function " - "timeout or decreasing the shutdown deadline buffer " - "(work_time=%s, shutdown_buffer=%s)", - work_time, - shutdown_buffer, - ) - - # Build per-invocation connect kwargs with identity from Lambda context. - invocation_connect_kwargs: ClientConnectConfig = {**config.client_connect_config} - if "identity" not in invocation_connect_kwargs: - ctx_info = extract_lambda_ctx(lambda_context) - if ctx_info is not None: - request_id, function_arn = ctx_info - invocation_connect_kwargs["identity"] = build_lambda_identity( - request_id, function_arn - ) - - # Connect to Temporal. - client = await deps.connect(**invocation_connect_kwargs) - - # Create the worker. - worker = deps.create_worker(client, **config.worker_config) - - # Run the worker until the deadline approaches or context is done. - if deadline_available: - assert remaining_ms_fn is not None - work_time_secs = ( - timedelta(milliseconds=remaining_ms_fn()) - shutdown_buffer - ).total_seconds() - if work_time_secs > 0: - try: - await asyncio.wait_for(worker.run(), timeout=work_time_secs) - except asyncio.TimeoutError: - pass - else: - # No deadline - run until cancelled. - await worker.run() - - # Run shutdown hooks after worker has stopped. - await _run_shutdown_hooks(config) + async with _invocation_config_scope(configure, new_config) as config: + shutdown_buffer = config.shutdown_deadline_buffer + + # Check deadline feasibility. + remaining_ms_fn = getattr(lambda_context, "get_remaining_time_in_millis", None) + deadline_available = remaining_ms_fn is not None + if deadline_available: + assert remaining_ms_fn is not None + remaining = timedelta(milliseconds=remaining_ms_fn()) + work_time = remaining - shutdown_buffer + if work_time <= timedelta(seconds=1): + raise RuntimeError( + f"Lambda timeout is too short: {remaining.total_seconds():.1f}s " + f"remaining but {shutdown_buffer.total_seconds():.1f}s is " + f"reserved for shutdown, leaving no time for work. " + f"Increase the function timeout or decrease the shutdown " + f"deadline buffer" + ) + elif work_time < timedelta(seconds=5): + logger.warning( + "Lambda timeout leaves less than 5s for work after " + "shutdown buffer; consider increasing the function " + "timeout or decreasing the shutdown deadline buffer " + "(work_time=%s, shutdown_buffer=%s)", + work_time, + shutdown_buffer, + ) + + # Build per-invocation connect kwargs with identity from Lambda context. + invocation_connect_kwargs: ClientConnectConfig = { + **config.client_connect_config + } + if "identity" not in invocation_connect_kwargs: + ctx_info = extract_lambda_ctx(lambda_context) + if ctx_info is not None: + request_id, function_arn = ctx_info + invocation_connect_kwargs["identity"] = build_lambda_identity( + request_id, function_arn + ) + + # Connect to Temporal. + client = await deps.connect(**invocation_connect_kwargs) + + # Create the worker. + worker = deps.create_worker(client, **config.worker_config) + + # Run the worker until the deadline approaches or context is done. + if deadline_available: + assert remaining_ms_fn is not None + work_time_secs = ( + timedelta(milliseconds=remaining_ms_fn()) - shutdown_buffer + ).total_seconds() + if work_time_secs > 0: + try: + await asyncio.wait_for(worker.run(), timeout=work_time_secs) + except asyncio.TimeoutError: + pass + else: + # No deadline - run until cancelled. + await worker.run() + + # Run shutdown hooks after worker has stopped, before any async-generator + # configure teardown (which unwinds on scope exit). + await _run_shutdown_hooks(config) diff --git a/tests/contrib/aws/lambda_worker/test_lambda_worker.py b/tests/contrib/aws/lambda_worker/test_lambda_worker.py index cda1cd12f..9d2ec78a7 100644 --- a/tests/contrib/aws/lambda_worker/test_lambda_worker.py +++ b/tests/contrib/aws/lambda_worker/test_lambda_worker.py @@ -2,6 +2,9 @@ from __future__ import annotations +import dataclasses +import itertools +from contextlib import asynccontextmanager from datetime import timedelta from pathlib import Path from typing import Any @@ -126,8 +129,6 @@ def second_hook() -> None: assert second_called def test_is_dataclass(self) -> None: - import dataclasses - assert dataclasses.is_dataclass(LambdaWorkerConfig) def test_default_field_independence(self) -> None: @@ -278,14 +279,17 @@ def test_configure_callback_error(self) -> None: def bad_configure(_config: LambdaWorkerConfig) -> None: raise RuntimeError("bad config") + # configure runs per invocation, so the error surfaces when the handler is invoked. + handler = _run_worker_internal(TEST_VERSION, bad_configure, deps) with pytest.raises(RuntimeError, match="bad config"): - _run_worker_internal(TEST_VERSION, bad_configure, deps) + handler({}, _make_lambda_context()) def test_missing_task_queue(self) -> None: deps = _make_test_deps() deps.getenv = lambda _: None # type: ignore[assignment] + handler = _run_worker_internal(TEST_VERSION, lambda config: None, deps) with pytest.raises(ValueError, match="task queue not configured"): - _run_worker_internal(TEST_VERSION, lambda config: None, deps) + handler({}, _make_lambda_context()) def test_missing_version(self) -> None: deps = _make_test_deps() @@ -494,7 +498,8 @@ def test_task_queue_pre_populated_from_env(self) -> None: def configure(config: LambdaWorkerConfig) -> None: task_queues.append(config.worker_config.get("task_queue")) - _run_worker_internal(TEST_VERSION, configure, deps) + handler = _run_worker_internal(TEST_VERSION, configure, deps) + handler({}, _make_lambda_context()) assert task_queues[0] == "test-queue" def test_config_pre_populated_with_defaults(self) -> None: @@ -505,7 +510,8 @@ def test_config_pre_populated_with_defaults(self) -> None: def configure(config: LambdaWorkerConfig) -> None: captured.append(config) - _run_worker_internal(TEST_VERSION, configure, deps) + handler = _run_worker_internal(TEST_VERSION, configure, deps) + handler({}, _make_lambda_context()) wc = captured[0].worker_config assert wc.get("max_concurrent_activities") == DEFAULT_MAX_CONCURRENT_ACTIVITIES assert wc.get("disable_eager_activity_execution") is True @@ -522,3 +528,141 @@ def test_no_deadline_runs_until_complete(self) -> None: ctx.aws_request_id = "req-123" ctx.invoked_function_arn = "arn:aws:lambda:us-east-1:123:function:f" handler({}, ctx) + + +class TestAsyncConfigure: + """configure may be sync, an async coroutine, or an async generator; all run once per + invocation inside that invocation's event loop.""" + + def test_async_configure_called_per_invocation(self) -> None: + deps = _make_test_deps() + calls = 0 + + async def configure(config: LambdaWorkerConfig) -> None: + nonlocal calls + calls += 1 + config.worker_config["task_queue"] = "async-queue" + + handler = _run_worker_internal(TEST_VERSION, configure, deps) + handler({}, _make_lambda_context()) + handler({}, _make_lambda_context()) + assert calls == 2 + + def test_async_configure_can_set_data_converter(self) -> None: + connect_capture: list[dict[str, Any]] = [] + deps = _make_test_deps(connect_kwargs_capture=connect_capture) + sentinel = object() + + async def configure(config: LambdaWorkerConfig) -> None: + config.client_connect_config["data_converter"] = sentinel # type: ignore[typeddict-item] + + handler = _run_worker_internal(TEST_VERSION, configure, deps) + handler({}, _make_lambda_context()) + assert connect_capture[0]["data_converter"] is sentinel + + def test_async_generator_setup_runs_before_connect_teardown_after(self) -> None: + order: list[str] = [] + deps = _make_test_deps() + + original_connect = deps.connect + + async def tracking_connect(**kwargs: Any) -> Any: + order.append("connect") + return await original_connect(**kwargs) + + deps.connect = tracking_connect + + async def configure(config: LambdaWorkerConfig): + order.append("setup") + config.worker_config["task_queue"] = "gen-queue" + yield + order.append("teardown") + + handler = _run_worker_internal(TEST_VERSION, configure, deps) + handler({}, _make_lambda_context()) + assert order == ["setup", "connect", "teardown"] + + def test_async_generator_teardown_runs_on_error(self) -> None: + """Teardown after the yield runs even when the worker run raises.""" + torn_down = False + deps = _make_test_deps() + + async def failing_run() -> None: + raise RuntimeError("worker boom") + + def fake_create_worker(_client: Any, **_kwargs: Any) -> Any: + w = MagicMock() + w.run = failing_run + return w + + deps.create_worker = fake_create_worker + + async def configure(config: LambdaWorkerConfig): + nonlocal torn_down + config.worker_config["task_queue"] = "gen-queue" + try: + yield + finally: + torn_down = True + + handler = _run_worker_internal(TEST_VERSION, configure, deps) + with pytest.raises(RuntimeError, match="worker boom"): + handler({}, _make_lambda_context()) + assert torn_down + + def test_async_generator_resource_per_invocation(self) -> None: + """Each invocation builds and tears down its own resource instance. Tagging each + resource with a construction sequence number proves the instances are distinct + (open-1/close-1, then open-2/close-2) rather than one resource reopened.""" + events: list[str] = [] + counter = itertools.count(1) + deps = _make_test_deps() + + class FakeResource: + def __init__(self) -> None: + self.n = next(counter) + + async def __aenter__(self) -> FakeResource: + events.append(f"open-{self.n}") + return self + + async def __aexit__(self, *exc: Any) -> None: + events.append(f"close-{self.n}") + + async def configure(config: LambdaWorkerConfig): + config.worker_config["task_queue"] = "gen-queue" + async with FakeResource(): + yield + + handler = _run_worker_internal(TEST_VERSION, configure, deps) + handler({}, _make_lambda_context()) + handler({}, _make_lambda_context()) + assert events == ["open-1", "close-1", "open-2", "close-2"] + + def test_async_configure_validates_task_queue_per_invocation(self) -> None: + deps = _make_test_deps() + deps.getenv = lambda _: None # type: ignore[assignment] + + async def configure(_config: LambdaWorkerConfig) -> None: + pass + + handler = _run_worker_internal(TEST_VERSION, configure, deps) + with pytest.raises(ValueError, match="task queue not configured"): + handler({}, _make_lambda_context()) + + def test_asynccontextmanager_decorated_configure_supported(self) -> None: + """A @asynccontextmanager-decorated configure is entered and exited per invocation, + the same as a bare async generator.""" + events: list[str] = [] + deps = _make_test_deps() + + @asynccontextmanager + async def configure(config: LambdaWorkerConfig): + events.append("setup") + config.worker_config["task_queue"] = "gen-queue" + yield + events.append("teardown") + + handler = _run_worker_internal(TEST_VERSION, configure, deps) + handler({}, _make_lambda_context()) + assert events == ["setup", "teardown"] From 631ebaf0e20fb214b16589b45627b358048a5d77 Mon Sep 17 00:00:00 2001 From: tconley1428 Date: Thu, 18 Jun 2026 13:28:40 -0700 Subject: [PATCH 139/226] Add release preparation script (#1611) --- CHANGELOG.md | 13 +- CONTRIBUTING.md | 2 +- scripts/__init__.py | 1 + scripts/prepare_release.py | 235 ++++++++++++++++++++++++++++++++++ tests/test_prepare_release.py | 75 +++++++++++ 5 files changed, 322 insertions(+), 4 deletions(-) create mode 100644 scripts/__init__.py create mode 100644 scripts/prepare_release.py create mode 100644 tests/test_prepare_release.py diff --git a/CHANGELOG.md b/CHANGELOG.md index 0183a74a4..b6e993a85 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,9 +3,8 @@ High-level release notes. Loosely based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/). When your PR includes a user-facing change, add an entry below under the -appropriate heading (create the heading if it does not yet exist). Within -each heading content can be free-form. Feel free to include examples, links -to docs, or any other relevant information. +appropriate heading. Within each heading content can be free-form. Feel free +to include examples, links to docs, or any other relevant information. ### Added — new features ### Changed — changes in existing functionality @@ -19,12 +18,16 @@ to docs, or any other relevant information. ## [Unreleased] +### Added + ### Changed - AWS Lambda worker `configure` parameter supports sync, async, and async generator style functions. This callback is invoked on the asyncio event loop. +### Deprecated + ### Breaking Changes - AWS Lambda worker `configure` parameter has been changed to be invoked @@ -32,6 +35,10 @@ to docs, or any other relevant information. any shared, heavy-weight operations are performed outside of the callback before `run_worker` is invoked. +### Fixed + +### Security + ## [1.29.0] - 2026-06-17 ### Added diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 83b27f007..6096c5b2b 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -14,7 +14,7 @@ User-facing changes are recorded in [`CHANGELOG.md`](CHANGELOG.md), loosely foll If your PR includes a user-facing change (new feature, behavior change, deprecation, breaking change, notable bug fix, or security fix), add a short, high-level entry to the `## [Unreleased]` -section at the top of `CHANGELOG.md` under the appropriate heading, creating it if needed: +section at the top of `CHANGELOG.md` under the appropriate heading: Added, Changed, Deprecated, Breaking Changes, Fixed, or Security. Keep entries high-level and written for users. The full commit log is appended at release time, diff --git a/scripts/__init__.py b/scripts/__init__.py new file mode 100644 index 000000000..9f29c1099 --- /dev/null +++ b/scripts/__init__.py @@ -0,0 +1 @@ +"""Repository helper scripts.""" diff --git a/scripts/prepare_release.py b/scripts/prepare_release.py new file mode 100644 index 000000000..68f2ba39f --- /dev/null +++ b/scripts/prepare_release.py @@ -0,0 +1,235 @@ +"""Prepare checked-in files for an SDK release.""" + +from __future__ import annotations + +import argparse +import datetime +import pathlib +import re +import subprocess +import sys +from collections.abc import Sequence + +if __package__ is None or __package__ == "": + sys.path.insert(0, str(pathlib.Path(__file__).resolve().parents[1])) + +CHANGELOG_HEADERS = ( + "Added", + "Changed", + "Deprecated", + "Breaking Changes", + "Fixed", + "Security", +) +VERSION_RE = re.compile(r"[0-9]+(?:\.[0-9]+)+(?:[a-zA-Z0-9_.+-]+)?") +_CHANGELOG_HEADING_RE = re.compile(r"^## \[(?P[^\]]+)\](?:\s+-\s+.*)?\s*$") +_CHANGELOG_SUBHEADING_RE = re.compile(r"^### (?P
    .+?)\s*$") + + +def validate_version(version: str) -> str: + if not VERSION_RE.fullmatch(version): + raise ValueError( + f"Invalid version {version!r}; expected a version like '1.30.0'" + ) + return version + + +def parse_date(date: str) -> datetime.date: + try: + return datetime.date.fromisoformat(date) + except ValueError as err: + raise ValueError(f"Invalid release date {date!r}; expected YYYY-MM-DD") from err + + +def finalize_changelog_release( + text: str, + *, + version: str, + release_date: datetime.date, +) -> str: + validate_version(version) + lines = text.splitlines() + + if _find_version_section(lines, version) is not None: + raise RuntimeError(f"Changelog already has a section for {version!r}") + + unreleased = _find_version_section(lines, "Unreleased") + if unreleased is None: + raise RuntimeError("Could not find changelog section for 'Unreleased'") + + heading_index, section_start, section_end = unreleased + unreleased_lines = _strip_empty_changelog_headers( + _strip_outer_blank_lines(lines[section_start:section_end]) + ) + if not unreleased_lines: + raise RuntimeError("Changelog section for 'Unreleased' is empty") + + next_lines = [ + *lines[:heading_index], + *_seeded_unreleased_lines(), + f"## [{version}] - {release_date.isoformat()}", + "", + *unreleased_lines, + "", + *lines[section_end:], + ] + return "\n".join(_collapse_blank_lines(next_lines)).rstrip() + "\n" + + +def replace_project_version(text: str, version: str) -> str: + return _replace_once( + r'(?m)^version = "[^"]+"\s*$', + f'version = "{validate_version(version)}"', + text, + description="project version", + ) + + +def replace_service_version(text: str, version: str) -> str: + return _replace_once( + r'(?m)^__version__ = "[^"]+"\s*$', + f'__version__ = "{validate_version(version)}"', + text, + description="service version", + ) + + +def _seeded_unreleased_lines() -> list[str]: + lines = ["## [Unreleased]", ""] + for header in CHANGELOG_HEADERS: + lines.extend([f"### {header}", ""]) + return lines + + +def _strip_empty_changelog_headers(lines: list[str]) -> list[str]: + filtered: list[str] = [] + index = 0 + while index < len(lines): + match = _CHANGELOG_SUBHEADING_RE.match(lines[index]) + if not match or match.group("header") not in CHANGELOG_HEADERS: + filtered.append(lines[index]) + index += 1 + continue + + next_index = index + 1 + while next_index < len(lines) and not lines[next_index].startswith("### "): + next_index += 1 + + content = lines[index + 1 : next_index] + if any(line.strip() for line in content): + filtered.append(lines[index]) + filtered.extend(content) + index = next_index + + return _strip_outer_blank_lines(filtered) + + +def _find_version_section( + lines: list[str], + version: str, +) -> tuple[int, int, int] | None: + for index, line in enumerate(lines): + match = _CHANGELOG_HEADING_RE.match(line) + if match and match.group("version") == version: + section_end = len(lines) + for end_index in range(index + 1, len(lines)): + if lines[end_index].startswith("## "): + section_end = end_index + break + return index, index + 1, section_end + return None + + +def _strip_outer_blank_lines(lines: list[str]) -> list[str]: + while lines and not lines[0].strip(): + lines.pop(0) + while lines and not lines[-1].strip(): + lines.pop() + return lines + + +def _collapse_blank_lines(lines: list[str]) -> list[str]: + collapsed: list[str] = [] + previous_blank = False + for line in lines: + blank = not line.strip() + if blank and previous_blank: + continue + collapsed.append(line) + previous_blank = blank + return collapsed + + +def _replace_once( + pattern: str, + replacement: str, + text: str, + *, + description: str, +) -> str: + updated, count = re.subn(pattern, replacement, text, count=1) + if count != 1: + raise RuntimeError(f"Could not find {description}") + return updated.rstrip("\n") + + +def main(argv: Sequence[str] | None = None) -> None: + parser = argparse.ArgumentParser( + description=( + "Bump the SDK version, roll CHANGELOG.md's Unreleased section into " + "a dated release section, seed a fresh Unreleased section, and " + "refresh uv.lock." + ) + ) + parser.add_argument("version", help="Release version, for example 1.30.0") + parser.add_argument( + "--date", + default=datetime.date.today().isoformat(), + help="Release date in YYYY-MM-DD format. Defaults to today.", + ) + parser.add_argument( + "--skip-lock", + action="store_true", + help="Do not run 'uv lock'. Intended only for local testing.", + ) + args = parser.parse_args(argv) + + repo_root = pathlib.Path(__file__).resolve().parents[1] + version = validate_version(args.version) + release_date = parse_date(args.date) + changelog_path = repo_root / "CHANGELOG.md" + pyproject_path = repo_root / "pyproject.toml" + service_path = repo_root / "temporalio" / "service.py" + + changelog_text = finalize_changelog_release( + changelog_path.read_text(encoding="utf-8"), + version=version, + release_date=release_date, + ) + pyproject_text = ( + replace_project_version( + pyproject_path.read_text(encoding="utf-8"), + version, + ) + + "\n" + ) + service_text = ( + replace_service_version( + service_path.read_text(encoding="utf-8"), + version, + ) + + "\n" + ) + + changelog_path.write_text(changelog_text, encoding="utf-8") + pyproject_path.write_text(pyproject_text, encoding="utf-8") + service_path.write_text(service_text, encoding="utf-8") + + if not args.skip_lock: + subprocess.run(["uv", "lock"], cwd=repo_root, check=True) + + print(f"Prepared release {version} dated {release_date.isoformat()}") + + +if __name__ == "__main__": + main() diff --git a/tests/test_prepare_release.py b/tests/test_prepare_release.py new file mode 100644 index 000000000..07bdbd4a5 --- /dev/null +++ b/tests/test_prepare_release.py @@ -0,0 +1,75 @@ +from __future__ import annotations + +import datetime + +from scripts.prepare_release import ( + finalize_changelog_release, + replace_project_version, + replace_service_version, +) + + +def test_finalize_changelog_release_seeds_unreleased_and_versions_notes() -> None: + changelog = """# Changelog + +## [Unreleased] + +### Added + +### Changed + +- Changed a thing. + +### Fixed + +## [1.29.0] - 2026-06-17 + +### Added + +- Previous release. +""" + + updated = finalize_changelog_release( + changelog, + version="1.30.0", + release_date=datetime.date(2026, 6, 18), + ) + + assert updated.startswith( + """# Changelog + +## [Unreleased] + +### Added + +### Changed + +### Deprecated + +### Breaking Changes + +### Fixed + +### Security + +## [1.30.0] - 2026-06-18 + +### Changed + +- Changed a thing. +""" + ) + assert "### Added\n\n### Changed\n\n- Changed a thing." not in updated + + +def test_replace_versions() -> None: + assert ( + replace_project_version( + '[project]\nname = "temporalio"\nversion = "1.29.0"\n', "1.30.0" + ) + == '[project]\nname = "temporalio"\nversion = "1.30.0"' + ) + assert ( + replace_service_version('__version__ = "1.29.0"\n', "1.30.0") + == '__version__ = "1.30.0"' + ) From f129be7cfb3edbfd7ba63659e2f04f8226b301e0 Mon Sep 17 00:00:00 2001 From: tconley1428 Date: Mon, 22 Jun 2026 08:04:53 -0700 Subject: [PATCH 140/226] Allow protobuf 7 (#1610) * Allow protobuf 7 * Fix changelog placement --- .github/workflows/ci.yml | 1 + CHANGELOG.md | 2 ++ pyproject.toml | 6 ++--- scripts/_proto/Dockerfile | 1 + scripts/gen_payload_visitor.py | 29 ++++++++++++++++------ temporalio/converter/_failure_converter.py | 4 ++- tests/conftest.py | 5 ++-- tests/nexus/test_temporal_system_nexus.py | 27 +++++++++++++++----- tests/worker/test_command_aware_visitor.py | 4 +-- uv.lock | 20 +++++++-------- 10 files changed, 67 insertions(+), 32 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 2bdc06191..9218d2901 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -123,6 +123,7 @@ jobs: - uses: astral-sh/setup-uv@cec208311dfd045dd5311c1add060b2062131d57 # v8 - run: uv tool install poethepoet - run: uv remove google-adk --optional google-adk + - run: uv add --dev --python 3.10 "googleapis-common-protos==1.70.0" - run: uv add --python 3.10 "protobuf<4" - run: uv sync --all-extras - run: poe build-develop diff --git a/CHANGELOG.md b/CHANGELOG.md index b6e993a85..2fc6b902a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -25,6 +25,8 @@ to include examples, links to docs, or any other relevant information. - AWS Lambda worker `configure` parameter supports sync, async, and async generator style functions. This callback is invoked on the asyncio event loop. +- Relaxed the protobuf dependency bounds to allow protobuf 7 where compatible + with the selected optional dependencies. ### Deprecated diff --git a/pyproject.toml b/pyproject.toml index 299c03df9..6b1e9b736 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -10,9 +10,9 @@ license-files = ["LICENSE"] keywords = ["temporal", "workflow"] dependencies = [ "nexus-rpc==1.4.0", - "protobuf>=3.20,<7.0.0", + "protobuf>=3.20,<8.0.0", "python-dateutil>=2.8.2,<3 ; python_version < '3.11'", - "types-protobuf>=3.20,<7.0.0", + "types-protobuf>=3.20,<8.0.0", "typing-extensions>=4.2.0,<5", ] classifiers = [ @@ -74,7 +74,7 @@ dev = [ "openai-agents[litellm]>=0.14.0; python_version < '3.14'", "litellm>=1.83.0", "openinference-instrumentation-google-adk>=0.1.11", - "googleapis-common-protos==1.70.0", + "googleapis-common-protos>=1.75.0,<2", "pytest-rerunfailures>=16.1", "pytest-xdist>=3.6,<4", "moto[s3,server]>=5", diff --git a/scripts/_proto/Dockerfile b/scripts/_proto/Dockerfile index 2e2f58391..0bbe18bb3 100644 --- a/scripts/_proto/Dockerfile +++ b/scripts/_proto/Dockerfile @@ -9,6 +9,7 @@ COPY ./ ./ RUN mkdir -p ./temporalio/api RUN uv remove google-adk --optional google-adk +RUN uv add --dev "googleapis-common-protos==1.70.0" RUN uv add "protobuf<4" RUN uv sync --all-extras RUN uv run scripts/gen_protos.py diff --git a/scripts/gen_payload_visitor.py b/scripts/gen_payload_visitor.py index e3b988ca9..da1be23ea 100644 --- a/scripts/gen_payload_visitor.py +++ b/scripts/gen_payload_visitor.py @@ -56,6 +56,16 @@ def name_for(desc: Descriptor) -> str: return desc.full_name.replace(".", "_") +def field_is_repeated(field: FieldDescriptor) -> bool: + return bool( + getattr( + field, + "is_repeated", + getattr(field, "label") == FieldDescriptor.LABEL_REPEATED, + ) + ) + + def emit_loop( field_name: str, iter_expr: str, @@ -290,17 +300,16 @@ def walk(self, desc: Descriptor) -> bool: continue # Repeated fields (including maps which are represented as repeated messages) - if field.label == FieldDescriptor.LABEL_REPEATED: - if ( - field.message_type is not None - and field.message_type.GetOptions().map_entry - ): - val_fd = field.message_type.fields_by_name.get("value") + if field_is_repeated(field): + message_type = field.message_type + if message_type is not None and message_type.GetOptions().map_entry: + val_fd = message_type.fields_by_name.get("value") if ( val_fd is not None and val_fd.type == FieldDescriptor.TYPE_MESSAGE ): child_desc = val_fd.message_type + assert child_desc is not None child_needed = self.walk(child_desc) if child_needed: has_payload = True @@ -313,12 +322,13 @@ def walk(self, desc: Descriptor) -> bool: ) ) - key_fd = field.message_type.fields_by_name.get("key") + key_fd = message_type.fields_by_name.get("key") if ( key_fd is not None and key_fd.type == FieldDescriptor.TYPE_MESSAGE ): child_desc = key_fd.message_type + assert child_desc is not None child_needed = self.walk(child_desc) if child_needed: has_payload = True @@ -331,14 +341,16 @@ def walk(self, desc: Descriptor) -> bool: ) ) else: + assert message_type is not None item = self._collect_repeated( - field.message_type, field, f"o.{field.name}" + message_type, field, f"o.{field.name}" ) if item is not None: has_payload = True emit_items.append(item) else: child_desc = field.message_type + assert child_desc is not None child_has_payload = self.walk(child_desc) has_payload |= child_has_payload if child_has_payload: @@ -358,6 +370,7 @@ def walk(self, desc: Descriptor) -> bool: first = True for field in fields: child_desc = field.message_type + assert child_desc is not None child_has_payload = self.walk(child_desc) has_payload |= child_has_payload if child_has_payload: diff --git a/temporalio/converter/_failure_converter.py b/temporalio/converter/_failure_converter.py index b1511b0b0..c76f95c23 100644 --- a/temporalio/converter/_failure_converter.py +++ b/temporalio/converter/_failure_converter.py @@ -283,7 +283,9 @@ def _nexus_failure_to_temporal_failure( failure.metadata and failure.metadata.get("type") == _TEMPORAL_FAILURE_PROTO_TYPE ): - google.protobuf.json_format.ParseDict(failure.details, temporal_failure) + google.protobuf.json_format.ParseDict( + dict(failure.details or {}), temporal_failure + ) else: temporal_failure.application_failure_info.SetInParent() temporal_failure.application_failure_info.type = "NexusFailure" diff --git a/tests/conftest.py b/tests/conftest.py index 9eaa1ff47..19ac8721f 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -30,7 +30,7 @@ f"Expected {temporalio.__file__} to be in {sys.prefix}" ) -# Unless specifically overridden, we expect tests to run under protobuf 4.x/5.x lib +# Unless specifically overridden, we expect tests to run under protobuf 4.x/5.x/6.x/7.x lib import google.protobuf protobuf_version = google.protobuf.__version__ @@ -43,7 +43,8 @@ protobuf_version.startswith("4.") or protobuf_version.startswith("5.") or protobuf_version.startswith("6.") - ), f"Expected protobuf 4.x/5.x/6.x, got {protobuf_version}" + or protobuf_version.startswith("7.") + ), f"Expected protobuf 4.x/5.x/6.x/7.x, got {protobuf_version}" def pytest_runtest_setup(item): # type: ignore[reportMissingParameterType] diff --git a/tests/nexus/test_temporal_system_nexus.py b/tests/nexus/test_temporal_system_nexus.py index c7d9319ca..532cd4974 100644 --- a/tests/nexus/test_temporal_system_nexus.py +++ b/tests/nexus/test_temporal_system_nexus.py @@ -147,12 +147,13 @@ def _build_proto_sample(message_type: type[Message]) -> Message: def _populate_proto_sample(message: Message, *, path: str = "value") -> None: seen_oneofs: set[str] = set() - for field in message.DESCRIPTOR.fields: + for raw_field in message.DESCRIPTOR.fields: + field = cast(FieldDescriptor, raw_field) if field.containing_oneof is not None: if field.containing_oneof.name in seen_oneofs: continue seen_oneofs.add(field.containing_oneof.name) - if field.label == FieldDescriptor.LABEL_REPEATED: + if _field_is_repeated(field): if ( field.message_type is not None and field.message_type.GetOptions().map_entry @@ -186,8 +187,10 @@ def _populate_proto_map_entry( *, path: str, ) -> None: - key_field = field.message_type.fields_by_name["key"] - value_field = field.message_type.fields_by_name["value"] + message_type = field.message_type + assert message_type is not None + key_field = message_type.fields_by_name["key"] + value_field = message_type.fields_by_name["value"] key = _proto_scalar_sample(key_field, path=f"{path}.{field.name}.key") container = getattr(message, field.name) if value_field.cpp_type == FieldDescriptor.CPPTYPE_MESSAGE: @@ -222,13 +225,25 @@ def _proto_scalar_sample(field: FieldDescriptor, *, path: str) -> Any: ): return 1.5 if field.cpp_type == FieldDescriptor.CPPTYPE_ENUM: - for enum_value in field.enum_type.values: + enum_type = field.enum_type + assert enum_type is not None + for enum_value in enum_type.values: if enum_value.number != 0: return enum_value.number - return field.enum_type.values[0].number + return enum_type.values[0].number raise TypeError(f"Unhandled proto scalar sample at {path}: {field!r}") +def _field_is_repeated(field: FieldDescriptor) -> bool: + return bool( + getattr( + field, + "is_repeated", + getattr(field, "label") == FieldDescriptor.LABEL_REPEATED, + ) + ) + + @pytest.mark.parametrize( "message_type", [ diff --git a/tests/worker/test_command_aware_visitor.py b/tests/worker/test_command_aware_visitor.py index f354c8614..6e7da7963 100644 --- a/tests/worker/test_command_aware_visitor.py +++ b/tests/worker/test_command_aware_visitor.py @@ -78,11 +78,11 @@ def _get_workflow_command_protos_with_seq() -> Iterator[type[Any]]: """Get concrete classes of all workflow command protos with a seq field.""" for descriptor in workflow_commands_pb2.DESCRIPTOR.message_types_by_name.values(): if "seq" in descriptor.fields_by_name: - yield descriptor._concrete_class + yield getattr(descriptor, "_concrete_class") def _get_workflow_activation_job_protos_with_seq() -> Iterator[type[Any]]: """Get concrete classes of all workflow activation job protos with a seq field.""" for descriptor in workflow_activation_pb2.DESCRIPTOR.message_types_by_name.values(): if "seq" in descriptor.fields_by_name: - yield descriptor._concrete_class + yield getattr(descriptor, "_concrete_class") diff --git a/uv.lock b/uv.lock index 3e48e3df7..04fdec20e 100644 --- a/uv.lock +++ b/uv.lock @@ -9,7 +9,7 @@ resolution-markers = [ ] [options] -exclude-newer = "2026-06-01T18:36:48.998335583Z" +exclude-newer = "2026-06-04T17:08:08.645499Z" exclude-newer-span = "P2W" [options.exclude-newer-package] @@ -1812,14 +1812,14 @@ wheels = [ [[package]] name = "googleapis-common-protos" -version = "1.70.0" +version = "1.75.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "protobuf" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/39/24/33db22342cf4a2ea27c9955e6713140fedd51e8b141b5ce5260897020f1a/googleapis_common_protos-1.70.0.tar.gz", hash = "sha256:0e1b44e0ea153e6594f9f394fef15193a68aaaea2d843f83e2742717ca753257", size = 145903, upload-time = "2025-04-14T10:17:02.924Z" } +sdist = { url = "https://files.pythonhosted.org/packages/b5/c8/f439cffde755cffa462bfbb156278fa6f9d09119719af9814b858fd4f81f/googleapis_common_protos-1.75.0.tar.gz", hash = "sha256:53a062ff3c32552fbd62c11fe23768b78e4ddf0494d5e5fd97d3f4689c75fbbd", size = 151035, upload-time = "2026-05-07T08:04:49.423Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/86/f1/62a193f0227cf15a920390abe675f386dec35f7ae3ffe6da582d3ade42c7/googleapis_common_protos-1.70.0-py3-none-any.whl", hash = "sha256:b8bfcca8c25a2bb253e0e0b0adaf8c00773e5e6af6fd92397576680b807e0fd8", size = 294530, upload-time = "2025-04-14T10:17:01.271Z" }, + { 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] @@ -5520,12 +5520,12 @@ requires-dist = [ { name = "opentelemetry-sdk", marker = "extra == 'opentelemetry'", specifier = ">=1.11.1,<2" }, { name = "opentelemetry-sdk-extension-aws", marker = "extra == 'lambda-worker-otel'", specifier = ">=2.0.0,<3" }, { name = "opentelemetry-semantic-conventions", marker = "extra == 'lambda-worker-otel'", specifier = ">=0.40b0,<1" }, - { name = "protobuf", specifier = ">=3.20,<7.0.0" }, + { name = "protobuf", specifier = ">=3.20,<8.0.0" }, { name = "pydantic", marker = "extra == 'pydantic'", specifier = ">=2.0.0,<3" }, { name = "python-dateutil", marker = "python_full_version < '3.11'", specifier = ">=2.8.2,<3" }, { name = "strands-agents", marker = "extra == 'strands-agents'", specifier = ">=1.39.0" }, { name = "types-aioboto3", extras = ["s3"], marker = "extra == 'aioboto3'", specifier = ">=10.4.0" }, - { name = "types-protobuf", specifier = ">=3.20,<7.0.0" }, + { name = "types-protobuf", specifier = ">=3.20,<8.0.0" }, { name = "typing-extensions", specifier = ">=4.2.0,<5" }, ] provides-extras = ["grpc", "opentelemetry", "pydantic", "openai-agents", "google-adk", "langgraph", "langsmith", "lambda-worker-otel", "aioboto3", "strands-agents"] @@ -5535,7 +5535,7 @@ dev = [ { name = "async-timeout", marker = "python_full_version < '3.11'", specifier = ">=4.0,<6" }, { name = "basedpyright", specifier = "==1.34.0" }, { name = "cibuildwheel", specifier = ">=2.22.0,<3" }, - { name = "googleapis-common-protos", specifier = "==1.70.0" }, + { name = "googleapis-common-protos", specifier = ">=1.75.0,<2" }, { name = "grpcio-tools", specifier = ">=1.48.2,<2" }, { name = "httpx", specifier = ">=0.28.1" }, { name = "langgraph", specifier = ">=1.1.0" }, @@ -5856,11 +5856,11 @@ wheels = [ [[package]] name = "types-protobuf" -version = "6.32.1.20260221" +version = "7.34.1.20260518" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/5f/e2/9aa4a3b2469508bd7b4e2ae11cbedaf419222a09a1b94daffcd5efca4023/types_protobuf-6.32.1.20260221.tar.gz", hash = "sha256:6d5fb060a616bfb076cbb61b4b3c3969f5fc8bec5810f9a2f7e648ee5cbcbf6e", size = 64408, upload-time = "2026-02-21T03:55:13.916Z" } +sdist = { url = "https://files.pythonhosted.org/packages/29/59/e2b13b499d15e6720150c4b1a8d91e31fcacf716b432397475b3151ff7e4/types_protobuf-7.34.1.20260518.tar.gz", hash = "sha256:28cfaded25889cb83ebfb63cfb0a43628f0b6f3785767bec17287dc6468795f2", size = 68936, upload-time = "2026-05-18T06:01:47.332Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/2e/e8/1fd38926f9cf031188fbc5a96694203ea6f24b0e34bd64a225ec6f6291ba/types_protobuf-6.32.1.20260221-py3-none-any.whl", hash = "sha256:da7cdd947975964a93c30bfbcc2c6841ee646b318d3816b033adc2c4eb6448e4", size = 77956, upload-time = "2026-02-21T03:55:12.894Z" }, + { url = "https://files.pythonhosted.org/packages/2a/1f/ec5caf72c2e3b688ca3927e0979a04ddad19e1afc4bf1c199bd743e0f419/types_protobuf-7.34.1.20260518-py3-none-any.whl", hash = "sha256:a0a5337413347166439c0e07cbc26c6164d091401c6f01b1dfd8cdb966c4dd8f", size = 85992, upload-time = "2026-05-18T06:01:45.696Z" }, ] [[package]] From c37fa7e4682b8b38b5374ae72bc07f90db8a0c07 Mon Sep 17 00:00:00 2001 From: Brian Strauch Date: Mon, 22 Jun 2026 10:03:39 -0700 Subject: [PATCH 141/226] Propagate OTEL trace id across client-workflow boundary (#1601) The OTEL-aware OpenAI Agents interceptor propagated and seeded the OTEL span id but never the trace id, so the client-side root span and the workflow's reconstructed spans ended up in different traces. This made test_sdk_trace_to_otel_span_parenting flaky. Wire up the existing seed_trace_id so the workflow's root span reuses the caller's trace id. --- .../contrib/openai_agents/_otel_trace_interceptor.py | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/temporalio/contrib/openai_agents/_otel_trace_interceptor.py b/temporalio/contrib/openai_agents/_otel_trace_interceptor.py index 6b7bb3c1b..63f8f9d83 100644 --- a/temporalio/contrib/openai_agents/_otel_trace_interceptor.py +++ b/temporalio/contrib/openai_agents/_otel_trace_interceptor.py @@ -45,10 +45,11 @@ def header_contents(self) -> dict[str, Any]: otel_span = opentelemetry.trace.get_current_span() if otel_span and otel_span.get_span_context().is_valid: - otel_span_id = otel_span.get_span_context().span_id + span_context = otel_span.get_span_context() return { **super().header_contents(), - "otelSpanId": otel_span_id, + "otelSpanId": span_context.span_id, + "otelTraceId": span_context.trace_id, } else: return super().header_contents() @@ -63,6 +64,12 @@ def context_from_header( if span_info is None: return otel_span_id = span_info.get("otelSpanId") + otel_trace_id = span_info.get("otelTraceId") + + # Seed the trace id before the trace is reconstructed so the workflow's root + # OTEL span shares the caller's trace id rather than generating a new one. + if otel_trace_id and self._otel_id_generator: + self._otel_id_generator.seed_trace_id(otel_trace_id) # If only a trace was propagated from the caller, we need to seed for trace context if otel_span_id and self._otel_id_generator and span_info.get("spanId") is None: From b0b934fbfac7660e274cfd1844337838d17a2314 Mon Sep 17 00:00:00 2001 From: Spencer Judge Date: Wed, 24 Jun 2026 09:39:56 -0700 Subject: [PATCH 142/226] Expose continue-as-new backoff start interval (#1613) * Expose continue-as-new backoff start interval * Add changelog note --- CHANGELOG.md | 2 + temporalio/bridge/Cargo.lock | 2 + .../workflow_commands_pb2.py | 68 +++++++++---------- .../workflow_commands_pb2.pyi | 9 +++ temporalio/bridge/sdk-core | 2 +- temporalio/worker/_interceptor.py | 1 + temporalio/worker/_workflow_instance.py | 4 ++ temporalio/workflow/_context.py | 1 + temporalio/workflow/_workflow_ops.py | 9 +++ tests/worker/test_workflow.py | 14 ++++ 10 files changed, 77 insertions(+), 35 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2fc6b902a..b0075011c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,6 +20,8 @@ to include examples, links to docs, or any other relevant information. ### Added +- Exposed `backoff_start_interval` for continue-as-new, to allow the new workflow to start after a delay. + ### Changed - AWS Lambda worker `configure` parameter supports sync, async, and async diff --git a/temporalio/bridge/Cargo.lock b/temporalio/bridge/Cargo.lock index 8b37057f4..c3a0a9e72 100644 --- a/temporalio/bridge/Cargo.lock +++ b/temporalio/bridge/Cargo.lock @@ -2601,6 +2601,7 @@ dependencies = [ "prometheus", "prost", "prost-types", + "reqwest 0.12.28", "ringbuf", "serde", "serde_json", @@ -2690,6 +2691,7 @@ dependencies = [ "itertools", "lru", "mockall", + "opentelemetry-otlp", "parking_lot", "pid", "pin-project", diff --git a/temporalio/bridge/proto/workflow_commands/workflow_commands_pb2.py b/temporalio/bridge/proto/workflow_commands/workflow_commands_pb2.py index dd56fb25b..a82430744 100644 --- a/temporalio/bridge/proto/workflow_commands/workflow_commands_pb2.py +++ b/temporalio/bridge/proto/workflow_commands/workflow_commands_pb2.py @@ -42,7 +42,7 @@ ) DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile( - b'\n;temporal/sdk/core/workflow_commands/workflow_commands.proto\x12\x19\x63oresdk.workflow_commands\x1a\x1egoogle/protobuf/duration.proto\x1a\x1fgoogle/protobuf/timestamp.proto\x1a\x1bgoogle/protobuf/empty.proto\x1a$temporal/api/common/v1/message.proto\x1a$temporal/api/enums/v1/workflow.proto\x1a%temporal/api/failure/v1/message.proto\x1a\'temporal/api/sdk/v1/user_metadata.proto\x1a\x35temporal/sdk/core/child_workflow/child_workflow.proto\x1a#temporal/sdk/core/nexus/nexus.proto\x1a%temporal/sdk/core/common/common.proto"\xe5\x0f\n\x0fWorkflowCommand\x12\x38\n\ruser_metadata\x18\x64 \x01(\x0b\x32!.temporal.api.sdk.v1.UserMetadata\x12<\n\x0bstart_timer\x18\x01 \x01(\x0b\x32%.coresdk.workflow_commands.StartTimerH\x00\x12H\n\x11schedule_activity\x18\x02 \x01(\x0b\x32+.coresdk.workflow_commands.ScheduleActivityH\x00\x12\x42\n\x10respond_to_query\x18\x03 \x01(\x0b\x32&.coresdk.workflow_commands.QueryResultH\x00\x12S\n\x17request_cancel_activity\x18\x04 \x01(\x0b\x32\x30.coresdk.workflow_commands.RequestCancelActivityH\x00\x12>\n\x0c\x63\x61ncel_timer\x18\x05 \x01(\x0b\x32&.coresdk.workflow_commands.CancelTimerH\x00\x12[\n\x1b\x63omplete_workflow_execution\x18\x06 \x01(\x0b\x32\x34.coresdk.workflow_commands.CompleteWorkflowExecutionH\x00\x12S\n\x17\x66\x61il_workflow_execution\x18\x07 \x01(\x0b\x32\x30.coresdk.workflow_commands.FailWorkflowExecutionH\x00\x12g\n"continue_as_new_workflow_execution\x18\x08 \x01(\x0b\x32\x39.coresdk.workflow_commands.ContinueAsNewWorkflowExecutionH\x00\x12W\n\x19\x63\x61ncel_workflow_execution\x18\t \x01(\x0b\x32\x32.coresdk.workflow_commands.CancelWorkflowExecutionH\x00\x12\x45\n\x10set_patch_marker\x18\n \x01(\x0b\x32).coresdk.workflow_commands.SetPatchMarkerH\x00\x12`\n\x1estart_child_workflow_execution\x18\x0b \x01(\x0b\x32\x36.coresdk.workflow_commands.StartChildWorkflowExecutionH\x00\x12\x62\n\x1f\x63\x61ncel_child_workflow_execution\x18\x0c \x01(\x0b\x32\x37.coresdk.workflow_commands.CancelChildWorkflowExecutionH\x00\x12w\n*request_cancel_external_workflow_execution\x18\r \x01(\x0b\x32\x41.coresdk.workflow_commands.RequestCancelExternalWorkflowExecutionH\x00\x12h\n"signal_external_workflow_execution\x18\x0e \x01(\x0b\x32:.coresdk.workflow_commands.SignalExternalWorkflowExecutionH\x00\x12Q\n\x16\x63\x61ncel_signal_workflow\x18\x0f \x01(\x0b\x32/.coresdk.workflow_commands.CancelSignalWorkflowH\x00\x12S\n\x17schedule_local_activity\x18\x10 \x01(\x0b\x32\x30.coresdk.workflow_commands.ScheduleLocalActivityH\x00\x12^\n\x1drequest_cancel_local_activity\x18\x11 \x01(\x0b\x32\x35.coresdk.workflow_commands.RequestCancelLocalActivityH\x00\x12\x66\n!upsert_workflow_search_attributes\x18\x12 \x01(\x0b\x32\x39.coresdk.workflow_commands.UpsertWorkflowSearchAttributesH\x00\x12Y\n\x1amodify_workflow_properties\x18\x13 \x01(\x0b\x32\x33.coresdk.workflow_commands.ModifyWorkflowPropertiesH\x00\x12\x44\n\x0fupdate_response\x18\x14 \x01(\x0b\x32).coresdk.workflow_commands.UpdateResponseH\x00\x12U\n\x18schedule_nexus_operation\x18\x15 \x01(\x0b\x32\x31.coresdk.workflow_commands.ScheduleNexusOperationH\x00\x12`\n\x1erequest_cancel_nexus_operation\x18\x16 \x01(\x0b\x32\x36.coresdk.workflow_commands.RequestCancelNexusOperationH\x00\x42\t\n\x07variant"S\n\nStartTimer\x12\x0b\n\x03seq\x18\x01 \x01(\r\x12\x38\n\x15start_to_fire_timeout\x18\x02 \x01(\x0b\x32\x19.google.protobuf.Duration"\x1a\n\x0b\x43\x61ncelTimer\x12\x0b\n\x03seq\x18\x01 \x01(\r"\xb8\x06\n\x10ScheduleActivity\x12\x0b\n\x03seq\x18\x01 \x01(\r\x12\x13\n\x0b\x61\x63tivity_id\x18\x02 \x01(\t\x12\x15\n\ractivity_type\x18\x03 \x01(\t\x12\x12\n\ntask_queue\x18\x05 \x01(\t\x12I\n\x07headers\x18\x06 \x03(\x0b\x32\x38.coresdk.workflow_commands.ScheduleActivity.HeadersEntry\x12\x32\n\targuments\x18\x07 \x03(\x0b\x32\x1f.temporal.api.common.v1.Payload\x12<\n\x19schedule_to_close_timeout\x18\x08 \x01(\x0b\x32\x19.google.protobuf.Duration\x12<\n\x19schedule_to_start_timeout\x18\t \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x39\n\x16start_to_close_timeout\x18\n \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x34\n\x11heartbeat_timeout\x18\x0b \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x39\n\x0cretry_policy\x18\x0c \x01(\x0b\x32#.temporal.api.common.v1.RetryPolicy\x12N\n\x11\x63\x61ncellation_type\x18\r \x01(\x0e\x32\x33.coresdk.workflow_commands.ActivityCancellationType\x12\x1e\n\x16\x64o_not_eagerly_execute\x18\x0e \x01(\x08\x12;\n\x11versioning_intent\x18\x0f \x01(\x0e\x32 .coresdk.common.VersioningIntent\x12\x32\n\x08priority\x18\x10 \x01(\x0b\x32 .temporal.api.common.v1.Priority\x1aO\n\x0cHeadersEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12.\n\x05value\x18\x02 \x01(\x0b\x32\x1f.temporal.api.common.v1.Payload:\x02\x38\x01"\xee\x05\n\x15ScheduleLocalActivity\x12\x0b\n\x03seq\x18\x01 \x01(\r\x12\x13\n\x0b\x61\x63tivity_id\x18\x02 \x01(\t\x12\x15\n\ractivity_type\x18\x03 \x01(\t\x12\x0f\n\x07\x61ttempt\x18\x04 \x01(\r\x12:\n\x16original_schedule_time\x18\x05 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12N\n\x07headers\x18\x06 \x03(\x0b\x32=.coresdk.workflow_commands.ScheduleLocalActivity.HeadersEntry\x12\x32\n\targuments\x18\x07 \x03(\x0b\x32\x1f.temporal.api.common.v1.Payload\x12<\n\x19schedule_to_close_timeout\x18\x08 \x01(\x0b\x32\x19.google.protobuf.Duration\x12<\n\x19schedule_to_start_timeout\x18\t \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x39\n\x16start_to_close_timeout\x18\n \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x39\n\x0cretry_policy\x18\x0b \x01(\x0b\x32#.temporal.api.common.v1.RetryPolicy\x12\x38\n\x15local_retry_threshold\x18\x0c \x01(\x0b\x32\x19.google.protobuf.Duration\x12N\n\x11\x63\x61ncellation_type\x18\r \x01(\x0e\x32\x33.coresdk.workflow_commands.ActivityCancellationType\x1aO\n\x0cHeadersEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12.\n\x05value\x18\x02 \x01(\x0b\x32\x1f.temporal.api.common.v1.Payload:\x02\x38\x01"$\n\x15RequestCancelActivity\x12\x0b\n\x03seq\x18\x01 \x01(\r")\n\x1aRequestCancelLocalActivity\x12\x0b\n\x03seq\x18\x01 \x01(\r"\x9c\x01\n\x0bQueryResult\x12\x10\n\x08query_id\x18\x01 \x01(\t\x12<\n\tsucceeded\x18\x02 \x01(\x0b\x32\'.coresdk.workflow_commands.QuerySuccessH\x00\x12\x32\n\x06\x66\x61iled\x18\x03 \x01(\x0b\x32 .temporal.api.failure.v1.FailureH\x00\x42\t\n\x07variant"A\n\x0cQuerySuccess\x12\x31\n\x08response\x18\x01 \x01(\x0b\x32\x1f.temporal.api.common.v1.Payload"L\n\x19\x43ompleteWorkflowExecution\x12/\n\x06result\x18\x01 \x01(\x0b\x32\x1f.temporal.api.common.v1.Payload"J\n\x15\x46\x61ilWorkflowExecution\x12\x31\n\x07\x66\x61ilure\x18\x01 \x01(\x0b\x32 .temporal.api.failure.v1.Failure"\xd7\x06\n\x1e\x43ontinueAsNewWorkflowExecution\x12\x15\n\rworkflow_type\x18\x01 \x01(\t\x12\x12\n\ntask_queue\x18\x02 \x01(\t\x12\x32\n\targuments\x18\x03 \x03(\x0b\x32\x1f.temporal.api.common.v1.Payload\x12\x37\n\x14workflow_run_timeout\x18\x04 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x38\n\x15workflow_task_timeout\x18\x05 \x01(\x0b\x32\x19.google.protobuf.Duration\x12Q\n\x04memo\x18\x06 \x03(\x0b\x32\x43.coresdk.workflow_commands.ContinueAsNewWorkflowExecution.MemoEntry\x12W\n\x07headers\x18\x07 \x03(\x0b\x32\x46.coresdk.workflow_commands.ContinueAsNewWorkflowExecution.HeadersEntry\x12\x43\n\x11search_attributes\x18\x08 \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes\x12\x39\n\x0cretry_policy\x18\t \x01(\x0b\x32#.temporal.api.common.v1.RetryPolicy\x12;\n\x11versioning_intent\x18\n \x01(\x0e\x32 .coresdk.common.VersioningIntent\x12[\n\x1binitial_versioning_behavior\x18\x0b \x01(\x0e\x32\x36.temporal.api.enums.v1.ContinueAsNewVersioningBehavior\x1aL\n\tMemoEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12.\n\x05value\x18\x02 \x01(\x0b\x32\x1f.temporal.api.common.v1.Payload:\x02\x38\x01\x1aO\n\x0cHeadersEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12.\n\x05value\x18\x02 \x01(\x0b\x32\x1f.temporal.api.common.v1.Payload:\x02\x38\x01"\x19\n\x17\x43\x61ncelWorkflowExecution"6\n\x0eSetPatchMarker\x12\x10\n\x08patch_id\x18\x01 \x01(\t\x12\x12\n\ndeprecated\x18\x02 \x01(\x08"\x96\t\n\x1bStartChildWorkflowExecution\x12\x0b\n\x03seq\x18\x01 \x01(\r\x12\x11\n\tnamespace\x18\x02 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x03 \x01(\t\x12\x15\n\rworkflow_type\x18\x04 \x01(\t\x12\x12\n\ntask_queue\x18\x05 \x01(\t\x12.\n\x05input\x18\x06 \x03(\x0b\x32\x1f.temporal.api.common.v1.Payload\x12=\n\x1aworkflow_execution_timeout\x18\x07 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x37\n\x14workflow_run_timeout\x18\x08 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x38\n\x15workflow_task_timeout\x18\t \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x46\n\x13parent_close_policy\x18\n \x01(\x0e\x32).coresdk.child_workflow.ParentClosePolicy\x12N\n\x18workflow_id_reuse_policy\x18\x0c \x01(\x0e\x32,.temporal.api.enums.v1.WorkflowIdReusePolicy\x12\x39\n\x0cretry_policy\x18\r \x01(\x0b\x32#.temporal.api.common.v1.RetryPolicy\x12\x15\n\rcron_schedule\x18\x0e \x01(\t\x12T\n\x07headers\x18\x0f \x03(\x0b\x32\x43.coresdk.workflow_commands.StartChildWorkflowExecution.HeadersEntry\x12N\n\x04memo\x18\x10 \x03(\x0b\x32@.coresdk.workflow_commands.StartChildWorkflowExecution.MemoEntry\x12\x43\n\x11search_attributes\x18\x11 \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes\x12P\n\x11\x63\x61ncellation_type\x18\x12 \x01(\x0e\x32\x35.coresdk.child_workflow.ChildWorkflowCancellationType\x12;\n\x11versioning_intent\x18\x13 \x01(\x0e\x32 .coresdk.common.VersioningIntent\x12\x32\n\x08priority\x18\x14 \x01(\x0b\x32 .temporal.api.common.v1.Priority\x1aO\n\x0cHeadersEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12.\n\x05value\x18\x02 \x01(\x0b\x32\x1f.temporal.api.common.v1.Payload:\x02\x38\x01\x1aL\n\tMemoEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12.\n\x05value\x18\x02 \x01(\x0b\x32\x1f.temporal.api.common.v1.Payload:\x02\x38\x01"J\n\x1c\x43\x61ncelChildWorkflowExecution\x12\x1a\n\x12\x63hild_workflow_seq\x18\x01 \x01(\r\x12\x0e\n\x06reason\x18\x02 \x01(\t"\x8e\x01\n&RequestCancelExternalWorkflowExecution\x12\x0b\n\x03seq\x18\x01 \x01(\r\x12G\n\x12workflow_execution\x18\x02 \x01(\x0b\x32+.coresdk.common.NamespacedWorkflowExecution\x12\x0e\n\x06reason\x18\x03 \x01(\t"\x8f\x03\n\x1fSignalExternalWorkflowExecution\x12\x0b\n\x03seq\x18\x01 \x01(\r\x12I\n\x12workflow_execution\x18\x02 \x01(\x0b\x32+.coresdk.common.NamespacedWorkflowExecutionH\x00\x12\x1b\n\x11\x63hild_workflow_id\x18\x03 \x01(\tH\x00\x12\x13\n\x0bsignal_name\x18\x04 \x01(\t\x12-\n\x04\x61rgs\x18\x05 \x03(\x0b\x32\x1f.temporal.api.common.v1.Payload\x12X\n\x07headers\x18\x06 \x03(\x0b\x32G.coresdk.workflow_commands.SignalExternalWorkflowExecution.HeadersEntry\x1aO\n\x0cHeadersEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12.\n\x05value\x18\x02 \x01(\x0b\x32\x1f.temporal.api.common.v1.Payload:\x02\x38\x01\x42\x08\n\x06target"#\n\x14\x43\x61ncelSignalWorkflow\x12\x0b\n\x03seq\x18\x01 \x01(\r"e\n\x1eUpsertWorkflowSearchAttributes\x12\x43\n\x11search_attributes\x18\x01 \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes"O\n\x18ModifyWorkflowProperties\x12\x33\n\rupserted_memo\x18\x01 \x01(\x0b\x32\x1c.temporal.api.common.v1.Memo"\xd2\x01\n\x0eUpdateResponse\x12\x1c\n\x14protocol_instance_id\x18\x01 \x01(\t\x12*\n\x08\x61\x63\x63\x65pted\x18\x02 \x01(\x0b\x32\x16.google.protobuf.EmptyH\x00\x12\x34\n\x08rejected\x18\x03 \x01(\x0b\x32 .temporal.api.failure.v1.FailureH\x00\x12\x34\n\tcompleted\x18\x04 \x01(\x0b\x32\x1f.temporal.api.common.v1.PayloadH\x00\x42\n\n\x08response"\x9a\x04\n\x16ScheduleNexusOperation\x12\x0b\n\x03seq\x18\x01 \x01(\r\x12\x10\n\x08\x65ndpoint\x18\x02 \x01(\t\x12\x0f\n\x07service\x18\x03 \x01(\t\x12\x11\n\toperation\x18\x04 \x01(\t\x12.\n\x05input\x18\x05 \x01(\x0b\x32\x1f.temporal.api.common.v1.Payload\x12<\n\x19schedule_to_close_timeout\x18\x06 \x01(\x0b\x32\x19.google.protobuf.Duration\x12X\n\x0cnexus_header\x18\x07 \x03(\x0b\x32\x42.coresdk.workflow_commands.ScheduleNexusOperation.NexusHeaderEntry\x12H\n\x11\x63\x61ncellation_type\x18\x08 \x01(\x0e\x32-.coresdk.nexus.NexusOperationCancellationType\x12<\n\x19schedule_to_start_timeout\x18\t \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x39\n\x16start_to_close_timeout\x18\n \x01(\x0b\x32\x19.google.protobuf.Duration\x1a\x32\n\x10NexusHeaderEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01"*\n\x1bRequestCancelNexusOperation\x12\x0b\n\x03seq\x18\x01 \x01(\r*X\n\x18\x41\x63tivityCancellationType\x12\x0e\n\nTRY_CANCEL\x10\x00\x12\x1f\n\x1bWAIT_CANCELLATION_COMPLETED\x10\x01\x12\x0b\n\x07\x41\x42\x41NDON\x10\x02\x42\x36\xea\x02\x33Temporalio::Internal::Bridge::Api::WorkflowCommandsb\x06proto3' + b'\n;temporal/sdk/core/workflow_commands/workflow_commands.proto\x12\x19\x63oresdk.workflow_commands\x1a\x1egoogle/protobuf/duration.proto\x1a\x1fgoogle/protobuf/timestamp.proto\x1a\x1bgoogle/protobuf/empty.proto\x1a$temporal/api/common/v1/message.proto\x1a$temporal/api/enums/v1/workflow.proto\x1a%temporal/api/failure/v1/message.proto\x1a\'temporal/api/sdk/v1/user_metadata.proto\x1a\x35temporal/sdk/core/child_workflow/child_workflow.proto\x1a#temporal/sdk/core/nexus/nexus.proto\x1a%temporal/sdk/core/common/common.proto"\xe5\x0f\n\x0fWorkflowCommand\x12\x38\n\ruser_metadata\x18\x64 \x01(\x0b\x32!.temporal.api.sdk.v1.UserMetadata\x12<\n\x0bstart_timer\x18\x01 \x01(\x0b\x32%.coresdk.workflow_commands.StartTimerH\x00\x12H\n\x11schedule_activity\x18\x02 \x01(\x0b\x32+.coresdk.workflow_commands.ScheduleActivityH\x00\x12\x42\n\x10respond_to_query\x18\x03 \x01(\x0b\x32&.coresdk.workflow_commands.QueryResultH\x00\x12S\n\x17request_cancel_activity\x18\x04 \x01(\x0b\x32\x30.coresdk.workflow_commands.RequestCancelActivityH\x00\x12>\n\x0c\x63\x61ncel_timer\x18\x05 \x01(\x0b\x32&.coresdk.workflow_commands.CancelTimerH\x00\x12[\n\x1b\x63omplete_workflow_execution\x18\x06 \x01(\x0b\x32\x34.coresdk.workflow_commands.CompleteWorkflowExecutionH\x00\x12S\n\x17\x66\x61il_workflow_execution\x18\x07 \x01(\x0b\x32\x30.coresdk.workflow_commands.FailWorkflowExecutionH\x00\x12g\n"continue_as_new_workflow_execution\x18\x08 \x01(\x0b\x32\x39.coresdk.workflow_commands.ContinueAsNewWorkflowExecutionH\x00\x12W\n\x19\x63\x61ncel_workflow_execution\x18\t \x01(\x0b\x32\x32.coresdk.workflow_commands.CancelWorkflowExecutionH\x00\x12\x45\n\x10set_patch_marker\x18\n \x01(\x0b\x32).coresdk.workflow_commands.SetPatchMarkerH\x00\x12`\n\x1estart_child_workflow_execution\x18\x0b \x01(\x0b\x32\x36.coresdk.workflow_commands.StartChildWorkflowExecutionH\x00\x12\x62\n\x1f\x63\x61ncel_child_workflow_execution\x18\x0c \x01(\x0b\x32\x37.coresdk.workflow_commands.CancelChildWorkflowExecutionH\x00\x12w\n*request_cancel_external_workflow_execution\x18\r \x01(\x0b\x32\x41.coresdk.workflow_commands.RequestCancelExternalWorkflowExecutionH\x00\x12h\n"signal_external_workflow_execution\x18\x0e \x01(\x0b\x32:.coresdk.workflow_commands.SignalExternalWorkflowExecutionH\x00\x12Q\n\x16\x63\x61ncel_signal_workflow\x18\x0f \x01(\x0b\x32/.coresdk.workflow_commands.CancelSignalWorkflowH\x00\x12S\n\x17schedule_local_activity\x18\x10 \x01(\x0b\x32\x30.coresdk.workflow_commands.ScheduleLocalActivityH\x00\x12^\n\x1drequest_cancel_local_activity\x18\x11 \x01(\x0b\x32\x35.coresdk.workflow_commands.RequestCancelLocalActivityH\x00\x12\x66\n!upsert_workflow_search_attributes\x18\x12 \x01(\x0b\x32\x39.coresdk.workflow_commands.UpsertWorkflowSearchAttributesH\x00\x12Y\n\x1amodify_workflow_properties\x18\x13 \x01(\x0b\x32\x33.coresdk.workflow_commands.ModifyWorkflowPropertiesH\x00\x12\x44\n\x0fupdate_response\x18\x14 \x01(\x0b\x32).coresdk.workflow_commands.UpdateResponseH\x00\x12U\n\x18schedule_nexus_operation\x18\x15 \x01(\x0b\x32\x31.coresdk.workflow_commands.ScheduleNexusOperationH\x00\x12`\n\x1erequest_cancel_nexus_operation\x18\x16 \x01(\x0b\x32\x36.coresdk.workflow_commands.RequestCancelNexusOperationH\x00\x42\t\n\x07variant"S\n\nStartTimer\x12\x0b\n\x03seq\x18\x01 \x01(\r\x12\x38\n\x15start_to_fire_timeout\x18\x02 \x01(\x0b\x32\x19.google.protobuf.Duration"\x1a\n\x0b\x43\x61ncelTimer\x12\x0b\n\x03seq\x18\x01 \x01(\r"\xb8\x06\n\x10ScheduleActivity\x12\x0b\n\x03seq\x18\x01 \x01(\r\x12\x13\n\x0b\x61\x63tivity_id\x18\x02 \x01(\t\x12\x15\n\ractivity_type\x18\x03 \x01(\t\x12\x12\n\ntask_queue\x18\x05 \x01(\t\x12I\n\x07headers\x18\x06 \x03(\x0b\x32\x38.coresdk.workflow_commands.ScheduleActivity.HeadersEntry\x12\x32\n\targuments\x18\x07 \x03(\x0b\x32\x1f.temporal.api.common.v1.Payload\x12<\n\x19schedule_to_close_timeout\x18\x08 \x01(\x0b\x32\x19.google.protobuf.Duration\x12<\n\x19schedule_to_start_timeout\x18\t \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x39\n\x16start_to_close_timeout\x18\n \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x34\n\x11heartbeat_timeout\x18\x0b \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x39\n\x0cretry_policy\x18\x0c \x01(\x0b\x32#.temporal.api.common.v1.RetryPolicy\x12N\n\x11\x63\x61ncellation_type\x18\r \x01(\x0e\x32\x33.coresdk.workflow_commands.ActivityCancellationType\x12\x1e\n\x16\x64o_not_eagerly_execute\x18\x0e \x01(\x08\x12;\n\x11versioning_intent\x18\x0f \x01(\x0e\x32 .coresdk.common.VersioningIntent\x12\x32\n\x08priority\x18\x10 \x01(\x0b\x32 .temporal.api.common.v1.Priority\x1aO\n\x0cHeadersEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12.\n\x05value\x18\x02 \x01(\x0b\x32\x1f.temporal.api.common.v1.Payload:\x02\x38\x01"\xee\x05\n\x15ScheduleLocalActivity\x12\x0b\n\x03seq\x18\x01 \x01(\r\x12\x13\n\x0b\x61\x63tivity_id\x18\x02 \x01(\t\x12\x15\n\ractivity_type\x18\x03 \x01(\t\x12\x0f\n\x07\x61ttempt\x18\x04 \x01(\r\x12:\n\x16original_schedule_time\x18\x05 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12N\n\x07headers\x18\x06 \x03(\x0b\x32=.coresdk.workflow_commands.ScheduleLocalActivity.HeadersEntry\x12\x32\n\targuments\x18\x07 \x03(\x0b\x32\x1f.temporal.api.common.v1.Payload\x12<\n\x19schedule_to_close_timeout\x18\x08 \x01(\x0b\x32\x19.google.protobuf.Duration\x12<\n\x19schedule_to_start_timeout\x18\t \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x39\n\x16start_to_close_timeout\x18\n \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x39\n\x0cretry_policy\x18\x0b \x01(\x0b\x32#.temporal.api.common.v1.RetryPolicy\x12\x38\n\x15local_retry_threshold\x18\x0c \x01(\x0b\x32\x19.google.protobuf.Duration\x12N\n\x11\x63\x61ncellation_type\x18\r \x01(\x0e\x32\x33.coresdk.workflow_commands.ActivityCancellationType\x1aO\n\x0cHeadersEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12.\n\x05value\x18\x02 \x01(\x0b\x32\x1f.temporal.api.common.v1.Payload:\x02\x38\x01"$\n\x15RequestCancelActivity\x12\x0b\n\x03seq\x18\x01 \x01(\r")\n\x1aRequestCancelLocalActivity\x12\x0b\n\x03seq\x18\x01 \x01(\r"\x9c\x01\n\x0bQueryResult\x12\x10\n\x08query_id\x18\x01 \x01(\t\x12<\n\tsucceeded\x18\x02 \x01(\x0b\x32\'.coresdk.workflow_commands.QuerySuccessH\x00\x12\x32\n\x06\x66\x61iled\x18\x03 \x01(\x0b\x32 .temporal.api.failure.v1.FailureH\x00\x42\t\n\x07variant"A\n\x0cQuerySuccess\x12\x31\n\x08response\x18\x01 \x01(\x0b\x32\x1f.temporal.api.common.v1.Payload"L\n\x19\x43ompleteWorkflowExecution\x12/\n\x06result\x18\x01 \x01(\x0b\x32\x1f.temporal.api.common.v1.Payload"J\n\x15\x46\x61ilWorkflowExecution\x12\x31\n\x07\x66\x61ilure\x18\x01 \x01(\x0b\x32 .temporal.api.failure.v1.Failure"\x92\x07\n\x1e\x43ontinueAsNewWorkflowExecution\x12\x15\n\rworkflow_type\x18\x01 \x01(\t\x12\x12\n\ntask_queue\x18\x02 \x01(\t\x12\x32\n\targuments\x18\x03 \x03(\x0b\x32\x1f.temporal.api.common.v1.Payload\x12\x37\n\x14workflow_run_timeout\x18\x04 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x38\n\x15workflow_task_timeout\x18\x05 \x01(\x0b\x32\x19.google.protobuf.Duration\x12Q\n\x04memo\x18\x06 \x03(\x0b\x32\x43.coresdk.workflow_commands.ContinueAsNewWorkflowExecution.MemoEntry\x12W\n\x07headers\x18\x07 \x03(\x0b\x32\x46.coresdk.workflow_commands.ContinueAsNewWorkflowExecution.HeadersEntry\x12\x43\n\x11search_attributes\x18\x08 \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes\x12\x39\n\x0cretry_policy\x18\t \x01(\x0b\x32#.temporal.api.common.v1.RetryPolicy\x12;\n\x11versioning_intent\x18\n \x01(\x0e\x32 .coresdk.common.VersioningIntent\x12[\n\x1binitial_versioning_behavior\x18\x0b \x01(\x0e\x32\x36.temporal.api.enums.v1.ContinueAsNewVersioningBehavior\x12\x39\n\x16\x62\x61\x63koff_start_interval\x18\x0c \x01(\x0b\x32\x19.google.protobuf.Duration\x1aL\n\tMemoEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12.\n\x05value\x18\x02 \x01(\x0b\x32\x1f.temporal.api.common.v1.Payload:\x02\x38\x01\x1aO\n\x0cHeadersEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12.\n\x05value\x18\x02 \x01(\x0b\x32\x1f.temporal.api.common.v1.Payload:\x02\x38\x01"\x19\n\x17\x43\x61ncelWorkflowExecution"6\n\x0eSetPatchMarker\x12\x10\n\x08patch_id\x18\x01 \x01(\t\x12\x12\n\ndeprecated\x18\x02 \x01(\x08"\x96\t\n\x1bStartChildWorkflowExecution\x12\x0b\n\x03seq\x18\x01 \x01(\r\x12\x11\n\tnamespace\x18\x02 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x03 \x01(\t\x12\x15\n\rworkflow_type\x18\x04 \x01(\t\x12\x12\n\ntask_queue\x18\x05 \x01(\t\x12.\n\x05input\x18\x06 \x03(\x0b\x32\x1f.temporal.api.common.v1.Payload\x12=\n\x1aworkflow_execution_timeout\x18\x07 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x37\n\x14workflow_run_timeout\x18\x08 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x38\n\x15workflow_task_timeout\x18\t \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x46\n\x13parent_close_policy\x18\n \x01(\x0e\x32).coresdk.child_workflow.ParentClosePolicy\x12N\n\x18workflow_id_reuse_policy\x18\x0c \x01(\x0e\x32,.temporal.api.enums.v1.WorkflowIdReusePolicy\x12\x39\n\x0cretry_policy\x18\r \x01(\x0b\x32#.temporal.api.common.v1.RetryPolicy\x12\x15\n\rcron_schedule\x18\x0e \x01(\t\x12T\n\x07headers\x18\x0f \x03(\x0b\x32\x43.coresdk.workflow_commands.StartChildWorkflowExecution.HeadersEntry\x12N\n\x04memo\x18\x10 \x03(\x0b\x32@.coresdk.workflow_commands.StartChildWorkflowExecution.MemoEntry\x12\x43\n\x11search_attributes\x18\x11 \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes\x12P\n\x11\x63\x61ncellation_type\x18\x12 \x01(\x0e\x32\x35.coresdk.child_workflow.ChildWorkflowCancellationType\x12;\n\x11versioning_intent\x18\x13 \x01(\x0e\x32 .coresdk.common.VersioningIntent\x12\x32\n\x08priority\x18\x14 \x01(\x0b\x32 .temporal.api.common.v1.Priority\x1aO\n\x0cHeadersEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12.\n\x05value\x18\x02 \x01(\x0b\x32\x1f.temporal.api.common.v1.Payload:\x02\x38\x01\x1aL\n\tMemoEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12.\n\x05value\x18\x02 \x01(\x0b\x32\x1f.temporal.api.common.v1.Payload:\x02\x38\x01"J\n\x1c\x43\x61ncelChildWorkflowExecution\x12\x1a\n\x12\x63hild_workflow_seq\x18\x01 \x01(\r\x12\x0e\n\x06reason\x18\x02 \x01(\t"\x8e\x01\n&RequestCancelExternalWorkflowExecution\x12\x0b\n\x03seq\x18\x01 \x01(\r\x12G\n\x12workflow_execution\x18\x02 \x01(\x0b\x32+.coresdk.common.NamespacedWorkflowExecution\x12\x0e\n\x06reason\x18\x03 \x01(\t"\x8f\x03\n\x1fSignalExternalWorkflowExecution\x12\x0b\n\x03seq\x18\x01 \x01(\r\x12I\n\x12workflow_execution\x18\x02 \x01(\x0b\x32+.coresdk.common.NamespacedWorkflowExecutionH\x00\x12\x1b\n\x11\x63hild_workflow_id\x18\x03 \x01(\tH\x00\x12\x13\n\x0bsignal_name\x18\x04 \x01(\t\x12-\n\x04\x61rgs\x18\x05 \x03(\x0b\x32\x1f.temporal.api.common.v1.Payload\x12X\n\x07headers\x18\x06 \x03(\x0b\x32G.coresdk.workflow_commands.SignalExternalWorkflowExecution.HeadersEntry\x1aO\n\x0cHeadersEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12.\n\x05value\x18\x02 \x01(\x0b\x32\x1f.temporal.api.common.v1.Payload:\x02\x38\x01\x42\x08\n\x06target"#\n\x14\x43\x61ncelSignalWorkflow\x12\x0b\n\x03seq\x18\x01 \x01(\r"e\n\x1eUpsertWorkflowSearchAttributes\x12\x43\n\x11search_attributes\x18\x01 \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes"O\n\x18ModifyWorkflowProperties\x12\x33\n\rupserted_memo\x18\x01 \x01(\x0b\x32\x1c.temporal.api.common.v1.Memo"\xd2\x01\n\x0eUpdateResponse\x12\x1c\n\x14protocol_instance_id\x18\x01 \x01(\t\x12*\n\x08\x61\x63\x63\x65pted\x18\x02 \x01(\x0b\x32\x16.google.protobuf.EmptyH\x00\x12\x34\n\x08rejected\x18\x03 \x01(\x0b\x32 .temporal.api.failure.v1.FailureH\x00\x12\x34\n\tcompleted\x18\x04 \x01(\x0b\x32\x1f.temporal.api.common.v1.PayloadH\x00\x42\n\n\x08response"\x9a\x04\n\x16ScheduleNexusOperation\x12\x0b\n\x03seq\x18\x01 \x01(\r\x12\x10\n\x08\x65ndpoint\x18\x02 \x01(\t\x12\x0f\n\x07service\x18\x03 \x01(\t\x12\x11\n\toperation\x18\x04 \x01(\t\x12.\n\x05input\x18\x05 \x01(\x0b\x32\x1f.temporal.api.common.v1.Payload\x12<\n\x19schedule_to_close_timeout\x18\x06 \x01(\x0b\x32\x19.google.protobuf.Duration\x12X\n\x0cnexus_header\x18\x07 \x03(\x0b\x32\x42.coresdk.workflow_commands.ScheduleNexusOperation.NexusHeaderEntry\x12H\n\x11\x63\x61ncellation_type\x18\x08 \x01(\x0e\x32-.coresdk.nexus.NexusOperationCancellationType\x12<\n\x19schedule_to_start_timeout\x18\t \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x39\n\x16start_to_close_timeout\x18\n \x01(\x0b\x32\x19.google.protobuf.Duration\x1a\x32\n\x10NexusHeaderEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01"*\n\x1bRequestCancelNexusOperation\x12\x0b\n\x03seq\x18\x01 \x01(\r*X\n\x18\x41\x63tivityCancellationType\x12\x0e\n\nTRY_CANCEL\x10\x00\x12\x1f\n\x1bWAIT_CANCELLATION_COMPLETED\x10\x01\x12\x0b\n\x07\x41\x42\x41NDON\x10\x02\x42\x36\xea\x02\x33Temporalio::Internal::Bridge::Api::WorkflowCommandsb\x06proto3' ) _ACTIVITYCANCELLATIONTYPE = DESCRIPTOR.enum_types_by_name["ActivityCancellationType"] @@ -481,8 +481,8 @@ _SIGNALEXTERNALWORKFLOWEXECUTION_HEADERSENTRY._serialized_options = b"8\001" _SCHEDULENEXUSOPERATION_NEXUSHEADERENTRY._options = None _SCHEDULENEXUSOPERATION_NEXUSHEADERENTRY._serialized_options = b"8\001" - _ACTIVITYCANCELLATIONTYPE._serialized_start = 8409 - _ACTIVITYCANCELLATIONTYPE._serialized_end = 8497 + _ACTIVITYCANCELLATIONTYPE._serialized_start = 8468 + _ACTIVITYCANCELLATIONTYPE._serialized_end = 8556 _WORKFLOWCOMMAND._serialized_start = 472 _WORKFLOWCOMMAND._serialized_end = 2493 _STARTTIMER._serialized_start = 2495 @@ -510,41 +510,41 @@ _FAILWORKFLOWEXECUTION._serialized_start = 4573 _FAILWORKFLOWEXECUTION._serialized_end = 4647 _CONTINUEASNEWWORKFLOWEXECUTION._serialized_start = 4650 - _CONTINUEASNEWWORKFLOWEXECUTION._serialized_end = 5505 - _CONTINUEASNEWWORKFLOWEXECUTION_MEMOENTRY._serialized_start = 5348 - _CONTINUEASNEWWORKFLOWEXECUTION_MEMOENTRY._serialized_end = 5424 + _CONTINUEASNEWWORKFLOWEXECUTION._serialized_end = 5564 + _CONTINUEASNEWWORKFLOWEXECUTION_MEMOENTRY._serialized_start = 5407 + _CONTINUEASNEWWORKFLOWEXECUTION_MEMOENTRY._serialized_end = 5483 _CONTINUEASNEWWORKFLOWEXECUTION_HEADERSENTRY._serialized_start = 3354 _CONTINUEASNEWWORKFLOWEXECUTION_HEADERSENTRY._serialized_end = 3433 - _CANCELWORKFLOWEXECUTION._serialized_start = 5507 - _CANCELWORKFLOWEXECUTION._serialized_end = 5532 - _SETPATCHMARKER._serialized_start = 5534 - _SETPATCHMARKER._serialized_end = 5588 - _STARTCHILDWORKFLOWEXECUTION._serialized_start = 5591 - _STARTCHILDWORKFLOWEXECUTION._serialized_end = 6765 + _CANCELWORKFLOWEXECUTION._serialized_start = 5566 + _CANCELWORKFLOWEXECUTION._serialized_end = 5591 + _SETPATCHMARKER._serialized_start = 5593 + _SETPATCHMARKER._serialized_end = 5647 + _STARTCHILDWORKFLOWEXECUTION._serialized_start = 5650 + _STARTCHILDWORKFLOWEXECUTION._serialized_end = 6824 _STARTCHILDWORKFLOWEXECUTION_HEADERSENTRY._serialized_start = 3354 _STARTCHILDWORKFLOWEXECUTION_HEADERSENTRY._serialized_end = 3433 - _STARTCHILDWORKFLOWEXECUTION_MEMOENTRY._serialized_start = 5348 - _STARTCHILDWORKFLOWEXECUTION_MEMOENTRY._serialized_end = 5424 - _CANCELCHILDWORKFLOWEXECUTION._serialized_start = 6767 - _CANCELCHILDWORKFLOWEXECUTION._serialized_end = 6841 - _REQUESTCANCELEXTERNALWORKFLOWEXECUTION._serialized_start = 6844 - _REQUESTCANCELEXTERNALWORKFLOWEXECUTION._serialized_end = 6986 - _SIGNALEXTERNALWORKFLOWEXECUTION._serialized_start = 6989 - _SIGNALEXTERNALWORKFLOWEXECUTION._serialized_end = 7388 + _STARTCHILDWORKFLOWEXECUTION_MEMOENTRY._serialized_start = 5407 + _STARTCHILDWORKFLOWEXECUTION_MEMOENTRY._serialized_end = 5483 + _CANCELCHILDWORKFLOWEXECUTION._serialized_start = 6826 + _CANCELCHILDWORKFLOWEXECUTION._serialized_end = 6900 + _REQUESTCANCELEXTERNALWORKFLOWEXECUTION._serialized_start = 6903 + _REQUESTCANCELEXTERNALWORKFLOWEXECUTION._serialized_end = 7045 + _SIGNALEXTERNALWORKFLOWEXECUTION._serialized_start = 7048 + _SIGNALEXTERNALWORKFLOWEXECUTION._serialized_end = 7447 _SIGNALEXTERNALWORKFLOWEXECUTION_HEADERSENTRY._serialized_start = 3354 _SIGNALEXTERNALWORKFLOWEXECUTION_HEADERSENTRY._serialized_end = 3433 - _CANCELSIGNALWORKFLOW._serialized_start = 7390 - _CANCELSIGNALWORKFLOW._serialized_end = 7425 - _UPSERTWORKFLOWSEARCHATTRIBUTES._serialized_start = 7427 - _UPSERTWORKFLOWSEARCHATTRIBUTES._serialized_end = 7528 - _MODIFYWORKFLOWPROPERTIES._serialized_start = 7530 - _MODIFYWORKFLOWPROPERTIES._serialized_end = 7609 - _UPDATERESPONSE._serialized_start = 7612 - _UPDATERESPONSE._serialized_end = 7822 - _SCHEDULENEXUSOPERATION._serialized_start = 7825 - _SCHEDULENEXUSOPERATION._serialized_end = 8363 - _SCHEDULENEXUSOPERATION_NEXUSHEADERENTRY._serialized_start = 8313 - _SCHEDULENEXUSOPERATION_NEXUSHEADERENTRY._serialized_end = 8363 - _REQUESTCANCELNEXUSOPERATION._serialized_start = 8365 - _REQUESTCANCELNEXUSOPERATION._serialized_end = 8407 + _CANCELSIGNALWORKFLOW._serialized_start = 7449 + _CANCELSIGNALWORKFLOW._serialized_end = 7484 + _UPSERTWORKFLOWSEARCHATTRIBUTES._serialized_start = 7486 + _UPSERTWORKFLOWSEARCHATTRIBUTES._serialized_end = 7587 + _MODIFYWORKFLOWPROPERTIES._serialized_start = 7589 + _MODIFYWORKFLOWPROPERTIES._serialized_end = 7668 + _UPDATERESPONSE._serialized_start = 7671 + _UPDATERESPONSE._serialized_end = 7881 + _SCHEDULENEXUSOPERATION._serialized_start = 7884 + _SCHEDULENEXUSOPERATION._serialized_end = 8422 + _SCHEDULENEXUSOPERATION_NEXUSHEADERENTRY._serialized_start = 8372 + _SCHEDULENEXUSOPERATION_NEXUSHEADERENTRY._serialized_end = 8422 + _REQUESTCANCELNEXUSOPERATION._serialized_start = 8424 + _REQUESTCANCELNEXUSOPERATION._serialized_end = 8466 # @@protoc_insertion_point(module_scope) diff --git a/temporalio/bridge/proto/workflow_commands/workflow_commands_pb2.pyi b/temporalio/bridge/proto/workflow_commands/workflow_commands_pb2.pyi index 6f532fa54..3860809b9 100644 --- a/temporalio/bridge/proto/workflow_commands/workflow_commands_pb2.pyi +++ b/temporalio/bridge/proto/workflow_commands/workflow_commands_pb2.pyi @@ -942,6 +942,7 @@ class ContinueAsNewWorkflowExecution(google.protobuf.message.Message): RETRY_POLICY_FIELD_NUMBER: builtins.int VERSIONING_INTENT_FIELD_NUMBER: builtins.int INITIAL_VERSIONING_BEHAVIOR_FIELD_NUMBER: builtins.int + BACKOFF_START_INTERVAL_FIELD_NUMBER: builtins.int workflow_type: builtins.str """The identifier the lang-specific sdk uses to execute workflow code""" task_queue: builtins.str @@ -1000,6 +1001,9 @@ class ContinueAsNewWorkflowExecution(google.protobuf.message.Message): For example, choose to AutoUpgrade on continue-as-new instead of inheriting the pinned version of the previous run. """ + @property + def backoff_start_interval(self) -> google.protobuf.duration_pb2.Duration: + """Delay before the first workflow task of the continued run is scheduled.""" def __init__( self, *, @@ -1024,10 +1028,13 @@ class ContinueAsNewWorkflowExecution(google.protobuf.message.Message): retry_policy: temporalio.api.common.v1.message_pb2.RetryPolicy | None = ..., versioning_intent: temporalio.bridge.proto.common.common_pb2.VersioningIntent.ValueType = ..., initial_versioning_behavior: temporalio.api.enums.v1.workflow_pb2.ContinueAsNewVersioningBehavior.ValueType = ..., + backoff_start_interval: google.protobuf.duration_pb2.Duration | None = ..., ) -> None: ... def HasField( self, field_name: typing_extensions.Literal[ + "backoff_start_interval", + b"backoff_start_interval", "retry_policy", b"retry_policy", "search_attributes", @@ -1043,6 +1050,8 @@ class ContinueAsNewWorkflowExecution(google.protobuf.message.Message): field_name: typing_extensions.Literal[ "arguments", b"arguments", + "backoff_start_interval", + b"backoff_start_interval", "headers", b"headers", "initial_versioning_behavior", diff --git a/temporalio/bridge/sdk-core b/temporalio/bridge/sdk-core index c5a6646e9..d79f8681f 160000 --- a/temporalio/bridge/sdk-core +++ b/temporalio/bridge/sdk-core @@ -1 +1 @@ -Subproject commit c5a6646e96fd7f202dd91805c7d53f2cdd03c544 +Subproject commit d79f8681fad38572e2f9b6e98083590781ee0a34 diff --git a/temporalio/worker/_interceptor.py b/temporalio/worker/_interceptor.py index f0d616f2c..4acf3c5d1 100644 --- a/temporalio/worker/_interceptor.py +++ b/temporalio/worker/_interceptor.py @@ -165,6 +165,7 @@ class ContinueAsNewInput: task_queue: str | None run_timeout: timedelta | None task_timeout: timedelta | None + backoff_start_interval: timedelta | None retry_policy: temporalio.common.RetryPolicy | None memo: Mapping[str, Any] | None search_attributes: None | ( diff --git a/temporalio/worker/_workflow_instance.py b/temporalio/worker/_workflow_instance.py index deefb5ad3..ff92d6bac 100644 --- a/temporalio/worker/_workflow_instance.py +++ b/temporalio/worker/_workflow_instance.py @@ -1148,6 +1148,7 @@ def workflow_continue_as_new( task_queue: str | None, run_timeout: timedelta | None, task_timeout: timedelta | None, + backoff_start_interval: timedelta | None, retry_policy: temporalio.common.RetryPolicy | None, memo: Mapping[str, Any] | None, search_attributes: None @@ -1178,6 +1179,7 @@ def workflow_continue_as_new( task_queue=task_queue, run_timeout=run_timeout, task_timeout=task_timeout, + backoff_start_interval=backoff_start_interval, retry_policy=retry_policy, memo=memo, search_attributes=search_attributes, @@ -3587,6 +3589,8 @@ def _apply_command(self) -> None: v.workflow_run_timeout.FromTimedelta(self._input.run_timeout) if self._input.task_timeout: v.workflow_task_timeout.FromTimedelta(self._input.task_timeout) + if self._input.backoff_start_interval: + v.backoff_start_interval.FromTimedelta(self._input.backoff_start_interval) if self._input.headers: temporalio.common._apply_headers(self._input.headers, v.headers) if self._input.retry_policy: diff --git a/temporalio/workflow/_context.py b/temporalio/workflow/_context.py index 297a8bf30..23c943cd0 100644 --- a/temporalio/workflow/_context.py +++ b/temporalio/workflow/_context.py @@ -286,6 +286,7 @@ def workflow_continue_as_new( task_queue: str | None, run_timeout: timedelta | None, task_timeout: timedelta | None, + backoff_start_interval: timedelta | None, retry_policy: temporalio.common.RetryPolicy | None, memo: Mapping[str, Any] | None, search_attributes: None diff --git a/temporalio/workflow/_workflow_ops.py b/temporalio/workflow/_workflow_ops.py index b877be585..f80ca1bdb 100644 --- a/temporalio/workflow/_workflow_ops.py +++ b/temporalio/workflow/_workflow_ops.py @@ -683,6 +683,7 @@ def continue_as_new( task_queue: str | None = None, run_timeout: timedelta | None = None, task_timeout: timedelta | None = None, + backoff_start_interval: timedelta | None = None, retry_policy: temporalio.common.RetryPolicy | None = None, memo: Mapping[str, Any] | None = None, search_attributes: None @@ -702,6 +703,7 @@ def continue_as_new( task_queue: str | None = None, run_timeout: timedelta | None = None, task_timeout: timedelta | None = None, + backoff_start_interval: timedelta | None = None, retry_policy: temporalio.common.RetryPolicy | None = None, memo: Mapping[str, Any] | None = None, search_attributes: None @@ -722,6 +724,7 @@ def continue_as_new( task_queue: str | None = None, run_timeout: timedelta | None = None, task_timeout: timedelta | None = None, + backoff_start_interval: timedelta | None = None, retry_policy: temporalio.common.RetryPolicy | None = None, memo: Mapping[str, Any] | None = None, search_attributes: None @@ -742,6 +745,7 @@ def continue_as_new( task_queue: str | None = None, run_timeout: timedelta | None = None, task_timeout: timedelta | None = None, + backoff_start_interval: timedelta | None = None, retry_policy: temporalio.common.RetryPolicy | None = None, memo: Mapping[str, Any] | None = None, search_attributes: None @@ -762,6 +766,7 @@ def continue_as_new( task_queue: str | None = None, run_timeout: timedelta | None = None, task_timeout: timedelta | None = None, + backoff_start_interval: timedelta | None = None, retry_policy: temporalio.common.RetryPolicy | None = None, memo: Mapping[str, Any] | None = None, search_attributes: None @@ -781,6 +786,7 @@ def continue_as_new( task_queue: str | None = None, run_timeout: timedelta | None = None, task_timeout: timedelta | None = None, + backoff_start_interval: timedelta | None = None, retry_policy: temporalio.common.RetryPolicy | None = None, memo: Mapping[str, Any] | None = None, search_attributes: None @@ -804,6 +810,8 @@ def continue_as_new( workflow's run timeout. task_timeout: Timeout of a single workflow task. Defaults to the current workflow's task timeout. + backoff_start_interval: Delay before the first workflow task of the + continued run is scheduled. memo: Memo for the workflow. Defaults to the current workflow's memo. search_attributes: Search attributes for the workflow. Defaults to the current workflow's search attributes. The dictionary form of this is @@ -826,6 +834,7 @@ def continue_as_new( task_queue=task_queue, run_timeout=run_timeout, task_timeout=task_timeout, + backoff_start_interval=backoff_start_interval, retry_policy=retry_policy, memo=memo, search_attributes=search_attributes, diff --git a/tests/worker/test_workflow.py b/tests/worker/test_workflow.py index 4cd070cc8..d20077cf5 100644 --- a/tests/worker/test_workflow.py +++ b/tests/worker/test_workflow.py @@ -1893,6 +1893,7 @@ async def run(self, past_run_ids: list[str]) -> list[str]: # Add memo and retry policy to check memo={"past_run_id_count": len(past_run_ids)}, retry_policy=RetryPolicy(maximum_attempts=1000 + len(past_run_ids)), + backoff_start_interval=timedelta(milliseconds=1), ) @@ -1914,6 +1915,19 @@ async def test_workflow_continue_as_new(client: Client, env: WorkflowEnvironment result = await handle.result() assert len(result) == 5 assert result[0] == handle.first_execution_run_id + first_run_handle = client.get_workflow_handle( + handle.id, run_id=handle.first_execution_run_id + ) + history = await first_run_handle.fetch_history() + continued = [ + event.workflow_execution_continued_as_new_event_attributes + for event in history.events + if event.HasField("workflow_execution_continued_as_new_event_attributes") + ] + assert continued + assert continued[0].backoff_start_interval.ToTimedelta() == timedelta( + milliseconds=1 + ) sa_prefix = "python_test_" From 5f1d35274aa20bcf8f45670be137dda90cfbce87 Mon Sep 17 00:00:00 2001 From: Brian Strauch Date: Wed, 24 Jun 2026 12:45:33 -0700 Subject: [PATCH 143/226] Fix continue-as-new handling in workflow_streams subscribe (#1581) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Fix continue-as-new detection in workflow_streams subscribe _follow_continue_as_new described the workflow with no run id, which returns the current run. After a continue-as-new that is the new RUNNING run, never CONTINUED_AS_NEW (which only sits on the old, closed run), so the check never fired and subscribe() stopped during a rollover instead of following the stream. Capture the run id each poll's update is admitted to (start_update with WaitForStage ACCEPTED, read workflow_run_id, then await result) and describe that specific run on failure. A rolled-over run reports CONTINUED_AS_NEW, a terminal run reports a terminal status, and a still-RUNNING run is a transient error that should surface. This also avoids mistaking an unrelated new execution that reused the workflow id for a successor. Co-Authored-By: Claude Opus 4.8 (1M context) * Retry poll rejected while stream is draining for continue-as-new The poll update's validator rejected new polls during detach-for-CAN with an untyped RuntimeError, which subscribe() did not classify and re-raised — ending the subscription with an error during a routine rollover. Give the validator the well-known StreamDraining ApplicationError type and have subscribe() back off and retry on it, so the poll lands on the successor run once the rollover completes. Co-Authored-By: Claude Opus 4.8 (1M context) * Add CODEOWNERS entries for workflow_streams * Address review feedback on workflow_streams continue-as-new fix - Hoist StreamDraining/TruncatedOffset error types to constants in _types.py so the raise sites (_stream.py) and handling sites (_client.py) cannot diverge. - Annotate _describe_polled_run return type. - Drop dead non_retryable=True flags: all three ApplicationErrors are raised from update validators/handlers, where retry policy does not apply, so the flag was a no-op. - Document poll_cooldown semantics and warn against timedelta(0). - Add test verifying the subscribe flow captures the polled run id. Co-Authored-By: Claude Opus 4.8 (1M context) --------- Co-authored-by: Claude Opus 4.8 (1M context) --- .github/CODEOWNERS | 3 +- .../contrib/workflow_streams/_client.py | 62 ++++- .../contrib/workflow_streams/_stream.py | 18 +- temporalio/contrib/workflow_streams/_types.py | 7 + .../workflow_streams/test_workflow_streams.py | 221 ++++++++++++++++++ 5 files changed, 295 insertions(+), 16 deletions(-) diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index d638fd70e..145eb42c4 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -10,14 +10,15 @@ # other than the SDK team. For each one, we add the owning team, # as well as @temporalio/sdk, so the SDK team can continue to # manage repo-wide concerns. -/temporalio/contrib/common/ @temporalio/ai-sdk @temporalio/sdk /temporalio/contrib/google_adk_agents/ @temporalio/ai-sdk @temporalio/sdk /temporalio/contrib/langgraph/ @temporalio/ai-sdk @temporalio/sdk /temporalio/contrib/langsmith/ @temporalio/ai-sdk @temporalio/sdk /temporalio/contrib/openai_agents/ @temporalio/ai-sdk @temporalio/sdk /temporalio/contrib/strands/ @temporalio/ai-sdk @temporalio/sdk +/temporalio/contrib/workflow_streams/ @temporalio/ai-sdk @temporalio/sdk /tests/contrib/google_adk_agents/ @temporalio/ai-sdk @temporalio/sdk /tests/contrib/langgraph/ @temporalio/ai-sdk @temporalio/sdk /tests/contrib/langsmith/ @temporalio/ai-sdk @temporalio/sdk /tests/contrib/openai_agents/ @temporalio/ai-sdk @temporalio/sdk /tests/contrib/strands/ @temporalio/ai-sdk @temporalio/sdk +/tests/contrib/workflow_streams/ @temporalio/ai-sdk @temporalio/sdk diff --git a/temporalio/contrib/workflow_streams/_client.py b/temporalio/contrib/workflow_streams/_client.py index e28437e69..605bf3f03 100644 --- a/temporalio/contrib/workflow_streams/_client.py +++ b/temporalio/contrib/workflow_streams/_client.py @@ -31,16 +31,20 @@ from temporalio.api.common.v1 import Payload from temporalio.client import ( Client, + WorkflowExecutionDescription, WorkflowExecutionStatus, WorkflowHandle, WorkflowUpdateFailedError, WorkflowUpdateRPCTimeoutOrCancelledError, + WorkflowUpdateStage, ) from temporalio.converter import DataConverter, PayloadConverter from temporalio.service import RPCError, RPCStatusCode from ._topic_handle import TopicHandle from ._types import ( + STREAM_DRAINING_ERROR_TYPE, + TRUNCATED_OFFSET_ERROR_TYPE, PollInput, PollResult, PublishEntry, @@ -127,6 +131,10 @@ def __init__( self._pending_seq: int = 0 self._pending_since: float | None = None self._topic_types: dict[str, type[Any]] = {} + # Run id the most recent poll's update was admitted to. Captured before + # waiting for the outcome so a mid-poll continue-as-new can be detected by + # describing that specific run. None until the first poll is admitted. + self._polled_run_id: str | None = None @classmethod def create( @@ -504,9 +512,11 @@ async def subscribe( ``Payload`` — useful for heterogeneous topics where the caller dispatches on ``Payload.metadata`` or wants to forward the bytes without decoding. - poll_cooldown: Minimum interval between polls to avoid - overwhelming the workflow when items arrive faster - than the poll round-trip. Defaults to 100ms. + poll_cooldown: Minimum interval between polls when caught + up (backlogs always drain at full speed). Defaults to + 100ms. Avoid ``timedelta(0)``: an idle subscriber + busy-loops, and each poll grows workflow history toward + its limit. Use 0 only in tests. Yields: :class:`WorkflowStreamItem` for each matching item. @@ -528,22 +538,37 @@ async def subscribe( offset = from_offset while True: try: - result: PollResult = await self._handle.execute_update( + # Wait only for ACCEPTED so the handle (and the run id it was + # admitted to) is available before we block on the outcome; if + # the run continues-as-new mid-poll, result() fails but we still + # know which run to inspect. + handle = await self._handle.start_update( "__temporal_workflow_stream_poll", PollInput(topics=topic_filter, from_offset=offset), + wait_for_stage=WorkflowUpdateStage.ACCEPTED, result_type=PollResult, ) + self._polled_run_id = handle.workflow_run_id + result: PollResult = await handle.result() except asyncio.CancelledError: return except WorkflowUpdateFailedError as e: cause_type = getattr(e.cause, "type", None) - if cause_type == "TruncatedOffset": + if cause_type == TRUNCATED_OFFSET_ERROR_TYPE: # Subscriber fell behind truncation. Retry from # offset 0 which the stream treats as "from the # beginning of whatever exists" (i.e., from # base_offset). offset = 0 continue + if cause_type == STREAM_DRAINING_ERROR_TYPE: + # Workflow is detaching for continue-as-new. Back off and + # retry; the poll lands on the successor run once the + # rollover completes. + cooldown_secs = poll_cooldown.total_seconds() + if cooldown_secs > 0: + await asyncio.sleep(cooldown_secs) + continue if cause_type == "AcceptedUpdateCompletedWorkflow": # Workflow returned (or continued-as-new) before # this poll's update completed. Either follow the @@ -586,15 +611,32 @@ async def subscribe( if not result.more_ready and cooldown_secs > 0: await asyncio.sleep(cooldown_secs) + async def _describe_polled_run(self) -> WorkflowExecutionDescription: + """Describe the specific run the most recent poll was admitted to. + + Describing that run (rather than the latest) is what lets a + continue-as-new be detected: a rolled-over run is closed with status + CONTINUED_AS_NEW, whereas the latest run would report RUNNING. Falls + back to the latest run when no run id has been captured yet, or when no + client is available to target a specific run. + """ + if self._client is not None: + return await self._client.get_workflow_handle( + self._workflow_id, run_id=self._polled_run_id + ).describe() + return await self._handle.describe() + async def _follow_continue_as_new(self) -> bool: - """Check if the workflow continued-as-new and re-target the handle. + """Check if the polled run continued-as-new and re-target the handle. - Returns True if the handle was updated (caller should retry). + Returns True if the handle was updated (caller should retry). The + successor run id is not needed — re-targeting to an unpinned handle + makes the next poll address the latest (successor) run. """ if self._client is None: return False try: - desc = await self._handle.describe() + desc = await self._describe_polled_run() except Exception: return False if desc.status == WorkflowExecutionStatus.CONTINUED_AS_NEW: @@ -603,14 +645,14 @@ async def _follow_continue_as_new(self) -> bool: return False async def _workflow_in_terminal_state(self) -> bool: - """Return True if the workflow has reached a terminal state. + """Return True if the polled run has reached a terminal state. Used by ``subscribe()`` to distinguish "workflow finished — stream is done" from "wrong workflow id" when a poll RPC returns NOT_FOUND. """ try: - desc = await self._handle.describe() + desc = await self._describe_polled_run() except Exception: return False return desc.status in ( diff --git a/temporalio/contrib/workflow_streams/_stream.py b/temporalio/contrib/workflow_streams/_stream.py index 2753f04c2..ae8608c3b 100644 --- a/temporalio/contrib/workflow_streams/_stream.py +++ b/temporalio/contrib/workflow_streams/_stream.py @@ -37,6 +37,8 @@ from ._topic_handle import WorkflowTopicHandle from ._types import ( + STREAM_DRAINING_ERROR_TYPE, + TRUNCATED_OFFSET_ERROR_TYPE, PollInput, PollResult, PublisherState, @@ -357,7 +359,6 @@ def truncate(self, up_to_offset: int) -> None: f"Cannot truncate to offset {up_to_offset}: " f"valid range is [{self._base_offset}, {self._base_offset + len(self._log)})", type="TruncateOutOfRange", - non_retryable=True, ) self._log = self._log[log_index:] self._base_offset = up_to_offset @@ -419,8 +420,7 @@ async def _on_poll(self, payload: PollInput) -> PollResult: raise ApplicationError( f"Requested offset {payload.from_offset} has been truncated. " f"Current base offset is {self._base_offset}.", - type="TruncatedOffset", - non_retryable=True, + type=TRUNCATED_OFFSET_ERROR_TYPE, ) all_new = self._log[log_offset:] if payload.topics: @@ -460,9 +460,17 @@ async def _on_poll(self, payload: PollInput) -> PollResult: ) def _validate_poll(self, _payload: PollInput) -> None: - """Reject new polls when pollers are detached for continue-as-new.""" + """Reject new polls when pollers are detached for continue-as-new. + + Uses the well-known ``StreamDraining`` type so a subscriber recognizes + the rollover-in-progress and retries until its poll lands on the + successor run, rather than surfacing the rejection as an error. + """ if self._detaching: - raise RuntimeError("Workflow pollers are detached for continue-as-new") + raise ApplicationError( + "Workflow pollers are detached for continue-as-new", + type=STREAM_DRAINING_ERROR_TYPE, + ) def _on_offset(self) -> int: """Return the current global offset (base_offset + log length).""" diff --git a/temporalio/contrib/workflow_streams/_types.py b/temporalio/contrib/workflow_streams/_types.py index 94bfb1a9b..a58cf75ae 100644 --- a/temporalio/contrib/workflow_streams/_types.py +++ b/temporalio/contrib/workflow_streams/_types.py @@ -26,6 +26,13 @@ T = TypeVar("T") +# Well-known ``ApplicationError.type`` values the stream workflow uses to reject +# polls, and which ``WorkflowStreamClient.subscribe`` recognizes to drive retry +# behavior. Defined here so the raise sites (``_stream.py``) and the handling +# sites (``_client.py``) cannot diverge. +STREAM_DRAINING_ERROR_TYPE = "StreamDraining" +TRUNCATED_OFFSET_ERROR_TYPE = "TruncatedOffset" + # basedpyright flags _-prefixed module-level functions as unused even when # sibling modules import them (_stream.py, _client.py). Vanilla pyright does diff --git a/tests/contrib/workflow_streams/test_workflow_streams.py b/tests/contrib/workflow_streams/test_workflow_streams.py index 7353cbdd5..12026ff1a 100644 --- a/tests/contrib/workflow_streams/test_workflow_streams.py +++ b/tests/contrib/workflow_streams/test_workflow_streams.py @@ -28,6 +28,7 @@ from temporalio import activity, nexus, workflow from temporalio.client import ( Client, + WorkflowExecutionStatus, WorkflowHandle, WorkflowUpdateFailedError, WorkflowUpdateStage, @@ -2008,6 +2009,226 @@ async def test_continue_as_new_helper(client: Client) -> None: await new_handle.signal(ContinueAsNewHelperWorkflow.close) +@pytest.mark.asyncio +async def test_follow_continue_as_new_describes_polled_run(client: Client) -> None: + """Regression test for continue-as-new detection. + + ``_follow_continue_as_new`` must describe the *specific run the poll was + admitted to* — a rolled-over run is closed with status CONTINUED_AS_NEW, + whereas the latest (successor) run reports RUNNING. The previous + implementation described the latest run, so the check never fired and a poll + failure during a rollover stopped the subscription instead of following it. + + Driving the exact poll-failure race deterministically is impractical (the + workflow drains in-flight polls before continuing-as-new), so this asserts + the helper's decision directly against a real post-rollover run. + """ + async with new_worker(client, ContinueAsNewHelperWorkflow) as worker: + handle = await client.start_workflow( + ContinueAsNewHelperWorkflow.run, + CANWorkflowInputTyped(), + id=f"workflow-stream-can-follow-{uuid.uuid4()}", + task_queue=worker.task_queue, + ) + await handle.signal( + "__temporal_workflow_stream_publish", + PublishInput( + items=[PublishEntry(topic="events", data=_wire_bytes(b"item-0"))], + publisher_id="pub", + sequence=1, + ), + ) + old_run_id = handle.result_run_id + + await handle.signal(ContinueAsNewHelperWorkflow.trigger_continue) + new_handle = client.get_workflow_handle(handle.id) + await assert_eq_eventually(True, lambda: _is_different_run(handle, new_handle)) + + # The fix's premise: the polled (old) run reports CONTINUED_AS_NEW; the + # latest run reports RUNNING. + old_desc = await client.get_workflow_handle( + handle.id, run_id=old_run_id + ).describe() + assert old_desc.status == WorkflowExecutionStatus.CONTINUED_AS_NEW + latest_desc = await client.get_workflow_handle(handle.id).describe() + assert latest_desc.status == WorkflowExecutionStatus.RUNNING + + # The client follows the rollover when it describes the polled run, but + # the previous latest-run behavior (polled_run_id unset) would not. + following = WorkflowStreamClient.create(client, handle.id) + following._polled_run_id = old_run_id + assert await following._follow_continue_as_new() is True + + latest_only = WorkflowStreamClient.create(client, handle.id) + latest_only._polled_run_id = None # describes the latest run, as the bug did + assert await latest_only._follow_continue_as_new() is False + + await new_handle.signal(ContinueAsNewHelperWorkflow.close) + + +@pytest.mark.asyncio +async def test_subscribe_captures_polled_run_id(client: Client) -> None: + """The ``subscribe`` loop must record the run each poll was admitted to. + + ``_follow_continue_as_new`` relies on ``_polled_run_id`` to describe the + *polled* run rather than the latest one (see + ``test_follow_continue_as_new_describes_polled_run``). This verifies the + real subscribe flow populates that field, rather than setting it by hand. + """ + async with new_worker(client, BasicWorkflowStreamWorkflow) as worker: + handle = await client.start_workflow( + BasicWorkflowStreamWorkflow.run, + id=f"workflow-stream-polled-run-{uuid.uuid4()}", + task_queue=worker.task_queue, + ) + await handle.signal( + "__temporal_workflow_stream_publish", + PublishInput( + items=[PublishEntry(topic="events", data=_wire_bytes(b"item-0"))], + publisher_id="pub", + sequence=1, + ), + ) + + stream = WorkflowStreamClient.create(client, handle.id) + received: list[WorkflowStreamItem] = [] + + async def consume() -> None: + async for item in stream.subscribe( + from_offset=0, poll_cooldown=timedelta(0), result_type=bytes + ): + received.append(item) + + async def received_count() -> int: + return len(received) + + task = asyncio.create_task(consume()) + try: + await assert_eq_eventually(1, received_count) + # The poll was admitted to the run we started; subscribe must have + # captured exactly that run id, not left it unset. + assert stream._polled_run_id == handle.result_run_id + finally: + task.cancel() + try: + await task + except asyncio.CancelledError: + pass + await handle.signal(BasicWorkflowStreamWorkflow.close) + + +@workflow.defn +class DrainingGateWorkflow: + """CAN workflow that detaches pollers and then *holds* in the draining state + until released, so a subscriber deterministically hits the draining poll + rejection before the rollover completes.""" + + @workflow.init + def __init__(self, input: CANWorkflowInputTyped) -> None: + self.stream = WorkflowStream(prior_state=input.stream_state) + self._should_continue = False + self._release = False + self._closed = False + + @workflow.signal + def close(self) -> None: + self._closed = True + + @workflow.signal + def trigger_continue(self) -> None: + self._should_continue = True + + @workflow.signal + def release(self) -> None: + self._release = True + + @workflow.run + async def run(self, _input: CANWorkflowInputTyped) -> None: + del _input + await workflow.wait_condition(lambda: self._should_continue or self._closed) + if self._closed: + return + # Detach but stay open until released, so new polls are rejected with + # StreamDraining for a deterministic window. + self.stream.detach_pollers() + await workflow.wait_condition(lambda: self._release) + await workflow.wait_condition(workflow.all_handlers_finished) + workflow.continue_as_new( + args=[CANWorkflowInputTyped(stream_state=self.stream.get_state())] + ) + + +@pytest.mark.asyncio +async def test_subscribe_retries_while_draining(client: Client) -> None: + """A poll rejected because the stream is draining for continue-as-new must + be retried, not surfaced as an error: the subscription stays alive through + the rollover and resumes on the successor run.""" + async with new_worker(client, DrainingGateWorkflow) as worker: + handle = await client.start_workflow( + DrainingGateWorkflow.run, + CANWorkflowInputTyped(), + id=f"workflow-stream-draining-{uuid.uuid4()}", + task_queue=worker.task_queue, + ) + await handle.signal( + "__temporal_workflow_stream_publish", + PublishInput( + items=[PublishEntry(topic="events", data=_wire_bytes(b"item-0"))], + publisher_id="pub", + sequence=1, + ), + ) + + stream = WorkflowStreamClient.create(client, handle.id) + received: list[WorkflowStreamItem] = [] + + async def consume() -> None: + async for item in stream.subscribe( + from_offset=0, poll_cooldown=timedelta(0), result_type=bytes + ): + received.append(item) + + async def received_count() -> int: + return len(received) + + task = asyncio.create_task(consume()) + new_handle = client.get_workflow_handle(handle.id) + try: + await assert_eq_eventually(1, received_count) + + # Detach; the subscriber's polls are now rejected with StreamDraining. + await handle.signal(DrainingGateWorkflow.trigger_continue) + # The subscription must keep retrying, not error out. + await asyncio.sleep(1.0) + assert not task.done(), "draining rejection must not end the subscription" + + # Release: the workflow continues-as-new; the subscription resumes on + # the successor run and receives an item published there. + await handle.signal(DrainingGateWorkflow.release) + await assert_eq_eventually( + True, lambda: _is_different_run(handle, new_handle) + ) + await new_handle.signal( + "__temporal_workflow_stream_publish", + PublishInput( + items=[PublishEntry(topic="events", data=_wire_bytes(b"item-1"))], + publisher_id="pub", + sequence=2, + ), + ) + + await assert_eq_eventually(2, received_count) + assert [i.data for i in received] == [b"item-0", b"item-1"] + assert [i.offset for i in received] == [0, 1] + finally: + task.cancel() + try: + await task + except asyncio.CancelledError: + pass + await new_handle.signal(DrainingGateWorkflow.close) + + # --------------------------------------------------------------------------- # Cross-workflow workflow stream (Scenario 1) # --------------------------------------------------------------------------- From 31a0a1a881be89429d07f2b06459938f836e1bef Mon Sep 17 00:00:00 2001 From: Evan Reynolds Date: Wed, 24 Jun 2026 15:07:44 -0700 Subject: [PATCH 144/226] Adding links to Nexus signals (#1593) * Signal work * Reviewing * Renaming to RequestLink and ResponseLink * Addressing PR comments * Updating method name * Removed unused test methods * Adding tests, fixed an issue * Adding tests * Fix a linter issue * Added entry to Changelog * Fixing a race condition * centralize and simplify start workflow response link handling. Move private start context accessor to nexus package. Update tests to reflect that response links are created when using plain start workflow * run formatter, address lint * move changelog entry. Remove inaccurate comment --------- Co-authored-by: Alex Mazzeo --- CHANGELOG.md | 5 + temporalio/client/_impl.py | 39 +- temporalio/nexus/_link_conversion.py | 26 +- temporalio/nexus/_operation_context.py | 88 ++- temporalio/worker/_workflow.py | 6 +- tests/conftest.py | 2 + tests/nexus/test_link_conversion.py | 12 +- tests/nexus/test_signal_link_propagation.py | 558 +++++++++++++++++ .../nexus/test_signal_link_propagation_e2e.py | 567 ++++++++++++++++++ 9 files changed, 1245 insertions(+), 58 deletions(-) create mode 100644 tests/nexus/test_signal_link_propagation.py create mode 100644 tests/nexus/test_signal_link_propagation_e2e.py diff --git a/CHANGELOG.md b/CHANGELOG.md index b0075011c..f002d37d8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,6 +20,11 @@ to include examples, links to docs, or any other relevant information. ### Added +- Nexus operation link propagation for signals. When a Nexus operation handler signals a workflow + (including signal-with-start), the inbound Nexus request links are now forwarded onto the signaled + workflow so its history events link back to the caller, and the link the server returns for the + signaled event is attached to the caller workflow's Nexus operation history event. This makes the + caller and callee mutually navigable in the UI for signal-based Nexus operations. - Exposed `backoff_start_interval` for continue-as-new, to allow the new workflow to start after a delay. ### Changed diff --git a/temporalio/client/_impl.py b/temporalio/client/_impl.py index 1481c8327..4e7049985 100644 --- a/temporalio/client/_impl.py +++ b/temporalio/client/_impl.py @@ -200,6 +200,9 @@ async def start_workflow( start_workflow_response=resp, ) setattr(handle, "__temporal_eagerly_started", eagerly_started) + nexus_ctx = temporalio.nexus._operation_context._try_start_operation_context() + if nexus_ctx is not None: + nexus_ctx._add_start_workflow_response_link(handle) return handle async def _build_start_workflow_execution_request( @@ -237,10 +240,24 @@ async def _build_start_workflow_execution_request( # Links are duplicated on request for compatibility with older server versions. req.links.extend(links) - if temporalio.nexus._operation_context._in_nexus_backing_workflow_start_context(): + nexus_ctx = temporalio.nexus._operation_context._try_start_operation_context() + if nexus_ctx is not None: + # This start was issued from inside a Nexus operation handler. If the workflow ID + # conflict policy is WORKFLOW_ID_CONFLICT_POLICY_USE_EXISTING and a conflict is + # detected, attach this request's request ID, completion callbacks, and links to + # the existing run. The TemporalNexusClient and WorkflowRunOperationContext are + # responsible for setting the callbacks correctly, so it is safe to enable all + # on-conflict options whenever we are invoked from an operation handler. req.on_conflict_options.attach_request_id = True req.on_conflict_options.attach_completion_callbacks = True req.on_conflict_options.attach_links = True + # The nexus-backing workflow already carries its inbound links via input.links + # (start_workflow forwards them as links=...). A plain start_workflow issued from + # inside a Nexus operation handler must forward the inbound Nexus task links + # explicitly so the started callee's WorkflowExecutionStarted event links back to + # the caller. + if not temporalio.nexus._operation_context._in_nexus_backing_workflow_start_context(): + req.links.extend(nexus_ctx._get_request_links()) return req @@ -267,6 +284,15 @@ async def _build_signal_with_start_workflow_execution_request( await data_converter.encode(input.start_signal_args) ) await self._populate_start_workflow_execution_request(req, input) + # If this signal-with-start is issued from inside a Nexus operation handler (but not the + # nexus-backing workflow), forward the inbound Nexus task links so both the callee's + # WorkflowExecutionStarted and WorkflowExecutionSignaled events link back to the caller. + if not temporalio.nexus._operation_context._in_nexus_backing_workflow_start_context(): + nexus_ctx = ( + temporalio.nexus._operation_context._try_start_operation_context() + ) + if nexus_ctx is not None: + req.links.extend(nexus_ctx._get_request_links()) return req async def _build_update_with_start_start_workflow_execution_request( @@ -500,9 +526,18 @@ async def signal_workflow(self, input: SignalWorkflowInput) -> None: req.input.payloads.extend(await data_converter.encode(input.args)) if input.headers is not None: # type:ignore[reportUnnecessaryComparison] await self._apply_headers(input.headers, req.header.fields) - await self._client.workflow_service.signal_workflow_execution( + # If this signal is issued from inside a Nexus operation handler, forward the inbound + # Nexus task links so the WorkflowExecutionSignaled event links back to the caller. + nexus_ctx = temporalio.nexus._operation_context._try_start_operation_context() + if nexus_ctx is not None: + req.links.extend(nexus_ctx._get_request_links()) + resp = await self._client.workflow_service.signal_workflow_execution( req, retry=True, metadata=input.rpc_metadata, timeout=input.rpc_timeout ) + # Server >= 1.31 with EnableCHASMSignalBacklinks returns a response link pointing at the + # signal event; older servers leave it unset. Propagate when present. + if nexus_ctx is not None and resp.HasField("link"): + nexus_ctx._add_response_link(resp.link) async def terminate_workflow(self, input: TerminateWorkflowInput) -> None: data_converter = self._client.data_converter._with_contexts( diff --git a/temporalio/nexus/_link_conversion.py b/temporalio/nexus/_link_conversion.py index 9958fd718..54ed3869a 100644 --- a/temporalio/nexus/_link_conversion.py +++ b/temporalio/nexus/_link_conversion.py @@ -20,7 +20,7 @@ logger = logging.getLogger(__name__) _NEXUS_OPERATION_LINK_URL_PATH_REGEX = re.compile( - r"^/namespaces/(?P[^/]+)/nexus-operations/(?P[^/]+)$" + r"^/namespaces/(?P[^/]+)/nexus-operations/(?P[^/]+)/(?P[^/]*)/details$" ) _WORKFLOW_LINK_URL_PATH_REGEX = re.compile( @@ -38,7 +38,6 @@ class _LinkType(str, Enum): LINK_EVENT_TYPE_PARAM_NAME = "eventType" LINK_REQUEST_ID_PARAM_NAME = "requestID" LINK_REFERENCE_TYPE_PARAM_NAME = "referenceType" -LINK_RUN_ID_PARAM_NAME = "runID" LINK_REASON_PARAM_NAME = "reason" EVENT_REFERENCE_TYPE = "EventReference" @@ -182,18 +181,11 @@ def nexus_operation_to_nexus_link( """ namespace = urllib.parse.quote(op_link.namespace, safe="") operation_id = urllib.parse.quote(op_link.operation_id, safe="") - path = f"/namespaces/{namespace}/nexus-operations/{operation_id}" - - query_params = "" - if op_link.run_id: - query_params = urllib.parse.urlencode( - { - LINK_RUN_ID_PARAM_NAME: op_link.run_id, - }, - ) + run_id = urllib.parse.quote(op_link.run_id, safe="") + path = f"/namespaces/{namespace}/nexus-operations/{operation_id}/{run_id}/details" return nexusrpc.Link( - url=_temporal_nexus_url(path, query_params=query_params), + url=_temporal_nexus_url(path), type=_LinkType.NEXUS_OPERATION.value, ) @@ -333,19 +325,11 @@ def nexus_link_to_nexus_operation_link( ) return None - query_params = urllib.parse.parse_qs(url.query) - - try: - run_id = _optional_single_query_param(query_params, LINK_RUN_ID_PARAM_NAME) - except ValueError as err: - logger.warning(f"Invalid Nexus link: {nexus_link}. {err}") - return None - groups = match.groupdict() nexus_op_link = temporalio.api.common.v1.Link.NexusOperation( namespace=urllib.parse.unquote(groups["namespace"]), operation_id=urllib.parse.unquote(groups["operation_id"]), - run_id=run_id, + run_id=urllib.parse.unquote(groups["run_id"]), ) return temporalio.api.common.v1.Link(nexus_operation=nexus_op_link) diff --git a/temporalio/nexus/_operation_context.py b/temporalio/nexus/_operation_context.py index 0d9d11449..1128d1b71 100644 --- a/temporalio/nexus/_operation_context.py +++ b/temporalio/nexus/_operation_context.py @@ -23,6 +23,7 @@ overload, ) +import nexusrpc from nexusrpc.handler import ( CancelOperationContext, OperationContext, @@ -44,6 +45,7 @@ from ._link_conversion import ( nexus_link_to_temporal_link, + temporal_link_to_nexus_link, workflow_event_to_nexus_link, workflow_execution_started_event_link_from_workflow_handle, ) @@ -167,6 +169,11 @@ def _try_temporal_context() -> ( return start_ctx or cancel_ctx +def _try_start_operation_context() -> _TemporalStartOperationContext | None: # pyright: ignore[reportUnusedFunction] + """The Nexus start-operation context if a handler is currently running, else None.""" + return _temporal_start_operation_context.get(None) + + @contextmanager def _nexus_backing_workflow_start_context() -> Generator[None]: token = _temporal_nexus_backing_workflow_start_context.set(True) @@ -239,44 +246,73 @@ def _get_callbacks(self, token: str) -> list[temporalio.client.Callback]: else [] ) - def _get_links( - self, - ) -> list[temporalio.api.common.v1.Link]: + def _get_request_links(self) -> list[temporalio.api.common.v1.Link]: + """Request links to attach to RPCs the operation handler issues. + + These are the inbound Nexus task links. When the operation handler signals, + signal-with-starts, or starts a workflow, these links are added to the request's + ``links`` field so the callee's history event links back to whatever scheduled this + Nexus operation. + """ event_links: list[temporalio.api.common.v1.Link] = [] for inbound_link in self.nexus_context.inbound_links: if link := nexus_link_to_temporal_link(inbound_link): event_links.append(link) return event_links - def _add_outbound_links( + def _add_start_workflow_response_link( self, workflow_handle: temporalio.client.WorkflowHandle[Any, Any] ): - # If links were not sent in StartWorkflowExecutionResponse then construct them. - wf_event_links: list[temporalio.api.common.v1.Link.WorkflowEvent] = [] - try: - if isinstance( - workflow_handle._start_workflow_response, - temporalio.api.workflowservice.v1.StartWorkflowExecutionResponse, - ): - if workflow_handle._start_workflow_response.HasField("link"): - if link := workflow_handle._start_workflow_response.link: - if link.HasField("workflow_event"): - wf_event_links.append(link.workflow_event) - if not wf_event_links: - wf_event_links = [ - workflow_execution_started_event_link_from_workflow_handle( + response = workflow_handle._start_workflow_response + + nexus_link: nexusrpc.Link | None = None + if isinstance( + response, temporalio.api.workflowservice.v1.StartWorkflowExecutionResponse + ): + if response.HasField("link"): + nexus_link = temporal_link_to_nexus_link(response.link) + else: + # If a link was not sent in response then construct it. + link = temporalio.api.common.v1.Link( + workflow_event=workflow_execution_started_event_link_from_workflow_handle( workflow_handle, self.nexus_context.request_id, ) - ] - self.nexus_context.outbound_links.extend( - workflow_event_to_nexus_link(link) for link in wf_event_links - ) + ) + nexus_link = temporal_link_to_nexus_link(link) + + elif isinstance( + response, + temporalio.api.workflowservice.v1.SignalWithStartWorkflowExecutionResponse, + ): + # Server >= 1.31 with EnableCHASMSignalBacklinks returns signal_link pointing at + # the WorkflowExecutionSignaled event; older servers leave it unset. + if response.HasField("signal_link"): + nexus_link = temporal_link_to_nexus_link(response.signal_link) + + try: + if nexus_link is not None: + self.nexus_context.outbound_links.append(nexus_link) except Exception as e: logger.warning( - f"Failed to create WorkflowExecutionStarted event links for workflow {workflow_handle}: {e}" + f"Failed to create event links for workflow {workflow_handle}: {e}" ) - return workflow_handle + + def _add_response_link(self, link: temporalio.api.common.v1.Link | None) -> None: + """Append a response link returned by an RPC the operation handler issued. + + ``link`` is the ``common.v1.Link`` returned on a signal, signal-with-start, or start + response (or ``None`` against a server that did not return one). When present and of the + ``workflow_event`` variant, it is converted to a Nexus link and added to the operation's + outbound links so the caller workflow's Nexus history event links to the callee event. + + This is only safe to call from the single thread/task that runs the operation handler. + """ + if link is None or not link.HasField("workflow_event"): + return + self.nexus_context.outbound_links.append( + workflow_event_to_nexus_link(link.workflow_event) + ) class WorkflowRunOperationContext(StartOperationContext): @@ -674,10 +710,8 @@ async def _start_nexus_backing_workflow( priority=priority, versioning_override=versioning_override, callbacks=temporal_context._get_callbacks(token), - links=temporal_context._get_links(), + links=temporal_context._get_request_links(), request_id=temporal_context.nexus_context.request_id, ) - temporal_context._add_outbound_links(wf_handle) - return WorkflowHandle[ReturnType]._unsafe_from_client_workflow_handle(wf_handle) diff --git a/temporalio/worker/_workflow.py b/temporalio/worker/_workflow.py index 9ca802c40..8e6ba2726 100644 --- a/temporalio/worker/_workflow.py +++ b/temporalio/worker/_workflow.py @@ -518,12 +518,13 @@ async def _handle_activation( # Log workflow task duration with external storage metrics self._log_workflow_task_duration( - act, task_start_time, download_metrics, upload_metrics + act, workflow, task_start_time, download_metrics, upload_metrics ) def _log_workflow_task_duration( self, act: temporalio.bridge.proto.workflow_activation.WorkflowActivation, + workflow: _RunningWorkflow | None, task_start_time: float, download_metrics: temporalio.converter._extstore.StorageOperationMetrics, upload_metrics: temporalio.converter._extstore.StorageOperationMetrics, @@ -537,8 +538,7 @@ def _fmt_duration(td: timedelta) -> str: return f"{secs * 1000:.3f}ms" completed_event_id = act.history_length + 1 - _running = self._running_workflows.get(act.run_id) - _info = _running.get_info() if _running is not None else None + _info = workflow.get_info() if workflow is not None else None attempt = _info.attempt if _info is not None else "unknown" log_id = f"{act.run_id}:{completed_event_id}:{attempt}" msg_details, extra = temporalio.workflow._build_log_context( diff --git a/tests/conftest.py b/tests/conftest.py index 19ac8721f..e01773e7e 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -134,6 +134,8 @@ async def env(env_type: str) -> AsyncGenerator[WorkflowEnvironment, None]: "--dynamic-config-value", "history.enableChasmCallbacks=true", "--dynamic-config-value", + "history.enableCHASMSignalBacklinks=true", + "--dynamic-config-value", "nexusoperation.enableStandalone=true", "--dynamic-config-value", 'system.system.refreshNexusEndpointsMinWait="0s"', diff --git a/tests/nexus/test_link_conversion.py b/tests/nexus/test_link_conversion.py index d324f16d6..4afe3367e 100644 --- a/tests/nexus/test_link_conversion.py +++ b/tests/nexus/test_link_conversion.py @@ -277,7 +277,7 @@ def test_link_conversion_workflow_to_link_and_back( ), nexusrpc.Link( type=temporalio.api.common.v1.Link.NexusOperation.DESCRIPTOR.full_name, - url="temporal:///namespaces/ns/nexus-operations/op-id?runID=run-id", + url="temporal:///namespaces/ns/nexus-operations/op-id/run-id/details", ), ), ( @@ -289,7 +289,7 @@ def test_link_conversion_workflow_to_link_and_back( ), nexusrpc.Link( type=temporalio.api.common.v1.Link.NexusOperation.DESCRIPTOR.full_name, - url="temporal:///namespaces/ns/nexus-operations/op-id", + url="temporal:///namespaces/ns/nexus-operations/op-id//details", ), ), ( @@ -301,7 +301,7 @@ def test_link_conversion_workflow_to_link_and_back( ), nexusrpc.Link( type=temporalio.api.common.v1.Link.NexusOperation.DESCRIPTOR.full_name, - url="temporal:///namespaces/ns/nexus-operations/op%2Fid", + url="temporal:///namespaces/ns/nexus-operations/op%2Fid//details", ), ), ], @@ -332,10 +332,12 @@ def test_link_conversion_nexus_operation_to_link_and_back( ) -def test_nexus_operation_link_with_duplicate_run_id_is_ignored(): +def test_nexus_operation_link_with_unparseable_url_is_ignored(): + # The canonical path is /nexus-operations/{op_id}/{run_id}/details; a URL missing the + # run-id/details suffix (e.g. the legacy ?runID= form) does not parse. link = nexusrpc.Link( type=temporalio.api.common.v1.Link.NexusOperation.DESCRIPTOR.full_name, - url="temporal:///namespaces/ns/nexus-operations/op-id?runID=one&runID=two", + url="temporal:///namespaces/ns/nexus-operations/op-id?runID=run-id", ) assert temporalio.nexus._link_conversion.nexus_link_to_temporal_link(link) is None diff --git a/tests/nexus/test_signal_link_propagation.py b/tests/nexus/test_signal_link_propagation.py new file mode 100644 index 000000000..daff71c78 --- /dev/null +++ b/tests/nexus/test_signal_link_propagation.py @@ -0,0 +1,558 @@ +"""Unit tests for Nexus signal-backlink propagation. + +These exercise the in/out link propagation that happens when a Nexus operation handler issues a +signal, signal-with-start, or start-workflow RPC, against a mocked workflow service. +The corresponding end-to-end behavior requires a real server with EnableCHASMSignalBacklinks=true and is therefore +and is therefore not covered here. +""" + +from __future__ import annotations + +from collections.abc import Generator +from typing import Any +from unittest import mock + +import nexusrpc +import nexusrpc.handler +import pytest +from nexusrpc.handler import ( + OperationHandler, + StartOperationContext, + StartOperationResultAsync, + service_handler, + sync_operation, +) +from nexusrpc.handler._decorators import operation_handler + +import temporalio.api.common.v1 +import temporalio.api.enums.v1 +import temporalio.api.nexus.v1 +import temporalio.api.workflowservice.v1 +import temporalio.common +import temporalio.converter +import temporalio.nexus._link_conversion +import temporalio.nexus._operation_context +from temporalio.client._impl import _ClientImpl +from temporalio.client._interceptor import ( + SignalWorkflowInput, + StartWorkflowInput, +) +from temporalio.nexus._operation_context import _TemporalStartOperationContext +from temporalio.worker._nexus import _NexusTaskCancellation, _NexusWorker + +NAMESPACE = "test-namespace" +WORKFLOW_ID = "wf-target" + + +def _workflow_event_link( + workflow_id: str, + run_id: str, + event_type: temporalio.api.enums.v1.EventType.ValueType, +) -> temporalio.api.common.v1.Link: + return temporalio.api.common.v1.Link( + workflow_event=temporalio.api.common.v1.Link.WorkflowEvent( + namespace=NAMESPACE, + workflow_id=workflow_id, + run_id=run_id, + event_ref=temporalio.api.common.v1.Link.WorkflowEvent.EventReference( + event_type=event_type, + ), + ) + ) + + +def _inbound_nexus_link() -> temporalio.api.common.v1.Link: + return _workflow_event_link( + "caller-wf", + "caller-run", + temporalio.api.enums.v1.EventType.EVENT_TYPE_NEXUS_OPERATION_SCHEDULED, + ) + + +@pytest.fixture +def nexus_ctx() -> Generator[_TemporalStartOperationContext]: + """Install a Nexus start-operation context with a single inbound link. + + The inbound link is provided in nexusrpc.Link form, exactly as the worker populates it from + the inbound Nexus task. Yields the temporal context so tests can inspect outbound_links. + """ + inbound = temporalio.nexus._link_conversion.workflow_event_to_nexus_link( + _inbound_nexus_link().workflow_event + ) + nexus_context = nexusrpc.handler.StartOperationContext( + service="svc", + operation="op", + headers={}, + request_id="req-id", + callback_url=None, + inbound_links=[inbound], + callback_headers={}, + task_cancellation=_NexusTaskCancellation(), + ) + ctx = temporalio.nexus._operation_context._TemporalStartOperationContext( + nexus_context=nexus_context, + client=mock.MagicMock(namespace=NAMESPACE), + info=lambda: temporalio.nexus.Info( + endpoint="endpoint", namespace=NAMESPACE, task_queue="tq" + ), + _runtime_metric_meter=mock.MagicMock(), + _worker_shutdown_event=mock.MagicMock(), + ) + token = temporalio.nexus._operation_context._temporal_start_operation_context.set( + ctx + ) + try: + yield ctx + finally: + temporalio.nexus._operation_context._temporal_start_operation_context.reset( + token + ) + + +def _make_client_impl(workflow_service: Any) -> _ClientImpl: + client = mock.MagicMock() + client.namespace = NAMESPACE + client.identity = "test-identity" + client.workflow_service = workflow_service + client.data_converter = temporalio.converter.DataConverter.default + return _ClientImpl(client) + + +def _signal_input() -> SignalWorkflowInput: + return SignalWorkflowInput( + id=WORKFLOW_ID, + run_id=None, + signal="test-signal", + args=[], + headers={}, + rpc_metadata={}, + rpc_timeout=None, + ) + + +def _start_input(start_signal: str | None = None) -> StartWorkflowInput: + return StartWorkflowInput( + workflow="TestWorkflow", + args=[], + id=WORKFLOW_ID, + task_queue="tq", + execution_timeout=None, + run_timeout=None, + task_timeout=None, + id_reuse_policy=temporalio.common.WorkflowIDReusePolicy.ALLOW_DUPLICATE, + id_conflict_policy=temporalio.common.WorkflowIDConflictPolicy.UNSPECIFIED, + retry_policy=None, + cron_schedule="", + memo=None, + search_attributes=None, + start_delay=None, + headers={}, + start_signal=start_signal, + start_signal_args=[], + static_summary=None, + static_details=None, + ret_type=None, + rpc_metadata={}, + rpc_timeout=None, + request_eager_start=False, + priority=temporalio.common.Priority.default, + callbacks=[], + links=[], + request_id=None, + versioning_override=None, + ) + + +def _outbound_link_urls(ctx: Any) -> list[str]: + return [link.url for link in ctx.nexus_context.outbound_links] + + +# ── signal ──────────────────────────────────────────────────────────────────────────────── + + +async def test_signal_forwards_inbound_links_and_captures_response_backlink( + nexus_ctx: _TemporalStartOperationContext, +) -> None: + response_link = _workflow_event_link( + WORKFLOW_ID, + "target-run", + temporalio.api.enums.v1.EventType.EVENT_TYPE_WORKFLOW_EXECUTION_SIGNALED, + ) + workflow_service = mock.MagicMock() + workflow_service.signal_workflow_execution = mock.AsyncMock( + return_value=temporalio.api.workflowservice.v1.SignalWorkflowExecutionResponse( + link=response_link + ) + ) + impl = _make_client_impl(workflow_service) + + await impl.signal_workflow(_signal_input()) + + # Forward: the request carries the single inbound link. + sent = workflow_service.signal_workflow_execution.call_args.args[0] + assert len(sent.links) == 1 + assert sent.links[0] == _inbound_nexus_link() + + # Backward: the response link is added to the operation's outbound links (as a Nexus link). + assert len(nexus_ctx.nexus_context.outbound_links) == 1 + assert "wf-target" in _outbound_link_urls(nexus_ctx)[0] + + +async def test_signal_against_older_server_captures_no_backlink( + nexus_ctx: _TemporalStartOperationContext, +) -> None: + workflow_service = mock.MagicMock() + workflow_service.signal_workflow_execution = mock.AsyncMock( + return_value=temporalio.api.workflowservice.v1.SignalWorkflowExecutionResponse() + ) + impl = _make_client_impl(workflow_service) + + await impl.signal_workflow(_signal_input()) + + # Forward direction still works regardless of server version. + sent = workflow_service.signal_workflow_execution.call_args.args[0] + assert len(sent.links) == 1 + + # Backward: no backlink because the server returned no link. + assert nexus_ctx.nexus_context.outbound_links == [] + + +async def test_multiple_signals_accumulate_all_backlinks( + nexus_ctx: _TemporalStartOperationContext, +) -> None: + first = _workflow_event_link( + "callee-a", + "run-a", + temporalio.api.enums.v1.EventType.EVENT_TYPE_WORKFLOW_EXECUTION_SIGNALED, + ) + second = _workflow_event_link( + "callee-b", + "run-b", + temporalio.api.enums.v1.EventType.EVENT_TYPE_WORKFLOW_EXECUTION_SIGNALED, + ) + workflow_service = mock.MagicMock() + workflow_service.signal_workflow_execution = mock.AsyncMock( + side_effect=[ + temporalio.api.workflowservice.v1.SignalWorkflowExecutionResponse( + link=first + ), + temporalio.api.workflowservice.v1.SignalWorkflowExecutionResponse( + link=second + ), + ] + ) + impl = _make_client_impl(workflow_service) + + await impl.signal_workflow(_signal_input()) + await impl.signal_workflow(_signal_input()) + + urls = _outbound_link_urls(nexus_ctx) + assert len(urls) == 2 + assert "callee-a" in urls[0] + assert "callee-b" in urls[1] + + +async def test_signal_outside_nexus_context_does_not_touch_links() -> None: + workflow_service = mock.MagicMock() + workflow_service.signal_workflow_execution = mock.AsyncMock( + return_value=temporalio.api.workflowservice.v1.SignalWorkflowExecutionResponse() + ) + impl = _make_client_impl(workflow_service) + + await impl.signal_workflow(_signal_input()) + + sent = workflow_service.signal_workflow_execution.call_args.args[0] + assert len(sent.links) == 0 + + +# ── signal-with-start ─────────────────────────────────────────────────────────────────────── + + +async def test_signal_with_start_forwards_inbound_links_and_captures_backlink( + nexus_ctx: _TemporalStartOperationContext, +) -> None: + response_link = _workflow_event_link( + WORKFLOW_ID, + "target-run", + temporalio.api.enums.v1.EventType.EVENT_TYPE_WORKFLOW_EXECUTION_SIGNALED, + ) + workflow_service = mock.MagicMock() + workflow_service.signal_with_start_workflow_execution = mock.AsyncMock( + return_value=temporalio.api.workflowservice.v1.SignalWithStartWorkflowExecutionResponse( + run_id="target-run", + signal_link=response_link, + ) + ) + impl = _make_client_impl(workflow_service) + + await impl.start_workflow(_start_input(start_signal="test-signal")) + + # Forward: the SignalWithStart request carries the inbound link. + sent = workflow_service.signal_with_start_workflow_execution.call_args.args[0] + assert len(sent.links) == 1 + assert sent.links[0] == _inbound_nexus_link() + + # Backward: response.signal_link is captured as an outbound Nexus link. + assert len(nexus_ctx.nexus_context.outbound_links) == 1 + assert "wf-target" in _outbound_link_urls(nexus_ctx)[0] + + +async def test_signal_with_start_against_older_server_captures_no_backlink( + nexus_ctx: _TemporalStartOperationContext, +) -> None: + workflow_service = mock.MagicMock() + workflow_service.signal_with_start_workflow_execution = mock.AsyncMock( + return_value=temporalio.api.workflowservice.v1.SignalWithStartWorkflowExecutionResponse( + run_id="target-run", + ) + ) + impl = _make_client_impl(workflow_service) + + await impl.start_workflow(_start_input(start_signal="test-signal")) + + sent = workflow_service.signal_with_start_workflow_execution.call_args.args[0] + assert len(sent.links) == 1 + assert nexus_ctx.nexus_context.outbound_links == [] + + +# ── start ───────────────────────────────────────────────────────────────────────────────── + + +async def test_start_forwards_inbound_links_and_captures_backlink( + nexus_ctx: _TemporalStartOperationContext, +) -> None: + server_link = _workflow_event_link( + WORKFLOW_ID, + "target-run", + temporalio.api.enums.v1.EventType.EVENT_TYPE_WORKFLOW_EXECUTION_STARTED, + ) + workflow_service = mock.MagicMock() + workflow_service.start_workflow_execution = mock.AsyncMock( + return_value=temporalio.api.workflowservice.v1.StartWorkflowExecutionResponse( + run_id="target-run", + link=server_link, + ) + ) + impl = _make_client_impl(workflow_service) + + await impl.start_workflow(_start_input()) + + # Forward: the start request carries the single inbound link. + sent = workflow_service.start_workflow_execution.call_args.args[0] + assert len(sent.links) == 1 + assert sent.links[0] == _inbound_nexus_link() + + # Backward: a plain start captures a backlink + assert len(nexus_ctx.nexus_context.outbound_links) == 1 + assert "wf-target" in _outbound_link_urls(nexus_ctx)[0] + + +async def test_start_against_older_server_captures_no_backlink( + nexus_ctx: _TemporalStartOperationContext, +) -> None: + workflow_service = mock.MagicMock() + workflow_service.start_workflow_execution = mock.AsyncMock( + return_value=temporalio.api.workflowservice.v1.StartWorkflowExecutionResponse( + run_id="target-run", + ) + ) + impl = _make_client_impl(workflow_service) + + await impl.start_workflow(_start_input()) + + # Forward direction still works regardless of server version. + sent = workflow_service.start_workflow_execution.call_args.args[0] + assert len(sent.links) == 1 + assert sent.links[0] == _inbound_nexus_link() + + # Backward: a plain start fabricates a backlink when the server doesn't return one. + assert len(nexus_ctx.nexus_context.outbound_links) == 1 + assert "wf-target" in _outbound_link_urls(nexus_ctx)[0] + + +async def test_start_outside_nexus_context_does_not_touch_links() -> None: + workflow_service = mock.MagicMock() + workflow_service.start_workflow_execution = mock.AsyncMock( + return_value=temporalio.api.workflowservice.v1.StartWorkflowExecutionResponse( + run_id="target-run", + ) + ) + impl = _make_client_impl(workflow_service) + + # Should not raise even though there is no Nexus context. + handle = await impl.start_workflow(_start_input()) + assert handle.result_run_id == "target-run" + sent = workflow_service.start_workflow_execution.call_args.args[0] + assert len(sent.links) == 0 + + +# ── start: on-conflict options ────────────────────────────────────────────────────────────── +# +# A start issued from inside a Nexus operation handler enables all on_conflict_options so that, +# under a WORKFLOW_ID_CONFLICT_POLICY_USE_EXISTING policy, a detected conflict attaches the +# request id, completion callbacks, and links to the existing run. + + +def _start_response() -> ( + temporalio.api.workflowservice.v1.StartWorkflowExecutionResponse +): + return temporalio.api.workflowservice.v1.StartWorkflowExecutionResponse( + run_id="target-run", + ) + + +@pytest.mark.usefixtures("nexus_ctx") +async def test_start_from_nexus_context_sets_all_on_conflict_options() -> None: + workflow_service = mock.MagicMock() + workflow_service.start_workflow_execution = mock.AsyncMock( + return_value=_start_response() + ) + impl = _make_client_impl(workflow_service) + + await impl.start_workflow(_start_input()) + + sent = workflow_service.start_workflow_execution.call_args.args[0] + assert sent.HasField("on_conflict_options") + assert sent.on_conflict_options.attach_request_id + assert sent.on_conflict_options.attach_completion_callbacks + assert sent.on_conflict_options.attach_links + + +@pytest.mark.usefixtures("nexus_ctx") +async def test_backing_workflow_start_sets_on_conflict_options_without_duplicating_links() -> ( + None +): + workflow_service = mock.MagicMock() + workflow_service.start_workflow_execution = mock.AsyncMock( + return_value=_start_response() + ) + impl = _make_client_impl(workflow_service) + + # The nexus-backing workflow carries its inbound links via input.links (start_workflow + # forwards them as links=), so the build path must enable on_conflict_options but must not + # also re-add the context's request links. + start_input = _start_input() + start_input.links = [_inbound_nexus_link()] + with temporalio.nexus._operation_context._nexus_backing_workflow_start_context(): + await impl.start_workflow(start_input) + + sent = workflow_service.start_workflow_execution.call_args.args[0] + assert sent.HasField("on_conflict_options") + assert sent.on_conflict_options.attach_request_id + assert sent.on_conflict_options.attach_completion_callbacks + assert sent.on_conflict_options.attach_links + # The single inbound link appears exactly once, not duplicated. + assert len(sent.links) == 1 + assert sent.links[0] == _inbound_nexus_link() + + +async def test_start_outside_nexus_context_leaves_on_conflict_options_unset() -> None: + workflow_service = mock.MagicMock() + workflow_service.start_workflow_execution = mock.AsyncMock( + return_value=_start_response() + ) + impl = _make_client_impl(workflow_service) + + await impl.start_workflow(_start_input()) + + sent = workflow_service.start_workflow_execution.call_args.args[0] + assert not sent.HasField("on_conflict_options") + + +# ── handler-level: backlinks land on the StartOperationResponse ────────────────────────────── + +# A response link that a handler stashes on ctx.outbound_links, mimicking what a signal RPC inside +# the handler would do via _add_response_link. +_BACKLINK = temporalio.nexus._link_conversion.workflow_event_to_nexus_link( + temporalio.api.common.v1.Link.WorkflowEvent( + namespace=NAMESPACE, + workflow_id="callee-wf", + run_id="callee-run-id", + event_ref=temporalio.api.common.v1.Link.WorkflowEvent.EventReference( + event_type=temporalio.api.enums.v1.EventType.EVENT_TYPE_WORKFLOW_EXECUTION_SIGNALED, + ), + ) +) + + +class _AsyncBacklinkOperation(OperationHandler): + """Stashes a backlink then returns an async result, simulating a signaling handler.""" + + async def start( + self, ctx: StartOperationContext, input: str + ) -> StartOperationResultAsync: + ctx.outbound_links.append(_BACKLINK) + return StartOperationResultAsync(token=input) + + async def cancel(self, ctx: Any, token: str) -> None: ... + + +@service_handler +class _BacklinkStashingService: + @sync_operation + async def sync_op(self, ctx: StartOperationContext, _input: str) -> str: + # Stash a backlink and return a sync result. + ctx.outbound_links.append(_BACKLINK) + return "result" + + @operation_handler + def async_op(self) -> OperationHandler[str, str]: + return _AsyncBacklinkOperation() + + +def _make_nexus_worker() -> _NexusWorker: + return _NexusWorker( + bridge_worker=lambda: mock.MagicMock(), + client=mock.MagicMock(namespace=NAMESPACE), + namespace=NAMESPACE, + task_queue="tq", + service_handlers=[_BacklinkStashingService()], + data_converter=temporalio.converter.DataConverter.default, + interceptors=[], + metric_meter=mock.MagicMock(), + executor=None, + ) + + +def _start_request( + operation: str, input: str +) -> temporalio.api.nexus.v1.StartOperationRequest: + [payload] = ( + temporalio.converter.DataConverter.default.payload_converter.to_payloads( + [input] + ) + ) + return temporalio.api.nexus.v1.StartOperationRequest( + service="_BacklinkStashingService", + operation=operation, + payload=payload, + ) + + +async def test_sync_response_includes_signal_backlinks() -> None: + worker = _make_nexus_worker() + response = await worker._start_operation( + _start_request("sync_op", "input"), + headers={}, + cancellation=_NexusTaskCancellation(), + request_deadline=None, + endpoint="endpoint", + ) + assert response.HasField("sync_success") + assert len(response.sync_success.links) == 1 + assert "callee-wf" in response.sync_success.links[0].url + + +async def test_async_response_includes_signal_backlinks() -> None: + worker = _make_nexus_worker() + response = await worker._start_operation( + _start_request("async_op", "op-token"), + headers={}, + cancellation=_NexusTaskCancellation(), + request_deadline=None, + endpoint="endpoint", + ) + assert response.HasField("async_success") + assert response.async_success.operation_token == "op-token" + assert len(response.async_success.links) == 1 + assert "callee-wf" in response.async_success.links[0].url diff --git a/tests/nexus/test_signal_link_propagation_e2e.py b/tests/nexus/test_signal_link_propagation_e2e.py new file mode 100644 index 000000000..9795fd841 --- /dev/null +++ b/tests/nexus/test_signal_link_propagation_e2e.py @@ -0,0 +1,567 @@ +"""End-to-end (server-based) tests for Nexus signal-backlink propagation. + +These exercise, against a real server, the bidirectional +link propagation that occurs when a Nexus operation handler signals (or signal-with-starts) a +workflow: + +- Forward: the caller's ``NexusOperationScheduled`` event is referenced by the callee's + ``WorkflowExecutionSignaled`` event (attached to the signal RPC the handler issues). +- Backward: a backlink pointing at the callee's ``WorkflowExecutionSignaled`` event lands on + the caller's ``NexusOperationCompleted`` event (sync handler) or ``NexusOperationStarted`` + event (async handler). + +The backward direction is produced server-side (temporalio/temporal#9897) and is gated by +``history.enableCHASMSignalBacklinks=true`` (added to the local dev-server args in +``tests/conftest.py``). The server populates the backlink's reference via ``RequestIdReference`` +rather than ``EventReference``, so backlink assertions tolerate both oneof variants of +``common.v1.Link.WorkflowEvent.reference`` (see ``_backlink_event_type``). When run against a +server that does not emit the backlink, the backward assertions are skipped. + +The forward/backward description above applies to operations scheduled by a caller workflow. The +file also covers the same handlers invoked as standalone (client-initiated) operations via +``client.create_nexus_client``; that case has no caller workflow, so the forward link is a +``NexusOperation`` link to the operation execution itself and only the forward direction is +asserted (see the standalone tests near the end of the file for details). +""" + +from __future__ import annotations + +import uuid +from dataclasses import dataclass +from datetime import timedelta + +import pytest +from nexusrpc import Operation, service +from nexusrpc.handler import ( + OperationHandler, + StartOperationContext, + StartOperationResultAsync, + service_handler, + sync_operation, +) +from nexusrpc.handler._decorators import operation_handler + +import temporalio.api.common.v1 +import temporalio.api.enums.v1 +import temporalio.api.history.v1 +import temporalio.common +from temporalio import nexus, workflow +from temporalio.client import Client, WorkflowHistory +from temporalio.service import RPCError, RPCStatusCode +from temporalio.testing import WorkflowEnvironment +from temporalio.worker import Worker +from tests.helpers import assert_eventually +from tests.helpers.nexus import make_nexus_endpoint_name + +EventType = temporalio.api.enums.v1.EventType + + +# ── Service definition ────────────────────────────────────────────────────────────────────── + + +@dataclass +class OpInput: + mode: str + callee_id: str + + +@service +class SignalingService: + op: Operation[OpInput, str] + + +# ── Callee workflow ─────────────────────────────────────────────────────────────────────── + + +@workflow.defn +class CalleeWorkflow: + def __init__(self) -> None: + self._received: list[str] = [] + self._expected = 1 + + @workflow.run + async def run(self, expected_signals: int) -> str: + self._expected = expected_signals + await workflow.wait_condition(lambda: len(self._received) >= self._expected) + return ",".join(self._received) + + @workflow.signal + def ping(self, msg: str) -> None: + self._received.append(msg) + + +# ── Caller workflow ─────────────────────────────────────────────────────────────────────── + + +@workflow.defn +class CallerWorkflow: + @workflow.run + async def run(self, mode: str, callee_id: str, task_queue: str) -> str: + client = workflow.create_nexus_client( + service=SignalingService, + endpoint=make_nexus_endpoint_name(task_queue), + ) + return await client.execute_operation( + SignalingService.op, OpInput(mode=mode, callee_id=callee_id) + ) + + +# ── Nexus service handler ───────────────────────────────────────────────────────────────── + +MODE_SYNC = "sync" +MODE_ASYNC = "async" + + +class _AsyncSignalingOperation(OperationHandler[OpInput, str]): + """Signal-with-starts the callee then returns an async result. + + The backlink stashed on ``ctx.outbound_links`` by the signal-with-start RPC is carried on + the start-operation response, landing on the caller's ``NexusOperationStarted`` event. + """ + + async def start( + self, ctx: StartOperationContext, input: OpInput + ) -> StartOperationResultAsync: + await _signal_with_start(input.callee_id, "async-signal") + return StartOperationResultAsync(token=f"async-op-{uuid.uuid4()}") + + async def cancel(self, ctx, token: str) -> None: # type: ignore[no-untyped-def] + raise NotImplementedError + + +@service_handler(service=SignalingService) +class SignalingServiceHandler: + @sync_operation + async def op(self, _ctx: StartOperationContext, input: OpInput) -> str: + # Synchronous path: signal-with-start the callee (first signal) then plain-signal it + # (second signal). Both backlinks are carried on the sync start-operation response and + # land on the caller's NexusOperationCompleted event. + await _signal_with_start(input.callee_id, "first") + await ( + nexus.client() + .get_workflow_handle(input.callee_id) + .signal(CalleeWorkflow.ping, "second") + ) + return "ok:sync" + + +# A separate service exposing only the async operation, so the caller can address it by name. +@service +class AsyncSignalingService: + op: Operation[OpInput, str] + + +@service_handler(service=AsyncSignalingService) +class AsyncSignalingServiceHandler: + @operation_handler + def op(self) -> OperationHandler[OpInput, str]: + return _AsyncSignalingOperation() + + +# A service whose handler issues a plain start_workflow (no signal, not the nexus-backing +# workflow) against an already-running callee under a USE_EXISTING conflict policy. +@service +class StartConflictService: + op: Operation[OpInput, str] + + +@service_handler(service=StartConflictService) +class StartConflictServiceHandler: + @sync_operation + async def op(self, _ctx: StartOperationContext, input: OpInput) -> str: + # Plain start_workflow from inside a Nexus operation handler, targeting the + # already-running callee with WORKFLOW_ID_CONFLICT_POLICY_USE_EXISTING. The build path + # enables on_conflict_options, so the detected conflict attaches this request's request + # id (and links) to the existing run. + await nexus.client().start_workflow( + CalleeWorkflow.run, + 1, + id=input.callee_id, + task_queue=nexus.info().task_queue, + id_conflict_policy=temporalio.common.WorkflowIDConflictPolicy.USE_EXISTING, + ) + return "ok:conflict" + + +async def _signal_with_start(callee_id: str, payload: str) -> None: + # signal-with-start exercises the SignalWithStartWorkflowExecutionResponse.signal_link + # backlink path in temporalio.client._impl. + await nexus.client().start_workflow( + CalleeWorkflow.run, + 2 if payload == "first" else 1, + id=callee_id, + task_queue=nexus.info().task_queue, + start_signal="ping", + start_signal_args=[payload], + ) + + +@workflow.defn +class AsyncSignalCallerWorkflow: + @workflow.run + async def run(self, callee_id: str, task_queue: str) -> str: + client = workflow.create_nexus_client( + service=AsyncSignalingService, + endpoint=make_nexus_endpoint_name(task_queue), + ) + handle = await client.start_operation( + AsyncSignalingService.op, OpInput(mode=MODE_ASYNC, callee_id=callee_id) + ) + # Do not await the result: the async op never completes (no completion is delivered). + # Returning the token confirms the operation reached the Started state, whose history + # event carries the backlink. + return handle.operation_token or "async-started" + + +# ── Assertion helpers ─────────────────────────────────────────────────────────────────────── + + +def _events_of_type( + history: WorkflowHistory, + event_type: temporalio.api.enums.v1.EventType.ValueType, +) -> list[temporalio.api.history.v1.HistoryEvent]: + return [e for e in history.events if e.event_type == event_type] + + +def _backlink_event_type( + we: temporalio.api.common.v1.Link.WorkflowEvent, +) -> temporalio.api.enums.v1.EventType.ValueType: + # Server PR #9897 keys backlinks via RequestIdReference rather than EventReference; accept + # either oneof variant (matches Java SignalOperationLinkingTest.assertBacklink). + if we.HasField("request_id_ref"): + return we.request_id_ref.event_type + return we.event_ref.event_type + + +def _assert_forward_link( + callee_history: WorkflowHistory, + caller_id: str, + expected_count: int, +) -> None: + signaled = _events_of_type( + callee_history, EventType.EVENT_TYPE_WORKFLOW_EXECUTION_SIGNALED + ) + assert len(signaled) == expected_count, ( + f"expected {expected_count} WorkflowExecutionSignaled events, got {len(signaled)}" + ) + for event in signaled: + assert len(event.links) >= 1, ( + "expected at least one link on each WorkflowExecutionSignaled event" + ) + we = event.links[0].workflow_event + assert we.workflow_id == caller_id, ( + "forward link should reference the caller workflow" + ) + assert we.event_ref.event_type == EventType.EVENT_TYPE_NEXUS_OPERATION_SCHEDULED + + +def _assert_backlink( + event: temporalio.api.history.v1.HistoryEvent, callee_id: str +) -> bool: + """Assert the event carries a signal-event backlink to the callee. + + Returns False (and asserts nothing) if no backlink is present, so the test soft-passes + against a server that does not emit backlinks. + """ + if len(event.links) < 1: + return False + we = event.links[0].workflow_event + assert we.workflow_id == callee_id, "backlink should reference the callee workflow" + assert _backlink_event_type(we) == EventType.EVENT_TYPE_WORKFLOW_EXECUTION_SIGNALED + return True + + +# ── Tests ───────────────────────────────────────────────────────────────────────────────── + + +async def test_sync_signal_operation_links( + client: Client, + env: WorkflowEnvironment, +) -> None: + if env.supports_time_skipping: + pytest.skip("Nexus tests don't work with time-skipping server") + + task_queue = str(uuid.uuid4()) + await env.create_nexus_endpoint(make_nexus_endpoint_name(task_queue), task_queue) + callee_id = f"callee-{uuid.uuid4()}" + caller_id = f"caller-{uuid.uuid4()}" + + async with Worker( + client, + task_queue=task_queue, + nexus_service_handlers=[SignalingServiceHandler()], + workflows=[CallerWorkflow, CalleeWorkflow], + ): + caller_handle = await client.start_workflow( + CallerWorkflow.run, + args=[MODE_SYNC, callee_id, task_queue], + id=caller_id, + task_queue=task_queue, + ) + assert await caller_handle.result() == "ok:sync" + + callee_result = await client.get_workflow_handle(callee_id).result() + assert callee_result == "first,second" + + caller_history = await caller_handle.fetch_history() + callee_history = await client.get_workflow_handle(callee_id).fetch_history() + + # Forward: both signal events on the callee reference the caller's scheduled event. + _assert_forward_link(callee_history, caller_id, expected_count=2) + + # Backward: the single NexusOperationCompleted carries backlinks to the callee. + completed = _events_of_type( + caller_history, EventType.EVENT_TYPE_NEXUS_OPERATION_COMPLETED + ) + assert len(completed) == 1, ( + f"expected exactly one NexusOperationCompleted event, got {len(completed)}" + ) + if not _assert_backlink(completed[0], callee_id): + pytest.skip( + "server did not emit a signal backlink " + "(history.enableCHASMSignalBacklinks not enabled)" + ) + + +async def test_async_signal_operation_links( + client: Client, + env: WorkflowEnvironment, +) -> None: + if env.supports_time_skipping: + pytest.skip("Nexus tests don't work with time-skipping server") + + task_queue = str(uuid.uuid4()) + await env.create_nexus_endpoint(make_nexus_endpoint_name(task_queue), task_queue) + callee_id = f"async-callee-{uuid.uuid4()}" + caller_id = f"async-caller-{uuid.uuid4()}" + + async with Worker( + client, + task_queue=task_queue, + nexus_service_handlers=[AsyncSignalingServiceHandler()], + workflows=[AsyncSignalCallerWorkflow, CalleeWorkflow], + ): + caller_handle = await client.start_workflow( + AsyncSignalCallerWorkflow.run, + args=[callee_id, task_queue], + id=caller_id, + task_queue=task_queue, + ) + # Caller returns once the async operation reaches Started; result is the op token. + assert await caller_handle.result() + + callee_result = await client.get_workflow_handle(callee_id).result() + assert callee_result == "async-signal" + + caller_history = await caller_handle.fetch_history() + callee_history = await client.get_workflow_handle(callee_id).fetch_history() + + # Forward: the single signal event on the callee references the caller's scheduled event. + _assert_forward_link(callee_history, caller_id, expected_count=1) + + # Backward: the backlink lands on NexusOperationStarted for the async response path. + started = _events_of_type( + caller_history, EventType.EVENT_TYPE_NEXUS_OPERATION_STARTED + ) + assert len(started) == 1, ( + f"expected exactly one NexusOperationStarted event, got {len(started)}" + ) + if not _assert_backlink(started[0], callee_id): + pytest.skip( + "server did not emit a signal backlink " + "(history.enableCHASMSignalBacklinks not enabled)" + ) + + +# ── Standalone (client-initiated) operations ───────────────────────────────────────────────── +# +# The tests above drive the operation from a caller workflow. The tests below invoke the same +# handlers directly via ``client.create_nexus_client`` (a standalone Nexus operation, with no +# caller workflow). The forward link still propagates, but as a ``NexusOperation`` link +# referencing the operation execution itself rather than a ``WorkflowEvent`` link to a caller's +# ``NexusOperationScheduled`` event. The backward (response) link lands on the standalone +# operation's own execution, which is a CHASM ``nexusoperation.operation`` archetype and is not +# retrievable via the workflow history API, so only the forward direction is asserted here. + + +def _assert_standalone_forward_link( + callee_history: WorkflowHistory, + operation_id: str, + expected_count: int, +) -> None: + signaled = _events_of_type( + callee_history, EventType.EVENT_TYPE_WORKFLOW_EXECUTION_SIGNALED + ) + assert len(signaled) == expected_count, ( + f"expected {expected_count} WorkflowExecutionSignaled events, got {len(signaled)}" + ) + for event in signaled: + assert len(event.links) >= 1, ( + "expected at least one link on each WorkflowExecutionSignaled event" + ) + link = event.links[0] + assert link.HasField("nexus_operation"), ( + "standalone forward link should be a NexusOperation link" + ) + assert link.nexus_operation.operation_id == operation_id, ( + "forward link should reference the standalone Nexus operation" + ) + + +async def test_standalone_sync_signal_operation_links( + client: Client, + env: WorkflowEnvironment, +) -> None: + if env.supports_time_skipping: + pytest.skip("Nexus tests don't work with time-skipping server") + + task_queue = str(uuid.uuid4()) + await env.create_nexus_endpoint(make_nexus_endpoint_name(task_queue), task_queue) + callee_id = f"standalone-callee-{uuid.uuid4()}" + operation_id = f"standalone-op-{uuid.uuid4()}" + + async with Worker( + client, + task_queue=task_queue, + nexus_service_handlers=[SignalingServiceHandler()], + workflows=[CalleeWorkflow], + ): + nexus_client = client.create_nexus_client( + service=SignalingService, + endpoint=make_nexus_endpoint_name(task_queue), + ) + handle = await nexus_client.start_operation( + SignalingService.op, + OpInput(mode=MODE_SYNC, callee_id=callee_id), + id=operation_id, + schedule_to_close_timeout=timedelta(seconds=20), + ) + assert await handle.result() == "ok:sync" + + callee_result = await client.get_workflow_handle(callee_id).result() + assert callee_result == "first,second" + + callee_history = await client.get_workflow_handle(callee_id).fetch_history() + + # Forward: both signal events on the callee reference the standalone Nexus operation. + _assert_standalone_forward_link(callee_history, operation_id, expected_count=2) + + +async def test_standalone_async_signal_operation_links( + client: Client, + env: WorkflowEnvironment, +) -> None: + if env.supports_time_skipping: + pytest.skip("Nexus tests don't work with time-skipping server") + + task_queue = str(uuid.uuid4()) + await env.create_nexus_endpoint(make_nexus_endpoint_name(task_queue), task_queue) + callee_id = f"standalone-async-callee-{uuid.uuid4()}" + operation_id = f"standalone-async-op-{uuid.uuid4()}" + + async with Worker( + client, + task_queue=task_queue, + nexus_service_handlers=[AsyncSignalingServiceHandler()], + workflows=[CalleeWorkflow], + ): + nexus_client = client.create_nexus_client( + service=AsyncSignalingService, + endpoint=make_nexus_endpoint_name(task_queue), + ) + # The async operation never completes (no completion is delivered), so we do not await + # its result; the handler signals the callee during start. + await nexus_client.start_operation( + AsyncSignalingService.op, + OpInput(mode=MODE_ASYNC, callee_id=callee_id), + id=operation_id, + schedule_to_close_timeout=timedelta(seconds=20), + ) + + async def _callee_result() -> str: + # The callee is signal-with-started from the handler; tolerate the brief window + # before it exists. + try: + return await client.get_workflow_handle(callee_id).result() + except RPCError as err: + if err.status == RPCStatusCode.NOT_FOUND: + raise AssertionError("callee not created yet") + raise + + assert await assert_eventually(_callee_result) == "async-signal" + + callee_history = await client.get_workflow_handle(callee_id).fetch_history() + + # Forward: the single signal event on the callee references the standalone operation. + _assert_standalone_forward_link(callee_history, operation_id, expected_count=1) + + +# ── on-conflict options for a plain start from a handler ────────────────────────────────────── +# +# When a Nexus operation handler issues a plain start_workflow (no signal, not the nexus-backing +# workflow) against an already-running workflow under a USE_EXISTING conflict policy, the SDK +# enables on_conflict_options so the server attaches this request's request id (and links) to the +# existing run. The attachment surfaces as a WorkflowExecutionOptionsUpdated event on the +# existing workflow's history. Older servers may not emit it, so the assertion soft-skips. + + +async def test_start_from_handler_attaches_on_conflict_options( + client: Client, + env: WorkflowEnvironment, +) -> None: + if env.supports_time_skipping: + pytest.skip("Nexus tests don't work with time-skipping server") + + task_queue = str(uuid.uuid4()) + await env.create_nexus_endpoint(make_nexus_endpoint_name(task_queue), task_queue) + callee_id = f"conflict-callee-{uuid.uuid4()}" + operation_id = f"conflict-op-{uuid.uuid4()}" + + async with Worker( + client, + task_queue=task_queue, + nexus_service_handlers=[StartConflictServiceHandler()], + workflows=[CalleeWorkflow], + ): + # Start the callee first so the handler's start_workflow hits a conflict. + callee_handle = await client.start_workflow( + CalleeWorkflow.run, + 1, + id=callee_id, + task_queue=task_queue, + ) + + nexus_client = client.create_nexus_client( + service=StartConflictService, + endpoint=make_nexus_endpoint_name(task_queue), + ) + handle = await nexus_client.start_operation( + StartConflictService.op, + OpInput(mode=MODE_SYNC, callee_id=callee_id), + id=operation_id, + schedule_to_close_timeout=timedelta(seconds=20), + ) + # USE_EXISTING resolves the conflict to the existing run; the operation succeeds. + assert await handle.result() == "ok:conflict" + + # Release the callee so it terminates cleanly, then read its history. + await callee_handle.signal(CalleeWorkflow.ping, "done") + assert await callee_handle.result() == "done" + callee_history = await callee_handle.fetch_history() + + updated = _events_of_type( + callee_history, EventType.EVENT_TYPE_WORKFLOW_EXECUTION_OPTIONS_UPDATED + ) + if not updated: + pytest.skip( + "server did not emit a WorkflowExecutionOptionsUpdated event " + "(on_conflict_options not honored by this server version)" + ) + # The conflict resolution attached this start request's request id to the existing run, + # which only happens because on_conflict_options.attach_request_id was set on the request. + assert any( + e.workflow_execution_options_updated_event_attributes.attached_request_id + for e in updated + ), ( + "expected a WorkflowExecutionOptionsUpdated event carrying an attached request id" + ) From 7aa567c8159ada9a316397b09c2708e97fdc6aec Mon Sep 17 00:00:00 2001 From: Tim Conley Date: Thu, 25 Jun 2026 09:36:06 -0700 Subject: [PATCH 145/226] Use endpoint for system Nexus detection (#1616) --- scripts/gen_payload_visitor.py | 13 ++- temporalio/bridge/_visitor.py | 10 +-- temporalio/nexus/system/__init__.py | 39 +++------ temporalio/nexus/system/_payload_visitor.py | 6 +- temporalio/worker/_workflow_instance.py | 4 +- tests/nexus/test_temporal_system_nexus.py | 87 +++++++++++++++++++++ tests/worker/test_visitor.py | 1 + 7 files changed, 110 insertions(+), 50 deletions(-) diff --git a/scripts/gen_payload_visitor.py b/scripts/gen_payload_visitor.py index da1be23ea..efe9c0df2 100644 --- a/scripts/gen_payload_visitor.py +++ b/scripts/gen_payload_visitor.py @@ -188,13 +188,11 @@ async def visit( async def _visit_nexus_operation_input_payload( self, fs: VisitorFunctions, - service: str, - operation: str, + endpoint: str, payload: Payload, ) -> None: new_payload = await temporalio.nexus.system.maybe_visit_payload( - service, - operation, + endpoint, payload, fs, self.skip_search_attributes, @@ -292,8 +290,7 @@ def walk(self, desc: Descriptor) -> bool: ( "system_nexus", field.name, - "o.service", - "o.operation", + "o.endpoint", "o.input", ) ) @@ -406,11 +403,11 @@ def walk(self, desc: Descriptor) -> bool: ) ) elif item[0] == "system_nexus": - _, field_name, service_expr, operation_expr, payload_expr = item + _, field_name, endpoint_expr, payload_expr = item lines.append( f' if o.HasField("{field_name}"):\n' " await self._visit_nexus_operation_input_payload(\n" - f" fs, {service_expr}, {operation_expr}, {payload_expr}\n" + f" fs, {endpoint_expr}, {payload_expr}\n" " )" ) else: # oneof_group diff --git a/temporalio/bridge/_visitor.py b/temporalio/bridge/_visitor.py index 5ec2b0547..4e258b9a1 100644 --- a/temporalio/bridge/_visitor.py +++ b/temporalio/bridge/_visitor.py @@ -58,13 +58,11 @@ async def visit(self, fs: VisitorFunctions, root: Any) -> None: async def _visit_nexus_operation_input_payload( self, fs: VisitorFunctions, - service: str, - operation: str, + endpoint: str, payload: Payload, ) -> None: new_payload = await temporalio.nexus.system.maybe_visit_payload( - service, - operation, + endpoint, payload, fs, self.skip_search_attributes, @@ -476,9 +474,7 @@ async def _visit_coresdk_workflow_commands_ScheduleNexusOperation( self, fs: VisitorFunctions, o: Any ): if o.HasField("input"): - await self._visit_nexus_operation_input_payload( - fs, o.service, o.operation, o.input - ) + await self._visit_nexus_operation_input_payload(fs, o.endpoint, o.input) async def _visit_coresdk_workflow_commands_WorkflowCommand( self, fs: VisitorFunctions, o: Any diff --git a/temporalio/nexus/system/__init__.py b/temporalio/nexus/system/__init__.py index d4ab868c4..21c5a1408 100644 --- a/temporalio/nexus/system/__init__.py +++ b/temporalio/nexus/system/__init__.py @@ -2,16 +2,12 @@ from __future__ import annotations -import typing - -import google.protobuf.message -import nexusrpc - import temporalio.api.common.v1 import temporalio.converter from temporalio.bridge._visitor_functions import VisitorFunctions from temporalio.converter import BinaryProtoPayloadConverter, CompositePayloadConverter -from temporalio.nexus.system import workflow_service + +TEMPORAL_SYSTEM_ENDPOINT = "__temporal_system" class SystemNexusPayloadConverter(CompositePayloadConverter): @@ -22,32 +18,23 @@ def __init__(self) -> None: super().__init__(BinaryProtoPayloadConverter()) -def _operation( - service: str, operation: str -) -> nexusrpc.Operation[typing.Any, typing.Any] | None: - return workflow_service.__nexus_operation_registry__.get((service, operation)) +def is_system_endpoint(endpoint: str) -> bool: + """Return whether a Nexus endpoint is the Temporal system endpoint.""" + return endpoint == TEMPORAL_SYSTEM_ENDPOINT async def maybe_visit_payload( - service: str, - operation: str, + endpoint: str, payload: temporalio.api.common.v1.Payload, visitor_functions: VisitorFunctions, skip_search_attributes: bool, ) -> temporalio.api.common.v1.Payload | None: - """Visit nested payloads if the payload is a recognized system Nexus envelope.""" - operation_def = _operation(service, operation) - if operation_def is None: - return None - input_type = operation_def.input_type - if not ( - isinstance(input_type, type) - and issubclass(input_type, google.protobuf.message.Message) - ): + """Visit nested payloads if the payload is for the Temporal system endpoint.""" + if not is_system_endpoint(endpoint): return None payload_converter = get_payload_converter() - value = payload_converter.from_payload(payload, input_type) + value = payload_converter.from_payload(payload) from ._payload_visitor import PayloadVisitor await PayloadVisitor(skip_search_attributes=skip_search_attributes).visit( @@ -56,19 +43,15 @@ async def maybe_visit_payload( return payload_converter.to_payload(value) -def is_system_operation(service: str, operation: str) -> bool: - """Return whether a Nexus operation uses a generated system envelope.""" - return _operation(service, operation) is not None - - def get_payload_converter() -> temporalio.converter.PayloadConverter: """Return the fixed payload converter for system Nexus outer envelopes.""" return SystemNexusPayloadConverter() __all__ = [ + "TEMPORAL_SYSTEM_ENDPOINT", "get_payload_converter", - "is_system_operation", + "is_system_endpoint", "maybe_visit_payload", "SystemNexusPayloadConverter", ] diff --git a/temporalio/nexus/system/_payload_visitor.py b/temporalio/nexus/system/_payload_visitor.py index b569e2c19..5b4178ff1 100644 --- a/temporalio/nexus/system/_payload_visitor.py +++ b/temporalio/nexus/system/_payload_visitor.py @@ -58,13 +58,11 @@ async def visit(self, fs: VisitorFunctions, root: Any) -> None: async def _visit_nexus_operation_input_payload( self, fs: VisitorFunctions, - service: str, - operation: str, + endpoint: str, payload: Payload, ) -> None: new_payload = await temporalio.nexus.system.maybe_visit_payload( - service, - operation, + endpoint, payload, fs, self.skip_search_attributes, diff --git a/temporalio/worker/_workflow_instance.py b/temporalio/worker/_workflow_instance.py index ff92d6bac..74edc66b7 100644 --- a/temporalio/worker/_workflow_instance.py +++ b/temporalio/worker/_workflow_instance.py @@ -2090,9 +2090,7 @@ async def operation_handle_fn() -> OutputT: payload_converter = ( temporalio.nexus.system.get_payload_converter() - if temporalio.nexus.system.is_system_operation( - input.service, input.operation_name - ) + if temporalio.nexus.system.is_system_endpoint(input.endpoint) else self._context_free_payload_converter ) handle = _NexusOperationHandle( diff --git a/tests/nexus/test_temporal_system_nexus.py b/tests/nexus/test_temporal_system_nexus.py index 532cd4974..b689ee8d9 100644 --- a/tests/nexus/test_temporal_system_nexus.py +++ b/tests/nexus/test_temporal_system_nexus.py @@ -15,6 +15,10 @@ import temporalio.converter import temporalio.nexus.system as nexus_system from temporalio import workflow +from temporalio.bridge._visitor import PayloadVisitor +from temporalio.bridge.proto.workflow_completion.workflow_completion_pb2 import ( + WorkflowActivationCompletion, +) from temporalio.client import Client from temporalio.converter import ExternalStorage, PayloadCodec from temporalio.testing import WorkflowEnvironment @@ -139,6 +143,89 @@ def _assert_start_nexus_operation_interceptor_trace() -> None: assert request.workflow_type.name == "test-workflow" +class _MarkingPayloadVisitor: + def __init__(self) -> None: + self.visited_payload_count = 0 + self.system_envelope_count = 0 + + async def visit_payload(self, payload: temporalio.api.common.v1.Payload) -> None: + self.visited_payload_count += 1 + payload.metadata["visited"] = b"true" + + async def visit_payloads( + self, payloads: Sequence[temporalio.api.common.v1.Payload] + ) -> None: + for payload in payloads: + await self.visit_payload(payload) + + async def visit_system_nexus_envelope( + self, payload: temporalio.api.common.v1.Payload + ) -> None: + _ = payload + self.system_envelope_count += 1 + + +def _new_schedule_nexus_completion( + endpoint: str, payload: temporalio.api.common.v1.Payload +) -> WorkflowActivationCompletion: + completion = WorkflowActivationCompletion() + command = completion.successful.commands.add() + schedule = command.schedule_nexus_operation + schedule.seq = 1 + schedule.endpoint = endpoint + schedule.service = "not-a-registered-system-service" + schedule.operation = "NotARegisteredSystemOperation" + schedule.input.CopyFrom(payload) + return completion + + +def _new_system_nexus_request_payload() -> temporalio.api.common.v1.Payload: + nested_payload = temporalio.converter.PayloadConverter.default.to_payload( + "workflow-input" + ) + assert nested_payload is not None + request = workflowservice_pb2.SignalWithStartWorkflowExecutionRequest() + request.input.payloads.add().CopyFrom(nested_payload) + payload = nexus_system.get_payload_converter().to_payload(request) + assert payload is not None + return payload + + +async def test_schedule_system_nexus_endpoint_ignores_operation_registry() -> None: + completion = _new_schedule_nexus_completion( + nexus_system.TEMPORAL_SYSTEM_ENDPOINT, + _new_system_nexus_request_payload(), + ) + visitor = _MarkingPayloadVisitor() + + await PayloadVisitor().visit(visitor, completion) + + schedule = completion.successful.commands[0].schedule_nexus_operation + decoded = nexus_system.get_payload_converter().from_payload(schedule.input) + assert isinstance( + decoded, workflowservice_pb2.SignalWithStartWorkflowExecutionRequest + ) + assert decoded.input.payloads[0].metadata["visited"] == b"true" + assert "visited" not in schedule.input.metadata + assert visitor.visited_payload_count == 1 + assert visitor.system_envelope_count == 1 + + +async def test_schedule_non_system_nexus_visits_input_as_regular_payload() -> None: + completion = _new_schedule_nexus_completion( + "not-the-system-endpoint", + _new_system_nexus_request_payload(), + ) + visitor = _MarkingPayloadVisitor() + + await PayloadVisitor().visit(visitor, completion) + + schedule = completion.successful.commands[0].schedule_nexus_operation + assert schedule.input.metadata["visited"] == b"true" + assert visitor.visited_payload_count == 1 + assert visitor.system_envelope_count == 0 + + def _build_proto_sample(message_type: type[Message]) -> Message: message = message_type() _populate_proto_sample(message) diff --git a/tests/worker/test_visitor.py b/tests/worker/test_visitor.py index 7c06aa199..bd4004625 100644 --- a/tests/worker/test_visitor.py +++ b/tests/worker/test_visitor.py @@ -371,6 +371,7 @@ async def _visit(self) -> None: WorkflowCommand( schedule_nexus_operation=ScheduleNexusOperation( seq=1, + endpoint=nexus_system.TEMPORAL_SYSTEM_ENDPOINT, service="temporal.api.workflowservice.v1.WorkflowService", operation="SignalWithStartWorkflowExecution", input=payload, From e5c27a04704ec82eb884b27d3c8147666fcd668e Mon Sep 17 00:00:00 2001 From: Tim Conley Date: Fri, 26 Jun 2026 07:45:37 -0700 Subject: [PATCH 146/226] Update bridge Cargo dependencies (#1617) --- temporalio/bridge/Cargo.lock | 279 +++++++++-------------------------- 1 file changed, 66 insertions(+), 213 deletions(-) diff --git a/temporalio/bridge/Cargo.lock b/temporalio/bridge/Cargo.lock index c3a0a9e72..25093dcd4 100644 --- a/temporalio/bridge/Cargo.lock +++ b/temporalio/bridge/Cargo.lock @@ -148,9 +148,9 @@ checksum = "b4388bee8683e3d04af747c73422af53102d2bd24d9eadb6cbc100baef4b43f8" [[package]] name = "bon" -version = "3.9.1" +version = "3.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f47dbe92550676ee653353c310dfb9cf6ba17ee70396e1f7cf0a2020ad49b2fe" +checksum = "a602c73c7b0148ec6d12af6fd5cc7a46e2eacc8878271a999abac56eed12f561" dependencies = [ "bon-macros", "rustversion", @@ -158,9 +158,9 @@ dependencies = [ [[package]] name = "bon-macros" -version = "3.9.1" +version = "3.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "519bd3116aeeb42d5372c29d982d16d0170d3d4a5ed85fc7dd91642ffff3c67c" +checksum = "6dee98b0db6a962de883bf5d20362dee4d7ca0d12fe39a7c6c73c844e1cd7c1f" dependencies = [ "darling", "ident_case", @@ -179,9 +179,9 @@ checksum = "72f5acc6cb2ba439de613abc23857ec3d78374d8ed5ac84e9d11336e87da8649" [[package]] name = "bytes" -version = "1.11.1" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e748733b7cbc798e1434b6ac524f0c1ff2ab456fe201501e6497c8417a4fc33" +checksum = "8ae3f5d315924270530207e2a68396c3cc547f6dca3fbdca317cfb1a51edb593" [[package]] name = "bzip2" @@ -194,9 +194,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.2.63" +version = "1.2.65" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "556e016178bb5662a08681bbe0f00f8e17631781a4dfc8c45e466e4b185ec27f" +checksum = "e228eec9be7c17ccb640b59b36a5cd805ea2a564a4c5e162c2f659fea30d3b96" dependencies = [ "find-msvc-tools", "jobserver", @@ -218,9 +218,9 @@ checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" [[package]] name = "chacha20" -version = "0.10.0" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f8d983286843e49675a4b7a2d174efe136dc93a18d69130dd18198a6c167601" +checksum = "d524456ba66e72eb8b115ff89e01e497f8e6d11d78b70b1aa13c0fbd97540a81" dependencies = [ "cfg-if", "cpufeatures", @@ -705,23 +705,21 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.4.2" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0de51e6874e94e7bf76d726fc5d13ba782deca734ff60d5bb2fb2607c7406555" +checksum = "300e883d756b2e4ec94e02791f39b04b522276138852cfc41d9fb7e904106099" dependencies = [ "cfg-if", "libc", "r-efi 6.0.0", "rand_core 0.10.1", - "wasip2", - "wasip3", ] [[package]] name = "h2" -version = "0.4.14" +version = "0.4.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "171fefbc92fe4a4de27e0698d6a5b392d6a0e333506bc49133760b3bcf948733" +checksum = "6cb093c84e8bd9b188d4c4a8cb6579fc016968d14c99882163cd3ff402a4f155" dependencies = [ "atomic-waker", "bytes", @@ -963,12 +961,6 @@ dependencies = [ "zerovec", ] -[[package]] -name = "id-arena" -version = "2.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d3067d79b975e8844ca9eb072e16b31c3c1c36928edf9c6789548c524d0d954" - [[package]] name = "ident_case" version = "1.0.1" @@ -1004,8 +996,6 @@ checksum = "d466e9454f08e4a911e14806c24e16fba1b4c121d1ea474396f396069cf949d9" dependencies = [ "equivalent", "hashbrown 0.17.1", - "serde", - "serde_core", ] [[package]] @@ -1108,9 +1098,9 @@ dependencies = [ [[package]] name = "js-sys" -version = "0.3.100" +version = "0.3.103" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2025f20d7a4fa7785846e7b63d10a76d3f1cee98ee5cb79ea59703f95e42162" +checksum = "53b44bfcdb3f8d5837a46dae1ca9660a837176eee74a28b229bc626816589102" dependencies = [ "cfg-if", "futures-util", @@ -1123,12 +1113,6 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" -[[package]] -name = "leb128fmt" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2" - [[package]] name = "libbz2-rs-sys" version = "0.2.5" @@ -1173,9 +1157,9 @@ dependencies = [ [[package]] name = "log" -version = "0.4.32" +version = "0.4.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "953f07c43838f8e6f9758cab68bf5bed85465e7587ebe0b823f1bcd81978ad3a" +checksum = "0ceec5bc11778974d1bcb055b18002eba7f4b3518b6a0081b3af5f21666da9ad" [[package]] name = "lru" @@ -1209,9 +1193,9 @@ checksum = "47e1ffaa40ddd1f3ed91f717a33c8c0ee23fff369e3aa8772b9605cc1d22f4c3" [[package]] name = "memchr" -version = "2.8.1" +version = "2.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b947ae49db0d222b1dbc6b113ce7248a3fc3a6ca21b696717bfc000ba4484d8" +checksum = "88904434abc2901f197fe8cc55f0445e7ded921dba5911dad2e2b39b48e663c4" [[package]] name = "mime" @@ -1809,9 +1793,9 @@ dependencies = [ [[package]] name = "quinn" -version = "0.11.9" +version = "0.11.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9e20a958963c291dc322d98411f541009df2ced7b5a4f2bd52337638cfccf20" +checksum = "0c1a41e437b6bbd489372cd4971de128e85c855f56c57f283d20ff016cf7c0a8" dependencies = [ "bytes", "cfg_aliases", @@ -1829,9 +1813,9 @@ dependencies = [ [[package]] name = "quinn-proto" -version = "0.11.14" +version = "0.11.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "434b42fec591c96ef50e21e886936e66d3cc3f737104fdb9b737c40ffb94c098" +checksum = "4fcb935c5bec503c2f0e306bdd3e58bb9029dcb14fa8d9ac76e3a5256ac0763e" dependencies = [ "aws-lc-rs", "bytes", @@ -1865,9 +1849,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.45" +version = "1.0.46" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924" +checksum = "dfbc457d0c7a0759a614551b11a6409e5951f6c7537be1f1b7682b9ae9230368" dependencies = [ "proc-macro2", ] @@ -1912,7 +1896,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d2e8e8bcc7961af1fdac401278c6a831614941f6164ee3bf4ce61b7edb162207" dependencies = [ "chacha20", - "getrandom 0.4.2", + "getrandom 0.4.3", "rand_core 0.10.1", ] @@ -1982,9 +1966,9 @@ dependencies = [ [[package]] name = "regex" -version = "1.12.3" +version = "1.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e10754a14b9137dd7b1e3e5b0493cc9171fdd105e0ab477f51b72e7f3ac0e276" +checksum = "f1292b7759ae1cb9ec195452d1390a074f0cd8541ab7a5a8c31cd6db45d4a6ba" dependencies = [ "aho-corasick", "memchr", @@ -2005,9 +1989,9 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.8.10" +version = "0.8.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc897dd8d9e8bd1ed8cdad82b5966c3e0ecae09fb1907d58efaa013543185d0a" +checksum = "d6f6ff9a378485b298a5286656da665ba74413d36db0979633275d2e708145d4" [[package]] name = "reqwest" @@ -2145,9 +2129,9 @@ dependencies = [ [[package]] name = "rustls" -version = "0.23.40" +version = "0.23.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef86cd5876211988985292b91c96a8f2d298df24e75989a43a3c73f2d4d8168b" +checksum = "6b92b125634d9b795e7beca796cc790df15a7fb38323bf3196fda83292d06b1f" dependencies = [ "aws-lc-rs", "log", @@ -2419,9 +2403,9 @@ dependencies = [ [[package]] name = "smallvec" -version = "1.15.1" +version = "1.15.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" +checksum = "8ed6a63f02c8539c91a8685a86f4099661ba3da017932f6ebbea6de3f0fa7c90" [[package]] name = "socket2" @@ -2453,9 +2437,9 @@ checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" [[package]] name = "syn" -version = "2.0.117" +version = "2.0.118" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99" +checksum = "1b9ae57f904213ebb649ce6895b8a66c66f0203b9319718f69a5612a065b1422" dependencies = [ "proc-macro2", "quote", @@ -2520,7 +2504,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32497e9a4c7b38532efcdebeef879707aa9f794296a4f0244f6f69e9bc8574bd" dependencies = [ "fastrand", - "getrandom 0.4.2", + "getrandom 0.4.3", "once_cell", "rustix", "windows-sys 0.61.2", @@ -3141,11 +3125,11 @@ checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" [[package]] name = "uuid" -version = "1.23.2" +version = "1.23.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d258b83ceec21034727ecee8c382cfa6c3e133699b0742c64571814fb420c9f7" +checksum = "bf80a72845275afea99e7f2b434723d3bc7e38470fcd1c7ed39a599c73319a53" dependencies = [ - "getrandom 0.4.2", + "getrandom 0.4.3", ] [[package]] @@ -3187,27 +3171,18 @@ checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" [[package]] name = "wasip2" -version = "1.0.3+wasi-0.2.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "20064672db26d7cdc89c7798c48a0fdfac8213434a1186e5ef29fd560ae223d6" -dependencies = [ - "wit-bindgen 0.57.1", -] - -[[package]] -name = "wasip3" -version = "0.4.0+wasi-0.3.0-rc-2026-01-06" +version = "1.0.4+wasi-0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5428f8bf88ea5ddc08faddef2ac4a67e390b88186c703ce6dbd955e1c145aca5" +checksum = "b67efb37e106e55ce722a510d6b5f9c17f083e5fc79afc2badeb12cc313d9487" dependencies = [ - "wit-bindgen 0.51.0", + "wit-bindgen", ] [[package]] name = "wasm-bindgen" -version = "0.2.123" +version = "0.2.126" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a254a4b10c19a76f09a27640e7ffbf9bc30bf67e16a3bf28aaefa4920fe81563" +checksum = "4b067c0c11094aef6b7a801c1e34a26affafdf3d051dba08456b868789aaf9a4" dependencies = [ "cfg-if", "once_cell", @@ -3218,9 +3193,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-futures" -version = "0.4.73" +version = "0.4.76" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54568702fabf5d4849ce2b90fadfa64168a097eaf4b351ce9df8b687a0086aaf" +checksum = "c62df1340f32221cb9c54d6a27b030e3dba64361d4a95bed55f9aacb44da291d" dependencies = [ "js-sys", "wasm-bindgen", @@ -3228,9 +3203,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.123" +version = "0.2.126" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24a40fc75b0ec6f3746ceb10d36f53a93dcd68a93b11b6445983945d79eba0dc" +checksum = "167ce5e579f6bcf889c4f7175a8a5a585de84e8ff93976ce393efa5f2837aab1" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -3238,9 +3213,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.123" +version = "0.2.126" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "908f34bd9b9ce3d4caf07b72dfab63d61504d156856c6bd3cd87fa350cf3985b" +checksum = "f3997c7839262f4ef12cf90b818d6340c18e80f263f1a94bf157d0ec4420380e" dependencies = [ "bumpalo", "proc-macro2", @@ -3251,35 +3226,13 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.123" +version = "0.2.126" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7acbf7616c27b194bbb550bf77ed0c2c3e5b7fd1260a93082b95fb7f47959b92" +checksum = "dc1b4cb0cc549fcf58d7dfc081778139b3d283a081644e833e84682ad71cea24" dependencies = [ "unicode-ident", ] -[[package]] -name = "wasm-encoder" -version = "0.244.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "990065f2fe63003fe337b932cfb5e3b80e0b4d0f5ff650e6985b1048f62c8319" -dependencies = [ - "leb128fmt", - "wasmparser", -] - -[[package]] -name = "wasm-metadata" -version = "0.244.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb0e353e6a2fbdc176932bbaab493762eb1255a7900fe0fea1a2f96c296cc909" -dependencies = [ - "anyhow", - "indexmap", - "wasm-encoder", - "wasmparser", -] - [[package]] name = "wasm-streams" version = "0.5.0" @@ -3293,23 +3246,11 @@ dependencies = [ "web-sys", ] -[[package]] -name = "wasmparser" -version = "0.244.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "47b807c72e1bac69382b3a6fb3dbe8ea4c0ed87ff5629b8685ae6b9a611028fe" -dependencies = [ - "bitflags", - "hashbrown 0.15.5", - "indexmap", - "semver", -] - [[package]] name = "web-sys" -version = "0.3.100" +version = "0.3.103" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e0871acf327f283dc6da28a1696cdc64fb355ba9f935d052021fa77f35cce69" +checksum = "8622dcb61c0bcc9fffa6938bed81210af2da9a7e4a1a834b2e37a59b6dfb6141" dependencies = [ "js-sys", "wasm-bindgen", @@ -3327,9 +3268,9 @@ dependencies = [ [[package]] name = "webpki-root-certs" -version = "1.0.7" +version = "1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f31141ce3fc3e300ae89b78c0dd67f9708061d1d2eda54b8209346fd6be9a92c" +checksum = "0d46a5a140e6f7afeccd8eae97eff335163939eac8b929834875168b29b3d267" dependencies = [ "rustls-pki-types", ] @@ -3637,100 +3578,12 @@ version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0592e1c9d151f854e6fd382574c3a0855250e1d9b2f99d9281c6e6391af352f1" -[[package]] -name = "wit-bindgen" -version = "0.51.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7249219f66ced02969388cf2bb044a09756a083d0fab1e566056b04d9fbcaa5" -dependencies = [ - "wit-bindgen-rust-macro", -] - [[package]] name = "wit-bindgen" version = "0.57.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1ebf944e87a7c253233ad6766e082e3cd714b5d03812acc24c318f549614536e" -[[package]] -name = "wit-bindgen-core" -version = "0.51.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea61de684c3ea68cb082b7a88508a8b27fcc8b797d738bfc99a82facf1d752dc" -dependencies = [ - "anyhow", - "heck", - "wit-parser", -] - -[[package]] -name = "wit-bindgen-rust" -version = "0.51.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7c566e0f4b284dd6561c786d9cb0142da491f46a9fbed79ea69cdad5db17f21" -dependencies = [ - "anyhow", - "heck", - "indexmap", - "prettyplease", - "syn", - "wasm-metadata", - "wit-bindgen-core", - "wit-component", -] - -[[package]] -name = "wit-bindgen-rust-macro" -version = "0.51.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c0f9bfd77e6a48eccf51359e3ae77140a7f50b1e2ebfe62422d8afdaffab17a" -dependencies = [ - "anyhow", - "prettyplease", - "proc-macro2", - "quote", - "syn", - "wit-bindgen-core", - "wit-bindgen-rust", -] - -[[package]] -name = "wit-component" -version = "0.244.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d66ea20e9553b30172b5e831994e35fbde2d165325bec84fc43dbf6f4eb9cb2" -dependencies = [ - "anyhow", - "bitflags", - "indexmap", - "log", - "serde", - "serde_derive", - "serde_json", - "wasm-encoder", - "wasm-metadata", - "wasmparser", - "wit-parser", -] - -[[package]] -name = "wit-parser" -version = "0.244.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ecc8ac4bc1dc3381b7f59c34f00b67e18f910c2c0f50015669dde7def656a736" -dependencies = [ - "anyhow", - "id-arena", - "indexmap", - "log", - "semver", - "serde", - "serde_derive", - "serde_json", - "unicode-xid", - "wasmparser", -] - [[package]] name = "writeable" version = "0.6.3" @@ -3772,18 +3625,18 @@ dependencies = [ [[package]] name = "zerocopy" -version = "0.8.50" +version = "0.8.52" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b065d4f0e55f82fae73202e189638116a87c55ab6b8e6c2721e13dd9d854ad1" +checksum = "ce1022995ff5ff5d841ad7d994facc23098cd40152f2c1d11cd607c6f530653f" dependencies = [ "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.8.50" +version = "0.8.52" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b631b19d36a892ab55420c92dbc83ccd79274f25be714855d3074aa71cab639" +checksum = "1ae7f38b72ec2a254e2b87ef277cf2cd4fb97cbebf944faa6f33354da0867930" dependencies = [ "proc-macro2", "quote", @@ -3813,9 +3666,9 @@ dependencies = [ [[package]] name = "zeroize" -version = "1.8.2" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b97154e67e32c85465826e8bcc1c59429aaaf107c1e4a9e53c8d8ccd5eff88d0" +checksum = "e13c156562582aa81c60cb29407084cdb54c4164760106ab78e6c5b0858cf64e" [[package]] name = "zerotrie" @@ -3868,9 +3721,9 @@ dependencies = [ [[package]] name = "zlib-rs" -version = "0.6.3" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3be3d40e40a133f9c916ee3f9f4fa2d9d63435b5fbe1bfc6d9dae0aa0ada1513" +checksum = "977347db8caa080403f6b6b7c1cda9479a8e869316f7e13a59b19076a40f94e3" [[package]] name = "zmij" From ca62ed26b6c65d6b37d3da05c4731faf6b01acf5 Mon Sep 17 00:00:00 2001 From: Kent Gruber Date: Fri, 26 Jun 2026 18:37:15 -0400 Subject: [PATCH 147/226] VLN-1613: fix checkout-below-v7 (#1622) Co-authored-by: picatz <14850816+picatz@users.noreply.github.com> --- .github/workflows/ci.yml | 8 ++++---- .github/workflows/release-publish.yml | 10 +++++----- .github/workflows/run-bench.yml | 2 +- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 9218d2901..55eb7eb56 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -36,7 +36,7 @@ jobs: runsOn: macos-latest runs-on: ${{ matrix.runsOn || matrix.os }} steps: - - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: submodules: recursive - uses: dtolnay/rust-toolchain@29eef336d9b2848a0b548edc03f92a220660cdb8 # stable @@ -104,7 +104,7 @@ jobs: timeout-minutes: 30 runs-on: ubuntu-latest steps: - - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: submodules: recursive - uses: dtolnay/rust-toolchain@29eef336d9b2848a0b548edc03f92a220660cdb8 # stable @@ -140,7 +140,7 @@ jobs: timeout-minutes: 30 runs-on: ubuntu-latest steps: - - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: submodules: recursive - uses: dtolnay/rust-toolchain@29eef336d9b2848a0b548edc03f92a220660cdb8 # stable @@ -181,7 +181,7 @@ jobs: timeout-minutes: 15 runs-on: ubuntu-latest steps: - - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: submodules: recursive - uses: dtolnay/rust-toolchain@29eef336d9b2848a0b548edc03f92a220660cdb8 # stable diff --git a/.github/workflows/release-publish.yml b/.github/workflows/release-publish.yml index 9996e2fef..3be7ad849 100644 --- a/.github/workflows/release-publish.yml +++ b/.github/workflows/release-publish.yml @@ -35,7 +35,7 @@ jobs: permissions: contents: read steps: - - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: ref: ${{ github.sha }} submodules: recursive @@ -98,7 +98,7 @@ jobs: release_sha: ${{ steps.validate_versions.outputs.sha }} version: ${{ steps.validate_versions.outputs.version }} steps: - - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: ref: ${{ github.sha }} fetch-depth: 0 @@ -193,7 +193,7 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 10 steps: - - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 - uses: ./.github/actions/release-smoke-package with: version: ${{ needs.verify_artifacts.outputs.version }} @@ -241,7 +241,7 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 10 steps: - - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 - uses: ./.github/actions/release-smoke-package with: version: ${{ needs.verify_artifacts.outputs.version }} @@ -257,7 +257,7 @@ jobs: permissions: contents: write steps: - - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: ref: ${{ needs.verify_artifacts.outputs.release_sha }} fetch-depth: 0 diff --git a/.github/workflows/run-bench.yml b/.github/workflows/run-bench.yml index 6b9a17da8..26e0b4759 100644 --- a/.github/workflows/run-bench.yml +++ b/.github/workflows/run-bench.yml @@ -29,7 +29,7 @@ jobs: runs-on: ${{ matrix.os }} steps: # Prepare - - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: submodules: recursive - uses: dtolnay/rust-toolchain@29eef336d9b2848a0b548edc03f92a220660cdb8 # stable From c4e7062bd1a09ce6bc18057274eb7fc77702f7ba Mon Sep 17 00:00:00 2001 From: Alex Mazzeo Date: Mon, 29 Jun 2026 11:01:55 -0700 Subject: [PATCH 148/226] Send SANO links in requests (#1621) * Remove filtering of nexus links when sending requests. Refactor some test helpers into shared helpers. * update changelog --- CHANGELOG.md | 1 + temporalio/client/_impl.py | 14 +-- tests/helpers/nexus.py | 99 +++++++++++++++ .../nexus/test_signal_link_propagation_e2e.py | 43 +++---- tests/nexus/test_standalone_operations.py | 114 +++++++++++++++++- tests/nexus/test_workflow_caller.py | 21 +--- 6 files changed, 237 insertions(+), 55 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f002d37d8..32527c303 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -34,6 +34,7 @@ to include examples, links to docs, or any other relevant information. loop. - Relaxed the protobuf dependency bounds to allow protobuf 7 where compatible with the selected optional dependencies. +- Standalone Nexus operation links are now forwarded on start workflow and signal requests. ### Deprecated diff --git a/temporalio/client/_impl.py b/temporalio/client/_impl.py index 4e7049985..8e33ff910 100644 --- a/temporalio/client/_impl.py +++ b/temporalio/client/_impl.py @@ -217,28 +217,18 @@ async def _build_start_workflow_execution_request( if input.request_id: req.request_id = input.request_id - # Server currently only supports workflow_event and batch_job - # link types. This filter should be removed or adapted as - # server-side support comes online. - # See https://github.com/temporalio/temporal/issues/10345 - links = [ - link - for link in input.links - if link.HasField("workflow_event") or link.HasField("batch_job") - ] - req.completion_callbacks.extend( temporalio.api.common.v1.Callback( nexus=temporalio.api.common.v1.Callback.Nexus( url=callback.url, header=callback.headers, ), - links=links, + links=input.links, ) for callback in input.callbacks ) # Links are duplicated on request for compatibility with older server versions. - req.links.extend(links) + req.links.extend(input.links) nexus_ctx = temporalio.nexus._operation_context._try_start_operation_context() if nexus_ctx is not None: diff --git a/tests/helpers/nexus.py b/tests/helpers/nexus.py index d3142f74a..0af468b44 100644 --- a/tests/helpers/nexus.py +++ b/tests/helpers/nexus.py @@ -1,3 +1,102 @@ +from collections.abc import Sequence + +import temporalio.api.common.v1 +import temporalio.api.enums.v1 +import temporalio.api.history.v1 +from temporalio.client import WorkflowHistory + + def make_nexus_endpoint_name(task_queue: str) -> str: # Create endpoints for different task queues without name collisions. return f"nexus-endpoint-{task_queue}" + + +def events_of_type( + history: WorkflowHistory, + event_type: temporalio.api.enums.v1.EventType.ValueType, +) -> list[temporalio.api.history.v1.HistoryEvent]: + return [event for event in history.events if event.event_type == event_type] + + +def links_from_workflow_execution_started_event( + event: temporalio.api.history.v1.HistoryEvent, +) -> list[temporalio.api.common.v1.Link]: + callback_links = [ + link + for callback in event.workflow_execution_started_event_attributes.completion_callbacks + for link in callback.links + ] + if callback_links: + return list(callback_links) + return list(event.links) + + +def workflow_event_link_event_type( + workflow_event: temporalio.api.common.v1.Link.WorkflowEvent, +) -> temporalio.api.enums.v1.EventType.ValueType: + if workflow_event.HasField("request_id_ref"): + return workflow_event.request_id_ref.event_type + return workflow_event.event_ref.event_type + + +def expected_nexus_operation_link( + *, + namespace: str, + operation_id: str, + run_id: str, +) -> temporalio.api.common.v1.Link: + return temporalio.api.common.v1.Link( + nexus_operation=temporalio.api.common.v1.Link.NexusOperation( + namespace=namespace, + operation_id=operation_id, + run_id=run_id, + ) + ) + + +def expected_workflow_event_link( + *, + namespace: str, + workflow_id: str, + run_id: str, + event_type: temporalio.api.enums.v1.EventType.ValueType, + event_id: int = 0, + request_id: str | None = None, +) -> temporalio.api.common.v1.Link: + if request_id is not None: + return temporalio.api.common.v1.Link( + workflow_event=temporalio.api.common.v1.Link.WorkflowEvent( + namespace=namespace, + workflow_id=workflow_id, + run_id=run_id, + request_id_ref=temporalio.api.common.v1.Link.WorkflowEvent.RequestIdReference( + request_id=request_id, + event_type=event_type, + ), + ) + ) + + return temporalio.api.common.v1.Link( + workflow_event=temporalio.api.common.v1.Link.WorkflowEvent( + namespace=namespace, + workflow_id=workflow_id, + run_id=run_id, + event_ref=temporalio.api.common.v1.Link.WorkflowEvent.EventReference( + event_id=event_id, + event_type=event_type, + ), + ) + ) + + +def assert_links_match( + links: Sequence[temporalio.api.common.v1.Link], + *expected_links: temporalio.api.common.v1.Link, +) -> None: + actual = sorted(list(links), key=_link_sort_key) + expected = sorted(list(expected_links), key=_link_sort_key) + assert actual == expected + + +def _link_sort_key(link: temporalio.api.common.v1.Link) -> bytes: + return link.SerializeToString(deterministic=True) diff --git a/tests/nexus/test_signal_link_propagation_e2e.py b/tests/nexus/test_signal_link_propagation_e2e.py index 9795fd841..e489ad8a7 100644 --- a/tests/nexus/test_signal_link_propagation_e2e.py +++ b/tests/nexus/test_signal_link_propagation_e2e.py @@ -14,8 +14,8 @@ ``history.enableCHASMSignalBacklinks=true`` (added to the local dev-server args in ``tests/conftest.py``). The server populates the backlink's reference via ``RequestIdReference`` rather than ``EventReference``, so backlink assertions tolerate both oneof variants of -``common.v1.Link.WorkflowEvent.reference`` (see ``_backlink_event_type``). When run against a -server that does not emit the backlink, the backward assertions are skipped. +``common.v1.Link.WorkflowEvent.reference`` (see ``workflow_event_link_event_type``). When run +against a server that does not emit the backlink, the backward assertions are skipped. The forward/backward description above applies to operations scheduled by a caller workflow. The file also covers the same handlers invoked as standalone (client-initiated) operations via @@ -41,7 +41,6 @@ ) from nexusrpc.handler._decorators import operation_handler -import temporalio.api.common.v1 import temporalio.api.enums.v1 import temporalio.api.history.v1 import temporalio.common @@ -51,7 +50,11 @@ from temporalio.testing import WorkflowEnvironment from temporalio.worker import Worker from tests.helpers import assert_eventually -from tests.helpers.nexus import make_nexus_endpoint_name +from tests.helpers.nexus import ( + events_of_type, + make_nexus_endpoint_name, + workflow_event_link_event_type, +) EventType = temporalio.api.enums.v1.EventType @@ -216,29 +219,12 @@ async def run(self, callee_id: str, task_queue: str) -> str: # ── Assertion helpers ─────────────────────────────────────────────────────────────────────── -def _events_of_type( - history: WorkflowHistory, - event_type: temporalio.api.enums.v1.EventType.ValueType, -) -> list[temporalio.api.history.v1.HistoryEvent]: - return [e for e in history.events if e.event_type == event_type] - - -def _backlink_event_type( - we: temporalio.api.common.v1.Link.WorkflowEvent, -) -> temporalio.api.enums.v1.EventType.ValueType: - # Server PR #9897 keys backlinks via RequestIdReference rather than EventReference; accept - # either oneof variant (matches Java SignalOperationLinkingTest.assertBacklink). - if we.HasField("request_id_ref"): - return we.request_id_ref.event_type - return we.event_ref.event_type - - def _assert_forward_link( callee_history: WorkflowHistory, caller_id: str, expected_count: int, ) -> None: - signaled = _events_of_type( + signaled = events_of_type( callee_history, EventType.EVENT_TYPE_WORKFLOW_EXECUTION_SIGNALED ) assert len(signaled) == expected_count, ( @@ -267,7 +253,10 @@ def _assert_backlink( return False we = event.links[0].workflow_event assert we.workflow_id == callee_id, "backlink should reference the callee workflow" - assert _backlink_event_type(we) == EventType.EVENT_TYPE_WORKFLOW_EXECUTION_SIGNALED + assert ( + workflow_event_link_event_type(we) + == EventType.EVENT_TYPE_WORKFLOW_EXECUTION_SIGNALED + ) return True @@ -310,7 +299,7 @@ async def test_sync_signal_operation_links( _assert_forward_link(callee_history, caller_id, expected_count=2) # Backward: the single NexusOperationCompleted carries backlinks to the callee. - completed = _events_of_type( + completed = events_of_type( caller_history, EventType.EVENT_TYPE_NEXUS_OPERATION_COMPLETED ) assert len(completed) == 1, ( @@ -360,7 +349,7 @@ async def test_async_signal_operation_links( _assert_forward_link(callee_history, caller_id, expected_count=1) # Backward: the backlink lands on NexusOperationStarted for the async response path. - started = _events_of_type( + started = events_of_type( caller_history, EventType.EVENT_TYPE_NEXUS_OPERATION_STARTED ) assert len(started) == 1, ( @@ -389,7 +378,7 @@ def _assert_standalone_forward_link( operation_id: str, expected_count: int, ) -> None: - signaled = _events_of_type( + signaled = events_of_type( callee_history, EventType.EVENT_TYPE_WORKFLOW_EXECUTION_SIGNALED ) assert len(signaled) == expected_count, ( @@ -549,7 +538,7 @@ async def test_start_from_handler_attaches_on_conflict_options( assert await callee_handle.result() == "done" callee_history = await callee_handle.fetch_history() - updated = _events_of_type( + updated = events_of_type( callee_history, EventType.EVENT_TYPE_WORKFLOW_EXECUTION_OPTIONS_UPDATED ) if not updated: diff --git a/tests/nexus/test_standalone_operations.py b/tests/nexus/test_standalone_operations.py index 10b2f17fa..8193ba7ba 100644 --- a/tests/nexus/test_standalone_operations.py +++ b/tests/nexus/test_standalone_operations.py @@ -21,6 +21,7 @@ sync_operation, ) +import temporalio.api.enums.v1 from temporalio import nexus, workflow from temporalio.client import ( CancelNexusOperationInput, @@ -36,6 +37,7 @@ OutboundInterceptor, StartNexusOperationInput, TerminateNexusOperationInput, + WorkflowHistory, WorkflowUpdateStage, ) from temporalio.common import ( @@ -56,7 +58,13 @@ from temporalio.testing import WorkflowEnvironment from temporalio.worker import Worker from tests.helpers import assert_eventually -from tests.helpers.nexus import make_nexus_endpoint_name +from tests.helpers.nexus import ( + assert_links_match, + expected_nexus_operation_link, + expected_workflow_event_link, + links_from_workflow_execution_started_event, + make_nexus_endpoint_name, +) # --------------------------------------------------------------------------- # Data types @@ -259,6 +267,61 @@ async def test_start_async_operation_and_poll_result( assert result.value == "async-hello" +async def test_started_workflow_has_link_to_standalone_nexus_operation( + client: Client, env: WorkflowEnvironment +): + """Start a workflow_run operation and verify its workflow links back to the Nexus op.""" + if env.supports_time_skipping: + pytest.skip( + "Standalone Nexus Operation tests don't work with time-skipping server" + ) + + task_queue = str(uuid.uuid4()) + endpoint_name = make_nexus_endpoint_name(task_queue) + service_handler = StandaloneTestServiceHandler() + + async with Worker( + client, + task_queue=task_queue, + nexus_service_handlers=[service_handler], + workflows=[EchoHandlerWorkflow, BlockingHandlerWorkflow], + ): + await env.create_nexus_endpoint(endpoint_name, task_queue) + + nexus_client = client.create_nexus_client( + service=StandaloneTestService, endpoint=endpoint_name + ) + op_id = str(uuid.uuid4()) + input_value = f"link-test-{uuid.uuid4()}" + workflow_id = f"blocking_async-{input_value}" + + handle = await nexus_client.start_operation( + StandaloneTestService.blocking_async, + EchoInput(value=input_value), + id=op_id, + id_reuse_policy=NexusOperationIDReusePolicy.REJECT_DUPLICATE, + id_conflict_policy=NexusOperationIDConflictPolicy.FAIL, + schedule_to_close_timeout=timedelta(seconds=30), + ) + + await service_handler.started_blocking.wait() + workflow_history = await _assert_workflow_started_with_nexus_operation_link( + client, workflow_id, handle + ) + await _assert_nexus_operation_has_link_to_started_workflow( + client, workflow_history, handle + ) + + workflow_handle = client.get_workflow_handle(workflow_id) + await workflow_handle.start_update( + BlockingHandlerWorkflow.unblock, + wait_for_stage=WorkflowUpdateStage.COMPLETED, + ) + result = await handle.result() + assert isinstance(result, EchoOutput) + assert result.value == input_value + + async def test_execute_operation(client: Client, env: WorkflowEnvironment): """Use execute_operation convenience method, verify it returns result directly.""" if env.supports_time_skipping: @@ -949,3 +1012,52 @@ async def test_interceptor_receives_inputs(client: Client, env: WorkflowEnvironm count_input = interceptor.count_calls[-1] assert isinstance(count_input, CountNexusOperationsInput) assert count_input.query == query + + +async def _assert_workflow_started_with_nexus_operation_link( + client: Client, + workflow_id: str, + operation_handle: NexusOperationHandle[Any], +) -> WorkflowHistory: + history = await client.get_workflow_handle(workflow_id).fetch_history() + started_event = next( + ( + e + for e in history.events + if ( + e.event_type + == temporalio.api.enums.v1.EventType.EVENT_TYPE_WORKFLOW_EXECUTION_STARTED + ) + ), + None, + ) + assert started_event is not None + + assert operation_handle.run_id is not None + assert_links_match( + links_from_workflow_execution_started_event(started_event), + expected_nexus_operation_link( + namespace=client.namespace, + operation_id=operation_handle.operation_id, + run_id=operation_handle.run_id, + ), + ) + return history + + +async def _assert_nexus_operation_has_link_to_started_workflow( + client: Client, + workflow_history: WorkflowHistory, + operation_handle: NexusOperationHandle[Any], +) -> None: + desc = await operation_handle.describe() + assert_links_match( + desc.raw_description.links, + expected_workflow_event_link( + namespace=client.namespace, + workflow_id=workflow_history.workflow_id, + run_id=workflow_history.run_id, + event_type=temporalio.api.enums.v1.EventType.EVENT_TYPE_WORKFLOW_EXECUTION_STARTED, + event_id=workflow_history.events[0].event_id, + ), + ) diff --git a/tests/nexus/test_workflow_caller.py b/tests/nexus/test_workflow_caller.py index df6ace9fa..89ce2719a 100644 --- a/tests/nexus/test_workflow_caller.py +++ b/tests/nexus/test_workflow_caller.py @@ -27,9 +27,7 @@ from nexusrpc.handler._decorators import operation_handler import temporalio.api -import temporalio.api.common.v1 import temporalio.api.enums.v1 -import temporalio.api.history.v1 import temporalio.nexus._operation_handlers from temporalio import nexus, workflow from temporalio.client import ( @@ -69,7 +67,10 @@ ) from tests.helpers import find_free_port, new_worker from tests.helpers.metrics import PromMetricMatcher -from tests.helpers.nexus import make_nexus_endpoint_name +from tests.helpers.nexus import ( + links_from_workflow_execution_started_event, + make_nexus_endpoint_name, +) # TODO(nexus-preview): test worker shutdown, wait_all_completed, drain etc @@ -1285,7 +1286,7 @@ async def test_untyped_caller( task_queue=task_queue, workflow_failure_exception_types=[Exception], ): - if type(response_type) == SyncResponse: + if type(response_type) is SyncResponse: response_type = SyncResponse( op_definition_type=op_definition_type, use_async_def=True, @@ -1696,7 +1697,7 @@ async def assert_handler_workflow_has_link_to_caller_workflow( == temporalio.api.enums.v1.EventType.EVENT_TYPE_WORKFLOW_EXECUTION_STARTED ) ) - links = _get_links_from_workflow_execution_started_event(wf_started_event) + links = links_from_workflow_execution_started_event(wf_started_event) if not len(links) == 1: pytest.fail( f"Expected 1 link on WorkflowExecutionStarted event, got {len(links)}" @@ -1712,16 +1713,6 @@ async def assert_handler_workflow_has_link_to_caller_workflow( ) -def _get_links_from_workflow_execution_started_event( - event: temporalio.api.history.v1.HistoryEvent, -) -> list[temporalio.api.common.v1.Link]: - [callback] = event.workflow_execution_started_event_attributes.completion_callbacks - if links := callback.links: - return list(links) - else: - return list(event.links) - - # When request_cancel is True, the NexusOperationHandle in the workflow evolves # through the following states: # start_fut result_fut handle_task w/ fut_waiter (task._must_cancel) From 7807169cb7c9ef342c1775ef5f62b9a25f693727 Mon Sep 17 00:00:00 2001 From: Tim Conley Date: Tue, 30 Jun 2026 08:11:30 -0700 Subject: [PATCH 149/226] Update core submodule and otel lock (#1626) --- temporalio/bridge/Cargo.lock | 75 +++++++++++++++++++----------------- temporalio/bridge/Cargo.toml | 6 +-- temporalio/bridge/sdk-core | 2 +- 3 files changed, 44 insertions(+), 39 deletions(-) diff --git a/temporalio/bridge/Cargo.lock b/temporalio/bridge/Cargo.lock index 25093dcd4..b71dcd615 100644 --- a/temporalio/bridge/Cargo.lock +++ b/temporalio/bridge/Cargo.lock @@ -389,7 +389,7 @@ dependencies = [ "libc", "option-ext", "redox_users", - "windows-sys 0.61.2", + "windows-sys 0.60.2", ] [[package]] @@ -483,7 +483,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" dependencies = [ "libc", - "windows-sys 0.61.2", + "windows-sys 0.52.0", ] [[package]] @@ -837,7 +837,6 @@ dependencies = [ "hyper", "hyper-util", "rustls", - "rustls-native-certs", "tokio", "tokio-rustls", "tower-service", @@ -1271,7 +1270,7 @@ version = "0.50.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5" dependencies = [ - "windows-sys 0.61.2", + "windows-sys 0.60.2", ] [[package]] @@ -1316,9 +1315,9 @@ checksum = "7c87def4c32ab89d880effc9e097653c8da5d6ef28e6b539d313baaacfbafcbe" [[package]] name = "opentelemetry" -version = "0.31.0" +version = "0.32.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b84bcd6ae87133e903af7ef497404dda70c60d0ea14895fc8a5e6722754fc2a0" +checksum = "b0142c63252a9e054e68a4c61a5778f7b14f576274d593f8ce883d191a099682" dependencies = [ "futures-core", "futures-sink", @@ -1329,22 +1328,22 @@ dependencies = [ [[package]] name = "opentelemetry-http" -version = "0.31.0" +version = "0.32.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7a6d09a73194e6b66df7c8f1b680f156d916a1a942abf2de06823dd02b7855d" +checksum = "5683015d09e2df236ef005b17f6f196f0d5f6313c4fa43a7b6a53b52776e4331" dependencies = [ "async-trait", "bytes", "http", "opentelemetry", - "reqwest 0.12.28", + "reqwest 0.13.4", ] [[package]] name = "opentelemetry-otlp" -version = "0.31.1" +version = "0.32.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f69cd6acbb9af919df949cd1ec9e5e7fdc2ef15d234b6b795aaa525cc02f71f" +checksum = "9966929966d17620d7c316c643ba62631826e10021409357772d5eea84f62c35" dependencies = [ "http", "opentelemetry", @@ -1352,17 +1351,18 @@ dependencies = [ "opentelemetry-proto", "opentelemetry_sdk", "prost", - "reqwest 0.12.28", + "reqwest 0.13.4", "thiserror", "tokio", "tonic", + "tonic-types", ] [[package]] name = "opentelemetry-proto" -version = "0.31.0" +version = "0.32.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7175df06de5eaee9909d4805a3d07e28bb752c34cab57fa9cff549da596b30f" +checksum = "56d658ba1faf63f7b9c492cfbe6e0ec365440a16132d3270c1065f7b33f1b638" dependencies = [ "opentelemetry", "opentelemetry_sdk", @@ -1373,15 +1373,16 @@ dependencies = [ [[package]] name = "opentelemetry_sdk" -version = "0.31.0" +version = "0.32.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e14ae4f5991976fd48df6d843de219ca6d31b01daaab2dad5af2badeded372bd" +checksum = "9b59f80e1ac4d5ff7a2db8fb6c80badb7f0f3f858211fba08dd9aaec750894f9" dependencies = [ "futures-channel", "futures-executor", "futures-util", "opentelemetry", "percent-encoding", + "portable-atomic", "rand 0.9.4", "thiserror", "tokio", @@ -2001,29 +2002,21 @@ checksum = "eddd3ca559203180a307f12d114c268abf583f59b03cb906fd0b3ff8646c1147" dependencies = [ "base64", "bytes", - "futures-channel", "futures-core", - "futures-util", "http", "http-body", "http-body-util", "hyper", - "hyper-rustls", "hyper-util", "js-sys", "log", "percent-encoding", "pin-project-lite", - "quinn", - "rustls", - "rustls-native-certs", - "rustls-pki-types", "serde", "serde_json", "serde_urlencoded", "sync_wrapper", "tokio", - "tokio-rustls", "tower", "tower-http", "tower-service", @@ -2041,6 +2034,7 @@ checksum = "219c5811de6525e5416c7d5d53bb656d3afdbc6c5af816e0802bcfa42dbdc1c3" dependencies = [ "base64", "bytes", + "futures-channel", "futures-core", "futures-util", "http", @@ -2124,7 +2118,7 @@ dependencies = [ "errno", "libc", "linux-raw-sys", - "windows-sys 0.61.2", + "windows-sys 0.52.0", ] [[package]] @@ -2183,7 +2177,7 @@ dependencies = [ "security-framework", "security-framework-sys", "webpki-root-certs", - "windows-sys 0.61.2", + "windows-sys 0.52.0", ] [[package]] @@ -2414,7 +2408,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "52d1cfed4120b4d927bf7c0f86d2087a4a7d6027c906d9f9d525a80573b9be51" dependencies = [ "libc", - "windows-sys 0.61.2", + "windows-sys 0.60.2", ] [[package]] @@ -2507,7 +2501,7 @@ dependencies = [ "getrandom 0.4.3", "once_cell", "rustix", - "windows-sys 0.61.2", + "windows-sys 0.52.0", ] [[package]] @@ -2533,7 +2527,7 @@ dependencies = [ [[package]] name = "temporalio-client" -version = "0.4.0" +version = "0.5.0" dependencies = [ "anyhow", "async-trait", @@ -2564,7 +2558,7 @@ dependencies = [ [[package]] name = "temporalio-common" -version = "0.4.0" +version = "0.5.0" dependencies = [ "anyhow", "async-trait", @@ -2604,7 +2598,7 @@ dependencies = [ [[package]] name = "temporalio-common-wasm" -version = "0.4.0" +version = "0.5.0" dependencies = [ "anyhow", "async-trait", @@ -2627,7 +2621,7 @@ dependencies = [ [[package]] name = "temporalio-macros" -version = "0.4.0" +version = "0.5.0" dependencies = [ "proc-macro2", "quote", @@ -2636,7 +2630,7 @@ dependencies = [ [[package]] name = "temporalio-protos" -version = "0.4.0" +version = "0.5.0" dependencies = [ "anyhow", "base64", @@ -2657,7 +2651,7 @@ dependencies = [ [[package]] name = "temporalio-sdk-core" -version = "0.4.0" +version = "0.5.0" dependencies = [ "anyhow", "async-trait", @@ -2935,6 +2929,17 @@ dependencies = [ "tonic-build", ] +[[package]] +name = "tonic-types" +version = "0.14.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73ab1b02061f83d519bba3caa167f88f261ef05720ab8ebc954ade70de3348e8" +dependencies = [ + "prost", + "prost-types", + "tonic", +] + [[package]] name = "tower" version = "0.5.3" @@ -3297,7 +3302,7 @@ version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" dependencies = [ - "windows-sys 0.61.2", + "windows-sys 0.52.0", ] [[package]] diff --git a/temporalio/bridge/Cargo.toml b/temporalio/bridge/Cargo.toml index 1e21e136d..a1c6b5e3f 100644 --- a/temporalio/bridge/Cargo.toml +++ b/temporalio/bridge/Cargo.toml @@ -28,11 +28,11 @@ pyo3 = { version = "0.29", features = [ ] } pyo3-async-runtimes = { version = "0.29", features = ["tokio-runtime"] } pythonize = "0.29" -temporalio-client = { version = "0.4", path = "./sdk-core/crates/client" } -temporalio-common = { version = "0.4", path = "./sdk-core/crates/common", features = [ +temporalio-client = { version = "0.5", path = "./sdk-core/crates/client" } +temporalio-common = { version = "0.5", path = "./sdk-core/crates/common", features = [ "envconfig", "otel" ]} -temporalio-sdk-core = { version = "0.4", path = "./sdk-core/crates/sdk-core", features = [ +temporalio-sdk-core = { version = "0.5", path = "./sdk-core/crates/sdk-core", features = [ "ephemeral-server", ] } tokio = "1.26" diff --git a/temporalio/bridge/sdk-core b/temporalio/bridge/sdk-core index d79f8681f..b9e20dad5 160000 --- a/temporalio/bridge/sdk-core +++ b/temporalio/bridge/sdk-core @@ -1 +1 @@ -Subproject commit d79f8681fad38572e2f9b6e98083590781ee0a34 +Subproject commit b9e20dad51763ca6a7e4c8b2ae7f54e1623dea18 From 9475eba0897b0addf61aa8d70dbb0ffb7c0ebde8 Mon Sep 17 00:00:00 2001 From: Tim Conley Date: Tue, 30 Jun 2026 10:30:34 -0700 Subject: [PATCH 150/226] Update uv lock (#1627) * Update uv lock * Downgrade pytest below 9.1 --- uv.lock | 3825 ++++++++++++++++++++++++++++++------------------------- 1 file changed, 2070 insertions(+), 1755 deletions(-) diff --git a/uv.lock b/uv.lock index 04fdec20e..5df24adfa 100644 --- a/uv.lock +++ b/uv.lock @@ -9,7 +9,7 @@ resolution-markers = [ ] [options] -exclude-newer = "2026-06-04T17:08:08.645499Z" +exclude-newer = "2026-06-16T15:22:43.641437Z" exclude-newer-span = "P2W" [options.exclude-newer-package] @@ -62,16 +62,16 @@ wheels = [ [[package]] name = "aiohappyeyeballs" -version = "2.6.1" +version = "2.6.2" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/26/30/f84a107a9c4331c14b2b586036f40965c128aa4fee4dda5d3d51cb14ad54/aiohappyeyeballs-2.6.1.tar.gz", hash = "sha256:c3f9d0113123803ccadfdf3f0faa505bc78e6a72d1cc4806cbd719826e943558", size = 22760, upload-time = "2025-03-12T01:42:48.764Z" } +sdist = { url = "https://files.pythonhosted.org/packages/33/c6/61a2d7b7572279226bb2e7f61d7a19ca7c90da0329c93fa0d560cbf288d8/aiohappyeyeballs-2.6.2.tar.gz", hash = "sha256:e202810ee718bd01fc6ef49e8ea53d023d5cb6b581076d7925aa499fa55dbe64", size = 22591, upload-time = "2026-05-20T15:12:24.631Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/0f/15/5bf3b99495fb160b63f95972b81750f18f7f4e02ad051373b669d17d44f2/aiohappyeyeballs-2.6.1-py3-none-any.whl", hash = "sha256:f349ba8f4b75cb25c99c5c2d84e997e485204d2902a9597802b0371f09331fb8", size = 15265, upload-time = "2025-03-12T01:42:47.083Z" }, + { url = "https://files.pythonhosted.org/packages/5f/fc/a7bf5b6e4e617b45f90f2d9d2a68519c249c81dd4fc2658c7a2a61c4f4b7/aiohappyeyeballs-2.6.2-py3-none-any.whl", hash = "sha256:4708045e2d7a6c6bdf8aafa8ed39649eaf926a4543b54560659129e3365953c4", size = 15062, upload-time = "2026-05-20T15:12:23.328Z" }, ] [[package]] name = "aiohttp" -version = "3.13.5" +version = "3.14.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "aiohappyeyeballs" }, @@ -81,112 +81,129 @@ dependencies = [ { name = "frozenlist" }, { name = "multidict" }, { name = "propcache" }, + { name = "typing-extensions", marker = "python_full_version < '3.13'" }, { name = "yarl" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/77/9a/152096d4808df8e4268befa55fba462f440f14beab85e8ad9bf990516918/aiohttp-3.13.5.tar.gz", hash = "sha256:9d98cc980ecc96be6eb4c1994ce35d28d8b1f5e5208a23b421187d1209dbb7d1", size = 7858271, upload-time = "2026-03-31T22:01:03.343Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/bd/85/cebc47ee74d8b408749073a1a46c6fcba13d170dc8af7e61996c6c9394ac/aiohttp-3.13.5-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:02222e7e233295f40e011c1b00e3b0bd451f22cf853a0304c3595633ee47da4b", size = 750547, upload-time = "2026-03-31T21:56:30.024Z" }, - { url = "https://files.pythonhosted.org/packages/05/98/afd308e35b9d3d8c9ec54c0918f1d722c86dc17ddfec272fcdbcce5a3124/aiohttp-3.13.5-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:bace460460ed20614fa6bc8cb09966c0b8517b8c58ad8046828c6078d25333b5", size = 503535, upload-time = "2026-03-31T21:56:31.935Z" }, - { url = "https://files.pythonhosted.org/packages/6f/4d/926c183e06b09d5270a309eb50fbde7b09782bfd305dec1e800f329834fb/aiohttp-3.13.5-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8f546a4dc1e6a5edbb9fd1fd6ad18134550e096a5a43f4ad74acfbd834fc6670", size = 497830, upload-time = "2026-03-31T21:56:33.654Z" }, - { url = "https://files.pythonhosted.org/packages/e4/d6/f47d1c690f115a5c2a5e8938cce4a232a5be9aac5c5fb2647efcbbbda333/aiohttp-3.13.5-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c86969d012e51b8e415a8c6ce96f7857d6a87d6207303ab02d5d11ef0cad2274", size = 1682474, upload-time = "2026-03-31T21:56:35.513Z" }, - { url = "https://files.pythonhosted.org/packages/01/44/056fd37b1bb52eac760303e5196acc74d9d546631b035704ae5927f7b4ac/aiohttp-3.13.5-cp310-cp310-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:b6f6cd1560c5fa427e3b6074bb24d2c64e225afbb7165008903bd42e4e33e28a", size = 1655259, upload-time = "2026-03-31T21:56:37.843Z" }, - { url = "https://files.pythonhosted.org/packages/91/9f/78eb1a20c1c28ae02f6a3c0f4d7b0dcc66abce5290cadd53d78ce3084175/aiohttp-3.13.5-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:636bc362f0c5bbc7372bc3ae49737f9e3030dbce469f0f422c8f38079780363d", size = 1736204, upload-time = "2026-03-31T21:56:39.822Z" }, - { url = "https://files.pythonhosted.org/packages/de/6c/d20d7de23f0b52b8c1d9e2033b2db1ac4dacbb470bb74c56de0f5f86bb4f/aiohttp-3.13.5-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:6a7cbeb06d1070f1d14895eeeed4dac5913b22d7b456f2eb969f11f4b3993796", size = 1826198, upload-time = "2026-03-31T21:56:41.378Z" }, - { url = "https://files.pythonhosted.org/packages/2f/86/a6f3ff1fd795f49545a7c74b2c92f62729135d73e7e4055bf74da5a26c82/aiohttp-3.13.5-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:bca9ef7517fd7874a1a08970ae88f497bf5c984610caa0bf40bd7e8450852b95", size = 1681329, upload-time = "2026-03-31T21:56:43.374Z" }, - { url = "https://files.pythonhosted.org/packages/fb/68/84cd3dab6b7b4f3e6fe9459a961acb142aaab846417f6e8905110d7027e5/aiohttp-3.13.5-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:019a67772e034a0e6b9b17c13d0a8fe56ad9fb150fc724b7f3ffd3724288d9e5", size = 1560023, upload-time = "2026-03-31T21:56:45.031Z" }, - { url = "https://files.pythonhosted.org/packages/41/2c/db61b64b0249e30f954a65ab4cb4970ced57544b1de2e3c98ee5dc24165f/aiohttp-3.13.5-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:f34ecee82858e41dd217734f0c41a532bd066bcaab636ad830f03a30b2a96f2a", size = 1652372, upload-time = "2026-03-31T21:56:47.075Z" }, - { url = "https://files.pythonhosted.org/packages/25/6f/e96988a6c982d047810c772e28c43c64c300c943b0ed5c1c0c4ce1e1027c/aiohttp-3.13.5-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:4eac02d9af4813ee289cd63a361576da36dba57f5a1ab36377bc2600db0cbb73", size = 1662031, upload-time = "2026-03-31T21:56:48.835Z" }, - { url = "https://files.pythonhosted.org/packages/b7/26/a56feace81f3d347b4052403a9d03754a0ab23f7940780dada0849a38c92/aiohttp-3.13.5-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:4beac52e9fe46d6abf98b0176a88154b742e878fdf209d2248e99fcdf73cd297", size = 1708118, upload-time = "2026-03-31T21:56:50.833Z" }, - { url = "https://files.pythonhosted.org/packages/78/6e/b6173a8ff03d01d5e1a694bc06764b5dad1df2d4ed8f0ceec12bb3277936/aiohttp-3.13.5-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:c180f480207a9b2475f2b8d8bd7204e47aec952d084b2a2be58a782ffcf96074", size = 1548667, upload-time = "2026-03-31T21:56:52.81Z" }, - { url = "https://files.pythonhosted.org/packages/16/13/13296ffe2c132d888b3fe2c195c8b9c0c24c89c3fa5cc2c44464dc23b22e/aiohttp-3.13.5-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:2837fb92951564d6339cedae4a7231692aa9f73cbc4fb2e04263b96844e03b4e", size = 1724490, upload-time = "2026-03-31T21:56:54.541Z" }, - { url = "https://files.pythonhosted.org/packages/7a/b4/1f1c287f4a79782ef36e5a6e62954c85343bc30470d862d30bd5f26c9fa2/aiohttp-3.13.5-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:d9010032a0b9710f58012a1e9c222528763d860ba2ee1422c03473eab47703e7", size = 1667109, upload-time = "2026-03-31T21:56:56.21Z" }, - { url = "https://files.pythonhosted.org/packages/ef/42/8461a2aaf60a8f4ea4549a4056be36b904b0eb03d97ca9a8a2604681a500/aiohttp-3.13.5-cp310-cp310-win32.whl", hash = "sha256:7c4b6668b2b2b9027f209ddf647f2a4407784b5d88b8be4efcc72036f365baf9", size = 439478, upload-time = "2026-03-31T21:56:58.292Z" }, - { url = "https://files.pythonhosted.org/packages/e5/71/06956304cb5ee439dfe8d86e1b2e70088bd88ed1ced1f42fb29e5d855f0e/aiohttp-3.13.5-cp310-cp310-win_amd64.whl", hash = "sha256:cd3db5927bf9167d5a6157ddb2f036f6b6b0ad001ac82355d43e97a4bde76d76", size = 462047, upload-time = "2026-03-31T21:57:00.257Z" }, - { url = "https://files.pythonhosted.org/packages/d6/f5/a20c4ac64aeaef1679e25c9983573618ff765d7aa829fa2b84ae7573169e/aiohttp-3.13.5-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:7ab7229b6f9b5c1ba4910d6c41a9eb11f543eadb3f384df1b4c293f4e73d44d6", size = 757513, upload-time = "2026-03-31T21:57:02.146Z" }, - { url = "https://files.pythonhosted.org/packages/75/0a/39fa6c6b179b53fcb3e4b3d2b6d6cad0180854eda17060c7218540102bef/aiohttp-3.13.5-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:8f14c50708bb156b3a3ca7230b3d820199d56a48e3af76fa21c2d6087190fe3d", size = 506748, upload-time = "2026-03-31T21:57:04.275Z" }, - { url = "https://files.pythonhosted.org/packages/87/ec/e38ce072e724fd7add6243613f8d1810da084f54175353d25ccf9f9c7e5a/aiohttp-3.13.5-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:e7d2f8616f0ff60bd332022279011776c3ac0faa0f1b463f7bb12326fbc97a1c", size = 501673, upload-time = "2026-03-31T21:57:06.208Z" }, - { url = "https://files.pythonhosted.org/packages/ba/ba/3bc7525d7e2beaa11b309a70d48b0d3cfc3c2089ec6a7d0820d59c657053/aiohttp-3.13.5-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a2567b72e1ffc3ab25510db43f355b29eeada56c0a622e58dcdb19530eb0a3cb", size = 1763757, upload-time = "2026-03-31T21:57:07.882Z" }, - { url = "https://files.pythonhosted.org/packages/5e/ab/e87744cf18f1bd78263aba24924d4953b41086bd3a31d22452378e9028a0/aiohttp-3.13.5-cp311-cp311-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:fb0540c854ac9c0c5ad495908fdfd3e332d553ec731698c0e29b1877ba0d2ec6", size = 1720152, upload-time = "2026-03-31T21:57:09.946Z" }, - { url = "https://files.pythonhosted.org/packages/6b/f3/ed17a6f2d742af17b50bae2d152315ed1b164b07a5fd5cc1754d99e4dfa5/aiohttp-3.13.5-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:c9883051c6972f58bfc4ebb2116345ee2aa151178e99c3f2b2bbe2af712abd13", size = 1818010, upload-time = "2026-03-31T21:57:12.157Z" }, - { url = "https://files.pythonhosted.org/packages/53/06/ecbc63dc937192e2a5cb46df4d3edb21deb8225535818802f210a6ea5816/aiohttp-3.13.5-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:2294172ce08a82fb7c7273485895de1fa1186cc8294cfeb6aef4af42ad261174", size = 1907251, upload-time = "2026-03-31T21:57:14.023Z" }, - { url = "https://files.pythonhosted.org/packages/7e/a5/0521aa32c1ddf3aa1e71dcc466be0b7db2771907a13f18cddaa45967d97b/aiohttp-3.13.5-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:3a807cabd5115fb55af198b98178997a5e0e57dead43eb74a93d9c07d6d4a7dc", size = 1759969, upload-time = "2026-03-31T21:57:16.146Z" }, - { url = "https://files.pythonhosted.org/packages/f6/78/a38f8c9105199dd3b9706745865a8a59d0041b6be0ca0cc4b2ccf1bab374/aiohttp-3.13.5-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:aa6d0d932e0f39c02b80744273cd5c388a2d9bc07760a03164f229c8e02662f6", size = 1616871, upload-time = "2026-03-31T21:57:17.856Z" }, - { url = "https://files.pythonhosted.org/packages/6f/41/27392a61ead8ab38072105c71aa44ff891e71653fe53d576a7067da2b4e8/aiohttp-3.13.5-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:60869c7ac4aaabe7110f26499f3e6e5696eae98144735b12a9c3d9eae2b51a49", size = 1739844, upload-time = "2026-03-31T21:57:19.679Z" }, - { url = "https://files.pythonhosted.org/packages/6e/55/5564e7ae26d94f3214250009a0b1c65a0c6af4bf88924ccb6fdab901de28/aiohttp-3.13.5-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:26d2f8546f1dfa75efa50c3488215a903c0168d253b75fba4210f57ab77a0fb8", size = 1731969, upload-time = "2026-03-31T21:57:22.006Z" }, - { url = "https://files.pythonhosted.org/packages/6d/c5/705a3929149865fc941bcbdd1047b238e4a72bcb215a9b16b9d7a2e8d992/aiohttp-3.13.5-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:f1162a1492032c82f14271e831c8f4b49f2b6078f4f5fc74de2c912fa225d51d", size = 1795193, upload-time = "2026-03-31T21:57:24.256Z" }, - { url = "https://files.pythonhosted.org/packages/a6/19/edabed62f718d02cff7231ca0db4ef1c72504235bc467f7b67adb1679f48/aiohttp-3.13.5-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:8b14eb3262fad0dc2f89c1a43b13727e709504972186ff6a99a3ecaa77102b6c", size = 1606477, upload-time = "2026-03-31T21:57:26.364Z" }, - { url = "https://files.pythonhosted.org/packages/de/fc/76f80ef008675637d88d0b21584596dc27410a990b0918cb1e5776545b5b/aiohttp-3.13.5-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:ca9ac61ac6db4eb6c2a0cd1d0f7e1357647b638ccc92f7e9d8d133e71ed3c6ac", size = 1813198, upload-time = "2026-03-31T21:57:28.316Z" }, - { url = "https://files.pythonhosted.org/packages/e5/67/5b3ac26b80adb20ea541c487f73730dc8fa107d632c998f25bbbab98fcda/aiohttp-3.13.5-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:7996023b2ed59489ae4762256c8516df9820f751cf2c5da8ed2fb20ee50abab3", size = 1752321, upload-time = "2026-03-31T21:57:30.549Z" }, - { url = "https://files.pythonhosted.org/packages/88/06/e4a2e49255ea23fa4feeb5ab092d90240d927c15e47b5b5c48dff5a9ce29/aiohttp-3.13.5-cp311-cp311-win32.whl", hash = "sha256:77dfa48c9f8013271011e51c00f8ada19851f013cde2c48fca1ba5e0caf5bb06", size = 439069, upload-time = "2026-03-31T21:57:32.388Z" }, - { url = "https://files.pythonhosted.org/packages/c0/43/8c7163a596dab4f8be12c190cf467a1e07e4734cf90eebb39f7f5d53fc6a/aiohttp-3.13.5-cp311-cp311-win_amd64.whl", hash = "sha256:d3a4834f221061624b8887090637db9ad4f61752001eae37d56c52fddade2dc8", size = 462859, upload-time = "2026-03-31T21:57:34.455Z" }, - { url = "https://files.pythonhosted.org/packages/be/6f/353954c29e7dcce7cf00280a02c75f30e133c00793c7a2ed3776d7b2f426/aiohttp-3.13.5-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:023ecba036ddd840b0b19bf195bfae970083fd7024ce1ac22e9bba90464620e9", size = 748876, upload-time = "2026-03-31T21:57:36.319Z" }, - { url = "https://files.pythonhosted.org/packages/f5/1b/428a7c64687b3b2e9cd293186695affc0e1e54a445d0361743b231f11066/aiohttp-3.13.5-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:15c933ad7920b7d9a20de151efcd05a6e38302cbf0e10c9b2acb9a42210a2416", size = 499557, upload-time = "2026-03-31T21:57:38.236Z" }, - { url = "https://files.pythonhosted.org/packages/29/47/7be41556bfbb6917069d6a6634bb7dd5e163ba445b783a90d40f5ac7e3a7/aiohttp-3.13.5-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ab2899f9fa2f9f741896ebb6fa07c4c883bfa5c7f2ddd8cf2aafa86fa981b2d2", size = 500258, upload-time = "2026-03-31T21:57:39.923Z" }, - { url = "https://files.pythonhosted.org/packages/67/84/c9ecc5828cb0b3695856c07c0a6817a99d51e2473400f705275a2b3d9239/aiohttp-3.13.5-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a60eaa2d440cd4707696b52e40ed3e2b0f73f65be07fd0ef23b6b539c9c0b0b4", size = 1749199, upload-time = "2026-03-31T21:57:41.938Z" }, - { url = "https://files.pythonhosted.org/packages/f0/d3/3c6d610e66b495657622edb6ae7c7fd31b2e9086b4ec50b47897ad6042a9/aiohttp-3.13.5-cp312-cp312-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:55b3bdd3292283295774ab585160c4004f4f2f203946997f49aac032c84649e9", size = 1721013, upload-time = "2026-03-31T21:57:43.904Z" }, - { url = "https://files.pythonhosted.org/packages/49/a0/24409c12217456df0bae7babe3b014e460b0b38a8e60753d6cb339f6556d/aiohttp-3.13.5-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:c2b2355dc094e5f7d45a7bb262fe7207aa0460b37a0d87027dcf21b5d890e7d5", size = 1781501, upload-time = "2026-03-31T21:57:46.285Z" }, - { url = "https://files.pythonhosted.org/packages/98/9d/b65ec649adc5bccc008b0957a9a9c691070aeac4e41cea18559fef49958b/aiohttp-3.13.5-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:b38765950832f7d728297689ad78f5f2cf79ff82487131c4d26fe6ceecdc5f8e", size = 1878981, upload-time = "2026-03-31T21:57:48.734Z" }, - { url = "https://files.pythonhosted.org/packages/57/d8/8d44036d7eb7b6a8ec4c5494ea0c8c8b94fbc0ed3991c1a7adf230df03bf/aiohttp-3.13.5-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b18f31b80d5a33661e08c89e202edabf1986e9b49c42b4504371daeaa11b47c1", size = 1767934, upload-time = "2026-03-31T21:57:51.171Z" }, - { url = "https://files.pythonhosted.org/packages/31/04/d3f8211f273356f158e3464e9e45484d3fb8c4ce5eb2f6fe9405c3273983/aiohttp-3.13.5-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:33add2463dde55c4f2d9635c6ab33ce154e5ecf322bd26d09af95c5f81cfa286", size = 1566671, upload-time = "2026-03-31T21:57:53.326Z" }, - { url = "https://files.pythonhosted.org/packages/41/db/073e4ebe00b78e2dfcacff734291651729a62953b48933d765dc513bf798/aiohttp-3.13.5-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:327cc432fdf1356fb4fbc6fe833ad4e9f6aacb71a8acaa5f1855e4b25910e4a9", size = 1705219, upload-time = "2026-03-31T21:57:55.385Z" }, - { url = "https://files.pythonhosted.org/packages/48/45/7dfba71a2f9fd97b15c95c06819de7eb38113d2cdb6319669195a7d64270/aiohttp-3.13.5-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:7c35b0bf0b48a70b4cb4fc5d7bed9b932532728e124874355de1a0af8ec4bc88", size = 1743049, upload-time = "2026-03-31T21:57:57.341Z" }, - { url = "https://files.pythonhosted.org/packages/18/71/901db0061e0f717d226386a7f471bb59b19566f2cae5f0d93874b017271f/aiohttp-3.13.5-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:df23d57718f24badef8656c49743e11a89fd6f5358fa8a7b96e728fda2abf7d3", size = 1749557, upload-time = "2026-03-31T21:57:59.626Z" }, - { url = "https://files.pythonhosted.org/packages/08/d5/41eebd16066e59cd43728fe74bce953d7402f2b4ddfdfef2c0e9f17ca274/aiohttp-3.13.5-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:02e048037a6501a5ec1f6fc9736135aec6eb8a004ce48838cb951c515f32c80b", size = 1558931, upload-time = "2026-03-31T21:58:01.972Z" }, - { url = "https://files.pythonhosted.org/packages/30/e6/4a799798bf05740e66c3a1161079bda7a3dd8e22ca392481d7a7f9af82a6/aiohttp-3.13.5-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:31cebae8b26f8a615d2b546fee45d5ffb76852ae6450e2a03f42c9102260d6fe", size = 1774125, upload-time = "2026-03-31T21:58:04.007Z" }, - { url = "https://files.pythonhosted.org/packages/84/63/7749337c90f92bc2cb18f9560d67aa6258c7060d1397d21529b8004fcf6f/aiohttp-3.13.5-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:888e78eb5ca55a615d285c3c09a7a91b42e9dd6fc699b166ebd5dee87c9ccf14", size = 1732427, upload-time = "2026-03-31T21:58:06.337Z" }, - { url = "https://files.pythonhosted.org/packages/98/de/cf2f44ff98d307e72fb97d5f5bbae3bfcb442f0ea9790c0bf5c5c2331404/aiohttp-3.13.5-cp312-cp312-win32.whl", hash = "sha256:8bd3ec6376e68a41f9f95f5ed170e2fcf22d4eb27a1f8cb361d0508f6e0557f3", size = 433534, upload-time = "2026-03-31T21:58:08.712Z" }, - { url = "https://files.pythonhosted.org/packages/aa/ca/eadf6f9c8fa5e31d40993e3db153fb5ed0b11008ad5d9de98a95045bed84/aiohttp-3.13.5-cp312-cp312-win_amd64.whl", hash = "sha256:110e448e02c729bcebb18c60b9214a87ba33bac4a9fa5e9a5f139938b56c6cb1", size = 460446, upload-time = "2026-03-31T21:58:10.945Z" }, - { url = "https://files.pythonhosted.org/packages/78/e9/d76bf503005709e390122d34e15256b88f7008e246c4bdbe915cd4f1adce/aiohttp-3.13.5-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:a5029cc80718bbd545123cd8fe5d15025eccaaaace5d0eeec6bd556ad6163d61", size = 742930, upload-time = "2026-03-31T21:58:13.155Z" }, - { url = "https://files.pythonhosted.org/packages/57/00/4b7b70223deaebd9bb85984d01a764b0d7bd6526fcdc73cca83bcbe7243e/aiohttp-3.13.5-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:4bb6bf5811620003614076bdc807ef3b5e38244f9d25ca5fe888eaccea2a9832", size = 496927, upload-time = "2026-03-31T21:58:15.073Z" }, - { url = "https://files.pythonhosted.org/packages/9c/f5/0fb20fb49f8efdcdce6cd8127604ad2c503e754a8f139f5e02b01626523f/aiohttp-3.13.5-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:a84792f8631bf5a94e52d9cc881c0b824ab42717165a5579c760b830d9392ac9", size = 497141, upload-time = "2026-03-31T21:58:17.009Z" }, - { url = "https://files.pythonhosted.org/packages/3b/86/b7c870053e36a94e8951b803cb5b909bfbc9b90ca941527f5fcafbf6b0fa/aiohttp-3.13.5-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:57653eac22c6a4c13eb22ecf4d673d64a12f266e72785ab1c8b8e5940d0e8090", size = 1732476, upload-time = "2026-03-31T21:58:18.925Z" }, - { url = "https://files.pythonhosted.org/packages/b5/e5/4e161f84f98d80c03a238671b4136e6530453d65262867d989bbe78244d0/aiohttp-3.13.5-cp313-cp313-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:e5e5f7debc7a57af53fdf5c5009f9391d9f4c12867049d509bf7bb164a6e295b", size = 1706507, upload-time = "2026-03-31T21:58:21.094Z" }, - { url = "https://files.pythonhosted.org/packages/d4/56/ea11a9f01518bd5a2a2fcee869d248c4b8a0cfa0bb13401574fa31adf4d4/aiohttp-3.13.5-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:c719f65bebcdf6716f10e9eff80d27567f7892d8988c06de12bbbd39307c6e3a", size = 1773465, upload-time = "2026-03-31T21:58:23.159Z" }, - { url = "https://files.pythonhosted.org/packages/eb/40/333ca27fb74b0383f17c90570c748f7582501507307350a79d9f9f3c6eb1/aiohttp-3.13.5-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:d97f93fdae594d886c5a866636397e2bcab146fd7a132fd6bb9ce182224452f8", size = 1873523, upload-time = "2026-03-31T21:58:25.59Z" }, - { url = "https://files.pythonhosted.org/packages/f0/d2/e2f77eef1acb7111405433c707dc735e63f67a56e176e72e9e7a2cd3f493/aiohttp-3.13.5-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:3df334e39d4c2f899a914f1dba283c1aadc311790733f705182998c6f7cae665", size = 1754113, upload-time = "2026-03-31T21:58:27.624Z" }, - { url = "https://files.pythonhosted.org/packages/fb/56/3f653d7f53c89669301ec9e42c95233e2a0c0a6dd051269e6e678db4fdb0/aiohttp-3.13.5-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:fe6970addfea9e5e081401bcbadf865d2b6da045472f58af08427e108d618540", size = 1562351, upload-time = "2026-03-31T21:58:29.918Z" }, - { url = "https://files.pythonhosted.org/packages/ec/a6/9b3e91eb8ae791cce4ee736da02211c85c6f835f1bdfac0594a8a3b7018c/aiohttp-3.13.5-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:7becdf835feff2f4f335d7477f121af787e3504b48b449ff737afb35869ba7bb", size = 1693205, upload-time = "2026-03-31T21:58:32.214Z" }, - { url = "https://files.pythonhosted.org/packages/98/fc/bfb437a99a2fcebd6b6eaec609571954de2ed424f01c352f4b5504371dd3/aiohttp-3.13.5-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:676e5651705ad5d8a70aeb8eb6936c436d8ebbd56e63436cb7dd9bb36d2a9a46", size = 1730618, upload-time = "2026-03-31T21:58:34.728Z" }, - { url = "https://files.pythonhosted.org/packages/e4/b6/c8534862126191a034f68153194c389addc285a0f1347d85096d349bbc15/aiohttp-3.13.5-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:9b16c653d38eb1a611cc898c41e76859ca27f119d25b53c12875fd0474ae31a8", size = 1745185, upload-time = "2026-03-31T21:58:36.909Z" }, - { url = "https://files.pythonhosted.org/packages/0b/93/4ca8ee2ef5236e2707e0fd5fecb10ce214aee1ff4ab307af9c558bda3b37/aiohttp-3.13.5-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:999802d5fa0389f58decd24b537c54aa63c01c3219ce17d1214cbda3c2b22d2d", size = 1557311, upload-time = "2026-03-31T21:58:39.38Z" }, - { url = "https://files.pythonhosted.org/packages/57/ae/76177b15f18c5f5d094f19901d284025db28eccc5ae374d1d254181d33f4/aiohttp-3.13.5-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:ec707059ee75732b1ba130ed5f9580fe10ff75180c812bc267ded039db5128c6", size = 1773147, upload-time = "2026-03-31T21:58:41.476Z" }, - { url = "https://files.pythonhosted.org/packages/01/a4/62f05a0a98d88af59d93b7fcac564e5f18f513cb7471696ac286db970d6a/aiohttp-3.13.5-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:2d6d44a5b48132053c2f6cd5c8cb14bc67e99a63594e336b0f2af81e94d5530c", size = 1730356, upload-time = "2026-03-31T21:58:44.049Z" }, - { url = "https://files.pythonhosted.org/packages/e4/85/fc8601f59dfa8c9523808281f2da571f8b4699685f9809a228adcc90838d/aiohttp-3.13.5-cp313-cp313-win32.whl", hash = "sha256:329f292ed14d38a6c4c435e465f48bebb47479fd676a0411936cc371643225cc", size = 432637, upload-time = "2026-03-31T21:58:46.167Z" }, - { url = "https://files.pythonhosted.org/packages/c0/1b/ac685a8882896acf0f6b31d689e3792199cfe7aba37969fa91da63a7fa27/aiohttp-3.13.5-cp313-cp313-win_amd64.whl", hash = "sha256:69f571de7500e0557801c0b51f4780482c0ec5fe2ac851af5a92cfce1af1cb83", size = 458896, upload-time = "2026-03-31T21:58:48.119Z" }, - { url = "https://files.pythonhosted.org/packages/5d/ce/46572759afc859e867a5bc8ec3487315869013f59281ce61764f76d879de/aiohttp-3.13.5-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:eb4639f32fd4a9904ab8fb45bf3383ba71137f3d9d4ba25b3b3f3109977c5b8c", size = 745721, upload-time = "2026-03-31T21:58:50.229Z" }, - { url = "https://files.pythonhosted.org/packages/13/fe/8a2efd7626dbe6049b2ef8ace18ffda8a4dfcbe1bcff3ac30c0c7575c20b/aiohttp-3.13.5-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:7e5dc4311bd5ac493886c63cbf76ab579dbe4641268e7c74e48e774c74b6f2be", size = 497663, upload-time = "2026-03-31T21:58:52.232Z" }, - { url = "https://files.pythonhosted.org/packages/9b/91/cc8cc78a111826c54743d88651e1687008133c37e5ee615fee9b57990fac/aiohttp-3.13.5-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:756c3c304d394977519824449600adaf2be0ccee76d206ee339c5e76b70ded25", size = 499094, upload-time = "2026-03-31T21:58:54.566Z" }, - { url = "https://files.pythonhosted.org/packages/0a/33/a8362cb15cf16a3af7e86ed11962d5cd7d59b449202dc576cdc731310bde/aiohttp-3.13.5-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ecc26751323224cf8186efcf7fbcbc30f4e1d8c7970659daf25ad995e4032a56", size = 1726701, upload-time = "2026-03-31T21:58:56.864Z" }, - { url = "https://files.pythonhosted.org/packages/45/0c/c091ac5c3a17114bd76cbf85d674650969ddf93387876cf67f754204bd77/aiohttp-3.13.5-cp314-cp314-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:10a75acfcf794edf9d8db50e5a7ec5fc818b2a8d3f591ce93bc7b1210df016d2", size = 1683360, upload-time = "2026-03-31T21:58:59.072Z" }, - { url = "https://files.pythonhosted.org/packages/23/73/bcee1c2b79bc275e964d1446c55c54441a461938e70267c86afaae6fba27/aiohttp-3.13.5-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:0f7a18f258d124cd678c5fe072fe4432a4d5232b0657fca7c1847f599233c83a", size = 1773023, upload-time = "2026-03-31T21:59:01.776Z" }, - { url = "https://files.pythonhosted.org/packages/c7/ef/720e639df03004fee2d869f771799d8c23046dec47d5b81e396c7cda583a/aiohttp-3.13.5-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:df6104c009713d3a89621096f3e3e88cc323fd269dbd7c20afe18535094320be", size = 1853795, upload-time = "2026-03-31T21:59:04.568Z" }, - { url = "https://files.pythonhosted.org/packages/bd/c9/989f4034fb46841208de7aeeac2c6d8300745ab4f28c42f629ba77c2d916/aiohttp-3.13.5-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:241a94f7de7c0c3b616627aaad530fe2cb620084a8b144d3be7b6ecfe95bae3b", size = 1730405, upload-time = "2026-03-31T21:59:07.221Z" }, - { url = "https://files.pythonhosted.org/packages/ce/75/ee1fd286ca7dc599d824b5651dad7b3be7ff8d9a7e7b3fe9820d9180f7db/aiohttp-3.13.5-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:c974fb66180e58709b6fc402846f13791240d180b74de81d23913abe48e96d94", size = 1558082, upload-time = "2026-03-31T21:59:09.484Z" }, - { url = "https://files.pythonhosted.org/packages/c3/20/1e9e6650dfc436340116b7aa89ff8cb2bbdf0abc11dfaceaad8f74273a10/aiohttp-3.13.5-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:6e27ea05d184afac78aabbac667450c75e54e35f62238d44463131bd3f96753d", size = 1692346, upload-time = "2026-03-31T21:59:12.068Z" }, - { url = "https://files.pythonhosted.org/packages/d8/40/8ebc6658d48ea630ac7903912fe0dd4e262f0e16825aa4c833c56c9f1f56/aiohttp-3.13.5-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:a79a6d399cef33a11b6f004c67bb07741d91f2be01b8d712d52c75711b1e07c7", size = 1698891, upload-time = "2026-03-31T21:59:14.552Z" }, - { url = "https://files.pythonhosted.org/packages/d8/78/ea0ae5ec8ba7a5c10bdd6e318f1ba5e76fcde17db8275188772afc7917a4/aiohttp-3.13.5-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:c632ce9c0b534fbe25b52c974515ed674937c5b99f549a92127c85f771a78772", size = 1742113, upload-time = "2026-03-31T21:59:17.068Z" }, - { url = "https://files.pythonhosted.org/packages/8a/66/9d308ed71e3f2491be1acb8769d96c6f0c47d92099f3bc9119cada27b357/aiohttp-3.13.5-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:fceedde51fbd67ee2bcc8c0b33d0126cc8b51ef3bbde2f86662bd6d5a6f10ec5", size = 1553088, upload-time = "2026-03-31T21:59:19.541Z" }, - { url = "https://files.pythonhosted.org/packages/da/a6/6cc25ed8dfc6e00c90f5c6d126a98e2cf28957ad06fa1036bd34b6f24a2c/aiohttp-3.13.5-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:f92995dfec9420bb69ae629abf422e516923ba79ba4403bc750d94fb4a6c68c1", size = 1757976, upload-time = "2026-03-31T21:59:22.311Z" }, - { url = "https://files.pythonhosted.org/packages/c1/2b/cce5b0ffe0de99c83e5e36d8f828e4161e415660a9f3e58339d07cce3006/aiohttp-3.13.5-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:20ae0ff08b1f2c8788d6fb85afcb798654ae6ba0b747575f8562de738078457b", size = 1712444, upload-time = "2026-03-31T21:59:24.635Z" }, - { url = "https://files.pythonhosted.org/packages/6c/cf/9e1795b4160c58d29421eafd1a69c6ce351e2f7c8d3c6b7e4ca44aea1a5b/aiohttp-3.13.5-cp314-cp314-win32.whl", hash = "sha256:b20df693de16f42b2472a9c485e1c948ee55524786a0a34345511afdd22246f3", size = 438128, upload-time = "2026-03-31T21:59:27.291Z" }, - { url = "https://files.pythonhosted.org/packages/22/4d/eaedff67fc805aeba4ba746aec891b4b24cebb1a7d078084b6300f79d063/aiohttp-3.13.5-cp314-cp314-win_amd64.whl", hash = "sha256:f85c6f327bf0b8c29da7d93b1cabb6363fb5e4e160a32fa241ed2dce21b73162", size = 464029, upload-time = "2026-03-31T21:59:29.429Z" }, - { url = "https://files.pythonhosted.org/packages/79/11/c27d9332ee20d68dd164dc12a6ecdef2e2e35ecc97ed6cf0d2442844624b/aiohttp-3.13.5-cp314-cp314t-macosx_10_13_universal2.whl", hash = "sha256:1efb06900858bb618ff5cee184ae2de5828896c448403d51fb633f09e109be0a", size = 778758, upload-time = "2026-03-31T21:59:31.547Z" }, - { url = "https://files.pythonhosted.org/packages/04/fb/377aead2e0a3ba5f09b7624f702a964bdf4f08b5b6728a9799830c80041e/aiohttp-3.13.5-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:fee86b7c4bd29bdaf0d53d14739b08a106fdda809ca5fe032a15f52fae5fe254", size = 512883, upload-time = "2026-03-31T21:59:34.098Z" }, - { url = "https://files.pythonhosted.org/packages/bb/a6/aa109a33671f7a5d3bd78b46da9d852797c5e665bfda7d6b373f56bff2ec/aiohttp-3.13.5-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:20058e23909b9e65f9da62b396b77dfa95965cbe840f8def6e572538b1d32e36", size = 516668, upload-time = "2026-03-31T21:59:36.497Z" }, - { url = "https://files.pythonhosted.org/packages/79/b3/ca078f9f2fa9563c36fb8ef89053ea2bb146d6f792c5104574d49d8acb63/aiohttp-3.13.5-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8cf20a8d6868cb15a73cab329ffc07291ba8c22b1b88176026106ae39aa6df0f", size = 1883461, upload-time = "2026-03-31T21:59:38.723Z" }, - { url = "https://files.pythonhosted.org/packages/b7/e3/a7ad633ca1ca497b852233a3cce6906a56c3225fb6d9217b5e5e60b7419d/aiohttp-3.13.5-cp314-cp314t-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:330f5da04c987f1d5bdb8ae189137c77139f36bd1cb23779ca1a354a4b027800", size = 1747661, upload-time = "2026-03-31T21:59:41.187Z" }, - { url = "https://files.pythonhosted.org/packages/33/b9/cd6fe579bed34a906d3d783fe60f2fa297ef55b27bb4538438ee49d4dc41/aiohttp-3.13.5-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:6f1cbf0c7926d315c3c26c2da41fd2b5d2fe01ac0e157b78caefc51a782196cf", size = 1863800, upload-time = "2026-03-31T21:59:43.84Z" }, - { url = "https://files.pythonhosted.org/packages/c0/3f/2c1e2f5144cefa889c8afd5cf431994c32f3b29da9961698ff4e3811b79a/aiohttp-3.13.5-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:53fc049ed6390d05423ba33103ded7281fe897cf97878f369a527070bd95795b", size = 1958382, upload-time = "2026-03-31T21:59:46.187Z" }, - { url = "https://files.pythonhosted.org/packages/66/1d/f31ec3f1013723b3babe3609e7f119c2c2fb6ef33da90061a705ef3e1bc8/aiohttp-3.13.5-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:898703aa2667e3c5ca4c54ca36cd73f58b7a38ef87a5606414799ebce4d3fd3a", size = 1803724, upload-time = "2026-03-31T21:59:48.656Z" }, - { url = "https://files.pythonhosted.org/packages/0e/b4/57712dfc6f1542f067daa81eb61da282fab3e6f1966fca25db06c4fc62d5/aiohttp-3.13.5-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:0494a01ca9584eea1e5fbd6d748e61ecff218c51b576ee1999c23db7066417d8", size = 1640027, upload-time = "2026-03-31T21:59:51.284Z" }, - { url = "https://files.pythonhosted.org/packages/25/3c/734c878fb43ec083d8e31bf029daae1beafeae582d1b35da234739e82ee7/aiohttp-3.13.5-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:6cf81fe010b8c17b09495cbd15c1d35afbc8fb405c0c9cf4738e5ae3af1d65be", size = 1806644, upload-time = "2026-03-31T21:59:53.753Z" }, - { url = "https://files.pythonhosted.org/packages/20/a5/f671e5cbec1c21d044ff3078223f949748f3a7f86b14e34a365d74a5d21f/aiohttp-3.13.5-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:c564dd5f09ddc9d8f2c2d0a301cd30a79a2cc1b46dd1a73bef8f0038863d016b", size = 1791630, upload-time = "2026-03-31T21:59:56.239Z" }, - { url = "https://files.pythonhosted.org/packages/0b/63/fb8d0ad63a0b8a99be97deac8c04dacf0785721c158bdf23d679a87aa99e/aiohttp-3.13.5-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:2994be9f6e51046c4f864598fd9abeb4fba6e88f0b2152422c9666dcd4aea9c6", size = 1809403, upload-time = "2026-03-31T21:59:59.103Z" }, - { url = "https://files.pythonhosted.org/packages/59/0c/bfed7f30662fcf12206481c2aac57dedee43fe1c49275e85b3a1e1742294/aiohttp-3.13.5-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:157826e2fa245d2ef46c83ea8a5faf77ca19355d278d425c29fda0beb3318037", size = 1634924, upload-time = "2026-03-31T22:00:02.116Z" }, - { url = "https://files.pythonhosted.org/packages/17/d6/fd518d668a09fd5a3319ae5e984d4d80b9a4b3df4e21c52f02251ef5a32e/aiohttp-3.13.5-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:a8aca50daa9493e9e13c0f566201a9006f080e7c50e5e90d0b06f53146a54500", size = 1836119, upload-time = "2026-03-31T22:00:04.756Z" }, - { url = "https://files.pythonhosted.org/packages/78/b7/15fb7a9d52e112a25b621c67b69c167805cb1f2ab8f1708a5c490d1b52fe/aiohttp-3.13.5-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:3b13560160d07e047a93f23aaa30718606493036253d5430887514715b67c9d9", size = 1772072, upload-time = "2026-03-31T22:00:07.494Z" }, - { url = "https://files.pythonhosted.org/packages/7e/df/57ba7f0c4a553fc2bd8b6321df236870ec6fd64a2a473a8a13d4f733214e/aiohttp-3.13.5-cp314-cp314t-win32.whl", hash = "sha256:9a0f4474b6ea6818b41f82172d799e4b3d29e22c2c520ce4357856fced9af2f8", size = 471819, upload-time = "2026-03-31T22:00:10.277Z" }, - { url = "https://files.pythonhosted.org/packages/62/29/2f8418269e46454a26171bfdd6a055d74febf32234e474930f2f60a17145/aiohttp-3.13.5-cp314-cp314t-win_amd64.whl", hash = "sha256:18a2f6c1182c51baa1d28d68fea51513cb2a76612f038853c0ad3c145423d3d9", size = 505441, upload-time = "2026-03-31T22:00:12.791Z" }, +sdist = { url = "https://files.pythonhosted.org/packages/82/78/8ea7308cac6934de8c74a14f3d5f65d1c89287426688be79538d0e5c013d/aiohttp-3.14.1.tar.gz", hash = "sha256:307f2cff90a764d329e77040603fa032db89c5c24fdad50c4c15334cba744035", size = 7955794, upload-time = "2026-06-07T21:09:35.529Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/6d/67/58ded4b3f2e10f94972d8928050c85330e249a31dd45a0e5f3c0e9c3fa05/aiohttp-3.14.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:8f6bb621e5863cfe8fe5ff5468002d200ec31f30f1280b259dc505b02595099e", size = 766140, upload-time = "2026-06-07T21:05:37.471Z" }, + { url = "https://files.pythonhosted.org/packages/18/68/4ae5b4e08943f316594bb68da89957d3baf5760588fa09509594bd777e4b/aiohttp-3.14.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:4f7215cb3933784f79ed20e5f050e15984f390424339b22375d5a53c933a0491", size = 519430, upload-time = "2026-06-07T21:05:40.751Z" }, + { url = "https://files.pythonhosted.org/packages/cb/c1/316c8f3549dbe5245f92bfd523ec6f32dd4d98cafe21df3f6a19b1184c75/aiohttp-3.14.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:d9d4e294455b23a68c9b8f042d0e8e377a265bcb15332753695f6e5b6819e0ce", size = 514406, upload-time = "2026-06-07T21:05:42.111Z" }, + { url = "https://files.pythonhosted.org/packages/5a/ee/fb0ac28684e8d753b83c8a4eebc19a5846912aa0a4daaabb6a9936363840/aiohttp-3.14.1-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b238af795833d5731d049d82bc84b768ae6f8f97f0495963b3ed9935c5901cc3", size = 1703649, upload-time = "2026-06-07T21:05:43.427Z" }, + { url = "https://files.pythonhosted.org/packages/3b/57/aa2beab673331f111885db8a7b69dfe3ab0e53e446a0ace18ca694b4dc58/aiohttp-3.14.1-cp310-cp310-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:e4e5e0ae56914ecdbf446493addefc0159053dd53962cef37d7839f37f73d505", size = 1675126, upload-time = "2026-06-07T21:05:44.897Z" }, + { url = "https://files.pythonhosted.org/packages/47/ea/dad128abe365e79be03b16ed464198ac73e0d257e8260c6f7d6f31cbef26/aiohttp-3.14.1-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:092e4ce3619a7c6dee52a6bdabda973d9b34b66781f840ce93c7e0cec30cf521", size = 1771558, upload-time = "2026-06-07T21:05:46.405Z" }, + { url = "https://files.pythonhosted.org/packages/63/f3/b5b4e10327cb85d34d24232c6b71b64602f190b3ccb238a043ac6b187dac/aiohttp-3.14.1-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:bb33777ea21e8b7ecde0e6fc84f598be0a1192eab1a63bc746d75aa75d38e7bd", size = 1856631, upload-time = "2026-06-07T21:05:47.844Z" }, + { url = "https://files.pythonhosted.org/packages/2b/9d/93294c3045775c708ac8310eb3d3622a11d2951345ad590d532d62a1faa4/aiohttp-3.14.1-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:23119f8fd4f5d16902ed459b63b100bcd269628075162bddac56cc7b5273b3fb", size = 1714139, upload-time = "2026-06-07T21:05:49.982Z" }, + { url = "https://files.pythonhosted.org/packages/29/c4/93067c85a0373492ce8e577435203c5947c454af074ac48ed4f3a1b9dd4a/aiohttp-3.14.1-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:57fc6745a4b7d0f5a9eb4f40a69718be6c0bc1b8368cc9fe89e90118719f4f42", size = 1588321, upload-time = "2026-06-07T21:05:51.431Z" }, + { url = "https://files.pythonhosted.org/packages/c4/39/9ff91aaf02af8b7b8222a987466da539f154c3e01732c22b5f5a20a8ee66/aiohttp-3.14.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:6fd35beba67c4183b09375c5fff9accb47524191a244a99f95fd4472f5402c2b", size = 1670375, upload-time = "2026-06-07T21:05:53.109Z" }, + { url = "https://files.pythonhosted.org/packages/aa/e4/77452a3676b8d99ac1375f77691d6bf65ea6e9f4b201b82ef77c916dc767/aiohttp-3.14.1-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:672b9d65f42eb877f5c3f234a4547e4e1a226ca8c2eed879bb34670a0ce51192", size = 1690933, upload-time = "2026-06-07T21:05:54.902Z" }, + { url = "https://files.pythonhosted.org/packages/7d/84/b0059a7c7fc05ea23f3bc1596ba91c12f79588b9450564a24cac37536d0a/aiohttp-3.14.1-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:24ba13339fed9251d9b1a1bec8c7ab84c0d1675d79d33501e11f94f8b9a84e05", size = 1740798, upload-time = "2026-06-07T21:05:56.458Z" }, + { url = "https://files.pythonhosted.org/packages/8f/3a/e2a513ecbfc362591caa51a7f7e011b3bfc8938b388ae44cd95560d36999/aiohttp-3.14.1-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:94da27378da0610e341c4d30de29a191672683cc82b8f9556e8f7c7212a020fe", size = 1576412, upload-time = "2026-06-07T21:05:57.953Z" }, + { url = "https://files.pythonhosted.org/packages/a1/10/08f1654f538f93d36dcac66310a06eefce4641cdafca83f9f0a5317be254/aiohttp-3.14.1-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:52cdac9432d8b4a719f35094a818d95adcae0f0b4fe9b9b921909e0c87de9e7d", size = 1750199, upload-time = "2026-06-07T21:05:59.488Z" }, + { url = "https://files.pythonhosted.org/packages/99/e4/d91b70c57d8b8e9611e4a2e52238ca3698d3dc1c2efe25b7a9bf594ac584/aiohttp-3.14.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:672ac254412a24d0d0cf00a9e6c238877e4be5e5fa2d188832c1244f45f31966", size = 1699356, upload-time = "2026-06-07T21:06:01.131Z" }, + { url = "https://files.pythonhosted.org/packages/3d/f1/15340176f35ff61b95dbe34020bcf43f9e624a2d7bbac934715ff97d2033/aiohttp-3.14.1-cp310-cp310-win32.whl", hash = "sha256:2fe3607e71acc6ebb0ec8e492a247bf7a291226192dc0084236dfc12478916f6", size = 458939, upload-time = "2026-06-07T21:06:02.86Z" }, + { url = "https://files.pythonhosted.org/packages/c3/c2/a2f1ec5b37f903109e43ae2862268cfe4a67a60c1b2cf43169fcdff5995f/aiohttp-3.14.1-cp310-cp310-win_amd64.whl", hash = "sha256:30099eda75a53c32efb0920e9c33c195314d2cc1c680fbfd30894932ac5f27df", size = 482583, upload-time = "2026-06-07T21:06:04.666Z" }, + { url = "https://files.pythonhosted.org/packages/d0/7a/7b56f6732ef79530afaa72aa335d41b67c8d79b946995f0b11ad72985435/aiohttp-3.14.1-cp310-cp310-win_arm64.whl", hash = "sha256:5a837f49d901f9e368651b676912bff1104ed8c1a83b280bcd7b29adccef5c9c", size = 453470, upload-time = "2026-06-07T21:06:06.322Z" }, + { url = "https://files.pythonhosted.org/packages/26/dd/bf526e6f0a1120dd6f2df2e97bacfe4d358f13d17a0ff5847301a1375a51/aiohttp-3.14.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:aa00140699487bd435fde4342d85c94cb256b7cd3a5b9c3396c67f19922afda2", size = 765225, upload-time = "2026-06-07T21:06:07.957Z" }, + { url = "https://files.pythonhosted.org/packages/8f/e1/a2872aa55495a70f61310d411541c6ee23812d9a884e000c716e1bc3edbf/aiohttp-3.14.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:1c1af67559445498b502030c35c59db59966f47041ca9de5b4e707f86bd10b5f", size = 518743, upload-time = "2026-06-07T21:06:09.749Z" }, + { url = "https://files.pythonhosted.org/packages/5b/e7/c60c7b209e509cc787de3cea0550a518538cfc08003e1c1e14c1c63fff71/aiohttp-3.14.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:d44ec478e713ee7f29b439f7eb8dc2b9d4079e11ae114d2c2ac3d5daf30516c8", size = 514139, upload-time = "2026-06-07T21:06:11.26Z" }, + { url = "https://files.pythonhosted.org/packages/5b/8d/614ace2f579702c9840ab1e1447fd8509e35b0b904f7196418fa2f57b25d/aiohttp-3.14.1-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d3b1a184a9a8f548a6b73f1e26b96b052193e4b3175ed7342aaf1151a1f00a04", size = 1784088, upload-time = "2026-06-07T21:06:12.887Z" }, + { url = "https://files.pythonhosted.org/packages/49/e0/726e90f99542bf292f81a96a12cc4847deb86f3ccf62c6f4014a201f4d33/aiohttp-3.14.1-cp311-cp311-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:5f2504bc0322437c9a1ff6d3333ca56c7477b727c995f036b976ae17b98372c8", size = 1737835, upload-time = "2026-06-07T21:06:14.564Z" }, + { url = "https://files.pythonhosted.org/packages/0b/4b/d176d5c4db9d33dacf0543102ea59503bc1d528af4cfd0b719949ca49389/aiohttp-3.14.1-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:73f05ea02013e02512c3bf42714f1208c57168c779cc6fe23516e4543089d0a6", size = 1842801, upload-time = "2026-06-07T21:06:16.228Z" }, + { url = "https://files.pythonhosted.org/packages/dc/d6/5a99b563690ea0cbed912ae94a2ce33993a5709a651a3a4fe761e7dd973a/aiohttp-3.14.1-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:797457503c2d426bee06eef808d07b31ede30b65e054444e7de64cad0061b7af", size = 1929992, upload-time = "2026-06-07T21:06:17.947Z" }, + { url = "https://files.pythonhosted.org/packages/76/7f/a987b14a3859094b3cea3f4825219c3e5536242564af6e3f9c2f6c994eb2/aiohttp-3.14.1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b821a1f7dedf7e37450654e620038ac3b2e81e8fa6ea269337e97101978ec730", size = 1786989, upload-time = "2026-06-07T21:06:19.677Z" }, + { url = "https://files.pythonhosted.org/packages/f1/1a/420e5c85a3e73349372ed22ce0b6af86bfa6ce16a4b20a64a2e94608c781/aiohttp-3.14.1-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:4cd96b5ba05d67ed0cf00b5b405c8cd99586d8e3481e8ee0a831057591af7621", size = 1640129, upload-time = "2026-06-07T21:06:22.558Z" }, + { url = "https://files.pythonhosted.org/packages/a7/80/18a592ed3be0a402cc03670bd72ee1f8563ddbe1d8d5542dbf868f274136/aiohttp-3.14.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:1d459b98a932296c6f0e94f87511a0b1b90a8a02c30a50e60a297619cd5a58ee", size = 1756576, upload-time = "2026-06-07T21:06:24.8Z" }, + { url = "https://files.pythonhosted.org/packages/ec/0b/8b3d5713373858ff71a617daf6e3b0e81ad63e79d09a3cf2f6b6b983939c/aiohttp-3.14.1-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:764457a7be60825fb770a644852ff717bcbb5042f189f2bd16df61a81b3f6573", size = 1754668, upload-time = "2026-06-07T21:06:26.528Z" }, + { url = "https://files.pythonhosted.org/packages/9f/49/fd564575cf225821d7ba5a117cb8bc27213d8a7e1811162afb43ae077039/aiohttp-3.14.1-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:f7a16ef45b081454ef844502d87a848876c490c4cb5c650c230f6ec79ed2c1e7", size = 1817019, upload-time = "2026-06-07T21:06:28.297Z" }, + { url = "https://files.pythonhosted.org/packages/ed/1b/e850c9ae6fc91356552ae668bb6c51e93fa29c8aef13398a10b56678557f/aiohttp-3.14.1-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:2fbc3ed048b3475b9f0cbcb9978e9d2d3511acd91ead203af26ed9f0056004cf", size = 1631638, upload-time = "2026-06-07T21:06:30.242Z" }, + { url = "https://files.pythonhosted.org/packages/eb/94/3c337ba72451a89806ace6f75bddc92bafc5b8d53d90115a512858024b63/aiohttp-3.14.1-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:bedb0cd073cc2dc035e30aeb99444389d3cd2113afe4ef9fcd23d439f5bade85", size = 1835660, upload-time = "2026-06-07T21:06:31.943Z" }, + { url = "https://files.pythonhosted.org/packages/2b/9c/9c18cf367a0498212d9ba7daf990b504a5e8ae064cda4b504e2647c89c03/aiohttp-3.14.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:b6feea921016eb3d4e04d65fc4e9ca402d1a3801f562aef94989f54694917af3", size = 1775698, upload-time = "2026-06-07T21:06:33.72Z" }, + { url = "https://files.pythonhosted.org/packages/b5/63/a251a9d2a6cb45065b2ddc0bde2b3dd10108740a9a42f632c66405a761a2/aiohttp-3.14.1-cp311-cp311-win32.whl", hash = "sha256:313701e488100074ce99850404ee36e741abf6330179fec908a1944ecf570126", size = 458386, upload-time = "2026-06-07T21:06:35.279Z" }, + { url = "https://files.pythonhosted.org/packages/17/ca/69274c51dcd6e8947d77b2806cf47a4a15f2c846e2cbeb1882547d3da283/aiohttp-3.14.1-cp311-cp311-win_amd64.whl", hash = "sha256:03ab4530fdcb3a543a122ba4b65ac9919da9fe9f78a03d328a6e38ff962f7aa5", size = 483406, upload-time = "2026-06-07T21:06:36.824Z" }, + { url = "https://files.pythonhosted.org/packages/2c/8a/c25904f77690c3688ec140f87591ef11a0cfe36bf3d5c0f1f38056fb62b3/aiohttp-3.14.1-cp311-cp311-win_arm64.whl", hash = "sha256:486f7d16ed54c39c2cbd7ca71fd8ba2b8bb7860df65bd7b6ed640bab96a38a8b", size = 452987, upload-time = "2026-06-07T21:06:38.371Z" }, + { url = "https://files.pythonhosted.org/packages/1d/21/151624b51cd92553d95424daf4bf19f19ce9be9002d19253e7e7ce67197b/aiohttp-3.14.1-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:d35143e27778b4bb0fb189562d7f275bff79c62ab8e98459717c0ea617ff2480", size = 757402, upload-time = "2026-06-07T21:06:40.311Z" }, + { url = "https://files.pythonhosted.org/packages/c2/82/280619e0bd7bf2454987e19282616e84762255dd9c8468f62382e8c191f1/aiohttp-3.14.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:bcfb80a2cc36fba2534e5e5b5264dc7ae6fcd9bf15256da3e53d2f499e6fa29d", size = 512310, upload-time = "2026-06-07T21:06:42.207Z" }, + { url = "https://files.pythonhosted.org/packages/55/b2/2aac325583aaa1353045f96dffa586d8a34e8322e14a7ba49cffeb103ab4/aiohttp-3.14.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:27fd7c91e51729b4f7e1577865fa6d34c9adccbc39aabe9000285b48af9f0ec2", size = 512448, upload-time = "2026-06-07T21:06:43.813Z" }, + { url = "https://files.pythonhosted.org/packages/8a/72/a60607cb849faa8af8a356c9329ea2eb6f395d49e82cc82ccba1fd8deb8f/aiohttp-3.14.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:64c567bf9eaf664280116a8688f63016e6b32db2505908e2bdaca1b6438142f2", size = 1766854, upload-time = "2026-06-07T21:06:45.391Z" }, + { url = "https://files.pythonhosted.org/packages/b5/d3/d9fe1c9ec7557ab4d0d82bebaa728c6418f0b93295ec2f4ab015f7710cc7/aiohttp-3.14.1-cp312-cp312-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:f5e6ff2bdbb8f4cd3fbe41f99e25bbcd58e3bf9f13d3dd31a11e7917251cc77a", size = 1740884, upload-time = "2026-06-07T21:06:47.413Z" }, + { url = "https://files.pythonhosted.org/packages/c1/dc/f2cecfaf9337ba3e63f181500814ff502aa3d00d9c7ec93a9d23d10a27b2/aiohttp-3.14.1-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:2f73e01dc37122325caf079982621262f96d74823c179038a82fddfc50359264", size = 1810034, upload-time = "2026-06-07T21:06:50.165Z" }, + { url = "https://files.pythonhosted.org/packages/66/d7/2ff65c5e65c0d7476daf7e15c032e0805e36811185b9623e3238ad6c763e/aiohttp-3.14.1-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:bb2c0c80d431c0d03f2c7dbf125150fedd4f0de17366a7ca33f7ccb822391842", size = 1904054, upload-time = "2026-06-07T21:06:52.035Z" }, + { url = "https://files.pythonhosted.org/packages/20/9c/d445818389df371f56d141d881153ba23183c4735a03f7356ffb43f7757d/aiohttp-3.14.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:3e6fc1a85fa7194a1a7d19f44e8609180f4a8eb5fa4c7ed8b4355f080fad235c", size = 1790278, upload-time = "2026-06-07T21:06:54.049Z" }, + { url = "https://files.pythonhosted.org/packages/4d/aa/bf04cb4d865fc6101c2229a294ad744973b72e513fdc5a6b791e6983d72a/aiohttp-3.14.1-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:686b6c0d3911ec387b444ddf5dc62fb7f7c0a7d5186a7861626496a5ab4aff95", size = 1591795, upload-time = "2026-06-07T21:06:55.911Z" }, + { url = "https://files.pythonhosted.org/packages/dc/b4/4dac0038960427ba832f6609dfb4ea5437d7fd80c72001b9e48f834f428b/aiohttp-3.14.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:c6fa4dc7ad6f8109c70bb1499e589f76b0b792baf39f9b017eb92c8a81d0a199", size = 1728397, upload-time = "2026-06-07T21:06:57.777Z" }, + { url = "https://files.pythonhosted.org/packages/2b/f9/7cd4e8ad7aa3b75f17d56bb5498dd604a93d4e6eece822ba0568c413fff0/aiohttp-3.14.1-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:87a5eea1b2a5e21e1ebdbb33ad4165359189327e63fc4e4894693e7f821ac817", size = 1766504, upload-time = "2026-06-07T21:07:00.009Z" }, + { url = "https://files.pythonhosted.org/packages/f9/df/fc01d9fcad0f73fed3f3d361f1f94f975947b50dff82919f6dc2bf4316cc/aiohttp-3.14.1-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:1c1421eb01d4fd608d88cc8290211d177a58532b55ad94076fb349c5bf467f0a", size = 1777806, upload-time = "2026-06-07T21:07:02.064Z" }, + { url = "https://files.pythonhosted.org/packages/41/09/47e2d090bddcc8fb4ccb4c314aadc32d7c5d9bb55f50f6ad1c92fc15d501/aiohttp-3.14.1-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:34b257ec41345c1e8f2df68fa908a7952f5de932723871eb633ecbbff396c9a4", size = 1580707, upload-time = "2026-06-07T21:07:03.942Z" }, + { url = "https://files.pythonhosted.org/packages/3d/36/f1a4ce904ae0b6930cfe9afc96d0896f7ec1a620c400405d63783bb95a9c/aiohttp-3.14.1-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:de538791a80e5d862addbc183f70f0158ac9b9bb872bb147f1fd2a683691e087", size = 1798121, upload-time = "2026-06-07T21:07:05.987Z" }, + { url = "https://files.pythonhosted.org/packages/70/0a/e0075ce9ca0279ee1d4f0c0b85f54fea02ebc83c3007651a72bece658fec/aiohttp-3.14.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:6f71173be42d3241d428f760122febb748de0623f44308a6f120d0dd9ec572e3", size = 1767580, upload-time = "2026-06-07T21:07:07.873Z" }, + { url = "https://files.pythonhosted.org/packages/3e/61/a0c0a8f327a9c52095cdd8e312391b00d3ed64ab6c72bb5c33d8ec251cf7/aiohttp-3.14.1-cp312-cp312-win32.whl", hash = "sha256:ec8dc383ee57ea3e883477dcca3f11b65d58199f1080acaf4cd6ad9a99698be4", size = 452771, upload-time = "2026-06-07T21:07:09.669Z" }, + { url = "https://files.pythonhosted.org/packages/df/d9/ea367c75f16ac9c6cdc8febb25e8318fa21a2b1bc8d6514d4b2d890bface/aiohttp-3.14.1-cp312-cp312-win_amd64.whl", hash = "sha256:2aa92c87868cd13674989f9ee83e5f9f7ea4237589b728048e1f0c8f6caa3271", size = 479873, upload-time = "2026-06-07T21:07:11.538Z" }, + { url = "https://files.pythonhosted.org/packages/03/64/8d96784a7851156db8a4c6c3f6f91042fdf39fb15a4cc38c8b3c14833c45/aiohttp-3.14.1-cp312-cp312-win_arm64.whl", hash = "sha256:2c840c90759922cb5e6dda94596e079a30fb5a5ba548e7e0dc00574703940847", size = 448073, upload-time = "2026-06-07T21:07:13.637Z" }, + { url = "https://files.pythonhosted.org/packages/bc/97/bd137012dd97e1649162b099135a80e1fd59aaa807b2430fc448d1029aff/aiohttp-3.14.1-cp313-cp313-android_21_arm64_v8a.whl", hash = "sha256:b3a03285a7f9c7b016324574a6d92a1c895da6b978cb8f1deee3ac72bc6da178", size = 506882, upload-time = "2026-06-07T21:07:15.501Z" }, + { url = "https://files.pythonhosted.org/packages/ef/79/e5cc690e9d922a66887ceeaca53a8ffd5a7b0be3816142b7abc433742d89/aiohttp-3.14.1-cp313-cp313-android_21_x86_64.whl", hash = "sha256:2a73f487ab8ef5abbb24b7aa9b73e98eaba9e9e031804ff2416f02eca315ccaf", size = 515270, upload-time = "2026-06-07T21:07:17.53Z" }, + { url = "https://files.pythonhosted.org/packages/fe/22/a73ccbf9dbd6e26dda0b24d5fd5db7da92ee3383a79f47677ffb834c5c5b/aiohttp-3.14.1-cp313-cp313-ios_13_0_arm64_iphoneos.whl", hash = "sha256:915fbb7b41b115192259f8c9ae58f3ddc444d2b5579917270211858e606a4afd", size = 485841, upload-time = "2026-06-07T21:07:19.555Z" }, + { url = "https://files.pythonhosted.org/packages/3b/b9/57ed8eaf596321c2ad747bd480fb1700dbd7177c60dfc9e4c187f629662e/aiohttp-3.14.1-cp313-cp313-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:7fb4bdf95b0561a79f259f9d28fbc109728c5ee7f27aff6391f0ca703a329abe", size = 492088, upload-time = "2026-06-07T21:07:21.581Z" }, + { url = "https://files.pythonhosted.org/packages/78/c0/5ebe5270a7c140d7c6f79dcb018640225f14d406c149e4eec04a7d82fe71/aiohttp-3.14.1-cp313-cp313-ios_13_0_x86_64_iphonesimulator.whl", hash = "sha256:1b9748363260121d2927704f5d4fc498150669ca3ae93625986ee89c8f80dcd4", size = 501564, upload-time = "2026-06-07T21:07:23.388Z" }, + { url = "https://files.pythonhosted.org/packages/75/7f/8cdaa24fc7983865e0915153b96a9ac5bcdd3548d64c5a27d17cecccad2d/aiohttp-3.14.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:86a6dab78b0e43e2897a3bbe15745aa60dc5423ca437b7b0b164c069bf91b876", size = 751998, upload-time = "2026-06-07T21:07:25.046Z" }, + { url = "https://files.pythonhosted.org/packages/b2/f4/c4227aacfacc5cb0cc2d119b65301d177912a6842cd64e120c47af76064f/aiohttp-3.14.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:4dfd6e47d3c44c2279907607f73a4240b88c69eb8b90da7e2441a8045dfd21da", size = 510918, upload-time = "2026-06-07T21:07:27.28Z" }, + { url = "https://files.pythonhosted.org/packages/ab/01/a2d5f96cd4e74424864d30bc0a7e44d0a12dacdcfa91b5b2d1bd3dca6bf3/aiohttp-3.14.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:317acd9f8602858dc7d59679812c376c7f0b97bcbbf16e0d6237f54141d8a8a6", size = 508657, upload-time = "2026-06-07T21:07:29.252Z" }, + { url = "https://files.pythonhosted.org/packages/e8/ed/3c0fb5c500fdd8e7ebc10d1889c04384fffa1a9163eac1356088ca9da1b1/aiohttp-3.14.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:bd869c427324e5cb15195793de951295710db28be7d818247f3097b4ab5d4b96", size = 1757907, upload-time = "2026-06-07T21:07:31.03Z" }, + { url = "https://files.pythonhosted.org/packages/0b/ab/d4c924d9bd5be3050c226612413ce68cb54c70d2c31b661bfc8d9a5b6a70/aiohttp-3.14.1-cp313-cp313-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:93b032b5ec3255473c143627d21a69ac74ae12f7f33974cb587c564d11b1066f", size = 1737565, upload-time = "2026-06-07T21:07:33.031Z" }, + { url = "https://files.pythonhosted.org/packages/19/2a/37326821ff779084020cdc33224d20b19f42f4183a500ff92022a739eda7/aiohttp-3.14.1-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:f234b4deb12f3ad59127e037bc57c40c21e45b45282df7d3a55a0f409f595296", size = 1799018, upload-time = "2026-06-07T21:07:35.003Z" }, + { url = "https://files.pythonhosted.org/packages/b3/4f/6e947ba73e4ce09070761c05ed3a8ceb7c21f5e46798671d8b2aac0e4626/aiohttp-3.14.1-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:9af6779bfb46abf124068327abcdf9ce95c9ef8287a3e8da76ccf2d0f16c28fa", size = 1894416, upload-time = "2026-06-07T21:07:36.956Z" }, + { url = "https://files.pythonhosted.org/packages/9d/6e/dbf1d0625dc711fb2851f4f3c3055c39ed58bae92082d8c627dbe6013736/aiohttp-3.14.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:faccab372e66bc76d5731525e7f1143c922271725b9d38c9f97edcc66266b451", size = 1783881, upload-time = "2026-06-07T21:07:39.063Z" }, + { url = "https://files.pythonhosted.org/packages/44/c2/5e25098a67268ed369483ae7d1a58bd0a13d03aab860d2a0e4a6eb25b046/aiohttp-3.14.1-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:f380468b09d2a81633ee863b0ec5648d364bd17bb8ecfb8c2f387f7ac1faf42c", size = 1587572, upload-time = "2026-06-07T21:07:41.058Z" }, + { url = "https://files.pythonhosted.org/packages/2a/bd/cf9cee17e140f942a3de73e658a543aa8fbf35a5fc67a9d2538d52d77f0b/aiohttp-3.14.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:97e704dcd26271f5bda3fa07c3ce0fb76d6d3f8659f4baa1a24442cc9ba177ca", size = 1722137, upload-time = "2026-06-07T21:07:43.014Z" }, + { url = "https://files.pythonhosted.org/packages/89/6d/5684f8c59045c96f81a18cefbc1fbbd79d25b88f1c622f2a5c5c08fcb632/aiohttp-3.14.1-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:269b76ac5394092b95bc4a098f4fc6c191c083c3bd12775d1e30e663132f6a09", size = 1755953, upload-time = "2026-06-07T21:07:45.933Z" }, + { url = "https://files.pythonhosted.org/packages/a8/40/35caf3170f8359760740a7d9aa0fff2e344bef98e1d1186f5a0f6dec17e6/aiohttp-3.14.1-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:5c0b3e614340c889d575451696374c9d17affd54cd607ca0babed8f8c37b9397", size = 1766479, upload-time = "2026-06-07T21:07:48.047Z" }, + { url = "https://files.pythonhosted.org/packages/6d/a1/b0c61e7a137f0d81de49a82023a6df73c3c16d6fefb0f8e4a93d21639002/aiohttp-3.14.1-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:5663ee9257cfa1add7253a7da3035a02f31b6600ec48261585e1800a81533080", size = 1580077, upload-time = "2026-06-07T21:07:50.069Z" }, + { url = "https://files.pythonhosted.org/packages/0b/41/194ea4623693009fcefebef7aef63c141754f153e9cd0d39d3b9e36c175c/aiohttp-3.14.1-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:603a2c834142172ffddc054067f5ec0ca65d57a0aa98a71bc81952573208e345", size = 1791688, upload-time = "2026-06-07T21:07:52.106Z" }, + { url = "https://files.pythonhosted.org/packages/ba/45/4de841f005cfe1fd63e2a2fe011262c515e2a62aa6994b15947e7d717ac9/aiohttp-3.14.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:cb21957bb8aca671c1765e32f58164cf0c50e6bf41c0bbbd16da20732ecaf588", size = 1761094, upload-time = "2026-06-07T21:07:54.113Z" }, + { url = "https://files.pythonhosted.org/packages/e4/ae/dbce10533d3896d544d5053939ed75b7dc31a1b0973d959b1b5ae21028d6/aiohttp-3.14.1-cp313-cp313-win32.whl", hash = "sha256:e509a55f681e6158c20f70f102f9cf61fb20fbc382272bc6d94b7343f2582780", size = 452662, upload-time = "2026-06-07T21:07:56.06Z" }, + { url = "https://files.pythonhosted.org/packages/7b/d9/0bf1a19362c32f06229da5e7ddfcec91f93474d6307f7a2d3135e9c674dc/aiohttp-3.14.1-cp313-cp313-win_amd64.whl", hash = "sha256:1ac8531b638959718e18c2207fbfe297819875da46a740b29dfa29beba64355a", size = 479748, upload-time = "2026-06-07T21:07:58.319Z" }, + { url = "https://files.pythonhosted.org/packages/22/0a/62e7232dc9484fbec112ceb32efb6a624cc7994ec6e2b019286f17c4e8f2/aiohttp-3.14.1-cp313-cp313-win_arm64.whl", hash = "sha256:250d14af67f6b6a1a4a811049b1afa69d61d617fca6bf33149b3ab1a6dbcf7b8", size = 447723, upload-time = "2026-06-07T21:08:00.154Z" }, + { url = "https://files.pythonhosted.org/packages/c4/a1/5fafa04e1ca91ddb47608699d60649c1c6db3cf41c99e78fc4056f9513db/aiohttp-3.14.1-cp314-cp314-android_24_arm64_v8a.whl", hash = "sha256:7c106c26852ca1c2047c6b80384f17100b4e439af276f21ef3d4e2f450ae7e15", size = 508531, upload-time = "2026-06-07T21:08:02.093Z" }, + { url = "https://files.pythonhosted.org/packages/fa/2e/bfa02f699d87ffc86d5959270b28f1cb410add3ccaced8ed2e0b8a5238fc/aiohttp-3.14.1-cp314-cp314-android_24_x86_64.whl", hash = "sha256:20205f7f5ade7aaec9f4b500549bbc071b046453aed72f9c06dcab87896a83e8", size = 514718, upload-time = "2026-06-07T21:08:04.476Z" }, + { url = "https://files.pythonhosted.org/packages/85/a5/9594ad6289eebbc97d167c44213d557807f90e59115caad24de21ad2c3b1/aiohttp-3.14.1-cp314-cp314-ios_13_0_arm64_iphoneos.whl", hash = "sha256:62a759436b29e677181a9e76bab8b8f689a29cb9c535f45f7c48c9c830d3f8c3", size = 487918, upload-time = "2026-06-07T21:08:06.377Z" }, + { url = "https://files.pythonhosted.org/packages/b4/61/16a32c36c3c49edec122a3dc811f2057df2f94d3b14aa107c8017d981618/aiohttp-3.14.1-cp314-cp314-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:2964cbf553df4d7a57348da44d961d871895fc1ee4e8c322b2a95612c7b17fba", size = 494014, upload-time = "2026-06-07T21:08:08.263Z" }, + { url = "https://files.pythonhosted.org/packages/9b/89/3ebcf96ed99c05bec9c434aaac6963fd3cbab4a786ae739908a144d9ce44/aiohttp-3.14.1-cp314-cp314-ios_13_0_x86_64_iphonesimulator.whl", hash = "sha256:237651caadc3a59badd39319c54642b5299e9cc98a3a194310e55d5bb9f5e397", size = 502398, upload-time = "2026-06-07T21:08:10.244Z" }, + { url = "https://files.pythonhosted.org/packages/fd/3d/b74870a0c2d40c355928cd5b96c7a11fa821b8a40fc41365e64479b151fb/aiohttp-3.14.1-cp314-cp314-macosx_10_15_universal2.whl", hash = "sha256:896e12dfdbbab9d8f7e16d2b28c6769a60126fa92095d1ebf9473d02593a2448", size = 758018, upload-time = "2026-06-07T21:08:12.447Z" }, + { url = "https://files.pythonhosted.org/packages/d3/66/f42f5c984d99e49c6cff5f26f590750f2e2f7ef1fcfb99966ab5be1b632e/aiohttp-3.14.1-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:d03f281ed22579314ba00821ce20115a7c0ac430660b4cc05704a3f818b3e004", size = 512462, upload-time = "2026-06-07T21:08:14.624Z" }, + { url = "https://files.pythonhosted.org/packages/e9/a7/248e1aebe0c7810b0271e021a0f2a5eb6e78a051885b3c9df49f42a5802d/aiohttp-3.14.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:07eabb979d236335fed927e137a928c9adfb7df3b9ec7aa31726f133a62be983", size = 512824, upload-time = "2026-06-07T21:08:16.572Z" }, + { url = "https://files.pythonhosted.org/packages/26/97/2aa0e5ba0727dc3bd5aaebb7ccbc510f7dfb7fb961ec87497cd496635ab1/aiohttp-3.14.1-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4fe1f1087cbadb280b5e1bb054a4f00d1423c74d6626c5e48400d871d34ecefe", size = 1749898, upload-time = "2026-06-07T21:08:18.635Z" }, + { url = "https://files.pythonhosted.org/packages/00/8d/e97f6c96c891d457c8479d92a514ba194d0412f981d72c70341ee18488ed/aiohttp-3.14.1-cp314-cp314-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:367a9314fdc79dab0fac96e216cb41dd73c85bdca85306ce8999118ba7e0f333", size = 1710114, upload-time = "2026-06-07T21:08:20.892Z" }, + { url = "https://files.pythonhosted.org/packages/6f/e6/aa8d7e863048c8fceb5cd6ce74017311cec3ead07847387e12265fb4444e/aiohttp-3.14.1-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:a24f677ebe83749039e7bdf862ff0bbb16818ae4193d4ef96505e269375bcce0", size = 1802541, upload-time = "2026-06-07T21:08:23.044Z" }, + { url = "https://files.pythonhosted.org/packages/83/a8/72193137de57fda4ebfae4563182d082c8856e3b6e9871d0b46f028fb369/aiohttp-3.14.1-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:c83afe0ba876be7e943d2e0ba645809ad441575d2840c895c21ee5de93b9377a", size = 1875776, upload-time = "2026-06-07T21:08:25.288Z" }, + { url = "https://files.pythonhosted.org/packages/a0/18/938441025db6769a3464596b2410af3afde0b21eb2f204c6f766f68af4bd/aiohttp-3.14.1-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:634e385930fb6d2d479cf3aa66515955863b77a5e3c2b5894ca259a25b308602", size = 1760329, upload-time = "2026-06-07T21:08:27.363Z" }, + { url = "https://files.pythonhosted.org/packages/60/29/bf2496b4065e76e09fe48015aaffe5ce161d8f089b06ac6982070f653076/aiohttp-3.14.1-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:eeea07c4397bbc57719c4eed8f9c284874d4f175f9b6d57f7a1546b976d455ca", size = 1587293, upload-time = "2026-06-07T21:08:29.805Z" }, + { url = "https://files.pythonhosted.org/packages/49/a2/2136674d52123b1354bd05dd5753c318db47dc0c927cc70b27bab3755456/aiohttp-3.14.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:335c0cc3e3545ce98dcb9cfcb836f40c3411f43fa03dab757597d80c89af8a35", size = 1714756, upload-time = "2026-06-07T21:08:32.094Z" }, + { url = "https://files.pythonhosted.org/packages/a7/b9/e5fd2e6f915503081c0f9b1e8540947037929c70c191da2e4d54b31a21a1/aiohttp-3.14.1-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:ae6be797afdef264e8a84864a85b196ca06045586481b3df8a967322fd2fa844", size = 1721052, upload-time = "2026-06-07T21:08:34.167Z" }, + { url = "https://files.pythonhosted.org/packages/63/5a/2833e324a2263e104e31e2e91bc5bbee81bc499afd32203faee048a883f0/aiohttp-3.14.1-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:8560b4d712474335d08907db7973f71912d3a9a8f1dee992ec06b5d2fe359496", size = 1766888, upload-time = "2026-06-07T21:08:36.95Z" }, + { url = "https://files.pythonhosted.org/packages/57/fa/dea6511870913162f3b2e8c42a7614eb203a4540b8c2da43e0bfb0548f3c/aiohttp-3.14.1-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:2b7edd08e0a5deb1e8564a2fcd8f4561014a3f05252334671bbf55ddd47db0e5", size = 1581679, upload-time = "2026-06-07T21:08:39.292Z" }, + { url = "https://files.pythonhosted.org/packages/14/bd/3cf0d55e71784b33534e9710a67d382d900598b4787fbce6cc7317f8c42a/aiohttp-3.14.1-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:b6ff7fcee63287ae57b5df3e4f5957ce032122802509246dec1a5bcc55904c95", size = 1782021, upload-time = "2026-06-07T21:08:41.407Z" }, + { url = "https://files.pythonhosted.org/packages/c1/af/14bb5843eccbe234f4dfb78ab73e549d99727247e62ae5d62cbd22eaf5b0/aiohttp-3.14.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:6ffbb2f4ec1ceaff7e07d43922954da26b223d188bf30658e561b98e23089444", size = 1742574, upload-time = "2026-06-07T21:08:43.795Z" }, + { url = "https://files.pythonhosted.org/packages/f2/1e/fbeb7af9210a67ac0f9c9bec0f8f4568497924e33137a3d5b48e1cf85f3f/aiohttp-3.14.1-cp314-cp314-win32.whl", hash = "sha256:a9875b46d910cff3ea2f5962f9d266b465459fe634e22556ab9bd6fc1192eea0", size = 457773, upload-time = "2026-06-07T21:08:46.168Z" }, + { url = "https://files.pythonhosted.org/packages/f0/2b/13e8d741a9ec5db7d900c060554cf8352ab85e44e2a4469ebb9d377bda17/aiohttp-3.14.1-cp314-cp314-win_amd64.whl", hash = "sha256:af8b4b81a960eeaf1234971ac3cd0ba5901f3cd42eae42a46b4d089a8b492719", size = 485001, upload-time = "2026-06-07T21:08:48.401Z" }, + { url = "https://files.pythonhosted.org/packages/df/30/491acfa2c4d6c3ff59c49a14fc1b50be3241e25bbb0c84c09e2da4d11395/aiohttp-3.14.1-cp314-cp314-win_arm64.whl", hash = "sha256:cf4491381b1b57425c315a56a439251b1bdac07b2275f19a8c44bc57744532ec", size = 453809, upload-time = "2026-06-07T21:08:50.7Z" }, + { url = "https://files.pythonhosted.org/packages/34/e3/19dbe1a1f4cc6230eb9e314de7fe68053b0992f9302b27d12141a0b5db53/aiohttp-3.14.1-cp314-cp314t-macosx_10_15_universal2.whl", hash = "sha256:819c054312f1af92947e6a55883d1b66feefab11531a7fc45e0fb9b63880b5c2", size = 793320, upload-time = "2026-06-07T21:08:52.775Z" }, + { url = "https://files.pythonhosted.org/packages/7f/20/1b7182219ba1b108430d6e4dc53d25ae02dcfcf5a045b33af4e8c5167527/aiohttp-3.14.1-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:10ee9c1753a8f706345b22496c79fbddb5be0599e0823f3738b1534058e25340", size = 529077, upload-time = "2026-06-07T21:08:55Z" }, + { url = "https://files.pythonhosted.org/packages/b9/c8/14ce60ec31a2e5f5274bb17d383a6f7a3aabca31ac04eee05585bbadab16/aiohttp-3.14.1-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:1601cc37baf5750ccacae618ec2daf020769581695550e3b654a911f859c563d", size = 532476, upload-time = "2026-06-07T21:08:57.176Z" }, + { url = "https://files.pythonhosted.org/packages/7e/02/9ac85e081e53da2e061b02fa7758fe0a12d17b8ce2d1f5e6c7cb76730328/aiohttp-3.14.1-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4d6e0ac9da31c9c04c84e1c0182ad8d6df35965a85cae29cd71d089621b3ae94", size = 1922347, upload-time = "2026-06-07T21:08:59.563Z" }, + { url = "https://files.pythonhosted.org/packages/c0/3e/d3ba07a0ab38b5389e10bec4362d21e10a4f667cba2d79ba30837b3a5059/aiohttp-3.14.1-cp314-cp314t-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:9e8f2d660c350b3d0e259c7a7e3d9b7fc8b41210cbcc3d4a7076ff0a5e5c2fdc", size = 1786465, upload-time = "2026-06-07T21:09:01.909Z" }, + { url = "https://files.pythonhosted.org/packages/0b/cb/e2ee978a00cfb2df829704a69528b18154eba5939f45bc1efa8f33aee4c5/aiohttp-3.14.1-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:4691802dda97be727f79d86818acaad7eb8e9252626a1d6b519fedbb92d5e251", size = 1909423, upload-time = "2026-06-07T21:09:04.357Z" }, + { url = "https://files.pythonhosted.org/packages/73/5d/1430334858b1022b58ae50399a918f0bd6fe8fa7fa183598d657ff61e040/aiohttp-3.14.1-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:c389c482a7e9b9dc3ee2701ac46c4125297a3818875b9c305ddb603c04828fd1", size = 2001906, upload-time = "2026-06-07T21:09:06.722Z" }, + { url = "https://files.pythonhosted.org/packages/66/4e/560c7472d3d198a23aa5c8b19a5115bf6a9b77b7d3e4bb363da320430ad2/aiohttp-3.14.1-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:fc0cacab7ba4e56f0f81c82a98c09bed2f39c940107b03a34b168bdf7597edd3", size = 1877095, upload-time = "2026-06-07T21:09:09.011Z" }, + { url = "https://files.pythonhosted.org/packages/0d/f1/4745806578d447db4a784a8591e2dae3afdfc2bcb96f8f81271b13df6543/aiohttp-3.14.1-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:979ed4717f59b8bb12e3963378fa285d93d367e15bcd66c721311826d3c44a6c", size = 1676222, upload-time = "2026-06-07T21:09:11.461Z" }, + { url = "https://files.pythonhosted.org/packages/6a/c9/48255813cca749a229ef0ab476004ec623728ad79a9c0840616f6c076325/aiohttp-3.14.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:38e1e7daaea81df51c952e18483f323d878499a1e2bfe564790e0f9701d6f203", size = 1842922, upload-time = "2026-06-07T21:09:14.118Z" }, + { url = "https://files.pythonhosted.org/packages/3d/c0/bbd054e2bee909f529523a5af3891052606af5143c09f5f183ec3b234676/aiohttp-3.14.1-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:4132e72c608fe9fecb8f409113567605915b83e9bdd3ea56538d2f9cd35002f1", size = 1825035, upload-time = "2026-06-07T21:09:16.447Z" }, + { url = "https://files.pythonhosted.org/packages/a8/ae/90395d4376deceb74e09ec26b6adf7d2015a6f8802d6d84446af860fef04/aiohttp-3.14.1-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:eefd9cc9b6d4a2db5f00a26bc3e4f9acf71926a6ec557cd56c9c6f27c290b665", size = 1849512, upload-time = "2026-06-07T21:09:18.742Z" }, + { url = "https://files.pythonhosted.org/packages/93/bd/fb25f3049957553d4ce0ba6ae480aa2f592a6985497fca590837d16c1be0/aiohttp-3.14.1-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:b165790117eea512d7f3fb22f1f6dad3d55a7189571993eb015591c1401276d1", size = 1668571, upload-time = "2026-06-07T21:09:21.458Z" }, + { url = "https://files.pythonhosted.org/packages/3f/22/7f73303d64dd567ff3addca90b556690ed1233a47b8f55d242fb90af3681/aiohttp-3.14.1-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:ed09c7eb1c391271c2ed0314a51903e72a3acb653d5ccfc264cdf3ef11f8269d", size = 1881159, upload-time = "2026-06-07T21:09:23.813Z" }, + { url = "https://files.pythonhosted.org/packages/44/be/0474c5a8b5640e1e4aa1923430a91f4151be82e511373fe764189b89aef5/aiohttp-3.14.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:99abd37084b82f5830c635fddd0b4993b9742a66eb746dacf433c8590e8f9e3c", size = 1841409, upload-time = "2026-06-07T21:09:26.207Z" }, + { url = "https://files.pythonhosted.org/packages/7b/3c/bb4a7cba26956cb3da4553cc2056cf67be5b5ff6e6d8fa4fbdff73bfb7ae/aiohttp-3.14.1-cp314-cp314t-win32.whl", hash = "sha256:47ddf841cdecc810749921d25606dee45857d12d2ad5ddb7b5bd7eab12e4b365", size = 494166, upload-time = "2026-06-07T21:09:28.505Z" }, + { url = "https://files.pythonhosted.org/packages/8a/84/ec80c2c1f66a952555a9f86df6b33af65108a6febfa0471b69013a12f807/aiohttp-3.14.1-cp314-cp314t-win_amd64.whl", hash = "sha256:5e78b522b7a6e27e0b25d19b247b75039ac4c94f99823e3c9e53ae1603a9f7e9", size = 530255, upload-time = "2026-06-07T21:09:30.843Z" }, + { url = "https://files.pythonhosted.org/packages/2a/71/6e22be134a4061ada85a92951b842f2657f17d926b727f3f94c56ae963d6/aiohttp-3.14.1-cp314-cp314t-win_arm64.whl", hash = "sha256:90d53f1609c29ccc2193945ef732428382a28f78d0456ae4d3daf0d48b74f0f6", size = 469640, upload-time = "2026-06-07T21:09:33.028Z" }, ] [[package]] @@ -296,15 +313,15 @@ wheels = [ [[package]] name = "authlib" -version = "1.7.0" +version = "1.7.2" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "cryptography" }, { name = "joserfc" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/d9/82/4d0603f30c1b4629b1f091bb266b0d7986434891d6940a8c87f8098db24e/authlib-1.7.0.tar.gz", hash = "sha256:b3e326c9aa9cc3ea95fe7d89fd880722d3608da4d00e8a27e061e64b48d801d5", size = 175890, upload-time = "2026-04-18T11:00:28.559Z" } +sdist = { url = "https://files.pythonhosted.org/packages/36/98/7d93f30d029643c0275dbc0bd6d5a6f670661ee6c9a94d93af7ab4887600/authlib-1.7.2.tar.gz", hash = "sha256:2cea25fefcd4e7173bdf1372c0afc265c8034b23a8cd5dcb6a9164b826c64231", size = 176511, upload-time = "2026-05-06T08:10:23.116Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/ca/48/c954218b2a250e23f178f10167c4173fecb5a75d2c206f0a67ba58006c26/authlib-1.7.0-py2.py3-none-any.whl", hash = "sha256:e36817afb02f6f0b6bf55f150782499ddd6ddf44b402bb055d3263cc65ac9ae0", size = 258779, upload-time = "2026-04-18T11:00:26.64Z" }, + { url = "https://files.pythonhosted.org/packages/fb/95/adcb68e20c34162e9135f370d6e31737719c2b6f94bc953fe7ed1f10fe21/authlib-1.7.2-py2.py3-none-any.whl", hash = "sha256:3e1faedc9d87e7d56a164eca3ccb6ace0d61b94abe83e92242f8dc8bba9b4a9f", size = 259548, upload-time = "2026-05-06T08:10:21.436Z" }, ] [[package]] @@ -330,7 +347,7 @@ wheels = [ [[package]] name = "aws-sam-translator" -version = "1.106.0" +version = "1.110.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "boto3" }, @@ -338,9 +355,9 @@ dependencies = [ { name = "pydantic" }, { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/d3/52/feef23ec9392e2321ab889fa491a1a86d5818d35948bc331cd92dae0087c/aws_sam_translator-1.106.0.tar.gz", hash = "sha256:87712ced7eb6835fea2d4e9674ba7268494aa98f5b186ec5ad684245e2707ef7", size = 355440, upload-time = "2025-12-17T19:07:05.078Z" } +sdist = { url = "https://files.pythonhosted.org/packages/6e/2f/adeed2ce2bc62eca7ead7b3ae70fdd2cf84eecd582cd69a9529e6da89876/aws_sam_translator-1.110.0.tar.gz", hash = "sha256:466ee0e8200992c51b7fd5ede5e56ca2e8dd5473cc551e8495c14f2f4d636127", size = 368671, upload-time = "2026-05-19T21:21:06.959Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/64/b9/8272f2a22ab1c225ded0fafc702adca0f6631777df9999f7b9b793c48feb/aws_sam_translator-1.106.0-py3-none-any.whl", hash = "sha256:09e58160cdba3539dd37be209bc2accf51f8b71f8d4cc5431e248f794b122644", size = 415433, upload-time = "2025-12-17T19:07:03.285Z" }, + { url = "https://files.pythonhosted.org/packages/42/6f/286e3e49d3b6b181473fefa5d9fc02e10d98ccc417e0de74e396db951fd9/aws_sam_translator-1.110.0-py3-none-any.whl", hash = "sha256:69b09aacf2d305ac747037b7b913224cb8a9d653f47a0306509c1d20e420b670", size = 431671, upload-time = "2026-05-19T21:21:05.26Z" }, ] [[package]] @@ -388,15 +405,15 @@ wheels = [ [[package]] name = "beautifulsoup4" -version = "4.14.3" +version = "4.15.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "soupsieve" }, { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/c3/b0/1c6a16426d389813b48d95e26898aff79abbde42ad353958ad95cc8c9b21/beautifulsoup4-4.14.3.tar.gz", hash = "sha256:6292b1c5186d356bba669ef9f7f051757099565ad9ada5dd630bd9de5fa7fb86", size = 627737, upload-time = "2025-11-30T15:08:26.084Z" } +sdist = { url = "https://files.pythonhosted.org/packages/43/65/318323f98dbee45d42dff61d8f047181bc6f2268a9068cfad035a46be5af/beautifulsoup4-4.15.0.tar.gz", hash = "sha256:288e3ca7d54b06f2ac191970bc275c1939cb46d450b255bf6718b04aa37ab4f7", size = 632571, upload-time = "2026-06-07T16:44:20.453Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/1a/39/47f9197bdd44df24d67ac8893641e16f386c984a0619ef2ee4c51fbbc019/beautifulsoup4-4.14.3-py3-none-any.whl", hash = "sha256:0918bfe44902e6ad8d57732ba310582e98da931428d231a5ecb9e7c703a735bb", size = 107721, upload-time = "2025-11-30T15:08:24.087Z" }, + { url = "https://files.pythonhosted.org/packages/88/c6/92fcd42f1ba33e1184263f25bfabf3d27c383410470f169e4b8163bf9c17/beautifulsoup4-4.15.0-py3-none-any.whl", hash = "sha256:d6f88de62e1d4e38ecb1077eb9724cd0eff29d2a08ca16a401e9b9e93f117cf9", size = 109924, upload-time = "2026-06-07T16:44:21.566Z" }, ] [[package]] @@ -438,14 +455,14 @@ wheels = [ [[package]] name = "botocore-stubs" -version = "1.42.41" +version = "1.43.14" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "types-awscrt" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/0c/a8/a26608ff39e3a5866c6c79eda10133490205cbddd45074190becece3ff2a/botocore_stubs-1.42.41.tar.gz", hash = "sha256:dbeac2f744df6b814ce83ec3f3777b299a015cbea57a2efc41c33b8c38265825", size = 42411, upload-time = "2026-02-03T20:46:14.479Z" } +sdist = { url = "https://files.pythonhosted.org/packages/7f/81/79693e833291c00dc89ee610e5e915381b6f08233912e28df50106840780/botocore_stubs-1.43.14.tar.gz", hash = "sha256:9e3bc1fdd51da7473f0df726c82747a1b0ae913449d629659765c247fecc2039", size = 42738, upload-time = "2026-05-25T06:06:37.484Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/32/76/cab7af7f16c0b09347f2ebe7ffda7101132f786acb767666dce43055faab/botocore_stubs-1.42.41-py3-none-any.whl", hash = "sha256:9423110fb0e391834bd2ed44ae5f879d8cb370a444703d966d30842ce2bcb5f0", size = 66759, upload-time = "2026-02-03T20:46:13.02Z" }, + { url = "https://files.pythonhosted.org/packages/89/ca/f017727b11895908c5dedc829cf2ec35e0c4b2a26ba875db325fef2cefdf/botocore_stubs-1.43.14-py3-none-any.whl", hash = "sha256:fb98f1475c92fd718644e786b5c543a20f1b1f610e89e0a7191c3f1f429c75aa", size = 67093, upload-time = "2026-05-25T06:06:34.532Z" }, ] [[package]] @@ -477,11 +494,11 @@ filecache = [ [[package]] name = "certifi" -version = "2026.4.22" +version = "2026.5.20" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/25/ee/6caf7a40c36a1220410afe15a1cc64993a1f864871f698c0f93acb72842a/certifi-2026.4.22.tar.gz", hash = "sha256:8d455352a37b71bf76a79caa83a3d6c25afee4a385d632127b6afb3963f1c580", size = 137077, upload-time = "2026-04-22T11:26:11.191Z" } +sdist = { url = "https://files.pythonhosted.org/packages/f3/ce/ee2ecad540810a79593028e88299baeae54d346cc7a0d94b6199988b89b1/certifi-2026.5.20.tar.gz", hash = "sha256:69dea482ab64caa7b9f6aba1c6bf48bb6a5448d1c0f1b17ab42ad8c763a5344d", size = 135422, upload-time = "2026-05-20T11:46:50.073Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/22/30/7cd8fdcdfbc5b869528b079bfb76dcdf6056b1a2097a662e5e8c04f42965/certifi-2026.4.22-py3-none-any.whl", hash = "sha256:3cb2210c8f88ba2318d29b0388d1023c8492ff72ecdde4ebdaddbb13a31b1c4a", size = 135707, upload-time = "2026-04-22T11:26:09.372Z" }, + { url = "https://files.pythonhosted.org/packages/59/8c/57e832b7af6d7c5abe66eb3fbe3a3a32f4d11ea23a1aa7131371035be991/certifi-2026.5.20-py3-none-any.whl", hash = "sha256:3c52e209ba0a4ad7aebe60436a4ab349c39e1e602e8c134221e546902ad25897", size = 134134, upload-time = "2026-05-20T11:46:48.578Z" }, ] [[package]] @@ -568,7 +585,7 @@ wheels = [ [[package]] name = "cfn-lint" -version = "1.47.1" +version = "1.51.4" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "aws-sam-translator" }, @@ -580,9 +597,9 @@ dependencies = [ { name = "sympy" }, { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/10/34/e66811016e7709cab78b0cf896437b922d7537986ac727344663b6cc2044/cfn_lint-1.47.1.tar.gz", hash = "sha256:b2eedbcee3aa104602f79933e3ad74c01f0fa1e226b70327118926fd78d8d3f1", size = 3672271, upload-time = "2026-03-24T15:59:34.526Z" } +sdist = { url = "https://files.pythonhosted.org/packages/22/7d/77cb6921776aff87b261a48610b977b1f3d790c2caee9d6d8c6d251329d1/cfn_lint-1.51.4.tar.gz", hash = "sha256:d37c48645e03abecfd826b8588103b06991abd838fe05c641f2853812289c021", size = 4156267, upload-time = "2026-06-03T15:17:06.006Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/a5/88/19802ef0e1ef6259c4bc4b58226c0e7ff8b7ae93806ca32354c007e3480a/cfn_lint-1.47.1-py3-none-any.whl", hash = "sha256:3a4b5dba0fd03c24f2bc0e112a88ad90fa29014971e881b8f1e297d22f398a97", size = 5299292, upload-time = "2026-03-24T15:59:31.86Z" }, + { url = "https://files.pythonhosted.org/packages/26/7f/a541df327c5c25c4e59e8bc35961f6c244837f9d0f3f2f22f94272e5fd11/cfn_lint-1.51.4-py3-none-any.whl", hash = "sha256:4897321a7d90c6e48859fde0c7c7c3c919815a947ddc85d0584dc12ad5bc544c", size = 6162327, upload-time = "2026-06-03T15:17:03.659Z" }, ] [[package]] @@ -712,14 +729,14 @@ wheels = [ [[package]] name = "click" -version = "8.4.0" +version = "8.4.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "colorama", marker = "sys_platform == 'win32'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/23/e4/796662cd90cf80e3a363c99db2b88e0e394b988a575f60a17e16440cd011/click-8.4.0.tar.gz", hash = "sha256:638f1338fe1235c8f4e008e4a8a254fb5c5fbdcbb40ece3c9142ebb78e792973", size = 350843, upload-time = "2026-05-17T00:47:58.425Z" } +sdist = { url = "https://files.pythonhosted.org/packages/9b/98/518d8e5081007684232226f475082b30087d0f585e8457db087298259f49/click-8.4.1.tar.gz", hash = "sha256:918b5633eddf6b41c32d4f454bf0de810065c74e3f7dbf8ee5452f8be88d3e96", size = 353007, upload-time = "2026-05-22T04:08:37.769Z" } 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" }, + { url = "https://files.pythonhosted.org/packages/c7/0d/67e5b4109ea4a837e80daa87c2c696711955e40449a97e8926672534def2/click-8.4.1-py3-none-any.whl", hash = "sha256:482be17c6991b8c19c5429a1e995d9b0efdbb63172824c41f99965dc0ade8ec2", size = 116639, upload-time = "2026-05-22T04:08:35.26Z" }, ] [[package]] @@ -760,115 +777,115 @@ wheels = [ [[package]] name = "coverage" -version = "7.13.5" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/9d/e0/70553e3000e345daff267cec284ce4cbf3fc141b6da229ac52775b5428f1/coverage-7.13.5.tar.gz", hash = "sha256:c81f6515c4c40141f83f502b07bbfa5c240ba25bbe73da7b33f1e5b6120ff179", size = 915967, upload-time = "2026-03-17T10:33:18.341Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/69/33/e8c48488c29a73fd089f9d71f9653c1be7478f2ad6b5bc870db11a55d23d/coverage-7.13.5-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e0723d2c96324561b9aa76fb982406e11d93cdb388a7a7da2b16e04719cf7ca5", size = 219255, upload-time = "2026-03-17T10:29:51.081Z" }, - { url = "https://files.pythonhosted.org/packages/da/bd/b0ebe9f677d7f4b74a3e115eec7ddd4bcf892074963a00d91e8b164a6386/coverage-7.13.5-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:52f444e86475992506b32d4e5ca55c24fc88d73bcbda0e9745095b28ef4dc0cf", size = 219772, upload-time = "2026-03-17T10:29:52.867Z" }, - { url = "https://files.pythonhosted.org/packages/48/cc/5cb9502f4e01972f54eedd48218bb203fe81e294be606a2bc93970208013/coverage-7.13.5-cp310-cp310-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:704de6328e3d612a8f6c07000a878ff38181ec3263d5a11da1db294fa6a9bdf8", size = 246532, upload-time = "2026-03-17T10:29:54.688Z" }, - { url = "https://files.pythonhosted.org/packages/7d/d8/3217636d86c7e7b12e126e4f30ef1581047da73140614523af7495ed5f2d/coverage-7.13.5-cp310-cp310-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:a1a6d79a14e1ec1832cabc833898636ad5f3754a678ef8bb4908515208bf84f4", size = 248333, upload-time = "2026-03-17T10:29:56.221Z" }, - { url = "https://files.pythonhosted.org/packages/2b/30/2002ac6729ba2d4357438e2ed3c447ad8562866c8c63fc16f6dfc33afe56/coverage-7.13.5-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:79060214983769c7ba3f0cee10b54c97609dca4d478fa1aa32b914480fd5738d", size = 250211, upload-time = "2026-03-17T10:29:57.938Z" }, - { url = "https://files.pythonhosted.org/packages/6c/85/552496626d6b9359eb0e2f86f920037c9cbfba09b24d914c6e1528155f7d/coverage-7.13.5-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:356e76b46783a98c2a2fe81ec79df4883a1e62895ea952968fb253c114e7f930", size = 252125, upload-time = "2026-03-17T10:29:59.388Z" }, - { url = "https://files.pythonhosted.org/packages/44/21/40256eabdcbccdb6acf6b381b3016a154399a75fe39d406f790ae84d1f3c/coverage-7.13.5-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:0cef0cdec915d11254a7f549c1170afecce708d30610c6abdded1f74e581666d", size = 247219, upload-time = "2026-03-17T10:30:01.199Z" }, - { url = "https://files.pythonhosted.org/packages/b1/e8/96e2a6c3f21a0ea77d7830b254a1542d0328acc8d7bdf6a284ba7e529f77/coverage-7.13.5-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:dc022073d063b25a402454e5712ef9e007113e3a676b96c5f29b2bda29352f40", size = 248248, upload-time = "2026-03-17T10:30:03.317Z" }, - { url = "https://files.pythonhosted.org/packages/da/ba/8477f549e554827da390ec659f3c38e4b6d95470f4daafc2d8ff94eaa9c2/coverage-7.13.5-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:9b74db26dfea4f4e50d48a4602207cd1e78be33182bc9cbf22da94f332f99878", size = 246254, upload-time = "2026-03-17T10:30:04.832Z" }, - { url = "https://files.pythonhosted.org/packages/55/59/bc22aef0e6aa179d5b1b001e8b3654785e9adf27ef24c93dc4228ebd5d68/coverage-7.13.5-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:ad146744ca4fd09b50c482650e3c1b1f4dfa1d4792e0a04a369c7f23336f0400", size = 250067, upload-time = "2026-03-17T10:30:06.535Z" }, - { url = "https://files.pythonhosted.org/packages/de/1b/c6a023a160806a5137dca53468fd97530d6acad24a22003b1578a9c2e429/coverage-7.13.5-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:c555b48be1853fe3997c11c4bd521cdd9a9612352de01fa4508f16ec341e6fe0", size = 246521, upload-time = "2026-03-17T10:30:08.486Z" }, - { url = "https://files.pythonhosted.org/packages/2d/3f/3532c85a55aa2f899fa17c186f831cfa1aa434d88ff792a709636f64130e/coverage-7.13.5-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:7034b5c56a58ae5e85f23949d52c14aca2cfc6848a31764995b7de88f13a1ea0", size = 247126, upload-time = "2026-03-17T10:30:09.966Z" }, - { url = "https://files.pythonhosted.org/packages/aa/2e/b9d56af4a24ef45dfbcda88e06870cb7d57b2b0bfa3a888d79b4c8debd76/coverage-7.13.5-cp310-cp310-win32.whl", hash = "sha256:eb7fdf1ef130660e7415e0253a01a7d5a88c9c4d158bcf75cbbd922fd65a5b58", size = 221860, upload-time = "2026-03-17T10:30:11.393Z" }, - { url = "https://files.pythonhosted.org/packages/9f/cc/d938417e7a4d7f0433ad4edee8bb2acdc60dc7ac5af19e2a07a048ecbee3/coverage-7.13.5-cp310-cp310-win_amd64.whl", hash = "sha256:3e1bb5f6c78feeb1be3475789b14a0f0a5b47d505bfc7267126ccbd50289999e", size = 222788, upload-time = "2026-03-17T10:30:12.886Z" }, - { url = "https://files.pythonhosted.org/packages/4b/37/d24c8f8220ff07b839b2c043ea4903a33b0f455abe673ae3c03bbdb7f212/coverage-7.13.5-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:66a80c616f80181f4d643b0f9e709d97bcea413ecd9631e1dedc7401c8e6695d", size = 219381, upload-time = "2026-03-17T10:30:14.68Z" }, - { url = "https://files.pythonhosted.org/packages/35/8b/cd129b0ca4afe886a6ce9d183c44d8301acbd4ef248622e7c49a23145605/coverage-7.13.5-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:145ede53ccbafb297c1c9287f788d1bc3efd6c900da23bf6931b09eafc931587", size = 219880, upload-time = "2026-03-17T10:30:16.231Z" }, - { url = "https://files.pythonhosted.org/packages/55/2f/e0e5b237bffdb5d6c530ce87cc1d413a5b7d7dfd60fb067ad6d254c35c76/coverage-7.13.5-cp311-cp311-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:0672854dc733c342fa3e957e0605256d2bf5934feeac328da9e0b5449634a642", size = 250303, upload-time = "2026-03-17T10:30:17.748Z" }, - { url = "https://files.pythonhosted.org/packages/92/be/b1afb692be85b947f3401375851484496134c5554e67e822c35f28bf2fbc/coverage-7.13.5-cp311-cp311-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:ec10e2a42b41c923c2209b846126c6582db5e43a33157e9870ba9fb70dc7854b", size = 252218, upload-time = "2026-03-17T10:30:19.804Z" }, - { url = "https://files.pythonhosted.org/packages/da/69/2f47bb6fa1b8d1e3e5d0c4be8ccb4313c63d742476a619418f85740d597b/coverage-7.13.5-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:be3d4bbad9d4b037791794ddeedd7d64a56f5933a2c1373e18e9e568b9141686", size = 254326, upload-time = "2026-03-17T10:30:21.321Z" }, - { url = "https://files.pythonhosted.org/packages/d5/d0/79db81da58965bd29dabc8f4ad2a2af70611a57cba9d1ec006f072f30a54/coverage-7.13.5-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:4d2afbc5cc54d286bfb54541aa50b64cdb07a718227168c87b9e2fb8f25e1743", size = 256267, upload-time = "2026-03-17T10:30:23.094Z" }, - { url = "https://files.pythonhosted.org/packages/e5/32/d0d7cc8168f91ddab44c0ce4806b969df5f5fdfdbb568eaca2dbc2a04936/coverage-7.13.5-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:3ad050321264c49c2fa67bb599100456fc51d004b82534f379d16445da40fb75", size = 250430, upload-time = "2026-03-17T10:30:25.311Z" }, - { url = "https://files.pythonhosted.org/packages/4d/06/a055311d891ddbe231cd69fdd20ea4be6e3603ffebddf8704b8ca8e10a3c/coverage-7.13.5-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:7300c8a6d13335b29bb76d7651c66af6bd8658517c43499f110ddc6717bfc209", size = 252017, upload-time = "2026-03-17T10:30:27.284Z" }, - { url = "https://files.pythonhosted.org/packages/d6/f6/d0fd2d21e29a657b5f77a2fe7082e1568158340dceb941954f776dce1b7b/coverage-7.13.5-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:eb07647a5738b89baab047f14edd18ded523de60f3b30e75c2acc826f79c839a", size = 250080, upload-time = "2026-03-17T10:30:29.481Z" }, - { url = "https://files.pythonhosted.org/packages/4e/ab/0d7fb2efc2e9a5eb7ddcc6e722f834a69b454b7e6e5888c3a8567ecffb31/coverage-7.13.5-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:9adb6688e3b53adffefd4a52d72cbd8b02602bfb8f74dcd862337182fd4d1a4e", size = 253843, upload-time = "2026-03-17T10:30:31.301Z" }, - { url = "https://files.pythonhosted.org/packages/ba/6f/7467b917bbf5408610178f62a49c0ed4377bb16c1657f689cc61470da8ce/coverage-7.13.5-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:7c8d4bc913dd70b93488d6c496c77f3aff5ea99a07e36a18f865bca55adef8bd", size = 249802, upload-time = "2026-03-17T10:30:33.358Z" }, - { url = "https://files.pythonhosted.org/packages/75/2c/1172fb689df92135f5bfbbd69fc83017a76d24ea2e2f3a1154007e2fb9f8/coverage-7.13.5-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:0e3c426ffc4cd952f54ee9ffbdd10345709ecc78a3ecfd796a57236bfad0b9b8", size = 250707, upload-time = "2026-03-17T10:30:35.2Z" }, - { url = "https://files.pythonhosted.org/packages/67/21/9ac389377380a07884e3b48ba7a620fcd9dbfaf1d40565facdc6b36ec9ef/coverage-7.13.5-cp311-cp311-win32.whl", hash = "sha256:259b69bb83ad9894c4b25be2528139eecba9a82646ebdda2d9db1ba28424a6bf", size = 221880, upload-time = "2026-03-17T10:30:36.775Z" }, - { url = "https://files.pythonhosted.org/packages/af/7f/4cd8a92531253f9d7c1bbecd9fa1b472907fb54446ca768c59b531248dc5/coverage-7.13.5-cp311-cp311-win_amd64.whl", hash = "sha256:258354455f4e86e3e9d0d17571d522e13b4e1e19bf0f8596bcf9476d61e7d8a9", size = 222816, upload-time = "2026-03-17T10:30:38.891Z" }, - { url = "https://files.pythonhosted.org/packages/12/a6/1d3f6155fb0010ca68eba7fe48ca6c9da7385058b77a95848710ecf189b1/coverage-7.13.5-cp311-cp311-win_arm64.whl", hash = "sha256:bff95879c33ec8da99fc9b6fe345ddb5be6414b41d6d1ad1c8f188d26f36e028", size = 221483, upload-time = "2026-03-17T10:30:40.463Z" }, - { url = "https://files.pythonhosted.org/packages/a0/c3/a396306ba7db865bf96fc1fb3b7fd29bcbf3d829df642e77b13555163cd6/coverage-7.13.5-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:460cf0114c5016fa841214ff5564aa4864f11948da9440bc97e21ad1f4ba1e01", size = 219554, upload-time = "2026-03-17T10:30:42.208Z" }, - { url = "https://files.pythonhosted.org/packages/a6/16/a68a19e5384e93f811dccc51034b1fd0b865841c390e3c931dcc4699e035/coverage-7.13.5-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:0e223ce4b4ed47f065bfb123687686512e37629be25cc63728557ae7db261422", size = 219908, upload-time = "2026-03-17T10:30:43.906Z" }, - { url = "https://files.pythonhosted.org/packages/29/72/20b917c6793af3a5ceb7fb9c50033f3ec7865f2911a1416b34a7cfa0813b/coverage-7.13.5-cp312-cp312-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:6e3370441f4513c6252bf042b9c36d22491142385049243253c7e48398a15a9f", size = 251419, upload-time = "2026-03-17T10:30:45.545Z" }, - { url = "https://files.pythonhosted.org/packages/8c/49/cd14b789536ac6a4778c453c6a2338bc0a2fb60c5a5a41b4008328b9acc1/coverage-7.13.5-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:03ccc709a17a1de074fb1d11f217342fb0d2b1582ed544f554fc9fc3f07e95f5", size = 254159, upload-time = "2026-03-17T10:30:47.204Z" }, - { url = "https://files.pythonhosted.org/packages/9d/00/7b0edcfe64e2ed4c0340dac14a52ad0f4c9bd0b8b5e531af7d55b703db7c/coverage-7.13.5-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3f4818d065964db3c1c66dc0fbdac5ac692ecbc875555e13374fdbe7eedb4376", size = 255270, upload-time = "2026-03-17T10:30:48.812Z" }, - { url = "https://files.pythonhosted.org/packages/93/89/7ffc4ba0f5d0a55c1e84ea7cee39c9fc06af7b170513d83fbf3bbefce280/coverage-7.13.5-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:012d5319e66e9d5a218834642d6c35d265515a62f01157a45bcc036ecf947256", size = 257538, upload-time = "2026-03-17T10:30:50.77Z" }, - { url = "https://files.pythonhosted.org/packages/81/bd/73ddf85f93f7e6fa83e77ccecb6162d9415c79007b4bc124008a4995e4a7/coverage-7.13.5-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:8dd02af98971bdb956363e4827d34425cb3df19ee550ef92855b0acb9c7ce51c", size = 251821, upload-time = "2026-03-17T10:30:52.5Z" }, - { url = "https://files.pythonhosted.org/packages/a0/81/278aff4e8dec4926a0bcb9486320752811f543a3ce5b602cc7a29978d073/coverage-7.13.5-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:f08fd75c50a760c7eb068ae823777268daaf16a80b918fa58eea888f8e3919f5", size = 253191, upload-time = "2026-03-17T10:30:54.543Z" }, - { url = "https://files.pythonhosted.org/packages/70/ee/fe1621488e2e0a58d7e94c4800f0d96f79671553488d401a612bebae324b/coverage-7.13.5-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:843ea8643cf967d1ac7e8ecd4bb00c99135adf4816c0c0593fdcc47b597fcf09", size = 251337, upload-time = "2026-03-17T10:30:56.663Z" }, - { url = "https://files.pythonhosted.org/packages/37/a6/f79fb37aa104b562207cc23cb5711ab6793608e246cae1e93f26b2236ed9/coverage-7.13.5-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:9d44d7aa963820b1b971dbecd90bfe5fe8f81cff79787eb6cca15750bd2f79b9", size = 255404, upload-time = "2026-03-17T10:30:58.427Z" }, - { url = "https://files.pythonhosted.org/packages/75/f0/ed15262a58ec81ce457ceb717b7f78752a1713556b19081b76e90896e8d4/coverage-7.13.5-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:7132bed4bd7b836200c591410ae7d97bf7ae8be6fc87d160b2bd881df929e7bf", size = 250903, upload-time = "2026-03-17T10:31:00.093Z" }, - { url = "https://files.pythonhosted.org/packages/0f/e9/9129958f20e7e9d4d56d51d42ccf708d15cac355ff4ac6e736e97a9393d2/coverage-7.13.5-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:a698e363641b98843c517817db75373c83254781426e94ada3197cabbc2c919c", size = 252780, upload-time = "2026-03-17T10:31:01.916Z" }, - { url = "https://files.pythonhosted.org/packages/a4/d7/0ad9b15812d81272db94379fe4c6df8fd17781cc7671fdfa30c76ba5ff7b/coverage-7.13.5-cp312-cp312-win32.whl", hash = "sha256:bdba0a6b8812e8c7df002d908a9a2ea3c36e92611b5708633c50869e6d922fdf", size = 222093, upload-time = "2026-03-17T10:31:03.642Z" }, - { url = "https://files.pythonhosted.org/packages/29/3d/821a9a5799fac2556bcf0bd37a70d1d11fa9e49784b6d22e92e8b2f85f18/coverage-7.13.5-cp312-cp312-win_amd64.whl", hash = "sha256:d2c87e0c473a10bffe991502eac389220533024c8082ec1ce849f4218dded810", size = 222900, upload-time = "2026-03-17T10:31:05.651Z" }, - { url = "https://files.pythonhosted.org/packages/d4/fa/2238c2ad08e35cf4f020ea721f717e09ec3152aea75d191a7faf3ef009a8/coverage-7.13.5-cp312-cp312-win_arm64.whl", hash = "sha256:bf69236a9a81bdca3bff53796237aab096cdbf8d78a66ad61e992d9dac7eb2de", size = 221515, upload-time = "2026-03-17T10:31:07.293Z" }, - { url = "https://files.pythonhosted.org/packages/74/8c/74fedc9663dcf168b0a059d4ea756ecae4da77a489048f94b5f512a8d0b3/coverage-7.13.5-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:5ec4af212df513e399cf11610cc27063f1586419e814755ab362e50a85ea69c1", size = 219576, upload-time = "2026-03-17T10:31:09.045Z" }, - { url = "https://files.pythonhosted.org/packages/0c/c9/44fb661c55062f0818a6ffd2685c67aa30816200d5f2817543717d4b92eb/coverage-7.13.5-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:941617e518602e2d64942c88ec8499f7fbd49d3f6c4327d3a71d43a1973032f3", size = 219942, upload-time = "2026-03-17T10:31:10.708Z" }, - { url = "https://files.pythonhosted.org/packages/5f/13/93419671cee82b780bab7ea96b67c8ef448f5f295f36bf5031154ec9a790/coverage-7.13.5-cp313-cp313-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:da305e9937617ee95c2e39d8ff9f040e0487cbf1ac174f777ed5eddd7a7c1f26", size = 250935, upload-time = "2026-03-17T10:31:12.392Z" }, - { url = "https://files.pythonhosted.org/packages/ac/68/1666e3a4462f8202d836920114fa7a5ee9275d1fa45366d336c551a162dd/coverage-7.13.5-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:78e696e1cc714e57e8b25760b33a8b1026b7048d270140d25dafe1b0a1ee05a3", size = 253541, upload-time = "2026-03-17T10:31:14.247Z" }, - { url = "https://files.pythonhosted.org/packages/4e/5e/3ee3b835647be646dcf3c65a7c6c18f87c27326a858f72ab22c12730773d/coverage-7.13.5-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:02ca0eed225b2ff301c474aeeeae27d26e2537942aa0f87491d3e147e784a82b", size = 254780, upload-time = "2026-03-17T10:31:16.193Z" }, - { url = "https://files.pythonhosted.org/packages/44/b3/cb5bd1a04cfcc49ede6cd8409d80bee17661167686741e041abc7ee1b9a9/coverage-7.13.5-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:04690832cbea4e4663d9149e05dba142546ca05cb1848816760e7f58285c970a", size = 256912, upload-time = "2026-03-17T10:31:17.89Z" }, - { url = "https://files.pythonhosted.org/packages/1b/66/c1dceb7b9714473800b075f5c8a84f4588f887a90eb8645282031676e242/coverage-7.13.5-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:0590e44dd2745c696a778f7bab6aa95256de2cbc8b8cff4f7db8ff09813d6969", size = 251165, upload-time = "2026-03-17T10:31:19.605Z" }, - { url = "https://files.pythonhosted.org/packages/b7/62/5502b73b97aa2e53ea22a39cf8649ff44827bef76d90bf638777daa27a9d/coverage-7.13.5-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:d7cfad2d6d81dd298ab6b89fe72c3b7b05ec7544bdda3b707ddaecff8d25c161", size = 252908, upload-time = "2026-03-17T10:31:21.312Z" }, - { url = "https://files.pythonhosted.org/packages/7d/37/7792c2d69854397ca77a55c4646e5897c467928b0e27f2d235d83b5d08c6/coverage-7.13.5-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:e092b9499de38ae0fbfbc603a74660eb6ff3e869e507b50d85a13b6db9863e15", size = 250873, upload-time = "2026-03-17T10:31:23.565Z" }, - { url = "https://files.pythonhosted.org/packages/a3/23/bc866fb6163be52a8a9e5d708ba0d3b1283c12158cefca0a8bbb6e247a43/coverage-7.13.5-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:48c39bc4a04d983a54a705a6389512883d4a3b9862991b3617d547940e9f52b1", size = 255030, upload-time = "2026-03-17T10:31:25.58Z" }, - { url = "https://files.pythonhosted.org/packages/7d/8b/ef67e1c222ef49860701d346b8bbb70881bef283bd5f6cbba68a39a086c7/coverage-7.13.5-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:2d3807015f138ffea1ed9afeeb8624fd781703f2858b62a8dd8da5a0994c57b6", size = 250694, upload-time = "2026-03-17T10:31:27.316Z" }, - { url = "https://files.pythonhosted.org/packages/46/0d/866d1f74f0acddbb906db212e096dee77a8e2158ca5e6bb44729f9d93298/coverage-7.13.5-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:ee2aa19e03161671ec964004fb74b2257805d9710bf14a5c704558b9d8dbaf17", size = 252469, upload-time = "2026-03-17T10:31:29.472Z" }, - { url = "https://files.pythonhosted.org/packages/7a/f5/be742fec31118f02ce42b21c6af187ad6a344fed546b56ca60caacc6a9a0/coverage-7.13.5-cp313-cp313-win32.whl", hash = "sha256:ce1998c0483007608c8382f4ff50164bfc5bd07a2246dd272aa4043b75e61e85", size = 222112, upload-time = "2026-03-17T10:31:31.526Z" }, - { url = "https://files.pythonhosted.org/packages/66/40/7732d648ab9d069a46e686043241f01206348e2bbf128daea85be4d6414b/coverage-7.13.5-cp313-cp313-win_amd64.whl", hash = "sha256:631efb83f01569670a5e866ceb80fe483e7c159fac6f167e6571522636104a0b", size = 222923, upload-time = "2026-03-17T10:31:33.633Z" }, - { url = "https://files.pythonhosted.org/packages/48/af/fea819c12a095781f6ccd504890aaddaf88b8fab263c4940e82c7b770124/coverage-7.13.5-cp313-cp313-win_arm64.whl", hash = "sha256:f4cd16206ad171cbc2470dbea9103cf9a7607d5fe8c242fdf1edf36174020664", size = 221540, upload-time = "2026-03-17T10:31:35.445Z" }, - { url = "https://files.pythonhosted.org/packages/23/d2/17879af479df7fbbd44bd528a31692a48f6b25055d16482fdf5cdb633805/coverage-7.13.5-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:0428cbef5783ad91fe240f673cc1f76b25e74bbfe1a13115e4aa30d3f538162d", size = 220262, upload-time = "2026-03-17T10:31:37.184Z" }, - { url = "https://files.pythonhosted.org/packages/5b/4c/d20e554f988c8f91d6a02c5118f9abbbf73a8768a3048cb4962230d5743f/coverage-7.13.5-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:e0b216a19534b2427cc201a26c25da4a48633f29a487c61258643e89d28200c0", size = 220617, upload-time = "2026-03-17T10:31:39.245Z" }, - { url = "https://files.pythonhosted.org/packages/29/9c/f9f5277b95184f764b24e7231e166dfdb5780a46d408a2ac665969416d61/coverage-7.13.5-cp313-cp313t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:972a9cd27894afe4bc2b1480107054e062df08e671df7c2f18c205e805ccd806", size = 261912, upload-time = "2026-03-17T10:31:41.324Z" }, - { url = "https://files.pythonhosted.org/packages/d5/f6/7f1ab39393eeb50cfe4747ae8ef0e4fc564b989225aa1152e13a180d74f8/coverage-7.13.5-cp313-cp313t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:4b59148601efcd2bac8c4dbf1f0ad6391693ccf7a74b8205781751637076aee3", size = 263987, upload-time = "2026-03-17T10:31:43.724Z" }, - { url = "https://files.pythonhosted.org/packages/a0/d7/62c084fb489ed9c6fbdf57e006752e7c516ea46fd690e5ed8b8617c7d52e/coverage-7.13.5-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:505d7083c8b0c87a8fa8c07370c285847c1f77739b22e299ad75a6af6c32c5c9", size = 266416, upload-time = "2026-03-17T10:31:45.769Z" }, - { url = "https://files.pythonhosted.org/packages/a9/f6/df63d8660e1a0bff6125947afda112a0502736f470d62ca68b288ea762d8/coverage-7.13.5-cp313-cp313t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:60365289c3741e4db327e7baff2a4aaacf22f788e80fa4683393891b70a89fbd", size = 267558, upload-time = "2026-03-17T10:31:48.293Z" }, - { url = "https://files.pythonhosted.org/packages/5b/02/353ca81d36779bd108f6d384425f7139ac3c58c750dcfaafe5d0bee6436b/coverage-7.13.5-cp313-cp313t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:1b88c69c8ef5d4b6fe7dea66d6636056a0f6a7527c440e890cf9259011f5e606", size = 261163, upload-time = "2026-03-17T10:31:50.125Z" }, - { url = "https://files.pythonhosted.org/packages/2c/16/2e79106d5749bcaf3aee6d309123548e3276517cd7851faa8da213bc61bf/coverage-7.13.5-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:5b13955d31d1633cf9376908089b7cebe7d15ddad7aeaabcbe969a595a97e95e", size = 263981, upload-time = "2026-03-17T10:31:51.961Z" }, - { url = "https://files.pythonhosted.org/packages/29/c7/c29e0c59ffa6942030ae6f50b88ae49988e7e8da06de7ecdbf49c6d4feae/coverage-7.13.5-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:f70c9ab2595c56f81a89620e22899eea8b212a4041bd728ac6f4a28bf5d3ddd0", size = 261604, upload-time = "2026-03-17T10:31:53.872Z" }, - { url = "https://files.pythonhosted.org/packages/40/48/097cdc3db342f34006a308ab41c3a7c11c3f0d84750d340f45d88a782e00/coverage-7.13.5-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:084b84a8c63e8d6fc7e3931b316a9bcafca1458d753c539db82d31ed20091a87", size = 265321, upload-time = "2026-03-17T10:31:55.997Z" }, - { url = "https://files.pythonhosted.org/packages/bb/1f/4994af354689e14fd03a75f8ec85a9a68d94e0188bbdab3fc1516b55e512/coverage-7.13.5-cp313-cp313t-musllinux_1_2_riscv64.whl", hash = "sha256:ad14385487393e386e2ea988b09d62dd42c397662ac2dabc3832d71253eee479", size = 260502, upload-time = "2026-03-17T10:31:58.308Z" }, - { url = "https://files.pythonhosted.org/packages/22/c6/9bb9ef55903e628033560885f5c31aa227e46878118b63ab15dc7ba87797/coverage-7.13.5-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:7f2c47b36fe7709a6e83bfadf4eefb90bd25fbe4014d715224c4316f808e59a2", size = 262688, upload-time = "2026-03-17T10:32:00.141Z" }, - { url = "https://files.pythonhosted.org/packages/14/4f/f5df9007e50b15e53e01edea486814783a7f019893733d9e4d6caad75557/coverage-7.13.5-cp313-cp313t-win32.whl", hash = "sha256:67e9bc5449801fad0e5dff329499fb090ba4c5800b86805c80617b4e29809b2a", size = 222788, upload-time = "2026-03-17T10:32:02.246Z" }, - { url = "https://files.pythonhosted.org/packages/e1/98/aa7fccaa97d0f3192bec013c4e6fd6d294a6ed44b640e6bb61f479e00ed5/coverage-7.13.5-cp313-cp313t-win_amd64.whl", hash = "sha256:da86cdcf10d2519e10cabb8ac2de03da1bcb6e4853790b7fbd48523332e3a819", size = 223851, upload-time = "2026-03-17T10:32:04.416Z" }, - { url = "https://files.pythonhosted.org/packages/3d/8b/e5c469f7352651e5f013198e9e21f97510b23de957dd06a84071683b4b60/coverage-7.13.5-cp313-cp313t-win_arm64.whl", hash = "sha256:0ecf12ecb326fe2c339d93fc131816f3a7367d223db37817208905c89bded911", size = 222104, upload-time = "2026-03-17T10:32:06.65Z" }, - { url = "https://files.pythonhosted.org/packages/8e/77/39703f0d1d4b478bfd30191d3c14f53caf596fac00efb3f8f6ee23646439/coverage-7.13.5-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:fbabfaceaeb587e16f7008f7795cd80d20ec548dc7f94fbb0d4ec2e038ce563f", size = 219621, upload-time = "2026-03-17T10:32:08.589Z" }, - { url = "https://files.pythonhosted.org/packages/e2/3e/51dff36d99ae14639a133d9b164d63e628532e2974d8b1edb99dd1ebc733/coverage-7.13.5-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:9bb2a28101a443669a423b665939381084412b81c3f8c0fcfbac57f4e30b5b8e", size = 219953, upload-time = "2026-03-17T10:32:10.507Z" }, - { url = "https://files.pythonhosted.org/packages/6a/6c/1f1917b01eb647c2f2adc9962bd66c79eb978951cab61bdc1acab3290c07/coverage-7.13.5-cp314-cp314-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:bd3a2fbc1c6cccb3c5106140d87cc6a8715110373ef42b63cf5aea29df8c217a", size = 250992, upload-time = "2026-03-17T10:32:12.41Z" }, - { url = "https://files.pythonhosted.org/packages/22/e5/06b1f88f42a5a99df42ce61208bdec3bddb3d261412874280a19796fc09c/coverage-7.13.5-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:6c36ddb64ed9d7e496028d1d00dfec3e428e0aabf4006583bb1839958d280510", size = 253503, upload-time = "2026-03-17T10:32:14.449Z" }, - { url = "https://files.pythonhosted.org/packages/80/28/2a148a51e5907e504fa7b85490277734e6771d8844ebcc48764a15e28155/coverage-7.13.5-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:380e8e9084d8eb38db3a9176a1a4f3c0082c3806fa0dc882d1d87abc3c789247", size = 254852, upload-time = "2026-03-17T10:32:16.56Z" }, - { url = "https://files.pythonhosted.org/packages/61/77/50e8d3d85cc0b7ebe09f30f151d670e302c7ff4a1bf6243f71dd8b0981fa/coverage-7.13.5-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:e808af52a0513762df4d945ea164a24b37f2f518cbe97e03deaa0ee66139b4d6", size = 257161, upload-time = "2026-03-17T10:32:19.004Z" }, - { url = "https://files.pythonhosted.org/packages/3b/c4/b5fd1d4b7bf8d0e75d997afd3925c59ba629fc8616f1b3aae7605132e256/coverage-7.13.5-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:e301d30dd7e95ae068671d746ba8c34e945a82682e62918e41b2679acd2051a0", size = 251021, upload-time = "2026-03-17T10:32:21.344Z" }, - { url = "https://files.pythonhosted.org/packages/f8/66/6ea21f910e92d69ef0b1c3346ea5922a51bad4446c9126db2ae96ee24c4c/coverage-7.13.5-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:800bc829053c80d240a687ceeb927a94fd108bbdc68dfbe505d0d75ab578a882", size = 252858, upload-time = "2026-03-17T10:32:23.506Z" }, - { url = "https://files.pythonhosted.org/packages/9e/ea/879c83cb5d61aa2a35fb80e72715e92672daef8191b84911a643f533840c/coverage-7.13.5-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:0b67af5492adb31940ee418a5a655c28e48165da5afab8c7fa6fd72a142f8740", size = 250823, upload-time = "2026-03-17T10:32:25.516Z" }, - { url = "https://files.pythonhosted.org/packages/8a/fb/616d95d3adb88b9803b275580bdeee8bd1b69a886d057652521f83d7322f/coverage-7.13.5-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:c9136ff29c3a91e25b1d1552b5308e53a1e0653a23e53b6366d7c2dcbbaf8a16", size = 255099, upload-time = "2026-03-17T10:32:27.944Z" }, - { url = "https://files.pythonhosted.org/packages/1c/93/25e6917c90ec1c9a56b0b26f6cad6408e5f13bb6b35d484a0d75c9cf000d/coverage-7.13.5-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:cff784eef7f0b8f6cb28804fbddcfa99f89efe4cc35fb5627e3ac58f91ed3ac0", size = 250638, upload-time = "2026-03-17T10:32:29.914Z" }, - { url = "https://files.pythonhosted.org/packages/fc/7b/dc1776b0464145a929deed214aef9fb1493f159b59ff3c7eeeedf91eddd0/coverage-7.13.5-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:68a4953be99b17ac3c23b6efbc8a38330d99680c9458927491d18700ef23ded0", size = 252295, upload-time = "2026-03-17T10:32:31.981Z" }, - { url = "https://files.pythonhosted.org/packages/ea/fb/99cbbc56a26e07762a2740713f3c8f9f3f3106e3a3dd8cc4474954bccd34/coverage-7.13.5-cp314-cp314-win32.whl", hash = "sha256:35a31f2b1578185fbe6aa2e74cea1b1d0bbf4c552774247d9160d29b80ed56cc", size = 222360, upload-time = "2026-03-17T10:32:34.233Z" }, - { url = "https://files.pythonhosted.org/packages/8d/b7/4758d4f73fb536347cc5e4ad63662f9d60ba9118cb6785e9616b2ce5d7fa/coverage-7.13.5-cp314-cp314-win_amd64.whl", hash = "sha256:2aa055ae1857258f9e0045be26a6d62bdb47a72448b62d7b55f4820f361a2633", size = 223174, upload-time = "2026-03-17T10:32:36.369Z" }, - { url = "https://files.pythonhosted.org/packages/2c/f2/24d84e1dfe70f8ac9fdf30d338239860d0d1d5da0bda528959d0ebc9da28/coverage-7.13.5-cp314-cp314-win_arm64.whl", hash = "sha256:1b11eef33edeae9d142f9b4358edb76273b3bfd30bc3df9a4f95d0e49caf94e8", size = 221739, upload-time = "2026-03-17T10:32:38.736Z" }, - { url = "https://files.pythonhosted.org/packages/60/5b/4a168591057b3668c2428bff25dd3ebc21b629d666d90bcdfa0217940e84/coverage-7.13.5-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:10a0c37f0b646eaff7cce1874c31d1f1ccb297688d4c747291f4f4c70741cc8b", size = 220351, upload-time = "2026-03-17T10:32:41.196Z" }, - { url = "https://files.pythonhosted.org/packages/f5/21/1fd5c4dbfe4a58b6b99649125635df46decdfd4a784c3cd6d410d303e370/coverage-7.13.5-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:b5db73ba3c41c7008037fa731ad5459fc3944cb7452fc0aa9f822ad3533c583c", size = 220612, upload-time = "2026-03-17T10:32:43.204Z" }, - { url = "https://files.pythonhosted.org/packages/d6/fe/2a924b3055a5e7e4512655a9d4609781b0d62334fa0140c3e742926834e2/coverage-7.13.5-cp314-cp314t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:750db93a81e3e5a9831b534be7b1229df848b2e125a604fe6651e48aa070e5f9", size = 261985, upload-time = "2026-03-17T10:32:45.514Z" }, - { url = "https://files.pythonhosted.org/packages/d7/0d/c8928f2bd518c45990fe1a2ab8db42e914ef9b726c975facc4282578c3eb/coverage-7.13.5-cp314-cp314t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:9ddb4f4a5479f2539644be484da179b653273bca1a323947d48ab107b3ed1f29", size = 264107, upload-time = "2026-03-17T10:32:47.971Z" }, - { url = "https://files.pythonhosted.org/packages/ef/ae/4ae35bbd9a0af9d820362751f0766582833c211224b38665c0f8de3d487f/coverage-7.13.5-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d8a7a2049c14f413163e2bdabd37e41179b1d1ccb10ffc6ccc4b7a718429c607", size = 266513, upload-time = "2026-03-17T10:32:50.1Z" }, - { url = "https://files.pythonhosted.org/packages/9c/20/d326174c55af36f74eac6ae781612d9492f060ce8244b570bb9d50d9d609/coverage-7.13.5-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:e1c85e0b6c05c592ea6d8768a66a254bfb3874b53774b12d4c89c481eb78cb90", size = 267650, upload-time = "2026-03-17T10:32:52.391Z" }, - { url = "https://files.pythonhosted.org/packages/7a/5e/31484d62cbd0eabd3412e30d74386ece4a0837d4f6c3040a653878bfc019/coverage-7.13.5-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:777c4d1eff1b67876139d24288aaf1817f6c03d6bae9c5cc8d27b83bcfe38fe3", size = 261089, upload-time = "2026-03-17T10:32:54.544Z" }, - { url = "https://files.pythonhosted.org/packages/e9/d8/49a72d6de146eebb0b7e48cc0f4bc2c0dd858e3d4790ab2b39a2872b62bd/coverage-7.13.5-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:6697e29b93707167687543480a40f0db8f356e86d9f67ddf2e37e2dfd91a9dab", size = 263982, upload-time = "2026-03-17T10:32:56.803Z" }, - { url = "https://files.pythonhosted.org/packages/06/3b/0351f1bd566e6e4dd39e978efe7958bde1d32f879e85589de147654f57bb/coverage-7.13.5-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:8fdf453a942c3e4d99bd80088141c4c6960bb232c409d9c3558e2dbaa3998562", size = 261579, upload-time = "2026-03-17T10:32:59.466Z" }, - { url = "https://files.pythonhosted.org/packages/5d/ce/796a2a2f4017f554d7810f5c573449b35b1e46788424a548d4d19201b222/coverage-7.13.5-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:32ca0c0114c9834a43f045a87dcebd69d108d8ffb666957ea65aa132f50332e2", size = 265316, upload-time = "2026-03-17T10:33:01.847Z" }, - { url = "https://files.pythonhosted.org/packages/3d/16/d5ae91455541d1a78bc90abf495be600588aff8f6db5c8b0dae739fa39c9/coverage-7.13.5-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:8769751c10f339021e2638cd354e13adeac54004d1941119b2c96fe5276d45ea", size = 260427, upload-time = "2026-03-17T10:33:03.945Z" }, - { url = "https://files.pythonhosted.org/packages/48/11/07f413dba62db21fb3fad5d0de013a50e073cc4e2dc4306e770360f6dfc8/coverage-7.13.5-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:cec2d83125531bd153175354055cdb7a09987af08a9430bd173c937c6d0fba2a", size = 262745, upload-time = "2026-03-17T10:33:06.285Z" }, - { url = "https://files.pythonhosted.org/packages/91/15/d792371332eb4663115becf4bad47e047d16234b1aff687b1b18c58d60ae/coverage-7.13.5-cp314-cp314t-win32.whl", hash = "sha256:0cd9ed7a8b181775459296e402ca4fb27db1279740a24e93b3b41942ebe4b215", size = 223146, upload-time = "2026-03-17T10:33:08.756Z" }, - { url = "https://files.pythonhosted.org/packages/db/51/37221f59a111dca5e85be7dbf09696323b5b9f13ff65e0641d535ed06ea8/coverage-7.13.5-cp314-cp314t-win_amd64.whl", hash = "sha256:301e3b7dfefecaca37c9f1aa6f0049b7d4ab8dd933742b607765d757aca77d43", size = 224254, upload-time = "2026-03-17T10:33:11.174Z" }, - { url = "https://files.pythonhosted.org/packages/54/83/6acacc889de8987441aa7d5adfbdbf33d288dad28704a67e574f1df9bcbb/coverage-7.13.5-cp314-cp314t-win_arm64.whl", hash = "sha256:9dacc2ad679b292709e0f5fc1ac74a6d4d5562e424058962c7bb0c658ad25e45", size = 222276, upload-time = "2026-03-17T10:33:13.466Z" }, - { url = "https://files.pythonhosted.org/packages/9e/ee/a4cf96b8ce1e566ed238f0659ac2d3f007ed1d14b181bcb684e19561a69a/coverage-7.13.5-py3-none-any.whl", hash = "sha256:34b02417cf070e173989b3db962f7ed56d2f644307b2cf9d5a0f258e13084a61", size = 211346, upload-time = "2026-03-17T10:33:15.691Z" }, +version = "7.14.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/54/fd/0ab2772530e946e1be1abd0bc09e647ec9b02e88f0867857601fefca8953/coverage-7.14.1.tar.gz", hash = "sha256:30c08f7d90415aa98b3c990385dea2939b0da55f38515e5b369b83655f8523be", size = 920132, upload-time = "2026-05-26T20:41:36.783Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/92/69/0d2ef01ff4b8fcecd4cba920d11e92fa4f96ae412441d3b56a90a258e69b/coverage-7.14.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:3e3680291c4a1d0dadfa84a2c459576a4af5133abb617905714339a0c73138cf", size = 219722, upload-time = "2026-05-26T20:38:14.002Z" }, + { url = "https://files.pythonhosted.org/packages/f8/ae/9afdeaa31b9d9ce98124b6abf8bb49119bf71aecae04f8567c189d91299f/coverage-7.14.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:a5274669f37f2343635a347b91a60777621341ab3378e9c6ac9335eee704bddf", size = 220240, upload-time = "2026-05-26T20:38:17.424Z" }, + { url = "https://files.pythonhosted.org/packages/51/69/c998589871df7ea7dba865cc5ee32b5a3e1d47ba6c68ef91104c7c46fa5e/coverage-7.14.1-cp310-cp310-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:cfe5a5fec635799ef33428f1e5e61bafa45a92a96190ba731561ba558ccc214d", size = 246981, upload-time = "2026-05-26T20:38:19.266Z" }, + { url = "https://files.pythonhosted.org/packages/fc/10/1c7d04c13040dac531d21b712bbe08f902e6dd9b58f5d77875c4d030f8f2/coverage-7.14.1-cp310-cp310-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:62a9f70b52e0b5a95cfef4a5c5641b06983cadc5e538a3feeb5c00211f523ac2", size = 248812, upload-time = "2026-05-26T20:38:20.75Z" }, + { url = "https://files.pythonhosted.org/packages/c1/65/2a38a4607ef27cadcfbcee034dba5830ae2569f90144a0f4c7dbf47d30b0/coverage-7.14.1-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3c18ebc343e15be53049b3a2dce38fe82d58f37e20ab9094b3a39c0aa4f6bb47", size = 250675, upload-time = "2026-05-26T20:38:22.159Z" }, + { url = "https://files.pythonhosted.org/packages/c9/a2/a446ed9752a4a59b79e0fb6cbb319f6facb2183045c0725462625e66f87e/coverage-7.14.1-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:b84ffdf877644e7096aa936991efeed873f7f3df57b9cd001312b7668ab08550", size = 252590, upload-time = "2026-05-26T20:38:23.63Z" }, + { url = "https://files.pythonhosted.org/packages/9e/fd/e81fbd7ba752365546e9842b1cbdaad3d6919d2a522c590aef16a281ec5e/coverage-7.14.1-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:e854312c4103f2ad4c0dc023b69b77ebfd2c89db5f86c4c94dc2353f9a92167e", size = 247691, upload-time = "2026-05-26T20:38:25.057Z" }, + { url = "https://files.pythonhosted.org/packages/53/35/f3c26fdaae9ea937d154ca4d372e5ea0a4167ff70d36c6074ac2eacb2f83/coverage-7.14.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:c643734307300234fafa36bf2a040a7235f8f177ea1fd6ec1423aea6fb7b929f", size = 248716, upload-time = "2026-05-26T20:38:26.406Z" }, + { url = "https://files.pythonhosted.org/packages/2e/14/940b6c49551fd343e8507ee2b0ba7af5d0aa04ed5bf768285cb7c72a9884/coverage-7.14.1-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:84ac9499e48700399a5dd0ea7085b5091961fec52c68d66b4ec0d3cf7f4441b1", size = 246721, upload-time = "2026-05-26T20:38:28.282Z" }, + { url = "https://files.pythonhosted.org/packages/aa/2c/40fc0634186c28292a662dff578866b3913983d6c375a3c2a74020938719/coverage-7.14.1-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:7f02d09f70776579b926d889a4c9c235070a1f47c40458aeaca563fae5acfdb5", size = 250533, upload-time = "2026-05-26T20:38:29.753Z" }, + { url = "https://files.pythonhosted.org/packages/de/e3/2c26bf1e811f9df991ff2a9bdddebdd13ee0665d564df7d05979f9146297/coverage-7.14.1-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:ce66d8e46da2bb5ee313a745cbd2e391d319176c1f7a9451bfcd3a2fb920859b", size = 246990, upload-time = "2026-05-26T20:38:31.516Z" }, + { url = "https://files.pythonhosted.org/packages/a8/b0/060260ef56bd92363ebdce0c7095ce422b06e69aae71828efeca473ab1ca/coverage-7.14.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:c912c259304cfb5ee584481cfb7ce1ff932b4d61e6c9140b8f19cb7b5ed82332", size = 247593, upload-time = "2026-05-26T20:38:33.065Z" }, + { url = "https://files.pythonhosted.org/packages/63/f3/501502046efeb0d6d94b5ca54941d95f1184183dd6bdb7f283985783bb4a/coverage-7.14.1-cp310-cp310-win32.whl", hash = "sha256:1238cb94638e610e972c60dac68e813f868dc7d6e982535270558443058d9d59", size = 222330, upload-time = "2026-05-26T20:38:35.36Z" }, + { url = "https://files.pythonhosted.org/packages/a0/5d/1bf99f2c558f128faf7906817ccbdb576ba815d3b41ce2ac1719b70a3663/coverage-7.14.1-cp310-cp310-win_amd64.whl", hash = "sha256:fc459e5d73be2d6332fcfe8dbf3d8994671fe33c700f4565988ecfa511547253", size = 223261, upload-time = "2026-05-26T20:38:37.196Z" }, + { url = "https://files.pythonhosted.org/packages/7d/d7/477ad149490e6cb849f28abea1dabb9c823cea72e7500c81b4240ce619c0/coverage-7.14.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:478b5bcd63c2e1357c5c7e16c070690df7b07f676b1c114d7b93e533c664309f", size = 219848, upload-time = "2026-05-26T20:38:38.715Z" }, + { url = "https://files.pythonhosted.org/packages/91/82/a5eb47257c50601bb7b9a9d2857c67b7a3a85ad74180eb2c98bb1fbe0ce5/coverage-7.14.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:a24a81f9715ee42ef59a316cc11611c98fe23920f7c81861315c9f3ff4a230f4", size = 220354, upload-time = "2026-05-26T20:38:40.232Z" }, + { url = "https://files.pythonhosted.org/packages/43/8b/78419b5391a5cb706b6544390507e469d83ffc9a8248b02c4011aceb9365/coverage-7.14.1-cp311-cp311-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:196a13319ad88d6d8ef5ab489ec4f44ddde2143c0c7d5b27786f6c3ffd56a7e1", size = 250771, upload-time = "2026-05-26T20:38:41.782Z" }, + { url = "https://files.pythonhosted.org/packages/77/63/e77aaacd491182210d639636b7a8bba23ffffa9b82aa3762da9431855fa9/coverage-7.14.1-cp311-cp311-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:3d452fd08b5c72c5167c93e6867b5c08500bd40f2a21e1e854a500550b6cc36f", size = 252683, upload-time = "2026-05-26T20:38:43.305Z" }, + { url = "https://files.pythonhosted.org/packages/65/1c/a022e3cfbec2ac241640003cb3a817e161d9c7f5aa9b49173756cdc03204/coverage-7.14.1-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:23bf7fa51ac02e07fc7c96849b82946da47ae862dc8f86d183b2a4864fc38129", size = 254791, upload-time = "2026-05-26T20:38:45.361Z" }, + { url = "https://files.pythonhosted.org/packages/61/d6/967e408aca4c1ceb88cb0cc677169110ae7f5995fb5eaf5fb1f5a1bb8f5d/coverage-7.14.1-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:bcaa50684dcaadfa599ac48f81103c756d791cfd85c97203d2217c593d48b860", size = 256748, upload-time = "2026-05-26T20:38:46.91Z" }, + { url = "https://files.pythonhosted.org/packages/b8/be/869188f7fe28638078ec479331ace6dc5f7b40b7153eb616f47ab79404d8/coverage-7.14.1-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:4ea1c034f95c9b056e856b794630b17f9fa3d57e4800ff1e503d3be0f9c9078c", size = 250907, upload-time = "2026-05-26T20:38:48.493Z" }, + { url = "https://files.pythonhosted.org/packages/07/aa/adb7d3b4278d690e68703abcd76ab1b948242e3668d921711551b78f9ddb/coverage-7.14.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:c7e057326434e441306226fbeb5d1aaf14a2637efe97ba668306635835f32ad7", size = 252483, upload-time = "2026-05-26T20:38:50.074Z" }, + { url = "https://files.pythonhosted.org/packages/43/61/331c74103c62dcb0c4b9b3a0de9a61aca016208b0a90f109592a9f9ecc28/coverage-7.14.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:59baf88468dbc8d63b1887afd92bda52e40bb1561696e5819670601403810cec", size = 250545, upload-time = "2026-05-26T20:38:51.613Z" }, + { url = "https://files.pythonhosted.org/packages/f6/b6/c5dae3c104d89be04828f61810e6b3473825482e4c288cc4ed04553e08ae/coverage-7.14.1-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:d34d75f892b3ab73ba11cab5442cce7b3e168fd64162b16f0e1e0d09c508edef", size = 254310, upload-time = "2026-05-26T20:38:53.503Z" }, + { url = "https://files.pythonhosted.org/packages/ad/a1/2b9d5863e3b83c01ad8199e3c597802fbb3a9dc90b058885804c20296d31/coverage-7.14.1-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:3a56abc20a472baf0304c455721bc601477440d28ecfde8a03dde79ede07e0df", size = 250266, upload-time = "2026-05-26T20:38:55.414Z" }, + { url = "https://files.pythonhosted.org/packages/7f/5e/0e511fbdb269359be26fe678a1c3fa1f2aa2a01573cc3f54268c8d6d4797/coverage-7.14.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:6a3cb83d1552c0cd1b4906655b6a33fd4a8473229633a901c6b73bf86914dee9", size = 251174, upload-time = "2026-05-26T20:38:57.141Z" }, + { url = "https://files.pythonhosted.org/packages/85/10/e55307b622b3dd9671cb321824502dc10f93e72f2802b9946159a8edadeb/coverage-7.14.1-cp311-cp311-win32.whl", hash = "sha256:10274a1fbeb8ec5d72966e17bb198a3104257aca4ac09d98667c5f8aca8c8548", size = 222354, upload-time = "2026-05-26T20:38:58.727Z" }, + { url = "https://files.pythonhosted.org/packages/71/cf/107421693cfb71e4f1ca5bf70443f64d4161878068d07a3e51c7ad21d17b/coverage-7.14.1-cp311-cp311-win_amd64.whl", hash = "sha256:87ebdf787d4888e3f3f2d523eadc6e18c6d18c6d0eb173801a189641627fb37e", size = 223290, upload-time = "2026-05-26T20:39:00.413Z" }, + { url = "https://files.pythonhosted.org/packages/b8/1d/3e3644585eb29e9dafefb19555078529a4d7cce12bd21929664eea989277/coverage-7.14.1-cp311-cp311-win_arm64.whl", hash = "sha256:dd34767fa19848d35659ffc0a75314f58c7af3f1cd87ec521e8292a1238398a3", size = 221953, upload-time = "2026-05-26T20:39:02.159Z" }, + { url = "https://files.pythonhosted.org/packages/3d/b7/bdbb725ba02c5b42825b200c940f38b7a54fcad24627b7192f78f8110d76/coverage-7.14.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:a06c76364a9360e33d6d23769aefdf7f66f38e2ffb60ceb1baaa4989d83b695c", size = 220022, upload-time = "2026-05-26T20:39:03.702Z" }, + { url = "https://files.pythonhosted.org/packages/72/81/fdc0898a55c6219223291ec1a1fe89966ef212ce82276aa0899df84b5de0/coverage-7.14.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:fad54e871165f6ec2f536063ac74c3104508a12963e64072ba44bd822de52b0c", size = 220379, upload-time = "2026-05-26T20:39:05.381Z" }, + { url = "https://files.pythonhosted.org/packages/de/72/de048c4a25e13bce59ac6a339351c10bdf2515e07459afcdaf04dc3143a2/coverage-7.14.1-cp312-cp312-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:84b535f00655ecafe1d929d1fb00ed5d6fa3051ea643ab2c161a3887b86f294b", size = 251888, upload-time = "2026-05-26T20:39:07.367Z" }, + { url = "https://files.pythonhosted.org/packages/28/30/300c343f68beb9d4cbb64ec81e58c5b6b80b56927f72d2b38654ac26e013/coverage-7.14.1-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:6b6b0853b895fe0e98cbfc580d1ec3393d9302b4b1e96a77b3f5c91fdab899e6", size = 254624, upload-time = "2026-05-26T20:39:09.037Z" }, + { url = "https://files.pythonhosted.org/packages/b1/ed/7b25642496e8170b6bac14adce00537c6e5fa2d586159401a4de3e8b49e6/coverage-7.14.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:442cc9c952b2df400cda54bb04ab87330cf2cd08a8692cbbea36773531eb6f37", size = 255739, upload-time = "2026-05-26T20:39:10.889Z" }, + { url = "https://files.pythonhosted.org/packages/7f/a2/abd210b8c4e29c24e4624916db97bb519097a91034aaeb767f937e7da794/coverage-7.14.1-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:8270544c361ed405a27a060dbc9ed2c124b084d96dfdc2d9a2510482aef981ad", size = 257998, upload-time = "2026-05-26T20:39:12.722Z" }, + { url = "https://files.pythonhosted.org/packages/7f/24/7c50beed3792fe62f6ce0545c6686ce83379719e2c0276179333d97eae92/coverage-7.14.1-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:48b283b1dd6372e8de2a7a9a4c4d5dc06f4d4fd209b876f3c88a7a205a0c8f84", size = 252296, upload-time = "2026-05-26T20:39:14.259Z" }, + { url = "https://files.pythonhosted.org/packages/15/05/0f874628ebcbfc77ead559ff210281ef06a97db08481832e7dd39274a135/coverage-7.14.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:5b0c99ba93a07d56f6df340bb79be53202a082b2fdb81bfe6190b741a3470d54", size = 253658, upload-time = "2026-05-26T20:39:15.923Z" }, + { url = "https://files.pythonhosted.org/packages/99/6f/ca6ad067364b337ef997802115e7ecad2abd2248b05471464b0dea02b4d4/coverage-7.14.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:e471bc5769ff073b058cfadb0d736b56ce067c8560eabeb0da88462df98c23e7", size = 251803, upload-time = "2026-05-26T20:39:17.537Z" }, + { url = "https://files.pythonhosted.org/packages/c0/30/b9b4d377cd9f40baf228068f5a81faf8450c6228503011bd499708483a50/coverage-7.14.1-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:f497a1ea81d4cd7c10ddcaa685135b9aabd291af3d55775a9ddf3cb7a364cdd9", size = 255873, upload-time = "2026-05-26T20:39:19.414Z" }, + { url = "https://files.pythonhosted.org/packages/3c/21/7c721a9e5e6bb88547d30a787aefb97512d3f54c1324c7488d9b3743f7f9/coverage-7.14.1-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:2222be86d0b54f5dd5a38f45f17f315f737245e857bf0bdedc70734f84a13c02", size = 251372, upload-time = "2026-05-26T20:39:21.169Z" }, + { url = "https://files.pythonhosted.org/packages/9d/8c/f8ae5a2200130e1503cd7661a6cd3b2b7bacef98277fbf3571fb13f8b766/coverage-7.14.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:85e85586565842f6932abebd4c18bcb1074223dc0b3576e7d173ca710622813a", size = 253245, upload-time = "2026-05-26T20:39:23.097Z" }, + { url = "https://files.pythonhosted.org/packages/34/62/70a9024672a5f6910517d9628c52c9afbdd3cf8f46426af52bb148a56fff/coverage-7.14.1-cp312-cp312-win32.whl", hash = "sha256:4a28fd227808366b196a75476dced2eb35b351d6766ba9c858dc93319e87f4f1", size = 222567, upload-time = "2026-05-26T20:39:24.868Z" }, + { url = "https://files.pythonhosted.org/packages/f6/81/8b7cd386839b039ebe1855733b9f9449a8dec5d79564018234f185a7fa70/coverage-7.14.1-cp312-cp312-win_amd64.whl", hash = "sha256:54acdb6674a4661768d7bf7db32dfb9f46ab1d764f8aba6df75ce1a6a088724e", size = 223372, upload-time = "2026-05-26T20:39:26.603Z" }, + { url = "https://files.pythonhosted.org/packages/ae/ba/b44d472022f620d289d95fa830143235c0c36461c6f2437ea8d51e5481ed/coverage-7.14.1-cp312-cp312-win_arm64.whl", hash = "sha256:99cd41ff91afd94896fea3bc002706b6ae4ce95727d06e4a0f39c0a8d8bd8b1a", size = 221989, upload-time = "2026-05-26T20:39:28.242Z" }, + { url = "https://files.pythonhosted.org/packages/8a/9e/5f6d56327c62b185225d145191c607e07515294a0aa6338e58805cd4a5ac/coverage-7.14.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:be9f2c802dcfce3f71298303aa5dad0dce440a76c52f2f60dacd8656dab78793", size = 220044, upload-time = "2026-05-26T20:39:29.902Z" }, + { url = "https://files.pythonhosted.org/packages/75/92/e82aca356744cbbc0f77a0b623e38918c1872361963413a3bab5d0340393/coverage-7.14.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:6223a72fd0e4c7156353ec0f08a5f93623e1d3034d0e2683b9bb8ea674131b1d", size = 220412, upload-time = "2026-05-26T20:39:31.561Z" }, + { url = "https://files.pythonhosted.org/packages/27/c9/385bde0bf7ed0f4bf3a7ee5367060a86b5d218718cfd6fb943c0f836b34f/coverage-7.14.1-cp313-cp313-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:7279d2110a28cebc738b6459ecda2771735a4c18465fbbd36b3288fe5ed92247", size = 251412, upload-time = "2026-05-26T20:39:33.337Z" }, + { url = "https://files.pythonhosted.org/packages/51/8c/23faf6a2343a0d17f960a4bd56c43bc7eb4cf312f774dd6ceebd82c7d8fc/coverage-7.14.1-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:9eeb3fcbc13ba40dfbdb22d01d196a28e9cef9ed4c29b60061a1e0e823a9929d", size = 254008, upload-time = "2026-05-26T20:39:35.009Z" }, + { url = "https://files.pythonhosted.org/packages/42/06/36f4aa9ca8a815e6036156e80706a67828bb97bd826948244f6996dda957/coverage-7.14.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5f0cfc27c539f07cf5c0a4cfe211d0b6cae039f8f40526dbaa71944e64b50a7b", size = 255241, upload-time = "2026-05-26T20:39:36.71Z" }, + { url = "https://files.pythonhosted.org/packages/ca/79/95266316352f90f6b1c6736bb413302edfde2453fb32422d3911642691b3/coverage-7.14.1-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:221c70f316241a78e77e607c227cefc8808d4e08f28d99c04f35694690e940be", size = 257373, upload-time = "2026-05-26T20:39:38.412Z" }, + { url = "https://files.pythonhosted.org/packages/e3/9c/58316d1f66c488b5fca8a0eb3e98348807813efa8a0d0833b9021be27488/coverage-7.14.1-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:da028256b04ec30e5e0114b6f76172938c313991f0a2d3d894271315cf5d5e43", size = 251635, upload-time = "2026-05-26T20:39:40.268Z" }, + { url = "https://files.pythonhosted.org/packages/ef/5a/ca2398a568e16fed7bb713e84ba3603a7164fb65779abe645c565ec890d5/coverage-7.14.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:76a085d7005236a767e3426148b2c407e53ad61695c562f8a81da2d373324901", size = 253373, upload-time = "2026-05-26T20:39:42.145Z" }, + { url = "https://files.pythonhosted.org/packages/6e/2c/0396562c32deaebe7be51d865b3a41e9a87d7561acafe1a28f53b07e019a/coverage-7.14.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:b553d04b5e778a8e56d57eb134aff42a92718ecba45e79c4764ecfa40efd92ff", size = 251341, upload-time = "2026-05-26T20:39:43.907Z" }, + { url = "https://files.pythonhosted.org/packages/fd/8f/a94f9221184c9cae1ee115820e3798e48b6b17777a9f19e46fb9a0c8dc74/coverage-7.14.1-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:46f714d2fb8ae2f4f29f23ada7f1e79b759fff5a70f94a1dac23af204c3ec9e4", size = 255497, upload-time = "2026-05-26T20:39:46.166Z" }, + { url = "https://files.pythonhosted.org/packages/71/69/505d70e47db1eaebcd002c39759707621ef184cd6b1ae084d9f41293f323/coverage-7.14.1-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:1896f5e19ff3f0431c7ce2172adc54890fd97f86b59ced8ca1649145d9ffe35d", size = 251159, upload-time = "2026-05-26T20:39:48.03Z" }, + { url = "https://files.pythonhosted.org/packages/e0/aa/58681c383aa33a9d2ed40a02d7a22fbf780d1fa4d575396365777828198c/coverage-7.14.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:62fd185ef9df3c33d1c8178c5af105f762afbad96038de9a4ae100aa6297ca33", size = 252934, upload-time = "2026-05-26T20:39:49.872Z" }, + { url = "https://files.pythonhosted.org/packages/eb/fd/11c928cd6bdffc7074bb5965c173d9ebf517fb00205e1da524b98d29ef92/coverage-7.14.1-cp313-cp313-win32.whl", hash = "sha256:ab4af6352741a604c431c6072fce5bee33bf0f20dc7a56618d6bf6bb89e9810c", size = 222584, upload-time = "2026-05-26T20:39:51.68Z" }, + { url = "https://files.pythonhosted.org/packages/6f/92/fb416fc26d340dcba19518c418d6048e913186e17243982c5e435e41fa7a/coverage-7.14.1-cp313-cp313-win_amd64.whl", hash = "sha256:7af486dabe8954d03b087f0021540897afe084f04e16ff5579e08cc46f871416", size = 223394, upload-time = "2026-05-26T20:39:53.472Z" }, + { url = "https://files.pythonhosted.org/packages/73/c6/02d56e3867972f77d5036de924643f26c056e848f00452cafb4dbc3c29b4/coverage-7.14.1-cp313-cp313-win_arm64.whl", hash = "sha256:2224f89ffd0c5605ccce1ed7a584da162bc7c55f601ab1c946bc9de31a486b42", size = 222015, upload-time = "2026-05-26T20:39:55.374Z" }, + { url = "https://files.pythonhosted.org/packages/4d/9e/fcc77914050df73f7662fa1f00902774c79c075a8388ab334074574bf77e/coverage-7.14.1-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:de286598cc65d2b489411174b1faec2f5a7775fb3201fd925db2a76b4030f37d", size = 220733, upload-time = "2026-05-26T20:39:57.189Z" }, + { url = "https://files.pythonhosted.org/packages/f7/67/2963cbdaf5cbadec44efa3a1e39eaa1f02df4079585f05387607a221e126/coverage-7.14.1-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:042c46ded7c288aeb07cf14a28b6c1e10b78fcba40171c3fa1e939377eeef0b5", size = 221086, upload-time = "2026-05-26T20:39:59.019Z" }, + { url = "https://files.pythonhosted.org/packages/c8/c5/8701645574e11881f2f47d8930f98bc48b5d43b25eb5b4430dfc4a2f9f48/coverage-7.14.1-cp313-cp313t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:f4ddbe407477f04c45115d1a4e5bc480f753553b534d338d4c3358b1cdd0ea52", size = 262381, upload-time = "2026-05-26T20:40:00.822Z" }, + { url = "https://files.pythonhosted.org/packages/7c/28/7a64d73598263e0c5abd5084211a8474488d31b3c552ff531c719dfcff62/coverage-7.14.1-cp313-cp313t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:d13e6725992e2d2fd7d81d4f5241952d13740121dfd501da09201be39b2c003a", size = 264458, upload-time = "2026-05-26T20:40:02.506Z" }, + { url = "https://files.pythonhosted.org/packages/fa/d8/4969179db9f7eb4df218e69540adf829d1c835f59452513d065d15446802/coverage-7.14.1-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f747dc8edcfe740130f28f32f3995e955494285717e86ee25af51db2219df08a", size = 266884, upload-time = "2026-05-26T20:40:04.421Z" }, + { url = "https://files.pythonhosted.org/packages/a6/78/a45d5794dbc9bafd97afc96a4377c86c7820d78b6cf51b89bc1d4e919275/coverage-7.14.1-cp313-cp313t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:ced2f09ef276fd58611a1ef502164ad266d2b75174e5a40cabbdb4033f9f6cf2", size = 268022, upload-time = "2026-05-26T20:40:06.298Z" }, + { url = "https://files.pythonhosted.org/packages/21/cb/4f5e354e9e3e67af96bd4e57113e6db6b22298c7168b13eec408a549903d/coverage-7.14.1-cp313-cp313t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:b84800013769a78ccb9ef4659402e26d06867e337b61ec365f77ad008adea80e", size = 261631, upload-time = "2026-05-26T20:40:08.226Z" }, + { url = "https://files.pythonhosted.org/packages/ec/49/eced49af4cb996d5d8b7e94e736175c513e4facd3398507b89892b4326d8/coverage-7.14.1-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:ea8cd6ca0ee9f616aaef3afc6882e32c2cbf18b00d96313ffd76af650574034d", size = 264443, upload-time = "2026-05-26T20:40:10.137Z" }, + { url = "https://files.pythonhosted.org/packages/f1/d8/5603a88a7c5913a6b54f6cb1a8c46f7b39cbb30f27cd3f492908da09b2d7/coverage-7.14.1-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:aa5e304a873fabddc11e484e9b6b738bd38bd7bed17b09aa84eecf5332e8b8bb", size = 262069, upload-time = "2026-05-26T20:40:11.999Z" }, + { url = "https://files.pythonhosted.org/packages/f0/59/2ae3cb79da554a06c8619d6c88ea19dd1e4aed4b834b6a83bb1fa243bdc5/coverage-7.14.1-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:5a1c5215be81035e629d5bc756650634d0bf31991038db7a0eccb90f025ce16d", size = 265780, upload-time = "2026-05-26T20:40:13.858Z" }, + { url = "https://files.pythonhosted.org/packages/af/5f/b130c1dc999031f2648bd25317fbce505ad8d5562079b4ed81e736a84967/coverage-7.14.1-cp313-cp313t-musllinux_1_2_riscv64.whl", hash = "sha256:79058c47dae6788504b5effb319961bcd72d7240551464b91d474bc0ed186d69", size = 260970, upload-time = "2026-05-26T20:40:16.142Z" }, + { url = "https://files.pythonhosted.org/packages/87/d1/ec13ccddeb48ec963bdfa72a11224bac2584bd045ba13beca82f8113e9c7/coverage-7.14.1-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:370c5afae3fa0658e11694a32b24c2778f6bc2d17718121f94ee185e69f26b54", size = 263157, upload-time = "2026-05-26T20:40:18.382Z" }, + { url = "https://files.pythonhosted.org/packages/cf/c2/cd91ead503045161092d3845f7bb95ea2f25131ce96d3e314dd835d91b9c/coverage-7.14.1-cp313-cp313t-win32.whl", hash = "sha256:3758dd0a7f1fa57365ef2e781df0f0731d38b6e3772259d13dae4bd8a958d4b1", size = 223259, upload-time = "2026-05-26T20:40:20.381Z" }, + { url = "https://files.pythonhosted.org/packages/71/9f/1e28d97e6bd2c76b07f38b7c02870f1371255ff6717f54eca578fcbbdd0e/coverage-7.14.1-cp313-cp313t-win_amd64.whl", hash = "sha256:6ff665fb023a77386fe11685190cee1f60a7d635994a30d9b0a061533d470fce", size = 224320, upload-time = "2026-05-26T20:40:22.316Z" }, + { url = "https://files.pythonhosted.org/packages/a9/e0/d936e908f0e1efa55e52b91e01b52f1055cef5e1ab2718493390ed8e2fb8/coverage-7.14.1-cp313-cp313t-win_arm64.whl", hash = "sha256:17a5a241e5997621a956a7f402a7433ef4221e5152809b785bec79e2323799f1", size = 222577, upload-time = "2026-05-26T20:40:24.894Z" }, + { url = "https://files.pythonhosted.org/packages/d6/34/fc2f101b151af3799a101f0550b0454aa008afdc0add677394ec4aa8ea10/coverage-7.14.1-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:d5ed429d0b8edaac649e889b4ffcedb6c80b06629a3f93050e3dddfb99235bee", size = 220091, upload-time = "2026-05-26T20:40:27.249Z" }, + { url = "https://files.pythonhosted.org/packages/3d/a7/1ebae2ab5b961b5c79bb09fe7b3ac99edb190d8be4a8c510b2cf66f46468/coverage-7.14.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:8011224a62280e50dab346960c03cf47aca1a1e09e608c0fb33fd6e0cc8e9500", size = 220421, upload-time = "2026-05-26T20:40:30.084Z" }, + { url = "https://files.pythonhosted.org/packages/5e/90/92aca9cf0acc95123c96cd1eb1f08917897a7f5dee01e15738922971ec31/coverage-7.14.1-cp314-cp314-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:12c42ec1e14f553c4f817e989365982e646e27211f10a0f717855b94a79c8906", size = 251466, upload-time = "2026-05-26T20:40:32.542Z" }, + { url = "https://files.pythonhosted.org/packages/26/2b/78048cbe3b999f6cbf9cc0d90abba6a88a3e0863a8c1c6cbc762f3f8802f/coverage-7.14.1-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:06144cd511cf2624873a035c5069cf297144f6e77a73ee3d7a55b605ec5efb42", size = 253973, upload-time = "2026-05-26T20:40:34.473Z" }, + { url = "https://files.pythonhosted.org/packages/8e/21/c2e33b29d1cfde484a19d437afc343c6cd30b08d78cbbf9f5aff14e57b2b/coverage-7.14.1-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a311d8e1da24be5c1ccf85cbfb06315dbaa1703d5a1eab3f6432c72b837917c8", size = 255318, upload-time = "2026-05-26T20:40:38.154Z" }, + { url = "https://files.pythonhosted.org/packages/8e/ee/aad2f108d63b769121005302f16bf66db8625c88ceaba466942e09a2607e/coverage-7.14.1-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:c79cead5b5bc584d9c71451cb984d0e3a84e0c0937379c8efcbf27c8d661b851", size = 257633, upload-time = "2026-05-26T20:40:40.164Z" }, + { url = "https://files.pythonhosted.org/packages/c2/f8/11a2c29b4fd76d9849f81d0bb812ec0017a9396df3217214e38934a8c837/coverage-7.14.1-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:dcbf65f1f66a26cdd88c35cf68fb4729c5d1cd2e88added72420541dfb212034", size = 251488, upload-time = "2026-05-26T20:40:42.631Z" }, + { url = "https://files.pythonhosted.org/packages/c9/b8/9a5820de4b8ac2b71d85e3b5fb49108d7469c665f0e2ad0dd7569023e305/coverage-7.14.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:fd86572566fb40189a8260446158235159bc7a82dfbc87a3b39cf4fb57fcec1c", size = 253329, upload-time = "2026-05-26T20:40:45.208Z" }, + { url = "https://files.pythonhosted.org/packages/6b/ff/f33e4823667e27548e8fd8df44217515303f9808d0ff29817db56f87d990/coverage-7.14.1-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:7771b601718fdde84832c3a434ca9bbf4ae9adbc49d84198b4110700c3c77c36", size = 251291, upload-time = "2026-05-26T20:40:47.502Z" }, + { url = "https://files.pythonhosted.org/packages/68/9b/489db0ebb209054766b90a9014a45f6d26eb724c02ec21311c3733b5a644/coverage-7.14.1-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:39b21e212c55af06fa375e3dbf90a8a8e38792f3a910c580066d23563830ddd5", size = 255564, upload-time = "2026-05-26T20:40:49.372Z" }, + { url = "https://files.pythonhosted.org/packages/27/b5/16bc2d4c2409b23c7737edb68c83bc89e345f378050549fe1d75ac7d34d5/coverage-7.14.1-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:f2302660e32562a532b442480121aef8aa61a5bdb20b30bf0adab29f10a5a4b4", size = 251107, upload-time = "2026-05-26T20:40:51.677Z" }, + { url = "https://files.pythonhosted.org/packages/7d/0c/2629997469a00cd069d588a41c9dc887610f2775ae89d250c4791e65272a/coverage-7.14.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:03a6f93c1ec3b7f2e77b5dbcc5573a2c21f12529a5c6bbe0f16f72303cc2fa4d", size = 252764, upload-time = "2026-05-26T20:40:54.267Z" }, + { url = "https://files.pythonhosted.org/packages/d2/ee/f78d63c8f079e0d7211c7e2401fa17e311514534ba61bae03e4b287ce4ab/coverage-7.14.1-cp314-cp314-win32.whl", hash = "sha256:8a3ce026d73290f42f08dafecbd82c193a74df280461fbf97300fec51fd133ee", size = 222837, upload-time = "2026-05-26T20:40:56.496Z" }, + { url = "https://files.pythonhosted.org/packages/dc/b9/be539854f93a70dfbeec69117f33ec70dc42ff0b65b5b07ab8d40d04228e/coverage-7.14.1-cp314-cp314-win_amd64.whl", hash = "sha256:114c95ef29302423b87d159075805f4ab973254a2638a5d7d046c94887cc87d7", size = 223650, upload-time = "2026-05-26T20:40:58.351Z" }, + { url = "https://files.pythonhosted.org/packages/fe/9e/24e2842fef40f35ac82ba3a7719c8023d011bf3bf652d0675316a9d088a1/coverage-7.14.1-cp314-cp314-win_arm64.whl", hash = "sha256:a07891c3f4805442b31b71e84ba3cf29ed1aa9a428284e06deeb4b23e5b46343", size = 222218, upload-time = "2026-05-26T20:41:00.321Z" }, + { url = "https://files.pythonhosted.org/packages/0a/1d/ac0a9df5fe31c1e8bdd658074905fc12844a05c1a7e3fdb8417e97c31e23/coverage-7.14.1-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:1101a5ebb083aecb625ebb6209d4105b58f647b093cb2dc8122d7b33f743cfe1", size = 220822, upload-time = "2026-05-26T20:41:02.281Z" }, + { url = "https://files.pythonhosted.org/packages/32/cf/f964fd9aff20323f9f1a726c97135f8a76bcd87b92dad141a456a43f3c64/coverage-7.14.1-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:851b9e1e4e8a4608e77c79714b2e77c0970d2ed7202a05e92ae407817481887b", size = 221084, upload-time = "2026-05-26T20:41:04.593Z" }, + { url = "https://files.pythonhosted.org/packages/d8/5e/7e5ef2aba844de2b80d678619fcf0841b42e3f37f16411226f3fe4c1016f/coverage-7.14.1-cp314-cp314t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:d5b89cdfb2ee051b71e8c3c70bd81a9eff81100f736a269136fe1a68efe00474", size = 262454, upload-time = "2026-05-26T20:41:06.641Z" }, + { url = "https://files.pythonhosted.org/packages/64/62/75809bded87015cc4935524218a2a8ed8dd1a8498bfed30a2f4f7a4b4d34/coverage-7.14.1-cp314-cp314t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:0177614a0370f227888b4e436a7c55686d6a9f90eb1ade2b624ba685a1686e86", size = 264578, upload-time = "2026-05-26T20:41:08.556Z" }, + { url = "https://files.pythonhosted.org/packages/f3/42/d33392dc14633525012d2d504fa1a33b05538bf535f5c1d64675e5754b78/coverage-7.14.1-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:2d69af5dea2de76fc485a83032a630523f985198b7e25be901ec60181587b01e", size = 266981, upload-time = "2026-05-26T20:41:10.824Z" }, + { url = "https://files.pythonhosted.org/packages/2a/49/0157c4428c2aca7f1e09d5565930586fd5ae36f1655f08b0daa7cf1fcae1/coverage-7.14.1-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:35ab22d91de736e8966b980dc355cbcdd2c6dbbcfe275f9a2991bc8a91b3df65", size = 268112, upload-time = "2026-05-26T20:41:12.966Z" }, + { url = "https://files.pythonhosted.org/packages/96/26/86b9ce71f4092b1ed325ce1421698081df1286b833400b6836912834d6e0/coverage-7.14.1-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:357d4e32935c36588aaba057d734fa32428c360c9fc2e4442afbf1b646beee6e", size = 261558, upload-time = "2026-05-26T20:41:15Z" }, + { url = "https://files.pythonhosted.org/packages/20/4c/c311210c5472cf5401d8422b0d7812cdd520f24417673afabda6c323faca/coverage-7.14.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:51bd64741cc6fa065abd300ede1afe5a5291ece9c31da8b24884deda48bcc3f8", size = 264447, upload-time = "2026-05-26T20:41:17.369Z" }, + { url = "https://files.pythonhosted.org/packages/fb/71/59513f8710ed3e6b0ac0a050a5b7e977bb9c9e880354863b5d00d8809256/coverage-7.14.1-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:9132cd363a68a4c3daa7c8704a654b1e39d3360f6f5b8ddd470608a945236c07", size = 262048, upload-time = "2026-05-26T20:41:19.309Z" }, + { url = "https://files.pythonhosted.org/packages/84/8d/bceed32dc494f5bbf50f775cd2e78ca814953942b5ea28d3c1c3ac316f14/coverage-7.14.1-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:07c6290b1697b862c0478eab545eec949a0d0e4d6d03497f446d706da3b4f2de", size = 265781, upload-time = "2026-05-26T20:41:21.559Z" }, + { url = "https://files.pythonhosted.org/packages/e7/c5/9348fe40dbfd4991aaf78df2c6c3098bfb2cc834d1fd362a64b4efef855a/coverage-7.14.1-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:5ea0c297e27133853b4d8a3eb799bff5a2dbd9f2f41537a240d337ac9b4df890", size = 260896, upload-time = "2026-05-26T20:41:23.428Z" }, + { url = "https://files.pythonhosted.org/packages/ca/92/1ea0f03929da7cf87206b1fa24f4c8e9c158be0455481af29ec0a1f3503f/coverage-7.14.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:01b7733daad0237daa01ef80fe2dfceffc911e6a17fa7b55d14aa8214eaaaecd", size = 263214, upload-time = "2026-05-26T20:41:25.419Z" }, + { url = "https://files.pythonhosted.org/packages/f6/a9/b2493c054c0e01a643266742ab45e15744e60743f9260cd930c7142b1124/coverage-7.14.1-cp314-cp314t-win32.whl", hash = "sha256:6adc5a36984624a70bf11d7184e20fa0a49aa7c47ffab43804106a1a695ea22e", size = 223624, upload-time = "2026-05-26T20:41:27.795Z" }, + { url = "https://files.pythonhosted.org/packages/fc/bd/3e1e6a57fccd2d7c83fcdf338e93ba98eb85c6e877dd34731ac585375490/coverage-7.14.1-cp314-cp314t-win_amd64.whl", hash = "sha256:ddf799247318f34dbcd2efa8c95a8d0642674e926bb1774cf9b63dfd2a389d1c", size = 224728, upload-time = "2026-05-26T20:41:30.098Z" }, + { url = "https://files.pythonhosted.org/packages/bb/d7/31066cf1d2f0c6c797fce911bcfa01dd35642dc6da992a950256097c5860/coverage-7.14.1-cp314-cp314t-win_arm64.whl", hash = "sha256:145986fe66647eb489f18d9a997567a3fd358584c4b5a808769113abc07466af", size = 222752, upload-time = "2026-05-26T20:41:32.123Z" }, + { url = "https://files.pythonhosted.org/packages/8a/3c/1a983b9a745d7f83d53f057bcc5bf79ba6a2bbc08266b3f0c7d6fe630c9b/coverage-7.14.1-py3-none-any.whl", hash = "sha256:a252f21c27e38347e60111a3266b03827422a7d5525951aceee313aa68bab1d2", size = 211815, upload-time = "2026-05-26T20:41:34.078Z" }, ] [package.optional-dependencies] @@ -878,62 +895,59 @@ toml = [ [[package]] name = "cryptography" -version = "46.0.7" +version = "49.0.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "cffi", marker = "platform_python_implementation != 'PyPy'" }, { name = "typing-extensions", marker = "python_full_version < '3.11'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/47/93/ac8f3d5ff04d54bc814e961a43ae5b0b146154c89c61b47bb07557679b18/cryptography-46.0.7.tar.gz", hash = "sha256:e4cfd68c5f3e0bfdad0d38e023239b96a2fe84146481852dffbcca442c245aa5", size = 750652, upload-time = "2026-04-08T01:57:54.692Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/0b/5d/4a8f770695d73be252331e60e526291e3df0c9b27556a90a6b47bccca4c2/cryptography-46.0.7-cp311-abi3-macosx_10_9_universal2.whl", hash = "sha256:ea42cbe97209df307fdc3b155f1b6fa2577c0defa8f1f7d3be7d31d189108ad4", size = 7179869, upload-time = "2026-04-08T01:56:17.157Z" }, - { url = "https://files.pythonhosted.org/packages/5f/45/6d80dc379b0bbc1f9d1e429f42e4cb9e1d319c7a8201beffd967c516ea01/cryptography-46.0.7-cp311-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:b36a4695e29fe69215d75960b22577197aca3f7a25b9cf9d165dcfe9d80bc325", size = 4275492, upload-time = "2026-04-08T01:56:19.36Z" }, - { url = "https://files.pythonhosted.org/packages/4a/9a/1765afe9f572e239c3469f2cb429f3ba7b31878c893b246b4b2994ffe2fe/cryptography-46.0.7-cp311-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:5ad9ef796328c5e3c4ceed237a183f5d41d21150f972455a9d926593a1dcb308", size = 4426670, upload-time = "2026-04-08T01:56:21.415Z" }, - { url = "https://files.pythonhosted.org/packages/8f/3e/af9246aaf23cd4ee060699adab1e47ced3f5f7e7a8ffdd339f817b446462/cryptography-46.0.7-cp311-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:73510b83623e080a2c35c62c15298096e2a5dc8d51c3b4e1740211839d0dea77", size = 4280275, upload-time = "2026-04-08T01:56:23.539Z" }, - { url = "https://files.pythonhosted.org/packages/0f/54/6bbbfc5efe86f9d71041827b793c24811a017c6ac0fd12883e4caa86b8ed/cryptography-46.0.7-cp311-abi3-manylinux_2_28_ppc64le.whl", hash = "sha256:cbd5fb06b62bd0721e1170273d3f4d5a277044c47ca27ee257025146c34cbdd1", size = 4928402, upload-time = "2026-04-08T01:56:25.624Z" }, - { url = "https://files.pythonhosted.org/packages/2d/cf/054b9d8220f81509939599c8bdbc0c408dbd2bdd41688616a20731371fe0/cryptography-46.0.7-cp311-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:420b1e4109cc95f0e5700eed79908cef9268265c773d3a66f7af1eef53d409ef", size = 4459985, upload-time = "2026-04-08T01:56:27.309Z" }, - { url = "https://files.pythonhosted.org/packages/f9/46/4e4e9c6040fb01c7467d47217d2f882daddeb8828f7df800cb806d8a2288/cryptography-46.0.7-cp311-abi3-manylinux_2_31_armv7l.whl", hash = "sha256:24402210aa54baae71d99441d15bb5a1919c195398a87b563df84468160a65de", size = 3990652, upload-time = "2026-04-08T01:56:29.095Z" }, - { url = "https://files.pythonhosted.org/packages/36/5f/313586c3be5a2fbe87e4c9a254207b860155a8e1f3cca99f9910008e7d08/cryptography-46.0.7-cp311-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:8a469028a86f12eb7d2fe97162d0634026d92a21f3ae0ac87ed1c4a447886c83", size = 4279805, upload-time = "2026-04-08T01:56:30.928Z" }, - { url = "https://files.pythonhosted.org/packages/69/33/60dfc4595f334a2082749673386a4d05e4f0cf4df8248e63b2c3437585f2/cryptography-46.0.7-cp311-abi3-manylinux_2_34_ppc64le.whl", hash = "sha256:9694078c5d44c157ef3162e3bf3946510b857df5a3955458381d1c7cfc143ddb", size = 4892883, upload-time = "2026-04-08T01:56:32.614Z" }, - { url = "https://files.pythonhosted.org/packages/c7/0b/333ddab4270c4f5b972f980adef4faa66951a4aaf646ca067af597f15563/cryptography-46.0.7-cp311-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:42a1e5f98abb6391717978baf9f90dc28a743b7d9be7f0751a6f56a75d14065b", size = 4459756, upload-time = "2026-04-08T01:56:34.306Z" }, - { url = "https://files.pythonhosted.org/packages/d2/14/633913398b43b75f1234834170947957c6b623d1701ffc7a9600da907e89/cryptography-46.0.7-cp311-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:91bbcb08347344f810cbe49065914fe048949648f6bd5c2519f34619142bbe85", size = 4410244, upload-time = "2026-04-08T01:56:35.977Z" }, - { url = "https://files.pythonhosted.org/packages/10/f2/19ceb3b3dc14009373432af0c13f46aa08e3ce334ec6eff13492e1812ccd/cryptography-46.0.7-cp311-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:5d1c02a14ceb9148cc7816249f64f623fbfee39e8c03b3650d842ad3f34d637e", size = 4674868, upload-time = "2026-04-08T01:56:38.034Z" }, - { url = "https://files.pythonhosted.org/packages/1a/bb/a5c213c19ee94b15dfccc48f363738633a493812687f5567addbcbba9f6f/cryptography-46.0.7-cp311-abi3-win32.whl", hash = "sha256:d23c8ca48e44ee015cd0a54aeccdf9f09004eba9fc96f38c911011d9ff1bd457", size = 3026504, upload-time = "2026-04-08T01:56:39.666Z" }, - { url = "https://files.pythonhosted.org/packages/2b/02/7788f9fefa1d060ca68717c3901ae7fffa21ee087a90b7f23c7a603c32ae/cryptography-46.0.7-cp311-abi3-win_amd64.whl", hash = "sha256:397655da831414d165029da9bc483bed2fe0e75dde6a1523ec2fe63f3c46046b", size = 3488363, upload-time = "2026-04-08T01:56:41.893Z" }, - { url = "https://files.pythonhosted.org/packages/7b/56/15619b210e689c5403bb0540e4cb7dbf11a6bf42e483b7644e471a2812b3/cryptography-46.0.7-cp314-cp314t-macosx_10_9_universal2.whl", hash = "sha256:d151173275e1728cf7839aaa80c34fe550c04ddb27b34f48c232193df8db5842", size = 7119671, upload-time = "2026-04-08T01:56:44Z" }, - { url = "https://files.pythonhosted.org/packages/74/66/e3ce040721b0b5599e175ba91ab08884c75928fbeb74597dd10ef13505d2/cryptography-46.0.7-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:db0f493b9181c7820c8134437eb8b0b4792085d37dbb24da050476ccb664e59c", size = 4268551, upload-time = "2026-04-08T01:56:46.071Z" }, - { url = "https://files.pythonhosted.org/packages/03/11/5e395f961d6868269835dee1bafec6a1ac176505a167f68b7d8818431068/cryptography-46.0.7-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:ebd6daf519b9f189f85c479427bbd6e9c9037862cf8fe89ee35503bd209ed902", size = 4408887, upload-time = "2026-04-08T01:56:47.718Z" }, - { url = "https://files.pythonhosted.org/packages/40/53/8ed1cf4c3b9c8e611e7122fb56f1c32d09e1fff0f1d77e78d9ff7c82653e/cryptography-46.0.7-cp314-cp314t-manylinux_2_28_aarch64.whl", hash = "sha256:b7b412817be92117ec5ed95f880defe9cf18a832e8cafacf0a22337dc1981b4d", size = 4271354, upload-time = "2026-04-08T01:56:49.312Z" }, - { url = "https://files.pythonhosted.org/packages/50/46/cf71e26025c2e767c5609162c866a78e8a2915bbcfa408b7ca495c6140c4/cryptography-46.0.7-cp314-cp314t-manylinux_2_28_ppc64le.whl", hash = "sha256:fbfd0e5f273877695cb93baf14b185f4878128b250cc9f8e617ea0c025dfb022", size = 4905845, upload-time = "2026-04-08T01:56:50.916Z" }, - { url = "https://files.pythonhosted.org/packages/c0/ea/01276740375bac6249d0a971ebdf6b4dc9ead0ee0a34ef3b5a88c1a9b0d4/cryptography-46.0.7-cp314-cp314t-manylinux_2_28_x86_64.whl", hash = "sha256:ffca7aa1d00cf7d6469b988c581598f2259e46215e0140af408966a24cf086ce", size = 4444641, upload-time = "2026-04-08T01:56:52.882Z" }, - { url = "https://files.pythonhosted.org/packages/3d/4c/7d258f169ae71230f25d9f3d06caabcff8c3baf0978e2b7d65e0acac3827/cryptography-46.0.7-cp314-cp314t-manylinux_2_31_armv7l.whl", hash = "sha256:60627cf07e0d9274338521205899337c5d18249db56865f943cbe753aa96f40f", size = 3967749, upload-time = "2026-04-08T01:56:54.597Z" }, - { url = "https://files.pythonhosted.org/packages/b5/2a/2ea0767cad19e71b3530e4cad9605d0b5e338b6a1e72c37c9c1ceb86c333/cryptography-46.0.7-cp314-cp314t-manylinux_2_34_aarch64.whl", hash = "sha256:80406c3065e2c55d7f49a9550fe0c49b3f12e5bfff5dedb727e319e1afb9bf99", size = 4270942, upload-time = "2026-04-08T01:56:56.416Z" }, - { url = "https://files.pythonhosted.org/packages/41/3d/fe14df95a83319af25717677e956567a105bb6ab25641acaa093db79975d/cryptography-46.0.7-cp314-cp314t-manylinux_2_34_ppc64le.whl", hash = "sha256:c5b1ccd1239f48b7151a65bc6dd54bcfcc15e028c8ac126d3fada09db0e07ef1", size = 4871079, upload-time = "2026-04-08T01:56:58.31Z" }, - { url = "https://files.pythonhosted.org/packages/9c/59/4a479e0f36f8f378d397f4eab4c850b4ffb79a2f0d58704b8fa0703ddc11/cryptography-46.0.7-cp314-cp314t-manylinux_2_34_x86_64.whl", hash = "sha256:d5f7520159cd9c2154eb61eb67548ca05c5774d39e9c2c4339fd793fe7d097b2", size = 4443999, upload-time = "2026-04-08T01:57:00.508Z" }, - { url = "https://files.pythonhosted.org/packages/28/17/b59a741645822ec6d04732b43c5d35e4ef58be7bfa84a81e5ae6f05a1d33/cryptography-46.0.7-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:fcd8eac50d9138c1d7fc53a653ba60a2bee81a505f9f8850b6b2888555a45d0e", size = 4399191, upload-time = "2026-04-08T01:57:02.654Z" }, - { url = "https://files.pythonhosted.org/packages/59/6a/bb2e166d6d0e0955f1e9ff70f10ec4b2824c9cfcdb4da772c7dd69cc7d80/cryptography-46.0.7-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:65814c60f8cc400c63131584e3e1fad01235edba2614b61fbfbfa954082db0ee", size = 4655782, upload-time = "2026-04-08T01:57:04.592Z" }, - { url = "https://files.pythonhosted.org/packages/95/b6/3da51d48415bcb63b00dc17c2eff3a651b7c4fed484308d0f19b30e8cb2c/cryptography-46.0.7-cp314-cp314t-win32.whl", hash = "sha256:fdd1736fed309b4300346f88f74cd120c27c56852c3838cab416e7a166f67298", size = 3002227, upload-time = "2026-04-08T01:57:06.91Z" }, - { url = "https://files.pythonhosted.org/packages/32/a8/9f0e4ed57ec9cebe506e58db11ae472972ecb0c659e4d52bbaee80ca340a/cryptography-46.0.7-cp314-cp314t-win_amd64.whl", hash = "sha256:e06acf3c99be55aa3b516397fe42f5855597f430add9c17fa46bf2e0fb34c9bb", size = 3475332, upload-time = "2026-04-08T01:57:08.807Z" }, - { url = "https://files.pythonhosted.org/packages/a7/7f/cd42fc3614386bc0c12f0cb3c4ae1fc2bbca5c9662dfed031514911d513d/cryptography-46.0.7-cp38-abi3-macosx_10_9_universal2.whl", hash = "sha256:462ad5cb1c148a22b2e3bcc5ad52504dff325d17daf5df8d88c17dda1f75f2a4", size = 7165618, upload-time = "2026-04-08T01:57:10.645Z" }, - { url = "https://files.pythonhosted.org/packages/a5/d0/36a49f0262d2319139d2829f773f1b97ef8aef7f97e6e5bd21455e5a8fb5/cryptography-46.0.7-cp38-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:84d4cced91f0f159a7ddacad249cc077e63195c36aac40b4150e7a57e84fffe7", size = 4270628, upload-time = "2026-04-08T01:57:12.885Z" }, - { url = "https://files.pythonhosted.org/packages/8a/6c/1a42450f464dda6ffbe578a911f773e54dd48c10f9895a23a7e88b3e7db5/cryptography-46.0.7-cp38-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:128c5edfe5e5938b86b03941e94fac9ee793a94452ad1365c9fc3f4f62216832", size = 4415405, upload-time = "2026-04-08T01:57:14.923Z" }, - { url = "https://files.pythonhosted.org/packages/9a/92/4ed714dbe93a066dc1f4b4581a464d2d7dbec9046f7c8b7016f5286329e2/cryptography-46.0.7-cp38-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:5e51be372b26ef4ba3de3c167cd3d1022934bc838ae9eaad7e644986d2a3d163", size = 4272715, upload-time = "2026-04-08T01:57:16.638Z" }, - { url = "https://files.pythonhosted.org/packages/b7/e6/a26b84096eddd51494bba19111f8fffe976f6a09f132706f8f1bf03f51f7/cryptography-46.0.7-cp38-abi3-manylinux_2_28_ppc64le.whl", hash = "sha256:cdf1a610ef82abb396451862739e3fc93b071c844399e15b90726ef7470eeaf2", size = 4918400, upload-time = "2026-04-08T01:57:19.021Z" }, - { url = "https://files.pythonhosted.org/packages/c7/08/ffd537b605568a148543ac3c2b239708ae0bd635064bab41359252ef88ed/cryptography-46.0.7-cp38-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:1d25aee46d0c6f1a501adcddb2d2fee4b979381346a78558ed13e50aa8a59067", size = 4450634, upload-time = "2026-04-08T01:57:21.185Z" }, - { url = "https://files.pythonhosted.org/packages/16/01/0cd51dd86ab5b9befe0d031e276510491976c3a80e9f6e31810cce46c4ad/cryptography-46.0.7-cp38-abi3-manylinux_2_31_armv7l.whl", hash = "sha256:cdfbe22376065ffcf8be74dc9a909f032df19bc58a699456a21712d6e5eabfd0", size = 3985233, upload-time = "2026-04-08T01:57:22.862Z" }, - { url = "https://files.pythonhosted.org/packages/92/49/819d6ed3a7d9349c2939f81b500a738cb733ab62fbecdbc1e38e83d45e12/cryptography-46.0.7-cp38-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:abad9dac36cbf55de6eb49badd4016806b3165d396f64925bf2999bcb67837ba", size = 4271955, upload-time = "2026-04-08T01:57:24.814Z" }, - { url = "https://files.pythonhosted.org/packages/80/07/ad9b3c56ebb95ed2473d46df0847357e01583f4c52a85754d1a55e29e4d0/cryptography-46.0.7-cp38-abi3-manylinux_2_34_ppc64le.whl", hash = "sha256:935ce7e3cfdb53e3536119a542b839bb94ec1ad081013e9ab9b7cfd478b05006", size = 4879888, upload-time = "2026-04-08T01:57:26.88Z" }, - { url = "https://files.pythonhosted.org/packages/b8/c7/201d3d58f30c4c2bdbe9b03844c291feb77c20511cc3586daf7edc12a47b/cryptography-46.0.7-cp38-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:35719dc79d4730d30f1c2b6474bd6acda36ae2dfae1e3c16f2051f215df33ce0", size = 4449961, upload-time = "2026-04-08T01:57:29.068Z" }, - { url = "https://files.pythonhosted.org/packages/a5/ef/649750cbf96f3033c3c976e112265c33906f8e462291a33d77f90356548c/cryptography-46.0.7-cp38-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:7bbc6ccf49d05ac8f7d7b5e2e2c33830d4fe2061def88210a126d130d7f71a85", size = 4401696, upload-time = "2026-04-08T01:57:31.029Z" }, - { url = "https://files.pythonhosted.org/packages/41/52/a8908dcb1a389a459a29008c29966c1d552588d4ae6d43f3a1a4512e0ebe/cryptography-46.0.7-cp38-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:a1529d614f44b863a7b480c6d000fe93b59acee9c82ffa027cfadc77521a9f5e", size = 4664256, upload-time = "2026-04-08T01:57:33.144Z" }, - { url = "https://files.pythonhosted.org/packages/4b/fa/f0ab06238e899cc3fb332623f337a7364f36f4bb3f2534c2bb95a35b132c/cryptography-46.0.7-cp38-abi3-win32.whl", hash = "sha256:f247c8c1a1fb45e12586afbb436ef21ff1e80670b2861a90353d9b025583d246", size = 3013001, upload-time = "2026-04-08T01:57:34.933Z" }, - { url = "https://files.pythonhosted.org/packages/d2/f1/00ce3bde3ca542d1acd8f8cfa38e446840945aa6363f9b74746394b14127/cryptography-46.0.7-cp38-abi3-win_amd64.whl", hash = "sha256:506c4ff91eff4f82bdac7633318a526b1d1309fc07ca76a3ad182cb5b686d6d3", size = 3472985, upload-time = "2026-04-08T01:57:36.714Z" }, - { url = "https://files.pythonhosted.org/packages/63/0c/dca8abb64e7ca4f6b2978769f6fea5ad06686a190cec381f0a796fdcaaba/cryptography-46.0.7-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:fc9ab8856ae6cf7c9358430e49b368f3108f050031442eaeb6b9d87e4dcf4e4f", size = 3476879, upload-time = "2026-04-08T01:57:38.664Z" }, - { url = "https://files.pythonhosted.org/packages/3a/ea/075aac6a84b7c271578d81a2f9968acb6e273002408729f2ddff517fed4a/cryptography-46.0.7-pp311-pypy311_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:d3b99c535a9de0adced13d159c5a9cf65c325601aa30f4be08afd680643e9c15", size = 4219700, upload-time = "2026-04-08T01:57:40.625Z" }, - { url = "https://files.pythonhosted.org/packages/6c/7b/1c55db7242b5e5612b29fc7a630e91ee7a6e3c8e7bf5406d22e206875fbd/cryptography-46.0.7-pp311-pypy311_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:d02c738dacda7dc2a74d1b2b3177042009d5cab7c7079db74afc19e56ca1b455", size = 4385982, upload-time = "2026-04-08T01:57:42.725Z" }, - { url = "https://files.pythonhosted.org/packages/cb/da/9870eec4b69c63ef5925bf7d8342b7e13bc2ee3d47791461c4e49ca212f4/cryptography-46.0.7-pp311-pypy311_pp73-manylinux_2_34_aarch64.whl", hash = "sha256:04959522f938493042d595a736e7dbdff6eb6cc2339c11465b3ff89343b65f65", size = 4219115, upload-time = "2026-04-08T01:57:44.939Z" }, - { url = "https://files.pythonhosted.org/packages/f4/72/05aa5832b82dd341969e9a734d1812a6aadb088d9eb6f0430fc337cc5a8f/cryptography-46.0.7-pp311-pypy311_pp73-manylinux_2_34_x86_64.whl", hash = "sha256:3986ac1dee6def53797289999eabe84798ad7817f3e97779b5061a95b0ee4968", size = 4385479, upload-time = "2026-04-08T01:57:46.86Z" }, - { url = "https://files.pythonhosted.org/packages/20/2a/1b016902351a523aa2bd446b50a5bc1175d7a7d1cf90fe2ef904f9b84ebc/cryptography-46.0.7-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:258514877e15963bd43b558917bc9f54cf7cf866c38aa576ebf47a77ddbc43a4", size = 3412829, upload-time = "2026-04-08T01:57:48.874Z" }, +sdist = { url = "https://files.pythonhosted.org/packages/1f/99/d1c90d6041656cc6ee229dc99cd67fd0cd5aec3c5f7d72fffc27cc750054/cryptography-49.0.0.tar.gz", hash = "sha256:f89660a348f4f78a92366240a61404e337586ef7f5909a2fef59ca88ef505493", size = 854345, upload-time = "2026-06-12T20:02:30.512Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/9b/22/adf66990e63584a68dfb50c24f48a125c07b1699899381c8151e63ed458c/cryptography-49.0.0-cp311-abi3-macosx_11_0_arm64.whl", hash = "sha256:966fe0e9c67490071f14c0d2b1cb2dfb3023c5ce39457343931415f08382f2db", size = 4032100, upload-time = "2026-06-12T20:02:32.143Z" }, + { url = "https://files.pythonhosted.org/packages/09/41/3797cfaf69cae04a13ee78ebd83f0678d9c02b4779d21ce24445326f1a69/cryptography-49.0.0-cp311-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:36d1709f992593689b45bda411498d62c6e365f2ca00b84657d4dadd24de16db", size = 4692978, upload-time = "2026-06-12T20:01:21.305Z" }, + { url = "https://files.pythonhosted.org/packages/e6/8b/43011f7ebe515a8aa20d61f290a326cd890c2e738e16e59eaff8d9c3a412/cryptography-49.0.0-cp311-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:0e959b578856a3924bc0cbb710fc12c387b9412a951389f3ca61704a9e25f325", size = 4716422, upload-time = "2026-06-12T20:01:48.566Z" }, + { url = "https://files.pythonhosted.org/packages/4a/91/01ce7303a4579e6d3a6abef01bd322848e9ea7a219adcabc5048b9033571/cryptography-49.0.0-cp311-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:53ecee2e23f7169b6117e99fc8a944e5e50f79e69758a83b52a00cb98ab2b2d2", size = 4700503, upload-time = "2026-06-12T20:02:47.091Z" }, + { url = "https://files.pythonhosted.org/packages/62/99/a2c95cf8293f07491e9e27c20cc4dcd18176d944e674679adeb1d0173fd6/cryptography-49.0.0-cp311-abi3-manylinux_2_28_ppc64le.whl", hash = "sha256:2eda353d8a27bcbcaa4cbed18994a74ab4d19a2ca897db188ea269ab9b71419b", size = 5309779, upload-time = "2026-06-12T20:02:08.987Z" }, + { url = "https://files.pythonhosted.org/packages/20/2c/0622f20ff02b2ef32558733443805dc82fd4c275be01b2d19d14676f3a1b/cryptography-49.0.0-cp311-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:2afe9051da7ae7bd5905da5a949280c7d2bb75682e188f650a9d0f2756b834c6", size = 4749683, upload-time = "2026-06-12T20:02:03.335Z" }, + { url = "https://files.pythonhosted.org/packages/a3/5b/c5246635d5fd3b64e0d45ae10e99fd32fe9676a79915ccfe5a61ba9af1a5/cryptography-49.0.0-cp311-abi3-manylinux_2_31_armv7l.whl", hash = "sha256:0b82e28ee398a386f0807bba7884d30f25218855690f45115831bcce5d90822c", size = 4337874, upload-time = "2026-06-12T20:02:54.323Z" }, + { url = "https://files.pythonhosted.org/packages/6d/88/05563c7fe2e914e87d1a536d06fe83e66b4e1d95cb593e05aea375531da8/cryptography-49.0.0-cp311-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:ccac2bfebc306b862133e3bb71f3f6ee8bb525240089b2d952e4144b3a6d5da7", size = 4700283, upload-time = "2026-06-12T20:01:34.822Z" }, + { url = "https://files.pythonhosted.org/packages/c4/b6/d7696e4e890d6ae1469935164c9e5215c557671cb78d6e3f458ccceaa632/cryptography-49.0.0-cp311-abi3-manylinux_2_34_ppc64le.whl", hash = "sha256:d0527ce944105f257f605a827d6ebead966c752038b6e8656abb9c5edee6fc68", size = 5265844, upload-time = "2026-06-12T20:01:24.09Z" }, + { url = "https://files.pythonhosted.org/packages/a9/3c/f3ad17eecc1a57b0ba236dc01f90e783c51f4a2f35f64777cc4f47a184b2/cryptography-49.0.0-cp311-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:cbc77da8c523d5abd028635ba850a6966fcee2c82e2bf65a41d1d8afe0f98be9", size = 4749290, upload-time = "2026-06-12T20:01:30.848Z" }, + { url = "https://files.pythonhosted.org/packages/4f/01/339573cf1023163a400b0b5d16f6d507de413b9f60be6fd1b77feeaf6737/cryptography-49.0.0-cp311-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:b87e65d263b3e5d3bb92a57e2a6638e2f31110fa7aa890c7b2dbba42248d0a3f", size = 4834612, upload-time = "2026-06-12T20:01:29.246Z" }, + { url = "https://files.pythonhosted.org/packages/71/fd/577302e213a1be9468f92d1afef66fcf1ef83d516819d9992ca547f592bd/cryptography-49.0.0-cp311-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:66ec79c3904820572d7e987abdf304281f141d37ad9a489b8e97066e7b9b6459", size = 4980804, upload-time = "2026-06-12T20:01:42.853Z" }, + { url = "https://files.pythonhosted.org/packages/1f/09/f42b1d190c5ba75f72062a387f8030d1d75f6ab035788f1d9c4b01de6525/cryptography-49.0.0-cp311-abi3-win_amd64.whl", hash = "sha256:e5dfc1e64de5677cec922ffa8da89c546d0415bf6efdf081842e5d44c84e1f0e", size = 3810026, upload-time = "2026-06-12T20:02:39.262Z" }, + { url = "https://files.pythonhosted.org/packages/ec/9e/db72b3ae7fc9cfad53e630e56c6ae83b9b6ff0bf3718ffb8012d20b3aabf/cryptography-49.0.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:73a205dce83953d131a4aa1e0fd917a2fd1c5b1eef251e9d7152efefcbf5caf7", size = 4013892, upload-time = "2026-06-12T20:02:10.735Z" }, + { url = "https://files.pythonhosted.org/packages/86/12/c48a424f38db03027be9f7ed5c7dc5de9933dbee992865f98b13727a009d/cryptography-49.0.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:196ecd6a36e4e9aa10270393bb98d8df88fccee0bf1e5128b91ae4eb4375896d", size = 4678835, upload-time = "2026-06-12T20:02:48.743Z" }, + { url = "https://files.pythonhosted.org/packages/68/28/8a3ad4653662c93fc44dc4e5d8fd374c25c42e07b34bbfbadf49cf57a5a8/cryptography-49.0.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:7abcee80084cda3f7691f3eb1ce480d8df49cec637b429aa35986c1de71738aa", size = 4697239, upload-time = "2026-06-12T20:02:56.03Z" }, + { url = "https://files.pythonhosted.org/packages/a8/b2/2193fc74f81aee4f9b62733133b73b5176718932ed8f2e4b03fa040480a6/cryptography-49.0.0-cp314-cp314t-manylinux_2_28_aarch64.whl", hash = "sha256:4ae387c9cb68ea569ca17e490d66d8142b81c3cc814bf179974b7d146e490bbb", size = 4685593, upload-time = "2026-06-12T20:02:50.666Z" }, + { url = "https://files.pythonhosted.org/packages/47/f1/1d3eaa243bfc5de4a187b22aa8c048b3e4980bfbe830ac46e6bac2e66947/cryptography-49.0.0-cp314-cp314t-manylinux_2_28_ppc64le.whl", hash = "sha256:f37d847238971164fdbc68ade6f6574aecc9c0af714190e2083429ff68f4ce9d", size = 5289961, upload-time = "2026-06-12T20:01:46.468Z" }, + { url = "https://files.pythonhosted.org/packages/58/39/2d51306721330c486495853eda1c567880ff036de15a14c4b74f399934af/cryptography-49.0.0-cp314-cp314t-manylinux_2_28_x86_64.whl", hash = "sha256:c2bc30226390d60ea19d9f82b19db005fe0452154a23c1c410c12ea801e43561", size = 4731145, upload-time = "2026-06-12T20:02:16.832Z" }, + { url = "https://files.pythonhosted.org/packages/17/50/983e838c7fd0d87fd8c969bcdd328edaf5f756e38df5281637424c155873/cryptography-49.0.0-cp314-cp314t-manylinux_2_31_armv7l.whl", hash = "sha256:07cab27cc7b7e0fd28e5e26bb9eeedde5c135c868b46de4a27845abe94af6122", size = 4321719, upload-time = "2026-06-12T20:02:52.611Z" }, + { url = "https://files.pythonhosted.org/packages/a7/f5/8f571d7e27c55bce9f76f026143bcb1e040a4233149ecca0bea5fa5dd5f7/cryptography-49.0.0-cp314-cp314t-manylinux_2_34_aarch64.whl", hash = "sha256:b20133d204d2bb56ba047642199603876c872026ca53e79c35b83772ab2cc505", size = 4685209, upload-time = "2026-06-12T20:02:07.282Z" }, + { url = "https://files.pythonhosted.org/packages/e7/84/0e27016a6fc5a0886f797018b26aa42f40c09a82332bff77822a451deaaa/cryptography-49.0.0-cp314-cp314t-manylinux_2_34_ppc64le.whl", hash = "sha256:b970c6da94d5bb18629db453d14f2a1300f6bf59b61e9b82377931ef95504866", size = 5246285, upload-time = "2026-06-12T20:01:32.439Z" }, + { url = "https://files.pythonhosted.org/packages/11/2d/5e1fb307cb5931881516b464c98774b3f2c36b5d4bb9a2830253cf553cad/cryptography-49.0.0-cp314-cp314t-manylinux_2_34_x86_64.whl", hash = "sha256:d8ecde755e2e91bf773fc94e8c9d730cd7f2007004cb492263a794ec3899a1c8", size = 4730441, upload-time = "2026-06-12T20:02:01.469Z" }, + { url = "https://files.pythonhosted.org/packages/e4/c0/bff5a02ee731d207d6a1ed51732549d8c53d2bc8da1d10ec6f2844201d68/cryptography-49.0.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:e3fb64c420688e5319ae25113a354015abbd8dffbfbc41781a1ea66fc7622ac3", size = 4815869, upload-time = "2026-06-12T20:01:36.574Z" }, + { url = "https://files.pythonhosted.org/packages/b9/26/814681d14248d95d73d5c3eea0c39a94eb8302df966f670a2c60de90974b/cryptography-49.0.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:32703d93296f5c1f4b53349ad3a250c2cae0fdecd3a3dd5d47e616d8d616af27", size = 4960948, upload-time = "2026-06-12T20:02:18.688Z" }, + { url = "https://files.pythonhosted.org/packages/4c/fe/93ecac273d3738939d023612ad12cca9a3740a5345d69fda04134c43fd96/cryptography-49.0.0-cp314-cp314t-win_amd64.whl", hash = "sha256:33cd0565932807baddb67b96dbee92f2c374b5c89dee09fd74079aeb8c8dba61", size = 3799153, upload-time = "2026-06-12T20:01:39.059Z" }, + { url = "https://files.pythonhosted.org/packages/19/2a/5bb823f5bedcf80718cea7fbc95ec5515cca3769633c4b01a32be7f30e7c/cryptography-49.0.0-cp39-abi3-macosx_11_0_arm64.whl", hash = "sha256:ec5e529fb80935c94fe7b729f9972b50e351a0e6b50aa294fd5cabb109fcc29a", size = 4025947, upload-time = "2026-06-12T20:01:25.745Z" }, + { url = "https://files.pythonhosted.org/packages/3d/df/40577043ca124e17012f408ddddaeb213b856336ac82ddb3bc915f39e29f/cryptography-49.0.0-cp39-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:f78ff2c9ed8dc2d036b0f4d640e22522213d047c1b14e61205a7e55c80a494d4", size = 4692429, upload-time = "2026-06-12T20:01:53.628Z" }, + { url = "https://files.pythonhosted.org/packages/2c/99/2d13299eb3dd27b02dcfaafcc91d6b5cb3329f7cbd6d8f51921acd566c1a/cryptography-49.0.0-cp39-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:35b151772baff2c74cba7fa290ceaff4c3b11c0c881eb93eb5dbc05a7cfbba18", size = 4700968, upload-time = "2026-06-12T20:02:45.383Z" }, + { url = "https://files.pythonhosted.org/packages/a5/4d/9c0cd02f95e2602dd5e563da149ee0830abef3537be8b34dc56281ebe27a/cryptography-49.0.0-cp39-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:0f21641cf4b30fca7aee061ced0ec7ad7b073518088b7c9969a297c0ae796c69", size = 4697758, upload-time = "2026-06-12T20:01:41.13Z" }, + { url = "https://files.pythonhosted.org/packages/24/01/186c825898477d77e2324d5360fefe622ff1d8d1963ec0554e2cada8ec77/cryptography-49.0.0-cp39-abi3-manylinux_2_28_ppc64le.whl", hash = "sha256:9e82dcc8e56052715fb18b2429e3bca4823b1629136a2084fc45a9a5cecb9b64", size = 5298863, upload-time = "2026-06-12T20:02:24.579Z" }, + { url = "https://files.pythonhosted.org/packages/b8/7b/62cbbab75d0659865bf0273790031544a0b16c8072d258f9428dcd8190dc/cryptography-49.0.0-cp39-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:6f2debedf9ca60cf1d5bd466475638af5130f89965605cd818484d19987d3a21", size = 4735983, upload-time = "2026-06-12T20:01:50.14Z" }, + { url = "https://files.pythonhosted.org/packages/6c/72/3e798c064bc39e471008075d0f9bc9daf77a80879c092e4a8e170c585ed4/cryptography-49.0.0-cp39-abi3-manylinux_2_31_armv7l.whl", hash = "sha256:8c25ceb16df5b9435f3f6a9829204985b0e0cbee3b48aacd432c7d2c850b44d9", size = 4334173, upload-time = "2026-06-12T20:01:44.743Z" }, + { url = "https://files.pythonhosted.org/packages/f0/ee/6fca21d1ac73e06f8bef71940abfd4d2f6472b4bca284d770f32bd4086f6/cryptography-49.0.0-cp39-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:28d8b15e6275f12c8a207dc309dfa957903c927d08d0cc937ee3f63f200693cc", size = 4697298, upload-time = "2026-06-12T20:02:20.918Z" }, + { url = "https://files.pythonhosted.org/packages/67/d0/a5fcd3515f0bae49a7b6d0413cc1bdccdcc1fc0047037a0d480642cdc5d6/cryptography-49.0.0-cp39-abi3-manylinux_2_34_ppc64le.whl", hash = "sha256:6fc361c34fb6aac015ce19435876635e5c6d21db31998b0920f675f131e043b8", size = 5254338, upload-time = "2026-06-12T20:02:22.737Z" }, + { url = "https://files.pythonhosted.org/packages/a0/84/84fe36f19caf857d61cb7fc9c63035a47ffabd84ea12d1d393148efa3615/cryptography-49.0.0-cp39-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:2400ef9c9e2299a25614eb1dea3db54a69b1349efd043bfac9c67630d136df36", size = 4735650, upload-time = "2026-06-12T20:02:41.389Z" }, + { url = "https://files.pythonhosted.org/packages/6c/a0/db537264e234f7273a73ec020873d6d6b39dfd8a53db78b550ca8320440e/cryptography-49.0.0-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:67e1d20ad9ef3a563c59ef22e7a8a0b8210bd26604369ea4a30a7c66aefe504e", size = 4834820, upload-time = "2026-06-12T20:01:51.847Z" }, + { url = "https://files.pythonhosted.org/packages/93/77/8df9eb486495979bccecd1062e2eaf435250e84437040295b57d09048b0b/cryptography-49.0.0-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:42b0684e0e40cf26122427802486f6d93aea593612603a94fbf260c7eb1e9c1b", size = 4967968, upload-time = "2026-06-12T20:02:12.524Z" }, + { url = "https://files.pythonhosted.org/packages/c2/e6/f60198ea8d9dfa15fff9ed4ca02ce362f6eadd9ba757dcc50634c4257b63/cryptography-49.0.0-cp39-abi3-win_amd64.whl", hash = "sha256:026ac7423e6fa66872d3bf889be5974507da3944f866f704fa200eadacd00001", size = 3785547, upload-time = "2026-06-12T20:02:26.847Z" }, + { url = "https://files.pythonhosted.org/packages/63/d3/4a83af35d65e3fad632c926fad684c193ea4398569ccb0bbbc7fe8f5dc9a/cryptography-49.0.0-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:fc1e275c2f1d97b1a6450b8b0ea3ebfa6e087a611c2b26cb2404d48588abab7b", size = 3993685, upload-time = "2026-06-12T20:02:14.883Z" }, + { url = "https://files.pythonhosted.org/packages/d6/a7/f9dac0ab7f80368c56993a7bf638ef9935f825c91902798481fac0898138/cryptography-49.0.0-pp311-pypy311_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:c83782480a4a9da4d0feb51950131ba32e12e70813848b3343f6e18c28a66838", size = 4676239, upload-time = "2026-06-12T20:02:28.793Z" }, + { url = "https://files.pythonhosted.org/packages/d7/70/2ba3769dd0ae167e2f33dfa9592d45db6ff9a61d62ca1a5b3d1bdd09068f/cryptography-49.0.0-pp311-pypy311_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:b39efa323140595abd3ecca8529d321ae50f55f3aa3ba9cc81ea56a6011953d5", size = 4715584, upload-time = "2026-06-12T20:01:27.495Z" }, + { url = "https://files.pythonhosted.org/packages/94/64/2923570ac1c0bd3a737aa366ac3abbbbde273042308b8cde95e2364a6e6a/cryptography-49.0.0-pp311-pypy311_pp73-manylinux_2_34_aarch64.whl", hash = "sha256:b47db11c2c3525083296069b98ac5221907455e989ae0c2e3008bde851921615", size = 4675885, upload-time = "2026-06-12T20:01:55.49Z" }, + { url = "https://files.pythonhosted.org/packages/ab/f8/614dc7e051418cfe53d55173c1e24c6b0085e89996fe90508c2fdf769aef/cryptography-49.0.0-pp311-pypy311_pp73-manylinux_2_34_x86_64.whl", hash = "sha256:084ef1af862eb07ec46d25f68689f2102a9fc0e05ce7b80f14f5fe51e4eef0f6", size = 4715449, upload-time = "2026-06-12T20:02:05.469Z" }, + { url = "https://files.pythonhosted.org/packages/aa/50/a9caea39ad19c431c1a3f8a31114df65b260cdfe67786b6c7e7c040c4c44/cryptography-49.0.0-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:be9fcb48a55f023493482827d4f459bd263cc20efde64f204b97c123201850c6", size = 3783731, upload-time = "2026-06-12T20:02:43.319Z" }, ] [[package]] @@ -992,11 +1006,11 @@ wheels = [ [[package]] name = "docutils" -version = "0.22.4" +version = "0.23" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/ae/b6/03bb70946330e88ffec97aefd3ea75ba575cb2e762061e0e62a213befee8/docutils-0.22.4.tar.gz", hash = "sha256:4db53b1fde9abecbb74d91230d32ab626d94f6badfc575d6db9194a49df29968", size = 2291750, upload-time = "2025-12-18T19:00:26.443Z" } +sdist = { url = "https://files.pythonhosted.org/packages/39/a4/5180d9afc57e8fca05601dd652bdff19604c218814037fe90ffc7625a50a/docutils-0.23.tar.gz", hash = "sha256:746f5060322511280a1e50eb76846ed6bf2342984b2ac04dc42caa1a8d78799e", size = 2303823, upload-time = "2026-05-27T17:41:06.934Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/02/10/5da547df7a391dcde17f59520a231527b8571e6f46fc8efb02ccb370ab12/docutils-0.22.4-py3-none-any.whl", hash = "sha256:d0013f540772d1420576855455d050a2180186c91c15779301ac2ccb3eeb68de", size = 633196, upload-time = "2025-12-18T19:00:18.077Z" }, + { url = "https://files.pythonhosted.org/packages/32/91/30151a39f7570f448ed84529390628a651d7f27c87d73c9b887f8189695e/docutils-0.23-py3-none-any.whl", hash = "sha256:25d013af9bf23bc1c7b2b093dff4208166c53a94786c9e447808335ef1185fea", size = 634701, upload-time = "2026-05-27T17:40:58.442Z" }, ] [[package]] @@ -1022,7 +1036,7 @@ wheels = [ [[package]] name = "fastapi" -version = "0.136.0" +version = "0.137.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "annotated-doc" }, @@ -1031,9 +1045,9 @@ dependencies = [ { name = "typing-extensions" }, { name = "typing-inspection" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/4e/d9/e66315807e41e69e7f6a1b42a162dada2f249c5f06ad3f1a95f84ab336ef/fastapi-0.136.0.tar.gz", hash = "sha256:cf08e067cc66e106e102d9ba659463abfac245200752f8a5b7b1e813de4ff73e", size = 396607, upload-time = "2026-04-16T11:47:13.623Z" } +sdist = { url = "https://files.pythonhosted.org/packages/d5/b1/e5b92c59d2c37817e77c1a8c2fc1f79cdcc04c68253e5406b43e3204cba7/fastapi-0.137.1.tar.gz", hash = "sha256:822360704230d9533d8d9475399613525968aa2f0b5bd2a3ccc9f18c88fd541c", size = 408293, upload-time = "2026-06-15T11:28:20.79Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/26/a3/0bd5f0cdb0bbc92650e8dc457e9250358411ee5d1b65e42b6632387daf81/fastapi-0.136.0-py3-none-any.whl", hash = "sha256:8793d44ec7378e2be07f8a013cf7f7aa47d6327d0dfe9804862688ec4541a6b4", size = 117556, upload-time = "2026-04-16T11:47:11.922Z" }, + { url = "https://files.pythonhosted.org/packages/da/35/380b9a5922f4340e51c309cde09e5bd32e62f02302971bee30dc15aa0624/fastapi-0.137.1-py3-none-any.whl", hash = "sha256:64f6983c59e45c4b9fdc44e57cb8035c2451ee91ea8e8ec042aca37de7cf6b69", size = 121877, upload-time = "2026-06-15T11:28:19.523Z" }, ] [[package]] @@ -1101,11 +1115,11 @@ wheels = [ [[package]] name = "filelock" -version = "3.29.0" +version = "3.29.4" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/b5/fe/997687a931ab51049acce6fa1f23e8f01216374ea81374ddee763c493db5/filelock-3.29.0.tar.gz", hash = "sha256:69974355e960702e789734cb4871f884ea6fe50bd8404051a3530bc07809cf90", size = 57571, upload-time = "2026-04-19T15:39:10.068Z" } +sdist = { url = "https://files.pythonhosted.org/packages/e6/dc/be6cbe99670cd6e4ad387123647cb08e0c32975e223f82551e914c5568a6/filelock-3.29.4.tar.gz", hash = "sha256:10cdb3656fc44541cdf30652a93fb10ec6b05325620eb316bd26893e4201538a", size = 63028, upload-time = "2026-06-13T16:12:00.744Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/81/47/dd9a212ef6e343a6857485ffe25bba537304f1913bdbed446a23f7f592e1/filelock-3.29.0-py3-none-any.whl", hash = "sha256:96f5f6344709aa1572bbf631c640e4ebeeb519e08da902c39a001882f30ac258", size = 39812, upload-time = "2026-04-19T15:39:08.752Z" }, + { url = "https://files.pythonhosted.org/packages/13/37/a065dc3bd6e49423a6532c642ca7378d3f467b1ef44c2800c937af7f9739/filelock-3.29.4-py3-none-any.whl", hash = "sha256:dac1648087d5115554850d113e7dd8c83ab2d38e3435dde2d4f163847e57b767", size = 42757, upload-time = "2026-06-13T16:11:59.582Z" }, ] [[package]] @@ -1127,15 +1141,16 @@ wheels = [ [[package]] name = "flask-cors" -version = "6.0.2" +version = "6.0.5" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "flask" }, + { name = "typing-extensions", marker = "python_full_version < '3.11'" }, { name = "werkzeug" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/70/74/0fc0fa68d62f21daef41017dafab19ef4b36551521260987eb3a5394c7ba/flask_cors-6.0.2.tar.gz", hash = "sha256:6e118f3698249ae33e429760db98ce032a8bf9913638d085ca0f4c5534ad2423", size = 13472, upload-time = "2025-12-12T20:31:42.861Z" } +sdist = { url = "https://files.pythonhosted.org/packages/47/03/4e464a50860f9adf08b5c1d3479cb8ea1f12af2aa69535c7042c6e628135/flask_cors-6.0.5.tar.gz", hash = "sha256:30c5031552cd59f620ac0c8211dac45b345d3b2df310e7721879e4f46ef9c601", size = 101386, upload-time = "2026-06-08T20:20:17.765Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/4f/af/72ad54402e599152de6d067324c46fe6a4f531c7c65baf7e96c63db55eaf/flask_cors-6.0.2-py3-none-any.whl", hash = "sha256:e57544d415dfd7da89a9564e1e3a9e515042df76e12130641ca6f3f2f03b699a", size = 13257, upload-time = "2025-12-12T20:31:41.3Z" }, + { url = "https://files.pythonhosted.org/packages/49/55/5bb1a2d918e9f02f131e47a59032bae70e48050e986e941511fd737a935c/flask_cors-6.0.5-py3-none-any.whl", hash = "sha256:68fcf75693e961f3af26683b23c4b9a8fb6b64de17d20d0c37b95e8de7ab2ed8", size = 16692, upload-time = "2026-06-08T20:20:16.247Z" }, ] [[package]] @@ -1261,16 +1276,16 @@ wheels = [ [[package]] name = "fsspec" -version = "2026.3.0" +version = "2026.4.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/e1/cf/b50ddf667c15276a9ab15a70ef5f257564de271957933ffea49d2cdbcdfb/fsspec-2026.3.0.tar.gz", hash = "sha256:1ee6a0e28677557f8c2f994e3eea77db6392b4de9cd1f5d7a9e87a0ae9d01b41", size = 313547, upload-time = "2026-03-27T19:11:14.892Z" } +sdist = { url = "https://files.pythonhosted.org/packages/d5/8d/1c51c094345df128ca4a990d633fe1a0ff28726c9e6b3c41ba65087bba1d/fsspec-2026.4.0.tar.gz", hash = "sha256:301d8ac70ae90ef3ad05dcf94d6c3754a097f9b5fe4667d2787aa359ec7df7e4", size = 312760, upload-time = "2026-04-29T20:42:38.635Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/d5/1f/5f4a3cd9e4440e9d9bc78ad0a91a1c8d46b4d429d5239ebe6793c9fe5c41/fsspec-2026.3.0-py3-none-any.whl", hash = "sha256:d2ceafaad1b3457968ed14efa28798162f1638dbb5d2a6868a2db002a5ee39a4", size = 202595, upload-time = "2026-03-27T19:11:13.595Z" }, + { url = "https://files.pythonhosted.org/packages/d5/0c/043d5e551459da400957a1395e0febbf771446ff34291afcbe3d8be2a279/fsspec-2026.4.0-py3-none-any.whl", hash = "sha256:11ef7bb35dab8a394fde6e608221d5cf3e8499401c249bebaeaad760a1a8dec2", size = 203402, upload-time = "2026-04-29T20:42:36.842Z" }, ] [[package]] name = "google-adk" -version = "1.31.1" +version = "1.35.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "aiosqlite" }, @@ -1319,14 +1334,14 @@ dependencies = [ { name = "watchdog" }, { name = "websockets" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/9b/f7/e2371e8a871202f47f8911992da7daf8623dd61e714e0af5c6fec019ba67/google_adk-1.31.1.tar.gz", hash = "sha256:e56416264f62e931709da6262bc9fe05140faeb7a889a2fe8f5684617e8a05c3", size = 2408228, upload-time = "2026-04-21T02:06:48.623Z" } +sdist = { url = "https://files.pythonhosted.org/packages/3a/a7/8cba69e86af4f25b73f0bd4cbce9b0ca990a6a779cedee9a242264fca259/google_adk-1.35.0.tar.gz", hash = "sha256:c3f36447d29c1a3400ba45b344f232d857db9b18d1224517a00b267da1f51dff", size = 2432700, upload-time = "2026-06-10T05:32:34.778Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/c8/02/6e7b88b122708569004ac024ec7f6773cc9d10ce1b086a4a6668a95ca142/google_adk-1.31.1-py3-none-any.whl", hash = "sha256:8f5d9c67c9a87832c2fe581bd4b1248dddf8964c98351a38e2663f0999bc7209", size = 2850553, upload-time = "2026-04-21T02:06:45.992Z" }, + { url = "https://files.pythonhosted.org/packages/2b/9a/dc5192a79bea70730c9261b8ca54ee4103265a260444d3bffdd2eab47876/google_adk-1.35.0-py3-none-any.whl", hash = "sha256:f4c10f86c37e4fba157868d6884d4493bbb88a53fea00004d900dc03a3347f85", size = 2877569, upload-time = "2026-06-10T05:32:37.085Z" }, ] [[package]] name = "google-api-core" -version = "2.30.3" +version = "2.31.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "google-auth" }, @@ -1335,9 +1350,9 @@ dependencies = [ { name = "protobuf" }, { name = "requests" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/16/ce/502a57fb0ec752026d24df1280b162294b22a0afb98a326084f9a979138b/google_api_core-2.30.3.tar.gz", hash = "sha256:e601a37f148585319b26db36e219df68c5d07b6382cff2d580e83404e44d641b", size = 177001, upload-time = "2026-04-10T00:41:28.035Z" } +sdist = { url = "https://files.pythonhosted.org/packages/c6/22/155cadf1d49272a9cf48f3168c0f3874fa13397297e611a5ea00cd093880/google_api_core-2.31.0.tar.gz", hash = "sha256:2be84ee0f584c48e6bde1b36766e23348b361fb7e55e56135fc76ce1c397f9c2", size = 176492, upload-time = "2026-06-03T14:52:17.257Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/03/15/e56f351cf6ef1cfea58e6ac226a7318ed1deb2218c4b3cc9bd9e4b786c5a/google_api_core-2.30.3-py3-none-any.whl", hash = "sha256:a85761ba72c444dad5d611c2220633480b2b6be2521eca69cca2dbb3ffd6bfe8", size = 173274, upload-time = "2026-04-09T22:57:16.198Z" }, + { url = "https://files.pythonhosted.org/packages/86/40/9bdbb60b03a332bd45acb8703da08bbc27d991d35286b62e42acc86d243a/google_api_core-2.31.0-py3-none-any.whl", hash = "sha256:ef79fb3784c71cbac89cbd03301ba0c8fb8ad2aa95d7f9204dd9628f7adf59ab", size = 173102, upload-time = "2026-06-03T14:51:26.729Z" }, ] [package.optional-dependencies] @@ -1348,7 +1363,7 @@ grpc = [ [[package]] name = "google-api-python-client" -version = "2.194.0" +version = "2.197.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "google-api-core" }, @@ -1357,22 +1372,22 @@ dependencies = [ { name = "httplib2" }, { name = "uritemplate" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/60/ab/e83af0eb043e4ccc49571ca7a6a49984e9d00f4e9e6e6f1238d60bc84dce/google_api_python_client-2.194.0.tar.gz", hash = "sha256:db92647bd1a90f40b79c9618461553c2b20b6a43ce7395fa6de07132dc14f023", size = 14443469, upload-time = "2026-04-08T23:07:35.757Z" } +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/b0/34/5a624e49f179aa5b0cb87b2ce8093960299030ff40423bfbde09360eb908/google_api_python_client-2.194.0-py3-none-any.whl", hash = "sha256:61eaaac3b8fc8fdf11c08af87abc3d1342d1b37319cc1b57405f86ef7697e717", size = 15016514, upload-time = "2026-04-08T23:07:33.093Z" }, + { 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" }, ] [[package]] name = "google-auth" -version = "2.49.2" +version = "2.54.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "cryptography" }, { name = "pyasn1-modules" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/c6/fc/e925290a1ad95c975c459e2df070fac2b90954e13a0370ac505dff78cb99/google_auth-2.49.2.tar.gz", hash = "sha256:c1ae38500e73065dcae57355adb6278cf8b5c8e391994ae9cbadbcb9631ab409", size = 333958, upload-time = "2026-04-10T00:41:21.888Z" } +sdist = { url = "https://files.pythonhosted.org/packages/15/f6/494e18317546d7def90c957b71d68b025d24f0e22e486c2606bc57765c48/google_auth-2.54.0.tar.gz", hash = "sha256:130f6fd5e3f497fdad897a23ed9489973437edf561238c4b92a4d02c435f8af9", size = 343161, upload-time = "2026-06-12T18:03:17.606Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/73/76/d241a5c927433420507215df6cac1b1fa4ac0ba7a794df42a84326c68da8/google_auth-2.49.2-py3-none-any.whl", hash = "sha256:c2720924dfc82dedb962c9f52cabb2ab16714fd0a6a707e40561d217574ed6d5", size = 240638, upload-time = "2026-04-10T00:41:14.501Z" }, + { url = "https://files.pythonhosted.org/packages/70/c5/d53bddd2c0949833fcb4ea06f9d5dd1c40575a1a4214cd1021eff57ba301/google_auth-2.54.0-py3-none-any.whl", hash = "sha256:784e9837f92244141250470d47c893df50cbab485ce491aca5e9deb558ad2b48", size = 249878, upload-time = "2026-06-12T18:02:57.58Z" }, ] [package.optional-dependencies] @@ -1385,22 +1400,23 @@ requests = [ [[package]] name = "google-auth-httplib2" -version = "0.3.1" +version = "0.4.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "google-auth" }, { name = "httplib2" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/ed/99/107612bef8d24b298bb5a7c8466f908ecda791d43f9466f5c3978f5b24c1/google_auth_httplib2-0.3.1.tar.gz", hash = "sha256:0af542e815784cb64159b4469aa5d71dd41069ba93effa006e1916b1dcd88e55", size = 11152, upload-time = "2026-03-30T22:50:26.766Z" } +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/e9/93afb14d23a949acaa3f4e7cc51a0024671174e116e35f42850764b99634/google_auth_httplib2-0.3.1-py3-none-any.whl", hash = "sha256:682356a90ef4ba3d06548c37e9112eea6fc00395a11b0303a644c1a86abc275c", size = 9534, upload-time = "2026-03-30T22:49:03.384Z" }, + { 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" +version = "1.157.0" source = { registry = "https://pypi.org/simple" } dependencies = [ + { name = "certifi" }, { name = "docstring-parser" }, { name = "google-api-core", extra = ["grpc"] }, { name = "google-auth" }, @@ -1414,9 +1430,9 @@ dependencies = [ { 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" } +sdist = { url = "https://files.pythonhosted.org/packages/e0/d9/e2a5f5a8535bbc8f68729796f3fc2d68d59a72818fb44f6544edbc2592e4/google_cloud_aiplatform-1.157.0.tar.gz", hash = "sha256:ce8413ed3584c4896f7656b663214c24e91c2c89426f1c91fbd1d220ffda23af", size = 11064992, upload-time = "2026-06-10T00:19:33.643Z" } 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" }, + { url = "https://files.pythonhosted.org/packages/e3/82/3ec2ba56dc1fa71ef783348a0c519721879dbc8f1e568534e6d4b4856ccd/google_cloud_aiplatform-1.157.0-py2.py3-none-any.whl", hash = "sha256:0ca499ac5648988916fc089f9e94bd99667eefba13f6936475247f4a0bf86634", size = 9200777, upload-time = "2026-06-10T00:19:30.181Z" }, ] [package.optional-dependencies] @@ -1437,7 +1453,7 @@ agent-engines = [ [[package]] name = "google-cloud-appengine-logging" -version = "1.9.0" +version = "1.10.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "google-api-core", extra = ["grpc"] }, @@ -1446,22 +1462,22 @@ dependencies = [ { name = "proto-plus" }, { name = "protobuf" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/bc/02/800897064ca6f1a26835cdf23939c4b93e38a30f3fb5c7cec7c01ae2edc2/google_cloud_appengine_logging-1.9.0.tar.gz", hash = "sha256:ff397f0bbc1485f979ab45767c38e0f676c9598c97c384f7412216e6ea22f805", size = 17963, upload-time = "2026-03-30T22:51:33.556Z" } +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/56/4a/304d42664ab2afbe7be39559c9eb3f81dd06e7ac9284f9f36f726f15939d/google_cloud_appengine_logging-1.9.0-py3-none-any.whl", hash = "sha256:bbf3a7e4dc171678f7f481259d1f68c3ae7d337530f1f2361f8a0b214dbcfe36", size = 18333, upload-time = "2026-03-30T22:49:39.045Z" }, + { 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.5.0" +version = "0.6.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "googleapis-common-protos" }, { name = "protobuf" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/be/9f/3aedb3ce1d58c58ec7dd06b3964836eabfd17a16a95b60c8f609c0afff7f/google_cloud_audit_log-0.5.0.tar.gz", hash = "sha256:3b32d5e77db634c46fbd6c5e01f5bda836f420dfbb21d730501c75e9fab4e4a4", size = 44670, upload-time = "2026-03-30T22:50:42.295Z" } +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/64/40/79fa535b6e3321d5e07b2a9ab4bb63860d3fea12230c765837881348003c/google_cloud_audit_log-0.5.0-py3-none-any.whl", hash = "sha256:3f4632f25bf67446fa9085c52868f3cb42fb1afbab9489ba8978e30991afc79f", size = 44862, upload-time = "2026-03-30T22:47:57.533Z" }, + { 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]] @@ -1484,7 +1500,7 @@ wheels = [ [[package]] name = "google-cloud-bigquery-storage" -version = "2.37.0" +version = "2.39.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "google-api-core", extra = ["grpc"] }, @@ -1493,14 +1509,14 @@ dependencies = [ { name = "proto-plus" }, { name = "protobuf" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/13/31/5c6fa9e7b8e266a765ec80d13a2b2852cb0a6d3733572e7dbdc0cb39003c/google_cloud_bigquery_storage-2.37.0.tar.gz", hash = "sha256:f88ee7f1e49db1e639da3d9a8b79835ca4bc47afbb514fb2adfc0ccb41a7fd97", size = 310578, upload-time = "2026-03-30T22:51:13.418Z" } +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/74/0e/2950d4d0160300f51c7397a080b1685d3e25b40badb2c96f03d58d0ee868/google_cloud_bigquery_storage-2.37.0-py3-none-any.whl", hash = "sha256:1e319c27ef60fc31030f6e0b52e5e891e1cdd50551effe8c6f673a4c3c56fcb6", size = 306678, upload-time = "2026-03-30T22:47:42.333Z" }, + { 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.36.0" +version = "2.38.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "google-api-core", extra = ["grpc"] }, @@ -1508,30 +1524,31 @@ dependencies = [ { 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/52/f5/ad2a48306a7e8d5e47b5203703ce9c343389e60f025b5ea3f0c62ba92129/google_cloud_bigtable-2.36.0.tar.gz", hash = "sha256:d5987733c2f60c739f93f259d2037858411cc994ac37cdfbccb6bb159f3ca43e", size = 796035, upload-time = "2026-04-02T21:23:33.248Z" } +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/d1/19/1cc695fa8489ef446a70ee9e983c12f4b47e0649005758035530eaec4b1c/google_cloud_bigtable-2.36.0-py3-none-any.whl", hash = "sha256:21b2f41231b7368a550b44d5b493b811b3507fcb23eb26d00005cd3f205f2207", size = 552799, upload-time = "2026-04-02T21:23:20.475Z" }, + { 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.5.1" +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/dc/24/6ca08b0a03c7b0c620427503ab00353a4ae806b848b93bcea18b6b76fde6/google_cloud_core-2.5.1.tar.gz", hash = "sha256:3dc94bdec9d05a31d9f355045ed0f369fbc0d8c665076c734f065d729800f811", size = 36078, upload-time = "2026-03-30T22:50:08.057Z" } +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/73/d9/5bb050cb32826466aa9b25f79e2ca2879fe66cb76782d4ed798dd7506151/google_cloud_core-2.5.1-py3-none-any.whl", hash = "sha256:ea62cdf502c20e3e14be8a32c05ed02113d7bef454e40ff3fab6fe1ec9f1f4e7", size = 29452, upload-time = "2026-03-30T22:48:31.567Z" }, + { 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.18.0" +version = "2.20.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "google-api-core", extra = ["grpc"] }, @@ -1541,9 +1558,9 @@ dependencies = [ { name = "proto-plus" }, { name = "protobuf" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/ee/2b/c390bbe1f68015ea57eb9352e90ebbbf459c3139d9e5a8e6faa0b1abdc6e/google_cloud_dataplex-2.18.0.tar.gz", hash = "sha256:ae3f7f1b5c64675e8a4b66725d404eec864e12d29051323a2232bdb05797016d", size = 881810, upload-time = "2026-03-30T22:49:53.747Z" } +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/b2/9a/8b096a6d772b7abf1c97dfbce17d47ba1d8a944ce8d7a239fd300a3ad8ae/google_cloud_dataplex-2.18.0-py3-none-any.whl", hash = "sha256:6e4ec95b24f64e95cec5f3753fbe7419f78ddb8b1ba90f8d955bc7613bb90764", size = 675743, upload-time = "2026-03-30T20:02:27.12Z" }, + { 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]] @@ -1563,7 +1580,7 @@ wheels = [ [[package]] name = "google-cloud-iam" -version = "2.22.0" +version = "2.23.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "google-api-core", extra = ["grpc"] }, @@ -1573,14 +1590,14 @@ dependencies = [ { name = "proto-plus" }, { name = "protobuf" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/62/e5/07d4f1daf85a2a0bd9f78ad865ea678d7b4e1227ed76f671c7167aae147f/google_cloud_iam-2.22.0.tar.gz", hash = "sha256:203ddfece17e014ee4fbc5c3244daa14a88b7ee57c8e3a7622d0f2a1a3b8d7f3", size = 502498, upload-time = "2026-03-30T22:51:28.878Z" } +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/aa/a8/d721ea11d0eb93803d14cb2e90d0442bb3b269a82f7cb5faff2b98022039/google_cloud_iam-2.22.0-py3-none-any.whl", hash = "sha256:c443b34b5a6a9e51d32cee397879bb781b900af68937c67a275def23bbc025f3", size = 463425, upload-time = "2026-03-30T20:02:42.967Z" }, + { 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.15.0" +version = "3.16.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "google-api-core", extra = ["grpc"] }, @@ -1594,14 +1611,14 @@ dependencies = [ { name = "proto-plus" }, { name = "protobuf" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/99/06/253e9795a5877f35183a7175977ca47a17255fe0c8487155f48b86c83f3e/google_cloud_logging-3.15.0.tar.gz", hash = "sha256:72168a1e98bbfc27c75f0b8f630a7f5d786065f3f1f7e9e53d2d787a03693a4a", size = 294881, upload-time = "2026-03-26T22:18:36.947Z" } +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/86/0c/fc1a0c57f95d21559ed13e381d9024e9ee9d521489707573fd10af856545/google_cloud_logging-3.15.0-py3-none-any.whl", hash = "sha256:7dcc67434c4e7181510c133d5ac8fd4ce60c23fa4158661f67e54bf440c32450", size = 234212, upload-time = "2026-03-26T22:15:16.404Z" }, + { 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.30.0" +version = "2.31.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "google-api-core", extra = ["grpc"] }, @@ -1610,29 +1627,29 @@ dependencies = [ { name = "proto-plus" }, { name = "protobuf" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/eb/3f/7bc306ebb006114f58fb9143aec91e1b014a11577350d8bbd6bbc38389f9/google_cloud_monitoring-2.30.0.tar.gz", hash = "sha256:a9530aa9aa246c490810dfa7be32d67e8340d19108acc99cbc02d1ed494fba76", size = 407108, upload-time = "2026-03-26T22:17:10.365Z" } +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/ad/c8/666c21c470b9d6fd62ac9ee74dc265419975228f9b16f8ad72ec22e8d98b/google_cloud_monitoring-2.30.0-py3-none-any.whl", hash = "sha256:2729f3b88a4798b7757b1d9d31b6cb562bb3544e8173765e4e5cd44d8685b1ed", size = 391367, upload-time = "2026-03-26T22:15:04.088Z" }, + { 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.37.0" +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", marker = "python_full_version < '3.14'" }, + { name = "grpcio" }, { name = "grpcio-status" }, { name = "opentelemetry-api" }, { name = "opentelemetry-sdk" }, { name = "proto-plus" }, { name = "protobuf" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/50/89/558c48382d6875335ea6cd7f6409acfbf256b9f7fbc2ad1c19976aabdb1f/google_cloud_pubsub-2.37.0.tar.gz", hash = "sha256:7c5ba9beb5236e2b83c091dd6171423dc7d6d0e989391bd09f60dbd242b29f10", size = 403391, upload-time = "2026-04-10T00:41:17.799Z" } +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/64/f1/bb7162ec50971b1d252e6837d05f64f185d5cfe4e08de8f706e363c305d9/google_cloud_pubsub-2.37.0-py3-none-any.whl", hash = "sha256:dd912422cf66e4ffb423b0d5391ca81bdfa408eb0f21f57adecdb6fb3b1e0bb1", size = 325136, upload-time = "2026-04-10T00:41:01.391Z" }, + { 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]] @@ -1654,7 +1671,7 @@ wheels = [ [[package]] name = "google-cloud-secret-manager" -version = "2.27.0" +version = "2.29.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "google-api-core", extra = ["grpc"] }, @@ -1664,21 +1681,23 @@ dependencies = [ { name = "proto-plus" }, { name = "protobuf" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/6d/df/fbea0536e1baa6ea2239fdd19e9e22c9d64c8e26a0f3921596ecc0e5397d/google_cloud_secret_manager-2.27.0.tar.gz", hash = "sha256:6af864c252bd3c11db7bb02b80cb0b14a8c9a33fc7ec4d6f245f33d8ce1f7cd1", size = 279769, upload-time = "2026-03-26T22:17:15.271Z" } +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/1f/4b/6dd1e2efd9a2e73aa847fd455a1ce375d8d3cba1a2c4f7fd69f9bf0b9dce/google_cloud_secret_manager-2.27.0-py3-none-any.whl", hash = "sha256:e5540bece65a3ad720146f3b438973faf9315109b3ffa012a58711843047a3dc", size = 225577, upload-time = "2026-03-26T22:15:19.622Z" }, + { 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.65.0" +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" }, @@ -1688,14 +1707,14 @@ dependencies = [ { name = "protobuf" }, { name = "sqlparse" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/0d/90/b3e3c9c7b1a5ebc76d780fcda58e3a27208d5a10c6c5b78fab64dc5ea5f9/google_cloud_spanner-3.65.0.tar.gz", hash = "sha256:434139bd1439528398cd2a96e390a57182420747c214a33f317bbac64afd9c5c", size = 889154, upload-time = "2026-04-13T22:14:34.416Z" } +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/be/c6/0f0806253de7e1ef5943a9e30df7798c0f5dd6e840707a899975e17d4c60/google_cloud_spanner-3.65.0-py3-none-any.whl", hash = "sha256:67ca892698d9530d10c682be7c38265089088b57272af3e57f1ea7afb9e88eff", size = 614036, upload-time = "2026-04-13T22:14:32.533Z" }, + { 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.38.0" +version = "2.40.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "google-api-core", extra = ["grpc"] }, @@ -1704,14 +1723,14 @@ dependencies = [ { name = "proto-plus" }, { name = "protobuf" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/21/1f/d0122ad8af8c0608fb3168bd5030e62ce0a1fcc09c730487bc8be541874a/google_cloud_speech-2.38.0.tar.gz", hash = "sha256:1854b51cbb7957273b6ba61f4a6cf49dec8d09ec450991587897e50267eaca51", size = 406015, upload-time = "2026-03-26T22:18:54.434Z" } +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/01/96/008365cddc78720d65475091be929466fb16c62b47283546f8eab5ff4445/google_cloud_speech-2.38.0-py3-none-any.whl", hash = "sha256:dbccb340a750a409b0e70c48c16c8d7d5d48a87c70cce2add50f3d571f5375a0", size = 346013, upload-time = "2026-03-26T22:13:50.88Z" }, + { 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.10.1" +version = "3.12.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "google-api-core" }, @@ -1721,9 +1740,9 @@ dependencies = [ { name = "google-resumable-media" }, { name = "requests" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/4c/47/205eb8e9a1739b5345843e5a425775cbdc472cc38e7eda082ba5b8d02450/google_cloud_storage-3.10.1.tar.gz", hash = "sha256:97db9aa4460727982040edd2bd13ff3d5e2260b5331ad22895802da1fc2a5286", size = 17309950, upload-time = "2026-03-23T09:35:23.409Z" } +sdist = { url = "https://files.pythonhosted.org/packages/58/72/86f94e1639a8bcd9d33e8e01b49afcaa1c3a13bda7683c681717e0901e15/google_cloud_storage-3.12.0.tar.gz", hash = "sha256:03ae9847c6babb368f35f054126b8a08cbc0e3266efb990eb17b9926a45cf3be", size = 17338620, upload-time = "2026-06-12T18:03:29.215Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/ad/ff/ca9ab2417fa913d75aae38bf40bf856bb2749a604b2e0f701b37cfcd23cc/google_cloud_storage-3.10.1-py3-none-any.whl", hash = "sha256:a72f656759b7b99bda700f901adcb3425a828d4a29f911bc26b3ea79c5b1217f", size = 324453, upload-time = "2026-03-23T09:35:21.368Z" }, + { url = "https://files.pythonhosted.org/packages/1b/bd/a89eaebd2f9db5f92ddcc8e4f23c266be1dbd11058bb83451d8dd029f34c/google_cloud_storage-3.12.0-py3-none-any.whl", hash = "sha256:3880773754ddf7c27567b04e2a4d193950b6b99429f37b9097d873686e95b09c", size = 340605, upload-time = "2026-06-12T18:03:12.677Z" }, ] [[package]] @@ -1779,7 +1798,7 @@ wheels = [ [[package]] name = "google-genai" -version = "1.73.1" +version = "1.75.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "anyio" }, @@ -1793,21 +1812,21 @@ dependencies = [ { name = "typing-extensions" }, { name = "websockets" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/3d/d8/40f5f107e5a2976bbac52d421f04d14fc221b55a8f05e66be44b2f739fe6/google_genai-1.73.1.tar.gz", hash = "sha256:b637e3a3b9e2eccc46f27136d470165803de84eca52abfed2e7352081a4d5a15", size = 530998, upload-time = "2026-04-14T21:06:19.153Z" } +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/65/af/508e0528015240d710c6763f7c89ff44fab9a94a80b4377e265d692cbfd6/google_genai-1.73.1-py3-none-any.whl", hash = "sha256:af2d2287d25e42a187de19811ef33beb2e347c7e2bdb4dc8c467d78254e43a2c", size = 783595, upload-time = "2026-04-14T21:06:17.464Z" }, + { 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.8.2" +version = "2.10.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "google-crc32c" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/3f/d1/b1ea14b93b6b78f57fc580125de44e9f593ab88dd2460f1a8a8d18f74754/google_resumable_media-2.8.2.tar.gz", hash = "sha256:f3354a182ebd193ae3f42e3ef95e6c9b10f128320de23ac7637236713b1acd70", size = 2164510, upload-time = "2026-03-30T23:34:25.369Z" } +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" } wheels = [ - { url = "https://files.pythonhosted.org/packages/5e/f8/50bfaf4658431ff9de45c5c3935af7ab01157a4903c603cd0eee6e78e087/google_resumable_media-2.8.2-py3-none-any.whl", hash = "sha256:82b6d8ccd11765268cdd2a2123f417ec806b8eef3000a9a38dfe3033da5fb220", size = 81511, upload-time = "2026-03-30T23:34:09.671Z" }, + { 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" }, ] [[package]] @@ -1829,11 +1848,11 @@ grpc = [ [[package]] name = "graphql-core" -version = "3.2.8" +version = "3.2.11" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/68/c5/36aa96205c3ecbb3d34c7c24189e4553c7ca2ebc7e1dd07432339b980272/graphql_core-3.2.8.tar.gz", hash = "sha256:015457da5d996c924ddf57a43f4e959b0b94fb695b85ed4c29446e508ed65cf3", size = 513181, upload-time = "2026-03-05T19:55:37.332Z" } +sdist = { url = "https://files.pythonhosted.org/packages/4d/90/f2aff026ab4aebd80eb71905106a0885f4cfde85dcf965543f45bed0d9ee/graphql_core-3.2.11.tar.gz", hash = "sha256:e7e156d10beb127cab5c89ff0da71416fc73d27c484a4757d3b2d35633774802", size = 528407, upload-time = "2026-06-05T13:45:22.915Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/86/41/cb887d9afc5dabd78feefe6ccbaf83ff423c206a7a1b7aeeac05120b2125/graphql_core-3.2.8-py3-none-any.whl", hash = "sha256:cbee07bee1b3ed5e531723685369039f32ff815ef60166686e0162f540f1520c", size = 207349, upload-time = "2026-03-05T19:55:35.911Z" }, + { url = "https://files.pythonhosted.org/packages/00/15/b92b4e1d88d02c6eff9733c9eea21846ab435cc4d813d84ccc5d335955df/graphql_core-3.2.11-py3-none-any.whl", hash = "sha256:0b3e35ff41e9adba53021ab0cef475eb18f57c7f53f0f2ca55567fbf3c537ea0", size = 214879, upload-time = "2026-06-05T13:45:21.245Z" }, ] [[package]] @@ -1847,56 +1866,72 @@ wheels = [ [[package]] name = "greenlet" -version = "3.4.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/86/94/a5935717b307d7c71fe877b52b884c6af707d2d2090db118a03fbd799369/greenlet-3.4.0.tar.gz", hash = "sha256:f50a96b64dafd6169e595a5c56c9146ef80333e67d4476a65a9c55f400fc22ff", size = 195913, upload-time = "2026-04-08T17:08:00.863Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/0c/bc/e30e1e3d5e8860b0e0ce4d2b16b2681b77fd13542fc0d72f7e3c22d16eff/greenlet-3.4.0-cp310-cp310-macosx_11_0_universal2.whl", hash = "sha256:d18eae9a7fb0f499efcd146b8c9750a2e1f6e0e93b5a382b3481875354a430e6", size = 284315, upload-time = "2026-04-08T17:02:52.322Z" }, - { url = "https://files.pythonhosted.org/packages/5b/cc/e023ae1967d2a26737387cac083e99e47f65f58868bd155c4c80c01ec4e0/greenlet-3.4.0-cp310-cp310-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:636d2f95c309e35f650e421c23297d5011716be15d966e6328b367c9fc513a82", size = 601916, upload-time = "2026-04-08T16:24:35.533Z" }, - { url = "https://files.pythonhosted.org/packages/67/32/5be1677954b6d8810b33abe94e3eb88726311c58fa777dc97e390f7caf5a/greenlet-3.4.0-cp310-cp310-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:234582c20af9742583c3b2ddfbdbb58a756cfff803763ffaae1ac7990a9fac31", size = 616399, upload-time = "2026-04-08T16:30:54.536Z" }, - { url = "https://files.pythonhosted.org/packages/74/bf/2d58d5ea515704f83e34699128c9072a34bea27d2b6a556e102105fe62a5/greenlet-3.4.0-cp310-cp310-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:523677e69cd4711b5a014e37bc1fb3a29947c3e3a5bb6a527e1cc50312e5a398", size = 611978, upload-time = "2026-04-08T15:56:31.335Z" }, - { url = "https://files.pythonhosted.org/packages/bd/69/6525049b6c179d8a923256304d8387b8bdd4acab1acf0407852463c6d514/greenlet-3.4.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:b45e45fe47a19051a396abb22e19e7836a59ee6c5a90f3be427343c37908d65b", size = 1571957, upload-time = "2026-04-08T16:26:17.041Z" }, - { url = "https://files.pythonhosted.org/packages/4e/6c/bbfb798b05fec736a0d24dc23e81b45bcee87f45a83cfb39db031853bddc/greenlet-3.4.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:5434271357be07f3ad0936c312645853b7e689e679e29310e2de09a9ea6c3adf", size = 1637223, upload-time = "2026-04-08T15:57:27.556Z" }, - { url = "https://files.pythonhosted.org/packages/b7/7d/981fe0e7c07bd9d5e7eb18decb8590a11e3955878291f7a7de2e9c668eb7/greenlet-3.4.0-cp310-cp310-win_amd64.whl", hash = "sha256:a19093fbad824ed7c0f355b5ff4214bffda5f1a7f35f29b31fcaa240cc0135ab", size = 237902, upload-time = "2026-04-08T17:03:14.16Z" }, - { url = "https://files.pythonhosted.org/packages/fb/c6/dba32cab7e3a625b011aa5647486e2d28423a48845a2998c126dd69c85e1/greenlet-3.4.0-cp311-cp311-macosx_11_0_universal2.whl", hash = "sha256:805bebb4945094acbab757d34d6e1098be6de8966009ab9ca54f06ff492def58", size = 285504, upload-time = "2026-04-08T15:52:14.071Z" }, - { url = "https://files.pythonhosted.org/packages/54/f4/7cb5c2b1feb9a1f50e038be79980dfa969aa91979e5e3a18fdbcfad2c517/greenlet-3.4.0-cp311-cp311-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:439fc2f12b9b512d9dfa681c5afe5f6b3232c708d13e6f02c845e0d9f4c2d8c6", size = 605476, upload-time = "2026-04-08T16:24:37.064Z" }, - { url = "https://files.pythonhosted.org/packages/d6/af/b66ab0b2f9a4c5a867c136bf66d9599f34f21a1bcca26a2884a29c450bd9/greenlet-3.4.0-cp311-cp311-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:a70ed1cb0295bee1df57b63bf7f46b4e56a5c93709eea769c1fec1bb23a95875", size = 618336, upload-time = "2026-04-08T16:30:56.59Z" }, - { url = "https://files.pythonhosted.org/packages/e5/5c/8c5633ece6ba611d64bf2770219a98dd439921d6424e4e8cf16b0ac74ea5/greenlet-3.4.0-cp311-cp311-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c660bce1940a1acae5f51f0a064f1bc785d07ea16efcb4bc708090afc4d69e83", size = 613515, upload-time = "2026-04-08T15:56:32.478Z" }, - { url = "https://files.pythonhosted.org/packages/a9/df/950d15bca0d90a0e7395eb777903060504cdb509b7b705631e8fb69ff415/greenlet-3.4.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:ee407d4d1ca9dc632265aee1c8732c4a2d60adff848057cdebfe5fe94eb2c8a2", size = 1574623, upload-time = "2026-04-08T16:26:18.596Z" }, - { url = "https://files.pythonhosted.org/packages/1a/e7/0839afab829fcb7333c9ff6d80c040949510055d2d4d63251f0d1c7c804e/greenlet-3.4.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:956215d5e355fffa7c021d168728321fd4d31fd730ac609b1653b450f6a4bc71", size = 1639579, upload-time = "2026-04-08T15:57:29.231Z" }, - { url = "https://files.pythonhosted.org/packages/d9/2b/b4482401e9bcaf9f5c97f67ead38db89c19520ff6d0d6699979c6efcc200/greenlet-3.4.0-cp311-cp311-win_amd64.whl", hash = "sha256:5cb614ace7c27571270354e9c9f696554d073f8aa9319079dcba466bbdead711", size = 238233, upload-time = "2026-04-08T17:02:54.286Z" }, - { url = "https://files.pythonhosted.org/packages/0c/4d/d8123a4e0bcd583d5cfc8ddae0bbe29c67aab96711be331a7cc935a35966/greenlet-3.4.0-cp311-cp311-win_arm64.whl", hash = "sha256:04403ac74fe295a361f650818de93be11b5038a78f49ccfb64d3b1be8fbf1267", size = 235045, upload-time = "2026-04-08T17:04:05.072Z" }, - { url = "https://files.pythonhosted.org/packages/65/8b/3669ad3b3f247a791b2b4aceb3aa5a31f5f6817bf547e4e1ff712338145a/greenlet-3.4.0-cp312-cp312-macosx_11_0_universal2.whl", hash = "sha256:1a54a921561dd9518d31d2d3db4d7f80e589083063ab4d3e2e950756ef809e1a", size = 286902, upload-time = "2026-04-08T15:52:12.138Z" }, - { url = "https://files.pythonhosted.org/packages/38/3e/3c0e19b82900873e2d8469b590a6c4b3dfd2b316d0591f1c26b38a4879a5/greenlet-3.4.0-cp312-cp312-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:16dec271460a9a2b154e3b1c2fa1050ce6280878430320e85e08c166772e3f97", size = 606099, upload-time = "2026-04-08T16:24:38.408Z" }, - { url = "https://files.pythonhosted.org/packages/b5/33/99fef65e7754fc76a4ed14794074c38c9ed3394a5bd129d7f61b705f3168/greenlet-3.4.0-cp312-cp312-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:90036ce224ed6fe75508c1907a77e4540176dcf0744473627785dd519c6f9996", size = 618837, upload-time = "2026-04-08T16:30:58.298Z" }, - { url = "https://files.pythonhosted.org/packages/36/f7/229f3aed6948faa20e0616a0b8568da22e365ede6a54d7d369058b128afd/greenlet-3.4.0-cp312-cp312-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a1c4f6b453006efb8310affb2d132832e9bbb4fc01ce6df6b70d810d38f1f6dc", size = 615062, upload-time = "2026-04-08T15:56:33.766Z" }, - { url = "https://files.pythonhosted.org/packages/08/97/d988180011aa40135c46cd0d0cf01dd97f7162bae14139b4a3ef54889ba5/greenlet-3.4.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:9b2d9a138ffa0e306d0e2b72976d2fb10b97e690d40ab36a472acaab0838e2de", size = 1573511, upload-time = "2026-04-08T16:26:20.058Z" }, - { url = "https://files.pythonhosted.org/packages/d4/0f/a5a26fe152fb3d12e6a474181f6e9848283504d0afd095f353d85726374b/greenlet-3.4.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:8424683caf46eb0eb6f626cb95e008e8cc30d0cb675bdfa48200925c79b38a08", size = 1640396, upload-time = "2026-04-08T15:57:30.88Z" }, - { url = "https://files.pythonhosted.org/packages/42/cf/bb2c32d9a100e36ee9f6e38fad6b1e082b8184010cb06259b49e1266ca01/greenlet-3.4.0-cp312-cp312-win_amd64.whl", hash = "sha256:a0a53fb071531d003b075c444014ff8f8b1a9898d36bb88abd9ac7b3524648a2", size = 238892, upload-time = "2026-04-08T17:03:10.094Z" }, - { url = "https://files.pythonhosted.org/packages/b7/47/6c41314bac56e71436ce551c7fbe3cc830ed857e6aa9708dbb9c65142eb6/greenlet-3.4.0-cp312-cp312-win_arm64.whl", hash = "sha256:f38b81880ba28f232f1f675893a39cf7b6db25b31cc0a09bb50787ecf957e85e", size = 235599, upload-time = "2026-04-08T15:52:54.3Z" }, - { url = "https://files.pythonhosted.org/packages/7a/75/7e9cd1126a1e1f0cd67b0eda02e5221b28488d352684704a78ed505bd719/greenlet-3.4.0-cp313-cp313-macosx_11_0_universal2.whl", hash = "sha256:43748988b097f9c6f09364f260741aa73c80747f63389824435c7a50bfdfd5c1", size = 285856, upload-time = "2026-04-08T15:52:45.82Z" }, - { url = "https://files.pythonhosted.org/packages/9d/c4/3e2df392e5cb199527c4d9dbcaa75c14edcc394b45040f0189f649631e3c/greenlet-3.4.0-cp313-cp313-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5566e4e2cd7a880e8c27618e3eab20f3494452d12fd5129edef7b2f7aa9a36d1", size = 610208, upload-time = "2026-04-08T16:24:39.674Z" }, - { url = "https://files.pythonhosted.org/packages/da/af/750cdfda1d1bd30a6c28080245be8d0346e669a98fdbae7f4102aa95fff3/greenlet-3.4.0-cp313-cp313-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:1054c5a3c78e2ab599d452f23f7adafef55062a783a8e241d24f3b633ba6ff82", size = 621269, upload-time = "2026-04-08T16:30:59.767Z" }, - { url = "https://files.pythonhosted.org/packages/54/78/0cbc693622cd54ebe25207efbb3a0eb07c2639cb8594f6e3aaaa0bb077a8/greenlet-3.4.0-cp313-cp313-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f82cb6cddc27dd81c96b1506f4aa7def15070c3b2a67d4e46fd19016aacce6cf", size = 617549, upload-time = "2026-04-08T15:56:34.893Z" }, - { url = "https://files.pythonhosted.org/packages/ba/c0/8966767de01343c1ff47e8b855dc78e7d1a8ed2b7b9c83576a57e289f81d/greenlet-3.4.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:227a46251ecba4ff46ae742bc5ce95c91d5aceb4b02f885487aff269c127a729", size = 1575310, upload-time = "2026-04-08T16:26:21.671Z" }, - { url = "https://files.pythonhosted.org/packages/b8/38/bcdc71ba05e9a5fda87f63ffc2abcd1f15693b659346df994a48c968003d/greenlet-3.4.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:5b99e87be7eba788dd5b75ba1cde5639edffdec5f91fe0d734a249535ec3408c", size = 1640435, upload-time = "2026-04-08T15:57:32.572Z" }, - { url = "https://files.pythonhosted.org/packages/a1/c2/19b664b7173b9e4ef5f77e8cef9f14c20ec7fce7920dc1ccd7afd955d093/greenlet-3.4.0-cp313-cp313-win_amd64.whl", hash = "sha256:849f8bc17acd6295fcb5de8e46d55cc0e52381c56eaf50a2afd258e97bc65940", size = 238760, upload-time = "2026-04-08T17:04:03.878Z" }, - { url = "https://files.pythonhosted.org/packages/9b/96/795619651d39c7fbd809a522f881aa6f0ead504cc8201c3a5b789dfaef99/greenlet-3.4.0-cp313-cp313-win_arm64.whl", hash = "sha256:9390ad88b652b1903814eaabd629ca184db15e0eeb6fe8a390bbf8b9106ae15a", size = 235498, upload-time = "2026-04-08T17:05:00.584Z" }, - { url = "https://files.pythonhosted.org/packages/78/02/bde66806e8f169cf90b14d02c500c44cdbe02c8e224c9c67bafd1b8cadd1/greenlet-3.4.0-cp314-cp314-macosx_11_0_universal2.whl", hash = "sha256:10a07aca6babdd18c16a3f4f8880acfffc2b88dfe431ad6aa5f5740759d7d75e", size = 286291, upload-time = "2026-04-08T17:09:34.307Z" }, - { url = "https://files.pythonhosted.org/packages/05/1f/39da1c336a87d47c58352fb8a78541ce63d63ae57c5b9dae1fe02801bbc2/greenlet-3.4.0-cp314-cp314-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:076e21040b3a917d3ce4ad68fb5c3c6b32f1405616c4a57aa83120979649bd3d", size = 656749, upload-time = "2026-04-08T16:24:41.721Z" }, - { url = "https://files.pythonhosted.org/packages/d3/6c/90ee29a4ee27af7aa2e2ec408799eeb69ee3fcc5abcecac6ddd07a5cd0f2/greenlet-3.4.0-cp314-cp314-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:e82689eea4a237e530bb5cb41b180ef81fa2160e1f89422a67be7d90da67f615", size = 669084, upload-time = "2026-04-08T16:31:01.372Z" }, - { url = "https://files.pythonhosted.org/packages/07/49/d4cad6e5381a50947bb973d2f6cf6592621451b09368b8c20d9b8af49c5b/greenlet-3.4.0-cp314-cp314-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4df3b0b2289ec686d3c821a5fee44259c05cfe824dd5e6e12c8e5f5df23085cf", size = 665621, upload-time = "2026-04-08T15:56:35.995Z" }, - { url = "https://files.pythonhosted.org/packages/37/31/d1edd54f424761b5d47718822f506b435b6aab2f3f93b465441143ea5119/greenlet-3.4.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:8bff29d586ea415688f4cec96a591fcc3bf762d046a796cdadc1fdb6e7f2d5bf", size = 1622259, upload-time = "2026-04-08T16:26:23.201Z" }, - { url = "https://files.pythonhosted.org/packages/b0/c6/6d3f9cdcb21c4e12a79cb332579f1c6aa1af78eb68059c5a957c7812d95e/greenlet-3.4.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:8a569c2fb840c53c13a2b8967c63621fafbd1a0e015b9c82f408c33d626a2fda", size = 1686916, upload-time = "2026-04-08T15:57:34.282Z" }, - { url = "https://files.pythonhosted.org/packages/63/45/c1ca4a1ad975de4727e52d3ffe641ae23e1d7a8ffaa8ff7a0477e1827b92/greenlet-3.4.0-cp314-cp314-win_amd64.whl", hash = "sha256:207ba5b97ea8b0b60eb43ffcacf26969dd83726095161d676aac03ff913ee50d", size = 239821, upload-time = "2026-04-08T17:03:48.423Z" }, - { url = "https://files.pythonhosted.org/packages/71/c4/6f621023364d7e85a4769c014c8982f98053246d142420e0328980933ceb/greenlet-3.4.0-cp314-cp314-win_arm64.whl", hash = "sha256:f8296d4e2b92af34ebde81085a01690f26a51eb9ac09a0fcadb331eb36dbc802", size = 236932, upload-time = "2026-04-08T17:04:33.551Z" }, - { url = "https://files.pythonhosted.org/packages/d4/8f/18d72b629783f5e8d045a76f5325c1e938e659a9e4da79c7dcd10169a48d/greenlet-3.4.0-cp314-cp314t-macosx_11_0_universal2.whl", hash = "sha256:d70012e51df2dbbccfaf63a40aaf9b40c8bed37c3e3a38751c926301ce538ece", size = 294681, upload-time = "2026-04-08T15:52:35.778Z" }, - { url = "https://files.pythonhosted.org/packages/9e/ad/5fa86ec46769c4153820d58a04062285b3b9e10ba3d461ee257b68dcbf53/greenlet-3.4.0-cp314-cp314t-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a58bec0751f43068cd40cff31bb3ca02ad6000b3a51ca81367af4eb5abc480c8", size = 658899, upload-time = "2026-04-08T16:24:43.32Z" }, - { url = "https://files.pythonhosted.org/packages/43/f0/4e8174ca0e87ae748c409f055a1ba161038c43cc0a5a6f1433a26ac2e5bf/greenlet-3.4.0-cp314-cp314t-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:05fa0803561028f4b2e3b490ee41216a842eaee11aed004cc343a996d9523aa2", size = 665284, upload-time = "2026-04-08T16:31:02.833Z" }, - { url = "https://files.pythonhosted.org/packages/19/da/991cf7cd33662e2df92a1274b7eb4d61769294d38a1bba8a45f31364845e/greenlet-3.4.0-cp314-cp314t-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e60d38719cb80b3ab5e85f9f1aed4960acfde09868af6762ccb27b260d68f4ed", size = 661861, upload-time = "2026-04-08T15:56:37.269Z" }, - { url = "https://files.pythonhosted.org/packages/36/c5/6c2c708e14db3d9caea4b459d8464f58c32047451142fe2cfd90e7458f41/greenlet-3.4.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:7f50c804733b43eded05ae694691c9aa68bca7d0a867d67d4a3f514742a2d53f", size = 1622182, upload-time = "2026-04-08T16:26:24.777Z" }, - { url = "https://files.pythonhosted.org/packages/7a/4c/50c5fed19378e11a29fabab1f6be39ea95358f4a0a07e115a51ca93385d8/greenlet-3.4.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:2d4f0635dc4aa638cda4b2f5a07ae9a2cff9280327b581a3fcb6f317b4fbc38a", size = 1685050, upload-time = "2026-04-08T15:57:36.453Z" }, - { url = "https://files.pythonhosted.org/packages/db/72/85ae954d734703ab48e622c59d4ce35d77ce840c265814af9c078cacc7aa/greenlet-3.4.0-cp314-cp314t-win_amd64.whl", hash = "sha256:1a4a48f24681300c640f143ba7c404270e1ebbbcf34331d7104a4ff40f8ea705", size = 245554, upload-time = "2026-04-08T17:03:50.044Z" }, +version = "3.5.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/6d/6e/802acd792aebb2256fbbee8cacf2727faaeb6f240ac11008f09eae4414bc/greenlet-3.5.1.tar.gz", hash = "sha256:5a56aeb7d5d9cc4b3a735efb5095bd4b4f6f0e4f93e5ca876d0e2315137b7829", size = 197356, upload-time = "2026-05-20T15:05:03.917Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/1d/21/117c8710abb7f146d804a124c07eb5964a60b90d02b72452885aecc18efa/greenlet-3.5.1-cp310-cp310-macosx_11_0_universal2.whl", hash = "sha256:7eacb17a9d41538a2bc4912eba5ef13823c83cb69e4d141d0813debe7163187f", size = 283510, upload-time = "2026-05-20T13:12:26.475Z" }, + { url = "https://files.pythonhosted.org/packages/b9/f7/6762a56fa5f6c2295c449c6524e10ce481e381c994cc44d9d03aef0700fb/greenlet-3.5.1-cp310-cp310-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e5cc9606aa5f4e0bde0d3bd502b44f743864c3ffa5cfa1011b1e30f5aa02366f", size = 599696, upload-time = "2026-05-20T14:00:02.906Z" }, + { url = "https://files.pythonhosted.org/packages/0f/05/85a511e68ee109aff0aa00b4b497806091dd2d82ce209e49c6e801bd5d92/greenlet-3.5.1-cp310-cp310-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:c3d35f87c7253b715d13d679e0783d845910144f282cb939fe1ba4ac8616269c", size = 612618, upload-time = "2026-05-20T14:05:39.202Z" }, + { url = "https://files.pythonhosted.org/packages/89/b8/8b83d18ae07c46c019617f35afd7b47aab7f9b4fbb12fc637d681e10bdd8/greenlet-3.5.1-cp310-cp310-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:540dae7b956209af4d70a3be35927b4055f617763771e5e84a5255bea934d2f5", size = 612947, upload-time = "2026-05-20T13:14:23.469Z" }, + { url = "https://files.pythonhosted.org/packages/5d/14/ad1f9fc9b82384c010212464a3702bd911f95dab2f1180bc6fbcfb1f958c/greenlet-3.5.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:ed8cdb691169715a9a492844a83246f090182247d1a5031dc78a403f68ba1e97", size = 1571425, upload-time = "2026-05-20T14:02:22.671Z" }, + { url = "https://files.pythonhosted.org/packages/46/1c/43b8203cf10f4292c9e3d270e9e5f5ade79115a0a0ca5ea6f1be5f8915a7/greenlet-3.5.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:9d59e840387076a51016777a9328b3f2c427c6f9208a6e958bad251be50a648d", size = 1638688, upload-time = "2026-05-20T13:14:30.026Z" }, + { url = "https://files.pythonhosted.org/packages/ac/6e/0344b1e99f58f71715456e46492101fd2daa408957b8186ade0a4b515da7/greenlet-3.5.1-cp310-cp310-win_amd64.whl", hash = "sha256:b9152fca4a6466e114aaec745ae61cba739903a109754a9d4e1262f01e9259b1", size = 237763, upload-time = "2026-05-20T13:11:35.659Z" }, + { url = "https://files.pythonhosted.org/packages/42/3c/ff890b466eaba2b0f5e6bdfff025f8c75f41b8ffdc3dbc3d24ad261e764a/greenlet-3.5.1-cp311-cp311-macosx_11_0_universal2.whl", hash = "sha256:73f78f9b9f0a5c06e5c946ba1e8e36f5114923b6be109ee618c54f079c3ea14f", size = 284764, upload-time = "2026-05-20T13:09:10.204Z" }, + { url = "https://files.pythonhosted.org/packages/81/0e/5e5457be3d256918f6a4756f073548a3f0190836e2cc94aa6d0d617a940b/greenlet-3.5.1-cp311-cp311-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a0cbed8bb44e23c5b199f888f4e4ce096b45ad9f25ff74a7ad0213875e936bb2", size = 603479, upload-time = "2026-05-20T14:00:04.757Z" }, + { url = "https://files.pythonhosted.org/packages/6d/e1/f89a21d58d308298e6f275f13a1b472ed96c680b601a371b08be6a725989/greenlet-3.5.1-cp311-cp311-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:a203a8bd0acb0701653d3bbb26e404854a68674139ed5cbb778830f42b09bb33", size = 615495, upload-time = "2026-05-20T14:05:40.87Z" }, + { url = "https://files.pythonhosted.org/packages/75/de/af6cef182862d2ccd6975440d21c9058a77c3f9b469abf94e322dfd2e0e3/greenlet-3.5.1-cp311-cp311-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8a271fcd66c74615cda6a964fda3f304267a12e50a084472218a39bb0376f563", size = 614754, upload-time = "2026-05-20T13:14:24.947Z" }, + { url = "https://files.pythonhosted.org/packages/1a/c6/50e520283a9f19388a7326b05f9e8637e566003475eacaadad04f558c68d/greenlet-3.5.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:ded7b068c7c31c1a8657d4fd42d886b3e051ae29f88b80c5ff9d502257b0f071", size = 1574097, upload-time = "2026-05-20T14:02:24.003Z" }, + { url = "https://files.pythonhosted.org/packages/21/1c/13abd1f4860d987fa5e1170a01930d6e6cd40d328de487a3c9fdaff0ffd0/greenlet-3.5.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:d0932b81d72f552ded9d810d00021b64d89f2195a91ce115b893f943b7a4ab3c", size = 1641058, upload-time = "2026-05-20T13:14:31.83Z" }, + { url = "https://files.pythonhosted.org/packages/f5/56/5f332b7705545eac2dc01b4e9254d24a793f2656d55d5cc6b94ee59d22ae/greenlet-3.5.1-cp311-cp311-win_amd64.whl", hash = "sha256:88e300d136eac057b2397aa1cfd7328b4c87c7eb66a09c7bc6a1292234db474e", size = 238089, upload-time = "2026-05-20T13:14:03.229Z" }, + { url = "https://files.pythonhosted.org/packages/d9/a9/a3c2fa886c5b94863fb0e61b3bc14610b7aa94cf4f17f8741b11708305fc/greenlet-3.5.1-cp311-cp311-win_arm64.whl", hash = "sha256:cc6ab7e555c8a112ad3a76e368e86e12a2754bcae1652a5602e133ec7b635523", size = 234989, upload-time = "2026-05-20T13:08:27.715Z" }, + { url = "https://files.pythonhosted.org/packages/c4/37/4549f149c9797c21b32c2683c33522af22522099de128b2406672526d005/greenlet-3.5.1-cp312-cp312-macosx_11_0_universal2.whl", hash = "sha256:fa4f98af3a528f0c3fd592a26df7f376f93329c8f4d987f6bb979057af8bf5e2", size = 286220, upload-time = "2026-05-20T13:07:28.463Z" }, + { url = "https://files.pythonhosted.org/packages/38/ff/a4f436709716965eaab9f36ea7b906c8a927fbe32fb1372a2071d964f6b1/greenlet-3.5.1-cp312-cp312-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ffea73584b216150eab159b6d12348fb253e68757974de1e2c40d8a318ac89ed", size = 601585, upload-time = "2026-05-20T14:00:06.141Z" }, + { url = "https://files.pythonhosted.org/packages/65/ad/54bc3fcee3ad368a61b19b67d88117f7a8c29727bf71fffdeda81fbd946e/greenlet-3.5.1-cp312-cp312-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:1072b4f9edcc1e192d9283a66a3e68d6b84c561de33a83d7858beb9ba1effe10", size = 614215, upload-time = "2026-05-20T14:05:42.675Z" }, + { url = "https://files.pythonhosted.org/packages/40/69/b91cda0647df839483201545913514c2827ebea5e5ccdf931842763bc127/greenlet-3.5.1-cp312-cp312-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:add5217d68b31130f0beca584d7fef4878327d2e31642b66618a14eef312b63b", size = 611358, upload-time = "2026-05-20T13:14:26.37Z" }, + { url = "https://files.pythonhosted.org/packages/59/90/3cf77e080350cd02fa307bb2abf05df48f4482c240275bbd2c203ba8bb1c/greenlet-3.5.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:a5ea42a752d47a145eae922b605cd1634665ac3d5ec1e72402d5048e8d60d207", size = 1570475, upload-time = "2026-05-20T14:02:25.29Z" }, + { url = "https://files.pythonhosted.org/packages/65/2c/18cece62045e74598c3c393f70dce4a63f56222015ba29a5d4eeb04f764c/greenlet-3.5.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:c5551170cf4f5ff5623e9af81323751979fee2c731e2287b61f73cd27257b823", size = 1635625, upload-time = "2026-05-20T13:14:34.027Z" }, + { url = "https://files.pythonhosted.org/packages/30/f5/310d104ddf41eb5a70f4c268d22508dfb0c3c8e86fec152be34d0d2ed819/greenlet-3.5.1-cp312-cp312-win_amd64.whl", hash = "sha256:3c8bb982ad117d29478ef8f5533e97df21f1e2befd17a299257b0c96d1371c0b", size = 238791, upload-time = "2026-05-20T13:10:39.018Z" }, + { url = "https://files.pythonhosted.org/packages/62/90/ceca11f504cd23a8047a3dea31919adc48df9b626dd0c13f0d858734fdfd/greenlet-3.5.1-cp312-cp312-win_arm64.whl", hash = "sha256:80eb4b04dadc4e67df3fae179a32c4706a3f495bc7f22fc8a81115d5f5512188", size = 235580, upload-time = "2026-05-20T13:08:45.056Z" }, + { url = "https://files.pythonhosted.org/packages/27/69/7f7e5372d998b81001899b1c0823c957aa413ba0f2662e65821611cc31e4/greenlet-3.5.1-cp313-cp313-macosx_11_0_universal2.whl", hash = "sha256:51518ff74664078fc51bffcc6fc529b0df5ae58da192691cee765d45ce944a2b", size = 285060, upload-time = "2026-05-20T13:08:51.899Z" }, + { url = "https://files.pythonhosted.org/packages/b1/bf/387f9b6b865fd2ae0d0be09e0004827295a01b71be76ed350dd1e28a91a4/greenlet-3.5.1-cp313-cp313-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1ffdb3c0bb002c99cd8f298957e046c3dbf6006b5b7cdf11a4e19194624a0a0a", size = 604370, upload-time = "2026-05-20T14:00:07.492Z" }, + { url = "https://files.pythonhosted.org/packages/32/f5/169ce3d4e4c67291bd18f8cbe0299c9f3e45102c7f1fb3c14780c93e4532/greenlet-3.5.1-cp313-cp313-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:7715a5a2c3378ba602c3a440558261e13a820bb53a82693aacd7b7f6d964e283", size = 616987, upload-time = "2026-05-20T14:05:44.237Z" }, + { url = "https://files.pythonhosted.org/packages/ee/e5/7f2e41d5273be07e77560d61ea4e56485b4d6c316d2a84518c62d1364061/greenlet-3.5.1-cp313-cp313-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:dc71ff466927a201b08305acac451ebe1aedfcea002f62f1f2f2ac2ac1e6a135", size = 613911, upload-time = "2026-05-20T13:14:27.539Z" }, + { url = "https://files.pythonhosted.org/packages/c5/a4/fbdc67579b73615a1f91615e814303cc71e06128f7baaba87be79b8fb90c/greenlet-3.5.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:cd443683db272ebaaca03af98c0b063ab30db70ea8a31a1559f35e3f7b744ccd", size = 1570689, upload-time = "2026-05-20T14:02:27.225Z" }, + { url = "https://files.pythonhosted.org/packages/e6/b4/77abbe35078be39718a46cd49caf16bceb35662f97a34101dca28aa98e47/greenlet-3.5.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:089fff7a6ce8d9316d1f65ebc00273a56be258c1725b32b94de90a3a979557e1", size = 1635602, upload-time = "2026-05-20T13:14:36.344Z" }, + { url = "https://files.pythonhosted.org/packages/37/f7/129f27ca700845b8ee8ca88ce7f43435a1239c2eddb7677fc938822762cf/greenlet-3.5.1-cp313-cp313-win_amd64.whl", hash = "sha256:110a1ca7b49b014b097f6078272c3f4ed31af45b254de5228b79adba879f6af9", size = 238683, upload-time = "2026-05-20T13:11:50.57Z" }, + { url = "https://files.pythonhosted.org/packages/6d/5c/a485a36e87df8d8fd0632ee01511244f5156a20ed3746cc6599340326395/greenlet-3.5.1-cp313-cp313-win_arm64.whl", hash = "sha256:f16ba1efc0715b680a18b8123d90dad887c6112ae3555b4b5c32c149540c6b4e", size = 235499, upload-time = "2026-05-20T13:12:42.028Z" }, + { url = "https://files.pythonhosted.org/packages/8a/cb/c62454606daf5640369c94d8a9dd540599b1bfc090e2d2180cb77f4038d2/greenlet-3.5.1-cp314-cp314-macosx_11_0_universal2.whl", hash = "sha256:d8ab31c9de8651a2facdd5c5bb0011f2380dd1a7af78ce2adf4b56095294fc07", size = 285579, upload-time = "2026-05-20T13:08:56.396Z" }, + { url = "https://files.pythonhosted.org/packages/ec/71/c4270398c2eba968a6071af1dfbdcaeee6ec1c24bc8b435b8cc452700da6/greenlet-3.5.1-cp314-cp314-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5e300185139abc337ade480c327183adf42a875ac7181bfe66d7d4efea31fbea", size = 651106, upload-time = "2026-05-20T14:00:09.448Z" }, + { url = "https://files.pythonhosted.org/packages/1a/ab/71e34b78a44ec271fb5f550c17bc46d301ddc5953890d935f270b0dcdb5a/greenlet-3.5.1-cp314-cp314-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:7ffdb990dcaa0234cf9845aead5df2e3c3a8b6507d409274dd87e0d5ab05ffc2", size = 663478, upload-time = "2026-05-20T14:05:45.88Z" }, + { url = "https://files.pythonhosted.org/packages/77/96/4efd6fa5c62c85426a0c19077a586258ebc3a2a146ff2493e4312a697a22/greenlet-3.5.1-cp314-cp314-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:2f82b3597e9d83b63408affed0b48fd0f54935edac4302237b9a837be0dae33c", size = 660800, upload-time = "2026-05-20T13:14:29.129Z" }, + { url = "https://files.pythonhosted.org/packages/7a/e0/6c71401a25cac7000261304e866a2f2cc04dc74810d40e2f118aa4799495/greenlet-3.5.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:c0141e37414c10164e702b8fb1473304221ad98f71600850c6ef7ff4880feba0", size = 1617518, upload-time = "2026-05-20T14:02:28.662Z" }, + { url = "https://files.pythonhosted.org/packages/41/26/c5c06643e8c0af9e7bf18e16cb51d0ab7625155f0392e1c9015d66d556cd/greenlet-3.5.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:50ae25a67bea74ea41fb14b960bc532df73eb713417b2d61892dced82fe8d3bc", size = 1681593, upload-time = "2026-05-20T13:14:39.417Z" }, + { url = "https://files.pythonhosted.org/packages/8a/bd/e11a108317485075e68af9d23039619b86b28130c3b50d227d42edece64b/greenlet-3.5.1-cp314-cp314-win_amd64.whl", hash = "sha256:8a17c42330e261299766b75ac1ea32caa437a9453c8f65d16a13140db378ecd3", size = 239800, upload-time = "2026-05-20T13:09:30.128Z" }, + { url = "https://files.pythonhosted.org/packages/47/f8/8e8e8417b7bf28639a5a56356ef934d0375e1d0c70a57e04d7701e870ffe/greenlet-3.5.1-cp314-cp314-win_arm64.whl", hash = "sha256:7b5f5fae05b8ac6d176a61b60c394a8cbdc2b5b91b81793066e68745cf165e54", size = 236862, upload-time = "2026-05-20T13:09:10.498Z" }, + { url = "https://files.pythonhosted.org/packages/90/12/41bf27fde4d3605d3773ae57751eda182b8be2f5398011c041173b1d9534/greenlet-3.5.1-cp314-cp314t-macosx_11_0_universal2.whl", hash = "sha256:ea8da1e900d758d078810d4255d8c6aa572181896a31ec79d779eb79c3adc9ad", size = 293637, upload-time = "2026-05-20T13:12:35.529Z" }, + { url = "https://files.pythonhosted.org/packages/44/44/ba14b23e9757707050c2f397d305bbcae62e5d7cad122f8b6baec5ae4a1f/greenlet-3.5.1-cp314-cp314t-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a19570c52a21420dcbc94e661994bc325c0b5b11304540fed514586da5dc8f2e", size = 650840, upload-time = "2026-05-20T14:00:11.079Z" }, + { url = "https://files.pythonhosted.org/packages/a8/37/5ddc2b686a6844f91abecef43411842426da2e1573f60b49ecf2547f4ae1/greenlet-3.5.1-cp314-cp314t-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:3d955c89b75eeca4723d7cc14135f393cd47c32e2a6cb4a8e4c6e760a26b0986", size = 656416, upload-time = "2026-05-20T14:05:47.118Z" }, + { url = "https://files.pythonhosted.org/packages/e1/f0/d17510297c35a2992712f0bf84de3779749999f7d3d63aa1f09db7c62dbe/greenlet-3.5.1-cp314-cp314t-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:de2daaaebd1a5aa88c49045b6baf9310b3263796bd88db713edf37cf53e7bb4e", size = 654397, upload-time = "2026-05-20T13:14:30.696Z" }, + { url = "https://files.pythonhosted.org/packages/37/eb/147387705bb89092645b012586e7273cb5ed3c90ef7eaf3a69173eaf0209/greenlet-3.5.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:3bfbd69cc349e43bf3a8ae1c85548ff0718efc887615c2db16c3833d7b0b072d", size = 1614469, upload-time = "2026-05-20T14:02:30.192Z" }, + { url = "https://files.pythonhosted.org/packages/a6/4e/37ee0da7732b7aa9896f17e15579a9df34b9fcb9dd494f0adfa749af6623/greenlet-3.5.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:4378720dd888136c27215a0214d32a4d37c3852765d45bc37aad0623423cfd78", size = 1675115, upload-time = "2026-05-20T13:14:40.972Z" }, + { url = "https://files.pythonhosted.org/packages/57/f3/97dfcf4a6eb5077f8a672234216fb5923eb89f2cab7081cb10b2cf75b605/greenlet-3.5.1-cp314-cp314t-win_amd64.whl", hash = "sha256:45718441607f9325d948db98cbc691276059316d0358c188c246da4e1d4d23d2", size = 245246, upload-time = "2026-05-20T13:12:22.646Z" }, + { url = "https://files.pythonhosted.org/packages/5d/73/d7f72e34b582f694f4a9b248162db7b09cc458a259ba8f0c0bfa1a34ea7d/greenlet-3.5.1-cp315-cp315-macosx_11_0_universal2.whl", hash = "sha256:2baee5ca02031757ffe8cc3d69f0cc0aec7065ce362622da74f32d3bcab1c541", size = 285575, upload-time = "2026-05-20T13:12:07.043Z" }, + { url = "https://files.pythonhosted.org/packages/df/59/fa9c6e87dc8ad27a95dabe2f29f372b733d05a8a67470f6c901ed9975655/greenlet-3.5.1-cp315-cp315-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:9b1ec3274918a81d3ea778b9e75b56b72b33f300edb6cf7f3a7fe1dae56683de", size = 656428, upload-time = "2026-05-20T14:00:12.556Z" }, + { url = "https://files.pythonhosted.org/packages/f6/f9/e753408871eaa61dfe35e619cfc67512b036fde99893685d50eea9e07146/greenlet-3.5.1-cp315-cp315-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:111e2390ffffc47d5840b01711dd7fac07d4c09283d0283e7f3264b14e284c64", size = 667064, upload-time = "2026-05-20T14:05:48.662Z" }, + { url = "https://files.pythonhosted.org/packages/96/27/5565b5b40389f1c7753003a07e21892fda8660926787036d5bc0308b8113/greenlet-3.5.1-cp315-cp315-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e630136e905fe5ff43e86945ae41220b6d1470956a39220e708110ac48d01ea5", size = 665697, upload-time = "2026-05-20T13:14:32.943Z" }, + { url = "https://files.pythonhosted.org/packages/cf/82/e7de4178c0c2d1c9a5a3be3cc0b33e46a85b3ee4a77c071bf7ad8600e079/greenlet-3.5.1-cp315-cp315-musllinux_1_2_aarch64.whl", hash = "sha256:975eac34b44a7077ca4d421348455b94f0f518246a7f14bc6d2fdcfe5b584368", size = 1621256, upload-time = "2026-05-20T14:02:31.91Z" }, + { url = "https://files.pythonhosted.org/packages/00/10/f2dddcf7dacac17dfc68691809589adad06135eb28930429cf58a6467a2f/greenlet-3.5.1-cp315-cp315-musllinux_1_2_x86_64.whl", hash = "sha256:9ab3c3a0b2ae6198e67c898dad5215a49f9ae0d0081b3c3ec59f333e39eeca26", size = 1685956, upload-time = "2026-05-20T13:14:42.55Z" }, + { url = "https://files.pythonhosted.org/packages/22/17/4a232b32133230ada52f70e9d7f5b65b0caef8772f01849bd8d149e7e4ca/greenlet-3.5.1-cp315-cp315-win_amd64.whl", hash = "sha256:cbfc69be86e10dcfef5b1e6269d1d6926552aa89ee39e1de3353360c1b6989ab", size = 239802, upload-time = "2026-05-20T13:13:15.481Z" }, + { url = "https://files.pythonhosted.org/packages/c2/ae/4e623a7e6d4d2a5f4cb8e4c82de4169fc637942caae68d6e676b8a128ac5/greenlet-3.5.1-cp315-cp315-win_arm64.whl", hash = "sha256:92fd6d44ac5e5a887c8a5dc4a8ba0ba908527c31c12f78c6bc7dcfe8aab279f6", size = 236853, upload-time = "2026-05-20T13:15:37.301Z" }, + { url = "https://files.pythonhosted.org/packages/7a/57/816d9cff29119da3505b3d6a5e14a8af89006ac36f47f891ff293ee05af1/greenlet-3.5.1-cp315-cp315t-macosx_11_0_universal2.whl", hash = "sha256:a6fdf2433a5441ef9a95464f7c3e674775da1c8c1177fff311cee1acad4626ed", size = 293877, upload-time = "2026-05-20T13:10:19.078Z" }, + { url = "https://files.pythonhosted.org/packages/23/a1/59b0a7c7d140ff1a75626680b9a9899b79a9176cab298b394968fb023295/greenlet-3.5.1-cp315-cp315t-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:7546556f0d649f99f6a361098a55f761181bb2ea12ff150bb16d26092ad88244", size = 655333, upload-time = "2026-05-20T14:00:14.758Z" }, + { url = "https://files.pythonhosted.org/packages/72/1b/5efe127597625042218939d01855109f352779050768b670b52edcc16a6c/greenlet-3.5.1-cp315-cp315t-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:d5ee3ea898009fa898f85f9982255d35278c477bebe185beca249cab42d4526c", size = 659443, upload-time = "2026-05-20T14:05:50.159Z" }, + { url = "https://files.pythonhosted.org/packages/6c/6d/c404246ea4d22d097a7426d0efb5b781bd7eb67715f09e79001bd552ab18/greenlet-3.5.1-cp315-cp315t-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a5c81f74d204d3edd136ebfd50dce53acbb776995d721a0fe801626cfc93b8cd", size = 658356, upload-time = "2026-05-20T13:14:35.091Z" }, + { url = "https://files.pythonhosted.org/packages/51/02/f8ee37fb6d2219329f350af241c27fcf12df57e723d11f6fc6d3bacdadaa/greenlet-3.5.1-cp315-cp315t-musllinux_1_2_aarch64.whl", hash = "sha256:2c18ef16bf6d4dd410e4dd52996888ea1497be26892fe5bbc73580aba4287b8e", size = 1619216, upload-time = "2026-05-20T14:02:33.403Z" }, + { url = "https://files.pythonhosted.org/packages/93/c5/3dc9475ace2c7a3680da12372cddd7f1ac874eb410a1ac48d3e9dab83782/greenlet-3.5.1-cp315-cp315t-musllinux_1_2_x86_64.whl", hash = "sha256:17d86354f0ae6b61bf9be5148d0dd34e06c3cb7c602c671f79f29ac3b150e659", size = 1678427, upload-time = "2026-05-20T13:14:43.71Z" }, + { url = "https://files.pythonhosted.org/packages/df/4e/750c15c317a41ffb36f0bf40b933e3d744a7dede61889f74443ea69690cf/greenlet-3.5.1-cp315-cp315t-win_amd64.whl", hash = "sha256:e7516cf6ae6b8a582c2770a0caed47b8a48373ed732c33d69a72913ae6ac923e", size = 245225, upload-time = "2026-05-20T13:13:59.366Z" }, + { url = "https://files.pythonhosted.org/packages/4f/fd/d3baea2eeb7b617efd47e87ca06e2ec2c6118d303aa9e918e0ce16eadc10/greenlet-3.5.1-cp315-cp315t-win_arm64.whl", hash = "sha256:5028648bf2253ec4745add746129d3904121fa7fe871a76bed23c5720573ce0a", size = 239590, upload-time = "2026-05-20T13:13:37.382Z" }, ] [[package]] @@ -1936,140 +1971,140 @@ wheels = [ [[package]] name = "grpcio" -version = "1.80.0" +version = "1.81.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/b7/48/af6173dbca4454f4637a4678b67f52ca7e0c1ed7d5894d89d434fecede05/grpcio-1.80.0.tar.gz", hash = "sha256:29aca15edd0688c22ba01d7cc01cb000d72b2033f4a3c72a81a19b56fd143257", size = 12978905, upload-time = "2026-03-30T08:49:10.502Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/9d/cd/bb7b7e54084a344c03d68144450da7ddd5564e51a298ae1662de65f48e2d/grpcio-1.80.0-cp310-cp310-linux_armv7l.whl", hash = "sha256:886457a7768e408cdce226ad1ca67d2958917d306523a0e21e1a2fdaa75c9c9c", size = 6050363, upload-time = "2026-03-30T08:46:20.894Z" }, - { url = "https://files.pythonhosted.org/packages/16/02/1417f5c3460dea65f7a2e3c14e8b31e77f7ffb730e9bfadd89eda7a9f477/grpcio-1.80.0-cp310-cp310-macosx_11_0_universal2.whl", hash = "sha256:7b641fc3f1dc647bfd80bd713addc68f6d145956f64677e56d9ebafc0bd72388", size = 12026037, upload-time = "2026-03-30T08:46:25.144Z" }, - { url = "https://files.pythonhosted.org/packages/43/98/c910254eedf2cae368d78336a2de0678e66a7317d27c02522392f949b5c6/grpcio-1.80.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:33eb763f18f006dc7fee1e69831d38d23f5eccd15b2e0f92a13ee1d9242e5e02", size = 6602306, upload-time = "2026-03-30T08:46:27.593Z" }, - { url = "https://files.pythonhosted.org/packages/7c/f8/88ca4e78c077b2b2113d95da1e1ab43efd43d723c9a0397d26529c2c1a56/grpcio-1.80.0-cp310-cp310-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:52d143637e3872633fc7dd7c3c6a1c84e396b359f3a72e215f8bf69fd82084fc", size = 7301535, upload-time = "2026-03-30T08:46:29.556Z" }, - { url = "https://files.pythonhosted.org/packages/f9/96/f28660fe2fe0f153288bf4a04e4910b7309d442395135c88ed4f5b3b8b40/grpcio-1.80.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:c51bf8ac4575af2e0678bccfb07e47321fc7acb5049b4482832c5c195e04e13a", size = 6808669, upload-time = "2026-03-30T08:46:31.984Z" }, - { url = "https://files.pythonhosted.org/packages/47/eb/3f68a5e955779c00aeef23850e019c1c1d0e032d90633ba49c01ad5a96e0/grpcio-1.80.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:50a9871536d71c4fba24ee856abc03a87764570f0c457dd8db0b4018f379fed9", size = 7409489, upload-time = "2026-03-30T08:46:34.684Z" }, - { url = "https://files.pythonhosted.org/packages/5b/a7/d2f681a4bfb881be40659a309771f3bdfbfdb1190619442816c3f0ffc079/grpcio-1.80.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:a72d84ad0514db063e21887fbacd1fd7acb4d494a564cae22227cd45c7fbf199", size = 8423167, upload-time = "2026-03-30T08:46:36.833Z" }, - { url = "https://files.pythonhosted.org/packages/97/8a/29b4589c204959aa35ce5708400a05bba72181807c45c47b3ec000c39333/grpcio-1.80.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:f7691a6788ad9196872f95716df5bc643ebba13c97140b7a5ee5c8e75d1dea81", size = 7846761, upload-time = "2026-03-30T08:46:40.091Z" }, - { url = "https://files.pythonhosted.org/packages/6b/d2/ed143e097230ee121ac5848f6ff14372dba91289b10b536d54fb1b7cbae7/grpcio-1.80.0-cp310-cp310-win32.whl", hash = "sha256:46c2390b59d67f84e882694d489f5b45707c657832d7934859ceb8c33f467069", size = 4156534, upload-time = "2026-03-30T08:46:42.026Z" }, - { url = "https://files.pythonhosted.org/packages/d5/c9/df8279bb49b29409995e95efa85b72973d62f8aeff89abee58c91f393710/grpcio-1.80.0-cp310-cp310-win_amd64.whl", hash = "sha256:dc053420fc75749c961e2a4c906398d7c15725d36ccc04ae6d16093167223b58", size = 4889869, upload-time = "2026-03-30T08:46:44.219Z" }, - { url = "https://files.pythonhosted.org/packages/5d/db/1d56e5f5823257b291962d6c0ce106146c6447f405b60b234c4f222a7cde/grpcio-1.80.0-cp311-cp311-linux_armv7l.whl", hash = "sha256:dfab85db094068ff42e2a3563f60ab3dddcc9d6488a35abf0132daec13209c8a", size = 6055009, upload-time = "2026-03-30T08:46:46.265Z" }, - { url = "https://files.pythonhosted.org/packages/6e/18/c83f3cad64c5ca63bca7e91e5e46b0d026afc5af9d0a9972472ceba294b3/grpcio-1.80.0-cp311-cp311-macosx_11_0_universal2.whl", hash = "sha256:5c07e82e822e1161354e32da2662f741a4944ea955f9f580ec8fb409dd6f6060", size = 12035295, upload-time = "2026-03-30T08:46:49.099Z" }, - { url = "https://files.pythonhosted.org/packages/0f/8e/e14966b435be2dda99fbe89db9525ea436edc79780431a1c2875a3582644/grpcio-1.80.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:ba0915d51fd4ced2db5ff719f84e270afe0e2d4c45a7bdb1e8d036e4502928c2", size = 6610297, upload-time = "2026-03-30T08:46:52.123Z" }, - { url = "https://files.pythonhosted.org/packages/cc/26/d5eb38f42ce0e3fdc8174ea4d52036ef8d58cc4426cb800f2610f625dd75/grpcio-1.80.0-cp311-cp311-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:3cb8130ba457d2aa09fa6b7c3ed6b6e4e6a2685fce63cb803d479576c4d80e21", size = 7300208, upload-time = "2026-03-30T08:46:54.859Z" }, - { url = "https://files.pythonhosted.org/packages/25/51/bd267c989f85a17a5b3eea65a6feb4ff672af41ca614e5a0279cc0ea381c/grpcio-1.80.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:09e5e478b3d14afd23f12e49e8b44c8684ac3c5f08561c43a5b9691c54d136ab", size = 6813442, upload-time = "2026-03-30T08:46:57.056Z" }, - { url = "https://files.pythonhosted.org/packages/9e/d9/d80eef735b19e9169e30164bbf889b46f9df9127598a83d174eb13a48b26/grpcio-1.80.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:00168469238b022500e486c1c33916acf2f2a9b2c022202cf8a1885d2e3073c1", size = 7414743, upload-time = "2026-03-30T08:46:59.682Z" }, - { url = "https://files.pythonhosted.org/packages/de/f2/567f5bd5054398ed6b0509b9a30900376dcf2786bd936812098808b49d8d/grpcio-1.80.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:8502122a3cc1714038e39a0b071acb1207ca7844208d5ea0d091317555ee7106", size = 8426046, upload-time = "2026-03-30T08:47:02.474Z" }, - { url = "https://files.pythonhosted.org/packages/62/29/73ef0141b4732ff5eacd68430ff2512a65c004696997f70476a83e548e7e/grpcio-1.80.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:ce1794f4ea6cc3ca29463f42d665c32ba1b964b48958a66497917fe9069f26e6", size = 7851641, upload-time = "2026-03-30T08:47:05.462Z" }, - { url = "https://files.pythonhosted.org/packages/46/69/abbfa360eb229a8623bab5f5a4f8105e445bd38ce81a89514ba55d281ad0/grpcio-1.80.0-cp311-cp311-win32.whl", hash = "sha256:51b4a7189b0bef2aa30adce3c78f09c83526cf3dddb24c6a96555e3b97340440", size = 4154368, upload-time = "2026-03-30T08:47:08.027Z" }, - { url = "https://files.pythonhosted.org/packages/6f/d4/ae92206d01183b08613e846076115f5ac5991bae358d2a749fa864da5699/grpcio-1.80.0-cp311-cp311-win_amd64.whl", hash = "sha256:02e64bb0bb2da14d947a49e6f120a75e947250aebe65f9629b62bb1f5c14e6e9", size = 4894235, upload-time = "2026-03-30T08:47:10.839Z" }, - { url = "https://files.pythonhosted.org/packages/5c/e8/a2b749265eb3415abc94f2e619bbd9e9707bebdda787e61c593004ec927a/grpcio-1.80.0-cp312-cp312-linux_armv7l.whl", hash = "sha256:c624cc9f1008361014378c9d776de7182b11fe8b2e5a81bc69f23a295f2a1ad0", size = 6015616, upload-time = "2026-03-30T08:47:13.428Z" }, - { url = "https://files.pythonhosted.org/packages/3e/97/b1282161a15d699d1e90c360df18d19165a045ce1c343c7f313f5e8a0b77/grpcio-1.80.0-cp312-cp312-macosx_11_0_universal2.whl", hash = "sha256:f49eddcac43c3bf350c0385366a58f36bed8cc2c0ec35ef7b74b49e56552c0c2", size = 12014204, upload-time = "2026-03-30T08:47:15.873Z" }, - { url = "https://files.pythonhosted.org/packages/6e/5e/d319c6e997b50c155ac5a8cb12f5173d5b42677510e886d250d50264949d/grpcio-1.80.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:d334591df610ab94714048e0d5b4f3dd5ad1bee74dfec11eee344220077a79de", size = 6563866, upload-time = "2026-03-30T08:47:18.588Z" }, - { url = "https://files.pythonhosted.org/packages/ae/f6/fdd975a2cb4d78eb67769a7b3b3830970bfa2e919f1decf724ae4445f42c/grpcio-1.80.0-cp312-cp312-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:0cb517eb1d0d0aaf1d87af7cc5b801d686557c1d88b2619f5e31fab3c2315921", size = 7273060, upload-time = "2026-03-30T08:47:21.113Z" }, - { url = "https://files.pythonhosted.org/packages/db/f0/a3deb5feba60d9538a962913e37bd2e69a195f1c3376a3dd44fe0427e996/grpcio-1.80.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:4e78c4ac0d97dc2e569b2f4bcbbb447491167cb358d1a389fc4af71ab6f70411", size = 6782121, upload-time = "2026-03-30T08:47:23.827Z" }, - { url = "https://files.pythonhosted.org/packages/ca/84/36c6dcfddc093e108141f757c407902a05085e0c328007cb090d56646cdf/grpcio-1.80.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:2ed770b4c06984f3b47eb0517b1c69ad0b84ef3f40128f51448433be904634cd", size = 7383811, upload-time = "2026-03-30T08:47:26.517Z" }, - { url = "https://files.pythonhosted.org/packages/7c/ef/f3a77e3dc5b471a0ec86c564c98d6adfa3510d38f8ee99010410858d591e/grpcio-1.80.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:256507e2f524092f1473071a05e65a5b10d84b82e3ff24c5b571513cfaa61e2f", size = 8393860, upload-time = "2026-03-30T08:47:29.439Z" }, - { url = "https://files.pythonhosted.org/packages/9b/8d/9d4d27ed7f33d109c50d6b5ce578a9914aa68edab75d65869a17e630a8d1/grpcio-1.80.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:9a6284a5d907c37db53350645567c522be314bac859a64a7a5ca63b77bb7958f", size = 7830132, upload-time = "2026-03-30T08:47:33.254Z" }, - { url = "https://files.pythonhosted.org/packages/14/e4/9990b41c6d7a44e1e9dee8ac11d7a9802ba1378b40d77468a7761d1ad288/grpcio-1.80.0-cp312-cp312-win32.whl", hash = "sha256:c71309cfce2f22be26aa4a847357c502db6c621f1a49825ae98aa0907595b193", size = 4140904, upload-time = "2026-03-30T08:47:35.319Z" }, - { url = "https://files.pythonhosted.org/packages/2f/2c/296f6138caca1f4b92a31ace4ae1b87dab692fc16a7a3417af3bb3c805bf/grpcio-1.80.0-cp312-cp312-win_amd64.whl", hash = "sha256:9fe648599c0e37594c4809d81a9e77bd138cc82eb8baa71b6a86af65426723ff", size = 4880944, upload-time = "2026-03-30T08:47:37.831Z" }, - { url = "https://files.pythonhosted.org/packages/2f/3a/7c3c25789e3f069e581dc342e03613c5b1cb012c4e8c7d9d5cf960a75856/grpcio-1.80.0-cp313-cp313-linux_armv7l.whl", hash = "sha256:e9e408fc016dffd20661f0126c53d8a31c2821b5c13c5d67a0f5ed5de93319ad", size = 6017243, upload-time = "2026-03-30T08:47:40.075Z" }, - { url = "https://files.pythonhosted.org/packages/04/19/21a9806eb8240e174fd1ab0cd5b9aa948bb0e05c2f2f55f9d5d7405e6d08/grpcio-1.80.0-cp313-cp313-macosx_11_0_universal2.whl", hash = "sha256:92d787312e613754d4d8b9ca6d3297e69994a7912a32fa38c4c4e01c272974b0", size = 12010840, upload-time = "2026-03-30T08:47:43.11Z" }, - { url = "https://files.pythonhosted.org/packages/18/3a/23347d35f76f639e807fb7a36fad3068aed100996849a33809591f26eca6/grpcio-1.80.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:8ac393b58aa16991a2f1144ec578084d544038c12242da3a215966b512904d0f", size = 6567644, upload-time = "2026-03-30T08:47:46.806Z" }, - { url = "https://files.pythonhosted.org/packages/ff/40/96e07ecb604a6a67ae6ab151e3e35b132875d98bc68ec65f3e5ab3e781d7/grpcio-1.80.0-cp313-cp313-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:68e5851ac4b9afe07e7f84483803ad167852570d65326b34d54ca560bfa53fb6", size = 7277830, upload-time = "2026-03-30T08:47:49.643Z" }, - { url = "https://files.pythonhosted.org/packages/9b/e2/da1506ecea1f34a5e365964644b35edef53803052b763ca214ba3870c856/grpcio-1.80.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:873ff5d17d68992ef6605330127425d2fc4e77e612fa3c3e0ed4e668685e3140", size = 6783216, upload-time = "2026-03-30T08:47:52.817Z" }, - { url = "https://files.pythonhosted.org/packages/44/83/3b20ff58d0c3b7f6caaa3af9a4174d4023701df40a3f39f7f1c8e7c48f9d/grpcio-1.80.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:2bea16af2750fd0a899bf1abd9022244418b55d1f37da2202249ba4ba673838d", size = 7385866, upload-time = "2026-03-30T08:47:55.687Z" }, - { url = "https://files.pythonhosted.org/packages/47/45/55c507599c5520416de5eefecc927d6a0d7af55e91cfffb2e410607e5744/grpcio-1.80.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:ba0db34f7e1d803a878284cd70e4c63cb6ae2510ba51937bf8f45ba997cefcf7", size = 8391602, upload-time = "2026-03-30T08:47:58.303Z" }, - { url = "https://files.pythonhosted.org/packages/10/bb/dd06f4c24c01db9cf11341b547d0a016b2c90ed7dbbb086a5710df7dd1d7/grpcio-1.80.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:8eb613f02d34721f1acf3626dfdb3545bd3c8505b0e52bf8b5710a28d02e8aa7", size = 7826752, upload-time = "2026-03-30T08:48:01.311Z" }, - { url = "https://files.pythonhosted.org/packages/f9/1e/9d67992ba23371fd63d4527096eb8c6b76d74d52b500df992a3343fd7251/grpcio-1.80.0-cp313-cp313-win32.whl", hash = "sha256:93b6f823810720912fd131f561f91f5fed0fda372b6b7028a2681b8194d5d294", size = 4142310, upload-time = "2026-03-30T08:48:04.594Z" }, - { url = "https://files.pythonhosted.org/packages/cf/e6/283326a27da9e2c3038bc93eeea36fb118ce0b2d03922a9cda6688f53c5b/grpcio-1.80.0-cp313-cp313-win_amd64.whl", hash = "sha256:e172cf795a3ba5246d3529e4d34c53db70e888fa582a8ffebd2e6e48bc0cba50", size = 4882833, upload-time = "2026-03-30T08:48:07.363Z" }, - { url = "https://files.pythonhosted.org/packages/c5/6d/e65307ce20f5a09244ba9e9d8476e99fb039de7154f37fb85f26978b59c3/grpcio-1.80.0-cp314-cp314-linux_armv7l.whl", hash = "sha256:3d4147a97c8344d065d01bbf8b6acec2cf86fb0400d40696c8bdad34a64ffc0e", size = 6017376, upload-time = "2026-03-30T08:48:10.005Z" }, - { url = "https://files.pythonhosted.org/packages/69/10/9cef5d9650c72625a699c549940f0abb3c4bfdb5ed45a5ce431f92f31806/grpcio-1.80.0-cp314-cp314-macosx_11_0_universal2.whl", hash = "sha256:d8e11f167935b3eb089ac9038e1a063e6d7dbe995c0bb4a661e614583352e76f", size = 12018133, upload-time = "2026-03-30T08:48:12.927Z" }, - { url = "https://files.pythonhosted.org/packages/04/82/983aabaad82ba26113caceeb9091706a0696b25da004fe3defb5b346e15b/grpcio-1.80.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:f14b618fc30de822681ee986cfdcc2d9327229dc4c98aed16896761cacd468b9", size = 6574748, upload-time = "2026-03-30T08:48:16.386Z" }, - { url = "https://files.pythonhosted.org/packages/07/d7/031666ef155aa0bf399ed7e19439656c38bbd143779ae0861b038ce82abd/grpcio-1.80.0-cp314-cp314-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:4ed39fbdcf9b87370f6e8df4e39ca7b38b3e5e9d1b0013c7b6be9639d6578d14", size = 7277711, upload-time = "2026-03-30T08:48:19.627Z" }, - { url = "https://files.pythonhosted.org/packages/e8/43/f437a78f7f4f1d311804189e8f11fb311a01049b2e08557c1068d470cb2e/grpcio-1.80.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:2dcc70e9f0ba987526e8e8603a610fb4f460e42899e74e7a518bf3c68fe1bf05", size = 6785372, upload-time = "2026-03-30T08:48:22.373Z" }, - { url = "https://files.pythonhosted.org/packages/93/3d/f6558e9c6296cb4227faa5c43c54a34c68d32654b829f53288313d16a86e/grpcio-1.80.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:448c884b668b868562b1bda833c5fce6272d26e1926ec46747cda05741d302c1", size = 7395268, upload-time = "2026-03-30T08:48:25.638Z" }, - { url = "https://files.pythonhosted.org/packages/06/21/0fdd77e84720b08843c371a2efa6f2e19dbebf56adc72df73d891f5506f0/grpcio-1.80.0-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:a1dc80fe55685b4a543555e6eef975303b36c8db1023b1599b094b92aa77965f", size = 8392000, upload-time = "2026-03-30T08:48:28.974Z" }, - { url = "https://files.pythonhosted.org/packages/f5/68/67f4947ed55d2e69f2cc199ab9fd85e0a0034d813bbeef84df6d2ba4d4b7/grpcio-1.80.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:31b9ac4ad1aa28ffee5503821fafd09e4da0a261ce1c1281c6c8da0423c83b6e", size = 7828477, upload-time = "2026-03-30T08:48:32.054Z" }, - { url = "https://files.pythonhosted.org/packages/44/b6/8d4096691b2e385e8271911a0de4f35f0a6c7d05aff7098e296c3de86939/grpcio-1.80.0-cp314-cp314-win32.whl", hash = "sha256:367ce30ba67d05e0592470428f0ec1c31714cab9ef19b8f2e37be1f4c7d32fae", size = 4218563, upload-time = "2026-03-30T08:48:34.538Z" }, - { 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" }, +sdist = { url = "https://files.pythonhosted.org/packages/b0/b5/1ff353970a87eda4c98251e34d2dfd214abd4982dc89119c9252a2a482d2/grpcio-1.81.1.tar.gz", hash = "sha256:6fa10a767143a5e82e8eaab53918af0cd8909a57a27f8cb2288b80a613ac671b", size = 13026582, upload-time = "2026-06-11T12:46:51.673Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/9a/d5/f2b159d8eec08be2a855ef698f5b6f7f9fdda022e4dd9e4f5d968affd678/grpcio-1.81.1-cp310-cp310-linux_armv7l.whl", hash = "sha256:6f9a0c9c1cc15c112d1c053064fd032b64917062292c3d70aea280e02ae10b77", size = 6086868, upload-time = "2026-06-11T12:44:19.364Z" }, + { url = "https://files.pythonhosted.org/packages/80/41/9c95232b94b219ed8b14029d9cd000e0381cafba869c451dda60af84f4ba/grpcio-1.81.1-cp310-cp310-macosx_11_0_universal2.whl", hash = "sha256:69ef28e54fc85397f91b8c19592b8ef3d81952080366914823bd8572a2958120", size = 12062291, upload-time = "2026-06-11T12:44:27.142Z" }, + { url = "https://files.pythonhosted.org/packages/83/8b/bd9284bdd665ddf877a3e8bc2930d1bcf6ebdbae7b0da5c783dc26bd6e33/grpcio-1.81.1-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:15641444eca4a29358107b3dceb74c1c6305c55c822fd199b458aaea4068a7fb", size = 6635242, upload-time = "2026-06-11T12:44:30.741Z" }, + { url = "https://files.pythonhosted.org/packages/60/24/78fa025517a925f1a17da71c4ef9d5f1c6f9fa65af22dfb523c5c6317a21/grpcio-1.81.1-cp310-cp310-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:d4b2dddfc219f54f956ccd53cf76a1d338ffe68fc7f2849ec9c7feb9927ff692", size = 7332974, upload-time = "2026-06-11T12:44:33.72Z" }, + { url = "https://files.pythonhosted.org/packages/f7/11/402295b388dd35861007f8a26a37c2e2f284212d57bdf407c31f36043746/grpcio-1.81.1-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:ca1cc11d82677b9662082e5478b7528e2b7db7beaa6bdff42bd62789d81be399", size = 6836597, upload-time = "2026-06-11T12:44:36.108Z" }, + { url = "https://files.pythonhosted.org/packages/4d/71/37b10fd4fd579ffade6e695c14e9df5e8cba9e2365b81c131da438b67c34/grpcio-1.81.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:aa2ba7d2ad6df4d80127cea65e5b8d5e2c3adbf153ff4804452836328aca7c54", size = 7440660, upload-time = "2026-06-11T12:44:38.664Z" }, + { url = "https://files.pythonhosted.org/packages/4a/d5/40203f828abc83d458b634666df6df13778032f178c03845ad5a93682388/grpcio-1.81.1-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:592b5fee597faa91cce2dd294dd7d9a1c83d76c4dbf877e33ec1adb866b2fbed", size = 8443171, upload-time = "2026-06-11T12:44:41.678Z" }, + { url = "https://files.pythonhosted.org/packages/eb/2c/0ed82ea35b5ec595e10444940c1db8c0e0ef57aa46bc8797d5ff838a219e/grpcio-1.81.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:62481553b1793a27e9b9c3cf9e5bd483ef045ca72462592074b46d42b0c4d9b9", size = 7868905, upload-time = "2026-06-11T12:44:44.854Z" }, + { url = "https://files.pythonhosted.org/packages/9e/1f/dcbdc1a68a07cc2b631c3098953794f17d75f93426a019240b90ce5423d6/grpcio-1.81.1-cp310-cp310-win32.whl", hash = "sha256:bb693b1e3d9a2f3fd228e2110daf4b5aeedb36761ca1e4282f74725f6d89f611", size = 4202215, upload-time = "2026-06-11T12:44:47.165Z" }, + { url = "https://files.pythonhosted.org/packages/75/a1/d7ab9f1f42efcb7d9e6111d38be6b367737a72ea2c534e1f55c81e1b6436/grpcio-1.81.1-cp310-cp310-win_amd64.whl", hash = "sha256:88268ca418cacea64cecb0d1d600d3c6b3a8038fcba02e1e205178c5b1f47661", size = 4936582, upload-time = "2026-06-11T12:44:49.479Z" }, + { url = "https://files.pythonhosted.org/packages/52/ea/1c2fa386b718ff493225e61cfc052ef400b4d6ffc54cbe261026432624b5/grpcio-1.81.1-cp311-cp311-linux_armv7l.whl", hash = "sha256:d71d30f2d92f67d944631c523713934fee37292469e182ebcd2c1dd8a64ce53f", size = 6093112, upload-time = "2026-06-11T12:44:52.131Z" }, + { url = "https://files.pythonhosted.org/packages/2b/18/acf45fa8bd1bc5d7b0c2fd3dc4c209379fbd5bb396b440b68a83342226b7/grpcio-1.81.1-cp311-cp311-macosx_11_0_universal2.whl", hash = "sha256:b137f4bf3ada9dc44d411478decc6ff09a79ed30b306cd2abaa98408c3588137", size = 12074277, upload-time = "2026-06-11T12:44:55.354Z" }, + { url = "https://files.pythonhosted.org/packages/48/d7/ee86a60699b7db039f772a2c4a7e4facc7138984ff42c0130933a0063884/grpcio-1.81.1-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:a3acb384427816dd5d470f47e62137b87f74da694faa8a50147012cf40df276a", size = 6640348, upload-time = "2026-06-11T12:44:59.223Z" }, + { url = "https://files.pythonhosted.org/packages/26/ee/d2de5e47378ffc207d476c230fea3be4d2601edbce9995f4fe45535d4896/grpcio-1.81.1-cp311-cp311-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:f9a0ebbe45c29b5e5866593c12b78bd9035f0f0f0d4bc8361680cd580d99db49", size = 7331842, upload-time = "2026-06-11T12:45:02.001Z" }, + { url = "https://files.pythonhosted.org/packages/23/d6/abeda5c2b896a0b341584fe5ac411bbf72e197a9a374c355fb90965e08d2/grpcio-1.81.1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:0a37165cc80b1a368384b383e63a4c38116a10467ae44c904d2d7468c4470ec2", size = 6842229, upload-time = "2026-06-11T12:45:04.76Z" }, + { url = "https://files.pythonhosted.org/packages/10/1c/1f0da7d590b4aeee006826ba568d0e419ca14b23e18f901a3da3e9fba613/grpcio-1.81.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:6282caffb41ec326d4cb67ca9cf53b739d1b2f975a2acb498c7418e9f7d9a416", size = 7446096, upload-time = "2026-06-11T12:45:07.499Z" }, + { url = "https://files.pythonhosted.org/packages/6a/81/5c505d508f7c887aa7982d21443a4126597c80d34b0bcf40f9cec576d7f3/grpcio-1.81.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:a35009284d0d3d5c2c9601c164a911b8b4331608d98a9a66d47d97bb2f522b70", size = 8445238, upload-time = "2026-06-11T12:45:10.243Z" }, + { url = "https://files.pythonhosted.org/packages/f7/b2/524847365122ee509ca17bcc4e092198b700e94af7bfd5bb5e6dd9f3ee66/grpcio-1.81.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:1b22c80559854b789a01fd89e8929b3798a156c0829b5282a8939f33ad4115ad", size = 7873989, upload-time = "2026-06-11T12:45:13.102Z" }, + { url = "https://files.pythonhosted.org/packages/18/fa/07c037c50b006909d1d13a5848774f8aa7b242f70dc03a035c64eea0e6db/grpcio-1.81.1-cp311-cp311-win32.whl", hash = "sha256:428bec0161b48d8cf583c068591bc0016d0d9cfff52462b72b3884861ea768c5", size = 4202223, upload-time = "2026-06-11T12:45:16.166Z" }, + { url = "https://files.pythonhosted.org/packages/41/ed/6bff15376920942fac6b95b9802752b837437172c9e8fc2d3170546b89cc/grpcio-1.81.1-cp311-cp311-win_amd64.whl", hash = "sha256:30e825f6848d9f18bba350ed6c75c1b02a0b5184474a31db9a32b1fa66fd8c79", size = 4941303, upload-time = "2026-06-11T12:45:18.724Z" }, + { url = "https://files.pythonhosted.org/packages/85/07/9a979c81738863a738dc23d65177056e71fbb2db817740ed870b33434e7a/grpcio-1.81.1-cp312-cp312-linux_armv7l.whl", hash = "sha256:8b39472beafc0bdcafc4c8c73ad082ebfdb449d566897a61e7acb4fa88089115", size = 6053264, upload-time = "2026-06-11T12:45:21.017Z" }, + { url = "https://files.pythonhosted.org/packages/75/95/539706ca0d3bd40dbad583dc56fd883da941f37556b629132da5762781b9/grpcio-1.81.1-cp312-cp312-macosx_11_0_universal2.whl", hash = "sha256:12b7524c88d4026d3dcb7b0ebe16b6714f3b4af402ddd0f0639ab064a00c87c3", size = 12052560, upload-time = "2026-06-11T12:45:23.652Z" }, + { url = "https://files.pythonhosted.org/packages/e0/44/f257b7e0bd69c93b06c6cb8ac8d1b901ccb42bedabd83c1a4c77a71f8810/grpcio-1.81.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:1e123f9b37edb8375fd74130d1f69c944bbf0a7b06761ae7211154b8759e94d2", size = 6595983, upload-time = "2026-06-11T12:45:26.963Z" }, + { url = "https://files.pythonhosted.org/packages/b9/f3/19782aa04c960968bef8c5539329d8e3bbc3364e2e46d19eb5e5cc5e43b7/grpcio-1.81.1-cp312-cp312-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:2c2e2ae6867c2966b8daccc836d54a13218e0007e9a490aeb81dd05be64d22d7", size = 7303455, upload-time = "2026-06-11T12:45:29.707Z" }, + { url = "https://files.pythonhosted.org/packages/eb/8c/dea020b6d91508cd84463917a63149ec196ee7db505d032ae43fcb3303b9/grpcio-1.81.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:766bc7c9a9c340342f4c864ccbda8e78111e4751f13b895812b9c148fb79e9d0", size = 6809167, upload-time = "2026-06-11T12:45:32.52Z" }, + { url = "https://files.pythonhosted.org/packages/1c/c7/3030dd940408083bd32cd95d634777a71605ade4887154d93e8a89244946/grpcio-1.81.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:b259a04a737cb3496be0901328eb8b7552ed8df4865d8c8f1cf1bffcfc0776a3", size = 7412536, upload-time = "2026-06-11T12:45:35.403Z" }, + { url = "https://files.pythonhosted.org/packages/e0/dd/1172a9e42b168edcafefad6115346ef619a3fc02158bb170e66ced24bcdd/grpcio-1.81.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:85b10a45b8993d195c4f3ff57025b8d1e11834909ee475c403bfa60cb4caefaf", size = 8408276, upload-time = "2026-06-11T12:45:37.78Z" }, + { url = "https://files.pythonhosted.org/packages/25/7a/71437c7f3596e5246155c515852795a85a1a8d228190212432b13b97a95d/grpcio-1.81.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:8ea1936c26b99999b27479853039a7f34713f56c49375ad52b38535ec93a796c", size = 7849660, upload-time = "2026-06-11T12:45:40.627Z" }, + { url = "https://files.pythonhosted.org/packages/65/40/7debc0da45d2efebafb82da75644be347497fe4ee250514b8cd3b86ae8bf/grpcio-1.81.1-cp312-cp312-win32.whl", hash = "sha256:a185a04039df6cae8648bc8ab6d6fde7bf94f7188ecf7828e76ac52eef1e41d6", size = 4185819, upload-time = "2026-06-11T12:45:43.027Z" }, + { url = "https://files.pythonhosted.org/packages/2e/b9/8fe3ba5ed462067774ebc1f9c7f26aa7ebcc280ddd476be107153de1339e/grpcio-1.81.1-cp312-cp312-win_amd64.whl", hash = "sha256:3ad74f8bb1a18963914c5452d289422830b39459e8776ebbcd207be1fbfb1d94", size = 4930461, upload-time = "2026-06-11T12:45:45.775Z" }, + { url = "https://files.pythonhosted.org/packages/7a/42/dcc2e4b600538ef18327c0839d56b7d3c3812337c5d710df5877dbb39b1e/grpcio-1.81.1-cp313-cp313-linux_armv7l.whl", hash = "sha256:b10e1ff4756ed27d5a29d7fc79cfce7ef1ff56ad20025b89bac7cf79e09abbbe", size = 6054466, upload-time = "2026-06-11T12:45:48.43Z" }, + { url = "https://files.pythonhosted.org/packages/7b/4a/a36e03210183a8a7d4c80c3936acee679f4bd77d5861f369db47b2cc5f05/grpcio-1.81.1-cp313-cp313-macosx_11_0_universal2.whl", hash = "sha256:819edbdcb42ab8598b494bcf0222684bbb7a3c772bd1b1f0be7e029a6063c28e", size = 12048795, upload-time = "2026-06-11T12:45:54.011Z" }, + { url = "https://files.pythonhosted.org/packages/b0/d5/d68e30b29098f63beab6fe501100fe82674ff142b32c672532da86a99b3a/grpcio-1.81.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:c5bf2dc311127d91230cc79b92188c082634a06cf66c5234db49a43b910183b0", size = 6599094, upload-time = "2026-06-11T12:45:57.799Z" }, + { url = "https://files.pythonhosted.org/packages/3d/b3/e837954d279754f638a11cca5dcf6b24a005efb398984cefaf7735945a54/grpcio-1.81.1-cp313-cp313-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:e8ca6a1fcdb2943c9cbc1804a1baf3acb6071d72a471591678ded84218006e14", size = 7307182, upload-time = "2026-06-11T12:46:00.568Z" }, + { url = "https://files.pythonhosted.org/packages/0d/1e/b47957057e729adc6cdf519a47f8be2562b7140e280f1418443eb4022192/grpcio-1.81.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:e64dd101d380a115cc5a0c7856788adb535f1a4e21fc543775602f8be95180ae", size = 6810962, upload-time = "2026-06-11T12:46:03.312Z" }, + { url = "https://files.pythonhosted.org/packages/40/26/569868e364e05b19ec8f969da53d230bcd89c962cd198f7c29943155c4d3/grpcio-1.81.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:98a07f9bf591e3a8919797bee1c53f026ba4acd587e5a4404c8e57c9ec36b2a5", size = 7415698, upload-time = "2026-06-11T12:46:06.005Z" }, + { url = "https://files.pythonhosted.org/packages/36/0c/5440a0582cb5653fc42a6e262eeb22700943313f8076f9dc927491b20a59/grpcio-1.81.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:c261d74b1a945cf895a9d6eccd1685a8e837531beaab782da4d630a8d12deffb", size = 8407779, upload-time = "2026-06-11T12:46:08.84Z" }, + { url = "https://files.pythonhosted.org/packages/ff/aa/66fe9f39871d766987d869a03ee0842a026f499c7b1e62decb9e78a8088e/grpcio-1.81.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:58ad1131c300d3c9b933802b3cc4dc69d380822935ba50b28703156ea826fbf7", size = 7844521, upload-time = "2026-06-11T12:46:12.171Z" }, + { url = "https://files.pythonhosted.org/packages/f0/9e/69bb7194861bcd28fb3193261d4f9c3831b4446993f002cf59068943e7ab/grpcio-1.81.1-cp313-cp313-win32.whl", hash = "sha256:78e29211f26da2fdd0e9c6d2b79f489476140cf7029b6a64808ade7ca4156a42", size = 4182786, upload-time = "2026-06-11T12:46:15.192Z" }, + { url = "https://files.pythonhosted.org/packages/0d/20/3da8bb0d637feccdc3e1e419bb511ce93651ce7d54164f95de22cc0b8b34/grpcio-1.81.1-cp313-cp313-win_amd64.whl", hash = "sha256:edb59506291b647a30884b1d51a599d605f40b20af4a7dc3d33786a47a31de60", size = 4928648, upload-time = "2026-06-11T12:46:17.823Z" }, + { url = "https://files.pythonhosted.org/packages/b6/58/19414622b1bf6981bc9c05a365bd548e71876c89000083b3af489251e9c0/grpcio-1.81.1-cp314-cp314-linux_armv7l.whl", hash = "sha256:506f48f2f9c29b143fca3dad7b0d518c188b6c9648c75a2ae6e2d9f2c13a060b", size = 6055336, upload-time = "2026-06-11T12:46:20.557Z" }, + { url = "https://files.pythonhosted.org/packages/32/f1/2ec88adb92b0eba970dd0e0e7dd086341daa3c75eba4f735f9e44bf684b0/grpcio-1.81.1-cp314-cp314-macosx_11_0_universal2.whl", hash = "sha256:d865db4a6318e1c1bea83292e0ed231090538fc4ca45425b0f0480eb338bbc6e", size = 12056279, upload-time = "2026-06-11T12:46:24.255Z" }, + { url = "https://files.pythonhosted.org/packages/41/36/e8c5f8c6ec71de73733695ebc809e98b178b534ec6d8eaa31a7ebab4ad4c/grpcio-1.81.1-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:e2aa72e3ce1770317ef534f63d397b55e130725f5149bd36077c3b539019db27", size = 6608225, upload-time = "2026-06-11T12:46:27.601Z" }, + { url = "https://files.pythonhosted.org/packages/30/22/96fc577a845ab093326d9ab1adb874bd4936c8cf98ac8ed2f3db13a0a2fb/grpcio-1.81.1-cp314-cp314-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:0490c30c261eded63f3f354979f9dc4502a9fb944cccb60cd9dc85f5a7349854", size = 7306576, upload-time = "2026-06-11T12:46:30.514Z" }, + { url = "https://files.pythonhosted.org/packages/76/7b/61dab5d5969f28d97fb1009cead1df0a5cd987d3315e1b37f18a4449f8bc/grpcio-1.81.1-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:410482da976329fe5f4067270401b12cf2bd552ff8020f054ecfaddb5475f9d6", size = 6812165, upload-time = "2026-06-11T12:46:33.699Z" }, + { url = "https://files.pythonhosted.org/packages/82/78/6e501929d4f5f96462fd82fd9f0f06e5f9612207582b862868d68757b27d/grpcio-1.81.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:e3657301562ac3cb8018d30d0d3ebfa39932239f7b5703422057ef14b69949f5", size = 7422962, upload-time = "2026-06-11T12:46:36.511Z" }, + { url = "https://files.pythonhosted.org/packages/2a/7e/f2157589e66daa78ebb3165942d05a08bdea93b9d11c2bc1e172aef89685/grpcio-1.81.1-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:24c8e57504c8f45b237e40b99262d181071e5099a07053695b75d97bb53053a0", size = 8408176, upload-time = "2026-06-11T12:46:39.803Z" }, + { url = "https://files.pythonhosted.org/packages/da/df/c6717fef716e00d235ffb96123baf6dce76d6004f6233fa767c502861460/grpcio-1.81.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:b427c19380991a4eaab2f6144b64b99b412043314c6bf4ab544f97bb31ee4190", size = 7846681, upload-time = "2026-06-11T12:46:43.013Z" }, + { url = "https://files.pythonhosted.org/packages/36/84/3502e9f210a6a5c4438c8aca3f88edd2e04f6a27f3d41b26cf0a0024b096/grpcio-1.81.1-cp314-cp314-win32.whl", hash = "sha256:61233fe8951e5c85dff81c2458b6528624760166946b5b47ea150a589168411f", size = 4264615, upload-time = "2026-06-11T12:46:45.741Z" }, + { url = "https://files.pythonhosted.org/packages/ff/b0/4af731ff7492c68a96e4c71bfd0f4590acde92b31c6fe4894e6465c10ff6/grpcio-1.81.1-cp314-cp314-win_amd64.whl", hash = "sha256:3768a5ff1b2125e6f552e561b6b2dca0e64982d8949689b4df145cf8b98d7821", size = 5070275, upload-time = "2026-06-11T12:46:48.486Z" }, ] [[package]] name = "grpcio-status" -version = "1.80.0" +version = "1.81.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "googleapis-common-protos" }, { name = "grpcio" }, { name = "protobuf" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/b1/ed/105f619bdd00cb47a49aa2feea6232ea2bbb04199d52a22cc6a7d603b5cb/grpcio_status-1.80.0.tar.gz", hash = "sha256:df73802a4c89a3ea88aa2aff971e886fccce162bc2e6511408b3d67a144381cd", size = 13901, upload-time = "2026-03-30T08:54:34.784Z" } +sdist = { url = "https://files.pythonhosted.org/packages/32/26/0aa9168c87882381fd810d140c279a2490ed6aee655f0515d6f56c5ca404/grpcio_status-1.81.1.tar.gz", hash = "sha256:9389a03e746017b10f0630c064289201458f3ce01f5d7ef4b0bebc1ef6cf82ad", size = 13923, upload-time = "2026-06-11T12:58:48.636Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/76/80/58cd2dfc19a07d022abe44bde7c365627f6c7cb6f692ada6c65ca437d09a/grpcio_status-1.80.0-py3-none-any.whl", hash = "sha256:4b56990363af50dbf2c2ebb80f1967185c07d87aa25aa2bea45ddb75fc181dbe", size = 14638, upload-time = "2026-03-30T08:54:01.569Z" }, + { url = "https://files.pythonhosted.org/packages/e5/5e/5abfec5f7e89d3b7993d57cfb025ca5f968a2c18656d7fcda2b6919440b9/grpcio_status-1.81.1-py3-none-any.whl", hash = "sha256:08072fa9995f4a95c647fc6f4f85e2411573d00087bcabdf30f260114338f232", size = 14638, upload-time = "2026-06-11T12:58:31.982Z" }, ] [[package]] name = "grpcio-tools" -version = "1.80.0" +version = "1.81.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "grpcio" }, { name = "protobuf" }, { name = "setuptools" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/94/c8/1223f29c84a143ae9a56c084fc96894de0ba84b6e8d60a26241abd81d278/grpcio_tools-1.80.0.tar.gz", hash = "sha256:26052b19c6ce0dcf52d1024496aea3e2bdfa864159f06dc7b97b22d041a94b26", size = 6133212, upload-time = "2026-03-30T08:52:39.077Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/7a/54/1de67f5080da305a258758a8deb33f85666fa759f56785042a80b114a53f/grpcio_tools-1.80.0-cp310-cp310-linux_armv7l.whl", hash = "sha256:727477b9afa4b53f5ec70cafb41c3965d893835e0d4ea9b542fe3d0d005602bf", size = 2549601, upload-time = "2026-03-30T08:50:09.498Z" }, - { url = "https://files.pythonhosted.org/packages/9a/b4/6d57ea199c5b880d182a2234aafa9a686f9c54c708ea7be75bd19d5aa825/grpcio_tools-1.80.0-cp310-cp310-macosx_11_0_universal2.whl", hash = "sha256:85fe8d15f146c62cb76f38d963e256392d287442b9232717d30ae9e3bbda9bc3", size = 5712717, upload-time = "2026-03-30T08:50:15.028Z" }, - { url = "https://files.pythonhosted.org/packages/6a/1a/5505ee2277d368b409c796c78f22ea34a2a517b7d16755247efd663dc7af/grpcio_tools-1.80.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:95f0fffb5ca00519f3b602f938169b4dfa04b165e03258323965a9dfe8cc4d80", size = 2595941, upload-time = "2026-03-30T08:50:17.299Z" }, - { url = "https://files.pythonhosted.org/packages/4e/39/7fc1d16d8b767805079d76365d73e82c88dfaf179034473dbc9fbccedb77/grpcio_tools-1.80.0-cp310-cp310-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:7a0106af212748823a6ebd8ffbd9043414216f47cae3835f3187de0a62c415d3", size = 2909304, upload-time = "2026-03-30T08:50:19.485Z" }, - { url = "https://files.pythonhosted.org/packages/97/d8/276ee759755d8f34f2ca5e9d2debd1a59f29f66059fb790bc369f2236c26/grpcio_tools-1.80.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:31fd01a4038b5dfc4ec79504a17061344f670f851833411717fef66920f13cd7", size = 2660269, upload-time = "2026-03-30T08:50:21.266Z" }, - { url = "https://files.pythonhosted.org/packages/51/04/a6bb47942ad52901d777a649324d3203cf19d487f1d446263637f7a5bf12/grpcio_tools-1.80.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:57da9e19607fac4a01c48ead333c0dd15d91ed38794dce1194eda308f73e2038", size = 3109798, upload-time = "2026-03-30T08:50:23.267Z" }, - { url = "https://files.pythonhosted.org/packages/be/50/7ee69b2919916739787d725f205b878e8d1619dd30422b8278e324664669/grpcio_tools-1.80.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:90968f751851abb8b145593609800fa70c837e1c93ba0792c480b1c8d8bc29ef", size = 3658930, upload-time = "2026-03-30T08:50:25.458Z" }, - { url = "https://files.pythonhosted.org/packages/92/61/6d50783092b0e8bbcb04152d5388bf50ecf3ea2f783d95288ff6c3bb00fa/grpcio_tools-1.80.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:b69dc5d6376ab43406304d1e2fc61ccf960b287d4325d77c3d45448c37a9d2da", size = 3326562, upload-time = "2026-03-30T08:50:27.809Z" }, - { url = "https://files.pythonhosted.org/packages/ea/58/d272ba549f6b1f0d8504f5fc4cd0a296f2c495a64d6e987fe871c4151557/grpcio_tools-1.80.0-cp310-cp310-win32.whl", hash = "sha256:3e8dcfebe34cb54df095de3d5871a4562a85a29f26d0f8bb41ee2c3dcfb11c3c", size = 997620, upload-time = "2026-03-30T08:50:29.959Z" }, - { url = "https://files.pythonhosted.org/packages/70/5f/9f45a9946a0298711c72ca48b2c1f46a7d0c207a44cd3e4bb59d04556ba3/grpcio_tools-1.80.0-cp310-cp310-win_amd64.whl", hash = "sha256:fc622ed4ca400695f41c9eae3266276c6ba007e4c28164ce53b44e7ccc5e492b", size = 1162466, upload-time = "2026-03-30T08:50:32.242Z" }, - { url = "https://files.pythonhosted.org/packages/8a/d7/225dc91e6cb4f8d4830f16a478a468e9c6f342dcdf8cacc3772cc1d1f607/grpcio_tools-1.80.0-cp311-cp311-linux_armv7l.whl", hash = "sha256:1c43e5c768578fe0c6de3dbfaabe64af642951e1aa05c487cacedda63fa6c6c4", size = 2549937, upload-time = "2026-03-30T08:50:34.651Z" }, - { url = "https://files.pythonhosted.org/packages/97/3d/a3684cb7677f3bea8db434eae02a9ce30135d7a268cd473b1bc8041c4722/grpcio_tools-1.80.0-cp311-cp311-macosx_11_0_universal2.whl", hash = "sha256:a225348456575f3ac7851d8e23163195e76d2a905ee340cf73f33da62fba08aa", size = 5713099, upload-time = "2026-03-30T08:50:37.158Z" }, - { url = "https://files.pythonhosted.org/packages/b1/81/5665c697173ec346076358bfbfed0f7386825852494593ca14386478dfee/grpcio_tools-1.80.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:a9396f02820d3f51c368c2c9dee15c55c77636c91be48a4d5c702e98d6fe0fdc", size = 2595776, upload-time = "2026-03-30T08:50:39.087Z" }, - { url = "https://files.pythonhosted.org/packages/03/4f/fb81384f08a8226fa079972ba88272ac6277581fc72e8ab234d74c7e065b/grpcio_tools-1.80.0-cp311-cp311-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:797c08460cae16b402326eac329aec720dccf45c9f9279b95a352792eb53cf0f", size = 2909144, upload-time = "2026-03-30T08:50:40.922Z" }, - { url = "https://files.pythonhosted.org/packages/4d/9c/c957618f1c2a3195ecf5e83b03edcb364c2c1391f74183cb76e5763fa536/grpcio_tools-1.80.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:1872a867eb6217de19edb70a4ce4a374ced9d94293533dfd42fa649713f55bf4", size = 2660477, upload-time = "2026-03-30T08:50:42.766Z" }, - { url = "https://files.pythonhosted.org/packages/42/c7/23913da184febfd4eaf04de256a26bc5ff0411a5feb753e2adcff10fa86a/grpcio_tools-1.80.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:db122ba5ee357e3bb14e8944d69bbebcbdae91d5eace29ed4df3edc53cbc6528", size = 3110164, upload-time = "2026-03-30T08:50:44.761Z" }, - { url = "https://files.pythonhosted.org/packages/af/fa/b25ed85ebdb0396910eaa250b1346d75527d22fca586265416bd4330dcd5/grpcio_tools-1.80.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:ddefd48c227e6f4d640fe576fac5fb2c4a8898196f513604c8ec7671b3b3d421", size = 3658988, upload-time = "2026-03-30T08:50:47.546Z" }, - { url = "https://files.pythonhosted.org/packages/60/85/2a55147cc9645e2ed777d1afcd2dc68cb34ba6f6c726bd4378ddb001a5ea/grpcio_tools-1.80.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:970ec058fa469dd6dae6ebc687501c5da670d95dead75f62f5b0933dce2c9794", size = 3326662, upload-time = "2026-03-30T08:50:49.59Z" }, - { url = "https://files.pythonhosted.org/packages/68/ed/b05bee2a992e6f9bda81909692ea920d0896cfa05c5c9dd77ba03f2d22fb/grpcio_tools-1.80.0-cp311-cp311-win32.whl", hash = "sha256:526b4402d47a0e9b31cd6087e42b7674784617916cc73c764e0bc35ed41b4ee5", size = 997969, upload-time = "2026-03-30T08:50:51.539Z" }, - { url = "https://files.pythonhosted.org/packages/b6/9a/cb50c8270e2f6285ff2761130ae257ac4e51789ded4b9d9710ce0381814d/grpcio_tools-1.80.0-cp311-cp311-win_amd64.whl", hash = "sha256:ee101ecda7231770f6a5da1024a9a6ed587a7785f8fe23ab8283f4a1acb3ffe6", size = 1162742, upload-time = "2026-03-30T08:50:54.232Z" }, - { url = "https://files.pythonhosted.org/packages/0c/b9/65929df8c9614792db900a8e45d4997fadbd1734c827da3f0eb1f2fe4866/grpcio_tools-1.80.0-cp312-cp312-linux_armv7l.whl", hash = "sha256:d19d5a8244311947b96f749c417b32d144641c6953f1164824579e1f0a51d040", size = 2550856, upload-time = "2026-03-30T08:50:57.3Z" }, - { url = "https://files.pythonhosted.org/packages/28/17/af1557544d68d1aeca9d9ea53ed16524022d521fec6ba334ab3530e9c1a6/grpcio_tools-1.80.0-cp312-cp312-macosx_11_0_universal2.whl", hash = "sha256:fb599a3dc89ed1bb24489a2724b2f6dd4cddbbf0f7bdd69c073477bab0dc7554", size = 5710883, upload-time = "2026-03-30T08:51:00.077Z" }, - { url = "https://files.pythonhosted.org/packages/cc/48/aa9b4f7519ca972bc40d315d5c28f05ca28fa08de13d4e8b69f551b798ab/grpcio_tools-1.80.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:623ee31fc2ff7df9a987b4f3d139c30af17ce46a861ae0e25fb8c112daa32dd8", size = 2598004, upload-time = "2026-03-30T08:51:02.102Z" }, - { url = "https://files.pythonhosted.org/packages/b4/b8/b01371c119924b3beca1fe3f047b1bc2cdc66b3d37f0f3acc9d10c567a43/grpcio_tools-1.80.0-cp312-cp312-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:b46570a68378539ee2b75a5a43202561f8d753c832798b1047099e3c551cf5d6", size = 2909568, upload-time = "2026-03-30T08:51:04.159Z" }, - { url = "https://files.pythonhosted.org/packages/4f/7c/1108f7bdb58475a7e701ec89b55eb494538b6e76acd211ba0d4cc5fd28e8/grpcio_tools-1.80.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:51caf99c28999e7e0f97e9cea190c1405b7681a57bb2e0631205accd92b43fa4", size = 2660938, upload-time = "2026-03-30T08:51:06.126Z" }, - { url = "https://files.pythonhosted.org/packages/67/59/d1c0063d4cd3b85363c7044ff3e5159d6d5df96e2692a9a5312d9c8cb290/grpcio_tools-1.80.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:cdaa1c9aa8d3a87891a96700cadd29beec214711d6522818d207277f6452567c", size = 3113814, upload-time = "2026-03-30T08:51:08.834Z" }, - { url = "https://files.pythonhosted.org/packages/76/21/18d34a4efe524c903cf66b0cfa5260d81f277b6ae668b647edf795df9ce5/grpcio_tools-1.80.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:3399b5fd7b59bcffd59c6b9975a969d9f37a3c87f3e3d63c3a09c147907acb0d", size = 3662793, upload-time = "2026-03-30T08:51:11.094Z" }, - { url = "https://files.pythonhosted.org/packages/f3/40/cf2d9295a6bd593244ea703858f8fc2efd315046ca3ef7c6f9ebc5b810fa/grpcio_tools-1.80.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:9c6abc08d3485b2aac99bb58afcd31dc6cd4316ce36cf263ff09cb6df15f287f", size = 3329149, upload-time = "2026-03-30T08:51:13.066Z" }, - { url = "https://files.pythonhosted.org/packages/0d/1d/fc34b32167966df20d69429b71dfca83c48434b047a5ac4fd6cd91ca4eed/grpcio_tools-1.80.0-cp312-cp312-win32.whl", hash = "sha256:18c51e07652ac7386fcdbd11866f8d55a795de073337c12447b5805575339f74", size = 997519, upload-time = "2026-03-30T08:51:14.87Z" }, - { url = "https://files.pythonhosted.org/packages/91/98/6d6563cdf51085b75f8ec24605c6f2ce84197571878ca8ab4af949c6be2d/grpcio_tools-1.80.0-cp312-cp312-win_amd64.whl", hash = "sha256:ac6fdd42d5bb18f0d903a067e2825be172deff70cf197164b6f65676cb506c9b", size = 1162407, upload-time = "2026-03-30T08:51:16.793Z" }, - { url = "https://files.pythonhosted.org/packages/44/d9/f7887a4805939e9a85d03744b66fc02575dc1df3c3e8b4d9ec000ee7a33d/grpcio_tools-1.80.0-cp313-cp313-linux_armv7l.whl", hash = "sha256:e7046837859bbfd10b01786056145480155c16b222c9e209215b68d3be13060e", size = 2550319, upload-time = "2026-03-30T08:51:19.117Z" }, - { url = "https://files.pythonhosted.org/packages/57/5a/c8a05b32bd7203f1b9f4c0151090a2d6179d6c97692d32f2066dc29c67a6/grpcio_tools-1.80.0-cp313-cp313-macosx_11_0_universal2.whl", hash = "sha256:a447f28958a8fe84ff0d9d3d9473868feb27ee4a9c9c805e66f5b670121cec59", size = 5709681, upload-time = "2026-03-30T08:51:21.991Z" }, - { url = "https://files.pythonhosted.org/packages/82/6b/794350ed645c12c310008f97068f6a6fd927150b0d0d08aad1d909e880b1/grpcio_tools-1.80.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:75f00450e08fe648ad8a1eeb25bc52219679d54cdd02f04dfdddc747309d83f6", size = 2596820, upload-time = "2026-03-30T08:51:24.323Z" }, - { url = "https://files.pythonhosted.org/packages/f9/b2/b39e7b79f7c878135e0784a53cd7260ee77260c8c7f2c9e46bca8e05d017/grpcio_tools-1.80.0-cp313-cp313-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:3db830eaff1f2c2797328f2fa86c9dcdbd7d81af573a68db81e27afa2182a611", size = 2909193, upload-time = "2026-03-30T08:51:27.025Z" }, - { url = "https://files.pythonhosted.org/packages/10/f3/abe089b058f87f9910c9a458409505cbeb0b3e1c2d993a79721d02ee6a32/grpcio_tools-1.80.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:7982b5fe42f012686b667dda12916884de95c4b1c65ff64371fb7232a1474b23", size = 2660197, upload-time = "2026-03-30T08:51:29.392Z" }, - { url = "https://files.pythonhosted.org/packages/09/c3/3f7806ad8b731d8a89fe3c6ed496473abd1ef4c9c42c9e9a8836ce96e377/grpcio_tools-1.80.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:6451b3f4eb52d12c7f32d04bf8e0185f80521f3f088ad04b8d222b3a4819c71e", size = 3113144, upload-time = "2026-03-30T08:51:31.671Z" }, - { url = "https://files.pythonhosted.org/packages/fe/f5/415ef205e0b7e75d2a2005df6120145c4f02fda28d7b3715b55d924fe1a4/grpcio_tools-1.80.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:258bc30654a9a2236be4ca8e2ad443e2ac6db7c8cc20454d34cce60265922726", size = 3661897, upload-time = "2026-03-30T08:51:34.849Z" }, - { url = "https://files.pythonhosted.org/packages/e3/d3/2ad54764c2a9547080dd8518f4a4dc7899c7e6e747a1b1de542ce6a12066/grpcio_tools-1.80.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:865a2b8e6334c838976ab02a322cbd55c863d2eaf3c1e1a0255883c63996772a", size = 3328786, upload-time = "2026-03-30T08:51:37.265Z" }, - { url = "https://files.pythonhosted.org/packages/eb/63/23ab7db01f9630ab4f3742a2fc9fbff38b0cfc30c976114f913950664a75/grpcio_tools-1.80.0-cp313-cp313-win32.whl", hash = "sha256:f760ac1722f33e774814c37b6aa0444143f612e85088ead7447a0e9cd306a1f1", size = 997087, upload-time = "2026-03-30T08:51:39.137Z" }, - { url = "https://files.pythonhosted.org/packages/9b/af/b1c1c4423fb49cb7c8e9d2c02196b038c44160b7028b425466743c6c81fa/grpcio_tools-1.80.0-cp313-cp313-win_amd64.whl", hash = "sha256:7843b9ac6ff8ca508424d0dd968bd9a1a4559967e4a290f26be5bd6f04af2234", size = 1162167, upload-time = "2026-03-30T08:51:41.498Z" }, - { url = "https://files.pythonhosted.org/packages/0e/44/7beeee2348f9f412804f5bf80b7d13b81d522bf926a338ae3da46b2213b7/grpcio_tools-1.80.0-cp314-cp314-linux_armv7l.whl", hash = "sha256:12f950470449dbeec78317dbc090add7a00eb6ca812af7b0538ab7441e0a42c3", size = 2550303, upload-time = "2026-03-30T08:51:44.373Z" }, - { url = "https://files.pythonhosted.org/packages/2d/aa/f77dd85409a1855f8c6319ffc69d81e8c3ffe122ee3a7136653e1991d8b6/grpcio_tools-1.80.0-cp314-cp314-macosx_11_0_universal2.whl", hash = "sha256:d3f9a376a29c9adf62bb56f7ff5bc81eb4abeaf53d1e7dde5015564832901a51", size = 5709778, upload-time = "2026-03-30T08:51:47.112Z" }, - { url = "https://files.pythonhosted.org/packages/9c/7c/ab7af4883ebdfdc228b853de89fed409703955e8d47285b321a5794856bd/grpcio_tools-1.80.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:1ba1ffbf2cff71533615e2c5a138ed5569611eec9ae7f9c67b8898e127b54ac0", size = 2597928, upload-time = "2026-03-30T08:51:49.494Z" }, - { url = "https://files.pythonhosted.org/packages/22/e8/4381a963d472e3ab6690ba067ed2b1f1abf8518b10f402678bd2dcb79a54/grpcio_tools-1.80.0-cp314-cp314-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:13f60f8d9397c514c6745a967d22b5c8c698347e88deebca1ff2e1b94555e450", size = 2909333, upload-time = "2026-03-30T08:51:52.124Z" }, - { url = "https://files.pythonhosted.org/packages/94/cb/356b5fdf79dd99455b425fb16302fe60995554ceb721afbf3cf770a19208/grpcio_tools-1.80.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:88d77bad5dd3cd5e6f952c4ecdd0ee33e0c02ecfc2e4b0cbee3391ac19e0a431", size = 2660217, upload-time = "2026-03-30T08:51:55.066Z" }, - { url = "https://files.pythonhosted.org/packages/2b/d7/1752018cc2c36b2c5612051379e2e5f59f2dbe612de23e817d2f066a9487/grpcio_tools-1.80.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:017945c3e98a4ed1c4e21399781b4137fc08dfc1f802c8ace2e64ef52d32b142", size = 3113896, upload-time = "2026-03-30T08:51:57.3Z" }, - { url = "https://files.pythonhosted.org/packages/cc/17/695bbe454f70df35c03e22b48c5314683b913d3e6ed35ec90d065418c1ab/grpcio_tools-1.80.0-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:a33e265d4db803495007a6c623eafb0f6b9bb123ff4a0af89e44567dad809b88", size = 3661950, upload-time = "2026-03-30T08:51:59.867Z" }, - { url = "https://files.pythonhosted.org/packages/9c/d0/533d87629ec823c02c9169ee20228f734c264b209dcdf55268b5a14cde0a/grpcio_tools-1.80.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:6c129da370c5f85f569be2e545317dda786a60dd51d7deea29b03b0c05f6aac3", size = 3328755, upload-time = "2026-03-30T08:52:02.942Z" }, - { url = "https://files.pythonhosted.org/packages/08/a1/504d7838770c73a9761e8a8ff4869dba1146b44f297ff0ac6641481942d3/grpcio_tools-1.80.0-cp314-cp314-win32.whl", hash = "sha256:25742de5958ae4325249a37e724e7c0e5120f8e302a24a977ebd1737b48a5e97", size = 1019620, upload-time = "2026-03-30T08:52:05.342Z" }, - { url = "https://files.pythonhosted.org/packages/f3/75/8b7cd281c5cdfb4ca2c308f7e9b2799bab2be6e7a9e9212ea5a82e2aecd4/grpcio_tools-1.80.0-cp314-cp314-win_amd64.whl", hash = "sha256:bbf8eeef78fda1966f732f79c1c802fadd5cfd203d845d2af4d314d18569069c", size = 1194210, upload-time = "2026-03-30T08:52:08.105Z" }, +sdist = { url = "https://files.pythonhosted.org/packages/83/b3/1c5951352d6777fd7f99a0ccee04617fdfd8a5dbf2918a1f58c8b2b280b8/grpcio_tools-1.81.1.tar.gz", hash = "sha256:a22a3870180927fdd84e2b27d079ef5b7f5f8c6110181b6736afc17a463481f1", size = 6236155, upload-time = "2026-06-11T12:51:21.235Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/5a/e1/1fcf884902ae7255d8da224cfa638ea88a46d50f62a33d06d35c8960b029/grpcio_tools-1.81.1-cp310-cp310-linux_armv7l.whl", hash = "sha256:9b6ba8a72cfda576508701a7c0bbeebe6f6f9843320d4f12e74efd19ddccd965", size = 2586261, upload-time = "2026-06-11T12:49:21.447Z" }, + { url = "https://files.pythonhosted.org/packages/a2/d7/1815110b2d40ec99dbb0a7e6d7eafd591cd1f1e9bf9d3858cd9cf3ffacbd/grpcio_tools-1.81.1-cp310-cp310-macosx_11_0_universal2.whl", hash = "sha256:ac47a9ea1224df8b653072614e6f0207e9fbfe63fdabaa5918a60ca5fc931b88", size = 5817509, upload-time = "2026-06-11T12:49:25.958Z" }, + { url = "https://files.pythonhosted.org/packages/23/e8/af99579842b5a555312fa782f32ce0f99bd35b2b7a1243294b2755468857/grpcio_tools-1.81.1-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:eac4bb645ceff0c147cc720a40ae68f97427eaafb4968e866dd8fcc20d3d4831", size = 2634112, upload-time = "2026-06-11T12:49:27.937Z" }, + { url = "https://files.pythonhosted.org/packages/b5/cd/235ad56ac728c49c17e9218c4daccd5831e6ec7af94236bec0cc66c71c68/grpcio_tools-1.81.1-cp310-cp310-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:cc410b621dd85193766c12dca2e238696199a27a65d2b31b6f0a4c6c0043ff26", size = 2957950, upload-time = "2026-06-11T12:49:29.619Z" }, + { url = "https://files.pythonhosted.org/packages/77/3e/9103e8b4610597bf89db49eb112091c91bf5d63ddef2a951e11a4be05f2b/grpcio_tools-1.81.1-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:b62d254c214faa3773eac709376ae25cf7abff1a76ba5fc4dbcd7b14fc4e4ae6", size = 2697765, upload-time = "2026-06-11T12:49:31.702Z" }, + { url = "https://files.pythonhosted.org/packages/3c/86/beb2a43fbb93570a2305696083f6736566301d957869f463308ec6839f95/grpcio_tools-1.81.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:bd0b68dc76b10b3384b9b6e9f59202b83dcaafd8098eb644759a69316686acf8", size = 3147588, upload-time = "2026-06-11T12:49:33.748Z" }, + { url = "https://files.pythonhosted.org/packages/af/4d/b0182d9948631cd837a372b6625cf59d6e335d4aab0f425d4b7306619074/grpcio_tools-1.81.1-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:a28d231455ab6e3558299f7d831a73c8be8ee6b7ec614ecf39eb50c0ed15767f", size = 3708798, upload-time = "2026-06-11T12:49:35.979Z" }, + { url = "https://files.pythonhosted.org/packages/23/9b/f452a189d399051d85cf82fe2f27a070efaa52512a2c5e3ae6ef1ae99a1f/grpcio_tools-1.81.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:82740248eb6f3b6a38988cb5e64adb7303af9ea5cb4197c8ed08c1fabc767440", size = 3366969, upload-time = "2026-06-11T12:49:37.911Z" }, + { url = "https://files.pythonhosted.org/packages/9b/48/0075cb4f6ae7db280f461de2dbba700b22ae62e351ae13e6e461cd6804de/grpcio_tools-1.81.1-cp310-cp310-win32.whl", hash = "sha256:801d9d8ab5cddf8f8e064225292f0713427011252a07828a6b54e2ed64d534de", size = 1008713, upload-time = "2026-06-11T12:49:39.791Z" }, + { url = "https://files.pythonhosted.org/packages/17/bd/7692bc698259e5645b68720e77e7b176d376f6ae0c9db8b5b750a02f1958/grpcio_tools-1.81.1-cp310-cp310-win_amd64.whl", hash = "sha256:3c8611d6e4e859ac5373422ef27c4b7540cf98c9991c9abc6722613ef72b13aa", size = 1174752, upload-time = "2026-06-11T12:49:41.43Z" }, + { url = "https://files.pythonhosted.org/packages/18/76/14ff87090199a36f914388299a1148d0734a20cea1b0ca8480bae1f373f1/grpcio_tools-1.81.1-cp311-cp311-linux_armv7l.whl", hash = "sha256:8161f398f957a376cae7385ea7c8684f439d460ef702b528912da3bcb31fc515", size = 2586251, upload-time = "2026-06-11T12:49:43.514Z" }, + { url = "https://files.pythonhosted.org/packages/87/a8/d5aa99de9d8b2dd2a8192c1779796eda8b0d0f1dd915422e0a8a61b80391/grpcio_tools-1.81.1-cp311-cp311-macosx_11_0_universal2.whl", hash = "sha256:53ef76cc3b0493ff734a5e8c39d5b519e1822236fcccdfe7677c5e1efd767761", size = 5818063, upload-time = "2026-06-11T12:49:45.975Z" }, + { url = "https://files.pythonhosted.org/packages/ba/cb/2e9a6dbc6a514dd3cd264fb3bf9217937453a4d45dbc3ca6ca4ee34ba1a7/grpcio_tools-1.81.1-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:690e6dcaa8b8a7886ce206ba344e2127211597e1a1ddab73df9f3d80c8f6707e", size = 2634061, upload-time = "2026-06-11T12:49:48.13Z" }, + { url = "https://files.pythonhosted.org/packages/c8/2b/2ccd1a929e6c8ad84a0aa8d66ad9f615b4a8e79d9927373d86aa36b4ba2e/grpcio_tools-1.81.1-cp311-cp311-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:ad7a997c07bd345e84842e60561e7e2cc090ce6c4e1d2f0407e31b85b40fc49a", size = 2958029, upload-time = "2026-06-11T12:49:50.466Z" }, + { url = "https://files.pythonhosted.org/packages/e7/67/2da8cd312edc348f44f26f82096b25cdb7d2905cd786acc6bf777b169502/grpcio_tools-1.81.1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:b6bd163ece4535726e5292b845ed80ae9b2cae73ba091c7d6c66033c430e3857", size = 2698031, upload-time = "2026-06-11T12:49:52.292Z" }, + { url = "https://files.pythonhosted.org/packages/d9/ba/ad1680fbdf9317c4f1e54c37c96d1f422370df66ac9adbd175c7cb3531d7/grpcio_tools-1.81.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:2baa7e735f35b2a648144c03348a126097b13e101d3c242d5edb6ac91437ccbe", size = 3147541, upload-time = "2026-06-11T12:49:54.43Z" }, + { url = "https://files.pythonhosted.org/packages/57/c1/57cd08eef293d713cb8935295e4f08d8f0013480b2ba3aad1af0271eb7ba/grpcio_tools-1.81.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:1d602b410b2b2addc434cace9ce4fe2035974a3078228f98ffa049a5c90acc2f", size = 3708524, upload-time = "2026-06-11T12:49:56.544Z" }, + { url = "https://files.pythonhosted.org/packages/52/31/01ea8ca9c82fe2c79b5b594c3ae427d56699bc106b2d91caca129add8b10/grpcio_tools-1.81.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:f8cb64f87c45ccca8234fa47e6b21f09e43801ff11b556deecb461b3b3e9f292", size = 3367022, upload-time = "2026-06-11T12:49:59.608Z" }, + { url = "https://files.pythonhosted.org/packages/7d/35/8140cd175602df3d17215cfb28a7ea55b7a67e2b872be76e1ee4af5c4df9/grpcio_tools-1.81.1-cp311-cp311-win32.whl", hash = "sha256:87b25ca0e27373a4a32a629a4ba976f5764b9887dd50d6fe017d38009a0363e8", size = 1008980, upload-time = "2026-06-11T12:50:01.422Z" }, + { url = "https://files.pythonhosted.org/packages/be/86/1bd29ab3c52457702b96536f1f208ab27695322d855f95c9666dfb713019/grpcio_tools-1.81.1-cp311-cp311-win_amd64.whl", hash = "sha256:204de03b539a4b08772c6553b92bcc112cbc965e0ac22f909f6d133b8ac33a8c", size = 1174840, upload-time = "2026-06-11T12:50:03.408Z" }, + { url = "https://files.pythonhosted.org/packages/3b/8a/824a9ca20bcdce8a568bb8c9f98bfeb7fad62129235e6d2ae7576fd1250a/grpcio_tools-1.81.1-cp312-cp312-linux_armv7l.whl", hash = "sha256:353b1fafcc739c31ed42271052709595b340d34f27c459beeb78a32938305bb5", size = 2585927, upload-time = "2026-06-11T12:50:05.671Z" }, + { url = "https://files.pythonhosted.org/packages/2f/35/e5f9f671378b1b89a896150d3e4fa2c6ec61a5e1e9e5107ce4c140ccc931/grpcio_tools-1.81.1-cp312-cp312-macosx_11_0_universal2.whl", hash = "sha256:768f584c2423cbeb6cb6867817a39365b987ff16b8259a3adbc6546b9e303a4e", size = 5815665, upload-time = "2026-06-11T12:50:08.178Z" }, + { url = "https://files.pythonhosted.org/packages/c6/02/631b628e4072e988c669bd8f1b2406ef3c9a4cfcb2625bbf2a308a07b71d/grpcio_tools-1.81.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:1680b35a84f4694401819ac4acac42dda6dbc7bb8fc74112fd1a60425a07adf4", size = 2635518, upload-time = "2026-06-11T12:50:10.391Z" }, + { url = "https://files.pythonhosted.org/packages/de/7c/2e3537e3ea3d1c0ddd6766cf6a7c62b487d89fb005713df2781d5f21483a/grpcio_tools-1.81.1-cp312-cp312-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:f64e665c8ec639278ecf009beb92cbdcc5994f617c1af3d58036e1f70b1423ec", size = 2958252, upload-time = "2026-06-11T12:50:12.677Z" }, + { url = "https://files.pythonhosted.org/packages/35/68/14013cb2942bdac354746b643b4c37dd91906da8dce00f41c616e88bf33d/grpcio_tools-1.81.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:ba8f1ae82ad199f43448995715445cc623fb20d3882382e4be61f0da8ccb3f0e", size = 2698439, upload-time = "2026-06-11T12:50:15.017Z" }, + { url = "https://files.pythonhosted.org/packages/bd/45/000c14c0338a7ad36054b9f17ea41842deb7841c05c067dd36cc831bc0f4/grpcio_tools-1.81.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:b7b6d1e986d5923751bfe2b5cca9c4cb3d5653446e4fa4aacd438033e2dc360a", size = 3152160, upload-time = "2026-06-11T12:50:17.3Z" }, + { url = "https://files.pythonhosted.org/packages/41/97/881930ca3967d2c8a95649bea8ebc991a7cf2331bc96679fd3600450dccc/grpcio_tools-1.81.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:7f208c207aca639dcb34648d3826c38d7cf3485118fb2065117e9fc4827406b3", size = 3710468, upload-time = "2026-06-11T12:50:19.479Z" }, + { url = "https://files.pythonhosted.org/packages/c7/b5/67baeba7366162652cdc1dbd962289accde07241bc8f42f6f02b305efcc6/grpcio_tools-1.81.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:724ecb69af63d2f6d4ccea3e6fa0ca110ed9c5824d48c2f887c631bbb03c1c3c", size = 3370797, upload-time = "2026-06-11T12:50:21.501Z" }, + { url = "https://files.pythonhosted.org/packages/f2/5d/34f2dce2125ccb107e32b57f5a9c1257edcc0793b0d2fef1e8b13a6bac3c/grpcio_tools-1.81.1-cp312-cp312-win32.whl", hash = "sha256:895a6782cec86beac71ccebb4b9848259c6f04a3028b8e42fa8d40cfe5146593", size = 1008453, upload-time = "2026-06-11T12:50:23.358Z" }, + { url = "https://files.pythonhosted.org/packages/8a/be/09da8256ec8d2a5ce8a1acc51cbbc4ca52a462d78ed3412778440a56502e/grpcio_tools-1.81.1-cp312-cp312-win_amd64.whl", hash = "sha256:0265fd1386b7458302f79542558345880d484f8fa92ae196c0c0268242c5f23a", size = 1174857, upload-time = "2026-06-11T12:50:25.685Z" }, + { url = "https://files.pythonhosted.org/packages/76/90/5faa8b26e03495e5117f93bef8293cbada4af136362745dad7d1813ef0b0/grpcio_tools-1.81.1-cp313-cp313-linux_armv7l.whl", hash = "sha256:3d604b4fd114b79ebb9f865bf3e04fd3ae93c704e1fad96f7fd03b0865c263b7", size = 2586071, upload-time = "2026-06-11T12:50:28.4Z" }, + { url = "https://files.pythonhosted.org/packages/e8/9a/85dc589fa6ae2439451eaa81a1578de31e29c676980d38bef7549b8a1f45/grpcio_tools-1.81.1-cp313-cp313-macosx_11_0_universal2.whl", hash = "sha256:3389e705460efa3f3758141ba5520e6743b131c9576197c944fb9cbe49048126", size = 5813299, upload-time = "2026-06-11T12:50:31.295Z" }, + { url = "https://files.pythonhosted.org/packages/77/fd/c53994e58a837e6eefe48f53eb3492afc04f2b8af255df4adb37d14378f8/grpcio_tools-1.81.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:8a17d8ceeb6a855fadf39f5171c80a382d97c4db98d5943eca553497fdebf84b", size = 2634668, upload-time = "2026-06-11T12:50:33.938Z" }, + { url = "https://files.pythonhosted.org/packages/34/32/de988e86688686a2117e7ce6ce9eff4f638c929bb55b0afe60d6fbd2e45c/grpcio_tools-1.81.1-cp313-cp313-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:43baf71dc60fd653062da2e95e95c73b35dd130be8f9fa3d544c3af3f808a290", size = 2957930, upload-time = "2026-06-11T12:50:36.726Z" }, + { url = "https://files.pythonhosted.org/packages/72/97/3f18a0ea32b5f809d21961dbd0bc382b589a4c3d501e3d67c345d5456ed3/grpcio_tools-1.81.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:136e90906af0df51ad929713244ba812d0dbb1844b4f467d5d86bdb054698f90", size = 2697760, upload-time = "2026-06-11T12:50:39.108Z" }, + { url = "https://files.pythonhosted.org/packages/49/c0/dbf5cbc877290ff7504a59959a8af4fdcfdaa1e84237948405ccf1aa82a6/grpcio_tools-1.81.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:bd6c3bf3ea6a61eb58c54368d72ada591f2a270f3a31a32e8536e773337e76d9", size = 3151456, upload-time = "2026-06-11T12:50:41.983Z" }, + { url = "https://files.pythonhosted.org/packages/de/ea/16fe2dc83140a59e5c0a0b9dc2693dd36bfaa6bd835724b4ec66a68eab7b/grpcio_tools-1.81.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:2c306c307f8f74cddc4056fdbb6f1da55de087a21120efbd02bd915daa5a52fd", size = 3710469, upload-time = "2026-06-11T12:50:44.596Z" }, + { url = "https://files.pythonhosted.org/packages/22/7d/df987d7d81e7ad2f7516d9e9d56ff29c54dbc6d8587e425688dca9a28e49/grpcio_tools-1.81.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:bdbdc927be2e0ea13c32564a72ee31d712a716fb6f8c0d53d37a77d8277c272c", size = 3370488, upload-time = "2026-06-11T12:50:47.199Z" }, + { url = "https://files.pythonhosted.org/packages/ba/c5/5a63444d694ea47bf670138208f71830cc1759c402c8818092b28ab2dc5f/grpcio_tools-1.81.1-cp313-cp313-win32.whl", hash = "sha256:9d383724bcd67244b6def9e9164c640ee9380c0b7534ee7545a6fb0022a59afe", size = 1008229, upload-time = "2026-06-11T12:50:49.527Z" }, + { url = "https://files.pythonhosted.org/packages/00/75/3945e26d5c94ae6ed9be5caef73d4d66c47dc8cfdd7b4995efaf942754e0/grpcio_tools-1.81.1-cp313-cp313-win_amd64.whl", hash = "sha256:f3eb15849979ca7bb864ce81a74d68b0f225a7f111ed3fe212bfc08cf9812b10", size = 1174523, upload-time = "2026-06-11T12:50:51.755Z" }, + { url = "https://files.pythonhosted.org/packages/0d/08/e581ad42ae517a61172285047e4d710e2ac75f2f1915f7c91f284254e6d5/grpcio_tools-1.81.1-cp314-cp314-linux_armv7l.whl", hash = "sha256:7d168ea26390717d0462c0d0408331dc98a60fc7f7e6118afac9b73f5a66d87c", size = 2585944, upload-time = "2026-06-11T12:50:54.528Z" }, + { url = "https://files.pythonhosted.org/packages/78/c8/200d90ebad685af7eea5ff7e0360c504dd01ec053fe0f1f9c4abe3ea2d5a/grpcio_tools-1.81.1-cp314-cp314-macosx_11_0_universal2.whl", hash = "sha256:43c528655b226375013036692d8db4cd59060c1f41dd62c77f4d17b69f6ce828", size = 5813492, upload-time = "2026-06-11T12:50:57.291Z" }, + { url = "https://files.pythonhosted.org/packages/2d/c0/60da2a1af37aa8eb47308cec24d9f7709a8976fdec3a53fd35b56b358326/grpcio_tools-1.81.1-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:a9c6fcc68c9d5a208967bfe4fd3224d3c3be9a950c3e827e8f4b17e15c2dc555", size = 2634991, upload-time = "2026-06-11T12:50:59.767Z" }, + { url = "https://files.pythonhosted.org/packages/0c/7f/dede28b579ae9bf9079ba1aa913e8088d1dc0cdbe21c85caa22f0790cad2/grpcio_tools-1.81.1-cp314-cp314-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:a987c85dcbe1b32066d7acd46266d1a428aecbd629331bf5b853e74c835bf876", size = 2957913, upload-time = "2026-06-11T12:51:02.31Z" }, + { url = "https://files.pythonhosted.org/packages/4c/38/4de2118adb58ec7ffba65ec623b5836db769665c192517cbf187db3f6145/grpcio_tools-1.81.1-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:a882382507bb5ec6d7edc9648053dfd3bc8f9285cde56a6fa9b9a83b4bd07f1c", size = 2697709, upload-time = "2026-06-11T12:51:05.016Z" }, + { url = "https://files.pythonhosted.org/packages/6b/e1/762ced51059e4f694fd337ecae491581d42a4e61dcb0415d8c5c60e6ddcb/grpcio_tools-1.81.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:7746e508d4239a02f7e93638be5bc0ebb0120ddb796f7506aaae9d47a4599d97", size = 3151884, upload-time = "2026-06-11T12:51:07.593Z" }, + { url = "https://files.pythonhosted.org/packages/19/d8/9823090dc801e7229944874e7429c3b98e741ac778d8dc373f60240e1c43/grpcio_tools-1.81.1-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:fc3d2a41a7a4467fa03b391394fffada9291fe8feebc8679b526f6bc36942b25", size = 3710404, upload-time = "2026-06-11T12:51:10.172Z" }, + { url = "https://files.pythonhosted.org/packages/64/4e/4eae98d02148cb6f9f452f09942afba407afa6851e6c1fddc5ae9ec0b4ed/grpcio_tools-1.81.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:21bb3ba90e6d8df1ff663d4ee39a4e5b25a64e8ed4902476ca9ded0954d3917a", size = 3370525, upload-time = "2026-06-11T12:51:12.678Z" }, + { url = "https://files.pythonhosted.org/packages/e0/3e/2206e597a128da6a03a6106d2eaf2c3e72c7d80843d4be933e3a3d10d02a/grpcio_tools-1.81.1-cp314-cp314-win32.whl", hash = "sha256:3dca56016d90a710c4d9861bae793dc089c1430a90c79ce672e948ddb65fa539", size = 1030582, upload-time = "2026-06-11T12:51:14.906Z" }, + { url = "https://files.pythonhosted.org/packages/cf/f2/bbeef86c687225b7bbc7c0acdfbd25c8bcaa3f5b1c941db053e5c3d9e859/grpcio_tools-1.81.1-cp314-cp314-win_amd64.whl", hash = "sha256:cb08172b7b629e75cb33866928d319a3196540a725eaab628ba721007140f1af", size = 1207490, upload-time = "2026-06-11T12:51:17.598Z" }, ] [[package]] @@ -2083,34 +2118,34 @@ wheels = [ [[package]] name = "hf-xet" -version = "1.4.3" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/53/92/ec9ad04d0b5728dca387a45af7bc98fbb0d73b2118759f5f6038b61a57e8/hf_xet-1.4.3.tar.gz", hash = "sha256:8ddedb73c8c08928c793df2f3401ec26f95be7f7e516a7bee2fbb546f6676113", size = 670477, upload-time = "2026-03-31T22:40:07.874Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/72/43/724d307b34e353da0abd476e02f72f735cdd2bc86082dee1b32ea0bfee1d/hf_xet-1.4.3-cp313-cp313t-macosx_10_12_x86_64.whl", hash = "sha256:7551659ba4f1e1074e9623996f28c3873682530aee0a846b7f2f066239228144", size = 3800935, upload-time = "2026-03-31T22:39:49.618Z" }, - { url = "https://files.pythonhosted.org/packages/2b/d2/8bee5996b699262edb87dbb54118d287c0e1b2fc78af7cdc41857ba5e3c4/hf_xet-1.4.3-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:bee693ada985e7045997f05f081d0e12c4c08bd7626dc397f8a7c487e6c04f7f", size = 3558942, upload-time = "2026-03-31T22:39:47.938Z" }, - { url = "https://files.pythonhosted.org/packages/c3/a1/e993d09cbe251196fb60812b09a58901c468127b7259d2bf0f68bf6088eb/hf_xet-1.4.3-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:21644b404bb0100fe3857892f752c4d09642586fd988e61501c95bbf44b393a3", size = 4207657, upload-time = "2026-03-31T22:39:39.69Z" }, - { url = "https://files.pythonhosted.org/packages/64/44/9eb6d21e5c34c63e5e399803a6932fa983cabdf47c0ecbcfe7ea97684b8c/hf_xet-1.4.3-cp313-cp313t-manylinux_2_28_aarch64.whl", hash = "sha256:987f09cfe418237812896a6736b81b1af02a3a6dcb4b4944425c4c4fca7a7cf8", size = 3986765, upload-time = "2026-03-31T22:39:37.936Z" }, - { url = "https://files.pythonhosted.org/packages/ea/7b/8ad6f16fdb82f5f7284a34b5ec48645bd575bdcd2f6f0d1644775909c486/hf_xet-1.4.3-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:60cf7fc43a99da0a853345cf86d23738c03983ee5249613a6305d3e57a5dca74", size = 4188162, upload-time = "2026-03-31T22:39:58.382Z" }, - { url = "https://files.pythonhosted.org/packages/1b/c4/39d6e136cbeea9ca5a23aad4b33024319222adbdc059ebcda5fc7d9d5ff4/hf_xet-1.4.3-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:2815a49a7a59f3e2edf0cf113ae88e8cb2ca2a221bf353fb60c609584f4884d4", size = 4424525, upload-time = "2026-03-31T22:40:00.225Z" }, - { url = "https://files.pythonhosted.org/packages/46/f2/adc32dae6bdbc367853118b9878139ac869419a4ae7ba07185dc31251b76/hf_xet-1.4.3-cp313-cp313t-win_amd64.whl", hash = "sha256:42ee323265f1e6a81b0e11094564fb7f7e0ec75b5105ffd91ae63f403a11931b", size = 3671610, upload-time = "2026-03-31T22:40:10.42Z" }, - { url = "https://files.pythonhosted.org/packages/e2/19/25d897dcc3f81953e0c2cde9ec186c7a0fee413eb0c9a7a9130d87d94d3a/hf_xet-1.4.3-cp313-cp313t-win_arm64.whl", hash = "sha256:27c976ba60079fb8217f485b9c5c7fcd21c90b0367753805f87cb9f3cdc4418a", size = 3528529, upload-time = "2026-03-31T22:40:09.106Z" }, - { url = "https://files.pythonhosted.org/packages/ec/36/3e8f85ca9fe09b8de2b2e10c63b3b3353d7dda88a0b3d426dffbe7b8313b/hf_xet-1.4.3-cp314-cp314t-macosx_10_12_x86_64.whl", hash = "sha256:5251d5ece3a81815bae9abab41cf7ddb7bcb8f56411bce0827f4a3071c92fdc6", size = 3801019, upload-time = "2026-03-31T22:39:56.651Z" }, - { url = "https://files.pythonhosted.org/packages/b5/9c/defb6cb1de28bccb7bd8d95f6e60f72a3d3fa4cb3d0329c26fb9a488bfe7/hf_xet-1.4.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:1feb0f3abeacee143367c326a128a2e2b60868ec12a36c225afb1d6c5a05e6d2", size = 3558746, upload-time = "2026-03-31T22:39:54.766Z" }, - { url = "https://files.pythonhosted.org/packages/c1/bd/8d001191893178ff8e826e46ad5299446e62b93cd164e17b0ffea08832ec/hf_xet-1.4.3-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:8b301fc150290ca90b4fccd079829b84bb4786747584ae08b94b4577d82fb791", size = 4207692, upload-time = "2026-03-31T22:39:46.246Z" }, - { url = "https://files.pythonhosted.org/packages/ce/48/6790b402803250e9936435613d3a78b9aaeee7973439f0918848dde58309/hf_xet-1.4.3-cp314-cp314t-manylinux_2_28_aarch64.whl", hash = "sha256:d972fbe95ddc0d3c0fc49b31a8a69f47db35c1e3699bf316421705741aab6653", size = 3986281, upload-time = "2026-03-31T22:39:44.648Z" }, - { url = "https://files.pythonhosted.org/packages/51/56/ea62552fe53db652a9099eda600b032d75554d0e86c12a73824bfedef88b/hf_xet-1.4.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:c5b48db1ee344a805a1b9bd2cda9b6b65fe77ed3787bd6e87ad5521141d317cd", size = 4187414, upload-time = "2026-03-31T22:40:04.951Z" }, - { url = "https://files.pythonhosted.org/packages/7d/f5/bc1456d4638061bea997e6d2db60a1a613d7b200e0755965ec312dc1ef79/hf_xet-1.4.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:22bdc1f5fb8b15bf2831440b91d1c9bbceeb7e10c81a12e8d75889996a5c9da8", size = 4424368, upload-time = "2026-03-31T22:40:06.347Z" }, - { url = "https://files.pythonhosted.org/packages/e4/76/ab597bae87e1f06d18d3ecb8ed7f0d3c9a37037fc32ce76233d369273c64/hf_xet-1.4.3-cp314-cp314t-win_amd64.whl", hash = "sha256:0392c79b7cf48418cd61478c1a925246cf10639f4cd9d94368d8ca1e8df9ea07", size = 3672280, upload-time = "2026-03-31T22:40:16.401Z" }, - { url = "https://files.pythonhosted.org/packages/62/05/2e462d34e23a09a74d73785dbed71cc5dbad82a72eee2ad60a72a554155d/hf_xet-1.4.3-cp314-cp314t-win_arm64.whl", hash = "sha256:681c92a07796325778a79d76c67011764ecc9042a8c3579332b61b63ae512075", size = 3528945, upload-time = "2026-03-31T22:40:14.995Z" }, - { url = "https://files.pythonhosted.org/packages/ac/9f/9c23e4a447b8f83120798f9279d0297a4d1360bdbf59ef49ebec78fe2545/hf_xet-1.4.3-cp37-abi3-macosx_10_12_x86_64.whl", hash = "sha256:d0da85329eaf196e03e90b84c2d0aca53bd4573d097a75f99609e80775f98025", size = 3805048, upload-time = "2026-03-31T22:39:53.105Z" }, - { url = "https://files.pythonhosted.org/packages/0b/f8/7aacb8e5f4a7899d39c787b5984e912e6c18b11be136ef13947d7a66d265/hf_xet-1.4.3-cp37-abi3-macosx_11_0_arm64.whl", hash = "sha256:e23717ce4186b265f69afa66e6f0069fe7efbf331546f5c313d00e123dc84583", size = 3562178, upload-time = "2026-03-31T22:39:51.295Z" }, - { url = "https://files.pythonhosted.org/packages/df/9a/a24b26dc8a65f0ecc0fe5be981a19e61e7ca963b85e062c083f3a9100529/hf_xet-1.4.3-cp37-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:fc360b70c815bf340ed56c7b8c63aacf11762a4b099b2fe2c9bd6d6068668c08", size = 4212320, upload-time = "2026-03-31T22:39:42.922Z" }, - { url = "https://files.pythonhosted.org/packages/53/60/46d493db155d2ee2801b71fb1b0fd67696359047fdd8caee2c914cc50c79/hf_xet-1.4.3-cp37-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:39f2d2e9654cd9b4319885733993807aab6de9dfbd34c42f0b78338d6617421f", size = 3991546, upload-time = "2026-03-31T22:39:41.335Z" }, - { url = "https://files.pythonhosted.org/packages/bc/f5/067363e1c96c6b17256910830d1b54099d06287e10f4ec6ec4e7e08371fc/hf_xet-1.4.3-cp37-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:49ad8a8cead2b56051aa84d7fce3e1335efe68df3cf6c058f22a65513885baac", size = 4193200, upload-time = "2026-03-31T22:40:01.936Z" }, - { url = "https://files.pythonhosted.org/packages/42/4b/53951592882d9c23080c7644542fda34a3813104e9e11fa1a7d82d419cb8/hf_xet-1.4.3-cp37-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:7716d62015477a70ea272d2d68cd7cad140f61c52ee452e133e139abfe2c17ba", size = 4429392, upload-time = "2026-03-31T22:40:03.492Z" }, - { url = "https://files.pythonhosted.org/packages/8a/21/75a6c175b4e79662ad8e62f46a40ce341d8d6b206b06b4320d07d55b188c/hf_xet-1.4.3-cp37-abi3-win_amd64.whl", hash = "sha256:6b591fcad34e272a5b02607485e4f2a1334aebf1bc6d16ce8eb1eb8978ac2021", size = 3677359, upload-time = "2026-03-31T22:40:13.619Z" }, - { url = "https://files.pythonhosted.org/packages/8a/7c/44314ecd0e89f8b2b51c9d9e5e7a60a9c1c82024ac471d415860557d3cd8/hf_xet-1.4.3-cp37-abi3-win_arm64.whl", hash = "sha256:7c2c7e20bcfcc946dc67187c203463f5e932e395845d098cc2a93f5b67ca0b47", size = 3533664, upload-time = "2026-03-31T22:40:12.152Z" }, +version = "1.5.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/4b/2d/57fd21d84d93efb4bd0b962383790e19dd1bc053501b4264c97903b4e83e/hf_xet-1.5.1.tar.gz", hash = "sha256:51ef4500dab3764b41135ee1381a4b62ce56fc54d4c92b719b59e597d6df5bf6", size = 876636, upload-time = "2026-06-08T23:02:53.897Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/64/ee/dd9ba7beae1005e54131b7d45263cc74c8a066d47d354e6d58ae9445a388/hf_xet-1.5.1-cp313-cp313t-macosx_10_12_x86_64.whl", hash = "sha256:dbf48c0d02cf0b2e568944330c60d9120c272dabe013bd892d48e25bc6797577", size = 4069485, upload-time = "2026-06-08T23:02:13.193Z" }, + { url = "https://files.pythonhosted.org/packages/b6/bc/9cae6cfeb4e03070874e73e5c97c66eb90369d3206b6a2b1ef5f96520888/hf_xet-1.5.1-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:e78e4e5192ad2b674c2e1160b651cb9134db974f8ae1835bdfbfb0166b894a43", size = 3838493, upload-time = "2026-06-08T23:02:15.282Z" }, + { url = "https://files.pythonhosted.org/packages/ba/b4/d5c01e0eb6d9f2ca2dacd84d0d1b71e6cfbb2ef3208c968528e010e9b3d7/hf_xet-1.5.1-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:6f7a04a8ad962422e225bc49fbbac99dc1806764b1f3e54dbd154bffa7593947", size = 4505658, upload-time = "2026-06-08T23:02:17.196Z" }, + { url = "https://files.pythonhosted.org/packages/76/c5/29a7598c0c6383c523dc22186d577f4e04267a626cd95ae60f67c00bfe66/hf_xet-1.5.1-cp313-cp313t-manylinux_2_28_aarch64.whl", hash = "sha256:d48199c2bf4f8df0adc55d31d1368b6ec0e4d4f45bc86b08038089c23db0bed8", size = 4292822, upload-time = "2026-06-08T23:02:18.608Z" }, + { url = "https://files.pythonhosted.org/packages/04/9a/dceaf6ca69390126b86ea825fb354b93d01163199070b7bd849225de9468/hf_xet-1.5.1-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:97f212a88d14bbf573619a74b7fecb238de77d08fc702e54dec6f78276ca3283", size = 4491255, upload-time = "2026-06-08T23:02:20.124Z" }, + { url = "https://files.pythonhosted.org/packages/48/a7/e5a7afaacf6c1791fdbeeac42951fb81c3d2bc482992b115dedcc86d963e/hf_xet-1.5.1-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:f61e3665892a6c8c5e765395838b8ddf36185da835253d4bc4509a81e49fb342", size = 4711062, upload-time = "2026-06-08T23:02:21.863Z" }, + { url = "https://files.pythonhosted.org/packages/53/49/2802f8433c9742ce281bddc1e65c02c32268ca3098d66828b05e12e45ee2/hf_xet-1.5.1-cp313-cp313t-win_amd64.whl", hash = "sha256:f4ad3ebd4c32dd2b27099d69dc7b2df821e30767e46fb6ee6a0713778243b8ff", size = 4017205, upload-time = "2026-06-08T23:02:23.495Z" }, + { url = "https://files.pythonhosted.org/packages/9e/5a/50c71195b9fb883659f596e7252faf4c18c58e753a9013bdbf9bac5d2250/hf_xet-1.5.1-cp313-cp313t-win_arm64.whl", hash = "sha256:8298485c1e36e7e67cbd01eeb1376619b7af43d4f1ec245caae306f890a8a32d", size = 3845426, upload-time = "2026-06-08T23:02:25.124Z" }, + { url = "https://files.pythonhosted.org/packages/05/24/5e0c28f80371c17d49fed004597d9d132cb75c1f6f53db2cb95f459d2312/hf_xet-1.5.1-cp314-cp314t-macosx_10_12_x86_64.whl", hash = "sha256:3474760d10e3bb6f92ff3f024fcb00c0b3e4001e9b035c7483e49a5dd17aa70f", size = 4069676, upload-time = "2026-06-08T23:02:26.759Z" }, + { url = "https://files.pythonhosted.org/packages/d2/17/261ba565b6a4d960fb478f61fdf919c0be5824645aaf1c319eca660c1611/hf_xet-1.5.1-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:6762d89b9e3267dfd502b29b2a327b4525f33b17e7b509a78d94e2151a30ce30", size = 3838509, upload-time = "2026-06-08T23:02:28.573Z" }, + { url = "https://files.pythonhosted.org/packages/4e/44/7ffdc2e184b0d41fc0f683ba3936ef669ab63cf242cf36ef50e57d683668/hf_xet-1.5.1-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:bf67e6ed10260cef62e852789dc91ebb03f382d5bdc4b1dbeb64763ea275e7d6", size = 4505881, upload-time = "2026-06-08T23:02:30.257Z" }, + { url = "https://files.pythonhosted.org/packages/63/b6/788060d5aa4d5e671f1a31bf69624c314eb2d8babab3aa562f9e5d53444e/hf_xet-1.5.1-cp314-cp314t-manylinux_2_28_aarch64.whl", hash = "sha256:c6b6cd08ca095058780b50b8ce4d6cbf6787bcf27841705d58a9d32246e3e47a", size = 4292995, upload-time = "2026-06-08T23:02:31.993Z" }, + { url = "https://files.pythonhosted.org/packages/22/93/c5540cbd6b55529b7dc42f6734e88cebee21aefbea34128b66229df56c57/hf_xet-1.5.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:e1af0de8ca6f190d4294a28b88023db64a1e2d1d719cab044baf75bec569e7a9", size = 4491570, upload-time = "2026-06-08T23:02:33.86Z" }, + { url = "https://files.pythonhosted.org/packages/03/f3/9d8ceab30f44f36c1679b1b8683054c71a0dadc787dbf07421891742d3ca/hf_xet-1.5.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:4f561cbbb92f80960772059864b7fb07eae879adde1b2e781ec6f86f6ac26c59", size = 4711565, upload-time = "2026-06-08T23:02:35.454Z" }, + { url = "https://files.pythonhosted.org/packages/cd/54/27ed9a5e2cc583b4df82f75a03a4df8dbf55f5a9fa1f47f1fadfb20dbeac/hf_xet-1.5.1-cp314-cp314t-win_amd64.whl", hash = "sha256:e7dbb40617410f432182d918e37c12303fe6700fd6aa6c5964e30a535a4461d6", size = 4017343, upload-time = "2026-06-08T23:02:37.14Z" }, + { url = "https://files.pythonhosted.org/packages/ae/12/ecb2fc8d45e767580e3a37faa97cb895608b614965567efb4f18cff67e27/hf_xet-1.5.1-cp314-cp314t-win_arm64.whl", hash = "sha256:6071d5ccb4d8d2cbd5fea5cc798da4f0ba3f44e25369591c4e89a4987050e61d", size = 3845716, upload-time = "2026-06-08T23:02:39.073Z" }, + { url = "https://files.pythonhosted.org/packages/7a/d8/5e54cf37434759d1f4f2ba9b66077ff9d4c4e1f37b6bd7975da5c40d94ab/hf_xet-1.5.1-cp37-abi3-macosx_10_12_x86_64.whl", hash = "sha256:6abd35c3221eff63836618ddfb954dcf84798603f71d8e33e3ed7b04acfdbe6e", size = 4077794, upload-time = "2026-06-08T23:02:40.656Z" }, + { url = "https://files.pythonhosted.org/packages/35/94/4b2ecfbad8f8b04701a23aefb62f540b9137d058b7e1dbef16a32676f0e9/hf_xet-1.5.1-cp37-abi3-macosx_11_0_arm64.whl", hash = "sha256:94e761bbd266bf4c03cee73753916062665ce8365aa40ed321f45afcb934b41e", size = 3845354, upload-time = "2026-06-08T23:02:42.702Z" }, + { url = "https://files.pythonhosted.org/packages/de/cc/f99f4bc7295023d7bd9ebbfd51f75cc530ca262c1227666268b8208f4b77/hf_xet-1.5.1-cp37-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:892e3a3a3aecc12aded8b93cf4f9cd059282c7de0732f7d55026f3abdf474350", size = 4514864, upload-time = "2026-06-08T23:02:44.497Z" }, + { url = "https://files.pythonhosted.org/packages/cd/6e/21f7e5a2381278bd3b7b7a5a4d90038518bb6308a0c1daf5d9f8268bb178/hf_xet-1.5.1-cp37-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:a93df2039190502835b1db8cd7e178b0b7b889fe9ab51299d5ced26e0dd879a4", size = 4303784, upload-time = "2026-06-08T23:02:46.203Z" }, + { url = "https://files.pythonhosted.org/packages/35/0e/f992bb6927ac1cb30ef74e62268f551f338bc32b2191f7c96a44c6f7283e/hf_xet-1.5.1-cp37-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:0c97106032ef70467b4f6bc2d0ccc266d7613ee076afc56516c502f87ce1c4a6", size = 4500703, upload-time = "2026-06-08T23:02:47.628Z" }, + { url = "https://files.pythonhosted.org/packages/fb/d1/90a498d05447980b977b1669246eeeeae4cfb0ea3e7a286eaba627f91bf9/hf_xet-1.5.1-cp37-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:6208adb15d192b90e4c2ad2a27ed864359b2cb0f2494eb6d7c7f3699ac02e2bf", size = 4719498, upload-time = "2026-06-08T23:02:49.268Z" }, + { url = "https://files.pythonhosted.org/packages/6d/b6/20f99cfe97cc663a711f7b33cc21d4793e51968e9a26125b4afcd77315ba/hf_xet-1.5.1-cp37-abi3-win_amd64.whl", hash = "sha256:f7b3002f95d1c13e24bcb4537baa8f0eb3838957067c91bb4959bc004a6435f5", size = 4026419, upload-time = "2026-06-08T23:02:50.829Z" }, + { url = "https://files.pythonhosted.org/packages/f9/fa/77453694888f03e5a8c8852d1514a0894d8e81c622d39edbaf308ea0dcf4/hf_xet-1.5.1-cp37-abi3-win_arm64.whl", hash = "sha256:93d090b57b211133f6c0dab0205ef5cb6d89162979ba75a74845045cc3063b8e", size = 3855178, upload-time = "2026-06-08T23:02:52.452Z" }, ] [[package]] @@ -2164,9 +2199,10 @@ wheels = [ [[package]] name = "huggingface-hub" -version = "1.11.0" +version = "1.19.0" source = { registry = "https://pypi.org/simple" } dependencies = [ + { name = "click" }, { name = "filelock" }, { name = "fsspec" }, { name = "hf-xet", marker = "platform_machine == 'AMD64' or platform_machine == 'aarch64' or platform_machine == 'amd64' or platform_machine == 'arm64' or platform_machine == 'x86_64'" }, @@ -2177,9 +2213,9 @@ dependencies = [ { name = "typer" }, { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/dc/89/e7aa12d8a6b9259bed10671abb25ae6fa437c0f88a86ecbf59617bae7759/huggingface_hub-1.11.0.tar.gz", hash = "sha256:15fb3713c7f9cdff7b808a94fd91664f661ab142796bb48c9cd9493e8d166278", size = 761749, upload-time = "2026-04-16T13:07:39.73Z" } +sdist = { url = "https://files.pythonhosted.org/packages/88/27/629cfe58c582f92ded066c4a07d1a057ff617118ab7973200f770bd853cb/huggingface_hub-1.19.0.tar.gz", hash = "sha256:fd771622182d40977272a923953ee3b1b13538f9f8a7f5d78398f10af0f1c0bd", size = 824721, upload-time = "2026-06-11T12:33:18.665Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/37/02/4f3f8997d1ea7fe0146b343e5e14bd065fa87af790d07e5576d31b31cc18/huggingface_hub-1.11.0-py3-none-any.whl", hash = "sha256:42a6de0afbfeb5e022222d36398f029679db4eb4778801aafda32257ae9131ab", size = 645499, upload-time = "2026-04-16T13:07:37.716Z" }, + { url = "https://files.pythonhosted.org/packages/b2/a5/558da89f66464d8d0229ff497e8b8666977de2d8cf48c28a2862ecf1250f/huggingface_hub-1.19.0-py3-none-any.whl", hash = "sha256:1dc72e1f6b4d6df6b30eb72e57d00514ef453d660f04af2b87f0e67267f31ee0", size = 693398, upload-time = "2026-06-11T12:33:16.695Z" }, ] [[package]] @@ -2196,11 +2232,11 @@ wheels = [ [[package]] name = "idna" -version = "3.13" +version = "3.18" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/ce/cc/762dfb036166873f0059f3b7de4565e1b5bc3d6f28a414c13da27e442f99/idna-3.13.tar.gz", hash = "sha256:585ea8fe5d69b9181ec1afba340451fba6ba764af97026f92a91d4eef164a242", size = 194210, upload-time = "2026-04-22T16:42:42.314Z" } +sdist = { url = "https://files.pythonhosted.org/packages/cd/63/9496c57188a2ee585e0f1db071d75089a11e98aa86eb99d9d7618fc1edce/idna-3.18.tar.gz", hash = "sha256:ffb385a7e039654cef1ab9ef32c6fafe283c0c0467bba1d9029738ce4a14a848", size = 196711, upload-time = "2026-06-02T14:34:07.794Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/5d/13/ad7d7ca3808a898b4612b6fe93cde56b53f3034dcde235acb1f0e1df24c6/idna-3.13-py3-none-any.whl", hash = "sha256:892ea0cde124a99ce773decba204c5552b69c3c67ffd5f232eb7696135bc8bb3", size = 68629, upload-time = "2026-04-22T16:42:40.909Z" }, + { url = "https://files.pythonhosted.org/packages/1e/5e/d4e9f1a599fb8e573b7b87160658329fbf28d19eac2718f51fc3def3aa5a/idna-3.18-py3-none-any.whl", hash = "sha256:7f952cbe720b688055e3f87de14f5c3e5fdaa8bc3928985c4077ca689de849a2", size = 65455, upload-time = "2026-06-02T14:34:06.319Z" }, ] [[package]] @@ -2272,14 +2308,14 @@ wheels = [ [[package]] name = "jaraco-functools" -version = "4.4.0" +version = "4.5.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "more-itertools" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/0f/27/056e0638a86749374d6f57d0b0db39f29509cce9313cf91bdc0ac4d91084/jaraco_functools-4.4.0.tar.gz", hash = "sha256:da21933b0417b89515562656547a77b4931f98176eb173644c0d35032a33d6bb", size = 19943, upload-time = "2025-12-21T09:29:43.6Z" } +sdist = { url = "https://files.pythonhosted.org/packages/36/cf/ea4ef2920830dea3f5ab2ea4da6fb67724e6dca80ee2553788c3607243d0/jaraco_functools-4.5.0.tar.gz", hash = "sha256:3bb5665ea4a020cf78a7040e89154c77edadb3ca74f366479669c5999aa70b03", size = 20272, upload-time = "2026-05-15T21:34:10.025Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/fd/c4/813bb09f0985cb21e959f21f2464169eca882656849adf727ac7bb7e1767/jaraco_functools-4.4.0-py3-none-any.whl", hash = "sha256:9eec1e36f45c818d9bf307c8948eb03b2b56cd44087b3cdc989abca1f20b9176", size = 10481, upload-time = "2025-12-21T09:29:42.27Z" }, + { url = "https://files.pythonhosted.org/packages/96/9a/982e48afcffcd727a9144506720ffd4224b6b7e355c98641866f38b7c043/jaraco_functools-4.5.0-py3-none-any.whl", hash = "sha256:79ce39246eddbde4b3a03b77ea5f0f7878dc669b166a66cf3fa8e266aa3fa2f4", size = 10594, upload-time = "2026-05-15T21:34:08.595Z" }, ] [[package]] @@ -2305,105 +2341,105 @@ wheels = [ [[package]] name = "jiter" -version = "0.14.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/6e/c1/0cddc6eb17d4c53a99840953f95dd3accdc5cfc7a337b0e9b26476276be9/jiter-0.14.0.tar.gz", hash = "sha256:e8a39e66dac7153cf3f964a12aad515afa8d74938ec5cc0018adcdae5367c79e", size = 165725, upload-time = "2026-04-10T14:28:42.01Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/64/2e/a9959997739c403378d0a4a3a1c4ed80b60aeace216c4d37b303a9fc60a4/jiter-0.14.0-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:02f36a5c700f105ac04a6556fe664a59037a2c200db3b7e88784fac2ddf02531", size = 316927, upload-time = "2026-04-10T14:25:40.753Z" }, - { url = "https://files.pythonhosted.org/packages/27/72/b6de8a531e0adbadd839bec301165feb1fccf00e9ff55073ba2dd20f0043/jiter-0.14.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:41eab6c09ceffb6f0fe25e214b3068146edb1eda3649ca2aee2a061029c7ba2e", size = 321181, upload-time = "2026-04-10T14:25:42.621Z" }, - { url = "https://files.pythonhosted.org/packages/db/d8/2040b9efa13c917f855c40890ae4119fe02c25b7c7677d5b4fa820a851fc/jiter-0.14.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5cf4d4c109641f9cfaf4a7b6aebd51654e405cd00fa9ebbf87163b8b97b325aa", size = 347387, upload-time = "2026-04-10T14:25:44.212Z" }, - { url = "https://files.pythonhosted.org/packages/49/62/655c0ad5ce6a8e90f9068c175b8a236877d753e460762b3183c136db1c5b/jiter-0.14.0-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:b80c7b41a628e6be2213ad0ece763c5f88aa5ee003fa394d58acaaee1f4b8342", size = 373083, upload-time = "2026-04-10T14:25:45.55Z" }, - { url = "https://files.pythonhosted.org/packages/f1/66/549c40fa068f08710b7570869c306a051eb67a29758bd64f4114f730554c/jiter-0.14.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:fb3dbf7cc0d4dbe73cce307ebe7eefa7f73a7d3d854dd119ea0c243f03e40927", size = 463639, upload-time = "2026-04-10T14:25:47.452Z" }, - { url = "https://files.pythonhosted.org/packages/25/2f/97a32a05fed14ed58a18e181fdfb619e05163f3726b54ee6080ec0539c09/jiter-0.14.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7054adcdeb06b46efd17b5734f75817a44a2d06d3748e36c3a023a1bb52af9ec", size = 380735, upload-time = "2026-04-10T14:25:49.305Z" }, - { url = "https://files.pythonhosted.org/packages/2a/3b/4347e1d6c2a973d653bbb7a2d671a2d2426e54b52ba735b8ff0d0a29b75c/jiter-0.14.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d597cd1bf6790376f3fffc7c708766e57301d99a19314824ea0ccc9c3c70e1e2", size = 358632, upload-time = "2026-04-10T14:25:50.931Z" }, - { url = "https://files.pythonhosted.org/packages/ef/24/ca452fbf2ea33548ed30ce68a39a50442d3f7c9bf0704a7af958a930c057/jiter-0.14.0-cp310-cp310-manylinux_2_31_riscv64.whl", hash = "sha256:df63a14878da754427926281626fd3ee249424a186e25a274e78176d42945264", size = 359969, upload-time = "2026-04-10T14:25:52.381Z" }, - { url = "https://files.pythonhosted.org/packages/e3/a3/94470a0d199287caabeb4da2bb2ae5f6d17f3cf05dfc975d7cb064d58e0f/jiter-0.14.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:4ea73187627bcc5810e085df715e8a99da8bdfd96a7eb36b4b4df700ba6d4c9c", size = 397529, upload-time = "2026-04-10T14:25:53.801Z" }, - { url = "https://files.pythonhosted.org/packages/cf/71/6768edc09d7c45c39f093feb3de105fa718a3e982b5208b8a2ed6382b44b/jiter-0.14.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:9f541eaf7bb8382367a1a23d6fc3d6aad57f8dd8c18c3c17f838bee20f217220", size = 522342, upload-time = "2026-04-10T14:25:55.396Z" }, - { url = "https://files.pythonhosted.org/packages/3d/6b/5c2e17559a0f4e96e934479f7137df46c939e983fa05244e674815befb73/jiter-0.14.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:107465250de4fce00fdb47166bcd51df8e634e049541174fe3c71848e44f52ce", size = 556784, upload-time = "2026-04-10T14:25:56.927Z" }, - { url = "https://files.pythonhosted.org/packages/b1/83/c25f3556a60fc74d11199100f1b6cc0c006b815c8494dea8ca16fe398732/jiter-0.14.0-cp310-cp310-win32.whl", hash = "sha256:ffb2a08a406465bb076b7cc1df41d833106d3cf7905076cc73f0cb90078c7d10", size = 208439, upload-time = "2026-04-10T14:25:58.796Z" }, - { url = "https://files.pythonhosted.org/packages/2e/99/781a1b413f0989b7f2ea203b094b331685f1a35e52e0a45e5d000ecaab27/jiter-0.14.0-cp310-cp310-win_amd64.whl", hash = "sha256:cb8b682d10cb0cce7ff4c1af7244af7022c9b01ae16d46c357bdd0df13afb25d", size = 204558, upload-time = "2026-04-10T14:26:00.208Z" }, - { url = "https://files.pythonhosted.org/packages/8a/1f/198ae537fccb7080a0ed655eb56abf64a92f79489dfbf79f40fa34225bcd/jiter-0.14.0-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:7e791e247b8044512e070bd1f3633dc08350d32776d2d6e7473309d0edf256a2", size = 316896, upload-time = "2026-04-10T14:26:01.986Z" }, - { url = "https://files.pythonhosted.org/packages/cf/34/da67cff3fce964a36d03c3e365fb0f8726ade2a6cfd4d3c70107e216ead6/jiter-0.14.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:71527ce13fd5a0c4e40ad37331f8c547177dbb2dd0a93e5278b6a5eecf748804", size = 321085, upload-time = "2026-04-10T14:26:03.364Z" }, - { url = "https://files.pythonhosted.org/packages/ed/36/4c72e67180d4e71a4f5dcf7886d0840e83c49ab11788172177a77570326e/jiter-0.14.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:02c4a7ab56f746014874f2c525584c0daca1dec37f66fd707ecef3b7e5c2228c", size = 347393, upload-time = "2026-04-10T14:26:05.314Z" }, - { url = "https://files.pythonhosted.org/packages/bc/db/9b39e09ceafa9878235c0fc29e3e3f9b12a4c6a98ea3085b998cadf3accc/jiter-0.14.0-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:376e9dafff914253bb9d46cdc5f7965607fbe7feb0a491c34e35f92b2770702e", size = 372937, upload-time = "2026-04-10T14:26:06.884Z" }, - { url = "https://files.pythonhosted.org/packages/b0/96/0dcba1d7a82c1b720774b48ef239376addbaf30df24c34742ac4a57b67b2/jiter-0.14.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:23ad2a7a9da1935575c820428dd8d2490ce4d23189691ce33da1fc0a58e14e1c", size = 463646, upload-time = "2026-04-10T14:26:08.345Z" }, - { url = "https://files.pythonhosted.org/packages/f1/e3/f61b71543e746e6b8b805e7755814fc242715c16f1dba58e1cbccb8032c2/jiter-0.14.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:54b3ddf5786bc7732d293bba3411ac637ecfa200a39983166d1df86a59a43c9f", size = 380225, upload-time = "2026-04-10T14:26:10.161Z" }, - { url = "https://files.pythonhosted.org/packages/ad/5e/0ddeb7096aca099114abe36c4921016e8d251e6f35f5890240b31f1f60ae/jiter-0.14.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5c001d5a646c2a50dc055dd526dad5d5245969e8234d2b1131d0451e81f3a373", size = 358682, upload-time = "2026-04-10T14:26:11.574Z" }, - { url = "https://files.pythonhosted.org/packages/e9/d1/fe0c46cd7fda9cad8f1ff9ad217dc61f1e4280b21052ec6dfe88c1446ef2/jiter-0.14.0-cp311-cp311-manylinux_2_31_riscv64.whl", hash = "sha256:834bb5bdabca2e91592a03d373838a8d0a1b8bbde7077ae6913fd2fc51812d00", size = 359973, upload-time = "2026-04-10T14:26:13.316Z" }, - { url = "https://files.pythonhosted.org/packages/ac/21/f5317f91729b501019184771c80d60abd89907009e7bfa6c7e348c5bdd44/jiter-0.14.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:4e9178be60e229b1b2b0710f61b9e24d1f4f8556985a83ff4c4f95920eea7314", size = 397568, upload-time = "2026-04-10T14:26:15.212Z" }, - { url = "https://files.pythonhosted.org/packages/e9/05/79d8f33fb2bf168db0df5c9cd16fe440a8ada57e929d3677b22712c2568f/jiter-0.14.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:a7e4ccff04ec03614e62c613e976a3a5860dc9714ce8266f44328bdc8b1cab2c", size = 522535, upload-time = "2026-04-10T14:26:16.956Z" }, - { url = "https://files.pythonhosted.org/packages/5c/00/d1e3ff3d2a465e67f08507d74bafb2dcd29eba91dc939820e39e8dea38b8/jiter-0.14.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:69539d936fb5d55caf6ecd33e2e884de083ff0ea28579780d56c4403094bb8d9", size = 556709, upload-time = "2026-04-10T14:26:18.5Z" }, - { url = "https://files.pythonhosted.org/packages/60/5b/bbb2189f62ace8d95e869aa4c84c9946616f301e2d02895a6f20dcc3bba3/jiter-0.14.0-cp311-cp311-win32.whl", hash = "sha256:4927d09b3e572787cc5e0a5318601448e1ab9391bcef95677f5840c2d00eaa6d", size = 208660, upload-time = "2026-04-10T14:26:20.511Z" }, - { url = "https://files.pythonhosted.org/packages/b8/86/c500b53dcbf08575f5963e536ebd757a1f7c568272ba5d180b212c9a87fb/jiter-0.14.0-cp311-cp311-win_amd64.whl", hash = "sha256:42d6ed359ac49eb922fdd565f209c57340aa06d589c84c8413e42a0f9ae1b842", size = 204659, upload-time = "2026-04-10T14:26:22.152Z" }, - { url = "https://files.pythonhosted.org/packages/75/4a/a676249049d42cb29bef82233e4fe0524d414cbe3606c7a4b311193c2f77/jiter-0.14.0-cp311-cp311-win_arm64.whl", hash = "sha256:6dd689f5f4a5a33747b28686e051095beb214fe28cfda5e9fe58a295a788f593", size = 194772, upload-time = "2026-04-10T14:26:23.458Z" }, - { url = "https://files.pythonhosted.org/packages/5a/68/7390a418f10897da93b158f2d5a8bd0bcd73a0f9ec3bb36917085bb759ef/jiter-0.14.0-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:2fb2ce3a7bc331256dfb14cefc34832366bb28a9aca81deaf43bbf2a5659e607", size = 316295, upload-time = "2026-04-10T14:26:24.887Z" }, - { url = "https://files.pythonhosted.org/packages/60/a0/5854ac00ff63551c52c6c89534ec6aba4b93474e7924d64e860b1c94165b/jiter-0.14.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:5252a7ca23785cef5d02d4ece6077a1b556a410c591b379f82091c3001e14844", size = 315898, upload-time = "2026-04-10T14:26:26.601Z" }, - { url = "https://files.pythonhosted.org/packages/41/a1/4f44832650a16b18e8391f1bf1d6ca4909bc738351826bcc198bba4357f4/jiter-0.14.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c409578cbd77c338975670ada777add4efd53379667edf0aceea730cabede6fb", size = 343730, upload-time = "2026-04-10T14:26:28.326Z" }, - { url = "https://files.pythonhosted.org/packages/48/64/a329e9d469f86307203594b1707e11ae51c3348d03bfd514a5f997870012/jiter-0.14.0-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:7ede4331a1899d604463369c730dbb961ffdc5312bc7f16c41c2896415b1304a", size = 370102, upload-time = "2026-04-10T14:26:30.089Z" }, - { url = "https://files.pythonhosted.org/packages/94/c1/5e3dfc59635aa4d4c7bd20a820ac1d09b8ed851568356802cf1c08edb3cf/jiter-0.14.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:92cd8b6025981a041f5310430310b55b25ca593972c16407af8837d3d7d2ca01", size = 461335, upload-time = "2026-04-10T14:26:31.911Z" }, - { url = "https://files.pythonhosted.org/packages/e3/1b/dd157009dbc058f7b00108f545ccb72a2d56461395c4fc7b9cfdccb00af4/jiter-0.14.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:351bf6eda4e3a7ceb876377840c702e9a3e4ecc4624dbfb2d6463c67ae52637d", size = 378536, upload-time = "2026-04-10T14:26:33.595Z" }, - { url = "https://files.pythonhosted.org/packages/91/78/256013667b7c10b8834f8e6e54cd3e562d4c6e34227a1596addccc05e38c/jiter-0.14.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c1dcfbeb93d9ecd9ca128bbf8910120367777973fa193fb9a39c31237d8df165", size = 353859, upload-time = "2026-04-10T14:26:35.098Z" }, - { url = "https://files.pythonhosted.org/packages/de/d9/137d65ade9093a409fe80955ce60b12bb753722c986467aeda47faf450ad/jiter-0.14.0-cp312-cp312-manylinux_2_31_riscv64.whl", hash = "sha256:ae039aaef8de3f8157ecc1fdd4d85043ac4f57538c245a0afaecb8321ec951c3", size = 357626, upload-time = "2026-04-10T14:26:36.685Z" }, - { url = "https://files.pythonhosted.org/packages/2e/48/76750835b87029342727c1a268bea8878ab988caf81ee4e7b880900eeb5a/jiter-0.14.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:7d9d51eb96c82a9652933bd769fe6de66877d6eb2b2440e281f2938c51b5643e", size = 393172, upload-time = "2026-04-10T14:26:38.097Z" }, - { url = "https://files.pythonhosted.org/packages/a6/60/456c4e81d5c8045279aefe60e9e483be08793828800a4e64add8fdde7f2a/jiter-0.14.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:d824ca4148b705970bf4e120924a212fdfca9859a73e42bd7889a63a4ea6bb98", size = 520300, upload-time = "2026-04-10T14:26:39.532Z" }, - { url = "https://files.pythonhosted.org/packages/a8/9f/2020e0984c235f678dced38fe4eec3058cf528e6af36ebf969b410305941/jiter-0.14.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:ff3a6465b3a0f54b1a430f45c3c0ba7d61ceb45cbc3e33f9e1a7f638d690baf3", size = 553059, upload-time = "2026-04-10T14:26:40.991Z" }, - { url = "https://files.pythonhosted.org/packages/ef/32/e2d298e1a22a4bbe6062136d1c7192db7dba003a6975e51d9a9eecabc4c2/jiter-0.14.0-cp312-cp312-win32.whl", hash = "sha256:5dec7c0a3e98d2a3f8a2e67382d0d7c3ac60c69103a4b271da889b4e8bb1e129", size = 206030, upload-time = "2026-04-10T14:26:42.517Z" }, - { url = "https://files.pythonhosted.org/packages/36/ac/96369141b3d8a4a8e4590e983085efe1c436f35c0cda940dd76d942e3e40/jiter-0.14.0-cp312-cp312-win_amd64.whl", hash = "sha256:fc7e37b4b8bc7e80a63ad6cfa5fc11fab27dbfea4cc4ae644b1ab3f273dc348f", size = 201603, upload-time = "2026-04-10T14:26:44.328Z" }, - { url = "https://files.pythonhosted.org/packages/01/c3/75d847f264647017d7e3052bbcc8b1e24b95fa139c320c5f5066fa7a0bdd/jiter-0.14.0-cp312-cp312-win_arm64.whl", hash = "sha256:ee4a72f12847ef29b072aee9ad5474041ab2924106bdca9fcf5d7d965853e057", size = 191525, upload-time = "2026-04-10T14:26:46Z" }, - { url = "https://files.pythonhosted.org/packages/97/2a/09f70020898507a89279659a1afe3364d57fc1b2c89949081975d135f6f5/jiter-0.14.0-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:af72f204cf4d44258e5b4c1745130ac45ddab0e71a06333b01de660ab4187a94", size = 315502, upload-time = "2026-04-10T14:26:47.697Z" }, - { url = "https://files.pythonhosted.org/packages/d6/be/080c96a45cd74f9fce5db4fd68510b88087fb37ffe2541ff73c12db92535/jiter-0.14.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:4b77da71f6e819be5fbcec11a453fde5b1d0267ef6ed487e2a392fd8e14e4e3a", size = 314870, upload-time = "2026-04-10T14:26:49.149Z" }, - { url = "https://files.pythonhosted.org/packages/7d/5e/2d0fee155826a968a832cc32438de5e2a193292c8721ca70d0b53e58245b/jiter-0.14.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:77f4ea612fe8b84b8b04e51d0e78029ecf3466348e25973f953de6e6a59aa4c1", size = 343406, upload-time = "2026-04-10T14:26:50.762Z" }, - { url = "https://files.pythonhosted.org/packages/70/af/bf9ee0d3a4f8dc0d679fc1337f874fe60cdbf841ebbb304b374e1c9aaceb/jiter-0.14.0-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:62fe2451f8fcc0240261e6a4df18ecbcd58327857e61e625b2393ea3b468aac9", size = 369415, upload-time = "2026-04-10T14:26:52.188Z" }, - { url = "https://files.pythonhosted.org/packages/0f/83/8e8561eadba31f4d3948a5b712fb0447ec71c3560b57a855449e7b8ddc98/jiter-0.14.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6112f26f5afc75bcb475787d29da3aa92f9d09c7858f632f4be6ffe607be82e9", size = 461456, upload-time = "2026-04-10T14:26:53.611Z" }, - { url = "https://files.pythonhosted.org/packages/f6/c9/c5299e826a5fe6108d172b344033f61c69b1bb979dd8d9ddd4278a160971/jiter-0.14.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:215a6cb8fb7dc702aa35d475cc00ddc7f970e5c0b1417fb4b4ac5d82fa2a29db", size = 378488, upload-time = "2026-04-10T14:26:55.211Z" }, - { url = "https://files.pythonhosted.org/packages/5d/37/c16d9d15c0a471b8644b1abe3c82668092a707d9bedcf076f24ff2e380cd/jiter-0.14.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fc4ab96a30fb3cb2c7e0cd33f7616c8860da5f5674438988a54ac717caccdbaa", size = 353242, upload-time = "2026-04-10T14:26:56.705Z" }, - { url = "https://files.pythonhosted.org/packages/58/ea/8050cb0dc654e728e1bfacbc0c640772f2181af5dedd13ae70145743a439/jiter-0.14.0-cp313-cp313-manylinux_2_31_riscv64.whl", hash = "sha256:3a99c1387b1f2928f799a9de899193484d66206a50e98233b6b088a7f0c1edb2", size = 356823, upload-time = "2026-04-10T14:26:58.281Z" }, - { url = "https://files.pythonhosted.org/packages/b0/3b/cf71506d270e5f84d97326bf220e47aed9b95e9a4a060758fb07772170ab/jiter-0.14.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:ab18d11074485438695f8d34a1b6da61db9754248f96d51341956607a8f39985", size = 392564, upload-time = "2026-04-10T14:27:00.018Z" }, - { url = "https://files.pythonhosted.org/packages/b0/cc/8c6c74a3efb5bd671bfd14f51e8a73375464ca914b1551bc3b40e26ac2c9/jiter-0.14.0-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:801028dcfc26ac0895e4964cbc0fd62c73be9fd4a7d7b1aaf6e5790033a719b7", size = 520322, upload-time = "2026-04-10T14:27:01.664Z" }, - { url = "https://files.pythonhosted.org/packages/41/24/68d7b883ec959884ddf00d019b2e0e82ba81b167e1253684fa90519ce33c/jiter-0.14.0-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:ad425b087aafb4a1c7e1e98a279200743b9aaf30c3e0ba723aec93f061bd9bc8", size = 552619, upload-time = "2026-04-10T14:27:03.316Z" }, - { url = "https://files.pythonhosted.org/packages/b6/89/b1a0985223bbf3150ff9e8f46f98fc9360c1de94f48abe271bbe1b465682/jiter-0.14.0-cp313-cp313-win32.whl", hash = "sha256:882bcb9b334318e233950b8be366fe5f92c86b66a7e449e76975dfd6d776a01f", size = 205699, upload-time = "2026-04-10T14:27:04.662Z" }, - { url = "https://files.pythonhosted.org/packages/4c/19/3f339a5a7f14a11730e67f6be34f9d5105751d547b615ef593fa122a5ded/jiter-0.14.0-cp313-cp313-win_amd64.whl", hash = "sha256:9b8c571a5dba09b98bd3462b5a53f27209a5cbbe85670391692ede71974e979f", size = 201323, upload-time = "2026-04-10T14:27:06.139Z" }, - { url = "https://files.pythonhosted.org/packages/50/56/752dd89c84be0e022a8ea3720bcfa0a8431db79a962578544812ce061739/jiter-0.14.0-cp313-cp313-win_arm64.whl", hash = "sha256:34f19dcc35cb1abe7c369b3756babf8c7f04595c0807a848df8f26ef8298ef92", size = 191099, upload-time = "2026-04-10T14:27:07.564Z" }, - { url = "https://files.pythonhosted.org/packages/91/28/292916f354f25a1fe8cf2c918d1415c699a4a659ae00be0430e1c5d9ffea/jiter-0.14.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:e89bcd7d426a75bb4952c696b267075790d854a07aad4c9894551a82c5b574ab", size = 320880, upload-time = "2026-04-10T14:27:09.326Z" }, - { url = "https://files.pythonhosted.org/packages/ad/c7/b002a7d8b8957ac3d469bd59c18ef4b1595a5216ae0de639a287b9816023/jiter-0.14.0-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7b25beaa0d4447ea8c7ae0c18c688905d34840d7d0b937f2f7bdd52162c98a40", size = 346563, upload-time = "2026-04-10T14:27:11.287Z" }, - { url = "https://files.pythonhosted.org/packages/f9/3b/f8d07580d8706021d255a6356b8fab13ee4c869412995550ce6ed4ddf97d/jiter-0.14.0-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:651a8758dd413c51e3b7f6557cdc6921faf70b14106f45f969f091f5cda990ea", size = 357928, upload-time = "2026-04-10T14:27:12.729Z" }, - { url = "https://files.pythonhosted.org/packages/47/5b/ac1a974da29e35507230383110ffec59998b290a8732585d04e19a9eb5ba/jiter-0.14.0-cp313-cp313t-win_amd64.whl", hash = "sha256:e1a7eead856a5038a8d291f1447176ab0b525c77a279a058121b5fccee257f6f", size = 203519, upload-time = "2026-04-10T14:27:14.125Z" }, - { url = "https://files.pythonhosted.org/packages/96/6d/9fc8433d667d2454271378a79747d8c76c10b51b482b454e6190e511f244/jiter-0.14.0-cp313-cp313t-win_arm64.whl", hash = "sha256:2e692633a12cda97e352fdcd1c4acc971b1c28707e1e33aeef782b0cbf051975", size = 190113, upload-time = "2026-04-10T14:27:16.638Z" }, - { url = "https://files.pythonhosted.org/packages/4f/1e/354ed92461b165bd581f9ef5150971a572c873ec3b68a916d5aa91da3cc2/jiter-0.14.0-cp314-cp314-macosx_10_12_x86_64.whl", hash = "sha256:6f396837fc7577871ca8c12edaf239ed9ccef3bbe39904ae9b8b63ce0a48b140", size = 315277, upload-time = "2026-04-10T14:27:18.109Z" }, - { url = "https://files.pythonhosted.org/packages/a6/95/8c7c7028aa8636ac21b7a55faef3e34215e6ed0cbf5ae58258427f621aa3/jiter-0.14.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:a4d50ea3d8ba4176f79754333bd35f1bbcd28e91adc13eb9b7ca91bc52a6cef9", size = 315923, upload-time = "2026-04-10T14:27:19.603Z" }, - { url = "https://files.pythonhosted.org/packages/47/40/e2a852a44c4a089f2681a16611b7ce113224a80fd8504c46d78491b47220/jiter-0.14.0-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ce17f8a050447d1b4153bda4fb7d26e6a9e74eb4f4a41913f30934c5075bf615", size = 344943, upload-time = "2026-04-10T14:27:21.262Z" }, - { url = "https://files.pythonhosted.org/packages/fc/1f/670f92adee1e9895eac41e8a4d623b6da68c4d46249d8b556b60b63f949e/jiter-0.14.0-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:f4f1c4b125e1652aefbc2e2c1617b60a160ab789d180e3d423c41439e5f32850", size = 369725, upload-time = "2026-04-10T14:27:22.766Z" }, - { url = "https://files.pythonhosted.org/packages/01/2f/541c9ba567d05de1c4874a0f8f8c5e3fd78e2b874266623da9a775cf46e0/jiter-0.14.0-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:be808176a6a3a14321d18c603f2d40741858a7c4fc982f83232842689fe86dd9", size = 461210, upload-time = "2026-04-10T14:27:24.315Z" }, - { url = "https://files.pythonhosted.org/packages/ce/a9/c31cbec09627e0d5de7aeaec7690dba03e090caa808fefd8133137cf45bc/jiter-0.14.0-cp314-cp314-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:26679d58ba816f88c3849306dd58cb863a90a1cf352cdd4ef67e30ccf8a77994", size = 380002, upload-time = "2026-04-10T14:27:26.155Z" }, - { url = "https://files.pythonhosted.org/packages/50/02/3c05c1666c41904a2f607475a73e7a4763d1cbde2d18229c4f85b22dc253/jiter-0.14.0-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:80381f5a19af8fa9aef743f080e34f6b25ebd89656475f8cf0470ec6157052aa", size = 354678, upload-time = "2026-04-10T14:27:27.701Z" }, - { url = "https://files.pythonhosted.org/packages/7d/97/e15b33545c2b13518f560d695f974b9891b311641bdcf178d63177e8801e/jiter-0.14.0-cp314-cp314-manylinux_2_31_riscv64.whl", hash = "sha256:004df5fdb8ecbd6d99f3227df18ba1a259254c4359736a2e6f036c944e02d7c5", size = 358920, upload-time = "2026-04-10T14:27:29.256Z" }, - { url = "https://files.pythonhosted.org/packages/ad/d2/8b1461def6b96ba44530df20d07ef7a1c7da22f3f9bf1727e2d611077bf1/jiter-0.14.0-cp314-cp314-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:cff5708f7ed0fa098f2b53446c6fa74c48469118e5cd7497b4f1cd569ab06928", size = 394512, upload-time = "2026-04-10T14:27:31.344Z" }, - { url = "https://files.pythonhosted.org/packages/e3/88/837566dd6ed6e452e8d3205355afd484ce44b2533edfa4ed73a298ea893e/jiter-0.14.0-cp314-cp314-musllinux_1_1_aarch64.whl", hash = "sha256:2492e5f06c36a976d25c7cc347a60e26d5470178d44cde1b9b75e60b4e519f28", size = 521120, upload-time = "2026-04-10T14:27:33.299Z" }, - { url = "https://files.pythonhosted.org/packages/89/6b/b00b45c4d1b4c031777fe161d620b755b5b02cdade1e316dcb46e4471d63/jiter-0.14.0-cp314-cp314-musllinux_1_1_x86_64.whl", hash = "sha256:7609cfbe3a03d37bfdbf5052012d5a879e72b83168a363deae7b3a26564d57de", size = 553668, upload-time = "2026-04-10T14:27:34.868Z" }, - { url = "https://files.pythonhosted.org/packages/ad/d8/6fe5b42011d19397433d345716eac16728ac241862a2aac9c91923c7509a/jiter-0.14.0-cp314-cp314-win32.whl", hash = "sha256:7282342d32e357543565286b6450378c3cd402eea333fc1ebe146f1fabb306fc", size = 207001, upload-time = "2026-04-10T14:27:36.455Z" }, - { url = "https://files.pythonhosted.org/packages/e5/43/5c2e08da1efad5e410f0eaaabeadd954812612c33fbbd8fd5328b489139d/jiter-0.14.0-cp314-cp314-win_amd64.whl", hash = "sha256:bd77945f38866a448e73b0b7637366afa814d4617790ecd88a18ca74377e6c02", size = 202187, upload-time = "2026-04-10T14:27:38Z" }, - { url = "https://files.pythonhosted.org/packages/aa/1f/6e39ac0b4cdfa23e606af5b245df5f9adaa76f35e0c5096790da430ca506/jiter-0.14.0-cp314-cp314-win_arm64.whl", hash = "sha256:f2d4c61da0821ee42e0cdf5489da60a6d074306313a377c2b35af464955a3611", size = 192257, upload-time = "2026-04-10T14:27:39.504Z" }, - { url = "https://files.pythonhosted.org/packages/05/57/7dbc0ffbbb5176a27e3518716608aa464aee2e2887dc938f0b900a120449/jiter-0.14.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:1bf7ff85517dd2f20a5750081d2b75083c1b269cf75afc7511bdf1f9548beb3b", size = 323441, upload-time = "2026-04-10T14:27:41.039Z" }, - { url = "https://files.pythonhosted.org/packages/83/6e/7b3314398d8983f06b557aa21b670511ec72d3b79a68ee5e4d9bff972286/jiter-0.14.0-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c8ef8791c3e78d6c6b157c6d360fbb5c715bebb8113bc6a9303c5caff012754a", size = 348109, upload-time = "2026-04-10T14:27:42.552Z" }, - { url = "https://files.pythonhosted.org/packages/ae/4f/8dc674bcd7db6dba566de73c08c763c337058baff1dbeb34567045b27cdc/jiter-0.14.0-cp314-cp314t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e74663b8b10da1fe0f4e4703fd7980d24ad17174b6bb35d8498d6e3ebce2ae6a", size = 368328, upload-time = "2026-04-10T14:27:44.574Z" }, - { url = "https://files.pythonhosted.org/packages/3b/5f/188e09a1f20906f98bbdec44ed820e19f4e8eb8aff88b9d1a5a497587ff3/jiter-0.14.0-cp314-cp314t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1aca29ba52913f78362ec9c2da62f22cdc4c3083313403f90c15460979b84d9b", size = 463301, upload-time = "2026-04-10T14:27:46.717Z" }, - { url = "https://files.pythonhosted.org/packages/ac/f0/19046ef965ed8f349e8554775bb12ff4352f443fbe12b95d31f575891256/jiter-0.14.0-cp314-cp314t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8b39b7d87a952b79949af5fef44d2544e58c21a28da7f1bae3ef166455c61746", size = 378891, upload-time = "2026-04-10T14:27:48.32Z" }, - { url = "https://files.pythonhosted.org/packages/c4/c3/da43bd8431ee175695777ee78cf0e93eacbb47393ff493f18c45231b427d/jiter-0.14.0-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:78d918a68b26e9fab068c2b5453577ef04943ab2807b9a6275df2a812599a310", size = 360749, upload-time = "2026-04-10T14:27:49.88Z" }, - { url = "https://files.pythonhosted.org/packages/72/26/e054771be889707c6161dbdec9c23d33a9ec70945395d70f07cfea1e9a6f/jiter-0.14.0-cp314-cp314t-manylinux_2_31_riscv64.whl", hash = "sha256:b08997c35aee1201c1a5361466a8fb9162d03ae7bf6568df70b6c859f1e654a4", size = 358526, upload-time = "2026-04-10T14:27:51.504Z" }, - { url = "https://files.pythonhosted.org/packages/c3/0f/7bea65ea2a6d91f2bf989ff11a18136644392bf2b0497a1fa50934c30a9c/jiter-0.14.0-cp314-cp314t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:260bf7ca20704d58d41f669e5e9fe7fe2fa72901a6b324e79056f5d52e9c9be2", size = 393926, upload-time = "2026-04-10T14:27:53.368Z" }, - { url = "https://files.pythonhosted.org/packages/3c/a1/b1ff7d70deef61ac0b7c6c2f12d2ace950cdeecb4fdc94500a0926802857/jiter-0.14.0-cp314-cp314t-musllinux_1_1_aarch64.whl", hash = "sha256:37826e3df29e60f30a382f9294348d0238ef127f4b5d7f5f8da78b5b9e050560", size = 521052, upload-time = "2026-04-10T14:27:55.058Z" }, - { url = "https://files.pythonhosted.org/packages/0b/7b/3b0649983cbaf15eda26a414b5b1982e910c67bd6f7b1b490f3cfc76896a/jiter-0.14.0-cp314-cp314t-musllinux_1_1_x86_64.whl", hash = "sha256:645be49c46f2900937ba0eaf871ad5183c96858c0af74b6becc7f4e367e36e06", size = 553716, upload-time = "2026-04-10T14:27:57.269Z" }, - { url = "https://files.pythonhosted.org/packages/97/f8/33d78c83bd93ae0c0af05293a6660f88a1977caef39a6d72a84afab94ce0/jiter-0.14.0-cp314-cp314t-win32.whl", hash = "sha256:2f7877ed45118de283786178eceaf877110abacd04fde31efff3940ae9672674", size = 207957, upload-time = "2026-04-10T14:27:59.285Z" }, - { url = "https://files.pythonhosted.org/packages/d6/ac/2b760516c03e2227826d1f7025d89bf6bf6357a28fe75c2a2800873c50bf/jiter-0.14.0-cp314-cp314t-win_amd64.whl", hash = "sha256:14c0cb10337c49f5eafe8e7364daca5e29a020ea03580b8f8e6c597fed4e1588", size = 204690, upload-time = "2026-04-10T14:28:00.962Z" }, - { url = "https://files.pythonhosted.org/packages/dc/2e/a44c20c58aeed0355f2d326969a181696aeb551a25195f47563908a815be/jiter-0.14.0-cp314-cp314t-win_arm64.whl", hash = "sha256:5419d4aa2024961da9fe12a9cfe7484996735dca99e8e090b5c88595ef1951ff", size = 191338, upload-time = "2026-04-10T14:28:02.853Z" }, - { url = "https://files.pythonhosted.org/packages/32/a1/ef34ca2cab2962598591636a1804b93645821201cc0095d4a93a9a329c9d/jiter-0.14.0-graalpy311-graalpy242_311_native-macosx_10_12_x86_64.whl", hash = "sha256:a25ffa2dbbdf8721855612f6dca15c108224b12d0c4024d0ac3d7902132b4211", size = 311366, upload-time = "2026-04-10T14:28:27.943Z" }, - { url = "https://files.pythonhosted.org/packages/60/bb/520576a532a6b8a6f42747afed289c8448c879a34d7802fe2c832d4fd38f/jiter-0.14.0-graalpy311-graalpy242_311_native-macosx_11_0_arm64.whl", hash = "sha256:0ac9cbaa86c10996b92bd12c91659b60f939f8e28fcfa6bc11a0e90a774ce95b", size = 309873, upload-time = "2026-04-10T14:28:29.688Z" }, - { url = "https://files.pythonhosted.org/packages/b2/7c/c16db114ea1f2f532f198aa8dc39585026af45af362c69a0492f31bc4821/jiter-0.14.0-graalpy311-graalpy242_311_native-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:844e73b6c56b505e9e169234ea3bdea2ea43f769f847f47ac559ba1d2361ebea", size = 344816, upload-time = "2026-04-10T14:28:31.348Z" }, - { url = "https://files.pythonhosted.org/packages/99/8f/15e7741ff19e9bcd4d753f7ff22f988fd54592f134ca13701c13ea8c20e0/jiter-0.14.0-graalpy311-graalpy242_311_native-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e52c076f187405fc21523c746c04399c9af8ece566077ed147b2126f2bcba577", size = 351445, upload-time = "2026-04-10T14:28:33.093Z" }, - { url = "https://files.pythonhosted.org/packages/21/42/9042c3f3019de4adcb8c16591c325ec7255beea9fcd33a42a43f3b0b1000/jiter-0.14.0-graalpy312-graalpy250_312_native-macosx_10_12_x86_64.whl", hash = "sha256:fbd9e482663ca9d005d051330e4d2d8150bb208a209409c10f7e7dfdf7c49da9", size = 308810, upload-time = "2026-04-10T14:28:34.673Z" }, - { url = "https://files.pythonhosted.org/packages/60/cf/a7e19b308bd86bb04776803b1f01a5f9a287a4c55205f4708827ee487fbf/jiter-0.14.0-graalpy312-graalpy250_312_native-macosx_11_0_arm64.whl", hash = "sha256:33a20d838b91ef376b3a56896d5b04e725c7df5bc4864cc6569cf046a8d73b6d", size = 308443, upload-time = "2026-04-10T14:28:36.658Z" }, - { url = "https://files.pythonhosted.org/packages/ca/44/e26ede3f0caeff93f222559cb0cc4ca68579f07d009d7b6010c5b586f9b1/jiter-0.14.0-graalpy312-graalpy250_312_native-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:432c4db5255d86a259efde91e55cb4c8d18c0521d844c9e2e7efcce3899fb016", size = 343039, upload-time = "2026-04-10T14:28:38.356Z" }, - { url = "https://files.pythonhosted.org/packages/da/e9/1f9ada30cef7b05e74bb06f52127e7a724976c225f46adb65c37b1dadfb6/jiter-0.14.0-graalpy312-graalpy250_312_native-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:67f00d94b281174144d6532a04b66a12cb866cbdc47c3af3bfe2973677f9861a", size = 349613, upload-time = "2026-04-10T14:28:40.066Z" }, +version = "0.15.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/66/b5/55f06bb281d92fb3cc86d14e1def2bd908bb77693183e7cb1f5a3c388b0c/jiter-0.15.0.tar.gz", hash = "sha256:4251acc80e2b7c9b7b8823456ea0fceeb0734dac2df7636d3c711b38476b5a76", size = 166640, upload-time = "2026-05-19T10:09:48.361Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/1d/da/76a2c7e510ba15fe323d9509c223ab272da79ea59f54488f4a78da6426db/jiter-0.15.0-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:edebcf7d1f601199084bb6e844d7dc67e03e04f6ac786b0332d616635c4ff7a4", size = 310849, upload-time = "2026-05-19T10:06:51.944Z" }, + { url = "https://files.pythonhosted.org/packages/5d/8e/827be942883a4dc0862c48626ff41af3320b1902d136a0bf4b9041f2c567/jiter-0.15.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9f924585cdacf631cd382b657966847bb537bf9ed0a6f9b991da5f05a631480f", size = 314991, upload-time = "2026-05-19T10:06:53.522Z" }, + { url = "https://files.pythonhosted.org/packages/6d/38/be2832be361ba1b9517c76f46d30b64e985be1dd43c974f4c3a4b1844436/jiter-0.15.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:abbf258599526ad0326fe51e252e24f2bd6f24f1852681b4b78feda3808f1d18", size = 340843, upload-time = "2026-05-19T10:06:55.071Z" }, + { url = "https://files.pythonhosted.org/packages/6d/d8/90f01fb83c0c7ba509303ec93e32a308fbfa167d264860b01c0fd0dbbd06/jiter-0.15.0-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:7c468136b8bd6bb18c8786e4236a1fa27362f24cb23450ba0cb204ab379b8e6f", size = 365116, upload-time = "2026-05-19T10:06:56.893Z" }, + { url = "https://files.pythonhosted.org/packages/91/38/94593d34f8c67a0b6f6cbc027f016ffa9780b3a858a7a86f6fd7a15bcc1e/jiter-0.15.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:05906b93d72f03339e6bb7cf8dc10ebda64a0266126eed6beba79e20abcf5fd4", size = 457970, upload-time = "2026-05-19T10:06:58.707Z" }, + { url = "https://files.pythonhosted.org/packages/df/04/d79962dd49d00c97e2a9b4cacea1947904d02135936960351f9a96d4c1a6/jiter-0.15.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:30ce785d2adb8e32c3f7741442370a74834ec4c01f3c48f0750227a0b4ef27d6", size = 375744, upload-time = "2026-05-19T10:07:00.471Z" }, + { url = "https://files.pythonhosted.org/packages/c3/2e/5d37abe2be0e819c21e2338bebd410e481763ce526a9138c8c3652fa0123/jiter-0.15.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2fd73e3da91a0a722d67165e849ce2cdc10de0e0d48738c142be8c6c5f310f4c", size = 349609, upload-time = "2026-05-19T10:07:01.829Z" }, + { url = "https://files.pythonhosted.org/packages/7a/90/98768ad2ed90c1fda15d64157de2dfbf73c1c074d4b1bfaca915480bc7cf/jiter-0.15.0-cp310-cp310-manylinux_2_31_riscv64.whl", hash = "sha256:ceb8fc27d38793f9c97149be8302720c5b22e5c195a37bf2c45dc36c4600a512", size = 354366, upload-time = "2026-05-19T10:07:03.587Z" }, + { url = "https://files.pythonhosted.org/packages/d6/c4/fbfb806209f1fe4b7dccdfb07bc62bb044300734a945b06fd64db446ef6a/jiter-0.15.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d726e3ceeb337191324b49de298142f27c3ad10886341555d1d5315b5f252c6a", size = 393519, upload-time = "2026-05-19T10:07:05.08Z" }, + { url = "https://files.pythonhosted.org/packages/37/1c/b9c257cd70cb453b6d10f3ebf0402cdb11669ab455389096f09839670290/jiter-0.15.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:2c8aea7781d2a372227871de4e1a1332aa96f5a89fd76c5e835dafdbad102887", size = 519952, upload-time = "2026-05-19T10:07:06.589Z" }, + { url = "https://files.pythonhosted.org/packages/a9/1a/aa85027db7ab15829c12feebbc33b404f53fc399bd559d85fd0d6365ff0d/jiter-0.15.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:cf4bd113a69c0a740e27cb962ce10630c36d2b8f59d759a651b955ee9d18a823", size = 550770, upload-time = "2026-05-19T10:07:08.228Z" }, + { url = "https://files.pythonhosted.org/packages/d4/54/8c3f65c8a5687925e84708f19d63f7f37d28e2b86a48d951702ad94424d8/jiter-0.15.0-cp310-cp310-win32.whl", hash = "sha256:d92a5cd21fdb083931d546c207aa29633787c5dc5b02daab2d32b843f88a2c53", size = 209303, upload-time = "2026-05-19T10:07:10.006Z" }, + { url = "https://files.pythonhosted.org/packages/d5/72/0528a1eb9f42dd2d8228a0711458628f35924d131f623eaebc35fd23d3d4/jiter-0.15.0-cp310-cp310-win_amd64.whl", hash = "sha256:e58585a58209d72691ce2d62a9147445f5a87beb0bde97fde284c96ae392a3d1", size = 200404, upload-time = "2026-05-19T10:07:11.426Z" }, + { url = "https://files.pythonhosted.org/packages/e4/13/daa722f5765c393576f466378f9dfd29d77c9bed939e0688f96afa3601ea/jiter-0.15.0-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:0f862193b8696249d22ec433e85fd2ab0ad9596bc3e45e6c0bc55e8aeba97be2", size = 310899, upload-time = "2026-05-19T10:07:12.89Z" }, + { url = "https://files.pythonhosted.org/packages/7f/82/2d2551829b082f4b6d82b9f939b031fb808a10aab1ec0664f82e150bb9a2/jiter-0.15.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:1303d4d68a9b051ea90502402063ecf3807da00ad2affa19ca1ae3b90b3c5f67", size = 314963, upload-time = "2026-05-19T10:07:14.539Z" }, + { url = "https://files.pythonhosted.org/packages/2a/0a/8b1a51466f7fe9f31dbe4bc7e0ca848674f9825e0f737b929b97e8c60aa7/jiter-0.15.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:392b8ab019e5502d08aff85c6272209c24bc2cbe706ea82a56368f524236614a", size = 341730, upload-time = "2026-05-19T10:07:15.869Z" }, + { url = "https://files.pythonhosted.org/packages/f6/2a/e71dea19822e2e404e83992a08c1d6b9b617bb944f28c9c2fbd85d02c91e/jiter-0.15.0-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:773b6eb282ce11ee19f05f6b2d4404fa308e5bbd353b0b80a0262caad6db2cd7", size = 366214, upload-time = "2026-05-19T10:07:17.259Z" }, + { url = "https://files.pythonhosted.org/packages/c4/59/97e1fa539d124a509a00ab7f669289d1c1d236ecabf12948a18f16c91082/jiter-0.15.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8d2c0c44d569ce0f2850f5c926f8caeb5f245fbc84475aeb36efccc2103e6dbd", size = 459527, upload-time = "2026-05-19T10:07:18.741Z" }, + { url = "https://files.pythonhosted.org/packages/d1/7a/4a68d331aef8cf2e2393c14a3aacb635c62aa86071b0229899fb5baaa907/jiter-0.15.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:032396229564bca02440396bd327710719f724f5e7b7e9f7a8eb3faa4a2c2281", size = 375451, upload-time = "2026-05-19T10:07:20.208Z" }, + { url = "https://files.pythonhosted.org/packages/7b/7e/1c445c2b6f0e30a274dc8082e0c3c7825411cce80d726bccd697c98cc8d3/jiter-0.15.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f3d37768fce7f88dd2a8c6091f2325dea27d30d30d5c6e7a1c0f0af77723b708", size = 349428, upload-time = "2026-05-19T10:07:22.372Z" }, + { url = "https://files.pythonhosted.org/packages/00/94/e20d38984fc17a636371bffd2ae0f698124fdc8e75ef969cd2da6ba7cea7/jiter-0.15.0-cp311-cp311-manylinux_2_31_riscv64.whl", hash = "sha256:2c9cb907439d20bd0c7d7565ca01ee52234203208433749bae5b516907526928", size = 355405, upload-time = "2026-05-19T10:07:23.916Z" }, + { url = "https://files.pythonhosted.org/packages/94/fa/4d09f814779d0ea80a28ed8e4c6662ec9a4a8ecef0ac52190ebac6262d14/jiter-0.15.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:9100ddbec09741cc66feb0fc6773f8bdbd0e3c345689368f260082ff85dcc0cd", size = 393688, upload-time = "2026-05-19T10:07:25.854Z" }, + { url = "https://files.pythonhosted.org/packages/54/9d/8eb5d4fb8bf7e93a75964a5da71a75c67c864baf7fa3f98598187b3c7e57/jiter-0.15.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:ae1b0d82ac2d987f9ea512b1c9adfcc71a28de3dea3a6039b54d76cffda9901e", size = 520853, upload-time = "2026-05-19T10:07:27.303Z" }, + { url = "https://files.pythonhosted.org/packages/e7/2c/5e07874e59e623a943a0acf1552a80d05b70f31b402287a8fc6d7ec634c7/jiter-0.15.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:8020c99ec13a7db2b6f96cbe82ef4721c88b426a4892f27478044af0284615ef", size = 551016, upload-time = "2026-05-19T10:07:28.846Z" }, + { url = "https://files.pythonhosted.org/packages/22/ed/d2d34422143474cadc15b60d482b1c35683dbc5c63c24346ddd0df09bcaf/jiter-0.15.0-cp311-cp311-win32.whl", hash = "sha256:42bfb257930800cf43e7c62c832402c704ab60797c992faf88d20e903eac8f32", size = 209518, upload-time = "2026-05-19T10:07:30.431Z" }, + { url = "https://files.pythonhosted.org/packages/1d/7d/52778b930e5cc3e52a37d950b1c10494244308b4329b25a0ff0d88303a81/jiter-0.15.0-cp311-cp311-win_amd64.whl", hash = "sha256:860a74063284a2ae9bfedd694f299cc2c68e2696c5f3d440cc9d18bb81b9dd04", size = 200565, upload-time = "2026-05-19T10:07:32.125Z" }, + { url = "https://files.pythonhosted.org/packages/3b/4f/d9b4067feb69b3fa6eb0488e1b59e2ad5b463fe39f59e527eab2aca00bb0/jiter-0.15.0-cp311-cp311-win_arm64.whl", hash = "sha256:37a10c377ce3a4a85f4a67f28b7afe093154cde77eaf248a72e856aa08b4d865", size = 195488, upload-time = "2026-05-19T10:07:33.846Z" }, + { url = "https://files.pythonhosted.org/packages/44/53/4f6bddbcde3c71e56d0aa1337ec95950f3d27dd4153e25aadf0feac71751/jiter-0.15.0-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:0e90a1c315a0226ec822d973817967f9223b7701546c8c2a7913e7ab0926294d", size = 308793, upload-time = "2026-05-19T10:07:35.25Z" }, + { url = "https://files.pythonhosted.org/packages/01/84/c01099b59a285a1ebba64ae93f62bfa036675340fd1b0045ae65890a0442/jiter-0.15.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8c9004af7c8d67cce7f1aae1026fb55607f4aa600710d08ede3a3ce4aeefe7e0", size = 309570, upload-time = "2026-05-19T10:07:36.919Z" }, + { url = "https://files.pythonhosted.org/packages/58/64/8fb7f9d45bb98190355454cd04dad8d8f27223d6bd52f83af07f637168a6/jiter-0.15.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c210f8b35dc6f30aafd4b4365ca89b9d1189f21ab49b8e68fa6322a847aef138", size = 336783, upload-time = "2026-05-19T10:07:38.694Z" }, + { url = "https://files.pythonhosted.org/packages/c3/b6/f5739011d009b3a30f6a53c5240979030ba29ae46a8c67e3a15759f7c37d/jiter-0.15.0-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5f30bae8bc1c2d613e28e5af3e8cceb09b742f1c8a8a5f839fb67afaffc03b61", size = 363555, upload-time = "2026-05-19T10:07:40.832Z" }, + { url = "https://files.pythonhosted.org/packages/e5/12/98a9d9f766665e8a3b6252454e17cb0c464606a28cf2fa09399b003345fa/jiter-0.15.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c60e71b6d10cfc284c9bf36bd885e8d44c46f688ce50aa91b5edd90181dea687", size = 452255, upload-time = "2026-05-19T10:07:42.62Z" }, + { url = "https://files.pythonhosted.org/packages/e8/d5/60f972840f79c5e7544fce567c56f1e4e50468f996baba3e78d823dd62a6/jiter-0.15.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0ab068bce62a45aa3e7367eceaffb5dde60b7eb853be8dece45132e3d0ff4879", size = 373559, upload-time = "2026-05-19T10:07:44.201Z" }, + { url = "https://files.pythonhosted.org/packages/ee/cf/d46ef1234ba335aabc2f013210db8e0821a22f5e644a2e9449df199ecc23/jiter-0.15.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fa248c9eb220197d363f688818dac2fd4b2f0cd7d843ca7105d652034823427d", size = 346055, upload-time = "2026-05-19T10:07:46.005Z" }, + { url = "https://files.pythonhosted.org/packages/f0/63/4d2749d8d54d230bad9b3a6b0d00cc28c6ff6b2fdffc26a8ccf76cc5a974/jiter-0.15.0-cp312-cp312-manylinux_2_31_riscv64.whl", hash = "sha256:2a77aadd57cac1682e4401a72724d2796d89a4ba129b1a5812aa94ee480826eb", size = 351406, upload-time = "2026-05-19T10:07:47.855Z" }, + { url = "https://files.pythonhosted.org/packages/d9/b9/9965b990035d8773328e0a8c8b457a87bf2b19f6c4126d9d99296be5d16a/jiter-0.15.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2ae901f3a55bfafdde31d289590fa25e3245735a2b1e8c7cc15871710a002871", size = 389357, upload-time = "2026-05-19T10:07:49.665Z" }, + { url = "https://files.pythonhosted.org/packages/2d/55/9ddf903deda1413e87fed792f416b7123daee5b8efbad6a202a7421c36a5/jiter-0.15.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:f0b271b462769543716f92d3a4f90527df6ef5ed05ee95ec4137f513e21e1b77", size = 517263, upload-time = "2026-05-19T10:07:51.537Z" }, + { url = "https://files.pythonhosted.org/packages/e8/76/a0c40ad064d3a20a4fde231e35d56e9a01ce82164278180e82d5daf85469/jiter-0.15.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:2fb6a5d26af81fc0f00f9360a891e05cf755e149bba391c4d563adc54812973d", size = 548646, upload-time = "2026-05-19T10:07:53.196Z" }, + { url = "https://files.pythonhosted.org/packages/23/4f/eca9b954942916ba2f453891b8593ab444cd872396fe66a3936616f236f3/jiter-0.15.0-cp312-cp312-win32.whl", hash = "sha256:c2f6bb8b5216ab9e7873bc08b5d7bef2b8abbb578a3069bf1cd14a45d71d771d", size = 206427, upload-time = "2026-05-19T10:07:55.307Z" }, + { url = "https://files.pythonhosted.org/packages/95/bf/8ead82a87495149542748e828d153fd232a512a22c83b02c4815c1a9c7d8/jiter-0.15.0-cp312-cp312-win_amd64.whl", hash = "sha256:40b2c7e92c44a84d748d21706c68dc6ff8161d80b59c99d774721a0d2317d7c7", size = 197300, upload-time = "2026-05-19T10:07:56.651Z" }, + { url = "https://files.pythonhosted.org/packages/f4/e4/9b8a78fb2d894471bc344e37f1949bdd784bd914d031dba0ba3a40c71dd7/jiter-0.15.0-cp312-cp312-win_arm64.whl", hash = "sha256:cc0bc345cf2df9d1c00ac443f50d543c1ccfa8b0422cb85b1ab70d681c0b255b", size = 192702, upload-time = "2026-05-19T10:07:58.307Z" }, + { url = "https://files.pythonhosted.org/packages/e5/f4/f708c900ecee41b2025ef8413d5351e5649eb2125c506f6720cc69b06f5c/jiter-0.15.0-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:1c11465f97e2abf45a014b83b730222f8f1c5335e802c7055a67d50de6f1f4e3", size = 307829, upload-time = "2026-05-19T10:07:59.704Z" }, + { url = "https://files.pythonhosted.org/packages/86/59/db537c0949e83668c38481d426b9f2fd5ab758c4ee53a811dd0a510626a0/jiter-0.15.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:d1e7b1776f0797956c509e123d0952d10d293a9492dea9f288ab9570ec01d1a5", size = 308445, upload-time = "2026-05-19T10:08:01.184Z" }, + { url = "https://files.pythonhosted.org/packages/37/38/ea0e13b18c30ef951da0d47d39e7fa9edb82a93a62990ffbd7cea9b622d4/jiter-0.15.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:351a341c2105aa430b7047e30f1bf7975f6313b00165d3fc07be2edaf741f279", size = 336181, upload-time = "2026-05-19T10:08:02.688Z" }, + { url = "https://files.pythonhosted.org/packages/58/fc/2303901b16c4ba05865588990a420c0b4156270b44379c20931544a1d962/jiter-0.15.0-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:4ab395feec8d249ec4044e228e98a7033f043426a265df439dc3698823f0a4e4", size = 362985, upload-time = "2026-05-19T10:08:04.394Z" }, + { url = "https://files.pythonhosted.org/packages/5b/6f/11bace093c52e7d4d26c8e606ccd7ae8c972189622469ec0d9e28161e28b/jiter-0.15.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a2a438005b6f22d0273413484d6094d7c2c5d10ec1b3a3bf128e0d1d3ba53258", size = 453292, upload-time = "2026-05-19T10:08:05.967Z" }, + { url = "https://files.pythonhosted.org/packages/22/db/987f2f086ca4d7a6582eb4ccd513f9b26b42d9e4243a087609a3137a8fc7/jiter-0.15.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f18f85e4218d1b40f000f42a92239a7a61a902cd42c65e6c360dbd17dcb20894", size = 373501, upload-time = "2026-05-19T10:08:07.857Z" }, + { url = "https://files.pythonhosted.org/packages/8f/7c/89fbcabb2739b7a5b8dc959a1b6c5761f6484f5fed3486854b3c789bb1de/jiter-0.15.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d1aa62e277fc1cbd80e6deacae6f4d983b41b3d7728e0645c5d741a6149bba45", size = 344683, upload-time = "2026-05-19T10:08:09.431Z" }, + { url = "https://files.pythonhosted.org/packages/30/6f/6cca7692e7dddfec6d8d76c54dc97f2af2a41df4ac0674b999df1f09a5f3/jiter-0.15.0-cp313-cp313-manylinux_2_31_riscv64.whl", hash = "sha256:6550fa135c7deb8ead6af49ed7ff648532ea8334a1447fe34a36315ef79c5c29", size = 350892, upload-time = "2026-05-19T10:08:11.352Z" }, + { url = "https://files.pythonhosted.org/packages/39/14/0338d6190cb8e6d22e677ab1d4eabd4117f67cca70c54cd04b82ff64e068/jiter-0.15.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:066f8f33f18b2419cd8213b2436fa7fbc9c499f315971cfa3ce1f9820c001b1b", size = 388723, upload-time = "2026-05-19T10:08:12.912Z" }, + { url = "https://files.pythonhosted.org/packages/90/31/cc19f4a1bdb6afb09ce6a2f2615aa8d44d994eba0d8e6105ed1af920e736/jiter-0.15.0-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:75e8a04e91432dde9f1838373cf93d23726c79d3e908d319acf0e796f85592e7", size = 516648, upload-time = "2026-05-19T10:08:14.808Z" }, + { url = "https://files.pythonhosted.org/packages/49/9f/833c541512cd091b63c10c0381973dfe11bc7a503a818c16384417e0c81e/jiter-0.15.0-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:a97261f1fccb8e50ecd2890a96e46efdc3f57c80a197324c6777827231eca712", size = 547382, upload-time = "2026-05-19T10:08:16.927Z" }, + { url = "https://files.pythonhosted.org/packages/d2/11/e7b70e91f90bc4477e8eee9e8a5f7cf3cb41b4525d6394dc98a714eb8f7f/jiter-0.15.0-cp313-cp313-win32.whl", hash = "sha256:c77496cb10bd7549690fbbab3e5ec05857b83e49276f4a9423a766ddd2afcd4c", size = 205845, upload-time = "2026-05-19T10:08:18.401Z" }, + { url = "https://files.pythonhosted.org/packages/4b/23/5c20d9ad6f02c493e4023e5d2d09e1c1f15fe2753c9102c544aff068a88e/jiter-0.15.0-cp313-cp313-win_amd64.whl", hash = "sha256:b15741f501469009ae0ae90b7147958a664a7dede40aa7ff174a8a4645f546d0", size = 196842, upload-time = "2026-05-19T10:08:20.131Z" }, + { url = "https://files.pythonhosted.org/packages/6b/11/1eb400ef248e8c925fd883fbe325daf5e42cd1b0d308539dd332bd4f7ffc/jiter-0.15.0-cp313-cp313-win_arm64.whl", hash = "sha256:5d6a60072b44c3c2b797a7ddcbcbbf2b34ea3cfd4721580fbfd2a09d9d9b84ba", size = 192212, upload-time = "2026-05-19T10:08:21.807Z" }, + { url = "https://files.pythonhosted.org/packages/8a/60/2fd8d7c79da8acf9b7b277c7616847773779356b92acfc9bb158452174da/jiter-0.15.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:ef1fd24d9413f6209e00d3d5a453e67acfe004a25cc6c8e8484faed4311ab9e8", size = 315065, upload-time = "2026-05-19T10:08:23.218Z" }, + { url = "https://files.pythonhosted.org/packages/46/f4/008fb7d65e8ac2abf00811651a661e025c4ba80bbc6f378450384ddd3aed/jiter-0.15.0-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:144f8e72cb53dab146347b91cceac01f5481237f2b93b4a339a1ee8f8878b67c", size = 339444, upload-time = "2026-05-19T10:08:24.701Z" }, + { url = "https://files.pythonhosted.org/packages/00/55/90b0c7b9c6896c0f2a591dd36d36b71d22e09674bfef178fa03ba3f81499/jiter-0.15.0-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:553fcac2ef2cb990877f9fc0833b8b629a3e6a5670b6b5fd58219b41a653ddc4", size = 347779, upload-time = "2026-05-19T10:08:26.408Z" }, + { url = "https://files.pythonhosted.org/packages/51/6b/69666cec5000fd57734c118437394516c749ae8dbeea9fb66d6fef9c4775/jiter-0.15.0-cp313-cp313t-win_amd64.whl", hash = "sha256:774f93f65031856bf14ad9f59bdcab8b8cad501e5ceabd51ba3525f76937a25b", size = 200395, upload-time = "2026-05-19T10:08:28.055Z" }, + { url = "https://files.pythonhosted.org/packages/39/04/a6aa62cd27e8149b0d28df5561f10f6cceaf7935a9ccf3f1c5a05f9a0cd8/jiter-0.15.0-cp313-cp313t-win_arm64.whl", hash = "sha256:f1e1754960f38ec40613a07e5e372df67acb3b890fb383b6fb3de3e49ddbf3c7", size = 190516, upload-time = "2026-05-19T10:08:29.35Z" }, + { url = "https://files.pythonhosted.org/packages/eb/d2/079f350ebf7859d081de30aa890f9e3be68516f754f3ba32366ffff4dcee/jiter-0.15.0-cp314-cp314-macosx_10_12_x86_64.whl", hash = "sha256:ac0d9ddea4350974be7a221fc25895f251a8fee748c889bdced2141c0fec1a49", size = 308884, upload-time = "2026-05-19T10:08:31.667Z" }, + { url = "https://files.pythonhosted.org/packages/04/4e/a2c30a7f69b48c03b20935d647479106fe932f6e63f75faf53937197e05d/jiter-0.15.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:01a8222cf05ab1128e239421156c207949808acaaea2bdfd33130ae666786e86", size = 310028, upload-time = "2026-05-19T10:08:33.304Z" }, + { url = "https://files.pythonhosted.org/packages/40/90/2e7cdfd3cf8ca967be38c48f5cf474d79f089efaf559a40f15984a77ae69/jiter-0.15.0-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:182226cbc930c9fab81bc2e41a4da672f89539906dadb05e75670ac07b94f71f", size = 337485, upload-time = "2026-05-19T10:08:35.259Z" }, + { url = "https://files.pythonhosted.org/packages/9b/11/15a1aa28b120b8ee5b4f1fb894c125046225f09847738bd64233d3b84883/jiter-0.15.0-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:71683c38c825452999b5717fcae07ea708e8c93003e808be4319c1b02e3d176e", size = 364223, upload-time = "2026-05-19T10:08:36.694Z" }, + { url = "https://files.pythonhosted.org/packages/b7/25/f442e8af5f3d0dcf47b39e83a0efd9ee45ea946aa6d04625dc3181eae3b6/jiter-0.15.0-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:30f2218e6a9e5c18bc10fe6d41ac189c442c88eacf11bad9f28ef95a9bef00e6", size = 456387, upload-time = "2026-05-19T10:08:38.143Z" }, + { url = "https://files.pythonhosted.org/packages/da/f4/37f2d2c9f64f49af7da652ed7532bb5a2372e588e6927c3fdd76f911db65/jiter-0.15.0-cp314-cp314-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5157de9f76eb4bc5ea74a1219366a25f945ad305641d74e04f59c54087091aa9", size = 374461, upload-time = "2026-05-19T10:08:39.869Z" }, + { url = "https://files.pythonhosted.org/packages/60/28/edcfbbbf0cb15436f36664a8908a0df47ab9006298d4cd937dc08ea932d6/jiter-0.15.0-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:90c5db5527c221249a876160663ab891ace358c17f7b9c93ec1478b7f0550e5c", size = 345924, upload-time = "2026-05-19T10:08:41.668Z" }, + { url = "https://files.pythonhosted.org/packages/47/13/89fba6398dab7f202b7278c4b4aac122399d2c0183971c4a57a3b7088df5/jiter-0.15.0-cp314-cp314-manylinux_2_31_riscv64.whl", hash = "sha256:3e4540b8e74e4268811ac05db226a6a128ff572e7e0ce3f1163b693cadb184cd", size = 352283, upload-time = "2026-05-19T10:08:43.091Z" }, + { url = "https://files.pythonhosted.org/packages/1b/da/0f6af8cef2c565a1ab44d970f268c43ccaa72707386ea6388e6fe2b6cd26/jiter-0.15.0-cp314-cp314-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:62ebd14e47e9aed9df4472afcb2663668ce4d74891cd54f86bf6e44029d6dc89", size = 389985, upload-time = "2026-05-19T10:08:44.915Z" }, + { url = "https://files.pythonhosted.org/packages/a1/ec/b9cb7d6d29e24ee14910266157d2a279d7a8f60ee0df7fa840882976ba64/jiter-0.15.0-cp314-cp314-musllinux_1_1_aarch64.whl", hash = "sha256:0be6f5ad41a809f303f416d17cec92a7a725902fb9b4f3de3d19362ac0ef8554", size = 517695, upload-time = "2026-05-19T10:08:46.486Z" }, + { url = "https://files.pythonhosted.org/packages/64/5e/6d1bda880723aae0ad86b4b763f044362448efe31e3e819635d41cb03451/jiter-0.15.0-cp314-cp314-musllinux_1_1_x86_64.whl", hash = "sha256:813dfbb17d65328bf86e5f0905dd277ba2265d3ca20556e86c0c7035b7182e5a", size = 548868, upload-time = "2026-05-19T10:08:48.026Z" }, + { url = "https://files.pythonhosted.org/packages/0c/72/7de501cf38dcacaf35098796f3a50e0f2e338baba18a58946c618544b809/jiter-0.15.0-cp314-cp314-win32.whl", hash = "sha256:50e51156192722a9c58db112837d3f8ef96fb3c5ecc14e95f409134b08b158ec", size = 206380, upload-time = "2026-05-19T10:08:49.738Z" }, + { url = "https://files.pythonhosted.org/packages/1e/a9/e19addf4b0c1bdce52c6da12351e6bc42c340c45e7c09e2158e46d293ccc/jiter-0.15.0-cp314-cp314-win_amd64.whl", hash = "sha256:30ce1a5d16b5641dc935d50ef775af6a0871e3d14ab05d6fc54dff371b78e558", size = 197687, upload-time = "2026-05-19T10:08:51.088Z" }, + { url = "https://files.pythonhosted.org/packages/f2/c9/776b1db01db25fc6c1d58d1979a37b0a9fe787e5f5b1d062d2eaacb77923/jiter-0.15.0-cp314-cp314-win_arm64.whl", hash = "sha256:510c8b3c17a0ed9ac69850c0438dada3c9b82d9c4d589fcb62002a5a9cf3a866", size = 192571, upload-time = "2026-05-19T10:08:52.451Z" }, + { url = "https://files.pythonhosted.org/packages/a0/f6/45bb4670bacf300fd2c7abadbfb3af376e5f1b6ae75fd9bc069891d15870/jiter-0.15.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:7553333dd0930c104a5a0db8df72bf7219fe663d731383b576bb6ed6351c984d", size = 317151, upload-time = "2026-05-19T10:08:53.867Z" }, + { url = "https://files.pythonhosted.org/packages/d7/68/ed635ad5acd7b73e454283083bbb7c8205ad10e88b0d9d7d793b09fe8226/jiter-0.15.0-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f2143ab06181d2b029eedcb6af3cebe95f11bbac62441781860f98ee9330a6a6", size = 341243, upload-time = "2026-05-19T10:08:55.383Z" }, + { url = "https://files.pythonhosted.org/packages/5d/db/3ff4176b817b8ea33879e71e13d8bc2b0d481a7ed3fe9e080f333d415c16/jiter-0.15.0-cp314-cp314t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:6eac374c5c975709b69c10f09afd199df74150172156ad10c8d4fd785b7da995", size = 363629, upload-time = "2026-05-19T10:08:56.928Z" }, + { url = "https://files.pythonhosted.org/packages/ab/24/5f8270e0ba9c883582f96f722f8a0b58015c7ce1f8c6d4571cf394e99b6b/jiter-0.15.0-cp314-cp314t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b3b3b775e33d3bfaec9899edc526ae97b0da0bf9d071a46124ba419149a414f8", size = 456198, upload-time = "2026-05-19T10:08:58.618Z" }, + { url = "https://files.pythonhosted.org/packages/45/5b/76fc02b0b5c54c3d18c60653156e2f76fde1816f9b4722db68d6ee2c897e/jiter-0.15.0-cp314-cp314t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:eda3071db3346334beae1360b46da4606da57bf3528c167b3c38533afaf9f2c5", size = 373710, upload-time = "2026-05-19T10:09:00.151Z" }, + { url = "https://files.pythonhosted.org/packages/c4/52/4310821b0ea9277994d3e1f49fc6a4b34e4800caebacb2c0af81da59a454/jiter-0.15.0-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c6694a173ecabc12eb60efbc0b474464ead1951ff65cd8b1e72100715c64512b", size = 349901, upload-time = "2026-05-19T10:09:01.621Z" }, + { url = "https://files.pythonhosted.org/packages/93/fe/67648c35b3594fba8854ac64cc8a826d8bcd18324bbdb53d77697c60b6ef/jiter-0.15.0-cp314-cp314t-manylinux_2_31_riscv64.whl", hash = "sha256:a254e10b593624d230c365b6d616b22ca0ad65e63a16e6631c2b3466022e6ba8", size = 352438, upload-time = "2026-05-19T10:09:03.216Z" }, + { url = "https://files.pythonhosted.org/packages/cb/28/0a1879d07ad6b3e025a2750027363452ced93c2d16d1c9d4b153ffd51c91/jiter-0.15.0-cp314-cp314t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d8d2955167274e15d79a7a020afdd9b39c990eb80b2d89fca695d92dcfdd38ec", size = 388152, upload-time = "2026-05-19T10:09:04.741Z" }, + { url = "https://files.pythonhosted.org/packages/c1/78/46c6f6b56ba85c90021f4afd72ed42f691f8f84daacb5fe27277070e3858/jiter-0.15.0-cp314-cp314t-musllinux_1_1_aarch64.whl", hash = "sha256:acf4ee4d1fc55917239fe72972fb292dd773055d05eb040d36f4326e02cc2c0e", size = 517707, upload-time = "2026-05-19T10:09:06.231Z" }, + { url = "https://files.pythonhosted.org/packages/ca/cb/720662d4c88fcad606e826fef5424365527ba43ce4868a479aed8f8c507e/jiter-0.15.0-cp314-cp314t-musllinux_1_1_x86_64.whl", hash = "sha256:e7196e56f1cd69af1dbb07dff02dcfb260a50b45a82d409d92a06fedb32473b5", size = 548241, upload-time = "2026-05-19T10:09:08.093Z" }, + { url = "https://files.pythonhosted.org/packages/60/e3/935b8034fd143f21125c87d51404a9e0e1449186a494405721ff5d1d695e/jiter-0.15.0-cp314-cp314t-win32.whl", hash = "sha256:7f6163c0f10b055245f814dcc59f4818da60dfe72f3e72ab89fc24b6bd5e9c52", size = 207950, upload-time = "2026-05-19T10:09:09.616Z" }, + { url = "https://files.pythonhosted.org/packages/93/59/984fd9ece895953dad3e0880a650e766f5a2da2c5514f0eafdaaabbeb5f9/jiter-0.15.0-cp314-cp314t-win_amd64.whl", hash = "sha256:980c256edb05b78a111b99c4de3b1d32e31634b867fd1fc2cf726e7b7bba9854", size = 200055, upload-time = "2026-05-19T10:09:11.367Z" }, + { url = "https://files.pythonhosted.org/packages/0e/a4/cf8d779feb133a27a2e3bc833bccb9e13aa332cdf820497ebf72c10ce8c3/jiter-0.15.0-cp314-cp314t-win_arm64.whl", hash = "sha256:66b1880df2d01e206e8339769d1c7c1753bcb653efd6289e203f6f24ebada0c0", size = 191244, upload-time = "2026-05-19T10:09:12.74Z" }, + { url = "https://files.pythonhosted.org/packages/65/43/1fc62172aa98b50a7de9a25554060db510f85c89cfbed0dfe13e1907a139/jiter-0.15.0-graalpy311-graalpy242_311_native-macosx_10_12_x86_64.whl", hash = "sha256:411fa4dfa5a7ae3d11491027ffb9beadec3996010a986862db70d91abba1c750", size = 305585, upload-time = "2026-05-19T10:09:35.995Z" }, + { url = "https://files.pythonhosted.org/packages/e8/c4/dd58fcd9e2df83666e5c1c1347bef58ce919cd8efc3ffa38aeea62ce493b/jiter-0.15.0-graalpy311-graalpy242_311_native-macosx_11_0_arm64.whl", hash = "sha256:2b0074e2f56eb2dacca1689760fd2852a068f85a0547a157b82cb4cafeb6768b", size = 306936, upload-time = "2026-05-19T10:09:37.435Z" }, + { url = "https://files.pythonhosted.org/packages/39/86/b695e16f1180c07f43ea98e73ecd21cf63fa2e1b0c1103739013784d11ae/jiter-0.15.0-graalpy311-graalpy242_311_native-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:913d02d29c9606643418d9ccfc3b72492ab25a6bf7889934e09a3490f8d3438b", size = 342453, upload-time = "2026-05-19T10:09:39.294Z" }, + { url = "https://files.pythonhosted.org/packages/34/56/55d76614af37fe3f22a3347d1e410d2a15da581997cb2da499a625000bb5/jiter-0.15.0-graalpy311-graalpy242_311_native-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b15d3ec9b0449c40e85319bdb4caa8b77ab526e74f5532ed94bec15e2f66822c", size = 345606, upload-time = "2026-05-19T10:09:40.727Z" }, + { url = "https://files.pythonhosted.org/packages/73/38/505941b2b092fd5bbbd60a52a880db1173f1690ae6751bed3af1c9ddcb4e/jiter-0.15.0-graalpy312-graalpy250_312_native-macosx_10_12_x86_64.whl", hash = "sha256:631f13a3d04e97d4e083993b10f4b99530e3a10d953e2eb5e196b7dc7f812ce0", size = 303769, upload-time = "2026-05-19T10:09:42.203Z" }, + { url = "https://files.pythonhosted.org/packages/e7/95/a06692b29e77473f286e1ec1f426d3ca44d7b5843be8ad21d7a5f3fcdcc0/jiter-0.15.0-graalpy312-graalpy250_312_native-macosx_11_0_arm64.whl", hash = "sha256:b6c0ffae686c39bf3737be60793783267628783ea42545632c10b291105aee45", size = 305128, upload-time = "2026-05-19T10:09:43.657Z" }, + { url = "https://files.pythonhosted.org/packages/23/85/7270d7ad41d6061a25b950c6bf91d638bd9aacb113200a8c8d57a055fd67/jiter-0.15.0-graalpy312-graalpy250_312_native-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1d54fb5b31dea401a41af3f8a7d2512e9b6a6a005491e6166c7e4ffab9639a9c", size = 340459, upload-time = "2026-05-19T10:09:45.452Z" }, + { url = "https://files.pythonhosted.org/packages/c8/8d/302cb2057b7513327b4d575cff6b1d066ee6431a5357fc3f8867cd684406/jiter-0.15.0-graalpy312-graalpy250_312_native-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:54d5d6090cdc1b7c9e780dfb04949a990adb1e301a2fc0bbcee7de4638d33f9a", size = 344469, upload-time = "2026-05-19T10:09:46.864Z" }, ] [[package]] @@ -2417,14 +2453,14 @@ wheels = [ [[package]] name = "joserfc" -version = "1.6.4" +version = "1.7.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "cryptography" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/de/c6/de8fdbdfa75c8ca04fead38a82d573df8a82906e984c349d58665f459558/joserfc-1.6.4.tar.gz", hash = "sha256:34ce5f499bfcc5e9ad4cc75077f9278ab3227b71da9aaf28f9ab705f8a560d3c", size = 231866, upload-time = "2026-04-13T13:15:40.632Z" } +sdist = { url = "https://files.pythonhosted.org/packages/44/90/25cb27518750218e4f850be63d8bbb2343efaad1c01c3571aaa4b3c33bd7/joserfc-1.7.1.tar.gz", hash = "sha256:77d0b76514879c68c6f433bc5b7357a4ab72008ff1e33d8379fd11d72bd8ca81", size = 233181, upload-time = "2026-06-08T07:21:33.412Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/b6/f7/210b27752e972edb36d239315b08d3eb6b14824cc4a590da2337d195260b/joserfc-1.6.4-py3-none-any.whl", hash = "sha256:3e4a22b509b41908989237a045e25c8308d5fd47ab96bdae2dd8057c6451003a", size = 70464, upload-time = "2026-04-13T13:15:39.259Z" }, + { url = "https://files.pythonhosted.org/packages/b3/00/fa62404c3e347f946faa13aa21085205f9cc06ad17671e37f81a51662ae8/joserfc-1.7.1-py3-none-any.whl", hash = "sha256:b3e3d655612e2e1ef67b2600f2f420e12e537b020208fab1761fad647319c164", size = 70423, upload-time = "2026-06-08T07:21:32.001Z" }, ] [[package]] @@ -2465,7 +2501,8 @@ dependencies = [ { name = "attrs" }, { name = "jsonschema-specifications" }, { name = "referencing" }, - { name = "rpds-py" }, + { name = "rpds-py", version = "0.30.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.11'" }, + { name = "rpds-py", version = "2026.5.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/b3/fc/e067678238fa451312d4c62bf6e6cf5ec56375422aee02f9cb5f909b3047/jsonschema-4.26.0.tar.gz", hash = "sha256:0c26707e2efad8aa1bfc5b7ce170f3fccc2e4918ff85989ba9ffa9facb2be326", size = 366583, upload-time = "2026-01-07T13:41:07.246Z" } wheels = [ @@ -2519,10 +2556,11 @@ wheels = [ [[package]] name = "langchain-core" -version = "1.3.0" +version = "1.4.7" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "jsonpatch" }, + { name = "langchain-protocol" }, { name = "langsmith" }, { name = "packaging" }, { name = "pydantic" }, @@ -2531,14 +2569,26 @@ dependencies = [ { name = "typing-extensions" }, { name = "uuid-utils" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/92/fe/20190232d9b513242899dbb0c2bb77e31b4d61e343743adbe90ebc2603d2/langchain_core-1.3.0.tar.gz", hash = "sha256:14a39f528bf459aa3aa40d0a7f7f1bae7520d435ef991ae14a4ceb74d8c49046", size = 860755, upload-time = "2026-04-17T14:51:38.298Z" } +sdist = { url = "https://files.pythonhosted.org/packages/ee/2b/fffaff399d20a56d40b9562fa19701e91abd72d8c9d9bc8c2673077b56b6/langchain_core-1.4.7.tar.gz", hash = "sha256:7a825d77de0a3f39adbd9d09612a75e85527e14a52c1601089bcc062972d9f2b", size = 952522, upload-time = "2026-06-12T19:23:57.588Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/f8/e2/dbfa347aa072a6dc4cd38d6f9ebfc730b4c14c258c47f480f4c5c546f177/langchain_core-1.3.0-py3-none-any.whl", hash = "sha256:baf16ee028475df177b9ab8869a751c79406d64a6f12125b93802991b566cced", size = 515140, upload-time = "2026-04-17T14:51:36.274Z" }, + { url = "https://files.pythonhosted.org/packages/de/3e/dcdffa60078ae7b3a00ebb4cbbf1a204a14c3609983c604886523a7d4418/langchain_core-1.4.7-py3-none-any.whl", hash = "sha256:bcadd51951140ecdcba98311dbd931ba5de02a5ba8a2288dad5069c1eea2a13d", size = 554941, upload-time = "2026-06-12T19:23:55.826Z" }, +] + +[[package]] +name = "langchain-protocol" +version = "0.0.17" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/44/b3/4e2429876c7a35585618caa2b9f9089f7162a6b50562b614ad82ac11c17e/langchain_protocol-0.0.17.tar.gz", hash = "sha256:e7cbe58c205df4b4fd87dc6d5bb23f10e13b236d0e2e1b0b9d05bc2b648f3eea", size = 6026, upload-time = "2026-06-12T18:39:51.923Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/13/0a/a1bfe72c6ec856e99773bbd96c8086421e554b3693d0142b9ea009c6ac92/langchain_protocol-0.0.17-py3-none-any.whl", hash = "sha256:982a08fe152586ed10d4ff3d538c2e0b5766e5f307cdea325e10be3f2c17cae6", size = 7096, upload-time = "2026-06-12T18:39:50.973Z" }, ] [[package]] name = "langgraph" -version = "1.1.9" +version = "1.2.5" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "langchain-core" }, @@ -2548,53 +2598,56 @@ dependencies = [ { name = "pydantic" }, { name = "xxhash" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/8c/d5/9d9c65d5500a1ca7ea63d6d65aecfb248037018a74d7d4ef52e276bb4e4b/langgraph-1.1.9.tar.gz", hash = "sha256:bc5a49d5a5e71fda1f9c53c06c62f4caec9a95545b739d130a58b6ab3269e274", size = 560717, upload-time = "2026-04-21T13:43:06.809Z" } +sdist = { url = "https://files.pythonhosted.org/packages/77/9d/7c9ebd17b95569122e2d2e641f535cf086c870d66bb8e59be33cdba856b3/langgraph-1.2.5.tar.gz", hash = "sha256:09a3bdec6fdb3228623fc78b6f69a1400d383f66348d0b04d0efb692022cc6ef", size = 712532, upload-time = "2026-06-12T20:30:58.498Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/16/58/0380420e66619d12c992c1f8cfda0c7a04e8f0fe8a84752245b9e7b1cba7/langgraph-1.1.9-py3-none-any.whl", hash = "sha256:7db13ceecde4ea643df6c097dcc9e534895dcd9fcc6500eeff2f2cde0fab16b2", size = 173744, upload-time = "2026-04-21T13:43:05.513Z" }, + { url = "https://files.pythonhosted.org/packages/a2/03/187281cf61845c5a9c397ae6cd9cd73bb54b39435e5575a7b83c853e5b76/langgraph-1.2.5-py3-none-any.whl", hash = "sha256:9286bb5def82fc865959c14378fe473518dc097d586225f622f029637a2a4bb9", size = 246150, upload-time = "2026-06-12T20:30:57.018Z" }, ] [[package]] name = "langgraph-checkpoint" -version = "4.0.2" +version = "4.1.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "langchain-core" }, { name = "ormsgpack" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/2e/f2/cf8086e1f1a3358d9228805614e72602c281b18307f3fae64a5b854aad2d/langgraph_checkpoint-4.0.2.tar.gz", hash = "sha256:4f6f99cba8e272deabf81b2d8cdc96582af07a57a6ad591cdf216bb310497039", size = 160810, upload-time = "2026-04-15T21:03:00.062Z" } +sdist = { url = "https://files.pythonhosted.org/packages/83/47/886af6f886f0bff2273164a45f008694e48a96ff3cd25ff0228f2aa9480e/langgraph_checkpoint-4.1.1.tar.gz", hash = "sha256:6c2bdb530c91f91d7d9c1bd100925d0fc4f498d418c17f3587d1526279482a25", size = 184020, upload-time = "2026-05-22T16:57:38.503Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/b9/5a/6dba29dd89b0a46ae21c707da0f9d17e94f27d3e481ed15bc99d6bd20aa6/langgraph_checkpoint-4.0.2-py3-none-any.whl", hash = "sha256:59b0f29216128a629c58dd07c98aa004f82f51805d5573126ffb419b753ff253", size = 51000, upload-time = "2026-04-15T21:02:59.096Z" }, + { url = "https://files.pythonhosted.org/packages/bd/b4/71425e3e38be92611300b9cc5e46a5bf98ab23f5ea8a75b73d02a2f1413c/langgraph_checkpoint-4.1.1-py3-none-any.whl", hash = "sha256:25d29144b082827218e7bc3f1e9b0566a4bb007895cd6cc26f66a8428739f56e", size = 56212, upload-time = "2026-05-22T16:57:37.203Z" }, ] [[package]] name = "langgraph-prebuilt" -version = "1.0.10" +version = "1.1.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "langchain-core" }, { name = "langgraph-checkpoint" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/fe/c8/01471b1b5601f2e9c9a69c39fc9a2fb8611613ede0002e5a2b81c0acd850/langgraph_prebuilt-1.0.10.tar.gz", hash = "sha256:5a6fc513f8907074563b6218ff991c4ed9db19ac63101314919686e8029ddb07", size = 169769, upload-time = "2026-04-17T17:59:45.373Z" } +sdist = { url = "https://files.pythonhosted.org/packages/29/66/ed9b93f56bc17ef22d551892f0ac2b225a97fe0fcf23a511b857f70d590b/langgraph_prebuilt-1.1.0.tar.gz", hash = "sha256:3c579cf6eed2d17f9c157c2d0fcaddcd8688524e7022d3b22b37a3bf4589d528", size = 178833, upload-time = "2026-05-12T03:37:49.332Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/50/49/d073375beabdc6955df6cbe570ba7786836bd4c817ae998955d35037f2fd/langgraph_prebuilt-1.0.10-py3-none-any.whl", hash = "sha256:e3baa1977d819982e690a357ba5bb77ccc1d4d8d4a029c48e502a3b6d171185f", size = 36086, upload-time = "2026-04-17T17:59:44.395Z" }, + { url = "https://files.pythonhosted.org/packages/e9/43/3fe1a700b8490ed02679cdbbc8c915eb23a092faf496c9c1118abcd10be3/langgraph_prebuilt-1.1.0-py3-none-any.whl", hash = "sha256:51e311747d755b751d5c6b39b0c1446124d3a7643d2515017e6714b323508fc9", size = 41043, upload-time = "2026-05-12T03:37:48.007Z" }, ] [[package]] name = "langgraph-sdk" -version = "0.3.13" +version = "0.4.2" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "httpx" }, + { name = "langchain-core" }, + { name = "langchain-protocol" }, { name = "orjson" }, + { name = "websockets" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/0e/db/77a45127dddcfea5e4256ba916182903e4c31dc4cfca305b8c386f0a9e53/langgraph_sdk-0.3.13.tar.gz", hash = "sha256:419ca5663eec3cec192ad194ac0647c0c826866b446073eb40f384f950986cd5", size = 196360, upload-time = "2026-04-07T20:34:18.766Z" } +sdist = { url = "https://files.pythonhosted.org/packages/b4/2b/bd8ac26d4e97f6df88ef05ce5b6a38945a3903e1025d926f4752aa88aa97/langgraph_sdk-0.4.2.tar.gz", hash = "sha256:b88f0f5f6328ac0680d6790614a905b2bcfa257f2276dba4e38f0e86db0aa738", size = 348327, upload-time = "2026-06-01T17:51:19.856Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/fe/ef/64d64e9f8eea47ce7b939aa6da6863b674c8d418647813c20111645fcc62/langgraph_sdk-0.3.13-py3-none-any.whl", hash = "sha256:aee09e345c90775f6de9d6f4c7b847cfc652e49055c27a2aed0d981af2af3bd0", size = 96668, upload-time = "2026-04-07T20:34:17.866Z" }, + { url = "https://files.pythonhosted.org/packages/a0/05/aac507337cceae773c2cc9ab91eb6301963af7aeeb55b4217a00e15aff17/langgraph_sdk-0.4.2-py3-none-any.whl", hash = "sha256:75fa5096c1177ce39c847096a8fe3745ffd480ddb412995f836e9f5f884c43dd", size = 160521, upload-time = "2026-06-01T17:51:18.849Z" }, ] [[package]] name = "langsmith" -version = "0.8.4" +version = "0.8.16" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "httpx" }, @@ -2604,12 +2657,13 @@ dependencies = [ { name = "requests" }, { name = "requests-toolbelt" }, { name = "uuid-utils" }, + { name = "websockets" }, { name = "xxhash" }, { name = "zstandard" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/d4/e9/4ceeba766bae47de1a6ecdaa4024d10eff63eed936796b77005742399e8d/langsmith-0.8.4.tar.gz", hash = "sha256:989b387f6ff92ec5f9d14c0edb333e2579590cad5a1ca07042d924b0ec43cd10", size = 4460243, upload-time = "2026-05-13T21:00:59.338Z" } +sdist = { url = "https://files.pythonhosted.org/packages/6f/19/1ed2af9c6d5d7a148e6b3e809b0af8ce8848e1f66a0726c8223d30e5292b/langsmith-0.8.16.tar.gz", hash = "sha256:8c943f0c9185fe2a9637b5b442828b7efd823b1de28d50d14c136c79660f909b", size = 4513275, upload-time = "2026-06-15T17:41:24.413Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/db/94/8b872959ea529ecfbbe2c3f91d9ebf98cb8dbd9e3f7487bc134740d3d235/langsmith-0.8.4-py3-none-any.whl", hash = "sha256:4e334ab223d10129c9943c461d95fa9089523638ea29cd048045a7f99b973f50", size = 398701, upload-time = "2026-05-13T21:00:57.393Z" }, + { url = "https://files.pythonhosted.org/packages/c3/13/8186a9867c67f3fef9958a1d60b45f46c1a9b5d28f67d8fd136f28ceab3f/langsmith-0.8.16-py3-none-any.whl", hash = "sha256:081e57c0175d142192683288740a796eb0eb32d9e703b4bf9133678ceefe3286", size = 500303, upload-time = "2026-06-15T17:41:22.33Z" }, ] [[package]] @@ -2659,7 +2713,7 @@ wheels = [ [[package]] name = "litellm" -version = "1.85.0" +version = "1.89.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "aiohttp" }, @@ -2675,9 +2729,9 @@ dependencies = [ { name = "tiktoken" }, { name = "tokenizers" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/3b/d5/3c9b560db2ffa9e498655d0dfd74f408bc5b32ede858b5731c2a5fa4c752/litellm-1.85.0.tar.gz", hash = "sha256:babdd569809af913d08a08a7eb55df1ed3e6a3960ee365c6cef4ad031c9bc72a", size = 15344387, upload-time = "2026-05-17T01:59:15.97Z" } +sdist = { url = "https://files.pythonhosted.org/packages/86/4b/15d4cb75f054933c1f19bcfd5683e139cdf792099b995ae55916b26094dc/litellm-1.89.0.tar.gz", hash = "sha256:eb1910a23497044b4375a0500c65f4c60d291a575d7b679c7566a5df9b9a5fcb", size = 14062606, upload-time = "2026-06-13T23:45:53.723Z" } 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" }, + { url = "https://files.pythonhosted.org/packages/eb/86/49cf94af8c51cacc15fd9bff1e6f9de1fb07ab10b8bb09961675ab389af4/litellm-1.89.0-py3-none-any.whl", hash = "sha256:63b33e2de386ab2a83fed7ed852c755e59d461a21b16c79fc17993f1b8c3d154", size = 15475805, upload-time = "2026-06-13T23:45:46.037Z" }, ] [[package]] @@ -2691,26 +2745,26 @@ wheels = [ [[package]] name = "mako" -version = "1.3.11" +version = "1.3.12" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "markupsafe" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/59/8a/805404d0c0b9f3d7a326475ca008db57aea9c5c9f2e1e39ed0faa335571c/mako-1.3.11.tar.gz", hash = "sha256:071eb4ab4c5010443152255d77db7faa6ce5916f35226eb02dc34479b6858069", size = 399811, upload-time = "2026-04-14T20:19:51.493Z" } +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/68/a5/19d7aaa7e433713ffe881df33705925a196afb9532efc8475d26593921a6/mako-1.3.11-py3-none-any.whl", hash = "sha256:e372c6e333cf004aa736a15f425087ec977e1fcbd2966aae7f17c8dc1da27a77", size = 78503, upload-time = "2026-04-14T20:19:53.233Z" }, + { 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.0.0" +version = "4.2.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "mdurl" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/5b/f5/4ec618ed16cc4f8fb3b701563655a69816155e79e24a17b651541804721d/markdown_it_py-4.0.0.tar.gz", hash = "sha256:cb0a2b4aa34f932c007117b194e945bd74e0ec24133ceb5bac59009cda1cb9f3", size = 73070, upload-time = "2025-08-11T12:57:52.854Z" } +sdist = { url = "https://files.pythonhosted.org/packages/06/ff/7841249c247aa650a76b9ee4bbaeae59370dc8bfd2f6c01f3630c35eb134/markdown_it_py-4.2.0.tar.gz", hash = "sha256:04a21681d6fbb623de53f6f364d352309d4094dd4194040a10fd51833e418d49", size = 82454, upload-time = "2026-05-07T12:08:28.36Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/94/54/e7d793b573f298e1c9013b8c4dade17d481164aa517d1d7148619c2cedbf/markdown_it_py-4.0.0-py3-none-any.whl", hash = "sha256:87327c59b172c5011896038353a81343b6754500a08cd7a4973bb48c6d578147", size = 87321, upload-time = "2025-08-11T12:57:51.923Z" }, + { url = "https://files.pythonhosted.org/packages/b3/81/4da04ced5a082363ecfa159c010d200ecbd959ae410c10c0264a38cac0f5/markdown_it_py-4.2.0-py3-none-any.whl", hash = "sha256:9f7ebbcd14fe59494226453aed97c1070d83f8d24b6fc3a3bcf9a38092641c4a", size = 91687, upload-time = "2026-05-07T12:08:27.182Z" }, ] [[package]] @@ -2813,31 +2867,31 @@ wheels = [ [[package]] name = "maturin" -version = "1.13.1" +version = "1.14.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "tomli", marker = "python_full_version < '3.11'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/39/16/b284a7bc4af3dd87717c784278c1b8cb18606ad1f6f7a671c47bfd9c3df0/maturin-1.13.1.tar.gz", hash = "sha256:9a87ff3b8e4d1c6eac33ebfe8e261e8236516d98d45c0323550621819b5a1a2f", size = 340369, upload-time = "2026-04-09T15:14:07.026Z" } +sdist = { url = "https://files.pythonhosted.org/packages/a7/d0/b7c8b7778cc44df3efbc96eb23acaa995e06ea1a60eb9b02f29858fcbd08/maturin-1.14.0.tar.gz", hash = "sha256:f7f82a6aca4a6c402bf00b99200be199d4874d04b9b9e74e825726a3478bba7f", size = 367010, upload-time = "2026-06-12T00:13:30.811Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/43/4d/a23fc95be881aa8c7a6ea353410417872e4d7065df03d7f3db8f0dbed4a7/maturin-1.13.1-py3-none-linux_armv6l.whl", hash = "sha256:416e4e01cb88b798e606ee43929df897e42c1647b722ef68283816cca99a8742", size = 10102444, upload-time = "2026-04-09T15:13:48.393Z" }, - { url = "https://files.pythonhosted.org/packages/a6/1e/65c385d65bae95cf04895d52f39dbed8b1453ae55da2903d252ade40a774/maturin-1.13.1-py3-none-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:72888e87819ce546d0d2df900e4b385e4ef299077d92ee37b48923a5602dae94", size = 19576043, upload-time = "2026-04-09T15:14:08.685Z" }, - { url = "https://files.pythonhosted.org/packages/8f/13/f6bc868d0bfecd9314870b97f530a167e31f7878ac4945c78245c6eef69c/maturin-1.13.1-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:98b5fcf1a186c217830a8295ecc2989c6b1cf50945417adfc15252107b9475b7", size = 10117339, upload-time = "2026-04-09T15:13:40.559Z" }, - { url = "https://files.pythonhosted.org/packages/51/58/279e081305c11c1c1c4fccacf77df8959646c5d4de7a57ec7e787653e270/maturin-1.13.1-py3-none-manylinux_2_12_i686.manylinux2010_i686.musllinux_1_1_i686.whl", hash = "sha256:3da18cccf2f683c0977bff9146a0908d6ffce836d600665736ac01679f588cb9", size = 10139689, upload-time = "2026-04-09T15:13:38.291Z" }, - { url = "https://files.pythonhosted.org/packages/00/94/69391af5396c6aab723932240803f49e5f3de3dd7c57d32f02d237a0ce32/maturin-1.13.1-py3-none-manylinux_2_12_x86_64.manylinux2010_x86_64.musllinux_1_1_x86_64.whl", hash = "sha256:6b1e5916a253243e8f5f9e847b62bbc98420eec48c9ce2e2e8724c6da89d359b", size = 10551141, upload-time = "2026-04-09T15:13:42.887Z" }, - { url = "https://files.pythonhosted.org/packages/9e/bf/4edac2667b49e3733438062ae416413b8fc8d42e1bd499ba15e1fb02fc55/maturin-1.13.1-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.musllinux_1_1_aarch64.whl", hash = "sha256:dc91031e0619c1e28730279ef9ee5f106c9b9ec806b013f888676b242f892eb7", size = 9983094, upload-time = "2026-04-09T15:13:56.868Z" }, - { url = "https://files.pythonhosted.org/packages/79/94/a6d651cfe8fc6bf2e892c90e3cdbb25c06d81c9115140d03ea1a68a97575/maturin-1.13.1-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.musllinux_1_1_armv7l.whl", hash = "sha256:001741c6cff56aa8ea59a0d78ae990c0550d0e3e82b00b683eedb4158a8ef7e6", size = 9949980, upload-time = "2026-04-09T15:13:59.185Z" }, - { url = "https://files.pythonhosted.org/packages/b5/d1/82c067464f848e38af9910bce55eb54302b1c1284a279d515dbfcf5994f5/maturin-1.13.1-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.musllinux_1_1_ppc64le.whl", hash = "sha256:01c845825c917c07c1d0b2c9032c59c16a7d383d1e649a46481d3e5693c2750f", size = 13186276, upload-time = "2026-04-09T15:13:45.725Z" }, - { url = "https://files.pythonhosted.org/packages/7c/f4/25367baf1025580f047f9b37598bb3fadc416e24536afd4f28e190335c73/maturin-1.13.1-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f69093ed4a0e6464e52a7fc26d714f859ce15630ec8070743398c6bf41f38a9e", size = 10891837, upload-time = "2026-04-09T15:13:35.68Z" }, - { url = "https://files.pythonhosted.org/packages/af/be/caafad8ce74974b7deafdf144d12f758993dfea4c66c9905b138f51a7792/maturin-1.13.1-py3-none-manylinux_2_31_riscv64.musllinux_1_1_riscv64.whl", hash = "sha256:c1490584f3c70af45466ee99065b49e6657ebdccac6b10571bb44681309c9396", size = 10351032, upload-time = "2026-04-09T15:14:01.632Z" }, - { url = "https://files.pythonhosted.org/packages/66/0e/970a721d27cfa410e8bfa0a1e32e6ef52cb8169692110a5fdabe1af3f570/maturin-1.13.1-py3-none-win32.whl", hash = "sha256:c6a720b252c99de072922dbe4432ab19662b6f80045b0355fec23bdfccb450da", size = 8855465, upload-time = "2026-04-09T15:13:51.122Z" }, - { url = "https://files.pythonhosted.org/packages/88/70/7c1e0d65fa147d5479055a171541c82b8cdfc1c825d85a82240470f14176/maturin-1.13.1-py3-none-win_amd64.whl", hash = "sha256:a2017d2281203d0c6570240e7d746564d766d756105823b7de68bda6ae722711", size = 10230471, upload-time = "2026-04-09T15:13:53.89Z" }, - { url = "https://files.pythonhosted.org/packages/c5/2a/afe0193b673a79ffd2e01ad999511b7e9e6b49af02bb3759d82a78c3043d/maturin-1.13.1-py3-none-win_arm64.whl", hash = "sha256:2839024dcd65776abb4759e5bca29941971e095574162a4d335191da4be9ff24", size = 8905575, upload-time = "2026-04-09T15:14:03.891Z" }, + { url = "https://files.pythonhosted.org/packages/88/51/49367dcd8f6ec139e69ef0c695c8ff5075223673382101812b4affa53216/maturin-1.14.0-py3-none-linux_armv6l.whl", hash = "sha256:019ea3ec7e71f4c9759a367d4d21022ed5a3a621a2ce123abf3fb114ab3711ca", size = 10204135, upload-time = "2026-06-12T00:13:34.308Z" }, + { url = "https://files.pythonhosted.org/packages/dd/2a/487ce56c838d25e0ce64350e75ec4e3dc89544c0a6233221c229d6aa1a84/maturin-1.14.0-py3-none-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:6948a10f5f3470b791f79319be51debdd8bfd1778b36f2409f98e1314bc3859b", size = 19736800, upload-time = "2026-06-12T00:13:40.456Z" }, + { url = "https://files.pythonhosted.org/packages/a8/a5/12f2efc18f419edce3282a93629cba16278bb502135dac95cd04ef7c2eae/maturin-1.14.0-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:1506e86b1e273a98074a62e281b13f27ac96f8cdef85f7f98d3e3589a9387a23", size = 10201144, upload-time = "2026-06-12T00:13:26.842Z" }, + { url = "https://files.pythonhosted.org/packages/bf/95/3789e72273fd8bc80c33a11c787634b3251c4989d7a7203a92438836d4ff/maturin-1.14.0-py3-none-manylinux_2_12_i686.manylinux2010_i686.musllinux_1_1_i686.whl", hash = "sha256:df10ce4f7ba97fd3423f624f39b94c888ae3e5b470642a91918e1ccec81282fd", size = 10182394, upload-time = "2026-06-12T00:13:13.693Z" }, + { url = "https://files.pythonhosted.org/packages/40/79/15957eb4e055597f217e6310963a9c1371372e63c5b4a3e30803365addd2/maturin-1.14.0-py3-none-manylinux_2_12_x86_64.manylinux2010_x86_64.musllinux_1_1_x86_64.whl", hash = "sha256:75bcd4468a7fe597652cc2980c6bb16ce4bb8c411e3eb85dac2c4418cef0e95a", size = 10616603, upload-time = "2026-06-12T00:13:22.795Z" }, + { url = "https://files.pythonhosted.org/packages/3e/4b/d1822f88cd5e855640f0e10ee00c39b9be614c1ef2f827e9792332d94b9f/maturin-1.14.0-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.musllinux_1_1_aarch64.whl", hash = "sha256:2d123337e817f8dfe23755d6760139c01104137bb63e9e20c289c547e25ec857", size = 10075309, upload-time = "2026-06-12T00:13:38.274Z" }, + { url = "https://files.pythonhosted.org/packages/c0/82/c1b160d2163e8784489285e82a5c811fdcef3e0704e35b34c1cfe1828de3/maturin-1.14.0-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.musllinux_1_1_armv7l.whl", hash = "sha256:107f84110d890090a01bb1ecd01761fdfae925c23c659ba492c9b83dd179eab4", size = 10024058, upload-time = "2026-06-12T00:13:16.49Z" }, + { url = "https://files.pythonhosted.org/packages/0c/e8/88a9d1872997d4535af10ebe79f550e834880bf613cf8e50b50d2d938e3b/maturin-1.14.0-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.musllinux_1_1_ppc64le.whl", hash = "sha256:9a84277aa907961cd47ad26fef1539e79efa30611972eaf7499606e773e991b2", size = 13302073, upload-time = "2026-06-12T00:13:29.027Z" }, + { url = "https://files.pythonhosted.org/packages/4a/13/3f6d28bb7b744558b9bc78c995c1855d7e5ff21ad475f46d9de5c3dab039/maturin-1.14.0-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:095714b2a904927e3c868a1c5d078257ff0443c5049f7623777352966768306e", size = 10863616, upload-time = "2026-06-12T00:13:32.191Z" }, + { url = "https://files.pythonhosted.org/packages/24/06/39352d2b402efa3a7dd01d4ed197b301ea35eec10208ba2b8c649101f4df/maturin-1.14.0-py3-none-manylinux_2_31_riscv64.musllinux_1_1_riscv64.whl", hash = "sha256:20229d332f87166b930e4ca07cdbee8a1726f2eea87a337610aa25bba3ddf4b4", size = 10399943, upload-time = "2026-06-12T00:13:36.273Z" }, + { url = "https://files.pythonhosted.org/packages/58/77/641504541336240fef3836b2d15a785eaeb33c941fb118513c267dd70840/maturin-1.14.0-py3-none-win32.whl", hash = "sha256:4ba1e3c3f33609f461d587b7549104c81a15fd6d42ba63a73cea9376a1e9876e", size = 8905117, upload-time = "2026-06-12T00:13:18.38Z" }, + { url = "https://files.pythonhosted.org/packages/02/4a/ca247a0c43069b2f48cf783c5b13c3a9eb92c8f596dc7fbdb9f75fea4414/maturin-1.14.0-py3-none-win_amd64.whl", hash = "sha256:cb09a313f097adeb4dda0082277871a28d1bd26615dbadab42e6234b6df6fe69", size = 10309099, upload-time = "2026-06-12T00:13:20.523Z" }, + { url = "https://files.pythonhosted.org/packages/8b/a4/f14a3f6086cc3caaa90d12e832e4aa41de771c310041959f0d35dd4efe17/maturin-1.14.0-py3-none-win_arm64.whl", hash = "sha256:8c1a8188195f5b6ce1aab99ae2d92e342900298f901456b43ca028947fd3b288", size = 9719100, upload-time = "2026-06-12T00:13:24.741Z" }, ] [[package]] name = "mcp" -version = "1.27.0" +version = "1.27.2" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "anyio" }, @@ -2855,9 +2909,9 @@ dependencies = [ { name = "typing-inspection" }, { name = "uvicorn", marker = "sys_platform != 'emscripten'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/8b/eb/c0cfc62075dc6e1ec1c64d352ae09ac051d9334311ed226f1f425312848a/mcp-1.27.0.tar.gz", hash = "sha256:d3dc35a7eec0d458c1da4976a48f982097ddaab87e278c5511d5a4a56e852b83", size = 607509, upload-time = "2026-04-02T14:48:08.88Z" } +sdist = { url = "https://files.pythonhosted.org/packages/27/3c/347cf965d313f5d41764e7d46bea6ffe7d9ef13b983cc429b0340962a082/mcp-1.27.2.tar.gz", hash = "sha256:8e02db104096d1c25b28e64bde29a5c32b31bc241710213e12fd4d84985bdfef", size = 621116, upload-time = "2026-05-29T17:16:04.039Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/9c/46/f6b4ad632c67ef35209a66127e4bddc95759649dd595f71f13fba11bdf9a/mcp-1.27.0-py3-none-any.whl", hash = "sha256:5ce1fa81614958e267b21fb2aa34e0aea8e2c6ede60d52aba45fd47246b4d741", size = 215967, upload-time = "2026-04-02T14:48:07.24Z" }, + { url = "https://files.pythonhosted.org/packages/c9/11/252c6f971dc4f16af1d98a1c469d8ba523aab00d1bb76b4d3bc1ff32eacc/mcp-1.27.2-py3-none-any.whl", hash = "sha256:d6ff5160c6ca65d93013626efb3fc249de683c30b2d8570755ceddd490344de5", size = 220498, upload-time = "2026-05-29T17:16:02.442Z" }, ] [[package]] @@ -2985,31 +3039,29 @@ wheels = [ [[package]] name = "more-itertools" -version = "11.0.2" +version = "11.1.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/a2/f7/139d22fef48ac78127d18e01d80cf1be40236ae489769d17f35c3d425293/more_itertools-11.0.2.tar.gz", hash = "sha256:392a9e1e362cbc106a2457d37cabf9b36e5e12efd4ebff1654630e76597df804", size = 144659, upload-time = "2026-04-09T15:01:33.297Z" } +sdist = { url = "https://files.pythonhosted.org/packages/de/1d/f4da6f02cdffe04d6362210b807146a26044c88d839208aec273bb0d9184/more_itertools-11.1.0.tar.gz", hash = "sha256:48e8f4d9e7e5878571ecf6f2b4e57634f93cd474cc8cfbd2376f2d11b396e30d", size = 145772, upload-time = "2026-05-22T14:14:29.909Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/cb/98/6af411189d9413534c3eb691182bff1f5c6d44ed2f93f2edfe52a1bbceb8/more_itertools-11.0.2-py3-none-any.whl", hash = "sha256:6e35b35f818b01f691643c6c611bc0902f2e92b46c18fffa77ae1e7c46e912e4", size = 71939, upload-time = "2026-04-09T15:01:32.21Z" }, + { url = "https://files.pythonhosted.org/packages/e8/3d/1087453384dbde46a8c7f9356eead2c58be8a7bf156bca40243377c85715/more_itertools-11.1.0-py3-none-any.whl", hash = "sha256:4b65538ae22f6fed0ce4874efd317463a7489796a0939fa66824dd542125a192", size = 72226, upload-time = "2026-05-22T14:14:28.824Z" }, ] [[package]] name = "moto" -version = "5.1.18" +version = "5.2.2" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "boto3" }, { name = "botocore" }, { name = "cryptography" }, - { name = "jinja2" }, - { name = "python-dateutil" }, { name = "requests" }, { name = "responses" }, { name = "werkzeug" }, { name = "xmltodict" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/e3/6a/a73bef67261bfab55714390f07c7df97531d00cea730b7c0ace4d0ad7669/moto-5.1.18.tar.gz", hash = "sha256:45298ef7b88561b839f6fe3e9da2a6e2ecd10283c7bf3daf43a07a97465885f9", size = 8271655, upload-time = "2025-11-30T22:03:59.58Z" } +sdist = { url = "https://files.pythonhosted.org/packages/47/63/d944f387582cc53f53febbff2b3fa36a6d2ed7c1feef8990bf646cfa9cba/moto-5.2.2.tar.gz", hash = "sha256:aac8023a429e125e91c91f8f4730a67b54f518cda587352f7e67252fe3168f75", size = 8678761, upload-time = "2026-06-06T18:57:54.931Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/83/d4/6991df072b34741a0c115e8d21dc2fe142e4b497319d762e957f6677f001/moto-5.1.18-py3-none-any.whl", hash = "sha256:b65aa8fc9032c5c574415451e14fd7da4e43fd50b8bdcb5f10289ad382c25bcf", size = 6357278, upload-time = "2025-11-30T22:03:56.831Z" }, + { url = "https://files.pythonhosted.org/packages/c1/45/13cff46f4f617a6e97e1d497d75abd913e250bb4c823a4985668c6e593e4/moto-5.2.2-py3-none-any.whl", hash = "sha256:3817f1e39721ca833579b921e53e3b68547ace6a34d848c9486fbb5905808de9", size = 6698689, upload-time = "2026-06-06T18:57:51.435Z" }, ] [package.optional-dependencies] @@ -3045,63 +3097,75 @@ wheels = [ [[package]] name = "msgpack" -version = "1.1.2" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/4d/f2/bfb55a6236ed8725a96b0aa3acbd0ec17588e6a2c3b62a93eb513ed8783f/msgpack-1.1.2.tar.gz", hash = "sha256:3b60763c1373dd60f398488069bcdc703cd08a711477b5d480eecc9f9626f47e", size = 173581, upload-time = "2025-10-08T09:15:56.596Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/f5/a2/3b68a9e769db68668b25c6108444a35f9bd163bb848c0650d516761a59c0/msgpack-1.1.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:0051fffef5a37ca2cd16978ae4f0aef92f164df86823871b5162812bebecd8e2", size = 81318, upload-time = "2025-10-08T09:14:38.722Z" }, - { url = "https://files.pythonhosted.org/packages/5b/e1/2b720cc341325c00be44e1ed59e7cfeae2678329fbf5aa68f5bda57fe728/msgpack-1.1.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:a605409040f2da88676e9c9e5853b3449ba8011973616189ea5ee55ddbc5bc87", size = 83786, upload-time = "2025-10-08T09:14:40.082Z" }, - { url = "https://files.pythonhosted.org/packages/71/e5/c2241de64bfceac456b140737812a2ab310b10538a7b34a1d393b748e095/msgpack-1.1.2-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8b696e83c9f1532b4af884045ba7f3aa741a63b2bc22617293a2c6a7c645f251", size = 398240, upload-time = "2025-10-08T09:14:41.151Z" }, - { url = "https://files.pythonhosted.org/packages/b7/09/2a06956383c0fdebaef5aa9246e2356776f12ea6f2a44bd1368abf0e46c4/msgpack-1.1.2-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:365c0bbe981a27d8932da71af63ef86acc59ed5c01ad929e09a0b88c6294e28a", size = 406070, upload-time = "2025-10-08T09:14:42.821Z" }, - { url = "https://files.pythonhosted.org/packages/0e/74/2957703f0e1ef20637d6aead4fbb314330c26f39aa046b348c7edcf6ca6b/msgpack-1.1.2-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:41d1a5d875680166d3ac5c38573896453bbbea7092936d2e107214daf43b1d4f", size = 393403, upload-time = "2025-10-08T09:14:44.38Z" }, - { url = "https://files.pythonhosted.org/packages/a5/09/3bfc12aa90f77b37322fc33e7a8a7c29ba7c8edeadfa27664451801b9860/msgpack-1.1.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:354e81bcdebaab427c3df4281187edc765d5d76bfb3a7c125af9da7a27e8458f", size = 398947, upload-time = "2025-10-08T09:14:45.56Z" }, - { url = "https://files.pythonhosted.org/packages/4b/4f/05fcebd3b4977cb3d840f7ef6b77c51f8582086de5e642f3fefee35c86fc/msgpack-1.1.2-cp310-cp310-win32.whl", hash = "sha256:e64c8d2f5e5d5fda7b842f55dec6133260ea8f53c4257d64494c534f306bf7a9", size = 64769, upload-time = "2025-10-08T09:14:47.334Z" }, - { url = "https://files.pythonhosted.org/packages/d0/3e/b4547e3a34210956382eed1c85935fff7e0f9b98be3106b3745d7dec9c5e/msgpack-1.1.2-cp310-cp310-win_amd64.whl", hash = "sha256:db6192777d943bdaaafb6ba66d44bf65aa0e9c5616fa1d2da9bb08828c6b39aa", size = 71293, upload-time = "2025-10-08T09:14:48.665Z" }, - { url = "https://files.pythonhosted.org/packages/2c/97/560d11202bcd537abca693fd85d81cebe2107ba17301de42b01ac1677b69/msgpack-1.1.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:2e86a607e558d22985d856948c12a3fa7b42efad264dca8a3ebbcfa2735d786c", size = 82271, upload-time = "2025-10-08T09:14:49.967Z" }, - { url = "https://files.pythonhosted.org/packages/83/04/28a41024ccbd67467380b6fb440ae916c1e4f25e2cd4c63abe6835ac566e/msgpack-1.1.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:283ae72fc89da59aa004ba147e8fc2f766647b1251500182fac0350d8af299c0", size = 84914, upload-time = "2025-10-08T09:14:50.958Z" }, - { url = "https://files.pythonhosted.org/packages/71/46/b817349db6886d79e57a966346cf0902a426375aadc1e8e7a86a75e22f19/msgpack-1.1.2-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:61c8aa3bd513d87c72ed0b37b53dd5c5a0f58f2ff9f26e1555d3bd7948fb7296", size = 416962, upload-time = "2025-10-08T09:14:51.997Z" }, - { url = "https://files.pythonhosted.org/packages/da/e0/6cc2e852837cd6086fe7d8406af4294e66827a60a4cf60b86575a4a65ca8/msgpack-1.1.2-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:454e29e186285d2ebe65be34629fa0e8605202c60fbc7c4c650ccd41870896ef", size = 426183, upload-time = "2025-10-08T09:14:53.477Z" }, - { url = "https://files.pythonhosted.org/packages/25/98/6a19f030b3d2ea906696cedd1eb251708e50a5891d0978b012cb6107234c/msgpack-1.1.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:7bc8813f88417599564fafa59fd6f95be417179f76b40325b500b3c98409757c", size = 411454, upload-time = "2025-10-08T09:14:54.648Z" }, - { url = "https://files.pythonhosted.org/packages/b7/cd/9098fcb6adb32187a70b7ecaabf6339da50553351558f37600e53a4a2a23/msgpack-1.1.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:bafca952dc13907bdfdedfc6a5f579bf4f292bdd506fadb38389afa3ac5b208e", size = 422341, upload-time = "2025-10-08T09:14:56.328Z" }, - { url = "https://files.pythonhosted.org/packages/e6/ae/270cecbcf36c1dc85ec086b33a51a4d7d08fc4f404bdbc15b582255d05ff/msgpack-1.1.2-cp311-cp311-win32.whl", hash = "sha256:602b6740e95ffc55bfb078172d279de3773d7b7db1f703b2f1323566b878b90e", size = 64747, upload-time = "2025-10-08T09:14:57.882Z" }, - { url = "https://files.pythonhosted.org/packages/2a/79/309d0e637f6f37e83c711f547308b91af02b72d2326ddd860b966080ef29/msgpack-1.1.2-cp311-cp311-win_amd64.whl", hash = "sha256:d198d275222dc54244bf3327eb8cbe00307d220241d9cec4d306d49a44e85f68", size = 71633, upload-time = "2025-10-08T09:14:59.177Z" }, - { url = "https://files.pythonhosted.org/packages/73/4d/7c4e2b3d9b1106cd0aa6cb56cc57c6267f59fa8bfab7d91df5adc802c847/msgpack-1.1.2-cp311-cp311-win_arm64.whl", hash = "sha256:86f8136dfa5c116365a8a651a7d7484b65b13339731dd6faebb9a0242151c406", size = 64755, upload-time = "2025-10-08T09:15:00.48Z" }, - { url = "https://files.pythonhosted.org/packages/ad/bd/8b0d01c756203fbab65d265859749860682ccd2a59594609aeec3a144efa/msgpack-1.1.2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:70a0dff9d1f8da25179ffcf880e10cf1aad55fdb63cd59c9a49a1b82290062aa", size = 81939, upload-time = "2025-10-08T09:15:01.472Z" }, - { url = "https://files.pythonhosted.org/packages/34/68/ba4f155f793a74c1483d4bdef136e1023f7bcba557f0db4ef3db3c665cf1/msgpack-1.1.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:446abdd8b94b55c800ac34b102dffd2f6aa0ce643c55dfc017ad89347db3dbdb", size = 85064, upload-time = "2025-10-08T09:15:03.764Z" }, - { url = "https://files.pythonhosted.org/packages/f2/60/a064b0345fc36c4c3d2c743c82d9100c40388d77f0b48b2f04d6041dbec1/msgpack-1.1.2-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c63eea553c69ab05b6747901b97d620bb2a690633c77f23feb0c6a947a8a7b8f", size = 417131, upload-time = "2025-10-08T09:15:05.136Z" }, - { url = "https://files.pythonhosted.org/packages/65/92/a5100f7185a800a5d29f8d14041f61475b9de465ffcc0f3b9fba606e4505/msgpack-1.1.2-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:372839311ccf6bdaf39b00b61288e0557916c3729529b301c52c2d88842add42", size = 427556, upload-time = "2025-10-08T09:15:06.837Z" }, - { url = "https://files.pythonhosted.org/packages/f5/87/ffe21d1bf7d9991354ad93949286f643b2bb6ddbeab66373922b44c3b8cc/msgpack-1.1.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:2929af52106ca73fcb28576218476ffbb531a036c2adbcf54a3664de124303e9", size = 404920, upload-time = "2025-10-08T09:15:08.179Z" }, - { url = "https://files.pythonhosted.org/packages/ff/41/8543ed2b8604f7c0d89ce066f42007faac1eaa7d79a81555f206a5cdb889/msgpack-1.1.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:be52a8fc79e45b0364210eef5234a7cf8d330836d0a64dfbb878efa903d84620", size = 415013, upload-time = "2025-10-08T09:15:09.83Z" }, - { url = "https://files.pythonhosted.org/packages/41/0d/2ddfaa8b7e1cee6c490d46cb0a39742b19e2481600a7a0e96537e9c22f43/msgpack-1.1.2-cp312-cp312-win32.whl", hash = "sha256:1fff3d825d7859ac888b0fbda39a42d59193543920eda9d9bea44d958a878029", size = 65096, upload-time = "2025-10-08T09:15:11.11Z" }, - { url = "https://files.pythonhosted.org/packages/8c/ec/d431eb7941fb55a31dd6ca3404d41fbb52d99172df2e7707754488390910/msgpack-1.1.2-cp312-cp312-win_amd64.whl", hash = "sha256:1de460f0403172cff81169a30b9a92b260cb809c4cb7e2fc79ae8d0510c78b6b", size = 72708, upload-time = "2025-10-08T09:15:12.554Z" }, - { url = "https://files.pythonhosted.org/packages/c5/31/5b1a1f70eb0e87d1678e9624908f86317787b536060641d6798e3cf70ace/msgpack-1.1.2-cp312-cp312-win_arm64.whl", hash = "sha256:be5980f3ee0e6bd44f3a9e9dea01054f175b50c3e6cdb692bc9424c0bbb8bf69", size = 64119, upload-time = "2025-10-08T09:15:13.589Z" }, - { url = "https://files.pythonhosted.org/packages/6b/31/b46518ecc604d7edf3a4f94cb3bf021fc62aa301f0cb849936968164ef23/msgpack-1.1.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:4efd7b5979ccb539c221a4c4e16aac1a533efc97f3b759bb5a5ac9f6d10383bf", size = 81212, upload-time = "2025-10-08T09:15:14.552Z" }, - { url = "https://files.pythonhosted.org/packages/92/dc/c385f38f2c2433333345a82926c6bfa5ecfff3ef787201614317b58dd8be/msgpack-1.1.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:42eefe2c3e2af97ed470eec850facbe1b5ad1d6eacdbadc42ec98e7dcf68b4b7", size = 84315, upload-time = "2025-10-08T09:15:15.543Z" }, - { url = "https://files.pythonhosted.org/packages/d3/68/93180dce57f684a61a88a45ed13047558ded2be46f03acb8dec6d7c513af/msgpack-1.1.2-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1fdf7d83102bf09e7ce3357de96c59b627395352a4024f6e2458501f158bf999", size = 412721, upload-time = "2025-10-08T09:15:16.567Z" }, - { url = "https://files.pythonhosted.org/packages/5d/ba/459f18c16f2b3fc1a1ca871f72f07d70c07bf768ad0a507a698b8052ac58/msgpack-1.1.2-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:fac4be746328f90caa3cd4bc67e6fe36ca2bf61d5c6eb6d895b6527e3f05071e", size = 424657, upload-time = "2025-10-08T09:15:17.825Z" }, - { url = "https://files.pythonhosted.org/packages/38/f8/4398c46863b093252fe67368b44edc6c13b17f4e6b0e4929dbf0bdb13f23/msgpack-1.1.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:fffee09044073e69f2bad787071aeec727183e7580443dfeb8556cbf1978d162", size = 402668, upload-time = "2025-10-08T09:15:19.003Z" }, - { url = "https://files.pythonhosted.org/packages/28/ce/698c1eff75626e4124b4d78e21cca0b4cc90043afb80a507626ea354ab52/msgpack-1.1.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:5928604de9b032bc17f5099496417f113c45bc6bc21b5c6920caf34b3c428794", size = 419040, upload-time = "2025-10-08T09:15:20.183Z" }, - { url = "https://files.pythonhosted.org/packages/67/32/f3cd1667028424fa7001d82e10ee35386eea1408b93d399b09fb0aa7875f/msgpack-1.1.2-cp313-cp313-win32.whl", hash = "sha256:a7787d353595c7c7e145e2331abf8b7ff1e6673a6b974ded96e6d4ec09f00c8c", size = 65037, upload-time = "2025-10-08T09:15:21.416Z" }, - { url = "https://files.pythonhosted.org/packages/74/07/1ed8277f8653c40ebc65985180b007879f6a836c525b3885dcc6448ae6cb/msgpack-1.1.2-cp313-cp313-win_amd64.whl", hash = "sha256:a465f0dceb8e13a487e54c07d04ae3ba131c7c5b95e2612596eafde1dccf64a9", size = 72631, upload-time = "2025-10-08T09:15:22.431Z" }, - { url = "https://files.pythonhosted.org/packages/e5/db/0314e4e2db56ebcf450f277904ffd84a7988b9e5da8d0d61ab2d057df2b6/msgpack-1.1.2-cp313-cp313-win_arm64.whl", hash = "sha256:e69b39f8c0aa5ec24b57737ebee40be647035158f14ed4b40e6f150077e21a84", size = 64118, upload-time = "2025-10-08T09:15:23.402Z" }, - { url = "https://files.pythonhosted.org/packages/22/71/201105712d0a2ff07b7873ed3c220292fb2ea5120603c00c4b634bcdafb3/msgpack-1.1.2-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:e23ce8d5f7aa6ea6d2a2b326b4ba46c985dbb204523759984430db7114f8aa00", size = 81127, upload-time = "2025-10-08T09:15:24.408Z" }, - { url = "https://files.pythonhosted.org/packages/1b/9f/38ff9e57a2eade7bf9dfee5eae17f39fc0e998658050279cbb14d97d36d9/msgpack-1.1.2-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:6c15b7d74c939ebe620dd8e559384be806204d73b4f9356320632d783d1f7939", size = 84981, upload-time = "2025-10-08T09:15:25.812Z" }, - { url = "https://files.pythonhosted.org/packages/8e/a9/3536e385167b88c2cc8f4424c49e28d49a6fc35206d4a8060f136e71f94c/msgpack-1.1.2-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:99e2cb7b9031568a2a5c73aa077180f93dd2e95b4f8d3b8e14a73ae94a9e667e", size = 411885, upload-time = "2025-10-08T09:15:27.22Z" }, - { url = "https://files.pythonhosted.org/packages/2f/40/dc34d1a8d5f1e51fc64640b62b191684da52ca469da9cd74e84936ffa4a6/msgpack-1.1.2-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:180759d89a057eab503cf62eeec0aa61c4ea1200dee709f3a8e9397dbb3b6931", size = 419658, upload-time = "2025-10-08T09:15:28.4Z" }, - { url = "https://files.pythonhosted.org/packages/3b/ef/2b92e286366500a09a67e03496ee8b8ba00562797a52f3c117aa2b29514b/msgpack-1.1.2-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:04fb995247a6e83830b62f0b07bf36540c213f6eac8e851166d8d86d83cbd014", size = 403290, upload-time = "2025-10-08T09:15:29.764Z" }, - { url = "https://files.pythonhosted.org/packages/78/90/e0ea7990abea5764e4655b8177aa7c63cdfa89945b6e7641055800f6c16b/msgpack-1.1.2-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:8e22ab046fa7ede9e36eeb4cfad44d46450f37bb05d5ec482b02868f451c95e2", size = 415234, upload-time = "2025-10-08T09:15:31.022Z" }, - { url = "https://files.pythonhosted.org/packages/72/4e/9390aed5db983a2310818cd7d3ec0aecad45e1f7007e0cda79c79507bb0d/msgpack-1.1.2-cp314-cp314-win32.whl", hash = "sha256:80a0ff7d4abf5fecb995fcf235d4064b9a9a8a40a3ab80999e6ac1e30b702717", size = 66391, upload-time = "2025-10-08T09:15:32.265Z" }, - { url = "https://files.pythonhosted.org/packages/6e/f1/abd09c2ae91228c5f3998dbd7f41353def9eac64253de3c8105efa2082f7/msgpack-1.1.2-cp314-cp314-win_amd64.whl", hash = "sha256:9ade919fac6a3e7260b7f64cea89df6bec59104987cbea34d34a2fa15d74310b", size = 73787, upload-time = "2025-10-08T09:15:33.219Z" }, - { url = "https://files.pythonhosted.org/packages/6a/b0/9d9f667ab48b16ad4115c1935d94023b82b3198064cb84a123e97f7466c1/msgpack-1.1.2-cp314-cp314-win_arm64.whl", hash = "sha256:59415c6076b1e30e563eb732e23b994a61c159cec44deaf584e5cc1dd662f2af", size = 66453, upload-time = "2025-10-08T09:15:34.225Z" }, - { url = "https://files.pythonhosted.org/packages/16/67/93f80545eb1792b61a217fa7f06d5e5cb9e0055bed867f43e2b8e012e137/msgpack-1.1.2-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:897c478140877e5307760b0ea66e0932738879e7aa68144d9b78ea4c8302a84a", size = 85264, upload-time = "2025-10-08T09:15:35.61Z" }, - { url = "https://files.pythonhosted.org/packages/87/1c/33c8a24959cf193966ef11a6f6a2995a65eb066bd681fd085afd519a57ce/msgpack-1.1.2-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:a668204fa43e6d02f89dbe79a30b0d67238d9ec4c5bd8a940fc3a004a47b721b", size = 89076, upload-time = "2025-10-08T09:15:36.619Z" }, - { url = "https://files.pythonhosted.org/packages/fc/6b/62e85ff7193663fbea5c0254ef32f0c77134b4059f8da89b958beb7696f3/msgpack-1.1.2-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5559d03930d3aa0f3aacb4c42c776af1a2ace2611871c84a75afe436695e6245", size = 435242, upload-time = "2025-10-08T09:15:37.647Z" }, - { url = "https://files.pythonhosted.org/packages/c1/47/5c74ecb4cc277cf09f64e913947871682ffa82b3b93c8dad68083112f412/msgpack-1.1.2-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:70c5a7a9fea7f036b716191c29047374c10721c389c21e9ffafad04df8c52c90", size = 432509, upload-time = "2025-10-08T09:15:38.794Z" }, - { url = "https://files.pythonhosted.org/packages/24/a4/e98ccdb56dc4e98c929a3f150de1799831c0a800583cde9fa022fa90602d/msgpack-1.1.2-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:f2cb069d8b981abc72b41aea1c580ce92d57c673ec61af4c500153a626cb9e20", size = 415957, upload-time = "2025-10-08T09:15:40.238Z" }, - { url = "https://files.pythonhosted.org/packages/da/28/6951f7fb67bc0a4e184a6b38ab71a92d9ba58080b27a77d3e2fb0be5998f/msgpack-1.1.2-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:d62ce1f483f355f61adb5433ebfd8868c5f078d1a52d042b0a998682b4fa8c27", size = 422910, upload-time = "2025-10-08T09:15:41.505Z" }, - { url = "https://files.pythonhosted.org/packages/f0/03/42106dcded51f0a0b5284d3ce30a671e7bd3f7318d122b2ead66ad289fed/msgpack-1.1.2-cp314-cp314t-win32.whl", hash = "sha256:1d1418482b1ee984625d88aa9585db570180c286d942da463533b238b98b812b", size = 75197, upload-time = "2025-10-08T09:15:42.954Z" }, - { url = "https://files.pythonhosted.org/packages/15/86/d0071e94987f8db59d4eeb386ddc64d0bb9b10820a8d82bcd3e53eeb2da6/msgpack-1.1.2-cp314-cp314t-win_amd64.whl", hash = "sha256:5a46bf7e831d09470ad92dff02b8b1ac92175ca36b087f904a0519857c6be3ff", size = 85772, upload-time = "2025-10-08T09:15:43.954Z" }, - { url = "https://files.pythonhosted.org/packages/81/f2/08ace4142eb281c12701fc3b93a10795e4d4dc7f753911d836675050f886/msgpack-1.1.2-cp314-cp314t-win_arm64.whl", hash = "sha256:d99ef64f349d5ec3293688e91486c5fdb925ed03807f64d98d205d2713c60b46", size = 70868, upload-time = "2025-10-08T09:15:44.959Z" }, +version = "1.2.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/92/23/6139781ca7aadf656fa8e384fa84693ffb13f299e6931b6526427fe5e297/msgpack-1.2.0.tar.gz", hash = "sha256:8e17af38197bf58e7e819041678f6178f4491493f5b8c8580414f40f7c2c3c41", size = 183017, upload-time = "2026-06-11T04:16:10.775Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/0f/52/fed22bca455ff3ed28c0ee0d1117398b7cb3ce440270050e85b09240fa8d/msgpack-1.2.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:ed8c9495a0f12d17a2b4b69e23f895b88f26aabe40911c86594d3fbddecfff08", size = 82473, upload-time = "2026-06-11T04:14:38.484Z" }, + { url = "https://files.pythonhosted.org/packages/3b/09/0b54d386024a9fa2073135212c11d1e83b059d98459d943d5a82ba9dcdc9/msgpack-1.2.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:d7384859c90b45a28a4b31aa50b49cca84504c9f27df459cea6e072627650dcb", size = 82150, upload-time = "2026-06-11T04:14:39.985Z" }, + { url = "https://files.pythonhosted.org/packages/44/ba/c6310a6f37e9bf9279b492640ec425e6f6e68a94e4cac4782ab518b05d64/msgpack-1.2.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:63b35e8e65f04ff7ad5c9c70885da587c74f51e4b4eb3db624eac6d250e8cf59", size = 398355, upload-time = "2026-06-11T04:14:41.493Z" }, + { url = "https://files.pythonhosted.org/packages/d8/1b/f4bad0e9dea608b14d36065c44e347e4b10c0392f92cca441496cc0598ef/msgpack-1.2.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9004c5a02acd3eca4e15e1ae7b461c32e3711105a28b1ad78be2f6facff4c523", size = 405162, upload-time = "2026-06-11T04:14:42.957Z" }, + { url = "https://files.pythonhosted.org/packages/63/34/4653bc7f426bd6ce9803f75133aa362232639e5adb8c6b99550107c71ed5/msgpack-1.2.0-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:7e2032dacb0a973fcbf7bd088415a369dae31c5af40e199d234806be22e86765", size = 372720, upload-time = "2026-06-11T04:14:44.532Z" }, + { url = "https://files.pythonhosted.org/packages/13/3c/8c607e10db2225af52107ffa918280483248363819fecb4437a35a1f4ae2/msgpack-1.2.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:c1feb100651fbe4b39826207cb20af065dfbfbfa43b1bafd7eaa2252abf7acfd", size = 390946, upload-time = "2026-06-11T04:14:46.054Z" }, + { url = "https://files.pythonhosted.org/packages/96/05/c4cb5fb30569cff4b4c7be4574adddb0faf7faaf3049bbab000b6f07da5b/msgpack-1.2.0-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:82487709d4c597d252311a65370220675fb1cc859e7da9269a3060c03ac02cf6", size = 374062, upload-time = "2026-06-11T04:14:47.817Z" }, + { url = "https://files.pythonhosted.org/packages/40/d7/b51b11e58277e6b678ba5a2f6608f88fdb0778973391a39d7f1a385f5bde/msgpack-1.2.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:0268c67a74f5f913f545a0fdbbfaa3f6ebcf23b4c3209bb99704a2ea87e13f90", size = 405458, upload-time = "2026-06-11T04:14:49.618Z" }, + { url = "https://files.pythonhosted.org/packages/2c/0e/9eca2961be302a6fc77a3fcb15faec749e325c9f0a8fe9c4c4576fc2cad5/msgpack-1.2.0-cp310-cp310-win32.whl", hash = "sha256:7df87173b0e13ddd134919731f13525dbbf75204145597decf1cb86887ebb492", size = 64010, upload-time = "2026-06-11T04:14:51.071Z" }, + { url = "https://files.pythonhosted.org/packages/e7/e3/55b14ae13ed056ed35364ff71144c6a12af25227c20093045a945d08273a/msgpack-1.2.0-cp310-cp310-win_amd64.whl", hash = "sha256:6371edb47788fbfd8a22016f9a97b5616dd9849bc50abcbb8e82d38f71efa096", size = 69863, upload-time = "2026-06-11T04:14:52.376Z" }, + { url = "https://files.pythonhosted.org/packages/ee/23/35de3182a647fcc84ab304160169edfa5dac7bbd8913fbed0a505ddc0d55/msgpack-1.2.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:ec35cd3f127f50806aa10c3f74bf27b749f13ddf1d2217964ada8f38042d1653", size = 82368, upload-time = "2026-06-11T04:14:53.57Z" }, + { url = "https://files.pythonhosted.org/packages/aa/79/8d9bfdab933b1c7a02aba9518605a81aa30d38e9efd4915ec1a6b2d55778/msgpack-1.2.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:317eb298297121bfad9173d748124a04a36af27b6ac39c2bbc1db1ce57608dcf", size = 82095, upload-time = "2026-06-11T04:14:54.784Z" }, + { url = "https://files.pythonhosted.org/packages/d2/e1/b5accbc1354edbcee107fb35ec247db0547e91c3f90e4fabdeaee500a5a6/msgpack-1.2.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:50fe6434de89073273026dd032a62e8b63f8857a261d7a2df5b07c9e72f3a8f7", size = 413818, upload-time = "2026-06-11T04:14:56.1Z" }, + { url = "https://files.pythonhosted.org/packages/82/31/1141cbbf7118d525834f20dcd614d1b85f1f2ffd33bc2a5ce710e6dd2516/msgpack-1.2.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:106c6d333ff3d4eda075b7d4b9695d1752c5bcc635e40d0dbaf4e276c9ed80e1", size = 423790, upload-time = "2026-06-11T04:14:57.509Z" }, + { url = "https://files.pythonhosted.org/packages/04/e7/9582f2bd4d7546139fe297740de49bd1f7ef2d195eb0bb9fa5efeee88158/msgpack-1.2.0-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:67055a611e871cb1bd0acb732f2e9f64ca8155ca0bba1d0a5bb362e7209e5541", size = 387521, upload-time = "2026-06-11T04:14:59.08Z" }, + { url = "https://files.pythonhosted.org/packages/7d/12/5aadd08ff068bfd42e2ac0be6a20aa9819965df8622e87c1f0c6119c1c22/msgpack-1.2.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:ceec7f8e633d5a4b4a32b0416bef90ee3cd1017ea36247f705e523072e576119", size = 406324, upload-time = "2026-06-11T04:15:00.686Z" }, + { url = "https://files.pythonhosted.org/packages/39/ee/3041564f0cc4c2fe7c53315aec0edf3d84807fc9b9ea714e6ac07dbdb1db/msgpack-1.2.0-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:7ec5851160a3c2c0f77d68ddec620318cd8e7d88d94f9c058190e8ce0dfa1d31", size = 384242, upload-time = "2026-06-11T04:15:02.121Z" }, + { url = "https://files.pythonhosted.org/packages/5d/d4/de94b3dbc266229f4c2ce84485eeb221220351b7f1931029e875995bb232/msgpack-1.2.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:dd7140f7b09dbe1984a0dff3189375d840247e3e4cf4ac45c5a499b3b599c8d2", size = 420392, upload-time = "2026-06-11T04:15:03.692Z" }, + { url = "https://files.pythonhosted.org/packages/f7/5d/c4a3fde69a292eecb202caaa87c29df7728644a65118614b821bcaddc05a/msgpack-1.2.0-cp311-cp311-win32.whl", hash = "sha256:cbfd54018d386da0951c7a2be13de0f58559d251313e613b2155e52ed1cbd8f1", size = 63976, upload-time = "2026-06-11T04:15:05.355Z" }, + { url = "https://files.pythonhosted.org/packages/18/fa/df47f83115375e7717c985265a30f3ba096c5331518e28fb647b55c46d31/msgpack-1.2.0-cp311-cp311-win_amd64.whl", hash = "sha256:653373c4614c31463ba486a67776e4bb396af289921bd5353e209534b71467fa", size = 70273, upload-time = "2026-06-11T04:15:06.529Z" }, + { url = "https://files.pythonhosted.org/packages/54/d1/ffd02e54c064aa73b6b53aa08171f92dc406727077ff275d7050c6aca28a/msgpack-1.2.0-cp311-cp311-win_arm64.whl", hash = "sha256:7a260aea1e5e7d6c7f1d9284c7360d29021627b61dc4dd7df144b81210810537", size = 64783, upload-time = "2026-06-11T04:15:07.677Z" }, + { url = "https://files.pythonhosted.org/packages/44/07/dcb13f37e670257c8d0e944f116c799c34ac6968ecb48c83619f7e91d8b5/msgpack-1.2.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:e2d6047ccd11a12c96a69f2bfe026471abef67334c3d0494a93e5310e45140a2", size = 82888, upload-time = "2026-06-11T04:15:08.992Z" }, + { url = "https://files.pythonhosted.org/packages/84/5f/6643b2a6a36ca4bc73c7674831be1d4d581cceecc7eb019dba1915951739/msgpack-1.2.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:0347e3ac0dfee99086d3b68fe959da3f5f657c0019ddbaeaaa259a85f8603422", size = 82223, upload-time = "2026-06-11T04:15:10.182Z" }, + { url = "https://files.pythonhosted.org/packages/2c/c8/9e1668b9897358e5ab39a18142e38be3cf15807e643757782da9f4a53cb3/msgpack-1.2.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:25552ff1f2ff3dc8333e27eabb94f702da5929ed0e07969688194a3e9f12e151", size = 409700, upload-time = "2026-06-11T04:15:11.441Z" }, + { url = "https://files.pythonhosted.org/packages/38/ed/b7728573156d70b6b094233b0f38d876fc37340826cf852347ec2c7ca8ca/msgpack-1.2.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a0d94420d9d52c56568159a69200af7e45eadb29615fa9d09fada140de1c38c7", size = 420090, upload-time = "2026-06-11T04:15:12.868Z" }, + { url = "https://files.pythonhosted.org/packages/3f/f7/5ea755a89868c04f9cdf6d96d2d99da4b3d198af10e76a6082dd0fceccc0/msgpack-1.2.0-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:d16e1f2db4a9eebc07b7cc91898d71e710f2eed8358711a605fee802caff8923", size = 378538, upload-time = "2026-06-11T04:15:14.511Z" }, + { url = "https://files.pythonhosted.org/packages/80/2d/126e59332a439c94ffd682c38ca0102b23480e2784b3dac48d8959b0bbac/msgpack-1.2.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:e9cb2e700e85f1e27bbb5c9de6cc1c9a4bc5ac64d5404bdcbcb37a0dc7a947a3", size = 399468, upload-time = "2026-06-11T04:15:16.133Z" }, + { url = "https://files.pythonhosted.org/packages/da/f9/7abcef683a0ad2e5ab3a4940344aad9f20cdf1f42057ecb0982cf55085d6/msgpack-1.2.0-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:717d0b166dd176a5f786aeafff081f6439680acf5af193eb63e6266c12b04d3d", size = 374212, upload-time = "2026-06-11T04:15:17.536Z" }, + { url = "https://files.pythonhosted.org/packages/27/23/2d62cf0e971678e96f8a3cfa9bd77fb719ddb98da73790f63c53fd847ad8/msgpack-1.2.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:e87c7a21654d18111eb1a89bd5c42baba42e61887365d9e89585e112b4203f9e", size = 414361, upload-time = "2026-06-11T04:15:18.99Z" }, + { url = "https://files.pythonhosted.org/packages/32/fb/f5c153f614037aaf802d291a4653ba1bb731f56feacba886f7c21c109e56/msgpack-1.2.0-cp312-cp312-win32.whl", hash = "sha256:967e0c891f5f23ab65762f2e5dc95922759c79f1ef99ef4c7e1fdd863e0d0af9", size = 64389, upload-time = "2026-06-11T04:15:20.237Z" }, + { url = "https://files.pythonhosted.org/packages/90/af/8aafce6e5544b43b84cb670aca40c8bea7eb5ae8f42bfcbdc7098739987a/msgpack-1.2.0-cp312-cp312-win_amd64.whl", hash = "sha256:6c23e33cee28dcffa112ae205661da4636fd7b06bd9ad1559a890623b92d060b", size = 71185, upload-time = "2026-06-11T04:15:21.51Z" }, + { url = "https://files.pythonhosted.org/packages/ba/08/9cc94be1fc1fe3d1379d439326259aef0344274f64623a8138feb54dff68/msgpack-1.2.0-cp312-cp312-win_arm64.whl", hash = "sha256:6eeb771571f63f68045433b1a35c0256b946f31ed62f006997e40b8ad8b735af", size = 64481, upload-time = "2026-06-11T04:15:22.639Z" }, + { url = "https://files.pythonhosted.org/packages/7d/26/2902c6946ab5c8fe1e46e40842dfc32b8824464ad5cd4725364fd83f7a58/msgpack-1.2.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:3a1d30df1f302f2b7a7404afbac2ab76d510036c34cf34dffb01f704a7288e45", size = 82621, upload-time = "2026-06-11T04:15:23.844Z" }, + { url = "https://files.pythonhosted.org/packages/c9/59/7e6b812629d2f919e586041bffc130e1af32079f71bb20699eed54ed6d92/msgpack-1.2.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:581e317112260d8ca488d490cad9290a5682276f309c41c7de237a85ed8799c8", size = 81866, upload-time = "2026-06-11T04:15:25.032Z" }, + { url = "https://files.pythonhosted.org/packages/31/13/8c291196e60aafdbae38f482205d79432297749ac5d412fe638154fb6f1d/msgpack-1.2.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c6827d12eacc16873eba62408a1b7bbe8ecfb4a8f7ed78a631ae9bae6ad43cf2", size = 405618, upload-time = "2026-06-11T04:15:26.235Z" }, + { url = "https://files.pythonhosted.org/packages/fb/63/68f5d0ea81e167db5f59ddb94dc6f837667062113feff1c73fabf8907061/msgpack-1.2.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a186027e4279efa4c8bf06ce30605498d7d0d3af0fba0b9799dce85a3fd4a93c", size = 416468, upload-time = "2026-06-11T04:15:27.732Z" }, + { url = "https://files.pythonhosted.org/packages/73/58/567dddf5c5a2790f673bcd7d80c83466d68e5ee9a9674ebca3db8101c0c8/msgpack-1.2.0-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:a96142c14a11cf1a509e8b9aaf72858a3b742b7613e095ce646913e88ce7bd99", size = 374464, upload-time = "2026-06-11T04:15:29.286Z" }, + { url = "https://files.pythonhosted.org/packages/0d/30/0c2342fc9092e4498045f5f60bca6ccbe4f4d87789778c2300e6fd6efe82/msgpack-1.2.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:50c220579b68a6085b95408b2eaa486b259520f55d8e363ddc9b5d7ba5a6ac6d", size = 395879, upload-time = "2026-06-11T04:15:30.973Z" }, + { url = "https://files.pythonhosted.org/packages/b9/11/9565b29b58ce3c33e177b490478b7aaeb8f726ecaaeda26d815893c1db5a/msgpack-1.2.0-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:4dcb9d12ab100ecacdfaaf37a3d72fe8392eacc7054afc1916b12d1b747c8446", size = 371749, upload-time = "2026-06-11T04:15:32.418Z" }, + { url = "https://files.pythonhosted.org/packages/f2/da/7bade19d60b73e2ef73fb76aaf4504c112a70cb760951b7202a0c64b5111/msgpack-1.2.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:a804727188ab0ebb237fadb303b743f04925a69d8c3247292d1e33e679767c15", size = 410416, upload-time = "2026-06-11T04:15:34.053Z" }, + { url = "https://files.pythonhosted.org/packages/6d/14/c0c619571c02432208a5977a8dbdd3fc65fe1369f8226ca4b6d08cca87d8/msgpack-1.2.0-cp313-cp313-win32.whl", hash = "sha256:1a1ac6ae1fe23298f79380e7b144c8a454e5d05616b0096584f353ba2d750114", size = 64357, upload-time = "2026-06-11T04:15:35.535Z" }, + { url = "https://files.pythonhosted.org/packages/50/a5/de06718460909aa965737fec4cfe8a15dedc6544a8c55feeb6956fa0d6e3/msgpack-1.2.0-cp313-cp313-win_amd64.whl", hash = "sha256:1c3c80949d79578f9dc85fd9fb91edfe6694e8a729cd5744634d59d8455fdde3", size = 71057, upload-time = "2026-06-11T04:15:36.83Z" }, + { url = "https://files.pythonhosted.org/packages/c7/52/73446b0141c94a856e22b787c56709c0815fc34f185326577e15b26d8cfe/msgpack-1.2.0-cp313-cp313-win_arm64.whl", hash = "sha256:fcf8f76fa587c2395fd0057c7232dbf071241f9ad280b235adb7ab585289989e", size = 64490, upload-time = "2026-06-11T04:15:38.001Z" }, + { url = "https://files.pythonhosted.org/packages/35/3d/a7e3cdafa8c0cf36c81e2fa848ec4d30cf089459af45b390ad03f9ce6f49/msgpack-1.2.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:f854fa1a8b55d75d82ef9a905d9cdbeffdf7897c088f6020bd221867da5e56a5", size = 83032, upload-time = "2026-06-11T04:15:39.38Z" }, + { url = "https://files.pythonhosted.org/packages/ca/aa/53ddfba0e347cc4b484e95f629c5850b9e800ca8390c91ffc604407acf87/msgpack-1.2.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:e90df581f80f53b372d5d9d9349078d729851a3a0d0bd74f53ccb598d01e45b8", size = 82600, upload-time = "2026-06-11T04:15:40.609Z" }, + { url = "https://files.pythonhosted.org/packages/59/fd/e64c2c776e6dbad0af3c963fe0c0dd1ee1ba09efac478b233ab1db41868f/msgpack-1.2.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b276ed50d8ac75d1f134a433ae79af8557d0fa25ee5b4737da533dfc2ce382e8", size = 404342, upload-time = "2026-06-11T04:15:41.87Z" }, + { url = "https://files.pythonhosted.org/packages/1b/60/fb9a08e6ccba882dfd370a5837fe3a07572938fdfe954f0f17fdf3e574b9/msgpack-1.2.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:544d972459c92aa32e63b800d07c2d9cf2734a3be29cee3a0b478a622850e9f5", size = 412351, upload-time = "2026-06-11T04:15:43.253Z" }, + { url = "https://files.pythonhosted.org/packages/37/4d/df5c575c274fedc68ac9c6c61d045161899efad2afcdc25138efa7edde69/msgpack-1.2.0-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:a070147cc2cf6b8a891734e0f5c8fe8f70ed8739ab30ba140b058005a6e86af4", size = 373331, upload-time = "2026-06-11T04:15:44.754Z" }, + { url = "https://files.pythonhosted.org/packages/7d/a4/c8b98f8191e985ed2003d87664ce3c95cca41db5d0cf6bf4f54327d32ec8/msgpack-1.2.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:7685e23b0f51745a751629c31713fbefdef8896b31b2bb38299dfa4ae6c0740c", size = 394654, upload-time = "2026-06-11T04:15:46.423Z" }, + { url = "https://files.pythonhosted.org/packages/d4/49/76f036720a602ea24428cfec5ec806f2487c0380b1bff0a2aa3094e15f87/msgpack-1.2.0-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:b9204daeee8d91a7ae5acf2d2a8e3983be9a3025f38aa21bfaefbd7eea84a7dc", size = 370624, upload-time = "2026-06-11T04:15:48.062Z" }, + { url = "https://files.pythonhosted.org/packages/9f/38/40af3d29232833705a43b0fce0d07425cc280a7b92ab2b29932425b40df4/msgpack-1.2.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:bfc057248609742ebbabf6bcd27fea4fd99c4980584e613c168c9b002318298f", size = 408038, upload-time = "2026-06-11T04:15:49.669Z" }, + { url = "https://files.pythonhosted.org/packages/30/b2/f140ca450524dff4d8d0eb81eb9ed75f8f3e0b1f12e49c5b01617cfa0b1c/msgpack-1.2.0-cp314-cp314-win32.whl", hash = "sha256:a3faa7edf2388337ae849239878e92f0298b4dab4488e4f1834062f9d0c410c9", size = 65823, upload-time = "2026-06-11T04:15:51.062Z" }, + { url = "https://files.pythonhosted.org/packages/4d/13/6517bf966b841c7675ded30701a068ce141f3e698a27aaa35c702d8e078b/msgpack-1.2.0-cp314-cp314-win_amd64.whl", hash = "sha256:1a3effc392a57744e4681e55d05f97d5ee7b598747d718340a9b4b8a970c40e1", size = 72484, upload-time = "2026-06-11T04:15:52.289Z" }, + { url = "https://files.pythonhosted.org/packages/45/8c/1d948420fdaa24de4efdb8012a6a5bebe09c82ee002b8c2ca745e9917f1f/msgpack-1.2.0-cp314-cp314-win_arm64.whl", hash = "sha256:56a318f7df6bec7b40928d6b0519961f20a510d8baabf6baa393a70444588f0a", size = 66657, upload-time = "2026-06-11T04:15:53.583Z" }, + { url = "https://files.pythonhosted.org/packages/39/16/1674faa1b7bddc19e79b465fd8e88e2cf4e3f7cae90723740701e8541068/msgpack-1.2.0-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:afa4a65ab2097795e771a74a3a81ea49534aaeba874eaf426a3332268e045ae6", size = 86093, upload-time = "2026-06-11T04:15:54.98Z" }, + { url = "https://files.pythonhosted.org/packages/dd/24/f241bcfdd9e96b2246289357c5a5e5a496189fd41c5844bee802c116aac7/msgpack-1.2.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:409550770632bb28daa70a11d0ed5763f7db38f40b06f7db9f11dd2794d01102", size = 86372, upload-time = "2026-06-11T04:15:56.381Z" }, + { url = "https://files.pythonhosted.org/packages/94/c9/57f8ab98a1b21808c27b6dd6029053e0a796ffbb9b371e460dbe997011a9/msgpack-1.2.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:bf47e3cd11ce044965a9736a322afdd390b31ed602d1c1b10211d1a841f1d587", size = 428207, upload-time = "2026-06-11T04:15:57.739Z" }, + { url = "https://files.pythonhosted.org/packages/17/6b/4fd4aa739f131ded751ca7167c8ee87d2aab32506ebbeea893b60b51d343/msgpack-1.2.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:204bc9f5d6e59c1718c0a4a84fc8ff71b5b4562faac257c1a68bca611ecf9b72", size = 426082, upload-time = "2026-06-11T04:15:59.356Z" }, + { url = "https://files.pythonhosted.org/packages/f9/00/db88e9a08fcd6513decaad06cbd5c168142bc3e662fb2f1aca3a563b7aa1/msgpack-1.2.0-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:610154307b27267266368bc1d1c7bb8aeb71da7be9356d403cb2442d9e6399f5", size = 378355, upload-time = "2026-06-11T04:16:00.916Z" }, + { url = "https://files.pythonhosted.org/packages/54/84/eee4dd703d7a600cf46159d621c070b0b9468cf3dbade4ea8272bf5232a4/msgpack-1.2.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:6799f157bb63e79f11e2e590cfdb28423fc18dd60c270c3914b5b4586ae36f7e", size = 410848, upload-time = "2026-06-11T04:16:02.745Z" }, + { url = "https://files.pythonhosted.org/packages/12/0a/195e2c549fd4631eb7f157d016ff15a10c4c1cf82b6d0a9b1edaef5174b1/msgpack-1.2.0-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:72bd844902cf0a5ac3af2ef742f253cd0b1e5bcd184f49b4fb9a6a1f7bf305e8", size = 376152, upload-time = "2026-06-11T04:16:04.041Z" }, + { url = "https://files.pythonhosted.org/packages/45/9b/bdd143fa79baec411dc658f5686fed680a18b36fcea5fccb6af1b8c7d832/msgpack-1.2.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:3c0bd450f78d0d81722c80da6cdbf674a856967870a9db2f6c4debc4d8b3c67c", size = 417061, upload-time = "2026-06-11T04:16:05.63Z" }, + { url = "https://files.pythonhosted.org/packages/2d/ce/011ffcd8b919f55196ec53f12ae162e21c879d95afba226894314ff62c07/msgpack-1.2.0-cp314-cp314t-win32.whl", hash = "sha256:378caf74c4c718dfc17590ce68a6d710ed398ff6fcf08237de23b77755730b55", size = 70782, upload-time = "2026-06-11T04:16:07.105Z" }, + { url = "https://files.pythonhosted.org/packages/57/a8/9b8791ca96b1be6b9f659c718271e2cb7f99f73f58aad2dd0b30f750f6c0/msgpack-1.2.0-cp314-cp314t-win_amd64.whl", hash = "sha256:553b42598165c4dd3235994fd6e4b0dfb1ce5f3fd33d94ba9609442643015f38", size = 77899, upload-time = "2026-06-11T04:16:08.353Z" }, + { url = "https://files.pythonhosted.org/packages/5b/04/3fa2dffb87bf598696b86bde7cd642d0a7590520c3fa24cd19611dfebeb7/msgpack-1.2.0-cp314-cp314t-win_arm64.whl", hash = "sha256:2825bb1da548d214ab8a810906b7dd69a10f3838b615a2cc46e5172d3cb44f6e", size = 71004, upload-time = "2026-06-11T04:16:09.556Z" }, ] [[package]] @@ -3349,36 +3413,36 @@ wheels = [ [[package]] name = "nh3" -version = "0.3.4" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/4e/86/f8d3a7c9bd1bbaa181f6312c757e0b74d25f71ecf84ea3c0dc5e0f01840d/nh3-0.3.4.tar.gz", hash = "sha256:96709a379997c1b28c8974146ca660b0dcd3794f4f6d50c1ea549bab39ac6ade", size = 19520, upload-time = "2026-03-25T10:57:30.789Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/fd/5e/c400663d14be2216bc084ed2befc871b7b12563f85d40904f2a4bf0dd2b7/nh3-0.3.4-cp314-cp314t-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:8b61058f34c2105d44d2a4d4241bacf603a1ef5c143b08766bbd0cf23830118f", size = 1417991, upload-time = "2026-03-25T10:56:59.13Z" }, - { url = "https://files.pythonhosted.org/packages/36/f5/109526f5002ec41322ac8cafd50f0f154bae0c26b9607c0fcb708bdca8ec/nh3-0.3.4-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:554cc2bab281758e94d770c3fb0bf2d8be5fb403ef6b2e8841dd7c1615df7a0f", size = 790566, upload-time = "2026-03-25T10:57:00.445Z" }, - { url = "https://files.pythonhosted.org/packages/7b/66/38950f2b4b316ffd82ee51ed8f9143d1f56fdd620312cacc91613b77b3e7/nh3-0.3.4-cp314-cp314t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:dbe76feaa44e2ef9436f345016012a591550e77818876a8de5c8bc2a248e08df", size = 837538, upload-time = "2026-03-25T10:57:01.848Z" }, - { url = "https://files.pythonhosted.org/packages/d8/9f/9d6da970e9524fe360ea02a2082856390c2c8ba540409d1be6e5851887b3/nh3-0.3.4-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:87dac8d611b4a478400e0821a13b35770e88c266582f065e7249d6a37b0f86e8", size = 1012154, upload-time = "2026-03-25T10:57:03.592Z" }, - { url = "https://files.pythonhosted.org/packages/54/92/7c85c33c241e9dd51dda115bd3f765e940446588cdaaca62ef8edffe675f/nh3-0.3.4-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:8d697e19f2995b337f648204848ac3a528eaafffc39e7ce4ac6b7a2fbe6c84af", size = 1092516, upload-time = "2026-03-25T10:57:04.726Z" }, - { url = "https://files.pythonhosted.org/packages/16/0f/597842bdb2890999a3faa2f3fcb02db8aa6ad09320d3d843ff6d0a1f737b/nh3-0.3.4-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:7cae217f031809321db962cd7e092bda8d4e95a87f78c0226628fa6c2ea8ebc5", size = 1053793, upload-time = "2026-03-25T10:57:06.171Z" }, - { url = "https://files.pythonhosted.org/packages/7d/32/669da65147bc10746d2e1d7a8a3dbfbffe0315f419e74b559e2ee3471a01/nh3-0.3.4-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:07999b998bf89692738f15c0eac76a416382932f855709e0b7488b595c30ec89", size = 1035975, upload-time = "2026-03-25T10:57:07.292Z" }, - { url = "https://files.pythonhosted.org/packages/a1/7e/9e97a8b3c5161c79b4bf21cc54e9334860a52cc54ede15bf2239ef494b73/nh3-0.3.4-cp314-cp314t-win32.whl", hash = "sha256:ca90397c8d36c1535bf1988b2bed006597337843a164c7ec269dc8813f37536b", size = 600419, upload-time = "2026-03-25T10:57:08.342Z" }, - { url = "https://files.pythonhosted.org/packages/e0/c7/6849d8d4295d3997d148eacb2d4b1c9faada4895ee3c1b1e12e72f4611e2/nh3-0.3.4-cp314-cp314t-win_amd64.whl", hash = "sha256:41e46b3499918ab6128b6421677b316e79869d0c140da24069d220a94f4e72d1", size = 613342, upload-time = "2026-03-25T10:57:09.593Z" }, - { url = "https://files.pythonhosted.org/packages/8b/0e/14a3f510f36c20b922c123a2730f071f938d006fb513aacfd46d6cbc03a7/nh3-0.3.4-cp314-cp314t-win_arm64.whl", hash = "sha256:80b955d802bf365bd42e09f6c3d64567dce777d20e97968d94b3e9d9e99b265e", size = 607025, upload-time = "2026-03-25T10:57:10.959Z" }, - { url = "https://files.pythonhosted.org/packages/4a/57/a97955bc95960cfb1f0517043d60a121f4ba93fde252d4d9ffd3c2a9eead/nh3-0.3.4-cp38-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:d8bebcb20ab4b91858385cd98fe58046ec4a624275b45ef9b976475604f45b49", size = 1439519, upload-time = "2026-03-25T10:57:12.019Z" }, - { url = "https://files.pythonhosted.org/packages/2b/60/c9a33361da8cde7c7760f091cd10467bc470634e4eea31c8bb70935b00a4/nh3-0.3.4-cp38-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0d825722a1e8cbc87d7ca1e47ffb1d2a6cf343ad4c1b8465becf7cadcabcdfd0", size = 833798, upload-time = "2026-03-25T10:57:13.264Z" }, - { url = "https://files.pythonhosted.org/packages/6b/19/9487790780b8c94eacca37866c1270b747a4af8e244d43b3b550fddbbf62/nh3-0.3.4-cp38-abi3-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:4aa8b43e68c26b68069a3b6cef09de166d1d7fa140cf8d77e409a46cbf742e44", size = 820414, upload-time = "2026-03-25T10:57:14.236Z" }, - { url = "https://files.pythonhosted.org/packages/6b/b4/c6a340dd321d20b1e4a663307032741da045685c87403926c43656f6f5ec/nh3-0.3.4-cp38-abi3-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:f5f214618ad5eff4f2a6b13a8d4da4d9e7f37c569d90a13fb9f0caaf7d04fe21", size = 1061531, upload-time = "2026-03-25T10:57:15.384Z" }, - { url = "https://files.pythonhosted.org/packages/c4/49/f6b4b474e0032e4bcbb7174b44e4cf6915670e09c62421deb06ccfcb88b8/nh3-0.3.4-cp38-abi3-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3390e4333883673a684ce16c1716b481e91782d6f56dec5c85fed9feedb23382", size = 1021889, upload-time = "2026-03-25T10:57:16.454Z" }, - { url = "https://files.pythonhosted.org/packages/43/da/e52a6941746d1f974752af3fc8591f1dbcdcf7fd8c726c7d99f444ba820e/nh3-0.3.4-cp38-abi3-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:18a2e44ccb29cbb45071b8f3f2dab9ebfb41a6516f328f91f1f1fd18196239a4", size = 912965, upload-time = "2026-03-25T10:57:17.624Z" }, - { url = "https://files.pythonhosted.org/packages/d6/b7/ec1cbc6b297a808c513f59f501656389623fc09ad6a58c640851289c7854/nh3-0.3.4-cp38-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0961a27dc2057c38d0364cb05880e1997ae1c80220cbc847db63213720b8f304", size = 804975, upload-time = "2026-03-25T10:57:18.994Z" }, - { url = "https://files.pythonhosted.org/packages/a9/56/b1275aa2c6510191eed76178da4626b0900402439cb9f27d6b9bf7c6d5e9/nh3-0.3.4-cp38-abi3-manylinux_2_31_riscv64.whl", hash = "sha256:9337517edb7c10228252cce2898e20fb3d77e32ffaccbb3c66897927d74215a0", size = 833400, upload-time = "2026-03-25T10:57:20.086Z" }, - { url = "https://files.pythonhosted.org/packages/7c/a5/5d574ffa3c6e49a5364d1b25ebad165501c055340056671493beb467a15e/nh3-0.3.4-cp38-abi3-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d866701affe67a5171b916b5c076e767a74c6a9efb7fb2006eb8d3c5f9a293d5", size = 854277, upload-time = "2026-03-25T10:57:21.433Z" }, - { url = "https://files.pythonhosted.org/packages/79/36/8aeb2ab21517cefa212db109e41024e02650716cb42bf293d0a88437a92d/nh3-0.3.4-cp38-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:47d749d99ae005ab19517224140b280dd56e77b33afb82f9b600e106d0458003", size = 1022021, upload-time = "2026-03-25T10:57:22.433Z" }, - { url = "https://files.pythonhosted.org/packages/9c/95/9fd860997685e64abe2d5a995ca2eb5004c0fb6d6585429612a7871548b9/nh3-0.3.4-cp38-abi3-musllinux_1_2_armv7l.whl", hash = "sha256:f987cb56458323405e8e5ea827e1befcf141ffa0c0ac797d6d02e6b646056d9a", size = 1103526, upload-time = "2026-03-25T10:57:23.487Z" }, - { url = "https://files.pythonhosted.org/packages/7d/0d/df545070614c1007f0109bb004230226c9000e7857c9785583ec25cda9d7/nh3-0.3.4-cp38-abi3-musllinux_1_2_i686.whl", hash = "sha256:883d5a6d6ee8078c4afc8e96e022fe579c4c265775ff6ee21e39b8c542cabab3", size = 1068050, upload-time = "2026-03-25T10:57:24.624Z" }, - { url = "https://files.pythonhosted.org/packages/94/d5/17b016df52df052f714c53be71df26a1943551d9931e9383b92c998b88f8/nh3-0.3.4-cp38-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:75643c22f5092d8e209f766ee8108c400bc1e44760fc94d2d638eb138d18f853", size = 1046037, upload-time = "2026-03-25T10:57:25.799Z" }, - { url = "https://files.pythonhosted.org/packages/51/39/49f737907e6ab2b4ca71855d3bd63dd7958862e9c8b94fb4e5b18ccf6988/nh3-0.3.4-cp38-abi3-win32.whl", hash = "sha256:72e4e9ca1c4bd41b4a28b0190edc2e21e3f71496acd36a0162858e1a28db3d7e", size = 609542, upload-time = "2026-03-25T10:57:27.112Z" }, - { url = "https://files.pythonhosted.org/packages/73/4f/af8e9071d7464575a7316831938237ffc9d92d27f163dbdd964b1309cd9b/nh3-0.3.4-cp38-abi3-win_amd64.whl", hash = "sha256:c10b1f0c741e257a5cb2978d6bac86e7c784ab20572724b20c6402c2e24bce75", size = 624244, upload-time = "2026-03-25T10:57:28.302Z" }, - { url = "https://files.pythonhosted.org/packages/44/0c/37695d6b0168f6714b5c492331636a9e6123d6ec22d25876c68d06eab1b8/nh3-0.3.4-cp38-abi3-win_arm64.whl", hash = "sha256:43ad4eedee7e049b9069bc015b7b095d320ed6d167ecec111f877de1540656e9", size = 616649, upload-time = "2026-03-25T10:57:29.623Z" }, +version = "0.3.5" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/9c/5f/1d19bdc7d27238e37f3672cdc02cb77c56a4a86d140cd4f4f23c90df6e16/nh3-0.3.5.tar.gz", hash = "sha256:45855e14ff056064fec77133bfcf7cd691838168e5e17bbef075394954dc9dc8", size = 20743, upload-time = "2026-04-25T10:44:16.066Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/63/b0/8587ac42a9627ab88e7e221601f1dfccbf4db80b2a29222ea63266dc9abc/nh3-0.3.5-cp314-cp314t-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:23a312224875f72cd16bde417f49071451877e29ef646a60e50fcb69407cc18a", size = 1420126, upload-time = "2026-04-25T10:43:39.834Z" }, + { url = "https://files.pythonhosted.org/packages/c0/1b/1dbc4d0c43f12e8c1784ede17eaee6f061d4fbe5505757c65c49b2ceab95/nh3-0.3.5-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:387abd011e81959d5a35151a11350a0795c6edeb53ebfa02d2e882dc01299263", size = 793943, upload-time = "2026-04-25T10:43:41.363Z" }, + { url = "https://files.pythonhosted.org/packages/47/9f/d6758d7a14ee964bf439cc35ae4fa24a763a93399c8ef6f22bd11d532d29/nh3-0.3.5-cp314-cp314t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:48f45e3e914be93a596431aa143dedf1582557bf41a58153c296048d6e3798c9", size = 841150, upload-time = "2026-04-25T10:43:43.007Z" }, + { url = "https://files.pythonhosted.org/packages/b6/36/d5d1ae8374612c98f390e1ea7c610fa6c9716259a03bbf4d15b269f40073/nh3-0.3.5-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:0a09f51806fd51b4fedbf9ea2b61fef388f19aef0d62fe51199d41648be14588", size = 1008415, upload-time = "2026-04-25T10:43:44.324Z" }, + { url = "https://files.pythonhosted.org/packages/ba/8f/d13a9c3fd2d9c131a2a281737380e9379eb0f8c33fea24c2b923aaafbb15/nh3-0.3.5-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:c357f1d042c67f135a5e6babb2b0e3b9d9224ff4a3543240f597767b01384ffd", size = 1092706, upload-time = "2026-04-25T10:43:45.653Z" }, + { url = "https://files.pythonhosted.org/packages/bb/57/2f3add7f8680fcc896afa6a675cb2bab09982853ee8af40bad621f6b61c4/nh3-0.3.5-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:38748140bf76383ab7ce2dce0ad4cb663855d8fbc9098f7f3483673d09616a17", size = 1048346, upload-time = "2026-04-25T10:43:46.974Z" }, + { url = "https://files.pythonhosted.org/packages/c1/c3/2f9e4ffa82863074d1361bfe949bc46393d91b3411579dfbbd090b24cac5/nh3-0.3.5-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:84bdeb082544fbcb77a12c034dd77d7da0556fdc0727b787eb6214b958c15e29", size = 1029038, upload-time = "2026-04-25T10:43:48.569Z" }, + { url = "https://files.pythonhosted.org/packages/e8/10/2804deb3f3315184c9cae41702e293c87524b5a21f766b07d7fe3ffbcfbb/nh3-0.3.5-cp314-cp314t-win32.whl", hash = "sha256:c3aae321f67ae66cff2a627115f106a377d4475d10b0e13d97959a13486b9a88", size = 603263, upload-time = "2026-04-25T10:43:49.851Z" }, + { url = "https://files.pythonhosted.org/packages/eb/a2/f6685248b49f7548fc9a8c335ab3a52f68610b72e8a61576447151e4e2e6/nh3-0.3.5-cp314-cp314t-win_amd64.whl", hash = "sha256:c88605d8d468f7fc1b31e06129bc91d6c96f6c621776c9b504a0da9beac9df5f", size = 616866, upload-time = "2026-04-25T10:43:51.005Z" }, + { url = "https://files.pythonhosted.org/packages/ca/b6/d8c9018635d4acfefde6b68470daa510eed715a350cbaa2f928ba0609f81/nh3-0.3.5-cp314-cp314t-win_arm64.whl", hash = "sha256:72c5bdedec27fa33de6a5326346ea8aa3fe54f6ac294d54c4b204fb66a9f1e79", size = 602566, upload-time = "2026-04-25T10:43:52.283Z" }, + { url = "https://files.pythonhosted.org/packages/85/30/d162e99746a2fb1d98bb0ef23af3e201b156cf09f7de867c7390c8fe1c06/nh3-0.3.5-cp38-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:3bb854485c9b33e5bb143ff3e49e577073bc6bc320f0ff8fc316dd89c0d3c101", size = 1442393, upload-time = "2026-04-25T10:43:53.556Z" }, + { url = "https://files.pythonhosted.org/packages/25/8c/072120d506978ab053e1732d0efa7c86cb478fee0ee098fda0ac0d31cb34/nh3-0.3.5-cp38-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:50d401ab2d8e86d59e2126e3ab2a2f45840c405842b626d9a51624b3a33b6878", size = 837722, upload-time = "2026-04-25T10:43:55.073Z" }, + { url = "https://files.pythonhosted.org/packages/52/86/d4e06e28c5ad1c4b065f89737d02631bd49f1660b6ebcf17a87ffcd201da/nh3-0.3.5-cp38-abi3-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:acfd354e61accbe4c74f8017c6e397a776916dfe47c48643cf7fd84ade826f93", size = 822872, upload-time = "2026-04-25T10:43:56.581Z" }, + { url = "https://files.pythonhosted.org/packages/0a/62/50659255213f241ec5797ae7427464c969397373e83b3659372b341ae869/nh3-0.3.5-cp38-abi3-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:52d877980d7ca01dc3baf3936bf844828bc6f332962227a684ed79c18cce14c3", size = 1100031, upload-time = "2026-04-25T10:43:58.098Z" }, + { url = "https://files.pythonhosted.org/packages/00/7a/a12ae77593b2fcf3be25df7bc1c01967d0de448bdb4b6c7ec80fe4f5a74f/nh3-0.3.5-cp38-abi3-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:207c01801d3e9bb8ec08f08689346bdd30ce15b8bf60013a925d08b5388962a4", size = 1057669, upload-time = "2026-04-25T10:43:59.328Z" }, + { url = "https://files.pythonhosted.org/packages/2d/71/5647dc04c0233192a3956fc91708822b21403a06508cacf78083c68e7bf0/nh3-0.3.5-cp38-abi3-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ea232933394d1d58bf7c4bb348dc4660eae6604e1ae81cd2ba6d9ed80d390f3b", size = 914795, upload-time = "2026-04-25T10:44:00.52Z" }, + { url = "https://files.pythonhosted.org/packages/1b/0e/bf298920729f216adcb002acf7ea01b90842603d2e4e2ce9b900d9ee8fab/nh3-0.3.5-cp38-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fe3a787dc76b50de6bee54ef242f26c41dfe47654428e3e94f0fae5bb6dd2cc1", size = 806976, upload-time = "2026-04-25T10:44:01.743Z" }, + { url = "https://files.pythonhosted.org/packages/85/01/26761e1dc2b848e65a62c19e5d39ad446283287cd4afddc89f364ab86bc9/nh3-0.3.5-cp38-abi3-manylinux_2_31_riscv64.whl", hash = "sha256:488928988caad25ba14b1eb5bc74e25e21f3b5e40341d956f3ce4a8bc19460dc", size = 834904, upload-time = "2026-04-25T10:44:03.454Z" }, + { url = "https://files.pythonhosted.org/packages/33/53/0766113e679540ac1edc1b82b1295aecd321eeb75d6fead70109a838b6ee/nh3-0.3.5-cp38-abi3-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2c069570b06aa848457713ad7af4a9905691291548c4466a9ad78ee95808382b", size = 857159, upload-time = "2026-04-25T10:44:05.003Z" }, + { url = "https://files.pythonhosted.org/packages/58/36/734d353dfaf292fed574b8b3092f0ef79dc6404f3879f7faaa61a4701fad/nh3-0.3.5-cp38-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:eeedc90ed8c42c327e8e10e621ccfa314fc6cce35d5929f4297ff1cdb89667c4", size = 1018600, upload-time = "2026-04-25T10:44:06.18Z" }, + { url = "https://files.pythonhosted.org/packages/6b/aa/d9c59c1b49669fcb7bababa55df82385f029ad5c2651f583c3a1141cfdd1/nh3-0.3.5-cp38-abi3-musllinux_1_2_armv7l.whl", hash = "sha256:de8e8621853b6470fe928c684ee0d3f39ea8086cebafe4c416486488dea7b68d", size = 1103530, upload-time = "2026-04-25T10:44:07.68Z" }, + { url = "https://files.pythonhosted.org/packages/90/b0/cdd210bfb8d9d43fb02fc3c868336b9955934d8e15e66eb1d15a147b8af0/nh3-0.3.5-cp38-abi3-musllinux_1_2_i686.whl", hash = "sha256:6ea58cc44d274c643b83547ca9654a0b1a817609b160601356f76a2b744c49ad", size = 1061754, upload-time = "2026-04-25T10:44:09.362Z" }, + { url = "https://files.pythonhosted.org/packages/ce/cb/7a39e72e668c8445bdd95e494b3e21cfdddc68329be8ea3522c8befb46c4/nh3-0.3.5-cp38-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:e49c9b564e6bcb03ecd2f057213df9a0de15a95812ac9db9600b590db23d3ae9", size = 1040938, upload-time = "2026-04-25T10:44:10.775Z" }, + { url = "https://files.pythonhosted.org/packages/af/4c/fc2f9ed208a3801a319f59b5fea03cdc20cf3bd8af14be930d3a8de01224/nh3-0.3.5-cp38-abi3-win32.whl", hash = "sha256:559e4c73b689e9a7aa97ac9760b1bc488038d7c1a575aa4ab5a0e19ee9630c0f", size = 611445, upload-time = "2026-04-25T10:44:12.317Z" }, + { url = "https://files.pythonhosted.org/packages/db/1a/e4c9b5e2ae13e6092c9ec16d8ca30646cb01fcdea245f36c5b08fd21fbd5/nh3-0.3.5-cp38-abi3-win_amd64.whl", hash = "sha256:45e6a65dc88a300a2e3502cb9c8e6d1d6b831d6fba7470643333609c6aab1f30", size = 626502, upload-time = "2026-04-25T10:44:13.682Z" }, + { url = "https://files.pythonhosted.org/packages/80/7c/19cd0671d1ba2762fb388fc149697d20d0568ccfeef833b11280a619e526/nh3-0.3.5-cp38-abi3-win_arm64.whl", hash = "sha256:8f85285700a18e9f3fc5bff41fe573fa84f81542ef13b48a89f9fecca0474d3b", size = 611069, upload-time = "2026-04-25T10:44:14.934Z" }, ] [[package]] @@ -3392,23 +3456,23 @@ wheels = [ [[package]] name = "nodejs-wheel-binaries" -version = "24.15.0" +version = "24.16.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/3f/70/a1e4f4d5986768ab90cc860b1cc3660fd2ded74ca175a900a5c29f839c7d/nodejs_wheel_binaries-24.15.0.tar.gz", hash = "sha256:b43f5c4f6e5768d8845b2ae4682eb703a19bf7aadc84187e2d903ed3a611c859", size = 8057, upload-time = "2026-04-19T15:48:16.899Z" } +sdist = { url = "https://files.pythonhosted.org/packages/a3/22/2a5beb4e21417c73233d9f65cf6f3e96e891b80d2f550a8f630ebc6b88c6/nodejs_wheel_binaries-24.16.0.tar.gz", hash = "sha256:c973cb69dc5fd16e6f6dc6e579e2c3d5534e2a1f57619dddf5ba070efa7dde37", size = 8056, upload-time = "2026-05-30T16:52:09.807Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/85/66/54051d14853d6ab4fb85f8be9b042b530be653357fb9a19557498bc91ab7/nodejs_wheel_binaries-24.15.0-py2.py3-none-macosx_13_0_arm64.whl", hash = "sha256:a6232fa8b754220941f52388c8ead923f7c1c7fdf0ea0d98f657523bd9a81ef4", size = 55173485, upload-time = "2026-04-19T15:47:34.561Z" }, - { url = "https://files.pythonhosted.org/packages/ad/5f/66acada164da5ca10a0824db021aa7394ae18396c550cd9280e839a43126/nodejs_wheel_binaries-24.15.0-py2.py3-none-macosx_13_0_x86_64.whl", hash = "sha256:001a6b62c69d9109c1738163cca00608dd2722e8663af59300054ea02610972d", size = 55348100, upload-time = "2026-04-19T15:47:40.521Z" }, - { url = "https://files.pythonhosted.org/packages/0d/2d/0cbd5ff40c9bb030ca1735d8f8793bd74f08a4cbd49100a1d19313ea57ab/nodejs_wheel_binaries-24.15.0-py2.py3-none-manylinux_2_28_aarch64.whl", hash = "sha256:0fbc48765e60ed0ff30d43898dbf5cadbadf2e5f1e7f204afc2b01493b7ebce6", size = 59668206, upload-time = "2026-04-19T15:47:46.848Z" }, - { url = "https://files.pythonhosted.org/packages/da/d5/91ac63951ec75927a486b83b8cafe650e360fa70ac01dc94adfb32b93b97/nodejs_wheel_binaries-24.15.0-py2.py3-none-manylinux_2_28_x86_64.whl", hash = "sha256:20ee0536809795da8a4942fc1ab4cbdebbcaaf29383eab67ba8874268fb00008", size = 60206736, upload-time = "2026-04-19T15:47:52.668Z" }, - { url = "https://files.pythonhosted.org/packages/db/72/dc22776974d928869c0c30d23ee98ed7df254243c2df68f09f5963e8e8b8/nodejs_wheel_binaries-24.15.0-py2.py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:1fade6c214285e72472ca40a631e98ff36559671cd5eefc8bf009471d67f04b4", size = 61720456, upload-time = "2026-04-19T15:47:58.325Z" }, - { url = "https://files.pythonhosted.org/packages/01/0a/34461b9050cb45ee371dccdefc622aef6351506ea2691b08fc761ca67150/nodejs_wheel_binaries-24.15.0-py2.py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:3984cb8d87766567aee67a49743227ab40ede6f47734ec990ff90e50b74e7740", size = 62326172, upload-time = "2026-04-19T15:48:04.094Z" }, - { url = "https://files.pythonhosted.org/packages/c9/17/09252bf35672dba926649d59dfe51443a0f6955ad13784e91131d5ec82a2/nodejs_wheel_binaries-24.15.0-py2.py3-none-win_amd64.whl", hash = "sha256:a437601956b532dcb3082046e6978e622733f90edc0932cbb9adb3bb97a16501", size = 41543461, upload-time = "2026-04-19T15:48:09.332Z" }, - { url = "https://files.pythonhosted.org/packages/0a/7e/b649777d148e1e0c2ce349156603cdb12f7ed99921b95d93717393650193/nodejs_wheel_binaries-24.15.0-py2.py3-none-win_arm64.whl", hash = "sha256:bdf4a431e08321a32efc604111c6f23941f87055d796a537e8c4110daecad23f", size = 39233248, upload-time = "2026-04-19T15:48:13.326Z" }, + { url = "https://files.pythonhosted.org/packages/83/d1/68b43b53cd0fa83ae6fd406705023ca988d9e0ca41c724d82e66fbeb2ef6/nodejs_wheel_binaries-24.16.0-py2.py3-none-macosx_13_0_arm64.whl", hash = "sha256:d9f8f677dcf30e37ac244f07869726abe043f01eb0f45722b1df31cc2af7093c", size = 55666374, upload-time = "2026-05-30T16:51:39.588Z" }, + { url = "https://files.pythonhosted.org/packages/e9/b2/40a989159599080da485de966c4c2d207e852ac7aa7864702626d96c8bf5/nodejs_wheel_binaries-24.16.0-py2.py3-none-macosx_13_0_x86_64.whl", hash = "sha256:3d0370fe7120ce9697a4f60d40480d2bd8808d9f30131458d5afc0040d4e5a51", size = 55838487, upload-time = "2026-05-30T16:51:43.383Z" }, + { url = "https://files.pythonhosted.org/packages/d7/a7/cd42174fb5ff6faff7fa8d326a18914d8f232098ab5de055b57c16fa13ca/nodejs_wheel_binaries-24.16.0-py2.py3-none-manylinux_2_28_aarch64.whl", hash = "sha256:85dc92bbb79c851569c5925dcc2a4c915a034efab375f99e4e7e6bbe9cca8342", size = 60179540, upload-time = "2026-05-30T16:51:47.036Z" }, + { url = "https://files.pythonhosted.org/packages/2b/95/c8a1f9ae140aa28df8744d984d01d4b3af7cdd6555af12127f40ceb45a7d/nodejs_wheel_binaries-24.16.0-py2.py3-none-manylinux_2_28_x86_64.whl", hash = "sha256:2f3036292811514ba847b3708492644764f88a833ac425c5f55007014308ddfd", size = 60716262, upload-time = "2026-05-30T16:51:50.711Z" }, + { url = "https://files.pythonhosted.org/packages/64/c9/7c35b3737f59e36d0249c265397b7bff570519b95301d6e16ea361e904ad/nodejs_wheel_binaries-24.16.0-py2.py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:db8a8a76ebd2b28ecbfc9ad464baa3707241b9e050a30e2efdf6f60c0f886502", size = 62230592, upload-time = "2026-05-30T16:51:55Z" }, + { url = "https://files.pythonhosted.org/packages/04/96/d931255cf9d11a84d6b54d882dba7434646467d568ccf070ea3418638df3/nodejs_wheel_binaries-24.16.0-py2.py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:f1a3d8f7b4491cbbd023ba3fc4e901fcca2d9fb80d57f24ba3890de8b1dbac03", size = 62841759, upload-time = "2026-05-30T16:51:59.407Z" }, + { url = "https://files.pythonhosted.org/packages/a2/7b/8b7a3f41bc255411be30b6d7d288aab8ffd9ea2055db8555ced3548007b9/nodejs_wheel_binaries-24.16.0-py2.py3-none-win_amd64.whl", hash = "sha256:bb136be9944f0662dcf1120f45193a6b75b13fac378971a95cc42c9f879a81aa", size = 42027734, upload-time = "2026-05-30T16:52:03.348Z" }, + { url = "https://files.pythonhosted.org/packages/17/66/1ed71f1f529b8ca727d42c7ceb9db0bef145ce4a13dfc86fb50aa44f3be6/nodejs_wheel_binaries-24.16.0-py2.py3-none-win_arm64.whl", hash = "sha256:8308940b5edd0a50dc5267ea36ba21c9f668e83fe0d9f293937174d3a7e31c36", size = 39714528, upload-time = "2026-05-30T16:52:06.421Z" }, ] [[package]] name = "openai" -version = "2.37.0" +version = "2.41.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "anyio" }, @@ -3420,14 +3484,14 @@ dependencies = [ { name = "tqdm" }, { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/32/50/5901f01ef14e6c27788beb91e54fef5d6204fb5fb9e97402fc8a14de2e32/openai-2.37.0.tar.gz", hash = "sha256:f4bc562cc5f3a43d40d678105572d9d44765f6e0f50c125f63055419b72f4bd9", size = 754706, upload-time = "2026-05-15T22:30:35.428Z" } +sdist = { url = "https://files.pythonhosted.org/packages/40/36/4c926a91554483977608951360c18c2e911592785eb87a6437813f6123f7/openai-2.41.1.tar.gz", hash = "sha256:23d617a0432457ad844973bee8f540be9da90894f7c5686852d2d365da058f57", size = 783584, upload-time = "2026-06-10T16:10:37.667Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/ed/4c/bce61680d0699a78a405fd9a67989b175ba020590428831aab2ab1d2be7c/openai-2.37.0-py3-none-any.whl", hash = "sha256:814633888b8f3b1ffd6615697c6e4ef93632d08b7c2e28c8c5ef3556e5a10107", size = 1303238, upload-time = "2026-05-15T22:30:32.767Z" }, + { url = "https://files.pythonhosted.org/packages/20/74/925d7b3892927e9804aaf58d374a45dc28e4420ff90e992272b77286343e/openai-2.41.1-py3-none-any.whl", hash = "sha256:a939565f350cb7443cb843b801b88c716ac8024b492fb94ca269d5f6b1bbefd6", size = 1353380, upload-time = "2026-06-10T16:10:35.756Z" }, ] [[package]] name = "openai-agents" -version = "0.17.5" +version = "0.17.7" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "griffelib" }, @@ -3435,13 +3499,12 @@ dependencies = [ { name = "openai" }, { name = "pydantic" }, { name = "requests" }, - { name = "types-requests" }, { name = "typing-extensions" }, { name = "websockets" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/72/fe/ef185f2a21f2fba1b0b107f72a7646bb51369d4c4025e2ab4d1ec65764f3/openai_agents-0.17.5.tar.gz", hash = "sha256:5dd46943b993e1a68a78acd254fc6a00cf0455fc3dcc802078ea26964b14278c", size = 5420036, upload-time = "2026-06-11T04:12:35.775Z" } +sdist = { url = "https://files.pythonhosted.org/packages/d4/b2/235cbfdefe86623fc77f65fc1d016686372f61d4a1bf3fc66151de2eb847/openai_agents-0.17.7.tar.gz", hash = "sha256:ca76e7f882c9d8f06e3dfb8064cc33bcb5a5f34a29816cb9af863f395964ff0c", size = 5485068, upload-time = "2026-06-24T05:15:33.705Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/b9/f0/9184cd6d3d089a568fc544f1c7f0965d63818fa310c912b30abd333ea138/openai_agents-0.17.5-py3-none-any.whl", hash = "sha256:9afa8a67f0b9fbcdfd2d1545b38d3c52d47e4182921cb79952ad61580d950973", size = 846844, upload-time = "2026-06-11T04:12:32.485Z" }, + { url = "https://files.pythonhosted.org/packages/1e/2e/2e96ca6928951fe1d16744c22dc1355eda1dd5b0dd920ca1d3ab602929f8/openai_agents-0.17.7-py3-none-any.whl", hash = "sha256:51b5ae43756eea37032e430f95979ba3999af6b1ade397df6c0ffeaf1939646a", size = 856074, upload-time = "2026-06-24T05:15:31.741Z" }, ] [package.optional-dependencies] @@ -3485,7 +3548,7 @@ wheels = [ [[package]] name = "openinference-instrumentation" -version = "0.1.47" +version = "0.1.53" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "openinference-semantic-conventions" }, @@ -3493,14 +3556,14 @@ dependencies = [ { name = "opentelemetry-sdk" }, { name = "wrapt" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/18/d4/390c47304f172161e7d1ccdf6e4d02bc3f5612741a6768d652eb264b2edc/openinference_instrumentation-0.1.47.tar.gz", hash = "sha256:4f68930d974c04bdf765b31262fd8ec35c3b6b1b24dbbadbbdec2c685024b06b", size = 23931, upload-time = "2026-04-22T00:39:25.472Z" } +sdist = { url = "https://files.pythonhosted.org/packages/f9/b6/c0e7e047ae4962f2755a3bc9141fdd6272c75c74e47dfc6aa71978a9b78f/openinference_instrumentation-0.1.53.tar.gz", hash = "sha256:3c0c145cf6e13cfa630b29d0e3ca806f3821470ffca7922f1590e3970fadd4da", size = 33712, upload-time = "2026-06-02T16:37:21.771Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/1a/83/31420c5f503fec0f6b3cc66d9a93a10b656ce77bbe16421cdb4aad5b12fe/openinference_instrumentation-0.1.47-py3-none-any.whl", hash = "sha256:8496b29de79d0ceb7a7e5a523920da73351f192800fddd43aebc23c58d5586b9", size = 30112, upload-time = "2026-04-22T00:39:24.561Z" }, + { url = "https://files.pythonhosted.org/packages/13/bb/01262d9945c476e15aa21bb9ca05b18604e525d73d9761cadb677f485198/openinference_instrumentation-0.1.53-py3-none-any.whl", hash = "sha256:f43695080eded47b1e03ff1b19cb5c23ea4409459cfe16c5b5748d5656832eb1", size = 40958, upload-time = "2026-06-02T16:37:20.69Z" }, ] [[package]] name = "openinference-instrumentation-google-adk" -version = "0.1.11" +version = "0.1.15" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "openinference-instrumentation" }, @@ -3511,14 +3574,14 @@ dependencies = [ { name = "typing-extensions" }, { name = "wrapt" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/79/7e/a6a6c7dc7bd01e098374cdee69b10b6586d2f7a481ed34f8a283fcbfd830/openinference_instrumentation_google_adk-0.1.11.tar.gz", hash = "sha256:b36310d4e8b8143d41fe5c74be04c09f367710ec8019471f232bb721ede143b1", size = 14473, upload-time = "2026-05-05T06:43:34.828Z" } +sdist = { url = "https://files.pythonhosted.org/packages/1b/1a/f35f3f38dba763e3ab41a73c15125de6107b3dd1aacbff50201b945e7d89/openinference_instrumentation_google_adk-0.1.15.tar.gz", hash = "sha256:1c0c73ad3b128858486f2066ceba3690061cbb8755bcd97a58220d9a5a42cf8e", size = 14739, upload-time = "2026-05-22T21:10:48.449Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/c7/51/0d4df97fd0fb3ac2282dc268e9a11f82523f881e623264291d6abf2fd5ed/openinference_instrumentation_google_adk-0.1.11-py3-none-any.whl", hash = "sha256:8dd546f9db3a6589106287b8a99b99f06361ac95e6e0b32305e6ce1a76f98630", size = 16384, upload-time = "2026-05-05T06:43:33.836Z" }, + { url = "https://files.pythonhosted.org/packages/49/24/dbddd058a5b837c5f50a42dd94b4d9e338dc362c3cf067a6620c18a7f5c3/openinference_instrumentation_google_adk-0.1.15-py3-none-any.whl", hash = "sha256:be6db6bb68922acae5103bbb72fda9b880a809309b49289fa23d685742de8ebe", size = 16661, upload-time = "2026-05-22T21:10:46.054Z" }, ] [[package]] name = "openinference-instrumentation-openai-agents" -version = "1.4.1" +version = "1.6.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "openinference-instrumentation" }, @@ -3529,36 +3592,36 @@ dependencies = [ { name = "typing-extensions" }, { name = "wrapt" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/0f/95/9ace0fa5c1455f24b3c6e9c54ff7fbfab752abd66deccd3689f31d9200d3/openinference_instrumentation_openai_agents-1.4.1.tar.gz", hash = "sha256:145741867f809a04fa4640adc188e65e745ed9e3b306f811c3ecd994346f8cca", size = 12783, upload-time = "2026-04-03T21:21:26.042Z" } +sdist = { url = "https://files.pythonhosted.org/packages/cc/6f/281a267b837d33505c8b4ef70644b8ebfeb7ed902a909200333916185851/openinference_instrumentation_openai_agents-1.6.1.tar.gz", hash = "sha256:39b211b7ff28d59a401b2659f3885f967fb3e17580b29b4b4aedac6b8fc98e0e", size = 26089, upload-time = "2026-06-05T19:54:22.737Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/aa/5a/1e42244b23fba3d785f792fc2783264d3eae033eb785ec9fde260adf81d9/openinference_instrumentation_openai_agents-1.4.1-py3-none-any.whl", hash = "sha256:834c7cbaba2fdd3d2ce75967ef1d9f946e5f29aa8833d69c33d6fb2c85c65896", size = 14489, upload-time = "2026-04-03T21:21:24.892Z" }, + { url = "https://files.pythonhosted.org/packages/08/54/c3d4e67bdad5170e315bb03086f034d2a60ccb26c4200010428456c9f4d6/openinference_instrumentation_openai_agents-1.6.1-py3-none-any.whl", hash = "sha256:ca5dc650fc53461cbce0f8f19bfa78d43de605c439a9d3c44d99fd0b6e10e3ba", size = 28466, upload-time = "2026-06-05T19:54:21.48Z" }, ] [[package]] name = "openinference-semantic-conventions" -version = "0.1.29" +version = "0.1.30" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/15/6b/9ed67f9ce8c92436b297207abde730800b00bdec7e114f71b8dfe91cd26b/openinference_semantic_conventions-0.1.29.tar.gz", hash = "sha256:bbeb6472777a45a574169894bb9c4d80c6832a8befd32ab238cb875438ce1044", size = 12959, upload-time = "2026-04-22T00:39:27.916Z" } +sdist = { url = "https://files.pythonhosted.org/packages/2c/51/8ba1182ee86fc79793d5ff2d11e7fdcda10ded2d01f3e46ca6fcf0568213/openinference_semantic_conventions-0.1.30.tar.gz", hash = "sha256:81fece76e09c83789e35c393b8b30523481eeabf1008745b955631a53e3221d9", size = 13391, upload-time = "2026-05-22T21:10:44.065Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/be/7b/45ad1b95315b5563baa7338c8e8088bb1af66905c46e1bd1fe6ecbe30ea8/openinference_semantic_conventions-0.1.29-py3-none-any.whl", hash = "sha256:f45e0b1cf79fe407af4722bcf391a01565f0878c95be3ebcc9382245d0367cc5", size = 10582, upload-time = "2026-04-22T00:39:27.066Z" }, + { url = "https://files.pythonhosted.org/packages/b6/76/5b7e78cf0de38589b821bbe8e9c29c59a6e76edfb980488d0854cbb90f7c/openinference_semantic_conventions-0.1.30-py3-none-any.whl", hash = "sha256:36d946d3f95f699b7c4b12324ae9c1f02d6c7750df11eece56aa159cff430b3d", size = 10911, upload-time = "2026-05-22T21:10:43.04Z" }, ] [[package]] name = "opentelemetry-api" -version = "1.38.0" +version = "1.41.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "importlib-metadata" }, { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/08/d8/0f354c375628e048bd0570645b310797299754730079853095bf000fba69/opentelemetry_api-1.38.0.tar.gz", hash = "sha256:f4c193b5e8acb0912b06ac5b16321908dd0843d75049c091487322284a3eea12", size = 65242, upload-time = "2025-10-16T08:35:50.25Z" } +sdist = { url = "https://files.pythonhosted.org/packages/fa/fc/b7564cbef36601aef0d6c9bc01f7badb64be8e862c2e1c3c5c3b43b53e4f/opentelemetry_api-1.41.1.tar.gz", hash = "sha256:0ad1814d73b875f84494387dae86ce0b12c68556331ce6ce8fe789197c949621", size = 71416, upload-time = "2026-04-24T13:15:38.262Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/ae/a2/d86e01c28300bd41bab8f18afd613676e2bd63515417b77636fc1add426f/opentelemetry_api-1.38.0-py3-none-any.whl", hash = "sha256:2891b0197f47124454ab9f0cf58f3be33faca394457ac3e09daba13ff50aa582", size = 65947, upload-time = "2025-10-16T08:35:30.23Z" }, + { 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.11.0a0" +version = "1.12.0a0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "google-cloud-logging" }, @@ -3566,14 +3629,14 @@ dependencies = [ { name = "opentelemetry-resourcedetector-gcp" }, { name = "opentelemetry-sdk" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/72/2d/6aa7063b009768d8f9415b36a29ae9b3eb1e2c5eff70f58ca15e104c245f/opentelemetry_exporter_gcp_logging-1.11.0a0.tar.gz", hash = "sha256:58496f11b930c84570060ffbd4343cd0b597ea13c7bc5c879df01163dd552f14", size = 22400, upload-time = "2025-11-04T19:32:13.812Z" } +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/a4/b7/2d3df53fa39bfd52f88c78a60367d45a7b1adbf8a756cce62d6ac149d49a/opentelemetry_exporter_gcp_logging-1.11.0a0-py3-none-any.whl", hash = "sha256:f8357c552947cb9c0101c4575a7702b8d3268e28bdeefdd1405cf838e128c6ef", size = 14168, upload-time = "2025-11-04T19:32:07.073Z" }, + { 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.11.0a0" +version = "1.12.0a0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "google-cloud-monitoring" }, @@ -3581,14 +3644,14 @@ dependencies = [ { name = "opentelemetry-resourcedetector-gcp" }, { name = "opentelemetry-sdk" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/3f/48/d1c7d2380bb1754d1eb6a011a2e0de08c6868cb6c0f34bcda0444fa0d614/opentelemetry_exporter_gcp_monitoring-1.11.0a0.tar.gz", hash = "sha256:386276eddbbd978a6f30fafd3397975beeb02a1302bdad554185242a8e2c343c", size = 20828, upload-time = "2025-11-04T19:32:14.522Z" } +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/8c/8c/03a6e73e270a9c890dbd6cc1c47c83d86b8a8a974a9168d92e043c6277cc/opentelemetry_exporter_gcp_monitoring-1.11.0a0-py3-none-any.whl", hash = "sha256:b6740cba61b2f9555274829fe87a58447b64d0378f1067a4faebb4f5b364ca22", size = 13611, upload-time = "2025-11-04T19:32:08.212Z" }, + { 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.11.0" +version = "1.12.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "google-cloud-trace" }, @@ -3596,26 +3659,26 @@ dependencies = [ { name = "opentelemetry-resourcedetector-gcp" }, { name = "opentelemetry-sdk" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/10/9c/4c3b26e5494f8b53c7873732a2317df905abe2b8ab33e9edfcbd5a8ff79b/opentelemetry_exporter_gcp_trace-1.11.0.tar.gz", hash = "sha256:c947ab4ab53e16517ade23d6fe71fe88cf7ca3f57a42c9f0e4162d2b929fecb6", size = 18770, upload-time = "2025-11-04T19:32:15.109Z" } +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/5f/4a/876703e8c5845198d95cd4006c8d1b2e3b129a9e288558e33133360f8d5d/opentelemetry_exporter_gcp_trace-1.11.0-py3-none-any.whl", hash = "sha256:b3dcb314e1a9985e9185cb7720b693eb393886fde98ae4c095ffc0893de6cefa", size = 14016, upload-time = "2025-11-04T19:32:09.009Z" }, + { 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.38.0" +version = "1.41.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "opentelemetry-proto" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/19/83/dd4660f2956ff88ed071e9e0e36e830df14b8c5dc06722dbde1841accbe8/opentelemetry_exporter_otlp_proto_common-1.38.0.tar.gz", hash = "sha256:e333278afab4695aa8114eeb7bf4e44e65c6607d54968271a249c180b2cb605c", size = 20431, upload-time = "2025-10-16T08:35:53.285Z" } +sdist = { url = "https://files.pythonhosted.org/packages/ae/fa/f9e3bd3c4d692b3ce9a2880a167d1f79681a1bea11f00d5bf76adc03e6ea/opentelemetry_exporter_otlp_proto_common-1.41.1.tar.gz", hash = "sha256:0e253156ea9c36b0bd3d2440c5c9ba7dd1f3fb64ba7a08fc85fbac536b56e1fb", size = 20409, upload-time = "2026-04-24T13:15:40.924Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/a7/9e/55a41c9601191e8cd8eb626b54ee6827b9c9d4a46d736f32abc80d8039fc/opentelemetry_exporter_otlp_proto_common-1.38.0-py3-none-any.whl", hash = "sha256:03cb76ab213300fe4f4c62b7d8f17d97fcfd21b89f0b5ce38ea156327ddda74a", size = 18359, upload-time = "2025-10-16T08:35:34.099Z" }, + { url = "https://files.pythonhosted.org/packages/29/48/bce76d3ea772b609757e9bc844e02ab408a6446609bf74fb562062ba6b71/opentelemetry_exporter_otlp_proto_common-1.41.1-py3-none-any.whl", hash = "sha256:10da74dad6a49344b9b7b21b6182e3060373a235fde1528616d5f01f92e66aa9", size = 18366, upload-time = "2026-04-24T13:15:18.917Z" }, ] [[package]] name = "opentelemetry-exporter-otlp-proto-grpc" -version = "1.38.0" +version = "1.41.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "googleapis-common-protos" }, @@ -3626,14 +3689,14 @@ dependencies = [ { name = "opentelemetry-sdk" }, { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/a2/c0/43222f5b97dc10812bc4f0abc5dc7cd0a2525a91b5151d26c9e2e958f52e/opentelemetry_exporter_otlp_proto_grpc-1.38.0.tar.gz", hash = "sha256:2473935e9eac71f401de6101d37d6f3f0f1831db92b953c7dcc912536158ebd6", size = 24676, upload-time = "2025-10-16T08:35:53.83Z" } +sdist = { url = "https://files.pythonhosted.org/packages/1e/9b/e4503060b8695579dbaad187dc8cef4554188de68748c88060599b77489e/opentelemetry_exporter_otlp_proto_grpc-1.41.1.tar.gz", hash = "sha256:b05df8fa1333dc9a3fda36b676b96b5095ab6016d3f0c3296d430d629ba1443b", size = 25755, upload-time = "2026-04-24T13:15:41.93Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/28/f0/bd831afbdba74ca2ce3982142a2fad707f8c487e8a3b6fef01f1d5945d1b/opentelemetry_exporter_otlp_proto_grpc-1.38.0-py3-none-any.whl", hash = "sha256:7c49fd9b4bd0dbe9ba13d91f764c2d20b0025649a6e4ac35792fb8d84d764bc7", size = 19695, upload-time = "2025-10-16T08:35:35.053Z" }, + { 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.38.0" +version = "1.41.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "googleapis-common-protos" }, @@ -3644,14 +3707,14 @@ dependencies = [ { name = "requests" }, { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/81/0a/debcdfb029fbd1ccd1563f7c287b89a6f7bef3b2902ade56797bfd020854/opentelemetry_exporter_otlp_proto_http-1.38.0.tar.gz", hash = "sha256:f16bd44baf15cbe07633c5112ffc68229d0edbeac7b37610be0b2def4e21e90b", size = 17282, upload-time = "2025-10-16T08:35:54.422Z" } +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/e5/77/154004c99fb9f291f74aa0822a2f5bbf565a72d8126b3a1b63ed8e5f83c7/opentelemetry_exporter_otlp_proto_http-1.38.0-py3-none-any.whl", hash = "sha256:84b937305edfc563f08ec69b9cb2298be8188371217e867c1854d77198d0825b", size = 19579, upload-time = "2025-10-16T08:35:36.269Z" }, + { 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.59b0" +version = "0.62b1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "opentelemetry-api" }, @@ -3659,40 +3722,40 @@ dependencies = [ { name = "packaging" }, { name = "wrapt" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/04/ed/9c65cd209407fd807fa05be03ee30f159bdac8d59e7ea16a8fe5a1601222/opentelemetry_instrumentation-0.59b0.tar.gz", hash = "sha256:6010f0faaacdaf7c4dff8aac84e226d23437b331dcda7e70367f6d73a7db1adc", size = 31544, upload-time = "2025-10-16T08:39:31.959Z" } +sdist = { url = "https://files.pythonhosted.org/packages/52/cb/0523b92c112a6cc70be43724343dc45225d3af134419844d7879a07755d4/opentelemetry_instrumentation-0.62b1.tar.gz", hash = "sha256:90e92a905ba4f84db06ac3aec96701df6c079b2d66e9379f8739f0a1bdcc7f45", size = 34043, upload-time = "2026-04-24T13:22:31.997Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/10/f5/7a40ff3f62bfe715dad2f633d7f1174ba1a7dd74254c15b2558b3401262a/opentelemetry_instrumentation-0.59b0-py3-none-any.whl", hash = "sha256:44082cc8fe56b0186e87ee8f7c17c327c4c2ce93bdbe86496e600985d74368ee", size = 33020, upload-time = "2025-10-16T08:38:31.463Z" }, + { url = "https://files.pythonhosted.org/packages/4d/0f/45adbaea1f81b847cffdcee4f4b5f89297e42facf7fac78c7aaac4c38e75/opentelemetry_instrumentation-0.62b1-py3-none-any.whl", hash = "sha256:976fc6e640f2006599e97429c949e622c108d0c17c2059347d1e6c93c707f257", size = 34163, upload-time = "2026-04-24T13:21:31.722Z" }, ] [[package]] name = "opentelemetry-instrumentation-threading" -version = "0.59b0" +version = "0.62b1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "opentelemetry-api" }, { name = "opentelemetry-instrumentation" }, { name = "wrapt" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/82/7a/84e97d8992808197006e607ae410c2219bdbbc23d1289ba0c244d3220741/opentelemetry_instrumentation_threading-0.59b0.tar.gz", hash = "sha256:ce5658730b697dcbc0e0d6d13643a69fd8aeb1b32fa8db3bade8ce114c7975f3", size = 8770, upload-time = "2025-10-16T08:40:03.587Z" } +sdist = { url = "https://files.pythonhosted.org/packages/e7/2d/2537d5990fa341198cbc8ae70b2c3637037061b8ab1196af1d924a275f55/opentelemetry_instrumentation_threading-0.62b1.tar.gz", hash = "sha256:4b3c876907657e3b8b977bfe15d248f2c02db56302c51883724e7ac2f8ce26d2", size = 9180, upload-time = "2026-04-24T13:23:06.15Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/b8/50/32d29076aaa1c91983cdd3ca8c6bb4d344830cd7d87a7c0fdc2d98c58509/opentelemetry_instrumentation_threading-0.59b0-py3-none-any.whl", hash = "sha256:76da2fc01fe1dccebff6581080cff9e42ac7b27cc61eb563f3c4435c727e8eca", size = 9313, upload-time = "2025-10-16T08:39:15.876Z" }, + { url = "https://files.pythonhosted.org/packages/aa/37/a80fb13b76f85b4e433ff44b4ba177615823c36c28dca12e94d2c37de681/opentelemetry_instrumentation_threading-0.62b1-py3-none-any.whl", hash = "sha256:4596e79c47de122eb2e85877c1a8bfed1cd6ab06bd2c29d120ebcf8a708a433a", size = 9335, upload-time = "2026-04-24T13:22:19.419Z" }, ] [[package]] name = "opentelemetry-proto" -version = "1.38.0" +version = "1.41.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "protobuf" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/51/14/f0c4f0f6371b9cb7f9fa9ee8918bfd59ac7040c7791f1e6da32a1839780d/opentelemetry_proto-1.38.0.tar.gz", hash = "sha256:88b161e89d9d372ce723da289b7da74c3a8354a8e5359992be813942969ed468", size = 46152, upload-time = "2025-10-16T08:36:01.612Z" } +sdist = { url = "https://files.pythonhosted.org/packages/99/e8/633c6d8a9c8840338b105907e55c32d3da1983abab5e52f899f72a82c3d1/opentelemetry_proto-1.41.1.tar.gz", hash = "sha256:4b9d2eb631237ea43b80e16c073af438554e32bc7e9e3f8ca4a9582f900020e5", size = 45670, upload-time = "2026-04-24T13:15:49.768Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/b6/6a/82b68b14efca5150b2632f3692d627afa76b77378c4999f2648979409528/opentelemetry_proto-1.38.0-py3-none-any.whl", hash = "sha256:b6ebe54d3217c42e45462e2a1ae28c3e2bf2ec5a5645236a490f55f45f1a0a18", size = 72535, upload-time = "2025-10-16T08:35:45.749Z" }, + { 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.11.0a0" +version = "1.12.0a0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "opentelemetry-api" }, @@ -3700,23 +3763,23 @@ dependencies = [ { name = "requests" }, { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/c1/5d/2b3240d914b87b6dd9cd5ca2ef1ccaf1d0626b897d4c06877e22c8c10fcf/opentelemetry_resourcedetector_gcp-1.11.0a0.tar.gz", hash = "sha256:915a1d6fd15daca9eedd3fc52b0f705375054f2ef140e2e7a6b4cca95a47cdb1", size = 18796, upload-time = "2025-11-04T19:32:16.59Z" } +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/c3/6c/1e13fe142a7ca3dc6489167203a1209d32430cca12775e1df9c9a41c54b2/opentelemetry_resourcedetector_gcp-1.11.0a0-py3-none-any.whl", hash = "sha256:5d65a2a039b1d40c6f41421dbb08d5f441368275ac6de6e76a8fccd1f6acb67e", size = 18798, upload-time = "2025-11-04T19:32:10.915Z" }, + { 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.38.0" +version = "1.41.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "opentelemetry-api" }, { name = "opentelemetry-semantic-conventions" }, { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/85/cb/f0eee1445161faf4c9af3ba7b848cc22a50a3d3e2515051ad8628c35ff80/opentelemetry_sdk-1.38.0.tar.gz", hash = "sha256:93df5d4d871ed09cb4272305be4d996236eedb232253e3ab864c8620f051cebe", size = 171942, upload-time = "2025-10-16T08:36:02.257Z" } +sdist = { url = "https://files.pythonhosted.org/packages/58/d0/54ee30dab82fb0acda23d144502771ff76ef8728459c83c3e89ef9fb1825/opentelemetry_sdk-1.41.1.tar.gz", hash = "sha256:724b615e1215b5aeacda0abb8a6a8922c9a1853068948bd0bd225a56d0c792e6", size = 230180, upload-time = "2026-04-24T13:15:50.991Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/2f/2e/e93777a95d7d9c40d270a371392b6d6f1ff170c2a3cb32d6176741b5b723/opentelemetry_sdk-1.38.0-py3-none-any.whl", hash = "sha256:1c66af6564ecc1553d72d811a01df063ff097cdc82ce188da9951f93b8d10f6b", size = 132349, upload-time = "2025-10-16T08:35:46.995Z" }, + { url = "https://files.pythonhosted.org/packages/b4/e7/a1420b698aad018e1cf60fdbaaccbe49021fb415e2a0d81c242f4c518f54/opentelemetry_sdk-1.41.1-py3-none-any.whl", hash = "sha256:edee379c126c1bce952b0c812b48fe8ff35b30df0eecf17e98afa4d598b7d85d", size = 180213, upload-time = "2026-04-24T13:15:33.767Z" }, ] [[package]] @@ -3733,96 +3796,96 @@ wheels = [ [[package]] name = "opentelemetry-semantic-conventions" -version = "0.59b0" +version = "0.62b1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "opentelemetry-api" }, { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/40/bc/8b9ad3802cd8ac6583a4eb7de7e5d7db004e89cb7efe7008f9c8a537ee75/opentelemetry_semantic_conventions-0.59b0.tar.gz", hash = "sha256:7a6db3f30d70202d5bf9fa4b69bc866ca6a30437287de6c510fb594878aed6b0", size = 129861, upload-time = "2025-10-16T08:36:03.346Z" } +sdist = { url = "https://files.pythonhosted.org/packages/9e/de/911ac9e309052aca1b20b2d5549d3db45d1011e1a610e552c6ccdd1b64f8/opentelemetry_semantic_conventions-0.62b1.tar.gz", hash = "sha256:c5cc6e04a7f8c7cdd30be2ed81499fa4e75bfbd52c9cb70d40af1f9cd3619802", size = 145750, upload-time = "2026-04-24T13:15:52.236Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/24/7d/c88d7b15ba8fe5c6b8f93be50fc11795e9fc05386c44afaf6b76fe191f9b/opentelemetry_semantic_conventions-0.59b0-py3-none-any.whl", hash = "sha256:35d3b8833ef97d614136e253c1da9342b4c3c083bbaf29ce31d572a1c3825eed", size = 207954, upload-time = "2025-10-16T08:35:48.054Z" }, + { url = "https://files.pythonhosted.org/packages/eb/a6/83dc2ab6fa397ee66fba04fe2e74bdf7be3b3870005359ceb7689103c058/opentelemetry_semantic_conventions-0.62b1-py3-none-any.whl", hash = "sha256:cf506938103d331fbb78eded0d9788095f7fd59016f2bda813c3324e5a74a93c", size = 231620, upload-time = "2026-04-24T13:15:35.454Z" }, ] [[package]] name = "orjson" -version = "3.11.8" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/9d/1b/2024d06792d0779f9dbc51531b61c24f76c75b9f4ce05e6f3377a1814cea/orjson-3.11.8.tar.gz", hash = "sha256:96163d9cdc5a202703e9ad1b9ae757d5f0ca62f4fa0cc93d1f27b0e180cc404e", size = 5603832, upload-time = "2026-03-31T16:16:27.878Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/2f/90/5d81f61fe3e4270da80c71442864c091cee3003cc8984c75f413fe742a07/orjson-3.11.8-cp310-cp310-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:e6693ff90018600c72fd18d3d22fa438be26076cd3c823da5f63f7bab28c11cb", size = 229663, upload-time = "2026-03-31T16:14:30.708Z" }, - { url = "https://files.pythonhosted.org/packages/6c/ef/85e06b0eb11de6fb424120fd5788a07035bd4c5e6bb7841ae9972a0526d1/orjson-3.11.8-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:93de06bc920854552493c81f1f729fab7213b7db4b8195355db5fda02c7d1363", size = 132321, upload-time = "2026-03-31T16:14:32.317Z" }, - { url = "https://files.pythonhosted.org/packages/86/71/089338ee51b3132f050db0864a7df9bdd5e94c2a03820ab8a91e8f655618/orjson-3.11.8-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:fe0b8c83e0f36247fc9431ce5425a5d95f9b3a689133d494831bdbd6f0bceb13", size = 130658, upload-time = "2026-03-31T16:14:33.935Z" }, - { url = "https://files.pythonhosted.org/packages/10/0d/f39d8802345d0ad65f7fd4374b29b9b59f98656dc30f21ca5c773265b2f0/orjson-3.11.8-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:97d823831105c01f6c8029faf297633dbeb30271892bd430e9c24ceae3734744", size = 135708, upload-time = "2026-03-31T16:14:35.224Z" }, - { url = "https://files.pythonhosted.org/packages/ff/b5/40aae576b3473511696dcffea84fde638b2b64774eb4dcb8b2c262729f8a/orjson-3.11.8-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c60c0423f15abb6cf78f56dff00168a1b582f7a1c23f114036e2bfc697814d5f", size = 147047, upload-time = "2026-03-31T16:14:36.489Z" }, - { url = "https://files.pythonhosted.org/packages/7b/f0/778a84458d1fdaa634b2e572e51ce0b354232f580b2327e1f00a8d88c38c/orjson-3.11.8-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:01928d0476b216ad2201823b0a74000440360cef4fed1912d297b8d84718f277", size = 133072, upload-time = "2026-03-31T16:14:37.715Z" }, - { url = "https://files.pythonhosted.org/packages/bf/d3/1bbf2fc3ffcc4b829ade554b574af68cec898c9b5ad6420a923c75a073d3/orjson-3.11.8-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6a4a639049c44d36a6d1ae0f4a94b271605c745aee5647fa8ffaabcdc01b69a6", size = 133867, upload-time = "2026-03-31T16:14:39.356Z" }, - { url = "https://files.pythonhosted.org/packages/08/94/6413da22edc99a69a8d0c2e83bf42973b8aa94d83ef52a6d39ac85da00bc/orjson-3.11.8-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:3222adff1e1ff0dce93c16146b93063a7793de6c43d52309ae321234cdaf0f4d", size = 142268, upload-time = "2026-03-31T16:14:40.972Z" }, - { url = "https://files.pythonhosted.org/packages/4a/5f/aa5dbaa6136d7ba55f5461ac2e885efc6e6349424a428927fd46d68f4396/orjson-3.11.8-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:3223665349bbfb68da234acd9846955b1a0808cbe5520ff634bf253a4407009b", size = 424008, upload-time = "2026-03-31T16:14:42.637Z" }, - { url = "https://files.pythonhosted.org/packages/fa/aa/2c1962d108c7fe5e27aa03a354b378caf56d8eafdef15fd83dec081ce45a/orjson-3.11.8-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:61c9d357a59465736022d5d9ba06687afb7611dfb581a9d2129b77a6fcf78e59", size = 147942, upload-time = "2026-03-31T16:14:44.256Z" }, - { url = "https://files.pythonhosted.org/packages/47/d1/65f404f4c47eb1b0b4476f03ec838cac0c4aa933920ff81e5dda4dee14e7/orjson-3.11.8-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:58fb9b17b4472c7b1dcf1a54583629e62e23779b2331052f09a9249edf81675b", size = 136640, upload-time = "2026-03-31T16:14:45.884Z" }, - { url = "https://files.pythonhosted.org/packages/90/5f/7b784aea98bdb125a2f2da7c27d6c2d2f6d943d96ef0278bae596d563f85/orjson-3.11.8-cp310-cp310-win32.whl", hash = "sha256:b43dc2a391981d36c42fa57747a49dae793ef1d2e43898b197925b5534abd10a", size = 132066, upload-time = "2026-03-31T16:14:47.397Z" }, - { url = "https://files.pythonhosted.org/packages/92/ec/2e284af8d6c9478df5ef938917743f61d68f4c70d17f1b6e82f7e3b8dba1/orjson-3.11.8-cp310-cp310-win_amd64.whl", hash = "sha256:c98121237fea2f679480765abd566f7713185897f35c9e6c2add7e3a9900eb61", size = 127609, upload-time = "2026-03-31T16:14:48.78Z" }, - { url = "https://files.pythonhosted.org/packages/67/41/5aa7fa3b0f4dc6b47dcafc3cea909299c37e40e9972feabc8b6a74e2730d/orjson-3.11.8-cp311-cp311-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:003646067cc48b7fcab2ae0c562491c9b5d2cbd43f1e5f16d98fd118c5522d34", size = 229229, upload-time = "2026-03-31T16:14:50.424Z" }, - { url = "https://files.pythonhosted.org/packages/0a/d7/57e7f2458e0a2c41694f39fc830030a13053a84f837a5b73423dca1f0938/orjson-3.11.8-cp311-cp311-macosx_15_0_arm64.whl", hash = "sha256:ed193ce51d77a3830cad399a529cd4ef029968761f43ddc549e1bc62b40d88f8", size = 128871, upload-time = "2026-03-31T16:14:51.888Z" }, - { url = "https://files.pythonhosted.org/packages/53/4a/e0fdb9430983e6c46e0299559275025075568aad5d21dd606faee3703924/orjson-3.11.8-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f30491bc4f862aa15744b9738517454f1e46e56c972a2be87d70d727d5b2a8f8", size = 132104, upload-time = "2026-03-31T16:14:53.142Z" }, - { url = "https://files.pythonhosted.org/packages/08/4a/2025a60ff3f5c8522060cda46612d9b1efa653de66ed2908591d8d82f22d/orjson-3.11.8-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:6eda5b8b6be91d3f26efb7dc6e5e68ee805bc5617f65a328587b35255f138bf4", size = 130483, upload-time = "2026-03-31T16:14:54.605Z" }, - { url = "https://files.pythonhosted.org/packages/2d/3c/b9cde05bdc7b2385c66014e0620627da638d3d04e4954416ab48c31196c5/orjson-3.11.8-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ee8db7bfb6fe03581bbab54d7c4124a6dd6a7f4273a38f7267197890f094675f", size = 135481, upload-time = "2026-03-31T16:14:55.901Z" }, - { url = "https://files.pythonhosted.org/packages/ff/f2/a8238e7734de7cb589fed319857a8025d509c89dc52fdcc88f39c6d03d5a/orjson-3.11.8-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5d8b5231de76c528a46b57010bbd83fb51e056aa0220a372fd5065e978406f1c", size = 146819, upload-time = "2026-03-31T16:14:57.548Z" }, - { url = "https://files.pythonhosted.org/packages/db/10/dbf1e2a3cafea673b1b4350e371877b759060d6018a998643b7040e5de48/orjson-3.11.8-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:58a4a208a6fbfdb7a7327b8f201c6014f189f721fd55d047cafc4157af1bc62a", size = 132846, upload-time = "2026-03-31T16:14:58.91Z" }, - { url = "https://files.pythonhosted.org/packages/f8/fc/55e667ec9c85694038fcff00573d221b085d50777368ee3d77f38668bf3c/orjson-3.11.8-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5f8952d6d2505c003e8f0224ff7858d341fa4e33fef82b91c4ff0ef070f2393c", size = 133580, upload-time = "2026-03-31T16:15:00.519Z" }, - { url = "https://files.pythonhosted.org/packages/7e/a6/c08c589a9aad0cb46c4831d17de212a2b6901f9d976814321ff8e69e8785/orjson-3.11.8-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:0022bb50f90da04b009ce32c512dc1885910daa7cb10b7b0cba4505b16db82a8", size = 142042, upload-time = "2026-03-31T16:15:01.906Z" }, - { url = "https://files.pythonhosted.org/packages/5c/cc/2f78ea241d52b717d2efc38878615fe80425bf2beb6e68c984dde257a766/orjson-3.11.8-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:ff51f9d657d1afb6f410cb435792ce4e1fe427aab23d2fcd727a2876e21d4cb6", size = 423845, upload-time = "2026-03-31T16:15:03.703Z" }, - { url = "https://files.pythonhosted.org/packages/70/07/c17dcf05dd8045457538428a983bf1f1127928df5bf328cb24d2b7cddacb/orjson-3.11.8-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:6dbe9a97bdb4d8d9d5367b52a7c32549bba70b2739c58ef74a6964a6d05ae054", size = 147729, upload-time = "2026-03-31T16:15:05.203Z" }, - { url = "https://files.pythonhosted.org/packages/90/6c/0fb6e8a24e682e0958d71711ae6f39110e4b9cd8cab1357e2a89cb8e1951/orjson-3.11.8-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:a5c370674ebabe16c6ccac33ff80c62bf8a6e59439f5e9d40c1f5ab8fd2215b7", size = 136425, upload-time = "2026-03-31T16:15:07.052Z" }, - { url = "https://files.pythonhosted.org/packages/b2/35/4d3cc3a3d616035beb51b24a09bb872942dc452cf2df0c1d11ab35046d9f/orjson-3.11.8-cp311-cp311-win32.whl", hash = "sha256:0e32f7154299f42ae66f13488963269e5eccb8d588a65bc839ed986919fc9fac", size = 131870, upload-time = "2026-03-31T16:15:08.678Z" }, - { url = "https://files.pythonhosted.org/packages/13/26/9fe70f81d16b702f8c3a775e8731b50ad91d22dacd14c7599b60a0941cd1/orjson-3.11.8-cp311-cp311-win_amd64.whl", hash = "sha256:25e0c672a2e32348d2eb33057b41e754091f2835f87222e4675b796b92264f06", size = 127440, upload-time = "2026-03-31T16:15:09.994Z" }, - { url = "https://files.pythonhosted.org/packages/e8/c6/b038339f4145efd2859c1ca53097a52c0bb9cbdd24f947ebe146da1ad067/orjson-3.11.8-cp311-cp311-win_arm64.whl", hash = "sha256:9185589c1f2a944c17e26c9925dcdbc2df061cc4a145395c57f0c51f9b5dbfcd", size = 127399, upload-time = "2026-03-31T16:15:11.412Z" }, - { url = "https://files.pythonhosted.org/packages/01/f6/8d58b32ab32d9215973a1688aebd098252ee8af1766c0e4e36e7831f0295/orjson-3.11.8-cp312-cp312-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:1cd0b77e77c95758f8e1100139844e99f3ccc87e71e6fc8e1c027e55807c549f", size = 229233, upload-time = "2026-03-31T16:15:12.762Z" }, - { url = "https://files.pythonhosted.org/packages/a9/8b/2ffe35e71f6b92622e8ea4607bf33ecf7dfb51b3619dcfabfd36cbe2d0a5/orjson-3.11.8-cp312-cp312-macosx_15_0_arm64.whl", hash = "sha256:6a3d159d5ffa0e3961f353c4b036540996bf8b9697ccc38261c0eac1fd3347a6", size = 128772, upload-time = "2026-03-31T16:15:14.237Z" }, - { url = "https://files.pythonhosted.org/packages/27/d2/1f8682ae50d5c6897a563cb96bc106da8c9cb5b7b6e81a52e4cc086679b9/orjson-3.11.8-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:76070a76e9c5ae661e2d9848f216980d8d533e0f8143e6ed462807b242e3c5e8", size = 131946, upload-time = "2026-03-31T16:15:15.607Z" }, - { url = "https://files.pythonhosted.org/packages/52/4b/5500f76f0eece84226e0689cb48dcde081104c2fa6e2483d17ca13685ffb/orjson-3.11.8-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:54153d21520a71a4c82a0dbb4523e468941d549d221dc173de0f019678cf3813", size = 130368, upload-time = "2026-03-31T16:15:17.066Z" }, - { url = "https://files.pythonhosted.org/packages/da/4e/58b927e08fbe9840e6c920d9e299b051ea667463b1f39a56e668669f8508/orjson-3.11.8-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:469ac2125611b7c5741a0b3798cd9e5786cbad6345f9f400c77212be89563bec", size = 135540, upload-time = "2026-03-31T16:15:18.404Z" }, - { url = "https://files.pythonhosted.org/packages/56/7c/ba7cb871cba1bcd5cd02ee34f98d894c6cea96353ad87466e5aef2429c60/orjson-3.11.8-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:14778ffd0f6896aa613951a7fbf4690229aa7a543cb2bfbe9f358e08aafa9546", size = 146877, upload-time = "2026-03-31T16:15:19.833Z" }, - { url = "https://files.pythonhosted.org/packages/0b/5d/eb9c25fc1386696c6a342cd361c306452c75e0b55e86ad602dd4827a7fd7/orjson-3.11.8-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ea56a955056a6d6c550cf18b3348656a9d9a4f02e2d0c02cabf3c73f1055d506", size = 132837, upload-time = "2026-03-31T16:15:21.282Z" }, - { url = "https://files.pythonhosted.org/packages/37/87/5ddeb7fc1fbd9004aeccab08426f34c81a5b4c25c7061281862b015fce2b/orjson-3.11.8-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:53a0f57e59a530d18a142f4d4ba6dfc708dc5fdedce45e98ff06b44930a2a48f", size = 133624, upload-time = "2026-03-31T16:15:22.641Z" }, - { url = "https://files.pythonhosted.org/packages/22/09/90048793db94ee4b2fcec4ac8e5ddb077367637d6650be896b3494b79bb7/orjson-3.11.8-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:9b48e274f8824567d74e2158199e269597edf00823a1b12b63d48462bbf5123e", size = 141904, upload-time = "2026-03-31T16:15:24.435Z" }, - { url = "https://files.pythonhosted.org/packages/c0/cf/eb284847487821a5d415e54149a6449ba9bfc5872ce63ab7be41b8ec401c/orjson-3.11.8-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:3f262401086a3960586af06c054609365e98407151f5ea24a62893a40d80dbbb", size = 423742, upload-time = "2026-03-31T16:15:26.155Z" }, - { url = "https://files.pythonhosted.org/packages/44/09/e12423d327071c851c13e76936f144a96adacfc037394dec35ac3fc8d1e8/orjson-3.11.8-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:8e8c6218b614badf8e229b697865df4301afa74b791b6c9ade01d19a9953a942", size = 147806, upload-time = "2026-03-31T16:15:27.909Z" }, - { url = "https://files.pythonhosted.org/packages/b3/6d/37c2589ba864e582ffe7611643314785c6afb1f83c701654ef05daa8fcc7/orjson-3.11.8-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:093d489fa039ddade2db541097dbb484999fcc65fc2b0ff9819141e2ab364f25", size = 136485, upload-time = "2026-03-31T16:15:29.749Z" }, - { url = "https://files.pythonhosted.org/packages/be/c9/135194a02ab76b04ed9a10f68624b7ebd238bbe55548878b11ff15a0f352/orjson-3.11.8-cp312-cp312-win32.whl", hash = "sha256:e0950ed1bcb9893f4293fd5c5a7ee10934fbf82c4101c70be360db23ce24b7d2", size = 131966, upload-time = "2026-03-31T16:15:31.687Z" }, - { url = "https://files.pythonhosted.org/packages/ed/9a/9796f8fbe3cf30ce9cb696748dbb535e5c87be4bf4fe2e9ca498ef1fa8cf/orjson-3.11.8-cp312-cp312-win_amd64.whl", hash = "sha256:3cf17c141617b88ced4536b2135c552490f07799f6ad565948ea07bef0dcb9a6", size = 127441, upload-time = "2026-03-31T16:15:33.333Z" }, - { url = "https://files.pythonhosted.org/packages/cc/47/5aaf54524a7a4a0dd09dd778f3fa65dd2108290615b652e23d944152bc8e/orjson-3.11.8-cp312-cp312-win_arm64.whl", hash = "sha256:48854463b0572cc87dac7d981aa72ed8bf6deedc0511853dc76b8bbd5482d36d", size = 127364, upload-time = "2026-03-31T16:15:34.748Z" }, - { url = "https://files.pythonhosted.org/packages/66/7f/95fba509bb2305fab0073558f1e8c3a2ec4b2afe58ed9fcb7d3b8beafe94/orjson-3.11.8-cp313-cp313-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:3f23426851d98478c8970da5991f84784a76682213cd50eb73a1da56b95239dc", size = 229180, upload-time = "2026-03-31T16:15:36.426Z" }, - { url = "https://files.pythonhosted.org/packages/f6/9d/b237215c743ca073697d759b5503abd2cb8a0d7b9c9e21f524bcf176ab66/orjson-3.11.8-cp313-cp313-macosx_15_0_arm64.whl", hash = "sha256:ebaed4cef74a045b83e23537b52ef19a367c7e3f536751e355a2a394f8648559", size = 128754, upload-time = "2026-03-31T16:15:38.049Z" }, - { url = "https://files.pythonhosted.org/packages/42/3d/27d65b6d11e63f133781425f132807aef793ed25075fec686fc8e46dd528/orjson-3.11.8-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:97c8f5d3b62380b70c36ffacb2a356b7c6becec86099b177f73851ba095ef623", size = 131877, upload-time = "2026-03-31T16:15:39.484Z" }, - { url = "https://files.pythonhosted.org/packages/dd/cc/faee30cd8f00421999e40ef0eba7332e3a625ce91a58200a2f52c7fef235/orjson-3.11.8-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:436c4922968a619fb7fef1ccd4b8b3a76c13b67d607073914d675026e911a65c", size = 130361, upload-time = "2026-03-31T16:15:41.274Z" }, - { url = "https://files.pythonhosted.org/packages/5c/bb/a6c55896197f97b6d4b4e7c7fd77e7235517c34f5d6ad5aadd43c54c6d7c/orjson-3.11.8-cp313-cp313-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1ab359aff0436d80bfe8a23b46b5fea69f1e18aaf1760a709b4787f1318b317f", size = 135521, upload-time = "2026-03-31T16:15:42.758Z" }, - { url = "https://files.pythonhosted.org/packages/9c/7c/ca3a3525aa32ff636ebb1778e77e3587b016ab2edb1b618b36ba96f8f2c0/orjson-3.11.8-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f89b6d0b3a8d81e1929d3ab3d92bbc225688bd80a770c49432543928fe09ac55", size = 146862, upload-time = "2026-03-31T16:15:44.341Z" }, - { url = "https://files.pythonhosted.org/packages/3c/0c/18a9d7f18b5edd37344d1fd5be17e94dc652c67826ab749c6e5948a78112/orjson-3.11.8-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:29c009e7a2ca9ad0ed1376ce20dd692146a5d9fe4310848904b6b4fee5c5c137", size = 132847, upload-time = "2026-03-31T16:15:46.368Z" }, - { url = "https://files.pythonhosted.org/packages/23/91/7e722f352ad67ca573cee44de2a58fb810d0f4eb4e33276c6a557979fd8a/orjson-3.11.8-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:705b895b781b3e395c067129d8551655642dfe9437273211d5404e87ac752b53", size = 133637, upload-time = "2026-03-31T16:15:48.123Z" }, - { url = "https://files.pythonhosted.org/packages/af/04/32845ce13ac5bd1046ddb02ac9432ba856cc35f6d74dde95864fe0ad5523/orjson-3.11.8-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:88006eda83858a9fdf73985ce3804e885c2befb2f506c9a3723cdeb5a2880e3e", size = 141906, upload-time = "2026-03-31T16:15:49.626Z" }, - { url = "https://files.pythonhosted.org/packages/02/5e/c551387ddf2d7106d9039369862245c85738b828844d13b99ccb8d61fd06/orjson-3.11.8-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:55120759e61309af7fcf9e961c6f6af3dde5921cdb3ee863ef63fd9db126cae6", size = 423722, upload-time = "2026-03-31T16:15:51.176Z" }, - { url = "https://files.pythonhosted.org/packages/00/a3/ecfe62434096f8a794d4976728cb59bcfc4a643977f21c2040545d37eb4c/orjson-3.11.8-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:98bdc6cb889d19bed01de46e67574a2eab61f5cc6b768ed50e8ac68e9d6ffab6", size = 147801, upload-time = "2026-03-31T16:15:52.939Z" }, - { url = "https://files.pythonhosted.org/packages/18/6d/0dce10b9f6643fdc59d99333871a38fa5a769d8e2fc34a18e5d2bfdee900/orjson-3.11.8-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:708c95f925a43ab9f34625e45dcdadf09ec8a6e7b664a938f2f8d5650f6c090b", size = 136460, upload-time = "2026-03-31T16:15:54.431Z" }, - { url = "https://files.pythonhosted.org/packages/01/d6/6dde4f31842d87099238f1f07b459d24edc1a774d20687187443ab044191/orjson-3.11.8-cp313-cp313-win32.whl", hash = "sha256:01c4e5a6695dc09098f2e6468a251bc4671c50922d4d745aff1a0a33a0cf5b8d", size = 131956, upload-time = "2026-03-31T16:15:56.081Z" }, - { url = "https://files.pythonhosted.org/packages/c1/f9/4e494a56e013db957fb77186b818b916d4695b8fa2aa612364974160e91b/orjson-3.11.8-cp313-cp313-win_amd64.whl", hash = "sha256:c154a35dd1330707450bb4d4e7dd1f17fa6f42267a40c1e8a1daa5e13719b4b8", size = 127410, upload-time = "2026-03-31T16:15:57.54Z" }, - { url = "https://files.pythonhosted.org/packages/57/7f/803203d00d6edb6e9e7eef421d4e1adbb5ea973e40b3533f3cfd9aeb374e/orjson-3.11.8-cp313-cp313-win_arm64.whl", hash = "sha256:4861bde57f4d253ab041e374f44023460e60e71efaa121f3c5f0ed457c3a701e", size = 127338, upload-time = "2026-03-31T16:15:59.106Z" }, - { url = "https://files.pythonhosted.org/packages/6d/35/b01910c3d6b85dc882442afe5060cbf719c7d1fc85749294beda23d17873/orjson-3.11.8-cp314-cp314-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:ec795530a73c269a55130498842aaa762e4a939f6ce481a7e986eeaa790e9da4", size = 229171, upload-time = "2026-03-31T16:16:00.651Z" }, - { url = "https://files.pythonhosted.org/packages/c2/56/c9ec97bd11240abef39b9e5d99a15462809c45f677420fd148a6c5e6295e/orjson-3.11.8-cp314-cp314-macosx_15_0_arm64.whl", hash = "sha256:c492a0e011c0f9066e9ceaa896fbc5b068c54d365fea5f3444b697ee01bc8625", size = 128746, upload-time = "2026-03-31T16:16:02.673Z" }, - { url = "https://files.pythonhosted.org/packages/3b/e4/66d4f30a90de45e2f0cbd9623588e8ae71eef7679dbe2ae954ed6d66a41f/orjson-3.11.8-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:883206d55b1bd5f5679ad5e6ddd3d1a5e3cac5190482927fdb8c78fb699193b5", size = 131867, upload-time = "2026-03-31T16:16:04.342Z" }, - { url = "https://files.pythonhosted.org/packages/19/30/2a645fc9286b928675e43fa2a3a16fb7b6764aa78cc719dc82141e00f30b/orjson-3.11.8-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5774c1fdcc98b2259800b683b19599c133baeb11d60033e2095fd9d4667b82db", size = 124664, upload-time = "2026-03-31T16:16:05.837Z" }, - { url = "https://files.pythonhosted.org/packages/db/44/77b9a86d84a28d52ba3316d77737f6514e17118119ade3f91b639e859029/orjson-3.11.8-cp314-cp314-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8ac7381c83dd3d4a6347e6635950aa448f54e7b8406a27c7ecb4a37e9f1ae08b", size = 129701, upload-time = "2026-03-31T16:16:07.407Z" }, - { url = "https://files.pythonhosted.org/packages/b3/ea/eff3d9bfe47e9bc6969c9181c58d9f71237f923f9c86a2d2f490cd898c82/orjson-3.11.8-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:14439063aebcb92401c11afc68ee4e407258d2752e62d748b6942dad20d2a70d", size = 141202, upload-time = "2026-03-31T16:16:09.48Z" }, - { url = "https://files.pythonhosted.org/packages/52/c8/90d4b4c60c84d62068d0cf9e4d8f0a4e05e76971d133ac0c60d818d4db20/orjson-3.11.8-cp314-cp314-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:fa72e71977bff96567b0f500fc5bfd2fdf915f34052c782a4c6ebbdaa97aa858", size = 127194, upload-time = "2026-03-31T16:16:11.02Z" }, - { url = "https://files.pythonhosted.org/packages/8d/c7/ea9e08d1f0ba981adffb629811148b44774d935171e7b3d780ae43c4c254/orjson-3.11.8-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7679bc2f01bb0d219758f1a5f87bb7c8a81c0a186824a393b366876b4948e14f", size = 133639, upload-time = "2026-03-31T16:16:13.434Z" }, - { url = "https://files.pythonhosted.org/packages/6c/8c/ddbbfd6ba59453c8fc7fe1d0e5983895864e264c37481b2a791db635f046/orjson-3.11.8-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:14f7b8fcb35ef403b42fa5ecfa4ed032332a91f3dc7368fbce4184d59e1eae0d", size = 141914, upload-time = "2026-03-31T16:16:14.955Z" }, - { url = "https://files.pythonhosted.org/packages/4e/31/dbfbefec9df060d34ef4962cd0afcb6fa7a9ec65884cb78f04a7859526c3/orjson-3.11.8-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:c2bdf7b2facc80b5e34f48a2d557727d5c5c57a8a450de122ae81fa26a81c1bc", size = 423800, upload-time = "2026-03-31T16:16:16.594Z" }, - { url = "https://files.pythonhosted.org/packages/87/cf/f74e9ae9803d4ab46b163494adba636c6d7ea955af5cc23b8aaa94cfd528/orjson-3.11.8-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:ccd7ba1b0605813a0715171d39ec4c314cb97a9c85893c2c5c0c3a3729df38bf", size = 147837, upload-time = "2026-03-31T16:16:18.585Z" }, - { url = "https://files.pythonhosted.org/packages/64/e6/9214f017b5db85e84e68602792f742e5dc5249e963503d1b356bee611e01/orjson-3.11.8-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:cdbc8c9c02463fef4d3c53a9ba3336d05496ec8e1f1c53326a1e4acc11f5c600", size = 136441, upload-time = "2026-03-31T16:16:20.151Z" }, - { url = "https://files.pythonhosted.org/packages/24/dd/3590348818f58f837a75fb969b04cdf187ae197e14d60b5e5a794a38b79d/orjson-3.11.8-cp314-cp314-win32.whl", hash = "sha256:0b57f67710a8cd459e4e54eb96d5f77f3624eba0c661ba19a525807e42eccade", size = 131983, upload-time = "2026-03-31T16:16:21.823Z" }, - { url = "https://files.pythonhosted.org/packages/3f/0f/b6cb692116e05d058f31ceee819c70f097fa9167c82f67fabe7516289abc/orjson-3.11.8-cp314-cp314-win_amd64.whl", hash = "sha256:735e2262363dcbe05c35e3a8869898022af78f89dde9e256924dc02e99fe69ca", size = 127396, upload-time = "2026-03-31T16:16:23.685Z" }, - { url = "https://files.pythonhosted.org/packages/c0/d1/facb5b5051fabb0ef9d26c6544d87ef19a939a9a001198655d0d891062dd/orjson-3.11.8-cp314-cp314-win_arm64.whl", hash = "sha256:6ccdea2c213cf9f3d9490cbd5d427693c870753df41e6cb375bd79bcbafc8817", size = 127330, upload-time = "2026-03-31T16:16:25.496Z" }, +version = "3.11.9" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/7e/0c/964746fcafbd16f8ff53219ad9f6b412b34f345c75f384ad434ceaadb538/orjson-3.11.9.tar.gz", hash = "sha256:4fef17e1f8722c11587a6ef18e35902450221da0028e65dbaaa543619e68e48f", size = 5599163, upload-time = "2026-05-06T15:11:08.309Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/10/5d/b95ca542a001135cc250a49370f282f578c8f4e46cc8617d73775297eea8/orjson-3.11.9-cp310-cp310-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:135869ef917b8704ea0a94e01620e0c05021c15c52036e4663baffe75e72f8ce", size = 228986, upload-time = "2026-05-06T15:09:14.765Z" }, + { url = "https://files.pythonhosted.org/packages/80/01/be33fbff646e22f93398429ea645f20d2097aea1a6cdc1e6628e70125f83/orjson-3.11.9-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:115ab5f5f4a0f203cc2a5f0fb09aee503a3f771aa08392949ab5ca230c4fbdbd", size = 132558, upload-time = "2026-05-06T15:09:17.431Z" }, + { url = "https://files.pythonhosted.org/packages/4e/61/73d49333bba660a075daccca10970dc6409ce1cf42ae4046646a19468aad/orjson-3.11.9-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:4da3c38a2083ca4aaf9c2a36776cce3e9328e6647b10d118948f3cfb4913ffe4", size = 128213, upload-time = "2026-05-06T15:09:18.719Z" }, + { url = "https://files.pythonhosted.org/packages/1f/7d/30e844b3dac3f74aed66b1f984daf9db3c98c0328c03d965a9e8dc06449e/orjson-3.11.9-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:53b50b0e14084b8f7e29c5ce84c5af0f1160169b30d8a6914231d97d2fe297d4", size = 135430, upload-time = "2026-05-06T15:09:20.257Z" }, + { url = "https://files.pythonhosted.org/packages/16/64/bd815f5c610b3facc204f26ba94e87a9eb49b0d83de3d5fc1eee2402d91b/orjson-3.11.9-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:231742b4a11dad8d5380a435962c57e91b7c37b79be858f4ef1c0df1a259897e", size = 146178, upload-time = "2026-05-06T15:09:21.616Z" }, + { url = "https://files.pythonhosted.org/packages/c7/35/e744fd36c79b339d27beb06068b5a08a8882ef5418804d0ce545a31f718d/orjson-3.11.9-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:34fd2317602587321faab75ab76c623a0117e80841a6413654f04e47f339a8fb", size = 133068, upload-time = "2026-05-06T15:09:23.228Z" }, + { url = "https://files.pythonhosted.org/packages/2a/56/d54152b67b63a0b3e556cfc549d6ce84f74d7f425ddeadc6c8a74d913da7/orjson-3.11.9-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:71f3db16e69b667b132e0f305a833d5497da302d801508cbb051ed9a9819da47", size = 134217, upload-time = "2026-05-06T15:09:24.847Z" }, + { url = "https://files.pythonhosted.org/packages/0b/ee/66154baf69f71c7164a268a5e888908aec5a0819d13c81d5e2755a257758/orjson-3.11.9-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:0b34789fa0da61cf7bef0546b09c738fb195331e017e477096d129e9105ab03d", size = 141917, upload-time = "2026-05-06T15:09:26.647Z" }, + { url = "https://files.pythonhosted.org/packages/09/d3/c5824260ca8b9d7ba82648d042a3f8f4815d18c15bb98a1f30edd1bb2d83/orjson-3.11.9-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:87e4d4ab280b0c87424d47695bec2182caf8cfc17879ea78dab76680194abc13", size = 415356, upload-time = "2026-05-06T15:09:28.252Z" }, + { url = "https://files.pythonhosted.org/packages/64/cb/509c2e816fe4df641d93dc92f6a89adc8df3ada8ebdee2bd44aba3264c3c/orjson-3.11.9-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:ace6c58523302d3b97b6ac5c38a5298a54b473762b6be82726b4265c41029f92", size = 148112, upload-time = "2026-05-06T15:09:29.783Z" }, + { url = "https://files.pythonhosted.org/packages/db/b5/3ceae56d2e4962979eedb023ba6a46a4bb65f333960379be0ca470686220/orjson-3.11.9-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:97d0d932803c1b164fde11cb542a9efcb1e0f63b184537cca65887147906ff48", size = 137112, upload-time = "2026-05-06T15:09:31.432Z" }, + { url = "https://files.pythonhosted.org/packages/d7/7a/81fa3f2c7bef79b04cf2ab7838e5ac74b1f12511ceab979759b0275d6bb4/orjson-3.11.9-cp310-cp310-win32.whl", hash = "sha256:b3afcf569c15577a9fe64627292daa3e6b3a70f4fb77a5df246a87ec21681b94", size = 131706, upload-time = "2026-05-06T15:09:32.707Z" }, + { url = "https://files.pythonhosted.org/packages/ae/d8/b64600f9083c7f151ad39717a5877fccbeb0ef6d7efcb55f971ce00b6bee/orjson-3.11.9-cp310-cp310-win_amd64.whl", hash = "sha256:8697ab6a080a5c46edaad50e2bc5bd8c7ca5c66442d24104fa44ec74910a8244", size = 127282, upload-time = "2026-05-06T15:09:33.955Z" }, + { url = "https://files.pythonhosted.org/packages/1e/51/3fb9e65ae76ee97bd611869a503fa3fc0a6e81dd8b737cf3003f682df7ff/orjson-3.11.9-cp311-cp311-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:f01c4818b3fc9b0da8e096722a84318071eaa118df35f6ed2344da0e73a5444f", size = 228522, upload-time = "2026-05-06T15:09:35.362Z" }, + { url = "https://files.pythonhosted.org/packages/16/fa/9d54b07cb3f3b0bfd57841478e42d7a0ece4a9f49f9907eecf5a45461687/orjson-3.11.9-cp311-cp311-macosx_15_0_arm64.whl", hash = "sha256:3ebca4179031ee716ed076ffadc29428e900512f6fccee8614c9983157fcf19c", size = 128463, upload-time = "2026-05-06T15:09:37.063Z" }, + { url = "https://files.pythonhosted.org/packages/88/b1/6ceafc2eefd0a553e3be77ce6c49d107e772485d9568629376171c50e634/orjson-3.11.9-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:48ee05097750de0ff69ed5b7bbcf0732182fd57a24043dcc2a1da780a5ead3a5", size = 132306, upload-time = "2026-05-06T15:09:38.299Z" }, + { url = "https://files.pythonhosted.org/packages/ea/76/f11311285324a40aab1e3031385c50b635a7cd0734fdaf60c7e89a696f60/orjson-3.11.9-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:a6082706765a95a6680d812e1daf1c0cfe8adec7831b3ff3b625693f3b461b1c", size = 127988, upload-time = "2026-05-06T15:09:39.597Z" }, + { url = "https://files.pythonhosted.org/packages/9e/85/0ef63bcf1337f44031ce9b91b1919563f62a37527b3ea4368bb15a22e5d7/orjson-3.11.9-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:277fefe9d76ee17eb14debf399e3533d4d63b5f677a4d3719eb763536af1f4bd", size = 135188, upload-time = "2026-05-06T15:09:40.957Z" }, + { url = "https://files.pythonhosted.org/packages/05/94/b0d27090ea8a2095db3c2bd1b1c96f96f19bbb494d7fef33130e846e613d/orjson-3.11.9-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:03db380e3780fa0015ed776a90f20e8e20bb11dde13b216ce19e5718e3dfba62", size = 145937, upload-time = "2026-05-06T15:09:42.249Z" }, + { url = "https://files.pythonhosted.org/packages/09/eb/75d50c29c05b8054013e221e598820a365c8e64065312e75e202ed880709/orjson-3.11.9-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:33d7d766701847dc6729846362dc27895d2f2d2251264f9d10e7cb9878194877", size = 132758, upload-time = "2026-05-06T15:09:43.945Z" }, + { url = "https://files.pythonhosted.org/packages/49/bd/360686f39348aa88827cb6fbf7dc606fd41c831a35235e1abf1db8e3a9e6/orjson-3.11.9-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:147302878da387104b66bb4a8b0227d1d487e976ce41a8501916161072ed87b1", size = 133971, upload-time = "2026-05-06T15:09:45.239Z" }, + { url = "https://files.pythonhosted.org/packages/0e/30/3178eb16f3221aeef068b6f1f1ebe05f656ea5c6dffe9f6c917329fe17a3/orjson-3.11.9-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:3513550321f8c8c811a7c3297b8a630e82dc08e4c10216d07703c997776236cd", size = 141685, upload-time = "2026-05-06T15:09:46.858Z" }, + { url = "https://files.pythonhosted.org/packages/5f/f1/ff2f19ed0225f9680fafa42febca3570dd59444ebf190980738d376214c2/orjson-3.11.9-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:c5d001196b89fa9cf0a4ab79766cd835b991a166e4b621ba95089edc50c429ff", size = 415167, upload-time = "2026-05-06T15:09:48.312Z" }, + { url = "https://files.pythonhosted.org/packages/9b/61/863bddf0da6e9e586765414debd54b4e58db05f560902b6d00658cb88636/orjson-3.11.9-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:16969c9d369c98eb084889c6e4d2d39b77c7eb38ceccf8da2a9fff62ae908980", size = 147913, upload-time = "2026-05-06T15:09:49.733Z" }, + { url = "https://files.pythonhosted.org/packages/b6/8a/4081492586d75b073d60c5271a8d0f05a0955cabf1e34c8473f6fcd84235/orjson-3.11.9-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:63e0efbc991250c0b3143488fa57d95affcabbfc63c99c48d625dd37779aafe2", size = 136959, upload-time = "2026-05-06T15:09:51.311Z" }, + { url = "https://files.pythonhosted.org/packages/0d/bd/70b6ab193594d7abb875320c0a7c8335e846f28968c432c31042409c3c8d/orjson-3.11.9-cp311-cp311-win32.whl", hash = "sha256:14ed654580c1ed2bc217352ec82f91b047aef82951aa71c7f64e0dcb03c0e180", size = 131533, upload-time = "2026-05-06T15:09:52.637Z" }, + { url = "https://files.pythonhosted.org/packages/3f/17/1a1a228183d62d1b77e2c30d210f47dd4768b310ebe1607c63e3c0e3a71e/orjson-3.11.9-cp311-cp311-win_amd64.whl", hash = "sha256:57ea77fb70a448ce87d18fca050193202a3da5e54598f6501ca5476fb66cfe02", size = 127106, upload-time = "2026-05-06T15:09:54.204Z" }, + { url = "https://files.pythonhosted.org/packages/b8/95/285de5fa296d09681ee9c546cd4a8aeb773b701cf343dc125994f4d52953/orjson-3.11.9-cp311-cp311-win_arm64.whl", hash = "sha256:19b72ed11572a2ee51a67a903afbe5af504f84ed6f529c0fe44b0ab3fb5cc697", size = 126848, upload-time = "2026-05-06T15:09:55.551Z" }, + { url = "https://files.pythonhosted.org/packages/16/6d/11867a3ffa3a3608d84a4de51ef4dd0896d6b5cc9132fbe1daf593e677bc/orjson-3.11.9-cp312-cp312-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:9ef6fe90aadef185c7b128859f40beb24720b4ecea95379fc9000931179c3a49", size = 228515, upload-time = "2026-05-06T15:09:57.265Z" }, + { url = "https://files.pythonhosted.org/packages/24/75/05912954c8b288f34fcf5cd4b9b071cb4f6e77b9961e175e56ebb258089f/orjson-3.11.9-cp312-cp312-macosx_15_0_arm64.whl", hash = "sha256:e5c9b8f28e726e97d97696c826bc7bea5d71cecd63576dba92924a32c1961291", size = 128409, upload-time = "2026-05-06T15:09:59.063Z" }, + { url = "https://files.pythonhosted.org/packages/ab/86/1c3a47df3bc8191ea9ac51603bbb872a95167a364320c269f2557911f406/orjson-3.11.9-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:26a473dbb4162108b27901492546f83c76fdcea3d0eadff00ae7a07e18dcce09", size = 132106, upload-time = "2026-05-06T15:10:00.798Z" }, + { url = "https://files.pythonhosted.org/packages/d7/cf/b33b5f3e695ae7d63feef9d915c37cc3b8f465493dcd4f8e0b4c697a2366/orjson-3.11.9-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:011382e2a60fda9d46f1cdee31068cfc52ffe952b587d683ec0463002802a0f4", size = 127864, upload-time = "2026-05-06T15:10:02.15Z" }, + { url = "https://files.pythonhosted.org/packages/31/6a/6cf69385a58208024fcb8c014e2141b8ce838aba6492b589f8acfff97fab/orjson-3.11.9-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c2d3dc759490128c5c1711a53eeaa8ee1d437fd0038ffd2b6008abf46db3f882", size = 135213, upload-time = "2026-05-06T15:10:03.515Z" }, + { url = "https://files.pythonhosted.org/packages/e8/f8/0b1bd3e8f2efcdd376af5c8cfd79eaf13f018080c0089c80ebd724e3c7fb/orjson-3.11.9-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d8ea516b3726d190e1b4297e6f4e7a8650347ae053868a18163b4dd3641d1fff", size = 145994, upload-time = "2026-05-06T15:10:05.083Z" }, + { url = "https://files.pythonhosted.org/packages/f3/59/dab79f61044c529d2c81aecdc589b1f833a1c8dec11ba3b1c2498a02ca7e/orjson-3.11.9-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:380cdce7ba24989af81d0a7013d0aaec5d0e2a21734c0e2681b1bc4f141957fe", size = 132744, upload-time = "2026-05-06T15:10:06.853Z" }, + { url = "https://files.pythonhosted.org/packages/0e/a4/82b7a2fe5d8a67a59ed831b24d59a3d46ea7d207b66e1602d376541d94a6/orjson-3.11.9-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:be4fa4f0af7fa18951f7ab3fc2148e223af211bf03f59e1c6034ec3f97f21d61", size = 134014, upload-time = "2026-05-06T15:10:08.213Z" }, + { url = "https://files.pythonhosted.org/packages/50/c7/375e83a76851b73b2e39f3bcf0e5a19e2b89bad13e5bca97d0b293d27f24/orjson-3.11.9-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:a8f5f8bc7ce7d59f08d9f99fa510c06496164a24cb5f3d34537dbd9ca30132e2", size = 141509, upload-time = "2026-05-06T15:10:09.595Z" }, + { url = "https://files.pythonhosted.org/packages/7f/7c/49d5d82a3d3097f641f094f552131f1e2723b0b8cb0fa2874ab65ecfffa6/orjson-3.11.9-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:4d7fde5501b944f83b3e665e1b31343ff6e154b15560a16b7130ea1e594a4206", size = 415127, upload-time = "2026-05-06T15:10:11.049Z" }, + { url = "https://files.pythonhosted.org/packages/3a/dc/7446c538590d55f455647e5f3c61fc33f7108714e7afcffa6a2a033f8350/orjson-3.11.9-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:cde1a448023ba7d5bb4c01c5afb48894380b5e4956e0627266526587ef4e535f", size = 148025, upload-time = "2026-05-06T15:10:12.842Z" }, + { url = "https://files.pythonhosted.org/packages/df/e5/4d2d8af06f788329b4f78f8cc3679bb395392fcaa1e4d8d3c33e85308fa4/orjson-3.11.9-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:71e63adb0e1f1ed5d9e168f50a91ceb93ae6420731d222dc7da5c69409aa47aa", size = 136943, upload-time = "2026-05-06T15:10:14.405Z" }, + { url = "https://files.pythonhosted.org/packages/06/69/850264ccf6d80f6b174620d30a87f65c9b1490aba33fe6b62798e618cad3/orjson-3.11.9-cp312-cp312-win32.whl", hash = "sha256:2d057a602cdd19a0ad680417527c45b6961a095081c0f46fe0e03e304aac6470", size = 131606, upload-time = "2026-05-06T15:10:15.791Z" }, + { url = "https://files.pythonhosted.org/packages/b9/d5/973a43fc9c55e20f2051e9830997649f669be0cb3ca52192087c0143f118/orjson-3.11.9-cp312-cp312-win_amd64.whl", hash = "sha256:59e403b1cc5a676da8eaf31f6254801b7341b3e29efa85f92b48d272637e77be", size = 127101, upload-time = "2026-05-06T15:10:17.129Z" }, + { url = "https://files.pythonhosted.org/packages/fe/ae/495470f0e4a18f73fa10b7f6b84b464ec4cc5291c4e0c7c2a6c400bef006/orjson-3.11.9-cp312-cp312-win_arm64.whl", hash = "sha256:9af678d6488357948f1f84c6cd1c1d397c014e1ae2f98ae082a44eb48f602624", size = 126736, upload-time = "2026-05-06T15:10:18.645Z" }, + { url = "https://files.pythonhosted.org/packages/32/33/93fcc25907235c344ae73122f8a4e01d2d393ef062b4af7d2e2487a32c37/orjson-3.11.9-cp313-cp313-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:4bab1b2d6141fe7b32ae71dac905666ece4f94936efbfb13d55bb7739a3a6021", size = 228458, upload-time = "2026-05-06T15:10:20.079Z" }, + { url = "https://files.pythonhosted.org/packages/8f/27/b1e6dadb3c080313c03fdd8067b85e6a0460c7d8d6a1c3984ef77b904e4d/orjson-3.11.9-cp313-cp313-macosx_15_0_arm64.whl", hash = "sha256:844417969855fc7a41be124aafe83dc424592a7f77cd4501900c67307122b92c", size = 128368, upload-time = "2026-05-06T15:10:21.549Z" }, + { url = "https://files.pythonhosted.org/packages/21/0f/c9ede0bf052f6b4051e64a7d4fa91b725cccf8321a6a786e86eb03519f00/orjson-3.11.9-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ffe02797b5e9f3a9d8292ddcd289b474ad13e81ad83cd1891a240811f1d2cb81", size = 132070, upload-time = "2026-05-06T15:10:23.371Z" }, + { url = "https://files.pythonhosted.org/packages/fd/26/d398e28048dc18205bbe812f2c88cb9b40313db2470778e25964796458fe/orjson-3.11.9-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:0e4eed3b200023042814d2fc8a5d2e880f13b52e1ed2485e83da4f3962f7dc1a", size = 127892, upload-time = "2026-05-06T15:10:24.714Z" }, + { url = "https://files.pythonhosted.org/packages/66/60/52b0054c4c700d5aa7fc5b7ca96917400d8f061307778578e67a10e25852/orjson-3.11.9-cp313-cp313-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8aff7da9952a5ad1cef8e68017724d96c7b9a66e99e91d6252e1b133d67a7b10", size = 135217, upload-time = "2026-05-06T15:10:26.084Z" }, + { url = "https://files.pythonhosted.org/packages/d5/97/1e3dc2b2a28b7b2528f403d2fc1d79ec5f39af3bc143ab65d3ec26426385/orjson-3.11.9-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4d4e98d6f3b8afed8bc8cd9718ec0cdf46661826beefb53fe8eafb37f2bf0362", size = 145980, upload-time = "2026-05-06T15:10:28.062Z" }, + { url = "https://files.pythonhosted.org/packages/fc/39/31fbfe7850f2de32dee7e7e5c09f26d403ab01e440ac96001c6b01ad3c99/orjson-3.11.9-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3a81d52442a7c99b3662333235b3adf96a1715864658b35bb797212be7bddb97", size = 132738, upload-time = "2026-05-06T15:10:29.727Z" }, + { url = "https://files.pythonhosted.org/packages/a1/08/dca0082dd2a194acb93e5457e73455388e2e2ca464a2672449a9ddbb679d/orjson-3.11.9-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4e39364e726a8fff737309aff059ff67d8a8c8d5b677be7bb49a8b3e84b7e218", size = 134033, upload-time = "2026-05-06T15:10:31.152Z" }, + { url = "https://files.pythonhosted.org/packages/11/d4/5bdb0626801230139987385554c5d4c42255218ac906525bf4347f22cd95/orjson-3.11.9-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:4fd66214623f1b17501df9f0543bef0b833979ab5b6ded1e1d123222866aa8c9", size = 141492, upload-time = "2026-05-06T15:10:32.641Z" }, + { url = "https://files.pythonhosted.org/packages/fa/88/a21fb53b3ede6703aede6dce4710ed4111e5b201cfa6bbff5e544f9d47d7/orjson-3.11.9-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:8ecc30f10465fa1e0ce13fd01d9e22c316e5053a719a8d915d4545a09a5ff677", size = 415087, upload-time = "2026-05-06T15:10:34.438Z" }, + { url = "https://files.pythonhosted.org/packages/3d/57/1b30daf70f0d8180e9a73cefbfbdd99e4bf19eb020466502b01fba7e0e50/orjson-3.11.9-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:97db4c94a7db398a5bd636273324f0b3fd58b350bbbac8bb380ceb825a9b40f4", size = 148031, upload-time = "2026-05-06T15:10:36.358Z" }, + { url = "https://files.pythonhosted.org/packages/04/83/45fbb6d962e260807f99441db9613cee868ceda4baceda59b3720a563f97/orjson-3.11.9-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:9f78cf8fec5bd627f4082b8dfeac7871b43d7f3274904492a43dab39f18a19a0", size = 136915, upload-time = "2026-05-06T15:10:38.013Z" }, + { url = "https://files.pythonhosted.org/packages/5f/cc/2d10025f9056d376e4127ec05a5808b218d46f035fdc08178a5411b34250/orjson-3.11.9-cp313-cp313-win32.whl", hash = "sha256:d4087e5c0209a0a8efe4de3303c234b9c44d1174161dcd851e8eea07c7560b32", size = 131613, upload-time = "2026-05-06T15:10:39.569Z" }, + { url = "https://files.pythonhosted.org/packages/67/bd/2775ff28bfe883b9aa1ff348300542eb2ef1ee18d8ae0e3a49846817a865/orjson-3.11.9-cp313-cp313-win_amd64.whl", hash = "sha256:051b102c93b4f634e89f3866b07b9a9a98915ada541f4ec30f177067b2694979", size = 127086, upload-time = "2026-05-06T15:10:41.262Z" }, + { url = "https://files.pythonhosted.org/packages/91/2b/d26799e580939e32a7da9a39531bc9e58e15ca32ffaa6a8cb3e9bb0d22cd/orjson-3.11.9-cp313-cp313-win_arm64.whl", hash = "sha256:cce9127885941bd28f080cecf1f1d288336b7e0d812c345b08be88b572796254", size = 126696, upload-time = "2026-05-06T15:10:42.651Z" }, + { url = "https://files.pythonhosted.org/packages/8e/eb/5da01e356015aee6ecfa1187ced87aef51364e306f5e695dd52719bf0e78/orjson-3.11.9-cp314-cp314-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:b6ef1979adc4bc243523f1a2ba91418030a8e29b0a99cbe7e0e2d6807d4dce6e", size = 228465, upload-time = "2026-05-06T15:10:44.097Z" }, + { url = "https://files.pythonhosted.org/packages/64/62/3e0e0c14c957133bcd855395c62b55ed4e3b0af23ffea11b032cb1dcbdb1/orjson-3.11.9-cp314-cp314-macosx_15_0_arm64.whl", hash = "sha256:f36b7f32c7c0db4a719f1fc5824db4a9c6f8bd1a354debb91faf26ebf3a4c71e", size = 128364, upload-time = "2026-05-06T15:10:45.839Z" }, + { url = "https://files.pythonhosted.org/packages/5a/5a/07d8aa117211a8ed7630bda80c8c0b14d04e0f8dcf99bcf49656e4a710eb/orjson-3.11.9-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:08f4d8ebb44925c794e535b2bebc507cebf32209df81de22ae285fb0d8d66de0", size = 132063, upload-time = "2026-05-06T15:10:47.267Z" }, + { url = "https://files.pythonhosted.org/packages/d6/ec/4acaf21483e18aa945be74a474c74b434f284b549f275a0a39b9f98956e9/orjson-3.11.9-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:6cc7923789694fd58f001cbcac7e47abc13af4d560ebbfcf3b41a8b1a0748124", size = 122356, upload-time = "2026-05-06T15:10:48.765Z" }, + { url = "https://files.pythonhosted.org/packages/13/d8/5f0555e7638801323b7a75850f92e7dfa891bc84fe27a1ba4449170d1200/orjson-3.11.9-cp314-cp314-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ea5c46eb2d3af39e806b986f4b09d5c2706a1f5afde3cbf7544ce6616127173c", size = 129592, upload-time = "2026-05-06T15:10:50.13Z" }, + { url = "https://files.pythonhosted.org/packages/b6/30/ed9860412a3603ceb3c5955bfd72d28b9d0e7ba6ed81add14f83d7114236/orjson-3.11.9-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f5d89a2ed90731df3be64bab0aa44f78bff39fdc9d71c291f4a8023aa46425b7", size = 140491, upload-time = "2026-05-06T15:10:51.582Z" }, + { url = "https://files.pythonhosted.org/packages/d0/17/adc514dea7ac7c505527febf884934b815d34f0c7b8693c1a8b39c5c4a57/orjson-3.11.9-cp314-cp314-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:25e4aed0312d292c09f61af25bba34e0b2c88546041472b09088c39a4d828af1", size = 127309, upload-time = "2026-05-06T15:10:53.329Z" }, + { url = "https://files.pythonhosted.org/packages/76/3e/c0b690253f0b82d86e99949af13533363acfb5432ecb5d53dd5b3bce9c34/orjson-3.11.9-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:aaea64f3f467d22e70eeed68bdccb3bc4f83f650446c4a03c59f2cba28a108db", size = 134030, upload-time = "2026-05-06T15:10:54.988Z" }, + { url = "https://files.pythonhosted.org/packages/c1/7a/bc82a0bb25e9faaf92dc4d9ef002732efc09737706af83e346788641d4a7/orjson-3.11.9-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:a028425d1b440c5d92a6be1e1a020739dfe67ea87d96c6dbe828c1b30041728b", size = 141482, upload-time = "2026-05-06T15:10:56.663Z" }, + { url = "https://files.pythonhosted.org/packages/01/55/e69188b939f77d5d32a9833745ace31ea5ccae3ab613a1ec185d3cd2c4fb/orjson-3.11.9-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:5b192c6cf397e4455b11523c5cf2b18ed084c1bbd61b6c0926344d2129481972", size = 415178, upload-time = "2026-05-06T15:10:58.446Z" }, + { url = "https://files.pythonhosted.org/packages/2e/1a/b8a5a7ac527e80b9cb11d51e3f6689b709279183264b9ec5c7bc680bb8b5/orjson-3.11.9-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:ea407d4ccf5891d667d045fecae97a7a1e5e87b3b97f97ae1803c2e741130be0", size = 148089, upload-time = "2026-05-06T15:11:00.441Z" }, + { url = "https://files.pythonhosted.org/packages/97/4e/00503f64204bf859b37213a63927028f30fb6268cd8677fb0a5ad48155e1/orjson-3.11.9-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:5f63aaf97afd9f6dec5b1a68e1b8da12bfccb4cb9a9a65c3e0b6c847849e7586", size = 136921, upload-time = "2026-05-06T15:11:02.176Z" }, + { url = "https://files.pythonhosted.org/packages/0d/ba/a23b82a0a8d0ed7bed4e5f5035aae751cad4ff6a1e8d2ecd14d8860f5929/orjson-3.11.9-cp314-cp314-win32.whl", hash = "sha256:e30ab17845bb9fa54ccf67fa4f9f5282652d54faa6d17452f47d0f369d038673", size = 131638, upload-time = "2026-05-06T15:11:03.696Z" }, + { url = "https://files.pythonhosted.org/packages/f3/c3/0c6798456bade745c75c452342dabacce5798196483e77e643be1f53877d/orjson-3.11.9-cp314-cp314-win_amd64.whl", hash = "sha256:32ef5f4283a3be81913947d19608eacb7c6608026851123790cd9cc8982af34b", size = 127078, upload-time = "2026-05-06T15:11:05.123Z" }, + { url = "https://files.pythonhosted.org/packages/16/21/5a3f1e8913103b703a436a5664238e5b965ec392b555fe68943ea3691e6b/orjson-3.11.9-cp314-cp314-win_arm64.whl", hash = "sha256:eebdbdeef0094e4f5aefa20dcd4eb2368ab5e7a3b4edea27f1e7b2892e009cf9", size = 126687, upload-time = "2026-05-06T15:11:06.602Z" }, ] [[package]] @@ -3883,11 +3946,11 @@ wheels = [ [[package]] name = "packaging" -version = "26.1" +version = "26.2" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/df/de/0d2b39fb4af88a0258f3bac87dfcbb48e73fbdea4a2ed0e2213f9a4c2f9a/packaging-26.1.tar.gz", hash = "sha256:f042152b681c4bfac5cae2742a55e103d27ab2ec0f3d88037136b6bfe7c9c5de", size = 215519, upload-time = "2026-04-14T21:12:49.362Z" } +sdist = { url = "https://files.pythonhosted.org/packages/d7/f1/e7a6dd94a8d4a5626c03e4e99c87f241ba9e350cd9e6d75123f992427270/packaging-26.2.tar.gz", hash = "sha256:ff452ff5a3e828ce110190feff1178bb1f2ea2281fa2075aadb987c2fb221661", size = 228134, upload-time = "2026-04-24T20:15:23.917Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/7a/c2/920ef838e2f0028c8262f16101ec09ebd5969864e5a64c4c05fad0617c56/packaging-26.1-py3-none-any.whl", hash = "sha256:5d9c0669c6285e491e0ced2eee587eaf67b670d94a19e94e3984a481aba6802f", size = 95831, upload-time = "2026-04-14T21:12:47.56Z" }, + { url = "https://files.pythonhosted.org/packages/df/b2/87e62e8c3e2f4b32e5fe99e0b86d576da1312593b39f47d8ceef365e95ed/packaging-26.2-py3-none-any.whl", hash = "sha256:5fc45236b9446107ff2415ce77c807cee2862cb6fac22b8a73826d0693b0980e", size = 100195, upload-time = "2026-04-24T20:15:22.081Z" }, ] [[package]] @@ -3901,11 +3964,11 @@ wheels = [ [[package]] name = "pathspec" -version = "1.1.0" +version = "1.1.1" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/2e/17/9c3094b822982b9f1ea666d8580ce59000f61f87c1663556fb72031ad9ec/pathspec-1.1.0.tar.gz", hash = "sha256:f5d7c555da02fd8dde3e4a2354b6aba817a89112fa8f333f7917a2a4834dd080", size = 133918, upload-time = "2026-04-23T01:46:22.298Z" } +sdist = { url = "https://files.pythonhosted.org/packages/5a/82/42f767fc1c1143d6fd36efb827202a2d997a375e160a71eb2888a925aac1/pathspec-1.1.1.tar.gz", hash = "sha256:17db5ecd524104a120e173814c90367a96a98d07c45b2e10c2f3919fff91bf5a", size = 135180, upload-time = "2026-04-27T01:46:08.907Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/fa/c9/8eed0486f074e9f1ca7f8ce5ad663e65f12fdab344028d658fa1b03d35e0/pathspec-1.1.0-py3-none-any.whl", hash = "sha256:574b128f7456bd899045ccd142dd446af7e6cfd0072d63ad73fbc55fbb4aaa42", size = 56264, upload-time = "2026-04-23T01:46:20.606Z" }, + { url = "https://files.pythonhosted.org/packages/f1/d9/7fb5aa316bc299258e68c73ba3bddbc499654a07f151cba08f6153988714/pathspec-1.1.1-py3-none-any.whl", hash = "sha256:a00ce642f577bf7f473932318056212bc4f8bfdf53128c78bbd5af0b9b20b189", size = 57328, upload-time = "2026-04-27T01:46:07.06Z" }, ] [[package]] @@ -4017,11 +4080,11 @@ wheels = [ [[package]] name = "platformdirs" -version = "4.9.6" +version = "4.10.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/9f/4a/0883b8e3802965322523f0b200ecf33d31f10991d0401162f4b23c698b42/platformdirs-4.9.6.tar.gz", hash = "sha256:3bfa75b0ad0db84096ae777218481852c0ebc6c727b3168c1b9e0118e458cf0a", size = 29400, upload-time = "2026-04-09T00:04:10.812Z" } +sdist = { url = "https://files.pythonhosted.org/packages/d7/47/e4501f49c178ae1d9f4a75073fda4204f52647993f075a9db4d14930e0c5/platformdirs-4.10.0.tar.gz", hash = "sha256:31e761a6a0ca04faf7353ea759bdba55652be214725111e5aac52dfa29d4bef7", size = 31224, upload-time = "2026-05-28T03:32:53.587Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/75/a6/a0a304dc33b49145b21f4808d763822111e67d1c3a32b524a1baf947b6e1/platformdirs-4.9.6-py3-none-any.whl", hash = "sha256:e61adb1d5e5cb3441b4b7710bea7e4c12250ca49439228cc1021c00dcfac0917", size = 21348, upload-time = "2026-04-09T00:04:09.463Z" }, + { url = "https://files.pythonhosted.org/packages/81/e6/cd9575ac904136b3cbf7aa7ee819ef86eedb7274e46f230e94ea4342e729/platformdirs-4.10.0-py3-none-any.whl", hash = "sha256:fb516cdb12eb0d857d0cd85a7c57cea4d060bee4578d6cf5a14dfdf8cbf8784a", size = 22743, upload-time = "2026-05-28T03:32:52.175Z" }, ] [[package]] @@ -4047,128 +4110,142 @@ wheels = [ [[package]] name = "propcache" -version = "0.4.1" +version = "0.5.2" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/9e/da/e9fc233cf63743258bff22b3dfa7ea5baef7b5bc324af47a0ad89b8ffc6f/propcache-0.4.1.tar.gz", hash = "sha256:f48107a8c637e80362555f37ecf49abe20370e557cc4ab374f04ec4423c97c3d", size = 46442, upload-time = "2025-10-08T19:49:02.291Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/3c/0e/934b541323035566a9af292dba85a195f7b78179114f2c6ebb24551118a9/propcache-0.4.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:7c2d1fa3201efaf55d730400d945b5b3ab6e672e100ba0f9a409d950ab25d7db", size = 79534, upload-time = "2025-10-08T19:46:02.083Z" }, - { url = "https://files.pythonhosted.org/packages/a1/6b/db0d03d96726d995dc7171286c6ba9d8d14251f37433890f88368951a44e/propcache-0.4.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:1eb2994229cc8ce7fe9b3db88f5465f5fd8651672840b2e426b88cdb1a30aac8", size = 45526, upload-time = "2025-10-08T19:46:03.884Z" }, - { url = "https://files.pythonhosted.org/packages/e4/c3/82728404aea669e1600f304f2609cde9e665c18df5a11cdd57ed73c1dceb/propcache-0.4.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:66c1f011f45a3b33d7bcb22daed4b29c0c9e2224758b6be00686731e1b46f925", size = 47263, upload-time = "2025-10-08T19:46:05.405Z" }, - { url = "https://files.pythonhosted.org/packages/df/1b/39313ddad2bf9187a1432654c38249bab4562ef535ef07f5eb6eb04d0b1b/propcache-0.4.1-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:9a52009f2adffe195d0b605c25ec929d26b36ef986ba85244891dee3b294df21", size = 201012, upload-time = "2025-10-08T19:46:07.165Z" }, - { url = "https://files.pythonhosted.org/packages/5b/01/f1d0b57d136f294a142acf97f4ed58c8e5b974c21e543000968357115011/propcache-0.4.1-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:5d4e2366a9c7b837555cf02fb9be2e3167d333aff716332ef1b7c3a142ec40c5", size = 209491, upload-time = "2025-10-08T19:46:08.909Z" }, - { url = "https://files.pythonhosted.org/packages/a1/c8/038d909c61c5bb039070b3fb02ad5cccdb1dde0d714792e251cdb17c9c05/propcache-0.4.1-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:9d2b6caef873b4f09e26ea7e33d65f42b944837563a47a94719cc3544319a0db", size = 215319, upload-time = "2025-10-08T19:46:10.7Z" }, - { url = "https://files.pythonhosted.org/packages/08/57/8c87e93142b2c1fa2408e45695205a7ba05fb5db458c0bf5c06ba0e09ea6/propcache-0.4.1-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:2b16ec437a8c8a965ecf95739448dd938b5c7f56e67ea009f4300d8df05f32b7", size = 196856, upload-time = "2025-10-08T19:46:12.003Z" }, - { url = "https://files.pythonhosted.org/packages/42/df/5615fec76aa561987a534759b3686008a288e73107faa49a8ae5795a9f7a/propcache-0.4.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:296f4c8ed03ca7476813fe666c9ea97869a8d7aec972618671b33a38a5182ef4", size = 193241, upload-time = "2025-10-08T19:46:13.495Z" }, - { url = "https://files.pythonhosted.org/packages/d5/21/62949eb3a7a54afe8327011c90aca7e03547787a88fb8bd9726806482fea/propcache-0.4.1-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:1f0978529a418ebd1f49dad413a2b68af33f85d5c5ca5c6ca2a3bed375a7ac60", size = 190552, upload-time = "2025-10-08T19:46:14.938Z" }, - { url = "https://files.pythonhosted.org/packages/30/ee/ab4d727dd70806e5b4de96a798ae7ac6e4d42516f030ee60522474b6b332/propcache-0.4.1-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:fd138803047fb4c062b1c1dd95462f5209456bfab55c734458f15d11da288f8f", size = 200113, upload-time = "2025-10-08T19:46:16.695Z" }, - { url = "https://files.pythonhosted.org/packages/8a/0b/38b46208e6711b016aa8966a3ac793eee0d05c7159d8342aa27fc0bc365e/propcache-0.4.1-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:8c9b3cbe4584636d72ff556d9036e0c9317fa27b3ac1f0f558e7e84d1c9c5900", size = 200778, upload-time = "2025-10-08T19:46:18.023Z" }, - { url = "https://files.pythonhosted.org/packages/cf/81/5abec54355ed344476bee711e9f04815d4b00a311ab0535599204eecc257/propcache-0.4.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:f93243fdc5657247533273ac4f86ae106cc6445a0efacb9a1bfe982fcfefd90c", size = 193047, upload-time = "2025-10-08T19:46:19.449Z" }, - { url = "https://files.pythonhosted.org/packages/ec/b6/1f237c04e32063cb034acd5f6ef34ef3a394f75502e72703545631ab1ef6/propcache-0.4.1-cp310-cp310-win32.whl", hash = "sha256:a0ee98db9c5f80785b266eb805016e36058ac72c51a064040f2bc43b61101cdb", size = 38093, upload-time = "2025-10-08T19:46:20.643Z" }, - { url = "https://files.pythonhosted.org/packages/a6/67/354aac4e0603a15f76439caf0427781bcd6797f370377f75a642133bc954/propcache-0.4.1-cp310-cp310-win_amd64.whl", hash = "sha256:1cdb7988c4e5ac7f6d175a28a9aa0c94cb6f2ebe52756a3c0cda98d2809a9e37", size = 41638, upload-time = "2025-10-08T19:46:21.935Z" }, - { url = "https://files.pythonhosted.org/packages/e0/e1/74e55b9fd1a4c209ff1a9a824bf6c8b3d1fc5a1ac3eabe23462637466785/propcache-0.4.1-cp310-cp310-win_arm64.whl", hash = "sha256:d82ad62b19645419fe79dd63b3f9253e15b30e955c0170e5cebc350c1844e581", size = 38229, upload-time = "2025-10-08T19:46:23.368Z" }, - { url = "https://files.pythonhosted.org/packages/8c/d4/4e2c9aaf7ac2242b9358f98dccd8f90f2605402f5afeff6c578682c2c491/propcache-0.4.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:60a8fda9644b7dfd5dece8c61d8a85e271cb958075bfc4e01083c148b61a7caf", size = 80208, upload-time = "2025-10-08T19:46:24.597Z" }, - { url = "https://files.pythonhosted.org/packages/c2/21/d7b68e911f9c8e18e4ae43bdbc1e1e9bbd971f8866eb81608947b6f585ff/propcache-0.4.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c30b53e7e6bda1d547cabb47c825f3843a0a1a42b0496087bb58d8fedf9f41b5", size = 45777, upload-time = "2025-10-08T19:46:25.733Z" }, - { url = "https://files.pythonhosted.org/packages/d3/1d/11605e99ac8ea9435651ee71ab4cb4bf03f0949586246476a25aadfec54a/propcache-0.4.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:6918ecbd897443087a3b7cd978d56546a812517dcaaca51b49526720571fa93e", size = 47647, upload-time = "2025-10-08T19:46:27.304Z" }, - { url = "https://files.pythonhosted.org/packages/58/1a/3c62c127a8466c9c843bccb503d40a273e5cc69838805f322e2826509e0d/propcache-0.4.1-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3d902a36df4e5989763425a8ab9e98cd8ad5c52c823b34ee7ef307fd50582566", size = 214929, upload-time = "2025-10-08T19:46:28.62Z" }, - { url = "https://files.pythonhosted.org/packages/56/b9/8fa98f850960b367c4b8fe0592e7fc341daa7a9462e925228f10a60cf74f/propcache-0.4.1-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:a9695397f85973bb40427dedddf70d8dc4a44b22f1650dd4af9eedf443d45165", size = 221778, upload-time = "2025-10-08T19:46:30.358Z" }, - { url = "https://files.pythonhosted.org/packages/46/a6/0ab4f660eb59649d14b3d3d65c439421cf2f87fe5dd68591cbe3c1e78a89/propcache-0.4.1-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:2bb07ffd7eaad486576430c89f9b215f9e4be68c4866a96e97db9e97fead85dc", size = 228144, upload-time = "2025-10-08T19:46:32.607Z" }, - { url = "https://files.pythonhosted.org/packages/52/6a/57f43e054fb3d3a56ac9fc532bc684fc6169a26c75c353e65425b3e56eef/propcache-0.4.1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:fd6f30fdcf9ae2a70abd34da54f18da086160e4d7d9251f81f3da0ff84fc5a48", size = 210030, upload-time = "2025-10-08T19:46:33.969Z" }, - { url = "https://files.pythonhosted.org/packages/40/e2/27e6feebb5f6b8408fa29f5efbb765cd54c153ac77314d27e457a3e993b7/propcache-0.4.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:fc38cba02d1acba4e2869eef1a57a43dfbd3d49a59bf90dda7444ec2be6a5570", size = 208252, upload-time = "2025-10-08T19:46:35.309Z" }, - { url = "https://files.pythonhosted.org/packages/9e/f8/91c27b22ccda1dbc7967f921c42825564fa5336a01ecd72eb78a9f4f53c2/propcache-0.4.1-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:67fad6162281e80e882fb3ec355398cf72864a54069d060321f6cd0ade95fe85", size = 202064, upload-time = "2025-10-08T19:46:36.993Z" }, - { url = "https://files.pythonhosted.org/packages/f2/26/7f00bd6bd1adba5aafe5f4a66390f243acab58eab24ff1a08bebb2ef9d40/propcache-0.4.1-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:f10207adf04d08bec185bae14d9606a1444715bc99180f9331c9c02093e1959e", size = 212429, upload-time = "2025-10-08T19:46:38.398Z" }, - { url = "https://files.pythonhosted.org/packages/84/89/fd108ba7815c1117ddca79c228f3f8a15fc82a73bca8b142eb5de13b2785/propcache-0.4.1-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:e9b0d8d0845bbc4cfcdcbcdbf5086886bc8157aa963c31c777ceff7846c77757", size = 216727, upload-time = "2025-10-08T19:46:39.732Z" }, - { url = "https://files.pythonhosted.org/packages/79/37/3ec3f7e3173e73f1d600495d8b545b53802cbf35506e5732dd8578db3724/propcache-0.4.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:981333cb2f4c1896a12f4ab92a9cc8f09ea664e9b7dbdc4eff74627af3a11c0f", size = 205097, upload-time = "2025-10-08T19:46:41.025Z" }, - { url = "https://files.pythonhosted.org/packages/61/b0/b2631c19793f869d35f47d5a3a56fb19e9160d3c119f15ac7344fc3ccae7/propcache-0.4.1-cp311-cp311-win32.whl", hash = "sha256:f1d2f90aeec838a52f1c1a32fe9a619fefd5e411721a9117fbf82aea638fe8a1", size = 38084, upload-time = "2025-10-08T19:46:42.693Z" }, - { url = "https://files.pythonhosted.org/packages/f4/78/6cce448e2098e9f3bfc91bb877f06aa24b6ccace872e39c53b2f707c4648/propcache-0.4.1-cp311-cp311-win_amd64.whl", hash = "sha256:364426a62660f3f699949ac8c621aad6977be7126c5807ce48c0aeb8e7333ea6", size = 41637, upload-time = "2025-10-08T19:46:43.778Z" }, - { url = "https://files.pythonhosted.org/packages/9c/e9/754f180cccd7f51a39913782c74717c581b9cc8177ad0e949f4d51812383/propcache-0.4.1-cp311-cp311-win_arm64.whl", hash = "sha256:e53f3a38d3510c11953f3e6a33f205c6d1b001129f972805ca9b42fc308bc239", size = 38064, upload-time = "2025-10-08T19:46:44.872Z" }, - { url = "https://files.pythonhosted.org/packages/a2/0f/f17b1b2b221d5ca28b4b876e8bb046ac40466513960646bda8e1853cdfa2/propcache-0.4.1-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:e153e9cd40cc8945138822807139367f256f89c6810c2634a4f6902b52d3b4e2", size = 80061, upload-time = "2025-10-08T19:46:46.075Z" }, - { url = "https://files.pythonhosted.org/packages/76/47/8ccf75935f51448ba9a16a71b783eb7ef6b9ee60f5d14c7f8a8a79fbeed7/propcache-0.4.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:cd547953428f7abb73c5ad82cbb32109566204260d98e41e5dfdc682eb7f8403", size = 46037, upload-time = "2025-10-08T19:46:47.23Z" }, - { url = "https://files.pythonhosted.org/packages/0a/b6/5c9a0e42df4d00bfb4a3cbbe5cf9f54260300c88a0e9af1f47ca5ce17ac0/propcache-0.4.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:f048da1b4f243fc44f205dfd320933a951b8d89e0afd4c7cacc762a8b9165207", size = 47324, upload-time = "2025-10-08T19:46:48.384Z" }, - { url = "https://files.pythonhosted.org/packages/9e/d3/6c7ee328b39a81ee877c962469f1e795f9db87f925251efeb0545e0020d0/propcache-0.4.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ec17c65562a827bba85e3872ead335f95405ea1674860d96483a02f5c698fa72", size = 225505, upload-time = "2025-10-08T19:46:50.055Z" }, - { url = "https://files.pythonhosted.org/packages/01/5d/1c53f4563490b1d06a684742cc6076ef944bc6457df6051b7d1a877c057b/propcache-0.4.1-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:405aac25c6394ef275dee4c709be43745d36674b223ba4eb7144bf4d691b7367", size = 230242, upload-time = "2025-10-08T19:46:51.815Z" }, - { url = "https://files.pythonhosted.org/packages/20/e1/ce4620633b0e2422207c3cb774a0ee61cac13abc6217763a7b9e2e3f4a12/propcache-0.4.1-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:0013cb6f8dde4b2a2f66903b8ba740bdfe378c943c4377a200551ceb27f379e4", size = 238474, upload-time = "2025-10-08T19:46:53.208Z" }, - { url = "https://files.pythonhosted.org/packages/46/4b/3aae6835b8e5f44ea6a68348ad90f78134047b503765087be2f9912140ea/propcache-0.4.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:15932ab57837c3368b024473a525e25d316d8353016e7cc0e5ba9eb343fbb1cf", size = 221575, upload-time = "2025-10-08T19:46:54.511Z" }, - { url = "https://files.pythonhosted.org/packages/6e/a5/8a5e8678bcc9d3a1a15b9a29165640d64762d424a16af543f00629c87338/propcache-0.4.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:031dce78b9dc099f4c29785d9cf5577a3faf9ebf74ecbd3c856a7b92768c3df3", size = 216736, upload-time = "2025-10-08T19:46:56.212Z" }, - { url = "https://files.pythonhosted.org/packages/f1/63/b7b215eddeac83ca1c6b934f89d09a625aa9ee4ba158338854c87210cc36/propcache-0.4.1-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:ab08df6c9a035bee56e31af99be621526bd237bea9f32def431c656b29e41778", size = 213019, upload-time = "2025-10-08T19:46:57.595Z" }, - { url = "https://files.pythonhosted.org/packages/57/74/f580099a58c8af587cac7ba19ee7cb418506342fbbe2d4a4401661cca886/propcache-0.4.1-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:4d7af63f9f93fe593afbf104c21b3b15868efb2c21d07d8732c0c4287e66b6a6", size = 220376, upload-time = "2025-10-08T19:46:59.067Z" }, - { url = "https://files.pythonhosted.org/packages/c4/ee/542f1313aff7eaf19c2bb758c5d0560d2683dac001a1c96d0774af799843/propcache-0.4.1-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:cfc27c945f422e8b5071b6e93169679e4eb5bf73bbcbf1ba3ae3a83d2f78ebd9", size = 226988, upload-time = "2025-10-08T19:47:00.544Z" }, - { url = "https://files.pythonhosted.org/packages/8f/18/9c6b015dd9c6930f6ce2229e1f02fb35298b847f2087ea2b436a5bfa7287/propcache-0.4.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:35c3277624a080cc6ec6f847cbbbb5b49affa3598c4535a0a4682a697aaa5c75", size = 215615, upload-time = "2025-10-08T19:47:01.968Z" }, - { url = "https://files.pythonhosted.org/packages/80/9e/e7b85720b98c45a45e1fca6a177024934dc9bc5f4d5dd04207f216fc33ed/propcache-0.4.1-cp312-cp312-win32.whl", hash = "sha256:671538c2262dadb5ba6395e26c1731e1d52534bfe9ae56d0b5573ce539266aa8", size = 38066, upload-time = "2025-10-08T19:47:03.503Z" }, - { url = "https://files.pythonhosted.org/packages/54/09/d19cff2a5aaac632ec8fc03737b223597b1e347416934c1b3a7df079784c/propcache-0.4.1-cp312-cp312-win_amd64.whl", hash = "sha256:cb2d222e72399fcf5890d1d5cc1060857b9b236adff2792ff48ca2dfd46c81db", size = 41655, upload-time = "2025-10-08T19:47:04.973Z" }, - { url = "https://files.pythonhosted.org/packages/68/ab/6b5c191bb5de08036a8c697b265d4ca76148efb10fa162f14af14fb5f076/propcache-0.4.1-cp312-cp312-win_arm64.whl", hash = "sha256:204483131fb222bdaaeeea9f9e6c6ed0cac32731f75dfc1d4a567fc1926477c1", size = 37789, upload-time = "2025-10-08T19:47:06.077Z" }, - { url = "https://files.pythonhosted.org/packages/bf/df/6d9c1b6ac12b003837dde8a10231a7344512186e87b36e855bef32241942/propcache-0.4.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:43eedf29202c08550aac1d14e0ee619b0430aaef78f85864c1a892294fbc28cf", size = 77750, upload-time = "2025-10-08T19:47:07.648Z" }, - { url = "https://files.pythonhosted.org/packages/8b/e8/677a0025e8a2acf07d3418a2e7ba529c9c33caf09d3c1f25513023c1db56/propcache-0.4.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:d62cdfcfd89ccb8de04e0eda998535c406bf5e060ffd56be6c586cbcc05b3311", size = 44780, upload-time = "2025-10-08T19:47:08.851Z" }, - { url = "https://files.pythonhosted.org/packages/89/a4/92380f7ca60f99ebae761936bc48a72a639e8a47b29050615eef757cb2a7/propcache-0.4.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:cae65ad55793da34db5f54e4029b89d3b9b9490d8abe1b4c7ab5d4b8ec7ebf74", size = 46308, upload-time = "2025-10-08T19:47:09.982Z" }, - { url = "https://files.pythonhosted.org/packages/2d/48/c5ac64dee5262044348d1d78a5f85dd1a57464a60d30daee946699963eb3/propcache-0.4.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:333ddb9031d2704a301ee3e506dc46b1fe5f294ec198ed6435ad5b6a085facfe", size = 208182, upload-time = "2025-10-08T19:47:11.319Z" }, - { url = "https://files.pythonhosted.org/packages/c6/0c/cd762dd011a9287389a6a3eb43aa30207bde253610cca06824aeabfe9653/propcache-0.4.1-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:fd0858c20f078a32cf55f7e81473d96dcf3b93fd2ccdb3d40fdf54b8573df3af", size = 211215, upload-time = "2025-10-08T19:47:13.146Z" }, - { url = "https://files.pythonhosted.org/packages/30/3e/49861e90233ba36890ae0ca4c660e95df565b2cd15d4a68556ab5865974e/propcache-0.4.1-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:678ae89ebc632c5c204c794f8dab2837c5f159aeb59e6ed0539500400577298c", size = 218112, upload-time = "2025-10-08T19:47:14.913Z" }, - { url = "https://files.pythonhosted.org/packages/f1/8b/544bc867e24e1bd48f3118cecd3b05c694e160a168478fa28770f22fd094/propcache-0.4.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d472aeb4fbf9865e0c6d622d7f4d54a4e101a89715d8904282bb5f9a2f476c3f", size = 204442, upload-time = "2025-10-08T19:47:16.277Z" }, - { url = "https://files.pythonhosted.org/packages/50/a6/4282772fd016a76d3e5c0df58380a5ea64900afd836cec2c2f662d1b9bb3/propcache-0.4.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:4d3df5fa7e36b3225954fba85589da77a0fe6a53e3976de39caf04a0db4c36f1", size = 199398, upload-time = "2025-10-08T19:47:17.962Z" }, - { url = "https://files.pythonhosted.org/packages/3e/ec/d8a7cd406ee1ddb705db2139f8a10a8a427100347bd698e7014351c7af09/propcache-0.4.1-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:ee17f18d2498f2673e432faaa71698032b0127ebf23ae5974eeaf806c279df24", size = 196920, upload-time = "2025-10-08T19:47:19.355Z" }, - { url = "https://files.pythonhosted.org/packages/f6/6c/f38ab64af3764f431e359f8baf9e0a21013e24329e8b85d2da32e8ed07ca/propcache-0.4.1-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:580e97762b950f993ae618e167e7be9256b8353c2dcd8b99ec100eb50f5286aa", size = 203748, upload-time = "2025-10-08T19:47:21.338Z" }, - { url = "https://files.pythonhosted.org/packages/d6/e3/fa846bd70f6534d647886621388f0a265254d30e3ce47e5c8e6e27dbf153/propcache-0.4.1-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:501d20b891688eb8e7aa903021f0b72d5a55db40ffaab27edefd1027caaafa61", size = 205877, upload-time = "2025-10-08T19:47:23.059Z" }, - { url = "https://files.pythonhosted.org/packages/e2/39/8163fc6f3133fea7b5f2827e8eba2029a0277ab2c5beee6c1db7b10fc23d/propcache-0.4.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:9a0bd56e5b100aef69bd8562b74b46254e7c8812918d3baa700c8a8009b0af66", size = 199437, upload-time = "2025-10-08T19:47:24.445Z" }, - { url = "https://files.pythonhosted.org/packages/93/89/caa9089970ca49c7c01662bd0eeedfe85494e863e8043565aeb6472ce8fe/propcache-0.4.1-cp313-cp313-win32.whl", hash = "sha256:bcc9aaa5d80322bc2fb24bb7accb4a30f81e90ab8d6ba187aec0744bc302ad81", size = 37586, upload-time = "2025-10-08T19:47:25.736Z" }, - { url = "https://files.pythonhosted.org/packages/f5/ab/f76ec3c3627c883215b5c8080debb4394ef5a7a29be811f786415fc1e6fd/propcache-0.4.1-cp313-cp313-win_amd64.whl", hash = "sha256:381914df18634f5494334d201e98245c0596067504b9372d8cf93f4bb23e025e", size = 40790, upload-time = "2025-10-08T19:47:26.847Z" }, - { url = "https://files.pythonhosted.org/packages/59/1b/e71ae98235f8e2ba5004d8cb19765a74877abf189bc53fc0c80d799e56c3/propcache-0.4.1-cp313-cp313-win_arm64.whl", hash = "sha256:8873eb4460fd55333ea49b7d189749ecf6e55bf85080f11b1c4530ed3034cba1", size = 37158, upload-time = "2025-10-08T19:47:27.961Z" }, - { url = "https://files.pythonhosted.org/packages/83/ce/a31bbdfc24ee0dcbba458c8175ed26089cf109a55bbe7b7640ed2470cfe9/propcache-0.4.1-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:92d1935ee1f8d7442da9c0c4fa7ac20d07e94064184811b685f5c4fada64553b", size = 81451, upload-time = "2025-10-08T19:47:29.445Z" }, - { url = "https://files.pythonhosted.org/packages/25/9c/442a45a470a68456e710d96cacd3573ef26a1d0a60067e6a7d5e655621ed/propcache-0.4.1-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:473c61b39e1460d386479b9b2f337da492042447c9b685f28be4f74d3529e566", size = 46374, upload-time = "2025-10-08T19:47:30.579Z" }, - { url = "https://files.pythonhosted.org/packages/f4/bf/b1d5e21dbc3b2e889ea4327044fb16312a736d97640fb8b6aa3f9c7b3b65/propcache-0.4.1-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:c0ef0aaafc66fbd87842a3fe3902fd889825646bc21149eafe47be6072725835", size = 48396, upload-time = "2025-10-08T19:47:31.79Z" }, - { url = "https://files.pythonhosted.org/packages/f4/04/5b4c54a103d480e978d3c8a76073502b18db0c4bc17ab91b3cb5092ad949/propcache-0.4.1-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f95393b4d66bfae908c3ca8d169d5f79cd65636ae15b5e7a4f6e67af675adb0e", size = 275950, upload-time = "2025-10-08T19:47:33.481Z" }, - { url = "https://files.pythonhosted.org/packages/b4/c1/86f846827fb969c4b78b0af79bba1d1ea2156492e1b83dea8b8a6ae27395/propcache-0.4.1-cp313-cp313t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:c07fda85708bc48578467e85099645167a955ba093be0a2dcba962195676e859", size = 273856, upload-time = "2025-10-08T19:47:34.906Z" }, - { url = "https://files.pythonhosted.org/packages/36/1d/fc272a63c8d3bbad6878c336c7a7dea15e8f2d23a544bda43205dfa83ada/propcache-0.4.1-cp313-cp313t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:af223b406d6d000830c6f65f1e6431783fc3f713ba3e6cc8c024d5ee96170a4b", size = 280420, upload-time = "2025-10-08T19:47:36.338Z" }, - { url = "https://files.pythonhosted.org/packages/07/0c/01f2219d39f7e53d52e5173bcb09c976609ba30209912a0680adfb8c593a/propcache-0.4.1-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a78372c932c90ee474559c5ddfffd718238e8673c340dc21fe45c5b8b54559a0", size = 263254, upload-time = "2025-10-08T19:47:37.692Z" }, - { url = "https://files.pythonhosted.org/packages/2d/18/cd28081658ce597898f0c4d174d4d0f3c5b6d4dc27ffafeef835c95eb359/propcache-0.4.1-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:564d9f0d4d9509e1a870c920a89b2fec951b44bf5ba7d537a9e7c1ccec2c18af", size = 261205, upload-time = "2025-10-08T19:47:39.659Z" }, - { url = "https://files.pythonhosted.org/packages/7a/71/1f9e22eb8b8316701c2a19fa1f388c8a3185082607da8e406a803c9b954e/propcache-0.4.1-cp313-cp313t-musllinux_1_2_armv7l.whl", hash = "sha256:17612831fda0138059cc5546f4d12a2aacfb9e47068c06af35c400ba58ba7393", size = 247873, upload-time = "2025-10-08T19:47:41.084Z" }, - { url = "https://files.pythonhosted.org/packages/4a/65/3d4b61f36af2b4eddba9def857959f1016a51066b4f1ce348e0cf7881f58/propcache-0.4.1-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:41a89040cb10bd345b3c1a873b2bf36413d48da1def52f268a055f7398514874", size = 262739, upload-time = "2025-10-08T19:47:42.51Z" }, - { url = "https://files.pythonhosted.org/packages/2a/42/26746ab087faa77c1c68079b228810436ccd9a5ce9ac85e2b7307195fd06/propcache-0.4.1-cp313-cp313t-musllinux_1_2_s390x.whl", hash = "sha256:e35b88984e7fa64aacecea39236cee32dd9bd8c55f57ba8a75cf2399553f9bd7", size = 263514, upload-time = "2025-10-08T19:47:43.927Z" }, - { url = "https://files.pythonhosted.org/packages/94/13/630690fe201f5502d2403dd3cfd451ed8858fe3c738ee88d095ad2ff407b/propcache-0.4.1-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:6f8b465489f927b0df505cbe26ffbeed4d6d8a2bbc61ce90eb074ff129ef0ab1", size = 257781, upload-time = "2025-10-08T19:47:45.448Z" }, - { url = "https://files.pythonhosted.org/packages/92/f7/1d4ec5841505f423469efbfc381d64b7b467438cd5a4bbcbb063f3b73d27/propcache-0.4.1-cp313-cp313t-win32.whl", hash = "sha256:2ad890caa1d928c7c2965b48f3a3815c853180831d0e5503d35cf00c472f4717", size = 41396, upload-time = "2025-10-08T19:47:47.202Z" }, - { url = "https://files.pythonhosted.org/packages/48/f0/615c30622316496d2cbbc29f5985f7777d3ada70f23370608c1d3e081c1f/propcache-0.4.1-cp313-cp313t-win_amd64.whl", hash = "sha256:f7ee0e597f495cf415bcbd3da3caa3bd7e816b74d0d52b8145954c5e6fd3ff37", size = 44897, upload-time = "2025-10-08T19:47:48.336Z" }, - { url = "https://files.pythonhosted.org/packages/fd/ca/6002e46eccbe0e33dcd4069ef32f7f1c9e243736e07adca37ae8c4830ec3/propcache-0.4.1-cp313-cp313t-win_arm64.whl", hash = "sha256:929d7cbe1f01bb7baffb33dc14eb5691c95831450a26354cd210a8155170c93a", size = 39789, upload-time = "2025-10-08T19:47:49.876Z" }, - { url = "https://files.pythonhosted.org/packages/8e/5c/bca52d654a896f831b8256683457ceddd490ec18d9ec50e97dfd8fc726a8/propcache-0.4.1-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:3f7124c9d820ba5548d431afb4632301acf965db49e666aa21c305cbe8c6de12", size = 78152, upload-time = "2025-10-08T19:47:51.051Z" }, - { url = "https://files.pythonhosted.org/packages/65/9b/03b04e7d82a5f54fb16113d839f5ea1ede58a61e90edf515f6577c66fa8f/propcache-0.4.1-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:c0d4b719b7da33599dfe3b22d3db1ef789210a0597bc650b7cee9c77c2be8c5c", size = 44869, upload-time = "2025-10-08T19:47:52.594Z" }, - { url = "https://files.pythonhosted.org/packages/b2/fa/89a8ef0468d5833a23fff277b143d0573897cf75bd56670a6d28126c7d68/propcache-0.4.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:9f302f4783709a78240ebc311b793f123328716a60911d667e0c036bc5dcbded", size = 46596, upload-time = "2025-10-08T19:47:54.073Z" }, - { url = "https://files.pythonhosted.org/packages/86/bd/47816020d337f4a746edc42fe8d53669965138f39ee117414c7d7a340cfe/propcache-0.4.1-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c80ee5802e3fb9ea37938e7eecc307fb984837091d5fd262bb37238b1ae97641", size = 206981, upload-time = "2025-10-08T19:47:55.715Z" }, - { url = "https://files.pythonhosted.org/packages/df/f6/c5fa1357cc9748510ee55f37173eb31bfde6d94e98ccd9e6f033f2fc06e1/propcache-0.4.1-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:ed5a841e8bb29a55fb8159ed526b26adc5bdd7e8bd7bf793ce647cb08656cdf4", size = 211490, upload-time = "2025-10-08T19:47:57.499Z" }, - { url = "https://files.pythonhosted.org/packages/80/1e/e5889652a7c4a3846683401a48f0f2e5083ce0ec1a8a5221d8058fbd1adf/propcache-0.4.1-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:55c72fd6ea2da4c318e74ffdf93c4fe4e926051133657459131a95c846d16d44", size = 215371, upload-time = "2025-10-08T19:47:59.317Z" }, - { url = "https://files.pythonhosted.org/packages/b2/f2/889ad4b2408f72fe1a4f6a19491177b30ea7bf1a0fd5f17050ca08cfc882/propcache-0.4.1-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8326e144341460402713f91df60ade3c999d601e7eb5ff8f6f7862d54de0610d", size = 201424, upload-time = "2025-10-08T19:48:00.67Z" }, - { url = "https://files.pythonhosted.org/packages/27/73/033d63069b57b0812c8bd19f311faebeceb6ba31b8f32b73432d12a0b826/propcache-0.4.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:060b16ae65bc098da7f6d25bf359f1f31f688384858204fe5d652979e0015e5b", size = 197566, upload-time = "2025-10-08T19:48:02.604Z" }, - { url = "https://files.pythonhosted.org/packages/dc/89/ce24f3dc182630b4e07aa6d15f0ff4b14ed4b9955fae95a0b54c58d66c05/propcache-0.4.1-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:89eb3fa9524f7bec9de6e83cf3faed9d79bffa560672c118a96a171a6f55831e", size = 193130, upload-time = "2025-10-08T19:48:04.499Z" }, - { url = "https://files.pythonhosted.org/packages/a9/24/ef0d5fd1a811fb5c609278d0209c9f10c35f20581fcc16f818da959fc5b4/propcache-0.4.1-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:dee69d7015dc235f526fe80a9c90d65eb0039103fe565776250881731f06349f", size = 202625, upload-time = "2025-10-08T19:48:06.213Z" }, - { url = "https://files.pythonhosted.org/packages/f5/02/98ec20ff5546f68d673df2f7a69e8c0d076b5abd05ca882dc7ee3a83653d/propcache-0.4.1-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:5558992a00dfd54ccbc64a32726a3357ec93825a418a401f5cc67df0ac5d9e49", size = 204209, upload-time = "2025-10-08T19:48:08.432Z" }, - { url = "https://files.pythonhosted.org/packages/a0/87/492694f76759b15f0467a2a93ab68d32859672b646aa8a04ce4864e7932d/propcache-0.4.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:c9b822a577f560fbd9554812526831712c1436d2c046cedee4c3796d3543b144", size = 197797, upload-time = "2025-10-08T19:48:09.968Z" }, - { url = "https://files.pythonhosted.org/packages/ee/36/66367de3575db1d2d3f3d177432bd14ee577a39d3f5d1b3d5df8afe3b6e2/propcache-0.4.1-cp314-cp314-win32.whl", hash = "sha256:ab4c29b49d560fe48b696cdcb127dd36e0bc2472548f3bf56cc5cb3da2b2984f", size = 38140, upload-time = "2025-10-08T19:48:11.232Z" }, - { url = "https://files.pythonhosted.org/packages/0c/2a/a758b47de253636e1b8aef181c0b4f4f204bf0dd964914fb2af90a95b49b/propcache-0.4.1-cp314-cp314-win_amd64.whl", hash = "sha256:5a103c3eb905fcea0ab98be99c3a9a5ab2de60228aa5aceedc614c0281cf6153", size = 41257, upload-time = "2025-10-08T19:48:12.707Z" }, - { url = "https://files.pythonhosted.org/packages/34/5e/63bd5896c3fec12edcbd6f12508d4890d23c265df28c74b175e1ef9f4f3b/propcache-0.4.1-cp314-cp314-win_arm64.whl", hash = "sha256:74c1fb26515153e482e00177a1ad654721bf9207da8a494a0c05e797ad27b992", size = 38097, upload-time = "2025-10-08T19:48:13.923Z" }, - { url = "https://files.pythonhosted.org/packages/99/85/9ff785d787ccf9bbb3f3106f79884a130951436f58392000231b4c737c80/propcache-0.4.1-cp314-cp314t-macosx_10_13_universal2.whl", hash = "sha256:824e908bce90fb2743bd6b59db36eb4f45cd350a39637c9f73b1c1ea66f5b75f", size = 81455, upload-time = "2025-10-08T19:48:15.16Z" }, - { url = "https://files.pythonhosted.org/packages/90/85/2431c10c8e7ddb1445c1f7c4b54d886e8ad20e3c6307e7218f05922cad67/propcache-0.4.1-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:c2b5e7db5328427c57c8e8831abda175421b709672f6cfc3d630c3b7e2146393", size = 46372, upload-time = "2025-10-08T19:48:16.424Z" }, - { url = "https://files.pythonhosted.org/packages/01/20/b0972d902472da9bcb683fa595099911f4d2e86e5683bcc45de60dd05dc3/propcache-0.4.1-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:6f6ff873ed40292cd4969ef5310179afd5db59fdf055897e282485043fc80ad0", size = 48411, upload-time = "2025-10-08T19:48:17.577Z" }, - { url = "https://files.pythonhosted.org/packages/e2/e3/7dc89f4f21e8f99bad3d5ddb3a3389afcf9da4ac69e3deb2dcdc96e74169/propcache-0.4.1-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:49a2dc67c154db2c1463013594c458881a069fcf98940e61a0569016a583020a", size = 275712, upload-time = "2025-10-08T19:48:18.901Z" }, - { url = "https://files.pythonhosted.org/packages/20/67/89800c8352489b21a8047c773067644e3897f02ecbbd610f4d46b7f08612/propcache-0.4.1-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:005f08e6a0529984491e37d8dbc3dd86f84bd78a8ceb5fa9a021f4c48d4984be", size = 273557, upload-time = "2025-10-08T19:48:20.762Z" }, - { url = "https://files.pythonhosted.org/packages/e2/a1/b52b055c766a54ce6d9c16d9aca0cad8059acd9637cdf8aa0222f4a026ef/propcache-0.4.1-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:5c3310452e0d31390da9035c348633b43d7e7feb2e37be252be6da45abd1abcc", size = 280015, upload-time = "2025-10-08T19:48:22.592Z" }, - { url = "https://files.pythonhosted.org/packages/48/c8/33cee30bd890672c63743049f3c9e4be087e6780906bfc3ec58528be59c1/propcache-0.4.1-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4c3c70630930447f9ef1caac7728c8ad1c56bc5015338b20fed0d08ea2480b3a", size = 262880, upload-time = "2025-10-08T19:48:23.947Z" }, - { url = "https://files.pythonhosted.org/packages/0c/b1/8f08a143b204b418285c88b83d00edbd61afbc2c6415ffafc8905da7038b/propcache-0.4.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:8e57061305815dfc910a3634dcf584f08168a8836e6999983569f51a8544cd89", size = 260938, upload-time = "2025-10-08T19:48:25.656Z" }, - { url = "https://files.pythonhosted.org/packages/cf/12/96e4664c82ca2f31e1c8dff86afb867348979eb78d3cb8546a680287a1e9/propcache-0.4.1-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:521a463429ef54143092c11a77e04056dd00636f72e8c45b70aaa3140d639726", size = 247641, upload-time = "2025-10-08T19:48:27.207Z" }, - { url = "https://files.pythonhosted.org/packages/18/ed/e7a9cfca28133386ba52278136d42209d3125db08d0a6395f0cba0c0285c/propcache-0.4.1-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:120c964da3fdc75e3731aa392527136d4ad35868cc556fd09bb6d09172d9a367", size = 262510, upload-time = "2025-10-08T19:48:28.65Z" }, - { url = "https://files.pythonhosted.org/packages/f5/76/16d8bf65e8845dd62b4e2b57444ab81f07f40caa5652b8969b87ddcf2ef6/propcache-0.4.1-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:d8f353eb14ee3441ee844ade4277d560cdd68288838673273b978e3d6d2c8f36", size = 263161, upload-time = "2025-10-08T19:48:30.133Z" }, - { url = "https://files.pythonhosted.org/packages/e7/70/c99e9edb5d91d5ad8a49fa3c1e8285ba64f1476782fed10ab251ff413ba1/propcache-0.4.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:ab2943be7c652f09638800905ee1bab2c544e537edb57d527997a24c13dc1455", size = 257393, upload-time = "2025-10-08T19:48:31.567Z" }, - { url = "https://files.pythonhosted.org/packages/08/02/87b25304249a35c0915d236575bc3574a323f60b47939a2262b77632a3ee/propcache-0.4.1-cp314-cp314t-win32.whl", hash = "sha256:05674a162469f31358c30bcaa8883cb7829fa3110bf9c0991fe27d7896c42d85", size = 42546, upload-time = "2025-10-08T19:48:32.872Z" }, - { url = "https://files.pythonhosted.org/packages/cb/ef/3c6ecf8b317aa982f309835e8f96987466123c6e596646d4e6a1dfcd080f/propcache-0.4.1-cp314-cp314t-win_amd64.whl", hash = "sha256:990f6b3e2a27d683cb7602ed6c86f15ee6b43b1194736f9baaeb93d0016633b1", size = 46259, upload-time = "2025-10-08T19:48:34.226Z" }, - { url = "https://files.pythonhosted.org/packages/c4/2d/346e946d4951f37eca1e4f55be0f0174c52cd70720f84029b02f296f4a38/propcache-0.4.1-cp314-cp314t-win_arm64.whl", hash = "sha256:ecef2343af4cc68e05131e45024ba34f6095821988a9d0a02aa7c73fcc448aa9", size = 40428, upload-time = "2025-10-08T19:48:35.441Z" }, - { url = "https://files.pythonhosted.org/packages/5b/5a/bc7b4a4ef808fa59a816c17b20c4bef6884daebbdf627ff2a161da67da19/propcache-0.4.1-py3-none-any.whl", hash = "sha256:af2a6052aeb6cf17d3e46ee169099044fd8224cbaf75c76a2ef596e8163e2237", size = 13305, upload-time = "2025-10-08T19:49:00.792Z" }, +sdist = { url = "https://files.pythonhosted.org/packages/ec/44/c87281c333769159c50594f22610f77398a47ccbfbbf23074e744e86f87c/propcache-0.5.2.tar.gz", hash = "sha256:01c4fc7480cd0598bb4b57022df55b9ca296da7fc5a8760bd8451a7e63a7d427", size = 50208, upload-time = "2026-05-08T21:02:12.199Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/5b/56/030b7b4719d53085722893e0009dffb9236aa10bca1b12121bdc5626ef16/propcache-0.5.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:d5a81be28596d6559f6131ef33e10200de6e17643b3c74ce03f9eb103be6ae8b", size = 93417, upload-time = "2026-05-08T20:59:15.597Z" }, + { url = "https://files.pythonhosted.org/packages/1a/55/1140a8e067b8ec093a18a4ae7bb0045d9db65da38a08618ddc5e2f1994aa/propcache-0.5.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:29cbaac5ea0212663e6845e04b5e188d5a6ae6dd919810ac835bf1d3b42c3f4c", size = 53847, upload-time = "2026-05-08T20:59:17.096Z" }, + { url = "https://files.pythonhosted.org/packages/20/42/0e7443c90310498561addf346e7d57fe3c6ba1914e1ba938b5464c7bbfd2/propcache-0.5.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:6bf3be92233808fcd338eba0fb4d0b59ec5772af4f4ecfcec450d1bfc0f8b5eb", size = 53512, upload-time = "2026-05-08T20:59:18.64Z" }, + { url = "https://files.pythonhosted.org/packages/b7/db/cf51a71bab2009517d1a7f0ee07657e3bd446c4d69f67e6966cf17bcf956/propcache-0.5.2-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:2f8ea531c794b9d6274acd4e8d2c2ebcac590a4361d27482edd3010b79f1325e", size = 58068, upload-time = "2026-05-08T20:59:20.683Z" }, + { url = "https://files.pythonhosted.org/packages/b7/43/39b6bdee9699fa1e1641c519feeb64a67e2a9f93bb465c70776b37a7333f/propcache-0.5.2-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:decfca4c79dd53ebab484b00cc4b6717d8c369f86e74aa4ca395a64ac651495e", size = 61020, upload-time = "2026-05-08T20:59:22.112Z" }, + { url = "https://files.pythonhosted.org/packages/26/0b/843726fbb0a29a8c5684fdb25971823638399f31e52e9d1f06a02dc9aa6b/propcache-0.5.2-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:4621064bbf28fa77ff64dd5d94367c04684c67d3a5bf1dff25f0cd0d98a38f3b", size = 62732, upload-time = "2026-05-08T20:59:23.805Z" }, + { url = "https://files.pythonhosted.org/packages/39/6e/899fed76dc1942b8a64193a4f059d7f1a2c7ef65085e8a9366ed8ec0d199/propcache-0.5.2-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b96db7141a592cbc968daf1feea83a118e6ab378af4abbc72b248c895414c22d", size = 60140, upload-time = "2026-05-08T20:59:25.389Z" }, + { url = "https://files.pythonhosted.org/packages/ab/09/3da4be9b5b879219ad234aa535b3dd4a080ed1ad48d3a73ca07a9e798f22/propcache-0.5.2-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:1ca071adabaab6e9219924bbe00af821f1ee7de113a9eca1cdc292de3d120f4d", size = 60400, upload-time = "2026-05-08T20:59:27.238Z" }, + { url = "https://files.pythonhosted.org/packages/60/2f/09b72b874a9aa0044faf52a69807a6ed618e267ceaa9ec4a63195fa5b504/propcache-0.5.2-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:e4294d04a94dcab1b3bccd8b66d962dcad411a1d19414b2a41d1445f1de32ad0", size = 58155, upload-time = "2026-05-08T20:59:28.48Z" }, + { url = "https://files.pythonhosted.org/packages/8a/37/97489848c54c95578045473954f10956d619ce6a09e7ac137b71cdcb698b/propcache-0.5.2-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:a0e399a2eccb91ed18721f86aa85757727400b6865c89e88934781deb9c8498b", size = 57037, upload-time = "2026-05-08T20:59:30.146Z" }, + { url = "https://files.pythonhosted.org/packages/22/db/6c695285ccfc49012743ee9c98212b8c5dd0aed7b63cfd816d4a0f7a1601/propcache-0.5.2-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:823581fd5cb08b12a48bfa11fe962a7916766b6170c17b028fbdf762b85eb9bf", size = 61103, upload-time = "2026-05-08T20:59:31.626Z" }, + { url = "https://files.pythonhosted.org/packages/98/a9/1e500401ca593b0bdb6bf75a70bc2d723835fd53360edff6af70692c7546/propcache-0.5.2-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:949c91d1a990cf3b2e8188dfcfb25005e0b834a06c63fa4ef9f360878ce21ecf", size = 60394, upload-time = "2026-05-08T20:59:32.829Z" }, + { url = "https://files.pythonhosted.org/packages/1f/87/f638b6e375eae0f30a1a2325d8b34fd85fdc785bb9960cf805f3bf1ec69a/propcache-0.5.2-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:cc1177027eda740fdb152706bd215a3f124e3eea15afc39f2cb9fe351b50619e", size = 63084, upload-time = "2026-05-08T20:59:35.964Z" }, + { url = "https://files.pythonhosted.org/packages/f6/18/884573f5d97b6d9eba68de759a82c901b7e39d7904d30f7b8d58d42d2a12/propcache-0.5.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:b05d643f944a8c3c4bd86d65ffd87bf3264b617f87791940302bc474d2ff5274", size = 60999, upload-time = "2026-05-08T20:59:38.481Z" }, + { url = "https://files.pythonhosted.org/packages/8f/1a/c3915eb059ceec9e758a56e4cfd955292bc0f201be2176a46b76d94b303a/propcache-0.5.2-cp310-cp310-win32.whl", hash = "sha256:8114f28879e0904748e831c3a7774261bd9e75f49be089f389a76f959dcd13fe", size = 39036, upload-time = "2026-05-08T20:59:40.323Z" }, + { url = "https://files.pythonhosted.org/packages/5b/02/1dfd5607501a602d19c1c449d2d193b7d1c611f9246b4059026a1189a80e/propcache-0.5.2-cp310-cp310-win_amd64.whl", hash = "sha256:5fcb98e7598b1ee0addab320d90f65b530297a867dbfe9de52ea838077e16e3d", size = 42190, upload-time = "2026-05-08T20:59:42.232Z" }, + { url = "https://files.pythonhosted.org/packages/57/93/f71588ad08b3e6f4b555b5ef215808a3c02b042d0151ad82fa6f15be677a/propcache-0.5.2-cp310-cp310-win_arm64.whl", hash = "sha256:04dc2390d9edbbaef7461f33322555976ffddf0b650a038649d026358714e6c5", size = 38545, upload-time = "2026-05-08T20:59:44.087Z" }, + { url = "https://files.pythonhosted.org/packages/e7/f1/8a8cc1c2c7e7934ab77e0163414f736fadbc0f5e8dd9673b952355ac175b/propcache-0.5.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:74b70780220e2dd89175ca24b81b68b67c83db499ae611e7f2313cb329801c78", size = 90744, upload-time = "2026-05-08T20:59:45.799Z" }, + { url = "https://files.pythonhosted.org/packages/c2/f4/651b1225e976bd1a2ba5cfba0c29d096581c2636b437e3a9a7ab6276270a/propcache-0.5.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:a4840ab0ae0216d952f4b53dc6d0b992bfc2bedbfe360bdd9b548bc184c08959", size = 52033, upload-time = "2026-05-08T20:59:47.408Z" }, + { url = "https://files.pythonhosted.org/packages/15/a8/8ede85d6aa1f79fc7dc2f8fd2c8d65920b8272c3892903c8a1affde48cfb/propcache-0.5.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:c6844ba6364fb12f403928a82cfd295ab103a2b315c77c747b2dbe4a41894ea7", size = 52754, upload-time = "2026-05-08T20:59:49.202Z" }, + { url = "https://files.pythonhosted.org/packages/7d/fe/b3551b41bbc2f5b5bb088fc6920567cd43101253e68fbaa261339eb96fe1/propcache-0.5.2-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:2293949b855ce597f2826452d17c2d545fb5622379c4ea6fdf525e9b8e8a2511", size = 57573, upload-time = "2026-05-08T20:59:50.778Z" }, + { url = "https://files.pythonhosted.org/packages/83/27/ab851ebd1b7172e3e161f5f8d39e315d54a91bea246f01f4d872d3376aef/propcache-0.5.2-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:0fd59b5af35f74da48d905dcbad55449ba13be91823cb05a9bd590bbf5b61660", size = 60645, upload-time = "2026-05-08T20:59:52.227Z" }, + { url = "https://files.pythonhosted.org/packages/95/7d/466b3d18022e9897cbda9c735c493c5bd747d7a4c6f5ea1480b4cec434b6/propcache-0.5.2-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:29f9309a2e42b0d273be006fdb4be2d6c39a47f6f57d8fb1cf9f81481df81b66", size = 61563, upload-time = "2026-05-08T20:59:53.866Z" }, + { url = "https://files.pythonhosted.org/packages/27/1b/16ab7f2cf2041da2f60d156ba64c2484eadf9168075b4ff43c3ef60045af/propcache-0.5.2-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5aaa2b923c1944ac8febd6609cb373540a5563e7cbcb0fd770f75dace2eb817b", size = 58888, upload-time = "2026-05-08T20:59:55.457Z" }, + { url = "https://files.pythonhosted.org/packages/0a/67/bb777ffd907633563bf35fd859c4ce97b0512c32f4633cf5d1eb7c33512b/propcache-0.5.2-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:66ea454f095ddf5b6b14f56c064c0941c4788be11e18d2464cf643bf7203ff67", size = 59253, upload-time = "2026-05-08T20:59:57.075Z" }, + { url = "https://files.pythonhosted.org/packages/b9/42/64f8d90b73fd9cdc1499b48057ff6d9cd2a98a25734c9bb62ecf07e87061/propcache-0.5.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:95f1e3f4760d404b13c9976c0229b2b49a3c8e2c62a9ce92efdd2b11ada75e3f", size = 57558, upload-time = "2026-05-08T20:59:58.602Z" }, + { url = "https://files.pythonhosted.org/packages/eb/02/dba5bc03c9041f2092ea55a449caf5dfe68352c6654511b29ba0654ddb69/propcache-0.5.2-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:85341b12b9d55bad0bded24cac341bb34289469e03a11f3f583ea1cc1db0326c", size = 55007, upload-time = "2026-05-08T20:59:59.837Z" }, + { url = "https://files.pythonhosted.org/packages/14/c0/43f649c7aa2a77a3b100d84e9dea3a483120ecb608bfe36ce49eaff517fe/propcache-0.5.2-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:26a4dca084132874e639895c3135dfad5eb20bae209f62d1aeb31b03e601c3c0", size = 60355, upload-time = "2026-05-08T21:00:01.144Z" }, + { url = "https://files.pythonhosted.org/packages/83/c0/435dafd27f1cb4a495381dae60e25883ccfe4020bb72818e8184c1678092/propcache-0.5.2-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:3b199b9b2b3d6a7edf3183ba8a9a137a22b97f7df525feb5ae1eccf026d2a9c6", size = 59057, upload-time = "2026-05-08T21:00:02.401Z" }, + { url = "https://files.pythonhosted.org/packages/53/ae/6e292df9135d659944e96cb3389258e4a663e5b2b5f6c217ef0ddc8d2f73/propcache-0.5.2-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:e59bc9e66329185b93dab73f210f1a37f81cb40f321501db8017c9aea15dba27", size = 61938, upload-time = "2026-05-08T21:00:03.638Z" }, + { url = "https://files.pythonhosted.org/packages/0b/42/314ebc50d8159055411fd6b0bda322ff510e4b1f7d2e4927940ad0f6af20/propcache-0.5.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:552ffadf6ad409844bc5919c42a0a83d88314cedddaea0e41e80a8b8fffe881f", size = 59731, upload-time = "2026-05-08T21:00:04.881Z" }, + { url = "https://files.pythonhosted.org/packages/b8/9b/2da6dee38871c3c8772fabc2758325a5c9077d6d18c597737dc04dd884cd/propcache-0.5.2-cp311-cp311-win32.whl", hash = "sha256:cd416c1de191973c52ff1a12a57446bfc7642797b282d7caf2162d7d1b8aa9a0", size = 38966, upload-time = "2026-05-08T21:00:06.511Z" }, + { url = "https://files.pythonhosted.org/packages/42/4e/f17363fb58c0afe05b067361cb6d86ed2d29de6506779a27547c4d183075/propcache-0.5.2-cp311-cp311-win_amd64.whl", hash = "sha256:44e488ef40dbb452700b2b1f8188934121f6648f52c295055662d2191959ff82", size = 42135, upload-time = "2026-05-08T21:00:08.088Z" }, + { url = "https://files.pythonhosted.org/packages/c6/eb/6af6685077d22e8b33358d3c548e3282706a0b3cd85044ffba4e5dd08e3b/propcache-0.5.2-cp311-cp311-win_arm64.whl", hash = "sha256:54adaa85a22078d1e306304a40984dc5be99d599bf3dc0a24dc98f7daeab89ab", size = 38381, upload-time = "2026-05-08T21:00:09.692Z" }, + { url = "https://files.pythonhosted.org/packages/4a/cb/e27bc2b2737a0bb49962b275efa051e8f1c35a936df7d5139b6b658b7dc9/propcache-0.5.2-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:806719138ecd720339a12410fb9614ac9b2b2d3a5fdf8235d56981c36f4039ba", size = 95887, upload-time = "2026-05-08T21:00:11.277Z" }, + { url = "https://files.pythonhosted.org/packages/e6/13/b8ae04c59392f8d11c6cd9fb4011d1dc7c86b81225c770280300e259ffe1/propcache-0.5.2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:db2b80ea58eab4f86b2beec3cc8b39e8ff9276ac20e96b7cce43c8ae84cd6b5a", size = 54654, upload-time = "2026-05-08T21:00:12.604Z" }, + { url = "https://files.pythonhosted.org/packages/2c/7d/49777a3e20b55863d4794384a38acd460c04157b0a00f8602b0d508b8431/propcache-0.5.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:e5cbfac9f61484f7e9f3597775500cd3ebe8274e9b050c38f9525c77c97520bf", size = 55190, upload-time = "2026-05-08T21:00:13.935Z" }, + { url = "https://files.pythonhosted.org/packages/44/c7/085d0cd63062e84044e3f05797749c3f8e3938ff3aeb0eb2f69d43fafc91/propcache-0.5.2-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5dbc581d2814337da56222fab8dc5f161cd798a434e49bac27930aaef798e144", size = 59995, upload-time = "2026-05-08T21:00:15.526Z" }, + { url = "https://files.pythonhosted.org/packages/9c/42/32cf8e3009e92b2645cf1e944f701e8ea4e924dffde1ee26db860bcbf7e4/propcache-0.5.2-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:857187f381f88c8e2fa2fe56ab94879d011b883d5a2ee5a1b60a8cd2a06846d9", size = 63422, upload-time = "2026-05-08T21:00:16.824Z" }, + { url = "https://files.pythonhosted.org/packages/9e/1b/f112433f99fc979431b87a39ef169e3f8df070d99a72792c56d6937ac48b/propcache-0.5.2-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:178b4a2cdaac1818e2bf1c5a99b94383fa73ea5382e032a48dec07dc5668dc42", size = 64342, upload-time = "2026-05-08T21:00:18.362Z" }, + { url = "https://files.pythonhosted.org/packages/14/15/5574111ae50dd6e879456888c0eadd4c5a869959775854e18e18a6b345f3/propcache-0.5.2-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6f328175a2cde1f0ff2c4ed8ce968b9dcfb55f3a7153f39e2957ed994da13476", size = 61639, upload-time = "2026-05-08T21:00:19.692Z" }, + { url = "https://files.pythonhosted.org/packages/cc/da/4d775080b1490c0ae604acda868bd71aabe3a89ed16f2aa4339eb8a283e7/propcache-0.5.2-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:5671d09a36b06d0fd4a3da0fccbcae360e9b1570924171a15e9e0997f0249fba", size = 61588, upload-time = "2026-05-08T21:00:21.155Z" }, + { url = "https://files.pythonhosted.org/packages/04/ac/f076982cbe2195ee9cf32de5a1e46951d9fb399fc207f390562dd0fd8fb2/propcache-0.5.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:80168e2ebe4d3ec6599d10ad8f520304ae1cad9b6c5a95372aef1b66b7bfb53a", size = 60029, upload-time = "2026-05-08T21:00:22.713Z" }, + { url = "https://files.pythonhosted.org/packages/70/60/189be62e0dd898dce3b331e1b8c7a543cd3a405ac0c81fe8ee8a9d5d77e1/propcache-0.5.2-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:45f11346f884bc47444f6e6647131055844134c3175b629f84952e2b5cd62b64", size = 56774, upload-time = "2026-05-08T21:00:24.001Z" }, + { url = "https://files.pythonhosted.org/packages/ea/9e/93377b9c7939c1ffae98f878dee955efadfd638078bc86dbc21f9d52f651/propcache-0.5.2-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:8e778ebd44ef4f66ed60a0416b06b489687db264a9c0b3620362f26489492913", size = 63532, upload-time = "2026-05-08T21:00:25.545Z" }, + { url = "https://files.pythonhosted.org/packages/14/f9/590ef6cfb9b8028d516d287812ece32bb0bc5f11fbb9c8bf6b2e6313fec8/propcache-0.5.2-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:c0cb9ed24c8964e172768d455a38254c2dd8a552905729ce006cad3d3dda59b1", size = 61592, upload-time = "2026-05-08T21:00:27.186Z" }, + { url = "https://files.pythonhosted.org/packages/b4/5e/70958b3034c297a630bba2f17ca7abc2d5f39a803ad7e370ab79d1ecd022/propcache-0.5.2-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:1d1ad32d9d4355e2be65574fd0bfd3677e7066b009cd5b9b2dee8aa6a6393b33", size = 64788, upload-time = "2026-05-08T21:00:28.8Z" }, + { url = "https://files.pythonhosted.org/packages/12/fd/77fe5936d8c3086ca9048f7f415f122ed82e53884a9ec193646b42deef06/propcache-0.5.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:c80f4ba3e8f00189165999a742ee526ebeccedf6c3f7beb0c7df821e9772435a", size = 62514, upload-time = "2026-05-08T21:00:30.098Z" }, + { url = "https://files.pythonhosted.org/packages/cf/74/66bd798b5b3be70aa1b391f5cc9d6a0a5532d7fd3b19ec0b213e72e6ad9d/propcache-0.5.2-cp312-cp312-win32.whl", hash = "sha256:8c7972d8f193740d9175f0998ab38717e6cd322d5935c5b0fef8c0d323fd9031", size = 39018, upload-time = "2026-05-08T21:00:31.622Z" }, + { url = "https://files.pythonhosted.org/packages/61/7c/5c0d34aa3024694d6dcb9271cdbdd08c4e47c1c0ad95ec7e7bc74cdea145/propcache-0.5.2-cp312-cp312-win_amd64.whl", hash = "sha256:d9ee8826a7d47863a08ac44e1a5f611a462eefc3a194b492da242128bec75b42", size = 42322, upload-time = "2026-05-08T21:00:32.918Z" }, + { url = "https://files.pythonhosted.org/packages/4d/91/875812f1a3feb20ceba818ef39fbe4d92f1081e04ac815c822496d0d038b/propcache-0.5.2-cp312-cp312-win_arm64.whl", hash = "sha256:2800a4a8ead6b28cccd1ec54b59346f0def7922ee1c7598e8499c733cfbb7c84", size = 38172, upload-time = "2026-05-08T21:00:35.124Z" }, + { url = "https://files.pythonhosted.org/packages/c5/09/f049e45385503fe67db75a6b6186a7b9f0c3930366dc960522c312a825b1/propcache-0.5.2-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:099aaf4b4d1a02265b92a977edf00b5c4f63b3b17ac6de39b0d637c9cac0188a", size = 94457, upload-time = "2026-05-08T21:00:36.355Z" }, + { url = "https://files.pythonhosted.org/packages/6b/65/83d1d05655baf63113731bd5a1008435e14f8d1e5a06cbe4ec5b23ad7a31/propcache-0.5.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:68ce1c44c7a813a7f71ea04315a8c7b330b63db99d059a797a4651bb6f69f117", size = 53835, upload-time = "2026-05-08T21:00:38.072Z" }, + { url = "https://files.pythonhosted.org/packages/a9/12/a6ba6482bb5ea3260c000c9b20881c95fa11c6b30173715668259f844ed7/propcache-0.5.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:fc299c129490f55f254cd90be0deca4764e36e9a7c08b4aa588479a3bbed3098", size = 54545, upload-time = "2026-05-08T21:00:39.319Z" }, + { url = "https://files.pythonhosted.org/packages/a9/19/7fa086f5764c59ec8a8e157cd93aa8497acc00aba9dcdec56bfffb32602d/propcache-0.5.2-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a6ae2198be502c10f09b2516e7b5d019816924bc3183a43ce792a7bd6625e6f4", size = 59886, upload-time = "2026-05-08T21:00:40.621Z" }, + { url = "https://files.pythonhosted.org/packages/a1/e4/5d7663dc8235956c8f5281698a3af1d351d8820341ddd890f59d9a9127f2/propcache-0.5.2-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:6041d31504dc1779d700e1edcfb08eea334b357620b06681a4eabb57a74e574e", size = 63261, upload-time = "2026-05-08T21:00:41.775Z" }, + { url = "https://files.pythonhosted.org/packages/4a/4a/15a03adee24d6350da4292caeac44c34c033d2afe5e87eb370f38854560f/propcache-0.5.2-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:f7eabc04151c78a9f4d5bbb5f1faf571e4defeb4b585e0fe95b60ff2dbe4d3d7", size = 64184, upload-time = "2026-05-08T21:00:43.018Z" }, + { url = "https://files.pythonhosted.org/packages/8b/c6/979176efdaa3d239e36d503d5af63a0a773b36662ed8f52e5b6a6d9fd40e/propcache-0.5.2-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4db0ba63d693afd40d249bd93f842b5f144f8fcbb83de05660373bcf30517b1d", size = 61534, upload-time = "2026-05-08T21:00:44.507Z" }, + { url = "https://files.pythonhosted.org/packages/c8/22/63e8cd1bae4c2d2be6493b6b7d10566ddafad88137cfbc99964a1119853c/propcache-0.5.2-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:1dbcf7675229b35d31abb6547d8ebc8c27a830ac3f9a794edff6254873ec7c0a", size = 61500, upload-time = "2026-05-08T21:00:45.796Z" }, + { url = "https://files.pythonhosted.org/packages/60/5a/28e5d9acbac1cc9ccb67045e8c1b943aa8d79fdf39c93bd73cacd68008ea/propcache-0.5.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:d310c013aad2c72f1c3f2f8dd3279d460a858c551f97aeb8c63e4693cca7b4d2", size = 59994, upload-time = "2026-05-08T21:00:47.093Z" }, + { url = "https://files.pythonhosted.org/packages/f3/40/db650677f554a95b9c01a7c9d93d629e93a15562f5deb4573c9ee136fed2/propcache-0.5.2-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:06187263ddad280d05b4d8a8b3bb7d164cbebd469236544a42e6d9b28ac6a4fa", size = 56884, upload-time = "2026-05-08T21:00:48.376Z" }, + { url = "https://files.pythonhosted.org/packages/80/45/70b39b89516ff8b96bf732fa6fded8cef20f293cb1508690101c3c07ec51/propcache-0.5.2-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:3115559b8effafd63b142ea5ed53d63a16ea6469cbc63dce4ee194b42db5d853", size = 63464, upload-time = "2026-05-08T21:00:49.954Z" }, + { url = "https://files.pythonhosted.org/packages/f9/e2/fa59d3a89eac5534293124af4f1d0d0ada091ce4a0ab4610ce03fd2bdd8d/propcache-0.5.2-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:c60462af8e6dc30c35407c7237ea908d777b22862bbee27bc4699c0d8bcdc45a", size = 61588, upload-time = "2026-05-08T21:00:51.281Z" }, + { url = "https://files.pythonhosted.org/packages/0b/97/efb547a55c4bc7381cfb202d6a2239ac621045277bc1ea5dfd3a7f0516c0/propcache-0.5.2-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:40314bca9ac559716fe374094fc81c11dcc34b64fd6c585360f5775690505704", size = 64667, upload-time = "2026-05-08T21:00:52.602Z" }, + { url = "https://files.pythonhosted.org/packages/92/56/f5c7d9b4b7595d5127da38974d791b2153f3d1eae6c674af3583ace92ad3/propcache-0.5.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:cfa21e036ce1e1db2be04ba3b85d2df1bb1702fa01932d984c5464c665228ff4", size = 62463, upload-time = "2026-05-08T21:00:54.303Z" }, + { url = "https://files.pythonhosted.org/packages/bd/3b/484a3a65fc9f9f60c41dcd17b428bace5389544e2c680994534a20755066/propcache-0.5.2-cp313-cp313-win32.whl", hash = "sha256:f156a3529f38063b6dbaf356e15602a7f95f8055b1295a438433a6386f10463d", size = 38621, upload-time = "2026-05-08T21:00:55.808Z" }, + { url = "https://files.pythonhosted.org/packages/1c/fd/3f0f10dba4dabad3bf53102be007abf55481067952bde0fdddff439e7c61/propcache-0.5.2-cp313-cp313-win_amd64.whl", hash = "sha256:dfed59d0a5aeb01e242e66ff0300bc4a265a7c05f612d30016f0b60b1017d757", size = 41649, upload-time = "2026-05-08T21:00:57.061Z" }, + { url = "https://files.pythonhosted.org/packages/90/ec/6ce619cc32bb500a482f811f9cd509368b4e58e638d13f2c68f370d6b475/propcache-0.5.2-cp313-cp313-win_arm64.whl", hash = "sha256:ba338430e87ceb9c8f0cf754de38a9860560261e56c00376debd628698a7364f", size = 37636, upload-time = "2026-05-08T21:00:58.646Z" }, + { url = "https://files.pythonhosted.org/packages/1b/82/c1d268bbbf2ef981c5bf0fbbe746db617c66e3bcefe431a1aa8943fbe23a/propcache-0.5.2-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:a592f5f3da71c8691c788c13cb6734b6d17663d2e1cb8caddf0673d01ef8847d", size = 98872, upload-time = "2026-05-08T21:00:59.889Z" }, + { url = "https://files.pythonhosted.org/packages/f4/d4/52c871e73e864e6b34c0e2d58ac1ec5ccd149497ddc7ad2137ae98323a35/propcache-0.5.2-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:6a997d0489e9668a384fcfd5061b857aa5361de73191cac204d04b889cfbbafa", size = 56257, upload-time = "2026-05-08T21:01:01.195Z" }, + { url = "https://files.pythonhosted.org/packages/67/f0/9b90ca2a210b3d09bcfcd96ecd0f55545c091535abce2a45de2775cfd357/propcache-0.5.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:10734b5484ea113152ee25a91dccedf81631791805d2c9ccb054958e51842c94", size = 56696, upload-time = "2026-05-08T21:01:02.941Z" }, + { url = "https://files.pythonhosted.org/packages/9d/0e/6e9d4ba07c8e56e21ddec1e75f12148142b21ca83a51871babce095334f4/propcache-0.5.2-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:cafca7e56c12bb02ae16d283742bef25a61122e9dab2b5b3f2ccbe589ce32164", size = 62378, upload-time = "2026-05-08T21:01:04.475Z" }, + { url = "https://files.pythonhosted.org/packages/65/19/c10badaa463dde8a27ce884f8ee2ec37e6035b7c9f5ff0c8f74f06f08dac/propcache-0.5.2-cp313-cp313t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:f064f8d2b59177878b7615df1735cd8fe3462ed6be8c7b217d17a276489c2b7f", size = 65283, upload-time = "2026-05-08T21:01:05.959Z" }, + { url = "https://files.pythonhosted.org/packages/b0/b6/93bea99ca80e19cef6512a8580e5b7857bbe09422d9daa7fd4ef5723306c/propcache-0.5.2-cp313-cp313t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:f78abfa8dfc32376fd1aacf597b2f2fbbe0ea751419aee718af5d4f82537ef8c", size = 66616, upload-time = "2026-05-08T21:01:07.228Z" }, + { url = "https://files.pythonhosted.org/packages/83/e4/5c7462e50625f051f37fb38b8224f7639f667184bbd34424ec83819bb1b7/propcache-0.5.2-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f7467da8a9822bf1a55336f877340c5bcbd3c482afc43a99771169f74a26dedc", size = 63773, upload-time = "2026-05-08T21:01:08.514Z" }, + { url = "https://files.pythonhosted.org/packages/ca/b6/99238894047b13c823be25027e736626cd414a52a5e30d2c3347c2733529/propcache-0.5.2-cp313-cp313t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:a6ddc6ac9e25de626c1f129c1b467d7ecd33ce2237d3fd0c4e429feef0a7ee1f", size = 63664, upload-time = "2026-05-08T21:01:09.874Z" }, + { url = "https://files.pythonhosted.org/packages/85/1e/a3a1a63116a2b8edb415a8bb9a6f0c34bd03830b1e18e8ce2904e1dc1cf4/propcache-0.5.2-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:2f22cbbac9e26a8e864c0985ff1268d5d939d53d9d9411a9824279097e03a2cb", size = 62643, upload-time = "2026-05-08T21:01:11.132Z" }, + { url = "https://files.pythonhosted.org/packages/e4/03/893cf147de2fc6543c5eaa07ad833170e7e2a2385725bbebe8c0503723bb/propcache-0.5.2-cp313-cp313t-musllinux_1_2_armv7l.whl", hash = "sha256:fc76378c62a0f04d0cd82fbb1a2cd2d7e28fcb40d5873f28a6c44e388aaa2751", size = 59595, upload-time = "2026-05-08T21:01:12.387Z" }, + { url = "https://files.pythonhosted.org/packages/86/3b/04c1a2e12c57766568ba75ba72b3bf2042818d4c1425fab6fc07155c7cff/propcache-0.5.2-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:acd2c8edba48e31e58a363b8cf4e5c7db3b04b3f9e371f601df30d9b0d244836", size = 65711, upload-time = "2026-05-08T21:01:13.676Z" }, + { url = "https://files.pythonhosted.org/packages/1c/34/80f8d0099f8d6bacc4de1624c85672681c8cd1149ca2da0e38fd120b817f/propcache-0.5.2-cp313-cp313t-musllinux_1_2_riscv64.whl", hash = "sha256:452b5065457eb9991ec5eb38ff41d6cd4c991c9ac7c531c4d5849ae473a9a13f", size = 64247, upload-time = "2026-05-08T21:01:14.936Z" }, + { url = "https://files.pythonhosted.org/packages/f3/1a/8b08f3a5f1037e9e370c55883ceeeee0f6dd0416fb2d2d67b8bfc91f2a79/propcache-0.5.2-cp313-cp313t-musllinux_1_2_s390x.whl", hash = "sha256:3430bb2bfe1331885c427745a751e774ee679fd4344f80b97bf879815fe8fa55", size = 67102, upload-time = "2026-05-08T21:01:16.281Z" }, + { url = "https://files.pythonhosted.org/packages/34/68/8bdb7bb7756d76e005490649d10e4a8369e610c74d619f71e1aedf889e9c/propcache-0.5.2-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:cef6cea3922890dd6c9654971001fa797b526c16ab5e1e46c05fd6f877be7568", size = 64964, upload-time = "2026-05-08T21:01:17.57Z" }, + { url = "https://files.pythonhosted.org/packages/0a/aa/50fb0b5d3968b61a510926ff8b8465f1d6e976b3ab74496d7a4b9fc42515/propcache-0.5.2-cp313-cp313t-win32.whl", hash = "sha256:72d61e16dd78228b58c5d47be830ff3da7e5f139abdf0aef9d86cde1c5cf2191", size = 42546, upload-time = "2026-05-08T21:01:18.946Z" }, + { url = "https://files.pythonhosted.org/packages/ae/4c/0ddbae64321bd4a95bcbfc19307238016b5b1fee645c84626c8d539e5b74/propcache-0.5.2-cp313-cp313t-win_amd64.whl", hash = "sha256:0958834041a0166d343b8d2cedcd8bcbaeb4fdbe0cf08320c5379f143c3be6e7", size = 46330, upload-time = "2026-05-08T21:01:20.162Z" }, + { url = "https://files.pythonhosted.org/packages/00/d9/9cddc8efb78d8af264c5ec9f6d10b62f57c515feda8d321595f56010fb23/propcache-0.5.2-cp313-cp313t-win_arm64.whl", hash = "sha256:6de8bd93ddde9b992cf2b2e0d796d501a19026b5b9fd87356d7d0779531a8d96", size = 40521, upload-time = "2026-05-08T21:01:21.399Z" }, + { url = "https://files.pythonhosted.org/packages/e2/ea/23ee535d90ce8bcc465a3028eb3cc0ce3bd1005f4bb27710b30587de798d/propcache-0.5.2-cp314-cp314-macosx_10_15_universal2.whl", hash = "sha256:46088abff4cba581dea21ae0467a480526cb25aa5f3c269e909f800328bc3999", size = 94662, upload-time = "2026-05-08T21:01:22.683Z" }, + { url = "https://files.pythonhosted.org/packages/b5/06/c5a52f419b5d8972f8d46a7577476090d8e3263ff589ce40b5ca4968d5be/propcache-0.5.2-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:fc88b26f08d634f7bc819a7852e5214f5802641ab8d9fd5326892292eee1993e", size = 53928, upload-time = "2026-05-08T21:01:23.986Z" }, + { url = "https://files.pythonhosted.org/packages/63/b1/4260d67d6bd85e58a66b72d54ce15d5de789b6f3870cc6bedf8ff9667401/propcache-0.5.2-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:97797ebb098e670a2f92dd66f32897e30d7615b14e7f59711de23e30a9072539", size = 54650, upload-time = "2026-05-08T21:01:25.305Z" }, + { url = "https://files.pythonhosted.org/packages/70/06/2f46c318e3307cd7a6a7481def374ce838c0fe20084b39dd54b0879d0e99/propcache-0.5.2-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ba57fffe4ac99c5d30076161b5866336d97600769bad35cc68f7774b15298a4e", size = 59912, upload-time = "2026-05-08T21:01:26.545Z" }, + { url = "https://files.pythonhosted.org/packages/4c/29/fe1aebec2ce57ab985a9c382bded1124431f85078113aa222c5d278430d4/propcache-0.5.2-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:583c19759d9eec1e5b69e2fbef36a7d9c326041be9746cb822d335c8cedc2979", size = 63300, upload-time = "2026-05-08T21:01:27.937Z" }, + { url = "https://files.pythonhosted.org/packages/b4/18/2334b26768b6c82be8c69e83671b767d5ef426aa09b0cba6c2ea47816774/propcache-0.5.2-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:d0326e2e5e1f3163fa306c834e48e8d490e5fae607a097a40c0648109b47ba80", size = 64208, upload-time = "2026-05-08T21:01:29.484Z" }, + { url = "https://files.pythonhosted.org/packages/2b/76/7f1bfd6afff4c5e38e36a3c6d68eb5f4b7311ea80baf693db78d95b603c4/propcache-0.5.2-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e00820e192c8dbebcafb383ebbf99030895f09905e7a0eb2e0340a0bcc2bc825", size = 61633, upload-time = "2026-05-08T21:01:31.068Z" }, + { url = "https://files.pythonhosted.org/packages/c4/46/b3ff8aba2b4953a3e50de2cf72f1b5748b8eca93b15f3dc2c84339084c09/propcache-0.5.2-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:c66afea89b1e43725731d2004732a046fe6fe955d51f952c3e95a7314a284a39", size = 61724, upload-time = "2026-05-08T21:01:32.374Z" }, + { url = "https://files.pythonhosted.org/packages/c5/01/814cfcafbcff954f94c01cf30e097ddc88a076b5440fbcf4570753437d40/propcache-0.5.2-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:d4dc37dec6c6cdad0b57881a5658fd14fbf53e333b1a86cf86559f190e1d9ec4", size = 60069, upload-time = "2026-05-08T21:01:33.67Z" }, + { url = "https://files.pythonhosted.org/packages/da/68/5c6f7622d510cc666a300687e06fd060c1a43361c0c9b20d284f06d8096a/propcache-0.5.2-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:5570dbcc97571c15f68068e529c92715a12f8d54030e272d264b377e22bd17a5", size = 57099, upload-time = "2026-05-08T21:01:34.915Z" }, + { url = "https://files.pythonhosted.org/packages/55/27/9cb0b4c679124085327957d42521c99dba04c88c90c3e55a6f0b633ebccc/propcache-0.5.2-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:f814362777a9f841adddb200ecdf8f5cb1e5a3c4b7a86378edbd6ccb26edd702", size = 63391, upload-time = "2026-05-08T21:01:36.231Z" }, + { url = "https://files.pythonhosted.org/packages/f0/9d/7258aaa5bdf60fc6f27591eef6fe52768cb0beda7140be477c8b12c9794a/propcache-0.5.2-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:196913dea116aeb5a2ba95af4ddcb7ea85559ae07d8eee8751688310d09168c3", size = 61626, upload-time = "2026-05-08T21:01:37.545Z" }, + { url = "https://files.pythonhosted.org/packages/8e/0d/41c602003e8a9b16fe1e7eadf62c7bfba9d5474370b24200bf48b315f45f/propcache-0.5.2-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:6e7b8719005dd1175be4ab1cd25e9b98659a5e0347331506ec6760d2773a7fb5", size = 64781, upload-time = "2026-05-08T21:01:38.83Z" }, + { url = "https://files.pythonhosted.org/packages/8b/f3/38e66b1856e9bd079deea015bc4a55f7767c0e4db2f7dcf69e7e680ba4ce/propcache-0.5.2-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:51f96d685ab16e88cab128cd37a52c5da540809c8b879fa047731bfcb4ad35a4", size = 62570, upload-time = "2026-05-08T21:01:40.415Z" }, + { url = "https://files.pythonhosted.org/packages/95/ca/bbfe9b910ce57dde8bb4876b4520fc02a4e89497c10de26be936758a3aaa/propcache-0.5.2-cp314-cp314-win32.whl", hash = "sha256:cc6fc3cc62e8501d3ed62894425040d2728ecddb1ed072737a5c70bd537aa9f0", size = 39436, upload-time = "2026-05-08T21:01:41.654Z" }, + { url = "https://files.pythonhosted.org/packages/61/d2/45c9defbaa1ea297035d9d4cce9e8f80daafbf19319c6007f157c6256ea9/propcache-0.5.2-cp314-cp314-win_amd64.whl", hash = "sha256:81e3a30b0bb60caa22033dd0f8a3618d1d67356212514f62c57db75cb0ef410c", size = 42373, upload-time = "2026-05-08T21:01:43.041Z" }, + { url = "https://files.pythonhosted.org/packages/44/68/9ea5103f41d5217d7d6ec24db90018e23aebec070c3f9a6e54d12b841fd8/propcache-0.5.2-cp314-cp314-win_arm64.whl", hash = "sha256:0d2c9bf8528f135dbb805ce027567e09164f7efa51a2be07458a2c0420f292d0", size = 38554, upload-time = "2026-05-08T21:01:44.336Z" }, + { url = "https://files.pythonhosted.org/packages/8a/81/fadf555f42d3b762eea8a53950b0489fdc0aa9da5f8ed9e10ce0a4e01b48/propcache-0.5.2-cp314-cp314t-macosx_10_15_universal2.whl", hash = "sha256:4bc8ff1feffc6a61c7002ffe84634c41b822e104990ae009f44a0834430070bb", size = 99395, upload-time = "2026-05-08T21:01:45.883Z" }, + { url = "https://files.pythonhosted.org/packages/f5/c9/c61e134a686949cf7971af3a390148b1156f7be81c73bc0cd12c873e2d48/propcache-0.5.2-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:79aa3ff0a9b566633b642fa9caf7e21ed1c13d6feca718187873f199e1514078", size = 56653, upload-time = "2026-05-08T21:01:47.307Z" }, + { url = "https://files.pythonhosted.org/packages/cb/73/daf935ea7048ddd7ec8eec5345b4a40b619d2d178b3c0a0900796bc3c794/propcache-0.5.2-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:1b31822f4474c4036bae62de9402710051d431a606d6a0f907fec79935a071aa", size = 56914, upload-time = "2026-05-08T21:01:48.573Z" }, + { url = "https://files.pythonhosted.org/packages/79/9f/aba959b435ea18617edd7cf0a7ad0b9c574b8fc7e3d2cd55fb59cb255d33/propcache-0.5.2-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:13fef48778b5a2a756523fdb781326b028ca75e32858b04f2cdd19f394564917", size = 62567, upload-time = "2026-05-08T21:01:49.903Z" }, + { url = "https://files.pythonhosted.org/packages/6c/a1/859942de9a791ff42f6141736f5b37749b8f53e65edfa49638c67dd67e6a/propcache-0.5.2-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:8b73ab70f1a3351fbc71f663b3e645af6dd0329100c353081cf69c37433fc6fe", size = 65542, upload-time = "2026-05-08T21:01:51.204Z" }, + { url = "https://files.pythonhosted.org/packages/b5/61/315bc0fd6c0fc7f80a528b8afd209e5fc4a875ea79571b91b8f50f442907/propcache-0.5.2-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:5538d2c13d93e4698af7e092b57bc7298fd35d1d58e656ae18f23ee0d0378e03", size = 66845, upload-time = "2026-05-08T21:01:52.539Z" }, + { url = "https://files.pythonhosted.org/packages/47/f7/9f8122e3132e8e354ac41975ef8f1099be7d5a16bc7ae562734e993665c0/propcache-0.5.2-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:cd645f03898405cabe694fb8bc35241e3a9c332ec85627584fe3de201452b335", size = 63985, upload-time = "2026-05-08T21:01:53.847Z" }, + { url = "https://files.pythonhosted.org/packages/c8/54/c317819ec157cbf6f35df9df9657a6f82daf34d5faf15948b2f639c2192e/propcache-0.5.2-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:a473b3440261e0c60706e732b2ed2f517857344fc21bf48fdfe211e2d98eb285", size = 63999, upload-time = "2026-05-08T21:01:55.179Z" }, + { url = "https://files.pythonhosted.org/packages/5a/56/387e3f7dfce0a9233df41fb888aa1c30222cb4bbbf09537c02dd9bd85fe2/propcache-0.5.2-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:7afa37062e6650640e932e4cc9297d81f9f42d9944029cc386b8247dea4da837", size = 62779, upload-time = "2026-05-08T21:01:57.489Z" }, + { url = "https://files.pythonhosted.org/packages/a1/9c/596784cb5824ed61ee960d3f8655a3f0993e107c6e98ab6c818b7fb92ccb/propcache-0.5.2-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:8a90efd5777e996e42d568db9ac740b944d691e565cbfd31b2f7832f9184b2b8", size = 59796, upload-time = "2026-05-08T21:01:58.736Z" }, + { url = "https://files.pythonhosted.org/packages/c2/3d/1a6cfa1726a48542c1e8784a0761421476a5b68e09b7f36bf95eb954aaba/propcache-0.5.2-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:f19bb891234d72535764d703bfed1153cc34f4214d5bd7150aee1eec9e8f4366", size = 66023, upload-time = "2026-05-08T21:02:00.228Z" }, + { url = "https://files.pythonhosted.org/packages/e4/0e/05fd6990369477076e4e280bcb970de760fddf0161a46e988bc95f7940ec/propcache-0.5.2-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:32775082acd2d807ee3db715c7770d38767b817870acfa08c29e057f3c4d5b56", size = 64448, upload-time = "2026-05-08T21:02:01.888Z" }, + { url = "https://files.pythonhosted.org/packages/cd/86/5f8da315a4309c62c10c0b2516b17492d5d3bbe1bb862b96604db67e2a37/propcache-0.5.2-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:9282fb1a3bccd038da9f768b927b24a0c753e466c086b7c4f3c6982851eefb2d", size = 67329, upload-time = "2026-05-08T21:02:03.484Z" }, + { url = "https://files.pythonhosted.org/packages/da/d3/3368efe79ab21f0cdf86ef49895811c9cc933131d4cde1f28a624e22e712/propcache-0.5.2-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:cc49723e2f60d6b32a0f0b08a3fd6d13203c07f1cd9566cfce0f12a917c967a2", size = 65172, upload-time = "2026-05-08T21:02:04.745Z" }, + { url = "https://files.pythonhosted.org/packages/d5/07/127e8b0bacfb325396196f9d976a22453049b89b9b2b08477cc3145faa44/propcache-0.5.2-cp314-cp314t-win32.whl", hash = "sha256:2d7aa89ebca5acc98cba9d1472d976e394782f587bad6661003602a619fd1821", size = 43813, upload-time = "2026-05-08T21:02:06.025Z" }, + { url = "https://files.pythonhosted.org/packages/88/fb/46dad6c0ae49ed230ab1b16c890c2b6314e2403e6c412976f4a72d64a527/propcache-0.5.2-cp314-cp314t-win_amd64.whl", hash = "sha256:d447bb0b3054be5818458fbb171208b1d9ff11eba14e18ca18b90cbb45767370", size = 47764, upload-time = "2026-05-08T21:02:07.353Z" }, + { url = "https://files.pythonhosted.org/packages/e7/c4/a47d0a63aa309d10d59ede6e9d4cff03a344a79d1f0f4cd0cd74997b53e0/propcache-0.5.2-cp314-cp314t-win_arm64.whl", hash = "sha256:fe67a3d11cd9b4efabfa45c3d00ffba2b26811442a73a581a94b67c2b5faccf6", size = 41140, upload-time = "2026-05-08T21:02:09.065Z" }, + { 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.27.2" +version = "1.28.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "protobuf" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/81/0d/94dfe80193e79d55258345901acd2917523d56e8381bc4dee7fd38e3868a/proto_plus-1.27.2.tar.gz", hash = "sha256:b2adde53adadf75737c44d3dcb0104fde65250dfc83ad59168b4aa3e574b6a24", size = 57204, upload-time = "2026-03-26T22:18:57.174Z" } +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/84/f3/1fba73eeffafc998a25d59703b63f8be4fe8a5cb12eaff7386a0ba0f7125/proto_plus-1.27.2-py3-none-any.whl", hash = "sha256:6432f75893d3b9e70b9c412f1d2f03f65b11fb164b793d14ae2ca01821d22718", size = 50450, upload-time = "2026-03-26T22:13:42.927Z" }, + { 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]] @@ -4429,16 +4506,16 @@ wheels = [ [[package]] name = "pydantic-settings" -version = "2.14.0" +version = "2.14.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "pydantic" }, { name = "python-dotenv" }, { name = "typing-inspection" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/42/98/c8345dccdc31de4228c039a98f6467a941e39558da41c1744fbe29fa5666/pydantic_settings-2.14.0.tar.gz", hash = "sha256:24285fd4b0e0c06507dd9fdfd331ee23794305352aaec8fc4eb92d4047aeb67d", size = 235709, upload-time = "2026-04-20T13:37:40.293Z" } +sdist = { url = "https://files.pythonhosted.org/packages/07/60/1d1e59c9c90d54591469ada7d268251f71c24bdb765f1a8a832cee8c6653/pydantic_settings-2.14.1.tar.gz", hash = "sha256:e874d3bec7e787b0c9958277956ed9b4dd5de6a80e162188fdaff7c5e26fd5fa", size = 235551, upload-time = "2026-05-08T13:40:06.542Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/01/dd/bebff3040138f00ae8a102d426b27349b9a49acc310fcae7f92112d867e3/pydantic_settings-2.14.0-py3-none-any.whl", hash = "sha256:fc8d5d692eb7092e43c8647c1c35a3ecd00e040fcf02ed86f4cb5458ca62182e", size = 60940, upload-time = "2026-04-20T13:37:38.586Z" }, + { url = "https://files.pythonhosted.org/packages/ae/8d/f1af3832f5e6eb13ba94ee809e72b8ecb5eef226d27ee0bef7d963d943c7/pydantic_settings-2.14.1-py3-none-any.whl", hash = "sha256:6e3c7edfd8277687cdc598f56e5cff0e9bfff0910a3749deaa8d4401c3a2b9de", size = 60964, upload-time = "2026-05-08T13:40:04.958Z" }, ] [[package]] @@ -4485,14 +4562,14 @@ wheels = [ [[package]] name = "pyjwt" -version = "2.12.1" +version = "2.13.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "typing-extensions", marker = "python_full_version < '3.11'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/c2/27/a3b6e5bf6ff856d2509292e95c8f57f0df7017cf5394921fc4e4ef40308a/pyjwt-2.12.1.tar.gz", hash = "sha256:c74a7a2adf861c04d002db713dd85f84beb242228e671280bf709d765b03672b", size = 102564, upload-time = "2026-03-13T19:27:37.25Z" } +sdist = { url = "https://files.pythonhosted.org/packages/3b/81/58d0ac84e1ef3a3843791d6954d94c0b33d526c75eeb1efbce9d0a4c4077/pyjwt-2.13.0.tar.gz", hash = "sha256:41571c89ca91598c79e8ef18a2d07367d4810fbbd6f637794879baf1b7703423", size = 107515, upload-time = "2026-05-21T19:54:36.618Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/e5/7a/8dd906bd22e79e47397a61742927f6747fe93242ef86645ee9092e610244/pyjwt-2.12.1-py3-none-any.whl", hash = "sha256:28ca37c070cad8ba8cd9790cd940535d40274d22f80ab87f3ac6a713e6e8454c", size = 29726, upload-time = "2026-03-13T19:27:35.677Z" }, + { url = "https://files.pythonhosted.org/packages/a3/5e/ecf12fdb62546d64385c158514e9b2b671f7832108ef2ecd2020ce0af2d1/pyjwt-2.13.0-py3-none-any.whl", hash = "sha256:66adcc2aff09b3f1bbd95fc1e1577df8ac8723c978552fd43304c8a290ac5728", size = 31274, upload-time = "2026-05-21T19:54:35.362Z" }, ] [package.optional-dependencies] @@ -4502,15 +4579,15 @@ crypto = [ [[package]] name = "pyopenssl" -version = "26.0.0" +version = "26.3.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "cryptography" }, { name = "typing-extensions", marker = "python_full_version < '3.13'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/8e/11/a62e1d33b373da2b2c2cd9eb508147871c80f12b1cacde3c5d314922afdd/pyopenssl-26.0.0.tar.gz", hash = "sha256:f293934e52936f2e3413b89c6ce36df66a0b34ae1ea3a053b8c5020ff2f513fc", size = 185534, upload-time = "2026-03-15T14:28:26.353Z" } +sdist = { url = "https://files.pythonhosted.org/packages/74/b7/da07bae88f5a9506b4def6f2f4903cf4c3b8831e560dba8fa18ca08f758f/pyopenssl-26.3.0.tar.gz", hash = "sha256:589de7fae1c9ea670d18422ed00fc04da787bbde8e1454aea872aa57b49ad341", size = 182024, upload-time = "2026-06-12T20:28:07.458Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/fb/7d/d4f7d908fa8415571771b30669251d57c3cf313b36a856e6d7548ae01619/pyopenssl-26.0.0-py3-none-any.whl", hash = "sha256:df94d28498848b98cc1c0ffb8ef1e71e40210d3b0a8064c9d29571ed2904bf81", size = 57969, upload-time = "2026-03-15T14:28:24.864Z" }, + { url = "https://files.pythonhosted.org/packages/54/18/1dd71c9b43192ab83f1d531ad6002dc81108ac36c475f79fb7a295abe2f4/pyopenssl-26.3.0-py3-none-any.whl", hash = "sha256:46367f8f66b92271e6d218da9c87607e1ef5a0bc5c8dea5bb3db82f395c385a3", size = 56008, upload-time = "2026-06-12T20:28:05.999Z" }, ] [[package]] @@ -4606,15 +4683,15 @@ wheels = [ [[package]] name = "pytest-rerunfailures" -version = "16.1" +version = "16.3" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "packaging" }, { name = "pytest" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/de/04/71e9520551fc8fe2cf5c1a1842e4e600265b0815f2016b7c27ec85688682/pytest_rerunfailures-16.1.tar.gz", hash = "sha256:c38b266db8a808953ebd71ac25c381cb1981a78ff9340a14bcb9f1b9bff1899e", size = 30889, upload-time = "2025-10-10T07:06:01.238Z" } +sdist = { url = "https://files.pythonhosted.org/packages/4d/f0/74f8e685be7ecd1572c1256132f18fce3a665d7e07649a3f23b7eb2d3bec/pytest_rerunfailures-16.3.tar.gz", hash = "sha256:37c9b1231c8083e9f4e724f50f7a21241822f9516c15c700ebbf218d6452355c", size = 34148, upload-time = "2026-05-22T06:51:22.292Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/77/54/60eabb34445e3db3d3d874dc1dfa72751bfec3265bd611cb13c8b290adea/pytest_rerunfailures-16.1-py3-none-any.whl", hash = "sha256:5d11b12c0ca9a1665b5054052fcc1084f8deadd9328962745ef6b04e26382e86", size = 14093, upload-time = "2025-10-10T07:06:00.019Z" }, + { url = "https://files.pythonhosted.org/packages/f8/98/58a71d68d3126d7f6a6ed1944c37ec207a4ff3dc66cad3bed7b59d38df61/pytest_rerunfailures-16.3-py3-none-any.whl", hash = "sha256:6bdfb8ffb46c46072e6c16bdedee38b6c13eac620d9415ed5b63152cbf283170", size = 15396, upload-time = "2026-05-22T06:51:20.547Z" }, ] [[package]] @@ -4665,33 +4742,36 @@ wheels = [ [[package]] name = "python-multipart" -version = "0.0.26" +version = "0.0.32" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/88/71/b145a380824a960ebd60e1014256dbb7d2253f2316ff2d73dfd8928ec2c3/python_multipart-0.0.26.tar.gz", hash = "sha256:08fadc45918cd615e26846437f50c5d6d23304da32c341f289a617127b081f17", size = 43501, upload-time = "2026-04-10T14:09:59.473Z" } +sdist = { url = "https://files.pythonhosted.org/packages/5b/42/55c32bb9b12693c092ad250a0e82edb5b31ddeda6eb772de5f308b3804ad/python_multipart-0.0.32.tar.gz", hash = "sha256:be54b7f3fa167bb83e4fcd936b887b708f4e57fe75911c02aebf53efaf8d938e", size = 46881, upload-time = "2026-06-04T16:18:58.647Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/9a/22/f1925cdda983ab66fc8ec6ec8014b959262747e58bdca26a4e3d1da29d56/python_multipart-0.0.26-py3-none-any.whl", hash = "sha256:c0b169f8c4484c13b0dcf2ef0ec3a4adb255c4b7d18d8e420477d2b1dd03f185", size = 28847, upload-time = "2026-04-10T14:09:58.131Z" }, + { url = "https://files.pythonhosted.org/packages/e1/04/e8135ebd1ad02c56ec633277529b2602ff99ff634be76cdba5744cf554fd/python_multipart-0.0.32-py3-none-any.whl", hash = "sha256:ff6d3f776f16878c894e52e107296ffc890e913c611b1a4ec6c44e2821fe2e23", size = 30042, upload-time = "2026-06-04T16:18:57.319Z" }, ] [[package]] name = "pywin32" -version = "311" -source = { registry = "https://pypi.org/simple" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/7b/40/44efbb0dfbd33aca6a6483191dae0716070ed99e2ecb0c53683f400a0b4f/pywin32-311-cp310-cp310-win32.whl", hash = "sha256:d03ff496d2a0cd4a5893504789d4a15399133fe82517455e78bad62efbb7f0a3", size = 8760432, upload-time = "2025-07-14T20:13:05.9Z" }, - { url = "https://files.pythonhosted.org/packages/5e/bf/360243b1e953bd254a82f12653974be395ba880e7ec23e3731d9f73921cc/pywin32-311-cp310-cp310-win_amd64.whl", hash = "sha256:797c2772017851984b97180b0bebe4b620bb86328e8a884bb626156295a63b3b", size = 9590103, upload-time = "2025-07-14T20:13:07.698Z" }, - { url = "https://files.pythonhosted.org/packages/57/38/d290720e6f138086fb3d5ffe0b6caa019a791dd57866940c82e4eeaf2012/pywin32-311-cp310-cp310-win_arm64.whl", hash = "sha256:0502d1facf1fed4839a9a51ccbcc63d952cf318f78ffc00a7e78528ac27d7a2b", size = 8778557, upload-time = "2025-07-14T20:13:11.11Z" }, - { url = "https://files.pythonhosted.org/packages/7c/af/449a6a91e5d6db51420875c54f6aff7c97a86a3b13a0b4f1a5c13b988de3/pywin32-311-cp311-cp311-win32.whl", hash = "sha256:184eb5e436dea364dcd3d2316d577d625c0351bf237c4e9a5fabbcfa5a58b151", size = 8697031, upload-time = "2025-07-14T20:13:13.266Z" }, - { url = "https://files.pythonhosted.org/packages/51/8f/9bb81dd5bb77d22243d33c8397f09377056d5c687aa6d4042bea7fbf8364/pywin32-311-cp311-cp311-win_amd64.whl", hash = "sha256:3ce80b34b22b17ccbd937a6e78e7225d80c52f5ab9940fe0506a1a16f3dab503", size = 9508308, upload-time = "2025-07-14T20:13:15.147Z" }, - { url = "https://files.pythonhosted.org/packages/44/7b/9c2ab54f74a138c491aba1b1cd0795ba61f144c711daea84a88b63dc0f6c/pywin32-311-cp311-cp311-win_arm64.whl", hash = "sha256:a733f1388e1a842abb67ffa8e7aad0e70ac519e09b0f6a784e65a136ec7cefd2", size = 8703930, upload-time = "2025-07-14T20:13:16.945Z" }, - { url = "https://files.pythonhosted.org/packages/e7/ab/01ea1943d4eba0f850c3c61e78e8dd59757ff815ff3ccd0a84de5f541f42/pywin32-311-cp312-cp312-win32.whl", hash = "sha256:750ec6e621af2b948540032557b10a2d43b0cee2ae9758c54154d711cc852d31", size = 8706543, upload-time = "2025-07-14T20:13:20.765Z" }, - { url = "https://files.pythonhosted.org/packages/d1/a8/a0e8d07d4d051ec7502cd58b291ec98dcc0c3fff027caad0470b72cfcc2f/pywin32-311-cp312-cp312-win_amd64.whl", hash = "sha256:b8c095edad5c211ff31c05223658e71bf7116daa0ecf3ad85f3201ea3190d067", size = 9495040, upload-time = "2025-07-14T20:13:22.543Z" }, - { url = "https://files.pythonhosted.org/packages/ba/3a/2ae996277b4b50f17d61f0603efd8253cb2d79cc7ae159468007b586396d/pywin32-311-cp312-cp312-win_arm64.whl", hash = "sha256:e286f46a9a39c4a18b319c28f59b61de793654af2f395c102b4f819e584b5852", size = 8710102, upload-time = "2025-07-14T20:13:24.682Z" }, - { url = "https://files.pythonhosted.org/packages/a5/be/3fd5de0979fcb3994bfee0d65ed8ca9506a8a1260651b86174f6a86f52b3/pywin32-311-cp313-cp313-win32.whl", hash = "sha256:f95ba5a847cba10dd8c4d8fefa9f2a6cf283b8b88ed6178fa8a6c1ab16054d0d", size = 8705700, upload-time = "2025-07-14T20:13:26.471Z" }, - { url = "https://files.pythonhosted.org/packages/e3/28/e0a1909523c6890208295a29e05c2adb2126364e289826c0a8bc7297bd5c/pywin32-311-cp313-cp313-win_amd64.whl", hash = "sha256:718a38f7e5b058e76aee1c56ddd06908116d35147e133427e59a3983f703a20d", size = 9494700, upload-time = "2025-07-14T20:13:28.243Z" }, - { url = "https://files.pythonhosted.org/packages/04/bf/90339ac0f55726dce7d794e6d79a18a91265bdf3aa70b6b9ca52f35e022a/pywin32-311-cp313-cp313-win_arm64.whl", hash = "sha256:7b4075d959648406202d92a2310cb990fea19b535c7f4a78d3f5e10b926eeb8a", size = 8709318, upload-time = "2025-07-14T20:13:30.348Z" }, - { url = "https://files.pythonhosted.org/packages/c9/31/097f2e132c4f16d99a22bfb777e0fd88bd8e1c634304e102f313af69ace5/pywin32-311-cp314-cp314-win32.whl", hash = "sha256:b7a2c10b93f8986666d0c803ee19b5990885872a7de910fc460f9b0c2fbf92ee", size = 8840714, upload-time = "2025-07-14T20:13:32.449Z" }, - { url = "https://files.pythonhosted.org/packages/90/4b/07c77d8ba0e01349358082713400435347df8426208171ce297da32c313d/pywin32-311-cp314-cp314-win_amd64.whl", hash = "sha256:3aca44c046bd2ed8c90de9cb8427f581c479e594e99b5c0bb19b29c10fd6cb87", size = 9656800, upload-time = "2025-07-14T20:13:34.312Z" }, - { url = "https://files.pythonhosted.org/packages/c0/d2/21af5c535501a7233e734b8af901574572da66fcc254cb35d0609c9080dd/pywin32-311-cp314-cp314-win_arm64.whl", hash = "sha256:a508e2d9025764a8270f93111a970e1d0fbfc33f4153b388bb649b7eec4f9b42", size = 8932540, upload-time = "2025-07-14T20:13:36.379Z" }, +version = "312" +source = { registry = "https://pypi.org/simple" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/fe/1b/9cfdeac80ee45bebbbcb31f1b7b99a0d81a1c72de48d837be984e0e88b1d/pywin32-312-cp310-cp310-win32.whl", hash = "sha256:772235332b5d1024c696f11cea1ae4be7930f0a8b894bb43db14e3f435f1ff7e", size = 6361387, upload-time = "2026-06-04T07:49:14.329Z" }, + { url = "https://files.pythonhosted.org/packages/33/b1/7afc96d041d982c27bc2df6f853d43f01fd273e3d39d04be3647ddeb533d/pywin32-312-cp310-cp310-win_amd64.whl", hash = "sha256:5dbc35d2b5320dc07f25fa31269cfb767471002b17de5eb067d03da68c7cb2db", size = 6926780, upload-time = "2026-06-04T07:49:16.881Z" }, + { url = "https://files.pythonhosted.org/packages/ce/3a/4140da9ad54108e517f4a16b2d83da3033e08662144623e1239587cb7db6/pywin32-312-cp310-cp310-win_arm64.whl", hash = "sha256:3020656e34f1cf7faeb7bccd2b84653a607c6ff0c55ada85e6487d61716deabd", size = 4307203, upload-time = "2026-06-04T07:49:18.993Z" }, + { url = "https://files.pythonhosted.org/packages/1f/f5/10a6e845a00fc5e7afd0a988b744f403d4d57162a28d160a093c4d9322f0/pywin32-312-cp311-cp311-win32.whl", hash = "sha256:17948aeadbdb091f0ced6ef0841620794e68327b94ee415571c1203594b7215c", size = 6362659, upload-time = "2026-06-04T07:49:21.349Z" }, + { url = "https://files.pythonhosted.org/packages/35/c4/dcd2d62b5944b6d5db53413a5899016ccd57ffcb7278f3f81655d25d2027/pywin32-312-cp311-cp311-win_amd64.whl", hash = "sha256:d11417d84412f859b722fad0841b3614459ed0047f7542d8362e77884f6b6e8a", size = 6928825, upload-time = "2026-06-04T07:49:23.934Z" }, + { url = "https://files.pythonhosted.org/packages/b7/56/3cbb433fe4501cdba2eb9040f56a4e1a8243faa4186b25295564d1a7a79d/pywin32-312-cp311-cp311-win_arm64.whl", hash = "sha256:b2200a054ca6d6625c4842fc56a4976a4b47f96b73dbe5538c3f813a80359f47", size = 6721875, upload-time = "2026-06-04T07:49:26.416Z" }, + { url = "https://files.pythonhosted.org/packages/83/ff/32aa7d2ed0ab12b323aaa64f9b75e6ad4f8fd09f9ccfc28c79414d46838d/pywin32-312-cp312-cp312-win32.whl", hash = "sha256:dab4f65ac9c4e48400a2a0530c46c3c579cd5905ecd11b80692373915269208b", size = 6371877, upload-time = "2026-06-04T07:49:28.836Z" }, + { url = "https://files.pythonhosted.org/packages/03/d9/77040d3b43df3f3be32ea289433d660d2727f5ba327bc73be835127d9d60/pywin32-312-cp312-cp312-win_amd64.whl", hash = "sha256:b457f6d628a47e8a7346ce22acb7e1a46a4a78b52e1d17e1af56871bd19a93bc", size = 6914841, upload-time = "2026-06-04T07:49:31.85Z" }, + { url = "https://files.pythonhosted.org/packages/e3/cc/7b1ec671775756020a0ee7f4feeaf3c568f0ab86bd3900088cf986937a92/pywin32-312-cp312-cp312-win_arm64.whl", hash = "sha256:6017c58e12f6809fbb0555b75df144c2922a9ffd18e4b9b5afa863b6c1a9d950", size = 6727901, upload-time = "2026-06-04T07:49:34.244Z" }, + { url = "https://files.pythonhosted.org/packages/2d/41/12fbfd7f36ed2146d8bc9de96c2741296bf0d490b98508496cff322e274c/pywin32-312-cp313-cp313-win32.whl", hash = "sha256:7a27df850933d16a8eabfbaeb73d52b273e2da667f80d70b01a89d1f6828d02c", size = 6370184, upload-time = "2026-06-04T07:49:36.253Z" }, + { url = "https://files.pythonhosted.org/packages/ba/db/36a78e3403099d31d9746d13fdcde5accc43c1155f375a34d15983a479a7/pywin32-312-cp313-cp313-win_amd64.whl", hash = "sha256:c53e878d15a1c44788082bfe712a905433473aa38f86375b7cf8b45e3acbaaf9", size = 6914298, upload-time = "2026-06-04T07:49:38.876Z" }, + { url = "https://files.pythonhosted.org/packages/84/37/c1697194092b76de9ed47ca124323f02c57ffc8a45c06f88a3d5acaf01eb/pywin32-312-cp313-cp313-win_arm64.whl", hash = "sha256:59aba5d5940842075343a5ddc6b11f1cdf0d1567fe745290359dfbcc7c2eb831", size = 6727640, upload-time = "2026-06-04T07:49:41.083Z" }, + { url = "https://files.pythonhosted.org/packages/fc/2b/1f3cded5822fd49c02f40544cbb5f58c7cfd6b1694869fd476cb6170ee97/pywin32-312-cp314-cp314-win32.whl", hash = "sha256:a77a90fbb6881238d2ca9c6fd797b25817f3768fe78d214a90137ff055a75f5b", size = 6468928, upload-time = "2026-06-04T07:49:43.188Z" }, + { url = "https://files.pythonhosted.org/packages/21/82/3bf86d2e2808902013132e1ce905a7da0da53790f3836c64bf44d55e24f3/pywin32-312-cp314-cp314-win_amd64.whl", hash = "sha256:a4dd3a848290ef724347b19f301045831d8e802fa4464f491b98b1e0a081432e", size = 7024157, upload-time = "2026-06-04T07:49:45.34Z" }, + { url = "https://files.pythonhosted.org/packages/a4/0e/73f6d6800b4f27655abd9e9f6aaeaefcddb2b946e4674efa2bab184a7f7b/pywin32-312-cp314-cp314-win_arm64.whl", hash = "sha256:9fce94568364e0155e6dfb781ac5d95903be8baf28670632beab1b523f300daa", size = 6839598, upload-time = "2026-06-04T07:49:47.613Z" }, + { url = "https://files.pythonhosted.org/packages/eb/61/caa39686032d2ebdd04ff0ab5cbe163126c0066d98e00c9018646e42393b/pywin32-312-cp315-cp315-win32.whl", hash = "sha256:5c1fbe4a937a73ae9297384a3da38518cbc694c68ad8a809b2e19acd350f03ed", size = 6471159, upload-time = "2026-06-04T07:49:50.035Z" }, + { url = "https://files.pythonhosted.org/packages/0f/cd/7e1de64a4a6f69c04214169657ccab0d93a670ea50e35eb8f489d7378249/pywin32-312-cp315-cp315-win_amd64.whl", hash = "sha256:c2f03a0f73f804a13c2735b99392b0cd426bb4f2c4d0178e5ac966a0f21618d5", size = 7025293, upload-time = "2026-06-04T07:49:54.857Z" }, + { url = "https://files.pythonhosted.org/packages/23/ed/4532e9388e65fa16b46776ef47ad631a64eda1631884488af707666350ed/pywin32-312-cp315-cp315-win_arm64.whl", hash = "sha256:a8597d28f267b39074aef51fa593530082b39cbe5a074226096857b1fed2dfb9", size = 6840337, upload-time = "2026-06-04T07:49:57.531Z" }, ] [[package]] @@ -4769,16 +4849,16 @@ wheels = [ [[package]] name = "readme-renderer" -version = "44.0" +version = "45.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "docutils" }, { name = "nh3" }, { name = "pygments" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/5a/a9/104ec9234c8448c4379768221ea6df01260cd6c2ce13182d4eac531c8342/readme_renderer-44.0.tar.gz", hash = "sha256:8712034eabbfa6805cacf1402b4eeb2a73028f72d1166d6f5cb7f9c047c5d1e1", size = 32056, upload-time = "2024-07-08T15:00:57.805Z" } +sdist = { url = "https://files.pythonhosted.org/packages/02/51/d3a6ea424652c60f05600d8c2e01a55c913755e7cdad64afabbd1aa16f44/readme_renderer-45.0.tar.gz", hash = "sha256:030a8fac74904f8fba11ad1bb6964e3f76e896dc7e5e71f16af190c9056696d1", size = 36172, upload-time = "2026-06-09T21:05:17.37Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/e1/67/921ec3024056483db83953ae8e48079ad62b92db7880013ca77632921dd0/readme_renderer-44.0-py3-none-any.whl", hash = "sha256:2fbca89b81a08526aadf1357a8c2ae889ec05fb03f5da67f9769c9a592166151", size = 13310, upload-time = "2024-07-08T15:00:56.577Z" }, + { url = "https://files.pythonhosted.org/packages/97/1b/295bf2fa3e740131778065e5ffa2c481f0e7210182d408e9a2c244ff5b0c/readme_renderer-45.0-py3-none-any.whl", hash = "sha256:3385ed220117104a2bceb4a9dac8c5fdf6d1f96890d7ea2a9c7174fd5c84091f", size = 14134, upload-time = "2026-06-09T21:05:15.85Z" }, ] [[package]] @@ -4787,7 +4867,8 @@ version = "0.37.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "attrs" }, - { name = "rpds-py" }, + { name = "rpds-py", version = "0.30.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.11'" }, + { name = "rpds-py", version = "2026.5.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" }, { name = "typing-extensions", marker = "python_full_version < '3.13'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/22/f5/df4e9027acead3ecc63e50fe1e36aca1523e1719559c499951bb4b53188f/referencing-0.37.0.tar.gz", hash = "sha256:44aefc3142c5b842538163acb373e24cce6632bd54bdb01b21ad5863489f50d8", size = 78036, upload-time = "2025-10-13T15:30:48.871Z" } @@ -4797,128 +4878,128 @@ wheels = [ [[package]] name = "regex" -version = "2026.4.4" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/cb/0e/3a246dbf05666918bd3664d9d787f84a9108f6f43cc953a077e4a7dfdb7e/regex-2026.4.4.tar.gz", hash = "sha256:e08270659717f6973523ce3afbafa53515c4dc5dcad637dc215b6fd50f689423", size = 416000, upload-time = "2026-04-03T20:56:28.155Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/12/59/fd98f8fd54b3feaa76a855324c676c17668c5a1121ec91b7ec96b01bf865/regex-2026.4.4-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:74fa82dcc8143386c7c0392e18032009d1db715c25f4ba22d23dc2e04d02a20f", size = 489403, upload-time = "2026-04-03T20:52:39.742Z" }, - { url = "https://files.pythonhosted.org/packages/6c/64/d0f222f68e3579d50babf0e4fcc9c9639ef0587fecc00b15e1e46bfc32fa/regex-2026.4.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:a85b620a388d6c9caa12189233109e236b3da3deffe4ff11b84ae84e218a274f", size = 291208, upload-time = "2026-04-03T20:52:42.943Z" }, - { url = "https://files.pythonhosted.org/packages/16/7f/3fab9709b0b0060ba81a04b8a107b34147cd14b9c5551b772154d6505504/regex-2026.4.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:2895506ebe32cc63eeed8f80e6eae453171cfccccab35b70dc3129abec35a5b8", size = 289214, upload-time = "2026-04-03T20:52:44.648Z" }, - { url = "https://files.pythonhosted.org/packages/14/bc/f5dcf04fd462139dcd75495c02eee22032ef741cfa151386a39c3f5fc9b5/regex-2026.4.4-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6780f008ee81381c737634e75c24e5a6569cc883c4f8e37a37917ee79efcafd9", size = 785505, upload-time = "2026-04-03T20:52:46.35Z" }, - { url = "https://files.pythonhosted.org/packages/37/36/8a906e216d5b4de7ec3788c1d589b45db40c1c9580cd7b326835cfc976d4/regex-2026.4.4-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:88e9b048345c613f253bea4645b2fe7e579782b82cac99b1daad81e29cc2ed8e", size = 852129, upload-time = "2026-04-03T20:52:48.661Z" }, - { url = "https://files.pythonhosted.org/packages/a5/bb/bad2d79be0917a6ef31f5e0f161d9265cb56fd90a3ae1d2e8d991882a48b/regex-2026.4.4-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:be061028481186ba62a0f4c5f1cc1e3d5ab8bce70c89236ebe01023883bc903b", size = 899578, upload-time = "2026-04-03T20:52:50.61Z" }, - { url = "https://files.pythonhosted.org/packages/1a/b9/7cd0ceb58cd99c70806241636640ae15b4a3fe62e22e9b99afa67a0d7965/regex-2026.4.4-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d2228c02b368d69b724c36e96d3d1da721561fb9cc7faa373d7bf65e07d75cb5", size = 793634, upload-time = "2026-04-03T20:52:53Z" }, - { url = "https://files.pythonhosted.org/packages/2c/fb/c58e3ea40ed183806ccbac05c29a3e8c2f88c1d3a66ed27860d5cad7c62d/regex-2026.4.4-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:0540e5b733618a2f84e9cb3e812c8afa82e151ca8e19cf6c4e95c5a65198236f", size = 786210, upload-time = "2026-04-03T20:52:54.713Z" }, - { url = "https://files.pythonhosted.org/packages/54/a9/53790fc7a6c948a7be2bc7214fd9cabdd0d1ba561b0f401c91f4ff0357f0/regex-2026.4.4-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:cf9b1b2e692d4877880388934ac746c99552ce6bf40792a767fd42c8c99f136d", size = 769930, upload-time = "2026-04-03T20:52:56.825Z" }, - { url = "https://files.pythonhosted.org/packages/e3/3c/29ca44729191c79f5476538cd0fa04fa2553b3c45508519ecea4c7afa8f6/regex-2026.4.4-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:011bb48bffc1b46553ac704c975b3348717f4e4aa7a67522b51906f99da1820c", size = 774892, upload-time = "2026-04-03T20:52:58.934Z" }, - { url = "https://files.pythonhosted.org/packages/3e/db/6ae74ef8a4cfead341c367e4eed45f71fb1aaba35827a775eed4f1ba4f74/regex-2026.4.4-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:8512fcdb43f1bf18582698a478b5ab73f9c1667a5b7548761329ef410cd0a760", size = 848816, upload-time = "2026-04-03T20:53:00.684Z" }, - { url = "https://files.pythonhosted.org/packages/53/9a/f7f2c1c6b610d7c6de1c3dc5951effd92c324b1fde761af2044b4721020f/regex-2026.4.4-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:867bddc63109a0276f5a31999e4c8e0eb7bbbad7d6166e28d969a2c1afeb97f9", size = 758363, upload-time = "2026-04-03T20:53:02.155Z" }, - { url = "https://files.pythonhosted.org/packages/dd/55/e5386d393bbf8b43c8b084703a46d635e7b2bdc6e0f5909a2619ea1125f1/regex-2026.4.4-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:1b9a00b83f3a40e09859c78920571dcb83293c8004079653dd22ec14bbfa98c7", size = 837122, upload-time = "2026-04-03T20:53:03.727Z" }, - { url = "https://files.pythonhosted.org/packages/01/da/cc78710ea2e60b10bacfcc9beb18c67514200ab03597b3b2b319995785c2/regex-2026.4.4-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:e355be718caf838aa089870259cf1776dc2a4aa980514af9d02c59544d9a8b22", size = 782140, upload-time = "2026-04-03T20:53:05.608Z" }, - { url = "https://files.pythonhosted.org/packages/a2/5f/c7bcba41529105d6c2ca7080ecab7184cd00bee2e1ad1fdea80e618704ea/regex-2026.4.4-cp310-cp310-win32.whl", hash = "sha256:33bfda9684646d323414df7abe5692c61d297dbb0530b28ec66442e768813c59", size = 266225, upload-time = "2026-04-03T20:53:07.342Z" }, - { url = "https://files.pythonhosted.org/packages/eb/26/a745729c2c49354ec4f4bce168f29da932ca01b4758227686cc16c7dde1b/regex-2026.4.4-cp310-cp310-win_amd64.whl", hash = "sha256:0709f22a56798457ae317bcce42aacee33c680068a8f14097430d9f9ba364bee", size = 278393, upload-time = "2026-04-03T20:53:08.65Z" }, - { url = "https://files.pythonhosted.org/packages/87/8b/4327eeb9dbb4b098ebecaf02e9f82b79b6077beeb54c43d9a0660cf7c44c/regex-2026.4.4-cp310-cp310-win_arm64.whl", hash = "sha256:ee9627de8587c1a22201cb16d0296ab92b4df5cdcb5349f4e9744d61db7c7c98", size = 270470, upload-time = "2026-04-03T20:53:10.018Z" }, - { url = "https://files.pythonhosted.org/packages/e0/7a/617356cbecdb452812a5d42f720d6d5096b360d4a4c1073af700ea140ad2/regex-2026.4.4-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:b4c36a85b00fadb85db9d9e90144af0a980e1a3d2ef9cd0f8a5bef88054657c6", size = 489415, upload-time = "2026-04-03T20:53:11.645Z" }, - { url = "https://files.pythonhosted.org/packages/20/e6/bf057227144d02e3ba758b66649e87531d744dda5f3254f48660f18ae9d8/regex-2026.4.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:dcb5453ecf9cd58b562967badd1edbf092b0588a3af9e32ee3d05c985077ce87", size = 291205, upload-time = "2026-04-03T20:53:13.289Z" }, - { url = "https://files.pythonhosted.org/packages/eb/3b/637181b787dd1a820ba1c712cee2b4144cd84a32dc776ca067b12b2d70c8/regex-2026.4.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:6aa809ed4dc3706cc38594d67e641601bd2f36d5555b2780ff074edfcb136cf8", size = 289225, upload-time = "2026-04-03T20:53:16.002Z" }, - { url = "https://files.pythonhosted.org/packages/05/21/bac05d806ed02cd4b39d9c8e5b5f9a2998c94c3a351b7792e80671fa5315/regex-2026.4.4-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:33424f5188a7db12958246a54f59a435b6cb62c5cf9c8d71f7cc49475a5fdada", size = 792434, upload-time = "2026-04-03T20:53:17.414Z" }, - { url = "https://files.pythonhosted.org/packages/d9/17/c65d1d8ae90b772d5758eb4014e1e011bb2db353fc4455432e6cc9100df7/regex-2026.4.4-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:7d346fccdde28abba117cc9edc696b9518c3307fbfcb689e549d9b5979018c6d", size = 861730, upload-time = "2026-04-03T20:53:18.903Z" }, - { url = "https://files.pythonhosted.org/packages/ad/64/933321aa082a2c6ee2785f22776143ba89840189c20d3b6b1d12b6aae16b/regex-2026.4.4-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:415a994b536440f5011aa77e50a4274d15da3245e876e5c7f19da349caaedd87", size = 906495, upload-time = "2026-04-03T20:53:20.561Z" }, - { url = "https://files.pythonhosted.org/packages/01/ea/4c8d306e9c36ac22417336b1e02e7b358152c34dc379673f2d331143725f/regex-2026.4.4-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:21e5eb86179b4c67b5759d452ea7c48eb135cd93308e7a260aa489ed2eb423a4", size = 799810, upload-time = "2026-04-03T20:53:22.961Z" }, - { url = "https://files.pythonhosted.org/packages/29/ce/7605048f00e1379eba89d610c7d644d8f695dc9b26d3b6ecfa3132b872ff/regex-2026.4.4-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:312ec9dd1ae7d96abd8c5a36a552b2139931914407d26fba723f9e53c8186f86", size = 774242, upload-time = "2026-04-03T20:53:25.015Z" }, - { url = "https://files.pythonhosted.org/packages/e9/77/283e0d5023fde22cd9e86190d6d9beb21590a452b195ffe00274de470691/regex-2026.4.4-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:a0d2b28aa1354c7cd7f71b7658c4326f7facac106edd7f40eda984424229fd59", size = 781257, upload-time = "2026-04-03T20:53:26.918Z" }, - { url = "https://files.pythonhosted.org/packages/8b/fb/7f3b772be101373c8626ed34c5d727dcbb8abd42a7b1219bc25fd9a3cc04/regex-2026.4.4-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:349d7310eddff40429a099c08d995c6d4a4bfaf3ff40bd3b5e5cb5a5a3c7d453", size = 854490, upload-time = "2026-04-03T20:53:29.065Z" }, - { url = "https://files.pythonhosted.org/packages/85/30/56547b80f34f4dd2986e1cdd63b1712932f63b6c4ce2f79c50a6cd79d1c2/regex-2026.4.4-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:e7ab63e9fe45a9ec3417509e18116b367e89c9ceb6219222a3396fa30b147f80", size = 763544, upload-time = "2026-04-03T20:53:30.917Z" }, - { url = "https://files.pythonhosted.org/packages/ac/2f/ce060fdfea8eff34a8997603532e44cdb7d1f35e3bc253612a8707a90538/regex-2026.4.4-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:fe896e07a5a2462308297e515c0054e9ec2dd18dfdc9427b19900b37dfe6f40b", size = 844442, upload-time = "2026-04-03T20:53:32.463Z" }, - { url = "https://files.pythonhosted.org/packages/e5/44/810cb113096a1dacbe82789fbfab2823f79d19b7f1271acecb7009ba9b88/regex-2026.4.4-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:eb59c65069498dbae3c0ef07bbe224e1eaa079825a437fb47a479f0af11f774f", size = 789162, upload-time = "2026-04-03T20:53:34.039Z" }, - { url = "https://files.pythonhosted.org/packages/20/96/9647dd7f2ecf6d9ce1fb04dfdb66910d094e10d8fe53e9c15096d8aa0bd2/regex-2026.4.4-cp311-cp311-win32.whl", hash = "sha256:2a5d273181b560ef8397c8825f2b9d57013de744da9e8257b8467e5da8599351", size = 266227, upload-time = "2026-04-03T20:53:35.601Z" }, - { url = "https://files.pythonhosted.org/packages/33/80/74e13262460530c3097ff343a17de9a34d040a5dc4de9cf3a8241faab51c/regex-2026.4.4-cp311-cp311-win_amd64.whl", hash = "sha256:9542ccc1e689e752594309444081582f7be2fdb2df75acafea8a075108566735", size = 278399, upload-time = "2026-04-03T20:53:37.021Z" }, - { url = "https://files.pythonhosted.org/packages/1c/3c/39f19f47f19dcefa3403f09d13562ca1c0fd07ab54db2bc03148f3f6b46a/regex-2026.4.4-cp311-cp311-win_arm64.whl", hash = "sha256:b5f9fb784824a042be3455b53d0b112655686fdb7a91f88f095f3fee1e2a2a54", size = 270473, upload-time = "2026-04-03T20:53:38.633Z" }, - { url = "https://files.pythonhosted.org/packages/e5/28/b972a4d3df61e1d7bcf1b59fdb3cddef22f88b6be43f161bb41ebc0e4081/regex-2026.4.4-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:c07ab8794fa929e58d97a0e1796b8b76f70943fa39df225ac9964615cf1f9d52", size = 490434, upload-time = "2026-04-03T20:53:40.219Z" }, - { url = "https://files.pythonhosted.org/packages/84/20/30041446cf6dc3e0eab344fc62770e84c23b6b68a3b657821f9f80cb69b4/regex-2026.4.4-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:2c785939dc023a1ce4ec09599c032cc9933d258a998d16ca6f2b596c010940eb", size = 292061, upload-time = "2026-04-03T20:53:41.862Z" }, - { url = "https://files.pythonhosted.org/packages/62/c8/3baa06d75c98c46d4cc4262b71fd2edb9062b5665e868bca57859dadf93a/regex-2026.4.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:1b1ce5c81c9114f1ce2f9288a51a8fd3aeea33a0cc440c415bf02da323aa0a76", size = 289628, upload-time = "2026-04-03T20:53:43.701Z" }, - { url = "https://files.pythonhosted.org/packages/31/87/3accf55634caad8c0acab23f5135ef7d4a21c39f28c55c816ae012931408/regex-2026.4.4-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:760ef21c17d8e6a4fe8cf406a97cf2806a4df93416ccc82fc98d25b1c20425be", size = 796651, upload-time = "2026-04-03T20:53:45.379Z" }, - { url = "https://files.pythonhosted.org/packages/f6/0c/aaa2c83f34efedbf06f61cb1942c25f6cf1ee3b200f832c4d05f28306c2e/regex-2026.4.4-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:7088fcdcb604a4417c208e2169715800d28838fefd7455fbe40416231d1d47c1", size = 865916, upload-time = "2026-04-03T20:53:47.064Z" }, - { url = "https://files.pythonhosted.org/packages/d9/f6/8c6924c865124643e8f37823eca845dc27ac509b2ee58123685e71cd0279/regex-2026.4.4-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:07edca1ba687998968f7db5bc355288d0c6505caa7374f013d27356d93976d13", size = 912287, upload-time = "2026-04-03T20:53:49.422Z" }, - { url = "https://files.pythonhosted.org/packages/11/0e/a9f6f81013e0deaf559b25711623864970fe6a098314e374ccb1540a4152/regex-2026.4.4-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:993f657a7c1c6ec51b5e0ba97c9817d06b84ea5fa8d82e43b9405de0defdc2b9", size = 801126, upload-time = "2026-04-03T20:53:51.096Z" }, - { url = "https://files.pythonhosted.org/packages/71/61/3a0cc8af2dc0c8deb48e644dd2521f173f7e6513c6e195aad9aa8dd77ac5/regex-2026.4.4-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:2b69102a743e7569ebee67e634a69c4cb7e59d6fa2e1aa7d3bdbf3f61435f62d", size = 776788, upload-time = "2026-04-03T20:53:52.889Z" }, - { url = "https://files.pythonhosted.org/packages/64/0b/8bb9cbf21ef7dee58e49b0fdb066a7aded146c823202e16494a36777594f/regex-2026.4.4-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:6dac006c8b6dda72d86ea3d1333d45147de79a3a3f26f10c1cf9287ca4ca0ac3", size = 785184, upload-time = "2026-04-03T20:53:55.627Z" }, - { url = "https://files.pythonhosted.org/packages/99/c2/d3e80e8137b25ee06c92627de4e4d98b94830e02b3e6f81f3d2e3f504cf5/regex-2026.4.4-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:50a766ee2010d504554bfb5f578ed2e066898aa26411d57e6296230627cdefa0", size = 859913, upload-time = "2026-04-03T20:53:57.249Z" }, - { url = "https://files.pythonhosted.org/packages/bc/e6/9d5d876157d969c804622456ef250017ac7a8f83e0e14f903b9e6df5ce95/regex-2026.4.4-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:9e2f5217648f68e3028c823df58663587c1507a5ba8419f4fdfc8a461be76043", size = 765732, upload-time = "2026-04-03T20:53:59.428Z" }, - { url = "https://files.pythonhosted.org/packages/82/80/b568935b4421388561c8ed42aff77247285d3ae3bb2a6ca22af63bae805e/regex-2026.4.4-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:39d8de85a08e32632974151ba59c6e9140646dcc36c80423962b1c5c0a92e244", size = 852152, upload-time = "2026-04-03T20:54:01.505Z" }, - { url = "https://files.pythonhosted.org/packages/39/29/f0f81217e21cd998245da047405366385d5c6072048038a3d33b37a79dc0/regex-2026.4.4-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:55d9304e0e7178dfb1e106c33edf834097ddf4a890e2f676f6c5118f84390f73", size = 789076, upload-time = "2026-04-03T20:54:03.323Z" }, - { url = "https://files.pythonhosted.org/packages/49/1d/1d957a61976ab9d4e767dd4f9d04b66cc0c41c5e36cf40e2d43688b5ae6f/regex-2026.4.4-cp312-cp312-win32.whl", hash = "sha256:04bb679bc0bde8a7bfb71e991493d47314e7b98380b083df2447cda4b6edb60f", size = 266700, upload-time = "2026-04-03T20:54:05.639Z" }, - { url = "https://files.pythonhosted.org/packages/c5/5c/bf575d396aeb58ea13b06ef2adf624f65b70fafef6950a80fc3da9cae3bc/regex-2026.4.4-cp312-cp312-win_amd64.whl", hash = "sha256:db0ac18435a40a2543dbb3d21e161a6c78e33e8159bd2e009343d224bb03bb1b", size = 277768, upload-time = "2026-04-03T20:54:07.312Z" }, - { url = "https://files.pythonhosted.org/packages/c9/27/049df16ec6a6828ccd72add3c7f54b4df029669bea8e9817df6fff58be90/regex-2026.4.4-cp312-cp312-win_arm64.whl", hash = "sha256:4ce255cc05c1947a12989c6db801c96461947adb7a59990f1360b5983fab4983", size = 270568, upload-time = "2026-04-03T20:54:09.484Z" }, - { url = "https://files.pythonhosted.org/packages/9d/83/c4373bc5f31f2cf4b66f9b7c31005bd87fe66f0dce17701f7db4ee79ee29/regex-2026.4.4-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:62f5519042c101762509b1d717b45a69c0139d60414b3c604b81328c01bd1943", size = 490273, upload-time = "2026-04-03T20:54:11.202Z" }, - { url = "https://files.pythonhosted.org/packages/46/f8/fe62afbcc3cf4ad4ac9adeaafd98aa747869ae12d3e8e2ac293d0593c435/regex-2026.4.4-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:3790ba9fb5dd76715a7afe34dbe603ba03f8820764b1dc929dd08106214ed031", size = 291954, upload-time = "2026-04-03T20:54:13.412Z" }, - { url = "https://files.pythonhosted.org/packages/5a/92/4712b9fe6a33d232eeb1c189484b80c6c4b8422b90e766e1195d6e758207/regex-2026.4.4-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:8fae3c6e795d7678963f2170152b0d892cf6aee9ee8afc8c45e6be38d5107fe7", size = 289487, upload-time = "2026-04-03T20:54:15.824Z" }, - { url = "https://files.pythonhosted.org/packages/88/2c/f83b93f85e01168f1070f045a42d4c937b69fdb8dd7ae82d307253f7e36e/regex-2026.4.4-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:298c3ec2d53225b3bf91142eb9691025bab610e0c0c51592dde149db679b3d17", size = 796646, upload-time = "2026-04-03T20:54:18.229Z" }, - { url = "https://files.pythonhosted.org/packages/df/55/61a2e17bf0c4dc57e11caf8dd11771280d8aaa361785f9e3bc40d653f4a7/regex-2026.4.4-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:e9638791082eaf5b3ac112c587518ee78e083a11c4b28012d8fe2a0f536dfb17", size = 865904, upload-time = "2026-04-03T20:54:20.019Z" }, - { url = "https://files.pythonhosted.org/packages/45/32/1ac8ed1b5a346b5993a3d256abe0a0f03b0b73c8cc88d928537368ac65b6/regex-2026.4.4-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:ae3e764bd4c5ff55035dc82a8d49acceb42a5298edf6eb2fc4d328ee5dd7afae", size = 912304, upload-time = "2026-04-03T20:54:22.403Z" }, - { url = "https://files.pythonhosted.org/packages/26/47/2ee5c613ab546f0eddebf9905d23e07beb933416b1246c2d8791d01979b4/regex-2026.4.4-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ffa81f81b80047ba89a3c69ae6a0f78d06f4a42ce5126b0eb2a0a10ad44e0b2e", size = 801126, upload-time = "2026-04-03T20:54:24.308Z" }, - { url = "https://files.pythonhosted.org/packages/75/cd/41dacd129ca9fd20bd7d02f83e0fad83e034ac8a084ec369c90f55ef37e2/regex-2026.4.4-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:f56ebf9d70305307a707911b88469213630aba821e77de7d603f9d2f0730687d", size = 776772, upload-time = "2026-04-03T20:54:26.319Z" }, - { url = "https://files.pythonhosted.org/packages/89/6d/5af0b588174cb5f46041fa7dd64d3fd5cd2fe51f18766703d1edc387f324/regex-2026.4.4-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:773d1dfd652bbffb09336abf890bfd64785c7463716bf766d0eb3bc19c8b7f27", size = 785228, upload-time = "2026-04-03T20:54:28.387Z" }, - { url = "https://files.pythonhosted.org/packages/b7/3b/f5a72b7045bd59575fc33bf1345f156fcfd5a8484aea6ad84b12c5a82114/regex-2026.4.4-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:d51d20befd5275d092cdffba57ded05f3c436317ee56466c8928ac32d960edaf", size = 860032, upload-time = "2026-04-03T20:54:30.641Z" }, - { url = "https://files.pythonhosted.org/packages/39/a4/72a317003d6fcd7a573584a85f59f525dfe8f67e355ca74eb6b53d66a5e2/regex-2026.4.4-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:0a51cdb3c1e9161154f976cb2bef9894bc063ac82f31b733087ffb8e880137d0", size = 765714, upload-time = "2026-04-03T20:54:32.789Z" }, - { url = "https://files.pythonhosted.org/packages/25/1e/5672e16f34dbbcb2560cc7e6a2fbb26dfa8b270711e730101da4423d3973/regex-2026.4.4-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:ae5266a82596114e41fb5302140e9630204c1b5f325c770bec654b95dd54b0aa", size = 852078, upload-time = "2026-04-03T20:54:34.546Z" }, - { url = "https://files.pythonhosted.org/packages/f7/0d/c813f0af7c6cc7ed7b9558bac2e5120b60ad0fa48f813e4d4bd55446f214/regex-2026.4.4-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:c882cd92ec68585e9c1cf36c447ec846c0d94edd706fe59e0c198e65822fd23b", size = 789181, upload-time = "2026-04-03T20:54:36.642Z" }, - { url = "https://files.pythonhosted.org/packages/ea/6d/a344608d1adbd2a95090ddd906cec09a11be0e6517e878d02a5123e0917f/regex-2026.4.4-cp313-cp313-win32.whl", hash = "sha256:05568c4fbf3cb4fa9e28e3af198c40d3237cf6041608a9022285fe567ec3ad62", size = 266690, upload-time = "2026-04-03T20:54:38.343Z" }, - { url = "https://files.pythonhosted.org/packages/31/07/54049f89b46235ca6f45cd6c88668a7050e77d4a15555e47dd40fde75263/regex-2026.4.4-cp313-cp313-win_amd64.whl", hash = "sha256:3384df51ed52db0bea967e21458ab0a414f67cdddfd94401688274e55147bb81", size = 277733, upload-time = "2026-04-03T20:54:40.11Z" }, - { url = "https://files.pythonhosted.org/packages/0e/21/61366a8e20f4d43fb597708cac7f0e2baadb491ecc9549b4980b2be27d16/regex-2026.4.4-cp313-cp313-win_arm64.whl", hash = "sha256:acd38177bd2c8e69a411d6521760806042e244d0ef94e2dd03ecdaa8a3c99427", size = 270565, upload-time = "2026-04-03T20:54:41.883Z" }, - { url = "https://files.pythonhosted.org/packages/f1/1e/3a2b9672433bef02f5d39aa1143ca2c08f311c1d041c464a42be9ae648dc/regex-2026.4.4-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:f94a11a9d05afcfcfa640e096319720a19cc0c9f7768e1a61fceee6a3afc6c7c", size = 494126, upload-time = "2026-04-03T20:54:43.602Z" }, - { url = "https://files.pythonhosted.org/packages/4e/4b/c132a4f4fe18ad3340d89fcb56235132b69559136036b845be3c073142ed/regex-2026.4.4-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:36bcb9d6d1307ab629edc553775baada2aefa5c50ccc0215fbfd2afcfff43141", size = 293882, upload-time = "2026-04-03T20:54:45.41Z" }, - { url = "https://files.pythonhosted.org/packages/f4/5f/eaa38092ce7a023656280f2341dbbd4ad5f05d780a70abba7bb4f4bea54c/regex-2026.4.4-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:261c015b3e2ed0919157046d768774ecde57f03d8fa4ba78d29793447f70e717", size = 292334, upload-time = "2026-04-03T20:54:47.051Z" }, - { url = "https://files.pythonhosted.org/packages/5f/f6/dd38146af1392dac33db7074ab331cec23cced3759167735c42c5460a243/regex-2026.4.4-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c228cf65b4a54583763645dcd73819b3b381ca8b4bb1b349dee1c135f4112c07", size = 811691, upload-time = "2026-04-03T20:54:49.074Z" }, - { url = "https://files.pythonhosted.org/packages/7a/f0/dc54c2e69f5eeec50601054998ec3690d5344277e782bd717e49867c1d29/regex-2026.4.4-cp313-cp313t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:dd2630faeb6876fb0c287f664d93ddce4d50cd46c6e88e60378c05c9047e08ca", size = 871227, upload-time = "2026-04-03T20:54:51.035Z" }, - { url = "https://files.pythonhosted.org/packages/a1/af/cb16bd5dc61621e27df919a4449bbb7e5a1034c34d307e0a706e9cc0f3e3/regex-2026.4.4-cp313-cp313t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:6a50ab11b7779b849472337191f3a043e27e17f71555f98d0092fa6d73364520", size = 917435, upload-time = "2026-04-03T20:54:52.994Z" }, - { url = "https://files.pythonhosted.org/packages/5c/71/8b260897f22996b666edd9402861668f45a2ca259f665ac029e6104a2d7d/regex-2026.4.4-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0734f63afe785138549fbe822a8cfeaccd1bae814c5057cc0ed5b9f2de4fc883", size = 816358, upload-time = "2026-04-03T20:54:54.884Z" }, - { url = "https://files.pythonhosted.org/packages/1c/60/775f7f72a510ef238254906c2f3d737fc80b16ca85f07d20e318d2eea894/regex-2026.4.4-cp313-cp313t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:c4ee50606cb1967db7e523224e05f32089101945f859928e65657a2cbb3d278b", size = 785549, upload-time = "2026-04-03T20:54:57.01Z" }, - { url = "https://files.pythonhosted.org/packages/58/42/34d289b3627c03cf381e44da534a0021664188fa49ba41513da0b4ec6776/regex-2026.4.4-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:6c1818f37be3ca02dcb76d63f2c7aaba4b0dc171b579796c6fbe00148dfec6b1", size = 801364, upload-time = "2026-04-03T20:54:58.981Z" }, - { url = "https://files.pythonhosted.org/packages/fc/20/f6ecf319b382a8f1ab529e898b222c3f30600fcede7834733c26279e7465/regex-2026.4.4-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:f5bfc2741d150d0be3e4a0401a5c22b06e60acb9aa4daa46d9e79a6dcd0f135b", size = 866221, upload-time = "2026-04-03T20:55:00.88Z" }, - { url = "https://files.pythonhosted.org/packages/92/6a/9f16d3609d549bd96d7a0b2aee1625d7512ba6a03efc01652149ef88e74d/regex-2026.4.4-cp313-cp313t-musllinux_1_2_riscv64.whl", hash = "sha256:504ffa8a03609a087cad81277a629b6ce884b51a24bd388a7980ad61748618ff", size = 772530, upload-time = "2026-04-03T20:55:03.213Z" }, - { url = "https://files.pythonhosted.org/packages/fa/f6/aa9768bc96a4c361ac96419fbaf2dcdc33970bb813df3ba9b09d5d7b6d96/regex-2026.4.4-cp313-cp313t-musllinux_1_2_s390x.whl", hash = "sha256:70aadc6ff12e4b444586e57fc30771f86253f9f0045b29016b9605b4be5f7dfb", size = 856989, upload-time = "2026-04-03T20:55:05.087Z" }, - { url = "https://files.pythonhosted.org/packages/4d/b4/c671db3556be2473ae3e4bb7a297c518d281452871501221251ea4ecba57/regex-2026.4.4-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:f4f83781191007b6ef43b03debc35435f10cad9b96e16d147efe84a1d48bdde4", size = 803241, upload-time = "2026-04-03T20:55:07.162Z" }, - { url = "https://files.pythonhosted.org/packages/2a/5c/83e3b1d89fa4f6e5a1bc97b4abd4a9a97b3c1ac7854164f694f5f0ba98a0/regex-2026.4.4-cp313-cp313t-win32.whl", hash = "sha256:e014a797de43d1847df957c0a2a8e861d1c17547ee08467d1db2c370b7568baa", size = 269921, upload-time = "2026-04-03T20:55:09.62Z" }, - { url = "https://files.pythonhosted.org/packages/28/07/077c387121f42cdb4d92b1301133c0d93b5709d096d1669ab847dda9fe2e/regex-2026.4.4-cp313-cp313t-win_amd64.whl", hash = "sha256:b15b88b0d52b179712632832c1d6e58e5774f93717849a41096880442da41ab0", size = 281240, upload-time = "2026-04-03T20:55:11.521Z" }, - { url = "https://files.pythonhosted.org/packages/9d/22/ead4a4abc7c59a4d882662aa292ca02c8b617f30b6e163bc1728879e9353/regex-2026.4.4-cp313-cp313t-win_arm64.whl", hash = "sha256:586b89cdadf7d67bf86ae3342a4dcd2b8d70a832d90c18a0ae955105caf34dbe", size = 272440, upload-time = "2026-04-03T20:55:13.365Z" }, - { url = "https://files.pythonhosted.org/packages/f0/f5/ed97c2dc47b5fbd4b73c0d7d75f9ebc8eca139f2bbef476bba35f28c0a77/regex-2026.4.4-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:2da82d643fa698e5e5210e54af90181603d5853cf469f5eedf9bfc8f59b4b8c7", size = 490343, upload-time = "2026-04-03T20:55:15.241Z" }, - { url = "https://files.pythonhosted.org/packages/80/e9/de4828a7385ec166d673a5790ad06ac48cdaa98bc0960108dd4b9cc1aef7/regex-2026.4.4-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:54a1189ad9d9357760557c91103d5e421f0a2dabe68a5cdf9103d0dcf4e00752", size = 291909, upload-time = "2026-04-03T20:55:17.558Z" }, - { url = "https://files.pythonhosted.org/packages/b4/d6/5cfbfc97f3201a4d24b596a77957e092030dcc4205894bc035cedcfce62f/regex-2026.4.4-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:76d67d5afb1fe402d10a6403bae668d000441e2ab115191a804287d53b772951", size = 289692, upload-time = "2026-04-03T20:55:20.561Z" }, - { url = "https://files.pythonhosted.org/packages/8e/ac/f2212d9fd56fe897e36d0110ba30ba2d247bd6410c5bd98499c7e5a1e1f2/regex-2026.4.4-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e7cd3e4ee8d80447a83bbc9ab0c8459781fa77087f856c3e740d7763be0df27f", size = 796979, upload-time = "2026-04-03T20:55:22.56Z" }, - { url = "https://files.pythonhosted.org/packages/c9/e3/a016c12675fbac988a60c7e1c16e67823ff0bc016beb27bd7a001dbdabc6/regex-2026.4.4-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:2e19e18c568d2866d8b6a6dfad823db86193503f90823a8f66689315ba28fbe8", size = 866744, upload-time = "2026-04-03T20:55:24.646Z" }, - { url = "https://files.pythonhosted.org/packages/af/a4/0b90ca4cf17adc3cb43de80ec71018c37c88ad64987e8d0d481a95ca60b5/regex-2026.4.4-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:7698a6f38730fd1385d390d1ed07bb13dce39aa616aca6a6d89bea178464b9a4", size = 911613, upload-time = "2026-04-03T20:55:27.033Z" }, - { url = "https://files.pythonhosted.org/packages/8e/3b/2b3dac0b82d41ab43aa87c6ecde63d71189d03fe8854b8ca455a315edac3/regex-2026.4.4-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:173a66f3651cdb761018078e2d9487f4cf971232c990035ec0eb1cdc6bf929a9", size = 800551, upload-time = "2026-04-03T20:55:29.532Z" }, - { url = "https://files.pythonhosted.org/packages/25/fe/5365eb7aa0e753c4b5957815c321519ecab033c279c60e1b1ae2367fa810/regex-2026.4.4-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:fa7922bbb2cc84fa062d37723f199d4c0cd200245ce269c05db82d904db66b83", size = 776911, upload-time = "2026-04-03T20:55:31.526Z" }, - { url = "https://files.pythonhosted.org/packages/aa/b3/7fb0072156bba065e3b778a7bc7b0a6328212be5dd6a86fd207e0c4f2dab/regex-2026.4.4-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:59f67cd0a0acaf0e564c20bbd7f767286f23e91e2572c5703bf3e56ea7557edb", size = 785751, upload-time = "2026-04-03T20:55:33.797Z" }, - { url = "https://files.pythonhosted.org/packages/02/1a/9f83677eb699273e56e858f7bd95acdbee376d42f59e8bfca2fd80d79df3/regex-2026.4.4-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:475e50f3f73f73614f7cba5524d6de49dee269df00272a1b85e3d19f6d498465", size = 860484, upload-time = "2026-04-03T20:55:35.745Z" }, - { url = "https://files.pythonhosted.org/packages/3b/7a/93937507b61cfcff8b4c5857f1b452852b09f741daa9acae15c971d8554e/regex-2026.4.4-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:a1c0c7d67b64d85ac2e1879923bad2f08a08f3004055f2f406ef73c850114bd4", size = 765939, upload-time = "2026-04-03T20:55:37.972Z" }, - { url = "https://files.pythonhosted.org/packages/86/ea/81a7f968a351c6552b1670ead861e2a385be730ee28402233020c67f9e0f/regex-2026.4.4-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:1371c2ccbb744d66ee63631cc9ca12aa233d5749972626b68fe1a649dd98e566", size = 851417, upload-time = "2026-04-03T20:55:39.92Z" }, - { url = "https://files.pythonhosted.org/packages/4c/7e/323c18ce4b5b8f44517a36342961a0306e931e499febbd876bb149d900f0/regex-2026.4.4-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:59968142787042db793348a3f5b918cf24ced1f23247328530e063f89c128a95", size = 789056, upload-time = "2026-04-03T20:55:42.303Z" }, - { url = "https://files.pythonhosted.org/packages/c0/af/e7510f9b11b1913b0cd44eddb784b2d650b2af6515bfce4cffcc5bfd1d38/regex-2026.4.4-cp314-cp314-win32.whl", hash = "sha256:59efe72d37fd5a91e373e5146f187f921f365f4abc1249a5ab446a60f30dd5f8", size = 272130, upload-time = "2026-04-03T20:55:44.995Z" }, - { url = "https://files.pythonhosted.org/packages/9a/51/57dae534c915e2d3a21490e88836fa2ae79dde3b66255ecc0c0a155d2c10/regex-2026.4.4-cp314-cp314-win_amd64.whl", hash = "sha256:e0aab3ff447845049d676827d2ff714aab4f73f340e155b7de7458cf53baa5a4", size = 280992, upload-time = "2026-04-03T20:55:47.316Z" }, - { url = "https://files.pythonhosted.org/packages/0a/5e/abaf9f4c3792e34edb1434f06717fae2b07888d85cb5cec29f9204931bf8/regex-2026.4.4-cp314-cp314-win_arm64.whl", hash = "sha256:a7a5bb6aa0cf62208bb4fa079b0c756734f8ad0e333b425732e8609bd51ee22f", size = 273563, upload-time = "2026-04-03T20:55:49.273Z" }, - { url = "https://files.pythonhosted.org/packages/ff/06/35da85f9f217b9538b99cbb170738993bcc3b23784322decb77619f11502/regex-2026.4.4-cp314-cp314t-macosx_10_13_universal2.whl", hash = "sha256:97850d0638391bdc7d35dc1c1039974dcb921eaafa8cc935ae4d7f272b1d60b3", size = 494191, upload-time = "2026-04-03T20:55:51.258Z" }, - { url = "https://files.pythonhosted.org/packages/54/5b/1bc35f479eef8285c4baf88d8c002023efdeebb7b44a8735b36195486ae7/regex-2026.4.4-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:ee7337f88f2a580679f7bbfe69dc86c043954f9f9c541012f49abc554a962f2e", size = 293877, upload-time = "2026-04-03T20:55:53.214Z" }, - { url = "https://files.pythonhosted.org/packages/39/5b/f53b9ad17480b3ddd14c90da04bfb55ac6894b129e5dea87bcaf7d00e336/regex-2026.4.4-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:7429f4e6192c11d659900c0648ba8776243bf396ab95558b8c51a345afeddde6", size = 292410, upload-time = "2026-04-03T20:55:55.736Z" }, - { url = "https://files.pythonhosted.org/packages/bb/56/52377f59f60a7c51aa4161eecf0b6032c20b461805aca051250da435ffc9/regex-2026.4.4-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:dc4f10fbd5dd13dcf4265b4cc07d69ca70280742870c97ae10093e3d66000359", size = 811831, upload-time = "2026-04-03T20:55:57.802Z" }, - { url = "https://files.pythonhosted.org/packages/dd/63/8026310bf066f702a9c361f83a8c9658f3fe4edb349f9c1e5d5273b7c40c/regex-2026.4.4-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:a152560af4f9742b96f3827090f866eeec5becd4765c8e0d3473d9d280e76a5a", size = 871199, upload-time = "2026-04-03T20:56:00.333Z" }, - { url = "https://files.pythonhosted.org/packages/20/9f/a514bbb00a466dbb506d43f187a04047f7be1505f10a9a15615ead5080ee/regex-2026.4.4-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:54170b3e95339f415d54651f97df3bff7434a663912f9358237941bbf9143f55", size = 917649, upload-time = "2026-04-03T20:56:02.445Z" }, - { url = "https://files.pythonhosted.org/packages/cb/6b/8399f68dd41a2030218839b9b18360d79b86d22b9fab5ef477c7f23ca67c/regex-2026.4.4-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:07f190d65f5a72dcb9cf7106bfc3d21e7a49dd2879eda2207b683f32165e4d99", size = 816388, upload-time = "2026-04-03T20:56:04.595Z" }, - { url = "https://files.pythonhosted.org/packages/1e/9c/103963f47c24339a483b05edd568594c2be486188f688c0170fd504b2948/regex-2026.4.4-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:9a2741ce5a29d3c84b0b94261ba630ab459a1b847a0d6beca7d62d188175c790", size = 785746, upload-time = "2026-04-03T20:56:07.13Z" }, - { url = "https://files.pythonhosted.org/packages/fa/ee/7f6054c0dec0cee3463c304405e4ff42e27cff05bf36fcb34be549ab17bd/regex-2026.4.4-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:b26c30df3a28fd9793113dac7385a4deb7294a06c0f760dd2b008bd49a9139bc", size = 801483, upload-time = "2026-04-03T20:56:09.365Z" }, - { url = "https://files.pythonhosted.org/packages/30/c2/51d3d941cf6070dc00c3338ecf138615fc3cce0421c3df6abe97a08af61a/regex-2026.4.4-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:421439d1bee44b19f4583ccf42670ca464ffb90e9fdc38d37f39d1ddd1e44f1f", size = 866331, upload-time = "2026-04-03T20:56:12.039Z" }, - { url = "https://files.pythonhosted.org/packages/16/e8/76d50dcc122ac33927d939f350eebcfe3dbcbda96913e03433fc36de5e63/regex-2026.4.4-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:b40379b53ecbc747fd9bdf4a0ea14eb8188ca1bd0f54f78893a39024b28f4863", size = 772673, upload-time = "2026-04-03T20:56:14.558Z" }, - { url = "https://files.pythonhosted.org/packages/a5/6e/5f6bf75e20ea6873d05ba4ec78378c375cbe08cdec571c83fbb01606e563/regex-2026.4.4-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:08c55c13d2eef54f73eeadc33146fb0baaa49e7335eb1aff6ae1324bf0ddbe4a", size = 857146, upload-time = "2026-04-03T20:56:16.663Z" }, - { url = "https://files.pythonhosted.org/packages/0b/33/3c76d9962949e487ebba353a18e89399f292287204ac8f2f4cfc3a51c233/regex-2026.4.4-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:9776b85f510062f5a75ef112afe5f494ef1635607bf1cc220c1391e9ac2f5e81", size = 803463, upload-time = "2026-04-03T20:56:18.923Z" }, - { url = "https://files.pythonhosted.org/packages/19/eb/ef32dcd2cb69b69bc0c3e55205bce94a7def48d495358946bc42186dcccc/regex-2026.4.4-cp314-cp314t-win32.whl", hash = "sha256:385edaebde5db5be103577afc8699fea73a0e36a734ba24870be7ffa61119d74", size = 275709, upload-time = "2026-04-03T20:56:20.996Z" }, - { url = "https://files.pythonhosted.org/packages/a0/86/c291bf740945acbf35ed7dbebf8e2eea2f3f78041f6bd7cdab80cb274dc0/regex-2026.4.4-cp314-cp314t-win_amd64.whl", hash = "sha256:5d354b18839328927832e2fa5f7c95b7a3ccc39e7a681529e1685898e6436d45", size = 285622, upload-time = "2026-04-03T20:56:23.641Z" }, - { url = "https://files.pythonhosted.org/packages/d5/e7/ec846d560ae6a597115153c02ca6138a7877a1748b2072d9521c10a93e58/regex-2026.4.4-cp314-cp314t-win_arm64.whl", hash = "sha256:af0384cb01a33600c49505c27c6c57ab0b27bf84a74e28524c92ca897ebdac9d", size = 275773, upload-time = "2026-04-03T20:56:26.07Z" }, +version = "2026.5.9" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/dc/0e/49aee608ad09480e7fd276898c99ec6192985fa331abe4eb3a986094490b/regex-2026.5.9.tar.gz", hash = "sha256:a8234aa23ec39894bfe4a3f1b85616a7032481964a13ac6fc9f10de4f6fca270", size = 416074, upload-time = "2026-05-09T23:15:19.37Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/fe/ed/0ad2c8edf634918eb4484365d3819fa7bd7f58daf807fe7fb21812c316e5/regex-2026.5.9-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:a9e1328e17c84c1a5d22ec9f785ecef4a967fab9a42b6a8dc3bcbebd0a0c9e44", size = 489438, upload-time = "2026-05-09T23:11:29.374Z" }, + { url = "https://files.pythonhosted.org/packages/89/a9/4ed972ad263963b860b7c3e86e0e1bcc791def47b43b8c8efe57e710f139/regex-2026.5.9-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:bfe1ce50cbfb569d74e1e4337da6468961f31dbea55fd85aa5de59c0947a805a", size = 291270, upload-time = "2026-05-09T23:11:33.254Z" }, + { url = "https://files.pythonhosted.org/packages/16/81/075930d9fa28c4ea1f53398dd015ee7c882f623539759113cda1257f4b82/regex-2026.5.9-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:15ee42209947f4ca045412eae98416317238163618ace2a8e54f99586a466733", size = 289198, upload-time = "2026-05-09T23:11:35.769Z" }, + { url = "https://files.pythonhosted.org/packages/d4/c8/5cdfbf0b5dc6599e1b6131eff43262e5275d4ec3469ce10216061659aadb/regex-2026.5.9-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b4bb445ff3f725f59df8f6014edb547ee928ec7023a774f6a39a3f953038cbb2", size = 784765, upload-time = "2026-05-09T23:11:37.689Z" }, + { url = "https://files.pythonhosted.org/packages/cd/ca/ae5fd6edc59b7f84b904b31d6ec39a860cbcecd10f64bd5a062ca83a4864/regex-2026.5.9-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:446ddd671e43ab535810c4b21cff7104945c701d4a14d1e6d1cd6f4e445a8bea", size = 852115, upload-time = "2026-05-09T23:11:39.973Z" }, + { url = "https://files.pythonhosted.org/packages/f6/ce/a91cf555afb51f3b74a182e24ba073b91ea7bb64592fc4b315c111bb19fd/regex-2026.5.9-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:7b92817338591505f282cf3864c145244b1edcf5381d237038df955001091538", size = 899503, upload-time = "2026-05-09T23:11:42.48Z" }, + { url = "https://files.pythonhosted.org/packages/55/7f/725a0a2b245a4cf0c4bab29d0e97c74285d94136a65d1b55a6459a583502/regex-2026.5.9-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d6b8a143aca6c39b446ea8092cde25cc8fe9304d4f5fecfbc1a9dbb0282703c2", size = 794093, upload-time = "2026-05-09T23:11:44.681Z" }, + { url = "https://files.pythonhosted.org/packages/e3/2a/996efbd59ce6b5d4a09e3af6180ceb62af171f4a9a6fb557d2f0ae0d462b/regex-2026.5.9-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:0f03aa6898aaaac4592479821df16e68e8d0e29e903e65d8f2dfb2f19028a989", size = 786234, upload-time = "2026-05-09T23:11:46.882Z" }, + { url = "https://files.pythonhosted.org/packages/4b/0a/8731e8b8806174c9cdd5903f80a14990331c1f42fc4209b540952e9e010d/regex-2026.5.9-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:ed457d8e98ae812ed7732bef7bf78de78e834eae0372a74e23ca90ef21d910f9", size = 769895, upload-time = "2026-05-09T23:11:49.324Z" }, + { url = "https://files.pythonhosted.org/packages/9a/0b/932473194bd563f342a412ae2ffbbd6da608306a2bc4e99249a41c2b0b92/regex-2026.5.9-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:71b61c5bfe1c806332defc42ad6c780b3c55f661986d7f40283a3a88274b4c00", size = 774991, upload-time = "2026-05-09T23:11:51.261Z" }, + { url = "https://files.pythonhosted.org/packages/98/80/9523d196010031df25f7177ee0a467efbee436324038e5d99def17a57515/regex-2026.5.9-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:3b1e39888c5e0c7d92cea4fc777396c4a90363b05de75d02eb459a4752200808", size = 848790, upload-time = "2026-05-09T23:11:53.232Z" }, + { url = "https://files.pythonhosted.org/packages/3c/07/56987b35e89edf47e4a38cf2845aeee476bfa688a6bdbd3e820cda461dc1/regex-2026.5.9-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:6ba42b2e7e7f46cf68cc6a5ca36fa07959f9bbd9c6bdcc47b6ee76549a590248", size = 757679, upload-time = "2026-05-09T23:11:55.82Z" }, + { url = "https://files.pythonhosted.org/packages/04/2a/ff713fff0c566507c06a4ce2dc0ae8e7eeebc88811a95fc81cf1e7d534dd/regex-2026.5.9-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:c010eb8caca74bdb40c07498d7ece26b4428fd3f04aa8a72c9ac6f79e8faaac6", size = 837116, upload-time = "2026-05-09T23:11:57.934Z" }, + { url = "https://files.pythonhosted.org/packages/77/90/df6d982b03e3614785c6937ba51b57f6733d97d2ee1c9bc7531dbfab3a54/regex-2026.5.9-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:a6a563446a41adc451393dc6b8e6ad87979efaee3c8738690a8d1b08ebead1b4", size = 782081, upload-time = "2026-05-09T23:11:59.607Z" }, + { url = "https://files.pythonhosted.org/packages/c7/8a/4e88a5f7c3e98489aac4dd23142723d907b2a595b4a6abcbacabefeded09/regex-2026.5.9-cp310-cp310-win32.whl", hash = "sha256:954cc214c04663ee6d266fc61739cad83054683048de65c5bd1d640ad28098ac", size = 266247, upload-time = "2026-05-09T23:12:01.116Z" }, + { url = "https://files.pythonhosted.org/packages/6a/40/4b224cb0582b2dca1786726e6cdabe26abbf757d7f6718332f186da155d2/regex-2026.5.9-cp310-cp310-win_amd64.whl", hash = "sha256:b310768746dd314ea6e2ff4cc89ef215426813396ff4e94ee8e6f7096c8b6e03", size = 278416, upload-time = "2026-05-09T23:12:03.2Z" }, + { url = "https://files.pythonhosted.org/packages/12/4d/014fbe803204cab0947ee428f09f658a29632053dde1d3c6176bb4f0fd4c/regex-2026.5.9-cp310-cp310-win_arm64.whl", hash = "sha256:19c16ceb4a267a8789e25733e583983eeab9f0f8664e66b0bd1c5d21f14c2d4b", size = 270413, upload-time = "2026-05-09T23:12:04.649Z" }, + { url = "https://files.pythonhosted.org/packages/c2/dc/c1f2df4027e82fc54b5a473e4b250f5139faca49a0fbe29a48668d228f34/regex-2026.5.9-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:ccf5249114cc3e772ecdd88a98a86eca0fd74c61ce32a94743758c083fc05d48", size = 489445, upload-time = "2026-05-09T23:12:06.111Z" }, + { url = "https://files.pythonhosted.org/packages/03/d2/59f01110660081cce9c0bc30ebd0b5ee250dacf658e3248ed92f01e0e8ee/regex-2026.5.9-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:46f1326ca6e65b0879d23ca302c0f2415aad42ff0309b9c818e7949fe19a41d8", size = 291271, upload-time = "2026-05-09T23:12:07.731Z" }, + { url = "https://files.pythonhosted.org/packages/58/b6/14b2c84ff90ddb370c81d27503f4a0fcf071496416f4855f6cc8c5d81c35/regex-2026.5.9-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:ef31cbfe458e21c6122ba8150ff060e0c7789ed0d26eb423f25472584920b555", size = 289212, upload-time = "2026-05-09T23:12:09.266Z" }, + { url = "https://files.pythonhosted.org/packages/03/d0/4db86529117320de0c84afd90e70bb47434625875e34fcef9d8c127c5b16/regex-2026.5.9-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:992604d02e6d9c6d786c24a706a71ecffe1020fc1ef264044474cd81fa2c3919", size = 792310, upload-time = "2026-05-09T23:12:11.416Z" }, + { url = "https://files.pythonhosted.org/packages/07/78/fe4800cd322f862ecffd2d553409b20d80650e5ed71b9d178f853d020b82/regex-2026.5.9-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:c9411dd64ca95477225734a93dfc8583b51916b8d5942f99d6cac21e09965451", size = 861721, upload-time = "2026-05-09T23:12:13.681Z" }, + { url = "https://files.pythonhosted.org/packages/b5/d0/b3618a895dd8feb897c61bb2954edd265e1767d82a01d53065d5871127a3/regex-2026.5.9-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:3dd4a3ff360dfb836fecdb93a4598f9d6e2ac81e3e397125145c6221bf58cf4c", size = 906460, upload-time = "2026-05-09T23:12:15.443Z" }, + { url = "https://files.pythonhosted.org/packages/33/6f/1481597e859ef19508b345eec4afd1416ed6e6b459c75a64026ef193aecf/regex-2026.5.9-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:2a661a7d270a61f7cf460caee8b9fa2d5ef9e5c681234bcb9e0fe14f488e7dfc", size = 799843, upload-time = "2026-05-09T23:12:16.892Z" }, + { url = "https://files.pythonhosted.org/packages/73/59/955734c803f59108deccba3597ae440c76b62a652733c0006e6243758420/regex-2026.5.9-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:f079e50a0d3cc3cd5091fa9ff45869a2e6b2cd35895731edafb0327901a8d86d", size = 773610, upload-time = "2026-05-09T23:12:19.127Z" }, + { url = "https://files.pythonhosted.org/packages/68/8f/70c04a236d651c81881dac42ef8538bddda6121434509d0a22d9e601503b/regex-2026.5.9-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:4ebe8f0b5ec5a5024dc4a4c59f444c4e9afc5f2abdbb8962065b75d27fb971f9", size = 781645, upload-time = "2026-05-09T23:12:20.806Z" }, + { url = "https://files.pythonhosted.org/packages/1d/96/05c7434d88185e5d27fe54aeb74df86bd77cd79f52f0b4eae54faa8fea70/regex-2026.5.9-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:97cf3bc1b7d7d2306772ec07366c80d9df00ff79e79cea32898883a646d2fae2", size = 854473, upload-time = "2026-05-09T23:12:22.465Z" }, + { url = "https://files.pythonhosted.org/packages/4e/c1/6e3d8202d981f3117004bf341ee74893ba4ba8a9fbaf4b94615846550a08/regex-2026.5.9-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:0f9eede6a5cbdc02d4978090186390936e1776a7d1359b21e41014c609880bcf", size = 763311, upload-time = "2026-05-09T23:12:24.351Z" }, + { url = "https://files.pythonhosted.org/packages/93/c7/e7737f1526b3fb32bd4c337fd6c71c3ebb5c8296fc34d11197e0955d2e35/regex-2026.5.9-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:01f0f5f55f4b64dacec85dc116d3c05fd23ad3ff037bbc73a2085775953c2611", size = 844593, upload-time = "2026-05-09T23:12:26.341Z" }, + { url = "https://files.pythonhosted.org/packages/a5/27/0daffb1a535bb39f422c3d200f4ab023c71110ad66a32b366bee708baba0/regex-2026.5.9-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:1268eddd8486dc561d08eee1156e40aa3a8fe10f4bdec8fa653b455fcbffd12c", size = 789167, upload-time = "2026-05-09T23:12:27.975Z" }, + { url = "https://files.pythonhosted.org/packages/ce/fc/294fe4fac4f2ed67207b17471815870c1c45b3a489e08e0ac96daea16ef6/regex-2026.5.9-cp311-cp311-win32.whl", hash = "sha256:8676474c07469d6f33dd1085ca2cd45f65785f32518f2b20e36d9953ca07f994", size = 266249, upload-time = "2026-05-09T23:12:30.141Z" }, + { url = "https://files.pythonhosted.org/packages/d0/b0/8dce459f6245bcf8f6e9f23ac9569f1a0f15c131cc0745e82b43226204cf/regex-2026.5.9-cp311-cp311-win_amd64.whl", hash = "sha256:246de9d60aa3f8538b519834dd95cbf276ea263d6a7bd5a3666dc3fa0230505b", size = 278423, upload-time = "2026-05-09T23:12:31.676Z" }, + { url = "https://files.pythonhosted.org/packages/db/8d/f9aeff6ad63a3ef720386f2907e6d34a35a510a6e498ebad28b0fb3f6ab6/regex-2026.5.9-cp311-cp311-win_arm64.whl", hash = "sha256:d726ca3f0d76969bf1e8e477d160d3d666bbf999f6860bd314889e5345782046", size = 270420, upload-time = "2026-05-09T23:12:33.194Z" }, + { url = "https://files.pythonhosted.org/packages/50/9b/6550044bc44e17c84d312c031c2ec42fbdb6a4ec4e29093be3a172d08772/regex-2026.5.9-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:57eeeb05db7979413dec5438f2db21d7ecbba787cde7a711df1a6f6df672aa06", size = 490451, upload-time = "2026-05-09T23:12:34.72Z" }, + { url = "https://files.pythonhosted.org/packages/1e/95/fc7ba4303b5a0f92446a12ee6778ef2c6c799233f5060042a31bf390cfe9/regex-2026.5.9-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:398c521292f4c7fb807001dcd54694d3a1fcafc179a36ad9cc56f98df85930b6", size = 292112, upload-time = "2026-05-09T23:12:36.285Z" }, + { url = "https://files.pythonhosted.org/packages/54/4b/ee27938d1b2c443e89a9a10e00d2d19aa5ee300cd3d61140644e93bb083e/regex-2026.5.9-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:f7a7c26137296beba7784de6eba69c6a93a63ccebc385e4962fe67e267a91225", size = 289599, upload-time = "2026-05-09T23:12:38.089Z" }, + { url = "https://files.pythonhosted.org/packages/d8/dd/ba103dc19614e25f3880800ca67ce093d6e21b325d72b8383c7bf906e9fa/regex-2026.5.9-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6441cc660d76107934a09c22167200839a0e89604a6297f78a974e66e931d2c0", size = 796732, upload-time = "2026-05-09T23:12:40.062Z" }, + { url = "https://files.pythonhosted.org/packages/cf/e7/f035b4fd858b050b0080bf302968dc0f59ba34e391872d54936758e6844e/regex-2026.5.9-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:91328f1c23d47595ca3ef0a7557fa129c5a23404b775c770697d2f35b33e0107", size = 865440, upload-time = "2026-05-09T23:12:42.059Z" }, + { url = "https://files.pythonhosted.org/packages/0a/51/8cd301ecc899aea28124357f729f4272f44de7806fc7ca02490bfbe253e8/regex-2026.5.9-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:93a7860539414dddaefba2b40f8771765ae17949d4c7182b876ce429e11a8309", size = 912329, upload-time = "2026-05-09T23:12:44.373Z" }, + { url = "https://files.pythonhosted.org/packages/cc/1e/3fbe2fa1e8cebd62f3bb7d3321cff1640aca2e240b51d9bd624aad949260/regex-2026.5.9-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:dd2810d22146b6d838acc5ec15602cb6b47920aa4e33015df3868eedfd20bab8", size = 801239, upload-time = "2026-05-09T23:12:46.268Z" }, + { url = "https://files.pythonhosted.org/packages/17/2f/6f6008682bf2cf98040a0d3153a8e557b6ab728d7713d045cee4ce544ab8/regex-2026.5.9-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:daff2bdbaf1d23e52fdff7c0b7bc2048b68f978df6a4d107ac981f94caef2e66", size = 777054, upload-time = "2026-05-09T23:12:48.051Z" }, + { url = "https://files.pythonhosted.org/packages/19/2b/eee0d20a6842ba04df4b8847a920b57ef56853f14ef85405473e586b605a/regex-2026.5.9-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:4eeb011098fcb77af513dcef521a3dbecbf8849b1e38940759d293b7a93f5026", size = 785098, upload-time = "2026-05-09T23:12:49.851Z" }, + { url = "https://files.pythonhosted.org/packages/4a/98/6fc1e6410feefb92159edaed5041992bfe390e8d26c721865434acbca558/regex-2026.5.9-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:ea9c8ecfa1b73c73b626534d6626e5340d429630943672b8480724f44e84b962", size = 860095, upload-time = "2026-05-09T23:12:51.666Z" }, + { url = "https://files.pythonhosted.org/packages/18/a3/bd855e0f2cb1a978ecf6fa6bb69632dd9c3f6ea3b81cde62fde14c9daec7/regex-2026.5.9-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:cd2846168eb9ee3c513902bc8225409cb1caab31d04728b145171fa1625d9621", size = 765762, upload-time = "2026-05-09T23:12:53.413Z" }, + { url = "https://files.pythonhosted.org/packages/dc/66/0ae8c092e60b14c79d24f8e0b7f0aea5bfbffdcab00b5483d13404d3c3a5/regex-2026.5.9-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:39617fb0cde9c0e6306dc70e3bfc096f3da793219879f7ae7aa341a69fbdcf6d", size = 852100, upload-time = "2026-05-09T23:12:55.256Z" }, + { url = "https://files.pythonhosted.org/packages/21/de/8dfde60fc1b21c946a893ba273403b72617edb261370cb1087099a83f088/regex-2026.5.9-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:fd03c4f0e33280d15cae17159b899245d6b7c53d21def19b263b39655061f5ce", size = 789479, upload-time = "2026-05-09T23:12:57.573Z" }, + { url = "https://files.pythonhosted.org/packages/c3/1c/bdcc98f9a4af4fdd166c74941174619ccff4726d3ce32faa8e9a2ecd38dd/regex-2026.5.9-cp312-cp312-win32.whl", hash = "sha256:164eba9b755ea6f244b0d881196fbc1fac09714e9782c9e2732b813142033c8e", size = 266699, upload-time = "2026-05-09T23:12:59.14Z" }, + { url = "https://files.pythonhosted.org/packages/78/87/240d36864f9e48ace85f72e79ced97ceb7f27ce87739a947dcb834b4e6bc/regex-2026.5.9-cp312-cp312-win_amd64.whl", hash = "sha256:86f40a5d6444db30a125c9c9177e6b25dad981cbc37451fd838f145e6edac92e", size = 277783, upload-time = "2026-05-09T23:13:00.789Z" }, + { url = "https://files.pythonhosted.org/packages/4f/b5/7b30f312b0669dff5beebe5b0989dc2d1a312b1a44fab852199c387a5b96/regex-2026.5.9-cp312-cp312-win_arm64.whl", hash = "sha256:96f5f58b54a063d7ea9dca08e1cf57bfe10499c4d579ee672da284f57f5f0070", size = 270513, upload-time = "2026-05-09T23:13:02.426Z" }, + { url = "https://files.pythonhosted.org/packages/aa/da/797e91ecec6f84135da778ddce78c20e0af5d2a15c26f87a81bc3eadb6db/regex-2026.5.9-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:d626b84406444b165fc0ba981604edea39f0588ff1f92baa23fe50799ea9afdb", size = 490303, upload-time = "2026-05-09T23:13:04.382Z" }, + { url = "https://files.pythonhosted.org/packages/44/da/bf30abaaa737b58f4a4b8c4a03659e02fd92092c822e0197ed9e0daab917/regex-2026.5.9-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:d7bdc0ab8f3dd7e1b4f9ab88634e13374669db86bb3c72e8292f07ae313f539f", size = 292019, upload-time = "2026-05-09T23:13:06.022Z" }, + { url = "https://files.pythonhosted.org/packages/2d/e7/d0eaf5713828417b9e5648cf81fa9bacd4961f6ab98c380c2034f8716e35/regex-2026.5.9-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:a8820737949116ffff55fe18f9fc644530063ba6ebfcb8314239416e78f1347c", size = 289468, upload-time = "2026-05-09T23:13:08.214Z" }, + { url = "https://files.pythonhosted.org/packages/d3/9b/b3fdd62b003baa1a9b593cd8c8699c9651c2e80cc21a5c715707983c42d7/regex-2026.5.9-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:aa0fbdbac82cb3e4450d0ccde7d7a35607f4cb2dd9fba4b8b69bfaf8c9fa6aed", size = 796749, upload-time = "2026-05-09T23:13:10.573Z" }, + { url = "https://files.pythonhosted.org/packages/d4/30/66ab84588765f5b4b271a9ca09ef7ce2b87caa95176ec3d2ad65d7bc4902/regex-2026.5.9-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:57e8915c7986aa33d25e4d3629cef711cd2863f2961b10409f0c04cb8b7d9020", size = 865445, upload-time = "2026-05-09T23:13:12.523Z" }, + { url = "https://files.pythonhosted.org/packages/1a/89/f05169e8588aac365f35ffc7f3bc3184f095ef4cfded7cfaa3c7fd5dbd89/regex-2026.5.9-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:508f56a89ba9cb26e4168cbc37dbd60a28d82430a9e18ad1d25fe0883c314ca2", size = 912322, upload-time = "2026-05-09T23:13:14.281Z" }, + { url = "https://files.pythonhosted.org/packages/30/e1/c93444052cf41581f3c884ab3fb5823daf0992f11cd4388d4275ca610558/regex-2026.5.9-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b6d189041f15691cfa2b6c4290448ec221244d225b3f5fe9e7771b34ffcdf6e2", size = 801269, upload-time = "2026-05-09T23:13:16.569Z" }, + { url = "https://files.pythonhosted.org/packages/50/fe/0cf96b882f540e62e8b9956599798203d599c44cf4c77917ca27400ff69b/regex-2026.5.9-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:e82db382b44d0111b22601c509c89f64434816c9e0eef9d1989cda8cc6ff1c04", size = 777085, upload-time = "2026-05-09T23:13:18.675Z" }, + { url = "https://files.pythonhosted.org/packages/23/5c/d78d4924e7fc875557b9e9b768423925fdfaac5549d06da7810019a9bd26/regex-2026.5.9-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:2acfb48634f64996b57f90f39afa692ff362162722581921fe92239a59960f3c", size = 785153, upload-time = "2026-05-09T23:13:20.525Z" }, + { url = "https://files.pythonhosted.org/packages/bf/e0/5214774090e7b4524dcea3e3c4aa74141d43043f8beb49c1599db1c8b53a/regex-2026.5.9-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:d29eebfc9525db68cad3c97eedd7f754fa265aa5cd0cf4f863b2421e1b48fc9f", size = 860164, upload-time = "2026-05-09T23:13:22.263Z" }, + { url = "https://files.pythonhosted.org/packages/6e/e1/4a57a83350319b1271f0d7a249b8672513ed928b237a741631270de6caea/regex-2026.5.9-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:debb893095e944091c16e641a6e33c1b0f4cb61ab945ec5afbf53ce7068834d8", size = 765731, upload-time = "2026-05-09T23:13:24.277Z" }, + { url = "https://files.pythonhosted.org/packages/12/f4/499e74a20c156fc75836ee04a72a38d1a063978f600937f9760467beb1b0/regex-2026.5.9-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:d659eee77986549c9ea45b861c7567e44d6287c3dc9a4565478853f7b9fe2ff6", size = 852062, upload-time = "2026-05-09T23:13:26.125Z" }, + { url = "https://files.pythonhosted.org/packages/5b/92/7eebc0d0a01e78629695f342ba17e0deaff8fb45e79cc0d7b98287da6e3e/regex-2026.5.9-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:2efa205e6d98b24d1f3ab395c11aa15cdf10935bca283d0285e0499c284fba21", size = 789577, upload-time = "2026-05-09T23:13:27.814Z" }, + { url = "https://files.pythonhosted.org/packages/05/a4/018e71f7d2ad48c1ebe6d3ae0026f9b7cb4802fd15c7cc02fdf724355102/regex-2026.5.9-cp313-cp313-win32.whl", hash = "sha256:f3844f134e834076677dd369976e9f5068679fcb8e50102fdf6b7ac96a3ec127", size = 266691, upload-time = "2026-05-09T23:13:29.549Z" }, + { url = "https://files.pythonhosted.org/packages/e6/1d/861a93719fb9ee7dbfc3761b3797b7a3e112a5d42c6129459d2d741be9b5/regex-2026.5.9-cp313-cp313-win_amd64.whl", hash = "sha256:3527bb4942d2c14552155406cdedd906567456821848aed1cb4933a391bf5eca", size = 277747, upload-time = "2026-05-09T23:13:31.859Z" }, + { url = "https://files.pythonhosted.org/packages/d9/c6/0a2436ae4da1ba76e51cb98943c6838a9a721faa40ebe2dce07694ae34e3/regex-2026.5.9-cp313-cp313-win_arm64.whl", hash = "sha256:56a33f191f17d8c417f99945ebdc1e691d3af9605d86ec68c7e54a57e3e17af6", size = 270500, upload-time = "2026-05-09T23:13:33.525Z" }, + { url = "https://files.pythonhosted.org/packages/e8/e9/d21346f7b60ed58789371358ed66b09d00f832e1bd7c06e55d9da5679882/regex-2026.5.9-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:01f28d868834624c934b8d2e0aa1c8341337e37831f4a012f18a5afcba4cbaf3", size = 494172, upload-time = "2026-05-09T23:13:35.935Z" }, + { url = "https://files.pythonhosted.org/packages/c4/43/fd1177a2032037c681baecdb3422ee4e1424aec4e4f470ef47793d325274/regex-2026.5.9-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:48036f6374aaa79eb3b754ec29c61d1c6b1606749d705a13f8854fa2539671f6", size = 293952, upload-time = "2026-05-09T23:13:38.307Z" }, + { url = "https://files.pythonhosted.org/packages/f2/7d/9fbf919768368d3f8a4f6c692cf2aa61e482b2b81ec6a298ace4cbf02480/regex-2026.5.9-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:b96350aa424e79d4fd6b567b344dcbe2b2d6bfc48dfe7717587e1fa6d43da6ff", size = 292314, upload-time = "2026-05-09T23:13:40.353Z" }, + { url = "https://files.pythonhosted.org/packages/e2/6c/e41bfeecb589716843e7c4df09ba46ff2a42961457afece19059d85caeef/regex-2026.5.9-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8f3af7a4903c5c04a11a196a5aa75cdd7dd3f8508132f9fb3259d9f5908e3b88", size = 811681, upload-time = "2026-05-09T23:13:42.543Z" }, + { url = "https://files.pythonhosted.org/packages/87/83/a5c1c525fba0aa656e88ad0face0b1829788ef4c2fb6b26df58aa1151b84/regex-2026.5.9-cp313-cp313t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:7e87577720152d2caae19fe2baaf1f8d5ca12091e9e229f03915c37d1e4b9178", size = 871135, upload-time = "2026-05-09T23:13:44.326Z" }, + { url = "https://files.pythonhosted.org/packages/18/d4/80882e799e440dd878b0979cbebf8fa4d54624a332c83037c7a701649e3f/regex-2026.5.9-cp313-cp313t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:c8b9b9d294cfea3cd19c718ade7cc93492b2c4991abd9a68d0b3477ae6d8e100", size = 917265, upload-time = "2026-05-09T23:13:47.295Z" }, + { url = "https://files.pythonhosted.org/packages/ae/ff/8db60211e2286e396aad7dc7725356c502bff0901ea05bd6cdc2e1a042b9/regex-2026.5.9-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:728d8bfd28a8845c8b6bc5dc7ce010453d206396786c0765c2740cb65f37791e", size = 816311, upload-time = "2026-05-09T23:13:49.885Z" }, + { url = "https://files.pythonhosted.org/packages/4c/47/742ef579c61730f8d268e5cf1f9ce0e37e2ea041ad0f5644724f2378e463/regex-2026.5.9-cp313-cp313t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:7e30b874d341fac767d7df5a0870540541c2c054b80cfaac116e8d367a8a7ff2", size = 785498, upload-time = "2026-05-09T23:13:52.25Z" }, + { url = "https://files.pythonhosted.org/packages/7f/ab/cb0999802dcb0fb95b1ab005e8d4163d8afdd67efc2cb6b6630ac13f8cb1/regex-2026.5.9-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:fd190e88a895a8901325fad284a3f74ea52b1da8525b76cc811fa9b1edf0ce2b", size = 801348, upload-time = "2026-05-09T23:13:54.127Z" }, + { url = "https://files.pythonhosted.org/packages/7d/62/8ca59a24c55bc34d166eefaf3717bd77772f329fdbf984d86581e0a3571c/regex-2026.5.9-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:8e76e8161ad00694cfce6767d5dea860c6391ac5b83e5c3a39661e696f11fc7e", size = 866493, upload-time = "2026-05-09T23:13:56.067Z" }, + { url = "https://files.pythonhosted.org/packages/8d/3d/30f2ae62cef3278bb5bb821f467277a55fb73f01032cf85997e15e8289a8/regex-2026.5.9-cp313-cp313t-musllinux_1_2_riscv64.whl", hash = "sha256:ddda5340e6c01a293027dd46232fa79eaff1b48058ce7a98f572b6445b088041", size = 772811, upload-time = "2026-05-09T23:13:57.867Z" }, + { url = "https://files.pythonhosted.org/packages/d8/ae/7d2089bcd78ad0c0161bc684339df50032acb438a7bd3305e7ddb1193cec/regex-2026.5.9-cp313-cp313t-musllinux_1_2_s390x.whl", hash = "sha256:205109e96b3cf5adf8f4cd62bedde9487feb282b9497a3535451e5a24cd706a0", size = 856584, upload-time = "2026-05-09T23:13:59.679Z" }, + { url = "https://files.pythonhosted.org/packages/a9/29/92ff47f75990131ea4f24ba17819e5a9d141e10819807e09addd73409af6/regex-2026.5.9-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:dfbe4579b9f08036aa7d101d1835437a20783574ac66327e6b29b4018a138081", size = 803453, upload-time = "2026-05-09T23:14:01.978Z" }, + { url = "https://files.pythonhosted.org/packages/04/99/eff29f1037dcab36702c9ee5d6858cf1ce2336ea8ea2987f64245b99ea5e/regex-2026.5.9-cp313-cp313t-win32.whl", hash = "sha256:ed2c9e8068b614c574d8d30e543d617cf5379b0535d46f97ef00e904745a08b5", size = 269951, upload-time = "2026-05-09T23:14:03.661Z" }, + { url = "https://files.pythonhosted.org/packages/0e/9d/8870b8981d27b22cda77bb26a5ac7ebfa9c7d9e0dea195a834a82380e748/regex-2026.5.9-cp313-cp313t-win_amd64.whl", hash = "sha256:b46b0f094dc1d3b90356c85a0bd2c9bafc4a6a190b9d6f8ddd5a033b6e088ed4", size = 281240, upload-time = "2026-05-09T23:14:05.56Z" }, + { url = "https://files.pythonhosted.org/packages/72/b1/3379415e8f135c13ac551353397cc4fe97b4978f3cac73c5fcbcded548b8/regex-2026.5.9-cp313-cp313t-win_arm64.whl", hash = "sha256:872acc074bd29ffc9913ecdfedf6ea77502312ca44a4aa0d3779089c6069d8de", size = 272383, upload-time = "2026-05-09T23:14:07.843Z" }, + { url = "https://files.pythonhosted.org/packages/13/3e/9c3cd292d8808b3645a2ce517e200179b6d0e903f176300bd8b542e14de5/regex-2026.5.9-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:1bd7587a2948b4085195d5a3374eaf4a425dc3e55784c038175355ecf3bbbf8a", size = 490376, upload-time = "2026-05-09T23:14:09.64Z" }, + { url = "https://files.pythonhosted.org/packages/60/70/d43ee8a2ca0a8b68d167f21658b85520ac0574617c7f320367c5047f7556/regex-2026.5.9-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:dea2e88e1cce4522496cce630e11e67b98b7076620bc4336c3f674bc21a375f4", size = 291964, upload-time = "2026-05-09T23:14:11.424Z" }, + { url = "https://files.pythonhosted.org/packages/21/91/9d50b433828d8e74196904e168a43abf1e6e88b2a15d47ed742456720c37/regex-2026.5.9-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:2099f7e7ff7b6aa3192312650a56e91cc091e49d50b04e4f6f8b6e28b3b27f1c", size = 289682, upload-time = "2026-05-09T23:14:13.123Z" }, + { url = "https://files.pythonhosted.org/packages/3e/d2/b835e3cafbb9d977736912436259ff551d60919f7d7b3d37d46659c63564/regex-2026.5.9-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ecd353045824e4477562a2ac718c25799cdaaa41f7aa925a806a8a3e6848a5b9", size = 796996, upload-time = "2026-05-09T23:14:14.923Z" }, + { url = "https://files.pythonhosted.org/packages/2c/a6/9f992d00019166b9de01c546dd4549bc679f2a68df11b877740b0760b7c2/regex-2026.5.9-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:65c8c8c37377794bd5b2f3ebe51919042bf17aec802e23c833d89782ed0c78af", size = 866089, upload-time = "2026-05-09T23:14:17.757Z" }, + { url = "https://files.pythonhosted.org/packages/e0/08/4d32af657e049b19cb62b02e46e38fe1518797bfb2203ee93a510b21b0dc/regex-2026.5.9-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:5b73ab8afcf66c622db143d1c6fda4e58e4d537ee4f125229ad47b1ab80f34c0", size = 911530, upload-time = "2026-05-09T23:14:20.353Z" }, + { url = "https://files.pythonhosted.org/packages/d9/27/2af43dd1dc201d1fecefda64a45f4ad0995855b92724f795a777b402ee69/regex-2026.5.9-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0de5cf193997384ed2ca6f1cd4f78055b255d93d82d5a8cd6ba0d11c10b167e4", size = 800643, upload-time = "2026-05-09T23:14:22.265Z" }, + { url = "https://files.pythonhosted.org/packages/a4/dd/23a249047013b5321d4a60c4d2437462086f601b061776a525e5fba2a59f/regex-2026.5.9-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:d641a8c9a61618047796d572a39a79b26167b0411d2c3031937b2fe2d081e2cf", size = 777223, upload-time = "2026-05-09T23:14:24.179Z" }, + { url = "https://files.pythonhosted.org/packages/94/6a/e85ed9538cd19586d0465076a4578a12e093ce776d15f3f8ce92733a8dd6/regex-2026.5.9-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:24b2355ef5cc9aa5b8f07d17704face1c166fdcc2290fa7bd6e6c925655a8346", size = 785760, upload-time = "2026-05-09T23:14:26.065Z" }, + { url = "https://files.pythonhosted.org/packages/2a/c4/f25473209438638e947c55f9156fd8f236f74169229028cc99116380868e/regex-2026.5.9-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:a24852d3c29ad9e47593593d8a247c44ccc3d0548ef12c822d6ed0810affe676", size = 860891, upload-time = "2026-05-09T23:14:28.17Z" }, + { url = "https://files.pythonhosted.org/packages/f9/f7/f4f86e3c74419c37370e91f150ae0c2ef7d34b2e0e4cdd5da046a02e4022/regex-2026.5.9-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:916714069da19329ef7de197dcbc77bb3104145c7c2c864dbfbe318f46b88b14", size = 765891, upload-time = "2026-05-09T23:14:30.06Z" }, + { url = "https://files.pythonhosted.org/packages/26/70/704d8e13765939146b1cd0ef4e2feb71d7929727d2290f026eed10095955/regex-2026.5.9-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:fa411799ca8da32a8d38d020a88faa5b6f91657d284761352940ecf9f7c3bbdd", size = 851380, upload-time = "2026-05-09T23:14:32.123Z" }, + { url = "https://files.pythonhosted.org/packages/26/29/1a13582a8460038edc38e49f64ceb0dd7c60f5caba77571f4bf6601965d9/regex-2026.5.9-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:1e6da47d679b7010ef27556b6e0f99771b744936db1792a10ceac6547ae1503e", size = 789350, upload-time = "2026-05-09T23:14:34.799Z" }, + { url = "https://files.pythonhosted.org/packages/73/56/3dcafe34fc72e271d62ad9a291801e88a1457bb251c132f15fcc2e5aad1a/regex-2026.5.9-cp314-cp314-win32.whl", hash = "sha256:98bd73080e8756255137e1bd3f3f00295bbc5aa383c0e0f973920e9134d7c4ad", size = 272130, upload-time = "2026-05-09T23:14:36.729Z" }, + { url = "https://files.pythonhosted.org/packages/d0/9c/02eebf0be95efe416c664db7fb8b6b05b7a0b06a7544f2884f2558b0526f/regex-2026.5.9-cp314-cp314-win_amd64.whl", hash = "sha256:ff8d372ac2acdc048d1c19916f27ee61bc5722728458ba6ca5052f2c72d51763", size = 280999, upload-time = "2026-05-09T23:14:39.126Z" }, + { url = "https://files.pythonhosted.org/packages/70/5a/1dd1abee76cb7a846a0bcf42fdc87e5720c3c33c24f3e37814310a513d9f/regex-2026.5.9-cp314-cp314-win_arm64.whl", hash = "sha256:e1d93bf647916292e8edcec150c07ddf3dc50179ccaf770c04a7f9e452155372", size = 273500, upload-time = "2026-05-09T23:14:41.059Z" }, + { url = "https://files.pythonhosted.org/packages/86/c1/c5f619b0057a7965cb78ec559c1d7a45ce8c99a35bea95483d64959a93d9/regex-2026.5.9-cp314-cp314t-macosx_10_13_universal2.whl", hash = "sha256:83d0ee4a57d1c87cb549e195ec300b8f0ec3a82eba66d835e4e2ed8634fe4499", size = 494269, upload-time = "2026-05-09T23:14:42.869Z" }, + { url = "https://files.pythonhosted.org/packages/05/2c/5d01f1aee33de4bbe60c8452945bfc8477ca7c5ae4450f6bfe711036cb36/regex-2026.5.9-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:d3d7eb5c9a7f6df82ed3cfac9beb93882a5cbcb5b8b157b56cb2b3b276574ac1", size = 293954, upload-time = "2026-05-09T23:14:44.822Z" }, + { url = "https://files.pythonhosted.org/packages/7a/fe/e8988b2ae2108c6ef71bd4aa8d87fbe257976dd0810e826cd75f701c68b6/regex-2026.5.9-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:075160bf16658e16d35233300b8453aac25de4cbea808d22348b6979668e924d", size = 292405, upload-time = "2026-05-09T23:14:47.211Z" }, + { url = "https://files.pythonhosted.org/packages/79/34/d2b0937faa7859263f7f0a3c6b103a1296306be6952dc173d0154e9a2f49/regex-2026.5.9-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:45375819235558a4ff1c4971dc32881f022613abdb180128f5cb4768c1765a1c", size = 811855, upload-time = "2026-05-09T23:14:49.21Z" }, + { url = "https://files.pythonhosted.org/packages/80/fe/daf53a47457a8486db66c66c01ceb9c2303eecee3f87197f1e77eb1a736d/regex-2026.5.9-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:ead4b163ac30a29574510cd4b3e2e985ac5290c05fc7095557d6a5f403fc31b5", size = 871189, upload-time = "2026-05-09T23:14:51.555Z" }, + { url = "https://files.pythonhosted.org/packages/1c/75/058fc4470cbfbf57d800aff1a0022b929a3f9fa553ee10a0cdf2070eb31f/regex-2026.5.9-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:8c6e4218fbdfbcd4f6c19efca40930d24a621bf4b48cb76bc6640543bd28ef20", size = 917485, upload-time = "2026-05-09T23:14:53.633Z" }, + { url = "https://files.pythonhosted.org/packages/88/e7/179cfda3a28bc843b5c6cfe7f79f23489c791ed95f151083803660878432/regex-2026.5.9-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6351571c8a42b505eb555c0dc47d740d0fb66977dc142919eea6f4325b7c56a0", size = 816369, upload-time = "2026-05-09T23:14:56.198Z" }, + { url = "https://files.pythonhosted.org/packages/41/90/6f0cc422071688266d344fca8462d787cba0a2c144acb25721f9a61ec265/regex-2026.5.9-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:002205cafd2a9e78c6290c7d1df277bf3277b3b7a30e0b4bb0dac2e2e3f7cb2d", size = 785869, upload-time = "2026-05-09T23:14:58.602Z" }, + { url = "https://files.pythonhosted.org/packages/02/67/a31f1760f09c27b251ef39e9beb541f462cf977381d067faa764c2c0e393/regex-2026.5.9-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:8abd33fef90b2a9efac5557d6033ca82d1195ed3a15fea5af15ba7b463c6a63b", size = 801427, upload-time = "2026-05-09T23:15:00.642Z" }, + { url = "https://files.pythonhosted.org/packages/e3/c4/1a80654597b6bc1e1ea0494824c31200e8a956abe290afae9b19a166a148/regex-2026.5.9-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:31037c82eccb44b7ea2e9e221d7c01429430e989a1f4b91ea5a855f6017b509a", size = 866482, upload-time = "2026-05-09T23:15:03.384Z" }, + { url = "https://files.pythonhosted.org/packages/d1/11/960724e06482c08466ff5611e242e86f80062949cdf6b4b9cc317b9dd93d/regex-2026.5.9-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:5604dfd046dc37eca90250fc3be938b076c8059fa772ac0ed6f499b0f0fb0415", size = 773022, upload-time = "2026-05-09T23:15:05.625Z" }, + { url = "https://files.pythonhosted.org/packages/50/a8/a9979c3e7918280e93159ebcab5ef1a65116dd4f3bd6091be0eae4a126e8/regex-2026.5.9-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:0e1b1b4e496afbb24f4a62aba855ee4f88f25578927697b340702e48c9ee6bc2", size = 856642, upload-time = "2026-05-09T23:15:07.966Z" }, + { url = "https://files.pythonhosted.org/packages/fe/d4/a9b732f2f0072c0ab12227483abb24fffcb9f73f8a2b203df0a6d0434735/regex-2026.5.9-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:be3372b9df6ddecff6486d37e19095a7b4973137caf5512407a89f4455361f41", size = 803552, upload-time = "2026-05-09T23:15:10.215Z" }, + { url = "https://files.pythonhosted.org/packages/d5/fe/1b3113817447a1d4155e4ac76d2e072f42c0bcba2f43fa8a0e756ea2cd91/regex-2026.5.9-cp314-cp314t-win32.whl", hash = "sha256:3ddd90103f9e5c471c49c7852ecc1fe27c7e45eb99e977aefe7caa4e779f4f58", size = 275746, upload-time = "2026-05-09T23:15:12.609Z" }, + { url = "https://files.pythonhosted.org/packages/92/73/93d42045302636c91f2e5ef588b65b84b01428f28ec77de256b1dfdfbe5c/regex-2026.5.9-cp314-cp314t-win_amd64.whl", hash = "sha256:ca518ed29c46eecba6010b15f1b9a479314d2de409536e71b6a13aa04e3b8a77", size = 285685, upload-time = "2026-05-09T23:15:15.086Z" }, + { url = "https://files.pythonhosted.org/packages/da/80/35b4c33c804a165a7f55289afda3ea9e3eb6d15800341a2d66455c0f1f30/regex-2026.5.9-cp314-cp314t-win_arm64.whl", hash = "sha256:5e41809d2683fcde7d5a8c87a6567ba1fb1ce0de9f31bff578de00a4b2d76daa", size = 275713, upload-time = "2026-05-09T23:15:16.98Z" }, ] [[package]] name = "requests" -version = "2.33.1" +version = "2.34.2" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "certifi" }, @@ -4926,9 +5007,9 @@ dependencies = [ { name = "idna" }, { name = "urllib3" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/5f/a4/98b9c7c6428a668bf7e42ebb7c79d576a1c3c1e3ae2d47e674b468388871/requests-2.33.1.tar.gz", hash = "sha256:18817f8c57c6263968bc123d237e3b8b08ac046f5456bd1e307ee8f4250d3517", size = 134120, upload-time = "2026-03-30T16:09:15.531Z" } +sdist = { url = "https://files.pythonhosted.org/packages/ac/c3/e2a2b89f2d3e2179abd6d00ebd70bff6273f37fb3e0cc209f48b39d00cbf/requests-2.34.2.tar.gz", hash = "sha256:f288924cae4e29463698d6d60bc6a4da69c89185ad1e0bcc4104f584e960b9ed", size = 142856, upload-time = "2026-05-14T19:25:27.735Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/d7/8e/7540e8a2036f79a125c1d2ebadf69ed7901608859186c856fa0388ef4197/requests-2.33.1-py3-none-any.whl", hash = "sha256:4e6d1ef462f3626a1f0a0a9c42dd93c63bad33f9f1c1937509b8c5c8718ab56a", size = 64947, upload-time = "2026-03-30T16:09:13.83Z" }, + { url = "https://files.pythonhosted.org/packages/a0/f4/c67b0b3f1b9245e8d266f0f112c500d50e5b4e83cb6f3b71b6528104182a/requests-2.34.2-py3-none-any.whl", hash = "sha256:2a0d60c172f83ac6ab31e4554906c0f3b3588d37b5cb939b1c061f4907e278e0", size = 73075, upload-time = "2026-05-14T19:25:26.443Z" }, ] [[package]] @@ -4945,16 +5026,16 @@ wheels = [ [[package]] name = "responses" -version = "0.26.0" +version = "0.26.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "pyyaml" }, { name = "requests" }, { name = "urllib3" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/9f/b4/b7e040379838cc71bf5aabdb26998dfbe5ee73904c92c1c161faf5de8866/responses-0.26.0.tar.gz", hash = "sha256:c7f6923e6343ef3682816ba421c006626777893cb0d5e1434f674b649bac9eb4", size = 81303, upload-time = "2026-02-19T14:38:05.574Z" } +sdist = { url = "https://files.pythonhosted.org/packages/c2/58/1fb6de3503428196df78638f991ec8095274f1ee9723e272ee4d9ff0092b/responses-0.26.1.tar.gz", hash = "sha256:2eb3218553cc8f79b57d257bac23af5e1bf381f5b9390b1767816f0843e01dc2", size = 83088, upload-time = "2026-05-21T19:56:39.747Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/ce/04/7f73d05b556da048923e31a0cc878f03be7c5425ed1f268082255c75d872/responses-0.26.0-py3-none-any.whl", hash = "sha256:03ec4409088cd5c66b71ecbbbd27fe2c58ddfad801c66203457b3e6a04868c37", size = 35099, upload-time = "2026-02-19T14:38:03.847Z" }, + { url = "https://files.pythonhosted.org/packages/3a/31/6a620b4427d546b9e7cca8b3b8c5f0559d9cef2bb9eedcda7f73c1473c19/responses-0.26.1-py3-none-any.whl", hash = "sha256:8aacc4586eb08fb2208ef64a9eb4258d9b0c6e6f4260845f2f018ab847495345", size = 35502, upload-time = "2026-05-21T19:56:38.046Z" }, ] [[package]] @@ -4995,6 +5076,9 @@ wheels = [ name = "rpds-py" version = "0.30.0" source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version < '3.11'", +] sdist = { url = "https://files.pythonhosted.org/packages/20/af/3f2f423103f1113b36230496629986e0ef7e199d2aa8392452b484b38ced/rpds_py-0.30.0.tar.gz", hash = "sha256:dd8ff7cf90014af0c0f787eea34794ebf6415242ee1d6fa91eaba725cc441e84", size = 69469, upload-time = "2025-11-30T20:24:38.837Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/06/0c/0c411a0ec64ccb6d104dcabe0e713e05e153a9a2c3c2bd2b32ce412166fe/rpds_py-0.30.0-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:679ae98e00c0e8d68a7fda324e16b90fd5260945b45d3b824c892cec9eea3288", size = 370490, upload-time = "2025-11-30T20:21:33.256Z" }, @@ -5113,29 +5197,171 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/d1/b7/b95708304cd49b7b6f82fdd039f1748b66ec2b21d6a45180910802f1abf1/rpds_py-0.30.0-pp311-pypy311_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:ac37f9f516c51e5753f27dfdef11a88330f04de2d564be3991384b2f3535d02e", size = 562191, upload-time = "2025-11-30T20:24:36.853Z" }, ] +[[package]] +name = "rpds-py" +version = "2026.5.1" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version >= '3.14'", + "python_full_version == '3.13.*'", + "python_full_version >= '3.11' and python_full_version < '3.13'", +] +sdist = { url = "https://files.pythonhosted.org/packages/2e/43/25a8dcd3feedd735039a8f0b5b7e3b118232b5eae288c4fd9ab200d41094/rpds_py-2026.5.1.tar.gz", hash = "sha256:07b24fea40541e28570e5b795a4a38fbdcd12550c06bd0748005ecc8116ca256", size = 64459, upload-time = "2026-05-28T12:02:13.232Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/4f/a0/acf8b6fc20bfdcd3a45bd3f57680fb198e157b7e997b9123b10763798bd2/rpds_py-2026.5.1-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:3397a5ed7174dc2786bb214030232fc36fe8e5584fec43a9952cc542b1a12036", size = 355609, upload-time = "2026-05-28T11:58:50.78Z" }, + { url = "https://files.pythonhosted.org/packages/b6/95/f8203fd997484b1690a6869cd0e503b6c3c6be55b0ecc36d1a491fe742f0/rpds_py-2026.5.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:99ab6ba7bfa2cb0f96a04e3652355bf04e3f51aceb1e943b8541dab7ba4828cc", size = 348460, upload-time = "2026-05-28T11:58:52.374Z" }, + { url = "https://files.pythonhosted.org/packages/33/8c/b47326ad2f0be545a5e5c1a55937a12afaea7d392ba2837bb9680f57e6c9/rpds_py-2026.5.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d0efbe45632665e53e3db8fe1e5692db58fc5cb9bab4459d570b83efefe11164", size = 381031, upload-time = "2026-05-28T11:58:53.775Z" }, + { url = "https://files.pythonhosted.org/packages/22/0b/e83bbd97ffac6f6389b605cd4e1c8ac5761dc7e977769c9255d8c5adb7bd/rpds_py-2026.5.1-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:01d17b29c0c23d82b1f4751147ec49cf451f1fc2554eb9ef5f957e55d2656ead", size = 387121, upload-time = "2026-05-28T11:58:55.243Z" }, + { url = "https://files.pythonhosted.org/packages/fd/0e/d285d1bc8864245919c61e1ca82263e4a66d337759c3a4cef72766ff9afc/rpds_py-2026.5.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7559f72b94ae52659086c595dfa017cde03155f7832071d30959049052cb3ece", size = 501026, upload-time = "2026-05-28T11:58:56.788Z" }, + { url = "https://files.pythonhosted.org/packages/86/06/ccb2109a1e543437b5e43816f2b43b9554cc6783145528a4e3711e05c011/rpds_py-2026.5.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9e25b7088f9ccbfc0dfcaa52bf969300ca229e10ecf758974ebcbb080a4b37bb", size = 391865, upload-time = "2026-05-28T11:58:58.298Z" }, + { url = "https://files.pythonhosted.org/packages/3d/33/237173db1cfef10105b3839a24de00eb8d2a523711add4632447cdf0aedd/rpds_py-2026.5.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:613fc4ee9eaef26dc5840666214dd6fbcebcf32f46e76f4abc473059f4e13dda", size = 378012, upload-time = "2026-05-28T11:58:59.589Z" }, + { url = "https://files.pythonhosted.org/packages/97/64/1eae54e34d5161f9969295e80bd6b62a55f2b6ac5f2a5b60d02c2140e758/rpds_py-2026.5.1-cp311-cp311-manylinux_2_31_riscv64.whl", hash = "sha256:85264a90ff4c05c1568dd65f5921c837614b67c60358fb4c17df3b7f2e90690a", size = 391111, upload-time = "2026-05-28T11:59:01.104Z" }, + { url = "https://files.pythonhosted.org/packages/d8/34/5bb334a5a0f65d77869217c4654f34c78a7d11b93938a3c076a2edeafc52/rpds_py-2026.5.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:fe71bca7d547acb17027c7fd1624ff8aae623499c498d3e7011182c4de5c25e0", size = 409225, upload-time = "2026-05-28T11:59:02.433Z" }, + { url = "https://files.pythonhosted.org/packages/16/0f/007ec21283b5b040b4ec3bd95e0402591e22bfa7d5c93dfe01c465c2d2d7/rpds_py-2026.5.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:a05fa4f41f37ec97c9c260441a940450a192f78d774d2b097eee1379f1e1246a", size = 556487, upload-time = "2026-05-28T11:59:04.012Z" }, + { url = "https://files.pythonhosted.org/packages/ff/10/5437c94508169b6b22d8418fef7a66e9ffb5f3b9e9c94460f2eedafe06ff/rpds_py-2026.5.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:df1d2a1996755b24b9ecee92cb4d36c28f86f464a6a173349c26bab41e94b8c2", size = 620798, upload-time = "2026-05-28T11:59:05.485Z" }, + { url = "https://files.pythonhosted.org/packages/e0/d5/9937dce4d6bda74157b954e7d1460db05a22f5929dccfeeba1ed27a93df0/rpds_py-2026.5.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:8895840ac4809e5f60c88fd07617cd71326e73d6e5a8aa783c5c0f7c24985de2", size = 584053, upload-time = "2026-05-28T11:59:06.837Z" }, + { url = "https://files.pythonhosted.org/packages/6c/31/750617dd0ae1752471bf43f9e41d263398fae7cde7849d23b8574a70e617/rpds_py-2026.5.1-cp311-cp311-win32.whl", hash = "sha256:3684a59b158a7683aaeb8e25352e9a9dd2122cec78f2d8530266e4f91b4c7b3f", size = 214390, upload-time = "2026-05-28T11:59:08.402Z" }, + { url = "https://files.pythonhosted.org/packages/3c/bb/3dcab0e1d9516303f2eb672a5d6f62eca5a69e2886301e9c8c54b520c39b/rpds_py-2026.5.1-cp311-cp311-win_amd64.whl", hash = "sha256:7bd530e6a530bb3ea892f194fafa455f3516ac25ecf7143fd33c09be62b0470a", size = 231097, upload-time = "2026-05-28T11:59:09.786Z" }, + { url = "https://files.pythonhosted.org/packages/49/d6/c6bbf5cb1cf12b9732df8074b57f6ef8341ba884c95d40632ae8bddb44e4/rpds_py-2026.5.1-cp311-cp311-win_arm64.whl", hash = "sha256:0a5ae4dbe43c1076983b72616496919872ae7bbe7a1e21cc48336bc3154d130b", size = 226361, upload-time = "2026-05-28T11:59:11.079Z" }, + { url = "https://files.pythonhosted.org/packages/d4/e7/a78582dc57caa592dcc7d4fb69b61390561e908eb3d2f5df5928a8e354c0/rpds_py-2026.5.1-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:3abe24a66e57adcfa645d718063a5fa5103ecc71ddbf26d78af8f9368018ff1d", size = 353040, upload-time = "2026-05-28T11:59:12.531Z" }, + { url = "https://files.pythonhosted.org/packages/a3/43/35e3f136343aef451e545ce8c38d36c2f93c0ed88703db8b64ba2b205c68/rpds_py-2026.5.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:58b1d94308ddf0b1982f61f2eb54bf92997c9ece8a8093ef014250f4a517906c", size = 345775, upload-time = "2026-05-28T11:59:13.827Z" }, + { url = "https://files.pythonhosted.org/packages/20/e1/0f2160c5982d3157734d5cb3ed63d8b2d583a73c9864f77b666449f32cf8/rpds_py-2026.5.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0fa92420128dadce7f54bd73ba1825a273e9268fe9e35dbf7e6362890efa4e08", size = 376329, upload-time = "2026-05-28T11:59:15.271Z" }, + { url = "https://files.pythonhosted.org/packages/d0/11/ee0ba42aff83bf4effdbc576673c6be64c5e173978c3f6d537e94482f77d/rpds_py-2026.5.1-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ca653c6546386227cd9800d1bef6a348099acf8db4250341da6d90f663d6dfcb", size = 383539, upload-time = "2026-05-28T11:59:16.665Z" }, + { url = "https://files.pythonhosted.org/packages/11/df/d94aa6a499d4ac40afe2d7620f2c597fd3c0f182e854ad7cf3f596a81cb6/rpds_py-2026.5.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:66c93681c4729e4e3ecba31b8179fae083ff3118841672835140338b4b9867c1", size = 494674, upload-time = "2026-05-28T11:59:17.991Z" }, + { url = "https://files.pythonhosted.org/packages/1f/75/33d30f43bb2f458de11979486a591b1bf6e5651765ed1704c6197c2dc773/rpds_py-2026.5.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:40ff257542e04796880e011e15cd4dc21c2599975df2aaa8f2c8495ca574e1a5", size = 389268, upload-time = "2026-05-28T11:59:19.434Z" }, + { url = "https://files.pythonhosted.org/packages/f4/1e/2c9096fc19d5fd084b0184ca2b651e659aa0a37e6fdbecf6ece47f147fe1/rpds_py-2026.5.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b6825cc329b290e93c5f6a9be2393118a763f6ccf6abd83704e0c102ca583644", size = 376280, upload-time = "2026-05-28T11:59:21Z" }, + { url = "https://files.pythonhosted.org/packages/b9/e5/61ec9f8be8211ea7f48448195549e4aaf02004083475493b0e137702ecb2/rpds_py-2026.5.1-cp312-cp312-manylinux_2_31_riscv64.whl", hash = "sha256:de42116e69cb53b911cc34aee5ab98f36c597b822545045d49e938818b99e5e4", size = 387233, upload-time = "2026-05-28T11:59:22.454Z" }, + { url = "https://files.pythonhosted.org/packages/0d/ca/bcec1005c4f4a234f92a29078631fee49206c7265ccae966f18fd332e80e/rpds_py-2026.5.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:c0f920015df2a504bebaba6d4c31ccf3fcf942f92655c086da30b671aad19aa6", size = 405009, upload-time = "2026-05-28T11:59:23.845Z" }, + { url = "https://files.pythonhosted.org/packages/72/e6/4d5718c5cf26c522dc7c9999e238da1e77380b81d0c5d1df11e271ddfeb1/rpds_py-2026.5.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:0408a24e44feb919423dc6d9da677cb5cddb894d2ca9e763967d156d9c60fab4", size = 553113, upload-time = "2026-05-28T11:59:25.184Z" }, + { url = "https://files.pythonhosted.org/packages/d4/25/2ee807bdb3e1f0b7eddf7782acd5665a8b5205a331a7d7244a52c4812fd9/rpds_py-2026.5.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:cea68bcd53467561ae2f96a6bdad1544299ba97b5b0ddcd5ac3d376e5c781c24", size = 618838, upload-time = "2026-05-28T11:59:26.749Z" }, + { url = "https://files.pythonhosted.org/packages/6a/c1/7d4c26f167f8c41501cc073d30ee22082b16ce358cf5b00ec97cbc7804ea/rpds_py-2026.5.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:4be8b1d2a705cc37d08256004e1d07de143fa0075c8e85a3df020b776f62b732", size = 582436, upload-time = "2026-05-28T11:59:28.11Z" }, + { url = "https://files.pythonhosted.org/packages/04/1d/9d12b0a337bab46f4769f8857f4007e3b2d639e14f9a44a0efe157696e64/rpds_py-2026.5.1-cp312-cp312-win32.whl", hash = "sha256:6736718bd4fc49cbcb538ba30516fdbef161522acefb739657d48b97bd864fed", size = 212734, upload-time = "2026-05-28T11:59:29.689Z" }, + { url = "https://files.pythonhosted.org/packages/c5/93/e4116f2de7f56bc7406a76033dc501811ddeb22b7f056b92d632871ebb0c/rpds_py-2026.5.1-cp312-cp312-win_amd64.whl", hash = "sha256:0a7d1eec967df0e9b22614a5e177622e0c89611d03727fa0cb48e45028907870", size = 229045, upload-time = "2026-05-28T11:59:31.033Z" }, + { url = "https://files.pythonhosted.org/packages/cb/53/6c3419d85eb2ec5938a37627c585b42d76a63bb731d6e42ed4b079ebf486/rpds_py-2026.5.1-cp312-cp312-win_arm64.whl", hash = "sha256:1841d067089e117142d79b98aa0df2f08b52f2ecc1819dd2700636c0db74a473", size = 223967, upload-time = "2026-05-28T11:59:32.318Z" }, + { url = "https://files.pythonhosted.org/packages/6c/32/14c961ad295f490eb0849ada8b79683e93a59b9de3afdd983eaf55fa6867/rpds_py-2026.5.1-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:efef4ac29c6ff495531eb17ee705b62841ecaa291b7c7077e848ea03e237164d", size = 352787, upload-time = "2026-05-28T11:59:33.655Z" }, + { url = "https://files.pythonhosted.org/packages/ca/bb/d1b85117967c11191441a7274ae616c65d93901d082c588f89a50a8da5ae/rpds_py-2026.5.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:c39f5b67a8a2e67179ada2a954227d670fe65fa9098457f698f56ddf248709b3", size = 345179, upload-time = "2026-05-28T11:59:35Z" }, + { url = "https://files.pythonhosted.org/packages/7c/46/d84105f062e626a1b233f863907288a4708c2d833b8b4c6fb2764bc080c0/rpds_py-2026.5.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b5c30f3f04eef4fbd362226a6f31d7c8895ca4fbb6e0b790f6890a98d8da8559", size = 376173, upload-time = "2026-05-28T11:59:36.43Z" }, + { url = "https://files.pythonhosted.org/packages/e2/ae/469d7959ce5b1201e1de135dc735b86db3b35dd0d1734f6a44246d5f061c/rpds_py-2026.5.1-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:277f6c82f0580848796c7ecc8a7173aa3bfb928e4ff831261c2f60a81dc270db", size = 383162, upload-time = "2026-05-28T11:59:37.995Z" }, + { url = "https://files.pythonhosted.org/packages/dc/a2/57853d31a1116a561aa072794602ad3f6341e18d70a8523f1bd5b9fc1e5a/rpds_py-2026.5.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:63c2c4c213f1a4e3f3de28ecab029dbdee976324e729c0d7a55211be72576b02", size = 495093, upload-time = "2026-05-28T11:59:39.453Z" }, + { url = "https://files.pythonhosted.org/packages/99/63/3a8eabcad9314b7daf5c65f451d2c33d989235cd8a5762186cf2c3f5a4f8/rpds_py-2026.5.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3350ec808fb538fe71a1f94dfaa0e29c598dfad805ce49f0caec5ae3183c652b", size = 389829, upload-time = "2026-05-28T11:59:40.896Z" }, + { url = "https://files.pythonhosted.org/packages/4b/25/05678d97fc25e2622df14dc530fb82023174ecfff6733991ed0d78f167bd/rpds_py-2026.5.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b1b964e3ab599e718dc46c018d104b1ebc007cbc6567d827c94a687fca56d77e", size = 374786, upload-time = "2026-05-28T11:59:42.626Z" }, + { url = "https://files.pythonhosted.org/packages/88/d1/8c90b6431e80a3b91b284a5c7c8c0c4f9c006444d90477a740d6e0f9c694/rpds_py-2026.5.1-cp313-cp313-manylinux_2_31_riscv64.whl", hash = "sha256:19cb09fab7b7fc96b2a6e28f2e34b72a3705ff27b37edb77455316e5d3f3dc9b", size = 386920, upload-time = "2026-05-28T11:59:44.124Z" }, + { url = "https://files.pythonhosted.org/packages/ff/99/4638f672ab356682d633ee0da9255f5b67ce6efd0b85eb94ad3e255e65a5/rpds_py-2026.5.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:abe76bcdba31e576cb83eeb8797aa0d882b738fef6dc65d0601fc753806a5b46", size = 405059, upload-time = "2026-05-28T11:59:47.177Z" }, + { url = "https://files.pythonhosted.org/packages/66/3f/3546524b6eb4cc2e1f363a3d638fa52f6c24faae3500c25fb488b02f1740/rpds_py-2026.5.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:8bff7073db3899158fff55ebf57b113a67030af26f80a18978f9f0aa60250ddf", size = 553030, upload-time = "2026-05-28T11:59:48.603Z" }, + { url = "https://files.pythonhosted.org/packages/c6/c3/7b3388c796fcf471bd17194242d4dc1a7608567c0fa422bcc1c5e79f9c1e/rpds_py-2026.5.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:8ba264fa49be666cd9cc56bf34ec7002fb3d27a4aee5bcb4d43d0d18feb1bb6f", size = 618975, upload-time = "2026-05-28T11:59:50.314Z" }, + { url = "https://files.pythonhosted.org/packages/61/1e/a3cb07f2795075d1d88efddae2f541359fde5f08c81ee114c29c2949c90a/rpds_py-2026.5.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:4860b603ddda0475a8885499b3729e90229d480105b42651962a5397d995fa89", size = 581178, upload-time = "2026-05-28T11:59:51.673Z" }, + { url = "https://files.pythonhosted.org/packages/a1/74/e758c03a5ef46f04c37f2651a2893db846d569ba8a7bca469d4b58939bcd/rpds_py-2026.5.1-cp313-cp313-win32.whl", hash = "sha256:7944270ae71383f6e2657dd7d5ce4eeb4ac2d0059a6738f0510583d462ab4842", size = 212481, upload-time = "2026-05-28T11:59:53.148Z" }, + { url = "https://files.pythonhosted.org/packages/70/ec/a2aca432db9c7359b40fa393eeeaa0d166c2f70175be956e75fa24197c44/rpds_py-2026.5.1-cp313-cp313-win_amd64.whl", hash = "sha256:88647f43a73c4e01be19b04ceef0c8d3a1958153604d13c773becd8016f2a0cf", size = 228519, upload-time = "2026-05-28T11:59:54.505Z" }, + { url = "https://files.pythonhosted.org/packages/29/60/a73bfdd45b096574556acf303bbd9fa9eed36ca8a818b514e2a5d5fe2b9d/rpds_py-2026.5.1-cp313-cp313-win_arm64.whl", hash = "sha256:453895624ecf7db7063b1004e44037522bbaef9ff6a945e59bc71662d7a03abd", size = 223446, upload-time = "2026-05-28T11:59:56.081Z" }, + { url = "https://files.pythonhosted.org/packages/18/e2/408105fd611823f00882aea810f3989a30d26b1bab8b6beb20f98c724e0e/rpds_py-2026.5.1-cp313-cp313t-macosx_10_12_x86_64.whl", hash = "sha256:b4e4bc98639ec915f512fde3aa7a95e0041d95d9c3cc86eea841fa63cb1e8600", size = 355287, upload-time = "2026-05-28T11:59:57.448Z" }, + { url = "https://files.pythonhosted.org/packages/8d/58/5c4a43436843c90d0f6d19f82c200c80e3843ca9fa07b237623327f6d384/rpds_py-2026.5.1-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:cacedb7a6e167680acba45ad5716e89067d225dc80da0d7040cae8c81d4572fa", size = 347033, upload-time = "2026-05-28T11:59:58.881Z" }, + { url = "https://files.pythonhosted.org/packages/fb/c2/1a71acdacaf4e259b10278fb87b039ded3cf80041bcd89dd8a3ea702ded6/rpds_py-2026.5.1-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:68700371c5d7ae1412862ddfa719090925c93ecf351c566d66f09d04b136ea00", size = 376891, upload-time = "2026-05-28T12:00:00.516Z" }, + { url = "https://files.pythonhosted.org/packages/c2/c8/535f3d9b65addd8e28aa87b83c6e526799c3717a88273db8ea795beeef7a/rpds_py-2026.5.1-cp313-cp313t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:296c799becfa849c779c8725494fe9ed94959ed886787df4364b058465bad7f0", size = 385646, upload-time = "2026-05-28T12:00:02.394Z" }, + { url = "https://files.pythonhosted.org/packages/1c/91/dc033f313345c354ade914dbe73cdb90b615a4409ea02430d5356794f3d8/rpds_py-2026.5.1-cp313-cp313t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d3858b908218ee108d0bbfb2095ccc237648053c9bf98affad7cb079acaf1d97", size = 498830, upload-time = "2026-05-28T12:00:04.189Z" }, + { url = "https://files.pythonhosted.org/packages/27/fc/90fcbea459dbb8ddc18a2e0fd1de9412b48bc84ffff2db771cf714bacfd6/rpds_py-2026.5.1-cp313-cp313t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4fb8d2e7cb2f850b169806d61d1b991738acec96500a75c30f49caf064ce7cef", size = 392830, upload-time = "2026-05-28T12:00:05.797Z" }, + { url = "https://files.pythonhosted.org/packages/b2/1d/46cd11a228c9750684a798d98f878be6f614aa762438da7378f035e79e35/rpds_py-2026.5.1-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:27b74c10ed6a8f190f4287f53bcfea348b92a84a9c9f70d30183d1e6172d580d", size = 379613, upload-time = "2026-05-28T12:00:07.433Z" }, + { url = "https://files.pythonhosted.org/packages/24/4a/d9b0c6af3a1de03eb93741bbe8be2bdce84d8fda8224f3005451d86df389/rpds_py-2026.5.1-cp313-cp313t-manylinux_2_31_riscv64.whl", hash = "sha256:b9a6528956191c48c52294a592dbd4a8386d7048bdb25c0efcb6b966466c6d83", size = 388183, upload-time = "2026-05-28T12:00:09.227Z" }, + { url = "https://files.pythonhosted.org/packages/c5/b4/db7aaabdda6d020afc87d981bcc2f57a434c7dec60ecfc2ab3dd50b20351/rpds_py-2026.5.1-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:af03e34e860047bc7a352b842856fcf78798fbb81132cc98bd2f907ab4eb9cd2", size = 408578, upload-time = "2026-05-28T12:00:10.779Z" }, + { url = "https://files.pythonhosted.org/packages/08/d6/070f6a41cbb343e2ac4171859bf3f3623e0ab002f72619d6d505313ec2de/rpds_py-2026.5.1-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:fea6e836d10abbe191d557d33bd58bd5987725fe63aa1eefe557d230209855bd", size = 553573, upload-time = "2026-05-28T12:00:12.443Z" }, + { url = "https://files.pythonhosted.org/packages/75/ab/1a71ea3589c4345dac0a0518f0e6a031cb42689277851b683c46d27463a5/rpds_py-2026.5.1-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:fc0c0f878ea770a0a8a462456c5ad36fc9fe6358e6b76fdadc7f17575e0b8bf1", size = 620861, upload-time = "2026-05-28T12:00:14.09Z" }, + { url = "https://files.pythonhosted.org/packages/8a/22/9bf80a56069c0c443fcfefac639a86a744550a2898817a6dfd3e26654924/rpds_py-2026.5.1-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:e0b360f316d966b048b085857630b3cc51f3db2f07b06f440eac8f695374d1e3", size = 585633, upload-time = "2026-05-28T12:00:15.66Z" }, + { url = "https://files.pythonhosted.org/packages/da/68/3b2c0a75c9e04125696f84ebdbbf304acf5a40b58ba4481cdb98a922c3ba/rpds_py-2026.5.1-cp313-cp313t-win32.whl", hash = "sha256:a2999883eedf72fdfb7520b92c7d4ec2572a71ff40239377aa604cc529eecafc", size = 210074, upload-time = "2026-05-28T12:00:17.291Z" }, + { url = "https://files.pythonhosted.org/packages/e7/8b/609157d5a25d37d4f29f92840ba531f416907c34ae5c5739dd21fc2bef98/rpds_py-2026.5.1-cp313-cp313t-win_amd64.whl", hash = "sha256:e07be2a9d7122bd6e82dea89814ef8dc893feb1aae97fec1630f3263bbb30e55", size = 228635, upload-time = "2026-05-28T12:00:18.73Z" }, + { url = "https://files.pythonhosted.org/packages/d4/6f/19c1918a4b590d8de87e712e4abe4b3875771eff60216fb6153cf6665c68/rpds_py-2026.5.1-cp314-cp314-macosx_10_12_x86_64.whl", hash = "sha256:1f2c391c3059798093b65df23aca2cac150460ae9c630d99dec83d703d9485b9", size = 349756, upload-time = "2026-05-28T12:00:20.217Z" }, + { url = "https://files.pythonhosted.org/packages/e5/60/a06fe7da34eca79dacbf958a2ba0c6eea85bc2b29de20080bf40f72f66fa/rpds_py-2026.5.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:413b424f7c4ee65ab5e5be91f5731be0f8b41a1ee2b12dfe810d716312e95a78", size = 343831, upload-time = "2026-05-28T12:00:21.711Z" }, + { url = "https://files.pythonhosted.org/packages/bf/ec/b2333b97b90e2a6ef6ca8ad386ee284968e74bcfe113b3f1a8d9036429a9/rpds_py-2026.5.1-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2c595a1d9255dce0599e13130d1440ab2506654f2b50294226ee06402f8fef63", size = 375127, upload-time = "2026-05-28T12:00:23.326Z" }, + { url = "https://files.pythonhosted.org/packages/14/7f/e00aae54067f2b488c4637961d5f58204d470795fc791085fa3f15060d2e/rpds_py-2026.5.1-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:1c27c5f6102eac8c03e7595a00827a53b271ba40a53b59ff8709170e0855ea4a", size = 379034, upload-time = "2026-05-28T12:00:24.89Z" }, + { url = "https://files.pythonhosted.org/packages/be/cc/423999bbb8ae8dc93c77fc1d5e984ade5eb89d237d3bb884ccfa72ae2890/rpds_py-2026.5.1-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6c7fcf61d44cacecaf3aea542b0e053db77972a4573e7ceda16fb2b399161195", size = 490823, upload-time = "2026-05-28T12:00:26.676Z" }, + { url = "https://files.pythonhosted.org/packages/0f/aa/c671bf660f12e68d3c52ff86c7066ed1372df5a0f4f2ff584e419b8207e7/rpds_py-2026.5.1-cp314-cp314-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2c817a189d4ee14290420e5ff051e4dd6baa13f3edf84685071dee07a6d538ee", size = 388144, upload-time = "2026-05-28T12:00:28.577Z" }, + { url = "https://files.pythonhosted.org/packages/19/c8/d63bb75b68afe77b229e3021c6031bcaf01da5db5b0e69d0d10f9ba679a7/rpds_py-2026.5.1-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:21846aac0ed2e0589f38c12dc44e77bb64e494b771eadbcf169cba00566ba7ba", size = 371959, upload-time = "2026-05-28T12:00:30.304Z" }, + { url = "https://files.pythonhosted.org/packages/82/35/c51122014d8274ff37dc606d60049c3db7d83da02b5b282511e5a906a9a6/rpds_py-2026.5.1-cp314-cp314-manylinux_2_31_riscv64.whl", hash = "sha256:b317c87a13f769a4e787819bd508aaa5d69aa09b0880de9af6d3a8a54571cdec", size = 383558, upload-time = "2026-05-28T12:00:31.764Z" }, + { url = "https://files.pythonhosted.org/packages/e3/f9/2790cb99c136a5363acdeacf5c27c56f3de0d4118a1f48fca83404c99c89/rpds_py-2026.5.1-cp314-cp314-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:ce87129d9f2c14fa6c4a8601fb80eb4488c80d38a20cd13758ef11123e14995d", size = 402789, upload-time = "2026-05-28T12:00:33.247Z" }, + { url = "https://files.pythonhosted.org/packages/e5/1b/e4fb584f8c75d35c38150ff6a332cda949e6f97acba1f4fd123b14ab56fe/rpds_py-2026.5.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:9cdddb6c1207d284d94fd1530adf57fbd797fe7c4b8704ba85f49414f2557e7d", size = 551405, upload-time = "2026-05-28T12:00:34.819Z" }, + { url = "https://files.pythonhosted.org/packages/d8/f7/a6731b4216cb3793ea1af5391da240f5683dacc0d13e034fe5fc3503f240/rpds_py-2026.5.1-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:4e237e139f94d3c036fd28eb9f564c99055476ff4ff05cd42be55ce349b5aa02", size = 616975, upload-time = "2026-05-28T12:00:36.268Z" }, + { url = "https://files.pythonhosted.org/packages/2c/ea/2e051a81d95d8e63f4b35a1c463a87e8766bc3d083c067c5dfb6bf220747/rpds_py-2026.5.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:ed0954b524873214369184a9c82b0eaa45a3fbb9a798cd95b17e0d98499e7ea0", size = 578701, upload-time = "2026-05-28T12:00:37.82Z" }, + { url = "https://files.pythonhosted.org/packages/65/56/b5f6fdb2083e32bca8a8993d89e70db114b4756c9e2c38421328126689d2/rpds_py-2026.5.1-cp314-cp314-win32.whl", hash = "sha256:2d88621d6a7d4dfa633d21abe90f280bb205274e16b1d1e61c6ad4640b2453b7", size = 209806, upload-time = "2026-05-28T12:00:39.492Z" }, + { url = "https://files.pythonhosted.org/packages/fb/80/65a5aa96c155e611d1ed844e4e1f57f3e36b021f396d9f8585d756e6b90d/rpds_py-2026.5.1-cp314-cp314-win_amd64.whl", hash = "sha256:cef8ac28d26f4dda3533060c20fbf80a325458fa9fd23ea72a73cdfa8e978838", size = 225985, upload-time = "2026-05-28T12:00:40.94Z" }, + { url = "https://files.pythonhosted.org/packages/27/7c/ad185212e87b05f196daef92bc5f3caf07298eb47c295b5585c3dd3093ac/rpds_py-2026.5.1-cp314-cp314-win_arm64.whl", hash = "sha256:eaaea962c68cdc68d4a533ba985ab8e9484277910bbfaa2ab3ef7732667bfed8", size = 221219, upload-time = "2026-05-28T12:00:43.15Z" }, + { url = "https://files.pythonhosted.org/packages/23/58/e14ae18759020334646b031e708ab4158d653a938822bfb7b95ef2e93aa3/rpds_py-2026.5.1-cp314-cp314t-macosx_10_12_x86_64.whl", hash = "sha256:21942f52dbbd5f8758bf021213d28bd45c39e873e65e2407faf5f1846f5761ad", size = 352148, upload-time = "2026-05-28T12:00:44.638Z" }, + { url = "https://files.pythonhosted.org/packages/31/9b/5f4a1e2f960bca3ac5d052b139dd31eed97b259f9d909173821760d542e8/rpds_py-2026.5.1-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:f414556f6e3958300ff941e40c9f97e3dc9774ddd1b3434c475d73dd354bbed3", size = 345196, upload-time = "2026-05-28T12:00:46.14Z" }, + { url = "https://files.pythonhosted.org/packages/1a/71/1d9574d6a2fa20ab60eaa55c7467f5aa20cbc770f341a05f09c0876f59e2/rpds_py-2026.5.1-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ef1013a8625c74043210190b246f5b1551e09757c1f356c6e4160ef96c5bc081", size = 374981, upload-time = "2026-05-28T12:00:47.531Z" }, + { url = "https://files.pythonhosted.org/packages/0c/9a/37e99f4915a80aa71670263c1267f7ae0af95f53a3f61e6c3bdc016d4515/rpds_py-2026.5.1-cp314-cp314t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:cc68e231a77a5f0d774ae278a1f8e55c0456501820847c1e4efb3829f3441df6", size = 379961, upload-time = "2026-05-28T12:00:49.216Z" }, + { url = "https://files.pythonhosted.org/packages/a8/ff/6e73f74b89d2e0715e0fc86b7dde893f9a61ae2f9b256ff3bdfe41ac4e94/rpds_py-2026.5.1-cp314-cp314t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9baffb505aff33acc69b422a19f77806680f3c8632227d79f48de8a810d1c2c5", size = 495965, upload-time = "2026-05-28T12:00:51.111Z" }, + { url = "https://files.pythonhosted.org/packages/ea/e0/425faba25f59d74d4638b267f7c7a80e8649d2ef4db10a19b0c4a71e6e6f/rpds_py-2026.5.1-cp314-cp314t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b8d2f912928d426e8cfa396f7f3f8d29a59e6689c86dcca3c420730c1096322b", size = 389526, upload-time = "2026-05-28T12:00:52.77Z" }, + { url = "https://files.pythonhosted.org/packages/c6/76/7a41960e3fddae47fab43a28684d5da981401dffd88253de0944148654cb/rpds_py-2026.5.1-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:90f628283be835db980c941767d41c9a27b5239e54ba0a9c1335247e82406964", size = 376190, upload-time = "2026-05-28T12:00:54.215Z" }, + { url = "https://files.pythonhosted.org/packages/27/60/5f38dc70824fc6951b51d35377e577a3a3a4c81a6769cc5a2de25ebe0ad1/rpds_py-2026.5.1-cp314-cp314t-manylinux_2_31_riscv64.whl", hash = "sha256:1ebb2f0ab7e16132995a72de805170e0203df0c3dd22e1ef1cd1fdd90bd7a131", size = 383921, upload-time = "2026-05-28T12:00:55.673Z" }, + { url = "https://files.pythonhosted.org/packages/60/1a/d60a38caa1505f4b9483c3fbbde12c94e1079154f4f401a6da96f7e77621/rpds_py-2026.5.1-cp314-cp314t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:f3df3d16ded76f1f8c9cdebd0e1ea55fdf4c23b812de189814da7cf229c22a81", size = 404766, upload-time = "2026-05-28T12:00:57.518Z" }, + { url = "https://files.pythonhosted.org/packages/87/ff/602fd3f174d6425f0bce05ad0dfbec0e96b38d0f7d08a79af5aa20083885/rpds_py-2026.5.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:9af8905b8f854990e40d5206aa5ac58d9b0fe0b7f351ff2bb086c20f6c8c6a47", size = 551343, upload-time = "2026-05-28T12:00:58.978Z" }, + { url = "https://files.pythonhosted.org/packages/b8/c1/1be13327acdbead3eca1fde03b6a34dbb011f1e864e217f0d32cc1779a7f/rpds_py-2026.5.1-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:036a36a87fb1cd3b214d11c4b3c4f7d2ddad933625dca1c900b56a057c07740a", size = 618502, upload-time = "2026-05-28T12:01:00.656Z" }, + { url = "https://files.pythonhosted.org/packages/f3/d7/afb49b49d7f2be8b7ba1a9f0977fa5168003437b93086726f066544e8351/rpds_py-2026.5.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:62ae3853454fe9ef283a03c96c2d835d39e84b14643a9d62c82ef0fb87d702ca", size = 581916, upload-time = "2026-05-28T12:01:02.22Z" }, + { url = "https://files.pythonhosted.org/packages/25/d1/dbef8c1f8a10f07beb62b5f054e20099fd9924b3ec001b8f0b6ac7813a85/rpds_py-2026.5.1-cp314-cp314t-win32.whl", hash = "sha256:6c3d771a46ec18b12af06ce36243a9a80b07a5d0515236332d90863ca8bb326a", size = 207855, upload-time = "2026-05-28T12:01:03.821Z" }, + { url = "https://files.pythonhosted.org/packages/2a/72/bfa4e61ab8e7dc1c8adf397e05e6cbdd4239357bd72b248d3de662f23915/rpds_py-2026.5.1-cp314-cp314t-win_amd64.whl", hash = "sha256:c93c629be4636cf54337bd5f06c104d55e42ced54d681f6fe21ae510a65116f6", size = 225422, upload-time = "2026-05-28T12:01:05.194Z" }, + { url = "https://files.pythonhosted.org/packages/27/3a/7b5da92b640f67b6717ccafc83cdd06bfa7ff2395c3685c68922bb54d703/rpds_py-2026.5.1-cp315-cp315-macosx_10_12_x86_64.whl", hash = "sha256:3574b55c604b8f75dacb007136508bbc0db406e626301778096a133327e7f2fb", size = 349576, upload-time = "2026-05-28T12:01:06.722Z" }, + { url = "https://files.pythonhosted.org/packages/d7/8a/2aafd7ad355a1bd48ca76e2262b74b15e6432b5a1efe150efd4d779cd55d/rpds_py-2026.5.1-cp315-cp315-macosx_11_0_arm64.whl", hash = "sha256:94068eb3ae6d43f5a786b7db96a406a34e6d5c24489feef32fd6e8946ea7b291", size = 343640, upload-time = "2026-05-28T12:01:08.441Z" }, + { url = "https://files.pythonhosted.org/packages/f7/7d/6c9523c1abbe840a1b7fba3c516d48e1d3487cc80fea4366c4071cf56784/rpds_py-2026.5.1-cp315-cp315-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f3a5b10e8ce894825f380a8f1b6444cf73c294dfea62afbb2d13e3a9e630cec1", size = 375322, upload-time = "2026-05-28T12:01:09.934Z" }, + { url = "https://files.pythonhosted.org/packages/5a/5d/0b7b03fb1dc509321f01de3149784ab773e34c8573022029af8076afcb9c/rpds_py-2026.5.1-cp315-cp315-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:fc09f82e63d4bcd58149572f857a431bae851dc747e313c3b5bdf7abb907fda8", size = 379066, upload-time = "2026-05-28T12:01:11.48Z" }, + { url = "https://files.pythonhosted.org/packages/d7/e2/8ef6012999ebf1cb1c22f876d9ce5e63d960fd4631d2af3202d3f480aa25/rpds_py-2026.5.1-cp315-cp315-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e10464d17df3b582745c25cec695cb9558bca2cb6ddb631aee1787fc72c767b2", size = 494586, upload-time = "2026-05-28T12:01:13.051Z" }, + { url = "https://files.pythonhosted.org/packages/80/af/1eeb029bec67582c226b7809172207cd005073af4ebd906e65ff494f4983/rpds_py-2026.5.1-cp315-cp315-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ba05adbf15d994c38ec0b7ab32e858e5110c21e9009a00a86545fd220f84e038", size = 388415, upload-time = "2026-05-28T12:01:14.631Z" }, + { url = "https://files.pythonhosted.org/packages/18/23/ffbe10711c4d766c1cab0557d6906c074f795814863c67b351355d29354a/rpds_py-2026.5.1-cp315-cp315-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:77c004fdc7b891967106f78ddfd7b076bfe6813c6139c6fff6aed3bcaa960b26", size = 372427, upload-time = "2026-05-28T12:01:16.153Z" }, + { url = "https://files.pythonhosted.org/packages/bd/3a/30ba4a6ad457e5b070c18d742a33fb77d8d922b565cc881f8a5313d63bfe/rpds_py-2026.5.1-cp315-cp315-manylinux_2_31_riscv64.whl", hash = "sha256:83bcf894486c9d78dd290d3c0124ff6dd8875d3025e2090a8ec49fcc37c55fdd", size = 383615, upload-time = "2026-05-28T12:01:17.809Z" }, + { url = "https://files.pythonhosted.org/packages/d3/69/62e242b53ce39c0814bd24e1a6e6eba6c92be716277745f317f9540a2e7b/rpds_py-2026.5.1-cp315-cp315-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:c3df104083952a0e0c6f10de33e440eabe98fb6317d23e1a58c68f6df08d01b9", size = 402786, upload-time = "2026-05-28T12:01:19.419Z" }, + { url = "https://files.pythonhosted.org/packages/38/c1/a770b9c186928a1ed0f7e6d7ae50e7f3950ed23e3f9e366dbc8e38cb55de/rpds_py-2026.5.1-cp315-cp315-musllinux_1_2_aarch64.whl", hash = "sha256:980450826cf22e133c57e0835070bdd0dd3f73b9b708c3ce223def2cb9469e14", size = 551583, upload-time = "2026-05-28T12:01:21.013Z" }, + { url = "https://files.pythonhosted.org/packages/21/7c/68e8579b95375b70d2a963103c42e705856cdb98569258bd807f4423891c/rpds_py-2026.5.1-cp315-cp315-musllinux_1_2_i686.whl", hash = "sha256:205dde846f24332ab0c1188699a043b8d165b79bb84529ce272c45048ff6be01", size = 616941, upload-time = "2026-05-28T12:01:22.548Z" }, + { url = "https://files.pythonhosted.org/packages/70/a1/a6135aed5730ff03ab957182259987ac11e55fb392a28dc6f0592048a280/rpds_py-2026.5.1-cp315-cp315-musllinux_1_2_x86_64.whl", hash = "sha256:3966b82dd563176396df030f3dd52a6e54cb69b718e95e78bd555ed3d1e0185d", size = 578349, upload-time = "2026-05-28T12:01:24.118Z" }, + { url = "https://files.pythonhosted.org/packages/09/6e/f24201a76a84e6c49d0bdfdfcb735210e21701e9b21c5bfc0ba497dd62f6/rpds_py-2026.5.1-cp315-cp315-win32.whl", hash = "sha256:7818f8d0a415be74d2be3590b0a1c1f463a642f4d0217e7d10602dceef5b79aa", size = 209922, upload-time = "2026-05-28T12:01:25.522Z" }, + { url = "https://files.pythonhosted.org/packages/9e/e4/966bc240bb0485fc265278f6de44d05834bf0b3618886e0b22e33d54c49a/rpds_py-2026.5.1-cp315-cp315-win_amd64.whl", hash = "sha256:b3cc20c0d800af78fd0fac68086e28c1856cec51ea528bb81ea851aa40d39325", size = 226003, upload-time = "2026-05-28T12:01:27.062Z" }, + { url = "https://files.pythonhosted.org/packages/5c/5c/a15a59269cd5e74472734516c73795c15eccfc841b3d4b0228c3f53f19d0/rpds_py-2026.5.1-cp315-cp315-win_arm64.whl", hash = "sha256:3609e9939a8a76cd904cf98a3f1f13b5dc7e150adeaee89e0ea09652ea213e16", size = 221245, upload-time = "2026-05-28T12:01:28.51Z" }, + { url = "https://files.pythonhosted.org/packages/e0/22/135ce03804e179a71ceb13be095deda4a279bc88f7a6b8fa161c5ad44e12/rpds_py-2026.5.1-cp315-cp315t-macosx_10_12_x86_64.whl", hash = "sha256:5d333a7127d4b307601ac37792bee01bb95c867cbfacf21b6375b804d6bbd723", size = 352015, upload-time = "2026-05-28T12:01:30.214Z" }, + { url = "https://files.pythonhosted.org/packages/3b/5f/f1f6d2652eb9d848f6eb369d8db83a2da6249bb49ad2c2a48f45d54538d3/rpds_py-2026.5.1-cp315-cp315t-macosx_11_0_arm64.whl", hash = "sha256:b5f077b44a4f7808520f66dae234988d867deb9aed9be5da057ce9ba831b2a41", size = 345016, upload-time = "2026-05-28T12:01:31.656Z" }, + { url = "https://files.pythonhosted.org/packages/88/66/b74182775691ea2290c99e52ac8d5db844e56fbec90ce421f107658c8314/rpds_py-2026.5.1-cp315-cp315t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:55d8f9b7b78c9538fc9e04e82ec0e888ff0c3cffcfad152c77e57cd09351a98a", size = 374775, upload-time = "2026-05-28T12:01:33.136Z" }, + { url = "https://files.pythonhosted.org/packages/ff/8f/15e5a61d9f0a43902d36561d4f07cae6ae9f4716be825159fd72717f33af/rpds_py-2026.5.1-cp315-cp315t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e3a8ae58895ac107ed934a6bf51e5846f95c53b9b940c2c6d310838fd5846358", size = 380270, upload-time = "2026-05-28T12:01:34.574Z" }, + { url = "https://files.pythonhosted.org/packages/02/c3/f859b12763a80540cdf2af0f15b19904cf756a71d7bdd3f82ff3e5b1bbf9/rpds_py-2026.5.1-cp315-cp315t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0957cf3c2b8632ec7aaebffebea8005b353cc2a237b6e2ae3c2cac0820704cfb", size = 495285, upload-time = "2026-05-28T12:01:36.127Z" }, + { url = "https://files.pythonhosted.org/packages/1c/c7/ff27c2ac8411d30b03b1829fd88cae8dad1a4d0da48dd25e57c4038042e6/rpds_py-2026.5.1-cp315-cp315t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c396c1304de421050b3681ea70f371874b54d41b0151e96109758144c231e30b", size = 389581, upload-time = "2026-05-28T12:01:37.635Z" }, + { url = "https://files.pythonhosted.org/packages/6e/67/fe92ee32a6cc05c77228a2f8b1762e7124f386ec20ff83d0757b762d58d0/rpds_py-2026.5.1-cp315-cp315t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:aad1bff7f666b9598e573815affd666aac6a13a585dde336f843e33350c7fadc", size = 376041, upload-time = "2026-05-28T12:01:39.307Z" }, + { url = "https://files.pythonhosted.org/packages/f8/91/b4d6685c27aba55bd82f25b278be8237038117d05f9659a6213ad3408130/rpds_py-2026.5.1-cp315-cp315t-manylinux_2_31_riscv64.whl", hash = "sha256:656a042550878f12d45752452d47094b7cfe5ad1e9d7b87b5a22ad3ae5ff8015", size = 383946, upload-time = "2026-05-28T12:01:41.043Z" }, + { url = "https://files.pythonhosted.org/packages/bd/79/2c1d832a53c8e0f8e98fc970ec257b950fecd4f62be2ab7182b500a0cbc8/rpds_py-2026.5.1-cp315-cp315t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:73c4bd4f70294737b5206a3e8e30ccadbf8a60301831c8ea23eec5dbeea1ecfa", size = 405526, upload-time = "2026-05-28T12:01:43.032Z" }, + { url = "https://files.pythonhosted.org/packages/78/c4/c98117b03c6a8581ab2c2dfccfe9a5ad82bd8128a3c28b46a6ad2d97c393/rpds_py-2026.5.1-cp315-cp315t-musllinux_1_2_aarch64.whl", hash = "sha256:43bca78665423cabae77146f2fe7ce55272b6c8d55d82cca83effd42c7e13972", size = 551165, upload-time = "2026-05-28T12:01:44.648Z" }, + { url = "https://files.pythonhosted.org/packages/3b/c1/bc479ca069200af730881b1bd525e3114b2b391a351509fcb1b772f28086/rpds_py-2026.5.1-cp315-cp315t-musllinux_1_2_i686.whl", hash = "sha256:42d0f20e85e549c870749d0e247f0c10d318a45b7e9676d575d2dcb04a1b2e66", size = 618778, upload-time = "2026-05-28T12:01:46.337Z" }, + { url = "https://files.pythonhosted.org/packages/77/65/38ab2f90df44c2febfb63cc10ced40763d9b4bc94d173e734528663fe7f5/rpds_py-2026.5.1-cp315-cp315t-musllinux_1_2_x86_64.whl", hash = "sha256:b1be5c35683684d5331b93600c210e8367c254683d8a6df6bd21bd2da3a334fb", size = 581839, upload-time = "2026-05-28T12:01:48.109Z" }, + { url = "https://files.pythonhosted.org/packages/15/2d/ce1f605fe036aadd460e5822e578c6c7ec3a860936cca37d6e0f299daa77/rpds_py-2026.5.1-cp315-cp315t-win32.whl", hash = "sha256:75808f6c38ce7749bb68cc2770161aae5045e6c6f6781a9782e74b93304399df", size = 207866, upload-time = "2026-05-28T12:01:49.648Z" }, + { url = "https://files.pythonhosted.org/packages/79/cb/966040123eb102371559746908ef2c9471f4d43e17ec9a645a2258dab64b/rpds_py-2026.5.1-cp315-cp315t-win_amd64.whl", hash = "sha256:90bd6630002a1c7f09e7843dd79f0d24f3d2897cc25a753480917865d14f15b3", size = 225441, upload-time = "2026-05-28T12:01:51.408Z" }, + { url = "https://files.pythonhosted.org/packages/42/56/3fe0fb34820ff667be791b3a3c22b85e8bcba54e9c832f47438c191fa7be/rpds_py-2026.5.1-pp311-pypy311_pp73-macosx_10_12_x86_64.whl", hash = "sha256:edf2765d84e42447f112ad877af8fe1db0089aaec5b28e88d6eab45e7fe99cea", size = 357151, upload-time = "2026-05-28T12:01:53.43Z" }, + { url = "https://files.pythonhosted.org/packages/8b/f2/3eb9ccdb9f143b8c9b003978898cb497f942a324c077401e6b8834238e63/rpds_py-2026.5.1-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:ad3773236e95f7f33991eb125224b7da66f206504d032a253a02da7e134519fb", size = 350195, upload-time = "2026-05-28T12:01:54.901Z" }, + { url = "https://files.pythonhosted.org/packages/a7/24/dbda232bc4f3ed732120692ab0d2c8402cb020516556d8bee622dcef2413/rpds_py-2026.5.1-pp311-pypy311_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a04df86b3f0fade39ec8fd0e0aab089b1da9fbd2b48df778a57ef96f5e7d38df", size = 381850, upload-time = "2026-05-28T12:01:56.601Z" }, + { url = "https://files.pythonhosted.org/packages/40/30/32e769839a358f78810c234f160f2cc21d1e4e47e1c0e0e0d535be5a0219/rpds_py-2026.5.1-pp311-pypy311_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:6142dbd80c4df62a5d899f0d616d417f84e0bc8d32526c8e5589019d75d028a7", size = 387899, upload-time = "2026-05-28T12:01:58.212Z" }, + { url = "https://files.pythonhosted.org/packages/ab/86/ec84d243aadb3b34b71dd26a010d0930b2d284ff5fc9a69fec53810ee6fd/rpds_py-2026.5.1-pp311-pypy311_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0b35217adefe87f2fe4db7e9766cabe84744bfe9616d9667be18988928c7f2dc", size = 501618, upload-time = "2026-05-28T12:01:59.888Z" }, + { url = "https://files.pythonhosted.org/packages/74/25/b60e52686bbff777a64f9e4f4d3dd57980dc846913777177a2c92e4937aa/rpds_py-2026.5.1-pp311-pypy311_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b95d5e11fc712b752081183a55a244c03cd00570489edd7014d8899f8ceb8162", size = 394003, upload-time = "2026-05-28T12:02:01.482Z" }, + { url = "https://files.pythonhosted.org/packages/9b/c7/b3a6a588cc2219510ef3f42e207483a93950bedd1e3a0fd4015c95cff9e5/rpds_py-2026.5.1-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:141c9498daf2ace9eda35d2b0e376f9ea8b058d84f2aef4f96fccfd449a2f251", size = 379778, upload-time = "2026-05-28T12:02:03.197Z" }, + { url = "https://files.pythonhosted.org/packages/31/00/c7dba3fc8a3da8cb3f6db1eb3386be4d79c2e97c6890d20eb9ac66ae8c43/rpds_py-2026.5.1-pp311-pypy311_pp73-manylinux_2_31_riscv64.whl", hash = "sha256:6f249f8b860a200ad35193af961183ebe9132710484e6f6ce0cf89fd83c63a9a", size = 392359, upload-time = "2026-05-28T12:02:04.817Z" }, + { url = "https://files.pythonhosted.org/packages/93/dd/472ba494c70753f93745992c99855bee0636daf74e6984e5e003f150316f/rpds_py-2026.5.1-pp311-pypy311_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:e4abbf391a70be864920858bf360f4fb380577c9a0f732438a1996726e2c195b", size = 412820, upload-time = "2026-05-28T12:02:06.401Z" }, + { url = "https://files.pythonhosted.org/packages/1d/6f/93831a3bfe789542ed0c1d0d74b78b440f055d6dc3ea4640eba2d95e6e23/rpds_py-2026.5.1-pp311-pypy311_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:c74005a7bb87752acf351c93897ec63ad77a07a0da7ecad9c050e32e7286ba34", size = 557243, upload-time = "2026-05-28T12:02:08.013Z" }, + { url = "https://files.pythonhosted.org/packages/1f/ff/0b3d604614ffc77522c6b288fdbce68957eb583da1002aa65ba38ac0ee40/rpds_py-2026.5.1-pp311-pypy311_pp73-musllinux_1_2_i686.whl", hash = "sha256:8213afbe8a3a906fb9acb2014423fe3359ee783d0bf90995f70623a3217bfa6c", size = 623541, upload-time = "2026-05-28T12:02:09.661Z" }, + { url = "https://files.pythonhosted.org/packages/ea/ea/e7b0251441da9adfeaebcf29601d10f2a1455fcf0772fae9e7e19032bd96/rpds_py-2026.5.1-pp311-pypy311_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:8c43a8a973270fd173bf48cdf80bbe66312421cba68d40845034f174f2389049", size = 586326, upload-time = "2026-05-28T12:02:11.47Z" }, +] + [[package]] name = "ruff" -version = "0.15.12" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/99/43/3291f1cc9106f4c63bdce7a8d0df5047fe8422a75b091c16b5e9355e0b11/ruff-0.15.12.tar.gz", hash = "sha256:ecea26adb26b4232c0c2ca19ccbc0083a68344180bba2a600605538ce51a40a6", size = 4643852, upload-time = "2026-04-24T18:17:14.305Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/c3/6e/e78ffb61d4686f3d96ba3df2c801161843746dcbcbb17a1e927d4829312b/ruff-0.15.12-py3-none-linux_armv6l.whl", hash = "sha256:f86f176e188e94d6bdbc09f09bfd9dc729059ad93d0e7390b5a73efe19f8861c", size = 10640713, upload-time = "2026-04-24T18:17:22.841Z" }, - { url = "https://files.pythonhosted.org/packages/ae/08/a317bc231fb9e7b93e4ef3089501e51922ff88d6936ce5cf870c4fe55419/ruff-0.15.12-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:e3bcd123364c3770b8e1b7baaf343cc99a35f197c5c6e8af79015c666c423a6c", size = 11069267, upload-time = "2026-04-24T18:17:30.105Z" }, - { url = "https://files.pythonhosted.org/packages/aa/a4/f828e9718d3dce1f5f11c39c4f65afd32783c8b2aebb2e3d259e492c47bd/ruff-0.15.12-py3-none-macosx_11_0_arm64.whl", hash = "sha256:fe87510d000220aa1ed530d4448a7c696a0cae1213e5ec30e5874287b66557b5", size = 10397182, upload-time = "2026-04-24T18:17:07.177Z" }, - { url = "https://files.pythonhosted.org/packages/71/e0/3310fc6d1b5e1fdea22bf3b1b807c7e187b581021b0d7d4514cccdb5fb71/ruff-0.15.12-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:84a1630093121375a3e2a95b4a6dc7b59e2b4ee76216e32d81aae550a832d002", size = 10758012, upload-time = "2026-04-24T18:16:55.759Z" }, - { url = "https://files.pythonhosted.org/packages/11/c1/a606911aee04c324ddaa883ae418f3569792fd3c4a10c50e0dd0a2311e1e/ruff-0.15.12-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:fb129f40f114f089ebe0ca56c0d251cf2061b17651d464bb6478dc01e69f11f5", size = 10447479, upload-time = "2026-04-24T18:16:51.677Z" }, - { url = "https://files.pythonhosted.org/packages/9d/68/4201e8444f0894f21ab4aeeaee68aa4f10b51613514a20d80bd628d57e88/ruff-0.15.12-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b0c862b172d695db7598426b8af465e7e9ac00a3ea2a3630ee67eb82e366aaa6", size = 11234040, upload-time = "2026-04-24T18:17:16.529Z" }, - { url = "https://files.pythonhosted.org/packages/34/ff/8a6d6cf4ccc23fd67060874e832c18919d1557a0611ebef03fdb01fff11e/ruff-0.15.12-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2849ea9f3484c3aca43a82f484210370319e7170df4dfe4843395ddf6c57bc33", size = 12087377, upload-time = "2026-04-24T18:17:04.944Z" }, - { url = "https://files.pythonhosted.org/packages/85/f6/c669cf73f5152f623d34e69866a46d5e6185816b19fcd5b6dd8a2d299922/ruff-0.15.12-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9e77c7e51c07fe396826d5969a5b846d9cd4c402535835fb6e21ce8b28fef847", size = 11367784, upload-time = "2026-04-24T18:17:25.409Z" }, - { url = "https://files.pythonhosted.org/packages/e8/39/c61d193b8a1daaa8977f7dea9e8d8ba866e02ea7b65d32f6861693aa4c12/ruff-0.15.12-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:83b2f4f2f3b1026b5fb449b467d9264bf22067b600f7b6f41fc5958909f449d0", size = 11344088, upload-time = "2026-04-24T18:17:12.258Z" }, - { url = "https://files.pythonhosted.org/packages/c2/8d/49afab3645e31e12c590acb6d3b5b69d7aab5b81926dbaf7461f9441f37a/ruff-0.15.12-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:9ba3b8f1afd7e2e43d8943e55f249e13f9682fde09711644a6e7290eb4f3e339", size = 11271770, upload-time = "2026-04-24T18:17:02.457Z" }, - { url = "https://files.pythonhosted.org/packages/46/06/33f41fe94403e2b755481cdfb9b7ef3e4e0ed031c4581124658d935d52b4/ruff-0.15.12-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:e852ba9fdc890655e1d78f2df1499efbe0e54126bd405362154a75e2bde159c5", size = 10719355, upload-time = "2026-04-24T18:17:27.648Z" }, - { url = "https://files.pythonhosted.org/packages/0d/59/18aa4e014debbf559670e4048e39260a85c7fcee84acfd761ac01e7b8d35/ruff-0.15.12-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:dd8aed930da53780d22fc70bdf84452c843cf64f8cb4eb38984319c24c5cd5fd", size = 10462758, upload-time = "2026-04-24T18:17:32.347Z" }, - { url = "https://files.pythonhosted.org/packages/25/e7/cc9f16fd0f3b5fddcbd7ec3d6ae30c8f3fde1047f32a4093a98d633c6570/ruff-0.15.12-py3-none-musllinux_1_2_i686.whl", hash = "sha256:01da3988d225628b709493d7dc67c3b9b12c0210016b08690ef9bd27970b262b", size = 10953498, upload-time = "2026-04-24T18:17:20.674Z" }, - { url = "https://files.pythonhosted.org/packages/72/7a/a9ba7f98c7a575978698f4230c5e8cc54bbc761af34f560818f933dafa0c/ruff-0.15.12-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:9cae0f92bd5700d1213188b31cd3bdd2b315361296d10b96b8e2337d3d11f53e", size = 11447765, upload-time = "2026-04-24T18:17:09.755Z" }, - { url = "https://files.pythonhosted.org/packages/ea/f9/0ae446942c846b8266059ad8a30702a35afae55f5cdc54c5adf8d7afdc27/ruff-0.15.12-py3-none-win32.whl", hash = "sha256:d0185894e038d7043ba8fd6aee7499ece6462dc0ea9f1e260c7451807c714c20", size = 10657277, upload-time = "2026-04-24T18:17:18.591Z" }, - { url = "https://files.pythonhosted.org/packages/33/f1/9614e03e1cdcbf9437570b5400ced8a720b5db22b28d8e0f1bda429f660d/ruff-0.15.12-py3-none-win_amd64.whl", hash = "sha256:c87a162d61ab3adca47c03f7f717c68672edec7d1b5499e652331780fe74950d", size = 11837758, upload-time = "2026-04-24T18:17:00.113Z" }, - { url = "https://files.pythonhosted.org/packages/c0/98/6beb4b351e472e5f4c4613f7c35a5290b8be2497e183825310c4c3a3984b/ruff-0.15.12-py3-none-win_arm64.whl", hash = "sha256:a538f7a82d061cee7be55542aca1d86d1393d55d81d4fcc314370f4340930d4f", size = 11120821, upload-time = "2026-04-24T18:16:57.979Z" }, +version = "0.15.17" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/8c/a9/3abdf488f1bf3d24c699415e454ed554a6350d5d89ce183be1ee0a3361ac/ruff-0.15.17.tar.gz", hash = "sha256:2ec446937fd16c8c4de2674a209cc5af64d9c6f17d21fbf1151054fa0bcf5219", size = 4743346, upload-time = "2026-06-11T17:54:47.663Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/db/4d/e11259f5da07cb6afb2d074c31bf09da9671993f7329d4f15d2fdc458301/ruff-0.15.17-py3-none-linux_armv6l.whl", hash = "sha256:d9feddb927fc68bd295f5eebc587a7e42cfaf9b65f60ca4a2386febff575da8f", size = 10856677, upload-time = "2026-06-11T17:54:49.533Z" }, + { url = "https://files.pythonhosted.org/packages/29/3e/772d679e1a0dc058e58875bd2c0cb713a0530877b4a76fee3c7966df0d49/ruff-0.15.17-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:25805a226d741c47d274a35ad5c10a7dde175fcddfa511d7cf3da0a21eb3eab7", size = 11223443, upload-time = "2026-06-11T17:55:00.573Z" }, + { url = "https://files.pythonhosted.org/packages/68/58/bd41f7688b2fd5623012605130ed70e60aa7f2244baa3d5066bdd61530c8/ruff-0.15.17-py3-none-macosx_11_0_arm64.whl", hash = "sha256:f6ad73b14c2d18a3bf8ad7cb6974294d7f613a7898604826058e6ac64918ef4d", size = 10566458, upload-time = "2026-06-11T17:55:07.52Z" }, + { url = "https://files.pythonhosted.org/packages/d8/5b/733371013fcf1ec339e477ece6ab42bfe10bdd9bba8ee88a9516aa56bfc0/ruff-0.15.17-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6ba0c1e4f95bcb3869d0d30cbd5917071ef2e28665abfec970cdab0492c713ed", size = 10914483, upload-time = "2026-06-11T17:55:05.501Z" }, + { url = "https://files.pythonhosted.org/packages/bd/cc/6f24251cc0252f7239391ccb85833f320efad14ebe5b443943f37ced6332/ruff-0.15.17-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:81647960f10bff57d2e51cadd0c3950fe598400c852863a038720ef5b8cca91e", size = 10647497, upload-time = "2026-06-11T17:54:57.733Z" }, + { url = "https://files.pythonhosted.org/packages/68/dd/0d10c17ce1a1624d6fc3156309c3f834fdb5dfaad026ec90c85684f3990e/ruff-0.15.17-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0e01a84ddbc8c16c23055ba3924476850f1bbc1917cebbb9376665a63e74260d", size = 11416967, upload-time = "2026-06-11T17:54:51.461Z" }, + { url = "https://files.pythonhosted.org/packages/2f/91/556bfb156f6144f355e831c23db00b2fc4120f86b3ce81cc5f7fd2df51f3/ruff-0.15.17-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:84fe9f653152f8f294f9f7e03bf3a453d8b4a27f7a59c78c8666167f2b17b96c", size = 12335770, upload-time = "2026-06-11T17:54:45.793Z" }, + { url = "https://files.pythonhosted.org/packages/88/82/8b5999aa13355e926f06d9f42a32dcca862f623bf0363785ff89d607dffd/ruff-0.15.17-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8c0fe88a7676e7a05b73174d4d4a59cb2ac21ff8263583f87a81a6018475a978", size = 11575441, upload-time = "2026-06-11T17:54:32.661Z" }, + { url = "https://files.pythonhosted.org/packages/11/93/f10377bb04109ca0e8cbc483ff1982c54b6d418210041776f93e8cdc7fa9/ruff-0.15.17-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ecfc3c7878fff94633ab0348524e093f9ce3243080416dd7d14f8ba400174719", size = 11557614, upload-time = "2026-06-11T17:54:34.698Z" }, + { url = "https://files.pythonhosted.org/packages/c7/a6/eeeae7f7d5493df41649ab3db92f086b2d0a30199e4efdf8e3dd7a033f24/ruff-0.15.17-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:b8461180b22420b1bdc289909410930761629fddf2a5aaf60fae1ab26cedc4c4", size = 11544450, upload-time = "2026-06-11T17:54:39.042Z" }, + { url = "https://files.pythonhosted.org/packages/32/88/5991ce565129a24dd4a00db1254b3b5db2e53018cbe4018ea5a89738e727/ruff-0.15.17-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:6eccbe50a038b503e7140b441aa9c7fc8c1f36edf23ebef9f4165c2f28f568b7", size = 10892524, upload-time = "2026-06-11T17:55:09.432Z" }, + { url = "https://files.pythonhosted.org/packages/f5/1d/0fdd248313425f55223968af04b0a42125466a8d88d21c1d99c6af0a51e8/ruff-0.15.17-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:382fc0521025f5a8ad447d8bdd523545d0d7646adb718eb1c2dac5065ec27c0f", size = 10659573, upload-time = "2026-06-11T17:54:36.824Z" }, + { url = "https://files.pythonhosted.org/packages/9e/0e/072e8260deb9461062ce9311ced27a8e541229a6ffd483013dd37661e43e/ruff-0.15.17-py3-none-musllinux_1_2_i686.whl", hash = "sha256:456d41fcd1b2777ad63f09a6e7121d43f7b688bbc76a800c10f7f8fb1f912c3f", size = 11127818, upload-time = "2026-06-11T17:55:03.124Z" }, + { url = "https://files.pythonhosted.org/packages/ab/b4/55060a34163121498014696b5f656db5b8c6963768f227dbf0d76b311073/ruff-0.15.17-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:b1a04bcc94ae6194e9db05d16ad31f298a7194bfbcb08258bbe589cee1d587b8", size = 11655901, upload-time = "2026-06-11T17:54:53.562Z" }, + { url = "https://files.pythonhosted.org/packages/49/71/9b29d6b87cef468d697f43c6a91e3fae4a80185779d7d5a4ef27d173439f/ruff-0.15.17-py3-none-win32.whl", hash = "sha256:596065960ab1ff593f744220c9fe6580eda00a95003cffa9f4048bb5b1bf0392", size = 10925574, upload-time = "2026-06-11T17:54:55.723Z" }, + { url = "https://files.pythonhosted.org/packages/3d/b2/8fc77f3723228836fa5d12497eb71c808f83782e10d058d2b15cfa14640b/ruff-0.15.17-py3-none-win_amd64.whl", hash = "sha256:6769e5fa1710b179b92e0bfa5a51735b35baea9013dadb06d5f44cbcf9547084", size = 12058788, upload-time = "2026-06-11T17:54:41.042Z" }, + { url = "https://files.pythonhosted.org/packages/2d/c7/c53e8dbff9c9dc4b7928773421ae294a5d28fcb8dcda1a089579d3a7e510/ruff-0.15.17-py3-none-win_arm64.whl", hash = "sha256:f3be1fbb34bcdfd146240d8fb92a709d4c2c8191348580a3c044ec60fa0b4456", size = 11355275, upload-time = "2026-06-11T17:54:43.635Z" }, ] [[package]] @@ -5204,11 +5430,11 @@ wheels = [ [[package]] name = "slack-sdk" -version = "3.41.0" +version = "3.42.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/22/35/fc009118a13187dd9731657c60138e5a7c2dea88681a7f04dc406af5da7d/slack_sdk-3.41.0.tar.gz", hash = "sha256:eb61eb12a65bebeca9cb5d36b3f799e836ed2be21b456d15df2627cfe34076ca", size = 250568, upload-time = "2026-03-12T16:10:11.381Z" } +sdist = { url = "https://files.pythonhosted.org/packages/0e/00/16258bfa547559b2c936b50c882b4f0a36ebf6b69639eb763d8fa5e8d6cb/slack_sdk-3.42.0.tar.gz", hash = "sha256:873db9e1f632ac650ffdbf9d8ba825f3e9e7e576a1e4f9604ccb2a15b3727e3d", size = 252136, upload-time = "2026-05-18T17:50:44.727Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/a1/df/2e4be347ff98281b505cc0ccf141408cdd25eb5ca9f3830deb361b2472d3/slack_sdk-3.41.0-py2.py3-none-any.whl", hash = "sha256:bb18dcdfff1413ec448e759cf807ec3324090993d8ab9111c74081623b692a89", size = 313885, upload-time = "2026-03-12T16:10:09.811Z" }, + { url = "https://files.pythonhosted.org/packages/ce/ef/8a1556bd4843443993fc116783790a7cc553601a37f7d965ec26eef95e76/slack_sdk-3.42.0-py2.py3-none-any.whl", hash = "sha256:eb39aff97e476e10cc5a8ac29bd2e79a9959e880d9fe0c03b4e8f05b2ac996ff", size = 315469, upload-time = "2026-05-18T17:50:41.972Z" }, ] [[package]] @@ -5222,94 +5448,89 @@ wheels = [ [[package]] name = "snowballstemmer" -version = "3.0.1" +version = "3.1.1" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/75/a7/9810d872919697c9d01295633f5d574fb416d47e535f258272ca1f01f447/snowballstemmer-3.0.1.tar.gz", hash = "sha256:6d5eeeec8e9f84d4d56b847692bacf79bc2c8e90c7f80ca4444ff8b6f2e52895", size = 105575, upload-time = "2025-05-09T16:34:51.843Z" } +sdist = { url = "https://files.pythonhosted.org/packages/43/f8/0a71edf031f03c40db17503cb8ca78a69a171254e568e7db241b0ab57ea1/snowballstemmer-3.1.1.tar.gz", hash = "sha256:e07bbc54a0d798fe6010a12398422e62a8bfbba95c394fd0956ef58cb4d3e260", size = 123314, upload-time = "2026-06-03T00:56:40.194Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/c8/78/3565d011c61f5a43488987ee32b6f3f656e7f107ac2782dd57bdd7d91d9a/snowballstemmer-3.0.1-py3-none-any.whl", hash = "sha256:6cd7b3897da8d6c9ffb968a6781fa6532dce9c3618a4b127d920dab764a19064", size = 103274, upload-time = "2025-05-09T16:34:50.371Z" }, + { url = "https://files.pythonhosted.org/packages/4c/07/2ebca9b11fb9be7340a818d8d6f63feaebb146be2c4afbd6061701d6df6e/snowballstemmer-3.1.1-py3-none-any.whl", hash = "sha256:7e207fa178741da09cdee59d3ecec3827ad5f92b1fc5c9ff3755b639f71f5752", size = 104164, upload-time = "2026-06-03T00:56:38.614Z" }, ] [[package]] name = "soupsieve" -version = "2.8.3" +version = "2.8.4" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/7b/ae/2d9c981590ed9999a0d91755b47fc74f74de286b0f5cee14c9269041e6c4/soupsieve-2.8.3.tar.gz", hash = "sha256:3267f1eeea4251fb42728b6dfb746edc9acaffc4a45b27e19450b676586e8349", size = 118627, upload-time = "2026-01-20T04:27:02.457Z" } +sdist = { url = "https://files.pythonhosted.org/packages/47/2c/0a5f6f8ee0d5589e48c7640213ed5175d52cf540a06725b628cc1a45d6ce/soupsieve-2.8.4.tar.gz", hash = "sha256:e121fd02e975c695e4e9e8774a5ee35d74714b59307868dcc5319ad2d9e3328e", size = 121110, upload-time = "2026-05-24T13:55:57.154Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/46/2c/1462b1d0a634697ae9e55b3cecdcb64788e8b7d63f54d923fcd0bb140aed/soupsieve-2.8.3-py3-none-any.whl", hash = "sha256:ed64f2ba4eebeab06cc4962affce381647455978ffc1e36bb79a545b91f45a95", size = 37016, upload-time = "2026-01-20T04:27:01.012Z" }, + { 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.49" +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/09/45/461788f35e0364a8da7bda51a1fe1b09762d0c32f12f63727998d85a873b/sqlalchemy-2.0.49.tar.gz", hash = "sha256:d15950a57a210e36dd4cec1aac22787e2a4d57ba9318233e2ef8b2daf9ff2d5f", size = 9898221, upload-time = "2026-04-03T16:38:11.704Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/96/76/f908955139842c362aa877848f42f9249642d5b69e06cee9eae5111da1bd/sqlalchemy-2.0.49-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:42e8804962f9e6f4be2cbaedc0c3718f08f60a16910fa3d86da5a1e3b1bfe60f", size = 2159321, upload-time = "2026-04-03T16:50:11.8Z" }, - { url = "https://files.pythonhosted.org/packages/24/e2/17ba0b7bfbd8de67196889b6d951de269e8a46057d92baca162889beb16d/sqlalchemy-2.0.49-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:cc992c6ed024c8c3c592c5fc9846a03dd68a425674900c70122c77ea16c5fb0b", size = 3238937, upload-time = "2026-04-03T16:54:45.731Z" }, - { url = "https://files.pythonhosted.org/packages/90/1e/410dd499c039deacff395eec01a9da057125fcd0c97e3badc252c6a2d6a7/sqlalchemy-2.0.49-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6eb188b84269f357669b62cb576b5b918de10fb7c728a005fa0ebb0b758adce1", size = 3237188, upload-time = "2026-04-03T16:56:53.217Z" }, - { url = "https://files.pythonhosted.org/packages/ab/06/e797a8b98a3993ac4bc785309b9b6d005457fc70238ee6cefa7c8867a92e/sqlalchemy-2.0.49-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:62557958002b69699bdb7f5137c6714ca1133f045f97b3903964f47db97ea339", size = 3190061, upload-time = "2026-04-03T16:54:47.489Z" }, - { url = "https://files.pythonhosted.org/packages/44/d3/5a9f7ef580af1031184b38235da6ac58c3b571df01c9ec061c44b2b0c5a6/sqlalchemy-2.0.49-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:da9b91bca419dc9b9267ffadde24eae9b1a6bffcd09d0a207e5e3af99a03ce0d", size = 3211477, upload-time = "2026-04-03T16:56:55.056Z" }, - { url = "https://files.pythonhosted.org/packages/69/ec/7be8c8cb35f038e963a203e4fe5a028989167cc7299927b7cf297c271e37/sqlalchemy-2.0.49-cp310-cp310-win32.whl", hash = "sha256:5e61abbec255be7b122aa461021daa7c3f310f3e743411a67079f9b3cc91ece3", size = 2119965, upload-time = "2026-04-03T17:00:50.009Z" }, - { url = "https://files.pythonhosted.org/packages/b5/31/0defb93e3a10b0cf7d1271aedd87251a08c3a597ee4f353281769b547b5a/sqlalchemy-2.0.49-cp310-cp310-win_amd64.whl", hash = "sha256:0c98c59075b890df8abfcc6ad632879540f5791c68baebacb4f833713b510e75", size = 2142935, upload-time = "2026-04-03T17:00:51.675Z" }, - { url = "https://files.pythonhosted.org/packages/60/b5/e3617cc67420f8f403efebd7b043128f94775e57e5b84e7255203390ceae/sqlalchemy-2.0.49-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:c5070135e1b7409c4161133aa525419b0062088ed77c92b1da95366ec5cbebbe", size = 2159126, upload-time = "2026-04-03T16:50:13.242Z" }, - { url = "https://files.pythonhosted.org/packages/20/9b/91ca80403b17cd389622a642699e5f6564096b698e7cdcbcbb6409898bc4/sqlalchemy-2.0.49-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:9ac7a3e245fd0310fd31495eb61af772e637bdf7d88ee81e7f10a3f271bff014", size = 3315509, upload-time = "2026-04-03T16:54:49.332Z" }, - { url = "https://files.pythonhosted.org/packages/b1/61/0722511d98c54de95acb327824cb759e8653789af2b1944ab1cc69d32565/sqlalchemy-2.0.49-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4d4e5a0ceba319942fa6b585cf82539288a61e314ef006c1209f734551ab9536", size = 3315014, upload-time = "2026-04-03T16:56:56.376Z" }, - { url = "https://files.pythonhosted.org/packages/46/55/d514a653ffeb4cebf4b54c47bec32ee28ad89d39fafba16eeed1d81dccd5/sqlalchemy-2.0.49-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:3ddcb27fb39171de36e207600116ac9dfd4ae46f86c82a9bf3934043e80ebb88", size = 3267388, upload-time = "2026-04-03T16:54:51.272Z" }, - { url = "https://files.pythonhosted.org/packages/2f/16/0dcc56cb6d3335c1671a2258f5d2cb8267c9a2260e27fde53cbfb1b3540a/sqlalchemy-2.0.49-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:32fe6a41ad97302db2931f05bb91abbcc65b5ce4c675cd44b972428dd2947700", size = 3289602, upload-time = "2026-04-03T16:56:57.63Z" }, - { url = "https://files.pythonhosted.org/packages/51/6c/f8ab6fb04470a133cd80608db40aa292e6bae5f162c3a3d4ab19544a67af/sqlalchemy-2.0.49-cp311-cp311-win32.whl", hash = "sha256:46d51518d53edfbe0563662c96954dc8fcace9832332b914375f45a99b77cc9a", size = 2119044, upload-time = "2026-04-03T17:00:53.455Z" }, - { url = "https://files.pythonhosted.org/packages/c4/59/55a6d627d04b6ebb290693681d7683c7da001eddf90b60cfcc41ee907978/sqlalchemy-2.0.49-cp311-cp311-win_amd64.whl", hash = "sha256:951d4a210744813be63019f3df343bf233b7432aadf0db54c75802247330d3af", size = 2143642, upload-time = "2026-04-03T17:00:54.769Z" }, - { url = "https://files.pythonhosted.org/packages/49/b3/2de412451330756aaaa72d27131db6dde23995efe62c941184e15242a5fa/sqlalchemy-2.0.49-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:4bbccb45260e4ff1b7db0be80a9025bb1e6698bdb808b83fff0000f7a90b2c0b", size = 2157681, upload-time = "2026-04-03T16:53:07.132Z" }, - { url = "https://files.pythonhosted.org/packages/50/84/b2a56e2105bd11ebf9f0b93abddd748e1a78d592819099359aa98134a8bf/sqlalchemy-2.0.49-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:fb37f15714ec2652d574f021d479e78cd4eb9d04396dca36568fdfffb3487982", size = 3338976, upload-time = "2026-04-03T17:07:40Z" }, - { url = "https://files.pythonhosted.org/packages/2c/fa/65fcae2ed62f84ab72cf89536c7c3217a156e71a2c111b1305ab6f0690e2/sqlalchemy-2.0.49-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:3bb9ec6436a820a4c006aad1ac351f12de2f2dbdaad171692ee457a02429b672", size = 3351937, upload-time = "2026-04-03T17:12:23.374Z" }, - { url = "https://files.pythonhosted.org/packages/f8/2f/6fd118563572a7fe475925742eb6b3443b2250e346a0cc27d8d408e73773/sqlalchemy-2.0.49-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:8d6efc136f44a7e8bc8088507eaabbb8c2b55b3dbb63fe102c690da0ddebe55e", size = 3281646, upload-time = "2026-04-03T17:07:41.949Z" }, - { url = "https://files.pythonhosted.org/packages/c5/d7/410f4a007c65275b9cf82354adb4bb8ba587b176d0a6ee99caa16fe638f8/sqlalchemy-2.0.49-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:e06e617e3d4fd9e51d385dfe45b077a41e9d1b033a7702551e3278ac597dc750", size = 3316695, upload-time = "2026-04-03T17:12:25.642Z" }, - { url = "https://files.pythonhosted.org/packages/d9/95/81f594aa60ded13273a844539041ccf1e66c5a7bed0a8e27810a3b52d522/sqlalchemy-2.0.49-cp312-cp312-win32.whl", hash = "sha256:83101a6930332b87653886c01d1ee7e294b1fe46a07dd9a2d2b4f91bcc88eec0", size = 2117483, upload-time = "2026-04-03T17:05:40.896Z" }, - { url = "https://files.pythonhosted.org/packages/47/9e/fd90114059175cac64e4fafa9bf3ac20584384d66de40793ae2e2f26f3bb/sqlalchemy-2.0.49-cp312-cp312-win_amd64.whl", hash = "sha256:618a308215b6cececb6240b9abde545e3acdabac7ae3e1d4e666896bf5ba44b4", size = 2144494, upload-time = "2026-04-03T17:05:42.282Z" }, - { url = "https://files.pythonhosted.org/packages/ae/81/81755f50eb2478eaf2049728491d4ea4f416c1eb013338682173259efa09/sqlalchemy-2.0.49-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:df2d441bacf97022e81ad047e1597552eb3f83ca8a8f1a1fdd43cd7fe3898120", size = 2154547, upload-time = "2026-04-03T16:53:08.64Z" }, - { url = "https://files.pythonhosted.org/packages/a2/bc/3494270da80811d08bcfa247404292428c4fe16294932bce5593f215cad9/sqlalchemy-2.0.49-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8e20e511dc15265fb433571391ba313e10dd8ea7e509d51686a51313b4ac01a2", size = 3280782, upload-time = "2026-04-03T17:07:43.508Z" }, - { url = "https://files.pythonhosted.org/packages/cd/f5/038741f5e747a5f6ea3e72487211579d8cbea5eb9827a9cbd61d0108c4bd/sqlalchemy-2.0.49-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:47604cb2159f8bbd5a1ab48a714557156320f20871ee64d550d8bf2683d980d3", size = 3297156, upload-time = "2026-04-03T17:12:27.697Z" }, - { url = "https://files.pythonhosted.org/packages/88/50/a6af0ff9dc954b43a65ca9b5367334e45d99684c90a3d3413fc19a02d43c/sqlalchemy-2.0.49-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:22d8798819f86720bc646ab015baff5ea4c971d68121cb36e2ebc2ee43ead2b7", size = 3228832, upload-time = "2026-04-03T17:07:45.38Z" }, - { url = "https://files.pythonhosted.org/packages/bc/d1/5f6bdad8de0bf546fc74370939621396515e0cdb9067402d6ba1b8afbe9a/sqlalchemy-2.0.49-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:9b1c058c171b739e7c330760044803099c7fff11511e3ab3573e5327116a9c33", size = 3267000, upload-time = "2026-04-03T17:12:29.657Z" }, - { url = "https://files.pythonhosted.org/packages/f7/30/ad62227b4a9819a5e1c6abff77c0f614fa7c9326e5a3bdbee90f7139382b/sqlalchemy-2.0.49-cp313-cp313-win32.whl", hash = "sha256:a143af2ea6672f2af3f44ed8f9cd020e9cc34c56f0e8db12019d5d9ecf41cb3b", size = 2115641, upload-time = "2026-04-03T17:05:43.989Z" }, - { url = "https://files.pythonhosted.org/packages/17/3a/7215b1b7d6d49dc9a87211be44562077f5f04f9bb5a59552c1c8e2d98173/sqlalchemy-2.0.49-cp313-cp313-win_amd64.whl", hash = "sha256:12b04d1db2663b421fe072d638a138460a51d5a862403295671c4f3987fb9148", size = 2141498, upload-time = "2026-04-03T17:05:45.7Z" }, - { url = "https://files.pythonhosted.org/packages/28/4b/52a0cb2687a9cd1648252bb257be5a1ba2c2ded20ba695c65756a55a15a4/sqlalchemy-2.0.49-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:24bd94bb301ec672d8f0623eba9226cc90d775d25a0c92b5f8e4965d7f3a1518", size = 3560807, upload-time = "2026-04-03T16:58:31.666Z" }, - { url = "https://files.pythonhosted.org/packages/8c/d8/fda95459204877eed0458550d6c7c64c98cc50c2d8d618026737de9ed41a/sqlalchemy-2.0.49-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a51d3db74ba489266ef55c7a4534eb0b8db9a326553df481c11e5d7660c8364d", size = 3527481, upload-time = "2026-04-03T17:06:00.155Z" }, - { url = "https://files.pythonhosted.org/packages/ff/0a/2aac8b78ac6487240cf7afef8f203ca783e8796002dc0cf65c4ee99ff8bb/sqlalchemy-2.0.49-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:55250fe61d6ebfd6934a272ee16ef1244e0f16b7af6cd18ab5b1fc9f08631db0", size = 3468565, upload-time = "2026-04-03T16:58:33.414Z" }, - { url = "https://files.pythonhosted.org/packages/a5/3d/ce71cfa82c50a373fd2148b3c870be05027155ce791dc9a5dcf439790b8b/sqlalchemy-2.0.49-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:46796877b47034b559a593d7e4b549aba151dae73f9e78212a3478161c12ab08", size = 3477769, upload-time = "2026-04-03T17:06:02.787Z" }, - { url = "https://files.pythonhosted.org/packages/d5/e8/0a9f5c1f7c6f9ca480319bf57c2d7423f08d31445974167a27d14483c948/sqlalchemy-2.0.49-cp313-cp313t-win32.whl", hash = "sha256:9c4969a86e41454f2858256c39bdfb966a20961e9b58bf8749b65abf447e9a8d", size = 2143319, upload-time = "2026-04-03T17:02:04.328Z" }, - { url = "https://files.pythonhosted.org/packages/0e/51/fb5240729fbec73006e137c4f7a7918ffd583ab08921e6ff81a999d6517a/sqlalchemy-2.0.49-cp313-cp313t-win_amd64.whl", hash = "sha256:b9870d15ef00e4d0559ae10ee5bc71b654d1f20076dbe8bc7ed19b4c0625ceba", size = 2175104, upload-time = "2026-04-03T17:02:05.989Z" }, - { url = "https://files.pythonhosted.org/packages/55/33/bf28f618c0a9597d14e0b9ee7d1e0622faff738d44fe986ee287cdf1b8d0/sqlalchemy-2.0.49-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:233088b4b99ebcbc5258c755a097aa52fbf90727a03a5a80781c4b9c54347a2e", size = 2156356, upload-time = "2026-04-03T16:53:09.914Z" }, - { url = "https://files.pythonhosted.org/packages/d1/a7/5f476227576cb8644650eff68cc35fa837d3802b997465c96b8340ced1e2/sqlalchemy-2.0.49-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:57ca426a48eb2c682dae8204cd89ea8ab7031e2675120a47924fabc7caacbc2a", size = 3276486, upload-time = "2026-04-03T17:07:46.9Z" }, - { url = "https://files.pythonhosted.org/packages/2e/84/efc7c0bf3a1c5eef81d397f6fddac855becdbb11cb38ff957888603014a7/sqlalchemy-2.0.49-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:685e93e9c8f399b0c96a624799820176312f5ceef958c0f88215af4013d29066", size = 3281479, upload-time = "2026-04-03T17:12:32.226Z" }, - { url = "https://files.pythonhosted.org/packages/91/68/bb406fa4257099c67bd75f3f2261b129c63204b9155de0d450b37f004698/sqlalchemy-2.0.49-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:9e0400fa22f79acc334d9a6b185dc00a44a8e6578aa7e12d0ddcd8434152b187", size = 3226269, upload-time = "2026-04-03T17:07:48.678Z" }, - { url = "https://files.pythonhosted.org/packages/67/84/acb56c00cca9f251f437cb49e718e14f7687505749ea9255d7bd8158a6df/sqlalchemy-2.0.49-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:a05977bffe9bffd2229f477fa75eabe3192b1b05f408961d1bebff8d1cd4d401", size = 3248260, upload-time = "2026-04-03T17:12:34.381Z" }, - { url = "https://files.pythonhosted.org/packages/56/19/6a20ea25606d1efd7bd1862149bb2a22d1451c3f851d23d887969201633f/sqlalchemy-2.0.49-cp314-cp314-win32.whl", hash = "sha256:0f2fa354ba106eafff2c14b0cc51f22801d1e8b2e4149342023bd6f0955de5f5", size = 2118463, upload-time = "2026-04-03T17:05:47.093Z" }, - { url = "https://files.pythonhosted.org/packages/cf/4f/8297e4ed88e80baa1f5aa3c484a0ee29ef3c69c7582f206c916973b75057/sqlalchemy-2.0.49-cp314-cp314-win_amd64.whl", hash = "sha256:77641d299179c37b89cf2343ca9972c88bb6eef0d5fc504a2f86afd15cd5adf5", size = 2144204, upload-time = "2026-04-03T17:05:48.694Z" }, - { url = "https://files.pythonhosted.org/packages/1f/33/95e7216df810c706e0cd3655a778604bbd319ed4f43333127d465a46862d/sqlalchemy-2.0.49-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c1dc3368794d522f43914e03312202523cc89692f5389c32bea0233924f8d977", size = 3565474, upload-time = "2026-04-03T16:58:35.128Z" }, - { url = "https://files.pythonhosted.org/packages/0c/a4/ed7b18d8ccf7f954a83af6bb73866f5bc6f5636f44c7731fbb741f72cc4f/sqlalchemy-2.0.49-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:7c821c47ecfe05cc32140dcf8dc6fd5d21971c86dbd56eabfe5ba07a64910c01", size = 3530567, upload-time = "2026-04-03T17:06:04.587Z" }, - { url = "https://files.pythonhosted.org/packages/73/a3/20faa869c7e21a827c4a2a42b41353a54b0f9f5e96df5087629c306df71e/sqlalchemy-2.0.49-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:9c04bff9a5335eb95c6ecf1c117576a0aa560def274876fd156cfe5510fccc61", size = 3474282, upload-time = "2026-04-03T16:58:37.131Z" }, - { url = "https://files.pythonhosted.org/packages/b7/50/276b9a007aa0764304ad467eceb70b04822dc32092492ee5f322d559a4dc/sqlalchemy-2.0.49-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:7f605a456948c35260e7b2a39f8952a26f077fd25653c37740ed186b90aaa68a", size = 3480406, upload-time = "2026-04-03T17:06:07.176Z" }, - { url = "https://files.pythonhosted.org/packages/e5/c3/c80fcdb41905a2df650c2a3e0337198b6848876e63d66fe9188ef9003d24/sqlalchemy-2.0.49-cp314-cp314t-win32.whl", hash = "sha256:6270d717b11c5476b0cbb21eedc8d4dbb7d1a956fd6c15a23e96f197a6193158", size = 2149151, upload-time = "2026-04-03T17:02:07.281Z" }, - { url = "https://files.pythonhosted.org/packages/05/52/9f1a62feab6ed368aff068524ff414f26a6daebc7361861035ae00b05530/sqlalchemy-2.0.49-cp314-cp314t-win_amd64.whl", hash = "sha256:275424295f4256fd301744b8f335cff367825d270f155d522b30c7bf49903ee7", size = 2184178, upload-time = "2026-04-03T17:02:08.623Z" }, - { url = "https://files.pythonhosted.org/packages/e5/30/8519fdde58a7bdf155b714359791ad1dc018b47d60269d5d160d311fdc36/sqlalchemy-2.0.49-py3-none-any.whl", hash = "sha256:ec44cfa7ef1a728e88ad41674de50f6db8cfdb3e2af84af86e0041aaf02d43d0", size = 1942158, upload-time = "2026-04-03T16:53:44.135Z" }, +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.17.3" +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/6b/1c/c7d28d88e8dd9a67be006a40135f05cbdf5a0f5f79bc51bb692f54432cf1/sqlalchemy_spanner-1.17.3.tar.gz", hash = "sha256:ea829d8223c404f19f854c4c2dbf6bf2ee48fb1347caa258f03e88071f3afa22", size = 82842, upload-time = "2026-03-23T22:44:01.25Z" } +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/f3/43/cf21f3e70a8aa9e721fb557bd1459528906f0d9726b2ce642cd757fe592b/sqlalchemy_spanner-1.17.3-py3-none-any.whl", hash = "sha256:b0a13d2cae3bb0ee5aac898c44d22f56ec3edfc7780dd7d165d51f676590daf3", size = 31925, upload-time = "2026-03-23T22:43:33.214Z" }, + { 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]] @@ -5323,15 +5544,15 @@ wheels = [ [[package]] name = "sse-starlette" -version = "3.3.4" +version = "3.4.4" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "anyio" }, { name = "starlette" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/26/8c/f9290339ef6d79badbc010f067cd769d6601ec11a57d78569c683fb4dd87/sse_starlette-3.3.4.tar.gz", hash = "sha256:aaf92fc067af8a5427192895ac028e947b484ac01edbc3caf00e7e7137c7bef1", size = 32427, upload-time = "2026-03-29T09:00:23.307Z" } +sdist = { url = "https://files.pythonhosted.org/packages/f7/2b/58abc2d1fd397e7dde08e947e05c884d8ef2f78d5e2588c17a12d42d6994/sse_starlette-3.4.4.tar.gz", hash = "sha256:07e0fa0460138baf25cdd5fb28683472c3995dc1642225191b3832d62526bcb0", size = 31819, upload-time = "2026-05-12T17:37:17.019Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/f8/7f/3de5402f39890ac5660b86bcf5c03f9d855dad5c4ed764866d7b592b46fd/sse_starlette-3.3.4-py3-none-any.whl", hash = "sha256:84bb06e58939a8b38d8341f1bc9792f06c2b53f48c608dd207582b664fc8f3c1", size = 14330, upload-time = "2026-03-29T09:00:21.846Z" }, + { url = "https://files.pythonhosted.org/packages/dc/67/805710444ea8cc75fbf70b920ed431a560c4bf9c57f7d5a3117213189399/sse_starlette-3.4.4-py3-none-any.whl", hash = "sha256:3f4dd50d8aed2771a091f3a83000323fc3844541c16b4fe585ae2420cc6df973", size = 16514, upload-time = "2026-05-12T17:37:15.601Z" }, ] [[package]] @@ -5349,7 +5570,7 @@ wheels = [ [[package]] name = "strands-agents" -version = "1.39.0" +version = "1.43.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "boto3" }, @@ -5365,14 +5586,14 @@ dependencies = [ { name = "typing-extensions" }, { name = "watchdog" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/d6/5b/e267a7dab0b4a6d39133c9c0c516f93f33483e29f39e05c03b755f993ef6/strands_agents-1.39.0.tar.gz", hash = "sha256:efff5914323b8b4b472ca3f13c7115a5746935b00bc86dacc40a5d1ab1242817", size = 873258, upload-time = "2026-05-08T13:27:19.661Z" } +sdist = { url = "https://files.pythonhosted.org/packages/06/e7/ba9faab3ebaa63325ef03b61a74806bc5ccb6b626428541f898b4f33fb21/strands_agents-1.43.0.tar.gz", hash = "sha256:379ad28af36d9306c7ae3f43702b086082193e8eafa53de051c9ce91496178ac", size = 922114, upload-time = "2026-06-12T14:27:57.069Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/95/41/d054b5a5f54175eb4e775d1e408e169439eba6be63e9e8f2e77ff44e38fc/strands_agents-1.39.0-py3-none-any.whl", hash = "sha256:7369dbfc6be29f59483a6183f5aacf0bdd0e7e5973b4b70f8d0e663880d42f79", size = 430272, upload-time = "2026-05-08T13:27:18.088Z" }, + { url = "https://files.pythonhosted.org/packages/68/35/29fc4c02293aef54dfa59a5516419153a9fb15a4857ecf8f2ce8638ae3dd/strands_agents-1.43.0-py3-none-any.whl", hash = "sha256:b934f74fe1b7103d438684b69ee044223a5bb407db2ccd2b55e5da6bf639d31b", size = 472542, upload-time = "2026-06-12T14:27:55.55Z" }, ] [[package]] name = "strands-agents-tools" -version = "0.5.2" +version = "0.8.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "aiohttp" }, @@ -5393,9 +5614,9 @@ dependencies = [ { name = "tzdata", marker = "sys_platform == 'win32'" }, { name = "watchdog" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/63/32/710a49ffd32b0a232ec1731620ee6105c045e9a77ecee1f3ecaa1a80a6cd/strands_agents_tools-0.5.2.tar.gz", hash = "sha256:96763c8ae75933c5dd327cca87561f573aed720c9c0f3d17fd20835910d11381", size = 483164, upload-time = "2026-04-30T17:08:13.151Z" } +sdist = { url = "https://files.pythonhosted.org/packages/d4/74/aed74502a19a18ce1ddcd56e1dc4a0de6e9f2cb6babcc9f2d1969f253c0b/strands_agents_tools-0.8.0.tar.gz", hash = "sha256:fd93104d2d8dcff780505e8a2fca0cb2fa7a3da6bae01369073b60da0e08c5aa", size = 490638, upload-time = "2026-06-03T19:20:03.872Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/59/ef/fe73b6d25d095784d2e1f6f33419265e796143100fb2f32a6e86f8ae68af/strands_agents_tools-0.5.2-py3-none-any.whl", hash = "sha256:8f85e4cb28d9411e62e1f159aa7e300d3a0f4b1d2b878a7cdfd5d746d9333343", size = 316178, upload-time = "2026-04-30T17:08:11.416Z" }, + { url = "https://files.pythonhosted.org/packages/0a/37/9f611363451cf38f912c7551b73308339e6af54bf1b5e9a3e8efc7ae0972/strands_agents_tools-0.8.0-py3-none-any.whl", hash = "sha256:7446ae423794b6f886fb36e1a0f8a62fe0546978c18b805e6f50dcdddee1559e", size = 319602, upload-time = "2026-06-03T19:20:01.92Z" }, ] [[package]] @@ -5583,93 +5804,90 @@ wheels = [ [[package]] name = "tiktoken" -version = "0.12.0" +version = "0.13.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "regex" }, { name = "requests" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/7d/ab/4d017d0f76ec3171d469d80fc03dfbb4e48a4bcaddaa831b31d526f05edc/tiktoken-0.12.0.tar.gz", hash = "sha256:b18ba7ee2b093863978fcb14f74b3707cdc8d4d4d3836853ce7ec60772139931", size = 37806, upload-time = "2025-10-06T20:22:45.419Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/89/b3/2cb7c17b6c4cf8ca983204255d3f1d95eda7213e247e6947a0ee2c747a2c/tiktoken-0.12.0-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:3de02f5a491cfd179aec916eddb70331814bd6bf764075d39e21d5862e533970", size = 1051991, upload-time = "2025-10-06T20:21:34.098Z" }, - { url = "https://files.pythonhosted.org/packages/27/0f/df139f1df5f6167194ee5ab24634582ba9a1b62c6b996472b0277ec80f66/tiktoken-0.12.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:b6cfb6d9b7b54d20af21a912bfe63a2727d9cfa8fbda642fd8322c70340aad16", size = 995798, upload-time = "2025-10-06T20:21:35.579Z" }, - { url = "https://files.pythonhosted.org/packages/ef/5d/26a691f28ab220d5edc09b9b787399b130f24327ef824de15e5d85ef21aa/tiktoken-0.12.0-cp310-cp310-manylinux_2_28_aarch64.whl", hash = "sha256:cde24cdb1b8a08368f709124f15b36ab5524aac5fa830cc3fdce9c03d4fb8030", size = 1129865, upload-time = "2025-10-06T20:21:36.675Z" }, - { url = "https://files.pythonhosted.org/packages/b2/94/443fab3d4e5ebecac895712abd3849b8da93b7b7dec61c7db5c9c7ebe40c/tiktoken-0.12.0-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:6de0da39f605992649b9cfa6f84071e3f9ef2cec458d08c5feb1b6f0ff62e134", size = 1152856, upload-time = "2025-10-06T20:21:37.873Z" }, - { url = "https://files.pythonhosted.org/packages/54/35/388f941251b2521c70dd4c5958e598ea6d2c88e28445d2fb8189eecc1dfc/tiktoken-0.12.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:6faa0534e0eefbcafaccb75927a4a380463a2eaa7e26000f0173b920e98b720a", size = 1195308, upload-time = "2025-10-06T20:21:39.577Z" }, - { url = "https://files.pythonhosted.org/packages/f8/00/c6681c7f833dd410576183715a530437a9873fa910265817081f65f9105f/tiktoken-0.12.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:82991e04fc860afb933efb63957affc7ad54f83e2216fe7d319007dab1ba5892", size = 1255697, upload-time = "2025-10-06T20:21:41.154Z" }, - { url = "https://files.pythonhosted.org/packages/5f/d2/82e795a6a9bafa034bf26a58e68fe9a89eeaaa610d51dbeb22106ba04f0a/tiktoken-0.12.0-cp310-cp310-win_amd64.whl", hash = "sha256:6fb2995b487c2e31acf0a9e17647e3b242235a20832642bb7a9d1a181c0c1bb1", size = 879375, upload-time = "2025-10-06T20:21:43.201Z" }, - { url = "https://files.pythonhosted.org/packages/de/46/21ea696b21f1d6d1efec8639c204bdf20fde8bafb351e1355c72c5d7de52/tiktoken-0.12.0-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:6e227c7f96925003487c33b1b32265fad2fbcec2b7cf4817afb76d416f40f6bb", size = 1051565, upload-time = "2025-10-06T20:21:44.566Z" }, - { url = "https://files.pythonhosted.org/packages/c9/d9/35c5d2d9e22bb2a5f74ba48266fb56c63d76ae6f66e02feb628671c0283e/tiktoken-0.12.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:c06cf0fcc24c2cb2adb5e185c7082a82cba29c17575e828518c2f11a01f445aa", size = 995284, upload-time = "2025-10-06T20:21:45.622Z" }, - { url = "https://files.pythonhosted.org/packages/01/84/961106c37b8e49b9fdcf33fe007bb3a8fdcc380c528b20cc7fbba80578b8/tiktoken-0.12.0-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:f18f249b041851954217e9fd8e5c00b024ab2315ffda5ed77665a05fa91f42dc", size = 1129201, upload-time = "2025-10-06T20:21:47.074Z" }, - { url = "https://files.pythonhosted.org/packages/6a/d0/3d9275198e067f8b65076a68894bb52fd253875f3644f0a321a720277b8a/tiktoken-0.12.0-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:47a5bc270b8c3db00bb46ece01ef34ad050e364b51d406b6f9730b64ac28eded", size = 1152444, upload-time = "2025-10-06T20:21:48.139Z" }, - { url = "https://files.pythonhosted.org/packages/78/db/a58e09687c1698a7c592e1038e01c206569b86a0377828d51635561f8ebf/tiktoken-0.12.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:508fa71810c0efdcd1b898fda574889ee62852989f7c1667414736bcb2b9a4bd", size = 1195080, upload-time = "2025-10-06T20:21:49.246Z" }, - { url = "https://files.pythonhosted.org/packages/9e/1b/a9e4d2bf91d515c0f74afc526fd773a812232dd6cda33ebea7f531202325/tiktoken-0.12.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:a1af81a6c44f008cba48494089dd98cccb8b313f55e961a52f5b222d1e507967", size = 1255240, upload-time = "2025-10-06T20:21:50.274Z" }, - { url = "https://files.pythonhosted.org/packages/9d/15/963819345f1b1fb0809070a79e9dd96938d4ca41297367d471733e79c76c/tiktoken-0.12.0-cp311-cp311-win_amd64.whl", hash = "sha256:3e68e3e593637b53e56f7237be560f7a394451cb8c11079755e80ae64b9e6def", size = 879422, upload-time = "2025-10-06T20:21:51.734Z" }, - { url = "https://files.pythonhosted.org/packages/a4/85/be65d39d6b647c79800fd9d29241d081d4eeb06271f383bb87200d74cf76/tiktoken-0.12.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:b97f74aca0d78a1ff21b8cd9e9925714c15a9236d6ceacf5c7327c117e6e21e8", size = 1050728, upload-time = "2025-10-06T20:21:52.756Z" }, - { url = "https://files.pythonhosted.org/packages/4a/42/6573e9129bc55c9bf7300b3a35bef2c6b9117018acca0dc760ac2d93dffe/tiktoken-0.12.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2b90f5ad190a4bb7c3eb30c5fa32e1e182ca1ca79f05e49b448438c3e225a49b", size = 994049, upload-time = "2025-10-06T20:21:53.782Z" }, - { url = "https://files.pythonhosted.org/packages/66/c5/ed88504d2f4a5fd6856990b230b56d85a777feab84e6129af0822f5d0f70/tiktoken-0.12.0-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:65b26c7a780e2139e73acc193e5c63ac754021f160df919add909c1492c0fb37", size = 1129008, upload-time = "2025-10-06T20:21:54.832Z" }, - { url = "https://files.pythonhosted.org/packages/f4/90/3dae6cc5436137ebd38944d396b5849e167896fc2073da643a49f372dc4f/tiktoken-0.12.0-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:edde1ec917dfd21c1f2f8046b86348b0f54a2c0547f68149d8600859598769ad", size = 1152665, upload-time = "2025-10-06T20:21:56.129Z" }, - { url = "https://files.pythonhosted.org/packages/a3/fe/26df24ce53ffde419a42f5f53d755b995c9318908288c17ec3f3448313a3/tiktoken-0.12.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:35a2f8ddd3824608b3d650a000c1ef71f730d0c56486845705a8248da00f9fe5", size = 1194230, upload-time = "2025-10-06T20:21:57.546Z" }, - { url = "https://files.pythonhosted.org/packages/20/cc/b064cae1a0e9fac84b0d2c46b89f4e57051a5f41324e385d10225a984c24/tiktoken-0.12.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:83d16643edb7fa2c99eff2ab7733508aae1eebb03d5dfc46f5565862810f24e3", size = 1254688, upload-time = "2025-10-06T20:21:58.619Z" }, - { url = "https://files.pythonhosted.org/packages/81/10/b8523105c590c5b8349f2587e2fdfe51a69544bd5a76295fc20f2374f470/tiktoken-0.12.0-cp312-cp312-win_amd64.whl", hash = "sha256:ffc5288f34a8bc02e1ea7047b8d041104791d2ddbf42d1e5fa07822cbffe16bd", size = 878694, upload-time = "2025-10-06T20:21:59.876Z" }, - { url = "https://files.pythonhosted.org/packages/00/61/441588ee21e6b5cdf59d6870f86beb9789e532ee9718c251b391b70c68d6/tiktoken-0.12.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:775c2c55de2310cc1bc9a3ad8826761cbdc87770e586fd7b6da7d4589e13dab3", size = 1050802, upload-time = "2025-10-06T20:22:00.96Z" }, - { url = "https://files.pythonhosted.org/packages/1f/05/dcf94486d5c5c8d34496abe271ac76c5b785507c8eae71b3708f1ad9b45a/tiktoken-0.12.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:a01b12f69052fbe4b080a2cfb867c4de12c704b56178edf1d1d7b273561db160", size = 993995, upload-time = "2025-10-06T20:22:02.788Z" }, - { url = "https://files.pythonhosted.org/packages/a0/70/5163fe5359b943f8db9946b62f19be2305de8c3d78a16f629d4165e2f40e/tiktoken-0.12.0-cp313-cp313-manylinux_2_28_aarch64.whl", hash = "sha256:01d99484dc93b129cd0964f9d34eee953f2737301f18b3c7257bf368d7615baa", size = 1128948, upload-time = "2025-10-06T20:22:03.814Z" }, - { url = "https://files.pythonhosted.org/packages/0c/da/c028aa0babf77315e1cef357d4d768800c5f8a6de04d0eac0f377cb619fa/tiktoken-0.12.0-cp313-cp313-manylinux_2_28_x86_64.whl", hash = "sha256:4a1a4fcd021f022bfc81904a911d3df0f6543b9e7627b51411da75ff2fe7a1be", size = 1151986, upload-time = "2025-10-06T20:22:05.173Z" }, - { url = "https://files.pythonhosted.org/packages/a0/5a/886b108b766aa53e295f7216b509be95eb7d60b166049ce2c58416b25f2a/tiktoken-0.12.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:981a81e39812d57031efdc9ec59fa32b2a5a5524d20d4776574c4b4bd2e9014a", size = 1194222, upload-time = "2025-10-06T20:22:06.265Z" }, - { url = "https://files.pythonhosted.org/packages/f4/f8/4db272048397636ac7a078d22773dd2795b1becee7bc4922fe6207288d57/tiktoken-0.12.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:9baf52f84a3f42eef3ff4e754a0db79a13a27921b457ca9832cf944c6be4f8f3", size = 1255097, upload-time = "2025-10-06T20:22:07.403Z" }, - { url = "https://files.pythonhosted.org/packages/8e/32/45d02e2e0ea2be3a9ed22afc47d93741247e75018aac967b713b2941f8ea/tiktoken-0.12.0-cp313-cp313-win_amd64.whl", hash = "sha256:b8a0cd0c789a61f31bf44851defbd609e8dd1e2c8589c614cc1060940ef1f697", size = 879117, upload-time = "2025-10-06T20:22:08.418Z" }, - { url = "https://files.pythonhosted.org/packages/ce/76/994fc868f88e016e6d05b0da5ac24582a14c47893f4474c3e9744283f1d5/tiktoken-0.12.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:d5f89ea5680066b68bcb797ae85219c72916c922ef0fcdd3480c7d2315ffff16", size = 1050309, upload-time = "2025-10-06T20:22:10.939Z" }, - { url = "https://files.pythonhosted.org/packages/f6/b8/57ef1456504c43a849821920d582a738a461b76a047f352f18c0b26c6516/tiktoken-0.12.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:b4e7ed1c6a7a8a60a3230965bdedba8cc58f68926b835e519341413370e0399a", size = 993712, upload-time = "2025-10-06T20:22:12.115Z" }, - { url = "https://files.pythonhosted.org/packages/72/90/13da56f664286ffbae9dbcfadcc625439142675845baa62715e49b87b68b/tiktoken-0.12.0-cp313-cp313t-manylinux_2_28_aarch64.whl", hash = "sha256:fc530a28591a2d74bce821d10b418b26a094bf33839e69042a6e86ddb7a7fb27", size = 1128725, upload-time = "2025-10-06T20:22:13.541Z" }, - { url = "https://files.pythonhosted.org/packages/05/df/4f80030d44682235bdaecd7346c90f67ae87ec8f3df4a3442cb53834f7e4/tiktoken-0.12.0-cp313-cp313t-manylinux_2_28_x86_64.whl", hash = "sha256:06a9f4f49884139013b138920a4c393aa6556b2f8f536345f11819389c703ebb", size = 1151875, upload-time = "2025-10-06T20:22:14.559Z" }, - { url = "https://files.pythonhosted.org/packages/22/1f/ae535223a8c4ef4c0c1192e3f9b82da660be9eb66b9279e95c99288e9dab/tiktoken-0.12.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:04f0e6a985d95913cabc96a741c5ffec525a2c72e9df086ff17ebe35985c800e", size = 1194451, upload-time = "2025-10-06T20:22:15.545Z" }, - { url = "https://files.pythonhosted.org/packages/78/a7/f8ead382fce0243cb625c4f266e66c27f65ae65ee9e77f59ea1653b6d730/tiktoken-0.12.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:0ee8f9ae00c41770b5f9b0bb1235474768884ae157de3beb5439ca0fd70f3e25", size = 1253794, upload-time = "2025-10-06T20:22:16.624Z" }, - { url = "https://files.pythonhosted.org/packages/93/e0/6cc82a562bc6365785a3ff0af27a2a092d57c47d7a81d9e2295d8c36f011/tiktoken-0.12.0-cp313-cp313t-win_amd64.whl", hash = "sha256:dc2dd125a62cb2b3d858484d6c614d136b5b848976794edfb63688d539b8b93f", size = 878777, upload-time = "2025-10-06T20:22:18.036Z" }, - { url = "https://files.pythonhosted.org/packages/72/05/3abc1db5d2c9aadc4d2c76fa5640134e475e58d9fbb82b5c535dc0de9b01/tiktoken-0.12.0-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:a90388128df3b3abeb2bfd1895b0681412a8d7dc644142519e6f0a97c2111646", size = 1050188, upload-time = "2025-10-06T20:22:19.563Z" }, - { url = "https://files.pythonhosted.org/packages/e3/7b/50c2f060412202d6c95f32b20755c7a6273543b125c0985d6fa9465105af/tiktoken-0.12.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:da900aa0ad52247d8794e307d6446bd3cdea8e192769b56276695d34d2c9aa88", size = 993978, upload-time = "2025-10-06T20:22:20.702Z" }, - { url = "https://files.pythonhosted.org/packages/14/27/bf795595a2b897e271771cd31cb847d479073497344c637966bdf2853da1/tiktoken-0.12.0-cp314-cp314-manylinux_2_28_aarch64.whl", hash = "sha256:285ba9d73ea0d6171e7f9407039a290ca77efcdb026be7769dccc01d2c8d7fff", size = 1129271, upload-time = "2025-10-06T20:22:22.06Z" }, - { url = "https://files.pythonhosted.org/packages/f5/de/9341a6d7a8f1b448573bbf3425fa57669ac58258a667eb48a25dfe916d70/tiktoken-0.12.0-cp314-cp314-manylinux_2_28_x86_64.whl", hash = "sha256:d186a5c60c6a0213f04a7a802264083dea1bbde92a2d4c7069e1a56630aef830", size = 1151216, upload-time = "2025-10-06T20:22:23.085Z" }, - { url = "https://files.pythonhosted.org/packages/75/0d/881866647b8d1be4d67cb24e50d0c26f9f807f994aa1510cb9ba2fe5f612/tiktoken-0.12.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:604831189bd05480f2b885ecd2d1986dc7686f609de48208ebbbddeea071fc0b", size = 1194860, upload-time = "2025-10-06T20:22:24.602Z" }, - { url = "https://files.pythonhosted.org/packages/b3/1e/b651ec3059474dab649b8d5b69f5c65cd8fcd8918568c1935bd4136c9392/tiktoken-0.12.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:8f317e8530bb3a222547b85a58583238c8f74fd7a7408305f9f63246d1a0958b", size = 1254567, upload-time = "2025-10-06T20:22:25.671Z" }, - { url = "https://files.pythonhosted.org/packages/80/57/ce64fd16ac390fafde001268c364d559447ba09b509181b2808622420eec/tiktoken-0.12.0-cp314-cp314-win_amd64.whl", hash = "sha256:399c3dd672a6406719d84442299a490420b458c44d3ae65516302a99675888f3", size = 921067, upload-time = "2025-10-06T20:22:26.753Z" }, - { url = "https://files.pythonhosted.org/packages/ac/a4/72eed53e8976a099539cdd5eb36f241987212c29629d0a52c305173e0a68/tiktoken-0.12.0-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:c2c714c72bc00a38ca969dae79e8266ddec999c7ceccd603cc4f0d04ccd76365", size = 1050473, upload-time = "2025-10-06T20:22:27.775Z" }, - { url = "https://files.pythonhosted.org/packages/e6/d7/0110b8f54c008466b19672c615f2168896b83706a6611ba6e47313dbc6e9/tiktoken-0.12.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:cbb9a3ba275165a2cb0f9a83f5d7025afe6b9d0ab01a22b50f0e74fee2ad253e", size = 993855, upload-time = "2025-10-06T20:22:28.799Z" }, - { url = "https://files.pythonhosted.org/packages/5f/77/4f268c41a3957c418b084dd576ea2fad2e95da0d8e1ab705372892c2ca22/tiktoken-0.12.0-cp314-cp314t-manylinux_2_28_aarch64.whl", hash = "sha256:dfdfaa5ffff8993a3af94d1125870b1d27aed7cb97aa7eb8c1cefdbc87dbee63", size = 1129022, upload-time = "2025-10-06T20:22:29.981Z" }, - { url = "https://files.pythonhosted.org/packages/4e/2b/fc46c90fe5028bd094cd6ee25a7db321cb91d45dc87531e2bdbb26b4867a/tiktoken-0.12.0-cp314-cp314t-manylinux_2_28_x86_64.whl", hash = "sha256:584c3ad3d0c74f5269906eb8a659c8bfc6144a52895d9261cdaf90a0ae5f4de0", size = 1150736, upload-time = "2025-10-06T20:22:30.996Z" }, - { url = "https://files.pythonhosted.org/packages/28/c0/3c7a39ff68022ddfd7d93f3337ad90389a342f761c4d71de99a3ccc57857/tiktoken-0.12.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:54c891b416a0e36b8e2045b12b33dd66fb34a4fe7965565f1b482da50da3e86a", size = 1194908, upload-time = "2025-10-06T20:22:32.073Z" }, - { url = "https://files.pythonhosted.org/packages/ab/0d/c1ad6f4016a3968c048545f5d9b8ffebf577774b2ede3e2e352553b685fe/tiktoken-0.12.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:5edb8743b88d5be814b1a8a8854494719080c28faaa1ccbef02e87354fe71ef0", size = 1253706, upload-time = "2025-10-06T20:22:33.385Z" }, - { url = "https://files.pythonhosted.org/packages/af/df/c7891ef9d2712ad774777271d39fdef63941ffba0a9d59b7ad1fd2765e57/tiktoken-0.12.0-cp314-cp314t-win_amd64.whl", hash = "sha256:f61c0aea5565ac82e2ec50a05e02a6c44734e91b51c10510b084ea1b8e633a71", size = 920667, upload-time = "2025-10-06T20:22:34.444Z" }, +sdist = { url = "https://files.pythonhosted.org/packages/e4/e5/5f3cb2159769d0f4324c0e9e87f9de3c4b1cd45848a96b2eb3566ad5ca77/tiktoken-0.13.0.tar.gz", hash = "sha256:c9435714c3a84c2319499de9a300c0e604449dd0799ff246458b3bb6a7f433c1", size = 38986, upload-time = "2026-05-15T04:51:27.153Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/38/e3/03c90dadcf5b3f82b83cee9adee60ef666b329c654f58c066af44eae0287/tiktoken-0.13.0-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:47b1df8d73390a24f94980c75158cdd5c56d256f16d55f30cb49c230caba9ba4", size = 1036627, upload-time = "2026-05-15T04:50:11.229Z" }, + { url = "https://files.pythonhosted.org/packages/5e/30/760463e5b2e8ad2bc229ae0a17ecb06727b6cbc094f08d8f65844315632e/tiktoken-0.13.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:7d40c6c5aab171dcd6eb8455bc567bde404bb9def60cdb8c1299cc782b242bb9", size = 984699, upload-time = "2026-05-15T04:50:12.874Z" }, + { url = "https://files.pythonhosted.org/packages/de/8a/8895f342a6b6aabd1a358e672f6f077b3ae51d0c63ca605d142db3bcd8ab/tiktoken-0.13.0-cp310-cp310-manylinux_2_28_aarch64.whl", hash = "sha256:9b842981fa91accdffd48ff6408a977b7a91c3fbda55d353c3c68114d5c9d69e", size = 1118690, upload-time = "2026-05-15T04:50:14.234Z" }, + { url = "https://files.pythonhosted.org/packages/51/e0/92557768fb0801f0d9dd9243cb9b6d342900b05e4b1006d4771f49ce233e/tiktoken-0.13.0-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:ed5a30027cb4d8c7ca8b273d4766f3db3cf58fad9e9f3b1a68a351ffb54873d5", size = 1138423, upload-time = "2026-05-15T04:50:15.668Z" }, + { url = "https://files.pythonhosted.org/packages/8f/b9/a3d99feeedb032ffd09cd6652077f86bdee9a70dd0b990b2b272b445d4c3/tiktoken-0.13.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:7ab10f4a21c2999846940113f6dbd72e0fa06a24119feddd74cc47e85818e06d", size = 1185077, upload-time = "2026-05-15T04:50:17.19Z" }, + { url = "https://files.pythonhosted.org/packages/cc/93/bab868277d475dc6d2aaacd34cdd239c282f4908dcc8702e0a3311a8e032/tiktoken-0.13.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:a2937ad042d49d50eac6e1ba07c5661d4bd3942a5b1e0c0d08475c4df83676e1", size = 1241702, upload-time = "2026-05-15T04:50:18.772Z" }, + { url = "https://files.pythonhosted.org/packages/c3/16/27e9f7e0ed76e501cfefc9fb2112df4c7bf70ca96945b15ecb7615aac860/tiktoken-0.13.0-cp310-cp310-win_amd64.whl", hash = "sha256:44733b99bfd72b590cd0936b1c01b3b4dd73122db2d544bc1ceeb18a7678c910", size = 876565, upload-time = "2026-05-15T04:50:20.268Z" }, + { url = "https://files.pythonhosted.org/packages/1a/4c/1bc81f4cd53e827c4ee67ca951b5935724716049452d8dfa09b8b82372bb/tiktoken-0.13.0-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:7bfe1849caa65d1e1d9871817170ec497bbb7984e182012e1bdce72f66608cdb", size = 1036353, upload-time = "2026-05-15T04:50:21.757Z" }, + { url = "https://files.pythonhosted.org/packages/75/91/10b9c7076bc02c246c853201fdbbe300a4b8c5ed7b84c25f7403f4e32655/tiktoken-0.13.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:91c180fe255bd5a86d8316210d2833a1d4d33d026cd86a67812f4773743c8d26", size = 984644, upload-time = "2026-05-15T04:50:23.256Z" }, + { url = "https://files.pythonhosted.org/packages/4e/e4/fceae98015fab47fcd49b8bd7f46145bcd187a47e0add1e5378ed67ef980/tiktoken-0.13.0-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:059c8ecf554eb5b41e6e054ba467b871b03277d267dee7244380aca4359747d4", size = 1119261, upload-time = "2026-05-15T04:50:24.348Z" }, + { url = "https://files.pythonhosted.org/packages/f9/39/fe42ad00de01a8c4a49ad8649a2c8a316835a9cad5961b11d21eac0020a5/tiktoken-0.13.0-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:36217497eaffc158607a3b26f065300db2aefd43b115263f3b9688ce38146173", size = 1138253, upload-time = "2026-05-15T04:50:25.505Z" }, + { url = "https://files.pythonhosted.org/packages/03/c4/ccee1ecccca107e9a16efcecdeeb964c325305038554d466ece65b42338f/tiktoken-0.13.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:303f7d91b4fce3baddbcde05c139091d4caa5026ac7214c1dc7ff7a71ee429ff", size = 1185747, upload-time = "2026-05-15T04:50:27.02Z" }, + { url = "https://files.pythonhosted.org/packages/9d/03/cd0cba295522b91eb55c6b2704f1df895f8226cfe60ab10d4d51d0cc9e69/tiktoken-0.13.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:5d48843bee149630eb735a99e1f4a85b47308d21868ea63163f6e87768d3cfed", size = 1241265, upload-time = "2026-05-15T04:50:28.815Z" }, + { url = "https://files.pythonhosted.org/packages/7e/25/a10efd564402d82c2ff50d12057353ace447aa8007deceaa48641f63d35c/tiktoken-0.13.0-cp311-cp311-win_amd64.whl", hash = "sha256:fc1c44cd37b43fc46bae593129164f4f281e82ea116b57a85aa81bda57eafc94", size = 876509, upload-time = "2026-05-15T04:50:30.026Z" }, + { url = "https://files.pythonhosted.org/packages/85/8e/144bde4e01df66b34bb865557c7cd754ed08b036217ebd79c9db5e9048a9/tiktoken-0.13.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:32ac870a806cfb260a02d0cb70426aef02e038297f8ad50df5040bb5af360791", size = 1034888, upload-time = "2026-05-15T04:50:31.579Z" }, + { url = "https://files.pythonhosted.org/packages/36/18/d4ac9d20956cdebca04841316660ed584c2fecdc2b81722a28bc7ad3b1e4/tiktoken-0.13.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:4d9980f11429ed2d737c463bb1fb78cf330caa026adf002f714aced7849a687b", size = 982970, upload-time = "2026-05-15T04:50:32.961Z" }, + { url = "https://files.pythonhosted.org/packages/74/ed/6bb8d05b9f731f749fee5c6f5ca63e981143c826a5985877330507bd13b7/tiktoken-0.13.0-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:3f277ebea5edd7b8bf03c6f9431e1d67d517530115572b2dc1d465326e8f88c7", size = 1115741, upload-time = "2026-05-15T04:50:34.475Z" }, + { url = "https://files.pythonhosted.org/packages/34/de/2ca96b07a82d972b74fe4b46de055b79c904e45c7eab699354a0bfa697dc/tiktoken-0.13.0-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:a116178fa7e1b4065bff05214360373a65cac22f965be7b3f73d00a0dbfe7649", size = 1136523, upload-time = "2026-05-15T04:50:35.782Z" }, + { url = "https://files.pythonhosted.org/packages/ee/dc/9dafec002c2d4424378563cf4cf5c7fb93631d2a55013c8b87554ee4012c/tiktoken-0.13.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:2c397ddda233208345b01bd30f2fca79ff730e55731d0108a603f9bc57f6af3b", size = 1181954, upload-time = "2026-05-15T04:50:36.99Z" }, + { url = "https://files.pythonhosted.org/packages/a1/d0/1f8578c45b2f24759b46f0b50d31878c63c73e6bf0f2227e10ec5c5408dc/tiktoken-0.13.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:95097e4f89b06403976e498abf61a0ee73a7497e73fb599cb211d8197a054d91", size = 1240069, upload-time = "2026-05-15T04:50:38.221Z" }, + { url = "https://files.pythonhosted.org/packages/aa/90/28d7f154888610aa9237e541986beb62b479df29d193a5a0617dbb1514d0/tiktoken-0.13.0-cp312-cp312-win_amd64.whl", hash = "sha256:8f2d16e7a7c783ad81f36e457d046d1f1c8af70b22aec8a13238efe531977c41", size = 874748, upload-time = "2026-05-15T04:50:39.587Z" }, + { url = "https://files.pythonhosted.org/packages/9c/83/b096c859c2a47c11731bf2f5885f4028b809dfe2396582883eed9cae372f/tiktoken-0.13.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:5df5d1507bd245f1ccad4a074698240021239e455eb0bb4ced4e3d7181872154", size = 1034228, upload-time = "2026-05-15T04:50:40.988Z" }, + { url = "https://files.pythonhosted.org/packages/53/61/c68e123b6d753e3fc2751e9b18e732c9d8bf1e1926762e736eee935d931c/tiktoken-0.13.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:8fe806a50664e83a6ffd56cbd1e4f5dcc6cd32a3e7538f70dc38b1a271384545", size = 982978, upload-time = "2026-05-15T04:50:42.195Z" }, + { url = "https://files.pythonhosted.org/packages/ef/8b/96cc178cc584e65d363134500f297790b06cd48cdeb1e8fcf7bbe60f4715/tiktoken-0.13.0-cp313-cp313-manylinux_2_28_aarch64.whl", hash = "sha256:125bc05005e747f993a83dc67934249932d6e4209854452cd4c0b1d53fba3ba2", size = 1116355, upload-time = "2026-05-15T04:50:43.564Z" }, + { url = "https://files.pythonhosted.org/packages/86/f5/bab735d2c72ea55404b295d02d092644eb5f7cc6205e34d35eb9abfb9ab2/tiktoken-0.13.0-cp313-cp313-manylinux_2_28_x86_64.whl", hash = "sha256:5e6358911cab4adee6712da27d65573496a4f68cf8a2b5fca6a4ad10fc5748cf", size = 1135772, upload-time = "2026-05-15T04:50:44.782Z" }, + { url = "https://files.pythonhosted.org/packages/4e/b9/6de04ebdf904edfaad87788011b3735087a0c9ea671b9027e1e4e965e8c8/tiktoken-0.13.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:975cbd78d085d75d26b59660e262736dcaed1e35f8f142cd6291025c01d25486", size = 1182415, upload-time = "2026-05-15T04:50:46.422Z" }, + { url = "https://files.pythonhosted.org/packages/0d/9c/470a05f3b1caf038f44880e334d47ab674e0c80d514c66b375d14d5afa10/tiktoken-0.13.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:75ab9bc99fa020a4c283424590ecd7f3afd70c1c281cb3fa3192a6c3af9f9615", size = 1239879, upload-time = "2026-05-15T04:50:48.052Z" }, + { url = "https://files.pythonhosted.org/packages/42/a6/c1936d16055436cb32e6c6128d68629622e00f4768562f55653752d34768/tiktoken-0.13.0-cp313-cp313-win_amd64.whl", hash = "sha256:6b1615f0ff71953d19729ceb18865429c185b0a23c5353f1bbca34a394bf60f7", size = 874829, upload-time = "2026-05-15T04:50:49.202Z" }, + { url = "https://files.pythonhosted.org/packages/d6/07/acb5992c3772b5a36284f742cfb7a5895aa4471d1848ac31464ad50d7fdf/tiktoken-0.13.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:6eb4a5bfbc6426938026b1a334e898ac53541360d62d8c689870160cc80abd67", size = 1033600, upload-time = "2026-05-15T04:50:50.4Z" }, + { url = "https://files.pythonhosted.org/packages/14/e9/742e9aec30f59b9f161f7ff7cd072e02ea836c9e1c0854a8076dfcd40d5c/tiktoken-0.13.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:43cee3e5400573b2046fbf092cc7a5bc30164f9e4c95ce20714da929df48737a", size = 982516, upload-time = "2026-05-15T04:50:52.03Z" }, + { url = "https://files.pythonhosted.org/packages/72/74/ca1541b053e7648254d2e4b42a253e1bb4359f2c91a0a8d49228c794e1a0/tiktoken-0.13.0-cp313-cp313t-manylinux_2_28_aarch64.whl", hash = "sha256:7de52e3f566d19b3b11bd37eea552c6c305ad74081f736882bd44d148ed4c48d", size = 1115518, upload-time = "2026-05-15T04:50:53.543Z" }, + { url = "https://files.pythonhosted.org/packages/46/e3/93825eaf5a4a504795b787e5d5dea07fbeb3dabf97aa7b450be8bde59c89/tiktoken-0.13.0-cp313-cp313t-manylinux_2_28_x86_64.whl", hash = "sha256:51384448aa508e4df84c0f7c1dc3211c7f7b8096325660ee5fc82f3e11b381ce", size = 1136867, upload-time = "2026-05-15T04:50:55.191Z" }, + { url = "https://files.pythonhosted.org/packages/8c/46/002b68de6827091d5ae90b048f326e8aad8d953520950e5ce1508879414f/tiktoken-0.13.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:e28157350f7ebf35008dd8e9e0fdb621f976e4230c881099c85e8cf07eaa50e2", size = 1181826, upload-time = "2026-05-15T04:50:56.296Z" }, + { url = "https://files.pythonhosted.org/packages/db/c6/d393e3185a276505182f7abd93fe714f3c444a2be9180798fa052347504e/tiktoken-0.13.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:165cf1820ea4a354985c2490a5205d4cc74661c934aca79dd0368232fff94e0f", size = 1239489, upload-time = "2026-05-15T04:50:57.918Z" }, + { url = "https://files.pythonhosted.org/packages/b7/4d/bc07d1f1635d4897a202acc0ae11c2886eaa7325c359ba4741b47bf8e225/tiktoken-0.13.0-cp313-cp313t-win_amd64.whl", hash = "sha256:6c43a675ca14f6f2749ba7f12075d37456015a24b859f2517b9beb4ef30807ec", size = 873820, upload-time = "2026-05-15T04:50:59.528Z" }, + { url = "https://files.pythonhosted.org/packages/8c/93/0dd6adca026a616c3a92974566b43381eea4b475ce1f36c062b8271a9ac5/tiktoken-0.13.0-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:eaaaef47c2406277181d2086484c317bf7fc433e2d5d03ff94f56b0dcec87471", size = 1034977, upload-time = "2026-05-15T04:51:00.957Z" }, + { url = "https://files.pythonhosted.org/packages/d9/77/5ec6e6bc5b30bed6d93f7f2162d8f6b32437b3ba27cb527cfe004f6109c9/tiktoken-0.13.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:ca8b310bd93b3772cb1b7922d915446864860f562bdfe4825c63a0aed3fb28cd", size = 983635, upload-time = "2026-05-15T04:51:02.629Z" }, + { url = "https://files.pythonhosted.org/packages/94/b0/c8ae9aff00d625c50659b4513e707a0462c4bf5d4d6cc1b802103225c02e/tiktoken-0.13.0-cp314-cp314-manylinux_2_28_aarch64.whl", hash = "sha256:32e0c12305105002c047b3bb1070b0dd9a73b0cb3b2856a8972b810e7a4f5881", size = 1116036, upload-time = "2026-05-15T04:51:04.082Z" }, + { url = "https://files.pythonhosted.org/packages/1b/ac/6a5dddd1d0a6018ecb389bd0353e6b4a515eb4d2286611bd0ace1937b9e1/tiktoken-0.13.0-cp314-cp314-manylinux_2_28_x86_64.whl", hash = "sha256:5ba5fd62507a932d1241346179e3b39bc7bf7408f03c272652d93b3bedf5db24", size = 1135544, upload-time = "2026-05-15T04:51:05.229Z" }, + { url = "https://files.pythonhosted.org/packages/f4/b8/585032b4384b2f7dcdaddcb52865c83a701a420d09e3c2b4a2be1c450c57/tiktoken-0.13.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:d108bc2d470fc53c8ecd24f2c0fd2b5f98c33e87cdb6aa2e9b8c5dced703d273", size = 1182217, upload-time = "2026-05-15T04:51:06.517Z" }, + { url = "https://files.pythonhosted.org/packages/cd/b6/993ff1ded3958215fd341a847b8e5ffeb5de473f435296870d314fc91ac4/tiktoken-0.13.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:cb99cb5127449f58d0a2d5f5ccfb390d8dbdfd919c221246caaee29d8725ed51", size = 1239404, upload-time = "2026-05-15T04:51:07.843Z" }, + { url = "https://files.pythonhosted.org/packages/dd/3d/fef7e06e3b33e7538db0ced734cf9fe23b6832d2ac4990c119c377aec55e/tiktoken-0.13.0-cp314-cp314-win_amd64.whl", hash = "sha256:115c4f26ffa11caac8b54eea35c2ad38c612c20a48d35dd15d70a02ac6f51f58", size = 918686, upload-time = "2026-05-15T04:51:08.925Z" }, + { url = "https://files.pythonhosted.org/packages/c1/82/a7fc44582bc32ab00de988a2299bf77c077f59068b233109e34b7d6ca7e6/tiktoken-0.13.0-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:472527e9132952f2fbf77cd290658bacf003d4d5a3fabc18e5fbd407cbae4d9b", size = 1034454, upload-time = "2026-05-15T04:51:10.035Z" }, + { url = "https://files.pythonhosted.org/packages/37/d0/24d8a890c14f432a05cea669c17bebeaa99f96a7c79523b590f564246411/tiktoken-0.13.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:4e2f67d27c9626cdd25fe33d9313c5cdb3d8d82da646b68d6eb8e7e9c20e6448", size = 982976, upload-time = "2026-05-15T04:51:11.23Z" }, + { url = "https://files.pythonhosted.org/packages/49/b7/2ab43f62788a9266187a9bfc1d3af99ad83e5eaa25fbef168a69cd5ad14f/tiktoken-0.13.0-cp314-cp314t-manylinux_2_28_aarch64.whl", hash = "sha256:2b920b35805cd64585a37c3dc7ce65fba4d2d36016be01e1d7942482ca29093a", size = 1115526, upload-time = "2026-05-15T04:51:12.608Z" }, + { url = "https://files.pythonhosted.org/packages/64/39/1494321ed323ce7a14d88e3cd6cb9058625977df1c6961ddc492bd10a9f3/tiktoken-0.13.0-cp314-cp314t-manylinux_2_28_x86_64.whl", hash = "sha256:493af3aa28a4aaf2e3d2600a2ee717252c9bf5ab38fff94eb5a02db5ab77e5ad", size = 1136466, upload-time = "2026-05-15T04:51:13.926Z" }, + { url = "https://files.pythonhosted.org/packages/96/d9/dfd086aa2d918c563a140720e0ce296cada1634efd2783d5cf51e05f984e/tiktoken-0.13.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:6644c9c2b5cf3916f5a3641d7d12fdb3f006a7b3d9ff6acdaec44e29ab1ff91e", size = 1181863, upload-time = "2026-05-15T04:51:15.025Z" }, + { url = "https://files.pythonhosted.org/packages/2f/68/a18b4f307086954fdae32714cb4f85562e34f9d34ab206e61f1816aa6018/tiktoken-0.13.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:5cb65b60b9408563676d874a3a4ee573370066f0dc4e29d84e82e989c6517424", size = 1239218, upload-time = "2026-05-15T04:51:16.103Z" }, + { url = "https://files.pythonhosted.org/packages/16/5b/f2aa703a4fc5d2dff73460a7d46cc2f3f44aa0f3dd8eeb20d2a0ecf68862/tiktoken-0.13.0-cp314-cp314t-win_amd64.whl", hash = "sha256:85b78cc3a2c3d48723ca751fa981f1fedccd54194ca0471b957364353a898b07", size = 918110, upload-time = "2026-05-15T04:51:17.237Z" }, ] [[package]] name = "tokenizers" -version = "0.22.2" +version = "0.23.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "huggingface-hub" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/73/6f/f80cfef4a312e1fb34baf7d85c72d4411afde10978d4657f8cdd811d3ccc/tokenizers-0.22.2.tar.gz", hash = "sha256:473b83b915e547aa366d1eee11806deaf419e17be16310ac0a14077f1e28f917", size = 372115, upload-time = "2026-01-05T10:45:15.988Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/92/97/5dbfabf04c7e348e655e907ed27913e03db0923abb5dfdd120d7b25630e1/tokenizers-0.22.2-cp39-abi3-macosx_10_12_x86_64.whl", hash = "sha256:544dd704ae7238755d790de45ba8da072e9af3eea688f698b137915ae959281c", size = 3100275, upload-time = "2026-01-05T10:41:02.158Z" }, - { url = "https://files.pythonhosted.org/packages/2e/47/174dca0502ef88b28f1c9e06b73ce33500eedfac7a7692108aec220464e7/tokenizers-0.22.2-cp39-abi3-macosx_11_0_arm64.whl", hash = "sha256:1e418a55456beedca4621dbab65a318981467a2b188e982a23e117f115ce5001", size = 2981472, upload-time = "2026-01-05T10:41:00.276Z" }, - { url = "https://files.pythonhosted.org/packages/d6/84/7990e799f1309a8b87af6b948f31edaa12a3ed22d11b352eaf4f4b2e5753/tokenizers-0.22.2-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2249487018adec45d6e3554c71d46eb39fa8ea67156c640f7513eb26f318cec7", size = 3290736, upload-time = "2026-01-05T10:40:32.165Z" }, - { url = "https://files.pythonhosted.org/packages/78/59/09d0d9ba94dcd5f4f1368d4858d24546b4bdc0231c2354aa31d6199f0399/tokenizers-0.22.2-cp39-abi3-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:25b85325d0815e86e0bac263506dd114578953b7b53d7de09a6485e4a160a7dd", size = 3168835, upload-time = "2026-01-05T10:40:38.847Z" }, - { url = "https://files.pythonhosted.org/packages/47/50/b3ebb4243e7160bda8d34b731e54dd8ab8b133e50775872e7a434e524c28/tokenizers-0.22.2-cp39-abi3-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bfb88f22a209ff7b40a576d5324bf8286b519d7358663db21d6246fb17eea2d5", size = 3521673, upload-time = "2026-01-05T10:40:56.614Z" }, - { url = "https://files.pythonhosted.org/packages/e0/fa/89f4cb9e08df770b57adb96f8cbb7e22695a4cb6c2bd5f0c4f0ebcf33b66/tokenizers-0.22.2-cp39-abi3-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1c774b1276f71e1ef716e5486f21e76333464f47bece56bbd554485982a9e03e", size = 3724818, upload-time = "2026-01-05T10:40:44.507Z" }, - { url = "https://files.pythonhosted.org/packages/64/04/ca2363f0bfbe3b3d36e95bf67e56a4c88c8e3362b658e616d1ac185d47f2/tokenizers-0.22.2-cp39-abi3-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:df6c4265b289083bf710dff49bc51ef252f9d5be33a45ee2bed151114a56207b", size = 3379195, upload-time = "2026-01-05T10:40:51.139Z" }, - { url = "https://files.pythonhosted.org/packages/2e/76/932be4b50ef6ccedf9d3c6639b056a967a86258c6d9200643f01269211ca/tokenizers-0.22.2-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:369cc9fc8cc10cb24143873a0d95438bb8ee257bb80c71989e3ee290e8d72c67", size = 3274982, upload-time = "2026-01-05T10:40:58.331Z" }, - { url = "https://files.pythonhosted.org/packages/1d/28/5f9f5a4cc211b69e89420980e483831bcc29dade307955cc9dc858a40f01/tokenizers-0.22.2-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:29c30b83d8dcd061078b05ae0cb94d3c710555fbb44861139f9f83dcca3dc3e4", size = 9478245, upload-time = "2026-01-05T10:41:04.053Z" }, - { url = "https://files.pythonhosted.org/packages/6c/fb/66e2da4704d6aadebf8cb39f1d6d1957df667ab24cff2326b77cda0dcb85/tokenizers-0.22.2-cp39-abi3-musllinux_1_2_armv7l.whl", hash = "sha256:37ae80a28c1d3265bb1f22464c856bd23c02a05bb211e56d0c5301a435be6c1a", size = 9560069, upload-time = "2026-01-05T10:45:10.673Z" }, - { url = "https://files.pythonhosted.org/packages/16/04/fed398b05caa87ce9b1a1bb5166645e38196081b225059a6edaff6440fac/tokenizers-0.22.2-cp39-abi3-musllinux_1_2_i686.whl", hash = "sha256:791135ee325f2336f498590eb2f11dc5c295232f288e75c99a36c5dbce63088a", size = 9899263, upload-time = "2026-01-05T10:45:12.559Z" }, - { url = "https://files.pythonhosted.org/packages/05/a1/d62dfe7376beaaf1394917e0f8e93ee5f67fea8fcf4107501db35996586b/tokenizers-0.22.2-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:38337540fbbddff8e999d59970f3c6f35a82de10053206a7562f1ea02d046fa5", size = 10033429, upload-time = "2026-01-05T10:45:14.333Z" }, - { url = "https://files.pythonhosted.org/packages/fd/18/a545c4ea42af3df6effd7d13d250ba77a0a86fb20393143bbb9a92e434d4/tokenizers-0.22.2-cp39-abi3-win32.whl", hash = "sha256:a6bf3f88c554a2b653af81f3204491c818ae2ac6fbc09e76ef4773351292bc92", size = 2502363, upload-time = "2026-01-05T10:45:20.593Z" }, - { url = "https://files.pythonhosted.org/packages/65/71/0670843133a43d43070abeb1949abfdef12a86d490bea9cd9e18e37c5ff7/tokenizers-0.22.2-cp39-abi3-win_amd64.whl", hash = "sha256:c9ea31edff2968b44a88f97d784c2f16dc0729b8b143ed004699ebca91f05c48", size = 2747786, upload-time = "2026-01-05T10:45:18.411Z" }, - { url = "https://files.pythonhosted.org/packages/72/f4/0de46cfa12cdcbcd464cc59fde36912af405696f687e53a091fb432f694c/tokenizers-0.22.2-cp39-abi3-win_arm64.whl", hash = "sha256:9ce725d22864a1e965217204946f830c37876eee3b2ba6fc6255e8e903d5fcbc", size = 2612133, upload-time = "2026-01-05T10:45:17.232Z" }, - { url = "https://files.pythonhosted.org/packages/84/04/655b79dbcc9b3ac5f1479f18e931a344af67e5b7d3b251d2dcdcd7558592/tokenizers-0.22.2-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:753d47ebd4542742ef9261d9da92cd545b2cacbb48349a1225466745bb866ec4", size = 3282301, upload-time = "2026-01-05T10:40:34.858Z" }, - { url = "https://files.pythonhosted.org/packages/46/cd/e4851401f3d8f6f45d8480262ab6a5c8cb9c4302a790a35aa14eeed6d2fd/tokenizers-0.22.2-pp310-pypy310_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e10bf9113d209be7cd046d40fbabbaf3278ff6d18eb4da4c500443185dc1896c", size = 3161308, upload-time = "2026-01-05T10:40:40.737Z" }, - { url = "https://files.pythonhosted.org/packages/6f/6e/55553992a89982cd12d4a66dddb5e02126c58677ea3931efcbe601d419db/tokenizers-0.22.2-pp310-pypy310_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:64d94e84f6660764e64e7e0b22baa72f6cd942279fdbb21d46abd70d179f0195", size = 3718964, upload-time = "2026-01-05T10:40:46.56Z" }, - { url = "https://files.pythonhosted.org/packages/59/8c/b1c87148aa15e099243ec9f0cf9d0e970cc2234c3257d558c25a2c5304e6/tokenizers-0.22.2-pp310-pypy310_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f01a9c019878532f98927d2bacb79bbb404b43d3437455522a00a30718cdedb5", size = 3373542, upload-time = "2026-01-05T10:40:52.803Z" }, +sdist = { url = "https://files.pythonhosted.org/packages/c1/60/21f715d9faba5f5407ff759472ade058ec4a507ad62bcea47cb847239a73/tokenizers-0.23.1.tar.gz", hash = "sha256:1feeeadf865a7915adc25445dea30e9933e593c31bb96c277cee36de227c8bfa", size = 365748, upload-time = "2026-04-27T14:43:25.606Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/87/39/b87a87d5bb9470610b80a2d31df42fcffeaf35118b8b97952b2aff598cc7/tokenizers-0.23.1-cp310-abi3-macosx_10_12_x86_64.whl", hash = "sha256:e03d6ffcbe0d56ee9c1ccd070e70a13fa750727c0277e138152acbc0252c2224", size = 3146732, upload-time = "2026-04-27T14:43:15.427Z" }, + { url = "https://files.pythonhosted.org/packages/e2/6a/068ed9f6e444c9d7e9d55ce134181325700f3d7f30410721bdc8f848d727/tokenizers-0.23.1-cp310-abi3-macosx_11_0_arm64.whl", hash = "sha256:e0948bbb1ac1d7cdfc9fb6d62c596e3b7550036ad60ecd654a66ad273326324e", size = 3054954, upload-time = "2026-04-27T14:43:13.745Z" }, + { url = "https://files.pythonhosted.org/packages/6c/36/e006edf031154cba92b8416057d92c3abe3635e4c4b0aa0b5b9bb39dde70/tokenizers-0.23.1-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1bf13402aff9bc533c89cb849ec3b412dc3fbeacc9744840e423d7bf3f7dc0e3", size = 3374081, upload-time = "2026-04-27T14:43:01.241Z" }, + { url = "https://files.pythonhosted.org/packages/a2/ef/7735d226f9c7f874a6bee5e3f27fb25ecabdf207d37b8cf45286d0795893/tokenizers-0.23.1-cp310-abi3-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:f836ca703b89ae07919a309f9651f7a88fd5a33d5f718ba5ad0870ec0256bad6", size = 3247641, upload-time = "2026-04-27T14:43:03.856Z" }, + { url = "https://files.pythonhosted.org/packages/b9/d9/24827036f6e21297bfffda0768e58eb6096a4f411e932964a01707857931/tokenizers-0.23.1-cp310-abi3-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ae848657742035523fdf261773630cb819a26995fcd3d9ecae0c1daf6e5a4959", size = 3585624, upload-time = "2026-04-27T14:43:10.664Z" }, + { url = "https://files.pythonhosted.org/packages/0c/9a/22f3582b3a4f49358293a5206e25317621ee4526bfe9cdaa0f07a12e770e/tokenizers-0.23.1-cp310-abi3-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:53b09e85775d5187941e7bab30e941b4134ab4a7dd8c68e783d231fb7ca27c51", size = 3844062, upload-time = "2026-04-27T14:43:05.643Z" }, + { url = "https://files.pythonhosted.org/packages/7e/65/b8f8814eef95800f20721384136d9a1d22241d50b2874357cb70542c392f/tokenizers-0.23.1-cp310-abi3-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ea5a0ce170074329faaa8ea3f6400ecde604b6678192688533af80980daae71a", size = 3460098, upload-time = "2026-04-27T14:43:08.854Z" }, + { url = "https://files.pythonhosted.org/packages/0d/d5/1353e5f677ec27c2494fb6a6725e82d56c985f53e90ec511369e7e4f02c6/tokenizers-0.23.1-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5075b405006415ea148a992d093699c66eb01952bf59f4d5727089a98bda45a4", size = 3346235, upload-time = "2026-04-27T14:43:12.377Z" }, + { url = "https://files.pythonhosted.org/packages/71/89/39b6b8fc073fb6d413d0147aa333dc7eff7be65639ac9d19930a0b21bf33/tokenizers-0.23.1-cp310-abi3-manylinux_2_31_riscv64.whl", hash = "sha256:56f3a77de629917652f876294dc9fe6bad4a0c43bc229dc72e59bb23a0f4729a", size = 3426398, upload-time = "2026-04-27T14:43:07.264Z" }, + { url = "https://files.pythonhosted.org/packages/0f/80/127c854da64827e5b79264ce524993a90dddcb320e5cd42412c5c02f9e8a/tokenizers-0.23.1-cp310-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:9d10a6d957ef01896dc274e890eee27d41bd0e74ef31e60616f0fc311345184e", size = 9823279, upload-time = "2026-04-27T14:43:17.222Z" }, + { url = "https://files.pythonhosted.org/packages/fe/ba/44c2502feb1a058f096ddfb4e0996ef3225a01a388e1a9b094e91689fe93/tokenizers-0.23.1-cp310-abi3-musllinux_1_2_armv7l.whl", hash = "sha256:1974288a609c343774f1b897c8b482c791ab17b75ab5c8c2b1737565c1d82288", size = 9644986, upload-time = "2026-04-27T14:43:19.45Z" }, + { url = "https://files.pythonhosted.org/packages/9e/c1/464019a9fb059870bfe4eebb4ba12208f3042035e258bf5e782906bd3847/tokenizers-0.23.1-cp310-abi3-musllinux_1_2_i686.whl", hash = "sha256:120468fb4c24faf0543c835a4fabafa4deb3f20a035c9b6e83d0b553a97615d4", size = 9976181, upload-time = "2026-04-27T14:43:21.463Z" }, + { url = "https://files.pythonhosted.org/packages/79/94/3ac1432bda31626071e9b6a12709b97ae05131c804b94c8f3ac622c5da32/tokenizers-0.23.1-cp310-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:e3d8f40ea6268047de7046906326abed5134f27d4e8447b23763afe5808c8a96", size = 10113853, upload-time = "2026-04-27T14:43:23.617Z" }, + { url = "https://files.pythonhosted.org/packages/6a/dd/631b21433c771b1382535326f0eca80b9c9cee2e64961dd993bc9ac4669e/tokenizers-0.23.1-cp310-abi3-win32.whl", hash = "sha256:93120a930b919416da7cd10a2f606ac9919cc69cacae7980fa2140e277660948", size = 2536263, upload-time = "2026-04-27T14:43:29.888Z" }, + { url = "https://files.pythonhosted.org/packages/97/c9/2553f72aaf65a2797d4229e37fa7fbe38ffbf3e32912d31bdd78b3323e59/tokenizers-0.23.1-cp310-abi3-win_amd64.whl", hash = "sha256:e7bfaf995c1bdbbd21d13539decb6650967013759318627d85daeb7881af16b7", size = 2798223, upload-time = "2026-04-27T14:43:28.51Z" }, + { url = "https://files.pythonhosted.org/packages/cd/2b/2be299bab55fc595e3d38567edb1a87f86e594842968fa9515a07bdcf422/tokenizers-0.23.1-cp310-abi3-win_arm64.whl", hash = "sha256:a26197957d8e4425dfba746315f3c425ea00cfa8367c5fbc4ec73447893dcea9", size = 2664127, upload-time = "2026-04-27T14:43:26.949Z" }, ] [[package]] @@ -5737,14 +5955,14 @@ wheels = [ [[package]] name = "tqdm" -version = "4.67.3" +version = "4.68.2" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "colorama", marker = "sys_platform == 'win32'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/09/a9/6ba95a270c6f1fbcd8dac228323f2777d886cb206987444e4bce66338dd4/tqdm-4.67.3.tar.gz", hash = "sha256:7d825f03f89244ef73f1d4ce193cb1774a8179fd96f31d7e1dcde62092b960bb", size = 169598, upload-time = "2026-02-03T17:35:53.048Z" } +sdist = { url = "https://files.pythonhosted.org/packages/85/05/0d5260f1f1ca784f4a4a0def9cbe6affe587f5b4025328d446c3d67765f4/tqdm-4.68.2.tar.gz", hash = "sha256:89c230e8dbc67c7615c142487111222f878c77427ea09549960f62389e258add", size = 171923, upload-time = "2026-06-09T13:26:42.539Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/16/e1/3079a9ff9b8e11b846c6ac5c8b5bfb7ff225eee721825310c91b3b50304f/tqdm-4.67.3-py3-none-any.whl", hash = "sha256:ee1e4c0e59148062281c49d80b25b67771a127c85fc9676d3be5f243206826bf", size = 78374, upload-time = "2026-02-03T17:35:50.982Z" }, + { url = "https://files.pythonhosted.org/packages/eb/75/1a0392bcc21c44dcdf87b3cf2d137e7829be2c083a1e38d44efca3d57a16/tqdm-4.68.2-py3-none-any.whl", hash = "sha256:d4240441fb5353290b87d6a85968c9decc131a99b8c7faa28269d829de669ede", size = 78578, upload-time = "2026-06-09T13:26:40.731Z" }, ] [[package]] @@ -5769,7 +5987,7 @@ wheels = [ [[package]] name = "twisted" -version = "25.5.0" +version = "26.4.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "attrs" }, @@ -5780,14 +5998,14 @@ dependencies = [ { name = "typing-extensions" }, { name = "zope-interface" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/13/0f/82716ed849bf7ea4984c21385597c949944f0f9b428b5710f79d0afc084d/twisted-25.5.0.tar.gz", hash = "sha256:1deb272358cb6be1e3e8fc6f9c8b36f78eb0fa7c2233d2dbe11ec6fee04ea316", size = 3545725, upload-time = "2025-06-07T09:52:24.858Z" } +sdist = { url = "https://files.pythonhosted.org/packages/db/97/6e9beb1e78247ae6dc34114f27d538cf2cb183c4afcd3609dfdf2b0439c8/twisted-26.4.0.tar.gz", hash = "sha256:dbfd0fe1ee409d0243fdd7a6a6ff14f4948cec1fd78e0376291f805e1501fae9", size = 3575095, upload-time = "2026-05-11T11:24:51.861Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/eb/66/ab7efd8941f0bc7b2bd555b0f0471bff77df4c88e0cc31120c82737fec77/twisted-25.5.0-py3-none-any.whl", hash = "sha256:8559f654d01a54a8c3efe66d533d43f383531ebf8d81d9f9ab4769d91ca15df7", size = 3204767, upload-time = "2025-06-07T09:52:21.428Z" }, + { url = "https://files.pythonhosted.org/packages/a6/57/bcf4e2370dd218c9aa68a9140a65d86729c73f1d529f7e94786c2766fc72/twisted-26.4.0-py3-none-any.whl", hash = "sha256:dc25ea0ebf6511c24f03232ee9f4afa54b291c5d897990e3a39cc4d14a1ef4c0", size = 3230362, upload-time = "2026-05-11T11:24:49.5Z" }, ] [[package]] name = "typer" -version = "0.24.2" +version = "0.25.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "annotated-doc" }, @@ -5795,9 +6013,9 @@ dependencies = [ { name = "rich" }, { name = "shellingham" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/83/b8/9ebb531b6c2d377af08ac6746a5df3425b21853a5d2260876919b58a2a4a/typer-0.24.2.tar.gz", hash = "sha256:ec070dcfca1408e85ee203c6365001e818c3b7fffe686fd07ff2d68095ca0480", size = 119849, upload-time = "2026-04-22T17:45:34.413Z" } +sdist = { url = "https://files.pythonhosted.org/packages/e4/51/9aed62104cea109b820bbd6c14245af756112017d309da813ef107d42e7e/typer-0.25.1.tar.gz", hash = "sha256:9616eb8853a09ffeabab1698952f33c6f29ffdbceb4eaeecf571880e8d7664cc", size = 122276, upload-time = "2026-04-30T19:32:16.964Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/39/d1/9484b497e0a0410b901c12b8251c3e746e1e863f7d28419ffe06f7892fda/typer-0.24.2-py3-none-any.whl", hash = "sha256:b618bc3d721f9a8d30f3e05565be26416d06e9bcc29d49bc491dc26aba674fa8", size = 55977, upload-time = "2026-04-22T17:45:33.055Z" }, + { url = "https://files.pythonhosted.org/packages/3f/f9/2b3ff4e56e5fa7debfaf9eb135d0da96f3e9a1d5b27222223c7296336e5f/typer-0.25.1-py3-none-any.whl", hash = "sha256:75caa44ed46a03fb2dab8808753ffacdbfea88495e74c85a28c5eefcf5f39c89", size = 58409, upload-time = "2026-04-30T19:32:18.271Z" }, ] [[package]] @@ -5822,15 +6040,15 @@ s3 = [ [[package]] name = "types-aiobotocore" -version = "3.5.0" +version = "3.7.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "botocore-stubs" }, { name = "typing-extensions", marker = "python_full_version < '3.12'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/d5/99/3863acdc373aa621cf56634bb08145fb54f2213e647d893c1ac7b2636c11/types_aiobotocore-3.5.0.tar.gz", hash = "sha256:8636c9e5a9837d41e45264570349d98c0cdad51fe7961ee19664a11094bb2262", size = 87983, upload-time = "2026-04-23T02:57:02.576Z" } +sdist = { url = "https://files.pythonhosted.org/packages/76/e8/ef1fcb876937dbdddc0f01b5df4ed53f33b166a6367d80a9014d5e5f091d/types_aiobotocore-3.7.0.tar.gz", hash = "sha256:fe35de52c12e5fdb89ca60b3989766e7fe827e3d2e95fcf4583e91581945205c", size = 87992, upload-time = "2026-05-10T03:19:32.353Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/ed/d7/2b2d4d5b64b81149b08cc3fde6e826788c703c012b687cd4cc4d83742afd/types_aiobotocore-3.5.0-py3-none-any.whl", hash = "sha256:7c75ff73c10098d1d885e5b061f05945afdc4e9d0d5b573274292c329abe8a62", size = 54805, upload-time = "2026-04-23T02:56:59.721Z" }, + { url = "https://files.pythonhosted.org/packages/f9/68/0cdfd7df415ee3e769c8e8f9bd8013c64c88cdd7306f72453a02123c58f9/types_aiobotocore-3.7.0-py3-none-any.whl", hash = "sha256:ff4139b3eae22d242b6b39ba56048344b2b86f67daeeca4680da1a6e191681fd", size = 54804, upload-time = "2026-05-10T03:19:29.487Z" }, ] [[package]] @@ -5847,11 +6065,11 @@ wheels = [ [[package]] name = "types-awscrt" -version = "0.31.3" +version = "0.34.1" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/76/26/0aa563e229c269c528a3b8c709fc671ac2a5c564732fab0852ac6ee006cf/types_awscrt-0.31.3.tar.gz", hash = "sha256:09d3eaf00231e0f47e101bd9867e430873bc57040050e2a3bd8305cb4fc30865", size = 18178, upload-time = "2026-03-08T02:31:14.569Z" } +sdist = { url = "https://files.pythonhosted.org/packages/3e/59/44409a8fc06b444ab1a6f71dcb29d49a6e17e02424345eb51b051bebb345/types_awscrt-0.34.1.tar.gz", hash = "sha256:559aa04250f6a419a617dfb788f3e10903aaf74700ef23e521b64a411b83b803", size = 19062, upload-time = "2026-06-05T04:40:10.689Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/3e/e5/47a573bbbd0a790f8f9fe452f7188ea72b212d21c9be57d5fc0cbc442075/types_awscrt-0.31.3-py3-none-any.whl", hash = "sha256:e5ce65a00a2ab4f35eacc1e3d700d792338d56e4823ee7b4dbe017f94cfc4458", size = 43340, upload-time = "2026-03-08T02:31:13.38Z" }, + { url = "https://files.pythonhosted.org/packages/e4/b1/214b12162b452ed6acd230065e6c587cde6b96871e3ce6d653f40888f8df/types_awscrt-0.34.1-py3-none-any.whl", hash = "sha256:20c752b6031544d8f694803c35174aee129f1be5ddf886ae46d22f7ffd9b7d75", size = 45688, upload-time = "2026-06-05T04:40:09.198Z" }, ] [[package]] @@ -5863,18 +6081,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/2a/1f/ec5caf72c2e3b688ca3927e0979a04ddad19e1afc4bf1c199bd743e0f419/types_protobuf-7.34.1.20260518-py3-none-any.whl", hash = "sha256:a0a5337413347166439c0e07cbc26c6164d091401c6f01b1dfd8cdb966c4dd8f", size = 85992, upload-time = "2026-05-18T06:01:45.696Z" }, ] -[[package]] -name = "types-requests" -version = "2.33.0.20260408" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "urllib3" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/69/6a/749dc53a54a3f35842c1f8197b3ca6b54af6d7458a1bfc75f6629b6da666/types_requests-2.33.0.20260408.tar.gz", hash = "sha256:95b9a86376807a216b2fb412b47617b202091c3ea7c078f47cc358d5528ccb7b", size = 23882, upload-time = "2026-04-08T04:34:49.33Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/90/b8/78fd6c037de4788c040fdd323b3369804400351b7827473920f6c1d03c10/types_requests-2.33.0.20260408-py3-none-any.whl", hash = "sha256:81f31d5ea4acb39f03be7bc8bed569ba6d5a9c5d97e89f45ac43d819b68ca50f", size = 20739, upload-time = "2026-04-08T04:34:48.325Z" }, -] - [[package]] name = "types-s3transfer" version = "0.16.0" @@ -5907,23 +6113,23 @@ wheels = [ [[package]] name = "tzdata" -version = "2026.1" +version = "2026.2" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/19/f5/cd531b2d15a671a40c0f66cf06bc3570a12cd56eef98960068ebbad1bf5a/tzdata-2026.1.tar.gz", hash = "sha256:67658a1903c75917309e753fdc349ac0efd8c27db7a0cb406a25be4840f87f98", size = 197639, upload-time = "2026-04-03T11:25:22.002Z" } +sdist = { url = "https://files.pythonhosted.org/packages/ba/19/1b9b0e29f30c6d35cb345486df41110984ea67ae69dddbc0e8a100999493/tzdata-2026.2.tar.gz", hash = "sha256:9173fde7d80d9018e02a662e168e5a2d04f87c41ea174b139fbef642eda62d10", size = 198254, upload-time = "2026-04-24T15:22:08.651Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/b0/70/d460bd685a170790ec89317e9bd33047988e4bce507b831f5db771e142de/tzdata-2026.1-py2.py3-none-any.whl", hash = "sha256:4b1d2be7ac37ceafd7327b961aa3a54e467efbdb563a23655fbfe0d39cfc42a9", size = 348952, upload-time = "2026-04-03T11:25:20.313Z" }, + { url = "https://files.pythonhosted.org/packages/ce/e4/dccd7f47c4b64213ac01ef921a1337ee6e30e8c6466046018326977efd95/tzdata-2026.2-py2.py3-none-any.whl", hash = "sha256:bbe9af844f658da81a5f95019480da3a89415801f6cc966806612cc7169bffe7", size = 349321, upload-time = "2026-04-24T15:22:05.876Z" }, ] [[package]] name = "tzlocal" -version = "5.3.1" +version = "5.4" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "tzdata", marker = "sys_platform == 'win32'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/8b/2e/c14812d3d4d9cd1773c6be938f89e5735a1f11a9f184ac3639b93cef35d5/tzlocal-5.3.1.tar.gz", hash = "sha256:cceffc7edecefea1f595541dbd6e990cb1ea3d19bf01b2809f362a03dd7921fd", size = 30761, upload-time = "2025-03-05T21:17:41.549Z" } +sdist = { url = "https://files.pythonhosted.org/packages/d8/52/ee2e6d7031687c5bad28363148cb72f2bbf38201d2e220671bd9fb830bc2/tzlocal-5.4.tar.gz", hash = "sha256:41e1293f80d4b5ff38dff222601a8fbd06b4fdcaf25e224704047ad26a39af54", size = 30922, upload-time = "2026-06-15T12:06:56.594Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/c2/14/e2a54fabd4f08cd7af1c07030603c3356b74da07f7cc056e600436edfa17/tzlocal-5.3.1-py3-none-any.whl", hash = "sha256:eb1a66c3ef5847adf7a834f1be0800581b683b5608e74f86ecbcef8ab91bb85d", size = 18026, upload-time = "2025-03-05T21:17:39.857Z" }, + { url = "https://files.pythonhosted.org/packages/1d/70/5771c9ecbdb7cc0c3f3bbded7e0fa7911ee8e872ce5b5dc48ce7dce21a11/tzlocal-5.4-py3-none-any.whl", hash = "sha256:024d11221ff83453eae1f608f09b145b9779e1345d08c15404ce8ff7917cf629", size = 28261, upload-time = "2026-06-15T12:06:54.914Z" }, ] [[package]] @@ -5937,54 +6143,138 @@ wheels = [ [[package]] name = "urllib3" -version = "2.6.3" +version = "2.7.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/c7/24/5f1b3bdffd70275f6661c76461e25f024d5a38a46f04aaca912426a2b1d3/urllib3-2.6.3.tar.gz", hash = "sha256:1b62b6884944a57dbe321509ab94fd4d3b307075e0c2eae991ac71ee15ad38ed", size = 435556, upload-time = "2026-01-07T16:24:43.925Z" } +sdist = { url = "https://files.pythonhosted.org/packages/53/0c/06f8b233b8fd13b9e5ee11424ef85419ba0d8ba0b3138bf360be2ff56953/urllib3-2.7.0.tar.gz", hash = "sha256:231e0ec3b63ceb14667c67be60f2f2c40a518cb38b03af60abc813da26505f4c", size = 433602, upload-time = "2026-05-07T16:13:18.596Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/39/08/aaaad47bc4e9dc8c725e68f9d04865dbcb2052843ff09c97b08904852d84/urllib3-2.6.3-py3-none-any.whl", hash = "sha256:bf272323e553dfb2e87d9bfd225ca7b0f467b919d7bbd355436d3fd37cb0acd4", size = 131584, upload-time = "2026-01-07T16:24:42.685Z" }, + { url = "https://files.pythonhosted.org/packages/7f/3e/5db95bcf282c52709639744ca2a8b149baccf648e39c8cc87553df9eae0c/urllib3-2.7.0-py3-none-any.whl", hash = "sha256:9fb4c81ebbb1ce9531cce37674bbc6f1360472bc18ca9a553ede278ef7276897", size = 131087, upload-time = "2026-05-07T16:13:17.151Z" }, ] [[package]] name = "uuid-utils" -version = "0.14.1" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/7b/d1/38a573f0c631c062cf42fa1f5d021d4dd3c31fb23e4376e4b56b0c9fbbed/uuid_utils-0.14.1.tar.gz", hash = "sha256:9bfc95f64af80ccf129c604fb6b8ca66c6f256451e32bc4570f760e4309c9b69", size = 22195, upload-time = "2026-02-20T22:50:38.833Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/43/b7/add4363039a34506a58457d96d4aa2126061df3a143eb4d042aedd6a2e76/uuid_utils-0.14.1-cp39-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:93a3b5dc798a54a1feb693f2d1cb4cf08258c32ff05ae4929b5f0a2ca624a4f0", size = 604679, upload-time = "2026-02-20T22:50:27.469Z" }, - { url = "https://files.pythonhosted.org/packages/dd/84/d1d0bef50d9e66d31b2019997c741b42274d53dde2e001b7a83e9511c339/uuid_utils-0.14.1-cp39-abi3-macosx_10_12_x86_64.whl", hash = "sha256:ccd65a4b8e83af23eae5e56d88034b2fe7264f465d3e830845f10d1591b81741", size = 309346, upload-time = "2026-02-20T22:50:31.857Z" }, - { url = "https://files.pythonhosted.org/packages/ef/ed/b6d6fd52a6636d7c3eddf97d68da50910bf17cd5ac221992506fb56cf12e/uuid_utils-0.14.1-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b56b0cacd81583834820588378e432b0696186683b813058b707aedc1e16c4b1", size = 344714, upload-time = "2026-02-20T22:50:42.642Z" }, - { url = "https://files.pythonhosted.org/packages/a8/a7/a19a1719fb626fe0b31882db36056d44fe904dc0cf15b06fdf56b2679cf7/uuid_utils-0.14.1-cp39-abi3-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:bb3cf14de789097320a3c56bfdfdd51b1225d11d67298afbedee7e84e3837c96", size = 350914, upload-time = "2026-02-20T22:50:36.487Z" }, - { url = "https://files.pythonhosted.org/packages/1d/fc/f6690e667fdc3bb1a73f57951f97497771c56fe23e3d302d7404be394d4f/uuid_utils-0.14.1-cp39-abi3-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:60e0854a90d67f4b0cc6e54773deb8be618f4c9bad98d3326f081423b5d14fae", size = 482609, upload-time = "2026-02-20T22:50:37.511Z" }, - { url = "https://files.pythonhosted.org/packages/54/6e/dcd3fa031320921a12ec7b4672dea3bd1dd90ddffa363a91831ba834d559/uuid_utils-0.14.1-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ce6743ba194de3910b5feb1a62590cd2587e33a73ab6af8a01b642ceb5055862", size = 345699, upload-time = "2026-02-20T22:50:46.87Z" }, - { url = "https://files.pythonhosted.org/packages/04/28/e5220204b58b44ac0047226a9d016a113fde039280cc8732d9e6da43b39f/uuid_utils-0.14.1-cp39-abi3-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:043fb58fde6cf1620a6c066382f04f87a8e74feb0f95a585e4ed46f5d44af57b", size = 372205, upload-time = "2026-02-20T22:50:28.438Z" }, - { url = "https://files.pythonhosted.org/packages/c7/d9/3d2eb98af94b8dfffc82b6a33b4dfc87b0a5de2c68a28f6dde0db1f8681b/uuid_utils-0.14.1-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:c915d53f22945e55fe0d3d3b0b87fd965a57f5fd15666fd92d6593a73b1dd297", size = 521836, upload-time = "2026-02-20T22:50:23.057Z" }, - { url = "https://files.pythonhosted.org/packages/a8/15/0eb106cc6fe182f7577bc0ab6e2f0a40be247f35c5e297dbf7bbc460bd02/uuid_utils-0.14.1-cp39-abi3-musllinux_1_2_armv7l.whl", hash = "sha256:0972488e3f9b449e83f006ead5a0e0a33ad4a13e4462e865b7c286ab7d7566a3", size = 625260, upload-time = "2026-02-20T22:50:25.949Z" }, - { url = "https://files.pythonhosted.org/packages/3c/17/f539507091334b109e7496830af2f093d9fc8082411eafd3ece58af1f8ba/uuid_utils-0.14.1-cp39-abi3-musllinux_1_2_i686.whl", hash = "sha256:1c238812ae0c8ffe77d8d447a32c6dfd058ea4631246b08b5a71df586ff08531", size = 587824, upload-time = "2026-02-20T22:50:35.225Z" }, - { url = "https://files.pythonhosted.org/packages/2e/c2/d37a7b2e41f153519367d4db01f0526e0d4b06f1a4a87f1c5dfca5d70a8b/uuid_utils-0.14.1-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:bec8f8ef627af86abf8298e7ec50926627e29b34fa907fcfbedb45aaa72bca43", size = 551407, upload-time = "2026-02-20T22:50:44.915Z" }, - { url = "https://files.pythonhosted.org/packages/65/36/2d24b2cbe78547c6532da33fb8613debd3126eccc33a6374ab788f5e46e9/uuid_utils-0.14.1-cp39-abi3-win32.whl", hash = "sha256:b54d6aa6252d96bac1fdbc80d26ba71bad9f220b2724d692ad2f2310c22ef523", size = 183476, upload-time = "2026-02-20T22:50:32.745Z" }, - { url = "https://files.pythonhosted.org/packages/83/92/2d7e90df8b1a69ec4cff33243ce02b7a62f926ef9e2f0eca5a026889cd73/uuid_utils-0.14.1-cp39-abi3-win_amd64.whl", hash = "sha256:fc27638c2ce267a0ce3e06828aff786f91367f093c80625ee21dad0208e0f5ba", size = 187147, upload-time = "2026-02-20T22:50:45.807Z" }, - { url = "https://files.pythonhosted.org/packages/d9/26/529f4beee17e5248e37e0bc17a2761d34c0fa3b1e5729c88adb2065bae6e/uuid_utils-0.14.1-cp39-abi3-win_arm64.whl", hash = "sha256:b04cb49b42afbc4ff8dbc60cf054930afc479d6f4dd7f1ec3bbe5dbfdde06b7a", size = 188132, upload-time = "2026-02-20T22:50:41.718Z" }, - { url = "https://files.pythonhosted.org/packages/91/f9/6c64bdbf71f58ccde7919e00491812556f446a5291573af92c49a5e9aaef/uuid_utils-0.14.1-pp311-pypy311_pp73-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:b197cd5424cf89fb019ca7f53641d05bfe34b1879614bed111c9c313b5574cd8", size = 591617, upload-time = "2026-02-20T22:50:24.532Z" }, - { url = "https://files.pythonhosted.org/packages/d0/f0/758c3b0fb0c4871c7704fef26a5bc861de4f8a68e4831669883bebe07b0f/uuid_utils-0.14.1-pp311-pypy311_pp73-macosx_10_12_x86_64.whl", hash = "sha256:12c65020ba6cb6abe1d57fcbfc2d0ea0506c67049ee031714057f5caf0f9bc9c", size = 303702, upload-time = "2026-02-20T22:50:40.687Z" }, - { url = "https://files.pythonhosted.org/packages/85/89/d91862b544c695cd58855efe3201f83894ed82fffe34500774238ab8eba7/uuid_utils-0.14.1-pp311-pypy311_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0b5d2ad28063d422ccc2c28d46471d47b61a58de885d35113a8f18cb547e25bf", size = 337678, upload-time = "2026-02-20T22:50:39.768Z" }, - { url = "https://files.pythonhosted.org/packages/ee/6b/cf342ba8a898f1de024be0243fac67c025cad530c79ea7f89c4ce718891a/uuid_utils-0.14.1-pp311-pypy311_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:da2234387b45fde40b0fedfee64a0ba591caeea9c48c7698ab6e2d85c7991533", size = 343711, upload-time = "2026-02-20T22:50:43.965Z" }, - { url = "https://files.pythonhosted.org/packages/b3/20/049418d094d396dfa6606b30af925cc68a6670c3b9103b23e6990f84b589/uuid_utils-0.14.1-pp311-pypy311_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:50fffc2827348c1e48972eed3d1c698959e63f9d030aa5dd82ba451113158a62", size = 476731, upload-time = "2026-02-20T22:50:30.589Z" }, - { url = "https://files.pythonhosted.org/packages/77/a1/0857f64d53a90321e6a46a3d4cc394f50e1366132dcd2ae147f9326ca98b/uuid_utils-0.14.1-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c1dbe718765f70f5b7f9b7f66b6a937802941b1cc56bcf642ce0274169741e01", size = 338902, upload-time = "2026-02-20T22:50:33.927Z" }, - { url = "https://files.pythonhosted.org/packages/ed/d0/5bf7cbf1ac138c92b9ac21066d18faf4d7e7f651047b700eb192ca4b9fdb/uuid_utils-0.14.1-pp311-pypy311_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:258186964039a8e36db10810c1ece879d229b01331e09e9030bc5dcabe231bd2", size = 364700, upload-time = "2026-02-20T22:50:21.732Z" }, +version = "0.16.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/01/a1/822ceef22d1c139cffebe4b1b660cfaa10253d5c770aa2598dc8e9497593/uuid_utils-0.16.0.tar.gz", hash = "sha256:d6902d4375dfba4c9902c736bb82d3c040417b67f7d0fa48910ddfdb1ac95de7", size = 42596, upload-time = "2026-05-19T07:44:23.28Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/fd/78/fc830a25597001586770f0436a4917aac21fcdaf7ac2824bbe168ccdc724/uuid_utils-0.16.0-cp310-cp310-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:a632fead2a6505a8df3318d5e95503739b9aa1c518521cd93d83ce00699b78f8", size = 566691, upload-time = "2026-05-19T07:45:14.2Z" }, + { url = "https://files.pythonhosted.org/packages/10/39/3f1eee6d3c3c33d6dd75441bdb49ac246de57f97f67faa7ff04cdb5e4ffe/uuid_utils-0.16.0-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:d716e5b35266400d2a2cd349697868179825f113c543e55c9d2ac304991f8d4f", size = 291039, upload-time = "2026-05-19T07:45:52.28Z" }, + { url = "https://files.pythonhosted.org/packages/c6/85/f7fb16eed216fd8085d62d4ce7179e2a81ac7649e043f34168e7700b6df4/uuid_utils-0.16.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:207c2a98ca8b065cc93378a3a59744efb88a68e9ecc2c3afefe43d59c864280a", size = 327880, upload-time = "2026-05-19T07:44:28.611Z" }, + { url = "https://files.pythonhosted.org/packages/06/ea/b2b629d29c8234677850e1ae47add9c8866dfb3864af257542989a13ba1b/uuid_utils-0.16.0-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:79824850330e450c7b2fa933572e32192240060937426052fa3fc05134ed3faa", size = 334090, upload-time = "2026-05-19T07:44:57.354Z" }, + { url = "https://files.pythonhosted.org/packages/1b/8e/a6871c6231244bb80be06a2babf3ca34396b29d893103d84ddfd3654e6e4/uuid_utils-0.16.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d89927c47e1a55509e90b7f2fd3e7ff89908c77b61f8f0deda97a89d8854e0f8", size = 448558, upload-time = "2026-05-19T07:45:03.986Z" }, + { url = "https://files.pythonhosted.org/packages/bf/d0/b606a2857f98c20c149044e80f276ff7966c9f679fc7b25f6d608bd8d48b/uuid_utils-0.16.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f7ae4168e1ca0ae69d24207645a8b3cd2b641a0ad15058eda17d2c9898aa89d3", size = 327733, upload-time = "2026-05-19T07:43:40.129Z" }, + { url = "https://files.pythonhosted.org/packages/2d/e1/7951dd47b6717b6ebb340e673d31d539be928d280a697fab4dd233bcc7fa/uuid_utils-0.16.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d363017a3223de3a57eb6fca135df6ffcef7c534836bff2e71354dce7d10987c", size = 353659, upload-time = "2026-05-19T07:44:03.551Z" }, + { url = "https://files.pythonhosted.org/packages/a2/5d/f46e91fad5f049c7bd12701293c1ac31b4460ec83606c4bdd37c05abef52/uuid_utils-0.16.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:4a87a7433b355eadaa200f150da6bb5b87bb6de0adf260883b26cb637aba0410", size = 504509, upload-time = "2026-05-19T07:44:34.147Z" }, + { url = "https://files.pythonhosted.org/packages/f4/94/ea4f559e5e87da5847ecf78ba68a78e8bb4e537e1169093ea543cab94886/uuid_utils-0.16.0-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:6da070e75b0e2424728e6f8547647cce36c83f9a6101a08da4849a8ab2b58105", size = 609358, upload-time = "2026-05-19T07:44:39.711Z" }, + { url = "https://files.pythonhosted.org/packages/bf/41/60dbac2459426a925b77e08cb8ec492d4bc82caa0f124f498d2e24409cb8/uuid_utils-0.16.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:1baab8966f9e0097cbaf9cc01ad448b38e616e7b4968ca5e49cb53a74ad91a2f", size = 569428, upload-time = "2026-05-19T07:44:46.025Z" }, + { url = "https://files.pythonhosted.org/packages/e8/90/ae39c1e1bff65dfe9c7c70cbd64b8d529a3d1cc836aeaa7accdc44e5c308/uuid_utils-0.16.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:b42014536943c1a654ff107538c0f7dc39809d8d774ec8dafd19bec05006e568", size = 532465, upload-time = "2026-05-19T07:44:05.127Z" }, + { url = "https://files.pythonhosted.org/packages/03/5c/4dc93017a095c9c314525a9abc4f9983e520d88d7eff9bd52398d81c374e/uuid_utils-0.16.0-cp310-cp310-win32.whl", hash = "sha256:228701ab6f188b6def24f2add6db64f0794adb1f06d0abacdcec40b0cda13cdf", size = 171162, upload-time = "2026-05-19T07:44:58.518Z" }, + { url = "https://files.pythonhosted.org/packages/43/df/1398f5b117d5daa4d757b156728db7aa092a3eff1271c40ec39dbe945327/uuid_utils-0.16.0-cp310-cp310-win_amd64.whl", hash = "sha256:10d3c5983f770b1b2847ad811c87a1c9e28f8155d1a27cc581abcd5abb386b64", size = 176927, upload-time = "2026-05-19T07:44:54.93Z" }, + { url = "https://files.pythonhosted.org/packages/24/24/0e18177e2fbb0b9f54f90fd48fe3302dfda731e22ad650d6e6f8f4b3d3d3/uuid_utils-0.16.0-cp311-cp311-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:04af9966ecd82b78eeba5725e29aa1e86fb8eb84b5443dd6a9935f9fadb6678e", size = 565929, upload-time = "2026-05-19T07:44:06.496Z" }, + { url = "https://files.pythonhosted.org/packages/5a/7e/bb91b04b2c8a081a4df2d50f1a50dd85502e2391c6eaed71b339ec9f2524/uuid_utils-0.16.0-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:3d86ca394e0ea21bdb53784eb99276d263b93d1586f56678cab1414b7ae1d0f3", size = 290556, upload-time = "2026-05-19T07:43:44.973Z" }, + { url = "https://files.pythonhosted.org/packages/69/2a/47ee18b294af59754ef5acfa96eb027137c98cef7521199b6f70be705de4/uuid_utils-0.16.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c9f504efeb20ffd9571621658f7c8093c646d33150406d5742e49ff7cd861615", size = 328059, upload-time = "2026-05-19T07:45:30.533Z" }, + { url = "https://files.pythonhosted.org/packages/89/7c/ed6d8bb48eeecaed6722af1187d722c5243334be750419d10d5f05dffeb2/uuid_utils-0.16.0-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:57d85f48535dc541060f6b82f277cbcd12b78c04008ccc1039546cfcec027327", size = 334759, upload-time = "2026-05-19T07:45:07.715Z" }, + { url = "https://files.pythonhosted.org/packages/ff/33/371bddf9fd47e045c375df9668eea0d96ce9201ab6a03985b0155498e376/uuid_utils-0.16.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:39453f1ebf4398fbeb71607f3437e2ac469c9e38b5921755c1e17ad0158a8907", size = 448927, upload-time = "2026-05-19T07:45:11.464Z" }, + { url = "https://files.pythonhosted.org/packages/dc/f1/b201d5ee005d4987fc072714fcb9f6e75303520cf19d4deec0b4df44bf40/uuid_utils-0.16.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:50361aca5c2a770728a6343df85109fe57f89ac026827f34fe0153563cdc9ce7", size = 327178, upload-time = "2026-05-19T07:44:02.255Z" }, + { url = "https://files.pythonhosted.org/packages/b1/6a/04b4c02ce5c24a3602baa12e59bd3ec853ae73c3e9319b706c4620f47a05/uuid_utils-0.16.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:948485c47d8569a8bf6e86f522a2599fa9134674bee9f483898e601e68c3caca", size = 352981, upload-time = "2026-05-19T07:44:25.578Z" }, + { url = "https://files.pythonhosted.org/packages/2c/19/25db019727d14630c75c2a75a8ea66dd712bb468adcf410bac8d01ff19fd/uuid_utils-0.16.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:ceef237cf8467fddbf6d8466cc1f6e2c04605ec919046ef5eba10a895b559fcf", size = 504686, upload-time = "2026-05-19T07:43:46.43Z" }, + { url = "https://files.pythonhosted.org/packages/5d/93/c000cd42ebfdd37cc74981ed31c979a1270156572bdebab8b5d61460e750/uuid_utils-0.16.0-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:24e6fa0d0ade7a9ad60a3c296022474983243df5b4e863babb4828a85ef2e52c", size = 610102, upload-time = "2026-05-19T07:45:53.765Z" }, + { url = "https://files.pythonhosted.org/packages/15/1d/7dd239909c82616722b9ee53fa1b4657c6244fb4fd026890300ebf6db22b/uuid_utils-0.16.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:1c2df42314b014c9d23330f92887e21d2fc72fde0beb170c7833cd2d22d845a1", size = 569048, upload-time = "2026-05-19T07:45:41.596Z" }, + { url = "https://files.pythonhosted.org/packages/f1/49/b6a688648368a9cc0137e183657956853a91dc06ef73deda27290d586155/uuid_utils-0.16.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:2e2f369dd734050fe96ae4905c58779b09276d47d5e9a0e5cd33ec7982784341", size = 532255, upload-time = "2026-05-19T07:45:16.936Z" }, + { url = "https://files.pythonhosted.org/packages/3f/fb/34f221ae93d5ea249a0d7056bdf45313b8d267d6aa9c5d0673ac1a4746c7/uuid_utils-0.16.0-cp311-cp311-win32.whl", hash = "sha256:733da81d51ea578862d8b9b754e8968b6da2be2b7840aee868917c23cae84015", size = 171081, upload-time = "2026-05-19T07:45:26.578Z" }, + { url = "https://files.pythonhosted.org/packages/a5/70/c2a608a813f655834ee6df4ce53ea46edad4d54f774eac1890be5c7e4e1c/uuid_utils-0.16.0-cp311-cp311-win_amd64.whl", hash = "sha256:10d21fddb086e69245c4f0f77c7b442471f3a242aa85f62954bff157baa1c5f2", size = 176770, upload-time = "2026-05-19T07:43:49.102Z" }, + { url = "https://files.pythonhosted.org/packages/fd/c3/8ab4eff328a833c065f280b2e0d9ac873505b5e5282f2bc5133a9843d4dd/uuid_utils-0.16.0-cp311-cp311-win_arm64.whl", hash = "sha256:98e2404713677070cee9a99a1f1e24afd496c18e833ee1b31a0587659452ff80", size = 175274, upload-time = "2026-05-19T07:44:27.216Z" }, + { url = "https://files.pythonhosted.org/packages/ff/4c/b4cf43a5d22bcdb91727acdf54be0d78e83e595b73c5a9a8a4291875f059/uuid_utils-0.16.0-cp312-cp312-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:727fae3f0682191ec9c8ce1cd0f71e81b471a2e26b7c5fd66712fc0f11640aa0", size = 562183, upload-time = "2026-05-19T07:45:02.683Z" }, + { url = "https://files.pythonhosted.org/packages/d6/fb/4b0d1c4b5e9f8679ca41b9cdbce5749e1d5db3d3d42a07060d6ce61ac583/uuid_utils-0.16.0-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:66a9c8cedf7695c28e700f6a66bde0809c3b2e0d8a70968be7bfd47c908952e5", size = 289018, upload-time = "2026-05-19T07:44:07.726Z" }, + { url = "https://files.pythonhosted.org/packages/de/43/2dc6c7401c8fab86e46b0b33ada6dcfde949b2fd48877ba6f880862be80e/uuid_utils-0.16.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9152bff801ec2ccf630df06d67389090a2c612dea87fbf9a887ab4b222929f6f", size = 326171, upload-time = "2026-05-19T07:45:25.186Z" }, + { url = "https://files.pythonhosted.org/packages/9b/f5/48f11fb91f36453611ca148bc441436f279870b1ec6b576dc5167fb6e680/uuid_utils-0.16.0-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:06fc7db470c37e5c1ab3fd2cd159697d6f8b279d7d23b5b96bd418b115f8caa9", size = 332222, upload-time = "2026-05-19T07:45:09.036Z" }, + { url = "https://files.pythonhosted.org/packages/30/cb/b2b49528521e4a097f129e8bf7850a26f00af46afba778832cf3458a5c00/uuid_utils-0.16.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3e1a1f57fe3631e164dad27b24aa81267810e20575f705af3b0fa734f3a21247", size = 444801, upload-time = "2026-05-19T07:45:37.517Z" }, + { url = "https://files.pythonhosted.org/packages/a9/b3/a28d9c6f7c701dfe01c8020b30e33899a28eb9e4d056b07e7388f50ebf67/uuid_utils-0.16.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3ee392fe59808a731b7b6bf4d453fb6e833774921331cceae5f254d1e9c5b97d", size = 325594, upload-time = "2026-05-19T07:44:44.682Z" }, + { url = "https://files.pythonhosted.org/packages/cf/65/e1ff41dc44966e396ead86e104ba21b35ddb07ff7a64bb55013074ee77fe/uuid_utils-0.16.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:b2e981b1258db444df4cf4bf4c79673570d081d48d35f22d0f86471e0ad795c5", size = 349312, upload-time = "2026-05-19T07:45:15.582Z" }, + { url = "https://files.pythonhosted.org/packages/ed/57/fb19b7951f66a46e03bd1943a61ee9d59c83e994e56e8c97d79aff1f0e47/uuid_utils-0.16.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:bbb92feb4db08cd76e27b4d3b1a82bfde708447317150c614eb9f761a43b387e", size = 502115, upload-time = "2026-05-19T07:43:38.756Z" }, + { url = "https://files.pythonhosted.org/packages/2f/8e/9a129c469b7b77afb62da5c6b7e92591073b845bd0c3108c0d0aa65389fb/uuid_utils-0.16.0-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:1c3c5afaaa68b1d6393d653e9fc93a2fde9da1681da01f74b4593f41d31fb5f1", size = 607433, upload-time = "2026-05-19T07:44:11.675Z" }, + { url = "https://files.pythonhosted.org/packages/4a/56/2ef71fad168cc3d894f7094fa458086c093635d7835381c91470b19c9ad3/uuid_utils-0.16.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:38126b353527c5f001e4b24db9e62351eb768d0367febcd68100a4b39a035109", size = 566076, upload-time = "2026-05-19T07:44:35.453Z" }, + { url = "https://files.pythonhosted.org/packages/95/bf/68e60ea053ca30f35df877b96001331398140d5c4983561affa1350331b1/uuid_utils-0.16.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:41a67e546d9adf11c4e4cb5c8e81f000f8b1f000c17912ced089b499855719a5", size = 530645, upload-time = "2026-05-19T07:45:49.278Z" }, + { url = "https://files.pythonhosted.org/packages/42/19/b521f7d73094fca4c0c44002f4a42bfcbcf0b770fdc3c4b9a596dda25734/uuid_utils-0.16.0-cp312-cp312-win32.whl", hash = "sha256:52d2cc8c12a3466cd1727883e0746d8bad5dddd670369eb553ba17fdc3b565ca", size = 168887, upload-time = "2026-05-19T07:45:45.502Z" }, + { url = "https://files.pythonhosted.org/packages/87/1f/4126c3ccbc2d98a613664e55f6ab6d7bd4b98424a04486e4fcc76549af15/uuid_utils-0.16.0-cp312-cp312-win_amd64.whl", hash = "sha256:c97625e5edfda8b118160ce1e88756f92b1635775f836c168be7bf10928d97fa", size = 174607, upload-time = "2026-05-19T07:43:52.938Z" }, + { url = "https://files.pythonhosted.org/packages/74/62/b83ccc8446ae39dcc0bda2cb3b525b6af6a2036383afe1d1d5fe7b234c2c/uuid_utils-0.16.0-cp312-cp312-win_arm64.whl", hash = "sha256:baf79c8050eb784b252dd34807df73f61130fe8676b61231baccab62530f20ec", size = 173021, upload-time = "2026-05-19T07:45:10.204Z" }, + { url = "https://files.pythonhosted.org/packages/60/9b/74c1f47a9b4f138a254e51528e5ffaeba6bf99ecead9f0c4b6fccccfbfcb/uuid_utils-0.16.0-cp313-cp313-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:d34cf9681e8892fad2a63e393068e544505408748cd8bf0c3517d753a01528d4", size = 563166, upload-time = "2026-05-19T07:44:10.494Z" }, + { url = "https://files.pythonhosted.org/packages/7c/1c/009e37b70f1f0ff17e7103a36bafde33d503d9ea7fe739761aa3e3c9fde6/uuid_utils-0.16.0-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:0681d1bdb7956e0c6d581e7601dabcfb2b08c25d2a65189f4e9b102c94f5ff46", size = 289529, upload-time = "2026-05-19T07:43:54.466Z" }, + { url = "https://files.pythonhosted.org/packages/5e/5e/e0323d54321166639eb2be5e8a464f5cb0fc04d72d91f3e78944bb6a1da8/uuid_utils-0.16.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ed45fb8732d216426227096b55accbb87cba57febc86a044d90780b090eb99d0", size = 326328, upload-time = "2026-05-19T07:45:31.901Z" }, + { url = "https://files.pythonhosted.org/packages/f0/a3/046f6cb958467c3bf4a163a8a53b178b64a62e21ed8ad5b2c1dacb3a2cfc/uuid_utils-0.16.0-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:b617a334bb01ef2ff8c22900f5a14125eb9063f602131494cc9dc59519beaa5b", size = 332322, upload-time = "2026-05-19T07:43:41.284Z" }, + { url = "https://files.pythonhosted.org/packages/67/80/01914e3949744db7acd0006885e5542fbebb6e39114857d007d29b3265c2/uuid_utils-0.16.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a750d8aeb8ae880aa9a2529606bde0e994bcc7448730c953107f357a28e6102e", size = 445787, upload-time = "2026-05-19T07:45:36.102Z" }, + { url = "https://files.pythonhosted.org/packages/14/ef/f6908f41279f205d70c8a0d5dcb25dd6802741d7f88e3f0123453c3584d3/uuid_utils-0.16.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9a250e111903c4368745fce5ac2aa607bd477c62d3307e45347338fdb64b38e0", size = 324678, upload-time = "2026-05-19T07:45:12.77Z" }, + { url = "https://files.pythonhosted.org/packages/11/4a/bf841ba90f829c7779d82155e0f4b88ef6726ccc25507d064d50ac2cd329/uuid_utils-0.16.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:95b7f480010ea98a29ee809857a98aa923008c68129af1b39244adccff7377fb", size = 349704, upload-time = "2026-05-19T07:44:47.172Z" }, + { url = "https://files.pythonhosted.org/packages/e6/31/3b5c60172b8c57bf4ca485484b8e4edef550ca324f9287f1183be97422e2/uuid_utils-0.16.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:420aa3ca403cedb73490b6ea3aeefeea7e0455f5ce60bbf856390ee872ae3306", size = 502456, upload-time = "2026-05-19T07:45:00.821Z" }, + { url = "https://files.pythonhosted.org/packages/88/bf/3da8d497af80fd51d8bf85551c77ede67f07825924ec5987bf9b6031014a/uuid_utils-0.16.0-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:b8a9a7b1065a12d40f2cc25b7d705ab34954cc57095034367bca39ebcf4a876b", size = 607727, upload-time = "2026-05-19T07:44:30.058Z" }, + { url = "https://files.pythonhosted.org/packages/bd/4e/7c8cf03ec15cd6f40e4cbab81b2b4a625461327f68c7971e54723280ec3e/uuid_utils-0.16.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:f235ac5827d74ac630cc87f29278cdaa5d2f273613a6e05bbd96df7aa4170776", size = 566204, upload-time = "2026-05-19T07:44:51.225Z" }, + { url = "https://files.pythonhosted.org/packages/f9/5f/af955feae69cce7fd2121ca3f790ff4b85ad2e17b2149546f50753e1a047/uuid_utils-0.16.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:c8083284488b84ad178e74add64cfd1e74e8be5e30821e5acbc5019281c658b0", size = 529986, upload-time = "2026-05-19T07:45:57.85Z" }, + { url = "https://files.pythonhosted.org/packages/10/cf/3fec757e51bef10eb41ae8075f5442c60e85ff456b42d16a3063f5dc6c80/uuid_utils-0.16.0-cp313-cp313-pyemscripten_2025_0_wasm32.whl", hash = "sha256:27a071a899ba46a551d6524dbbc5a98b88be176d0f55ddf72cf71c005326ac10", size = 98683, upload-time = "2026-05-19T07:44:16.369Z" }, + { url = "https://files.pythonhosted.org/packages/40/a7/cd1adbea7ef882a70db064c00cd93b12e11027b4cdd7ffd79e95c35fc3e3/uuid_utils-0.16.0-cp313-cp313-win32.whl", hash = "sha256:924a8de04460e4cf65998ad0b6568084f7c51740ebd3254d07a0bcde35a84af6", size = 168822, upload-time = "2026-05-19T07:44:24.09Z" }, + { url = "https://files.pythonhosted.org/packages/74/99/617ceb9e3a95b23837012740979baf71afad723b70daf34862da3f7c17a1/uuid_utils-0.16.0-cp313-cp313-win_amd64.whl", hash = "sha256:5279bc7ab3c6683f1c67314695bee14d869015acbbc677bdb0015190fe753d16", size = 174967, upload-time = "2026-05-19T07:44:56.022Z" }, + { url = "https://files.pythonhosted.org/packages/d9/d8/148ae707bfc36d482e39db679c86b81bdce264d4feb9df5d40a03b7687e3/uuid_utils-0.16.0-cp313-cp313-win_arm64.whl", hash = "sha256:61a9c4c26ad12ac66fa4bfd0fdb8494724fe7a5b98a9fcd43e78e2b388663dbb", size = 173142, upload-time = "2026-05-19T07:43:50.171Z" }, + { url = "https://files.pythonhosted.org/packages/21/05/ca6d60705e71fdeaa3431dad94e279a8213c5573cb2925e1aabf3dc0330a/uuid_utils-0.16.0-cp313-cp313t-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:73486b6aa3f755a6c97000f5ea67e7ac78d6df89bf22980789a1e943e24b74f0", size = 564408, upload-time = "2026-05-19T07:44:38.351Z" }, + { url = "https://files.pythonhosted.org/packages/eb/8c/b9a0462c38535c1662acb1025768e2d626bee5ce9e1790bad6b5381162ea/uuid_utils-0.16.0-cp313-cp313t-macosx_10_12_x86_64.whl", hash = "sha256:f1614572fd9345cdc3dde3f40c237345719fabca1aa87d2d87b321d523cfa34d", size = 289923, upload-time = "2026-05-19T07:45:19.611Z" }, + { url = "https://files.pythonhosted.org/packages/f2/33/a53afeef1a56051551a0f5a801e4bce411dd73c6a8c99bad16902651256d/uuid_utils-0.16.0-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9346ce6eb1fbd8b03a6b331d66016afcb4edcdff6eac708e21391600529a016a", size = 325762, upload-time = "2026-05-19T07:45:18.261Z" }, + { url = "https://files.pythonhosted.org/packages/72/ca/4462a4f36365d7ee72d41e05e6bcfe127e861b073ab37c25b2c8a518317c/uuid_utils-0.16.0-cp313-cp313t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:a0fc6eb3fd821466fbab69cf356c6ec2b7327266bbbc740a2eb57c77c4bef965", size = 332359, upload-time = "2026-05-19T07:45:34.886Z" }, + { url = "https://files.pythonhosted.org/packages/c5/67/9d3373fa7c5a746fdecc64e30caf915c29eb632203508d87676f9243ed03/uuid_utils-0.16.0-cp313-cp313t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:13a797e5e8f0dadc18351a5aa013815ddac25dce6864072a539d510910c95f71", size = 445483, upload-time = "2026-05-19T07:44:49.598Z" }, + { url = "https://files.pythonhosted.org/packages/57/08/ce01aa6d897fc7f875844fe58cad0a542c8ebf089d9242b654b56260ecb8/uuid_utils-0.16.0-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:57c3583b1f1c00a94f59726a5e2b988fa209221143919a1af5c2fc24e318fc98", size = 326281, upload-time = "2026-05-19T07:44:59.677Z" }, + { url = "https://files.pythonhosted.org/packages/76/ef/2c719b2c26bb5b5e5061a1435c11ad2bd33ac3cd6d4cd0c7c3ac1d3396ed/uuid_utils-0.16.0-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:caac9c8b1d50e8fbddc76e93bfefbef472978eb45adbfdb6289d578816992953", size = 350809, upload-time = "2026-05-19T07:45:28.076Z" }, + { url = "https://files.pythonhosted.org/packages/e0/9b/c1ed447328b32229cca38ac4c62d309eab006e5e9c4020e2056a175bc607/uuid_utils-0.16.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:91db59bad97ed2b9d2c6ed25082fe9762b2c422e694fe06786b28cf4e776ac4c", size = 502088, upload-time = "2026-05-19T07:44:09.208Z" }, + { url = "https://files.pythonhosted.org/packages/c1/e0/8442f4efe7bde72f0b4ae5f675d0c7fbe209ad0b54718b8ddf43c46c6fae/uuid_utils-0.16.0-cp313-cp313t-musllinux_1_2_armv7l.whl", hash = "sha256:41985e342a30e76366a8becc60bbdb07d72cd1b86ec657b1f31654e9fb1baada", size = 607631, upload-time = "2026-05-19T07:44:19.384Z" }, + { url = "https://files.pythonhosted.org/packages/f1/1e/9a9fa261edf4c972f28ae83421377e3ab8dbd0bd7db58fd316e782d09a3b/uuid_utils-0.16.0-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:1b0dcedf9266bf34a54d5cbe78648eaa627e02352f2a6923ed647530aea2f661", size = 567618, upload-time = "2026-05-19T07:43:58.478Z" }, + { url = "https://files.pythonhosted.org/packages/cc/f7/1bcfdb9d539bd42736dd6076470a42fbb5db23f79712c0a06aa0a3752f7b/uuid_utils-0.16.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:26fe23ab60f05de4ad70aaa5b6a4c2a7bbd43055e3dd6f6b31efba0532ac9c71", size = 530971, upload-time = "2026-05-19T07:45:06.348Z" }, + { url = "https://files.pythonhosted.org/packages/24/0c/18945f417d6bb4d0dd2b7652fe36c58c4e83bcf593b9b326b83aa40b853a/uuid_utils-0.16.0-cp313-cp313t-win32.whl", hash = "sha256:7f8cf49c05d58523a0f977cb7f11afc05791a0fa164d7303b8365a34750638e7", size = 169369, upload-time = "2026-05-19T07:44:32.581Z" }, + { url = "https://files.pythonhosted.org/packages/cc/cc/c0eb0c3fab2ed80d706369b750029143b53126809b77b36bcbb77da66bab/uuid_utils-0.16.0-cp313-cp313t-win_amd64.whl", hash = "sha256:e99f9a8b2420b228faba23a637e96efaf5c6a678b2e225870f24431c82707f50", size = 175384, upload-time = "2026-05-19T07:45:56.623Z" }, + { url = "https://files.pythonhosted.org/packages/b7/77/50ac87b6e18b1c686f700aa38c9471a990683c6a955f71ac1a6677ed8145/uuid_utils-0.16.0-cp314-cp314-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:6853b627983aa1b4fd95aa52d9e87136eb94a7b3b7de0fbb1db8a498d457eeec", size = 564108, upload-time = "2026-05-19T07:43:55.609Z" }, + { url = "https://files.pythonhosted.org/packages/83/16/65046676de246bb5334d9f58aa96d2feb9fc347fda3556aaff7da1c2fc7a/uuid_utils-0.16.0-cp314-cp314-macosx_10_12_x86_64.whl", hash = "sha256:f44b65ae0c329843817d9c90e36a7a3c677b413bf407c99e67db874dac49dad3", size = 289967, upload-time = "2026-05-19T07:45:38.886Z" }, + { url = "https://files.pythonhosted.org/packages/91/d6/54fa988606a15dfd2028e925d8eb9c3ee6edbf1eb7692a67b37282880b56/uuid_utils-0.16.0-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:de8a365795a76f347f5622621c2bee543cffa0c70949f3ee093bdefc9d926dcc", size = 325835, upload-time = "2026-05-19T07:44:42.02Z" }, + { url = "https://files.pythonhosted.org/packages/d5/1b/50622f967ceacea1f89fd065d9bfd395b51acb02cfb0a4ddc8fa9ff0c983/uuid_utils-0.16.0-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:426a8c9af90242d879706ccf29da56f0b0712e7739fb0bbe16baacabc75596e2", size = 332607, upload-time = "2026-05-19T07:43:42.42Z" }, + { url = "https://files.pythonhosted.org/packages/12/f5/4059706be6617e2787e375ea52994ce3c3fa3920b7d4a9c8ebf7895681a5/uuid_utils-0.16.0-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:833bc4b3c3fc24be541f67b01b4a75b6b9942a9b7137395b4eb35435948bd6da", size = 444287, upload-time = "2026-05-19T07:43:37.106Z" }, + { url = "https://files.pythonhosted.org/packages/65/d5/f44b2710563da687a368f0ce4dcbd462dfb6708bcd46439d831991d595c7/uuid_utils-0.16.0-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:efb5252d7c00d586077f10e169d6e6d0b0d0f806d8a085073f0d19b4737aef4e", size = 324949, upload-time = "2026-05-19T07:45:33.175Z" }, + { url = "https://files.pythonhosted.org/packages/3a/a7/a69e859e37d26c5603f0bc0ae481860f691224f140e5a832f325b804770d/uuid_utils-0.16.0-cp314-cp314-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:0b3377ce388fd7bf8d231ec9d1d4f58c8e87888ddea93581f60ed6f878a4f722", size = 349651, upload-time = "2026-05-19T07:43:59.998Z" }, + { url = "https://files.pythonhosted.org/packages/db/73/4139cd3ca7b81ea283c1c8769373e9b2008241c0744a8ffb25f0a1b31325/uuid_utils-0.16.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:12b6310beb38adc173ec5dc89e98812fd7e3d98f87f3ef01d2ea6ecb5d87994f", size = 502326, upload-time = "2026-05-19T07:45:40.292Z" }, + { url = "https://files.pythonhosted.org/packages/cb/8c/858101583fbad1b3fa04da88b1f7170836aa0f00b4cb712063325c44466d/uuid_utils-0.16.0-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:a49b5a75497643479c919e2e537a4a36224ac3aaa0fada61b75d87024021ac3e", size = 607689, upload-time = "2026-05-19T07:44:48.355Z" }, + { url = "https://files.pythonhosted.org/packages/5e/bd/8f3d54a4763dd91ebd0f3d7b0c2ec434e4e0b1fc667b03a44d611a465ec6/uuid_utils-0.16.0-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:63bfdf00be51b6b3b79275d6767d034ea5c7a0caa067a35d72861284100cb60a", size = 566214, upload-time = "2026-05-19T07:44:53.519Z" }, + { url = "https://files.pythonhosted.org/packages/54/76/4c9a8d9baaa243c7902d84dbba4d51b1ab51c379c66d3fd6368ff6933ecf/uuid_utils-0.16.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:7525bc59ac4579c32317d2493dd42cf134b9bb50cd0bc6a41dd9f77e4740dde6", size = 529989, upload-time = "2026-05-19T07:44:43.141Z" }, + { url = "https://files.pythonhosted.org/packages/6d/13/d32cea997f880cedde415730ce0e872ebfd7a040155ae0bbda70eccd208e/uuid_utils-0.16.0-cp314-cp314-win32.whl", hash = "sha256:fbcac6e6710aa2e4bfbb81762758e01470dc56d5048ba4253acc77c9833568ff", size = 169146, upload-time = "2026-05-19T07:45:46.655Z" }, + { url = "https://files.pythonhosted.org/packages/1c/19/9fc55172d8fe59e1f27a14d598b427fa508a7ebb35fa7b7b99c24fa0ef13/uuid_utils-0.16.0-cp314-cp314-win_amd64.whl", hash = "sha256:d23fcaf37368a1647319187ef6f8b741bf079f033065899bc2d00a44b0a1214a", size = 175364, upload-time = "2026-05-19T07:45:55.335Z" }, + { url = "https://files.pythonhosted.org/packages/89/5d/fcd9226b715c5aa0638fcdd6deaf0de6c6c3c451c692cd76bfca810c6512/uuid_utils-0.16.0-cp314-cp314-win_arm64.whl", hash = "sha256:ea3265f8e2b452a4870f3298cb1d183dc4e36a3682cbb264dbe46af31267e706", size = 173268, upload-time = "2026-05-19T07:44:31.19Z" }, + { url = "https://files.pythonhosted.org/packages/c1/64/97ec9af95e58b8187f2934008ffab26e1604d149e34fe01c388b0543a24f/uuid_utils-0.16.0-cp314-cp314t-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:99f8420c3ed59f89a086782ac197e257f4b1debb4545dffa90cf5db23f96c892", size = 564464, upload-time = "2026-05-19T07:44:40.856Z" }, + { url = "https://files.pythonhosted.org/packages/3e/6d/e4082f407484ac28923c0bf8e861e71d277118d8b7542d0a350340e45350/uuid_utils-0.16.0-cp314-cp314t-macosx_10_12_x86_64.whl", hash = "sha256:259bab73c241743d684dcc3507feb76f484d720545e4e4805582aeff8e19700b", size = 290087, upload-time = "2026-05-19T07:44:01.084Z" }, + { url = "https://files.pythonhosted.org/packages/8c/43/c5c5f273c0ff889f20f10344784f9197dd00eb81ccc294330d4b949fea7e/uuid_utils-0.16.0-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:897e8ef0dc5e4ac0b17cf9cae84bb41e560d806280ec5b93db7475b504022105", size = 325532, upload-time = "2026-05-19T07:43:47.508Z" }, + { url = "https://files.pythonhosted.org/packages/13/7f/669aa899ab5378374d28a28231e6978f739921a1af394c7ebd6cc86e2639/uuid_utils-0.16.0-cp314-cp314t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:c5af79cde16a7600dfccb7d431aec0afd3088ff170b6a09887bf3f7ab3cc7c81", size = 332209, upload-time = "2026-05-19T07:43:51.528Z" }, + { url = "https://files.pythonhosted.org/packages/2b/57/a2a32406d79a222794ef98a19254fd9a81a029a0f32d7740fba9873bff1f/uuid_utils-0.16.0-cp314-cp314t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:bece1a6f677ca36047442c465d8166643eed9818b9e43e0bf42d3cf73e92dcff", size = 445507, upload-time = "2026-05-19T07:44:20.541Z" }, + { url = "https://files.pythonhosted.org/packages/26/6b/85459a35bfa7d73e79acbc4eab1cf6aa6e4d9d022c3260ed9dea539c7f0b/uuid_utils-0.16.0-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2bb3444498e7b099499c8a607d7771377020fa55f7274e46f54106af19f752d7", size = 326154, upload-time = "2026-05-19T07:45:23.587Z" }, + { url = "https://files.pythonhosted.org/packages/84/9e/e965efdbb503ed14d6e57aec1a22b98326ed24cc2fb48e750c4d192267a0/uuid_utils-0.16.0-cp314-cp314t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:542098f6cb6874aebeff98715f3ab7646fbe0f2ffb24509ca372828c68c4ed0e", size = 350905, upload-time = "2026-05-19T07:44:36.957Z" }, + { url = "https://files.pythonhosted.org/packages/23/ae/4321867888a783d03b7c053c0b68ca45d03974d86fcebf44d4ec268db397/uuid_utils-0.16.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:7207b25fe534bcf4d57e0110f90670e61c1c38b6f4598ba855af69ab428fc118", size = 502098, upload-time = "2026-05-19T07:44:17.696Z" }, + { url = "https://files.pythonhosted.org/packages/9d/9a/914a47bf42479bff0ce3e1fa1cbe3585354708edc928e27687cf91de9c26/uuid_utils-0.16.0-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:16dc5c6e439f75b0456114e955983e2156c1f38887733e54d54205d3005223e4", size = 607032, upload-time = "2026-05-19T07:44:22.151Z" }, + { url = "https://files.pythonhosted.org/packages/85/4c/2abacd6badba61a047eaa39c8347656229d12843bd9bbe4906daa6dc752c/uuid_utils-0.16.0-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:a6d3ee32c57898d8415242b08d5dd086bc4f7bcbbb3fc102ef257f3d793eb294", size = 567664, upload-time = "2026-05-19T07:45:21.043Z" }, + { url = "https://files.pythonhosted.org/packages/53/1f/9d1a09521276424da19dc0d74456aed3311170fec181b28fa6acba45d963/uuid_utils-0.16.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:7555f120a2282d1901c9a632c2398a614101af4fe3f7c8114aa0f1d8c1978855", size = 530996, upload-time = "2026-05-19T07:45:44.229Z" }, + { url = "https://files.pythonhosted.org/packages/b4/22/14dbedb6b61f492d5524077fd10bbfb137583b0f0aafa6cd870ccb43f39a/uuid_utils-0.16.0-cp314-cp314t-win32.whl", hash = "sha256:756575d082ea4cb7d2f923d5b640c0efe7c82573aab49220c4e09b62d13737ff", size = 169358, upload-time = "2026-05-19T07:45:05.146Z" }, + { url = "https://files.pythonhosted.org/packages/25/f4/a636806c98401a1108f2456e9cc3fa39a618145bfb1d0860c57203159cfe/uuid_utils-0.16.0-cp314-cp314t-win_amd64.whl", hash = "sha256:aa50261a83991dbb570a00573741455bd8f3249444f7329e5bdcd494799d1504", size = 174813, upload-time = "2026-05-19T07:45:59.579Z" }, + { url = "https://files.pythonhosted.org/packages/75/12/3823742459d87a100deb24bb6b41692aa961b267abd130fa7739cdf7d409/uuid_utils-0.16.0-cp314-cp314t-win_arm64.whl", hash = "sha256:22a17e93a371d850ffce8fcdbacc2239f890efe73aa3262b6170c1febc08afe1", size = 171733, upload-time = "2026-05-19T07:45:29.283Z" }, + { url = "https://files.pythonhosted.org/packages/d3/89/655408a5485c56bf2c4561eb85f5bca119b1f4020370b4daaeb8d13e46fb/uuid_utils-0.16.0-pp311-pypy311_pp73-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:4e35e9a986e86806a61288fac3afbb51317f2580929feefd1661891ffd7b8c24", size = 569295, upload-time = "2026-05-19T07:45:22.325Z" }, + { url = "https://files.pythonhosted.org/packages/24/1c/a7c5506a4e2cf95ac98fec0996c56daa14e41f2ab1858f569b3556a202f9/uuid_utils-0.16.0-pp311-pypy311_pp73-macosx_10_12_x86_64.whl", hash = "sha256:b35706350cf9bd4813f1811bebe03cac09795a5a379f90cb3616171f4e9ffc9e", size = 292316, upload-time = "2026-05-19T07:43:57.044Z" }, + { url = "https://files.pythonhosted.org/packages/dd/75/4267ab8baa1e6a8ad7c262e204484b44df0fde0920025ea9b43c2b869726/uuid_utils-0.16.0-pp311-pypy311_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a4fd5c7936a876ba2606ba124603b559a5c2cea458c59b9c31677e6acc3c53cc", size = 329619, upload-time = "2026-05-19T07:44:12.928Z" }, + { url = "https://files.pythonhosted.org/packages/15/77/c794102831e331564f651099cac55006694677938d70f1033b35da451a89/uuid_utils-0.16.0-pp311-pypy311_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:130f7452c1b87b7c16d0bdc1f32a1de531ae4cc4220ed4e691402bbcfc39e0a9", size = 335121, upload-time = "2026-05-19T07:45:47.974Z" }, + { url = "https://files.pythonhosted.org/packages/8b/3e/458a0a2da75c596b151182a6c7550c6c3d30f479e14e40f69c0336579e59/uuid_utils-0.16.0-pp311-pypy311_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d5ee0bbbd4ca3968422cd8308f0072520bc73dc760cb26c6fa75ca1aca14d210", size = 449631, upload-time = "2026-05-19T07:45:50.645Z" }, + { url = "https://files.pythonhosted.org/packages/ed/15/dd1fab6f7fcd15f2c331d0c1f0f516bb1113a640216460f82be53db3dcf8/uuid_utils-0.16.0-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dc0824a31898ef46a9d84d748c3abe27cdb615ac3773c53cc1f84fc8e66dc7c4", size = 328418, upload-time = "2026-05-19T07:44:52.38Z" }, + { url = "https://files.pythonhosted.org/packages/96/56/62dcd551b140cbeb0f87522da2015b4b9e5818327b920506ad88d28562b0/uuid_utils-0.16.0-pp311-pypy311_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:abfbf5e0c47fb31b37164a99515104e449a0bee36a071dc8b105457a2b35a5e6", size = 356177, upload-time = "2026-05-19T07:45:42.856Z" }, + { url = "https://files.pythonhosted.org/packages/44/e7/3937b9a9d6745b94dbe7b86531e098db8c53b77c8d07df7daa9577a47b8e/uuid_utils-0.16.0-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:680799a9ade01d69c53cb9d41392ced24919d4f600bfab5060b61fca37510097", size = 178508, upload-time = "2026-05-19T07:43:43.774Z" }, ] [[package]] name = "uvicorn" -version = "0.46.0" +version = "0.49.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "click" }, { name = "h11" }, { name = "typing-extensions", marker = "python_full_version < '3.11'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/1f/93/041fca8274050e40e6791f267d82e0e2e27dd165627bd640d3e0e378d877/uvicorn-0.46.0.tar.gz", hash = "sha256:fb9da0926999cc6cb22dc7cd71a94a632f078e6ae47ff683c5c420750fb7413d", size = 88758, upload-time = "2026-04-23T07:16:00.151Z" } +sdist = { url = "https://files.pythonhosted.org/packages/c4/1f/fa18009dea8469069cca78a4e877a008ab78f08b064bfc9ab891579077ff/uvicorn-0.49.0.tar.gz", hash = "sha256:ebf4271aa580d9de97f93192d4595176df6e91f9aae919ca73e4fc07df1e66a3", size = 91284, upload-time = "2026-06-03T22:01:30.448Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/31/a3/5b1562db76a5a488274b2332a97199b32d0442aca0ed193697fd47786316/uvicorn-0.46.0-py3-none-any.whl", hash = "sha256:bbebbcbed972d162afca128605223022bedd345b7bc7855ce66deb31487a9048", size = 70926, upload-time = "2026-04-23T07:15:58.355Z" }, + { url = "https://files.pythonhosted.org/packages/88/fa/e1388bbcf24ef3274f45c0c1c7b501fd14971037c1b6ee23610553307497/uvicorn-0.49.0-py3-none-any.whl", hash = "sha256:ba3d14c3ee7e41c6c654c46c9eb489d33213cdd30aa1696eab1374337c13f68f", size = 71376, upload-time = "2026-06-03T22:01:29.037Z" }, ] [[package]] @@ -6021,11 +6311,11 @@ wheels = [ [[package]] name = "wcwidth" -version = "0.7.0" +version = "0.8.1" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/2c/ee/afaf0f85a9a18fe47a67f1e4422ed6cf1fe642f0ae0a2f81166231303c52/wcwidth-0.7.0.tar.gz", hash = "sha256:90e3a7ea092341c44b99562e75d09e4d5160fe7a3974c6fb842a101a95e7eed0", size = 182132, upload-time = "2026-05-02T16:04:12.653Z" } +sdist = { url = "https://files.pythonhosted.org/packages/49/b4/51fe890511f0f242d07cb1ebe6a5b6db417262b9d2568b460347c57d95cc/wcwidth-0.8.1.tar.gz", hash = "sha256:faf5b4a5366a72dc49cad48cdf21f52bdf63bdda995178e483ba247ff79089b9", size = 1466072, upload-time = "2026-06-08T05:57:23.146Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/41/52/e465037f5375f43533d1a80b6923955201596a99142ed524d77b571a1418/wcwidth-0.7.0-py3-none-any.whl", hash = "sha256:5d69154c429a82910e241c738cd0e2976fac8a2dd47a1a805f4afed1c0f136f2", size = 110825, upload-time = "2026-05-02T16:04:11.033Z" }, + { url = "https://files.pythonhosted.org/packages/bd/6e/95b0e537de1f4d4301f76f944642c6da50d1511cc7b3d64dc418a66c7509/wcwidth-0.8.1-py3-none-any.whl", hash = "sha256:f453740b1e4a4f3291faa37944c555d71056c4da08d59809b307ef4feba695c8", size = 323092, upload-time = "2026-06-08T05:57:21.413Z" }, ] [[package]] @@ -6179,307 +6469,332 @@ wheels = [ [[package]] name = "xxhash" -version = "3.6.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/02/84/30869e01909fb37a6cc7e18688ee8bf1e42d57e7e0777636bd47524c43c7/xxhash-3.6.0.tar.gz", hash = "sha256:f0162a78b13a0d7617b2845b90c763339d1f1d82bb04a4b07f4ab535cc5e05d6", size = 85160, upload-time = "2025-10-02T14:37:08.097Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/34/ee/f9f1d656ad168681bb0f6b092372c1e533c4416b8069b1896a175c46e484/xxhash-3.6.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:87ff03d7e35c61435976554477a7f4cd1704c3596a89a8300d5ce7fc83874a71", size = 32845, upload-time = "2025-10-02T14:33:51.573Z" }, - { url = "https://files.pythonhosted.org/packages/a3/b1/93508d9460b292c74a09b83d16750c52a0ead89c51eea9951cb97a60d959/xxhash-3.6.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:f572dfd3d0e2eb1a57511831cf6341242f5a9f8298a45862d085f5b93394a27d", size = 30807, upload-time = "2025-10-02T14:33:52.964Z" }, - { url = "https://files.pythonhosted.org/packages/07/55/28c93a3662f2d200c70704efe74aab9640e824f8ce330d8d3943bf7c9b3c/xxhash-3.6.0-cp310-cp310-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:89952ea539566b9fed2bbd94e589672794b4286f342254fad28b149f9615fef8", size = 193786, upload-time = "2025-10-02T14:33:54.272Z" }, - { url = "https://files.pythonhosted.org/packages/c1/96/fec0be9bb4b8f5d9c57d76380a366f31a1781fb802f76fc7cda6c84893c7/xxhash-3.6.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:48e6f2ffb07a50b52465a1032c3cf1f4a5683f944acaca8a134a2f23674c2058", size = 212830, upload-time = "2025-10-02T14:33:55.706Z" }, - { url = "https://files.pythonhosted.org/packages/c4/a0/c706845ba77b9611f81fd2e93fad9859346b026e8445e76f8c6fd057cc6d/xxhash-3.6.0-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:b5b848ad6c16d308c3ac7ad4ba6bede80ed5df2ba8ed382f8932df63158dd4b2", size = 211606, upload-time = "2025-10-02T14:33:57.133Z" }, - { url = "https://files.pythonhosted.org/packages/67/1e/164126a2999e5045f04a69257eea946c0dc3e86541b400d4385d646b53d7/xxhash-3.6.0-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:a034590a727b44dd8ac5914236a7b8504144447a9682586c3327e935f33ec8cc", size = 444872, upload-time = "2025-10-02T14:33:58.446Z" }, - { url = "https://files.pythonhosted.org/packages/2d/4b/55ab404c56cd70a2cf5ecfe484838865d0fea5627365c6c8ca156bd09c8f/xxhash-3.6.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8a8f1972e75ebdd161d7896743122834fe87378160c20e97f8b09166213bf8cc", size = 193217, upload-time = "2025-10-02T14:33:59.724Z" }, - { url = "https://files.pythonhosted.org/packages/45/e6/52abf06bac316db33aa269091ae7311bd53cfc6f4b120ae77bac1b348091/xxhash-3.6.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:ee34327b187f002a596d7b167ebc59a1b729e963ce645964bbc050d2f1b73d07", size = 210139, upload-time = "2025-10-02T14:34:02.041Z" }, - { url = "https://files.pythonhosted.org/packages/34/37/db94d490b8691236d356bc249c08819cbcef9273a1a30acf1254ff9ce157/xxhash-3.6.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:339f518c3c7a850dd033ab416ea25a692759dc7478a71131fe8869010d2b75e4", size = 197669, upload-time = "2025-10-02T14:34:03.664Z" }, - { url = "https://files.pythonhosted.org/packages/b7/36/c4f219ef4a17a4f7a64ed3569bc2b5a9c8311abdb22249ac96093625b1a4/xxhash-3.6.0-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:bf48889c9630542d4709192578aebbd836177c9f7a4a2778a7d6340107c65f06", size = 210018, upload-time = "2025-10-02T14:34:05.325Z" }, - { url = "https://files.pythonhosted.org/packages/fd/06/bfac889a374fc2fc439a69223d1750eed2e18a7db8514737ab630534fa08/xxhash-3.6.0-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:5576b002a56207f640636056b4160a378fe36a58db73ae5c27a7ec8db35f71d4", size = 413058, upload-time = "2025-10-02T14:34:06.925Z" }, - { url = "https://files.pythonhosted.org/packages/c9/d1/555d8447e0dd32ad0930a249a522bb2e289f0d08b6b16204cfa42c1f5a0c/xxhash-3.6.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:af1f3278bd02814d6dedc5dec397993b549d6f16c19379721e5a1d31e132c49b", size = 190628, upload-time = "2025-10-02T14:34:08.669Z" }, - { url = "https://files.pythonhosted.org/packages/d1/15/8751330b5186cedc4ed4b597989882ea05e0408b53fa47bcb46a6125bfc6/xxhash-3.6.0-cp310-cp310-win32.whl", hash = "sha256:aed058764db109dc9052720da65fafe84873b05eb8b07e5e653597951af57c3b", size = 30577, upload-time = "2025-10-02T14:34:10.234Z" }, - { url = "https://files.pythonhosted.org/packages/bb/cc/53f87e8b5871a6eb2ff7e89c48c66093bda2be52315a8161ddc54ea550c4/xxhash-3.6.0-cp310-cp310-win_amd64.whl", hash = "sha256:e82da5670f2d0d98950317f82a0e4a0197150ff19a6df2ba40399c2a3b9ae5fb", size = 31487, upload-time = "2025-10-02T14:34:11.618Z" }, - { url = "https://files.pythonhosted.org/packages/9f/00/60f9ea3bb697667a14314d7269956f58bf56bb73864f8f8d52a3c2535e9a/xxhash-3.6.0-cp310-cp310-win_arm64.whl", hash = "sha256:4a082ffff8c6ac07707fb6b671caf7c6e020c75226c561830b73d862060f281d", size = 27863, upload-time = "2025-10-02T14:34:12.619Z" }, - { url = "https://files.pythonhosted.org/packages/17/d4/cc2f0400e9154df4b9964249da78ebd72f318e35ccc425e9f403c392f22a/xxhash-3.6.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:b47bbd8cf2d72797f3c2772eaaac0ded3d3af26481a26d7d7d41dc2d3c46b04a", size = 32844, upload-time = "2025-10-02T14:34:14.037Z" }, - { url = "https://files.pythonhosted.org/packages/5e/ec/1cc11cd13e26ea8bc3cb4af4eaadd8d46d5014aebb67be3f71fb0b68802a/xxhash-3.6.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:2b6821e94346f96db75abaa6e255706fb06ebd530899ed76d32cd99f20dc52fa", size = 30809, upload-time = "2025-10-02T14:34:15.484Z" }, - { url = "https://files.pythonhosted.org/packages/04/5f/19fe357ea348d98ca22f456f75a30ac0916b51c753e1f8b2e0e6fb884cce/xxhash-3.6.0-cp311-cp311-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:d0a9751f71a1a65ce3584e9cae4467651c7e70c9d31017fa57574583a4540248", size = 194665, upload-time = "2025-10-02T14:34:16.541Z" }, - { url = "https://files.pythonhosted.org/packages/90/3b/d1f1a8f5442a5fd8beedae110c5af7604dc37349a8e16519c13c19a9a2de/xxhash-3.6.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8b29ee68625ab37b04c0b40c3fafdf24d2f75ccd778333cfb698f65f6c463f62", size = 213550, upload-time = "2025-10-02T14:34:17.878Z" }, - { url = "https://files.pythonhosted.org/packages/c4/ef/3a9b05eb527457d5db13a135a2ae1a26c80fecd624d20f3e8dcc4cb170f3/xxhash-3.6.0-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:6812c25fe0d6c36a46ccb002f40f27ac903bf18af9f6dd8f9669cb4d176ab18f", size = 212384, upload-time = "2025-10-02T14:34:19.182Z" }, - { url = "https://files.pythonhosted.org/packages/0f/18/ccc194ee698c6c623acbf0f8c2969811a8a4b6185af5e824cd27b9e4fd3e/xxhash-3.6.0-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:4ccbff013972390b51a18ef1255ef5ac125c92dc9143b2d1909f59abc765540e", size = 445749, upload-time = "2025-10-02T14:34:20.659Z" }, - { url = "https://files.pythonhosted.org/packages/a5/86/cf2c0321dc3940a7aa73076f4fd677a0fb3e405cb297ead7d864fd90847e/xxhash-3.6.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:297b7fbf86c82c550e12e8fb71968b3f033d27b874276ba3624ea868c11165a8", size = 193880, upload-time = "2025-10-02T14:34:22.431Z" }, - { url = "https://files.pythonhosted.org/packages/82/fb/96213c8560e6f948a1ecc9a7613f8032b19ee45f747f4fca4eb31bb6d6ed/xxhash-3.6.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:dea26ae1eb293db089798d3973a5fc928a18fdd97cc8801226fae705b02b14b0", size = 210912, upload-time = "2025-10-02T14:34:23.937Z" }, - { url = "https://files.pythonhosted.org/packages/40/aa/4395e669b0606a096d6788f40dbdf2b819d6773aa290c19e6e83cbfc312f/xxhash-3.6.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:7a0b169aafb98f4284f73635a8e93f0735f9cbde17bd5ec332480484241aaa77", size = 198654, upload-time = "2025-10-02T14:34:25.644Z" }, - { url = "https://files.pythonhosted.org/packages/67/74/b044fcd6b3d89e9b1b665924d85d3f400636c23590226feb1eb09e1176ce/xxhash-3.6.0-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:08d45aef063a4531b785cd72de4887766d01dc8f362a515693df349fdb825e0c", size = 210867, upload-time = "2025-10-02T14:34:27.203Z" }, - { url = "https://files.pythonhosted.org/packages/bc/fd/3ce73bf753b08cb19daee1eb14aa0d7fe331f8da9c02dd95316ddfe5275e/xxhash-3.6.0-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:929142361a48ee07f09121fe9e96a84950e8d4df3bb298ca5d88061969f34d7b", size = 414012, upload-time = "2025-10-02T14:34:28.409Z" }, - { url = "https://files.pythonhosted.org/packages/ba/b3/5a4241309217c5c876f156b10778f3ab3af7ba7e3259e6d5f5c7d0129eb2/xxhash-3.6.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:51312c768403d8540487dbbfb557454cfc55589bbde6424456951f7fcd4facb3", size = 191409, upload-time = "2025-10-02T14:34:29.696Z" }, - { url = "https://files.pythonhosted.org/packages/c0/01/99bfbc15fb9abb9a72b088c1d95219fc4782b7d01fc835bd5744d66dd0b8/xxhash-3.6.0-cp311-cp311-win32.whl", hash = "sha256:d1927a69feddc24c987b337ce81ac15c4720955b667fe9b588e02254b80446fd", size = 30574, upload-time = "2025-10-02T14:34:31.028Z" }, - { url = "https://files.pythonhosted.org/packages/65/79/9d24d7f53819fe301b231044ea362ce64e86c74f6e8c8e51320de248b3e5/xxhash-3.6.0-cp311-cp311-win_amd64.whl", hash = "sha256:26734cdc2d4ffe449b41d186bbeac416f704a482ed835d375a5c0cb02bc63fef", size = 31481, upload-time = "2025-10-02T14:34:32.062Z" }, - { url = "https://files.pythonhosted.org/packages/30/4e/15cd0e3e8772071344eab2961ce83f6e485111fed8beb491a3f1ce100270/xxhash-3.6.0-cp311-cp311-win_arm64.whl", hash = "sha256:d72f67ef8bf36e05f5b6c65e8524f265bd61071471cd4cf1d36743ebeeeb06b7", size = 27861, upload-time = "2025-10-02T14:34:33.555Z" }, - { url = "https://files.pythonhosted.org/packages/9a/07/d9412f3d7d462347e4511181dea65e47e0d0e16e26fbee2ea86a2aefb657/xxhash-3.6.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:01362c4331775398e7bb34e3ab403bc9ee9f7c497bc7dee6272114055277dd3c", size = 32744, upload-time = "2025-10-02T14:34:34.622Z" }, - { url = "https://files.pythonhosted.org/packages/79/35/0429ee11d035fc33abe32dca1b2b69e8c18d236547b9a9b72c1929189b9a/xxhash-3.6.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:b7b2df81a23f8cb99656378e72501b2cb41b1827c0f5a86f87d6b06b69f9f204", size = 30816, upload-time = "2025-10-02T14:34:36.043Z" }, - { url = "https://files.pythonhosted.org/packages/b7/f2/57eb99aa0f7d98624c0932c5b9a170e1806406cdbcdb510546634a1359e0/xxhash-3.6.0-cp312-cp312-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:dc94790144e66b14f67b10ac8ed75b39ca47536bf8800eb7c24b50271ea0c490", size = 194035, upload-time = "2025-10-02T14:34:37.354Z" }, - { url = "https://files.pythonhosted.org/packages/4c/ed/6224ba353690d73af7a3f1c7cdb1fc1b002e38f783cb991ae338e1eb3d79/xxhash-3.6.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:93f107c673bccf0d592cdba077dedaf52fe7f42dcd7676eba1f6d6f0c3efffd2", size = 212914, upload-time = "2025-10-02T14:34:38.6Z" }, - { url = "https://files.pythonhosted.org/packages/38/86/fb6b6130d8dd6b8942cc17ab4d90e223653a89aa32ad2776f8af7064ed13/xxhash-3.6.0-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:2aa5ee3444c25b69813663c9f8067dcfaa2e126dc55e8dddf40f4d1c25d7effa", size = 212163, upload-time = "2025-10-02T14:34:39.872Z" }, - { url = "https://files.pythonhosted.org/packages/ee/dc/e84875682b0593e884ad73b2d40767b5790d417bde603cceb6878901d647/xxhash-3.6.0-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:f7f99123f0e1194fa59cc69ad46dbae2e07becec5df50a0509a808f90a0f03f0", size = 445411, upload-time = "2025-10-02T14:34:41.569Z" }, - { url = "https://files.pythonhosted.org/packages/11/4f/426f91b96701ec2f37bb2b8cec664eff4f658a11f3fa9d94f0a887ea6d2b/xxhash-3.6.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:49e03e6fe2cac4a1bc64952dd250cf0dbc5ef4ebb7b8d96bce82e2de163c82a2", size = 193883, upload-time = "2025-10-02T14:34:43.249Z" }, - { url = "https://files.pythonhosted.org/packages/53/5a/ddbb83eee8e28b778eacfc5a85c969673e4023cdeedcfcef61f36731610b/xxhash-3.6.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:bd17fede52a17a4f9a7bc4472a5867cb0b160deeb431795c0e4abe158bc784e9", size = 210392, upload-time = "2025-10-02T14:34:45.042Z" }, - { url = "https://files.pythonhosted.org/packages/1e/c2/ff69efd07c8c074ccdf0a4f36fcdd3d27363665bcdf4ba399abebe643465/xxhash-3.6.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:6fb5f5476bef678f69db04f2bd1efbed3030d2aba305b0fc1773645f187d6a4e", size = 197898, upload-time = "2025-10-02T14:34:46.302Z" }, - { url = "https://files.pythonhosted.org/packages/58/ca/faa05ac19b3b622c7c9317ac3e23954187516298a091eb02c976d0d3dd45/xxhash-3.6.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:843b52f6d88071f87eba1631b684fcb4b2068cd2180a0224122fe4ef011a9374", size = 210655, upload-time = "2025-10-02T14:34:47.571Z" }, - { url = "https://files.pythonhosted.org/packages/d4/7a/06aa7482345480cc0cb597f5c875b11a82c3953f534394f620b0be2f700c/xxhash-3.6.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:7d14a6cfaf03b1b6f5f9790f76880601ccc7896aff7ab9cd8978a939c1eb7e0d", size = 414001, upload-time = "2025-10-02T14:34:49.273Z" }, - { url = "https://files.pythonhosted.org/packages/23/07/63ffb386cd47029aa2916b3d2f454e6cc5b9f5c5ada3790377d5430084e7/xxhash-3.6.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:418daf3db71e1413cfe211c2f9a528456936645c17f46b5204705581a45390ae", size = 191431, upload-time = "2025-10-02T14:34:50.798Z" }, - { url = "https://files.pythonhosted.org/packages/0f/93/14fde614cadb4ddf5e7cebf8918b7e8fac5ae7861c1875964f17e678205c/xxhash-3.6.0-cp312-cp312-win32.whl", hash = "sha256:50fc255f39428a27299c20e280d6193d8b63b8ef8028995323bf834a026b4fbb", size = 30617, upload-time = "2025-10-02T14:34:51.954Z" }, - { url = "https://files.pythonhosted.org/packages/13/5d/0d125536cbe7565a83d06e43783389ecae0c0f2ed037b48ede185de477c0/xxhash-3.6.0-cp312-cp312-win_amd64.whl", hash = "sha256:c0f2ab8c715630565ab8991b536ecded9416d615538be8ecddce43ccf26cbc7c", size = 31534, upload-time = "2025-10-02T14:34:53.276Z" }, - { url = "https://files.pythonhosted.org/packages/54/85/6ec269b0952ec7e36ba019125982cf11d91256a778c7c3f98a4c5043d283/xxhash-3.6.0-cp312-cp312-win_arm64.whl", hash = "sha256:eae5c13f3bc455a3bbb68bdc513912dc7356de7e2280363ea235f71f54064829", size = 27876, upload-time = "2025-10-02T14:34:54.371Z" }, - { url = "https://files.pythonhosted.org/packages/33/76/35d05267ac82f53ae9b0e554da7c5e281ee61f3cad44c743f0fcd354f211/xxhash-3.6.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:599e64ba7f67472481ceb6ee80fa3bd828fd61ba59fb11475572cc5ee52b89ec", size = 32738, upload-time = "2025-10-02T14:34:55.839Z" }, - { url = "https://files.pythonhosted.org/packages/31/a8/3fbce1cd96534a95e35d5120637bf29b0d7f5d8fa2f6374e31b4156dd419/xxhash-3.6.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:7d8b8aaa30fca4f16f0c84a5c8d7ddee0e25250ec2796c973775373257dde8f1", size = 30821, upload-time = "2025-10-02T14:34:57.219Z" }, - { url = "https://files.pythonhosted.org/packages/0c/ea/d387530ca7ecfa183cb358027f1833297c6ac6098223fd14f9782cd0015c/xxhash-3.6.0-cp313-cp313-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:d597acf8506d6e7101a4a44a5e428977a51c0fadbbfd3c39650cca9253f6e5a6", size = 194127, upload-time = "2025-10-02T14:34:59.21Z" }, - { url = "https://files.pythonhosted.org/packages/ba/0c/71435dcb99874b09a43b8d7c54071e600a7481e42b3e3ce1eb5226a5711a/xxhash-3.6.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:858dc935963a33bc33490128edc1c12b0c14d9c7ebaa4e387a7869ecc4f3e263", size = 212975, upload-time = "2025-10-02T14:35:00.816Z" }, - { url = "https://files.pythonhosted.org/packages/84/7a/c2b3d071e4bb4a90b7057228a99b10d51744878f4a8a6dd643c8bd897620/xxhash-3.6.0-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:ba284920194615cb8edf73bf52236ce2e1664ccd4a38fdb543506413529cc546", size = 212241, upload-time = "2025-10-02T14:35:02.207Z" }, - { url = "https://files.pythonhosted.org/packages/81/5f/640b6eac0128e215f177df99eadcd0f1b7c42c274ab6a394a05059694c5a/xxhash-3.6.0-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:4b54219177f6c6674d5378bd862c6aedf64725f70dd29c472eaae154df1a2e89", size = 445471, upload-time = "2025-10-02T14:35:03.61Z" }, - { url = "https://files.pythonhosted.org/packages/5e/1e/3c3d3ef071b051cc3abbe3721ffb8365033a172613c04af2da89d5548a87/xxhash-3.6.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:42c36dd7dbad2f5238950c377fcbf6811b1cdb1c444fab447960030cea60504d", size = 193936, upload-time = "2025-10-02T14:35:05.013Z" }, - { url = "https://files.pythonhosted.org/packages/2c/bd/4a5f68381939219abfe1c22a9e3a5854a4f6f6f3c4983a87d255f21f2e5d/xxhash-3.6.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:f22927652cba98c44639ffdc7aaf35828dccf679b10b31c4ad72a5b530a18eb7", size = 210440, upload-time = "2025-10-02T14:35:06.239Z" }, - { url = "https://files.pythonhosted.org/packages/eb/37/b80fe3d5cfb9faff01a02121a0f4d565eb7237e9e5fc66e73017e74dcd36/xxhash-3.6.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:b45fad44d9c5c119e9c6fbf2e1c656a46dc68e280275007bbfd3d572b21426db", size = 197990, upload-time = "2025-10-02T14:35:07.735Z" }, - { url = "https://files.pythonhosted.org/packages/d7/fd/2c0a00c97b9e18f72e1f240ad4e8f8a90fd9d408289ba9c7c495ed7dc05c/xxhash-3.6.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:6f2580ffab1a8b68ef2b901cde7e55fa8da5e4be0977c68f78fc80f3c143de42", size = 210689, upload-time = "2025-10-02T14:35:09.438Z" }, - { url = "https://files.pythonhosted.org/packages/93/86/5dd8076a926b9a95db3206aba20d89a7fc14dd5aac16e5c4de4b56033140/xxhash-3.6.0-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:40c391dd3cd041ebc3ffe6f2c862f402e306eb571422e0aa918d8070ba31da11", size = 414068, upload-time = "2025-10-02T14:35:11.162Z" }, - { url = "https://files.pythonhosted.org/packages/af/3c/0bb129170ee8f3650f08e993baee550a09593462a5cddd8e44d0011102b1/xxhash-3.6.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:f205badabde7aafd1a31e8ca2a3e5a763107a71c397c4481d6a804eb5063d8bd", size = 191495, upload-time = "2025-10-02T14:35:12.971Z" }, - { url = "https://files.pythonhosted.org/packages/e9/3a/6797e0114c21d1725e2577508e24006fd7ff1d8c0c502d3b52e45c1771d8/xxhash-3.6.0-cp313-cp313-win32.whl", hash = "sha256:2577b276e060b73b73a53042ea5bd5203d3e6347ce0d09f98500f418a9fcf799", size = 30620, upload-time = "2025-10-02T14:35:14.129Z" }, - { url = "https://files.pythonhosted.org/packages/86/15/9bc32671e9a38b413a76d24722a2bf8784a132c043063a8f5152d390b0f9/xxhash-3.6.0-cp313-cp313-win_amd64.whl", hash = "sha256:757320d45d2fbcce8f30c42a6b2f47862967aea7bf458b9625b4bbe7ee390392", size = 31542, upload-time = "2025-10-02T14:35:15.21Z" }, - { url = "https://files.pythonhosted.org/packages/39/c5/cc01e4f6188656e56112d6a8e0dfe298a16934b8c47a247236549a3f7695/xxhash-3.6.0-cp313-cp313-win_arm64.whl", hash = "sha256:457b8f85dec5825eed7b69c11ae86834a018b8e3df5e77783c999663da2f96d6", size = 27880, upload-time = "2025-10-02T14:35:16.315Z" }, - { url = "https://files.pythonhosted.org/packages/f3/30/25e5321c8732759e930c555176d37e24ab84365482d257c3b16362235212/xxhash-3.6.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:a42e633d75cdad6d625434e3468126c73f13f7584545a9cf34e883aa1710e702", size = 32956, upload-time = "2025-10-02T14:35:17.413Z" }, - { url = "https://files.pythonhosted.org/packages/9f/3c/0573299560d7d9f8ab1838f1efc021a280b5ae5ae2e849034ef3dee18810/xxhash-3.6.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:568a6d743219e717b07b4e03b0a828ce593833e498c3b64752e0f5df6bfe84db", size = 31072, upload-time = "2025-10-02T14:35:18.844Z" }, - { url = "https://files.pythonhosted.org/packages/7a/1c/52d83a06e417cd9d4137722693424885cc9878249beb3a7c829e74bf7ce9/xxhash-3.6.0-cp313-cp313t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:bec91b562d8012dae276af8025a55811b875baace6af510412a5e58e3121bc54", size = 196409, upload-time = "2025-10-02T14:35:20.31Z" }, - { url = "https://files.pythonhosted.org/packages/e3/8e/c6d158d12a79bbd0b878f8355432075fc82759e356ab5a111463422a239b/xxhash-3.6.0-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:78e7f2f4c521c30ad5e786fdd6bae89d47a32672a80195467b5de0480aa97b1f", size = 215736, upload-time = "2025-10-02T14:35:21.616Z" }, - { url = "https://files.pythonhosted.org/packages/bc/68/c4c80614716345d55071a396cf03d06e34b5f4917a467faf43083c995155/xxhash-3.6.0-cp313-cp313t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:3ed0df1b11a79856df5ffcab572cbd6b9627034c1c748c5566fa79df9048a7c5", size = 214833, upload-time = "2025-10-02T14:35:23.32Z" }, - { url = "https://files.pythonhosted.org/packages/7e/e9/ae27c8ffec8b953efa84c7c4a6c6802c263d587b9fc0d6e7cea64e08c3af/xxhash-3.6.0-cp313-cp313t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:0e4edbfc7d420925b0dd5e792478ed393d6e75ff8fc219a6546fb446b6a417b1", size = 448348, upload-time = "2025-10-02T14:35:25.111Z" }, - { url = "https://files.pythonhosted.org/packages/d7/6b/33e21afb1b5b3f46b74b6bd1913639066af218d704cc0941404ca717fc57/xxhash-3.6.0-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:fba27a198363a7ef87f8c0f6b171ec36b674fe9053742c58dd7e3201c1ab30ee", size = 196070, upload-time = "2025-10-02T14:35:26.586Z" }, - { url = "https://files.pythonhosted.org/packages/96/b6/fcabd337bc5fa624e7203aa0fa7d0c49eed22f72e93229431752bddc83d9/xxhash-3.6.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:794fe9145fe60191c6532fa95063765529770edcdd67b3d537793e8004cabbfd", size = 212907, upload-time = "2025-10-02T14:35:28.087Z" }, - { url = "https://files.pythonhosted.org/packages/4b/d3/9ee6160e644d660fcf176c5825e61411c7f62648728f69c79ba237250143/xxhash-3.6.0-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:6105ef7e62b5ac73a837778efc331a591d8442f8ef5c7e102376506cb4ae2729", size = 200839, upload-time = "2025-10-02T14:35:29.857Z" }, - { url = "https://files.pythonhosted.org/packages/0d/98/e8de5baa5109394baf5118f5e72ab21a86387c4f89b0e77ef3e2f6b0327b/xxhash-3.6.0-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:f01375c0e55395b814a679b3eea205db7919ac2af213f4a6682e01220e5fe292", size = 213304, upload-time = "2025-10-02T14:35:31.222Z" }, - { url = "https://files.pythonhosted.org/packages/7b/1d/71056535dec5c3177eeb53e38e3d367dd1d16e024e63b1cee208d572a033/xxhash-3.6.0-cp313-cp313t-musllinux_1_2_s390x.whl", hash = "sha256:d706dca2d24d834a4661619dcacf51a75c16d65985718d6a7d73c1eeeb903ddf", size = 416930, upload-time = "2025-10-02T14:35:32.517Z" }, - { url = "https://files.pythonhosted.org/packages/dc/6c/5cbde9de2cd967c322e651c65c543700b19e7ae3e0aae8ece3469bf9683d/xxhash-3.6.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:5f059d9faeacd49c0215d66f4056e1326c80503f51a1532ca336a385edadd033", size = 193787, upload-time = "2025-10-02T14:35:33.827Z" }, - { url = "https://files.pythonhosted.org/packages/19/fa/0172e350361d61febcea941b0cc541d6e6c8d65d153e85f850a7b256ff8a/xxhash-3.6.0-cp313-cp313t-win32.whl", hash = "sha256:1244460adc3a9be84731d72b8e80625788e5815b68da3da8b83f78115a40a7ec", size = 30916, upload-time = "2025-10-02T14:35:35.107Z" }, - { url = "https://files.pythonhosted.org/packages/ad/e6/e8cf858a2b19d6d45820f072eff1bea413910592ff17157cabc5f1227a16/xxhash-3.6.0-cp313-cp313t-win_amd64.whl", hash = "sha256:b1e420ef35c503869c4064f4a2f2b08ad6431ab7b229a05cce39d74268bca6b8", size = 31799, upload-time = "2025-10-02T14:35:36.165Z" }, - { url = "https://files.pythonhosted.org/packages/56/15/064b197e855bfb7b343210e82490ae672f8bc7cdf3ddb02e92f64304ee8a/xxhash-3.6.0-cp313-cp313t-win_arm64.whl", hash = "sha256:ec44b73a4220623235f67a996c862049f375df3b1052d9899f40a6382c32d746", size = 28044, upload-time = "2025-10-02T14:35:37.195Z" }, - { url = "https://files.pythonhosted.org/packages/7e/5e/0138bc4484ea9b897864d59fce9be9086030825bc778b76cb5a33a906d37/xxhash-3.6.0-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:a40a3d35b204b7cc7643cbcf8c9976d818cb47befcfac8bbefec8038ac363f3e", size = 32754, upload-time = "2025-10-02T14:35:38.245Z" }, - { url = "https://files.pythonhosted.org/packages/18/d7/5dac2eb2ec75fd771957a13e5dda560efb2176d5203f39502a5fc571f899/xxhash-3.6.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:a54844be970d3fc22630b32d515e79a90d0a3ddb2644d8d7402e3c4c8da61405", size = 30846, upload-time = "2025-10-02T14:35:39.6Z" }, - { url = "https://files.pythonhosted.org/packages/fe/71/8bc5be2bb00deb5682e92e8da955ebe5fa982da13a69da5a40a4c8db12fb/xxhash-3.6.0-cp314-cp314-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:016e9190af8f0a4e3741343777710e3d5717427f175adfdc3e72508f59e2a7f3", size = 194343, upload-time = "2025-10-02T14:35:40.69Z" }, - { url = "https://files.pythonhosted.org/packages/e7/3b/52badfb2aecec2c377ddf1ae75f55db3ba2d321c5e164f14461c90837ef3/xxhash-3.6.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4f6f72232f849eb9d0141e2ebe2677ece15adfd0fa599bc058aad83c714bb2c6", size = 213074, upload-time = "2025-10-02T14:35:42.29Z" }, - { url = "https://files.pythonhosted.org/packages/a2/2b/ae46b4e9b92e537fa30d03dbc19cdae57ed407e9c26d163895e968e3de85/xxhash-3.6.0-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:63275a8aba7865e44b1813d2177e0f5ea7eadad3dd063a21f7cf9afdc7054063", size = 212388, upload-time = "2025-10-02T14:35:43.929Z" }, - { url = "https://files.pythonhosted.org/packages/f5/80/49f88d3afc724b4ac7fbd664c8452d6db51b49915be48c6982659e0e7942/xxhash-3.6.0-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:3cd01fa2aa00d8b017c97eb46b9a794fbdca53fc14f845f5a328c71254b0abb7", size = 445614, upload-time = "2025-10-02T14:35:45.216Z" }, - { url = "https://files.pythonhosted.org/packages/ed/ba/603ce3961e339413543d8cd44f21f2c80e2a7c5cfe692a7b1f2cccf58f3c/xxhash-3.6.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0226aa89035b62b6a86d3c68df4d7c1f47a342b8683da2b60cedcddb46c4d95b", size = 194024, upload-time = "2025-10-02T14:35:46.959Z" }, - { url = "https://files.pythonhosted.org/packages/78/d1/8e225ff7113bf81545cfdcd79eef124a7b7064a0bba53605ff39590b95c2/xxhash-3.6.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:c6e193e9f56e4ca4923c61238cdaced324f0feac782544eb4c6d55ad5cc99ddd", size = 210541, upload-time = "2025-10-02T14:35:48.301Z" }, - { url = "https://files.pythonhosted.org/packages/6f/58/0f89d149f0bad89def1a8dd38feb50ccdeb643d9797ec84707091d4cb494/xxhash-3.6.0-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:9176dcaddf4ca963d4deb93866d739a343c01c969231dbe21680e13a5d1a5bf0", size = 198305, upload-time = "2025-10-02T14:35:49.584Z" }, - { url = "https://files.pythonhosted.org/packages/11/38/5eab81580703c4df93feb5f32ff8fa7fe1e2c51c1f183ee4e48d4bb9d3d7/xxhash-3.6.0-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:c1ce4009c97a752e682b897aa99aef84191077a9433eb237774689f14f8ec152", size = 210848, upload-time = "2025-10-02T14:35:50.877Z" }, - { url = "https://files.pythonhosted.org/packages/5e/6b/953dc4b05c3ce678abca756416e4c130d2382f877a9c30a20d08ee6a77c0/xxhash-3.6.0-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:8cb2f4f679b01513b7adbb9b1b2f0f9cdc31b70007eaf9d59d0878809f385b11", size = 414142, upload-time = "2025-10-02T14:35:52.15Z" }, - { url = "https://files.pythonhosted.org/packages/08/a9/238ec0d4e81a10eb5026d4a6972677cbc898ba6c8b9dbaec12ae001b1b35/xxhash-3.6.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:653a91d7c2ab54a92c19ccf43508b6a555440b9be1bc8be553376778be7f20b5", size = 191547, upload-time = "2025-10-02T14:35:53.547Z" }, - { url = "https://files.pythonhosted.org/packages/f1/ee/3cf8589e06c2164ac77c3bf0aa127012801128f1feebf2a079272da5737c/xxhash-3.6.0-cp314-cp314-win32.whl", hash = "sha256:a756fe893389483ee8c394d06b5ab765d96e68fbbfe6fde7aa17e11f5720559f", size = 31214, upload-time = "2025-10-02T14:35:54.746Z" }, - { url = "https://files.pythonhosted.org/packages/02/5d/a19552fbc6ad4cb54ff953c3908bbc095f4a921bc569433d791f755186f1/xxhash-3.6.0-cp314-cp314-win_amd64.whl", hash = "sha256:39be8e4e142550ef69629c9cd71b88c90e9a5db703fecbcf265546d9536ca4ad", size = 32290, upload-time = "2025-10-02T14:35:55.791Z" }, - { url = "https://files.pythonhosted.org/packages/b1/11/dafa0643bc30442c887b55baf8e73353a344ee89c1901b5a5c54a6c17d39/xxhash-3.6.0-cp314-cp314-win_arm64.whl", hash = "sha256:25915e6000338999236f1eb68a02a32c3275ac338628a7eaa5a269c401995679", size = 28795, upload-time = "2025-10-02T14:35:57.162Z" }, - { url = "https://files.pythonhosted.org/packages/2c/db/0e99732ed7f64182aef4a6fb145e1a295558deec2a746265dcdec12d191e/xxhash-3.6.0-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:c5294f596a9017ca5a3e3f8884c00b91ab2ad2933cf288f4923c3fd4346cf3d4", size = 32955, upload-time = "2025-10-02T14:35:58.267Z" }, - { url = "https://files.pythonhosted.org/packages/55/f4/2a7c3c68e564a099becfa44bb3d398810cc0ff6749b0d3cb8ccb93f23c14/xxhash-3.6.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:1cf9dcc4ab9cff01dfbba78544297a3a01dafd60f3bde4e2bfd016cf7e4ddc67", size = 31072, upload-time = "2025-10-02T14:35:59.382Z" }, - { url = "https://files.pythonhosted.org/packages/c6/d9/72a29cddc7250e8a5819dad5d466facb5dc4c802ce120645630149127e73/xxhash-3.6.0-cp314-cp314t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:01262da8798422d0685f7cef03b2bd3f4f46511b02830861df548d7def4402ad", size = 196579, upload-time = "2025-10-02T14:36:00.838Z" }, - { url = "https://files.pythonhosted.org/packages/63/93/b21590e1e381040e2ca305a884d89e1c345b347404f7780f07f2cdd47ef4/xxhash-3.6.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:51a73fb7cb3a3ead9f7a8b583ffd9b8038e277cdb8cb87cf890e88b3456afa0b", size = 215854, upload-time = "2025-10-02T14:36:02.207Z" }, - { url = "https://files.pythonhosted.org/packages/ce/b8/edab8a7d4fa14e924b29be877d54155dcbd8b80be85ea00d2be3413a9ed4/xxhash-3.6.0-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:b9c6df83594f7df8f7f708ce5ebeacfc69f72c9fbaaababf6cf4758eaada0c9b", size = 214965, upload-time = "2025-10-02T14:36:03.507Z" }, - { url = "https://files.pythonhosted.org/packages/27/67/dfa980ac7f0d509d54ea0d5a486d2bb4b80c3f1bb22b66e6a05d3efaf6c0/xxhash-3.6.0-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:627f0af069b0ea56f312fd5189001c24578868643203bca1abbc2c52d3a6f3ca", size = 448484, upload-time = "2025-10-02T14:36:04.828Z" }, - { url = "https://files.pythonhosted.org/packages/8c/63/8ffc2cc97e811c0ca5d00ab36604b3ea6f4254f20b7bc658ca825ce6c954/xxhash-3.6.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:aa912c62f842dfd013c5f21a642c9c10cd9f4c4e943e0af83618b4a404d9091a", size = 196162, upload-time = "2025-10-02T14:36:06.182Z" }, - { url = "https://files.pythonhosted.org/packages/4b/77/07f0e7a3edd11a6097e990f6e5b815b6592459cb16dae990d967693e6ea9/xxhash-3.6.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:b465afd7909db30168ab62afe40b2fcf79eedc0b89a6c0ab3123515dc0df8b99", size = 213007, upload-time = "2025-10-02T14:36:07.733Z" }, - { url = "https://files.pythonhosted.org/packages/ae/d8/bc5fa0d152837117eb0bef6f83f956c509332ce133c91c63ce07ee7c4873/xxhash-3.6.0-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:a881851cf38b0a70e7c4d3ce81fc7afd86fbc2a024f4cfb2a97cf49ce04b75d3", size = 200956, upload-time = "2025-10-02T14:36:09.106Z" }, - { url = "https://files.pythonhosted.org/packages/26/a5/d749334130de9411783873e9b98ecc46688dad5db64ca6e04b02acc8b473/xxhash-3.6.0-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:9b3222c686a919a0f3253cfc12bb118b8b103506612253b5baeaac10d8027cf6", size = 213401, upload-time = "2025-10-02T14:36:10.585Z" }, - { url = "https://files.pythonhosted.org/packages/89/72/abed959c956a4bfc72b58c0384bb7940663c678127538634d896b1195c10/xxhash-3.6.0-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:c5aa639bc113e9286137cec8fadc20e9cd732b2cc385c0b7fa673b84fc1f2a93", size = 417083, upload-time = "2025-10-02T14:36:12.276Z" }, - { url = "https://files.pythonhosted.org/packages/0c/b3/62fd2b586283b7d7d665fb98e266decadf31f058f1cf6c478741f68af0cb/xxhash-3.6.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:5c1343d49ac102799905e115aee590183c3921d475356cb24b4de29a4bc56518", size = 193913, upload-time = "2025-10-02T14:36:14.025Z" }, - { url = "https://files.pythonhosted.org/packages/9a/9a/c19c42c5b3f5a4aad748a6d5b4f23df3bed7ee5445accc65a0fb3ff03953/xxhash-3.6.0-cp314-cp314t-win32.whl", hash = "sha256:5851f033c3030dd95c086b4a36a2683c2ff4a799b23af60977188b057e467119", size = 31586, upload-time = "2025-10-02T14:36:15.603Z" }, - { url = "https://files.pythonhosted.org/packages/03/d6/4cc450345be9924fd5dc8c590ceda1db5b43a0a889587b0ae81a95511360/xxhash-3.6.0-cp314-cp314t-win_amd64.whl", hash = "sha256:0444e7967dac37569052d2409b00a8860c2135cff05502df4da80267d384849f", size = 32526, upload-time = "2025-10-02T14:36:16.708Z" }, - { url = "https://files.pythonhosted.org/packages/0f/c9/7243eb3f9eaabd1a88a5a5acadf06df2d83b100c62684b7425c6a11bcaa8/xxhash-3.6.0-cp314-cp314t-win_arm64.whl", hash = "sha256:bb79b1e63f6fd84ec778a4b1916dfe0a7c3fdb986c06addd5db3a0d413819d95", size = 28898, upload-time = "2025-10-02T14:36:17.843Z" }, - { url = "https://files.pythonhosted.org/packages/93/1e/8aec23647a34a249f62e2398c42955acd9b4c6ed5cf08cbea94dc46f78d2/xxhash-3.6.0-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:0f7b7e2ec26c1666ad5fc9dbfa426a6a3367ceaf79db5dd76264659d509d73b0", size = 30662, upload-time = "2025-10-02T14:37:01.743Z" }, - { url = "https://files.pythonhosted.org/packages/b8/0b/b14510b38ba91caf43006209db846a696ceea6a847a0c9ba0a5b1adc53d6/xxhash-3.6.0-pp311-pypy311_pp73-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:5dc1e14d14fa0f5789ec29a7062004b5933964bb9b02aae6622b8f530dc40296", size = 41056, upload-time = "2025-10-02T14:37:02.879Z" }, - { url = "https://files.pythonhosted.org/packages/50/55/15a7b8a56590e66ccd374bbfa3f9ffc45b810886c8c3b614e3f90bd2367c/xxhash-3.6.0-pp311-pypy311_pp73-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:881b47fc47e051b37d94d13e7455131054b56749b91b508b0907eb07900d1c13", size = 36251, upload-time = "2025-10-02T14:37:04.44Z" }, - { url = "https://files.pythonhosted.org/packages/62/b2/5ac99a041a29e58e95f907876b04f7067a0242cb85b5f39e726153981503/xxhash-3.6.0-pp311-pypy311_pp73-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c6dc31591899f5e5666f04cc2e529e69b4072827085c1ef15294d91a004bc1bd", size = 32481, upload-time = "2025-10-02T14:37:05.869Z" }, - { url = "https://files.pythonhosted.org/packages/7b/d9/8d95e906764a386a3d3b596f3c68bb63687dfca806373509f51ce8eea81f/xxhash-3.6.0-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:15e0dac10eb9309508bfc41f7f9deaa7755c69e35af835db9cb10751adebc35d", size = 31565, upload-time = "2025-10-02T14:37:06.966Z" }, +version = "3.7.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/24/2f/e183a1b407002f5af81822bee18b61cdb94b8670208ef34734d8d2b8ebe9/xxhash-3.7.0.tar.gz", hash = "sha256:6cc4eefbb542a5d6ffd6d70ea9c502957c925e800f998c5630ecc809d6702bae", size = 82022, upload-time = "2026-04-25T11:10:32.553Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/92/49/e4b575b4ed170a7f640c8bd69cfadfa81c7b700191fde5e72228762b9f73/xxhash-3.7.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:cd8ab85c916a58d5c8656ea15e3ce9df836fe2f120a74c296e01d69fab2614b4", size = 33426, upload-time = "2026-04-25T11:05:15.702Z" }, + { url = "https://files.pythonhosted.org/packages/07/61/40f0155b0b09988eb6cdbfc52652f2f371810b0c58163208cb05667757bd/xxhash-3.7.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:85f5c0e26d945b5bb475e0a3d95193117498130baa7619357bdc7869c2391b5a", size = 30859, upload-time = "2026-04-25T11:05:17.708Z" }, + { url = "https://files.pythonhosted.org/packages/12/bd/2902b7aad574e43cd85fd84849cfbce48c52cb02c7d6902b8a2b3f6e668e/xxhash-3.7.0-cp310-cp310-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:b7ffeaada9f8699be63d639536b0b60dff73b7d3325b7475c5bc8fdbf4eed47f", size = 193839, upload-time = "2026-04-25T11:05:19.364Z" }, + { url = "https://files.pythonhosted.org/packages/48/df/343ce8fd09e47ba8fba43b3bad3283ddf0deca799d5a27b084c3aa2ce502/xxhash-3.7.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:cee88dfaa6b1b2bfadd3c031fa5f05584870e62fb05dc500942e9900c44fcfda", size = 212896, upload-time = "2026-04-25T11:05:21.131Z" }, + { url = "https://files.pythonhosted.org/packages/79/cf/703e8422a8b52407864281fb4eb52c605e9f33180413b4458f05de110eba/xxhash-3.7.0-cp310-cp310-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:7426ff0dfa76eb47efc2cc59d4a717bfa9dc9938bff5e49e748bca749f6aa616", size = 235896, upload-time = "2026-04-25T11:05:22.988Z" }, + { url = "https://files.pythonhosted.org/packages/ed/bc/d4b039edbd426575add5f217abeeb2bf870e2c510d35445df81b4f457901/xxhash-3.7.0-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:e8ff6ec73110f610425caef3ea875afbfc34caa542f01df3a80f45aadeb9f906", size = 211665, upload-time = "2026-04-25T11:05:24.799Z" }, + { url = "https://files.pythonhosted.org/packages/42/24/c6f81361796814b92399a88bf079d3b65e617f531819128fcf1bd6ef0571/xxhash-3.7.0-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:0d23fd49fdc5c8af61fb7104f1ad247954499140f6cb6045b3aa5c99dadbbf28", size = 444929, upload-time = "2026-04-25T11:05:26.245Z" }, + { url = "https://files.pythonhosted.org/packages/a4/db/268012153eb7f6bf2c8a0491fdcde11e093f166990821a2ab754fe95537d/xxhash-3.7.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:12c249621af6d50a05d9f10af894b404157b15819878e18f75fcbb0213a77d07", size = 193271, upload-time = "2026-04-25T11:05:28.282Z" }, + { url = "https://files.pythonhosted.org/packages/0a/86/1d0d905d659850dad7f59c807c130249fdb204dc6f71f1fb36268f3f3e61/xxhash-3.7.0-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:6741564a923f082f3c2941c8bb920462ed5b25eaebdd1e161f162233c9a10bc5", size = 284580, upload-time = "2026-04-25T11:05:30.116Z" }, + { url = "https://files.pythonhosted.org/packages/1f/52/fc01ca7ff425a9bdb38d9e3a17f2630447ce3b45d45a929a6cd94d469334/xxhash-3.7.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:c4fd8acc6e32596350619896feb372033c0920975992d29837c32853bb1feacd", size = 210193, upload-time = "2026-04-25T11:05:31.969Z" }, + { url = "https://files.pythonhosted.org/packages/ec/96/122e0c6a3537a54b30752031dca557182576bae1a4171c0be8c532c84496/xxhash-3.7.0-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:646a69b56d8145d85f7fd2289d14fba07880c8a5bda406aa256b407481a61f35", size = 241094, upload-time = "2026-04-25T11:05:33.651Z" }, + { url = "https://files.pythonhosted.org/packages/d8/17/92e33338db8c18add33a46b56c2b7d5dcc6cc2ac076c45389f6017b1bf37/xxhash-3.7.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:11dd69b1a34b7b9af29012f390825b0cdb0617c0966560e227ca74daa7478ba9", size = 197721, upload-time = "2026-04-25T11:05:35.387Z" }, + { url = "https://files.pythonhosted.org/packages/c7/04/fd4114a0820913f336bef5c82ef851bde8d06270982ebd7b2a859961bbf2/xxhash-3.7.0-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:01cf5c5333aed26cc8d5eea33b8d6398e085e365a704b7372fabdf7ab06441a9", size = 210073, upload-time = "2026-04-25T11:05:37.405Z" }, + { url = "https://files.pythonhosted.org/packages/dd/eb/a2472b8b81cd576a9af3a4889ad8ba5784e8c5a04592587056cdaededd6c/xxhash-3.7.0-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:f1e65d52c2d526734abecb98372c256b7eacce8fdc42e0df8570417fb39e2772", size = 274960, upload-time = "2026-04-25T11:05:39.224Z" }, + { url = "https://files.pythonhosted.org/packages/3d/d3/493afc544aae50b5fb2844ceaeb3697283bb59695db1a7cb40448636de05/xxhash-3.7.0-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:8ff00fcc3eb436617ed8556cf15daf76c2b501248361a065625a588af78a0a02", size = 413113, upload-time = "2026-04-25T11:05:40.669Z" }, + { url = "https://files.pythonhosted.org/packages/50/6a/002800845a22bff32bcf5fd09caceb4d3f5c3da6b754c46edb9743ce908b/xxhash-3.7.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:b5cd29840505631c6f7dbb8a5d34b742b5e6bbda38fe0b9f54e825f3ea6b61dc", size = 190677, upload-time = "2026-04-25T11:05:42.403Z" }, + { url = "https://files.pythonhosted.org/packages/f4/0f/86ee514622a381c0dc49167c8d431a22aa93518a4063559c3e36e4b82bc8/xxhash-3.7.0-cp310-cp310-win32.whl", hash = "sha256:5bf2f1940499839b39fef1561b5ecb6ede9ac34ef4457474e1337fc7ef07c2f3", size = 30627, upload-time = "2026-04-25T11:05:44.022Z" }, + { url = "https://files.pythonhosted.org/packages/86/45/2ef2310803efb4a2d07844e8098d797e25702024793aa2e85858623a43b5/xxhash-3.7.0-cp310-cp310-win_amd64.whl", hash = "sha256:d41fcda2fa8ca682ebca134a2f2dc02575ba549267585597e73061565795f475", size = 31463, upload-time = "2026-04-25T11:05:45.218Z" }, + { url = "https://files.pythonhosted.org/packages/9e/75/40dbf8f142baf8993c38cd988c8d8f51fe0c51e6c84c5769a3c0280a651d/xxhash-3.7.0-cp310-cp310-win_arm64.whl", hash = "sha256:a845a59664d5c531525a467470220f8edc37959e0a6f8e734ffb6654da5c4bee", size = 27747, upload-time = "2026-04-25T11:05:46.422Z" }, + { url = "https://files.pythonhosted.org/packages/3b/f4/7bd35089ff1f8e2c96baa2dce05775a122aacd2e3830a73165e27a4d0848/xxhash-3.7.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:fdc7d06929ae28dda98297a18eef7b0fd38991a3b405d8d7b55c9ef24c296958", size = 33423, upload-time = "2026-04-25T11:05:47.628Z" }, + { url = "https://files.pythonhosted.org/packages/a3/26/4e00c88a6a2c8a759cfb77d2a9a405f901e8aa66e60ef1fd0aeb35edda48/xxhash-3.7.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:ea6daa712f4e094a30830cf01e9b47d03b24d05cc9dab8609f0d9a9db8454712", size = 30857, upload-time = "2026-04-25T11:05:49.189Z" }, + { url = "https://files.pythonhosted.org/packages/82/2f/eeb942c17a5a761a8f01cb9180a0b76bfb62a2c39e6f46b1f9001899027a/xxhash-3.7.0-cp311-cp311-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:9e6c0d843f1daf85ea23aeb053579135552bde575b7b98af20bfc667b6e4548d", size = 194702, upload-time = "2026-04-25T11:05:50.457Z" }, + { url = "https://files.pythonhosted.org/packages/0e/fd/96f132c08b1e5951c68691d3b9ec351ec2edc028f6a01fcd294f46b9d9f0/xxhash-3.7.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:363c139bf15e1ac5f136b981d3c077eb551299b1effede7f12faa010b8590a60", size = 213613, upload-time = "2026-04-25T11:05:52.571Z" }, + { url = "https://files.pythonhosted.org/packages/82/89/d4e92b796c5ed052d29ed324dbfc1dc1188e0c4bf64bebbf0f8fc20698df/xxhash-3.7.0-cp311-cp311-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:a778b25874cb0f862eaab5986bff4ca49ffb0def7c0a34c237b948b3c6c775b2", size = 236726, upload-time = "2026-04-25T11:05:54.395Z" }, + { url = "https://files.pythonhosted.org/packages/40/f1/81fc4361921dc6e557a9c60cb3712f36d244d06eeeb71cd2f4252ac42678/xxhash-3.7.0-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:3e1860f1e43d40e9d904cf22d93e587ea42e010ebce4160877e46bcab4bc232a", size = 212443, upload-time = "2026-04-25T11:05:56.334Z" }, + { url = "https://files.pythonhosted.org/packages/6a/d0/afeddd4cff50a332f50d4b8a2e8857673153ab0564ef472fcdeb0b5430df/xxhash-3.7.0-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:9122ad6f867c4a0f5e655f5c3bdf89103852009dbb442a3d23e688b9e699e800", size = 445793, upload-time = "2026-04-25T11:05:58.953Z" }, + { url = "https://files.pythonhosted.org/packages/f7/d0/3c91e4e6a05ca4d7df8e39ec3a75b713609258ec84705ab34be6430826a1/xxhash-3.7.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d7d9110d0c3fb02679972837a033251fd186c529aa62f19c132fc909c74052b8", size = 193937, upload-time = "2026-04-25T11:06:00.546Z" }, + { url = "https://files.pythonhosted.org/packages/4e/3a/a6b0772d9801dd4bea4ca4fd34734d6e9b51a711c8a611a24a79de26a878/xxhash-3.7.0-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:347a93f2b4ce67ce61959665e32a7447c380f8347e55e100daa23766baacf0e5", size = 285188, upload-time = "2026-04-25T11:06:01.96Z" }, + { url = "https://files.pythonhosted.org/packages/6c/f8/cf8e31fd7282230fe7367cd501a2e75b4b67b222bfc7eacccfc20d2652cb/xxhash-3.7.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:acbb48679ddf3852c45280c10ff10d52ca2cd1da2e552fb81db1ff786c75d0e4", size = 210966, upload-time = "2026-04-25T11:06:03.453Z" }, + { url = "https://files.pythonhosted.org/packages/cc/f0/fd36cc4a81bf52ee5633275daae2b93dd958aace67fd4f5d466ec83b5f35/xxhash-3.7.0-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:fe14c356f8b23ad811dc026077a6d4abccdaa7bce5ca98579605550657b6fcfb", size = 241994, upload-time = "2026-04-25T11:06:05.264Z" }, + { url = "https://files.pythonhosted.org/packages/08/e1/67f5d9c9369be42eaf99ba02c01bf14c5ecd67087b02567960bfcee43b63/xxhash-3.7.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:f420ad3d41e38194353a498bbc9561fd5a9973a27b536ce46d8583479cf44335", size = 198707, upload-time = "2026-04-25T11:06:07.044Z" }, + { url = "https://files.pythonhosted.org/packages/50/17/a4c865ca22d2da6b1bc7d739bf88cab209533cf52ba06ca9da27c3039bee/xxhash-3.7.0-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:693d02c6dc7d1aa0a45921d54cd8c1ff629e09dfdc2238471507af1f7a1c6f04", size = 210917, upload-time = "2026-04-25T11:06:08.853Z" }, + { url = "https://files.pythonhosted.org/packages/49/8b/453b35810d697abac3c96bde3528bece685869227da274eb80a4a4d4a119/xxhash-3.7.0-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:14bf7a54e43825ec131ee7fe3c60e142e7c2c1e676ad0f93fc893432d15414af", size = 275772, upload-time = "2026-04-25T11:06:10.645Z" }, + { url = "https://files.pythonhosted.org/packages/b5/ad/4eed7eab07fd3ee6678f416190f0413d097ab5d7c1278906bf1e9549d789/xxhash-3.7.0-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:ae3a39a4d96bdb6f8d154fd7f490c4ad06f0532fcd2bb656052a9a7762cf5d31", size = 414068, upload-time = "2026-04-25T11:06:12.511Z" }, + { url = "https://files.pythonhosted.org/packages/d3/4e/fd6f8a680ba248fdb83054fa71a8bfa3891225200de1708b888ef2c49829/xxhash-3.7.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:1cc07c639e3a77ef1d32987464d3e408565b8a3be57b545d3542b191054d9923", size = 191459, upload-time = "2026-04-25T11:06:14.07Z" }, + { url = "https://files.pythonhosted.org/packages/50/7c/8cb34b3bed4f44ca6827a534d50833f9bc6c006e83b0eb410ac9fa0793bd/xxhash-3.7.0-cp311-cp311-win32.whl", hash = "sha256:3281ba1d1e60ee7a382a7b958513ba03c2c0d5fcbd9a6f7517c0a81251a23422", size = 30628, upload-time = "2026-04-25T11:06:15.802Z" }, + { url = "https://files.pythonhosted.org/packages/0b/47/a49767bd7b40782bedae9ff0721bfe1d7e4dd9dc1585dea684e57ba67c20/xxhash-3.7.0-cp311-cp311-win_amd64.whl", hash = "sha256:a7f25baec4c5d851d40718d6fae52285b31683093d4ff5207e63ab306ccf14a5", size = 31461, upload-time = "2026-04-25T11:06:17.104Z" }, + { url = "https://files.pythonhosted.org/packages/7c/c6/3957bfacfb706bd687be246dfa8dd60f8df97c44186d229f7fd6e26c4b7e/xxhash-3.7.0-cp311-cp311-win_arm64.whl", hash = "sha256:4c2454448ce847c72635827bb75c15c5a3434b03ee1afd28cb6dc6fb2597d830", size = 27746, upload-time = "2026-04-25T11:06:18.716Z" }, + { url = "https://files.pythonhosted.org/packages/f2/8a/51a14cdef4728c6c2337db8a7d8704422cc65676d9199d77215464c880af/xxhash-3.7.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:082c87bfdd2b9f457606c7a4a53457f4c4b48b0cdc48de0277f4349d79bb3d7a", size = 33357, upload-time = "2026-04-25T11:06:20.44Z" }, + { url = "https://files.pythonhosted.org/packages/b9/1b/0c2c933809421ffd9bf42b59315552c143c755db5d9a816b2f1ae273e884/xxhash-3.7.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:5e7ce913b61f35b0c1c839a49ac9c8e75dd8d860150688aed353b0ce1bf409d8", size = 30869, upload-time = "2026-04-25T11:06:21.989Z" }, + { url = "https://files.pythonhosted.org/packages/03/a8/89d5fdd6ee12d70ba99451de46dd0e8010167468dcd913ec855653f4dd50/xxhash-3.7.0-cp312-cp312-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:3beb1de3b1e9694fcdd853e570ee64c631c7062435d2f8c69c1adf809bc086f0", size = 194100, upload-time = "2026-04-25T11:06:23.586Z" }, + { url = "https://files.pythonhosted.org/packages/87/ee/2f9f2ed993e77206d1e66991290a1ebe22e843351ca3ebec8e49e01ba186/xxhash-3.7.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f3e7b689c3bce16699efcf736066f5c6cc4472c3840fe4b22bd8279daf4abdac", size = 212977, upload-time = "2026-04-25T11:06:25.019Z" }, + { url = "https://files.pythonhosted.org/packages/de/60/5a91644615a9e9d4e42c2e9925f1908e3a24e4e691d9de7340d565bea024/xxhash-3.7.0-cp312-cp312-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:a6545e6b409e3d5cbafc850fb84c55a1ca26ed15a6b11e3bf07a0e0cd84517c8", size = 236373, upload-time = "2026-04-25T11:06:26.482Z" }, + { url = "https://files.pythonhosted.org/packages/22/c0/f3a9384eaaed9d14d4d062a5d953aa0da489bfe9747877aa994caa87cd0b/xxhash-3.7.0-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:31ab1461c77a11461d703c88eb949e132a1c6515933cf675d97ec680f4bd18de", size = 212229, upload-time = "2026-04-25T11:06:28.065Z" }, + { url = "https://files.pythonhosted.org/packages/2e/67/02f07a9fd79726804190f2172c4894c3ed9a4ebccaca05653c84beb58025/xxhash-3.7.0-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:7c4d596b7676f811172687ec567cbafb9e4dea2f9be1bbb4f622410cb7f40f40", size = 445462, upload-time = "2026-04-25T11:06:30.048Z" }, + { url = "https://files.pythonhosted.org/packages/40/37/558f5a90c0672fc9b4402dc25d87ac5b7406616e8969430c9ca4e52ee74d/xxhash-3.7.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:13805f0461cba0a857924e70ff91ae6d52d2598f79a884e788db80532614a4a1", size = 193932, upload-time = "2026-04-25T11:06:31.857Z" }, + { url = "https://files.pythonhosted.org/packages/d5/90/aaa09cd58661d32044dbbad7df55bbe22a623032b810e7ed3b8c569a2a6f/xxhash-3.7.0-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:1d398f372496152f1c6933a33566373f8d1b37b98b8c9d608fa6edc0976f23b2", size = 284807, upload-time = "2026-04-25T11:06:33.697Z" }, + { url = "https://files.pythonhosted.org/packages/d6/f3/53df3719ab127a02c174f0c1c74924fcd110866e89c966bc7909cfa8fa84/xxhash-3.7.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:d610aa62cdb7d4d497740741772a24a794903bf3e79eaa51d2e800082abe11e5", size = 210445, upload-time = "2026-04-25T11:06:35.488Z" }, + { url = "https://files.pythonhosted.org/packages/72/33/d219975c0e8b6fa2eb9ccd486fe47e21bf1847985b878dd2fbc3126e0d5c/xxhash-3.7.0-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:073c23900a9fbf3d26616c17c830db28af9803677cd5b33aea3224d824111514", size = 241273, upload-time = "2026-04-25T11:06:37.24Z" }, + { url = "https://files.pythonhosted.org/packages/3e/50/49b1afe610eb3964cedcb90a4d4c3d46a261ee8669cbd4f060652619ae3c/xxhash-3.7.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:418a463c3e6a590c0cdc890f8be19adb44a8c8acd175ca5b2a6de77e61d0b386", size = 197950, upload-time = "2026-04-25T11:06:39.148Z" }, + { url = "https://files.pythonhosted.org/packages/c6/75/5f42a1a4c78717d906a4b6a140c6dbf837ab1f547a54d23c4e2903310936/xxhash-3.7.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:03f8ff4474ee61c845758ce00711d7087a770d77efb36f7e74a6e867301000b8", size = 210709, upload-time = "2026-04-25T11:06:40.958Z" }, + { url = "https://files.pythonhosted.org/packages/8a/85/237e446c25abced71e9c53d269f2cef5bab8a82b3f88a12e00c5368e7368/xxhash-3.7.0-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:44fba4a5f1d179b7ddc7b3dc40f56f9209046421679b57025d4d8821b376fd8d", size = 275345, upload-time = "2026-04-25T11:06:42.525Z" }, + { url = "https://files.pythonhosted.org/packages/62/34/c2c26c0a6a9cc739bc2a5f0ae03ba8b87deb12b8bce35f7ac495e790dc6d/xxhash-3.7.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:31e3516a0f829d06ded4a2c0f3c7c5561993256bfa1c493975fb9dc7bfa828a1", size = 414056, upload-time = "2026-04-25T11:06:44.343Z" }, + { url = "https://files.pythonhosted.org/packages/a0/aa/5c58e9bc8071b8afd8dcf297ff362f723c4892168faba149f19904132bf4/xxhash-3.7.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:b59ee2ac81de57771a09ecad09191e840a1d2fae1ef684208320591055768f83", size = 191485, upload-time = "2026-04-25T11:06:46.262Z" }, + { url = "https://files.pythonhosted.org/packages/d4/69/a929cf9d1e2e65a48b818cdce72cb6b69eab2e6877f21436d0a1942aff43/xxhash-3.7.0-cp312-cp312-win32.whl", hash = "sha256:74bbd92f8c7fcc397ba0a11bfdc106bc72ad7f11e3a60277753f87e7532b4d81", size = 30671, upload-time = "2026-04-25T11:06:48.039Z" }, + { url = "https://files.pythonhosted.org/packages/b9/1b/104b41a8947f4e1d4a66ce1e628eea752f37d1890bfd7453559ca7a3d950/xxhash-3.7.0-cp312-cp312-win_amd64.whl", hash = "sha256:7bd7bc82dd4f185f28f35193c2e968ef46131628e3cac62f639dadf321cba4d1", size = 31514, upload-time = "2026-04-25T11:06:49.279Z" }, + { url = "https://files.pythonhosted.org/packages/98/a0/1fd0ea1f1b886d9e7c73f0397571e22333a7d79e31da6d7127c2a4a71d75/xxhash-3.7.0-cp312-cp312-win_arm64.whl", hash = "sha256:7d7148180ec99ba36585b42c8c5de25e9b40191613bc4be68909b4d25a77a852", size = 27761, upload-time = "2026-04-25T11:06:50.448Z" }, + { url = "https://files.pythonhosted.org/packages/c1/ca/d5174b4c36d10f64d4ca7050563138c5a599efb01a765858ddefc9c1202a/xxhash-3.7.0-cp313-cp313-android_21_arm64_v8a.whl", hash = "sha256:4b6d6b33f141158692bd4eafbb96edbc5aa0dabdb593a962db01a91983d4f8fa", size = 36813, upload-time = "2026-04-25T11:06:51.73Z" }, + { url = "https://files.pythonhosted.org/packages/41/d0/abc6c9d347ba1f1e1e1d98125d0881a0452c7f9a76a9dd03a7b5d2197f23/xxhash-3.7.0-cp313-cp313-android_21_x86_64.whl", hash = "sha256:845d347df254d6c619f616afa921331bada8614b8d373d58725c663ba97c3605", size = 35121, upload-time = "2026-04-25T11:06:53.048Z" }, + { url = "https://files.pythonhosted.org/packages/bf/11/4cc834eb3d79f2f2b3a6ef7324195208bcdfbdcf7534d2b17267aa5f3a8f/xxhash-3.7.0-cp313-cp313-ios_13_0_arm64_iphoneos.whl", hash = "sha256:fddbbb69a6fff4f421e7a0d1fa28f894b20112e9e3fab306af451e2dfd0e459b", size = 29624, upload-time = "2026-04-25T11:06:54.311Z" }, + { url = "https://files.pythonhosted.org/packages/23/83/e97d3e7b635fe73a1dfb1e91f805324dd6d930bb42041cbf18f183bc0b6d/xxhash-3.7.0-cp313-cp313-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:54876a4e45101cec2bf8f31a973cda073a23e2e108538dad224ba07f85f22487", size = 30638, upload-time = "2026-04-25T11:06:55.864Z" }, + { url = "https://files.pythonhosted.org/packages/f4/40/d84951d80c35db1f4c40a29a64a8520eea5d56e764c603906b4fe763580f/xxhash-3.7.0-cp313-cp313-ios_13_0_x86_64_iphonesimulator.whl", hash = "sha256:0c72fe9c7e3d6dfd7f1e21e224a877917fa09c465694ba4e06464b9511b65544", size = 33323, upload-time = "2026-04-25T11:06:57.336Z" }, + { url = "https://files.pythonhosted.org/packages/89/cc/c7dc6558d97e9ab023f663d69ab28b340ed9bf4d2d94f2c259cf896bb354/xxhash-3.7.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:a6d73a830b17ef49bc04e00182bd839164c1b3c59c127cd7c54fcb10c7ed8ee8", size = 33362, upload-time = "2026-04-25T11:06:58.656Z" }, + { url = "https://files.pythonhosted.org/packages/2a/6e/46b84017b1301d54091430353d4ad5901654a3e0871649877a416f7f1644/xxhash-3.7.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:91c3b07cf3362086d8f126c6aecd8e5e9396ad8b2f2219ea7e49a8250c318acd", size = 30874, upload-time = "2026-04-25T11:06:59.834Z" }, + { url = "https://files.pythonhosted.org/packages/df/5e/8f9158e3ab906ad3fec51e09b5ea0093e769f12207bfa42a368ca204e7ab/xxhash-3.7.0-cp313-cp313-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:50e879ebbac351c81565ca108db766d7832f5b8b6a5b14b8c0151f7190028e3d", size = 194185, upload-time = "2026-04-25T11:07:01.658Z" }, + { url = "https://files.pythonhosted.org/packages/f3/29/a804ded9f5d3d3758292678d23e7528b08fda7b7e750688d08b052322475/xxhash-3.7.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:921c14e93817842dd0dd9f372890a0f0c72e534650b6ab13c5be5cd0db11d47e", size = 213033, upload-time = "2026-04-25T11:07:03.606Z" }, + { url = "https://files.pythonhosted.org/packages/8b/91/1ce5a7d2fdc975267320e2c78fc1cecfe7ab735ccbcf6993ec5dd541cb2c/xxhash-3.7.0-cp313-cp313-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:e64a7c9d7dfca3e0fafcbc5e455519090706a3e36e95d655cec3e04e79f95aaa", size = 236140, upload-time = "2026-04-25T11:07:05.396Z" }, + { url = "https://files.pythonhosted.org/packages/34/04/fd595a4fd8617b05fa27bd9b684ecb4985bfed27917848eea85d54036d06/xxhash-3.7.0-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:2220af08163baf5fa36c2b8af079dc2cbe6e66ae061385267f9472362dfd53c6", size = 212291, upload-time = "2026-04-25T11:07:06.966Z" }, + { url = "https://files.pythonhosted.org/packages/03/fb/f1a379cbc372ae5b9f4ab36154c48a849ca6ebe3ac477067a57865bf3bc6/xxhash-3.7.0-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:f14bb8b22a4a91325813e3d553b8963c10cf8c756cff65ee50c194431296c655", size = 445532, upload-time = "2026-04-25T11:07:08.525Z" }, + { url = "https://files.pythonhosted.org/packages/65/59/172424b79f8cfd4b6d8a122b2193e6b8ad4b11f7159bb3b6f9b3191329bb/xxhash-3.7.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:496736f86a9bedaf64b0dc70e3539d0766df01c71ea22032698e88f3f04a1ce9", size = 193990, upload-time = "2026-04-25T11:07:10.315Z" }, + { url = "https://files.pythonhosted.org/packages/b9/19/aeac22161d953f139f07ba5586cb4a17c5b7b6dff985122803bb12933500/xxhash-3.7.0-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:0ff71596bd79816975b3de7130ab1ff4541410285a3c084584eeb1c8239996fd", size = 284876, upload-time = "2026-04-25T11:07:12.15Z" }, + { url = "https://files.pythonhosted.org/packages/77/d5/4fd0b59e7a02242953da05ff679fbb961b0a4368eac97a217e11dae110c1/xxhash-3.7.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:1ad86695c19b1d46fe106925db3c7a37f16be37669dcf58dcc70a9dd6e324676", size = 210495, upload-time = "2026-04-25T11:07:13.952Z" }, + { url = "https://files.pythonhosted.org/packages/aa/fb/976a3165c728c7faf74aa1b5ab3cf6a85e6d731612894741840524c7d28c/xxhash-3.7.0-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:970f9f8c50961d639cbd0d988c96f80ddf66006de93641719282c4fe7a87c5e6", size = 241331, upload-time = "2026-04-25T11:07:15.557Z" }, + { url = "https://files.pythonhosted.org/packages/4a/2c/6763d5901d53ac9e6ba296e5717ae599025c9d268396e8faa8b4b0a8e0ac/xxhash-3.7.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:5886ad85e9e347911783760a1d16cb6b393e8f9e3b52c982568226cb56927bdc", size = 198037, upload-time = "2026-04-25T11:07:17.563Z" }, + { url = "https://files.pythonhosted.org/packages/61/2b/876e722d533833f5f9a83473e6ba993e48745701096944e77bbecf29b2c3/xxhash-3.7.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:6e934bbae1e0ec74e27d5f0d7f37ef547ce5ff9f0a7e63fb39e559fc99526734", size = 210744, upload-time = "2026-04-25T11:07:19.055Z" }, + { url = "https://files.pythonhosted.org/packages/21/e6/d7e7baef7ce24166b4668d3c48557bb35a23b92ecadcac7e7718d099ab69/xxhash-3.7.0-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:3b6b3d28228af044ebcded71c4a3dd86e1dbd7e2f4645bf40f7b5da65bb5fb5a", size = 275406, upload-time = "2026-04-25T11:07:20.908Z" }, + { url = "https://files.pythonhosted.org/packages/92/fe/198b3763b2e01ca908f2154969a2352ec99bda892b574a11a9a151c5ede4/xxhash-3.7.0-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:6be4d70d9ab76c9f324ead9c01af6ff52c324745ea0c3731682a0cf99720f1fe", size = 414125, upload-time = "2026-04-25T11:07:23.037Z" }, + { url = "https://files.pythonhosted.org/packages/3a/6d/019a11affd5a5499137cacca53808659964785439855b5aa40dfd3412916/xxhash-3.7.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:151d7520838d4465461a0b7f4ae488b3b00de16183dd3214c1a6b14bf89d7fb6", size = 191555, upload-time = "2026-04-25T11:07:24.991Z" }, + { url = "https://files.pythonhosted.org/packages/76/21/b96d58568df2d01533244c3e0e5cbdd0c8b2b25c4bec4d72f19259a292d7/xxhash-3.7.0-cp313-cp313-win32.whl", hash = "sha256:d798c1e291bffb8e37b5bbe0dda77fc767cd19e89cadaf66e6ed5d0ff88c9fe6", size = 30668, upload-time = "2026-04-25T11:07:26.665Z" }, + { url = "https://files.pythonhosted.org/packages/99/57/d849a8d3afa1f8f4bc6a831cd89f49f9706fbbad94d2975d6140a171988c/xxhash-3.7.0-cp313-cp313-win_amd64.whl", hash = "sha256:875811ba23c543b1a1c3143c926e43996eb27ebb8f52d3500744aa608c275aed", size = 31524, upload-time = "2026-04-25T11:07:27.92Z" }, + { url = "https://files.pythonhosted.org/packages/81/52/bacc753e92dee78b058af8dcef0a50815f5f860986c664a92d75f965b6a5/xxhash-3.7.0-cp313-cp313-win_arm64.whl", hash = "sha256:54a675cb300dda83d71daae2a599389d22db8021a0f8db0dd659e14626eb3ecc", size = 27768, upload-time = "2026-04-25T11:07:29.113Z" }, + { url = "https://files.pythonhosted.org/packages/1c/47/ddbd683b7fc7e592c1a8d9d65f73ce9ab513f082b3967eee2baf549b8fc6/xxhash-3.7.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:a3b19a42111c4057c1547a4a1396a53961dca576a0f6b82bfa88a2d1561764b2", size = 33576, upload-time = "2026-04-25T11:07:30.469Z" }, + { url = "https://files.pythonhosted.org/packages/07/f2/36d3310161db7f72efb4562aadde0ed429f1d0531782dd6345b12d2da527/xxhash-3.7.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:8f4608a06e4d61b7a3425665a46d00e0579122e1a2fae97a0c52953a3aad9aa3", size = 31123, upload-time = "2026-04-25T11:07:31.989Z" }, + { url = "https://files.pythonhosted.org/packages/0d/3f/75937a5c69556ed213021e43cbedd84c8e0279d0d74e7d41a255d84ba4b1/xxhash-3.7.0-cp313-cp313t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:ad37c7792479e49cf96c1ab25517d7003fe0d93687a772ba19a097d235bbe41e", size = 196491, upload-time = "2026-04-25T11:07:33.358Z" }, + { url = "https://files.pythonhosted.org/packages/22/29/f10d7ff8c7a733d4403a43b9de18c8fabc005f98cec054644f04418659ee/xxhash-3.7.0-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:dc026e3b89d98e30a8288c95cb696e77d150b3f0fb7a51f73dcd49ee6b5577fa", size = 215793, upload-time = "2026-04-25T11:07:34.919Z" }, + { url = "https://files.pythonhosted.org/packages/8b/fd/778f60aa295f58907938f030a8b514611f391405614a525cccd2ffc00eb5/xxhash-3.7.0-cp313-cp313t-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:c9b31ab1f28b078a6a1ac1a54eb35e7d5390deddd56870d0be3a0a733d1c321c", size = 237993, upload-time = "2026-04-25T11:07:36.638Z" }, + { url = "https://files.pythonhosted.org/packages/70/f5/736db5de387b4a540e37a05b84b40dc58a1ce974bfd2b4e5754ce29b68c3/xxhash-3.7.0-cp313-cp313t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:3bb5fd680c038fd5229e44e9c493782f90df9bef632fd0499d442374688ff70b", size = 214887, upload-time = "2026-04-25T11:07:38.564Z" }, + { url = "https://files.pythonhosted.org/packages/4d/aa/09a095f22fdb9a27fbb716841fbff52119721f9ca4261952d07a912f7839/xxhash-3.7.0-cp313-cp313t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:030c0fd688fce3569fbb49a2feefd4110cbb0b650186fb4610759ecfac677548", size = 448407, upload-time = "2026-04-25T11:07:40.552Z" }, + { url = "https://files.pythonhosted.org/packages/74/8a/b745efeeca9e34a91c26fdc97ad8514c43d5a81ac78565cba80a1353870a/xxhash-3.7.0-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5b1bde10324f4c31812ae0d0502e92d916ae8917cad7209353f122b8b8f610c3", size = 196119, upload-time = "2026-04-25T11:07:42.101Z" }, + { url = "https://files.pythonhosted.org/packages/8a/5c/0cfceb024af90c191f665c7933b1f318ee234f4797858383bebd1881d52f/xxhash-3.7.0-cp313-cp313t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:503722d52a615f2604f5e7611de7d43878df010dc0053094ef91cb9a9ac3d987", size = 286751, upload-time = "2026-04-25T11:07:43.568Z" }, + { url = "https://files.pythonhosted.org/packages/0b/0a/0793e405dc3cf8f4ebe2c1acec1e4e4608cd9e7e50ea691dabbc2a95ccbb/xxhash-3.7.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:c72500a3b6d6c30ebfc135035bcace9eb5884f2dc220804efcaaba43e9f611dd", size = 212961, upload-time = "2026-04-25T11:07:45.388Z" }, + { url = "https://files.pythonhosted.org/packages/0c/7e/721118ffc63bfff94aa565bcf2555a820f9f4bdb0f001e0d609bdfad70de/xxhash-3.7.0-cp313-cp313t-musllinux_1_2_armv7l.whl", hash = "sha256:43475925a766d01ca8cd9a857fd87f3d50406983c8506a4c07c4df12adcc867f", size = 243703, upload-time = "2026-04-25T11:07:47.053Z" }, + { url = "https://files.pythonhosted.org/packages/6e/18/16f6267160488b8276fd3d449d425712512add292ba545c1b6946bfdb7dd/xxhash-3.7.0-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:8d09dfd2ab135b985daf868b594315ebe11ad86cd9fea46e6c69f19b28f7d25a", size = 200894, upload-time = "2026-04-25T11:07:48.657Z" }, + { url = "https://files.pythonhosted.org/packages/2d/94/80ba841287fd97e3e9cac1d228788c8ef623746f570404961eec748ecb5c/xxhash-3.7.0-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:c50269d0055ac1faecfd559886d2cbe4b730de236585aba0e873f9d9dadbe585", size = 213357, upload-time = "2026-04-25T11:07:50.257Z" }, + { url = "https://files.pythonhosted.org/packages/a1/7e/106d4067130c59f1e18a55ffadcd876d8c68534883a1e02685b29d3d8153/xxhash-3.7.0-cp313-cp313t-musllinux_1_2_riscv64.whl", hash = "sha256:1910df4756a5ab58cfad8744fc2d0f23926e3efcc346ee76e87b974abab922f4", size = 277600, upload-time = "2026-04-25T11:07:51.745Z" }, + { url = "https://files.pythonhosted.org/packages/c5/86/a081dd30da71d720b2612a792bfd55e45fa9a07ac76a0507f60487473c25/xxhash-3.7.0-cp313-cp313t-musllinux_1_2_s390x.whl", hash = "sha256:d006faf3b491957efcb433489be3c149efe4787b7063d5cddb8ddaefdc60e0c1", size = 416980, upload-time = "2026-04-25T11:07:53.504Z" }, + { url = "https://files.pythonhosted.org/packages/35/29/1a95221a029a3c1293773869e1ab47b07cbbdd82444a42809e8c60156626/xxhash-3.7.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:abb65b4e947e958f7b3b0d71db3ce447d1bc5f37f5eab871ce7223bda8768a04", size = 193840, upload-time = "2026-04-25T11:07:55.103Z" }, + { url = "https://files.pythonhosted.org/packages/c5/e0/db909dd0823285de2286f67e10ee4d81e96ad35d7d8e964ecb07fccd8af9/xxhash-3.7.0-cp313-cp313t-win32.whl", hash = "sha256:178959906cb1716a1ce08e0d69c82886c70a15a6f2790fc084fdd146ca30cd49", size = 30966, upload-time = "2026-04-25T11:07:56.524Z" }, + { url = "https://files.pythonhosted.org/packages/7b/ff/d705b15b22f21ee106adce239cb65d35067a158c630b240270f09b17c2e6/xxhash-3.7.0-cp313-cp313t-win_amd64.whl", hash = "sha256:2524a1e20d4c231d13b50f7cf39e44265b055669a64a7a4b9a2a44faa03f19b6", size = 31784, upload-time = "2026-04-25T11:07:57.758Z" }, + { url = "https://files.pythonhosted.org/packages/a2/1f/b2cf83c3638fd0588e0b17f22e5a9400bdfb1a3e3755324ac0aee2250b88/xxhash-3.7.0-cp313-cp313t-win_arm64.whl", hash = "sha256:37d994d0ffe81ef087bb330d392caa809bb5853c77e22ea3f71db024a0543dba", size = 27932, upload-time = "2026-04-25T11:07:59.109Z" }, + { url = "https://files.pythonhosted.org/packages/0e/cc/431db584f6fbb9312e40a173af027644e5580d39df1f73603cbb9dca4d6b/xxhash-3.7.0-cp314-cp314-android_24_arm64_v8a.whl", hash = "sha256:8c5fcfd806c335bfa2adf1cd0b3110a44fc7b6995c3a648c27489bae85801465", size = 36644, upload-time = "2026-04-25T11:08:00.658Z" }, + { url = "https://files.pythonhosted.org/packages/bc/01/255ec513e0a705d1f9a61413e78dfce4e3235203f0ed525a24c2b4b56345/xxhash-3.7.0-cp314-cp314-android_24_x86_64.whl", hash = "sha256:506a0b488f190f0a06769575e30caf71615c898ed93ab18b0dbcb6dec5c3713c", size = 35003, upload-time = "2026-04-25T11:08:02.338Z" }, + { url = "https://files.pythonhosted.org/packages/68/70/c55fc33c93445b44d8fc5a17b41ed99e3cebe92bcf8396809e63fc9a1165/xxhash-3.7.0-cp314-cp314-ios_13_0_arm64_iphoneos.whl", hash = "sha256:ec68dbba21532c0173a9872298e65c89749f7c9d21538c3a78b5bb6105871568", size = 29655, upload-time = "2026-04-25T11:08:03.701Z" }, + { url = "https://files.pythonhosted.org/packages/c2/72/ff8de73df000d74467d12a59ce6d6e2b2a368b978d41ab7b1fba5ed442be/xxhash-3.7.0-cp314-cp314-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:fa77e7ec1450d415d20129961814787c9abd9a07f98872f070b1fe96c5084611", size = 30664, upload-time = "2026-04-25T11:08:05.011Z" }, + { url = "https://files.pythonhosted.org/packages/b6/91/08416d9bd9bc3bf39d831abe8a5631ac2db5141dfd6fe81c3fe59a1f9264/xxhash-3.7.0-cp314-cp314-ios_13_0_x86_64_iphonesimulator.whl", hash = "sha256:fe32736295ea38e43e7d9424053c8c47c9f64fecfc7c895fb3da9b30b131c9ee", size = 33317, upload-time = "2026-04-25T11:08:06.413Z" }, + { url = "https://files.pythonhosted.org/packages/0e/3b/86b1caa4dee10a99f4bf9521e623359341c5e50d05158fa10c275b2bd079/xxhash-3.7.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:ab9dd2c83c4bbd63e422181a76f13502d049d3ddcac9a1bdc29196263d692bb8", size = 33457, upload-time = "2026-04-25T11:08:08.099Z" }, + { url = "https://files.pythonhosted.org/packages/ed/38/98ea14ad1517e1461292a65906951458d520689782bfbae111050145bdba/xxhash-3.7.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:3afec3a336a2286601a437cb07562ab0227685e6fbb9ec17e8c18457ff348ecf", size = 30894, upload-time = "2026-04-25T11:08:09.429Z" }, + { url = "https://files.pythonhosted.org/packages/61/a2/074654d0b893606541199993c7db70067d9fc63b748e0d60020a52a1bd36/xxhash-3.7.0-cp314-cp314-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:565df64437a9390f84465dcca33e7377114c7ede8d05cd2cf20081f831ea788e", size = 194409, upload-time = "2026-04-25T11:08:10.91Z" }, + { url = "https://files.pythonhosted.org/packages/e2/26/6d2a1afc468189f77ca28c32e1c83e1b9da1178231e05641dbc1b350e332/xxhash-3.7.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:12eca820a5d558633d423bf8bb78ce72a55394823f64089247f788a7e0ae691e", size = 213135, upload-time = "2026-04-25T11:08:12.575Z" }, + { url = "https://files.pythonhosted.org/packages/8e/0e/d8aecf95e09c42547453137be74d2f7b8b14e08f5177fa2fab6144a19061/xxhash-3.7.0-cp314-cp314-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:f262b8f7599516567e070abf607b9af649052b2c4bd6f9be02b0cb41b7024805", size = 236379, upload-time = "2026-04-25T11:08:14.206Z" }, + { url = "https://files.pythonhosted.org/packages/f2/74/8140e8210536b3dd0cc816c4faaeb5ba6e63e8125ab25af4bcddd6a037b3/xxhash-3.7.0-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:f1598916cb197681e03e601901e4ab96a9a963de398c59d0964f8a6f44a2b361", size = 212447, upload-time = "2026-04-25T11:08:15.79Z" }, + { url = "https://files.pythonhosted.org/packages/a0/d2/462001d2903b4bee5a5689598a0a55e5e7cd1ac7f4247a5545cff10d3ebb/xxhash-3.7.0-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:322b2f0622230f526aeb1738149948a7ae357a9e2ceb1383c6fd1fdaecdafa16", size = 445660, upload-time = "2026-04-25T11:08:17.441Z" }, + { url = "https://files.pythonhosted.org/packages/23/09/2bd1ed7f8689b20e51727952cac8329d50c694dc32b2eba06ba5bc742b37/xxhash-3.7.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:24cc22070880cc57b830a65cde4e65fa884c6d9b28ae4803b5ee05911e7bafba", size = 194076, upload-time = "2026-04-25T11:08:19.134Z" }, + { url = "https://files.pythonhosted.org/packages/c9/6e/692302cd0a5f4ac4e6289f37fa888dc2e1e07750b68fe3e4bfe939b8cea3/xxhash-3.7.0-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:cb5a888a968b2434abf9ecda357b5d43f10d7b5a6da6fdbbe036208473aff0e2", size = 284990, upload-time = "2026-04-25T11:08:20.618Z" }, + { url = "https://files.pythonhosted.org/packages/05/d9/e54b159b3d9df7999d2a7c676ce7b323d1b5588a64f8f51ed8172567bd87/xxhash-3.7.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:a999771ff97bec27d18341be4f3a36b163bb1ac41ec17bef6d2dabd84acd33c7", size = 210590, upload-time = "2026-04-25T11:08:22.24Z" }, + { url = "https://files.pythonhosted.org/packages/50/93/0e0df1a3a196ced4ca71de76d65ead25d8e87bbfb87b64306ea47a40c00d/xxhash-3.7.0-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:ed4a6efe2dee1655adb73e7ad40c6aa955a6892422b1e3b95de6a34de56e3cbb", size = 241442, upload-time = "2026-04-25T11:08:23.844Z" }, + { url = "https://files.pythonhosted.org/packages/9a/a9/d917a7a814e90b218f8a0d37967105eea91bf752c3303683c99a1f7bfc1f/xxhash-3.7.0-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:9fd17f14ac0faa12126c2f9ca774a8cf342957265ec3c8669c144e5e6cdb478c", size = 198356, upload-time = "2026-04-25T11:08:25.99Z" }, + { url = "https://files.pythonhosted.org/packages/89/5e/f2ba1877c39469abbefc72991d6ebdcbd4c0880db01ae8cb1f553b0c537d/xxhash-3.7.0-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:05fd1254268c59b5cb2a029dfc204275e9fc52de2913f1e53aa8d01442c96b4d", size = 210898, upload-time = "2026-04-25T11:08:27.608Z" }, + { url = "https://files.pythonhosted.org/packages/90/c6/be56b58e73de531f39a10de1355bb77ceb663900dc4bf2d6d3002a9c3f9e/xxhash-3.7.0-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:a2eae53197c6276d5b317f75a1be226bbf440c20b58bf525f36b5d0e1f657ca6", size = 275519, upload-time = "2026-04-25T11:08:29.301Z" }, + { url = "https://files.pythonhosted.org/packages/92/e2/17ddc85d5765b9c709f192009ed8f5a1fc876f4eb35bba7c307b5b1169f9/xxhash-3.7.0-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:bfe6f92e3522dcbe8c4281efd74fa7542a336cb00b0e3272c4ec0edabeaeaf67", size = 414191, upload-time = "2026-04-25T11:08:31.16Z" }, + { url = "https://files.pythonhosted.org/packages/9c/42/85f5b79f4bf1ec7ba052491164adfd4f4e9519f5dc7246de4fbd64a1bd56/xxhash-3.7.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:7ab9a49c410d8c6c786ab99e79c529938d894c01433130353dd0fe999111077a", size = 191604, upload-time = "2026-04-25T11:08:32.862Z" }, + { url = "https://files.pythonhosted.org/packages/b8/d0/6127b623aa4cca18d8b7743592b048d689fd6c6e37ff26a22cddf6cd9d7f/xxhash-3.7.0-cp314-cp314-win32.whl", hash = "sha256:040ea63668f9185b92bc74942df09c7e65703deed71431333678fc6e739a9955", size = 31271, upload-time = "2026-04-25T11:08:34.651Z" }, + { url = "https://files.pythonhosted.org/packages/64/4f/44fc4788568004c43921701cbc127f48218a1eede2c9aea231115323564d/xxhash-3.7.0-cp314-cp314-win_amd64.whl", hash = "sha256:2a61e2a3fb23c892496d587b470dee7fa1b58b248a187719c65ea8e94ec13257", size = 32284, upload-time = "2026-04-25T11:08:35.987Z" }, + { url = "https://files.pythonhosted.org/packages/6d/77/18bb895eb60a49453d16e17d67990e5caff557c78eafc90ad4e2eabf4570/xxhash-3.7.0-cp314-cp314-win_arm64.whl", hash = "sha256:c7741c7524961d8c0cb4d4c21b28957ff731a3fd5b5cd8b856dc80a40e9e5acc", size = 28701, upload-time = "2026-04-25T11:08:37.767Z" }, + { url = "https://files.pythonhosted.org/packages/45/a0/46f72244570c550fbbb7db1ef554183dd5ebe9136385f30e032b781ae8f6/xxhash-3.7.0-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:fc84bf7aa7592f31ec63a3e7b11d624f468a3f19f5238cec7282a42e838ab1d7", size = 33646, upload-time = "2026-04-25T11:08:39.109Z" }, + { url = "https://files.pythonhosted.org/packages/4a/3a/453846a7eceea11e75def361eed01ec6a0205b9822c19927ed364ccae7cc/xxhash-3.7.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:9f1563fdc8abfc389748e6932c7e4e99c89a53e4ec37d4563c24fc06f5e5644b", size = 31125, upload-time = "2026-04-25T11:08:40.467Z" }, + { url = "https://files.pythonhosted.org/packages/bd/3e/49434aba738885d512f9e486db1bdd19db28dfa40372b56da26ef7a4e738/xxhash-3.7.0-cp314-cp314t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:2d415f18becf6f153046ab6adc97da77e3643a0ee205dae61c4012604113a020", size = 196633, upload-time = "2026-04-25T11:08:41.943Z" }, + { url = "https://files.pythonhosted.org/packages/a4/e9/006cb6127baeb9f8abe6d15e62faa01349f09b34e2bfd65175b2422d026b/xxhash-3.7.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:bb16aa13ed175bc9be5c2491ba031b85a9b51c4ed90e0b3d4ebe63cf3fb54f8e", size = 215899, upload-time = "2026-04-25T11:08:43.645Z" }, + { url = "https://files.pythonhosted.org/packages/27/e4/cc57d72e66df0ae29b914335f1c6dcf61e8f3746ddf0ae3c471aa4f15e00/xxhash-3.7.0-cp314-cp314t-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:f9fd595f1e5941b3d7863e4774e4b30caa6731fc34b9277da032295aa5656ee5", size = 238116, upload-time = "2026-04-25T11:08:45.698Z" }, + { url = "https://files.pythonhosted.org/packages/af/78/3531d4a3fd8a0038cc6be1f265a69c1b3587f557a10b677dd736de2202c1/xxhash-3.7.0-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:1295325c5a98d552333fa53dc2b026b0ef0ec9c8e73ca3a952990b4c7d65d459", size = 215012, upload-time = "2026-04-25T11:08:47.355Z" }, + { url = "https://files.pythonhosted.org/packages/b4/f6/259fb1eaaec921f59b17203b0daee69829761226d3b980d5191d7723dd83/xxhash-3.7.0-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:3573a651d146912da9daa9e29e5fbc45994420daaa9ef1e2fa5823e1dc485513", size = 448534, upload-time = "2026-04-25T11:08:49.149Z" }, + { url = "https://files.pythonhosted.org/packages/7b/16/a66d0eaf6a7e68532c07714361ddc904c663ec940f3b028c1ae4a21a7b9d/xxhash-3.7.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5ec1e080a3d02d94ea9335bfab0e3374b877e25411422c18f51a943fa4b46381", size = 196217, upload-time = "2026-04-25T11:08:50.805Z" }, + { url = "https://files.pythonhosted.org/packages/8d/ef/d2efc7fc51756dc52509109d1a25cefc859d74bc4b19a167b12dbd8c2786/xxhash-3.7.0-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:84415265192072d8638a3afc3c1bc5995e310570cd9acb54dc46d3939e364fe0", size = 286906, upload-time = "2026-04-25T11:08:52.418Z" }, + { url = "https://files.pythonhosted.org/packages/fc/67/25decd1d4a4018582ec4db2a868a2b7e40640f4adb20dfeb19ac923aa825/xxhash-3.7.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:8d4dea659b57443989ef32f4295104fd6912c73d0bf26d1d148bb88a9f159b02", size = 213057, upload-time = "2026-04-25T11:08:54.105Z" }, + { url = "https://files.pythonhosted.org/packages/0d/5d/17651eb29d06786cdc40c60ae3d27d645aa5d61d2eca6237a7ba0b94789b/xxhash-3.7.0-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:05ece0fe4d9c9c2728912d1981ae1566cfc83a011571b24732cbf76e1fb70dca", size = 243886, upload-time = "2026-04-25T11:08:56.109Z" }, + { url = "https://files.pythonhosted.org/packages/8a/d4/174d9cf7502243d586e6a9ae842b1ae23026620995114f85f1380e588bc9/xxhash-3.7.0-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:fd880353cf1ffaf321bc18dd663e111976dbd0d3bbd8a66d58d2b470dfa7f396", size = 201015, upload-time = "2026-04-25T11:08:57.777Z" }, + { url = "https://files.pythonhosted.org/packages/91/8c/2254e2d06c3ac5e6fe22eaf3da791b87ea823ae9f2c17b4af66755c5752d/xxhash-3.7.0-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:4e15cc9e2817f6481160f930c62842b3ff419e20e13072bcbab12230943092bc", size = 213457, upload-time = "2026-04-25T11:08:59.826Z" }, + { url = "https://files.pythonhosted.org/packages/79/a2/e3daa762545921173e3360f3b4ff7fc63c2d27359f7230ec1a7a74e117f6/xxhash-3.7.0-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:90b9d1a8bd37d768ffc92a1f651ec69afc532a96fa1ac2ea7abbed5d630b3237", size = 277738, upload-time = "2026-04-25T11:09:01.423Z" }, + { url = "https://files.pythonhosted.org/packages/e1/4c/e186da2c46b87f5204640e008d42730bf3c1ee9f0efb71ae1ebcdfeac681/xxhash-3.7.0-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:157c49475b34ecea8809e51123d9769a534e139d1247942f7a4bc67710bb2533", size = 417127, upload-time = "2026-04-25T11:09:03.592Z" }, + { url = "https://files.pythonhosted.org/packages/17/28/3798e15007a3712d0da3d3fe70f8e11916569858b5cc371053bc26270832/xxhash-3.7.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:5a6ddec83325685e729ca119d1f5c518ec39294212ecd770e60693cdc5f7eb79", size = 193962, upload-time = "2026-04-25T11:09:06.228Z" }, + { url = "https://files.pythonhosted.org/packages/ad/95/a26baa93b5241fd7630998816a4ec47a5a0bad193b3f8fc8f3593e1a4a67/xxhash-3.7.0-cp314-cp314t-win32.whl", hash = "sha256:a04a6cab47e2166435aaf5b9e5ee41d1532cc8300efdef87f2a4d0acb7db19ed", size = 31643, upload-time = "2026-04-25T11:09:08.153Z" }, + { url = "https://files.pythonhosted.org/packages/44/36/5454f13c447e395f9b06a3e91274c59f503d31fad84e1836efe3bdb71f6a/xxhash-3.7.0-cp314-cp314t-win_amd64.whl", hash = "sha256:8653dd7c2eda020545bb2c71c7f7039b53fe7434d0fc1a0a9deb79ab3f1a4fc1", size = 32522, upload-time = "2026-04-25T11:09:09.534Z" }, + { url = "https://files.pythonhosted.org/packages/74/35/698e7e3ff38e22992ea24870a511d8762474fb6783627a2910ff22a185c2/xxhash-3.7.0-cp314-cp314t-win_arm64.whl", hash = "sha256:468f0fc114faaa4b36699f8e328bbc3bb11dc418ba94ac52c26dd736d4b6c637", size = 28807, upload-time = "2026-04-25T11:09:11.234Z" }, + { url = "https://files.pythonhosted.org/packages/54/c1/e57ac7317b1f58a92bab692da6d497e2a7ce44735b224e296347a7ecc754/xxhash-3.7.0-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:ad3aa71e12ee634f22b39a0ff439357583706e50765f17f05550f92dbf128a23", size = 31232, upload-time = "2026-04-25T11:10:21.51Z" }, + { url = "https://files.pythonhosted.org/packages/4f/4e/075559bd712bc62e84915ea46bbee859f935d285659082c129bdbff679dd/xxhash-3.7.0-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:5de686e73690cdaf72b96d4fa083c230ec9020bcc2627ce6316138e2cf2fe2d1", size = 28553, upload-time = "2026-04-25T11:10:23.1Z" }, + { url = "https://files.pythonhosted.org/packages/92/ca/a9c78cb384d4b033b0c58196bd5c8509873cabe76389e195127b0302a741/xxhash-3.7.0-pp311-pypy311_pp73-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:7fbec49f5341bbdea0c471f7d1e2fb41ae8925af9b6f28025c28defd8eb94274", size = 41109, upload-time = "2026-04-25T11:10:25.022Z" }, + { url = "https://files.pythonhosted.org/packages/bd/b1/dfe2629f7c77eb2fa234c72ff537cdd64939763df704e256446ed364a16d/xxhash-3.7.0-pp311-pypy311_pp73-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:48b542c347c2089f43dc5a6db31d2a6f3cdb04ee33505ec6e9f653834dbb0bde", size = 36307, upload-time = "2026-04-25T11:10:26.949Z" }, + { url = "https://files.pythonhosted.org/packages/e7/f7/5a484afce0f48dd8083208b42e4911f290a82c7b52458ef2927e4d421a45/xxhash-3.7.0-pp311-pypy311_pp73-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a169a036bed0995e090d1493b283cc2cc8a6f5046821086b843abefff80643bc", size = 32534, upload-time = "2026-04-25T11:10:29.01Z" }, + { url = "https://files.pythonhosted.org/packages/0f/5f/4acfcd490db9780cf36c58534d828003c564cde5350220a1c783c4d10776/xxhash-3.7.0-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:ec101643395d7f21405b640f728f6f627e6986557027d740f2f9b220955edafe", size = 31552, upload-time = "2026-04-25T11:10:30.727Z" }, ] [[package]] name = "yarl" -version = "1.23.0" +version = "1.24.2" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "idna" }, { name = "multidict" }, { name = "propcache" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/23/6e/beb1beec874a72f23815c1434518bfc4ed2175065173fb138c3705f658d4/yarl-1.23.0.tar.gz", hash = "sha256:53b1ea6ca88ebd4420379c330aea57e258408dd0df9af0992e5de2078dc9f5d5", size = 194676, upload-time = "2026-03-01T22:07:53.373Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/8b/0d/9cc638702f6fc3c7a3685bcc8cf2a9ed7d6206e932a49f5242658047ef51/yarl-1.23.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:cff6d44cb13d39db2663a22b22305d10855efa0fa8015ddeacc40bc59b9d8107", size = 123764, upload-time = "2026-03-01T22:04:09.7Z" }, - { url = "https://files.pythonhosted.org/packages/7a/35/5a553687c5793df5429cd1db45909d4f3af7eee90014888c208d086a44f0/yarl-1.23.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e4c53f8347cd4200f0d70a48ad059cabaf24f5adc6ba08622a23423bc7efa10d", size = 86282, upload-time = "2026-03-01T22:04:11.892Z" }, - { url = "https://files.pythonhosted.org/packages/68/2e/c5a2234238f8ce37a8312b52801ee74117f576b1539eec8404a480434acc/yarl-1.23.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:2a6940a074fb3c48356ed0158a3ca5699c955ee4185b4d7d619be3c327143e05", size = 86053, upload-time = "2026-03-01T22:04:13.292Z" }, - { url = "https://files.pythonhosted.org/packages/74/3f/bbd8ff36fb038622797ffbaf7db314918bb4d76f1cc8a4f9ca7a55fe5195/yarl-1.23.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ed5f69ce7be7902e5c70ea19eb72d20abf7d725ab5d49777d696e32d4fc1811d", size = 99395, upload-time = "2026-03-01T22:04:15.133Z" }, - { url = "https://files.pythonhosted.org/packages/77/04/9516bc4e269d2a3ec9c6779fcdeac51ce5b3a9b0156f06ac7152e5bba864/yarl-1.23.0-cp310-cp310-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:389871e65468400d6283c0308e791a640b5ab5c83bcee02a2f51295f95e09748", size = 92143, upload-time = "2026-03-01T22:04:16.829Z" }, - { url = "https://files.pythonhosted.org/packages/c7/63/88802d1f6b1cb1fc67d67a58cd0cf8a1790de4ce7946e434240f1d60ab4a/yarl-1.23.0-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:dda608c88cf709b1d406bdfcd84d8d63cff7c9e577a403c6108ce8ce9dcc8764", size = 107643, upload-time = "2026-03-01T22:04:18.519Z" }, - { url = "https://files.pythonhosted.org/packages/8e/db/4f9b838f4d8bdd6f0f385aed8bbf21c71ed11a0b9983305c302cbd557815/yarl-1.23.0-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:8c4fe09e0780c6c3bf2b7d4af02ee2394439d11a523bbcf095cf4747c2932007", size = 108700, upload-time = "2026-03-01T22:04:20.373Z" }, - { url = "https://files.pythonhosted.org/packages/50/12/95a1d33f04a79c402664070d43b8b9f72dc18914e135b345b611b0b1f8cc/yarl-1.23.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:31c9921eb8bd12633b41ad27686bbb0b1a2a9b8452bfdf221e34f311e9942ed4", size = 102769, upload-time = "2026-03-01T22:04:23.055Z" }, - { url = "https://files.pythonhosted.org/packages/86/65/91a0285f51321369fd1a8308aa19207520c5f0587772cfc2e03fc2467e90/yarl-1.23.0-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:5f10fd85e4b75967468af655228fbfd212bdf66db1c0d135065ce288982eda26", size = 101114, upload-time = "2026-03-01T22:04:25.031Z" }, - { url = "https://files.pythonhosted.org/packages/58/80/c7c8244fc3e5bc483dc71a09560f43b619fab29301a0f0a8f936e42865c7/yarl-1.23.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:dbf507e9ef5688bada447a24d68b4b58dd389ba93b7afc065a2ba892bea54769", size = 98883, upload-time = "2026-03-01T22:04:27.281Z" }, - { url = "https://files.pythonhosted.org/packages/86/e7/71ca9cc9ca79c0b7d491216177d1aed559d632947b8ffb0ee60f7d8b23e3/yarl-1.23.0-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:85e9beda1f591bc73e77ea1c51965c68e98dafd0fec72cdd745f77d727466716", size = 94172, upload-time = "2026-03-01T22:04:28.554Z" }, - { url = "https://files.pythonhosted.org/packages/6a/3f/6c6c8a0fe29c26fb2db2e8d32195bb84ec1bfb8f1d32e7f73b787fcf349b/yarl-1.23.0-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:0e1fdaa14ef51366d7757b45bde294e95f6c8c049194e793eedb8387c86d5993", size = 107010, upload-time = "2026-03-01T22:04:30.385Z" }, - { url = "https://files.pythonhosted.org/packages/56/38/12730c05e5ad40a76374d440ed8b0899729a96c250516d91c620a6e38fc2/yarl-1.23.0-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:75e3026ab649bf48f9a10c0134512638725b521340293f202a69b567518d94e0", size = 100285, upload-time = "2026-03-01T22:04:31.752Z" }, - { url = "https://files.pythonhosted.org/packages/34/92/6a7be9239f2347234e027284e7a5f74b1140cc86575e7b469d13fba1ebfe/yarl-1.23.0-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:80e6d33a3d42a7549b409f199857b4fb54e2103fc44fb87605b6663b7a7ff750", size = 108230, upload-time = "2026-03-01T22:04:33.844Z" }, - { url = "https://files.pythonhosted.org/packages/5e/81/4aebccfa9376bd98b9d8bfad20621a57d3e8cfc5b8631c1fa5f62cdd03f4/yarl-1.23.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:5ec2f42d41ccbd5df0270d7df31618a8ee267bfa50997f5d720ddba86c4a83a6", size = 103008, upload-time = "2026-03-01T22:04:35.856Z" }, - { url = "https://files.pythonhosted.org/packages/38/0f/0b4e3edcec794a86b853b0c6396c0a888d72dfce19b2d88c02ac289fb6c1/yarl-1.23.0-cp310-cp310-win32.whl", hash = "sha256:debe9c4f41c32990771be5c22b56f810659f9ddf3d63f67abfdcaa2c6c9c5c1d", size = 83073, upload-time = "2026-03-01T22:04:38.268Z" }, - { url = "https://files.pythonhosted.org/packages/a0/71/ad95c33da18897e4c636528bbc24a1dd23fe16797de8bc4ec667b8db0ba4/yarl-1.23.0-cp310-cp310-win_amd64.whl", hash = "sha256:ab5f043cb8a2d71c981c09c510da013bc79fd661f5c60139f00dd3c3cc4f2ffb", size = 87328, upload-time = "2026-03-01T22:04:39.558Z" }, - { url = "https://files.pythonhosted.org/packages/e2/14/dfa369523c79bccf9c9c746b0a63eb31f65db9418ac01275f7950962e504/yarl-1.23.0-cp310-cp310-win_arm64.whl", hash = "sha256:263cd4f47159c09b8b685890af949195b51d1aa82ba451c5847ca9bc6413c220", size = 82463, upload-time = "2026-03-01T22:04:41.454Z" }, - { url = "https://files.pythonhosted.org/packages/a2/aa/60da938b8f0997ba3a911263c40d82b6f645a67902a490b46f3355e10fae/yarl-1.23.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:b35d13d549077713e4414f927cdc388d62e543987c572baee613bf82f11a4b99", size = 123641, upload-time = "2026-03-01T22:04:42.841Z" }, - { url = "https://files.pythonhosted.org/packages/24/84/e237607faf4e099dbb8a4f511cfd5efcb5f75918baad200ff7380635631b/yarl-1.23.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:cbb0fef01f0c6b38cb0f39b1f78fc90b807e0e3c86a7ff3ce74ad77ce5c7880c", size = 86248, upload-time = "2026-03-01T22:04:44.757Z" }, - { url = "https://files.pythonhosted.org/packages/b2/0d/71ceabc14c146ba8ee3804ca7b3d42b1664c8440439de5214d366fec7d3a/yarl-1.23.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:dc52310451fc7c629e13c4e061cbe2dd01684d91f2f8ee2821b083c58bd72432", size = 85988, upload-time = "2026-03-01T22:04:46.365Z" }, - { url = "https://files.pythonhosted.org/packages/8c/6c/4a90d59c572e46b270ca132aca66954f1175abd691f74c1ef4c6711828e2/yarl-1.23.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b2c6b50c7b0464165472b56b42d4c76a7b864597007d9c085e8b63e185cf4a7a", size = 100566, upload-time = "2026-03-01T22:04:47.639Z" }, - { url = "https://files.pythonhosted.org/packages/49/fb/c438fb5108047e629f6282a371e6e91cf3f97ee087c4fb748a1f32ceef55/yarl-1.23.0-cp311-cp311-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:aafe5dcfda86c8af00386d7781d4c2181b5011b7be3f2add5e99899ea925df05", size = 92079, upload-time = "2026-03-01T22:04:48.925Z" }, - { url = "https://files.pythonhosted.org/packages/d9/13/d269aa1aed3e4f50a5a103f96327210cc5fa5dd2d50882778f13c7a14606/yarl-1.23.0-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:9ee33b875f0b390564c1fb7bc528abf18c8ee6073b201c6ae8524aca778e2d83", size = 108741, upload-time = "2026-03-01T22:04:50.838Z" }, - { url = "https://files.pythonhosted.org/packages/85/fb/115b16f22c37ea4437d323e472945bea97301c8ec6089868fa560abab590/yarl-1.23.0-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:4c41e021bc6d7affb3364dc1e1e5fa9582b470f283748784bd6ea0558f87f42c", size = 108099, upload-time = "2026-03-01T22:04:52.499Z" }, - { url = "https://files.pythonhosted.org/packages/9a/64/c53487d9f4968045b8afa51aed7ca44f58b2589e772f32745f3744476c82/yarl-1.23.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:99c8a9ed30f4164bc4c14b37a90208836cbf50d4ce2a57c71d0f52c7fb4f7598", size = 102678, upload-time = "2026-03-01T22:04:55.176Z" }, - { url = "https://files.pythonhosted.org/packages/85/59/cd98e556fbb2bf8fab29c1a722f67ad45c5f3447cac798ab85620d1e70af/yarl-1.23.0-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:f2af5c81a1f124609d5f33507082fc3f739959d4719b56877ab1ee7e7b3d602b", size = 100803, upload-time = "2026-03-01T22:04:56.588Z" }, - { url = "https://files.pythonhosted.org/packages/9e/c0/b39770b56d4a9f0bb5f77e2f1763cd2d75cc2f6c0131e3b4c360348fcd65/yarl-1.23.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:6b41389c19b07c760c7e427a3462e8ab83c4bb087d127f0e854c706ce1b9215c", size = 100163, upload-time = "2026-03-01T22:04:58.492Z" }, - { url = "https://files.pythonhosted.org/packages/e7/64/6980f99ab00e1f0ff67cb84766c93d595b067eed07439cfccfc8fb28c1a6/yarl-1.23.0-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:1dc702e42d0684f42d6519c8d581e49c96cefaaab16691f03566d30658ee8788", size = 93859, upload-time = "2026-03-01T22:05:00.268Z" }, - { url = "https://files.pythonhosted.org/packages/38/69/912e6c5e146793e5d4b5fe39ff5b00f4d22463dfd5a162bec565ac757673/yarl-1.23.0-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:0e40111274f340d32ebcc0a5668d54d2b552a6cca84c9475859d364b380e3222", size = 108202, upload-time = "2026-03-01T22:05:02.273Z" }, - { url = "https://files.pythonhosted.org/packages/59/97/35ca6767524687ad64e5f5c31ad54bc76d585585a9fcb40f649e7e82ffed/yarl-1.23.0-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:4764a6a7588561a9aef92f65bda2c4fb58fe7c675c0883862e6df97559de0bfb", size = 99866, upload-time = "2026-03-01T22:05:03.597Z" }, - { url = "https://files.pythonhosted.org/packages/d3/1c/1a3387ee6d73589f6f2a220ae06f2984f6c20b40c734989b0a44f5987308/yarl-1.23.0-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:03214408cfa590df47728b84c679ae4ef00be2428e11630277be0727eba2d7cc", size = 107852, upload-time = "2026-03-01T22:05:04.986Z" }, - { url = "https://files.pythonhosted.org/packages/a4/b8/35c0750fcd5a3f781058bfd954515dd4b1eab45e218cbb85cf11132215f1/yarl-1.23.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:170e26584b060879e29fac213e4228ef063f39128723807a312e5c7fec28eff2", size = 102919, upload-time = "2026-03-01T22:05:06.397Z" }, - { url = "https://files.pythonhosted.org/packages/e5/1c/9a1979aec4a81896d597bcb2177827f2dbee3f5b7cc48b2d0dadb644b41d/yarl-1.23.0-cp311-cp311-win32.whl", hash = "sha256:51430653db848d258336cfa0244427b17d12db63d42603a55f0d4546f50f25b5", size = 82602, upload-time = "2026-03-01T22:05:08.444Z" }, - { url = "https://files.pythonhosted.org/packages/93/22/b85eca6fa2ad9491af48c973e4c8cf6b103a73dbb271fe3346949449fca0/yarl-1.23.0-cp311-cp311-win_amd64.whl", hash = "sha256:bf49a3ae946a87083ef3a34c8f677ae4243f5b824bfc4c69672e72b3d6719d46", size = 87461, upload-time = "2026-03-01T22:05:10.145Z" }, - { url = "https://files.pythonhosted.org/packages/93/95/07e3553fe6f113e6864a20bdc53a78113cda3b9ced8784ee52a52c9f80d8/yarl-1.23.0-cp311-cp311-win_arm64.whl", hash = "sha256:b39cb32a6582750b6cc77bfb3c49c0f8760dc18dc96ec9fb55fbb0f04e08b928", size = 82336, upload-time = "2026-03-01T22:05:11.554Z" }, - { url = "https://files.pythonhosted.org/packages/88/8a/94615bc31022f711add374097ad4144d569e95ff3c38d39215d07ac153a0/yarl-1.23.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:1932b6b8bba8d0160a9d1078aae5838a66039e8832d41d2992daa9a3a08f7860", size = 124737, upload-time = "2026-03-01T22:05:12.897Z" }, - { url = "https://files.pythonhosted.org/packages/e3/6f/c6554045d59d64052698add01226bc867b52fe4a12373415d7991fdca95d/yarl-1.23.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:411225bae281f114067578891bc75534cfb3d92a3b4dfef7a6ca78ba354e6069", size = 87029, upload-time = "2026-03-01T22:05:14.376Z" }, - { url = "https://files.pythonhosted.org/packages/19/2a/725ecc166d53438bc88f76822ed4b1e3b10756e790bafd7b523fe97c322d/yarl-1.23.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:13a563739ae600a631c36ce096615fe307f131344588b0bc0daec108cdb47b25", size = 86310, upload-time = "2026-03-01T22:05:15.71Z" }, - { url = "https://files.pythonhosted.org/packages/99/30/58260ed98e6ff7f90ba84442c1ddd758c9170d70327394a6227b310cd60f/yarl-1.23.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:9cbf44c5cb4a7633d078788e1b56387e3d3cf2b8139a3be38040b22d6c3221c8", size = 97587, upload-time = "2026-03-01T22:05:17.384Z" }, - { url = "https://files.pythonhosted.org/packages/76/0a/8b08aac08b50682e65759f7f8dde98ae8168f72487e7357a5d684c581ef9/yarl-1.23.0-cp312-cp312-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:53ad387048f6f09a8969631e4de3f1bf70c50e93545d64af4f751b2498755072", size = 92528, upload-time = "2026-03-01T22:05:18.804Z" }, - { url = "https://files.pythonhosted.org/packages/52/07/0b7179101fe5f8385ec6c6bb5d0cb9f76bd9fb4a769591ab6fb5cdbfc69a/yarl-1.23.0-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:4a59ba56f340334766f3a4442e0efd0af895fae9e2b204741ef885c446b3a1a8", size = 105339, upload-time = "2026-03-01T22:05:20.235Z" }, - { url = "https://files.pythonhosted.org/packages/d3/8a/36d82869ab5ec829ca8574dfcb92b51286fcfb1e9c7a73659616362dc880/yarl-1.23.0-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:803a3c3ce4acc62eaf01eaca1208dcf0783025ef27572c3336502b9c232005e7", size = 105061, upload-time = "2026-03-01T22:05:22.268Z" }, - { url = "https://files.pythonhosted.org/packages/66/3e/868e5c3364b6cee19ff3e1a122194fa4ce51def02c61023970442162859e/yarl-1.23.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a3d2bff8f37f8d0f96c7ec554d16945050d54462d6e95414babaa18bfafc7f51", size = 100132, upload-time = "2026-03-01T22:05:23.638Z" }, - { url = "https://files.pythonhosted.org/packages/cf/26/9c89acf82f08a52cb52d6d39454f8d18af15f9d386a23795389d1d423823/yarl-1.23.0-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:c75eb09e8d55bceb4367e83496ff8ef2bc7ea6960efb38e978e8073ea59ecb67", size = 99289, upload-time = "2026-03-01T22:05:25.749Z" }, - { url = "https://files.pythonhosted.org/packages/6f/54/5b0db00d2cb056922356104468019c0a132e89c8d3ab67d8ede9f4483d2a/yarl-1.23.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:877b0738624280e34c55680d6054a307aa94f7d52fa0e3034a9cc6e790871da7", size = 96950, upload-time = "2026-03-01T22:05:27.318Z" }, - { url = "https://files.pythonhosted.org/packages/f6/40/10fa93811fd439341fad7e0718a86aca0de9548023bbb403668d6555acab/yarl-1.23.0-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:b5405bb8f0e783a988172993cfc627e4d9d00432d6bbac65a923041edacf997d", size = 93960, upload-time = "2026-03-01T22:05:28.738Z" }, - { url = "https://files.pythonhosted.org/packages/bc/d2/8ae2e6cd77d0805f4526e30ec43b6f9a3dfc542d401ac4990d178e4bf0cf/yarl-1.23.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:1c3a3598a832590c5a3ce56ab5576361b5688c12cb1d39429cf5dba30b510760", size = 104703, upload-time = "2026-03-01T22:05:30.438Z" }, - { url = "https://files.pythonhosted.org/packages/2f/0c/b3ceacf82c3fe21183ce35fa2acf5320af003d52bc1fcf5915077681142e/yarl-1.23.0-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:8419ebd326430d1cbb7efb5292330a2cf39114e82df5cc3d83c9a0d5ebeaf2f2", size = 98325, upload-time = "2026-03-01T22:05:31.835Z" }, - { url = "https://files.pythonhosted.org/packages/9d/e0/12900edd28bdab91a69bd2554b85ad7b151f64e8b521fe16f9ad2f56477a/yarl-1.23.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:be61f6fff406ca40e3b1d84716fde398fc08bc63dd96d15f3a14230a0973ed86", size = 105067, upload-time = "2026-03-01T22:05:33.358Z" }, - { url = "https://files.pythonhosted.org/packages/15/61/74bb1182cf79c9bbe4eb6b1f14a57a22d7a0be5e9cedf8e2d5c2086474c3/yarl-1.23.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:3ceb13c5c858d01321b5d9bb65e4cf37a92169ea470b70fec6f236b2c9dd7e34", size = 100285, upload-time = "2026-03-01T22:05:35.4Z" }, - { url = "https://files.pythonhosted.org/packages/69/7f/cd5ef733f2550de6241bd8bd8c3febc78158b9d75f197d9c7baa113436af/yarl-1.23.0-cp312-cp312-win32.whl", hash = "sha256:fffc45637bcd6538de8b85f51e3df3223e4ad89bccbfca0481c08c7fc8b7ed7d", size = 82359, upload-time = "2026-03-01T22:05:36.811Z" }, - { url = "https://files.pythonhosted.org/packages/f5/be/25216a49daeeb7af2bec0db22d5e7df08ed1d7c9f65d78b14f3b74fd72fc/yarl-1.23.0-cp312-cp312-win_amd64.whl", hash = "sha256:f69f57305656a4852f2a7203efc661d8c042e6cc67f7acd97d8667fb448a426e", size = 87674, upload-time = "2026-03-01T22:05:38.171Z" }, - { url = "https://files.pythonhosted.org/packages/d2/35/aeab955d6c425b227d5b7247eafb24f2653fedc32f95373a001af5dfeb9e/yarl-1.23.0-cp312-cp312-win_arm64.whl", hash = "sha256:6e87a6e8735b44816e7db0b2fbc9686932df473c826b0d9743148432e10bb9b9", size = 81879, upload-time = "2026-03-01T22:05:40.006Z" }, - { url = "https://files.pythonhosted.org/packages/9a/4b/a0a6e5d0ee8a2f3a373ddef8a4097d74ac901ac363eea1440464ccbe0898/yarl-1.23.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:16c6994ac35c3e74fb0ae93323bf8b9c2a9088d55946109489667c510a7d010e", size = 123796, upload-time = "2026-03-01T22:05:41.412Z" }, - { url = "https://files.pythonhosted.org/packages/67/b6/8925d68af039b835ae876db5838e82e76ec87b9782ecc97e192b809c4831/yarl-1.23.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:4a42e651629dafb64fd5b0286a3580613702b5809ad3f24934ea87595804f2c5", size = 86547, upload-time = "2026-03-01T22:05:42.841Z" }, - { url = "https://files.pythonhosted.org/packages/ae/50/06d511cc4b8e0360d3c94af051a768e84b755c5eb031b12adaaab6dec6e5/yarl-1.23.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:7c6b9461a2a8b47c65eef63bb1c76a4f1c119618ffa99ea79bc5bb1e46c5821b", size = 85854, upload-time = "2026-03-01T22:05:44.85Z" }, - { url = "https://files.pythonhosted.org/packages/c4/f4/4e30b250927ffdab4db70da08b9b8d2194d7c7b400167b8fbeca1e4701ca/yarl-1.23.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:2569b67d616eab450d262ca7cb9f9e19d2f718c70a8b88712859359d0ab17035", size = 98351, upload-time = "2026-03-01T22:05:46.836Z" }, - { url = "https://files.pythonhosted.org/packages/86/fc/4118c5671ea948208bdb1492d8b76bdf1453d3e73df051f939f563e7dcc5/yarl-1.23.0-cp313-cp313-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:e9d9a4d06d3481eab79803beb4d9bd6f6a8e781ec078ac70d7ef2dcc29d1bea5", size = 92711, upload-time = "2026-03-01T22:05:48.316Z" }, - { url = "https://files.pythonhosted.org/packages/56/11/1ed91d42bd9e73c13dc9e7eb0dd92298d75e7ac4dd7f046ad0c472e231cd/yarl-1.23.0-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:f514f6474e04179d3d33175ed3f3e31434d3130d42ec153540d5b157deefd735", size = 106014, upload-time = "2026-03-01T22:05:50.028Z" }, - { url = "https://files.pythonhosted.org/packages/ce/c9/74e44e056a23fbc33aca71779ef450ca648a5bc472bdad7a82339918f818/yarl-1.23.0-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:fda207c815b253e34f7e1909840fd14299567b1c0eb4908f8c2ce01a41265401", size = 105557, upload-time = "2026-03-01T22:05:51.416Z" }, - { url = "https://files.pythonhosted.org/packages/66/fe/b1e10b08d287f518994f1e2ff9b6d26f0adeecd8dd7d533b01bab29a3eda/yarl-1.23.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:34b6cf500e61c90f305094911f9acc9c86da1a05a7a3f5be9f68817043f486e4", size = 101559, upload-time = "2026-03-01T22:05:52.872Z" }, - { url = "https://files.pythonhosted.org/packages/72/59/c5b8d94b14e3d3c2a9c20cb100119fd534ab5a14b93673ab4cc4a4141ea5/yarl-1.23.0-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:d7504f2b476d21653e4d143f44a175f7f751cd41233525312696c76aa3dbb23f", size = 100502, upload-time = "2026-03-01T22:05:54.954Z" }, - { url = "https://files.pythonhosted.org/packages/77/4f/96976cb54cbfc5c9fd73ed4c51804f92f209481d1fb190981c0f8a07a1d7/yarl-1.23.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:578110dd426f0d209d1509244e6d4a3f1a3e9077655d98c5f22583d63252a08a", size = 98027, upload-time = "2026-03-01T22:05:56.409Z" }, - { url = "https://files.pythonhosted.org/packages/63/6e/904c4f476471afdbad6b7e5b70362fb5810e35cd7466529a97322b6f5556/yarl-1.23.0-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:609d3614d78d74ebe35f54953c5bbd2ac647a7ddb9c30a5d877580f5e86b22f2", size = 95369, upload-time = "2026-03-01T22:05:58.141Z" }, - { url = "https://files.pythonhosted.org/packages/9d/40/acfcdb3b5f9d68ef499e39e04d25e141fe90661f9d54114556cf83be8353/yarl-1.23.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:4966242ec68afc74c122f8459abd597afd7d8a60dc93d695c1334c5fd25f762f", size = 105565, upload-time = "2026-03-01T22:06:00.286Z" }, - { url = "https://files.pythonhosted.org/packages/5e/c6/31e28f3a6ba2869c43d124f37ea5260cac9c9281df803c354b31f4dd1f3c/yarl-1.23.0-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:e0fd068364a6759bc794459f0a735ab151d11304346332489c7972bacbe9e72b", size = 99813, upload-time = "2026-03-01T22:06:01.712Z" }, - { url = "https://files.pythonhosted.org/packages/08/1f/6f65f59e72d54aa467119b63fc0b0b1762eff0232db1f4720cd89e2f4a17/yarl-1.23.0-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:39004f0ad156da43e86aa71f44e033de68a44e5a31fc53507b36dd253970054a", size = 105632, upload-time = "2026-03-01T22:06:03.188Z" }, - { url = "https://files.pythonhosted.org/packages/a3/c4/18b178a69935f9e7a338127d5b77d868fdc0f0e49becd286d51b3a18c61d/yarl-1.23.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:e5723c01a56c5028c807c701aa66722916d2747ad737a046853f6c46f4875543", size = 101895, upload-time = "2026-03-01T22:06:04.651Z" }, - { url = "https://files.pythonhosted.org/packages/8f/54/f5b870b5505663911dba950a8e4776a0dbd51c9c54c0ae88e823e4b874a0/yarl-1.23.0-cp313-cp313-win32.whl", hash = "sha256:1b6b572edd95b4fa8df75de10b04bc81acc87c1c7d16bcdd2035b09d30acc957", size = 82356, upload-time = "2026-03-01T22:06:06.04Z" }, - { url = "https://files.pythonhosted.org/packages/7a/84/266e8da36879c6edcd37b02b547e2d9ecdfea776be49598e75696e3316e1/yarl-1.23.0-cp313-cp313-win_amd64.whl", hash = "sha256:baaf55442359053c7d62f6f8413a62adba3205119bcb6f49594894d8be47e5e3", size = 87515, upload-time = "2026-03-01T22:06:08.107Z" }, - { url = "https://files.pythonhosted.org/packages/00/fd/7e1c66efad35e1649114fa13f17485f62881ad58edeeb7f49f8c5e748bf9/yarl-1.23.0-cp313-cp313-win_arm64.whl", hash = "sha256:fb4948814a2a98e3912505f09c9e7493b1506226afb1f881825368d6fb776ee3", size = 81785, upload-time = "2026-03-01T22:06:10.181Z" }, - { url = "https://files.pythonhosted.org/packages/9c/fc/119dd07004f17ea43bb91e3ece6587759edd7519d6b086d16bfbd3319982/yarl-1.23.0-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:aecfed0b41aa72b7881712c65cf764e39ce2ec352324f5e0837c7048d9e6daaa", size = 130719, upload-time = "2026-03-01T22:06:11.708Z" }, - { url = "https://files.pythonhosted.org/packages/e6/0d/9f2348502fbb3af409e8f47730282cd6bc80dec6630c1e06374d882d6eb2/yarl-1.23.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:a41bcf68efd19073376eb8cf948b8d9be0af26256403e512bb18f3966f1f9120", size = 89690, upload-time = "2026-03-01T22:06:13.429Z" }, - { url = "https://files.pythonhosted.org/packages/50/93/e88f3c80971b42cfc83f50a51b9d165a1dbf154b97005f2994a79f212a07/yarl-1.23.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:cde9a2ecd91668bcb7f077c4966d8ceddb60af01b52e6e3e2680e4cf00ad1a59", size = 89851, upload-time = "2026-03-01T22:06:15.53Z" }, - { url = "https://files.pythonhosted.org/packages/1c/07/61c9dd8ba8f86473263b4036f70fb594c09e99c0d9737a799dfd8bc85651/yarl-1.23.0-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5023346c4ee7992febc0068e7593de5fa2bf611848c08404b35ebbb76b1b0512", size = 95874, upload-time = "2026-03-01T22:06:17.553Z" }, - { url = "https://files.pythonhosted.org/packages/9e/e9/f9ff8ceefba599eac6abddcfb0b3bee9b9e636e96dbf54342a8577252379/yarl-1.23.0-cp313-cp313t-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:d1009abedb49ae95b136a8904a3f71b342f849ffeced2d3747bf29caeda218c4", size = 88710, upload-time = "2026-03-01T22:06:19.004Z" }, - { url = "https://files.pythonhosted.org/packages/eb/78/0231bfcc5d4c8eec220bc2f9ef82cb4566192ea867a7c5b4148f44f6cbcd/yarl-1.23.0-cp313-cp313t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:a8d00f29b42f534cc8aa3931cfe773b13b23e561e10d2b26f27a8d309b0e82a1", size = 101033, upload-time = "2026-03-01T22:06:21.203Z" }, - { url = "https://files.pythonhosted.org/packages/cd/9b/30ea5239a61786f18fd25797151a17fbb3be176977187a48d541b5447dd4/yarl-1.23.0-cp313-cp313t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:95451e6ce06c3e104556d73b559f5da6c34a069b6b62946d3ad66afcd51642ea", size = 100817, upload-time = "2026-03-01T22:06:22.738Z" }, - { url = "https://files.pythonhosted.org/packages/62/e2/a4980481071791bc83bce2b7a1a1f7adcabfa366007518b4b845e92eeee3/yarl-1.23.0-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:531ef597132086b6cf96faa7c6c1dcd0361dd5f1694e5cc30375907b9b7d3ea9", size = 97482, upload-time = "2026-03-01T22:06:24.21Z" }, - { url = "https://files.pythonhosted.org/packages/e5/1e/304a00cf5f6100414c4b5a01fc7ff9ee724b62158a08df2f8170dfc72a2d/yarl-1.23.0-cp313-cp313t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:88f9fb0116fbfcefcab70f85cf4b74a2b6ce5d199c41345296f49d974ddb4123", size = 95949, upload-time = "2026-03-01T22:06:25.697Z" }, - { url = "https://files.pythonhosted.org/packages/68/03/093f4055ed4cae649ac53bca3d180bd37102e9e11d048588e9ab0c0108d0/yarl-1.23.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:e7b0460976dc75cb87ad9cc1f9899a4b97751e7d4e77ab840fc9b6d377b8fd24", size = 95839, upload-time = "2026-03-01T22:06:27.309Z" }, - { url = "https://files.pythonhosted.org/packages/b9/28/4c75ebb108f322aa8f917ae10a8ffa4f07cae10a8a627b64e578617df6a0/yarl-1.23.0-cp313-cp313t-musllinux_1_2_armv7l.whl", hash = "sha256:115136c4a426f9da976187d238e84139ff6b51a20839aa6e3720cd1026d768de", size = 90696, upload-time = "2026-03-01T22:06:29.048Z" }, - { url = "https://files.pythonhosted.org/packages/23/9c/42c2e2dd91c1a570402f51bdf066bfdb1241c2240ba001967bad778e77b7/yarl-1.23.0-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:ead11956716a940c1abc816b7df3fa2b84d06eaed8832ca32f5c5e058c65506b", size = 100865, upload-time = "2026-03-01T22:06:30.525Z" }, - { url = "https://files.pythonhosted.org/packages/74/05/1bcd60a8a0a914d462c305137246b6f9d167628d73568505fce3f1cb2e65/yarl-1.23.0-cp313-cp313t-musllinux_1_2_riscv64.whl", hash = "sha256:fe8f8f5e70e6dbdfca9882cd9deaac058729bcf323cf7a58660901e55c9c94f6", size = 96234, upload-time = "2026-03-01T22:06:32.692Z" }, - { url = "https://files.pythonhosted.org/packages/90/b2/f52381aac396d6778ce516b7bc149c79e65bfc068b5de2857ab69eeea3b7/yarl-1.23.0-cp313-cp313t-musllinux_1_2_s390x.whl", hash = "sha256:a0e317df055958a0c1e79e5d2aa5a5eaa4a6d05a20d4b0c9c3f48918139c9fc6", size = 100295, upload-time = "2026-03-01T22:06:34.268Z" }, - { url = "https://files.pythonhosted.org/packages/e5/e8/638bae5bbf1113a659b2435d8895474598afe38b4a837103764f603aba56/yarl-1.23.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:6f0fd84de0c957b2d280143522c4f91a73aada1923caee763e24a2b3fda9f8a5", size = 97784, upload-time = "2026-03-01T22:06:35.864Z" }, - { url = "https://files.pythonhosted.org/packages/80/25/a3892b46182c586c202629fc2159aa13975d3741d52ebd7347fd501d48d5/yarl-1.23.0-cp313-cp313t-win32.whl", hash = "sha256:93a784271881035ab4406a172edb0faecb6e7d00f4b53dc2f55919d6c9688595", size = 88313, upload-time = "2026-03-01T22:06:37.39Z" }, - { url = "https://files.pythonhosted.org/packages/43/68/8c5b36aa5178900b37387937bc2c2fe0e9505537f713495472dcf6f6fccc/yarl-1.23.0-cp313-cp313t-win_amd64.whl", hash = "sha256:dd00607bffbf30250fe108065f07453ec124dbf223420f57f5e749b04295e090", size = 94932, upload-time = "2026-03-01T22:06:39.579Z" }, - { url = "https://files.pythonhosted.org/packages/c6/cc/d79ba8292f51f81f4dc533a8ccfb9fc6992cabf0998ed3245de7589dc07c/yarl-1.23.0-cp313-cp313t-win_arm64.whl", hash = "sha256:ac09d42f48f80c9ee1635b2fcaa819496a44502737660d3c0f2ade7526d29144", size = 84786, upload-time = "2026-03-01T22:06:41.988Z" }, - { url = "https://files.pythonhosted.org/packages/90/98/b85a038d65d1b92c3903ab89444f48d3cee490a883477b716d7a24b1a78c/yarl-1.23.0-cp314-cp314-macosx_10_15_universal2.whl", hash = "sha256:21d1b7305a71a15b4794b5ff22e8eef96ff4a6d7f9657155e5aa419444b28912", size = 124455, upload-time = "2026-03-01T22:06:43.615Z" }, - { url = "https://files.pythonhosted.org/packages/39/54/bc2b45559f86543d163b6e294417a107bb87557609007c007ad889afec18/yarl-1.23.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:85610b4f27f69984932a7abbe52703688de3724d9f72bceb1cca667deff27474", size = 86752, upload-time = "2026-03-01T22:06:45.425Z" }, - { url = "https://files.pythonhosted.org/packages/24/f9/e8242b68362bffe6fb536c8db5076861466fc780f0f1b479fc4ffbebb128/yarl-1.23.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:23f371bd662cf44a7630d4d113101eafc0cfa7518a2760d20760b26021454719", size = 86291, upload-time = "2026-03-01T22:06:46.974Z" }, - { url = "https://files.pythonhosted.org/packages/ea/d8/d1cb2378c81dd729e98c716582b1ccb08357e8488e4c24714658cc6630e8/yarl-1.23.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c4a80f77dc1acaaa61f0934176fccca7096d9b1ff08c8ba9cddf5ae034a24319", size = 99026, upload-time = "2026-03-01T22:06:48.459Z" }, - { url = "https://files.pythonhosted.org/packages/0a/ff/7196790538f31debe3341283b5b0707e7feb947620fc5e8236ef28d44f72/yarl-1.23.0-cp314-cp314-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:bd654fad46d8d9e823afbb4f87c79160b5a374ed1ff5bde24e542e6ba8f41434", size = 92355, upload-time = "2026-03-01T22:06:50.306Z" }, - { url = "https://files.pythonhosted.org/packages/c1/56/25d58c3eddde825890a5fe6aa1866228377354a3c39262235234ab5f616b/yarl-1.23.0-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:682bae25f0a0dd23a056739f23a134db9f52a63e2afd6bfb37ddc76292bbd723", size = 106417, upload-time = "2026-03-01T22:06:52.1Z" }, - { url = "https://files.pythonhosted.org/packages/51/8a/882c0e7bc8277eb895b31bce0138f51a1ba551fc2e1ec6753ffc1e7c1377/yarl-1.23.0-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:a82836cab5f197a0514235aaf7ffccdc886ccdaa2324bc0aafdd4ae898103039", size = 106422, upload-time = "2026-03-01T22:06:54.424Z" }, - { url = "https://files.pythonhosted.org/packages/42/2b/fef67d616931055bf3d6764885990a3ac647d68734a2d6a9e1d13de437a2/yarl-1.23.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1c57676bdedc94cd3bc37724cf6f8cd2779f02f6aba48de45feca073e714fe52", size = 101915, upload-time = "2026-03-01T22:06:55.895Z" }, - { url = "https://files.pythonhosted.org/packages/18/6a/530e16aebce27c5937920f3431c628a29a4b6b430fab3fd1c117b26ff3f6/yarl-1.23.0-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:c7f8dc16c498ff06497c015642333219871effba93e4a2e8604a06264aca5c5c", size = 100690, upload-time = "2026-03-01T22:06:58.21Z" }, - { url = "https://files.pythonhosted.org/packages/88/08/93749219179a45e27b036e03260fda05190b911de8e18225c294ac95bbc9/yarl-1.23.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:5ee586fb17ff8f90c91cf73c6108a434b02d69925f44f5f8e0d7f2f260607eae", size = 98750, upload-time = "2026-03-01T22:06:59.794Z" }, - { url = "https://files.pythonhosted.org/packages/d9/cf/ea424a004969f5d81a362110a6ac1496d79efdc6d50c2c4b2e3ea0fc2519/yarl-1.23.0-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:17235362f580149742739cc3828b80e24029d08cbb9c4bda0242c7b5bc610a8e", size = 94685, upload-time = "2026-03-01T22:07:01.375Z" }, - { url = "https://files.pythonhosted.org/packages/e2/b7/14341481fe568e2b0408bcf1484c652accafe06a0ade9387b5d3fd9df446/yarl-1.23.0-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:0793e2bd0cf14234983bbb371591e6bea9e876ddf6896cdcc93450996b0b5c85", size = 106009, upload-time = "2026-03-01T22:07:03.151Z" }, - { url = "https://files.pythonhosted.org/packages/0a/e6/5c744a9b54f4e8007ad35bce96fbc9218338e84812d36f3390cea616881a/yarl-1.23.0-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:3650dc2480f94f7116c364096bc84b1d602f44224ef7d5c7208425915c0475dd", size = 100033, upload-time = "2026-03-01T22:07:04.701Z" }, - { url = "https://files.pythonhosted.org/packages/0c/23/e3bfc188d0b400f025bc49d99793d02c9abe15752138dcc27e4eaf0c4a9e/yarl-1.23.0-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:f40e782d49630ad384db66d4d8b73ff4f1b8955dc12e26b09a3e3af064b3b9d6", size = 106483, upload-time = "2026-03-01T22:07:06.231Z" }, - { url = "https://files.pythonhosted.org/packages/72/42/f0505f949a90b3f8b7a363d6cbdf398f6e6c58946d85c6d3a3bc70595b26/yarl-1.23.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:94f8575fbdf81749008d980c17796097e645574a3b8c28ee313931068dad14fe", size = 102175, upload-time = "2026-03-01T22:07:08.4Z" }, - { url = "https://files.pythonhosted.org/packages/aa/65/b39290f1d892a9dd671d1c722014ca062a9c35d60885d57e5375db0404b5/yarl-1.23.0-cp314-cp314-win32.whl", hash = "sha256:c8aa34a5c864db1087d911a0b902d60d203ea3607d91f615acd3f3108ac32169", size = 83871, upload-time = "2026-03-01T22:07:09.968Z" }, - { url = "https://files.pythonhosted.org/packages/a9/5b/9b92f54c784c26e2a422e55a8d2607ab15b7ea3349e28359282f84f01d43/yarl-1.23.0-cp314-cp314-win_amd64.whl", hash = "sha256:63e92247f383c85ab00dd0091e8c3fa331a96e865459f5ee80353c70a4a42d70", size = 89093, upload-time = "2026-03-01T22:07:11.501Z" }, - { url = "https://files.pythonhosted.org/packages/e0/7d/8a84dc9381fd4412d5e7ff04926f9865f6372b4c2fd91e10092e65d29eb8/yarl-1.23.0-cp314-cp314-win_arm64.whl", hash = "sha256:70efd20be968c76ece7baa8dafe04c5be06abc57f754d6f36f3741f7aa7a208e", size = 83384, upload-time = "2026-03-01T22:07:13.069Z" }, - { url = "https://files.pythonhosted.org/packages/dd/8d/d2fad34b1c08aa161b74394183daa7d800141aaaee207317e82c790b418d/yarl-1.23.0-cp314-cp314t-macosx_10_15_universal2.whl", hash = "sha256:9a18d6f9359e45722c064c97464ec883eb0e0366d33eda61cb19a244bf222679", size = 131019, upload-time = "2026-03-01T22:07:14.903Z" }, - { url = "https://files.pythonhosted.org/packages/19/ff/33009a39d3ccf4b94d7d7880dfe17fb5816c5a4fe0096d9b56abceea9ac7/yarl-1.23.0-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:2803ed8b21ca47a43da80a6fd1ed3019d30061f7061daa35ac54f63933409412", size = 89894, upload-time = "2026-03-01T22:07:17.372Z" }, - { url = "https://files.pythonhosted.org/packages/0c/f1/dab7ac5e7306fb79c0190766a3c00b4cb8d09a1f390ded68c85a5934faf5/yarl-1.23.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:394906945aa8b19fc14a61cf69743a868bb8c465efe85eee687109cc540b98f4", size = 89979, upload-time = "2026-03-01T22:07:19.361Z" }, - { url = "https://files.pythonhosted.org/packages/aa/b1/08e95f3caee1fad6e65017b9f26c1d79877b502622d60e517de01e72f95d/yarl-1.23.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:71d006bee8397a4a89f469b8deb22469fe7508132d3c17fa6ed871e79832691c", size = 95943, upload-time = "2026-03-01T22:07:21.266Z" }, - { url = "https://files.pythonhosted.org/packages/c0/cc/6409f9018864a6aa186c61175b977131f373f1988e198e031236916e87e4/yarl-1.23.0-cp314-cp314t-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:62694e275c93d54f7ccedcfef57d42761b2aad5234b6be1f3e3026cae4001cd4", size = 88786, upload-time = "2026-03-01T22:07:23.129Z" }, - { url = "https://files.pythonhosted.org/packages/76/40/cc22d1d7714b717fde2006fad2ced5efe5580606cb059ae42117542122f3/yarl-1.23.0-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:a31de1613658308efdb21ada98cbc86a97c181aa050ba22a808120bb5be3ab94", size = 101307, upload-time = "2026-03-01T22:07:24.689Z" }, - { url = "https://files.pythonhosted.org/packages/8f/0d/476c38e85ddb4c6ec6b20b815bdd779aa386a013f3d8b85516feee55c8dc/yarl-1.23.0-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:fb1e8b8d66c278b21d13b0a7ca22c41dd757a7c209c6b12c313e445c31dd3b28", size = 100904, upload-time = "2026-03-01T22:07:26.287Z" }, - { url = "https://files.pythonhosted.org/packages/72/32/0abe4a76d59adf2081dcb0397168553ece4616ada1c54d1c49d8936c74f8/yarl-1.23.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:50f9d8d531dfb767c565f348f33dd5139a6c43f5cbdf3f67da40d54241df93f6", size = 97728, upload-time = "2026-03-01T22:07:27.906Z" }, - { url = "https://files.pythonhosted.org/packages/b7/35/7b30f4810fba112f60f5a43237545867504e15b1c7647a785fbaf588fac2/yarl-1.23.0-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:575aa4405a656e61a540f4a80eaa5260f2a38fff7bfdc4b5f611840d76e9e277", size = 95964, upload-time = "2026-03-01T22:07:30.198Z" }, - { url = "https://files.pythonhosted.org/packages/2d/86/ed7a73ab85ef00e8bb70b0cb5421d8a2a625b81a333941a469a6f4022828/yarl-1.23.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:041b1a4cefacf65840b4e295c6985f334ba83c30607441ae3cf206a0eed1a2e4", size = 95882, upload-time = "2026-03-01T22:07:32.132Z" }, - { url = "https://files.pythonhosted.org/packages/19/90/d56967f61a29d8498efb7afb651e0b2b422a1e9b47b0ab5f4e40a19b699b/yarl-1.23.0-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:d38c1e8231722c4ce40d7593f28d92b5fc72f3e9774fe73d7e800ec32299f63a", size = 90797, upload-time = "2026-03-01T22:07:34.404Z" }, - { url = "https://files.pythonhosted.org/packages/72/00/8b8f76909259f56647adb1011d7ed8b321bcf97e464515c65016a47ecdf0/yarl-1.23.0-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:d53834e23c015ee83a99377db6e5e37d8484f333edb03bd15b4bc312cc7254fb", size = 101023, upload-time = "2026-03-01T22:07:35.953Z" }, - { url = "https://files.pythonhosted.org/packages/ac/e2/cab11b126fb7d440281b7df8e9ddbe4851e70a4dde47a202b6642586b8d9/yarl-1.23.0-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:2e27c8841126e017dd2a054a95771569e6070b9ee1b133366d8b31beb5018a41", size = 96227, upload-time = "2026-03-01T22:07:37.594Z" }, - { url = "https://files.pythonhosted.org/packages/c2/9b/2c893e16bfc50e6b2edf76c1a9eb6cb0c744346197e74c65e99ad8d634d0/yarl-1.23.0-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:76855800ac56f878847a09ce6dba727c93ca2d89c9e9d63002d26b916810b0a2", size = 100302, upload-time = "2026-03-01T22:07:39.334Z" }, - { url = "https://files.pythonhosted.org/packages/28/ec/5498c4e3a6d5f1003beb23405671c2eb9cdbf3067d1c80f15eeafe301010/yarl-1.23.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:e09fd068c2e169a7070d83d3bde728a4d48de0549f975290be3c108c02e499b4", size = 98202, upload-time = "2026-03-01T22:07:41.717Z" }, - { url = "https://files.pythonhosted.org/packages/fe/c3/cd737e2d45e70717907f83e146f6949f20cc23cd4bf7b2688727763aa458/yarl-1.23.0-cp314-cp314t-win32.whl", hash = "sha256:73309162a6a571d4cbd3b6a1dcc703c7311843ae0d1578df6f09be4e98df38d4", size = 90558, upload-time = "2026-03-01T22:07:43.433Z" }, - { url = "https://files.pythonhosted.org/packages/e1/19/3774d162f6732d1cfb0b47b4140a942a35ca82bb19b6db1f80e9e7bdc8f8/yarl-1.23.0-cp314-cp314t-win_amd64.whl", hash = "sha256:4503053d296bc6e4cbd1fad61cf3b6e33b939886c4f249ba7c78b602214fabe2", size = 97610, upload-time = "2026-03-01T22:07:45.773Z" }, - { url = "https://files.pythonhosted.org/packages/51/47/3fa2286c3cb162c71cdb34c4224d5745a1ceceb391b2bd9b19b668a8d724/yarl-1.23.0-cp314-cp314t-win_arm64.whl", hash = "sha256:44bb7bef4ea409384e3f8bc36c063d77ea1b8d4a5b2706956c0d6695f07dcc25", size = 86041, upload-time = "2026-03-01T22:07:49.026Z" }, - { url = "https://files.pythonhosted.org/packages/69/68/c8739671f5699c7dc470580a4f821ef37c32c4cb0b047ce223a7f115757f/yarl-1.23.0-py3-none-any.whl", hash = "sha256:a2df6afe50dea8ae15fa34c9f824a3ee958d785fd5d089063d960bae1daa0a3f", size = 48288, upload-time = "2026-03-01T22:07:51.388Z" }, +sdist = { url = "https://files.pythonhosted.org/packages/79/12/1e8f37460ea0f7eb59c221fdaf0ed75e7ac43e97f8093b9c6f411df50a78/yarl-1.24.2.tar.gz", hash = "sha256:9ac374123c6fd7abf64d1fec93962b0bd4ee2c19751755a762a72dd96c0378f8", size = 210798, upload-time = "2026-05-19T21:31:05.599Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/3f/df/f1c7a3de0831cd83194f1a85c5bb431b13f81e6b45079314c86d1c4ef3f2/yarl-1.24.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:5249a113065c2b7a958bc699759e359cd61cfc81e3069662208f48f191b7ed12", size = 129057, upload-time = "2026-05-19T21:27:47.564Z" }, + { url = "https://files.pythonhosted.org/packages/48/41/7daafb32dd7562bf45b1ce56562e7e1a9146f6479b6456873eb8a3413c40/yarl-1.24.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:7f4425fa244fbf530b006d0c5f79ce920114cfff5b4f5f6056e669f8e160fdc0", size = 91545, upload-time = "2026-05-19T21:27:50.089Z" }, + { url = "https://files.pythonhosted.org/packages/a8/8f/7b3ec212f1ea0683f55f978e3246bc313c38818664edfc97a9f349a4901e/yarl-1.24.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:15c0b5e49d3c44e2a0b93e6a49476c5edad0a7686b92c395765a7ea775572a75", size = 91380, upload-time = "2026-05-19T21:27:51.953Z" }, + { url = "https://files.pythonhosted.org/packages/8a/1b/8bafab7db23b0567ae9db749099b329d91e3b82bc6028b2050ba583e116c/yarl-1.24.2-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:246d32a53a947c8f0189f5d699cbd4c7036de45d9359e13ba238d1239678c727", size = 105957, upload-time = "2026-05-19T21:27:53.98Z" }, + { url = "https://files.pythonhosted.org/packages/7f/77/21030c2f8d21d21559719beafc772ada2014be933418ed1eaed9cc800e42/yarl-1.24.2-cp310-cp310-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:64480fb3e4d4ed9ed71c48a91a477384fc342a50ca30071d2f8a88d51d9c9413", size = 97242, upload-time = "2026-05-19T21:27:55.981Z" }, + { url = "https://files.pythonhosted.org/packages/50/d8/f9ea63d1b6aa910a866e089d871fff6cbd49caab29b86b35221a62dfa0d5/yarl-1.24.2-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:349de4701dc3760b6e876628423a8f147ef4f5599d10aba1e10702075d424ed9", size = 114719, upload-time = "2026-05-19T21:27:58.037Z" }, + { url = "https://files.pythonhosted.org/packages/e9/a3/04e0ee98ac58a249ea7ed75223f5f901ba81a834f0b4921b58e5cec11757/yarl-1.24.2-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:d162677af8d5d3d6ebab8394b021f4d041ac107a4b705873148a77a49dc9e1b2", size = 112140, upload-time = "2026-05-19T21:27:59.618Z" }, + { url = "https://files.pythonhosted.org/packages/02/ad/0b9cc9f38a7324a7eb1d80f834eaa5283d17e9271bbda3186e598dddaeac/yarl-1.24.2-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f5f5c6ec23a9043f2d139cc072f53dd23168d202a334b9b2fda8de4c3e890d90", size = 106721, upload-time = "2026-05-19T21:28:02.586Z" }, + { url = "https://files.pythonhosted.org/packages/65/e7/a52478ebfc66ec989e085c6ae038b9f1bfa4190baa193b133b669c709e2f/yarl-1.24.2-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:60de6742447fbbf697f16f070b8a443f1b5fe6ca3826fbef9fe70ecd5328e643", size = 106478, upload-time = "2026-05-19T21:28:04.523Z" }, + { url = "https://files.pythonhosted.org/packages/04/d8/5508530fea8472542de00013ae280765fc938ee196fc4030c43a498afb36/yarl-1.24.2-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:acf93187c3710e422368eb768aee98db551ec7c85adc250207a95c16548ab7ac", size = 105423, upload-time = "2026-05-19T21:28:06.515Z" }, + { url = "https://files.pythonhosted.org/packages/84/f1/ece28505e9628e8b756e11bb4f28864a17cc33b6b44db4d2aaf0622bf630/yarl-1.24.2-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:f4b0352fd41fd34b6651934606268816afd6914d09626f9bcbbf018edb0afb3f", size = 99878, upload-time = "2026-05-19T21:28:08.637Z" }, + { url = "https://files.pythonhosted.org/packages/3f/52/fb5d34529b46dd84013afcfb30b8d2bc2832ed03d412736f577d604fa393/yarl-1.24.2-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:6b208bb939099b4b297438da4e9b25357f0b1c791888669b963e45b203ea9f36", size = 114025, upload-time = "2026-05-19T21:28:10.64Z" }, + { url = "https://files.pythonhosted.org/packages/43/f0/ff9d31aaab024f7a251c0ed308a98ae29bf9f7dc344e78f28b1322431ca2/yarl-1.24.2-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:4b85b8825e631295ff4bc8943f7471d54c533a9360bbe15ebb38e018b555bb8a", size = 105613, upload-time = "2026-05-19T21:28:12.784Z" }, + { url = "https://files.pythonhosted.org/packages/31/7d/3296fb3f3ecd52bf9ae6c16b0895c1cda7e9170a2083861552b683f70264/yarl-1.24.2-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:e26acf20c26cb4fefc631fdb75aca2a6b8fa8b7b5d7f204fb6a8f1e63c706f53", size = 111665, upload-time = "2026-05-19T21:28:14.393Z" }, + { url = "https://files.pythonhosted.org/packages/1a/74/77aa6ddaca4fbf42e45e675a465c43956dd40702281049975a2aa04eae59/yarl-1.24.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:819ca24f8eafcfb683c1bd5f44f2f488cea1274eb8944731ffd2e1f10f619342", size = 106914, upload-time = "2026-05-19T21:28:15.893Z" }, + { url = "https://files.pythonhosted.org/packages/d8/02/7611f22cd1d4ed7373eb7f9ee21fde1046edba2e7c0e514880d760352f48/yarl-1.24.2-cp310-cp310-win_amd64.whl", hash = "sha256:5cb0f995a901c36be096ccbf4c673591c2faabbe96279598ffaec8c030f85bf4", size = 92658, upload-time = "2026-05-19T21:28:17.471Z" }, + { url = "https://files.pythonhosted.org/packages/91/00/671d0add79938127292839ae44506ce2f7fe8909c72d5a931864f128fd0b/yarl-1.24.2-cp310-cp310-win_arm64.whl", hash = "sha256:f408eace7e22a68b467a0562e0d27d322f91fe3eaaa6f466b962c6cfaea9fa39", size = 87887, upload-time = "2026-05-19T21:28:19.021Z" }, + { url = "https://files.pythonhosted.org/packages/c5/c5/1ce244152ff2839645e7cae92f90e7bafcb2c52bea7ff586ac714f14f5df/yarl-1.24.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:36348bebb147b83818b9d7e673ea4debc75970afc6ffdc7e3975ad05ce5a58c1", size = 128971, upload-time = "2026-05-19T21:28:20.543Z" }, + { url = "https://files.pythonhosted.org/packages/87/5a/00f36967203ed89cb3acd2c8ed526cc3fed9418eb70ce128160a911c8499/yarl-1.24.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:1a97e42c8a2233f2f279ecadd9e4a037bcb5d813b78435e8eedd4db5a9e9708c", size = 91507, upload-time = "2026-05-19T21:28:22.556Z" }, + { url = "https://files.pythonhosted.org/packages/31/d0/1fb0c1cd27288f39f6974da4318c32768d72c9890984541fdf1e2e32a51d/yarl-1.24.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:8d027d56f1035e339d1001ac33eceab5b2ec8e42e449787bb75e289fb9a5cd1d", size = 91343, upload-time = "2026-05-19T21:28:24.092Z" }, + { url = "https://files.pythonhosted.org/packages/03/ce/d4a646508bed2f8dec6435b40166fe9308dd191262033d3f307b2bbcaecd/yarl-1.24.2-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0a6377060e7927187a42b7eb202090cbe2b34933a4eeaf90e3bd9e33432e5cae", size = 105704, upload-time = "2026-05-19T21:28:25.872Z" }, + { url = "https://files.pythonhosted.org/packages/4b/07/b3278e82d8bc41485bcf6d856cd0433262593de615b1d3dc43bd3f5bead4/yarl-1.24.2-cp311-cp311-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:17076578bce0049a5ce57d14ad1bded391b68a3b213e9b81b0097b090244999a", size = 97281, upload-time = "2026-05-19T21:28:27.352Z" }, + { url = "https://files.pythonhosted.org/packages/17/5b/4cee6e7c92e487bebe7afc797da0aa54a248ab4e776a68fe369ec29665a5/yarl-1.24.2-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:50713f1d4d6be6375bb178bb43d140ee1acb8abe589cd723320b7925a275be1e", size = 114020, upload-time = "2026-05-19T21:28:29.458Z" }, + { url = "https://files.pythonhosted.org/packages/5c/82/111076571545a7d4f9cca3fbd5c6f40615af58642be09f12328f48022468/yarl-1.24.2-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:34263e2fa8fb5bb63a0d97706cda38edbad62fddb58c7f12d6acbc092812aa50", size = 111450, upload-time = "2026-05-19T21:28:31.262Z" }, + { url = "https://files.pythonhosted.org/packages/b6/ec/08f671f69a444d704aeecebf92af659b67b97a869942411d0a578b08c334/yarl-1.24.2-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:49016d82f032b1bd1e10b01078a7d29ae71bf468eeae0ea22df8bab691e60003", size = 106384, upload-time = "2026-05-19T21:28:32.856Z" }, + { url = "https://files.pythonhosted.org/packages/e5/86/ce41e7a7a199340b2330d52b60f25c4074b6636dd0e60b1a80d31a9db042/yarl-1.24.2-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:3f6d2c216318f8f32038ca3f72501ba08536f0fd18a36e858836b121b2deed9f", size = 106153, upload-time = "2026-05-19T21:28:35.222Z" }, + { url = "https://files.pythonhosted.org/packages/c4/5d/31be8a729531ab3e55ac3e7e5c800be8c89ea98947f418b2f6ea259fb6ee/yarl-1.24.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:08d3a33218e0c64393e7610284e770409a9c31c429b078bcb24096ed0a783b8f", size = 105322, upload-time = "2026-05-19T21:28:36.642Z" }, + { url = "https://files.pythonhosted.org/packages/47/9b/b57afb22b386ae87ac9940f09878b98d8c333f89113e6fc96fcf4ca9eb64/yarl-1.24.2-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:5d699376c4ca3cba49bbfae3a05b5b70ded572937171ce1e0b8d87118e2ba294", size = 99057, upload-time = "2026-05-19T21:28:38.386Z" }, + { url = "https://files.pythonhosted.org/packages/a3/4f/06348c27c8389256c313e8a57d796808fc0264c915dd5e7cfd3c0e314dc7/yarl-1.24.2-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:a1cab588b4fa14bea2e55ebea27478adfb05372f47573738e1acc4a36c0b05d2", size = 113502, upload-time = "2026-05-19T21:28:40.091Z" }, + { url = "https://files.pythonhosted.org/packages/5f/1c/284f307b298e4a17b7943b07d9d7ecc4151537f8d137ba51f3bb6c31ca20/yarl-1.24.2-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:ec87ccc31bd21db7ad009d8572c127c1000f268517618a4cc09adba3c2a7f21c", size = 105253, upload-time = "2026-05-19T21:28:41.987Z" }, + { url = "https://files.pythonhosted.org/packages/c8/bf/0de123bec8619e45c80cbded9085f61b5b4a9eddb8abe6d25d28ee1ec866/yarl-1.24.2-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:d1dd47a22843b212baa8d74f37796815d43bd046b42a0f41e9da433386c3136b", size = 111345, upload-time = "2026-05-19T21:28:43.93Z" }, + { url = "https://files.pythonhosted.org/packages/90/af/0248eb065e51129d2a9b2436cd1b5c772c19a6b04e5b6a186955671e3319/yarl-1.24.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:7b54b9c67c2b06bd7b9a77253d242124b9c95d2c02def5a1144001ee547dd9d5", size = 106558, upload-time = "2026-05-19T21:28:45.806Z" }, + { url = "https://files.pythonhosted.org/packages/21/3c/f960d7a65ef97d8ba9b424fb5128796a4bc710fc6df2ddbbd7dfdc3bbd20/yarl-1.24.2-cp311-cp311-win_amd64.whl", hash = "sha256:f8fdbcff8b2c7c9284e60c196f693588598ddcee31e11c18e14949ce44519d45", size = 92808, upload-time = "2026-05-19T21:28:48.465Z" }, + { url = "https://files.pythonhosted.org/packages/03/1a/49fb03750e4de4d2284cd5b885a383133c34eef45bd59631b2bb8b7e81e8/yarl-1.24.2-cp311-cp311-win_arm64.whl", hash = "sha256:b32c37a7a337e90822c45797bf3d79d60875cfcccd3ecc80e9f453d87026c122", size = 87610, upload-time = "2026-05-19T21:28:50.07Z" }, + { url = "https://files.pythonhosted.org/packages/f0/da/866bcb01076ba49d2b42b309867bed3826421f1c479655eb7a607b44f20b/yarl-1.24.2-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:b975866c184564c827e0877380f0dae57dcca7e52782128381b72feff6dfceb8", size = 129957, upload-time = "2026-05-19T21:28:51.695Z" }, + { url = "https://files.pythonhosted.org/packages/bf/1d/fcefb70922ea2268a8971d8e5874d9a8218644200fb8465f1dcad55e6851/yarl-1.24.2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:3b075301a2836a0e297b1b658cb6d6135df535d62efefdd60366bd589c2c82f2", size = 92164, upload-time = "2026-05-19T21:28:53.242Z" }, + { url = "https://files.pythonhosted.org/packages/29/b6/170e2b8d4e3bc30e6bfdcca53556537f5bf595e938632dfcb059311f3ff6/yarl-1.24.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8ae44649b00947634ab0dab2a374a638f52923a6e67083f2c156cd5cbd1a881d", size = 91688, upload-time = "2026-05-19T21:28:54.865Z" }, + { url = "https://files.pythonhosted.org/packages/fe/a5/c9f655d5553ea0b99fdac9d6a99ad3f9b3e73b8e5758bb46f58c9831f74c/yarl-1.24.2-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:507cc19f0b45454e2d6dcd62ff7d062b9f77a2812404e62dbdaec05b50faa035", size = 102902, upload-time = "2026-05-19T21:28:56.963Z" }, + { url = "https://files.pythonhosted.org/packages/5d/bc/6b9664d815d79af4ee553337f9d606c56bbf269186ada9172de45f1b5f60/yarl-1.24.2-cp312-cp312-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:c4c17bad5a530912d2111825d3f05e89bab2dd376aaa8cbc77e449e6db63e576", size = 97931, upload-time = "2026-05-19T21:28:58.56Z" }, + { url = "https://files.pythonhosted.org/packages/98/ec/32ba48acae30fecd60928f5791188b80a9d6ee3840507ffda29fecd37b71/yarl-1.24.2-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:f5f0cbb112838a4a293985b6ed73948a547dadcc1ba6d2089938e7abdedceef8", size = 111030, upload-time = "2026-05-19T21:29:00.148Z" }, + { url = "https://files.pythonhosted.org/packages/82/5a/6f4cd081e5f4934d2ae3a8ef4abe3afacc010d26f0035ee91b35cd7d7c37/yarl-1.24.2-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:5ec8356b8a6afcf81fc7aeeef13b1ff7a49dec00f313394bbb9e83830d32ccd7", size = 110392, upload-time = "2026-05-19T21:29:02.155Z" }, + { url = "https://files.pythonhosted.org/packages/7a/da/323a01c349bd5fb01bb6652e314d9bb218cee630a736bdb810ad50e4013f/yarl-1.24.2-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:7e7ebcdef69dec6c6451e616f32b622a6d4a2e92b445c992f7c8e5274a6bbc4c", size = 105612, upload-time = "2026-05-19T21:29:04.247Z" }, + { url = "https://files.pythonhosted.org/packages/7c/80/264ab684f181e1a876389374519ff05d10248725535ae2ac4e8ac4e563d6/yarl-1.24.2-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:47a55d6cf6db2f401017a9e96e5288844e5051911fb4e0c8311a3980f5e59a7d", size = 104487, upload-time = "2026-05-19T21:29:06.491Z" }, + { url = "https://files.pythonhosted.org/packages/41/07/efabe5df87e96d7ad5959760b888344be48cd6884db127b407c6b5503adc/yarl-1.24.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:3065657c80a2321225e804048597ad55658a7e76b32d6f5ee4074d04c50401db", size = 102333, upload-time = "2026-05-19T21:29:08.267Z" }, + { url = "https://files.pythonhosted.org/packages/44/0c/bcf7c42603e1009295f586d8890f2ba032c8b53310e815adf0a202c73d9f/yarl-1.24.2-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:cb84b80d88e19ede158619b80813968713d8d008b0e2497a576e6a0557d50712", size = 99025, upload-time = "2026-05-19T21:29:10.682Z" }, + { url = "https://files.pythonhosted.org/packages/4f/82/84482ab1a57a0f21a08afe6a7004c61d741f8f2ecc3b05c321577c612164/yarl-1.24.2-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:990de4f680b1c217e77ff0d6aa0029f9eb79889c11fb3e9a3942c7eba29c1996", size = 110507, upload-time = "2026-05-19T21:29:12.954Z" }, + { url = "https://files.pythonhosted.org/packages/c4/8d/a546ba1dfe1b0f290e05fef145cd07614c0f15df1a707195e512d1e39d1d/yarl-1.24.2-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:abb8ec0323b80161e3802da3150ef660b41d0e9be2048b76a363d93eee992c2b", size = 103719, upload-time = "2026-05-19T21:29:14.893Z" }, + { url = "https://files.pythonhosted.org/packages/1a/b6/267f2a09213138473adfce6b8a6e17791d7fee70bd4d9003218e4dec58b0/yarl-1.24.2-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:e7977781f83638a4c73e0f88425563d70173e0dfd90ac006a45c65036293ee3c", size = 110438, upload-time = "2026-05-19T21:29:16.485Z" }, + { url = "https://files.pythonhosted.org/packages/48/2d/1c8d89c7c5f9cad9fb2902445d94e2ab1d7aa35de029afbb8ae95c42d00f/yarl-1.24.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:e30dd55825dc554ec5b66a94953b8eda8745926514c5089dfcacecb9c99b5bd1", size = 105719, upload-time = "2026-05-19T21:29:18.367Z" }, + { url = "https://files.pythonhosted.org/packages/a7/25/722e3b93bd687009afb2d59a35e13d30ddd8f80571445bb0c4e4ce26ec66/yarl-1.24.2-cp312-cp312-win_amd64.whl", hash = "sha256:7dafe10c12ddd4d120d528c4b5599c953bd7b12845347d507b95451195bb6cad", size = 92901, upload-time = "2026-05-19T21:29:20.014Z" }, + { url = "https://files.pythonhosted.org/packages/39/47/4486ccfb674c04854a1ef8aa77868b6a6f765feaf69633409d7ca4f02cb8/yarl-1.24.2-cp312-cp312-win_arm64.whl", hash = "sha256:044a09d8401fcf8681977faef6d286b8ade1e2d2e9dceda175d1cfa5ca496f30", size = 87229, upload-time = "2026-05-19T21:29:22.1Z" }, + { url = "https://files.pythonhosted.org/packages/82/62/fcf0ce677f17e5c471c06311dd25964be38a4c586993632910d2e75278bc/yarl-1.24.2-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:491ac9141decf49ee8030199e1ee251cdff0e131f25678817ff6aa5f837a3536", size = 128978, upload-time = "2026-05-19T21:29:23.83Z" }, + { url = "https://files.pythonhosted.org/packages/d3/58/8e63299bb71ed61a834121d9d3fe6c9fcf2a6a5d09754ff4f20f2d20baf5/yarl-1.24.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:e89418f65eda18f99030386305bd44d7d504e328a7945db1ead514fbe03a0607", size = 91733, upload-time = "2026-05-19T21:29:25.375Z" }, + { url = "https://files.pythonhosted.org/packages/c1/24/16748d5dab6daec8b0ed81ccec639a1cded0f18dcc62a4f696b4fe366c37/yarl-1.24.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:cdfcce633b4a4bb8281913c57fcafd4b5933fbc19111a5e3930bbd299d6102f1", size = 91113, upload-time = "2026-05-19T21:29:26.928Z" }, + { url = "https://files.pythonhosted.org/packages/1b/66/b63fff7b71211e866624b21432d5943cbb633eb0c2872d9ee3070648f22c/yarl-1.24.2-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:863297ddede92ee49024e9a9b11ecb59f310ca85b60d8537f56bed9bbb5b1986", size = 103899, upload-time = "2026-05-19T21:29:28.842Z" }, + { url = "https://files.pythonhosted.org/packages/9d/ac/ba1974b8533909636f7733fe86cf677e3619527c3c2fa913e0ea89c48757/yarl-1.24.2-cp313-cp313-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:374423f70754a2c96942ede36a29d37dc6b0cb8f92f8d009ddf3ed78d3da5488", size = 97862, upload-time = "2026-05-19T21:29:31.086Z" }, + { url = "https://files.pythonhosted.org/packages/1b/a5/123ac993b5c2ba6f554a140305620cb8f150fa543711bbc49be3ec0a65a4/yarl-1.24.2-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:33a29b5d00ccbf3219bb3e351d7875739c19481e030779f48cc46a7a71681a9b", size = 111060, upload-time = "2026-05-19T21:29:32.657Z" }, + { url = "https://files.pythonhosted.org/packages/23/37/c472d3af3509688392134a88a825276770a187f1daa4de3f6dc0a327a751/yarl-1.24.2-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:a9532c57211730c515341af11fef6e9b61d157487272a096d0c04da445642592", size = 110613, upload-time = "2026-05-19T21:29:34.379Z" }, + { url = "https://files.pythonhosted.org/packages/df/88/09c28dad91e662ccfaa1b78f1c57badde74fc9d0b23e74aef644750ecd73/yarl-1.24.2-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:91e72cf093fd833483a97ee648e0c053c7c629f51ff4a0e7edd84f806b0c5617", size = 107012, upload-time = "2026-05-19T21:29:36.216Z" }, + { url = "https://files.pythonhosted.org/packages/07/ab/9d4f69d571a94f4d112fa7e2e007200f5a54d319f58c82ac7b7baa61f5c6/yarl-1.24.2-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:b3177bc0a768ef3bacceb4f272632990b7bea352f1b2f1eee9d6d6ff16516f92", size = 105887, upload-time = "2026-05-19T21:29:38.746Z" }, + { url = "https://files.pythonhosted.org/packages/8e/9a/000b2b66c0d772a499fc531d21dab92dfeb73b640a12eed6ba89f49bb2d0/yarl-1.24.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:e196952aacaf3b232e265ff02980b64d483dc0972bd49bcb061171ff22ac203a", size = 103620, upload-time = "2026-05-19T21:29:40.368Z" }, + { url = "https://files.pythonhosted.org/packages/41/7c/7c1050f73450fbdaa3f0c72017059f00ce5e13366692f3dba25275a1083d/yarl-1.24.2-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:204e7a61ce99919c0de1bf904ab5d7aa188a129ea8f690a8f76cfb6e2844dc44", size = 100599, upload-time = "2026-05-19T21:29:42.66Z" }, + { url = "https://files.pythonhosted.org/packages/ec/b1/29e5756b3926705f5f6089bd5b9f50a56eaac550da6e260bf713ead44d04/yarl-1.24.2-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:4b156914620f0b9d78dc1adb3751141daee561cfec796088abb89ed49d220f1a", size = 110604, upload-time = "2026-05-19T21:29:44.632Z" }, + { url = "https://files.pythonhosted.org/packages/a3/4b/8415bc96e9b150cde942fbac9a8182985e58f40ce5c54c34ed015407d3ee/yarl-1.24.2-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:8372a2b976cf70654b2be6619ab6068acabb35f724c0fda7b277fbf53d66a5cf", size = 105161, upload-time = "2026-05-19T21:29:46.755Z" }, + { url = "https://files.pythonhosted.org/packages/8b/d4/cde059abfa229553b7298a2eadde2752e723d50aeedaef86ce59da2718ee/yarl-1.24.2-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:f9a1e9b622ca284143aab5d885848686dcd85453bb1ca9abcdb7503e64dc0056", size = 110619, upload-time = "2026-05-19T21:29:48.972Z" }, + { url = "https://files.pythonhosted.org/packages/e7/2c/d6a6c9a61549f7b6c7e6dc6937d195bcf069582b47b7200dcd0e7b256acf/yarl-1.24.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:810e19b685c8c3c5862f6a38160a1f4e4c0916c9390024ec347b6157a45a0992", size = 107362, upload-time = "2026-05-19T21:29:51Z" }, + { url = "https://files.pythonhosted.org/packages/92/dd/3ae5fe417e9d1c353a548553326eb9935e76b6b727161563b424cc296df3/yarl-1.24.2-cp313-cp313-win_amd64.whl", hash = "sha256:7d37fb7c38f2b6edab0f845c4f85148d4c44204f52bc127021bd2bc9fdbf1656", size = 92667, upload-time = "2026-05-19T21:29:52.743Z" }, + { url = "https://files.pythonhosted.org/packages/10/cc/a7beb239f78f27fca1b053c8e8595e4179c02e62249b4687ec218c370c50/yarl-1.24.2-cp313-cp313-win_arm64.whl", hash = "sha256:1e831894be7c2954240e49791fa4b50c05a0dc881de2552cfe3ffd8631c7f461", size = 87069, upload-time = "2026-05-19T21:29:54.442Z" }, + { url = "https://files.pythonhosted.org/packages/40/0e/e08087695fc12789263821c5dc0f8dc52b5b17efd0887cacf419f8a43ba3/yarl-1.24.2-cp314-cp314-macosx_10_15_universal2.whl", hash = "sha256:f9312b3c02d9b3d23840f67952913c9c8721d7f1b7db305289faefa878f364c2", size = 129670, upload-time = "2026-05-19T21:29:56.631Z" }, + { url = "https://files.pythonhosted.org/packages/3a/98/ab4b5ed1b1b5cd973c8a3eb994c3a6aefb6ce6d399e21bb5f0316c33815c/yarl-1.24.2-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:a4f4d6cd615823bfc7fb7e9b5987c3f41666371d870d51058f77e2680fbe9630", size = 91916, upload-time = "2026-05-19T21:29:58.645Z" }, + { url = "https://files.pythonhosted.org/packages/ba/b1/5297bb6a7df4782f7605bffc43b31f5044070935fbbcaa6c705a07e6ac65/yarl-1.24.2-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:0c3063e5c0a8e8e62fae6c2596fa01da1561e4cd1da6fec5789f5cf99a8aefd8", size = 91625, upload-time = "2026-05-19T21:30:00.412Z" }, + { url = "https://files.pythonhosted.org/packages/02/a7/45baabfff76829264e623b185cff0c340d7e11bf3e1cd9ea37e7d17934bd/yarl-1.24.2-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:fecd17873a096036c1c87ab3486f1aef7f269ada7f23f7f856f93b1cc7744f14", size = 104574, upload-time = "2026-05-19T21:30:02.544Z" }, + { url = "https://files.pythonhosted.org/packages/f3/40/3a5ab144d3d650ca37d4f4b57e56169be8af3ca34c448793e064b30baaed/yarl-1.24.2-cp314-cp314-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:a46d1ab4ba4d32e6dc80daf8a28ce0bd83d08df52fbc32f3e288663427734535", size = 97534, upload-time = "2026-05-19T21:30:04.319Z" }, + { url = "https://files.pythonhosted.org/packages/9c/b5/5658fef3681fb5776b4513b052bec750009f47b3a592251c705d75375798/yarl-1.24.2-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:73e68edf6dfd5f73f9ca127d84e2a6f9213c65bdffb736bda19524c0564fcd14", size = 111481, upload-time = "2026-05-19T21:30:05.988Z" }, + { url = "https://files.pythonhosted.org/packages/4c/06/fdcd7dde037f00866dce123ed4ba23dba94beb56fc4cf561668d27be37f2/yarl-1.24.2-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:a296ca617f2d25fbceafb962b88750d627e5984e75732c712154d058ae8d79a3", size = 111529, upload-time = "2026-05-19T21:30:07.738Z" }, + { url = "https://files.pythonhosted.org/packages/c2/53/d81269aaafccea0d33396c03035de997b743f11e648e6e27a0df99c72980/yarl-1.24.2-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e51b2cf5ec89a8b8470177641ed62a3ba22d74e1e898e06ad53aa77972487208", size = 107338, upload-time = "2026-05-19T21:30:09.713Z" }, + { url = "https://files.pythonhosted.org/packages/ae/04/23049463f729bd899df203a7960505a75333edd499cda8aa1d5a82b64df5/yarl-1.24.2-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:310fc687f7b2044ec54e372c8cbe923bb88f5c37bded0d3079e5791c2fc3cf50", size = 106147, upload-time = "2026-05-19T21:30:11.365Z" }, + { url = "https://files.pythonhosted.org/packages/14/18/04a4b5830b43ed5e4c5015b40e9f6241ad91487d71611061b4e111d6ac80/yarl-1.24.2-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:297a2fe352ecf858b30a98f87948746ec16f001d279f84aebdbd3bd965e2f1bd", size = 104272, upload-time = "2026-05-19T21:30:12.978Z" }, + { url = "https://files.pythonhosted.org/packages/5a/f7/8cffdf319aee7a7c1dbd07b61d91c3e3fda460c7a93b5f93e445f3806c4c/yarl-1.24.2-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:2a263e76b97bc42bdcd7c5f4953dec1f7cd62a1112fa7f869e57255229390d67", size = 99962, upload-time = "2026-05-19T21:30:15.001Z" }, + { url = "https://files.pythonhosted.org/packages/d7/39/b3cce3b7dbef64ac700ad4cea156a207d01bede0f507587616c364b5468e/yarl-1.24.2-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:822519b64cf0b474f1a0aaef1dc621438ea46bb77c94df97a5b4d213a7d8a8b1", size = 111063, upload-time = "2026-05-19T21:30:16.683Z" }, + { url = "https://files.pythonhosted.org/packages/a1/ea/100818505e7ebf165c7242ff17fdf7d9fee79e27234aeca871c1082920d7/yarl-1.24.2-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:b6067060d9dc594899ba83e6db6c48c68d1e494a6dab158156ed86977ca7bcb1", size = 105438, upload-time = "2026-05-19T21:30:18.769Z" }, + { url = "https://files.pythonhosted.org/packages/8f/d2/e075a0b32aa6625087de9e653087df0759fed5de4a435fef594181102a77/yarl-1.24.2-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:0063adad533e57171b79db3943b229d40dfafeeee579767f96541f106bac5f1b", size = 111458, upload-time = "2026-05-19T21:30:21.024Z" }, + { url = "https://files.pythonhosted.org/packages/e6/5c/ceea7ba98b65c8eb8d947fdc52f9bedfcd43c6a57c9e3c90c17be8f324a3/yarl-1.24.2-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:ee8e3fb34513e8dc082b586ef4910c98335d43a6fab688cd44d4851bacfce3e8", size = 107589, upload-time = "2026-05-19T21:30:23.412Z" }, + { url = "https://files.pythonhosted.org/packages/fa/d9/5582d57e2b2db9b85eb6663a22efdd78e08805f3f5389566e9fcad254d1b/yarl-1.24.2-cp314-cp314-win_amd64.whl", hash = "sha256:afb00d7fd8e0f285ca29a44cc50df2d622ff2f7a6d933fa641577b5f9d5f3db0", size = 94424, upload-time = "2026-05-19T21:30:25.425Z" }, + { url = "https://files.pythonhosted.org/packages/92/10/7dc07a0e22806a9280f42a57361395506e800c64e22737cd7b0886feab42/yarl-1.24.2-cp314-cp314-win_arm64.whl", hash = "sha256:68cf6eacd6028ef1142bc4b48376b81566385ca6f9e7dde3b0fa91be08ffcb57", size = 88690, upload-time = "2026-05-19T21:30:27.623Z" }, + { url = "https://files.pythonhosted.org/packages/9e/13/d5b8e2c8667db955bcb3de233f18798fefe7edf1d7429c2c9d4f9c401114/yarl-1.24.2-cp314-cp314t-macosx_10_15_universal2.whl", hash = "sha256:221ce1dd921ac4f603957f17d7c18c5cc0797fbb52f156941f92e04605d1d67b", size = 136248, upload-time = "2026-05-19T21:30:29.297Z" }, + { url = "https://files.pythonhosted.org/packages/de/46/a4a97c05c9c9b8fd266bb2a0df12992c7fbd02391eb9640583411b6dab32/yarl-1.24.2-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:5f3224db28173a00d7afacdee07045cc4673dfab2b15492c7ae10deddbece761", size = 95084, upload-time = "2026-05-19T21:30:31.031Z" }, + { url = "https://files.pythonhosted.org/packages/95/b2/845cf2074a015e6fe0d0808cf1a2d9e868386c4220d657ebd8302b199043/yarl-1.24.2-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:c557165320d6244ebe3a02431b2a201a20080e02f41f0cfa0ccc47a183765da8", size = 95272, upload-time = "2026-05-19T21:30:33.062Z" }, + { url = "https://files.pythonhosted.org/packages/fe/16/e69d4aa244aef45235ddfebc0e04036a6829842bc5a6a795aedc6c998d23/yarl-1.24.2-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:904065e6e85b1fa54d0d87438bd58c14c0bad97aad654ad1077fd9d87e8478ed", size = 101497, upload-time = "2026-05-19T21:30:34.842Z" }, + { url = "https://files.pythonhosted.org/packages/15/94/c07107715d621076863ee88b3ddf183fa5e9d4aba5769623c9979828410a/yarl-1.24.2-cp314-cp314t-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:8cec2a38d70edc10e0e856ceda886af5327a017ccbde8e1de1bd44d300357543", size = 94002, upload-time = "2026-05-19T21:30:37.724Z" }, + { url = "https://files.pythonhosted.org/packages/a9/35/fc1bbdd895b5e4010b8fdd037f7ed3aa289d3863e08231b30231ca9a0815/yarl-1.24.2-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:e7484b9361ed222ee1ca5b4337aa4cbdcc4618ce5aff57d9ef1582fd95893fc0", size = 106524, upload-time = "2026-05-19T21:30:40.196Z" }, + { url = "https://files.pythonhosted.org/packages/1f/f2/32b66d0a4ba47c296cf86d03e2c67bff58399fe6d6d84d5205c04c66cc6d/yarl-1.24.2-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:84f9670b89f34db07f81e53aee83e0b938a3412329d51c8f922488be7fcc4024", size = 106165, upload-time = "2026-05-19T21:30:41.888Z" }, + { url = "https://files.pythonhosted.org/packages/95/47/37cb5ff50c5e825d4d38e81bb04d1b7e96bf960f7ab89f9850b162f3f114/yarl-1.24.2-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:abb2759733d63a28b4956500a5dd57140f26486c92b2caedfb964ab7d9b79dbf", size = 103010, upload-time = "2026-05-19T21:30:43.985Z" }, + { url = "https://files.pythonhosted.org/packages/6f/d2/4597912315096f7bb359e46e13bf8b60994fcbb2db29b804c0902ef4eff5/yarl-1.24.2-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:081c2bf54efe03774d0311172bc04fedf9ca01e644d4cd8c805688e527209bdc", size = 101128, upload-time = "2026-05-19T21:30:46.291Z" }, + { url = "https://files.pythonhosted.org/packages/b9/d5/c8e86e120521e646013d02a8e3b8884392e28494be8f392366e50d208efc/yarl-1.24.2-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:86746bef442aa479107fe28132e1277237f9c24c2f00b0b0cf22b3ee0904f2bb", size = 101382, upload-time = "2026-05-19T21:30:48.085Z" }, + { url = "https://files.pythonhosted.org/packages/fa/98/70b229236118f89dbeb739b76f10225bbf53b5497725502594c9a01d699a/yarl-1.24.2-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:2d07d21d0bc4b17558e8de0b02fbfdf1e347d3bb3699edd00bb92e7c57925420", size = 95964, upload-time = "2026-05-19T21:30:49.785Z" }, + { url = "https://files.pythonhosted.org/packages/87/f8/56c386981e3c8648d279fdef2397ffec577e8320fd5649745e34d54faeb7/yarl-1.24.2-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:4fb1ac3fc5fecd8ae7453ea237e4d22b49befa70266dfe1629924245c21a0c7f", size = 106204, upload-time = "2026-05-19T21:30:51.862Z" }, + { url = "https://files.pythonhosted.org/packages/1a/1e/765afe97811ca35933e2a7de70ac57b1997ea2e4ee895719ee7a231fb7e5/yarl-1.24.2-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:4da31a5512ed1729ca8d8aacde3f7faeb8843cde3165d6bcf7f88f74f17bb8aa", size = 101510, upload-time = "2026-05-19T21:30:53.62Z" }, + { url = "https://files.pythonhosted.org/packages/ee/78/393913f4b9039e1edd09ae8a9bbb9d539be909a8abf6d8a2084585bed4b7/yarl-1.24.2-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:533ded4dceb5f1f3da7906244f4e82cf46cfd40d84c69a1faf5ac506aa65ecbe", size = 105584, upload-time = "2026-05-19T21:30:55.962Z" }, + { url = "https://files.pythonhosted.org/packages/78/87/deb17b7049bbe74ea11a713b86f8f27800cc1c8648b0b797243ebb4830ba/yarl-1.24.2-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:7b3a85525f6e7eeabcfdd372862b21ee1915db1b498a04e8bf0e389b607ff0bd", size = 103410, upload-time = "2026-05-19T21:30:57.962Z" }, + { url = "https://files.pythonhosted.org/packages/8f/be/f9f7594e23b5b93affff0318e4593c1920331bcaefda326cabcad94296a1/yarl-1.24.2-cp314-cp314t-win_amd64.whl", hash = "sha256:a7624b1ca46ca5d7b864ef0d2f8efe3091454085ee1855b4e992314529972215", size = 102980, upload-time = "2026-05-19T21:30:59.735Z" }, + { url = "https://files.pythonhosted.org/packages/65/a4/ba80dccd3593ff1f01051a818694d07b58cb8232677ee9a22a5a1f93a9fc/yarl-1.24.2-cp314-cp314t-win_arm64.whl", hash = "sha256:e434a45ce2e7a947f951fc5a8944c8cc080b7e59f9c50ae80fd39107cf88126d", size = 91219, upload-time = "2026-05-19T21:31:01.934Z" }, + { url = "https://files.pythonhosted.org/packages/fd/4d/4b880086bd0d3e034d25647be1d830afc3e3f610e98c4ab3490af6b1b6d5/yarl-1.24.2-py3-none-any.whl", hash = "sha256:2783d9226db8797636cd6896e4de81feed252d1db72265686c9558d97a4d94b9", size = 53576, upload-time = "2026-05-19T21:31:03.909Z" }, ] [[package]] name = "zipp" -version = "3.23.1" +version = "4.1.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/30/21/093488dfc7cc8964ded15ab726fad40f25fd3d788fd741cc1c5a17d78ee8/zipp-3.23.1.tar.gz", hash = "sha256:32120e378d32cd9714ad503c1d024619063ec28aad2248dc6672ad13edfa5110", size = 25965, upload-time = "2026-04-13T23:21:46.6Z" } +sdist = { url = "https://files.pythonhosted.org/packages/b9/d8/eab98a517c14134c0b2eb4e2387bc5f457334293ec5d2dd3857ec2966802/zipp-4.1.0.tar.gz", hash = "sha256:4cb57381f544315db7688e976e922a2b18cdb513d21cc194eb42232ba2a3e602", size = 26214, upload-time = "2026-05-18T20:08:57.967Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/08/8a/0861bec20485572fbddf3dfba2910e38fe249796cb73ecdeb74e07eeb8d3/zipp-3.23.1-py3-none-any.whl", hash = "sha256:0b3596c50a5c700c9cb40ba8d86d9f2cc4807e9bedb06bcdf7fac85633e444dc", size = 10378, upload-time = "2026-04-13T23:21:45.386Z" }, + { url = "https://files.pythonhosted.org/packages/3a/13/547360d81e6d88d58492968ffda9f9542854f11310ee556fef14260cc886/zipp-4.1.0-py3-none-any.whl", hash = "sha256:25ad4e16390cd314347dd8f1de67a2ac538ae658ed4ab9db16029c07c188e97f", size = 10238, upload-time = "2026-05-18T20:08:57.045Z" }, ] [[package]] name = "zope-interface" -version = "8.3" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/c9/04/0b1d92e7d31507c5fbe203d9cc1ae80fb0645688c7af751ea0ec18c2223e/zope_interface-8.3.tar.gz", hash = "sha256:e1a9de7d0b5b5c249a73b91aebf4598ce05e334303af6aa94865893283e9ff10", size = 256822, upload-time = "2026-04-10T06:12:35.036Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/5e/47/791e8da00c00332d4db7f9add22cb102c523e452ea0449bb63eb7dcc3c17/zope_interface-8.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:c8a2f9c4ee0f2ad4817e9481684993d33b66d9b815f9157a716a189af483bc34", size = 210367, upload-time = "2026-04-10T06:21:50.304Z" }, - { url = "https://files.pythonhosted.org/packages/8b/d5/92bad86cb429af22f59f6e08227c58c74a3d8395a64a5ca61b9301fc6171/zope_interface-8.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:99c84e12efe0e17f03c6bb5a8ea18fb2841e6666ee0b8331d5967fec84337884", size = 210726, upload-time = "2026-04-10T06:21:52.375Z" }, - { url = "https://files.pythonhosted.org/packages/cb/55/ddf1aeb3e4d5f7a343599a76dafc0766ec42b32112bfedc37f7ddeff753f/zope_interface-8.3-cp310-cp310-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:a918f8e73c35a1352a4b49db67b90b37d33fb7651c834def3f0e3784437bb3a8", size = 254046, upload-time = "2026-04-10T06:21:54.332Z" }, - { url = "https://files.pythonhosted.org/packages/b6/4f/a52a78b389c79d85d3d4afbf71b2984bd4a8a682beec248cdc21576b13a6/zope_interface-8.3-cp310-cp310-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:5a5b50d0dcdb4200f1936f75b6688bd86de5c14c5d20bed2e004300a04521826", size = 258910, upload-time = "2026-04-10T06:21:56.588Z" }, - { url = "https://files.pythonhosted.org/packages/08/34/2841cb5c1dea43a1e3893deb0ed412d4eeb16f4a3eb4daf2465d24b71069/zope_interface-8.3-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:731eaf0a0f2a683315a2dfc2953ef831ae51e062b87cff6220e0e5102a83b612", size = 259521, upload-time = "2026-04-10T06:21:58.505Z" }, - { url = "https://files.pythonhosted.org/packages/23/ff/66ba0f3aba2d3724e425fdb99122d6f7927a37d623492a606477094a6891/zope_interface-8.3-cp310-cp310-win_amd64.whl", hash = "sha256:5e9861493457268f923d8aae4052383922162c3d56094c4e3a9ff83173d64be3", size = 214205, upload-time = "2026-04-10T06:22:00.611Z" }, - { url = "https://files.pythonhosted.org/packages/0d/99/cee01c7e8be6c5889f2c74914196decd91170011f420c9912792336f284c/zope_interface-8.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:e8964f1a13b07c8770eab88b7a6cd0870c3e36442e4ef4937f36fd0b6d1cea2c", size = 210875, upload-time = "2026-04-10T06:22:02.746Z" }, - { url = "https://files.pythonhosted.org/packages/e2/f1/cf7a49b36385ed1ee0cc7f6b8861904f1533a3286e01cd1e3c2eb72976b9/zope_interface-8.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:ec2728e3cf685126ccd2e0f7635fb60edf116f76f402dd66f4df13d9d9348b4b", size = 211199, upload-time = "2026-04-10T06:22:04.596Z" }, - { url = "https://files.pythonhosted.org/packages/cc/86/1ccb73ce9189b1345b7824830a18796ae0b33317d3725d8a034a6ce06501/zope_interface-8.3-cp311-cp311-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:568b97cb701fd2830b52198a2885e851317a019e1912eaad107860e3cca71964", size = 259885, upload-time = "2026-04-10T06:22:06.403Z" }, - { url = "https://files.pythonhosted.org/packages/a1/de/d0185211ad4902641c0233b7c3b42e21582ffac24f5afe5cc4736b196346/zope_interface-8.3-cp311-cp311-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:62839e4201869a29f99742df7f7139cac4ce301850d3787da37f84e271ad9b95", size = 264308, upload-time = "2026-04-10T06:22:08.425Z" }, - { url = "https://files.pythonhosted.org/packages/0e/e5/ac6f24cdaa04711246d425a2ca301e2f3c97e8d6d672b44258eb2ceb92ff/zope_interface-8.3-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:d287183767926bc9841e51471a28b77c7b49fddf65016aa7faf5a1447e2b6558", size = 265594, upload-time = "2026-04-10T06:22:10.111Z" }, - { url = "https://files.pythonhosted.org/packages/b3/ca/e888c67123b6a7019936c67b5ebcc9396fdb3067cf278d7541d24f4c1a86/zope_interface-8.3-cp311-cp311-win_amd64.whl", hash = "sha256:12a33bb596ca20520e44f97918950cfc66a632ac0278a7f40608217cc4269948", size = 214562, upload-time = "2026-04-10T06:22:12.681Z" }, - { url = "https://files.pythonhosted.org/packages/16/1e/7ed593f9c3664e560febe1f132fdf73b8bb9a3de6e3448093b0167239c8c/zope_interface-8.3-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:b361b7ce566bc024e55f74eb1e88afc14039d7bd8ea13eeff3b7a8400dc59683", size = 211571, upload-time = "2026-04-10T06:22:14.775Z" }, - { url = "https://files.pythonhosted.org/packages/cf/31/844979b472f30efd2a68480738c9a3be518786b0885137075616607e88c7/zope_interface-8.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:f5be73ca1304daa3046ee5835f7fa6b3badadf02102b570532dd57cd25dd72d6", size = 211748, upload-time = "2026-04-10T06:22:16.695Z" }, - { url = "https://files.pythonhosted.org/packages/6e/b6/71f5c9d8dde7334e1b67306fea5814c67eac92d871bb0dfc664c9f3355f1/zope_interface-8.3-cp312-cp312-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:961af756797e36c1e77f7d0dc8ac1322de0c071eaa1a641dbe3b790061968dd9", size = 264718, upload-time = "2026-04-10T06:22:19.473Z" }, - { url = "https://files.pythonhosted.org/packages/94/e3/5eab77fd6795ca37b9ed1aeea5290170018938549322003745bdcd939238/zope_interface-8.3-cp312-cp312-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:a6329f296b70f62043bf2df06eb91b4be040baee32ec4a3e0314f3893fa5c51c", size = 269795, upload-time = "2026-04-10T06:22:21.728Z" }, - { url = "https://files.pythonhosted.org/packages/a2/2f/4bc8807d65833f06335a49beb1786bafcf748cde7472ba14cdb4db463ba8/zope_interface-8.3-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:f420f6c96307ff265981c510782f0ed97475107b78ca9fca0bb04fe36f363eb4", size = 269418, upload-time = "2026-04-10T06:22:23.802Z" }, - { url = "https://files.pythonhosted.org/packages/50/3d/1cfaf770bc6bc64edec3d4c5f17b5dbe600bf93cd2caac5ee0880eb9f9e0/zope_interface-8.3-cp312-cp312-win_amd64.whl", hash = "sha256:ffeae9102aa6ba5bd2f9a547016347bd87c9cf01aea564936c0d165fff0b1242", size = 214390, upload-time = "2026-04-10T06:22:25.735Z" }, - { url = "https://files.pythonhosted.org/packages/27/da/ff205c5463e52ad64cc40be667fdff2b01b9754a385c6b95bac01645fa4f/zope_interface-8.3-cp313-cp313-macosx_10_9_x86_64.whl", hash = "sha256:1aa0e1d72212cedc38b2156bbca08cf24625c057135a7947ef6b19bc732b2772", size = 211889, upload-time = "2026-04-10T06:22:27.612Z" }, - { url = "https://files.pythonhosted.org/packages/c7/21/0cc848e22769b1cf4c0cd636ec2e60ea05cfb958423435ea526d5a291fe8/zope_interface-8.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:54ab83218a8f6947ba4b6cb1a121f1e1abe2e418b838ccdac71639d0f97e734e", size = 211961, upload-time = "2026-04-10T06:22:29.575Z" }, - { url = "https://files.pythonhosted.org/packages/e3/54/815c9dbb90336c50694b4c7ef7ced06bc389e5597200c77457b557a0221c/zope_interface-8.3-cp313-cp313-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:34d6c10fa790005487c471e0e4ab537b0fa9a70e55a96994e51ffeef92205fa4", size = 264409, upload-time = "2026-04-10T06:22:31.426Z" }, - { url = "https://files.pythonhosted.org/packages/3a/69/2e5c30adde0e94552d934971fa6eba107449d3d11fa086cfcfeb8ea6354d/zope_interface-8.3-cp313-cp313-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:93108d5f8dee20177a637438bf4df4c6faf8a317c9d4a8b1d5e78123854e3317", size = 269592, upload-time = "2026-04-10T06:22:33.393Z" }, - { url = "https://files.pythonhosted.org/packages/23/8a/fbb1dceb5c5400b2b27934aa102d29fe4cb06732122e7f409efebeb6e097/zope_interface-8.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:8f81d90f80b9fbf36602549e2f187861c9d7139837f8c9dd685ce3b933c6360f", size = 269548, upload-time = "2026-04-10T06:22:35.339Z" }, - { url = "https://files.pythonhosted.org/packages/a2/70/abd0bb9cc9b1a9a718f30c81f46a184a2e751dd80cf57db142ffa42730da/zope_interface-8.3-cp313-cp313-win_amd64.whl", hash = "sha256:96106a5f609bb355e1aec6ab0361213c8af0843ca1e1ba9c42eacfbd0910914e", size = 214391, upload-time = "2026-04-10T06:22:36.969Z" }, - { url = "https://files.pythonhosted.org/packages/8a/d9/95fe0d4d8da09042383c42f239e0106f1019ec86a27ed9f5000e754f6e7a/zope_interface-8.3-cp314-cp314-macosx_10_9_x86_64.whl", hash = "sha256:96f0001b49227d756770fc70ecde49f19332ae98ec98e1bbbf2fd7a87e9d4e45", size = 211979, upload-time = "2026-04-10T06:22:38.628Z" }, - { url = "https://files.pythonhosted.org/packages/f3/01/b6f694444ea1c911a4ea915f4ef066a95e9d1a58256a30c131ec88c3ae64/zope_interface-8.3-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:3853bfb808084e1b4a3a769b00bd8b58a52b0c4a4fc5c23de26d283cd8beb627", size = 212038, upload-time = "2026-04-10T06:22:40.475Z" }, - { url = "https://files.pythonhosted.org/packages/f7/cf/237de1fba4f05686bc344eeb035236bd89890679c8211f129f05b5971ccf/zope_interface-8.3-cp314-cp314-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:33a13acba79ef693fb64ceb6193ece913d39586f184797f133c1bc549da86851", size = 266041, upload-time = "2026-04-10T06:22:42.093Z" }, - { url = "https://files.pythonhosted.org/packages/58/5f/df85b1ff5626d7f05231e69b7efd38bdc2c82ca363495e0bb112aaf655b3/zope_interface-8.3-cp314-cp314-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:e9f7e4b46741a11a9e1fab8b68710f08dec700e9f1b877cdca02480fbebe4846", size = 269094, upload-time = "2026-04-10T06:22:43.832Z" }, - { url = "https://files.pythonhosted.org/packages/5f/10/7ad1ff9c514fe38b176fc1271967c453074eb386a4515bd3b957c485f3a8/zope_interface-8.3-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:8ce49d43366e12aeccd14fcaebb3ef110f50f5795e0d4a95383ea057365cedf2", size = 269413, upload-time = "2026-04-10T06:22:45.573Z" }, - { url = "https://files.pythonhosted.org/packages/38/42/3b0b5edee7801e0dd5c42c2c9bb4ec8bec430a6628462eb1315db76a7954/zope_interface-8.3-cp314-cp314-win_amd64.whl", hash = "sha256:301db4049c79a15a3b29d89795e150daf0e9ae701404b112ad6585ea863f6ef5", size = 215170, upload-time = "2026-04-10T06:22:47.115Z" }, +version = "8.5" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/08/dc/50550cfcbb2ea3cbca5f1d7ed05c8aa840f831a0f2d63aec0a953f7c590e/zope_interface-8.5.tar.gz", hash = "sha256:7a3ba1c5877f0f3e3906b02ddf793abed2becc2948116414ce0e1dd820b68d6d", size = 257957, upload-time = "2026-05-26T06:50:14.574Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b6/43/9cd98bee951d23848de690ba2809f87e3b22c67c370987acc960da15ad37/zope_interface-8.5-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:c0c8aa2bf8f3911ef37b87deb1bbe225a310e6eb6522a16d77f5d8330c4f6fbe", size = 210951, upload-time = "2026-05-26T06:49:00.178Z" }, + { url = "https://files.pythonhosted.org/packages/17/0f/8f1a29966bcf863e3a2121edcafb81c55715de7886bcc9544749cc79e7da/zope_interface-8.5-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:efe234a0fafb4b6b1602e9be9245b97c2bf06d67c07af5a4bc3c0438978b555c", size = 211309, upload-time = "2026-05-26T06:49:02.732Z" }, + { url = "https://files.pythonhosted.org/packages/9f/9f/37e564eaaf85e3abc1ada40a79fa43f2ab45bdb67431b0ec0fe29e4763e2/zope_interface-8.5-cp310-cp310-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:dabeb6fe1228d411994f300811edc6866fff0cdcbc9cef98a78f05ea0da42e37", size = 254881, upload-time = "2026-05-26T06:49:04.303Z" }, + { url = "https://files.pythonhosted.org/packages/06/61/e6501d8ea7a2cac3217e03f404e1f98c1df7191d83cfe86b1895fbba5dac/zope_interface-8.5-cp310-cp310-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:147a9442dcc2b7339ecdb1be2b3cdb098e90462e39425054053ebfb50d99125a", size = 259811, upload-time = "2026-05-26T06:49:06.373Z" }, + { url = "https://files.pythonhosted.org/packages/91/15/bfa25ef480b02af6e9452c478483fec75e87c9e2b60c407fd0b1f6054b9c/zope_interface-8.5-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:a17e681224267880707c9ec9e730ad9a1ad2d65c371256843efba6cf48711b58", size = 260358, upload-time = "2026-05-26T06:49:08.317Z" }, + { url = "https://files.pythonhosted.org/packages/64/51/2b518072fea76242da64451d501c69b7b5ccdef9b57fead584ccf1c180d5/zope_interface-8.5-cp310-cp310-win_amd64.whl", hash = "sha256:d178968a1a611df30549a717d1624cb38ca810347339e3e37b7baa6f6781a170", size = 214822, upload-time = "2026-05-26T06:49:10.441Z" }, + { url = "https://files.pythonhosted.org/packages/ce/f1/83ad110fb847413affe71609bb50e59e1aa082e1236030122227c7c283d3/zope_interface-8.5-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:afc66ccaef2a3c0bef6ca02aad40d29a39276389dad16a8eac36f9f385e4d057", size = 211426, upload-time = "2026-05-26T06:49:12.595Z" }, + { url = "https://files.pythonhosted.org/packages/bb/a7/6b6e0c31ac240cb9fc015ae9ed45ca54be886c18fcf7bfa2377a4d7a8785/zope_interface-8.5-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:c28044972187245d7a309e4699319bfdbd2ffcbf7176d1d4ddf5adffb2dea80f", size = 211850, upload-time = "2026-05-26T06:49:14.474Z" }, + { url = "https://files.pythonhosted.org/packages/37/36/7599ecabcf80ce4fef2e1ef3c5ac0d4696b61f03f724cc44022f4d226af9/zope_interface-8.5-cp311-cp311-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:03bbecc7982af713d7499d4084bc03916413d17ffd45f89009348cc0c1d9e376", size = 260711, upload-time = "2026-05-26T06:49:16.568Z" }, + { url = "https://files.pythonhosted.org/packages/03/3e/1774b0ee46ccbb5498ee3c33ece40315b6ef58bc71957be94bd345340bc1/zope_interface-8.5-cp311-cp311-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:bf917009a4a7457c7290225a019f4a0aa706d96accd2cfdba2418d3bc1fcde2f", size = 265277, upload-time = "2026-05-26T06:49:18.656Z" }, + { url = "https://files.pythonhosted.org/packages/b6/09/e533b2ffabaae4e5d5730d6768a591cf335defe8e37bec2ad905d09be656/zope_interface-8.5-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:31cff25b2aaedb5267e6e77b1e9be6b0ec4f622032de8a069202b8ffacda7dc2", size = 266369, upload-time = "2026-05-26T06:49:20.174Z" }, + { url = "https://files.pythonhosted.org/packages/49/4a/3ebe6a4c122b2d5340db45cbe7e490663d3228b172710ec71060cd5d541e/zope_interface-8.5-cp311-cp311-win_amd64.whl", hash = "sha256:17a3114bbdddb5e75e5784cdf318944636190cbbc72d357ef9fb1a8b0351f955", size = 215161, upload-time = "2026-05-26T06:49:21.799Z" }, + { url = "https://files.pythonhosted.org/packages/d2/59/056ad97af5b16db1975ee98ec7ab03d2ce3f3355efad904ced1dbce0e39f/zope_interface-8.5-cp311-cp311-win_arm64.whl", hash = "sha256:aab6bb5bee10f38ea688b95ba054396b67f613552d2c8378be7fcb2d2fba7646", size = 213481, upload-time = "2026-05-26T06:49:25.085Z" }, + { url = "https://files.pythonhosted.org/packages/97/cc/b84123a948f3162a34623e188922827cd845244fdd043ed20f8d02228caa/zope_interface-8.5-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:8e6ee90c2e6de7c37058d5fa41f123c8b13a312db8d1e0fb5840d7f4bcdff9c9", size = 212165, upload-time = "2026-05-26T06:49:26.566Z" }, + { url = "https://files.pythonhosted.org/packages/4e/78/cbceec44f1b27208a76c1a688c131302685852406a23df5aab68324109cc/zope_interface-8.5-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:c1adc90d3576b3b4c4de4953e6002c37bef28b78d7fa54c1bbfd0c50f022fe7c", size = 212341, upload-time = "2026-05-26T06:49:28.182Z" }, + { url = "https://files.pythonhosted.org/packages/e1/c3/005032195ff3b210c139b7c560ed5c534e844b0907d8e44d2b3d8919305e/zope_interface-8.5-cp312-cp312-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:e6347b8d8d12c5eca6502450a92be30079b7acfade2c4f693efa0deb8871b06e", size = 265296, upload-time = "2026-05-26T06:49:29.741Z" }, + { url = "https://files.pythonhosted.org/packages/c5/66/1036543d6a66bc04c19df3cf650f3ad938a002ab0a443c24e23e8de5e8b9/zope_interface-8.5-cp312-cp312-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:5e970dabea777a24b0b0bbf9dae3ab75ce8b2d8e948edf4875627034b21f3560", size = 270689, upload-time = "2026-05-26T06:49:31.767Z" }, + { url = "https://files.pythonhosted.org/packages/30/4c/8b56259558cace4414e753ca6740396a1f59d4a95ddb55b4658600408670/zope_interface-8.5-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:f0b48ccadaa9839e09ff81e969703cecb3f402c813bfe8b958652e699bea69f5", size = 270280, upload-time = "2026-05-26T06:49:33.489Z" }, + { url = "https://files.pythonhosted.org/packages/f9/ea/649908c83aa8fdb7faf2ddca4d3cf6fb8f2157121267dc56e8f72681e26c/zope_interface-8.5-cp312-cp312-win_amd64.whl", hash = "sha256:e0e311f1277468c08fd59a2b41f71b43d25dff639789d364747acd1705c0df6e", size = 215019, upload-time = "2026-05-26T06:49:35.607Z" }, + { url = "https://files.pythonhosted.org/packages/9f/97/da13037b4c563e4df32eedbc819f8c00b754af494f68211e3dffd48d52da/zope_interface-8.5-cp312-cp312-win_arm64.whl", hash = "sha256:652b73107a04159ec6c020db6c1543d4f1e8f4d069bd2aac88a947820923517b", size = 213569, upload-time = "2026-05-26T06:49:37.317Z" }, + { url = "https://files.pythonhosted.org/packages/f4/8c/4c15755d701f2ec0e80d64a18e1ebaf5be2c584c0ec153fd516f5d13eada/zope_interface-8.5-cp313-cp313-macosx_10_9_x86_64.whl", hash = "sha256:28e80457c134d1fa57a7d758004dece348654e1b1467ac22dcdc20fc1d127c52", size = 212512, upload-time = "2026-05-26T06:49:38.996Z" }, + { url = "https://files.pythonhosted.org/packages/9a/2e/4360c54c465db042cc8fbeeec92abac28b4cedbf6ba63c1f092fd08a190f/zope_interface-8.5-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:09495ce9d559c06b70f2d4855b3e4f48a822a9ddc8be1d30c5b4e5be14ae1ace", size = 212541, upload-time = "2026-05-26T06:49:41.186Z" }, + { url = "https://files.pythonhosted.org/packages/aa/a5/692a2b8d70f78e848793231d5fae5fecbf8d0cccd73430fdc34802a6d3c1/zope_interface-8.5-cp313-cp313-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:7849ad8fa90763cc1087f4dda78ca3a233e950b3e08fac7079297c9cafbbd7bb", size = 265191, upload-time = "2026-05-26T06:49:43.449Z" }, + { url = "https://files.pythonhosted.org/packages/70/8d/454a9cfc7a050c394ab4f11b3371f7897828b7415e096afff724637e65e0/zope_interface-8.5-cp313-cp313-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:5578c9421ca409a1f39f153d6f7803e4cde01da592ec75a9ac5e1b777d18d33b", size = 270626, upload-time = "2026-05-26T06:49:45.425Z" }, + { url = "https://files.pythonhosted.org/packages/51/8c/db8409cfa3575b8e9b4800babd7d49f8228433cd1f0c56814bd0ada49c33/zope_interface-8.5-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:e1bd7d96b4ca5fa311f54c9eac16dce4886b428c1531dbe06067763ccdf123b4", size = 270444, upload-time = "2026-05-26T06:49:47.025Z" }, + { url = "https://files.pythonhosted.org/packages/4a/df/a386940e41469ef615e100a216d8b386521e9e598817147f87932ca203c4/zope_interface-8.5-cp313-cp313-win_amd64.whl", hash = "sha256:0c8123d2a4dfde2a613c7cb772605477724782c20bc2e0ad1d9435376a6a44a3", size = 215021, upload-time = "2026-05-26T06:49:48.478Z" }, + { url = "https://files.pythonhosted.org/packages/89/75/477eb5669b6b2a7a843decd1a075e9b1971a8720017654143a7183abd3d9/zope_interface-8.5-cp313-cp313-win_arm64.whl", hash = "sha256:6d02be14f3173c6c7288bc2fdf530090c01c3cf8764ad46c68024686f364278e", size = 213610, upload-time = "2026-05-26T06:49:50.01Z" }, + { url = "https://files.pythonhosted.org/packages/d4/19/5032e954827fdf02db2d2f49737ac4378bb9cfc2cd95a8f2e2a5ae2ec01a/zope_interface-8.5-cp314-cp314-macosx_10_9_x86_64.whl", hash = "sha256:ffaecf013251a89d0de6feb49a46eba48ad8cbbf8a40aeb6045e459e7bec6784", size = 212597, upload-time = "2026-05-26T06:49:51.63Z" }, + { url = "https://files.pythonhosted.org/packages/f1/53/3ef644012cf8a6a234a2d6134aab5a5c65ac5467c86296865501d4fbc406/zope_interface-8.5-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:126fa9d1c52295ae076d4cf968634f0a1826afa408a20808b57ff72877b8f69f", size = 212626, upload-time = "2026-05-26T06:49:53.236Z" }, + { url = "https://files.pythonhosted.org/packages/32/67/bc8b4f465d388039255003e230c284a175cedf1203c692f23cb7bff64efe/zope_interface-8.5-cp314-cp314-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:3090e3a663d20194756a59a272e0c8508b889341e31d5894223331fe6b4f9b21", size = 266827, upload-time = "2026-05-26T06:49:54.873Z" }, + { url = "https://files.pythonhosted.org/packages/a7/eb/37d05b935ede53d79690fecc8d201440084418e590bcfc05f384451c7593/zope_interface-8.5-cp314-cp314-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:9342fb74e2afefdb081bf1df727d209ea56995c6e13f5a0540e6d7aff4beafb8", size = 270139, upload-time = "2026-05-26T06:49:57.116Z" }, + { url = "https://files.pythonhosted.org/packages/8b/0b/fd0c54579e2ce8dc6cf1a757903f3374bc6fbda929a46af9e0f53cb0e5f0/zope_interface-8.5-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:6c54725d818f1b57a7efb8b16528326e1f3c257b602b32393fd255c45af8799d", size = 270338, upload-time = "2026-05-26T06:49:58.698Z" }, + { url = "https://files.pythonhosted.org/packages/c1/1d/c420dcd777bb761067ea92879ac766694a5ca78608185f1aecea64cbfc11/zope_interface-8.5-cp314-cp314-win_amd64.whl", hash = "sha256:29d74febbae1afeb6834c4ccbf42e242a673c860060f09e53142825270456140", size = 215789, upload-time = "2026-05-26T06:50:00.405Z" }, + { url = "https://files.pythonhosted.org/packages/62/94/50b5eb8f94e527edceac14f9955e58917424ea79bb572ddc18548561cbc2/zope_interface-8.5-cp314-cp314-win_arm64.whl", hash = "sha256:633c8c49396f38df030340797c533e9fe460d1b5d1e42d88e55e938e525f548c", size = 213757, upload-time = "2026-05-26T06:50:01.973Z" }, + { url = "https://files.pythonhosted.org/packages/17/6f/5d5f32c4dfcdb16ce2ec5363da686840f13c13e1a1214cb70b49e1cd6d9f/zope_interface-8.5-cp314-cp314t-macosx_10_9_x86_64.whl", hash = "sha256:133999820fdbae513c36c03d6f29ef87317aaa3edef39112222b155083664714", size = 213591, upload-time = "2026-05-26T06:50:03.529Z" }, + { url = "https://files.pythonhosted.org/packages/f3/55/de0c3459ff717fce3342f9a29464c281fdeb0d36c3171ee88d119d5f0650/zope_interface-8.5-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:8bd75c96966e573232f0599deaff717564828031c7f05563ccc1ac35c5ee0304", size = 213733, upload-time = "2026-05-26T06:50:05.101Z" }, + { url = "https://files.pythonhosted.org/packages/c2/95/d97430abd5ae9677e8b9295b58720c0064a5b557dbb6b8bf5928484cf0d8/zope_interface-8.5-cp314-cp314t-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:14b0e9799351d4c34fe99afd67f0cdd76e55ba15c66a98699d5fc22ea8241e08", size = 294905, upload-time = "2026-05-26T06:50:07.384Z" }, + { url = "https://files.pythonhosted.org/packages/41/ec/a0f8f3dad6e74992f4654bdd94802be0929eabca7b871cac3b6fbb5e961b/zope_interface-8.5-cp314-cp314t-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:0cd6a732ac84b94eb1ef9222a117347a27efd294ee16810ffdf7ecd307677ed5", size = 300885, upload-time = "2026-05-26T06:50:08.997Z" }, + { url = "https://files.pythonhosted.org/packages/0f/da/6881b48803a0ee8d23eb5efa30fce3ed218a2bd9de5758ce489d224fee81/zope_interface-8.5-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:798b7c87d0e59a7d5d086d642208d0d8700ff0d55c4029134b3c479c3bfb110f", size = 304672, upload-time = "2026-05-26T06:50:10.563Z" }, + { url = "https://files.pythonhosted.org/packages/2e/0e/b4c01320859ff1d585438bc231fd60bd258d096359bccf6654fecdf0cffb/zope_interface-8.5-cp314-cp314t-win_amd64.whl", hash = "sha256:0fc3a9d45f114d27eaa1e53beeb144533689edca8a9f66505b1e8e8b3f075e42", size = 217241, upload-time = "2026-05-26T06:50:12.171Z" }, ] [[package]] From 68bc8236cae709b6bf4f0444ac09e31dad8b7eb0 Mon Sep 17 00:00:00 2001 From: Tim Conley Date: Wed, 1 Jul 2026 11:24:22 -0700 Subject: [PATCH 151/226] Prepare release 1.30.0 (#1630) --- CHANGELOG.md | 20 ++++++++++++++------ pyproject.toml | 2 +- scripts/prepare_release.py | 4 ++-- temporalio/service.py | 2 +- tests/test_prepare_release.py | 7 +++++++ uv.lock | 4 ++-- 6 files changed, 27 insertions(+), 12 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 32527c303..1a1a92a95 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,6 +20,20 @@ to include examples, links to docs, or any other relevant information. ### Added +### Changed + +### Deprecated + +### Breaking Changes + +### Fixed + +### Security + +## [1.30.0] - 2026-07-01 + +### Added + - Nexus operation link propagation for signals. When a Nexus operation handler signals a workflow (including signal-with-start), the inbound Nexus request links are now forwarded onto the signaled workflow so its history events link back to the caller, and the link the server returns for the @@ -36,8 +50,6 @@ to include examples, links to docs, or any other relevant information. with the selected optional dependencies. - Standalone Nexus operation links are now forwarded on start workflow and signal requests. -### Deprecated - ### Breaking Changes - AWS Lambda worker `configure` parameter has been changed to be invoked @@ -45,10 +57,6 @@ to include examples, links to docs, or any other relevant information. any shared, heavy-weight operations are performed outside of the callback before `run_worker` is invoked. -### Fixed - -### Security - ## [1.29.0] - 2026-06-17 ### Added diff --git a/pyproject.toml b/pyproject.toml index 6b1e9b736..99aea21bf 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "temporalio" -version = "1.29.0" +version = "1.30.0" description = "Temporal.io Python SDK" authors = [{ name = "Temporal Technologies Inc", email = "sdk@temporal.io" }] requires-python = ">=3.10" diff --git a/scripts/prepare_release.py b/scripts/prepare_release.py index 68f2ba39f..22305aa8a 100644 --- a/scripts/prepare_release.py +++ b/scripts/prepare_release.py @@ -78,7 +78,7 @@ def finalize_changelog_release( def replace_project_version(text: str, version: str) -> str: return _replace_once( - r'(?m)^version = "[^"]+"\s*$', + r'(?m)^version = "[^"]+"[^\S\r\n]*$', f'version = "{validate_version(version)}"', text, description="project version", @@ -87,7 +87,7 @@ def replace_project_version(text: str, version: str) -> str: def replace_service_version(text: str, version: str) -> str: return _replace_once( - r'(?m)^__version__ = "[^"]+"\s*$', + r'(?m)^__version__ = "[^"]+"[^\S\r\n]*$', f'__version__ = "{validate_version(version)}"', text, description="service version", diff --git a/temporalio/service.py b/temporalio/service.py index 2d3829c08..d4cb79720 100644 --- a/temporalio/service.py +++ b/temporalio/service.py @@ -24,7 +24,7 @@ import temporalio.runtime from temporalio.bridge.client import RPCError as BridgeRPCError -__version__ = "1.29.0" +__version__ = "1.30.0" ServiceRequest = TypeVar("ServiceRequest", bound=google.protobuf.message.Message) ServiceResponse = TypeVar("ServiceResponse", bound=google.protobuf.message.Message) diff --git a/tests/test_prepare_release.py b/tests/test_prepare_release.py index 07bdbd4a5..b971d499a 100644 --- a/tests/test_prepare_release.py +++ b/tests/test_prepare_release.py @@ -73,3 +73,10 @@ def test_replace_versions() -> None: replace_service_version('__version__ = "1.29.0"\n', "1.30.0") == '__version__ = "1.30.0"' ) + assert ( + replace_service_version( + '__version__ = "1.29.0"\n\nServiceRequest = TypeVar("ServiceRequest")\n', + "1.30.0", + ) + == '__version__ = "1.30.0"\n\nServiceRequest = TypeVar("ServiceRequest")' + ) diff --git a/uv.lock b/uv.lock index 5df24adfa..a591392ad 100644 --- a/uv.lock +++ b/uv.lock @@ -9,7 +9,7 @@ resolution-markers = [ ] [options] -exclude-newer = "2026-06-16T15:22:43.641437Z" +exclude-newer = "2026-06-17T16:16:53.404973Z" exclude-newer-span = "P2W" [options.exclude-newer-package] @@ -5633,7 +5633,7 @@ wheels = [ [[package]] name = "temporalio" -version = "1.29.0" +version = "1.30.0" source = { virtual = "." } dependencies = [ { name = "nexus-rpc" }, From b5777e98595a1fe359a8b4bf49368c68e362a613 Mon Sep 17 00:00:00 2001 From: Tim Conley Date: Thu, 2 Jul 2026 12:38:15 -0700 Subject: [PATCH 152/226] Update sdk-core submodule (#1632) * Update sdk-core submodule * Update Cargo.lock for sdk-core bump --- temporalio/bridge/Cargo.lock | 51 +++++++++++++++++++----------------- temporalio/bridge/sdk-core | 2 +- 2 files changed, 28 insertions(+), 25 deletions(-) diff --git a/temporalio/bridge/Cargo.lock b/temporalio/bridge/Cargo.lock index b71dcd615..1d45b94de 100644 --- a/temporalio/bridge/Cargo.lock +++ b/temporalio/bridge/Cargo.lock @@ -31,9 +31,9 @@ checksum = "940b3a0ca603d1eade50a4846a2afffd5ef57a9feac2c0e2ec2e14f9ead76000" [[package]] name = "anyhow" -version = "1.0.102" +version = "1.0.103" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f202df86484c868dbad7eaa557ef785d5c66295e41b460ef922eca0723b842c" +checksum = "2a4385e2e34eb35d6b3efe798b9eb88096925d87726c0798709bf56d9ed84af3" [[package]] name = "async-trait" @@ -60,9 +60,9 @@ checksum = "f2032f911046de80f0a198e0901378627c33f59ea0ac00e363d481118bd70a53" [[package]] name = "aws-lc-rs" -version = "1.17.0" +version = "1.17.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ec2f1fc3ec205783a5da9a7e6c1509cc69dedf09a1949e412c1e18469326d00" +checksum = "4342d8937fc7e5dd9b1c60292261c0670c882a2cd1719cfc11b1af41731e32ad" dependencies = [ "aws-lc-sys", "zeroize", @@ -70,14 +70,15 @@ dependencies = [ [[package]] name = "aws-lc-sys" -version = "0.41.0" +version = "0.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a2f9779ce85b93ab6170dd940ad0169b5766ff848247aff13bb788b832fe3f4" +checksum = "6d9ceb1da931507a12f4fccea479dccd00da1943e1b4ae72d8e502d707361444" dependencies = [ "cc", "cmake", "dunce", "fs_extra", + "pkg-config", ] [[package]] @@ -389,7 +390,7 @@ dependencies = [ "libc", "option-ext", "redox_users", - "windows-sys 0.60.2", + "windows-sys 0.61.2", ] [[package]] @@ -483,7 +484,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" dependencies = [ "libc", - "windows-sys 0.52.0", + "windows-sys 0.61.2", ] [[package]] @@ -1126,9 +1127,9 @@ checksum = "68ab91017fe16c622486840e4c83c9a37afeff978bd239b5293d61ece587de66" [[package]] name = "libredox" -version = "0.1.17" +version = "0.1.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f02ab6bace2054fb888a3c16f990117b579d14a3088e472d63c6011fa185c9d3" +checksum = "c943259e342f1e06ff2da7a83eabdfe7f92ce10262688dbf1895ff0b3e6e4652" dependencies = [ "libc", ] @@ -1270,7 +1271,7 @@ version = "0.50.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5" dependencies = [ - "windows-sys 0.60.2", + "windows-sys 0.61.2", ] [[package]] @@ -1892,9 +1893,9 @@ dependencies = [ [[package]] name = "rand" -version = "0.10.1" +version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2e8e8bcc7961af1fdac401278c6a831614941f6164ee3bf4ce61b7edb162207" +checksum = "c7f5fa3a058cd35567ef9bfa5e75732bee0f9e4c55fa90477bef2dfcdbc4be80" dependencies = [ "chacha20", "getrandom 0.4.3", @@ -2118,7 +2119,7 @@ dependencies = [ "errno", "libc", "linux-raw-sys", - "windows-sys 0.52.0", + "windows-sys 0.61.2", ] [[package]] @@ -2151,9 +2152,9 @@ dependencies = [ [[package]] name = "rustls-pki-types" -version = "1.14.1" +version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30a7197ae7eb376e574fe940d068c30fe0462554a3ddbe4eca7838e049c937a9" +checksum = "764899a24af3980067ee14bc143654f297b22eaebfe3c7b6b211920a5a59b046" dependencies = [ "web-time", "zeroize", @@ -2177,7 +2178,7 @@ dependencies = [ "security-framework", "security-framework-sys", "webpki-root-certs", - "windows-sys 0.52.0", + "windows-sys 0.61.2", ] [[package]] @@ -2408,7 +2409,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "52d1cfed4120b4d927bf7c0f86d2087a4a7d6027c906d9f9d525a80573b9be51" dependencies = [ "libc", - "windows-sys 0.60.2", + "windows-sys 0.61.2", ] [[package]] @@ -2501,7 +2502,7 @@ dependencies = [ "getrandom 0.4.3", "once_cell", "rustix", - "windows-sys 0.52.0", + "windows-sys 0.61.2", ] [[package]] @@ -2544,7 +2545,7 @@ dependencies = [ "hyper", "hyper-util", "parking_lot", - "rand 0.10.1", + "rand 0.10.2", "temporalio-common", "thiserror", "tokio", @@ -2603,12 +2604,14 @@ dependencies = [ "anyhow", "async-trait", "bon", + "chrono", "crc32fast", "derive_more", "erased-serde", "futures", "parking_lot", "prost", + "prost-wkt-types", "serde", "serde_json", "temporalio-protos", @@ -2675,7 +2678,7 @@ dependencies = [ "pin-project", "prost", "prost-wkt-types", - "rand 0.10.1", + "rand 0.10.2", "reqwest 0.13.4", "serde", "serde_json", @@ -3302,7 +3305,7 @@ version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" dependencies = [ - "windows-sys 0.52.0", + "windows-sys 0.61.2", ] [[package]] @@ -3726,9 +3729,9 @@ dependencies = [ [[package]] name = "zlib-rs" -version = "0.6.4" +version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "977347db8caa080403f6b6b7c1cda9479a8e869316f7e13a59b19076a40f94e3" +checksum = "5431d5661c32445236631278f27946e444ddafe4684cac70b185272d4f9c52d5" [[package]] name = "zmij" diff --git a/temporalio/bridge/sdk-core b/temporalio/bridge/sdk-core index b9e20dad5..9f83b7e30 160000 --- a/temporalio/bridge/sdk-core +++ b/temporalio/bridge/sdk-core @@ -1 +1 @@ -Subproject commit b9e20dad51763ca6a7e4c8b2ae7f54e1623dea18 +Subproject commit 9f83b7e307dc032b31ff3bd3811ef3438106f77a From 776998dfa2cabb836ee088178e1f841132ff9111 Mon Sep 17 00:00:00 2001 From: Stefan Wang <1fannnw@gmail.com> Date: Mon, 6 Jul 2026 10:10:34 -0700 Subject: [PATCH 153/226] Do not mutate caller's extra dict in activity LoggerAdapter (#1513) The activity LoggerAdapter mutated the caller-provided ``extra`` mapping in place when injecting ``temporal_activity`` and ``activity_info``. If the caller reused the dict across log calls (or held a reference to it elsewhere), Temporal context would leak back into their state. Copy the caller's extra into a fresh dict before adding our keys. This matches what the workflow LoggerAdapter already does via ``_build_log_context``. Fixes #503 Signed-off-by: 1fanwang <1fannnw@gmail.com> Co-authored-by: tconley1428 --- temporalio/activity.py | 17 +++++++------ tests/testing/test_activity.py | 44 ++++++++++++++++++++++++++++++++++ 2 files changed, 52 insertions(+), 9 deletions(-) diff --git a/temporalio/activity.py b/temporalio/activity.py index 417195d59..4e632701e 100644 --- a/temporalio/activity.py +++ b/temporalio/activity.py @@ -513,15 +513,14 @@ def process( if context: if self.activity_info_on_message: msg = f"{msg} ({context.logger_details})" - if self.activity_info_on_extra: - # Extra can be absent or None, this handles both - extra = kwargs.get("extra", None) or {} - extra["temporal_activity"] = context.logger_details - kwargs["extra"] = extra - if self.full_activity_info_on_extra: - # Extra can be absent or None, this handles both - extra = kwargs.get("extra", None) or {} - extra["activity_info"] = context.info() + if self.activity_info_on_extra or self.full_activity_info_on_extra: + # Copy any caller-provided extra rather than mutating it in + # place (see https://github.com/temporalio/sdk-python/issues/503). + extra = dict(kwargs.get("extra") or {}) + if self.activity_info_on_extra: + extra["temporal_activity"] = context.logger_details + if self.full_activity_info_on_extra: + extra["activity_info"] = context.info() kwargs["extra"] = extra return (msg, kwargs) diff --git a/tests/testing/test_activity.py b/tests/testing/test_activity.py index 2acf93639..71ba7f590 100644 --- a/tests/testing/test_activity.py +++ b/tests/testing/test_activity.py @@ -167,3 +167,47 @@ def my_activity() -> None: env = ActivityEnvironment(client=Mock(spec=Client)) env.run(my_activity) assert saw_error + + +async def test_activity_logger_does_not_mutate_caller_extra(): + """Regression test for https://github.com/temporalio/sdk-python/issues/503. + + The activity LoggerAdapter must not mutate the ``extra`` dict provided by + the caller; it should merge its temporal context into a fresh dict. + """ + import logging + import logging.handlers + import queue + + handler = logging.handlers.QueueHandler(queue.Queue()) + activity.logger.base_logger.addHandler(handler) + previous_level = activity.logger.base_logger.level + activity.logger.base_logger.setLevel(logging.INFO) + previous_full = activity.logger.full_activity_info_on_extra + activity.logger.full_activity_info_on_extra = True + + try: + + def log_with_extra() -> dict: + caller_extra = {"request_id": "req-1"} + activity.logger.info("hi", extra=caller_extra) + return caller_extra + + env = ActivityEnvironment() + caller_extra = env.run(log_with_extra) + finally: + activity.logger.base_logger.removeHandler(handler) + activity.logger.base_logger.setLevel(previous_level) + activity.logger.full_activity_info_on_extra = previous_full + + # The caller's dict must be untouched. + assert caller_extra == {"request_id": "req-1"} + + # But the emitted record should still carry the temporal-injected fields + # alongside the caller-provided one. + records: list[logging.LogRecord] = list(handler.queue.queue) # type: ignore[attr-defined] + assert records, "expected one log record" + record = records[-1] + assert record.__dict__["request_id"] == "req-1" + assert record.__dict__["temporal_activity"]["activity_type"] == "unknown" + assert "activity_info" in record.__dict__ From aec285a42ab0f85e598f9016952327f5413057cb Mon Sep 17 00:00:00 2001 From: Gregory Michael Travis Date: Tue, 7 Jul 2026 11:24:04 -0400 Subject: [PATCH 154/226] Update sdk-core to incorporate time-skipping api changes (#1633) * Bump to 467e871a * gen dem protos --------- Co-authored-by: Thomas Hardy --- temporalio/api/command/v1/message_pb2.py | 85 +- temporalio/api/command/v1/message_pb2.pyi | 15 + temporalio/api/common/v1/__init__.py | 4 + temporalio/api/common/v1/message_pb2.py | 173 +-- temporalio/api/common/v1/message_pb2.pyi | 113 ++ temporalio/api/deployment/v1/__init__.py | 2 + temporalio/api/deployment/v1/message_pb2.py | 59 +- temporalio/api/deployment/v1/message_pb2.pyi | 74 ++ temporalio/api/history/v1/message_pb2.py | 269 ++-- temporalio/api/history/v1/message_pb2.pyi | 95 +- temporalio/api/namespace/v1/message_pb2.py | 38 +- temporalio/api/namespace/v1/message_pb2.pyi | 6 + temporalio/api/sdk/v1/__init__.py | 2 + .../api/sdk/v1/event_group_marker_pb2.py | 84 ++ .../api/sdk/v1/event_group_marker_pb2.pyi | 159 +++ temporalio/api/workflow/v1/__init__.py | 2 - temporalio/api/workflow/v1/message_pb2.py | 69 +- temporalio/api/workflow/v1/message_pb2.pyi | 165 +-- temporalio/api/workflowservice/v1/__init__.py | 4 + .../v1/request_response_pb2.py | 1088 +++++++++-------- .../v1/request_response_pb2.pyi | 78 +- .../api/workflowservice/v1/service_pb2.py | 8 +- .../workflowservice/v1/service_pb2_grpc.py | 45 + .../workflowservice/v1/service_pb2_grpc.pyi | 12 + temporalio/bridge/sdk-core | 2 +- temporalio/bridge/services_generated.py | 18 + temporalio/bridge/src/client_rpc_generated.rs | 9 + .../testmodules/proto/proto_message_pb2.py | 40 +- .../testmodules/proto/proto_message_pb2.pyi | 10 +- 29 files changed, 1737 insertions(+), 991 deletions(-) create mode 100644 temporalio/api/sdk/v1/event_group_marker_pb2.py create mode 100644 temporalio/api/sdk/v1/event_group_marker_pb2.pyi diff --git a/temporalio/api/command/v1/message_pb2.py b/temporalio/api/command/v1/message_pb2.py index fe94363f5..f1a749b83 100644 --- a/temporalio/api/command/v1/message_pb2.py +++ b/temporalio/api/command/v1/message_pb2.py @@ -28,6 +28,9 @@ from temporalio.api.failure.v1 import ( message_pb2 as temporal_dot_api_dot_failure_dot_v1_dot_message__pb2, ) +from temporalio.api.sdk.v1 import ( + event_group_marker_pb2 as temporal_dot_api_dot_sdk_dot_v1_dot_event__group__marker__pb2, +) from temporalio.api.sdk.v1 import ( user_metadata_pb2 as temporal_dot_api_dot_sdk_dot_v1_dot_user__metadata__pb2, ) @@ -36,7 +39,7 @@ ) DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile( - b'\n%temporal/api/command/v1/message.proto\x12\x17temporal.api.command.v1\x1a\x1egoogle/protobuf/duration.proto\x1a$temporal/api/enums/v1/workflow.proto\x1a(temporal/api/enums/v1/command_type.proto\x1a$temporal/api/common/v1/message.proto\x1a%temporal/api/failure/v1/message.proto\x1a\'temporal/api/taskqueue/v1/message.proto\x1a\'temporal/api/sdk/v1/user_metadata.proto"\xb6\x05\n%ScheduleActivityTaskCommandAttributes\x12\x13\n\x0b\x61\x63tivity_id\x18\x01 \x01(\t\x12;\n\ractivity_type\x18\x02 \x01(\x0b\x32$.temporal.api.common.v1.ActivityType\x12\x38\n\ntask_queue\x18\x04 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12.\n\x06header\x18\x05 \x01(\x0b\x32\x1e.temporal.api.common.v1.Header\x12/\n\x05input\x18\x06 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12<\n\x19schedule_to_close_timeout\x18\x07 \x01(\x0b\x32\x19.google.protobuf.Duration\x12<\n\x19schedule_to_start_timeout\x18\x08 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x39\n\x16start_to_close_timeout\x18\t \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x34\n\x11heartbeat_timeout\x18\n \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x39\n\x0cretry_policy\x18\x0b \x01(\x0b\x32#.temporal.api.common.v1.RetryPolicy\x12\x1f\n\x17request_eager_execution\x18\x0c \x01(\x08\x12\x1d\n\x15use_workflow_build_id\x18\r \x01(\x08\x12\x32\n\x08priority\x18\x0e \x01(\x0b\x32 .temporal.api.common.v1.PriorityJ\x04\x08\x03\x10\x04"H\n*RequestCancelActivityTaskCommandAttributes\x12\x1a\n\x12scheduled_event_id\x18\x01 \x01(\x03"i\n\x1bStartTimerCommandAttributes\x12\x10\n\x08timer_id\x18\x01 \x01(\t\x12\x38\n\x15start_to_fire_timeout\x18\x02 \x01(\x0b\x32\x19.google.protobuf.Duration"^\n*CompleteWorkflowExecutionCommandAttributes\x12\x30\n\x06result\x18\x01 \x01(\x0b\x32 .temporal.api.common.v1.Payloads"[\n&FailWorkflowExecutionCommandAttributes\x12\x31\n\x07\x66\x61ilure\x18\x01 \x01(\x0b\x32 .temporal.api.failure.v1.Failure"0\n\x1c\x43\x61ncelTimerCommandAttributes\x12\x10\n\x08timer_id\x18\x01 \x01(\t"]\n(CancelWorkflowExecutionCommandAttributes\x12\x31\n\x07\x64\x65tails\x18\x01 \x01(\x0b\x32 .temporal.api.common.v1.Payloads"\xb7\x01\n7RequestCancelExternalWorkflowExecutionCommandAttributes\x12\x15\n\tnamespace\x18\x01 \x01(\tB\x02\x18\x01\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x12\x13\n\x07\x63ontrol\x18\x04 \x01(\tB\x02\x18\x01\x12\x1b\n\x13\x63hild_workflow_only\x18\x05 \x01(\x08\x12\x0e\n\x06reason\x18\x06 \x01(\t"\xaf\x02\n0SignalExternalWorkflowExecutionCommandAttributes\x12\x15\n\tnamespace\x18\x01 \x01(\tB\x02\x18\x01\x12<\n\texecution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x13\n\x0bsignal_name\x18\x03 \x01(\t\x12/\n\x05input\x18\x04 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x13\n\x07\x63ontrol\x18\x05 \x01(\tB\x02\x18\x01\x12\x1b\n\x13\x63hild_workflow_only\x18\x06 \x01(\x08\x12.\n\x06header\x18\x07 \x01(\x0b\x32\x1e.temporal.api.common.v1.Header"v\n/UpsertWorkflowSearchAttributesCommandAttributes\x12\x43\n\x11search_attributes\x18\x01 \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes"`\n)ModifyWorkflowPropertiesCommandAttributes\x12\x33\n\rupserted_memo\x18\x01 \x01(\x0b\x32\x1c.temporal.api.common.v1.Memo"\xbf\x02\n\x1dRecordMarkerCommandAttributes\x12\x13\n\x0bmarker_name\x18\x01 \x01(\t\x12T\n\x07\x64\x65tails\x18\x02 \x03(\x0b\x32\x43.temporal.api.command.v1.RecordMarkerCommandAttributes.DetailsEntry\x12.\n\x06header\x18\x03 \x01(\x0b\x32\x1e.temporal.api.common.v1.Header\x12\x31\n\x07\x66\x61ilure\x18\x04 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x1aP\n\x0c\x44\x65tailsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12/\n\x05value\x18\x02 \x01(\x0b\x32 .temporal.api.common.v1.Payloads:\x02\x38\x01"\xac\x07\n/ContinueAsNewWorkflowExecutionCommandAttributes\x12;\n\rworkflow_type\x18\x01 \x01(\x0b\x32$.temporal.api.common.v1.WorkflowType\x12\x38\n\ntask_queue\x18\x02 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12/\n\x05input\x18\x03 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x37\n\x14workflow_run_timeout\x18\x04 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x38\n\x15workflow_task_timeout\x18\x05 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x39\n\x16\x62\x61\x63koff_start_interval\x18\x06 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x39\n\x0cretry_policy\x18\x07 \x01(\x0b\x32#.temporal.api.common.v1.RetryPolicy\x12@\n\tinitiator\x18\x08 \x01(\x0e\x32-.temporal.api.enums.v1.ContinueAsNewInitiator\x12\x31\n\x07\x66\x61ilure\x18\t \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12@\n\x16last_completion_result\x18\n \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x15\n\rcron_schedule\x18\x0b \x01(\t\x12.\n\x06header\x18\x0c \x01(\x0b\x32\x1e.temporal.api.common.v1.Header\x12*\n\x04memo\x18\r \x01(\x0b\x32\x1c.temporal.api.common.v1.Memo\x12\x43\n\x11search_attributes\x18\x0e \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes\x12\x1c\n\x10inherit_build_id\x18\x0f \x01(\x08\x42\x02\x18\x01\x12[\n\x1binitial_versioning_behavior\x18\x10 \x01(\x0e\x32\x36.temporal.api.enums.v1.ContinueAsNewVersioningBehavior"\xa1\x07\n,StartChildWorkflowExecutionCommandAttributes\x12\x15\n\tnamespace\x18\x01 \x01(\tB\x02\x18\x01\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12;\n\rworkflow_type\x18\x03 \x01(\x0b\x32$.temporal.api.common.v1.WorkflowType\x12\x38\n\ntask_queue\x18\x04 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12/\n\x05input\x18\x05 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12=\n\x1aworkflow_execution_timeout\x18\x06 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x37\n\x14workflow_run_timeout\x18\x07 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x38\n\x15workflow_task_timeout\x18\x08 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x45\n\x13parent_close_policy\x18\t \x01(\x0e\x32(.temporal.api.enums.v1.ParentClosePolicy\x12\x0f\n\x07\x63ontrol\x18\n \x01(\t\x12N\n\x18workflow_id_reuse_policy\x18\x0b \x01(\x0e\x32,.temporal.api.enums.v1.WorkflowIdReusePolicy\x12\x39\n\x0cretry_policy\x18\x0c \x01(\x0b\x32#.temporal.api.common.v1.RetryPolicy\x12\x15\n\rcron_schedule\x18\r \x01(\t\x12.\n\x06header\x18\x0e \x01(\x0b\x32\x1e.temporal.api.common.v1.Header\x12*\n\x04memo\x18\x0f \x01(\x0b\x32\x1c.temporal.api.common.v1.Memo\x12\x43\n\x11search_attributes\x18\x10 \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes\x12\x1c\n\x10inherit_build_id\x18\x11 \x01(\x08\x42\x02\x18\x01\x12\x32\n\x08priority\x18\x12 \x01(\x0b\x32 .temporal.api.common.v1.Priority"6\n ProtocolMessageCommandAttributes\x12\x12\n\nmessage_id\x18\x01 \x01(\t"\xe3\x03\n\'ScheduleNexusOperationCommandAttributes\x12\x10\n\x08\x65ndpoint\x18\x01 \x01(\t\x12\x0f\n\x07service\x18\x02 \x01(\t\x12\x11\n\toperation\x18\x03 \x01(\t\x12.\n\x05input\x18\x04 \x01(\x0b\x32\x1f.temporal.api.common.v1.Payload\x12<\n\x19schedule_to_close_timeout\x18\x05 \x01(\x0b\x32\x19.google.protobuf.Duration\x12g\n\x0cnexus_header\x18\x06 \x03(\x0b\x32Q.temporal.api.command.v1.ScheduleNexusOperationCommandAttributes.NexusHeaderEntry\x12<\n\x19schedule_to_start_timeout\x18\x07 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x39\n\x16start_to_close_timeout\x18\x08 \x01(\x0b\x32\x19.google.protobuf.Duration\x1a\x32\n\x10NexusHeaderEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01"J\n,RequestCancelNexusOperationCommandAttributes\x12\x1a\n\x12scheduled_event_id\x18\x01 \x01(\x03"\xc2\x11\n\x07\x43ommand\x12\x38\n\x0c\x63ommand_type\x18\x01 \x01(\x0e\x32".temporal.api.enums.v1.CommandType\x12\x39\n\ruser_metadata\x18\xad\x02 \x01(\x0b\x32!.temporal.api.sdk.v1.UserMetadata\x12s\n)schedule_activity_task_command_attributes\x18\x02 \x01(\x0b\x32>.temporal.api.command.v1.ScheduleActivityTaskCommandAttributesH\x00\x12^\n\x1estart_timer_command_attributes\x18\x03 \x01(\x0b\x32\x34.temporal.api.command.v1.StartTimerCommandAttributesH\x00\x12}\n.complete_workflow_execution_command_attributes\x18\x04 \x01(\x0b\x32\x43.temporal.api.command.v1.CompleteWorkflowExecutionCommandAttributesH\x00\x12u\n*fail_workflow_execution_command_attributes\x18\x05 \x01(\x0b\x32?.temporal.api.command.v1.FailWorkflowExecutionCommandAttributesH\x00\x12~\n/request_cancel_activity_task_command_attributes\x18\x06 \x01(\x0b\x32\x43.temporal.api.command.v1.RequestCancelActivityTaskCommandAttributesH\x00\x12`\n\x1f\x63\x61ncel_timer_command_attributes\x18\x07 \x01(\x0b\x32\x35.temporal.api.command.v1.CancelTimerCommandAttributesH\x00\x12y\n,cancel_workflow_execution_command_attributes\x18\x08 \x01(\x0b\x32\x41.temporal.api.command.v1.CancelWorkflowExecutionCommandAttributesH\x00\x12\x99\x01\n=request_cancel_external_workflow_execution_command_attributes\x18\t \x01(\x0b\x32P.temporal.api.command.v1.RequestCancelExternalWorkflowExecutionCommandAttributesH\x00\x12\x62\n record_marker_command_attributes\x18\n \x01(\x0b\x32\x36.temporal.api.command.v1.RecordMarkerCommandAttributesH\x00\x12\x89\x01\n5continue_as_new_workflow_execution_command_attributes\x18\x0b \x01(\x0b\x32H.temporal.api.command.v1.ContinueAsNewWorkflowExecutionCommandAttributesH\x00\x12\x82\x01\n1start_child_workflow_execution_command_attributes\x18\x0c \x01(\x0b\x32\x45.temporal.api.command.v1.StartChildWorkflowExecutionCommandAttributesH\x00\x12\x8a\x01\n5signal_external_workflow_execution_command_attributes\x18\r \x01(\x0b\x32I.temporal.api.command.v1.SignalExternalWorkflowExecutionCommandAttributesH\x00\x12\x88\x01\n4upsert_workflow_search_attributes_command_attributes\x18\x0e \x01(\x0b\x32H.temporal.api.command.v1.UpsertWorkflowSearchAttributesCommandAttributesH\x00\x12h\n#protocol_message_command_attributes\x18\x0f \x01(\x0b\x32\x39.temporal.api.command.v1.ProtocolMessageCommandAttributesH\x00\x12{\n-modify_workflow_properties_command_attributes\x18\x11 \x01(\x0b\x32\x42.temporal.api.command.v1.ModifyWorkflowPropertiesCommandAttributesH\x00\x12w\n+schedule_nexus_operation_command_attributes\x18\x12 \x01(\x0b\x32@.temporal.api.command.v1.ScheduleNexusOperationCommandAttributesH\x00\x12\x82\x01\n1request_cancel_nexus_operation_command_attributes\x18\x13 \x01(\x0b\x32\x45.temporal.api.command.v1.RequestCancelNexusOperationCommandAttributesH\x00\x42\x0c\n\nattributesB\x8e\x01\n\x1aio.temporal.api.command.v1B\x0cMessageProtoP\x01Z%go.temporal.io/api/command/v1;command\xaa\x02\x19Temporalio.Api.Command.V1\xea\x02\x1cTemporalio::Api::Command::V1b\x06proto3' + b'\n%temporal/api/command/v1/message.proto\x12\x17temporal.api.command.v1\x1a\x1egoogle/protobuf/duration.proto\x1a$temporal/api/enums/v1/workflow.proto\x1a(temporal/api/enums/v1/command_type.proto\x1a$temporal/api/common/v1/message.proto\x1a%temporal/api/failure/v1/message.proto\x1a\'temporal/api/taskqueue/v1/message.proto\x1a\'temporal/api/sdk/v1/user_metadata.proto\x1a,temporal/api/sdk/v1/event_group_marker.proto"\xb6\x05\n%ScheduleActivityTaskCommandAttributes\x12\x13\n\x0b\x61\x63tivity_id\x18\x01 \x01(\t\x12;\n\ractivity_type\x18\x02 \x01(\x0b\x32$.temporal.api.common.v1.ActivityType\x12\x38\n\ntask_queue\x18\x04 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12.\n\x06header\x18\x05 \x01(\x0b\x32\x1e.temporal.api.common.v1.Header\x12/\n\x05input\x18\x06 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12<\n\x19schedule_to_close_timeout\x18\x07 \x01(\x0b\x32\x19.google.protobuf.Duration\x12<\n\x19schedule_to_start_timeout\x18\x08 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x39\n\x16start_to_close_timeout\x18\t \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x34\n\x11heartbeat_timeout\x18\n \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x39\n\x0cretry_policy\x18\x0b \x01(\x0b\x32#.temporal.api.common.v1.RetryPolicy\x12\x1f\n\x17request_eager_execution\x18\x0c \x01(\x08\x12\x1d\n\x15use_workflow_build_id\x18\r \x01(\x08\x12\x32\n\x08priority\x18\x0e \x01(\x0b\x32 .temporal.api.common.v1.PriorityJ\x04\x08\x03\x10\x04"H\n*RequestCancelActivityTaskCommandAttributes\x12\x1a\n\x12scheduled_event_id\x18\x01 \x01(\x03"i\n\x1bStartTimerCommandAttributes\x12\x10\n\x08timer_id\x18\x01 \x01(\t\x12\x38\n\x15start_to_fire_timeout\x18\x02 \x01(\x0b\x32\x19.google.protobuf.Duration"^\n*CompleteWorkflowExecutionCommandAttributes\x12\x30\n\x06result\x18\x01 \x01(\x0b\x32 .temporal.api.common.v1.Payloads"[\n&FailWorkflowExecutionCommandAttributes\x12\x31\n\x07\x66\x61ilure\x18\x01 \x01(\x0b\x32 .temporal.api.failure.v1.Failure"0\n\x1c\x43\x61ncelTimerCommandAttributes\x12\x10\n\x08timer_id\x18\x01 \x01(\t"]\n(CancelWorkflowExecutionCommandAttributes\x12\x31\n\x07\x64\x65tails\x18\x01 \x01(\x0b\x32 .temporal.api.common.v1.Payloads"\xb7\x01\n7RequestCancelExternalWorkflowExecutionCommandAttributes\x12\x15\n\tnamespace\x18\x01 \x01(\tB\x02\x18\x01\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x12\x13\n\x07\x63ontrol\x18\x04 \x01(\tB\x02\x18\x01\x12\x1b\n\x13\x63hild_workflow_only\x18\x05 \x01(\x08\x12\x0e\n\x06reason\x18\x06 \x01(\t"\xaf\x02\n0SignalExternalWorkflowExecutionCommandAttributes\x12\x15\n\tnamespace\x18\x01 \x01(\tB\x02\x18\x01\x12<\n\texecution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x13\n\x0bsignal_name\x18\x03 \x01(\t\x12/\n\x05input\x18\x04 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x13\n\x07\x63ontrol\x18\x05 \x01(\tB\x02\x18\x01\x12\x1b\n\x13\x63hild_workflow_only\x18\x06 \x01(\x08\x12.\n\x06header\x18\x07 \x01(\x0b\x32\x1e.temporal.api.common.v1.Header"v\n/UpsertWorkflowSearchAttributesCommandAttributes\x12\x43\n\x11search_attributes\x18\x01 \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes"`\n)ModifyWorkflowPropertiesCommandAttributes\x12\x33\n\rupserted_memo\x18\x01 \x01(\x0b\x32\x1c.temporal.api.common.v1.Memo"\xbf\x02\n\x1dRecordMarkerCommandAttributes\x12\x13\n\x0bmarker_name\x18\x01 \x01(\t\x12T\n\x07\x64\x65tails\x18\x02 \x03(\x0b\x32\x43.temporal.api.command.v1.RecordMarkerCommandAttributes.DetailsEntry\x12.\n\x06header\x18\x03 \x01(\x0b\x32\x1e.temporal.api.common.v1.Header\x12\x31\n\x07\x66\x61ilure\x18\x04 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x1aP\n\x0c\x44\x65tailsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12/\n\x05value\x18\x02 \x01(\x0b\x32 .temporal.api.common.v1.Payloads:\x02\x38\x01"\xac\x07\n/ContinueAsNewWorkflowExecutionCommandAttributes\x12;\n\rworkflow_type\x18\x01 \x01(\x0b\x32$.temporal.api.common.v1.WorkflowType\x12\x38\n\ntask_queue\x18\x02 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12/\n\x05input\x18\x03 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x37\n\x14workflow_run_timeout\x18\x04 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x38\n\x15workflow_task_timeout\x18\x05 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x39\n\x16\x62\x61\x63koff_start_interval\x18\x06 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x39\n\x0cretry_policy\x18\x07 \x01(\x0b\x32#.temporal.api.common.v1.RetryPolicy\x12@\n\tinitiator\x18\x08 \x01(\x0e\x32-.temporal.api.enums.v1.ContinueAsNewInitiator\x12\x31\n\x07\x66\x61ilure\x18\t \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12@\n\x16last_completion_result\x18\n \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x15\n\rcron_schedule\x18\x0b \x01(\t\x12.\n\x06header\x18\x0c \x01(\x0b\x32\x1e.temporal.api.common.v1.Header\x12*\n\x04memo\x18\r \x01(\x0b\x32\x1c.temporal.api.common.v1.Memo\x12\x43\n\x11search_attributes\x18\x0e \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes\x12\x1c\n\x10inherit_build_id\x18\x0f \x01(\x08\x42\x02\x18\x01\x12[\n\x1binitial_versioning_behavior\x18\x10 \x01(\x0e\x32\x36.temporal.api.enums.v1.ContinueAsNewVersioningBehavior"\xa1\x07\n,StartChildWorkflowExecutionCommandAttributes\x12\x15\n\tnamespace\x18\x01 \x01(\tB\x02\x18\x01\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12;\n\rworkflow_type\x18\x03 \x01(\x0b\x32$.temporal.api.common.v1.WorkflowType\x12\x38\n\ntask_queue\x18\x04 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12/\n\x05input\x18\x05 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12=\n\x1aworkflow_execution_timeout\x18\x06 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x37\n\x14workflow_run_timeout\x18\x07 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x38\n\x15workflow_task_timeout\x18\x08 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x45\n\x13parent_close_policy\x18\t \x01(\x0e\x32(.temporal.api.enums.v1.ParentClosePolicy\x12\x0f\n\x07\x63ontrol\x18\n \x01(\t\x12N\n\x18workflow_id_reuse_policy\x18\x0b \x01(\x0e\x32,.temporal.api.enums.v1.WorkflowIdReusePolicy\x12\x39\n\x0cretry_policy\x18\x0c \x01(\x0b\x32#.temporal.api.common.v1.RetryPolicy\x12\x15\n\rcron_schedule\x18\r \x01(\t\x12.\n\x06header\x18\x0e \x01(\x0b\x32\x1e.temporal.api.common.v1.Header\x12*\n\x04memo\x18\x0f \x01(\x0b\x32\x1c.temporal.api.common.v1.Memo\x12\x43\n\x11search_attributes\x18\x10 \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes\x12\x1c\n\x10inherit_build_id\x18\x11 \x01(\x08\x42\x02\x18\x01\x12\x32\n\x08priority\x18\x12 \x01(\x0b\x32 .temporal.api.common.v1.Priority"6\n ProtocolMessageCommandAttributes\x12\x12\n\nmessage_id\x18\x01 \x01(\t"\xe3\x03\n\'ScheduleNexusOperationCommandAttributes\x12\x10\n\x08\x65ndpoint\x18\x01 \x01(\t\x12\x0f\n\x07service\x18\x02 \x01(\t\x12\x11\n\toperation\x18\x03 \x01(\t\x12.\n\x05input\x18\x04 \x01(\x0b\x32\x1f.temporal.api.common.v1.Payload\x12<\n\x19schedule_to_close_timeout\x18\x05 \x01(\x0b\x32\x19.google.protobuf.Duration\x12g\n\x0cnexus_header\x18\x06 \x03(\x0b\x32Q.temporal.api.command.v1.ScheduleNexusOperationCommandAttributes.NexusHeaderEntry\x12<\n\x19schedule_to_start_timeout\x18\x07 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x39\n\x16start_to_close_timeout\x18\x08 \x01(\x0b\x32\x19.google.protobuf.Duration\x1a\x32\n\x10NexusHeaderEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01"J\n,RequestCancelNexusOperationCommandAttributes\x12\x1a\n\x12scheduled_event_id\x18\x01 \x01(\x03"\x87\x12\n\x07\x43ommand\x12\x38\n\x0c\x63ommand_type\x18\x01 \x01(\x0e\x32".temporal.api.enums.v1.CommandType\x12\x39\n\ruser_metadata\x18\xad\x02 \x01(\x0b\x32!.temporal.api.sdk.v1.UserMetadata\x12\x43\n\x13\x65vent_group_markers\x18\xae\x02 \x03(\x0b\x32%.temporal.api.sdk.v1.EventGroupMarker\x12s\n)schedule_activity_task_command_attributes\x18\x02 \x01(\x0b\x32>.temporal.api.command.v1.ScheduleActivityTaskCommandAttributesH\x00\x12^\n\x1estart_timer_command_attributes\x18\x03 \x01(\x0b\x32\x34.temporal.api.command.v1.StartTimerCommandAttributesH\x00\x12}\n.complete_workflow_execution_command_attributes\x18\x04 \x01(\x0b\x32\x43.temporal.api.command.v1.CompleteWorkflowExecutionCommandAttributesH\x00\x12u\n*fail_workflow_execution_command_attributes\x18\x05 \x01(\x0b\x32?.temporal.api.command.v1.FailWorkflowExecutionCommandAttributesH\x00\x12~\n/request_cancel_activity_task_command_attributes\x18\x06 \x01(\x0b\x32\x43.temporal.api.command.v1.RequestCancelActivityTaskCommandAttributesH\x00\x12`\n\x1f\x63\x61ncel_timer_command_attributes\x18\x07 \x01(\x0b\x32\x35.temporal.api.command.v1.CancelTimerCommandAttributesH\x00\x12y\n,cancel_workflow_execution_command_attributes\x18\x08 \x01(\x0b\x32\x41.temporal.api.command.v1.CancelWorkflowExecutionCommandAttributesH\x00\x12\x99\x01\n=request_cancel_external_workflow_execution_command_attributes\x18\t \x01(\x0b\x32P.temporal.api.command.v1.RequestCancelExternalWorkflowExecutionCommandAttributesH\x00\x12\x62\n record_marker_command_attributes\x18\n \x01(\x0b\x32\x36.temporal.api.command.v1.RecordMarkerCommandAttributesH\x00\x12\x89\x01\n5continue_as_new_workflow_execution_command_attributes\x18\x0b \x01(\x0b\x32H.temporal.api.command.v1.ContinueAsNewWorkflowExecutionCommandAttributesH\x00\x12\x82\x01\n1start_child_workflow_execution_command_attributes\x18\x0c \x01(\x0b\x32\x45.temporal.api.command.v1.StartChildWorkflowExecutionCommandAttributesH\x00\x12\x8a\x01\n5signal_external_workflow_execution_command_attributes\x18\r \x01(\x0b\x32I.temporal.api.command.v1.SignalExternalWorkflowExecutionCommandAttributesH\x00\x12\x88\x01\n4upsert_workflow_search_attributes_command_attributes\x18\x0e \x01(\x0b\x32H.temporal.api.command.v1.UpsertWorkflowSearchAttributesCommandAttributesH\x00\x12h\n#protocol_message_command_attributes\x18\x0f \x01(\x0b\x32\x39.temporal.api.command.v1.ProtocolMessageCommandAttributesH\x00\x12{\n-modify_workflow_properties_command_attributes\x18\x11 \x01(\x0b\x32\x42.temporal.api.command.v1.ModifyWorkflowPropertiesCommandAttributesH\x00\x12w\n+schedule_nexus_operation_command_attributes\x18\x12 \x01(\x0b\x32@.temporal.api.command.v1.ScheduleNexusOperationCommandAttributesH\x00\x12\x82\x01\n1request_cancel_nexus_operation_command_attributes\x18\x13 \x01(\x0b\x32\x45.temporal.api.command.v1.RequestCancelNexusOperationCommandAttributesH\x00\x42\x0c\n\nattributesB\x8e\x01\n\x1aio.temporal.api.command.v1B\x0cMessageProtoP\x01Z%go.temporal.io/api/command/v1;command\xaa\x02\x19Temporalio.Api.Command.V1\xea\x02\x1cTemporalio::Api::Command::V1b\x06proto3' ) @@ -377,44 +380,44 @@ _SCHEDULENEXUSOPERATIONCOMMANDATTRIBUTES_NEXUSHEADERENTRY._serialized_options = ( b"8\001" ) - _SCHEDULEACTIVITYTASKCOMMANDATTRIBUTES._serialized_start = 338 - _SCHEDULEACTIVITYTASKCOMMANDATTRIBUTES._serialized_end = 1032 - _REQUESTCANCELACTIVITYTASKCOMMANDATTRIBUTES._serialized_start = 1034 - _REQUESTCANCELACTIVITYTASKCOMMANDATTRIBUTES._serialized_end = 1106 - _STARTTIMERCOMMANDATTRIBUTES._serialized_start = 1108 - _STARTTIMERCOMMANDATTRIBUTES._serialized_end = 1213 - _COMPLETEWORKFLOWEXECUTIONCOMMANDATTRIBUTES._serialized_start = 1215 - _COMPLETEWORKFLOWEXECUTIONCOMMANDATTRIBUTES._serialized_end = 1309 - _FAILWORKFLOWEXECUTIONCOMMANDATTRIBUTES._serialized_start = 1311 - _FAILWORKFLOWEXECUTIONCOMMANDATTRIBUTES._serialized_end = 1402 - _CANCELTIMERCOMMANDATTRIBUTES._serialized_start = 1404 - _CANCELTIMERCOMMANDATTRIBUTES._serialized_end = 1452 - _CANCELWORKFLOWEXECUTIONCOMMANDATTRIBUTES._serialized_start = 1454 - _CANCELWORKFLOWEXECUTIONCOMMANDATTRIBUTES._serialized_end = 1547 - _REQUESTCANCELEXTERNALWORKFLOWEXECUTIONCOMMANDATTRIBUTES._serialized_start = 1550 - _REQUESTCANCELEXTERNALWORKFLOWEXECUTIONCOMMANDATTRIBUTES._serialized_end = 1733 - _SIGNALEXTERNALWORKFLOWEXECUTIONCOMMANDATTRIBUTES._serialized_start = 1736 - _SIGNALEXTERNALWORKFLOWEXECUTIONCOMMANDATTRIBUTES._serialized_end = 2039 - _UPSERTWORKFLOWSEARCHATTRIBUTESCOMMANDATTRIBUTES._serialized_start = 2041 - _UPSERTWORKFLOWSEARCHATTRIBUTESCOMMANDATTRIBUTES._serialized_end = 2159 - _MODIFYWORKFLOWPROPERTIESCOMMANDATTRIBUTES._serialized_start = 2161 - _MODIFYWORKFLOWPROPERTIESCOMMANDATTRIBUTES._serialized_end = 2257 - _RECORDMARKERCOMMANDATTRIBUTES._serialized_start = 2260 - _RECORDMARKERCOMMANDATTRIBUTES._serialized_end = 2579 - _RECORDMARKERCOMMANDATTRIBUTES_DETAILSENTRY._serialized_start = 2499 - _RECORDMARKERCOMMANDATTRIBUTES_DETAILSENTRY._serialized_end = 2579 - _CONTINUEASNEWWORKFLOWEXECUTIONCOMMANDATTRIBUTES._serialized_start = 2582 - _CONTINUEASNEWWORKFLOWEXECUTIONCOMMANDATTRIBUTES._serialized_end = 3522 - _STARTCHILDWORKFLOWEXECUTIONCOMMANDATTRIBUTES._serialized_start = 3525 - _STARTCHILDWORKFLOWEXECUTIONCOMMANDATTRIBUTES._serialized_end = 4454 - _PROTOCOLMESSAGECOMMANDATTRIBUTES._serialized_start = 4456 - _PROTOCOLMESSAGECOMMANDATTRIBUTES._serialized_end = 4510 - _SCHEDULENEXUSOPERATIONCOMMANDATTRIBUTES._serialized_start = 4513 - _SCHEDULENEXUSOPERATIONCOMMANDATTRIBUTES._serialized_end = 4996 - _SCHEDULENEXUSOPERATIONCOMMANDATTRIBUTES_NEXUSHEADERENTRY._serialized_start = 4946 - _SCHEDULENEXUSOPERATIONCOMMANDATTRIBUTES_NEXUSHEADERENTRY._serialized_end = 4996 - _REQUESTCANCELNEXUSOPERATIONCOMMANDATTRIBUTES._serialized_start = 4998 - _REQUESTCANCELNEXUSOPERATIONCOMMANDATTRIBUTES._serialized_end = 5072 - _COMMAND._serialized_start = 5075 - _COMMAND._serialized_end = 7317 + _SCHEDULEACTIVITYTASKCOMMANDATTRIBUTES._serialized_start = 384 + _SCHEDULEACTIVITYTASKCOMMANDATTRIBUTES._serialized_end = 1078 + _REQUESTCANCELACTIVITYTASKCOMMANDATTRIBUTES._serialized_start = 1080 + _REQUESTCANCELACTIVITYTASKCOMMANDATTRIBUTES._serialized_end = 1152 + _STARTTIMERCOMMANDATTRIBUTES._serialized_start = 1154 + _STARTTIMERCOMMANDATTRIBUTES._serialized_end = 1259 + _COMPLETEWORKFLOWEXECUTIONCOMMANDATTRIBUTES._serialized_start = 1261 + _COMPLETEWORKFLOWEXECUTIONCOMMANDATTRIBUTES._serialized_end = 1355 + _FAILWORKFLOWEXECUTIONCOMMANDATTRIBUTES._serialized_start = 1357 + _FAILWORKFLOWEXECUTIONCOMMANDATTRIBUTES._serialized_end = 1448 + _CANCELTIMERCOMMANDATTRIBUTES._serialized_start = 1450 + _CANCELTIMERCOMMANDATTRIBUTES._serialized_end = 1498 + _CANCELWORKFLOWEXECUTIONCOMMANDATTRIBUTES._serialized_start = 1500 + _CANCELWORKFLOWEXECUTIONCOMMANDATTRIBUTES._serialized_end = 1593 + _REQUESTCANCELEXTERNALWORKFLOWEXECUTIONCOMMANDATTRIBUTES._serialized_start = 1596 + _REQUESTCANCELEXTERNALWORKFLOWEXECUTIONCOMMANDATTRIBUTES._serialized_end = 1779 + _SIGNALEXTERNALWORKFLOWEXECUTIONCOMMANDATTRIBUTES._serialized_start = 1782 + _SIGNALEXTERNALWORKFLOWEXECUTIONCOMMANDATTRIBUTES._serialized_end = 2085 + _UPSERTWORKFLOWSEARCHATTRIBUTESCOMMANDATTRIBUTES._serialized_start = 2087 + _UPSERTWORKFLOWSEARCHATTRIBUTESCOMMANDATTRIBUTES._serialized_end = 2205 + _MODIFYWORKFLOWPROPERTIESCOMMANDATTRIBUTES._serialized_start = 2207 + _MODIFYWORKFLOWPROPERTIESCOMMANDATTRIBUTES._serialized_end = 2303 + _RECORDMARKERCOMMANDATTRIBUTES._serialized_start = 2306 + _RECORDMARKERCOMMANDATTRIBUTES._serialized_end = 2625 + _RECORDMARKERCOMMANDATTRIBUTES_DETAILSENTRY._serialized_start = 2545 + _RECORDMARKERCOMMANDATTRIBUTES_DETAILSENTRY._serialized_end = 2625 + _CONTINUEASNEWWORKFLOWEXECUTIONCOMMANDATTRIBUTES._serialized_start = 2628 + _CONTINUEASNEWWORKFLOWEXECUTIONCOMMANDATTRIBUTES._serialized_end = 3568 + _STARTCHILDWORKFLOWEXECUTIONCOMMANDATTRIBUTES._serialized_start = 3571 + _STARTCHILDWORKFLOWEXECUTIONCOMMANDATTRIBUTES._serialized_end = 4500 + _PROTOCOLMESSAGECOMMANDATTRIBUTES._serialized_start = 4502 + _PROTOCOLMESSAGECOMMANDATTRIBUTES._serialized_end = 4556 + _SCHEDULENEXUSOPERATIONCOMMANDATTRIBUTES._serialized_start = 4559 + _SCHEDULENEXUSOPERATIONCOMMANDATTRIBUTES._serialized_end = 5042 + _SCHEDULENEXUSOPERATIONCOMMANDATTRIBUTES_NEXUSHEADERENTRY._serialized_start = 4992 + _SCHEDULENEXUSOPERATIONCOMMANDATTRIBUTES_NEXUSHEADERENTRY._serialized_end = 5042 + _REQUESTCANCELNEXUSOPERATIONCOMMANDATTRIBUTES._serialized_start = 5044 + _REQUESTCANCELNEXUSOPERATIONCOMMANDATTRIBUTES._serialized_end = 5118 + _COMMAND._serialized_start = 5121 + _COMMAND._serialized_end = 7432 # @@protoc_insertion_point(module_scope) diff --git a/temporalio/api/command/v1/message_pb2.pyi b/temporalio/api/command/v1/message_pb2.pyi index 1b6bb3404..bf0cbf023 100644 --- a/temporalio/api/command/v1/message_pb2.pyi +++ b/temporalio/api/command/v1/message_pb2.pyi @@ -16,6 +16,7 @@ import temporalio.api.common.v1.message_pb2 import temporalio.api.enums.v1.command_type_pb2 import temporalio.api.enums.v1.workflow_pb2 import temporalio.api.failure.v1.message_pb2 +import temporalio.api.sdk.v1.event_group_marker_pb2 import temporalio.api.sdk.v1.user_metadata_pb2 import temporalio.api.taskqueue.v1.message_pb2 @@ -1083,6 +1084,7 @@ class Command(google.protobuf.message.Message): COMMAND_TYPE_FIELD_NUMBER: builtins.int USER_METADATA_FIELD_NUMBER: builtins.int + EVENT_GROUP_MARKERS_FIELD_NUMBER: builtins.int SCHEDULE_ACTIVITY_TASK_COMMAND_ATTRIBUTES_FIELD_NUMBER: builtins.int START_TIMER_COMMAND_ATTRIBUTES_FIELD_NUMBER: builtins.int COMPLETE_WORKFLOW_EXECUTION_COMMAND_ATTRIBUTES_FIELD_NUMBER: builtins.int @@ -1117,6 +1119,13 @@ class Command(google.protobuf.message.Message): started where the summary is used to identify the timer. """ @property + def event_group_markers( + self, + ) -> google.protobuf.internal.containers.RepeatedCompositeFieldContainer[ + temporalio.api.sdk.v1.event_group_marker_pb2.EventGroupMarker + ]: + """Event Group Markers attached to the command by the workflow author.""" + @property def schedule_activity_task_command_attributes( self, ) -> global___ScheduleActivityTaskCommandAttributes: ... @@ -1191,6 +1200,10 @@ class Command(google.protobuf.message.Message): command_type: temporalio.api.enums.v1.command_type_pb2.CommandType.ValueType = ..., user_metadata: temporalio.api.sdk.v1.user_metadata_pb2.UserMetadata | None = ..., + event_group_markers: collections.abc.Iterable[ + temporalio.api.sdk.v1.event_group_marker_pb2.EventGroupMarker + ] + | None = ..., schedule_activity_task_command_attributes: global___ScheduleActivityTaskCommandAttributes | None = ..., start_timer_command_attributes: global___StartTimerCommandAttributes @@ -1284,6 +1297,8 @@ class Command(google.protobuf.message.Message): b"complete_workflow_execution_command_attributes", "continue_as_new_workflow_execution_command_attributes", b"continue_as_new_workflow_execution_command_attributes", + "event_group_markers", + b"event_group_markers", "fail_workflow_execution_command_attributes", b"fail_workflow_execution_command_attributes", "modify_workflow_properties_command_attributes", diff --git a/temporalio/api/common/v1/__init__.py b/temporalio/api/common/v1/__init__.py index 112068861..4136d3b93 100644 --- a/temporalio/api/common/v1/__init__.py +++ b/temporalio/api/common/v1/__init__.py @@ -15,6 +15,8 @@ ResetOptions, RetryPolicy, SearchAttributes, + TimeSkippingConfig, + TimeSkippingStatePropagation, WorkerSelector, WorkerVersionCapabilities, WorkerVersionStamp, @@ -39,6 +41,8 @@ "ResetOptions", "RetryPolicy", "SearchAttributes", + "TimeSkippingConfig", + "TimeSkippingStatePropagation", "WorkerSelector", "WorkerVersionCapabilities", "WorkerVersionStamp", diff --git a/temporalio/api/common/v1/message_pb2.py b/temporalio/api/common/v1/message_pb2.py index aed909611..401e3721a 100644 --- a/temporalio/api/common/v1/message_pb2.py +++ b/temporalio/api/common/v1/message_pb2.py @@ -16,6 +16,7 @@ from google.protobuf import duration_pb2 as google_dot_protobuf_dot_duration__pb2 from google.protobuf import empty_pb2 as google_dot_protobuf_dot_empty__pb2 +from google.protobuf import timestamp_pb2 as google_dot_protobuf_dot_timestamp__pb2 from temporalio.api.enums.v1 import ( common_pb2 as temporal_dot_api_dot_enums_dot_v1_dot_common__pb2, @@ -28,7 +29,7 @@ ) DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile( - b'\n$temporal/api/common/v1/message.proto\x12\x16temporal.api.common.v1\x1a\x1egoogle/protobuf/duration.proto\x1a\x1bgoogle/protobuf/empty.proto\x1a"temporal/api/enums/v1/common.proto\x1a&temporal/api/enums/v1/event_type.proto\x1a!temporal/api/enums/v1/reset.proto"T\n\x08\x44\x61taBlob\x12:\n\rencoding_type\x18\x01 \x01(\x0e\x32#.temporal.api.enums.v1.EncodingType\x12\x0c\n\x04\x64\x61ta\x18\x02 \x01(\x0c"=\n\x08Payloads\x12\x31\n\x08payloads\x18\x01 \x03(\x0b\x32\x1f.temporal.api.common.v1.Payload"\x8a\x02\n\x07Payload\x12?\n\x08metadata\x18\x01 \x03(\x0b\x32-.temporal.api.common.v1.Payload.MetadataEntry\x12\x0c\n\x04\x64\x61ta\x18\x02 \x01(\x0c\x12Q\n\x11\x65xternal_payloads\x18\x03 \x03(\x0b\x32\x36.temporal.api.common.v1.Payload.ExternalPayloadDetails\x1a/\n\rMetadataEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\x0c:\x02\x38\x01\x1a,\n\x16\x45xternalPayloadDetails\x12\x12\n\nsize_bytes\x18\x01 \x01(\x03"\xbe\x01\n\x10SearchAttributes\x12S\n\x0eindexed_fields\x18\x01 \x03(\x0b\x32;.temporal.api.common.v1.SearchAttributes.IndexedFieldsEntry\x1aU\n\x12IndexedFieldsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12.\n\x05value\x18\x02 \x01(\x0b\x32\x1f.temporal.api.common.v1.Payload:\x02\x38\x01"\x90\x01\n\x04Memo\x12\x38\n\x06\x66ields\x18\x01 \x03(\x0b\x32(.temporal.api.common.v1.Memo.FieldsEntry\x1aN\n\x0b\x46ieldsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12.\n\x05value\x18\x02 \x01(\x0b\x32\x1f.temporal.api.common.v1.Payload:\x02\x38\x01"\x94\x01\n\x06Header\x12:\n\x06\x66ields\x18\x01 \x03(\x0b\x32*.temporal.api.common.v1.Header.FieldsEntry\x1aN\n\x0b\x46ieldsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12.\n\x05value\x18\x02 \x01(\x0b\x32\x1f.temporal.api.common.v1.Payload:\x02\x38\x01"8\n\x11WorkflowExecution\x12\x13\n\x0bworkflow_id\x18\x01 \x01(\t\x12\x0e\n\x06run_id\x18\x02 \x01(\t"\x1c\n\x0cWorkflowType\x12\x0c\n\x04name\x18\x01 \x01(\t"\x1c\n\x0c\x41\x63tivityType\x12\x0c\n\x04name\x18\x01 \x01(\t"\xd1\x01\n\x0bRetryPolicy\x12\x33\n\x10initial_interval\x18\x01 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x1b\n\x13\x62\x61\x63koff_coefficient\x18\x02 \x01(\x01\x12\x33\n\x10maximum_interval\x18\x03 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x18\n\x10maximum_attempts\x18\x04 \x01(\x05\x12!\n\x19non_retryable_error_types\x18\x05 \x03(\t"F\n\x10MeteringMetadata\x12\x32\n*nonfirst_local_activity_execution_attempts\x18\r \x01(\r">\n\x12WorkerVersionStamp\x12\x10\n\x08\x62uild_id\x18\x01 \x01(\t\x12\x16\n\x0euse_versioning\x18\x03 \x01(\x08"e\n\x19WorkerVersionCapabilities\x12\x10\n\x08\x62uild_id\x18\x01 \x01(\t\x12\x16\n\x0euse_versioning\x18\x02 \x01(\x08\x12\x1e\n\x16\x64\x65ployment_series_name\x18\x04 \x01(\t"\xed\x02\n\x0cResetOptions\x12\x35\n\x13\x66irst_workflow_task\x18\x01 \x01(\x0b\x32\x16.google.protobuf.EmptyH\x00\x12\x34\n\x12last_workflow_task\x18\x02 \x01(\x0b\x32\x16.google.protobuf.EmptyH\x00\x12\x1a\n\x10workflow_task_id\x18\x03 \x01(\x03H\x00\x12\x12\n\x08\x62uild_id\x18\x04 \x01(\tH\x00\x12G\n\x12reset_reapply_type\x18\n \x01(\x0e\x32\'.temporal.api.enums.v1.ResetReapplyTypeB\x02\x18\x01\x12\x18\n\x10\x63urrent_run_only\x18\x0b \x01(\x08\x12S\n\x1breset_reapply_exclude_types\x18\x0c \x03(\x0e\x32..temporal.api.enums.v1.ResetReapplyExcludeTypeB\x08\n\x06target"\xe4\x02\n\x08\x43\x61llback\x12\x37\n\x05nexus\x18\x02 \x01(\x0b\x32&.temporal.api.common.v1.Callback.NexusH\x00\x12=\n\x08internal\x18\x03 \x01(\x0b\x32).temporal.api.common.v1.Callback.InternalH\x00\x12+\n\x05links\x18\x64 \x03(\x0b\x32\x1c.temporal.api.common.v1.Link\x1a\x87\x01\n\x05Nexus\x12\x0b\n\x03url\x18\x01 \x01(\t\x12\x42\n\x06header\x18\x02 \x03(\x0b\x32\x32.temporal.api.common.v1.Callback.Nexus.HeaderEntry\x1a-\n\x0bHeaderEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x1a\x18\n\x08Internal\x12\x0c\n\x04\x64\x61ta\x18\x01 \x01(\x0c\x42\t\n\x07variantJ\x04\x08\x01\x10\x02"\x8a\x08\n\x04Link\x12\x44\n\x0eworkflow_event\x18\x01 \x01(\x0b\x32*.temporal.api.common.v1.Link.WorkflowEventH\x00\x12:\n\tbatch_job\x18\x02 \x01(\x0b\x32%.temporal.api.common.v1.Link.BatchJobH\x00\x12\x39\n\x08\x61\x63tivity\x18\x03 \x01(\x0b\x32%.temporal.api.common.v1.Link.ActivityH\x00\x12\x46\n\x0fnexus_operation\x18\x04 \x01(\x0b\x32+.temporal.api.common.v1.Link.NexusOperationH\x00\x12\x39\n\x08workflow\x18\x05 \x01(\x0b\x32%.temporal.api.common.v1.Link.WorkflowH\x00\x1a\xb7\x03\n\rWorkflowEvent\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x12N\n\tevent_ref\x18\x64 \x01(\x0b\x32\x39.temporal.api.common.v1.Link.WorkflowEvent.EventReferenceH\x00\x12W\n\x0erequest_id_ref\x18\x65 \x01(\x0b\x32=.temporal.api.common.v1.Link.WorkflowEvent.RequestIdReferenceH\x00\x1aX\n\x0e\x45ventReference\x12\x10\n\x08\x65vent_id\x18\x01 \x01(\x03\x12\x34\n\nevent_type\x18\x02 \x01(\x0e\x32 .temporal.api.enums.v1.EventType\x1a^\n\x12RequestIdReference\x12\x12\n\nrequest_id\x18\x01 \x01(\t\x12\x34\n\nevent_type\x18\x02 \x01(\x0e\x32 .temporal.api.enums.v1.EventTypeB\x0b\n\treference\x1a\x1a\n\x08\x42\x61tchJob\x12\x0e\n\x06job_id\x18\x01 \x01(\t\x1a\x42\n\x08\x41\x63tivity\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0b\x61\x63tivity_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x1aI\n\x0eNexusOperation\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x14\n\x0coperation_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x1aR\n\x08Workflow\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x12\x0e\n\x06reason\x18\x04 \x01(\tB\t\n\x07variant"\'\n\tPrincipal\x12\x0c\n\x04type\x18\x01 \x01(\t\x12\x0c\n\x04name\x18\x02 \x01(\t"O\n\x08Priority\x12\x14\n\x0cpriority_key\x18\x01 \x01(\x05\x12\x14\n\x0c\x66\x61irness_key\x18\x02 \x01(\t\x12\x17\n\x0f\x66\x61irness_weight\x18\x03 \x01(\x02";\n\x0eWorkerSelector\x12\x1d\n\x13worker_instance_key\x18\x01 \x01(\tH\x00\x42\n\n\x08selector"i\n\x11OnConflictOptions\x12\x19\n\x11\x61ttach_request_id\x18\x01 \x01(\x08\x12#\n\x1b\x61ttach_completion_callbacks\x18\x02 \x01(\x08\x12\x14\n\x0c\x61ttach_links\x18\x03 \x01(\x08\x42\x89\x01\n\x19io.temporal.api.common.v1B\x0cMessageProtoP\x01Z#go.temporal.io/api/common/v1;common\xaa\x02\x18Temporalio.Api.Common.V1\xea\x02\x1bTemporalio::Api::Common::V1b\x06proto3' + b'\n$temporal/api/common/v1/message.proto\x12\x16temporal.api.common.v1\x1a\x1egoogle/protobuf/duration.proto\x1a\x1bgoogle/protobuf/empty.proto\x1a\x1fgoogle/protobuf/timestamp.proto\x1a"temporal/api/enums/v1/common.proto\x1a&temporal/api/enums/v1/event_type.proto\x1a!temporal/api/enums/v1/reset.proto"T\n\x08\x44\x61taBlob\x12:\n\rencoding_type\x18\x01 \x01(\x0e\x32#.temporal.api.enums.v1.EncodingType\x12\x0c\n\x04\x64\x61ta\x18\x02 \x01(\x0c"=\n\x08Payloads\x12\x31\n\x08payloads\x18\x01 \x03(\x0b\x32\x1f.temporal.api.common.v1.Payload"\x8a\x02\n\x07Payload\x12?\n\x08metadata\x18\x01 \x03(\x0b\x32-.temporal.api.common.v1.Payload.MetadataEntry\x12\x0c\n\x04\x64\x61ta\x18\x02 \x01(\x0c\x12Q\n\x11\x65xternal_payloads\x18\x03 \x03(\x0b\x32\x36.temporal.api.common.v1.Payload.ExternalPayloadDetails\x1a/\n\rMetadataEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\x0c:\x02\x38\x01\x1a,\n\x16\x45xternalPayloadDetails\x12\x12\n\nsize_bytes\x18\x01 \x01(\x03"\xbe\x01\n\x10SearchAttributes\x12S\n\x0eindexed_fields\x18\x01 \x03(\x0b\x32;.temporal.api.common.v1.SearchAttributes.IndexedFieldsEntry\x1aU\n\x12IndexedFieldsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12.\n\x05value\x18\x02 \x01(\x0b\x32\x1f.temporal.api.common.v1.Payload:\x02\x38\x01"\x90\x01\n\x04Memo\x12\x38\n\x06\x66ields\x18\x01 \x03(\x0b\x32(.temporal.api.common.v1.Memo.FieldsEntry\x1aN\n\x0b\x46ieldsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12.\n\x05value\x18\x02 \x01(\x0b\x32\x1f.temporal.api.common.v1.Payload:\x02\x38\x01"\x94\x01\n\x06Header\x12:\n\x06\x66ields\x18\x01 \x03(\x0b\x32*.temporal.api.common.v1.Header.FieldsEntry\x1aN\n\x0b\x46ieldsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12.\n\x05value\x18\x02 \x01(\x0b\x32\x1f.temporal.api.common.v1.Payload:\x02\x38\x01"8\n\x11WorkflowExecution\x12\x13\n\x0bworkflow_id\x18\x01 \x01(\t\x12\x0e\n\x06run_id\x18\x02 \x01(\t"\x1c\n\x0cWorkflowType\x12\x0c\n\x04name\x18\x01 \x01(\t"\x1c\n\x0c\x41\x63tivityType\x12\x0c\n\x04name\x18\x01 \x01(\t"\xd1\x01\n\x0bRetryPolicy\x12\x33\n\x10initial_interval\x18\x01 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x1b\n\x13\x62\x61\x63koff_coefficient\x18\x02 \x01(\x01\x12\x33\n\x10maximum_interval\x18\x03 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x18\n\x10maximum_attempts\x18\x04 \x01(\x05\x12!\n\x19non_retryable_error_types\x18\x05 \x03(\t"F\n\x10MeteringMetadata\x12\x32\n*nonfirst_local_activity_execution_attempts\x18\r \x01(\r">\n\x12WorkerVersionStamp\x12\x10\n\x08\x62uild_id\x18\x01 \x01(\t\x12\x16\n\x0euse_versioning\x18\x03 \x01(\x08"e\n\x19WorkerVersionCapabilities\x12\x10\n\x08\x62uild_id\x18\x01 \x01(\t\x12\x16\n\x0euse_versioning\x18\x02 \x01(\x08\x12\x1e\n\x16\x64\x65ployment_series_name\x18\x04 \x01(\t"\xed\x02\n\x0cResetOptions\x12\x35\n\x13\x66irst_workflow_task\x18\x01 \x01(\x0b\x32\x16.google.protobuf.EmptyH\x00\x12\x34\n\x12last_workflow_task\x18\x02 \x01(\x0b\x32\x16.google.protobuf.EmptyH\x00\x12\x1a\n\x10workflow_task_id\x18\x03 \x01(\x03H\x00\x12\x12\n\x08\x62uild_id\x18\x04 \x01(\tH\x00\x12G\n\x12reset_reapply_type\x18\n \x01(\x0e\x32\'.temporal.api.enums.v1.ResetReapplyTypeB\x02\x18\x01\x12\x18\n\x10\x63urrent_run_only\x18\x0b \x01(\x08\x12S\n\x1breset_reapply_exclude_types\x18\x0c \x03(\x0e\x32..temporal.api.enums.v1.ResetReapplyExcludeTypeB\x08\n\x06target"\xe4\x02\n\x08\x43\x61llback\x12\x37\n\x05nexus\x18\x02 \x01(\x0b\x32&.temporal.api.common.v1.Callback.NexusH\x00\x12=\n\x08internal\x18\x03 \x01(\x0b\x32).temporal.api.common.v1.Callback.InternalH\x00\x12+\n\x05links\x18\x64 \x03(\x0b\x32\x1c.temporal.api.common.v1.Link\x1a\x87\x01\n\x05Nexus\x12\x0b\n\x03url\x18\x01 \x01(\t\x12\x42\n\x06header\x18\x02 \x03(\x0b\x32\x32.temporal.api.common.v1.Callback.Nexus.HeaderEntry\x1a-\n\x0bHeaderEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x1a\x18\n\x08Internal\x12\x0c\n\x04\x64\x61ta\x18\x01 \x01(\x0c\x42\t\n\x07variantJ\x04\x08\x01\x10\x02"\x8a\x08\n\x04Link\x12\x44\n\x0eworkflow_event\x18\x01 \x01(\x0b\x32*.temporal.api.common.v1.Link.WorkflowEventH\x00\x12:\n\tbatch_job\x18\x02 \x01(\x0b\x32%.temporal.api.common.v1.Link.BatchJobH\x00\x12\x39\n\x08\x61\x63tivity\x18\x03 \x01(\x0b\x32%.temporal.api.common.v1.Link.ActivityH\x00\x12\x46\n\x0fnexus_operation\x18\x04 \x01(\x0b\x32+.temporal.api.common.v1.Link.NexusOperationH\x00\x12\x39\n\x08workflow\x18\x05 \x01(\x0b\x32%.temporal.api.common.v1.Link.WorkflowH\x00\x1a\xb7\x03\n\rWorkflowEvent\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x12N\n\tevent_ref\x18\x64 \x01(\x0b\x32\x39.temporal.api.common.v1.Link.WorkflowEvent.EventReferenceH\x00\x12W\n\x0erequest_id_ref\x18\x65 \x01(\x0b\x32=.temporal.api.common.v1.Link.WorkflowEvent.RequestIdReferenceH\x00\x1aX\n\x0e\x45ventReference\x12\x10\n\x08\x65vent_id\x18\x01 \x01(\x03\x12\x34\n\nevent_type\x18\x02 \x01(\x0e\x32 .temporal.api.enums.v1.EventType\x1a^\n\x12RequestIdReference\x12\x12\n\nrequest_id\x18\x01 \x01(\t\x12\x34\n\nevent_type\x18\x02 \x01(\x0e\x32 .temporal.api.enums.v1.EventTypeB\x0b\n\treference\x1a\x1a\n\x08\x42\x61tchJob\x12\x0e\n\x06job_id\x18\x01 \x01(\t\x1a\x42\n\x08\x41\x63tivity\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0b\x61\x63tivity_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x1aI\n\x0eNexusOperation\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x14\n\x0coperation_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x1aR\n\x08Workflow\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x12\x0e\n\x06reason\x18\x04 \x01(\tB\t\n\x07variant"\'\n\tPrincipal\x12\x0c\n\x04type\x18\x01 \x01(\t\x12\x0c\n\x04name\x18\x02 \x01(\t"O\n\x08Priority\x12\x14\n\x0cpriority_key\x18\x01 \x01(\x05\x12\x14\n\x0c\x66\x61irness_key\x18\x02 \x01(\t\x12\x17\n\x0f\x66\x61irness_weight\x18\x03 \x01(\x02";\n\x0eWorkerSelector\x12\x1d\n\x13worker_instance_key\x18\x01 \x01(\tH\x00\x42\n\n\x08selector"i\n\x11OnConflictOptions\x12\x19\n\x11\x61ttach_request_id\x18\x01 \x01(\x08\x12#\n\x1b\x61ttach_completion_callbacks\x18\x02 \x01(\x08\x12\x14\n\x0c\x61ttach_links\x18\x03 \x01(\x08"y\n\x12TimeSkippingConfig\x12\x0f\n\x07\x65nabled\x18\x01 \x01(\x08\x12/\n\x0c\x66\x61st_forward\x18\x02 \x01(\x0b\x32\x19.google.protobuf.Duration\x12!\n\x19\x64isable_child_propagation\x18\x03 \x01(\x08"\x99\x01\n\x1cTimeSkippingStatePropagation\x12;\n\x18initial_skipped_duration\x18\x01 \x01(\x0b\x32\x19.google.protobuf.Duration\x12<\n\x18\x66\x61st_forward_target_time\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.TimestampB\x89\x01\n\x19io.temporal.api.common.v1B\x0cMessageProtoP\x01Z#go.temporal.io/api/common/v1;common\xaa\x02\x18Temporalio.Api.Common.V1\xea\x02\x1bTemporalio::Api::Common::V1b\x06proto3' ) @@ -77,6 +78,10 @@ _PRIORITY = DESCRIPTOR.message_types_by_name["Priority"] _WORKERSELECTOR = DESCRIPTOR.message_types_by_name["WorkerSelector"] _ONCONFLICTOPTIONS = DESCRIPTOR.message_types_by_name["OnConflictOptions"] +_TIMESKIPPINGCONFIG = DESCRIPTOR.message_types_by_name["TimeSkippingConfig"] +_TIMESKIPPINGSTATEPROPAGATION = DESCRIPTOR.message_types_by_name[ + "TimeSkippingStatePropagation" +] DataBlob = _reflection.GeneratedProtocolMessageType( "DataBlob", (_message.Message,), @@ -447,6 +452,28 @@ ) _sym_db.RegisterMessage(OnConflictOptions) +TimeSkippingConfig = _reflection.GeneratedProtocolMessageType( + "TimeSkippingConfig", + (_message.Message,), + { + "DESCRIPTOR": _TIMESKIPPINGCONFIG, + "__module__": "temporalio.api.common.v1.message_pb2", + # @@protoc_insertion_point(class_scope:temporal.api.common.v1.TimeSkippingConfig) + }, +) +_sym_db.RegisterMessage(TimeSkippingConfig) + +TimeSkippingStatePropagation = _reflection.GeneratedProtocolMessageType( + "TimeSkippingStatePropagation", + (_message.Message,), + { + "DESCRIPTOR": _TIMESKIPPINGSTATEPROPAGATION, + "__module__": "temporalio.api.common.v1.message_pb2", + # @@protoc_insertion_point(class_scope:temporal.api.common.v1.TimeSkippingStatePropagation) + }, +) +_sym_db.RegisterMessage(TimeSkippingStatePropagation) + if _descriptor._USE_C_DESCRIPTORS == False: DESCRIPTOR._options = None DESCRIPTOR._serialized_options = b"\n\031io.temporal.api.common.v1B\014MessageProtoP\001Z#go.temporal.io/api/common/v1;common\252\002\030Temporalio.Api.Common.V1\352\002\033Temporalio::Api::Common::V1" @@ -462,74 +489,78 @@ _RESETOPTIONS.fields_by_name["reset_reapply_type"]._serialized_options = b"\030\001" _CALLBACK_NEXUS_HEADERENTRY._options = None _CALLBACK_NEXUS_HEADERENTRY._serialized_options = b"8\001" - _DATABLOB._serialized_start = 236 - _DATABLOB._serialized_end = 320 - _PAYLOADS._serialized_start = 322 - _PAYLOADS._serialized_end = 383 - _PAYLOAD._serialized_start = 386 - _PAYLOAD._serialized_end = 652 - _PAYLOAD_METADATAENTRY._serialized_start = 559 - _PAYLOAD_METADATAENTRY._serialized_end = 606 - _PAYLOAD_EXTERNALPAYLOADDETAILS._serialized_start = 608 - _PAYLOAD_EXTERNALPAYLOADDETAILS._serialized_end = 652 - _SEARCHATTRIBUTES._serialized_start = 655 - _SEARCHATTRIBUTES._serialized_end = 845 - _SEARCHATTRIBUTES_INDEXEDFIELDSENTRY._serialized_start = 760 - _SEARCHATTRIBUTES_INDEXEDFIELDSENTRY._serialized_end = 845 - _MEMO._serialized_start = 848 - _MEMO._serialized_end = 992 - _MEMO_FIELDSENTRY._serialized_start = 914 - _MEMO_FIELDSENTRY._serialized_end = 992 - _HEADER._serialized_start = 995 - _HEADER._serialized_end = 1143 - _HEADER_FIELDSENTRY._serialized_start = 914 - _HEADER_FIELDSENTRY._serialized_end = 992 - _WORKFLOWEXECUTION._serialized_start = 1145 - _WORKFLOWEXECUTION._serialized_end = 1201 - _WORKFLOWTYPE._serialized_start = 1203 - _WORKFLOWTYPE._serialized_end = 1231 - _ACTIVITYTYPE._serialized_start = 1233 - _ACTIVITYTYPE._serialized_end = 1261 - _RETRYPOLICY._serialized_start = 1264 - _RETRYPOLICY._serialized_end = 1473 - _METERINGMETADATA._serialized_start = 1475 - _METERINGMETADATA._serialized_end = 1545 - _WORKERVERSIONSTAMP._serialized_start = 1547 - _WORKERVERSIONSTAMP._serialized_end = 1609 - _WORKERVERSIONCAPABILITIES._serialized_start = 1611 - _WORKERVERSIONCAPABILITIES._serialized_end = 1712 - _RESETOPTIONS._serialized_start = 1715 - _RESETOPTIONS._serialized_end = 2080 - _CALLBACK._serialized_start = 2083 - _CALLBACK._serialized_end = 2439 - _CALLBACK_NEXUS._serialized_start = 2261 - _CALLBACK_NEXUS._serialized_end = 2396 - _CALLBACK_NEXUS_HEADERENTRY._serialized_start = 2351 - _CALLBACK_NEXUS_HEADERENTRY._serialized_end = 2396 - _CALLBACK_INTERNAL._serialized_start = 2398 - _CALLBACK_INTERNAL._serialized_end = 2422 - _LINK._serialized_start = 2442 - _LINK._serialized_end = 3476 - _LINK_WORKFLOWEVENT._serialized_start = 2771 - _LINK_WORKFLOWEVENT._serialized_end = 3210 - _LINK_WORKFLOWEVENT_EVENTREFERENCE._serialized_start = 3013 - _LINK_WORKFLOWEVENT_EVENTREFERENCE._serialized_end = 3101 - _LINK_WORKFLOWEVENT_REQUESTIDREFERENCE._serialized_start = 3103 - _LINK_WORKFLOWEVENT_REQUESTIDREFERENCE._serialized_end = 3197 - _LINK_BATCHJOB._serialized_start = 3212 - _LINK_BATCHJOB._serialized_end = 3238 - _LINK_ACTIVITY._serialized_start = 3240 - _LINK_ACTIVITY._serialized_end = 3306 - _LINK_NEXUSOPERATION._serialized_start = 3308 - _LINK_NEXUSOPERATION._serialized_end = 3381 - _LINK_WORKFLOW._serialized_start = 3383 - _LINK_WORKFLOW._serialized_end = 3465 - _PRINCIPAL._serialized_start = 3478 - _PRINCIPAL._serialized_end = 3517 - _PRIORITY._serialized_start = 3519 - _PRIORITY._serialized_end = 3598 - _WORKERSELECTOR._serialized_start = 3600 - _WORKERSELECTOR._serialized_end = 3659 - _ONCONFLICTOPTIONS._serialized_start = 3661 - _ONCONFLICTOPTIONS._serialized_end = 3766 + _DATABLOB._serialized_start = 269 + _DATABLOB._serialized_end = 353 + _PAYLOADS._serialized_start = 355 + _PAYLOADS._serialized_end = 416 + _PAYLOAD._serialized_start = 419 + _PAYLOAD._serialized_end = 685 + _PAYLOAD_METADATAENTRY._serialized_start = 592 + _PAYLOAD_METADATAENTRY._serialized_end = 639 + _PAYLOAD_EXTERNALPAYLOADDETAILS._serialized_start = 641 + _PAYLOAD_EXTERNALPAYLOADDETAILS._serialized_end = 685 + _SEARCHATTRIBUTES._serialized_start = 688 + _SEARCHATTRIBUTES._serialized_end = 878 + _SEARCHATTRIBUTES_INDEXEDFIELDSENTRY._serialized_start = 793 + _SEARCHATTRIBUTES_INDEXEDFIELDSENTRY._serialized_end = 878 + _MEMO._serialized_start = 881 + _MEMO._serialized_end = 1025 + _MEMO_FIELDSENTRY._serialized_start = 947 + _MEMO_FIELDSENTRY._serialized_end = 1025 + _HEADER._serialized_start = 1028 + _HEADER._serialized_end = 1176 + _HEADER_FIELDSENTRY._serialized_start = 947 + _HEADER_FIELDSENTRY._serialized_end = 1025 + _WORKFLOWEXECUTION._serialized_start = 1178 + _WORKFLOWEXECUTION._serialized_end = 1234 + _WORKFLOWTYPE._serialized_start = 1236 + _WORKFLOWTYPE._serialized_end = 1264 + _ACTIVITYTYPE._serialized_start = 1266 + _ACTIVITYTYPE._serialized_end = 1294 + _RETRYPOLICY._serialized_start = 1297 + _RETRYPOLICY._serialized_end = 1506 + _METERINGMETADATA._serialized_start = 1508 + _METERINGMETADATA._serialized_end = 1578 + _WORKERVERSIONSTAMP._serialized_start = 1580 + _WORKERVERSIONSTAMP._serialized_end = 1642 + _WORKERVERSIONCAPABILITIES._serialized_start = 1644 + _WORKERVERSIONCAPABILITIES._serialized_end = 1745 + _RESETOPTIONS._serialized_start = 1748 + _RESETOPTIONS._serialized_end = 2113 + _CALLBACK._serialized_start = 2116 + _CALLBACK._serialized_end = 2472 + _CALLBACK_NEXUS._serialized_start = 2294 + _CALLBACK_NEXUS._serialized_end = 2429 + _CALLBACK_NEXUS_HEADERENTRY._serialized_start = 2384 + _CALLBACK_NEXUS_HEADERENTRY._serialized_end = 2429 + _CALLBACK_INTERNAL._serialized_start = 2431 + _CALLBACK_INTERNAL._serialized_end = 2455 + _LINK._serialized_start = 2475 + _LINK._serialized_end = 3509 + _LINK_WORKFLOWEVENT._serialized_start = 2804 + _LINK_WORKFLOWEVENT._serialized_end = 3243 + _LINK_WORKFLOWEVENT_EVENTREFERENCE._serialized_start = 3046 + _LINK_WORKFLOWEVENT_EVENTREFERENCE._serialized_end = 3134 + _LINK_WORKFLOWEVENT_REQUESTIDREFERENCE._serialized_start = 3136 + _LINK_WORKFLOWEVENT_REQUESTIDREFERENCE._serialized_end = 3230 + _LINK_BATCHJOB._serialized_start = 3245 + _LINK_BATCHJOB._serialized_end = 3271 + _LINK_ACTIVITY._serialized_start = 3273 + _LINK_ACTIVITY._serialized_end = 3339 + _LINK_NEXUSOPERATION._serialized_start = 3341 + _LINK_NEXUSOPERATION._serialized_end = 3414 + _LINK_WORKFLOW._serialized_start = 3416 + _LINK_WORKFLOW._serialized_end = 3498 + _PRINCIPAL._serialized_start = 3511 + _PRINCIPAL._serialized_end = 3550 + _PRIORITY._serialized_start = 3552 + _PRIORITY._serialized_end = 3631 + _WORKERSELECTOR._serialized_start = 3633 + _WORKERSELECTOR._serialized_end = 3692 + _ONCONFLICTOPTIONS._serialized_start = 3694 + _ONCONFLICTOPTIONS._serialized_end = 3799 + _TIMESKIPPINGCONFIG._serialized_start = 3801 + _TIMESKIPPINGCONFIG._serialized_end = 3922 + _TIMESKIPPINGSTATEPROPAGATION._serialized_start = 3925 + _TIMESKIPPINGSTATEPROPAGATION._serialized_end = 4078 # @@protoc_insertion_point(module_scope) diff --git a/temporalio/api/common/v1/message_pb2.pyi b/temporalio/api/common/v1/message_pb2.pyi index 76e87fd56..04840f406 100644 --- a/temporalio/api/common/v1/message_pb2.pyi +++ b/temporalio/api/common/v1/message_pb2.pyi @@ -12,6 +12,7 @@ import google.protobuf.duration_pb2 import google.protobuf.empty_pb2 import google.protobuf.internal.containers import google.protobuf.message +import google.protobuf.timestamp_pb2 import temporalio.api.enums.v1.common_pb2 import temporalio.api.enums.v1.event_type_pb2 @@ -1255,3 +1256,115 @@ class OnConflictOptions(google.protobuf.message.Message): ) -> None: ... global___OnConflictOptions = OnConflictOptions + +class TimeSkippingConfig(google.protobuf.message.Message): + """The configuration for time skipping of a workflow execution (a chain of runs including retries, cron, continue-as-new). + When time skipping is enabled, virtual time advances automatically whenever there is no in-flight work. + In-flight work includes activities, child workflows, Nexus operations, signal/cancel external workflow operations, + and possibly other features added in the future. + User timers are not classified as in-flight work and will be skipped over; the virtual clock may also skip to the + time point of the registered fast forward when there is no in-flight work. + When time is skipped, a WorkflowExecutionTimeSkippingTransitionedEvent will be + added to the workflow history to capture the state changes. + + For child workflows, by default, if the parent execution is skipping time, the child execution will also skip time, + but a parent's fast_forward won't affect its child's execution. A flag is provided to disable propagation of the + "enabled" flag to child workflows; regardless of that flag, a child workflow inherits the virtual time from the + parent execution as its start time. + """ + + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + ENABLED_FIELD_NUMBER: builtins.int + FAST_FORWARD_FIELD_NUMBER: builtins.int + DISABLE_CHILD_PROPAGATION_FIELD_NUMBER: builtins.int + enabled: builtins.bool + """Enables or disables time skipping for this workflow execution.""" + @property + def fast_forward(self) -> google.protobuf.duration_pb2.Duration: + """Optionally fast-forward the current workflow execution by this duration ahead of current workflow execution time. + After the fast-forward completes, time skipping is disabled, and this + action is recorded in the WorkflowExecutionTimeSkippingTransitionedEvent. It can be re-enabled by + setting `enabled` to true or setting `fast_forward` again via UpdateWorkflowExecutionOptions. + The current workflow execution is a chain of runs (retries, cron, continue-as-new); + child workflows are separate executions, so this fast_forward won't affect them. + + For a given workflow execution, only one active fast-forward is allowed at a time. + If a new fast-forward is set via UpdateWorkflowExecutionOptions before the previous + one completes, the new one will override the previous one. + If the fast-forward duration exceeds the remaining execution timeout, time will only + be fast-forwarded up to the end of the execution. + """ + disable_child_propagation: builtins.bool + """By default, child workflows inherit the "enabled" flag when they are started. + This flag disables that inheritance. + """ + def __init__( + self, + *, + enabled: builtins.bool = ..., + fast_forward: google.protobuf.duration_pb2.Duration | None = ..., + disable_child_propagation: builtins.bool = ..., + ) -> None: ... + def HasField( + self, field_name: typing_extensions.Literal["fast_forward", b"fast_forward"] + ) -> builtins.bool: ... + def ClearField( + self, + field_name: typing_extensions.Literal[ + "disable_child_propagation", + b"disable_child_propagation", + "enabled", + b"enabled", + "fast_forward", + b"fast_forward", + ], + ) -> None: ... + +global___TimeSkippingConfig = TimeSkippingConfig + +class TimeSkippingStatePropagation(google.protobuf.message.Message): + """The time-skipping state that needs to be propagated from a parent workflow to a child workflow, + or through a chain of runs. + """ + + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + INITIAL_SKIPPED_DURATION_FIELD_NUMBER: builtins.int + FAST_FORWARD_TARGET_TIME_FIELD_NUMBER: builtins.int + @property + def initial_skipped_duration(self) -> google.protobuf.duration_pb2.Duration: + """The time skipped by the previous execution that started this workflow. + It can happen in child workflows and a chain of runs (CaN, cron, retry). + """ + @property + def fast_forward_target_time(self) -> google.protobuf.timestamp_pb2.Timestamp: + """If there is a fast-forward action set for the previous run in a chain of runs, + the target time should be propagated to the next run as well. + """ + def __init__( + self, + *, + initial_skipped_duration: google.protobuf.duration_pb2.Duration | None = ..., + fast_forward_target_time: google.protobuf.timestamp_pb2.Timestamp | None = ..., + ) -> None: ... + def HasField( + self, + field_name: typing_extensions.Literal[ + "fast_forward_target_time", + b"fast_forward_target_time", + "initial_skipped_duration", + b"initial_skipped_duration", + ], + ) -> builtins.bool: ... + def ClearField( + self, + field_name: typing_extensions.Literal[ + "fast_forward_target_time", + b"fast_forward_target_time", + "initial_skipped_duration", + b"initial_skipped_duration", + ], + ) -> None: ... + +global___TimeSkippingStatePropagation = TimeSkippingStatePropagation diff --git a/temporalio/api/deployment/v1/__init__.py b/temporalio/api/deployment/v1/__init__.py index 22f3e77e5..2abc00d31 100644 --- a/temporalio/api/deployment/v1/__init__.py +++ b/temporalio/api/deployment/v1/__init__.py @@ -1,4 +1,5 @@ from .message_pb2 import ( + ComputeStatus, Deployment, DeploymentInfo, DeploymentListInfo, @@ -14,6 +15,7 @@ ) __all__ = [ + "ComputeStatus", "Deployment", "DeploymentInfo", "DeploymentListInfo", diff --git a/temporalio/api/deployment/v1/message_pb2.py b/temporalio/api/deployment/v1/message_pb2.py index 08914a31f..cc3b1ea75 100644 --- a/temporalio/api/deployment/v1/message_pb2.py +++ b/temporalio/api/deployment/v1/message_pb2.py @@ -33,7 +33,7 @@ ) DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile( - b'\n(temporal/api/deployment/v1/message.proto\x12\x1atemporal.api.deployment.v1\x1a\x1fgoogle/protobuf/timestamp.proto\x1a$temporal/api/enums/v1/workflow.proto\x1a&temporal/api/enums/v1/deployment.proto\x1a&temporal/api/enums/v1/task_queue.proto\x1a$temporal/api/common/v1/message.proto\x1a$temporal/api/compute/v1/config.proto"\x91\x01\n\x17WorkerDeploymentOptions\x12\x17\n\x0f\x64\x65ployment_name\x18\x01 \x01(\t\x12\x10\n\x08\x62uild_id\x18\x02 \x01(\t\x12K\n\x16worker_versioning_mode\x18\x03 \x01(\x0e\x32+.temporal.api.enums.v1.WorkerVersioningMode"3\n\nDeployment\x12\x13\n\x0bseries_name\x18\x01 \x01(\t\x12\x10\n\x08\x62uild_id\x18\x02 \x01(\t"\x8e\x04\n\x0e\x44\x65ploymentInfo\x12:\n\ndeployment\x18\x01 \x01(\x0b\x32&.temporal.api.deployment.v1.Deployment\x12/\n\x0b\x63reate_time\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12R\n\x10task_queue_infos\x18\x03 \x03(\x0b\x32\x38.temporal.api.deployment.v1.DeploymentInfo.TaskQueueInfo\x12J\n\x08metadata\x18\x04 \x03(\x0b\x32\x38.temporal.api.deployment.v1.DeploymentInfo.MetadataEntry\x12\x12\n\nis_current\x18\x05 \x01(\x08\x1aP\n\rMetadataEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12.\n\x05value\x18\x02 \x01(\x0b\x32\x1f.temporal.api.common.v1.Payload:\x02\x38\x01\x1a\x88\x01\n\rTaskQueueInfo\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x32\n\x04type\x18\x02 \x01(\x0e\x32$.temporal.api.enums.v1.TaskQueueType\x12\x35\n\x11\x66irst_poller_time\x18\x03 \x01(\x0b\x32\x1a.google.protobuf.Timestamp"\xea\x01\n\x18UpdateDeploymentMetadata\x12_\n\x0eupsert_entries\x18\x01 \x03(\x0b\x32G.temporal.api.deployment.v1.UpdateDeploymentMetadata.UpsertEntriesEntry\x12\x16\n\x0eremove_entries\x18\x02 \x03(\t\x1aU\n\x12UpsertEntriesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12.\n\x05value\x18\x02 \x01(\x0b\x32\x1f.temporal.api.common.v1.Payload:\x02\x38\x01"\x95\x01\n\x12\x44\x65ploymentListInfo\x12:\n\ndeployment\x18\x01 \x01(\x0b\x32&.temporal.api.deployment.v1.Deployment\x12/\n\x0b\x63reate_time\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x12\n\nis_current\x18\x03 \x01(\x08"\xad\x08\n\x1bWorkerDeploymentVersionInfo\x12\x13\n\x07version\x18\x01 \x01(\tB\x02\x18\x01\x12\x44\n\x06status\x18\x0e \x01(\x0e\x32\x34.temporal.api.enums.v1.WorkerDeploymentVersionStatus\x12O\n\x12\x64\x65ployment_version\x18\x0b \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersion\x12\x17\n\x0f\x64\x65ployment_name\x18\x02 \x01(\t\x12/\n\x0b\x63reate_time\x18\x03 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x38\n\x14routing_changed_time\x18\x04 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x36\n\x12\x63urrent_since_time\x18\x05 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x36\n\x12ramping_since_time\x18\x06 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x39\n\x15\x66irst_activation_time\x18\x0c \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x35\n\x11last_current_time\x18\x0f \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12:\n\x16last_deactivation_time\x18\r \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x17\n\x0framp_percentage\x18\x07 \x01(\x02\x12\x66\n\x10task_queue_infos\x18\x08 \x03(\x0b\x32L.temporal.api.deployment.v1.WorkerDeploymentVersionInfo.VersionTaskQueueInfo\x12\x46\n\rdrainage_info\x18\t \x01(\x0b\x32/.temporal.api.deployment.v1.VersionDrainageInfo\x12=\n\x08metadata\x18\n \x01(\x0b\x32+.temporal.api.deployment.v1.VersionMetadata\x12>\n\x0e\x63ompute_config\x18\x10 \x01(\x0b\x32&.temporal.api.compute.v1.ComputeConfig\x12\x1e\n\x16last_modifier_identity\x18\x11 \x01(\t\x1aX\n\x14VersionTaskQueueInfo\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x32\n\x04type\x18\x02 \x01(\x0e\x32$.temporal.api.enums.v1.TaskQueueType"\xc1\x01\n\x13VersionDrainageInfo\x12<\n\x06status\x18\x01 \x01(\x0e\x32,.temporal.api.enums.v1.VersionDrainageStatus\x12\x35\n\x11last_changed_time\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x35\n\x11last_checked_time\x18\x03 \x01(\x0b\x32\x1a.google.protobuf.Timestamp"\xc1\t\n\x14WorkerDeploymentInfo\x12\x0c\n\x04name\x18\x01 \x01(\t\x12j\n\x11version_summaries\x18\x02 \x03(\x0b\x32O.temporal.api.deployment.v1.WorkerDeploymentInfo.WorkerDeploymentVersionSummary\x12/\n\x0b\x63reate_time\x18\x03 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x41\n\x0erouting_config\x18\x04 \x01(\x0b\x32).temporal.api.deployment.v1.RoutingConfig\x12\x1e\n\x16last_modifier_identity\x18\x05 \x01(\t\x12\x18\n\x10manager_identity\x18\x06 \x01(\t\x12T\n\x1brouting_config_update_state\x18\x07 \x01(\x0e\x32/.temporal.api.enums.v1.RoutingConfigUpdateState\x1a\xaa\x06\n\x1eWorkerDeploymentVersionSummary\x12\x13\n\x07version\x18\x01 \x01(\tB\x02\x18\x01\x12\x44\n\x06status\x18\x0b \x01(\x0e\x32\x34.temporal.api.enums.v1.WorkerDeploymentVersionStatus\x12O\n\x12\x64\x65ployment_version\x18\x04 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersion\x12/\n\x0b\x63reate_time\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x45\n\x0f\x64rainage_status\x18\x03 \x01(\x0e\x32,.temporal.api.enums.v1.VersionDrainageStatus\x12\x46\n\rdrainage_info\x18\x05 \x01(\x0b\x32/.temporal.api.deployment.v1.VersionDrainageInfo\x12\x36\n\x12\x63urrent_since_time\x18\x06 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x36\n\x12ramping_since_time\x18\x07 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x37\n\x13routing_update_time\x18\x08 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x39\n\x15\x66irst_activation_time\x18\t \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x35\n\x11last_current_time\x18\x0c \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12:\n\x16last_deactivation_time\x18\n \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x45\n\x0e\x63ompute_config\x18\r \x01(\x0b\x32-.temporal.api.compute.v1.ComputeConfigSummary"D\n\x17WorkerDeploymentVersion\x12\x10\n\x08\x62uild_id\x18\x01 \x01(\t\x12\x17\n\x0f\x64\x65ployment_name\x18\x02 \x01(\t"\xad\x01\n\x0fVersionMetadata\x12I\n\x07\x65ntries\x18\x01 \x03(\x0b\x32\x38.temporal.api.deployment.v1.VersionMetadata.EntriesEntry\x1aO\n\x0c\x45ntriesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12.\n\x05value\x18\x02 \x01(\x0b\x32\x1f.temporal.api.common.v1.Payload:\x02\x38\x01"\x89\x04\n\rRoutingConfig\x12W\n\x1a\x63urrent_deployment_version\x18\x07 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersion\x12\x1b\n\x0f\x63urrent_version\x18\x01 \x01(\tB\x02\x18\x01\x12W\n\x1aramping_deployment_version\x18\t \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersion\x12\x1b\n\x0framping_version\x18\x02 \x01(\tB\x02\x18\x01\x12"\n\x1aramping_version_percentage\x18\x03 \x01(\x02\x12@\n\x1c\x63urrent_version_changed_time\x18\x04 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12@\n\x1cramping_version_changed_time\x18\x05 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12K\n\'ramping_version_percentage_changed_time\x18\x06 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x17\n\x0frevision_number\x18\n \x01(\x03"\x8a\x02\n\x18InheritedAutoUpgradeInfo\x12V\n\x19source_deployment_version\x18\x01 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersion\x12)\n!source_deployment_revision_number\x18\x02 \x01(\x03\x12k\n+continue_as_new_initial_versioning_behavior\x18\x03 \x01(\x0e\x32\x36.temporal.api.enums.v1.ContinueAsNewVersioningBehaviorB\x9d\x01\n\x1dio.temporal.api.deployment.v1B\x0cMessageProtoP\x01Z+go.temporal.io/api/deployment/v1;deployment\xaa\x02\x1cTemporalio.Api.Deployment.V1\xea\x02\x1fTemporalio::Api::Deployment::V1b\x06proto3' + b'\n(temporal/api/deployment/v1/message.proto\x12\x1atemporal.api.deployment.v1\x1a\x1fgoogle/protobuf/timestamp.proto\x1a$temporal/api/enums/v1/workflow.proto\x1a&temporal/api/enums/v1/deployment.proto\x1a&temporal/api/enums/v1/task_queue.proto\x1a$temporal/api/common/v1/message.proto\x1a$temporal/api/compute/v1/config.proto"\x91\x01\n\x17WorkerDeploymentOptions\x12\x17\n\x0f\x64\x65ployment_name\x18\x01 \x01(\t\x12\x10\n\x08\x62uild_id\x18\x02 \x01(\t\x12K\n\x16worker_versioning_mode\x18\x03 \x01(\x0e\x32+.temporal.api.enums.v1.WorkerVersioningMode"3\n\nDeployment\x12\x13\n\x0bseries_name\x18\x01 \x01(\t\x12\x10\n\x08\x62uild_id\x18\x02 \x01(\t"\x8e\x04\n\x0e\x44\x65ploymentInfo\x12:\n\ndeployment\x18\x01 \x01(\x0b\x32&.temporal.api.deployment.v1.Deployment\x12/\n\x0b\x63reate_time\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12R\n\x10task_queue_infos\x18\x03 \x03(\x0b\x32\x38.temporal.api.deployment.v1.DeploymentInfo.TaskQueueInfo\x12J\n\x08metadata\x18\x04 \x03(\x0b\x32\x38.temporal.api.deployment.v1.DeploymentInfo.MetadataEntry\x12\x12\n\nis_current\x18\x05 \x01(\x08\x1aP\n\rMetadataEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12.\n\x05value\x18\x02 \x01(\x0b\x32\x1f.temporal.api.common.v1.Payload:\x02\x38\x01\x1a\x88\x01\n\rTaskQueueInfo\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x32\n\x04type\x18\x02 \x01(\x0e\x32$.temporal.api.enums.v1.TaskQueueType\x12\x35\n\x11\x66irst_poller_time\x18\x03 \x01(\x0b\x32\x1a.google.protobuf.Timestamp"\xea\x01\n\x18UpdateDeploymentMetadata\x12_\n\x0eupsert_entries\x18\x01 \x03(\x0b\x32G.temporal.api.deployment.v1.UpdateDeploymentMetadata.UpsertEntriesEntry\x12\x16\n\x0eremove_entries\x18\x02 \x03(\t\x1aU\n\x12UpsertEntriesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12.\n\x05value\x18\x02 \x01(\x0b\x32\x1f.temporal.api.common.v1.Payload:\x02\x38\x01"\x95\x01\n\x12\x44\x65ploymentListInfo\x12:\n\ndeployment\x18\x01 \x01(\x0b\x32&.temporal.api.deployment.v1.Deployment\x12/\n\x0b\x63reate_time\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x12\n\nis_current\x18\x03 \x01(\x08"\xad\x08\n\x1bWorkerDeploymentVersionInfo\x12\x13\n\x07version\x18\x01 \x01(\tB\x02\x18\x01\x12\x44\n\x06status\x18\x0e \x01(\x0e\x32\x34.temporal.api.enums.v1.WorkerDeploymentVersionStatus\x12O\n\x12\x64\x65ployment_version\x18\x0b \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersion\x12\x17\n\x0f\x64\x65ployment_name\x18\x02 \x01(\t\x12/\n\x0b\x63reate_time\x18\x03 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x38\n\x14routing_changed_time\x18\x04 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x36\n\x12\x63urrent_since_time\x18\x05 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x36\n\x12ramping_since_time\x18\x06 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x39\n\x15\x66irst_activation_time\x18\x0c \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x35\n\x11last_current_time\x18\x0f \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12:\n\x16last_deactivation_time\x18\r \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x17\n\x0framp_percentage\x18\x07 \x01(\x02\x12\x66\n\x10task_queue_infos\x18\x08 \x03(\x0b\x32L.temporal.api.deployment.v1.WorkerDeploymentVersionInfo.VersionTaskQueueInfo\x12\x46\n\rdrainage_info\x18\t \x01(\x0b\x32/.temporal.api.deployment.v1.VersionDrainageInfo\x12=\n\x08metadata\x18\n \x01(\x0b\x32+.temporal.api.deployment.v1.VersionMetadata\x12>\n\x0e\x63ompute_config\x18\x10 \x01(\x0b\x32&.temporal.api.compute.v1.ComputeConfig\x12\x1e\n\x16last_modifier_identity\x18\x11 \x01(\t\x1aX\n\x14VersionTaskQueueInfo\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x32\n\x04type\x18\x02 \x01(\x0e\x32$.temporal.api.enums.v1.TaskQueueType"\xc1\x01\n\x13VersionDrainageInfo\x12<\n\x06status\x18\x01 \x01(\x0e\x32,.temporal.api.enums.v1.VersionDrainageStatus\x12\x35\n\x11last_changed_time\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x35\n\x11last_checked_time\x18\x03 \x01(\x0b\x32\x1a.google.protobuf.Timestamp"\xd8\x01\n\rComputeStatus\x12_\n\x13provider_validation\x18\x01 \x01(\x0b\x32\x42.temporal.api.deployment.v1.ComputeStatus.ProviderValidationStatus\x1a\x66\n\x18ProviderValidationStatus\x12\x15\n\rerror_message\x18\x01 \x01(\t\x12\x33\n\x0flast_check_time\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.Timestamp"\x84\n\n\x14WorkerDeploymentInfo\x12\x0c\n\x04name\x18\x01 \x01(\t\x12j\n\x11version_summaries\x18\x02 \x03(\x0b\x32O.temporal.api.deployment.v1.WorkerDeploymentInfo.WorkerDeploymentVersionSummary\x12/\n\x0b\x63reate_time\x18\x03 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x41\n\x0erouting_config\x18\x04 \x01(\x0b\x32).temporal.api.deployment.v1.RoutingConfig\x12\x1e\n\x16last_modifier_identity\x18\x05 \x01(\t\x12\x18\n\x10manager_identity\x18\x06 \x01(\t\x12T\n\x1brouting_config_update_state\x18\x07 \x01(\x0e\x32/.temporal.api.enums.v1.RoutingConfigUpdateState\x1a\xed\x06\n\x1eWorkerDeploymentVersionSummary\x12\x13\n\x07version\x18\x01 \x01(\tB\x02\x18\x01\x12\x44\n\x06status\x18\x0b \x01(\x0e\x32\x34.temporal.api.enums.v1.WorkerDeploymentVersionStatus\x12O\n\x12\x64\x65ployment_version\x18\x04 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersion\x12/\n\x0b\x63reate_time\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x45\n\x0f\x64rainage_status\x18\x03 \x01(\x0e\x32,.temporal.api.enums.v1.VersionDrainageStatus\x12\x46\n\rdrainage_info\x18\x05 \x01(\x0b\x32/.temporal.api.deployment.v1.VersionDrainageInfo\x12\x36\n\x12\x63urrent_since_time\x18\x06 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x36\n\x12ramping_since_time\x18\x07 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x37\n\x13routing_update_time\x18\x08 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x39\n\x15\x66irst_activation_time\x18\t \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x35\n\x11last_current_time\x18\x0c \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12:\n\x16last_deactivation_time\x18\n \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x45\n\x0e\x63ompute_config\x18\r \x01(\x0b\x32-.temporal.api.compute.v1.ComputeConfigSummary\x12\x41\n\x0e\x63ompute_status\x18\x0e \x01(\x0b\x32).temporal.api.deployment.v1.ComputeStatus"D\n\x17WorkerDeploymentVersion\x12\x10\n\x08\x62uild_id\x18\x01 \x01(\t\x12\x17\n\x0f\x64\x65ployment_name\x18\x02 \x01(\t"\xad\x01\n\x0fVersionMetadata\x12I\n\x07\x65ntries\x18\x01 \x03(\x0b\x32\x38.temporal.api.deployment.v1.VersionMetadata.EntriesEntry\x1aO\n\x0c\x45ntriesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12.\n\x05value\x18\x02 \x01(\x0b\x32\x1f.temporal.api.common.v1.Payload:\x02\x38\x01"\x89\x04\n\rRoutingConfig\x12W\n\x1a\x63urrent_deployment_version\x18\x07 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersion\x12\x1b\n\x0f\x63urrent_version\x18\x01 \x01(\tB\x02\x18\x01\x12W\n\x1aramping_deployment_version\x18\t \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersion\x12\x1b\n\x0framping_version\x18\x02 \x01(\tB\x02\x18\x01\x12"\n\x1aramping_version_percentage\x18\x03 \x01(\x02\x12@\n\x1c\x63urrent_version_changed_time\x18\x04 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12@\n\x1cramping_version_changed_time\x18\x05 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12K\n\'ramping_version_percentage_changed_time\x18\x06 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x17\n\x0frevision_number\x18\n \x01(\x03"\x8a\x02\n\x18InheritedAutoUpgradeInfo\x12V\n\x19source_deployment_version\x18\x01 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersion\x12)\n!source_deployment_revision_number\x18\x02 \x01(\x03\x12k\n+continue_as_new_initial_versioning_behavior\x18\x03 \x01(\x0e\x32\x36.temporal.api.enums.v1.ContinueAsNewVersioningBehaviorB\x9d\x01\n\x1dio.temporal.api.deployment.v1B\x0cMessageProtoP\x01Z+go.temporal.io/api/deployment/v1;deployment\xaa\x02\x1cTemporalio.Api.Deployment.V1\xea\x02\x1fTemporalio::Api::Deployment::V1b\x06proto3' ) @@ -54,6 +54,10 @@ _WORKERDEPLOYMENTVERSIONINFO.nested_types_by_name["VersionTaskQueueInfo"] ) _VERSIONDRAINAGEINFO = DESCRIPTOR.message_types_by_name["VersionDrainageInfo"] +_COMPUTESTATUS = DESCRIPTOR.message_types_by_name["ComputeStatus"] +_COMPUTESTATUS_PROVIDERVALIDATIONSTATUS = _COMPUTESTATUS.nested_types_by_name[ + "ProviderValidationStatus" +] _WORKERDEPLOYMENTINFO = DESCRIPTOR.message_types_by_name["WorkerDeploymentInfo"] _WORKERDEPLOYMENTINFO_WORKERDEPLOYMENTVERSIONSUMMARY = ( _WORKERDEPLOYMENTINFO.nested_types_by_name["WorkerDeploymentVersionSummary"] @@ -180,6 +184,27 @@ ) _sym_db.RegisterMessage(VersionDrainageInfo) +ComputeStatus = _reflection.GeneratedProtocolMessageType( + "ComputeStatus", + (_message.Message,), + { + "ProviderValidationStatus": _reflection.GeneratedProtocolMessageType( + "ProviderValidationStatus", + (_message.Message,), + { + "DESCRIPTOR": _COMPUTESTATUS_PROVIDERVALIDATIONSTATUS, + "__module__": "temporalio.api.deployment.v1.message_pb2", + # @@protoc_insertion_point(class_scope:temporal.api.deployment.v1.ComputeStatus.ProviderValidationStatus) + }, + ), + "DESCRIPTOR": _COMPUTESTATUS, + "__module__": "temporalio.api.deployment.v1.message_pb2", + # @@protoc_insertion_point(class_scope:temporal.api.deployment.v1.ComputeStatus) + }, +) +_sym_db.RegisterMessage(ComputeStatus) +_sym_db.RegisterMessage(ComputeStatus.ProviderValidationStatus) + WorkerDeploymentInfo = _reflection.GeneratedProtocolMessageType( "WorkerDeploymentInfo", (_message.Message,), @@ -300,18 +325,22 @@ _WORKERDEPLOYMENTVERSIONINFO_VERSIONTASKQUEUEINFO._serialized_end = 2488 _VERSIONDRAINAGEINFO._serialized_start = 2491 _VERSIONDRAINAGEINFO._serialized_end = 2684 - _WORKERDEPLOYMENTINFO._serialized_start = 2687 - _WORKERDEPLOYMENTINFO._serialized_end = 3904 - _WORKERDEPLOYMENTINFO_WORKERDEPLOYMENTVERSIONSUMMARY._serialized_start = 3094 - _WORKERDEPLOYMENTINFO_WORKERDEPLOYMENTVERSIONSUMMARY._serialized_end = 3904 - _WORKERDEPLOYMENTVERSION._serialized_start = 3906 - _WORKERDEPLOYMENTVERSION._serialized_end = 3974 - _VERSIONMETADATA._serialized_start = 3977 - _VERSIONMETADATA._serialized_end = 4150 - _VERSIONMETADATA_ENTRIESENTRY._serialized_start = 4071 - _VERSIONMETADATA_ENTRIESENTRY._serialized_end = 4150 - _ROUTINGCONFIG._serialized_start = 4153 - _ROUTINGCONFIG._serialized_end = 4674 - _INHERITEDAUTOUPGRADEINFO._serialized_start = 4677 - _INHERITEDAUTOUPGRADEINFO._serialized_end = 4943 + _COMPUTESTATUS._serialized_start = 2687 + _COMPUTESTATUS._serialized_end = 2903 + _COMPUTESTATUS_PROVIDERVALIDATIONSTATUS._serialized_start = 2801 + _COMPUTESTATUS_PROVIDERVALIDATIONSTATUS._serialized_end = 2903 + _WORKERDEPLOYMENTINFO._serialized_start = 2906 + _WORKERDEPLOYMENTINFO._serialized_end = 4190 + _WORKERDEPLOYMENTINFO_WORKERDEPLOYMENTVERSIONSUMMARY._serialized_start = 3313 + _WORKERDEPLOYMENTINFO_WORKERDEPLOYMENTVERSIONSUMMARY._serialized_end = 4190 + _WORKERDEPLOYMENTVERSION._serialized_start = 4192 + _WORKERDEPLOYMENTVERSION._serialized_end = 4260 + _VERSIONMETADATA._serialized_start = 4263 + _VERSIONMETADATA._serialized_end = 4436 + _VERSIONMETADATA_ENTRIESENTRY._serialized_start = 4357 + _VERSIONMETADATA_ENTRIESENTRY._serialized_end = 4436 + _ROUTINGCONFIG._serialized_start = 4439 + _ROUTINGCONFIG._serialized_end = 4960 + _INHERITEDAUTOUPGRADEINFO._serialized_start = 4963 + _INHERITEDAUTOUPGRADEINFO._serialized_end = 5229 # @@protoc_insertion_point(module_scope) diff --git a/temporalio/api/deployment/v1/message_pb2.pyi b/temporalio/api/deployment/v1/message_pb2.pyi index 1b97a8db1..96f31edd1 100644 --- a/temporalio/api/deployment/v1/message_pb2.pyi +++ b/temporalio/api/deployment/v1/message_pb2.pyi @@ -614,6 +614,71 @@ class VersionDrainageInfo(google.protobuf.message.Message): global___VersionDrainageInfo = VersionDrainageInfo +class ComputeStatus(google.protobuf.message.Message): + """ComputeStatus represents compute-related configuration and health for a Worker Deployment Version.""" + + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + class ProviderValidationStatus(google.protobuf.message.Message): + """ProviderValidationStatus represents the result of the most recent + connectivity check between Temporal and a customer's compute provider. + """ + + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + ERROR_MESSAGE_FIELD_NUMBER: builtins.int + LAST_CHECK_TIME_FIELD_NUMBER: builtins.int + error_message: builtins.str + """Human-readable error message if connectivity validation failed. + An empty string means validation passed. + """ + @property + def last_check_time(self) -> google.protobuf.timestamp_pb2.Timestamp: + """Timestamp of the last validation check.""" + def __init__( + self, + *, + error_message: builtins.str = ..., + last_check_time: google.protobuf.timestamp_pb2.Timestamp | None = ..., + ) -> None: ... + def HasField( + self, + field_name: typing_extensions.Literal[ + "last_check_time", b"last_check_time" + ], + ) -> builtins.bool: ... + def ClearField( + self, + field_name: typing_extensions.Literal[ + "error_message", b"error_message", "last_check_time", b"last_check_time" + ], + ) -> None: ... + + PROVIDER_VALIDATION_FIELD_NUMBER: builtins.int + @property + def provider_validation(self) -> global___ComputeStatus.ProviderValidationStatus: + """provider_validation encapsulates the health signal for validating the compute provider.""" + def __init__( + self, + *, + provider_validation: global___ComputeStatus.ProviderValidationStatus + | None = ..., + ) -> None: ... + def HasField( + self, + field_name: typing_extensions.Literal[ + "provider_validation", b"provider_validation" + ], + ) -> builtins.bool: ... + def ClearField( + self, + field_name: typing_extensions.Literal[ + "provider_validation", b"provider_validation" + ], + ) -> None: ... + +global___ComputeStatus = ComputeStatus + class WorkerDeploymentInfo(google.protobuf.message.Message): """A Worker Deployment (Deployment, for short) represents all workers serving a shared set of Task Queues. Typically, a Deployment represents one service or @@ -642,6 +707,7 @@ class WorkerDeploymentInfo(google.protobuf.message.Message): LAST_CURRENT_TIME_FIELD_NUMBER: builtins.int LAST_DEACTIVATION_TIME_FIELD_NUMBER: builtins.int COMPUTE_CONFIG_FIELD_NUMBER: builtins.int + COMPUTE_STATUS_FIELD_NUMBER: builtins.int version: builtins.str """Deprecated. Use `deployment_version`.""" status: temporalio.api.enums.v1.deployment_pb2.WorkerDeploymentVersionStatus.ValueType @@ -692,6 +758,9 @@ class WorkerDeploymentInfo(google.protobuf.message.Message): def compute_config( self, ) -> temporalio.api.compute.v1.config_pb2.ComputeConfigSummary: ... + @property + def compute_status(self) -> global___ComputeStatus: + """ComputeStatus represents compute-related configuration and healthchecks.""" def __init__( self, *, @@ -710,12 +779,15 @@ class WorkerDeploymentInfo(google.protobuf.message.Message): | None = ..., compute_config: temporalio.api.compute.v1.config_pb2.ComputeConfigSummary | None = ..., + compute_status: global___ComputeStatus | None = ..., ) -> None: ... def HasField( self, field_name: typing_extensions.Literal[ "compute_config", b"compute_config", + "compute_status", + b"compute_status", "create_time", b"create_time", "current_since_time", @@ -741,6 +813,8 @@ class WorkerDeploymentInfo(google.protobuf.message.Message): field_name: typing_extensions.Literal[ "compute_config", b"compute_config", + "compute_status", + b"compute_status", "create_time", b"create_time", "current_since_time", diff --git a/temporalio/api/history/v1/message_pb2.py b/temporalio/api/history/v1/message_pb2.py index 3d3cd5132..a161b93d1 100644 --- a/temporalio/api/history/v1/message_pb2.py +++ b/temporalio/api/history/v1/message_pb2.py @@ -38,6 +38,9 @@ from temporalio.api.failure.v1 import ( message_pb2 as temporal_dot_api_dot_failure_dot_v1_dot_message__pb2, ) +from temporalio.api.sdk.v1 import ( + event_group_marker_pb2 as temporal_dot_api_dot_sdk_dot_v1_dot_event__group__marker__pb2, +) from temporalio.api.sdk.v1 import ( task_complete_metadata_pb2 as temporal_dot_api_dot_sdk_dot_v1_dot_task__complete__metadata__pb2, ) @@ -55,7 +58,7 @@ ) DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile( - b'\n%temporal/api/history/v1/message.proto\x12\x17temporal.api.history.v1\x1a\x1egoogle/protobuf/duration.proto\x1a\x1fgoogle/protobuf/timestamp.proto\x1a&temporal/api/enums/v1/event_type.proto\x1a(temporal/api/enums/v1/failed_cause.proto\x1a"temporal/api/enums/v1/update.proto\x1a$temporal/api/enums/v1/workflow.proto\x1a$temporal/api/common/v1/message.proto\x1a(temporal/api/deployment/v1/message.proto\x1a%temporal/api/failure/v1/message.proto\x1a\'temporal/api/taskqueue/v1/message.proto\x1a$temporal/api/update/v1/message.proto\x1a&temporal/api/workflow/v1/message.proto\x1a\x30temporal/api/sdk/v1/task_complete_metadata.proto\x1a\'temporal/api/sdk/v1/user_metadata.proto"\x9a\x12\n\'WorkflowExecutionStartedEventAttributes\x12;\n\rworkflow_type\x18\x01 \x01(\x0b\x32$.temporal.api.common.v1.WorkflowType\x12!\n\x19parent_workflow_namespace\x18\x02 \x01(\t\x12$\n\x1cparent_workflow_namespace_id\x18\x1b \x01(\t\x12L\n\x19parent_workflow_execution\x18\x03 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12!\n\x19parent_initiated_event_id\x18\x04 \x01(\x03\x12\x38\n\ntask_queue\x18\x05 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12/\n\x05input\x18\x06 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12=\n\x1aworkflow_execution_timeout\x18\x07 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x37\n\x14workflow_run_timeout\x18\x08 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x38\n\x15workflow_task_timeout\x18\t \x01(\x0b\x32\x19.google.protobuf.Duration\x12"\n\x1a\x63ontinued_execution_run_id\x18\n \x01(\t\x12@\n\tinitiator\x18\x0b \x01(\x0e\x32-.temporal.api.enums.v1.ContinueAsNewInitiator\x12;\n\x11\x63ontinued_failure\x18\x0c \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12@\n\x16last_completion_result\x18\r \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12!\n\x19original_execution_run_id\x18\x0e \x01(\t\x12\x10\n\x08identity\x18\x0f \x01(\t\x12\x1e\n\x16\x66irst_execution_run_id\x18\x10 \x01(\t\x12\x39\n\x0cretry_policy\x18\x11 \x01(\x0b\x32#.temporal.api.common.v1.RetryPolicy\x12\x0f\n\x07\x61ttempt\x18\x12 \x01(\x05\x12\x46\n"workflow_execution_expiration_time\x18\x13 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x15\n\rcron_schedule\x18\x14 \x01(\t\x12>\n\x1b\x66irst_workflow_task_backoff\x18\x15 \x01(\x0b\x32\x19.google.protobuf.Duration\x12*\n\x04memo\x18\x16 \x01(\x0b\x32\x1c.temporal.api.common.v1.Memo\x12\x43\n\x11search_attributes\x18\x17 \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes\x12\x45\n\x16prev_auto_reset_points\x18\x18 \x01(\x0b\x32%.temporal.api.workflow.v1.ResetPoints\x12.\n\x06header\x18\x19 \x01(\x0b\x32\x1e.temporal.api.common.v1.Header\x12&\n\x1eparent_initiated_event_version\x18\x1a \x01(\x03\x12\x13\n\x0bworkflow_id\x18\x1c \x01(\t\x12L\n\x14source_version_stamp\x18\x1d \x01(\x0b\x32*.temporal.api.common.v1.WorkerVersionStampB\x02\x18\x01\x12>\n\x14\x63ompletion_callbacks\x18\x1e \x03(\x0b\x32 .temporal.api.common.v1.Callback\x12J\n\x17root_workflow_execution\x18\x1f \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x1e\n\x12inherited_build_id\x18 \x01(\tB\x02\x18\x01\x12I\n\x13versioning_override\x18! \x01(\x0b\x32,.temporal.api.workflow.v1.VersioningOverride\x12\x33\n\'parent_pinned_worker_deployment_version\x18" \x01(\tB\x02\x18\x01\x12\x32\n\x08priority\x18# \x01(\x0b\x32 .temporal.api.common.v1.Priority\x12U\n\x18inherited_pinned_version\x18% \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersion\x12Y\n\x1binherited_auto_upgrade_info\x18\' \x01(\x0b\x32\x34.temporal.api.deployment.v1.InheritedAutoUpgradeInfo\x12 \n\x18\x65\x61ger_execution_accepted\x18& \x01(\x08\x12^\n\x1f\x64\x65\x63lined_target_version_upgrade\x18( \x01(\x0b\x32\x35.temporal.api.history.v1.DeclinedTargetVersionUpgrade\x12J\n\x14time_skipping_config\x18) \x01(\x0b\x32,.temporal.api.workflow.v1.TimeSkippingConfig\x12;\n\x18initial_skipped_duration\x18* \x01(\x0b\x32\x19.google.protobuf.DurationJ\x04\x08$\x10%R parent_pinned_deployment_version"\x88\x01\n\x1c\x44\x65\x63linedTargetVersionUpgrade\x12O\n\x12\x64\x65ployment_version\x18\x01 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersion\x12\x17\n\x0frevision_number\x18\x02 \x01(\x03"\xa5\x01\n)WorkflowExecutionCompletedEventAttributes\x12\x30\n\x06result\x18\x01 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12(\n workflow_task_completed_event_id\x18\x02 \x01(\x03\x12\x1c\n\x14new_execution_run_id\x18\x03 \x01(\t"\xdb\x01\n&WorkflowExecutionFailedEventAttributes\x12\x31\n\x07\x66\x61ilure\x18\x01 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12\x36\n\x0bretry_state\x18\x02 \x01(\x0e\x32!.temporal.api.enums.v1.RetryState\x12(\n workflow_task_completed_event_id\x18\x03 \x01(\x03\x12\x1c\n\x14new_execution_run_id\x18\x04 \x01(\t"\x80\x01\n(WorkflowExecutionTimedOutEventAttributes\x12\x36\n\x0bretry_state\x18\x01 \x01(\x0e\x32!.temporal.api.enums.v1.RetryState\x12\x1c\n\x14new_execution_run_id\x18\x02 \x01(\t"\xa5\x07\n.WorkflowExecutionContinuedAsNewEventAttributes\x12\x1c\n\x14new_execution_run_id\x18\x01 \x01(\t\x12;\n\rworkflow_type\x18\x02 \x01(\x0b\x32$.temporal.api.common.v1.WorkflowType\x12\x38\n\ntask_queue\x18\x03 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12/\n\x05input\x18\x04 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x37\n\x14workflow_run_timeout\x18\x05 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x38\n\x15workflow_task_timeout\x18\x06 \x01(\x0b\x32\x19.google.protobuf.Duration\x12(\n workflow_task_completed_event_id\x18\x07 \x01(\x03\x12\x39\n\x16\x62\x61\x63koff_start_interval\x18\x08 \x01(\x0b\x32\x19.google.protobuf.Duration\x12@\n\tinitiator\x18\t \x01(\x0e\x32-.temporal.api.enums.v1.ContinueAsNewInitiator\x12\x35\n\x07\x66\x61ilure\x18\n \x01(\x0b\x32 .temporal.api.failure.v1.FailureB\x02\x18\x01\x12@\n\x16last_completion_result\x18\x0b \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12.\n\x06header\x18\x0c \x01(\x0b\x32\x1e.temporal.api.common.v1.Header\x12*\n\x04memo\x18\r \x01(\x0b\x32\x1c.temporal.api.common.v1.Memo\x12\x43\n\x11search_attributes\x18\x0e \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes\x12\x1c\n\x10inherit_build_id\x18\x0f \x01(\x08\x42\x02\x18\x01\x12[\n\x1binitial_versioning_behavior\x18\x10 \x01(\x0e\x32\x36.temporal.api.enums.v1.ContinueAsNewVersioningBehavior"\xac\x01\n$WorkflowTaskScheduledEventAttributes\x12\x38\n\ntask_queue\x18\x01 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12\x39\n\x16start_to_close_timeout\x18\x02 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x0f\n\x07\x61ttempt\x18\x03 \x01(\x05"\xa0\x03\n"WorkflowTaskStartedEventAttributes\x12\x1a\n\x12scheduled_event_id\x18\x01 \x01(\x03\x12\x10\n\x08identity\x18\x02 \x01(\t\x12\x12\n\nrequest_id\x18\x03 \x01(\t\x12\x1f\n\x17suggest_continue_as_new\x18\x04 \x01(\x08\x12Z\n\x1fsuggest_continue_as_new_reasons\x18\x08 \x03(\x0e\x32\x31.temporal.api.enums.v1.SuggestContinueAsNewReason\x12\x30\n(target_worker_deployment_version_changed\x18\t \x01(\x08\x12\x1a\n\x12history_size_bytes\x18\x05 \x01(\x03\x12\x46\n\x0eworker_version\x18\x06 \x01(\x0b\x32*.temporal.api.common.v1.WorkerVersionStampB\x02\x18\x01\x12%\n\x19\x62uild_id_redirect_counter\x18\x07 \x01(\x03\x42\x02\x18\x01"\x82\x05\n$WorkflowTaskCompletedEventAttributes\x12\x1a\n\x12scheduled_event_id\x18\x01 \x01(\x03\x12\x18\n\x10started_event_id\x18\x02 \x01(\x03\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x1b\n\x0f\x62inary_checksum\x18\x04 \x01(\tB\x02\x18\x01\x12\x46\n\x0eworker_version\x18\x05 \x01(\x0b\x32*.temporal.api.common.v1.WorkerVersionStampB\x02\x18\x01\x12H\n\x0csdk_metadata\x18\x06 \x01(\x0b\x32\x32.temporal.api.sdk.v1.WorkflowTaskCompletedMetadata\x12\x43\n\x11metering_metadata\x18\r \x01(\x0b\x32(.temporal.api.common.v1.MeteringMetadata\x12>\n\ndeployment\x18\x07 \x01(\x0b\x32&.temporal.api.deployment.v1.DeploymentB\x02\x18\x01\x12\x46\n\x13versioning_behavior\x18\x08 \x01(\x0e\x32).temporal.api.enums.v1.VersioningBehavior\x12%\n\x19worker_deployment_version\x18\t \x01(\tB\x02\x18\x01\x12\x1e\n\x16worker_deployment_name\x18\n \x01(\t\x12O\n\x12\x64\x65ployment_version\x18\x0b \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersion"\x95\x01\n#WorkflowTaskTimedOutEventAttributes\x12\x1a\n\x12scheduled_event_id\x18\x01 \x01(\x03\x12\x18\n\x10started_event_id\x18\x02 \x01(\x03\x12\x38\n\x0ctimeout_type\x18\x03 \x01(\x0e\x32".temporal.api.enums.v1.TimeoutType"\x87\x03\n!WorkflowTaskFailedEventAttributes\x12\x1a\n\x12scheduled_event_id\x18\x01 \x01(\x03\x12\x18\n\x10started_event_id\x18\x02 \x01(\x03\x12=\n\x05\x63\x61use\x18\x03 \x01(\x0e\x32..temporal.api.enums.v1.WorkflowTaskFailedCause\x12\x31\n\x07\x66\x61ilure\x18\x04 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12\x10\n\x08identity\x18\x05 \x01(\t\x12\x13\n\x0b\x62\x61se_run_id\x18\x06 \x01(\t\x12\x12\n\nnew_run_id\x18\x07 \x01(\t\x12\x1a\n\x12\x66ork_event_version\x18\x08 \x01(\x03\x12\x1b\n\x0f\x62inary_checksum\x18\t \x01(\tB\x02\x18\x01\x12\x46\n\x0eworker_version\x18\n \x01(\x0b\x32*.temporal.api.common.v1.WorkerVersionStampB\x02\x18\x01"\xc2\x05\n$ActivityTaskScheduledEventAttributes\x12\x13\n\x0b\x61\x63tivity_id\x18\x01 \x01(\t\x12;\n\ractivity_type\x18\x02 \x01(\x0b\x32$.temporal.api.common.v1.ActivityType\x12\x38\n\ntask_queue\x18\x04 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12.\n\x06header\x18\x05 \x01(\x0b\x32\x1e.temporal.api.common.v1.Header\x12/\n\x05input\x18\x06 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12<\n\x19schedule_to_close_timeout\x18\x07 \x01(\x0b\x32\x19.google.protobuf.Duration\x12<\n\x19schedule_to_start_timeout\x18\x08 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x39\n\x16start_to_close_timeout\x18\t \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x34\n\x11heartbeat_timeout\x18\n \x01(\x0b\x32\x19.google.protobuf.Duration\x12(\n workflow_task_completed_event_id\x18\x0b \x01(\x03\x12\x39\n\x0cretry_policy\x18\x0c \x01(\x0b\x32#.temporal.api.common.v1.RetryPolicy\x12!\n\x15use_workflow_build_id\x18\r \x01(\x08\x42\x02\x18\x01\x12\x32\n\x08priority\x18\x0e \x01(\x0b\x32 .temporal.api.common.v1.PriorityJ\x04\x08\x03\x10\x04"\x9e\x02\n"ActivityTaskStartedEventAttributes\x12\x1a\n\x12scheduled_event_id\x18\x01 \x01(\x03\x12\x10\n\x08identity\x18\x02 \x01(\t\x12\x12\n\nrequest_id\x18\x03 \x01(\t\x12\x0f\n\x07\x61ttempt\x18\x04 \x01(\x05\x12\x36\n\x0clast_failure\x18\x05 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12\x46\n\x0eworker_version\x18\x06 \x01(\x0b\x32*.temporal.api.common.v1.WorkerVersionStampB\x02\x18\x01\x12%\n\x19\x62uild_id_redirect_counter\x18\x07 \x01(\x03\x42\x02\x18\x01"\xe8\x01\n$ActivityTaskCompletedEventAttributes\x12\x30\n\x06result\x18\x01 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x1a\n\x12scheduled_event_id\x18\x02 \x01(\x03\x12\x18\n\x10started_event_id\x18\x03 \x01(\x03\x12\x10\n\x08identity\x18\x04 \x01(\t\x12\x46\n\x0eworker_version\x18\x05 \x01(\x0b\x32*.temporal.api.common.v1.WorkerVersionStampB\x02\x18\x01"\x9e\x02\n!ActivityTaskFailedEventAttributes\x12\x31\n\x07\x66\x61ilure\x18\x01 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12\x1a\n\x12scheduled_event_id\x18\x02 \x01(\x03\x12\x18\n\x10started_event_id\x18\x03 \x01(\x03\x12\x10\n\x08identity\x18\x04 \x01(\t\x12\x36\n\x0bretry_state\x18\x05 \x01(\x0e\x32!.temporal.api.enums.v1.RetryState\x12\x46\n\x0eworker_version\x18\x06 \x01(\x0b\x32*.temporal.api.common.v1.WorkerVersionStampB\x02\x18\x01"\xc6\x01\n#ActivityTaskTimedOutEventAttributes\x12\x31\n\x07\x66\x61ilure\x18\x01 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12\x1a\n\x12scheduled_event_id\x18\x02 \x01(\x03\x12\x18\n\x10started_event_id\x18\x03 \x01(\x03\x12\x36\n\x0bretry_state\x18\x04 \x01(\x0e\x32!.temporal.api.enums.v1.RetryState"r\n*ActivityTaskCancelRequestedEventAttributes\x12\x1a\n\x12scheduled_event_id\x18\x01 \x01(\x03\x12(\n workflow_task_completed_event_id\x18\x02 \x01(\x03"\x92\x02\n#ActivityTaskCanceledEventAttributes\x12\x31\n\x07\x64\x65tails\x18\x01 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12(\n latest_cancel_requested_event_id\x18\x02 \x01(\x03\x12\x1a\n\x12scheduled_event_id\x18\x03 \x01(\x03\x12\x18\n\x10started_event_id\x18\x04 \x01(\x03\x12\x10\n\x08identity\x18\x05 \x01(\t\x12\x46\n\x0eworker_version\x18\x06 \x01(\x0b\x32*.temporal.api.common.v1.WorkerVersionStampB\x02\x18\x01"\x93\x01\n\x1bTimerStartedEventAttributes\x12\x10\n\x08timer_id\x18\x01 \x01(\t\x12\x38\n\x15start_to_fire_timeout\x18\x02 \x01(\x0b\x32\x19.google.protobuf.Duration\x12(\n workflow_task_completed_event_id\x18\x03 \x01(\x03"G\n\x19TimerFiredEventAttributes\x12\x10\n\x08timer_id\x18\x01 \x01(\t\x12\x18\n\x10started_event_id\x18\x02 \x01(\x03"\x86\x01\n\x1cTimerCanceledEventAttributes\x12\x10\n\x08timer_id\x18\x01 \x01(\t\x12\x18\n\x10started_event_id\x18\x02 \x01(\x03\x12(\n workflow_task_completed_event_id\x18\x03 \x01(\x03\x12\x10\n\x08identity\x18\x04 \x01(\t"\xc7\x01\n/WorkflowExecutionCancelRequestedEventAttributes\x12\r\n\x05\x63\x61use\x18\x01 \x01(\t\x12#\n\x1b\x65xternal_initiated_event_id\x18\x02 \x01(\x03\x12N\n\x1b\x65xternal_workflow_execution\x18\x03 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x10\n\x08identity\x18\x04 \x01(\t"\x87\x01\n(WorkflowExecutionCanceledEventAttributes\x12(\n workflow_task_completed_event_id\x18\x01 \x01(\x03\x12\x31\n\x07\x64\x65tails\x18\x02 \x01(\x0b\x32 .temporal.api.common.v1.Payloads"\xe9\x02\n\x1dMarkerRecordedEventAttributes\x12\x13\n\x0bmarker_name\x18\x01 \x01(\t\x12T\n\x07\x64\x65tails\x18\x02 \x03(\x0b\x32\x43.temporal.api.history.v1.MarkerRecordedEventAttributes.DetailsEntry\x12(\n workflow_task_completed_event_id\x18\x03 \x01(\x03\x12.\n\x06header\x18\x04 \x01(\x0b\x32\x1e.temporal.api.common.v1.Header\x12\x31\n\x07\x66\x61ilure\x18\x05 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x1aP\n\x0c\x44\x65tailsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12/\n\x05value\x18\x02 \x01(\x0b\x32 .temporal.api.common.v1.Payloads:\x02\x38\x01"\xbf\x02\n(WorkflowExecutionSignaledEventAttributes\x12\x13\n\x0bsignal_name\x18\x01 \x01(\t\x12/\n\x05input\x18\x02 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x10\n\x08identity\x18\x03 \x01(\t\x12.\n\x06header\x18\x04 \x01(\x0b\x32\x1e.temporal.api.common.v1.Header\x12\'\n\x1bskip_generate_workflow_task\x18\x05 \x01(\x08\x42\x02\x18\x01\x12N\n\x1b\x65xternal_workflow_execution\x18\x06 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x12\n\nrequest_id\x18\x07 \x01(\t"\x81\x01\n*WorkflowExecutionTerminatedEventAttributes\x12\x0e\n\x06reason\x18\x01 \x01(\t\x12\x31\n\x07\x64\x65tails\x18\x02 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x10\n\x08identity\x18\x03 \x01(\t"\x9c\x02\n>RequestCancelExternalWorkflowExecutionInitiatedEventAttributes\x12(\n workflow_task_completed_event_id\x18\x01 \x01(\x03\x12\x11\n\tnamespace\x18\x02 \x01(\t\x12\x14\n\x0cnamespace_id\x18\x07 \x01(\t\x12\x45\n\x12workflow_execution\x18\x03 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x13\n\x07\x63ontrol\x18\x04 \x01(\tB\x02\x18\x01\x12\x1b\n\x13\x63hild_workflow_only\x18\x05 \x01(\x08\x12\x0e\n\x06reason\x18\x06 \x01(\t"\xda\x02\n;RequestCancelExternalWorkflowExecutionFailedEventAttributes\x12P\n\x05\x63\x61use\x18\x01 \x01(\x0e\x32\x41.temporal.api.enums.v1.CancelExternalWorkflowExecutionFailedCause\x12(\n workflow_task_completed_event_id\x18\x02 \x01(\x03\x12\x11\n\tnamespace\x18\x03 \x01(\t\x12\x14\n\x0cnamespace_id\x18\x07 \x01(\t\x12\x45\n\x12workflow_execution\x18\x04 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x1a\n\x12initiated_event_id\x18\x05 \x01(\x03\x12\x13\n\x07\x63ontrol\x18\x06 \x01(\tB\x02\x18\x01"\xc5\x01\n7ExternalWorkflowExecutionCancelRequestedEventAttributes\x12\x1a\n\x12initiated_event_id\x18\x01 \x01(\x03\x12\x11\n\tnamespace\x18\x02 \x01(\t\x12\x14\n\x0cnamespace_id\x18\x04 \x01(\t\x12\x45\n\x12workflow_execution\x18\x03 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution"\xfb\x02\n7SignalExternalWorkflowExecutionInitiatedEventAttributes\x12(\n workflow_task_completed_event_id\x18\x01 \x01(\x03\x12\x11\n\tnamespace\x18\x02 \x01(\t\x12\x14\n\x0cnamespace_id\x18\t \x01(\t\x12\x45\n\x12workflow_execution\x18\x03 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x13\n\x0bsignal_name\x18\x04 \x01(\t\x12/\n\x05input\x18\x05 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x13\n\x07\x63ontrol\x18\x06 \x01(\tB\x02\x18\x01\x12\x1b\n\x13\x63hild_workflow_only\x18\x07 \x01(\x08\x12.\n\x06header\x18\x08 \x01(\x0b\x32\x1e.temporal.api.common.v1.Header"\xd3\x02\n4SignalExternalWorkflowExecutionFailedEventAttributes\x12P\n\x05\x63\x61use\x18\x01 \x01(\x0e\x32\x41.temporal.api.enums.v1.SignalExternalWorkflowExecutionFailedCause\x12(\n workflow_task_completed_event_id\x18\x02 \x01(\x03\x12\x11\n\tnamespace\x18\x03 \x01(\t\x12\x14\n\x0cnamespace_id\x18\x07 \x01(\t\x12\x45\n\x12workflow_execution\x18\x04 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x1a\n\x12initiated_event_id\x18\x05 \x01(\x03\x12\x13\n\x07\x63ontrol\x18\x06 \x01(\tB\x02\x18\x01"\xd3\x01\n0ExternalWorkflowExecutionSignaledEventAttributes\x12\x1a\n\x12initiated_event_id\x18\x01 \x01(\x03\x12\x11\n\tnamespace\x18\x02 \x01(\t\x12\x14\n\x0cnamespace_id\x18\x05 \x01(\t\x12\x45\n\x12workflow_execution\x18\x03 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x13\n\x07\x63ontrol\x18\x04 \x01(\tB\x02\x18\x01"\x9e\x01\n-UpsertWorkflowSearchAttributesEventAttributes\x12(\n workflow_task_completed_event_id\x18\x01 \x01(\x03\x12\x43\n\x11search_attributes\x18\x02 \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes"\x8a\x01\n)WorkflowPropertiesModifiedEventAttributes\x12(\n workflow_task_completed_event_id\x18\x01 \x01(\x03\x12\x33\n\rupserted_memo\x18\x02 \x01(\x0b\x32\x1c.temporal.api.common.v1.Memo"\xf1\x08\n3StartChildWorkflowExecutionInitiatedEventAttributes\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x14\n\x0cnamespace_id\x18\x12 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12;\n\rworkflow_type\x18\x03 \x01(\x0b\x32$.temporal.api.common.v1.WorkflowType\x12\x38\n\ntask_queue\x18\x04 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12/\n\x05input\x18\x05 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12=\n\x1aworkflow_execution_timeout\x18\x06 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x37\n\x14workflow_run_timeout\x18\x07 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x38\n\x15workflow_task_timeout\x18\x08 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x45\n\x13parent_close_policy\x18\t \x01(\x0e\x32(.temporal.api.enums.v1.ParentClosePolicy\x12\x13\n\x07\x63ontrol\x18\n \x01(\tB\x02\x18\x01\x12(\n workflow_task_completed_event_id\x18\x0b \x01(\x03\x12N\n\x18workflow_id_reuse_policy\x18\x0c \x01(\x0e\x32,.temporal.api.enums.v1.WorkflowIdReusePolicy\x12\x39\n\x0cretry_policy\x18\r \x01(\x0b\x32#.temporal.api.common.v1.RetryPolicy\x12\x15\n\rcron_schedule\x18\x0e \x01(\t\x12.\n\x06header\x18\x0f \x01(\x0b\x32\x1e.temporal.api.common.v1.Header\x12*\n\x04memo\x18\x10 \x01(\x0b\x32\x1c.temporal.api.common.v1.Memo\x12\x43\n\x11search_attributes\x18\x11 \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes\x12\x1c\n\x10inherit_build_id\x18\x13 \x01(\x08\x42\x02\x18\x01\x12\x32\n\x08priority\x18\x14 \x01(\x0b\x32 .temporal.api.common.v1.Priority\x12J\n\x14time_skipping_config\x18\x15 \x01(\x0b\x32,.temporal.api.workflow.v1.TimeSkippingConfig\x12;\n\x18initial_skipped_duration\x18\x1e \x01(\x0b\x32\x19.google.protobuf.Duration"\xd6\x02\n0StartChildWorkflowExecutionFailedEventAttributes\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x14\n\x0cnamespace_id\x18\x08 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12;\n\rworkflow_type\x18\x03 \x01(\x0b\x32$.temporal.api.common.v1.WorkflowType\x12L\n\x05\x63\x61use\x18\x04 \x01(\x0e\x32=.temporal.api.enums.v1.StartChildWorkflowExecutionFailedCause\x12\x13\n\x07\x63ontrol\x18\x05 \x01(\tB\x02\x18\x01\x12\x1a\n\x12initiated_event_id\x18\x06 \x01(\x03\x12(\n workflow_task_completed_event_id\x18\x07 \x01(\x03"\xa7\x02\n,ChildWorkflowExecutionStartedEventAttributes\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x14\n\x0cnamespace_id\x18\x06 \x01(\t\x12\x1a\n\x12initiated_event_id\x18\x02 \x01(\x03\x12\x45\n\x12workflow_execution\x18\x03 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12;\n\rworkflow_type\x18\x04 \x01(\x0b\x32$.temporal.api.common.v1.WorkflowType\x12.\n\x06header\x18\x05 \x01(\x0b\x32\x1e.temporal.api.common.v1.Header"\xc5\x02\n.ChildWorkflowExecutionCompletedEventAttributes\x12\x30\n\x06result\x18\x01 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x11\n\tnamespace\x18\x02 \x01(\t\x12\x14\n\x0cnamespace_id\x18\x07 \x01(\t\x12\x45\n\x12workflow_execution\x18\x03 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12;\n\rworkflow_type\x18\x04 \x01(\x0b\x32$.temporal.api.common.v1.WorkflowType\x12\x1a\n\x12initiated_event_id\x18\x05 \x01(\x03\x12\x18\n\x10started_event_id\x18\x06 \x01(\x03"\xfb\x02\n+ChildWorkflowExecutionFailedEventAttributes\x12\x31\n\x07\x66\x61ilure\x18\x01 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12\x11\n\tnamespace\x18\x02 \x01(\t\x12\x14\n\x0cnamespace_id\x18\x08 \x01(\t\x12\x45\n\x12workflow_execution\x18\x03 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12;\n\rworkflow_type\x18\x04 \x01(\x0b\x32$.temporal.api.common.v1.WorkflowType\x12\x1a\n\x12initiated_event_id\x18\x05 \x01(\x03\x12\x18\n\x10started_event_id\x18\x06 \x01(\x03\x12\x36\n\x0bretry_state\x18\x07 \x01(\x0e\x32!.temporal.api.enums.v1.RetryState"\xc5\x02\n-ChildWorkflowExecutionCanceledEventAttributes\x12\x31\n\x07\x64\x65tails\x18\x01 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x11\n\tnamespace\x18\x02 \x01(\t\x12\x14\n\x0cnamespace_id\x18\x07 \x01(\t\x12\x45\n\x12workflow_execution\x18\x03 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12;\n\rworkflow_type\x18\x04 \x01(\x0b\x32$.temporal.api.common.v1.WorkflowType\x12\x1a\n\x12initiated_event_id\x18\x05 \x01(\x03\x12\x18\n\x10started_event_id\x18\x06 \x01(\x03"\xca\x02\n-ChildWorkflowExecutionTimedOutEventAttributes\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x14\n\x0cnamespace_id\x18\x07 \x01(\t\x12\x45\n\x12workflow_execution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12;\n\rworkflow_type\x18\x03 \x01(\x0b\x32$.temporal.api.common.v1.WorkflowType\x12\x1a\n\x12initiated_event_id\x18\x04 \x01(\x03\x12\x18\n\x10started_event_id\x18\x05 \x01(\x03\x12\x36\n\x0bretry_state\x18\x06 \x01(\x0e\x32!.temporal.api.enums.v1.RetryState"\x94\x02\n/ChildWorkflowExecutionTerminatedEventAttributes\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x14\n\x0cnamespace_id\x18\x06 \x01(\t\x12\x45\n\x12workflow_execution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12;\n\rworkflow_type\x18\x03 \x01(\x0b\x32$.temporal.api.common.v1.WorkflowType\x12\x1a\n\x12initiated_event_id\x18\x04 \x01(\x03\x12\x18\n\x10started_event_id\x18\x05 \x01(\x03"\xb6\x05\n.WorkflowExecutionOptionsUpdatedEventAttributes\x12I\n\x13versioning_override\x18\x01 \x01(\x0b\x32,.temporal.api.workflow.v1.VersioningOverride\x12!\n\x19unset_versioning_override\x18\x02 \x01(\x08\x12\x1b\n\x13\x61ttached_request_id\x18\x03 \x01(\t\x12G\n\x1d\x61ttached_completion_callbacks\x18\x04 \x03(\x0b\x32 .temporal.api.common.v1.Callback\x12\x10\n\x08identity\x18\x05 \x01(\t\x12\x32\n\x08priority\x18\x06 \x01(\x0b\x32 .temporal.api.common.v1.Priority\x12J\n\x14time_skipping_config\x18\x07 \x01(\x0b\x32,.temporal.api.workflow.v1.TimeSkippingConfig\x12\x84\x01\n\x17workflow_update_options\x18\x08 \x03(\x0b\x32\x63.temporal.api.history.v1.WorkflowExecutionOptionsUpdatedEventAttributes.WorkflowUpdateOptionsUpdate\x1a\x96\x01\n\x1bWorkflowUpdateOptionsUpdate\x12\x11\n\tupdate_id\x18\x01 \x01(\t\x12\x1b\n\x13\x61ttached_request_id\x18\x02 \x01(\t\x12G\n\x1d\x61ttached_completion_callbacks\x18\x03 \x03(\x0b\x32 .temporal.api.common.v1.Callback"\xc0\x02\n3WorkflowPropertiesModifiedExternallyEventAttributes\x12\x16\n\x0enew_task_queue\x18\x01 \x01(\t\x12<\n\x19new_workflow_task_timeout\x18\x02 \x01(\x0b\x32\x19.google.protobuf.Duration\x12;\n\x18new_workflow_run_timeout\x18\x03 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x41\n\x1enew_workflow_execution_timeout\x18\x04 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x33\n\rupserted_memo\x18\x05 \x01(\x0b\x32\x1c.temporal.api.common.v1.Memo"\x90\x01\n3ActivityPropertiesModifiedExternallyEventAttributes\x12\x1a\n\x12scheduled_event_id\x18\x01 \x01(\x03\x12=\n\x10new_retry_policy\x18\x02 \x01(\x0b\x32#.temporal.api.common.v1.RetryPolicy"\xdc\x01\n.WorkflowExecutionUpdateAcceptedEventAttributes\x12\x1c\n\x14protocol_instance_id\x18\x01 \x01(\t\x12#\n\x1b\x61\x63\x63\x65pted_request_message_id\x18\x02 \x01(\t\x12,\n$accepted_request_sequencing_event_id\x18\x03 \x01(\x03\x12\x39\n\x10\x61\x63\x63\x65pted_request\x18\x04 \x01(\x0b\x32\x1f.temporal.api.update.v1.Request"\xaa\x01\n/WorkflowExecutionUpdateCompletedEventAttributes\x12*\n\x04meta\x18\x01 \x01(\x0b\x32\x1c.temporal.api.update.v1.Meta\x12\x19\n\x11\x61\x63\x63\x65pted_event_id\x18\x03 \x01(\x03\x12\x30\n\x07outcome\x18\x02 \x01(\x0b\x32\x1f.temporal.api.update.v1.Outcome"\x8f\x02\n.WorkflowExecutionUpdateRejectedEventAttributes\x12\x1c\n\x14protocol_instance_id\x18\x01 \x01(\t\x12#\n\x1brejected_request_message_id\x18\x02 \x01(\t\x12,\n$rejected_request_sequencing_event_id\x18\x03 \x01(\x03\x12\x39\n\x10rejected_request\x18\x04 \x01(\x0b\x32\x1f.temporal.api.update.v1.Request\x12\x31\n\x07\x66\x61ilure\x18\x05 \x01(\x0b\x32 .temporal.api.failure.v1.Failure"\xa4\x01\n.WorkflowExecutionUpdateAdmittedEventAttributes\x12\x30\n\x07request\x18\x01 \x01(\x0b\x32\x1f.temporal.api.update.v1.Request\x12@\n\x06origin\x18\x02 \x01(\x0e\x32\x30.temporal.api.enums.v1.UpdateAdmittedEventOrigin"^\n&WorkflowExecutionPausedEventAttributes\x12\x10\n\x08identity\x18\x01 \x01(\t\x12\x0e\n\x06reason\x18\x02 \x01(\t\x12\x12\n\nrequest_id\x18\x03 \x01(\t"`\n(WorkflowExecutionUnpausedEventAttributes\x12\x10\n\x08identity\x18\x01 \x01(\t\x12\x0e\n\x06reason\x18\x02 \x01(\t\x12\x12\n\nrequest_id\x18\x03 \x01(\t"\xbe\x01\n8WorkflowExecutionTimeSkippingTransitionedEventAttributes\x12/\n\x0btarget_time\x18\x01 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x1c\n\x14\x64isabled_after_bound\x18\x02 \x01(\x08\x12\x33\n\x0fwall_clock_time\x18\x03 \x01(\x0b\x32\x1a.google.protobuf.Timestamp"\xb4\x04\n&NexusOperationScheduledEventAttributes\x12\x10\n\x08\x65ndpoint\x18\x01 \x01(\t\x12\x0f\n\x07service\x18\x02 \x01(\t\x12\x11\n\toperation\x18\x03 \x01(\t\x12.\n\x05input\x18\x04 \x01(\x0b\x32\x1f.temporal.api.common.v1.Payload\x12<\n\x19schedule_to_close_timeout\x18\x05 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x66\n\x0cnexus_header\x18\x06 \x03(\x0b\x32P.temporal.api.history.v1.NexusOperationScheduledEventAttributes.NexusHeaderEntry\x12(\n workflow_task_completed_event_id\x18\x07 \x01(\x03\x12\x12\n\nrequest_id\x18\x08 \x01(\t\x12\x13\n\x0b\x65ndpoint_id\x18\t \x01(\t\x12<\n\x19schedule_to_start_timeout\x18\n \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x39\n\x16start_to_close_timeout\x18\x0b \x01(\x0b\x32\x19.google.protobuf.Duration\x1a\x32\n\x10NexusHeaderEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01"\x89\x01\n$NexusOperationStartedEventAttributes\x12\x1a\n\x12scheduled_event_id\x18\x01 \x01(\x03\x12\x18\n\x0coperation_id\x18\x03 \x01(\tB\x02\x18\x01\x12\x12\n\nrequest_id\x18\x04 \x01(\t\x12\x17\n\x0foperation_token\x18\x05 \x01(\t"\x89\x01\n&NexusOperationCompletedEventAttributes\x12\x1a\n\x12scheduled_event_id\x18\x01 \x01(\x03\x12/\n\x06result\x18\x02 \x01(\x0b\x32\x1f.temporal.api.common.v1.Payload\x12\x12\n\nrequest_id\x18\x03 \x01(\t"\x88\x01\n#NexusOperationFailedEventAttributes\x12\x1a\n\x12scheduled_event_id\x18\x01 \x01(\x03\x12\x31\n\x07\x66\x61ilure\x18\x02 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12\x12\n\nrequest_id\x18\x03 \x01(\t"\x8a\x01\n%NexusOperationTimedOutEventAttributes\x12\x1a\n\x12scheduled_event_id\x18\x01 \x01(\x03\x12\x31\n\x07\x66\x61ilure\x18\x02 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12\x12\n\nrequest_id\x18\x03 \x01(\t"\x8a\x01\n%NexusOperationCanceledEventAttributes\x12\x1a\n\x12scheduled_event_id\x18\x01 \x01(\x03\x12\x31\n\x07\x66\x61ilure\x18\x02 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12\x12\n\nrequest_id\x18\x03 \x01(\t"t\n,NexusOperationCancelRequestedEventAttributes\x12\x1a\n\x12scheduled_event_id\x18\x01 \x01(\x03\x12(\n workflow_task_completed_event_id\x18\x02 \x01(\x03"\x97\x01\n3NexusOperationCancelRequestCompletedEventAttributes\x12\x1a\n\x12requested_event_id\x18\x01 \x01(\x03\x12(\n workflow_task_completed_event_id\x18\x02 \x01(\x03\x12\x1a\n\x12scheduled_event_id\x18\x03 \x01(\x03"\xc7\x01\n0NexusOperationCancelRequestFailedEventAttributes\x12\x1a\n\x12requested_event_id\x18\x01 \x01(\x03\x12(\n workflow_task_completed_event_id\x18\x02 \x01(\x03\x12\x31\n\x07\x66\x61ilure\x18\x03 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12\x1a\n\x12scheduled_event_id\x18\x04 \x01(\x03"\x85?\n\x0cHistoryEvent\x12\x10\n\x08\x65vent_id\x18\x01 \x01(\x03\x12.\n\nevent_time\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x34\n\nevent_type\x18\x03 \x01(\x0e\x32 .temporal.api.enums.v1.EventType\x12\x0f\n\x07version\x18\x04 \x01(\x03\x12\x0f\n\x07task_id\x18\x05 \x01(\x03\x12\x1a\n\x11worker_may_ignore\x18\xac\x02 \x01(\x08\x12\x39\n\ruser_metadata\x18\xad\x02 \x01(\x0b\x32!.temporal.api.sdk.v1.UserMetadata\x12,\n\x05links\x18\xae\x02 \x03(\x0b\x32\x1c.temporal.api.common.v1.Link\x12\x35\n\tprincipal\x18\xaf\x02 \x01(\x0b\x32!.temporal.api.common.v1.Principal\x12w\n+workflow_execution_started_event_attributes\x18\x06 \x01(\x0b\x32@.temporal.api.history.v1.WorkflowExecutionStartedEventAttributesH\x00\x12{\n-workflow_execution_completed_event_attributes\x18\x07 \x01(\x0b\x32\x42.temporal.api.history.v1.WorkflowExecutionCompletedEventAttributesH\x00\x12u\n*workflow_execution_failed_event_attributes\x18\x08 \x01(\x0b\x32?.temporal.api.history.v1.WorkflowExecutionFailedEventAttributesH\x00\x12z\n-workflow_execution_timed_out_event_attributes\x18\t \x01(\x0b\x32\x41.temporal.api.history.v1.WorkflowExecutionTimedOutEventAttributesH\x00\x12q\n(workflow_task_scheduled_event_attributes\x18\n \x01(\x0b\x32=.temporal.api.history.v1.WorkflowTaskScheduledEventAttributesH\x00\x12m\n&workflow_task_started_event_attributes\x18\x0b \x01(\x0b\x32;.temporal.api.history.v1.WorkflowTaskStartedEventAttributesH\x00\x12q\n(workflow_task_completed_event_attributes\x18\x0c \x01(\x0b\x32=.temporal.api.history.v1.WorkflowTaskCompletedEventAttributesH\x00\x12p\n(workflow_task_timed_out_event_attributes\x18\r \x01(\x0b\x32<.temporal.api.history.v1.WorkflowTaskTimedOutEventAttributesH\x00\x12k\n%workflow_task_failed_event_attributes\x18\x0e \x01(\x0b\x32:.temporal.api.history.v1.WorkflowTaskFailedEventAttributesH\x00\x12q\n(activity_task_scheduled_event_attributes\x18\x0f \x01(\x0b\x32=.temporal.api.history.v1.ActivityTaskScheduledEventAttributesH\x00\x12m\n&activity_task_started_event_attributes\x18\x10 \x01(\x0b\x32;.temporal.api.history.v1.ActivityTaskStartedEventAttributesH\x00\x12q\n(activity_task_completed_event_attributes\x18\x11 \x01(\x0b\x32=.temporal.api.history.v1.ActivityTaskCompletedEventAttributesH\x00\x12k\n%activity_task_failed_event_attributes\x18\x12 \x01(\x0b\x32:.temporal.api.history.v1.ActivityTaskFailedEventAttributesH\x00\x12p\n(activity_task_timed_out_event_attributes\x18\x13 \x01(\x0b\x32<.temporal.api.history.v1.ActivityTaskTimedOutEventAttributesH\x00\x12^\n\x1etimer_started_event_attributes\x18\x14 \x01(\x0b\x32\x34.temporal.api.history.v1.TimerStartedEventAttributesH\x00\x12Z\n\x1ctimer_fired_event_attributes\x18\x15 \x01(\x0b\x32\x32.temporal.api.history.v1.TimerFiredEventAttributesH\x00\x12~\n/activity_task_cancel_requested_event_attributes\x18\x16 \x01(\x0b\x32\x43.temporal.api.history.v1.ActivityTaskCancelRequestedEventAttributesH\x00\x12o\n\'activity_task_canceled_event_attributes\x18\x17 \x01(\x0b\x32<.temporal.api.history.v1.ActivityTaskCanceledEventAttributesH\x00\x12`\n\x1ftimer_canceled_event_attributes\x18\x18 \x01(\x0b\x32\x35.temporal.api.history.v1.TimerCanceledEventAttributesH\x00\x12\x62\n marker_recorded_event_attributes\x18\x19 \x01(\x0b\x32\x36.temporal.api.history.v1.MarkerRecordedEventAttributesH\x00\x12y\n,workflow_execution_signaled_event_attributes\x18\x1a \x01(\x0b\x32\x41.temporal.api.history.v1.WorkflowExecutionSignaledEventAttributesH\x00\x12}\n.workflow_execution_terminated_event_attributes\x18\x1b \x01(\x0b\x32\x43.temporal.api.history.v1.WorkflowExecutionTerminatedEventAttributesH\x00\x12\x88\x01\n4workflow_execution_cancel_requested_event_attributes\x18\x1c \x01(\x0b\x32H.temporal.api.history.v1.WorkflowExecutionCancelRequestedEventAttributesH\x00\x12y\n,workflow_execution_canceled_event_attributes\x18\x1d \x01(\x0b\x32\x41.temporal.api.history.v1.WorkflowExecutionCanceledEventAttributesH\x00\x12\xa8\x01\nErequest_cancel_external_workflow_execution_initiated_event_attributes\x18\x1e \x01(\x0b\x32W.temporal.api.history.v1.RequestCancelExternalWorkflowExecutionInitiatedEventAttributesH\x00\x12\xa2\x01\nBrequest_cancel_external_workflow_execution_failed_event_attributes\x18\x1f \x01(\x0b\x32T.temporal.api.history.v1.RequestCancelExternalWorkflowExecutionFailedEventAttributesH\x00\x12\x99\x01\n=external_workflow_execution_cancel_requested_event_attributes\x18 \x01(\x0b\x32P.temporal.api.history.v1.ExternalWorkflowExecutionCancelRequestedEventAttributesH\x00\x12\x87\x01\n4workflow_execution_continued_as_new_event_attributes\x18! \x01(\x0b\x32G.temporal.api.history.v1.WorkflowExecutionContinuedAsNewEventAttributesH\x00\x12\x91\x01\n9start_child_workflow_execution_initiated_event_attributes\x18" \x01(\x0b\x32L.temporal.api.history.v1.StartChildWorkflowExecutionInitiatedEventAttributesH\x00\x12\x8b\x01\n6start_child_workflow_execution_failed_event_attributes\x18# \x01(\x0b\x32I.temporal.api.history.v1.StartChildWorkflowExecutionFailedEventAttributesH\x00\x12\x82\x01\n1child_workflow_execution_started_event_attributes\x18$ \x01(\x0b\x32\x45.temporal.api.history.v1.ChildWorkflowExecutionStartedEventAttributesH\x00\x12\x86\x01\n3child_workflow_execution_completed_event_attributes\x18% \x01(\x0b\x32G.temporal.api.history.v1.ChildWorkflowExecutionCompletedEventAttributesH\x00\x12\x80\x01\n0child_workflow_execution_failed_event_attributes\x18& \x01(\x0b\x32\x44.temporal.api.history.v1.ChildWorkflowExecutionFailedEventAttributesH\x00\x12\x84\x01\n2child_workflow_execution_canceled_event_attributes\x18\' \x01(\x0b\x32\x46.temporal.api.history.v1.ChildWorkflowExecutionCanceledEventAttributesH\x00\x12\x85\x01\n3child_workflow_execution_timed_out_event_attributes\x18( \x01(\x0b\x32\x46.temporal.api.history.v1.ChildWorkflowExecutionTimedOutEventAttributesH\x00\x12\x88\x01\n4child_workflow_execution_terminated_event_attributes\x18) \x01(\x0b\x32H.temporal.api.history.v1.ChildWorkflowExecutionTerminatedEventAttributesH\x00\x12\x99\x01\n=signal_external_workflow_execution_initiated_event_attributes\x18* \x01(\x0b\x32P.temporal.api.history.v1.SignalExternalWorkflowExecutionInitiatedEventAttributesH\x00\x12\x93\x01\n:signal_external_workflow_execution_failed_event_attributes\x18+ \x01(\x0b\x32M.temporal.api.history.v1.SignalExternalWorkflowExecutionFailedEventAttributesH\x00\x12\x8a\x01\n5external_workflow_execution_signaled_event_attributes\x18, \x01(\x0b\x32I.temporal.api.history.v1.ExternalWorkflowExecutionSignaledEventAttributesH\x00\x12\x84\x01\n2upsert_workflow_search_attributes_event_attributes\x18- \x01(\x0b\x32\x46.temporal.api.history.v1.UpsertWorkflowSearchAttributesEventAttributesH\x00\x12\x86\x01\n3workflow_execution_update_accepted_event_attributes\x18. \x01(\x0b\x32G.temporal.api.history.v1.WorkflowExecutionUpdateAcceptedEventAttributesH\x00\x12\x86\x01\n3workflow_execution_update_rejected_event_attributes\x18/ \x01(\x0b\x32G.temporal.api.history.v1.WorkflowExecutionUpdateRejectedEventAttributesH\x00\x12\x88\x01\n4workflow_execution_update_completed_event_attributes\x18\x30 \x01(\x0b\x32H.temporal.api.history.v1.WorkflowExecutionUpdateCompletedEventAttributesH\x00\x12\x90\x01\n8workflow_properties_modified_externally_event_attributes\x18\x31 \x01(\x0b\x32L.temporal.api.history.v1.WorkflowPropertiesModifiedExternallyEventAttributesH\x00\x12\x90\x01\n8activity_properties_modified_externally_event_attributes\x18\x32 \x01(\x0b\x32L.temporal.api.history.v1.ActivityPropertiesModifiedExternallyEventAttributesH\x00\x12{\n-workflow_properties_modified_event_attributes\x18\x33 \x01(\x0b\x32\x42.temporal.api.history.v1.WorkflowPropertiesModifiedEventAttributesH\x00\x12\x86\x01\n3workflow_execution_update_admitted_event_attributes\x18\x34 \x01(\x0b\x32G.temporal.api.history.v1.WorkflowExecutionUpdateAdmittedEventAttributesH\x00\x12u\n*nexus_operation_scheduled_event_attributes\x18\x35 \x01(\x0b\x32?.temporal.api.history.v1.NexusOperationScheduledEventAttributesH\x00\x12q\n(nexus_operation_started_event_attributes\x18\x36 \x01(\x0b\x32=.temporal.api.history.v1.NexusOperationStartedEventAttributesH\x00\x12u\n*nexus_operation_completed_event_attributes\x18\x37 \x01(\x0b\x32?.temporal.api.history.v1.NexusOperationCompletedEventAttributesH\x00\x12o\n\'nexus_operation_failed_event_attributes\x18\x38 \x01(\x0b\x32<.temporal.api.history.v1.NexusOperationFailedEventAttributesH\x00\x12s\n)nexus_operation_canceled_event_attributes\x18\x39 \x01(\x0b\x32>.temporal.api.history.v1.NexusOperationCanceledEventAttributesH\x00\x12t\n*nexus_operation_timed_out_event_attributes\x18: \x01(\x0b\x32>.temporal.api.history.v1.NexusOperationTimedOutEventAttributesH\x00\x12\x82\x01\n1nexus_operation_cancel_requested_event_attributes\x18; \x01(\x0b\x32\x45.temporal.api.history.v1.NexusOperationCancelRequestedEventAttributesH\x00\x12\x86\x01\n3workflow_execution_options_updated_event_attributes\x18< \x01(\x0b\x32G.temporal.api.history.v1.WorkflowExecutionOptionsUpdatedEventAttributesH\x00\x12\x91\x01\n9nexus_operation_cancel_request_completed_event_attributes\x18= \x01(\x0b\x32L.temporal.api.history.v1.NexusOperationCancelRequestCompletedEventAttributesH\x00\x12\x8b\x01\n6nexus_operation_cancel_request_failed_event_attributes\x18> \x01(\x0b\x32I.temporal.api.history.v1.NexusOperationCancelRequestFailedEventAttributesH\x00\x12u\n*workflow_execution_paused_event_attributes\x18? \x01(\x0b\x32?.temporal.api.history.v1.WorkflowExecutionPausedEventAttributesH\x00\x12y\n,workflow_execution_unpaused_event_attributes\x18@ \x01(\x0b\x32\x41.temporal.api.history.v1.WorkflowExecutionUnpausedEventAttributesH\x00\x12\x9b\x01\n>workflow_execution_time_skipping_transitioned_event_attributes\x18\x41 \x01(\x0b\x32Q.temporal.api.history.v1.WorkflowExecutionTimeSkippingTransitionedEventAttributesH\x00\x42\x0c\n\nattributes"@\n\x07History\x12\x35\n\x06\x65vents\x18\x01 \x03(\x0b\x32%.temporal.api.history.v1.HistoryEventB\x8e\x01\n\x1aio.temporal.api.history.v1B\x0cMessageProtoP\x01Z%go.temporal.io/api/history/v1;history\xaa\x02\x19Temporalio.Api.History.V1\xea\x02\x1cTemporalio::Api::History::V1b\x06proto3' + b'\n%temporal/api/history/v1/message.proto\x12\x17temporal.api.history.v1\x1a\x1egoogle/protobuf/duration.proto\x1a\x1fgoogle/protobuf/timestamp.proto\x1a&temporal/api/enums/v1/event_type.proto\x1a(temporal/api/enums/v1/failed_cause.proto\x1a"temporal/api/enums/v1/update.proto\x1a$temporal/api/enums/v1/workflow.proto\x1a$temporal/api/common/v1/message.proto\x1a(temporal/api/deployment/v1/message.proto\x1a%temporal/api/failure/v1/message.proto\x1a\'temporal/api/taskqueue/v1/message.proto\x1a$temporal/api/update/v1/message.proto\x1a&temporal/api/workflow/v1/message.proto\x1a\x30temporal/api/sdk/v1/task_complete_metadata.proto\x1a\'temporal/api/sdk/v1/user_metadata.proto\x1a,temporal/api/sdk/v1/event_group_marker.proto"\xda\x12\n\'WorkflowExecutionStartedEventAttributes\x12;\n\rworkflow_type\x18\x01 \x01(\x0b\x32$.temporal.api.common.v1.WorkflowType\x12!\n\x19parent_workflow_namespace\x18\x02 \x01(\t\x12$\n\x1cparent_workflow_namespace_id\x18\x1b \x01(\t\x12L\n\x19parent_workflow_execution\x18\x03 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12!\n\x19parent_initiated_event_id\x18\x04 \x01(\x03\x12\x38\n\ntask_queue\x18\x05 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12/\n\x05input\x18\x06 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12=\n\x1aworkflow_execution_timeout\x18\x07 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x37\n\x14workflow_run_timeout\x18\x08 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x38\n\x15workflow_task_timeout\x18\t \x01(\x0b\x32\x19.google.protobuf.Duration\x12"\n\x1a\x63ontinued_execution_run_id\x18\n \x01(\t\x12@\n\tinitiator\x18\x0b \x01(\x0e\x32-.temporal.api.enums.v1.ContinueAsNewInitiator\x12;\n\x11\x63ontinued_failure\x18\x0c \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12@\n\x16last_completion_result\x18\r \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12!\n\x19original_execution_run_id\x18\x0e \x01(\t\x12\x10\n\x08identity\x18\x0f \x01(\t\x12\x1e\n\x16\x66irst_execution_run_id\x18\x10 \x01(\t\x12\x39\n\x0cretry_policy\x18\x11 \x01(\x0b\x32#.temporal.api.common.v1.RetryPolicy\x12\x0f\n\x07\x61ttempt\x18\x12 \x01(\x05\x12\x46\n"workflow_execution_expiration_time\x18\x13 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x15\n\rcron_schedule\x18\x14 \x01(\t\x12>\n\x1b\x66irst_workflow_task_backoff\x18\x15 \x01(\x0b\x32\x19.google.protobuf.Duration\x12*\n\x04memo\x18\x16 \x01(\x0b\x32\x1c.temporal.api.common.v1.Memo\x12\x43\n\x11search_attributes\x18\x17 \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes\x12\x45\n\x16prev_auto_reset_points\x18\x18 \x01(\x0b\x32%.temporal.api.workflow.v1.ResetPoints\x12.\n\x06header\x18\x19 \x01(\x0b\x32\x1e.temporal.api.common.v1.Header\x12&\n\x1eparent_initiated_event_version\x18\x1a \x01(\x03\x12\x13\n\x0bworkflow_id\x18\x1c \x01(\t\x12L\n\x14source_version_stamp\x18\x1d \x01(\x0b\x32*.temporal.api.common.v1.WorkerVersionStampB\x02\x18\x01\x12>\n\x14\x63ompletion_callbacks\x18\x1e \x03(\x0b\x32 .temporal.api.common.v1.Callback\x12J\n\x17root_workflow_execution\x18\x1f \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x1e\n\x12inherited_build_id\x18 \x01(\tB\x02\x18\x01\x12I\n\x13versioning_override\x18! \x01(\x0b\x32,.temporal.api.workflow.v1.VersioningOverride\x12\x33\n\'parent_pinned_worker_deployment_version\x18" \x01(\tB\x02\x18\x01\x12\x32\n\x08priority\x18# \x01(\x0b\x32 .temporal.api.common.v1.Priority\x12U\n\x18inherited_pinned_version\x18% \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersion\x12Y\n\x1binherited_auto_upgrade_info\x18\' \x01(\x0b\x32\x34.temporal.api.deployment.v1.InheritedAutoUpgradeInfo\x12 \n\x18\x65\x61ger_execution_accepted\x18& \x01(\x08\x12^\n\x1f\x64\x65\x63lined_target_version_upgrade\x18( \x01(\x0b\x32\x35.temporal.api.history.v1.DeclinedTargetVersionUpgrade\x12H\n\x14time_skipping_config\x18) \x01(\x0b\x32*.temporal.api.common.v1.TimeSkippingConfig\x12]\n\x1ftime_skipping_state_propagation\x18+ \x01(\x0b\x32\x34.temporal.api.common.v1.TimeSkippingStatePropagationJ\x04\x08$\x10%J\x04\x08*\x10+R parent_pinned_deployment_versionR\x18initial_skipped_duration"\x88\x01\n\x1c\x44\x65\x63linedTargetVersionUpgrade\x12O\n\x12\x64\x65ployment_version\x18\x01 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersion\x12\x17\n\x0frevision_number\x18\x02 \x01(\x03"\xa5\x01\n)WorkflowExecutionCompletedEventAttributes\x12\x30\n\x06result\x18\x01 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12(\n workflow_task_completed_event_id\x18\x02 \x01(\x03\x12\x1c\n\x14new_execution_run_id\x18\x03 \x01(\t"\xdb\x01\n&WorkflowExecutionFailedEventAttributes\x12\x31\n\x07\x66\x61ilure\x18\x01 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12\x36\n\x0bretry_state\x18\x02 \x01(\x0e\x32!.temporal.api.enums.v1.RetryState\x12(\n workflow_task_completed_event_id\x18\x03 \x01(\x03\x12\x1c\n\x14new_execution_run_id\x18\x04 \x01(\t"\x80\x01\n(WorkflowExecutionTimedOutEventAttributes\x12\x36\n\x0bretry_state\x18\x01 \x01(\x0e\x32!.temporal.api.enums.v1.RetryState\x12\x1c\n\x14new_execution_run_id\x18\x02 \x01(\t"\xa5\x07\n.WorkflowExecutionContinuedAsNewEventAttributes\x12\x1c\n\x14new_execution_run_id\x18\x01 \x01(\t\x12;\n\rworkflow_type\x18\x02 \x01(\x0b\x32$.temporal.api.common.v1.WorkflowType\x12\x38\n\ntask_queue\x18\x03 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12/\n\x05input\x18\x04 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x37\n\x14workflow_run_timeout\x18\x05 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x38\n\x15workflow_task_timeout\x18\x06 \x01(\x0b\x32\x19.google.protobuf.Duration\x12(\n workflow_task_completed_event_id\x18\x07 \x01(\x03\x12\x39\n\x16\x62\x61\x63koff_start_interval\x18\x08 \x01(\x0b\x32\x19.google.protobuf.Duration\x12@\n\tinitiator\x18\t \x01(\x0e\x32-.temporal.api.enums.v1.ContinueAsNewInitiator\x12\x35\n\x07\x66\x61ilure\x18\n \x01(\x0b\x32 .temporal.api.failure.v1.FailureB\x02\x18\x01\x12@\n\x16last_completion_result\x18\x0b \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12.\n\x06header\x18\x0c \x01(\x0b\x32\x1e.temporal.api.common.v1.Header\x12*\n\x04memo\x18\r \x01(\x0b\x32\x1c.temporal.api.common.v1.Memo\x12\x43\n\x11search_attributes\x18\x0e \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes\x12\x1c\n\x10inherit_build_id\x18\x0f \x01(\x08\x42\x02\x18\x01\x12[\n\x1binitial_versioning_behavior\x18\x10 \x01(\x0e\x32\x36.temporal.api.enums.v1.ContinueAsNewVersioningBehavior"\xac\x01\n$WorkflowTaskScheduledEventAttributes\x12\x38\n\ntask_queue\x18\x01 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12\x39\n\x16start_to_close_timeout\x18\x02 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x0f\n\x07\x61ttempt\x18\x03 \x01(\x05"\xa0\x03\n"WorkflowTaskStartedEventAttributes\x12\x1a\n\x12scheduled_event_id\x18\x01 \x01(\x03\x12\x10\n\x08identity\x18\x02 \x01(\t\x12\x12\n\nrequest_id\x18\x03 \x01(\t\x12\x1f\n\x17suggest_continue_as_new\x18\x04 \x01(\x08\x12Z\n\x1fsuggest_continue_as_new_reasons\x18\x08 \x03(\x0e\x32\x31.temporal.api.enums.v1.SuggestContinueAsNewReason\x12\x30\n(target_worker_deployment_version_changed\x18\t \x01(\x08\x12\x1a\n\x12history_size_bytes\x18\x05 \x01(\x03\x12\x46\n\x0eworker_version\x18\x06 \x01(\x0b\x32*.temporal.api.common.v1.WorkerVersionStampB\x02\x18\x01\x12%\n\x19\x62uild_id_redirect_counter\x18\x07 \x01(\x03\x42\x02\x18\x01"\x82\x05\n$WorkflowTaskCompletedEventAttributes\x12\x1a\n\x12scheduled_event_id\x18\x01 \x01(\x03\x12\x18\n\x10started_event_id\x18\x02 \x01(\x03\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x1b\n\x0f\x62inary_checksum\x18\x04 \x01(\tB\x02\x18\x01\x12\x46\n\x0eworker_version\x18\x05 \x01(\x0b\x32*.temporal.api.common.v1.WorkerVersionStampB\x02\x18\x01\x12H\n\x0csdk_metadata\x18\x06 \x01(\x0b\x32\x32.temporal.api.sdk.v1.WorkflowTaskCompletedMetadata\x12\x43\n\x11metering_metadata\x18\r \x01(\x0b\x32(.temporal.api.common.v1.MeteringMetadata\x12>\n\ndeployment\x18\x07 \x01(\x0b\x32&.temporal.api.deployment.v1.DeploymentB\x02\x18\x01\x12\x46\n\x13versioning_behavior\x18\x08 \x01(\x0e\x32).temporal.api.enums.v1.VersioningBehavior\x12%\n\x19worker_deployment_version\x18\t \x01(\tB\x02\x18\x01\x12\x1e\n\x16worker_deployment_name\x18\n \x01(\t\x12O\n\x12\x64\x65ployment_version\x18\x0b \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersion"\x95\x01\n#WorkflowTaskTimedOutEventAttributes\x12\x1a\n\x12scheduled_event_id\x18\x01 \x01(\x03\x12\x18\n\x10started_event_id\x18\x02 \x01(\x03\x12\x38\n\x0ctimeout_type\x18\x03 \x01(\x0e\x32".temporal.api.enums.v1.TimeoutType"\x87\x03\n!WorkflowTaskFailedEventAttributes\x12\x1a\n\x12scheduled_event_id\x18\x01 \x01(\x03\x12\x18\n\x10started_event_id\x18\x02 \x01(\x03\x12=\n\x05\x63\x61use\x18\x03 \x01(\x0e\x32..temporal.api.enums.v1.WorkflowTaskFailedCause\x12\x31\n\x07\x66\x61ilure\x18\x04 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12\x10\n\x08identity\x18\x05 \x01(\t\x12\x13\n\x0b\x62\x61se_run_id\x18\x06 \x01(\t\x12\x12\n\nnew_run_id\x18\x07 \x01(\t\x12\x1a\n\x12\x66ork_event_version\x18\x08 \x01(\x03\x12\x1b\n\x0f\x62inary_checksum\x18\t \x01(\tB\x02\x18\x01\x12\x46\n\x0eworker_version\x18\n \x01(\x0b\x32*.temporal.api.common.v1.WorkerVersionStampB\x02\x18\x01"\xc2\x05\n$ActivityTaskScheduledEventAttributes\x12\x13\n\x0b\x61\x63tivity_id\x18\x01 \x01(\t\x12;\n\ractivity_type\x18\x02 \x01(\x0b\x32$.temporal.api.common.v1.ActivityType\x12\x38\n\ntask_queue\x18\x04 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12.\n\x06header\x18\x05 \x01(\x0b\x32\x1e.temporal.api.common.v1.Header\x12/\n\x05input\x18\x06 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12<\n\x19schedule_to_close_timeout\x18\x07 \x01(\x0b\x32\x19.google.protobuf.Duration\x12<\n\x19schedule_to_start_timeout\x18\x08 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x39\n\x16start_to_close_timeout\x18\t \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x34\n\x11heartbeat_timeout\x18\n \x01(\x0b\x32\x19.google.protobuf.Duration\x12(\n workflow_task_completed_event_id\x18\x0b \x01(\x03\x12\x39\n\x0cretry_policy\x18\x0c \x01(\x0b\x32#.temporal.api.common.v1.RetryPolicy\x12!\n\x15use_workflow_build_id\x18\r \x01(\x08\x42\x02\x18\x01\x12\x32\n\x08priority\x18\x0e \x01(\x0b\x32 .temporal.api.common.v1.PriorityJ\x04\x08\x03\x10\x04"\x9e\x02\n"ActivityTaskStartedEventAttributes\x12\x1a\n\x12scheduled_event_id\x18\x01 \x01(\x03\x12\x10\n\x08identity\x18\x02 \x01(\t\x12\x12\n\nrequest_id\x18\x03 \x01(\t\x12\x0f\n\x07\x61ttempt\x18\x04 \x01(\x05\x12\x36\n\x0clast_failure\x18\x05 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12\x46\n\x0eworker_version\x18\x06 \x01(\x0b\x32*.temporal.api.common.v1.WorkerVersionStampB\x02\x18\x01\x12%\n\x19\x62uild_id_redirect_counter\x18\x07 \x01(\x03\x42\x02\x18\x01"\xe8\x01\n$ActivityTaskCompletedEventAttributes\x12\x30\n\x06result\x18\x01 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x1a\n\x12scheduled_event_id\x18\x02 \x01(\x03\x12\x18\n\x10started_event_id\x18\x03 \x01(\x03\x12\x10\n\x08identity\x18\x04 \x01(\t\x12\x46\n\x0eworker_version\x18\x05 \x01(\x0b\x32*.temporal.api.common.v1.WorkerVersionStampB\x02\x18\x01"\x9e\x02\n!ActivityTaskFailedEventAttributes\x12\x31\n\x07\x66\x61ilure\x18\x01 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12\x1a\n\x12scheduled_event_id\x18\x02 \x01(\x03\x12\x18\n\x10started_event_id\x18\x03 \x01(\x03\x12\x10\n\x08identity\x18\x04 \x01(\t\x12\x36\n\x0bretry_state\x18\x05 \x01(\x0e\x32!.temporal.api.enums.v1.RetryState\x12\x46\n\x0eworker_version\x18\x06 \x01(\x0b\x32*.temporal.api.common.v1.WorkerVersionStampB\x02\x18\x01"\xc6\x01\n#ActivityTaskTimedOutEventAttributes\x12\x31\n\x07\x66\x61ilure\x18\x01 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12\x1a\n\x12scheduled_event_id\x18\x02 \x01(\x03\x12\x18\n\x10started_event_id\x18\x03 \x01(\x03\x12\x36\n\x0bretry_state\x18\x04 \x01(\x0e\x32!.temporal.api.enums.v1.RetryState"r\n*ActivityTaskCancelRequestedEventAttributes\x12\x1a\n\x12scheduled_event_id\x18\x01 \x01(\x03\x12(\n workflow_task_completed_event_id\x18\x02 \x01(\x03"\x92\x02\n#ActivityTaskCanceledEventAttributes\x12\x31\n\x07\x64\x65tails\x18\x01 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12(\n latest_cancel_requested_event_id\x18\x02 \x01(\x03\x12\x1a\n\x12scheduled_event_id\x18\x03 \x01(\x03\x12\x18\n\x10started_event_id\x18\x04 \x01(\x03\x12\x10\n\x08identity\x18\x05 \x01(\t\x12\x46\n\x0eworker_version\x18\x06 \x01(\x0b\x32*.temporal.api.common.v1.WorkerVersionStampB\x02\x18\x01"\x93\x01\n\x1bTimerStartedEventAttributes\x12\x10\n\x08timer_id\x18\x01 \x01(\t\x12\x38\n\x15start_to_fire_timeout\x18\x02 \x01(\x0b\x32\x19.google.protobuf.Duration\x12(\n workflow_task_completed_event_id\x18\x03 \x01(\x03"G\n\x19TimerFiredEventAttributes\x12\x10\n\x08timer_id\x18\x01 \x01(\t\x12\x18\n\x10started_event_id\x18\x02 \x01(\x03"\x86\x01\n\x1cTimerCanceledEventAttributes\x12\x10\n\x08timer_id\x18\x01 \x01(\t\x12\x18\n\x10started_event_id\x18\x02 \x01(\x03\x12(\n workflow_task_completed_event_id\x18\x03 \x01(\x03\x12\x10\n\x08identity\x18\x04 \x01(\t"\xc7\x01\n/WorkflowExecutionCancelRequestedEventAttributes\x12\r\n\x05\x63\x61use\x18\x01 \x01(\t\x12#\n\x1b\x65xternal_initiated_event_id\x18\x02 \x01(\x03\x12N\n\x1b\x65xternal_workflow_execution\x18\x03 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x10\n\x08identity\x18\x04 \x01(\t"\x87\x01\n(WorkflowExecutionCanceledEventAttributes\x12(\n workflow_task_completed_event_id\x18\x01 \x01(\x03\x12\x31\n\x07\x64\x65tails\x18\x02 \x01(\x0b\x32 .temporal.api.common.v1.Payloads"\xe9\x02\n\x1dMarkerRecordedEventAttributes\x12\x13\n\x0bmarker_name\x18\x01 \x01(\t\x12T\n\x07\x64\x65tails\x18\x02 \x03(\x0b\x32\x43.temporal.api.history.v1.MarkerRecordedEventAttributes.DetailsEntry\x12(\n workflow_task_completed_event_id\x18\x03 \x01(\x03\x12.\n\x06header\x18\x04 \x01(\x0b\x32\x1e.temporal.api.common.v1.Header\x12\x31\n\x07\x66\x61ilure\x18\x05 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x1aP\n\x0c\x44\x65tailsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12/\n\x05value\x18\x02 \x01(\x0b\x32 .temporal.api.common.v1.Payloads:\x02\x38\x01"\xbf\x02\n(WorkflowExecutionSignaledEventAttributes\x12\x13\n\x0bsignal_name\x18\x01 \x01(\t\x12/\n\x05input\x18\x02 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x10\n\x08identity\x18\x03 \x01(\t\x12.\n\x06header\x18\x04 \x01(\x0b\x32\x1e.temporal.api.common.v1.Header\x12\'\n\x1bskip_generate_workflow_task\x18\x05 \x01(\x08\x42\x02\x18\x01\x12N\n\x1b\x65xternal_workflow_execution\x18\x06 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x12\n\nrequest_id\x18\x07 \x01(\t"\x81\x01\n*WorkflowExecutionTerminatedEventAttributes\x12\x0e\n\x06reason\x18\x01 \x01(\t\x12\x31\n\x07\x64\x65tails\x18\x02 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x10\n\x08identity\x18\x03 \x01(\t"\x9c\x02\n>RequestCancelExternalWorkflowExecutionInitiatedEventAttributes\x12(\n workflow_task_completed_event_id\x18\x01 \x01(\x03\x12\x11\n\tnamespace\x18\x02 \x01(\t\x12\x14\n\x0cnamespace_id\x18\x07 \x01(\t\x12\x45\n\x12workflow_execution\x18\x03 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x13\n\x07\x63ontrol\x18\x04 \x01(\tB\x02\x18\x01\x12\x1b\n\x13\x63hild_workflow_only\x18\x05 \x01(\x08\x12\x0e\n\x06reason\x18\x06 \x01(\t"\xda\x02\n;RequestCancelExternalWorkflowExecutionFailedEventAttributes\x12P\n\x05\x63\x61use\x18\x01 \x01(\x0e\x32\x41.temporal.api.enums.v1.CancelExternalWorkflowExecutionFailedCause\x12(\n workflow_task_completed_event_id\x18\x02 \x01(\x03\x12\x11\n\tnamespace\x18\x03 \x01(\t\x12\x14\n\x0cnamespace_id\x18\x07 \x01(\t\x12\x45\n\x12workflow_execution\x18\x04 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x1a\n\x12initiated_event_id\x18\x05 \x01(\x03\x12\x13\n\x07\x63ontrol\x18\x06 \x01(\tB\x02\x18\x01"\xc5\x01\n7ExternalWorkflowExecutionCancelRequestedEventAttributes\x12\x1a\n\x12initiated_event_id\x18\x01 \x01(\x03\x12\x11\n\tnamespace\x18\x02 \x01(\t\x12\x14\n\x0cnamespace_id\x18\x04 \x01(\t\x12\x45\n\x12workflow_execution\x18\x03 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution"\xfb\x02\n7SignalExternalWorkflowExecutionInitiatedEventAttributes\x12(\n workflow_task_completed_event_id\x18\x01 \x01(\x03\x12\x11\n\tnamespace\x18\x02 \x01(\t\x12\x14\n\x0cnamespace_id\x18\t \x01(\t\x12\x45\n\x12workflow_execution\x18\x03 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x13\n\x0bsignal_name\x18\x04 \x01(\t\x12/\n\x05input\x18\x05 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x13\n\x07\x63ontrol\x18\x06 \x01(\tB\x02\x18\x01\x12\x1b\n\x13\x63hild_workflow_only\x18\x07 \x01(\x08\x12.\n\x06header\x18\x08 \x01(\x0b\x32\x1e.temporal.api.common.v1.Header"\xd3\x02\n4SignalExternalWorkflowExecutionFailedEventAttributes\x12P\n\x05\x63\x61use\x18\x01 \x01(\x0e\x32\x41.temporal.api.enums.v1.SignalExternalWorkflowExecutionFailedCause\x12(\n workflow_task_completed_event_id\x18\x02 \x01(\x03\x12\x11\n\tnamespace\x18\x03 \x01(\t\x12\x14\n\x0cnamespace_id\x18\x07 \x01(\t\x12\x45\n\x12workflow_execution\x18\x04 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x1a\n\x12initiated_event_id\x18\x05 \x01(\x03\x12\x13\n\x07\x63ontrol\x18\x06 \x01(\tB\x02\x18\x01"\xd3\x01\n0ExternalWorkflowExecutionSignaledEventAttributes\x12\x1a\n\x12initiated_event_id\x18\x01 \x01(\x03\x12\x11\n\tnamespace\x18\x02 \x01(\t\x12\x14\n\x0cnamespace_id\x18\x05 \x01(\t\x12\x45\n\x12workflow_execution\x18\x03 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x13\n\x07\x63ontrol\x18\x04 \x01(\tB\x02\x18\x01"\x9e\x01\n-UpsertWorkflowSearchAttributesEventAttributes\x12(\n workflow_task_completed_event_id\x18\x01 \x01(\x03\x12\x43\n\x11search_attributes\x18\x02 \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes"\x8a\x01\n)WorkflowPropertiesModifiedEventAttributes\x12(\n workflow_task_completed_event_id\x18\x01 \x01(\x03\x12\x33\n\rupserted_memo\x18\x02 \x01(\x0b\x32\x1c.temporal.api.common.v1.Memo"\xb1\t\n3StartChildWorkflowExecutionInitiatedEventAttributes\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x14\n\x0cnamespace_id\x18\x12 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12;\n\rworkflow_type\x18\x03 \x01(\x0b\x32$.temporal.api.common.v1.WorkflowType\x12\x38\n\ntask_queue\x18\x04 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12/\n\x05input\x18\x05 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12=\n\x1aworkflow_execution_timeout\x18\x06 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x37\n\x14workflow_run_timeout\x18\x07 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x38\n\x15workflow_task_timeout\x18\x08 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x45\n\x13parent_close_policy\x18\t \x01(\x0e\x32(.temporal.api.enums.v1.ParentClosePolicy\x12\x13\n\x07\x63ontrol\x18\n \x01(\tB\x02\x18\x01\x12(\n workflow_task_completed_event_id\x18\x0b \x01(\x03\x12N\n\x18workflow_id_reuse_policy\x18\x0c \x01(\x0e\x32,.temporal.api.enums.v1.WorkflowIdReusePolicy\x12\x39\n\x0cretry_policy\x18\r \x01(\x0b\x32#.temporal.api.common.v1.RetryPolicy\x12\x15\n\rcron_schedule\x18\x0e \x01(\t\x12.\n\x06header\x18\x0f \x01(\x0b\x32\x1e.temporal.api.common.v1.Header\x12*\n\x04memo\x18\x10 \x01(\x0b\x32\x1c.temporal.api.common.v1.Memo\x12\x43\n\x11search_attributes\x18\x11 \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes\x12\x1c\n\x10inherit_build_id\x18\x13 \x01(\x08\x42\x02\x18\x01\x12\x32\n\x08priority\x18\x14 \x01(\x0b\x32 .temporal.api.common.v1.Priority\x12H\n\x14time_skipping_config\x18\x15 \x01(\x0b\x32*.temporal.api.common.v1.TimeSkippingConfig\x12]\n\x1ftime_skipping_state_propagation\x18\x17 \x01(\x0b\x32\x34.temporal.api.common.v1.TimeSkippingStatePropagationJ\x04\x08\x16\x10\x17R\x18initial_skipped_duration"\xd6\x02\n0StartChildWorkflowExecutionFailedEventAttributes\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x14\n\x0cnamespace_id\x18\x08 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12;\n\rworkflow_type\x18\x03 \x01(\x0b\x32$.temporal.api.common.v1.WorkflowType\x12L\n\x05\x63\x61use\x18\x04 \x01(\x0e\x32=.temporal.api.enums.v1.StartChildWorkflowExecutionFailedCause\x12\x13\n\x07\x63ontrol\x18\x05 \x01(\tB\x02\x18\x01\x12\x1a\n\x12initiated_event_id\x18\x06 \x01(\x03\x12(\n workflow_task_completed_event_id\x18\x07 \x01(\x03"\xa7\x02\n,ChildWorkflowExecutionStartedEventAttributes\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x14\n\x0cnamespace_id\x18\x06 \x01(\t\x12\x1a\n\x12initiated_event_id\x18\x02 \x01(\x03\x12\x45\n\x12workflow_execution\x18\x03 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12;\n\rworkflow_type\x18\x04 \x01(\x0b\x32$.temporal.api.common.v1.WorkflowType\x12.\n\x06header\x18\x05 \x01(\x0b\x32\x1e.temporal.api.common.v1.Header"\xc5\x02\n.ChildWorkflowExecutionCompletedEventAttributes\x12\x30\n\x06result\x18\x01 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x11\n\tnamespace\x18\x02 \x01(\t\x12\x14\n\x0cnamespace_id\x18\x07 \x01(\t\x12\x45\n\x12workflow_execution\x18\x03 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12;\n\rworkflow_type\x18\x04 \x01(\x0b\x32$.temporal.api.common.v1.WorkflowType\x12\x1a\n\x12initiated_event_id\x18\x05 \x01(\x03\x12\x18\n\x10started_event_id\x18\x06 \x01(\x03"\xfb\x02\n+ChildWorkflowExecutionFailedEventAttributes\x12\x31\n\x07\x66\x61ilure\x18\x01 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12\x11\n\tnamespace\x18\x02 \x01(\t\x12\x14\n\x0cnamespace_id\x18\x08 \x01(\t\x12\x45\n\x12workflow_execution\x18\x03 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12;\n\rworkflow_type\x18\x04 \x01(\x0b\x32$.temporal.api.common.v1.WorkflowType\x12\x1a\n\x12initiated_event_id\x18\x05 \x01(\x03\x12\x18\n\x10started_event_id\x18\x06 \x01(\x03\x12\x36\n\x0bretry_state\x18\x07 \x01(\x0e\x32!.temporal.api.enums.v1.RetryState"\xc5\x02\n-ChildWorkflowExecutionCanceledEventAttributes\x12\x31\n\x07\x64\x65tails\x18\x01 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x11\n\tnamespace\x18\x02 \x01(\t\x12\x14\n\x0cnamespace_id\x18\x07 \x01(\t\x12\x45\n\x12workflow_execution\x18\x03 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12;\n\rworkflow_type\x18\x04 \x01(\x0b\x32$.temporal.api.common.v1.WorkflowType\x12\x1a\n\x12initiated_event_id\x18\x05 \x01(\x03\x12\x18\n\x10started_event_id\x18\x06 \x01(\x03"\xca\x02\n-ChildWorkflowExecutionTimedOutEventAttributes\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x14\n\x0cnamespace_id\x18\x07 \x01(\t\x12\x45\n\x12workflow_execution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12;\n\rworkflow_type\x18\x03 \x01(\x0b\x32$.temporal.api.common.v1.WorkflowType\x12\x1a\n\x12initiated_event_id\x18\x04 \x01(\x03\x12\x18\n\x10started_event_id\x18\x05 \x01(\x03\x12\x36\n\x0bretry_state\x18\x06 \x01(\x0e\x32!.temporal.api.enums.v1.RetryState"\x94\x02\n/ChildWorkflowExecutionTerminatedEventAttributes\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x14\n\x0cnamespace_id\x18\x06 \x01(\t\x12\x45\n\x12workflow_execution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12;\n\rworkflow_type\x18\x03 \x01(\x0b\x32$.temporal.api.common.v1.WorkflowType\x12\x1a\n\x12initiated_event_id\x18\x04 \x01(\x03\x12\x18\n\x10started_event_id\x18\x05 \x01(\x03"\xda\x05\n.WorkflowExecutionOptionsUpdatedEventAttributes\x12I\n\x13versioning_override\x18\x01 \x01(\x0b\x32,.temporal.api.workflow.v1.VersioningOverride\x12!\n\x19unset_versioning_override\x18\x02 \x01(\x08\x12\x1b\n\x13\x61ttached_request_id\x18\x03 \x01(\t\x12G\n\x1d\x61ttached_completion_callbacks\x18\x04 \x03(\x0b\x32 .temporal.api.common.v1.Callback\x12\x10\n\x08identity\x18\x05 \x01(\t\x12\x32\n\x08priority\x18\x06 \x01(\x0b\x32 .temporal.api.common.v1.Priority\x12H\n\x14time_skipping_config\x18\x07 \x01(\x0b\x32*.temporal.api.common.v1.TimeSkippingConfig\x12$\n\x1ctime_skipping_config_updated\x18\t \x01(\x08\x12\x84\x01\n\x17workflow_update_options\x18\x08 \x03(\x0b\x32\x63.temporal.api.history.v1.WorkflowExecutionOptionsUpdatedEventAttributes.WorkflowUpdateOptionsUpdate\x1a\x96\x01\n\x1bWorkflowUpdateOptionsUpdate\x12\x11\n\tupdate_id\x18\x01 \x01(\t\x12\x1b\n\x13\x61ttached_request_id\x18\x02 \x01(\t\x12G\n\x1d\x61ttached_completion_callbacks\x18\x03 \x03(\x0b\x32 .temporal.api.common.v1.Callback"\xc0\x02\n3WorkflowPropertiesModifiedExternallyEventAttributes\x12\x16\n\x0enew_task_queue\x18\x01 \x01(\t\x12<\n\x19new_workflow_task_timeout\x18\x02 \x01(\x0b\x32\x19.google.protobuf.Duration\x12;\n\x18new_workflow_run_timeout\x18\x03 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x41\n\x1enew_workflow_execution_timeout\x18\x04 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x33\n\rupserted_memo\x18\x05 \x01(\x0b\x32\x1c.temporal.api.common.v1.Memo"\x90\x01\n3ActivityPropertiesModifiedExternallyEventAttributes\x12\x1a\n\x12scheduled_event_id\x18\x01 \x01(\x03\x12=\n\x10new_retry_policy\x18\x02 \x01(\x0b\x32#.temporal.api.common.v1.RetryPolicy"\xdc\x01\n.WorkflowExecutionUpdateAcceptedEventAttributes\x12\x1c\n\x14protocol_instance_id\x18\x01 \x01(\t\x12#\n\x1b\x61\x63\x63\x65pted_request_message_id\x18\x02 \x01(\t\x12,\n$accepted_request_sequencing_event_id\x18\x03 \x01(\x03\x12\x39\n\x10\x61\x63\x63\x65pted_request\x18\x04 \x01(\x0b\x32\x1f.temporal.api.update.v1.Request"\xaa\x01\n/WorkflowExecutionUpdateCompletedEventAttributes\x12*\n\x04meta\x18\x01 \x01(\x0b\x32\x1c.temporal.api.update.v1.Meta\x12\x19\n\x11\x61\x63\x63\x65pted_event_id\x18\x03 \x01(\x03\x12\x30\n\x07outcome\x18\x02 \x01(\x0b\x32\x1f.temporal.api.update.v1.Outcome"\x8f\x02\n.WorkflowExecutionUpdateRejectedEventAttributes\x12\x1c\n\x14protocol_instance_id\x18\x01 \x01(\t\x12#\n\x1brejected_request_message_id\x18\x02 \x01(\t\x12,\n$rejected_request_sequencing_event_id\x18\x03 \x01(\x03\x12\x39\n\x10rejected_request\x18\x04 \x01(\x0b\x32\x1f.temporal.api.update.v1.Request\x12\x31\n\x07\x66\x61ilure\x18\x05 \x01(\x0b\x32 .temporal.api.failure.v1.Failure"\xa4\x01\n.WorkflowExecutionUpdateAdmittedEventAttributes\x12\x30\n\x07request\x18\x01 \x01(\x0b\x32\x1f.temporal.api.update.v1.Request\x12@\n\x06origin\x18\x02 \x01(\x0e\x32\x30.temporal.api.enums.v1.UpdateAdmittedEventOrigin"^\n&WorkflowExecutionPausedEventAttributes\x12\x10\n\x08identity\x18\x01 \x01(\t\x12\x0e\n\x06reason\x18\x02 \x01(\t\x12\x12\n\nrequest_id\x18\x03 \x01(\t"`\n(WorkflowExecutionUnpausedEventAttributes\x12\x10\n\x08identity\x18\x01 \x01(\t\x12\x0e\n\x06reason\x18\x02 \x01(\t\x12\x12\n\nrequest_id\x18\x03 \x01(\t"\xc5\x01\n8WorkflowExecutionTimeSkippingTransitionedEventAttributes\x12/\n\x0btarget_time\x18\x01 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12#\n\x1b\x64isabled_after_fast_forward\x18\x02 \x01(\x08\x12\x33\n\x0fwall_clock_time\x18\x03 \x01(\x0b\x32\x1a.google.protobuf.Timestamp"\xb4\x04\n&NexusOperationScheduledEventAttributes\x12\x10\n\x08\x65ndpoint\x18\x01 \x01(\t\x12\x0f\n\x07service\x18\x02 \x01(\t\x12\x11\n\toperation\x18\x03 \x01(\t\x12.\n\x05input\x18\x04 \x01(\x0b\x32\x1f.temporal.api.common.v1.Payload\x12<\n\x19schedule_to_close_timeout\x18\x05 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x66\n\x0cnexus_header\x18\x06 \x03(\x0b\x32P.temporal.api.history.v1.NexusOperationScheduledEventAttributes.NexusHeaderEntry\x12(\n workflow_task_completed_event_id\x18\x07 \x01(\x03\x12\x12\n\nrequest_id\x18\x08 \x01(\t\x12\x13\n\x0b\x65ndpoint_id\x18\t \x01(\t\x12<\n\x19schedule_to_start_timeout\x18\n \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x39\n\x16start_to_close_timeout\x18\x0b \x01(\x0b\x32\x19.google.protobuf.Duration\x1a\x32\n\x10NexusHeaderEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01"\x89\x01\n$NexusOperationStartedEventAttributes\x12\x1a\n\x12scheduled_event_id\x18\x01 \x01(\x03\x12\x18\n\x0coperation_id\x18\x03 \x01(\tB\x02\x18\x01\x12\x12\n\nrequest_id\x18\x04 \x01(\t\x12\x17\n\x0foperation_token\x18\x05 \x01(\t"\x89\x01\n&NexusOperationCompletedEventAttributes\x12\x1a\n\x12scheduled_event_id\x18\x01 \x01(\x03\x12/\n\x06result\x18\x02 \x01(\x0b\x32\x1f.temporal.api.common.v1.Payload\x12\x12\n\nrequest_id\x18\x03 \x01(\t"\x88\x01\n#NexusOperationFailedEventAttributes\x12\x1a\n\x12scheduled_event_id\x18\x01 \x01(\x03\x12\x31\n\x07\x66\x61ilure\x18\x02 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12\x12\n\nrequest_id\x18\x03 \x01(\t"\x8a\x01\n%NexusOperationTimedOutEventAttributes\x12\x1a\n\x12scheduled_event_id\x18\x01 \x01(\x03\x12\x31\n\x07\x66\x61ilure\x18\x02 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12\x12\n\nrequest_id\x18\x03 \x01(\t"\x8a\x01\n%NexusOperationCanceledEventAttributes\x12\x1a\n\x12scheduled_event_id\x18\x01 \x01(\x03\x12\x31\n\x07\x66\x61ilure\x18\x02 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12\x12\n\nrequest_id\x18\x03 \x01(\t"t\n,NexusOperationCancelRequestedEventAttributes\x12\x1a\n\x12scheduled_event_id\x18\x01 \x01(\x03\x12(\n workflow_task_completed_event_id\x18\x02 \x01(\x03"\x97\x01\n3NexusOperationCancelRequestCompletedEventAttributes\x12\x1a\n\x12requested_event_id\x18\x01 \x01(\x03\x12(\n workflow_task_completed_event_id\x18\x02 \x01(\x03\x12\x1a\n\x12scheduled_event_id\x18\x03 \x01(\x03"\xc7\x01\n0NexusOperationCancelRequestFailedEventAttributes\x12\x1a\n\x12requested_event_id\x18\x01 \x01(\x03\x12(\n workflow_task_completed_event_id\x18\x02 \x01(\x03\x12\x31\n\x07\x66\x61ilure\x18\x03 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12\x1a\n\x12scheduled_event_id\x18\x04 \x01(\x03"\xca?\n\x0cHistoryEvent\x12\x10\n\x08\x65vent_id\x18\x01 \x01(\x03\x12.\n\nevent_time\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x34\n\nevent_type\x18\x03 \x01(\x0e\x32 .temporal.api.enums.v1.EventType\x12\x0f\n\x07version\x18\x04 \x01(\x03\x12\x0f\n\x07task_id\x18\x05 \x01(\x03\x12\x1a\n\x11worker_may_ignore\x18\xac\x02 \x01(\x08\x12\x39\n\ruser_metadata\x18\xad\x02 \x01(\x0b\x32!.temporal.api.sdk.v1.UserMetadata\x12,\n\x05links\x18\xae\x02 \x03(\x0b\x32\x1c.temporal.api.common.v1.Link\x12\x35\n\tprincipal\x18\xaf\x02 \x01(\x0b\x32!.temporal.api.common.v1.Principal\x12\x43\n\x13\x65vent_group_markers\x18\xb0\x02 \x03(\x0b\x32%.temporal.api.sdk.v1.EventGroupMarker\x12w\n+workflow_execution_started_event_attributes\x18\x06 \x01(\x0b\x32@.temporal.api.history.v1.WorkflowExecutionStartedEventAttributesH\x00\x12{\n-workflow_execution_completed_event_attributes\x18\x07 \x01(\x0b\x32\x42.temporal.api.history.v1.WorkflowExecutionCompletedEventAttributesH\x00\x12u\n*workflow_execution_failed_event_attributes\x18\x08 \x01(\x0b\x32?.temporal.api.history.v1.WorkflowExecutionFailedEventAttributesH\x00\x12z\n-workflow_execution_timed_out_event_attributes\x18\t \x01(\x0b\x32\x41.temporal.api.history.v1.WorkflowExecutionTimedOutEventAttributesH\x00\x12q\n(workflow_task_scheduled_event_attributes\x18\n \x01(\x0b\x32=.temporal.api.history.v1.WorkflowTaskScheduledEventAttributesH\x00\x12m\n&workflow_task_started_event_attributes\x18\x0b \x01(\x0b\x32;.temporal.api.history.v1.WorkflowTaskStartedEventAttributesH\x00\x12q\n(workflow_task_completed_event_attributes\x18\x0c \x01(\x0b\x32=.temporal.api.history.v1.WorkflowTaskCompletedEventAttributesH\x00\x12p\n(workflow_task_timed_out_event_attributes\x18\r \x01(\x0b\x32<.temporal.api.history.v1.WorkflowTaskTimedOutEventAttributesH\x00\x12k\n%workflow_task_failed_event_attributes\x18\x0e \x01(\x0b\x32:.temporal.api.history.v1.WorkflowTaskFailedEventAttributesH\x00\x12q\n(activity_task_scheduled_event_attributes\x18\x0f \x01(\x0b\x32=.temporal.api.history.v1.ActivityTaskScheduledEventAttributesH\x00\x12m\n&activity_task_started_event_attributes\x18\x10 \x01(\x0b\x32;.temporal.api.history.v1.ActivityTaskStartedEventAttributesH\x00\x12q\n(activity_task_completed_event_attributes\x18\x11 \x01(\x0b\x32=.temporal.api.history.v1.ActivityTaskCompletedEventAttributesH\x00\x12k\n%activity_task_failed_event_attributes\x18\x12 \x01(\x0b\x32:.temporal.api.history.v1.ActivityTaskFailedEventAttributesH\x00\x12p\n(activity_task_timed_out_event_attributes\x18\x13 \x01(\x0b\x32<.temporal.api.history.v1.ActivityTaskTimedOutEventAttributesH\x00\x12^\n\x1etimer_started_event_attributes\x18\x14 \x01(\x0b\x32\x34.temporal.api.history.v1.TimerStartedEventAttributesH\x00\x12Z\n\x1ctimer_fired_event_attributes\x18\x15 \x01(\x0b\x32\x32.temporal.api.history.v1.TimerFiredEventAttributesH\x00\x12~\n/activity_task_cancel_requested_event_attributes\x18\x16 \x01(\x0b\x32\x43.temporal.api.history.v1.ActivityTaskCancelRequestedEventAttributesH\x00\x12o\n\'activity_task_canceled_event_attributes\x18\x17 \x01(\x0b\x32<.temporal.api.history.v1.ActivityTaskCanceledEventAttributesH\x00\x12`\n\x1ftimer_canceled_event_attributes\x18\x18 \x01(\x0b\x32\x35.temporal.api.history.v1.TimerCanceledEventAttributesH\x00\x12\x62\n marker_recorded_event_attributes\x18\x19 \x01(\x0b\x32\x36.temporal.api.history.v1.MarkerRecordedEventAttributesH\x00\x12y\n,workflow_execution_signaled_event_attributes\x18\x1a \x01(\x0b\x32\x41.temporal.api.history.v1.WorkflowExecutionSignaledEventAttributesH\x00\x12}\n.workflow_execution_terminated_event_attributes\x18\x1b \x01(\x0b\x32\x43.temporal.api.history.v1.WorkflowExecutionTerminatedEventAttributesH\x00\x12\x88\x01\n4workflow_execution_cancel_requested_event_attributes\x18\x1c \x01(\x0b\x32H.temporal.api.history.v1.WorkflowExecutionCancelRequestedEventAttributesH\x00\x12y\n,workflow_execution_canceled_event_attributes\x18\x1d \x01(\x0b\x32\x41.temporal.api.history.v1.WorkflowExecutionCanceledEventAttributesH\x00\x12\xa8\x01\nErequest_cancel_external_workflow_execution_initiated_event_attributes\x18\x1e \x01(\x0b\x32W.temporal.api.history.v1.RequestCancelExternalWorkflowExecutionInitiatedEventAttributesH\x00\x12\xa2\x01\nBrequest_cancel_external_workflow_execution_failed_event_attributes\x18\x1f \x01(\x0b\x32T.temporal.api.history.v1.RequestCancelExternalWorkflowExecutionFailedEventAttributesH\x00\x12\x99\x01\n=external_workflow_execution_cancel_requested_event_attributes\x18 \x01(\x0b\x32P.temporal.api.history.v1.ExternalWorkflowExecutionCancelRequestedEventAttributesH\x00\x12\x87\x01\n4workflow_execution_continued_as_new_event_attributes\x18! \x01(\x0b\x32G.temporal.api.history.v1.WorkflowExecutionContinuedAsNewEventAttributesH\x00\x12\x91\x01\n9start_child_workflow_execution_initiated_event_attributes\x18" \x01(\x0b\x32L.temporal.api.history.v1.StartChildWorkflowExecutionInitiatedEventAttributesH\x00\x12\x8b\x01\n6start_child_workflow_execution_failed_event_attributes\x18# \x01(\x0b\x32I.temporal.api.history.v1.StartChildWorkflowExecutionFailedEventAttributesH\x00\x12\x82\x01\n1child_workflow_execution_started_event_attributes\x18$ \x01(\x0b\x32\x45.temporal.api.history.v1.ChildWorkflowExecutionStartedEventAttributesH\x00\x12\x86\x01\n3child_workflow_execution_completed_event_attributes\x18% \x01(\x0b\x32G.temporal.api.history.v1.ChildWorkflowExecutionCompletedEventAttributesH\x00\x12\x80\x01\n0child_workflow_execution_failed_event_attributes\x18& \x01(\x0b\x32\x44.temporal.api.history.v1.ChildWorkflowExecutionFailedEventAttributesH\x00\x12\x84\x01\n2child_workflow_execution_canceled_event_attributes\x18\' \x01(\x0b\x32\x46.temporal.api.history.v1.ChildWorkflowExecutionCanceledEventAttributesH\x00\x12\x85\x01\n3child_workflow_execution_timed_out_event_attributes\x18( \x01(\x0b\x32\x46.temporal.api.history.v1.ChildWorkflowExecutionTimedOutEventAttributesH\x00\x12\x88\x01\n4child_workflow_execution_terminated_event_attributes\x18) \x01(\x0b\x32H.temporal.api.history.v1.ChildWorkflowExecutionTerminatedEventAttributesH\x00\x12\x99\x01\n=signal_external_workflow_execution_initiated_event_attributes\x18* \x01(\x0b\x32P.temporal.api.history.v1.SignalExternalWorkflowExecutionInitiatedEventAttributesH\x00\x12\x93\x01\n:signal_external_workflow_execution_failed_event_attributes\x18+ \x01(\x0b\x32M.temporal.api.history.v1.SignalExternalWorkflowExecutionFailedEventAttributesH\x00\x12\x8a\x01\n5external_workflow_execution_signaled_event_attributes\x18, \x01(\x0b\x32I.temporal.api.history.v1.ExternalWorkflowExecutionSignaledEventAttributesH\x00\x12\x84\x01\n2upsert_workflow_search_attributes_event_attributes\x18- \x01(\x0b\x32\x46.temporal.api.history.v1.UpsertWorkflowSearchAttributesEventAttributesH\x00\x12\x86\x01\n3workflow_execution_update_accepted_event_attributes\x18. \x01(\x0b\x32G.temporal.api.history.v1.WorkflowExecutionUpdateAcceptedEventAttributesH\x00\x12\x86\x01\n3workflow_execution_update_rejected_event_attributes\x18/ \x01(\x0b\x32G.temporal.api.history.v1.WorkflowExecutionUpdateRejectedEventAttributesH\x00\x12\x88\x01\n4workflow_execution_update_completed_event_attributes\x18\x30 \x01(\x0b\x32H.temporal.api.history.v1.WorkflowExecutionUpdateCompletedEventAttributesH\x00\x12\x90\x01\n8workflow_properties_modified_externally_event_attributes\x18\x31 \x01(\x0b\x32L.temporal.api.history.v1.WorkflowPropertiesModifiedExternallyEventAttributesH\x00\x12\x90\x01\n8activity_properties_modified_externally_event_attributes\x18\x32 \x01(\x0b\x32L.temporal.api.history.v1.ActivityPropertiesModifiedExternallyEventAttributesH\x00\x12{\n-workflow_properties_modified_event_attributes\x18\x33 \x01(\x0b\x32\x42.temporal.api.history.v1.WorkflowPropertiesModifiedEventAttributesH\x00\x12\x86\x01\n3workflow_execution_update_admitted_event_attributes\x18\x34 \x01(\x0b\x32G.temporal.api.history.v1.WorkflowExecutionUpdateAdmittedEventAttributesH\x00\x12u\n*nexus_operation_scheduled_event_attributes\x18\x35 \x01(\x0b\x32?.temporal.api.history.v1.NexusOperationScheduledEventAttributesH\x00\x12q\n(nexus_operation_started_event_attributes\x18\x36 \x01(\x0b\x32=.temporal.api.history.v1.NexusOperationStartedEventAttributesH\x00\x12u\n*nexus_operation_completed_event_attributes\x18\x37 \x01(\x0b\x32?.temporal.api.history.v1.NexusOperationCompletedEventAttributesH\x00\x12o\n\'nexus_operation_failed_event_attributes\x18\x38 \x01(\x0b\x32<.temporal.api.history.v1.NexusOperationFailedEventAttributesH\x00\x12s\n)nexus_operation_canceled_event_attributes\x18\x39 \x01(\x0b\x32>.temporal.api.history.v1.NexusOperationCanceledEventAttributesH\x00\x12t\n*nexus_operation_timed_out_event_attributes\x18: \x01(\x0b\x32>.temporal.api.history.v1.NexusOperationTimedOutEventAttributesH\x00\x12\x82\x01\n1nexus_operation_cancel_requested_event_attributes\x18; \x01(\x0b\x32\x45.temporal.api.history.v1.NexusOperationCancelRequestedEventAttributesH\x00\x12\x86\x01\n3workflow_execution_options_updated_event_attributes\x18< \x01(\x0b\x32G.temporal.api.history.v1.WorkflowExecutionOptionsUpdatedEventAttributesH\x00\x12\x91\x01\n9nexus_operation_cancel_request_completed_event_attributes\x18= \x01(\x0b\x32L.temporal.api.history.v1.NexusOperationCancelRequestCompletedEventAttributesH\x00\x12\x8b\x01\n6nexus_operation_cancel_request_failed_event_attributes\x18> \x01(\x0b\x32I.temporal.api.history.v1.NexusOperationCancelRequestFailedEventAttributesH\x00\x12u\n*workflow_execution_paused_event_attributes\x18? \x01(\x0b\x32?.temporal.api.history.v1.WorkflowExecutionPausedEventAttributesH\x00\x12y\n,workflow_execution_unpaused_event_attributes\x18@ \x01(\x0b\x32\x41.temporal.api.history.v1.WorkflowExecutionUnpausedEventAttributesH\x00\x12\x9b\x01\n>workflow_execution_time_skipping_transitioned_event_attributes\x18\x41 \x01(\x0b\x32Q.temporal.api.history.v1.WorkflowExecutionTimeSkippingTransitionedEventAttributesH\x00\x42\x0c\n\nattributes"@\n\x07History\x12\x35\n\x06\x65vents\x18\x01 \x03(\x0b\x32%.temporal.api.history.v1.HistoryEventB\x8e\x01\n\x1aio.temporal.api.history.v1B\x0cMessageProtoP\x01Z%go.temporal.io/api/history/v1;history\xaa\x02\x19Temporalio.Api.History.V1\xea\x02\x1cTemporalio::Api::History::V1b\x06proto3' ) @@ -1207,140 +1210,140 @@ _NEXUSOPERATIONSTARTEDEVENTATTRIBUTES.fields_by_name[ "operation_id" ]._serialized_options = b"\030\001" - _WORKFLOWEXECUTIONSTARTEDEVENTATTRIBUTES._serialized_start = 617 - _WORKFLOWEXECUTIONSTARTEDEVENTATTRIBUTES._serialized_end = 2947 - _DECLINEDTARGETVERSIONUPGRADE._serialized_start = 2950 - _DECLINEDTARGETVERSIONUPGRADE._serialized_end = 3086 - _WORKFLOWEXECUTIONCOMPLETEDEVENTATTRIBUTES._serialized_start = 3089 - _WORKFLOWEXECUTIONCOMPLETEDEVENTATTRIBUTES._serialized_end = 3254 - _WORKFLOWEXECUTIONFAILEDEVENTATTRIBUTES._serialized_start = 3257 - _WORKFLOWEXECUTIONFAILEDEVENTATTRIBUTES._serialized_end = 3476 - _WORKFLOWEXECUTIONTIMEDOUTEVENTATTRIBUTES._serialized_start = 3479 - _WORKFLOWEXECUTIONTIMEDOUTEVENTATTRIBUTES._serialized_end = 3607 - _WORKFLOWEXECUTIONCONTINUEDASNEWEVENTATTRIBUTES._serialized_start = 3610 - _WORKFLOWEXECUTIONCONTINUEDASNEWEVENTATTRIBUTES._serialized_end = 4543 - _WORKFLOWTASKSCHEDULEDEVENTATTRIBUTES._serialized_start = 4546 - _WORKFLOWTASKSCHEDULEDEVENTATTRIBUTES._serialized_end = 4718 - _WORKFLOWTASKSTARTEDEVENTATTRIBUTES._serialized_start = 4721 - _WORKFLOWTASKSTARTEDEVENTATTRIBUTES._serialized_end = 5137 - _WORKFLOWTASKCOMPLETEDEVENTATTRIBUTES._serialized_start = 5140 - _WORKFLOWTASKCOMPLETEDEVENTATTRIBUTES._serialized_end = 5782 - _WORKFLOWTASKTIMEDOUTEVENTATTRIBUTES._serialized_start = 5785 - _WORKFLOWTASKTIMEDOUTEVENTATTRIBUTES._serialized_end = 5934 - _WORKFLOWTASKFAILEDEVENTATTRIBUTES._serialized_start = 5937 - _WORKFLOWTASKFAILEDEVENTATTRIBUTES._serialized_end = 6328 - _ACTIVITYTASKSCHEDULEDEVENTATTRIBUTES._serialized_start = 6331 - _ACTIVITYTASKSCHEDULEDEVENTATTRIBUTES._serialized_end = 7037 - _ACTIVITYTASKSTARTEDEVENTATTRIBUTES._serialized_start = 7040 - _ACTIVITYTASKSTARTEDEVENTATTRIBUTES._serialized_end = 7326 - _ACTIVITYTASKCOMPLETEDEVENTATTRIBUTES._serialized_start = 7329 - _ACTIVITYTASKCOMPLETEDEVENTATTRIBUTES._serialized_end = 7561 - _ACTIVITYTASKFAILEDEVENTATTRIBUTES._serialized_start = 7564 - _ACTIVITYTASKFAILEDEVENTATTRIBUTES._serialized_end = 7850 - _ACTIVITYTASKTIMEDOUTEVENTATTRIBUTES._serialized_start = 7853 - _ACTIVITYTASKTIMEDOUTEVENTATTRIBUTES._serialized_end = 8051 - _ACTIVITYTASKCANCELREQUESTEDEVENTATTRIBUTES._serialized_start = 8053 - _ACTIVITYTASKCANCELREQUESTEDEVENTATTRIBUTES._serialized_end = 8167 - _ACTIVITYTASKCANCELEDEVENTATTRIBUTES._serialized_start = 8170 - _ACTIVITYTASKCANCELEDEVENTATTRIBUTES._serialized_end = 8444 - _TIMERSTARTEDEVENTATTRIBUTES._serialized_start = 8447 - _TIMERSTARTEDEVENTATTRIBUTES._serialized_end = 8594 - _TIMERFIREDEVENTATTRIBUTES._serialized_start = 8596 - _TIMERFIREDEVENTATTRIBUTES._serialized_end = 8667 - _TIMERCANCELEDEVENTATTRIBUTES._serialized_start = 8670 - _TIMERCANCELEDEVENTATTRIBUTES._serialized_end = 8804 - _WORKFLOWEXECUTIONCANCELREQUESTEDEVENTATTRIBUTES._serialized_start = 8807 - _WORKFLOWEXECUTIONCANCELREQUESTEDEVENTATTRIBUTES._serialized_end = 9006 - _WORKFLOWEXECUTIONCANCELEDEVENTATTRIBUTES._serialized_start = 9009 - _WORKFLOWEXECUTIONCANCELEDEVENTATTRIBUTES._serialized_end = 9144 - _MARKERRECORDEDEVENTATTRIBUTES._serialized_start = 9147 - _MARKERRECORDEDEVENTATTRIBUTES._serialized_end = 9508 - _MARKERRECORDEDEVENTATTRIBUTES_DETAILSENTRY._serialized_start = 9428 - _MARKERRECORDEDEVENTATTRIBUTES_DETAILSENTRY._serialized_end = 9508 - _WORKFLOWEXECUTIONSIGNALEDEVENTATTRIBUTES._serialized_start = 9511 - _WORKFLOWEXECUTIONSIGNALEDEVENTATTRIBUTES._serialized_end = 9830 - _WORKFLOWEXECUTIONTERMINATEDEVENTATTRIBUTES._serialized_start = 9833 - _WORKFLOWEXECUTIONTERMINATEDEVENTATTRIBUTES._serialized_end = 9962 - _REQUESTCANCELEXTERNALWORKFLOWEXECUTIONINITIATEDEVENTATTRIBUTES._serialized_start = 9965 + _WORKFLOWEXECUTIONSTARTEDEVENTATTRIBUTES._serialized_start = 663 + _WORKFLOWEXECUTIONSTARTEDEVENTATTRIBUTES._serialized_end = 3057 + _DECLINEDTARGETVERSIONUPGRADE._serialized_start = 3060 + _DECLINEDTARGETVERSIONUPGRADE._serialized_end = 3196 + _WORKFLOWEXECUTIONCOMPLETEDEVENTATTRIBUTES._serialized_start = 3199 + _WORKFLOWEXECUTIONCOMPLETEDEVENTATTRIBUTES._serialized_end = 3364 + _WORKFLOWEXECUTIONFAILEDEVENTATTRIBUTES._serialized_start = 3367 + _WORKFLOWEXECUTIONFAILEDEVENTATTRIBUTES._serialized_end = 3586 + _WORKFLOWEXECUTIONTIMEDOUTEVENTATTRIBUTES._serialized_start = 3589 + _WORKFLOWEXECUTIONTIMEDOUTEVENTATTRIBUTES._serialized_end = 3717 + _WORKFLOWEXECUTIONCONTINUEDASNEWEVENTATTRIBUTES._serialized_start = 3720 + _WORKFLOWEXECUTIONCONTINUEDASNEWEVENTATTRIBUTES._serialized_end = 4653 + _WORKFLOWTASKSCHEDULEDEVENTATTRIBUTES._serialized_start = 4656 + _WORKFLOWTASKSCHEDULEDEVENTATTRIBUTES._serialized_end = 4828 + _WORKFLOWTASKSTARTEDEVENTATTRIBUTES._serialized_start = 4831 + _WORKFLOWTASKSTARTEDEVENTATTRIBUTES._serialized_end = 5247 + _WORKFLOWTASKCOMPLETEDEVENTATTRIBUTES._serialized_start = 5250 + _WORKFLOWTASKCOMPLETEDEVENTATTRIBUTES._serialized_end = 5892 + _WORKFLOWTASKTIMEDOUTEVENTATTRIBUTES._serialized_start = 5895 + _WORKFLOWTASKTIMEDOUTEVENTATTRIBUTES._serialized_end = 6044 + _WORKFLOWTASKFAILEDEVENTATTRIBUTES._serialized_start = 6047 + _WORKFLOWTASKFAILEDEVENTATTRIBUTES._serialized_end = 6438 + _ACTIVITYTASKSCHEDULEDEVENTATTRIBUTES._serialized_start = 6441 + _ACTIVITYTASKSCHEDULEDEVENTATTRIBUTES._serialized_end = 7147 + _ACTIVITYTASKSTARTEDEVENTATTRIBUTES._serialized_start = 7150 + _ACTIVITYTASKSTARTEDEVENTATTRIBUTES._serialized_end = 7436 + _ACTIVITYTASKCOMPLETEDEVENTATTRIBUTES._serialized_start = 7439 + _ACTIVITYTASKCOMPLETEDEVENTATTRIBUTES._serialized_end = 7671 + _ACTIVITYTASKFAILEDEVENTATTRIBUTES._serialized_start = 7674 + _ACTIVITYTASKFAILEDEVENTATTRIBUTES._serialized_end = 7960 + _ACTIVITYTASKTIMEDOUTEVENTATTRIBUTES._serialized_start = 7963 + _ACTIVITYTASKTIMEDOUTEVENTATTRIBUTES._serialized_end = 8161 + _ACTIVITYTASKCANCELREQUESTEDEVENTATTRIBUTES._serialized_start = 8163 + _ACTIVITYTASKCANCELREQUESTEDEVENTATTRIBUTES._serialized_end = 8277 + _ACTIVITYTASKCANCELEDEVENTATTRIBUTES._serialized_start = 8280 + _ACTIVITYTASKCANCELEDEVENTATTRIBUTES._serialized_end = 8554 + _TIMERSTARTEDEVENTATTRIBUTES._serialized_start = 8557 + _TIMERSTARTEDEVENTATTRIBUTES._serialized_end = 8704 + _TIMERFIREDEVENTATTRIBUTES._serialized_start = 8706 + _TIMERFIREDEVENTATTRIBUTES._serialized_end = 8777 + _TIMERCANCELEDEVENTATTRIBUTES._serialized_start = 8780 + _TIMERCANCELEDEVENTATTRIBUTES._serialized_end = 8914 + _WORKFLOWEXECUTIONCANCELREQUESTEDEVENTATTRIBUTES._serialized_start = 8917 + _WORKFLOWEXECUTIONCANCELREQUESTEDEVENTATTRIBUTES._serialized_end = 9116 + _WORKFLOWEXECUTIONCANCELEDEVENTATTRIBUTES._serialized_start = 9119 + _WORKFLOWEXECUTIONCANCELEDEVENTATTRIBUTES._serialized_end = 9254 + _MARKERRECORDEDEVENTATTRIBUTES._serialized_start = 9257 + _MARKERRECORDEDEVENTATTRIBUTES._serialized_end = 9618 + _MARKERRECORDEDEVENTATTRIBUTES_DETAILSENTRY._serialized_start = 9538 + _MARKERRECORDEDEVENTATTRIBUTES_DETAILSENTRY._serialized_end = 9618 + _WORKFLOWEXECUTIONSIGNALEDEVENTATTRIBUTES._serialized_start = 9621 + _WORKFLOWEXECUTIONSIGNALEDEVENTATTRIBUTES._serialized_end = 9940 + _WORKFLOWEXECUTIONTERMINATEDEVENTATTRIBUTES._serialized_start = 9943 + _WORKFLOWEXECUTIONTERMINATEDEVENTATTRIBUTES._serialized_end = 10072 + _REQUESTCANCELEXTERNALWORKFLOWEXECUTIONINITIATEDEVENTATTRIBUTES._serialized_start = 10075 _REQUESTCANCELEXTERNALWORKFLOWEXECUTIONINITIATEDEVENTATTRIBUTES._serialized_end = ( - 10249 + 10359 ) _REQUESTCANCELEXTERNALWORKFLOWEXECUTIONFAILEDEVENTATTRIBUTES._serialized_start = ( - 10252 + 10362 ) - _REQUESTCANCELEXTERNALWORKFLOWEXECUTIONFAILEDEVENTATTRIBUTES._serialized_end = 10598 - _EXTERNALWORKFLOWEXECUTIONCANCELREQUESTEDEVENTATTRIBUTES._serialized_start = 10601 - _EXTERNALWORKFLOWEXECUTIONCANCELREQUESTEDEVENTATTRIBUTES._serialized_end = 10798 - _SIGNALEXTERNALWORKFLOWEXECUTIONINITIATEDEVENTATTRIBUTES._serialized_start = 10801 - _SIGNALEXTERNALWORKFLOWEXECUTIONINITIATEDEVENTATTRIBUTES._serialized_end = 11180 - _SIGNALEXTERNALWORKFLOWEXECUTIONFAILEDEVENTATTRIBUTES._serialized_start = 11183 - _SIGNALEXTERNALWORKFLOWEXECUTIONFAILEDEVENTATTRIBUTES._serialized_end = 11522 - _EXTERNALWORKFLOWEXECUTIONSIGNALEDEVENTATTRIBUTES._serialized_start = 11525 - _EXTERNALWORKFLOWEXECUTIONSIGNALEDEVENTATTRIBUTES._serialized_end = 11736 - _UPSERTWORKFLOWSEARCHATTRIBUTESEVENTATTRIBUTES._serialized_start = 11739 - _UPSERTWORKFLOWSEARCHATTRIBUTESEVENTATTRIBUTES._serialized_end = 11897 - _WORKFLOWPROPERTIESMODIFIEDEVENTATTRIBUTES._serialized_start = 11900 - _WORKFLOWPROPERTIESMODIFIEDEVENTATTRIBUTES._serialized_end = 12038 - _STARTCHILDWORKFLOWEXECUTIONINITIATEDEVENTATTRIBUTES._serialized_start = 12041 - _STARTCHILDWORKFLOWEXECUTIONINITIATEDEVENTATTRIBUTES._serialized_end = 13178 - _STARTCHILDWORKFLOWEXECUTIONFAILEDEVENTATTRIBUTES._serialized_start = 13181 - _STARTCHILDWORKFLOWEXECUTIONFAILEDEVENTATTRIBUTES._serialized_end = 13523 - _CHILDWORKFLOWEXECUTIONSTARTEDEVENTATTRIBUTES._serialized_start = 13526 - _CHILDWORKFLOWEXECUTIONSTARTEDEVENTATTRIBUTES._serialized_end = 13821 - _CHILDWORKFLOWEXECUTIONCOMPLETEDEVENTATTRIBUTES._serialized_start = 13824 - _CHILDWORKFLOWEXECUTIONCOMPLETEDEVENTATTRIBUTES._serialized_end = 14149 - _CHILDWORKFLOWEXECUTIONFAILEDEVENTATTRIBUTES._serialized_start = 14152 - _CHILDWORKFLOWEXECUTIONFAILEDEVENTATTRIBUTES._serialized_end = 14531 - _CHILDWORKFLOWEXECUTIONCANCELEDEVENTATTRIBUTES._serialized_start = 14534 - _CHILDWORKFLOWEXECUTIONCANCELEDEVENTATTRIBUTES._serialized_end = 14859 - _CHILDWORKFLOWEXECUTIONTIMEDOUTEVENTATTRIBUTES._serialized_start = 14862 - _CHILDWORKFLOWEXECUTIONTIMEDOUTEVENTATTRIBUTES._serialized_end = 15192 - _CHILDWORKFLOWEXECUTIONTERMINATEDEVENTATTRIBUTES._serialized_start = 15195 - _CHILDWORKFLOWEXECUTIONTERMINATEDEVENTATTRIBUTES._serialized_end = 15471 - _WORKFLOWEXECUTIONOPTIONSUPDATEDEVENTATTRIBUTES._serialized_start = 15474 - _WORKFLOWEXECUTIONOPTIONSUPDATEDEVENTATTRIBUTES._serialized_end = 16168 - _WORKFLOWEXECUTIONOPTIONSUPDATEDEVENTATTRIBUTES_WORKFLOWUPDATEOPTIONSUPDATE._serialized_start = 16018 - _WORKFLOWEXECUTIONOPTIONSUPDATEDEVENTATTRIBUTES_WORKFLOWUPDATEOPTIONSUPDATE._serialized_end = 16168 - _WORKFLOWPROPERTIESMODIFIEDEXTERNALLYEVENTATTRIBUTES._serialized_start = 16171 - _WORKFLOWPROPERTIESMODIFIEDEXTERNALLYEVENTATTRIBUTES._serialized_end = 16491 - _ACTIVITYPROPERTIESMODIFIEDEXTERNALLYEVENTATTRIBUTES._serialized_start = 16494 - _ACTIVITYPROPERTIESMODIFIEDEXTERNALLYEVENTATTRIBUTES._serialized_end = 16638 - _WORKFLOWEXECUTIONUPDATEACCEPTEDEVENTATTRIBUTES._serialized_start = 16641 - _WORKFLOWEXECUTIONUPDATEACCEPTEDEVENTATTRIBUTES._serialized_end = 16861 - _WORKFLOWEXECUTIONUPDATECOMPLETEDEVENTATTRIBUTES._serialized_start = 16864 - _WORKFLOWEXECUTIONUPDATECOMPLETEDEVENTATTRIBUTES._serialized_end = 17034 - _WORKFLOWEXECUTIONUPDATEREJECTEDEVENTATTRIBUTES._serialized_start = 17037 - _WORKFLOWEXECUTIONUPDATEREJECTEDEVENTATTRIBUTES._serialized_end = 17308 - _WORKFLOWEXECUTIONUPDATEADMITTEDEVENTATTRIBUTES._serialized_start = 17311 - _WORKFLOWEXECUTIONUPDATEADMITTEDEVENTATTRIBUTES._serialized_end = 17475 - _WORKFLOWEXECUTIONPAUSEDEVENTATTRIBUTES._serialized_start = 17477 - _WORKFLOWEXECUTIONPAUSEDEVENTATTRIBUTES._serialized_end = 17571 - _WORKFLOWEXECUTIONUNPAUSEDEVENTATTRIBUTES._serialized_start = 17573 - _WORKFLOWEXECUTIONUNPAUSEDEVENTATTRIBUTES._serialized_end = 17669 - _WORKFLOWEXECUTIONTIMESKIPPINGTRANSITIONEDEVENTATTRIBUTES._serialized_start = 17672 - _WORKFLOWEXECUTIONTIMESKIPPINGTRANSITIONEDEVENTATTRIBUTES._serialized_end = 17862 - _NEXUSOPERATIONSCHEDULEDEVENTATTRIBUTES._serialized_start = 17865 - _NEXUSOPERATIONSCHEDULEDEVENTATTRIBUTES._serialized_end = 18429 - _NEXUSOPERATIONSCHEDULEDEVENTATTRIBUTES_NEXUSHEADERENTRY._serialized_start = 18379 - _NEXUSOPERATIONSCHEDULEDEVENTATTRIBUTES_NEXUSHEADERENTRY._serialized_end = 18429 - _NEXUSOPERATIONSTARTEDEVENTATTRIBUTES._serialized_start = 18432 - _NEXUSOPERATIONSTARTEDEVENTATTRIBUTES._serialized_end = 18569 - _NEXUSOPERATIONCOMPLETEDEVENTATTRIBUTES._serialized_start = 18572 - _NEXUSOPERATIONCOMPLETEDEVENTATTRIBUTES._serialized_end = 18709 - _NEXUSOPERATIONFAILEDEVENTATTRIBUTES._serialized_start = 18712 - _NEXUSOPERATIONFAILEDEVENTATTRIBUTES._serialized_end = 18848 - _NEXUSOPERATIONTIMEDOUTEVENTATTRIBUTES._serialized_start = 18851 - _NEXUSOPERATIONTIMEDOUTEVENTATTRIBUTES._serialized_end = 18989 - _NEXUSOPERATIONCANCELEDEVENTATTRIBUTES._serialized_start = 18992 - _NEXUSOPERATIONCANCELEDEVENTATTRIBUTES._serialized_end = 19130 - _NEXUSOPERATIONCANCELREQUESTEDEVENTATTRIBUTES._serialized_start = 19132 - _NEXUSOPERATIONCANCELREQUESTEDEVENTATTRIBUTES._serialized_end = 19248 - _NEXUSOPERATIONCANCELREQUESTCOMPLETEDEVENTATTRIBUTES._serialized_start = 19251 - _NEXUSOPERATIONCANCELREQUESTCOMPLETEDEVENTATTRIBUTES._serialized_end = 19402 - _NEXUSOPERATIONCANCELREQUESTFAILEDEVENTATTRIBUTES._serialized_start = 19405 - _NEXUSOPERATIONCANCELREQUESTFAILEDEVENTATTRIBUTES._serialized_end = 19604 - _HISTORYEVENT._serialized_start = 19607 - _HISTORYEVENT._serialized_end = 27676 - _HISTORY._serialized_start = 27678 - _HISTORY._serialized_end = 27742 + _REQUESTCANCELEXTERNALWORKFLOWEXECUTIONFAILEDEVENTATTRIBUTES._serialized_end = 10708 + _EXTERNALWORKFLOWEXECUTIONCANCELREQUESTEDEVENTATTRIBUTES._serialized_start = 10711 + _EXTERNALWORKFLOWEXECUTIONCANCELREQUESTEDEVENTATTRIBUTES._serialized_end = 10908 + _SIGNALEXTERNALWORKFLOWEXECUTIONINITIATEDEVENTATTRIBUTES._serialized_start = 10911 + _SIGNALEXTERNALWORKFLOWEXECUTIONINITIATEDEVENTATTRIBUTES._serialized_end = 11290 + _SIGNALEXTERNALWORKFLOWEXECUTIONFAILEDEVENTATTRIBUTES._serialized_start = 11293 + _SIGNALEXTERNALWORKFLOWEXECUTIONFAILEDEVENTATTRIBUTES._serialized_end = 11632 + _EXTERNALWORKFLOWEXECUTIONSIGNALEDEVENTATTRIBUTES._serialized_start = 11635 + _EXTERNALWORKFLOWEXECUTIONSIGNALEDEVENTATTRIBUTES._serialized_end = 11846 + _UPSERTWORKFLOWSEARCHATTRIBUTESEVENTATTRIBUTES._serialized_start = 11849 + _UPSERTWORKFLOWSEARCHATTRIBUTESEVENTATTRIBUTES._serialized_end = 12007 + _WORKFLOWPROPERTIESMODIFIEDEVENTATTRIBUTES._serialized_start = 12010 + _WORKFLOWPROPERTIESMODIFIEDEVENTATTRIBUTES._serialized_end = 12148 + _STARTCHILDWORKFLOWEXECUTIONINITIATEDEVENTATTRIBUTES._serialized_start = 12151 + _STARTCHILDWORKFLOWEXECUTIONINITIATEDEVENTATTRIBUTES._serialized_end = 13352 + _STARTCHILDWORKFLOWEXECUTIONFAILEDEVENTATTRIBUTES._serialized_start = 13355 + _STARTCHILDWORKFLOWEXECUTIONFAILEDEVENTATTRIBUTES._serialized_end = 13697 + _CHILDWORKFLOWEXECUTIONSTARTEDEVENTATTRIBUTES._serialized_start = 13700 + _CHILDWORKFLOWEXECUTIONSTARTEDEVENTATTRIBUTES._serialized_end = 13995 + _CHILDWORKFLOWEXECUTIONCOMPLETEDEVENTATTRIBUTES._serialized_start = 13998 + _CHILDWORKFLOWEXECUTIONCOMPLETEDEVENTATTRIBUTES._serialized_end = 14323 + _CHILDWORKFLOWEXECUTIONFAILEDEVENTATTRIBUTES._serialized_start = 14326 + _CHILDWORKFLOWEXECUTIONFAILEDEVENTATTRIBUTES._serialized_end = 14705 + _CHILDWORKFLOWEXECUTIONCANCELEDEVENTATTRIBUTES._serialized_start = 14708 + _CHILDWORKFLOWEXECUTIONCANCELEDEVENTATTRIBUTES._serialized_end = 15033 + _CHILDWORKFLOWEXECUTIONTIMEDOUTEVENTATTRIBUTES._serialized_start = 15036 + _CHILDWORKFLOWEXECUTIONTIMEDOUTEVENTATTRIBUTES._serialized_end = 15366 + _CHILDWORKFLOWEXECUTIONTERMINATEDEVENTATTRIBUTES._serialized_start = 15369 + _CHILDWORKFLOWEXECUTIONTERMINATEDEVENTATTRIBUTES._serialized_end = 15645 + _WORKFLOWEXECUTIONOPTIONSUPDATEDEVENTATTRIBUTES._serialized_start = 15648 + _WORKFLOWEXECUTIONOPTIONSUPDATEDEVENTATTRIBUTES._serialized_end = 16378 + _WORKFLOWEXECUTIONOPTIONSUPDATEDEVENTATTRIBUTES_WORKFLOWUPDATEOPTIONSUPDATE._serialized_start = 16228 + _WORKFLOWEXECUTIONOPTIONSUPDATEDEVENTATTRIBUTES_WORKFLOWUPDATEOPTIONSUPDATE._serialized_end = 16378 + _WORKFLOWPROPERTIESMODIFIEDEXTERNALLYEVENTATTRIBUTES._serialized_start = 16381 + _WORKFLOWPROPERTIESMODIFIEDEXTERNALLYEVENTATTRIBUTES._serialized_end = 16701 + _ACTIVITYPROPERTIESMODIFIEDEXTERNALLYEVENTATTRIBUTES._serialized_start = 16704 + _ACTIVITYPROPERTIESMODIFIEDEXTERNALLYEVENTATTRIBUTES._serialized_end = 16848 + _WORKFLOWEXECUTIONUPDATEACCEPTEDEVENTATTRIBUTES._serialized_start = 16851 + _WORKFLOWEXECUTIONUPDATEACCEPTEDEVENTATTRIBUTES._serialized_end = 17071 + _WORKFLOWEXECUTIONUPDATECOMPLETEDEVENTATTRIBUTES._serialized_start = 17074 + _WORKFLOWEXECUTIONUPDATECOMPLETEDEVENTATTRIBUTES._serialized_end = 17244 + _WORKFLOWEXECUTIONUPDATEREJECTEDEVENTATTRIBUTES._serialized_start = 17247 + _WORKFLOWEXECUTIONUPDATEREJECTEDEVENTATTRIBUTES._serialized_end = 17518 + _WORKFLOWEXECUTIONUPDATEADMITTEDEVENTATTRIBUTES._serialized_start = 17521 + _WORKFLOWEXECUTIONUPDATEADMITTEDEVENTATTRIBUTES._serialized_end = 17685 + _WORKFLOWEXECUTIONPAUSEDEVENTATTRIBUTES._serialized_start = 17687 + _WORKFLOWEXECUTIONPAUSEDEVENTATTRIBUTES._serialized_end = 17781 + _WORKFLOWEXECUTIONUNPAUSEDEVENTATTRIBUTES._serialized_start = 17783 + _WORKFLOWEXECUTIONUNPAUSEDEVENTATTRIBUTES._serialized_end = 17879 + _WORKFLOWEXECUTIONTIMESKIPPINGTRANSITIONEDEVENTATTRIBUTES._serialized_start = 17882 + _WORKFLOWEXECUTIONTIMESKIPPINGTRANSITIONEDEVENTATTRIBUTES._serialized_end = 18079 + _NEXUSOPERATIONSCHEDULEDEVENTATTRIBUTES._serialized_start = 18082 + _NEXUSOPERATIONSCHEDULEDEVENTATTRIBUTES._serialized_end = 18646 + _NEXUSOPERATIONSCHEDULEDEVENTATTRIBUTES_NEXUSHEADERENTRY._serialized_start = 18596 + _NEXUSOPERATIONSCHEDULEDEVENTATTRIBUTES_NEXUSHEADERENTRY._serialized_end = 18646 + _NEXUSOPERATIONSTARTEDEVENTATTRIBUTES._serialized_start = 18649 + _NEXUSOPERATIONSTARTEDEVENTATTRIBUTES._serialized_end = 18786 + _NEXUSOPERATIONCOMPLETEDEVENTATTRIBUTES._serialized_start = 18789 + _NEXUSOPERATIONCOMPLETEDEVENTATTRIBUTES._serialized_end = 18926 + _NEXUSOPERATIONFAILEDEVENTATTRIBUTES._serialized_start = 18929 + _NEXUSOPERATIONFAILEDEVENTATTRIBUTES._serialized_end = 19065 + _NEXUSOPERATIONTIMEDOUTEVENTATTRIBUTES._serialized_start = 19068 + _NEXUSOPERATIONTIMEDOUTEVENTATTRIBUTES._serialized_end = 19206 + _NEXUSOPERATIONCANCELEDEVENTATTRIBUTES._serialized_start = 19209 + _NEXUSOPERATIONCANCELEDEVENTATTRIBUTES._serialized_end = 19347 + _NEXUSOPERATIONCANCELREQUESTEDEVENTATTRIBUTES._serialized_start = 19349 + _NEXUSOPERATIONCANCELREQUESTEDEVENTATTRIBUTES._serialized_end = 19465 + _NEXUSOPERATIONCANCELREQUESTCOMPLETEDEVENTATTRIBUTES._serialized_start = 19468 + _NEXUSOPERATIONCANCELREQUESTCOMPLETEDEVENTATTRIBUTES._serialized_end = 19619 + _NEXUSOPERATIONCANCELREQUESTFAILEDEVENTATTRIBUTES._serialized_start = 19622 + _NEXUSOPERATIONCANCELREQUESTFAILEDEVENTATTRIBUTES._serialized_end = 19821 + _HISTORYEVENT._serialized_start = 19824 + _HISTORYEVENT._serialized_end = 27962 + _HISTORY._serialized_start = 27964 + _HISTORY._serialized_end = 28028 # @@protoc_insertion_point(module_scope) diff --git a/temporalio/api/history/v1/message_pb2.pyi b/temporalio/api/history/v1/message_pb2.pyi index 26a4aa8a7..ee158460c 100644 --- a/temporalio/api/history/v1/message_pb2.pyi +++ b/temporalio/api/history/v1/message_pb2.pyi @@ -20,6 +20,7 @@ import temporalio.api.enums.v1.failed_cause_pb2 import temporalio.api.enums.v1.update_pb2 import temporalio.api.enums.v1.workflow_pb2 import temporalio.api.failure.v1.message_pb2 +import temporalio.api.sdk.v1.event_group_marker_pb2 import temporalio.api.sdk.v1.task_complete_metadata_pb2 import temporalio.api.sdk.v1.user_metadata_pb2 import temporalio.api.taskqueue.v1.message_pb2 @@ -78,7 +79,7 @@ class WorkflowExecutionStartedEventAttributes(google.protobuf.message.Message): EAGER_EXECUTION_ACCEPTED_FIELD_NUMBER: builtins.int DECLINED_TARGET_VERSION_UPGRADE_FIELD_NUMBER: builtins.int TIME_SKIPPING_CONFIG_FIELD_NUMBER: builtins.int - INITIAL_SKIPPED_DURATION_FIELD_NUMBER: builtins.int + TIME_SKIPPING_STATE_PROPAGATION_FIELD_NUMBER: builtins.int @property def workflow_type(self) -> temporalio.api.common.v1.message_pb2.WorkflowType: ... parent_workflow_namespace: builtins.str @@ -305,7 +306,7 @@ class WorkflowExecutionStartedEventAttributes(google.protobuf.message.Message): @property def time_skipping_config( self, - ) -> temporalio.api.workflow.v1.message_pb2.TimeSkippingConfig: + ) -> temporalio.api.common.v1.message_pb2.TimeSkippingConfig: """Initial time-skipping configuration for this workflow execution, recorded at start time. This may have been set explicitly via the start workflow request, or propagated from a parent/previous execution. @@ -314,9 +315,11 @@ class WorkflowExecutionStartedEventAttributes(google.protobuf.message.Message): will be reflected in the WorkflowExecutionOptionsUpdatedEvent. """ @property - def initial_skipped_duration(self) -> google.protobuf.duration_pb2.Duration: - """The time skipped by the previous execution that started this workflow. - It can happen in cases of child workflows and continue-as-new workflows. + def time_skipping_state_propagation( + self, + ) -> temporalio.api.common.v1.message_pb2.TimeSkippingStatePropagation: + """The time-skipping state propagated from a previous run of this workflow. This can be nil + if no time skipping has occurred or there is no previous run. """ def __init__( self, @@ -374,9 +377,10 @@ class WorkflowExecutionStartedEventAttributes(google.protobuf.message.Message): eager_execution_accepted: builtins.bool = ..., declined_target_version_upgrade: global___DeclinedTargetVersionUpgrade | None = ..., - time_skipping_config: temporalio.api.workflow.v1.message_pb2.TimeSkippingConfig + time_skipping_config: temporalio.api.common.v1.message_pb2.TimeSkippingConfig + | None = ..., + time_skipping_state_propagation: temporalio.api.common.v1.message_pb2.TimeSkippingStatePropagation | None = ..., - initial_skipped_duration: google.protobuf.duration_pb2.Duration | None = ..., ) -> None: ... def HasField( self, @@ -393,8 +397,6 @@ class WorkflowExecutionStartedEventAttributes(google.protobuf.message.Message): b"inherited_auto_upgrade_info", "inherited_pinned_version", b"inherited_pinned_version", - "initial_skipped_duration", - b"initial_skipped_duration", "input", b"input", "last_completion_result", @@ -419,6 +421,8 @@ class WorkflowExecutionStartedEventAttributes(google.protobuf.message.Message): b"task_queue", "time_skipping_config", b"time_skipping_config", + "time_skipping_state_propagation", + b"time_skipping_state_propagation", "versioning_override", b"versioning_override", "workflow_execution_expiration_time", @@ -464,8 +468,6 @@ class WorkflowExecutionStartedEventAttributes(google.protobuf.message.Message): b"inherited_build_id", "inherited_pinned_version", b"inherited_pinned_version", - "initial_skipped_duration", - b"initial_skipped_duration", "initiator", b"initiator", "input", @@ -504,6 +506,8 @@ class WorkflowExecutionStartedEventAttributes(google.protobuf.message.Message): b"task_queue", "time_skipping_config", b"time_skipping_config", + "time_skipping_state_propagation", + b"time_skipping_state_propagation", "versioning_override", b"versioning_override", "workflow_execution_expiration_time", @@ -2643,7 +2647,7 @@ class StartChildWorkflowExecutionInitiatedEventAttributes( INHERIT_BUILD_ID_FIELD_NUMBER: builtins.int PRIORITY_FIELD_NUMBER: builtins.int TIME_SKIPPING_CONFIG_FIELD_NUMBER: builtins.int - INITIAL_SKIPPED_DURATION_FIELD_NUMBER: builtins.int + TIME_SKIPPING_STATE_PROPAGATION_FIELD_NUMBER: builtins.int namespace: builtins.str """Namespace of the child workflow. SDKs and UI tools should use `namespace` field but server must use `namespace_id` only. @@ -2700,11 +2704,15 @@ class StartChildWorkflowExecutionInitiatedEventAttributes( @property def time_skipping_config( self, - ) -> temporalio.api.workflow.v1.message_pb2.TimeSkippingConfig: + ) -> temporalio.api.common.v1.message_pb2.TimeSkippingConfig: """The propagated time-skipping configuration for the child workflow.""" @property - def initial_skipped_duration(self) -> google.protobuf.duration_pb2.Duration: - """Propagate the duration skipped to the child workflow.""" + def time_skipping_state_propagation( + self, + ) -> temporalio.api.common.v1.message_pb2.TimeSkippingStatePropagation: + """The time-skipping state propagated from the parent workflow. This can be nil if no time skipping + has occurred or there is no previous run. + """ def __init__( self, *, @@ -2729,17 +2737,16 @@ class StartChildWorkflowExecutionInitiatedEventAttributes( | None = ..., inherit_build_id: builtins.bool = ..., priority: temporalio.api.common.v1.message_pb2.Priority | None = ..., - time_skipping_config: temporalio.api.workflow.v1.message_pb2.TimeSkippingConfig + time_skipping_config: temporalio.api.common.v1.message_pb2.TimeSkippingConfig + | None = ..., + time_skipping_state_propagation: temporalio.api.common.v1.message_pb2.TimeSkippingStatePropagation | None = ..., - initial_skipped_duration: google.protobuf.duration_pb2.Duration | None = ..., ) -> None: ... def HasField( self, field_name: typing_extensions.Literal[ "header", b"header", - "initial_skipped_duration", - b"initial_skipped_duration", "input", b"input", "memo", @@ -2754,6 +2761,8 @@ class StartChildWorkflowExecutionInitiatedEventAttributes( b"task_queue", "time_skipping_config", b"time_skipping_config", + "time_skipping_state_propagation", + b"time_skipping_state_propagation", "workflow_execution_timeout", b"workflow_execution_timeout", "workflow_run_timeout", @@ -2775,8 +2784,6 @@ class StartChildWorkflowExecutionInitiatedEventAttributes( b"header", "inherit_build_id", b"inherit_build_id", - "initial_skipped_duration", - b"initial_skipped_duration", "input", b"input", "memo", @@ -2797,6 +2804,8 @@ class StartChildWorkflowExecutionInitiatedEventAttributes( b"task_queue", "time_skipping_config", b"time_skipping_config", + "time_skipping_state_propagation", + b"time_skipping_state_propagation", "workflow_execution_timeout", b"workflow_execution_timeout", "workflow_id", @@ -3368,6 +3377,7 @@ class WorkflowExecutionOptionsUpdatedEventAttributes(google.protobuf.message.Mes IDENTITY_FIELD_NUMBER: builtins.int PRIORITY_FIELD_NUMBER: builtins.int TIME_SKIPPING_CONFIG_FIELD_NUMBER: builtins.int + TIME_SKIPPING_CONFIG_UPDATED_FIELD_NUMBER: builtins.int WORKFLOW_UPDATE_OPTIONS_FIELD_NUMBER: builtins.int @property def versioning_override( @@ -3399,8 +3409,12 @@ class WorkflowExecutionOptionsUpdatedEventAttributes(google.protobuf.message.Mes @property def time_skipping_config( self, - ) -> temporalio.api.workflow.v1.message_pb2.TimeSkippingConfig: - """If set, the time-skipping configuration was changed. Contains the full updated configuration.""" + ) -> temporalio.api.common.v1.message_pb2.TimeSkippingConfig: + """TimeSkippingConfig override upserted in this event. Represents the full config.""" + time_skipping_config_updated: builtins.bool + """Indicates the time skipping config was updated by the recent call to update + workflow execution options. + """ @property def workflow_update_options( self, @@ -3421,8 +3435,9 @@ class WorkflowExecutionOptionsUpdatedEventAttributes(google.protobuf.message.Mes | None = ..., identity: builtins.str = ..., priority: temporalio.api.common.v1.message_pb2.Priority | None = ..., - time_skipping_config: temporalio.api.workflow.v1.message_pb2.TimeSkippingConfig + time_skipping_config: temporalio.api.common.v1.message_pb2.TimeSkippingConfig | None = ..., + time_skipping_config_updated: builtins.bool = ..., workflow_update_options: collections.abc.Iterable[ global___WorkflowExecutionOptionsUpdatedEventAttributes.WorkflowUpdateOptionsUpdate ] @@ -3452,6 +3467,8 @@ class WorkflowExecutionOptionsUpdatedEventAttributes(google.protobuf.message.Mes b"priority", "time_skipping_config", b"time_skipping_config", + "time_skipping_config_updated", + b"time_skipping_config_updated", "unset_versioning_override", b"unset_versioning_override", "versioning_override", @@ -3820,20 +3837,20 @@ class WorkflowExecutionTimeSkippingTransitionedEventAttributes( google.protobuf.message.Message ): """Attributes for an event indicating that time skipping state changed for a workflow execution, - either time was advanced or time skipping was disabled automatically due to a bound being reached. + either time was advanced or time skipping was disabled automatically due to the fast_forward completing. The worker_may_ignore field in HistoryEvent should always be set true for this event. """ DESCRIPTOR: google.protobuf.descriptor.Descriptor TARGET_TIME_FIELD_NUMBER: builtins.int - DISABLED_AFTER_BOUND_FIELD_NUMBER: builtins.int + DISABLED_AFTER_FAST_FORWARD_FIELD_NUMBER: builtins.int WALL_CLOCK_TIME_FIELD_NUMBER: builtins.int @property def target_time(self) -> google.protobuf.timestamp_pb2.Timestamp: - """The virtual time after time skipping was applied.""" - disabled_after_bound: builtins.bool - """when true, time skipping was disabled automatically due to a bound being reached. + """The virtual time point that time skipping advanced to.""" + disabled_after_fast_forward: builtins.bool + """When true, time skipping has been disabled automatically due to a call to fast_forward completing. (-- api-linter: core::0140::prepositions=disabled aip.dev/not-precedent: "after" is used to indicate temporal ordering. --) """ @@ -3844,7 +3861,7 @@ class WorkflowExecutionTimeSkippingTransitionedEventAttributes( self, *, target_time: google.protobuf.timestamp_pb2.Timestamp | None = ..., - disabled_after_bound: builtins.bool = ..., + disabled_after_fast_forward: builtins.bool = ..., wall_clock_time: google.protobuf.timestamp_pb2.Timestamp | None = ..., ) -> None: ... def HasField( @@ -3856,8 +3873,8 @@ class WorkflowExecutionTimeSkippingTransitionedEventAttributes( def ClearField( self, field_name: typing_extensions.Literal[ - "disabled_after_bound", - b"disabled_after_bound", + "disabled_after_fast_forward", + b"disabled_after_fast_forward", "target_time", b"target_time", "wall_clock_time", @@ -4358,6 +4375,7 @@ class HistoryEvent(google.protobuf.message.Message): USER_METADATA_FIELD_NUMBER: builtins.int LINKS_FIELD_NUMBER: builtins.int PRINCIPAL_FIELD_NUMBER: builtins.int + EVENT_GROUP_MARKERS_FIELD_NUMBER: builtins.int WORKFLOW_EXECUTION_STARTED_EVENT_ATTRIBUTES_FIELD_NUMBER: builtins.int WORKFLOW_EXECUTION_COMPLETED_EVENT_ATTRIBUTES_FIELD_NUMBER: builtins.int WORKFLOW_EXECUTION_FAILED_EVENT_ATTRIBUTES_FIELD_NUMBER: builtins.int @@ -4469,6 +4487,13 @@ class HistoryEvent(google.protobuf.message.Message): def principal(self) -> temporalio.api.common.v1.message_pb2.Principal: """Server-computed authenticated caller identity associated with this event.""" @property + def event_group_markers( + self, + ) -> google.protobuf.internal.containers.RepeatedCompositeFieldContainer[ + temporalio.api.sdk.v1.event_group_marker_pb2.EventGroupMarker + ]: + """Event group markers attached to this event.""" + @property def workflow_execution_started_event_attributes( self, ) -> global___WorkflowExecutionStartedEventAttributes: ... @@ -4720,6 +4745,10 @@ class HistoryEvent(google.protobuf.message.Message): links: collections.abc.Iterable[temporalio.api.common.v1.message_pb2.Link] | None = ..., principal: temporalio.api.common.v1.message_pb2.Principal | None = ..., + event_group_markers: collections.abc.Iterable[ + temporalio.api.sdk.v1.event_group_marker_pb2.EventGroupMarker + ] + | None = ..., workflow_execution_started_event_attributes: global___WorkflowExecutionStartedEventAttributes | None = ..., workflow_execution_completed_event_attributes: global___WorkflowExecutionCompletedEventAttributes @@ -5006,6 +5035,8 @@ class HistoryEvent(google.protobuf.message.Message): b"child_workflow_execution_terminated_event_attributes", "child_workflow_execution_timed_out_event_attributes", b"child_workflow_execution_timed_out_event_attributes", + "event_group_markers", + b"event_group_markers", "event_id", b"event_id", "event_time", diff --git a/temporalio/api/namespace/v1/message_pb2.py b/temporalio/api/namespace/v1/message_pb2.py index 4c7018307..fd1858bb7 100644 --- a/temporalio/api/namespace/v1/message_pb2.py +++ b/temporalio/api/namespace/v1/message_pb2.py @@ -22,7 +22,7 @@ ) DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile( - b'\n\'temporal/api/namespace/v1/message.proto\x12\x19temporal.api.namespace.v1\x1a\x1egoogle/protobuf/duration.proto\x1a\x1fgoogle/protobuf/timestamp.proto\x1a%temporal/api/enums/v1/namespace.proto"\xe8\x06\n\rNamespaceInfo\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x34\n\x05state\x18\x02 \x01(\x0e\x32%.temporal.api.enums.v1.NamespaceState\x12\x13\n\x0b\x64\x65scription\x18\x03 \x01(\t\x12\x13\n\x0bowner_email\x18\x04 \x01(\t\x12@\n\x04\x64\x61ta\x18\x05 \x03(\x0b\x32\x32.temporal.api.namespace.v1.NamespaceInfo.DataEntry\x12\n\n\x02id\x18\x06 \x01(\t\x12K\n\x0c\x63\x61pabilities\x18\x07 \x01(\x0b\x32\x35.temporal.api.namespace.v1.NamespaceInfo.Capabilities\x12?\n\x06limits\x18\x08 \x01(\x0b\x32/.temporal.api.namespace.v1.NamespaceInfo.Limits\x12\x1a\n\x12supports_schedules\x18\x64 \x01(\x08\x1a+\n\tDataEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x1a\xfb\x02\n\x0c\x43\x61pabilities\x12\x1c\n\x14\x65\x61ger_workflow_start\x18\x01 \x01(\x08\x12\x13\n\x0bsync_update\x18\x02 \x01(\x08\x12\x14\n\x0c\x61sync_update\x18\x03 \x01(\x08\x12\x19\n\x11worker_heartbeats\x18\x04 \x01(\x08\x12*\n"reported_problems_search_attribute\x18\x05 \x01(\x08\x12\x16\n\x0eworkflow_pause\x18\x06 \x01(\x08\x12\x1d\n\x15standalone_activities\x18\x07 \x01(\x08\x12(\n worker_poll_complete_on_shutdown\x18\x08 \x01(\x08\x12\x1a\n\x12poller_autoscaling\x18\t \x01(\x08\x12\x17\n\x0fworker_commands\x18\n \x01(\x08\x12"\n\x1astandalone_nexus_operation\x18\x0b \x01(\x08\x12!\n\x19workflow_update_callbacks\x18\x0c \x01(\x08\x1a\x46\n\x06Limits\x12\x1d\n\x15\x62lob_size_limit_error\x18\x01 \x01(\x03\x12\x1d\n\x15memo_size_limit_error\x18\x02 \x01(\x03"\x9e\x04\n\x0fNamespaceConfig\x12\x43\n workflow_execution_retention_ttl\x18\x01 \x01(\x0b\x32\x19.google.protobuf.Duration\x12<\n\x0c\x62\x61\x64_binaries\x18\x02 \x01(\x0b\x32&.temporal.api.namespace.v1.BadBinaries\x12\x44\n\x16history_archival_state\x18\x03 \x01(\x0e\x32$.temporal.api.enums.v1.ArchivalState\x12\x1c\n\x14history_archival_uri\x18\x04 \x01(\t\x12G\n\x19visibility_archival_state\x18\x05 \x01(\x0e\x32$.temporal.api.enums.v1.ArchivalState\x12\x1f\n\x17visibility_archival_uri\x18\x06 \x01(\t\x12u\n\x1f\x63ustom_search_attribute_aliases\x18\x07 \x03(\x0b\x32L.temporal.api.namespace.v1.NamespaceConfig.CustomSearchAttributeAliasesEntry\x1a\x43\n!CustomSearchAttributeAliasesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01"\xb0\x01\n\x0b\x42\x61\x64\x42inaries\x12\x46\n\x08\x62inaries\x18\x01 \x03(\x0b\x32\x34.temporal.api.namespace.v1.BadBinaries.BinariesEntry\x1aY\n\rBinariesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x37\n\x05value\x18\x02 \x01(\x0b\x32(.temporal.api.namespace.v1.BadBinaryInfo:\x02\x38\x01"b\n\rBadBinaryInfo\x12\x0e\n\x06reason\x18\x01 \x01(\t\x12\x10\n\x08operator\x18\x02 \x01(\t\x12/\n\x0b\x63reate_time\x18\x03 \x01(\x0b\x32\x1a.google.protobuf.Timestamp"\xea\x01\n\x13UpdateNamespaceInfo\x12\x13\n\x0b\x64\x65scription\x18\x01 \x01(\t\x12\x13\n\x0bowner_email\x18\x02 \x01(\t\x12\x46\n\x04\x64\x61ta\x18\x03 \x03(\x0b\x32\x38.temporal.api.namespace.v1.UpdateNamespaceInfo.DataEntry\x12\x34\n\x05state\x18\x04 \x01(\x0e\x32%.temporal.api.enums.v1.NamespaceState\x1a+\n\tDataEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01"*\n\x0fNamespaceFilter\x12\x17\n\x0finclude_deleted\x18\x01 \x01(\x08\x42\x98\x01\n\x1cio.temporal.api.namespace.v1B\x0cMessageProtoP\x01Z)go.temporal.io/api/namespace/v1;namespace\xaa\x02\x1bTemporalio.Api.Namespace.V1\xea\x02\x1eTemporalio::Api::Namespace::V1b\x06proto3' + b'\n\'temporal/api/namespace/v1/message.proto\x12\x19temporal.api.namespace.v1\x1a\x1egoogle/protobuf/duration.proto\x1a\x1fgoogle/protobuf/timestamp.proto\x1a%temporal/api/enums/v1/namespace.proto"\x90\x07\n\rNamespaceInfo\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x34\n\x05state\x18\x02 \x01(\x0e\x32%.temporal.api.enums.v1.NamespaceState\x12\x13\n\x0b\x64\x65scription\x18\x03 \x01(\t\x12\x13\n\x0bowner_email\x18\x04 \x01(\t\x12@\n\x04\x64\x61ta\x18\x05 \x03(\x0b\x32\x32.temporal.api.namespace.v1.NamespaceInfo.DataEntry\x12\n\n\x02id\x18\x06 \x01(\t\x12K\n\x0c\x63\x61pabilities\x18\x07 \x01(\x0b\x32\x35.temporal.api.namespace.v1.NamespaceInfo.Capabilities\x12?\n\x06limits\x18\x08 \x01(\x0b\x32/.temporal.api.namespace.v1.NamespaceInfo.Limits\x12\x1a\n\x12supports_schedules\x18\x64 \x01(\x08\x1a+\n\tDataEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x1a\xa3\x03\n\x0c\x43\x61pabilities\x12\x1c\n\x14\x65\x61ger_workflow_start\x18\x01 \x01(\x08\x12\x13\n\x0bsync_update\x18\x02 \x01(\x08\x12\x14\n\x0c\x61sync_update\x18\x03 \x01(\x08\x12\x19\n\x11worker_heartbeats\x18\x04 \x01(\x08\x12*\n"reported_problems_search_attribute\x18\x05 \x01(\x08\x12\x16\n\x0eworkflow_pause\x18\x06 \x01(\x08\x12\x1d\n\x15standalone_activities\x18\x07 \x01(\x08\x12(\n worker_poll_complete_on_shutdown\x18\x08 \x01(\x08\x12\x1a\n\x12poller_autoscaling\x18\t \x01(\x08\x12\x17\n\x0fworker_commands\x18\n \x01(\x08\x12"\n\x1astandalone_nexus_operation\x18\x0b \x01(\x08\x12!\n\x19workflow_update_callbacks\x18\x0c \x01(\x08\x12&\n\x1epoller_autoscaling_auto_enroll\x18\r \x01(\x08\x1a\x46\n\x06Limits\x12\x1d\n\x15\x62lob_size_limit_error\x18\x01 \x01(\x03\x12\x1d\n\x15memo_size_limit_error\x18\x02 \x01(\x03"\x9e\x04\n\x0fNamespaceConfig\x12\x43\n workflow_execution_retention_ttl\x18\x01 \x01(\x0b\x32\x19.google.protobuf.Duration\x12<\n\x0c\x62\x61\x64_binaries\x18\x02 \x01(\x0b\x32&.temporal.api.namespace.v1.BadBinaries\x12\x44\n\x16history_archival_state\x18\x03 \x01(\x0e\x32$.temporal.api.enums.v1.ArchivalState\x12\x1c\n\x14history_archival_uri\x18\x04 \x01(\t\x12G\n\x19visibility_archival_state\x18\x05 \x01(\x0e\x32$.temporal.api.enums.v1.ArchivalState\x12\x1f\n\x17visibility_archival_uri\x18\x06 \x01(\t\x12u\n\x1f\x63ustom_search_attribute_aliases\x18\x07 \x03(\x0b\x32L.temporal.api.namespace.v1.NamespaceConfig.CustomSearchAttributeAliasesEntry\x1a\x43\n!CustomSearchAttributeAliasesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01"\xb0\x01\n\x0b\x42\x61\x64\x42inaries\x12\x46\n\x08\x62inaries\x18\x01 \x03(\x0b\x32\x34.temporal.api.namespace.v1.BadBinaries.BinariesEntry\x1aY\n\rBinariesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x37\n\x05value\x18\x02 \x01(\x0b\x32(.temporal.api.namespace.v1.BadBinaryInfo:\x02\x38\x01"b\n\rBadBinaryInfo\x12\x0e\n\x06reason\x18\x01 \x01(\t\x12\x10\n\x08operator\x18\x02 \x01(\t\x12/\n\x0b\x63reate_time\x18\x03 \x01(\x0b\x32\x1a.google.protobuf.Timestamp"\xea\x01\n\x13UpdateNamespaceInfo\x12\x13\n\x0b\x64\x65scription\x18\x01 \x01(\t\x12\x13\n\x0bowner_email\x18\x02 \x01(\t\x12\x46\n\x04\x64\x61ta\x18\x03 \x03(\x0b\x32\x38.temporal.api.namespace.v1.UpdateNamespaceInfo.DataEntry\x12\x34\n\x05state\x18\x04 \x01(\x0e\x32%.temporal.api.enums.v1.NamespaceState\x1a+\n\tDataEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01"*\n\x0fNamespaceFilter\x12\x17\n\x0finclude_deleted\x18\x01 \x01(\x08\x42\x98\x01\n\x1cio.temporal.api.namespace.v1B\x0cMessageProtoP\x01Z)go.temporal.io/api/namespace/v1;namespace\xaa\x02\x1bTemporalio.Api.Namespace.V1\xea\x02\x1eTemporalio::Api::Namespace::V1b\x06proto3' ) @@ -178,27 +178,27 @@ _UPDATENAMESPACEINFO_DATAENTRY._options = None _UPDATENAMESPACEINFO_DATAENTRY._serialized_options = b"8\001" _NAMESPACEINFO._serialized_start = 175 - _NAMESPACEINFO._serialized_end = 1047 + _NAMESPACEINFO._serialized_end = 1087 _NAMESPACEINFO_DATAENTRY._serialized_start = 550 _NAMESPACEINFO_DATAENTRY._serialized_end = 593 _NAMESPACEINFO_CAPABILITIES._serialized_start = 596 - _NAMESPACEINFO_CAPABILITIES._serialized_end = 975 - _NAMESPACEINFO_LIMITS._serialized_start = 977 - _NAMESPACEINFO_LIMITS._serialized_end = 1047 - _NAMESPACECONFIG._serialized_start = 1050 - _NAMESPACECONFIG._serialized_end = 1592 - _NAMESPACECONFIG_CUSTOMSEARCHATTRIBUTEALIASESENTRY._serialized_start = 1525 - _NAMESPACECONFIG_CUSTOMSEARCHATTRIBUTEALIASESENTRY._serialized_end = 1592 - _BADBINARIES._serialized_start = 1595 - _BADBINARIES._serialized_end = 1771 - _BADBINARIES_BINARIESENTRY._serialized_start = 1682 - _BADBINARIES_BINARIESENTRY._serialized_end = 1771 - _BADBINARYINFO._serialized_start = 1773 - _BADBINARYINFO._serialized_end = 1871 - _UPDATENAMESPACEINFO._serialized_start = 1874 - _UPDATENAMESPACEINFO._serialized_end = 2108 + _NAMESPACEINFO_CAPABILITIES._serialized_end = 1015 + _NAMESPACEINFO_LIMITS._serialized_start = 1017 + _NAMESPACEINFO_LIMITS._serialized_end = 1087 + _NAMESPACECONFIG._serialized_start = 1090 + _NAMESPACECONFIG._serialized_end = 1632 + _NAMESPACECONFIG_CUSTOMSEARCHATTRIBUTEALIASESENTRY._serialized_start = 1565 + _NAMESPACECONFIG_CUSTOMSEARCHATTRIBUTEALIASESENTRY._serialized_end = 1632 + _BADBINARIES._serialized_start = 1635 + _BADBINARIES._serialized_end = 1811 + _BADBINARIES_BINARIESENTRY._serialized_start = 1722 + _BADBINARIES_BINARIESENTRY._serialized_end = 1811 + _BADBINARYINFO._serialized_start = 1813 + _BADBINARYINFO._serialized_end = 1911 + _UPDATENAMESPACEINFO._serialized_start = 1914 + _UPDATENAMESPACEINFO._serialized_end = 2148 _UPDATENAMESPACEINFO_DATAENTRY._serialized_start = 550 _UPDATENAMESPACEINFO_DATAENTRY._serialized_end = 593 - _NAMESPACEFILTER._serialized_start = 2110 - _NAMESPACEFILTER._serialized_end = 2152 + _NAMESPACEFILTER._serialized_start = 2150 + _NAMESPACEFILTER._serialized_end = 2192 # @@protoc_insertion_point(module_scope) diff --git a/temporalio/api/namespace/v1/message_pb2.pyi b/temporalio/api/namespace/v1/message_pb2.pyi index a01a58c72..9680e7f5d 100644 --- a/temporalio/api/namespace/v1/message_pb2.pyi +++ b/temporalio/api/namespace/v1/message_pb2.pyi @@ -60,6 +60,7 @@ class NamespaceInfo(google.protobuf.message.Message): WORKER_COMMANDS_FIELD_NUMBER: builtins.int STANDALONE_NEXUS_OPERATION_FIELD_NUMBER: builtins.int WORKFLOW_UPDATE_CALLBACKS_FIELD_NUMBER: builtins.int + POLLER_AUTOSCALING_AUTO_ENROLL_FIELD_NUMBER: builtins.int eager_workflow_start: builtins.bool """True if the namespace supports eager workflow start.""" sync_update: builtins.bool @@ -89,6 +90,8 @@ class NamespaceInfo(google.protobuf.message.Message): """True if the namespace supports standalone Nexus operations.""" workflow_update_callbacks: builtins.bool """True if the namespace supports attaching callbacks on workflow updates""" + poller_autoscaling_auto_enroll: builtins.bool + """When true, workers should use poller autoscaling by default unless explicitly configured otherwise.""" def __init__( self, *, @@ -104,6 +107,7 @@ class NamespaceInfo(google.protobuf.message.Message): worker_commands: builtins.bool = ..., standalone_nexus_operation: builtins.bool = ..., workflow_update_callbacks: builtins.bool = ..., + poller_autoscaling_auto_enroll: builtins.bool = ..., ) -> None: ... def ClearField( self, @@ -114,6 +118,8 @@ class NamespaceInfo(google.protobuf.message.Message): b"eager_workflow_start", "poller_autoscaling", b"poller_autoscaling", + "poller_autoscaling_auto_enroll", + b"poller_autoscaling_auto_enroll", "reported_problems_search_attribute", b"reported_problems_search_attribute", "standalone_activities", diff --git a/temporalio/api/sdk/v1/__init__.py b/temporalio/api/sdk/v1/__init__.py index 0a72fe5cf..4f23aac6a 100644 --- a/temporalio/api/sdk/v1/__init__.py +++ b/temporalio/api/sdk/v1/__init__.py @@ -5,6 +5,7 @@ StackTraceFileSlice, StackTraceSDKInfo, ) +from .event_group_marker_pb2 import EventGroupMarker from .external_storage_pb2 import ExternalStorageReference from .task_complete_metadata_pb2 import WorkflowTaskCompletedMetadata from .user_metadata_pb2 import UserMetadata @@ -17,6 +18,7 @@ __all__ = [ "EnhancedStackTrace", + "EventGroupMarker", "ExternalStorageReference", "StackTrace", "StackTraceFileLocation", diff --git a/temporalio/api/sdk/v1/event_group_marker_pb2.py b/temporalio/api/sdk/v1/event_group_marker_pb2.py new file mode 100644 index 000000000..3475c8588 --- /dev/null +++ b/temporalio/api/sdk/v1/event_group_marker_pb2.py @@ -0,0 +1,84 @@ +# -*- coding: utf-8 -*- +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: temporal/api/sdk/v1/event_group_marker.proto +"""Generated protocol buffer code.""" + +from google.protobuf import descriptor as _descriptor +from google.protobuf import descriptor_pool as _descriptor_pool +from google.protobuf import message as _message +from google.protobuf import reflection as _reflection +from google.protobuf import symbol_database as _symbol_database + +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + +from temporalio.api.common.v1 import ( + message_pb2 as temporal_dot_api_dot_common_dot_v1_dot_message__pb2, +) + +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile( + b'\n,temporal/api/sdk/v1/event_group_marker.proto\x12\x13temporal.api.sdk.v1\x1a$temporal/api/common/v1/message.proto"\x92\x03\n\x10\x45ventGroupMarker\x12<\n\x05label\x18\x01 \x01(\x0b\x32+.temporal.api.sdk.v1.EventGroupMarker.LabelH\x00\x12K\n\rinbound_event\x18\x02 \x01(\x0b\x32\x32.temporal.api.sdk.v1.EventGroupMarker.InboundEventH\x00\x12M\n\x0einbound_update\x18\x03 \x01(\x0b\x32\x33.temporal.api.sdk.v1.EventGroupMarker.InboundUpdateH\x00\x1a\x43\n\x05Label\x12\n\n\x02id\x18\x01 \x01(\t\x12.\n\x05label\x18\x02 \x01(\x0b\x32\x1f.temporal.api.common.v1.Payload\x1a(\n\x0cInboundEvent\x12\x18\n\x10inbound_event_id\x18\x01 \x01(\x03\x1a*\n\rInboundUpdate\x12\x19\n\x11inbound_update_id\x18\x01 \x01(\tB\t\n\x07variantB\x83\x01\n\x16io.temporal.api.sdk.v1B\x15\x45ventGroupMarkerProtoP\x01Z\x1dgo.temporal.io/api/sdk/v1;sdk\xaa\x02\x15Temporalio.Api.Sdk.V1\xea\x02\x18Temporalio::Api::Sdk::V1b\x06proto3' +) + + +_EVENTGROUPMARKER = DESCRIPTOR.message_types_by_name["EventGroupMarker"] +_EVENTGROUPMARKER_LABEL = _EVENTGROUPMARKER.nested_types_by_name["Label"] +_EVENTGROUPMARKER_INBOUNDEVENT = _EVENTGROUPMARKER.nested_types_by_name["InboundEvent"] +_EVENTGROUPMARKER_INBOUNDUPDATE = _EVENTGROUPMARKER.nested_types_by_name[ + "InboundUpdate" +] +EventGroupMarker = _reflection.GeneratedProtocolMessageType( + "EventGroupMarker", + (_message.Message,), + { + "Label": _reflection.GeneratedProtocolMessageType( + "Label", + (_message.Message,), + { + "DESCRIPTOR": _EVENTGROUPMARKER_LABEL, + "__module__": "temporalio.api.sdk.v1.event_group_marker_pb2", + # @@protoc_insertion_point(class_scope:temporal.api.sdk.v1.EventGroupMarker.Label) + }, + ), + "InboundEvent": _reflection.GeneratedProtocolMessageType( + "InboundEvent", + (_message.Message,), + { + "DESCRIPTOR": _EVENTGROUPMARKER_INBOUNDEVENT, + "__module__": "temporalio.api.sdk.v1.event_group_marker_pb2", + # @@protoc_insertion_point(class_scope:temporal.api.sdk.v1.EventGroupMarker.InboundEvent) + }, + ), + "InboundUpdate": _reflection.GeneratedProtocolMessageType( + "InboundUpdate", + (_message.Message,), + { + "DESCRIPTOR": _EVENTGROUPMARKER_INBOUNDUPDATE, + "__module__": "temporalio.api.sdk.v1.event_group_marker_pb2", + # @@protoc_insertion_point(class_scope:temporal.api.sdk.v1.EventGroupMarker.InboundUpdate) + }, + ), + "DESCRIPTOR": _EVENTGROUPMARKER, + "__module__": "temporalio.api.sdk.v1.event_group_marker_pb2", + # @@protoc_insertion_point(class_scope:temporal.api.sdk.v1.EventGroupMarker) + }, +) +_sym_db.RegisterMessage(EventGroupMarker) +_sym_db.RegisterMessage(EventGroupMarker.Label) +_sym_db.RegisterMessage(EventGroupMarker.InboundEvent) +_sym_db.RegisterMessage(EventGroupMarker.InboundUpdate) + +if _descriptor._USE_C_DESCRIPTORS == False: + DESCRIPTOR._options = None + DESCRIPTOR._serialized_options = b"\n\026io.temporal.api.sdk.v1B\025EventGroupMarkerProtoP\001Z\035go.temporal.io/api/sdk/v1;sdk\252\002\025Temporalio.Api.Sdk.V1\352\002\030Temporalio::Api::Sdk::V1" + _EVENTGROUPMARKER._serialized_start = 108 + _EVENTGROUPMARKER._serialized_end = 510 + _EVENTGROUPMARKER_LABEL._serialized_start = 346 + _EVENTGROUPMARKER_LABEL._serialized_end = 413 + _EVENTGROUPMARKER_INBOUNDEVENT._serialized_start = 415 + _EVENTGROUPMARKER_INBOUNDEVENT._serialized_end = 455 + _EVENTGROUPMARKER_INBOUNDUPDATE._serialized_start = 457 + _EVENTGROUPMARKER_INBOUNDUPDATE._serialized_end = 499 +# @@protoc_insertion_point(module_scope) diff --git a/temporalio/api/sdk/v1/event_group_marker_pb2.pyi b/temporalio/api/sdk/v1/event_group_marker_pb2.pyi new file mode 100644 index 000000000..63a5f53eb --- /dev/null +++ b/temporalio/api/sdk/v1/event_group_marker_pb2.pyi @@ -0,0 +1,159 @@ +""" +@generated by mypy-protobuf. Do not edit manually! +isort:skip_file +""" + +import builtins +import sys + +import google.protobuf.descriptor +import google.protobuf.message + +import temporalio.api.common.v1.message_pb2 + +if sys.version_info >= (3, 8): + import typing as typing_extensions +else: + import typing_extensions + +DESCRIPTOR: google.protobuf.descriptor.FileDescriptor + +class EventGroupMarker(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + class Label(google.protobuf.message.Message): + """A user-defined short-form string value to be used as the group's label.""" + + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + ID_FIELD_NUMBER: builtins.int + LABEL_FIELD_NUMBER: builtins.int + id: builtins.str + """Opaque identifier assigned by the SDK.""" + @property + def label(self) -> temporalio.api.common.v1.message_pb2.Payload: + """This payload should be a "json/plain"-encoded payload that is a single + JSON string for use in user interfaces. User interface formatting may not + apply to this text when used in "label" situations. The payload data + section is limited to 400 bytes by default. + + Payload only needs to be set on the first use of a given Marker ID; + further references to an existing Marker ID reuse existing attributes of + the referenced Marker -- i.e. further label payloads are ignored. + + Note that it is valid to have distinct Markers (i.e. distinct Marker IDs) + in a given workflow execution that carry the same label, provided that + they have the distinct ID. + """ + def __init__( + self, + *, + id: builtins.str = ..., + label: temporalio.api.common.v1.message_pb2.Payload | None = ..., + ) -> None: ... + def HasField( + self, field_name: typing_extensions.Literal["label", b"label"] + ) -> builtins.bool: ... + def ClearField( + self, field_name: typing_extensions.Literal["id", b"id", "label", b"label"] + ) -> None: ... + + class InboundEvent(google.protobuf.message.Message): + """The event ID of an event in the present workflow that triggered implicit + creation of this group Marker. + + The target event's type must be one of the following: + - `WORKFLOW_EXECUTION_STARTED` + - `WORKFLOW_EXECUTION_SIGNALED` + """ + + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + INBOUND_EVENT_ID_FIELD_NUMBER: builtins.int + inbound_event_id: builtins.int + def __init__( + self, + *, + inbound_event_id: builtins.int = ..., + ) -> None: ... + def ClearField( + self, + field_name: typing_extensions.Literal[ + "inbound_event_id", b"inbound_event_id" + ], + ) -> None: ... + + class InboundUpdate(google.protobuf.message.Message): + """The identifier of an inbound Update (request.meta.update_id) + whose handler triggered implicit creation of this group Marker. + + Used in place of `inbound_event_id` for Updates because the event ID of the + UpdateAccepted history event is not known until the Workflow Task is + completed and recorded by the server, which may be too late. + """ + + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + INBOUND_UPDATE_ID_FIELD_NUMBER: builtins.int + inbound_update_id: builtins.str + def __init__( + self, + *, + inbound_update_id: builtins.str = ..., + ) -> None: ... + def ClearField( + self, + field_name: typing_extensions.Literal[ + "inbound_update_id", b"inbound_update_id" + ], + ) -> None: ... + + LABEL_FIELD_NUMBER: builtins.int + INBOUND_EVENT_FIELD_NUMBER: builtins.int + INBOUND_UPDATE_FIELD_NUMBER: builtins.int + @property + def label(self) -> global___EventGroupMarker.Label: ... + @property + def inbound_event(self) -> global___EventGroupMarker.InboundEvent: ... + @property + def inbound_update(self) -> global___EventGroupMarker.InboundUpdate: ... + def __init__( + self, + *, + label: global___EventGroupMarker.Label | None = ..., + inbound_event: global___EventGroupMarker.InboundEvent | None = ..., + inbound_update: global___EventGroupMarker.InboundUpdate | None = ..., + ) -> None: ... + def HasField( + self, + field_name: typing_extensions.Literal[ + "inbound_event", + b"inbound_event", + "inbound_update", + b"inbound_update", + "label", + b"label", + "variant", + b"variant", + ], + ) -> builtins.bool: ... + def ClearField( + self, + field_name: typing_extensions.Literal[ + "inbound_event", + b"inbound_event", + "inbound_update", + b"inbound_update", + "label", + b"label", + "variant", + b"variant", + ], + ) -> None: ... + def WhichOneof( + self, oneof_group: typing_extensions.Literal["variant", b"variant"] + ) -> ( + typing_extensions.Literal["label", "inbound_event", "inbound_update"] | None + ): ... + +global___EventGroupMarker = EventGroupMarker diff --git a/temporalio/api/workflow/v1/__init__.py b/temporalio/api/workflow/v1/__init__.py index 89878d551..ae647ab67 100644 --- a/temporalio/api/workflow/v1/__init__.py +++ b/temporalio/api/workflow/v1/__init__.py @@ -13,7 +13,6 @@ RequestIdInfo, ResetPointInfo, ResetPoints, - TimeSkippingConfig, VersioningOverride, WorkflowExecutionConfig, WorkflowExecutionExtendedInfo, @@ -38,7 +37,6 @@ "RequestIdInfo", "ResetPointInfo", "ResetPoints", - "TimeSkippingConfig", "VersioningOverride", "WorkflowExecutionConfig", "WorkflowExecutionExtendedInfo", diff --git a/temporalio/api/workflow/v1/message_pb2.py b/temporalio/api/workflow/v1/message_pb2.py index 70d909746..24a9f03e2 100644 --- a/temporalio/api/workflow/v1/message_pb2.py +++ b/temporalio/api/workflow/v1/message_pb2.py @@ -48,7 +48,7 @@ ) DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile( - b'\n&temporal/api/workflow/v1/message.proto\x12\x18temporal.api.workflow.v1\x1a\x1egoogle/protobuf/duration.proto\x1a\x1bgoogle/protobuf/empty.proto\x1a\x1fgoogle/protobuf/timestamp.proto\x1a google/protobuf/field_mask.proto\x1a&temporal/api/activity/v1/message.proto\x1a"temporal/api/enums/v1/common.proto\x1a&temporal/api/enums/v1/event_type.proto\x1a$temporal/api/enums/v1/workflow.proto\x1a$temporal/api/common/v1/message.proto\x1a(temporal/api/deployment/v1/message.proto\x1a%temporal/api/failure/v1/message.proto\x1a\'temporal/api/taskqueue/v1/message.proto\x1a\'temporal/api/sdk/v1/user_metadata.proto"\xf0\t\n\x15WorkflowExecutionInfo\x12<\n\texecution\x18\x01 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x32\n\x04type\x18\x02 \x01(\x0b\x32$.temporal.api.common.v1.WorkflowType\x12.\n\nstart_time\x18\x03 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12.\n\nclose_time\x18\x04 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12>\n\x06status\x18\x05 \x01(\x0e\x32..temporal.api.enums.v1.WorkflowExecutionStatus\x12\x16\n\x0ehistory_length\x18\x06 \x01(\x03\x12\x1b\n\x13parent_namespace_id\x18\x07 \x01(\t\x12\x43\n\x10parent_execution\x18\x08 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x32\n\x0e\x65xecution_time\x18\t \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12*\n\x04memo\x18\n \x01(\x0b\x32\x1c.temporal.api.common.v1.Memo\x12\x43\n\x11search_attributes\x18\x0b \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes\x12@\n\x11\x61uto_reset_points\x18\x0c \x01(\x0b\x32%.temporal.api.workflow.v1.ResetPoints\x12\x12\n\ntask_queue\x18\r \x01(\t\x12\x1e\n\x16state_transition_count\x18\x0e \x01(\x03\x12\x1a\n\x12history_size_bytes\x18\x0f \x01(\x03\x12X\n most_recent_worker_version_stamp\x18\x10 \x01(\x0b\x32*.temporal.api.common.v1.WorkerVersionStampB\x02\x18\x01\x12\x35\n\x12\x65xecution_duration\x18\x11 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x41\n\x0eroot_execution\x18\x12 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x1d\n\x11\x61ssigned_build_id\x18\x13 \x01(\tB\x02\x18\x01\x12\x1e\n\x12inherited_build_id\x18\x14 \x01(\tB\x02\x18\x01\x12\x14\n\x0c\x66irst_run_id\x18\x15 \x01(\t\x12R\n\x0fversioning_info\x18\x16 \x01(\x0b\x32\x39.temporal.api.workflow.v1.WorkflowExecutionVersioningInfo\x12\x1e\n\x16worker_deployment_name\x18\x17 \x01(\t\x12\x32\n\x08priority\x18\x18 \x01(\x0b\x32 .temporal.api.common.v1.Priority\x12#\n\x1b\x65xternal_payload_size_bytes\x18\x19 \x01(\x03\x12\x1e\n\x16\x65xternal_payload_count\x18\x1a \x01(\x03"\xc6\x04\n\x1dWorkflowExecutionExtendedInfo\x12=\n\x19\x65xecution_expiration_time\x18\x01 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x37\n\x13run_expiration_time\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x18\n\x10\x63\x61ncel_requested\x18\x03 \x01(\x08\x12\x33\n\x0flast_reset_time\x18\x04 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x37\n\x13original_start_time\x18\x05 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x14\n\x0creset_run_id\x18\x06 \x01(\t\x12\x65\n\x10request_id_infos\x18\x07 \x03(\x0b\x32K.temporal.api.workflow.v1.WorkflowExecutionExtendedInfo.RequestIdInfosEntry\x12H\n\npause_info\x18\x08 \x01(\x0b\x32\x34.temporal.api.workflow.v1.WorkflowExecutionPauseInfo\x1a^\n\x13RequestIdInfosEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x36\n\x05value\x18\x02 \x01(\x0b\x32\'.temporal.api.workflow.v1.RequestIdInfo:\x02\x38\x01"\xfb\x04\n\x1fWorkflowExecutionVersioningInfo\x12;\n\x08\x62\x65havior\x18\x01 \x01(\x0e\x32).temporal.api.enums.v1.VersioningBehavior\x12>\n\ndeployment\x18\x02 \x01(\x0b\x32&.temporal.api.deployment.v1.DeploymentB\x02\x18\x01\x12\x13\n\x07version\x18\x05 \x01(\tB\x02\x18\x01\x12O\n\x12\x64\x65ployment_version\x18\x07 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersion\x12I\n\x13versioning_override\x18\x03 \x01(\x0b\x32,.temporal.api.workflow.v1.VersioningOverride\x12Q\n\x15\x64\x65ployment_transition\x18\x04 \x01(\x0b\x32..temporal.api.workflow.v1.DeploymentTransitionB\x02\x18\x01\x12Q\n\x12version_transition\x18\x06 \x01(\x0b\x32\x35.temporal.api.workflow.v1.DeploymentVersionTransition\x12\x17\n\x0frevision_number\x18\x08 \x01(\x03\x12k\n+continue_as_new_initial_versioning_behavior\x18\t \x01(\x0e\x32\x36.temporal.api.enums.v1.ContinueAsNewVersioningBehavior"R\n\x14\x44\x65ploymentTransition\x12:\n\ndeployment\x18\x01 \x01(\x0b\x32&.temporal.api.deployment.v1.Deployment"\x83\x01\n\x1b\x44\x65ploymentVersionTransition\x12\x13\n\x07version\x18\x01 \x01(\tB\x02\x18\x01\x12O\n\x12\x64\x65ployment_version\x18\x02 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersion"\xc7\x02\n\x17WorkflowExecutionConfig\x12\x38\n\ntask_queue\x18\x01 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12=\n\x1aworkflow_execution_timeout\x18\x02 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x37\n\x14workflow_run_timeout\x18\x03 \x01(\x0b\x32\x19.google.protobuf.Duration\x12@\n\x1d\x64\x65\x66\x61ult_workflow_task_timeout\x18\x04 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x38\n\ruser_metadata\x18\x05 \x01(\x0b\x32!.temporal.api.sdk.v1.UserMetadata"\xbd\r\n\x13PendingActivityInfo\x12\x13\n\x0b\x61\x63tivity_id\x18\x01 \x01(\t\x12;\n\ractivity_type\x18\x02 \x01(\x0b\x32$.temporal.api.common.v1.ActivityType\x12:\n\x05state\x18\x03 \x01(\x0e\x32+.temporal.api.enums.v1.PendingActivityState\x12;\n\x11heartbeat_details\x18\x04 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x37\n\x13last_heartbeat_time\x18\x05 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x35\n\x11last_started_time\x18\x06 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x0f\n\x07\x61ttempt\x18\x07 \x01(\x05\x12\x18\n\x10maximum_attempts\x18\x08 \x01(\x05\x12\x32\n\x0escheduled_time\x18\t \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x33\n\x0f\x65xpiration_time\x18\n \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x36\n\x0clast_failure\x18\x0b \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12\x1c\n\x14last_worker_identity\x18\x0c \x01(\t\x12;\n\x15use_workflow_build_id\x18\r \x01(\x0b\x32\x16.google.protobuf.EmptyB\x02\x18\x01H\x00\x12\x32\n$last_independently_assigned_build_id\x18\x0e \x01(\tB\x02\x18\x01H\x00\x12Q\n\x19last_worker_version_stamp\x18\x0f \x01(\x0b\x32*.temporal.api.common.v1.WorkerVersionStampB\x02\x18\x01\x12\x39\n\x16\x63urrent_retry_interval\x18\x10 \x01(\x0b\x32\x19.google.protobuf.Duration\x12>\n\x1alast_attempt_complete_time\x18\x11 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12>\n\x1anext_attempt_schedule_time\x18\x12 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x0e\n\x06paused\x18\x13 \x01(\x08\x12\x43\n\x0flast_deployment\x18\x14 \x01(\x0b\x32&.temporal.api.deployment.v1.DeploymentB\x02\x18\x01\x12*\n\x1elast_worker_deployment_version\x18\x15 \x01(\tB\x02\x18\x01\x12T\n\x17last_deployment_version\x18\x19 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersion\x12\x32\n\x08priority\x18\x16 \x01(\x0b\x32 .temporal.api.common.v1.Priority\x12K\n\npause_info\x18\x17 \x01(\x0b\x32\x37.temporal.api.workflow.v1.PendingActivityInfo.PauseInfo\x12\x43\n\x10\x61\x63tivity_options\x18\x18 \x01(\x0b\x32).temporal.api.activity.v1.ActivityOptions\x1a\xcf\x02\n\tPauseInfo\x12.\n\npause_time\x18\x01 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12P\n\x06manual\x18\x02 \x01(\x0b\x32>.temporal.api.workflow.v1.PendingActivityInfo.PauseInfo.ManualH\x00\x12L\n\x04rule\x18\x04 \x01(\x0b\x32<.temporal.api.workflow.v1.PendingActivityInfo.PauseInfo.RuleH\x00\x1a*\n\x06Manual\x12\x10\n\x08identity\x18\x01 \x01(\t\x12\x0e\n\x06reason\x18\x02 \x01(\t\x1a\x39\n\x04Rule\x12\x0f\n\x07rule_id\x18\x01 \x01(\t\x12\x10\n\x08identity\x18\x02 \x01(\t\x12\x0e\n\x06reason\x18\x03 \x01(\tB\x0b\n\tpaused_byB\x13\n\x11\x61ssigned_build_id"\xb9\x01\n\x19PendingChildExecutionInfo\x12\x13\n\x0bworkflow_id\x18\x01 \x01(\t\x12\x0e\n\x06run_id\x18\x02 \x01(\t\x12\x1a\n\x12workflow_type_name\x18\x03 \x01(\t\x12\x14\n\x0cinitiated_id\x18\x04 \x01(\x03\x12\x45\n\x13parent_close_policy\x18\x05 \x01(\x0e\x32(.temporal.api.enums.v1.ParentClosePolicy"\x8d\x02\n\x17PendingWorkflowTaskInfo\x12>\n\x05state\x18\x01 \x01(\x0e\x32/.temporal.api.enums.v1.PendingWorkflowTaskState\x12\x32\n\x0escheduled_time\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12;\n\x17original_scheduled_time\x18\x03 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x30\n\x0cstarted_time\x18\x04 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x0f\n\x07\x61ttempt\x18\x05 \x01(\x05"G\n\x0bResetPoints\x12\x38\n\x06points\x18\x01 \x03(\x0b\x32(.temporal.api.workflow.v1.ResetPointInfo"\xef\x01\n\x0eResetPointInfo\x12\x10\n\x08\x62uild_id\x18\x07 \x01(\t\x12\x1b\n\x0f\x62inary_checksum\x18\x01 \x01(\tB\x02\x18\x01\x12\x0e\n\x06run_id\x18\x02 \x01(\t\x12(\n first_workflow_task_completed_id\x18\x03 \x01(\x03\x12/\n\x0b\x63reate_time\x18\x04 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12/\n\x0b\x65xpire_time\x18\x05 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x12\n\nresettable\x18\x06 \x01(\x08"\x85\x07\n\x18NewWorkflowExecutionInfo\x12\x13\n\x0bworkflow_id\x18\x01 \x01(\t\x12;\n\rworkflow_type\x18\x02 \x01(\x0b\x32$.temporal.api.common.v1.WorkflowType\x12\x38\n\ntask_queue\x18\x03 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12/\n\x05input\x18\x04 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12=\n\x1aworkflow_execution_timeout\x18\x05 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x37\n\x14workflow_run_timeout\x18\x06 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x38\n\x15workflow_task_timeout\x18\x07 \x01(\x0b\x32\x19.google.protobuf.Duration\x12N\n\x18workflow_id_reuse_policy\x18\x08 \x01(\x0e\x32,.temporal.api.enums.v1.WorkflowIdReusePolicy\x12\x39\n\x0cretry_policy\x18\t \x01(\x0b\x32#.temporal.api.common.v1.RetryPolicy\x12\x15\n\rcron_schedule\x18\n \x01(\t\x12*\n\x04memo\x18\x0b \x01(\x0b\x32\x1c.temporal.api.common.v1.Memo\x12\x43\n\x11search_attributes\x18\x0c \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes\x12.\n\x06header\x18\r \x01(\x0b\x32\x1e.temporal.api.common.v1.Header\x12\x38\n\ruser_metadata\x18\x0e \x01(\x0b\x32!.temporal.api.sdk.v1.UserMetadata\x12I\n\x13versioning_override\x18\x0f \x01(\x0b\x32,.temporal.api.workflow.v1.VersioningOverride\x12\x32\n\x08priority\x18\x10 \x01(\x0b\x32 .temporal.api.common.v1.Priority"\x82\x06\n\x0c\x43\x61llbackInfo\x12\x32\n\x08\x63\x61llback\x18\x01 \x01(\x0b\x32 .temporal.api.common.v1.Callback\x12?\n\x07trigger\x18\x02 \x01(\x0b\x32..temporal.api.workflow.v1.CallbackInfo.Trigger\x12\x35\n\x11registration_time\x18\x03 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x33\n\x05state\x18\x04 \x01(\x0e\x32$.temporal.api.enums.v1.CallbackState\x12\x0f\n\x07\x61ttempt\x18\x05 \x01(\x05\x12>\n\x1alast_attempt_complete_time\x18\x06 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12>\n\x14last_attempt_failure\x18\x07 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12>\n\x1anext_attempt_schedule_time\x18\x08 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x16\n\x0e\x62locked_reason\x18\t \x01(\t\x1a\x10\n\x0eWorkflowClosed\x1a\x35\n UpdateWorkflowExecutionCompleted\x12\x11\n\tupdate_id\x18\x01 \x01(\t\x1a\xde\x01\n\x07Trigger\x12P\n\x0fworkflow_closed\x18\x01 \x01(\x0b\x32\x35.temporal.api.workflow.v1.CallbackInfo.WorkflowClosedH\x00\x12v\n#update_workflow_execution_completed\x18\x02 \x01(\x0b\x32G.temporal.api.workflow.v1.CallbackInfo.UpdateWorkflowExecutionCompletedH\x00\x42\t\n\x07variant"\x8b\x06\n\x19PendingNexusOperationInfo\x12\x10\n\x08\x65ndpoint\x18\x01 \x01(\t\x12\x0f\n\x07service\x18\x02 \x01(\t\x12\x11\n\toperation\x18\x03 \x01(\t\x12\x18\n\x0coperation_id\x18\x04 \x01(\tB\x02\x18\x01\x12<\n\x19schedule_to_close_timeout\x18\x05 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x32\n\x0escheduled_time\x18\x06 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12@\n\x05state\x18\x07 \x01(\x0e\x32\x31.temporal.api.enums.v1.PendingNexusOperationState\x12\x0f\n\x07\x61ttempt\x18\x08 \x01(\x05\x12>\n\x1alast_attempt_complete_time\x18\t \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12>\n\x14last_attempt_failure\x18\n \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12>\n\x1anext_attempt_schedule_time\x18\x0b \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12S\n\x11\x63\x61ncellation_info\x18\x0c \x01(\x0b\x32\x38.temporal.api.workflow.v1.NexusOperationCancellationInfo\x12\x1a\n\x12scheduled_event_id\x18\r \x01(\x03\x12\x16\n\x0e\x62locked_reason\x18\x0e \x01(\t\x12\x17\n\x0foperation_token\x18\x0f \x01(\t\x12<\n\x19schedule_to_start_timeout\x18\x10 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x39\n\x16start_to_close_timeout\x18\x11 \x01(\x0b\x32\x19.google.protobuf.Duration"\x84\x03\n\x1eNexusOperationCancellationInfo\x12\x32\n\x0erequested_time\x18\x01 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x45\n\x05state\x18\x02 \x01(\x0e\x32\x36.temporal.api.enums.v1.NexusOperationCancellationState\x12\x0f\n\x07\x61ttempt\x18\x03 \x01(\x05\x12>\n\x1alast_attempt_complete_time\x18\x04 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12>\n\x14last_attempt_failure\x18\x05 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12>\n\x1anext_attempt_schedule_time\x18\x06 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x16\n\x0e\x62locked_reason\x18\x07 \x01(\t"\xe5\x01\n\x18WorkflowExecutionOptions\x12I\n\x13versioning_override\x18\x01 \x01(\x0b\x32,.temporal.api.workflow.v1.VersioningOverride\x12\x32\n\x08priority\x18\x02 \x01(\x0b\x32 .temporal.api.common.v1.Priority\x12J\n\x14time_skipping_config\x18\x03 \x01(\x0b\x32,.temporal.api.workflow.v1.TimeSkippingConfig"\xd6\x01\n\x12TimeSkippingConfig\x12\x0f\n\x07\x65nabled\x18\x01 \x01(\x08\x12\x39\n\x14max_skipped_duration\x18\x04 \x01(\x0b\x32\x19.google.protobuf.DurationH\x00\x12\x39\n\x14max_elapsed_duration\x18\x05 \x01(\x0b\x32\x19.google.protobuf.DurationH\x00\x42\x07\n\x05\x62oundJ\x04\x08\x02\x10\x03J\x04\x08\x06\x10\x07R\x13\x64isable_propagationR\x0fmax_target_time"\xbd\x04\n\x12VersioningOverride\x12M\n\x06pinned\x18\x03 \x01(\x0b\x32;.temporal.api.workflow.v1.VersioningOverride.PinnedOverrideH\x00\x12\x16\n\x0c\x61uto_upgrade\x18\x04 \x01(\x08H\x00\x12?\n\x08\x62\x65havior\x18\x01 \x01(\x0e\x32).temporal.api.enums.v1.VersioningBehaviorB\x02\x18\x01\x12>\n\ndeployment\x18\x02 \x01(\x0b\x32&.temporal.api.deployment.v1.DeploymentB\x02\x18\x01\x12\x1a\n\x0epinned_version\x18\t \x01(\tB\x02\x18\x01\x1a\xad\x01\n\x0ePinnedOverride\x12U\n\x08\x62\x65havior\x18\x01 \x01(\x0e\x32\x43.temporal.api.workflow.v1.VersioningOverride.PinnedOverrideBehavior\x12\x44\n\x07version\x18\x02 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersion"g\n\x16PinnedOverrideBehavior\x12(\n$PINNED_OVERRIDE_BEHAVIOR_UNSPECIFIED\x10\x00\x12#\n\x1fPINNED_OVERRIDE_BEHAVIOR_PINNED\x10\x01\x42\n\n\x08override"i\n\x11OnConflictOptions\x12\x19\n\x11\x61ttach_request_id\x18\x01 \x01(\x08\x12#\n\x1b\x61ttach_completion_callbacks\x18\x02 \x01(\x08\x12\x14\n\x0c\x61ttach_links\x18\x03 \x01(\x08"i\n\rRequestIdInfo\x12\x34\n\nevent_type\x18\x01 \x01(\x0e\x32 .temporal.api.enums.v1.EventType\x12\x10\n\x08\x65vent_id\x18\x02 \x01(\x03\x12\x10\n\x08\x62uffered\x18\x03 \x01(\x08"\xb7\x04\n\x12PostResetOperation\x12V\n\x0fsignal_workflow\x18\x01 \x01(\x0b\x32;.temporal.api.workflow.v1.PostResetOperation.SignalWorkflowH\x00\x12\x65\n\x17update_workflow_options\x18\x02 \x01(\x0b\x32\x42.temporal.api.workflow.v1.PostResetOperation.UpdateWorkflowOptionsH\x00\x1a\xb3\x01\n\x0eSignalWorkflow\x12\x13\n\x0bsignal_name\x18\x01 \x01(\t\x12/\n\x05input\x18\x02 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12.\n\x06header\x18\x03 \x01(\x0b\x32\x1e.temporal.api.common.v1.Header\x12+\n\x05links\x18\x04 \x03(\x0b\x32\x1c.temporal.api.common.v1.Link\x1a\xa0\x01\n\x15UpdateWorkflowOptions\x12V\n\x1aworkflow_execution_options\x18\x01 \x01(\x0b\x32\x32.temporal.api.workflow.v1.WorkflowExecutionOptions\x12/\n\x0bupdate_mask\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.FieldMaskB\t\n\x07variant"o\n\x1aWorkflowExecutionPauseInfo\x12\x10\n\x08identity\x18\x01 \x01(\t\x12/\n\x0bpaused_time\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x0e\n\x06reason\x18\x03 \x01(\tB\x93\x01\n\x1bio.temporal.api.workflow.v1B\x0cMessageProtoP\x01Z\'go.temporal.io/api/workflow/v1;workflow\xaa\x02\x1aTemporalio.Api.Workflow.V1\xea\x02\x1dTemporalio::Api::Workflow::V1b\x06proto3' + b'\n&temporal/api/workflow/v1/message.proto\x12\x18temporal.api.workflow.v1\x1a\x1egoogle/protobuf/duration.proto\x1a\x1bgoogle/protobuf/empty.proto\x1a\x1fgoogle/protobuf/timestamp.proto\x1a google/protobuf/field_mask.proto\x1a&temporal/api/activity/v1/message.proto\x1a"temporal/api/enums/v1/common.proto\x1a&temporal/api/enums/v1/event_type.proto\x1a$temporal/api/enums/v1/workflow.proto\x1a$temporal/api/common/v1/message.proto\x1a(temporal/api/deployment/v1/message.proto\x1a%temporal/api/failure/v1/message.proto\x1a\'temporal/api/taskqueue/v1/message.proto\x1a\'temporal/api/sdk/v1/user_metadata.proto"\xf0\t\n\x15WorkflowExecutionInfo\x12<\n\texecution\x18\x01 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x32\n\x04type\x18\x02 \x01(\x0b\x32$.temporal.api.common.v1.WorkflowType\x12.\n\nstart_time\x18\x03 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12.\n\nclose_time\x18\x04 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12>\n\x06status\x18\x05 \x01(\x0e\x32..temporal.api.enums.v1.WorkflowExecutionStatus\x12\x16\n\x0ehistory_length\x18\x06 \x01(\x03\x12\x1b\n\x13parent_namespace_id\x18\x07 \x01(\t\x12\x43\n\x10parent_execution\x18\x08 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x32\n\x0e\x65xecution_time\x18\t \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12*\n\x04memo\x18\n \x01(\x0b\x32\x1c.temporal.api.common.v1.Memo\x12\x43\n\x11search_attributes\x18\x0b \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes\x12@\n\x11\x61uto_reset_points\x18\x0c \x01(\x0b\x32%.temporal.api.workflow.v1.ResetPoints\x12\x12\n\ntask_queue\x18\r \x01(\t\x12\x1e\n\x16state_transition_count\x18\x0e \x01(\x03\x12\x1a\n\x12history_size_bytes\x18\x0f \x01(\x03\x12X\n most_recent_worker_version_stamp\x18\x10 \x01(\x0b\x32*.temporal.api.common.v1.WorkerVersionStampB\x02\x18\x01\x12\x35\n\x12\x65xecution_duration\x18\x11 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x41\n\x0eroot_execution\x18\x12 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x1d\n\x11\x61ssigned_build_id\x18\x13 \x01(\tB\x02\x18\x01\x12\x1e\n\x12inherited_build_id\x18\x14 \x01(\tB\x02\x18\x01\x12\x14\n\x0c\x66irst_run_id\x18\x15 \x01(\t\x12R\n\x0fversioning_info\x18\x16 \x01(\x0b\x32\x39.temporal.api.workflow.v1.WorkflowExecutionVersioningInfo\x12\x1e\n\x16worker_deployment_name\x18\x17 \x01(\t\x12\x32\n\x08priority\x18\x18 \x01(\x0b\x32 .temporal.api.common.v1.Priority\x12#\n\x1b\x65xternal_payload_size_bytes\x18\x19 \x01(\x03\x12\x1e\n\x16\x65xternal_payload_count\x18\x1a \x01(\x03"\xc6\x04\n\x1dWorkflowExecutionExtendedInfo\x12=\n\x19\x65xecution_expiration_time\x18\x01 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x37\n\x13run_expiration_time\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x18\n\x10\x63\x61ncel_requested\x18\x03 \x01(\x08\x12\x33\n\x0flast_reset_time\x18\x04 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x37\n\x13original_start_time\x18\x05 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x14\n\x0creset_run_id\x18\x06 \x01(\t\x12\x65\n\x10request_id_infos\x18\x07 \x03(\x0b\x32K.temporal.api.workflow.v1.WorkflowExecutionExtendedInfo.RequestIdInfosEntry\x12H\n\npause_info\x18\x08 \x01(\x0b\x32\x34.temporal.api.workflow.v1.WorkflowExecutionPauseInfo\x1a^\n\x13RequestIdInfosEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x36\n\x05value\x18\x02 \x01(\x0b\x32\'.temporal.api.workflow.v1.RequestIdInfo:\x02\x38\x01"\xfb\x04\n\x1fWorkflowExecutionVersioningInfo\x12;\n\x08\x62\x65havior\x18\x01 \x01(\x0e\x32).temporal.api.enums.v1.VersioningBehavior\x12>\n\ndeployment\x18\x02 \x01(\x0b\x32&.temporal.api.deployment.v1.DeploymentB\x02\x18\x01\x12\x13\n\x07version\x18\x05 \x01(\tB\x02\x18\x01\x12O\n\x12\x64\x65ployment_version\x18\x07 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersion\x12I\n\x13versioning_override\x18\x03 \x01(\x0b\x32,.temporal.api.workflow.v1.VersioningOverride\x12Q\n\x15\x64\x65ployment_transition\x18\x04 \x01(\x0b\x32..temporal.api.workflow.v1.DeploymentTransitionB\x02\x18\x01\x12Q\n\x12version_transition\x18\x06 \x01(\x0b\x32\x35.temporal.api.workflow.v1.DeploymentVersionTransition\x12\x17\n\x0frevision_number\x18\x08 \x01(\x03\x12k\n+continue_as_new_initial_versioning_behavior\x18\t \x01(\x0e\x32\x36.temporal.api.enums.v1.ContinueAsNewVersioningBehavior"R\n\x14\x44\x65ploymentTransition\x12:\n\ndeployment\x18\x01 \x01(\x0b\x32&.temporal.api.deployment.v1.Deployment"\x83\x01\n\x1b\x44\x65ploymentVersionTransition\x12\x13\n\x07version\x18\x01 \x01(\tB\x02\x18\x01\x12O\n\x12\x64\x65ployment_version\x18\x02 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersion"\xc7\x02\n\x17WorkflowExecutionConfig\x12\x38\n\ntask_queue\x18\x01 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12=\n\x1aworkflow_execution_timeout\x18\x02 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x37\n\x14workflow_run_timeout\x18\x03 \x01(\x0b\x32\x19.google.protobuf.Duration\x12@\n\x1d\x64\x65\x66\x61ult_workflow_task_timeout\x18\x04 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x38\n\ruser_metadata\x18\x05 \x01(\x0b\x32!.temporal.api.sdk.v1.UserMetadata"\xbd\r\n\x13PendingActivityInfo\x12\x13\n\x0b\x61\x63tivity_id\x18\x01 \x01(\t\x12;\n\ractivity_type\x18\x02 \x01(\x0b\x32$.temporal.api.common.v1.ActivityType\x12:\n\x05state\x18\x03 \x01(\x0e\x32+.temporal.api.enums.v1.PendingActivityState\x12;\n\x11heartbeat_details\x18\x04 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x37\n\x13last_heartbeat_time\x18\x05 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x35\n\x11last_started_time\x18\x06 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x0f\n\x07\x61ttempt\x18\x07 \x01(\x05\x12\x18\n\x10maximum_attempts\x18\x08 \x01(\x05\x12\x32\n\x0escheduled_time\x18\t \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x33\n\x0f\x65xpiration_time\x18\n \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x36\n\x0clast_failure\x18\x0b \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12\x1c\n\x14last_worker_identity\x18\x0c \x01(\t\x12;\n\x15use_workflow_build_id\x18\r \x01(\x0b\x32\x16.google.protobuf.EmptyB\x02\x18\x01H\x00\x12\x32\n$last_independently_assigned_build_id\x18\x0e \x01(\tB\x02\x18\x01H\x00\x12Q\n\x19last_worker_version_stamp\x18\x0f \x01(\x0b\x32*.temporal.api.common.v1.WorkerVersionStampB\x02\x18\x01\x12\x39\n\x16\x63urrent_retry_interval\x18\x10 \x01(\x0b\x32\x19.google.protobuf.Duration\x12>\n\x1alast_attempt_complete_time\x18\x11 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12>\n\x1anext_attempt_schedule_time\x18\x12 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x0e\n\x06paused\x18\x13 \x01(\x08\x12\x43\n\x0flast_deployment\x18\x14 \x01(\x0b\x32&.temporal.api.deployment.v1.DeploymentB\x02\x18\x01\x12*\n\x1elast_worker_deployment_version\x18\x15 \x01(\tB\x02\x18\x01\x12T\n\x17last_deployment_version\x18\x19 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersion\x12\x32\n\x08priority\x18\x16 \x01(\x0b\x32 .temporal.api.common.v1.Priority\x12K\n\npause_info\x18\x17 \x01(\x0b\x32\x37.temporal.api.workflow.v1.PendingActivityInfo.PauseInfo\x12\x43\n\x10\x61\x63tivity_options\x18\x18 \x01(\x0b\x32).temporal.api.activity.v1.ActivityOptions\x1a\xcf\x02\n\tPauseInfo\x12.\n\npause_time\x18\x01 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12P\n\x06manual\x18\x02 \x01(\x0b\x32>.temporal.api.workflow.v1.PendingActivityInfo.PauseInfo.ManualH\x00\x12L\n\x04rule\x18\x04 \x01(\x0b\x32<.temporal.api.workflow.v1.PendingActivityInfo.PauseInfo.RuleH\x00\x1a*\n\x06Manual\x12\x10\n\x08identity\x18\x01 \x01(\t\x12\x0e\n\x06reason\x18\x02 \x01(\t\x1a\x39\n\x04Rule\x12\x0f\n\x07rule_id\x18\x01 \x01(\t\x12\x10\n\x08identity\x18\x02 \x01(\t\x12\x0e\n\x06reason\x18\x03 \x01(\tB\x0b\n\tpaused_byB\x13\n\x11\x61ssigned_build_id"\xb9\x01\n\x19PendingChildExecutionInfo\x12\x13\n\x0bworkflow_id\x18\x01 \x01(\t\x12\x0e\n\x06run_id\x18\x02 \x01(\t\x12\x1a\n\x12workflow_type_name\x18\x03 \x01(\t\x12\x14\n\x0cinitiated_id\x18\x04 \x01(\x03\x12\x45\n\x13parent_close_policy\x18\x05 \x01(\x0e\x32(.temporal.api.enums.v1.ParentClosePolicy"\x8d\x02\n\x17PendingWorkflowTaskInfo\x12>\n\x05state\x18\x01 \x01(\x0e\x32/.temporal.api.enums.v1.PendingWorkflowTaskState\x12\x32\n\x0escheduled_time\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12;\n\x17original_scheduled_time\x18\x03 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x30\n\x0cstarted_time\x18\x04 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x0f\n\x07\x61ttempt\x18\x05 \x01(\x05"G\n\x0bResetPoints\x12\x38\n\x06points\x18\x01 \x03(\x0b\x32(.temporal.api.workflow.v1.ResetPointInfo"\xef\x01\n\x0eResetPointInfo\x12\x10\n\x08\x62uild_id\x18\x07 \x01(\t\x12\x1b\n\x0f\x62inary_checksum\x18\x01 \x01(\tB\x02\x18\x01\x12\x0e\n\x06run_id\x18\x02 \x01(\t\x12(\n first_workflow_task_completed_id\x18\x03 \x01(\x03\x12/\n\x0b\x63reate_time\x18\x04 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12/\n\x0b\x65xpire_time\x18\x05 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x12\n\nresettable\x18\x06 \x01(\x08"\x85\x07\n\x18NewWorkflowExecutionInfo\x12\x13\n\x0bworkflow_id\x18\x01 \x01(\t\x12;\n\rworkflow_type\x18\x02 \x01(\x0b\x32$.temporal.api.common.v1.WorkflowType\x12\x38\n\ntask_queue\x18\x03 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12/\n\x05input\x18\x04 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12=\n\x1aworkflow_execution_timeout\x18\x05 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x37\n\x14workflow_run_timeout\x18\x06 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x38\n\x15workflow_task_timeout\x18\x07 \x01(\x0b\x32\x19.google.protobuf.Duration\x12N\n\x18workflow_id_reuse_policy\x18\x08 \x01(\x0e\x32,.temporal.api.enums.v1.WorkflowIdReusePolicy\x12\x39\n\x0cretry_policy\x18\t \x01(\x0b\x32#.temporal.api.common.v1.RetryPolicy\x12\x15\n\rcron_schedule\x18\n \x01(\t\x12*\n\x04memo\x18\x0b \x01(\x0b\x32\x1c.temporal.api.common.v1.Memo\x12\x43\n\x11search_attributes\x18\x0c \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes\x12.\n\x06header\x18\r \x01(\x0b\x32\x1e.temporal.api.common.v1.Header\x12\x38\n\ruser_metadata\x18\x0e \x01(\x0b\x32!.temporal.api.sdk.v1.UserMetadata\x12I\n\x13versioning_override\x18\x0f \x01(\x0b\x32,.temporal.api.workflow.v1.VersioningOverride\x12\x32\n\x08priority\x18\x10 \x01(\x0b\x32 .temporal.api.common.v1.Priority"\x82\x06\n\x0c\x43\x61llbackInfo\x12\x32\n\x08\x63\x61llback\x18\x01 \x01(\x0b\x32 .temporal.api.common.v1.Callback\x12?\n\x07trigger\x18\x02 \x01(\x0b\x32..temporal.api.workflow.v1.CallbackInfo.Trigger\x12\x35\n\x11registration_time\x18\x03 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x33\n\x05state\x18\x04 \x01(\x0e\x32$.temporal.api.enums.v1.CallbackState\x12\x0f\n\x07\x61ttempt\x18\x05 \x01(\x05\x12>\n\x1alast_attempt_complete_time\x18\x06 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12>\n\x14last_attempt_failure\x18\x07 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12>\n\x1anext_attempt_schedule_time\x18\x08 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x16\n\x0e\x62locked_reason\x18\t \x01(\t\x1a\x10\n\x0eWorkflowClosed\x1a\x35\n UpdateWorkflowExecutionCompleted\x12\x11\n\tupdate_id\x18\x01 \x01(\t\x1a\xde\x01\n\x07Trigger\x12P\n\x0fworkflow_closed\x18\x01 \x01(\x0b\x32\x35.temporal.api.workflow.v1.CallbackInfo.WorkflowClosedH\x00\x12v\n#update_workflow_execution_completed\x18\x02 \x01(\x0b\x32G.temporal.api.workflow.v1.CallbackInfo.UpdateWorkflowExecutionCompletedH\x00\x42\t\n\x07variant"\x8b\x06\n\x19PendingNexusOperationInfo\x12\x10\n\x08\x65ndpoint\x18\x01 \x01(\t\x12\x0f\n\x07service\x18\x02 \x01(\t\x12\x11\n\toperation\x18\x03 \x01(\t\x12\x18\n\x0coperation_id\x18\x04 \x01(\tB\x02\x18\x01\x12<\n\x19schedule_to_close_timeout\x18\x05 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x32\n\x0escheduled_time\x18\x06 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12@\n\x05state\x18\x07 \x01(\x0e\x32\x31.temporal.api.enums.v1.PendingNexusOperationState\x12\x0f\n\x07\x61ttempt\x18\x08 \x01(\x05\x12>\n\x1alast_attempt_complete_time\x18\t \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12>\n\x14last_attempt_failure\x18\n \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12>\n\x1anext_attempt_schedule_time\x18\x0b \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12S\n\x11\x63\x61ncellation_info\x18\x0c \x01(\x0b\x32\x38.temporal.api.workflow.v1.NexusOperationCancellationInfo\x12\x1a\n\x12scheduled_event_id\x18\r \x01(\x03\x12\x16\n\x0e\x62locked_reason\x18\x0e \x01(\t\x12\x17\n\x0foperation_token\x18\x0f \x01(\t\x12<\n\x19schedule_to_start_timeout\x18\x10 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x39\n\x16start_to_close_timeout\x18\x11 \x01(\x0b\x32\x19.google.protobuf.Duration"\x84\x03\n\x1eNexusOperationCancellationInfo\x12\x32\n\x0erequested_time\x18\x01 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x45\n\x05state\x18\x02 \x01(\x0e\x32\x36.temporal.api.enums.v1.NexusOperationCancellationState\x12\x0f\n\x07\x61ttempt\x18\x03 \x01(\x05\x12>\n\x1alast_attempt_complete_time\x18\x04 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12>\n\x14last_attempt_failure\x18\x05 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12>\n\x1anext_attempt_schedule_time\x18\x06 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x16\n\x0e\x62locked_reason\x18\x07 \x01(\t"\xe3\x01\n\x18WorkflowExecutionOptions\x12I\n\x13versioning_override\x18\x01 \x01(\x0b\x32,.temporal.api.workflow.v1.VersioningOverride\x12\x32\n\x08priority\x18\x02 \x01(\x0b\x32 .temporal.api.common.v1.Priority\x12H\n\x14time_skipping_config\x18\x03 \x01(\x0b\x32*.temporal.api.common.v1.TimeSkippingConfig"\xfa\x05\n\x12VersioningOverride\x12M\n\x06pinned\x18\x03 \x01(\x0b\x32;.temporal.api.workflow.v1.VersioningOverride.PinnedOverrideH\x00\x12\x16\n\x0c\x61uto_upgrade\x18\x04 \x01(\x08H\x00\x12P\n\x08one_time\x18\x05 \x01(\x0b\x32<.temporal.api.workflow.v1.VersioningOverride.OneTimeOverrideH\x00\x12?\n\x08\x62\x65havior\x18\x01 \x01(\x0e\x32).temporal.api.enums.v1.VersioningBehaviorB\x02\x18\x01\x12>\n\ndeployment\x18\x02 \x01(\x0b\x32&.temporal.api.deployment.v1.DeploymentB\x02\x18\x01\x12\x1a\n\x0epinned_version\x18\t \x01(\tB\x02\x18\x01\x1a\xad\x01\n\x0ePinnedOverride\x12U\n\x08\x62\x65havior\x18\x01 \x01(\x0e\x32\x43.temporal.api.workflow.v1.VersioningOverride.PinnedOverrideBehavior\x12\x44\n\x07version\x18\x02 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersion\x1ai\n\x0fOneTimeOverride\x12V\n\x19target_deployment_version\x18\x01 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersion"g\n\x16PinnedOverrideBehavior\x12(\n$PINNED_OVERRIDE_BEHAVIOR_UNSPECIFIED\x10\x00\x12#\n\x1fPINNED_OVERRIDE_BEHAVIOR_PINNED\x10\x01\x42\n\n\x08override"i\n\x11OnConflictOptions\x12\x19\n\x11\x61ttach_request_id\x18\x01 \x01(\x08\x12#\n\x1b\x61ttach_completion_callbacks\x18\x02 \x01(\x08\x12\x14\n\x0c\x61ttach_links\x18\x03 \x01(\x08"i\n\rRequestIdInfo\x12\x34\n\nevent_type\x18\x01 \x01(\x0e\x32 .temporal.api.enums.v1.EventType\x12\x10\n\x08\x65vent_id\x18\x02 \x01(\x03\x12\x10\n\x08\x62uffered\x18\x03 \x01(\x08"\xb7\x04\n\x12PostResetOperation\x12V\n\x0fsignal_workflow\x18\x01 \x01(\x0b\x32;.temporal.api.workflow.v1.PostResetOperation.SignalWorkflowH\x00\x12\x65\n\x17update_workflow_options\x18\x02 \x01(\x0b\x32\x42.temporal.api.workflow.v1.PostResetOperation.UpdateWorkflowOptionsH\x00\x1a\xb3\x01\n\x0eSignalWorkflow\x12\x13\n\x0bsignal_name\x18\x01 \x01(\t\x12/\n\x05input\x18\x02 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12.\n\x06header\x18\x03 \x01(\x0b\x32\x1e.temporal.api.common.v1.Header\x12+\n\x05links\x18\x04 \x03(\x0b\x32\x1c.temporal.api.common.v1.Link\x1a\xa0\x01\n\x15UpdateWorkflowOptions\x12V\n\x1aworkflow_execution_options\x18\x01 \x01(\x0b\x32\x32.temporal.api.workflow.v1.WorkflowExecutionOptions\x12/\n\x0bupdate_mask\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.FieldMaskB\t\n\x07variant"o\n\x1aWorkflowExecutionPauseInfo\x12\x10\n\x08identity\x18\x01 \x01(\t\x12/\n\x0bpaused_time\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x0e\n\x06reason\x18\x03 \x01(\tB\x93\x01\n\x1bio.temporal.api.workflow.v1B\x0cMessageProtoP\x01Z\'go.temporal.io/api/workflow/v1;workflow\xaa\x02\x1aTemporalio.Api.Workflow.V1\xea\x02\x1dTemporalio::Api::Workflow::V1b\x06proto3' ) @@ -95,11 +95,13 @@ "NexusOperationCancellationInfo" ] _WORKFLOWEXECUTIONOPTIONS = DESCRIPTOR.message_types_by_name["WorkflowExecutionOptions"] -_TIMESKIPPINGCONFIG = DESCRIPTOR.message_types_by_name["TimeSkippingConfig"] _VERSIONINGOVERRIDE = DESCRIPTOR.message_types_by_name["VersioningOverride"] _VERSIONINGOVERRIDE_PINNEDOVERRIDE = _VERSIONINGOVERRIDE.nested_types_by_name[ "PinnedOverride" ] +_VERSIONINGOVERRIDE_ONETIMEOVERRIDE = _VERSIONINGOVERRIDE.nested_types_by_name[ + "OneTimeOverride" +] _ONCONFLICTOPTIONS = DESCRIPTOR.message_types_by_name["OnConflictOptions"] _REQUESTIDINFO = DESCRIPTOR.message_types_by_name["RequestIdInfo"] _POSTRESETOPERATION = DESCRIPTOR.message_types_by_name["PostResetOperation"] @@ -361,17 +363,6 @@ ) _sym_db.RegisterMessage(WorkflowExecutionOptions) -TimeSkippingConfig = _reflection.GeneratedProtocolMessageType( - "TimeSkippingConfig", - (_message.Message,), - { - "DESCRIPTOR": _TIMESKIPPINGCONFIG, - "__module__": "temporalio.api.workflow.v1.message_pb2", - # @@protoc_insertion_point(class_scope:temporal.api.workflow.v1.TimeSkippingConfig) - }, -) -_sym_db.RegisterMessage(TimeSkippingConfig) - VersioningOverride = _reflection.GeneratedProtocolMessageType( "VersioningOverride", (_message.Message,), @@ -385,6 +376,15 @@ # @@protoc_insertion_point(class_scope:temporal.api.workflow.v1.VersioningOverride.PinnedOverride) }, ), + "OneTimeOverride": _reflection.GeneratedProtocolMessageType( + "OneTimeOverride", + (_message.Message,), + { + "DESCRIPTOR": _VERSIONINGOVERRIDE_ONETIMEOVERRIDE, + "__module__": "temporalio.api.workflow.v1.message_pb2", + # @@protoc_insertion_point(class_scope:temporal.api.workflow.v1.VersioningOverride.OneTimeOverride) + }, + ), "DESCRIPTOR": _VERSIONINGOVERRIDE, "__module__": "temporalio.api.workflow.v1.message_pb2", # @@protoc_insertion_point(class_scope:temporal.api.workflow.v1.VersioningOverride) @@ -392,6 +392,7 @@ ) _sym_db.RegisterMessage(VersioningOverride) _sym_db.RegisterMessage(VersioningOverride.PinnedOverride) +_sym_db.RegisterMessage(VersioningOverride.OneTimeOverride) OnConflictOptions = _reflection.GeneratedProtocolMessageType( "OnConflictOptions", @@ -577,25 +578,25 @@ _NEXUSOPERATIONCANCELLATIONINFO._serialized_start = 8552 _NEXUSOPERATIONCANCELLATIONINFO._serialized_end = 8940 _WORKFLOWEXECUTIONOPTIONS._serialized_start = 8943 - _WORKFLOWEXECUTIONOPTIONS._serialized_end = 9172 - _TIMESKIPPINGCONFIG._serialized_start = 9175 - _TIMESKIPPINGCONFIG._serialized_end = 9389 - _VERSIONINGOVERRIDE._serialized_start = 9392 - _VERSIONINGOVERRIDE._serialized_end = 9965 - _VERSIONINGOVERRIDE_PINNEDOVERRIDE._serialized_start = 9675 - _VERSIONINGOVERRIDE_PINNEDOVERRIDE._serialized_end = 9848 - _VERSIONINGOVERRIDE_PINNEDOVERRIDEBEHAVIOR._serialized_start = 9850 - _VERSIONINGOVERRIDE_PINNEDOVERRIDEBEHAVIOR._serialized_end = 9953 - _ONCONFLICTOPTIONS._serialized_start = 9967 - _ONCONFLICTOPTIONS._serialized_end = 10072 - _REQUESTIDINFO._serialized_start = 10074 - _REQUESTIDINFO._serialized_end = 10179 - _POSTRESETOPERATION._serialized_start = 10182 - _POSTRESETOPERATION._serialized_end = 10749 - _POSTRESETOPERATION_SIGNALWORKFLOW._serialized_start = 10396 - _POSTRESETOPERATION_SIGNALWORKFLOW._serialized_end = 10575 - _POSTRESETOPERATION_UPDATEWORKFLOWOPTIONS._serialized_start = 10578 - _POSTRESETOPERATION_UPDATEWORKFLOWOPTIONS._serialized_end = 10738 - _WORKFLOWEXECUTIONPAUSEINFO._serialized_start = 10751 - _WORKFLOWEXECUTIONPAUSEINFO._serialized_end = 10862 + _WORKFLOWEXECUTIONOPTIONS._serialized_end = 9170 + _VERSIONINGOVERRIDE._serialized_start = 9173 + _VERSIONINGOVERRIDE._serialized_end = 9935 + _VERSIONINGOVERRIDE_PINNEDOVERRIDE._serialized_start = 9538 + _VERSIONINGOVERRIDE_PINNEDOVERRIDE._serialized_end = 9711 + _VERSIONINGOVERRIDE_ONETIMEOVERRIDE._serialized_start = 9713 + _VERSIONINGOVERRIDE_ONETIMEOVERRIDE._serialized_end = 9818 + _VERSIONINGOVERRIDE_PINNEDOVERRIDEBEHAVIOR._serialized_start = 9820 + _VERSIONINGOVERRIDE_PINNEDOVERRIDEBEHAVIOR._serialized_end = 9923 + _ONCONFLICTOPTIONS._serialized_start = 9937 + _ONCONFLICTOPTIONS._serialized_end = 10042 + _REQUESTIDINFO._serialized_start = 10044 + _REQUESTIDINFO._serialized_end = 10149 + _POSTRESETOPERATION._serialized_start = 10152 + _POSTRESETOPERATION._serialized_end = 10719 + _POSTRESETOPERATION_SIGNALWORKFLOW._serialized_start = 10366 + _POSTRESETOPERATION_SIGNALWORKFLOW._serialized_end = 10545 + _POSTRESETOPERATION_UPDATEWORKFLOWOPTIONS._serialized_start = 10548 + _POSTRESETOPERATION_UPDATEWORKFLOWOPTIONS._serialized_end = 10708 + _WORKFLOWEXECUTIONPAUSEINFO._serialized_start = 10721 + _WORKFLOWEXECUTIONPAUSEINFO._serialized_end = 10832 # @@protoc_insertion_point(module_scope) diff --git a/temporalio/api/workflow/v1/message_pb2.pyi b/temporalio/api/workflow/v1/message_pb2.pyi index e9491a87c..2aa370a8e 100644 --- a/temporalio/api/workflow/v1/message_pb2.pyi +++ b/temporalio/api/workflow/v1/message_pb2.pyi @@ -1886,17 +1886,26 @@ class WorkflowExecutionOptions(google.protobuf.message.Message): def priority(self) -> temporalio.api.common.v1.message_pb2.Priority: """If set, overrides the workflow's priority sent by the SDK.""" @property - def time_skipping_config(self) -> global___TimeSkippingConfig: - """Time-skipping configuration for this workflow execution. - If not set, the time-skipping configuration is not updated by this request; - the existing configuration is preserved. + def time_skipping_config( + self, + ) -> temporalio.api.common.v1.message_pb2.TimeSkippingConfig: + """The time-skipping configuration for this workflow execution. + When `fast_forward` is set, time will be fast-forwarded to a future point relative + to the current workflow timestamp. Each call takes effect, even if + `fast_forward` is set to the same duration, since the target time is recalculated + from the current timestamp on every call. + + This field must be updated as a whole; updating individual sub-fields is not supported. + When setting the update mask in `UpdateWorkflowExecutionOptionsRequest`, + `BatchOperationUpdateWorkflowExecutionOptions`, etc., use a mask that covers the entire field. """ def __init__( self, *, versioning_override: global___VersioningOverride | None = ..., priority: temporalio.api.common.v1.message_pb2.Priority | None = ..., - time_skipping_config: global___TimeSkippingConfig | None = ..., + time_skipping_config: temporalio.api.common.v1.message_pb2.TimeSkippingConfig + | None = ..., ) -> None: ... def HasField( self, @@ -1923,81 +1932,6 @@ class WorkflowExecutionOptions(google.protobuf.message.Message): global___WorkflowExecutionOptions = WorkflowExecutionOptions -class TimeSkippingConfig(google.protobuf.message.Message): - """Configuration for time skipping during a workflow execution. - When enabled, virtual time advances automatically whenever there is no in-flight work. - In-flight work includes activities, child workflows, Nexus operations, signal/cancel external workflow operations, - and possibly other features added in the future. - User timers are not classified as in-flight work and will be skipped over. - When time advances, it skips to the earlier of the next user timer or the configured bound, if either exists. - - Propagation behavior of time skipping: - The enabled flag, bound fields, and accumulated skipped duration are propagated to related executions as follows: - (1) Child workflows and continue-as-new: both the configuration and the accumulated skipped duration are - inherited from the current execution. The configured bound is shared between the inherited skipped - duration and any additional duration skipped by the new run. - (2) Retry and cron: the configuration and accumulated skipped duration are inherited as recorded when the - current workflow started; the accumulated skipped duration of the current run is not propagated. - (3) Reset: the new run retains the time-skipping configuration of the current execution. Because reset replays - all events up to the reset point and re-applies any UpdateWorkflowExecutionOptions changes made after that - point, the resulting run ends up with the same final time-skipping configuration as the previous run. - """ - - DESCRIPTOR: google.protobuf.descriptor.Descriptor - - ENABLED_FIELD_NUMBER: builtins.int - MAX_SKIPPED_DURATION_FIELD_NUMBER: builtins.int - MAX_ELAPSED_DURATION_FIELD_NUMBER: builtins.int - enabled: builtins.bool - """Enables or disables time skipping for this workflow execution.""" - @property - def max_skipped_duration(self) -> google.protobuf.duration_pb2.Duration: - """Maximum total virtual time that can be skipped.""" - @property - def max_elapsed_duration(self) -> google.protobuf.duration_pb2.Duration: - """Maximum elapsed time since time skipping was enabled. - This includes both skipped time and real time elapsing. - (-- api-linter: core::0142::time-field-names=disabled --) - """ - def __init__( - self, - *, - enabled: builtins.bool = ..., - max_skipped_duration: google.protobuf.duration_pb2.Duration | None = ..., - max_elapsed_duration: google.protobuf.duration_pb2.Duration | None = ..., - ) -> None: ... - def HasField( - self, - field_name: typing_extensions.Literal[ - "bound", - b"bound", - "max_elapsed_duration", - b"max_elapsed_duration", - "max_skipped_duration", - b"max_skipped_duration", - ], - ) -> builtins.bool: ... - def ClearField( - self, - field_name: typing_extensions.Literal[ - "bound", - b"bound", - "enabled", - b"enabled", - "max_elapsed_duration", - b"max_elapsed_duration", - "max_skipped_duration", - b"max_skipped_duration", - ], - ) -> None: ... - def WhichOneof( - self, oneof_group: typing_extensions.Literal["bound", b"bound"] - ) -> ( - typing_extensions.Literal["max_skipped_duration", "max_elapsed_duration"] | None - ): ... - -global___TimeSkippingConfig = TimeSkippingConfig - class VersioningOverride(google.protobuf.message.Message): """Used to override the versioning behavior (and pinned deployment version, if applicable) of a specific workflow execution. If set, this override takes precedence over worker-sent values. @@ -2083,16 +2017,78 @@ class VersioningOverride(google.protobuf.message.Message): ], ) -> None: ... + class OneTimeOverride(google.protobuf.message.Message): + """Routes Workflow Tasks for this execution to `target_deployment_version` + until a Workflow Task completes on that version, then clears the override. + + This does not force the workflow's normal Versioning Behavior to become + Pinned. After the Workflow Task completes on `target_deployment_version`, + the workflow execution's normal Versioning Behavior and Deployment Version + are taken from the worker's completion response. + + Example: if an execution is one-time moved from version X to version Y, and + version Z later becomes current: + - if worker Y reports Pinned, the execution stays on Y; + - if worker Y reports AutoUpgrade, the execution routes to Z on a future + Workflow Task; + - if worker Y reports Pinned and the workflow uses upgrade-on-continue-as-new, + the current run stays on Y and the execution can route to Z after + continue-as-new. + + If no Workflow Task completes on `target_deployment_version`, this override + remains pending. + """ + + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + TARGET_DEPLOYMENT_VERSION_FIELD_NUMBER: builtins.int + @property + def target_deployment_version( + self, + ) -> temporalio.api.deployment.v1.message_pb2.WorkerDeploymentVersion: + """Required. Worker Deployment Version to receive the one-time Workflow Task.""" + def __init__( + self, + *, + target_deployment_version: temporalio.api.deployment.v1.message_pb2.WorkerDeploymentVersion + | None = ..., + ) -> None: ... + def HasField( + self, + field_name: typing_extensions.Literal[ + "target_deployment_version", b"target_deployment_version" + ], + ) -> builtins.bool: ... + def ClearField( + self, + field_name: typing_extensions.Literal[ + "target_deployment_version", b"target_deployment_version" + ], + ) -> None: ... + PINNED_FIELD_NUMBER: builtins.int AUTO_UPGRADE_FIELD_NUMBER: builtins.int + ONE_TIME_FIELD_NUMBER: builtins.int BEHAVIOR_FIELD_NUMBER: builtins.int DEPLOYMENT_FIELD_NUMBER: builtins.int PINNED_VERSION_FIELD_NUMBER: builtins.int @property def pinned(self) -> global___VersioningOverride.PinnedOverride: - """Override the workflow to have Pinned behavior.""" + """Override the workflow to have Pinned behavior. This is a sticky override: + Workflow Tasks continue to route according to this override until it is + explicitly removed. + """ auto_upgrade: builtins.bool """Override the workflow to have AutoUpgrade behavior.""" + @property + def one_time(self) -> global___VersioningOverride.OneTimeOverride: + """Override Workflow Task routing to a specific Worker Deployment Version until + one Workflow Task completes there. After completion, the workflow execution's + Versioning Behavior and Deployment Version come from the worker's completion + response. + (-- api-linter: core::0142::time-field-type=disabled + aip.dev/not-precedent: one_time describes one-time routing semantics, not a timestamp or duration. --) + """ behavior: temporalio.api.enums.v1.workflow_pb2.VersioningBehavior.ValueType """Required. Deprecated. Use `override`. @@ -2114,6 +2110,7 @@ class VersioningOverride(google.protobuf.message.Message): *, pinned: global___VersioningOverride.PinnedOverride | None = ..., auto_upgrade: builtins.bool = ..., + one_time: global___VersioningOverride.OneTimeOverride | None = ..., behavior: temporalio.api.enums.v1.workflow_pb2.VersioningBehavior.ValueType = ..., deployment: temporalio.api.deployment.v1.message_pb2.Deployment | None = ..., pinned_version: builtins.str = ..., @@ -2125,6 +2122,8 @@ class VersioningOverride(google.protobuf.message.Message): b"auto_upgrade", "deployment", b"deployment", + "one_time", + b"one_time", "override", b"override", "pinned", @@ -2140,6 +2139,8 @@ class VersioningOverride(google.protobuf.message.Message): b"behavior", "deployment", b"deployment", + "one_time", + b"one_time", "override", b"override", "pinned", @@ -2150,7 +2151,7 @@ class VersioningOverride(google.protobuf.message.Message): ) -> None: ... def WhichOneof( self, oneof_group: typing_extensions.Literal["override", b"override"] - ) -> typing_extensions.Literal["pinned", "auto_upgrade"] | None: ... + ) -> typing_extensions.Literal["pinned", "auto_upgrade", "one_time"] | None: ... global___VersioningOverride = VersioningOverride diff --git a/temporalio/api/workflowservice/v1/__init__.py b/temporalio/api/workflowservice/v1/__init__.py index 771e4655c..88d7af571 100644 --- a/temporalio/api/workflowservice/v1/__init__.py +++ b/temporalio/api/workflowservice/v1/__init__.py @@ -5,6 +5,8 @@ CountNexusOperationExecutionsResponse, CountSchedulesRequest, CountSchedulesResponse, + CountWorkersRequest, + CountWorkersResponse, CountWorkflowExecutionsRequest, CountWorkflowExecutionsResponse, CreateScheduleRequest, @@ -250,6 +252,8 @@ "CountNexusOperationExecutionsResponse", "CountSchedulesRequest", "CountSchedulesResponse", + "CountWorkersRequest", + "CountWorkersResponse", "CountWorkflowExecutionsRequest", "CountWorkflowExecutionsResponse", "CreateScheduleRequest", diff --git a/temporalio/api/workflowservice/v1/request_response_pb2.py b/temporalio/api/workflowservice/v1/request_response_pb2.py index 32469c030..baabaf6ad 100644 --- a/temporalio/api/workflowservice/v1/request_response_pb2.py +++ b/temporalio/api/workflowservice/v1/request_response_pb2.py @@ -128,7 +128,7 @@ ) DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile( - b'\n6temporal/api/workflowservice/v1/request_response.proto\x12\x1ftemporal.api.workflowservice.v1\x1a+temporal/api/enums/v1/batch_operation.proto\x1a"temporal/api/enums/v1/common.proto\x1a$temporal/api/enums/v1/workflow.proto\x1a%temporal/api/enums/v1/namespace.proto\x1a(temporal/api/enums/v1/failed_cause.proto\x1a!temporal/api/enums/v1/query.proto\x1a!temporal/api/enums/v1/reset.proto\x1a&temporal/api/enums/v1/task_queue.proto\x1a&temporal/api/enums/v1/deployment.proto\x1a"temporal/api/enums/v1/update.proto\x1a$temporal/api/enums/v1/activity.proto\x1a!temporal/api/enums/v1/nexus.proto\x1a&temporal/api/activity/v1/message.proto\x1a$temporal/api/common/v1/message.proto\x1a%temporal/api/history/v1/message.proto\x1a&temporal/api/workflow/v1/message.proto\x1a%temporal/api/command/v1/message.proto\x1a$temporal/api/compute/v1/config.proto\x1a(temporal/api/deployment/v1/message.proto\x1a%temporal/api/failure/v1/message.proto\x1a$temporal/api/filter/v1/message.proto\x1a&temporal/api/protocol/v1/message.proto\x1a\'temporal/api/namespace/v1/message.proto\x1a#temporal/api/query/v1/message.proto\x1a)temporal/api/replication/v1/message.proto\x1a#temporal/api/rules/v1/message.proto\x1a\'temporal/api/sdk/v1/worker_config.proto\x1a&temporal/api/schedule/v1/message.proto\x1a\'temporal/api/taskqueue/v1/message.proto\x1a$temporal/api/update/v1/message.proto\x1a%temporal/api/version/v1/message.proto\x1a#temporal/api/batch/v1/message.proto\x1a\x30temporal/api/sdk/v1/task_complete_metadata.proto\x1a\'temporal/api/sdk/v1/user_metadata.proto\x1a#temporal/api/nexus/v1/message.proto\x1a$temporal/api/worker/v1/message.proto\x1a\x1egoogle/protobuf/duration.proto\x1a google/protobuf/field_mask.proto\x1a\x1fgoogle/protobuf/timestamp.proto"\x88\x05\n\x18RegisterNamespaceRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0b\x64\x65scription\x18\x02 \x01(\t\x12\x13\n\x0bowner_email\x18\x03 \x01(\t\x12\x46\n#workflow_execution_retention_period\x18\x04 \x01(\x0b\x32\x19.google.protobuf.Duration\x12G\n\x08\x63lusters\x18\x05 \x03(\x0b\x32\x35.temporal.api.replication.v1.ClusterReplicationConfig\x12\x1b\n\x13\x61\x63tive_cluster_name\x18\x06 \x01(\t\x12Q\n\x04\x64\x61ta\x18\x07 \x03(\x0b\x32\x43.temporal.api.workflowservice.v1.RegisterNamespaceRequest.DataEntry\x12\x16\n\x0esecurity_token\x18\x08 \x01(\t\x12\x1b\n\x13is_global_namespace\x18\t \x01(\x08\x12\x44\n\x16history_archival_state\x18\n \x01(\x0e\x32$.temporal.api.enums.v1.ArchivalState\x12\x1c\n\x14history_archival_uri\x18\x0b \x01(\t\x12G\n\x19visibility_archival_state\x18\x0c \x01(\x0e\x32$.temporal.api.enums.v1.ArchivalState\x12\x1f\n\x17visibility_archival_uri\x18\r \x01(\t\x1a+\n\tDataEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01"\x1b\n\x19RegisterNamespaceResponse"\x89\x01\n\x15ListNamespacesRequest\x12\x11\n\tpage_size\x18\x01 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c\x12\x44\n\x10namespace_filter\x18\x03 \x01(\x0b\x32*.temporal.api.namespace.v1.NamespaceFilter"\x81\x01\n\x16ListNamespacesResponse\x12N\n\nnamespaces\x18\x01 \x03(\x0b\x32:.temporal.api.workflowservice.v1.DescribeNamespaceResponse\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c"S\n\x18\x44\x65scribeNamespaceRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\n\n\x02id\x18\x02 \x01(\t\x12\x18\n\x10weak_consistency\x18\x03 \x01(\x08"\xb4\x03\n\x19\x44\x65scribeNamespaceResponse\x12@\n\x0enamespace_info\x18\x01 \x01(\x0b\x32(.temporal.api.namespace.v1.NamespaceInfo\x12:\n\x06\x63onfig\x18\x02 \x01(\x0b\x32*.temporal.api.namespace.v1.NamespaceConfig\x12S\n\x12replication_config\x18\x03 \x01(\x0b\x32\x37.temporal.api.replication.v1.NamespaceReplicationConfig\x12\x18\n\x10\x66\x61ilover_version\x18\x04 \x01(\x03\x12\x1b\n\x13is_global_namespace\x18\x05 \x01(\x08\x12\x45\n\x10\x66\x61ilover_history\x18\x06 \x03(\x0b\x32+.temporal.api.replication.v1.FailoverStatus\x12\x46\n\x12poller_group_infos\x18\x07 \x03(\x0b\x32*.temporal.api.taskqueue.v1.PollerGroupInfo"\xcf\x02\n\x16UpdateNamespaceRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x43\n\x0bupdate_info\x18\x02 \x01(\x0b\x32..temporal.api.namespace.v1.UpdateNamespaceInfo\x12:\n\x06\x63onfig\x18\x03 \x01(\x0b\x32*.temporal.api.namespace.v1.NamespaceConfig\x12S\n\x12replication_config\x18\x04 \x01(\x0b\x32\x37.temporal.api.replication.v1.NamespaceReplicationConfig\x12\x16\n\x0esecurity_token\x18\x05 \x01(\t\x12\x19\n\x11\x64\x65lete_bad_binary\x18\x06 \x01(\t\x12\x19\n\x11promote_namespace\x18\x07 \x01(\x08"\xa3\x02\n\x17UpdateNamespaceResponse\x12@\n\x0enamespace_info\x18\x01 \x01(\x0b\x32(.temporal.api.namespace.v1.NamespaceInfo\x12:\n\x06\x63onfig\x18\x02 \x01(\x0b\x32*.temporal.api.namespace.v1.NamespaceConfig\x12S\n\x12replication_config\x18\x03 \x01(\x0b\x32\x37.temporal.api.replication.v1.NamespaceReplicationConfig\x12\x18\n\x10\x66\x61ilover_version\x18\x04 \x01(\x03\x12\x1b\n\x13is_global_namespace\x18\x05 \x01(\x08"F\n\x19\x44\x65precateNamespaceRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x16\n\x0esecurity_token\x18\x02 \x01(\t"\x1c\n\x1a\x44\x65precateNamespaceResponse"\xd3\x0c\n\x1dStartWorkflowExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12;\n\rworkflow_type\x18\x03 \x01(\x0b\x32$.temporal.api.common.v1.WorkflowType\x12\x38\n\ntask_queue\x18\x04 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12/\n\x05input\x18\x05 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12=\n\x1aworkflow_execution_timeout\x18\x06 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x37\n\x14workflow_run_timeout\x18\x07 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x38\n\x15workflow_task_timeout\x18\x08 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x10\n\x08identity\x18\t \x01(\t\x12\x12\n\nrequest_id\x18\n \x01(\t\x12N\n\x18workflow_id_reuse_policy\x18\x0b \x01(\x0e\x32,.temporal.api.enums.v1.WorkflowIdReusePolicy\x12T\n\x1bworkflow_id_conflict_policy\x18\x16 \x01(\x0e\x32/.temporal.api.enums.v1.WorkflowIdConflictPolicy\x12\x39\n\x0cretry_policy\x18\x0c \x01(\x0b\x32#.temporal.api.common.v1.RetryPolicy\x12\x15\n\rcron_schedule\x18\r \x01(\t\x12*\n\x04memo\x18\x0e \x01(\x0b\x32\x1c.temporal.api.common.v1.Memo\x12\x43\n\x11search_attributes\x18\x0f \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes\x12.\n\x06header\x18\x10 \x01(\x0b\x32\x1e.temporal.api.common.v1.Header\x12\x1f\n\x17request_eager_execution\x18\x11 \x01(\x08\x12;\n\x11\x63ontinued_failure\x18\x12 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12@\n\x16last_completion_result\x18\x13 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x37\n\x14workflow_start_delay\x18\x14 \x01(\x0b\x32\x19.google.protobuf.Duration\x12>\n\x14\x63ompletion_callbacks\x18\x15 \x03(\x0b\x32 .temporal.api.common.v1.Callback\x12\x38\n\ruser_metadata\x18\x17 \x01(\x0b\x32!.temporal.api.sdk.v1.UserMetadata\x12+\n\x05links\x18\x18 \x03(\x0b\x32\x1c.temporal.api.common.v1.Link\x12I\n\x13versioning_override\x18\x19 \x01(\x0b\x32,.temporal.api.workflow.v1.VersioningOverride\x12H\n\x13on_conflict_options\x18\x1a \x01(\x0b\x32+.temporal.api.workflow.v1.OnConflictOptions\x12\x32\n\x08priority\x18\x1b \x01(\x0b\x32 .temporal.api.common.v1.Priority\x12\\\n\x1f\x65\x61ger_worker_deployment_options\x18\x1c \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentOptions\x12J\n\x14time_skipping_config\x18\x1d \x01(\x0b\x32,.temporal.api.workflow.v1.TimeSkippingConfig"\x8a\x02\n\x1eStartWorkflowExecutionResponse\x12\x0e\n\x06run_id\x18\x01 \x01(\t\x12\x0f\n\x07started\x18\x03 \x01(\x08\x12>\n\x06status\x18\x05 \x01(\x0e\x32..temporal.api.enums.v1.WorkflowExecutionStatus\x12[\n\x13\x65\x61ger_workflow_task\x18\x02 \x01(\x0b\x32>.temporal.api.workflowservice.v1.PollWorkflowTaskQueueResponse\x12*\n\x04link\x18\x04 \x01(\x0b\x32\x1c.temporal.api.common.v1.Link"\xaa\x02\n"GetWorkflowExecutionHistoryRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12<\n\texecution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x19\n\x11maximum_page_size\x18\x03 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x04 \x01(\x0c\x12\x16\n\x0ewait_new_event\x18\x05 \x01(\x08\x12P\n\x19history_event_filter_type\x18\x06 \x01(\x0e\x32-.temporal.api.enums.v1.HistoryEventFilterType\x12\x15\n\rskip_archival\x18\x07 \x01(\x08"\xba\x01\n#GetWorkflowExecutionHistoryResponse\x12\x31\n\x07history\x18\x01 \x01(\x0b\x32 .temporal.api.history.v1.History\x12\x35\n\x0braw_history\x18\x02 \x03(\x0b\x32 .temporal.api.common.v1.DataBlob\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c\x12\x10\n\x08\x61rchived\x18\x04 \x01(\x08"\xb0\x01\n)GetWorkflowExecutionHistoryReverseRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12<\n\texecution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x19\n\x11maximum_page_size\x18\x03 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x04 \x01(\x0c"x\n*GetWorkflowExecutionHistoryReverseResponse\x12\x31\n\x07history\x18\x01 \x01(\x0b\x32 .temporal.api.history.v1.History\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c"\xb8\x03\n\x1cPollWorkflowTaskQueueRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x38\n\ntask_queue\x18\x02 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12\x17\n\x0fpoller_group_id\x18\n \x01(\t\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x1b\n\x13worker_instance_key\x18\x08 \x01(\t\x12!\n\x19worker_control_task_queue\x18\t \x01(\t\x12\x1b\n\x0f\x62inary_checksum\x18\x04 \x01(\tB\x02\x18\x01\x12Z\n\x1bworker_version_capabilities\x18\x05 \x01(\x0b\x32\x31.temporal.api.common.v1.WorkerVersionCapabilitiesB\x02\x18\x01\x12O\n\x12\x64\x65ployment_options\x18\x06 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentOptionsJ\x04\x08\x07\x10\x08R\x10worker_heartbeat"\xf2\x07\n\x1dPollWorkflowTaskQueueResponse\x12\x12\n\ntask_token\x18\x01 \x01(\x0c\x12\x45\n\x12workflow_execution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12;\n\rworkflow_type\x18\x03 \x01(\x0b\x32$.temporal.api.common.v1.WorkflowType\x12!\n\x19previous_started_event_id\x18\x04 \x01(\x03\x12\x18\n\x10started_event_id\x18\x05 \x01(\x03\x12\x0f\n\x07\x61ttempt\x18\x06 \x01(\x05\x12\x1a\n\x12\x62\x61\x63klog_count_hint\x18\x07 \x01(\x03\x12\x31\n\x07history\x18\x08 \x01(\x0b\x32 .temporal.api.history.v1.History\x12\x17\n\x0fnext_page_token\x18\t \x01(\x0c\x12\x33\n\x05query\x18\n \x01(\x0b\x32$.temporal.api.query.v1.WorkflowQuery\x12K\n\x1dworkflow_execution_task_queue\x18\x0b \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12\x32\n\x0escheduled_time\x18\x0c \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x30\n\x0cstarted_time\x18\r \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\\\n\x07queries\x18\x0e \x03(\x0b\x32K.temporal.api.workflowservice.v1.PollWorkflowTaskQueueResponse.QueriesEntry\x12\x33\n\x08messages\x18\x0f \x03(\x0b\x32!.temporal.api.protocol.v1.Message\x12Q\n\x17poller_scaling_decision\x18\x10 \x01(\x0b\x32\x30.temporal.api.taskqueue.v1.PollerScalingDecision\x12\x17\n\x0fpoller_group_id\x18\x11 \x01(\t\x12\x46\n\x12poller_group_infos\x18\x12 \x03(\x0b\x32*.temporal.api.taskqueue.v1.PollerGroupInfo\x1aT\n\x0cQueriesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x33\n\x05value\x18\x02 \x01(\x0b\x32$.temporal.api.query.v1.WorkflowQuery:\x02\x38\x01"\x8a\n\n#RespondWorkflowTaskCompletedRequest\x12\x12\n\ntask_token\x18\x01 \x01(\x0c\x12\x32\n\x08\x63ommands\x18\x02 \x03(\x0b\x32 .temporal.api.command.v1.Command\x12\x10\n\x08identity\x18\x03 \x01(\t\x12O\n\x11sticky_attributes\x18\x04 \x01(\x0b\x32\x34.temporal.api.taskqueue.v1.StickyExecutionAttributes\x12 \n\x18return_new_workflow_task\x18\x05 \x01(\x08\x12&\n\x1e\x66orce_create_new_workflow_task\x18\x06 \x01(\x08\x12\x1b\n\x0f\x62inary_checksum\x18\x07 \x01(\tB\x02\x18\x01\x12m\n\rquery_results\x18\x08 \x03(\x0b\x32V.temporal.api.workflowservice.v1.RespondWorkflowTaskCompletedRequest.QueryResultsEntry\x12\x11\n\tnamespace\x18\t \x01(\t\x12\x13\n\x0bresource_id\x18\x12 \x01(\t\x12L\n\x14worker_version_stamp\x18\n \x01(\x0b\x32*.temporal.api.common.v1.WorkerVersionStampB\x02\x18\x01\x12\x33\n\x08messages\x18\x0b \x03(\x0b\x32!.temporal.api.protocol.v1.Message\x12H\n\x0csdk_metadata\x18\x0c \x01(\x0b\x32\x32.temporal.api.sdk.v1.WorkflowTaskCompletedMetadata\x12\x43\n\x11metering_metadata\x18\r \x01(\x0b\x32(.temporal.api.common.v1.MeteringMetadata\x12g\n\x0c\x63\x61pabilities\x18\x0e \x01(\x0b\x32Q.temporal.api.workflowservice.v1.RespondWorkflowTaskCompletedRequest.Capabilities\x12>\n\ndeployment\x18\x0f \x01(\x0b\x32&.temporal.api.deployment.v1.DeploymentB\x02\x18\x01\x12\x46\n\x13versioning_behavior\x18\x10 \x01(\x0e\x32).temporal.api.enums.v1.VersioningBehavior\x12O\n\x12\x64\x65ployment_options\x18\x11 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentOptions\x12\x1b\n\x13worker_instance_key\x18\x13 \x01(\t\x12!\n\x19worker_control_task_queue\x18\x14 \x01(\t\x1a_\n\x11QueryResultsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x39\n\x05value\x18\x02 \x01(\x0b\x32*.temporal.api.query.v1.WorkflowQueryResult:\x02\x38\x01\x1a\x45\n\x0c\x43\x61pabilities\x12\x35\n-discard_speculative_workflow_task_with_events\x18\x01 \x01(\x08"\xf5\x01\n$RespondWorkflowTaskCompletedResponse\x12U\n\rworkflow_task\x18\x01 \x01(\x0b\x32>.temporal.api.workflowservice.v1.PollWorkflowTaskQueueResponse\x12V\n\x0e\x61\x63tivity_tasks\x18\x02 \x03(\x0b\x32>.temporal.api.workflowservice.v1.PollActivityTaskQueueResponse\x12\x1e\n\x16reset_history_event_id\x18\x03 \x01(\x03"\x8d\x04\n RespondWorkflowTaskFailedRequest\x12\x12\n\ntask_token\x18\x01 \x01(\x0c\x12=\n\x05\x63\x61use\x18\x02 \x01(\x0e\x32..temporal.api.enums.v1.WorkflowTaskFailedCause\x12\x31\n\x07\x66\x61ilure\x18\x03 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12\x10\n\x08identity\x18\x04 \x01(\t\x12\x1b\n\x0f\x62inary_checksum\x18\x05 \x01(\tB\x02\x18\x01\x12\x11\n\tnamespace\x18\x06 \x01(\t\x12\x13\n\x0bresource_id\x18\x0b \x01(\t\x12\x33\n\x08messages\x18\x07 \x03(\x0b\x32!.temporal.api.protocol.v1.Message\x12\x46\n\x0eworker_version\x18\x08 \x01(\x0b\x32*.temporal.api.common.v1.WorkerVersionStampB\x02\x18\x01\x12>\n\ndeployment\x18\t \x01(\x0b\x32&.temporal.api.deployment.v1.DeploymentB\x02\x18\x01\x12O\n\x12\x64\x65ployment_options\x18\n \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentOptions"#\n!RespondWorkflowTaskFailedResponse"\xe6\x03\n\x1cPollActivityTaskQueueRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x38\n\ntask_queue\x18\x02 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12\x17\n\x0fpoller_group_id\x18\n \x01(\t\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x1b\n\x13worker_instance_key\x18\x08 \x01(\t\x12!\n\x19worker_control_task_queue\x18\t \x01(\t\x12I\n\x13task_queue_metadata\x18\x04 \x01(\x0b\x32,.temporal.api.taskqueue.v1.TaskQueueMetadata\x12Z\n\x1bworker_version_capabilities\x18\x05 \x01(\x0b\x32\x31.temporal.api.common.v1.WorkerVersionCapabilitiesB\x02\x18\x01\x12O\n\x12\x64\x65ployment_options\x18\x06 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentOptionsJ\x04\x08\x07\x10\x08R\x10worker_heartbeat"\xd0\x08\n\x1dPollActivityTaskQueueResponse\x12\x12\n\ntask_token\x18\x01 \x01(\x0c\x12\x1a\n\x12workflow_namespace\x18\x02 \x01(\t\x12;\n\rworkflow_type\x18\x03 \x01(\x0b\x32$.temporal.api.common.v1.WorkflowType\x12\x45\n\x12workflow_execution\x18\x04 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12;\n\ractivity_type\x18\x05 \x01(\x0b\x32$.temporal.api.common.v1.ActivityType\x12\x13\n\x0b\x61\x63tivity_id\x18\x06 \x01(\t\x12.\n\x06header\x18\x07 \x01(\x0b\x32\x1e.temporal.api.common.v1.Header\x12/\n\x05input\x18\x08 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12;\n\x11heartbeat_details\x18\t \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x32\n\x0escheduled_time\x18\n \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x42\n\x1e\x63urrent_attempt_scheduled_time\x18\x0b \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x30\n\x0cstarted_time\x18\x0c \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x0f\n\x07\x61ttempt\x18\r \x01(\x05\x12<\n\x19schedule_to_close_timeout\x18\x0e \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x39\n\x16start_to_close_timeout\x18\x0f \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x34\n\x11heartbeat_timeout\x18\x10 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x39\n\x0cretry_policy\x18\x11 \x01(\x0b\x32#.temporal.api.common.v1.RetryPolicy\x12Q\n\x17poller_scaling_decision\x18\x12 \x01(\x0b\x32\x30.temporal.api.taskqueue.v1.PollerScalingDecision\x12\x32\n\x08priority\x18\x13 \x01(\x0b\x32 .temporal.api.common.v1.Priority\x12\x17\n\x0f\x61\x63tivity_run_id\x18\x14 \x01(\t\x12\x46\n\x12poller_group_infos\x18\x15 \x03(\x0b\x32*.temporal.api.taskqueue.v1.PollerGroupInfo"\xa5\x01\n"RecordActivityTaskHeartbeatRequest\x12\x12\n\ntask_token\x18\x01 \x01(\x0c\x12\x31\n\x07\x64\x65tails\x18\x02 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x11\n\tnamespace\x18\x04 \x01(\t\x12\x13\n\x0bresource_id\x18\x05 \x01(\t"p\n#RecordActivityTaskHeartbeatResponse\x12\x18\n\x10\x63\x61ncel_requested\x18\x01 \x01(\x08\x12\x17\n\x0f\x61\x63tivity_paused\x18\x02 \x01(\x08\x12\x16\n\x0e\x61\x63tivity_reset\x18\x03 \x01(\x08"\xcf\x01\n&RecordActivityTaskHeartbeatByIdRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x12\x13\n\x0b\x61\x63tivity_id\x18\x04 \x01(\t\x12\x31\n\x07\x64\x65tails\x18\x05 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x10\n\x08identity\x18\x06 \x01(\t\x12\x13\n\x0bresource_id\x18\x07 \x01(\t"t\n\'RecordActivityTaskHeartbeatByIdResponse\x12\x18\n\x10\x63\x61ncel_requested\x18\x01 \x01(\x08\x12\x17\n\x0f\x61\x63tivity_paused\x18\x02 \x01(\x08\x12\x16\n\x0e\x61\x63tivity_reset\x18\x03 \x01(\x08"\xfe\x02\n#RespondActivityTaskCompletedRequest\x12\x12\n\ntask_token\x18\x01 \x01(\x0c\x12\x30\n\x06result\x18\x02 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x11\n\tnamespace\x18\x04 \x01(\t\x12\x13\n\x0bresource_id\x18\x08 \x01(\t\x12\x46\n\x0eworker_version\x18\x05 \x01(\x0b\x32*.temporal.api.common.v1.WorkerVersionStampB\x02\x18\x01\x12>\n\ndeployment\x18\x06 \x01(\x0b\x32&.temporal.api.deployment.v1.DeploymentB\x02\x18\x01\x12O\n\x12\x64\x65ployment_options\x18\x07 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentOptions"&\n$RespondActivityTaskCompletedResponse"\xcf\x01\n\'RespondActivityTaskCompletedByIdRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x12\x13\n\x0b\x61\x63tivity_id\x18\x04 \x01(\t\x12\x30\n\x06result\x18\x05 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x10\n\x08identity\x18\x06 \x01(\t\x12\x13\n\x0bresource_id\x18\x07 \x01(\t"*\n(RespondActivityTaskCompletedByIdResponse"\xbe\x03\n RespondActivityTaskFailedRequest\x12\x12\n\ntask_token\x18\x01 \x01(\x0c\x12\x31\n\x07\x66\x61ilure\x18\x02 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x11\n\tnamespace\x18\x04 \x01(\t\x12\x13\n\x0bresource_id\x18\t \x01(\t\x12@\n\x16last_heartbeat_details\x18\x05 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x46\n\x0eworker_version\x18\x06 \x01(\x0b\x32*.temporal.api.common.v1.WorkerVersionStampB\x02\x18\x01\x12>\n\ndeployment\x18\x07 \x01(\x0b\x32&.temporal.api.deployment.v1.DeploymentB\x02\x18\x01\x12O\n\x12\x64\x65ployment_options\x18\x08 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentOptions"W\n!RespondActivityTaskFailedResponse\x12\x32\n\x08\x66\x61ilures\x18\x01 \x03(\x0b\x32 .temporal.api.failure.v1.Failure"\x8f\x02\n$RespondActivityTaskFailedByIdRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x12\x13\n\x0b\x61\x63tivity_id\x18\x04 \x01(\t\x12\x31\n\x07\x66\x61ilure\x18\x05 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12\x10\n\x08identity\x18\x06 \x01(\t\x12@\n\x16last_heartbeat_details\x18\x07 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x13\n\x0bresource_id\x18\x08 \x01(\t"[\n%RespondActivityTaskFailedByIdResponse\x12\x32\n\x08\x66\x61ilures\x18\x01 \x03(\x0b\x32 .temporal.api.failure.v1.Failure"\xfe\x02\n"RespondActivityTaskCanceledRequest\x12\x12\n\ntask_token\x18\x01 \x01(\x0c\x12\x31\n\x07\x64\x65tails\x18\x02 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x11\n\tnamespace\x18\x04 \x01(\t\x12\x13\n\x0bresource_id\x18\x08 \x01(\t\x12\x46\n\x0eworker_version\x18\x05 \x01(\x0b\x32*.temporal.api.common.v1.WorkerVersionStampB\x02\x18\x01\x12>\n\ndeployment\x18\x06 \x01(\x0b\x32&.temporal.api.deployment.v1.DeploymentB\x02\x18\x01\x12O\n\x12\x64\x65ployment_options\x18\x07 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentOptions"%\n#RespondActivityTaskCanceledResponse"\xa0\x02\n&RespondActivityTaskCanceledByIdRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x12\x13\n\x0b\x61\x63tivity_id\x18\x04 \x01(\t\x12\x31\n\x07\x64\x65tails\x18\x05 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x10\n\x08identity\x18\x06 \x01(\t\x12O\n\x12\x64\x65ployment_options\x18\x07 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentOptions\x12\x13\n\x0bresource_id\x18\x08 \x01(\t")\n\'RespondActivityTaskCanceledByIdResponse"\x84\x02\n%RequestCancelWorkflowExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x45\n\x12workflow_execution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x12\n\nrequest_id\x18\x04 \x01(\t\x12\x1e\n\x16\x66irst_execution_run_id\x18\x05 \x01(\t\x12\x0e\n\x06reason\x18\x06 \x01(\t\x12+\n\x05links\x18\x07 \x03(\x0b\x32\x1c.temporal.api.common.v1.Link"(\n&RequestCancelWorkflowExecutionResponse"\xde\x02\n\x1eSignalWorkflowExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x45\n\x12workflow_execution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x13\n\x0bsignal_name\x18\x03 \x01(\t\x12/\n\x05input\x18\x04 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x10\n\x08identity\x18\x05 \x01(\t\x12\x12\n\nrequest_id\x18\x06 \x01(\t\x12\x13\n\x07\x63ontrol\x18\x07 \x01(\tB\x02\x18\x01\x12.\n\x06header\x18\x08 \x01(\x0b\x32\x1e.temporal.api.common.v1.Header\x12+\n\x05links\x18\n \x03(\x0b\x32\x1c.temporal.api.common.v1.LinkJ\x04\x08\t\x10\n"M\n\x1fSignalWorkflowExecutionResponse\x12*\n\x04link\x18\x01 \x01(\x0b\x32\x1c.temporal.api.common.v1.Link"\xbd\n\n\'SignalWithStartWorkflowExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12;\n\rworkflow_type\x18\x03 \x01(\x0b\x32$.temporal.api.common.v1.WorkflowType\x12\x38\n\ntask_queue\x18\x04 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12/\n\x05input\x18\x05 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12=\n\x1aworkflow_execution_timeout\x18\x06 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x37\n\x14workflow_run_timeout\x18\x07 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x38\n\x15workflow_task_timeout\x18\x08 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x10\n\x08identity\x18\t \x01(\t\x12\x12\n\nrequest_id\x18\n \x01(\t\x12N\n\x18workflow_id_reuse_policy\x18\x0b \x01(\x0e\x32,.temporal.api.enums.v1.WorkflowIdReusePolicy\x12T\n\x1bworkflow_id_conflict_policy\x18\x16 \x01(\x0e\x32/.temporal.api.enums.v1.WorkflowIdConflictPolicy\x12\x13\n\x0bsignal_name\x18\x0c \x01(\t\x12\x36\n\x0csignal_input\x18\r \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x13\n\x07\x63ontrol\x18\x0e \x01(\tB\x02\x18\x01\x12\x39\n\x0cretry_policy\x18\x0f \x01(\x0b\x32#.temporal.api.common.v1.RetryPolicy\x12\x15\n\rcron_schedule\x18\x10 \x01(\t\x12*\n\x04memo\x18\x11 \x01(\x0b\x32\x1c.temporal.api.common.v1.Memo\x12\x43\n\x11search_attributes\x18\x12 \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes\x12.\n\x06header\x18\x13 \x01(\x0b\x32\x1e.temporal.api.common.v1.Header\x12\x37\n\x14workflow_start_delay\x18\x14 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x38\n\ruser_metadata\x18\x17 \x01(\x0b\x32!.temporal.api.sdk.v1.UserMetadata\x12+\n\x05links\x18\x18 \x03(\x0b\x32\x1c.temporal.api.common.v1.Link\x12I\n\x13versioning_override\x18\x19 \x01(\x0b\x32,.temporal.api.workflow.v1.VersioningOverride\x12\x32\n\x08priority\x18\x1a \x01(\x0b\x32 .temporal.api.common.v1.Priority\x12J\n\x14time_skipping_config\x18\x1b \x01(\x0b\x32,.temporal.api.workflow.v1.TimeSkippingConfigJ\x04\x08\x15\x10\x16"~\n(SignalWithStartWorkflowExecutionResponse\x12\x0e\n\x06run_id\x18\x01 \x01(\t\x12\x0f\n\x07started\x18\x02 \x01(\x08\x12\x31\n\x0bsignal_link\x18\x03 \x01(\x0b\x32\x1c.temporal.api.common.v1.Link"\xc1\x03\n\x1dResetWorkflowExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x45\n\x12workflow_execution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x0e\n\x06reason\x18\x03 \x01(\t\x12%\n\x1dworkflow_task_finish_event_id\x18\x04 \x01(\x03\x12\x12\n\nrequest_id\x18\x05 \x01(\t\x12G\n\x12reset_reapply_type\x18\x06 \x01(\x0e\x32\'.temporal.api.enums.v1.ResetReapplyTypeB\x02\x18\x01\x12S\n\x1breset_reapply_exclude_types\x18\x07 \x03(\x0e\x32..temporal.api.enums.v1.ResetReapplyExcludeType\x12K\n\x15post_reset_operations\x18\x08 \x03(\x0b\x32,.temporal.api.workflow.v1.PostResetOperation\x12\x10\n\x08identity\x18\t \x01(\t"0\n\x1eResetWorkflowExecutionResponse\x12\x0e\n\x06run_id\x18\x01 \x01(\t"\x9f\x02\n!TerminateWorkflowExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x45\n\x12workflow_execution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x0e\n\x06reason\x18\x03 \x01(\t\x12\x31\n\x07\x64\x65tails\x18\x04 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x10\n\x08identity\x18\x05 \x01(\t\x12\x1e\n\x16\x66irst_execution_run_id\x18\x06 \x01(\t\x12+\n\x05links\x18\x07 \x03(\x0b\x32\x1c.temporal.api.common.v1.Link"$\n"TerminateWorkflowExecutionResponse"z\n\x1e\x44\x65leteWorkflowExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x45\n\x12workflow_execution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution"!\n\x1f\x44\x65leteWorkflowExecutionResponse"\xc9\x02\n!ListOpenWorkflowExecutionsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x19\n\x11maximum_page_size\x18\x02 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c\x12\x42\n\x11start_time_filter\x18\x04 \x01(\x0b\x32\'.temporal.api.filter.v1.StartTimeFilter\x12K\n\x10\x65xecution_filter\x18\x05 \x01(\x0b\x32/.temporal.api.filter.v1.WorkflowExecutionFilterH\x00\x12\x41\n\x0btype_filter\x18\x06 \x01(\x0b\x32*.temporal.api.filter.v1.WorkflowTypeFilterH\x00\x42\t\n\x07\x66ilters"\x82\x01\n"ListOpenWorkflowExecutionsResponse\x12\x43\n\nexecutions\x18\x01 \x03(\x0b\x32/.temporal.api.workflow.v1.WorkflowExecutionInfo\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c"\x8a\x03\n#ListClosedWorkflowExecutionsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x19\n\x11maximum_page_size\x18\x02 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c\x12\x42\n\x11start_time_filter\x18\x04 \x01(\x0b\x32\'.temporal.api.filter.v1.StartTimeFilter\x12K\n\x10\x65xecution_filter\x18\x05 \x01(\x0b\x32/.temporal.api.filter.v1.WorkflowExecutionFilterH\x00\x12\x41\n\x0btype_filter\x18\x06 \x01(\x0b\x32*.temporal.api.filter.v1.WorkflowTypeFilterH\x00\x12=\n\rstatus_filter\x18\x07 \x01(\x0b\x32$.temporal.api.filter.v1.StatusFilterH\x00\x42\t\n\x07\x66ilters"\x84\x01\n$ListClosedWorkflowExecutionsResponse\x12\x43\n\nexecutions\x18\x01 \x03(\x0b\x32/.temporal.api.workflow.v1.WorkflowExecutionInfo\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c"m\n\x1dListWorkflowExecutionsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x11\n\tpage_size\x18\x02 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c\x12\r\n\x05query\x18\x04 \x01(\t"~\n\x1eListWorkflowExecutionsResponse\x12\x43\n\nexecutions\x18\x01 \x03(\x0b\x32/.temporal.api.workflow.v1.WorkflowExecutionInfo\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c"u\n%ListArchivedWorkflowExecutionsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x11\n\tpage_size\x18\x02 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c\x12\r\n\x05query\x18\x04 \x01(\t"\x86\x01\n&ListArchivedWorkflowExecutionsResponse\x12\x43\n\nexecutions\x18\x01 \x03(\x0b\x32/.temporal.api.workflow.v1.WorkflowExecutionInfo\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c"m\n\x1dScanWorkflowExecutionsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x11\n\tpage_size\x18\x02 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c\x12\r\n\x05query\x18\x04 \x01(\t"~\n\x1eScanWorkflowExecutionsResponse\x12\x43\n\nexecutions\x18\x01 \x03(\x0b\x32/.temporal.api.workflow.v1.WorkflowExecutionInfo\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c"B\n\x1e\x43ountWorkflowExecutionsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\r\n\x05query\x18\x02 \x01(\t"\xed\x01\n\x1f\x43ountWorkflowExecutionsResponse\x12\r\n\x05\x63ount\x18\x01 \x01(\x03\x12\x61\n\x06groups\x18\x02 \x03(\x0b\x32Q.temporal.api.workflowservice.v1.CountWorkflowExecutionsResponse.AggregationGroup\x1aX\n\x10\x41ggregationGroup\x12\x35\n\x0cgroup_values\x18\x01 \x03(\x0b\x32\x1f.temporal.api.common.v1.Payload\x12\r\n\x05\x63ount\x18\x02 \x01(\x03"\x1c\n\x1aGetSearchAttributesRequest"\xc9\x01\n\x1bGetSearchAttributesResponse\x12T\n\x04keys\x18\x01 \x03(\x0b\x32\x46.temporal.api.workflowservice.v1.GetSearchAttributesResponse.KeysEntry\x1aT\n\tKeysEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x36\n\x05value\x18\x02 \x01(\x0e\x32\'.temporal.api.enums.v1.IndexedValueType:\x02\x38\x01"\xe9\x02\n RespondQueryTaskCompletedRequest\x12\x12\n\ntask_token\x18\x01 \x01(\x0c\x12>\n\x0e\x63ompleted_type\x18\x02 \x01(\x0e\x32&.temporal.api.enums.v1.QueryResultType\x12\x36\n\x0cquery_result\x18\x03 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x15\n\rerror_message\x18\x04 \x01(\t\x12\x11\n\tnamespace\x18\x06 \x01(\t\x12\x31\n\x07\x66\x61ilure\x18\x07 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12=\n\x05\x63\x61use\x18\x08 \x01(\x0e\x32..temporal.api.enums.v1.WorkflowTaskFailedCause\x12\x17\n\x0fpoller_group_id\x18\t \x01(\tJ\x04\x08\x05\x10\x06"#\n!RespondQueryTaskCompletedResponse"n\n\x1bResetStickyTaskQueueRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12<\n\texecution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution"\x1e\n\x1cResetStickyTaskQueueResponse"\x9b\x02\n\x15ShutdownWorkerRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x19\n\x11sticky_task_queue\x18\x02 \x01(\t\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x0e\n\x06reason\x18\x04 \x01(\t\x12\x41\n\x10worker_heartbeat\x18\x05 \x01(\x0b\x32\'.temporal.api.worker.v1.WorkerHeartbeat\x12\x1b\n\x13worker_instance_key\x18\x06 \x01(\t\x12\x12\n\ntask_queue\x18\x07 \x01(\t\x12>\n\x10task_queue_types\x18\x08 \x03(\x0e\x32$.temporal.api.enums.v1.TaskQueueType"\x18\n\x16ShutdownWorkerResponse"\xe9\x01\n\x14QueryWorkflowRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12<\n\texecution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x33\n\x05query\x18\x03 \x01(\x0b\x32$.temporal.api.query.v1.WorkflowQuery\x12K\n\x16query_reject_condition\x18\x04 \x01(\x0e\x32+.temporal.api.enums.v1.QueryRejectCondition"\x8d\x01\n\x15QueryWorkflowResponse\x12\x36\n\x0cquery_result\x18\x01 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12<\n\x0equery_rejected\x18\x02 \x01(\x0b\x32$.temporal.api.query.v1.QueryRejected"s\n DescribeWorkflowExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12<\n\texecution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution"\x99\x05\n!DescribeWorkflowExecutionResponse\x12K\n\x10\x65xecution_config\x18\x01 \x01(\x0b\x32\x31.temporal.api.workflow.v1.WorkflowExecutionConfig\x12P\n\x17workflow_execution_info\x18\x02 \x01(\x0b\x32/.temporal.api.workflow.v1.WorkflowExecutionInfo\x12I\n\x12pending_activities\x18\x03 \x03(\x0b\x32-.temporal.api.workflow.v1.PendingActivityInfo\x12M\n\x10pending_children\x18\x04 \x03(\x0b\x32\x33.temporal.api.workflow.v1.PendingChildExecutionInfo\x12P\n\x15pending_workflow_task\x18\x05 \x01(\x0b\x32\x31.temporal.api.workflow.v1.PendingWorkflowTaskInfo\x12\x39\n\tcallbacks\x18\x06 \x03(\x0b\x32&.temporal.api.workflow.v1.CallbackInfo\x12U\n\x18pending_nexus_operations\x18\x07 \x03(\x0b\x32\x33.temporal.api.workflow.v1.PendingNexusOperationInfo\x12W\n\x16workflow_extended_info\x18\x08 \x01(\x0b\x32\x37.temporal.api.workflow.v1.WorkflowExecutionExtendedInfo"\x90\x04\n\x18\x44\x65scribeTaskQueueRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x38\n\ntask_queue\x18\x02 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12=\n\x0ftask_queue_type\x18\x03 \x01(\x0e\x32$.temporal.api.enums.v1.TaskQueueType\x12\x14\n\x0creport_stats\x18\x08 \x01(\x08\x12\x15\n\rreport_config\x18\x0b \x01(\x08\x12%\n\x19include_task_queue_status\x18\x04 \x01(\x08\x42\x02\x18\x01\x12\x42\n\x08\x61pi_mode\x18\x05 \x01(\x0e\x32,.temporal.api.enums.v1.DescribeTaskQueueModeB\x02\x18\x01\x12J\n\x08versions\x18\x06 \x01(\x0b\x32\x34.temporal.api.taskqueue.v1.TaskQueueVersionSelectionB\x02\x18\x01\x12\x42\n\x10task_queue_types\x18\x07 \x03(\x0e\x32$.temporal.api.enums.v1.TaskQueueTypeB\x02\x18\x01\x12\x1a\n\x0ereport_pollers\x18\t \x01(\x08\x42\x02\x18\x01\x12$\n\x18report_task_reachability\x18\n \x01(\x08\x42\x02\x18\x01"\xec\x07\n\x19\x44\x65scribeTaskQueueResponse\x12\x36\n\x07pollers\x18\x01 \x03(\x0b\x32%.temporal.api.taskqueue.v1.PollerInfo\x12\x38\n\x05stats\x18\x05 \x01(\x0b\x32).temporal.api.taskqueue.v1.TaskQueueStats\x12q\n\x15stats_by_priority_key\x18\x08 \x03(\x0b\x32R.temporal.api.workflowservice.v1.DescribeTaskQueueResponse.StatsByPriorityKeyEntry\x12K\n\x0fversioning_info\x18\x04 \x01(\x0b\x32\x32.temporal.api.taskqueue.v1.TaskQueueVersioningInfo\x12:\n\x06\x63onfig\x18\x06 \x01(\x0b\x32*.temporal.api.taskqueue.v1.TaskQueueConfig\x12k\n\x14\x65\x66\x66\x65\x63tive_rate_limit\x18\x07 \x01(\x0b\x32M.temporal.api.workflowservice.v1.DescribeTaskQueueResponse.EffectiveRateLimit\x12I\n\x11task_queue_status\x18\x02 \x01(\x0b\x32*.temporal.api.taskqueue.v1.TaskQueueStatusB\x02\x18\x01\x12g\n\rversions_info\x18\x03 \x03(\x0b\x32L.temporal.api.workflowservice.v1.DescribeTaskQueueResponse.VersionsInfoEntryB\x02\x18\x01\x1a\x64\n\x17StatsByPriorityKeyEntry\x12\x0b\n\x03key\x18\x01 \x01(\x05\x12\x38\n\x05value\x18\x02 \x01(\x0b\x32).temporal.api.taskqueue.v1.TaskQueueStats:\x02\x38\x01\x1at\n\x12\x45\x66\x66\x65\x63tiveRateLimit\x12\x1b\n\x13requests_per_second\x18\x01 \x01(\x02\x12\x41\n\x11rate_limit_source\x18\x02 \x01(\x0e\x32&.temporal.api.enums.v1.RateLimitSource\x1a\x64\n\x11VersionsInfoEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12>\n\x05value\x18\x02 \x01(\x0b\x32/.temporal.api.taskqueue.v1.TaskQueueVersionInfo:\x02\x38\x01"\x17\n\x15GetClusterInfoRequest"\xd1\x03\n\x16GetClusterInfoResponse\x12h\n\x11supported_clients\x18\x01 \x03(\x0b\x32M.temporal.api.workflowservice.v1.GetClusterInfoResponse.SupportedClientsEntry\x12\x16\n\x0eserver_version\x18\x02 \x01(\t\x12\x12\n\ncluster_id\x18\x03 \x01(\t\x12:\n\x0cversion_info\x18\x04 \x01(\x0b\x32$.temporal.api.version.v1.VersionInfo\x12\x14\n\x0c\x63luster_name\x18\x05 \x01(\t\x12\x1b\n\x13history_shard_count\x18\x06 \x01(\x05\x12\x19\n\x11persistence_store\x18\x07 \x01(\t\x12\x18\n\x10visibility_store\x18\x08 \x01(\t\x12 \n\x18initial_failover_version\x18\t \x01(\x03\x12"\n\x1a\x66\x61ilover_version_increment\x18\n \x01(\x03\x1a\x37\n\x15SupportedClientsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01"\x16\n\x14GetSystemInfoRequest"\x97\x04\n\x15GetSystemInfoResponse\x12\x16\n\x0eserver_version\x18\x01 \x01(\t\x12Y\n\x0c\x63\x61pabilities\x18\x02 \x01(\x0b\x32\x43.temporal.api.workflowservice.v1.GetSystemInfoResponse.Capabilities\x1a\x8a\x03\n\x0c\x43\x61pabilities\x12\x1f\n\x17signal_and_query_header\x18\x01 \x01(\x08\x12&\n\x1einternal_error_differentiation\x18\x02 \x01(\x08\x12*\n"activity_failure_include_heartbeat\x18\x03 \x01(\x08\x12\x1a\n\x12supports_schedules\x18\x04 \x01(\x08\x12"\n\x1a\x65ncoded_failure_attributes\x18\x05 \x01(\x08\x12!\n\x19\x62uild_id_based_versioning\x18\x06 \x01(\x08\x12\x13\n\x0bupsert_memo\x18\x07 \x01(\x08\x12\x1c\n\x14\x65\x61ger_workflow_start\x18\x08 \x01(\x08\x12\x14\n\x0csdk_metadata\x18\t \x01(\x08\x12\'\n\x1f\x63ount_group_by_execution_status\x18\n \x01(\x08\x12\r\n\x05nexus\x18\x0b \x01(\x08\x12!\n\x19server_scaled_deployments\x18\x0c \x01(\x08"m\n\x1eListTaskQueuePartitionsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x38\n\ntask_queue\x18\x02 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue"\xdf\x01\n\x1fListTaskQueuePartitionsResponse\x12]\n\x1e\x61\x63tivity_task_queue_partitions\x18\x01 \x03(\x0b\x32\x35.temporal.api.taskqueue.v1.TaskQueuePartitionMetadata\x12]\n\x1eworkflow_task_queue_partitions\x18\x02 \x03(\x0b\x32\x35.temporal.api.taskqueue.v1.TaskQueuePartitionMetadata"\xcc\x02\n\x15\x43reateScheduleRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bschedule_id\x18\x02 \x01(\t\x12\x34\n\x08schedule\x18\x03 \x01(\x0b\x32".temporal.api.schedule.v1.Schedule\x12>\n\rinitial_patch\x18\x04 \x01(\x0b\x32\'.temporal.api.schedule.v1.SchedulePatch\x12\x10\n\x08identity\x18\x05 \x01(\t\x12\x12\n\nrequest_id\x18\x06 \x01(\t\x12*\n\x04memo\x18\x07 \x01(\x0b\x32\x1c.temporal.api.common.v1.Memo\x12\x43\n\x11search_attributes\x18\x08 \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes"0\n\x16\x43reateScheduleResponse\x12\x16\n\x0e\x63onflict_token\x18\x01 \x01(\x0c"A\n\x17\x44\x65scribeScheduleRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bschedule_id\x18\x02 \x01(\t"\x8f\x02\n\x18\x44\x65scribeScheduleResponse\x12\x34\n\x08schedule\x18\x01 \x01(\x0b\x32".temporal.api.schedule.v1.Schedule\x12\x34\n\x04info\x18\x02 \x01(\x0b\x32&.temporal.api.schedule.v1.ScheduleInfo\x12*\n\x04memo\x18\x03 \x01(\x0b\x32\x1c.temporal.api.common.v1.Memo\x12\x43\n\x11search_attributes\x18\x04 \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes\x12\x16\n\x0e\x63onflict_token\x18\x05 \x01(\x0c"\xa4\x02\n\x15UpdateScheduleRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bschedule_id\x18\x02 \x01(\t\x12\x34\n\x08schedule\x18\x03 \x01(\x0b\x32".temporal.api.schedule.v1.Schedule\x12\x16\n\x0e\x63onflict_token\x18\x04 \x01(\x0c\x12\x10\n\x08identity\x18\x05 \x01(\t\x12\x12\n\nrequest_id\x18\x06 \x01(\t\x12\x43\n\x11search_attributes\x18\x07 \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes\x12*\n\x04memo\x18\x08 \x01(\x0b\x32\x1c.temporal.api.common.v1.Memo"\x18\n\x16UpdateScheduleResponse"\x9c\x01\n\x14PatchScheduleRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bschedule_id\x18\x02 \x01(\t\x12\x36\n\x05patch\x18\x03 \x01(\x0b\x32\'.temporal.api.schedule.v1.SchedulePatch\x12\x10\n\x08identity\x18\x04 \x01(\t\x12\x12\n\nrequest_id\x18\x05 \x01(\t"\x17\n\x15PatchScheduleResponse"\xa8\x01\n ListScheduleMatchingTimesRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bschedule_id\x18\x02 \x01(\t\x12.\n\nstart_time\x18\x03 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12,\n\x08\x65nd_time\x18\x04 \x01(\x0b\x32\x1a.google.protobuf.Timestamp"S\n!ListScheduleMatchingTimesResponse\x12.\n\nstart_time\x18\x01 \x03(\x0b\x32\x1a.google.protobuf.Timestamp"Q\n\x15\x44\x65leteScheduleRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bschedule_id\x18\x02 \x01(\t\x12\x10\n\x08identity\x18\x03 \x01(\t"\x18\n\x16\x44\x65leteScheduleResponse"l\n\x14ListSchedulesRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x19\n\x11maximum_page_size\x18\x02 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c\x12\r\n\x05query\x18\x04 \x01(\t"p\n\x15ListSchedulesResponse\x12>\n\tschedules\x18\x01 \x03(\x0b\x32+.temporal.api.schedule.v1.ScheduleListEntry\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c"9\n\x15\x43ountSchedulesRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\r\n\x05query\x18\x02 \x01(\t"\xdb\x01\n\x16\x43ountSchedulesResponse\x12\r\n\x05\x63ount\x18\x01 \x01(\x03\x12X\n\x06groups\x18\x02 \x03(\x0b\x32H.temporal.api.workflowservice.v1.CountSchedulesResponse.AggregationGroup\x1aX\n\x10\x41ggregationGroup\x12\x35\n\x0cgroup_values\x18\x01 \x03(\x0b\x32\x1f.temporal.api.common.v1.Payload\x12\r\n\x05\x63ount\x18\x02 \x01(\x03"\x86\x05\n\'UpdateWorkerBuildIdCompatibilityRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x12\n\ntask_queue\x18\x02 \x01(\t\x12-\n#add_new_build_id_in_new_default_set\x18\x03 \x01(\tH\x00\x12\x87\x01\n\x1b\x61\x64\x64_new_compatible_build_id\x18\x04 \x01(\x0b\x32`.temporal.api.workflowservice.v1.UpdateWorkerBuildIdCompatibilityRequest.AddNewCompatibleVersionH\x00\x12!\n\x17promote_set_by_build_id\x18\x05 \x01(\tH\x00\x12%\n\x1bpromote_build_id_within_set\x18\x06 \x01(\tH\x00\x12h\n\nmerge_sets\x18\x07 \x01(\x0b\x32R.temporal.api.workflowservice.v1.UpdateWorkerBuildIdCompatibilityRequest.MergeSetsH\x00\x1ao\n\x17\x41\x64\x64NewCompatibleVersion\x12\x14\n\x0cnew_build_id\x18\x01 \x01(\t\x12$\n\x1c\x65xisting_compatible_build_id\x18\x02 \x01(\t\x12\x18\n\x10make_set_default\x18\x03 \x01(\x08\x1aI\n\tMergeSets\x12\x1c\n\x14primary_set_build_id\x18\x01 \x01(\t\x12\x1e\n\x16secondary_set_build_id\x18\x02 \x01(\tB\x0b\n\toperation"@\n(UpdateWorkerBuildIdCompatibilityResponseJ\x04\x08\x01\x10\x02R\x0eversion_set_id"_\n$GetWorkerBuildIdCompatibilityRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x12\n\ntask_queue\x18\x02 \x01(\t\x12\x10\n\x08max_sets\x18\x03 \x01(\x05"t\n%GetWorkerBuildIdCompatibilityResponse\x12K\n\x12major_version_sets\x18\x01 \x03(\x0b\x32/.temporal.api.taskqueue.v1.CompatibleVersionSet"\xb5\r\n"UpdateWorkerVersioningRulesRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x12\n\ntask_queue\x18\x02 \x01(\t\x12\x16\n\x0e\x63onflict_token\x18\x03 \x01(\x0c\x12\x81\x01\n\x16insert_assignment_rule\x18\x04 \x01(\x0b\x32_.temporal.api.workflowservice.v1.UpdateWorkerVersioningRulesRequest.InsertBuildIdAssignmentRuleH\x00\x12\x83\x01\n\x17replace_assignment_rule\x18\x05 \x01(\x0b\x32`.temporal.api.workflowservice.v1.UpdateWorkerVersioningRulesRequest.ReplaceBuildIdAssignmentRuleH\x00\x12\x81\x01\n\x16\x64\x65lete_assignment_rule\x18\x06 \x01(\x0b\x32_.temporal.api.workflowservice.v1.UpdateWorkerVersioningRulesRequest.DeleteBuildIdAssignmentRuleH\x00\x12\x8c\x01\n\x1c\x61\x64\x64_compatible_redirect_rule\x18\x07 \x01(\x0b\x32\x64.temporal.api.workflowservice.v1.UpdateWorkerVersioningRulesRequest.AddCompatibleBuildIdRedirectRuleH\x00\x12\x94\x01\n replace_compatible_redirect_rule\x18\x08 \x01(\x0b\x32h.temporal.api.workflowservice.v1.UpdateWorkerVersioningRulesRequest.ReplaceCompatibleBuildIdRedirectRuleH\x00\x12\x92\x01\n\x1f\x64\x65lete_compatible_redirect_rule\x18\t \x01(\x0b\x32g.temporal.api.workflowservice.v1.UpdateWorkerVersioningRulesRequest.DeleteCompatibleBuildIdRedirectRuleH\x00\x12l\n\x0f\x63ommit_build_id\x18\n \x01(\x0b\x32Q.temporal.api.workflowservice.v1.UpdateWorkerVersioningRulesRequest.CommitBuildIdH\x00\x1aq\n\x1bInsertBuildIdAssignmentRule\x12\x12\n\nrule_index\x18\x01 \x01(\x05\x12>\n\x04rule\x18\x02 \x01(\x0b\x32\x30.temporal.api.taskqueue.v1.BuildIdAssignmentRule\x1a\x81\x01\n\x1cReplaceBuildIdAssignmentRule\x12\x12\n\nrule_index\x18\x01 \x01(\x05\x12>\n\x04rule\x18\x02 \x01(\x0b\x32\x30.temporal.api.taskqueue.v1.BuildIdAssignmentRule\x12\r\n\x05\x66orce\x18\x03 \x01(\x08\x1a@\n\x1b\x44\x65leteBuildIdAssignmentRule\x12\x12\n\nrule_index\x18\x01 \x01(\x05\x12\r\n\x05\x66orce\x18\x02 \x01(\x08\x1aj\n AddCompatibleBuildIdRedirectRule\x12\x46\n\x04rule\x18\x01 \x01(\x0b\x32\x38.temporal.api.taskqueue.v1.CompatibleBuildIdRedirectRule\x1an\n$ReplaceCompatibleBuildIdRedirectRule\x12\x46\n\x04rule\x18\x01 \x01(\x0b\x32\x38.temporal.api.taskqueue.v1.CompatibleBuildIdRedirectRule\x1a>\n#DeleteCompatibleBuildIdRedirectRule\x12\x17\n\x0fsource_build_id\x18\x01 \x01(\t\x1a\x37\n\rCommitBuildId\x12\x17\n\x0ftarget_build_id\x18\x01 \x01(\t\x12\r\n\x05\x66orce\x18\x02 \x01(\x08\x42\x0b\n\toperation"\xfc\x01\n#UpdateWorkerVersioningRulesResponse\x12U\n\x10\x61ssignment_rules\x18\x01 \x03(\x0b\x32;.temporal.api.taskqueue.v1.TimestampedBuildIdAssignmentRule\x12\x66\n\x19\x63ompatible_redirect_rules\x18\x02 \x03(\x0b\x32\x43.temporal.api.taskqueue.v1.TimestampedCompatibleBuildIdRedirectRule\x12\x16\n\x0e\x63onflict_token\x18\x03 \x01(\x0c"H\n\x1fGetWorkerVersioningRulesRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x12\n\ntask_queue\x18\x02 \x01(\t"\xf9\x01\n GetWorkerVersioningRulesResponse\x12U\n\x10\x61ssignment_rules\x18\x01 \x03(\x0b\x32;.temporal.api.taskqueue.v1.TimestampedBuildIdAssignmentRule\x12\x66\n\x19\x63ompatible_redirect_rules\x18\x02 \x03(\x0b\x32\x43.temporal.api.taskqueue.v1.TimestampedCompatibleBuildIdRedirectRule\x12\x16\n\x0e\x63onflict_token\x18\x03 \x01(\x0c"\x9c\x01\n GetWorkerTaskReachabilityRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x11\n\tbuild_ids\x18\x02 \x03(\t\x12\x13\n\x0btask_queues\x18\x03 \x03(\t\x12=\n\x0creachability\x18\x04 \x01(\x0e\x32\'.temporal.api.enums.v1.TaskReachability"r\n!GetWorkerTaskReachabilityResponse\x12M\n\x15\x62uild_id_reachability\x18\x01 \x03(\x0b\x32..temporal.api.taskqueue.v1.BuildIdReachability"\x85\x02\n\x1eUpdateWorkflowExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x45\n\x12workflow_execution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x1e\n\x16\x66irst_execution_run_id\x18\x03 \x01(\t\x12\x37\n\x0bwait_policy\x18\x04 \x01(\x0b\x32".temporal.api.update.v1.WaitPolicy\x12\x30\n\x07request\x18\x05 \x01(\x0b\x32\x1f.temporal.api.update.v1.Request"\x83\x02\n\x1fUpdateWorkflowExecutionResponse\x12\x35\n\nupdate_ref\x18\x01 \x01(\x0b\x32!.temporal.api.update.v1.UpdateRef\x12\x30\n\x07outcome\x18\x02 \x01(\x0b\x32\x1f.temporal.api.update.v1.Outcome\x12K\n\x05stage\x18\x03 \x01(\x0e\x32<.temporal.api.enums.v1.UpdateWorkflowExecutionLifecycleStage\x12*\n\x04link\x18\x04 \x01(\x0b\x32\x1c.temporal.api.common.v1.Link"\xf4\x07\n\x1aStartBatchOperationRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x18\n\x10visibility_query\x18\x02 \x01(\t\x12\x0e\n\x06job_id\x18\x03 \x01(\t\x12\x0e\n\x06reason\x18\x04 \x01(\t\x12=\n\nexecutions\x18\x05 \x03(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12!\n\x19max_operations_per_second\x18\x06 \x01(\x02\x12Q\n\x15termination_operation\x18\n \x01(\x0b\x32\x30.temporal.api.batch.v1.BatchOperationTerminationH\x00\x12G\n\x10signal_operation\x18\x0b \x01(\x0b\x32+.temporal.api.batch.v1.BatchOperationSignalH\x00\x12S\n\x16\x63\x61ncellation_operation\x18\x0c \x01(\x0b\x32\x31.temporal.api.batch.v1.BatchOperationCancellationH\x00\x12K\n\x12\x64\x65letion_operation\x18\r \x01(\x0b\x32-.temporal.api.batch.v1.BatchOperationDeletionH\x00\x12\x45\n\x0freset_operation\x18\x0e \x01(\x0b\x32*.temporal.api.batch.v1.BatchOperationResetH\x00\x12p\n!update_workflow_options_operation\x18\x0f \x01(\x0b\x32\x43.temporal.api.batch.v1.BatchOperationUpdateWorkflowExecutionOptionsH\x00\x12^\n\x1cunpause_activities_operation\x18\x10 \x01(\x0b\x32\x36.temporal.api.batch.v1.BatchOperationUnpauseActivitiesH\x00\x12Z\n\x1areset_activities_operation\x18\x11 \x01(\x0b\x32\x34.temporal.api.batch.v1.BatchOperationResetActivitiesH\x00\x12g\n!update_activity_options_operation\x18\x12 \x01(\x0b\x32:.temporal.api.batch.v1.BatchOperationUpdateActivityOptionsH\x00\x42\x0b\n\toperation"\x1d\n\x1bStartBatchOperationResponse"`\n\x19StopBatchOperationRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x0e\n\x06job_id\x18\x02 \x01(\t\x12\x0e\n\x06reason\x18\x03 \x01(\t\x12\x10\n\x08identity\x18\x04 \x01(\t"\x1c\n\x1aStopBatchOperationResponse"B\n\x1d\x44\x65scribeBatchOperationRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x0e\n\x06job_id\x18\x02 \x01(\t"\x92\x03\n\x1e\x44\x65scribeBatchOperationResponse\x12\x41\n\x0eoperation_type\x18\x01 \x01(\x0e\x32).temporal.api.enums.v1.BatchOperationType\x12\x0e\n\x06job_id\x18\x02 \x01(\t\x12\x39\n\x05state\x18\x03 \x01(\x0e\x32*.temporal.api.enums.v1.BatchOperationState\x12.\n\nstart_time\x18\x04 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12.\n\nclose_time\x18\x05 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x1d\n\x15total_operation_count\x18\x06 \x01(\x03\x12 \n\x18\x63omplete_operation_count\x18\x07 \x01(\x03\x12\x1f\n\x17\x66\x61ilure_operation_count\x18\x08 \x01(\x03\x12\x10\n\x08identity\x18\t \x01(\t\x12\x0e\n\x06reason\x18\n \x01(\t"[\n\x1aListBatchOperationsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x11\n\tpage_size\x18\x02 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c"y\n\x1bListBatchOperationsResponse\x12\x41\n\x0eoperation_info\x18\x01 \x03(\x0b\x32).temporal.api.batch.v1.BatchOperationInfo\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c"\xb9\x01\n"PollWorkflowExecutionUpdateRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x35\n\nupdate_ref\x18\x02 \x01(\x0b\x32!.temporal.api.update.v1.UpdateRef\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x37\n\x0bwait_policy\x18\x04 \x01(\x0b\x32".temporal.api.update.v1.WaitPolicy"\xdb\x01\n#PollWorkflowExecutionUpdateResponse\x12\x30\n\x07outcome\x18\x01 \x01(\x0b\x32\x1f.temporal.api.update.v1.Outcome\x12K\n\x05stage\x18\x02 \x01(\x0e\x32<.temporal.api.enums.v1.UpdateWorkflowExecutionLifecycleStage\x12\x35\n\nupdate_ref\x18\x03 \x01(\x0b\x32!.temporal.api.update.v1.UpdateRef"\xa0\x03\n\x19PollNexusTaskQueueRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x38\n\ntask_queue\x18\x03 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12\x17\n\x0fpoller_group_id\x18\t \x01(\t\x12\x10\n\x08identity\x18\x02 \x01(\t\x12\x1b\n\x13worker_instance_key\x18\x08 \x01(\t\x12Z\n\x1bworker_version_capabilities\x18\x04 \x01(\x0b\x32\x31.temporal.api.common.v1.WorkerVersionCapabilitiesB\x02\x18\x01\x12O\n\x12\x64\x65ployment_options\x18\x06 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentOptions\x12\x41\n\x10worker_heartbeat\x18\x07 \x03(\x0b\x32\'.temporal.api.worker.v1.WorkerHeartbeat"\x95\x02\n\x1aPollNexusTaskQueueResponse\x12\x12\n\ntask_token\x18\x01 \x01(\x0c\x12/\n\x07request\x18\x02 \x01(\x0b\x32\x1e.temporal.api.nexus.v1.Request\x12Q\n\x17poller_scaling_decision\x18\x03 \x01(\x0b\x32\x30.temporal.api.taskqueue.v1.PollerScalingDecision\x12\x17\n\x0fpoller_group_id\x18\x04 \x01(\t\x12\x46\n\x12poller_group_infos\x18\x05 \x03(\x0b\x32*.temporal.api.taskqueue.v1.PollerGroupInfo"\xa7\x01\n RespondNexusTaskCompletedRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x10\n\x08identity\x18\x02 \x01(\t\x12\x12\n\ntask_token\x18\x03 \x01(\x0c\x12\x31\n\x08response\x18\x04 \x01(\x0b\x32\x1f.temporal.api.nexus.v1.Response\x12\x17\n\x0fpoller_group_id\x18\x05 \x01(\t"#\n!RespondNexusTaskCompletedResponse"\xdc\x01\n\x1dRespondNexusTaskFailedRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x10\n\x08identity\x18\x02 \x01(\t\x12\x12\n\ntask_token\x18\x03 \x01(\x0c\x12\x36\n\x05\x65rror\x18\x04 \x01(\x0b\x32#.temporal.api.nexus.v1.HandlerErrorB\x02\x18\x01\x12\x31\n\x07\x66\x61ilure\x18\x05 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12\x17\n\x0fpoller_group_id\x18\x06 \x01(\t" \n\x1eRespondNexusTaskFailedResponse"\xf4\x02\n\x1c\x45xecuteMultiOperationRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12[\n\noperations\x18\x02 \x03(\x0b\x32G.temporal.api.workflowservice.v1.ExecuteMultiOperationRequest.Operation\x12\x13\n\x0bresource_id\x18\x03 \x01(\t\x1a\xce\x01\n\tOperation\x12X\n\x0estart_workflow\x18\x01 \x01(\x0b\x32>.temporal.api.workflowservice.v1.StartWorkflowExecutionRequestH\x00\x12Z\n\x0fupdate_workflow\x18\x02 \x01(\x0b\x32?.temporal.api.workflowservice.v1.UpdateWorkflowExecutionRequestH\x00\x42\x0b\n\toperation"\xcc\x02\n\x1d\x45xecuteMultiOperationResponse\x12Z\n\tresponses\x18\x01 \x03(\x0b\x32G.temporal.api.workflowservice.v1.ExecuteMultiOperationResponse.Response\x1a\xce\x01\n\x08Response\x12Y\n\x0estart_workflow\x18\x01 \x01(\x0b\x32?.temporal.api.workflowservice.v1.StartWorkflowExecutionResponseH\x00\x12[\n\x0fupdate_workflow\x18\x02 \x01(\x0b\x32@.temporal.api.workflowservice.v1.UpdateWorkflowExecutionResponseH\x00\x42\n\n\x08response"\xd0\x02\n\x1cUpdateActivityOptionsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12<\n\texecution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x43\n\x10\x61\x63tivity_options\x18\x04 \x01(\x0b\x32).temporal.api.activity.v1.ActivityOptions\x12/\n\x0bupdate_mask\x18\x05 \x01(\x0b\x32\x1a.google.protobuf.FieldMask\x12\x0c\n\x02id\x18\x06 \x01(\tH\x00\x12\x0e\n\x04type\x18\x07 \x01(\tH\x00\x12\x13\n\tmatch_all\x18\t \x01(\x08H\x00\x12\x18\n\x10restore_original\x18\x08 \x01(\x08\x42\n\n\x08\x61\x63tivity"\xab\x02\n%UpdateActivityExecutionOptionsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12\x13\n\x0b\x61\x63tivity_id\x18\x03 \x01(\t\x12\x0e\n\x06run_id\x18\x04 \x01(\t\x12\x10\n\x08identity\x18\x05 \x01(\t\x12\x43\n\x10\x61\x63tivity_options\x18\x06 \x01(\x0b\x32).temporal.api.activity.v1.ActivityOptions\x12/\n\x0bupdate_mask\x18\x07 \x01(\x0b\x32\x1a.google.protobuf.FieldMask\x12\x18\n\x10restore_original\x18\x08 \x01(\x08\x12\x13\n\x0bresource_id\x18\t \x01(\t"d\n\x1dUpdateActivityOptionsResponse\x12\x43\n\x10\x61\x63tivity_options\x18\x01 \x01(\x0b\x32).temporal.api.activity.v1.ActivityOptions"m\n&UpdateActivityExecutionOptionsResponse\x12\x43\n\x10\x61\x63tivity_options\x18\x01 \x01(\x0b\x32).temporal.api.activity.v1.ActivityOptions"\xc7\x01\n\x14PauseActivityRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12<\n\texecution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x0c\n\x02id\x18\x04 \x01(\tH\x00\x12\x0e\n\x04type\x18\x05 \x01(\tH\x00\x12\x0e\n\x06reason\x18\x06 \x01(\t\x12\x12\n\nrequest_id\x18\x07 \x01(\tB\n\n\x08\x61\x63tivity"\xb7\x01\n\x1dPauseActivityExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12\x13\n\x0b\x61\x63tivity_id\x18\x03 \x01(\t\x12\x0e\n\x06run_id\x18\x04 \x01(\t\x12\x10\n\x08identity\x18\x05 \x01(\t\x12\x0e\n\x06reason\x18\x06 \x01(\t\x12\x13\n\x0bresource_id\x18\x07 \x01(\t\x12\x12\n\nrequest_id\x18\x08 \x01(\t"\x17\n\x15PauseActivityResponse" \n\x1ePauseActivityExecutionResponse"\x98\x02\n\x16UnpauseActivityRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12<\n\texecution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x0c\n\x02id\x18\x04 \x01(\tH\x00\x12\x0e\n\x04type\x18\x05 \x01(\tH\x00\x12\x15\n\x0bunpause_all\x18\x06 \x01(\x08H\x00\x12\x16\n\x0ereset_attempts\x18\x07 \x01(\x08\x12\x17\n\x0freset_heartbeat\x18\x08 \x01(\x08\x12)\n\x06jitter\x18\t \x01(\x0b\x32\x19.google.protobuf.DurationB\n\n\x08\x61\x63tivity"\x81\x02\n\x1fUnpauseActivityExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12\x13\n\x0b\x61\x63tivity_id\x18\x03 \x01(\t\x12\x0e\n\x06run_id\x18\x04 \x01(\t\x12\x10\n\x08identity\x18\x05 \x01(\t\x12\x16\n\x0ereset_attempts\x18\x06 \x01(\x08\x12\x17\n\x0freset_heartbeat\x18\x07 \x01(\x08\x12\x0e\n\x06reason\x18\x08 \x01(\t\x12)\n\x06jitter\x18\t \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x13\n\x0bresource_id\x18\n \x01(\t"\x19\n\x17UnpauseActivityResponse""\n UnpauseActivityExecutionResponse"\xb3\x02\n\x14ResetActivityRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12<\n\texecution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x0c\n\x02id\x18\x04 \x01(\tH\x00\x12\x0e\n\x04type\x18\x05 \x01(\tH\x00\x12\x13\n\tmatch_all\x18\n \x01(\x08H\x00\x12\x17\n\x0freset_heartbeat\x18\x06 \x01(\x08\x12\x13\n\x0bkeep_paused\x18\x07 \x01(\x08\x12)\n\x06jitter\x18\x08 \x01(\x0b\x32\x19.google.protobuf.Duration\x12 \n\x18restore_original_options\x18\t \x01(\x08\x42\n\n\x08\x61\x63tivity"\x8e\x02\n\x1dResetActivityExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12\x13\n\x0b\x61\x63tivity_id\x18\x03 \x01(\t\x12\x0e\n\x06run_id\x18\x04 \x01(\t\x12\x10\n\x08identity\x18\x05 \x01(\t\x12\x17\n\x0freset_heartbeat\x18\x06 \x01(\x08\x12\x13\n\x0bkeep_paused\x18\x07 \x01(\x08\x12)\n\x06jitter\x18\x08 \x01(\x0b\x32\x19.google.protobuf.Duration\x12 \n\x18restore_original_options\x18\t \x01(\x08\x12\x13\n\x0bresource_id\x18\n \x01(\t"\x17\n\x15ResetActivityResponse" \n\x1eResetActivityExecutionResponse"\x9c\x02\n%UpdateWorkflowExecutionOptionsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x45\n\x12workflow_execution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12V\n\x1aworkflow_execution_options\x18\x03 \x01(\x0b\x32\x32.temporal.api.workflow.v1.WorkflowExecutionOptions\x12/\n\x0bupdate_mask\x18\x04 \x01(\x0b\x32\x1a.google.protobuf.FieldMask\x12\x10\n\x08identity\x18\x05 \x01(\t"\x80\x01\n&UpdateWorkflowExecutionOptionsResponse\x12V\n\x1aworkflow_execution_options\x18\x01 \x01(\x0b\x32\x32.temporal.api.workflow.v1.WorkflowExecutionOptions"j\n\x19\x44\x65scribeDeploymentRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12:\n\ndeployment\x18\x02 \x01(\x0b\x32&.temporal.api.deployment.v1.Deployment"a\n\x1a\x44\x65scribeDeploymentResponse\x12\x43\n\x0f\x64\x65ployment_info\x18\x01 \x01(\x0b\x32*.temporal.api.deployment.v1.DeploymentInfo"\xc2\x01\n&DescribeWorkerDeploymentVersionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x07version\x18\x02 \x01(\tB\x02\x18\x01\x12O\n\x12\x64\x65ployment_version\x18\x03 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersion\x12\x1f\n\x17report_task_queue_stats\x18\x04 \x01(\x08"\x8c\x05\n\'DescribeWorkerDeploymentVersionResponse\x12_\n\x1eworker_deployment_version_info\x18\x01 \x01(\x0b\x32\x37.temporal.api.deployment.v1.WorkerDeploymentVersionInfo\x12v\n\x13version_task_queues\x18\x02 \x03(\x0b\x32Y.temporal.api.workflowservice.v1.DescribeWorkerDeploymentVersionResponse.VersionTaskQueue\x1a\x87\x03\n\x10VersionTaskQueue\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x32\n\x04type\x18\x02 \x01(\x0e\x32$.temporal.api.enums.v1.TaskQueueType\x12\x38\n\x05stats\x18\x03 \x01(\x0b\x32).temporal.api.taskqueue.v1.TaskQueueStats\x12\x90\x01\n\x15stats_by_priority_key\x18\x04 \x03(\x0b\x32q.temporal.api.workflowservice.v1.DescribeWorkerDeploymentVersionResponse.VersionTaskQueue.StatsByPriorityKeyEntry\x1a\x64\n\x17StatsByPriorityKeyEntry\x12\x0b\n\x03key\x18\x01 \x01(\x05\x12\x38\n\x05value\x18\x02 \x01(\x0b\x32).temporal.api.taskqueue.v1.TaskQueueStats:\x02\x38\x01"M\n\x1f\x44\x65scribeWorkerDeploymentRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x17\n\x0f\x64\x65ployment_name\x18\x02 \x01(\t"\x8c\x01\n DescribeWorkerDeploymentResponse\x12\x16\n\x0e\x63onflict_token\x18\x01 \x01(\x0c\x12P\n\x16worker_deployment_info\x18\x02 \x01(\x0b\x32\x30.temporal.api.deployment.v1.WorkerDeploymentInfo"l\n\x16ListDeploymentsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x11\n\tpage_size\x18\x02 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c\x12\x13\n\x0bseries_name\x18\x04 \x01(\t"w\n\x17ListDeploymentsResponse\x12\x17\n\x0fnext_page_token\x18\x01 \x01(\x0c\x12\x43\n\x0b\x64\x65ployments\x18\x02 \x03(\x0b\x32..temporal.api.deployment.v1.DeploymentListInfo"\xcd\x01\n\x1bSetCurrentDeploymentRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12:\n\ndeployment\x18\x02 \x01(\x0b\x32&.temporal.api.deployment.v1.Deployment\x12\x10\n\x08identity\x18\x03 \x01(\t\x12M\n\x0fupdate_metadata\x18\x04 \x01(\x0b\x32\x34.temporal.api.deployment.v1.UpdateDeploymentMetadata"\xb9\x01\n\x1cSetCurrentDeploymentResponse\x12K\n\x17\x63urrent_deployment_info\x18\x01 \x01(\x0b\x32*.temporal.api.deployment.v1.DeploymentInfo\x12L\n\x18previous_deployment_info\x18\x02 \x01(\x0b\x32*.temporal.api.deployment.v1.DeploymentInfo"\xe5\x01\n(SetWorkerDeploymentCurrentVersionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x17\n\x0f\x64\x65ployment_name\x18\x02 \x01(\t\x12\x13\n\x07version\x18\x03 \x01(\tB\x02\x18\x01\x12\x10\n\x08\x62uild_id\x18\x07 \x01(\t\x12\x16\n\x0e\x63onflict_token\x18\x04 \x01(\x0c\x12\x10\n\x08identity\x18\x05 \x01(\t\x12"\n\x1aignore_missing_task_queues\x18\x06 \x01(\x08\x12\x18\n\x10\x61llow_no_pollers\x18\t \x01(\x08"\xbf\x01\n)SetWorkerDeploymentCurrentVersionResponse\x12\x16\n\x0e\x63onflict_token\x18\x01 \x01(\x0c\x12\x1c\n\x10previous_version\x18\x02 \x01(\tB\x02\x18\x01\x12\\\n\x1bprevious_deployment_version\x18\x03 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersionB\x02\x18\x01"\xf9\x01\n(SetWorkerDeploymentRampingVersionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x17\n\x0f\x64\x65ployment_name\x18\x02 \x01(\t\x12\x13\n\x07version\x18\x03 \x01(\tB\x02\x18\x01\x12\x10\n\x08\x62uild_id\x18\x08 \x01(\t\x12\x12\n\npercentage\x18\x04 \x01(\x02\x12\x16\n\x0e\x63onflict_token\x18\x05 \x01(\x0c\x12\x10\n\x08identity\x18\x06 \x01(\t\x12"\n\x1aignore_missing_task_queues\x18\x07 \x01(\x08\x12\x18\n\x10\x61llow_no_pollers\x18\n \x01(\x08"\xe0\x01\n)SetWorkerDeploymentRampingVersionResponse\x12\x16\n\x0e\x63onflict_token\x18\x01 \x01(\x0c\x12\x1c\n\x10previous_version\x18\x02 \x01(\tB\x02\x18\x01\x12\\\n\x1bprevious_deployment_version\x18\x04 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersionB\x02\x18\x01\x12\x1f\n\x13previous_percentage\x18\x03 \x01(\x02\x42\x02\x18\x01"q\n\x1d\x43reateWorkerDeploymentRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x17\n\x0f\x64\x65ployment_name\x18\x02 \x01(\t\x12\x10\n\x08identity\x18\x04 \x01(\t\x12\x12\n\nrequest_id\x18\x05 \x01(\t"8\n\x1e\x43reateWorkerDeploymentResponse\x12\x16\n\x0e\x63onflict_token\x18\x01 \x01(\x0c"]\n\x1cListWorkerDeploymentsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x11\n\tpage_size\x18\x02 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c"\x9f\x05\n\x1dListWorkerDeploymentsResponse\x12\x17\n\x0fnext_page_token\x18\x01 \x01(\x0c\x12r\n\x12worker_deployments\x18\x02 \x03(\x0b\x32V.temporal.api.workflowservice.v1.ListWorkerDeploymentsResponse.WorkerDeploymentSummary\x1a\xf0\x03\n\x17WorkerDeploymentSummary\x12\x0c\n\x04name\x18\x01 \x01(\t\x12/\n\x0b\x63reate_time\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x41\n\x0erouting_config\x18\x03 \x01(\x0b\x32).temporal.api.deployment.v1.RoutingConfig\x12o\n\x16latest_version_summary\x18\x04 \x01(\x0b\x32O.temporal.api.deployment.v1.WorkerDeploymentInfo.WorkerDeploymentVersionSummary\x12p\n\x17\x63urrent_version_summary\x18\x05 \x01(\x0b\x32O.temporal.api.deployment.v1.WorkerDeploymentInfo.WorkerDeploymentVersionSummary\x12p\n\x17ramping_version_summary\x18\x06 \x01(\x0b\x32O.temporal.api.deployment.v1.WorkerDeploymentInfo.WorkerDeploymentVersionSummary"\xf0\x01\n$CreateWorkerDeploymentVersionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12O\n\x12\x64\x65ployment_version\x18\x02 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersion\x12>\n\x0e\x63ompute_config\x18\x04 \x01(\x0b\x32&.temporal.api.compute.v1.ComputeConfig\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x12\n\nrequest_id\x18\x05 \x01(\t"\'\n%CreateWorkerDeploymentVersionResponse"\xc8\x01\n$DeleteWorkerDeploymentVersionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x07version\x18\x02 \x01(\tB\x02\x18\x01\x12O\n\x12\x64\x65ployment_version\x18\x05 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersion\x12\x15\n\rskip_drainage\x18\x03 \x01(\x08\x12\x10\n\x08identity\x18\x04 \x01(\t"\'\n%DeleteWorkerDeploymentVersionResponse"]\n\x1d\x44\x65leteWorkerDeploymentRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x17\n\x0f\x64\x65ployment_name\x18\x02 \x01(\t\x12\x10\n\x08identity\x18\x03 \x01(\t" \n\x1e\x44\x65leteWorkerDeploymentResponse"\x84\x04\n1UpdateWorkerDeploymentVersionComputeConfigRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12O\n\x12\x64\x65ployment_version\x18\x02 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersion\x12\x99\x01\n\x1d\x63ompute_config_scaling_groups\x18\x06 \x03(\x0b\x32r.temporal.api.workflowservice.v1.UpdateWorkerDeploymentVersionComputeConfigRequest.ComputeConfigScalingGroupsEntry\x12,\n$remove_compute_config_scaling_groups\x18\x07 \x03(\t\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x12\n\nrequest_id\x18\x04 \x01(\t\x1a{\n\x1f\x43omputeConfigScalingGroupsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12G\n\x05value\x18\x02 \x01(\x0b\x32\x38.temporal.api.compute.v1.ComputeConfigScalingGroupUpdate:\x02\x38\x01"4\n2UpdateWorkerDeploymentVersionComputeConfigResponse"\xf4\x03\n3ValidateWorkerDeploymentVersionComputeConfigRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12O\n\x12\x64\x65ployment_version\x18\x02 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersion\x12\x9b\x01\n\x1d\x63ompute_config_scaling_groups\x18\x06 \x03(\x0b\x32t.temporal.api.workflowservice.v1.ValidateWorkerDeploymentVersionComputeConfigRequest.ComputeConfigScalingGroupsEntry\x12,\n$remove_compute_config_scaling_groups\x18\x07 \x03(\t\x12\x10\n\x08identity\x18\x03 \x01(\t\x1a{\n\x1f\x43omputeConfigScalingGroupsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12G\n\x05value\x18\x02 \x01(\x0b\x32\x38.temporal.api.compute.v1.ComputeConfigScalingGroupUpdate:\x02\x38\x01"6\n4ValidateWorkerDeploymentVersionComputeConfigResponse"\xa2\x03\n,UpdateWorkerDeploymentVersionMetadataRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x07version\x18\x02 \x01(\tB\x02\x18\x01\x12O\n\x12\x64\x65ployment_version\x18\x05 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersion\x12x\n\x0eupsert_entries\x18\x03 \x03(\x0b\x32`.temporal.api.workflowservice.v1.UpdateWorkerDeploymentVersionMetadataRequest.UpsertEntriesEntry\x12\x16\n\x0eremove_entries\x18\x04 \x03(\t\x12\x10\n\x08identity\x18\x06 \x01(\t\x1aU\n\x12UpsertEntriesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12.\n\x05value\x18\x02 \x01(\x0b\x32\x1f.temporal.api.common.v1.Payload:\x02\x38\x01"n\n-UpdateWorkerDeploymentVersionMetadataResponse\x12=\n\x08metadata\x18\x01 \x01(\x0b\x32+.temporal.api.deployment.v1.VersionMetadata"\xbd\x01\n!SetWorkerDeploymentManagerRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x17\n\x0f\x64\x65ployment_name\x18\x02 \x01(\t\x12\x1a\n\x10manager_identity\x18\x03 \x01(\tH\x00\x12\x0e\n\x04self\x18\x04 \x01(\x08H\x00\x12\x16\n\x0e\x63onflict_token\x18\x05 \x01(\x0c\x12\x10\n\x08identity\x18\x06 \x01(\tB\x16\n\x14new_manager_identity"c\n"SetWorkerDeploymentManagerResponse\x12\x16\n\x0e\x63onflict_token\x18\x01 \x01(\x0c\x12%\n\x19previous_manager_identity\x18\x02 \x01(\tB\x02\x18\x01"E\n\x1bGetCurrentDeploymentRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bseries_name\x18\x02 \x01(\t"k\n\x1cGetCurrentDeploymentResponse\x12K\n\x17\x63urrent_deployment_info\x18\x01 \x01(\x0b\x32*.temporal.api.deployment.v1.DeploymentInfo"q\n GetDeploymentReachabilityRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12:\n\ndeployment\x18\x02 \x01(\x0b\x32&.temporal.api.deployment.v1.Deployment"\xe3\x01\n!GetDeploymentReachabilityResponse\x12\x43\n\x0f\x64\x65ployment_info\x18\x01 \x01(\x0b\x32*.temporal.api.deployment.v1.DeploymentInfo\x12\x43\n\x0creachability\x18\x02 \x01(\x0e\x32-.temporal.api.enums.v1.DeploymentReachability\x12\x34\n\x10last_update_time\x18\x03 \x01(\x0b\x32\x1a.google.protobuf.Timestamp"\xb4\x01\n\x19\x43reateWorkflowRuleRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x35\n\x04spec\x18\x02 \x01(\x0b\x32\'.temporal.api.rules.v1.WorkflowRuleSpec\x12\x12\n\nforce_scan\x18\x03 \x01(\x08\x12\x12\n\nrequest_id\x18\x04 \x01(\t\x12\x10\n\x08identity\x18\x05 \x01(\t\x12\x13\n\x0b\x64\x65scription\x18\x06 \x01(\t"_\n\x1a\x43reateWorkflowRuleResponse\x12\x31\n\x04rule\x18\x01 \x01(\x0b\x32#.temporal.api.rules.v1.WorkflowRule\x12\x0e\n\x06job_id\x18\x02 \x01(\t"A\n\x1b\x44\x65scribeWorkflowRuleRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x0f\n\x07rule_id\x18\x02 \x01(\t"Q\n\x1c\x44\x65scribeWorkflowRuleResponse\x12\x31\n\x04rule\x18\x01 \x01(\x0b\x32#.temporal.api.rules.v1.WorkflowRule"?\n\x19\x44\x65leteWorkflowRuleRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x0f\n\x07rule_id\x18\x02 \x01(\t"\x1c\n\x1a\x44\x65leteWorkflowRuleResponse"F\n\x18ListWorkflowRulesRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c"h\n\x19ListWorkflowRulesResponse\x12\x32\n\x05rules\x18\x01 \x03(\x0b\x32#.temporal.api.rules.v1.WorkflowRule\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c"\xce\x01\n\x1aTriggerWorkflowRuleRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12<\n\texecution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x0c\n\x02id\x18\x04 \x01(\tH\x00\x12\x37\n\x04spec\x18\x05 \x01(\x0b\x32\'.temporal.api.rules.v1.WorkflowRuleSpecH\x00\x12\x10\n\x08identity\x18\x03 \x01(\tB\x06\n\x04rule".\n\x1bTriggerWorkflowRuleResponse\x12\x0f\n\x07\x61pplied\x18\x01 \x01(\x08"\x9b\x01\n\x1cRecordWorkerHeartbeatRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x10\n\x08identity\x18\x02 \x01(\t\x12\x41\n\x10worker_heartbeat\x18\x03 \x03(\x0b\x32\'.temporal.api.worker.v1.WorkerHeartbeat\x12\x13\n\x0bresource_id\x18\x04 \x01(\t"\x1f\n\x1dRecordWorkerHeartbeatResponse"\x82\x01\n\x12ListWorkersRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x11\n\tpage_size\x18\x02 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c\x12\r\n\x05query\x18\x04 \x01(\t\x12\x1e\n\x16include_system_workers\x18\x05 \x01(\x08"\xa5\x01\n\x13ListWorkersResponse\x12<\n\x0cworkers_info\x18\x01 \x03(\x0b\x32".temporal.api.worker.v1.WorkerInfoB\x02\x18\x01\x12\x37\n\x07workers\x18\x03 \x03(\x0b\x32&.temporal.api.worker.v1.WorkerListInfo\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c"\xd5\x05\n\x1cUpdateTaskQueueConfigRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x10\n\x08identity\x18\x02 \x01(\t\x12\x12\n\ntask_queue\x18\x03 \x01(\t\x12=\n\x0ftask_queue_type\x18\x04 \x01(\x0e\x32$.temporal.api.enums.v1.TaskQueueType\x12n\n\x17update_queue_rate_limit\x18\x05 \x01(\x0b\x32M.temporal.api.workflowservice.v1.UpdateTaskQueueConfigRequest.RateLimitUpdate\x12}\n&update_fairness_key_rate_limit_default\x18\x06 \x01(\x0b\x32M.temporal.api.workflowservice.v1.UpdateTaskQueueConfigRequest.RateLimitUpdate\x12\x84\x01\n\x1dset_fairness_weight_overrides\x18\x07 \x03(\x0b\x32].temporal.api.workflowservice.v1.UpdateTaskQueueConfigRequest.SetFairnessWeightOverridesEntry\x12\'\n\x1funset_fairness_weight_overrides\x18\x08 \x03(\t\x1a[\n\x0fRateLimitUpdate\x12\x38\n\nrate_limit\x18\x01 \x01(\x0b\x32$.temporal.api.taskqueue.v1.RateLimit\x12\x0e\n\x06reason\x18\x02 \x01(\t\x1a\x41\n\x1fSetFairnessWeightOverridesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\x02:\x02\x38\x01"[\n\x1dUpdateTaskQueueConfigResponse\x12:\n\x06\x63onfig\x18\x01 \x01(\x0b\x32*.temporal.api.taskqueue.v1.TaskQueueConfig"\x9e\x01\n\x18\x46\x65tchWorkerConfigRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x10\n\x08identity\x18\x02 \x01(\t\x12\x0e\n\x06reason\x18\x03 \x01(\t\x12\x38\n\x08selector\x18\x06 \x01(\x0b\x32&.temporal.api.common.v1.WorkerSelector\x12\x13\n\x0bresource_id\x18\x07 \x01(\t"U\n\x19\x46\x65tchWorkerConfigResponse\x12\x38\n\rworker_config\x18\x01 \x01(\x0b\x32!.temporal.api.sdk.v1.WorkerConfig"\x8a\x02\n\x19UpdateWorkerConfigRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x10\n\x08identity\x18\x02 \x01(\t\x12\x0e\n\x06reason\x18\x03 \x01(\t\x12\x38\n\rworker_config\x18\x04 \x01(\x0b\x32!.temporal.api.sdk.v1.WorkerConfig\x12/\n\x0bupdate_mask\x18\x05 \x01(\x0b\x32\x1a.google.protobuf.FieldMask\x12\x38\n\x08selector\x18\x06 \x01(\x0b\x32&.temporal.api.common.v1.WorkerSelector\x12\x13\n\x0bresource_id\x18\x07 \x01(\t"d\n\x1aUpdateWorkerConfigResponse\x12:\n\rworker_config\x18\x01 \x01(\x0b\x32!.temporal.api.sdk.v1.WorkerConfigH\x00\x42\n\n\x08response"G\n\x15\x44\x65scribeWorkerRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x1b\n\x13worker_instance_key\x18\x02 \x01(\t"Q\n\x16\x44\x65scribeWorkerResponse\x12\x37\n\x0bworker_info\x18\x01 \x01(\x0b\x32".temporal.api.worker.v1.WorkerInfo"\x8d\x01\n\x1dPauseWorkflowExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x12\x10\n\x08identity\x18\x04 \x01(\t\x12\x0e\n\x06reason\x18\x05 \x01(\t\x12\x12\n\nrequest_id\x18\x06 \x01(\t" \n\x1ePauseWorkflowExecutionResponse"\x8f\x01\n\x1fUnpauseWorkflowExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x12\x10\n\x08identity\x18\x04 \x01(\t\x12\x0e\n\x06reason\x18\x05 \x01(\t\x12\x12\n\nrequest_id\x18\x06 \x01(\t""\n UnpauseWorkflowExecutionResponse"\x99\t\n\x1dStartActivityExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x10\n\x08identity\x18\x02 \x01(\t\x12\x12\n\nrequest_id\x18\x03 \x01(\t\x12\x13\n\x0b\x61\x63tivity_id\x18\x04 \x01(\t\x12;\n\ractivity_type\x18\x05 \x01(\x0b\x32$.temporal.api.common.v1.ActivityType\x12\x38\n\ntask_queue\x18\x06 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12<\n\x19schedule_to_close_timeout\x18\x07 \x01(\x0b\x32\x19.google.protobuf.Duration\x12<\n\x19schedule_to_start_timeout\x18\x08 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x39\n\x16start_to_close_timeout\x18\t \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x34\n\x11heartbeat_timeout\x18\n \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x39\n\x0cretry_policy\x18\x0b \x01(\x0b\x32#.temporal.api.common.v1.RetryPolicy\x12/\n\x05input\x18\x0c \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x45\n\x0fid_reuse_policy\x18\r \x01(\x0e\x32,.temporal.api.enums.v1.ActivityIdReusePolicy\x12K\n\x12id_conflict_policy\x18\x0e \x01(\x0e\x32/.temporal.api.enums.v1.ActivityIdConflictPolicy\x12\x43\n\x11search_attributes\x18\x0f \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes\x12.\n\x06header\x18\x10 \x01(\x0b\x32\x1e.temporal.api.common.v1.Header\x12\x38\n\ruser_metadata\x18\x11 \x01(\x0b\x32!.temporal.api.sdk.v1.UserMetadata\x12\x32\n\x08priority\x18\x12 \x01(\x0b\x32 .temporal.api.common.v1.Priority\x12>\n\x14\x63ompletion_callbacks\x18\x13 \x03(\x0b\x32 .temporal.api.common.v1.Callback\x12+\n\x05links\x18\x14 \x03(\x0b\x32\x1c.temporal.api.common.v1.Link\x12\x46\n\x13on_conflict_options\x18\x15 \x01(\x0b\x32).temporal.api.common.v1.OnConflictOptions\x12.\n\x0bstart_delay\x18\x16 \x01(\x0b\x32\x19.google.protobuf.Duration"m\n\x1eStartActivityExecutionResponse\x12\x0e\n\x06run_id\x18\x01 \x01(\t\x12\x0f\n\x07started\x18\x02 \x01(\x08\x12*\n\x04link\x18\x03 \x01(\x0b\x32\x1c.temporal.api.common.v1.Link"\xe4\x01\n DescribeActivityExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0b\x61\x63tivity_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x12\x15\n\rinclude_input\x18\x04 \x01(\x08\x12\x17\n\x0finclude_outcome\x18\x05 \x01(\x08\x12\x17\n\x0flong_poll_token\x18\x06 \x01(\x0c\x12!\n\x19include_heartbeat_details\x18\x07 \x01(\x08\x12\x1c\n\x14include_last_failure\x18\x08 \x01(\x08"\xbc\x02\n!DescribeActivityExecutionResponse\x12\x0e\n\x06run_id\x18\x01 \x01(\t\x12=\n\x04info\x18\x02 \x01(\x0b\x32/.temporal.api.activity.v1.ActivityExecutionInfo\x12/\n\x05input\x18\x03 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x43\n\x07outcome\x18\x04 \x01(\x0b\x32\x32.temporal.api.activity.v1.ActivityExecutionOutcome\x12\x17\n\x0flong_poll_token\x18\x05 \x01(\x0c\x12\x39\n\tcallbacks\x18\x06 \x03(\x0b\x32&.temporal.api.activity.v1.CallbackInfo"V\n\x1cPollActivityExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0b\x61\x63tivity_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t"t\n\x1dPollActivityExecutionResponse\x12\x0e\n\x06run_id\x18\x01 \x01(\t\x12\x43\n\x07outcome\x18\x02 \x01(\x0b\x32\x32.temporal.api.activity.v1.ActivityExecutionOutcome"m\n\x1dListActivityExecutionsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x11\n\tpage_size\x18\x02 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c\x12\r\n\x05query\x18\x04 \x01(\t"\x82\x01\n\x1eListActivityExecutionsResponse\x12G\n\nexecutions\x18\x01 \x03(\x0b\x32\x33.temporal.api.activity.v1.ActivityExecutionListInfo\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c"\xd1\x06\n#StartNexusOperationExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x10\n\x08identity\x18\x02 \x01(\t\x12\x12\n\nrequest_id\x18\x03 \x01(\t\x12\x14\n\x0coperation_id\x18\x04 \x01(\t\x12\x10\n\x08\x65ndpoint\x18\x05 \x01(\t\x12\x0f\n\x07service\x18\x06 \x01(\t\x12\x11\n\toperation\x18\x07 \x01(\t\x12<\n\x19schedule_to_close_timeout\x18\x08 \x01(\x0b\x32\x19.google.protobuf.Duration\x12<\n\x19schedule_to_start_timeout\x18\t \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x39\n\x16start_to_close_timeout\x18\n \x01(\x0b\x32\x19.google.protobuf.Duration\x12.\n\x05input\x18\x0b \x01(\x0b\x32\x1f.temporal.api.common.v1.Payload\x12K\n\x0fid_reuse_policy\x18\x0c \x01(\x0e\x32\x32.temporal.api.enums.v1.NexusOperationIdReusePolicy\x12Q\n\x12id_conflict_policy\x18\r \x01(\x0e\x32\x35.temporal.api.enums.v1.NexusOperationIdConflictPolicy\x12\x43\n\x11search_attributes\x18\x0e \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes\x12k\n\x0cnexus_header\x18\x0f \x03(\x0b\x32U.temporal.api.workflowservice.v1.StartNexusOperationExecutionRequest.NexusHeaderEntry\x12\x38\n\ruser_metadata\x18\x10 \x01(\x0b\x32!.temporal.api.sdk.v1.UserMetadata\x1a\x32\n\x10NexusHeaderEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01"G\n$StartNexusOperationExecutionResponse\x12\x0e\n\x06run_id\x18\x01 \x01(\t\x12\x0f\n\x07started\x18\x02 \x01(\x08"\xaa\x01\n&DescribeNexusOperationExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x14\n\x0coperation_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x12\x15\n\rinclude_input\x18\x04 \x01(\x08\x12\x17\n\x0finclude_outcome\x18\x05 \x01(\x08\x12\x17\n\x0flong_poll_token\x18\x06 \x01(\x0c"\xb7\x02\n\'DescribeNexusOperationExecutionResponse\x12\x0e\n\x06run_id\x18\x01 \x01(\t\x12@\n\x04info\x18\x02 \x01(\x0b\x32\x32.temporal.api.nexus.v1.NexusOperationExecutionInfo\x12.\n\x05input\x18\x03 \x01(\x0b\x32\x1f.temporal.api.common.v1.Payload\x12\x31\n\x06result\x18\x04 \x01(\x0b\x32\x1f.temporal.api.common.v1.PayloadH\x00\x12\x33\n\x07\x66\x61ilure\x18\x05 \x01(\x0b\x32 .temporal.api.failure.v1.FailureH\x00\x12\x17\n\x0flong_poll_token\x18\x06 \x01(\x0c\x42\t\n\x07outcome"\xa1\x01\n"PollNexusOperationExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x14\n\x0coperation_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x12\x42\n\nwait_stage\x18\x04 \x01(\x0e\x32..temporal.api.enums.v1.NexusOperationWaitStage"\x85\x02\n#PollNexusOperationExecutionResponse\x12\x0e\n\x06run_id\x18\x01 \x01(\t\x12\x42\n\nwait_stage\x18\x02 \x01(\x0e\x32..temporal.api.enums.v1.NexusOperationWaitStage\x12\x17\n\x0foperation_token\x18\x03 \x01(\t\x12\x31\n\x06result\x18\x04 \x01(\x0b\x32\x1f.temporal.api.common.v1.PayloadH\x00\x12\x33\n\x07\x66\x61ilure\x18\x05 \x01(\x0b\x32 .temporal.api.failure.v1.FailureH\x00\x42\t\n\x07outcome"s\n#ListNexusOperationExecutionsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x11\n\tpage_size\x18\x02 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c\x12\r\n\x05query\x18\x04 \x01(\t"\x8b\x01\n$ListNexusOperationExecutionsResponse\x12J\n\noperations\x18\x01 \x03(\x0b\x32\x36.temporal.api.nexus.v1.NexusOperationExecutionListInfo\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c"B\n\x1e\x43ountActivityExecutionsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\r\n\x05query\x18\x02 \x01(\t"\xed\x01\n\x1f\x43ountActivityExecutionsResponse\x12\r\n\x05\x63ount\x18\x01 \x01(\x03\x12\x61\n\x06groups\x18\x02 \x03(\x0b\x32Q.temporal.api.workflowservice.v1.CountActivityExecutionsResponse.AggregationGroup\x1aX\n\x10\x41ggregationGroup\x12\x35\n\x0cgroup_values\x18\x01 \x03(\x0b\x32\x1f.temporal.api.common.v1.Payload\x12\r\n\x05\x63ount\x18\x02 \x01(\x03"H\n$CountNexusOperationExecutionsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\r\n\x05query\x18\x02 \x01(\t"\xf9\x01\n%CountNexusOperationExecutionsResponse\x12\r\n\x05\x63ount\x18\x01 \x01(\x03\x12g\n\x06groups\x18\x02 \x03(\x0b\x32W.temporal.api.workflowservice.v1.CountNexusOperationExecutionsResponse.AggregationGroup\x1aX\n\x10\x41ggregationGroup\x12\x35\n\x0cgroup_values\x18\x01 \x03(\x0b\x32\x1f.temporal.api.common.v1.Payload\x12\r\n\x05\x63ount\x18\x02 \x01(\x03"\x95\x01\n%RequestCancelActivityExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0b\x61\x63tivity_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x12\x10\n\x08identity\x18\x04 \x01(\t\x12\x12\n\nrequest_id\x18\x05 \x01(\t\x12\x0e\n\x06reason\x18\x06 \x01(\t"(\n&RequestCancelActivityExecutionResponse"\x91\x01\n!TerminateActivityExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0b\x61\x63tivity_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x12\x10\n\x08identity\x18\x04 \x01(\t\x12\x12\n\nrequest_id\x18\x05 \x01(\t\x12\x0e\n\x06reason\x18\x06 \x01(\t"$\n"TerminateActivityExecutionResponse"X\n\x1e\x44\x65leteActivityExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0b\x61\x63tivity_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t"!\n\x1f\x44\x65leteActivityExecutionResponse"\x9c\x01\n+RequestCancelNexusOperationExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x14\n\x0coperation_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x12\x10\n\x08identity\x18\x04 \x01(\t\x12\x12\n\nrequest_id\x18\x05 \x01(\t\x12\x0e\n\x06reason\x18\x06 \x01(\t".\n,RequestCancelNexusOperationExecutionResponse"\x98\x01\n\'TerminateNexusOperationExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x14\n\x0coperation_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x12\x10\n\x08identity\x18\x04 \x01(\t\x12\x12\n\nrequest_id\x18\x05 \x01(\t\x12\x0e\n\x06reason\x18\x06 \x01(\t"*\n(TerminateNexusOperationExecutionResponse"_\n$DeleteNexusOperationExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x14\n\x0coperation_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t"\'\n%DeleteNexusOperationExecutionResponseB\xbe\x01\n"io.temporal.api.workflowservice.v1B\x14RequestResponseProtoP\x01Z5go.temporal.io/api/workflowservice/v1;workflowservice\xaa\x02!Temporalio.Api.WorkflowService.V1\xea\x02$Temporalio::Api::WorkflowService::V1b\x06proto3' + b'\n6temporal/api/workflowservice/v1/request_response.proto\x12\x1ftemporal.api.workflowservice.v1\x1a+temporal/api/enums/v1/batch_operation.proto\x1a"temporal/api/enums/v1/common.proto\x1a$temporal/api/enums/v1/workflow.proto\x1a%temporal/api/enums/v1/namespace.proto\x1a(temporal/api/enums/v1/failed_cause.proto\x1a!temporal/api/enums/v1/query.proto\x1a!temporal/api/enums/v1/reset.proto\x1a&temporal/api/enums/v1/task_queue.proto\x1a&temporal/api/enums/v1/deployment.proto\x1a"temporal/api/enums/v1/update.proto\x1a$temporal/api/enums/v1/activity.proto\x1a!temporal/api/enums/v1/nexus.proto\x1a&temporal/api/activity/v1/message.proto\x1a$temporal/api/common/v1/message.proto\x1a%temporal/api/history/v1/message.proto\x1a&temporal/api/workflow/v1/message.proto\x1a%temporal/api/command/v1/message.proto\x1a$temporal/api/compute/v1/config.proto\x1a(temporal/api/deployment/v1/message.proto\x1a%temporal/api/failure/v1/message.proto\x1a$temporal/api/filter/v1/message.proto\x1a&temporal/api/protocol/v1/message.proto\x1a\'temporal/api/namespace/v1/message.proto\x1a#temporal/api/query/v1/message.proto\x1a)temporal/api/replication/v1/message.proto\x1a#temporal/api/rules/v1/message.proto\x1a\'temporal/api/sdk/v1/worker_config.proto\x1a&temporal/api/schedule/v1/message.proto\x1a\'temporal/api/taskqueue/v1/message.proto\x1a$temporal/api/update/v1/message.proto\x1a%temporal/api/version/v1/message.proto\x1a#temporal/api/batch/v1/message.proto\x1a\x30temporal/api/sdk/v1/task_complete_metadata.proto\x1a\'temporal/api/sdk/v1/user_metadata.proto\x1a#temporal/api/nexus/v1/message.proto\x1a$temporal/api/worker/v1/message.proto\x1a\x1egoogle/protobuf/duration.proto\x1a google/protobuf/field_mask.proto\x1a\x1fgoogle/protobuf/timestamp.proto"\x88\x05\n\x18RegisterNamespaceRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0b\x64\x65scription\x18\x02 \x01(\t\x12\x13\n\x0bowner_email\x18\x03 \x01(\t\x12\x46\n#workflow_execution_retention_period\x18\x04 \x01(\x0b\x32\x19.google.protobuf.Duration\x12G\n\x08\x63lusters\x18\x05 \x03(\x0b\x32\x35.temporal.api.replication.v1.ClusterReplicationConfig\x12\x1b\n\x13\x61\x63tive_cluster_name\x18\x06 \x01(\t\x12Q\n\x04\x64\x61ta\x18\x07 \x03(\x0b\x32\x43.temporal.api.workflowservice.v1.RegisterNamespaceRequest.DataEntry\x12\x16\n\x0esecurity_token\x18\x08 \x01(\t\x12\x1b\n\x13is_global_namespace\x18\t \x01(\x08\x12\x44\n\x16history_archival_state\x18\n \x01(\x0e\x32$.temporal.api.enums.v1.ArchivalState\x12\x1c\n\x14history_archival_uri\x18\x0b \x01(\t\x12G\n\x19visibility_archival_state\x18\x0c \x01(\x0e\x32$.temporal.api.enums.v1.ArchivalState\x12\x1f\n\x17visibility_archival_uri\x18\r \x01(\t\x1a+\n\tDataEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01"\x1b\n\x19RegisterNamespaceResponse"\x89\x01\n\x15ListNamespacesRequest\x12\x11\n\tpage_size\x18\x01 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c\x12\x44\n\x10namespace_filter\x18\x03 \x01(\x0b\x32*.temporal.api.namespace.v1.NamespaceFilter"\x81\x01\n\x16ListNamespacesResponse\x12N\n\nnamespaces\x18\x01 \x03(\x0b\x32:.temporal.api.workflowservice.v1.DescribeNamespaceResponse\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c"S\n\x18\x44\x65scribeNamespaceRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\n\n\x02id\x18\x02 \x01(\t\x12\x18\n\x10weak_consistency\x18\x03 \x01(\x08"\xb4\x03\n\x19\x44\x65scribeNamespaceResponse\x12@\n\x0enamespace_info\x18\x01 \x01(\x0b\x32(.temporal.api.namespace.v1.NamespaceInfo\x12:\n\x06\x63onfig\x18\x02 \x01(\x0b\x32*.temporal.api.namespace.v1.NamespaceConfig\x12S\n\x12replication_config\x18\x03 \x01(\x0b\x32\x37.temporal.api.replication.v1.NamespaceReplicationConfig\x12\x18\n\x10\x66\x61ilover_version\x18\x04 \x01(\x03\x12\x1b\n\x13is_global_namespace\x18\x05 \x01(\x08\x12\x45\n\x10\x66\x61ilover_history\x18\x06 \x03(\x0b\x32+.temporal.api.replication.v1.FailoverStatus\x12\x46\n\x12poller_group_infos\x18\x07 \x03(\x0b\x32*.temporal.api.taskqueue.v1.PollerGroupInfo"\xcf\x02\n\x16UpdateNamespaceRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x43\n\x0bupdate_info\x18\x02 \x01(\x0b\x32..temporal.api.namespace.v1.UpdateNamespaceInfo\x12:\n\x06\x63onfig\x18\x03 \x01(\x0b\x32*.temporal.api.namespace.v1.NamespaceConfig\x12S\n\x12replication_config\x18\x04 \x01(\x0b\x32\x37.temporal.api.replication.v1.NamespaceReplicationConfig\x12\x16\n\x0esecurity_token\x18\x05 \x01(\t\x12\x19\n\x11\x64\x65lete_bad_binary\x18\x06 \x01(\t\x12\x19\n\x11promote_namespace\x18\x07 \x01(\x08"\xa3\x02\n\x17UpdateNamespaceResponse\x12@\n\x0enamespace_info\x18\x01 \x01(\x0b\x32(.temporal.api.namespace.v1.NamespaceInfo\x12:\n\x06\x63onfig\x18\x02 \x01(\x0b\x32*.temporal.api.namespace.v1.NamespaceConfig\x12S\n\x12replication_config\x18\x03 \x01(\x0b\x32\x37.temporal.api.replication.v1.NamespaceReplicationConfig\x12\x18\n\x10\x66\x61ilover_version\x18\x04 \x01(\x03\x12\x1b\n\x13is_global_namespace\x18\x05 \x01(\x08"F\n\x19\x44\x65precateNamespaceRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x16\n\x0esecurity_token\x18\x02 \x01(\t"\x1c\n\x1a\x44\x65precateNamespaceResponse"\xd1\x0c\n\x1dStartWorkflowExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12;\n\rworkflow_type\x18\x03 \x01(\x0b\x32$.temporal.api.common.v1.WorkflowType\x12\x38\n\ntask_queue\x18\x04 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12/\n\x05input\x18\x05 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12=\n\x1aworkflow_execution_timeout\x18\x06 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x37\n\x14workflow_run_timeout\x18\x07 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x38\n\x15workflow_task_timeout\x18\x08 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x10\n\x08identity\x18\t \x01(\t\x12\x12\n\nrequest_id\x18\n \x01(\t\x12N\n\x18workflow_id_reuse_policy\x18\x0b \x01(\x0e\x32,.temporal.api.enums.v1.WorkflowIdReusePolicy\x12T\n\x1bworkflow_id_conflict_policy\x18\x16 \x01(\x0e\x32/.temporal.api.enums.v1.WorkflowIdConflictPolicy\x12\x39\n\x0cretry_policy\x18\x0c \x01(\x0b\x32#.temporal.api.common.v1.RetryPolicy\x12\x15\n\rcron_schedule\x18\r \x01(\t\x12*\n\x04memo\x18\x0e \x01(\x0b\x32\x1c.temporal.api.common.v1.Memo\x12\x43\n\x11search_attributes\x18\x0f \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes\x12.\n\x06header\x18\x10 \x01(\x0b\x32\x1e.temporal.api.common.v1.Header\x12\x1f\n\x17request_eager_execution\x18\x11 \x01(\x08\x12;\n\x11\x63ontinued_failure\x18\x12 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12@\n\x16last_completion_result\x18\x13 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x37\n\x14workflow_start_delay\x18\x14 \x01(\x0b\x32\x19.google.protobuf.Duration\x12>\n\x14\x63ompletion_callbacks\x18\x15 \x03(\x0b\x32 .temporal.api.common.v1.Callback\x12\x38\n\ruser_metadata\x18\x17 \x01(\x0b\x32!.temporal.api.sdk.v1.UserMetadata\x12+\n\x05links\x18\x18 \x03(\x0b\x32\x1c.temporal.api.common.v1.Link\x12I\n\x13versioning_override\x18\x19 \x01(\x0b\x32,.temporal.api.workflow.v1.VersioningOverride\x12H\n\x13on_conflict_options\x18\x1a \x01(\x0b\x32+.temporal.api.workflow.v1.OnConflictOptions\x12\x32\n\x08priority\x18\x1b \x01(\x0b\x32 .temporal.api.common.v1.Priority\x12\\\n\x1f\x65\x61ger_worker_deployment_options\x18\x1c \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentOptions\x12H\n\x14time_skipping_config\x18\x1d \x01(\x0b\x32*.temporal.api.common.v1.TimeSkippingConfig"\x8a\x02\n\x1eStartWorkflowExecutionResponse\x12\x0e\n\x06run_id\x18\x01 \x01(\t\x12\x0f\n\x07started\x18\x03 \x01(\x08\x12>\n\x06status\x18\x05 \x01(\x0e\x32..temporal.api.enums.v1.WorkflowExecutionStatus\x12[\n\x13\x65\x61ger_workflow_task\x18\x02 \x01(\x0b\x32>.temporal.api.workflowservice.v1.PollWorkflowTaskQueueResponse\x12*\n\x04link\x18\x04 \x01(\x0b\x32\x1c.temporal.api.common.v1.Link"\xaa\x02\n"GetWorkflowExecutionHistoryRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12<\n\texecution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x19\n\x11maximum_page_size\x18\x03 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x04 \x01(\x0c\x12\x16\n\x0ewait_new_event\x18\x05 \x01(\x08\x12P\n\x19history_event_filter_type\x18\x06 \x01(\x0e\x32-.temporal.api.enums.v1.HistoryEventFilterType\x12\x15\n\rskip_archival\x18\x07 \x01(\x08"\xba\x01\n#GetWorkflowExecutionHistoryResponse\x12\x31\n\x07history\x18\x01 \x01(\x0b\x32 .temporal.api.history.v1.History\x12\x35\n\x0braw_history\x18\x02 \x03(\x0b\x32 .temporal.api.common.v1.DataBlob\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c\x12\x10\n\x08\x61rchived\x18\x04 \x01(\x08"\xb0\x01\n)GetWorkflowExecutionHistoryReverseRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12<\n\texecution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x19\n\x11maximum_page_size\x18\x03 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x04 \x01(\x0c"x\n*GetWorkflowExecutionHistoryReverseResponse\x12\x31\n\x07history\x18\x01 \x01(\x0b\x32 .temporal.api.history.v1.History\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c"\xb8\x03\n\x1cPollWorkflowTaskQueueRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x38\n\ntask_queue\x18\x02 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12\x17\n\x0fpoller_group_id\x18\n \x01(\t\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x1b\n\x13worker_instance_key\x18\x08 \x01(\t\x12!\n\x19worker_control_task_queue\x18\t \x01(\t\x12\x1b\n\x0f\x62inary_checksum\x18\x04 \x01(\tB\x02\x18\x01\x12Z\n\x1bworker_version_capabilities\x18\x05 \x01(\x0b\x32\x31.temporal.api.common.v1.WorkerVersionCapabilitiesB\x02\x18\x01\x12O\n\x12\x64\x65ployment_options\x18\x06 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentOptionsJ\x04\x08\x07\x10\x08R\x10worker_heartbeat"\xf2\x07\n\x1dPollWorkflowTaskQueueResponse\x12\x12\n\ntask_token\x18\x01 \x01(\x0c\x12\x45\n\x12workflow_execution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12;\n\rworkflow_type\x18\x03 \x01(\x0b\x32$.temporal.api.common.v1.WorkflowType\x12!\n\x19previous_started_event_id\x18\x04 \x01(\x03\x12\x18\n\x10started_event_id\x18\x05 \x01(\x03\x12\x0f\n\x07\x61ttempt\x18\x06 \x01(\x05\x12\x1a\n\x12\x62\x61\x63klog_count_hint\x18\x07 \x01(\x03\x12\x31\n\x07history\x18\x08 \x01(\x0b\x32 .temporal.api.history.v1.History\x12\x17\n\x0fnext_page_token\x18\t \x01(\x0c\x12\x33\n\x05query\x18\n \x01(\x0b\x32$.temporal.api.query.v1.WorkflowQuery\x12K\n\x1dworkflow_execution_task_queue\x18\x0b \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12\x32\n\x0escheduled_time\x18\x0c \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x30\n\x0cstarted_time\x18\r \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\\\n\x07queries\x18\x0e \x03(\x0b\x32K.temporal.api.workflowservice.v1.PollWorkflowTaskQueueResponse.QueriesEntry\x12\x33\n\x08messages\x18\x0f \x03(\x0b\x32!.temporal.api.protocol.v1.Message\x12Q\n\x17poller_scaling_decision\x18\x10 \x01(\x0b\x32\x30.temporal.api.taskqueue.v1.PollerScalingDecision\x12\x17\n\x0fpoller_group_id\x18\x11 \x01(\t\x12\x46\n\x12poller_group_infos\x18\x12 \x03(\x0b\x32*.temporal.api.taskqueue.v1.PollerGroupInfo\x1aT\n\x0cQueriesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x33\n\x05value\x18\x02 \x01(\x0b\x32$.temporal.api.query.v1.WorkflowQuery:\x02\x38\x01"\x8a\n\n#RespondWorkflowTaskCompletedRequest\x12\x12\n\ntask_token\x18\x01 \x01(\x0c\x12\x32\n\x08\x63ommands\x18\x02 \x03(\x0b\x32 .temporal.api.command.v1.Command\x12\x10\n\x08identity\x18\x03 \x01(\t\x12O\n\x11sticky_attributes\x18\x04 \x01(\x0b\x32\x34.temporal.api.taskqueue.v1.StickyExecutionAttributes\x12 \n\x18return_new_workflow_task\x18\x05 \x01(\x08\x12&\n\x1e\x66orce_create_new_workflow_task\x18\x06 \x01(\x08\x12\x1b\n\x0f\x62inary_checksum\x18\x07 \x01(\tB\x02\x18\x01\x12m\n\rquery_results\x18\x08 \x03(\x0b\x32V.temporal.api.workflowservice.v1.RespondWorkflowTaskCompletedRequest.QueryResultsEntry\x12\x11\n\tnamespace\x18\t \x01(\t\x12\x13\n\x0bresource_id\x18\x12 \x01(\t\x12L\n\x14worker_version_stamp\x18\n \x01(\x0b\x32*.temporal.api.common.v1.WorkerVersionStampB\x02\x18\x01\x12\x33\n\x08messages\x18\x0b \x03(\x0b\x32!.temporal.api.protocol.v1.Message\x12H\n\x0csdk_metadata\x18\x0c \x01(\x0b\x32\x32.temporal.api.sdk.v1.WorkflowTaskCompletedMetadata\x12\x43\n\x11metering_metadata\x18\r \x01(\x0b\x32(.temporal.api.common.v1.MeteringMetadata\x12g\n\x0c\x63\x61pabilities\x18\x0e \x01(\x0b\x32Q.temporal.api.workflowservice.v1.RespondWorkflowTaskCompletedRequest.Capabilities\x12>\n\ndeployment\x18\x0f \x01(\x0b\x32&.temporal.api.deployment.v1.DeploymentB\x02\x18\x01\x12\x46\n\x13versioning_behavior\x18\x10 \x01(\x0e\x32).temporal.api.enums.v1.VersioningBehavior\x12O\n\x12\x64\x65ployment_options\x18\x11 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentOptions\x12\x1b\n\x13worker_instance_key\x18\x13 \x01(\t\x12!\n\x19worker_control_task_queue\x18\x14 \x01(\t\x1a_\n\x11QueryResultsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x39\n\x05value\x18\x02 \x01(\x0b\x32*.temporal.api.query.v1.WorkflowQueryResult:\x02\x38\x01\x1a\x45\n\x0c\x43\x61pabilities\x12\x35\n-discard_speculative_workflow_task_with_events\x18\x01 \x01(\x08"\xf5\x01\n$RespondWorkflowTaskCompletedResponse\x12U\n\rworkflow_task\x18\x01 \x01(\x0b\x32>.temporal.api.workflowservice.v1.PollWorkflowTaskQueueResponse\x12V\n\x0e\x61\x63tivity_tasks\x18\x02 \x03(\x0b\x32>.temporal.api.workflowservice.v1.PollActivityTaskQueueResponse\x12\x1e\n\x16reset_history_event_id\x18\x03 \x01(\x03"\x8d\x04\n RespondWorkflowTaskFailedRequest\x12\x12\n\ntask_token\x18\x01 \x01(\x0c\x12=\n\x05\x63\x61use\x18\x02 \x01(\x0e\x32..temporal.api.enums.v1.WorkflowTaskFailedCause\x12\x31\n\x07\x66\x61ilure\x18\x03 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12\x10\n\x08identity\x18\x04 \x01(\t\x12\x1b\n\x0f\x62inary_checksum\x18\x05 \x01(\tB\x02\x18\x01\x12\x11\n\tnamespace\x18\x06 \x01(\t\x12\x13\n\x0bresource_id\x18\x0b \x01(\t\x12\x33\n\x08messages\x18\x07 \x03(\x0b\x32!.temporal.api.protocol.v1.Message\x12\x46\n\x0eworker_version\x18\x08 \x01(\x0b\x32*.temporal.api.common.v1.WorkerVersionStampB\x02\x18\x01\x12>\n\ndeployment\x18\t \x01(\x0b\x32&.temporal.api.deployment.v1.DeploymentB\x02\x18\x01\x12O\n\x12\x64\x65ployment_options\x18\n \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentOptions"#\n!RespondWorkflowTaskFailedResponse"\xe6\x03\n\x1cPollActivityTaskQueueRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x38\n\ntask_queue\x18\x02 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12\x17\n\x0fpoller_group_id\x18\n \x01(\t\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x1b\n\x13worker_instance_key\x18\x08 \x01(\t\x12!\n\x19worker_control_task_queue\x18\t \x01(\t\x12I\n\x13task_queue_metadata\x18\x04 \x01(\x0b\x32,.temporal.api.taskqueue.v1.TaskQueueMetadata\x12Z\n\x1bworker_version_capabilities\x18\x05 \x01(\x0b\x32\x31.temporal.api.common.v1.WorkerVersionCapabilitiesB\x02\x18\x01\x12O\n\x12\x64\x65ployment_options\x18\x06 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentOptionsJ\x04\x08\x07\x10\x08R\x10worker_heartbeat"\xd0\x08\n\x1dPollActivityTaskQueueResponse\x12\x12\n\ntask_token\x18\x01 \x01(\x0c\x12\x1a\n\x12workflow_namespace\x18\x02 \x01(\t\x12;\n\rworkflow_type\x18\x03 \x01(\x0b\x32$.temporal.api.common.v1.WorkflowType\x12\x45\n\x12workflow_execution\x18\x04 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12;\n\ractivity_type\x18\x05 \x01(\x0b\x32$.temporal.api.common.v1.ActivityType\x12\x13\n\x0b\x61\x63tivity_id\x18\x06 \x01(\t\x12.\n\x06header\x18\x07 \x01(\x0b\x32\x1e.temporal.api.common.v1.Header\x12/\n\x05input\x18\x08 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12;\n\x11heartbeat_details\x18\t \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x32\n\x0escheduled_time\x18\n \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x42\n\x1e\x63urrent_attempt_scheduled_time\x18\x0b \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x30\n\x0cstarted_time\x18\x0c \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x0f\n\x07\x61ttempt\x18\r \x01(\x05\x12<\n\x19schedule_to_close_timeout\x18\x0e \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x39\n\x16start_to_close_timeout\x18\x0f \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x34\n\x11heartbeat_timeout\x18\x10 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x39\n\x0cretry_policy\x18\x11 \x01(\x0b\x32#.temporal.api.common.v1.RetryPolicy\x12Q\n\x17poller_scaling_decision\x18\x12 \x01(\x0b\x32\x30.temporal.api.taskqueue.v1.PollerScalingDecision\x12\x32\n\x08priority\x18\x13 \x01(\x0b\x32 .temporal.api.common.v1.Priority\x12\x17\n\x0f\x61\x63tivity_run_id\x18\x14 \x01(\t\x12\x46\n\x12poller_group_infos\x18\x15 \x03(\x0b\x32*.temporal.api.taskqueue.v1.PollerGroupInfo"\xa5\x01\n"RecordActivityTaskHeartbeatRequest\x12\x12\n\ntask_token\x18\x01 \x01(\x0c\x12\x31\n\x07\x64\x65tails\x18\x02 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x11\n\tnamespace\x18\x04 \x01(\t\x12\x13\n\x0bresource_id\x18\x05 \x01(\t"p\n#RecordActivityTaskHeartbeatResponse\x12\x18\n\x10\x63\x61ncel_requested\x18\x01 \x01(\x08\x12\x17\n\x0f\x61\x63tivity_paused\x18\x02 \x01(\x08\x12\x16\n\x0e\x61\x63tivity_reset\x18\x03 \x01(\x08"\xcf\x01\n&RecordActivityTaskHeartbeatByIdRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x12\x13\n\x0b\x61\x63tivity_id\x18\x04 \x01(\t\x12\x31\n\x07\x64\x65tails\x18\x05 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x10\n\x08identity\x18\x06 \x01(\t\x12\x13\n\x0bresource_id\x18\x07 \x01(\t"t\n\'RecordActivityTaskHeartbeatByIdResponse\x12\x18\n\x10\x63\x61ncel_requested\x18\x01 \x01(\x08\x12\x17\n\x0f\x61\x63tivity_paused\x18\x02 \x01(\x08\x12\x16\n\x0e\x61\x63tivity_reset\x18\x03 \x01(\x08"\xfe\x02\n#RespondActivityTaskCompletedRequest\x12\x12\n\ntask_token\x18\x01 \x01(\x0c\x12\x30\n\x06result\x18\x02 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x11\n\tnamespace\x18\x04 \x01(\t\x12\x13\n\x0bresource_id\x18\x08 \x01(\t\x12\x46\n\x0eworker_version\x18\x05 \x01(\x0b\x32*.temporal.api.common.v1.WorkerVersionStampB\x02\x18\x01\x12>\n\ndeployment\x18\x06 \x01(\x0b\x32&.temporal.api.deployment.v1.DeploymentB\x02\x18\x01\x12O\n\x12\x64\x65ployment_options\x18\x07 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentOptions"&\n$RespondActivityTaskCompletedResponse"\xcf\x01\n\'RespondActivityTaskCompletedByIdRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x12\x13\n\x0b\x61\x63tivity_id\x18\x04 \x01(\t\x12\x30\n\x06result\x18\x05 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x10\n\x08identity\x18\x06 \x01(\t\x12\x13\n\x0bresource_id\x18\x07 \x01(\t"*\n(RespondActivityTaskCompletedByIdResponse"\xbe\x03\n RespondActivityTaskFailedRequest\x12\x12\n\ntask_token\x18\x01 \x01(\x0c\x12\x31\n\x07\x66\x61ilure\x18\x02 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x11\n\tnamespace\x18\x04 \x01(\t\x12\x13\n\x0bresource_id\x18\t \x01(\t\x12@\n\x16last_heartbeat_details\x18\x05 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x46\n\x0eworker_version\x18\x06 \x01(\x0b\x32*.temporal.api.common.v1.WorkerVersionStampB\x02\x18\x01\x12>\n\ndeployment\x18\x07 \x01(\x0b\x32&.temporal.api.deployment.v1.DeploymentB\x02\x18\x01\x12O\n\x12\x64\x65ployment_options\x18\x08 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentOptions"W\n!RespondActivityTaskFailedResponse\x12\x32\n\x08\x66\x61ilures\x18\x01 \x03(\x0b\x32 .temporal.api.failure.v1.Failure"\x8f\x02\n$RespondActivityTaskFailedByIdRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x12\x13\n\x0b\x61\x63tivity_id\x18\x04 \x01(\t\x12\x31\n\x07\x66\x61ilure\x18\x05 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12\x10\n\x08identity\x18\x06 \x01(\t\x12@\n\x16last_heartbeat_details\x18\x07 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x13\n\x0bresource_id\x18\x08 \x01(\t"[\n%RespondActivityTaskFailedByIdResponse\x12\x32\n\x08\x66\x61ilures\x18\x01 \x03(\x0b\x32 .temporal.api.failure.v1.Failure"\xfe\x02\n"RespondActivityTaskCanceledRequest\x12\x12\n\ntask_token\x18\x01 \x01(\x0c\x12\x31\n\x07\x64\x65tails\x18\x02 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x11\n\tnamespace\x18\x04 \x01(\t\x12\x13\n\x0bresource_id\x18\x08 \x01(\t\x12\x46\n\x0eworker_version\x18\x05 \x01(\x0b\x32*.temporal.api.common.v1.WorkerVersionStampB\x02\x18\x01\x12>\n\ndeployment\x18\x06 \x01(\x0b\x32&.temporal.api.deployment.v1.DeploymentB\x02\x18\x01\x12O\n\x12\x64\x65ployment_options\x18\x07 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentOptions"%\n#RespondActivityTaskCanceledResponse"\xa0\x02\n&RespondActivityTaskCanceledByIdRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x12\x13\n\x0b\x61\x63tivity_id\x18\x04 \x01(\t\x12\x31\n\x07\x64\x65tails\x18\x05 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x10\n\x08identity\x18\x06 \x01(\t\x12O\n\x12\x64\x65ployment_options\x18\x07 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentOptions\x12\x13\n\x0bresource_id\x18\x08 \x01(\t")\n\'RespondActivityTaskCanceledByIdResponse"\x84\x02\n%RequestCancelWorkflowExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x45\n\x12workflow_execution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x12\n\nrequest_id\x18\x04 \x01(\t\x12\x1e\n\x16\x66irst_execution_run_id\x18\x05 \x01(\t\x12\x0e\n\x06reason\x18\x06 \x01(\t\x12+\n\x05links\x18\x07 \x03(\x0b\x32\x1c.temporal.api.common.v1.Link"(\n&RequestCancelWorkflowExecutionResponse"\xde\x02\n\x1eSignalWorkflowExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x45\n\x12workflow_execution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x13\n\x0bsignal_name\x18\x03 \x01(\t\x12/\n\x05input\x18\x04 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x10\n\x08identity\x18\x05 \x01(\t\x12\x12\n\nrequest_id\x18\x06 \x01(\t\x12\x13\n\x07\x63ontrol\x18\x07 \x01(\tB\x02\x18\x01\x12.\n\x06header\x18\x08 \x01(\x0b\x32\x1e.temporal.api.common.v1.Header\x12+\n\x05links\x18\n \x03(\x0b\x32\x1c.temporal.api.common.v1.LinkJ\x04\x08\t\x10\n"M\n\x1fSignalWorkflowExecutionResponse\x12*\n\x04link\x18\x01 \x01(\x0b\x32\x1c.temporal.api.common.v1.Link"\xbb\n\n\'SignalWithStartWorkflowExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12;\n\rworkflow_type\x18\x03 \x01(\x0b\x32$.temporal.api.common.v1.WorkflowType\x12\x38\n\ntask_queue\x18\x04 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12/\n\x05input\x18\x05 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12=\n\x1aworkflow_execution_timeout\x18\x06 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x37\n\x14workflow_run_timeout\x18\x07 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x38\n\x15workflow_task_timeout\x18\x08 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x10\n\x08identity\x18\t \x01(\t\x12\x12\n\nrequest_id\x18\n \x01(\t\x12N\n\x18workflow_id_reuse_policy\x18\x0b \x01(\x0e\x32,.temporal.api.enums.v1.WorkflowIdReusePolicy\x12T\n\x1bworkflow_id_conflict_policy\x18\x16 \x01(\x0e\x32/.temporal.api.enums.v1.WorkflowIdConflictPolicy\x12\x13\n\x0bsignal_name\x18\x0c \x01(\t\x12\x36\n\x0csignal_input\x18\r \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x13\n\x07\x63ontrol\x18\x0e \x01(\tB\x02\x18\x01\x12\x39\n\x0cretry_policy\x18\x0f \x01(\x0b\x32#.temporal.api.common.v1.RetryPolicy\x12\x15\n\rcron_schedule\x18\x10 \x01(\t\x12*\n\x04memo\x18\x11 \x01(\x0b\x32\x1c.temporal.api.common.v1.Memo\x12\x43\n\x11search_attributes\x18\x12 \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes\x12.\n\x06header\x18\x13 \x01(\x0b\x32\x1e.temporal.api.common.v1.Header\x12\x37\n\x14workflow_start_delay\x18\x14 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x38\n\ruser_metadata\x18\x17 \x01(\x0b\x32!.temporal.api.sdk.v1.UserMetadata\x12+\n\x05links\x18\x18 \x03(\x0b\x32\x1c.temporal.api.common.v1.Link\x12I\n\x13versioning_override\x18\x19 \x01(\x0b\x32,.temporal.api.workflow.v1.VersioningOverride\x12\x32\n\x08priority\x18\x1a \x01(\x0b\x32 .temporal.api.common.v1.Priority\x12H\n\x14time_skipping_config\x18\x1b \x01(\x0b\x32*.temporal.api.common.v1.TimeSkippingConfigJ\x04\x08\x15\x10\x16"~\n(SignalWithStartWorkflowExecutionResponse\x12\x0e\n\x06run_id\x18\x01 \x01(\t\x12\x0f\n\x07started\x18\x02 \x01(\x08\x12\x31\n\x0bsignal_link\x18\x03 \x01(\x0b\x32\x1c.temporal.api.common.v1.Link"\xc1\x03\n\x1dResetWorkflowExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x45\n\x12workflow_execution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x0e\n\x06reason\x18\x03 \x01(\t\x12%\n\x1dworkflow_task_finish_event_id\x18\x04 \x01(\x03\x12\x12\n\nrequest_id\x18\x05 \x01(\t\x12G\n\x12reset_reapply_type\x18\x06 \x01(\x0e\x32\'.temporal.api.enums.v1.ResetReapplyTypeB\x02\x18\x01\x12S\n\x1breset_reapply_exclude_types\x18\x07 \x03(\x0e\x32..temporal.api.enums.v1.ResetReapplyExcludeType\x12K\n\x15post_reset_operations\x18\x08 \x03(\x0b\x32,.temporal.api.workflow.v1.PostResetOperation\x12\x10\n\x08identity\x18\t \x01(\t"0\n\x1eResetWorkflowExecutionResponse\x12\x0e\n\x06run_id\x18\x01 \x01(\t"\x9f\x02\n!TerminateWorkflowExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x45\n\x12workflow_execution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x0e\n\x06reason\x18\x03 \x01(\t\x12\x31\n\x07\x64\x65tails\x18\x04 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x10\n\x08identity\x18\x05 \x01(\t\x12\x1e\n\x16\x66irst_execution_run_id\x18\x06 \x01(\t\x12+\n\x05links\x18\x07 \x03(\x0b\x32\x1c.temporal.api.common.v1.Link"$\n"TerminateWorkflowExecutionResponse"z\n\x1e\x44\x65leteWorkflowExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x45\n\x12workflow_execution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution"!\n\x1f\x44\x65leteWorkflowExecutionResponse"\xc9\x02\n!ListOpenWorkflowExecutionsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x19\n\x11maximum_page_size\x18\x02 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c\x12\x42\n\x11start_time_filter\x18\x04 \x01(\x0b\x32\'.temporal.api.filter.v1.StartTimeFilter\x12K\n\x10\x65xecution_filter\x18\x05 \x01(\x0b\x32/.temporal.api.filter.v1.WorkflowExecutionFilterH\x00\x12\x41\n\x0btype_filter\x18\x06 \x01(\x0b\x32*.temporal.api.filter.v1.WorkflowTypeFilterH\x00\x42\t\n\x07\x66ilters"\x82\x01\n"ListOpenWorkflowExecutionsResponse\x12\x43\n\nexecutions\x18\x01 \x03(\x0b\x32/.temporal.api.workflow.v1.WorkflowExecutionInfo\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c"\x8a\x03\n#ListClosedWorkflowExecutionsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x19\n\x11maximum_page_size\x18\x02 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c\x12\x42\n\x11start_time_filter\x18\x04 \x01(\x0b\x32\'.temporal.api.filter.v1.StartTimeFilter\x12K\n\x10\x65xecution_filter\x18\x05 \x01(\x0b\x32/.temporal.api.filter.v1.WorkflowExecutionFilterH\x00\x12\x41\n\x0btype_filter\x18\x06 \x01(\x0b\x32*.temporal.api.filter.v1.WorkflowTypeFilterH\x00\x12=\n\rstatus_filter\x18\x07 \x01(\x0b\x32$.temporal.api.filter.v1.StatusFilterH\x00\x42\t\n\x07\x66ilters"\x84\x01\n$ListClosedWorkflowExecutionsResponse\x12\x43\n\nexecutions\x18\x01 \x03(\x0b\x32/.temporal.api.workflow.v1.WorkflowExecutionInfo\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c"m\n\x1dListWorkflowExecutionsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x11\n\tpage_size\x18\x02 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c\x12\r\n\x05query\x18\x04 \x01(\t"~\n\x1eListWorkflowExecutionsResponse\x12\x43\n\nexecutions\x18\x01 \x03(\x0b\x32/.temporal.api.workflow.v1.WorkflowExecutionInfo\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c"u\n%ListArchivedWorkflowExecutionsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x11\n\tpage_size\x18\x02 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c\x12\r\n\x05query\x18\x04 \x01(\t"\x86\x01\n&ListArchivedWorkflowExecutionsResponse\x12\x43\n\nexecutions\x18\x01 \x03(\x0b\x32/.temporal.api.workflow.v1.WorkflowExecutionInfo\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c"m\n\x1dScanWorkflowExecutionsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x11\n\tpage_size\x18\x02 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c\x12\r\n\x05query\x18\x04 \x01(\t"~\n\x1eScanWorkflowExecutionsResponse\x12\x43\n\nexecutions\x18\x01 \x03(\x0b\x32/.temporal.api.workflow.v1.WorkflowExecutionInfo\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c"B\n\x1e\x43ountWorkflowExecutionsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\r\n\x05query\x18\x02 \x01(\t"\xed\x01\n\x1f\x43ountWorkflowExecutionsResponse\x12\r\n\x05\x63ount\x18\x01 \x01(\x03\x12\x61\n\x06groups\x18\x02 \x03(\x0b\x32Q.temporal.api.workflowservice.v1.CountWorkflowExecutionsResponse.AggregationGroup\x1aX\n\x10\x41ggregationGroup\x12\x35\n\x0cgroup_values\x18\x01 \x03(\x0b\x32\x1f.temporal.api.common.v1.Payload\x12\r\n\x05\x63ount\x18\x02 \x01(\x03"\x1c\n\x1aGetSearchAttributesRequest"\xc9\x01\n\x1bGetSearchAttributesResponse\x12T\n\x04keys\x18\x01 \x03(\x0b\x32\x46.temporal.api.workflowservice.v1.GetSearchAttributesResponse.KeysEntry\x1aT\n\tKeysEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x36\n\x05value\x18\x02 \x01(\x0e\x32\'.temporal.api.enums.v1.IndexedValueType:\x02\x38\x01"\xe9\x02\n RespondQueryTaskCompletedRequest\x12\x12\n\ntask_token\x18\x01 \x01(\x0c\x12>\n\x0e\x63ompleted_type\x18\x02 \x01(\x0e\x32&.temporal.api.enums.v1.QueryResultType\x12\x36\n\x0cquery_result\x18\x03 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x15\n\rerror_message\x18\x04 \x01(\t\x12\x11\n\tnamespace\x18\x06 \x01(\t\x12\x31\n\x07\x66\x61ilure\x18\x07 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12=\n\x05\x63\x61use\x18\x08 \x01(\x0e\x32..temporal.api.enums.v1.WorkflowTaskFailedCause\x12\x17\n\x0fpoller_group_id\x18\t \x01(\tJ\x04\x08\x05\x10\x06"#\n!RespondQueryTaskCompletedResponse"n\n\x1bResetStickyTaskQueueRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12<\n\texecution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution"\x1e\n\x1cResetStickyTaskQueueResponse"\x9b\x02\n\x15ShutdownWorkerRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x19\n\x11sticky_task_queue\x18\x02 \x01(\t\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x0e\n\x06reason\x18\x04 \x01(\t\x12\x41\n\x10worker_heartbeat\x18\x05 \x01(\x0b\x32\'.temporal.api.worker.v1.WorkerHeartbeat\x12\x1b\n\x13worker_instance_key\x18\x06 \x01(\t\x12\x12\n\ntask_queue\x18\x07 \x01(\t\x12>\n\x10task_queue_types\x18\x08 \x03(\x0e\x32$.temporal.api.enums.v1.TaskQueueType"\x18\n\x16ShutdownWorkerResponse"\xe9\x01\n\x14QueryWorkflowRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12<\n\texecution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x33\n\x05query\x18\x03 \x01(\x0b\x32$.temporal.api.query.v1.WorkflowQuery\x12K\n\x16query_reject_condition\x18\x04 \x01(\x0e\x32+.temporal.api.enums.v1.QueryRejectCondition"\x8d\x01\n\x15QueryWorkflowResponse\x12\x36\n\x0cquery_result\x18\x01 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12<\n\x0equery_rejected\x18\x02 \x01(\x0b\x32$.temporal.api.query.v1.QueryRejected"s\n DescribeWorkflowExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12<\n\texecution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution"\x99\x05\n!DescribeWorkflowExecutionResponse\x12K\n\x10\x65xecution_config\x18\x01 \x01(\x0b\x32\x31.temporal.api.workflow.v1.WorkflowExecutionConfig\x12P\n\x17workflow_execution_info\x18\x02 \x01(\x0b\x32/.temporal.api.workflow.v1.WorkflowExecutionInfo\x12I\n\x12pending_activities\x18\x03 \x03(\x0b\x32-.temporal.api.workflow.v1.PendingActivityInfo\x12M\n\x10pending_children\x18\x04 \x03(\x0b\x32\x33.temporal.api.workflow.v1.PendingChildExecutionInfo\x12P\n\x15pending_workflow_task\x18\x05 \x01(\x0b\x32\x31.temporal.api.workflow.v1.PendingWorkflowTaskInfo\x12\x39\n\tcallbacks\x18\x06 \x03(\x0b\x32&.temporal.api.workflow.v1.CallbackInfo\x12U\n\x18pending_nexus_operations\x18\x07 \x03(\x0b\x32\x33.temporal.api.workflow.v1.PendingNexusOperationInfo\x12W\n\x16workflow_extended_info\x18\x08 \x01(\x0b\x32\x37.temporal.api.workflow.v1.WorkflowExecutionExtendedInfo"\x90\x04\n\x18\x44\x65scribeTaskQueueRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x38\n\ntask_queue\x18\x02 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12=\n\x0ftask_queue_type\x18\x03 \x01(\x0e\x32$.temporal.api.enums.v1.TaskQueueType\x12\x14\n\x0creport_stats\x18\x08 \x01(\x08\x12\x15\n\rreport_config\x18\x0b \x01(\x08\x12%\n\x19include_task_queue_status\x18\x04 \x01(\x08\x42\x02\x18\x01\x12\x42\n\x08\x61pi_mode\x18\x05 \x01(\x0e\x32,.temporal.api.enums.v1.DescribeTaskQueueModeB\x02\x18\x01\x12J\n\x08versions\x18\x06 \x01(\x0b\x32\x34.temporal.api.taskqueue.v1.TaskQueueVersionSelectionB\x02\x18\x01\x12\x42\n\x10task_queue_types\x18\x07 \x03(\x0e\x32$.temporal.api.enums.v1.TaskQueueTypeB\x02\x18\x01\x12\x1a\n\x0ereport_pollers\x18\t \x01(\x08\x42\x02\x18\x01\x12$\n\x18report_task_reachability\x18\n \x01(\x08\x42\x02\x18\x01"\xec\x07\n\x19\x44\x65scribeTaskQueueResponse\x12\x36\n\x07pollers\x18\x01 \x03(\x0b\x32%.temporal.api.taskqueue.v1.PollerInfo\x12\x38\n\x05stats\x18\x05 \x01(\x0b\x32).temporal.api.taskqueue.v1.TaskQueueStats\x12q\n\x15stats_by_priority_key\x18\x08 \x03(\x0b\x32R.temporal.api.workflowservice.v1.DescribeTaskQueueResponse.StatsByPriorityKeyEntry\x12K\n\x0fversioning_info\x18\x04 \x01(\x0b\x32\x32.temporal.api.taskqueue.v1.TaskQueueVersioningInfo\x12:\n\x06\x63onfig\x18\x06 \x01(\x0b\x32*.temporal.api.taskqueue.v1.TaskQueueConfig\x12k\n\x14\x65\x66\x66\x65\x63tive_rate_limit\x18\x07 \x01(\x0b\x32M.temporal.api.workflowservice.v1.DescribeTaskQueueResponse.EffectiveRateLimit\x12I\n\x11task_queue_status\x18\x02 \x01(\x0b\x32*.temporal.api.taskqueue.v1.TaskQueueStatusB\x02\x18\x01\x12g\n\rversions_info\x18\x03 \x03(\x0b\x32L.temporal.api.workflowservice.v1.DescribeTaskQueueResponse.VersionsInfoEntryB\x02\x18\x01\x1a\x64\n\x17StatsByPriorityKeyEntry\x12\x0b\n\x03key\x18\x01 \x01(\x05\x12\x38\n\x05value\x18\x02 \x01(\x0b\x32).temporal.api.taskqueue.v1.TaskQueueStats:\x02\x38\x01\x1at\n\x12\x45\x66\x66\x65\x63tiveRateLimit\x12\x1b\n\x13requests_per_second\x18\x01 \x01(\x02\x12\x41\n\x11rate_limit_source\x18\x02 \x01(\x0e\x32&.temporal.api.enums.v1.RateLimitSource\x1a\x64\n\x11VersionsInfoEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12>\n\x05value\x18\x02 \x01(\x0b\x32/.temporal.api.taskqueue.v1.TaskQueueVersionInfo:\x02\x38\x01"\x17\n\x15GetClusterInfoRequest"\xd1\x03\n\x16GetClusterInfoResponse\x12h\n\x11supported_clients\x18\x01 \x03(\x0b\x32M.temporal.api.workflowservice.v1.GetClusterInfoResponse.SupportedClientsEntry\x12\x16\n\x0eserver_version\x18\x02 \x01(\t\x12\x12\n\ncluster_id\x18\x03 \x01(\t\x12:\n\x0cversion_info\x18\x04 \x01(\x0b\x32$.temporal.api.version.v1.VersionInfo\x12\x14\n\x0c\x63luster_name\x18\x05 \x01(\t\x12\x1b\n\x13history_shard_count\x18\x06 \x01(\x05\x12\x19\n\x11persistence_store\x18\x07 \x01(\t\x12\x18\n\x10visibility_store\x18\x08 \x01(\t\x12 \n\x18initial_failover_version\x18\t \x01(\x03\x12"\n\x1a\x66\x61ilover_version_increment\x18\n \x01(\x03\x1a\x37\n\x15SupportedClientsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01"\x16\n\x14GetSystemInfoRequest"\x97\x04\n\x15GetSystemInfoResponse\x12\x16\n\x0eserver_version\x18\x01 \x01(\t\x12Y\n\x0c\x63\x61pabilities\x18\x02 \x01(\x0b\x32\x43.temporal.api.workflowservice.v1.GetSystemInfoResponse.Capabilities\x1a\x8a\x03\n\x0c\x43\x61pabilities\x12\x1f\n\x17signal_and_query_header\x18\x01 \x01(\x08\x12&\n\x1einternal_error_differentiation\x18\x02 \x01(\x08\x12*\n"activity_failure_include_heartbeat\x18\x03 \x01(\x08\x12\x1a\n\x12supports_schedules\x18\x04 \x01(\x08\x12"\n\x1a\x65ncoded_failure_attributes\x18\x05 \x01(\x08\x12!\n\x19\x62uild_id_based_versioning\x18\x06 \x01(\x08\x12\x13\n\x0bupsert_memo\x18\x07 \x01(\x08\x12\x1c\n\x14\x65\x61ger_workflow_start\x18\x08 \x01(\x08\x12\x14\n\x0csdk_metadata\x18\t \x01(\x08\x12\'\n\x1f\x63ount_group_by_execution_status\x18\n \x01(\x08\x12\r\n\x05nexus\x18\x0b \x01(\x08\x12!\n\x19server_scaled_deployments\x18\x0c \x01(\x08"m\n\x1eListTaskQueuePartitionsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x38\n\ntask_queue\x18\x02 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue"\xdf\x01\n\x1fListTaskQueuePartitionsResponse\x12]\n\x1e\x61\x63tivity_task_queue_partitions\x18\x01 \x03(\x0b\x32\x35.temporal.api.taskqueue.v1.TaskQueuePartitionMetadata\x12]\n\x1eworkflow_task_queue_partitions\x18\x02 \x03(\x0b\x32\x35.temporal.api.taskqueue.v1.TaskQueuePartitionMetadata"\xcc\x02\n\x15\x43reateScheduleRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bschedule_id\x18\x02 \x01(\t\x12\x34\n\x08schedule\x18\x03 \x01(\x0b\x32".temporal.api.schedule.v1.Schedule\x12>\n\rinitial_patch\x18\x04 \x01(\x0b\x32\'.temporal.api.schedule.v1.SchedulePatch\x12\x10\n\x08identity\x18\x05 \x01(\t\x12\x12\n\nrequest_id\x18\x06 \x01(\t\x12*\n\x04memo\x18\x07 \x01(\x0b\x32\x1c.temporal.api.common.v1.Memo\x12\x43\n\x11search_attributes\x18\x08 \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes"0\n\x16\x43reateScheduleResponse\x12\x16\n\x0e\x63onflict_token\x18\x01 \x01(\x0c"A\n\x17\x44\x65scribeScheduleRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bschedule_id\x18\x02 \x01(\t"\x8f\x02\n\x18\x44\x65scribeScheduleResponse\x12\x34\n\x08schedule\x18\x01 \x01(\x0b\x32".temporal.api.schedule.v1.Schedule\x12\x34\n\x04info\x18\x02 \x01(\x0b\x32&.temporal.api.schedule.v1.ScheduleInfo\x12*\n\x04memo\x18\x03 \x01(\x0b\x32\x1c.temporal.api.common.v1.Memo\x12\x43\n\x11search_attributes\x18\x04 \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes\x12\x16\n\x0e\x63onflict_token\x18\x05 \x01(\x0c"\xa4\x02\n\x15UpdateScheduleRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bschedule_id\x18\x02 \x01(\t\x12\x34\n\x08schedule\x18\x03 \x01(\x0b\x32".temporal.api.schedule.v1.Schedule\x12\x16\n\x0e\x63onflict_token\x18\x04 \x01(\x0c\x12\x10\n\x08identity\x18\x05 \x01(\t\x12\x12\n\nrequest_id\x18\x06 \x01(\t\x12\x43\n\x11search_attributes\x18\x07 \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes\x12*\n\x04memo\x18\x08 \x01(\x0b\x32\x1c.temporal.api.common.v1.Memo"\x18\n\x16UpdateScheduleResponse"\x9c\x01\n\x14PatchScheduleRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bschedule_id\x18\x02 \x01(\t\x12\x36\n\x05patch\x18\x03 \x01(\x0b\x32\'.temporal.api.schedule.v1.SchedulePatch\x12\x10\n\x08identity\x18\x04 \x01(\t\x12\x12\n\nrequest_id\x18\x05 \x01(\t"\x17\n\x15PatchScheduleResponse"\xa8\x01\n ListScheduleMatchingTimesRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bschedule_id\x18\x02 \x01(\t\x12.\n\nstart_time\x18\x03 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12,\n\x08\x65nd_time\x18\x04 \x01(\x0b\x32\x1a.google.protobuf.Timestamp"S\n!ListScheduleMatchingTimesResponse\x12.\n\nstart_time\x18\x01 \x03(\x0b\x32\x1a.google.protobuf.Timestamp"Q\n\x15\x44\x65leteScheduleRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bschedule_id\x18\x02 \x01(\t\x12\x10\n\x08identity\x18\x03 \x01(\t"\x18\n\x16\x44\x65leteScheduleResponse"l\n\x14ListSchedulesRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x19\n\x11maximum_page_size\x18\x02 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c\x12\r\n\x05query\x18\x04 \x01(\t"p\n\x15ListSchedulesResponse\x12>\n\tschedules\x18\x01 \x03(\x0b\x32+.temporal.api.schedule.v1.ScheduleListEntry\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c"9\n\x15\x43ountSchedulesRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\r\n\x05query\x18\x02 \x01(\t"\xdb\x01\n\x16\x43ountSchedulesResponse\x12\r\n\x05\x63ount\x18\x01 \x01(\x03\x12X\n\x06groups\x18\x02 \x03(\x0b\x32H.temporal.api.workflowservice.v1.CountSchedulesResponse.AggregationGroup\x1aX\n\x10\x41ggregationGroup\x12\x35\n\x0cgroup_values\x18\x01 \x03(\x0b\x32\x1f.temporal.api.common.v1.Payload\x12\r\n\x05\x63ount\x18\x02 \x01(\x03"\x86\x05\n\'UpdateWorkerBuildIdCompatibilityRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x12\n\ntask_queue\x18\x02 \x01(\t\x12-\n#add_new_build_id_in_new_default_set\x18\x03 \x01(\tH\x00\x12\x87\x01\n\x1b\x61\x64\x64_new_compatible_build_id\x18\x04 \x01(\x0b\x32`.temporal.api.workflowservice.v1.UpdateWorkerBuildIdCompatibilityRequest.AddNewCompatibleVersionH\x00\x12!\n\x17promote_set_by_build_id\x18\x05 \x01(\tH\x00\x12%\n\x1bpromote_build_id_within_set\x18\x06 \x01(\tH\x00\x12h\n\nmerge_sets\x18\x07 \x01(\x0b\x32R.temporal.api.workflowservice.v1.UpdateWorkerBuildIdCompatibilityRequest.MergeSetsH\x00\x1ao\n\x17\x41\x64\x64NewCompatibleVersion\x12\x14\n\x0cnew_build_id\x18\x01 \x01(\t\x12$\n\x1c\x65xisting_compatible_build_id\x18\x02 \x01(\t\x12\x18\n\x10make_set_default\x18\x03 \x01(\x08\x1aI\n\tMergeSets\x12\x1c\n\x14primary_set_build_id\x18\x01 \x01(\t\x12\x1e\n\x16secondary_set_build_id\x18\x02 \x01(\tB\x0b\n\toperation"@\n(UpdateWorkerBuildIdCompatibilityResponseJ\x04\x08\x01\x10\x02R\x0eversion_set_id"_\n$GetWorkerBuildIdCompatibilityRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x12\n\ntask_queue\x18\x02 \x01(\t\x12\x10\n\x08max_sets\x18\x03 \x01(\x05"t\n%GetWorkerBuildIdCompatibilityResponse\x12K\n\x12major_version_sets\x18\x01 \x03(\x0b\x32/.temporal.api.taskqueue.v1.CompatibleVersionSet"\xb5\r\n"UpdateWorkerVersioningRulesRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x12\n\ntask_queue\x18\x02 \x01(\t\x12\x16\n\x0e\x63onflict_token\x18\x03 \x01(\x0c\x12\x81\x01\n\x16insert_assignment_rule\x18\x04 \x01(\x0b\x32_.temporal.api.workflowservice.v1.UpdateWorkerVersioningRulesRequest.InsertBuildIdAssignmentRuleH\x00\x12\x83\x01\n\x17replace_assignment_rule\x18\x05 \x01(\x0b\x32`.temporal.api.workflowservice.v1.UpdateWorkerVersioningRulesRequest.ReplaceBuildIdAssignmentRuleH\x00\x12\x81\x01\n\x16\x64\x65lete_assignment_rule\x18\x06 \x01(\x0b\x32_.temporal.api.workflowservice.v1.UpdateWorkerVersioningRulesRequest.DeleteBuildIdAssignmentRuleH\x00\x12\x8c\x01\n\x1c\x61\x64\x64_compatible_redirect_rule\x18\x07 \x01(\x0b\x32\x64.temporal.api.workflowservice.v1.UpdateWorkerVersioningRulesRequest.AddCompatibleBuildIdRedirectRuleH\x00\x12\x94\x01\n replace_compatible_redirect_rule\x18\x08 \x01(\x0b\x32h.temporal.api.workflowservice.v1.UpdateWorkerVersioningRulesRequest.ReplaceCompatibleBuildIdRedirectRuleH\x00\x12\x92\x01\n\x1f\x64\x65lete_compatible_redirect_rule\x18\t \x01(\x0b\x32g.temporal.api.workflowservice.v1.UpdateWorkerVersioningRulesRequest.DeleteCompatibleBuildIdRedirectRuleH\x00\x12l\n\x0f\x63ommit_build_id\x18\n \x01(\x0b\x32Q.temporal.api.workflowservice.v1.UpdateWorkerVersioningRulesRequest.CommitBuildIdH\x00\x1aq\n\x1bInsertBuildIdAssignmentRule\x12\x12\n\nrule_index\x18\x01 \x01(\x05\x12>\n\x04rule\x18\x02 \x01(\x0b\x32\x30.temporal.api.taskqueue.v1.BuildIdAssignmentRule\x1a\x81\x01\n\x1cReplaceBuildIdAssignmentRule\x12\x12\n\nrule_index\x18\x01 \x01(\x05\x12>\n\x04rule\x18\x02 \x01(\x0b\x32\x30.temporal.api.taskqueue.v1.BuildIdAssignmentRule\x12\r\n\x05\x66orce\x18\x03 \x01(\x08\x1a@\n\x1b\x44\x65leteBuildIdAssignmentRule\x12\x12\n\nrule_index\x18\x01 \x01(\x05\x12\r\n\x05\x66orce\x18\x02 \x01(\x08\x1aj\n AddCompatibleBuildIdRedirectRule\x12\x46\n\x04rule\x18\x01 \x01(\x0b\x32\x38.temporal.api.taskqueue.v1.CompatibleBuildIdRedirectRule\x1an\n$ReplaceCompatibleBuildIdRedirectRule\x12\x46\n\x04rule\x18\x01 \x01(\x0b\x32\x38.temporal.api.taskqueue.v1.CompatibleBuildIdRedirectRule\x1a>\n#DeleteCompatibleBuildIdRedirectRule\x12\x17\n\x0fsource_build_id\x18\x01 \x01(\t\x1a\x37\n\rCommitBuildId\x12\x17\n\x0ftarget_build_id\x18\x01 \x01(\t\x12\r\n\x05\x66orce\x18\x02 \x01(\x08\x42\x0b\n\toperation"\xfc\x01\n#UpdateWorkerVersioningRulesResponse\x12U\n\x10\x61ssignment_rules\x18\x01 \x03(\x0b\x32;.temporal.api.taskqueue.v1.TimestampedBuildIdAssignmentRule\x12\x66\n\x19\x63ompatible_redirect_rules\x18\x02 \x03(\x0b\x32\x43.temporal.api.taskqueue.v1.TimestampedCompatibleBuildIdRedirectRule\x12\x16\n\x0e\x63onflict_token\x18\x03 \x01(\x0c"H\n\x1fGetWorkerVersioningRulesRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x12\n\ntask_queue\x18\x02 \x01(\t"\xf9\x01\n GetWorkerVersioningRulesResponse\x12U\n\x10\x61ssignment_rules\x18\x01 \x03(\x0b\x32;.temporal.api.taskqueue.v1.TimestampedBuildIdAssignmentRule\x12\x66\n\x19\x63ompatible_redirect_rules\x18\x02 \x03(\x0b\x32\x43.temporal.api.taskqueue.v1.TimestampedCompatibleBuildIdRedirectRule\x12\x16\n\x0e\x63onflict_token\x18\x03 \x01(\x0c"\x9c\x01\n GetWorkerTaskReachabilityRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x11\n\tbuild_ids\x18\x02 \x03(\t\x12\x13\n\x0btask_queues\x18\x03 \x03(\t\x12=\n\x0creachability\x18\x04 \x01(\x0e\x32\'.temporal.api.enums.v1.TaskReachability"r\n!GetWorkerTaskReachabilityResponse\x12M\n\x15\x62uild_id_reachability\x18\x01 \x03(\x0b\x32..temporal.api.taskqueue.v1.BuildIdReachability"\x85\x02\n\x1eUpdateWorkflowExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x45\n\x12workflow_execution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x1e\n\x16\x66irst_execution_run_id\x18\x03 \x01(\t\x12\x37\n\x0bwait_policy\x18\x04 \x01(\x0b\x32".temporal.api.update.v1.WaitPolicy\x12\x30\n\x07request\x18\x05 \x01(\x0b\x32\x1f.temporal.api.update.v1.Request"\x83\x02\n\x1fUpdateWorkflowExecutionResponse\x12\x35\n\nupdate_ref\x18\x01 \x01(\x0b\x32!.temporal.api.update.v1.UpdateRef\x12\x30\n\x07outcome\x18\x02 \x01(\x0b\x32\x1f.temporal.api.update.v1.Outcome\x12K\n\x05stage\x18\x03 \x01(\x0e\x32<.temporal.api.enums.v1.UpdateWorkflowExecutionLifecycleStage\x12*\n\x04link\x18\x04 \x01(\x0b\x32\x1c.temporal.api.common.v1.Link"\xf4\x07\n\x1aStartBatchOperationRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x18\n\x10visibility_query\x18\x02 \x01(\t\x12\x0e\n\x06job_id\x18\x03 \x01(\t\x12\x0e\n\x06reason\x18\x04 \x01(\t\x12=\n\nexecutions\x18\x05 \x03(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12!\n\x19max_operations_per_second\x18\x06 \x01(\x02\x12Q\n\x15termination_operation\x18\n \x01(\x0b\x32\x30.temporal.api.batch.v1.BatchOperationTerminationH\x00\x12G\n\x10signal_operation\x18\x0b \x01(\x0b\x32+.temporal.api.batch.v1.BatchOperationSignalH\x00\x12S\n\x16\x63\x61ncellation_operation\x18\x0c \x01(\x0b\x32\x31.temporal.api.batch.v1.BatchOperationCancellationH\x00\x12K\n\x12\x64\x65letion_operation\x18\r \x01(\x0b\x32-.temporal.api.batch.v1.BatchOperationDeletionH\x00\x12\x45\n\x0freset_operation\x18\x0e \x01(\x0b\x32*.temporal.api.batch.v1.BatchOperationResetH\x00\x12p\n!update_workflow_options_operation\x18\x0f \x01(\x0b\x32\x43.temporal.api.batch.v1.BatchOperationUpdateWorkflowExecutionOptionsH\x00\x12^\n\x1cunpause_activities_operation\x18\x10 \x01(\x0b\x32\x36.temporal.api.batch.v1.BatchOperationUnpauseActivitiesH\x00\x12Z\n\x1areset_activities_operation\x18\x11 \x01(\x0b\x32\x34.temporal.api.batch.v1.BatchOperationResetActivitiesH\x00\x12g\n!update_activity_options_operation\x18\x12 \x01(\x0b\x32:.temporal.api.batch.v1.BatchOperationUpdateActivityOptionsH\x00\x42\x0b\n\toperation"\x1d\n\x1bStartBatchOperationResponse"`\n\x19StopBatchOperationRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x0e\n\x06job_id\x18\x02 \x01(\t\x12\x0e\n\x06reason\x18\x03 \x01(\t\x12\x10\n\x08identity\x18\x04 \x01(\t"\x1c\n\x1aStopBatchOperationResponse"B\n\x1d\x44\x65scribeBatchOperationRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x0e\n\x06job_id\x18\x02 \x01(\t"\x92\x03\n\x1e\x44\x65scribeBatchOperationResponse\x12\x41\n\x0eoperation_type\x18\x01 \x01(\x0e\x32).temporal.api.enums.v1.BatchOperationType\x12\x0e\n\x06job_id\x18\x02 \x01(\t\x12\x39\n\x05state\x18\x03 \x01(\x0e\x32*.temporal.api.enums.v1.BatchOperationState\x12.\n\nstart_time\x18\x04 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12.\n\nclose_time\x18\x05 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x1d\n\x15total_operation_count\x18\x06 \x01(\x03\x12 \n\x18\x63omplete_operation_count\x18\x07 \x01(\x03\x12\x1f\n\x17\x66\x61ilure_operation_count\x18\x08 \x01(\x03\x12\x10\n\x08identity\x18\t \x01(\t\x12\x0e\n\x06reason\x18\n \x01(\t"[\n\x1aListBatchOperationsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x11\n\tpage_size\x18\x02 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c"y\n\x1bListBatchOperationsResponse\x12\x41\n\x0eoperation_info\x18\x01 \x03(\x0b\x32).temporal.api.batch.v1.BatchOperationInfo\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c"\xb9\x01\n"PollWorkflowExecutionUpdateRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x35\n\nupdate_ref\x18\x02 \x01(\x0b\x32!.temporal.api.update.v1.UpdateRef\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x37\n\x0bwait_policy\x18\x04 \x01(\x0b\x32".temporal.api.update.v1.WaitPolicy"\xdb\x01\n#PollWorkflowExecutionUpdateResponse\x12\x30\n\x07outcome\x18\x01 \x01(\x0b\x32\x1f.temporal.api.update.v1.Outcome\x12K\n\x05stage\x18\x02 \x01(\x0e\x32<.temporal.api.enums.v1.UpdateWorkflowExecutionLifecycleStage\x12\x35\n\nupdate_ref\x18\x03 \x01(\x0b\x32!.temporal.api.update.v1.UpdateRef"\xa0\x03\n\x19PollNexusTaskQueueRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x38\n\ntask_queue\x18\x03 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12\x17\n\x0fpoller_group_id\x18\t \x01(\t\x12\x10\n\x08identity\x18\x02 \x01(\t\x12\x1b\n\x13worker_instance_key\x18\x08 \x01(\t\x12Z\n\x1bworker_version_capabilities\x18\x04 \x01(\x0b\x32\x31.temporal.api.common.v1.WorkerVersionCapabilitiesB\x02\x18\x01\x12O\n\x12\x64\x65ployment_options\x18\x06 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentOptions\x12\x41\n\x10worker_heartbeat\x18\x07 \x03(\x0b\x32\'.temporal.api.worker.v1.WorkerHeartbeat"\x95\x02\n\x1aPollNexusTaskQueueResponse\x12\x12\n\ntask_token\x18\x01 \x01(\x0c\x12/\n\x07request\x18\x02 \x01(\x0b\x32\x1e.temporal.api.nexus.v1.Request\x12Q\n\x17poller_scaling_decision\x18\x03 \x01(\x0b\x32\x30.temporal.api.taskqueue.v1.PollerScalingDecision\x12\x17\n\x0fpoller_group_id\x18\x04 \x01(\t\x12\x46\n\x12poller_group_infos\x18\x05 \x03(\x0b\x32*.temporal.api.taskqueue.v1.PollerGroupInfo"\xa7\x01\n RespondNexusTaskCompletedRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x10\n\x08identity\x18\x02 \x01(\t\x12\x12\n\ntask_token\x18\x03 \x01(\x0c\x12\x31\n\x08response\x18\x04 \x01(\x0b\x32\x1f.temporal.api.nexus.v1.Response\x12\x17\n\x0fpoller_group_id\x18\x05 \x01(\t"#\n!RespondNexusTaskCompletedResponse"\xdc\x01\n\x1dRespondNexusTaskFailedRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x10\n\x08identity\x18\x02 \x01(\t\x12\x12\n\ntask_token\x18\x03 \x01(\x0c\x12\x36\n\x05\x65rror\x18\x04 \x01(\x0b\x32#.temporal.api.nexus.v1.HandlerErrorB\x02\x18\x01\x12\x31\n\x07\x66\x61ilure\x18\x05 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12\x17\n\x0fpoller_group_id\x18\x06 \x01(\t" \n\x1eRespondNexusTaskFailedResponse"\xf4\x02\n\x1c\x45xecuteMultiOperationRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12[\n\noperations\x18\x02 \x03(\x0b\x32G.temporal.api.workflowservice.v1.ExecuteMultiOperationRequest.Operation\x12\x13\n\x0bresource_id\x18\x03 \x01(\t\x1a\xce\x01\n\tOperation\x12X\n\x0estart_workflow\x18\x01 \x01(\x0b\x32>.temporal.api.workflowservice.v1.StartWorkflowExecutionRequestH\x00\x12Z\n\x0fupdate_workflow\x18\x02 \x01(\x0b\x32?.temporal.api.workflowservice.v1.UpdateWorkflowExecutionRequestH\x00\x42\x0b\n\toperation"\xcc\x02\n\x1d\x45xecuteMultiOperationResponse\x12Z\n\tresponses\x18\x01 \x03(\x0b\x32G.temporal.api.workflowservice.v1.ExecuteMultiOperationResponse.Response\x1a\xce\x01\n\x08Response\x12Y\n\x0estart_workflow\x18\x01 \x01(\x0b\x32?.temporal.api.workflowservice.v1.StartWorkflowExecutionResponseH\x00\x12[\n\x0fupdate_workflow\x18\x02 \x01(\x0b\x32@.temporal.api.workflowservice.v1.UpdateWorkflowExecutionResponseH\x00\x42\n\n\x08response"\xd0\x02\n\x1cUpdateActivityOptionsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12<\n\texecution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x43\n\x10\x61\x63tivity_options\x18\x04 \x01(\x0b\x32).temporal.api.activity.v1.ActivityOptions\x12/\n\x0bupdate_mask\x18\x05 \x01(\x0b\x32\x1a.google.protobuf.FieldMask\x12\x0c\n\x02id\x18\x06 \x01(\tH\x00\x12\x0e\n\x04type\x18\x07 \x01(\tH\x00\x12\x13\n\tmatch_all\x18\t \x01(\x08H\x00\x12\x18\n\x10restore_original\x18\x08 \x01(\x08\x42\n\n\x08\x61\x63tivity"\xab\x02\n%UpdateActivityExecutionOptionsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12\x13\n\x0b\x61\x63tivity_id\x18\x03 \x01(\t\x12\x0e\n\x06run_id\x18\x04 \x01(\t\x12\x10\n\x08identity\x18\x05 \x01(\t\x12\x43\n\x10\x61\x63tivity_options\x18\x06 \x01(\x0b\x32).temporal.api.activity.v1.ActivityOptions\x12/\n\x0bupdate_mask\x18\x07 \x01(\x0b\x32\x1a.google.protobuf.FieldMask\x12\x18\n\x10restore_original\x18\x08 \x01(\x08\x12\x13\n\x0bresource_id\x18\t \x01(\t"d\n\x1dUpdateActivityOptionsResponse\x12\x43\n\x10\x61\x63tivity_options\x18\x01 \x01(\x0b\x32).temporal.api.activity.v1.ActivityOptions"m\n&UpdateActivityExecutionOptionsResponse\x12\x43\n\x10\x61\x63tivity_options\x18\x01 \x01(\x0b\x32).temporal.api.activity.v1.ActivityOptions"\xc7\x01\n\x14PauseActivityRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12<\n\texecution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x0c\n\x02id\x18\x04 \x01(\tH\x00\x12\x0e\n\x04type\x18\x05 \x01(\tH\x00\x12\x0e\n\x06reason\x18\x06 \x01(\t\x12\x12\n\nrequest_id\x18\x07 \x01(\tB\n\n\x08\x61\x63tivity"\xb7\x01\n\x1dPauseActivityExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12\x13\n\x0b\x61\x63tivity_id\x18\x03 \x01(\t\x12\x0e\n\x06run_id\x18\x04 \x01(\t\x12\x10\n\x08identity\x18\x05 \x01(\t\x12\x0e\n\x06reason\x18\x06 \x01(\t\x12\x13\n\x0bresource_id\x18\x07 \x01(\t\x12\x12\n\nrequest_id\x18\x08 \x01(\t"\x17\n\x15PauseActivityResponse" \n\x1ePauseActivityExecutionResponse"\x98\x02\n\x16UnpauseActivityRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12<\n\texecution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x0c\n\x02id\x18\x04 \x01(\tH\x00\x12\x0e\n\x04type\x18\x05 \x01(\tH\x00\x12\x15\n\x0bunpause_all\x18\x06 \x01(\x08H\x00\x12\x16\n\x0ereset_attempts\x18\x07 \x01(\x08\x12\x17\n\x0freset_heartbeat\x18\x08 \x01(\x08\x12)\n\x06jitter\x18\t \x01(\x0b\x32\x19.google.protobuf.DurationB\n\n\x08\x61\x63tivity"\x81\x02\n\x1fUnpauseActivityExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12\x13\n\x0b\x61\x63tivity_id\x18\x03 \x01(\t\x12\x0e\n\x06run_id\x18\x04 \x01(\t\x12\x10\n\x08identity\x18\x05 \x01(\t\x12\x16\n\x0ereset_attempts\x18\x06 \x01(\x08\x12\x17\n\x0freset_heartbeat\x18\x07 \x01(\x08\x12\x0e\n\x06reason\x18\x08 \x01(\t\x12)\n\x06jitter\x18\t \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x13\n\x0bresource_id\x18\n \x01(\t"\x19\n\x17UnpauseActivityResponse""\n UnpauseActivityExecutionResponse"\xb3\x02\n\x14ResetActivityRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12<\n\texecution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x0c\n\x02id\x18\x04 \x01(\tH\x00\x12\x0e\n\x04type\x18\x05 \x01(\tH\x00\x12\x13\n\tmatch_all\x18\n \x01(\x08H\x00\x12\x17\n\x0freset_heartbeat\x18\x06 \x01(\x08\x12\x13\n\x0bkeep_paused\x18\x07 \x01(\x08\x12)\n\x06jitter\x18\x08 \x01(\x0b\x32\x19.google.protobuf.Duration\x12 \n\x18restore_original_options\x18\t \x01(\x08\x42\n\n\x08\x61\x63tivity"\x8e\x02\n\x1dResetActivityExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12\x13\n\x0b\x61\x63tivity_id\x18\x03 \x01(\t\x12\x0e\n\x06run_id\x18\x04 \x01(\t\x12\x10\n\x08identity\x18\x05 \x01(\t\x12\x17\n\x0freset_heartbeat\x18\x06 \x01(\x08\x12\x13\n\x0bkeep_paused\x18\x07 \x01(\x08\x12)\n\x06jitter\x18\x08 \x01(\x0b\x32\x19.google.protobuf.Duration\x12 \n\x18restore_original_options\x18\t \x01(\x08\x12\x13\n\x0bresource_id\x18\n \x01(\t"\x17\n\x15ResetActivityResponse" \n\x1eResetActivityExecutionResponse"\x9c\x02\n%UpdateWorkflowExecutionOptionsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x45\n\x12workflow_execution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12V\n\x1aworkflow_execution_options\x18\x03 \x01(\x0b\x32\x32.temporal.api.workflow.v1.WorkflowExecutionOptions\x12/\n\x0bupdate_mask\x18\x04 \x01(\x0b\x32\x1a.google.protobuf.FieldMask\x12\x10\n\x08identity\x18\x05 \x01(\t"\xb1\x01\n&UpdateWorkflowExecutionOptionsResponse\x12V\n\x1aworkflow_execution_options\x18\x01 \x01(\x0b\x32\x32.temporal.api.workflow.v1.WorkflowExecutionOptions\x12/\n\x0bupdate_time\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.Timestamp"j\n\x19\x44\x65scribeDeploymentRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12:\n\ndeployment\x18\x02 \x01(\x0b\x32&.temporal.api.deployment.v1.Deployment"a\n\x1a\x44\x65scribeDeploymentResponse\x12\x43\n\x0f\x64\x65ployment_info\x18\x01 \x01(\x0b\x32*.temporal.api.deployment.v1.DeploymentInfo"\xc2\x01\n&DescribeWorkerDeploymentVersionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x07version\x18\x02 \x01(\tB\x02\x18\x01\x12O\n\x12\x64\x65ployment_version\x18\x03 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersion\x12\x1f\n\x17report_task_queue_stats\x18\x04 \x01(\x08"\x8c\x05\n\'DescribeWorkerDeploymentVersionResponse\x12_\n\x1eworker_deployment_version_info\x18\x01 \x01(\x0b\x32\x37.temporal.api.deployment.v1.WorkerDeploymentVersionInfo\x12v\n\x13version_task_queues\x18\x02 \x03(\x0b\x32Y.temporal.api.workflowservice.v1.DescribeWorkerDeploymentVersionResponse.VersionTaskQueue\x1a\x87\x03\n\x10VersionTaskQueue\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x32\n\x04type\x18\x02 \x01(\x0e\x32$.temporal.api.enums.v1.TaskQueueType\x12\x38\n\x05stats\x18\x03 \x01(\x0b\x32).temporal.api.taskqueue.v1.TaskQueueStats\x12\x90\x01\n\x15stats_by_priority_key\x18\x04 \x03(\x0b\x32q.temporal.api.workflowservice.v1.DescribeWorkerDeploymentVersionResponse.VersionTaskQueue.StatsByPriorityKeyEntry\x1a\x64\n\x17StatsByPriorityKeyEntry\x12\x0b\n\x03key\x18\x01 \x01(\x05\x12\x38\n\x05value\x18\x02 \x01(\x0b\x32).temporal.api.taskqueue.v1.TaskQueueStats:\x02\x38\x01"M\n\x1f\x44\x65scribeWorkerDeploymentRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x17\n\x0f\x64\x65ployment_name\x18\x02 \x01(\t"\x8c\x01\n DescribeWorkerDeploymentResponse\x12\x16\n\x0e\x63onflict_token\x18\x01 \x01(\x0c\x12P\n\x16worker_deployment_info\x18\x02 \x01(\x0b\x32\x30.temporal.api.deployment.v1.WorkerDeploymentInfo"l\n\x16ListDeploymentsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x11\n\tpage_size\x18\x02 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c\x12\x13\n\x0bseries_name\x18\x04 \x01(\t"w\n\x17ListDeploymentsResponse\x12\x17\n\x0fnext_page_token\x18\x01 \x01(\x0c\x12\x43\n\x0b\x64\x65ployments\x18\x02 \x03(\x0b\x32..temporal.api.deployment.v1.DeploymentListInfo"\xcd\x01\n\x1bSetCurrentDeploymentRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12:\n\ndeployment\x18\x02 \x01(\x0b\x32&.temporal.api.deployment.v1.Deployment\x12\x10\n\x08identity\x18\x03 \x01(\t\x12M\n\x0fupdate_metadata\x18\x04 \x01(\x0b\x32\x34.temporal.api.deployment.v1.UpdateDeploymentMetadata"\xb9\x01\n\x1cSetCurrentDeploymentResponse\x12K\n\x17\x63urrent_deployment_info\x18\x01 \x01(\x0b\x32*.temporal.api.deployment.v1.DeploymentInfo\x12L\n\x18previous_deployment_info\x18\x02 \x01(\x0b\x32*.temporal.api.deployment.v1.DeploymentInfo"\xe5\x01\n(SetWorkerDeploymentCurrentVersionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x17\n\x0f\x64\x65ployment_name\x18\x02 \x01(\t\x12\x13\n\x07version\x18\x03 \x01(\tB\x02\x18\x01\x12\x10\n\x08\x62uild_id\x18\x07 \x01(\t\x12\x16\n\x0e\x63onflict_token\x18\x04 \x01(\x0c\x12\x10\n\x08identity\x18\x05 \x01(\t\x12"\n\x1aignore_missing_task_queues\x18\x06 \x01(\x08\x12\x18\n\x10\x61llow_no_pollers\x18\t \x01(\x08"\xbf\x01\n)SetWorkerDeploymentCurrentVersionResponse\x12\x16\n\x0e\x63onflict_token\x18\x01 \x01(\x0c\x12\x1c\n\x10previous_version\x18\x02 \x01(\tB\x02\x18\x01\x12\\\n\x1bprevious_deployment_version\x18\x03 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersionB\x02\x18\x01"\xf9\x01\n(SetWorkerDeploymentRampingVersionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x17\n\x0f\x64\x65ployment_name\x18\x02 \x01(\t\x12\x13\n\x07version\x18\x03 \x01(\tB\x02\x18\x01\x12\x10\n\x08\x62uild_id\x18\x08 \x01(\t\x12\x12\n\npercentage\x18\x04 \x01(\x02\x12\x16\n\x0e\x63onflict_token\x18\x05 \x01(\x0c\x12\x10\n\x08identity\x18\x06 \x01(\t\x12"\n\x1aignore_missing_task_queues\x18\x07 \x01(\x08\x12\x18\n\x10\x61llow_no_pollers\x18\n \x01(\x08"\xe0\x01\n)SetWorkerDeploymentRampingVersionResponse\x12\x16\n\x0e\x63onflict_token\x18\x01 \x01(\x0c\x12\x1c\n\x10previous_version\x18\x02 \x01(\tB\x02\x18\x01\x12\\\n\x1bprevious_deployment_version\x18\x04 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersionB\x02\x18\x01\x12\x1f\n\x13previous_percentage\x18\x03 \x01(\x02\x42\x02\x18\x01"q\n\x1d\x43reateWorkerDeploymentRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x17\n\x0f\x64\x65ployment_name\x18\x02 \x01(\t\x12\x10\n\x08identity\x18\x04 \x01(\t\x12\x12\n\nrequest_id\x18\x05 \x01(\t"8\n\x1e\x43reateWorkerDeploymentResponse\x12\x16\n\x0e\x63onflict_token\x18\x01 \x01(\x0c"]\n\x1cListWorkerDeploymentsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x11\n\tpage_size\x18\x02 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c"\x9f\x05\n\x1dListWorkerDeploymentsResponse\x12\x17\n\x0fnext_page_token\x18\x01 \x01(\x0c\x12r\n\x12worker_deployments\x18\x02 \x03(\x0b\x32V.temporal.api.workflowservice.v1.ListWorkerDeploymentsResponse.WorkerDeploymentSummary\x1a\xf0\x03\n\x17WorkerDeploymentSummary\x12\x0c\n\x04name\x18\x01 \x01(\t\x12/\n\x0b\x63reate_time\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x41\n\x0erouting_config\x18\x03 \x01(\x0b\x32).temporal.api.deployment.v1.RoutingConfig\x12o\n\x16latest_version_summary\x18\x04 \x01(\x0b\x32O.temporal.api.deployment.v1.WorkerDeploymentInfo.WorkerDeploymentVersionSummary\x12p\n\x17\x63urrent_version_summary\x18\x05 \x01(\x0b\x32O.temporal.api.deployment.v1.WorkerDeploymentInfo.WorkerDeploymentVersionSummary\x12p\n\x17ramping_version_summary\x18\x06 \x01(\x0b\x32O.temporal.api.deployment.v1.WorkerDeploymentInfo.WorkerDeploymentVersionSummary"\xf0\x01\n$CreateWorkerDeploymentVersionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12O\n\x12\x64\x65ployment_version\x18\x02 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersion\x12>\n\x0e\x63ompute_config\x18\x04 \x01(\x0b\x32&.temporal.api.compute.v1.ComputeConfig\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x12\n\nrequest_id\x18\x05 \x01(\t"\'\n%CreateWorkerDeploymentVersionResponse"\xc8\x01\n$DeleteWorkerDeploymentVersionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x07version\x18\x02 \x01(\tB\x02\x18\x01\x12O\n\x12\x64\x65ployment_version\x18\x05 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersion\x12\x15\n\rskip_drainage\x18\x03 \x01(\x08\x12\x10\n\x08identity\x18\x04 \x01(\t"\'\n%DeleteWorkerDeploymentVersionResponse"]\n\x1d\x44\x65leteWorkerDeploymentRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x17\n\x0f\x64\x65ployment_name\x18\x02 \x01(\t\x12\x10\n\x08identity\x18\x03 \x01(\t" \n\x1e\x44\x65leteWorkerDeploymentResponse"\x84\x04\n1UpdateWorkerDeploymentVersionComputeConfigRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12O\n\x12\x64\x65ployment_version\x18\x02 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersion\x12\x99\x01\n\x1d\x63ompute_config_scaling_groups\x18\x06 \x03(\x0b\x32r.temporal.api.workflowservice.v1.UpdateWorkerDeploymentVersionComputeConfigRequest.ComputeConfigScalingGroupsEntry\x12,\n$remove_compute_config_scaling_groups\x18\x07 \x03(\t\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x12\n\nrequest_id\x18\x04 \x01(\t\x1a{\n\x1f\x43omputeConfigScalingGroupsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12G\n\x05value\x18\x02 \x01(\x0b\x32\x38.temporal.api.compute.v1.ComputeConfigScalingGroupUpdate:\x02\x38\x01"4\n2UpdateWorkerDeploymentVersionComputeConfigResponse"\xf4\x03\n3ValidateWorkerDeploymentVersionComputeConfigRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12O\n\x12\x64\x65ployment_version\x18\x02 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersion\x12\x9b\x01\n\x1d\x63ompute_config_scaling_groups\x18\x06 \x03(\x0b\x32t.temporal.api.workflowservice.v1.ValidateWorkerDeploymentVersionComputeConfigRequest.ComputeConfigScalingGroupsEntry\x12,\n$remove_compute_config_scaling_groups\x18\x07 \x03(\t\x12\x10\n\x08identity\x18\x03 \x01(\t\x1a{\n\x1f\x43omputeConfigScalingGroupsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12G\n\x05value\x18\x02 \x01(\x0b\x32\x38.temporal.api.compute.v1.ComputeConfigScalingGroupUpdate:\x02\x38\x01"6\n4ValidateWorkerDeploymentVersionComputeConfigResponse"\xa2\x03\n,UpdateWorkerDeploymentVersionMetadataRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x07version\x18\x02 \x01(\tB\x02\x18\x01\x12O\n\x12\x64\x65ployment_version\x18\x05 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersion\x12x\n\x0eupsert_entries\x18\x03 \x03(\x0b\x32`.temporal.api.workflowservice.v1.UpdateWorkerDeploymentVersionMetadataRequest.UpsertEntriesEntry\x12\x16\n\x0eremove_entries\x18\x04 \x03(\t\x12\x10\n\x08identity\x18\x06 \x01(\t\x1aU\n\x12UpsertEntriesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12.\n\x05value\x18\x02 \x01(\x0b\x32\x1f.temporal.api.common.v1.Payload:\x02\x38\x01"n\n-UpdateWorkerDeploymentVersionMetadataResponse\x12=\n\x08metadata\x18\x01 \x01(\x0b\x32+.temporal.api.deployment.v1.VersionMetadata"\xbd\x01\n!SetWorkerDeploymentManagerRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x17\n\x0f\x64\x65ployment_name\x18\x02 \x01(\t\x12\x1a\n\x10manager_identity\x18\x03 \x01(\tH\x00\x12\x0e\n\x04self\x18\x04 \x01(\x08H\x00\x12\x16\n\x0e\x63onflict_token\x18\x05 \x01(\x0c\x12\x10\n\x08identity\x18\x06 \x01(\tB\x16\n\x14new_manager_identity"c\n"SetWorkerDeploymentManagerResponse\x12\x16\n\x0e\x63onflict_token\x18\x01 \x01(\x0c\x12%\n\x19previous_manager_identity\x18\x02 \x01(\tB\x02\x18\x01"E\n\x1bGetCurrentDeploymentRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bseries_name\x18\x02 \x01(\t"k\n\x1cGetCurrentDeploymentResponse\x12K\n\x17\x63urrent_deployment_info\x18\x01 \x01(\x0b\x32*.temporal.api.deployment.v1.DeploymentInfo"q\n GetDeploymentReachabilityRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12:\n\ndeployment\x18\x02 \x01(\x0b\x32&.temporal.api.deployment.v1.Deployment"\xe3\x01\n!GetDeploymentReachabilityResponse\x12\x43\n\x0f\x64\x65ployment_info\x18\x01 \x01(\x0b\x32*.temporal.api.deployment.v1.DeploymentInfo\x12\x43\n\x0creachability\x18\x02 \x01(\x0e\x32-.temporal.api.enums.v1.DeploymentReachability\x12\x34\n\x10last_update_time\x18\x03 \x01(\x0b\x32\x1a.google.protobuf.Timestamp"\xb4\x01\n\x19\x43reateWorkflowRuleRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x35\n\x04spec\x18\x02 \x01(\x0b\x32\'.temporal.api.rules.v1.WorkflowRuleSpec\x12\x12\n\nforce_scan\x18\x03 \x01(\x08\x12\x12\n\nrequest_id\x18\x04 \x01(\t\x12\x10\n\x08identity\x18\x05 \x01(\t\x12\x13\n\x0b\x64\x65scription\x18\x06 \x01(\t"_\n\x1a\x43reateWorkflowRuleResponse\x12\x31\n\x04rule\x18\x01 \x01(\x0b\x32#.temporal.api.rules.v1.WorkflowRule\x12\x0e\n\x06job_id\x18\x02 \x01(\t"A\n\x1b\x44\x65scribeWorkflowRuleRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x0f\n\x07rule_id\x18\x02 \x01(\t"Q\n\x1c\x44\x65scribeWorkflowRuleResponse\x12\x31\n\x04rule\x18\x01 \x01(\x0b\x32#.temporal.api.rules.v1.WorkflowRule"?\n\x19\x44\x65leteWorkflowRuleRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x0f\n\x07rule_id\x18\x02 \x01(\t"\x1c\n\x1a\x44\x65leteWorkflowRuleResponse"F\n\x18ListWorkflowRulesRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c"h\n\x19ListWorkflowRulesResponse\x12\x32\n\x05rules\x18\x01 \x03(\x0b\x32#.temporal.api.rules.v1.WorkflowRule\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c"\xce\x01\n\x1aTriggerWorkflowRuleRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12<\n\texecution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x0c\n\x02id\x18\x04 \x01(\tH\x00\x12\x37\n\x04spec\x18\x05 \x01(\x0b\x32\'.temporal.api.rules.v1.WorkflowRuleSpecH\x00\x12\x10\n\x08identity\x18\x03 \x01(\tB\x06\n\x04rule".\n\x1bTriggerWorkflowRuleResponse\x12\x0f\n\x07\x61pplied\x18\x01 \x01(\x08"\x9b\x01\n\x1cRecordWorkerHeartbeatRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x10\n\x08identity\x18\x02 \x01(\t\x12\x41\n\x10worker_heartbeat\x18\x03 \x03(\x0b\x32\'.temporal.api.worker.v1.WorkerHeartbeat\x12\x13\n\x0bresource_id\x18\x04 \x01(\t"\x1f\n\x1dRecordWorkerHeartbeatResponse"\x82\x01\n\x12ListWorkersRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x11\n\tpage_size\x18\x02 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c\x12\r\n\x05query\x18\x04 \x01(\t\x12\x1e\n\x16include_system_workers\x18\x05 \x01(\x08"\xa5\x01\n\x13ListWorkersResponse\x12<\n\x0cworkers_info\x18\x01 \x03(\x0b\x32".temporal.api.worker.v1.WorkerInfoB\x02\x18\x01\x12\x37\n\x07workers\x18\x03 \x03(\x0b\x32&.temporal.api.worker.v1.WorkerListInfo\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c"\xd5\x05\n\x1cUpdateTaskQueueConfigRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x10\n\x08identity\x18\x02 \x01(\t\x12\x12\n\ntask_queue\x18\x03 \x01(\t\x12=\n\x0ftask_queue_type\x18\x04 \x01(\x0e\x32$.temporal.api.enums.v1.TaskQueueType\x12n\n\x17update_queue_rate_limit\x18\x05 \x01(\x0b\x32M.temporal.api.workflowservice.v1.UpdateTaskQueueConfigRequest.RateLimitUpdate\x12}\n&update_fairness_key_rate_limit_default\x18\x06 \x01(\x0b\x32M.temporal.api.workflowservice.v1.UpdateTaskQueueConfigRequest.RateLimitUpdate\x12\x84\x01\n\x1dset_fairness_weight_overrides\x18\x07 \x03(\x0b\x32].temporal.api.workflowservice.v1.UpdateTaskQueueConfigRequest.SetFairnessWeightOverridesEntry\x12\'\n\x1funset_fairness_weight_overrides\x18\x08 \x03(\t\x1a[\n\x0fRateLimitUpdate\x12\x38\n\nrate_limit\x18\x01 \x01(\x0b\x32$.temporal.api.taskqueue.v1.RateLimit\x12\x0e\n\x06reason\x18\x02 \x01(\t\x1a\x41\n\x1fSetFairnessWeightOverridesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\x02:\x02\x38\x01"[\n\x1dUpdateTaskQueueConfigResponse\x12:\n\x06\x63onfig\x18\x01 \x01(\x0b\x32*.temporal.api.taskqueue.v1.TaskQueueConfig"\x9e\x01\n\x18\x46\x65tchWorkerConfigRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x10\n\x08identity\x18\x02 \x01(\t\x12\x0e\n\x06reason\x18\x03 \x01(\t\x12\x38\n\x08selector\x18\x06 \x01(\x0b\x32&.temporal.api.common.v1.WorkerSelector\x12\x13\n\x0bresource_id\x18\x07 \x01(\t"U\n\x19\x46\x65tchWorkerConfigResponse\x12\x38\n\rworker_config\x18\x01 \x01(\x0b\x32!.temporal.api.sdk.v1.WorkerConfig"\x8a\x02\n\x19UpdateWorkerConfigRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x10\n\x08identity\x18\x02 \x01(\t\x12\x0e\n\x06reason\x18\x03 \x01(\t\x12\x38\n\rworker_config\x18\x04 \x01(\x0b\x32!.temporal.api.sdk.v1.WorkerConfig\x12/\n\x0bupdate_mask\x18\x05 \x01(\x0b\x32\x1a.google.protobuf.FieldMask\x12\x38\n\x08selector\x18\x06 \x01(\x0b\x32&.temporal.api.common.v1.WorkerSelector\x12\x13\n\x0bresource_id\x18\x07 \x01(\t"d\n\x1aUpdateWorkerConfigResponse\x12:\n\rworker_config\x18\x01 \x01(\x0b\x32!.temporal.api.sdk.v1.WorkerConfigH\x00\x42\n\n\x08response"G\n\x15\x44\x65scribeWorkerRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x1b\n\x13worker_instance_key\x18\x02 \x01(\t"Q\n\x16\x44\x65scribeWorkerResponse\x12\x37\n\x0bworker_info\x18\x01 \x01(\x0b\x32".temporal.api.worker.v1.WorkerInfo"W\n\x13\x43ountWorkersRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\r\n\x05query\x18\x02 \x01(\t\x12\x1e\n\x16include_system_workers\x18\x03 \x01(\x08"%\n\x14\x43ountWorkersResponse\x12\r\n\x05\x63ount\x18\x01 \x01(\x03"\x8d\x01\n\x1dPauseWorkflowExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x12\x10\n\x08identity\x18\x04 \x01(\t\x12\x0e\n\x06reason\x18\x05 \x01(\t\x12\x12\n\nrequest_id\x18\x06 \x01(\t" \n\x1ePauseWorkflowExecutionResponse"\x8f\x01\n\x1fUnpauseWorkflowExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x12\x10\n\x08identity\x18\x04 \x01(\t\x12\x0e\n\x06reason\x18\x05 \x01(\t\x12\x12\n\nrequest_id\x18\x06 \x01(\t""\n UnpauseWorkflowExecutionResponse"\x99\t\n\x1dStartActivityExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x10\n\x08identity\x18\x02 \x01(\t\x12\x12\n\nrequest_id\x18\x03 \x01(\t\x12\x13\n\x0b\x61\x63tivity_id\x18\x04 \x01(\t\x12;\n\ractivity_type\x18\x05 \x01(\x0b\x32$.temporal.api.common.v1.ActivityType\x12\x38\n\ntask_queue\x18\x06 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12<\n\x19schedule_to_close_timeout\x18\x07 \x01(\x0b\x32\x19.google.protobuf.Duration\x12<\n\x19schedule_to_start_timeout\x18\x08 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x39\n\x16start_to_close_timeout\x18\t \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x34\n\x11heartbeat_timeout\x18\n \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x39\n\x0cretry_policy\x18\x0b \x01(\x0b\x32#.temporal.api.common.v1.RetryPolicy\x12/\n\x05input\x18\x0c \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x45\n\x0fid_reuse_policy\x18\r \x01(\x0e\x32,.temporal.api.enums.v1.ActivityIdReusePolicy\x12K\n\x12id_conflict_policy\x18\x0e \x01(\x0e\x32/.temporal.api.enums.v1.ActivityIdConflictPolicy\x12\x43\n\x11search_attributes\x18\x0f \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes\x12.\n\x06header\x18\x10 \x01(\x0b\x32\x1e.temporal.api.common.v1.Header\x12\x38\n\ruser_metadata\x18\x11 \x01(\x0b\x32!.temporal.api.sdk.v1.UserMetadata\x12\x32\n\x08priority\x18\x12 \x01(\x0b\x32 .temporal.api.common.v1.Priority\x12>\n\x14\x63ompletion_callbacks\x18\x13 \x03(\x0b\x32 .temporal.api.common.v1.Callback\x12+\n\x05links\x18\x14 \x03(\x0b\x32\x1c.temporal.api.common.v1.Link\x12\x46\n\x13on_conflict_options\x18\x15 \x01(\x0b\x32).temporal.api.common.v1.OnConflictOptions\x12.\n\x0bstart_delay\x18\x16 \x01(\x0b\x32\x19.google.protobuf.Duration"m\n\x1eStartActivityExecutionResponse\x12\x0e\n\x06run_id\x18\x01 \x01(\t\x12\x0f\n\x07started\x18\x02 \x01(\x08\x12*\n\x04link\x18\x03 \x01(\x0b\x32\x1c.temporal.api.common.v1.Link"\xe4\x01\n DescribeActivityExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0b\x61\x63tivity_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x12\x15\n\rinclude_input\x18\x04 \x01(\x08\x12\x17\n\x0finclude_outcome\x18\x05 \x01(\x08\x12\x17\n\x0flong_poll_token\x18\x06 \x01(\x0c\x12!\n\x19include_heartbeat_details\x18\x07 \x01(\x08\x12\x1c\n\x14include_last_failure\x18\x08 \x01(\x08"\xbc\x02\n!DescribeActivityExecutionResponse\x12\x0e\n\x06run_id\x18\x01 \x01(\t\x12=\n\x04info\x18\x02 \x01(\x0b\x32/.temporal.api.activity.v1.ActivityExecutionInfo\x12/\n\x05input\x18\x03 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x43\n\x07outcome\x18\x04 \x01(\x0b\x32\x32.temporal.api.activity.v1.ActivityExecutionOutcome\x12\x17\n\x0flong_poll_token\x18\x05 \x01(\x0c\x12\x39\n\tcallbacks\x18\x06 \x03(\x0b\x32&.temporal.api.activity.v1.CallbackInfo"V\n\x1cPollActivityExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0b\x61\x63tivity_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t"t\n\x1dPollActivityExecutionResponse\x12\x0e\n\x06run_id\x18\x01 \x01(\t\x12\x43\n\x07outcome\x18\x02 \x01(\x0b\x32\x32.temporal.api.activity.v1.ActivityExecutionOutcome"m\n\x1dListActivityExecutionsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x11\n\tpage_size\x18\x02 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c\x12\r\n\x05query\x18\x04 \x01(\t"\x82\x01\n\x1eListActivityExecutionsResponse\x12G\n\nexecutions\x18\x01 \x03(\x0b\x32\x33.temporal.api.activity.v1.ActivityExecutionListInfo\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c"\xd1\x06\n#StartNexusOperationExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x10\n\x08identity\x18\x02 \x01(\t\x12\x12\n\nrequest_id\x18\x03 \x01(\t\x12\x14\n\x0coperation_id\x18\x04 \x01(\t\x12\x10\n\x08\x65ndpoint\x18\x05 \x01(\t\x12\x0f\n\x07service\x18\x06 \x01(\t\x12\x11\n\toperation\x18\x07 \x01(\t\x12<\n\x19schedule_to_close_timeout\x18\x08 \x01(\x0b\x32\x19.google.protobuf.Duration\x12<\n\x19schedule_to_start_timeout\x18\t \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x39\n\x16start_to_close_timeout\x18\n \x01(\x0b\x32\x19.google.protobuf.Duration\x12.\n\x05input\x18\x0b \x01(\x0b\x32\x1f.temporal.api.common.v1.Payload\x12K\n\x0fid_reuse_policy\x18\x0c \x01(\x0e\x32\x32.temporal.api.enums.v1.NexusOperationIdReusePolicy\x12Q\n\x12id_conflict_policy\x18\r \x01(\x0e\x32\x35.temporal.api.enums.v1.NexusOperationIdConflictPolicy\x12\x43\n\x11search_attributes\x18\x0e \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes\x12k\n\x0cnexus_header\x18\x0f \x03(\x0b\x32U.temporal.api.workflowservice.v1.StartNexusOperationExecutionRequest.NexusHeaderEntry\x12\x38\n\ruser_metadata\x18\x10 \x01(\x0b\x32!.temporal.api.sdk.v1.UserMetadata\x1a\x32\n\x10NexusHeaderEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01"G\n$StartNexusOperationExecutionResponse\x12\x0e\n\x06run_id\x18\x01 \x01(\t\x12\x0f\n\x07started\x18\x02 \x01(\x08"\xaa\x01\n&DescribeNexusOperationExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x14\n\x0coperation_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x12\x15\n\rinclude_input\x18\x04 \x01(\x08\x12\x17\n\x0finclude_outcome\x18\x05 \x01(\x08\x12\x17\n\x0flong_poll_token\x18\x06 \x01(\x0c"\xb7\x02\n\'DescribeNexusOperationExecutionResponse\x12\x0e\n\x06run_id\x18\x01 \x01(\t\x12@\n\x04info\x18\x02 \x01(\x0b\x32\x32.temporal.api.nexus.v1.NexusOperationExecutionInfo\x12.\n\x05input\x18\x03 \x01(\x0b\x32\x1f.temporal.api.common.v1.Payload\x12\x31\n\x06result\x18\x04 \x01(\x0b\x32\x1f.temporal.api.common.v1.PayloadH\x00\x12\x33\n\x07\x66\x61ilure\x18\x05 \x01(\x0b\x32 .temporal.api.failure.v1.FailureH\x00\x12\x17\n\x0flong_poll_token\x18\x06 \x01(\x0c\x42\t\n\x07outcome"\xa1\x01\n"PollNexusOperationExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x14\n\x0coperation_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x12\x42\n\nwait_stage\x18\x04 \x01(\x0e\x32..temporal.api.enums.v1.NexusOperationWaitStage"\x85\x02\n#PollNexusOperationExecutionResponse\x12\x0e\n\x06run_id\x18\x01 \x01(\t\x12\x42\n\nwait_stage\x18\x02 \x01(\x0e\x32..temporal.api.enums.v1.NexusOperationWaitStage\x12\x17\n\x0foperation_token\x18\x03 \x01(\t\x12\x31\n\x06result\x18\x04 \x01(\x0b\x32\x1f.temporal.api.common.v1.PayloadH\x00\x12\x33\n\x07\x66\x61ilure\x18\x05 \x01(\x0b\x32 .temporal.api.failure.v1.FailureH\x00\x42\t\n\x07outcome"s\n#ListNexusOperationExecutionsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x11\n\tpage_size\x18\x02 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c\x12\r\n\x05query\x18\x04 \x01(\t"\x8b\x01\n$ListNexusOperationExecutionsResponse\x12J\n\noperations\x18\x01 \x03(\x0b\x32\x36.temporal.api.nexus.v1.NexusOperationExecutionListInfo\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c"B\n\x1e\x43ountActivityExecutionsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\r\n\x05query\x18\x02 \x01(\t"\xed\x01\n\x1f\x43ountActivityExecutionsResponse\x12\r\n\x05\x63ount\x18\x01 \x01(\x03\x12\x61\n\x06groups\x18\x02 \x03(\x0b\x32Q.temporal.api.workflowservice.v1.CountActivityExecutionsResponse.AggregationGroup\x1aX\n\x10\x41ggregationGroup\x12\x35\n\x0cgroup_values\x18\x01 \x03(\x0b\x32\x1f.temporal.api.common.v1.Payload\x12\r\n\x05\x63ount\x18\x02 \x01(\x03"H\n$CountNexusOperationExecutionsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\r\n\x05query\x18\x02 \x01(\t"\xf9\x01\n%CountNexusOperationExecutionsResponse\x12\r\n\x05\x63ount\x18\x01 \x01(\x03\x12g\n\x06groups\x18\x02 \x03(\x0b\x32W.temporal.api.workflowservice.v1.CountNexusOperationExecutionsResponse.AggregationGroup\x1aX\n\x10\x41ggregationGroup\x12\x35\n\x0cgroup_values\x18\x01 \x03(\x0b\x32\x1f.temporal.api.common.v1.Payload\x12\r\n\x05\x63ount\x18\x02 \x01(\x03"\x95\x01\n%RequestCancelActivityExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0b\x61\x63tivity_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x12\x10\n\x08identity\x18\x04 \x01(\t\x12\x12\n\nrequest_id\x18\x05 \x01(\t\x12\x0e\n\x06reason\x18\x06 \x01(\t"(\n&RequestCancelActivityExecutionResponse"\x91\x01\n!TerminateActivityExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0b\x61\x63tivity_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x12\x10\n\x08identity\x18\x04 \x01(\t\x12\x12\n\nrequest_id\x18\x05 \x01(\t\x12\x0e\n\x06reason\x18\x06 \x01(\t"$\n"TerminateActivityExecutionResponse"X\n\x1e\x44\x65leteActivityExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0b\x61\x63tivity_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t"!\n\x1f\x44\x65leteActivityExecutionResponse"\x9c\x01\n+RequestCancelNexusOperationExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x14\n\x0coperation_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x12\x10\n\x08identity\x18\x04 \x01(\t\x12\x12\n\nrequest_id\x18\x05 \x01(\t\x12\x0e\n\x06reason\x18\x06 \x01(\t".\n,RequestCancelNexusOperationExecutionResponse"\x98\x01\n\'TerminateNexusOperationExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x14\n\x0coperation_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x12\x10\n\x08identity\x18\x04 \x01(\t\x12\x12\n\nrequest_id\x18\x05 \x01(\t\x12\x0e\n\x06reason\x18\x06 \x01(\t"*\n(TerminateNexusOperationExecutionResponse"_\n$DeleteNexusOperationExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x14\n\x0coperation_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t"\'\n%DeleteNexusOperationExecutionResponseB\xbe\x01\n"io.temporal.api.workflowservice.v1B\x14RequestResponseProtoP\x01Z5go.temporal.io/api/workflowservice/v1;workflowservice\xaa\x02!Temporalio.Api.WorkflowService.V1\xea\x02$Temporalio::Api::WorkflowService::V1b\x06proto3' ) @@ -783,6 +783,8 @@ ] _DESCRIBEWORKERREQUEST = DESCRIPTOR.message_types_by_name["DescribeWorkerRequest"] _DESCRIBEWORKERRESPONSE = DESCRIPTOR.message_types_by_name["DescribeWorkerResponse"] +_COUNTWORKERSREQUEST = DESCRIPTOR.message_types_by_name["CountWorkersRequest"] +_COUNTWORKERSRESPONSE = DESCRIPTOR.message_types_by_name["CountWorkersResponse"] _PAUSEWORKFLOWEXECUTIONREQUEST = DESCRIPTOR.message_types_by_name[ "PauseWorkflowExecutionRequest" ] @@ -3494,6 +3496,28 @@ ) _sym_db.RegisterMessage(DescribeWorkerResponse) +CountWorkersRequest = _reflection.GeneratedProtocolMessageType( + "CountWorkersRequest", + (_message.Message,), + { + "DESCRIPTOR": _COUNTWORKERSREQUEST, + "__module__": "temporalio.api.workflowservice.v1.request_response_pb2", + # @@protoc_insertion_point(class_scope:temporal.api.workflowservice.v1.CountWorkersRequest) + }, +) +_sym_db.RegisterMessage(CountWorkersRequest) + +CountWorkersResponse = _reflection.GeneratedProtocolMessageType( + "CountWorkersResponse", + (_message.Message,), + { + "DESCRIPTOR": _COUNTWORKERSRESPONSE, + "__module__": "temporalio.api.workflowservice.v1.request_response_pb2", + # @@protoc_insertion_point(class_scope:temporal.api.workflowservice.v1.CountWorkersResponse) + }, +) +_sym_db.RegisterMessage(CountWorkersResponse) + PauseWorkflowExecutionRequest = _reflection.GeneratedProtocolMessageType( "PauseWorkflowExecutionRequest", (_message.Message,), @@ -4162,547 +4186,551 @@ _DEPRECATENAMESPACERESPONSE._serialized_start = 3782 _DEPRECATENAMESPACERESPONSE._serialized_end = 3810 _STARTWORKFLOWEXECUTIONREQUEST._serialized_start = 3813 - _STARTWORKFLOWEXECUTIONREQUEST._serialized_end = 5432 - _STARTWORKFLOWEXECUTIONRESPONSE._serialized_start = 5435 - _STARTWORKFLOWEXECUTIONRESPONSE._serialized_end = 5701 - _GETWORKFLOWEXECUTIONHISTORYREQUEST._serialized_start = 5704 - _GETWORKFLOWEXECUTIONHISTORYREQUEST._serialized_end = 6002 - _GETWORKFLOWEXECUTIONHISTORYRESPONSE._serialized_start = 6005 - _GETWORKFLOWEXECUTIONHISTORYRESPONSE._serialized_end = 6191 - _GETWORKFLOWEXECUTIONHISTORYREVERSEREQUEST._serialized_start = 6194 - _GETWORKFLOWEXECUTIONHISTORYREVERSEREQUEST._serialized_end = 6370 - _GETWORKFLOWEXECUTIONHISTORYREVERSERESPONSE._serialized_start = 6372 - _GETWORKFLOWEXECUTIONHISTORYREVERSERESPONSE._serialized_end = 6492 - _POLLWORKFLOWTASKQUEUEREQUEST._serialized_start = 6495 - _POLLWORKFLOWTASKQUEUEREQUEST._serialized_end = 6935 - _POLLWORKFLOWTASKQUEUERESPONSE._serialized_start = 6938 - _POLLWORKFLOWTASKQUEUERESPONSE._serialized_end = 7948 - _POLLWORKFLOWTASKQUEUERESPONSE_QUERIESENTRY._serialized_start = 7864 - _POLLWORKFLOWTASKQUEUERESPONSE_QUERIESENTRY._serialized_end = 7948 - _RESPONDWORKFLOWTASKCOMPLETEDREQUEST._serialized_start = 7951 - _RESPONDWORKFLOWTASKCOMPLETEDREQUEST._serialized_end = 9241 - _RESPONDWORKFLOWTASKCOMPLETEDREQUEST_QUERYRESULTSENTRY._serialized_start = 9075 - _RESPONDWORKFLOWTASKCOMPLETEDREQUEST_QUERYRESULTSENTRY._serialized_end = 9170 - _RESPONDWORKFLOWTASKCOMPLETEDREQUEST_CAPABILITIES._serialized_start = 9172 - _RESPONDWORKFLOWTASKCOMPLETEDREQUEST_CAPABILITIES._serialized_end = 9241 - _RESPONDWORKFLOWTASKCOMPLETEDRESPONSE._serialized_start = 9244 - _RESPONDWORKFLOWTASKCOMPLETEDRESPONSE._serialized_end = 9489 - _RESPONDWORKFLOWTASKFAILEDREQUEST._serialized_start = 9492 - _RESPONDWORKFLOWTASKFAILEDREQUEST._serialized_end = 10017 - _RESPONDWORKFLOWTASKFAILEDRESPONSE._serialized_start = 10019 - _RESPONDWORKFLOWTASKFAILEDRESPONSE._serialized_end = 10054 - _POLLACTIVITYTASKQUEUEREQUEST._serialized_start = 10057 - _POLLACTIVITYTASKQUEUEREQUEST._serialized_end = 10543 - _POLLACTIVITYTASKQUEUERESPONSE._serialized_start = 10546 - _POLLACTIVITYTASKQUEUERESPONSE._serialized_end = 11650 - _RECORDACTIVITYTASKHEARTBEATREQUEST._serialized_start = 11653 - _RECORDACTIVITYTASKHEARTBEATREQUEST._serialized_end = 11818 - _RECORDACTIVITYTASKHEARTBEATRESPONSE._serialized_start = 11820 - _RECORDACTIVITYTASKHEARTBEATRESPONSE._serialized_end = 11932 - _RECORDACTIVITYTASKHEARTBEATBYIDREQUEST._serialized_start = 11935 - _RECORDACTIVITYTASKHEARTBEATBYIDREQUEST._serialized_end = 12142 - _RECORDACTIVITYTASKHEARTBEATBYIDRESPONSE._serialized_start = 12144 - _RECORDACTIVITYTASKHEARTBEATBYIDRESPONSE._serialized_end = 12260 - _RESPONDACTIVITYTASKCOMPLETEDREQUEST._serialized_start = 12263 - _RESPONDACTIVITYTASKCOMPLETEDREQUEST._serialized_end = 12645 - _RESPONDACTIVITYTASKCOMPLETEDRESPONSE._serialized_start = 12647 - _RESPONDACTIVITYTASKCOMPLETEDRESPONSE._serialized_end = 12685 - _RESPONDACTIVITYTASKCOMPLETEDBYIDREQUEST._serialized_start = 12688 - _RESPONDACTIVITYTASKCOMPLETEDBYIDREQUEST._serialized_end = 12895 - _RESPONDACTIVITYTASKCOMPLETEDBYIDRESPONSE._serialized_start = 12897 - _RESPONDACTIVITYTASKCOMPLETEDBYIDRESPONSE._serialized_end = 12939 - _RESPONDACTIVITYTASKFAILEDREQUEST._serialized_start = 12942 - _RESPONDACTIVITYTASKFAILEDREQUEST._serialized_end = 13388 - _RESPONDACTIVITYTASKFAILEDRESPONSE._serialized_start = 13390 - _RESPONDACTIVITYTASKFAILEDRESPONSE._serialized_end = 13477 - _RESPONDACTIVITYTASKFAILEDBYIDREQUEST._serialized_start = 13480 - _RESPONDACTIVITYTASKFAILEDBYIDREQUEST._serialized_end = 13751 - _RESPONDACTIVITYTASKFAILEDBYIDRESPONSE._serialized_start = 13753 - _RESPONDACTIVITYTASKFAILEDBYIDRESPONSE._serialized_end = 13844 - _RESPONDACTIVITYTASKCANCELEDREQUEST._serialized_start = 13847 - _RESPONDACTIVITYTASKCANCELEDREQUEST._serialized_end = 14229 - _RESPONDACTIVITYTASKCANCELEDRESPONSE._serialized_start = 14231 - _RESPONDACTIVITYTASKCANCELEDRESPONSE._serialized_end = 14268 - _RESPONDACTIVITYTASKCANCELEDBYIDREQUEST._serialized_start = 14271 - _RESPONDACTIVITYTASKCANCELEDBYIDREQUEST._serialized_end = 14559 - _RESPONDACTIVITYTASKCANCELEDBYIDRESPONSE._serialized_start = 14561 - _RESPONDACTIVITYTASKCANCELEDBYIDRESPONSE._serialized_end = 14602 - _REQUESTCANCELWORKFLOWEXECUTIONREQUEST._serialized_start = 14605 - _REQUESTCANCELWORKFLOWEXECUTIONREQUEST._serialized_end = 14865 - _REQUESTCANCELWORKFLOWEXECUTIONRESPONSE._serialized_start = 14867 - _REQUESTCANCELWORKFLOWEXECUTIONRESPONSE._serialized_end = 14907 - _SIGNALWORKFLOWEXECUTIONREQUEST._serialized_start = 14910 - _SIGNALWORKFLOWEXECUTIONREQUEST._serialized_end = 15260 - _SIGNALWORKFLOWEXECUTIONRESPONSE._serialized_start = 15262 - _SIGNALWORKFLOWEXECUTIONRESPONSE._serialized_end = 15339 - _SIGNALWITHSTARTWORKFLOWEXECUTIONREQUEST._serialized_start = 15342 - _SIGNALWITHSTARTWORKFLOWEXECUTIONREQUEST._serialized_end = 16683 - _SIGNALWITHSTARTWORKFLOWEXECUTIONRESPONSE._serialized_start = 16685 - _SIGNALWITHSTARTWORKFLOWEXECUTIONRESPONSE._serialized_end = 16811 - _RESETWORKFLOWEXECUTIONREQUEST._serialized_start = 16814 - _RESETWORKFLOWEXECUTIONREQUEST._serialized_end = 17263 - _RESETWORKFLOWEXECUTIONRESPONSE._serialized_start = 17265 - _RESETWORKFLOWEXECUTIONRESPONSE._serialized_end = 17313 - _TERMINATEWORKFLOWEXECUTIONREQUEST._serialized_start = 17316 - _TERMINATEWORKFLOWEXECUTIONREQUEST._serialized_end = 17603 - _TERMINATEWORKFLOWEXECUTIONRESPONSE._serialized_start = 17605 - _TERMINATEWORKFLOWEXECUTIONRESPONSE._serialized_end = 17641 - _DELETEWORKFLOWEXECUTIONREQUEST._serialized_start = 17643 - _DELETEWORKFLOWEXECUTIONREQUEST._serialized_end = 17765 - _DELETEWORKFLOWEXECUTIONRESPONSE._serialized_start = 17767 - _DELETEWORKFLOWEXECUTIONRESPONSE._serialized_end = 17800 - _LISTOPENWORKFLOWEXECUTIONSREQUEST._serialized_start = 17803 - _LISTOPENWORKFLOWEXECUTIONSREQUEST._serialized_end = 18132 - _LISTOPENWORKFLOWEXECUTIONSRESPONSE._serialized_start = 18135 - _LISTOPENWORKFLOWEXECUTIONSRESPONSE._serialized_end = 18265 - _LISTCLOSEDWORKFLOWEXECUTIONSREQUEST._serialized_start = 18268 - _LISTCLOSEDWORKFLOWEXECUTIONSREQUEST._serialized_end = 18662 - _LISTCLOSEDWORKFLOWEXECUTIONSRESPONSE._serialized_start = 18665 - _LISTCLOSEDWORKFLOWEXECUTIONSRESPONSE._serialized_end = 18797 - _LISTWORKFLOWEXECUTIONSREQUEST._serialized_start = 18799 - _LISTWORKFLOWEXECUTIONSREQUEST._serialized_end = 18908 - _LISTWORKFLOWEXECUTIONSRESPONSE._serialized_start = 18910 - _LISTWORKFLOWEXECUTIONSRESPONSE._serialized_end = 19036 - _LISTARCHIVEDWORKFLOWEXECUTIONSREQUEST._serialized_start = 19038 - _LISTARCHIVEDWORKFLOWEXECUTIONSREQUEST._serialized_end = 19155 - _LISTARCHIVEDWORKFLOWEXECUTIONSRESPONSE._serialized_start = 19158 - _LISTARCHIVEDWORKFLOWEXECUTIONSRESPONSE._serialized_end = 19292 - _SCANWORKFLOWEXECUTIONSREQUEST._serialized_start = 19294 - _SCANWORKFLOWEXECUTIONSREQUEST._serialized_end = 19403 - _SCANWORKFLOWEXECUTIONSRESPONSE._serialized_start = 19405 - _SCANWORKFLOWEXECUTIONSRESPONSE._serialized_end = 19531 - _COUNTWORKFLOWEXECUTIONSREQUEST._serialized_start = 19533 - _COUNTWORKFLOWEXECUTIONSREQUEST._serialized_end = 19599 - _COUNTWORKFLOWEXECUTIONSRESPONSE._serialized_start = 19602 - _COUNTWORKFLOWEXECUTIONSRESPONSE._serialized_end = 19839 - _COUNTWORKFLOWEXECUTIONSRESPONSE_AGGREGATIONGROUP._serialized_start = 19751 - _COUNTWORKFLOWEXECUTIONSRESPONSE_AGGREGATIONGROUP._serialized_end = 19839 - _GETSEARCHATTRIBUTESREQUEST._serialized_start = 19841 - _GETSEARCHATTRIBUTESREQUEST._serialized_end = 19869 - _GETSEARCHATTRIBUTESRESPONSE._serialized_start = 19872 - _GETSEARCHATTRIBUTESRESPONSE._serialized_end = 20073 - _GETSEARCHATTRIBUTESRESPONSE_KEYSENTRY._serialized_start = 19989 - _GETSEARCHATTRIBUTESRESPONSE_KEYSENTRY._serialized_end = 20073 - _RESPONDQUERYTASKCOMPLETEDREQUEST._serialized_start = 20076 - _RESPONDQUERYTASKCOMPLETEDREQUEST._serialized_end = 20437 - _RESPONDQUERYTASKCOMPLETEDRESPONSE._serialized_start = 20439 - _RESPONDQUERYTASKCOMPLETEDRESPONSE._serialized_end = 20474 - _RESETSTICKYTASKQUEUEREQUEST._serialized_start = 20476 - _RESETSTICKYTASKQUEUEREQUEST._serialized_end = 20586 - _RESETSTICKYTASKQUEUERESPONSE._serialized_start = 20588 - _RESETSTICKYTASKQUEUERESPONSE._serialized_end = 20618 - _SHUTDOWNWORKERREQUEST._serialized_start = 20621 - _SHUTDOWNWORKERREQUEST._serialized_end = 20904 - _SHUTDOWNWORKERRESPONSE._serialized_start = 20906 - _SHUTDOWNWORKERRESPONSE._serialized_end = 20930 - _QUERYWORKFLOWREQUEST._serialized_start = 20933 - _QUERYWORKFLOWREQUEST._serialized_end = 21166 - _QUERYWORKFLOWRESPONSE._serialized_start = 21169 - _QUERYWORKFLOWRESPONSE._serialized_end = 21310 - _DESCRIBEWORKFLOWEXECUTIONREQUEST._serialized_start = 21312 - _DESCRIBEWORKFLOWEXECUTIONREQUEST._serialized_end = 21427 - _DESCRIBEWORKFLOWEXECUTIONRESPONSE._serialized_start = 21430 - _DESCRIBEWORKFLOWEXECUTIONRESPONSE._serialized_end = 22095 - _DESCRIBETASKQUEUEREQUEST._serialized_start = 22098 - _DESCRIBETASKQUEUEREQUEST._serialized_end = 22626 - _DESCRIBETASKQUEUERESPONSE._serialized_start = 22629 - _DESCRIBETASKQUEUERESPONSE._serialized_end = 23633 - _DESCRIBETASKQUEUERESPONSE_STATSBYPRIORITYKEYENTRY._serialized_start = 23313 - _DESCRIBETASKQUEUERESPONSE_STATSBYPRIORITYKEYENTRY._serialized_end = 23413 - _DESCRIBETASKQUEUERESPONSE_EFFECTIVERATELIMIT._serialized_start = 23415 - _DESCRIBETASKQUEUERESPONSE_EFFECTIVERATELIMIT._serialized_end = 23531 - _DESCRIBETASKQUEUERESPONSE_VERSIONSINFOENTRY._serialized_start = 23533 - _DESCRIBETASKQUEUERESPONSE_VERSIONSINFOENTRY._serialized_end = 23633 - _GETCLUSTERINFOREQUEST._serialized_start = 23635 - _GETCLUSTERINFOREQUEST._serialized_end = 23658 - _GETCLUSTERINFORESPONSE._serialized_start = 23661 - _GETCLUSTERINFORESPONSE._serialized_end = 24126 - _GETCLUSTERINFORESPONSE_SUPPORTEDCLIENTSENTRY._serialized_start = 24071 - _GETCLUSTERINFORESPONSE_SUPPORTEDCLIENTSENTRY._serialized_end = 24126 - _GETSYSTEMINFOREQUEST._serialized_start = 24128 - _GETSYSTEMINFOREQUEST._serialized_end = 24150 - _GETSYSTEMINFORESPONSE._serialized_start = 24153 - _GETSYSTEMINFORESPONSE._serialized_end = 24688 - _GETSYSTEMINFORESPONSE_CAPABILITIES._serialized_start = 24294 - _GETSYSTEMINFORESPONSE_CAPABILITIES._serialized_end = 24688 - _LISTTASKQUEUEPARTITIONSREQUEST._serialized_start = 24690 - _LISTTASKQUEUEPARTITIONSREQUEST._serialized_end = 24799 - _LISTTASKQUEUEPARTITIONSRESPONSE._serialized_start = 24802 - _LISTTASKQUEUEPARTITIONSRESPONSE._serialized_end = 25025 - _CREATESCHEDULEREQUEST._serialized_start = 25028 - _CREATESCHEDULEREQUEST._serialized_end = 25360 - _CREATESCHEDULERESPONSE._serialized_start = 25362 - _CREATESCHEDULERESPONSE._serialized_end = 25410 - _DESCRIBESCHEDULEREQUEST._serialized_start = 25412 - _DESCRIBESCHEDULEREQUEST._serialized_end = 25477 - _DESCRIBESCHEDULERESPONSE._serialized_start = 25480 - _DESCRIBESCHEDULERESPONSE._serialized_end = 25751 - _UPDATESCHEDULEREQUEST._serialized_start = 25754 - _UPDATESCHEDULEREQUEST._serialized_end = 26046 - _UPDATESCHEDULERESPONSE._serialized_start = 26048 - _UPDATESCHEDULERESPONSE._serialized_end = 26072 - _PATCHSCHEDULEREQUEST._serialized_start = 26075 - _PATCHSCHEDULEREQUEST._serialized_end = 26231 - _PATCHSCHEDULERESPONSE._serialized_start = 26233 - _PATCHSCHEDULERESPONSE._serialized_end = 26256 - _LISTSCHEDULEMATCHINGTIMESREQUEST._serialized_start = 26259 - _LISTSCHEDULEMATCHINGTIMESREQUEST._serialized_end = 26427 - _LISTSCHEDULEMATCHINGTIMESRESPONSE._serialized_start = 26429 - _LISTSCHEDULEMATCHINGTIMESRESPONSE._serialized_end = 26512 - _DELETESCHEDULEREQUEST._serialized_start = 26514 - _DELETESCHEDULEREQUEST._serialized_end = 26595 - _DELETESCHEDULERESPONSE._serialized_start = 26597 - _DELETESCHEDULERESPONSE._serialized_end = 26621 - _LISTSCHEDULESREQUEST._serialized_start = 26623 - _LISTSCHEDULESREQUEST._serialized_end = 26731 - _LISTSCHEDULESRESPONSE._serialized_start = 26733 - _LISTSCHEDULESRESPONSE._serialized_end = 26845 - _COUNTSCHEDULESREQUEST._serialized_start = 26847 - _COUNTSCHEDULESREQUEST._serialized_end = 26904 - _COUNTSCHEDULESRESPONSE._serialized_start = 26907 - _COUNTSCHEDULESRESPONSE._serialized_end = 27126 - _COUNTSCHEDULESRESPONSE_AGGREGATIONGROUP._serialized_start = 19751 - _COUNTSCHEDULESRESPONSE_AGGREGATIONGROUP._serialized_end = 19839 - _UPDATEWORKERBUILDIDCOMPATIBILITYREQUEST._serialized_start = 27129 - _UPDATEWORKERBUILDIDCOMPATIBILITYREQUEST._serialized_end = 27775 - _UPDATEWORKERBUILDIDCOMPATIBILITYREQUEST_ADDNEWCOMPATIBLEVERSION._serialized_start = 27576 + _STARTWORKFLOWEXECUTIONREQUEST._serialized_end = 5430 + _STARTWORKFLOWEXECUTIONRESPONSE._serialized_start = 5433 + _STARTWORKFLOWEXECUTIONRESPONSE._serialized_end = 5699 + _GETWORKFLOWEXECUTIONHISTORYREQUEST._serialized_start = 5702 + _GETWORKFLOWEXECUTIONHISTORYREQUEST._serialized_end = 6000 + _GETWORKFLOWEXECUTIONHISTORYRESPONSE._serialized_start = 6003 + _GETWORKFLOWEXECUTIONHISTORYRESPONSE._serialized_end = 6189 + _GETWORKFLOWEXECUTIONHISTORYREVERSEREQUEST._serialized_start = 6192 + _GETWORKFLOWEXECUTIONHISTORYREVERSEREQUEST._serialized_end = 6368 + _GETWORKFLOWEXECUTIONHISTORYREVERSERESPONSE._serialized_start = 6370 + _GETWORKFLOWEXECUTIONHISTORYREVERSERESPONSE._serialized_end = 6490 + _POLLWORKFLOWTASKQUEUEREQUEST._serialized_start = 6493 + _POLLWORKFLOWTASKQUEUEREQUEST._serialized_end = 6933 + _POLLWORKFLOWTASKQUEUERESPONSE._serialized_start = 6936 + _POLLWORKFLOWTASKQUEUERESPONSE._serialized_end = 7946 + _POLLWORKFLOWTASKQUEUERESPONSE_QUERIESENTRY._serialized_start = 7862 + _POLLWORKFLOWTASKQUEUERESPONSE_QUERIESENTRY._serialized_end = 7946 + _RESPONDWORKFLOWTASKCOMPLETEDREQUEST._serialized_start = 7949 + _RESPONDWORKFLOWTASKCOMPLETEDREQUEST._serialized_end = 9239 + _RESPONDWORKFLOWTASKCOMPLETEDREQUEST_QUERYRESULTSENTRY._serialized_start = 9073 + _RESPONDWORKFLOWTASKCOMPLETEDREQUEST_QUERYRESULTSENTRY._serialized_end = 9168 + _RESPONDWORKFLOWTASKCOMPLETEDREQUEST_CAPABILITIES._serialized_start = 9170 + _RESPONDWORKFLOWTASKCOMPLETEDREQUEST_CAPABILITIES._serialized_end = 9239 + _RESPONDWORKFLOWTASKCOMPLETEDRESPONSE._serialized_start = 9242 + _RESPONDWORKFLOWTASKCOMPLETEDRESPONSE._serialized_end = 9487 + _RESPONDWORKFLOWTASKFAILEDREQUEST._serialized_start = 9490 + _RESPONDWORKFLOWTASKFAILEDREQUEST._serialized_end = 10015 + _RESPONDWORKFLOWTASKFAILEDRESPONSE._serialized_start = 10017 + _RESPONDWORKFLOWTASKFAILEDRESPONSE._serialized_end = 10052 + _POLLACTIVITYTASKQUEUEREQUEST._serialized_start = 10055 + _POLLACTIVITYTASKQUEUEREQUEST._serialized_end = 10541 + _POLLACTIVITYTASKQUEUERESPONSE._serialized_start = 10544 + _POLLACTIVITYTASKQUEUERESPONSE._serialized_end = 11648 + _RECORDACTIVITYTASKHEARTBEATREQUEST._serialized_start = 11651 + _RECORDACTIVITYTASKHEARTBEATREQUEST._serialized_end = 11816 + _RECORDACTIVITYTASKHEARTBEATRESPONSE._serialized_start = 11818 + _RECORDACTIVITYTASKHEARTBEATRESPONSE._serialized_end = 11930 + _RECORDACTIVITYTASKHEARTBEATBYIDREQUEST._serialized_start = 11933 + _RECORDACTIVITYTASKHEARTBEATBYIDREQUEST._serialized_end = 12140 + _RECORDACTIVITYTASKHEARTBEATBYIDRESPONSE._serialized_start = 12142 + _RECORDACTIVITYTASKHEARTBEATBYIDRESPONSE._serialized_end = 12258 + _RESPONDACTIVITYTASKCOMPLETEDREQUEST._serialized_start = 12261 + _RESPONDACTIVITYTASKCOMPLETEDREQUEST._serialized_end = 12643 + _RESPONDACTIVITYTASKCOMPLETEDRESPONSE._serialized_start = 12645 + _RESPONDACTIVITYTASKCOMPLETEDRESPONSE._serialized_end = 12683 + _RESPONDACTIVITYTASKCOMPLETEDBYIDREQUEST._serialized_start = 12686 + _RESPONDACTIVITYTASKCOMPLETEDBYIDREQUEST._serialized_end = 12893 + _RESPONDACTIVITYTASKCOMPLETEDBYIDRESPONSE._serialized_start = 12895 + _RESPONDACTIVITYTASKCOMPLETEDBYIDRESPONSE._serialized_end = 12937 + _RESPONDACTIVITYTASKFAILEDREQUEST._serialized_start = 12940 + _RESPONDACTIVITYTASKFAILEDREQUEST._serialized_end = 13386 + _RESPONDACTIVITYTASKFAILEDRESPONSE._serialized_start = 13388 + _RESPONDACTIVITYTASKFAILEDRESPONSE._serialized_end = 13475 + _RESPONDACTIVITYTASKFAILEDBYIDREQUEST._serialized_start = 13478 + _RESPONDACTIVITYTASKFAILEDBYIDREQUEST._serialized_end = 13749 + _RESPONDACTIVITYTASKFAILEDBYIDRESPONSE._serialized_start = 13751 + _RESPONDACTIVITYTASKFAILEDBYIDRESPONSE._serialized_end = 13842 + _RESPONDACTIVITYTASKCANCELEDREQUEST._serialized_start = 13845 + _RESPONDACTIVITYTASKCANCELEDREQUEST._serialized_end = 14227 + _RESPONDACTIVITYTASKCANCELEDRESPONSE._serialized_start = 14229 + _RESPONDACTIVITYTASKCANCELEDRESPONSE._serialized_end = 14266 + _RESPONDACTIVITYTASKCANCELEDBYIDREQUEST._serialized_start = 14269 + _RESPONDACTIVITYTASKCANCELEDBYIDREQUEST._serialized_end = 14557 + _RESPONDACTIVITYTASKCANCELEDBYIDRESPONSE._serialized_start = 14559 + _RESPONDACTIVITYTASKCANCELEDBYIDRESPONSE._serialized_end = 14600 + _REQUESTCANCELWORKFLOWEXECUTIONREQUEST._serialized_start = 14603 + _REQUESTCANCELWORKFLOWEXECUTIONREQUEST._serialized_end = 14863 + _REQUESTCANCELWORKFLOWEXECUTIONRESPONSE._serialized_start = 14865 + _REQUESTCANCELWORKFLOWEXECUTIONRESPONSE._serialized_end = 14905 + _SIGNALWORKFLOWEXECUTIONREQUEST._serialized_start = 14908 + _SIGNALWORKFLOWEXECUTIONREQUEST._serialized_end = 15258 + _SIGNALWORKFLOWEXECUTIONRESPONSE._serialized_start = 15260 + _SIGNALWORKFLOWEXECUTIONRESPONSE._serialized_end = 15337 + _SIGNALWITHSTARTWORKFLOWEXECUTIONREQUEST._serialized_start = 15340 + _SIGNALWITHSTARTWORKFLOWEXECUTIONREQUEST._serialized_end = 16679 + _SIGNALWITHSTARTWORKFLOWEXECUTIONRESPONSE._serialized_start = 16681 + _SIGNALWITHSTARTWORKFLOWEXECUTIONRESPONSE._serialized_end = 16807 + _RESETWORKFLOWEXECUTIONREQUEST._serialized_start = 16810 + _RESETWORKFLOWEXECUTIONREQUEST._serialized_end = 17259 + _RESETWORKFLOWEXECUTIONRESPONSE._serialized_start = 17261 + _RESETWORKFLOWEXECUTIONRESPONSE._serialized_end = 17309 + _TERMINATEWORKFLOWEXECUTIONREQUEST._serialized_start = 17312 + _TERMINATEWORKFLOWEXECUTIONREQUEST._serialized_end = 17599 + _TERMINATEWORKFLOWEXECUTIONRESPONSE._serialized_start = 17601 + _TERMINATEWORKFLOWEXECUTIONRESPONSE._serialized_end = 17637 + _DELETEWORKFLOWEXECUTIONREQUEST._serialized_start = 17639 + _DELETEWORKFLOWEXECUTIONREQUEST._serialized_end = 17761 + _DELETEWORKFLOWEXECUTIONRESPONSE._serialized_start = 17763 + _DELETEWORKFLOWEXECUTIONRESPONSE._serialized_end = 17796 + _LISTOPENWORKFLOWEXECUTIONSREQUEST._serialized_start = 17799 + _LISTOPENWORKFLOWEXECUTIONSREQUEST._serialized_end = 18128 + _LISTOPENWORKFLOWEXECUTIONSRESPONSE._serialized_start = 18131 + _LISTOPENWORKFLOWEXECUTIONSRESPONSE._serialized_end = 18261 + _LISTCLOSEDWORKFLOWEXECUTIONSREQUEST._serialized_start = 18264 + _LISTCLOSEDWORKFLOWEXECUTIONSREQUEST._serialized_end = 18658 + _LISTCLOSEDWORKFLOWEXECUTIONSRESPONSE._serialized_start = 18661 + _LISTCLOSEDWORKFLOWEXECUTIONSRESPONSE._serialized_end = 18793 + _LISTWORKFLOWEXECUTIONSREQUEST._serialized_start = 18795 + _LISTWORKFLOWEXECUTIONSREQUEST._serialized_end = 18904 + _LISTWORKFLOWEXECUTIONSRESPONSE._serialized_start = 18906 + _LISTWORKFLOWEXECUTIONSRESPONSE._serialized_end = 19032 + _LISTARCHIVEDWORKFLOWEXECUTIONSREQUEST._serialized_start = 19034 + _LISTARCHIVEDWORKFLOWEXECUTIONSREQUEST._serialized_end = 19151 + _LISTARCHIVEDWORKFLOWEXECUTIONSRESPONSE._serialized_start = 19154 + _LISTARCHIVEDWORKFLOWEXECUTIONSRESPONSE._serialized_end = 19288 + _SCANWORKFLOWEXECUTIONSREQUEST._serialized_start = 19290 + _SCANWORKFLOWEXECUTIONSREQUEST._serialized_end = 19399 + _SCANWORKFLOWEXECUTIONSRESPONSE._serialized_start = 19401 + _SCANWORKFLOWEXECUTIONSRESPONSE._serialized_end = 19527 + _COUNTWORKFLOWEXECUTIONSREQUEST._serialized_start = 19529 + _COUNTWORKFLOWEXECUTIONSREQUEST._serialized_end = 19595 + _COUNTWORKFLOWEXECUTIONSRESPONSE._serialized_start = 19598 + _COUNTWORKFLOWEXECUTIONSRESPONSE._serialized_end = 19835 + _COUNTWORKFLOWEXECUTIONSRESPONSE_AGGREGATIONGROUP._serialized_start = 19747 + _COUNTWORKFLOWEXECUTIONSRESPONSE_AGGREGATIONGROUP._serialized_end = 19835 + _GETSEARCHATTRIBUTESREQUEST._serialized_start = 19837 + _GETSEARCHATTRIBUTESREQUEST._serialized_end = 19865 + _GETSEARCHATTRIBUTESRESPONSE._serialized_start = 19868 + _GETSEARCHATTRIBUTESRESPONSE._serialized_end = 20069 + _GETSEARCHATTRIBUTESRESPONSE_KEYSENTRY._serialized_start = 19985 + _GETSEARCHATTRIBUTESRESPONSE_KEYSENTRY._serialized_end = 20069 + _RESPONDQUERYTASKCOMPLETEDREQUEST._serialized_start = 20072 + _RESPONDQUERYTASKCOMPLETEDREQUEST._serialized_end = 20433 + _RESPONDQUERYTASKCOMPLETEDRESPONSE._serialized_start = 20435 + _RESPONDQUERYTASKCOMPLETEDRESPONSE._serialized_end = 20470 + _RESETSTICKYTASKQUEUEREQUEST._serialized_start = 20472 + _RESETSTICKYTASKQUEUEREQUEST._serialized_end = 20582 + _RESETSTICKYTASKQUEUERESPONSE._serialized_start = 20584 + _RESETSTICKYTASKQUEUERESPONSE._serialized_end = 20614 + _SHUTDOWNWORKERREQUEST._serialized_start = 20617 + _SHUTDOWNWORKERREQUEST._serialized_end = 20900 + _SHUTDOWNWORKERRESPONSE._serialized_start = 20902 + _SHUTDOWNWORKERRESPONSE._serialized_end = 20926 + _QUERYWORKFLOWREQUEST._serialized_start = 20929 + _QUERYWORKFLOWREQUEST._serialized_end = 21162 + _QUERYWORKFLOWRESPONSE._serialized_start = 21165 + _QUERYWORKFLOWRESPONSE._serialized_end = 21306 + _DESCRIBEWORKFLOWEXECUTIONREQUEST._serialized_start = 21308 + _DESCRIBEWORKFLOWEXECUTIONREQUEST._serialized_end = 21423 + _DESCRIBEWORKFLOWEXECUTIONRESPONSE._serialized_start = 21426 + _DESCRIBEWORKFLOWEXECUTIONRESPONSE._serialized_end = 22091 + _DESCRIBETASKQUEUEREQUEST._serialized_start = 22094 + _DESCRIBETASKQUEUEREQUEST._serialized_end = 22622 + _DESCRIBETASKQUEUERESPONSE._serialized_start = 22625 + _DESCRIBETASKQUEUERESPONSE._serialized_end = 23629 + _DESCRIBETASKQUEUERESPONSE_STATSBYPRIORITYKEYENTRY._serialized_start = 23309 + _DESCRIBETASKQUEUERESPONSE_STATSBYPRIORITYKEYENTRY._serialized_end = 23409 + _DESCRIBETASKQUEUERESPONSE_EFFECTIVERATELIMIT._serialized_start = 23411 + _DESCRIBETASKQUEUERESPONSE_EFFECTIVERATELIMIT._serialized_end = 23527 + _DESCRIBETASKQUEUERESPONSE_VERSIONSINFOENTRY._serialized_start = 23529 + _DESCRIBETASKQUEUERESPONSE_VERSIONSINFOENTRY._serialized_end = 23629 + _GETCLUSTERINFOREQUEST._serialized_start = 23631 + _GETCLUSTERINFOREQUEST._serialized_end = 23654 + _GETCLUSTERINFORESPONSE._serialized_start = 23657 + _GETCLUSTERINFORESPONSE._serialized_end = 24122 + _GETCLUSTERINFORESPONSE_SUPPORTEDCLIENTSENTRY._serialized_start = 24067 + _GETCLUSTERINFORESPONSE_SUPPORTEDCLIENTSENTRY._serialized_end = 24122 + _GETSYSTEMINFOREQUEST._serialized_start = 24124 + _GETSYSTEMINFOREQUEST._serialized_end = 24146 + _GETSYSTEMINFORESPONSE._serialized_start = 24149 + _GETSYSTEMINFORESPONSE._serialized_end = 24684 + _GETSYSTEMINFORESPONSE_CAPABILITIES._serialized_start = 24290 + _GETSYSTEMINFORESPONSE_CAPABILITIES._serialized_end = 24684 + _LISTTASKQUEUEPARTITIONSREQUEST._serialized_start = 24686 + _LISTTASKQUEUEPARTITIONSREQUEST._serialized_end = 24795 + _LISTTASKQUEUEPARTITIONSRESPONSE._serialized_start = 24798 + _LISTTASKQUEUEPARTITIONSRESPONSE._serialized_end = 25021 + _CREATESCHEDULEREQUEST._serialized_start = 25024 + _CREATESCHEDULEREQUEST._serialized_end = 25356 + _CREATESCHEDULERESPONSE._serialized_start = 25358 + _CREATESCHEDULERESPONSE._serialized_end = 25406 + _DESCRIBESCHEDULEREQUEST._serialized_start = 25408 + _DESCRIBESCHEDULEREQUEST._serialized_end = 25473 + _DESCRIBESCHEDULERESPONSE._serialized_start = 25476 + _DESCRIBESCHEDULERESPONSE._serialized_end = 25747 + _UPDATESCHEDULEREQUEST._serialized_start = 25750 + _UPDATESCHEDULEREQUEST._serialized_end = 26042 + _UPDATESCHEDULERESPONSE._serialized_start = 26044 + _UPDATESCHEDULERESPONSE._serialized_end = 26068 + _PATCHSCHEDULEREQUEST._serialized_start = 26071 + _PATCHSCHEDULEREQUEST._serialized_end = 26227 + _PATCHSCHEDULERESPONSE._serialized_start = 26229 + _PATCHSCHEDULERESPONSE._serialized_end = 26252 + _LISTSCHEDULEMATCHINGTIMESREQUEST._serialized_start = 26255 + _LISTSCHEDULEMATCHINGTIMESREQUEST._serialized_end = 26423 + _LISTSCHEDULEMATCHINGTIMESRESPONSE._serialized_start = 26425 + _LISTSCHEDULEMATCHINGTIMESRESPONSE._serialized_end = 26508 + _DELETESCHEDULEREQUEST._serialized_start = 26510 + _DELETESCHEDULEREQUEST._serialized_end = 26591 + _DELETESCHEDULERESPONSE._serialized_start = 26593 + _DELETESCHEDULERESPONSE._serialized_end = 26617 + _LISTSCHEDULESREQUEST._serialized_start = 26619 + _LISTSCHEDULESREQUEST._serialized_end = 26727 + _LISTSCHEDULESRESPONSE._serialized_start = 26729 + _LISTSCHEDULESRESPONSE._serialized_end = 26841 + _COUNTSCHEDULESREQUEST._serialized_start = 26843 + _COUNTSCHEDULESREQUEST._serialized_end = 26900 + _COUNTSCHEDULESRESPONSE._serialized_start = 26903 + _COUNTSCHEDULESRESPONSE._serialized_end = 27122 + _COUNTSCHEDULESRESPONSE_AGGREGATIONGROUP._serialized_start = 19747 + _COUNTSCHEDULESRESPONSE_AGGREGATIONGROUP._serialized_end = 19835 + _UPDATEWORKERBUILDIDCOMPATIBILITYREQUEST._serialized_start = 27125 + _UPDATEWORKERBUILDIDCOMPATIBILITYREQUEST._serialized_end = 27771 + _UPDATEWORKERBUILDIDCOMPATIBILITYREQUEST_ADDNEWCOMPATIBLEVERSION._serialized_start = 27572 _UPDATEWORKERBUILDIDCOMPATIBILITYREQUEST_ADDNEWCOMPATIBLEVERSION._serialized_end = ( - 27687 + 27683 ) - _UPDATEWORKERBUILDIDCOMPATIBILITYREQUEST_MERGESETS._serialized_start = 27689 - _UPDATEWORKERBUILDIDCOMPATIBILITYREQUEST_MERGESETS._serialized_end = 27762 - _UPDATEWORKERBUILDIDCOMPATIBILITYRESPONSE._serialized_start = 27777 - _UPDATEWORKERBUILDIDCOMPATIBILITYRESPONSE._serialized_end = 27841 - _GETWORKERBUILDIDCOMPATIBILITYREQUEST._serialized_start = 27843 - _GETWORKERBUILDIDCOMPATIBILITYREQUEST._serialized_end = 27938 - _GETWORKERBUILDIDCOMPATIBILITYRESPONSE._serialized_start = 27940 - _GETWORKERBUILDIDCOMPATIBILITYRESPONSE._serialized_end = 28056 - _UPDATEWORKERVERSIONINGRULESREQUEST._serialized_start = 28059 - _UPDATEWORKERVERSIONINGRULESREQUEST._serialized_end = 29776 - _UPDATEWORKERVERSIONINGRULESREQUEST_INSERTBUILDIDASSIGNMENTRULE._serialized_start = 29111 + _UPDATEWORKERBUILDIDCOMPATIBILITYREQUEST_MERGESETS._serialized_start = 27685 + _UPDATEWORKERBUILDIDCOMPATIBILITYREQUEST_MERGESETS._serialized_end = 27758 + _UPDATEWORKERBUILDIDCOMPATIBILITYRESPONSE._serialized_start = 27773 + _UPDATEWORKERBUILDIDCOMPATIBILITYRESPONSE._serialized_end = 27837 + _GETWORKERBUILDIDCOMPATIBILITYREQUEST._serialized_start = 27839 + _GETWORKERBUILDIDCOMPATIBILITYREQUEST._serialized_end = 27934 + _GETWORKERBUILDIDCOMPATIBILITYRESPONSE._serialized_start = 27936 + _GETWORKERBUILDIDCOMPATIBILITYRESPONSE._serialized_end = 28052 + _UPDATEWORKERVERSIONINGRULESREQUEST._serialized_start = 28055 + _UPDATEWORKERVERSIONINGRULESREQUEST._serialized_end = 29772 + _UPDATEWORKERVERSIONINGRULESREQUEST_INSERTBUILDIDASSIGNMENTRULE._serialized_start = 29107 _UPDATEWORKERVERSIONINGRULESREQUEST_INSERTBUILDIDASSIGNMENTRULE._serialized_end = ( - 29224 + 29220 ) - _UPDATEWORKERVERSIONINGRULESREQUEST_REPLACEBUILDIDASSIGNMENTRULE._serialized_start = 29227 + _UPDATEWORKERVERSIONINGRULESREQUEST_REPLACEBUILDIDASSIGNMENTRULE._serialized_start = 29223 _UPDATEWORKERVERSIONINGRULESREQUEST_REPLACEBUILDIDASSIGNMENTRULE._serialized_end = ( - 29356 + 29352 ) - _UPDATEWORKERVERSIONINGRULESREQUEST_DELETEBUILDIDASSIGNMENTRULE._serialized_start = 29358 + _UPDATEWORKERVERSIONINGRULESREQUEST_DELETEBUILDIDASSIGNMENTRULE._serialized_start = 29354 _UPDATEWORKERVERSIONINGRULESREQUEST_DELETEBUILDIDASSIGNMENTRULE._serialized_end = ( - 29422 + 29418 ) - _UPDATEWORKERVERSIONINGRULESREQUEST_ADDCOMPATIBLEBUILDIDREDIRECTRULE._serialized_start = 29424 - _UPDATEWORKERVERSIONINGRULESREQUEST_ADDCOMPATIBLEBUILDIDREDIRECTRULE._serialized_end = 29530 - _UPDATEWORKERVERSIONINGRULESREQUEST_REPLACECOMPATIBLEBUILDIDREDIRECTRULE._serialized_start = 29532 - _UPDATEWORKERVERSIONINGRULESREQUEST_REPLACECOMPATIBLEBUILDIDREDIRECTRULE._serialized_end = 29642 - _UPDATEWORKERVERSIONINGRULESREQUEST_DELETECOMPATIBLEBUILDIDREDIRECTRULE._serialized_start = 29644 - _UPDATEWORKERVERSIONINGRULESREQUEST_DELETECOMPATIBLEBUILDIDREDIRECTRULE._serialized_end = 29706 - _UPDATEWORKERVERSIONINGRULESREQUEST_COMMITBUILDID._serialized_start = 29708 - _UPDATEWORKERVERSIONINGRULESREQUEST_COMMITBUILDID._serialized_end = 29763 - _UPDATEWORKERVERSIONINGRULESRESPONSE._serialized_start = 29779 - _UPDATEWORKERVERSIONINGRULESRESPONSE._serialized_end = 30031 - _GETWORKERVERSIONINGRULESREQUEST._serialized_start = 30033 - _GETWORKERVERSIONINGRULESREQUEST._serialized_end = 30105 - _GETWORKERVERSIONINGRULESRESPONSE._serialized_start = 30108 - _GETWORKERVERSIONINGRULESRESPONSE._serialized_end = 30357 - _GETWORKERTASKREACHABILITYREQUEST._serialized_start = 30360 - _GETWORKERTASKREACHABILITYREQUEST._serialized_end = 30516 - _GETWORKERTASKREACHABILITYRESPONSE._serialized_start = 30518 - _GETWORKERTASKREACHABILITYRESPONSE._serialized_end = 30632 - _UPDATEWORKFLOWEXECUTIONREQUEST._serialized_start = 30635 - _UPDATEWORKFLOWEXECUTIONREQUEST._serialized_end = 30896 - _UPDATEWORKFLOWEXECUTIONRESPONSE._serialized_start = 30899 - _UPDATEWORKFLOWEXECUTIONRESPONSE._serialized_end = 31158 - _STARTBATCHOPERATIONREQUEST._serialized_start = 31161 - _STARTBATCHOPERATIONREQUEST._serialized_end = 32173 - _STARTBATCHOPERATIONRESPONSE._serialized_start = 32175 - _STARTBATCHOPERATIONRESPONSE._serialized_end = 32204 - _STOPBATCHOPERATIONREQUEST._serialized_start = 32206 - _STOPBATCHOPERATIONREQUEST._serialized_end = 32302 - _STOPBATCHOPERATIONRESPONSE._serialized_start = 32304 - _STOPBATCHOPERATIONRESPONSE._serialized_end = 32332 - _DESCRIBEBATCHOPERATIONREQUEST._serialized_start = 32334 - _DESCRIBEBATCHOPERATIONREQUEST._serialized_end = 32400 - _DESCRIBEBATCHOPERATIONRESPONSE._serialized_start = 32403 - _DESCRIBEBATCHOPERATIONRESPONSE._serialized_end = 32805 - _LISTBATCHOPERATIONSREQUEST._serialized_start = 32807 - _LISTBATCHOPERATIONSREQUEST._serialized_end = 32898 - _LISTBATCHOPERATIONSRESPONSE._serialized_start = 32900 - _LISTBATCHOPERATIONSRESPONSE._serialized_end = 33021 - _POLLWORKFLOWEXECUTIONUPDATEREQUEST._serialized_start = 33024 - _POLLWORKFLOWEXECUTIONUPDATEREQUEST._serialized_end = 33209 - _POLLWORKFLOWEXECUTIONUPDATERESPONSE._serialized_start = 33212 - _POLLWORKFLOWEXECUTIONUPDATERESPONSE._serialized_end = 33431 - _POLLNEXUSTASKQUEUEREQUEST._serialized_start = 33434 - _POLLNEXUSTASKQUEUEREQUEST._serialized_end = 33850 - _POLLNEXUSTASKQUEUERESPONSE._serialized_start = 33853 - _POLLNEXUSTASKQUEUERESPONSE._serialized_end = 34130 - _RESPONDNEXUSTASKCOMPLETEDREQUEST._serialized_start = 34133 - _RESPONDNEXUSTASKCOMPLETEDREQUEST._serialized_end = 34300 - _RESPONDNEXUSTASKCOMPLETEDRESPONSE._serialized_start = 34302 - _RESPONDNEXUSTASKCOMPLETEDRESPONSE._serialized_end = 34337 - _RESPONDNEXUSTASKFAILEDREQUEST._serialized_start = 34340 - _RESPONDNEXUSTASKFAILEDREQUEST._serialized_end = 34560 - _RESPONDNEXUSTASKFAILEDRESPONSE._serialized_start = 34562 - _RESPONDNEXUSTASKFAILEDRESPONSE._serialized_end = 34594 - _EXECUTEMULTIOPERATIONREQUEST._serialized_start = 34597 - _EXECUTEMULTIOPERATIONREQUEST._serialized_end = 34969 - _EXECUTEMULTIOPERATIONREQUEST_OPERATION._serialized_start = 34763 - _EXECUTEMULTIOPERATIONREQUEST_OPERATION._serialized_end = 34969 - _EXECUTEMULTIOPERATIONRESPONSE._serialized_start = 34972 - _EXECUTEMULTIOPERATIONRESPONSE._serialized_end = 35304 - _EXECUTEMULTIOPERATIONRESPONSE_RESPONSE._serialized_start = 35098 - _EXECUTEMULTIOPERATIONRESPONSE_RESPONSE._serialized_end = 35304 - _UPDATEACTIVITYOPTIONSREQUEST._serialized_start = 35307 - _UPDATEACTIVITYOPTIONSREQUEST._serialized_end = 35643 - _UPDATEACTIVITYEXECUTIONOPTIONSREQUEST._serialized_start = 35646 - _UPDATEACTIVITYEXECUTIONOPTIONSREQUEST._serialized_end = 35945 - _UPDATEACTIVITYOPTIONSRESPONSE._serialized_start = 35947 - _UPDATEACTIVITYOPTIONSRESPONSE._serialized_end = 36047 - _UPDATEACTIVITYEXECUTIONOPTIONSRESPONSE._serialized_start = 36049 - _UPDATEACTIVITYEXECUTIONOPTIONSRESPONSE._serialized_end = 36158 - _PAUSEACTIVITYREQUEST._serialized_start = 36161 - _PAUSEACTIVITYREQUEST._serialized_end = 36360 - _PAUSEACTIVITYEXECUTIONREQUEST._serialized_start = 36363 - _PAUSEACTIVITYEXECUTIONREQUEST._serialized_end = 36546 - _PAUSEACTIVITYRESPONSE._serialized_start = 36548 - _PAUSEACTIVITYRESPONSE._serialized_end = 36571 - _PAUSEACTIVITYEXECUTIONRESPONSE._serialized_start = 36573 - _PAUSEACTIVITYEXECUTIONRESPONSE._serialized_end = 36605 - _UNPAUSEACTIVITYREQUEST._serialized_start = 36608 - _UNPAUSEACTIVITYREQUEST._serialized_end = 36888 - _UNPAUSEACTIVITYEXECUTIONREQUEST._serialized_start = 36891 - _UNPAUSEACTIVITYEXECUTIONREQUEST._serialized_end = 37148 - _UNPAUSEACTIVITYRESPONSE._serialized_start = 37150 - _UNPAUSEACTIVITYRESPONSE._serialized_end = 37175 - _UNPAUSEACTIVITYEXECUTIONRESPONSE._serialized_start = 37177 - _UNPAUSEACTIVITYEXECUTIONRESPONSE._serialized_end = 37211 - _RESETACTIVITYREQUEST._serialized_start = 37214 - _RESETACTIVITYREQUEST._serialized_end = 37521 - _RESETACTIVITYEXECUTIONREQUEST._serialized_start = 37524 - _RESETACTIVITYEXECUTIONREQUEST._serialized_end = 37794 - _RESETACTIVITYRESPONSE._serialized_start = 37796 - _RESETACTIVITYRESPONSE._serialized_end = 37819 - _RESETACTIVITYEXECUTIONRESPONSE._serialized_start = 37821 - _RESETACTIVITYEXECUTIONRESPONSE._serialized_end = 37853 - _UPDATEWORKFLOWEXECUTIONOPTIONSREQUEST._serialized_start = 37856 - _UPDATEWORKFLOWEXECUTIONOPTIONSREQUEST._serialized_end = 38140 - _UPDATEWORKFLOWEXECUTIONOPTIONSRESPONSE._serialized_start = 38143 - _UPDATEWORKFLOWEXECUTIONOPTIONSRESPONSE._serialized_end = 38271 - _DESCRIBEDEPLOYMENTREQUEST._serialized_start = 38273 - _DESCRIBEDEPLOYMENTREQUEST._serialized_end = 38379 - _DESCRIBEDEPLOYMENTRESPONSE._serialized_start = 38381 - _DESCRIBEDEPLOYMENTRESPONSE._serialized_end = 38478 - _DESCRIBEWORKERDEPLOYMENTVERSIONREQUEST._serialized_start = 38481 - _DESCRIBEWORKERDEPLOYMENTVERSIONREQUEST._serialized_end = 38675 - _DESCRIBEWORKERDEPLOYMENTVERSIONRESPONSE._serialized_start = 38678 - _DESCRIBEWORKERDEPLOYMENTVERSIONRESPONSE._serialized_end = 39330 - _DESCRIBEWORKERDEPLOYMENTVERSIONRESPONSE_VERSIONTASKQUEUE._serialized_start = 38939 - _DESCRIBEWORKERDEPLOYMENTVERSIONRESPONSE_VERSIONTASKQUEUE._serialized_end = 39330 - _DESCRIBEWORKERDEPLOYMENTVERSIONRESPONSE_VERSIONTASKQUEUE_STATSBYPRIORITYKEYENTRY._serialized_start = 23313 - _DESCRIBEWORKERDEPLOYMENTVERSIONRESPONSE_VERSIONTASKQUEUE_STATSBYPRIORITYKEYENTRY._serialized_end = 23413 - _DESCRIBEWORKERDEPLOYMENTREQUEST._serialized_start = 39332 - _DESCRIBEWORKERDEPLOYMENTREQUEST._serialized_end = 39409 - _DESCRIBEWORKERDEPLOYMENTRESPONSE._serialized_start = 39412 - _DESCRIBEWORKERDEPLOYMENTRESPONSE._serialized_end = 39552 - _LISTDEPLOYMENTSREQUEST._serialized_start = 39554 - _LISTDEPLOYMENTSREQUEST._serialized_end = 39662 - _LISTDEPLOYMENTSRESPONSE._serialized_start = 39664 - _LISTDEPLOYMENTSRESPONSE._serialized_end = 39783 - _SETCURRENTDEPLOYMENTREQUEST._serialized_start = 39786 - _SETCURRENTDEPLOYMENTREQUEST._serialized_end = 39991 - _SETCURRENTDEPLOYMENTRESPONSE._serialized_start = 39994 - _SETCURRENTDEPLOYMENTRESPONSE._serialized_end = 40179 - _SETWORKERDEPLOYMENTCURRENTVERSIONREQUEST._serialized_start = 40182 - _SETWORKERDEPLOYMENTCURRENTVERSIONREQUEST._serialized_end = 40411 - _SETWORKERDEPLOYMENTCURRENTVERSIONRESPONSE._serialized_start = 40414 - _SETWORKERDEPLOYMENTCURRENTVERSIONRESPONSE._serialized_end = 40605 - _SETWORKERDEPLOYMENTRAMPINGVERSIONREQUEST._serialized_start = 40608 - _SETWORKERDEPLOYMENTRAMPINGVERSIONREQUEST._serialized_end = 40857 - _SETWORKERDEPLOYMENTRAMPINGVERSIONRESPONSE._serialized_start = 40860 - _SETWORKERDEPLOYMENTRAMPINGVERSIONRESPONSE._serialized_end = 41084 - _CREATEWORKERDEPLOYMENTREQUEST._serialized_start = 41086 - _CREATEWORKERDEPLOYMENTREQUEST._serialized_end = 41199 - _CREATEWORKERDEPLOYMENTRESPONSE._serialized_start = 41201 - _CREATEWORKERDEPLOYMENTRESPONSE._serialized_end = 41257 - _LISTWORKERDEPLOYMENTSREQUEST._serialized_start = 41259 - _LISTWORKERDEPLOYMENTSREQUEST._serialized_end = 41352 - _LISTWORKERDEPLOYMENTSRESPONSE._serialized_start = 41355 - _LISTWORKERDEPLOYMENTSRESPONSE._serialized_end = 42026 - _LISTWORKERDEPLOYMENTSRESPONSE_WORKERDEPLOYMENTSUMMARY._serialized_start = 41530 - _LISTWORKERDEPLOYMENTSRESPONSE_WORKERDEPLOYMENTSUMMARY._serialized_end = 42026 - _CREATEWORKERDEPLOYMENTVERSIONREQUEST._serialized_start = 42029 - _CREATEWORKERDEPLOYMENTVERSIONREQUEST._serialized_end = 42269 - _CREATEWORKERDEPLOYMENTVERSIONRESPONSE._serialized_start = 42271 - _CREATEWORKERDEPLOYMENTVERSIONRESPONSE._serialized_end = 42310 - _DELETEWORKERDEPLOYMENTVERSIONREQUEST._serialized_start = 42313 - _DELETEWORKERDEPLOYMENTVERSIONREQUEST._serialized_end = 42513 - _DELETEWORKERDEPLOYMENTVERSIONRESPONSE._serialized_start = 42515 - _DELETEWORKERDEPLOYMENTVERSIONRESPONSE._serialized_end = 42554 - _DELETEWORKERDEPLOYMENTREQUEST._serialized_start = 42556 - _DELETEWORKERDEPLOYMENTREQUEST._serialized_end = 42649 - _DELETEWORKERDEPLOYMENTRESPONSE._serialized_start = 42651 - _DELETEWORKERDEPLOYMENTRESPONSE._serialized_end = 42683 - _UPDATEWORKERDEPLOYMENTVERSIONCOMPUTECONFIGREQUEST._serialized_start = 42686 - _UPDATEWORKERDEPLOYMENTVERSIONCOMPUTECONFIGREQUEST._serialized_end = 43202 - _UPDATEWORKERDEPLOYMENTVERSIONCOMPUTECONFIGREQUEST_COMPUTECONFIGSCALINGGROUPSENTRY._serialized_start = 43079 - _UPDATEWORKERDEPLOYMENTVERSIONCOMPUTECONFIGREQUEST_COMPUTECONFIGSCALINGGROUPSENTRY._serialized_end = 43202 - _UPDATEWORKERDEPLOYMENTVERSIONCOMPUTECONFIGRESPONSE._serialized_start = 43204 - _UPDATEWORKERDEPLOYMENTVERSIONCOMPUTECONFIGRESPONSE._serialized_end = 43256 - _VALIDATEWORKERDEPLOYMENTVERSIONCOMPUTECONFIGREQUEST._serialized_start = 43259 - _VALIDATEWORKERDEPLOYMENTVERSIONCOMPUTECONFIGREQUEST._serialized_end = 43759 - _VALIDATEWORKERDEPLOYMENTVERSIONCOMPUTECONFIGREQUEST_COMPUTECONFIGSCALINGGROUPSENTRY._serialized_start = 43079 - _VALIDATEWORKERDEPLOYMENTVERSIONCOMPUTECONFIGREQUEST_COMPUTECONFIGSCALINGGROUPSENTRY._serialized_end = 43202 - _VALIDATEWORKERDEPLOYMENTVERSIONCOMPUTECONFIGRESPONSE._serialized_start = 43761 - _VALIDATEWORKERDEPLOYMENTVERSIONCOMPUTECONFIGRESPONSE._serialized_end = 43815 - _UPDATEWORKERDEPLOYMENTVERSIONMETADATAREQUEST._serialized_start = 43818 - _UPDATEWORKERDEPLOYMENTVERSIONMETADATAREQUEST._serialized_end = 44236 - _UPDATEWORKERDEPLOYMENTVERSIONMETADATAREQUEST_UPSERTENTRIESENTRY._serialized_start = 44151 + _UPDATEWORKERVERSIONINGRULESREQUEST_ADDCOMPATIBLEBUILDIDREDIRECTRULE._serialized_start = 29420 + _UPDATEWORKERVERSIONINGRULESREQUEST_ADDCOMPATIBLEBUILDIDREDIRECTRULE._serialized_end = 29526 + _UPDATEWORKERVERSIONINGRULESREQUEST_REPLACECOMPATIBLEBUILDIDREDIRECTRULE._serialized_start = 29528 + _UPDATEWORKERVERSIONINGRULESREQUEST_REPLACECOMPATIBLEBUILDIDREDIRECTRULE._serialized_end = 29638 + _UPDATEWORKERVERSIONINGRULESREQUEST_DELETECOMPATIBLEBUILDIDREDIRECTRULE._serialized_start = 29640 + _UPDATEWORKERVERSIONINGRULESREQUEST_DELETECOMPATIBLEBUILDIDREDIRECTRULE._serialized_end = 29702 + _UPDATEWORKERVERSIONINGRULESREQUEST_COMMITBUILDID._serialized_start = 29704 + _UPDATEWORKERVERSIONINGRULESREQUEST_COMMITBUILDID._serialized_end = 29759 + _UPDATEWORKERVERSIONINGRULESRESPONSE._serialized_start = 29775 + _UPDATEWORKERVERSIONINGRULESRESPONSE._serialized_end = 30027 + _GETWORKERVERSIONINGRULESREQUEST._serialized_start = 30029 + _GETWORKERVERSIONINGRULESREQUEST._serialized_end = 30101 + _GETWORKERVERSIONINGRULESRESPONSE._serialized_start = 30104 + _GETWORKERVERSIONINGRULESRESPONSE._serialized_end = 30353 + _GETWORKERTASKREACHABILITYREQUEST._serialized_start = 30356 + _GETWORKERTASKREACHABILITYREQUEST._serialized_end = 30512 + _GETWORKERTASKREACHABILITYRESPONSE._serialized_start = 30514 + _GETWORKERTASKREACHABILITYRESPONSE._serialized_end = 30628 + _UPDATEWORKFLOWEXECUTIONREQUEST._serialized_start = 30631 + _UPDATEWORKFLOWEXECUTIONREQUEST._serialized_end = 30892 + _UPDATEWORKFLOWEXECUTIONRESPONSE._serialized_start = 30895 + _UPDATEWORKFLOWEXECUTIONRESPONSE._serialized_end = 31154 + _STARTBATCHOPERATIONREQUEST._serialized_start = 31157 + _STARTBATCHOPERATIONREQUEST._serialized_end = 32169 + _STARTBATCHOPERATIONRESPONSE._serialized_start = 32171 + _STARTBATCHOPERATIONRESPONSE._serialized_end = 32200 + _STOPBATCHOPERATIONREQUEST._serialized_start = 32202 + _STOPBATCHOPERATIONREQUEST._serialized_end = 32298 + _STOPBATCHOPERATIONRESPONSE._serialized_start = 32300 + _STOPBATCHOPERATIONRESPONSE._serialized_end = 32328 + _DESCRIBEBATCHOPERATIONREQUEST._serialized_start = 32330 + _DESCRIBEBATCHOPERATIONREQUEST._serialized_end = 32396 + _DESCRIBEBATCHOPERATIONRESPONSE._serialized_start = 32399 + _DESCRIBEBATCHOPERATIONRESPONSE._serialized_end = 32801 + _LISTBATCHOPERATIONSREQUEST._serialized_start = 32803 + _LISTBATCHOPERATIONSREQUEST._serialized_end = 32894 + _LISTBATCHOPERATIONSRESPONSE._serialized_start = 32896 + _LISTBATCHOPERATIONSRESPONSE._serialized_end = 33017 + _POLLWORKFLOWEXECUTIONUPDATEREQUEST._serialized_start = 33020 + _POLLWORKFLOWEXECUTIONUPDATEREQUEST._serialized_end = 33205 + _POLLWORKFLOWEXECUTIONUPDATERESPONSE._serialized_start = 33208 + _POLLWORKFLOWEXECUTIONUPDATERESPONSE._serialized_end = 33427 + _POLLNEXUSTASKQUEUEREQUEST._serialized_start = 33430 + _POLLNEXUSTASKQUEUEREQUEST._serialized_end = 33846 + _POLLNEXUSTASKQUEUERESPONSE._serialized_start = 33849 + _POLLNEXUSTASKQUEUERESPONSE._serialized_end = 34126 + _RESPONDNEXUSTASKCOMPLETEDREQUEST._serialized_start = 34129 + _RESPONDNEXUSTASKCOMPLETEDREQUEST._serialized_end = 34296 + _RESPONDNEXUSTASKCOMPLETEDRESPONSE._serialized_start = 34298 + _RESPONDNEXUSTASKCOMPLETEDRESPONSE._serialized_end = 34333 + _RESPONDNEXUSTASKFAILEDREQUEST._serialized_start = 34336 + _RESPONDNEXUSTASKFAILEDREQUEST._serialized_end = 34556 + _RESPONDNEXUSTASKFAILEDRESPONSE._serialized_start = 34558 + _RESPONDNEXUSTASKFAILEDRESPONSE._serialized_end = 34590 + _EXECUTEMULTIOPERATIONREQUEST._serialized_start = 34593 + _EXECUTEMULTIOPERATIONREQUEST._serialized_end = 34965 + _EXECUTEMULTIOPERATIONREQUEST_OPERATION._serialized_start = 34759 + _EXECUTEMULTIOPERATIONREQUEST_OPERATION._serialized_end = 34965 + _EXECUTEMULTIOPERATIONRESPONSE._serialized_start = 34968 + _EXECUTEMULTIOPERATIONRESPONSE._serialized_end = 35300 + _EXECUTEMULTIOPERATIONRESPONSE_RESPONSE._serialized_start = 35094 + _EXECUTEMULTIOPERATIONRESPONSE_RESPONSE._serialized_end = 35300 + _UPDATEACTIVITYOPTIONSREQUEST._serialized_start = 35303 + _UPDATEACTIVITYOPTIONSREQUEST._serialized_end = 35639 + _UPDATEACTIVITYEXECUTIONOPTIONSREQUEST._serialized_start = 35642 + _UPDATEACTIVITYEXECUTIONOPTIONSREQUEST._serialized_end = 35941 + _UPDATEACTIVITYOPTIONSRESPONSE._serialized_start = 35943 + _UPDATEACTIVITYOPTIONSRESPONSE._serialized_end = 36043 + _UPDATEACTIVITYEXECUTIONOPTIONSRESPONSE._serialized_start = 36045 + _UPDATEACTIVITYEXECUTIONOPTIONSRESPONSE._serialized_end = 36154 + _PAUSEACTIVITYREQUEST._serialized_start = 36157 + _PAUSEACTIVITYREQUEST._serialized_end = 36356 + _PAUSEACTIVITYEXECUTIONREQUEST._serialized_start = 36359 + _PAUSEACTIVITYEXECUTIONREQUEST._serialized_end = 36542 + _PAUSEACTIVITYRESPONSE._serialized_start = 36544 + _PAUSEACTIVITYRESPONSE._serialized_end = 36567 + _PAUSEACTIVITYEXECUTIONRESPONSE._serialized_start = 36569 + _PAUSEACTIVITYEXECUTIONRESPONSE._serialized_end = 36601 + _UNPAUSEACTIVITYREQUEST._serialized_start = 36604 + _UNPAUSEACTIVITYREQUEST._serialized_end = 36884 + _UNPAUSEACTIVITYEXECUTIONREQUEST._serialized_start = 36887 + _UNPAUSEACTIVITYEXECUTIONREQUEST._serialized_end = 37144 + _UNPAUSEACTIVITYRESPONSE._serialized_start = 37146 + _UNPAUSEACTIVITYRESPONSE._serialized_end = 37171 + _UNPAUSEACTIVITYEXECUTIONRESPONSE._serialized_start = 37173 + _UNPAUSEACTIVITYEXECUTIONRESPONSE._serialized_end = 37207 + _RESETACTIVITYREQUEST._serialized_start = 37210 + _RESETACTIVITYREQUEST._serialized_end = 37517 + _RESETACTIVITYEXECUTIONREQUEST._serialized_start = 37520 + _RESETACTIVITYEXECUTIONREQUEST._serialized_end = 37790 + _RESETACTIVITYRESPONSE._serialized_start = 37792 + _RESETACTIVITYRESPONSE._serialized_end = 37815 + _RESETACTIVITYEXECUTIONRESPONSE._serialized_start = 37817 + _RESETACTIVITYEXECUTIONRESPONSE._serialized_end = 37849 + _UPDATEWORKFLOWEXECUTIONOPTIONSREQUEST._serialized_start = 37852 + _UPDATEWORKFLOWEXECUTIONOPTIONSREQUEST._serialized_end = 38136 + _UPDATEWORKFLOWEXECUTIONOPTIONSRESPONSE._serialized_start = 38139 + _UPDATEWORKFLOWEXECUTIONOPTIONSRESPONSE._serialized_end = 38316 + _DESCRIBEDEPLOYMENTREQUEST._serialized_start = 38318 + _DESCRIBEDEPLOYMENTREQUEST._serialized_end = 38424 + _DESCRIBEDEPLOYMENTRESPONSE._serialized_start = 38426 + _DESCRIBEDEPLOYMENTRESPONSE._serialized_end = 38523 + _DESCRIBEWORKERDEPLOYMENTVERSIONREQUEST._serialized_start = 38526 + _DESCRIBEWORKERDEPLOYMENTVERSIONREQUEST._serialized_end = 38720 + _DESCRIBEWORKERDEPLOYMENTVERSIONRESPONSE._serialized_start = 38723 + _DESCRIBEWORKERDEPLOYMENTVERSIONRESPONSE._serialized_end = 39375 + _DESCRIBEWORKERDEPLOYMENTVERSIONRESPONSE_VERSIONTASKQUEUE._serialized_start = 38984 + _DESCRIBEWORKERDEPLOYMENTVERSIONRESPONSE_VERSIONTASKQUEUE._serialized_end = 39375 + _DESCRIBEWORKERDEPLOYMENTVERSIONRESPONSE_VERSIONTASKQUEUE_STATSBYPRIORITYKEYENTRY._serialized_start = 23309 + _DESCRIBEWORKERDEPLOYMENTVERSIONRESPONSE_VERSIONTASKQUEUE_STATSBYPRIORITYKEYENTRY._serialized_end = 23409 + _DESCRIBEWORKERDEPLOYMENTREQUEST._serialized_start = 39377 + _DESCRIBEWORKERDEPLOYMENTREQUEST._serialized_end = 39454 + _DESCRIBEWORKERDEPLOYMENTRESPONSE._serialized_start = 39457 + _DESCRIBEWORKERDEPLOYMENTRESPONSE._serialized_end = 39597 + _LISTDEPLOYMENTSREQUEST._serialized_start = 39599 + _LISTDEPLOYMENTSREQUEST._serialized_end = 39707 + _LISTDEPLOYMENTSRESPONSE._serialized_start = 39709 + _LISTDEPLOYMENTSRESPONSE._serialized_end = 39828 + _SETCURRENTDEPLOYMENTREQUEST._serialized_start = 39831 + _SETCURRENTDEPLOYMENTREQUEST._serialized_end = 40036 + _SETCURRENTDEPLOYMENTRESPONSE._serialized_start = 40039 + _SETCURRENTDEPLOYMENTRESPONSE._serialized_end = 40224 + _SETWORKERDEPLOYMENTCURRENTVERSIONREQUEST._serialized_start = 40227 + _SETWORKERDEPLOYMENTCURRENTVERSIONREQUEST._serialized_end = 40456 + _SETWORKERDEPLOYMENTCURRENTVERSIONRESPONSE._serialized_start = 40459 + _SETWORKERDEPLOYMENTCURRENTVERSIONRESPONSE._serialized_end = 40650 + _SETWORKERDEPLOYMENTRAMPINGVERSIONREQUEST._serialized_start = 40653 + _SETWORKERDEPLOYMENTRAMPINGVERSIONREQUEST._serialized_end = 40902 + _SETWORKERDEPLOYMENTRAMPINGVERSIONRESPONSE._serialized_start = 40905 + _SETWORKERDEPLOYMENTRAMPINGVERSIONRESPONSE._serialized_end = 41129 + _CREATEWORKERDEPLOYMENTREQUEST._serialized_start = 41131 + _CREATEWORKERDEPLOYMENTREQUEST._serialized_end = 41244 + _CREATEWORKERDEPLOYMENTRESPONSE._serialized_start = 41246 + _CREATEWORKERDEPLOYMENTRESPONSE._serialized_end = 41302 + _LISTWORKERDEPLOYMENTSREQUEST._serialized_start = 41304 + _LISTWORKERDEPLOYMENTSREQUEST._serialized_end = 41397 + _LISTWORKERDEPLOYMENTSRESPONSE._serialized_start = 41400 + _LISTWORKERDEPLOYMENTSRESPONSE._serialized_end = 42071 + _LISTWORKERDEPLOYMENTSRESPONSE_WORKERDEPLOYMENTSUMMARY._serialized_start = 41575 + _LISTWORKERDEPLOYMENTSRESPONSE_WORKERDEPLOYMENTSUMMARY._serialized_end = 42071 + _CREATEWORKERDEPLOYMENTVERSIONREQUEST._serialized_start = 42074 + _CREATEWORKERDEPLOYMENTVERSIONREQUEST._serialized_end = 42314 + _CREATEWORKERDEPLOYMENTVERSIONRESPONSE._serialized_start = 42316 + _CREATEWORKERDEPLOYMENTVERSIONRESPONSE._serialized_end = 42355 + _DELETEWORKERDEPLOYMENTVERSIONREQUEST._serialized_start = 42358 + _DELETEWORKERDEPLOYMENTVERSIONREQUEST._serialized_end = 42558 + _DELETEWORKERDEPLOYMENTVERSIONRESPONSE._serialized_start = 42560 + _DELETEWORKERDEPLOYMENTVERSIONRESPONSE._serialized_end = 42599 + _DELETEWORKERDEPLOYMENTREQUEST._serialized_start = 42601 + _DELETEWORKERDEPLOYMENTREQUEST._serialized_end = 42694 + _DELETEWORKERDEPLOYMENTRESPONSE._serialized_start = 42696 + _DELETEWORKERDEPLOYMENTRESPONSE._serialized_end = 42728 + _UPDATEWORKERDEPLOYMENTVERSIONCOMPUTECONFIGREQUEST._serialized_start = 42731 + _UPDATEWORKERDEPLOYMENTVERSIONCOMPUTECONFIGREQUEST._serialized_end = 43247 + _UPDATEWORKERDEPLOYMENTVERSIONCOMPUTECONFIGREQUEST_COMPUTECONFIGSCALINGGROUPSENTRY._serialized_start = 43124 + _UPDATEWORKERDEPLOYMENTVERSIONCOMPUTECONFIGREQUEST_COMPUTECONFIGSCALINGGROUPSENTRY._serialized_end = 43247 + _UPDATEWORKERDEPLOYMENTVERSIONCOMPUTECONFIGRESPONSE._serialized_start = 43249 + _UPDATEWORKERDEPLOYMENTVERSIONCOMPUTECONFIGRESPONSE._serialized_end = 43301 + _VALIDATEWORKERDEPLOYMENTVERSIONCOMPUTECONFIGREQUEST._serialized_start = 43304 + _VALIDATEWORKERDEPLOYMENTVERSIONCOMPUTECONFIGREQUEST._serialized_end = 43804 + _VALIDATEWORKERDEPLOYMENTVERSIONCOMPUTECONFIGREQUEST_COMPUTECONFIGSCALINGGROUPSENTRY._serialized_start = 43124 + _VALIDATEWORKERDEPLOYMENTVERSIONCOMPUTECONFIGREQUEST_COMPUTECONFIGSCALINGGROUPSENTRY._serialized_end = 43247 + _VALIDATEWORKERDEPLOYMENTVERSIONCOMPUTECONFIGRESPONSE._serialized_start = 43806 + _VALIDATEWORKERDEPLOYMENTVERSIONCOMPUTECONFIGRESPONSE._serialized_end = 43860 + _UPDATEWORKERDEPLOYMENTVERSIONMETADATAREQUEST._serialized_start = 43863 + _UPDATEWORKERDEPLOYMENTVERSIONMETADATAREQUEST._serialized_end = 44281 + _UPDATEWORKERDEPLOYMENTVERSIONMETADATAREQUEST_UPSERTENTRIESENTRY._serialized_start = 44196 _UPDATEWORKERDEPLOYMENTVERSIONMETADATAREQUEST_UPSERTENTRIESENTRY._serialized_end = ( - 44236 + 44281 ) - _UPDATEWORKERDEPLOYMENTVERSIONMETADATARESPONSE._serialized_start = 44238 - _UPDATEWORKERDEPLOYMENTVERSIONMETADATARESPONSE._serialized_end = 44348 - _SETWORKERDEPLOYMENTMANAGERREQUEST._serialized_start = 44351 - _SETWORKERDEPLOYMENTMANAGERREQUEST._serialized_end = 44540 - _SETWORKERDEPLOYMENTMANAGERRESPONSE._serialized_start = 44542 - _SETWORKERDEPLOYMENTMANAGERRESPONSE._serialized_end = 44641 - _GETCURRENTDEPLOYMENTREQUEST._serialized_start = 44643 - _GETCURRENTDEPLOYMENTREQUEST._serialized_end = 44712 - _GETCURRENTDEPLOYMENTRESPONSE._serialized_start = 44714 - _GETCURRENTDEPLOYMENTRESPONSE._serialized_end = 44821 - _GETDEPLOYMENTREACHABILITYREQUEST._serialized_start = 44823 - _GETDEPLOYMENTREACHABILITYREQUEST._serialized_end = 44936 - _GETDEPLOYMENTREACHABILITYRESPONSE._serialized_start = 44939 - _GETDEPLOYMENTREACHABILITYRESPONSE._serialized_end = 45166 - _CREATEWORKFLOWRULEREQUEST._serialized_start = 45169 - _CREATEWORKFLOWRULEREQUEST._serialized_end = 45349 - _CREATEWORKFLOWRULERESPONSE._serialized_start = 45351 - _CREATEWORKFLOWRULERESPONSE._serialized_end = 45446 - _DESCRIBEWORKFLOWRULEREQUEST._serialized_start = 45448 - _DESCRIBEWORKFLOWRULEREQUEST._serialized_end = 45513 - _DESCRIBEWORKFLOWRULERESPONSE._serialized_start = 45515 - _DESCRIBEWORKFLOWRULERESPONSE._serialized_end = 45596 - _DELETEWORKFLOWRULEREQUEST._serialized_start = 45598 - _DELETEWORKFLOWRULEREQUEST._serialized_end = 45661 - _DELETEWORKFLOWRULERESPONSE._serialized_start = 45663 - _DELETEWORKFLOWRULERESPONSE._serialized_end = 45691 - _LISTWORKFLOWRULESREQUEST._serialized_start = 45693 - _LISTWORKFLOWRULESREQUEST._serialized_end = 45763 - _LISTWORKFLOWRULESRESPONSE._serialized_start = 45765 - _LISTWORKFLOWRULESRESPONSE._serialized_end = 45869 - _TRIGGERWORKFLOWRULEREQUEST._serialized_start = 45872 - _TRIGGERWORKFLOWRULEREQUEST._serialized_end = 46078 - _TRIGGERWORKFLOWRULERESPONSE._serialized_start = 46080 - _TRIGGERWORKFLOWRULERESPONSE._serialized_end = 46126 - _RECORDWORKERHEARTBEATREQUEST._serialized_start = 46129 - _RECORDWORKERHEARTBEATREQUEST._serialized_end = 46284 - _RECORDWORKERHEARTBEATRESPONSE._serialized_start = 46286 - _RECORDWORKERHEARTBEATRESPONSE._serialized_end = 46317 - _LISTWORKERSREQUEST._serialized_start = 46320 - _LISTWORKERSREQUEST._serialized_end = 46450 - _LISTWORKERSRESPONSE._serialized_start = 46453 - _LISTWORKERSRESPONSE._serialized_end = 46618 - _UPDATETASKQUEUECONFIGREQUEST._serialized_start = 46621 - _UPDATETASKQUEUECONFIGREQUEST._serialized_end = 47346 - _UPDATETASKQUEUECONFIGREQUEST_RATELIMITUPDATE._serialized_start = 47188 - _UPDATETASKQUEUECONFIGREQUEST_RATELIMITUPDATE._serialized_end = 47279 + _UPDATEWORKERDEPLOYMENTVERSIONMETADATARESPONSE._serialized_start = 44283 + _UPDATEWORKERDEPLOYMENTVERSIONMETADATARESPONSE._serialized_end = 44393 + _SETWORKERDEPLOYMENTMANAGERREQUEST._serialized_start = 44396 + _SETWORKERDEPLOYMENTMANAGERREQUEST._serialized_end = 44585 + _SETWORKERDEPLOYMENTMANAGERRESPONSE._serialized_start = 44587 + _SETWORKERDEPLOYMENTMANAGERRESPONSE._serialized_end = 44686 + _GETCURRENTDEPLOYMENTREQUEST._serialized_start = 44688 + _GETCURRENTDEPLOYMENTREQUEST._serialized_end = 44757 + _GETCURRENTDEPLOYMENTRESPONSE._serialized_start = 44759 + _GETCURRENTDEPLOYMENTRESPONSE._serialized_end = 44866 + _GETDEPLOYMENTREACHABILITYREQUEST._serialized_start = 44868 + _GETDEPLOYMENTREACHABILITYREQUEST._serialized_end = 44981 + _GETDEPLOYMENTREACHABILITYRESPONSE._serialized_start = 44984 + _GETDEPLOYMENTREACHABILITYRESPONSE._serialized_end = 45211 + _CREATEWORKFLOWRULEREQUEST._serialized_start = 45214 + _CREATEWORKFLOWRULEREQUEST._serialized_end = 45394 + _CREATEWORKFLOWRULERESPONSE._serialized_start = 45396 + _CREATEWORKFLOWRULERESPONSE._serialized_end = 45491 + _DESCRIBEWORKFLOWRULEREQUEST._serialized_start = 45493 + _DESCRIBEWORKFLOWRULEREQUEST._serialized_end = 45558 + _DESCRIBEWORKFLOWRULERESPONSE._serialized_start = 45560 + _DESCRIBEWORKFLOWRULERESPONSE._serialized_end = 45641 + _DELETEWORKFLOWRULEREQUEST._serialized_start = 45643 + _DELETEWORKFLOWRULEREQUEST._serialized_end = 45706 + _DELETEWORKFLOWRULERESPONSE._serialized_start = 45708 + _DELETEWORKFLOWRULERESPONSE._serialized_end = 45736 + _LISTWORKFLOWRULESREQUEST._serialized_start = 45738 + _LISTWORKFLOWRULESREQUEST._serialized_end = 45808 + _LISTWORKFLOWRULESRESPONSE._serialized_start = 45810 + _LISTWORKFLOWRULESRESPONSE._serialized_end = 45914 + _TRIGGERWORKFLOWRULEREQUEST._serialized_start = 45917 + _TRIGGERWORKFLOWRULEREQUEST._serialized_end = 46123 + _TRIGGERWORKFLOWRULERESPONSE._serialized_start = 46125 + _TRIGGERWORKFLOWRULERESPONSE._serialized_end = 46171 + _RECORDWORKERHEARTBEATREQUEST._serialized_start = 46174 + _RECORDWORKERHEARTBEATREQUEST._serialized_end = 46329 + _RECORDWORKERHEARTBEATRESPONSE._serialized_start = 46331 + _RECORDWORKERHEARTBEATRESPONSE._serialized_end = 46362 + _LISTWORKERSREQUEST._serialized_start = 46365 + _LISTWORKERSREQUEST._serialized_end = 46495 + _LISTWORKERSRESPONSE._serialized_start = 46498 + _LISTWORKERSRESPONSE._serialized_end = 46663 + _UPDATETASKQUEUECONFIGREQUEST._serialized_start = 46666 + _UPDATETASKQUEUECONFIGREQUEST._serialized_end = 47391 + _UPDATETASKQUEUECONFIGREQUEST_RATELIMITUPDATE._serialized_start = 47233 + _UPDATETASKQUEUECONFIGREQUEST_RATELIMITUPDATE._serialized_end = 47324 _UPDATETASKQUEUECONFIGREQUEST_SETFAIRNESSWEIGHTOVERRIDESENTRY._serialized_start = ( - 47281 + 47326 ) _UPDATETASKQUEUECONFIGREQUEST_SETFAIRNESSWEIGHTOVERRIDESENTRY._serialized_end = ( - 47346 + 47391 ) - _UPDATETASKQUEUECONFIGRESPONSE._serialized_start = 47348 - _UPDATETASKQUEUECONFIGRESPONSE._serialized_end = 47439 - _FETCHWORKERCONFIGREQUEST._serialized_start = 47442 - _FETCHWORKERCONFIGREQUEST._serialized_end = 47600 - _FETCHWORKERCONFIGRESPONSE._serialized_start = 47602 - _FETCHWORKERCONFIGRESPONSE._serialized_end = 47687 - _UPDATEWORKERCONFIGREQUEST._serialized_start = 47690 - _UPDATEWORKERCONFIGREQUEST._serialized_end = 47956 - _UPDATEWORKERCONFIGRESPONSE._serialized_start = 47958 - _UPDATEWORKERCONFIGRESPONSE._serialized_end = 48058 - _DESCRIBEWORKERREQUEST._serialized_start = 48060 - _DESCRIBEWORKERREQUEST._serialized_end = 48131 - _DESCRIBEWORKERRESPONSE._serialized_start = 48133 - _DESCRIBEWORKERRESPONSE._serialized_end = 48214 - _PAUSEWORKFLOWEXECUTIONREQUEST._serialized_start = 48217 - _PAUSEWORKFLOWEXECUTIONREQUEST._serialized_end = 48358 - _PAUSEWORKFLOWEXECUTIONRESPONSE._serialized_start = 48360 - _PAUSEWORKFLOWEXECUTIONRESPONSE._serialized_end = 48392 - _UNPAUSEWORKFLOWEXECUTIONREQUEST._serialized_start = 48395 - _UNPAUSEWORKFLOWEXECUTIONREQUEST._serialized_end = 48538 - _UNPAUSEWORKFLOWEXECUTIONRESPONSE._serialized_start = 48540 - _UNPAUSEWORKFLOWEXECUTIONRESPONSE._serialized_end = 48574 - _STARTACTIVITYEXECUTIONREQUEST._serialized_start = 48577 - _STARTACTIVITYEXECUTIONREQUEST._serialized_end = 49754 - _STARTACTIVITYEXECUTIONRESPONSE._serialized_start = 49756 - _STARTACTIVITYEXECUTIONRESPONSE._serialized_end = 49865 - _DESCRIBEACTIVITYEXECUTIONREQUEST._serialized_start = 49868 - _DESCRIBEACTIVITYEXECUTIONREQUEST._serialized_end = 50096 - _DESCRIBEACTIVITYEXECUTIONRESPONSE._serialized_start = 50099 - _DESCRIBEACTIVITYEXECUTIONRESPONSE._serialized_end = 50415 - _POLLACTIVITYEXECUTIONREQUEST._serialized_start = 50417 - _POLLACTIVITYEXECUTIONREQUEST._serialized_end = 50503 - _POLLACTIVITYEXECUTIONRESPONSE._serialized_start = 50505 - _POLLACTIVITYEXECUTIONRESPONSE._serialized_end = 50621 - _LISTACTIVITYEXECUTIONSREQUEST._serialized_start = 50623 - _LISTACTIVITYEXECUTIONSREQUEST._serialized_end = 50732 - _LISTACTIVITYEXECUTIONSRESPONSE._serialized_start = 50735 - _LISTACTIVITYEXECUTIONSRESPONSE._serialized_end = 50865 - _STARTNEXUSOPERATIONEXECUTIONREQUEST._serialized_start = 50868 - _STARTNEXUSOPERATIONEXECUTIONREQUEST._serialized_end = 51717 - _STARTNEXUSOPERATIONEXECUTIONREQUEST_NEXUSHEADERENTRY._serialized_start = 51667 - _STARTNEXUSOPERATIONEXECUTIONREQUEST_NEXUSHEADERENTRY._serialized_end = 51717 - _STARTNEXUSOPERATIONEXECUTIONRESPONSE._serialized_start = 51719 - _STARTNEXUSOPERATIONEXECUTIONRESPONSE._serialized_end = 51790 - _DESCRIBENEXUSOPERATIONEXECUTIONREQUEST._serialized_start = 51793 - _DESCRIBENEXUSOPERATIONEXECUTIONREQUEST._serialized_end = 51963 - _DESCRIBENEXUSOPERATIONEXECUTIONRESPONSE._serialized_start = 51966 - _DESCRIBENEXUSOPERATIONEXECUTIONRESPONSE._serialized_end = 52277 - _POLLNEXUSOPERATIONEXECUTIONREQUEST._serialized_start = 52280 - _POLLNEXUSOPERATIONEXECUTIONREQUEST._serialized_end = 52441 - _POLLNEXUSOPERATIONEXECUTIONRESPONSE._serialized_start = 52444 - _POLLNEXUSOPERATIONEXECUTIONRESPONSE._serialized_end = 52705 - _LISTNEXUSOPERATIONEXECUTIONSREQUEST._serialized_start = 52707 - _LISTNEXUSOPERATIONEXECUTIONSREQUEST._serialized_end = 52822 - _LISTNEXUSOPERATIONEXECUTIONSRESPONSE._serialized_start = 52825 - _LISTNEXUSOPERATIONEXECUTIONSRESPONSE._serialized_end = 52964 - _COUNTACTIVITYEXECUTIONSREQUEST._serialized_start = 52966 - _COUNTACTIVITYEXECUTIONSREQUEST._serialized_end = 53032 - _COUNTACTIVITYEXECUTIONSRESPONSE._serialized_start = 53035 - _COUNTACTIVITYEXECUTIONSRESPONSE._serialized_end = 53272 - _COUNTACTIVITYEXECUTIONSRESPONSE_AGGREGATIONGROUP._serialized_start = 19751 - _COUNTACTIVITYEXECUTIONSRESPONSE_AGGREGATIONGROUP._serialized_end = 19839 - _COUNTNEXUSOPERATIONEXECUTIONSREQUEST._serialized_start = 53274 - _COUNTNEXUSOPERATIONEXECUTIONSREQUEST._serialized_end = 53346 - _COUNTNEXUSOPERATIONEXECUTIONSRESPONSE._serialized_start = 53349 - _COUNTNEXUSOPERATIONEXECUTIONSRESPONSE._serialized_end = 53598 - _COUNTNEXUSOPERATIONEXECUTIONSRESPONSE_AGGREGATIONGROUP._serialized_start = 19751 - _COUNTNEXUSOPERATIONEXECUTIONSRESPONSE_AGGREGATIONGROUP._serialized_end = 19839 - _REQUESTCANCELACTIVITYEXECUTIONREQUEST._serialized_start = 53601 - _REQUESTCANCELACTIVITYEXECUTIONREQUEST._serialized_end = 53750 - _REQUESTCANCELACTIVITYEXECUTIONRESPONSE._serialized_start = 53752 - _REQUESTCANCELACTIVITYEXECUTIONRESPONSE._serialized_end = 53792 - _TERMINATEACTIVITYEXECUTIONREQUEST._serialized_start = 53795 - _TERMINATEACTIVITYEXECUTIONREQUEST._serialized_end = 53940 - _TERMINATEACTIVITYEXECUTIONRESPONSE._serialized_start = 53942 - _TERMINATEACTIVITYEXECUTIONRESPONSE._serialized_end = 53978 - _DELETEACTIVITYEXECUTIONREQUEST._serialized_start = 53980 - _DELETEACTIVITYEXECUTIONREQUEST._serialized_end = 54068 - _DELETEACTIVITYEXECUTIONRESPONSE._serialized_start = 54070 - _DELETEACTIVITYEXECUTIONRESPONSE._serialized_end = 54103 - _REQUESTCANCELNEXUSOPERATIONEXECUTIONREQUEST._serialized_start = 54106 - _REQUESTCANCELNEXUSOPERATIONEXECUTIONREQUEST._serialized_end = 54262 - _REQUESTCANCELNEXUSOPERATIONEXECUTIONRESPONSE._serialized_start = 54264 - _REQUESTCANCELNEXUSOPERATIONEXECUTIONRESPONSE._serialized_end = 54310 - _TERMINATENEXUSOPERATIONEXECUTIONREQUEST._serialized_start = 54313 - _TERMINATENEXUSOPERATIONEXECUTIONREQUEST._serialized_end = 54465 - _TERMINATENEXUSOPERATIONEXECUTIONRESPONSE._serialized_start = 54467 - _TERMINATENEXUSOPERATIONEXECUTIONRESPONSE._serialized_end = 54509 - _DELETENEXUSOPERATIONEXECUTIONREQUEST._serialized_start = 54511 - _DELETENEXUSOPERATIONEXECUTIONREQUEST._serialized_end = 54606 - _DELETENEXUSOPERATIONEXECUTIONRESPONSE._serialized_start = 54608 - _DELETENEXUSOPERATIONEXECUTIONRESPONSE._serialized_end = 54647 + _UPDATETASKQUEUECONFIGRESPONSE._serialized_start = 47393 + _UPDATETASKQUEUECONFIGRESPONSE._serialized_end = 47484 + _FETCHWORKERCONFIGREQUEST._serialized_start = 47487 + _FETCHWORKERCONFIGREQUEST._serialized_end = 47645 + _FETCHWORKERCONFIGRESPONSE._serialized_start = 47647 + _FETCHWORKERCONFIGRESPONSE._serialized_end = 47732 + _UPDATEWORKERCONFIGREQUEST._serialized_start = 47735 + _UPDATEWORKERCONFIGREQUEST._serialized_end = 48001 + _UPDATEWORKERCONFIGRESPONSE._serialized_start = 48003 + _UPDATEWORKERCONFIGRESPONSE._serialized_end = 48103 + _DESCRIBEWORKERREQUEST._serialized_start = 48105 + _DESCRIBEWORKERREQUEST._serialized_end = 48176 + _DESCRIBEWORKERRESPONSE._serialized_start = 48178 + _DESCRIBEWORKERRESPONSE._serialized_end = 48259 + _COUNTWORKERSREQUEST._serialized_start = 48261 + _COUNTWORKERSREQUEST._serialized_end = 48348 + _COUNTWORKERSRESPONSE._serialized_start = 48350 + _COUNTWORKERSRESPONSE._serialized_end = 48387 + _PAUSEWORKFLOWEXECUTIONREQUEST._serialized_start = 48390 + _PAUSEWORKFLOWEXECUTIONREQUEST._serialized_end = 48531 + _PAUSEWORKFLOWEXECUTIONRESPONSE._serialized_start = 48533 + _PAUSEWORKFLOWEXECUTIONRESPONSE._serialized_end = 48565 + _UNPAUSEWORKFLOWEXECUTIONREQUEST._serialized_start = 48568 + _UNPAUSEWORKFLOWEXECUTIONREQUEST._serialized_end = 48711 + _UNPAUSEWORKFLOWEXECUTIONRESPONSE._serialized_start = 48713 + _UNPAUSEWORKFLOWEXECUTIONRESPONSE._serialized_end = 48747 + _STARTACTIVITYEXECUTIONREQUEST._serialized_start = 48750 + _STARTACTIVITYEXECUTIONREQUEST._serialized_end = 49927 + _STARTACTIVITYEXECUTIONRESPONSE._serialized_start = 49929 + _STARTACTIVITYEXECUTIONRESPONSE._serialized_end = 50038 + _DESCRIBEACTIVITYEXECUTIONREQUEST._serialized_start = 50041 + _DESCRIBEACTIVITYEXECUTIONREQUEST._serialized_end = 50269 + _DESCRIBEACTIVITYEXECUTIONRESPONSE._serialized_start = 50272 + _DESCRIBEACTIVITYEXECUTIONRESPONSE._serialized_end = 50588 + _POLLACTIVITYEXECUTIONREQUEST._serialized_start = 50590 + _POLLACTIVITYEXECUTIONREQUEST._serialized_end = 50676 + _POLLACTIVITYEXECUTIONRESPONSE._serialized_start = 50678 + _POLLACTIVITYEXECUTIONRESPONSE._serialized_end = 50794 + _LISTACTIVITYEXECUTIONSREQUEST._serialized_start = 50796 + _LISTACTIVITYEXECUTIONSREQUEST._serialized_end = 50905 + _LISTACTIVITYEXECUTIONSRESPONSE._serialized_start = 50908 + _LISTACTIVITYEXECUTIONSRESPONSE._serialized_end = 51038 + _STARTNEXUSOPERATIONEXECUTIONREQUEST._serialized_start = 51041 + _STARTNEXUSOPERATIONEXECUTIONREQUEST._serialized_end = 51890 + _STARTNEXUSOPERATIONEXECUTIONREQUEST_NEXUSHEADERENTRY._serialized_start = 51840 + _STARTNEXUSOPERATIONEXECUTIONREQUEST_NEXUSHEADERENTRY._serialized_end = 51890 + _STARTNEXUSOPERATIONEXECUTIONRESPONSE._serialized_start = 51892 + _STARTNEXUSOPERATIONEXECUTIONRESPONSE._serialized_end = 51963 + _DESCRIBENEXUSOPERATIONEXECUTIONREQUEST._serialized_start = 51966 + _DESCRIBENEXUSOPERATIONEXECUTIONREQUEST._serialized_end = 52136 + _DESCRIBENEXUSOPERATIONEXECUTIONRESPONSE._serialized_start = 52139 + _DESCRIBENEXUSOPERATIONEXECUTIONRESPONSE._serialized_end = 52450 + _POLLNEXUSOPERATIONEXECUTIONREQUEST._serialized_start = 52453 + _POLLNEXUSOPERATIONEXECUTIONREQUEST._serialized_end = 52614 + _POLLNEXUSOPERATIONEXECUTIONRESPONSE._serialized_start = 52617 + _POLLNEXUSOPERATIONEXECUTIONRESPONSE._serialized_end = 52878 + _LISTNEXUSOPERATIONEXECUTIONSREQUEST._serialized_start = 52880 + _LISTNEXUSOPERATIONEXECUTIONSREQUEST._serialized_end = 52995 + _LISTNEXUSOPERATIONEXECUTIONSRESPONSE._serialized_start = 52998 + _LISTNEXUSOPERATIONEXECUTIONSRESPONSE._serialized_end = 53137 + _COUNTACTIVITYEXECUTIONSREQUEST._serialized_start = 53139 + _COUNTACTIVITYEXECUTIONSREQUEST._serialized_end = 53205 + _COUNTACTIVITYEXECUTIONSRESPONSE._serialized_start = 53208 + _COUNTACTIVITYEXECUTIONSRESPONSE._serialized_end = 53445 + _COUNTACTIVITYEXECUTIONSRESPONSE_AGGREGATIONGROUP._serialized_start = 19747 + _COUNTACTIVITYEXECUTIONSRESPONSE_AGGREGATIONGROUP._serialized_end = 19835 + _COUNTNEXUSOPERATIONEXECUTIONSREQUEST._serialized_start = 53447 + _COUNTNEXUSOPERATIONEXECUTIONSREQUEST._serialized_end = 53519 + _COUNTNEXUSOPERATIONEXECUTIONSRESPONSE._serialized_start = 53522 + _COUNTNEXUSOPERATIONEXECUTIONSRESPONSE._serialized_end = 53771 + _COUNTNEXUSOPERATIONEXECUTIONSRESPONSE_AGGREGATIONGROUP._serialized_start = 19747 + _COUNTNEXUSOPERATIONEXECUTIONSRESPONSE_AGGREGATIONGROUP._serialized_end = 19835 + _REQUESTCANCELACTIVITYEXECUTIONREQUEST._serialized_start = 53774 + _REQUESTCANCELACTIVITYEXECUTIONREQUEST._serialized_end = 53923 + _REQUESTCANCELACTIVITYEXECUTIONRESPONSE._serialized_start = 53925 + _REQUESTCANCELACTIVITYEXECUTIONRESPONSE._serialized_end = 53965 + _TERMINATEACTIVITYEXECUTIONREQUEST._serialized_start = 53968 + _TERMINATEACTIVITYEXECUTIONREQUEST._serialized_end = 54113 + _TERMINATEACTIVITYEXECUTIONRESPONSE._serialized_start = 54115 + _TERMINATEACTIVITYEXECUTIONRESPONSE._serialized_end = 54151 + _DELETEACTIVITYEXECUTIONREQUEST._serialized_start = 54153 + _DELETEACTIVITYEXECUTIONREQUEST._serialized_end = 54241 + _DELETEACTIVITYEXECUTIONRESPONSE._serialized_start = 54243 + _DELETEACTIVITYEXECUTIONRESPONSE._serialized_end = 54276 + _REQUESTCANCELNEXUSOPERATIONEXECUTIONREQUEST._serialized_start = 54279 + _REQUESTCANCELNEXUSOPERATIONEXECUTIONREQUEST._serialized_end = 54435 + _REQUESTCANCELNEXUSOPERATIONEXECUTIONRESPONSE._serialized_start = 54437 + _REQUESTCANCELNEXUSOPERATIONEXECUTIONRESPONSE._serialized_end = 54483 + _TERMINATENEXUSOPERATIONEXECUTIONREQUEST._serialized_start = 54486 + _TERMINATENEXUSOPERATIONEXECUTIONREQUEST._serialized_end = 54638 + _TERMINATENEXUSOPERATIONEXECUTIONRESPONSE._serialized_start = 54640 + _TERMINATENEXUSOPERATIONEXECUTIONRESPONSE._serialized_end = 54682 + _DELETENEXUSOPERATIONEXECUTIONREQUEST._serialized_start = 54684 + _DELETENEXUSOPERATIONEXECUTIONREQUEST._serialized_end = 54779 + _DELETENEXUSOPERATIONEXECUTIONRESPONSE._serialized_start = 54781 + _DELETENEXUSOPERATIONEXECUTIONRESPONSE._serialized_end = 54820 # @@protoc_insertion_point(module_scope) diff --git a/temporalio/api/workflowservice/v1/request_response_pb2.pyi b/temporalio/api/workflowservice/v1/request_response_pb2.pyi index 1e92d50e1..8f1069d3d 100644 --- a/temporalio/api/workflowservice/v1/request_response_pb2.pyi +++ b/temporalio/api/workflowservice/v1/request_response_pb2.pyi @@ -710,7 +710,7 @@ class StartWorkflowExecutionRequest(google.protobuf.message.Message): @property def time_skipping_config( self, - ) -> temporalio.api.workflow.v1.message_pb2.TimeSkippingConfig: + ) -> temporalio.api.common.v1.message_pb2.TimeSkippingConfig: """Time-skipping configuration. If not set, time skipping is disabled.""" def __init__( self, @@ -753,7 +753,7 @@ class StartWorkflowExecutionRequest(google.protobuf.message.Message): priority: temporalio.api.common.v1.message_pb2.Priority | None = ..., eager_worker_deployment_options: temporalio.api.deployment.v1.message_pb2.WorkerDeploymentOptions | None = ..., - time_skipping_config: temporalio.api.workflow.v1.message_pb2.TimeSkippingConfig + time_skipping_config: temporalio.api.common.v1.message_pb2.TimeSkippingConfig | None = ..., ) -> None: ... def HasField( @@ -3342,7 +3342,7 @@ class SignalWithStartWorkflowExecutionRequest(google.protobuf.message.Message): @property def time_skipping_config( self, - ) -> temporalio.api.workflow.v1.message_pb2.TimeSkippingConfig: + ) -> temporalio.api.common.v1.message_pb2.TimeSkippingConfig: """Time-skipping configuration. If not set, time skipping is disabled.""" def __init__( self, @@ -3376,7 +3376,7 @@ class SignalWithStartWorkflowExecutionRequest(google.protobuf.message.Message): versioning_override: temporalio.api.workflow.v1.message_pb2.VersioningOverride | None = ..., priority: temporalio.api.common.v1.message_pb2.Priority | None = ..., - time_skipping_config: temporalio.api.workflow.v1.message_pb2.TimeSkippingConfig + time_skipping_config: temporalio.api.common.v1.message_pb2.TimeSkippingConfig | None = ..., ) -> None: ... def HasField( @@ -8927,27 +8927,40 @@ class UpdateWorkflowExecutionOptionsResponse(google.protobuf.message.Message): DESCRIPTOR: google.protobuf.descriptor.Descriptor WORKFLOW_EXECUTION_OPTIONS_FIELD_NUMBER: builtins.int + UPDATE_TIME_FIELD_NUMBER: builtins.int @property def workflow_execution_options( self, ) -> temporalio.api.workflow.v1.message_pb2.WorkflowExecutionOptions: """Workflow Execution options after update.""" + @property + def update_time(self) -> google.protobuf.timestamp_pb2.Timestamp: + """The Workflow Execution time when the options were updated. When time skipping is + enabled, this is the workflow's virtual time rather than wall-clock time. + """ def __init__( self, *, workflow_execution_options: temporalio.api.workflow.v1.message_pb2.WorkflowExecutionOptions | None = ..., + update_time: google.protobuf.timestamp_pb2.Timestamp | None = ..., ) -> None: ... def HasField( self, field_name: typing_extensions.Literal[ - "workflow_execution_options", b"workflow_execution_options" + "update_time", + b"update_time", + "workflow_execution_options", + b"workflow_execution_options", ], ) -> builtins.bool: ... def ClearField( self, field_name: typing_extensions.Literal[ - "workflow_execution_options", b"workflow_execution_options" + "update_time", + b"update_time", + "workflow_execution_options", + b"workflow_execution_options", ], ) -> None: ... @@ -11545,6 +11558,59 @@ class DescribeWorkerResponse(google.protobuf.message.Message): global___DescribeWorkerResponse = DescribeWorkerResponse +class CountWorkersRequest(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + NAMESPACE_FIELD_NUMBER: builtins.int + QUERY_FIELD_NUMBER: builtins.int + INCLUDE_SYSTEM_WORKERS_FIELD_NUMBER: builtins.int + namespace: builtins.str + query: builtins.str + """Query to filter workers before counting. + Supported filter fields are the same as in ListWorkersRequest. + """ + include_system_workers: builtins.bool + """When true, the count will include system workers that are created implicitly + by the server and not by the user. By default, system workers are excluded. + """ + def __init__( + self, + *, + namespace: builtins.str = ..., + query: builtins.str = ..., + include_system_workers: builtins.bool = ..., + ) -> None: ... + def ClearField( + self, + field_name: typing_extensions.Literal[ + "include_system_workers", + b"include_system_workers", + "namespace", + b"namespace", + "query", + b"query", + ], + ) -> None: ... + +global___CountWorkersRequest = CountWorkersRequest + +class CountWorkersResponse(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + COUNT_FIELD_NUMBER: builtins.int + count: builtins.int + """Number of workers matching the query.""" + def __init__( + self, + *, + count: builtins.int = ..., + ) -> None: ... + def ClearField( + self, field_name: typing_extensions.Literal["count", b"count"] + ) -> None: ... + +global___CountWorkersResponse = CountWorkersResponse + class PauseWorkflowExecutionRequest(google.protobuf.message.Message): """Request to pause a workflow execution.""" diff --git a/temporalio/api/workflowservice/v1/service_pb2.py b/temporalio/api/workflowservice/v1/service_pb2.py index bc9ca40a4..502f68ba6 100644 --- a/temporalio/api/workflowservice/v1/service_pb2.py +++ b/temporalio/api/workflowservice/v1/service_pb2.py @@ -27,7 +27,7 @@ ) DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile( - b'\n-temporal/api/workflowservice/v1/service.proto\x12\x1ftemporal.api.workflowservice.v1\x1a\x1cgoogle/api/annotations.proto\x1a!nexusannotations/v1/options.proto\x1a+temporal/api/protometa/v1/annotations.proto\x1a\x36temporal/api/workflowservice/v1/request_response.proto2\xbd\xad\x02\n\x0fWorkflowService\x12\xc3\x01\n\x11RegisterNamespace\x12\x39.temporal.api.workflowservice.v1.RegisterNamespaceRequest\x1a:.temporal.api.workflowservice.v1.RegisterNamespaceResponse"7\x82\xd3\xe4\x93\x02\x31"\x13/cluster/namespaces:\x01*Z\x17"\x12/api/v1/namespaces:\x01*\x12\xd5\x01\n\x11\x44\x65scribeNamespace\x12\x39.temporal.api.workflowservice.v1.DescribeNamespaceRequest\x1a:.temporal.api.workflowservice.v1.DescribeNamespaceResponse"I\x82\xd3\xe4\x93\x02\x43\x12\x1f/cluster/namespaces/{namespace}Z \x12\x1e/api/v1/namespaces/{namespace}\x12\xb4\x01\n\x0eListNamespaces\x12\x36.temporal.api.workflowservice.v1.ListNamespacesRequest\x1a\x37.temporal.api.workflowservice.v1.ListNamespacesResponse"1\x82\xd3\xe4\x93\x02+\x12\x13/cluster/namespacesZ\x14\x12\x12/api/v1/namespaces\x12\xe3\x01\n\x0fUpdateNamespace\x12\x37.temporal.api.workflowservice.v1.UpdateNamespaceRequest\x1a\x38.temporal.api.workflowservice.v1.UpdateNamespaceResponse"]\x82\xd3\xe4\x93\x02W"&/cluster/namespaces/{namespace}/update:\x01*Z*"%/api/v1/namespaces/{namespace}/update:\x01*\x12\x8f\x01\n\x12\x44\x65precateNamespace\x12:.temporal.api.workflowservice.v1.DeprecateNamespaceRequest\x1a;.temporal.api.workflowservice.v1.DeprecateNamespaceResponse"\x00\x12\xc6\x02\n\x16StartWorkflowExecution\x12>.temporal.api.workflowservice.v1.StartWorkflowExecutionRequest\x1a?.temporal.api.workflowservice.v1.StartWorkflowExecutionResponse"\xaa\x01\x82\xd3\xe4\x93\x02q"//namespaces/{namespace}/workflows/{workflow_id}:\x01*Z;"6/api/v1/namespaces/{namespace}/workflows/{workflow_id}:\x01*\x8a\x9d\xcc\x1b.\n\x14temporal-resource-id\x12\x16workflow:{workflow_id}\x12\xc2\x01\n\x15\x45xecuteMultiOperation\x12=.temporal.api.workflowservice.v1.ExecuteMultiOperationRequest\x1a>.temporal.api.workflowservice.v1.ExecuteMultiOperationResponse"*\x8a\x9d\xcc\x1b%\n\x14temporal-resource-id\x12\r{resource_id}\x12\xfe\x02\n\x1bGetWorkflowExecutionHistory\x12\x43.temporal.api.workflowservice.v1.GetWorkflowExecutionHistoryRequest\x1a\x44.temporal.api.workflowservice.v1.GetWorkflowExecutionHistoryResponse"\xd3\x01\x82\xd3\xe4\x93\x02\x8f\x01\x12\x41/namespaces/{namespace}/workflows/{execution.workflow_id}/historyZJ\x12H/api/v1/namespaces/{namespace}/workflows/{execution.workflow_id}/history\x8a\x9d\xcc\x1b\x38\n\x14temporal-resource-id\x12 workflow:{execution.workflow_id}\x12\xa3\x03\n"GetWorkflowExecutionHistoryReverse\x12J.temporal.api.workflowservice.v1.GetWorkflowExecutionHistoryReverseRequest\x1aK.temporal.api.workflowservice.v1.GetWorkflowExecutionHistoryReverseResponse"\xe3\x01\x82\xd3\xe4\x93\x02\x9f\x01\x12I/namespaces/{namespace}/workflows/{execution.workflow_id}/history-reverseZR\x12P/api/v1/namespaces/{namespace}/workflows/{execution.workflow_id}/history-reverse\x8a\x9d\xcc\x1b\x38\n\x14temporal-resource-id\x12 workflow:{execution.workflow_id}\x12\xcd\x01\n\x15PollWorkflowTaskQueue\x12=.temporal.api.workflowservice.v1.PollWorkflowTaskQueueRequest\x1a>.temporal.api.workflowservice.v1.PollWorkflowTaskQueueResponse"5\x8a\x9d\xcc\x1b\x30\n\x14temporal-resource-id\x12\x18poller:{poller_group_id}\x12\xd7\x01\n\x1cRespondWorkflowTaskCompleted\x12\x44.temporal.api.workflowservice.v1.RespondWorkflowTaskCompletedRequest\x1a\x45.temporal.api.workflowservice.v1.RespondWorkflowTaskCompletedResponse"*\x8a\x9d\xcc\x1b%\n\x14temporal-resource-id\x12\r{resource_id}\x12\xce\x01\n\x19RespondWorkflowTaskFailed\x12\x41.temporal.api.workflowservice.v1.RespondWorkflowTaskFailedRequest\x1a\x42.temporal.api.workflowservice.v1.RespondWorkflowTaskFailedResponse"*\x8a\x9d\xcc\x1b%\n\x14temporal-resource-id\x12\r{resource_id}\x12\xcd\x01\n\x15PollActivityTaskQueue\x12=.temporal.api.workflowservice.v1.PollActivityTaskQueueRequest\x1a>.temporal.api.workflowservice.v1.PollActivityTaskQueueResponse"5\x8a\x9d\xcc\x1b\x30\n\x14temporal-resource-id\x12\x18poller:{poller_group_id}\x12\xc2\x02\n\x1bRecordActivityTaskHeartbeat\x12\x43.temporal.api.workflowservice.v1.RecordActivityTaskHeartbeatRequest\x1a\x44.temporal.api.workflowservice.v1.RecordActivityTaskHeartbeatResponse"\x97\x01\x82\xd3\xe4\x93\x02g"*/namespaces/{namespace}/activity-heartbeat:\x01*Z6"1/api/v1/namespaces/{namespace}/activity-heartbeat:\x01*\x8a\x9d\xcc\x1b%\n\x14temporal-resource-id\x12\r{resource_id}\x12\xa8\x04\n\x1fRecordActivityTaskHeartbeatById\x12G.temporal.api.workflowservice.v1.RecordActivityTaskHeartbeatByIdRequest\x1aH.temporal.api.workflowservice.v1.RecordActivityTaskHeartbeatByIdResponse"\xf1\x02\x82\xd3\xe4\x93\x02\xc0\x02":/namespaces/{namespace}/activities/{activity_id}/heartbeat:\x01*ZF"A/api/v1/namespaces/{namespace}/activities/{activity_id}/heartbeat:\x01*ZW"R/namespaces/{namespace}/workflows/{workflow_id}/activities/{activity_id}/heartbeat:\x01*Z^"Y/api/v1/namespaces/{namespace}/workflows/{workflow_id}/activities/{activity_id}/heartbeat:\x01*\x8a\x9d\xcc\x1b%\n\x14temporal-resource-id\x12\r{resource_id}\x12\xc3\x02\n\x1cRespondActivityTaskCompleted\x12\x44.temporal.api.workflowservice.v1.RespondActivityTaskCompletedRequest\x1a\x45.temporal.api.workflowservice.v1.RespondActivityTaskCompletedResponse"\x95\x01\x82\xd3\xe4\x93\x02\x65")/namespaces/{namespace}/activity-complete:\x01*Z5"0/api/v1/namespaces/{namespace}/activity-complete:\x01*\x8a\x9d\xcc\x1b%\n\x14temporal-resource-id\x12\r{resource_id}\x12\xa7\x04\n RespondActivityTaskCompletedById\x12H.temporal.api.workflowservice.v1.RespondActivityTaskCompletedByIdRequest\x1aI.temporal.api.workflowservice.v1.RespondActivityTaskCompletedByIdResponse"\xed\x02\x82\xd3\xe4\x93\x02\xbc\x02"9/namespaces/{namespace}/activities/{activity_id}/complete:\x01*ZE"@/api/v1/namespaces/{namespace}/activities/{activity_id}/complete:\x01*ZV"Q/namespaces/{namespace}/workflows/{workflow_id}/activities/{activity_id}/complete:\x01*Z]"X/api/v1/namespaces/{namespace}/workflows/{workflow_id}/activities/{activity_id}/complete:\x01*\x8a\x9d\xcc\x1b%\n\x14temporal-resource-id\x12\r{resource_id}\x12\xb2\x02\n\x19RespondActivityTaskFailed\x12\x41.temporal.api.workflowservice.v1.RespondActivityTaskFailedRequest\x1a\x42.temporal.api.workflowservice.v1.RespondActivityTaskFailedResponse"\x8d\x01\x82\xd3\xe4\x93\x02]"%/namespaces/{namespace}/activity-fail:\x01*Z1",/api/v1/namespaces/{namespace}/activity-fail:\x01*\x8a\x9d\xcc\x1b%\n\x14temporal-resource-id\x12\r{resource_id}\x12\x8e\x04\n\x1dRespondActivityTaskFailedById\x12\x45.temporal.api.workflowservice.v1.RespondActivityTaskFailedByIdRequest\x1a\x46.temporal.api.workflowservice.v1.RespondActivityTaskFailedByIdResponse"\xdd\x02\x82\xd3\xe4\x93\x02\xac\x02"5/namespaces/{namespace}/activities/{activity_id}/fail:\x01*ZA".temporal.api.workflowservice.v1.ResetWorkflowExecutionRequest\x1a?.temporal.api.workflowservice.v1.ResetWorkflowExecutionResponse"\xf0\x01\x82\xd3\xe4\x93\x02\xa3\x01"H/namespaces/{namespace}/workflows/{workflow_execution.workflow_id}/reset:\x01*ZT"O/api/v1/namespaces/{namespace}/workflows/{workflow_execution.workflow_id}/reset:\x01*\x8a\x9d\xcc\x1b\x41\n\x14temporal-resource-id\x12)workflow:{workflow_execution.workflow_id}\x12\xa0\x03\n\x1aTerminateWorkflowExecution\x12\x42.temporal.api.workflowservice.v1.TerminateWorkflowExecutionRequest\x1a\x43.temporal.api.workflowservice.v1.TerminateWorkflowExecutionResponse"\xf8\x01\x82\xd3\xe4\x93\x02\xab\x01"L/namespaces/{namespace}/workflows/{workflow_execution.workflow_id}/terminate:\x01*ZX"S/api/v1/namespaces/{namespace}/workflows/{workflow_execution.workflow_id}/terminate:\x01*\x8a\x9d\xcc\x1b\x41\n\x14temporal-resource-id\x12)workflow:{workflow_execution.workflow_id}\x12\xe4\x01\n\x17\x44\x65leteWorkflowExecution\x12?.temporal.api.workflowservice.v1.DeleteWorkflowExecutionRequest\x1a@.temporal.api.workflowservice.v1.DeleteWorkflowExecutionResponse"F\x8a\x9d\xcc\x1b\x41\n\x14temporal-resource-id\x12)workflow:{workflow_execution.workflow_id}\x12\xa7\x01\n\x1aListOpenWorkflowExecutions\x12\x42.temporal.api.workflowservice.v1.ListOpenWorkflowExecutionsRequest\x1a\x43.temporal.api.workflowservice.v1.ListOpenWorkflowExecutionsResponse"\x00\x12\xad\x01\n\x1cListClosedWorkflowExecutions\x12\x44.temporal.api.workflowservice.v1.ListClosedWorkflowExecutionsRequest\x1a\x45.temporal.api.workflowservice.v1.ListClosedWorkflowExecutionsResponse"\x00\x12\xf0\x01\n\x16ListWorkflowExecutions\x12>.temporal.api.workflowservice.v1.ListWorkflowExecutionsRequest\x1a?.temporal.api.workflowservice.v1.ListWorkflowExecutionsResponse"U\x82\xd3\xe4\x93\x02O\x12!/namespaces/{namespace}/workflowsZ*\x12(/api/v1/namespaces/{namespace}/workflows\x12\x9a\x02\n\x1eListArchivedWorkflowExecutions\x12\x46.temporal.api.workflowservice.v1.ListArchivedWorkflowExecutionsRequest\x1aG.temporal.api.workflowservice.v1.ListArchivedWorkflowExecutionsResponse"g\x82\xd3\xe4\x93\x02\x61\x12*/namespaces/{namespace}/archived-workflowsZ3\x12\x31/api/v1/namespaces/{namespace}/archived-workflows\x12\x9b\x01\n\x16ScanWorkflowExecutions\x12>.temporal.api.workflowservice.v1.ScanWorkflowExecutionsRequest\x1a?.temporal.api.workflowservice.v1.ScanWorkflowExecutionsResponse"\x00\x12\xfd\x01\n\x17\x43ountWorkflowExecutions\x12?.temporal.api.workflowservice.v1.CountWorkflowExecutionsRequest\x1a@.temporal.api.workflowservice.v1.CountWorkflowExecutionsResponse"_\x82\xd3\xe4\x93\x02Y\x12&/namespaces/{namespace}/workflow-countZ/\x12-/api/v1/namespaces/{namespace}/workflow-count\x12\x92\x01\n\x13GetSearchAttributes\x12;.temporal.api.workflowservice.v1.GetSearchAttributesRequest\x1a<.temporal.api.workflowservice.v1.GetSearchAttributesResponse"\x00\x12\xd9\x01\n\x19RespondQueryTaskCompleted\x12\x41.temporal.api.workflowservice.v1.RespondQueryTaskCompletedRequest\x1a\x42.temporal.api.workflowservice.v1.RespondQueryTaskCompletedResponse"5\x8a\x9d\xcc\x1b\x30\n\x14temporal-resource-id\x12\x18poller:{poller_group_id}\x12\xd2\x01\n\x14ResetStickyTaskQueue\x12<.temporal.api.workflowservice.v1.ResetStickyTaskQueueRequest\x1a=.temporal.api.workflowservice.v1.ResetStickyTaskQueueResponse"=\x8a\x9d\xcc\x1b\x38\n\x14temporal-resource-id\x12 workflow:{execution.workflow_id}\x12\x83\x01\n\x0eShutdownWorker\x12\x36.temporal.api.workflowservice.v1.ShutdownWorkerRequest\x1a\x37.temporal.api.workflowservice.v1.ShutdownWorkerResponse"\x00\x12\xfc\x02\n\rQueryWorkflow\x12\x35.temporal.api.workflowservice.v1.QueryWorkflowRequest\x1a\x36.temporal.api.workflowservice.v1.QueryWorkflowResponse"\xfb\x01\x82\xd3\xe4\x93\x02\xb7\x01"R/namespaces/{namespace}/workflows/{execution.workflow_id}/query/{query.query_type}:\x01*Z^"Y/api/v1/namespaces/{namespace}/workflows/{execution.workflow_id}/query/{query.query_type}:\x01*\x8a\x9d\xcc\x1b\x38\n\x14temporal-resource-id\x12 workflow:{execution.workflow_id}\x12\xe7\x02\n\x19\x44\x65scribeWorkflowExecution\x12\x41.temporal.api.workflowservice.v1.DescribeWorkflowExecutionRequest\x1a\x42.temporal.api.workflowservice.v1.DescribeWorkflowExecutionResponse"\xc2\x01\x82\xd3\xe4\x93\x02\x7f\x12\x39/namespaces/{namespace}/workflows/{execution.workflow_id}ZB\x12@/api/v1/namespaces/{namespace}/workflows/{execution.workflow_id}\x8a\x9d\xcc\x1b\x38\n\x14temporal-resource-id\x12 workflow:{execution.workflow_id}\x12\xc2\x02\n\x11\x44\x65scribeTaskQueue\x12\x39.temporal.api.workflowservice.v1.DescribeTaskQueueRequest\x1a:.temporal.api.workflowservice.v1.DescribeTaskQueueResponse"\xb5\x01\x82\xd3\xe4\x93\x02w\x12\x35/namespaces/{namespace}/task-queues/{task_queue.name}Z>\x12/namespaces/{namespace}/schedules/{schedule_id}/matching-timesZG\x12\x45/api/v1/namespaces/{namespace}/schedules/{schedule_id}/matching-times\x8a\x9d\xcc\x1b.\n\x14temporal-resource-id\x12\x16schedule:{schedule_id}\x12\xa8\x02\n\x0e\x44\x65leteSchedule\x12\x36.temporal.api.workflowservice.v1.DeleteScheduleRequest\x1a\x37.temporal.api.workflowservice.v1.DeleteScheduleResponse"\xa4\x01\x82\xd3\xe4\x93\x02k*//namespaces/{namespace}/schedules/{schedule_id}Z8*6/api/v1/namespaces/{namespace}/schedules/{schedule_id}\x8a\x9d\xcc\x1b.\n\x14temporal-resource-id\x12\x16schedule:{schedule_id}\x12\xd5\x01\n\rListSchedules\x12\x35.temporal.api.workflowservice.v1.ListSchedulesRequest\x1a\x36.temporal.api.workflowservice.v1.ListSchedulesResponse"U\x82\xd3\xe4\x93\x02O\x12!/namespaces/{namespace}/schedulesZ*\x12(/api/v1/namespaces/{namespace}/schedules\x12\xe2\x01\n\x0e\x43ountSchedules\x12\x36.temporal.api.workflowservice.v1.CountSchedulesRequest\x1a\x37.temporal.api.workflowservice.v1.CountSchedulesResponse"_\x82\xd3\xe4\x93\x02Y\x12&/namespaces/{namespace}/schedule-countZ/\x12-/api/v1/namespaces/{namespace}/schedule-count\x12\xb9\x01\n UpdateWorkerBuildIdCompatibility\x12H.temporal.api.workflowservice.v1.UpdateWorkerBuildIdCompatibilityRequest\x1aI.temporal.api.workflowservice.v1.UpdateWorkerBuildIdCompatibilityResponse"\x00\x12\xe1\x02\n\x1dGetWorkerBuildIdCompatibility\x12\x45.temporal.api.workflowservice.v1.GetWorkerBuildIdCompatibilityRequest\x1a\x46.temporal.api.workflowservice.v1.GetWorkerBuildIdCompatibilityResponse"\xb0\x01\x82\xd3\xe4\x93\x02\xa9\x01\x12N/namespaces/{namespace}/task-queues/{task_queue}/worker-build-id-compatibilityZW\x12U/api/v1/namespaces/{namespace}/task-queues/{task_queue}/worker-build-id-compatibility\x12\xaa\x01\n\x1bUpdateWorkerVersioningRules\x12\x43.temporal.api.workflowservice.v1.UpdateWorkerVersioningRulesRequest\x1a\x44.temporal.api.workflowservice.v1.UpdateWorkerVersioningRulesResponse"\x00\x12\xc6\x02\n\x18GetWorkerVersioningRules\x12@.temporal.api.workflowservice.v1.GetWorkerVersioningRulesRequest\x1a\x41.temporal.api.workflowservice.v1.GetWorkerVersioningRulesResponse"\xa4\x01\x82\xd3\xe4\x93\x02\x9d\x01\x12H/namespaces/{namespace}/task-queues/{task_queue}/worker-versioning-rulesZQ\x12O/api/v1/namespaces/{namespace}/task-queues/{task_queue}/worker-versioning-rules\x12\x97\x02\n\x19GetWorkerTaskReachability\x12\x41.temporal.api.workflowservice.v1.GetWorkerTaskReachabilityRequest\x1a\x42.temporal.api.workflowservice.v1.GetWorkerTaskReachabilityResponse"s\x82\xd3\xe4\x93\x02m\x12\x30/namespaces/{namespace}/worker-task-reachabilityZ9\x12\x37/api/v1/namespaces/{namespace}/worker-task-reachability\x12\xc8\x02\n\x12\x44\x65scribeDeployment\x12:.temporal.api.workflowservice.v1.DescribeDeploymentRequest\x1a;.temporal.api.workflowservice.v1.DescribeDeploymentResponse"\xb8\x01\x82\xd3\xe4\x93\x02\xb1\x01\x12R/namespaces/{namespace}/deployments/{deployment.series_name}/{deployment.build_id}Z[\x12Y/api/v1/namespaces/{namespace}/deployments/{deployment.series_name}/{deployment.build_id}\x12\x81\x04\n\x1f\x44\x65scribeWorkerDeploymentVersion\x12G.temporal.api.workflowservice.v1.DescribeWorkerDeploymentVersionRequest\x1aH.temporal.api.workflowservice.v1.DescribeWorkerDeploymentVersionResponse"\xca\x02\x82\xd3\xe4\x93\x02\xf7\x01\x12u/namespaces/{namespace}/worker-deployment-versions/{deployment_version.deployment_name}/{deployment_version.build_id}Z~\x12|/api/v1/namespaces/{namespace}/worker-deployment-versions/{deployment_version.deployment_name}/{deployment_version.build_id}\x8a\x9d\xcc\x1bG\n\x14temporal-resource-id\x12/deployment:{deployment_version.deployment_name}\x12\xdf\x01\n\x0fListDeployments\x12\x37.temporal.api.workflowservice.v1.ListDeploymentsRequest\x1a\x38.temporal.api.workflowservice.v1.ListDeploymentsResponse"Y\x82\xd3\xe4\x93\x02S\x12#/namespaces/{namespace}/deploymentsZ,\x12*/api/v1/namespaces/{namespace}/deployments\x12\xf7\x02\n\x19GetDeploymentReachability\x12\x41.temporal.api.workflowservice.v1.GetDeploymentReachabilityRequest\x1a\x42.temporal.api.workflowservice.v1.GetDeploymentReachabilityResponse"\xd2\x01\x82\xd3\xe4\x93\x02\xcb\x01\x12_/namespaces/{namespace}/deployments/{deployment.series_name}/{deployment.build_id}/reachabilityZh\x12\x66/api/v1/namespaces/{namespace}/deployments/{deployment.series_name}/{deployment.build_id}/reachability\x12\x99\x02\n\x14GetCurrentDeployment\x12<.temporal.api.workflowservice.v1.GetCurrentDeploymentRequest\x1a=.temporal.api.workflowservice.v1.GetCurrentDeploymentResponse"\x83\x01\x82\xd3\xe4\x93\x02}\x12\x38/namespaces/{namespace}/current-deployment/{series_name}ZA\x12?/api/v1/namespaces/{namespace}/current-deployment/{series_name}\x12\xb6\x02\n\x14SetCurrentDeployment\x12<.temporal.api.workflowservice.v1.SetCurrentDeploymentRequest\x1a=.temporal.api.workflowservice.v1.SetCurrentDeploymentResponse"\xa0\x01\x82\xd3\xe4\x93\x02\x99\x01"C/namespaces/{namespace}/current-deployment/{deployment.series_name}:\x01*ZO"J/api/v1/namespaces/{namespace}/current-deployment/{deployment.series_name}:\x01*\x12\xb0\x03\n!SetWorkerDeploymentCurrentVersion\x12I.temporal.api.workflowservice.v1.SetWorkerDeploymentCurrentVersionRequest\x1aJ.temporal.api.workflowservice.v1.SetWorkerDeploymentCurrentVersionResponse"\xf3\x01\x82\xd3\xe4\x93\x02\xb3\x01"P/namespaces/{namespace}/worker-deployments/{deployment_name}/set-current-version:\x01*Z\\"W/api/v1/namespaces/{namespace}/worker-deployments/{deployment_name}/set-current-version:\x01*\x8a\x9d\xcc\x1b\x34\n\x14temporal-resource-id\x12\x1c\x64\x65ployment:{deployment_name}\x12\xe7\x02\n\x18\x44\x65scribeWorkerDeployment\x12@.temporal.api.workflowservice.v1.DescribeWorkerDeploymentRequest\x1a\x41.temporal.api.workflowservice.v1.DescribeWorkerDeploymentResponse"\xc5\x01\x82\xd3\xe4\x93\x02\x85\x01\x12.temporal.api.workflowservice.v1.DeleteWorkerDeploymentRequest\x1a?.temporal.api.workflowservice.v1.DeleteWorkerDeploymentResponse"\xc5\x01\x82\xd3\xe4\x93\x02\x85\x01*.temporal.api.workflowservice.v1.ListWorkerDeploymentsResponse"g\x82\xd3\xe4\x93\x02\x61\x12*/namespaces/{namespace}/worker-deploymentsZ3\x12\x31/api/v1/namespaces/{namespace}/worker-deployments\x12\xae\x02\n\x16\x43reateWorkerDeployment\x12>.temporal.api.workflowservice.v1.CreateWorkerDeploymentRequest\x1a?.temporal.api.workflowservice.v1.CreateWorkerDeploymentResponse"\x92\x01\x82\xd3\xe4\x93\x02\x8b\x01".temporal.api.workflowservice.v1.DescribeBatchOperationRequest\x1a?.temporal.api.workflowservice.v1.DescribeBatchOperationResponse"\xa0\x01\x82\xd3\xe4\x93\x02o\x12\x31/namespaces/{namespace}/batch-operations/{job_id}Z:\x12\x38/api/v1/namespaces/{namespace}/batch-operations/{job_id}\x8a\x9d\xcc\x1b&\n\x14temporal-resource-id\x12\x0e\x62\x61tch:{job_id}\x12\xf5\x01\n\x13ListBatchOperations\x12;.temporal.api.workflowservice.v1.ListBatchOperationsRequest\x1a<.temporal.api.workflowservice.v1.ListBatchOperationsResponse"c\x82\xd3\xe4\x93\x02]\x12(/namespaces/{namespace}/batch-operationsZ1\x12//api/v1/namespaces/{namespace}/batch-operations\x12\xc4\x01\n\x12PollNexusTaskQueue\x12:.temporal.api.workflowservice.v1.PollNexusTaskQueueRequest\x1a;.temporal.api.workflowservice.v1.PollNexusTaskQueueResponse"5\x8a\x9d\xcc\x1b\x30\n\x14temporal-resource-id\x12\x18poller:{poller_group_id}\x12\xd9\x01\n\x19RespondNexusTaskCompleted\x12\x41.temporal.api.workflowservice.v1.RespondNexusTaskCompletedRequest\x1a\x42.temporal.api.workflowservice.v1.RespondNexusTaskCompletedResponse"5\x8a\x9d\xcc\x1b\x30\n\x14temporal-resource-id\x12\x18poller:{poller_group_id}\x12\xd0\x01\n\x16RespondNexusTaskFailed\x12>.temporal.api.workflowservice.v1.RespondNexusTaskFailedRequest\x1a?.temporal.api.workflowservice.v1.RespondNexusTaskFailedResponse"5\x8a\x9d\xcc\x1b\x30\n\x14temporal-resource-id\x12\x18poller:{poller_group_id}\x12\xe8\x02\n\x15UpdateActivityOptions\x12=.temporal.api.workflowservice.v1.UpdateActivityOptionsRequest\x1a>.temporal.api.workflowservice.v1.UpdateActivityOptionsResponse"\xcf\x01\x82\xd3\xe4\x93\x02\x8b\x01".temporal.api.workflowservice.v1.RecordWorkerHeartbeatResponse"\x95\x01\x82\xd3\xe4\x93\x02\x65")/namespaces/{namespace}/workers/heartbeat:\x01*Z5"0/api/v1/namespaces/{namespace}/workers/heartbeat:\x01*\x8a\x9d\xcc\x1b%\n\x14temporal-resource-id\x12\r{resource_id}\x12\xcb\x01\n\x0bListWorkers\x12\x33.temporal.api.workflowservice.v1.ListWorkersRequest\x1a\x34.temporal.api.workflowservice.v1.ListWorkersResponse"Q\x82\xd3\xe4\x93\x02K\x12\x1f/namespaces/{namespace}/workersZ(\x12&/api/v1/namespaces/{namespace}/workers\x12\xe2\x02\n\x15UpdateTaskQueueConfig\x12=.temporal.api.workflowservice.v1.UpdateTaskQueueConfigRequest\x1a>.temporal.api.workflowservice.v1.UpdateTaskQueueConfigResponse"\xc9\x01\x82\xd3\xe4\x93\x02\x8f\x01">/namespaces/{namespace}/task-queues/{task_queue}/update-config:\x01*ZJ"E/api/v1/namespaces/{namespace}/task-queues/{task_queue}/update-config:\x01*\x8a\x9d\xcc\x1b.\n\x14temporal-resource-id\x12\x16taskqueue:{task_queue}\x12\xa8\x02\n\x11\x46\x65tchWorkerConfig\x12\x39.temporal.api.workflowservice.v1.FetchWorkerConfigRequest\x1a:.temporal.api.workflowservice.v1.FetchWorkerConfigResponse"\x9b\x01\x82\xd3\xe4\x93\x02k",/namespaces/{namespace}/workers/fetch-config:\x01*Z8"3/api/v1/namespaces/{namespace}/workers/fetch-config:\x01*\x8a\x9d\xcc\x1b%\n\x14temporal-resource-id\x12\r{resource_id}\x12\xad\x02\n\x12UpdateWorkerConfig\x12:.temporal.api.workflowservice.v1.UpdateWorkerConfigRequest\x1a;.temporal.api.workflowservice.v1.UpdateWorkerConfigResponse"\x9d\x01\x82\xd3\xe4\x93\x02m"-/namespaces/{namespace}/workers/update-config:\x01*Z9"4/api/v1/namespaces/{namespace}/workers/update-config:\x01*\x8a\x9d\xcc\x1b%\n\x14temporal-resource-id\x12\r{resource_id}\x12\xcd\x02\n\x0e\x44\x65scribeWorker\x12\x36.temporal.api.workflowservice.v1.DescribeWorkerRequest\x1a\x37.temporal.api.workflowservice.v1.DescribeWorkerResponse"\xc9\x01\x82\xd3\xe4\x93\x02\x89\x01\x12>/namespaces/{namespace}/workers/describe/{worker_instance_key}ZG\x12\x45/api/v1/namespaces/{namespace}/workers/describe/{worker_instance_key}\x8a\x9d\xcc\x1b\x34\n\x14temporal-resource-id\x12\x1cworker:{worker_instance_key}\x12\xd2\x02\n\x16PauseWorkflowExecution\x12>.temporal.api.workflowservice.v1.PauseWorkflowExecutionRequest\x1a?.temporal.api.workflowservice.v1.PauseWorkflowExecutionResponse"\xb6\x01\x82\xd3\xe4\x93\x02}"5/namespaces/{namespace}/workflows/{workflow_id}/pause:\x01*ZA"/api/v1/namespaces/{namespace}/workflows/{workflow_id}/unpause:\x01*\x8a\x9d\xcc\x1b.\n\x14temporal-resource-id\x12\x16workflow:{workflow_id}\x12\xc8\x02\n\x16StartActivityExecution\x12>.temporal.api.workflowservice.v1.StartActivityExecutionRequest\x1a?.temporal.api.workflowservice.v1.StartActivityExecutionResponse"\xac\x01\x82\xd3\xe4\x93\x02s"0/namespaces/{namespace}/activities/{activity_id}:\x01*Z<"7/api/v1/namespaces/{namespace}/activities/{activity_id}:\x01*\x8a\x9d\xcc\x1b.\n\x14temporal-resource-id\x12\x16\x61\x63tivity:{activity_id}\x12\xb6\x02\n\x1cStartNexusOperationExecution\x12\x44.temporal.api.workflowservice.v1.StartNexusOperationExecutionRequest\x1a\x45.temporal.api.workflowservice.v1.StartNexusOperationExecutionResponse"\x88\x01\x82\xd3\xe4\x93\x02\x81\x01"7/namespaces/{namespace}/nexus-operations/{operation_id}:\x01*ZC">/api/v1/namespaces/{namespace}/nexus-operations/{operation_id}:\x01*\x12\xcb\x02\n\x19\x44\x65scribeActivityExecution\x12\x41.temporal.api.workflowservice.v1.DescribeActivityExecutionRequest\x1a\x42.temporal.api.workflowservice.v1.DescribeActivityExecutionResponse"\xa6\x01\x82\xd3\xe4\x93\x02m\x12\x30/namespaces/{namespace}/activities/{activity_id}Z9\x12\x37/api/v1/namespaces/{namespace}/activities/{activity_id}\x8a\x9d\xcc\x1b.\n\x14temporal-resource-id\x12\x16\x61\x63tivity:{activity_id}\x12\xb8\x02\n\x1f\x44\x65scribeNexusOperationExecution\x12G.temporal.api.workflowservice.v1.DescribeNexusOperationExecutionRequest\x1aH.temporal.api.workflowservice.v1.DescribeNexusOperationExecutionResponse"\x81\x01\x82\xd3\xe4\x93\x02{\x12\x37/namespaces/{namespace}/nexus-operations/{operation_id}Z@\x12>/api/v1/namespaces/{namespace}/nexus-operations/{operation_id}\x12\xcf\x02\n\x15PollActivityExecution\x12=.temporal.api.workflowservice.v1.PollActivityExecutionRequest\x1a>.temporal.api.workflowservice.v1.PollActivityExecutionResponse"\xb6\x01\x82\xd3\xe4\x93\x02}\x12\x38/namespaces/{namespace}/activities/{activity_id}/outcomeZA\x12?/api/v1/namespaces/{namespace}/activities/{activity_id}/outcome\x8a\x9d\xcc\x1b.\n\x14temporal-resource-id\x12\x16\x61\x63tivity:{activity_id}\x12\xb7\x02\n\x1bPollNexusOperationExecution\x12\x43.temporal.api.workflowservice.v1.PollNexusOperationExecutionRequest\x1a\x44.temporal.api.workflowservice.v1.PollNexusOperationExecutionResponse"\x8c\x01\x82\xd3\xe4\x93\x02\x85\x01\x12.temporal.api.workflowservice.v1.ListActivityExecutionsRequest\x1a?.temporal.api.workflowservice.v1.ListActivityExecutionsResponse"W\x82\xd3\xe4\x93\x02Q\x12"/namespaces/{namespace}/activitiesZ+\x12)/api/v1/namespaces/{namespace}/activities\x12\x90\x02\n\x1cListNexusOperationExecutions\x12\x44.temporal.api.workflowservice.v1.ListNexusOperationExecutionsRequest\x1a\x45.temporal.api.workflowservice.v1.ListNexusOperationExecutionsResponse"c\x82\xd3\xe4\x93\x02]\x12(/namespaces/{namespace}/nexus-operationsZ1\x12//api/v1/namespaces/{namespace}/nexus-operations\x12\xfd\x01\n\x17\x43ountActivityExecutions\x12?.temporal.api.workflowservice.v1.CountActivityExecutionsRequest\x1a@.temporal.api.workflowservice.v1.CountActivityExecutionsResponse"_\x82\xd3\xe4\x93\x02Y\x12&/namespaces/{namespace}/activity-countZ/\x12-/api/v1/namespaces/{namespace}/activity-count\x12\x9d\x02\n\x1d\x43ountNexusOperationExecutions\x12\x45.temporal.api.workflowservice.v1.CountNexusOperationExecutionsRequest\x1a\x46.temporal.api.workflowservice.v1.CountNexusOperationExecutionsResponse"m\x82\xd3\xe4\x93\x02g\x12-/namespaces/{namespace}/nexus-operation-countZ6\x12\x34/api/v1/namespaces/{namespace}/nexus-operation-count\x12\xef\x02\n\x1eRequestCancelActivityExecution\x12\x46.temporal.api.workflowservice.v1.RequestCancelActivityExecutionRequest\x1aG.temporal.api.workflowservice.v1.RequestCancelActivityExecutionResponse"\xbb\x01\x82\xd3\xe4\x93\x02\x81\x01"7/namespaces/{namespace}/activities/{activity_id}/cancel:\x01*ZC">/api/v1/namespaces/{namespace}/activities/{activity_id}/cancel:\x01*\x8a\x9d\xcc\x1b.\n\x14temporal-resource-id\x12\x16\x61\x63tivity:{activity_id}\x12\xdc\x02\n$RequestCancelNexusOperationExecution\x12L.temporal.api.workflowservice.v1.RequestCancelNexusOperationExecutionRequest\x1aM.temporal.api.workflowservice.v1.RequestCancelNexusOperationExecutionResponse"\x96\x01\x82\xd3\xe4\x93\x02\x8f\x01">/namespaces/{namespace}/nexus-operations/{operation_id}/cancel:\x01*ZJ"E/api/v1/namespaces/{namespace}/nexus-operations/{operation_id}/cancel:\x01*\x12\xe9\x02\n\x1aTerminateActivityExecution\x12\x42.temporal.api.workflowservice.v1.TerminateActivityExecutionRequest\x1a\x43.temporal.api.workflowservice.v1.TerminateActivityExecutionResponse"\xc1\x01\x82\xd3\xe4\x93\x02\x87\x01":/namespaces/{namespace}/activities/{activity_id}/terminate:\x01*ZF"A/api/v1/namespaces/{namespace}/activities/{activity_id}/terminate:\x01*\x8a\x9d\xcc\x1b.\n\x14temporal-resource-id\x12\x16\x61\x63tivity:{activity_id}\x12\x9e\x01\n\x17\x44\x65leteActivityExecution\x12?.temporal.api.workflowservice.v1.DeleteActivityExecutionRequest\x1a@.temporal.api.workflowservice.v1.DeleteActivityExecutionResponse"\x00\x12\xfd\x03\n\x16PauseActivityExecution\x12>.temporal.api.workflowservice.v1.PauseActivityExecutionRequest\x1a?.temporal.api.workflowservice.v1.PauseActivityExecutionResponse"\xe1\x02\x82\xd3\xe4\x93\x02\xb0\x02"6/namespaces/{namespace}/activities/{activity_id}/pause:\x01*ZB"=/api/v1/namespaces/{namespace}/activities/{activity_id}/pause:\x01*ZS"N/namespaces/{namespace}/workflows/{workflow_id}/activities/{activity_id}/pause:\x01*ZZ"U/api/v1/namespaces/{namespace}/workflows/{workflow_id}/activities/{activity_id}/pause:\x01*\x8a\x9d\xcc\x1b%\n\x14temporal-resource-id\x12\r{resource_id}\x12\xfd\x03\n\x16ResetActivityExecution\x12>.temporal.api.workflowservice.v1.ResetActivityExecutionRequest\x1a?.temporal.api.workflowservice.v1.ResetActivityExecutionResponse"\xe1\x02\x82\xd3\xe4\x93\x02\xb0\x02"6/namespaces/{namespace}/activities/{activity_id}/reset:\x01*ZB"=/api/v1/namespaces/{namespace}/activities/{activity_id}/reset:\x01*ZS"N/namespaces/{namespace}/workflows/{workflow_id}/activities/{activity_id}/reset:\x01*ZZ"U/api/v1/namespaces/{namespace}/workflows/{workflow_id}/activities/{activity_id}/reset:\x01*\x8a\x9d\xcc\x1b%\n\x14temporal-resource-id\x12\r{resource_id}\x12\x8b\x04\n\x18UnpauseActivityExecution\x12@.temporal.api.workflowservice.v1.UnpauseActivityExecutionRequest\x1a\x41.temporal.api.workflowservice.v1.UnpauseActivityExecutionResponse"\xe9\x02\x82\xd3\xe4\x93\x02\xb8\x02"8/namespaces/{namespace}/activities/{activity_id}/unpause:\x01*ZD"?/api/v1/namespaces/{namespace}/activities/{activity_id}/unpause:\x01*ZU"P/namespaces/{namespace}/workflows/{workflow_id}/activities/{activity_id}/unpause:\x01*Z\\"W/api/v1/namespaces/{namespace}/workflows/{workflow_id}/activities/{activity_id}/unpause:\x01*\x8a\x9d\xcc\x1b%\n\x14temporal-resource-id\x12\r{resource_id}\x12\xb9\x04\n\x1eUpdateActivityExecutionOptions\x12\x46.temporal.api.workflowservice.v1.UpdateActivityExecutionOptionsRequest\x1aG.temporal.api.workflowservice.v1.UpdateActivityExecutionOptionsResponse"\x85\x03\x82\xd3\xe4\x93\x02\xd4\x02"?/namespaces/{namespace}/activities/{activity_id}/update-options:\x01*ZK"F/api/v1/namespaces/{namespace}/activities/{activity_id}/update-options:\x01*Z\\"W/namespaces/{namespace}/workflows/{workflow_id}/activities/{activity_id}/update-options:\x01*Zc"^/api/v1/namespaces/{namespace}/workflows/{workflow_id}/activities/{activity_id}/update-options:\x01*\x8a\x9d\xcc\x1b%\n\x14temporal-resource-id\x12\r{resource_id}\x12\xd6\x02\n TerminateNexusOperationExecution\x12H.temporal.api.workflowservice.v1.TerminateNexusOperationExecutionRequest\x1aI.temporal.api.workflowservice.v1.TerminateNexusOperationExecutionResponse"\x9c\x01\x82\xd3\xe4\x93\x02\x95\x01"A/namespaces/{namespace}/nexus-operations/{operation_id}/terminate:\x01*ZM"H/api/v1/namespaces/{namespace}/nexus-operations/{operation_id}/terminate:\x01*\x12\xb0\x01\n\x1d\x44\x65leteNexusOperationExecution\x12\x45.temporal.api.workflowservice.v1.DeleteNexusOperationExecutionRequest\x1a\x46.temporal.api.workflowservice.v1.DeleteNexusOperationExecutionResponse"\x00\x42\xb6\x01\n"io.temporal.api.workflowservice.v1B\x0cServiceProtoP\x01Z5go.temporal.io/api/workflowservice/v1;workflowservice\xaa\x02!Temporalio.Api.WorkflowService.V1\xea\x02$Temporalio::Api::WorkflowService::V1b\x06proto3' + b'\n-temporal/api/workflowservice/v1/service.proto\x12\x1ftemporal.api.workflowservice.v1\x1a\x1cgoogle/api/annotations.proto\x1a!nexusannotations/v1/options.proto\x1a+temporal/api/protometa/v1/annotations.proto\x1a\x36temporal/api/workflowservice/v1/request_response.proto2\x98\xaf\x02\n\x0fWorkflowService\x12\xc3\x01\n\x11RegisterNamespace\x12\x39.temporal.api.workflowservice.v1.RegisterNamespaceRequest\x1a:.temporal.api.workflowservice.v1.RegisterNamespaceResponse"7\x82\xd3\xe4\x93\x02\x31"\x13/cluster/namespaces:\x01*Z\x17"\x12/api/v1/namespaces:\x01*\x12\xd5\x01\n\x11\x44\x65scribeNamespace\x12\x39.temporal.api.workflowservice.v1.DescribeNamespaceRequest\x1a:.temporal.api.workflowservice.v1.DescribeNamespaceResponse"I\x82\xd3\xe4\x93\x02\x43\x12\x1f/cluster/namespaces/{namespace}Z \x12\x1e/api/v1/namespaces/{namespace}\x12\xb4\x01\n\x0eListNamespaces\x12\x36.temporal.api.workflowservice.v1.ListNamespacesRequest\x1a\x37.temporal.api.workflowservice.v1.ListNamespacesResponse"1\x82\xd3\xe4\x93\x02+\x12\x13/cluster/namespacesZ\x14\x12\x12/api/v1/namespaces\x12\xe3\x01\n\x0fUpdateNamespace\x12\x37.temporal.api.workflowservice.v1.UpdateNamespaceRequest\x1a\x38.temporal.api.workflowservice.v1.UpdateNamespaceResponse"]\x82\xd3\xe4\x93\x02W"&/cluster/namespaces/{namespace}/update:\x01*Z*"%/api/v1/namespaces/{namespace}/update:\x01*\x12\x8f\x01\n\x12\x44\x65precateNamespace\x12:.temporal.api.workflowservice.v1.DeprecateNamespaceRequest\x1a;.temporal.api.workflowservice.v1.DeprecateNamespaceResponse"\x00\x12\xc6\x02\n\x16StartWorkflowExecution\x12>.temporal.api.workflowservice.v1.StartWorkflowExecutionRequest\x1a?.temporal.api.workflowservice.v1.StartWorkflowExecutionResponse"\xaa\x01\x82\xd3\xe4\x93\x02q"//namespaces/{namespace}/workflows/{workflow_id}:\x01*Z;"6/api/v1/namespaces/{namespace}/workflows/{workflow_id}:\x01*\x8a\x9d\xcc\x1b.\n\x14temporal-resource-id\x12\x16workflow:{workflow_id}\x12\xc2\x01\n\x15\x45xecuteMultiOperation\x12=.temporal.api.workflowservice.v1.ExecuteMultiOperationRequest\x1a>.temporal.api.workflowservice.v1.ExecuteMultiOperationResponse"*\x8a\x9d\xcc\x1b%\n\x14temporal-resource-id\x12\r{resource_id}\x12\xfe\x02\n\x1bGetWorkflowExecutionHistory\x12\x43.temporal.api.workflowservice.v1.GetWorkflowExecutionHistoryRequest\x1a\x44.temporal.api.workflowservice.v1.GetWorkflowExecutionHistoryResponse"\xd3\x01\x82\xd3\xe4\x93\x02\x8f\x01\x12\x41/namespaces/{namespace}/workflows/{execution.workflow_id}/historyZJ\x12H/api/v1/namespaces/{namespace}/workflows/{execution.workflow_id}/history\x8a\x9d\xcc\x1b\x38\n\x14temporal-resource-id\x12 workflow:{execution.workflow_id}\x12\xa3\x03\n"GetWorkflowExecutionHistoryReverse\x12J.temporal.api.workflowservice.v1.GetWorkflowExecutionHistoryReverseRequest\x1aK.temporal.api.workflowservice.v1.GetWorkflowExecutionHistoryReverseResponse"\xe3\x01\x82\xd3\xe4\x93\x02\x9f\x01\x12I/namespaces/{namespace}/workflows/{execution.workflow_id}/history-reverseZR\x12P/api/v1/namespaces/{namespace}/workflows/{execution.workflow_id}/history-reverse\x8a\x9d\xcc\x1b\x38\n\x14temporal-resource-id\x12 workflow:{execution.workflow_id}\x12\xcd\x01\n\x15PollWorkflowTaskQueue\x12=.temporal.api.workflowservice.v1.PollWorkflowTaskQueueRequest\x1a>.temporal.api.workflowservice.v1.PollWorkflowTaskQueueResponse"5\x8a\x9d\xcc\x1b\x30\n\x14temporal-resource-id\x12\x18poller:{poller_group_id}\x12\xd7\x01\n\x1cRespondWorkflowTaskCompleted\x12\x44.temporal.api.workflowservice.v1.RespondWorkflowTaskCompletedRequest\x1a\x45.temporal.api.workflowservice.v1.RespondWorkflowTaskCompletedResponse"*\x8a\x9d\xcc\x1b%\n\x14temporal-resource-id\x12\r{resource_id}\x12\xce\x01\n\x19RespondWorkflowTaskFailed\x12\x41.temporal.api.workflowservice.v1.RespondWorkflowTaskFailedRequest\x1a\x42.temporal.api.workflowservice.v1.RespondWorkflowTaskFailedResponse"*\x8a\x9d\xcc\x1b%\n\x14temporal-resource-id\x12\r{resource_id}\x12\xcd\x01\n\x15PollActivityTaskQueue\x12=.temporal.api.workflowservice.v1.PollActivityTaskQueueRequest\x1a>.temporal.api.workflowservice.v1.PollActivityTaskQueueResponse"5\x8a\x9d\xcc\x1b\x30\n\x14temporal-resource-id\x12\x18poller:{poller_group_id}\x12\xc2\x02\n\x1bRecordActivityTaskHeartbeat\x12\x43.temporal.api.workflowservice.v1.RecordActivityTaskHeartbeatRequest\x1a\x44.temporal.api.workflowservice.v1.RecordActivityTaskHeartbeatResponse"\x97\x01\x82\xd3\xe4\x93\x02g"*/namespaces/{namespace}/activity-heartbeat:\x01*Z6"1/api/v1/namespaces/{namespace}/activity-heartbeat:\x01*\x8a\x9d\xcc\x1b%\n\x14temporal-resource-id\x12\r{resource_id}\x12\xa8\x04\n\x1fRecordActivityTaskHeartbeatById\x12G.temporal.api.workflowservice.v1.RecordActivityTaskHeartbeatByIdRequest\x1aH.temporal.api.workflowservice.v1.RecordActivityTaskHeartbeatByIdResponse"\xf1\x02\x82\xd3\xe4\x93\x02\xc0\x02":/namespaces/{namespace}/activities/{activity_id}/heartbeat:\x01*ZF"A/api/v1/namespaces/{namespace}/activities/{activity_id}/heartbeat:\x01*ZW"R/namespaces/{namespace}/workflows/{workflow_id}/activities/{activity_id}/heartbeat:\x01*Z^"Y/api/v1/namespaces/{namespace}/workflows/{workflow_id}/activities/{activity_id}/heartbeat:\x01*\x8a\x9d\xcc\x1b%\n\x14temporal-resource-id\x12\r{resource_id}\x12\xc3\x02\n\x1cRespondActivityTaskCompleted\x12\x44.temporal.api.workflowservice.v1.RespondActivityTaskCompletedRequest\x1a\x45.temporal.api.workflowservice.v1.RespondActivityTaskCompletedResponse"\x95\x01\x82\xd3\xe4\x93\x02\x65")/namespaces/{namespace}/activity-complete:\x01*Z5"0/api/v1/namespaces/{namespace}/activity-complete:\x01*\x8a\x9d\xcc\x1b%\n\x14temporal-resource-id\x12\r{resource_id}\x12\xa7\x04\n RespondActivityTaskCompletedById\x12H.temporal.api.workflowservice.v1.RespondActivityTaskCompletedByIdRequest\x1aI.temporal.api.workflowservice.v1.RespondActivityTaskCompletedByIdResponse"\xed\x02\x82\xd3\xe4\x93\x02\xbc\x02"9/namespaces/{namespace}/activities/{activity_id}/complete:\x01*ZE"@/api/v1/namespaces/{namespace}/activities/{activity_id}/complete:\x01*ZV"Q/namespaces/{namespace}/workflows/{workflow_id}/activities/{activity_id}/complete:\x01*Z]"X/api/v1/namespaces/{namespace}/workflows/{workflow_id}/activities/{activity_id}/complete:\x01*\x8a\x9d\xcc\x1b%\n\x14temporal-resource-id\x12\r{resource_id}\x12\xb2\x02\n\x19RespondActivityTaskFailed\x12\x41.temporal.api.workflowservice.v1.RespondActivityTaskFailedRequest\x1a\x42.temporal.api.workflowservice.v1.RespondActivityTaskFailedResponse"\x8d\x01\x82\xd3\xe4\x93\x02]"%/namespaces/{namespace}/activity-fail:\x01*Z1",/api/v1/namespaces/{namespace}/activity-fail:\x01*\x8a\x9d\xcc\x1b%\n\x14temporal-resource-id\x12\r{resource_id}\x12\x8e\x04\n\x1dRespondActivityTaskFailedById\x12\x45.temporal.api.workflowservice.v1.RespondActivityTaskFailedByIdRequest\x1a\x46.temporal.api.workflowservice.v1.RespondActivityTaskFailedByIdResponse"\xdd\x02\x82\xd3\xe4\x93\x02\xac\x02"5/namespaces/{namespace}/activities/{activity_id}/fail:\x01*ZA".temporal.api.workflowservice.v1.ResetWorkflowExecutionRequest\x1a?.temporal.api.workflowservice.v1.ResetWorkflowExecutionResponse"\xf0\x01\x82\xd3\xe4\x93\x02\xa3\x01"H/namespaces/{namespace}/workflows/{workflow_execution.workflow_id}/reset:\x01*ZT"O/api/v1/namespaces/{namespace}/workflows/{workflow_execution.workflow_id}/reset:\x01*\x8a\x9d\xcc\x1b\x41\n\x14temporal-resource-id\x12)workflow:{workflow_execution.workflow_id}\x12\xa0\x03\n\x1aTerminateWorkflowExecution\x12\x42.temporal.api.workflowservice.v1.TerminateWorkflowExecutionRequest\x1a\x43.temporal.api.workflowservice.v1.TerminateWorkflowExecutionResponse"\xf8\x01\x82\xd3\xe4\x93\x02\xab\x01"L/namespaces/{namespace}/workflows/{workflow_execution.workflow_id}/terminate:\x01*ZX"S/api/v1/namespaces/{namespace}/workflows/{workflow_execution.workflow_id}/terminate:\x01*\x8a\x9d\xcc\x1b\x41\n\x14temporal-resource-id\x12)workflow:{workflow_execution.workflow_id}\x12\xe4\x01\n\x17\x44\x65leteWorkflowExecution\x12?.temporal.api.workflowservice.v1.DeleteWorkflowExecutionRequest\x1a@.temporal.api.workflowservice.v1.DeleteWorkflowExecutionResponse"F\x8a\x9d\xcc\x1b\x41\n\x14temporal-resource-id\x12)workflow:{workflow_execution.workflow_id}\x12\xa7\x01\n\x1aListOpenWorkflowExecutions\x12\x42.temporal.api.workflowservice.v1.ListOpenWorkflowExecutionsRequest\x1a\x43.temporal.api.workflowservice.v1.ListOpenWorkflowExecutionsResponse"\x00\x12\xad\x01\n\x1cListClosedWorkflowExecutions\x12\x44.temporal.api.workflowservice.v1.ListClosedWorkflowExecutionsRequest\x1a\x45.temporal.api.workflowservice.v1.ListClosedWorkflowExecutionsResponse"\x00\x12\xf0\x01\n\x16ListWorkflowExecutions\x12>.temporal.api.workflowservice.v1.ListWorkflowExecutionsRequest\x1a?.temporal.api.workflowservice.v1.ListWorkflowExecutionsResponse"U\x82\xd3\xe4\x93\x02O\x12!/namespaces/{namespace}/workflowsZ*\x12(/api/v1/namespaces/{namespace}/workflows\x12\x9a\x02\n\x1eListArchivedWorkflowExecutions\x12\x46.temporal.api.workflowservice.v1.ListArchivedWorkflowExecutionsRequest\x1aG.temporal.api.workflowservice.v1.ListArchivedWorkflowExecutionsResponse"g\x82\xd3\xe4\x93\x02\x61\x12*/namespaces/{namespace}/archived-workflowsZ3\x12\x31/api/v1/namespaces/{namespace}/archived-workflows\x12\x9b\x01\n\x16ScanWorkflowExecutions\x12>.temporal.api.workflowservice.v1.ScanWorkflowExecutionsRequest\x1a?.temporal.api.workflowservice.v1.ScanWorkflowExecutionsResponse"\x00\x12\xfd\x01\n\x17\x43ountWorkflowExecutions\x12?.temporal.api.workflowservice.v1.CountWorkflowExecutionsRequest\x1a@.temporal.api.workflowservice.v1.CountWorkflowExecutionsResponse"_\x82\xd3\xe4\x93\x02Y\x12&/namespaces/{namespace}/workflow-countZ/\x12-/api/v1/namespaces/{namespace}/workflow-count\x12\x92\x01\n\x13GetSearchAttributes\x12;.temporal.api.workflowservice.v1.GetSearchAttributesRequest\x1a<.temporal.api.workflowservice.v1.GetSearchAttributesResponse"\x00\x12\xd9\x01\n\x19RespondQueryTaskCompleted\x12\x41.temporal.api.workflowservice.v1.RespondQueryTaskCompletedRequest\x1a\x42.temporal.api.workflowservice.v1.RespondQueryTaskCompletedResponse"5\x8a\x9d\xcc\x1b\x30\n\x14temporal-resource-id\x12\x18poller:{poller_group_id}\x12\xd2\x01\n\x14ResetStickyTaskQueue\x12<.temporal.api.workflowservice.v1.ResetStickyTaskQueueRequest\x1a=.temporal.api.workflowservice.v1.ResetStickyTaskQueueResponse"=\x8a\x9d\xcc\x1b\x38\n\x14temporal-resource-id\x12 workflow:{execution.workflow_id}\x12\x83\x01\n\x0eShutdownWorker\x12\x36.temporal.api.workflowservice.v1.ShutdownWorkerRequest\x1a\x37.temporal.api.workflowservice.v1.ShutdownWorkerResponse"\x00\x12\xfc\x02\n\rQueryWorkflow\x12\x35.temporal.api.workflowservice.v1.QueryWorkflowRequest\x1a\x36.temporal.api.workflowservice.v1.QueryWorkflowResponse"\xfb\x01\x82\xd3\xe4\x93\x02\xb7\x01"R/namespaces/{namespace}/workflows/{execution.workflow_id}/query/{query.query_type}:\x01*Z^"Y/api/v1/namespaces/{namespace}/workflows/{execution.workflow_id}/query/{query.query_type}:\x01*\x8a\x9d\xcc\x1b\x38\n\x14temporal-resource-id\x12 workflow:{execution.workflow_id}\x12\xe7\x02\n\x19\x44\x65scribeWorkflowExecution\x12\x41.temporal.api.workflowservice.v1.DescribeWorkflowExecutionRequest\x1a\x42.temporal.api.workflowservice.v1.DescribeWorkflowExecutionResponse"\xc2\x01\x82\xd3\xe4\x93\x02\x7f\x12\x39/namespaces/{namespace}/workflows/{execution.workflow_id}ZB\x12@/api/v1/namespaces/{namespace}/workflows/{execution.workflow_id}\x8a\x9d\xcc\x1b\x38\n\x14temporal-resource-id\x12 workflow:{execution.workflow_id}\x12\xc2\x02\n\x11\x44\x65scribeTaskQueue\x12\x39.temporal.api.workflowservice.v1.DescribeTaskQueueRequest\x1a:.temporal.api.workflowservice.v1.DescribeTaskQueueResponse"\xb5\x01\x82\xd3\xe4\x93\x02w\x12\x35/namespaces/{namespace}/task-queues/{task_queue.name}Z>\x12/namespaces/{namespace}/schedules/{schedule_id}/matching-timesZG\x12\x45/api/v1/namespaces/{namespace}/schedules/{schedule_id}/matching-times\x8a\x9d\xcc\x1b.\n\x14temporal-resource-id\x12\x16schedule:{schedule_id}\x12\xa8\x02\n\x0e\x44\x65leteSchedule\x12\x36.temporal.api.workflowservice.v1.DeleteScheduleRequest\x1a\x37.temporal.api.workflowservice.v1.DeleteScheduleResponse"\xa4\x01\x82\xd3\xe4\x93\x02k*//namespaces/{namespace}/schedules/{schedule_id}Z8*6/api/v1/namespaces/{namespace}/schedules/{schedule_id}\x8a\x9d\xcc\x1b.\n\x14temporal-resource-id\x12\x16schedule:{schedule_id}\x12\xd5\x01\n\rListSchedules\x12\x35.temporal.api.workflowservice.v1.ListSchedulesRequest\x1a\x36.temporal.api.workflowservice.v1.ListSchedulesResponse"U\x82\xd3\xe4\x93\x02O\x12!/namespaces/{namespace}/schedulesZ*\x12(/api/v1/namespaces/{namespace}/schedules\x12\xe2\x01\n\x0e\x43ountSchedules\x12\x36.temporal.api.workflowservice.v1.CountSchedulesRequest\x1a\x37.temporal.api.workflowservice.v1.CountSchedulesResponse"_\x82\xd3\xe4\x93\x02Y\x12&/namespaces/{namespace}/schedule-countZ/\x12-/api/v1/namespaces/{namespace}/schedule-count\x12\xb9\x01\n UpdateWorkerBuildIdCompatibility\x12H.temporal.api.workflowservice.v1.UpdateWorkerBuildIdCompatibilityRequest\x1aI.temporal.api.workflowservice.v1.UpdateWorkerBuildIdCompatibilityResponse"\x00\x12\xe1\x02\n\x1dGetWorkerBuildIdCompatibility\x12\x45.temporal.api.workflowservice.v1.GetWorkerBuildIdCompatibilityRequest\x1a\x46.temporal.api.workflowservice.v1.GetWorkerBuildIdCompatibilityResponse"\xb0\x01\x82\xd3\xe4\x93\x02\xa9\x01\x12N/namespaces/{namespace}/task-queues/{task_queue}/worker-build-id-compatibilityZW\x12U/api/v1/namespaces/{namespace}/task-queues/{task_queue}/worker-build-id-compatibility\x12\xaa\x01\n\x1bUpdateWorkerVersioningRules\x12\x43.temporal.api.workflowservice.v1.UpdateWorkerVersioningRulesRequest\x1a\x44.temporal.api.workflowservice.v1.UpdateWorkerVersioningRulesResponse"\x00\x12\xc6\x02\n\x18GetWorkerVersioningRules\x12@.temporal.api.workflowservice.v1.GetWorkerVersioningRulesRequest\x1a\x41.temporal.api.workflowservice.v1.GetWorkerVersioningRulesResponse"\xa4\x01\x82\xd3\xe4\x93\x02\x9d\x01\x12H/namespaces/{namespace}/task-queues/{task_queue}/worker-versioning-rulesZQ\x12O/api/v1/namespaces/{namespace}/task-queues/{task_queue}/worker-versioning-rules\x12\x97\x02\n\x19GetWorkerTaskReachability\x12\x41.temporal.api.workflowservice.v1.GetWorkerTaskReachabilityRequest\x1a\x42.temporal.api.workflowservice.v1.GetWorkerTaskReachabilityResponse"s\x82\xd3\xe4\x93\x02m\x12\x30/namespaces/{namespace}/worker-task-reachabilityZ9\x12\x37/api/v1/namespaces/{namespace}/worker-task-reachability\x12\xc8\x02\n\x12\x44\x65scribeDeployment\x12:.temporal.api.workflowservice.v1.DescribeDeploymentRequest\x1a;.temporal.api.workflowservice.v1.DescribeDeploymentResponse"\xb8\x01\x82\xd3\xe4\x93\x02\xb1\x01\x12R/namespaces/{namespace}/deployments/{deployment.series_name}/{deployment.build_id}Z[\x12Y/api/v1/namespaces/{namespace}/deployments/{deployment.series_name}/{deployment.build_id}\x12\x81\x04\n\x1f\x44\x65scribeWorkerDeploymentVersion\x12G.temporal.api.workflowservice.v1.DescribeWorkerDeploymentVersionRequest\x1aH.temporal.api.workflowservice.v1.DescribeWorkerDeploymentVersionResponse"\xca\x02\x82\xd3\xe4\x93\x02\xf7\x01\x12u/namespaces/{namespace}/worker-deployment-versions/{deployment_version.deployment_name}/{deployment_version.build_id}Z~\x12|/api/v1/namespaces/{namespace}/worker-deployment-versions/{deployment_version.deployment_name}/{deployment_version.build_id}\x8a\x9d\xcc\x1bG\n\x14temporal-resource-id\x12/deployment:{deployment_version.deployment_name}\x12\xdf\x01\n\x0fListDeployments\x12\x37.temporal.api.workflowservice.v1.ListDeploymentsRequest\x1a\x38.temporal.api.workflowservice.v1.ListDeploymentsResponse"Y\x82\xd3\xe4\x93\x02S\x12#/namespaces/{namespace}/deploymentsZ,\x12*/api/v1/namespaces/{namespace}/deployments\x12\xf7\x02\n\x19GetDeploymentReachability\x12\x41.temporal.api.workflowservice.v1.GetDeploymentReachabilityRequest\x1a\x42.temporal.api.workflowservice.v1.GetDeploymentReachabilityResponse"\xd2\x01\x82\xd3\xe4\x93\x02\xcb\x01\x12_/namespaces/{namespace}/deployments/{deployment.series_name}/{deployment.build_id}/reachabilityZh\x12\x66/api/v1/namespaces/{namespace}/deployments/{deployment.series_name}/{deployment.build_id}/reachability\x12\x99\x02\n\x14GetCurrentDeployment\x12<.temporal.api.workflowservice.v1.GetCurrentDeploymentRequest\x1a=.temporal.api.workflowservice.v1.GetCurrentDeploymentResponse"\x83\x01\x82\xd3\xe4\x93\x02}\x12\x38/namespaces/{namespace}/current-deployment/{series_name}ZA\x12?/api/v1/namespaces/{namespace}/current-deployment/{series_name}\x12\xb6\x02\n\x14SetCurrentDeployment\x12<.temporal.api.workflowservice.v1.SetCurrentDeploymentRequest\x1a=.temporal.api.workflowservice.v1.SetCurrentDeploymentResponse"\xa0\x01\x82\xd3\xe4\x93\x02\x99\x01"C/namespaces/{namespace}/current-deployment/{deployment.series_name}:\x01*ZO"J/api/v1/namespaces/{namespace}/current-deployment/{deployment.series_name}:\x01*\x12\xb0\x03\n!SetWorkerDeploymentCurrentVersion\x12I.temporal.api.workflowservice.v1.SetWorkerDeploymentCurrentVersionRequest\x1aJ.temporal.api.workflowservice.v1.SetWorkerDeploymentCurrentVersionResponse"\xf3\x01\x82\xd3\xe4\x93\x02\xb3\x01"P/namespaces/{namespace}/worker-deployments/{deployment_name}/set-current-version:\x01*Z\\"W/api/v1/namespaces/{namespace}/worker-deployments/{deployment_name}/set-current-version:\x01*\x8a\x9d\xcc\x1b\x34\n\x14temporal-resource-id\x12\x1c\x64\x65ployment:{deployment_name}\x12\xe7\x02\n\x18\x44\x65scribeWorkerDeployment\x12@.temporal.api.workflowservice.v1.DescribeWorkerDeploymentRequest\x1a\x41.temporal.api.workflowservice.v1.DescribeWorkerDeploymentResponse"\xc5\x01\x82\xd3\xe4\x93\x02\x85\x01\x12.temporal.api.workflowservice.v1.DeleteWorkerDeploymentRequest\x1a?.temporal.api.workflowservice.v1.DeleteWorkerDeploymentResponse"\xc5\x01\x82\xd3\xe4\x93\x02\x85\x01*.temporal.api.workflowservice.v1.ListWorkerDeploymentsResponse"g\x82\xd3\xe4\x93\x02\x61\x12*/namespaces/{namespace}/worker-deploymentsZ3\x12\x31/api/v1/namespaces/{namespace}/worker-deployments\x12\xae\x02\n\x16\x43reateWorkerDeployment\x12>.temporal.api.workflowservice.v1.CreateWorkerDeploymentRequest\x1a?.temporal.api.workflowservice.v1.CreateWorkerDeploymentResponse"\x92\x01\x82\xd3\xe4\x93\x02\x8b\x01".temporal.api.workflowservice.v1.DescribeBatchOperationRequest\x1a?.temporal.api.workflowservice.v1.DescribeBatchOperationResponse"\xa0\x01\x82\xd3\xe4\x93\x02o\x12\x31/namespaces/{namespace}/batch-operations/{job_id}Z:\x12\x38/api/v1/namespaces/{namespace}/batch-operations/{job_id}\x8a\x9d\xcc\x1b&\n\x14temporal-resource-id\x12\x0e\x62\x61tch:{job_id}\x12\xf5\x01\n\x13ListBatchOperations\x12;.temporal.api.workflowservice.v1.ListBatchOperationsRequest\x1a<.temporal.api.workflowservice.v1.ListBatchOperationsResponse"c\x82\xd3\xe4\x93\x02]\x12(/namespaces/{namespace}/batch-operationsZ1\x12//api/v1/namespaces/{namespace}/batch-operations\x12\xc4\x01\n\x12PollNexusTaskQueue\x12:.temporal.api.workflowservice.v1.PollNexusTaskQueueRequest\x1a;.temporal.api.workflowservice.v1.PollNexusTaskQueueResponse"5\x8a\x9d\xcc\x1b\x30\n\x14temporal-resource-id\x12\x18poller:{poller_group_id}\x12\xd9\x01\n\x19RespondNexusTaskCompleted\x12\x41.temporal.api.workflowservice.v1.RespondNexusTaskCompletedRequest\x1a\x42.temporal.api.workflowservice.v1.RespondNexusTaskCompletedResponse"5\x8a\x9d\xcc\x1b\x30\n\x14temporal-resource-id\x12\x18poller:{poller_group_id}\x12\xd0\x01\n\x16RespondNexusTaskFailed\x12>.temporal.api.workflowservice.v1.RespondNexusTaskFailedRequest\x1a?.temporal.api.workflowservice.v1.RespondNexusTaskFailedResponse"5\x8a\x9d\xcc\x1b\x30\n\x14temporal-resource-id\x12\x18poller:{poller_group_id}\x12\xe8\x02\n\x15UpdateActivityOptions\x12=.temporal.api.workflowservice.v1.UpdateActivityOptionsRequest\x1a>.temporal.api.workflowservice.v1.UpdateActivityOptionsResponse"\xcf\x01\x82\xd3\xe4\x93\x02\x8b\x01".temporal.api.workflowservice.v1.RecordWorkerHeartbeatResponse"\x95\x01\x82\xd3\xe4\x93\x02\x65")/namespaces/{namespace}/workers/heartbeat:\x01*Z5"0/api/v1/namespaces/{namespace}/workers/heartbeat:\x01*\x8a\x9d\xcc\x1b%\n\x14temporal-resource-id\x12\r{resource_id}\x12\xcb\x01\n\x0bListWorkers\x12\x33.temporal.api.workflowservice.v1.ListWorkersRequest\x1a\x34.temporal.api.workflowservice.v1.ListWorkersResponse"Q\x82\xd3\xe4\x93\x02K\x12\x1f/namespaces/{namespace}/workersZ(\x12&/api/v1/namespaces/{namespace}/workers\x12\xd8\x01\n\x0c\x43ountWorkers\x12\x34.temporal.api.workflowservice.v1.CountWorkersRequest\x1a\x35.temporal.api.workflowservice.v1.CountWorkersResponse"[\x82\xd3\xe4\x93\x02U\x12$/namespaces/{namespace}/worker-countZ-\x12+/api/v1/namespaces/{namespace}/worker-count\x12\xe2\x02\n\x15UpdateTaskQueueConfig\x12=.temporal.api.workflowservice.v1.UpdateTaskQueueConfigRequest\x1a>.temporal.api.workflowservice.v1.UpdateTaskQueueConfigResponse"\xc9\x01\x82\xd3\xe4\x93\x02\x8f\x01">/namespaces/{namespace}/task-queues/{task_queue}/update-config:\x01*ZJ"E/api/v1/namespaces/{namespace}/task-queues/{task_queue}/update-config:\x01*\x8a\x9d\xcc\x1b.\n\x14temporal-resource-id\x12\x16taskqueue:{task_queue}\x12\xa8\x02\n\x11\x46\x65tchWorkerConfig\x12\x39.temporal.api.workflowservice.v1.FetchWorkerConfigRequest\x1a:.temporal.api.workflowservice.v1.FetchWorkerConfigResponse"\x9b\x01\x82\xd3\xe4\x93\x02k",/namespaces/{namespace}/workers/fetch-config:\x01*Z8"3/api/v1/namespaces/{namespace}/workers/fetch-config:\x01*\x8a\x9d\xcc\x1b%\n\x14temporal-resource-id\x12\r{resource_id}\x12\xad\x02\n\x12UpdateWorkerConfig\x12:.temporal.api.workflowservice.v1.UpdateWorkerConfigRequest\x1a;.temporal.api.workflowservice.v1.UpdateWorkerConfigResponse"\x9d\x01\x82\xd3\xe4\x93\x02m"-/namespaces/{namespace}/workers/update-config:\x01*Z9"4/api/v1/namespaces/{namespace}/workers/update-config:\x01*\x8a\x9d\xcc\x1b%\n\x14temporal-resource-id\x12\r{resource_id}\x12\xcd\x02\n\x0e\x44\x65scribeWorker\x12\x36.temporal.api.workflowservice.v1.DescribeWorkerRequest\x1a\x37.temporal.api.workflowservice.v1.DescribeWorkerResponse"\xc9\x01\x82\xd3\xe4\x93\x02\x89\x01\x12>/namespaces/{namespace}/workers/describe/{worker_instance_key}ZG\x12\x45/api/v1/namespaces/{namespace}/workers/describe/{worker_instance_key}\x8a\x9d\xcc\x1b\x34\n\x14temporal-resource-id\x12\x1cworker:{worker_instance_key}\x12\xd2\x02\n\x16PauseWorkflowExecution\x12>.temporal.api.workflowservice.v1.PauseWorkflowExecutionRequest\x1a?.temporal.api.workflowservice.v1.PauseWorkflowExecutionResponse"\xb6\x01\x82\xd3\xe4\x93\x02}"5/namespaces/{namespace}/workflows/{workflow_id}/pause:\x01*ZA"/api/v1/namespaces/{namespace}/workflows/{workflow_id}/unpause:\x01*\x8a\x9d\xcc\x1b.\n\x14temporal-resource-id\x12\x16workflow:{workflow_id}\x12\xc8\x02\n\x16StartActivityExecution\x12>.temporal.api.workflowservice.v1.StartActivityExecutionRequest\x1a?.temporal.api.workflowservice.v1.StartActivityExecutionResponse"\xac\x01\x82\xd3\xe4\x93\x02s"0/namespaces/{namespace}/activities/{activity_id}:\x01*Z<"7/api/v1/namespaces/{namespace}/activities/{activity_id}:\x01*\x8a\x9d\xcc\x1b.\n\x14temporal-resource-id\x12\x16\x61\x63tivity:{activity_id}\x12\xb6\x02\n\x1cStartNexusOperationExecution\x12\x44.temporal.api.workflowservice.v1.StartNexusOperationExecutionRequest\x1a\x45.temporal.api.workflowservice.v1.StartNexusOperationExecutionResponse"\x88\x01\x82\xd3\xe4\x93\x02\x81\x01"7/namespaces/{namespace}/nexus-operations/{operation_id}:\x01*ZC">/api/v1/namespaces/{namespace}/nexus-operations/{operation_id}:\x01*\x12\xcb\x02\n\x19\x44\x65scribeActivityExecution\x12\x41.temporal.api.workflowservice.v1.DescribeActivityExecutionRequest\x1a\x42.temporal.api.workflowservice.v1.DescribeActivityExecutionResponse"\xa6\x01\x82\xd3\xe4\x93\x02m\x12\x30/namespaces/{namespace}/activities/{activity_id}Z9\x12\x37/api/v1/namespaces/{namespace}/activities/{activity_id}\x8a\x9d\xcc\x1b.\n\x14temporal-resource-id\x12\x16\x61\x63tivity:{activity_id}\x12\xb8\x02\n\x1f\x44\x65scribeNexusOperationExecution\x12G.temporal.api.workflowservice.v1.DescribeNexusOperationExecutionRequest\x1aH.temporal.api.workflowservice.v1.DescribeNexusOperationExecutionResponse"\x81\x01\x82\xd3\xe4\x93\x02{\x12\x37/namespaces/{namespace}/nexus-operations/{operation_id}Z@\x12>/api/v1/namespaces/{namespace}/nexus-operations/{operation_id}\x12\xcf\x02\n\x15PollActivityExecution\x12=.temporal.api.workflowservice.v1.PollActivityExecutionRequest\x1a>.temporal.api.workflowservice.v1.PollActivityExecutionResponse"\xb6\x01\x82\xd3\xe4\x93\x02}\x12\x38/namespaces/{namespace}/activities/{activity_id}/outcomeZA\x12?/api/v1/namespaces/{namespace}/activities/{activity_id}/outcome\x8a\x9d\xcc\x1b.\n\x14temporal-resource-id\x12\x16\x61\x63tivity:{activity_id}\x12\xb7\x02\n\x1bPollNexusOperationExecution\x12\x43.temporal.api.workflowservice.v1.PollNexusOperationExecutionRequest\x1a\x44.temporal.api.workflowservice.v1.PollNexusOperationExecutionResponse"\x8c\x01\x82\xd3\xe4\x93\x02\x85\x01\x12.temporal.api.workflowservice.v1.ListActivityExecutionsRequest\x1a?.temporal.api.workflowservice.v1.ListActivityExecutionsResponse"W\x82\xd3\xe4\x93\x02Q\x12"/namespaces/{namespace}/activitiesZ+\x12)/api/v1/namespaces/{namespace}/activities\x12\x90\x02\n\x1cListNexusOperationExecutions\x12\x44.temporal.api.workflowservice.v1.ListNexusOperationExecutionsRequest\x1a\x45.temporal.api.workflowservice.v1.ListNexusOperationExecutionsResponse"c\x82\xd3\xe4\x93\x02]\x12(/namespaces/{namespace}/nexus-operationsZ1\x12//api/v1/namespaces/{namespace}/nexus-operations\x12\xfd\x01\n\x17\x43ountActivityExecutions\x12?.temporal.api.workflowservice.v1.CountActivityExecutionsRequest\x1a@.temporal.api.workflowservice.v1.CountActivityExecutionsResponse"_\x82\xd3\xe4\x93\x02Y\x12&/namespaces/{namespace}/activity-countZ/\x12-/api/v1/namespaces/{namespace}/activity-count\x12\x9d\x02\n\x1d\x43ountNexusOperationExecutions\x12\x45.temporal.api.workflowservice.v1.CountNexusOperationExecutionsRequest\x1a\x46.temporal.api.workflowservice.v1.CountNexusOperationExecutionsResponse"m\x82\xd3\xe4\x93\x02g\x12-/namespaces/{namespace}/nexus-operation-countZ6\x12\x34/api/v1/namespaces/{namespace}/nexus-operation-count\x12\xef\x02\n\x1eRequestCancelActivityExecution\x12\x46.temporal.api.workflowservice.v1.RequestCancelActivityExecutionRequest\x1aG.temporal.api.workflowservice.v1.RequestCancelActivityExecutionResponse"\xbb\x01\x82\xd3\xe4\x93\x02\x81\x01"7/namespaces/{namespace}/activities/{activity_id}/cancel:\x01*ZC">/api/v1/namespaces/{namespace}/activities/{activity_id}/cancel:\x01*\x8a\x9d\xcc\x1b.\n\x14temporal-resource-id\x12\x16\x61\x63tivity:{activity_id}\x12\xdc\x02\n$RequestCancelNexusOperationExecution\x12L.temporal.api.workflowservice.v1.RequestCancelNexusOperationExecutionRequest\x1aM.temporal.api.workflowservice.v1.RequestCancelNexusOperationExecutionResponse"\x96\x01\x82\xd3\xe4\x93\x02\x8f\x01">/namespaces/{namespace}/nexus-operations/{operation_id}/cancel:\x01*ZJ"E/api/v1/namespaces/{namespace}/nexus-operations/{operation_id}/cancel:\x01*\x12\xe9\x02\n\x1aTerminateActivityExecution\x12\x42.temporal.api.workflowservice.v1.TerminateActivityExecutionRequest\x1a\x43.temporal.api.workflowservice.v1.TerminateActivityExecutionResponse"\xc1\x01\x82\xd3\xe4\x93\x02\x87\x01":/namespaces/{namespace}/activities/{activity_id}/terminate:\x01*ZF"A/api/v1/namespaces/{namespace}/activities/{activity_id}/terminate:\x01*\x8a\x9d\xcc\x1b.\n\x14temporal-resource-id\x12\x16\x61\x63tivity:{activity_id}\x12\x9e\x01\n\x17\x44\x65leteActivityExecution\x12?.temporal.api.workflowservice.v1.DeleteActivityExecutionRequest\x1a@.temporal.api.workflowservice.v1.DeleteActivityExecutionResponse"\x00\x12\xfd\x03\n\x16PauseActivityExecution\x12>.temporal.api.workflowservice.v1.PauseActivityExecutionRequest\x1a?.temporal.api.workflowservice.v1.PauseActivityExecutionResponse"\xe1\x02\x82\xd3\xe4\x93\x02\xb0\x02"6/namespaces/{namespace}/activities/{activity_id}/pause:\x01*ZB"=/api/v1/namespaces/{namespace}/activities/{activity_id}/pause:\x01*ZS"N/namespaces/{namespace}/workflows/{workflow_id}/activities/{activity_id}/pause:\x01*ZZ"U/api/v1/namespaces/{namespace}/workflows/{workflow_id}/activities/{activity_id}/pause:\x01*\x8a\x9d\xcc\x1b%\n\x14temporal-resource-id\x12\r{resource_id}\x12\xfd\x03\n\x16ResetActivityExecution\x12>.temporal.api.workflowservice.v1.ResetActivityExecutionRequest\x1a?.temporal.api.workflowservice.v1.ResetActivityExecutionResponse"\xe1\x02\x82\xd3\xe4\x93\x02\xb0\x02"6/namespaces/{namespace}/activities/{activity_id}/reset:\x01*ZB"=/api/v1/namespaces/{namespace}/activities/{activity_id}/reset:\x01*ZS"N/namespaces/{namespace}/workflows/{workflow_id}/activities/{activity_id}/reset:\x01*ZZ"U/api/v1/namespaces/{namespace}/workflows/{workflow_id}/activities/{activity_id}/reset:\x01*\x8a\x9d\xcc\x1b%\n\x14temporal-resource-id\x12\r{resource_id}\x12\x8b\x04\n\x18UnpauseActivityExecution\x12@.temporal.api.workflowservice.v1.UnpauseActivityExecutionRequest\x1a\x41.temporal.api.workflowservice.v1.UnpauseActivityExecutionResponse"\xe9\x02\x82\xd3\xe4\x93\x02\xb8\x02"8/namespaces/{namespace}/activities/{activity_id}/unpause:\x01*ZD"?/api/v1/namespaces/{namespace}/activities/{activity_id}/unpause:\x01*ZU"P/namespaces/{namespace}/workflows/{workflow_id}/activities/{activity_id}/unpause:\x01*Z\\"W/api/v1/namespaces/{namespace}/workflows/{workflow_id}/activities/{activity_id}/unpause:\x01*\x8a\x9d\xcc\x1b%\n\x14temporal-resource-id\x12\r{resource_id}\x12\xb9\x04\n\x1eUpdateActivityExecutionOptions\x12\x46.temporal.api.workflowservice.v1.UpdateActivityExecutionOptionsRequest\x1aG.temporal.api.workflowservice.v1.UpdateActivityExecutionOptionsResponse"\x85\x03\x82\xd3\xe4\x93\x02\xd4\x02"?/namespaces/{namespace}/activities/{activity_id}/update-options:\x01*ZK"F/api/v1/namespaces/{namespace}/activities/{activity_id}/update-options:\x01*Z\\"W/namespaces/{namespace}/workflows/{workflow_id}/activities/{activity_id}/update-options:\x01*Zc"^/api/v1/namespaces/{namespace}/workflows/{workflow_id}/activities/{activity_id}/update-options:\x01*\x8a\x9d\xcc\x1b%\n\x14temporal-resource-id\x12\r{resource_id}\x12\xd6\x02\n TerminateNexusOperationExecution\x12H.temporal.api.workflowservice.v1.TerminateNexusOperationExecutionRequest\x1aI.temporal.api.workflowservice.v1.TerminateNexusOperationExecutionResponse"\x9c\x01\x82\xd3\xe4\x93\x02\x95\x01"A/namespaces/{namespace}/nexus-operations/{operation_id}/terminate:\x01*ZM"H/api/v1/namespaces/{namespace}/nexus-operations/{operation_id}/terminate:\x01*\x12\xb0\x01\n\x1d\x44\x65leteNexusOperationExecution\x12\x45.temporal.api.workflowservice.v1.DeleteNexusOperationExecutionRequest\x1a\x46.temporal.api.workflowservice.v1.DeleteNexusOperationExecutionResponse"\x00\x42\xb6\x01\n"io.temporal.api.workflowservice.v1B\x0cServiceProtoP\x01Z5go.temporal.io/api/workflowservice/v1;workflowservice\xaa\x02!Temporalio.Api.WorkflowService.V1\xea\x02$Temporalio::Api::WorkflowService::V1b\x06proto3' ) @@ -417,6 +417,10 @@ _WORKFLOWSERVICE.methods_by_name[ "ListWorkers" ]._serialized_options = b"\202\323\344\223\002K\022\037/namespaces/{namespace}/workersZ(\022&/api/v1/namespaces/{namespace}/workers" + _WORKFLOWSERVICE.methods_by_name["CountWorkers"]._options = None + _WORKFLOWSERVICE.methods_by_name[ + "CountWorkers" + ]._serialized_options = b"\202\323\344\223\002U\022$/namespaces/{namespace}/worker-countZ-\022+/api/v1/namespaces/{namespace}/worker-count" _WORKFLOWSERVICE.methods_by_name["UpdateTaskQueueConfig"]._options = None _WORKFLOWSERVICE.methods_by_name[ "UpdateTaskQueueConfig" @@ -516,5 +520,5 @@ "TerminateNexusOperationExecution" ]._serialized_options = b'\202\323\344\223\002\225\001"A/namespaces/{namespace}/nexus-operations/{operation_id}/terminate:\001*ZM"H/api/v1/namespaces/{namespace}/nexus-operations/{operation_id}/terminate:\001*' _WORKFLOWSERVICE._serialized_start = 250 - _WORKFLOWSERVICE._serialized_end = 38839 + _WORKFLOWSERVICE._serialized_end = 39058 # @@protoc_insertion_point(module_scope) diff --git a/temporalio/api/workflowservice/v1/service_pb2_grpc.py b/temporalio/api/workflowservice/v1/service_pb2_grpc.py index f0fcc6730..f0b093213 100644 --- a/temporalio/api/workflowservice/v1/service_pb2_grpc.py +++ b/temporalio/api/workflowservice/v1/service_pb2_grpc.py @@ -503,6 +503,11 @@ def __init__(self, channel): request_serializer=temporal_dot_api_dot_workflowservice_dot_v1_dot_request__response__pb2.ListWorkersRequest.SerializeToString, response_deserializer=temporal_dot_api_dot_workflowservice_dot_v1_dot_request__response__pb2.ListWorkersResponse.FromString, ) + self.CountWorkers = channel.unary_unary( + "/temporal.api.workflowservice.v1.WorkflowService/CountWorkers", + request_serializer=temporal_dot_api_dot_workflowservice_dot_v1_dot_request__response__pb2.CountWorkersRequest.SerializeToString, + response_deserializer=temporal_dot_api_dot_workflowservice_dot_v1_dot_request__response__pb2.CountWorkersResponse.FromString, + ) self.UpdateTaskQueueConfig = channel.unary_unary( "/temporal.api.workflowservice.v1.WorkflowService/UpdateTaskQueueConfig", request_serializer=temporal_dot_api_dot_workflowservice_dot_v1_dot_request__response__pb2.UpdateTaskQueueConfigRequest.SerializeToString, @@ -1650,6 +1655,12 @@ def ListWorkers(self, request, context): context.set_details("Method not implemented!") raise NotImplementedError("Method not implemented!") + def CountWorkers(self, request, context): + """CountWorkers counts the number of workers in a specific namespace.""" + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details("Method not implemented!") + raise NotImplementedError("Method not implemented!") + def UpdateTaskQueueConfig(self, request, context): """Updates task queue configuration. For the overall queue rate limit: the rate limit set by this api overrides the worker-set rate limit, @@ -2393,6 +2404,11 @@ def add_WorkflowServiceServicer_to_server(servicer, server): request_deserializer=temporal_dot_api_dot_workflowservice_dot_v1_dot_request__response__pb2.ListWorkersRequest.FromString, response_serializer=temporal_dot_api_dot_workflowservice_dot_v1_dot_request__response__pb2.ListWorkersResponse.SerializeToString, ), + "CountWorkers": grpc.unary_unary_rpc_method_handler( + servicer.CountWorkers, + request_deserializer=temporal_dot_api_dot_workflowservice_dot_v1_dot_request__response__pb2.CountWorkersRequest.FromString, + response_serializer=temporal_dot_api_dot_workflowservice_dot_v1_dot_request__response__pb2.CountWorkersResponse.SerializeToString, + ), "UpdateTaskQueueConfig": grpc.unary_unary_rpc_method_handler( servicer.UpdateTaskQueueConfig, request_deserializer=temporal_dot_api_dot_workflowservice_dot_v1_dot_request__response__pb2.UpdateTaskQueueConfigRequest.FromString, @@ -5300,6 +5316,35 @@ def ListWorkers( metadata, ) + @staticmethod + def CountWorkers( + request, + target, + options=(), + channel_credentials=None, + call_credentials=None, + insecure=False, + compression=None, + wait_for_ready=None, + timeout=None, + metadata=None, + ): + return grpc.experimental.unary_unary( + request, + target, + "/temporal.api.workflowservice.v1.WorkflowService/CountWorkers", + temporal_dot_api_dot_workflowservice_dot_v1_dot_request__response__pb2.CountWorkersRequest.SerializeToString, + temporal_dot_api_dot_workflowservice_dot_v1_dot_request__response__pb2.CountWorkersResponse.FromString, + options, + channel_credentials, + insecure, + call_credentials, + compression, + wait_for_ready, + timeout, + metadata, + ) + @staticmethod def UpdateTaskQueueConfig( request, diff --git a/temporalio/api/workflowservice/v1/service_pb2_grpc.pyi b/temporalio/api/workflowservice/v1/service_pb2_grpc.pyi index d6d94abb3..9c9713144 100644 --- a/temporalio/api/workflowservice/v1/service_pb2_grpc.pyi +++ b/temporalio/api/workflowservice/v1/service_pb2_grpc.pyi @@ -930,6 +930,11 @@ class WorkflowServiceStub: temporalio.api.workflowservice.v1.request_response_pb2.ListWorkersResponse, ] """ListWorkers is a visibility API to list worker status information in a specific namespace.""" + CountWorkers: grpc.UnaryUnaryMultiCallable[ + temporalio.api.workflowservice.v1.request_response_pb2.CountWorkersRequest, + temporalio.api.workflowservice.v1.request_response_pb2.CountWorkersResponse, + ] + """CountWorkers counts the number of workers in a specific namespace.""" UpdateTaskQueueConfig: grpc.UnaryUnaryMultiCallable[ temporalio.api.workflowservice.v1.request_response_pb2.UpdateTaskQueueConfigRequest, temporalio.api.workflowservice.v1.request_response_pb2.UpdateTaskQueueConfigResponse, @@ -2291,6 +2296,13 @@ class WorkflowServiceServicer(metaclass=abc.ABCMeta): ) -> temporalio.api.workflowservice.v1.request_response_pb2.ListWorkersResponse: """ListWorkers is a visibility API to list worker status information in a specific namespace.""" @abc.abstractmethod + def CountWorkers( + self, + request: temporalio.api.workflowservice.v1.request_response_pb2.CountWorkersRequest, + context: grpc.ServicerContext, + ) -> temporalio.api.workflowservice.v1.request_response_pb2.CountWorkersResponse: + """CountWorkers counts the number of workers in a specific namespace.""" + @abc.abstractmethod def UpdateTaskQueueConfig( self, request: temporalio.api.workflowservice.v1.request_response_pb2.UpdateTaskQueueConfigRequest, diff --git a/temporalio/bridge/sdk-core b/temporalio/bridge/sdk-core index 9f83b7e30..467e871aa 160000 --- a/temporalio/bridge/sdk-core +++ b/temporalio/bridge/sdk-core @@ -1 +1 @@ -Subproject commit 9f83b7e307dc032b31ff3bd3811ef3438106f77a +Subproject commit 467e871aa922ecfeeba8a778b7b9b9de19849acc diff --git a/temporalio/bridge/services_generated.py b/temporalio/bridge/services_generated.py index 301c218cf..2f0fef8ac 100644 --- a/temporalio/bridge/services_generated.py +++ b/temporalio/bridge/services_generated.py @@ -81,6 +81,24 @@ async def count_schedules( timeout=timeout, ) + async def count_workers( + self, + req: temporalio.api.workflowservice.v1.CountWorkersRequest, + retry: bool = False, + metadata: Mapping[str, str | bytes] = {}, + timeout: timedelta | None = None, + ) -> temporalio.api.workflowservice.v1.CountWorkersResponse: + """Invokes the WorkflowService.count_workers rpc method.""" + return await self._client._rpc_call( + rpc="count_workers", + req=req, + service=self._service, + resp_type=temporalio.api.workflowservice.v1.CountWorkersResponse, + retry=retry, + metadata=metadata, + timeout=timeout, + ) + async def count_workflow_executions( self, req: temporalio.api.workflowservice.v1.CountWorkflowExecutionsRequest, diff --git a/temporalio/bridge/src/client_rpc_generated.rs b/temporalio/bridge/src/client_rpc_generated.rs index 931b77a32..a6f95b124 100644 --- a/temporalio/bridge/src/client_rpc_generated.rs +++ b/temporalio/bridge/src/client_rpc_generated.rs @@ -47,6 +47,15 @@ impl ClientRef { count_schedules ) } + "count_workers" => { + rpc_call!( + connection, + call, + WorkflowService, + workflow_service, + count_workers + ) + } "count_workflow_executions" => { rpc_call!( connection, diff --git a/tests/worker/workflow_sandbox/testmodules/proto/proto_message_pb2.py b/tests/worker/workflow_sandbox/testmodules/proto/proto_message_pb2.py index 19a1c69b2..73e1d2b1e 100644 --- a/tests/worker/workflow_sandbox/testmodules/proto/proto_message_pb2.py +++ b/tests/worker/workflow_sandbox/testmodules/proto/proto_message_pb2.py @@ -1,14 +1,24 @@ # -*- coding: utf-8 -*- # Generated by the protocol buffer compiler. DO NOT EDIT! +# NO CHECKED-IN PROTOBUF GENCODE # source: worker/workflow_sandbox/testmodules/proto/proto_message.proto +# Protobuf Python Version: 6.33.5 """Generated protocol buffer code.""" from google.protobuf import descriptor as _descriptor from google.protobuf import descriptor_pool as _descriptor_pool -from google.protobuf import message as _message -from google.protobuf import reflection as _reflection +from google.protobuf import runtime_version as _runtime_version from google.protobuf import symbol_database as _symbol_database - +from google.protobuf.internal import builder as _builder + +_runtime_version.ValidateProtobufRuntimeVersion( + _runtime_version.Domain.PUBLIC, + 6, + 33, + 5, + "", + "worker/workflow_sandbox/testmodules/proto/proto_message.proto", +) # @@protoc_insertion_point(imports) _sym_db = _symbol_database.Default() @@ -20,21 +30,13 @@ b'\n=worker/workflow_sandbox/testmodules/proto/proto_message.proto\x12)worker.workflow_sandbox.testmodules.proto\x1a\x1egoogle/protobuf/duration.proto"?\n\x0bSomeMessage\x12\x30\n\rsome_duration\x18\x01 \x01(\x0b\x32\x19.google.protobuf.Durationb\x06proto3' ) - -_SOMEMESSAGE = DESCRIPTOR.message_types_by_name["SomeMessage"] -SomeMessage = _reflection.GeneratedProtocolMessageType( - "SomeMessage", - (_message.Message,), - { - "DESCRIPTOR": _SOMEMESSAGE, - "__module__": "worker.workflow_sandbox.testmodules.proto.proto_message_pb2", - # @@protoc_insertion_point(class_scope:worker.workflow_sandbox.testmodules.proto.SomeMessage) - }, +_globals = globals() +_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) +_builder.BuildTopDescriptorsAndMessages( + DESCRIPTOR, "worker.workflow_sandbox.testmodules.proto.proto_message_pb2", _globals ) -_sym_db.RegisterMessage(SomeMessage) - -if _descriptor._USE_C_DESCRIPTORS == False: - DESCRIPTOR._options = None - _SOMEMESSAGE._serialized_start = 140 - _SOMEMESSAGE._serialized_end = 203 +if not _descriptor._USE_C_DESCRIPTORS: + DESCRIPTOR._loaded_options = None + _globals["_SOMEMESSAGE"]._serialized_start = 140 + _globals["_SOMEMESSAGE"]._serialized_end = 203 # @@protoc_insertion_point(module_scope) diff --git a/tests/worker/workflow_sandbox/testmodules/proto/proto_message_pb2.pyi b/tests/worker/workflow_sandbox/testmodules/proto/proto_message_pb2.pyi index db5f796b3..b2c6f24a9 100644 --- a/tests/worker/workflow_sandbox/testmodules/proto/proto_message_pb2.pyi +++ b/tests/worker/workflow_sandbox/testmodules/proto/proto_message_pb2.pyi @@ -5,18 +5,20 @@ isort:skip_file import builtins import sys +import typing import google.protobuf.descriptor import google.protobuf.duration_pb2 import google.protobuf.message -if sys.version_info >= (3, 8): +if sys.version_info >= (3, 10): import typing as typing_extensions else: import typing_extensions DESCRIPTOR: google.protobuf.descriptor.FileDescriptor +@typing.final class SomeMessage(google.protobuf.message.Message): DESCRIPTOR: google.protobuf.descriptor.Descriptor @@ -29,10 +31,10 @@ class SomeMessage(google.protobuf.message.Message): some_duration: google.protobuf.duration_pb2.Duration | None = ..., ) -> None: ... def HasField( - self, field_name: typing_extensions.Literal["some_duration", b"some_duration"] + self, field_name: typing.Literal["some_duration", b"some_duration"] ) -> builtins.bool: ... def ClearField( - self, field_name: typing_extensions.Literal["some_duration", b"some_duration"] + self, field_name: typing.Literal["some_duration", b"some_duration"] ) -> None: ... -global___SomeMessage = SomeMessage +Global___SomeMessage: typing_extensions.TypeAlias = SomeMessage From d824821d74f6c7cc53f35d7bd056fa5554651922 Mon Sep 17 00:00:00 2001 From: David Hyde Date: Tue, 7 Jul 2026 12:20:17 -0500 Subject: [PATCH 155/226] Fix flaky TMPRL1104 duration-log assertions in test_extstore (#1628) --- tests/worker/test_extstore.py | 42 ++++++++++++----------------------- 1 file changed, 14 insertions(+), 28 deletions(-) diff --git a/tests/worker/test_extstore.py b/tests/worker/test_extstore.py index e186f4e67..998a2bd27 100644 --- a/tests/worker/test_extstore.py +++ b/tests/worker/test_extstore.py @@ -624,6 +624,13 @@ def _tmprl1104_records(capturer: LogCapturer) -> list[logging.LogRecord]: return capturer.find_all(lambda r: r.getMessage().startswith("[TMPRL1104]")) +# Accept any duration-bucket wording: a loaded host can push a trivial task past 5s. +_TMPRL1104_DURATION_MESSAGE = re.compile( + r"\[TMPRL1104\] [^:]+:\d+:\d+ Workflow task " + r"(?:duration information|exceeded \d+ seconds) \(" +) + + async def _expected_payload_size( converter: temporalio.converter.DataConverter, value: object ) -> int: @@ -655,10 +662,7 @@ async def test_tmprl1104_no_extstore(env: WorkflowEnvironment) -> None: records = _tmprl1104_records(capturer) assert len(records) == 1 record = records[0] - assert re.match( - r"\[TMPRL1104\] [^:]+:\d+:\d+ Workflow task duration information \(", - record.getMessage(), - ) + assert _TMPRL1104_DURATION_MESSAGE.match(record.getMessage()) assert hasattr(record, "workflow_task_duration") assert hasattr(record, "event_id") # No external storage — download/upload fields must be absent @@ -710,20 +714,14 @@ async def test_tmprl1104_with_extstore_download(env: WorkflowEnvironment) -> Non assert len(records) == 2 # WFT 1: retrieves the externalized workflow input - assert re.match( - r"\[TMPRL1104\] [^:]+:\d+:\d+ Workflow task duration information \(", - records[0].getMessage(), - ) + assert _TMPRL1104_DURATION_MESSAGE.match(records[0].getMessage()) assert getattr(records[0], "payload_download_count") == 1 assert getattr(records[0], "payload_download_size") == expected_input_size assert getattr(records[0], "payload_download_duration") > timedelta(0) assert not hasattr(records[0], "payload_upload_count") # WFT 2: activity result is small — no external storage - assert re.match( - r"\[TMPRL1104\] [^:]+:\d+:\d+ Workflow task duration information \(", - records[1].getMessage(), - ) + assert _TMPRL1104_DURATION_MESSAGE.match(records[1].getMessage()) assert not hasattr(records[1], "payload_download_count") assert not hasattr(records[1], "payload_upload_count") @@ -768,18 +766,12 @@ async def test_tmprl1104_with_extstore_upload(env: WorkflowEnvironment) -> None: assert len(records) == 2 # WFT 1: small input — no external storage - assert re.match( - r"\[TMPRL1104\] [^:]+:\d+:\d+ Workflow task duration information \(", - records[0].getMessage(), - ) + assert _TMPRL1104_DURATION_MESSAGE.match(records[0].getMessage()) assert not hasattr(records[0], "payload_download_count") assert not hasattr(records[0], "payload_upload_count") # WFT 2: workflow returns large result → uploaded - assert re.match( - r"\[TMPRL1104\] [^:]+:\d+:\d+ Workflow task duration information \(", - records[1].getMessage(), - ) + assert _TMPRL1104_DURATION_MESSAGE.match(records[1].getMessage()) assert not hasattr(records[1], "payload_download_count") assert getattr(records[1], "payload_upload_count") == 1 assert getattr(records[1], "payload_upload_size") == expected_output_size @@ -830,20 +822,14 @@ async def test_tmprl1104_with_extstore_download_and_upload( assert len(records) == 2 # WFT 1: retrieves externalized workflow input - assert re.match( - r"\[TMPRL1104\] [^:]+:\d+:\d+ Workflow task duration information \(", - records[0].getMessage(), - ) + assert _TMPRL1104_DURATION_MESSAGE.match(records[0].getMessage()) assert getattr(records[0], "payload_download_count") == 1 assert getattr(records[0], "payload_download_size") == expected_input_size assert getattr(records[0], "payload_download_duration") > timedelta(0) assert not hasattr(records[0], "payload_upload_count") # WFT 2: uploads externalized workflow result - assert re.match( - r"\[TMPRL1104\] [^:]+:\d+:\d+ Workflow task duration information \(", - records[1].getMessage(), - ) + assert _TMPRL1104_DURATION_MESSAGE.match(records[1].getMessage()) assert not hasattr(records[1], "payload_download_count") assert getattr(records[1], "payload_upload_count") == 1 assert getattr(records[1], "payload_upload_size") == expected_output_size From 59c11647e787a426ce21ee323f9485e37b221eea Mon Sep 17 00:00:00 2001 From: David Hyde Date: Tue, 7 Jul 2026 14:48:43 -0500 Subject: [PATCH 156/226] Add dynamic node/task summaries to LangGraph plugin (#1612) * Add dynamic node/task summaries to LangGraph plugin Adds a per-node/per-task summary_fn(args, kwargs) -> str | None (and a plugin-wide default_summary_fn) that computes a Temporal summary at runtime from the node's input. - execute_in="activity" nodes: the result sets the activity summary (user_metadata, shown on each scheduled-activity event). - execute_in="workflow" nodes: the result updates the workflow's current details via workflow.set_current_details (last-writer-wins). A static summary activity option already flowed through to execute_activity; this is now documented. Setting both a static summary and summary_fn on the same node raises ValueError. summary_fn runs in workflow context (must be deterministic and must not raise) and is replay-safe, since summaries ride in user_metadata. * Comment why summary_fn is popped from node opts * Scope summary_fn per-node and normalize static summary - Drop the plugin-level default_summary_fn; summary_fn is now set only per node (Graph metadata) / per task (activity_options), matching the ADK plugin's per-model scoping so each node manages its own summary. - Normalize a static summary into a summary_fn (a constant function), so static and dynamic summaries share one resolution path feeding the activity summary kwarg / set_current_details. - Workflow-bound nodes now clear current details when summary_fn returns empty, so a node no longer shows a stale summary from an earlier node. * Layer node summary settings over defaults instead of conflicting summary and summary_fn are two forms of one setting, but as separate dict keys a default of one form and a node-level value of the other survived the merge together and tripped the exclusivity guard (e.g. default_activity_options={"summary_fn": fn} + one node with a static summary raised ValueError). Merge now drops the inherited form when a node/task supplies either, so the more-specific setting wins, and the exclusivity check only rejects both forms set at the same level (per-node, or in default_activity_options via a new init check). --- temporalio/contrib/langgraph/README.md | 40 +++ temporalio/contrib/langgraph/_activity.py | 13 +- temporalio/contrib/langgraph/_plugin.py | 77 ++++- temporalio/contrib/langgraph/_workflow.py | 11 + tests/contrib/langgraph/test_summary_fn.py | 362 +++++++++++++++++++++ 5 files changed, 490 insertions(+), 13 deletions(-) create mode 100644 tests/contrib/langgraph/test_summary_fn.py diff --git a/temporalio/contrib/langgraph/README.md b/temporalio/contrib/langgraph/README.md index dafe598b7..d5b7d4e0f 100644 --- a/temporalio/contrib/langgraph/README.md +++ b/temporalio/contrib/langgraph/README.md @@ -143,6 +143,46 @@ await g.ainvoke({...}, context=Context(user_id="alice")) Your `context` object must be serializable by the configured Temporal payload converter, since it crosses the Activity boundary. +## Summaries + +Summaries are short, human-readable labels that show up in the Temporal UI and CLI, making it easier to see what each step of a run is doing. + +### Static summary + +`summary` is an ordinary Activity option, so a fixed per-node label works today — pass it like any other option: + +```python +g.add_node("plan", plan, metadata={"execute_in": "activity", "summary": "Planning step"}) +``` + +It is attached to the node's scheduled-activity event (`execute_in="activity"` only). + +### Dynamic summary (`summary_fn`) + +To derive the label from the node's input at runtime, supply a `summary_fn`. It receives the node's `(args, kwargs)` and returns a summary string, or `None`/`""` for no summary. For a `StateGraph` node `args[0]` is the state; for a Functional `@task` it is the task's arguments. + +```python +def summarize(args, kwargs) -> str | None: + state = args[0] + return f"stage={state['stage']} doc={state['doc_id']}" + +# Graph API: per-node +g.add_node("plan", plan, metadata={"execute_in": "activity", "summary_fn": summarize}) + +# Functional API: per-task +plugin = LangGraphPlugin( + tasks=[plan], + activity_options={"plan": {"execute_in": "activity", "summary_fn": summarize}}, +) +``` + +`summary_fn` is set per node/task (like the static `summary`), so different nodes — which receive different inputs — can compute their summaries independently. You can also put a `summary` or `summary_fn` in `default_activity_options` as a fallback for every node; a node/task that sets either form overrides the inherited default (you just can't set both forms at the same level). + +- For `execute_in="activity"` nodes the result sets the activity `summary` (one per scheduled-activity event, visible in history). +- For `execute_in="workflow"` nodes there is no activity, so the result updates the workflow's current details via [`workflow.set_current_details()`](https://python.temporal.io/temporalio.workflow.html#set_current_details). This is a single workflow-level slot (last-writer-wins) reflecting the most recent workflow-bound node that defines a `summary_fn`; a `None`/`""` result clears it. It is queryable via `__temporal_workflow_metadata`. + +`summary_fn` runs in workflow context on every replay, so it **must be deterministic and must not raise** (an exception fails the workflow task). Setting both a static `summary` and a `summary_fn` on the same node raises `ValueError`. + ## Streaming When `streaming_topic` is set on `LangGraphPlugin`, calls to `langgraph.config.get_stream_writer()` inside a node publish to the named topic on the workflow's [`WorkflowStream`](https://github.com/temporalio/sdk-python/tree/main/temporalio/contrib/workflow_streams). Activity-side nodes publish via `WorkflowStreamClient` (a signal carrying batched items, controlled by `streaming_batch_interval`); workflow-side nodes publish synchronously to the in-workflow stream (no signal). External subscribers consume the stream with `WorkflowStreamClient.create(...).topic(...).subscribe(...)`. diff --git a/temporalio/contrib/langgraph/_activity.py b/temporalio/contrib/langgraph/_activity.py index d75dbac2e..c8447df47 100644 --- a/temporalio/contrib/langgraph/_activity.py +++ b/temporalio/contrib/langgraph/_activity.py @@ -109,6 +109,7 @@ def thread_safe_writer(value: Any) -> None: def wrap_execute_activity( afunc: Callable[[ActivityInput], Awaitable[ActivityOutput]], task_id: str = "", + summary_fn: Callable[[tuple[Any, ...], dict[str, Any]], str | None] | None = None, **execute_activity_kwargs: Any, ) -> Callable[..., Any]: """Wrap an activity function to be called via workflow.execute_activity with caching.""" @@ -156,9 +157,15 @@ async def wrapper(*args: Any, **kwargs: Any) -> Any: input = ActivityInput( args=args, kwargs=kwargs, langgraph_config=langgraph_config ) - output = await workflow.execute_activity( - afunc, input, **execute_activity_kwargs - ) + # Compute a dynamic activity summary (if configured) on the schedule + # path only; a cache hit above returns before reaching here, so no + # activity is scheduled and no summary is needed. + call_kwargs = dict(execute_activity_kwargs) + if summary_fn is not None: + summary = summary_fn(args, kwargs) + if summary: + call_kwargs["summary"] = summary + output = await workflow.execute_activity(afunc, input, **call_kwargs) if output.langgraph_interrupts is not None: raise GraphInterrupt(output.langgraph_interrupts) diff --git a/temporalio/contrib/langgraph/_plugin.py b/temporalio/contrib/langgraph/_plugin.py index a1320d1a8..03881ca2a 100644 --- a/temporalio/contrib/langgraph/_plugin.py +++ b/temporalio/contrib/langgraph/_plugin.py @@ -35,6 +35,36 @@ _ACTIVITY_OPTION_KEYS: frozenset[str] = frozenset( {"execute_in", *inspect.signature(workflow.execute_activity).parameters} ) +# Node/task option keys beyond the raw execute_activity parameters: +# 'summary_fn' is a callable consumed in the workflow (not a Temporal +# option), so it must be split out of Graph API metadata too. +_LANGGRAPH_OPTION_KEYS: frozenset[str] = _ACTIVITY_OPTION_KEYS | frozenset( + {"summary_fn"} +) + + +def _constant_summary_fn( + value: str, +) -> Callable[[tuple[Any, ...], dict[str, Any]], str]: + """Adapt a static summary string to the summary_fn interface.""" + return lambda args, kwargs: value + + +def _merge_activity_opts( + defaults: dict[str, Any] | None, specific: dict[str, Any] +) -> dict[str, Any]: + """Layer per-node/task options over the plugin defaults. + + ``summary`` and ``summary_fn`` are two forms of one setting, so a node or + task that supplies either form overrides an inherited default of *either* + form, rather than coexisting with it and tripping the exclusivity check. + """ + merged = dict(defaults or {}) + if "summary" in specific or "summary_fn" in specific: + merged.pop("summary", None) + merged.pop("summary_fn", None) + merged.update(specific) + return merged class LangGraphPlugin(SimplePlugin): @@ -69,7 +99,9 @@ class LangGraphPlugin(SimplePlugin): Functional API has no per-task ``metadata`` channel. default_activity_options: Activity options applied to every activity-bound node and task, overridable per-node (Graph API - ``metadata``) or per-task (``activity_options[name]``). + ``metadata``) or per-task (``activity_options[name]``). A + node/task that sets ``summary`` or ``summary_fn`` overrides an + inherited default of either form. streaming_topic: When set, ``langgraph.config.get_stream_writer()`` inside a node publishes to this topic on the workflow's :class:`WorkflowStream`. The workflow must construct @@ -130,6 +162,16 @@ def __init__( "activity_options[task_name] (Functional API)." ) + if ( + default_activity_options + and "summary" in default_activity_options + and "summary_fn" in default_activity_options + ): + raise ValueError( + "Set either 'summary' or 'summary_fn' in default_activity_options, " + "not both." + ) + self.activities: list = [] self._streaming_topic = streaming_topic self._streaming_batch_interval = streaming_batch_interval @@ -168,12 +210,14 @@ def __init__( # the node function via config["metadata"]. node_meta = node.metadata or {} node_opts = { - k: v for k, v in node_meta.items() if k in _ACTIVITY_OPTION_KEYS + k: v + for k, v in node_meta.items() + if k in _LANGGRAPH_OPTION_KEYS } node.metadata = { k: v for k, v in node_meta.items() - if k not in _ACTIVITY_OPTION_KEYS + if k not in _LANGGRAPH_OPTION_KEYS } if "execute_in" not in node_opts: raise ValueError( @@ -181,7 +225,7 @@ def __init__( f"'execute_in' in metadata. Set it to 'activity' or " f"'workflow'." ) - opts = {**(default_activity_options or {}), **node_opts} + opts = _merge_activity_opts(default_activity_options, node_opts) # Route all LangGraph node calls through afunc so the async # activity wrapper is always used. wrap_activity handles # sync vs. async user functions inside the activity itself. @@ -208,10 +252,7 @@ def __init__( f"activity_options[{name!r}]. Set it to 'activity' or " f"'workflow'." ) - opts = { - **(default_activity_options or {}), - **task_opts, - } + opts = _merge_activity_opts(default_activity_options, task_opts) task.func = self.execute(task_id(task.func), task.func, opts) task.func.__name__ = name @@ -253,6 +294,18 @@ def execute( """Prepare a node or task to execute as an activity or inline in the workflow.""" opts = kwargs or {} execute_in = opts.pop("execute_in") + # Normalize the node's summary to a single summary_fn. Both keys are + # popped so neither reaches workflow.execute_activity (which takes no + # summary_fn, and would get a duplicate summary kwarg); a static + # summary becomes a summary_fn that ignores its input. + summary_fn = opts.pop("summary_fn", None) + static_summary = opts.pop("summary", None) + if summary_fn is not None and static_summary is not None: + raise ValueError( + f"{activity_name}: set either 'summary' or 'summary_fn', not both." + ) + if static_summary is not None: + summary_fn = _constant_summary_fn(static_summary) if execute_in == "activity": wrapped = wrap_activity( @@ -262,9 +315,13 @@ def execute( ) a = activity.defn(name=activity_name)(wrapped) self.activities.append(a) - return wrap_execute_activity(a, task_id=task_id(func), **opts) + return wrap_execute_activity( + a, task_id=task_id(func), summary_fn=summary_fn, **opts + ) elif execute_in == "workflow": - return wrap_workflow(func, streaming_topic=self._streaming_topic) + return wrap_workflow( + func, streaming_topic=self._streaming_topic, summary_fn=summary_fn + ) else: raise ValueError(f"Invalid execute_in value: {execute_in}") diff --git a/temporalio/contrib/langgraph/_workflow.py b/temporalio/contrib/langgraph/_workflow.py index 67bfd4f68..43b3d06ae 100644 --- a/temporalio/contrib/langgraph/_workflow.py +++ b/temporalio/contrib/langgraph/_workflow.py @@ -20,6 +20,7 @@ def wrap_workflow( func: Callable[..., Any], *, streaming_topic: str | None = None, + summary_fn: Callable[[tuple[Any, ...], dict[str, Any]], str | None] | None = None, ) -> Callable[..., Awaitable[Any]]: """Wrap a function as a workflow-side LangGraph node. @@ -28,9 +29,19 @@ def wrap_workflow( function with the writer installed. Workflow-side nodes publish synchronously to the in-workflow ``WorkflowStream`` (no signal round-trip); activity-side nodes go through ``WorkflowStreamClient``. + + Workflow-side nodes have no activity to carry a summary, so a + ``summary_fn`` result updates the workflow's current details via + :func:`temporalio.workflow.set_current_details` (last-writer-wins); + an empty result clears it. """ async def wrapper(*args: Any, **kwargs: Any) -> Any: + if summary_fn is not None: + # Always write (clearing when empty) so this node never shows a + # stale summary left by an earlier workflow-bound node. + workflow.set_current_details(summary_fn(args, kwargs) or "") + async def run(stream_writer: Callable[[Any], None] | None) -> Any: token = None if stream_writer is not None: diff --git a/tests/contrib/langgraph/test_summary_fn.py b/tests/contrib/langgraph/test_summary_fn.py new file mode 100644 index 000000000..687a68edb --- /dev/null +++ b/tests/contrib/langgraph/test_summary_fn.py @@ -0,0 +1,362 @@ +"""Tests for node/task summaries (static summary and summary_fn).""" + +from __future__ import annotations + +import uuid +from datetime import timedelta +from typing import Any, Callable + +import pytest +from langchain_core.runnables import ( + RunnableConfig, # pyright: ignore[reportMissingTypeStubs] +) +from langgraph.graph import START, StateGraph # pyright: ignore[reportMissingTypeStubs] +from typing_extensions import TypedDict + +import temporalio.api.sdk.v1 +from temporalio import workflow +from temporalio.client import Client +from temporalio.contrib.langgraph import LangGraphPlugin, graph +from temporalio.testing import WorkflowEnvironment +from temporalio.worker import Replayer, Worker +from tests.helpers import assert_eq_eventually + +SummaryFn = Callable[[tuple[Any, ...], dict[str, Any]], "str | None"] + + +class State(TypedDict): + value: str + + +async def passthrough(state: State) -> dict[str, str]: + return {"value": state["value"]} + + +def summarize( + args: tuple[Any, ...], + kwargs: dict[str, Any], # pyright: ignore[reportUnusedParameter] +) -> str | None: + return f"value={args[0]['value']}" + + +@workflow.defn +class SummaryWorkflow: + def __init__(self) -> None: + self.app = graph("summary-graph").compile() + + @workflow.run + async def run(self, input: str) -> Any: + return await self.app.ainvoke({"value": input}) + + +def _activity_graph( + summary_fn: SummaryFn | None, +) -> StateGraph[State, None, State, State]: + metadata: dict[str, Any] = {"execute_in": "activity"} + if summary_fn is not None: + metadata["summary_fn"] = summary_fn + g: StateGraph[State, None, State, State] = StateGraph(State) + g.add_node("node", passthrough, metadata=metadata) + g.add_edge(START, "node") + return g + + +async def _run_and_collect_summaries( + client: Client, plugin: LangGraphPlugin, input: str +) -> list[bytes]: + task_queue = f"summary-{uuid.uuid4()}" + async with Worker( + client, + task_queue=task_queue, + workflows=[SummaryWorkflow], + plugins=[plugin], + max_cached_workflows=0, + ): + handle = await client.start_workflow( + SummaryWorkflow.run, + input, + id=f"summary-{uuid.uuid4()}", + task_queue=task_queue, + ) + await handle.result() + return [ + e.user_metadata.summary.data + async for e in handle.fetch_history_events() + if e.HasField("activity_task_scheduled_event_attributes") + ] + + +def _plugin(g: StateGraph[Any, Any, Any, Any], **kwargs: Any) -> LangGraphPlugin: + return LangGraphPlugin( + graphs={"summary-graph": g}, + default_activity_options={"start_to_close_timeout": timedelta(seconds=10)}, + **kwargs, + ) + + +async def test_activity_summary_fn_in_history(client: Client) -> None: + plugin = _plugin(_activity_graph(summarize)) + summaries = await _run_and_collect_summaries(client, plugin, "hello") + assert summaries == [b'"value=hello"'] + + +@pytest.mark.parametrize( + "summary_fn,expected", + [ + (lambda args, kwargs: f"value={args[0]['value']}", b'"value=x"'), + (lambda args, kwargs: None, b""), + (lambda args, kwargs: "", b""), + ], +) +async def test_summary_fn_variants( + client: Client, summary_fn: SummaryFn, expected: bytes +) -> None: + plugin = _plugin(_activity_graph(summary_fn)) + summaries = await _run_and_collect_summaries(client, plugin, "x") + assert summaries == [expected] + + +async def test_static_summary(client: Client) -> None: + g: StateGraph[State, None, State, State] = StateGraph(State) + g.add_node( + "node", passthrough, metadata={"execute_in": "activity", "summary": "static"} + ) + g.add_edge(START, "node") + summaries = await _run_and_collect_summaries(client, _plugin(g), "x") + assert summaries == [b'"static"'] + + +async def test_node_static_summary_overrides_default_summary_fn( + client: Client, +) -> None: + g: StateGraph[State, None, State, State] = StateGraph(State) + g.add_node( + "node", + passthrough, + metadata={"execute_in": "activity", "summary": "node-static"}, + ) + g.add_edge(START, "node") + plugin = LangGraphPlugin( + graphs={"summary-graph": g}, + default_activity_options={ + "start_to_close_timeout": timedelta(seconds=10), + "summary_fn": lambda args, kwargs: "global", + }, + ) + summaries = await _run_and_collect_summaries(client, plugin, "x") + assert summaries == [b'"node-static"'] + + +async def test_node_summary_fn_overrides_default_summary(client: Client) -> None: + plugin = LangGraphPlugin( + graphs={"summary-graph": _activity_graph(lambda args, kwargs: "node-fn")}, + default_activity_options={ + "start_to_close_timeout": timedelta(seconds=10), + "summary": "global-static", + }, + ) + summaries = await _run_and_collect_summaries(client, plugin, "x") + assert summaries == [b'"node-fn"'] + + +async def test_default_summary_fn_applies_without_override(client: Client) -> None: + plugin = LangGraphPlugin( + graphs={"summary-graph": _activity_graph(None)}, + default_activity_options={ + "start_to_close_timeout": timedelta(seconds=10), + "summary_fn": lambda args, kwargs: "global", + }, + ) + summaries = await _run_and_collect_summaries(client, plugin, "x") + assert summaries == [b'"global"'] + + +def test_both_in_default_activity_options_raises() -> None: + with pytest.raises(ValueError, match="default_activity_options"): + LangGraphPlugin( + default_activity_options={ + "summary": "s", + "summary_fn": lambda args, kwargs: "f", + } + ) + + +def test_summary_and_summary_fn_raises() -> None: + g: StateGraph[State, None, State, State] = StateGraph(State) + g.add_node( + "node", + passthrough, + metadata={ + "execute_in": "activity", + "summary": "static", + "summary_fn": lambda args, kwargs: "dynamic", + }, + ) + g.add_edge(START, "node") + with pytest.raises(ValueError, match="not both"): + LangGraphPlugin(graphs={f"summary-graph-{uuid.uuid4()}": g}) + + +async def node_reads_meta(state: State, config: RunnableConfig) -> dict[str, str]: + metadata = config.get("metadata") or {} + return {"value": f"{state['value']}-has_fn={'summary_fn' in metadata}"} + + +async def test_summary_fn_not_in_node_metadata(client: Client) -> None: + g: StateGraph[State, None, State, State] = StateGraph(State) + g.add_node( + "node", + node_reads_meta, + metadata={ + "execute_in": "activity", + "summary_fn": lambda args, kwargs: "dynamic", + "my_key": "my_value", + }, + ) + g.add_edge(START, "node") + task_queue = f"summary-{uuid.uuid4()}" + async with Worker( + client, + task_queue=task_queue, + workflows=[SummaryWorkflow], + plugins=[_plugin(g)], + ): + result = await client.execute_workflow( + SummaryWorkflow.run, + "in", + id=f"summary-{uuid.uuid4()}", + task_queue=task_queue, + ) + assert result == {"value": "in-has_fn=False"} + + +@workflow.defn +class WorkflowNodeSummaryWorkflow: + def __init__(self) -> None: + self.app = graph("wf-node-graph").compile() + self._done = False + self._invoked = False + + @workflow.run + async def run(self, input: str) -> Any: + result = await self.app.ainvoke({"value": input}) + self._invoked = True + await workflow.wait_condition(lambda: self._done) + return result + + @workflow.signal + def finish(self) -> None: + self._done = True + + @workflow.query + def ran(self) -> bool: + return workflow.get_current_details() != "" + + @workflow.query + def invoked(self) -> bool: + return self._invoked + + +async def test_workflow_node_sets_current_details( + client: Client, env: WorkflowEnvironment +) -> None: + if env.supports_time_skipping: + pytest.skip("metadata query unreliable on the time-skipping test server") + g: StateGraph[State, None, State, State] = StateGraph(State) + g.add_node( + "node", + passthrough, + metadata={ + "execute_in": "workflow", + "summary_fn": lambda args, kwargs: f"wf:{args[0]['value']}", + }, + ) + g.add_edge(START, "node") + task_queue = f"wf-node-{uuid.uuid4()}" + async with Worker( + client, + task_queue=task_queue, + workflows=[WorkflowNodeSummaryWorkflow], + plugins=[LangGraphPlugin(graphs={"wf-node-graph": g})], + ): + handle = await client.start_workflow( + WorkflowNodeSummaryWorkflow.run, + "ready", + id=f"wf-node-{uuid.uuid4()}", + task_queue=task_queue, + ) + await assert_eq_eventually( + True, lambda: handle.query(WorkflowNodeSummaryWorkflow.ran) + ) + md: temporalio.api.sdk.v1.WorkflowMetadata = await handle.query( + "__temporal_workflow_metadata", + result_type=temporalio.api.sdk.v1.WorkflowMetadata, + ) + assert md.current_details == "wf:ready" + await handle.signal(WorkflowNodeSummaryWorkflow.finish) + assert await handle.result() == {"value": "ready"} + + +async def test_workflow_node_clears_current_details_on_empty( + client: Client, env: WorkflowEnvironment +) -> None: + if env.supports_time_skipping: + pytest.skip("metadata query unreliable on the time-skipping test server") + g: StateGraph[State, None, State, State] = StateGraph(State) + g.add_node( + "a", + passthrough, + metadata={"execute_in": "workflow", "summary_fn": lambda args, kwargs: "first"}, + ) + g.add_node( + "b", + passthrough, + metadata={"execute_in": "workflow", "summary_fn": lambda args, kwargs: None}, + ) + g.add_edge(START, "a") + g.add_edge("a", "b") + task_queue = f"wf-node-clear-{uuid.uuid4()}" + async with Worker( + client, + task_queue=task_queue, + workflows=[WorkflowNodeSummaryWorkflow], + plugins=[LangGraphPlugin(graphs={"wf-node-graph": g})], + ): + handle = await client.start_workflow( + WorkflowNodeSummaryWorkflow.run, + "ready", + id=f"wf-node-clear-{uuid.uuid4()}", + task_queue=task_queue, + ) + await assert_eq_eventually( + True, lambda: handle.query(WorkflowNodeSummaryWorkflow.invoked) + ) + md: temporalio.api.sdk.v1.WorkflowMetadata = await handle.query( + "__temporal_workflow_metadata", + result_type=temporalio.api.sdk.v1.WorkflowMetadata, + ) + assert md.current_details == "" + await handle.signal(WorkflowNodeSummaryWorkflow.finish) + await handle.result() + + +async def test_replay_with_summary_fn(client: Client) -> None: + plugin = _plugin(_activity_graph(summarize)) + task_queue = f"summary-replay-{uuid.uuid4()}" + async with Worker( + client, + task_queue=task_queue, + workflows=[SummaryWorkflow], + plugins=[plugin], + ): + handle = await client.start_workflow( + SummaryWorkflow.run, + "hello", + id=f"summary-replay-{uuid.uuid4()}", + task_queue=task_queue, + ) + await handle.result() + + await Replayer(workflows=[SummaryWorkflow], plugins=[plugin]).replay_workflow( + await handle.fetch_history() + ) From 4ec9ab05b41a14cf8bf37a83f09fbfeb59628f7a Mon Sep 17 00:00:00 2001 From: Jason Steving <32336750+JasonSteving99@users.noreply.github.com> Date: Thu, 9 Jul 2026 14:16:06 -0700 Subject: [PATCH 157/226] Add First-Class Google Gen AI SDK Integration to Contrib (#1378) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Add First-Class Gemini SDK Integration to Contrib # Temporal Integration for the Google Gemini SDK This adds a first-class integration that lets users call the Gemini SDK's `AsyncClient` directly from within Temporal workflows. Every API call and tool invocation becomes a durable Temporal activity — giving full crash recovery, visibility in workflow event history, and replay safety — while keeping credentials entirely on the worker side. ## How it works The integration shims three layers of the Gemini SDK so that workflows can use `client.models`, `client.files`, `client.file_search_stores`, `client.chats`, and all other SDK modules naturally: ### `TemporalApiClient` (`_temporal_api_client.py`) A `BaseApiClient` subclass that replaces the SDK's HTTP layer. Instead of making network calls, `async_request` and `async_request_streamed` serialize the request and dispatch it through `workflow.execute_activity`. The real HTTP call happens inside the activity on the worker, where the actual `genai.Client` with real credentials lives. Sync methods raise immediately. Per-request `http_options` are validated (non-serializable fields like `httpx_client` are rejected), and `timeout` is mapped to Temporal's `start_to_close_timeout`. ### `TemporalAsyncFiles` / `TemporalAsyncFileSearchStores` (`_temporal_files.py`, `_temporal_file_search_stores.py`) Subclasses of `AsyncFiles` and `AsyncFileSearchStores` that override `upload`, `download`, `register_files`, and `upload_to_file_search_store` to dispatch the entire operation as a Temporal activity. This avoids filesystem access (`os` module) and credential token refresh in the workflow sandbox. Methods like `get`, `delete`, `list` are inherited and work through the `TemporalApiClient`'s `async_request` activity. File uploads accept `str` paths (resolved on the worker), `os.PathLike`, or `io.IOBase` (bytes serialized across the activity boundary). ### `TemporalAsyncClient` (`_temporal_async_client.py`) An `AsyncClient` subclass that wires in `TemporalAsyncFiles` and `TemporalAsyncFileSearchStores`. All other SDK modules (`models`, `tunings`, `caches`, `batches`, `live`, `tokens`, `operations`) are inherited unchanged since they only use `async_request` under the hood. ### `GeminiPlugin` (`_gemini_plugin.py`) A `SimplePlugin` that registers all activities, configures the Pydantic data converter, and passes `google.genai` through the workflow sandbox. Users pass a fully configured `genai.Client` — the plugin never constructs one itself. An optional `extra_credentials` parameter supports operations like `register_files` that need separate GCS credentials. ### `activity_as_tool` (`workflow.py`) Wraps any `@activity.defn` function so it looks like a regular async callable to Gemini's automatic function calling (AFC). When the model decides to call the tool, the SDK invokes the wrapper, which dispatches through `workflow.execute_activity`. Users can also pass plain workflow methods directly as tools — these run in-workflow without an activity. ### Batched streaming `generate_content_stream` is supported via a batched approach: the `async_request_streamed` activity collects all chunks from the real streaming response and returns them as a list. The workflow-side `TemporalApiClient` yields them back as an async generator so the SDK sees the expected interface. ## Usage ```python # Worker side client = genai.Client(api_key=os.environ["GOOGLE_API_KEY"]) plugin = GeminiPlugin(client) # Workflow side @workflow.defn class MyWorkflow: @workflow.run async def run(self, query: str) -> str: client = gemini_client() response = await client.models.generate_content( model="gemini-2.5-flash", contents=query, config=types.GenerateContentConfig( tools=[activity_as_tool(my_tool)], ), ) return response.text ``` ## Testing 31 integration tests covering: - Basic `generate_content` and multi-chunk streaming - AFC tool calling (single-arg, multi-arg, workflow methods, sequential multi-tool, failure propagation) - Per-request `http_options` propagation (headers, api_version, base_url) - File upload via str path and `io.BytesIO`, file download - File search store upload - Multi-turn chat via `client.chats` - `TemporalAsyncClient` wiring verification - `TemporalApiClient` error paths (sync raises, low-level upload/download raises) - `activity_as_tool` validation and signature preservation - A full end-to-end integration test that exercises all real activity implementations (generate, stream, file upload, download, store upload, RAG query, store delete) with a mocked `genai.Client` — ensuring the actual activity code in `_gemini_activity.py` is covered, not just the workflow-side shims. * update lock * address PR feedback * upper bound google-genai dep * move to `.../contrib/google_genai/` * rename `gemini_client` -> `google_genai_client` * Rename `GeminiPlugin` -> `GoogleGenAIPlugin` * add to codeowners * Fix docstring errors breaking poe gen-docs pydoctor runs with warnings-as-errors: the bullet list needed a blank line before it, and the :func: reference must use the unqualified name since pydoctor relocates __all__ re-exports to the package page. * google_genai: add MCP support, interactions/agents, and durability tests Client-side MCP (Gemini Developer API): TemporalMcpClientSession subclasses mcp.ClientSession and routes list_tools/call_tool through {server}-list-tools and {server}-call-tool activities, so the SDK's in-workflow AFC loop drives MCP tools while the real session lives on the worker. Servers register on the plugin via mcp_servers={name: factory} with a pooled, idle-evicted worker-side connection (mcp_connection_idle_timeout). Server-side MCP (Vertex McpServer config and Interactions API MCP steps) flows through unchanged as data. Also in this change: - Interactions API and managed agents support, plus files/file-search activities - Collapse activity_config defaults to a single documented 60s start_to_close - activity_as_tool requires an explicit timeout (matches openai_agents/strands) - Replay and side-effect (ActivityTaskScheduled count) tests, incl. MCP - mcp is an optional dep: lazy import + TYPE_CHECKING so the package imports without it; declared in the dev group for tests Co-Authored-By: Claude Opus 4.8 * google_genai: add GoogleGenAIError and make Temporal own retries - Add GoogleGenAIError(ApplicationError) and register it via the plugin's workflow_failure_exception_types so it terminally fails the workflow rather than retrying the task; activity_as_tool validation now raises it. - Reject the SDK's own retry config instead of silently overriding it: the plugin raises ValueError if the genai.Client has http_options.retry_options, and the workflow-side client raises GoogleGenAIError on per-request retry_options (previously dropped silently). Both point users to the activity retry_policy via activity_config. - Classify API-call activity errors: catch google.genai.errors.APIError and re-raise as ApplicationError with non_retryable set by HTTP status (408/429/5xx retryable, 4xx fail fast), with the SDK error class name as the type. Co-Authored-By: Claude Opus 4.8 * google_genai: add README, fix plugin name, document determinism, widen passthrough - Add a user-facing README (overview, install, hello world, tool calling, MCP, retries/errors, Vertex, composing). - Rename the plugin to the conventional "google_genai.GoogleGenAIPlugin". - Document the replay-determinism survey: the generate_content/AFC/MCP paths are replay-safe; note the one in-workflow caveat (Vertex batches.create auto-naming). - Add pydantic_core and annotated_types to sandbox passthrough so the SDK's in-workflow Pydantic validation doesn't reimport them after workflow load. Co-Authored-By: Claude Opus 4.8 * google_genai: README — explain Vertex project/location, trim MCP section - Vertex AI: document that project/location must be set explicitly on the workflow-side client; auto-discovery can't run in the sandbox and would make in-workflow request formatting non-deterministic. - MCP: drop the server-side/interactions bullet (works unchanged, no wiring) and focus the section on the client-side path the plugin actually wires. Co-Authored-By: Claude Opus 4.8 * google_genai: pin google-genai < 2.8.0 (in-workflow AFC regression) google-genai 2.8.0 regressed automatic function calling for plain workflow-method tools: the tool executes (its function response is correct) but its in-workflow state mutation is no longer visible on replay/query, failing test_workflow_method_as_tool. The activity_as_tool path is unaffected. Cap at < 2.8.0 until a fixed release ships upstream. Also simplify exclude-newer-package to disable the cutoff for google-adk outright (= false) rather than a dated pin that needs later cleanup. Co-Authored-By: Claude Opus 4.8 * google_genai: fix poe lint (exports, import order, type nits) - Export GoogleGenAIError in __all__ (fixes unused-import in __init__ and the "not exported" warning where tests import it from the package). - Sort imports in _gemini_activity.py (ruff I001). - Suppress reportUnusedClass on _TemporalApiClient (used in the sibling module) and reportUnusedFunction on the autouse MCP fixture, matching repo convention. - Use collections.abc.AsyncIterator and annotate the test helper parameter. Co-Authored-By: Claude Opus 4.8 * google_genai: add public testing utilities Add temporalio/contrib/google_genai/testing.py so users can test workflows that use TemporalAsyncClient without real Gemini API calls — the agent-framework "test fakes are table-stakes" expectation, matching openai_agents/testing.py. - text_response / function_call_response build canned generate_content bodies - GeminiTestServer scripts model responses (incl. AFC turns and streaming) and exposes a GoogleGenAIPlugin via .plugin(); records requests for assertions Co-Authored-By: Claude Opus 4.8 * google_genai: stream generate_content_stream via Workflow Streams Set TemporalAsyncClient(streaming_topic=...) and host a WorkflowStream in the workflow's @workflow.init; each generate_content_stream chunk is then published to that topic (as a parsed GenerateContentResponse) as it arrives, so external WorkflowStreamClient consumers observe model output in real time while the workflow runs durably. The workflow's own iteration is unchanged (still batched). - _models: _GeminiApiRequest carries streaming_topic + streaming_batch_interval_ms - TemporalAsyncClient/_TemporalApiClient: streaming_topic + streaming_batch_interval; fail fast (GoogleGenAIError) if a topic is set but no WorkflowStream is hosted - streamed activity publishes via WorkflowStreamClient.from_within_activity; publishing is best-effort and never breaks the batched return - README Streaming section + module docstring; tests in test_gemini_streaming.py Co-Authored-By: Claude Opus 4.8 * google_genai: fix gen-docs cross-reference link targets pydoctor (warnings-as-errors) couldn't resolve the `~`-prefixed `:class:` cross-references added for streaming/testing docstrings. Drop the `~` prefix to use the full dotted path, matching the form already used elsewhere (e.g. openai_agents references temporalio.contrib.workflow_streams.WorkflowStream). Co-Authored-By: Claude Opus 4.8 * google_genai: closure-wrap workflow-method tools for config deep-copy google-genai >= 2.8.0 deep-copies the request config internally (config.model_copy(deep=True)), which clones a bound-method tool's __self__ — so a workflow-method tool runs against a throwaway clone and its in-workflow state mutation is silently lost. TemporalAsyncClient now closure-wraps bound-method tools before handing the config to the SDK; copy.deepcopy leaves plain functions intact, so the closure keeps the tool bound to the real workflow instance. Plain functions and activity_as_tool wrappers are unaffected. Co-Authored-By: Claude Opus 4.8 (1M context) * google_genai: migrate interactions/agents to public API; require google-genai 2.10 google-genai 2.9.0 regenerated the vendored interactions client (google.genai._interactions -> google.genai._gaos), removing the private symbols the interactions/agents shims imported (construct_type, AsyncStream, and the AsyncInteractionsResource/AsyncAgentsResource base classes). Retarget the shims to the public google.genai.interactions surface: - TemporalAsyncInteractions/TemporalAsyncAgents are now standalone classes (they already overrode every method), not private-resource subclasses. - _deserialize uses public pydantic only: a TypeAdapter dispatches the InteractionSSEEvent discriminated union (and nested unions), and model_validate rehydrates plain models (recursing nested objects). - _TemporalInteractionAsyncStream is a plain async iterator/context manager, no longer subclassing the SDK's AsyncStream. - Worker-side activities use public types; the stream drain is typed structurally. Bump the pin to google-genai>=2.10.0,<3 (with an exclude-newer-package override so uv can select it past the cutoff) and update the tests. Co-Authored-By: Claude Opus 4.8 (1M context) * Fix lint errors from google-genai 2.10 migration - Mark the Agent import from google.genai.interactions with a reportPrivateImportUsage ignore (pyright can't follow the module's dynamically-built __all__), matching the source modules. - Narrow types in the bound-method tool-wrapping unit tests so pyright and mypy accept attribute/subscript access on the helper results. - Add missing __init__ docstrings flagged by pydocstyle. Co-Authored-By: Claude Fable 5 * Fix ADK multi-agent test mock under google-adk 2.4 google-adk 2.4 rewrites cross-agent history into "For context:" text parts after a transfer, so ResearchModel's dedup-against-history never matched and it re-served "transfer to researcher" to the researcher itself, failing test-latest-deps with "Agent 'researcher' cannot transfer to itself". Key the scripted responses off the calling agent's instruction text instead, which is stateless (replay-safe) and independent of ADK history rewriting. Passes on both the locked google-adk 2.2.0 and latest 2.4.0. Co-Authored-By: Claude Fable 5 --------- Co-authored-by: Brian Strauch Co-authored-by: Claude Opus 4.8 --- .github/CODEOWNERS | 2 + pyproject.toml | 6 +- temporalio/contrib/google_genai/README.md | 285 +++ temporalio/contrib/google_genai/__init__.py | 119 + temporalio/contrib/google_genai/_errors.py | 16 + .../contrib/google_genai/_gemini_activity.py | 356 +++ .../google_genai/_google_genai_plugin.py | 158 ++ temporalio/contrib/google_genai/_mcp.py | 226 ++ temporalio/contrib/google_genai/_models.py | 172 ++ .../contrib/google_genai/_temporal_agents.py | 143 ++ .../google_genai/_temporal_api_client.py | 319 +++ .../google_genai/_temporal_async_client.py | 285 +++ .../_temporal_file_search_stores.py | 109 + .../contrib/google_genai/_temporal_files.py | 169 ++ .../google_genai/_temporal_interactions.py | 257 +++ .../contrib/google_genai/_temporal_mcp.py | 116 + temporalio/contrib/google_genai/testing.py | 151 ++ temporalio/contrib/google_genai/workflow.py | 111 + .../test_google_adk_agents.py | 84 +- tests/contrib/google_genai/__init__.py | 1 + tests/contrib/google_genai/echo_mcp_server.py | 15 + tests/contrib/google_genai/test_gemini.py | 2052 +++++++++++++++++ tests/contrib/google_genai/test_gemini_mcp.py | 389 ++++ .../google_genai/test_gemini_streaming.py | 122 + uv.lock | 1016 +------- 25 files changed, 5651 insertions(+), 1028 deletions(-) create mode 100644 temporalio/contrib/google_genai/README.md create mode 100644 temporalio/contrib/google_genai/__init__.py create mode 100644 temporalio/contrib/google_genai/_errors.py create mode 100644 temporalio/contrib/google_genai/_gemini_activity.py create mode 100644 temporalio/contrib/google_genai/_google_genai_plugin.py create mode 100644 temporalio/contrib/google_genai/_mcp.py create mode 100644 temporalio/contrib/google_genai/_models.py create mode 100644 temporalio/contrib/google_genai/_temporal_agents.py create mode 100644 temporalio/contrib/google_genai/_temporal_api_client.py create mode 100644 temporalio/contrib/google_genai/_temporal_async_client.py create mode 100644 temporalio/contrib/google_genai/_temporal_file_search_stores.py create mode 100644 temporalio/contrib/google_genai/_temporal_files.py create mode 100644 temporalio/contrib/google_genai/_temporal_interactions.py create mode 100644 temporalio/contrib/google_genai/_temporal_mcp.py create mode 100644 temporalio/contrib/google_genai/testing.py create mode 100644 temporalio/contrib/google_genai/workflow.py create mode 100644 tests/contrib/google_genai/__init__.py create mode 100644 tests/contrib/google_genai/echo_mcp_server.py create mode 100644 tests/contrib/google_genai/test_gemini.py create mode 100644 tests/contrib/google_genai/test_gemini_mcp.py create mode 100644 tests/contrib/google_genai/test_gemini_streaming.py diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 145eb42c4..2c01cc259 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -11,12 +11,14 @@ # as well as @temporalio/sdk, so the SDK team can continue to # manage repo-wide concerns. /temporalio/contrib/google_adk_agents/ @temporalio/ai-sdk @temporalio/sdk +/temporalio/contrib/google_genai/ @temporalio/ai-sdk @temporalio/sdk /temporalio/contrib/langgraph/ @temporalio/ai-sdk @temporalio/sdk /temporalio/contrib/langsmith/ @temporalio/ai-sdk @temporalio/sdk /temporalio/contrib/openai_agents/ @temporalio/ai-sdk @temporalio/sdk /temporalio/contrib/strands/ @temporalio/ai-sdk @temporalio/sdk /temporalio/contrib/workflow_streams/ @temporalio/ai-sdk @temporalio/sdk /tests/contrib/google_adk_agents/ @temporalio/ai-sdk @temporalio/sdk +/tests/contrib/google_genai/ @temporalio/ai-sdk @temporalio/sdk /tests/contrib/langgraph/ @temporalio/ai-sdk @temporalio/sdk /tests/contrib/langsmith/ @temporalio/ai-sdk @temporalio/sdk /tests/contrib/openai_agents/ @temporalio/ai-sdk @temporalio/sdk diff --git a/pyproject.toml b/pyproject.toml index 99aea21bf..9017519b2 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -29,7 +29,7 @@ grpc = ["grpcio>=1.48.2,<2"] opentelemetry = ["opentelemetry-api>=1.11.1,<2", "opentelemetry-sdk>=1.11.1,<2"] pydantic = ["pydantic>=2.0.0,<3"] openai-agents = ["openai-agents>=0.17.5", "mcp>=1.9.4, <2"] -google-adk = ["google-adk>=1.27.0,<2"] +google-adk = ["google-adk>=2.2.0,<3"] langgraph = ["langgraph>=1.1.0"] langsmith = ["langsmith>=0.7.34,<0.9"] lambda-worker-otel = [ @@ -40,6 +40,7 @@ lambda-worker-otel = [ "opentelemetry-sdk-extension-aws>=2.0.0,<3", ] aioboto3 = ["aioboto3>=10.4.0", "types-aioboto3[s3]>=10.4.0"] +google-genai = ["google-genai>=2.10.0,<3.0.0"] strands-agents = ["strands-agents>=1.39.0"] [project.urls] @@ -88,6 +89,7 @@ dev = [ "async-timeout>=4.0,<6; python_version < '3.11'", "strands-agents>=1.39.0", "strands-agents-tools>=0.5.2", + "mcp>=1.9.4,<2", ] [tool.poe.tasks] @@ -260,4 +262,4 @@ exclude = ["temporalio/bridge/target/**/*"] # Prevent uv commands from building the package by default package = false exclude-newer = "2 weeks" -exclude-newer-package = { openai-agents = false } +exclude-newer-package = { google-adk = false, google-genai = false, openai-agents = false } diff --git a/temporalio/contrib/google_genai/README.md b/temporalio/contrib/google_genai/README.md new file mode 100644 index 000000000..fca5311f5 --- /dev/null +++ b/temporalio/contrib/google_genai/README.md @@ -0,0 +1,285 @@ +# Google Gemini SDK Integration for Temporal + +> ⚠️ **Experimental.** This integration may change in future versions. Use with +> caution in production. + +## Overview + +This plugin lets you use the [Google Gemini SDK](https://googleapis.github.io/python-genai/) +(`google-genai`) inside Temporal workflows with durable execution. Every Gemini +API call becomes a **Temporal activity**, so model calls, tool calls, file +operations, interactions, and managed agents are retried, recorded in history, +and survive worker restarts. + +Key properties: + +- **Credentials never enter the workflow.** The real `genai.Client` lives only + on the worker, inside activities; no API keys or tokens appear in event + history. +- **The SDK's automatic function calling (AFC) loop runs in the workflow**, so + tool wrappers (`activity_as_tool`) work naturally — no manual agent loop. +- **Temporal owns retries.** Configure them via the activity `retry_policy`; the + SDK's own retry loop is rejected to avoid double-retry (see + [Retries & errors](#retries--errors)). + +## Install + +```bash +uv add temporalio google-genai +# For client-side MCP support, also: +uv add mcp +``` + +## Hello World + +```python +import os +from datetime import timedelta + +from google import genai +from google.genai import types + +from temporalio import activity, workflow +from temporalio.client import Client +from temporalio.contrib.google_genai import ( + GoogleGenAIPlugin, + TemporalAsyncClient, + activity_as_tool, +) +from temporalio.worker import Worker +from temporalio.workflow import ActivityConfig + + +# ---- a tool, as a normal Temporal activity (runs on the worker) ---- +@activity.defn +async def get_weather(city: str) -> str: + return f"It's sunny in {city}." + + +# ---- the workflow (runs in the Temporal sandbox) ---- +@workflow.defn +class WeatherAgent: + @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), + ), + ), + ], + ), + ) + return response.text or "" + + +# ---- worker setup (outside the sandbox: real client + credentials) ---- +async def main() -> None: + gemini = genai.Client(api_key=os.environ["GOOGLE_API_KEY"]) + plugin = GoogleGenAIPlugin(gemini) + + client = await Client.connect("localhost:7233", plugins=[plugin]) + async with Worker( + client, + task_queue="gemini", + workflows=[WeatherAgent], + activities=[get_weather], + ): + result = await client.execute_workflow( + WeatherAgent.run, + "What's the weather in Tokyo?", + id="weather-1", + task_queue="gemini", + ) + print(result) +``` + +Construct `TemporalAsyncClient` **inside** the workflow; construct the real +`genai.Client` and `GoogleGenAIPlugin` **on the worker**. + +## What this plugin gives you + +| Surface | Workflow API | Runs as | +| --- | --- | --- | +| Model calls | `client.models.generate_content` / `generate_content_stream` | activity (AFC loop in workflow) | +| Tools | `activity_as_tool(fn, ...)` | one activity per tool call | +| Files | `client.files.upload` / `download` | activity | +| File search | `client.file_search_stores.upload_to_file_search_store` | activity | +| Interactions | `client.interactions.create` / `get` / `cancel` / `delete` | whole-operation activity | +| Managed agents | `client.agents.create` / `get` / `list` / `delete` | whole-operation activity | +| MCP (client-side) | `TemporalMcpClientSession(name)` in `tools=[...]` | `list_tools` / `call_tool` activities | + +Streamed responses are batched: the activity drains the stream and the workflow +iterates the collected chunks/events. `client.webhooks` is not supported in +workflows and raises. + +## Tool calling + +`activity_as_tool` wraps any `@activity.defn` function as a Gemini tool. When the +model calls it, the AFC loop (running in the workflow) dispatches it as a +durable activity: + +```python +activity_as_tool( + get_weather, + activity_config=ActivityConfig(start_to_close_timeout=timedelta(seconds=30)), +) +``` + +A timeout is required — `activity_config` must set `start_to_close_timeout` or +`schedule_to_close_timeout` (Temporal needs one; there is no default for tools). + +## MCP support + +Client-side MCP (Gemini Developer API) is wired through the plugin: register the +server on the worker and reference it by name in the workflow. + +```python +from contextlib import asynccontextmanager +import sys + +from mcp import ClientSession, StdioServerParameters +from mcp.client.stdio import stdio_client + +from temporalio.contrib.google_genai import TemporalMcpClientSession + + +# ---- worker: a factory yielding a connected, initialized session ---- +@asynccontextmanager +async def weather_mcp(): + params = StdioServerParameters(command=sys.executable, args=["weather_server.py"]) + async with stdio_client(params) as (read, write): + async with ClientSession(read, write) as session: + await session.initialize() + yield session + + +plugin = GoogleGenAIPlugin( + genai.Client(api_key=os.environ["GOOGLE_API_KEY"]), + mcp_servers={"weather": weather_mcp}, + mcp_connection_idle_timeout=timedelta(minutes=5), +) + + +# ---- workflow: reference the server by name in the tools list ---- +@workflow.defn +class McpAgent: + @workflow.run + async def run(self, prompt: str) -> str: + client = TemporalAsyncClient() + session = TemporalMcpClientSession( + "weather", + 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 "" +``` + +The MCP connection lives on the worker (pooled, idle-evicted); the workflow only +carries the server name. Tool discovery and calls run as `{name}-list-tools` / +`{name}-call-tool` activities, so the full tool parameter schema reaches the +model. Set `cache_tools=True` to list a server's tools once per workflow instead +of per turn. + +## Streaming + +`generate_content_stream` works as usual — the workflow iterates chunks (batched +from the activity). To let an **external** consumer (a chat UI) observe chunks in +real time while the workflow runs durably, set `streaming_topic` on the client +and host a [`WorkflowStream`](../workflow_streams/) in the workflow. Each +streamed `GenerateContentResponse` is published to that topic as it arrives: + +```python +from temporalio.contrib.workflow_streams import WorkflowStream + + +@workflow.defn +class StreamingAgent: + @workflow.init + def __init__(self, prompt: str) -> None: + self.stream = WorkflowStream() # required when streaming_topic is set + + @workflow.run + async def run(self, prompt: str) -> str: + client = TemporalAsyncClient(streaming_topic="gemini") + text = [] + async for chunk in await client.models.generate_content_stream( + model="gemini-2.5-flash", contents=prompt, + ): + text.append(chunk.text or "") + return "".join(text) +``` + +Consume the stream from outside the workflow: + +```python +from temporalio.contrib.workflow_streams import WorkflowStreamClient + + +async def consume(client, workflow_id): + stream = WorkflowStreamClient.create(client, workflow_id) + async for item in stream.subscribe( + ["gemini"], result_type=types.GenerateContentResponse, + ): + print(item.data.text, end="", flush=True) +``` + +The workflow's own iteration is unchanged (it still receives batched chunks for +the SDK to parse); the topic is purely for external real-time observation. If +`streaming_topic` is set but the workflow hosts no `WorkflowStream`, the call +raises `GoogleGenAIError`. Tune flush cadence with +`TemporalAsyncClient(streaming_topic=..., streaming_batch_interval=...)` +(default 100ms). + +## Retries & errors + +Temporal owns retries. Configure them with the activity `retry_policy` via +`activity_config`. The plugin **rejects** the SDK's own retry config so retries +don't compound: + +- Constructing the plugin with a `genai.Client` that has + `http_options.retry_options` raises `ValueError`. +- Setting `http_options.retry_options` on a per-request call raises + `GoogleGenAIError`. + +API-call activities classify failures: transient statuses (408, 429, 5xx) stay +retryable (the activity's `retry_policy` applies); other statuses (e.g. 4xx) are +non-retryable so the workflow fails fast. + +## Vertex AI + +Pass `vertexai=True` to both the worker-side `genai.Client` and the +workflow-side `TemporalAsyncClient`. On the workflow side you must also set +`project` and `location` **explicitly**: + +```python +# worker +genai.Client(vertexai=True, project="my-project", location="us-central1") + +# workflow +TemporalAsyncClient(vertexai=True, project="my-project", location="us-central1") +``` + +Normally the SDK auto-discovers `project`/`location` from the environment +(credentials, ADC, metadata server). That discovery +would be non-deterministic and break replay. Setting them by hand +keeps it deterministic. + +## Composing with other plugins + +`GoogleGenAIPlugin` is a `temporalio.plugin.SimplePlugin`; pass it in the +`plugins=[...]` list alongside others (e.g. OpenTelemetry). It contributes a +Pydantic data converter, the Gemini activities, a sandbox-passthrough config for +`google.genai` (and `mcp`), and registers `GoogleGenAIError` as a workflow +failure type. When composing data converters, construct the plugins so their +converters are compatible. diff --git a/temporalio/contrib/google_genai/__init__.py b/temporalio/contrib/google_genai/__init__.py new file mode 100644 index 000000000..8cedcbc63 --- /dev/null +++ b/temporalio/contrib/google_genai/__init__.py @@ -0,0 +1,119 @@ +"""First-class Temporal integration for the Google Gemini SDK. + +.. warning:: + This module is experimental and may change in future versions. + Use with caution in production environments. + +This integration lets you use the Gemini SDK's async client with full +automatic function calling (AFC) support. Every API call becomes a +**durable Temporal activity**. Tools default to plain workflow methods +that run deterministically in-workflow; wrap any ``@activity.defn`` with +:func:`activity_as_tool` to run a tool as a durable activity instead. + +No credentials are fetched in the workflow, and no auth material appears in +Temporal's event history. + +- :class:`GoogleGenAIPlugin` — registers the Gemini SDK activities using a + caller-provided ``genai.Client`` on the worker side. +- :class:`TemporalAsyncClient` — construct from a workflow to get an + ``AsyncClient`` that routes API calls through activities. +- :func:`activity_as_tool` — convert any ``@activity.defn`` function into a + Gemini tool callable; Gemini's AFC invokes it as a Temporal activity. + +The Interactions API (``client.interactions``) and managed agents +(``client.agents``) are supported as whole-operation activities; streamed +interactions are batched (the activity drains the SSE stream and the +workflow iterates the collected events). ``client.webhooks`` is not +supported in workflows. The Interactions API has no automatic function +calling: declare tools as ``{"type": "function", ...}`` dicts (per the +Gemini docs) and drive the tool loop yourself, executing each call via +``workflow.execute_activity`` or an :func:`activity_as_tool` callable. + +MCP is supported across three paths. Client-side MCP (Gemini Developer API) +uses :class:`TemporalMcpClientSession`: register a server with +``GoogleGenAIPlugin(mcp_servers={name: factory})`` on the worker, then place +``TemporalMcpClientSession(name)`` in a ``generate_content`` ``tools`` list — +the SDK's AFC loop drives it, with ``list_tools`` / ``call_tool`` running as +activities against a pooled worker-side connection. Server-side MCP on Vertex +AI (``Tool(mcp_servers=[McpServer(...)])``) and the Interactions API's MCP step +types are executed by Google's backend and flow through unchanged as request / +response data — no extra wiring needed. Client-side MCP requires the ``mcp`` +package. + +Streaming: set ``TemporalAsyncClient(streaming_topic=...)`` and host a +:class:`temporalio.contrib.workflow_streams.WorkflowStream` in the workflow's +``@workflow.init``. Each ``generate_content_stream`` chunk is then published to +that topic as it arrives, so external consumers can observe model output in real +time while the workflow runs durably; the workflow's own iteration is unchanged. + +Quickstart:: + + # ---- worker setup (outside the Temporal Python Sandbox) ---- + client = genai.Client(api_key=os.environ["GOOGLE_API_KEY"]) + plugin = GoogleGenAIPlugin(client) + + @activity.defn + async def get_weather(state: str) -> str: ... + + # ---- workflow (inside the Temporal Python Sandbox) ---- + @workflow.defn + class AgentWorkflow: + @workflow.run + async def run(self, query: str) -> str: + client = TemporalAsyncClient() + response = await client.models.generate_content( + model="gemini-2.5-flash", + contents=query, + config=types.GenerateContentConfig( + tools=[ + activity_as_tool( + get_weather, + activity_config=ActivityConfig( + start_to_close_timeout=timedelta(seconds=30), + ), + ), + ], + ), + ) + return response.text +""" + +from __future__ import annotations + +from typing import TYPE_CHECKING, Any + +from temporalio.contrib.google_genai._errors import GoogleGenAIError +from temporalio.contrib.google_genai._google_genai_plugin import GoogleGenAIPlugin +from temporalio.contrib.google_genai._temporal_async_client import ( + TemporalAsyncClient, +) +from temporalio.contrib.google_genai.workflow import ( + activity_as_tool, +) + +if TYPE_CHECKING: + from temporalio.contrib.google_genai._temporal_mcp import TemporalMcpClientSession + +__all__ = [ + "GoogleGenAIError", + "GoogleGenAIPlugin", + "TemporalAsyncClient", + "TemporalMcpClientSession", + "activity_as_tool", +] + + +def __getattr__(name: str) -> Any: + """Lazily expose ``TemporalMcpClientSession`` without importing ``mcp`` eagerly. + + ``mcp`` is an optional dependency, so importing this package must not require + it; the import (and any resulting ``ImportError``) is deferred until the + symbol is actually accessed. + """ + if name == "TemporalMcpClientSession": + from temporalio.contrib.google_genai._temporal_mcp import ( + TemporalMcpClientSession, + ) + + return TemporalMcpClientSession + raise AttributeError(f"module {__name__!r} has no attribute {name!r}") diff --git a/temporalio/contrib/google_genai/_errors.py b/temporalio/contrib/google_genai/_errors.py new file mode 100644 index 000000000..3f6595e4b --- /dev/null +++ b/temporalio/contrib/google_genai/_errors.py @@ -0,0 +1,16 @@ +"""Error types for the Google Gemini SDK Temporal integration.""" + +from __future__ import annotations + +from temporalio.exceptions import ApplicationError + + +class GoogleGenAIError(ApplicationError): + """Error raised by the Google Gemini Temporal integration. + + Registered with the worker (and replayer) via + ``workflow_failure_exception_types`` so that, when raised in workflow code, + it terminally fails the workflow execution rather than failing the workflow + task and retrying it indefinitely. Use it for conditions that cannot be + recovered by retry — e.g. a tool that is not a valid Temporal activity. + """ diff --git a/temporalio/contrib/google_genai/_gemini_activity.py b/temporalio/contrib/google_genai/_gemini_activity.py new file mode 100644 index 000000000..2e92c56a1 --- /dev/null +++ b/temporalio/contrib/google_genai/_gemini_activity.py @@ -0,0 +1,356 @@ +"""Temporal activity that executes Gemini SDK API calls with real credentials. + +The ``TemporalApiClient`` in the workflow dispatches calls here. This +activity holds a user-provided ``genai.Client`` and forwards structured +requests. Credentials are fetched/refreshed only within the activity — +they never appear in workflow event history. +""" + +from __future__ import annotations + +from collections.abc import Sequence +from contextlib import AsyncExitStack +from datetime import timedelta +from typing import Any, Callable + +import google.auth.credentials +from google.genai import Client as GeminiClient +from google.genai import errors as genai_errors +from google.genai import types +from google.genai.interactions import Interaction +from google.genai.types import HttpOptions +from google.genai.types import HttpResponse as SdkHttpResponse + +from temporalio import activity +from temporalio.contrib.google_genai._models import ( + _GeminiApiRequest, + _GeminiApiResponse, + _GeminiApiStreamedResponse, + _GeminiDownloadFileRequest, + _GeminiInteractionIdRequest, + _GeminiInteractionRequest, + _GeminiInteractionStreamedResponse, + _GeminiRegisterFilesRequest, + _GeminiUploadFileRequest, + _GeminiUploadToFileSearchStoreRequest, +) +from temporalio.contrib.workflow_streams import WorkflowStreamClient +from temporalio.exceptions import ApplicationError + + +def _resolve_http_options( + overrides: Any, +) -> HttpOptions | None: + """Reconstruct ``HttpOptions`` from serializable overrides, or None.""" + if overrides is None: + return None + return HttpOptions.model_validate(overrides.model_dump(exclude_none=True)) + + +# HTTP status codes the Gemini SDK itself treats as transient/retryable. +_RETRYABLE_HTTP_STATUS = frozenset({408, 429, 500, 502, 503, 504}) + + +def _classify_api_error(err: genai_errors.APIError) -> ApplicationError: + """Map a Gemini ``APIError`` to an ``ApplicationError`` Temporal can act on. + + Transient statuses (timeouts, rate limits, 5xx) stay retryable so the + activity's retry policy applies; everything else (e.g. 4xx client errors) + is marked non-retryable so the workflow fails fast instead of retrying a + request that cannot succeed. + """ + code = getattr(err, "code", None) + retryable = code in _RETRYABLE_HTTP_STATUS + return ApplicationError( + str(err), + type=type(err).__name__, + non_retryable=not retryable, + ) + + +async def _drain_interaction_stream( + stream: Any, +) -> _GeminiInteractionStreamedResponse: + """Collect every SSE event from an interaction stream, heartbeating per event. + + ``stream`` is the SDK's async streaming response; its concrete class is not a + stable public name, so it is typed structurally — only ``async with`` / + ``async for`` / ``event.model_dump(...)`` are used. + """ + events: list[dict[str, Any]] = [] + async with stream: + async for event in stream: + activity.heartbeat() + events.append( + event.model_dump(by_alias=True, exclude_none=True, mode="json") + ) + return _GeminiInteractionStreamedResponse(events=events) + + +class GeminiApiCaller: + """Wraps a ``genai.Client`` and exposes Temporal activities for SDK calls. + + The caller owns a reference to the user-provided ``genai.Client``. + All credential management, HTTP client configuration, etc. is the + responsibility of whoever constructs the client. + """ + + def __init__( + self, + client: GeminiClient, + credentials: google.auth.credentials.Credentials | None = None, + ) -> None: + """Initialize with a genai.Client and optional extra credentials.""" + self._client = client + self._credentials = credentials + + def activities(self) -> Sequence[Callable]: + """Return activities that route SDK calls through this client.""" + + @activity.defn + async def gemini_api_client_async_request( + req: _GeminiApiRequest, + ) -> _GeminiApiResponse: + """Execute a Gemini SDK API call with real credentials.""" + try: + response: SdkHttpResponse = ( + await self._client.aio._api_client.async_request( + http_method=req.http_method, + path=req.path, + request_dict=req.request_dict, + http_options=_resolve_http_options(req.http_options_overrides), + ) + ) + except genai_errors.APIError as err: + raise _classify_api_error(err) from err + return _GeminiApiResponse( + headers=response.headers or {}, + body=response.body or "", + ) + + @activity.defn + async def gemini_api_client_async_request_streamed( + req: _GeminiApiRequest, + ) -> _GeminiApiStreamedResponse: + """Execute a streamed Gemini SDK API call, collecting all chunks. + + When ``req.streaming_topic`` is set, each chunk is also published to + that workflow-stream topic (parsed as ``GenerateContentResponse``) + as it arrives, so external consumers see the model output in real + time. Chunks are still returned batched for the SDK to parse + in-workflow; publishing is best-effort and never breaks that path. + """ + chunks: list[_GeminiApiResponse] = [] + try: + async with AsyncExitStack() as stack: + topic = None + if req.streaming_topic: + publisher = WorkflowStreamClient.from_within_activity( + batch_interval=timedelta( + milliseconds=req.streaming_batch_interval_ms + ), + ) + await stack.enter_async_context(publisher) + topic = publisher.topic( + req.streaming_topic, type=types.GenerateContentResponse + ) + + stream = await self._client.aio._api_client.async_request_streamed( + http_method=req.http_method, + path=req.path, + request_dict=req.request_dict, + http_options=_resolve_http_options(req.http_options_overrides), + ) + async for chunk in stream: + body = chunk.body or "" + chunks.append( + _GeminiApiResponse(headers=chunk.headers or {}, body=body) + ) + if topic is not None and body: + try: + topic.publish( + types.GenerateContentResponse.model_validate_json( + body + ) + ) + except Exception: + # Best-effort: a malformed/transform-needing chunk + # must not break the batched return. + pass + except genai_errors.APIError as err: + raise _classify_api_error(err) from err + return _GeminiApiStreamedResponse(chunks=chunks) + + @activity.defn + async def gemini_files_upload( + req: _GeminiUploadFileRequest, + ) -> types.File: + """Upload a file using the real genai.Client on the worker.""" + if req.file_bytes is not None: + import io + + file_arg: Any = io.BytesIO(req.file_bytes) + else: + file_arg = req.file_path + + return await self._client.aio.files.upload(file=file_arg, config=req.config) + + @activity.defn + async def gemini_files_download( + req: _GeminiDownloadFileRequest, + ) -> bytes: + """Download a file using the real genai.Client on the worker.""" + return await self._client.aio.files.download( + file=req.file, config=req.config + ) + + @activity.defn + async def gemini_files_register( + req: _GeminiRegisterFilesRequest, + ) -> types.RegisterFilesResponse: + """Register GCS files using the real genai.Client on the worker. + + Uses ``credentials`` if provided at plugin init, + otherwise falls back to the client's own credentials. + Token refresh happens here on the worker side, so no auth + material enters the workflow event history. + """ + auth = self._credentials or self._client._api_client._credentials + if auth is None: + raise ValueError( + "No credentials available for register_files(). " + "Pass extra_credentials to GoogleGenAIPlugin or initialize " + "the genai.Client with credentials." + ) + return await self._client.aio.files.register_files( + auth=auth, + uris=req.uris, + config=req.config, + ) + + @activity.defn + async def gemini_file_search_stores_upload( + req: _GeminiUploadToFileSearchStoreRequest, + ) -> types.UploadToFileSearchStoreOperation: + """Upload a file to a file search store on the worker.""" + if req.file_bytes is not None: + import io + + file_arg: Any = io.BytesIO(req.file_bytes) + else: + file_arg = req.file_path + + return ( + await self._client.aio.file_search_stores.upload_to_file_search_store( + file_search_store_name=req.file_search_store_name, + file=file_arg, + config=req.config, + ) + ) + + @activity.defn + async def gemini_interactions_create( + req: _GeminiInteractionRequest, + ) -> dict[str, Any]: + """Create an interaction using the real genai.Client on the worker.""" + interaction = await self._client.aio.interactions.create(**req.params) + assert isinstance(interaction, Interaction) + return interaction.model_dump(by_alias=True, exclude_none=True, mode="json") + + @activity.defn + async def gemini_interactions_create_streamed( + req: _GeminiInteractionRequest, + ) -> _GeminiInteractionStreamedResponse: + """Create a streamed interaction, collecting all SSE events.""" + stream = await self._client.aio.interactions.create( + stream=True, **req.params + ) + assert not isinstance(stream, Interaction) + return await _drain_interaction_stream(stream) + + @activity.defn + async def gemini_interactions_get( + req: _GeminiInteractionIdRequest, + ) -> dict[str, Any]: + """Get an interaction using the real genai.Client on the worker.""" + interaction = await self._client.aio.interactions.get(req.id, **req.params) + return interaction.model_dump(by_alias=True, exclude_none=True, mode="json") + + @activity.defn + async def gemini_interactions_get_streamed( + req: _GeminiInteractionIdRequest, + ) -> _GeminiInteractionStreamedResponse: + """Get a streamed interaction, collecting all SSE events.""" + stream = await self._client.aio.interactions.get( + req.id, stream=True, **req.params + ) + assert not isinstance(stream, Interaction) + return await _drain_interaction_stream(stream) + + @activity.defn + async def gemini_interactions_delete( + req: _GeminiInteractionIdRequest, + ) -> Any: + """Delete an interaction using the real genai.Client on the worker.""" + return await self._client.aio.interactions.delete(req.id, **req.params) + + @activity.defn + async def gemini_interactions_cancel( + req: _GeminiInteractionIdRequest, + ) -> dict[str, Any]: + """Cancel an interaction using the real genai.Client on the worker.""" + interaction = await self._client.aio.interactions.cancel( + req.id, **req.params + ) + return interaction.model_dump(by_alias=True, exclude_none=True, mode="json") + + @activity.defn + async def gemini_agents_create( + req: _GeminiInteractionRequest, + ) -> dict[str, Any]: + """Create a managed agent using the real genai.Client on the worker.""" + agent = await self._client.aio.agents.create(**req.params) + return agent.model_dump(by_alias=True, exclude_none=True, mode="json") + + @activity.defn + async def gemini_agents_list( + req: _GeminiInteractionRequest, + ) -> dict[str, Any]: + """List managed agents using the real genai.Client on the worker.""" + response = await self._client.aio.agents.list(**req.params) + return response.model_dump(by_alias=True, exclude_none=True, mode="json") + + @activity.defn + async def gemini_agents_get( + req: _GeminiInteractionIdRequest, + ) -> dict[str, Any]: + """Get a managed agent using the real genai.Client on the worker.""" + agent = await self._client.aio.agents.get(req.id, **req.params) + return agent.model_dump(by_alias=True, exclude_none=True, mode="json") + + @activity.defn + async def gemini_agents_delete( + req: _GeminiInteractionIdRequest, + ) -> dict[str, Any]: + """Delete a managed agent using the real genai.Client on the worker.""" + response = await self._client.aio.agents.delete(req.id, **req.params) + return response.model_dump(by_alias=True, exclude_none=True, mode="json") + + return [ + gemini_api_client_async_request, + gemini_api_client_async_request_streamed, + gemini_files_upload, + gemini_files_download, + gemini_files_register, + gemini_file_search_stores_upload, + gemini_interactions_create, + gemini_interactions_create_streamed, + gemini_interactions_get, + gemini_interactions_get_streamed, + gemini_interactions_delete, + gemini_interactions_cancel, + gemini_agents_create, + gemini_agents_list, + gemini_agents_get, + gemini_agents_delete, + ] diff --git a/temporalio/contrib/google_genai/_google_genai_plugin.py b/temporalio/contrib/google_genai/_google_genai_plugin.py new file mode 100644 index 000000000..f7b65b769 --- /dev/null +++ b/temporalio/contrib/google_genai/_google_genai_plugin.py @@ -0,0 +1,158 @@ +"""Temporal plugin for Google Gemini SDK integration.""" + +from __future__ import annotations + +import dataclasses +from datetime import timedelta +from typing import TYPE_CHECKING + +import google.auth.credentials +from google.genai import Client as GeminiClient + +from temporalio.contrib.google_genai._errors import GoogleGenAIError +from temporalio.contrib.google_genai._gemini_activity import GeminiApiCaller +from temporalio.contrib.pydantic import PydanticPayloadConverter +from temporalio.converter import DataConverter, DefaultPayloadConverter +from temporalio.plugin import SimplePlugin +from temporalio.worker import WorkflowRunner +from temporalio.worker.workflow_sandbox import SandboxedWorkflowRunner + +if TYPE_CHECKING: + from temporalio.contrib.google_genai._mcp import McpSessionFactory + + +_RETRY_OPTIONS_MESSAGE = ( + "genai.Client is configured with http_options.retry_options, but Temporal " + "owns retries for durable execution. Remove retry_options from the client " + "and configure retries with the activity retry_policy instead — e.g. " + "TemporalAsyncClient(activity_config=ActivityConfig(retry_policy=...)) or " + "activity_as_tool(fn, activity_config=ActivityConfig(retry_policy=...))." +) + + +def _reject_sdk_retries(client: GeminiClient) -> None: + """Raise if the client enables the SDK's own retry loop. + + Temporal must own retries so each attempt is a separate, observable activity + attempt; an SDK-internal retry loop would hide retries inside one activity + and compound with Temporal's retry policy. + """ + http_options = getattr(client._api_client, "_http_options", None) + if http_options is not None and getattr(http_options, "retry_options", None): + raise ValueError(_RETRY_OPTIONS_MESSAGE) + + +def _data_converter(converter: DataConverter | None) -> DataConverter: + if converter is None: + return DataConverter(payload_converter_class=PydanticPayloadConverter) + elif converter.payload_converter_class is DefaultPayloadConverter: + return dataclasses.replace( + converter, payload_converter_class=PydanticPayloadConverter + ) + return converter + + +class GoogleGenAIPlugin(SimplePlugin): + """A Temporal Worker Plugin configured for the Google Gemini SDK. + + .. warning:: + This class is experimental and may change in future versions. + Use with caution in production environments. + + This plugin registers the ``gemini_api_client_async_request`` activity + using the provided ``genai.Client`` with real credentials. Workflows + construct a :class:`temporalio.contrib.google_genai.TemporalAsyncClient` + to get an ``AsyncClient`` backed by a ``TemporalApiClient`` that routes all + API calls through this activity. + + No credentials are passed to or from the workflow. Auth material never + appears in Temporal's event history. + + Example (Gemini Developer API):: + + client = genai.Client(api_key=os.environ["GOOGLE_API_KEY"]) + plugin = GoogleGenAIPlugin(client) + + Example (Vertex AI):: + + client = genai.Client( + vertexai=True, project="my-project", location="us-central1", + ) + plugin = GoogleGenAIPlugin(client) + + Example (with separate GCS credentials for file registration):: + + client = genai.Client(api_key=os.environ["GOOGLE_API_KEY"]) + gcs_creds, _ = google.auth.default() + plugin = GoogleGenAIPlugin(client, extra_credentials=gcs_creds) + """ + + def __init__( + self, + client: GeminiClient, + extra_credentials: google.auth.credentials.Credentials | None = None, + mcp_servers: dict[str, McpSessionFactory] | None = None, + mcp_connection_idle_timeout: timedelta | None = None, + ) -> None: + """Initialize the Gemini plugin. + + Args: + client: A fully configured ``genai.Client`` instance. + All credential management, HTTP client configuration, etc. + is the responsibility of the caller. + extra_credentials: Optional Google Cloud credentials used for + operations that require explicit auth (e.g. + ``files.register_files()``). If not provided, the + client's own credentials are used. + mcp_servers: MCP servers to expose to workflows, keyed by name. + Each value is a factory returning an async context manager that + yields a connected, initialized ``mcp.ClientSession``. A + workflow references a server by name with + ``TemporalMcpClientSession(name)`` in a ``generate_content`` + ``tools`` list; ``list_tools`` / ``call_tool`` then run as the + ``{name}-list-tools`` / ``{name}-call-tool`` activities against a + worker-side connection. Requires the ``mcp`` package. + mcp_connection_idle_timeout: How long a worker-process MCP + connection stays open while idle before being disconnected + (the timer resets on each reuse). Defaults to 5 minutes. + """ + _reject_sdk_retries(client) + self._api_caller = GeminiApiCaller(client, credentials=extra_credentials) + + activities = list(self._api_caller.activities()) + if mcp_servers: + # Imported lazily: ``mcp`` is an optional dependency, only needed + # when MCP servers are registered. + from temporalio.contrib.google_genai._mcp import build_mcp_activities + + activities.extend( + build_mcp_activities(mcp_servers, mcp_connection_idle_timeout) + ) + + def workflow_runner(runner: WorkflowRunner | None) -> WorkflowRunner: + if not runner: + raise ValueError("No WorkflowRunner provided to GoogleGenAIPlugin.") + if isinstance(runner, SandboxedWorkflowRunner): + return dataclasses.replace( + runner, + restrictions=runner.restrictions.with_passthrough_modules( + # The SDK's request formatting + AFC loop run in-workflow + # and validate google.genai's Pydantic models; mcp is + # imported to subclass ClientSession. pydantic itself is + # in the SDK default passthrough, but its compiled core + # and Annotated helper are not, so extend them. + "google.genai", + "mcp", + "pydantic_core", + "annotated_types", + ), + ) + return runner + + super().__init__( + name="google_genai.GoogleGenAIPlugin", + data_converter=_data_converter, + activities=activities, + workflow_runner=workflow_runner, + workflow_failure_exception_types=[GoogleGenAIError], + ) diff --git a/temporalio/contrib/google_genai/_mcp.py b/temporalio/contrib/google_genai/_mcp.py new file mode 100644 index 000000000..157ce458c --- /dev/null +++ b/temporalio/contrib/google_genai/_mcp.py @@ -0,0 +1,226 @@ +"""Worker-side MCP activities and a pooled-connection subsystem. + +The Gemini SDK's automatic-function-calling loop runs *inside* the workflow, +where it would otherwise call ``McpClientSession.list_tools`` / +``call_tool`` directly (network I/O — forbidden in a workflow). The +workflow-side ``TemporalMcpClientSession`` shim redirects those two methods to +the ``{server}-list-tools`` / ``{server}-call-tool`` activities defined here, +so the real ``mcp.ClientSession`` lives only on the worker. + +A single live session per server is held open in the worker process and reused +across activity invocations, with idle eviction — modeled on the strands +plugin's ``_temporal_mcp_client``. The MCP transport and ``ClientSession`` are +anyio context managers whose cancel scope is bound to the task that enters +them, so a dedicated owner task (``_ConnectionRecord._run``) holds them open for +the connection's lifetime while concurrent activities on the same event loop +call through the shared session. +""" + +from __future__ import annotations + +import asyncio +from collections.abc import Callable +from contextlib import AbstractAsyncContextManager +from datetime import timedelta + +from mcp import ClientSession +from mcp.types import CallToolResult, ListToolsResult + +from temporalio import activity +from temporalio.contrib.google_genai._models import _McpCallToolRequest + +# A factory yields a ready-to-use (connected and ``initialize()``-d) +# ``ClientSession`` as an async context manager. Mirrors the strands +# ``mcp_clients={name: factory}`` shape; the user writes a small +# ``@asynccontextmanager`` that enters the transport, opens the session, and +# initializes it before ``yield``. +McpSessionFactory = Callable[[], AbstractAsyncContextManager[ClientSession]] + +# Default time an idle MCP connection stays open before being disconnected. +# The timer resets on every call that reuses the connection. Override per +# worker via ``GoogleGenAIPlugin(mcp_connection_idle_timeout=...)``. +_MCP_CONNECTION_IDLE = timedelta(minutes=5) + +# Server name -> live connection held open in the activity worker process. +# Activities run in the worker process, so this module state is shared across +# activity invocations on the worker. +_CONNECTIONS: dict[str, _ConnectionRecord] = {} + + +class _ConnectionRecord: + """A single MCP session held open by a dedicated owner task. + + ``_run`` enters and exits the session's context manager in the same task + for the connection's whole lifetime; ``list_tools`` / ``call_tool`` + activities on the same event loop call through the shared session (MCP + multiplexes concurrent requests by id). + """ + + def __init__( + self, + server: str, + factory: McpSessionFactory, + idle_timeout: timedelta, + ) -> None: + loop = asyncio.get_running_loop() + self._server = server + self._idle_timeout = idle_timeout + self._stop = asyncio.Event() + self._ready: asyncio.Future[ClientSession] = loop.create_future() + self._idle_handle: asyncio.TimerHandle | None = None + self._inflight = 0 + self._owner = asyncio.create_task(self._run(factory)) + + async def _run(self, factory: McpSessionFactory) -> None: + try: + async with factory() as session: + self._ready.set_result(session) + await self._stop.wait() + except BaseException as err: + # A failed connect should not be cached; drop it so the next call + # retries instead of awaiting a permanently rejected future. + if not self._ready.done(): + self._ready.set_exception(err) + _CONNECTIONS.pop(self._server, None) + raise + + def acquire(self) -> None: + """Mark a call in flight; pause idle eviction while calls are active.""" + self._inflight += 1 + if self._idle_handle is not None: + self._idle_handle.cancel() + self._idle_handle = None + + def release(self) -> None: + """Mark a call done; arm idle eviction once no calls remain in flight.""" + self._inflight -= 1 + # Only the record still cached under this server arms a timer; a record + # already evicted or never cached must not schedule one, or it could + # later evict a different, healthy connection for the same server. + if self._inflight == 0 and _CONNECTIONS.get(self._server) is self: + loop = asyncio.get_running_loop() + self._idle_handle = loop.call_later( + self._idle_timeout.total_seconds(), self._on_idle + ) + + def _on_idle(self) -> None: + asyncio.ensure_future(self._maybe_evict()) + + async def _maybe_evict(self) -> None: + # A call may have acquired the connection between the timer firing and + # this task running; only evict if it is still idle. + if self._inflight == 0: + await _evict_connection(self._server) + + async def aclose(self) -> None: + """Signal the owner task to exit its context manager and wait for it.""" + if self._idle_handle is not None: + self._idle_handle.cancel() + self._idle_handle = None + self._stop.set() + try: + await self._owner + except BaseException: + pass + + async def session(self) -> ClientSession: + """Return the live session, or raise the connect failure.""" + return await self._ready + + +async def get_connection( + server: str, factory: McpSessionFactory, idle_timeout: timedelta +) -> tuple[ClientSession, _ConnectionRecord]: + """Return the cached session for ``server``, opening one lazily if needed. + + Concurrent first-callers dedupe onto a single connect handshake by awaiting + the same record. The returned record is acquired; the caller must + ``release()`` it once the call completes so idle eviction can resume. + """ + record = _CONNECTIONS.get(server) + if record is None: + record = _ConnectionRecord(server, factory, idle_timeout) + _CONNECTIONS[server] = record + record.acquire() + try: + session = await record.session() + except BaseException: + record.release() + raise + return session, record + + +async def _evict_connection(server: str) -> None: + record = _CONNECTIONS.pop(server, None) + if record is not None: + await record.aclose() + + +def build_list_tools_activity( + server: str, + factory: McpSessionFactory, + idle_timeout: timedelta | None = None, +) -> Callable: + """Return the per-server ``{server}-list-tools`` activity for registration. + + Reuses a lazily-opened, idle-evicted worker-process MCP session. Returns + the raw ``mcp.types.ListToolsResult`` so the workflow-side shim can hand it + to the Gemini SDK exactly as a live session would (preserving the full tool + parameter schema). + """ + idle = idle_timeout if idle_timeout is not None else _MCP_CONNECTION_IDLE + + @activity.defn(name=f"{server}-list-tools") + async def list_tools() -> ListToolsResult: + session, record = await get_connection(server, factory, idle) + try: + return await session.list_tools() + except Exception: + # The session may be broken; drop it so the next call reconnects. + await _evict_connection(server) + raise + finally: + record.release() + + return list_tools + + +def build_call_tool_activity( + server: str, + factory: McpSessionFactory, + idle_timeout: timedelta | None = None, +) -> Callable: + """Return the per-server ``{server}-call-tool`` activity for registration. + + Reuses the same lazily-opened, idle-evicted worker-process MCP session as + ``{server}-list-tools``. Returns the raw ``mcp.types.CallToolResult`` — + including tool-level error results (``isError=True``), which the model is + meant to see; only transport/protocol failures raise (and evict). + """ + idle = idle_timeout if idle_timeout is not None else _MCP_CONNECTION_IDLE + + @activity.defn(name=f"{server}-call-tool") + async def call_tool(req: _McpCallToolRequest) -> CallToolResult: + session, record = await get_connection(server, factory, idle) + try: + return await session.call_tool(name=req.name, arguments=req.arguments) + except Exception: + # The session may be broken; drop it so the next call reconnects. + await _evict_connection(server) + raise + finally: + record.release() + + return call_tool + + +def build_mcp_activities( + mcp_servers: dict[str, McpSessionFactory], + idle_timeout: timedelta | None = None, +) -> list[Callable]: + """Build the list-tools and call-tool activities for every registered server.""" + activities: list[Callable] = [] + for server, factory in mcp_servers.items(): + activities.append(build_list_tools_activity(server, factory, idle_timeout)) + activities.append(build_call_tool_activity(server, factory, idle_timeout)) + return activities diff --git a/temporalio/contrib/google_genai/_models.py b/temporalio/contrib/google_genai/_models.py new file mode 100644 index 000000000..2f70d9b4d --- /dev/null +++ b/temporalio/contrib/google_genai/_models.py @@ -0,0 +1,172 @@ +"""Serializable Pydantic models for the Gemini SDK Temporal integration. + +These models cross the activity boundary — they're constructed on the +workflow side and deserialized on the activity side (or vice versa). +""" + +from __future__ import annotations + +from typing import Any + +from google.genai import types +from pydantic import BaseModel + +__all__ = [ + "_GeminiApiRequest", + "_GeminiApiResponse", + "_GeminiApiStreamedResponse", + "_GeminiDownloadFileRequest", + "_GeminiInteractionIdRequest", + "_GeminiInteractionRequest", + "_GeminiInteractionStreamedResponse", + "_GeminiRegisterFilesRequest", + "_GeminiUploadFileRequest", + "_GeminiUploadToFileSearchStoreRequest", + "_McpCallToolRequest", + "_SerializableHttpOptions", +] + + +class _SerializableHttpOptions(BaseModel): + """Per-request HTTP options that can be serialized across the activity boundary. + + Non-serializable fields (httpx_client, httpx_async_client, aiohttp_client, + client_args, async_client_args) must be configured at GoogleGenAIPlugin init. + + ``timeout`` is excluded because Temporal owns timeouts/retries — configure + via ``ActivityConfig`` instead. + """ + + base_url: str | None = None + base_url_resource_scope: str | None = None + api_version: str | None = None + headers: dict[str, str] | None = None + extra_body: dict[str, Any] | None = None + + +# ── async_request models ────────────────────────────────────────────────── + + +class _GeminiApiRequest(BaseModel): + """Serializable activity input for a Gemini SDK API call. + + ``streaming_topic`` / ``streaming_batch_interval_ms`` are only read by the + streamed activity: when a topic is set, each streamed chunk is published to + that workflow-stream topic as it arrives (in addition to being returned + batched), so external consumers can observe the model output in real time. + """ + + http_method: str + path: str + request_dict: dict[str, object] + http_options_overrides: _SerializableHttpOptions | None = None + streaming_topic: str | None = None + streaming_batch_interval_ms: int = 100 + + +class _GeminiApiResponse(BaseModel): + """Serializable activity output for a Gemini SDK API call.""" + + headers: dict[str, str] + body: str + + +class _GeminiApiStreamedResponse(BaseModel): + """Serializable activity output for a batched streamed API call. + + The activity collects all streamed chunks and returns them as a list. + The ``TemporalApiClient`` then yields them one at a time to the SDK. + """ + + chunks: list[_GeminiApiResponse] + + +# ── files upload/download models ────────────────────────────────────────── + + +class _GeminiUploadFileRequest(BaseModel): + """Serializable activity input for a file upload. + + For file path uploads the path is resolved on the worker. For + in-memory uploads the raw bytes are sent across the activity boundary. + """ + + file_bytes: bytes | None = None + file_path: str | None = None + config: types.UploadFileConfig | None = None + + +class _GeminiDownloadFileRequest(BaseModel): + """Serializable activity input for a file download.""" + + file: str + config: types.DownloadFileConfig | None = None + + +class _GeminiRegisterFilesRequest(BaseModel): + """Serializable activity input for registering GCS files.""" + + uris: list[str] + config: types.RegisterFilesConfig | None = None + + +class _GeminiUploadToFileSearchStoreRequest(BaseModel): + """Serializable activity input for uploading a file to a file search store.""" + + file_search_store_name: str + file_bytes: bytes | None = None + file_path: str | None = None + config: types.UploadToFileSearchStoreConfig | None = None + + +# ── interactions / agents models ────────────────────────────────────────── + + +class _GeminiInteractionRequest(BaseModel): + """Serializable activity input for interactions/agents calls without an id. + + ``params`` is the caller's kwargs forwarded verbatim to the real SDK + method on the worker — ``stream`` and ``timeout`` are popped by the + workflow-side shim before dispatch (``stream`` selects the activity, + ``timeout`` maps to the activity's ``start_to_close_timeout``). + """ + + params: dict[str, Any] = {} + + +class _GeminiInteractionIdRequest(BaseModel): + """Serializable activity input for id-addressed interactions/agents calls.""" + + id: str + params: dict[str, Any] = {} + + +class _GeminiInteractionStreamedResponse(BaseModel): + """Serializable activity output for a batched streamed interaction call. + + ``events`` is the verbatim sequence of ``InteractionSSEEvent`` objects + yielded by the SDK's stream, each serialized via + ``model_dump(exclude_none=True, mode="json")``. The workflow-side shim + rehydrates each entry with ``_temporal_interactions._deserialize`` so + workflow code iterates the same typed events it would get from the SDK + directly. + """ + + events: list[dict[str, Any]] = [] + + +# ── MCP models ───────────────────────────────────────────────────────────── + + +class _McpCallToolRequest(BaseModel): + """Serializable activity input for an MCP ``call_tool`` invocation. + + Carries the tool name and arguments the Gemini SDK's AFC loop selected; + the worker-side activity forwards them to the real ``mcp.ClientSession``. + The ``mcp.types.ListToolsResult`` / ``CallToolResult`` returned by the + activities are themselves Pydantic models, so they serialize directly via + the plugin's ``PydanticPayloadConverter`` and need no wrapper here. + """ + + name: str + arguments: dict[str, Any] = {} diff --git a/temporalio/contrib/google_genai/_temporal_agents.py b/temporalio/contrib/google_genai/_temporal_agents.py new file mode 100644 index 000000000..2aaac8f78 --- /dev/null +++ b/temporalio/contrib/google_genai/_temporal_agents.py @@ -0,0 +1,143 @@ +"""Temporal-aware agents resource shim. + +``TemporalAsyncAgents`` exposes the same surface as google-genai's +``AsyncClient.agents`` resource, but each operation is dispatched through a +Temporal activity holding the real ``genai.Client`` on the worker. Agents are +server-side managed agent definitions (created once, then referenced by id in +``interactions.create(agent=...)``); like the Interactions API, the resource +lives in the vendored Stainless client that bypasses ``BaseApiClient``, so each +operation is routed as a whole through an activity instead. + +The shim depends only on the public ``google.genai.interactions`` surface, not +on google-genai internals. +""" + +from __future__ import annotations + +from datetime import timedelta +from typing import Any, cast + +# These types are runtime-public (in ``google.genai.interactions.__all__``) but +# pyright's stubs don't mark them re-exported; the alternative it suggests is a +# private ``_gaos`` path, so suppress the false positive. +from google.genai.interactions import ( + Agent, # pyright: ignore[reportPrivateImportUsage] + AgentDeleteResponse, # pyright: ignore[reportPrivateImportUsage] + AgentListResponse, # pyright: ignore[reportPrivateImportUsage] +) + +from temporalio import workflow as temporal_workflow +from temporalio.contrib.google_genai._models import ( + _GeminiInteractionIdRequest, + _GeminiInteractionRequest, +) +from temporalio.contrib.google_genai._temporal_interactions import ( + _deserialize, + _pop_timeout, +) +from temporalio.workflow import ActivityConfig + + +class TemporalAsyncAgents: + """Agents resource shim that routes calls through activities. + + Methods accept the same keyword arguments as the real resource and + forward them verbatim — the SDK validates them on the worker side, so + a bad argument surfaces as an activity failure (retried per the + activity's retry policy) rather than a workflow-side error. + + ``with_raw_response`` / ``with_streaming_response`` are not supported + in workflows. + """ + + def __init__( + self, + activity_config: ActivityConfig | None = None, + ) -> None: + """Initialize with activity config for agent operation timeouts.""" + self._activity_config = ( + ActivityConfig(start_to_close_timeout=timedelta(seconds=60)) + if activity_config is None + else activity_config + ) + + def _config(self, summary: str, params: dict[str, Any]) -> ActivityConfig: + config: ActivityConfig = {**self._activity_config} + if "summary" not in config: + config["summary"] = summary + _pop_timeout(params, config) + return config + + async def create( + self, + **kwargs: Any, + ) -> Agent: + """Create a managed agent definition via a Temporal activity.""" + params = dict(kwargs) + config = self._config("agents.create", params) + raw = await temporal_workflow.execute_activity( + "gemini_agents_create", + _GeminiInteractionRequest(params=params), + result_type=dict[str, Any], + **config, + ) + return cast(Agent, _deserialize(raw, Agent)) + + async def list( + self, + **kwargs: Any, + ) -> AgentListResponse: + """List managed agent definitions via a Temporal activity.""" + params = dict(kwargs) + config = self._config("agents.list", params) + raw = await temporal_workflow.execute_activity( + "gemini_agents_list", + _GeminiInteractionRequest(params=params), + result_type=dict[str, Any], + **config, + ) + return cast(AgentListResponse, _deserialize(raw, AgentListResponse)) + + async def get( + self, + id: str, + **kwargs: Any, + ) -> Agent: + """Get a managed agent definition via a Temporal activity.""" + params = dict(kwargs) + config = self._config("agents.get", params) + raw = await temporal_workflow.execute_activity( + "gemini_agents_get", + _GeminiInteractionIdRequest(id=id, params=params), + result_type=dict[str, Any], + **config, + ) + return cast(Agent, _deserialize(raw, Agent)) + + async def delete( + self, + id: str, + **kwargs: Any, + ) -> AgentDeleteResponse: + """Delete a managed agent definition via a Temporal activity.""" + params = dict(kwargs) + config = self._config("agents.delete", params) + raw = await temporal_workflow.execute_activity( + "gemini_agents_delete", + _GeminiInteractionIdRequest(id=id, params=params), + result_type=dict[str, Any], + **config, + ) + return cast(AgentDeleteResponse, _deserialize(raw, AgentDeleteResponse)) + + @property + def with_raw_response(self) -> Any: + """Raise — raw responses are not available in workflows.""" + raise RuntimeError("with_raw_response is not supported in Temporal workflows.") + + @property + def with_streaming_response(self) -> Any: + """Raise — streaming responses are not available in workflows.""" + raise RuntimeError( + "with_streaming_response is not supported in Temporal workflows." + ) diff --git a/temporalio/contrib/google_genai/_temporal_api_client.py b/temporalio/contrib/google_genai/_temporal_api_client.py new file mode 100644 index 000000000..0763d6890 --- /dev/null +++ b/temporalio/contrib/google_genai/_temporal_api_client.py @@ -0,0 +1,319 @@ +"""Temporal-aware BaseApiClient that routes SDK calls through activities. + +This module provides ``_TemporalApiClient``, a ``BaseApiClient`` subclass +whose HTTP methods dispatch through Temporal activities instead of making +direct calls. The real ``genai.Client`` with real credentials only exists +on the worker side inside the activity. + +This ensures: + +- No credential fetching or refreshing happens in the workflow. +- No auth material (tokens, API keys) appears in Temporal event history. +- The SDK's AFC (automatic function calling) loop runs in the workflow, + so ``activity_as_tool()`` wrappers work naturally. +""" + +from __future__ import annotations + +from datetime import timedelta +from typing import Any + +from google.genai._api_client import BaseApiClient +from google.genai.types import HttpOptions, HttpOptionsOrDict +from google.genai.types import HttpResponse as SdkHttpResponse + +from temporalio import workflow as temporal_workflow +from temporalio.contrib.google_genai._errors import GoogleGenAIError +from temporalio.contrib.google_genai._models import ( + _GeminiApiRequest, + _GeminiApiResponse, + _GeminiApiStreamedResponse, + _SerializableHttpOptions, +) +from temporalio.contrib.workflow_streams._stream import _PUBLISH_SIGNAL +from temporalio.workflow import ActivityConfig + +# Fields on HttpOptions that cannot be serialized or should not be forwarded. +_REJECTED_HTTP_OPTION_FIELDS = frozenset( + { + "httpx_client", + "httpx_async_client", + "aiohttp_client", + "client_args", + "async_client_args", + } +) + + +def _validate_http_options(http_options: HttpOptions | None) -> None: + """Raise if http_options contains non-serializable fields.""" + if http_options is None: + return + bad_fields = [ + f + for f in _REJECTED_HTTP_OPTION_FIELDS + if getattr(http_options, f, None) is not None + ] + if bad_fields: + raise ValueError( + f"http_options cannot include {bad_fields}. " + f"Configure custom HTTP clients at GoogleGenAIPlugin init instead." + ) + + +class _TemporalApiClient(BaseApiClient): # pyright: ignore[reportUnusedClass] + """A ``BaseApiClient`` that routes all API calls through Temporal activities. + + This client is used on the workflow side. It does NOT initialize HTTP + clients, load credentials, or make any network calls. It only holds the + minimal configuration needed for the SDK's request formatting logic + (e.g., choosing between Vertex AI and ML Dev parameter transformations). + + All actual HTTP calls are dispatched via ``workflow.execute_activity``. + """ + + def __init__( # pyright: ignore[reportMissingSuperCall] + self, + *, + vertexai: bool = False, + project: str | None = None, + location: str | None = None, + activity_config: ActivityConfig | None = None, + streaming_topic: str | None = None, + streaming_batch_interval: timedelta = timedelta(milliseconds=100), + ) -> None: + """Initialize without calling super (no HTTP clients needed).""" + # Do NOT call super().__init__() — it creates HTTP clients, loads + # credentials, etc. We only set the properties the SDK's request + # formatting code accesses. + self.vertexai = vertexai + self.project = project + self.location = location + self.api_key: str | None = None + self.custom_base_url: str | None = None + + self._activity_config = ( + ActivityConfig(start_to_close_timeout=timedelta(seconds=60)) + if activity_config is None + else activity_config + ) + self._streaming_topic = streaming_topic + self._streaming_batch_interval = streaming_batch_interval + + def _verify_response(self, response_model: Any) -> None: + """No-op — matches the base implementation.""" + pass + + def close(self) -> None: + """No-op — no HTTP resources to close.""" + pass + + async def aclose(self) -> None: + """No-op — no HTTP resources to close.""" + pass + + def __del__(self) -> None: + """No-op — no HTTP resources to clean up.""" + pass + + @staticmethod + def _process_http_options( + http_options: HttpOptionsOrDict | None, + config: ActivityConfig, + ) -> _SerializableHttpOptions | None: + """Validate and extract serializable per-request HTTP options. + + Rejects non-serializable fields (custom HTTP clients), maps timeout + to the Temporal activity config, and returns the remaining options + for forwarding to the activity. + + Args: + http_options: Per-request options from the SDK call. + config: Mutable activity config dict — timeout is applied here. + + Returns: + Serializable options to forward, or None if nothing to forward. + """ + if http_options is None: + return None + + if isinstance(http_options, HttpOptions): + opts = http_options + else: + opts = HttpOptions.model_validate(http_options) + + _validate_http_options(opts) + + if opts.retry_options is not None: + raise GoogleGenAIError( + "Per-request http_options.retry_options is not supported in " + "Temporal workflows. Temporal owns retries; configure them with " + "the activity retry_policy via activity_config instead." + ) + + # timeout is owned by Temporal — apply it to the activity config + # rather than forwarding to the underlying HTTP client. + if opts.timeout is not None: + config["start_to_close_timeout"] = timedelta(milliseconds=opts.timeout) + + result = _SerializableHttpOptions( + base_url=opts.base_url, + base_url_resource_scope=( + opts.base_url_resource_scope.value + if opts.base_url_resource_scope + else None + ), + api_version=opts.api_version, + headers=opts.headers, + extra_body=opts.extra_body, + ) + # Only return if there are actual values set + if not result.model_dump(exclude_none=True): + return None + return result + + # ── Async (primary path for workflows) ────────────────────────────── + + async def async_request( + self, + http_method: str, + path: str, + request_dict: dict[str, object], + http_options: HttpOptionsOrDict | None = None, + ) -> SdkHttpResponse: + """Dispatch an async API request through a Temporal activity.""" + config: ActivityConfig = {**self._activity_config} + if "summary" not in config: + # Default summary is the API path (e.g. "models/gemini-2.5-flash:generateContent"). + config["summary"] = f"{http_method.upper()} {path}" + overrides = self._process_http_options(http_options, config) + + resp = await temporal_workflow.execute_activity( + "gemini_api_client_async_request", + _GeminiApiRequest( + http_method=http_method, + path=path, + request_dict=request_dict, + http_options_overrides=overrides, + ), + result_type=_GeminiApiResponse, + **config, + ) + return SdkHttpResponse(headers=resp.headers, body=resp.body) + + # ── Sync (not expected in async workflows, but raise clearly) ─────── + + def request( + self, + http_method: str, + path: str, + request_dict: dict[str, object], + http_options: HttpOptionsOrDict | None = None, + ) -> SdkHttpResponse: + """Raise — sync requests not supported in workflows.""" + raise RuntimeError( + "Synchronous requests are not supported in Temporal workflows. " + "Use TemporalAsyncClient instead." + ) + + def request_streamed( + self, + http_method: str, + path: str, + request_dict: dict[str, object], + http_options: HttpOptionsOrDict | None = None, + ) -> Any: + """Raise — sync streaming not supported in workflows.""" + raise RuntimeError( + "Synchronous streaming is not supported in Temporal workflows. " + "Use TemporalAsyncClient instead." + ) + + async def async_request_streamed( + self, + http_method: str, + path: str, + request_dict: dict[str, object], + http_options: HttpOptionsOrDict | None = None, + ) -> Any: + """Dispatch a streamed request, batching chunks in the activity. + + When a ``streaming_topic`` is configured, the activity also publishes + each chunk to that workflow-stream topic as it arrives; the workflow + must host a ``WorkflowStream`` to receive them. + """ + config: ActivityConfig = {**self._activity_config} + if "summary" not in config: + config["summary"] = f"{http_method.upper()} {path}" + overrides = self._process_http_options(http_options, config) + + if self._streaming_topic is not None: + self._require_workflow_stream() + + resp = await temporal_workflow.execute_activity( + "gemini_api_client_async_request_streamed", + _GeminiApiRequest( + http_method=http_method, + path=path, + request_dict=request_dict, + http_options_overrides=overrides, + streaming_topic=self._streaming_topic, + streaming_batch_interval_ms=int( + self._streaming_batch_interval.total_seconds() * 1000 + ), + ), + result_type=_GeminiApiStreamedResponse, + **config, + ) + + async def _yield_chunks(): + for chunk in resp.chunks: + yield SdkHttpResponse(headers=chunk.headers, body=chunk.body) + + return _yield_chunks() + + def _require_workflow_stream(self) -> None: + """Fail fast if streaming is configured but no WorkflowStream is hosted. + + Published chunks are delivered to the workflow's ``WorkflowStream`` via + a signal; without a registered handler the signals would be silently + dropped, so surface a clear error instead. + """ + if temporal_workflow.get_signal_handler(_PUBLISH_SIGNAL) is None: + raise GoogleGenAIError( + "streaming_topic is set but this workflow has no WorkflowStream. " + "Construct WorkflowStream() in the workflow's @workflow.init " + "(from temporalio.contrib.workflow_streams).", + non_retryable=True, + ) + + # ── File upload/download ───────────────────────────────────────────── + # File operations are handled at a higher level by TemporalAsyncFiles + # (in _temporal_files.py), which dispatches the entire upload/download + # as a Temporal activity using the real client on the worker side. + # These internal BaseApiClient methods are not called in that path, + # so we raise here to catch any unexpected direct usage. + + def upload_file(self, *args: Any, **kwargs: Any) -> Any: + """Raise — use client.files.upload() instead.""" + raise NotImplementedError( + "Use client.files.upload() instead of the internal upload_file() method." + ) + + async def async_upload_file(self, *args: Any, **kwargs: Any) -> Any: + """Raise — use client.files.upload() instead.""" + raise NotImplementedError( + "Use client.files.upload() instead of the internal async_upload_file() method." + ) + + def download_file(self, *args: Any, **kwargs: Any) -> Any: + """Raise — use client.files.download() instead.""" + raise NotImplementedError( + "Use client.files.download() instead of the internal download_file() method." + ) + + async def async_download_file(self, *args: Any, **kwargs: Any) -> Any: + """Raise — use client.files.download() instead.""" + raise NotImplementedError( + "Use client.files.download() instead of the internal async_download_file() method." + ) diff --git a/temporalio/contrib/google_genai/_temporal_async_client.py b/temporalio/contrib/google_genai/_temporal_async_client.py new file mode 100644 index 000000000..c77cd5cee --- /dev/null +++ b/temporalio/contrib/google_genai/_temporal_async_client.py @@ -0,0 +1,285 @@ +"""Temporal-aware ``AsyncClient``. + +``TemporalAsyncClient`` is an ``AsyncClient`` whose every Gemini API call runs +as a Temporal activity. It builds and wraps a private ``BaseApiClient`` that +dispatches HTTP through ``workflow.execute_activity`` instead of making network +calls, so the SDK's request-formatting code (including the AFC loop) runs in +the workflow while the real ``genai.Client`` with real credentials only exists +on the worker side inside the activity. + +Construct it from within a workflow:: + + client = TemporalAsyncClient(activity_config=...) + response = await client.models.generate_content(...) + +This ensures: + +- No credential fetching or refreshing happens in the workflow. +- No auth material (tokens, API keys) appears in Temporal event history. +- The SDK's AFC (automatic function calling) loop runs in the workflow, so + ``activity_as_tool()`` wrappers work naturally. + +``AsyncFiles`` and ``AsyncFileSearchStores`` are replaced with shims that run +upload/download as activities; ``interactions`` and ``agents`` — which bypass +``BaseApiClient`` via a vendored HTTP client — are likewise replaced with +activity-backed shims; ``webhooks`` is not supported in workflows and raises. + +Replay determinism +------------------ +The SDK's request-formatting and automatic-function-calling loop run *in the +workflow*, so they must be deterministic. A survey of ``google.genai`` found no +``time``/``uuid``/``random`` use on the ``generate_content``/AFC path; the SDK's +own non-deterministic code (HTTP retry backoff, the interactions/agents vendored +client, local tokenizer temp paths) runs only inside activities on the worker. +The SDK exposes no time/id provider hooks to override, and none are needed. + +The one in-workflow exception is ``batches.create`` on Vertex AI: when +``display_name``/``dest`` are omitted the SDK auto-generates them from a +timestamp + UUID (``_common.timestamped_unique_name``), which is not +replay-safe. Pass explicit ``display_name`` and ``dest`` when creating Vertex +batch jobs from a workflow. +""" + +from __future__ import annotations + +import functools +import inspect +from collections.abc import AsyncIterator, Callable +from datetime import timedelta +from typing import Any, NoReturn, cast + +from google.genai import types +from google.genai.client import AsyncClient +from google.genai.models import AsyncModels + +from temporalio.contrib.google_genai._temporal_agents import ( + TemporalAsyncAgents, +) +from temporalio.contrib.google_genai._temporal_api_client import ( + _TemporalApiClient, +) +from temporalio.contrib.google_genai._temporal_file_search_stores import ( + TemporalAsyncFileSearchStores, +) +from temporalio.contrib.google_genai._temporal_files import ( + TemporalAsyncFiles, +) +from temporalio.contrib.google_genai._temporal_interactions import ( + TemporalAsyncInteractions, +) +from temporalio.workflow import ActivityConfig + + +def _closure_if_bound_method(tool: object) -> object: + """Return a plain-function wrapper for a bound method, else ``tool`` as-is. + + google-genai >= 2.8.0 deep-copies the request config internally + (``config.model_copy(deep=True)``). ``copy.deepcopy`` clones a bound + method's ``__self__``, so a workflow-method tool would run against a throwaway + clone of the workflow instance and its in-workflow state mutation would be + lost. ``deepcopy`` leaves plain functions untouched, so wrapping the method + in a closure keeps the tool bound to the real instance. Plain functions and + ``activity_as_tool`` wrappers are already closures and pass through unchanged. + """ + if not inspect.ismethod(tool): + return tool + method: Callable = tool + if inspect.iscoroutinefunction(method): + + @functools.wraps(method) + async def async_wrapper(*args: object, **kwargs: object) -> object: + return await method(*args, **kwargs) + + return async_wrapper + + @functools.wraps(method) + def sync_wrapper(*args: object, **kwargs: object) -> object: + return method(*args, **kwargs) + + return sync_wrapper + + +def _wrap_bound_method_tools( + config: types.GenerateContentConfigOrDict | None, +) -> types.GenerateContentConfigOrDict | None: + """Closure-wrap any bound-method tools in ``config`` (see :func:`_closure_if_bound_method`). + + Returns ``config`` unchanged when it holds no bound-method tools; otherwise + returns a shallow copy with the tools list rewritten, so the caller's config + is never mutated. + """ + if not config: + return config + if isinstance(config, dict): + tools = config.get("tools") + if not tools or not any(inspect.ismethod(t) for t in tools): + return config + updated: Any = { + **config, + "tools": [_closure_if_bound_method(t) for t in tools], + } + return cast(types.GenerateContentConfigDict, updated) + if not config.tools or not any(inspect.ismethod(t) for t in config.tools): + return config + return config.model_copy( + update={"tools": [_closure_if_bound_method(t) for t in config.tools]} + ) + + +class _TemporalAsyncModels(AsyncModels): + """``AsyncModels`` that closure-wraps bound-method tools before each call. + + This shields workflow-method tools from google-genai's internal deep-copy of + the config (>= 2.8.0), which would otherwise clone the workflow instance and + silently drop the tool's in-workflow state mutations. + """ + + async def generate_content( # type: ignore[override] + self, + *, + model: str, + contents: types.ContentListUnion | types.ContentListUnionDict, + config: types.GenerateContentConfigOrDict | None = None, + ) -> types.GenerateContentResponse: + return await super().generate_content( + model=model, + contents=contents, + config=_wrap_bound_method_tools(config), + ) + + async def generate_content_stream( # type: ignore[override] + self, + *, + model: str, + contents: types.ContentListUnion | types.ContentListUnionDict, + config: types.GenerateContentConfigOrDict | None = None, + ) -> AsyncIterator[types.GenerateContentResponse]: + return await super().generate_content_stream( + model=model, + contents=contents, + config=_wrap_bound_method_tools(config), + ) + + +class TemporalAsyncClient(AsyncClient): + """An ``AsyncClient`` whose API calls run as Temporal activities. + + .. warning:: + This API is experimental and may change in future versions. + Use with caution in production environments. + + Builds a private ``BaseApiClient`` that dispatches HTTP calls through + ``workflow.execute_activity`` and wraps it, so the SDK's request-formatting + code (including the AFC loop) runs in the workflow while only the actual + API calls cross into activities. Credentials are never fetched or stored + in the workflow — the activity worker handles authentication independently. + + ``AsyncFiles`` and ``AsyncFileSearchStores`` are replaced with shims that + run upload/download as activities; ``interactions`` and ``agents`` — which + bypass ``BaseApiClient`` via a vendored HTTP client — are likewise replaced + with activity-backed shims; ``webhooks`` is not supported in workflows and + raises. Other modules (models, tunings, caches, batches, live, tokens, + operations) are inherited unchanged and work through the private api + client's activity-backed HTTP methods. + + Construct it from within a workflow ``run`` method: + + .. code-block:: python + + @workflow.defn + class MyWorkflow: + @workflow.run + async def run(self, query: str) -> str: + client = TemporalAsyncClient() + response = await client.models.generate_content( + model="gemini-2.0-flash", + contents=query, + config=GenerateContentConfig( + tools=[ + activity_as_tool( + my_tool, + activity_config=ActivityConfig( + start_to_close_timeout=timedelta(seconds=30), + ), + ), + ], + ), + ) + return response.text + """ + + def __init__( + self, + *, + vertexai: bool = False, + project: str | None = None, + location: str | None = None, + activity_config: ActivityConfig | None = None, + streaming_topic: str | None = None, + streaming_batch_interval: timedelta = timedelta(milliseconds=100), + ) -> None: + """Initialize a Temporal-aware client. + + Args: + vertexai: Whether to use Vertex AI API endpoints. Must match the + ``GoogleGenAIPlugin`` configuration on the worker side. + Defaults to ``False`` (Gemini Developer API). + project: Google Cloud project ID. Only needed when + ``vertexai=True`` and the SDK's request formatting requires it + (e.g., cache operations). + location: Google Cloud location. Same conditions as ``project``. + activity_config: Override the default activity configuration + (timeouts, retry policy, etc.) for Gemini API call activities. + When not provided, every operation (model calls, files, + interactions, managed agents) defaults to a 60-second + ``start_to_close_timeout`` and Temporal's default retry policy. + streaming_topic: When set, ``generate_content_stream`` publishes each + streamed ``GenerateContentResponse`` to this + :class:`temporalio.contrib.workflow_streams.WorkflowStream` + topic as it arrives, so external consumers can observe the model + output in real time. The workflow must construct a + ``WorkflowStream`` in ``@workflow.init``; otherwise the call + raises. The workflow's own stream iteration is unchanged. + streaming_batch_interval: How often the streaming activity flushes + published chunks to the workflow stream. Defaults to 100ms. + """ + api_client = _TemporalApiClient( + vertexai=vertexai, + project=project, + location=location, + activity_config=activity_config, + streaming_topic=streaming_topic, + streaming_batch_interval=streaming_batch_interval, + ) + super().__init__(api_client) + # Closure-wrap bound-method tools so google-genai's internal + # config deep-copy (>= 2.8.0) can't clone the workflow instance. + self._models = _TemporalAsyncModels(api_client) + self._files = TemporalAsyncFiles(api_client, activity_config) + self._file_search_stores = TemporalAsyncFileSearchStores( + api_client, activity_config + ) + self._temporal_interactions = TemporalAsyncInteractions(activity_config) + self._temporal_agents = TemporalAsyncAgents(activity_config) + + @property + def interactions( # type: ignore[override] + self, + ) -> TemporalAsyncInteractions: # pyright: ignore[reportIncompatibleMethodOverride] + """Temporal-aware interactions resource; operations run as activities.""" + return self._temporal_interactions + + @property + def agents( # type: ignore[override] + self, + ) -> TemporalAsyncAgents: # pyright: ignore[reportIncompatibleMethodOverride] + """Temporal-aware agents resource; operations run as activities.""" + return self._temporal_agents + + @property + def webhooks(self) -> NoReturn: # pyright: ignore[reportIncompatibleMethodOverride] + """Raise — webhooks are not supported in Temporal workflows.""" + raise RuntimeError( + "client.webhooks is not supported in Temporal workflows. " + "Manage webhooks outside the workflow with a regular genai.Client." + ) diff --git a/temporalio/contrib/google_genai/_temporal_file_search_stores.py b/temporalio/contrib/google_genai/_temporal_file_search_stores.py new file mode 100644 index 000000000..7b7e3bbc8 --- /dev/null +++ b/temporalio/contrib/google_genai/_temporal_file_search_stores.py @@ -0,0 +1,109 @@ +"""Temporal-aware AsyncFileSearchStores shim. + +``TemporalAsyncFileSearchStores`` is an ``AsyncFileSearchStores`` subclass +whose ``upload_to_file_search_store`` method dispatches through a Temporal +activity so the entire upload (including filesystem access and resumable +upload negotiation) runs on the activity worker. +""" + +from __future__ import annotations + +import io +import os +from datetime import timedelta + +from google.genai import types +from google.genai.file_search_stores import AsyncFileSearchStores + +from temporalio import workflow as temporal_workflow +from temporalio.contrib.google_genai._models import ( + _GeminiUploadToFileSearchStoreRequest, +) +from temporalio.contrib.google_genai._temporal_api_client import ( + _TemporalApiClient, + _validate_http_options, +) +from temporalio.workflow import ActivityConfig + + +class TemporalAsyncFileSearchStores(AsyncFileSearchStores): + """``AsyncFileSearchStores`` subclass that routes ``upload_to_file_search_store`` through an activity. + + The entire upload operation — including filesystem access, resumable + upload negotiation, and chunked transfer — runs inside a Temporal + activity on the worker. All other methods (``create``, ``get``, + ``delete``, ``list``, ``import_file``, ``documents``) are inherited + and already work through the ``_TemporalApiClient``'s ``async_request`` + activity. + """ + + def __init__( + self, + api_client: _TemporalApiClient, + activity_config: ActivityConfig | None = None, + ) -> None: + """Initialize with activity config for upload timeouts.""" + super().__init__(api_client) + self._activity_config = ( + ActivityConfig(start_to_close_timeout=timedelta(seconds=60)) + if activity_config is None + else activity_config + ) + + async def upload_to_file_search_store( + self, + *, + file_search_store_name: str, + file: str | os.PathLike[str] | io.IOBase, + config: types.UploadToFileSearchStoreConfigOrDict | None = None, + ) -> types.UploadToFileSearchStoreOperation: + """Upload a file to a file search store via a Temporal activity. + + Accepts a file path (resolved on the worker), ``os.PathLike``, or + an ``io.IOBase`` (bytes sent across the activity boundary). + """ + act_config: ActivityConfig = {**self._activity_config} + if "summary" not in act_config: + act_config["summary"] = "file_search_stores.upload" + + upload_config = None + if config is not None: + if isinstance(config, dict): + upload_config = types.UploadToFileSearchStoreConfig.model_validate( + config + ) + else: + upload_config = config + _validate_http_options(upload_config.http_options) + + if isinstance(file, io.IOBase): + file_bytes = file.read() + if not isinstance(file_bytes, bytes): + raise TypeError( + "file must be a binary stream when passing an io.IOBase; " + f"file.read() must return bytes (got {type(file_bytes).__name__})" + ) + req = _GeminiUploadToFileSearchStoreRequest( + file_search_store_name=file_search_store_name, + file_bytes=file_bytes, + config=upload_config, + ) + elif isinstance(file, str): + req = _GeminiUploadToFileSearchStoreRequest( + file_search_store_name=file_search_store_name, + file_path=file, + config=upload_config, + ) + else: + req = _GeminiUploadToFileSearchStoreRequest( + file_search_store_name=file_search_store_name, + file_path=file.__fspath__(), + config=upload_config, + ) + + return await temporal_workflow.execute_activity( + "gemini_file_search_stores_upload", + req, + result_type=types.UploadToFileSearchStoreOperation, + **act_config, + ) diff --git a/temporalio/contrib/google_genai/_temporal_files.py b/temporalio/contrib/google_genai/_temporal_files.py new file mode 100644 index 000000000..f785c00cb --- /dev/null +++ b/temporalio/contrib/google_genai/_temporal_files.py @@ -0,0 +1,169 @@ +"""Temporal-aware AsyncFiles shim. + +``TemporalAsyncFiles`` is an ``AsyncFiles`` subclass whose ``upload`` +and ``download`` methods dispatch through Temporal activities so the +entire file operation (including filesystem access) runs on the +activity worker. +""" + +from __future__ import annotations + +import io +import os +from datetime import timedelta +from typing import TYPE_CHECKING + +if TYPE_CHECKING: + import google.auth.credentials +from google.genai import types +from google.genai.files import AsyncFiles + +from temporalio import workflow as temporal_workflow +from temporalio.contrib.google_genai._models import ( + _GeminiDownloadFileRequest, + _GeminiRegisterFilesRequest, + _GeminiUploadFileRequest, +) +from temporalio.contrib.google_genai._temporal_api_client import ( + _TemporalApiClient, + _validate_http_options, +) +from temporalio.workflow import ActivityConfig + + +class TemporalAsyncFiles(AsyncFiles): + """``AsyncFiles`` subclass that routes ``upload`` and ``download`` through activities. + + The entire file operation — including filesystem access, resumable + upload negotiation, and chunked transfer — runs inside a Temporal + activity on the worker. ``get``, ``delete``, and ``list`` are + inherited from ``AsyncFiles`` and already work through the + ``_TemporalApiClient``'s ``async_request`` activity. + """ + + def __init__( + self, + api_client: _TemporalApiClient, + activity_config: ActivityConfig | None = None, + ) -> None: + """Initialize with activity config for file operation timeouts.""" + super().__init__(api_client) + self._activity_config = ( + ActivityConfig(start_to_close_timeout=timedelta(seconds=60)) + if activity_config is None + else activity_config + ) + + async def upload( + self, + *, + file: str | os.PathLike[str] | io.IOBase, + config: types.UploadFileConfigOrDict | None = None, + ) -> types.File: + """Upload a file via a Temporal activity. + + Accepts a file path (resolved on the worker), ``os.PathLike``, or + an ``io.IOBase`` (bytes sent across the activity boundary). + """ + act_config: ActivityConfig = {**self._activity_config} + if "summary" not in act_config: + act_config["summary"] = "files.upload" + + upload_config = None + if config is not None: + if isinstance(config, dict): + upload_config = types.UploadFileConfig.model_validate(config) + else: + upload_config = config + _validate_http_options(upload_config.http_options) + + if isinstance(file, io.IOBase): + file_bytes = file.read() + if not isinstance(file_bytes, bytes): + raise TypeError( + "file must be a binary stream when passing an io.IOBase; " + f"file.read() must return bytes (got {type(file_bytes).__name__})" + ) + req = _GeminiUploadFileRequest(file_bytes=file_bytes, config=upload_config) + elif isinstance(file, str): + req = _GeminiUploadFileRequest(file_path=file, config=upload_config) + else: + # os.PathLike — convert via __fspath__() to avoid importing os + req = _GeminiUploadFileRequest( + file_path=file.__fspath__(), config=upload_config + ) + + return await temporal_workflow.execute_activity( + "gemini_files_upload", + req, + result_type=types.File, + **act_config, + ) + + async def download( + self, + *, + file: str | types.File, + config: types.DownloadFileConfigOrDict | None = None, + ) -> bytes: + """Download a file via a Temporal activity.""" + act_config: ActivityConfig = {**self._activity_config} + if "summary" not in act_config: + act_config["summary"] = "files.download" + + download_config = None + if config is not None: + if isinstance(config, dict): + download_config = types.DownloadFileConfig.model_validate(config) + else: + download_config = config + _validate_http_options(download_config.http_options) + + if isinstance(file, types.File): + if not file.name: + raise ValueError("File object must have a name to download.") + file_name = file.name + else: + file_name = file + + return await temporal_workflow.execute_activity( + "gemini_files_download", + _GeminiDownloadFileRequest(file=file_name, config=download_config), + result_type=bytes, + **act_config, + ) + + async def register_files( + self, + *, + auth: google.auth.credentials.Credentials, + uris: list[str], + config: types.RegisterFilesConfigOrDict | None = None, + ) -> types.RegisterFilesResponse: + """Register GCS files via a Temporal activity. + + .. note:: + The ``auth`` parameter is **ignored**. The activity uses + ``credentials`` if provided to ``GoogleGenAIPlugin``, + otherwise falls back to the ``genai.Client``'s own credentials. + Either way, those credentials must have access to the GCS URIs + being registered. + """ + act_config: ActivityConfig = {**self._activity_config} + if "summary" not in act_config: + act_config["summary"] = "files.register_files" + + register_config = None + if config is not None: + if isinstance(config, dict): + register_config = types.RegisterFilesConfig.model_validate(config) + else: + register_config = config + _validate_http_options(register_config.http_options) + + return await temporal_workflow.execute_activity( + "gemini_files_register", + _GeminiRegisterFilesRequest(uris=uris, config=register_config), + result_type=types.RegisterFilesResponse, + **act_config, + ) diff --git a/temporalio/contrib/google_genai/_temporal_interactions.py b/temporalio/contrib/google_genai/_temporal_interactions.py new file mode 100644 index 000000000..b5eb2edc0 --- /dev/null +++ b/temporalio/contrib/google_genai/_temporal_interactions.py @@ -0,0 +1,257 @@ +"""Temporal-aware interactions resource shim. + +``TemporalAsyncInteractions`` exposes the same surface as google-genai's +``AsyncClient.interactions`` resource, but each operation is dispatched through +a Temporal activity holding the real ``genai.Client`` on the worker. The +Interactions API does not go through ``BaseApiClient`` — it uses a vendored, +Stainless-generated HTTP client that the ``TemporalApiClient`` shim never sees — +so each operation is routed as a whole through an activity instead. + +The shim depends only on the public ``google.genai.interactions`` surface (types +plus ``client.aio.interactions`` on the worker), not on google-genai internals, +so it is unaffected by regeneration of the vendored client. +""" + +from __future__ import annotations + +from collections.abc import AsyncIterator +from datetime import timedelta +from types import TracebackType +from typing import Any, cast + +import pydantic +from google.genai.interactions import Interaction, InteractionSSEEvent + +from temporalio import workflow as temporal_workflow +from temporalio.contrib.google_genai._models import ( + _GeminiInteractionIdRequest, + _GeminiInteractionRequest, + _GeminiInteractionStreamedResponse, +) +from temporalio.workflow import ActivityConfig + +_DEFAULT_INTERACTION_TIMEOUT = timedelta(seconds=60) + +# ``InteractionSSEEvent`` is a discriminated union (on ``event_type``); a +# ``TypeAdapter`` dispatches it — including nested unions such as a +# ``step.start`` event's ``step`` — leniently. +_SSE_EVENT_ADAPTER: pydantic.TypeAdapter[Any] = pydantic.TypeAdapter( + InteractionSSEEvent +) + + +def _deserialize(value: dict[str, Any], type_: Any) -> Any: + """Rehydrate a dict returned by an activity into its public genai model. + + ``InteractionSSEEvent`` is deserialized through its ``TypeAdapter``, which + dispatches the discriminated union (and nested unions) and tolerates the + sparse nested payloads the API legitimately emits (e.g. an + ``interaction.created`` event carrying an ``Interaction`` with just ``id`` + and ``object``). Plain models use ``model_validate``, which recurses nested + models (e.g. ``AgentListResponse.agents`` into ``Agent``) and resolves + aliases; the SDK's optional fields keep it tolerant of the minimal objects + the API returns. Both paths are pure functions, safe to run in the workflow + on every replay. + """ + if type_ is InteractionSSEEvent: + return _SSE_EVENT_ADAPTER.validate_python(value) + return type_.model_validate(value) + + +def _pop_timeout(params: dict[str, Any], config: ActivityConfig) -> None: + """Pop a per-call ``timeout`` kwarg and apply it to the activity config. + + The Interactions API expresses timeouts in seconds. Temporal owns + timeouts/retries, so the value maps to ``start_to_close_timeout`` + rather than being forwarded to the underlying HTTP client. + """ + timeout = params.pop("timeout", None) + if timeout is None: + return + if not isinstance(timeout, (int, float)) or isinstance(timeout, bool): + raise ValueError( + "timeout must be numeric seconds when calling the Interactions " + "API from a workflow; configure anything more granular via " + "activity_config instead." + ) + config["start_to_close_timeout"] = timedelta(seconds=timeout) + + +class _TemporalInteractionAsyncStream: + """Async stream over interaction events already drained in an activity. + + Presents the same ``async for`` / ``async with`` / ``close()`` surface as + the SDK's streaming response, but iterates an in-memory event list drained + inside the activity (there is no httpx response or client on the workflow + side), rehydrating each event back into its typed form on iteration. + """ + + def __init__( + self, + events: list[dict[str, Any]], + ) -> None: + self._events = events + + def __aiter__(self) -> AsyncIterator[InteractionSSEEvent]: + return self._iter() + + async def _iter(self) -> AsyncIterator[InteractionSSEEvent]: + for event in self._events: + yield cast(InteractionSSEEvent, _deserialize(event, InteractionSSEEvent)) + + async def __aenter__(self) -> _TemporalInteractionAsyncStream: + return self + + async def __aexit__( + self, + exc_type: type[BaseException] | None, + exc: BaseException | None, + exc_tb: TracebackType | None, + ) -> None: + pass + + async def close(self) -> None: + """No-op — the upstream stream was drained inside the activity.""" + pass + + +class TemporalAsyncInteractions: + """Interactions resource shim that routes calls through activities. + + Methods accept the same keyword arguments as the real resource and + forward them verbatim — the SDK validates them on the worker side, so + a bad argument surfaces as an activity failure (retried per the + activity's retry policy) rather than a workflow-side error. + + ``with_raw_response`` / ``with_streaming_response`` are not supported + in workflows. + """ + + def __init__( + self, + activity_config: ActivityConfig | None = None, + ) -> None: + """Initialize with activity config for interaction operation timeouts.""" + self._activity_config = ( + ActivityConfig(start_to_close_timeout=_DEFAULT_INTERACTION_TIMEOUT) + if activity_config is None + else activity_config + ) + + def _config(self, summary: str, params: dict[str, Any]) -> ActivityConfig: + config: ActivityConfig = {**self._activity_config} + if "summary" not in config: + config["summary"] = summary + _pop_timeout(params, config) + return config + + async def create( + self, + *, + stream: bool = False, + **kwargs: Any, + ) -> Interaction | _TemporalInteractionAsyncStream: + """Create an interaction via a Temporal activity. + + ``kwargs`` is forwarded verbatim to ``client.aio.interactions.create`` + on the worker. With ``stream=True`` the activity drains the SSE + stream and returns all events batched; the returned object supports + ``async for`` / ``async with`` like the SDK's streaming response. + """ + params = dict(kwargs) + config = self._config( + "interactions.create (stream)" if stream else "interactions.create", + params, + ) + req = _GeminiInteractionRequest(params=params) + if stream: + resp = await temporal_workflow.execute_activity( + "gemini_interactions_create_streamed", + req, + result_type=_GeminiInteractionStreamedResponse, + **config, + ) + return _TemporalInteractionAsyncStream(resp.events) + raw = await temporal_workflow.execute_activity( + "gemini_interactions_create", + req, + result_type=dict[str, Any], + **config, + ) + return cast(Interaction, _deserialize(raw, Interaction)) + + async def get( + self, + id: str, + *, + stream: bool = False, + **kwargs: Any, + ) -> Interaction | _TemporalInteractionAsyncStream: + """Get an interaction via a Temporal activity. + + Supports ``stream=True`` (with the SDK's ``last_event_id`` kwarg + for resumption); events come back batched like :meth:`create`. + """ + params = dict(kwargs) + config = self._config( + "interactions.get (stream)" if stream else "interactions.get", + params, + ) + req = _GeminiInteractionIdRequest(id=id, params=params) + if stream: + resp = await temporal_workflow.execute_activity( + "gemini_interactions_get_streamed", + req, + result_type=_GeminiInteractionStreamedResponse, + **config, + ) + return _TemporalInteractionAsyncStream(resp.events) + raw = await temporal_workflow.execute_activity( + "gemini_interactions_get", + req, + result_type=dict[str, Any], + **config, + ) + return cast(Interaction, _deserialize(raw, Interaction)) + + async def delete( + self, + id: str, + **kwargs: Any, + ) -> object: + """Delete an interaction via a Temporal activity.""" + params = dict(kwargs) + config = self._config("interactions.delete", params) + return await temporal_workflow.execute_activity( + "gemini_interactions_delete", + _GeminiInteractionIdRequest(id=id, params=params), + **config, + ) + + async def cancel( + self, + id: str, + **kwargs: Any, + ) -> Interaction: + """Cancel an interaction via a Temporal activity.""" + params = dict(kwargs) + config = self._config("interactions.cancel", params) + raw = await temporal_workflow.execute_activity( + "gemini_interactions_cancel", + _GeminiInteractionIdRequest(id=id, params=params), + result_type=dict[str, Any], + **config, + ) + return cast(Interaction, _deserialize(raw, Interaction)) + + @property + def with_raw_response(self) -> Any: + """Raise — raw responses are not available in workflows.""" + raise RuntimeError("with_raw_response is not supported in Temporal workflows.") + + @property + def with_streaming_response(self) -> Any: + """Raise — streaming responses are not available in workflows.""" + raise RuntimeError( + "with_streaming_response is not supported in Temporal workflows." + ) diff --git a/temporalio/contrib/google_genai/_temporal_mcp.py b/temporalio/contrib/google_genai/_temporal_mcp.py new file mode 100644 index 000000000..718c6aaa3 --- /dev/null +++ b/temporalio/contrib/google_genai/_temporal_mcp.py @@ -0,0 +1,116 @@ +"""Temporal-aware ``mcp.ClientSession`` shim. + +``TemporalMcpClientSession`` is an ``mcp.ClientSession`` subclass that the user +places in ``generate_content(config=GenerateContentConfig(tools=[...]))`` just +like a real MCP session. The Gemini SDK recognizes it via +``isinstance(tool, McpClientSession)`` and, inside ``generate_content`` (which +runs in the workflow), calls only two methods on it: ``list_tools()`` at tool +discovery and ``call_tool(name, arguments)`` in the automatic-function-calling +loop. Both are overridden here to dispatch to the ``{server}-list-tools`` / +``{server}-call-tool`` activities, so the real ``mcp.ClientSession`` lives only +on the worker (registered via ``GoogleGenAIPlugin(mcp_servers=...)``). + +This mirrors strands' ``TemporalMCPClient``: the handle carries only the server +name (which selects the worker-side factory) plus activity options; the +connection factory is never passed to the workflow or the root client. +""" + +from __future__ import annotations + +from datetime import timedelta +from typing import Any + +from mcp import ClientSession +from mcp.shared.session import ProgressFnT +from mcp.types import CallToolResult, ListToolsResult, PaginatedRequestParams + +from temporalio import workflow as temporal_workflow +from temporalio.contrib.google_genai._models import _McpCallToolRequest +from temporalio.workflow import ActivityConfig + +_DEFAULT_MCP_TIMEOUT = timedelta(seconds=60) + + +class TemporalMcpClientSession(ClientSession): + """``mcp.ClientSession`` whose tool discovery and calls run as activities. + + .. warning:: + This API is experimental and may change in future versions. + + Construct inside a workflow and pass it in the ``tools`` list of a + ``generate_content`` call. The matching server name must be registered on + the worker via ``GoogleGenAIPlugin(mcp_servers={name: factory})``. + + ``cache_tools`` controls how often tools are listed. When ``False`` (the + default) the ``{server}-list-tools`` activity runs each time the SDK + discovers tools (i.e. per ``generate_content`` call), so a server whose + tools changed mid-workflow is picked up. When ``True`` the first listing is + cached on this instance and reused for its lifetime (replay-safe in-workflow + state). + + Args: + server_name: Name selecting the worker-side factory; also the activity + prefix (``{server_name}-list-tools`` / ``{server_name}-call-tool``). + cache_tools: Cache the tool listing after the first call. + activity_config: Activity configuration (timeouts, retry policy, etc.) + for the MCP activities. Defaults to a 60-second + ``start_to_close_timeout``. + """ + + def __init__( # pyright: ignore[reportMissingSuperCall] + self, + server_name: str, + *, + cache_tools: bool = False, + activity_config: ActivityConfig | None = None, + ) -> None: + """Initialize without calling super (no real streams exist here).""" + self._server_name = server_name + self._cache_tools = cache_tools + self._cached_tools: ListToolsResult | None = None + self._activity_config: ActivityConfig = ( + ActivityConfig(start_to_close_timeout=_DEFAULT_MCP_TIMEOUT) + if activity_config is None + else activity_config + ) + + def _config(self, summary: str) -> ActivityConfig: + config: ActivityConfig = {**self._activity_config} + if "summary" not in config: + config["summary"] = summary + return config + + async def list_tools( # pyright: ignore[reportIncompatibleMethodOverride] + self, + cursor: str | None = None, + *, + params: PaginatedRequestParams | None = None, + ) -> ListToolsResult: + """List the server's tools via the ``{server}-list-tools`` activity.""" + if self._cache_tools and self._cached_tools is not None: + return self._cached_tools + result = await temporal_workflow.execute_activity( + f"{self._server_name}-list-tools", + result_type=ListToolsResult, + **self._config(f"mcp.{self._server_name}.list_tools"), + ) + if self._cache_tools: + self._cached_tools = result + return result + + async def call_tool( # pyright: ignore[reportIncompatibleMethodOverride] + self, + name: str, + arguments: dict[str, Any] | None = None, + read_timeout_seconds: timedelta | None = None, + progress_callback: ProgressFnT | None = None, + *, + meta: dict[str, Any] | None = None, + ) -> CallToolResult: + """Call a tool via the ``{server}-call-tool`` activity.""" + return await temporal_workflow.execute_activity( + f"{self._server_name}-call-tool", + _McpCallToolRequest(name=name, arguments=arguments or {}), + result_type=CallToolResult, + **self._config(f"mcp.{self._server_name}.call_tool:{name}"), + ) diff --git a/temporalio/contrib/google_genai/testing.py b/temporalio/contrib/google_genai/testing.py new file mode 100644 index 000000000..d7884c636 --- /dev/null +++ b/temporalio/contrib/google_genai/testing.py @@ -0,0 +1,151 @@ +"""Testing utilities for the Google Gemini SDK Temporal integration. + +These let you exercise workflows that use +:class:`temporalio.contrib.google_genai.TemporalAsyncClient` without making +real Gemini API calls. Script the model's responses with :func:`text_response` +/ :func:`function_call_response`, build a plugin with +:class:`GeminiTestServer`, and register it on your worker like the real +:class:`temporalio.contrib.google_genai.GoogleGenAIPlugin`. + +Example:: + + server = GeminiTestServer( + [ + function_call_response("get_weather", {"city": "Tokyo"}), + text_response("It's sunny in Tokyo."), + ] + ) + async with Worker( + client, + task_queue="test", + workflows=[MyAgentWorkflow], + activities=[get_weather], + plugins=[server.plugin()], + ): + ... + assert len(server.requests) == 2 # one per model turn +""" + +from __future__ import annotations + +import json +from collections.abc import Sequence +from typing import Any + +from google.genai import Client as GeminiClient +from google.genai.types import HttpResponse as SdkHttpResponse + +from temporalio.contrib.google_genai._google_genai_plugin import GoogleGenAIPlugin + +__all__ = [ + "GeminiTestServer", + "function_call_response", + "text_response", +] + + +def text_response(text: str) -> str: + """Build a ``generate_content`` response body with a single text part.""" + return json.dumps( + { + "candidates": [ + { + "content": {"role": "model", "parts": [{"text": text}]}, + "finishReason": "STOP", + } + ], + "usageMetadata": { + "promptTokenCount": 5, + "candidatesTokenCount": 10, + }, + } + ) + + +def function_call_response(name: str, args: dict[str, Any]) -> str: + """Build a ``generate_content`` response body with a single function call. + + The Gemini SDK's automatic function calling loop will invoke the matching + tool, then request another response — so pair each function-call response + with a following :func:`text_response` (or further calls). + """ + return json.dumps( + { + "candidates": [ + { + "content": { + "role": "model", + "parts": [{"functionCall": {"name": name, "args": args}}], + }, + "finishReason": "STOP", + } + ], + "usageMetadata": { + "promptTokenCount": 10, + "candidatesTokenCount": 15, + }, + } + ) + + +class GeminiTestServer: + """Scripts Gemini model responses so workflows run without real API calls. + + Pass canned response bodies built with :func:`text_response` / + :func:`function_call_response`. Each model call — including each turn of an + automatic-function-calling loop and each ``generate_content_stream`` call — + consumes the next response in order. Build a plugin with :meth:`plugin` + and register it on your worker; inspect :attr:`requests` afterwards to + assert exactly what the integration sent. + + Only model calls (``client.models``) are scripted. File, interaction, and + agent operations are not; mock those on a ``genai.Client`` directly if a + test needs them. + """ + + def __init__(self, responses: Sequence[str]) -> None: + """Initialize with the response bodies to serve, in order.""" + self._responses = list(responses) + self._index = 0 + self.requests: list[dict[str, Any]] = [] + + def _next(self) -> str: + idx = self._index + self._index += 1 + if idx >= len(self._responses): + raise AssertionError( + f"GeminiTestServer ran out of responses (call {idx + 1}, " + f"have {len(self._responses)}); script another response." + ) + return self._responses[idx] + + def plugin(self) -> GoogleGenAIPlugin: + """Return a :class:`GoogleGenAIPlugin` whose model calls serve the script. + + The real plugin activities run; only the underlying HTTP layer is + replaced, so request formatting and the AFC loop are exercised exactly + as in production. + """ + client = GeminiClient(api_key="fake-test-key") + + async def fake_async_request(*_args: Any, **kwargs: Any) -> SdkHttpResponse: + self.requests.append(dict(kwargs.get("request_dict") or {})) + return SdkHttpResponse( + headers={"content-type": "application/json"}, + body=self._next(), + ) + + async def fake_async_request_streamed(*_args: Any, **kwargs: Any) -> Any: + self.requests.append(dict(kwargs.get("request_dict") or {})) + body = self._next() + + async def _gen() -> Any: + yield SdkHttpResponse( + headers={"content-type": "application/json"}, body=body + ) + + return _gen() + + client._api_client.async_request = fake_async_request # type: ignore[assignment] + client._api_client.async_request_streamed = fake_async_request_streamed # type: ignore[assignment] + return GoogleGenAIPlugin(client) diff --git a/temporalio/contrib/google_genai/workflow.py b/temporalio/contrib/google_genai/workflow.py new file mode 100644 index 000000000..08e40f0c5 --- /dev/null +++ b/temporalio/contrib/google_genai/workflow.py @@ -0,0 +1,111 @@ +"""Workflow utilities for Google Gemini SDK integration with Temporal. + +This module provides utilities for using the Google Gemini SDK within Temporal +workflows. The key entry points are: + +- :func:`activity_as_tool` — converts a Temporal activity into a Gemini tool + callable for use with automatic function calling (AFC). +""" + +from __future__ import annotations + +import functools +import inspect +from collections.abc import Callable +from typing import Any + +from temporalio import activity +from temporalio import workflow as temporal_workflow +from temporalio.contrib.google_genai._errors import GoogleGenAIError +from temporalio.workflow import ActivityConfig + + +def activity_as_tool( + fn: Callable, + *, + activity_config: ActivityConfig | None = None, +) -> Callable: + """Convert a Temporal activity into a Gemini-compatible async tool callable. + + .. warning:: + This API is experimental and may change in future versions. + Use with caution in production environments. + + Returns an async callable with the same name, docstring, and type signature as + ``fn``. When Gemini's automatic function calling (AFC) invokes the returned + callable from within a Temporal workflow, the call is executed as a Temporal + activity via :func:`workflow.execute_activity`. Each tool invocation therefore + appears as a separate, durable entry in the workflow event history. + + Because AFC is left **enabled**, the Gemini SDK owns the agentic loop — no + manual ``while`` loop or ``run_agent()`` helper is required. Pass the returned + callable directly to ``GenerateContentConfig(tools=[...])``. + + Args: + fn: A Temporal activity function decorated with ``@activity.defn``. + activity_config: Configuration for the activity execution (timeouts, + retry policy, etc.). Must set ``start_to_close_timeout`` or + ``schedule_to_close_timeout`` — Temporal requires one, and there is + no default; otherwise the tool call raises when the activity is + invoked. + + Returns: + An async callable suitable for use as a Gemini tool. + + Raises: + GoogleGenAIError: If ``fn`` is not decorated with ``@activity.defn`` or + has no activity name. + """ + ret = activity._Definition.from_callable(fn) + if not ret: + raise GoogleGenAIError( + "Bare function without @activity.defn decorator is not supported", + "invalid_tool", + ) + if ret.name is None: + raise GoogleGenAIError( + "Activity must have a name to be used as a Gemini tool", + "invalid_tool", + ) + + config: ActivityConfig = {**(activity_config or {})} + if "summary" not in config: + config["summary"] = "tool_call" + + # For class-based activities the first parameter is 'self'. Partially apply + # it so that Gemini inspects only the user-facing parameters when building + # the function-call schema, while the worker resolves the real instance at + # execution time. + params = list(inspect.signature(fn).parameters.keys()) + schema_fn: Callable = fn + if params and params[0] == "self": + partial = functools.partial(fn, None) + setattr(partial, "__name__", fn.__name__) + partial.__annotations__ = getattr(fn, "__annotations__", {}) + setattr( + partial, + "__temporal_activity_definition", + getattr(fn, "__temporal_activity_definition", None), + ) + partial.__doc__ = fn.__doc__ + schema_fn = partial + + activity_name: str = ret.name + + async def wrapper(*args: Any, **kwargs: Any) -> Any: + sig = inspect.signature(schema_fn) + bound = sig.bind(*args, **kwargs) + bound.apply_defaults() + activity_args = list(bound.arguments.values()) + return await temporal_workflow.execute_activity( + activity_name, + args=activity_args, + **config, + ) + + wrapper.__name__ = schema_fn.__name__ # type: ignore + wrapper.__doc__ = schema_fn.__doc__ + setattr(wrapper, "__signature__", inspect.signature(schema_fn)) + wrapper.__annotations__ = getattr(schema_fn, "__annotations__", {}) + + return wrapper diff --git a/tests/contrib/google_adk_agents/test_google_adk_agents.py b/tests/contrib/google_adk_agents/test_google_adk_agents.py index 2bea29efd..64da07103 100644 --- a/tests/contrib/google_adk_agents/test_google_adk_agents.py +++ b/tests/contrib/google_adk_agents/test_google_adk_agents.py @@ -285,40 +285,60 @@ async def test_single_agent(client: Client, use_local_model: bool): class ResearchModel(TestModel): - def responses(self) -> list[LlmResponse]: - return [ - LlmResponse( - content=Content( - role="model", - parts=[ - Part( - function_call=FunctionCall( - args={"agent_name": "researcher"}, - name="transfer_to_agent", - ) + """Scripted coordinator -> researcher -> writer flow. + + Responses are keyed off which agent is calling (via its instruction text in + the request's system instruction) rather than deduped against conversation + history, since the ADK rewrites cross-agent history between versions (e.g. + 2.4 converts prior transfer calls into "For context:" text parts). + """ + + _responses_by_instruction = { + "You are a coordinator": LlmResponse( + content=Content( + role="model", + parts=[ + Part( + function_call=FunctionCall( + args={"agent_name": "researcher"}, + name="transfer_to_agent", ) - ], - ) - ), - LlmResponse( - content=Content( - role="model", - parts=[ - Part( - function_call=FunctionCall( - args={"agent_name": "writer"}, name="transfer_to_agent" - ) + ) + ], + ) + ), + "You are a researcher": LlmResponse( + content=Content( + role="model", + parts=[ + Part( + function_call=FunctionCall( + args={"agent_name": "writer"}, name="transfer_to_agent" ) - ], - ) - ), - LlmResponse( - content=Content( - role="model", - parts=[Part(text="haiku")], - ) - ), - ] + ) + ], + ) + ), + "You are a poet": LlmResponse( + content=Content( + role="model", + parts=[Part(text="haiku")], + ) + ), + } + + def responses(self) -> list[LlmResponse]: + return list(self._responses_by_instruction.values()) + + async def generate_content_async( + self, llm_request: LlmRequest, stream: bool = False + ) -> AsyncGenerator[LlmResponse, None]: + instruction = str(llm_request.config.system_instruction or "") + for phrase, response in self._responses_by_instruction.items(): + if phrase in instruction: + yield response + return + raise ValueError(f"No scripted response for instruction: {instruction!r}") @classmethod def supported_models(cls) -> list[str]: diff --git a/tests/contrib/google_genai/__init__.py b/tests/contrib/google_genai/__init__.py new file mode 100644 index 000000000..26a790b56 --- /dev/null +++ b/tests/contrib/google_genai/__init__.py @@ -0,0 +1 @@ +"""Tests for the `google-genai` SDK Temporal integration.""" diff --git a/tests/contrib/google_genai/echo_mcp_server.py b/tests/contrib/google_genai/echo_mcp_server.py new file mode 100644 index 000000000..a69ac7b22 --- /dev/null +++ b/tests/contrib/google_genai/echo_mcp_server.py @@ -0,0 +1,15 @@ +"""A minimal stdio MCP server used by the google_genai MCP tests.""" + +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/tests/contrib/google_genai/test_gemini.py b/tests/contrib/google_genai/test_gemini.py new file mode 100644 index 000000000..543ad648c --- /dev/null +++ b/tests/contrib/google_genai/test_gemini.py @@ -0,0 +1,2052 @@ +"""Integration tests for the Google Gemini SDK Temporal integration. + +Tests cover: +- Basic generate_content through workflow +- Tool calling via activity_as_tool (single arg, multi arg, class method) +- Workflow method as a plain tool (runs in-workflow, not as an activity) +- Tool failure propagation +- Multiple sequential tool calls with arg verification +- Batched streaming via generate_content_stream +- Per-request http_options propagation +- File upload (str path + io.BytesIO) and download via TemporalAsyncFiles +- File search store upload via TemporalAsyncFileSearchStores +- Multi-turn chat via client.chats +- TemporalAsyncClient wiring (files, file_search_stores) +- _TemporalApiClient edge cases (sync raises) +- activity_as_tool validation and metadata preservation +- TemporalAsyncClient configuration +- Interactions API (create, batched streaming, get, cancel, delete) +- Managed agents (create, get, list, delete); webhooks unsupported +""" + +import inspect +import io +import json +import uuid +from datetime import timedelta +from typing import Any, Callable, cast +from unittest.mock import AsyncMock, MagicMock + +import pytest +from google.genai import Client as GeminiClient +from google.genai import types +from google.genai.interactions import ( + Agent, # pyright: ignore[reportPrivateImportUsage] + Interaction, + InteractionSSEEvent, +) +from google.genai.types import HttpResponse as SdkHttpResponse + +from temporalio import activity, workflow +from temporalio.client import Client, WorkflowFailureError +from temporalio.common import RetryPolicy +from temporalio.contrib.google_genai import ( + GoogleGenAIError, + GoogleGenAIPlugin, + activity_as_tool, +) +from temporalio.contrib.google_genai._models import ( + _GeminiApiRequest, + _GeminiApiResponse, + _GeminiApiStreamedResponse, + _GeminiDownloadFileRequest, + _GeminiInteractionIdRequest, + _GeminiInteractionRequest, + _GeminiInteractionStreamedResponse, + _GeminiUploadFileRequest, + _GeminiUploadToFileSearchStoreRequest, +) +from temporalio.contrib.google_genai._temporal_api_client import ( + _TemporalApiClient, +) +from temporalio.contrib.google_genai._temporal_async_client import ( + TemporalAsyncClient, + _closure_if_bound_method, + _wrap_bound_method_tools, +) +from temporalio.contrib.google_genai._temporal_file_search_stores import ( + TemporalAsyncFileSearchStores, +) +from temporalio.contrib.google_genai._temporal_files import ( + TemporalAsyncFiles, +) +from temporalio.contrib.google_genai._temporal_interactions import _deserialize +from temporalio.exceptions import ApplicationError +from temporalio.worker import Replayer +from temporalio.workflow import ActivityConfig +from tests.helpers import new_worker + +# --------------------------------------------------------------------------- +# Mock response helpers +# --------------------------------------------------------------------------- + + +def make_text_response(text: str) -> str: + """Build a JSON body string for a simple text response.""" + return json.dumps( + { + "candidates": [ + { + "content": { + "role": "model", + "parts": [{"text": text}], + }, + "finishReason": "STOP", + } + ], + "usageMetadata": { + "promptTokenCount": 5, + "candidatesTokenCount": 10, + }, + } + ) + + +def make_function_call_response(fn_name: str, args: dict) -> str: + """Build a JSON body string for a function-call response.""" + return json.dumps( + { + "candidates": [ + { + "content": { + "role": "model", + "parts": [{"functionCall": {"name": fn_name, "args": args}}], + }, + "finishReason": "STOP", + } + ], + "usageMetadata": { + "promptTokenCount": 10, + "candidatesTokenCount": 15, + }, + } + ) + + +INTERACTION_ID = "interactions/test-123" + + +def make_interaction_dict(status: str = "completed") -> dict[str, Any]: + """Build a minimal Interaction dict as the API would return it.""" + return {"id": INTERACTION_ID, "object": "interaction", "status": status} + + +def make_interaction_sse_events() -> list[dict[str, Any]]: + """Build a small SSE event sequence for a streamed interaction. + + Includes a sparse ``interaction.created`` payload (just ``id`` and + ``object``) to exercise the lenient ``_deserialize`` rehydration. + """ + return [ + { + "event_type": "interaction.created", + "interaction": {"id": INTERACTION_ID, "object": "interaction"}, + }, + { + "event_type": "step.delta", + "index": 0, + "delta": {"type": "text", "text": "Hello "}, + }, + { + "event_type": "step.delta", + "index": 0, + "delta": {"type": "text", "text": "world"}, + }, + {"event_type": "interaction.completed", "interaction": make_interaction_dict()}, + ] + + +def make_agent_dict(agent_id: str = "test-agent") -> dict[str, Any]: + """Build a minimal managed-agent dict as the API would return it.""" + return {"id": agent_id, "system_instruction": "Be helpful."} + + +# --------------------------------------------------------------------------- +# Tool call tracker — records every tool invocation for assertion +# --------------------------------------------------------------------------- + + +class ToolCallTracker: + """Tracks tool invocations across activities and workflow methods. + + Each tool appends (name, args_dict) to ``calls`` so tests can assert + exactly which tools were called, in what order, with what arguments. + """ + + def __init__(self) -> None: + self.calls: list[tuple[str, dict]] = [] + + @activity.defn + async def get_weather(self, city: str) -> str: + """Get the weather for a given city.""" + self.calls.append(("get_weather", {"city": city})) + return f"Weather in {city}: Sunny, 20C" + + @activity.defn + async def get_weather_country(self, city: str, country: str) -> str: + """Get the weather for a given city in a country.""" + self.calls.append(("get_weather_country", {"city": city, "country": country})) + return f"Weather in {city}, {country}: Rainy, 15C" + + @activity.defn + async def get_weather_failure(self, city: str) -> str: + """Activity that always fails.""" + self.calls.append(("get_weather_failure", {"city": city})) + raise ApplicationError("Weather service unavailable", non_retryable=True) + + +# --------------------------------------------------------------------------- +# Test helper: tracking gemini_api_client_async_request activity +# --------------------------------------------------------------------------- + + +class GeminiApiCallTracker: + """A test replacement for the gemini_api_client activities. + + Records every ``_GeminiApiRequest`` received and returns canned + ``_GeminiApiResponse`` bodies in order. After the workflow completes, + inspect ``requests`` to verify exactly what the integration sent. + + For streamed requests, the mock response is split into per-line chunks + to simulate multiple streamed chunks. + + The real ``GoogleGenAIPlugin`` is still used for its data converter, sandbox + passthrough, and workflow runner configuration — only its activity + registration is suppressed so this tracker can take its place. + """ + + def __init__(self, mock_responses: list[str]) -> None: + self._mock_responses = mock_responses + self.requests: list[_GeminiApiRequest] = [] + self.file_upload_requests: list[_GeminiUploadFileRequest] = [] + self.file_download_requests: list[_GeminiDownloadFileRequest] = [] + self.file_search_store_upload_requests: list[ + _GeminiUploadToFileSearchStoreRequest + ] = [] + self.interaction_requests: list[_GeminiInteractionRequest] = [] + self.interaction_id_requests: list[_GeminiInteractionIdRequest] = [] + self._call_index = 0 + + def _next_response(self, req: _GeminiApiRequest) -> str: + self.requests.append(req) + idx = self._call_index + self._call_index += 1 + if idx >= len(self._mock_responses): + raise ApplicationError( + f"No more mock responses (called {idx + 1} times, " + f"have {len(self._mock_responses)})", + non_retryable=True, + ) + return self._mock_responses[idx] + + @activity.defn + async def gemini_api_client_async_request( + self, req: _GeminiApiRequest + ) -> _GeminiApiResponse: + return _GeminiApiResponse( + headers={"content-type": "application/json"}, + body=self._next_response(req), + ) + + @activity.defn + async def gemini_api_client_async_request_streamed( + self, req: _GeminiApiRequest + ) -> _GeminiApiStreamedResponse: + body = self._next_response(req) + # Split the response text into word-level chunks so tests can + # verify that multiple chunks are yielded back to the workflow. + parsed = json.loads(body) + full_text = ( + parsed.get("candidates", [{}])[0] + .get("content", {}) + .get("parts", [{}])[0] + .get("text", "") + ) + words = full_text.split() + chunks = [] + for word in words: + chunks.append( + _GeminiApiResponse( + headers={"content-type": "application/json"}, + body=make_text_response(word), + ) + ) + return _GeminiApiStreamedResponse(chunks=chunks) + + @activity.defn + async def gemini_files_upload(self, req: _GeminiUploadFileRequest) -> types.File: + self.file_upload_requests.append(req) + return types.File( + name="files/test-uploaded-file", + uri="https://fake.uri/files/test-uploaded-file", + size_bytes=len(req.file_bytes) if req.file_bytes else 0, + ) + + @activity.defn + async def gemini_files_download(self, req: _GeminiDownloadFileRequest) -> bytes: + self.file_download_requests.append(req) + return b"fake file content" + + @activity.defn + async def gemini_file_search_stores_upload( + self, req: _GeminiUploadToFileSearchStoreRequest + ) -> types.UploadToFileSearchStoreOperation: + self.file_search_store_upload_requests.append(req) + return types.UploadToFileSearchStoreOperation.model_construct( + name="operations/test-op", + ) + + @activity.defn + async def gemini_interactions_create( + self, req: _GeminiInteractionRequest + ) -> dict[str, Any]: + self.interaction_requests.append(req) + return make_interaction_dict() + + @activity.defn + async def gemini_interactions_create_streamed( + self, req: _GeminiInteractionRequest + ) -> _GeminiInteractionStreamedResponse: + self.interaction_requests.append(req) + return _GeminiInteractionStreamedResponse(events=make_interaction_sse_events()) + + @activity.defn + async def gemini_interactions_get( + self, req: _GeminiInteractionIdRequest + ) -> dict[str, Any]: + self.interaction_id_requests.append(req) + return make_interaction_dict() + + @activity.defn + async def gemini_interactions_get_streamed( + self, req: _GeminiInteractionIdRequest + ) -> _GeminiInteractionStreamedResponse: + self.interaction_id_requests.append(req) + return _GeminiInteractionStreamedResponse(events=make_interaction_sse_events()) + + @activity.defn + async def gemini_interactions_delete(self, req: _GeminiInteractionIdRequest) -> Any: + self.interaction_id_requests.append(req) + return {"deleted": True} + + @activity.defn + async def gemini_interactions_cancel( + self, req: _GeminiInteractionIdRequest + ) -> dict[str, Any]: + self.interaction_id_requests.append(req) + return make_interaction_dict(status="cancelled") + + @activity.defn + async def gemini_agents_create( + self, req: _GeminiInteractionRequest + ) -> dict[str, Any]: + self.interaction_requests.append(req) + return make_agent_dict(req.params.get("id", "test-agent")) + + @activity.defn + async def gemini_agents_list( + self, req: _GeminiInteractionRequest + ) -> dict[str, Any]: + self.interaction_requests.append(req) + return {"agents": [make_agent_dict()], "next_page_token": "next-tok"} + + @activity.defn + async def gemini_agents_get( + self, req: _GeminiInteractionIdRequest + ) -> dict[str, Any]: + self.interaction_id_requests.append(req) + return make_agent_dict(req.id) + + @activity.defn + async def gemini_agents_delete( + self, req: _GeminiInteractionIdRequest + ) -> dict[str, Any]: + self.interaction_id_requests.append(req) + return {"id": req.id, "deleted": True} + + +def apply_plugin( + client: Client, mock_responses: list[str] +) -> tuple[Client, GeminiApiCallTracker]: + """Create a real GoogleGenAIPlugin whose activities include a tracking fake. + + Monkey-patches ``GeminiApiCaller.activities`` so that when the plugin + constructs itself, it registers our tracking activity instead of + the real ones. Everything else — data converter, sandbox passthrough, + workflow runner — is the real plugin code. + + Returns the configured Temporal client and the tracker. + """ + from temporalio.contrib.google_genai._gemini_activity import GeminiApiCaller + + tracker = GeminiApiCallTracker(mock_responses) + original_activities = GeminiApiCaller.activities + GeminiApiCaller.activities = lambda self: [ # type: ignore[method-assign] + tracker.gemini_api_client_async_request, + tracker.gemini_api_client_async_request_streamed, + tracker.gemini_files_upload, + tracker.gemini_files_download, + tracker.gemini_file_search_stores_upload, + tracker.gemini_interactions_create, + tracker.gemini_interactions_create_streamed, + tracker.gemini_interactions_get, + tracker.gemini_interactions_get_streamed, + tracker.gemini_interactions_delete, + tracker.gemini_interactions_cancel, + tracker.gemini_agents_create, + tracker.gemini_agents_list, + tracker.gemini_agents_get, + tracker.gemini_agents_delete, + ] + try: + gemini = GeminiClient(api_key="fake-test-key") + plugin = GoogleGenAIPlugin(gemini) + finally: + GeminiApiCaller.activities = original_activities # type: ignore[method-assign] + + config = client.config() + config["plugins"] = [plugin] + return Client(**config), tracker + + +# --------------------------------------------------------------------------- +# Workflows +# --------------------------------------------------------------------------- + + +@workflow.defn +class SimpleGenerateWorkflow: + """Workflow that does a simple generate_content call.""" + + @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 "" + + +@workflow.defn +class SingleArgToolWorkflow: + """Workflow that uses activity_as_tool for a single-arg tool.""" + + @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( + ToolCallTracker.get_weather, + activity_config=ActivityConfig( + start_to_close_timeout=timedelta(seconds=10), + ), + ), + ], + ), + ) + return response.text or "" + + +@workflow.defn +class MultiArgToolWorkflow: + """Workflow with multi-arg tool.""" + + @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( + ToolCallTracker.get_weather_country, + activity_config=ActivityConfig( + start_to_close_timeout=timedelta(seconds=10), + ), + ), + ], + ), + ) + return response.text or "" + + +@workflow.defn +class ToolFailureWorkflow: + """Workflow with a tool that always fails.""" + + @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( + ToolCallTracker.get_weather_failure, + activity_config=ActivityConfig( + start_to_close_timeout=timedelta(seconds=10), + retry_policy=RetryPolicy(maximum_attempts=1), + ), + ), + ], + ), + ) + return response.text or "" + + +@workflow.defn +class MultipleToolsWorkflow: + """Workflow with multiple tools that are called in sequence.""" + + @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( + ToolCallTracker.get_weather, + activity_config=ActivityConfig( + start_to_close_timeout=timedelta(seconds=10), + ), + ), + activity_as_tool( + ToolCallTracker.get_weather_country, + activity_config=ActivityConfig( + start_to_close_timeout=timedelta(seconds=10), + ), + ), + ], + ), + ) + return response.text or "" + + +@workflow.defn +class WorkflowMethodToolWorkflow: + """Workflow that passes a plain method as a tool (runs in-workflow, not as an activity).""" + + def __init__(self) -> None: + self.tool_calls: list[tuple[str, dict]] = [] + + @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=[self.lookup_city], + ), + ) + return response.text or "" + + async def lookup_city(self, city: str) -> str: + """Look up info about a city.""" + self.tool_calls.append(("lookup_city", {"city": city})) + return f"{city} is a great place to visit" + + @workflow.query + def get_tool_calls(self) -> list[tuple[str, dict]]: + return self.tool_calls + + +@workflow.defn +class StreamedGenerateWorkflow: + """Workflow that uses generate_content_stream.""" + + @workflow.run + async def run(self, prompt: str) -> list[str]: + client = TemporalAsyncClient() + chunks: list[str] = [] + async for chunk in await client.models.generate_content_stream( + model="gemini-2.5-flash", + contents=prompt, + ): + if chunk.text: + chunks.append(chunk.text) + return chunks + + +@workflow.defn +class HttpOptionsWorkflow: + """Workflow that passes per-request http_options through generate_content.""" + + @workflow.run + async def run(self, prompt: str, http_options: types.HttpOptionsDict) -> str: + client = TemporalAsyncClient() + response = await client.models.generate_content( + model="gemini-2.5-flash", + contents=prompt, + config=types.GenerateContentConfig( + http_options=types.HttpOptions.model_validate(http_options), + ), + ) + return response.text or "" + + +@workflow.defn +class FullIntegrationWorkflow: + """Exercises every activity path in a single workflow run. + + Uses the real GoogleGenAIPlugin activities (not the tracker), so this + tests the actual activity implementations end-to-end with a mocked + genai.Client. + """ + + @workflow.run + async def run(self, prompt: str) -> dict[str, Any]: + client = TemporalAsyncClient() + results: dict[str, Any] = {} + + # 1. generate_content (async_request activity) + response = await client.models.generate_content( + model="gemini-2.5-flash", + contents=prompt, + ) + results["generate"] = response.text or "" + + # 2. generate_content_stream (async_request_streamed activity) + chunks: list[str] = [] + async for chunk in await client.models.generate_content_stream( + model="gemini-2.5-flash", + contents=prompt, + ): + if chunk.text: + chunks.append(chunk.text) + results["stream_chunks"] = chunks + + # 3. files.upload (gemini_files_upload activity) + uploaded = await client.files.upload( + file="/tmp/fake.txt", + config=types.UploadFileConfig(display_name="Integration Test"), + ) + results["upload_name"] = uploaded.name or "" + + # 4. files.download (gemini_files_download activity) + data = await client.files.download(file="files/some-file") + results["download"] = data.decode() if isinstance(data, bytes) else str(data) + + # 5. file_search_stores.upload_to_file_search_store activity + store_name = "fileSearchStores/test" + op = await client.file_search_stores.upload_to_file_search_store( + file_search_store_name=store_name, + file="/tmp/doc.txt", + ) + results["fss_upload_op"] = op.name or "" + + # 6. generate_content grounded with file_search tool (RAG query) + rag_response = await client.models.generate_content( + model="gemini-2.5-flash", + contents="What does the document say?", + config=types.GenerateContentConfig( + tools=[ + types.Tool( + file_search=types.FileSearch( + file_search_store_names=[store_name], + ), + ), + ], + ), + ) + results["rag"] = rag_response.text or "" + + # 7. Clean up the file search store + await client.file_search_stores.delete( + name=store_name, + config=types.DeleteFileSearchStoreConfig(force=True), + ) + results["store_deleted"] = True + + # 8. interactions.create (gemini_interactions_create activity) + interaction = await client.interactions.create( + model="gemini-2.5-flash", + input=prompt, + ) + assert isinstance(interaction, Interaction) + results["interaction_id"] = interaction.id + + # 9. interactions.create streamed (gemini_interactions_create_streamed) + stream = await client.interactions.create( + model="gemini-2.5-flash", + input=prompt, + stream=True, + ) + assert not isinstance(stream, Interaction) + event_types: list[str] = [] + async with stream: + async for event in stream: + event_types.append(event.event_type) + results["interaction_events"] = event_types + + # 10. agents.create (gemini_agents_create activity) + agent = await client.agents.create( + id="test-agent", + system_instruction="Be helpful.", + ) + results["agent_id"] = agent.id + + return results + + +@workflow.defn +class FileUploadStrWorkflow: + """Workflow that uploads a file via str path.""" + + @workflow.run + async def run(self, file_path: str) -> str: + client = TemporalAsyncClient() + uploaded = await client.files.upload( + file=file_path, + config=types.UploadFileConfig( + display_name="Test File", + mime_type="text/plain", + ), + ) + return uploaded.name or "" + + +@workflow.defn +class FileUploadBytesWorkflow: + """Workflow that uploads a file via io.BytesIO.""" + + @workflow.run + async def run(self, data: bytes) -> str: + client = TemporalAsyncClient() + uploaded = await client.files.upload( + file=io.BytesIO(data), + config=types.UploadFileConfig( + display_name="Bytes File", + mime_type="text/plain", + ), + ) + return uploaded.name or "" + + +@workflow.defn +class FileDownloadWorkflow: + """Workflow that downloads a file by name.""" + + @workflow.run + async def run(self, file_name: str) -> bytes: + client = TemporalAsyncClient() + return await client.files.download(file=file_name) + + +@workflow.defn +class FileSearchStoreUploadWorkflow: + """Workflow that uploads to a file search store.""" + + @workflow.run + async def run(self, store_name: str, file_path: str) -> str: + client = TemporalAsyncClient() + op = await client.file_search_stores.upload_to_file_search_store( + file_search_store_name=store_name, + file=file_path, + config=types.UploadToFileSearchStoreConfig( + display_name="Test Doc", + mime_type="text/plain", + ), + ) + return op.name or "" + + +@workflow.defn +class RegisterFilesWorkflow: + """Workflow that calls files.register_files.""" + + @workflow.run + async def run(self, uris: list[str]) -> str: + client = TemporalAsyncClient() + # auth arg is ignored by TemporalAsyncFiles — the activity uses + # credentials from GoogleGenAIPlugin init. We pass a dummy here; + # can't import google.auth.credentials in the sandbox so we + # use a sentinel that satisfies the type at runtime. + resp = await client.files.register_files( + auth=None, # type: ignore[arg-type] + uris=uris, + ) + return str(len(resp.files or [])) + + +@workflow.defn +class ChatWorkflow: + """Workflow that uses client.chats for multi-turn conversation.""" + + @workflow.run + async def run(self, prompt: str) -> list[str]: + client = TemporalAsyncClient() + chat = client.chats.create( + model="gemini-2.5-flash", + ) + r1 = await chat.send_message(prompt) + r2 = await chat.send_message("Follow up question") + return [r1.text or "", r2.text or ""] + + +@workflow.defn +class InteractionCreateWorkflow: + """Workflow that creates an interaction (non-streaming).""" + + @workflow.run + async def run(self, prompt: str) -> dict[str, Any]: + client = TemporalAsyncClient() + interaction = await client.interactions.create( + model="gemini-2.5-flash", + input=prompt, + timeout=120, + ) + assert isinstance(interaction, Interaction) + return {"id": interaction.id, "status": str(interaction.status)} + + +@workflow.defn +class InteractionStreamWorkflow: + """Workflow that creates a streamed interaction and collects event types.""" + + @workflow.run + async def run(self, prompt: str) -> list[str]: + client = TemporalAsyncClient() + stream = await client.interactions.create( + model="gemini-2.5-flash", + input=prompt, + stream=True, + ) + assert not isinstance(stream, Interaction) + event_types: list[str] = [] + async with stream: + async for event in stream: + event_types.append(event.event_type) + return event_types + + +@workflow.defn +class InteractionLifecycleWorkflow: + """Workflow that gets, cancels, and deletes an interaction.""" + + @workflow.run + async def run(self, interaction_id: str) -> dict[str, Any]: + client = TemporalAsyncClient() + got = await client.interactions.get(interaction_id) + assert isinstance(got, Interaction) + cancelled = await client.interactions.cancel(interaction_id) + deleted = await client.interactions.delete(interaction_id) + return { + "got_id": got.id, + "cancel_status": str(cancelled.status), + "deleted": deleted, + } + + +@workflow.defn +class AgentsWorkflow: + """Workflow that exercises managed-agent CRUD.""" + + @workflow.run + async def run(self) -> dict[str, Any]: + client = TemporalAsyncClient() + agent = await client.agents.create( + id="test-agent", + system_instruction="Be helpful.", + ) + got = await client.agents.get("test-agent") + listing = await client.agents.list(page_size=10) + deleted = await client.agents.delete("test-agent") + return { + "created_id": agent.id, + "got_id": got.id, + "listed_ids": [a.id for a in (listing.agents or [])], + "next_page_token": listing.next_page_token, + # AgentDeleteResponse defines no fields; the API's JSON comes + # back as extras, so return the dict form. + "delete_response": deleted.model_dump(mode="json"), + } + + +@workflow.defn +class WebhooksUnsupportedWorkflow: + """Workflow that verifies client.webhooks raises a clear error.""" + + @workflow.run + async def run(self) -> str: + client = TemporalAsyncClient() + try: + _ = client.webhooks + except RuntimeError as e: + return str(e) + return "no error" + + +# =========================================================================== +# Integration tests — run workflows against a real Temporal test server +# =========================================================================== + + +async def test_simple_generate_content(client: Client): + """Basic generate_content returns text through a workflow.""" + new_client, _ = apply_plugin(client, [make_text_response("Hello from Gemini!")]) + + async with new_worker(new_client, SimpleGenerateWorkflow) as worker: + result = await new_client.execute_workflow( + SimpleGenerateWorkflow.run, + "Say hello", + id=f"gemini-simple-{uuid.uuid4()}", + task_queue=worker.task_queue, + execution_timeout=timedelta(seconds=10), + ) + + assert result == "Hello from Gemini!" + + +async def test_tool_call_single_arg(client: Client): + """Tool calling with a single-argument activity via AFC.""" + tool_tracker = ToolCallTracker() + new_client, _ = apply_plugin( + client, + [ + make_function_call_response("get_weather", {"city": "Tokyo"}), + make_text_response("The weather in Tokyo is sunny and 20C."), + ], + ) + + async with new_worker( + new_client, + SingleArgToolWorkflow, + activities=[tool_tracker.get_weather], + ) as worker: + result = await new_client.execute_workflow( + SingleArgToolWorkflow.run, + "What's the weather in Tokyo?", + id=f"gemini-tool-single-{uuid.uuid4()}", + task_queue=worker.task_queue, + execution_timeout=timedelta(seconds=10), + ) + + assert tool_tracker.calls == [("get_weather", {"city": "Tokyo"})] + assert result == "The weather in Tokyo is sunny and 20C." + + +async def test_tool_call_multi_arg(client: Client): + """Tool calling with a multi-argument activity.""" + tool_tracker = ToolCallTracker() + new_client, _ = apply_plugin( + client, + [ + make_function_call_response( + "get_weather_country", {"city": "Paris", "country": "France"} + ), + make_text_response("Paris, France: Rainy, 15C."), + ], + ) + + async with new_worker( + new_client, + MultiArgToolWorkflow, + activities=[tool_tracker.get_weather_country], + ) as worker: + result = await new_client.execute_workflow( + MultiArgToolWorkflow.run, + "What's the weather in Paris, France?", + id=f"gemini-tool-multi-{uuid.uuid4()}", + task_queue=worker.task_queue, + execution_timeout=timedelta(seconds=10), + ) + + assert tool_tracker.calls == [ + ("get_weather_country", {"city": "Paris", "country": "France"}) + ] + assert result == "Paris, France: Rainy, 15C." + + +async def test_tool_failure_propagation(client: Client): + """Tool activity failure causes the workflow to fail.""" + tool_tracker = ToolCallTracker() + new_client, _ = apply_plugin( + client, + [ + make_function_call_response("get_weather_failure", {"city": "Nowhere"}), + ], + ) + + async with new_worker( + new_client, + ToolFailureWorkflow, + activities=[tool_tracker.get_weather_failure], + ) as worker: + with pytest.raises(WorkflowFailureError): + await new_client.execute_workflow( + ToolFailureWorkflow.run, + "Weather in Nowhere?", + id=f"gemini-tool-fail-{uuid.uuid4()}", + task_queue=worker.task_queue, + execution_timeout=timedelta(seconds=10), + ) + + assert tool_tracker.calls == [("get_weather_failure", {"city": "Nowhere"})] + + +async def test_multiple_tools_sequential(client: Client): + """Multiple tools called in sequence within one generate_content call.""" + tool_tracker = ToolCallTracker() + new_client, _ = apply_plugin( + client, + [ + make_function_call_response("get_weather", {"city": "Tokyo"}), + make_function_call_response( + "get_weather_country", {"city": "Paris", "country": "France"} + ), + make_text_response("Tokyo is sunny; Paris is rainy."), + ], + ) + + async with new_worker( + new_client, + MultipleToolsWorkflow, + activities=[ + tool_tracker.get_weather, + tool_tracker.get_weather_country, + ], + ) as worker: + result = await new_client.execute_workflow( + MultipleToolsWorkflow.run, + "Compare Tokyo and Paris weather", + id=f"gemini-multi-tools-{uuid.uuid4()}", + task_queue=worker.task_queue, + execution_timeout=timedelta(seconds=15), + ) + + assert tool_tracker.calls == [ + ("get_weather", {"city": "Tokyo"}), + ("get_weather_country", {"city": "Paris", "country": "France"}), + ] + assert result == "Tokyo is sunny; Paris is rainy." + + +async def test_workflow_method_as_tool(client: Client): + """A plain workflow method (not an activity) used as a tool runs in-workflow.""" + new_client, _ = apply_plugin( + client, + [ + make_function_call_response("lookup_city", {"city": "Berlin"}), + make_text_response("Berlin is wonderful."), + ], + ) + + async with new_worker(new_client, WorkflowMethodToolWorkflow) as worker: + handle = await new_client.start_workflow( + WorkflowMethodToolWorkflow.run, + "Tell me about Berlin", + id=f"gemini-wf-method-tool-{uuid.uuid4()}", + task_queue=worker.task_queue, + execution_timeout=timedelta(seconds=10), + ) + result = await handle.result() + # Query must happen while worker is alive + tool_calls = await handle.query(WorkflowMethodToolWorkflow.get_tool_calls) + + assert tool_calls == [("lookup_city", {"city": "Berlin"})] + assert result == "Berlin is wonderful." + + +async def test_streamed_generate_content(client: Client): + """generate_content_stream collects batched chunks from the activity.""" + new_client, _ = apply_plugin( + client, [make_text_response("The quick brown fox jumps over the lazy dog")] + ) + + async with new_worker(new_client, StreamedGenerateWorkflow) as worker: + result = await new_client.execute_workflow( + StreamedGenerateWorkflow.run, + "Say something", + id=f"gemini-streamed-{uuid.uuid4()}", + task_queue=worker.task_queue, + execution_timeout=timedelta(seconds=10), + ) + + # The tracker splits the text into per-word chunks + assert len(result) == 9 + assert " ".join(result) == "The quick brown fox jumps over the lazy dog" + + +# =========================================================================== +# http_options propagation tests - per request overrides +# =========================================================================== + + +async def test_http_options_headers_propagate(client: Client): + """Custom headers passed via http_options arrive at the activity.""" + new_client, api_tracker = apply_plugin(client, [make_text_response("ok")]) + + async with new_worker(new_client, HttpOptionsWorkflow) as worker: + await new_client.execute_workflow( + HttpOptionsWorkflow.run, + args=["hi", {"headers": {"X-Custom": "test-value"}}], + id=f"gemini-http-headers-{uuid.uuid4()}", + task_queue=worker.task_queue, + execution_timeout=timedelta(seconds=10), + ) + + assert len(api_tracker.requests) == 1 + opts = api_tracker.requests[0].http_options_overrides + assert opts is not None + assert opts.headers == {"X-Custom": "test-value"} + + +async def test_http_options_api_version_propagates(client: Client): + """api_version passed via http_options arrives at the activity.""" + new_client, api_tracker = apply_plugin(client, [make_text_response("ok")]) + + async with new_worker(new_client, HttpOptionsWorkflow) as worker: + await new_client.execute_workflow( + HttpOptionsWorkflow.run, + args=["hi", {"api_version": "v1"}], + id=f"gemini-http-version-{uuid.uuid4()}", + task_queue=worker.task_queue, + execution_timeout=timedelta(seconds=10), + ) + + assert len(api_tracker.requests) == 1 + opts = api_tracker.requests[0].http_options_overrides + assert opts is not None + assert opts.api_version == "v1" + + +async def test_http_options_base_url_propagates(client: Client): + """base_url passed via http_options arrives at the activity.""" + new_client, api_tracker = apply_plugin(client, [make_text_response("ok")]) + + async with new_worker(new_client, HttpOptionsWorkflow) as worker: + await new_client.execute_workflow( + HttpOptionsWorkflow.run, + args=["hi", {"base_url": "https://custom.example.com"}], + id=f"gemini-http-base-url-{uuid.uuid4()}", + task_queue=worker.task_queue, + execution_timeout=timedelta(seconds=10), + ) + + assert len(api_tracker.requests) == 1 + opts = api_tracker.requests[0].http_options_overrides + assert opts is not None + assert opts.base_url == "https://custom.example.com" + + +async def test_http_options_multiple_fields_propagate(client: Client): + """Multiple http_options fields propagate together to the activity.""" + new_client, api_tracker = apply_plugin(client, [make_text_response("ok")]) + + async with new_worker(new_client, HttpOptionsWorkflow) as worker: + await new_client.execute_workflow( + HttpOptionsWorkflow.run, + args=[ + "hi", + { + "api_version": "v1beta", + "headers": {"X-Foo": "bar"}, + "base_url": "https://other.example.com", + }, + ], + id=f"gemini-http-multi-{uuid.uuid4()}", + task_queue=worker.task_queue, + execution_timeout=timedelta(seconds=10), + ) + + assert len(api_tracker.requests) == 1 + opts = api_tracker.requests[0].http_options_overrides + assert opts is not None + assert opts.api_version == "v1beta" + assert opts.headers == {"X-Foo": "bar"} + assert opts.base_url == "https://other.example.com" + + +async def test_no_http_options_passes_none(client: Client): + """When no per-request http_options are set, None reaches the activity.""" + new_client, api_tracker = apply_plugin(client, [make_text_response("ok")]) + + async with new_worker(new_client, SimpleGenerateWorkflow) as worker: + await new_client.execute_workflow( + SimpleGenerateWorkflow.run, + "hi", + id=f"gemini-http-none-{uuid.uuid4()}", + task_queue=worker.task_queue, + execution_timeout=timedelta(seconds=10), + ) + + assert len(api_tracker.requests) == 1 + assert api_tracker.requests[0].http_options_overrides is None + + +# =========================================================================== +# File upload/download tests +# =========================================================================== + + +async def test_file_upload_str_path(client: Client): + """Upload a file via str path dispatches through the activity.""" + new_client, api_tracker = apply_plugin(client, []) + + async with new_worker(new_client, FileUploadStrWorkflow) as worker: + result = await new_client.execute_workflow( + FileUploadStrWorkflow.run, + "/tmp/test.txt", + id=f"gemini-file-upload-str-{uuid.uuid4()}", + task_queue=worker.task_queue, + execution_timeout=timedelta(seconds=10), + ) + + assert len(api_tracker.file_upload_requests) == 1 + req = api_tracker.file_upload_requests[0] + assert req.file_path == "/tmp/test.txt" + assert req.file_bytes is None + assert req.config is not None + assert req.config.display_name == "Test File" + assert result == "files/test-uploaded-file" + + +async def test_file_upload_bytes(client: Client): + """Upload a file via io.BytesIO sends bytes through the activity.""" + new_client, api_tracker = apply_plugin(client, []) + + async with new_worker(new_client, FileUploadBytesWorkflow) as worker: + result = await new_client.execute_workflow( + FileUploadBytesWorkflow.run, + b"hello world", + id=f"gemini-file-upload-bytes-{uuid.uuid4()}", + task_queue=worker.task_queue, + execution_timeout=timedelta(seconds=10), + ) + + assert len(api_tracker.file_upload_requests) == 1 + req = api_tracker.file_upload_requests[0] + assert req.file_bytes == b"hello world" + assert req.file_path is None + assert req.config is not None + assert req.config.display_name == "Bytes File" + assert result == "files/test-uploaded-file" + + +async def test_file_download(client: Client): + """Download a file dispatches through the activity and returns bytes.""" + new_client, api_tracker = apply_plugin(client, []) + + async with new_worker(new_client, FileDownloadWorkflow) as worker: + result = await new_client.execute_workflow( + FileDownloadWorkflow.run, + "files/some-file", + id=f"gemini-file-download-{uuid.uuid4()}", + task_queue=worker.task_queue, + execution_timeout=timedelta(seconds=10), + ) + + assert len(api_tracker.file_download_requests) == 1 + assert api_tracker.file_download_requests[0].file == "files/some-file" + assert result == b"fake file content" + + +# =========================================================================== +# File search store upload tests +# =========================================================================== + + +async def test_file_search_store_upload(client: Client): + """Upload to file search store dispatches through the activity.""" + new_client, api_tracker = apply_plugin(client, []) + + async with new_worker(new_client, FileSearchStoreUploadWorkflow) as worker: + result = await new_client.execute_workflow( + FileSearchStoreUploadWorkflow.run, + args=["fileSearchStores/my-store", "/tmp/doc.txt"], + id=f"gemini-fss-upload-{uuid.uuid4()}", + task_queue=worker.task_queue, + execution_timeout=timedelta(seconds=10), + ) + + assert len(api_tracker.file_search_store_upload_requests) == 1 + req = api_tracker.file_search_store_upload_requests[0] + assert req.file_search_store_name == "fileSearchStores/my-store" + assert req.file_path == "/tmp/doc.txt" + assert req.config is not None + assert req.config.display_name == "Test Doc" + assert result == "operations/test-op" + + +# =========================================================================== +# Multi-turn chat tests +# =========================================================================== + + +async def test_chat_multi_turn(client: Client): + """Multi-turn chat sends multiple requests through the activity.""" + new_client, api_tracker = apply_plugin( + client, + [ + make_text_response("First answer"), + make_text_response("Second answer"), + ], + ) + + async with new_worker(new_client, ChatWorkflow) as worker: + result = await new_client.execute_workflow( + ChatWorkflow.run, + "Hello", + id=f"gemini-chat-{uuid.uuid4()}", + task_queue=worker.task_queue, + execution_timeout=timedelta(seconds=10), + ) + + assert len(api_tracker.requests) == 2 + assert result == ["First answer", "Second answer"] + + +class _FakeAsyncStream: + """Minimal stand-in for the SDK's AsyncStream in mocked-client tests.""" + + def __init__(self, events: list[Any]) -> None: + self._events = events + + def __aiter__(self) -> Any: + return self._gen() + + async def _gen(self) -> Any: + for event in self._events: + yield event + + async def __aenter__(self) -> "_FakeAsyncStream": + return self + + async def __aexit__(self, *_args: Any) -> None: + pass + + +# =========================================================================== +# Full integration test — real activities, mocked client +# =========================================================================== + + +def _apply_plugin_with_mock_client(client: Client, mock_responses: list[str]) -> Client: + """Create a real GoogleGenAIPlugin with real activities but a mocked client. + + Unlike ``apply_plugin``, this does NOT replace the activities. The + real ``GeminiApiCaller.activities()`` are registered, exercising the + full activity code path. The underlying ``genai.Client`` HTTP layer + and high-level file methods are mocked so no network calls are made. + """ + gemini = GeminiClient(api_key="fake-test-key") + + call_state = {"index": 0} + + async def fake_async_request(*_args: Any, **_kwargs: Any) -> SdkHttpResponse: + idx = call_state["index"] + call_state["index"] += 1 + if idx >= len(mock_responses): + raise RuntimeError( + f"No more mock responses (called {idx + 1} times, " + f"have {len(mock_responses)})" + ) + return SdkHttpResponse( + headers={"content-type": "application/json"}, + body=mock_responses[idx], + ) + + async def fake_async_request_streamed(*_args: Any, **_kwargs: Any) -> Any: + idx = call_state["index"] + call_state["index"] += 1 + if idx >= len(mock_responses): + raise RuntimeError( + f"No more mock responses (called {idx + 1} times, " + f"have {len(mock_responses)})" + ) + + async def _gen(): + yield SdkHttpResponse( + headers={"content-type": "application/json"}, + body=mock_responses[idx], + ) + + return _gen() + + gemini._api_client.async_request = fake_async_request # type: ignore[assignment] + gemini._api_client.async_request_streamed = fake_async_request_streamed # type: ignore[assignment] + + # Mock file operations at the high-level SDK interface (these are what + # the real activities call). + gemini.aio.files.upload = AsyncMock( # type: ignore[method-assign] + return_value=types.File( + name="files/mock-uploaded", + uri="https://fake.uri/files/mock-uploaded", + size_bytes=42, + ) + ) + gemini.aio.files.download = AsyncMock(return_value=b"mock download content") # type: ignore[method-assign] + gemini.aio.file_search_stores.upload_to_file_search_store = AsyncMock( # type: ignore[method-assign] + return_value=types.UploadToFileSearchStoreOperation.model_construct( + name="operations/mock-op" + ) + ) + + # Interactions and agents go through the vendored nextgen client (not + # BaseApiClient); inject a mock instance so the real activities exercise + # their code path without network access. + interaction = _deserialize(make_interaction_dict(), Interaction) + sse_events = [ + _deserialize(e, InteractionSSEEvent) for e in make_interaction_sse_events() + ] + + async def _interactions_create(*_args: Any, **kwargs: Any) -> Any: + if kwargs.get("stream"): + return _FakeAsyncStream(sse_events) + return interaction + + mock_interactions = MagicMock() + mock_interactions.create = _interactions_create + mock_agents = MagicMock() + mock_agents.create = AsyncMock(return_value=_deserialize(make_agent_dict(), Agent)) + # The interactions/agents resources are cached lazily on the async client; + # set them so the activities' client.aio.interactions/.agents calls hit the + # mocks instead of the network. + gemini.aio._interactions = mock_interactions # type: ignore[assignment] + gemini.aio._agents = mock_agents # type: ignore[assignment] + + plugin = GoogleGenAIPlugin(gemini) + config = client.config() + config["plugins"] = [plugin] + return Client(**config) + + +async def test_full_integration_with_mock_client(client: Client): + """Run a workflow through real activities with a mocked genai.Client. + + This is the only test that exercises the actual activity implementations + in _gemini_activity.py. Every other test uses the GeminiApiCallTracker + which replaces the activities entirely. + """ + # Mock responses are consumed in order by the async_request and + # async_request_streamed mocks. Steps 3-5 (file upload, download, + # store upload) are mocked separately at the SDK level and don't + # consume from this list. + new_client = _apply_plugin_with_mock_client( + client, + [ + make_text_response("Real activity response"), # generate_content + make_text_response("Streamed via real activity"), # generate_content_stream + make_text_response("Grounded RAG answer"), # RAG query with file_search + make_text_response(""), # file_search_stores.delete + ], + ) + + async with new_worker(new_client, FullIntegrationWorkflow) as worker: + result = await new_client.execute_workflow( + FullIntegrationWorkflow.run, + "test prompt", + id=f"gemini-full-integration-{uuid.uuid4()}", + task_queue=worker.task_queue, + execution_timeout=timedelta(seconds=15), + ) + + assert result["generate"] == "Real activity response" + assert len(result["stream_chunks"]) > 0 + assert "Streamed" in " ".join(result["stream_chunks"]) + assert result["upload_name"] == "files/mock-uploaded" + assert result["download"] == "mock download content" + assert result["fss_upload_op"] == "operations/mock-op" + assert result["rag"] == "Grounded RAG answer" + assert result["store_deleted"] is True + assert result["interaction_id"] == INTERACTION_ID + assert result["interaction_events"] == [ + "interaction.created", + "step.delta", + "step.delta", + "interaction.completed", + ] + assert result["agent_id"] == "test-agent" + + +async def test_register_files_without_credentials_fails(client: Client): + """register_files raises when no credentials are available.""" + # _apply_plugin_with_mock_client uses api_key auth with no + # extra_credentials, so the activity should raise ValueError. + new_client = _apply_plugin_with_mock_client(client, []) + + async with new_worker(new_client, RegisterFilesWorkflow) as worker: + with pytest.raises(WorkflowFailureError) as exc_info: + await new_client.execute_workflow( + RegisterFilesWorkflow.run, + ["gs://bucket/file.txt"], + id=f"gemini-register-no-creds-{uuid.uuid4()}", + task_queue=worker.task_queue, + execution_timeout=timedelta(seconds=10), + ) + + # The error is nested: WorkflowFailureError → ActivityError → ApplicationError + cause = exc_info.value.cause + while cause.__cause__ is not None: + cause = cause.__cause__ + assert "No credentials available for register_files" in str(cause) + + +# =========================================================================== +# TemporalAsyncClient wiring tests +# =========================================================================== + + +def test_temporal_async_client_has_temporal_files(): + """TemporalAsyncClient() returns a client with TemporalAsyncFiles.""" + client = TemporalAsyncClient() + assert isinstance(client, TemporalAsyncClient) + assert isinstance(client.files, TemporalAsyncFiles) + + +def test_temporal_async_client_has_temporal_file_search_stores(): + """TemporalAsyncClient() returns a client with TemporalAsyncFileSearchStores.""" + client = TemporalAsyncClient() + assert isinstance(client.file_search_stores, TemporalAsyncFileSearchStores) + + +# =========================================================================== +# Unit tests for _TemporalApiClient +# =========================================================================== + + +def test_sync_request_raises(): + """Synchronous request() raises RuntimeError.""" + api_client = _TemporalApiClient() + with pytest.raises(RuntimeError, match="Synchronous requests are not supported"): + api_client.request("GET", "/test", {}) + + +def test_sync_request_streamed_raises(): + """Synchronous request_streamed() raises RuntimeError.""" + api_client = _TemporalApiClient() + with pytest.raises(RuntimeError, match="Synchronous streaming is not supported"): + api_client.request_streamed("GET", "/test", {}) + + +def test_upload_file_raises(): + """Low-level upload_file() raises NotImplementedError.""" + api_client = _TemporalApiClient() + with pytest.raises(NotImplementedError, match="client.files.upload"): + api_client.upload_file() + + +def test_download_file_raises(): + """Low-level download_file() raises NotImplementedError.""" + api_client = _TemporalApiClient() + with pytest.raises(NotImplementedError, match="client.files.download"): + api_client.download_file() + + +# =========================================================================== +# Unit tests for activity_as_tool +# =========================================================================== + + +def test_activity_as_tool_bare_function_raises(): + """activity_as_tool rejects a function without @activity.defn.""" + + async def not_an_activity(x: str) -> str: + return x + + with pytest.raises(GoogleGenAIError, match="@activity.defn"): + activity_as_tool(not_an_activity) + + +def test_activity_as_tool_preserves_name(): + """Returned wrapper keeps the original function name.""" + wrapper = activity_as_tool(ToolCallTracker.get_weather) + assert wrapper.__name__ == "get_weather" + + +def test_activity_as_tool_preserves_doc(): + """Returned wrapper keeps the original docstring.""" + wrapper = activity_as_tool(ToolCallTracker.get_weather) + assert wrapper.__doc__ == "Get the weather for a given city." + + +def test_activity_as_tool_preserves_signature(): + """Returned wrapper has the correct parameter signature (self hidden).""" + wrapper = activity_as_tool(ToolCallTracker.get_weather) + sig = inspect.signature(wrapper) + params = list(sig.parameters.keys()) + assert params == ["city"] + + +def test_activity_as_tool_multi_arg_signature(): + """Multi-arg activity preserves all parameter names (self hidden).""" + wrapper = activity_as_tool(ToolCallTracker.get_weather_country) + sig = inspect.signature(wrapper) + params = list(sig.parameters.keys()) + assert params == ["city", "country"] + + +def test_activity_as_tool_is_async_callable(): + """Returned wrapper is an async callable.""" + wrapper = activity_as_tool(ToolCallTracker.get_weather) + assert inspect.iscoroutinefunction(wrapper) + + +# =========================================================================== +# Bound-method tool wrapping - shields workflow-method tools from google-genai's +# internal config deep-copy (>= 2.8.0), which would otherwise clone the workflow +# instance and drop in-workflow state mutations. Version-independent unit tests. +# =========================================================================== + + +class _StatefulTool: + def __init__(self) -> None: + self.calls: list[str] = [] + + async def lookup_city(self, city: str) -> str: + """Look up info about a city.""" + self.calls.append(city) + return f"{city} is great" + + +async def test_closure_if_bound_method_unbinds_and_mutates_original(): + """A bound method becomes a plain function that still mutates the real instance.""" + obj = _StatefulTool() + wrapped = cast(Callable[..., Any], _closure_if_bound_method(obj.lookup_city)) + + # No longer a bound method (so deepcopy leaves it — and its captured self — + # intact), but name/doc/signature are preserved for AFC schema building. + assert not inspect.ismethod(wrapped) + assert wrapped.__name__ == "lookup_city" + assert wrapped.__doc__ == "Look up info about a city." + assert list(inspect.signature(wrapped).parameters) == ["city"] + + assert await wrapped("Berlin") == "Berlin is great" + assert obj.calls == ["Berlin"] + + +def test_closure_survives_deepcopy_bound_method_does_not(): + """The wrapper keeps its instance across a deep-copy; a raw bound method clones it.""" + import copy + + obj = _StatefulTool() + + # Raw bound method: deepcopy clones __self__ (the 2.8.0 failure mode). + copied_method = copy.deepcopy(obj.lookup_city) + assert inspect.ismethod(copied_method) + assert copied_method.__self__ is not obj + + # Closure: deepcopy is a no-op, so the captured instance is preserved. + wrapped = _closure_if_bound_method(obj.lookup_city) + assert copy.deepcopy(wrapped) is wrapped + + +def test_closure_if_bound_method_passes_through_non_methods(): + """Plain functions and activity_as_tool wrappers are left untouched.""" + + def plain(city: str) -> str: + return city + + assert _closure_if_bound_method(plain) is plain + activity_tool = activity_as_tool(ToolCallTracker.get_weather) + assert _closure_if_bound_method(activity_tool) is activity_tool + + +def test_wrap_bound_method_tools_config_forms(): + """Config tools are wrapped for both model and dict configs, without mutating the caller.""" + obj = _StatefulTool() + + # Model config: bound method wrapped, caller's config left as-is. + config = types.GenerateContentConfig(tools=[obj.lookup_city]) + wrapped = _wrap_bound_method_tools(config) + assert isinstance(wrapped, types.GenerateContentConfig) + assert wrapped is not config + assert config.tools == [obj.lookup_city] # original untouched + assert wrapped.tools is not None + assert not inspect.ismethod(wrapped.tools[0]) + + # Dict config: same, and the original dict/list are not mutated. + dict_config: types.GenerateContentConfigDict = {"tools": [obj.lookup_city]} + wrapped_dict = _wrap_bound_method_tools(dict_config) + assert isinstance(wrapped_dict, dict) + assert dict_config.get("tools") == [obj.lookup_city] + wrapped_tools = wrapped_dict.get("tools") + assert wrapped_tools is not None + assert not inspect.ismethod(wrapped_tools[0]) + + # No bound methods -> returned unchanged (no needless copy). + def plain(city: str) -> str: + return city + + plain_config = types.GenerateContentConfig(tools=[plain]) + assert _wrap_bound_method_tools(plain_config) is plain_config + assert _wrap_bound_method_tools(None) is None + + +# =========================================================================== +# Unit tests for TemporalAsyncClient +# =========================================================================== + + +def test_temporal_async_client_vertexai_config(): + """TemporalAsyncClient() forwards Vertex AI configuration to the _TemporalApiClient.""" + result = TemporalAsyncClient(vertexai=True, project="proj", location="us-central1") + assert result._api_client.vertexai is True + assert result._api_client.project == "proj" + assert result._api_client.location == "us-central1" + + +# =========================================================================== +# Unit tests for io.IOBase text-stream rejection +# =========================================================================== + + +async def test_file_upload_text_stream_raises(): + """TemporalAsyncFiles.upload rejects text streams with a clear TypeError.""" + files = TemporalAsyncFiles(_TemporalApiClient()) + with pytest.raises( + TypeError, match="file must be a binary stream when passing an io.IOBase" + ): + await files.upload(file=io.StringIO("text")) + + +async def test_file_search_store_upload_text_stream_raises(): + """TemporalAsyncFileSearchStores.upload_to_file_search_store rejects text streams.""" + stores = TemporalAsyncFileSearchStores(_TemporalApiClient()) + with pytest.raises( + TypeError, match="file must be a binary stream when passing an io.IOBase" + ): + await stores.upload_to_file_search_store( + file_search_store_name="fileSearchStores/x", + file=io.StringIO("text"), + ) + + +# =========================================================================== +# Interactions API tests +# =========================================================================== + + +async def test_interaction_create(client: Client): + """Non-streaming interactions.create returns a typed Interaction.""" + new_client, tracker = apply_plugin(client, []) + + async with new_worker(new_client, InteractionCreateWorkflow) as worker: + result = await new_client.execute_workflow( + InteractionCreateWorkflow.run, + "What's an interaction?", + id=f"gemini-interaction-create-{uuid.uuid4()}", + task_queue=worker.task_queue, + execution_timeout=timedelta(seconds=10), + ) + + assert result == {"id": INTERACTION_ID, "status": "completed"} + assert len(tracker.interaction_requests) == 1 + params = tracker.interaction_requests[0].params + assert params["model"] == "gemini-2.5-flash" + assert params["input"] == "What's an interaction?" + # stream selects the activity; timeout maps to start_to_close_timeout. + assert "stream" not in params + assert "timeout" not in params + + +async def test_interaction_create_stream(client: Client): + """Streamed interactions.create yields typed events in order.""" + new_client, tracker = apply_plugin(client, []) + + async with new_worker(new_client, InteractionStreamWorkflow) as worker: + result = await new_client.execute_workflow( + InteractionStreamWorkflow.run, + "Stream me", + id=f"gemini-interaction-stream-{uuid.uuid4()}", + task_queue=worker.task_queue, + execution_timeout=timedelta(seconds=10), + ) + + assert result == [ + "interaction.created", + "step.delta", + "step.delta", + "interaction.completed", + ] + assert len(tracker.interaction_requests) == 1 + assert "stream" not in tracker.interaction_requests[0].params + + +async def test_interaction_lifecycle(client: Client): + """interactions.get/cancel/delete forward the interaction id.""" + new_client, tracker = apply_plugin(client, []) + + async with new_worker(new_client, InteractionLifecycleWorkflow) as worker: + result = await new_client.execute_workflow( + InteractionLifecycleWorkflow.run, + "interactions/abc", + id=f"gemini-interaction-lifecycle-{uuid.uuid4()}", + task_queue=worker.task_queue, + execution_timeout=timedelta(seconds=10), + ) + + assert result["got_id"] == INTERACTION_ID + assert result["cancel_status"] == "cancelled" + assert result["deleted"] == {"deleted": True} + assert [r.id for r in tracker.interaction_id_requests] == ["interactions/abc"] * 3 + + +async def test_agents_crud(client: Client): + """agents.create/get/list/delete round-trip through activities.""" + new_client, tracker = apply_plugin(client, []) + + async with new_worker(new_client, AgentsWorkflow) as worker: + result = await new_client.execute_workflow( + AgentsWorkflow.run, + id=f"gemini-agents-{uuid.uuid4()}", + task_queue=worker.task_queue, + execution_timeout=timedelta(seconds=10), + ) + + assert result["created_id"] == "test-agent" + assert result["got_id"] == "test-agent" + assert result["listed_ids"] == ["test-agent"] + assert result["next_page_token"] == "next-tok" + assert result["delete_response"]["id"] == "test-agent" + # create + list went through the no-id request path + assert [r.params.get("page_size") for r in tracker.interaction_requests] == [ + None, + 10, + ] + + +async def test_webhooks_unsupported(client: Client): + """client.webhooks raises a clear error inside a workflow.""" + new_client, _ = apply_plugin(client, []) + + async with new_worker(new_client, WebhooksUnsupportedWorkflow) as worker: + result = await new_client.execute_workflow( + WebhooksUnsupportedWorkflow.run, + id=f"gemini-webhooks-{uuid.uuid4()}", + task_queue=worker.task_queue, + execution_timeout=timedelta(seconds=10), + ) + + assert "client.webhooks is not supported in Temporal workflows" in result + + +# =========================================================================== +# Unit tests for interactions helpers +# =========================================================================== + + +def test_pop_timeout_maps_to_activity_config(): + """A numeric timeout kwarg becomes the activity start_to_close_timeout.""" + from temporalio.contrib.google_genai._temporal_interactions import _pop_timeout + + config = ActivityConfig() + params: dict[str, Any] = {"model": "gemini-2.5-flash", "timeout": 120} + _pop_timeout(params, config) + assert "timeout" not in params + assert config.get("start_to_close_timeout") == timedelta(seconds=120) + + +def test_pop_timeout_rejects_non_numeric(): + """Non-numeric timeouts (e.g. httpx.Timeout) are rejected.""" + import httpx + + from temporalio.contrib.google_genai._temporal_interactions import _pop_timeout + + with pytest.raises(ValueError, match="timeout must be numeric seconds"): + _pop_timeout({"timeout": httpx.Timeout(5.0)}, ActivityConfig()) + + +# =========================================================================== +# Retry handling + error classification (Temporal owns retries) +# =========================================================================== + + +def test_plugin_rejects_client_retry_options(): + """A genai.Client with retry_options is rejected at plugin construction.""" + from google.genai.types import HttpOptions, HttpRetryOptions + + from temporalio.contrib.google_genai._google_genai_plugin import ( + _reject_sdk_retries, + ) + + client = GeminiClient( + api_key="fake-test-key", + http_options=HttpOptions(retry_options=HttpRetryOptions(attempts=3)), + ) + with pytest.raises(ValueError, match="retry_options"): + _reject_sdk_retries(client) + + +def test_plugin_allows_no_retry_options(): + """A default client (no retry_options) passes the retry check.""" + from temporalio.contrib.google_genai._google_genai_plugin import ( + _reject_sdk_retries, + ) + + _reject_sdk_retries(GeminiClient(api_key="fake-test-key")) + + +def test_process_http_options_rejects_retry_options(): + """Per-request http_options.retry_options raises in the workflow.""" + from google.genai.types import HttpOptions, HttpRetryOptions + + from temporalio.contrib.google_genai._temporal_api_client import _TemporalApiClient + + with pytest.raises(GoogleGenAIError, match="retry_options"): + _TemporalApiClient._process_http_options( + HttpOptions(retry_options=HttpRetryOptions(attempts=2)), + ActivityConfig(), + ) + + +def test_classify_api_error_retryable_vs_non_retryable(): + """Transient HTTP statuses stay retryable; client errors are non-retryable.""" + from google.genai import errors + + from temporalio.contrib.google_genai._gemini_activity import _classify_api_error + + client_err = errors.ClientError.__new__(errors.ClientError) + client_err.code = 400 + classified = _classify_api_error(client_err) + assert classified.non_retryable is True + assert classified.type == "ClientError" + + server_err = errors.ServerError.__new__(errors.ServerError) + server_err.code = 503 + assert _classify_api_error(server_err).non_retryable is False + + +def test_google_genai_error_is_application_error(): + """GoogleGenAIError is an ApplicationError so existing handling still works.""" + assert issubclass(GoogleGenAIError, ApplicationError) + + +# =========================================================================== +# Replay determinism + side-effect (activity scheduling) tests +# =========================================================================== + + +def _replay_plugin() -> GoogleGenAIPlugin: + """Build a real plugin instance for the Replayer. + + Replay never executes activities, so a fake-key client is sufficient. + What matters is that the Replayer uses the plugin's data converter, + sandbox passthrough, and workflow runner — the same configuration that + runs in production — so a history recorded by the plugin replays under + it without nondeterminism. + """ + return GoogleGenAIPlugin(GeminiClient(api_key="fake-test-key")) + + +async def test_replay_simple_generate(client: Client): + """A recorded simple generate_content history replays deterministically.""" + new_client, _ = apply_plugin(client, [make_text_response("Hello from Gemini!")]) + + async with new_worker(new_client, SimpleGenerateWorkflow) as worker: + handle = await new_client.start_workflow( + SimpleGenerateWorkflow.run, + "Say hello", + id=f"gemini-replay-simple-{uuid.uuid4()}", + task_queue=worker.task_queue, + execution_timeout=timedelta(seconds=10), + ) + await handle.result() + history = await handle.fetch_history() + + await Replayer( + workflows=[SimpleGenerateWorkflow], + plugins=[_replay_plugin()], + ).replay_workflow(history) + + +async def test_replay_tool_loop(client: Client): + """The in-workflow AFC tool loop replays deterministically. + + The Gemini SDK's automatic-function-calling loop runs inside the + workflow, interleaving multiple activity calls with SDK-side request + formatting. That makes it the replay path most likely to surface + nondeterminism, so the recorded history is replayed under the real + plugin to prove the loop is replay-safe. + """ + tool_tracker = ToolCallTracker() + new_client, _ = apply_plugin( + client, + [ + make_function_call_response("get_weather", {"city": "Tokyo"}), + make_function_call_response( + "get_weather_country", {"city": "Paris", "country": "France"} + ), + make_text_response("Tokyo is sunny; Paris is rainy."), + ], + ) + + async with new_worker( + new_client, + MultipleToolsWorkflow, + activities=[tool_tracker.get_weather, tool_tracker.get_weather_country], + ) as worker: + handle = await new_client.start_workflow( + MultipleToolsWorkflow.run, + "Compare Tokyo and Paris weather", + id=f"gemini-replay-tools-{uuid.uuid4()}", + task_queue=worker.task_queue, + execution_timeout=timedelta(seconds=15), + ) + await handle.result() + history = await handle.fetch_history() + + await Replayer( + workflows=[MultipleToolsWorkflow], + plugins=[_replay_plugin()], + ).replay_workflow(history) + + +async def test_side_effects_activity_scheduling(client: Client): + """Each Gemini API call and tool call schedules exactly one activity. + + Runs with ``max_cached_workflows=0`` so the workflow is evicted and + replayed from history between tasks — any nondeterminism in the + in-workflow AFC loop would fail the run — then asserts the exact number + of ``ActivityTaskScheduled`` events per activity type. The multi-tool + workflow issues three generate_content calls (initial + one per tool + result) and one activity per tool invocation. + """ + tool_tracker = ToolCallTracker() + new_client, _ = apply_plugin( + client, + [ + make_function_call_response("get_weather", {"city": "Tokyo"}), + make_function_call_response( + "get_weather_country", {"city": "Paris", "country": "France"} + ), + make_text_response("Tokyo is sunny; Paris is rainy."), + ], + ) + + async with new_worker( + new_client, + MultipleToolsWorkflow, + activities=[tool_tracker.get_weather, tool_tracker.get_weather_country], + max_cached_workflows=0, + ) as worker: + handle = await new_client.start_workflow( + MultipleToolsWorkflow.run, + "Compare Tokyo and Paris weather", + id=f"gemini-side-effects-{uuid.uuid4()}", + task_queue=worker.task_queue, + execution_timeout=timedelta(seconds=15), + ) + await handle.result() + + scheduled: dict[str, int] = {} + async for e in handle.fetch_history_events(): + if e.HasField("activity_task_scheduled_event_attributes"): + name = e.activity_task_scheduled_event_attributes.activity_type.name + scheduled[name] = scheduled.get(name, 0) + 1 + + assert scheduled == { + "gemini_api_client_async_request": 3, + "get_weather": 1, + "get_weather_country": 1, + } diff --git a/tests/contrib/google_genai/test_gemini_mcp.py b/tests/contrib/google_genai/test_gemini_mcp.py new file mode 100644 index 000000000..3b32c28ca --- /dev/null +++ b/tests/contrib/google_genai/test_gemini_mcp.py @@ -0,0 +1,389 @@ +"""MCP integration tests for the Google Gemini SDK Temporal integration. + +Covers the client-side ``McpClientSession`` path (Gemini Developer API) routed +through ``TemporalMcpClientSession``: +- tool discovery + call through a real stdio MCP server on the worker +- worker-side connection pooling and idle eviction +- ``cache_tools`` listing frequency +- full parameter-schema propagation to the model (the MCP wire-format check) +- replay determinism and exact activity-scheduling counts + +Plus the server-side pass-through paths that need no shim code: +- Vertex AI ``Tool(mcp_servers=[McpServer(...)])`` config serialization +- Interactions API ``MCPServerToolCallStep`` / ``MCPServerToolResultStep`` rehydration +""" + +from __future__ import annotations + +import sys +from collections.abc import AsyncIterator +from contextlib import AbstractAsyncContextManager, asynccontextmanager +from datetime import timedelta +from pathlib import Path +from typing import Any +from uuid import uuid4 + +import pytest +from google.genai import types +from mcp import ClientSession, StdioServerParameters +from mcp.client.stdio import stdio_client + +from temporalio import workflow +from temporalio.client import Client +from temporalio.contrib.google_genai import ( + GoogleGenAIPlugin, + TemporalAsyncClient, + TemporalMcpClientSession, +) +from temporalio.contrib.google_genai._temporal_interactions import _deserialize +from temporalio.worker import Replayer +from temporalio.workflow import ActivityConfig +from tests.contrib.google_genai.test_gemini import ( + GeminiApiCallTracker, + make_function_call_response, + make_text_response, +) +from tests.helpers import new_worker + +_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 + + +class _CountingFactory: + """Wraps the echo factory to count how often a connection is opened.""" + + def __init__(self) -> None: + self.opens = 0 + + def __call__(self) -> AbstractAsyncContextManager[ClientSession]: + self.opens += 1 + return _echo_session() + + +def _apply_mcp_plugin( + client: Client, + mock_responses: list[str], + mcp_servers: dict, + mcp_connection_idle_timeout: timedelta | None = None, +) -> tuple[Client, GeminiApiCallTracker]: + """Build a plugin whose API activities are faked but MCP activities are real. + + Monkeypatches ``GeminiApiCaller.activities`` (so canned generate_content + responses drive the AFC loop) while leaving the plugin's MCP activities — + built from ``mcp_servers`` — to hit the real stdio echo server. + """ + from temporalio.contrib.google_genai._gemini_activity import GeminiApiCaller + + tracker = GeminiApiCallTracker(mock_responses) + original = GeminiApiCaller.activities + GeminiApiCaller.activities = lambda self: [ # type: ignore[method-assign] + tracker.gemini_api_client_async_request, + tracker.gemini_api_client_async_request_streamed, + ] + try: + from google.genai import Client as GeminiClient + + plugin = GoogleGenAIPlugin( + GeminiClient(api_key="fake-test-key"), + mcp_servers=mcp_servers, + mcp_connection_idle_timeout=mcp_connection_idle_timeout, + ) + finally: + GeminiApiCaller.activities = original # type: ignore[method-assign] + + config = client.config() + config["plugins"] = [plugin] + return Client(**config), tracker + + +def _replay_plugin(mcp_servers: dict) -> GoogleGenAIPlugin: + from google.genai import Client as GeminiClient + + return GoogleGenAIPlugin( + GeminiClient(api_key="fake-test-key"), mcp_servers=mcp_servers + ) + + +async def _activity_names(handle: Any) -> list[str]: + names: list[str] = [] + async for e in handle.fetch_history_events(): + if e.HasField("activity_task_scheduled_event_attributes"): + names.append(e.activity_task_scheduled_event_attributes.activity_type.name) + return names + + +@pytest.fixture(autouse=True) +def _clear_mcp_connections(): # pyright: ignore[reportUnusedFunction] + """Isolate the module-global MCP connection pool between tests.""" + from temporalio.contrib.google_genai import _mcp + + _mcp._CONNECTIONS.clear() + yield + _mcp._CONNECTIONS.clear() + + +# --------------------------------------------------------------------------- +# Workflow +# --------------------------------------------------------------------------- + + +@workflow.defn +class McpToolWorkflow: + """generate_content grounded by an MCP tool, via the AFC loop. + + Takes the MCP server name as an argument so each test can use a distinct + name (the worker-side connection pool is keyed by name and shared across + activity invocations in the worker process). The number of tool calls is + driven entirely by the mocked model responses, not the workflow. + """ + + @workflow.run + async def run(self, server_name: str, prompt: str) -> str: + client = TemporalAsyncClient() + session = TemporalMcpClientSession( + server_name, + 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 "" + + +# --------------------------------------------------------------------------- +# Client-side MCP tests +# --------------------------------------------------------------------------- + + +async def test_mcp_tool_discovery_and_call(client: Client): + """The AFC loop discovers + calls an MCP tool through activities.""" + server = "echo_basic" + new_client, _ = _apply_mcp_plugin( + client, + [ + make_function_call_response("echo", {"message": "hello"}), + make_text_response("Done!"), + ], + mcp_servers={server: _echo_session}, + ) + + async with new_worker(new_client, McpToolWorkflow) as worker: + handle = await new_client.start_workflow( + McpToolWorkflow.run, + args=[server, "echo hello"], + id=f"gemini-mcp-{uuid4()}", + task_queue=worker.task_queue, + execution_timeout=timedelta(seconds=30), + ) + result = await handle.result() + names = await _activity_names(handle) + + assert result == "Done!" + assert names == [ + f"{server}-list-tools", + "gemini_api_client_async_request", + f"{server}-call-tool", + "gemini_api_client_async_request", + ] + + +async def test_mcp_connection_pooling(client: Client): + """Two tool calls in one workflow reuse a single worker-side connection.""" + server = "echo_pool" + factory = _CountingFactory() + new_client, _ = _apply_mcp_plugin( + client, + [ + make_function_call_response("echo", {"message": "one"}), + make_function_call_response("echo", {"message": "two"}), + make_text_response("Done!"), + ], + mcp_servers={server: factory}, + ) + + async with new_worker(new_client, McpToolWorkflow) as worker: + handle = await new_client.start_workflow( + McpToolWorkflow.run, + args=[server, "echo twice"], + id=f"gemini-mcp-pool-{uuid4()}", + task_queue=worker.task_queue, + execution_timeout=timedelta(seconds=30), + ) + assert await handle.result() == "Done!" + names = await _activity_names(handle) + + # list-tools + two call-tools all served by one lazily-opened connection. + assert names.count(f"{server}-call-tool") == 2 + assert factory.opens == 1 + + +async def test_mcp_full_schema_propagation(client: Client): + """The model receives the MCP tool's full parameter schema, not just name.""" + server = "echo_schema" + new_client, tracker = _apply_mcp_plugin( + client, + [ + make_function_call_response("echo", {"message": "hi"}), + make_text_response("Done!"), + ], + mcp_servers={server: _echo_session}, + ) + + async with new_worker(new_client, McpToolWorkflow) as worker: + await new_client.execute_workflow( + McpToolWorkflow.run, + args=[server, "echo hi"], + id=f"gemini-mcp-schema-{uuid4()}", + task_queue=worker.task_queue, + execution_timeout=timedelta(seconds=30), + ) + + # The first generate request carries the tool declarations the SDK built + # from the MCP list_tools result. + first = tracker.requests[0].request_dict + decls = first["tools"][0]["functionDeclarations"] # type: ignore[index] + echo_decl = next(d for d in decls if d["name"] == "echo") + assert "parameters" in echo_decl + assert "message" in echo_decl["parameters"]["properties"] + + +async def test_mcp_replay(client: Client): + """A recorded MCP tool-loop history replays deterministically.""" + server = "echo_replay" + new_client, _ = _apply_mcp_plugin( + client, + [ + make_function_call_response("echo", {"message": "hello"}), + make_text_response("Done!"), + ], + mcp_servers={server: _echo_session}, + ) + + async with new_worker(new_client, McpToolWorkflow) as worker: + handle = await new_client.start_workflow( + McpToolWorkflow.run, + args=[server, "echo hello"], + id=f"gemini-mcp-replay-{uuid4()}", + task_queue=worker.task_queue, + execution_timeout=timedelta(seconds=30), + ) + await handle.result() + history = await handle.fetch_history() + + await Replayer( + workflows=[McpToolWorkflow], + plugins=[_replay_plugin({server: _echo_session})], + ).replay_workflow(history) + + +async def test_mcp_side_effects(client: Client): + """max_cached_workflows=0: exact ActivityTaskScheduled counts per type.""" + server = "echo_side" + new_client, _ = _apply_mcp_plugin( + client, + [ + make_function_call_response("echo", {"message": "hello"}), + make_text_response("Done!"), + ], + mcp_servers={server: _echo_session}, + ) + + async with new_worker( + new_client, McpToolWorkflow, max_cached_workflows=0 + ) as worker: + handle = await new_client.start_workflow( + McpToolWorkflow.run, + args=[server, "echo hello"], + id=f"gemini-mcp-side-effects-{uuid4()}", + task_queue=worker.task_queue, + execution_timeout=timedelta(seconds=30), + ) + await handle.result() + names = await _activity_names(handle) + + scheduled: dict[str, int] = {} + for n in names: + scheduled[n] = scheduled.get(n, 0) + 1 + assert scheduled == { + f"{server}-list-tools": 1, + "gemini_api_client_async_request": 2, + f"{server}-call-tool": 1, + } + + +# --------------------------------------------------------------------------- +# Server-side pass-through tests (no shim code) +# --------------------------------------------------------------------------- + + +def test_vertex_mcp_server_config_serializes(): + """Vertex server-side MCP config round-trips as plain request data.""" + tool = types.Tool( + mcp_servers=[ + types.McpServer( + name="weather", + streamable_http_transport=types.StreamableHttpTransport( + url="https://example.com/mcp", + ), + ) + ] + ) + config = types.GenerateContentConfig(tools=[tool]) + dumped = config.model_dump(mode="json", exclude_none=True) + server = dumped["tools"][0]["mcp_servers"][0] + assert server["name"] == "weather" + assert server["streamable_http_transport"]["url"] == "https://example.com/mcp" + + +def test_interactions_mcp_steps_rehydrate(): + """Interactions API MCP step payloads rehydrate via _deserialize.""" + from google.genai.interactions import InteractionSSEEvent + + call_event: Any = _deserialize( + { + "event_type": "step.start", + "index": 0, + "step": { + "type": "mcp_server_tool_call", + "id": "call-1", + "name": "lookup", + "server_name": "weather", + "arguments": {"city": "Tokyo"}, + }, + }, + InteractionSSEEvent, + ) + assert call_event.step.type == "mcp_server_tool_call" + assert call_event.step.server_name == "weather" + assert call_event.step.arguments == {"city": "Tokyo"} + + result_event: Any = _deserialize( + { + "event_type": "step.start", + "index": 0, + "step": { + "type": "mcp_server_tool_result", + "call_id": "call-1", + "name": "lookup", + "server_name": "weather", + "result": "sunny", + }, + }, + InteractionSSEEvent, + ) + assert result_event.step.type == "mcp_server_tool_result" + assert result_event.step.call_id == "call-1" diff --git a/tests/contrib/google_genai/test_gemini_streaming.py b/tests/contrib/google_genai/test_gemini_streaming.py new file mode 100644 index 000000000..e7bee8747 --- /dev/null +++ b/tests/contrib/google_genai/test_gemini_streaming.py @@ -0,0 +1,122 @@ +"""Streaming tests for the Google Gemini SDK Temporal integration. + +Covers ``generate_content_stream`` publishing each chunk to a +:class:`~temporalio.contrib.workflow_streams.WorkflowStream` topic for external +consumers, and the fail-fast when ``streaming_topic`` is set without a hosted +``WorkflowStream``. +""" + +from __future__ import annotations + +import uuid +from datetime import timedelta + +import pytest +from google.genai import types + +from temporalio import workflow +from temporalio.client import Client, WorkflowFailureError +from temporalio.contrib.google_genai import TemporalAsyncClient +from temporalio.contrib.google_genai.testing import GeminiTestServer, text_response +from temporalio.contrib.workflow_streams import WorkflowStream, WorkflowStreamClient +from tests.helpers import new_worker + + +@workflow.defn +class StreamingWorkflowStreamWorkflow: + """Streams generate_content_stream chunks to a WorkflowStream topic. + + Holds the run open on a ``finish`` signal so an external subscriber can + reliably consume the published chunk before the workflow completes. + """ + + @workflow.init + def __init__(self, prompt: str) -> None: + self.stream = WorkflowStream() + self._done = False + + @workflow.run + async def run(self, prompt: str) -> str: + client = TemporalAsyncClient(streaming_topic="gemini") + out: list[str] = [] + async for chunk in await client.models.generate_content_stream( + model="gemini-2.5-flash", + contents=prompt, + ): + out.append(chunk.text or "") + await workflow.wait_condition(lambda: self._done) + return "".join(out) + + @workflow.signal + def finish(self) -> None: + self._done = True + + +@workflow.defn +class StreamingNoStreamWorkflow: + """Sets streaming_topic but hosts no WorkflowStream — must fail fast.""" + + @workflow.run + async def run(self, prompt: str) -> str: + client = TemporalAsyncClient(streaming_topic="gemini") + async for _ in await client.models.generate_content_stream( + model="gemini-2.5-flash", + contents=prompt, + ): + pass + return "done" + + +async def test_streaming_publishes_to_workflow_stream(client: Client): + """Streamed chunks are published to the WorkflowStream for external consumers.""" + server = GeminiTestServer([text_response("Hello from Gemini stream")]) + config = client.config() + config["plugins"] = [server.plugin()] + new_client = Client(**config) + + async with new_worker(new_client, StreamingWorkflowStreamWorkflow) as worker: + wf_id = f"gemini-stream-{uuid.uuid4()}" + handle = await new_client.start_workflow( + StreamingWorkflowStreamWorkflow.run, + "say hi", + id=wf_id, + task_queue=worker.task_queue, + execution_timeout=timedelta(seconds=15), + ) + + stream = WorkflowStreamClient.create(new_client, wf_id) + received: list[types.GenerateContentResponse] = [] + async for item in stream.subscribe( + ["gemini"], + result_type=types.GenerateContentResponse, + poll_cooldown=timedelta(milliseconds=20), + ): + received.append(item.data) + break # one scripted chunk + + await handle.signal(StreamingWorkflowStreamWorkflow.finish) + result = await handle.result() + + assert result == "Hello from Gemini stream" + assert len(received) == 1 + assert received[0].text == "Hello from Gemini stream" + + +async def test_streaming_without_workflow_stream_raises(client: Client): + """streaming_topic set but no WorkflowStream hosted fails the workflow.""" + server = GeminiTestServer([text_response("unused")]) + config = client.config() + config["plugins"] = [server.plugin()] + new_client = Client(**config) + + async with new_worker(new_client, StreamingNoStreamWorkflow) as worker: + with pytest.raises(WorkflowFailureError) as exc_info: + await new_client.execute_workflow( + StreamingNoStreamWorkflow.run, + "hi", + id=f"gemini-stream-nostream-{uuid.uuid4()}", + task_queue=worker.task_queue, + execution_timeout=timedelta(seconds=10), + ) + + assert "WorkflowStream" in str(exc_info.value.cause) diff --git a/uv.lock b/uv.lock index a591392ad..0543cf0ed 100644 --- a/uv.lock +++ b/uv.lock @@ -9,10 +9,12 @@ resolution-markers = [ ] [options] -exclude-newer = "2026-06-17T16:16:53.404973Z" +exclude-newer = "0001-01-01T00:00:00Z" # This has no effect and is included for backwards compatibility when using relative exclude-newer values. exclude-newer-span = "P2W" [options.exclude-newer-package] +google-adk = false +google-genai = false openai-agents = false [[package]] @@ -237,21 +239,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" @@ -739,15 +726,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/c7/0d/67e5b4109ea4a837e80daa87c2c696711955e40449a97e8926672534def2/click-8.4.1-py3-none-any.whl", hash = "sha256:482be17c6991b8c19c5429a1e995d9b0efdbb63172824c41f99965dc0ade8ec2", size = 116639, upload-time = "2026-05-22T04:08:35.26Z" }, ] -[[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" @@ -1285,47 +1263,26 @@ wheels = [ [[package]] name = "google-adk" -version = "1.35.0" +version = "2.2.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" }, @@ -1334,47 +1291,9 @@ dependencies = [ { name = "watchdog" }, { name = "websockets" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/3a/a7/8cba69e86af4f25b73f0bd4cbce9b0ca990a6a779cedee9a242264fca259/google_adk-1.35.0.tar.gz", hash = "sha256:c3f36447d29c1a3400ba45b344f232d857db9b18d1224517a00b267da1f51dff", size = 2432700, upload-time = "2026-06-10T05:32:34.778Z" } +sdist = { url = "https://files.pythonhosted.org/packages/4a/65/3ff3f50b10dac3323ddecd694515e9f9ed345886e0eaf666d0e42c90748b/google_adk-2.2.0.tar.gz", hash = "sha256:04cb6318aba8829fe7c941ee1b456ccb4745253898c13595708c9eb07b4582ff", size = 3391545, upload-time = "2026-06-04T22:15:12.9Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/2b/9a/dc5192a79bea70730c9261b8ca54ee4103265a260444d3bffdd2eab47876/google_adk-1.35.0-py3-none-any.whl", hash = "sha256:f4c10f86c37e4fba157868d6884d4493bbb88a53fea00004d900dc03a3347f85", size = 2877569, upload-time = "2026-06-10T05:32:37.085Z" }, -] - -[[package]] -name = "google-api-core" -version = "2.31.0" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "google-auth" }, - { name = "googleapis-common-protos" }, - { name = "proto-plus" }, - { name = "protobuf" }, - { name = "requests" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/c6/22/155cadf1d49272a9cf48f3168c0f3874fa13397297e611a5ea00cd093880/google_api_core-2.31.0.tar.gz", hash = "sha256:2be84ee0f584c48e6bde1b36766e23348b361fb7e55e56135fc76ce1c397f9c2", size = 176492, upload-time = "2026-06-03T14:52:17.257Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/86/40/9bdbb60b03a332bd45acb8703da08bbc27d991d35286b62e42acc86d243a/google_api_core-2.31.0-py3-none-any.whl", hash = "sha256:ef79fb3784c71cbac89cbd03301ba0c8fb8ad2aa95d7f9204dd9628f7adf59ab", size = 173102, upload-time = "2026-06-03T14:51:26.729Z" }, -] - -[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/64/f5/44a3b20b17bac130497f2d1dde8b93c90cfc026983cd94f24488d540ea70/google_adk-2.2.0-py3-none-any.whl", hash = "sha256:ebdf3d931dc2b9c5b30d995358fc2ae99d59594c48a4aaf7496869ccd2c5f245", size = 3912613, upload-time = "2026-06-04T22:15:15.411Z" }, ] [[package]] @@ -1398,407 +1317,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.157.0" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "certifi" }, - { 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/e0/d9/e2a5f5a8535bbc8f68729796f3fc2d68d59a72818fb44f6544edbc2592e4/google_cloud_aiplatform-1.157.0.tar.gz", hash = "sha256:ce8413ed3584c4896f7656b663214c24e91c2c89426f1c91fbd1d220ffda23af", size = 11064992, upload-time = "2026-06-10T00:19:33.643Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/e3/82/3ec2ba56dc1fa71ef783348a0c519721879dbc8f1e568534e6d4b4856ccd/google_cloud_aiplatform-1.157.0-py2.py3-none-any.whl", hash = "sha256:0ca499ac5648988916fc089f9e94bd99667eefba13f6936475247f4a0bf86634", size = 9200777, upload-time = "2026-06-10T00:19:30.181Z" }, -] - -[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.41.0" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "google-api-core", extra = ["grpc"] }, - { name = "google-auth" }, - { name = "google-cloud-core" }, - { name = "google-resumable-media" }, - { name = "packaging" }, - { name = "python-dateutil" }, - { name = "requests" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/ce/13/6515c7aab55a4a0cf708ffd309fb9af5bab54c13e32dc22c5acd6497193c/google_cloud_bigquery-3.41.0.tar.gz", hash = "sha256:2217e488b47ed576360c9b2cc07d59d883a54b83167c0ef37f915c26b01a06fe", size = 513434, upload-time = "2026-03-30T22:50:55.347Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/40/33/1d3902efadef9194566d499d61507e1f038454e0b55499d2d7f8ab2a4fee/google_cloud_bigquery-3.41.0-py3-none-any.whl", hash = "sha256:2a5b5a737b401cbd824a6e5eac7554100b878668d908e6548836b5d8aaa4dcaa", size = 262343, upload-time = "2026-03-30T22:48:45.444Z" }, -] - -[[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.12.0" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "google-api-core" }, - { name = "google-auth" }, - { name = "google-cloud-core" }, - { name = "google-crc32c" }, - { name = "google-resumable-media" }, - { name = "requests" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/58/72/86f94e1639a8bcd9d33e8e01b49afcaa1c3a13bda7683c681717e0901e15/google_cloud_storage-3.12.0.tar.gz", hash = "sha256:03ae9847c6babb368f35f054126b8a08cbc0e3266efb990eb17b9926a45cf3be", size = 17338620, upload-time = "2026-06-12T18:03:29.215Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/1b/bd/a89eaebd2f9db5f92ddcc8e4f23c266be1dbd11058bb83451d8dd029f34c/google_cloud_storage-3.12.0-py3-none-any.whl", hash = "sha256:3880773754ddf7c27567b04e2a4d193950b6b99429f37b9097d873686e95b09c", size = 340605, upload-time = "2026-06-12T18:03:12.677Z" }, -] - -[[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.10.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "anyio" }, @@ -1812,21 +1333,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" } +sdist = { url = "https://files.pythonhosted.org/packages/cd/fe/b796087493c3c55371aa58b9f264841ace5bfdf8c668cafa7afa33c44bec/google_genai-2.10.0.tar.gz", hash = "sha256:77912cd558cd7dfd5b75c25fd1c609e78d7954dde583331104022a46ea90f9ee", size = 600039, upload-time = "2026-06-24T01:33:18.157Z" } 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" } -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/e0/39/00bcfd94de255d24249401efff4f48d77bf6066b46447e519fa193c0c299/google_genai-2.10.0-py3-none-any.whl", hash = "sha256:d5350311567ae660c24cbc1752aee4b3d660f89c0106d2dcd2a69978c35afe1e", size = 957974, upload-time = "2026-06-24T01:33:16.296Z" }, ] [[package]] @@ -1841,11 +1350,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.11" @@ -1864,76 +1368,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/91/4c/e0ce1ef95d4000ebc1c11801f9b944fa5910ecc15b5e351865763d8657f8/graphviz-0.21-py3-none-any.whl", hash = "sha256:54f33de9f4f911d7e84e4191749cac8cc5653f815b06738c54db9a15ab8b1e42", size = 47300, upload-time = "2025-06-15T09:35:04.433Z" }, ] -[[package]] -name = "greenlet" -version = "3.5.1" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/6d/6e/802acd792aebb2256fbbee8cacf2727faaeb6f240ac11008f09eae4414bc/greenlet-3.5.1.tar.gz", hash = "sha256:5a56aeb7d5d9cc4b3a735efb5095bd4b4f6f0e4f93e5ca876d0e2315137b7829", size = 197356, upload-time = "2026-05-20T15:05:03.917Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/1d/21/117c8710abb7f146d804a124c07eb5964a60b90d02b72452885aecc18efa/greenlet-3.5.1-cp310-cp310-macosx_11_0_universal2.whl", hash = "sha256:7eacb17a9d41538a2bc4912eba5ef13823c83cb69e4d141d0813debe7163187f", size = 283510, upload-time = "2026-05-20T13:12:26.475Z" }, - { url = "https://files.pythonhosted.org/packages/b9/f7/6762a56fa5f6c2295c449c6524e10ce481e381c994cc44d9d03aef0700fb/greenlet-3.5.1-cp310-cp310-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e5cc9606aa5f4e0bde0d3bd502b44f743864c3ffa5cfa1011b1e30f5aa02366f", size = 599696, upload-time = "2026-05-20T14:00:02.906Z" }, - { url = "https://files.pythonhosted.org/packages/0f/05/85a511e68ee109aff0aa00b4b497806091dd2d82ce209e49c6e801bd5d92/greenlet-3.5.1-cp310-cp310-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:c3d35f87c7253b715d13d679e0783d845910144f282cb939fe1ba4ac8616269c", size = 612618, upload-time = "2026-05-20T14:05:39.202Z" }, - { url = "https://files.pythonhosted.org/packages/89/b8/8b83d18ae07c46c019617f35afd7b47aab7f9b4fbb12fc637d681e10bdd8/greenlet-3.5.1-cp310-cp310-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:540dae7b956209af4d70a3be35927b4055f617763771e5e84a5255bea934d2f5", size = 612947, upload-time = "2026-05-20T13:14:23.469Z" }, - { url = "https://files.pythonhosted.org/packages/5d/14/ad1f9fc9b82384c010212464a3702bd911f95dab2f1180bc6fbcfb1f958c/greenlet-3.5.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:ed8cdb691169715a9a492844a83246f090182247d1a5031dc78a403f68ba1e97", size = 1571425, upload-time = "2026-05-20T14:02:22.671Z" }, - { url = "https://files.pythonhosted.org/packages/46/1c/43b8203cf10f4292c9e3d270e9e5f5ade79115a0a0ca5ea6f1be5f8915a7/greenlet-3.5.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:9d59e840387076a51016777a9328b3f2c427c6f9208a6e958bad251be50a648d", size = 1638688, upload-time = "2026-05-20T13:14:30.026Z" }, - { url = "https://files.pythonhosted.org/packages/ac/6e/0344b1e99f58f71715456e46492101fd2daa408957b8186ade0a4b515da7/greenlet-3.5.1-cp310-cp310-win_amd64.whl", hash = "sha256:b9152fca4a6466e114aaec745ae61cba739903a109754a9d4e1262f01e9259b1", size = 237763, upload-time = "2026-05-20T13:11:35.659Z" }, - { url = "https://files.pythonhosted.org/packages/42/3c/ff890b466eaba2b0f5e6bdfff025f8c75f41b8ffdc3dbc3d24ad261e764a/greenlet-3.5.1-cp311-cp311-macosx_11_0_universal2.whl", hash = "sha256:73f78f9b9f0a5c06e5c946ba1e8e36f5114923b6be109ee618c54f079c3ea14f", size = 284764, upload-time = "2026-05-20T13:09:10.204Z" }, - { url = "https://files.pythonhosted.org/packages/81/0e/5e5457be3d256918f6a4756f073548a3f0190836e2cc94aa6d0d617a940b/greenlet-3.5.1-cp311-cp311-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a0cbed8bb44e23c5b199f888f4e4ce096b45ad9f25ff74a7ad0213875e936bb2", size = 603479, upload-time = "2026-05-20T14:00:04.757Z" }, - { url = "https://files.pythonhosted.org/packages/6d/e1/f89a21d58d308298e6f275f13a1b472ed96c680b601a371b08be6a725989/greenlet-3.5.1-cp311-cp311-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:a203a8bd0acb0701653d3bbb26e404854a68674139ed5cbb778830f42b09bb33", size = 615495, upload-time = "2026-05-20T14:05:40.87Z" }, - { url = "https://files.pythonhosted.org/packages/75/de/af6cef182862d2ccd6975440d21c9058a77c3f9b469abf94e322dfd2e0e3/greenlet-3.5.1-cp311-cp311-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8a271fcd66c74615cda6a964fda3f304267a12e50a084472218a39bb0376f563", size = 614754, upload-time = "2026-05-20T13:14:24.947Z" }, - { url = "https://files.pythonhosted.org/packages/1a/c6/50e520283a9f19388a7326b05f9e8637e566003475eacaadad04f558c68d/greenlet-3.5.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:ded7b068c7c31c1a8657d4fd42d886b3e051ae29f88b80c5ff9d502257b0f071", size = 1574097, upload-time = "2026-05-20T14:02:24.003Z" }, - { url = "https://files.pythonhosted.org/packages/21/1c/13abd1f4860d987fa5e1170a01930d6e6cd40d328de487a3c9fdaff0ffd0/greenlet-3.5.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:d0932b81d72f552ded9d810d00021b64d89f2195a91ce115b893f943b7a4ab3c", size = 1641058, upload-time = "2026-05-20T13:14:31.83Z" }, - { url = "https://files.pythonhosted.org/packages/f5/56/5f332b7705545eac2dc01b4e9254d24a793f2656d55d5cc6b94ee59d22ae/greenlet-3.5.1-cp311-cp311-win_amd64.whl", hash = "sha256:88e300d136eac057b2397aa1cfd7328b4c87c7eb66a09c7bc6a1292234db474e", size = 238089, upload-time = "2026-05-20T13:14:03.229Z" }, - { url = "https://files.pythonhosted.org/packages/d9/a9/a3c2fa886c5b94863fb0e61b3bc14610b7aa94cf4f17f8741b11708305fc/greenlet-3.5.1-cp311-cp311-win_arm64.whl", hash = "sha256:cc6ab7e555c8a112ad3a76e368e86e12a2754bcae1652a5602e133ec7b635523", size = 234989, upload-time = "2026-05-20T13:08:27.715Z" }, - { url = "https://files.pythonhosted.org/packages/c4/37/4549f149c9797c21b32c2683c33522af22522099de128b2406672526d005/greenlet-3.5.1-cp312-cp312-macosx_11_0_universal2.whl", hash = "sha256:fa4f98af3a528f0c3fd592a26df7f376f93329c8f4d987f6bb979057af8bf5e2", size = 286220, upload-time = "2026-05-20T13:07:28.463Z" }, - { url = "https://files.pythonhosted.org/packages/38/ff/a4f436709716965eaab9f36ea7b906c8a927fbe32fb1372a2071d964f6b1/greenlet-3.5.1-cp312-cp312-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ffea73584b216150eab159b6d12348fb253e68757974de1e2c40d8a318ac89ed", size = 601585, upload-time = "2026-05-20T14:00:06.141Z" }, - { url = "https://files.pythonhosted.org/packages/65/ad/54bc3fcee3ad368a61b19b67d88117f7a8c29727bf71fffdeda81fbd946e/greenlet-3.5.1-cp312-cp312-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:1072b4f9edcc1e192d9283a66a3e68d6b84c561de33a83d7858beb9ba1effe10", size = 614215, upload-time = "2026-05-20T14:05:42.675Z" }, - { url = "https://files.pythonhosted.org/packages/40/69/b91cda0647df839483201545913514c2827ebea5e5ccdf931842763bc127/greenlet-3.5.1-cp312-cp312-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:add5217d68b31130f0beca584d7fef4878327d2e31642b66618a14eef312b63b", size = 611358, upload-time = "2026-05-20T13:14:26.37Z" }, - { url = "https://files.pythonhosted.org/packages/59/90/3cf77e080350cd02fa307bb2abf05df48f4482c240275bbd2c203ba8bb1c/greenlet-3.5.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:a5ea42a752d47a145eae922b605cd1634665ac3d5ec1e72402d5048e8d60d207", size = 1570475, upload-time = "2026-05-20T14:02:25.29Z" }, - { url = "https://files.pythonhosted.org/packages/65/2c/18cece62045e74598c3c393f70dce4a63f56222015ba29a5d4eeb04f764c/greenlet-3.5.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:c5551170cf4f5ff5623e9af81323751979fee2c731e2287b61f73cd27257b823", size = 1635625, upload-time = "2026-05-20T13:14:34.027Z" }, - { url = "https://files.pythonhosted.org/packages/30/f5/310d104ddf41eb5a70f4c268d22508dfb0c3c8e86fec152be34d0d2ed819/greenlet-3.5.1-cp312-cp312-win_amd64.whl", hash = "sha256:3c8bb982ad117d29478ef8f5533e97df21f1e2befd17a299257b0c96d1371c0b", size = 238791, upload-time = "2026-05-20T13:10:39.018Z" }, - { url = "https://files.pythonhosted.org/packages/62/90/ceca11f504cd23a8047a3dea31919adc48df9b626dd0c13f0d858734fdfd/greenlet-3.5.1-cp312-cp312-win_arm64.whl", hash = "sha256:80eb4b04dadc4e67df3fae179a32c4706a3f495bc7f22fc8a81115d5f5512188", size = 235580, upload-time = "2026-05-20T13:08:45.056Z" }, - { url = "https://files.pythonhosted.org/packages/27/69/7f7e5372d998b81001899b1c0823c957aa413ba0f2662e65821611cc31e4/greenlet-3.5.1-cp313-cp313-macosx_11_0_universal2.whl", hash = "sha256:51518ff74664078fc51bffcc6fc529b0df5ae58da192691cee765d45ce944a2b", size = 285060, upload-time = "2026-05-20T13:08:51.899Z" }, - { url = "https://files.pythonhosted.org/packages/b1/bf/387f9b6b865fd2ae0d0be09e0004827295a01b71be76ed350dd1e28a91a4/greenlet-3.5.1-cp313-cp313-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1ffdb3c0bb002c99cd8f298957e046c3dbf6006b5b7cdf11a4e19194624a0a0a", size = 604370, upload-time = "2026-05-20T14:00:07.492Z" }, - { url = "https://files.pythonhosted.org/packages/32/f5/169ce3d4e4c67291bd18f8cbe0299c9f3e45102c7f1fb3c14780c93e4532/greenlet-3.5.1-cp313-cp313-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:7715a5a2c3378ba602c3a440558261e13a820bb53a82693aacd7b7f6d964e283", size = 616987, upload-time = "2026-05-20T14:05:44.237Z" }, - { url = "https://files.pythonhosted.org/packages/ee/e5/7f2e41d5273be07e77560d61ea4e56485b4d6c316d2a84518c62d1364061/greenlet-3.5.1-cp313-cp313-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:dc71ff466927a201b08305acac451ebe1aedfcea002f62f1f2f2ac2ac1e6a135", size = 613911, upload-time = "2026-05-20T13:14:27.539Z" }, - { url = "https://files.pythonhosted.org/packages/c5/a4/fbdc67579b73615a1f91615e814303cc71e06128f7baaba87be79b8fb90c/greenlet-3.5.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:cd443683db272ebaaca03af98c0b063ab30db70ea8a31a1559f35e3f7b744ccd", size = 1570689, upload-time = "2026-05-20T14:02:27.225Z" }, - { url = "https://files.pythonhosted.org/packages/e6/b4/77abbe35078be39718a46cd49caf16bceb35662f97a34101dca28aa98e47/greenlet-3.5.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:089fff7a6ce8d9316d1f65ebc00273a56be258c1725b32b94de90a3a979557e1", size = 1635602, upload-time = "2026-05-20T13:14:36.344Z" }, - { url = "https://files.pythonhosted.org/packages/37/f7/129f27ca700845b8ee8ca88ce7f43435a1239c2eddb7677fc938822762cf/greenlet-3.5.1-cp313-cp313-win_amd64.whl", hash = "sha256:110a1ca7b49b014b097f6078272c3f4ed31af45b254de5228b79adba879f6af9", size = 238683, upload-time = "2026-05-20T13:11:50.57Z" }, - { url = "https://files.pythonhosted.org/packages/6d/5c/a485a36e87df8d8fd0632ee01511244f5156a20ed3746cc6599340326395/greenlet-3.5.1-cp313-cp313-win_arm64.whl", hash = "sha256:f16ba1efc0715b680a18b8123d90dad887c6112ae3555b4b5c32c149540c6b4e", size = 235499, upload-time = "2026-05-20T13:12:42.028Z" }, - { url = "https://files.pythonhosted.org/packages/8a/cb/c62454606daf5640369c94d8a9dd540599b1bfc090e2d2180cb77f4038d2/greenlet-3.5.1-cp314-cp314-macosx_11_0_universal2.whl", hash = "sha256:d8ab31c9de8651a2facdd5c5bb0011f2380dd1a7af78ce2adf4b56095294fc07", size = 285579, upload-time = "2026-05-20T13:08:56.396Z" }, - { url = "https://files.pythonhosted.org/packages/ec/71/c4270398c2eba968a6071af1dfbdcaeee6ec1c24bc8b435b8cc452700da6/greenlet-3.5.1-cp314-cp314-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5e300185139abc337ade480c327183adf42a875ac7181bfe66d7d4efea31fbea", size = 651106, upload-time = "2026-05-20T14:00:09.448Z" }, - { url = "https://files.pythonhosted.org/packages/1a/ab/71e34b78a44ec271fb5f550c17bc46d301ddc5953890d935f270b0dcdb5a/greenlet-3.5.1-cp314-cp314-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:7ffdb990dcaa0234cf9845aead5df2e3c3a8b6507d409274dd87e0d5ab05ffc2", size = 663478, upload-time = "2026-05-20T14:05:45.88Z" }, - { url = "https://files.pythonhosted.org/packages/77/96/4efd6fa5c62c85426a0c19077a586258ebc3a2a146ff2493e4312a697a22/greenlet-3.5.1-cp314-cp314-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:2f82b3597e9d83b63408affed0b48fd0f54935edac4302237b9a837be0dae33c", size = 660800, upload-time = "2026-05-20T13:14:29.129Z" }, - { url = "https://files.pythonhosted.org/packages/7a/e0/6c71401a25cac7000261304e866a2f2cc04dc74810d40e2f118aa4799495/greenlet-3.5.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:c0141e37414c10164e702b8fb1473304221ad98f71600850c6ef7ff4880feba0", size = 1617518, upload-time = "2026-05-20T14:02:28.662Z" }, - { url = "https://files.pythonhosted.org/packages/41/26/c5c06643e8c0af9e7bf18e16cb51d0ab7625155f0392e1c9015d66d556cd/greenlet-3.5.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:50ae25a67bea74ea41fb14b960bc532df73eb713417b2d61892dced82fe8d3bc", size = 1681593, upload-time = "2026-05-20T13:14:39.417Z" }, - { url = "https://files.pythonhosted.org/packages/8a/bd/e11a108317485075e68af9d23039619b86b28130c3b50d227d42edece64b/greenlet-3.5.1-cp314-cp314-win_amd64.whl", hash = "sha256:8a17c42330e261299766b75ac1ea32caa437a9453c8f65d16a13140db378ecd3", size = 239800, upload-time = "2026-05-20T13:09:30.128Z" }, - { url = "https://files.pythonhosted.org/packages/47/f8/8e8e8417b7bf28639a5a56356ef934d0375e1d0c70a57e04d7701e870ffe/greenlet-3.5.1-cp314-cp314-win_arm64.whl", hash = "sha256:7b5f5fae05b8ac6d176a61b60c394a8cbdc2b5b91b81793066e68745cf165e54", size = 236862, upload-time = "2026-05-20T13:09:10.498Z" }, - { url = "https://files.pythonhosted.org/packages/90/12/41bf27fde4d3605d3773ae57751eda182b8be2f5398011c041173b1d9534/greenlet-3.5.1-cp314-cp314t-macosx_11_0_universal2.whl", hash = "sha256:ea8da1e900d758d078810d4255d8c6aa572181896a31ec79d779eb79c3adc9ad", size = 293637, upload-time = "2026-05-20T13:12:35.529Z" }, - { url = "https://files.pythonhosted.org/packages/44/44/ba14b23e9757707050c2f397d305bbcae62e5d7cad122f8b6baec5ae4a1f/greenlet-3.5.1-cp314-cp314t-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a19570c52a21420dcbc94e661994bc325c0b5b11304540fed514586da5dc8f2e", size = 650840, upload-time = "2026-05-20T14:00:11.079Z" }, - { url = "https://files.pythonhosted.org/packages/a8/37/5ddc2b686a6844f91abecef43411842426da2e1573f60b49ecf2547f4ae1/greenlet-3.5.1-cp314-cp314t-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:3d955c89b75eeca4723d7cc14135f393cd47c32e2a6cb4a8e4c6e760a26b0986", size = 656416, upload-time = "2026-05-20T14:05:47.118Z" }, - { url = "https://files.pythonhosted.org/packages/e1/f0/d17510297c35a2992712f0bf84de3779749999f7d3d63aa1f09db7c62dbe/greenlet-3.5.1-cp314-cp314t-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:de2daaaebd1a5aa88c49045b6baf9310b3263796bd88db713edf37cf53e7bb4e", size = 654397, upload-time = "2026-05-20T13:14:30.696Z" }, - { url = "https://files.pythonhosted.org/packages/37/eb/147387705bb89092645b012586e7273cb5ed3c90ef7eaf3a69173eaf0209/greenlet-3.5.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:3bfbd69cc349e43bf3a8ae1c85548ff0718efc887615c2db16c3833d7b0b072d", size = 1614469, upload-time = "2026-05-20T14:02:30.192Z" }, - { url = "https://files.pythonhosted.org/packages/a6/4e/37ee0da7732b7aa9896f17e15579a9df34b9fcb9dd494f0adfa749af6623/greenlet-3.5.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:4378720dd888136c27215a0214d32a4d37c3852765d45bc37aad0623423cfd78", size = 1675115, upload-time = "2026-05-20T13:14:40.972Z" }, - { url = "https://files.pythonhosted.org/packages/57/f3/97dfcf4a6eb5077f8a672234216fb5923eb89f2cab7081cb10b2cf75b605/greenlet-3.5.1-cp314-cp314t-win_amd64.whl", hash = "sha256:45718441607f9325d948db98cbc691276059316d0358c188c246da4e1d4d23d2", size = 245246, upload-time = "2026-05-20T13:12:22.646Z" }, - { url = "https://files.pythonhosted.org/packages/5d/73/d7f72e34b582f694f4a9b248162db7b09cc458a259ba8f0c0bfa1a34ea7d/greenlet-3.5.1-cp315-cp315-macosx_11_0_universal2.whl", hash = "sha256:2baee5ca02031757ffe8cc3d69f0cc0aec7065ce362622da74f32d3bcab1c541", size = 285575, upload-time = "2026-05-20T13:12:07.043Z" }, - { url = "https://files.pythonhosted.org/packages/df/59/fa9c6e87dc8ad27a95dabe2f29f372b733d05a8a67470f6c901ed9975655/greenlet-3.5.1-cp315-cp315-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:9b1ec3274918a81d3ea778b9e75b56b72b33f300edb6cf7f3a7fe1dae56683de", size = 656428, upload-time = "2026-05-20T14:00:12.556Z" }, - { url = "https://files.pythonhosted.org/packages/f6/f9/e753408871eaa61dfe35e619cfc67512b036fde99893685d50eea9e07146/greenlet-3.5.1-cp315-cp315-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:111e2390ffffc47d5840b01711dd7fac07d4c09283d0283e7f3264b14e284c64", size = 667064, upload-time = "2026-05-20T14:05:48.662Z" }, - { url = "https://files.pythonhosted.org/packages/96/27/5565b5b40389f1c7753003a07e21892fda8660926787036d5bc0308b8113/greenlet-3.5.1-cp315-cp315-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e630136e905fe5ff43e86945ae41220b6d1470956a39220e708110ac48d01ea5", size = 665697, upload-time = "2026-05-20T13:14:32.943Z" }, - { url = "https://files.pythonhosted.org/packages/cf/82/e7de4178c0c2d1c9a5a3be3cc0b33e46a85b3ee4a77c071bf7ad8600e079/greenlet-3.5.1-cp315-cp315-musllinux_1_2_aarch64.whl", hash = "sha256:975eac34b44a7077ca4d421348455b94f0f518246a7f14bc6d2fdcfe5b584368", size = 1621256, upload-time = "2026-05-20T14:02:31.91Z" }, - { url = "https://files.pythonhosted.org/packages/00/10/f2dddcf7dacac17dfc68691809589adad06135eb28930429cf58a6467a2f/greenlet-3.5.1-cp315-cp315-musllinux_1_2_x86_64.whl", hash = "sha256:9ab3c3a0b2ae6198e67c898dad5215a49f9ae0d0081b3c3ec59f333e39eeca26", size = 1685956, upload-time = "2026-05-20T13:14:42.55Z" }, - { url = "https://files.pythonhosted.org/packages/22/17/4a232b32133230ada52f70e9d7f5b65b0caef8772f01849bd8d149e7e4ca/greenlet-3.5.1-cp315-cp315-win_amd64.whl", hash = "sha256:cbfc69be86e10dcfef5b1e6269d1d6926552aa89ee39e1de3353360c1b6989ab", size = 239802, upload-time = "2026-05-20T13:13:15.481Z" }, - { url = "https://files.pythonhosted.org/packages/c2/ae/4e623a7e6d4d2a5f4cb8e4c82de4169fc637942caae68d6e676b8a128ac5/greenlet-3.5.1-cp315-cp315-win_arm64.whl", hash = "sha256:92fd6d44ac5e5a887c8a5dc4a8ba0ba908527c31c12f78c6bc7dcfe8aab279f6", size = 236853, upload-time = "2026-05-20T13:15:37.301Z" }, - { url = "https://files.pythonhosted.org/packages/7a/57/816d9cff29119da3505b3d6a5e14a8af89006ac36f47f891ff293ee05af1/greenlet-3.5.1-cp315-cp315t-macosx_11_0_universal2.whl", hash = "sha256:a6fdf2433a5441ef9a95464f7c3e674775da1c8c1177fff311cee1acad4626ed", size = 293877, upload-time = "2026-05-20T13:10:19.078Z" }, - { url = "https://files.pythonhosted.org/packages/23/a1/59b0a7c7d140ff1a75626680b9a9899b79a9176cab298b394968fb023295/greenlet-3.5.1-cp315-cp315t-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:7546556f0d649f99f6a361098a55f761181bb2ea12ff150bb16d26092ad88244", size = 655333, upload-time = "2026-05-20T14:00:14.758Z" }, - { url = "https://files.pythonhosted.org/packages/72/1b/5efe127597625042218939d01855109f352779050768b670b52edcc16a6c/greenlet-3.5.1-cp315-cp315t-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:d5ee3ea898009fa898f85f9982255d35278c477bebe185beca249cab42d4526c", size = 659443, upload-time = "2026-05-20T14:05:50.159Z" }, - { url = "https://files.pythonhosted.org/packages/6c/6d/c404246ea4d22d097a7426d0efb5b781bd7eb67715f09e79001bd552ab18/greenlet-3.5.1-cp315-cp315t-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a5c81f74d204d3edd136ebfd50dce53acbb776995d721a0fe801626cfc93b8cd", size = 658356, upload-time = "2026-05-20T13:14:35.091Z" }, - { url = "https://files.pythonhosted.org/packages/51/02/f8ee37fb6d2219329f350af241c27fcf12df57e723d11f6fc6d3bacdadaa/greenlet-3.5.1-cp315-cp315t-musllinux_1_2_aarch64.whl", hash = "sha256:2c18ef16bf6d4dd410e4dd52996888ea1497be26892fe5bbc73580aba4287b8e", size = 1619216, upload-time = "2026-05-20T14:02:33.403Z" }, - { url = "https://files.pythonhosted.org/packages/93/c5/3dc9475ace2c7a3680da12372cddd7f1ac874eb410a1ac48d3e9dab83782/greenlet-3.5.1-cp315-cp315t-musllinux_1_2_x86_64.whl", hash = "sha256:17d86354f0ae6b61bf9be5148d0dd34e06c3cb7c602c671f79f29ac3b150e659", size = 1678427, upload-time = "2026-05-20T13:14:43.71Z" }, - { url = "https://files.pythonhosted.org/packages/df/4e/750c15c317a41ffb36f0bf40b933e3d744a7dede61889f74443ea69690cf/greenlet-3.5.1-cp315-cp315t-win_amd64.whl", hash = "sha256:e7516cf6ae6b8a582c2770a0caed47b8a48373ed732c33d69a72913ae6ac923e", size = 245225, upload-time = "2026-05-20T13:13:59.366Z" }, - { url = "https://files.pythonhosted.org/packages/4f/fd/d3baea2eeb7b617efd47e87ca06e2ec2c6118d303aa9e918e0ce16eadc10/greenlet-3.5.1-cp315-cp315t-win_arm64.whl", hash = "sha256:5028648bf2253ec4745add746129d3904121fa7fe871a76bed23c5720573ce0a", size = 239590, upload-time = "2026-05-20T13:13:37.382Z" }, -] - [[package]] name = "griffelib" version = "2.0.2" @@ -1943,32 +1377,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.81.1" @@ -2030,20 +1438,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/ff/b0/4af731ff7492c68a96e4c71bfd0f4590acde92b31c6fe4894e6465c10ff6/grpcio-1.81.1-cp314-cp314-win_amd64.whl", hash = "sha256:3768a5ff1b2125e6f552e561b6b2dca0e64982d8949689b4df145cf8b98d7821", size = 5070275, upload-time = "2026-06-11T12:46:48.486Z" }, ] -[[package]] -name = "grpcio-status" -version = "1.81.1" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "googleapis-common-protos" }, - { name = "grpcio" }, - { name = "protobuf" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/32/26/0aa9168c87882381fd810d140c279a2490ed6aee655f0515d6f56c5ca404/grpcio_status-1.81.1.tar.gz", hash = "sha256:9389a03e746017b10f0630c064289201458f3ce01f5d7ef4b0bebc1ef6cf82ad", size = 13923, upload-time = "2026-06-11T12:58:48.636Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/e5/5e/5abfec5f7e89d3b7993d57cfb025ca5f968a2c18656d7fcda2b6919440b9/grpcio_status-1.81.1-py3-none-any.whl", hash = "sha256:08072fa9995f4a95c647fc6f4f85e2411573d00087bcabdf30f260114338f232", size = 14638, upload-time = "2026-06-11T12:58:31.982Z" }, -] - [[package]] name = "grpcio-tools" version = "1.81.1" @@ -2161,18 +1555,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" @@ -2743,18 +2125,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/6c/8b/bf975fabd26195915ebdf3e4252baa936f1863bcd9eb49598b705638f5d5/lunr-0.8.0-py3-none-any.whl", hash = "sha256:a2bc4e08dbb35b32723006bf2edbe6dc1f4f4b95955eea0d23165a184d276ce8", size = 35211, upload-time = "2025-03-08T13:31:38.657Z" }, ] -[[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" @@ -2923,120 +2293,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 = "more-itertools" version = "11.1.0" @@ -3619,51 +2875,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" @@ -3694,24 +2905,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" @@ -3753,21 +2946,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" @@ -4236,18 +3414,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 = "6.33.6" @@ -4286,63 +3452,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/c9/33/a7cbfccc39056a5cf8126b7aab4c8bafbedd4f0ca68ae40ecb627a2d2cd3/py_partiql_parser-0.6.3-py2.py3-none-any.whl", hash = "sha256:deb0769c3346179d2f590dcbde556f708cdb929059fb654bad75f4cf6e07f582", size = 23752, upload-time = "2025-10-18T13:56:12.256Z" }, ] -[[package]] -name = "pyarrow" -version = "24.0.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/91/13/13e1069b351bdc3881266e11147ffccf687505dbb0ea74036237f5d454a5/pyarrow-24.0.0.tar.gz", hash = "sha256:85fe721a14dd823aca09127acbb06c3ca723efbd436c004f16bca601b04dcc83", size = 1180261, upload-time = "2026-04-21T10:51:25.837Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/a5/bf/a34fee1d624152124fa8355c42f34195ad5fe5233ce5bb87946432047d52/pyarrow-24.0.0-cp310-cp310-macosx_12_0_arm64.whl", hash = "sha256:7c2b98645d576a0b9616892ead22b64a83a5f043c5e2ca15ebcefcb5b70c80cb", size = 35076681, upload-time = "2026-04-21T08:51:46.845Z" }, - { url = "https://files.pythonhosted.org/packages/1d/41/64180033d7027afce12dc96d0fe1f504c6fa112190582b458acea2399530/pyarrow-24.0.0-cp310-cp310-macosx_12_0_x86_64.whl", hash = "sha256:644a246325b8c69c595ad1dd4b463eba4b0cdb731370e4a86137d433208d6147", size = 36684260, upload-time = "2026-04-21T08:51:53.642Z" }, - { url = "https://files.pythonhosted.org/packages/57/02/9b9320e673dd8a99411fac78690f3df92f6dd6f59754c750110bca66d64e/pyarrow-24.0.0-cp310-cp310-manylinux_2_28_aarch64.whl", hash = "sha256:3a577bd840ca83f646f0a625dbc571dba7044c43c2d1503afc378b570954345c", size = 45698566, upload-time = "2026-04-21T10:46:02.133Z" }, - { url = "https://files.pythonhosted.org/packages/67/33/f75e91b9a64c3f33c787e263c93b871ad91b8a4a68c1d5cebddd9840e835/pyarrow-24.0.0-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:e3268e43984d0b1a185c89b4cfff282a7ead12fc93f56cfd7088bdbcbe727041", size = 48835562, upload-time = "2026-04-21T10:46:10.278Z" }, - { url = "https://files.pythonhosted.org/packages/a5/63/097510448e47e4091faa41c43ba92f97cecaab8f4535b56a3d149578f634/pyarrow-24.0.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:2392d954fcb920f42d230284b677605e4e2fbb11f2821e823e642abd67fbb491", size = 49394997, upload-time = "2026-04-21T10:46:18.08Z" }, - { url = "https://files.pythonhosted.org/packages/60/6b/c047d6222ab279024a062742d1807e2fbaf27bba88a98637299ff47b9236/pyarrow-24.0.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:bec9373df11544592b0ba7ec2af0e35059e5f0e7647c6183a854dedd193298f1", size = 51911424, upload-time = "2026-04-21T10:46:25.347Z" }, - { url = "https://files.pythonhosted.org/packages/3a/ba/464cc70761c2a525d97ebd84e21c31ebd47f3ef4bdcee117009f51c46f24/pyarrow-24.0.0-cp310-cp310-win_amd64.whl", hash = "sha256:c42ab9439498270139cc63e18847a02afe5c8b3ed9c931266533cfe378bd3591", size = 27251730, upload-time = "2026-04-21T10:46:30.913Z" }, - { url = "https://files.pythonhosted.org/packages/62/c9/a47ab7ece0d86cbe6678418a0fbd1ac4bb493b9184a3891dfa0e7f287ae0/pyarrow-24.0.0-cp311-cp311-macosx_12_0_arm64.whl", hash = "sha256:b0e131f880cda8d04e076cee175a46fc0e8bc8b65c99c6c09dff6669335fde74", size = 35068898, upload-time = "2026-04-21T10:46:36.599Z" }, - { url = "https://files.pythonhosted.org/packages/d1/bc/8db86617a9a58008acf8913d6fed68ea2a46acb6de928db28d724c891a68/pyarrow-24.0.0-cp311-cp311-macosx_12_0_x86_64.whl", hash = "sha256:1b2fe7f9a5566401a0ef2571f197eb92358925c1f0c8dba305d6e43ea0871bb3", size = 36679915, upload-time = "2026-04-21T10:46:42.602Z" }, - { url = "https://files.pythonhosted.org/packages/eb/8e/fb178720400ef69db251eb4a9c3ccf4af269bc1feb5055529b8fc87170d1/pyarrow-24.0.0-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:0b3537c00fb8d384f15ac1e79b6eb6db04a16514c8c1d22e59a9b95c8ba42868", size = 45697931, upload-time = "2026-04-21T10:46:48.403Z" }, - { url = "https://files.pythonhosted.org/packages/f3/27/99c42abe8e21b44f4917f62631f3aa31404882a2c41d8a4cd5c110e13d52/pyarrow-24.0.0-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:14e31a3c9e35f1ab6356c6378f6f72830e6d2d5f1791df3774a7b097d18a6a1e", size = 48837449, upload-time = "2026-04-21T10:46:55.329Z" }, - { url = "https://files.pythonhosted.org/packages/36/b6/333749e2666e9032891125bf9c691146e92901bece62030ac1430e2e7c88/pyarrow-24.0.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:b7d9a514e73bc42711e6a35aaccf3587c520024fe0a25d830a1a8a27c15f4f57", size = 49395949, upload-time = "2026-04-21T10:47:01.869Z" }, - { url = "https://files.pythonhosted.org/packages/17/25/c5201706a2dd374e8ba6ee3fd7a8c89fb7ffc16eed5217a91fd2bd7f7626/pyarrow-24.0.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:b196eb3f931862af3fa84c2a253514d859c08e0d8fe020e07be12e75a5a9780c", size = 51912986, upload-time = "2026-04-21T10:47:09.872Z" }, - { url = "https://files.pythonhosted.org/packages/f8/d2/4d1bbba65320b21a49678d6fbdc6ff7c649251359fdcfc03568c4136231d/pyarrow-24.0.0-cp311-cp311-win_amd64.whl", hash = "sha256:35405aecb474e683fb36af650618fd5340ee5471fc65a21b36076a18bbc6c981", size = 27255371, upload-time = "2026-04-21T10:47:15.943Z" }, - { url = "https://files.pythonhosted.org/packages/b4/a9/9686d9f07837f91f775e8932659192e02c74f9d8920524b480b85212cc68/pyarrow-24.0.0-cp312-cp312-macosx_12_0_arm64.whl", hash = "sha256:6233c9ed9ab9d1db47de57d9753256d9dcffbf42db341576099f0fd9f6bf4810", size = 34981559, upload-time = "2026-04-21T10:47:22.17Z" }, - { url = "https://files.pythonhosted.org/packages/80/b6/0ddf0e9b6ead3474ab087ae598c76b031fc45532bf6a63f3a553440fb258/pyarrow-24.0.0-cp312-cp312-macosx_12_0_x86_64.whl", hash = "sha256:f7616236ec1bc2b15bfdec22a71ab38851c86f8f05ff64f379e1278cf20c634a", size = 36663654, upload-time = "2026-04-21T10:47:28.315Z" }, - { url = "https://files.pythonhosted.org/packages/7c/3b/926382efe8ce27ba729071d3566ade6dfb86bdf112f366000196b2f5780a/pyarrow-24.0.0-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:1617043b99bd33e5318ae18eb2919af09c71322ef1ca46566cdafc6e6712fb66", size = 45679394, upload-time = "2026-04-21T10:47:34.821Z" }, - { url = "https://files.pythonhosted.org/packages/b3/7a/829f7d9dfd37c207206081d6dad474d81dde29952401f07f2ba507814818/pyarrow-24.0.0-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:6165461f55ef6314f026de6638d661188e3455d3ec49834556a0ebbdbace18bb", size = 48863122, upload-time = "2026-04-21T10:47:42.056Z" }, - { url = "https://files.pythonhosted.org/packages/5f/e8/f88ce625fe8babaae64e8db2d417c7653adb3019b08aae85c5ed787dc816/pyarrow-24.0.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:3b13dedfe76a0ad2d1d859b0811b53827a4e9d93a0bcb05cf59333ab4980cc7e", size = 49376032, upload-time = "2026-04-21T10:47:48.967Z" }, - { url = "https://files.pythonhosted.org/packages/36/7a/82c363caa145fff88fb475da50d3bf52bb024f61917be5424c3392eaf878/pyarrow-24.0.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:25ea65d868eb04015cd18e6df2fbe98f07e5bda2abefabcb88fce39a947716f6", size = 51929490, upload-time = "2026-04-21T10:47:55.981Z" }, - { url = "https://files.pythonhosted.org/packages/66/1c/e3e72c8014ad2743ca64a701652c733cc5cbcee15c0463a32a8c55518d9e/pyarrow-24.0.0-cp312-cp312-win_amd64.whl", hash = "sha256:295f0a7f2e242dabd513737cf076007dc5b2d59237e3eca37b05c0c6446f3826", size = 27355660, upload-time = "2026-04-21T10:48:01.718Z" }, - { url = "https://files.pythonhosted.org/packages/6f/d3/a1abf004482026ddc17f4503db227787fa3cfe41ec5091ff20e4fea55e57/pyarrow-24.0.0-cp313-cp313-macosx_12_0_arm64.whl", hash = "sha256:02b001b3ed4723caa44f6cd1af2d5c86aa2cf9971dacc2ffa55b21237713dfba", size = 34976759, upload-time = "2026-04-21T10:48:07.258Z" }, - { url = "https://files.pythonhosted.org/packages/4f/4a/34f0a36d28a2dd32225301b79daad44e243dc1a2bb77d43b60749be255c4/pyarrow-24.0.0-cp313-cp313-macosx_12_0_x86_64.whl", hash = "sha256:04920d6a71aabd08a0417709efce97d45ea8e6fb733d9ca9ecffb13c67839f68", size = 36658471, upload-time = "2026-04-21T10:48:13.347Z" }, - { url = "https://files.pythonhosted.org/packages/1f/78/543b94712ae8bb1a6023bcc1acf1a740fbff8286747c289cd9468fced2a5/pyarrow-24.0.0-cp313-cp313-manylinux_2_28_aarch64.whl", hash = "sha256:a964266397740257f16f7bb2e4f08a0c81454004beab8ff59dd531b73610e9f2", size = 45675981, upload-time = "2026-04-21T10:48:20.201Z" }, - { url = "https://files.pythonhosted.org/packages/84/9f/8fb7c222b100d314137fa40ec050de56cd8c6d957d1cfff685ce72f15b17/pyarrow-24.0.0-cp313-cp313-manylinux_2_28_x86_64.whl", hash = "sha256:6f066b179d68c413374294bc1735f68475457c933258df594443bb9d88ddc2a0", size = 48859172, upload-time = "2026-04-21T10:48:27.541Z" }, - { url = "https://files.pythonhosted.org/packages/a7/d3/1ea72538e6c8b3b475ed78d1049a2c518e655761ea50fe1171fc855fcab7/pyarrow-24.0.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:1183baeb14c5f587b1ec52831e665718ce632caab84b7cd6b85fd44f96114495", size = 49385733, upload-time = "2026-04-21T10:48:34.7Z" }, - { url = "https://files.pythonhosted.org/packages/c3/be/c3d8b06a1ba35f2260f8e1f771abbee7d5e345c0937aab90675706b1690a/pyarrow-24.0.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:806f24b4085453c197a5078218d1ee08783ebbba271badd153d1ae22a3ee804f", size = 51934335, upload-time = "2026-04-21T10:48:42.099Z" }, - { url = "https://files.pythonhosted.org/packages/9c/62/89e07a1e7329d2cde3e3c6994ba0839a24977a2beda8be6005ea3d860b99/pyarrow-24.0.0-cp313-cp313-win_amd64.whl", hash = "sha256:e4505fc6583f7b05ab854934896bcac8253b04ac1171a77dfb73efef92076d91", size = 27271748, upload-time = "2026-04-21T10:49:42.532Z" }, - { url = "https://files.pythonhosted.org/packages/17/1a/cff3a59f80b5b1658549d46611b67163f65e0664431c076ad728bf9d5af4/pyarrow-24.0.0-cp313-cp313t-macosx_12_0_arm64.whl", hash = "sha256:1a4e45017efbf115032e4475ee876d525e0e36c742214fbe405332480ecd6275", size = 35238554, upload-time = "2026-04-21T10:48:48.526Z" }, - { url = "https://files.pythonhosted.org/packages/a8/99/cce0f42a327bfef2c420fb6078a3eb834826e5d6697bf3009fe11d2ad051/pyarrow-24.0.0-cp313-cp313t-macosx_12_0_x86_64.whl", hash = "sha256:7986f1fa71cee060ad00758bcc79d3a93bab8559bf978fab9e53472a2e25a17b", size = 36782301, upload-time = "2026-04-21T10:48:55.181Z" }, - { url = "https://files.pythonhosted.org/packages/2a/66/8e560d5ff6793ca29aca213c53eec0dd482dd46cb93b2819e5aab52e4252/pyarrow-24.0.0-cp313-cp313t-manylinux_2_28_aarch64.whl", hash = "sha256:d3e0b61e8efb24ed38898e5cdc5fffa9124be480008d401a1f8071500494ae42", size = 45721929, upload-time = "2026-04-21T10:49:03.676Z" }, - { url = "https://files.pythonhosted.org/packages/27/0c/a26e25505d030716e078d9f16eb74973cbf0b33b672884e9f9da1c83b871/pyarrow-24.0.0-cp313-cp313t-manylinux_2_28_x86_64.whl", hash = "sha256:55a3bc1e3df3b5567b7d27ef551b2283f0c68a5e86f1cd56abc569da4f31335b", size = 48825365, upload-time = "2026-04-21T10:49:11.714Z" }, - { url = "https://files.pythonhosted.org/packages/5f/eb/771f9ecb0c65e73fe9dccdd1717901b9594f08c4515d000c7c62df573811/pyarrow-24.0.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:641f795b361874ac9da5294f8f443dfdbee355cf2bd9e3b8d97aaac2306b9b37", size = 49451819, upload-time = "2026-04-21T10:49:21.474Z" }, - { url = "https://files.pythonhosted.org/packages/48/da/61ae89a88732f5a785646f3ec6125dbb640fa98a540eb2b9889caa561403/pyarrow-24.0.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:8adc8e6ce5fccf5dc707046ae4914fd537def529709cc0d285d37a7f9cd442ca", size = 51909252, upload-time = "2026-04-21T10:49:31.164Z" }, - { url = "https://files.pythonhosted.org/packages/cb/1a/8dd5cafab7b66573fa91c03d06d213356ad4edd71813aa75e08ce2b3a844/pyarrow-24.0.0-cp313-cp313t-win_amd64.whl", hash = "sha256:9b18371ad2f44044b81a8d23bc2d8a9b6a6226dca775e8e16cfee640473d6c5d", size = 27388127, upload-time = "2026-04-21T10:49:37.334Z" }, - { url = "https://files.pythonhosted.org/packages/ad/80/d022a34ff05d2cbedd8ccf841fc1f532ecfa9eb5ed1711b56d0e0ea71fc9/pyarrow-24.0.0-cp314-cp314-macosx_12_0_arm64.whl", hash = "sha256:1cc9057f0319e26333b357e17f3c2c022f1a83739b48a88b25bfd5fa2dc18838", size = 35007997, upload-time = "2026-04-21T10:49:48.796Z" }, - { url = "https://files.pythonhosted.org/packages/1a/ff/f01485fda6f4e5d441afb8dd5e7681e4db18826c1e271852f5d3957d6a80/pyarrow-24.0.0-cp314-cp314-macosx_12_0_x86_64.whl", hash = "sha256:e6f1278ee4785b6db21229374a1c9e54ec7c549de5d1efc9630b6207de7e170b", size = 36678720, upload-time = "2026-04-21T10:49:55.858Z" }, - { url = "https://files.pythonhosted.org/packages/9e/c2/2d2d5fea814237923f71b36495211f20b43a1576f9a4d6da7e751a64ec6f/pyarrow-24.0.0-cp314-cp314-manylinux_2_28_aarch64.whl", hash = "sha256:adbbedc55506cbdabb830890444fb856bfb0060c46c6f8026c6c2f2cf86ae795", size = 45741852, upload-time = "2026-04-21T10:50:04.624Z" }, - { url = "https://files.pythonhosted.org/packages/8e/3a/28ba9c1c1ebdbb5f1b94dfebb46f207e52e6a554b7fe4132540fde29a3a0/pyarrow-24.0.0-cp314-cp314-manylinux_2_28_x86_64.whl", hash = "sha256:ae8a1145af31d903fa9bb166824d7abe9b4681a000b0159c9fb99c11bc11ad26", size = 48889852, upload-time = "2026-04-21T10:50:12.293Z" }, - { url = "https://files.pythonhosted.org/packages/df/51/4a389acfd31dca009f8fb82d7f510bb4130f2b3a8e18cf00194d0687d8ac/pyarrow-24.0.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:d7027eba1df3b2069e2e8d80f644fa0918b68c46432af3d088ddd390d063ecde", size = 49445207, upload-time = "2026-04-21T10:50:20.677Z" }, - { url = "https://files.pythonhosted.org/packages/19/4b/0bab2b23d2ae901b1b9a03c0efd4b2d070256f8ce3fc43f6e58c167b2081/pyarrow-24.0.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:e56a1ffe9bf7b727432b89104cc0849c21582949dd7bdcb34f17b2001a351a76", size = 51954117, upload-time = "2026-04-21T10:50:29.14Z" }, - { url = "https://files.pythonhosted.org/packages/29/88/f4e9145da0417b3d2c12035a8492b35ff4a3dbc653e614fcfb51d9dedb38/pyarrow-24.0.0-cp314-cp314-win_amd64.whl", hash = "sha256:38be1808cdd068605b787e6ca9119b27eb275a0234e50212c3492331680c3b1e", size = 28001155, upload-time = "2026-04-21T10:51:22.337Z" }, - { url = "https://files.pythonhosted.org/packages/79/4f/46a49a63f43526da895b1a45bbb51d5baf8e4d77159f8528fc3e5490007f/pyarrow-24.0.0-cp314-cp314t-macosx_12_0_arm64.whl", hash = "sha256:418e48ce50a45a6a6c73c454677203a9c75c966cb1e92ca3370959185f197a05", size = 35250387, upload-time = "2026-04-21T10:50:35.552Z" }, - { url = "https://files.pythonhosted.org/packages/a0/da/d5e0cd5ef00796922404806d5f00325cdadc3441ce2c13fe7115f2df9a64/pyarrow-24.0.0-cp314-cp314t-macosx_12_0_x86_64.whl", hash = "sha256:2f16197705a230a78270cdd4ea8a1d57e86b2fdcbc34a1f6aebc72e65c986f9a", size = 36797102, upload-time = "2026-04-21T10:50:42.417Z" }, - { url = "https://files.pythonhosted.org/packages/34/c7/5904145b0a593a05236c882933d439b5720f0a145381179063722fbfc123/pyarrow-24.0.0-cp314-cp314t-manylinux_2_28_aarch64.whl", hash = "sha256:fb24ac194bfc5e86839d7dcd52092ee31e5fe6733fe11f5e3b06ef0812b20072", size = 45745118, upload-time = "2026-04-21T10:50:49.324Z" }, - { url = "https://files.pythonhosted.org/packages/13/d3/cca42fe166d1c6e4d5b80e530b7949104d10e17508a90ae202dac205ce2a/pyarrow-24.0.0-cp314-cp314t-manylinux_2_28_x86_64.whl", hash = "sha256:9700ebd9a51f5895ce75ff4ac4b3c47a7d4b42bc618be8e713e5d56bacf5f931", size = 48844765, upload-time = "2026-04-21T10:50:55.579Z" }, - { url = "https://files.pythonhosted.org/packages/b0/49/942c3b79878ba928324d1e17c274ed84581db8c0a749b24bcf4cbdf15bd3/pyarrow-24.0.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:d8ddd2768da81d3ee08cfea9b597f4abb4e8e1dc8ae7e204b608d23a0d3ab699", size = 49471890, upload-time = "2026-04-21T10:51:02.439Z" }, - { url = "https://files.pythonhosted.org/packages/76/97/ff71431000a75d84135a1ace5ca4ba11726a231a8007bbb320a4c54075d5/pyarrow-24.0.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:61a3d7eaa97a14768b542f3d284dc6400dd2470d9f080708b13cd46b6ae18136", size = 51932250, upload-time = "2026-04-21T10:51:10.576Z" }, - { url = "https://files.pythonhosted.org/packages/51/be/6f79d55816d5c22557cf27533543d5d70dfe692adfbee4b99f2760674f38/pyarrow-24.0.0-cp314-cp314t-win_amd64.whl", hash = "sha256:c91d00057f23b8d353039520dc3a6c09d8608164c692e9f59a175a42b2ae0c19", size = 28131282, upload-time = "2026-04-21T10:51:16.815Z" }, -] - [[package]] name = "pyasn1" version = "0.6.3" @@ -5464,84 +4573,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" @@ -5557,15 +4588,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]] @@ -5651,6 +4682,9 @@ aioboto3 = [ google-adk = [ { name = "google-adk" }, ] +google-genai = [ + { name = "google-genai" }, +] grpc = [ { name = "grpcio" }, ] @@ -5694,6 +4728,7 @@ dev = [ { name = "langsmith" }, { name = "litellm" }, { name = "maturin" }, + { name = "mcp" }, { name = "moto", extra = ["s3", "server"] }, { name = "mypy" }, { name = "mypy-protobuf" }, @@ -5727,7 +4762,8 @@ dev = [ [package.metadata] requires-dist = [ { name = "aioboto3", marker = "extra == 'aioboto3'", specifier = ">=10.4.0" }, - { name = "google-adk", marker = "extra == 'google-adk'", specifier = ">=1.27.0,<2" }, + { name = "google-adk", marker = "extra == 'google-adk'", specifier = ">=2.2.0,<3" }, + { name = "google-genai", marker = "extra == 'google-genai'", specifier = ">=2.10.0,<3.0.0" }, { name = "grpcio", marker = "extra == 'grpc'", specifier = ">=1.48.2,<2" }, { name = "langgraph", marker = "extra == 'langgraph'", specifier = ">=1.1.0" }, { name = "langsmith", marker = "extra == 'langsmith'", specifier = ">=0.7.34,<0.9" }, @@ -5749,7 +4785,7 @@ requires-dist = [ { name = "types-protobuf", specifier = ">=3.20,<8.0.0" }, { name = "typing-extensions", specifier = ">=4.2.0,<5" }, ] -provides-extras = ["grpc", "opentelemetry", "pydantic", "openai-agents", "google-adk", "langgraph", "langsmith", "lambda-worker-otel", "aioboto3", "strands-agents"] +provides-extras = ["grpc", "opentelemetry", "pydantic", "openai-agents", "google-adk", "langgraph", "langsmith", "lambda-worker-otel", "aioboto3", "google-genai", "strands-agents"] [package.metadata.requires-dev] dev = [ @@ -5763,6 +4799,7 @@ dev = [ { name = "langsmith", specifier = ">=0.7.34,<0.9" }, { name = "litellm", specifier = ">=1.83.0" }, { name = "maturin", specifier = ">=1.8.2" }, + { name = "mcp", specifier = ">=1.9.4,<2" }, { name = "moto", extras = ["s3", "server"], specifier = ">=5" }, { name = "mypy", specifier = "==1.18.2" }, { name = "mypy-protobuf", specifier = ">=3.3.0,<4" }, @@ -6132,15 +5169,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/1d/70/5771c9ecbdb7cc0c3f3bbded7e0fa7911ee8e872ce5b5dc48ce7dce21a11/tzlocal-5.4-py3-none-any.whl", hash = "sha256:024d11221ff83453eae1f608f09b145b9779e1345d08c15404ce8ff7917cf629", size = 28261, upload-time = "2026-06-15T12:06:54.914Z" }, ] -[[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" From aa26c8d12e8ebc32294398460acd6656042b393a Mon Sep 17 00:00:00 2001 From: brucearctor <5032356+brucearctor@users.noreply.github.com> Date: Fri, 10 Jul 2026 09:23:47 -0700 Subject: [PATCH 158/226] fix: use functools.wraps in activity_tool to preserve metadata (#1636) Replace manual metadata copying with @functools.wraps(activity_def) to preserve __annotations__, __module__, __qualname__, and __dict__ on the wrapper function. These are needed by ADK's tool schema generation (specifically _handle_params_as_deferred_annotations) to resolve type hints from the original activity function. Also adds test_activity_tool_preserves_metadata verifying that __name__, __doc__, __annotations__, __module__, and __signature__ are all correctly preserved on the wrapper. Fixes #1635 Co-authored-by: Brian Strauch --- .../contrib/google_adk_agents/workflow.py | 7 ++-- .../test_google_adk_agents.py | 39 +++++++++++++++++++ 2 files changed, 43 insertions(+), 3 deletions(-) diff --git a/temporalio/contrib/google_adk_agents/workflow.py b/temporalio/contrib/google_adk_agents/workflow.py index 274dde807..b1d150391 100644 --- a/temporalio/contrib/google_adk_agents/workflow.py +++ b/temporalio/contrib/google_adk_agents/workflow.py @@ -1,5 +1,6 @@ """Workflow utilities for Google ADK agents integration with Temporal.""" +import functools import inspect from typing import Any, Callable @@ -18,6 +19,7 @@ def activity_tool(activity_def: Callable, **kwargs: Any) -> Callable: while marking it as a tool that executes via 'workflow.execute_activity'. """ + @functools.wraps(activity_def) async def wrapper(*args: Any, **kw: Any): # Inspect signature to bind arguments sig = inspect.signature(activity_def) @@ -48,9 +50,8 @@ async def wrapper(*args: Any, **kw: Any): activity_def, args=activity_args, **options ) - # Copy metadata - wrapper.__name__ = activity_def.__name__ - wrapper.__doc__ = activity_def.__doc__ + # functools.wraps copies name/doc/module/annotations/qualname/dict. + # Signature must be set explicitly since the wrapper uses *args/**kw. setattr(wrapper, "__signature__", inspect.signature(activity_def)) return wrapper diff --git a/tests/contrib/google_adk_agents/test_google_adk_agents.py b/tests/contrib/google_adk_agents/test_google_adk_agents.py index 64da07103..7be7ec8c6 100644 --- a/tests/contrib/google_adk_agents/test_google_adk_agents.py +++ b/tests/contrib/google_adk_agents/test_google_adk_agents.py @@ -14,6 +14,7 @@ """Integration tests for ADK Temporal support.""" +import inspect import json import logging import os @@ -1119,3 +1120,41 @@ def test_explicitly_set_none_preserved() -> None: assert "cache_config" in serialized, "Explicitly-set None should be preserved" assert serialized["cache_config"] is None + + +def test_activity_tool_preserves_metadata() -> None: + """activity_tool wrapper preserves the original function's metadata. + + This ensures ADK's tool schema generation can inspect __annotations__ + and __module__ on the wrapper, which are needed by + ``_handle_params_as_deferred_annotations`` to resolve type hints. + """ + + @activity.defn + async def my_activity(city: str, count: int = 1) -> str: + """Get info for a city.""" + return f"{city}: {count}" + + tool = temporalio.contrib.google_adk_agents.workflow.activity_tool( + my_activity, start_to_close_timeout=timedelta(seconds=30) + ) + + # __name__ and __doc__ + assert tool.__name__ == "my_activity" + assert tool.__doc__ == "Get info for a city." + + # __annotations__ — critical for ADK type introspection + assert "city" in tool.__annotations__ + assert tool.__annotations__["city"] is str + assert tool.__annotations__["count"] is int + assert tool.__annotations__["return"] is str + + # __module__ — needed by _handle_params_as_deferred_annotations + assert tool.__module__ == my_activity.__module__ + + # __signature__ — must match the original, not *args/**kw + sig = inspect.signature(tool) + params = list(sig.parameters.keys()) + assert params == ["city", "count"] + assert sig.parameters["city"].annotation is str + assert sig.parameters["count"].default == 1 From 9312b9df2f724972429eec72b16265c02a1145ac Mon Sep 17 00:00:00 2001 From: Spencer Judge Date: Mon, 13 Jul 2026 08:36:22 -0700 Subject: [PATCH 159/226] Add musl/alpine support (#1634) --- .../actions/alpine-package-smoke/action.yml | 72 +++++++++++++++++++ .github/scripts/release_verify.py | 6 +- .github/workflows/ci.yml | 29 ++++++++ .github/workflows/release-publish.yml | 70 ++++++++++++++++++ pyproject.toml | 10 ++- scripts/cibuildwheel_before_all_linux.sh | 13 ++++ scripts/cibuildwheel_before_build_linux.sh | 8 +++ 7 files changed, 203 insertions(+), 5 deletions(-) create mode 100644 .github/actions/alpine-package-smoke/action.yml create mode 100644 scripts/cibuildwheel_before_all_linux.sh create mode 100644 scripts/cibuildwheel_before_build_linux.sh diff --git a/.github/actions/alpine-package-smoke/action.yml b/.github/actions/alpine-package-smoke/action.yml new file mode 100644 index 000000000..ad72f2eb9 --- /dev/null +++ b/.github/actions/alpine-package-smoke/action.yml @@ -0,0 +1,72 @@ +name: Alpine package smoke test +description: Install a local or published temporalio package in Alpine and run a minimal SDK workflow. +inputs: + wheel-dir: + description: "Directory containing local wheel files to install" + required: false + default: "" + version: + description: "Published package version to install and verify" + required: false + default: "" + index-url: + description: "Primary package index URL for published package installs" + required: false + default: "" + dependency-index-url: + description: "Optional dependency package index URL for published package installs" + required: false + default: "" + python-image: + description: "Alpine Python Docker image" + required: false + default: "python:3.10-alpine" +runs: + using: composite + steps: + - name: Install package and run SDK smoke test + shell: bash + env: + WHEEL_DIR: ${{ inputs.wheel-dir }} + VERSION: ${{ inputs.version }} + INDEX_URL: ${{ inputs.index-url }} + DEPENDENCY_INDEX_URL: ${{ inputs.dependency-index-url }} + PYTHON_IMAGE: ${{ inputs.python-image }} + run: | + set -euo pipefail + + if [[ -z "$WHEEL_DIR" && ( -z "$VERSION" || -z "$INDEX_URL" ) ]]; then + echo "Either wheel-dir or both version and index-url must be provided" >&2 + exit 1 + fi + + docker run --rm -v "$(pwd):/workspace" -w /tmp \ + -e WHEEL_DIR="$WHEEL_DIR" \ + -e VERSION="$VERSION" \ + -e INDEX_URL="$INDEX_URL" \ + -e DEPENDENCY_INDEX_URL="$DEPENDENCY_INDEX_URL" \ + "$PYTHON_IMAGE" sh -c ' + set -eu + python -m venv /tmp/alpine-smoke + /tmp/alpine-smoke/bin/python -m pip install --upgrade pip + + if [ -n "$WHEEL_DIR" ]; then + /tmp/alpine-smoke/bin/python -m pip install --prefer-binary /workspace/$WHEEL_DIR/*.whl + elif [ -n "$DEPENDENCY_INDEX_URL" ]; then + /tmp/alpine-smoke/bin/python /workspace/.github/scripts/install_release_package.py \ + --version "$VERSION" \ + --index-url "$INDEX_URL" \ + --dependency-index-url "$DEPENDENCY_INDEX_URL" + else + /tmp/alpine-smoke/bin/python /workspace/.github/scripts/install_release_package.py \ + --version "$VERSION" \ + --index-url "$INDEX_URL" + fi + + if [ -z "$VERSION" ]; then + VERSION=$(/tmp/alpine-smoke/bin/python -c "import importlib.metadata; print(importlib.metadata.version(\"temporalio\"))") + export VERSION + fi + + /tmp/alpine-smoke/bin/python /workspace/.github/scripts/release_smoke_package.py + ' diff --git a/.github/scripts/release_verify.py b/.github/scripts/release_verify.py index 390252854..280b2049e 100644 --- a/.github/scripts/release_verify.py +++ b/.github/scripts/release_verify.py @@ -75,9 +75,9 @@ def verify_dist(args: argparse.Namespace) -> None: expected_sdist = f"temporalio-{args.version}.tar.gz" if sdists != [expected_sdist]: raise RuntimeError(f"Expected only sdist {expected_sdist!r}, found {sdists!r}") - if len(wheels) != 5: + if len(wheels) != 7: raise RuntimeError( - f"Expected 5 platform wheels, found {len(wheels)}: {wheels!r}" + f"Expected 7 platform wheels, found {len(wheels)}: {wheels!r}" ) for name in files: @@ -90,6 +90,8 @@ def verify_dist(args: argparse.Namespace) -> None: expected_platforms = { "linux-x86_64": lambda name: "manylinux" in name and "x86_64" in name, "linux-aarch64": lambda name: "manylinux" in name and "aarch64" in name, + "linux-musl-x86_64": lambda name: "musllinux" in name and "x86_64" in name, + "linux-musl-aarch64": lambda name: "musllinux" in name and "aarch64" in name, "macos-x86_64": lambda name: "macosx" in name and "x86_64" in name, "macos-arm64": lambda name: "macosx" in name and "arm64" in name, "windows-amd64": lambda name: "win_amd64" in name, diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 55eb7eb56..86dbe6253 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -100,6 +100,35 @@ jobs: npx doctoc README.md [[ -z $(git status --porcelain README.md) ]] || (git diff README.md; echo "README changed"; exit 1) + alpine-package-test: + timeout-minutes: 60 + strategy: + fail-fast: false + matrix: + include: + - cibw-build: cp310-musllinux_x86_64 + runsOn: ubuntu-latest + - cibw-build: cp310-musllinux_aarch64 + runsOn: ubuntu-24.04-arm64-2-core + runs-on: ${{ matrix.runsOn }} + steps: + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 + with: + submodules: recursive + - uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5 + with: + python-version: "3.14" + - uses: astral-sh/setup-uv@cec208311dfd045dd5311c1add060b2062131d57 # v8 + - run: uv sync --all-extras + - name: Build Alpine wheel + run: uv run cibuildwheel --output-dir dist + env: + CIBW_BUILD: ${{ matrix.cibw-build }} + - name: Test Alpine wheel + uses: ./.github/actions/alpine-package-smoke + with: + wheel-dir: dist + check-protos: timeout-minutes: 30 runs-on: ubuntu-latest diff --git a/.github/workflows/release-publish.yml b/.github/workflows/release-publish.yml index 3be7ad849..d745804a8 100644 --- a/.github/workflows/release-publish.yml +++ b/.github/workflows/release-publish.yml @@ -20,17 +20,29 @@ jobs: include: - os: ubuntu-latest package-suffix: linux-amd64 + cibw-build: cp310-manylinux_x86_64 - os: ubuntu-arm package-suffix: linux-aarch64 + cibw-build: cp310-manylinux_aarch64 + runsOn: ubuntu-24.04-arm64-2-core + - os: ubuntu-latest + package-suffix: linux-musl-amd64 + cibw-build: cp310-musllinux_x86_64 + - os: ubuntu-arm + package-suffix: linux-musl-aarch64 + cibw-build: cp310-musllinux_aarch64 runsOn: ubuntu-24.04-arm64-2-core - os: macos-intel package-suffix: macos-amd64 + cibw-build: cp310-macosx_x86_64 runsOn: macos-15-intel - os: macos-arm package-suffix: macos-aarch64 + cibw-build: cp310-macosx_arm64 runsOn: macos-14 - os: windows-latest package-suffix: windows-amd64 + cibw-build: cp310-win_amd64 runs-on: ${{ matrix.runsOn || matrix.os }} permissions: contents: read @@ -63,9 +75,12 @@ jobs: # Build the wheel - run: uv run cibuildwheel --output-dir dist + env: + CIBW_BUILD: ${{ matrix.cibw-build }} # Install the wheel in a new venv and run a test - name: Test wheel + if: ${{ !contains(matrix.package-suffix, 'musl') }} shell: bash run: | mkdir __test_wheel__ @@ -80,6 +95,12 @@ jobs: ./.venv/$bindir/pip install --prefer-binary ../dist/*.whl ./.venv/$bindir/python -m pytest -s tests/worker/test_workflow.py -k test_workflow_hello + - name: Test Alpine wheel + if: ${{ contains(matrix.package-suffix, 'musl') }} + uses: ./.github/actions/alpine-package-smoke + with: + wheel-dir: dist + # Upload dist - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4 with: @@ -200,11 +221,36 @@ jobs: index-url: https://test.pypi.org/simple/ dependency-index-url: https://pypi.org/simple/ + smoke_testpypi_alpine: + name: Smoke test TestPyPI package on Alpine (${{ matrix.arch }}) + needs: + - verify_artifacts + - publish_testpypi + strategy: + fail-fast: false + matrix: + include: + - arch: x64 + runsOn: ubuntu-latest + - arch: arm64 + runsOn: ubuntu-24.04-arm64-2-core + runs-on: ${{ matrix.runsOn }} + timeout-minutes: 10 + steps: + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 + - name: Install and load package + uses: ./.github/actions/alpine-package-smoke + with: + version: ${{ needs.verify_artifacts.outputs.version }} + index-url: https://test.pypi.org/simple/ + dependency-index-url: https://pypi.org/simple/ + publish_pypi: name: Publish to PyPI needs: - verify_artifacts - smoke_testpypi + - smoke_testpypi_alpine runs-on: ubuntu-latest timeout-minutes: 10 environment: pypi @@ -247,11 +293,35 @@ jobs: version: ${{ needs.verify_artifacts.outputs.version }} index-url: https://pypi.org/simple/ + smoke_pypi_alpine: + name: Smoke test PyPI package on Alpine (${{ matrix.arch }}) + needs: + - verify_artifacts + - publish_pypi + strategy: + fail-fast: false + matrix: + include: + - arch: x64 + runsOn: ubuntu-latest + - arch: arm64 + runsOn: ubuntu-24.04-arm64-2-core + runs-on: ${{ matrix.runsOn }} + timeout-minutes: 10 + steps: + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 + - name: Install and load package + uses: ./.github/actions/alpine-package-smoke + with: + version: ${{ needs.verify_artifacts.outputs.version }} + index-url: https://pypi.org/simple/ + create_draft_release: name: Create draft GitHub Release needs: - verify_artifacts - smoke_pypi + - smoke_pypi_alpine runs-on: ubuntu-latest timeout-minutes: 5 permissions: diff --git a/pyproject.toml b/pyproject.toml index 9017519b2..bcad8903c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -153,17 +153,21 @@ filterwarnings = [ [tool.cibuildwheel] before-all = "pip install protoc-wheel-0" -build = "cp310-win_amd64 cp310-manylinux_x86_64 cp310-manylinux_aarch64 cp310-macosx_x86_64 cp310-macosx_arm64" +build = "cp310-win_amd64 cp310-manylinux_x86_64 cp310-manylinux_aarch64 cp310-musllinux_x86_64 cp310-musllinux_aarch64 cp310-macosx_x86_64 cp310-macosx_arm64" build-verbosity = 1 [tool.cibuildwheel.macos] environment = { MACOSX_DEPLOYMENT_TARGET = "10.12" } [tool.cibuildwheel.linux] -before-all = "curl https://sh.rustup.rs -sSf | sh -s -- --default-toolchain stable -y && yum install -y openssl-devel" -before-build = "pip install protoc-wheel-0" +before-all = "sh scripts/cibuildwheel_before_all_linux.sh" +before-build = "sh scripts/cibuildwheel_before_build_linux.sh" environment = { PATH = "$PATH:$HOME/.cargo/bin", CARGO_NET_GIT_FETCH_WITH_CLI = "true" } +[[tool.cibuildwheel.overrides]] +select = "*musllinux*" +environment = { PATH = "$PATH:$HOME/.cargo/bin", CARGO_NET_GIT_FETCH_WITH_CLI = "true", RUSTFLAGS = "-C target-feature=-crt-static" } + [tool.mypy] ignore_missing_imports = true exclude = [ diff --git a/scripts/cibuildwheel_before_all_linux.sh b/scripts/cibuildwheel_before_all_linux.sh new file mode 100644 index 000000000..be9b08986 --- /dev/null +++ b/scripts/cibuildwheel_before_all_linux.sh @@ -0,0 +1,13 @@ +#!/bin/sh +set -eu + +if command -v apk >/dev/null 2>&1; then + apk add --no-cache build-base curl openssl-dev protobuf-dev +elif command -v yum >/dev/null 2>&1; then + yum install -y openssl-devel +else + echo "Unsupported Linux image: expected apk or yum" >&2 + exit 1 +fi + +curl https://sh.rustup.rs -sSf | sh -s -- --default-toolchain stable -y diff --git a/scripts/cibuildwheel_before_build_linux.sh b/scripts/cibuildwheel_before_build_linux.sh new file mode 100644 index 000000000..838c7dd72 --- /dev/null +++ b/scripts/cibuildwheel_before_build_linux.sh @@ -0,0 +1,8 @@ +#!/bin/sh +set -eu + +if command -v protoc >/dev/null 2>&1; then + protoc --version +else + pip install protoc-wheel-0 +fi From a8544530a8efc85c01250793b0ee3862704049f6 Mon Sep 17 00:00:00 2001 From: Christopher Constable Date: Mon, 13 Jul 2026 15:00:09 -0400 Subject: [PATCH 160/226] Update extstore s3 driver key percent encoding to be consistent with other SDKs and S3's safe character guidelines. (#1637) --- temporalio/contrib/aws/s3driver/README.md | 18 ++++- temporalio/contrib/aws/s3driver/_driver.py | 40 +++++++--- tests/contrib/aws/s3driver/test_s3driver.py | 82 +++++++++++++++++++++ 3 files changed, 126 insertions(+), 14 deletions(-) diff --git a/temporalio/contrib/aws/s3driver/README.md b/temporalio/contrib/aws/s3driver/README.md index 73b9b3299..7494e4b96 100644 --- a/temporalio/contrib/aws/s3driver/README.md +++ b/temporalio/contrib/aws/s3driver/README.md @@ -58,9 +58,23 @@ driver = S3StorageDriver(client=MyS3Client(), bucket="my-temporal-payloads") ### Key structure -Payloads are stored under content-addressable keys derived from a SHA-256 hash of the serialized payload bytes, segmented by namespace and workflow/activity identifiers when serialization context is available, e.g.: +Payloads are stored under content-addressable keys derived from a SHA-256 hash of the serialized payload bytes, segmented by namespace and workflow/activity identifiers when serialization context is available. - v0/ns/my-namespace/wfi/my-workflow-id/d/sha256/ +Workflow key: + + v0/ns/{namespace}/wt/{workflow-type}/wi/{workflow-id}/ri/{run-id}/d/{hash-algorithm}/{hex-digest} + +Activity key: + + v0/ns/{namespace}/at/{activity-type}/ai/{activity-id}/ri/{run-id}/d/{hash-algorithm}/{hex-digest} + +Fallback key (used when no namespace, workflow, or activity information is available): + + v0/d/{hash-algorithm}/{hex-digest} + +- Missing values (including a missing run ID) are encoded as the literal `null`. +- `hex-digest` is the lower-case SHA-256 hex digest (64 characters). +- Dynamic path segments are percent-encoded: any byte outside S3's [safe character set](https://docs.aws.amazon.com/AmazonS3/latest/userguide/object-keys.html) (`0-9`, `a-z`, `A-Z`, and `! - _ . * ' ( )`) is escaped as `%XX` over its UTF-8 bytes. ### Notes diff --git a/temporalio/contrib/aws/s3driver/_driver.py b/temporalio/contrib/aws/s3driver/_driver.py index 445bfda8a..4bcf9de25 100644 --- a/temporalio/contrib/aws/s3driver/_driver.py +++ b/temporalio/contrib/aws/s3driver/_driver.py @@ -8,7 +8,7 @@ import asyncio import hashlib -import urllib.parse +import string from collections.abc import Callable, Coroutine, Sequence from typing import Any, TypeVar @@ -25,6 +25,26 @@ _T = TypeVar("_T") +# S3's safe character set for object key names. See +# https://docs.aws.amazon.com/AmazonS3/latest/userguide/object-keys.html +_S3_SAFE_CHARS = frozenset(string.ascii_letters + string.digits + "!-_.*'()") + + +def _percent_encode(val: str | None) -> str | None: + """Percent-encode a path segment per the S3 key spec. + + Encodes every byte outside :data:`_S3_SAFE_CHARS` as ``%XX`` with + upper-case hex digits, operating on the UTF-8 bytes so non-ASCII + characters are escaped byte by byte. Returns ``None`` for empty or + missing values so callers can substitute ``"null"``. + """ + if not val: + return None + return "".join( + chr(byte) if chr(byte) in _S3_SAFE_CHARS else f"%{byte:02X}" + for byte in val.encode("utf-8") + ) + def _format_client_context(client: S3StorageDriverClient) -> str: """Format the client's ``describe()`` output as ", k=v, k=v" for error @@ -127,24 +147,20 @@ async def store( (e.g. proto binary). The returned list is the same length as ``payloads``. """ - - def _quote(val: str | None) -> str | None: - return urllib.parse.quote(val, safe="") if val else None - # Build context segments from the target identity. context_segments = "" target = context.target - namespace = _quote(target.namespace) if target is not None else None + namespace = _percent_encode(target.namespace) if target is not None else None namespace_segment = f"/ns/{namespace}" if namespace else "" if isinstance(target, StorageDriverWorkflowInfo): - wf_type = _quote(target.type) or "null" - wf_id = _quote(target.id) or "null" - wf_run_id = _quote(target.run_id) or "null" + wf_type = _percent_encode(target.type) or "null" + wf_id = _percent_encode(target.id) or "null" + wf_run_id = _percent_encode(target.run_id) or "null" context_segments = f"/wt/{wf_type}/wi/{wf_id}/ri/{wf_run_id}" elif isinstance(target, StorageDriverActivityInfo): - act_type = _quote(target.type) or "null" - act_id = _quote(target.id) or "null" - act_run_id = _quote(target.run_id) or "null" + act_type = _percent_encode(target.type) or "null" + act_id = _percent_encode(target.id) or "null" + act_run_id = _percent_encode(target.run_id) or "null" context_segments = f"/at/{act_type}/ai/{act_id}/ri/{act_run_id}" async def _upload(payload: Payload) -> StorageDriverClaim: diff --git a/tests/contrib/aws/s3driver/test_s3driver.py b/tests/contrib/aws/s3driver/test_s3driver.py index 19b3419f8..05628a7f2 100644 --- a/tests/contrib/aws/s3driver/test_s3driver.py +++ b/tests/contrib/aws/s3driver/test_s3driver.py @@ -336,6 +336,88 @@ async def test_key_urlencodes_namespace( == f"v0/ns/my%2Fns%231/wt/null/wi/wf1/ri/null/d/sha256/{expected_hash}" ) + async def test_key_preserves_s3_safe_special_chars( + self, driver_client: S3StorageDriverClient + ) -> None: + """S3's safe special characters are left unescaped per the key spec.""" + driver = S3StorageDriver(client=driver_client, bucket=BUCKET) + payload = make_payload() + # Every special character S3 lists as safe: ! - _ . * ' ( ) + ctx = make_workflow_context(namespace="ns1", workflow_id="!-_.*'()") + [claim] = await driver.store(ctx, [payload]) + expected_hash = hashlib.sha256(payload.SerializeToString()).hexdigest() + assert ( + claim.claim_data["key"] + == f"v0/ns/ns1/wt/null/wi/!-_.*'()/ri/null/d/sha256/{expected_hash}" + ) + + async def test_key_escapes_tilde( + self, driver_client: S3StorageDriverClient + ) -> None: + """Tilde is not in S3's safe set and must be percent-encoded (%7E).""" + driver = S3StorageDriver(client=driver_client, bucket=BUCKET) + payload = make_payload() + ctx = make_workflow_context(namespace="ns1", workflow_id="wf~1") + [claim] = await driver.store(ctx, [payload]) + expected_hash = hashlib.sha256(payload.SerializeToString()).hexdigest() + assert ( + claim.claim_data["key"] + == f"v0/ns/ns1/wt/null/wi/wf%7E1/ri/null/d/sha256/{expected_hash}" + ) + + async def test_key_escapes_non_ascii_as_utf8_bytes( + self, driver_client: S3StorageDriverClient + ) -> None: + """Non-ASCII characters are percent-encoded byte by byte from UTF-8.""" + driver = S3StorageDriver(client=driver_client, bucket=BUCKET) + payload = make_payload() + # "é" is U+00E9, which is 0xC3 0xA9 in UTF-8. + ctx = make_workflow_context(namespace="ns1", workflow_id="café") + [claim] = await driver.store(ctx, [payload]) + expected_hash = hashlib.sha256(payload.SerializeToString()).hexdigest() + assert ( + claim.claim_data["key"] + == f"v0/ns/ns1/wt/null/wi/caf%C3%A9/ri/null/d/sha256/{expected_hash}" + ) + + async def test_key_matches_spec_workflow_example( + self, driver_client: S3StorageDriverClient + ) -> None: + """Reproduces the workflow key example from the S3 key spec.""" + driver = S3StorageDriver(client=driver_client, bucket=BUCKET) + payload = make_payload() + ctx = make_workflow_context( + namespace="payments prod", + workflow_type="ChargeWorkflow", + workflow_id="order+123=abc", + run_id="3f1d6c7a-8b2e-4f7a-9d0a-87a6f95e4d31", + ) + [claim] = await driver.store(ctx, [payload]) + expected_hash = hashlib.sha256(payload.SerializeToString()).hexdigest() + assert claim.claim_data["key"] == ( + "v0/ns/payments%20prod/wt/ChargeWorkflow/wi/order%2B123%3Dabc" + f"/ri/3f1d6c7a-8b2e-4f7a-9d0a-87a6f95e4d31/d/sha256/{expected_hash}" + ) + + async def test_key_matches_spec_activity_example( + self, driver_client: S3StorageDriverClient + ) -> None: + """Reproduces the activity key example from the S3 key spec.""" + driver = S3StorageDriver(client=driver_client, bucket=BUCKET) + payload = make_payload() + ctx = make_activity_context( + namespace="payments prod", + activity_type="Capture/Charge", + activity_id="activity id+42", + run_id="9e1d1fd9-2f8a-4c40-93e2-731f31b9268b", + ) + [claim] = await driver.store(ctx, [payload]) + expected_hash = hashlib.sha256(payload.SerializeToString()).hexdigest() + assert claim.claim_data["key"] == ( + "v0/ns/payments%20prod/at/Capture%2FCharge/ai/activity%20id%2B42" + f"/ri/9e1d1fd9-2f8a-4c40-93e2-731f31b9268b/d/sha256/{expected_hash}" + ) + async def test_key_urlencoded_roundtrip( self, driver_client: S3StorageDriverClient ) -> None: From a5578034312a8e6c659807349b4ea4e176b1f382 Mon Sep 17 00:00:00 2001 From: Tim Conley Date: Mon, 13 Jul 2026 13:22:20 -0700 Subject: [PATCH 161/226] Update contributing guide (#1625) * Update contributing guide * Mention AI-generated contributions * Add agent guidance * Small updates * Update AGENTS.md Co-authored-by: Spencer Judge * Update AGENTS.md Co-authored-by: Spencer Judge * Update AGENTS.md * Clarify issue assignment guidance --------- Co-authored-by: Spencer Judge --- AGENTS.md | 117 +++++++++++++++++++++++++++++++++++++++++++ CONTRIBUTING.md | 129 ++++++++++++++++++++++++++++++++++++++++++------ 2 files changed, 232 insertions(+), 14 deletions(-) create mode 100644 AGENTS.md diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 000000000..7ecbb40d5 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,117 @@ +# Contributor Guidance for `sdk-python` + +This repository provides the Temporal Python SDK, including Python packages, +tests, optional integrations, and the Rust bridge used by the SDK. Use this +document as a quick reference when submitting pull requests. + +## Requirements for coding agents + +* Prefer the repo's Poe tasks over invoking underlying tools directly. Use + `poe test`, `poe lint`, `poe format`, `poe build-develop`, and + `poe bridge-lint` unless there is a specific reason to run a lower-level + command. +* If you are about to run tests, you do not need to run a build separately first + unless Rust bridge changes need a fresh editable extension. For bridge changes, + run `poe build-develop` before Python tests that import `temporalio`. +* Use targeted tests while iterating. `poe test -s -k ` is preferred for + a small behavioral change; run broader tests only when the change affects + shared behavior. +* Do not use `--log-cli-level` by default. The pytest configuration shows logs + for failed tests at the end without streaming all logs for passing tests. +* Tests that use the workflow environment may start a local Temporal dev server + and may download a test server binary on first run. Unit tests that do not use + the workflow environment do not start a server. +* Time-skipping tests are run with `poe test -s --workflow-environment + time-skipping`. Time-skipping does not work on Linux ARM or Windows ARM. +* It is extremely important that comments explain why something is necessary, + not what the code already says. Avoid comments unless they clarify nonobvious + behavior. +* Avoid broad refactors, style churn, or unrelated cleanups in behavior changes. +* Avoid unqualified imports from `temporalio` packages except `temporalio.types`. + Relative imports are acceptable for private packages. +* Do not commit `uv.lock` or `pyproject.toml` changes created only for temporary + protobuf downgrade workflows. Prefer to use poe gen-protos-docker when possible. + +## Repo Specific Utilities + +* Poe tasks are defined in `pyproject.toml`: + * `poe build-develop` - build the Rust extension in editable debug mode. + * `poe test` - run pytest in parallel with the default workflow environment. + * `poe lint` - run import checks, formatting checks, type checks, and + docstyle. + * `poe lint-types` - run pyright, mypy, and basedpyright. + * `poe bridge-lint` - run clippy for the Rust bridge. + * `poe format` - run Ruff import sorting, Ruff formatting, and `cargo fmt` for + the bridge. + * `poe gen-protos-docker` - regenerate protobuf-related files using Docker. + * `poe gen-protos` - regenerate protobuf-related files without Docker, with + the Python/protobuf constraints documented in `README.md`. + +## Building and Testing + +The common local commands are: + +```bash +uv sync --all-extras +poe build-develop +poe lint +poe test +poe test -s --workflow-environment time-skipping +``` + +For focused iteration, prefer: + +```bash +poe test -s -k +uv run pytest tests/path/test_file.py::test_name +``` + +For release artifacts, use `uv build`. Documentation can be generated with +`poe gen-docs`. + +## Expectations for Pull Requests + +* Format and lint code before submitting. +* Include tests for behavior changes. +* Update public API documentation or doc comments for public behavior changes. +* Add a high-level changelog entry for user-facing changes according to the + existing `CHANGELOG.md` convention. +* Keep commit messages short and in the imperative mood. +* Provide a clear PR description outlining what changed, why it changed, and + what validation was run. + +## Review Checklist + +Reviewers will look for: + +* CI passing, including build, lint, type checks, unit tests, and workflow + environment tests. +* Tests covering behavior changes. +* Clear and concise code following existing style. +* Public API documentation updates when behavior changes. +* No unrelated generated files, lockfile churn, or broad rewrites. + +## Where Things Are + +* `temporalio/` - Python SDK source. + * `temporalio/worker/` - worker implementation. + * `temporalio/converter/` - payload and failure conversion. + * `temporalio/testing/` - testing utilities. + * `temporalio/nexus/` - Nexus support. + * `temporalio/contrib/` - optional integrations. + * `temporalio/bridge/` - Rust bridge and generated bridge bindings. +* `tests/` - pytest suites mirroring SDK areas. +* `scripts/` - generation, documentation, and helper scripts. +* `build/apidocs/` - generated API documentation. +* `dist/` - built wheels and source distributions. +* `temporalio/bridge/target/` - Rust build output. You should not need to inspect + this directory. + +## Notes + +* The SDK supports Python 3.10 and newer. +* Generated protobuf and bridge files have specific regeneration workflows; see + `README.md` before changing them. +* The Rust bridge uses SDK Core from `temporalio/bridge/sdk-core`. +* `__pycache__`, `build`, `dist`, and Rust `target` outputs are generated + artifacts and should not be reviewed as source changes. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 6096c5b2b..fcc672866 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,21 +1,122 @@ -# Contributing to the Temporal Python SDK +# Contributing to Temporal SDKs -Thanks for your interest in contributing! +Thanks for your interest in contributing to Temporal SDKs. -All contributors must complete the Temporal Contributor License Agreement (CLA) before changes -can be merged. A link to the CLA will be posted in the PR. +This guide describes expectations that apply across Temporal SDK repositories. Each +repository may have additional local conventions, but the guidance below should help +you open issues and pull requests that maintainers can evaluate efficiently. -See the [README](README.md) for build and development instructions. +## Before You Open an Issue -## Changelog +Search the existing issues first. If you find an issue that describes the same bug, +feature request, or design topic, add any relevant details there instead of opening a +duplicate. Use an upvote on the issue to show that it affects you too. -User-facing changes are recorded in [`CHANGELOG.md`](CHANGELOG.md), loosely following the -[Keep a Changelog](https://keepachangelog.com/en/1.1.0/) format. +Issues are assigned to people when they are actively working on them. Before taking +on an issue, check whether it is already assigned so you do not duplicate someone +else's work. -If your PR includes a user-facing change (new feature, behavior change, deprecation, breaking -change, notable bug fix, or security fix), add a short, high-level entry to the `## [Unreleased]` -section at the top of `CHANGELOG.md` under the appropriate heading: -Added, Changed, Deprecated, Breaking Changes, Fixed, or Security. +Use GitHub issues for actionable bugs and feature work. For usage questions, help +debugging an application, or general discussion, join the relevant +language-specific channel in the +[Temporal community Slack](https://temporal.io/slack) or use the support channel +available to you. -Keep entries high-level and written for users. The full commit log is appended at release time, -so internal-only changes (refactors, tests, CI, docs) don't need an entry. +## Bug Reports + +When reporting a bug, include enough detail for someone else to reproduce or +understand the problem: + +* A short summary of the problem. +* A minimal reproduction, preferably as code that can be copied into a small + project or test. +* What you expected to happen and what actually happened. +* The SDK version. +* The language runtime version. +* The operating system and architecture. +* Temporal Server or Temporal Cloud details, if the issue depends on service + behavior. +* Logs, stack traces, workflow histories, or other diagnostics that show the + failure. +* Whether the behavior is a regression, and the last version where it worked if + known. + +## Feature Requests and Design Changes + +Open or join a GitHub issue before starting substantial feature work, behavior +changes, or API design changes. This gives maintainers and other SDK users a chance +to discuss the approach before you invest in a larger implementation. + +The relevant language-specific channel in Temporal community Slack is also a good +place for early discussion, but important decisions should still be captured in a +GitHub issue so they are visible and searchable. + +Small bug fixes, documentation fixes, and narrowly scoped maintenance changes can go +straight to a pull request. + +## Pull Requests + +Good pull requests are focused and easy to review: + +* Keep each pull request scoped to one logical change. +* Include tests for behavior changes. +* Update public API documentation or doc comments when public behavior changes. +* Add a high-level changelog entry for user-facing changes according to the + repository's local changelog convention. +* Describe what changed, why it changed, and what validation you ran. + +Run the relevant local checks when practical. CI must pass before a pull request can +be merged. + +## Things to Avoid + +Avoid changes that make review harder without improving the contribution: + +* Unrelated refactors mixed into a behavior change. +* Style-only churn. +* Large feature pull requests that were not discussed first. +* License, copyright, or other legal changes without maintainer discussion. + +## AI-Generated Contributions + +Using AI tools while contributing is acceptable. You are responsible for the +correctness, quality, and maintainability of everything you submit. + +Thoroughly self-review AI-generated code and documentation before opening a pull +request. Make sure it is correct, tested where appropriate, and consistent with the +style and patterns of the codebase. + +Keep AI-assisted changes concise and scoped. Avoid verbose generated prose, +unnecessary comments, or broad rewrites that make the change harder to review. + +## Contributor License Agreement + +All contributors must complete the Temporal Contributor License Agreement (CLA) +before changes can be merged. A link to the CLA will be posted in the pull request. + +## Security Issues + +Do not open public GitHub issues for suspected security vulnerabilities. Report them +to security@temporal.io instead. + +## Review and CI + +Maintainers review pull requests for correctness, compatibility, test coverage, +documentation, and long-term maintainability. Review may require changes before a +pull request can be merged, and it may take maintainers some time to review a +contribution. + +CI is the final validation gate. If CI fails, update the pull request or ask for help +if the failure appears unrelated to your change. Some CI gates may wait for a +maintainer to approve or run them. + +## Inactive Pull Requests + +Maintainers may close inactive pull requests after follow-up if they are no longer +moving forward. If that happens, you are welcome to reopen the pull request or open a +new one when you are ready to continue. + +## Community Conduct + +Keep discussions respectful, constructive, and focused on the work. Clear context, +specific examples, and patience with review feedback help everyone move faster. From 7fe7e6f959781d2bab5ca37fb878bb9f66b7f668 Mon Sep 17 00:00:00 2001 From: Ali Amiri <943064+iampat@users.noreply.github.com> Date: Tue, 14 Jul 2026 13:36:17 -0700 Subject: [PATCH 162/226] Fix a few typos (#1647) --- temporalio/contrib/openai_agents/_mcp.py | 2 +- temporalio/contrib/openai_agents/testing.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/temporalio/contrib/openai_agents/_mcp.py b/temporalio/contrib/openai_agents/_mcp.py index ba494c42d..487634d13 100644 --- a/temporalio/contrib/openai_agents/_mcp.py +++ b/temporalio/contrib/openai_agents/_mcp.py @@ -414,7 +414,7 @@ async def get_prompt( class StatefulMCPServerProvider: """A stateful MCP server implementation for Temporal workflows. - This class wraps an function to create MCP servers to maintain a persistent connection throughout + This class wraps a function to create MCP servers to maintain a persistent connection throughout the workflow execution. It creates a dedicated worker that stays connected to the MCP server and processes operations on a dedicated task queue. diff --git a/temporalio/contrib/openai_agents/testing.py b/temporalio/contrib/openai_agents/testing.py index d4641105c..110ca20b7 100644 --- a/temporalio/contrib/openai_agents/testing.py +++ b/temporalio/contrib/openai_agents/testing.py @@ -90,7 +90,7 @@ def output_message(text: str) -> ModelResponse: class TestModelProvider(ModelProvider): - """Test model provider which simply returns the given module.""" + """Test model provider which simply returns the given model.""" __test__ = False From cd17e5777f894c0b0d600048d4e1c9f2faf7d4b6 Mon Sep 17 00:00:00 2001 From: odedkedemdreeze Date: Wed, 15 Jul 2026 20:23:59 +0300 Subject: [PATCH 163/226] Release the GIL during the activity heartbeat core call (#1643) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit record_activity_heartbeat was a synchronous pyo3 fn that held the GIL while core's record_heartbeat blocked on the outstanding-activity lock. Task starts invoke a custom slot supplier's mark_slot_used (which acquires the GIL) while holding that same lock, so any worker with a custom slot supplier and heartbeating activities could deadlock permanently (ABBA on GIL vs. lock). Decode the heartbeat proto with the GIL held (it borrows the Python bytes), then detach from the GIL for the core call so the cycle cannot form. Fixes #1642 Co-authored-by: “Oded <“oded”@dreeze.com”> Co-authored-by: Claude Fable 5 --- temporalio/bridge/src/worker.rs | 12 +++-- tests/worker/test_worker.py | 89 +++++++++++++++++++++++++++++++++ 2 files changed, 97 insertions(+), 4 deletions(-) diff --git a/temporalio/bridge/src/worker.rs b/temporalio/bridge/src/worker.rs index e530e89bb..223b220f0 100644 --- a/temporalio/bridge/src/worker.rs +++ b/temporalio/bridge/src/worker.rs @@ -658,10 +658,14 @@ impl WorkerRef { enter_sync!(self.runtime); let heartbeat = ActivityHeartbeat::decode(proto.as_bytes()) .map_err(|err| PyValueError::new_err(format!("Invalid proto: {err}")))?; - self.worker - .as_ref() - .unwrap() - .record_activity_heartbeat(heartbeat); + let worker = self.worker.as_ref().unwrap().clone(); + // Detach from the GIL during the core call. Core may block on internal + // locks whose holders can call back into Python (e.g. a custom slot + // supplier's mark_slot_used runs while core's outstanding-activity + // lock is held); holding the GIL here would deadlock the worker. + proto + .py() + .detach(move || worker.record_activity_heartbeat(heartbeat)); Ok(()) } diff --git a/tests/worker/test_worker.py b/tests/worker/test_worker.py index dda754a5b..1834af829 100644 --- a/tests/worker/test_worker.py +++ b/tests/worker/test_worker.py @@ -589,6 +589,95 @@ def release_slot(self, ctx: SlotReleaseContext) -> None: await asyncio.sleep(1) +@activity.defn +async def heartbeating_activity(beats: int) -> None: + for i in range(beats): + activity.heartbeat(i) + await asyncio.sleep(0) + + +@workflow.defn +class HeartbeatingFanOutWorkflow: + @workflow.run + async def run(self, total: int, beats: int, window: int) -> None: + in_flight = asyncio.Semaphore(window) + + async def run_one() -> None: + async with in_flight: + await workflow.execute_activity( + heartbeating_activity, + beats, + start_to_close_timeout=timedelta(minutes=1), + heartbeat_timeout=timedelta(seconds=30), + ) + + await asyncio.gather(*(run_one() for _ in range(total))) + + +async def test_custom_slot_supplier_with_heartbeating_activities(client: Client): + """Regression test for the GIL <-> core-mutex deadlock (#1642). + + Any custom slot supplier plus heartbeating activities used to wedge the + worker permanently: the heartbeat FFI held the GIL while blocking on + core's outstanding-activity lock, while an activity task start invoked + mark_slot_used (which acquires the GIL) under that same lock. The + supplier below is deliberately trivial - the deadlock was in the calling + convention, not in what the callbacks do. + + NOTE: on regression this test HANGS rather than fails - the deadlock + freezes the event loop, so no in-process timeout (including the + wait_for below) can fire, and only a CI-level job timeout kills it. + """ + + class CappedSlotSupplier(CustomSlotSupplier): + def __init__(self, max_slots: int) -> None: + self.max_slots = max_slots + self.used = 0 + + async def reserve_slot(self, ctx: SlotReserveContext) -> SlotPermit: + while True: + permit = self.try_reserve_slot(ctx) + if permit is not None: + return permit + await asyncio.sleep(0.005) + + def try_reserve_slot(self, ctx: SlotReserveContext) -> SlotPermit | None: + # Called with the GIL held, so no extra lock is needed + if self.used >= self.max_slots: + return None + self.used += 1 + return SlotPermit() + + def mark_slot_used(self, ctx: SlotMarkUsedContext) -> None: + return None + + def release_slot(self, ctx: SlotReleaseContext) -> None: + self.used = max(0, self.used - 1) + + fixed = FixedSizeSlotSupplier(100) + tuner = WorkerTuner.create_composite( + workflow_supplier=fixed, + # A small cap keeps activity starts (and thus mark_slot_used calls) + # churning against the heartbeat FFI + activity_supplier=CappedSlotSupplier(8), + local_activity_supplier=fixed, + nexus_supplier=fixed, + ) + async with new_worker( + client, + HeartbeatingFanOutWorkflow, + activities=[heartbeating_activity], + tuner=tuner, + ) as w: + wf1 = await client.start_workflow( + HeartbeatingFanOutWorkflow.run, + args=[600, 50, 150], + id=f"heartbeating-slot-supplier-{uuid.uuid4()}", + task_queue=w.task_queue, + ) + await asyncio.wait_for(wf1.result(), timeout=120) + + @workflow.defn( name="DeploymentVersioningWorkflow", versioning_behavior=VersioningBehavior.AUTO_UPGRADE, From 3660af629e6d0eaba63723e81e8e7e55b92ae5d7 Mon Sep 17 00:00:00 2001 From: xumaple <45406854+xumaple@users.noreply.github.com> Date: Wed, 15 Jul 2026 15:01:49 -0400 Subject: [PATCH 164/226] Fix copy-paste error message in OpenTelemetryPlugin (#1649) The no-runner guard named the OpenAI plugin, a copy-paste leftover from the OpenAI-agents plugin. --- temporalio/contrib/opentelemetry/_plugin.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/temporalio/contrib/opentelemetry/_plugin.py b/temporalio/contrib/opentelemetry/_plugin.py index 80a17de52..2a0e1e06c 100644 --- a/temporalio/contrib/opentelemetry/_plugin.py +++ b/temporalio/contrib/opentelemetry/_plugin.py @@ -34,7 +34,9 @@ def __init__(self, *, add_temporal_spans: bool = False): def workflow_runner(runner: WorkflowRunner | None) -> WorkflowRunner: if not runner: - raise ValueError("No WorkflowRunner provided to the OpenAI plugin.") + raise ValueError( + "No WorkflowRunner provided to the OpenTelemetry plugin." + ) # If in sandbox, add additional passthrough if isinstance(runner, SandboxedWorkflowRunner): From fd822986429b944f87341c4cb01784d69f1461e6 Mon Sep 17 00:00:00 2001 From: Spencer Judge Date: Wed, 15 Jul 2026 13:50:03 -0700 Subject: [PATCH 165/226] Clarify determinism of wait_condition with comment (#1638) * Clarify determinism of wait_condition with comment * Make 0 make more sense --- temporalio/workflow/_context.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/temporalio/workflow/_context.py b/temporalio/workflow/_context.py index 23c943cd0..d2ec0d633 100644 --- a/temporalio/workflow/_context.py +++ b/temporalio/workflow/_context.py @@ -928,6 +928,11 @@ async def wait_condition( This function returns when the callback returns true (invoked each loop iteration) or the timeout has been reached. + Importantly, using `None` value for ``timeout`` means that no Temporal timer is created. This + means changing from `None` to a positive value (or the inverse) constitutes a nondeterministic + change to workflow code. Using ``0`` will cause this function to immediately throw a timeout and + should not be used. + Args: fn: Non-async callback that accepts no parameters and returns a boolean. timeout: Optional number of seconds to wait until throwing From fa1d9376861afa3e5c4bbe39c0cbc9f3aa90f183 Mon Sep 17 00:00:00 2001 From: Brian Strauch Date: Thu, 16 Jul 2026 09:41:27 -0700 Subject: [PATCH 166/226] Remove exclude-newer-package exemptions (#1653) The pinned versions of google-adk, google-genai, and openai-agents are now all older than the 2-week exclude-newer cooldown, so the bypasses are no longer needed. Co-authored-by: Claude Fable 5 --- pyproject.toml | 1 - uv.lock | 5 ----- 2 files changed, 6 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index bcad8903c..b30a87fd3 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -266,4 +266,3 @@ exclude = ["temporalio/bridge/target/**/*"] # Prevent uv commands from building the package by default package = false exclude-newer = "2 weeks" -exclude-newer-package = { google-adk = false, google-genai = false, openai-agents = false } diff --git a/uv.lock b/uv.lock index 0543cf0ed..7a5172d1a 100644 --- a/uv.lock +++ b/uv.lock @@ -12,11 +12,6 @@ resolution-markers = [ exclude-newer = "0001-01-01T00:00:00Z" # This has no effect and is included for backwards compatibility when using relative exclude-newer values. exclude-newer-span = "P2W" -[options.exclude-newer-package] -google-adk = false -google-genai = false -openai-agents = false - [[package]] name = "aioboto3" version = "15.5.0" From 663ea64f6193b49cb7a4ef3ebde447f69a58b936 Mon Sep 17 00:00:00 2001 From: Spencer Judge Date: Thu, 16 Jul 2026 11:47:36 -0700 Subject: [PATCH 167/226] Add patch activation callback (#1639) --- CHANGELOG.md | 4 + temporalio/worker/__init__.py | 2 + temporalio/worker/_replayer.py | 1 + temporalio/worker/_worker.py | 16 +- temporalio/worker/_workflow.py | 4 + temporalio/worker/_workflow_instance.py | 29 +- temporalio/worker/workflow_sandbox/_runner.py | 1 + tests/worker/test_workflow.py | 326 ++++++++++++++++++ 8 files changed, 381 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1a1a92a95..cf1b7bafe 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,6 +20,10 @@ to include examples, links to docs, or any other relevant information. ### Added +- Added the experimental `Worker` `patch_activation_callback` option, allowing workers + to decide whether a first non-replay `workflow.patched` call should activate a patch + during rolling deployments. + ### Changed ### Deprecated diff --git a/temporalio/worker/__init__.py b/temporalio/worker/__init__.py index 55966b35d..4f6efe68c 100644 --- a/temporalio/worker/__init__.py +++ b/temporalio/worker/__init__.py @@ -58,6 +58,7 @@ WorkerDeploymentConfig, ) from ._workflow_instance import ( + PatchActivationInput, UnsandboxedWorkflowRunner, WorkflowInstance, WorkflowInstanceDetails, @@ -77,6 +78,7 @@ "PollerBehavior", "PollerBehaviorSimpleMaximum", "PollerBehaviorAutoscaling", + "PatchActivationInput", # Interceptor base classes "Interceptor", "ActivityInboundInterceptor", diff --git a/temporalio/worker/_replayer.py b/temporalio/worker/_replayer.py index 508d5f708..a9fc11b49 100644 --- a/temporalio/worker/_replayer.py +++ b/temporalio/worker/_replayer.py @@ -255,6 +255,7 @@ def on_eviction_hook( workflow_failure_exception_types=self._config.get( "workflow_failure_exception_types", [] ), + patch_activation_callback=None, debug_mode=self._config.get("debug_mode", False), metric_meter=runtime.metric_meter, on_eviction_hook=on_eviction_hook, diff --git a/temporalio/worker/_worker.py b/temporalio/worker/_worker.py index 2ad1d42c6..8f55e9632 100644 --- a/temporalio/worker/_worker.py +++ b/temporalio/worker/_worker.py @@ -40,7 +40,11 @@ _DEFAULT_WORKFLOW_TASK_EXTERNAL_STORAGE_CONCURRENCY, _WorkflowWorker, ) -from ._workflow_instance import UnsandboxedWorkflowRunner, WorkflowRunner +from ._workflow_instance import ( + PatchActivationInput, + UnsandboxedWorkflowRunner, + WorkflowRunner, +) from .workflow_sandbox import SandboxedWorkflowRunner logger = logging.getLogger(__name__) @@ -135,6 +139,7 @@ def __init__( use_worker_versioning: bool = False, disable_safe_workflow_eviction: bool = False, deployment_config: WorkerDeploymentConfig | None = None, + patch_activation_callback: Callable[[PatchActivationInput], bool] | None = None, workflow_task_poller_behavior: PollerBehavior = PollerBehaviorSimpleMaximum( maximum=5 ), @@ -307,6 +312,12 @@ def __init__( deployment_config: Deployment config for the worker. Exclusive with ``build_id`` and ``use_worker_versioning``. WARNING: This is an experimental feature and may change in the future. + patch_activation_callback: Callback to decide whether the first non-replay + call to :py:func:`workflow.patched` for a + patch ID should activate that patch. The callback receives a + :py:class:`PatchActivationInput` and must return ``True`` to activate the + patch or ``False`` to leave it inactive. + WARNING: This is an experimental feature and may change in the future. workflow_task_poller_behavior: Specify the behavior of workflow task polling. Defaults to a 5-poller maximum. activity_task_poller_behavior: Specify the behavior of activity task polling. @@ -368,6 +379,7 @@ def __init__( use_worker_versioning=use_worker_versioning, disable_safe_workflow_eviction=disable_safe_workflow_eviction, deployment_config=deployment_config, + patch_activation_callback=patch_activation_callback, workflow_task_poller_behavior=workflow_task_poller_behavior, activity_task_poller_behavior=activity_task_poller_behavior, nexus_task_poller_behavior=nexus_task_poller_behavior, @@ -528,6 +540,7 @@ def check_activity(activity: str): workflow_failure_exception_types=config[ "workflow_failure_exception_types" ], # type: ignore[reportTypedDictNotRequiredAccess] + patch_activation_callback=config.get("patch_activation_callback"), debug_mode=config["debug_mode"], # type: ignore[reportTypedDictNotRequiredAccess] disable_eager_activity_execution=config[ "disable_eager_activity_execution" @@ -982,6 +995,7 @@ class WorkerConfig(TypedDict, total=False): use_worker_versioning: bool disable_safe_workflow_eviction: bool deployment_config: WorkerDeploymentConfig | None + patch_activation_callback: Callable[[PatchActivationInput], bool] | None workflow_task_poller_behavior: PollerBehavior activity_task_poller_behavior: PollerBehavior nexus_task_poller_behavior: PollerBehavior diff --git a/temporalio/worker/_workflow.py b/temporalio/worker/_workflow.py index 8e6ba2726..953e07a5a 100644 --- a/temporalio/worker/_workflow.py +++ b/temporalio/worker/_workflow.py @@ -42,6 +42,7 @@ WorkflowInterceptorClassInput, ) from ._workflow_instance import ( + PatchActivationInput, WorkflowInstance, WorkflowInstanceDetails, WorkflowRunner, @@ -78,6 +79,7 @@ def __init__( data_converter: temporalio.converter.DataConverter, interceptors: Sequence[Interceptor], workflow_failure_exception_types: Sequence[type[BaseException]], + patch_activation_callback: Callable[[PatchActivationInput], bool] | None, debug_mode: bool, disable_eager_activity_execution: bool, metric_meter: temporalio.common.MetricMeter, @@ -145,6 +147,7 @@ def __init__( ) self._workflow_failure_exception_types = workflow_failure_exception_types + self._patch_activation_callback = patch_activation_callback self._running_workflows: dict[str, _RunningWorkflow] = {} self._disable_eager_activity_execution = disable_eager_activity_execution self._on_eviction_hook = on_eviction_hook @@ -798,6 +801,7 @@ def _create_workflow_instance( extern_functions=self._extern_functions, disable_eager_activity_execution=self._disable_eager_activity_execution, worker_level_failure_exception_types=self._workflow_failure_exception_types, + patch_activation_callback=self._patch_activation_callback, last_completion_result=init.last_completion_result, last_failure=last_failure, ) diff --git a/temporalio/worker/_workflow_instance.py b/temporalio/worker/_workflow_instance.py index 74edc66b7..c0e21bfd2 100644 --- a/temporalio/worker/_workflow_instance.py +++ b/temporalio/worker/_workflow_instance.py @@ -131,6 +131,17 @@ def set_worker_level_failure_exception_types( pass +@dataclass(frozen=True) +class PatchActivationInput: + """Input for the worker patch activation callback.""" + + workflow_info: temporalio.workflow.Info + """Information about the workflow execution calling ``patched``.""" + + patch_id: str + """Patch ID passed to ``patched``.""" + + @dataclass(frozen=True) class WorkflowInstanceDetails: """Immutable details for creating a workflow instance.""" @@ -144,6 +155,7 @@ class WorkflowInstanceDetails: extern_functions: Mapping[str, Callable] disable_eager_activity_execution: bool worker_level_failure_exception_types: Sequence[type[BaseException]] + patch_activation_callback: Callable[[PatchActivationInput], bool] | None last_completion_result: temporalio.api.common.v1.Payloads last_failure: Failure | None @@ -264,6 +276,7 @@ def __init__(self, det: WorkflowInstanceDetails) -> None: self._worker_level_failure_exception_types = ( det.worker_level_failure_exception_types ) + self._patch_activation_callback = det.patch_activation_callback self._primary_task: asyncio.Task[None] | None = None self._time_ns = 0 self._cancel_reason: str | None = None @@ -1363,7 +1376,20 @@ def workflow_patch(self, id: str, *, deprecated: bool) -> bool: if use_patch is not None: return use_patch - use_patch = not self._is_replaying or id in self._patches_notified + # Replay and history markers already determine the branch, and deprecation must + # keep existing patch semantics, so only a genuinely new patch consults the + # callback. + if deprecated or self._is_replaying or id in self._patches_notified: + use_patch = not self._is_replaying or id in self._patches_notified + elif self._patch_activation_callback is not None: + with self._as_read_only(in_query_or_validator=False): + use_patch = self._patch_activation_callback( + PatchActivationInput(workflow_info=self._info, patch_id=id) + ) + if type(use_patch) is not bool: + raise TypeError("Patch activation callback must return true or false") + else: + use_patch = True self._patches_memoized[id] = use_patch if use_patch: command = self._add_command() @@ -1873,6 +1899,7 @@ def workflow_random_seed(self) -> int: def workflow_register_random_seed_callback( self, callback: Callable[[int], None] ) -> None: + self._assert_not_read_only("register random seed callback") self._seed_callbacks.append(callback) #### Calls from outbound impl #### diff --git a/temporalio/worker/workflow_sandbox/_runner.py b/temporalio/worker/workflow_sandbox/_runner.py index b11c9b8c4..17f473d64 100644 --- a/temporalio/worker/workflow_sandbox/_runner.py +++ b/temporalio/worker/workflow_sandbox/_runner.py @@ -89,6 +89,7 @@ def prepare_workflow(self, defn: temporalio.workflow._Definition) -> None: extern_functions={}, disable_eager_activity_execution=False, worker_level_failure_exception_types=self._worker_level_failure_exception_types, + patch_activation_callback=None, last_completion_result=Payloads(), last_failure=Failure(), ), diff --git a/tests/worker/test_workflow.py b/tests/worker/test_workflow.py index d20077cf5..4c9546eab 100644 --- a/tests/worker/test_workflow.py +++ b/tests/worker/test_workflow.py @@ -3192,6 +3192,329 @@ async def waiting_signal() -> bool: ] == await post_patch_handle.result() +@workflow.defn +class PatchActivationWorkflow: + @workflow.run + async def run(self, patch_id: str, sleep_after_first: bool = False) -> list[bool]: + first = workflow.patched(patch_id) + if sleep_after_first: + await workflow.sleep(0.001) + return [first, workflow.patched(patch_id)] + + +@workflow.defn +class PatchActivationDeprecateWorkflow: + @workflow.run + async def run(self, patch_id: str) -> bool: + workflow.deprecate_patch(patch_id) + return workflow.patched(patch_id) + + +@workflow.defn(name="PatchActivationRolloutWorkflow") +class PatchActivationRolloutWorkflow: + def __init__(self) -> None: + self._ready = False + self._released = False + + @workflow.run + async def run(self) -> str: + workflow.patched("rollout-patch") + self._ready = True + await workflow.wait_condition(lambda: self._released) + return "new" if workflow.patched("rollout-patch") else "old" + + @workflow.query + def ready(self) -> bool: + return self._ready + + @workflow.signal + def release(self) -> None: + self._released = True + + +@workflow.defn(name="PatchActivationRolloutWorkflow") +class PatchActivationOldRolloutWorkflow: + def __init__(self) -> None: + self._ready = False + self._released = False + + @workflow.run + async def run(self) -> str: + self._ready = True + await workflow.wait_condition(lambda: self._released) + return "old" + + @workflow.query + def ready(self) -> bool: + return self._ready + + @workflow.signal + def release(self) -> None: + self._released = True + + +async def patch_marker_count(handle: WorkflowHandle) -> int: + count = 0 + async for event in handle.fetch_history_events(): + if event.event_type is EventType.EVENT_TYPE_MARKER_RECORDED: + count += 1 + return count + + +async def has_completed_workflow_task(handle: WorkflowHandle) -> bool: + async for event in handle.fetch_history_events(): + if event.event_type is EventType.EVENT_TYPE_WORKFLOW_TASK_COMPLETED: + return True + return False + + +def recording_patch_activation_callback( + calls: list[temporalio.worker.PatchActivationInput], decision: bool +) -> typing.Callable[[temporalio.worker.PatchActivationInput], bool]: + def callback(input: temporalio.worker.PatchActivationInput) -> bool: + calls.append(input) + return decision + + return callback + + +async def test_workflow_patch_activation_callback(client: Client): + workflow_id = f"workflow-{uuid.uuid4()}" + calls: list[temporalio.worker.PatchActivationInput] = [] + async with new_worker( + client, + PatchActivationWorkflow, + patch_activation_callback=recording_patch_activation_callback(calls, True), + ) as worker: + result = await client.execute_workflow( + PatchActivationWorkflow.run, + args=["my-patch", False], + id=workflow_id, + task_queue=worker.task_queue, + ) + + assert result == [True, True] + assert len(calls) == 1 + assert calls[0].workflow_info.workflow_id == workflow_id + assert calls[0].patch_id == "my-patch" + + +async def test_workflow_patch_activation_callback_can_decline(client: Client): + calls: list[temporalio.worker.PatchActivationInput] = [] + async with new_worker( + client, + PatchActivationWorkflow, + patch_activation_callback=recording_patch_activation_callback(calls, False), + ) as worker: + handle = await client.start_workflow( + PatchActivationWorkflow.run, + args=["my-patch", False], + id=f"workflow-{uuid.uuid4()}", + task_queue=worker.task_queue, + ) + assert await handle.result() == [False, False] + + assert len(calls) == 1 + assert await patch_marker_count(handle) == 0 + + +async def test_workflow_patch_activation_default_activates(client: Client): + async with new_worker(client, PatchActivationWorkflow) as worker: + handle = await client.start_workflow( + PatchActivationWorkflow.run, + args=["my-patch", False], + id=f"workflow-{uuid.uuid4()}", + task_queue=worker.task_queue, + ) + assert await handle.result() == [True, True] + + assert await patch_marker_count(handle) == 1 + + +async def test_workflow_patch_activation_callback_not_recalled_on_replay( + client: Client, +): + calls: list[temporalio.worker.PatchActivationInput] = [] + async with new_worker( + client, + PatchActivationWorkflow, + max_cached_workflows=0, + patch_activation_callback=recording_patch_activation_callback(calls, False), + ) as worker: + result = await client.execute_workflow( + PatchActivationWorkflow.run, + args=["my-patch", True], + id=f"workflow-{uuid.uuid4()}", + task_queue=worker.task_queue, + ) + assert result == [False, False] + + assert len(calls) == 1 + + +async def test_workflow_patch_activation_callback_bypassed_for_deprecate( + client: Client, +): + def unexpected_callback(_: temporalio.worker.PatchActivationInput) -> bool: + raise AssertionError("Patch activation callback should not be called") + + async with new_worker( + client, + PatchActivationDeprecateWorkflow, + patch_activation_callback=unexpected_callback, + ) as worker: + result = await client.execute_workflow( + PatchActivationDeprecateWorkflow.run, + "my-patch", + id=f"workflow-{uuid.uuid4()}", + task_queue=worker.task_queue, + ) + + assert result is True + + +async def test_workflow_patch_activation_callback_must_return_bool(client: Client): + def invalid_callback(_: temporalio.worker.PatchActivationInput) -> bool: + return "not a bool" # type: ignore[return-value] # pyright: ignore[reportReturnType] + + async with new_worker( + client, + PatchActivationWorkflow, + patch_activation_callback=invalid_callback, + ) as worker: + handle = await client.start_workflow( + PatchActivationWorkflow.run, + args=["my-patch", False], + id=f"workflow-{uuid.uuid4()}", + task_queue=worker.task_queue, + ) + await assert_task_fail_eventually( + handle, + message_contains="Patch activation callback must return true or false", + ) + + +async def test_workflow_patch_activation_callback_is_read_only(client: Client): + def make_command(_: temporalio.worker.PatchActivationInput) -> bool: + workflow.upsert_memo({"foo": "bar"}) + return True + + def schedule_task(_: temporalio.worker.PatchActivationInput) -> bool: + asyncio.get_running_loop().call_soon(lambda: None) + return True + + def wait_condition(_: temporalio.worker.PatchActivationInput) -> bool: + coroutine = workflow.wait_condition(lambda: True) + try: + coroutine.send(None) + finally: + coroutine.close() + return True + + def use_random(_: temporalio.worker.PatchActivationInput) -> bool: + workflow.random().random() + return True + + def register_random_seed_callback( + _: temporalio.worker.PatchActivationInput, + ) -> bool: + workflow.register_random_seed_callback(lambda _seed: None) + return True + + def create_new_random(_: temporalio.worker.PatchActivationInput) -> bool: + workflow.new_random() + return True + + callbacks = [ + (make_command, "action attempted: add command"), + (schedule_task, "action attempted: schedule task"), + (wait_condition, "action attempted: wait condition"), + (use_random, "action attempted: random"), + ( + register_random_seed_callback, + "action attempted: register random seed callback", + ), + (create_new_random, "action attempted: register random seed callback"), + ] + for callback, message in callbacks: + async with new_worker( + client, + PatchActivationWorkflow, + patch_activation_callback=callback, + ) as worker: + handle = await client.start_workflow( + PatchActivationWorkflow.run, + args=["my-patch", False], + id=f"workflow-{uuid.uuid4()}", + task_queue=worker.task_queue, + ) + await assert_task_fail_eventually(handle, message_contains=message) + + +async def test_workflow_declined_patch_rolls_out_to_old_worker(client: Client): + task_queue = f"tq-{uuid.uuid4()}" + calls: list[temporalio.worker.PatchActivationInput] = [] + async with new_worker( + client, + PatchActivationRolloutWorkflow, + task_queue=task_queue, + max_cached_workflows=0, + patch_activation_callback=recording_patch_activation_callback(calls, False), + ): + handle = await client.start_workflow( + PatchActivationRolloutWorkflow.run, + id=f"workflow-{uuid.uuid4()}", + task_queue=task_queue, + ) + await assert_eq_eventually(True, lambda: has_completed_workflow_task(handle)) + + assert len(calls) == 1 + async with new_worker( + client, + PatchActivationOldRolloutWorkflow, + task_queue=task_queue, + max_cached_workflows=0, + ): + await handle.signal("release") + assert await handle.result() == "old" + + +async def test_workflow_activated_patch_ignores_declining_worker(client: Client): + task_queue = f"tq-{uuid.uuid4()}" + activated_calls: list[temporalio.worker.PatchActivationInput] = [] + declining_calls: list[temporalio.worker.PatchActivationInput] = [] + async with new_worker( + client, + PatchActivationRolloutWorkflow, + task_queue=task_queue, + max_cached_workflows=0, + patch_activation_callback=recording_patch_activation_callback( + activated_calls, True + ), + ): + handle = await client.start_workflow( + PatchActivationRolloutWorkflow.run, + id=f"workflow-{uuid.uuid4()}", + task_queue=task_queue, + ) + await assert_eq_eventually(True, lambda: has_completed_workflow_task(handle)) + + assert len(activated_calls) == 1 + async with new_worker( + client, + PatchActivationRolloutWorkflow, + task_queue=task_queue, + max_cached_workflows=0, + patch_activation_callback=recording_patch_activation_callback( + declining_calls, False + ), + ): + await handle.signal(PatchActivationRolloutWorkflow.release) + assert await handle.result() == "new" + + assert not declining_calls + + @workflow.defn class UUIDWorkflow: def __init__(self) -> None: @@ -4175,6 +4498,8 @@ async def bad_query(self, bad_thing: str) -> str: workflow.set_query_handler("some-handler", lambda: "whatever") elif bad_thing == "patch": workflow.patched("some-patch") + elif bad_thing == "register_random_seed_callback": + workflow.register_random_seed_callback(lambda _seed: None) elif bad_thing == "signal_external_handle": await workflow.get_external_workflow_handle("some-id").signal("some-signal") return "should never get here" @@ -4203,6 +4528,7 @@ async def assert_bad_query(bad_thing: str) -> None: await assert_bad_query("random") await assert_bad_query("set_query_handler") await assert_bad_query("patch") + await assert_bad_query("register_random_seed_callback") await assert_bad_query("signal_external_handle") From c6386e9d49dfc1fd770408a899e768357e62249f Mon Sep 17 00:00:00 2001 From: Tim Conley Date: Thu, 16 Jul 2026 13:40:19 -0700 Subject: [PATCH 168/226] Prevent post-return activity cancel from killing pool thread (#1654) * Prevent post-return activity cancel from killing pool thread * Prevent post-return activity cancel from killing pool thread --- temporalio/worker/_activity.py | 24 ++++-- tests/worker/test_activity.py | 148 +++++++++++++++++++++++++++++++++ 2 files changed, 167 insertions(+), 5 deletions(-) diff --git a/temporalio/worker/_activity.py b/temporalio/worker/_activity.py index 088ed0380..8dd5fe12a 100644 --- a/temporalio/worker/_activity.py +++ b/temporalio/worker/_activity.py @@ -775,6 +775,20 @@ def set_thread_id(self, thread_id: int) -> None: with self._lock: self._thread_id = thread_id + @contextmanager + def active_thread(self) -> Iterator[None]: + thread_id = threading.current_thread().ident + if thread_id is not None: + self.set_thread_id(thread_id) + try: + yield None + finally: + if thread_id is not None: + with self._lock: + if self._thread_id == thread_id: + self._thread_id = None + self._pending_exception = None + def raise_in_thread(self, exc_type: type[Exception]) -> None: with self._lock: self._pending_exception = exc_type @@ -939,10 +953,6 @@ def _execute_sync_activity( fn: Callable[..., Any], *args: Any, ) -> Any: - if cancel_thread_raiser: - thread_id = threading.current_thread().ident - if thread_id is not None: - cancel_thread_raiser.set_thread_id(thread_id) if isinstance(heartbeat, SharedHeartbeatSender): def heartbeat_fn(*details: Any) -> None: @@ -968,7 +978,11 @@ def heartbeat_fn(*details: Any) -> None: cancellation_details=cancellation_details, ) ) - return fn(*args) + if not cancel_thread_raiser: + return fn(*args) + else: + with cancel_thread_raiser.active_thread(): + return fn(*args) class SharedStateManager(ABC): diff --git a/tests/worker/test_activity.py b/tests/worker/test_activity.py index df85b89fb..bbc7d19b0 100644 --- a/tests/worker/test_activity.py +++ b/tests/worker/test_activity.py @@ -1419,6 +1419,154 @@ def some_activity() -> str: assert result.result == "context var: some value!" +@activity.defn +def post_return_cancel_activity() -> str: + return "done" + + +@activity.defn +def post_return_cancel_probe_activity() -> str: + return "probe" + + +class PostReturnCancelInterceptor(Interceptor): + def __init__( + self, after_return_started: asyncio.Event, allow_completion: asyncio.Event + ) -> None: + super().__init__() + self.after_return_started = after_return_started + self.allow_completion = allow_completion + + def intercept_activity( + self, next: ActivityInboundInterceptor + ) -> ActivityInboundInterceptor: + return PostReturnCancelActivityInbound( + next, self.after_return_started, self.allow_completion + ) + + +class PostReturnCancelActivityInbound(ActivityInboundInterceptor): + def __init__( + self, + next: ActivityInboundInterceptor, + after_return_started: asyncio.Event, + allow_completion: asyncio.Event, + ) -> None: + super().__init__(next) + self.after_return_started = after_return_started + self.allow_completion = allow_completion + + async def execute_activity(self, input: ExecuteActivityInput) -> Any: + result = await super().execute_activity(input) + if activity.info().activity_type == "post_return_cancel_activity": + self.after_return_started.set() + await self.allow_completion.wait() + return result + + +async def test_sync_activity_cancel_after_return_does_not_kill_thread_pool_worker( + client: Client, + worker: ExternalWorker, + env: WorkflowEnvironment, + shared_state_manager: SharedStateManager, +): + if env.supports_time_skipping: + pytest.skip("Test requires real worker-side timeout cancellation delivery") + + def alive_thread_count(executor: ThreadPoolExecutor) -> int: + return sum(1 for thread in list(executor._threads) if thread.is_alive()) + + after_return_started = asyncio.Event() + allow_completion = asyncio.Event() + act_task_queue = str(uuid.uuid4()) + + with ThreadPoolExecutor(max_workers=1) as executor: + with pytest.warns( + UserWarning, + match="Worker max_concurrent_activities is 2 but activity_executor's max_workers is only", + ): + act_worker = Worker( + client, + task_queue=act_task_queue, + activities=[ + post_return_cancel_activity, + post_return_cancel_probe_activity, + ], + activity_executor=executor, + interceptors=[ + PostReturnCancelInterceptor(after_return_started, allow_completion) + ], + max_concurrent_activities=2, + shared_state_manager=shared_state_manager, + ) + + async with act_worker: + try: + timed_out_workflow = asyncio.create_task( + client.execute_workflow( + "kitchen_sink", + KSWorkflowParams( + actions=[ + KSAction( + execute_activity=KSExecuteActivityAction( + name="post_return_cancel_activity", + task_queue=act_task_queue, + start_to_close_timeout_ms=200, + retry_max_attempts=1, + ) + ) + ] + ), + id=str(uuid.uuid4()), + task_queue=worker.task_queue, + ) + ) + await asyncio.wait_for(after_return_started.wait(), timeout=5) + + with pytest.raises(WorkflowFailureError) as err: + await timed_out_workflow + timeout = assert_activity_error(err.value) + assert isinstance(timeout, TimeoutError) + assert timeout.type == TimeoutType.START_TO_CLOSE + + activity_worker = act_worker._activity_worker + assert activity_worker + for _ in range(50): + if any( + running.cancelled_event and running.cancelled_event.is_set() + for running in activity_worker._running_activities.values() + ): + break + await asyncio.sleep(0.1) + else: + pytest.fail("Timed out waiting for activity cancellation") + + probe_result = await asyncio.wait_for( + client.execute_workflow( + "kitchen_sink", + KSWorkflowParams( + actions=[ + KSAction( + execute_activity=KSExecuteActivityAction( + name="post_return_cancel_probe_activity", + task_queue=act_task_queue, + start_to_close_timeout_ms=30000, + retry_max_attempts=1, + ) + ) + ] + ), + id=str(uuid.uuid4()), + task_queue=worker.task_queue, + ), + timeout=5, + ) + assert probe_result == "probe" + assert alive_thread_count(executor) == 1 + finally: + allow_completion.set() + + @activity.defn async def local_without_schedule_to_close_activity() -> str: return "some-activity" From 1d2cd94762fc5cfc53184a7813bf32316c793753 Mon Sep 17 00:00:00 2001 From: xumaple <45406854+xumaple@users.noreply.github.com> Date: Mon, 20 Jul 2026 14:27:02 -0400 Subject: [PATCH 169/226] Fix stale workflow.tracer() references in OpenTelemetry contrib (#1662) workflow.tracer() does not exist; point the plugin and completed_span docstrings and the README at opentelemetry.trace.get_tracer(). --- temporalio/contrib/opentelemetry/README.md | 2 +- temporalio/contrib/opentelemetry/_plugin.py | 2 +- temporalio/contrib/opentelemetry/workflow.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/temporalio/contrib/opentelemetry/README.md b/temporalio/contrib/opentelemetry/README.md index 9f1e1303b..2c6e39817 100644 --- a/temporalio/contrib/opentelemetry/README.md +++ b/temporalio/contrib/opentelemetry/README.md @@ -68,7 +68,7 @@ worker = Worker( - **Accurate Duration Spans**: Workflow spans have real durations reflecting actual execution time - **Direct OpenTelemetry Usage**: Use `opentelemetry.trace.get_tracer()` directly within workflows - **Better Span Hierarchy**: More accurate parent-child relationships within workflows -- **Workflow Context Access**: Access spans within workflows using `temporalio.contrib.opentelemetry.workflow.tracer()` +- **Workflow Context Access**: Access spans within workflows using `opentelemetry.trace.get_tracer()` #### ⚠️ Considerations: - **Experimental Status**: Subject to breaking changes in future versions diff --git a/temporalio/contrib/opentelemetry/_plugin.py b/temporalio/contrib/opentelemetry/_plugin.py index 2a0e1e06c..2537c1776 100644 --- a/temporalio/contrib/opentelemetry/_plugin.py +++ b/temporalio/contrib/opentelemetry/_plugin.py @@ -18,7 +18,7 @@ class OpenTelemetryPlugin(SimplePlugin): It uses the new OpenTelemetryInterceptor implementation. Unlike the prior TracingInterceptor, this allows for accurate duration spans and parenting inside a workflow - with temporalio.contrib.opentelemetry.workflow.tracer() + using opentelemetry.trace.get_tracer() directly. Your tracer provider should be created with `create_tracer_provider` for it to be used within a Temporal worker. """ diff --git a/temporalio/contrib/opentelemetry/workflow.py b/temporalio/contrib/opentelemetry/workflow.py index 299e72b24..e872979a4 100644 --- a/temporalio/contrib/opentelemetry/workflow.py +++ b/temporalio/contrib/opentelemetry/workflow.py @@ -30,7 +30,7 @@ def completed_span( span and this interceptor is configured on the worker and the span is on the context). - To create a long-running span or to create a span that actually spans other code use OpenTelemetryPlugin and tracer(). + To create a long-running span or to create a span that actually spans other code use OpenTelemetryPlugin and opentelemetry.trace.get_tracer(). Args: name: Name of the span. From 41f67aaaa224224a07171d39cd4018b718097ad5 Mon Sep 17 00:00:00 2001 From: David Hyde Date: Tue, 21 Jul 2026 11:22:42 -0500 Subject: [PATCH 170/226] Fix type checking for google-genai 2.12.0 (#1652) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Fix google_genai type checking under google-genai 2.12.0 google-genai 2.12.0 exports two Interaction names from google.genai.interactions: the interaction resource class and a TypeAliasType over the trigger-request variants. Runtime star-import ordering deliberately binds the name to the resource class, but type checkers resolve it to the alias, which cannot be used with isinstance and lacks the resource fields — mypy fails with 34 errors (first seen on test-latest-deps when 2.12.0 released). Add a _compat shim that keeps the runtime binding on the public path (the imported object is unchanged — identity-verified against 2.10.0 and 2.12.0) and points the static view at the class's defining module, which is the same location in both versions. Redirect the three import sites through the shim. Verified with mypy, pyright, and basedpyright plus the google_genai test suite (62 passed) under both google-genai 2.10.0 (locked) and 2.12.0 (latest). * Clarify comments * Correct comments --- temporalio/contrib/google_genai/_compat.py | 24 +++++++++++++++++++ .../contrib/google_genai/_gemini_activity.py | 2 +- .../google_genai/_temporal_interactions.py | 3 ++- tests/contrib/google_genai/test_gemini.py | 2 +- 4 files changed, 28 insertions(+), 3 deletions(-) create mode 100644 temporalio/contrib/google_genai/_compat.py diff --git a/temporalio/contrib/google_genai/_compat.py b/temporalio/contrib/google_genai/_compat.py new file mode 100644 index 000000000..6613e2b9c --- /dev/null +++ b/temporalio/contrib/google_genai/_compat.py @@ -0,0 +1,24 @@ +"""Version-compatibility shims for the ``google-genai`` SDK. + +Single home for workarounds that keep the plugin importable and +type-checkable across the supported ``google-genai`` range; remove entries +as upstream fixes land. +""" + +from __future__ import annotations + +from typing import TYPE_CHECKING + +if TYPE_CHECKING: + # google-genai 2.12.0 exports two ``Interaction`` names: the interaction + # resource class and a ``TypeAliasType`` over the trigger-request + # variants. At runtime we get the resource class but type checkers + # resolve to the alias which causes failures (the alias has no ``id``, + # etc.). Force the type checker to see the class' defining module (in + # the same location in 2.10 and 2.12). + from google.genai._gaos.types.interactions.interaction import Interaction +else: + # At runtime, Interaction resolves properly for 2.10 and 2.12 + from google.genai.interactions import Interaction + +__all__ = ["Interaction"] diff --git a/temporalio/contrib/google_genai/_gemini_activity.py b/temporalio/contrib/google_genai/_gemini_activity.py index 2e92c56a1..496bbf1ab 100644 --- a/temporalio/contrib/google_genai/_gemini_activity.py +++ b/temporalio/contrib/google_genai/_gemini_activity.py @@ -17,11 +17,11 @@ from google.genai import Client as GeminiClient from google.genai import errors as genai_errors from google.genai import types -from google.genai.interactions import Interaction from google.genai.types import HttpOptions from google.genai.types import HttpResponse as SdkHttpResponse from temporalio import activity +from temporalio.contrib.google_genai._compat import Interaction from temporalio.contrib.google_genai._models import ( _GeminiApiRequest, _GeminiApiResponse, diff --git a/temporalio/contrib/google_genai/_temporal_interactions.py b/temporalio/contrib/google_genai/_temporal_interactions.py index b5eb2edc0..54d8353cd 100644 --- a/temporalio/contrib/google_genai/_temporal_interactions.py +++ b/temporalio/contrib/google_genai/_temporal_interactions.py @@ -20,9 +20,10 @@ from typing import Any, cast import pydantic -from google.genai.interactions import Interaction, InteractionSSEEvent +from google.genai.interactions import InteractionSSEEvent from temporalio import workflow as temporal_workflow +from temporalio.contrib.google_genai._compat import Interaction from temporalio.contrib.google_genai._models import ( _GeminiInteractionIdRequest, _GeminiInteractionRequest, diff --git a/tests/contrib/google_genai/test_gemini.py b/tests/contrib/google_genai/test_gemini.py index 543ad648c..0881f63b3 100644 --- a/tests/contrib/google_genai/test_gemini.py +++ b/tests/contrib/google_genai/test_gemini.py @@ -32,7 +32,6 @@ from google.genai import types from google.genai.interactions import ( Agent, # pyright: ignore[reportPrivateImportUsage] - Interaction, InteractionSSEEvent, ) from google.genai.types import HttpResponse as SdkHttpResponse @@ -45,6 +44,7 @@ GoogleGenAIPlugin, activity_as_tool, ) +from temporalio.contrib.google_genai._compat import Interaction from temporalio.contrib.google_genai._models import ( _GeminiApiRequest, _GeminiApiResponse, From b9168c1d8c68a84ab709633f39c26dbaa4997f05 Mon Sep 17 00:00:00 2001 From: Justin Anderson <44687433+jmaeagle99@users.noreply.github.com> Date: Tue, 21 Jul 2026 09:59:45 -0700 Subject: [PATCH 171/226] :boom: refactor: payloads/memo size validation (#1640) --- CHANGELOG.md | 6 + temporalio/bridge/client.py | 2 + temporalio/bridge/sdk-core | 2 +- temporalio/bridge/src/client.rs | 6 + temporalio/bridge/src/worker.rs | 23 +- temporalio/bridge/worker.py | 28 +- temporalio/client/__init__.py | 2 + temporalio/client/_client.py | 6 + temporalio/converter/__init__.py | 6 - temporalio/converter/_data_converter.py | 67 --- temporalio/converter/_failure_converter.py | 5 +- temporalio/converter/_payload_limits.py | 47 -- temporalio/runtime.py | 1 + temporalio/service.py | 17 + temporalio/worker/_activity.py | 227 ++++----- temporalio/worker/_nexus.py | 10 +- temporalio/worker/_replayer.py | 3 +- temporalio/worker/_worker.py | 25 +- temporalio/worker/_workflow.py | 37 +- tests/worker/test_payload_size_limits.py | 565 +++++---------------- 20 files changed, 287 insertions(+), 798 deletions(-) delete mode 100644 temporalio/converter/_payload_limits.py diff --git a/CHANGELOG.md b/CHANGELOG.md index cf1b7bafe..98b968dfc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -30,6 +30,12 @@ to include examples, links to docs, or any other relevant information. ### Breaking Changes +- Payload size limits have moved from `DataConverter` to `Client.connect`. Pass + `payload_limits=PayloadLimitsConfig(...)` (now exported from + `temporalio.client`) instead of setting `payload_limits` on `DataConverter`. + Config fields were renamed to `payloads_warn_size` and `memo_warn_size`, and + the deprecated `PayloadSizeWarning` was removed. + ### Fixed ### Security diff --git a/temporalio/bridge/client.py b/temporalio/bridge/client.py index c2c5bef6e..cdaf2e178 100644 --- a/temporalio/bridge/client.py +++ b/temporalio/bridge/client.py @@ -82,6 +82,8 @@ class ClientConfig: http_connect_proxy_config: ClientHttpConnectProxyConfig | None dns_load_balancing_config: ClientDnsLoadBalancingConfig | None grpc_compression: str + payloads_warn_size: int + memo_warn_size: int @dataclass diff --git a/temporalio/bridge/sdk-core b/temporalio/bridge/sdk-core index 467e871aa..3dac9013b 160000 --- a/temporalio/bridge/sdk-core +++ b/temporalio/bridge/sdk-core @@ -1 +1 @@ -Subproject commit 467e871aa922ecfeeba8a778b7b9b9de19849acc +Subproject commit 3dac9013b9031e5ffd51d7335838585b2db42efb diff --git a/temporalio/bridge/src/client.rs b/temporalio/bridge/src/client.rs index 85dedef94..aaa280a30 100644 --- a/temporalio/bridge/src/client.rs +++ b/temporalio/bridge/src/client.rs @@ -38,6 +38,8 @@ pub struct ClientConfig { http_connect_proxy_config: Option, dns_load_balancing_config: Option, grpc_compression: String, + payloads_warn_size: u64, + memo_warn_size: u64, } #[derive(FromPyObject)] @@ -268,6 +270,10 @@ impl ClientConfig { .maybe_http_connect_proxy(self.http_connect_proxy_config.map(Into::into)) .dns_load_balancing(dns_load_balancing) .grpc_compression(grpc_compression_from_str(&self.grpc_compression)?) + .payload_limits(temporalio_client::PayloadLimitsOptions { + payloads_warn_size: self.payloads_warn_size, + memo_warn_size: self.memo_warn_size, + }) .headers(ascii_headers) .binary_headers(binary_headers) .maybe_api_key(self.api_key) diff --git a/temporalio/bridge/src/worker.rs b/temporalio/bridge/src/worker.rs index 223b220f0..15518b224 100644 --- a/temporalio/bridge/src/worker.rs +++ b/temporalio/bridge/src/worker.rs @@ -63,6 +63,7 @@ pub struct WorkerConfig { nexus_task_poller_behavior: PollerBehavior, plugins: Vec, storage_drivers: HashSet, + disable_payload_error_limit: bool, } #[derive(FromPyObject)] @@ -774,6 +775,7 @@ fn convert_worker_config( .map(|r#type| StorageDriverInfo { r#type }) .collect::>(), ) + .disable_payload_error_limit(conf.disable_payload_error_limit) .build() .map_err(|err| PyValueError::new_err(format!("Invalid worker config: {err}"))) } @@ -827,11 +829,13 @@ fn convert_tuner_holder( } Ok(temporalio_sdk_core::TunerHolderOptions::builder() - .maybe_resource_based_options(first.map(|first| { - temporalio_sdk_core::ResourceBasedSlotsOptions::builder() - .target_mem_usage(first.target_memory_usage) - .target_cpu_usage(first.target_cpu_usage) - .build() + .maybe_resource_based_config(first.map(|first| { + temporalio_sdk_core::ResourceBasedTunerConfig::Options( + temporalio_sdk_core::ResourceBasedSlotsOptions::builder() + .target_mem_usage(first.target_memory_usage) + .target_cpu_usage(first.target_cpu_usage) + .build(), + ) })) .workflow_slot_options(convert_slot_supplier( holder.workflow_slot_supplier, @@ -899,10 +903,11 @@ fn convert_versioning_strategy( use_worker_versioning: options.use_worker_versioning, default_versioning_behavior: if options.use_worker_versioning { Some( - options - .default_versioning_behavior - .try_into() - .unwrap_or_default(), + temporalio_common::protos::temporal::api::enums::v1::VersioningBehavior::try_from( + options.default_versioning_behavior, + ) + .unwrap_or_default() + .into(), ) } else { None diff --git a/temporalio/bridge/worker.py b/temporalio/bridge/worker.py index e1e23dd89..6554c508c 100644 --- a/temporalio/bridge/worker.py +++ b/temporalio/bridge/worker.py @@ -58,6 +58,7 @@ class WorkerConfig: nexus_task_poller_behavior: PollerBehavior plugins: Sequence[str] storage_drivers: set[str] + disable_payload_error_limit: bool @dataclass @@ -284,10 +285,8 @@ class _Visitor(VisitorFunctions): def __init__( self, f: Callable[[Sequence[Payload]], Awaitable[list[Payload]]], - visit_system_nexus_envelope: Callable[[Payload], Awaitable[None]] | None = None, ): self._f = f - self._visit_system_nexus_envelope = visit_system_nexus_envelope async def visit_payload(self, payload: Payload) -> None: new_payload = (await self._f([payload]))[0] @@ -303,10 +302,6 @@ async def visit_payloads(self, payloads: PayloadSequence) -> None: del payloads[:] payloads.extend(new_payloads) - async def visit_system_nexus_envelope(self, payload: Payload) -> None: - if self._visit_system_nexus_envelope is not None: - await self._visit_system_nexus_envelope(payload) - async def decode_activation( activation: temporalio.bridge.proto.workflow_activation.WorkflowActivation, @@ -348,28 +343,14 @@ async def encode_completion( Returns: Metrics from any external storage store operations that occurred. """ - - async def _validate_system_nexus_envelope(payload: Payload) -> None: - data_converter._validate_payload_limits([payload]) - await CommandAwarePayloadVisitor( skip_search_attributes=True, skip_headers=not encode_headers, ).visit( - _Visitor( - data_converter._encode_payload_sequence, - visit_system_nexus_envelope=_validate_system_nexus_envelope, - ), + _Visitor(data_converter._encode_payload_sequence), completion, ) - async def _store_and_validate( - payloads: Sequence[Payload], - ) -> list[Payload]: - stored = await data_converter._external_store_payload_sequence(payloads) - data_converter._validate_payload_limits(stored) - return stored - metrics = temporalio.converter._extstore.StorageOperationMetrics() with metrics.track(): await CommandAwarePayloadVisitor( @@ -377,10 +358,7 @@ async def _store_and_validate( skip_headers=not encode_headers, concurrency_limit=storage_concurrency_limit, ).visit( - _Visitor( - _store_and_validate, - visit_system_nexus_envelope=_validate_system_nexus_envelope, - ), + _Visitor(data_converter._external_store_payload_sequence), completion, ) diff --git a/temporalio/client/__init__.py b/temporalio/client/__init__.py index 030f9a542..cdb34b860 100644 --- a/temporalio/client/__init__.py +++ b/temporalio/client/__init__.py @@ -19,6 +19,7 @@ GrpcCompression, HttpConnectProxyConfig, KeepAliveConfig, + PayloadLimitsConfig, RetryConfig, RPCError, RPCStatusCode, @@ -359,6 +360,7 @@ "GrpcCompression", "HttpConnectProxyConfig", "KeepAliveConfig", + "PayloadLimitsConfig", "RetryConfig", "RPCError", "RPCStatusCode", diff --git a/temporalio/client/_client.py b/temporalio/client/_client.py index 5efca9702..5acdfe476 100644 --- a/temporalio/client/_client.py +++ b/temporalio/client/_client.py @@ -35,6 +35,7 @@ GrpcCompression, HttpConnectProxyConfig, KeepAliveConfig, + PayloadLimitsConfig, RetryConfig, ServiceClient, TLSConfig, @@ -154,6 +155,7 @@ async def connect( http_connect_proxy_config: HttpConnectProxyConfig | None = None, dns_load_balancing_config: DnsLoadBalancingConfig | None = None, grpc_compression: GrpcCompression = GrpcCompression.GZIP, + payload_limits: PayloadLimitsConfig = PayloadLimitsConfig(), header_codec_behavior: HeaderCodecBehavior = HeaderCodecBehavior.NO_CODEC, ) -> Self: """Connect to a Temporal server. @@ -217,6 +219,8 @@ async def connect( grpc_compression: Transport-level gRPC compression for the client connection. Default is gzip. Set to :py:attr:`GrpcCompression.NONE` to disable compression. + payload_limits: Warning thresholds for outbound payload/memo sizes. Over-threshold + fields are logged but still sent. Set a threshold to 0 to disable it. header_codec_behavior: Encoding behavior for headers sent by the client. """ connect_config = temporalio.service.ConnectConfig( @@ -232,6 +236,7 @@ async def connect( http_connect_proxy_config=http_connect_proxy_config, dns_load_balancing_config=dns_load_balancing_config, grpc_compression=grpc_compression, + payload_limits=payload_limits, ) def make_lambda( @@ -3049,6 +3054,7 @@ class ClientConnectConfig(TypedDict, total=False): http_connect_proxy_config: HttpConnectProxyConfig | None dns_load_balancing_config: DnsLoadBalancingConfig | None grpc_compression: GrpcCompression + payload_limits: PayloadLimitsConfig header_codec_behavior: HeaderCodecBehavior diff --git a/temporalio/converter/__init__.py b/temporalio/converter/__init__.py index 3821cbd68..9192eb704 100644 --- a/temporalio/converter/__init__.py +++ b/temporalio/converter/__init__.py @@ -35,10 +35,6 @@ PayloadConverter, value_to_type, ) -from temporalio.converter._payload_limits import ( - PayloadLimitsConfig, - PayloadSizeWarning, -) from temporalio.converter._search_attributes import ( decode_search_attributes, decode_typed_search_attributes, @@ -80,8 +76,6 @@ "JSONTypeConverterUnhandled", "PayloadCodec", "PayloadConverter", - "PayloadLimitsConfig", - "PayloadSizeWarning", "SerializationContext", "WithSerializationContext", "WorkflowSerializationContext", diff --git a/temporalio/converter/_data_converter.py b/temporalio/converter/_data_converter.py index 13b48e695..823d1cc13 100644 --- a/temporalio/converter/_data_converter.py +++ b/temporalio/converter/_data_converter.py @@ -3,7 +3,6 @@ from __future__ import annotations import dataclasses -import warnings from collections.abc import Mapping, Sequence from dataclasses import dataclass from logging import getLogger @@ -30,12 +29,6 @@ from temporalio.converter._payload_converter import ( PayloadConverter, ) -from temporalio.converter._payload_limits import ( - PayloadLimitsConfig, - PayloadSizeWarning, - _PayloadSizeError, - _ServerPayloadErrorLimits, -) from temporalio.converter._serialization_context import ( SerializationContext, WithSerializationContext, @@ -86,9 +79,6 @@ class DataConverter(WithSerializationContext): failure_converter: FailureConverter = dataclasses.field(init=False) """Failure converter created from the :py:attr:`failure_converter_class`.""" - payload_limits: PayloadLimitsConfig = PayloadLimitsConfig() - """Settings for payload size limits.""" - external_storage: ExternalStorage | None = None """Options for external storage. If None, external storage is disabled. @@ -99,9 +89,6 @@ class DataConverter(WithSerializationContext): default: ClassVar[DataConverter] """Singleton default data converter.""" - _payload_error_limits: _ServerPayloadErrorLimits | None = None - """Server-reported limits for payloads.""" - def __post_init__(self) -> None: # noqa: D105 object.__setattr__(self, "payload_converter", self.payload_converter_class()) object.__setattr__(self, "failure_converter", self.failure_converter_class()) @@ -124,7 +111,6 @@ async def encode( payloads = self.payload_converter.to_payloads(values) payloads = await self._encode_payload_sequence(payloads) payloads = await self._external_store_payload_sequence(payloads) - self._validate_payload_limits(payloads) return payloads async def decode( @@ -230,11 +216,6 @@ def _with_contexts( """Return an instance with both serialization and store contexts applied.""" return self.with_context(serialization_ctx)._with_store_context(store_ctx) - def _with_payload_error_limits( - self, limits: _ServerPayloadErrorLimits | None - ) -> DataConverter: - return dataclasses.replace(self, _payload_error_limits=limits) - async def _decode_memo( self, source: temporalio.api.common.v1.Memo, @@ -273,16 +254,6 @@ async def _encode_memo_existing( if not isinstance(v, temporalio.api.common.v1.Payload): payload = (await self.encode([v]))[0] memo.fields[k].CopyFrom(payload) - # Memos have their field payloads validated all together in one unit - DataConverter._validate_limits( - list(memo.fields.values()), - self._payload_error_limits.memo_size_error - if self._payload_error_limits - else None, - "[TMPRL1103] Attempted to upload memo with size that exceeded the error limit.", - self.payload_limits.memo_size_warning, - "[TMPRL1103] Attempted to upload memo with size that exceeded the warning limit.", - ) async def _transform_outbound_payload( self, payload: temporalio.api.common.v1.Payload @@ -291,7 +262,6 @@ async def _transform_outbound_payload( payload = (await self.payload_codec.encode([payload]))[0] if self.external_storage: payload = await self.external_storage._store_payload(payload) - self._validate_payload_limits([payload]) return payload async def _transform_outbound_payloads( @@ -301,7 +271,6 @@ async def _transform_outbound_payloads( await self.payload_codec.encode_wrapper(payloads) if self.external_storage: await self.external_storage._store_payloads(payloads) - self._validate_payload_limits(payloads.payloads) async def _transform_inbound_payload( self, payload: temporalio.api.common.v1.Payload @@ -376,42 +345,6 @@ async def _decode_payload_sequence( def _decode_payload_has_effect(self) -> bool: return self.payload_codec is not None or self.external_storage is not None - def _validate_payload_limits( - self, - payloads: Sequence[temporalio.api.common.v1.Payload], - ): - DataConverter._validate_limits( - payloads, - self._payload_error_limits.payload_size_error - if self._payload_error_limits - else None, - "[TMPRL1103] Attempted to upload payloads with size that exceeded the error limit.", - self.payload_limits.payload_size_warning, - "[TMPRL1103] Attempted to upload payloads with size that exceeded the warning limit.", - ) - - @staticmethod - def _validate_limits( - payloads: Sequence[temporalio.api.common.v1.Payload], - error_limit: int | None, - error_message: str, - warning_limit: int, - warning_message: str, - ): - total_size = sum(payload.ByteSize() for payload in payloads) - - if error_limit and error_limit > 0 and total_size > error_limit: - raise _PayloadSizeError( - f"{error_message} Size: {total_size} bytes, Limit: {error_limit} bytes" - ) - - if warning_limit > 0 and total_size > warning_limit: - # TODO: Use a context aware logger to log extra information about workflow/activity/etc - warnings.warn( - f"{warning_message} Size: {total_size} bytes, Limit: {warning_limit} bytes", - PayloadSizeWarning, - ) - def default() -> DataConverter: """Default data converter. diff --git a/temporalio/converter/_failure_converter.py b/temporalio/converter/_failure_converter.py index c76f95c23..848dbc038 100644 --- a/temporalio/converter/_failure_converter.py +++ b/temporalio/converter/_failure_converter.py @@ -17,7 +17,6 @@ import temporalio.api.failure.v1 import temporalio.exceptions from temporalio.converter._payload_converter import PayloadConverter -from temporalio.converter._payload_limits import _PayloadSizeError logger = getLogger("temporalio.converter") @@ -108,9 +107,7 @@ def to_failure( # Convert to failure error failure_error = temporalio.exceptions.ApplicationError( str(exception), - type="PayloadSizeError" - if isinstance(exception, _PayloadSizeError) - else exception.__class__.__name__, + type=exception.__class__.__name__, ) failure_error.__traceback__ = exception.__traceback__ failure_error.__cause__ = exception.__cause__ diff --git a/temporalio/converter/_payload_limits.py b/temporalio/converter/_payload_limits.py deleted file mode 100644 index d6eb0b1d2..000000000 --- a/temporalio/converter/_payload_limits.py +++ /dev/null @@ -1,47 +0,0 @@ -"""Payload size limit configuration and related types.""" - -from __future__ import annotations - -from dataclasses import dataclass - -import temporalio.exceptions - - -@dataclass(frozen=True) -class PayloadLimitsConfig: - """Configuration for when payload sizes exceed limits.""" - - memo_size_warning: int = 2 * 1024 - """The limit (in bytes) at which a memo size warning is logged.""" - - payload_size_warning: int = 512 * 1024 - """The limit (in bytes) at which a payload size warning is logged.""" - - -class PayloadSizeWarning(RuntimeWarning): - """The size of payloads is above the warning limit.""" - - -class _PayloadSizeError(temporalio.exceptions.TemporalError): # type:ignore[reportUnusedClass] - """Error raised when payloads size exceeds payload size limits.""" - - def __init__(self, message: str): - """Initialize a payloads size error.""" - super().__init__(message) - self._message = message - - @property - def message(self) -> str: - """Message.""" - return self._message - - -@dataclass(frozen=True) -class _ServerPayloadErrorLimits: # type:ignore[reportUnusedClass] - """Error limits for payloads as described by the Temporal server.""" - - memo_size_error: int - """The limit (in bytes) at which a memo size error is raised.""" - - payload_size_error: int - """The limit (in bytes) at which a payload size error is raised.""" diff --git a/temporalio/runtime.py b/temporalio/runtime.py index 8fab68e9e..94ba9f95d 100644 --- a/temporalio/runtime.py +++ b/temporalio/runtime.py @@ -180,6 +180,7 @@ def formatted(self) -> str: # We intentionally aren't using __str__ or __format__ so they can keep # their original dataclass impls targets = [ + "temporalio_common", "temporalio_sdk_core", "temporalio_client", "temporalio_sdk", diff --git a/temporalio/service.py b/temporalio/service.py index d4cb79720..56179472b 100644 --- a/temporalio/service.py +++ b/temporalio/service.py @@ -192,6 +192,20 @@ def _to_bridge_config(self) -> str: GrpcCompression.GZIP = _GzipGrpcCompression() +@dataclass(frozen=True) +class PayloadLimitsConfig: + """Warning thresholds for outbound payload/memo sizes.""" + + # Defaults mirror the Temporal server's `limit.blobSize.warn` (512 KiB) and `limit.memoSize.warn` + # (2 KiB) dynamic-config defaults, so the SDK warns at the same sizes the server would. + payloads_warn_size: int = 512 * 1024 + """Warning threshold, in bytes, for the size of an outbound payload-bearing field. Set to 0 to + disable.""" + + memo_warn_size: int = 2 * 1024 + """Warning threshold, in bytes, for outbound memo size. Set to 0 to disable.""" + + @dataclass class ConnectConfig: """Config for connecting to the server.""" @@ -208,6 +222,7 @@ class ConnectConfig: http_connect_proxy_config: HttpConnectProxyConfig | None = None dns_load_balancing_config: DnsLoadBalancingConfig | None = None grpc_compression: GrpcCompression = GrpcCompression.GZIP + payload_limits: PayloadLimitsConfig = field(default_factory=PayloadLimitsConfig) def __post_init__(self) -> None: """Set extra defaults on unset properties.""" @@ -271,6 +286,8 @@ def _to_bridge_config(self) -> temporalio.bridge.client.ClientConfig: else None ), grpc_compression=self.grpc_compression._to_bridge_config(), + payloads_warn_size=self.payload_limits.payloads_warn_size, + memo_warn_size=self.payload_limits.memo_warn_size, ) diff --git a/temporalio/worker/_activity.py b/temporalio/worker/_activity.py index 8dd5fe12a..0304b3b75 100644 --- a/temporalio/worker/_activity.py +++ b/temporalio/worker/_activity.py @@ -32,7 +32,6 @@ import temporalio.client import temporalio.common import temporalio.converter -import temporalio.converter._payload_limits import temporalio.exceptions from temporalio.converter import ( StorageDriverActivityInfo, @@ -132,15 +131,8 @@ def __init__( else: self._dynamic_activity = defn - async def run( - self, - payload_error_limits: temporalio.converter._payload_limits._ServerPayloadErrorLimits - | None, - ) -> None: + async def run(self) -> None: """Continually poll for activity tasks and dispatch to handlers.""" - self._data_converter = self._data_converter._with_payload_error_limits( - payload_error_limits - ) async def raise_from_exception_queue() -> NoReturn: raise await self._fail_worker_exception_queue.get() @@ -363,136 +355,111 @@ async def _handle_start_activity_task( completion.result.completed.result.CopyFrom(payload) except BaseException as err: try: - try: - if isinstance(err, temporalio.activity._CompleteAsyncError): - temporalio.activity.logger.debug("Completing asynchronously") - completion.result.will_complete_async.SetInParent() - elif ( - isinstance( - err, - ( - asyncio.CancelledError, - temporalio.exceptions.CancelledError, - ), - ) - and running_activity.cancelled_due_to_heartbeat_error - ): - err = running_activity.cancelled_due_to_heartbeat_error - temporalio.activity.logger.warning( - f"Completing as failure during heartbeat with error of type {type(err)}: {err}", - ) - await data_converter.encode_failure( - err, completion.result.failed.failure - ) - elif ( - isinstance( - err, - ( - asyncio.CancelledError, - temporalio.exceptions.CancelledError, - ), - ) - and running_activity.cancellation_details.details - and running_activity.cancellation_details.details.paused - ): - temporalio.activity.logger.warning( - "Completing as failure due to unhandled cancel error produced by activity pause", - ) - await data_converter.encode_failure( - temporalio.exceptions.ApplicationError( - type="ActivityPause", - message="Unhandled activity cancel error produced by activity pause", - ), - completion.result.failed.failure, - ) - elif ( - isinstance( - err, - ( - asyncio.CancelledError, - temporalio.exceptions.CancelledError, - ), - ) - and running_activity.cancellation_details.details - and running_activity.cancellation_details.details.reset - ): - temporalio.activity.logger.warning( - "Completing as failure due to unhandled cancel error produced by activity reset", - ) - await data_converter.encode_failure( - temporalio.exceptions.ApplicationError( - type="ActivityReset", - message="Unhandled activity cancel error produced by activity reset", - ), - completion.result.failed.failure, - ) - elif ( + if isinstance(err, temporalio.activity._CompleteAsyncError): + temporalio.activity.logger.debug("Completing asynchronously") + completion.result.will_complete_async.SetInParent() + elif ( + isinstance( + err, + ( + asyncio.CancelledError, + temporalio.exceptions.CancelledError, + ), + ) + and running_activity.cancelled_due_to_heartbeat_error + ): + err = running_activity.cancelled_due_to_heartbeat_error + temporalio.activity.logger.warning( + f"Completing as failure during heartbeat with error of type {type(err)}: {err}", + ) + await data_converter.encode_failure( + err, completion.result.failed.failure + ) + elif ( + isinstance( + err, + ( + asyncio.CancelledError, + temporalio.exceptions.CancelledError, + ), + ) + and running_activity.cancellation_details.details + and running_activity.cancellation_details.details.paused + ): + temporalio.activity.logger.warning( + "Completing as failure due to unhandled cancel error produced by activity pause", + ) + await data_converter.encode_failure( + temporalio.exceptions.ApplicationError( + type="ActivityPause", + message="Unhandled activity cancel error produced by activity pause", + ), + completion.result.failed.failure, + ) + elif ( + isinstance( + err, + ( + asyncio.CancelledError, + temporalio.exceptions.CancelledError, + ), + ) + and running_activity.cancellation_details.details + and running_activity.cancellation_details.details.reset + ): + temporalio.activity.logger.warning( + "Completing as failure due to unhandled cancel error produced by activity reset", + ) + await data_converter.encode_failure( + temporalio.exceptions.ApplicationError( + type="ActivityReset", + message="Unhandled activity cancel error produced by activity reset", + ), + completion.result.failed.failure, + ) + elif ( + isinstance( + err, + ( + asyncio.CancelledError, + temporalio.exceptions.CancelledError, + ), + ) + and running_activity.cancelled_by_request + ): + temporalio.activity.logger.debug("Completing as cancelled") + await data_converter.encode_failure( + # TODO(cretz): Should use some other message? + temporalio.exceptions.CancelledError("Cancelled"), + completion.result.cancelled.failure, + ) + else: + if ( isinstance( err, - ( - asyncio.CancelledError, - temporalio.exceptions.CancelledError, - ), + temporalio.exceptions.ApplicationError, ) - and running_activity.cancelled_by_request + and err.category + == temporalio.exceptions.ApplicationErrorCategory.BENIGN ): - temporalio.activity.logger.debug("Completing as cancelled") - await data_converter.encode_failure( - # TODO(cretz): Should use some other message? - temporalio.exceptions.CancelledError("Cancelled"), - completion.result.cancelled.failure, - ) - elif isinstance( - err, - temporalio.converter._payload_limits._PayloadSizeError, - ): - temporalio.activity.logger.warning( - err.message, - extra={"__temporal_error_identifier": "PayloadSizeError"}, - ) - await data_converter.encode_failure( - err, completion.result.failed.failure + # Downgrade log level to DEBUG for BENIGN application errors. + temporalio.activity.logger.debug( + "Completing activity as failed", + exc_info=True, + extra={"__temporal_error_identifier": "ActivityFailure"}, ) else: - if ( - isinstance( - err, - temporalio.exceptions.ApplicationError, - ) - and err.category - == temporalio.exceptions.ApplicationErrorCategory.BENIGN - ): - # Downgrade log level to DEBUG for BENIGN application errors. - temporalio.activity.logger.debug( - "Completing activity as failed", - exc_info=True, - extra={ - "__temporal_error_identifier": "ActivityFailure" - }, - ) - else: - temporalio.activity.logger.warning( - "Completing activity as failed", - exc_info=True, - extra={ - "__temporal_error_identifier": "ActivityFailure" - }, - ) - await data_converter.encode_failure( - err, completion.result.failed.failure + temporalio.activity.logger.warning( + "Completing activity as failed", + exc_info=True, + extra={"__temporal_error_identifier": "ActivityFailure"}, ) - # For broken executors, we have to fail the entire worker - if isinstance(err, concurrent.futures.BrokenExecutor): - self._fail_worker_exception_queue.put_nowait(err) - # Handle PayloadSizeError from attempting to encode failure information - except ( - temporalio.converter._payload_limits._PayloadSizeError - ) as inner_err: - temporalio.activity.logger.exception(inner_err.message) - completion.result.Clear() await data_converter.encode_failure( - inner_err, completion.result.failed.failure + err, completion.result.failed.failure ) + # For broken executors, we have to fail the entire worker + if isinstance(err, concurrent.futures.BrokenExecutor): + self._fail_worker_exception_queue.put_nowait(err) except Exception as inner_err: temporalio.activity.logger.exception( f"Exception handling failed, original error: {err}" diff --git a/temporalio/worker/_nexus.py b/temporalio/worker/_nexus.py index f35d10fd5..08ecd2f81 100644 --- a/temporalio/worker/_nexus.py +++ b/temporalio/worker/_nexus.py @@ -29,7 +29,6 @@ import temporalio.client import temporalio.common import temporalio.converter -import temporalio.converter._payload_limits import temporalio.nexus from temporalio.bridge.worker import PollShutdownError from temporalio.exceptions import ( @@ -96,15 +95,8 @@ def __init__( self._fail_worker_exception_queue: asyncio.Queue[Exception] = asyncio.Queue() self._worker_shutdown_event: temporalio.common._CompositeEvent | None = None - async def run( - self, - payload_error_limits: temporalio.converter._payload_limits._ServerPayloadErrorLimits - | None, - ) -> None: + async def run(self) -> None: """Continually poll for Nexus tasks and dispatch to handlers.""" - self._data_converter = self._data_converter._with_payload_error_limits( - payload_error_limits - ) async def raise_from_exception_queue() -> NoReturn: raise await self._fail_worker_exception_queue.get() diff --git a/temporalio/worker/_replayer.py b/temporalio/worker/_replayer.py index a9fc11b49..61dcb84f4 100644 --- a/temporalio/worker/_replayer.py +++ b/temporalio/worker/_replayer.py @@ -308,6 +308,7 @@ def on_eviction_hook( ), nonsticky_to_sticky_poll_ratio=1, no_remote_activities=True, + disable_payload_error_limit=True, task_types=temporalio.bridge.worker.WorkerTaskTypes( enable_workflows=True, enable_local_activities=False, @@ -340,7 +341,7 @@ def on_eviction_hook( bridge_worker_scope = bridge_worker # Start worker - workflow_worker_task = asyncio.create_task(workflow_worker.run(None)) + workflow_worker_task = asyncio.create_task(workflow_worker.run()) # Yield iterator async def replay_iterator() -> AsyncIterator[WorkflowReplayResult]: diff --git a/temporalio/worker/_worker.py b/temporalio/worker/_worker.py index 8f55e9632..5e2d8ce58 100644 --- a/temporalio/worker/_worker.py +++ b/temporalio/worker/_worker.py @@ -29,7 +29,6 @@ VersioningBehavior, WorkerDeploymentVersion, ) -from temporalio.converter._payload_limits import _ServerPayloadErrorLimits from ._activity import SharedStateManager, _ActivityWorker from ._interceptor import Interceptor @@ -679,6 +678,9 @@ def check_activity(activity: str): ]._to_bridge(), # type: ignore[reportTypedDictNotRequiredAccess,reportOptionalMemberAccess] plugins=deduped_plugin_names, storage_drivers=deduped_storage_driver_types, + disable_payload_error_limit=config.get( + "disable_payload_error_limit", False + ), ), ) @@ -780,17 +782,8 @@ def make_lambda(plugin: Plugin, next: Callable[[Worker], Awaitable[None]]): await next_function(self) async def _run(self): - # Eagerly validate which will do a namespace check in Core - namespace_info = await self._bridge_worker.validate() - payload_error_limits = ( - _ServerPayloadErrorLimits( - memo_size_error=namespace_info.limits.memo_size_limit_error, - payload_size_error=namespace_info.limits.blob_size_limit_error, - ) - if namespace_info.HasField("limits") - and not self._config.get("disable_payload_error_limit", False) - else None - ) + # Eagerly validate which will do a namespace check in Core. + await self._bridge_worker.validate() if self._started: raise RuntimeError("Already started") @@ -810,16 +803,14 @@ async def raise_on_shutdown(): # Create tasks for workers if self._activity_worker: tasks[self._activity_worker] = asyncio.create_task( - self._activity_worker.run(payload_error_limits) + self._activity_worker.run() ) if self._workflow_worker: tasks[self._workflow_worker] = asyncio.create_task( - self._workflow_worker.run(payload_error_limits) + self._workflow_worker.run() ) if self._nexus_worker: - tasks[self._nexus_worker] = asyncio.create_task( - self._nexus_worker.run(payload_error_limits) - ) + tasks[self._nexus_worker] = asyncio.create_task(self._nexus_worker.run()) # Wait for either worker or shutdown requested wait_task = asyncio.wait(tasks.values(), return_when=asyncio.FIRST_EXCEPTION) diff --git a/temporalio/worker/_workflow.py b/temporalio/worker/_workflow.py index 953e07a5a..b9513068d 100644 --- a/temporalio/worker/_workflow.py +++ b/temporalio/worker/_workflow.py @@ -23,10 +23,8 @@ import temporalio.common import temporalio.converter import temporalio.converter._extstore -import temporalio.converter._payload_limits import temporalio.exceptions import temporalio.workflow -from temporalio.api.enums.v1 import WorkflowTaskFailedCause from temporalio.bridge.worker import PollShutdownError from temporalio.converter import StorageDriverStoreContext, StorageDriverWorkflowInfo from temporalio.worker.workflow_sandbox._runner import SandboxedWorkflowRunner @@ -209,15 +207,7 @@ def __init__( else: self._dynamic_workflow = defn - async def run( - self, - payload_error_limits: temporalio.converter._payload_limits._ServerPayloadErrorLimits - | None, - ) -> None: - self._data_converter = self._data_converter._with_payload_error_limits( - payload_error_limits - ) - + async def run(self) -> None: # Continually poll for workflow work task_tag = object() try: @@ -489,18 +479,12 @@ async def _handle_activation( upload_metrics = temporalio.converter._extstore.StorageOperationMetrics() try: - try: - upload_metrics = await temporalio.bridge.worker.encode_completion( - completion, - data_converter, - encode_headers=self._encode_headers, - storage_concurrency_limit=self._max_workflow_task_external_storage_concurrency, - ) - except temporalio.converter._payload_limits._PayloadSizeError as err: - logger.warning(err.message) - completion.failed.Clear() - await data_converter.encode_failure(err, completion.failed.failure) - completion.failed.force_cause = WorkflowTaskFailedCause.WORKFLOW_TASK_FAILED_CAUSE_PAYLOADS_TOO_LARGE + upload_metrics = await temporalio.bridge.worker.encode_completion( + completion, + data_converter, + encode_headers=self._encode_headers, + storage_concurrency_limit=self._max_workflow_task_external_storage_concurrency, + ) except Exception as err: logger.exception( "Failed encoding completion on workflow with run ID %s", act.run_id @@ -981,7 +965,6 @@ def create( payload_converter_class=workflow_context_dc.payload_converter_class, payload_codec=workflow_context_dc.payload_codec, failure_converter_class=workflow_context_dc.failure_converter_class, - payload_limits=workflow_context_dc.payload_limits, external_storage=workflow_context_dc.external_storage, _ca_instance=instance, _ca_context_free_dc=context_free_dc, @@ -1024,12 +1007,6 @@ async def _decode_payload_sequence( ) -> list[temporalio.api.common.v1.Payload]: return await self._get_current_dc()._decode_payload_sequence(payloads) - def _validate_payload_limits( - self, - payloads: Sequence[temporalio.api.common.v1.Payload], - ) -> None: - self._get_current_dc()._validate_payload_limits(payloads) - class _InterruptDeadlockError(BaseException): pass diff --git a/tests/worker/test_payload_size_limits.py b/tests/worker/test_payload_size_limits.py index 202899c38..b527f429c 100644 --- a/tests/worker/test_payload_size_limits.py +++ b/tests/worker/test_payload_size_limits.py @@ -1,20 +1,14 @@ -import dataclasses import logging import uuid -import warnings from dataclasses import dataclass from datetime import timedelta import pytest -import temporalio -import temporalio.converter +import temporalio.api.enums.v1 from temporalio import activity, workflow -from temporalio.client import Client, WorkflowFailureError -from temporalio.converter import PayloadLimitsConfig, PayloadSizeWarning +from temporalio.client import Client, PayloadLimitsConfig, WorkflowFailureError from temporalio.exceptions import ( - ActivityError, - ApplicationError, TerminatedError, TimeoutError, TimeoutType, @@ -27,184 +21,68 @@ TelemetryFilter, ) from temporalio.testing._workflow import WorkflowEnvironment -from temporalio.worker._replayer import Replayer from tests import DEV_SERVER_DOWNLOAD_VERSION -from tests.helpers import LogCapturer, new_worker +from tests.helpers import LogCapturer, assert_eventually, new_worker + +# Payload/memo size-limit enforcement lives in sdk-rust. These tests only assert that the SDK's +# plumbing reaches core: oversized completions are failed proactively, the worker opt-out lets +# oversized payloads through to the server, and the connection's warn threshold produces a +# forwarded [TMPRL1103] warning. @dataclass class LargePayloadWorkflowInput: activity_input_data_size: int - activity_output_data_size: int - activity_exception_data_size: int workflow_output_data_size: int - data: str - - -@dataclass -class LargePayloadWorkflowOutput: - data: str @dataclass class LargePayloadActivityInput: - exception_data_size: int - output_data_size: int - data: str - - -@dataclass -class LargePayloadActivityOutput: data: str @activity.defn -async def large_payload_activity( - input: LargePayloadActivityInput, -) -> LargePayloadActivityOutput: - if input.exception_data_size > 0: - raise ApplicationError( - "Intentional activity failure", "e" * input.exception_data_size - ) - return LargePayloadActivityOutput(data="o" * input.output_data_size) +async def large_payload_activity(_input: LargePayloadActivityInput) -> None: + return None @workflow.defn class LargePayloadWorkflow: @workflow.run - async def run(self, input: LargePayloadWorkflowInput) -> LargePayloadWorkflowOutput: - await workflow.execute_activity( - large_payload_activity, - LargePayloadActivityInput( - exception_data_size=input.activity_exception_data_size, - output_data_size=input.activity_output_data_size, - data="i" * input.activity_input_data_size, - ), - schedule_to_close_timeout=timedelta(seconds=5), - ) - return LargePayloadWorkflowOutput(data="o" * input.workflow_output_data_size) + async def run(self, input: LargePayloadWorkflowInput) -> str: + if input.activity_input_data_size > 0: + await workflow.execute_activity( + large_payload_activity, + LargePayloadActivityInput(data="i" * input.activity_input_data_size), + schedule_to_close_timeout=timedelta(seconds=5), + ) + return "o" * input.workflow_output_data_size PAYLOAD_ERROR_LIMIT = 10 * 1024 PAYLOAD_LIMITS_EXTRA_ARGS = [ "--dynamic-config-value", f"limit.blobSize.error={PAYLOAD_ERROR_LIMIT}", - # Warn limit must be specified to have the server enforce the error limit + # The server only enforces the error limit for payloads that also exceed the warn limit, so the + # warn limit must be below the error limit. "--dynamic-config-value", f"limit.blobSize.warn={2 * 1024}", ] -async def test_payload_size_warning_workflow_input(client: Client): - config = client.config() - config["data_converter"] = dataclasses.replace( - temporalio.converter.default(), - payload_limits=PayloadLimitsConfig( - payload_size_warning=100, - ), - ) - client = Client(**config) - - with warnings.catch_warnings(record=True) as w: - async with new_worker( - client, LargePayloadWorkflow, activities=[large_payload_activity] - ) as worker: - await client.execute_workflow( - LargePayloadWorkflow.run, - LargePayloadWorkflowInput( - activity_input_data_size=0, - activity_output_data_size=0, - activity_exception_data_size=0, - workflow_output_data_size=0, - data="i" * 2 * 1024, - ), - id=f"workflow-{uuid.uuid4()}", - task_queue=worker.task_queue, +def _forwarding_runtime(logger: logging.Logger) -> Runtime: + return Runtime( + telemetry=TelemetryConfig( + logging=LoggingConfig( + filter=TelemetryFilter(core_level="WARN", other_level="ERROR"), + forwarding=LogForwardingConfig(logger=logger), ) - - assert len(w) == 1 - assert issubclass(w[-1].category, PayloadSizeWarning) - assert ( - "[TMPRL1103] Attempted to upload payloads with size that exceeded the warning limit." - in str(w[-1].message) ) - - -async def test_payload_size_warning_workflow_memo(client: Client): - config = client.config() - config["data_converter"] = dataclasses.replace( - temporalio.converter.default(), - payload_limits=PayloadLimitsConfig(memo_size_warning=128), ) - client = Client(**config) - - with warnings.catch_warnings(record=True) as w: - async with new_worker( - client, LargePayloadWorkflow, activities=[large_payload_activity] - ) as worker: - await client.execute_workflow( - LargePayloadWorkflow.run, - LargePayloadWorkflowInput( - activity_input_data_size=0, - activity_output_data_size=0, - activity_exception_data_size=0, - workflow_output_data_size=0, - data="", - ), - id=f"workflow-{uuid.uuid4()}", - task_queue=worker.task_queue, - memo={ - "key1": [0] * 64, - "key2": [0] * 64, - "key3": [0] * 64, - }, - ) - - assert len(w) == 1 - assert issubclass(w[-1].category, PayloadSizeWarning) - assert ( - "[TMPRL1103] Attempted to upload memo with size that exceeded the warning limit." - in str(w[-1].message) - ) - - -async def test_payload_size_error_disabled_workflow_payload(env: WorkflowEnvironment): - if env.supports_time_skipping: - pytest.skip("Time-skipping server does not report payload limits.") - - async with await WorkflowEnvironment.start_local( - dev_server_extra_args=PAYLOAD_LIMITS_EXTRA_ARGS, - dev_server_download_version=DEV_SERVER_DOWNLOAD_VERSION, - ) as env: - async with new_worker( - env.client, - LargePayloadWorkflow, - activities=[large_payload_activity], - disable_payload_error_limit=True, - ) as worker: - with pytest.raises(WorkflowFailureError) as err: - await env.client.execute_workflow( - LargePayloadWorkflow.run, - LargePayloadWorkflowInput( - activity_input_data_size=PAYLOAD_ERROR_LIMIT + 1024, - activity_output_data_size=0, - activity_exception_data_size=0, - workflow_output_data_size=0, - data="", - ), - id=f"workflow-{uuid.uuid4()}", - task_queue=worker.task_queue, - execution_timeout=timedelta(seconds=3), - ) - - assert isinstance(err.value.cause, TerminatedError) - assert ( - err.value.cause.message - == "BadScheduleActivityAttributes: ScheduleActivityTaskCommandAttributes.Input exceeds size limit." - ) -async def test_payload_size_error_workflow_result(env: WorkflowEnvironment): +async def test_oversized_payload_fails_task_with_error_log(env: WorkflowEnvironment): + """An oversized workflow completion is proactively failed by worker, which logs [TMPRL1103].""" if env.supports_time_skipping: pytest.skip("Time-skipping server does not report payload limits.") @@ -212,28 +90,21 @@ async def test_payload_size_error_workflow_result(env: WorkflowEnvironment): dev_server_extra_args=PAYLOAD_LIMITS_EXTRA_ARGS, dev_server_download_version=DEV_SERVER_DOWNLOAD_VERSION, ) as env: - # Create worker runtime with forwarded logger worker_logger = logging.getLogger(f"log-{uuid.uuid4()}") - worker_runtime = Runtime( - telemetry=TelemetryConfig( - logging=LoggingConfig( - filter=TelemetryFilter(core_level="WARN", other_level="ERROR"), - forwarding=LogForwardingConfig(logger=worker_logger), - ) - ) - ) - - # Create client for worker with custom runtime logging worker_client = await Client.connect( env.client.service_client.config.target_host, namespace=env.client.namespace, - runtime=worker_runtime, + runtime=_forwarding_runtime(worker_logger), ) - with ( - LogCapturer().logs_captured(worker_logger) as worker_logger_capturer, - LogCapturer().logs_captured(logging.getLogger()) as root_logger_capturer, - ): + def predicate(record: logging.LogRecord) -> bool: + return ( + record.levelname == "ERROR" + and "[TMPRL1103] Attempted to upload payloads with size that exceeded the error limit." + in record.msg + ) + + with LogCapturer().logs_captured(worker_logger) as capturer: async with new_worker( worker_client, LargePayloadWorkflow, activities=[large_payload_activity] ) as worker: @@ -241,10 +112,7 @@ async def test_payload_size_error_workflow_result(env: WorkflowEnvironment): LargePayloadWorkflow.run, LargePayloadWorkflowInput( activity_input_data_size=0, - activity_output_data_size=0, - activity_exception_data_size=0, workflow_output_data_size=PAYLOAD_ERROR_LIMIT + 1024, - data="", ), id=f"workflow-{uuid.uuid4()}", task_queue=worker.task_queue, @@ -253,69 +121,29 @@ async def test_payload_size_error_workflow_result(env: WorkflowEnvironment): with pytest.raises(WorkflowFailureError) as err: await handle.result() - assert isinstance(err.value.cause, TimeoutError) assert err.value.cause.type == TimeoutType.START_TO_CLOSE - replayer = Replayer(workflows=[LargePayloadWorkflow]) - await replayer.replay_workflow(await handle.fetch_history()) + # Core forwards logs on a buffered interval; poll while the capturer is attached. + async def error_forwarded() -> None: + assert capturer.find(predicate) is not None - def worker_logger_predicate(record: logging.LogRecord) -> bool: - return ( - record.levelname == "WARNING" - and "[TMPRL1103] Attempted to upload payloads with size that exceeded the error limit." - in record.msg - ) + await assert_eventually(error_forwarded) - assert worker_logger_capturer.find(worker_logger_predicate) - - def root_logger_predicate(record: logging.LogRecord) -> bool: - return ( - record.levelname == "WARNING" - and "[TMPRL1103] Attempted to upload payloads with size that exceeded the error limit." - in record.msg + # Confirm worker reported a WorkflowTaskFailed with cause PAYLOADS_TOO_LARGE. + history = await handle.fetch_history() + assert any( + event.event_type + == temporalio.api.enums.v1.EventType.EVENT_TYPE_WORKFLOW_TASK_FAILED + and event.workflow_task_failed_event_attributes.cause + == temporalio.api.enums.v1.WorkflowTaskFailedCause.WORKFLOW_TASK_FAILED_CAUSE_PAYLOADS_TOO_LARGE + for event in history.events ) - assert root_logger_capturer.find(root_logger_predicate) - -async def test_payload_size_warning_workflow_result(client: Client): - config = client.config() - config["data_converter"] = dataclasses.replace( - temporalio.converter.default(), - payload_limits=PayloadLimitsConfig( - payload_size_warning=1024, - ), - ) - worker_client = Client(**config) - - with warnings.catch_warnings(record=True) as w: - async with new_worker( - worker_client, LargePayloadWorkflow, activities=[large_payload_activity] - ) as worker: - await client.execute_workflow( - LargePayloadWorkflow.run, - LargePayloadWorkflowInput( - activity_input_data_size=0, - activity_output_data_size=0, - activity_exception_data_size=0, - workflow_output_data_size=2 * 1024, - data="", - ), - id=f"workflow-{uuid.uuid4()}", - task_queue=worker.task_queue, - execution_timeout=timedelta(seconds=3), - ) - - assert len(w) == 1 - assert issubclass(w[-1].category, PayloadSizeWarning) - assert ( - "[TMPRL1103] Attempted to upload payloads with size that exceeded the warning limit." - in str(w[-1].message) - ) - - -async def test_payload_size_error_activity_input(env: WorkflowEnvironment): +async def test_disable_payload_error_limit_sends_to_server(env: WorkflowEnvironment): + """With the opt-out, worker does not pre-fail; the oversized payload reaches (and is rejected by) + the server.""" if env.supports_time_skipping: pytest.skip("Time-skipping server does not report payload limits.") @@ -323,273 +151,106 @@ async def test_payload_size_error_activity_input(env: WorkflowEnvironment): dev_server_extra_args=PAYLOAD_LIMITS_EXTRA_ARGS, dev_server_download_version=DEV_SERVER_DOWNLOAD_VERSION, ) as env: - # Create worker runtime with forwarded logger - worker_logger = logging.getLogger(f"log-{uuid.uuid4()}") - worker_runtime = Runtime( - telemetry=TelemetryConfig( - logging=LoggingConfig( - filter=TelemetryFilter(core_level="WARN", other_level="ERROR"), - forwarding=LogForwardingConfig(logger=worker_logger), - ) - ) - ) - - # Create client for worker with custom runtime logging - worker_client = await Client.connect( - env.client.service_client.config.target_host, - namespace=env.client.namespace, - runtime=worker_runtime, - ) - - with ( - LogCapturer().logs_captured(worker_logger) as worker_logger_capturer, - LogCapturer().logs_captured(logging.getLogger()) as root_logger_capturer, - ): - async with new_worker( - worker_client, LargePayloadWorkflow, activities=[large_payload_activity] - ) as worker: - handle = await env.client.start_workflow( + async with new_worker( + env.client, + LargePayloadWorkflow, + activities=[large_payload_activity], + disable_payload_error_limit=True, + ) as worker: + with pytest.raises(WorkflowFailureError) as err: + await env.client.execute_workflow( LargePayloadWorkflow.run, LargePayloadWorkflowInput( activity_input_data_size=PAYLOAD_ERROR_LIMIT + 1024, - activity_output_data_size=0, - activity_exception_data_size=0, workflow_output_data_size=0, - data="", ), id=f"workflow-{uuid.uuid4()}", task_queue=worker.task_queue, execution_timeout=timedelta(seconds=3), ) - with pytest.raises(WorkflowFailureError) as err: - await handle.result() - - assert isinstance(err.value.cause, TimeoutError) - - replayer = Replayer(workflows=[LargePayloadWorkflow]) - await replayer.replay_workflow(await handle.fetch_history()) - - def worker_logger_predicate(record: logging.LogRecord) -> bool: - return ( - record.levelname == "WARNING" - and "[TMPRL1103] Attempted to upload payloads with size that exceeded the error limit." - in record.msg - ) - - assert worker_logger_capturer.find(worker_logger_predicate) - - def root_logger_predicate(record: logging.LogRecord) -> bool: - return ( - record.levelname == "WARNING" - and "[TMPRL1103] Attempted to upload payloads with size that exceeded the error limit." - in record.msg - ) - - assert root_logger_capturer.find(root_logger_predicate) + assert isinstance(err.value.cause, TerminatedError) + assert ( + err.value.cause.message + == "BadScheduleActivityAttributes: ScheduleActivityTaskCommandAttributes.Input exceeds size limit." + ) -async def test_payload_size_warning_activity_input(client: Client): - config = client.config() - config["data_converter"] = dataclasses.replace( - temporalio.converter.default(), - payload_limits=PayloadLimitsConfig( - payload_size_warning=1024, - ), +async def test_payload_size_warning_forwarded(env: WorkflowEnvironment): + """The connection's warn threshold produces a forwarded [TMPRL1103] warning for over-threshold payloads.""" + worker_logger = logging.getLogger(f"log-{uuid.uuid4()}") + worker_client = await Client.connect( + env.client.service_client.config.target_host, + namespace=env.client.namespace, + runtime=_forwarding_runtime(worker_logger), + payload_limits=PayloadLimitsConfig(payloads_warn_size=1024), ) - worker_client = Client(**config) - with warnings.catch_warnings(record=True) as w: + def predicate(record: logging.LogRecord) -> bool: + return ( + record.levelname == "WARNING" + and "[TMPRL1103] Attempted to upload payloads with size that exceeded the warning limit." + in record.msg + ) + + with LogCapturer().logs_captured(worker_logger) as capturer: async with new_worker( worker_client, LargePayloadWorkflow, activities=[large_payload_activity] ) as worker: - await client.execute_workflow( + await worker_client.execute_workflow( LargePayloadWorkflow.run, LargePayloadWorkflowInput( - activity_input_data_size=2 * 1024, - activity_output_data_size=0, - activity_exception_data_size=0, - workflow_output_data_size=0, - data="", + activity_input_data_size=0, + workflow_output_data_size=2 * 1024, ), id=f"workflow-{uuid.uuid4()}", task_queue=worker.task_queue, + execution_timeout=timedelta(seconds=5), ) - assert len(w) == 1 - assert issubclass(w[-1].category, PayloadSizeWarning) - assert ( - "[TMPRL1103] Attempted to upload payloads with size that exceeded the warning limit." - in str(w[-1].message) - ) - - -async def test_payload_size_error_activity_exception(env: WorkflowEnvironment): - if env.supports_time_skipping: - pytest.skip("Time-skipping server does not report payload limits.") - - async with await WorkflowEnvironment.start_local( - dev_server_extra_args=PAYLOAD_LIMITS_EXTRA_ARGS, - dev_server_download_version=DEV_SERVER_DOWNLOAD_VERSION, - ) as env: - # Create worker runtime with forwarded logger - worker_logger = logging.getLogger(f"log-{uuid.uuid4()}") - worker_runtime = Runtime( - telemetry=TelemetryConfig( - logging=LoggingConfig( - filter=TelemetryFilter(core_level="WARN", other_level="ERROR"), - forwarding=LogForwardingConfig(logger=worker_logger), - ) - ) - ) - - # Create client for worker with custom runtime logging - worker_client = await Client.connect( - env.client.service_client.config.target_host, - namespace=env.client.namespace, - runtime=worker_runtime, - ) - - with ( - LogCapturer().logs_captured( - activity.logger.base_logger - ) as activity_logger_capturer, - ): - async with new_worker( - worker_client, LargePayloadWorkflow, activities=[large_payload_activity] - ) as worker: - handle = await env.client.start_workflow( - LargePayloadWorkflow.run, - LargePayloadWorkflowInput( - activity_input_data_size=0, - activity_output_data_size=0, - activity_exception_data_size=PAYLOAD_ERROR_LIMIT + 1024, - workflow_output_data_size=0, - data="", - ), - id=f"workflow-{uuid.uuid4()}", - task_queue=worker.task_queue, - ) - - with pytest.raises(WorkflowFailureError) as err: - await handle.result() - - assert isinstance(err.value.cause, ActivityError) - assert isinstance(err.value.cause.cause, ApplicationError) - - replayer = Replayer(workflows=[LargePayloadWorkflow]) - await replayer.replay_workflow(await handle.fetch_history()) + # Core forwards logs on a buffered interval; poll while the capturer is attached. + async def warning_forwarded() -> None: + assert capturer.find(predicate) is not None - def activity_logger_predicate(record: logging.LogRecord) -> bool: - return ( - record.levelname == "ERROR" - and "[TMPRL1103] Attempted to upload payloads with size that exceeded the error limit." - in record.msg - ) - - assert activity_logger_capturer.find(activity_logger_predicate) + await assert_eventually(warning_forwarded) -async def test_payload_size_error_activity_result(env: WorkflowEnvironment): - if env.supports_time_skipping: - pytest.skip("Time-skipping server does not report payload limits.") +async def test_memo_size_warning_forwarded(env: WorkflowEnvironment): + """The connection's memo warn threshold produces a forwarded [TMPRL1103] warning for an + over-threshold memo.""" + worker_logger = logging.getLogger(f"log-{uuid.uuid4()}") + worker_client = await Client.connect( + env.client.service_client.config.target_host, + namespace=env.client.namespace, + runtime=_forwarding_runtime(worker_logger), + payload_limits=PayloadLimitsConfig(memo_warn_size=1024), + ) - async with await WorkflowEnvironment.start_local( - dev_server_extra_args=PAYLOAD_LIMITS_EXTRA_ARGS, - dev_server_download_version=DEV_SERVER_DOWNLOAD_VERSION, - ) as env: - # Create worker runtime with forwarded logger - worker_logger = logging.getLogger(f"log-{uuid.uuid4()}") - worker_runtime = Runtime( - telemetry=TelemetryConfig( - logging=LoggingConfig( - filter=TelemetryFilter(core_level="WARN", other_level="ERROR"), - forwarding=LogForwardingConfig(logger=worker_logger), - ) - ) + def predicate(record: logging.LogRecord) -> bool: + return ( + record.levelname == "WARNING" + and "[TMPRL1103] Attempted to upload memo with size that exceeded the warning limit." + in record.msg ) - # Create client for worker with custom runtime logging - worker_client = await Client.connect( - env.client.service_client.config.target_host, - namespace=env.client.namespace, - runtime=worker_runtime, - ) - - with ( - LogCapturer().logs_captured( - activity.logger.base_logger - ) as activity_logger_capturer, - ): - async with new_worker( - worker_client, LargePayloadWorkflow, activities=[large_payload_activity] - ) as worker: - handle = await env.client.start_workflow( - LargePayloadWorkflow.run, - LargePayloadWorkflowInput( - activity_input_data_size=0, - activity_output_data_size=PAYLOAD_ERROR_LIMIT + 1024, - activity_exception_data_size=0, - workflow_output_data_size=0, - data="", - ), - id=f"workflow-{uuid.uuid4()}", - task_queue=worker.task_queue, - ) - - with pytest.raises(WorkflowFailureError) as err: - await handle.result() - - assert isinstance(err.value.cause, ActivityError) - assert isinstance(err.value.cause.cause, ApplicationError) - - assert handle is not None - replayer = Replayer(workflows=[LargePayloadWorkflow]) - await replayer.replay_workflow(await handle.fetch_history()) - - def activity_logger_predicate(record: logging.LogRecord) -> bool: - return ( - hasattr(record, "__temporal_error_identifier") - and getattr(record, "__temporal_error_identifier") - == "PayloadSizeError" - and record.levelname == "WARNING" - and "[TMPRL1103] Attempted to upload payloads with size that exceeded the error limit." - in record.msg - ) - - assert activity_logger_capturer.find(activity_logger_predicate) - - -async def test_payload_size_warning_activity_result(client: Client): - config = client.config() - config["data_converter"] = dataclasses.replace( - temporalio.converter.default(), - payload_limits=PayloadLimitsConfig( - payload_size_warning=1024, - ), - ) - worker_client = Client(**config) - - with warnings.catch_warnings(record=True) as w: + with LogCapturer().logs_captured(worker_logger) as capturer: async with new_worker( worker_client, LargePayloadWorkflow, activities=[large_payload_activity] ) as worker: - await client.execute_workflow( + await worker_client.execute_workflow( LargePayloadWorkflow.run, LargePayloadWorkflowInput( activity_input_data_size=0, - activity_output_data_size=2 * 1024, - activity_exception_data_size=0, workflow_output_data_size=0, - data="", ), id=f"workflow-{uuid.uuid4()}", task_queue=worker.task_queue, + execution_timeout=timedelta(seconds=5), + memo={"key": "a" * 2048}, ) - assert len(w) == 1 - assert issubclass(w[-1].category, PayloadSizeWarning) - assert ( - "[TMPRL1103] Attempted to upload payloads with size that exceeded the warning limit." - in str(w[-1].message) - ) + # Core forwards logs on a buffered interval; poll while the capturer is attached. + async def warning_forwarded() -> None: + assert capturer.find(predicate) is not None + + await assert_eventually(warning_forwarded) From 9d9087c3e23d53a3bf24d42dfac1771484a801f6 Mon Sep 17 00:00:00 2001 From: Parth Date: Tue, 21 Jul 2026 23:39:43 +0530 Subject: [PATCH 172/226] feat: expose histogram_bucket_overrides on OpenTelemetryConfig (#1433) * Expose histogram_bucket_overrides on OpenTelemetryConfig Mirror the existing PrometheusConfig.histogram_bucket_overrides field. The underlying OtelCollectorOptions builder already supports this via maybe_histogram_bucket_overrides; this change wires it through the Python wrapper and pyo3 bridge. * Add test for OpenTelemetry histogram_bucket_overrides * Drop redundant test comment * Fix runtime test lint * fix: reformat test_runtime.py with ruff 0.15.15 The test-latest-deps CI job upgrades ruff to 0.15.15, which reformats assert-with-message statements into the new preferred style. Co-Authored-By: Claude Sonnet 4.6 --------- Co-authored-by: tconley1428 Co-authored-by: Claude Sonnet 4.6 --- temporalio/bridge/runtime.py | 1 + temporalio/bridge/src/runtime.rs | 6 ++ temporalio/runtime.py | 6 ++ tests/test_runtime.py | 104 ++++++++++++++++++++++++++++++- 4 files changed, 116 insertions(+), 1 deletion(-) diff --git a/temporalio/bridge/runtime.py b/temporalio/bridge/runtime.py index fa7fb275d..87f03f9c3 100644 --- a/temporalio/bridge/runtime.py +++ b/temporalio/bridge/runtime.py @@ -71,6 +71,7 @@ class OpenTelemetryConfig: metric_temporality_delta: bool durations_as_seconds: bool http: bool + histogram_bucket_overrides: Mapping[str, Sequence[float]] | None = None @dataclass(frozen=True) diff --git a/temporalio/bridge/src/runtime.rs b/temporalio/bridge/src/runtime.rs index 26fd3482b..5cd65366f 100644 --- a/temporalio/bridge/src/runtime.rs +++ b/temporalio/bridge/src/runtime.rs @@ -75,6 +75,7 @@ pub struct OpenTelemetryConfig { metric_temporality_delta: bool, durations_as_seconds: bool, http: bool, + histogram_bucket_overrides: Option>>, } #[derive(FromPyObject)] @@ -357,6 +358,11 @@ impl TryFrom for Arc { } else { None }) + .maybe_histogram_bucket_overrides(otel_conf.histogram_bucket_overrides.map( + |overrides| temporalio_common::telemetry::HistogramBucketOverrides { + overrides, + }, + )) .build(); Ok(Arc::new(build_otlp_metric_exporter(otel_options).map_err( |err| PyValueError::new_err(format!("Failed building OTel exporter: {err}")), diff --git a/temporalio/runtime.py b/temporalio/runtime.py index 94ba9f95d..da5019908 100644 --- a/temporalio/runtime.py +++ b/temporalio/runtime.py @@ -336,6 +336,10 @@ class OpenTelemetryConfig: When enabled, the ``url`` should point to the HTTP endpoint (e.g. ``"http://localhost:4318/v1/metrics"``). Defaults to ``False`` (gRPC). + histogram_bucket_overrides: Override the default histogram bucket + boundaries for specific metrics. Keys are metric names and + values are sequences of bucket boundaries (e.g. + ``{"workflow_task_schedule_to_start_latency": [0.01, 0.05, 0.1, 0.5, 1.0, 5.0]}``). """ url: str @@ -346,6 +350,7 @@ class OpenTelemetryConfig: ) durations_as_seconds: bool = False http: bool = False + histogram_bucket_overrides: Mapping[str, Sequence[float]] | None = None def _to_bridge_config(self) -> temporalio.bridge.runtime.OpenTelemetryConfig: return temporalio.bridge.runtime.OpenTelemetryConfig( @@ -361,6 +366,7 @@ def _to_bridge_config(self) -> temporalio.bridge.runtime.OpenTelemetryConfig: ), durations_as_seconds=self.durations_as_seconds, http=self.http, + histogram_bucket_overrides=self.histogram_bucket_overrides, ) diff --git a/tests/test_runtime.py b/tests/test_runtime.py index c29961c52..55501883d 100644 --- a/tests/test_runtime.py +++ b/tests/test_runtime.py @@ -4,7 +4,7 @@ import re import uuid from datetime import timedelta -from typing import cast +from typing import Any, cast from urllib.request import urlopen import pytest @@ -14,6 +14,7 @@ from temporalio.runtime import ( LogForwardingConfig, LoggingConfig, + OpenTelemetryConfig, PrometheusConfig, Runtime, TelemetryConfig, @@ -269,6 +270,107 @@ async def check_metrics() -> None: await assert_eventually(check_metrics) +async def test_opentelemetry_histogram_bucket_overrides(client: Client): + # Set up an OpenTelemetry configuration with custom histogram bucket overrides + import threading + from http.server import BaseHTTPRequestHandler, HTTPServer + + from opentelemetry.proto.collector.metrics.v1.metrics_service_pb2 import ( + ExportMetricsServiceRequest, + ExportMetricsServiceResponse, + ) + + special_value = float(1234.5678) + histogram_overrides = { + "temporal_long_request_latency": [special_value / 2, special_value], + "custom_histogram": [special_value / 2, special_value], + } + + captured: dict[str, list[float]] = {} + lock = threading.Lock() + + class Handler(BaseHTTPRequestHandler): + def log_message(self, format: str, *args: Any): + pass # silence default stderr logging + + def do_POST(self): + length = int(self.headers.get("Content-Length", "0")) + req = ExportMetricsServiceRequest() + req.ParseFromString(self.rfile.read(length)) + with lock: + for rm in req.resource_metrics: + for sm in rm.scope_metrics: + for m in sm.metrics: + if m.HasField("histogram"): + for dp in m.histogram.data_points: + captured[m.name] = list(dp.explicit_bounds) + body = ExportMetricsServiceResponse().SerializeToString() + self.send_response(200) + self.send_header("Content-Type", "application/x-protobuf") + self.send_header("Content-Length", str(len(body))) + self.end_headers() + self.wfile.write(body) + + otel_port = find_free_port() + server = HTTPServer(("127.0.0.1", otel_port), Handler) + thread = threading.Thread(target=server.serve_forever, daemon=True) + thread.start() + try: + runtime = Runtime( + telemetry=TelemetryConfig( + metrics=OpenTelemetryConfig( + url=f"http://127.0.0.1:{otel_port}/v1/metrics", + http=True, + metric_periodicity=timedelta(milliseconds=100), + durations_as_seconds=False, + histogram_bucket_overrides=histogram_overrides, + ), + ), + ) + + # Create and record to a custom histogram + custom_histogram = runtime.metric_meter.create_histogram( + "custom_histogram", "Custom histogram", "ms" + ) + custom_histogram.record(600) + + # Run a workflow so built-in histograms (e.g. temporal_long_request_latency) + # are recorded and exported. + client_with_overrides = await Client.connect( + client.service_client.config.target_host, + namespace=client.namespace, + runtime=runtime, + ) + task_queue = f"task-queue-{uuid.uuid4()}" + async with Worker( + client_with_overrides, + task_queue=task_queue, + workflows=[HelloWorkflow], + ): + assert "Hello, World!" == await client_with_overrides.execute_workflow( + HelloWorkflow.run, + "World", + id=f"workflow-{uuid.uuid4()}", + task_queue=task_queue, + ) + + async def check_metrics() -> None: + with lock: + snapshot = dict(captured) + for key, buckets in histogram_overrides.items(): + assert key in snapshot, ( + f"Missing {key} in captured metrics: {list(snapshot)}" + ) + assert snapshot[key] == pytest.approx(buckets), ( + f"Bucket mismatch for {key}: got {snapshot[key]} expected {buckets}" + ) + + await assert_eventually(check_metrics) + finally: + server.shutdown() + server.server_close() + + def test_runtime_options_invalid_heartbeat() -> None: with pytest.raises(ValueError): Runtime( From 1dcced93e34c5a495c6e3d40c9afef76c01420e4 Mon Sep 17 00:00:00 2001 From: Chad Retz Date: Tue, 21 Jul 2026 13:30:58 -0500 Subject: [PATCH 173/226] Minor README update for Nexus operations and asyncio cancellation (#1234) Co-authored-by: Tim Conley --- README.md | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 03ed87d51..8d8b48147 100644 --- a/README.md +++ b/README.md @@ -895,9 +895,12 @@ protect tasks against cancellation. The following tasks, when cancelled, perform a Temporal cancellation: -* Activities - when the task executing an activity is cancelled, a cancellation request is sent to the activity -* Child workflows - when the task starting or executing a child workflow is cancelled, a cancellation request is sent to - cancel the child workflow +* Activities - when the task executing an activity is cancelled, a cancellation request may be sent to the activity + depending on cancellation type +* Child workflows - when the task starting or executing a child workflow is cancelled, a cancellation request may be + sent to cancel the child workflow depending on cancellation type +* Nexus operations - when the task starting or executing a Nexus operation is cancelled, a cancellation request may be + sent to cancel the Nexus operation depending on cancellation type * Timers - when the task executing a timer is cancelled (whether started via sleep or timeout), the timer is cancelled When the workflow itself is requested to cancel, `Task.cancel` is called on the main workflow task. Therefore, From f65283e3a1a46ef43ce28a46dd77acf57eab2e7f Mon Sep 17 00:00:00 2001 From: Bathula-Adiseshu <137028310+Bathula-Adiseshu@users.noreply.github.com> Date: Wed, 22 Jul 2026 00:04:09 +0530 Subject: [PATCH 174/226] fix: avoid spurious "exception in shielded future" logs on cancellation (#1624) * fix: avoid spurious shielded future logs on cancellation * test: move context manager to cover worker shutdown * style: apply ruff formatting fixes --------- Co-authored-by: Tim Conley --- temporalio/worker/_workflow_instance.py | 46 ++++++++++++------ tests/worker/test_workflow.py | 62 +++++++++++++++++++++++++ 2 files changed, 94 insertions(+), 14 deletions(-) diff --git a/temporalio/worker/_workflow_instance.py b/temporalio/worker/_workflow_instance.py index c0e21bfd2..726ff85e0 100644 --- a/temporalio/worker/_workflow_instance.py +++ b/temporalio/worker/_workflow_instance.py @@ -86,6 +86,17 @@ LOG_IGNORE_DURING_DELETE = False +async def _shield_await(fut: asyncio.Future[Any]) -> Any: + """Await a future without cancelling it if the awaiting task is cancelled. + + This behaves like ``asyncio.shield(fut)`` but avoids the spurious + "exception in shielded future" error log on Python 3.11+ when the + awaiting task is cancelled and the future eventually fails. + """ + await asyncio.wait([fut]) + return fut.result() + + class WorkflowRunner(ABC): """Abstract runner for workflows that creates workflow instances to run. @@ -1927,9 +1938,10 @@ async def run_activity() -> Any: # be marked as unstarted handle._started = True try: - # We have to shield because we don't want the underlying - # result future to be cancelled - return await asyncio.shield(handle._result_fut) + # We use _shield_await instead of asyncio.shield to prevent + # the underlying result future from being cancelled while avoiding + # a spurious error log on Python 3.11+ (see issue #1600). + return await _shield_await(handle._result_fut) except _ActivityDoBackoffError as err: # We have to sleep then reschedule. Note this sleep can be # cancelled like any other timer. @@ -2043,9 +2055,10 @@ def apply_child_cancel_error(err: asyncio.CancelledError) -> None: async def run_child() -> Any: while True: try: - # We have to shield because we don't want the future itself - # to be cancelled - return await asyncio.shield(handle._result_fut) + # We use _shield_await instead of asyncio.shield to prevent + # the future itself from being cancelled while avoiding a + # spurious error log on Python 3.11+ (see issue #1600). + return await _shield_await(handle._result_fut) except asyncio.CancelledError as err: apply_child_cancel_error(err) # Clear the cancellation counter on Python 3.11+ so the @@ -2066,9 +2079,10 @@ async def run_child() -> Any: # Wait on start before returning while True: try: - # We have to shield because we don't want the future itself - # to be cancelled - await asyncio.shield(handle._start_fut) + # We use _shield_await instead of asyncio.shield to prevent + # the future itself from being cancelled while avoiding a + # spurious error log on Python 3.11+ (see issue #1600). + await _shield_await(handle._start_fut) return handle except asyncio.CancelledError as err: apply_child_cancel_error(err) @@ -2103,7 +2117,7 @@ async def _outbound_start_nexus_operation( async def operation_handle_fn() -> OutputT: while True: try: - return cast(OutputT, await asyncio.shield(handle._result_fut)) + return cast(OutputT, await _shield_await(handle._result_fut)) except asyncio.CancelledError: cancel_command = self._add_command() handle._apply_cancel_command(cancel_command) @@ -2132,7 +2146,10 @@ async def operation_handle_fn() -> OutputT: while True: try: - await asyncio.shield(handle._start_fut) + # We use _shield_await instead of asyncio.shield to prevent + # the future itself from being cancelled while avoiding a + # spurious error log on Python 3.11+ (see issue #1600). + await _shield_await(handle._start_fut) return handle except asyncio.CancelledError: cancel_command = self._add_command() @@ -2671,9 +2688,10 @@ async def _signal_external_workflow( # Wait until completed or cancelled while True: try: - # We have to shield because we don't want the future itself - # to be cancelled - return await asyncio.shield(done_fut) + # We use _shield_await instead of asyncio.shield to prevent + # the future itself from being cancelled while avoiding a + # spurious error log on Python 3.11+ (see issue #1600). + return await _shield_await(done_fut) except asyncio.CancelledError: cancel_command = self._add_command() cancel_command.cancel_signal_workflow.seq = seq diff --git a/tests/worker/test_workflow.py b/tests/worker/test_workflow.py index 4c9546eab..5300e0fff 100644 --- a/tests/worker/test_workflow.py +++ b/tests/worker/test_workflow.py @@ -9488,3 +9488,65 @@ async def test_workflow_uncancel_shield_signal_external(client: Client): assert shielded_err is None, ( f"Unexpected 'exception in shielded future' log: {shielded_err}" ) + + +class _SlowActivity: + def __init__(self) -> None: + self.started = asyncio.Event() + + @activity.defn(name="slow_activity") + async def slow_activity(self) -> None: + self.started.set() + await asyncio.sleep(60) + + +@workflow.defn +class _CancelInFlightActivityWorkflow: + @workflow.run + async def run(self) -> None: + await asyncio.gather( + *( + workflow.execute_activity( + "slow_activity", + start_to_close_timeout=timedelta(minutes=2), + ) + for _ in range(4) + ) + ) + + +@pytest.mark.asyncio +async def test_workflow_cancel_no_shielded_future_log( + client: Client, caplog: pytest.LogCaptureFixture +): + activity_inst = _SlowActivity() + + with caplog.at_level(logging.ERROR): + async with new_worker( + client, + _CancelInFlightActivityWorkflow, + activities=[activity_inst.slow_activity], + ) as worker: + handle = await client.start_workflow( + _CancelInFlightActivityWorkflow.run, + id=f"workflow-{uuid.uuid4()}", + task_queue=worker.task_queue, + execution_timeout=timedelta(minutes=5), + ) + + # Wait for activities to start + await asyncio.wait_for(activity_inst.started.wait(), timeout=10) + + # Ignore worker startup logs + caplog.clear() + + await handle.cancel() + + try: + await handle.result() + except WorkflowFailureError as err: + assert isinstance(err.cause, CancelledError) + + assert not any( + "exception in shielded future" in record.message for record in caplog.records + ) From 615122dd0fb9de697542c65637f47b8b09067969 Mon Sep 17 00:00:00 2001 From: Dan Davison Date: Tue, 21 Jul 2026 14:35:39 -0400 Subject: [PATCH 175/226] Don't capture stderr (#1145) --- scripts/gen_protos_docker.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/gen_protos_docker.py b/scripts/gen_protos_docker.py index 500fb0cbd..6735bdf90 100644 --- a/scripts/gen_protos_docker.py +++ b/scripts/gen_protos_docker.py @@ -11,7 +11,7 @@ os.path.join("scripts", "_proto", "Dockerfile"), ".", ], - capture_output=True, + stdout=subprocess.PIPE, text=True, check=True, ) From 6121e132bbc626d2eaf84b9725e3b7af43239a1d Mon Sep 17 00:00:00 2001 From: Mason Egger Date: Tue, 21 Jul 2026 13:39:51 -0500 Subject: [PATCH 176/226] Fixing indent issue with kwargs["extra"] (#789) * Fixing indent issue with kwargs["extra"] * indent other two lines * Extend logging tests to cover no-info branch with bug --------- Co-authored-by: Dan Davison --- temporalio/workflow/_sandbox.py | 6 +-- tests/worker/test_workflow.py | 75 +++++++++++++++++++++++---------- 2 files changed, 56 insertions(+), 25 deletions(-) diff --git a/temporalio/workflow/_sandbox.py b/temporalio/workflow/_sandbox.py index 6f1d4569a..32a053604 100644 --- a/temporalio/workflow/_sandbox.py +++ b/temporalio/workflow/_sandbox.py @@ -268,9 +268,9 @@ def process( else None, ) - kwargs["extra"] = {**extra, **(kwargs.get("extra") or {})} - if msg_extra: - msg = f"{msg} ({msg_extra})" + kwargs["extra"] = {**extra, **(kwargs.get("extra") or {})} + if msg_extra: + msg = f"{msg} ({msg_extra})" return msg, kwargs def log( diff --git a/tests/worker/test_workflow.py b/tests/worker/test_workflow.py index 5300e0fff..dbd85ef20 100644 --- a/tests/worker/test_workflow.py +++ b/tests/worker/test_workflow.py @@ -2242,8 +2242,27 @@ def last_signal(self) -> str: return self._last_signal -async def test_workflow_logging(client: Client): - workflow.logger.full_workflow_info_on_extra = True +@pytest.mark.parametrize( + "with_workflow_info", + [True, False], +) +async def test_workflow_logging(client: Client, with_workflow_info: bool): + orig_on_message = workflow.logger.workflow_info_on_message + orig_on_extra = workflow.logger.workflow_info_on_extra + orig_full_on_extra = workflow.logger.full_workflow_info_on_extra + + try: + workflow.logger.workflow_info_on_message = with_workflow_info + workflow.logger.workflow_info_on_extra = with_workflow_info + workflow.logger.full_workflow_info_on_extra = with_workflow_info + await _do_workflow_logging_test(client, with_workflow_info) + finally: + workflow.logger.workflow_info_on_message = orig_on_message + workflow.logger.workflow_info_on_extra = orig_on_extra + workflow.logger.full_workflow_info_on_extra = orig_full_on_extra + + +async def _do_workflow_logging_test(client: Client, with_workflow_info: bool): with LogCapturer().logs_captured( workflow.logger.base_logger, activity.logger.base_logger ) as capturer: @@ -2270,31 +2289,43 @@ async def test_workflow_logging(client: Client): assert "signal 2" == await handle.query(LoggingWorkflow.last_signal) # Confirm logs were produced - assert capturer.find_log("Signal: signal 1 ({'attempt':") + assert capturer.find_log("Signal: signal 1") assert capturer.find_log("Signal: signal 2") assert capturer.find_log("Update: update 1") assert capturer.find_log("Update: update 2") assert capturer.find_log("Query called") assert not capturer.find_log("Signal: signal 3") - # Also make sure it has some workflow info and correct funcName - record = capturer.find_log("Signal: signal 1") - assert ( - record - and record.__dict__["temporal_workflow"]["workflow_type"] - == "LoggingWorkflow" - and record.funcName == "my_signal" - ) - # Since we enabled full info, make sure it's there - assert isinstance(record.__dict__["workflow_info"], workflow.Info) - # Check the log emitted by the update execution. - record = capturer.find_log("Update: update 1") - assert ( - record - and record.__dict__["temporal_workflow"]["update_id"] == "update-1" - and record.__dict__["temporal_workflow"]["update_name"] == "my_update" - and "'update_id': 'update-1'" in record.message - and "'update_name': 'my_update'" in record.message - ) + + if with_workflow_info: + record = capturer.find_log("Signal: signal 1 ({'attempt':") + assert ( + record + and record.__dict__["temporal_workflow"]["workflow_type"] + == "LoggingWorkflow" + and record.funcName == "my_signal" + ) + # Since we enabled full info, make sure it's there + assert isinstance(record.__dict__["workflow_info"], workflow.Info) + + # Check the log emitted by the update execution. + record = capturer.find_log("Update: update 1") + assert ( + record + and record.__dict__["temporal_workflow"]["update_id"] == "update-1" + and record.__dict__["temporal_workflow"]["update_name"] == "my_update" + and "'update_id': 'update-1'" in record.message + and "'update_name': 'my_update'" in record.message + ) + else: + record = capturer.find_log("Signal: signal 1") + assert record and "temporal_workflow" not in record.__dict__ + assert record and "workflow_info" not in record.__dict__ + + record = capturer.find_log("Update: update 1") + assert record and "temporal_workflow" not in record.__dict__ + assert record and "workflow_info" not in record.__dict__ + assert "'update_id': 'update-1'" not in record.message + assert "'update_name': 'my_update'" not in record.message # Clear queue and start a new one with more signals capturer.log_queue.queue.clear() From b77ebfa65babf99b3040f144532071595f548761 Mon Sep 17 00:00:00 2001 From: Tim Conley Date: Tue, 21 Jul 2026 11:40:02 -0700 Subject: [PATCH 177/226] Fix minor typo (#1666) --- temporalio/workflow/_definition.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/temporalio/workflow/_definition.py b/temporalio/workflow/_definition.py index c1ce21169..a14e7640a 100644 --- a/temporalio/workflow/_definition.py +++ b/temporalio/workflow/_definition.py @@ -73,7 +73,7 @@ def defn( cannot be set if dynamic is set. sandboxed: Whether the workflow should run in a sandbox. Default is true. - dynamic: If true, this activity will be dynamic. Dynamic workflows have + dynamic: If true, this workflow will be dynamic. Dynamic workflows have to accept a single 'Sequence[RawValue]' parameter. This cannot be set to true if name is present. failure_exception_types: The types of exceptions that, if a From 0fe762fd0e9b617621848a8da918700a1e7b272e Mon Sep 17 00:00:00 2001 From: Timothy Yen Date: Tue, 21 Jul 2026 11:40:39 -0700 Subject: [PATCH 178/226] Add TLSConfig.verification_server_name to decouple certificate verification from SNI (#1651) When set, the server certificate is verified against this fixed name (using server_root_ca_cert) via a custom rustls ServerCertVerifier built in the bridge, while SNI and the HTTP/2 authority keep following the connected host (or domain, if set). This supports servers whose certificate does not carry the dialed name without overriding SNI, e.g. when the connection traverses an SNI-inspecting proxy that must be able to resolve the SNI value. --- CHANGELOG.md | 7 + pyproject.toml | 1 + temporalio/bridge/Cargo.lock | 1 + temporalio/bridge/Cargo.toml | 3 + temporalio/bridge/client.py | 1 + temporalio/bridge/src/client.rs | 109 ++++++++++++++- temporalio/service.py | 18 ++- tests/test_tls.py | 227 ++++++++++++++++++++++++++++++++ uv.lock | 2 + 9 files changed, 366 insertions(+), 3 deletions(-) create mode 100644 tests/test_tls.py diff --git a/CHANGELOG.md b/CHANGELOG.md index 98b968dfc..31036bfed 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,6 +20,13 @@ to include examples, links to docs, or any other relevant information. ### Added +- Added `TLSConfig.verification_server_name` to verify the server certificate against a fixed name + instead of the connection's server name. Unlike `domain`, it does not change the TLS SNI or + HTTP/2 authority values, which keep following the connected host, so it can be used when the + server's certificate does not carry the dialed name but on-path infrastructure (e.g. an + SNI-inspecting egress proxy) needs the SNI to remain resolvable. Requires + `server_root_ca_cert`. + - Added the experimental `Worker` `patch_activation_callback` option, allowing workers to decide whether a first non-replay `workflow.patched` call should activate a patch during rolling deployments. diff --git a/pyproject.toml b/pyproject.toml index b30a87fd3..0e47787ef 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -53,6 +53,7 @@ Documentation = "https://docs.temporal.io/docs/python" dev = [ "basedpyright==1.34.0", "cibuildwheel>=2.22.0,<3", + "cryptography>=46", "grpcio-tools>=1.48.2,<2", "mypy==1.18.2", "mypy-protobuf>=3.3.0,<4", diff --git a/temporalio/bridge/Cargo.lock b/temporalio/bridge/Cargo.lock index 1d45b94de..a92196ee3 100644 --- a/temporalio/bridge/Cargo.lock +++ b/temporalio/bridge/Cargo.lock @@ -2520,6 +2520,7 @@ dependencies = [ "temporalio-common", "temporalio-sdk-core", "tokio", + "tokio-rustls", "tokio-stream", "tonic", "tracing", diff --git a/temporalio/bridge/Cargo.toml b/temporalio/bridge/Cargo.toml index a1c6b5e3f..5984d9546 100644 --- a/temporalio/bridge/Cargo.toml +++ b/temporalio/bridge/Cargo.toml @@ -36,6 +36,9 @@ temporalio-sdk-core = { version = "0.5", path = "./sdk-core/crates/sdk-core", fe "ephemeral-server", ] } tokio = "1.26" +# Matches the sdk-core client crate's rustls stack; used to build the custom +# server certificate verifier for ClientTlsConfig.verification_server_name. +tokio-rustls = { version = "0.26", default-features = false, features = ["ring"] } tokio-stream = "0.1" tonic = "0.14" tracing = "0.1" diff --git a/temporalio/bridge/client.py b/temporalio/bridge/client.py index cdaf2e178..213443f29 100644 --- a/temporalio/bridge/client.py +++ b/temporalio/bridge/client.py @@ -27,6 +27,7 @@ class ClientTlsConfig: domain: str | None client_cert: bytes | None client_private_key: bytes | None + verification_server_name: str | None @dataclass diff --git a/temporalio/bridge/src/client.rs b/temporalio/bridge/src/client.rs index aaa280a30..37bfc796d 100644 --- a/temporalio/bridge/src/client.rs +++ b/temporalio/bridge/src/client.rs @@ -2,6 +2,7 @@ use pyo3::exceptions::{PyException, PyRuntimeError, PyValueError}; use pyo3::prelude::*; use std::collections::HashMap; use std::str::FromStr; +use std::sync::Arc; use std::time::Duration; use temporalio_client::tonic::{ self, @@ -11,6 +12,14 @@ use temporalio_client::{ ClientKeepAliveOptions as CoreClientKeepAliveConfig, Connection, ConnectionOptions, DnsLoadBalancingOptions, GrpcCompression, HttpConnectProxyOptions, RetryOptions, }; +use tokio_rustls::rustls::client::danger::{ + HandshakeSignatureValid, ServerCertVerified, ServerCertVerifier, +}; +use tokio_rustls::rustls::client::WebPkiServerVerifier; +use tokio_rustls::rustls::crypto::CryptoProvider; +use tokio_rustls::rustls::pki_types::pem::PemObject; +use tokio_rustls::rustls::pki_types::{CertificateDer, ServerName, UnixTime}; +use tokio_rustls::rustls::{self, DigitallySignedStruct, RootCertStore, SignatureScheme}; use tracing::warn; use url::Url; @@ -48,6 +57,7 @@ struct ClientTlsConfig { domain: Option, client_cert: Option>, client_private_key: Option>, + verification_server_name: Option, } #[derive(FromPyObject)] @@ -301,8 +311,22 @@ impl TryFrom for temporalio_client::TlsOptions { type Error = PyErr; fn try_from(conf: ClientTlsConfig) -> PyResult { + let mut server_root_ca_cert = conf.server_root_ca_cert; + let server_cert_verifier = match conf.verification_server_name { + None => None, + Some(name) => { + // The CA bundle is consumed by the verifier's own root store; a + // custom verifier cannot be combined with roots on the connection. + let ca_cert = server_root_ca_cert.take().ok_or_else(|| { + PyValueError::new_err( + "Must have server root CA cert when verification server name is set", + ) + })?; + Some(fixed_server_name_verifier(&name, &ca_cert)?) + } + }; Ok(temporalio_client::TlsOptions { - server_root_ca_cert: conf.server_root_ca_cert, + server_root_ca_cert, domain: conf.domain, client_tls_options: match (conf.client_cert, conf.client_private_key) { (None, None) => None, @@ -318,11 +342,92 @@ impl TryFrom for temporalio_client::TlsOptions { )) } }, - server_cert_verifier: None, + server_cert_verifier, }) } } +/// Builds a standard WebPKI verifier over the given root CA bundle that +/// checks the certificate against `verification_server_name` rather than the +/// connection's server name, leaving SNI/`:authority` to follow the +/// connected host (or `domain` when set). +fn fixed_server_name_verifier( + verification_server_name: &str, + ca_cert_pem: &[u8], +) -> PyResult> { + let certs = CertificateDer::pem_slice_iter(ca_cert_pem) + .collect::, _>>() + .map_err(|err| { + PyValueError::new_err(format!("Invalid server root CA cert PEM: {err:?}")) + })?; + // Root loading and provider selection mirror tonic's default (no custom + // verifier) client path: unparsable certificates in the bundle are + // skipped, and the provider is the process default if one is installed, + // else ring, as with the connection's `tls-ring` feature. + let mut roots = RootCertStore::empty(); + roots.add_parsable_certificates(certs); + let provider = CryptoProvider::get_default() + .cloned() + .unwrap_or_else(|| Arc::new(rustls::crypto::ring::default_provider())); + let inner = WebPkiServerVerifier::builder_with_provider(roots.into(), provider) + .build() + .map_err(|err| { + PyValueError::new_err(format!("Failed building certificate verifier: {err}")) + })?; + let server_name = ServerName::try_from(verification_server_name.to_owned()) + .map_err(|err| PyValueError::new_err(format!("Invalid verification server name: {err}")))?; + Ok(Arc::new(FixedServerNameVerifier { inner, server_name })) +} + +/// Delegates to the standard WebPKI verifier, but verifies the certificate +/// against a fixed server name instead of the connection's server name. +#[derive(Debug)] +struct FixedServerNameVerifier { + inner: Arc, + server_name: ServerName<'static>, +} + +impl ServerCertVerifier for FixedServerNameVerifier { + fn verify_server_cert( + &self, + end_entity: &CertificateDer<'_>, + intermediates: &[CertificateDer<'_>], + _server_name: &ServerName<'_>, + ocsp_response: &[u8], + now: UnixTime, + ) -> Result { + self.inner.verify_server_cert( + end_entity, + intermediates, + &self.server_name, + ocsp_response, + now, + ) + } + + fn verify_tls12_signature( + &self, + message: &[u8], + cert: &CertificateDer<'_>, + dss: &DigitallySignedStruct, + ) -> Result { + self.inner.verify_tls12_signature(message, cert, dss) + } + + fn verify_tls13_signature( + &self, + message: &[u8], + cert: &CertificateDer<'_>, + dss: &DigitallySignedStruct, + ) -> Result { + self.inner.verify_tls13_signature(message, cert, dss) + } + + fn supported_verify_schemes(&self) -> Vec { + self.inner.supported_verify_schemes() + } +} + impl From for RetryOptions { fn from(conf: ClientRetryConfig) -> Self { RetryOptions { diff --git a/temporalio/service.py b/temporalio/service.py index 56179472b..bddcf97fc 100644 --- a/temporalio/service.py +++ b/temporalio/service.py @@ -43,7 +43,9 @@ class TLSConfig: """Root CA to validate the server certificate against.""" domain: str | None = None - """TLS domain.""" + """SNI host and HTTP/2 authority override, and the default name the server + certificate is verified against (see + :py:attr:`verification_server_name`).""" client_cert: bytes | None = None """Client certificate for mTLS. @@ -55,12 +57,26 @@ class TLSConfig: This must be combined with :py:attr:`client_cert`.""" + verification_server_name: str | None = None + """Name to verify the server certificate against, instead of the + :py:attr:`domain` / connected host. + + Unlike :py:attr:`domain`, this does not change the TLS SNI or HTTP/2 + authority values, which continue to follow the connected host (or + :py:attr:`domain` if set). Use this when the server's certificate does not + carry the name being dialed, e.g. when the connection traverses an + SNI-inspecting proxy that must be able to resolve the SNI value. + + Requires :py:attr:`server_root_ca_cert`; the system root store is not + consulted when this is set.""" + def _to_bridge_config(self) -> temporalio.bridge.client.ClientTlsConfig: return temporalio.bridge.client.ClientTlsConfig( server_root_ca_cert=self.server_root_ca_cert, domain=self.domain, client_cert=self.client_cert, client_private_key=self.client_private_key, + verification_server_name=self.verification_server_name, ) diff --git a/tests/test_tls.py b/tests/test_tls.py new file mode 100644 index 000000000..cc0eddde9 --- /dev/null +++ b/tests/test_tls.py @@ -0,0 +1,227 @@ +"""Tests for :py:attr:`temporalio.service.TLSConfig.verification_server_name`. + +Each test runs an in-process TLS server whose certificate is valid only for +``pinned.test`` while the client always dials ``localhost``, so no Temporal +server is needed. The server records each handshake's outcome and the SNI it +received. +""" + +from __future__ import annotations + +import asyncio +import datetime +import socket +import ssl +import threading +from collections.abc import AsyncIterator +from dataclasses import dataclass +from pathlib import Path + +import pytest +import pytest_asyncio +from cryptography import x509 +from cryptography.hazmat.primitives import hashes, serialization +from cryptography.hazmat.primitives.asymmetric import ec +from cryptography.x509.oid import NameOID + +import temporalio.service + +PINNED_NAME = "pinned.test" + + +def test_tls_config_verification_server_name_reaches_bridge(): + config = temporalio.service.TLSConfig(verification_server_name=PINNED_NAME) + assert config._to_bridge_config().verification_server_name == PINNED_NAME + default = temporalio.service.TLSConfig() + assert default._to_bridge_config().verification_server_name is None + + +async def test_tls_verification_server_name_requires_root_ca(): + # The check is enforced when building connection options, before any dial. + with pytest.raises(ValueError, match="server root CA cert"): + await temporalio.service.ServiceClient.connect( + temporalio.service.ConnectConfig( + target_host="localhost:1", + tls=temporalio.service.TLSConfig(verification_server_name=PINNED_NAME), + ) + ) + + +async def test_tls_default_verification_rejects_unmatched_name(tls_server: _TlsServer): + # Baseline for the tests below: the certificate is only valid for the + # pinned name, so verifying against the dialed host rejects it. + handshake = await _handshake( + tls_server, temporalio.service.TLSConfig(server_root_ca_cert=tls_server.ca_pem) + ) + assert not handshake.ok + + +async def test_tls_verification_server_name_decouples_verification_from_sni( + tls_server: _TlsServer, +): + # Verification against the pinned name succeeds, while the SNI the server + # sees is still the dialed host rather than the pinned name. + handshake = await _handshake( + tls_server, + temporalio.service.TLSConfig( + server_root_ca_cert=tls_server.ca_pem, + verification_server_name=PINNED_NAME, + ), + ) + assert handshake.ok + assert handshake.sni == "localhost" + + +async def test_tls_verification_server_name_is_enforced(tls_server: _TlsServer): + # A pinned name the certificate does not carry is still rejected; the + # option redirects verification rather than disabling it. + handshake = await _handshake( + tls_server, + temporalio.service.TLSConfig( + server_root_ca_cert=tls_server.ca_pem, + verification_server_name="wrong.test", + ), + ) + assert not handshake.ok + + +@dataclass +class _Handshake: + ok: bool + sni: str | None + + +async def _handshake( + server: _TlsServer, tls: temporalio.service.TLSConfig +) -> _Handshake: + """Attempt a connection and return the server's view of the handshake.""" + config = temporalio.service.ConnectConfig( + target_host=f"localhost:{server.port}", tls=tls + ) + # The connect always fails since this server speaks no gRPC; only whether + # the TLS handshake completed matters. + try: + await asyncio.wait_for(temporalio.service.ServiceClient.connect(config), 20) + except asyncio.TimeoutError: + raise + except Exception: + pass + else: + pytest.fail("connect unexpectedly succeeded") + return await server.next_handshake() + + +class _TlsServer: + """TLS server that records handshake outcomes and the SNI it receives.""" + + def __init__(self, certs: Path) -> None: + self.ca_pem = (certs / "ca.pem").read_bytes() + self._ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER) + self._ctx.load_cert_chain(certs / "srv.pem", certs / "srv.key") + self._ctx.set_alpn_protocols(["h2"]) + # Populated by the SNI callback for the connection currently + # handshaking; the accept loop is single-threaded. + self._sni: str | None = None + + def on_sni( + _sock: ssl.SSLObject, name: str | None, _ctx: ssl.SSLContext + ) -> None: + self._sni = name + + self._ctx.sni_callback = on_sni + self._handshakes: list[_Handshake] = [] + self._lock = threading.Lock() + self._stop = threading.Event() + self._sock = socket.create_server(("127.0.0.1", 0)) + self._sock.settimeout(0.1) + self.port: int = self._sock.getsockname()[1] + self._thread = threading.Thread(target=self._serve, daemon=True) + self._thread.start() + + def _serve(self) -> None: + while not self._stop.is_set(): + try: + conn, _ = self._sock.accept() + except TimeoutError: + continue + conn.settimeout(10) # A stalled handshake must not wedge this loop. + self._sni = None + try: + tls = self._ctx.wrap_socket(conn, server_side=True) + except (ssl.SSLError, OSError): + conn.close() + self._record(_Handshake(ok=False, sni=self._sni)) + continue + self._record(_Handshake(ok=True, sni=self._sni)) + tls.close() + self._sock.close() + + def _record(self, handshake: _Handshake) -> None: + with self._lock: + self._handshakes.append(handshake) + + async def next_handshake(self) -> _Handshake: + """Wait for and consume the next recorded handshake.""" + # The client can report its result before this thread has recorded + # the outcome, so wait for the observation to land. + for _ in range(200): + with self._lock: + if self._handshakes: + return self._handshakes.pop(0) + await asyncio.sleep(0.05) + raise AssertionError("server observed no TLS handshake") + + def close(self) -> None: + self._stop.set() + self._thread.join(timeout=2) + + +@pytest_asyncio.fixture # type: ignore[reportUntypedFunctionDecorator] +async def tls_server(tmp_path: Path) -> AsyncIterator[_TlsServer]: + _write_pinned_certs(tmp_path) + server = _TlsServer(tmp_path) + try: + yield server + finally: + server.close() + + +def _write_pinned_certs(path: Path) -> None: + """Write a CA and a server cert (chained to it) valid only for ``pinned.test``.""" + now = datetime.datetime.now(datetime.timezone.utc) + ca_key = ec.generate_private_key(ec.SECP256R1()) + ca_name = x509.Name([x509.NameAttribute(NameOID.COMMON_NAME, "test-ca")]) + ca_cert = ( + x509.CertificateBuilder() + .subject_name(ca_name) + .issuer_name(ca_name) + .public_key(ca_key.public_key()) + .serial_number(x509.random_serial_number()) + .not_valid_before(now - datetime.timedelta(days=1)) + .not_valid_after(now + datetime.timedelta(days=7)) + .add_extension(x509.BasicConstraints(ca=True, path_length=None), critical=True) + .sign(ca_key, hashes.SHA256()) + ) + server_key = ec.generate_private_key(ec.SECP256R1()) + server_cert = ( + x509.CertificateBuilder() + .subject_name(x509.Name([x509.NameAttribute(NameOID.COMMON_NAME, PINNED_NAME)])) + .issuer_name(ca_name) + .public_key(server_key.public_key()) + .serial_number(x509.random_serial_number()) + .not_valid_before(now - datetime.timedelta(days=1)) + .not_valid_after(now + datetime.timedelta(days=7)) + .add_extension( + x509.SubjectAlternativeName([x509.DNSName(PINNED_NAME)]), critical=False + ) + .sign(ca_key, hashes.SHA256()) + ) + (path / "ca.pem").write_bytes(ca_cert.public_bytes(serialization.Encoding.PEM)) + (path / "srv.pem").write_bytes(server_cert.public_bytes(serialization.Encoding.PEM)) + (path / "srv.key").write_bytes( + server_key.private_bytes( + serialization.Encoding.PEM, + serialization.PrivateFormat.PKCS8, + serialization.NoEncryption(), + ) + ) diff --git a/uv.lock b/uv.lock index 7a5172d1a..f3b9f8c9d 100644 --- a/uv.lock +++ b/uv.lock @@ -4716,6 +4716,7 @@ dev = [ { name = "async-timeout", marker = "python_full_version < '3.11'" }, { name = "basedpyright" }, { name = "cibuildwheel" }, + { name = "cryptography" }, { name = "googleapis-common-protos" }, { name = "grpcio-tools" }, { name = "httpx" }, @@ -4787,6 +4788,7 @@ dev = [ { name = "async-timeout", marker = "python_full_version < '3.11'", specifier = ">=4.0,<6" }, { name = "basedpyright", specifier = "==1.34.0" }, { name = "cibuildwheel", specifier = ">=2.22.0,<3" }, + { name = "cryptography", specifier = ">=46" }, { name = "googleapis-common-protos", specifier = ">=1.75.0,<2" }, { name = "grpcio-tools", specifier = ">=1.48.2,<2" }, { name = "httpx", specifier = ">=0.28.1" }, From 29e0c51b0f832e0c9148f28ebba4000ab183d42f Mon Sep 17 00:00:00 2001 From: mavemuri <74267563+mavemuri@users.noreply.github.com> Date: Tue, 21 Jul 2026 17:23:34 -0700 Subject: [PATCH 179/226] NEXUS-484: Support UpdateWorkflow as a Nexus Operation (#1631) * NEXUS-484: Add support for workflow update Nexus operations * address comments, cleanup run_id, extend tests * address comments 2, fix docstrings, clarify signatures and errors --- temporalio/client/_impl.py | 22 ++ temporalio/client/_interceptor.py | 4 + temporalio/client/_workflow.py | 10 +- temporalio/nexus/__init__.py | 2 + temporalio/nexus/_operation_context.py | 44 +++ temporalio/nexus/_operation_handlers.py | 48 ++++ temporalio/nexus/_temporal_client.py | 143 +++++++++- temporalio/nexus/_token.py | 35 ++- tests/conftest.py | 4 +- tests/nexus/test_temporal_operation.py | 343 ++++++++++++++++++++++++ 10 files changed, 650 insertions(+), 5 deletions(-) diff --git a/temporalio/client/_impl.py b/temporalio/client/_impl.py index 8e33ff910..7ba54746f 100644 --- a/temporalio/client/_impl.py +++ b/temporalio/client/_impl.py @@ -787,6 +787,11 @@ async def start_workflow_update( ): break + # Add response link if its a Nexus operation + nexus_ctx = temporalio.nexus._operation_context._try_start_operation_context() + if nexus_ctx is not None and resp.HasField("link"): + nexus_ctx._add_response_link(resp.link) + # Build the handle. If the user's wait stage is COMPLETED, make sure we # poll for result. handle: WorkflowUpdateHandle[Any] = WorkflowUpdateHandle( @@ -852,6 +857,23 @@ async def _build_update_workflow_execution_request( ) ), ) + # Only set Nexus fields for StartWorkflowUpdateInput, skip for UpdateWithStartUpdateWorkflowInput + if isinstance(input, StartWorkflowUpdateInput): + if input.request_id: + req.request.request_id = input.request_id + if input.links: + req.request.links.extend(input.links) + if input.callbacks: + req.request.completion_callbacks.extend( + temporalio.api.common.v1.Callback( + nexus=temporalio.api.common.v1.Callback.Nexus( + url=callback.url, + header=callback.headers, + ), + links=input.links or [], + ) + for callback in input.callbacks + ) if input.args: req.request.input.args.payloads.extend( await data_converter.encode(input.args) diff --git a/temporalio/client/_interceptor.py b/temporalio/client/_interceptor.py index 5333d487f..a6daedd45 100644 --- a/temporalio/client/_interceptor.py +++ b/temporalio/client/_interceptor.py @@ -322,6 +322,10 @@ class StartWorkflowUpdateInput: ret_type: type | None rpc_metadata: Mapping[str, str | bytes] rpc_timeout: timedelta | None + # The following options are for Workflow Updates exposed as Nexus Operations. Experimental and unstable + callbacks: Sequence[Callback] | None = None + links: Sequence[temporalio.api.common.v1.Link] | None = None + request_id: str | None = None @dataclass diff --git a/temporalio/client/_workflow.py b/temporalio/client/_workflow.py index 8579e8433..6b3559c31 100644 --- a/temporalio/client/_workflow.py +++ b/temporalio/client/_workflow.py @@ -59,6 +59,7 @@ ReturnType, SelfType, ) +from ._callback import Callback from ._exceptions import ( WorkflowContinuedAsNewError, WorkflowFailureError, @@ -955,6 +956,10 @@ async def _start_update( result_type: type | None = None, rpc_metadata: Mapping[str, str | bytes] = {}, rpc_timeout: timedelta | None = None, + # The following options are for Workflow Updates exposed as Nexus Operations. Experimental and unstable + callbacks: Sequence[Callback] | None = None, + links: Sequence[temporalio.api.common.v1.Link] | None = None, + request_id: str | None = None, ) -> WorkflowUpdateHandle[Any]: if wait_for_stage == WorkflowUpdateStage.ADMITTED: raise ValueError("ADMITTED wait stage not supported") @@ -967,7 +972,7 @@ async def _start_update( StartWorkflowUpdateInput( id=self._id, run_id=self._run_id, - first_execution_run_id=self.first_execution_run_id, + first_execution_run_id=self._first_execution_run_id, update_id=id, update=update_name, args=temporalio.common._arg_or_args(arg, args), @@ -976,6 +981,9 @@ async def _start_update( rpc_metadata=rpc_metadata, rpc_timeout=rpc_timeout, wait_for_stage=wait_for_stage, + callbacks=callbacks, + links=links, + request_id=request_id, ) ) diff --git a/temporalio/nexus/__init__.py b/temporalio/nexus/__init__.py index 402e4b04e..003df44df 100644 --- a/temporalio/nexus/__init__.py +++ b/temporalio/nexus/__init__.py @@ -25,6 +25,7 @@ wait_for_worker_shutdown_sync, ) from ._operation_handlers import ( + CancelUpdateWorkflowOptions, CancelWorkflowRunOptions, TemporalOperationHandler, ) @@ -34,6 +35,7 @@ __all__ = ( "workflow_run_operation", "CancelWorkflowRunOptions", + "CancelUpdateWorkflowOptions", "Info", "LoggerAdapter", "NexusCallback", diff --git a/temporalio/nexus/_operation_context.py b/temporalio/nexus/_operation_context.py index 1128d1b71..7206e433e 100644 --- a/temporalio/nexus/_operation_context.py +++ b/temporalio/nexus/_operation_context.py @@ -715,3 +715,47 @@ async def _start_nexus_backing_workflow( ) return WorkflowHandle[ReturnType]._unsafe_from_client_workflow_handle(wf_handle) + + +async def _start_nexus_operation_workflow_update( # pyright: ignore[reportUnusedFunction] + *, + temporal_context: _TemporalStartOperationContext, + workflow_id: str, + update: str | Callable, + arg: Any = temporalio.common._arg_unset, + args: Sequence[Any] = [], + update_id: str | None = None, + result_type: type | None = None, + rpc_metadata: Mapping[str, str | bytes] = {}, + rpc_timeout: timedelta | None = None, + run_id: str | None = None, + first_execution_run_id: str | None = None, +) -> temporalio.client.WorkflowUpdateHandle[Any]: + # Default update ID to the Nexus request ID for retry-safety (matches sdk-go). + update_id = update_id or temporal_context.nexus_context.request_id + # This token is different from the actual token returned to the caller + # because return token will have the run_id that is unknowable before + # making the call. If run_id is passed, then it will be the same + token = OperationToken( + type=OperationTokenType.UPDATE_WORKFLOW, + namespace=temporal_context.client.namespace, + workflow_id=workflow_id, + update_id=update_id, + run_id=run_id, + ).encode() + workflow_handle = temporal_context.client.get_workflow_handle( + workflow_id, run_id=run_id, first_execution_run_id=first_execution_run_id + ) + return await workflow_handle._start_update( + update, + arg, + args=args, + wait_for_stage=temporalio.client.WorkflowUpdateStage.ACCEPTED, # hardcoded as nexus only supports async updates + id=update_id, + result_type=result_type, + rpc_metadata=rpc_metadata, + rpc_timeout=rpc_timeout, + callbacks=temporal_context._get_callbacks(token), + links=temporal_context._get_request_links(), + request_id=temporal_context.nexus_context.request_id, + ) diff --git a/temporalio/nexus/_operation_handlers.py b/temporalio/nexus/_operation_handlers.py index e5c3bd762..0ad6c267c 100644 --- a/temporalio/nexus/_operation_handlers.py +++ b/temporalio/nexus/_operation_handlers.py @@ -138,6 +138,25 @@ class CancelWorkflowRunOptions: """The ID of the workflow to cancel.""" +@dataclass(frozen=True) +class CancelUpdateWorkflowOptions: + """Options for cancelling the workflow update backing a Nexus operation. + + These options are built by :py:class:`TemporalOperationHandler` and passed to + :py:meth:`TemporalOperationHandler.cancel_workflow_update`. + + .. warning:: + This API is experimental and unstable. + """ + + workflow_id: str + """The ID of the workflow where the update is running.""" + update_id: str + """The ID of the update to cancel.""" + run_id: str + """The workflow runID that accepted the update.""" + + class TemporalOperationHandler(OperationHandler[InputT, OutputT], ABC): """Operation handler for Nexus operations that interact with Temporal. Implementations override the start_operation method. @@ -190,6 +209,15 @@ async def cancel(self, ctx: CancelOperationContext, token: str) -> None: workflow_id=operation_token.workflow_id ) await self.cancel_workflow_run(cancel_ctx, options) + case OperationTokenType.UPDATE_WORKFLOW: + assert operation_token.update_id is not None + assert operation_token.run_id is not None + cancel_options = CancelUpdateWorkflowOptions( + workflow_id=operation_token.workflow_id, + update_id=operation_token.update_id, + run_id=operation_token.run_id, + ) + await self.cancel_workflow_update(cancel_ctx, cancel_options) async def cancel_workflow_run( self, @@ -205,3 +233,23 @@ async def cancel_workflow_run( options.workflow_id ) await workflow_handle.cancel() + + async def cancel_workflow_update( + self, + ctx: TemporalCancelOperationContext, # pyright: ignore[reportUnusedParameter] + options: CancelUpdateWorkflowOptions, # pyright: ignore[reportUnusedParameter] + ) -> None: + """Cancels the Workflow Update triggered by the Nexus operation. There is no native way to cancel an accepted Update, so cancellation depends on the Update handler itself. + Override this method and coordinate with the specific Update handler to trigger a cancellation. + + + .. warning:: + This API is experimental and unstable. + """ + raise HandlerError( + """ + There is no native way to cancel an accepted Update, so cancellation depends on the Update handler itself. + Override this method and coordinate with the specific Update handler to trigger a cancellation. + """, + type=HandlerErrorType.NOT_IMPLEMENTED, + ) diff --git a/temporalio/nexus/_temporal_client.py b/temporalio/nexus/_temporal_client.py index 08204d89b..479d1651b 100644 --- a/temporalio/nexus/_temporal_client.py +++ b/temporalio/nexus/_temporal_client.py @@ -15,13 +15,14 @@ overload, ) -from nexusrpc import HandlerError, HandlerErrorType +from nexusrpc import HandlerError, HandlerErrorType, OperationError, OperationErrorState from nexusrpc.handler import StartOperationResultAsync, StartOperationResultSync from typing_extensions import Self import temporalio.common from temporalio.nexus._operation_context import ( _start_nexus_backing_workflow, + _start_nexus_operation_workflow_update, _TemporalStartOperationContext, ) from temporalio.types import ( @@ -33,8 +34,11 @@ SelfType, ) +from ._token import OperationToken, OperationTokenType + if TYPE_CHECKING: import temporalio.client + import temporalio.workflow _ResultT = TypeVar("_ResultT") @@ -279,6 +283,91 @@ async def start_workflow( """ ... + # Overload for no-param update + @overload + async def start_workflow_update( + self, + workflow_id: str, + update: temporalio.workflow.UpdateMethodMultiParam[[Any], ReturnType], + *, + update_id: str | None = None, + rpc_metadata: Mapping[str, str | bytes] = {}, + rpc_timeout: timedelta | None = None, + run_id: str | None = None, + first_execution_run_id: str | None = None, + ) -> TemporalOperationResult[ReturnType]: ... + + # Overload for single-param update + @overload + async def start_workflow_update( + self, + workflow_id: str, + update: temporalio.workflow.UpdateMethodMultiParam[ + [Any, ParamType], ReturnType + ], + arg: ParamType, + *, + update_id: str | None = None, + rpc_metadata: Mapping[str, str | bytes] = {}, + rpc_timeout: timedelta | None = None, + run_id: str | None = None, + first_execution_run_id: str | None = None, + ) -> TemporalOperationResult[ReturnType]: ... + + # Overload for multi-param update + @overload + async def start_workflow_update( + self, + workflow_id: str, + update: temporalio.workflow.UpdateMethodMultiParam[MultiParamSpec, ReturnType], + *, + args: MultiParamSpec.args, # type: ignore + update_id: str | None = None, + rpc_metadata: Mapping[str, str | bytes] = {}, + rpc_timeout: timedelta | None = None, + run_id: str | None = None, + first_execution_run_id: str | None = None, + ) -> TemporalOperationResult[ReturnType]: ... + + # Overload for string-name update + @overload + async def start_workflow_update( + self, + workflow_id: str, + update: str, + arg: Any = temporalio.common._arg_unset, + *, + args: Sequence[Any] = [], + update_id: str | None = None, + result_type: type[ReturnType] | None = None, + rpc_metadata: Mapping[str, str | bytes] = {}, + rpc_timeout: timedelta | None = None, + run_id: str | None = None, + first_execution_run_id: str | None = None, + ) -> TemporalOperationResult[ReturnType]: ... + + @abstractmethod + async def start_workflow_update( + self, + workflow_id: str, + update: str | Callable, + arg: Any = temporalio.common._arg_unset, + *, + args: Sequence[Any] = [], + update_id: str | None = None, + result_type: type | None = None, + rpc_metadata: Mapping[str, str | bytes] = {}, + rpc_timeout: timedelta | None = None, + run_id: str | None = None, + first_execution_run_id: str | None = None, + ) -> TemporalOperationResult[Any]: + """Start a Workflow Update-backed Nexus Operation. + + .. warning:: + This API is experimental and unstable. + """ + ... + class _TemporalNexusClient(TemporalNexusClient): # pyright: ignore[reportUnusedClass] """Nexus-aware wrapper around a Temporal Client. @@ -377,3 +466,55 @@ async def start_workflow( ) return TemporalOperationResult.async_token(wf_handle.to_token()) + + async def start_workflow_update( + self, + workflow_id: str, + update: str | Callable, + arg: Any = temporalio.common._arg_unset, + *, + args: Sequence[Any] = [], + update_id: str | None = None, + result_type: type | None = None, + rpc_metadata: Mapping[str, str | bytes] = {}, + rpc_timeout: timedelta | None = None, + run_id: str | None = None, + first_execution_run_id: str | None = None, + ) -> TemporalOperationResult[Any]: + """Start a Workflow Update-backed Nexus Operation.""" + if not self._temporal_context.nexus_context.callback_url: + raise HandlerError( + "callback URL is required for a workflow update Nexus operation", + type=HandlerErrorType.BAD_REQUEST, + ) + with self._reserve_async_start(): + update_handle = await _start_nexus_operation_workflow_update( + temporal_context=self._temporal_context, + workflow_id=workflow_id, + update=update, + arg=arg, + args=args, + update_id=update_id, + result_type=result_type, + rpc_metadata=rpc_metadata, + rpc_timeout=rpc_timeout, + run_id=run_id, + first_execution_run_id=first_execution_run_id, + ) + # If the update has already completed, return the result synchronously + if update_handle._known_outcome is not None: + try: + result = await update_handle.result() + except temporalio.client.WorkflowUpdateFailedError as err: + raise OperationError( + str(err), state=OperationErrorState.FAILED + ) from err + return TemporalOperationResult.sync(result) + token = OperationToken( + type=OperationTokenType.UPDATE_WORKFLOW, + namespace=update_handle._client.namespace, + workflow_id=update_handle.workflow_id, + update_id=update_handle.id, + run_id=update_handle.workflow_run_id, + ).encode() + return TemporalOperationResult.async_token(token) diff --git a/temporalio/nexus/_token.py b/temporalio/nexus/_token.py index d52b54180..fe0a466c9 100644 --- a/temporalio/nexus/_token.py +++ b/temporalio/nexus/_token.py @@ -14,6 +14,7 @@ class OperationTokenType(IntEnum): """Type discriminator for Nexus operation tokens.""" WORKFLOW = 1 + UPDATE_WORKFLOW = 3 if TYPE_CHECKING: @@ -28,6 +29,8 @@ class OperationToken: type: OperationTokenType namespace: str workflow_id: str + run_id: str | None = None + update_id: str | None = None def encode(self) -> str: """Convert handle to a base64url-encoded token string.""" @@ -38,6 +41,10 @@ def encode(self) -> str: } if self.version is not None: token_details["v"] = self.version + if self.run_id is not None: + token_details["rid"] = self.run_id + if self.update_id is not None: + token_details["uid"] = self.update_id return _base64url_encode_no_padding( json.dumps( token_details, @@ -88,9 +95,24 @@ def decode(cls, token: str) -> Self: f"invalid token: expected workflow id to be a string, got {type(workflow_id)}" ) - if token_type == OperationTokenType.WORKFLOW and not workflow_id: + if ( + token_type == OperationTokenType.WORKFLOW + or token_type == OperationTokenType.UPDATE_WORKFLOW + ): + if not workflow_id: + raise TypeError( + f"invalid token: expected non-empty workflow id for token type `{token_type.name}`" + ) + + update_id = token_details.get("uid") + if not isinstance(update_id, str | None): raise TypeError( - "invalid token: expected non-empty workflow id for token type `WORKFLOW`" + f"invalid token: expected update_id to be a string or None, got {type(update_id)}" + ) + + if token_type == OperationTokenType.UPDATE_WORKFLOW and not update_id: + raise TypeError( + "invalid token: expected non-empty update id for token type `UPDATE_WORKFLOW`" ) namespace = token_details.get("ns") @@ -100,11 +122,20 @@ def decode(cls, token: str) -> Self: f"invalid token: expected namespace to be a string, got {type(namespace)}" ) + run_id = token_details.get("rid") + + if not isinstance(run_id, str | None): + raise TypeError( + f"invalid token: expected run_id to be a string or None, got {type(run_id)}" + ) + return cls( type=OperationTokenType(token_type), namespace=namespace, workflow_id=workflow_id, + run_id=run_id, version=version, + update_id=update_id, ) diff --git a/tests/conftest.py b/tests/conftest.py index e01773e7e..bfe005ede 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -132,7 +132,7 @@ async def env(env_type: str) -> AsyncGenerator[WorkflowEnvironment, None]: "--dynamic-config-value", "history.enableTransitionHistory=true", "--dynamic-config-value", - "history.enableChasmCallbacks=true", + "history.enableCHASMCallbacks=true", "--dynamic-config-value", "history.enableCHASMSignalBacklinks=true", "--dynamic-config-value", @@ -141,6 +141,8 @@ async def env(env_type: str) -> AsyncGenerator[WorkflowEnvironment, None]: 'system.system.refreshNexusEndpointsMinWait="0s"', "--dynamic-config-value", "history.enableSignalWithStartFromWorkflow=true", + "--dynamic-config-value", + "history.enableUpdateCallbacks=true", ], dev_server_download_version=DEV_SERVER_DOWNLOAD_VERSION, ) diff --git a/tests/nexus/test_temporal_operation.py b/tests/nexus/test_temporal_operation.py index c97792c8d..b6b1a92c7 100644 --- a/tests/nexus/test_temporal_operation.py +++ b/tests/nexus/test_temporal_operation.py @@ -1,6 +1,7 @@ import asyncio import uuid from dataclasses import dataclass +from datetime import timedelta import nexusrpc import pytest @@ -10,6 +11,7 @@ import temporalio.exceptions from temporalio import nexus, workflow +from temporalio.api.common.v1 import Link from temporalio.client import Client, WorkflowExecutionStatus, WorkflowFailureError from temporalio.common import NexusOperationExecutionStatus, WorkflowIDConflictPolicy from temporalio.nexus._token import OperationToken, OperationTokenType @@ -23,6 +25,9 @@ class Input: value: str task_queue: str + update_value: str = "" + update_id: str = "" + expect_sync_response: bool = False def test_temporal_operation_result_validates_single_result_kind() -> None: @@ -63,6 +68,7 @@ class TestService: retry_after_failed_start: Operation[Input, str] sync_result: Operation[Input, str] custom_cancel: Operation[str, None] + update_op: Operation[Input, str] @service_handler(service=TestService) @@ -216,6 +222,21 @@ async def cancel_workflow_run( return CustomCancelNexusOpHandler() + @nexus.temporal_operation + async def update_op( + self, + _ctx: nexus.TemporalStartOperationContext, + client: nexus.TemporalNexusClient, + input: Input, + ) -> nexus.TemporalOperationResult[str]: + # input.value carries the target workflow_id, input.update_value has actual update + return await client.start_workflow_update( + input.value, + UpdatableWorkflow.do_update, + input.update_value, + update_id=input.update_id, + ) + @workflow.defn class EchoWorkflowCaller: @@ -258,6 +279,283 @@ async def test_temporal_operation_start_workflow( ) +async def test_temporal_operation_update_workflow( + client: Client, env: WorkflowEnvironment +) -> None: + if ( + env.supports_time_skipping + ): # time skipping server uses different dynamic configs + pytest.skip("Update workflow tests don't work with time-skipping server") + task_queue = str(uuid.uuid4()) + endpoint_name = make_nexus_endpoint_name(task_queue) + await env.create_nexus_endpoint(endpoint_name, task_queue) + async with Worker( + env.client, + task_queue=task_queue, + nexus_service_handlers=[TestServiceHandler()], + workflows=[UpdatableWorkflow, UpdateWorkflowCaller], + ): + update_workflow_id = f"updatable-workflow-{uuid.uuid4()}" + target_handle = await client.start_workflow( + UpdatableWorkflow.run, id=update_workflow_id, task_queue=task_queue + ) + + async def check_simple_update_and_links(): + """Run an update, check state changes from pending to created, verify forward and back links are correct""" + wf_handle = await client.start_workflow( + UpdateWorkflowCaller.run, + Input( + value=update_workflow_id, + task_queue=task_queue, + update_value="Created", + ), + task_queue=task_queue, + id=f"update-workflow-caller-created-{uuid.uuid4()}", + ) + result = await wf_handle.result() + assert result == "Updated workflow status from Pending to Created" + # assert expected events are in expected sequence in caller history + await assert_event_subsequence( + wf_handle, + [ + EventType.EVENT_TYPE_NEXUS_OPERATION_SCHEDULED, + EventType.EVENT_TYPE_NEXUS_OPERATION_STARTED, + EventType.EVENT_TYPE_NEXUS_OPERATION_COMPLETED, + ], + ) + # now, check the links + caller_history = await wf_handle.fetch_history() + handler_history = await target_handle.fetch_history() + scheduled_event = next( + e + for e in caller_history.events + if e.event_type == EventType.EVENT_TYPE_NEXUS_OPERATION_SCHEDULED + ) + caller_request_id = ( + scheduled_event.nexus_operation_scheduled_event_attributes.request_id + ) + assert target_handle.result_run_id is not None + # from caller ns to target ns + expected_forward_link = Link( + workflow_event=Link.WorkflowEvent( + namespace=client.namespace, + workflow_id=update_workflow_id, + run_id=target_handle.result_run_id, + request_id_ref=Link.WorkflowEvent.RequestIdReference( + request_id=caller_request_id, + event_type=EventType.EVENT_TYPE_WORKFLOW_EXECUTION_UPDATE_ACCEPTED, + ), + ) + ) + assert wf_handle.result_run_id is not None + # from target ns back to caller ns + expected_backward_link = Link( + workflow_event=Link.WorkflowEvent( + namespace=client.namespace, + workflow_id=wf_handle.id, + run_id=wf_handle.result_run_id, + event_ref=Link.WorkflowEvent.EventReference( + event_id=scheduled_event.event_id, + event_type=EventType.EVENT_TYPE_NEXUS_OPERATION_SCHEDULED, + ), + ) + ) + caller_links = [ + link + for e in caller_history.events + if e.event_type == EventType.EVENT_TYPE_NEXUS_OPERATION_STARTED + for link in e.links + ] + handler_links = [ + link + for e in handler_history.events + if e.event_type + == EventType.EVENT_TYPE_WORKFLOW_EXECUTION_UPDATE_ACCEPTED + for link in e.links + ] + assert expected_forward_link in caller_links + assert expected_backward_link in handler_links + + async def check_sequential_updates_consistent(): + """Run updates back-to-back, verify update isnt re-processed""" + stable_update_id = "sequential-update" + wf_handle = await client.start_workflow( + UpdateWorkflowCaller.run, + Input( + value=update_workflow_id, + task_queue=task_queue, + update_value="Processed", + update_id=stable_update_id, + ), + task_queue=task_queue, + id="sequential-update-workflow-caller-processed-0", + ) + result = await wf_handle.result() + assert result == "Updated workflow status from Created to Processed" + + # same update_id -> wont be processed again, receives a sync result + wf_handle = await client.start_workflow( + UpdateWorkflowCaller.run, + Input( + value=update_workflow_id, + task_queue=task_queue, + update_value="Processed", + update_id=stable_update_id, + expect_sync_response=True, + ), + task_queue=task_queue, + id="sequential-update-workflow-caller-processed-1", + ) + result = await wf_handle.result() + assert result == "Updated workflow status from Created to Processed" + + async def check_parallel_updates_idempotent_and_finish(): + """Run multiple updates in parallel, verify they are idempotent and finish with same result""" + stable_id = "parallel-updates-id" + num_parallel = 3 + gate = asyncio.Event() + + async def run_update(i: int) -> str: + await gate.wait() + wf_handle = await client.start_workflow( + UpdateWorkflowCaller.run, + Input( + value=update_workflow_id, + task_queue=task_queue, + update_value="Completed", + update_id=stable_id, + ), + task_queue=task_queue, + id=f"parallel-update-workflow-caller-completed-{i}", + ) + return await wf_handle.result() + + tasks = [asyncio.create_task(run_update(i)) for i in range(num_parallel)] + gate.set() + results = await asyncio.gather(*tasks) + + for result in results: + assert result == "Updated workflow status from Processed to Completed" + + async def check_updates_on_completed_workflows_fail(): + """The handler workflow already finished at this point, further updaes should just fail""" + wf_handle = await client.start_workflow( + UpdateWorkflowCaller.run, + Input( + value=update_workflow_id, + task_queue=task_queue, + update_value="dummy, will fail anyway", + ), + task_queue=task_queue, + id=f"{uuid.uuid4()}", + ) + with pytest.raises(WorkflowFailureError): + await wf_handle.result() + + await check_simple_update_and_links() + await check_sequential_updates_consistent() + await check_parallel_updates_idempotent_and_finish() + await check_updates_on_completed_workflows_fail() + + +async def test_temporal_operation_update_workflow_delayed( + client: Client, env: WorkflowEnvironment +) -> None: + if ( + env.supports_time_skipping + ): # time skipping server uses different dynamic configs + pytest.skip("Update workflow tests don't work with time-skipping server") + task_queue = str(uuid.uuid4()) + endpoint_name = make_nexus_endpoint_name(task_queue) + await env.create_nexus_endpoint(endpoint_name, task_queue) + + update_workflow_id = f"another-updatable-workflow-{uuid.uuid4()}" + + # start both caller and handler without starting worker + wf_handle = await client.start_workflow( + UpdateWorkflowCaller.run, + Input( + value=update_workflow_id, + task_queue=task_queue, + update_value="Completed", + ), + task_queue=task_queue, + id=f"update-workflow-caller-created-{uuid.uuid4()}", + ) + target_handle = await client.start_workflow( + UpdatableWorkflow.run, id=update_workflow_id, task_queue=task_queue + ) + + # now, start the worker, it should process both the handler + # and the caller and finish the enqueued update + async with Worker( + env.client, + task_queue=task_queue, + nexus_service_handlers=[TestServiceHandler()], + workflows=[UpdatableWorkflow, UpdateWorkflowCaller], + ): + result = await wf_handle.result() + assert result == "Updated workflow status from Pending to Completed" + + await assert_event_subsequence( + wf_handle, + [ + EventType.EVENT_TYPE_NEXUS_OPERATION_SCHEDULED, + EventType.EVENT_TYPE_NEXUS_OPERATION_STARTED, + EventType.EVENT_TYPE_NEXUS_OPERATION_COMPLETED, + ], + ) + + caller_history = await wf_handle.fetch_history() + handler_history = await target_handle.fetch_history() + scheduled_event = next( + e + for e in caller_history.events + if e.event_type == EventType.EVENT_TYPE_NEXUS_OPERATION_SCHEDULED + ) + caller_request_id = ( + scheduled_event.nexus_operation_scheduled_event_attributes.request_id + ) + assert target_handle.result_run_id is not None + expected_forward_link = Link( + workflow_event=Link.WorkflowEvent( + namespace=client.namespace, + workflow_id=update_workflow_id, + run_id=target_handle.result_run_id, + request_id_ref=Link.WorkflowEvent.RequestIdReference( + request_id=caller_request_id, + event_type=EventType.EVENT_TYPE_WORKFLOW_EXECUTION_UPDATE_ACCEPTED, + ), + ) + ) + assert wf_handle.result_run_id is not None + expected_backward_link = Link( + workflow_event=Link.WorkflowEvent( + namespace=client.namespace, + workflow_id=wf_handle.id, + run_id=wf_handle.result_run_id, + event_ref=Link.WorkflowEvent.EventReference( + event_id=scheduled_event.event_id, + event_type=EventType.EVENT_TYPE_NEXUS_OPERATION_SCHEDULED, + ), + ) + ) + caller_links = [ + link + for e in caller_history.events + if e.event_type == EventType.EVENT_TYPE_NEXUS_OPERATION_STARTED + for link in e.links + ] + handler_links = [ + link + for e in handler_history.events + if e.event_type == EventType.EVENT_TYPE_WORKFLOW_EXECUTION_UPDATE_ACCEPTED + for link in e.links + ] + assert expected_forward_link in caller_links + assert expected_backward_link in handler_links + + @workflow.defn class BlockingWorkflow: def __init__(self) -> None: @@ -724,3 +1022,48 @@ async def test_temporal_operation_includes_token_in_callback( ).encode() assert token == expected_token + + +@workflow.defn +class UpdateWorkflowCaller: + """Simple caller workflow that triggers a workflow update via nexus op""" + + @workflow.run + async def run(self, input: Input) -> str: + client = workflow.create_nexus_client( + service=TestService, + endpoint=make_nexus_endpoint_name(input.task_queue), + ) + op_handle = await client.start_operation(TestService.update_op, input) + if input.expect_sync_response: + if op_handle.operation_token: + raise RuntimeError("unexpected operation token on a sync operation") + else: + if not op_handle.operation_token: + raise RuntimeError( + "unexpected empty operation token on an async operation" + ) + return await op_handle + + +@workflow.defn +class UpdatableWorkflow: + """Workflow that accepts updates and exits when it receives a specific status""" + + def __init__(self) -> None: + self.order_status = "Pending" + + @workflow.run + async def run(self) -> None: + await workflow.wait_condition(lambda: self.order_status == "Completed") + # some more order processing etc + + @workflow.update + async def do_update(self, value: str) -> str: + status = self.order_status + await workflow.sleep( + timedelta(seconds=1) + ) # small sleep to ensure updates are async and backlinks are to STARTED events + self.order_status = value + update_result = f"Updated workflow status from {status} to {value}" + return update_result From f942f2c0c6045b74a7200a14f58196d1247a29a5 Mon Sep 17 00:00:00 2001 From: Saksham Goyal <144555727+Sakshamm-Goyal@users.noreply.github.com> Date: Thu, 23 Jul 2026 23:17:54 +0530 Subject: [PATCH 180/226] fix: exclude sdk-core gitfile from wheels (#1669) * fix: exclude sdk-core gitfile from wheels * test: remove ineffective packaging config assertion --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 0e47787ef..ba0abfc3d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -261,7 +261,7 @@ manifest-path = "temporalio/bridge/Cargo.toml" module-name = "temporalio.bridge.temporal_sdk_bridge" python-packages = ["temporalio"] include = ["LICENSE"] -exclude = ["temporalio/bridge/target/**/*"] +exclude = ["temporalio/bridge/target/**/*", "temporalio/bridge/sdk-core/.git"] [tool.uv] # Prevent uv commands from building the package by default From 759876e43a856577620f9350a22d79213c79482c Mon Sep 17 00:00:00 2001 From: Tim Conley Date: Thu, 23 Jul 2026 11:06:30 -0700 Subject: [PATCH 181/226] :boom: Add transfer type payload conversion hooks (#1655) * Wrap payload converters for temporal intermediate models * Support intermediate hooks in system Nexus conversion * Rename intermediate hooks to data model hooks * Use typed data model converter decorators * Rename data model hooks to transfer types --- CHANGELOG.md | 12 ++ scripts/gen_payload_visitor.py | 2 +- temporalio/activity.py | 11 +- temporalio/bridge/_visitor.py | 2 +- temporalio/converter/__init__.py | 4 + temporalio/converter/_data_converter.py | 9 +- temporalio/converter/_payload_converter.py | 138 ++++++++++++++++++ temporalio/nexus/system/__init__.py | 92 ++++++++++-- temporalio/nexus/system/_payload_visitor.py | 2 +- temporalio/worker/_workflow.py | 2 +- temporalio/worker/_workflow_instance.py | 8 +- temporalio/worker/workflow_sandbox/_runner.py | 2 +- tests/nexus/test_temporal_system_nexus.py | 12 +- tests/test_converter.py | 111 ++++++++++++++ tests/worker/test_visitor.py | 4 +- 15 files changed, 385 insertions(+), 26 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 31036bfed..6230f2754 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,6 +20,11 @@ to include examples, links to docs, or any other relevant information. ### Added +- Added experimental SDK payload converter support for values and type hints + decorated with `@transfer_type_convertible(...)` using a `TransferTypeConverter` class. + This lets types with transfer type converters delegate their wire representation to the + configured payload converter, preserving SDK behavior such as serialization + contexts. - Added `TLSConfig.verification_server_name` to verify the server certificate against a fixed name instead of the connection's server name. Unlike `domain`, it does not change the TLS SNI or HTTP/2 authority values, which keep following the connected host, so it can be used when the @@ -37,6 +42,13 @@ to include examples, links to docs, or any other relevant information. ### Breaking Changes +- Custom workflow runners that construct `WorkflowInstanceDetails` must now pass + `payload_converter_factory` instead of `payload_converter_class`. The factory + returns the already wrapped payload converter that workflow instances should + use. +- System Nexus payload converter helpers added for generated bindings are now + private implementation details, and the remaining public `temporalio.nexus.system` + APIs are marked experimental and subject to change. - Payload size limits have moved from `DataConverter` to `Client.connect`. Pass `payload_limits=PayloadLimitsConfig(...)` (now exported from `temporalio.client`) instead of setting `payload_limits` on `DataConverter`. diff --git a/scripts/gen_payload_visitor.py b/scripts/gen_payload_visitor.py index efe9c0df2..c2bc15837 100644 --- a/scripts/gen_payload_visitor.py +++ b/scripts/gen_payload_visitor.py @@ -191,7 +191,7 @@ async def _visit_nexus_operation_input_payload( endpoint: str, payload: Payload, ) -> None: - new_payload = await temporalio.nexus.system.maybe_visit_payload( + new_payload = await temporalio.nexus.system._maybe_visit_payload( endpoint, payload, fs, diff --git a/temporalio/activity.py b/temporalio/activity.py index 4e632701e..3f69bc17f 100644 --- a/temporalio/activity.py +++ b/temporalio/activity.py @@ -29,6 +29,9 @@ import temporalio.bridge.proto.activity_task import temporalio.common import temporalio.converter +from temporalio.converter._payload_converter import ( + _TemporalTransferTypePayloadConverter, +) from .types import CallableType @@ -238,9 +241,13 @@ def payload_converter(self) -> temporalio.converter.PayloadConverter: self.payload_converter_class_or_instance, temporalio.converter.PayloadConverter, ): - self._payload_converter = self.payload_converter_class_or_instance + self._payload_converter = _TemporalTransferTypePayloadConverter.wrap( + self.payload_converter_class_or_instance + ) else: - self._payload_converter = self.payload_converter_class_or_instance() + self._payload_converter = _TemporalTransferTypePayloadConverter.wrap( + self.payload_converter_class_or_instance() + ) return self._payload_converter @property diff --git a/temporalio/bridge/_visitor.py b/temporalio/bridge/_visitor.py index 4e258b9a1..a9956e12b 100644 --- a/temporalio/bridge/_visitor.py +++ b/temporalio/bridge/_visitor.py @@ -61,7 +61,7 @@ async def _visit_nexus_operation_input_payload( endpoint: str, payload: Payload, ) -> None: - new_payload = await temporalio.nexus.system.maybe_visit_payload( + new_payload = await temporalio.nexus.system._maybe_visit_payload( endpoint, payload, fs, diff --git a/temporalio/converter/__init__.py b/temporalio/converter/__init__.py index 9192eb704..ebd2b8396 100644 --- a/temporalio/converter/__init__.py +++ b/temporalio/converter/__init__.py @@ -33,6 +33,8 @@ JSONTypeConverter, JSONTypeConverterUnhandled, PayloadConverter, + TransferTypeConverter, + transfer_type_convertible, value_to_type, ) from temporalio.converter._search_attributes import ( @@ -64,6 +66,7 @@ "BinaryPlainPayloadConverter", "BinaryProtoPayloadConverter", "CompositePayloadConverter", + "TransferTypeConverter", "DataConverter", "DefaultFailureConverter", "DefaultFailureConverterWithEncodedAttributes", @@ -79,6 +82,7 @@ "SerializationContext", "WithSerializationContext", "WorkflowSerializationContext", + "transfer_type_convertible", "decode_search_attributes", "decode_typed_search_attributes", "default", diff --git a/temporalio/converter/_data_converter.py b/temporalio/converter/_data_converter.py index 823d1cc13..6425d6b61 100644 --- a/temporalio/converter/_data_converter.py +++ b/temporalio/converter/_data_converter.py @@ -28,6 +28,7 @@ ) from temporalio.converter._payload_converter import ( PayloadConverter, + _TemporalTransferTypePayloadConverter, ) from temporalio.converter._serialization_context import ( SerializationContext, @@ -90,9 +91,15 @@ class DataConverter(WithSerializationContext): """Singleton default data converter.""" def __post_init__(self) -> None: # noqa: D105 - object.__setattr__(self, "payload_converter", self.payload_converter_class()) + object.__setattr__(self, "payload_converter", self._new_payload_converter()) object.__setattr__(self, "failure_converter", self.failure_converter_class()) + def _new_payload_converter(self) -> PayloadConverter: + """Create a payload converter instance with SDK transfer type hooks enabled.""" + return _TemporalTransferTypePayloadConverter.wrap( + self.payload_converter_class() + ) + async def encode( self, values: Sequence[Any] ) -> list[temporalio.api.common.v1.Payload]: diff --git a/temporalio/converter/_payload_converter.py b/temporalio/converter/_payload_converter.py index 8ee85ef72..f10b6a4e0 100644 --- a/temporalio/converter/_payload_converter.py +++ b/temporalio/converter/_payload_converter.py @@ -21,6 +21,7 @@ from typing import ( Any, ClassVar, + Generic, Literal, NewType, TypeVar, @@ -51,6 +52,75 @@ ) _sym_db = google.protobuf.symbol_database.Default() +ValueT = TypeVar("ValueT") +TransferTypeT = TypeVar("TransferTypeT") +_TRANSFER_TYPE_CONVERTER_ATTR = "__temporal_transfer_type_converter" + + +class TransferTypeConverter(Generic[ValueT, TransferTypeT], ABC): + """Converter between a user-facing value and a transfer type value. + + .. warning:: + This API is experimental and subject to change. + """ + + transfer_type: type[TransferTypeT] | None = None + """Optional type hint for the transfer type to use when decoding payloads. + + .. warning:: + This API is experimental and subject to change. + """ + + @abstractmethod + def to_transfer_type(self, value: ValueT) -> TransferTypeT: + """Convert a user-facing value to its transfer type value. + + .. warning:: + This API is experimental and subject to change. + """ + raise NotImplementedError + + @abstractmethod + def from_transfer_type(self, value: TransferTypeT) -> ValueT: + """Convert a transfer type value to its user-facing value. + + .. warning:: + This API is experimental and subject to change. + """ + raise NotImplementedError + + +class _TransferTypeConvertibleDecorator(Generic[ValueT, TransferTypeT]): + def __init__( + self, converter_type: type[TransferTypeConverter[ValueT, TransferTypeT]] + ) -> None: + self._converter_type = converter_type + + def __call__(self, cls: type[ValueT]) -> type[ValueT]: + if hasattr(cls, _TRANSFER_TYPE_CONVERTER_ATTR): + raise TypeError("class already has a transfer type converter") + setattr(cls, _TRANSFER_TYPE_CONVERTER_ATTR, self._converter_type()) + return cls + + +def transfer_type_convertible( + converter_type: type[TransferTypeConverter[ValueT, TransferTypeT]], +) -> _TransferTypeConvertibleDecorator[ValueT, TransferTypeT]: + """Decorate a class with a transfer type converter class. + + .. warning:: + This API is experimental and subject to change. + """ + return _TransferTypeConvertibleDecorator(converter_type) + + +def _get_transfer_type_converter( + value_type: object, +) -> TransferTypeConverter[Any, Any] | None: + converter = getattr(value_type, _TRANSFER_TYPE_CONVERTER_ATTR, None) + if isinstance(converter, TransferTypeConverter): + return converter + return None class PayloadConverter(ABC): @@ -514,6 +584,74 @@ def from_payload( raise RuntimeError("Failed parsing") from err +class _TemporalTransferTypePayloadConverter(PayloadConverter, WithSerializationContext): + """Payload converter wrapper for registered Temporal transfer type converters. + + Values with a registered transfer type converter are first converted to their + transfer type value, then encoded by the wrapped payload converter. When + decoding to a type with a registered transfer type converter, the wrapped + converter first decodes the payload to the transfer type value and this wrapper + constructs the requested user-facing type from it. + """ + + _inner_payload_converter: PayloadConverter + + def __init__(self, inner_payload_converter: PayloadConverter) -> None: + """Create a Temporal transfer type payload converter.""" + self._inner_payload_converter = inner_payload_converter + + @staticmethod + def wrap(payload_converter: PayloadConverter) -> PayloadConverter: + """Wrap a payload converter unless it is already wrapped.""" + if isinstance(payload_converter, _TemporalTransferTypePayloadConverter): + return payload_converter + return _TemporalTransferTypePayloadConverter(payload_converter) + + def to_payloads( + self, values: Sequence[Any] + ) -> list[temporalio.api.common.v1.Payload]: + """See base class.""" + transfer_type_values: list[Any] = [] + for value in values: + converter = _get_transfer_type_converter(type(value)) + if converter is not None: + value = converter.to_transfer_type(value) + transfer_type_values.append(value) + return self._inner_payload_converter.to_payloads(transfer_type_values) + + def from_payloads( + self, + payloads: Sequence[temporalio.api.common.v1.Payload], + type_hints: list[type] | None = None, + ) -> list[Any]: + """See base class.""" + if type_hints is None: + return self._inner_payload_converter.from_payloads(payloads, None) + converters = [ + _get_transfer_type_converter(type_hint) for type_hint in type_hints + ] + inner_type_hints = [ + converter.transfer_type if converter is not None else type_hint + for converter, type_hint in zip(converters, type_hints) + ] + values = self._inner_payload_converter.from_payloads( + payloads, typing.cast("list[type]", inner_type_hints) + ) + return [ + converter.from_transfer_type(value) if converter is not None else value + for value, converter in zip(values, converters) + ] + + def with_context(self, context: SerializationContext) -> Self: + """Return a new instance with context set on the inner converter.""" + if not isinstance(self._inner_payload_converter, WithSerializationContext): + return self + inner_payload_converter = self._inner_payload_converter.with_context(context) + if inner_payload_converter is self._inner_payload_converter: + return self + return type(self)(inner_payload_converter) + + class AdvancedJSONEncoder(json.JSONEncoder): """Advanced JSON encoder. diff --git a/temporalio/nexus/system/__init__.py b/temporalio/nexus/system/__init__.py index 21c5a1408..14a43cb72 100644 --- a/temporalio/nexus/system/__init__.py +++ b/temporalio/nexus/system/__init__.py @@ -1,29 +1,100 @@ -"""System Nexus operation helpers.""" +"""System Nexus operation helpers. + +.. warning:: + This API is experimental and subject to change. +""" from __future__ import annotations +import contextlib +import contextvars +from collections.abc import Iterator, Sequence +from typing import Any + import temporalio.api.common.v1 import temporalio.converter from temporalio.bridge._visitor_functions import VisitorFunctions from temporalio.converter import BinaryProtoPayloadConverter, CompositePayloadConverter +from temporalio.converter._payload_converter import ( + _TemporalTransferTypePayloadConverter, +) TEMPORAL_SYSTEM_ENDPOINT = "__temporal_system" +_user_payload_converter: contextvars.ContextVar[ + temporalio.converter.PayloadConverter | None +] = contextvars.ContextVar("temporal-system-nexus-user-payload-converter", default=None) -class SystemNexusPayloadConverter(CompositePayloadConverter): - """Payload converter for system Nexus outer envelopes.""" +@contextlib.contextmanager +def _user_payload_converter_context( + payload_converter: temporalio.converter.PayloadConverter, +) -> Iterator[None]: + """Set the user payload converter for system Nexus model conversion.""" + token = _user_payload_converter.set(payload_converter) + try: + yield + finally: + _user_payload_converter.reset(token) + + +def _current_user_payload_converter() -> temporalio.converter.PayloadConverter: # pyright: ignore[reportUnusedFunction] + """Return the active user payload converter for system Nexus model conversion.""" + payload_converter = _user_payload_converter.get() + if payload_converter is None: + raise RuntimeError("System Nexus user payload converter context is not active") + return payload_converter + + +class _SystemNexusOuterPayloadConverter(CompositePayloadConverter): + """Payload converter for system Nexus outer proto envelopes.""" def __init__(self) -> None: """Create a payload converter for system Nexus outer envelopes.""" super().__init__(BinaryProtoPayloadConverter()) +class _SystemNexusPayloadConverter(temporalio.converter.PayloadConverter): + """Payload converter for system Nexus outer envelopes.""" + + _user_payload_converter: temporalio.converter.PayloadConverter + _outer_payload_converter: temporalio.converter.PayloadConverter + + def __init__( + self, user_payload_converter: temporalio.converter.PayloadConverter + ) -> None: + """Create a payload converter for system Nexus outer envelopes.""" + self._user_payload_converter = user_payload_converter + self._outer_payload_converter = _TemporalTransferTypePayloadConverter.wrap( + _SystemNexusOuterPayloadConverter() + ) + + def to_payloads( + self, values: Sequence[Any] + ) -> list[temporalio.api.common.v1.Payload]: + """See base class.""" + with _user_payload_converter_context(self._user_payload_converter): + return self._outer_payload_converter.to_payloads(values) + + def from_payloads( + self, + payloads: Sequence[temporalio.api.common.v1.Payload], + type_hints: list[type] | None = None, + ) -> list[Any]: + """See base class.""" + with _user_payload_converter_context(self._user_payload_converter): + return self._outer_payload_converter.from_payloads(payloads, type_hints) + + def is_system_endpoint(endpoint: str) -> bool: - """Return whether a Nexus endpoint is the Temporal system endpoint.""" + """Return whether a Nexus endpoint is the Temporal system endpoint. + + .. warning:: + This API is experimental and subject to change. + """ return endpoint == TEMPORAL_SYSTEM_ENDPOINT -async def maybe_visit_payload( +async def _maybe_visit_payload( # pyright: ignore[reportUnusedFunction] endpoint: str, payload: temporalio.api.common.v1.Payload, visitor_functions: VisitorFunctions, @@ -33,7 +104,7 @@ async def maybe_visit_payload( if not is_system_endpoint(endpoint): return None - payload_converter = get_payload_converter() + payload_converter = _SystemNexusOuterPayloadConverter() value = payload_converter.from_payload(payload) from ._payload_visitor import PayloadVisitor @@ -43,15 +114,14 @@ async def maybe_visit_payload( return payload_converter.to_payload(value) -def get_payload_converter() -> temporalio.converter.PayloadConverter: +def _get_payload_converter( # pyright: ignore[reportUnusedFunction] + user_payload_converter: temporalio.converter.PayloadConverter, +) -> temporalio.converter.PayloadConverter: """Return the fixed payload converter for system Nexus outer envelopes.""" - return SystemNexusPayloadConverter() + return _SystemNexusPayloadConverter(user_payload_converter) __all__ = [ "TEMPORAL_SYSTEM_ENDPOINT", - "get_payload_converter", "is_system_endpoint", - "maybe_visit_payload", - "SystemNexusPayloadConverter", ] diff --git a/temporalio/nexus/system/_payload_visitor.py b/temporalio/nexus/system/_payload_visitor.py index 5b4178ff1..4f194168f 100644 --- a/temporalio/nexus/system/_payload_visitor.py +++ b/temporalio/nexus/system/_payload_visitor.py @@ -61,7 +61,7 @@ async def _visit_nexus_operation_input_payload( endpoint: str, payload: Payload, ) -> None: - new_payload = await temporalio.nexus.system.maybe_visit_payload( + new_payload = await temporalio.nexus.system._maybe_visit_payload( endpoint, payload, fs, diff --git a/temporalio/worker/_workflow.py b/temporalio/worker/_workflow.py index b9513068d..900d14b43 100644 --- a/temporalio/worker/_workflow.py +++ b/temporalio/worker/_workflow.py @@ -776,7 +776,7 @@ def _create_workflow_instance( # Create instance from details det = WorkflowInstanceDetails( - payload_converter_class=self._data_converter.payload_converter_class, + payload_converter_factory=self._data_converter._new_payload_converter, failure_converter_class=self._data_converter.failure_converter_class, interceptor_classes=self._interceptor_classes, defn=defn, diff --git a/temporalio/worker/_workflow_instance.py b/temporalio/worker/_workflow_instance.py index 726ff85e0..76b3304ef 100644 --- a/temporalio/worker/_workflow_instance.py +++ b/temporalio/worker/_workflow_instance.py @@ -157,7 +157,7 @@ class PatchActivationInput: class WorkflowInstanceDetails: """Immutable details for creating a workflow instance.""" - payload_converter_class: type[temporalio.converter.PayloadConverter] + payload_converter_factory: Callable[[], temporalio.converter.PayloadConverter] failure_converter_class: type[temporalio.converter.FailureConverter] interceptor_classes: Sequence[type[WorkflowInboundInterceptor]] defn: temporalio.workflow._Definition @@ -269,7 +269,7 @@ def __init__(self, det: WorkflowInstanceDetails) -> None: self._defn = det.defn self._workflow_input: ExecuteWorkflowInput | None = None self._info = det.info - self._context_free_payload_converter = det.payload_converter_class() + self._context_free_payload_converter = det.payload_converter_factory() self._context_free_failure_converter = det.failure_converter_class() workflow_context = temporalio.converter.WorkflowSerializationContext( namespace=det.info.namespace, @@ -2130,7 +2130,9 @@ async def operation_handle_fn() -> OutputT: t.uncancel() # type: ignore[union-attr] payload_converter = ( - temporalio.nexus.system.get_payload_converter() + temporalio.nexus.system._get_payload_converter( + self._workflow_context_payload_converter + ) if temporalio.nexus.system.is_system_endpoint(input.endpoint) else self._context_free_payload_converter ) diff --git a/temporalio/worker/workflow_sandbox/_runner.py b/temporalio/worker/workflow_sandbox/_runner.py index 17f473d64..7f06bfcd6 100644 --- a/temporalio/worker/workflow_sandbox/_runner.py +++ b/temporalio/worker/workflow_sandbox/_runner.py @@ -79,7 +79,7 @@ def prepare_workflow(self, defn: temporalio.workflow._Definition) -> None: # Just create with fake info which validates self.create_instance( WorkflowInstanceDetails( - payload_converter_class=temporalio.converter.DataConverter.default.payload_converter_class, + payload_converter_factory=temporalio.converter.DataConverter.default._new_payload_converter, failure_converter_class=temporalio.converter.DataConverter.default.failure_converter_class, interceptor_classes=[], defn=defn, diff --git a/tests/nexus/test_temporal_system_nexus.py b/tests/nexus/test_temporal_system_nexus.py index b689ee8d9..eb8ee603c 100644 --- a/tests/nexus/test_temporal_system_nexus.py +++ b/tests/nexus/test_temporal_system_nexus.py @@ -186,7 +186,9 @@ def _new_system_nexus_request_payload() -> temporalio.api.common.v1.Payload: assert nested_payload is not None request = workflowservice_pb2.SignalWithStartWorkflowExecutionRequest() request.input.payloads.add().CopyFrom(nested_payload) - payload = nexus_system.get_payload_converter().to_payload(request) + payload = nexus_system._get_payload_converter( + temporalio.converter.PayloadConverter.default + ).to_payload(request) assert payload is not None return payload @@ -201,7 +203,9 @@ async def test_schedule_system_nexus_endpoint_ignores_operation_registry() -> No await PayloadVisitor().visit(visitor, completion) schedule = completion.successful.commands[0].schedule_nexus_operation - decoded = nexus_system.get_payload_converter().from_payload(schedule.input) + decoded = nexus_system._get_payload_converter( + temporalio.converter.PayloadConverter.default + ).from_payload(schedule.input) assert isinstance( decoded, workflowservice_pb2.SignalWithStartWorkflowExecutionRequest ) @@ -339,7 +343,9 @@ def _field_is_repeated(field: FieldDescriptor) -> bool: ], ) def test_system_nexus_proto_roundtrip(message_type: type[Message]) -> None: - payload_converter = nexus_system.get_payload_converter() + payload_converter = nexus_system._get_payload_converter( + temporalio.converter.PayloadConverter.default + ) proto_value = _build_proto_sample(message_type) payload = payload_converter.to_payload(proto_value) assert payload is not None diff --git a/tests/test_converter.py b/tests/test_converter.py index 10365f9c1..b5e10c518 100644 --- a/tests/test_converter.py +++ b/tests/test_converter.py @@ -44,10 +44,15 @@ JSONTypeConverter, JSONTypeConverterUnhandled, PayloadCodec, + TransferTypeConverter, decode_search_attributes, encode_search_attribute_values, + transfer_type_convertible, value_to_type, ) +from temporalio.converter._payload_converter import ( + _TemporalTransferTypePayloadConverter, +) from temporalio.exceptions import ( ApplicationError, FailureError, @@ -254,6 +259,112 @@ def test_binary_proto(): assert decoded == proto +class TemporalTransferTypeValueConverter( + TransferTypeConverter[ + "TemporalTransferTypeValue", + temporalio.api.common.v1.WorkflowExecution, + ] +): + transfer_type = temporalio.api.common.v1.WorkflowExecution + + def to_transfer_type( + self, value: TemporalTransferTypeValue + ) -> temporalio.api.common.v1.WorkflowExecution: + return temporalio.api.common.v1.WorkflowExecution( + workflow_id=value.value, + run_id="run-id", + ) + + def from_transfer_type( + self, + value: temporalio.api.common.v1.WorkflowExecution, + ) -> TemporalTransferTypeValue: + return TemporalTransferTypeValue(value=value.workflow_id) + + +@transfer_type_convertible(TemporalTransferTypeValueConverter) +@dataclass +class TemporalTransferTypeValue: + value: str + + +class TemporalTransferTypeValueWithoutHintConverter( + TransferTypeConverter[ + "TemporalTransferTypeValueWithoutHint", + temporalio.api.common.v1.WorkflowExecution, + ] +): + def to_transfer_type( + self, value: TemporalTransferTypeValueWithoutHint + ) -> temporalio.api.common.v1.WorkflowExecution: + return temporalio.api.common.v1.WorkflowExecution( + workflow_id=value.value, + run_id="run-id", + ) + + def from_transfer_type( + self, + value: temporalio.api.common.v1.WorkflowExecution, + ) -> TemporalTransferTypeValueWithoutHint: + return TemporalTransferTypeValueWithoutHint(value=value.workflow_id) + + +@transfer_type_convertible(TemporalTransferTypeValueWithoutHintConverter) +@dataclass +class TemporalTransferTypeValueWithoutHint: + value: str + + +class CustomDefaultPayloadConverter(DefaultPayloadConverter): + pass + + +def test_temporal_transfer_type_payload_converter_wraps_user_converter(): + data_converter = DataConverter( + payload_converter_class=CustomDefaultPayloadConverter + ) + converter = data_converter.payload_converter + assert isinstance(converter, _TemporalTransferTypePayloadConverter) + value = TemporalTransferTypeValue("workflow-id") + + payload = converter.to_payload(value) + + assert payload.metadata["encoding"] == b"json/protobuf" + assert ( + payload.metadata["messageType"] == b"temporal.api.common.v1.WorkflowExecution" + ) + assert all("temporal-wire" not in key for key in payload.metadata) + assert all(b"temporal-wire" not in value for value in payload.metadata.values()) + assert converter.from_payload(payload, TemporalTransferTypeValue) == value + + plain_proto_payload = converter.to_payload( + temporalio.api.common.v1.WorkflowExecution(workflow_id="id1", run_id="id2") + ) + assert plain_proto_payload.metadata["encoding"] == b"json/protobuf" + + +def test_temporal_transfer_type_payload_converter_without_transfer_type_hint(): + converter = DataConverter.default.payload_converter + value = TemporalTransferTypeValueWithoutHint("workflow-id") + + payload = converter.to_payload(value) + + assert payload.metadata["encoding"] == b"json/protobuf" + assert ( + payload.metadata["messageType"] == b"temporal.api.common.v1.WorkflowExecution" + ) + assert ( + converter.from_payload(payload, TemporalTransferTypeValueWithoutHint) == value + ) + + +def test_transfer_type_convertible_rejects_existing_converter(): + with pytest.raises(TypeError, match="already has a transfer type converter"): + transfer_type_convertible(TemporalTransferTypeValueConverter)( + TemporalTransferTypeValue + ) + + def test_encode_search_attribute_values(): with pytest.raises(TypeError, match="of type tuple not one of"): encode_search_attribute_values([("bad type",)]) # type: ignore[arg-type] diff --git a/tests/worker/test_visitor.py b/tests/worker/test_visitor.py index bd4004625..3c3df42c1 100644 --- a/tests/worker/test_visitor.py +++ b/tests/worker/test_visitor.py @@ -357,7 +357,9 @@ async def _visit(self) -> None: finally: active_visits -= 1 - payload_converter = nexus_system.get_payload_converter() + payload_converter = nexus_system._get_payload_converter( + temporalio.converter.PayloadConverter.default + ) system_request = workflowservice_pb2.SignalWithStartWorkflowExecutionRequest( input=Payloads(payloads=[Payload(data=b"workflow-input")]), signal_input=Payloads(payloads=[Payload(data=b"signal-input")]), From 60e3b73474eea0e7d69c96a68f041a77bcc6f14d Mon Sep 17 00:00:00 2001 From: xumaple <45406854+xumaple@users.noreply.github.com> Date: Thu, 23 Jul 2026 20:02:55 -0400 Subject: [PATCH 182/226] Fix type checking for openai 2.45.0 (#1673) --- tests/contrib/openai_agents/test_openai_streaming.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/contrib/openai_agents/test_openai_streaming.py b/tests/contrib/openai_agents/test_openai_streaming.py index 851dc207d..ab711cd86 100644 --- a/tests/contrib/openai_agents/test_openai_streaming.py +++ b/tests/contrib/openai_agents/test_openai_streaming.py @@ -159,7 +159,9 @@ async def stream_response( input_tokens=10, output_tokens=5, total_tokens=15, - input_tokens_details=InputTokensDetails(cached_tokens=0), + input_tokens_details=InputTokensDetails.model_validate( + {"cached_tokens": 0, "cache_write_tokens": 0} + ), output_tokens_details=OutputTokensDetails(reasoning_tokens=0), ), ) From 43f59190abae83ee8625b14c7a3b65f2fb4c706f Mon Sep 17 00:00:00 2001 From: Spencer Judge Date: Mon, 27 Jul 2026 11:11:33 -0700 Subject: [PATCH 183/226] Make eager activity reservation limit configurable (#1674) --- CHANGELOG.md | 3 + temporalio/api/activity/v1/message_pb2.py | 24 +- temporalio/api/activity/v1/message_pb2.pyi | 40 +- temporalio/api/batch/v1/__init__.py | 6 + temporalio/api/batch/v1/message_pb2.py | 92 +- temporalio/api/batch/v1/message_pb2.pyi | 81 ++ temporalio/api/command/v1/message_pb2.py | 85 +- temporalio/api/command/v1/message_pb2.pyi | 15 + temporalio/api/common/v1/__init__.py | 2 + temporalio/api/common/v1/message_pb2.py | 116 +- temporalio/api/common/v1/message_pb2.pyi | 42 +- temporalio/api/enums/v1/__init__.py | 2 + temporalio/api/enums/v1/activity_pb2.py | 13 +- temporalio/api/enums/v1/activity_pb2.pyi | 12 +- .../api/enums/v1/batch_operation_pb2.py | 43 +- .../api/enums/v1/batch_operation_pb2.pyi | 34 + temporalio/api/enums/v1/common_pb2.py | 9 +- temporalio/api/enums/v1/common_pb2.pyi | 26 + temporalio/api/enums/v1/failed_cause_pb2.py | 27 +- temporalio/api/enums/v1/failed_cause_pb2.pyi | 26 + temporalio/api/errordetails/v1/__init__.py | 2 + temporalio/api/errordetails/v1/message_pb2.py | 92 +- .../api/errordetails/v1/message_pb2.pyi | 26 +- temporalio/api/history/v1/message_pb2.py | 124 +- temporalio/api/history/v1/message_pb2.pyi | 14 + temporalio/api/namespace/v1/message_pb2.py | 38 +- temporalio/api/namespace/v1/message_pb2.pyi | 24 + temporalio/api/taskqueue/v1/__init__.py | 2 + temporalio/api/taskqueue/v1/message_pb2.py | 98 +- temporalio/api/taskqueue/v1/message_pb2.pyi | 46 + .../v1/request_response_pb2.py | 1108 +++++++++-------- .../v1/request_response_pb2.pyi | 222 +++- temporalio/bridge/Cargo.lock | 527 ++++---- temporalio/bridge/sdk-core | 2 +- temporalio/bridge/src/worker.rs | 4 + temporalio/bridge/worker.py | 1 + temporalio/worker/_replayer.py | 1 + temporalio/worker/_worker.py | 16 + tests/worker/test_worker.py | 31 + 39 files changed, 1883 insertions(+), 1193 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6230f2754..0de28b563 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,6 +20,9 @@ to include examples, links to docs, or any other relevant information. ### Added +- Added the `Worker` `max_eager_activity_reservations_per_workflow_task` option for configuring + the number of activity slots reserved for eager execution per workflow task. Configured values + must be positive; use `disable_eager_activity_execution` to disable eager activity execution. - Added experimental SDK payload converter support for values and type hints decorated with `@transfer_type_convertible(...)` using a `TransferTypeConverter` class. This lets types with transfer type converters delegate their wire representation to the diff --git a/temporalio/api/activity/v1/message_pb2.py b/temporalio/api/activity/v1/message_pb2.py index 4f0a4b164..e3b6a79c6 100644 --- a/temporalio/api/activity/v1/message_pb2.py +++ b/temporalio/api/activity/v1/message_pb2.py @@ -43,7 +43,7 @@ ) DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile( - b'\n&temporal/api/activity/v1/message.proto\x12\x18temporal.api.activity.v1\x1a\x1egoogle/protobuf/duration.proto\x1a\x1fgoogle/protobuf/timestamp.proto\x1a$temporal/api/common/v1/message.proto\x1a(temporal/api/deployment/v1/message.proto\x1a$temporal/api/enums/v1/activity.proto\x1a&temporal/api/callback/v1/message.proto\x1a$temporal/api/enums/v1/workflow.proto\x1a%temporal/api/failure/v1/message.proto\x1a\'temporal/api/taskqueue/v1/message.proto\x1a\'temporal/api/sdk/v1/user_metadata.proto"\x8c\x01\n\x18\x41\x63tivityExecutionOutcome\x12\x32\n\x06result\x18\x01 \x01(\x0b\x32 .temporal.api.common.v1.PayloadsH\x00\x12\x33\n\x07\x66\x61ilure\x18\x02 \x01(\x0b\x32 .temporal.api.failure.v1.FailureH\x00\x42\x07\n\x05value"\xa7\x03\n\x0f\x41\x63tivityOptions\x12\x38\n\ntask_queue\x18\x01 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12<\n\x19schedule_to_close_timeout\x18\x02 \x01(\x0b\x32\x19.google.protobuf.Duration\x12<\n\x19schedule_to_start_timeout\x18\x03 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x39\n\x16start_to_close_timeout\x18\x04 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x34\n\x11heartbeat_timeout\x18\x05 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x39\n\x0cretry_policy\x18\x06 \x01(\x0b\x32#.temporal.api.common.v1.RetryPolicy\x12\x32\n\x08priority\x18\x07 \x01(\x0b\x32 .temporal.api.common.v1.Priority"\x82\x0e\n\x15\x41\x63tivityExecutionInfo\x12\x13\n\x0b\x61\x63tivity_id\x18\x01 \x01(\t\x12\x0e\n\x06run_id\x18\x02 \x01(\t\x12;\n\ractivity_type\x18\x03 \x01(\x0b\x32$.temporal.api.common.v1.ActivityType\x12>\n\x06status\x18\x04 \x01(\x0e\x32..temporal.api.enums.v1.ActivityExecutionStatus\x12>\n\trun_state\x18\x05 \x01(\x0e\x32+.temporal.api.enums.v1.PendingActivityState\x12\x12\n\ntask_queue\x18\x06 \x01(\t\x12<\n\x19schedule_to_close_timeout\x18\x07 \x01(\x0b\x32\x19.google.protobuf.Duration\x12<\n\x19schedule_to_start_timeout\x18\x08 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x39\n\x16start_to_close_timeout\x18\t \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x34\n\x11heartbeat_timeout\x18\n \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x39\n\x0cretry_policy\x18\x0b \x01(\x0b\x32#.temporal.api.common.v1.RetryPolicy\x12;\n\x11heartbeat_details\x18\x0c \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x37\n\x13last_heartbeat_time\x18\r \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x35\n\x11last_started_time\x18\x0e \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x0f\n\x07\x61ttempt\x18\x0f \x01(\x05\x12\x35\n\x12\x65xecution_duration\x18\x10 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x31\n\rschedule_time\x18\x11 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x33\n\x0f\x65xpiration_time\x18\x12 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12.\n\nclose_time\x18\x13 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x36\n\x0clast_failure\x18\x14 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12\x1c\n\x14last_worker_identity\x18\x15 \x01(\t\x12\x39\n\x16\x63urrent_retry_interval\x18\x16 \x01(\x0b\x32\x19.google.protobuf.Duration\x12>\n\x1alast_attempt_complete_time\x18\x17 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12>\n\x1anext_attempt_schedule_time\x18\x18 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12T\n\x17last_deployment_version\x18\x19 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersion\x12\x32\n\x08priority\x18\x1a \x01(\x0b\x32 .temporal.api.common.v1.Priority\x12\x1e\n\x16state_transition_count\x18\x1b \x01(\x03\x12\x18\n\x10state_size_bytes\x18\x1c \x01(\x03\x12\x43\n\x11search_attributes\x18\x1d \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes\x12.\n\x06header\x18\x1e \x01(\x0b\x32\x1e.temporal.api.common.v1.Header\x12\x38\n\ruser_metadata\x18\x1f \x01(\x0b\x32!.temporal.api.sdk.v1.UserMetadata\x12\x17\n\x0f\x63\x61nceled_reason\x18 \x01(\t\x12+\n\x05links\x18! \x03(\x0b\x32\x1c.temporal.api.common.v1.Link\x12\x1d\n\x15total_heartbeat_count\x18" \x01(\x03\x12\x10\n\x08sdk_name\x18# \x01(\t\x12\x13\n\x0bsdk_version\x18$ \x01(\t\x12.\n\x0bstart_delay\x18% \x01(\x0b\x32\x19.google.protobuf.Duration"\xea\x03\n\x19\x41\x63tivityExecutionListInfo\x12\x13\n\x0b\x61\x63tivity_id\x18\x01 \x01(\t\x12\x0e\n\x06run_id\x18\x02 \x01(\t\x12;\n\ractivity_type\x18\x03 \x01(\x0b\x32$.temporal.api.common.v1.ActivityType\x12\x31\n\rschedule_time\x18\x04 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12.\n\nclose_time\x18\x05 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12>\n\x06status\x18\x06 \x01(\x0e\x32..temporal.api.enums.v1.ActivityExecutionStatus\x12\x43\n\x11search_attributes\x18\x07 \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes\x12\x12\n\ntask_queue\x18\x08 \x01(\t\x12\x1e\n\x16state_transition_count\x18\t \x01(\x03\x12\x18\n\x10state_size_bytes\x18\n \x01(\x03\x12\x35\n\x12\x65xecution_duration\x18\x0b \x01(\x0b\x32\x19.google.protobuf.Duration"\xff\x01\n\x0c\x43\x61llbackInfo\x12?\n\x07trigger\x18\x01 \x01(\x0b\x32..temporal.api.activity.v1.CallbackInfo.Trigger\x12\x34\n\x04info\x18\x02 \x01(\x0b\x32&.temporal.api.callback.v1.CallbackInfo\x1a\x10\n\x0e\x41\x63tivityClosed\x1a\x66\n\x07Trigger\x12P\n\x0f\x61\x63tivity_closed\x18\x01 \x01(\x0b\x32\x35.temporal.api.activity.v1.CallbackInfo.ActivityClosedH\x00\x42\t\n\x07variantB\x93\x01\n\x1bio.temporal.api.activity.v1B\x0cMessageProtoP\x01Z\'go.temporal.io/api/activity/v1;activity\xaa\x02\x1aTemporalio.Api.Activity.V1\xea\x02\x1dTemporalio::Api::Activity::V1b\x06proto3' + b'\n&temporal/api/activity/v1/message.proto\x12\x18temporal.api.activity.v1\x1a\x1egoogle/protobuf/duration.proto\x1a\x1fgoogle/protobuf/timestamp.proto\x1a$temporal/api/common/v1/message.proto\x1a(temporal/api/deployment/v1/message.proto\x1a$temporal/api/enums/v1/activity.proto\x1a&temporal/api/callback/v1/message.proto\x1a$temporal/api/enums/v1/workflow.proto\x1a%temporal/api/failure/v1/message.proto\x1a\'temporal/api/taskqueue/v1/message.proto\x1a\'temporal/api/sdk/v1/user_metadata.proto"\x8c\x01\n\x18\x41\x63tivityExecutionOutcome\x12\x32\n\x06result\x18\x01 \x01(\x0b\x32 .temporal.api.common.v1.PayloadsH\x00\x12\x33\n\x07\x66\x61ilure\x18\x02 \x01(\x0b\x32 .temporal.api.failure.v1.FailureH\x00\x42\x07\n\x05value"\xd7\x03\n\x0f\x41\x63tivityOptions\x12\x38\n\ntask_queue\x18\x01 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12<\n\x19schedule_to_close_timeout\x18\x02 \x01(\x0b\x32\x19.google.protobuf.Duration\x12<\n\x19schedule_to_start_timeout\x18\x03 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x39\n\x16start_to_close_timeout\x18\x04 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x34\n\x11heartbeat_timeout\x18\x05 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x39\n\x0cretry_policy\x18\x06 \x01(\x0b\x32#.temporal.api.common.v1.RetryPolicy\x12\x32\n\x08priority\x18\x07 \x01(\x0b\x32 .temporal.api.common.v1.Priority\x12.\n\x0bstart_delay\x18\x08 \x01(\x0b\x32\x19.google.protobuf.Duration"\xb6\x0e\n\x15\x41\x63tivityExecutionInfo\x12\x13\n\x0b\x61\x63tivity_id\x18\x01 \x01(\t\x12\x0e\n\x06run_id\x18\x02 \x01(\t\x12;\n\ractivity_type\x18\x03 \x01(\x0b\x32$.temporal.api.common.v1.ActivityType\x12>\n\x06status\x18\x04 \x01(\x0e\x32..temporal.api.enums.v1.ActivityExecutionStatus\x12>\n\trun_state\x18\x05 \x01(\x0e\x32+.temporal.api.enums.v1.PendingActivityState\x12\x12\n\ntask_queue\x18\x06 \x01(\t\x12<\n\x19schedule_to_close_timeout\x18\x07 \x01(\x0b\x32\x19.google.protobuf.Duration\x12<\n\x19schedule_to_start_timeout\x18\x08 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x39\n\x16start_to_close_timeout\x18\t \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x34\n\x11heartbeat_timeout\x18\n \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x39\n\x0cretry_policy\x18\x0b \x01(\x0b\x32#.temporal.api.common.v1.RetryPolicy\x12;\n\x11heartbeat_details\x18\x0c \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x37\n\x13last_heartbeat_time\x18\r \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x35\n\x11last_started_time\x18\x0e \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x0f\n\x07\x61ttempt\x18\x0f \x01(\x05\x12\x35\n\x12\x65xecution_duration\x18\x10 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x31\n\rschedule_time\x18\x11 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x33\n\x0f\x65xpiration_time\x18\x12 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12.\n\nclose_time\x18\x13 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x36\n\x0clast_failure\x18\x14 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12\x1c\n\x14last_worker_identity\x18\x15 \x01(\t\x12\x39\n\x16\x63urrent_retry_interval\x18\x16 \x01(\x0b\x32\x19.google.protobuf.Duration\x12>\n\x1alast_attempt_complete_time\x18\x17 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12>\n\x1anext_attempt_schedule_time\x18\x18 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12T\n\x17last_deployment_version\x18\x19 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersion\x12\x32\n\x08priority\x18\x1a \x01(\x0b\x32 .temporal.api.common.v1.Priority\x12\x1e\n\x16state_transition_count\x18\x1b \x01(\x03\x12\x18\n\x10state_size_bytes\x18\x1c \x01(\x03\x12\x43\n\x11search_attributes\x18\x1d \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes\x12.\n\x06header\x18\x1e \x01(\x0b\x32\x1e.temporal.api.common.v1.Header\x12\x38\n\ruser_metadata\x18\x1f \x01(\x0b\x32!.temporal.api.sdk.v1.UserMetadata\x12\x17\n\x0f\x63\x61nceled_reason\x18 \x01(\t\x12+\n\x05links\x18! \x03(\x0b\x32\x1c.temporal.api.common.v1.Link\x12\x1d\n\x15total_heartbeat_count\x18" \x01(\x03\x12\x10\n\x08sdk_name\x18# \x01(\t\x12\x13\n\x0bsdk_version\x18$ \x01(\t\x12.\n\x0bstart_delay\x18% \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x32\n\x0e\x65xecution_time\x18& \x01(\x0b\x32\x1a.google.protobuf.Timestamp"\x9e\x04\n\x19\x41\x63tivityExecutionListInfo\x12\x13\n\x0b\x61\x63tivity_id\x18\x01 \x01(\t\x12\x0e\n\x06run_id\x18\x02 \x01(\t\x12;\n\ractivity_type\x18\x03 \x01(\x0b\x32$.temporal.api.common.v1.ActivityType\x12\x31\n\rschedule_time\x18\x04 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12.\n\nclose_time\x18\x05 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12>\n\x06status\x18\x06 \x01(\x0e\x32..temporal.api.enums.v1.ActivityExecutionStatus\x12\x43\n\x11search_attributes\x18\x07 \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes\x12\x12\n\ntask_queue\x18\x08 \x01(\t\x12\x1e\n\x16state_transition_count\x18\t \x01(\x03\x12\x18\n\x10state_size_bytes\x18\n \x01(\x03\x12\x35\n\x12\x65xecution_duration\x18\x0b \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x32\n\x0e\x65xecution_time\x18\x0c \x01(\x0b\x32\x1a.google.protobuf.Timestamp"\xff\x01\n\x0c\x43\x61llbackInfo\x12?\n\x07trigger\x18\x01 \x01(\x0b\x32..temporal.api.activity.v1.CallbackInfo.Trigger\x12\x34\n\x04info\x18\x02 \x01(\x0b\x32&.temporal.api.callback.v1.CallbackInfo\x1a\x10\n\x0e\x41\x63tivityClosed\x1a\x66\n\x07Trigger\x12P\n\x0f\x61\x63tivity_closed\x18\x01 \x01(\x0b\x32\x35.temporal.api.activity.v1.CallbackInfo.ActivityClosedH\x00\x42\t\n\x07variantB\x93\x01\n\x1bio.temporal.api.activity.v1B\x0cMessageProtoP\x01Z\'go.temporal.io/api/activity/v1;activity\xaa\x02\x1aTemporalio.Api.Activity.V1\xea\x02\x1dTemporalio::Api::Activity::V1b\x06proto3' ) @@ -137,15 +137,15 @@ _ACTIVITYEXECUTIONOUTCOME._serialized_start = 451 _ACTIVITYEXECUTIONOUTCOME._serialized_end = 591 _ACTIVITYOPTIONS._serialized_start = 594 - _ACTIVITYOPTIONS._serialized_end = 1017 - _ACTIVITYEXECUTIONINFO._serialized_start = 1020 - _ACTIVITYEXECUTIONINFO._serialized_end = 2814 - _ACTIVITYEXECUTIONLISTINFO._serialized_start = 2817 - _ACTIVITYEXECUTIONLISTINFO._serialized_end = 3307 - _CALLBACKINFO._serialized_start = 3310 - _CALLBACKINFO._serialized_end = 3565 - _CALLBACKINFO_ACTIVITYCLOSED._serialized_start = 3445 - _CALLBACKINFO_ACTIVITYCLOSED._serialized_end = 3461 - _CALLBACKINFO_TRIGGER._serialized_start = 3463 - _CALLBACKINFO_TRIGGER._serialized_end = 3565 + _ACTIVITYOPTIONS._serialized_end = 1065 + _ACTIVITYEXECUTIONINFO._serialized_start = 1068 + _ACTIVITYEXECUTIONINFO._serialized_end = 2914 + _ACTIVITYEXECUTIONLISTINFO._serialized_start = 2917 + _ACTIVITYEXECUTIONLISTINFO._serialized_end = 3459 + _CALLBACKINFO._serialized_start = 3462 + _CALLBACKINFO._serialized_end = 3717 + _CALLBACKINFO_ACTIVITYCLOSED._serialized_start = 3597 + _CALLBACKINFO_ACTIVITYCLOSED._serialized_end = 3613 + _CALLBACKINFO_TRIGGER._serialized_start = 3615 + _CALLBACKINFO_TRIGGER._serialized_end = 3717 # @@protoc_insertion_point(module_scope) diff --git a/temporalio/api/activity/v1/message_pb2.pyi b/temporalio/api/activity/v1/message_pb2.pyi index e57f3860c..46c3cef96 100644 --- a/temporalio/api/activity/v1/message_pb2.pyi +++ b/temporalio/api/activity/v1/message_pb2.pyi @@ -76,6 +76,7 @@ class ActivityOptions(google.protobuf.message.Message): HEARTBEAT_TIMEOUT_FIELD_NUMBER: builtins.int RETRY_POLICY_FIELD_NUMBER: builtins.int PRIORITY_FIELD_NUMBER: builtins.int + START_DELAY_FIELD_NUMBER: builtins.int @property def task_queue(self) -> temporalio.api.taskqueue.v1.message_pb2.TaskQueue: ... @property @@ -116,6 +117,12 @@ class ActivityOptions(google.protobuf.message.Message): """Priority metadata. If this message is not present, or any fields are not present, they inherit the values from the workflow. """ + @property + def start_delay(self) -> google.protobuf.duration_pb2.Duration: + """Time to wait before making the first activity task available for dispatch. This delay is not applied to retry attempts. + When updated, the time is added to the original `schedule_time`, not to the current time. + If the resulting time is in the past, the task is made available for dispatch immediately. + """ def __init__( self, *, @@ -126,6 +133,7 @@ class ActivityOptions(google.protobuf.message.Message): heartbeat_timeout: google.protobuf.duration_pb2.Duration | None = ..., retry_policy: temporalio.api.common.v1.message_pb2.RetryPolicy | None = ..., priority: temporalio.api.common.v1.message_pb2.Priority | None = ..., + start_delay: google.protobuf.duration_pb2.Duration | None = ..., ) -> None: ... def HasField( self, @@ -140,6 +148,8 @@ class ActivityOptions(google.protobuf.message.Message): b"schedule_to_close_timeout", "schedule_to_start_timeout", b"schedule_to_start_timeout", + "start_delay", + b"start_delay", "start_to_close_timeout", b"start_to_close_timeout", "task_queue", @@ -159,6 +169,8 @@ class ActivityOptions(google.protobuf.message.Message): b"schedule_to_close_timeout", "schedule_to_start_timeout", b"schedule_to_start_timeout", + "start_delay", + b"start_delay", "start_to_close_timeout", b"start_to_close_timeout", "task_queue", @@ -210,6 +222,7 @@ class ActivityExecutionInfo(google.protobuf.message.Message): SDK_NAME_FIELD_NUMBER: builtins.int SDK_VERSION_FIELD_NUMBER: builtins.int START_DELAY_FIELD_NUMBER: builtins.int + EXECUTION_TIME_FIELD_NUMBER: builtins.int activity_id: builtins.str """Unique identifier of this activity within its namespace along with run ID (below).""" run_id: builtins.str @@ -273,7 +286,9 @@ class ActivityExecutionInfo(google.protobuf.message.Message): """Time the activity was originally scheduled via a StartActivityExecution request.""" @property def expiration_time(self) -> google.protobuf.timestamp_pb2.Timestamp: - """Scheduled time + schedule to close timeout.""" + """The time at which the activity's Schedule-to-Close timeout expires. + Calculated as `schedule_time` + `start_delay` + `schedule_to_close_timeout`. + """ @property def close_time(self) -> google.protobuf.timestamp_pb2.Timestamp: """Time when the activity transitioned to a closed state.""" @@ -344,7 +359,12 @@ class ActivityExecutionInfo(google.protobuf.message.Message): """ @property def start_delay(self) -> google.protobuf.duration_pb2.Duration: - """Time to wait before dispatching the first activity task. This delay is not applied to retry attempts.""" + """Time to wait before making the first activity task available for dispatch. This delay is not applied to retry attempts.""" + @property + def execution_time(self) -> google.protobuf.timestamp_pb2.Timestamp: + """The time at which the first activity task is made available for dispatch, computed as + `schedule_time + start_delay`. Same as `schedule_time` if `start_delay` is not set. + """ def __init__( self, *, @@ -391,6 +411,7 @@ class ActivityExecutionInfo(google.protobuf.message.Message): sdk_name: builtins.str = ..., sdk_version: builtins.str = ..., start_delay: google.protobuf.duration_pb2.Duration | None = ..., + execution_time: google.protobuf.timestamp_pb2.Timestamp | None = ..., ) -> None: ... def HasField( self, @@ -403,6 +424,8 @@ class ActivityExecutionInfo(google.protobuf.message.Message): b"current_retry_interval", "execution_duration", b"execution_duration", + "execution_time", + b"execution_time", "expiration_time", b"expiration_time", "header", @@ -460,6 +483,8 @@ class ActivityExecutionInfo(google.protobuf.message.Message): b"current_retry_interval", "execution_duration", b"execution_duration", + "execution_time", + b"execution_time", "expiration_time", b"expiration_time", "header", @@ -544,6 +569,7 @@ class ActivityExecutionListInfo(google.protobuf.message.Message): STATE_TRANSITION_COUNT_FIELD_NUMBER: builtins.int STATE_SIZE_BYTES_FIELD_NUMBER: builtins.int EXECUTION_DURATION_FIELD_NUMBER: builtins.int + EXECUTION_TIME_FIELD_NUMBER: builtins.int activity_id: builtins.str """A unique identifier of this activity within its namespace along with run ID (below).""" run_id: builtins.str @@ -577,6 +603,11 @@ class ActivityExecutionListInfo(google.protobuf.message.Message): """The difference between close time and scheduled time. This field is only populated if the activity is closed. """ + @property + def execution_time(self) -> google.protobuf.timestamp_pb2.Timestamp: + """The time at which the first activity task is made available for dispatch, computed as + `schedule_time + start_delay`. Same as `schedule_time` if `start_delay` is not set. + """ def __init__( self, *, @@ -592,6 +623,7 @@ class ActivityExecutionListInfo(google.protobuf.message.Message): state_transition_count: builtins.int = ..., state_size_bytes: builtins.int = ..., execution_duration: google.protobuf.duration_pb2.Duration | None = ..., + execution_time: google.protobuf.timestamp_pb2.Timestamp | None = ..., ) -> None: ... def HasField( self, @@ -602,6 +634,8 @@ class ActivityExecutionListInfo(google.protobuf.message.Message): b"close_time", "execution_duration", b"execution_duration", + "execution_time", + b"execution_time", "schedule_time", b"schedule_time", "search_attributes", @@ -619,6 +653,8 @@ class ActivityExecutionListInfo(google.protobuf.message.Message): b"close_time", "execution_duration", b"execution_duration", + "execution_time", + b"execution_time", "run_id", b"run_id", "schedule_time", diff --git a/temporalio/api/batch/v1/__init__.py b/temporalio/api/batch/v1/__init__.py index 5ec8ad63a..fea70b41f 100644 --- a/temporalio/api/batch/v1/__init__.py +++ b/temporalio/api/batch/v1/__init__.py @@ -1,10 +1,13 @@ from .message_pb2 import ( + BatchOperationCancelActivities, BatchOperationCancellation, + BatchOperationDeleteActivities, BatchOperationDeletion, BatchOperationInfo, BatchOperationReset, BatchOperationResetActivities, BatchOperationSignal, + BatchOperationTerminateActivities, BatchOperationTermination, BatchOperationTriggerWorkflowRule, BatchOperationUnpauseActivities, @@ -13,12 +16,15 @@ ) __all__ = [ + "BatchOperationCancelActivities", "BatchOperationCancellation", + "BatchOperationDeleteActivities", "BatchOperationDeletion", "BatchOperationInfo", "BatchOperationReset", "BatchOperationResetActivities", "BatchOperationSignal", + "BatchOperationTerminateActivities", "BatchOperationTermination", "BatchOperationTriggerWorkflowRule", "BatchOperationUnpauseActivities", diff --git a/temporalio/api/batch/v1/message_pb2.py b/temporalio/api/batch/v1/message_pb2.py index cb1e39b73..292b2c182 100644 --- a/temporalio/api/batch/v1/message_pb2.py +++ b/temporalio/api/batch/v1/message_pb2.py @@ -38,7 +38,7 @@ ) DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile( - b'\n#temporal/api/batch/v1/message.proto\x12\x15temporal.api.batch.v1\x1a\x1egoogle/protobuf/duration.proto\x1a google/protobuf/field_mask.proto\x1a\x1fgoogle/protobuf/timestamp.proto\x1a&temporal/api/activity/v1/message.proto\x1a$temporal/api/common/v1/message.proto\x1a+temporal/api/enums/v1/batch_operation.proto\x1a!temporal/api/enums/v1/reset.proto\x1a#temporal/api/rules/v1/message.proto\x1a&temporal/api/workflow/v1/message.proto"\xbf\x01\n\x12\x42\x61tchOperationInfo\x12\x0e\n\x06job_id\x18\x01 \x01(\t\x12\x39\n\x05state\x18\x02 \x01(\x0e\x32*.temporal.api.enums.v1.BatchOperationState\x12.\n\nstart_time\x18\x03 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12.\n\nclose_time\x18\x04 \x01(\x0b\x32\x1a.google.protobuf.Timestamp"`\n\x19\x42\x61tchOperationTermination\x12\x31\n\x07\x64\x65tails\x18\x01 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x10\n\x08identity\x18\x02 \x01(\t"\x99\x01\n\x14\x42\x61tchOperationSignal\x12\x0e\n\x06signal\x18\x01 \x01(\t\x12/\n\x05input\x18\x02 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12.\n\x06header\x18\x03 \x01(\x0b\x32\x1e.temporal.api.common.v1.Header\x12\x10\n\x08identity\x18\x04 \x01(\t".\n\x1a\x42\x61tchOperationCancellation\x12\x10\n\x08identity\x18\x01 \x01(\t"*\n\x16\x42\x61tchOperationDeletion\x12\x10\n\x08identity\x18\x01 \x01(\t"\xae\x02\n\x13\x42\x61tchOperationReset\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x35\n\x07options\x18\x04 \x01(\x0b\x32$.temporal.api.common.v1.ResetOptions\x12\x38\n\nreset_type\x18\x01 \x01(\x0e\x32 .temporal.api.enums.v1.ResetTypeB\x02\x18\x01\x12G\n\x12reset_reapply_type\x18\x02 \x01(\x0e\x32\'.temporal.api.enums.v1.ResetReapplyTypeB\x02\x18\x01\x12K\n\x15post_reset_operations\x18\x05 \x03(\x0b\x32,.temporal.api.workflow.v1.PostResetOperation"\xc9\x01\n,BatchOperationUpdateWorkflowExecutionOptions\x12\x10\n\x08identity\x18\x01 \x01(\t\x12V\n\x1aworkflow_execution_options\x18\x02 \x01(\x0b\x32\x32.temporal.api.workflow.v1.WorkflowExecutionOptions\x12/\n\x0bupdate_mask\x18\x03 \x01(\x0b\x32\x1a.google.protobuf.FieldMask"\xc0\x01\n\x1f\x42\x61tchOperationUnpauseActivities\x12\x10\n\x08identity\x18\x01 \x01(\t\x12\x0e\n\x04type\x18\x02 \x01(\tH\x00\x12\x13\n\tmatch_all\x18\x03 \x01(\x08H\x00\x12\x16\n\x0ereset_attempts\x18\x04 \x01(\x08\x12\x17\n\x0freset_heartbeat\x18\x05 \x01(\x08\x12)\n\x06jitter\x18\x06 \x01(\x0b\x32\x19.google.protobuf.DurationB\n\n\x08\x61\x63tivity"\x84\x01\n!BatchOperationTriggerWorkflowRule\x12\x10\n\x08identity\x18\x01 \x01(\t\x12\x0c\n\x02id\x18\x02 \x01(\tH\x00\x12\x37\n\x04spec\x18\x03 \x01(\x0b\x32\'.temporal.api.rules.v1.WorkflowRuleSpecH\x00\x42\x06\n\x04rule"\xf5\x01\n\x1d\x42\x61tchOperationResetActivities\x12\x10\n\x08identity\x18\x01 \x01(\t\x12\x0e\n\x04type\x18\x02 \x01(\tH\x00\x12\x13\n\tmatch_all\x18\x03 \x01(\x08H\x00\x12\x16\n\x0ereset_attempts\x18\x04 \x01(\x08\x12\x17\n\x0freset_heartbeat\x18\x05 \x01(\x08\x12\x13\n\x0bkeep_paused\x18\x06 \x01(\x08\x12)\n\x06jitter\x18\x07 \x01(\x0b\x32\x19.google.protobuf.Duration\x12 \n\x18restore_original_options\x18\x08 \x01(\x08\x42\n\n\x08\x61\x63tivity"\xf8\x01\n#BatchOperationUpdateActivityOptions\x12\x10\n\x08identity\x18\x01 \x01(\t\x12\x0e\n\x04type\x18\x02 \x01(\tH\x00\x12\x13\n\tmatch_all\x18\x03 \x01(\x08H\x00\x12\x43\n\x10\x61\x63tivity_options\x18\x04 \x01(\x0b\x32).temporal.api.activity.v1.ActivityOptions\x12/\n\x0bupdate_mask\x18\x05 \x01(\x0b\x32\x1a.google.protobuf.FieldMask\x12\x18\n\x10restore_original\x18\x06 \x01(\x08\x42\n\n\x08\x61\x63tivityB\x84\x01\n\x18io.temporal.api.batch.v1B\x0cMessageProtoP\x01Z!go.temporal.io/api/batch/v1;batch\xaa\x02\x17Temporalio.Api.Batch.V1\xea\x02\x1aTemporalio::Api::Batch::V1b\x06proto3' + b'\n#temporal/api/batch/v1/message.proto\x12\x15temporal.api.batch.v1\x1a\x1egoogle/protobuf/duration.proto\x1a google/protobuf/field_mask.proto\x1a\x1fgoogle/protobuf/timestamp.proto\x1a&temporal/api/activity/v1/message.proto\x1a$temporal/api/common/v1/message.proto\x1a+temporal/api/enums/v1/batch_operation.proto\x1a!temporal/api/enums/v1/reset.proto\x1a#temporal/api/rules/v1/message.proto\x1a&temporal/api/workflow/v1/message.proto"\x82\x02\n\x12\x42\x61tchOperationInfo\x12\x0e\n\x06job_id\x18\x01 \x01(\t\x12\x39\n\x05state\x18\x02 \x01(\x0e\x32*.temporal.api.enums.v1.BatchOperationState\x12.\n\nstart_time\x18\x03 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12.\n\nclose_time\x18\x04 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x41\n\x0eoperation_type\x18\x05 \x01(\x0e\x32).temporal.api.enums.v1.BatchOperationType"`\n\x19\x42\x61tchOperationTermination\x12\x31\n\x07\x64\x65tails\x18\x01 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x10\n\x08identity\x18\x02 \x01(\t"E\n!BatchOperationTerminateActivities\x12\x10\n\x08identity\x18\x01 \x01(\t\x12\x0e\n\x06reason\x18\x02 \x01(\t"\x99\x01\n\x14\x42\x61tchOperationSignal\x12\x0e\n\x06signal\x18\x01 \x01(\t\x12/\n\x05input\x18\x02 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12.\n\x06header\x18\x03 \x01(\x0b\x32\x1e.temporal.api.common.v1.Header\x12\x10\n\x08identity\x18\x04 \x01(\t".\n\x1a\x42\x61tchOperationCancellation\x12\x10\n\x08identity\x18\x01 \x01(\t"B\n\x1e\x42\x61tchOperationCancelActivities\x12\x10\n\x08identity\x18\x01 \x01(\t\x12\x0e\n\x06reason\x18\x02 \x01(\t"*\n\x16\x42\x61tchOperationDeletion\x12\x10\n\x08identity\x18\x01 \x01(\t" \n\x1e\x42\x61tchOperationDeleteActivities"\xae\x02\n\x13\x42\x61tchOperationReset\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x35\n\x07options\x18\x04 \x01(\x0b\x32$.temporal.api.common.v1.ResetOptions\x12\x38\n\nreset_type\x18\x01 \x01(\x0e\x32 .temporal.api.enums.v1.ResetTypeB\x02\x18\x01\x12G\n\x12reset_reapply_type\x18\x02 \x01(\x0e\x32\'.temporal.api.enums.v1.ResetReapplyTypeB\x02\x18\x01\x12K\n\x15post_reset_operations\x18\x05 \x03(\x0b\x32,.temporal.api.workflow.v1.PostResetOperation"\xc9\x01\n,BatchOperationUpdateWorkflowExecutionOptions\x12\x10\n\x08identity\x18\x01 \x01(\t\x12V\n\x1aworkflow_execution_options\x18\x02 \x01(\x0b\x32\x32.temporal.api.workflow.v1.WorkflowExecutionOptions\x12/\n\x0bupdate_mask\x18\x03 \x01(\x0b\x32\x1a.google.protobuf.FieldMask"\xc0\x01\n\x1f\x42\x61tchOperationUnpauseActivities\x12\x10\n\x08identity\x18\x01 \x01(\t\x12\x0e\n\x04type\x18\x02 \x01(\tH\x00\x12\x13\n\tmatch_all\x18\x03 \x01(\x08H\x00\x12\x16\n\x0ereset_attempts\x18\x04 \x01(\x08\x12\x17\n\x0freset_heartbeat\x18\x05 \x01(\x08\x12)\n\x06jitter\x18\x06 \x01(\x0b\x32\x19.google.protobuf.DurationB\n\n\x08\x61\x63tivity"\x84\x01\n!BatchOperationTriggerWorkflowRule\x12\x10\n\x08identity\x18\x01 \x01(\t\x12\x0c\n\x02id\x18\x02 \x01(\tH\x00\x12\x37\n\x04spec\x18\x03 \x01(\x0b\x32\'.temporal.api.rules.v1.WorkflowRuleSpecH\x00\x42\x06\n\x04rule"\xf5\x01\n\x1d\x42\x61tchOperationResetActivities\x12\x10\n\x08identity\x18\x01 \x01(\t\x12\x0e\n\x04type\x18\x02 \x01(\tH\x00\x12\x13\n\tmatch_all\x18\x03 \x01(\x08H\x00\x12\x16\n\x0ereset_attempts\x18\x04 \x01(\x08\x12\x17\n\x0freset_heartbeat\x18\x05 \x01(\x08\x12\x13\n\x0bkeep_paused\x18\x06 \x01(\x08\x12)\n\x06jitter\x18\x07 \x01(\x0b\x32\x19.google.protobuf.Duration\x12 \n\x18restore_original_options\x18\x08 \x01(\x08\x42\n\n\x08\x61\x63tivity"\xf8\x01\n#BatchOperationUpdateActivityOptions\x12\x10\n\x08identity\x18\x01 \x01(\t\x12\x0e\n\x04type\x18\x02 \x01(\tH\x00\x12\x13\n\tmatch_all\x18\x03 \x01(\x08H\x00\x12\x43\n\x10\x61\x63tivity_options\x18\x04 \x01(\x0b\x32).temporal.api.activity.v1.ActivityOptions\x12/\n\x0bupdate_mask\x18\x05 \x01(\x0b\x32\x1a.google.protobuf.FieldMask\x12\x18\n\x10restore_original\x18\x06 \x01(\x08\x42\n\n\x08\x61\x63tivityB\x84\x01\n\x18io.temporal.api.batch.v1B\x0cMessageProtoP\x01Z!go.temporal.io/api/batch/v1;batch\xaa\x02\x17Temporalio.Api.Batch.V1\xea\x02\x1aTemporalio::Api::Batch::V1b\x06proto3' ) @@ -46,11 +46,20 @@ _BATCHOPERATIONTERMINATION = DESCRIPTOR.message_types_by_name[ "BatchOperationTermination" ] +_BATCHOPERATIONTERMINATEACTIVITIES = DESCRIPTOR.message_types_by_name[ + "BatchOperationTerminateActivities" +] _BATCHOPERATIONSIGNAL = DESCRIPTOR.message_types_by_name["BatchOperationSignal"] _BATCHOPERATIONCANCELLATION = DESCRIPTOR.message_types_by_name[ "BatchOperationCancellation" ] +_BATCHOPERATIONCANCELACTIVITIES = DESCRIPTOR.message_types_by_name[ + "BatchOperationCancelActivities" +] _BATCHOPERATIONDELETION = DESCRIPTOR.message_types_by_name["BatchOperationDeletion"] +_BATCHOPERATIONDELETEACTIVITIES = DESCRIPTOR.message_types_by_name[ + "BatchOperationDeleteActivities" +] _BATCHOPERATIONRESET = DESCRIPTOR.message_types_by_name["BatchOperationReset"] _BATCHOPERATIONUPDATEWORKFLOWEXECUTIONOPTIONS = DESCRIPTOR.message_types_by_name[ "BatchOperationUpdateWorkflowExecutionOptions" @@ -89,6 +98,17 @@ ) _sym_db.RegisterMessage(BatchOperationTermination) +BatchOperationTerminateActivities = _reflection.GeneratedProtocolMessageType( + "BatchOperationTerminateActivities", + (_message.Message,), + { + "DESCRIPTOR": _BATCHOPERATIONTERMINATEACTIVITIES, + "__module__": "temporalio.api.batch.v1.message_pb2", + # @@protoc_insertion_point(class_scope:temporal.api.batch.v1.BatchOperationTerminateActivities) + }, +) +_sym_db.RegisterMessage(BatchOperationTerminateActivities) + BatchOperationSignal = _reflection.GeneratedProtocolMessageType( "BatchOperationSignal", (_message.Message,), @@ -111,6 +131,17 @@ ) _sym_db.RegisterMessage(BatchOperationCancellation) +BatchOperationCancelActivities = _reflection.GeneratedProtocolMessageType( + "BatchOperationCancelActivities", + (_message.Message,), + { + "DESCRIPTOR": _BATCHOPERATIONCANCELACTIVITIES, + "__module__": "temporalio.api.batch.v1.message_pb2", + # @@protoc_insertion_point(class_scope:temporal.api.batch.v1.BatchOperationCancelActivities) + }, +) +_sym_db.RegisterMessage(BatchOperationCancelActivities) + BatchOperationDeletion = _reflection.GeneratedProtocolMessageType( "BatchOperationDeletion", (_message.Message,), @@ -122,6 +153,17 @@ ) _sym_db.RegisterMessage(BatchOperationDeletion) +BatchOperationDeleteActivities = _reflection.GeneratedProtocolMessageType( + "BatchOperationDeleteActivities", + (_message.Message,), + { + "DESCRIPTOR": _BATCHOPERATIONDELETEACTIVITIES, + "__module__": "temporalio.api.batch.v1.message_pb2", + # @@protoc_insertion_point(class_scope:temporal.api.batch.v1.BatchOperationDeleteActivities) + }, +) +_sym_db.RegisterMessage(BatchOperationDeleteActivities) + BatchOperationReset = _reflection.GeneratedProtocolMessageType( "BatchOperationReset", (_message.Message,), @@ -198,25 +240,31 @@ "reset_reapply_type" ]._serialized_options = b"\030\001" _BATCHOPERATIONINFO._serialized_start = 397 - _BATCHOPERATIONINFO._serialized_end = 588 - _BATCHOPERATIONTERMINATION._serialized_start = 590 - _BATCHOPERATIONTERMINATION._serialized_end = 686 - _BATCHOPERATIONSIGNAL._serialized_start = 689 - _BATCHOPERATIONSIGNAL._serialized_end = 842 - _BATCHOPERATIONCANCELLATION._serialized_start = 844 - _BATCHOPERATIONCANCELLATION._serialized_end = 890 - _BATCHOPERATIONDELETION._serialized_start = 892 - _BATCHOPERATIONDELETION._serialized_end = 934 - _BATCHOPERATIONRESET._serialized_start = 937 - _BATCHOPERATIONRESET._serialized_end = 1239 - _BATCHOPERATIONUPDATEWORKFLOWEXECUTIONOPTIONS._serialized_start = 1242 - _BATCHOPERATIONUPDATEWORKFLOWEXECUTIONOPTIONS._serialized_end = 1443 - _BATCHOPERATIONUNPAUSEACTIVITIES._serialized_start = 1446 - _BATCHOPERATIONUNPAUSEACTIVITIES._serialized_end = 1638 - _BATCHOPERATIONTRIGGERWORKFLOWRULE._serialized_start = 1641 - _BATCHOPERATIONTRIGGERWORKFLOWRULE._serialized_end = 1773 - _BATCHOPERATIONRESETACTIVITIES._serialized_start = 1776 - _BATCHOPERATIONRESETACTIVITIES._serialized_end = 2021 - _BATCHOPERATIONUPDATEACTIVITYOPTIONS._serialized_start = 2024 - _BATCHOPERATIONUPDATEACTIVITYOPTIONS._serialized_end = 2272 + _BATCHOPERATIONINFO._serialized_end = 655 + _BATCHOPERATIONTERMINATION._serialized_start = 657 + _BATCHOPERATIONTERMINATION._serialized_end = 753 + _BATCHOPERATIONTERMINATEACTIVITIES._serialized_start = 755 + _BATCHOPERATIONTERMINATEACTIVITIES._serialized_end = 824 + _BATCHOPERATIONSIGNAL._serialized_start = 827 + _BATCHOPERATIONSIGNAL._serialized_end = 980 + _BATCHOPERATIONCANCELLATION._serialized_start = 982 + _BATCHOPERATIONCANCELLATION._serialized_end = 1028 + _BATCHOPERATIONCANCELACTIVITIES._serialized_start = 1030 + _BATCHOPERATIONCANCELACTIVITIES._serialized_end = 1096 + _BATCHOPERATIONDELETION._serialized_start = 1098 + _BATCHOPERATIONDELETION._serialized_end = 1140 + _BATCHOPERATIONDELETEACTIVITIES._serialized_start = 1142 + _BATCHOPERATIONDELETEACTIVITIES._serialized_end = 1174 + _BATCHOPERATIONRESET._serialized_start = 1177 + _BATCHOPERATIONRESET._serialized_end = 1479 + _BATCHOPERATIONUPDATEWORKFLOWEXECUTIONOPTIONS._serialized_start = 1482 + _BATCHOPERATIONUPDATEWORKFLOWEXECUTIONOPTIONS._serialized_end = 1683 + _BATCHOPERATIONUNPAUSEACTIVITIES._serialized_start = 1686 + _BATCHOPERATIONUNPAUSEACTIVITIES._serialized_end = 1878 + _BATCHOPERATIONTRIGGERWORKFLOWRULE._serialized_start = 1881 + _BATCHOPERATIONTRIGGERWORKFLOWRULE._serialized_end = 2013 + _BATCHOPERATIONRESETACTIVITIES._serialized_start = 2016 + _BATCHOPERATIONRESETACTIVITIES._serialized_end = 2261 + _BATCHOPERATIONUPDATEACTIVITYOPTIONS._serialized_start = 2264 + _BATCHOPERATIONUPDATEACTIVITYOPTIONS._serialized_end = 2512 # @@protoc_insertion_point(module_scope) diff --git a/temporalio/api/batch/v1/message_pb2.pyi b/temporalio/api/batch/v1/message_pb2.pyi index 0f7e87da0..106b351ef 100644 --- a/temporalio/api/batch/v1/message_pb2.pyi +++ b/temporalio/api/batch/v1/message_pb2.pyi @@ -35,6 +35,7 @@ class BatchOperationInfo(google.protobuf.message.Message): STATE_FIELD_NUMBER: builtins.int START_TIME_FIELD_NUMBER: builtins.int CLOSE_TIME_FIELD_NUMBER: builtins.int + OPERATION_TYPE_FIELD_NUMBER: builtins.int job_id: builtins.str """Batch job ID""" state: temporalio.api.enums.v1.batch_operation_pb2.BatchOperationState.ValueType @@ -45,6 +46,10 @@ class BatchOperationInfo(google.protobuf.message.Message): @property def close_time(self) -> google.protobuf.timestamp_pb2.Timestamp: """Batch operation close time""" + operation_type: ( + temporalio.api.enums.v1.batch_operation_pb2.BatchOperationType.ValueType + ) + """Operation type""" def __init__( self, *, @@ -52,6 +57,7 @@ class BatchOperationInfo(google.protobuf.message.Message): state: temporalio.api.enums.v1.batch_operation_pb2.BatchOperationState.ValueType = ..., start_time: google.protobuf.timestamp_pb2.Timestamp | None = ..., close_time: google.protobuf.timestamp_pb2.Timestamp | None = ..., + operation_type: temporalio.api.enums.v1.batch_operation_pb2.BatchOperationType.ValueType = ..., ) -> None: ... def HasField( self, @@ -66,6 +72,8 @@ class BatchOperationInfo(google.protobuf.message.Message): b"close_time", "job_id", b"job_id", + "operation_type", + b"operation_type", "start_time", b"start_time", "state", @@ -108,6 +116,36 @@ class BatchOperationTermination(google.protobuf.message.Message): global___BatchOperationTermination = BatchOperationTermination +class BatchOperationTerminateActivities(google.protobuf.message.Message): + """BatchOperationTerminateActivities sends terminate requests to a batch of activities. + Keep the parameter in sync with temporalio.api.workflowservice.v1.TerminateActivityExecutionRequest. + """ + + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + IDENTITY_FIELD_NUMBER: builtins.int + REASON_FIELD_NUMBER: builtins.int + identity: builtins.str + """The identity of the worker/client""" + reason: builtins.str + """Reason for requesting the termination, recorded and available via the PollActivityExecution API. + Not propagated to a worker if an activity attempt is currently running. + """ + def __init__( + self, + *, + identity: builtins.str = ..., + reason: builtins.str = ..., + ) -> None: ... + def ClearField( + self, + field_name: typing_extensions.Literal[ + "identity", b"identity", "reason", b"reason" + ], + ) -> None: ... + +global___BatchOperationTerminateActivities = BatchOperationTerminateActivities + class BatchOperationSignal(google.protobuf.message.Message): """BatchOperationSignal sends signals to batch workflows. Keep the parameter in sync with temporalio.api.workflowservice.v1.SignalWorkflowExecutionRequest. @@ -181,6 +219,36 @@ class BatchOperationCancellation(google.protobuf.message.Message): global___BatchOperationCancellation = BatchOperationCancellation +class BatchOperationCancelActivities(google.protobuf.message.Message): + """BatchOperationCancelActivities sends cancel requests to a batch of activities. + Keep the parameter in sync with temporalio.api.workflowservice.v1.RequestCancelActivityExecutionRequest. + """ + + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + IDENTITY_FIELD_NUMBER: builtins.int + REASON_FIELD_NUMBER: builtins.int + identity: builtins.str + """The identity of the worker/client""" + reason: builtins.str + """Reason for requesting the cancellation, recorded and available via the PollActivityExecution API. + Not propagated to a worker if an activity attempt is currently running. + """ + def __init__( + self, + *, + identity: builtins.str = ..., + reason: builtins.str = ..., + ) -> None: ... + def ClearField( + self, + field_name: typing_extensions.Literal[ + "identity", b"identity", "reason", b"reason" + ], + ) -> None: ... + +global___BatchOperationCancelActivities = BatchOperationCancelActivities + class BatchOperationDeletion(google.protobuf.message.Message): """BatchOperationDeletion sends deletion requests to batch workflows. Keep the parameter in sync with temporalio.api.workflowservice.v1.DeleteWorkflowExecutionRequest. @@ -202,6 +270,19 @@ class BatchOperationDeletion(google.protobuf.message.Message): global___BatchOperationDeletion = BatchOperationDeletion +class BatchOperationDeleteActivities(google.protobuf.message.Message): + """BatchOperationDeleteActivities sends deletion requests to a batch of activities. + Keep the parameter in sync with temporalio.api.workflowservice.v1.DeleteActivityExecutionRequest. + """ + + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + def __init__( + self, + ) -> None: ... + +global___BatchOperationDeleteActivities = BatchOperationDeleteActivities + class BatchOperationReset(google.protobuf.message.Message): """BatchOperationReset sends reset requests to batch workflows. Keep the parameter in sync with temporalio.api.workflowservice.v1.ResetWorkflowExecutionRequest. diff --git a/temporalio/api/command/v1/message_pb2.py b/temporalio/api/command/v1/message_pb2.py index f1a749b83..ad004ae03 100644 --- a/temporalio/api/command/v1/message_pb2.py +++ b/temporalio/api/command/v1/message_pb2.py @@ -37,9 +37,12 @@ from temporalio.api.taskqueue.v1 import ( message_pb2 as temporal_dot_api_dot_taskqueue_dot_v1_dot_message__pb2, ) +from temporalio.api.workflow.v1 import ( + message_pb2 as temporal_dot_api_dot_workflow_dot_v1_dot_message__pb2, +) DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile( - b'\n%temporal/api/command/v1/message.proto\x12\x17temporal.api.command.v1\x1a\x1egoogle/protobuf/duration.proto\x1a$temporal/api/enums/v1/workflow.proto\x1a(temporal/api/enums/v1/command_type.proto\x1a$temporal/api/common/v1/message.proto\x1a%temporal/api/failure/v1/message.proto\x1a\'temporal/api/taskqueue/v1/message.proto\x1a\'temporal/api/sdk/v1/user_metadata.proto\x1a,temporal/api/sdk/v1/event_group_marker.proto"\xb6\x05\n%ScheduleActivityTaskCommandAttributes\x12\x13\n\x0b\x61\x63tivity_id\x18\x01 \x01(\t\x12;\n\ractivity_type\x18\x02 \x01(\x0b\x32$.temporal.api.common.v1.ActivityType\x12\x38\n\ntask_queue\x18\x04 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12.\n\x06header\x18\x05 \x01(\x0b\x32\x1e.temporal.api.common.v1.Header\x12/\n\x05input\x18\x06 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12<\n\x19schedule_to_close_timeout\x18\x07 \x01(\x0b\x32\x19.google.protobuf.Duration\x12<\n\x19schedule_to_start_timeout\x18\x08 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x39\n\x16start_to_close_timeout\x18\t \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x34\n\x11heartbeat_timeout\x18\n \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x39\n\x0cretry_policy\x18\x0b \x01(\x0b\x32#.temporal.api.common.v1.RetryPolicy\x12\x1f\n\x17request_eager_execution\x18\x0c \x01(\x08\x12\x1d\n\x15use_workflow_build_id\x18\r \x01(\x08\x12\x32\n\x08priority\x18\x0e \x01(\x0b\x32 .temporal.api.common.v1.PriorityJ\x04\x08\x03\x10\x04"H\n*RequestCancelActivityTaskCommandAttributes\x12\x1a\n\x12scheduled_event_id\x18\x01 \x01(\x03"i\n\x1bStartTimerCommandAttributes\x12\x10\n\x08timer_id\x18\x01 \x01(\t\x12\x38\n\x15start_to_fire_timeout\x18\x02 \x01(\x0b\x32\x19.google.protobuf.Duration"^\n*CompleteWorkflowExecutionCommandAttributes\x12\x30\n\x06result\x18\x01 \x01(\x0b\x32 .temporal.api.common.v1.Payloads"[\n&FailWorkflowExecutionCommandAttributes\x12\x31\n\x07\x66\x61ilure\x18\x01 \x01(\x0b\x32 .temporal.api.failure.v1.Failure"0\n\x1c\x43\x61ncelTimerCommandAttributes\x12\x10\n\x08timer_id\x18\x01 \x01(\t"]\n(CancelWorkflowExecutionCommandAttributes\x12\x31\n\x07\x64\x65tails\x18\x01 \x01(\x0b\x32 .temporal.api.common.v1.Payloads"\xb7\x01\n7RequestCancelExternalWorkflowExecutionCommandAttributes\x12\x15\n\tnamespace\x18\x01 \x01(\tB\x02\x18\x01\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x12\x13\n\x07\x63ontrol\x18\x04 \x01(\tB\x02\x18\x01\x12\x1b\n\x13\x63hild_workflow_only\x18\x05 \x01(\x08\x12\x0e\n\x06reason\x18\x06 \x01(\t"\xaf\x02\n0SignalExternalWorkflowExecutionCommandAttributes\x12\x15\n\tnamespace\x18\x01 \x01(\tB\x02\x18\x01\x12<\n\texecution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x13\n\x0bsignal_name\x18\x03 \x01(\t\x12/\n\x05input\x18\x04 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x13\n\x07\x63ontrol\x18\x05 \x01(\tB\x02\x18\x01\x12\x1b\n\x13\x63hild_workflow_only\x18\x06 \x01(\x08\x12.\n\x06header\x18\x07 \x01(\x0b\x32\x1e.temporal.api.common.v1.Header"v\n/UpsertWorkflowSearchAttributesCommandAttributes\x12\x43\n\x11search_attributes\x18\x01 \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes"`\n)ModifyWorkflowPropertiesCommandAttributes\x12\x33\n\rupserted_memo\x18\x01 \x01(\x0b\x32\x1c.temporal.api.common.v1.Memo"\xbf\x02\n\x1dRecordMarkerCommandAttributes\x12\x13\n\x0bmarker_name\x18\x01 \x01(\t\x12T\n\x07\x64\x65tails\x18\x02 \x03(\x0b\x32\x43.temporal.api.command.v1.RecordMarkerCommandAttributes.DetailsEntry\x12.\n\x06header\x18\x03 \x01(\x0b\x32\x1e.temporal.api.common.v1.Header\x12\x31\n\x07\x66\x61ilure\x18\x04 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x1aP\n\x0c\x44\x65tailsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12/\n\x05value\x18\x02 \x01(\x0b\x32 .temporal.api.common.v1.Payloads:\x02\x38\x01"\xac\x07\n/ContinueAsNewWorkflowExecutionCommandAttributes\x12;\n\rworkflow_type\x18\x01 \x01(\x0b\x32$.temporal.api.common.v1.WorkflowType\x12\x38\n\ntask_queue\x18\x02 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12/\n\x05input\x18\x03 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x37\n\x14workflow_run_timeout\x18\x04 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x38\n\x15workflow_task_timeout\x18\x05 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x39\n\x16\x62\x61\x63koff_start_interval\x18\x06 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x39\n\x0cretry_policy\x18\x07 \x01(\x0b\x32#.temporal.api.common.v1.RetryPolicy\x12@\n\tinitiator\x18\x08 \x01(\x0e\x32-.temporal.api.enums.v1.ContinueAsNewInitiator\x12\x31\n\x07\x66\x61ilure\x18\t \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12@\n\x16last_completion_result\x18\n \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x15\n\rcron_schedule\x18\x0b \x01(\t\x12.\n\x06header\x18\x0c \x01(\x0b\x32\x1e.temporal.api.common.v1.Header\x12*\n\x04memo\x18\r \x01(\x0b\x32\x1c.temporal.api.common.v1.Memo\x12\x43\n\x11search_attributes\x18\x0e \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes\x12\x1c\n\x10inherit_build_id\x18\x0f \x01(\x08\x42\x02\x18\x01\x12[\n\x1binitial_versioning_behavior\x18\x10 \x01(\x0e\x32\x36.temporal.api.enums.v1.ContinueAsNewVersioningBehavior"\xa1\x07\n,StartChildWorkflowExecutionCommandAttributes\x12\x15\n\tnamespace\x18\x01 \x01(\tB\x02\x18\x01\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12;\n\rworkflow_type\x18\x03 \x01(\x0b\x32$.temporal.api.common.v1.WorkflowType\x12\x38\n\ntask_queue\x18\x04 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12/\n\x05input\x18\x05 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12=\n\x1aworkflow_execution_timeout\x18\x06 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x37\n\x14workflow_run_timeout\x18\x07 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x38\n\x15workflow_task_timeout\x18\x08 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x45\n\x13parent_close_policy\x18\t \x01(\x0e\x32(.temporal.api.enums.v1.ParentClosePolicy\x12\x0f\n\x07\x63ontrol\x18\n \x01(\t\x12N\n\x18workflow_id_reuse_policy\x18\x0b \x01(\x0e\x32,.temporal.api.enums.v1.WorkflowIdReusePolicy\x12\x39\n\x0cretry_policy\x18\x0c \x01(\x0b\x32#.temporal.api.common.v1.RetryPolicy\x12\x15\n\rcron_schedule\x18\r \x01(\t\x12.\n\x06header\x18\x0e \x01(\x0b\x32\x1e.temporal.api.common.v1.Header\x12*\n\x04memo\x18\x0f \x01(\x0b\x32\x1c.temporal.api.common.v1.Memo\x12\x43\n\x11search_attributes\x18\x10 \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes\x12\x1c\n\x10inherit_build_id\x18\x11 \x01(\x08\x42\x02\x18\x01\x12\x32\n\x08priority\x18\x12 \x01(\x0b\x32 .temporal.api.common.v1.Priority"6\n ProtocolMessageCommandAttributes\x12\x12\n\nmessage_id\x18\x01 \x01(\t"\xe3\x03\n\'ScheduleNexusOperationCommandAttributes\x12\x10\n\x08\x65ndpoint\x18\x01 \x01(\t\x12\x0f\n\x07service\x18\x02 \x01(\t\x12\x11\n\toperation\x18\x03 \x01(\t\x12.\n\x05input\x18\x04 \x01(\x0b\x32\x1f.temporal.api.common.v1.Payload\x12<\n\x19schedule_to_close_timeout\x18\x05 \x01(\x0b\x32\x19.google.protobuf.Duration\x12g\n\x0cnexus_header\x18\x06 \x03(\x0b\x32Q.temporal.api.command.v1.ScheduleNexusOperationCommandAttributes.NexusHeaderEntry\x12<\n\x19schedule_to_start_timeout\x18\x07 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x39\n\x16start_to_close_timeout\x18\x08 \x01(\x0b\x32\x19.google.protobuf.Duration\x1a\x32\n\x10NexusHeaderEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01"J\n,RequestCancelNexusOperationCommandAttributes\x12\x1a\n\x12scheduled_event_id\x18\x01 \x01(\x03"\x87\x12\n\x07\x43ommand\x12\x38\n\x0c\x63ommand_type\x18\x01 \x01(\x0e\x32".temporal.api.enums.v1.CommandType\x12\x39\n\ruser_metadata\x18\xad\x02 \x01(\x0b\x32!.temporal.api.sdk.v1.UserMetadata\x12\x43\n\x13\x65vent_group_markers\x18\xae\x02 \x03(\x0b\x32%.temporal.api.sdk.v1.EventGroupMarker\x12s\n)schedule_activity_task_command_attributes\x18\x02 \x01(\x0b\x32>.temporal.api.command.v1.ScheduleActivityTaskCommandAttributesH\x00\x12^\n\x1estart_timer_command_attributes\x18\x03 \x01(\x0b\x32\x34.temporal.api.command.v1.StartTimerCommandAttributesH\x00\x12}\n.complete_workflow_execution_command_attributes\x18\x04 \x01(\x0b\x32\x43.temporal.api.command.v1.CompleteWorkflowExecutionCommandAttributesH\x00\x12u\n*fail_workflow_execution_command_attributes\x18\x05 \x01(\x0b\x32?.temporal.api.command.v1.FailWorkflowExecutionCommandAttributesH\x00\x12~\n/request_cancel_activity_task_command_attributes\x18\x06 \x01(\x0b\x32\x43.temporal.api.command.v1.RequestCancelActivityTaskCommandAttributesH\x00\x12`\n\x1f\x63\x61ncel_timer_command_attributes\x18\x07 \x01(\x0b\x32\x35.temporal.api.command.v1.CancelTimerCommandAttributesH\x00\x12y\n,cancel_workflow_execution_command_attributes\x18\x08 \x01(\x0b\x32\x41.temporal.api.command.v1.CancelWorkflowExecutionCommandAttributesH\x00\x12\x99\x01\n=request_cancel_external_workflow_execution_command_attributes\x18\t \x01(\x0b\x32P.temporal.api.command.v1.RequestCancelExternalWorkflowExecutionCommandAttributesH\x00\x12\x62\n record_marker_command_attributes\x18\n \x01(\x0b\x32\x36.temporal.api.command.v1.RecordMarkerCommandAttributesH\x00\x12\x89\x01\n5continue_as_new_workflow_execution_command_attributes\x18\x0b \x01(\x0b\x32H.temporal.api.command.v1.ContinueAsNewWorkflowExecutionCommandAttributesH\x00\x12\x82\x01\n1start_child_workflow_execution_command_attributes\x18\x0c \x01(\x0b\x32\x45.temporal.api.command.v1.StartChildWorkflowExecutionCommandAttributesH\x00\x12\x8a\x01\n5signal_external_workflow_execution_command_attributes\x18\r \x01(\x0b\x32I.temporal.api.command.v1.SignalExternalWorkflowExecutionCommandAttributesH\x00\x12\x88\x01\n4upsert_workflow_search_attributes_command_attributes\x18\x0e \x01(\x0b\x32H.temporal.api.command.v1.UpsertWorkflowSearchAttributesCommandAttributesH\x00\x12h\n#protocol_message_command_attributes\x18\x0f \x01(\x0b\x32\x39.temporal.api.command.v1.ProtocolMessageCommandAttributesH\x00\x12{\n-modify_workflow_properties_command_attributes\x18\x11 \x01(\x0b\x32\x42.temporal.api.command.v1.ModifyWorkflowPropertiesCommandAttributesH\x00\x12w\n+schedule_nexus_operation_command_attributes\x18\x12 \x01(\x0b\x32@.temporal.api.command.v1.ScheduleNexusOperationCommandAttributesH\x00\x12\x82\x01\n1request_cancel_nexus_operation_command_attributes\x18\x13 \x01(\x0b\x32\x45.temporal.api.command.v1.RequestCancelNexusOperationCommandAttributesH\x00\x42\x0c\n\nattributesB\x8e\x01\n\x1aio.temporal.api.command.v1B\x0cMessageProtoP\x01Z%go.temporal.io/api/command/v1;command\xaa\x02\x19Temporalio.Api.Command.V1\xea\x02\x1cTemporalio::Api::Command::V1b\x06proto3' + b'\n%temporal/api/command/v1/message.proto\x12\x17temporal.api.command.v1\x1a\x1egoogle/protobuf/duration.proto\x1a$temporal/api/enums/v1/workflow.proto\x1a(temporal/api/enums/v1/command_type.proto\x1a$temporal/api/common/v1/message.proto\x1a%temporal/api/failure/v1/message.proto\x1a\'temporal/api/taskqueue/v1/message.proto\x1a&temporal/api/workflow/v1/message.proto\x1a\'temporal/api/sdk/v1/user_metadata.proto\x1a,temporal/api/sdk/v1/event_group_marker.proto"\xb6\x05\n%ScheduleActivityTaskCommandAttributes\x12\x13\n\x0b\x61\x63tivity_id\x18\x01 \x01(\t\x12;\n\ractivity_type\x18\x02 \x01(\x0b\x32$.temporal.api.common.v1.ActivityType\x12\x38\n\ntask_queue\x18\x04 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12.\n\x06header\x18\x05 \x01(\x0b\x32\x1e.temporal.api.common.v1.Header\x12/\n\x05input\x18\x06 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12<\n\x19schedule_to_close_timeout\x18\x07 \x01(\x0b\x32\x19.google.protobuf.Duration\x12<\n\x19schedule_to_start_timeout\x18\x08 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x39\n\x16start_to_close_timeout\x18\t \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x34\n\x11heartbeat_timeout\x18\n \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x39\n\x0cretry_policy\x18\x0b \x01(\x0b\x32#.temporal.api.common.v1.RetryPolicy\x12\x1f\n\x17request_eager_execution\x18\x0c \x01(\x08\x12\x1d\n\x15use_workflow_build_id\x18\r \x01(\x08\x12\x32\n\x08priority\x18\x0e \x01(\x0b\x32 .temporal.api.common.v1.PriorityJ\x04\x08\x03\x10\x04"H\n*RequestCancelActivityTaskCommandAttributes\x12\x1a\n\x12scheduled_event_id\x18\x01 \x01(\x03"i\n\x1bStartTimerCommandAttributes\x12\x10\n\x08timer_id\x18\x01 \x01(\t\x12\x38\n\x15start_to_fire_timeout\x18\x02 \x01(\x0b\x32\x19.google.protobuf.Duration"^\n*CompleteWorkflowExecutionCommandAttributes\x12\x30\n\x06result\x18\x01 \x01(\x0b\x32 .temporal.api.common.v1.Payloads"[\n&FailWorkflowExecutionCommandAttributes\x12\x31\n\x07\x66\x61ilure\x18\x01 \x01(\x0b\x32 .temporal.api.failure.v1.Failure"0\n\x1c\x43\x61ncelTimerCommandAttributes\x12\x10\n\x08timer_id\x18\x01 \x01(\t"]\n(CancelWorkflowExecutionCommandAttributes\x12\x31\n\x07\x64\x65tails\x18\x01 \x01(\x0b\x32 .temporal.api.common.v1.Payloads"\xb7\x01\n7RequestCancelExternalWorkflowExecutionCommandAttributes\x12\x15\n\tnamespace\x18\x01 \x01(\tB\x02\x18\x01\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x12\x13\n\x07\x63ontrol\x18\x04 \x01(\tB\x02\x18\x01\x12\x1b\n\x13\x63hild_workflow_only\x18\x05 \x01(\x08\x12\x0e\n\x06reason\x18\x06 \x01(\t"\xaf\x02\n0SignalExternalWorkflowExecutionCommandAttributes\x12\x15\n\tnamespace\x18\x01 \x01(\tB\x02\x18\x01\x12<\n\texecution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x13\n\x0bsignal_name\x18\x03 \x01(\t\x12/\n\x05input\x18\x04 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x13\n\x07\x63ontrol\x18\x05 \x01(\tB\x02\x18\x01\x12\x1b\n\x13\x63hild_workflow_only\x18\x06 \x01(\x08\x12.\n\x06header\x18\x07 \x01(\x0b\x32\x1e.temporal.api.common.v1.Header"v\n/UpsertWorkflowSearchAttributesCommandAttributes\x12\x43\n\x11search_attributes\x18\x01 \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes"`\n)ModifyWorkflowPropertiesCommandAttributes\x12\x33\n\rupserted_memo\x18\x01 \x01(\x0b\x32\x1c.temporal.api.common.v1.Memo"\xbf\x02\n\x1dRecordMarkerCommandAttributes\x12\x13\n\x0bmarker_name\x18\x01 \x01(\t\x12T\n\x07\x64\x65tails\x18\x02 \x03(\x0b\x32\x43.temporal.api.command.v1.RecordMarkerCommandAttributes.DetailsEntry\x12.\n\x06header\x18\x03 \x01(\x0b\x32\x1e.temporal.api.common.v1.Header\x12\x31\n\x07\x66\x61ilure\x18\x04 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x1aP\n\x0c\x44\x65tailsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12/\n\x05value\x18\x02 \x01(\x0b\x32 .temporal.api.common.v1.Payloads:\x02\x38\x01"\xac\x07\n/ContinueAsNewWorkflowExecutionCommandAttributes\x12;\n\rworkflow_type\x18\x01 \x01(\x0b\x32$.temporal.api.common.v1.WorkflowType\x12\x38\n\ntask_queue\x18\x02 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12/\n\x05input\x18\x03 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x37\n\x14workflow_run_timeout\x18\x04 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x38\n\x15workflow_task_timeout\x18\x05 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x39\n\x16\x62\x61\x63koff_start_interval\x18\x06 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x39\n\x0cretry_policy\x18\x07 \x01(\x0b\x32#.temporal.api.common.v1.RetryPolicy\x12@\n\tinitiator\x18\x08 \x01(\x0e\x32-.temporal.api.enums.v1.ContinueAsNewInitiator\x12\x31\n\x07\x66\x61ilure\x18\t \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12@\n\x16last_completion_result\x18\n \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x15\n\rcron_schedule\x18\x0b \x01(\t\x12.\n\x06header\x18\x0c \x01(\x0b\x32\x1e.temporal.api.common.v1.Header\x12*\n\x04memo\x18\r \x01(\x0b\x32\x1c.temporal.api.common.v1.Memo\x12\x43\n\x11search_attributes\x18\x0e \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes\x12\x1c\n\x10inherit_build_id\x18\x0f \x01(\x08\x42\x02\x18\x01\x12[\n\x1binitial_versioning_behavior\x18\x10 \x01(\x0e\x32\x36.temporal.api.enums.v1.ContinueAsNewVersioningBehavior"\xec\x07\n,StartChildWorkflowExecutionCommandAttributes\x12\x15\n\tnamespace\x18\x01 \x01(\tB\x02\x18\x01\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12;\n\rworkflow_type\x18\x03 \x01(\x0b\x32$.temporal.api.common.v1.WorkflowType\x12\x38\n\ntask_queue\x18\x04 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12/\n\x05input\x18\x05 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12=\n\x1aworkflow_execution_timeout\x18\x06 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x37\n\x14workflow_run_timeout\x18\x07 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x38\n\x15workflow_task_timeout\x18\x08 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x45\n\x13parent_close_policy\x18\t \x01(\x0e\x32(.temporal.api.enums.v1.ParentClosePolicy\x12\x0f\n\x07\x63ontrol\x18\n \x01(\t\x12N\n\x18workflow_id_reuse_policy\x18\x0b \x01(\x0e\x32,.temporal.api.enums.v1.WorkflowIdReusePolicy\x12\x39\n\x0cretry_policy\x18\x0c \x01(\x0b\x32#.temporal.api.common.v1.RetryPolicy\x12\x15\n\rcron_schedule\x18\r \x01(\t\x12.\n\x06header\x18\x0e \x01(\x0b\x32\x1e.temporal.api.common.v1.Header\x12*\n\x04memo\x18\x0f \x01(\x0b\x32\x1c.temporal.api.common.v1.Memo\x12\x43\n\x11search_attributes\x18\x10 \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes\x12\x1c\n\x10inherit_build_id\x18\x11 \x01(\x08\x42\x02\x18\x01\x12\x32\n\x08priority\x18\x12 \x01(\x0b\x32 .temporal.api.common.v1.Priority\x12I\n\x13versioning_override\x18\x13 \x01(\x0b\x32,.temporal.api.workflow.v1.VersioningOverride"6\n ProtocolMessageCommandAttributes\x12\x12\n\nmessage_id\x18\x01 \x01(\t"\xe3\x03\n\'ScheduleNexusOperationCommandAttributes\x12\x10\n\x08\x65ndpoint\x18\x01 \x01(\t\x12\x0f\n\x07service\x18\x02 \x01(\t\x12\x11\n\toperation\x18\x03 \x01(\t\x12.\n\x05input\x18\x04 \x01(\x0b\x32\x1f.temporal.api.common.v1.Payload\x12<\n\x19schedule_to_close_timeout\x18\x05 \x01(\x0b\x32\x19.google.protobuf.Duration\x12g\n\x0cnexus_header\x18\x06 \x03(\x0b\x32Q.temporal.api.command.v1.ScheduleNexusOperationCommandAttributes.NexusHeaderEntry\x12<\n\x19schedule_to_start_timeout\x18\x07 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x39\n\x16start_to_close_timeout\x18\x08 \x01(\x0b\x32\x19.google.protobuf.Duration\x1a\x32\n\x10NexusHeaderEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01"J\n,RequestCancelNexusOperationCommandAttributes\x12\x1a\n\x12scheduled_event_id\x18\x01 \x01(\x03"\x87\x12\n\x07\x43ommand\x12\x38\n\x0c\x63ommand_type\x18\x01 \x01(\x0e\x32".temporal.api.enums.v1.CommandType\x12\x39\n\ruser_metadata\x18\xad\x02 \x01(\x0b\x32!.temporal.api.sdk.v1.UserMetadata\x12\x43\n\x13\x65vent_group_markers\x18\xae\x02 \x03(\x0b\x32%.temporal.api.sdk.v1.EventGroupMarker\x12s\n)schedule_activity_task_command_attributes\x18\x02 \x01(\x0b\x32>.temporal.api.command.v1.ScheduleActivityTaskCommandAttributesH\x00\x12^\n\x1estart_timer_command_attributes\x18\x03 \x01(\x0b\x32\x34.temporal.api.command.v1.StartTimerCommandAttributesH\x00\x12}\n.complete_workflow_execution_command_attributes\x18\x04 \x01(\x0b\x32\x43.temporal.api.command.v1.CompleteWorkflowExecutionCommandAttributesH\x00\x12u\n*fail_workflow_execution_command_attributes\x18\x05 \x01(\x0b\x32?.temporal.api.command.v1.FailWorkflowExecutionCommandAttributesH\x00\x12~\n/request_cancel_activity_task_command_attributes\x18\x06 \x01(\x0b\x32\x43.temporal.api.command.v1.RequestCancelActivityTaskCommandAttributesH\x00\x12`\n\x1f\x63\x61ncel_timer_command_attributes\x18\x07 \x01(\x0b\x32\x35.temporal.api.command.v1.CancelTimerCommandAttributesH\x00\x12y\n,cancel_workflow_execution_command_attributes\x18\x08 \x01(\x0b\x32\x41.temporal.api.command.v1.CancelWorkflowExecutionCommandAttributesH\x00\x12\x99\x01\n=request_cancel_external_workflow_execution_command_attributes\x18\t \x01(\x0b\x32P.temporal.api.command.v1.RequestCancelExternalWorkflowExecutionCommandAttributesH\x00\x12\x62\n record_marker_command_attributes\x18\n \x01(\x0b\x32\x36.temporal.api.command.v1.RecordMarkerCommandAttributesH\x00\x12\x89\x01\n5continue_as_new_workflow_execution_command_attributes\x18\x0b \x01(\x0b\x32H.temporal.api.command.v1.ContinueAsNewWorkflowExecutionCommandAttributesH\x00\x12\x82\x01\n1start_child_workflow_execution_command_attributes\x18\x0c \x01(\x0b\x32\x45.temporal.api.command.v1.StartChildWorkflowExecutionCommandAttributesH\x00\x12\x8a\x01\n5signal_external_workflow_execution_command_attributes\x18\r \x01(\x0b\x32I.temporal.api.command.v1.SignalExternalWorkflowExecutionCommandAttributesH\x00\x12\x88\x01\n4upsert_workflow_search_attributes_command_attributes\x18\x0e \x01(\x0b\x32H.temporal.api.command.v1.UpsertWorkflowSearchAttributesCommandAttributesH\x00\x12h\n#protocol_message_command_attributes\x18\x0f \x01(\x0b\x32\x39.temporal.api.command.v1.ProtocolMessageCommandAttributesH\x00\x12{\n-modify_workflow_properties_command_attributes\x18\x11 \x01(\x0b\x32\x42.temporal.api.command.v1.ModifyWorkflowPropertiesCommandAttributesH\x00\x12w\n+schedule_nexus_operation_command_attributes\x18\x12 \x01(\x0b\x32@.temporal.api.command.v1.ScheduleNexusOperationCommandAttributesH\x00\x12\x82\x01\n1request_cancel_nexus_operation_command_attributes\x18\x13 \x01(\x0b\x32\x45.temporal.api.command.v1.RequestCancelNexusOperationCommandAttributesH\x00\x42\x0c\n\nattributesB\x8e\x01\n\x1aio.temporal.api.command.v1B\x0cMessageProtoP\x01Z%go.temporal.io/api/command/v1;command\xaa\x02\x19Temporalio.Api.Command.V1\xea\x02\x1cTemporalio::Api::Command::V1b\x06proto3' ) @@ -380,44 +383,44 @@ _SCHEDULENEXUSOPERATIONCOMMANDATTRIBUTES_NEXUSHEADERENTRY._serialized_options = ( b"8\001" ) - _SCHEDULEACTIVITYTASKCOMMANDATTRIBUTES._serialized_start = 384 - _SCHEDULEACTIVITYTASKCOMMANDATTRIBUTES._serialized_end = 1078 - _REQUESTCANCELACTIVITYTASKCOMMANDATTRIBUTES._serialized_start = 1080 - _REQUESTCANCELACTIVITYTASKCOMMANDATTRIBUTES._serialized_end = 1152 - _STARTTIMERCOMMANDATTRIBUTES._serialized_start = 1154 - _STARTTIMERCOMMANDATTRIBUTES._serialized_end = 1259 - _COMPLETEWORKFLOWEXECUTIONCOMMANDATTRIBUTES._serialized_start = 1261 - _COMPLETEWORKFLOWEXECUTIONCOMMANDATTRIBUTES._serialized_end = 1355 - _FAILWORKFLOWEXECUTIONCOMMANDATTRIBUTES._serialized_start = 1357 - _FAILWORKFLOWEXECUTIONCOMMANDATTRIBUTES._serialized_end = 1448 - _CANCELTIMERCOMMANDATTRIBUTES._serialized_start = 1450 - _CANCELTIMERCOMMANDATTRIBUTES._serialized_end = 1498 - _CANCELWORKFLOWEXECUTIONCOMMANDATTRIBUTES._serialized_start = 1500 - _CANCELWORKFLOWEXECUTIONCOMMANDATTRIBUTES._serialized_end = 1593 - _REQUESTCANCELEXTERNALWORKFLOWEXECUTIONCOMMANDATTRIBUTES._serialized_start = 1596 - _REQUESTCANCELEXTERNALWORKFLOWEXECUTIONCOMMANDATTRIBUTES._serialized_end = 1779 - _SIGNALEXTERNALWORKFLOWEXECUTIONCOMMANDATTRIBUTES._serialized_start = 1782 - _SIGNALEXTERNALWORKFLOWEXECUTIONCOMMANDATTRIBUTES._serialized_end = 2085 - _UPSERTWORKFLOWSEARCHATTRIBUTESCOMMANDATTRIBUTES._serialized_start = 2087 - _UPSERTWORKFLOWSEARCHATTRIBUTESCOMMANDATTRIBUTES._serialized_end = 2205 - _MODIFYWORKFLOWPROPERTIESCOMMANDATTRIBUTES._serialized_start = 2207 - _MODIFYWORKFLOWPROPERTIESCOMMANDATTRIBUTES._serialized_end = 2303 - _RECORDMARKERCOMMANDATTRIBUTES._serialized_start = 2306 - _RECORDMARKERCOMMANDATTRIBUTES._serialized_end = 2625 - _RECORDMARKERCOMMANDATTRIBUTES_DETAILSENTRY._serialized_start = 2545 - _RECORDMARKERCOMMANDATTRIBUTES_DETAILSENTRY._serialized_end = 2625 - _CONTINUEASNEWWORKFLOWEXECUTIONCOMMANDATTRIBUTES._serialized_start = 2628 - _CONTINUEASNEWWORKFLOWEXECUTIONCOMMANDATTRIBUTES._serialized_end = 3568 - _STARTCHILDWORKFLOWEXECUTIONCOMMANDATTRIBUTES._serialized_start = 3571 - _STARTCHILDWORKFLOWEXECUTIONCOMMANDATTRIBUTES._serialized_end = 4500 - _PROTOCOLMESSAGECOMMANDATTRIBUTES._serialized_start = 4502 - _PROTOCOLMESSAGECOMMANDATTRIBUTES._serialized_end = 4556 - _SCHEDULENEXUSOPERATIONCOMMANDATTRIBUTES._serialized_start = 4559 - _SCHEDULENEXUSOPERATIONCOMMANDATTRIBUTES._serialized_end = 5042 - _SCHEDULENEXUSOPERATIONCOMMANDATTRIBUTES_NEXUSHEADERENTRY._serialized_start = 4992 - _SCHEDULENEXUSOPERATIONCOMMANDATTRIBUTES_NEXUSHEADERENTRY._serialized_end = 5042 - _REQUESTCANCELNEXUSOPERATIONCOMMANDATTRIBUTES._serialized_start = 5044 - _REQUESTCANCELNEXUSOPERATIONCOMMANDATTRIBUTES._serialized_end = 5118 - _COMMAND._serialized_start = 5121 - _COMMAND._serialized_end = 7432 + _SCHEDULEACTIVITYTASKCOMMANDATTRIBUTES._serialized_start = 424 + _SCHEDULEACTIVITYTASKCOMMANDATTRIBUTES._serialized_end = 1118 + _REQUESTCANCELACTIVITYTASKCOMMANDATTRIBUTES._serialized_start = 1120 + _REQUESTCANCELACTIVITYTASKCOMMANDATTRIBUTES._serialized_end = 1192 + _STARTTIMERCOMMANDATTRIBUTES._serialized_start = 1194 + _STARTTIMERCOMMANDATTRIBUTES._serialized_end = 1299 + _COMPLETEWORKFLOWEXECUTIONCOMMANDATTRIBUTES._serialized_start = 1301 + _COMPLETEWORKFLOWEXECUTIONCOMMANDATTRIBUTES._serialized_end = 1395 + _FAILWORKFLOWEXECUTIONCOMMANDATTRIBUTES._serialized_start = 1397 + _FAILWORKFLOWEXECUTIONCOMMANDATTRIBUTES._serialized_end = 1488 + _CANCELTIMERCOMMANDATTRIBUTES._serialized_start = 1490 + _CANCELTIMERCOMMANDATTRIBUTES._serialized_end = 1538 + _CANCELWORKFLOWEXECUTIONCOMMANDATTRIBUTES._serialized_start = 1540 + _CANCELWORKFLOWEXECUTIONCOMMANDATTRIBUTES._serialized_end = 1633 + _REQUESTCANCELEXTERNALWORKFLOWEXECUTIONCOMMANDATTRIBUTES._serialized_start = 1636 + _REQUESTCANCELEXTERNALWORKFLOWEXECUTIONCOMMANDATTRIBUTES._serialized_end = 1819 + _SIGNALEXTERNALWORKFLOWEXECUTIONCOMMANDATTRIBUTES._serialized_start = 1822 + _SIGNALEXTERNALWORKFLOWEXECUTIONCOMMANDATTRIBUTES._serialized_end = 2125 + _UPSERTWORKFLOWSEARCHATTRIBUTESCOMMANDATTRIBUTES._serialized_start = 2127 + _UPSERTWORKFLOWSEARCHATTRIBUTESCOMMANDATTRIBUTES._serialized_end = 2245 + _MODIFYWORKFLOWPROPERTIESCOMMANDATTRIBUTES._serialized_start = 2247 + _MODIFYWORKFLOWPROPERTIESCOMMANDATTRIBUTES._serialized_end = 2343 + _RECORDMARKERCOMMANDATTRIBUTES._serialized_start = 2346 + _RECORDMARKERCOMMANDATTRIBUTES._serialized_end = 2665 + _RECORDMARKERCOMMANDATTRIBUTES_DETAILSENTRY._serialized_start = 2585 + _RECORDMARKERCOMMANDATTRIBUTES_DETAILSENTRY._serialized_end = 2665 + _CONTINUEASNEWWORKFLOWEXECUTIONCOMMANDATTRIBUTES._serialized_start = 2668 + _CONTINUEASNEWWORKFLOWEXECUTIONCOMMANDATTRIBUTES._serialized_end = 3608 + _STARTCHILDWORKFLOWEXECUTIONCOMMANDATTRIBUTES._serialized_start = 3611 + _STARTCHILDWORKFLOWEXECUTIONCOMMANDATTRIBUTES._serialized_end = 4615 + _PROTOCOLMESSAGECOMMANDATTRIBUTES._serialized_start = 4617 + _PROTOCOLMESSAGECOMMANDATTRIBUTES._serialized_end = 4671 + _SCHEDULENEXUSOPERATIONCOMMANDATTRIBUTES._serialized_start = 4674 + _SCHEDULENEXUSOPERATIONCOMMANDATTRIBUTES._serialized_end = 5157 + _SCHEDULENEXUSOPERATIONCOMMANDATTRIBUTES_NEXUSHEADERENTRY._serialized_start = 5107 + _SCHEDULENEXUSOPERATIONCOMMANDATTRIBUTES_NEXUSHEADERENTRY._serialized_end = 5157 + _REQUESTCANCELNEXUSOPERATIONCOMMANDATTRIBUTES._serialized_start = 5159 + _REQUESTCANCELNEXUSOPERATIONCOMMANDATTRIBUTES._serialized_end = 5233 + _COMMAND._serialized_start = 5236 + _COMMAND._serialized_end = 7547 # @@protoc_insertion_point(module_scope) diff --git a/temporalio/api/command/v1/message_pb2.pyi b/temporalio/api/command/v1/message_pb2.pyi index bf0cbf023..18d0abc8b 100644 --- a/temporalio/api/command/v1/message_pb2.pyi +++ b/temporalio/api/command/v1/message_pb2.pyi @@ -19,6 +19,7 @@ import temporalio.api.failure.v1.message_pb2 import temporalio.api.sdk.v1.event_group_marker_pb2 import temporalio.api.sdk.v1.user_metadata_pb2 import temporalio.api.taskqueue.v1.message_pb2 +import temporalio.api.workflow.v1.message_pb2 if sys.version_info >= (3, 8): import typing as typing_extensions @@ -759,6 +760,7 @@ class StartChildWorkflowExecutionCommandAttributes(google.protobuf.message.Messa SEARCH_ATTRIBUTES_FIELD_NUMBER: builtins.int INHERIT_BUILD_ID_FIELD_NUMBER: builtins.int PRIORITY_FIELD_NUMBER: builtins.int + VERSIONING_OVERRIDE_FIELD_NUMBER: builtins.int namespace: builtins.str """Deprecated. Cross-namespace operations are disabled by default as of server 1.30.1.""" workflow_id: builtins.str @@ -808,6 +810,13 @@ class StartChildWorkflowExecutionCommandAttributes(google.protobuf.message.Messa """Priority metadata. If this message is not present, or any fields are not present, they inherit the values from the workflow. """ + @property + def versioning_override( + self, + ) -> temporalio.api.workflow.v1.message_pb2.VersioningOverride: + """Versioning override for the child workflow. If present, this explicit override takes + precedence over versioning behavior inherited from the parent workflow. + """ def __init__( self, *, @@ -830,6 +839,8 @@ class StartChildWorkflowExecutionCommandAttributes(google.protobuf.message.Messa | None = ..., inherit_build_id: builtins.bool = ..., priority: temporalio.api.common.v1.message_pb2.Priority | None = ..., + versioning_override: temporalio.api.workflow.v1.message_pb2.VersioningOverride + | None = ..., ) -> None: ... def HasField( self, @@ -848,6 +859,8 @@ class StartChildWorkflowExecutionCommandAttributes(google.protobuf.message.Messa b"search_attributes", "task_queue", b"task_queue", + "versioning_override", + b"versioning_override", "workflow_execution_timeout", b"workflow_execution_timeout", "workflow_run_timeout", @@ -885,6 +898,8 @@ class StartChildWorkflowExecutionCommandAttributes(google.protobuf.message.Messa b"search_attributes", "task_queue", b"task_queue", + "versioning_override", + b"versioning_override", "workflow_execution_timeout", b"workflow_execution_timeout", "workflow_id", diff --git a/temporalio/api/common/v1/__init__.py b/temporalio/api/common/v1/__init__.py index 4136d3b93..8764b274a 100644 --- a/temporalio/api/common/v1/__init__.py +++ b/temporalio/api/common/v1/__init__.py @@ -3,6 +3,7 @@ ActivityType, Callback, DataBlob, + Execution, Header, Link, Memo, @@ -28,6 +29,7 @@ "ActivityType", "Callback", "DataBlob", + "Execution", "GrpcStatus", "Header", "Link", diff --git a/temporalio/api/common/v1/message_pb2.py b/temporalio/api/common/v1/message_pb2.py index 401e3721a..ce5acffc7 100644 --- a/temporalio/api/common/v1/message_pb2.py +++ b/temporalio/api/common/v1/message_pb2.py @@ -29,7 +29,7 @@ ) DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile( - b'\n$temporal/api/common/v1/message.proto\x12\x16temporal.api.common.v1\x1a\x1egoogle/protobuf/duration.proto\x1a\x1bgoogle/protobuf/empty.proto\x1a\x1fgoogle/protobuf/timestamp.proto\x1a"temporal/api/enums/v1/common.proto\x1a&temporal/api/enums/v1/event_type.proto\x1a!temporal/api/enums/v1/reset.proto"T\n\x08\x44\x61taBlob\x12:\n\rencoding_type\x18\x01 \x01(\x0e\x32#.temporal.api.enums.v1.EncodingType\x12\x0c\n\x04\x64\x61ta\x18\x02 \x01(\x0c"=\n\x08Payloads\x12\x31\n\x08payloads\x18\x01 \x03(\x0b\x32\x1f.temporal.api.common.v1.Payload"\x8a\x02\n\x07Payload\x12?\n\x08metadata\x18\x01 \x03(\x0b\x32-.temporal.api.common.v1.Payload.MetadataEntry\x12\x0c\n\x04\x64\x61ta\x18\x02 \x01(\x0c\x12Q\n\x11\x65xternal_payloads\x18\x03 \x03(\x0b\x32\x36.temporal.api.common.v1.Payload.ExternalPayloadDetails\x1a/\n\rMetadataEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\x0c:\x02\x38\x01\x1a,\n\x16\x45xternalPayloadDetails\x12\x12\n\nsize_bytes\x18\x01 \x01(\x03"\xbe\x01\n\x10SearchAttributes\x12S\n\x0eindexed_fields\x18\x01 \x03(\x0b\x32;.temporal.api.common.v1.SearchAttributes.IndexedFieldsEntry\x1aU\n\x12IndexedFieldsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12.\n\x05value\x18\x02 \x01(\x0b\x32\x1f.temporal.api.common.v1.Payload:\x02\x38\x01"\x90\x01\n\x04Memo\x12\x38\n\x06\x66ields\x18\x01 \x03(\x0b\x32(.temporal.api.common.v1.Memo.FieldsEntry\x1aN\n\x0b\x46ieldsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12.\n\x05value\x18\x02 \x01(\x0b\x32\x1f.temporal.api.common.v1.Payload:\x02\x38\x01"\x94\x01\n\x06Header\x12:\n\x06\x66ields\x18\x01 \x03(\x0b\x32*.temporal.api.common.v1.Header.FieldsEntry\x1aN\n\x0b\x46ieldsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12.\n\x05value\x18\x02 \x01(\x0b\x32\x1f.temporal.api.common.v1.Payload:\x02\x38\x01"8\n\x11WorkflowExecution\x12\x13\n\x0bworkflow_id\x18\x01 \x01(\t\x12\x0e\n\x06run_id\x18\x02 \x01(\t"\x1c\n\x0cWorkflowType\x12\x0c\n\x04name\x18\x01 \x01(\t"\x1c\n\x0c\x41\x63tivityType\x12\x0c\n\x04name\x18\x01 \x01(\t"\xd1\x01\n\x0bRetryPolicy\x12\x33\n\x10initial_interval\x18\x01 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x1b\n\x13\x62\x61\x63koff_coefficient\x18\x02 \x01(\x01\x12\x33\n\x10maximum_interval\x18\x03 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x18\n\x10maximum_attempts\x18\x04 \x01(\x05\x12!\n\x19non_retryable_error_types\x18\x05 \x03(\t"F\n\x10MeteringMetadata\x12\x32\n*nonfirst_local_activity_execution_attempts\x18\r \x01(\r">\n\x12WorkerVersionStamp\x12\x10\n\x08\x62uild_id\x18\x01 \x01(\t\x12\x16\n\x0euse_versioning\x18\x03 \x01(\x08"e\n\x19WorkerVersionCapabilities\x12\x10\n\x08\x62uild_id\x18\x01 \x01(\t\x12\x16\n\x0euse_versioning\x18\x02 \x01(\x08\x12\x1e\n\x16\x64\x65ployment_series_name\x18\x04 \x01(\t"\xed\x02\n\x0cResetOptions\x12\x35\n\x13\x66irst_workflow_task\x18\x01 \x01(\x0b\x32\x16.google.protobuf.EmptyH\x00\x12\x34\n\x12last_workflow_task\x18\x02 \x01(\x0b\x32\x16.google.protobuf.EmptyH\x00\x12\x1a\n\x10workflow_task_id\x18\x03 \x01(\x03H\x00\x12\x12\n\x08\x62uild_id\x18\x04 \x01(\tH\x00\x12G\n\x12reset_reapply_type\x18\n \x01(\x0e\x32\'.temporal.api.enums.v1.ResetReapplyTypeB\x02\x18\x01\x12\x18\n\x10\x63urrent_run_only\x18\x0b \x01(\x08\x12S\n\x1breset_reapply_exclude_types\x18\x0c \x03(\x0e\x32..temporal.api.enums.v1.ResetReapplyExcludeTypeB\x08\n\x06target"\xe4\x02\n\x08\x43\x61llback\x12\x37\n\x05nexus\x18\x02 \x01(\x0b\x32&.temporal.api.common.v1.Callback.NexusH\x00\x12=\n\x08internal\x18\x03 \x01(\x0b\x32).temporal.api.common.v1.Callback.InternalH\x00\x12+\n\x05links\x18\x64 \x03(\x0b\x32\x1c.temporal.api.common.v1.Link\x1a\x87\x01\n\x05Nexus\x12\x0b\n\x03url\x18\x01 \x01(\t\x12\x42\n\x06header\x18\x02 \x03(\x0b\x32\x32.temporal.api.common.v1.Callback.Nexus.HeaderEntry\x1a-\n\x0bHeaderEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x1a\x18\n\x08Internal\x12\x0c\n\x04\x64\x61ta\x18\x01 \x01(\x0c\x42\t\n\x07variantJ\x04\x08\x01\x10\x02"\x8a\x08\n\x04Link\x12\x44\n\x0eworkflow_event\x18\x01 \x01(\x0b\x32*.temporal.api.common.v1.Link.WorkflowEventH\x00\x12:\n\tbatch_job\x18\x02 \x01(\x0b\x32%.temporal.api.common.v1.Link.BatchJobH\x00\x12\x39\n\x08\x61\x63tivity\x18\x03 \x01(\x0b\x32%.temporal.api.common.v1.Link.ActivityH\x00\x12\x46\n\x0fnexus_operation\x18\x04 \x01(\x0b\x32+.temporal.api.common.v1.Link.NexusOperationH\x00\x12\x39\n\x08workflow\x18\x05 \x01(\x0b\x32%.temporal.api.common.v1.Link.WorkflowH\x00\x1a\xb7\x03\n\rWorkflowEvent\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x12N\n\tevent_ref\x18\x64 \x01(\x0b\x32\x39.temporal.api.common.v1.Link.WorkflowEvent.EventReferenceH\x00\x12W\n\x0erequest_id_ref\x18\x65 \x01(\x0b\x32=.temporal.api.common.v1.Link.WorkflowEvent.RequestIdReferenceH\x00\x1aX\n\x0e\x45ventReference\x12\x10\n\x08\x65vent_id\x18\x01 \x01(\x03\x12\x34\n\nevent_type\x18\x02 \x01(\x0e\x32 .temporal.api.enums.v1.EventType\x1a^\n\x12RequestIdReference\x12\x12\n\nrequest_id\x18\x01 \x01(\t\x12\x34\n\nevent_type\x18\x02 \x01(\x0e\x32 .temporal.api.enums.v1.EventTypeB\x0b\n\treference\x1a\x1a\n\x08\x42\x61tchJob\x12\x0e\n\x06job_id\x18\x01 \x01(\t\x1a\x42\n\x08\x41\x63tivity\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0b\x61\x63tivity_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x1aI\n\x0eNexusOperation\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x14\n\x0coperation_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x1aR\n\x08Workflow\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x12\x0e\n\x06reason\x18\x04 \x01(\tB\t\n\x07variant"\'\n\tPrincipal\x12\x0c\n\x04type\x18\x01 \x01(\t\x12\x0c\n\x04name\x18\x02 \x01(\t"O\n\x08Priority\x12\x14\n\x0cpriority_key\x18\x01 \x01(\x05\x12\x14\n\x0c\x66\x61irness_key\x18\x02 \x01(\t\x12\x17\n\x0f\x66\x61irness_weight\x18\x03 \x01(\x02";\n\x0eWorkerSelector\x12\x1d\n\x13worker_instance_key\x18\x01 \x01(\tH\x00\x42\n\n\x08selector"i\n\x11OnConflictOptions\x12\x19\n\x11\x61ttach_request_id\x18\x01 \x01(\x08\x12#\n\x1b\x61ttach_completion_callbacks\x18\x02 \x01(\x08\x12\x14\n\x0c\x61ttach_links\x18\x03 \x01(\x08"y\n\x12TimeSkippingConfig\x12\x0f\n\x07\x65nabled\x18\x01 \x01(\x08\x12/\n\x0c\x66\x61st_forward\x18\x02 \x01(\x0b\x32\x19.google.protobuf.Duration\x12!\n\x19\x64isable_child_propagation\x18\x03 \x01(\x08"\x99\x01\n\x1cTimeSkippingStatePropagation\x12;\n\x18initial_skipped_duration\x18\x01 \x01(\x0b\x32\x19.google.protobuf.Duration\x12<\n\x18\x66\x61st_forward_target_time\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.TimestampB\x89\x01\n\x19io.temporal.api.common.v1B\x0cMessageProtoP\x01Z#go.temporal.io/api/common/v1;common\xaa\x02\x18Temporalio.Api.Common.V1\xea\x02\x1bTemporalio::Api::Common::V1b\x06proto3' + b'\n$temporal/api/common/v1/message.proto\x12\x16temporal.api.common.v1\x1a\x1egoogle/protobuf/duration.proto\x1a\x1bgoogle/protobuf/empty.proto\x1a\x1fgoogle/protobuf/timestamp.proto\x1a"temporal/api/enums/v1/common.proto\x1a&temporal/api/enums/v1/event_type.proto\x1a!temporal/api/enums/v1/reset.proto"T\n\x08\x44\x61taBlob\x12:\n\rencoding_type\x18\x01 \x01(\x0e\x32#.temporal.api.enums.v1.EncodingType\x12\x0c\n\x04\x64\x61ta\x18\x02 \x01(\x0c"=\n\x08Payloads\x12\x31\n\x08payloads\x18\x01 \x03(\x0b\x32\x1f.temporal.api.common.v1.Payload"\x8a\x02\n\x07Payload\x12?\n\x08metadata\x18\x01 \x03(\x0b\x32-.temporal.api.common.v1.Payload.MetadataEntry\x12\x0c\n\x04\x64\x61ta\x18\x02 \x01(\x0c\x12Q\n\x11\x65xternal_payloads\x18\x03 \x03(\x0b\x32\x36.temporal.api.common.v1.Payload.ExternalPayloadDetails\x1a/\n\rMetadataEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\x0c:\x02\x38\x01\x1a,\n\x16\x45xternalPayloadDetails\x12\x12\n\nsize_bytes\x18\x01 \x01(\x03"\xbe\x01\n\x10SearchAttributes\x12S\n\x0eindexed_fields\x18\x01 \x03(\x0b\x32;.temporal.api.common.v1.SearchAttributes.IndexedFieldsEntry\x1aU\n\x12IndexedFieldsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12.\n\x05value\x18\x02 \x01(\x0b\x32\x1f.temporal.api.common.v1.Payload:\x02\x38\x01"\x90\x01\n\x04Memo\x12\x38\n\x06\x66ields\x18\x01 \x03(\x0b\x32(.temporal.api.common.v1.Memo.FieldsEntry\x1aN\n\x0b\x46ieldsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12.\n\x05value\x18\x02 \x01(\x0b\x32\x1f.temporal.api.common.v1.Payload:\x02\x38\x01"\x94\x01\n\x06Header\x12:\n\x06\x66ields\x18\x01 \x03(\x0b\x32*.temporal.api.common.v1.Header.FieldsEntry\x1aN\n\x0b\x46ieldsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12.\n\x05value\x18\x02 \x01(\x0b\x32\x1f.temporal.api.common.v1.Payload:\x02\x38\x01"8\n\x11WorkflowExecution\x12\x13\n\x0bworkflow_id\x18\x01 \x01(\t\x12\x0e\n\x06run_id\x18\x02 \x01(\t"d\n\tExecution\x12\x32\n\x04type\x18\x01 \x01(\x0e\x32$.temporal.api.enums.v1.ExecutionType\x12\x13\n\x0b\x62usiness_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t"\x1c\n\x0cWorkflowType\x12\x0c\n\x04name\x18\x01 \x01(\t"\x1c\n\x0c\x41\x63tivityType\x12\x0c\n\x04name\x18\x01 \x01(\t"\xd1\x01\n\x0bRetryPolicy\x12\x33\n\x10initial_interval\x18\x01 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x1b\n\x13\x62\x61\x63koff_coefficient\x18\x02 \x01(\x01\x12\x33\n\x10maximum_interval\x18\x03 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x18\n\x10maximum_attempts\x18\x04 \x01(\x05\x12!\n\x19non_retryable_error_types\x18\x05 \x03(\t"F\n\x10MeteringMetadata\x12\x32\n*nonfirst_local_activity_execution_attempts\x18\r \x01(\r">\n\x12WorkerVersionStamp\x12\x10\n\x08\x62uild_id\x18\x01 \x01(\t\x12\x16\n\x0euse_versioning\x18\x03 \x01(\x08"e\n\x19WorkerVersionCapabilities\x12\x10\n\x08\x62uild_id\x18\x01 \x01(\t\x12\x16\n\x0euse_versioning\x18\x02 \x01(\x08\x12\x1e\n\x16\x64\x65ployment_series_name\x18\x04 \x01(\t"\xed\x02\n\x0cResetOptions\x12\x35\n\x13\x66irst_workflow_task\x18\x01 \x01(\x0b\x32\x16.google.protobuf.EmptyH\x00\x12\x34\n\x12last_workflow_task\x18\x02 \x01(\x0b\x32\x16.google.protobuf.EmptyH\x00\x12\x1a\n\x10workflow_task_id\x18\x03 \x01(\x03H\x00\x12\x12\n\x08\x62uild_id\x18\x04 \x01(\tH\x00\x12G\n\x12reset_reapply_type\x18\n \x01(\x0e\x32\'.temporal.api.enums.v1.ResetReapplyTypeB\x02\x18\x01\x12\x18\n\x10\x63urrent_run_only\x18\x0b \x01(\x08\x12S\n\x1breset_reapply_exclude_types\x18\x0c \x03(\x0e\x32..temporal.api.enums.v1.ResetReapplyExcludeTypeB\x08\n\x06target"\xe4\x02\n\x08\x43\x61llback\x12\x37\n\x05nexus\x18\x02 \x01(\x0b\x32&.temporal.api.common.v1.Callback.NexusH\x00\x12=\n\x08internal\x18\x03 \x01(\x0b\x32).temporal.api.common.v1.Callback.InternalH\x00\x12+\n\x05links\x18\x64 \x03(\x0b\x32\x1c.temporal.api.common.v1.Link\x1a\x87\x01\n\x05Nexus\x12\x0b\n\x03url\x18\x01 \x01(\t\x12\x42\n\x06header\x18\x02 \x03(\x0b\x32\x32.temporal.api.common.v1.Callback.Nexus.HeaderEntry\x1a-\n\x0bHeaderEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x1a\x18\n\x08Internal\x12\x0c\n\x04\x64\x61ta\x18\x01 \x01(\x0c\x42\t\n\x07variantJ\x04\x08\x01\x10\x02"\x8a\x08\n\x04Link\x12\x44\n\x0eworkflow_event\x18\x01 \x01(\x0b\x32*.temporal.api.common.v1.Link.WorkflowEventH\x00\x12:\n\tbatch_job\x18\x02 \x01(\x0b\x32%.temporal.api.common.v1.Link.BatchJobH\x00\x12\x39\n\x08\x61\x63tivity\x18\x03 \x01(\x0b\x32%.temporal.api.common.v1.Link.ActivityH\x00\x12\x46\n\x0fnexus_operation\x18\x04 \x01(\x0b\x32+.temporal.api.common.v1.Link.NexusOperationH\x00\x12\x39\n\x08workflow\x18\x05 \x01(\x0b\x32%.temporal.api.common.v1.Link.WorkflowH\x00\x1a\xb7\x03\n\rWorkflowEvent\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x12N\n\tevent_ref\x18\x64 \x01(\x0b\x32\x39.temporal.api.common.v1.Link.WorkflowEvent.EventReferenceH\x00\x12W\n\x0erequest_id_ref\x18\x65 \x01(\x0b\x32=.temporal.api.common.v1.Link.WorkflowEvent.RequestIdReferenceH\x00\x1aX\n\x0e\x45ventReference\x12\x10\n\x08\x65vent_id\x18\x01 \x01(\x03\x12\x34\n\nevent_type\x18\x02 \x01(\x0e\x32 .temporal.api.enums.v1.EventType\x1a^\n\x12RequestIdReference\x12\x12\n\nrequest_id\x18\x01 \x01(\t\x12\x34\n\nevent_type\x18\x02 \x01(\x0e\x32 .temporal.api.enums.v1.EventTypeB\x0b\n\treference\x1a\x1a\n\x08\x42\x61tchJob\x12\x0e\n\x06job_id\x18\x01 \x01(\t\x1a\x42\n\x08\x41\x63tivity\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0b\x61\x63tivity_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x1aI\n\x0eNexusOperation\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x14\n\x0coperation_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x1aR\n\x08Workflow\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x12\x0e\n\x06reason\x18\x04 \x01(\tB\t\n\x07variant"\'\n\tPrincipal\x12\x0c\n\x04type\x18\x01 \x01(\t\x12\x0c\n\x04name\x18\x02 \x01(\t"O\n\x08Priority\x12\x14\n\x0cpriority_key\x18\x01 \x01(\x05\x12\x14\n\x0c\x66\x61irness_key\x18\x02 \x01(\t\x12\x17\n\x0f\x66\x61irness_weight\x18\x03 \x01(\x02";\n\x0eWorkerSelector\x12\x1d\n\x13worker_instance_key\x18\x01 \x01(\tH\x00\x42\n\n\x08selector"i\n\x11OnConflictOptions\x12\x19\n\x11\x61ttach_request_id\x18\x01 \x01(\x08\x12#\n\x1b\x61ttach_completion_callbacks\x18\x02 \x01(\x08\x12\x14\n\x0c\x61ttach_links\x18\x03 \x01(\x08"s\n\x12TimeSkippingConfig\x12\x0f\n\x07\x65nabled\x18\x01 \x01(\x08\x12/\n\x0c\x66\x61st_forward\x18\x02 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x1b\n\x13\x64isable_propagation\x18\x03 \x01(\x08"\x99\x01\n\x1cTimeSkippingStatePropagation\x12;\n\x18initial_skipped_duration\x18\x01 \x01(\x0b\x32\x19.google.protobuf.Duration\x12<\n\x18\x66\x61st_forward_target_time\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.TimestampB\x89\x01\n\x19io.temporal.api.common.v1B\x0cMessageProtoP\x01Z#go.temporal.io/api/common/v1;common\xaa\x02\x18Temporalio.Api.Common.V1\xea\x02\x1bTemporalio::Api::Common::V1b\x06proto3' ) @@ -49,6 +49,7 @@ _HEADER = DESCRIPTOR.message_types_by_name["Header"] _HEADER_FIELDSENTRY = _HEADER.nested_types_by_name["FieldsEntry"] _WORKFLOWEXECUTION = DESCRIPTOR.message_types_by_name["WorkflowExecution"] +_EXECUTION = DESCRIPTOR.message_types_by_name["Execution"] _WORKFLOWTYPE = DESCRIPTOR.message_types_by_name["WorkflowType"] _ACTIVITYTYPE = DESCRIPTOR.message_types_by_name["ActivityType"] _RETRYPOLICY = DESCRIPTOR.message_types_by_name["RetryPolicy"] @@ -209,6 +210,17 @@ ) _sym_db.RegisterMessage(WorkflowExecution) +Execution = _reflection.GeneratedProtocolMessageType( + "Execution", + (_message.Message,), + { + "DESCRIPTOR": _EXECUTION, + "__module__": "temporalio.api.common.v1.message_pb2", + # @@protoc_insertion_point(class_scope:temporal.api.common.v1.Execution) + }, +) +_sym_db.RegisterMessage(Execution) + WorkflowType = _reflection.GeneratedProtocolMessageType( "WorkflowType", (_message.Message,), @@ -513,54 +525,56 @@ _HEADER_FIELDSENTRY._serialized_end = 1025 _WORKFLOWEXECUTION._serialized_start = 1178 _WORKFLOWEXECUTION._serialized_end = 1234 - _WORKFLOWTYPE._serialized_start = 1236 - _WORKFLOWTYPE._serialized_end = 1264 - _ACTIVITYTYPE._serialized_start = 1266 - _ACTIVITYTYPE._serialized_end = 1294 - _RETRYPOLICY._serialized_start = 1297 - _RETRYPOLICY._serialized_end = 1506 - _METERINGMETADATA._serialized_start = 1508 - _METERINGMETADATA._serialized_end = 1578 - _WORKERVERSIONSTAMP._serialized_start = 1580 - _WORKERVERSIONSTAMP._serialized_end = 1642 - _WORKERVERSIONCAPABILITIES._serialized_start = 1644 - _WORKERVERSIONCAPABILITIES._serialized_end = 1745 - _RESETOPTIONS._serialized_start = 1748 - _RESETOPTIONS._serialized_end = 2113 - _CALLBACK._serialized_start = 2116 - _CALLBACK._serialized_end = 2472 - _CALLBACK_NEXUS._serialized_start = 2294 - _CALLBACK_NEXUS._serialized_end = 2429 - _CALLBACK_NEXUS_HEADERENTRY._serialized_start = 2384 - _CALLBACK_NEXUS_HEADERENTRY._serialized_end = 2429 - _CALLBACK_INTERNAL._serialized_start = 2431 - _CALLBACK_INTERNAL._serialized_end = 2455 - _LINK._serialized_start = 2475 - _LINK._serialized_end = 3509 - _LINK_WORKFLOWEVENT._serialized_start = 2804 - _LINK_WORKFLOWEVENT._serialized_end = 3243 - _LINK_WORKFLOWEVENT_EVENTREFERENCE._serialized_start = 3046 - _LINK_WORKFLOWEVENT_EVENTREFERENCE._serialized_end = 3134 - _LINK_WORKFLOWEVENT_REQUESTIDREFERENCE._serialized_start = 3136 - _LINK_WORKFLOWEVENT_REQUESTIDREFERENCE._serialized_end = 3230 - _LINK_BATCHJOB._serialized_start = 3245 - _LINK_BATCHJOB._serialized_end = 3271 - _LINK_ACTIVITY._serialized_start = 3273 - _LINK_ACTIVITY._serialized_end = 3339 - _LINK_NEXUSOPERATION._serialized_start = 3341 - _LINK_NEXUSOPERATION._serialized_end = 3414 - _LINK_WORKFLOW._serialized_start = 3416 - _LINK_WORKFLOW._serialized_end = 3498 - _PRINCIPAL._serialized_start = 3511 - _PRINCIPAL._serialized_end = 3550 - _PRIORITY._serialized_start = 3552 - _PRIORITY._serialized_end = 3631 - _WORKERSELECTOR._serialized_start = 3633 - _WORKERSELECTOR._serialized_end = 3692 - _ONCONFLICTOPTIONS._serialized_start = 3694 - _ONCONFLICTOPTIONS._serialized_end = 3799 - _TIMESKIPPINGCONFIG._serialized_start = 3801 - _TIMESKIPPINGCONFIG._serialized_end = 3922 - _TIMESKIPPINGSTATEPROPAGATION._serialized_start = 3925 - _TIMESKIPPINGSTATEPROPAGATION._serialized_end = 4078 + _EXECUTION._serialized_start = 1236 + _EXECUTION._serialized_end = 1336 + _WORKFLOWTYPE._serialized_start = 1338 + _WORKFLOWTYPE._serialized_end = 1366 + _ACTIVITYTYPE._serialized_start = 1368 + _ACTIVITYTYPE._serialized_end = 1396 + _RETRYPOLICY._serialized_start = 1399 + _RETRYPOLICY._serialized_end = 1608 + _METERINGMETADATA._serialized_start = 1610 + _METERINGMETADATA._serialized_end = 1680 + _WORKERVERSIONSTAMP._serialized_start = 1682 + _WORKERVERSIONSTAMP._serialized_end = 1744 + _WORKERVERSIONCAPABILITIES._serialized_start = 1746 + _WORKERVERSIONCAPABILITIES._serialized_end = 1847 + _RESETOPTIONS._serialized_start = 1850 + _RESETOPTIONS._serialized_end = 2215 + _CALLBACK._serialized_start = 2218 + _CALLBACK._serialized_end = 2574 + _CALLBACK_NEXUS._serialized_start = 2396 + _CALLBACK_NEXUS._serialized_end = 2531 + _CALLBACK_NEXUS_HEADERENTRY._serialized_start = 2486 + _CALLBACK_NEXUS_HEADERENTRY._serialized_end = 2531 + _CALLBACK_INTERNAL._serialized_start = 2533 + _CALLBACK_INTERNAL._serialized_end = 2557 + _LINK._serialized_start = 2577 + _LINK._serialized_end = 3611 + _LINK_WORKFLOWEVENT._serialized_start = 2906 + _LINK_WORKFLOWEVENT._serialized_end = 3345 + _LINK_WORKFLOWEVENT_EVENTREFERENCE._serialized_start = 3148 + _LINK_WORKFLOWEVENT_EVENTREFERENCE._serialized_end = 3236 + _LINK_WORKFLOWEVENT_REQUESTIDREFERENCE._serialized_start = 3238 + _LINK_WORKFLOWEVENT_REQUESTIDREFERENCE._serialized_end = 3332 + _LINK_BATCHJOB._serialized_start = 3347 + _LINK_BATCHJOB._serialized_end = 3373 + _LINK_ACTIVITY._serialized_start = 3375 + _LINK_ACTIVITY._serialized_end = 3441 + _LINK_NEXUSOPERATION._serialized_start = 3443 + _LINK_NEXUSOPERATION._serialized_end = 3516 + _LINK_WORKFLOW._serialized_start = 3518 + _LINK_WORKFLOW._serialized_end = 3600 + _PRINCIPAL._serialized_start = 3613 + _PRINCIPAL._serialized_end = 3652 + _PRIORITY._serialized_start = 3654 + _PRIORITY._serialized_end = 3733 + _WORKERSELECTOR._serialized_start = 3735 + _WORKERSELECTOR._serialized_end = 3794 + _ONCONFLICTOPTIONS._serialized_start = 3796 + _ONCONFLICTOPTIONS._serialized_end = 3901 + _TIMESKIPPINGCONFIG._serialized_start = 3903 + _TIMESKIPPINGCONFIG._serialized_end = 4018 + _TIMESKIPPINGSTATEPROPAGATION._serialized_start = 4021 + _TIMESKIPPINGSTATEPROPAGATION._serialized_end = 4174 # @@protoc_insertion_point(module_scope) diff --git a/temporalio/api/common/v1/message_pb2.pyi b/temporalio/api/common/v1/message_pb2.pyi index 04840f406..37a553810 100644 --- a/temporalio/api/common/v1/message_pb2.pyi +++ b/temporalio/api/common/v1/message_pb2.pyi @@ -321,6 +321,35 @@ class WorkflowExecution(google.protobuf.message.Message): global___WorkflowExecution = WorkflowExecution +class Execution(google.protobuf.message.Message): + """Identifies a specific execution within a namespace. This is used for standalone activities + executions in batch jobs currently. + """ + + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + TYPE_FIELD_NUMBER: builtins.int + BUSINESS_ID_FIELD_NUMBER: builtins.int + RUN_ID_FIELD_NUMBER: builtins.int + type: temporalio.api.enums.v1.common_pb2.ExecutionType.ValueType + business_id: builtins.str + run_id: builtins.str + def __init__( + self, + *, + type: temporalio.api.enums.v1.common_pb2.ExecutionType.ValueType = ..., + business_id: builtins.str = ..., + run_id: builtins.str = ..., + ) -> None: ... + def ClearField( + self, + field_name: typing_extensions.Literal[ + "business_id", b"business_id", "run_id", b"run_id", "type", b"type" + ], + ) -> None: ... + +global___Execution = Execution + class WorkflowType(google.protobuf.message.Message): """Represents the identifier used by a workflow author to define the workflow. Typically, the name of a function. This is sometimes referred to as the workflow's "name" @@ -1277,7 +1306,7 @@ class TimeSkippingConfig(google.protobuf.message.Message): ENABLED_FIELD_NUMBER: builtins.int FAST_FORWARD_FIELD_NUMBER: builtins.int - DISABLE_CHILD_PROPAGATION_FIELD_NUMBER: builtins.int + DISABLE_PROPAGATION_FIELD_NUMBER: builtins.int enabled: builtins.bool """Enables or disables time skipping for this workflow execution.""" @property @@ -1295,8 +1324,9 @@ class TimeSkippingConfig(google.protobuf.message.Message): If the fast-forward duration exceeds the remaining execution timeout, time will only be fast-forwarded up to the end of the execution. """ - disable_child_propagation: builtins.bool - """By default, child workflows inherit the "enabled" flag when they are started. + disable_propagation: builtins.bool + """By default, executions started by another execution (e.g. a child workflow of a parent workflow or + a schedule with the timeskipping policy enabled), inherit the "enabled" flag and skip time when possible. This flag disables that inheritance. """ def __init__( @@ -1304,7 +1334,7 @@ class TimeSkippingConfig(google.protobuf.message.Message): *, enabled: builtins.bool = ..., fast_forward: google.protobuf.duration_pb2.Duration | None = ..., - disable_child_propagation: builtins.bool = ..., + disable_propagation: builtins.bool = ..., ) -> None: ... def HasField( self, field_name: typing_extensions.Literal["fast_forward", b"fast_forward"] @@ -1312,8 +1342,8 @@ class TimeSkippingConfig(google.protobuf.message.Message): def ClearField( self, field_name: typing_extensions.Literal[ - "disable_child_propagation", - b"disable_child_propagation", + "disable_propagation", + b"disable_propagation", "enabled", b"enabled", "fast_forward", diff --git a/temporalio/api/enums/v1/__init__.py b/temporalio/api/enums/v1/__init__.py index 82fef9b2c..4a1e72cca 100644 --- a/temporalio/api/enums/v1/__init__.py +++ b/temporalio/api/enums/v1/__init__.py @@ -9,6 +9,7 @@ ApplicationErrorCategory, CallbackState, EncodingType, + ExecutionType, IndexedValueType, NexusOperationCancellationState, PendingNexusOperationState, @@ -86,6 +87,7 @@ "DescribeTaskQueueMode", "EncodingType", "EventType", + "ExecutionType", "HistoryEventFilterType", "IndexedValueType", "NamespaceState", diff --git a/temporalio/api/enums/v1/activity_pb2.py b/temporalio/api/enums/v1/activity_pb2.py index ba5fddd25..fd709beb6 100644 --- a/temporalio/api/enums/v1/activity_pb2.py +++ b/temporalio/api/enums/v1/activity_pb2.py @@ -16,7 +16,7 @@ DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile( - b"\n$temporal/api/enums/v1/activity.proto\x12\x15temporal.api.enums.v1*\xb5\x02\n\x17\x41\x63tivityExecutionStatus\x12)\n%ACTIVITY_EXECUTION_STATUS_UNSPECIFIED\x10\x00\x12%\n!ACTIVITY_EXECUTION_STATUS_RUNNING\x10\x01\x12'\n#ACTIVITY_EXECUTION_STATUS_COMPLETED\x10\x02\x12$\n ACTIVITY_EXECUTION_STATUS_FAILED\x10\x03\x12&\n\"ACTIVITY_EXECUTION_STATUS_CANCELED\x10\x04\x12(\n$ACTIVITY_EXECUTION_STATUS_TERMINATED\x10\x05\x12'\n#ACTIVITY_EXECUTION_STATUS_TIMED_OUT\x10\x06*\xd8\x01\n\x15\x41\x63tivityIdReusePolicy\x12(\n$ACTIVITY_ID_REUSE_POLICY_UNSPECIFIED\x10\x00\x12,\n(ACTIVITY_ID_REUSE_POLICY_ALLOW_DUPLICATE\x10\x01\x12\x38\n4ACTIVITY_ID_REUSE_POLICY_ALLOW_DUPLICATE_FAILED_ONLY\x10\x02\x12-\n)ACTIVITY_ID_REUSE_POLICY_REJECT_DUPLICATE\x10\x03*\x9b\x01\n\x18\x41\x63tivityIdConflictPolicy\x12+\n'ACTIVITY_ID_CONFLICT_POLICY_UNSPECIFIED\x10\x00\x12$\n ACTIVITY_ID_CONFLICT_POLICY_FAIL\x10\x01\x12,\n(ACTIVITY_ID_CONFLICT_POLICY_USE_EXISTING\x10\x02\x42\x85\x01\n\x18io.temporal.api.enums.v1B\rActivityProtoP\x01Z!go.temporal.io/api/enums/v1;enums\xaa\x02\x17Temporalio.Api.Enums.V1\xea\x02\x1aTemporalio::Api::Enums::V1b\x06proto3" + b"\n$temporal/api/enums/v1/activity.proto\x12\x15temporal.api.enums.v1*\xdb\x02\n\x17\x41\x63tivityExecutionStatus\x12)\n%ACTIVITY_EXECUTION_STATUS_UNSPECIFIED\x10\x00\x12%\n!ACTIVITY_EXECUTION_STATUS_RUNNING\x10\x01\x12'\n#ACTIVITY_EXECUTION_STATUS_COMPLETED\x10\x02\x12$\n ACTIVITY_EXECUTION_STATUS_FAILED\x10\x03\x12&\n\"ACTIVITY_EXECUTION_STATUS_CANCELED\x10\x04\x12(\n$ACTIVITY_EXECUTION_STATUS_TERMINATED\x10\x05\x12'\n#ACTIVITY_EXECUTION_STATUS_TIMED_OUT\x10\x06\x12$\n ACTIVITY_EXECUTION_STATUS_PAUSED\x10\x07*\xd8\x01\n\x15\x41\x63tivityIdReusePolicy\x12(\n$ACTIVITY_ID_REUSE_POLICY_UNSPECIFIED\x10\x00\x12,\n(ACTIVITY_ID_REUSE_POLICY_ALLOW_DUPLICATE\x10\x01\x12\x38\n4ACTIVITY_ID_REUSE_POLICY_ALLOW_DUPLICATE_FAILED_ONLY\x10\x02\x12-\n)ACTIVITY_ID_REUSE_POLICY_REJECT_DUPLICATE\x10\x03*\x9b\x01\n\x18\x41\x63tivityIdConflictPolicy\x12+\n'ACTIVITY_ID_CONFLICT_POLICY_UNSPECIFIED\x10\x00\x12$\n ACTIVITY_ID_CONFLICT_POLICY_FAIL\x10\x01\x12,\n(ACTIVITY_ID_CONFLICT_POLICY_USE_EXISTING\x10\x02\x42\x85\x01\n\x18io.temporal.api.enums.v1B\rActivityProtoP\x01Z!go.temporal.io/api/enums/v1;enums\xaa\x02\x17Temporalio.Api.Enums.V1\xea\x02\x1aTemporalio::Api::Enums::V1b\x06proto3" ) _ACTIVITYEXECUTIONSTATUS = DESCRIPTOR.enum_types_by_name["ActivityExecutionStatus"] @@ -32,6 +32,7 @@ ACTIVITY_EXECUTION_STATUS_CANCELED = 4 ACTIVITY_EXECUTION_STATUS_TERMINATED = 5 ACTIVITY_EXECUTION_STATUS_TIMED_OUT = 6 +ACTIVITY_EXECUTION_STATUS_PAUSED = 7 ACTIVITY_ID_REUSE_POLICY_UNSPECIFIED = 0 ACTIVITY_ID_REUSE_POLICY_ALLOW_DUPLICATE = 1 ACTIVITY_ID_REUSE_POLICY_ALLOW_DUPLICATE_FAILED_ONLY = 2 @@ -45,9 +46,9 @@ DESCRIPTOR._options = None DESCRIPTOR._serialized_options = b"\n\030io.temporal.api.enums.v1B\rActivityProtoP\001Z!go.temporal.io/api/enums/v1;enums\252\002\027Temporalio.Api.Enums.V1\352\002\032Temporalio::Api::Enums::V1" _ACTIVITYEXECUTIONSTATUS._serialized_start = 64 - _ACTIVITYEXECUTIONSTATUS._serialized_end = 373 - _ACTIVITYIDREUSEPOLICY._serialized_start = 376 - _ACTIVITYIDREUSEPOLICY._serialized_end = 592 - _ACTIVITYIDCONFLICTPOLICY._serialized_start = 595 - _ACTIVITYIDCONFLICTPOLICY._serialized_end = 750 + _ACTIVITYEXECUTIONSTATUS._serialized_end = 411 + _ACTIVITYIDREUSEPOLICY._serialized_start = 414 + _ACTIVITYIDREUSEPOLICY._serialized_end = 630 + _ACTIVITYIDCONFLICTPOLICY._serialized_start = 633 + _ACTIVITYIDCONFLICTPOLICY._serialized_end = 788 # @@protoc_insertion_point(module_scope) diff --git a/temporalio/api/enums/v1/activity_pb2.pyi b/temporalio/api/enums/v1/activity_pb2.pyi index 73d846050..cadaedb37 100644 --- a/temporalio/api/enums/v1/activity_pb2.pyi +++ b/temporalio/api/enums/v1/activity_pb2.pyi @@ -62,13 +62,17 @@ class _ActivityExecutionStatusEnumTypeWrapper( reached when retry is blocked (RetryPolicy.maximum_attempts exhausted, SCHEDULE_TO_CLOSE would be exceeded, or cancellation has been requested). """ + ACTIVITY_EXECUTION_STATUS_PAUSED: _ActivityExecutionStatus.ValueType # 7 + """The activity is paused. Paused state is only reachable after calling + PauseActivityExecution on a standalone activity. + """ class ActivityExecutionStatus( _ActivityExecutionStatus, metaclass=_ActivityExecutionStatusEnumTypeWrapper ): """Status of a standalone activity. - The status is updated once, when the activity is originally scheduled, and again when the activity reaches a terminal - status. + The status is updated when the activity is originally scheduled, paused, unpaused, and when the + activity reaches a terminal state. (-- api-linter: core::0216::synonyms=disabled aip.dev/not-precedent: Named consistently with WorkflowExecutionStatus. --) """ @@ -107,6 +111,10 @@ ACTIVITY_EXECUTION_STATUS_TIMED_OUT: ActivityExecutionStatus.ValueType # 6 reached when retry is blocked (RetryPolicy.maximum_attempts exhausted, SCHEDULE_TO_CLOSE would be exceeded, or cancellation has been requested). """ +ACTIVITY_EXECUTION_STATUS_PAUSED: ActivityExecutionStatus.ValueType # 7 +"""The activity is paused. Paused state is only reachable after calling +PauseActivityExecution on a standalone activity. +""" global___ActivityExecutionStatus = ActivityExecutionStatus class _ActivityIdReusePolicy: diff --git a/temporalio/api/enums/v1/batch_operation_pb2.py b/temporalio/api/enums/v1/batch_operation_pb2.py index 60c9d7f2f..73d4e011b 100644 --- a/temporalio/api/enums/v1/batch_operation_pb2.py +++ b/temporalio/api/enums/v1/batch_operation_pb2.py @@ -16,7 +16,7 @@ DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile( - b"\n+temporal/api/enums/v1/batch_operation.proto\x12\x15temporal.api.enums.v1*\x9a\x03\n\x12\x42\x61tchOperationType\x12$\n BATCH_OPERATION_TYPE_UNSPECIFIED\x10\x00\x12\"\n\x1e\x42\x41TCH_OPERATION_TYPE_TERMINATE\x10\x01\x12\x1f\n\x1b\x42\x41TCH_OPERATION_TYPE_CANCEL\x10\x02\x12\x1f\n\x1b\x42\x41TCH_OPERATION_TYPE_SIGNAL\x10\x03\x12\x1f\n\x1b\x42\x41TCH_OPERATION_TYPE_DELETE\x10\x04\x12\x1e\n\x1a\x42\x41TCH_OPERATION_TYPE_RESET\x10\x05\x12\x31\n-BATCH_OPERATION_TYPE_UPDATE_EXECUTION_OPTIONS\x10\x06\x12)\n%BATCH_OPERATION_TYPE_UNPAUSE_ACTIVITY\x10\x07\x12\x30\n,BATCH_OPERATION_TYPE_UPDATE_ACTIVITY_OPTIONS\x10\x08\x12'\n#BATCH_OPERATION_TYPE_RESET_ACTIVITY\x10\t*\xa6\x01\n\x13\x42\x61tchOperationState\x12%\n!BATCH_OPERATION_STATE_UNSPECIFIED\x10\x00\x12!\n\x1d\x42\x41TCH_OPERATION_STATE_RUNNING\x10\x01\x12#\n\x1f\x42\x41TCH_OPERATION_STATE_COMPLETED\x10\x02\x12 \n\x1c\x42\x41TCH_OPERATION_STATE_FAILED\x10\x03\x42\x8b\x01\n\x18io.temporal.api.enums.v1B\x13\x42\x61tchOperationProtoP\x01Z!go.temporal.io/api/enums/v1;enums\xaa\x02\x17Temporalio.Api.Enums.V1\xea\x02\x1aTemporalio::Api::Enums::V1b\x06proto3" + b"\n+temporal/api/enums/v1/batch_operation.proto\x12\x15temporal.api.enums.v1*\xc3\x06\n\x12\x42\x61tchOperationType\x12$\n BATCH_OPERATION_TYPE_UNSPECIFIED\x10\x00\x12&\n\x1e\x42\x41TCH_OPERATION_TYPE_TERMINATE\x10\x01\x1a\x02\x08\x01\x12+\n'BATCH_OPERATION_TYPE_TERMINATE_WORKFLOW\x10\r\x12#\n\x1b\x42\x41TCH_OPERATION_TYPE_CANCEL\x10\x02\x1a\x02\x08\x01\x12(\n$BATCH_OPERATION_TYPE_CANCEL_WORKFLOW\x10\x0e\x12#\n\x1b\x42\x41TCH_OPERATION_TYPE_SIGNAL\x10\x03\x1a\x02\x08\x01\x12(\n$BATCH_OPERATION_TYPE_SIGNAL_WORKFLOW\x10\x0f\x12#\n\x1b\x42\x41TCH_OPERATION_TYPE_DELETE\x10\x04\x1a\x02\x08\x01\x12(\n$BATCH_OPERATION_TYPE_DELETE_WORKFLOW\x10\x10\x12\"\n\x1a\x42\x41TCH_OPERATION_TYPE_RESET\x10\x05\x1a\x02\x08\x01\x12'\n#BATCH_OPERATION_TYPE_RESET_WORKFLOW\x10\x11\x12\x35\n-BATCH_OPERATION_TYPE_UPDATE_EXECUTION_OPTIONS\x10\x06\x1a\x02\x08\x01\x12:\n6BATCH_OPERATION_TYPE_UPDATE_WORKFLOW_EXECUTION_OPTIONS\x10\x12\x12)\n%BATCH_OPERATION_TYPE_UNPAUSE_ACTIVITY\x10\x07\x12\x30\n,BATCH_OPERATION_TYPE_UPDATE_ACTIVITY_OPTIONS\x10\x08\x12'\n#BATCH_OPERATION_TYPE_RESET_ACTIVITY\x10\t\x12+\n'BATCH_OPERATION_TYPE_TERMINATE_ACTIVITY\x10\n\x12(\n$BATCH_OPERATION_TYPE_CANCEL_ACTIVITY\x10\x0b\x12(\n$BATCH_OPERATION_TYPE_DELETE_ACTIVITY\x10\x0c*\xa6\x01\n\x13\x42\x61tchOperationState\x12%\n!BATCH_OPERATION_STATE_UNSPECIFIED\x10\x00\x12!\n\x1d\x42\x41TCH_OPERATION_STATE_RUNNING\x10\x01\x12#\n\x1f\x42\x41TCH_OPERATION_STATE_COMPLETED\x10\x02\x12 \n\x1c\x42\x41TCH_OPERATION_STATE_FAILED\x10\x03\x42\x8b\x01\n\x18io.temporal.api.enums.v1B\x13\x42\x61tchOperationProtoP\x01Z!go.temporal.io/api/enums/v1;enums\xaa\x02\x17Temporalio.Api.Enums.V1\xea\x02\x1aTemporalio::Api::Enums::V1b\x06proto3" ) _BATCHOPERATIONTYPE = DESCRIPTOR.enum_types_by_name["BatchOperationType"] @@ -25,14 +25,23 @@ BatchOperationState = enum_type_wrapper.EnumTypeWrapper(_BATCHOPERATIONSTATE) BATCH_OPERATION_TYPE_UNSPECIFIED = 0 BATCH_OPERATION_TYPE_TERMINATE = 1 +BATCH_OPERATION_TYPE_TERMINATE_WORKFLOW = 13 BATCH_OPERATION_TYPE_CANCEL = 2 +BATCH_OPERATION_TYPE_CANCEL_WORKFLOW = 14 BATCH_OPERATION_TYPE_SIGNAL = 3 +BATCH_OPERATION_TYPE_SIGNAL_WORKFLOW = 15 BATCH_OPERATION_TYPE_DELETE = 4 +BATCH_OPERATION_TYPE_DELETE_WORKFLOW = 16 BATCH_OPERATION_TYPE_RESET = 5 +BATCH_OPERATION_TYPE_RESET_WORKFLOW = 17 BATCH_OPERATION_TYPE_UPDATE_EXECUTION_OPTIONS = 6 +BATCH_OPERATION_TYPE_UPDATE_WORKFLOW_EXECUTION_OPTIONS = 18 BATCH_OPERATION_TYPE_UNPAUSE_ACTIVITY = 7 BATCH_OPERATION_TYPE_UPDATE_ACTIVITY_OPTIONS = 8 BATCH_OPERATION_TYPE_RESET_ACTIVITY = 9 +BATCH_OPERATION_TYPE_TERMINATE_ACTIVITY = 10 +BATCH_OPERATION_TYPE_CANCEL_ACTIVITY = 11 +BATCH_OPERATION_TYPE_DELETE_ACTIVITY = 12 BATCH_OPERATION_STATE_UNSPECIFIED = 0 BATCH_OPERATION_STATE_RUNNING = 1 BATCH_OPERATION_STATE_COMPLETED = 2 @@ -42,8 +51,34 @@ if _descriptor._USE_C_DESCRIPTORS == False: DESCRIPTOR._options = None DESCRIPTOR._serialized_options = b"\n\030io.temporal.api.enums.v1B\023BatchOperationProtoP\001Z!go.temporal.io/api/enums/v1;enums\252\002\027Temporalio.Api.Enums.V1\352\002\032Temporalio::Api::Enums::V1" + _BATCHOPERATIONTYPE.values_by_name["BATCH_OPERATION_TYPE_TERMINATE"]._options = None + _BATCHOPERATIONTYPE.values_by_name[ + "BATCH_OPERATION_TYPE_TERMINATE" + ]._serialized_options = b"\010\001" + _BATCHOPERATIONTYPE.values_by_name["BATCH_OPERATION_TYPE_CANCEL"]._options = None + _BATCHOPERATIONTYPE.values_by_name[ + "BATCH_OPERATION_TYPE_CANCEL" + ]._serialized_options = b"\010\001" + _BATCHOPERATIONTYPE.values_by_name["BATCH_OPERATION_TYPE_SIGNAL"]._options = None + _BATCHOPERATIONTYPE.values_by_name[ + "BATCH_OPERATION_TYPE_SIGNAL" + ]._serialized_options = b"\010\001" + _BATCHOPERATIONTYPE.values_by_name["BATCH_OPERATION_TYPE_DELETE"]._options = None + _BATCHOPERATIONTYPE.values_by_name[ + "BATCH_OPERATION_TYPE_DELETE" + ]._serialized_options = b"\010\001" + _BATCHOPERATIONTYPE.values_by_name["BATCH_OPERATION_TYPE_RESET"]._options = None + _BATCHOPERATIONTYPE.values_by_name[ + "BATCH_OPERATION_TYPE_RESET" + ]._serialized_options = b"\010\001" + _BATCHOPERATIONTYPE.values_by_name[ + "BATCH_OPERATION_TYPE_UPDATE_EXECUTION_OPTIONS" + ]._options = None + _BATCHOPERATIONTYPE.values_by_name[ + "BATCH_OPERATION_TYPE_UPDATE_EXECUTION_OPTIONS" + ]._serialized_options = b"\010\001" _BATCHOPERATIONTYPE._serialized_start = 71 - _BATCHOPERATIONTYPE._serialized_end = 481 - _BATCHOPERATIONSTATE._serialized_start = 484 - _BATCHOPERATIONSTATE._serialized_end = 650 + _BATCHOPERATIONTYPE._serialized_end = 906 + _BATCHOPERATIONSTATE._serialized_start = 909 + _BATCHOPERATIONSTATE._serialized_end = 1075 # @@protoc_insertion_point(module_scope) diff --git a/temporalio/api/enums/v1/batch_operation_pb2.pyi b/temporalio/api/enums/v1/batch_operation_pb2.pyi index 49f426ebb..156ba51ed 100644 --- a/temporalio/api/enums/v1/batch_operation_pb2.pyi +++ b/temporalio/api/enums/v1/batch_operation_pb2.pyi @@ -30,14 +30,31 @@ class _BatchOperationTypeEnumTypeWrapper( DESCRIPTOR: google.protobuf.descriptor.EnumDescriptor BATCH_OPERATION_TYPE_UNSPECIFIED: _BatchOperationType.ValueType # 0 BATCH_OPERATION_TYPE_TERMINATE: _BatchOperationType.ValueType # 1 + """DEPRECATED: Use BATCH_OPERATION_TYPE_TERMINATE_WORKFLOW instead.""" + BATCH_OPERATION_TYPE_TERMINATE_WORKFLOW: _BatchOperationType.ValueType # 13 BATCH_OPERATION_TYPE_CANCEL: _BatchOperationType.ValueType # 2 + """DEPRECATED: Use BATCH_OPERATION_TYPE_CANCEL_WORKFLOW instead.""" + BATCH_OPERATION_TYPE_CANCEL_WORKFLOW: _BatchOperationType.ValueType # 14 BATCH_OPERATION_TYPE_SIGNAL: _BatchOperationType.ValueType # 3 + """DEPRECATED: Use BATCH_OPERATION_TYPE_SIGNAL_WORKFLOW instead.""" + BATCH_OPERATION_TYPE_SIGNAL_WORKFLOW: _BatchOperationType.ValueType # 15 BATCH_OPERATION_TYPE_DELETE: _BatchOperationType.ValueType # 4 + """DEPRECATED: Use BATCH_OPERATION_TYPE_DELETE_WORKFLOW instead.""" + BATCH_OPERATION_TYPE_DELETE_WORKFLOW: _BatchOperationType.ValueType # 16 BATCH_OPERATION_TYPE_RESET: _BatchOperationType.ValueType # 5 + """DEPRECATED: Use BATCH_OPERATION_TYPE_RESET_WORKFLOW instead.""" + BATCH_OPERATION_TYPE_RESET_WORKFLOW: _BatchOperationType.ValueType # 17 BATCH_OPERATION_TYPE_UPDATE_EXECUTION_OPTIONS: _BatchOperationType.ValueType # 6 + """DEPRECATED: Use BATCH_OPERATION_TYPE_UPDATE_WORKFLOW_EXECUTION_OPTIONS instead.""" + BATCH_OPERATION_TYPE_UPDATE_WORKFLOW_EXECUTION_OPTIONS: ( + _BatchOperationType.ValueType + ) # 18 BATCH_OPERATION_TYPE_UNPAUSE_ACTIVITY: _BatchOperationType.ValueType # 7 BATCH_OPERATION_TYPE_UPDATE_ACTIVITY_OPTIONS: _BatchOperationType.ValueType # 8 BATCH_OPERATION_TYPE_RESET_ACTIVITY: _BatchOperationType.ValueType # 9 + BATCH_OPERATION_TYPE_TERMINATE_ACTIVITY: _BatchOperationType.ValueType # 10 + BATCH_OPERATION_TYPE_CANCEL_ACTIVITY: _BatchOperationType.ValueType # 11 + BATCH_OPERATION_TYPE_DELETE_ACTIVITY: _BatchOperationType.ValueType # 12 class BatchOperationType( _BatchOperationType, metaclass=_BatchOperationTypeEnumTypeWrapper @@ -45,14 +62,31 @@ class BatchOperationType( BATCH_OPERATION_TYPE_UNSPECIFIED: BatchOperationType.ValueType # 0 BATCH_OPERATION_TYPE_TERMINATE: BatchOperationType.ValueType # 1 +"""DEPRECATED: Use BATCH_OPERATION_TYPE_TERMINATE_WORKFLOW instead.""" +BATCH_OPERATION_TYPE_TERMINATE_WORKFLOW: BatchOperationType.ValueType # 13 BATCH_OPERATION_TYPE_CANCEL: BatchOperationType.ValueType # 2 +"""DEPRECATED: Use BATCH_OPERATION_TYPE_CANCEL_WORKFLOW instead.""" +BATCH_OPERATION_TYPE_CANCEL_WORKFLOW: BatchOperationType.ValueType # 14 BATCH_OPERATION_TYPE_SIGNAL: BatchOperationType.ValueType # 3 +"""DEPRECATED: Use BATCH_OPERATION_TYPE_SIGNAL_WORKFLOW instead.""" +BATCH_OPERATION_TYPE_SIGNAL_WORKFLOW: BatchOperationType.ValueType # 15 BATCH_OPERATION_TYPE_DELETE: BatchOperationType.ValueType # 4 +"""DEPRECATED: Use BATCH_OPERATION_TYPE_DELETE_WORKFLOW instead.""" +BATCH_OPERATION_TYPE_DELETE_WORKFLOW: BatchOperationType.ValueType # 16 BATCH_OPERATION_TYPE_RESET: BatchOperationType.ValueType # 5 +"""DEPRECATED: Use BATCH_OPERATION_TYPE_RESET_WORKFLOW instead.""" +BATCH_OPERATION_TYPE_RESET_WORKFLOW: BatchOperationType.ValueType # 17 BATCH_OPERATION_TYPE_UPDATE_EXECUTION_OPTIONS: BatchOperationType.ValueType # 6 +"""DEPRECATED: Use BATCH_OPERATION_TYPE_UPDATE_WORKFLOW_EXECUTION_OPTIONS instead.""" +BATCH_OPERATION_TYPE_UPDATE_WORKFLOW_EXECUTION_OPTIONS: ( + BatchOperationType.ValueType +) # 18 BATCH_OPERATION_TYPE_UNPAUSE_ACTIVITY: BatchOperationType.ValueType # 7 BATCH_OPERATION_TYPE_UPDATE_ACTIVITY_OPTIONS: BatchOperationType.ValueType # 8 BATCH_OPERATION_TYPE_RESET_ACTIVITY: BatchOperationType.ValueType # 9 +BATCH_OPERATION_TYPE_TERMINATE_ACTIVITY: BatchOperationType.ValueType # 10 +BATCH_OPERATION_TYPE_CANCEL_ACTIVITY: BatchOperationType.ValueType # 11 +BATCH_OPERATION_TYPE_DELETE_ACTIVITY: BatchOperationType.ValueType # 12 global___BatchOperationType = BatchOperationType class _BatchOperationState: diff --git a/temporalio/api/enums/v1/common_pb2.py b/temporalio/api/enums/v1/common_pb2.py index 557ce7631..a646df4ad 100644 --- a/temporalio/api/enums/v1/common_pb2.py +++ b/temporalio/api/enums/v1/common_pb2.py @@ -16,7 +16,7 @@ DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile( - b"\n\"temporal/api/enums/v1/common.proto\x12\x15temporal.api.enums.v1*_\n\x0c\x45ncodingType\x12\x1d\n\x19\x45NCODING_TYPE_UNSPECIFIED\x10\x00\x12\x18\n\x14\x45NCODING_TYPE_PROTO3\x10\x01\x12\x16\n\x12\x45NCODING_TYPE_JSON\x10\x02*\x91\x02\n\x10IndexedValueType\x12\"\n\x1eINDEXED_VALUE_TYPE_UNSPECIFIED\x10\x00\x12\x1b\n\x17INDEXED_VALUE_TYPE_TEXT\x10\x01\x12\x1e\n\x1aINDEXED_VALUE_TYPE_KEYWORD\x10\x02\x12\x1a\n\x16INDEXED_VALUE_TYPE_INT\x10\x03\x12\x1d\n\x19INDEXED_VALUE_TYPE_DOUBLE\x10\x04\x12\x1b\n\x17INDEXED_VALUE_TYPE_BOOL\x10\x05\x12\x1f\n\x1bINDEXED_VALUE_TYPE_DATETIME\x10\x06\x12#\n\x1fINDEXED_VALUE_TYPE_KEYWORD_LIST\x10\x07*^\n\x08Severity\x12\x18\n\x14SEVERITY_UNSPECIFIED\x10\x00\x12\x11\n\rSEVERITY_HIGH\x10\x01\x12\x13\n\x0fSEVERITY_MEDIUM\x10\x02\x12\x10\n\x0cSEVERITY_LOW\x10\x03*\xde\x01\n\rCallbackState\x12\x1e\n\x1a\x43\x41LLBACK_STATE_UNSPECIFIED\x10\x00\x12\x1a\n\x16\x43\x41LLBACK_STATE_STANDBY\x10\x01\x12\x1c\n\x18\x43\x41LLBACK_STATE_SCHEDULED\x10\x02\x12\x1e\n\x1a\x43\x41LLBACK_STATE_BACKING_OFF\x10\x03\x12\x19\n\x15\x43\x41LLBACK_STATE_FAILED\x10\x04\x12\x1c\n\x18\x43\x41LLBACK_STATE_SUCCEEDED\x10\x05\x12\x1a\n\x16\x43\x41LLBACK_STATE_BLOCKED\x10\x06*\xfd\x01\n\x1aPendingNexusOperationState\x12-\n)PENDING_NEXUS_OPERATION_STATE_UNSPECIFIED\x10\x00\x12+\n'PENDING_NEXUS_OPERATION_STATE_SCHEDULED\x10\x01\x12-\n)PENDING_NEXUS_OPERATION_STATE_BACKING_OFF\x10\x02\x12)\n%PENDING_NEXUS_OPERATION_STATE_STARTED\x10\x03\x12)\n%PENDING_NEXUS_OPERATION_STATE_BLOCKED\x10\x04*\xfe\x02\n\x1fNexusOperationCancellationState\x12\x32\n.NEXUS_OPERATION_CANCELLATION_STATE_UNSPECIFIED\x10\x00\x12\x30\n,NEXUS_OPERATION_CANCELLATION_STATE_SCHEDULED\x10\x01\x12\x32\n.NEXUS_OPERATION_CANCELLATION_STATE_BACKING_OFF\x10\x02\x12\x30\n,NEXUS_OPERATION_CANCELLATION_STATE_SUCCEEDED\x10\x03\x12-\n)NEXUS_OPERATION_CANCELLATION_STATE_FAILED\x10\x04\x12\x30\n,NEXUS_OPERATION_CANCELLATION_STATE_TIMED_OUT\x10\x05\x12.\n*NEXUS_OPERATION_CANCELLATION_STATE_BLOCKED\x10\x06*\x97\x01\n\x17WorkflowRuleActionScope\x12*\n&WORKFLOW_RULE_ACTION_SCOPE_UNSPECIFIED\x10\x00\x12'\n#WORKFLOW_RULE_ACTION_SCOPE_WORKFLOW\x10\x01\x12'\n#WORKFLOW_RULE_ACTION_SCOPE_ACTIVITY\x10\x02*m\n\x18\x41pplicationErrorCategory\x12*\n&APPLICATION_ERROR_CATEGORY_UNSPECIFIED\x10\x00\x12%\n!APPLICATION_ERROR_CATEGORY_BENIGN\x10\x01*\x85\x01\n\x0cWorkerStatus\x12\x1d\n\x19WORKER_STATUS_UNSPECIFIED\x10\x00\x12\x19\n\x15WORKER_STATUS_RUNNING\x10\x01\x12\x1f\n\x1bWORKER_STATUS_SHUTTING_DOWN\x10\x02\x12\x1a\n\x16WORKER_STATUS_SHUTDOWN\x10\x03\x42\x83\x01\n\x18io.temporal.api.enums.v1B\x0b\x43ommonProtoP\x01Z!go.temporal.io/api/enums/v1;enums\xaa\x02\x17Temporalio.Api.Enums.V1\xea\x02\x1aTemporalio::Api::Enums::V1b\x06proto3" + b"\n\"temporal/api/enums/v1/common.proto\x12\x15temporal.api.enums.v1*_\n\x0c\x45ncodingType\x12\x1d\n\x19\x45NCODING_TYPE_UNSPECIFIED\x10\x00\x12\x18\n\x14\x45NCODING_TYPE_PROTO3\x10\x01\x12\x16\n\x12\x45NCODING_TYPE_JSON\x10\x02*\x91\x02\n\x10IndexedValueType\x12\"\n\x1eINDEXED_VALUE_TYPE_UNSPECIFIED\x10\x00\x12\x1b\n\x17INDEXED_VALUE_TYPE_TEXT\x10\x01\x12\x1e\n\x1aINDEXED_VALUE_TYPE_KEYWORD\x10\x02\x12\x1a\n\x16INDEXED_VALUE_TYPE_INT\x10\x03\x12\x1d\n\x19INDEXED_VALUE_TYPE_DOUBLE\x10\x04\x12\x1b\n\x17INDEXED_VALUE_TYPE_BOOL\x10\x05\x12\x1f\n\x1bINDEXED_VALUE_TYPE_DATETIME\x10\x06\x12#\n\x1fINDEXED_VALUE_TYPE_KEYWORD_LIST\x10\x07*^\n\x08Severity\x12\x18\n\x14SEVERITY_UNSPECIFIED\x10\x00\x12\x11\n\rSEVERITY_HIGH\x10\x01\x12\x13\n\x0fSEVERITY_MEDIUM\x10\x02\x12\x10\n\x0cSEVERITY_LOW\x10\x03*\xde\x01\n\rCallbackState\x12\x1e\n\x1a\x43\x41LLBACK_STATE_UNSPECIFIED\x10\x00\x12\x1a\n\x16\x43\x41LLBACK_STATE_STANDBY\x10\x01\x12\x1c\n\x18\x43\x41LLBACK_STATE_SCHEDULED\x10\x02\x12\x1e\n\x1a\x43\x41LLBACK_STATE_BACKING_OFF\x10\x03\x12\x19\n\x15\x43\x41LLBACK_STATE_FAILED\x10\x04\x12\x1c\n\x18\x43\x41LLBACK_STATE_SUCCEEDED\x10\x05\x12\x1a\n\x16\x43\x41LLBACK_STATE_BLOCKED\x10\x06*\xfd\x01\n\x1aPendingNexusOperationState\x12-\n)PENDING_NEXUS_OPERATION_STATE_UNSPECIFIED\x10\x00\x12+\n'PENDING_NEXUS_OPERATION_STATE_SCHEDULED\x10\x01\x12-\n)PENDING_NEXUS_OPERATION_STATE_BACKING_OFF\x10\x02\x12)\n%PENDING_NEXUS_OPERATION_STATE_STARTED\x10\x03\x12)\n%PENDING_NEXUS_OPERATION_STATE_BLOCKED\x10\x04*\xfe\x02\n\x1fNexusOperationCancellationState\x12\x32\n.NEXUS_OPERATION_CANCELLATION_STATE_UNSPECIFIED\x10\x00\x12\x30\n,NEXUS_OPERATION_CANCELLATION_STATE_SCHEDULED\x10\x01\x12\x32\n.NEXUS_OPERATION_CANCELLATION_STATE_BACKING_OFF\x10\x02\x12\x30\n,NEXUS_OPERATION_CANCELLATION_STATE_SUCCEEDED\x10\x03\x12-\n)NEXUS_OPERATION_CANCELLATION_STATE_FAILED\x10\x04\x12\x30\n,NEXUS_OPERATION_CANCELLATION_STATE_TIMED_OUT\x10\x05\x12.\n*NEXUS_OPERATION_CANCELLATION_STATE_BLOCKED\x10\x06*\x97\x01\n\x17WorkflowRuleActionScope\x12*\n&WORKFLOW_RULE_ACTION_SCOPE_UNSPECIFIED\x10\x00\x12'\n#WORKFLOW_RULE_ACTION_SCOPE_WORKFLOW\x10\x01\x12'\n#WORKFLOW_RULE_ACTION_SCOPE_ACTIVITY\x10\x02*m\n\x18\x41pplicationErrorCategory\x12*\n&APPLICATION_ERROR_CATEGORY_UNSPECIFIED\x10\x00\x12%\n!APPLICATION_ERROR_CATEGORY_BENIGN\x10\x01*\x85\x01\n\x0cWorkerStatus\x12\x1d\n\x19WORKER_STATUS_UNSPECIFIED\x10\x00\x12\x19\n\x15WORKER_STATUS_RUNNING\x10\x01\x12\x1f\n\x1bWORKER_STATUS_SHUTTING_DOWN\x10\x02\x12\x1a\n\x16WORKER_STATUS_SHUTDOWN\x10\x03*i\n\rExecutionType\x12\x1e\n\x1a\x45XECUTION_TYPE_UNSPECIFIED\x10\x00\x12\x1b\n\x17\x45XECUTION_TYPE_WORKFLOW\x10\x01\x12\x1b\n\x17\x45XECUTION_TYPE_ACTIVITY\x10\x02\x42\x83\x01\n\x18io.temporal.api.enums.v1B\x0b\x43ommonProtoP\x01Z!go.temporal.io/api/enums/v1;enums\xaa\x02\x17Temporalio.Api.Enums.V1\xea\x02\x1aTemporalio::Api::Enums::V1b\x06proto3" ) _ENCODINGTYPE = DESCRIPTOR.enum_types_by_name["EncodingType"] @@ -45,6 +45,8 @@ ApplicationErrorCategory = enum_type_wrapper.EnumTypeWrapper(_APPLICATIONERRORCATEGORY) _WORKERSTATUS = DESCRIPTOR.enum_types_by_name["WorkerStatus"] WorkerStatus = enum_type_wrapper.EnumTypeWrapper(_WORKERSTATUS) +_EXECUTIONTYPE = DESCRIPTOR.enum_types_by_name["ExecutionType"] +ExecutionType = enum_type_wrapper.EnumTypeWrapper(_EXECUTIONTYPE) ENCODING_TYPE_UNSPECIFIED = 0 ENCODING_TYPE_PROTO3 = 1 ENCODING_TYPE_JSON = 2 @@ -88,6 +90,9 @@ WORKER_STATUS_RUNNING = 1 WORKER_STATUS_SHUTTING_DOWN = 2 WORKER_STATUS_SHUTDOWN = 3 +EXECUTION_TYPE_UNSPECIFIED = 0 +EXECUTION_TYPE_WORKFLOW = 1 +EXECUTION_TYPE_ACTIVITY = 2 if _descriptor._USE_C_DESCRIPTORS == False: @@ -111,4 +116,6 @@ _APPLICATIONERRORCATEGORY._serialized_end = 1659 _WORKERSTATUS._serialized_start = 1662 _WORKERSTATUS._serialized_end = 1795 + _EXECUTIONTYPE._serialized_start = 1797 + _EXECUTIONTYPE._serialized_end = 1902 # @@protoc_insertion_point(module_scope) diff --git a/temporalio/api/enums/v1/common_pb2.pyi b/temporalio/api/enums/v1/common_pb2.pyi index 47e470295..47b6d030b 100644 --- a/temporalio/api/enums/v1/common_pb2.pyi +++ b/temporalio/api/enums/v1/common_pb2.pyi @@ -339,3 +339,29 @@ WORKER_STATUS_RUNNING: WorkerStatus.ValueType # 1 WORKER_STATUS_SHUTTING_DOWN: WorkerStatus.ValueType # 2 WORKER_STATUS_SHUTDOWN: WorkerStatus.ValueType # 3 global___WorkerStatus = WorkerStatus + +class _ExecutionType: + ValueType = typing.NewType("ValueType", builtins.int) + V: typing_extensions.TypeAlias = ValueType + +class _ExecutionTypeEnumTypeWrapper( + google.protobuf.internal.enum_type_wrapper._EnumTypeWrapper[ + _ExecutionType.ValueType + ], + builtins.type, +): # noqa: F821 + DESCRIPTOR: google.protobuf.descriptor.EnumDescriptor + EXECUTION_TYPE_UNSPECIFIED: _ExecutionType.ValueType # 0 + EXECUTION_TYPE_WORKFLOW: _ExecutionType.ValueType # 1 + """A workflow execution archetype.""" + EXECUTION_TYPE_ACTIVITY: _ExecutionType.ValueType # 2 + """An activity execution archetype. This is reserved for standalone activities.""" + +class ExecutionType(_ExecutionType, metaclass=_ExecutionTypeEnumTypeWrapper): ... + +EXECUTION_TYPE_UNSPECIFIED: ExecutionType.ValueType # 0 +EXECUTION_TYPE_WORKFLOW: ExecutionType.ValueType # 1 +"""A workflow execution archetype.""" +EXECUTION_TYPE_ACTIVITY: ExecutionType.ValueType # 2 +"""An activity execution archetype. This is reserved for standalone activities.""" +global___ExecutionType = ExecutionType diff --git a/temporalio/api/enums/v1/failed_cause_pb2.py b/temporalio/api/enums/v1/failed_cause_pb2.py index 141a06fcd..7ef32a839 100644 --- a/temporalio/api/enums/v1/failed_cause_pb2.py +++ b/temporalio/api/enums/v1/failed_cause_pb2.py @@ -16,7 +16,7 @@ DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile( - b'\n(temporal/api/enums/v1/failed_cause.proto\x12\x15temporal.api.enums.v1*\xd8\x12\n\x17WorkflowTaskFailedCause\x12*\n&WORKFLOW_TASK_FAILED_CAUSE_UNSPECIFIED\x10\x00\x12\x30\n,WORKFLOW_TASK_FAILED_CAUSE_UNHANDLED_COMMAND\x10\x01\x12?\n;WORKFLOW_TASK_FAILED_CAUSE_BAD_SCHEDULE_ACTIVITY_ATTRIBUTES\x10\x02\x12\x45\nAWORKFLOW_TASK_FAILED_CAUSE_BAD_REQUEST_CANCEL_ACTIVITY_ATTRIBUTES\x10\x03\x12\x39\n5WORKFLOW_TASK_FAILED_CAUSE_BAD_START_TIMER_ATTRIBUTES\x10\x04\x12:\n6WORKFLOW_TASK_FAILED_CAUSE_BAD_CANCEL_TIMER_ATTRIBUTES\x10\x05\x12;\n7WORKFLOW_TASK_FAILED_CAUSE_BAD_RECORD_MARKER_ATTRIBUTES\x10\x06\x12I\nEWORKFLOW_TASK_FAILED_CAUSE_BAD_COMPLETE_WORKFLOW_EXECUTION_ATTRIBUTES\x10\x07\x12\x45\nAWORKFLOW_TASK_FAILED_CAUSE_BAD_FAIL_WORKFLOW_EXECUTION_ATTRIBUTES\x10\x08\x12G\nCWORKFLOW_TASK_FAILED_CAUSE_BAD_CANCEL_WORKFLOW_EXECUTION_ATTRIBUTES\x10\t\x12X\nTWORKFLOW_TASK_FAILED_CAUSE_BAD_REQUEST_CANCEL_EXTERNAL_WORKFLOW_EXECUTION_ATTRIBUTES\x10\n\x12=\n9WORKFLOW_TASK_FAILED_CAUSE_BAD_CONTINUE_AS_NEW_ATTRIBUTES\x10\x0b\x12\x37\n3WORKFLOW_TASK_FAILED_CAUSE_START_TIMER_DUPLICATE_ID\x10\x0c\x12\x36\n2WORKFLOW_TASK_FAILED_CAUSE_RESET_STICKY_TASK_QUEUE\x10\r\x12@\n None: ... def ClearField( self, field_name: typing_extensions.Literal[ - "run_id", b"run_id", "start_request_id", b"start_request_id" + "first_execution_run_id", + b"first_execution_run_id", + "run_id", + b"run_id", + "start_request_id", + b"start_request_id", ], ) -> None: ... @@ -496,3 +504,19 @@ class NexusOperationExecutionAlreadyStartedFailure(google.protobuf.message.Messa global___NexusOperationExecutionAlreadyStartedFailure = ( NexusOperationExecutionAlreadyStartedFailure ) + +class WorkflowTaskCompletionBufferLostFailure(google.protobuf.message.Message): + """An error indicating that the server lost the buffered pages of a paginated workflow task + completion. This is a transient error: the workflow task is still valid, and the client + should resend all pages from page 0 using the same task token. + """ + + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + def __init__( + self, + ) -> None: ... + +global___WorkflowTaskCompletionBufferLostFailure = ( + WorkflowTaskCompletionBufferLostFailure +) diff --git a/temporalio/api/history/v1/message_pb2.py b/temporalio/api/history/v1/message_pb2.py index a161b93d1..ac337b708 100644 --- a/temporalio/api/history/v1/message_pb2.py +++ b/temporalio/api/history/v1/message_pb2.py @@ -58,7 +58,7 @@ ) DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile( - b'\n%temporal/api/history/v1/message.proto\x12\x17temporal.api.history.v1\x1a\x1egoogle/protobuf/duration.proto\x1a\x1fgoogle/protobuf/timestamp.proto\x1a&temporal/api/enums/v1/event_type.proto\x1a(temporal/api/enums/v1/failed_cause.proto\x1a"temporal/api/enums/v1/update.proto\x1a$temporal/api/enums/v1/workflow.proto\x1a$temporal/api/common/v1/message.proto\x1a(temporal/api/deployment/v1/message.proto\x1a%temporal/api/failure/v1/message.proto\x1a\'temporal/api/taskqueue/v1/message.proto\x1a$temporal/api/update/v1/message.proto\x1a&temporal/api/workflow/v1/message.proto\x1a\x30temporal/api/sdk/v1/task_complete_metadata.proto\x1a\'temporal/api/sdk/v1/user_metadata.proto\x1a,temporal/api/sdk/v1/event_group_marker.proto"\xda\x12\n\'WorkflowExecutionStartedEventAttributes\x12;\n\rworkflow_type\x18\x01 \x01(\x0b\x32$.temporal.api.common.v1.WorkflowType\x12!\n\x19parent_workflow_namespace\x18\x02 \x01(\t\x12$\n\x1cparent_workflow_namespace_id\x18\x1b \x01(\t\x12L\n\x19parent_workflow_execution\x18\x03 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12!\n\x19parent_initiated_event_id\x18\x04 \x01(\x03\x12\x38\n\ntask_queue\x18\x05 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12/\n\x05input\x18\x06 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12=\n\x1aworkflow_execution_timeout\x18\x07 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x37\n\x14workflow_run_timeout\x18\x08 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x38\n\x15workflow_task_timeout\x18\t \x01(\x0b\x32\x19.google.protobuf.Duration\x12"\n\x1a\x63ontinued_execution_run_id\x18\n \x01(\t\x12@\n\tinitiator\x18\x0b \x01(\x0e\x32-.temporal.api.enums.v1.ContinueAsNewInitiator\x12;\n\x11\x63ontinued_failure\x18\x0c \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12@\n\x16last_completion_result\x18\r \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12!\n\x19original_execution_run_id\x18\x0e \x01(\t\x12\x10\n\x08identity\x18\x0f \x01(\t\x12\x1e\n\x16\x66irst_execution_run_id\x18\x10 \x01(\t\x12\x39\n\x0cretry_policy\x18\x11 \x01(\x0b\x32#.temporal.api.common.v1.RetryPolicy\x12\x0f\n\x07\x61ttempt\x18\x12 \x01(\x05\x12\x46\n"workflow_execution_expiration_time\x18\x13 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x15\n\rcron_schedule\x18\x14 \x01(\t\x12>\n\x1b\x66irst_workflow_task_backoff\x18\x15 \x01(\x0b\x32\x19.google.protobuf.Duration\x12*\n\x04memo\x18\x16 \x01(\x0b\x32\x1c.temporal.api.common.v1.Memo\x12\x43\n\x11search_attributes\x18\x17 \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes\x12\x45\n\x16prev_auto_reset_points\x18\x18 \x01(\x0b\x32%.temporal.api.workflow.v1.ResetPoints\x12.\n\x06header\x18\x19 \x01(\x0b\x32\x1e.temporal.api.common.v1.Header\x12&\n\x1eparent_initiated_event_version\x18\x1a \x01(\x03\x12\x13\n\x0bworkflow_id\x18\x1c \x01(\t\x12L\n\x14source_version_stamp\x18\x1d \x01(\x0b\x32*.temporal.api.common.v1.WorkerVersionStampB\x02\x18\x01\x12>\n\x14\x63ompletion_callbacks\x18\x1e \x03(\x0b\x32 .temporal.api.common.v1.Callback\x12J\n\x17root_workflow_execution\x18\x1f \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x1e\n\x12inherited_build_id\x18 \x01(\tB\x02\x18\x01\x12I\n\x13versioning_override\x18! \x01(\x0b\x32,.temporal.api.workflow.v1.VersioningOverride\x12\x33\n\'parent_pinned_worker_deployment_version\x18" \x01(\tB\x02\x18\x01\x12\x32\n\x08priority\x18# \x01(\x0b\x32 .temporal.api.common.v1.Priority\x12U\n\x18inherited_pinned_version\x18% \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersion\x12Y\n\x1binherited_auto_upgrade_info\x18\' \x01(\x0b\x32\x34.temporal.api.deployment.v1.InheritedAutoUpgradeInfo\x12 \n\x18\x65\x61ger_execution_accepted\x18& \x01(\x08\x12^\n\x1f\x64\x65\x63lined_target_version_upgrade\x18( \x01(\x0b\x32\x35.temporal.api.history.v1.DeclinedTargetVersionUpgrade\x12H\n\x14time_skipping_config\x18) \x01(\x0b\x32*.temporal.api.common.v1.TimeSkippingConfig\x12]\n\x1ftime_skipping_state_propagation\x18+ \x01(\x0b\x32\x34.temporal.api.common.v1.TimeSkippingStatePropagationJ\x04\x08$\x10%J\x04\x08*\x10+R parent_pinned_deployment_versionR\x18initial_skipped_duration"\x88\x01\n\x1c\x44\x65\x63linedTargetVersionUpgrade\x12O\n\x12\x64\x65ployment_version\x18\x01 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersion\x12\x17\n\x0frevision_number\x18\x02 \x01(\x03"\xa5\x01\n)WorkflowExecutionCompletedEventAttributes\x12\x30\n\x06result\x18\x01 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12(\n workflow_task_completed_event_id\x18\x02 \x01(\x03\x12\x1c\n\x14new_execution_run_id\x18\x03 \x01(\t"\xdb\x01\n&WorkflowExecutionFailedEventAttributes\x12\x31\n\x07\x66\x61ilure\x18\x01 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12\x36\n\x0bretry_state\x18\x02 \x01(\x0e\x32!.temporal.api.enums.v1.RetryState\x12(\n workflow_task_completed_event_id\x18\x03 \x01(\x03\x12\x1c\n\x14new_execution_run_id\x18\x04 \x01(\t"\x80\x01\n(WorkflowExecutionTimedOutEventAttributes\x12\x36\n\x0bretry_state\x18\x01 \x01(\x0e\x32!.temporal.api.enums.v1.RetryState\x12\x1c\n\x14new_execution_run_id\x18\x02 \x01(\t"\xa5\x07\n.WorkflowExecutionContinuedAsNewEventAttributes\x12\x1c\n\x14new_execution_run_id\x18\x01 \x01(\t\x12;\n\rworkflow_type\x18\x02 \x01(\x0b\x32$.temporal.api.common.v1.WorkflowType\x12\x38\n\ntask_queue\x18\x03 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12/\n\x05input\x18\x04 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x37\n\x14workflow_run_timeout\x18\x05 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x38\n\x15workflow_task_timeout\x18\x06 \x01(\x0b\x32\x19.google.protobuf.Duration\x12(\n workflow_task_completed_event_id\x18\x07 \x01(\x03\x12\x39\n\x16\x62\x61\x63koff_start_interval\x18\x08 \x01(\x0b\x32\x19.google.protobuf.Duration\x12@\n\tinitiator\x18\t \x01(\x0e\x32-.temporal.api.enums.v1.ContinueAsNewInitiator\x12\x35\n\x07\x66\x61ilure\x18\n \x01(\x0b\x32 .temporal.api.failure.v1.FailureB\x02\x18\x01\x12@\n\x16last_completion_result\x18\x0b \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12.\n\x06header\x18\x0c \x01(\x0b\x32\x1e.temporal.api.common.v1.Header\x12*\n\x04memo\x18\r \x01(\x0b\x32\x1c.temporal.api.common.v1.Memo\x12\x43\n\x11search_attributes\x18\x0e \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes\x12\x1c\n\x10inherit_build_id\x18\x0f \x01(\x08\x42\x02\x18\x01\x12[\n\x1binitial_versioning_behavior\x18\x10 \x01(\x0e\x32\x36.temporal.api.enums.v1.ContinueAsNewVersioningBehavior"\xac\x01\n$WorkflowTaskScheduledEventAttributes\x12\x38\n\ntask_queue\x18\x01 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12\x39\n\x16start_to_close_timeout\x18\x02 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x0f\n\x07\x61ttempt\x18\x03 \x01(\x05"\xa0\x03\n"WorkflowTaskStartedEventAttributes\x12\x1a\n\x12scheduled_event_id\x18\x01 \x01(\x03\x12\x10\n\x08identity\x18\x02 \x01(\t\x12\x12\n\nrequest_id\x18\x03 \x01(\t\x12\x1f\n\x17suggest_continue_as_new\x18\x04 \x01(\x08\x12Z\n\x1fsuggest_continue_as_new_reasons\x18\x08 \x03(\x0e\x32\x31.temporal.api.enums.v1.SuggestContinueAsNewReason\x12\x30\n(target_worker_deployment_version_changed\x18\t \x01(\x08\x12\x1a\n\x12history_size_bytes\x18\x05 \x01(\x03\x12\x46\n\x0eworker_version\x18\x06 \x01(\x0b\x32*.temporal.api.common.v1.WorkerVersionStampB\x02\x18\x01\x12%\n\x19\x62uild_id_redirect_counter\x18\x07 \x01(\x03\x42\x02\x18\x01"\x82\x05\n$WorkflowTaskCompletedEventAttributes\x12\x1a\n\x12scheduled_event_id\x18\x01 \x01(\x03\x12\x18\n\x10started_event_id\x18\x02 \x01(\x03\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x1b\n\x0f\x62inary_checksum\x18\x04 \x01(\tB\x02\x18\x01\x12\x46\n\x0eworker_version\x18\x05 \x01(\x0b\x32*.temporal.api.common.v1.WorkerVersionStampB\x02\x18\x01\x12H\n\x0csdk_metadata\x18\x06 \x01(\x0b\x32\x32.temporal.api.sdk.v1.WorkflowTaskCompletedMetadata\x12\x43\n\x11metering_metadata\x18\r \x01(\x0b\x32(.temporal.api.common.v1.MeteringMetadata\x12>\n\ndeployment\x18\x07 \x01(\x0b\x32&.temporal.api.deployment.v1.DeploymentB\x02\x18\x01\x12\x46\n\x13versioning_behavior\x18\x08 \x01(\x0e\x32).temporal.api.enums.v1.VersioningBehavior\x12%\n\x19worker_deployment_version\x18\t \x01(\tB\x02\x18\x01\x12\x1e\n\x16worker_deployment_name\x18\n \x01(\t\x12O\n\x12\x64\x65ployment_version\x18\x0b \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersion"\x95\x01\n#WorkflowTaskTimedOutEventAttributes\x12\x1a\n\x12scheduled_event_id\x18\x01 \x01(\x03\x12\x18\n\x10started_event_id\x18\x02 \x01(\x03\x12\x38\n\x0ctimeout_type\x18\x03 \x01(\x0e\x32".temporal.api.enums.v1.TimeoutType"\x87\x03\n!WorkflowTaskFailedEventAttributes\x12\x1a\n\x12scheduled_event_id\x18\x01 \x01(\x03\x12\x18\n\x10started_event_id\x18\x02 \x01(\x03\x12=\n\x05\x63\x61use\x18\x03 \x01(\x0e\x32..temporal.api.enums.v1.WorkflowTaskFailedCause\x12\x31\n\x07\x66\x61ilure\x18\x04 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12\x10\n\x08identity\x18\x05 \x01(\t\x12\x13\n\x0b\x62\x61se_run_id\x18\x06 \x01(\t\x12\x12\n\nnew_run_id\x18\x07 \x01(\t\x12\x1a\n\x12\x66ork_event_version\x18\x08 \x01(\x03\x12\x1b\n\x0f\x62inary_checksum\x18\t \x01(\tB\x02\x18\x01\x12\x46\n\x0eworker_version\x18\n \x01(\x0b\x32*.temporal.api.common.v1.WorkerVersionStampB\x02\x18\x01"\xc2\x05\n$ActivityTaskScheduledEventAttributes\x12\x13\n\x0b\x61\x63tivity_id\x18\x01 \x01(\t\x12;\n\ractivity_type\x18\x02 \x01(\x0b\x32$.temporal.api.common.v1.ActivityType\x12\x38\n\ntask_queue\x18\x04 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12.\n\x06header\x18\x05 \x01(\x0b\x32\x1e.temporal.api.common.v1.Header\x12/\n\x05input\x18\x06 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12<\n\x19schedule_to_close_timeout\x18\x07 \x01(\x0b\x32\x19.google.protobuf.Duration\x12<\n\x19schedule_to_start_timeout\x18\x08 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x39\n\x16start_to_close_timeout\x18\t \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x34\n\x11heartbeat_timeout\x18\n \x01(\x0b\x32\x19.google.protobuf.Duration\x12(\n workflow_task_completed_event_id\x18\x0b \x01(\x03\x12\x39\n\x0cretry_policy\x18\x0c \x01(\x0b\x32#.temporal.api.common.v1.RetryPolicy\x12!\n\x15use_workflow_build_id\x18\r \x01(\x08\x42\x02\x18\x01\x12\x32\n\x08priority\x18\x0e \x01(\x0b\x32 .temporal.api.common.v1.PriorityJ\x04\x08\x03\x10\x04"\x9e\x02\n"ActivityTaskStartedEventAttributes\x12\x1a\n\x12scheduled_event_id\x18\x01 \x01(\x03\x12\x10\n\x08identity\x18\x02 \x01(\t\x12\x12\n\nrequest_id\x18\x03 \x01(\t\x12\x0f\n\x07\x61ttempt\x18\x04 \x01(\x05\x12\x36\n\x0clast_failure\x18\x05 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12\x46\n\x0eworker_version\x18\x06 \x01(\x0b\x32*.temporal.api.common.v1.WorkerVersionStampB\x02\x18\x01\x12%\n\x19\x62uild_id_redirect_counter\x18\x07 \x01(\x03\x42\x02\x18\x01"\xe8\x01\n$ActivityTaskCompletedEventAttributes\x12\x30\n\x06result\x18\x01 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x1a\n\x12scheduled_event_id\x18\x02 \x01(\x03\x12\x18\n\x10started_event_id\x18\x03 \x01(\x03\x12\x10\n\x08identity\x18\x04 \x01(\t\x12\x46\n\x0eworker_version\x18\x05 \x01(\x0b\x32*.temporal.api.common.v1.WorkerVersionStampB\x02\x18\x01"\x9e\x02\n!ActivityTaskFailedEventAttributes\x12\x31\n\x07\x66\x61ilure\x18\x01 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12\x1a\n\x12scheduled_event_id\x18\x02 \x01(\x03\x12\x18\n\x10started_event_id\x18\x03 \x01(\x03\x12\x10\n\x08identity\x18\x04 \x01(\t\x12\x36\n\x0bretry_state\x18\x05 \x01(\x0e\x32!.temporal.api.enums.v1.RetryState\x12\x46\n\x0eworker_version\x18\x06 \x01(\x0b\x32*.temporal.api.common.v1.WorkerVersionStampB\x02\x18\x01"\xc6\x01\n#ActivityTaskTimedOutEventAttributes\x12\x31\n\x07\x66\x61ilure\x18\x01 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12\x1a\n\x12scheduled_event_id\x18\x02 \x01(\x03\x12\x18\n\x10started_event_id\x18\x03 \x01(\x03\x12\x36\n\x0bretry_state\x18\x04 \x01(\x0e\x32!.temporal.api.enums.v1.RetryState"r\n*ActivityTaskCancelRequestedEventAttributes\x12\x1a\n\x12scheduled_event_id\x18\x01 \x01(\x03\x12(\n workflow_task_completed_event_id\x18\x02 \x01(\x03"\x92\x02\n#ActivityTaskCanceledEventAttributes\x12\x31\n\x07\x64\x65tails\x18\x01 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12(\n latest_cancel_requested_event_id\x18\x02 \x01(\x03\x12\x1a\n\x12scheduled_event_id\x18\x03 \x01(\x03\x12\x18\n\x10started_event_id\x18\x04 \x01(\x03\x12\x10\n\x08identity\x18\x05 \x01(\t\x12\x46\n\x0eworker_version\x18\x06 \x01(\x0b\x32*.temporal.api.common.v1.WorkerVersionStampB\x02\x18\x01"\x93\x01\n\x1bTimerStartedEventAttributes\x12\x10\n\x08timer_id\x18\x01 \x01(\t\x12\x38\n\x15start_to_fire_timeout\x18\x02 \x01(\x0b\x32\x19.google.protobuf.Duration\x12(\n workflow_task_completed_event_id\x18\x03 \x01(\x03"G\n\x19TimerFiredEventAttributes\x12\x10\n\x08timer_id\x18\x01 \x01(\t\x12\x18\n\x10started_event_id\x18\x02 \x01(\x03"\x86\x01\n\x1cTimerCanceledEventAttributes\x12\x10\n\x08timer_id\x18\x01 \x01(\t\x12\x18\n\x10started_event_id\x18\x02 \x01(\x03\x12(\n workflow_task_completed_event_id\x18\x03 \x01(\x03\x12\x10\n\x08identity\x18\x04 \x01(\t"\xc7\x01\n/WorkflowExecutionCancelRequestedEventAttributes\x12\r\n\x05\x63\x61use\x18\x01 \x01(\t\x12#\n\x1b\x65xternal_initiated_event_id\x18\x02 \x01(\x03\x12N\n\x1b\x65xternal_workflow_execution\x18\x03 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x10\n\x08identity\x18\x04 \x01(\t"\x87\x01\n(WorkflowExecutionCanceledEventAttributes\x12(\n workflow_task_completed_event_id\x18\x01 \x01(\x03\x12\x31\n\x07\x64\x65tails\x18\x02 \x01(\x0b\x32 .temporal.api.common.v1.Payloads"\xe9\x02\n\x1dMarkerRecordedEventAttributes\x12\x13\n\x0bmarker_name\x18\x01 \x01(\t\x12T\n\x07\x64\x65tails\x18\x02 \x03(\x0b\x32\x43.temporal.api.history.v1.MarkerRecordedEventAttributes.DetailsEntry\x12(\n workflow_task_completed_event_id\x18\x03 \x01(\x03\x12.\n\x06header\x18\x04 \x01(\x0b\x32\x1e.temporal.api.common.v1.Header\x12\x31\n\x07\x66\x61ilure\x18\x05 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x1aP\n\x0c\x44\x65tailsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12/\n\x05value\x18\x02 \x01(\x0b\x32 .temporal.api.common.v1.Payloads:\x02\x38\x01"\xbf\x02\n(WorkflowExecutionSignaledEventAttributes\x12\x13\n\x0bsignal_name\x18\x01 \x01(\t\x12/\n\x05input\x18\x02 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x10\n\x08identity\x18\x03 \x01(\t\x12.\n\x06header\x18\x04 \x01(\x0b\x32\x1e.temporal.api.common.v1.Header\x12\'\n\x1bskip_generate_workflow_task\x18\x05 \x01(\x08\x42\x02\x18\x01\x12N\n\x1b\x65xternal_workflow_execution\x18\x06 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x12\n\nrequest_id\x18\x07 \x01(\t"\x81\x01\n*WorkflowExecutionTerminatedEventAttributes\x12\x0e\n\x06reason\x18\x01 \x01(\t\x12\x31\n\x07\x64\x65tails\x18\x02 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x10\n\x08identity\x18\x03 \x01(\t"\x9c\x02\n>RequestCancelExternalWorkflowExecutionInitiatedEventAttributes\x12(\n workflow_task_completed_event_id\x18\x01 \x01(\x03\x12\x11\n\tnamespace\x18\x02 \x01(\t\x12\x14\n\x0cnamespace_id\x18\x07 \x01(\t\x12\x45\n\x12workflow_execution\x18\x03 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x13\n\x07\x63ontrol\x18\x04 \x01(\tB\x02\x18\x01\x12\x1b\n\x13\x63hild_workflow_only\x18\x05 \x01(\x08\x12\x0e\n\x06reason\x18\x06 \x01(\t"\xda\x02\n;RequestCancelExternalWorkflowExecutionFailedEventAttributes\x12P\n\x05\x63\x61use\x18\x01 \x01(\x0e\x32\x41.temporal.api.enums.v1.CancelExternalWorkflowExecutionFailedCause\x12(\n workflow_task_completed_event_id\x18\x02 \x01(\x03\x12\x11\n\tnamespace\x18\x03 \x01(\t\x12\x14\n\x0cnamespace_id\x18\x07 \x01(\t\x12\x45\n\x12workflow_execution\x18\x04 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x1a\n\x12initiated_event_id\x18\x05 \x01(\x03\x12\x13\n\x07\x63ontrol\x18\x06 \x01(\tB\x02\x18\x01"\xc5\x01\n7ExternalWorkflowExecutionCancelRequestedEventAttributes\x12\x1a\n\x12initiated_event_id\x18\x01 \x01(\x03\x12\x11\n\tnamespace\x18\x02 \x01(\t\x12\x14\n\x0cnamespace_id\x18\x04 \x01(\t\x12\x45\n\x12workflow_execution\x18\x03 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution"\xfb\x02\n7SignalExternalWorkflowExecutionInitiatedEventAttributes\x12(\n workflow_task_completed_event_id\x18\x01 \x01(\x03\x12\x11\n\tnamespace\x18\x02 \x01(\t\x12\x14\n\x0cnamespace_id\x18\t \x01(\t\x12\x45\n\x12workflow_execution\x18\x03 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x13\n\x0bsignal_name\x18\x04 \x01(\t\x12/\n\x05input\x18\x05 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x13\n\x07\x63ontrol\x18\x06 \x01(\tB\x02\x18\x01\x12\x1b\n\x13\x63hild_workflow_only\x18\x07 \x01(\x08\x12.\n\x06header\x18\x08 \x01(\x0b\x32\x1e.temporal.api.common.v1.Header"\xd3\x02\n4SignalExternalWorkflowExecutionFailedEventAttributes\x12P\n\x05\x63\x61use\x18\x01 \x01(\x0e\x32\x41.temporal.api.enums.v1.SignalExternalWorkflowExecutionFailedCause\x12(\n workflow_task_completed_event_id\x18\x02 \x01(\x03\x12\x11\n\tnamespace\x18\x03 \x01(\t\x12\x14\n\x0cnamespace_id\x18\x07 \x01(\t\x12\x45\n\x12workflow_execution\x18\x04 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x1a\n\x12initiated_event_id\x18\x05 \x01(\x03\x12\x13\n\x07\x63ontrol\x18\x06 \x01(\tB\x02\x18\x01"\xd3\x01\n0ExternalWorkflowExecutionSignaledEventAttributes\x12\x1a\n\x12initiated_event_id\x18\x01 \x01(\x03\x12\x11\n\tnamespace\x18\x02 \x01(\t\x12\x14\n\x0cnamespace_id\x18\x05 \x01(\t\x12\x45\n\x12workflow_execution\x18\x03 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x13\n\x07\x63ontrol\x18\x04 \x01(\tB\x02\x18\x01"\x9e\x01\n-UpsertWorkflowSearchAttributesEventAttributes\x12(\n workflow_task_completed_event_id\x18\x01 \x01(\x03\x12\x43\n\x11search_attributes\x18\x02 \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes"\x8a\x01\n)WorkflowPropertiesModifiedEventAttributes\x12(\n workflow_task_completed_event_id\x18\x01 \x01(\x03\x12\x33\n\rupserted_memo\x18\x02 \x01(\x0b\x32\x1c.temporal.api.common.v1.Memo"\xb1\t\n3StartChildWorkflowExecutionInitiatedEventAttributes\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x14\n\x0cnamespace_id\x18\x12 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12;\n\rworkflow_type\x18\x03 \x01(\x0b\x32$.temporal.api.common.v1.WorkflowType\x12\x38\n\ntask_queue\x18\x04 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12/\n\x05input\x18\x05 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12=\n\x1aworkflow_execution_timeout\x18\x06 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x37\n\x14workflow_run_timeout\x18\x07 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x38\n\x15workflow_task_timeout\x18\x08 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x45\n\x13parent_close_policy\x18\t \x01(\x0e\x32(.temporal.api.enums.v1.ParentClosePolicy\x12\x13\n\x07\x63ontrol\x18\n \x01(\tB\x02\x18\x01\x12(\n workflow_task_completed_event_id\x18\x0b \x01(\x03\x12N\n\x18workflow_id_reuse_policy\x18\x0c \x01(\x0e\x32,.temporal.api.enums.v1.WorkflowIdReusePolicy\x12\x39\n\x0cretry_policy\x18\r \x01(\x0b\x32#.temporal.api.common.v1.RetryPolicy\x12\x15\n\rcron_schedule\x18\x0e \x01(\t\x12.\n\x06header\x18\x0f \x01(\x0b\x32\x1e.temporal.api.common.v1.Header\x12*\n\x04memo\x18\x10 \x01(\x0b\x32\x1c.temporal.api.common.v1.Memo\x12\x43\n\x11search_attributes\x18\x11 \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes\x12\x1c\n\x10inherit_build_id\x18\x13 \x01(\x08\x42\x02\x18\x01\x12\x32\n\x08priority\x18\x14 \x01(\x0b\x32 .temporal.api.common.v1.Priority\x12H\n\x14time_skipping_config\x18\x15 \x01(\x0b\x32*.temporal.api.common.v1.TimeSkippingConfig\x12]\n\x1ftime_skipping_state_propagation\x18\x17 \x01(\x0b\x32\x34.temporal.api.common.v1.TimeSkippingStatePropagationJ\x04\x08\x16\x10\x17R\x18initial_skipped_duration"\xd6\x02\n0StartChildWorkflowExecutionFailedEventAttributes\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x14\n\x0cnamespace_id\x18\x08 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12;\n\rworkflow_type\x18\x03 \x01(\x0b\x32$.temporal.api.common.v1.WorkflowType\x12L\n\x05\x63\x61use\x18\x04 \x01(\x0e\x32=.temporal.api.enums.v1.StartChildWorkflowExecutionFailedCause\x12\x13\n\x07\x63ontrol\x18\x05 \x01(\tB\x02\x18\x01\x12\x1a\n\x12initiated_event_id\x18\x06 \x01(\x03\x12(\n workflow_task_completed_event_id\x18\x07 \x01(\x03"\xa7\x02\n,ChildWorkflowExecutionStartedEventAttributes\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x14\n\x0cnamespace_id\x18\x06 \x01(\t\x12\x1a\n\x12initiated_event_id\x18\x02 \x01(\x03\x12\x45\n\x12workflow_execution\x18\x03 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12;\n\rworkflow_type\x18\x04 \x01(\x0b\x32$.temporal.api.common.v1.WorkflowType\x12.\n\x06header\x18\x05 \x01(\x0b\x32\x1e.temporal.api.common.v1.Header"\xc5\x02\n.ChildWorkflowExecutionCompletedEventAttributes\x12\x30\n\x06result\x18\x01 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x11\n\tnamespace\x18\x02 \x01(\t\x12\x14\n\x0cnamespace_id\x18\x07 \x01(\t\x12\x45\n\x12workflow_execution\x18\x03 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12;\n\rworkflow_type\x18\x04 \x01(\x0b\x32$.temporal.api.common.v1.WorkflowType\x12\x1a\n\x12initiated_event_id\x18\x05 \x01(\x03\x12\x18\n\x10started_event_id\x18\x06 \x01(\x03"\xfb\x02\n+ChildWorkflowExecutionFailedEventAttributes\x12\x31\n\x07\x66\x61ilure\x18\x01 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12\x11\n\tnamespace\x18\x02 \x01(\t\x12\x14\n\x0cnamespace_id\x18\x08 \x01(\t\x12\x45\n\x12workflow_execution\x18\x03 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12;\n\rworkflow_type\x18\x04 \x01(\x0b\x32$.temporal.api.common.v1.WorkflowType\x12\x1a\n\x12initiated_event_id\x18\x05 \x01(\x03\x12\x18\n\x10started_event_id\x18\x06 \x01(\x03\x12\x36\n\x0bretry_state\x18\x07 \x01(\x0e\x32!.temporal.api.enums.v1.RetryState"\xc5\x02\n-ChildWorkflowExecutionCanceledEventAttributes\x12\x31\n\x07\x64\x65tails\x18\x01 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x11\n\tnamespace\x18\x02 \x01(\t\x12\x14\n\x0cnamespace_id\x18\x07 \x01(\t\x12\x45\n\x12workflow_execution\x18\x03 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12;\n\rworkflow_type\x18\x04 \x01(\x0b\x32$.temporal.api.common.v1.WorkflowType\x12\x1a\n\x12initiated_event_id\x18\x05 \x01(\x03\x12\x18\n\x10started_event_id\x18\x06 \x01(\x03"\xca\x02\n-ChildWorkflowExecutionTimedOutEventAttributes\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x14\n\x0cnamespace_id\x18\x07 \x01(\t\x12\x45\n\x12workflow_execution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12;\n\rworkflow_type\x18\x03 \x01(\x0b\x32$.temporal.api.common.v1.WorkflowType\x12\x1a\n\x12initiated_event_id\x18\x04 \x01(\x03\x12\x18\n\x10started_event_id\x18\x05 \x01(\x03\x12\x36\n\x0bretry_state\x18\x06 \x01(\x0e\x32!.temporal.api.enums.v1.RetryState"\x94\x02\n/ChildWorkflowExecutionTerminatedEventAttributes\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x14\n\x0cnamespace_id\x18\x06 \x01(\t\x12\x45\n\x12workflow_execution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12;\n\rworkflow_type\x18\x03 \x01(\x0b\x32$.temporal.api.common.v1.WorkflowType\x12\x1a\n\x12initiated_event_id\x18\x04 \x01(\x03\x12\x18\n\x10started_event_id\x18\x05 \x01(\x03"\xda\x05\n.WorkflowExecutionOptionsUpdatedEventAttributes\x12I\n\x13versioning_override\x18\x01 \x01(\x0b\x32,.temporal.api.workflow.v1.VersioningOverride\x12!\n\x19unset_versioning_override\x18\x02 \x01(\x08\x12\x1b\n\x13\x61ttached_request_id\x18\x03 \x01(\t\x12G\n\x1d\x61ttached_completion_callbacks\x18\x04 \x03(\x0b\x32 .temporal.api.common.v1.Callback\x12\x10\n\x08identity\x18\x05 \x01(\t\x12\x32\n\x08priority\x18\x06 \x01(\x0b\x32 .temporal.api.common.v1.Priority\x12H\n\x14time_skipping_config\x18\x07 \x01(\x0b\x32*.temporal.api.common.v1.TimeSkippingConfig\x12$\n\x1ctime_skipping_config_updated\x18\t \x01(\x08\x12\x84\x01\n\x17workflow_update_options\x18\x08 \x03(\x0b\x32\x63.temporal.api.history.v1.WorkflowExecutionOptionsUpdatedEventAttributes.WorkflowUpdateOptionsUpdate\x1a\x96\x01\n\x1bWorkflowUpdateOptionsUpdate\x12\x11\n\tupdate_id\x18\x01 \x01(\t\x12\x1b\n\x13\x61ttached_request_id\x18\x02 \x01(\t\x12G\n\x1d\x61ttached_completion_callbacks\x18\x03 \x03(\x0b\x32 .temporal.api.common.v1.Callback"\xc0\x02\n3WorkflowPropertiesModifiedExternallyEventAttributes\x12\x16\n\x0enew_task_queue\x18\x01 \x01(\t\x12<\n\x19new_workflow_task_timeout\x18\x02 \x01(\x0b\x32\x19.google.protobuf.Duration\x12;\n\x18new_workflow_run_timeout\x18\x03 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x41\n\x1enew_workflow_execution_timeout\x18\x04 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x33\n\rupserted_memo\x18\x05 \x01(\x0b\x32\x1c.temporal.api.common.v1.Memo"\x90\x01\n3ActivityPropertiesModifiedExternallyEventAttributes\x12\x1a\n\x12scheduled_event_id\x18\x01 \x01(\x03\x12=\n\x10new_retry_policy\x18\x02 \x01(\x0b\x32#.temporal.api.common.v1.RetryPolicy"\xdc\x01\n.WorkflowExecutionUpdateAcceptedEventAttributes\x12\x1c\n\x14protocol_instance_id\x18\x01 \x01(\t\x12#\n\x1b\x61\x63\x63\x65pted_request_message_id\x18\x02 \x01(\t\x12,\n$accepted_request_sequencing_event_id\x18\x03 \x01(\x03\x12\x39\n\x10\x61\x63\x63\x65pted_request\x18\x04 \x01(\x0b\x32\x1f.temporal.api.update.v1.Request"\xaa\x01\n/WorkflowExecutionUpdateCompletedEventAttributes\x12*\n\x04meta\x18\x01 \x01(\x0b\x32\x1c.temporal.api.update.v1.Meta\x12\x19\n\x11\x61\x63\x63\x65pted_event_id\x18\x03 \x01(\x03\x12\x30\n\x07outcome\x18\x02 \x01(\x0b\x32\x1f.temporal.api.update.v1.Outcome"\x8f\x02\n.WorkflowExecutionUpdateRejectedEventAttributes\x12\x1c\n\x14protocol_instance_id\x18\x01 \x01(\t\x12#\n\x1brejected_request_message_id\x18\x02 \x01(\t\x12,\n$rejected_request_sequencing_event_id\x18\x03 \x01(\x03\x12\x39\n\x10rejected_request\x18\x04 \x01(\x0b\x32\x1f.temporal.api.update.v1.Request\x12\x31\n\x07\x66\x61ilure\x18\x05 \x01(\x0b\x32 .temporal.api.failure.v1.Failure"\xa4\x01\n.WorkflowExecutionUpdateAdmittedEventAttributes\x12\x30\n\x07request\x18\x01 \x01(\x0b\x32\x1f.temporal.api.update.v1.Request\x12@\n\x06origin\x18\x02 \x01(\x0e\x32\x30.temporal.api.enums.v1.UpdateAdmittedEventOrigin"^\n&WorkflowExecutionPausedEventAttributes\x12\x10\n\x08identity\x18\x01 \x01(\t\x12\x0e\n\x06reason\x18\x02 \x01(\t\x12\x12\n\nrequest_id\x18\x03 \x01(\t"`\n(WorkflowExecutionUnpausedEventAttributes\x12\x10\n\x08identity\x18\x01 \x01(\t\x12\x0e\n\x06reason\x18\x02 \x01(\t\x12\x12\n\nrequest_id\x18\x03 \x01(\t"\xc5\x01\n8WorkflowExecutionTimeSkippingTransitionedEventAttributes\x12/\n\x0btarget_time\x18\x01 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12#\n\x1b\x64isabled_after_fast_forward\x18\x02 \x01(\x08\x12\x33\n\x0fwall_clock_time\x18\x03 \x01(\x0b\x32\x1a.google.protobuf.Timestamp"\xb4\x04\n&NexusOperationScheduledEventAttributes\x12\x10\n\x08\x65ndpoint\x18\x01 \x01(\t\x12\x0f\n\x07service\x18\x02 \x01(\t\x12\x11\n\toperation\x18\x03 \x01(\t\x12.\n\x05input\x18\x04 \x01(\x0b\x32\x1f.temporal.api.common.v1.Payload\x12<\n\x19schedule_to_close_timeout\x18\x05 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x66\n\x0cnexus_header\x18\x06 \x03(\x0b\x32P.temporal.api.history.v1.NexusOperationScheduledEventAttributes.NexusHeaderEntry\x12(\n workflow_task_completed_event_id\x18\x07 \x01(\x03\x12\x12\n\nrequest_id\x18\x08 \x01(\t\x12\x13\n\x0b\x65ndpoint_id\x18\t \x01(\t\x12<\n\x19schedule_to_start_timeout\x18\n \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x39\n\x16start_to_close_timeout\x18\x0b \x01(\x0b\x32\x19.google.protobuf.Duration\x1a\x32\n\x10NexusHeaderEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01"\x89\x01\n$NexusOperationStartedEventAttributes\x12\x1a\n\x12scheduled_event_id\x18\x01 \x01(\x03\x12\x18\n\x0coperation_id\x18\x03 \x01(\tB\x02\x18\x01\x12\x12\n\nrequest_id\x18\x04 \x01(\t\x12\x17\n\x0foperation_token\x18\x05 \x01(\t"\x89\x01\n&NexusOperationCompletedEventAttributes\x12\x1a\n\x12scheduled_event_id\x18\x01 \x01(\x03\x12/\n\x06result\x18\x02 \x01(\x0b\x32\x1f.temporal.api.common.v1.Payload\x12\x12\n\nrequest_id\x18\x03 \x01(\t"\x88\x01\n#NexusOperationFailedEventAttributes\x12\x1a\n\x12scheduled_event_id\x18\x01 \x01(\x03\x12\x31\n\x07\x66\x61ilure\x18\x02 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12\x12\n\nrequest_id\x18\x03 \x01(\t"\x8a\x01\n%NexusOperationTimedOutEventAttributes\x12\x1a\n\x12scheduled_event_id\x18\x01 \x01(\x03\x12\x31\n\x07\x66\x61ilure\x18\x02 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12\x12\n\nrequest_id\x18\x03 \x01(\t"\x8a\x01\n%NexusOperationCanceledEventAttributes\x12\x1a\n\x12scheduled_event_id\x18\x01 \x01(\x03\x12\x31\n\x07\x66\x61ilure\x18\x02 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12\x12\n\nrequest_id\x18\x03 \x01(\t"t\n,NexusOperationCancelRequestedEventAttributes\x12\x1a\n\x12scheduled_event_id\x18\x01 \x01(\x03\x12(\n workflow_task_completed_event_id\x18\x02 \x01(\x03"\x97\x01\n3NexusOperationCancelRequestCompletedEventAttributes\x12\x1a\n\x12requested_event_id\x18\x01 \x01(\x03\x12(\n workflow_task_completed_event_id\x18\x02 \x01(\x03\x12\x1a\n\x12scheduled_event_id\x18\x03 \x01(\x03"\xc7\x01\n0NexusOperationCancelRequestFailedEventAttributes\x12\x1a\n\x12requested_event_id\x18\x01 \x01(\x03\x12(\n workflow_task_completed_event_id\x18\x02 \x01(\x03\x12\x31\n\x07\x66\x61ilure\x18\x03 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12\x1a\n\x12scheduled_event_id\x18\x04 \x01(\x03"\xca?\n\x0cHistoryEvent\x12\x10\n\x08\x65vent_id\x18\x01 \x01(\x03\x12.\n\nevent_time\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x34\n\nevent_type\x18\x03 \x01(\x0e\x32 .temporal.api.enums.v1.EventType\x12\x0f\n\x07version\x18\x04 \x01(\x03\x12\x0f\n\x07task_id\x18\x05 \x01(\x03\x12\x1a\n\x11worker_may_ignore\x18\xac\x02 \x01(\x08\x12\x39\n\ruser_metadata\x18\xad\x02 \x01(\x0b\x32!.temporal.api.sdk.v1.UserMetadata\x12,\n\x05links\x18\xae\x02 \x03(\x0b\x32\x1c.temporal.api.common.v1.Link\x12\x35\n\tprincipal\x18\xaf\x02 \x01(\x0b\x32!.temporal.api.common.v1.Principal\x12\x43\n\x13\x65vent_group_markers\x18\xb0\x02 \x03(\x0b\x32%.temporal.api.sdk.v1.EventGroupMarker\x12w\n+workflow_execution_started_event_attributes\x18\x06 \x01(\x0b\x32@.temporal.api.history.v1.WorkflowExecutionStartedEventAttributesH\x00\x12{\n-workflow_execution_completed_event_attributes\x18\x07 \x01(\x0b\x32\x42.temporal.api.history.v1.WorkflowExecutionCompletedEventAttributesH\x00\x12u\n*workflow_execution_failed_event_attributes\x18\x08 \x01(\x0b\x32?.temporal.api.history.v1.WorkflowExecutionFailedEventAttributesH\x00\x12z\n-workflow_execution_timed_out_event_attributes\x18\t \x01(\x0b\x32\x41.temporal.api.history.v1.WorkflowExecutionTimedOutEventAttributesH\x00\x12q\n(workflow_task_scheduled_event_attributes\x18\n \x01(\x0b\x32=.temporal.api.history.v1.WorkflowTaskScheduledEventAttributesH\x00\x12m\n&workflow_task_started_event_attributes\x18\x0b \x01(\x0b\x32;.temporal.api.history.v1.WorkflowTaskStartedEventAttributesH\x00\x12q\n(workflow_task_completed_event_attributes\x18\x0c \x01(\x0b\x32=.temporal.api.history.v1.WorkflowTaskCompletedEventAttributesH\x00\x12p\n(workflow_task_timed_out_event_attributes\x18\r \x01(\x0b\x32<.temporal.api.history.v1.WorkflowTaskTimedOutEventAttributesH\x00\x12k\n%workflow_task_failed_event_attributes\x18\x0e \x01(\x0b\x32:.temporal.api.history.v1.WorkflowTaskFailedEventAttributesH\x00\x12q\n(activity_task_scheduled_event_attributes\x18\x0f \x01(\x0b\x32=.temporal.api.history.v1.ActivityTaskScheduledEventAttributesH\x00\x12m\n&activity_task_started_event_attributes\x18\x10 \x01(\x0b\x32;.temporal.api.history.v1.ActivityTaskStartedEventAttributesH\x00\x12q\n(activity_task_completed_event_attributes\x18\x11 \x01(\x0b\x32=.temporal.api.history.v1.ActivityTaskCompletedEventAttributesH\x00\x12k\n%activity_task_failed_event_attributes\x18\x12 \x01(\x0b\x32:.temporal.api.history.v1.ActivityTaskFailedEventAttributesH\x00\x12p\n(activity_task_timed_out_event_attributes\x18\x13 \x01(\x0b\x32<.temporal.api.history.v1.ActivityTaskTimedOutEventAttributesH\x00\x12^\n\x1etimer_started_event_attributes\x18\x14 \x01(\x0b\x32\x34.temporal.api.history.v1.TimerStartedEventAttributesH\x00\x12Z\n\x1ctimer_fired_event_attributes\x18\x15 \x01(\x0b\x32\x32.temporal.api.history.v1.TimerFiredEventAttributesH\x00\x12~\n/activity_task_cancel_requested_event_attributes\x18\x16 \x01(\x0b\x32\x43.temporal.api.history.v1.ActivityTaskCancelRequestedEventAttributesH\x00\x12o\n\'activity_task_canceled_event_attributes\x18\x17 \x01(\x0b\x32<.temporal.api.history.v1.ActivityTaskCanceledEventAttributesH\x00\x12`\n\x1ftimer_canceled_event_attributes\x18\x18 \x01(\x0b\x32\x35.temporal.api.history.v1.TimerCanceledEventAttributesH\x00\x12\x62\n marker_recorded_event_attributes\x18\x19 \x01(\x0b\x32\x36.temporal.api.history.v1.MarkerRecordedEventAttributesH\x00\x12y\n,workflow_execution_signaled_event_attributes\x18\x1a \x01(\x0b\x32\x41.temporal.api.history.v1.WorkflowExecutionSignaledEventAttributesH\x00\x12}\n.workflow_execution_terminated_event_attributes\x18\x1b \x01(\x0b\x32\x43.temporal.api.history.v1.WorkflowExecutionTerminatedEventAttributesH\x00\x12\x88\x01\n4workflow_execution_cancel_requested_event_attributes\x18\x1c \x01(\x0b\x32H.temporal.api.history.v1.WorkflowExecutionCancelRequestedEventAttributesH\x00\x12y\n,workflow_execution_canceled_event_attributes\x18\x1d \x01(\x0b\x32\x41.temporal.api.history.v1.WorkflowExecutionCanceledEventAttributesH\x00\x12\xa8\x01\nErequest_cancel_external_workflow_execution_initiated_event_attributes\x18\x1e \x01(\x0b\x32W.temporal.api.history.v1.RequestCancelExternalWorkflowExecutionInitiatedEventAttributesH\x00\x12\xa2\x01\nBrequest_cancel_external_workflow_execution_failed_event_attributes\x18\x1f \x01(\x0b\x32T.temporal.api.history.v1.RequestCancelExternalWorkflowExecutionFailedEventAttributesH\x00\x12\x99\x01\n=external_workflow_execution_cancel_requested_event_attributes\x18 \x01(\x0b\x32P.temporal.api.history.v1.ExternalWorkflowExecutionCancelRequestedEventAttributesH\x00\x12\x87\x01\n4workflow_execution_continued_as_new_event_attributes\x18! \x01(\x0b\x32G.temporal.api.history.v1.WorkflowExecutionContinuedAsNewEventAttributesH\x00\x12\x91\x01\n9start_child_workflow_execution_initiated_event_attributes\x18" \x01(\x0b\x32L.temporal.api.history.v1.StartChildWorkflowExecutionInitiatedEventAttributesH\x00\x12\x8b\x01\n6start_child_workflow_execution_failed_event_attributes\x18# \x01(\x0b\x32I.temporal.api.history.v1.StartChildWorkflowExecutionFailedEventAttributesH\x00\x12\x82\x01\n1child_workflow_execution_started_event_attributes\x18$ \x01(\x0b\x32\x45.temporal.api.history.v1.ChildWorkflowExecutionStartedEventAttributesH\x00\x12\x86\x01\n3child_workflow_execution_completed_event_attributes\x18% \x01(\x0b\x32G.temporal.api.history.v1.ChildWorkflowExecutionCompletedEventAttributesH\x00\x12\x80\x01\n0child_workflow_execution_failed_event_attributes\x18& \x01(\x0b\x32\x44.temporal.api.history.v1.ChildWorkflowExecutionFailedEventAttributesH\x00\x12\x84\x01\n2child_workflow_execution_canceled_event_attributes\x18\' \x01(\x0b\x32\x46.temporal.api.history.v1.ChildWorkflowExecutionCanceledEventAttributesH\x00\x12\x85\x01\n3child_workflow_execution_timed_out_event_attributes\x18( \x01(\x0b\x32\x46.temporal.api.history.v1.ChildWorkflowExecutionTimedOutEventAttributesH\x00\x12\x88\x01\n4child_workflow_execution_terminated_event_attributes\x18) \x01(\x0b\x32H.temporal.api.history.v1.ChildWorkflowExecutionTerminatedEventAttributesH\x00\x12\x99\x01\n=signal_external_workflow_execution_initiated_event_attributes\x18* \x01(\x0b\x32P.temporal.api.history.v1.SignalExternalWorkflowExecutionInitiatedEventAttributesH\x00\x12\x93\x01\n:signal_external_workflow_execution_failed_event_attributes\x18+ \x01(\x0b\x32M.temporal.api.history.v1.SignalExternalWorkflowExecutionFailedEventAttributesH\x00\x12\x8a\x01\n5external_workflow_execution_signaled_event_attributes\x18, \x01(\x0b\x32I.temporal.api.history.v1.ExternalWorkflowExecutionSignaledEventAttributesH\x00\x12\x84\x01\n2upsert_workflow_search_attributes_event_attributes\x18- \x01(\x0b\x32\x46.temporal.api.history.v1.UpsertWorkflowSearchAttributesEventAttributesH\x00\x12\x86\x01\n3workflow_execution_update_accepted_event_attributes\x18. \x01(\x0b\x32G.temporal.api.history.v1.WorkflowExecutionUpdateAcceptedEventAttributesH\x00\x12\x86\x01\n3workflow_execution_update_rejected_event_attributes\x18/ \x01(\x0b\x32G.temporal.api.history.v1.WorkflowExecutionUpdateRejectedEventAttributesH\x00\x12\x88\x01\n4workflow_execution_update_completed_event_attributes\x18\x30 \x01(\x0b\x32H.temporal.api.history.v1.WorkflowExecutionUpdateCompletedEventAttributesH\x00\x12\x90\x01\n8workflow_properties_modified_externally_event_attributes\x18\x31 \x01(\x0b\x32L.temporal.api.history.v1.WorkflowPropertiesModifiedExternallyEventAttributesH\x00\x12\x90\x01\n8activity_properties_modified_externally_event_attributes\x18\x32 \x01(\x0b\x32L.temporal.api.history.v1.ActivityPropertiesModifiedExternallyEventAttributesH\x00\x12{\n-workflow_properties_modified_event_attributes\x18\x33 \x01(\x0b\x32\x42.temporal.api.history.v1.WorkflowPropertiesModifiedEventAttributesH\x00\x12\x86\x01\n3workflow_execution_update_admitted_event_attributes\x18\x34 \x01(\x0b\x32G.temporal.api.history.v1.WorkflowExecutionUpdateAdmittedEventAttributesH\x00\x12u\n*nexus_operation_scheduled_event_attributes\x18\x35 \x01(\x0b\x32?.temporal.api.history.v1.NexusOperationScheduledEventAttributesH\x00\x12q\n(nexus_operation_started_event_attributes\x18\x36 \x01(\x0b\x32=.temporal.api.history.v1.NexusOperationStartedEventAttributesH\x00\x12u\n*nexus_operation_completed_event_attributes\x18\x37 \x01(\x0b\x32?.temporal.api.history.v1.NexusOperationCompletedEventAttributesH\x00\x12o\n\'nexus_operation_failed_event_attributes\x18\x38 \x01(\x0b\x32<.temporal.api.history.v1.NexusOperationFailedEventAttributesH\x00\x12s\n)nexus_operation_canceled_event_attributes\x18\x39 \x01(\x0b\x32>.temporal.api.history.v1.NexusOperationCanceledEventAttributesH\x00\x12t\n*nexus_operation_timed_out_event_attributes\x18: \x01(\x0b\x32>.temporal.api.history.v1.NexusOperationTimedOutEventAttributesH\x00\x12\x82\x01\n1nexus_operation_cancel_requested_event_attributes\x18; \x01(\x0b\x32\x45.temporal.api.history.v1.NexusOperationCancelRequestedEventAttributesH\x00\x12\x86\x01\n3workflow_execution_options_updated_event_attributes\x18< \x01(\x0b\x32G.temporal.api.history.v1.WorkflowExecutionOptionsUpdatedEventAttributesH\x00\x12\x91\x01\n9nexus_operation_cancel_request_completed_event_attributes\x18= \x01(\x0b\x32L.temporal.api.history.v1.NexusOperationCancelRequestCompletedEventAttributesH\x00\x12\x8b\x01\n6nexus_operation_cancel_request_failed_event_attributes\x18> \x01(\x0b\x32I.temporal.api.history.v1.NexusOperationCancelRequestFailedEventAttributesH\x00\x12u\n*workflow_execution_paused_event_attributes\x18? \x01(\x0b\x32?.temporal.api.history.v1.WorkflowExecutionPausedEventAttributesH\x00\x12y\n,workflow_execution_unpaused_event_attributes\x18@ \x01(\x0b\x32\x41.temporal.api.history.v1.WorkflowExecutionUnpausedEventAttributesH\x00\x12\x9b\x01\n>workflow_execution_time_skipping_transitioned_event_attributes\x18\x41 \x01(\x0b\x32Q.temporal.api.history.v1.WorkflowExecutionTimeSkippingTransitionedEventAttributesH\x00\x42\x0c\n\nattributes"@\n\x07History\x12\x35\n\x06\x65vents\x18\x01 \x03(\x0b\x32%.temporal.api.history.v1.HistoryEventB\x8e\x01\n\x1aio.temporal.api.history.v1B\x0cMessageProtoP\x01Z%go.temporal.io/api/history/v1;history\xaa\x02\x19Temporalio.Api.History.V1\xea\x02\x1cTemporalio::Api::History::V1b\x06proto3' + b'\n%temporal/api/history/v1/message.proto\x12\x17temporal.api.history.v1\x1a\x1egoogle/protobuf/duration.proto\x1a\x1fgoogle/protobuf/timestamp.proto\x1a&temporal/api/enums/v1/event_type.proto\x1a(temporal/api/enums/v1/failed_cause.proto\x1a"temporal/api/enums/v1/update.proto\x1a$temporal/api/enums/v1/workflow.proto\x1a$temporal/api/common/v1/message.proto\x1a(temporal/api/deployment/v1/message.proto\x1a%temporal/api/failure/v1/message.proto\x1a\'temporal/api/taskqueue/v1/message.proto\x1a$temporal/api/update/v1/message.proto\x1a&temporal/api/workflow/v1/message.proto\x1a\x30temporal/api/sdk/v1/task_complete_metadata.proto\x1a\'temporal/api/sdk/v1/user_metadata.proto\x1a,temporal/api/sdk/v1/event_group_marker.proto"\xda\x12\n\'WorkflowExecutionStartedEventAttributes\x12;\n\rworkflow_type\x18\x01 \x01(\x0b\x32$.temporal.api.common.v1.WorkflowType\x12!\n\x19parent_workflow_namespace\x18\x02 \x01(\t\x12$\n\x1cparent_workflow_namespace_id\x18\x1b \x01(\t\x12L\n\x19parent_workflow_execution\x18\x03 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12!\n\x19parent_initiated_event_id\x18\x04 \x01(\x03\x12\x38\n\ntask_queue\x18\x05 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12/\n\x05input\x18\x06 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12=\n\x1aworkflow_execution_timeout\x18\x07 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x37\n\x14workflow_run_timeout\x18\x08 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x38\n\x15workflow_task_timeout\x18\t \x01(\x0b\x32\x19.google.protobuf.Duration\x12"\n\x1a\x63ontinued_execution_run_id\x18\n \x01(\t\x12@\n\tinitiator\x18\x0b \x01(\x0e\x32-.temporal.api.enums.v1.ContinueAsNewInitiator\x12;\n\x11\x63ontinued_failure\x18\x0c \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12@\n\x16last_completion_result\x18\r \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12!\n\x19original_execution_run_id\x18\x0e \x01(\t\x12\x10\n\x08identity\x18\x0f \x01(\t\x12\x1e\n\x16\x66irst_execution_run_id\x18\x10 \x01(\t\x12\x39\n\x0cretry_policy\x18\x11 \x01(\x0b\x32#.temporal.api.common.v1.RetryPolicy\x12\x0f\n\x07\x61ttempt\x18\x12 \x01(\x05\x12\x46\n"workflow_execution_expiration_time\x18\x13 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x15\n\rcron_schedule\x18\x14 \x01(\t\x12>\n\x1b\x66irst_workflow_task_backoff\x18\x15 \x01(\x0b\x32\x19.google.protobuf.Duration\x12*\n\x04memo\x18\x16 \x01(\x0b\x32\x1c.temporal.api.common.v1.Memo\x12\x43\n\x11search_attributes\x18\x17 \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes\x12\x45\n\x16prev_auto_reset_points\x18\x18 \x01(\x0b\x32%.temporal.api.workflow.v1.ResetPoints\x12.\n\x06header\x18\x19 \x01(\x0b\x32\x1e.temporal.api.common.v1.Header\x12&\n\x1eparent_initiated_event_version\x18\x1a \x01(\x03\x12\x13\n\x0bworkflow_id\x18\x1c \x01(\t\x12L\n\x14source_version_stamp\x18\x1d \x01(\x0b\x32*.temporal.api.common.v1.WorkerVersionStampB\x02\x18\x01\x12>\n\x14\x63ompletion_callbacks\x18\x1e \x03(\x0b\x32 .temporal.api.common.v1.Callback\x12J\n\x17root_workflow_execution\x18\x1f \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x1e\n\x12inherited_build_id\x18 \x01(\tB\x02\x18\x01\x12I\n\x13versioning_override\x18! \x01(\x0b\x32,.temporal.api.workflow.v1.VersioningOverride\x12\x33\n\'parent_pinned_worker_deployment_version\x18" \x01(\tB\x02\x18\x01\x12\x32\n\x08priority\x18# \x01(\x0b\x32 .temporal.api.common.v1.Priority\x12U\n\x18inherited_pinned_version\x18% \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersion\x12Y\n\x1binherited_auto_upgrade_info\x18\' \x01(\x0b\x32\x34.temporal.api.deployment.v1.InheritedAutoUpgradeInfo\x12 \n\x18\x65\x61ger_execution_accepted\x18& \x01(\x08\x12^\n\x1f\x64\x65\x63lined_target_version_upgrade\x18( \x01(\x0b\x32\x35.temporal.api.history.v1.DeclinedTargetVersionUpgrade\x12H\n\x14time_skipping_config\x18) \x01(\x0b\x32*.temporal.api.common.v1.TimeSkippingConfig\x12]\n\x1ftime_skipping_state_propagation\x18+ \x01(\x0b\x32\x34.temporal.api.common.v1.TimeSkippingStatePropagationJ\x04\x08$\x10%J\x04\x08*\x10+R parent_pinned_deployment_versionR\x18initial_skipped_duration"\x88\x01\n\x1c\x44\x65\x63linedTargetVersionUpgrade\x12O\n\x12\x64\x65ployment_version\x18\x01 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersion\x12\x17\n\x0frevision_number\x18\x02 \x01(\x03"\xa5\x01\n)WorkflowExecutionCompletedEventAttributes\x12\x30\n\x06result\x18\x01 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12(\n workflow_task_completed_event_id\x18\x02 \x01(\x03\x12\x1c\n\x14new_execution_run_id\x18\x03 \x01(\t"\xdb\x01\n&WorkflowExecutionFailedEventAttributes\x12\x31\n\x07\x66\x61ilure\x18\x01 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12\x36\n\x0bretry_state\x18\x02 \x01(\x0e\x32!.temporal.api.enums.v1.RetryState\x12(\n workflow_task_completed_event_id\x18\x03 \x01(\x03\x12\x1c\n\x14new_execution_run_id\x18\x04 \x01(\t"\x80\x01\n(WorkflowExecutionTimedOutEventAttributes\x12\x36\n\x0bretry_state\x18\x01 \x01(\x0e\x32!.temporal.api.enums.v1.RetryState\x12\x1c\n\x14new_execution_run_id\x18\x02 \x01(\t"\xa5\x07\n.WorkflowExecutionContinuedAsNewEventAttributes\x12\x1c\n\x14new_execution_run_id\x18\x01 \x01(\t\x12;\n\rworkflow_type\x18\x02 \x01(\x0b\x32$.temporal.api.common.v1.WorkflowType\x12\x38\n\ntask_queue\x18\x03 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12/\n\x05input\x18\x04 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x37\n\x14workflow_run_timeout\x18\x05 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x38\n\x15workflow_task_timeout\x18\x06 \x01(\x0b\x32\x19.google.protobuf.Duration\x12(\n workflow_task_completed_event_id\x18\x07 \x01(\x03\x12\x39\n\x16\x62\x61\x63koff_start_interval\x18\x08 \x01(\x0b\x32\x19.google.protobuf.Duration\x12@\n\tinitiator\x18\t \x01(\x0e\x32-.temporal.api.enums.v1.ContinueAsNewInitiator\x12\x35\n\x07\x66\x61ilure\x18\n \x01(\x0b\x32 .temporal.api.failure.v1.FailureB\x02\x18\x01\x12@\n\x16last_completion_result\x18\x0b \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12.\n\x06header\x18\x0c \x01(\x0b\x32\x1e.temporal.api.common.v1.Header\x12*\n\x04memo\x18\r \x01(\x0b\x32\x1c.temporal.api.common.v1.Memo\x12\x43\n\x11search_attributes\x18\x0e \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes\x12\x1c\n\x10inherit_build_id\x18\x0f \x01(\x08\x42\x02\x18\x01\x12[\n\x1binitial_versioning_behavior\x18\x10 \x01(\x0e\x32\x36.temporal.api.enums.v1.ContinueAsNewVersioningBehavior"\xac\x01\n$WorkflowTaskScheduledEventAttributes\x12\x38\n\ntask_queue\x18\x01 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12\x39\n\x16start_to_close_timeout\x18\x02 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x0f\n\x07\x61ttempt\x18\x03 \x01(\x05"\xa0\x03\n"WorkflowTaskStartedEventAttributes\x12\x1a\n\x12scheduled_event_id\x18\x01 \x01(\x03\x12\x10\n\x08identity\x18\x02 \x01(\t\x12\x12\n\nrequest_id\x18\x03 \x01(\t\x12\x1f\n\x17suggest_continue_as_new\x18\x04 \x01(\x08\x12Z\n\x1fsuggest_continue_as_new_reasons\x18\x08 \x03(\x0e\x32\x31.temporal.api.enums.v1.SuggestContinueAsNewReason\x12\x30\n(target_worker_deployment_version_changed\x18\t \x01(\x08\x12\x1a\n\x12history_size_bytes\x18\x05 \x01(\x03\x12\x46\n\x0eworker_version\x18\x06 \x01(\x0b\x32*.temporal.api.common.v1.WorkerVersionStampB\x02\x18\x01\x12%\n\x19\x62uild_id_redirect_counter\x18\x07 \x01(\x03\x42\x02\x18\x01"\x82\x05\n$WorkflowTaskCompletedEventAttributes\x12\x1a\n\x12scheduled_event_id\x18\x01 \x01(\x03\x12\x18\n\x10started_event_id\x18\x02 \x01(\x03\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x1b\n\x0f\x62inary_checksum\x18\x04 \x01(\tB\x02\x18\x01\x12\x46\n\x0eworker_version\x18\x05 \x01(\x0b\x32*.temporal.api.common.v1.WorkerVersionStampB\x02\x18\x01\x12H\n\x0csdk_metadata\x18\x06 \x01(\x0b\x32\x32.temporal.api.sdk.v1.WorkflowTaskCompletedMetadata\x12\x43\n\x11metering_metadata\x18\r \x01(\x0b\x32(.temporal.api.common.v1.MeteringMetadata\x12>\n\ndeployment\x18\x07 \x01(\x0b\x32&.temporal.api.deployment.v1.DeploymentB\x02\x18\x01\x12\x46\n\x13versioning_behavior\x18\x08 \x01(\x0e\x32).temporal.api.enums.v1.VersioningBehavior\x12%\n\x19worker_deployment_version\x18\t \x01(\tB\x02\x18\x01\x12\x1e\n\x16worker_deployment_name\x18\n \x01(\t\x12O\n\x12\x64\x65ployment_version\x18\x0b \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersion"\x95\x01\n#WorkflowTaskTimedOutEventAttributes\x12\x1a\n\x12scheduled_event_id\x18\x01 \x01(\x03\x12\x18\n\x10started_event_id\x18\x02 \x01(\x03\x12\x38\n\x0ctimeout_type\x18\x03 \x01(\x0e\x32".temporal.api.enums.v1.TimeoutType"\x87\x03\n!WorkflowTaskFailedEventAttributes\x12\x1a\n\x12scheduled_event_id\x18\x01 \x01(\x03\x12\x18\n\x10started_event_id\x18\x02 \x01(\x03\x12=\n\x05\x63\x61use\x18\x03 \x01(\x0e\x32..temporal.api.enums.v1.WorkflowTaskFailedCause\x12\x31\n\x07\x66\x61ilure\x18\x04 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12\x10\n\x08identity\x18\x05 \x01(\t\x12\x13\n\x0b\x62\x61se_run_id\x18\x06 \x01(\t\x12\x12\n\nnew_run_id\x18\x07 \x01(\t\x12\x1a\n\x12\x66ork_event_version\x18\x08 \x01(\x03\x12\x1b\n\x0f\x62inary_checksum\x18\t \x01(\tB\x02\x18\x01\x12\x46\n\x0eworker_version\x18\n \x01(\x0b\x32*.temporal.api.common.v1.WorkerVersionStampB\x02\x18\x01"\xc2\x05\n$ActivityTaskScheduledEventAttributes\x12\x13\n\x0b\x61\x63tivity_id\x18\x01 \x01(\t\x12;\n\ractivity_type\x18\x02 \x01(\x0b\x32$.temporal.api.common.v1.ActivityType\x12\x38\n\ntask_queue\x18\x04 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12.\n\x06header\x18\x05 \x01(\x0b\x32\x1e.temporal.api.common.v1.Header\x12/\n\x05input\x18\x06 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12<\n\x19schedule_to_close_timeout\x18\x07 \x01(\x0b\x32\x19.google.protobuf.Duration\x12<\n\x19schedule_to_start_timeout\x18\x08 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x39\n\x16start_to_close_timeout\x18\t \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x34\n\x11heartbeat_timeout\x18\n \x01(\x0b\x32\x19.google.protobuf.Duration\x12(\n workflow_task_completed_event_id\x18\x0b \x01(\x03\x12\x39\n\x0cretry_policy\x18\x0c \x01(\x0b\x32#.temporal.api.common.v1.RetryPolicy\x12!\n\x15use_workflow_build_id\x18\r \x01(\x08\x42\x02\x18\x01\x12\x32\n\x08priority\x18\x0e \x01(\x0b\x32 .temporal.api.common.v1.PriorityJ\x04\x08\x03\x10\x04"\x9e\x02\n"ActivityTaskStartedEventAttributes\x12\x1a\n\x12scheduled_event_id\x18\x01 \x01(\x03\x12\x10\n\x08identity\x18\x02 \x01(\t\x12\x12\n\nrequest_id\x18\x03 \x01(\t\x12\x0f\n\x07\x61ttempt\x18\x04 \x01(\x05\x12\x36\n\x0clast_failure\x18\x05 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12\x46\n\x0eworker_version\x18\x06 \x01(\x0b\x32*.temporal.api.common.v1.WorkerVersionStampB\x02\x18\x01\x12%\n\x19\x62uild_id_redirect_counter\x18\x07 \x01(\x03\x42\x02\x18\x01"\xe8\x01\n$ActivityTaskCompletedEventAttributes\x12\x30\n\x06result\x18\x01 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x1a\n\x12scheduled_event_id\x18\x02 \x01(\x03\x12\x18\n\x10started_event_id\x18\x03 \x01(\x03\x12\x10\n\x08identity\x18\x04 \x01(\t\x12\x46\n\x0eworker_version\x18\x05 \x01(\x0b\x32*.temporal.api.common.v1.WorkerVersionStampB\x02\x18\x01"\x9e\x02\n!ActivityTaskFailedEventAttributes\x12\x31\n\x07\x66\x61ilure\x18\x01 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12\x1a\n\x12scheduled_event_id\x18\x02 \x01(\x03\x12\x18\n\x10started_event_id\x18\x03 \x01(\x03\x12\x10\n\x08identity\x18\x04 \x01(\t\x12\x36\n\x0bretry_state\x18\x05 \x01(\x0e\x32!.temporal.api.enums.v1.RetryState\x12\x46\n\x0eworker_version\x18\x06 \x01(\x0b\x32*.temporal.api.common.v1.WorkerVersionStampB\x02\x18\x01"\xc6\x01\n#ActivityTaskTimedOutEventAttributes\x12\x31\n\x07\x66\x61ilure\x18\x01 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12\x1a\n\x12scheduled_event_id\x18\x02 \x01(\x03\x12\x18\n\x10started_event_id\x18\x03 \x01(\x03\x12\x36\n\x0bretry_state\x18\x04 \x01(\x0e\x32!.temporal.api.enums.v1.RetryState"r\n*ActivityTaskCancelRequestedEventAttributes\x12\x1a\n\x12scheduled_event_id\x18\x01 \x01(\x03\x12(\n workflow_task_completed_event_id\x18\x02 \x01(\x03"\x92\x02\n#ActivityTaskCanceledEventAttributes\x12\x31\n\x07\x64\x65tails\x18\x01 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12(\n latest_cancel_requested_event_id\x18\x02 \x01(\x03\x12\x1a\n\x12scheduled_event_id\x18\x03 \x01(\x03\x12\x18\n\x10started_event_id\x18\x04 \x01(\x03\x12\x10\n\x08identity\x18\x05 \x01(\t\x12\x46\n\x0eworker_version\x18\x06 \x01(\x0b\x32*.temporal.api.common.v1.WorkerVersionStampB\x02\x18\x01"\x93\x01\n\x1bTimerStartedEventAttributes\x12\x10\n\x08timer_id\x18\x01 \x01(\t\x12\x38\n\x15start_to_fire_timeout\x18\x02 \x01(\x0b\x32\x19.google.protobuf.Duration\x12(\n workflow_task_completed_event_id\x18\x03 \x01(\x03"G\n\x19TimerFiredEventAttributes\x12\x10\n\x08timer_id\x18\x01 \x01(\t\x12\x18\n\x10started_event_id\x18\x02 \x01(\x03"\x86\x01\n\x1cTimerCanceledEventAttributes\x12\x10\n\x08timer_id\x18\x01 \x01(\t\x12\x18\n\x10started_event_id\x18\x02 \x01(\x03\x12(\n workflow_task_completed_event_id\x18\x03 \x01(\x03\x12\x10\n\x08identity\x18\x04 \x01(\t"\xc7\x01\n/WorkflowExecutionCancelRequestedEventAttributes\x12\r\n\x05\x63\x61use\x18\x01 \x01(\t\x12#\n\x1b\x65xternal_initiated_event_id\x18\x02 \x01(\x03\x12N\n\x1b\x65xternal_workflow_execution\x18\x03 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x10\n\x08identity\x18\x04 \x01(\t"\x87\x01\n(WorkflowExecutionCanceledEventAttributes\x12(\n workflow_task_completed_event_id\x18\x01 \x01(\x03\x12\x31\n\x07\x64\x65tails\x18\x02 \x01(\x0b\x32 .temporal.api.common.v1.Payloads"\xe9\x02\n\x1dMarkerRecordedEventAttributes\x12\x13\n\x0bmarker_name\x18\x01 \x01(\t\x12T\n\x07\x64\x65tails\x18\x02 \x03(\x0b\x32\x43.temporal.api.history.v1.MarkerRecordedEventAttributes.DetailsEntry\x12(\n workflow_task_completed_event_id\x18\x03 \x01(\x03\x12.\n\x06header\x18\x04 \x01(\x0b\x32\x1e.temporal.api.common.v1.Header\x12\x31\n\x07\x66\x61ilure\x18\x05 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x1aP\n\x0c\x44\x65tailsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12/\n\x05value\x18\x02 \x01(\x0b\x32 .temporal.api.common.v1.Payloads:\x02\x38\x01"\xbf\x02\n(WorkflowExecutionSignaledEventAttributes\x12\x13\n\x0bsignal_name\x18\x01 \x01(\t\x12/\n\x05input\x18\x02 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x10\n\x08identity\x18\x03 \x01(\t\x12.\n\x06header\x18\x04 \x01(\x0b\x32\x1e.temporal.api.common.v1.Header\x12\'\n\x1bskip_generate_workflow_task\x18\x05 \x01(\x08\x42\x02\x18\x01\x12N\n\x1b\x65xternal_workflow_execution\x18\x06 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x12\n\nrequest_id\x18\x07 \x01(\t"\x81\x01\n*WorkflowExecutionTerminatedEventAttributes\x12\x0e\n\x06reason\x18\x01 \x01(\t\x12\x31\n\x07\x64\x65tails\x18\x02 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x10\n\x08identity\x18\x03 \x01(\t"\x9c\x02\n>RequestCancelExternalWorkflowExecutionInitiatedEventAttributes\x12(\n workflow_task_completed_event_id\x18\x01 \x01(\x03\x12\x11\n\tnamespace\x18\x02 \x01(\t\x12\x14\n\x0cnamespace_id\x18\x07 \x01(\t\x12\x45\n\x12workflow_execution\x18\x03 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x13\n\x07\x63ontrol\x18\x04 \x01(\tB\x02\x18\x01\x12\x1b\n\x13\x63hild_workflow_only\x18\x05 \x01(\x08\x12\x0e\n\x06reason\x18\x06 \x01(\t"\xda\x02\n;RequestCancelExternalWorkflowExecutionFailedEventAttributes\x12P\n\x05\x63\x61use\x18\x01 \x01(\x0e\x32\x41.temporal.api.enums.v1.CancelExternalWorkflowExecutionFailedCause\x12(\n workflow_task_completed_event_id\x18\x02 \x01(\x03\x12\x11\n\tnamespace\x18\x03 \x01(\t\x12\x14\n\x0cnamespace_id\x18\x07 \x01(\t\x12\x45\n\x12workflow_execution\x18\x04 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x1a\n\x12initiated_event_id\x18\x05 \x01(\x03\x12\x13\n\x07\x63ontrol\x18\x06 \x01(\tB\x02\x18\x01"\xc5\x01\n7ExternalWorkflowExecutionCancelRequestedEventAttributes\x12\x1a\n\x12initiated_event_id\x18\x01 \x01(\x03\x12\x11\n\tnamespace\x18\x02 \x01(\t\x12\x14\n\x0cnamespace_id\x18\x04 \x01(\t\x12\x45\n\x12workflow_execution\x18\x03 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution"\xfb\x02\n7SignalExternalWorkflowExecutionInitiatedEventAttributes\x12(\n workflow_task_completed_event_id\x18\x01 \x01(\x03\x12\x11\n\tnamespace\x18\x02 \x01(\t\x12\x14\n\x0cnamespace_id\x18\t \x01(\t\x12\x45\n\x12workflow_execution\x18\x03 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x13\n\x0bsignal_name\x18\x04 \x01(\t\x12/\n\x05input\x18\x05 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x13\n\x07\x63ontrol\x18\x06 \x01(\tB\x02\x18\x01\x12\x1b\n\x13\x63hild_workflow_only\x18\x07 \x01(\x08\x12.\n\x06header\x18\x08 \x01(\x0b\x32\x1e.temporal.api.common.v1.Header"\xd3\x02\n4SignalExternalWorkflowExecutionFailedEventAttributes\x12P\n\x05\x63\x61use\x18\x01 \x01(\x0e\x32\x41.temporal.api.enums.v1.SignalExternalWorkflowExecutionFailedCause\x12(\n workflow_task_completed_event_id\x18\x02 \x01(\x03\x12\x11\n\tnamespace\x18\x03 \x01(\t\x12\x14\n\x0cnamespace_id\x18\x07 \x01(\t\x12\x45\n\x12workflow_execution\x18\x04 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x1a\n\x12initiated_event_id\x18\x05 \x01(\x03\x12\x13\n\x07\x63ontrol\x18\x06 \x01(\tB\x02\x18\x01"\xd3\x01\n0ExternalWorkflowExecutionSignaledEventAttributes\x12\x1a\n\x12initiated_event_id\x18\x01 \x01(\x03\x12\x11\n\tnamespace\x18\x02 \x01(\t\x12\x14\n\x0cnamespace_id\x18\x05 \x01(\t\x12\x45\n\x12workflow_execution\x18\x03 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x13\n\x07\x63ontrol\x18\x04 \x01(\tB\x02\x18\x01"\x9e\x01\n-UpsertWorkflowSearchAttributesEventAttributes\x12(\n workflow_task_completed_event_id\x18\x01 \x01(\x03\x12\x43\n\x11search_attributes\x18\x02 \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes"\x8a\x01\n)WorkflowPropertiesModifiedEventAttributes\x12(\n workflow_task_completed_event_id\x18\x01 \x01(\x03\x12\x33\n\rupserted_memo\x18\x02 \x01(\x0b\x32\x1c.temporal.api.common.v1.Memo"\xfc\t\n3StartChildWorkflowExecutionInitiatedEventAttributes\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x14\n\x0cnamespace_id\x18\x12 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12;\n\rworkflow_type\x18\x03 \x01(\x0b\x32$.temporal.api.common.v1.WorkflowType\x12\x38\n\ntask_queue\x18\x04 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12/\n\x05input\x18\x05 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12=\n\x1aworkflow_execution_timeout\x18\x06 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x37\n\x14workflow_run_timeout\x18\x07 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x38\n\x15workflow_task_timeout\x18\x08 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x45\n\x13parent_close_policy\x18\t \x01(\x0e\x32(.temporal.api.enums.v1.ParentClosePolicy\x12\x13\n\x07\x63ontrol\x18\n \x01(\tB\x02\x18\x01\x12(\n workflow_task_completed_event_id\x18\x0b \x01(\x03\x12N\n\x18workflow_id_reuse_policy\x18\x0c \x01(\x0e\x32,.temporal.api.enums.v1.WorkflowIdReusePolicy\x12\x39\n\x0cretry_policy\x18\r \x01(\x0b\x32#.temporal.api.common.v1.RetryPolicy\x12\x15\n\rcron_schedule\x18\x0e \x01(\t\x12.\n\x06header\x18\x0f \x01(\x0b\x32\x1e.temporal.api.common.v1.Header\x12*\n\x04memo\x18\x10 \x01(\x0b\x32\x1c.temporal.api.common.v1.Memo\x12\x43\n\x11search_attributes\x18\x11 \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes\x12\x1c\n\x10inherit_build_id\x18\x13 \x01(\x08\x42\x02\x18\x01\x12\x32\n\x08priority\x18\x14 \x01(\x0b\x32 .temporal.api.common.v1.Priority\x12H\n\x14time_skipping_config\x18\x15 \x01(\x0b\x32*.temporal.api.common.v1.TimeSkippingConfig\x12]\n\x1ftime_skipping_state_propagation\x18\x17 \x01(\x0b\x32\x34.temporal.api.common.v1.TimeSkippingStatePropagation\x12I\n\x13versioning_override\x18\x18 \x01(\x0b\x32,.temporal.api.workflow.v1.VersioningOverrideJ\x04\x08\x16\x10\x17R\x18initial_skipped_duration"\xd6\x02\n0StartChildWorkflowExecutionFailedEventAttributes\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x14\n\x0cnamespace_id\x18\x08 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12;\n\rworkflow_type\x18\x03 \x01(\x0b\x32$.temporal.api.common.v1.WorkflowType\x12L\n\x05\x63\x61use\x18\x04 \x01(\x0e\x32=.temporal.api.enums.v1.StartChildWorkflowExecutionFailedCause\x12\x13\n\x07\x63ontrol\x18\x05 \x01(\tB\x02\x18\x01\x12\x1a\n\x12initiated_event_id\x18\x06 \x01(\x03\x12(\n workflow_task_completed_event_id\x18\x07 \x01(\x03"\xa7\x02\n,ChildWorkflowExecutionStartedEventAttributes\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x14\n\x0cnamespace_id\x18\x06 \x01(\t\x12\x1a\n\x12initiated_event_id\x18\x02 \x01(\x03\x12\x45\n\x12workflow_execution\x18\x03 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12;\n\rworkflow_type\x18\x04 \x01(\x0b\x32$.temporal.api.common.v1.WorkflowType\x12.\n\x06header\x18\x05 \x01(\x0b\x32\x1e.temporal.api.common.v1.Header"\xc5\x02\n.ChildWorkflowExecutionCompletedEventAttributes\x12\x30\n\x06result\x18\x01 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x11\n\tnamespace\x18\x02 \x01(\t\x12\x14\n\x0cnamespace_id\x18\x07 \x01(\t\x12\x45\n\x12workflow_execution\x18\x03 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12;\n\rworkflow_type\x18\x04 \x01(\x0b\x32$.temporal.api.common.v1.WorkflowType\x12\x1a\n\x12initiated_event_id\x18\x05 \x01(\x03\x12\x18\n\x10started_event_id\x18\x06 \x01(\x03"\xfb\x02\n+ChildWorkflowExecutionFailedEventAttributes\x12\x31\n\x07\x66\x61ilure\x18\x01 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12\x11\n\tnamespace\x18\x02 \x01(\t\x12\x14\n\x0cnamespace_id\x18\x08 \x01(\t\x12\x45\n\x12workflow_execution\x18\x03 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12;\n\rworkflow_type\x18\x04 \x01(\x0b\x32$.temporal.api.common.v1.WorkflowType\x12\x1a\n\x12initiated_event_id\x18\x05 \x01(\x03\x12\x18\n\x10started_event_id\x18\x06 \x01(\x03\x12\x36\n\x0bretry_state\x18\x07 \x01(\x0e\x32!.temporal.api.enums.v1.RetryState"\xc5\x02\n-ChildWorkflowExecutionCanceledEventAttributes\x12\x31\n\x07\x64\x65tails\x18\x01 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x11\n\tnamespace\x18\x02 \x01(\t\x12\x14\n\x0cnamespace_id\x18\x07 \x01(\t\x12\x45\n\x12workflow_execution\x18\x03 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12;\n\rworkflow_type\x18\x04 \x01(\x0b\x32$.temporal.api.common.v1.WorkflowType\x12\x1a\n\x12initiated_event_id\x18\x05 \x01(\x03\x12\x18\n\x10started_event_id\x18\x06 \x01(\x03"\xca\x02\n-ChildWorkflowExecutionTimedOutEventAttributes\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x14\n\x0cnamespace_id\x18\x07 \x01(\t\x12\x45\n\x12workflow_execution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12;\n\rworkflow_type\x18\x03 \x01(\x0b\x32$.temporal.api.common.v1.WorkflowType\x12\x1a\n\x12initiated_event_id\x18\x04 \x01(\x03\x12\x18\n\x10started_event_id\x18\x05 \x01(\x03\x12\x36\n\x0bretry_state\x18\x06 \x01(\x0e\x32!.temporal.api.enums.v1.RetryState"\x94\x02\n/ChildWorkflowExecutionTerminatedEventAttributes\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x14\n\x0cnamespace_id\x18\x06 \x01(\t\x12\x45\n\x12workflow_execution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12;\n\rworkflow_type\x18\x03 \x01(\x0b\x32$.temporal.api.common.v1.WorkflowType\x12\x1a\n\x12initiated_event_id\x18\x04 \x01(\x03\x12\x18\n\x10started_event_id\x18\x05 \x01(\x03"\xda\x05\n.WorkflowExecutionOptionsUpdatedEventAttributes\x12I\n\x13versioning_override\x18\x01 \x01(\x0b\x32,.temporal.api.workflow.v1.VersioningOverride\x12!\n\x19unset_versioning_override\x18\x02 \x01(\x08\x12\x1b\n\x13\x61ttached_request_id\x18\x03 \x01(\t\x12G\n\x1d\x61ttached_completion_callbacks\x18\x04 \x03(\x0b\x32 .temporal.api.common.v1.Callback\x12\x10\n\x08identity\x18\x05 \x01(\t\x12\x32\n\x08priority\x18\x06 \x01(\x0b\x32 .temporal.api.common.v1.Priority\x12H\n\x14time_skipping_config\x18\x07 \x01(\x0b\x32*.temporal.api.common.v1.TimeSkippingConfig\x12$\n\x1ctime_skipping_config_updated\x18\t \x01(\x08\x12\x84\x01\n\x17workflow_update_options\x18\x08 \x03(\x0b\x32\x63.temporal.api.history.v1.WorkflowExecutionOptionsUpdatedEventAttributes.WorkflowUpdateOptionsUpdate\x1a\x96\x01\n\x1bWorkflowUpdateOptionsUpdate\x12\x11\n\tupdate_id\x18\x01 \x01(\t\x12\x1b\n\x13\x61ttached_request_id\x18\x02 \x01(\t\x12G\n\x1d\x61ttached_completion_callbacks\x18\x03 \x03(\x0b\x32 .temporal.api.common.v1.Callback"\xc0\x02\n3WorkflowPropertiesModifiedExternallyEventAttributes\x12\x16\n\x0enew_task_queue\x18\x01 \x01(\t\x12<\n\x19new_workflow_task_timeout\x18\x02 \x01(\x0b\x32\x19.google.protobuf.Duration\x12;\n\x18new_workflow_run_timeout\x18\x03 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x41\n\x1enew_workflow_execution_timeout\x18\x04 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x33\n\rupserted_memo\x18\x05 \x01(\x0b\x32\x1c.temporal.api.common.v1.Memo"\x90\x01\n3ActivityPropertiesModifiedExternallyEventAttributes\x12\x1a\n\x12scheduled_event_id\x18\x01 \x01(\x03\x12=\n\x10new_retry_policy\x18\x02 \x01(\x0b\x32#.temporal.api.common.v1.RetryPolicy"\xdc\x01\n.WorkflowExecutionUpdateAcceptedEventAttributes\x12\x1c\n\x14protocol_instance_id\x18\x01 \x01(\t\x12#\n\x1b\x61\x63\x63\x65pted_request_message_id\x18\x02 \x01(\t\x12,\n$accepted_request_sequencing_event_id\x18\x03 \x01(\x03\x12\x39\n\x10\x61\x63\x63\x65pted_request\x18\x04 \x01(\x0b\x32\x1f.temporal.api.update.v1.Request"\xaa\x01\n/WorkflowExecutionUpdateCompletedEventAttributes\x12*\n\x04meta\x18\x01 \x01(\x0b\x32\x1c.temporal.api.update.v1.Meta\x12\x19\n\x11\x61\x63\x63\x65pted_event_id\x18\x03 \x01(\x03\x12\x30\n\x07outcome\x18\x02 \x01(\x0b\x32\x1f.temporal.api.update.v1.Outcome"\x8f\x02\n.WorkflowExecutionUpdateRejectedEventAttributes\x12\x1c\n\x14protocol_instance_id\x18\x01 \x01(\t\x12#\n\x1brejected_request_message_id\x18\x02 \x01(\t\x12,\n$rejected_request_sequencing_event_id\x18\x03 \x01(\x03\x12\x39\n\x10rejected_request\x18\x04 \x01(\x0b\x32\x1f.temporal.api.update.v1.Request\x12\x31\n\x07\x66\x61ilure\x18\x05 \x01(\x0b\x32 .temporal.api.failure.v1.Failure"\xa4\x01\n.WorkflowExecutionUpdateAdmittedEventAttributes\x12\x30\n\x07request\x18\x01 \x01(\x0b\x32\x1f.temporal.api.update.v1.Request\x12@\n\x06origin\x18\x02 \x01(\x0e\x32\x30.temporal.api.enums.v1.UpdateAdmittedEventOrigin"^\n&WorkflowExecutionPausedEventAttributes\x12\x10\n\x08identity\x18\x01 \x01(\t\x12\x0e\n\x06reason\x18\x02 \x01(\t\x12\x12\n\nrequest_id\x18\x03 \x01(\t"`\n(WorkflowExecutionUnpausedEventAttributes\x12\x10\n\x08identity\x18\x01 \x01(\t\x12\x0e\n\x06reason\x18\x02 \x01(\t\x12\x12\n\nrequest_id\x18\x03 \x01(\t"\xc5\x01\n8WorkflowExecutionTimeSkippingTransitionedEventAttributes\x12/\n\x0btarget_time\x18\x01 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12#\n\x1b\x64isabled_after_fast_forward\x18\x02 \x01(\x08\x12\x33\n\x0fwall_clock_time\x18\x03 \x01(\x0b\x32\x1a.google.protobuf.Timestamp"\xb4\x04\n&NexusOperationScheduledEventAttributes\x12\x10\n\x08\x65ndpoint\x18\x01 \x01(\t\x12\x0f\n\x07service\x18\x02 \x01(\t\x12\x11\n\toperation\x18\x03 \x01(\t\x12.\n\x05input\x18\x04 \x01(\x0b\x32\x1f.temporal.api.common.v1.Payload\x12<\n\x19schedule_to_close_timeout\x18\x05 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x66\n\x0cnexus_header\x18\x06 \x03(\x0b\x32P.temporal.api.history.v1.NexusOperationScheduledEventAttributes.NexusHeaderEntry\x12(\n workflow_task_completed_event_id\x18\x07 \x01(\x03\x12\x12\n\nrequest_id\x18\x08 \x01(\t\x12\x13\n\x0b\x65ndpoint_id\x18\t \x01(\t\x12<\n\x19schedule_to_start_timeout\x18\n \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x39\n\x16start_to_close_timeout\x18\x0b \x01(\x0b\x32\x19.google.protobuf.Duration\x1a\x32\n\x10NexusHeaderEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01"\x89\x01\n$NexusOperationStartedEventAttributes\x12\x1a\n\x12scheduled_event_id\x18\x01 \x01(\x03\x12\x18\n\x0coperation_id\x18\x03 \x01(\tB\x02\x18\x01\x12\x12\n\nrequest_id\x18\x04 \x01(\t\x12\x17\n\x0foperation_token\x18\x05 \x01(\t"\x89\x01\n&NexusOperationCompletedEventAttributes\x12\x1a\n\x12scheduled_event_id\x18\x01 \x01(\x03\x12/\n\x06result\x18\x02 \x01(\x0b\x32\x1f.temporal.api.common.v1.Payload\x12\x12\n\nrequest_id\x18\x03 \x01(\t"\x88\x01\n#NexusOperationFailedEventAttributes\x12\x1a\n\x12scheduled_event_id\x18\x01 \x01(\x03\x12\x31\n\x07\x66\x61ilure\x18\x02 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12\x12\n\nrequest_id\x18\x03 \x01(\t"\x8a\x01\n%NexusOperationTimedOutEventAttributes\x12\x1a\n\x12scheduled_event_id\x18\x01 \x01(\x03\x12\x31\n\x07\x66\x61ilure\x18\x02 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12\x12\n\nrequest_id\x18\x03 \x01(\t"\x8a\x01\n%NexusOperationCanceledEventAttributes\x12\x1a\n\x12scheduled_event_id\x18\x01 \x01(\x03\x12\x31\n\x07\x66\x61ilure\x18\x02 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12\x12\n\nrequest_id\x18\x03 \x01(\t"t\n,NexusOperationCancelRequestedEventAttributes\x12\x1a\n\x12scheduled_event_id\x18\x01 \x01(\x03\x12(\n workflow_task_completed_event_id\x18\x02 \x01(\x03"\x97\x01\n3NexusOperationCancelRequestCompletedEventAttributes\x12\x1a\n\x12requested_event_id\x18\x01 \x01(\x03\x12(\n workflow_task_completed_event_id\x18\x02 \x01(\x03\x12\x1a\n\x12scheduled_event_id\x18\x03 \x01(\x03"\xc7\x01\n0NexusOperationCancelRequestFailedEventAttributes\x12\x1a\n\x12requested_event_id\x18\x01 \x01(\x03\x12(\n workflow_task_completed_event_id\x18\x02 \x01(\x03\x12\x31\n\x07\x66\x61ilure\x18\x03 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12\x1a\n\x12scheduled_event_id\x18\x04 \x01(\x03"\xca?\n\x0cHistoryEvent\x12\x10\n\x08\x65vent_id\x18\x01 \x01(\x03\x12.\n\nevent_time\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x34\n\nevent_type\x18\x03 \x01(\x0e\x32 .temporal.api.enums.v1.EventType\x12\x0f\n\x07version\x18\x04 \x01(\x03\x12\x0f\n\x07task_id\x18\x05 \x01(\x03\x12\x1a\n\x11worker_may_ignore\x18\xac\x02 \x01(\x08\x12\x39\n\ruser_metadata\x18\xad\x02 \x01(\x0b\x32!.temporal.api.sdk.v1.UserMetadata\x12,\n\x05links\x18\xae\x02 \x03(\x0b\x32\x1c.temporal.api.common.v1.Link\x12\x35\n\tprincipal\x18\xaf\x02 \x01(\x0b\x32!.temporal.api.common.v1.Principal\x12\x43\n\x13\x65vent_group_markers\x18\xb0\x02 \x03(\x0b\x32%.temporal.api.sdk.v1.EventGroupMarker\x12w\n+workflow_execution_started_event_attributes\x18\x06 \x01(\x0b\x32@.temporal.api.history.v1.WorkflowExecutionStartedEventAttributesH\x00\x12{\n-workflow_execution_completed_event_attributes\x18\x07 \x01(\x0b\x32\x42.temporal.api.history.v1.WorkflowExecutionCompletedEventAttributesH\x00\x12u\n*workflow_execution_failed_event_attributes\x18\x08 \x01(\x0b\x32?.temporal.api.history.v1.WorkflowExecutionFailedEventAttributesH\x00\x12z\n-workflow_execution_timed_out_event_attributes\x18\t \x01(\x0b\x32\x41.temporal.api.history.v1.WorkflowExecutionTimedOutEventAttributesH\x00\x12q\n(workflow_task_scheduled_event_attributes\x18\n \x01(\x0b\x32=.temporal.api.history.v1.WorkflowTaskScheduledEventAttributesH\x00\x12m\n&workflow_task_started_event_attributes\x18\x0b \x01(\x0b\x32;.temporal.api.history.v1.WorkflowTaskStartedEventAttributesH\x00\x12q\n(workflow_task_completed_event_attributes\x18\x0c \x01(\x0b\x32=.temporal.api.history.v1.WorkflowTaskCompletedEventAttributesH\x00\x12p\n(workflow_task_timed_out_event_attributes\x18\r \x01(\x0b\x32<.temporal.api.history.v1.WorkflowTaskTimedOutEventAttributesH\x00\x12k\n%workflow_task_failed_event_attributes\x18\x0e \x01(\x0b\x32:.temporal.api.history.v1.WorkflowTaskFailedEventAttributesH\x00\x12q\n(activity_task_scheduled_event_attributes\x18\x0f \x01(\x0b\x32=.temporal.api.history.v1.ActivityTaskScheduledEventAttributesH\x00\x12m\n&activity_task_started_event_attributes\x18\x10 \x01(\x0b\x32;.temporal.api.history.v1.ActivityTaskStartedEventAttributesH\x00\x12q\n(activity_task_completed_event_attributes\x18\x11 \x01(\x0b\x32=.temporal.api.history.v1.ActivityTaskCompletedEventAttributesH\x00\x12k\n%activity_task_failed_event_attributes\x18\x12 \x01(\x0b\x32:.temporal.api.history.v1.ActivityTaskFailedEventAttributesH\x00\x12p\n(activity_task_timed_out_event_attributes\x18\x13 \x01(\x0b\x32<.temporal.api.history.v1.ActivityTaskTimedOutEventAttributesH\x00\x12^\n\x1etimer_started_event_attributes\x18\x14 \x01(\x0b\x32\x34.temporal.api.history.v1.TimerStartedEventAttributesH\x00\x12Z\n\x1ctimer_fired_event_attributes\x18\x15 \x01(\x0b\x32\x32.temporal.api.history.v1.TimerFiredEventAttributesH\x00\x12~\n/activity_task_cancel_requested_event_attributes\x18\x16 \x01(\x0b\x32\x43.temporal.api.history.v1.ActivityTaskCancelRequestedEventAttributesH\x00\x12o\n\'activity_task_canceled_event_attributes\x18\x17 \x01(\x0b\x32<.temporal.api.history.v1.ActivityTaskCanceledEventAttributesH\x00\x12`\n\x1ftimer_canceled_event_attributes\x18\x18 \x01(\x0b\x32\x35.temporal.api.history.v1.TimerCanceledEventAttributesH\x00\x12\x62\n marker_recorded_event_attributes\x18\x19 \x01(\x0b\x32\x36.temporal.api.history.v1.MarkerRecordedEventAttributesH\x00\x12y\n,workflow_execution_signaled_event_attributes\x18\x1a \x01(\x0b\x32\x41.temporal.api.history.v1.WorkflowExecutionSignaledEventAttributesH\x00\x12}\n.workflow_execution_terminated_event_attributes\x18\x1b \x01(\x0b\x32\x43.temporal.api.history.v1.WorkflowExecutionTerminatedEventAttributesH\x00\x12\x88\x01\n4workflow_execution_cancel_requested_event_attributes\x18\x1c \x01(\x0b\x32H.temporal.api.history.v1.WorkflowExecutionCancelRequestedEventAttributesH\x00\x12y\n,workflow_execution_canceled_event_attributes\x18\x1d \x01(\x0b\x32\x41.temporal.api.history.v1.WorkflowExecutionCanceledEventAttributesH\x00\x12\xa8\x01\nErequest_cancel_external_workflow_execution_initiated_event_attributes\x18\x1e \x01(\x0b\x32W.temporal.api.history.v1.RequestCancelExternalWorkflowExecutionInitiatedEventAttributesH\x00\x12\xa2\x01\nBrequest_cancel_external_workflow_execution_failed_event_attributes\x18\x1f \x01(\x0b\x32T.temporal.api.history.v1.RequestCancelExternalWorkflowExecutionFailedEventAttributesH\x00\x12\x99\x01\n=external_workflow_execution_cancel_requested_event_attributes\x18 \x01(\x0b\x32P.temporal.api.history.v1.ExternalWorkflowExecutionCancelRequestedEventAttributesH\x00\x12\x87\x01\n4workflow_execution_continued_as_new_event_attributes\x18! \x01(\x0b\x32G.temporal.api.history.v1.WorkflowExecutionContinuedAsNewEventAttributesH\x00\x12\x91\x01\n9start_child_workflow_execution_initiated_event_attributes\x18" \x01(\x0b\x32L.temporal.api.history.v1.StartChildWorkflowExecutionInitiatedEventAttributesH\x00\x12\x8b\x01\n6start_child_workflow_execution_failed_event_attributes\x18# \x01(\x0b\x32I.temporal.api.history.v1.StartChildWorkflowExecutionFailedEventAttributesH\x00\x12\x82\x01\n1child_workflow_execution_started_event_attributes\x18$ \x01(\x0b\x32\x45.temporal.api.history.v1.ChildWorkflowExecutionStartedEventAttributesH\x00\x12\x86\x01\n3child_workflow_execution_completed_event_attributes\x18% \x01(\x0b\x32G.temporal.api.history.v1.ChildWorkflowExecutionCompletedEventAttributesH\x00\x12\x80\x01\n0child_workflow_execution_failed_event_attributes\x18& \x01(\x0b\x32\x44.temporal.api.history.v1.ChildWorkflowExecutionFailedEventAttributesH\x00\x12\x84\x01\n2child_workflow_execution_canceled_event_attributes\x18\' \x01(\x0b\x32\x46.temporal.api.history.v1.ChildWorkflowExecutionCanceledEventAttributesH\x00\x12\x85\x01\n3child_workflow_execution_timed_out_event_attributes\x18( \x01(\x0b\x32\x46.temporal.api.history.v1.ChildWorkflowExecutionTimedOutEventAttributesH\x00\x12\x88\x01\n4child_workflow_execution_terminated_event_attributes\x18) \x01(\x0b\x32H.temporal.api.history.v1.ChildWorkflowExecutionTerminatedEventAttributesH\x00\x12\x99\x01\n=signal_external_workflow_execution_initiated_event_attributes\x18* \x01(\x0b\x32P.temporal.api.history.v1.SignalExternalWorkflowExecutionInitiatedEventAttributesH\x00\x12\x93\x01\n:signal_external_workflow_execution_failed_event_attributes\x18+ \x01(\x0b\x32M.temporal.api.history.v1.SignalExternalWorkflowExecutionFailedEventAttributesH\x00\x12\x8a\x01\n5external_workflow_execution_signaled_event_attributes\x18, \x01(\x0b\x32I.temporal.api.history.v1.ExternalWorkflowExecutionSignaledEventAttributesH\x00\x12\x84\x01\n2upsert_workflow_search_attributes_event_attributes\x18- \x01(\x0b\x32\x46.temporal.api.history.v1.UpsertWorkflowSearchAttributesEventAttributesH\x00\x12\x86\x01\n3workflow_execution_update_accepted_event_attributes\x18. \x01(\x0b\x32G.temporal.api.history.v1.WorkflowExecutionUpdateAcceptedEventAttributesH\x00\x12\x86\x01\n3workflow_execution_update_rejected_event_attributes\x18/ \x01(\x0b\x32G.temporal.api.history.v1.WorkflowExecutionUpdateRejectedEventAttributesH\x00\x12\x88\x01\n4workflow_execution_update_completed_event_attributes\x18\x30 \x01(\x0b\x32H.temporal.api.history.v1.WorkflowExecutionUpdateCompletedEventAttributesH\x00\x12\x90\x01\n8workflow_properties_modified_externally_event_attributes\x18\x31 \x01(\x0b\x32L.temporal.api.history.v1.WorkflowPropertiesModifiedExternallyEventAttributesH\x00\x12\x90\x01\n8activity_properties_modified_externally_event_attributes\x18\x32 \x01(\x0b\x32L.temporal.api.history.v1.ActivityPropertiesModifiedExternallyEventAttributesH\x00\x12{\n-workflow_properties_modified_event_attributes\x18\x33 \x01(\x0b\x32\x42.temporal.api.history.v1.WorkflowPropertiesModifiedEventAttributesH\x00\x12\x86\x01\n3workflow_execution_update_admitted_event_attributes\x18\x34 \x01(\x0b\x32G.temporal.api.history.v1.WorkflowExecutionUpdateAdmittedEventAttributesH\x00\x12u\n*nexus_operation_scheduled_event_attributes\x18\x35 \x01(\x0b\x32?.temporal.api.history.v1.NexusOperationScheduledEventAttributesH\x00\x12q\n(nexus_operation_started_event_attributes\x18\x36 \x01(\x0b\x32=.temporal.api.history.v1.NexusOperationStartedEventAttributesH\x00\x12u\n*nexus_operation_completed_event_attributes\x18\x37 \x01(\x0b\x32?.temporal.api.history.v1.NexusOperationCompletedEventAttributesH\x00\x12o\n\'nexus_operation_failed_event_attributes\x18\x38 \x01(\x0b\x32<.temporal.api.history.v1.NexusOperationFailedEventAttributesH\x00\x12s\n)nexus_operation_canceled_event_attributes\x18\x39 \x01(\x0b\x32>.temporal.api.history.v1.NexusOperationCanceledEventAttributesH\x00\x12t\n*nexus_operation_timed_out_event_attributes\x18: \x01(\x0b\x32>.temporal.api.history.v1.NexusOperationTimedOutEventAttributesH\x00\x12\x82\x01\n1nexus_operation_cancel_requested_event_attributes\x18; \x01(\x0b\x32\x45.temporal.api.history.v1.NexusOperationCancelRequestedEventAttributesH\x00\x12\x86\x01\n3workflow_execution_options_updated_event_attributes\x18< \x01(\x0b\x32G.temporal.api.history.v1.WorkflowExecutionOptionsUpdatedEventAttributesH\x00\x12\x91\x01\n9nexus_operation_cancel_request_completed_event_attributes\x18= \x01(\x0b\x32L.temporal.api.history.v1.NexusOperationCancelRequestCompletedEventAttributesH\x00\x12\x8b\x01\n6nexus_operation_cancel_request_failed_event_attributes\x18> \x01(\x0b\x32I.temporal.api.history.v1.NexusOperationCancelRequestFailedEventAttributesH\x00\x12u\n*workflow_execution_paused_event_attributes\x18? \x01(\x0b\x32?.temporal.api.history.v1.WorkflowExecutionPausedEventAttributesH\x00\x12y\n,workflow_execution_unpaused_event_attributes\x18@ \x01(\x0b\x32\x41.temporal.api.history.v1.WorkflowExecutionUnpausedEventAttributesH\x00\x12\x9b\x01\n>workflow_execution_time_skipping_transitioned_event_attributes\x18\x41 \x01(\x0b\x32Q.temporal.api.history.v1.WorkflowExecutionTimeSkippingTransitionedEventAttributesH\x00\x42\x0c\n\nattributes"@\n\x07History\x12\x35\n\x06\x65vents\x18\x01 \x03(\x0b\x32%.temporal.api.history.v1.HistoryEventB\x8e\x01\n\x1aio.temporal.api.history.v1B\x0cMessageProtoP\x01Z%go.temporal.io/api/history/v1;history\xaa\x02\x19Temporalio.Api.History.V1\xea\x02\x1cTemporalio::Api::History::V1b\x06proto3' ) @@ -1285,65 +1285,65 @@ _WORKFLOWPROPERTIESMODIFIEDEVENTATTRIBUTES._serialized_start = 12010 _WORKFLOWPROPERTIESMODIFIEDEVENTATTRIBUTES._serialized_end = 12148 _STARTCHILDWORKFLOWEXECUTIONINITIATEDEVENTATTRIBUTES._serialized_start = 12151 - _STARTCHILDWORKFLOWEXECUTIONINITIATEDEVENTATTRIBUTES._serialized_end = 13352 - _STARTCHILDWORKFLOWEXECUTIONFAILEDEVENTATTRIBUTES._serialized_start = 13355 - _STARTCHILDWORKFLOWEXECUTIONFAILEDEVENTATTRIBUTES._serialized_end = 13697 - _CHILDWORKFLOWEXECUTIONSTARTEDEVENTATTRIBUTES._serialized_start = 13700 - _CHILDWORKFLOWEXECUTIONSTARTEDEVENTATTRIBUTES._serialized_end = 13995 - _CHILDWORKFLOWEXECUTIONCOMPLETEDEVENTATTRIBUTES._serialized_start = 13998 - _CHILDWORKFLOWEXECUTIONCOMPLETEDEVENTATTRIBUTES._serialized_end = 14323 - _CHILDWORKFLOWEXECUTIONFAILEDEVENTATTRIBUTES._serialized_start = 14326 - _CHILDWORKFLOWEXECUTIONFAILEDEVENTATTRIBUTES._serialized_end = 14705 - _CHILDWORKFLOWEXECUTIONCANCELEDEVENTATTRIBUTES._serialized_start = 14708 - _CHILDWORKFLOWEXECUTIONCANCELEDEVENTATTRIBUTES._serialized_end = 15033 - _CHILDWORKFLOWEXECUTIONTIMEDOUTEVENTATTRIBUTES._serialized_start = 15036 - _CHILDWORKFLOWEXECUTIONTIMEDOUTEVENTATTRIBUTES._serialized_end = 15366 - _CHILDWORKFLOWEXECUTIONTERMINATEDEVENTATTRIBUTES._serialized_start = 15369 - _CHILDWORKFLOWEXECUTIONTERMINATEDEVENTATTRIBUTES._serialized_end = 15645 - _WORKFLOWEXECUTIONOPTIONSUPDATEDEVENTATTRIBUTES._serialized_start = 15648 - _WORKFLOWEXECUTIONOPTIONSUPDATEDEVENTATTRIBUTES._serialized_end = 16378 - _WORKFLOWEXECUTIONOPTIONSUPDATEDEVENTATTRIBUTES_WORKFLOWUPDATEOPTIONSUPDATE._serialized_start = 16228 - _WORKFLOWEXECUTIONOPTIONSUPDATEDEVENTATTRIBUTES_WORKFLOWUPDATEOPTIONSUPDATE._serialized_end = 16378 - _WORKFLOWPROPERTIESMODIFIEDEXTERNALLYEVENTATTRIBUTES._serialized_start = 16381 - _WORKFLOWPROPERTIESMODIFIEDEXTERNALLYEVENTATTRIBUTES._serialized_end = 16701 - _ACTIVITYPROPERTIESMODIFIEDEXTERNALLYEVENTATTRIBUTES._serialized_start = 16704 - _ACTIVITYPROPERTIESMODIFIEDEXTERNALLYEVENTATTRIBUTES._serialized_end = 16848 - _WORKFLOWEXECUTIONUPDATEACCEPTEDEVENTATTRIBUTES._serialized_start = 16851 - _WORKFLOWEXECUTIONUPDATEACCEPTEDEVENTATTRIBUTES._serialized_end = 17071 - _WORKFLOWEXECUTIONUPDATECOMPLETEDEVENTATTRIBUTES._serialized_start = 17074 - _WORKFLOWEXECUTIONUPDATECOMPLETEDEVENTATTRIBUTES._serialized_end = 17244 - _WORKFLOWEXECUTIONUPDATEREJECTEDEVENTATTRIBUTES._serialized_start = 17247 - _WORKFLOWEXECUTIONUPDATEREJECTEDEVENTATTRIBUTES._serialized_end = 17518 - _WORKFLOWEXECUTIONUPDATEADMITTEDEVENTATTRIBUTES._serialized_start = 17521 - _WORKFLOWEXECUTIONUPDATEADMITTEDEVENTATTRIBUTES._serialized_end = 17685 - _WORKFLOWEXECUTIONPAUSEDEVENTATTRIBUTES._serialized_start = 17687 - _WORKFLOWEXECUTIONPAUSEDEVENTATTRIBUTES._serialized_end = 17781 - _WORKFLOWEXECUTIONUNPAUSEDEVENTATTRIBUTES._serialized_start = 17783 - _WORKFLOWEXECUTIONUNPAUSEDEVENTATTRIBUTES._serialized_end = 17879 - _WORKFLOWEXECUTIONTIMESKIPPINGTRANSITIONEDEVENTATTRIBUTES._serialized_start = 17882 - _WORKFLOWEXECUTIONTIMESKIPPINGTRANSITIONEDEVENTATTRIBUTES._serialized_end = 18079 - _NEXUSOPERATIONSCHEDULEDEVENTATTRIBUTES._serialized_start = 18082 - _NEXUSOPERATIONSCHEDULEDEVENTATTRIBUTES._serialized_end = 18646 - _NEXUSOPERATIONSCHEDULEDEVENTATTRIBUTES_NEXUSHEADERENTRY._serialized_start = 18596 - _NEXUSOPERATIONSCHEDULEDEVENTATTRIBUTES_NEXUSHEADERENTRY._serialized_end = 18646 - _NEXUSOPERATIONSTARTEDEVENTATTRIBUTES._serialized_start = 18649 - _NEXUSOPERATIONSTARTEDEVENTATTRIBUTES._serialized_end = 18786 - _NEXUSOPERATIONCOMPLETEDEVENTATTRIBUTES._serialized_start = 18789 - _NEXUSOPERATIONCOMPLETEDEVENTATTRIBUTES._serialized_end = 18926 - _NEXUSOPERATIONFAILEDEVENTATTRIBUTES._serialized_start = 18929 - _NEXUSOPERATIONFAILEDEVENTATTRIBUTES._serialized_end = 19065 - _NEXUSOPERATIONTIMEDOUTEVENTATTRIBUTES._serialized_start = 19068 - _NEXUSOPERATIONTIMEDOUTEVENTATTRIBUTES._serialized_end = 19206 - _NEXUSOPERATIONCANCELEDEVENTATTRIBUTES._serialized_start = 19209 - _NEXUSOPERATIONCANCELEDEVENTATTRIBUTES._serialized_end = 19347 - _NEXUSOPERATIONCANCELREQUESTEDEVENTATTRIBUTES._serialized_start = 19349 - _NEXUSOPERATIONCANCELREQUESTEDEVENTATTRIBUTES._serialized_end = 19465 - _NEXUSOPERATIONCANCELREQUESTCOMPLETEDEVENTATTRIBUTES._serialized_start = 19468 - _NEXUSOPERATIONCANCELREQUESTCOMPLETEDEVENTATTRIBUTES._serialized_end = 19619 - _NEXUSOPERATIONCANCELREQUESTFAILEDEVENTATTRIBUTES._serialized_start = 19622 - _NEXUSOPERATIONCANCELREQUESTFAILEDEVENTATTRIBUTES._serialized_end = 19821 - _HISTORYEVENT._serialized_start = 19824 - _HISTORYEVENT._serialized_end = 27962 - _HISTORY._serialized_start = 27964 - _HISTORY._serialized_end = 28028 + _STARTCHILDWORKFLOWEXECUTIONINITIATEDEVENTATTRIBUTES._serialized_end = 13427 + _STARTCHILDWORKFLOWEXECUTIONFAILEDEVENTATTRIBUTES._serialized_start = 13430 + _STARTCHILDWORKFLOWEXECUTIONFAILEDEVENTATTRIBUTES._serialized_end = 13772 + _CHILDWORKFLOWEXECUTIONSTARTEDEVENTATTRIBUTES._serialized_start = 13775 + _CHILDWORKFLOWEXECUTIONSTARTEDEVENTATTRIBUTES._serialized_end = 14070 + _CHILDWORKFLOWEXECUTIONCOMPLETEDEVENTATTRIBUTES._serialized_start = 14073 + _CHILDWORKFLOWEXECUTIONCOMPLETEDEVENTATTRIBUTES._serialized_end = 14398 + _CHILDWORKFLOWEXECUTIONFAILEDEVENTATTRIBUTES._serialized_start = 14401 + _CHILDWORKFLOWEXECUTIONFAILEDEVENTATTRIBUTES._serialized_end = 14780 + _CHILDWORKFLOWEXECUTIONCANCELEDEVENTATTRIBUTES._serialized_start = 14783 + _CHILDWORKFLOWEXECUTIONCANCELEDEVENTATTRIBUTES._serialized_end = 15108 + _CHILDWORKFLOWEXECUTIONTIMEDOUTEVENTATTRIBUTES._serialized_start = 15111 + _CHILDWORKFLOWEXECUTIONTIMEDOUTEVENTATTRIBUTES._serialized_end = 15441 + _CHILDWORKFLOWEXECUTIONTERMINATEDEVENTATTRIBUTES._serialized_start = 15444 + _CHILDWORKFLOWEXECUTIONTERMINATEDEVENTATTRIBUTES._serialized_end = 15720 + _WORKFLOWEXECUTIONOPTIONSUPDATEDEVENTATTRIBUTES._serialized_start = 15723 + _WORKFLOWEXECUTIONOPTIONSUPDATEDEVENTATTRIBUTES._serialized_end = 16453 + _WORKFLOWEXECUTIONOPTIONSUPDATEDEVENTATTRIBUTES_WORKFLOWUPDATEOPTIONSUPDATE._serialized_start = 16303 + _WORKFLOWEXECUTIONOPTIONSUPDATEDEVENTATTRIBUTES_WORKFLOWUPDATEOPTIONSUPDATE._serialized_end = 16453 + _WORKFLOWPROPERTIESMODIFIEDEXTERNALLYEVENTATTRIBUTES._serialized_start = 16456 + _WORKFLOWPROPERTIESMODIFIEDEXTERNALLYEVENTATTRIBUTES._serialized_end = 16776 + _ACTIVITYPROPERTIESMODIFIEDEXTERNALLYEVENTATTRIBUTES._serialized_start = 16779 + _ACTIVITYPROPERTIESMODIFIEDEXTERNALLYEVENTATTRIBUTES._serialized_end = 16923 + _WORKFLOWEXECUTIONUPDATEACCEPTEDEVENTATTRIBUTES._serialized_start = 16926 + _WORKFLOWEXECUTIONUPDATEACCEPTEDEVENTATTRIBUTES._serialized_end = 17146 + _WORKFLOWEXECUTIONUPDATECOMPLETEDEVENTATTRIBUTES._serialized_start = 17149 + _WORKFLOWEXECUTIONUPDATECOMPLETEDEVENTATTRIBUTES._serialized_end = 17319 + _WORKFLOWEXECUTIONUPDATEREJECTEDEVENTATTRIBUTES._serialized_start = 17322 + _WORKFLOWEXECUTIONUPDATEREJECTEDEVENTATTRIBUTES._serialized_end = 17593 + _WORKFLOWEXECUTIONUPDATEADMITTEDEVENTATTRIBUTES._serialized_start = 17596 + _WORKFLOWEXECUTIONUPDATEADMITTEDEVENTATTRIBUTES._serialized_end = 17760 + _WORKFLOWEXECUTIONPAUSEDEVENTATTRIBUTES._serialized_start = 17762 + _WORKFLOWEXECUTIONPAUSEDEVENTATTRIBUTES._serialized_end = 17856 + _WORKFLOWEXECUTIONUNPAUSEDEVENTATTRIBUTES._serialized_start = 17858 + _WORKFLOWEXECUTIONUNPAUSEDEVENTATTRIBUTES._serialized_end = 17954 + _WORKFLOWEXECUTIONTIMESKIPPINGTRANSITIONEDEVENTATTRIBUTES._serialized_start = 17957 + _WORKFLOWEXECUTIONTIMESKIPPINGTRANSITIONEDEVENTATTRIBUTES._serialized_end = 18154 + _NEXUSOPERATIONSCHEDULEDEVENTATTRIBUTES._serialized_start = 18157 + _NEXUSOPERATIONSCHEDULEDEVENTATTRIBUTES._serialized_end = 18721 + _NEXUSOPERATIONSCHEDULEDEVENTATTRIBUTES_NEXUSHEADERENTRY._serialized_start = 18671 + _NEXUSOPERATIONSCHEDULEDEVENTATTRIBUTES_NEXUSHEADERENTRY._serialized_end = 18721 + _NEXUSOPERATIONSTARTEDEVENTATTRIBUTES._serialized_start = 18724 + _NEXUSOPERATIONSTARTEDEVENTATTRIBUTES._serialized_end = 18861 + _NEXUSOPERATIONCOMPLETEDEVENTATTRIBUTES._serialized_start = 18864 + _NEXUSOPERATIONCOMPLETEDEVENTATTRIBUTES._serialized_end = 19001 + _NEXUSOPERATIONFAILEDEVENTATTRIBUTES._serialized_start = 19004 + _NEXUSOPERATIONFAILEDEVENTATTRIBUTES._serialized_end = 19140 + _NEXUSOPERATIONTIMEDOUTEVENTATTRIBUTES._serialized_start = 19143 + _NEXUSOPERATIONTIMEDOUTEVENTATTRIBUTES._serialized_end = 19281 + _NEXUSOPERATIONCANCELEDEVENTATTRIBUTES._serialized_start = 19284 + _NEXUSOPERATIONCANCELEDEVENTATTRIBUTES._serialized_end = 19422 + _NEXUSOPERATIONCANCELREQUESTEDEVENTATTRIBUTES._serialized_start = 19424 + _NEXUSOPERATIONCANCELREQUESTEDEVENTATTRIBUTES._serialized_end = 19540 + _NEXUSOPERATIONCANCELREQUESTCOMPLETEDEVENTATTRIBUTES._serialized_start = 19543 + _NEXUSOPERATIONCANCELREQUESTCOMPLETEDEVENTATTRIBUTES._serialized_end = 19694 + _NEXUSOPERATIONCANCELREQUESTFAILEDEVENTATTRIBUTES._serialized_start = 19697 + _NEXUSOPERATIONCANCELREQUESTFAILEDEVENTATTRIBUTES._serialized_end = 19896 + _HISTORYEVENT._serialized_start = 19899 + _HISTORYEVENT._serialized_end = 28037 + _HISTORY._serialized_start = 28039 + _HISTORY._serialized_end = 28103 # @@protoc_insertion_point(module_scope) diff --git a/temporalio/api/history/v1/message_pb2.pyi b/temporalio/api/history/v1/message_pb2.pyi index ee158460c..9735097e2 100644 --- a/temporalio/api/history/v1/message_pb2.pyi +++ b/temporalio/api/history/v1/message_pb2.pyi @@ -2648,6 +2648,7 @@ class StartChildWorkflowExecutionInitiatedEventAttributes( PRIORITY_FIELD_NUMBER: builtins.int TIME_SKIPPING_CONFIG_FIELD_NUMBER: builtins.int TIME_SKIPPING_STATE_PROPAGATION_FIELD_NUMBER: builtins.int + VERSIONING_OVERRIDE_FIELD_NUMBER: builtins.int namespace: builtins.str """Namespace of the child workflow. SDKs and UI tools should use `namespace` field but server must use `namespace_id` only. @@ -2713,6 +2714,13 @@ class StartChildWorkflowExecutionInitiatedEventAttributes( """The time-skipping state propagated from the parent workflow. This can be nil if no time skipping has occurred or there is no previous run. """ + @property + def versioning_override( + self, + ) -> temporalio.api.workflow.v1.message_pb2.VersioningOverride: + """Versioning override requested for the child workflow. If present, this explicit override + takes precedence over versioning behavior inherited from the parent workflow. + """ def __init__( self, *, @@ -2741,6 +2749,8 @@ class StartChildWorkflowExecutionInitiatedEventAttributes( | None = ..., time_skipping_state_propagation: temporalio.api.common.v1.message_pb2.TimeSkippingStatePropagation | None = ..., + versioning_override: temporalio.api.workflow.v1.message_pb2.VersioningOverride + | None = ..., ) -> None: ... def HasField( self, @@ -2763,6 +2773,8 @@ class StartChildWorkflowExecutionInitiatedEventAttributes( b"time_skipping_config", "time_skipping_state_propagation", b"time_skipping_state_propagation", + "versioning_override", + b"versioning_override", "workflow_execution_timeout", b"workflow_execution_timeout", "workflow_run_timeout", @@ -2806,6 +2818,8 @@ class StartChildWorkflowExecutionInitiatedEventAttributes( b"time_skipping_config", "time_skipping_state_propagation", b"time_skipping_state_propagation", + "versioning_override", + b"versioning_override", "workflow_execution_timeout", b"workflow_execution_timeout", "workflow_id", diff --git a/temporalio/api/namespace/v1/message_pb2.py b/temporalio/api/namespace/v1/message_pb2.py index fd1858bb7..150a49384 100644 --- a/temporalio/api/namespace/v1/message_pb2.py +++ b/temporalio/api/namespace/v1/message_pb2.py @@ -22,7 +22,7 @@ ) DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile( - b'\n\'temporal/api/namespace/v1/message.proto\x12\x19temporal.api.namespace.v1\x1a\x1egoogle/protobuf/duration.proto\x1a\x1fgoogle/protobuf/timestamp.proto\x1a%temporal/api/enums/v1/namespace.proto"\x90\x07\n\rNamespaceInfo\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x34\n\x05state\x18\x02 \x01(\x0e\x32%.temporal.api.enums.v1.NamespaceState\x12\x13\n\x0b\x64\x65scription\x18\x03 \x01(\t\x12\x13\n\x0bowner_email\x18\x04 \x01(\t\x12@\n\x04\x64\x61ta\x18\x05 \x03(\x0b\x32\x32.temporal.api.namespace.v1.NamespaceInfo.DataEntry\x12\n\n\x02id\x18\x06 \x01(\t\x12K\n\x0c\x63\x61pabilities\x18\x07 \x01(\x0b\x32\x35.temporal.api.namespace.v1.NamespaceInfo.Capabilities\x12?\n\x06limits\x18\x08 \x01(\x0b\x32/.temporal.api.namespace.v1.NamespaceInfo.Limits\x12\x1a\n\x12supports_schedules\x18\x64 \x01(\x08\x1a+\n\tDataEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x1a\xa3\x03\n\x0c\x43\x61pabilities\x12\x1c\n\x14\x65\x61ger_workflow_start\x18\x01 \x01(\x08\x12\x13\n\x0bsync_update\x18\x02 \x01(\x08\x12\x14\n\x0c\x61sync_update\x18\x03 \x01(\x08\x12\x19\n\x11worker_heartbeats\x18\x04 \x01(\x08\x12*\n"reported_problems_search_attribute\x18\x05 \x01(\x08\x12\x16\n\x0eworkflow_pause\x18\x06 \x01(\x08\x12\x1d\n\x15standalone_activities\x18\x07 \x01(\x08\x12(\n worker_poll_complete_on_shutdown\x18\x08 \x01(\x08\x12\x1a\n\x12poller_autoscaling\x18\t \x01(\x08\x12\x17\n\x0fworker_commands\x18\n \x01(\x08\x12"\n\x1astandalone_nexus_operation\x18\x0b \x01(\x08\x12!\n\x19workflow_update_callbacks\x18\x0c \x01(\x08\x12&\n\x1epoller_autoscaling_auto_enroll\x18\r \x01(\x08\x1a\x46\n\x06Limits\x12\x1d\n\x15\x62lob_size_limit_error\x18\x01 \x01(\x03\x12\x1d\n\x15memo_size_limit_error\x18\x02 \x01(\x03"\x9e\x04\n\x0fNamespaceConfig\x12\x43\n workflow_execution_retention_ttl\x18\x01 \x01(\x0b\x32\x19.google.protobuf.Duration\x12<\n\x0c\x62\x61\x64_binaries\x18\x02 \x01(\x0b\x32&.temporal.api.namespace.v1.BadBinaries\x12\x44\n\x16history_archival_state\x18\x03 \x01(\x0e\x32$.temporal.api.enums.v1.ArchivalState\x12\x1c\n\x14history_archival_uri\x18\x04 \x01(\t\x12G\n\x19visibility_archival_state\x18\x05 \x01(\x0e\x32$.temporal.api.enums.v1.ArchivalState\x12\x1f\n\x17visibility_archival_uri\x18\x06 \x01(\t\x12u\n\x1f\x63ustom_search_attribute_aliases\x18\x07 \x03(\x0b\x32L.temporal.api.namespace.v1.NamespaceConfig.CustomSearchAttributeAliasesEntry\x1a\x43\n!CustomSearchAttributeAliasesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01"\xb0\x01\n\x0b\x42\x61\x64\x42inaries\x12\x46\n\x08\x62inaries\x18\x01 \x03(\x0b\x32\x34.temporal.api.namespace.v1.BadBinaries.BinariesEntry\x1aY\n\rBinariesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x37\n\x05value\x18\x02 \x01(\x0b\x32(.temporal.api.namespace.v1.BadBinaryInfo:\x02\x38\x01"b\n\rBadBinaryInfo\x12\x0e\n\x06reason\x18\x01 \x01(\t\x12\x10\n\x08operator\x18\x02 \x01(\t\x12/\n\x0b\x63reate_time\x18\x03 \x01(\x0b\x32\x1a.google.protobuf.Timestamp"\xea\x01\n\x13UpdateNamespaceInfo\x12\x13\n\x0b\x64\x65scription\x18\x01 \x01(\t\x12\x13\n\x0bowner_email\x18\x02 \x01(\t\x12\x46\n\x04\x64\x61ta\x18\x03 \x03(\x0b\x32\x38.temporal.api.namespace.v1.UpdateNamespaceInfo.DataEntry\x12\x34\n\x05state\x18\x04 \x01(\x0e\x32%.temporal.api.enums.v1.NamespaceState\x1a+\n\tDataEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01"*\n\x0fNamespaceFilter\x12\x17\n\x0finclude_deleted\x18\x01 \x01(\x08\x42\x98\x01\n\x1cio.temporal.api.namespace.v1B\x0cMessageProtoP\x01Z)go.temporal.io/api/namespace/v1;namespace\xaa\x02\x1bTemporalio.Api.Namespace.V1\xea\x02\x1eTemporalio::Api::Namespace::V1b\x06proto3' + b'\n\'temporal/api/namespace/v1/message.proto\x12\x19temporal.api.namespace.v1\x1a\x1egoogle/protobuf/duration.proto\x1a\x1fgoogle/protobuf/timestamp.proto\x1a%temporal/api/enums/v1/namespace.proto"\xc3\x08\n\rNamespaceInfo\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x34\n\x05state\x18\x02 \x01(\x0e\x32%.temporal.api.enums.v1.NamespaceState\x12\x13\n\x0b\x64\x65scription\x18\x03 \x01(\t\x12\x13\n\x0bowner_email\x18\x04 \x01(\t\x12@\n\x04\x64\x61ta\x18\x05 \x03(\x0b\x32\x32.temporal.api.namespace.v1.NamespaceInfo.DataEntry\x12\n\n\x02id\x18\x06 \x01(\t\x12K\n\x0c\x63\x61pabilities\x18\x07 \x01(\x0b\x32\x35.temporal.api.namespace.v1.NamespaceInfo.Capabilities\x12?\n\x06limits\x18\x08 \x01(\x0b\x32/.temporal.api.namespace.v1.NamespaceInfo.Limits\x12\x1a\n\x12supports_schedules\x18\x64 \x01(\x08\x1a+\n\tDataEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x1a\xd6\x04\n\x0c\x43\x61pabilities\x12\x1c\n\x14\x65\x61ger_workflow_start\x18\x01 \x01(\x08\x12\x13\n\x0bsync_update\x18\x02 \x01(\x08\x12\x14\n\x0c\x61sync_update\x18\x03 \x01(\x08\x12\x19\n\x11worker_heartbeats\x18\x04 \x01(\x08\x12*\n"reported_problems_search_attribute\x18\x05 \x01(\x08\x12\x16\n\x0eworkflow_pause\x18\x06 \x01(\x08\x12\x1d\n\x15standalone_activities\x18\x07 \x01(\x08\x12(\n worker_poll_complete_on_shutdown\x18\x08 \x01(\x08\x12\x1a\n\x12poller_autoscaling\x18\t \x01(\x08\x12\x17\n\x0fworker_commands\x18\n \x01(\x08\x12"\n\x1astandalone_nexus_operation\x18\x0b \x01(\x08\x12!\n\x19workflow_update_callbacks\x18\x0c \x01(\x08\x12&\n\x1epoller_autoscaling_auto_enroll\x18\r \x01(\x08\x12+\n#workflow_task_completion_pagination\x18\x0e \x01(\x08\x12\'\n\x1fstandalone_activity_start_delay\x18\x0f \x01(\x08\x12,\n$standalone_activity_batch_operations\x18\x10 \x01(\x08\x12-\n%standalone_activity_operator_commands\x18\x11 \x01(\x08\x1a\x46\n\x06Limits\x12\x1d\n\x15\x62lob_size_limit_error\x18\x01 \x01(\x03\x12\x1d\n\x15memo_size_limit_error\x18\x02 \x01(\x03"\x9e\x04\n\x0fNamespaceConfig\x12\x43\n workflow_execution_retention_ttl\x18\x01 \x01(\x0b\x32\x19.google.protobuf.Duration\x12<\n\x0c\x62\x61\x64_binaries\x18\x02 \x01(\x0b\x32&.temporal.api.namespace.v1.BadBinaries\x12\x44\n\x16history_archival_state\x18\x03 \x01(\x0e\x32$.temporal.api.enums.v1.ArchivalState\x12\x1c\n\x14history_archival_uri\x18\x04 \x01(\t\x12G\n\x19visibility_archival_state\x18\x05 \x01(\x0e\x32$.temporal.api.enums.v1.ArchivalState\x12\x1f\n\x17visibility_archival_uri\x18\x06 \x01(\t\x12u\n\x1f\x63ustom_search_attribute_aliases\x18\x07 \x03(\x0b\x32L.temporal.api.namespace.v1.NamespaceConfig.CustomSearchAttributeAliasesEntry\x1a\x43\n!CustomSearchAttributeAliasesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01"\xb0\x01\n\x0b\x42\x61\x64\x42inaries\x12\x46\n\x08\x62inaries\x18\x01 \x03(\x0b\x32\x34.temporal.api.namespace.v1.BadBinaries.BinariesEntry\x1aY\n\rBinariesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x37\n\x05value\x18\x02 \x01(\x0b\x32(.temporal.api.namespace.v1.BadBinaryInfo:\x02\x38\x01"b\n\rBadBinaryInfo\x12\x0e\n\x06reason\x18\x01 \x01(\t\x12\x10\n\x08operator\x18\x02 \x01(\t\x12/\n\x0b\x63reate_time\x18\x03 \x01(\x0b\x32\x1a.google.protobuf.Timestamp"\xea\x01\n\x13UpdateNamespaceInfo\x12\x13\n\x0b\x64\x65scription\x18\x01 \x01(\t\x12\x13\n\x0bowner_email\x18\x02 \x01(\t\x12\x46\n\x04\x64\x61ta\x18\x03 \x03(\x0b\x32\x38.temporal.api.namespace.v1.UpdateNamespaceInfo.DataEntry\x12\x34\n\x05state\x18\x04 \x01(\x0e\x32%.temporal.api.enums.v1.NamespaceState\x1a+\n\tDataEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01"*\n\x0fNamespaceFilter\x12\x17\n\x0finclude_deleted\x18\x01 \x01(\x08\x42\x98\x01\n\x1cio.temporal.api.namespace.v1B\x0cMessageProtoP\x01Z)go.temporal.io/api/namespace/v1;namespace\xaa\x02\x1bTemporalio.Api.Namespace.V1\xea\x02\x1eTemporalio::Api::Namespace::V1b\x06proto3' ) @@ -178,27 +178,27 @@ _UPDATENAMESPACEINFO_DATAENTRY._options = None _UPDATENAMESPACEINFO_DATAENTRY._serialized_options = b"8\001" _NAMESPACEINFO._serialized_start = 175 - _NAMESPACEINFO._serialized_end = 1087 + _NAMESPACEINFO._serialized_end = 1266 _NAMESPACEINFO_DATAENTRY._serialized_start = 550 _NAMESPACEINFO_DATAENTRY._serialized_end = 593 _NAMESPACEINFO_CAPABILITIES._serialized_start = 596 - _NAMESPACEINFO_CAPABILITIES._serialized_end = 1015 - _NAMESPACEINFO_LIMITS._serialized_start = 1017 - _NAMESPACEINFO_LIMITS._serialized_end = 1087 - _NAMESPACECONFIG._serialized_start = 1090 - _NAMESPACECONFIG._serialized_end = 1632 - _NAMESPACECONFIG_CUSTOMSEARCHATTRIBUTEALIASESENTRY._serialized_start = 1565 - _NAMESPACECONFIG_CUSTOMSEARCHATTRIBUTEALIASESENTRY._serialized_end = 1632 - _BADBINARIES._serialized_start = 1635 - _BADBINARIES._serialized_end = 1811 - _BADBINARIES_BINARIESENTRY._serialized_start = 1722 - _BADBINARIES_BINARIESENTRY._serialized_end = 1811 - _BADBINARYINFO._serialized_start = 1813 - _BADBINARYINFO._serialized_end = 1911 - _UPDATENAMESPACEINFO._serialized_start = 1914 - _UPDATENAMESPACEINFO._serialized_end = 2148 + _NAMESPACEINFO_CAPABILITIES._serialized_end = 1194 + _NAMESPACEINFO_LIMITS._serialized_start = 1196 + _NAMESPACEINFO_LIMITS._serialized_end = 1266 + _NAMESPACECONFIG._serialized_start = 1269 + _NAMESPACECONFIG._serialized_end = 1811 + _NAMESPACECONFIG_CUSTOMSEARCHATTRIBUTEALIASESENTRY._serialized_start = 1744 + _NAMESPACECONFIG_CUSTOMSEARCHATTRIBUTEALIASESENTRY._serialized_end = 1811 + _BADBINARIES._serialized_start = 1814 + _BADBINARIES._serialized_end = 1990 + _BADBINARIES_BINARIESENTRY._serialized_start = 1901 + _BADBINARIES_BINARIESENTRY._serialized_end = 1990 + _BADBINARYINFO._serialized_start = 1992 + _BADBINARYINFO._serialized_end = 2090 + _UPDATENAMESPACEINFO._serialized_start = 2093 + _UPDATENAMESPACEINFO._serialized_end = 2327 _UPDATENAMESPACEINFO_DATAENTRY._serialized_start = 550 _UPDATENAMESPACEINFO_DATAENTRY._serialized_end = 593 - _NAMESPACEFILTER._serialized_start = 2150 - _NAMESPACEFILTER._serialized_end = 2192 + _NAMESPACEFILTER._serialized_start = 2329 + _NAMESPACEFILTER._serialized_end = 2371 # @@protoc_insertion_point(module_scope) diff --git a/temporalio/api/namespace/v1/message_pb2.pyi b/temporalio/api/namespace/v1/message_pb2.pyi index 9680e7f5d..51f386e39 100644 --- a/temporalio/api/namespace/v1/message_pb2.pyi +++ b/temporalio/api/namespace/v1/message_pb2.pyi @@ -61,6 +61,10 @@ class NamespaceInfo(google.protobuf.message.Message): STANDALONE_NEXUS_OPERATION_FIELD_NUMBER: builtins.int WORKFLOW_UPDATE_CALLBACKS_FIELD_NUMBER: builtins.int POLLER_AUTOSCALING_AUTO_ENROLL_FIELD_NUMBER: builtins.int + WORKFLOW_TASK_COMPLETION_PAGINATION_FIELD_NUMBER: builtins.int + STANDALONE_ACTIVITY_START_DELAY_FIELD_NUMBER: builtins.int + STANDALONE_ACTIVITY_BATCH_OPERATIONS_FIELD_NUMBER: builtins.int + STANDALONE_ACTIVITY_OPERATOR_COMMANDS_FIELD_NUMBER: builtins.int eager_workflow_start: builtins.bool """True if the namespace supports eager workflow start.""" sync_update: builtins.bool @@ -92,6 +96,14 @@ class NamespaceInfo(google.protobuf.message.Message): """True if the namespace supports attaching callbacks on workflow updates""" poller_autoscaling_auto_enroll: builtins.bool """When true, workers should use poller autoscaling by default unless explicitly configured otherwise.""" + workflow_task_completion_pagination: builtins.bool + """True if the namespace supports pagination of `RespondWorkflowTaskCompleted` request.""" + standalone_activity_start_delay: builtins.bool + """True if the namespace supports start delay for standalone activities.""" + standalone_activity_batch_operations: builtins.bool + """True if the namespace supports batch operations for standalone activities.""" + standalone_activity_operator_commands: builtins.bool + """True if the namespace supports standalone activity operator commands.""" def __init__( self, *, @@ -108,6 +120,10 @@ class NamespaceInfo(google.protobuf.message.Message): standalone_nexus_operation: builtins.bool = ..., workflow_update_callbacks: builtins.bool = ..., poller_autoscaling_auto_enroll: builtins.bool = ..., + workflow_task_completion_pagination: builtins.bool = ..., + standalone_activity_start_delay: builtins.bool = ..., + standalone_activity_batch_operations: builtins.bool = ..., + standalone_activity_operator_commands: builtins.bool = ..., ) -> None: ... def ClearField( self, @@ -124,6 +140,12 @@ class NamespaceInfo(google.protobuf.message.Message): b"reported_problems_search_attribute", "standalone_activities", b"standalone_activities", + "standalone_activity_batch_operations", + b"standalone_activity_batch_operations", + "standalone_activity_operator_commands", + b"standalone_activity_operator_commands", + "standalone_activity_start_delay", + b"standalone_activity_start_delay", "standalone_nexus_operation", b"standalone_nexus_operation", "sync_update", @@ -136,6 +158,8 @@ class NamespaceInfo(google.protobuf.message.Message): b"worker_poll_complete_on_shutdown", "workflow_pause", b"workflow_pause", + "workflow_task_completion_pagination", + b"workflow_task_completion_pagination", "workflow_update_callbacks", b"workflow_update_callbacks", ], diff --git a/temporalio/api/taskqueue/v1/__init__.py b/temporalio/api/taskqueue/v1/__init__.py index dac573696..98595069b 100644 --- a/temporalio/api/taskqueue/v1/__init__.py +++ b/temporalio/api/taskqueue/v1/__init__.py @@ -5,6 +5,7 @@ CompatibleVersionSet, ConfigMetadata, PollerGroupInfo, + PollerGroupsInfo, PollerInfo, PollerScalingDecision, RampByPercentage, @@ -34,6 +35,7 @@ "CompatibleVersionSet", "ConfigMetadata", "PollerGroupInfo", + "PollerGroupsInfo", "PollerInfo", "PollerScalingDecision", "RampByPercentage", diff --git a/temporalio/api/taskqueue/v1/message_pb2.py b/temporalio/api/taskqueue/v1/message_pb2.py index bf0eab1d0..e5caf07ac 100644 --- a/temporalio/api/taskqueue/v1/message_pb2.py +++ b/temporalio/api/taskqueue/v1/message_pb2.py @@ -29,7 +29,7 @@ ) DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile( - b'\n\'temporal/api/taskqueue/v1/message.proto\x12\x19temporal.api.taskqueue.v1\x1a\x1egoogle/protobuf/duration.proto\x1a\x1fgoogle/protobuf/timestamp.proto\x1a\x1egoogle/protobuf/wrappers.proto\x1a&temporal/api/enums/v1/task_queue.proto\x1a$temporal/api/common/v1/message.proto\x1a(temporal/api/deployment/v1/message.proto"b\n\tTaskQueue\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x32\n\x04kind\x18\x02 \x01(\x0e\x32$.temporal.api.enums.v1.TaskQueueKind\x12\x13\n\x0bnormal_name\x18\x03 \x01(\t"O\n\x11TaskQueueMetadata\x12:\n\x14max_tasks_per_second\x18\x01 \x01(\x0b\x32\x1c.google.protobuf.DoubleValue"\xda\x02\n\x17TaskQueueVersioningInfo\x12W\n\x1a\x63urrent_deployment_version\x18\x07 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersion\x12\x1b\n\x0f\x63urrent_version\x18\x01 \x01(\tB\x02\x18\x01\x12W\n\x1aramping_deployment_version\x18\t \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersion\x12\x1b\n\x0framping_version\x18\x02 \x01(\tB\x02\x18\x01\x12"\n\x1aramping_version_percentage\x18\x03 \x01(\x02\x12/\n\x0bupdate_time\x18\x04 \x01(\x0b\x32\x1a.google.protobuf.Timestamp"W\n\x19TaskQueueVersionSelection\x12\x11\n\tbuild_ids\x18\x01 \x03(\t\x12\x13\n\x0bunversioned\x18\x02 \x01(\x08\x12\x12\n\nall_active\x18\x03 \x01(\x08"\x95\x02\n\x14TaskQueueVersionInfo\x12R\n\ntypes_info\x18\x01 \x03(\x0b\x32>.temporal.api.taskqueue.v1.TaskQueueVersionInfo.TypesInfoEntry\x12I\n\x11task_reachability\x18\x02 \x01(\x0e\x32..temporal.api.enums.v1.BuildIdTaskReachability\x1a^\n\x0eTypesInfoEntry\x12\x0b\n\x03key\x18\x01 \x01(\x05\x12;\n\x05value\x18\x02 \x01(\x0b\x32,.temporal.api.taskqueue.v1.TaskQueueTypeInfo:\x02\x38\x01"\x85\x01\n\x11TaskQueueTypeInfo\x12\x36\n\x07pollers\x18\x01 \x03(\x0b\x32%.temporal.api.taskqueue.v1.PollerInfo\x12\x38\n\x05stats\x18\x02 \x01(\x0b\x32).temporal.api.taskqueue.v1.TaskQueueStats"\xa4\x01\n\x0eTaskQueueStats\x12!\n\x19\x61pproximate_backlog_count\x18\x01 \x01(\x03\x12:\n\x17\x61pproximate_backlog_age\x18\x02 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x16\n\x0etasks_add_rate\x18\x03 \x01(\x02\x12\x1b\n\x13tasks_dispatch_rate\x18\x04 \x01(\x02"\xac\x01\n\x0fTaskQueueStatus\x12\x1a\n\x12\x62\x61\x63klog_count_hint\x18\x01 \x01(\x03\x12\x12\n\nread_level\x18\x02 \x01(\x03\x12\x11\n\tack_level\x18\x03 \x01(\x03\x12\x17\n\x0frate_per_second\x18\x04 \x01(\x01\x12=\n\rtask_id_block\x18\x05 \x01(\x0b\x32&.temporal.api.taskqueue.v1.TaskIdBlock"/\n\x0bTaskIdBlock\x12\x10\n\x08start_id\x18\x01 \x01(\x03\x12\x0e\n\x06\x65nd_id\x18\x02 \x01(\x03"B\n\x1aTaskQueuePartitionMetadata\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x17\n\x0fowner_host_name\x18\x02 \x01(\t"\x9a\x02\n\nPollerInfo\x12\x34\n\x10last_access_time\x18\x01 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x10\n\x08identity\x18\x02 \x01(\t\x12\x17\n\x0frate_per_second\x18\x03 \x01(\x01\x12Z\n\x1bworker_version_capabilities\x18\x04 \x01(\x0b\x32\x31.temporal.api.common.v1.WorkerVersionCapabilitiesB\x02\x18\x01\x12O\n\x12\x64\x65ployment_options\x18\x05 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentOptions"\x9a\x01\n\x19StickyExecutionAttributes\x12?\n\x11worker_task_queue\x18\x01 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12<\n\x19schedule_to_start_timeout\x18\x02 \x01(\x0b\x32\x19.google.protobuf.Duration")\n\x14\x43ompatibleVersionSet\x12\x11\n\tbuild_ids\x18\x01 \x03(\t"j\n\x15TaskQueueReachability\x12\x12\n\ntask_queue\x18\x01 \x01(\t\x12=\n\x0creachability\x18\x02 \x03(\x0e\x32\'.temporal.api.enums.v1.TaskReachability"z\n\x13\x42uildIdReachability\x12\x10\n\x08\x62uild_id\x18\x01 \x01(\t\x12Q\n\x17task_queue_reachability\x18\x02 \x03(\x0b\x32\x30.temporal.api.taskqueue.v1.TaskQueueReachability"+\n\x10RampByPercentage\x12\x17\n\x0framp_percentage\x18\x01 \x01(\x02"\x80\x01\n\x15\x42uildIdAssignmentRule\x12\x17\n\x0ftarget_build_id\x18\x01 \x01(\t\x12\x46\n\x0fpercentage_ramp\x18\x03 \x01(\x0b\x32+.temporal.api.taskqueue.v1.RampByPercentageH\x00\x42\x06\n\x04ramp"Q\n\x1d\x43ompatibleBuildIdRedirectRule\x12\x17\n\x0fsource_build_id\x18\x01 \x01(\t\x12\x17\n\x0ftarget_build_id\x18\x02 \x01(\t"\x93\x01\n TimestampedBuildIdAssignmentRule\x12>\n\x04rule\x18\x01 \x01(\x0b\x32\x30.temporal.api.taskqueue.v1.BuildIdAssignmentRule\x12/\n\x0b\x63reate_time\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.Timestamp"\xa3\x01\n(TimestampedCompatibleBuildIdRedirectRule\x12\x46\n\x04rule\x18\x01 \x01(\x0b\x32\x38.temporal.api.taskqueue.v1.CompatibleBuildIdRedirectRule\x12/\n\x0b\x63reate_time\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.Timestamp"-\n\x0fPollerGroupInfo\x12\n\n\x02id\x18\x01 \x01(\t\x12\x0e\n\x06weight\x18\x02 \x01(\x02">\n\x15PollerScalingDecision\x12%\n\x1dpoll_request_delta_suggestion\x18\x01 \x01(\x05"(\n\tRateLimit\x12\x1b\n\x13requests_per_second\x18\x01 \x01(\x02"j\n\x0e\x43onfigMetadata\x12\x0e\n\x06reason\x18\x01 \x01(\t\x12\x17\n\x0fupdate_identity\x18\x02 \x01(\t\x12/\n\x0bupdate_time\x18\x03 \x01(\x0b\x32\x1a.google.protobuf.Timestamp"\x88\x01\n\x0fRateLimitConfig\x12\x38\n\nrate_limit\x18\x01 \x01(\x0b\x32$.temporal.api.taskqueue.v1.RateLimit\x12;\n\x08metadata\x18\x02 \x01(\x0b\x32).temporal.api.taskqueue.v1.ConfigMetadata"\xd9\x02\n\x0fTaskQueueConfig\x12\x44\n\x10queue_rate_limit\x18\x01 \x01(\x0b\x32*.temporal.api.taskqueue.v1.RateLimitConfig\x12T\n fairness_keys_rate_limit_default\x18\x02 \x01(\x0b\x32*.temporal.api.taskqueue.v1.RateLimitConfig\x12j\n\x19\x66\x61irness_weight_overrides\x18\x03 \x03(\x0b\x32G.temporal.api.taskqueue.v1.TaskQueueConfig.FairnessWeightOverridesEntry\x1a>\n\x1c\x46\x61irnessWeightOverridesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\x02:\x02\x38\x01\x42\x98\x01\n\x1cio.temporal.api.taskqueue.v1B\x0cMessageProtoP\x01Z)go.temporal.io/api/taskqueue/v1;taskqueue\xaa\x02\x1bTemporalio.Api.TaskQueue.V1\xea\x02\x1eTemporalio::Api::TaskQueue::V1b\x06proto3' + b'\n\'temporal/api/taskqueue/v1/message.proto\x12\x19temporal.api.taskqueue.v1\x1a\x1egoogle/protobuf/duration.proto\x1a\x1fgoogle/protobuf/timestamp.proto\x1a\x1egoogle/protobuf/wrappers.proto\x1a&temporal/api/enums/v1/task_queue.proto\x1a$temporal/api/common/v1/message.proto\x1a(temporal/api/deployment/v1/message.proto"b\n\tTaskQueue\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x32\n\x04kind\x18\x02 \x01(\x0e\x32$.temporal.api.enums.v1.TaskQueueKind\x12\x13\n\x0bnormal_name\x18\x03 \x01(\t"O\n\x11TaskQueueMetadata\x12:\n\x14max_tasks_per_second\x18\x01 \x01(\x0b\x32\x1c.google.protobuf.DoubleValue"\xda\x02\n\x17TaskQueueVersioningInfo\x12W\n\x1a\x63urrent_deployment_version\x18\x07 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersion\x12\x1b\n\x0f\x63urrent_version\x18\x01 \x01(\tB\x02\x18\x01\x12W\n\x1aramping_deployment_version\x18\t \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersion\x12\x1b\n\x0framping_version\x18\x02 \x01(\tB\x02\x18\x01\x12"\n\x1aramping_version_percentage\x18\x03 \x01(\x02\x12/\n\x0bupdate_time\x18\x04 \x01(\x0b\x32\x1a.google.protobuf.Timestamp"W\n\x19TaskQueueVersionSelection\x12\x11\n\tbuild_ids\x18\x01 \x03(\t\x12\x13\n\x0bunversioned\x18\x02 \x01(\x08\x12\x12\n\nall_active\x18\x03 \x01(\x08"\x95\x02\n\x14TaskQueueVersionInfo\x12R\n\ntypes_info\x18\x01 \x03(\x0b\x32>.temporal.api.taskqueue.v1.TaskQueueVersionInfo.TypesInfoEntry\x12I\n\x11task_reachability\x18\x02 \x01(\x0e\x32..temporal.api.enums.v1.BuildIdTaskReachability\x1a^\n\x0eTypesInfoEntry\x12\x0b\n\x03key\x18\x01 \x01(\x05\x12;\n\x05value\x18\x02 \x01(\x0b\x32,.temporal.api.taskqueue.v1.TaskQueueTypeInfo:\x02\x38\x01"\x85\x01\n\x11TaskQueueTypeInfo\x12\x36\n\x07pollers\x18\x01 \x03(\x0b\x32%.temporal.api.taskqueue.v1.PollerInfo\x12\x38\n\x05stats\x18\x02 \x01(\x0b\x32).temporal.api.taskqueue.v1.TaskQueueStats"\xc2\x01\n\x0eTaskQueueStats\x12!\n\x19\x61pproximate_backlog_count\x18\x01 \x01(\x03\x12:\n\x17\x61pproximate_backlog_age\x18\x02 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x16\n\x0etasks_add_rate\x18\x03 \x01(\x02\x12\x1b\n\x13tasks_dispatch_rate\x18\x04 \x01(\x02\x12\x1c\n\x14rate_limiting_active\x18\x05 \x01(\x08"\xac\x01\n\x0fTaskQueueStatus\x12\x1a\n\x12\x62\x61\x63klog_count_hint\x18\x01 \x01(\x03\x12\x12\n\nread_level\x18\x02 \x01(\x03\x12\x11\n\tack_level\x18\x03 \x01(\x03\x12\x17\n\x0frate_per_second\x18\x04 \x01(\x01\x12=\n\rtask_id_block\x18\x05 \x01(\x0b\x32&.temporal.api.taskqueue.v1.TaskIdBlock"/\n\x0bTaskIdBlock\x12\x10\n\x08start_id\x18\x01 \x01(\x03\x12\x0e\n\x06\x65nd_id\x18\x02 \x01(\x03"B\n\x1aTaskQueuePartitionMetadata\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x17\n\x0fowner_host_name\x18\x02 \x01(\t"\x9a\x02\n\nPollerInfo\x12\x34\n\x10last_access_time\x18\x01 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x10\n\x08identity\x18\x02 \x01(\t\x12\x17\n\x0frate_per_second\x18\x03 \x01(\x01\x12Z\n\x1bworker_version_capabilities\x18\x04 \x01(\x0b\x32\x31.temporal.api.common.v1.WorkerVersionCapabilitiesB\x02\x18\x01\x12O\n\x12\x64\x65ployment_options\x18\x05 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentOptions"\x9a\x01\n\x19StickyExecutionAttributes\x12?\n\x11worker_task_queue\x18\x01 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12<\n\x19schedule_to_start_timeout\x18\x02 \x01(\x0b\x32\x19.google.protobuf.Duration")\n\x14\x43ompatibleVersionSet\x12\x11\n\tbuild_ids\x18\x01 \x03(\t"j\n\x15TaskQueueReachability\x12\x12\n\ntask_queue\x18\x01 \x01(\t\x12=\n\x0creachability\x18\x02 \x03(\x0e\x32\'.temporal.api.enums.v1.TaskReachability"z\n\x13\x42uildIdReachability\x12\x10\n\x08\x62uild_id\x18\x01 \x01(\t\x12Q\n\x17task_queue_reachability\x18\x02 \x03(\x0b\x32\x30.temporal.api.taskqueue.v1.TaskQueueReachability"+\n\x10RampByPercentage\x12\x17\n\x0framp_percentage\x18\x01 \x01(\x02"\x80\x01\n\x15\x42uildIdAssignmentRule\x12\x17\n\x0ftarget_build_id\x18\x01 \x01(\t\x12\x46\n\x0fpercentage_ramp\x18\x03 \x01(\x0b\x32+.temporal.api.taskqueue.v1.RampByPercentageH\x00\x42\x06\n\x04ramp"Q\n\x1d\x43ompatibleBuildIdRedirectRule\x12\x17\n\x0fsource_build_id\x18\x01 \x01(\t\x12\x17\n\x0ftarget_build_id\x18\x02 \x01(\t"\x93\x01\n TimestampedBuildIdAssignmentRule\x12>\n\x04rule\x18\x01 \x01(\x0b\x32\x30.temporal.api.taskqueue.v1.BuildIdAssignmentRule\x12/\n\x0b\x63reate_time\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.Timestamp"\xa3\x01\n(TimestampedCompatibleBuildIdRedirectRule\x12\x46\n\x04rule\x18\x01 \x01(\x0b\x32\x38.temporal.api.taskqueue.v1.CompatibleBuildIdRedirectRule\x12/\n\x0b\x63reate_time\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.Timestamp"-\n\x0fPollerGroupInfo\x12\n\n\x02id\x18\x01 \x01(\t\x12\x0e\n\x06weight\x18\x02 \x01(\x02"f\n\x10PollerGroupsInfo\x12\x0f\n\x07version\x18\x01 \x01(\x03\x12\x41\n\rpoller_groups\x18\x02 \x03(\x0b\x32*.temporal.api.taskqueue.v1.PollerGroupInfo">\n\x15PollerScalingDecision\x12%\n\x1dpoll_request_delta_suggestion\x18\x01 \x01(\x05"(\n\tRateLimit\x12\x1b\n\x13requests_per_second\x18\x01 \x01(\x02"j\n\x0e\x43onfigMetadata\x12\x0e\n\x06reason\x18\x01 \x01(\t\x12\x17\n\x0fupdate_identity\x18\x02 \x01(\t\x12/\n\x0bupdate_time\x18\x03 \x01(\x0b\x32\x1a.google.protobuf.Timestamp"\x88\x01\n\x0fRateLimitConfig\x12\x38\n\nrate_limit\x18\x01 \x01(\x0b\x32$.temporal.api.taskqueue.v1.RateLimit\x12;\n\x08metadata\x18\x02 \x01(\x0b\x32).temporal.api.taskqueue.v1.ConfigMetadata"\xd9\x02\n\x0fTaskQueueConfig\x12\x44\n\x10queue_rate_limit\x18\x01 \x01(\x0b\x32*.temporal.api.taskqueue.v1.RateLimitConfig\x12T\n fairness_keys_rate_limit_default\x18\x02 \x01(\x0b\x32*.temporal.api.taskqueue.v1.RateLimitConfig\x12j\n\x19\x66\x61irness_weight_overrides\x18\x03 \x03(\x0b\x32G.temporal.api.taskqueue.v1.TaskQueueConfig.FairnessWeightOverridesEntry\x1a>\n\x1c\x46\x61irnessWeightOverridesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\x02:\x02\x38\x01\x42\x98\x01\n\x1cio.temporal.api.taskqueue.v1B\x0cMessageProtoP\x01Z)go.temporal.io/api/taskqueue/v1;taskqueue\xaa\x02\x1bTemporalio.Api.TaskQueue.V1\xea\x02\x1eTemporalio::Api::TaskQueue::V1b\x06proto3' ) @@ -69,6 +69,7 @@ "TimestampedCompatibleBuildIdRedirectRule" ] _POLLERGROUPINFO = DESCRIPTOR.message_types_by_name["PollerGroupInfo"] +_POLLERGROUPSINFO = DESCRIPTOR.message_types_by_name["PollerGroupsInfo"] _POLLERSCALINGDECISION = DESCRIPTOR.message_types_by_name["PollerScalingDecision"] _RATELIMIT = DESCRIPTOR.message_types_by_name["RateLimit"] _CONFIGMETADATA = DESCRIPTOR.message_types_by_name["ConfigMetadata"] @@ -318,6 +319,17 @@ ) _sym_db.RegisterMessage(PollerGroupInfo) +PollerGroupsInfo = _reflection.GeneratedProtocolMessageType( + "PollerGroupsInfo", + (_message.Message,), + { + "DESCRIPTOR": _POLLERGROUPSINFO, + "__module__": "temporalio.api.taskqueue.v1.message_pb2", + # @@protoc_insertion_point(class_scope:temporal.api.taskqueue.v1.PollerGroupsInfo) + }, +) +_sym_db.RegisterMessage(PollerGroupsInfo) + PollerScalingDecision = _reflection.GeneratedProtocolMessageType( "PollerScalingDecision", (_message.Message,), @@ -417,45 +429,47 @@ _TASKQUEUETYPEINFO._serialized_start = 1187 _TASKQUEUETYPEINFO._serialized_end = 1320 _TASKQUEUESTATS._serialized_start = 1323 - _TASKQUEUESTATS._serialized_end = 1487 - _TASKQUEUESTATUS._serialized_start = 1490 - _TASKQUEUESTATUS._serialized_end = 1662 - _TASKIDBLOCK._serialized_start = 1664 - _TASKIDBLOCK._serialized_end = 1711 - _TASKQUEUEPARTITIONMETADATA._serialized_start = 1713 - _TASKQUEUEPARTITIONMETADATA._serialized_end = 1779 - _POLLERINFO._serialized_start = 1782 - _POLLERINFO._serialized_end = 2064 - _STICKYEXECUTIONATTRIBUTES._serialized_start = 2067 - _STICKYEXECUTIONATTRIBUTES._serialized_end = 2221 - _COMPATIBLEVERSIONSET._serialized_start = 2223 - _COMPATIBLEVERSIONSET._serialized_end = 2264 - _TASKQUEUEREACHABILITY._serialized_start = 2266 - _TASKQUEUEREACHABILITY._serialized_end = 2372 - _BUILDIDREACHABILITY._serialized_start = 2374 - _BUILDIDREACHABILITY._serialized_end = 2496 - _RAMPBYPERCENTAGE._serialized_start = 2498 - _RAMPBYPERCENTAGE._serialized_end = 2541 - _BUILDIDASSIGNMENTRULE._serialized_start = 2544 - _BUILDIDASSIGNMENTRULE._serialized_end = 2672 - _COMPATIBLEBUILDIDREDIRECTRULE._serialized_start = 2674 - _COMPATIBLEBUILDIDREDIRECTRULE._serialized_end = 2755 - _TIMESTAMPEDBUILDIDASSIGNMENTRULE._serialized_start = 2758 - _TIMESTAMPEDBUILDIDASSIGNMENTRULE._serialized_end = 2905 - _TIMESTAMPEDCOMPATIBLEBUILDIDREDIRECTRULE._serialized_start = 2908 - _TIMESTAMPEDCOMPATIBLEBUILDIDREDIRECTRULE._serialized_end = 3071 - _POLLERGROUPINFO._serialized_start = 3073 - _POLLERGROUPINFO._serialized_end = 3118 - _POLLERSCALINGDECISION._serialized_start = 3120 - _POLLERSCALINGDECISION._serialized_end = 3182 - _RATELIMIT._serialized_start = 3184 - _RATELIMIT._serialized_end = 3224 - _CONFIGMETADATA._serialized_start = 3226 - _CONFIGMETADATA._serialized_end = 3332 - _RATELIMITCONFIG._serialized_start = 3335 - _RATELIMITCONFIG._serialized_end = 3471 - _TASKQUEUECONFIG._serialized_start = 3474 - _TASKQUEUECONFIG._serialized_end = 3819 - _TASKQUEUECONFIG_FAIRNESSWEIGHTOVERRIDESENTRY._serialized_start = 3757 - _TASKQUEUECONFIG_FAIRNESSWEIGHTOVERRIDESENTRY._serialized_end = 3819 + _TASKQUEUESTATS._serialized_end = 1517 + _TASKQUEUESTATUS._serialized_start = 1520 + _TASKQUEUESTATUS._serialized_end = 1692 + _TASKIDBLOCK._serialized_start = 1694 + _TASKIDBLOCK._serialized_end = 1741 + _TASKQUEUEPARTITIONMETADATA._serialized_start = 1743 + _TASKQUEUEPARTITIONMETADATA._serialized_end = 1809 + _POLLERINFO._serialized_start = 1812 + _POLLERINFO._serialized_end = 2094 + _STICKYEXECUTIONATTRIBUTES._serialized_start = 2097 + _STICKYEXECUTIONATTRIBUTES._serialized_end = 2251 + _COMPATIBLEVERSIONSET._serialized_start = 2253 + _COMPATIBLEVERSIONSET._serialized_end = 2294 + _TASKQUEUEREACHABILITY._serialized_start = 2296 + _TASKQUEUEREACHABILITY._serialized_end = 2402 + _BUILDIDREACHABILITY._serialized_start = 2404 + _BUILDIDREACHABILITY._serialized_end = 2526 + _RAMPBYPERCENTAGE._serialized_start = 2528 + _RAMPBYPERCENTAGE._serialized_end = 2571 + _BUILDIDASSIGNMENTRULE._serialized_start = 2574 + _BUILDIDASSIGNMENTRULE._serialized_end = 2702 + _COMPATIBLEBUILDIDREDIRECTRULE._serialized_start = 2704 + _COMPATIBLEBUILDIDREDIRECTRULE._serialized_end = 2785 + _TIMESTAMPEDBUILDIDASSIGNMENTRULE._serialized_start = 2788 + _TIMESTAMPEDBUILDIDASSIGNMENTRULE._serialized_end = 2935 + _TIMESTAMPEDCOMPATIBLEBUILDIDREDIRECTRULE._serialized_start = 2938 + _TIMESTAMPEDCOMPATIBLEBUILDIDREDIRECTRULE._serialized_end = 3101 + _POLLERGROUPINFO._serialized_start = 3103 + _POLLERGROUPINFO._serialized_end = 3148 + _POLLERGROUPSINFO._serialized_start = 3150 + _POLLERGROUPSINFO._serialized_end = 3252 + _POLLERSCALINGDECISION._serialized_start = 3254 + _POLLERSCALINGDECISION._serialized_end = 3316 + _RATELIMIT._serialized_start = 3318 + _RATELIMIT._serialized_end = 3358 + _CONFIGMETADATA._serialized_start = 3360 + _CONFIGMETADATA._serialized_end = 3466 + _RATELIMITCONFIG._serialized_start = 3469 + _RATELIMITCONFIG._serialized_end = 3605 + _TASKQUEUECONFIG._serialized_start = 3608 + _TASKQUEUECONFIG._serialized_end = 3953 + _TASKQUEUECONFIG_FAIRNESSWEIGHTOVERRIDESENTRY._serialized_start = 3891 + _TASKQUEUECONFIG_FAIRNESSWEIGHTOVERRIDESENTRY._serialized_end = 3953 # @@protoc_insertion_point(module_scope) diff --git a/temporalio/api/taskqueue/v1/message_pb2.pyi b/temporalio/api/taskqueue/v1/message_pb2.pyi index e614430d6..3b43a559f 100644 --- a/temporalio/api/taskqueue/v1/message_pb2.pyi +++ b/temporalio/api/taskqueue/v1/message_pb2.pyi @@ -316,6 +316,7 @@ class TaskQueueStats(google.protobuf.message.Message): APPROXIMATE_BACKLOG_AGE_FIELD_NUMBER: builtins.int TASKS_ADD_RATE_FIELD_NUMBER: builtins.int TASKS_DISPATCH_RATE_FIELD_NUMBER: builtins.int + RATE_LIMITING_ACTIVE_FIELD_NUMBER: builtins.int approximate_backlog_count: builtins.int """The approximate number of tasks backlogged in this task queue. May count expired tasks but eventually converges to the right value. Can be relied upon for scaling decisions. @@ -365,6 +366,12 @@ class TaskQueueStats(google.protobuf.message.Message): workflow goes to a normal queue, and the rest workflow tasks go to the Sticky queue associated with a specific worker instance. """ + rate_limiting_active: builtins.bool + """Whether rate limiting blocked any dispatches within the recent observation window (approximately + 30 seconds). When true, adding more workers will not increase throughput — the bottleneck is the + rate limit, not worker count. This field is useful for auto-scaling systems to avoid unnecessary + scale-up. + """ def __init__( self, *, @@ -372,6 +379,7 @@ class TaskQueueStats(google.protobuf.message.Message): approximate_backlog_age: google.protobuf.duration_pb2.Duration | None = ..., tasks_add_rate: builtins.float = ..., tasks_dispatch_rate: builtins.float = ..., + rate_limiting_active: builtins.bool = ..., ) -> None: ... def HasField( self, @@ -386,6 +394,8 @@ class TaskQueueStats(google.protobuf.message.Message): b"approximate_backlog_age", "approximate_backlog_count", b"approximate_backlog_count", + "rate_limiting_active", + b"rate_limiting_active", "tasks_add_rate", b"tasks_add_rate", "tasks_dispatch_rate", @@ -914,6 +924,42 @@ class PollerGroupInfo(google.protobuf.message.Message): global___PollerGroupInfo = PollerGroupInfo +class PollerGroupsInfo(google.protobuf.message.Message): + """A versioned snapshot of the poller groups the client should use for future polls to a task + queue. The version is monotonically increasing so that a client can ignore a snapshot that is + older than the one it has already applied. + """ + + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + VERSION_FIELD_NUMBER: builtins.int + POLLER_GROUPS_FIELD_NUMBER: builtins.int + version: builtins.int + """Monotonically increasing version of this snapshot. A client should ignore any snapshot whose + version is not greater than the one it last applied. + """ + @property + def poller_groups( + self, + ) -> google.protobuf.internal.containers.RepeatedCompositeFieldContainer[ + global___PollerGroupInfo + ]: + """The weighted list of poller groups the client should use for future polls to this task queue.""" + def __init__( + self, + *, + version: builtins.int = ..., + poller_groups: collections.abc.Iterable[global___PollerGroupInfo] | None = ..., + ) -> None: ... + def ClearField( + self, + field_name: typing_extensions.Literal[ + "poller_groups", b"poller_groups", "version", b"version" + ], + ) -> None: ... + +global___PollerGroupsInfo = PollerGroupsInfo + class PollerScalingDecision(google.protobuf.message.Message): """Attached to task responses to give hints to the SDK about how it may adjust its number of pollers. diff --git a/temporalio/api/workflowservice/v1/request_response_pb2.py b/temporalio/api/workflowservice/v1/request_response_pb2.py index baabaf6ad..8f73b5c4c 100644 --- a/temporalio/api/workflowservice/v1/request_response_pb2.py +++ b/temporalio/api/workflowservice/v1/request_response_pb2.py @@ -128,7 +128,7 @@ ) DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile( - b'\n6temporal/api/workflowservice/v1/request_response.proto\x12\x1ftemporal.api.workflowservice.v1\x1a+temporal/api/enums/v1/batch_operation.proto\x1a"temporal/api/enums/v1/common.proto\x1a$temporal/api/enums/v1/workflow.proto\x1a%temporal/api/enums/v1/namespace.proto\x1a(temporal/api/enums/v1/failed_cause.proto\x1a!temporal/api/enums/v1/query.proto\x1a!temporal/api/enums/v1/reset.proto\x1a&temporal/api/enums/v1/task_queue.proto\x1a&temporal/api/enums/v1/deployment.proto\x1a"temporal/api/enums/v1/update.proto\x1a$temporal/api/enums/v1/activity.proto\x1a!temporal/api/enums/v1/nexus.proto\x1a&temporal/api/activity/v1/message.proto\x1a$temporal/api/common/v1/message.proto\x1a%temporal/api/history/v1/message.proto\x1a&temporal/api/workflow/v1/message.proto\x1a%temporal/api/command/v1/message.proto\x1a$temporal/api/compute/v1/config.proto\x1a(temporal/api/deployment/v1/message.proto\x1a%temporal/api/failure/v1/message.proto\x1a$temporal/api/filter/v1/message.proto\x1a&temporal/api/protocol/v1/message.proto\x1a\'temporal/api/namespace/v1/message.proto\x1a#temporal/api/query/v1/message.proto\x1a)temporal/api/replication/v1/message.proto\x1a#temporal/api/rules/v1/message.proto\x1a\'temporal/api/sdk/v1/worker_config.proto\x1a&temporal/api/schedule/v1/message.proto\x1a\'temporal/api/taskqueue/v1/message.proto\x1a$temporal/api/update/v1/message.proto\x1a%temporal/api/version/v1/message.proto\x1a#temporal/api/batch/v1/message.proto\x1a\x30temporal/api/sdk/v1/task_complete_metadata.proto\x1a\'temporal/api/sdk/v1/user_metadata.proto\x1a#temporal/api/nexus/v1/message.proto\x1a$temporal/api/worker/v1/message.proto\x1a\x1egoogle/protobuf/duration.proto\x1a google/protobuf/field_mask.proto\x1a\x1fgoogle/protobuf/timestamp.proto"\x88\x05\n\x18RegisterNamespaceRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0b\x64\x65scription\x18\x02 \x01(\t\x12\x13\n\x0bowner_email\x18\x03 \x01(\t\x12\x46\n#workflow_execution_retention_period\x18\x04 \x01(\x0b\x32\x19.google.protobuf.Duration\x12G\n\x08\x63lusters\x18\x05 \x03(\x0b\x32\x35.temporal.api.replication.v1.ClusterReplicationConfig\x12\x1b\n\x13\x61\x63tive_cluster_name\x18\x06 \x01(\t\x12Q\n\x04\x64\x61ta\x18\x07 \x03(\x0b\x32\x43.temporal.api.workflowservice.v1.RegisterNamespaceRequest.DataEntry\x12\x16\n\x0esecurity_token\x18\x08 \x01(\t\x12\x1b\n\x13is_global_namespace\x18\t \x01(\x08\x12\x44\n\x16history_archival_state\x18\n \x01(\x0e\x32$.temporal.api.enums.v1.ArchivalState\x12\x1c\n\x14history_archival_uri\x18\x0b \x01(\t\x12G\n\x19visibility_archival_state\x18\x0c \x01(\x0e\x32$.temporal.api.enums.v1.ArchivalState\x12\x1f\n\x17visibility_archival_uri\x18\r \x01(\t\x1a+\n\tDataEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01"\x1b\n\x19RegisterNamespaceResponse"\x89\x01\n\x15ListNamespacesRequest\x12\x11\n\tpage_size\x18\x01 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c\x12\x44\n\x10namespace_filter\x18\x03 \x01(\x0b\x32*.temporal.api.namespace.v1.NamespaceFilter"\x81\x01\n\x16ListNamespacesResponse\x12N\n\nnamespaces\x18\x01 \x03(\x0b\x32:.temporal.api.workflowservice.v1.DescribeNamespaceResponse\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c"S\n\x18\x44\x65scribeNamespaceRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\n\n\x02id\x18\x02 \x01(\t\x12\x18\n\x10weak_consistency\x18\x03 \x01(\x08"\xb4\x03\n\x19\x44\x65scribeNamespaceResponse\x12@\n\x0enamespace_info\x18\x01 \x01(\x0b\x32(.temporal.api.namespace.v1.NamespaceInfo\x12:\n\x06\x63onfig\x18\x02 \x01(\x0b\x32*.temporal.api.namespace.v1.NamespaceConfig\x12S\n\x12replication_config\x18\x03 \x01(\x0b\x32\x37.temporal.api.replication.v1.NamespaceReplicationConfig\x12\x18\n\x10\x66\x61ilover_version\x18\x04 \x01(\x03\x12\x1b\n\x13is_global_namespace\x18\x05 \x01(\x08\x12\x45\n\x10\x66\x61ilover_history\x18\x06 \x03(\x0b\x32+.temporal.api.replication.v1.FailoverStatus\x12\x46\n\x12poller_group_infos\x18\x07 \x03(\x0b\x32*.temporal.api.taskqueue.v1.PollerGroupInfo"\xcf\x02\n\x16UpdateNamespaceRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x43\n\x0bupdate_info\x18\x02 \x01(\x0b\x32..temporal.api.namespace.v1.UpdateNamespaceInfo\x12:\n\x06\x63onfig\x18\x03 \x01(\x0b\x32*.temporal.api.namespace.v1.NamespaceConfig\x12S\n\x12replication_config\x18\x04 \x01(\x0b\x32\x37.temporal.api.replication.v1.NamespaceReplicationConfig\x12\x16\n\x0esecurity_token\x18\x05 \x01(\t\x12\x19\n\x11\x64\x65lete_bad_binary\x18\x06 \x01(\t\x12\x19\n\x11promote_namespace\x18\x07 \x01(\x08"\xa3\x02\n\x17UpdateNamespaceResponse\x12@\n\x0enamespace_info\x18\x01 \x01(\x0b\x32(.temporal.api.namespace.v1.NamespaceInfo\x12:\n\x06\x63onfig\x18\x02 \x01(\x0b\x32*.temporal.api.namespace.v1.NamespaceConfig\x12S\n\x12replication_config\x18\x03 \x01(\x0b\x32\x37.temporal.api.replication.v1.NamespaceReplicationConfig\x12\x18\n\x10\x66\x61ilover_version\x18\x04 \x01(\x03\x12\x1b\n\x13is_global_namespace\x18\x05 \x01(\x08"F\n\x19\x44\x65precateNamespaceRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x16\n\x0esecurity_token\x18\x02 \x01(\t"\x1c\n\x1a\x44\x65precateNamespaceResponse"\xd1\x0c\n\x1dStartWorkflowExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12;\n\rworkflow_type\x18\x03 \x01(\x0b\x32$.temporal.api.common.v1.WorkflowType\x12\x38\n\ntask_queue\x18\x04 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12/\n\x05input\x18\x05 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12=\n\x1aworkflow_execution_timeout\x18\x06 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x37\n\x14workflow_run_timeout\x18\x07 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x38\n\x15workflow_task_timeout\x18\x08 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x10\n\x08identity\x18\t \x01(\t\x12\x12\n\nrequest_id\x18\n \x01(\t\x12N\n\x18workflow_id_reuse_policy\x18\x0b \x01(\x0e\x32,.temporal.api.enums.v1.WorkflowIdReusePolicy\x12T\n\x1bworkflow_id_conflict_policy\x18\x16 \x01(\x0e\x32/.temporal.api.enums.v1.WorkflowIdConflictPolicy\x12\x39\n\x0cretry_policy\x18\x0c \x01(\x0b\x32#.temporal.api.common.v1.RetryPolicy\x12\x15\n\rcron_schedule\x18\r \x01(\t\x12*\n\x04memo\x18\x0e \x01(\x0b\x32\x1c.temporal.api.common.v1.Memo\x12\x43\n\x11search_attributes\x18\x0f \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes\x12.\n\x06header\x18\x10 \x01(\x0b\x32\x1e.temporal.api.common.v1.Header\x12\x1f\n\x17request_eager_execution\x18\x11 \x01(\x08\x12;\n\x11\x63ontinued_failure\x18\x12 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12@\n\x16last_completion_result\x18\x13 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x37\n\x14workflow_start_delay\x18\x14 \x01(\x0b\x32\x19.google.protobuf.Duration\x12>\n\x14\x63ompletion_callbacks\x18\x15 \x03(\x0b\x32 .temporal.api.common.v1.Callback\x12\x38\n\ruser_metadata\x18\x17 \x01(\x0b\x32!.temporal.api.sdk.v1.UserMetadata\x12+\n\x05links\x18\x18 \x03(\x0b\x32\x1c.temporal.api.common.v1.Link\x12I\n\x13versioning_override\x18\x19 \x01(\x0b\x32,.temporal.api.workflow.v1.VersioningOverride\x12H\n\x13on_conflict_options\x18\x1a \x01(\x0b\x32+.temporal.api.workflow.v1.OnConflictOptions\x12\x32\n\x08priority\x18\x1b \x01(\x0b\x32 .temporal.api.common.v1.Priority\x12\\\n\x1f\x65\x61ger_worker_deployment_options\x18\x1c \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentOptions\x12H\n\x14time_skipping_config\x18\x1d \x01(\x0b\x32*.temporal.api.common.v1.TimeSkippingConfig"\x8a\x02\n\x1eStartWorkflowExecutionResponse\x12\x0e\n\x06run_id\x18\x01 \x01(\t\x12\x0f\n\x07started\x18\x03 \x01(\x08\x12>\n\x06status\x18\x05 \x01(\x0e\x32..temporal.api.enums.v1.WorkflowExecutionStatus\x12[\n\x13\x65\x61ger_workflow_task\x18\x02 \x01(\x0b\x32>.temporal.api.workflowservice.v1.PollWorkflowTaskQueueResponse\x12*\n\x04link\x18\x04 \x01(\x0b\x32\x1c.temporal.api.common.v1.Link"\xaa\x02\n"GetWorkflowExecutionHistoryRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12<\n\texecution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x19\n\x11maximum_page_size\x18\x03 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x04 \x01(\x0c\x12\x16\n\x0ewait_new_event\x18\x05 \x01(\x08\x12P\n\x19history_event_filter_type\x18\x06 \x01(\x0e\x32-.temporal.api.enums.v1.HistoryEventFilterType\x12\x15\n\rskip_archival\x18\x07 \x01(\x08"\xba\x01\n#GetWorkflowExecutionHistoryResponse\x12\x31\n\x07history\x18\x01 \x01(\x0b\x32 .temporal.api.history.v1.History\x12\x35\n\x0braw_history\x18\x02 \x03(\x0b\x32 .temporal.api.common.v1.DataBlob\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c\x12\x10\n\x08\x61rchived\x18\x04 \x01(\x08"\xb0\x01\n)GetWorkflowExecutionHistoryReverseRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12<\n\texecution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x19\n\x11maximum_page_size\x18\x03 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x04 \x01(\x0c"x\n*GetWorkflowExecutionHistoryReverseResponse\x12\x31\n\x07history\x18\x01 \x01(\x0b\x32 .temporal.api.history.v1.History\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c"\xb8\x03\n\x1cPollWorkflowTaskQueueRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x38\n\ntask_queue\x18\x02 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12\x17\n\x0fpoller_group_id\x18\n \x01(\t\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x1b\n\x13worker_instance_key\x18\x08 \x01(\t\x12!\n\x19worker_control_task_queue\x18\t \x01(\t\x12\x1b\n\x0f\x62inary_checksum\x18\x04 \x01(\tB\x02\x18\x01\x12Z\n\x1bworker_version_capabilities\x18\x05 \x01(\x0b\x32\x31.temporal.api.common.v1.WorkerVersionCapabilitiesB\x02\x18\x01\x12O\n\x12\x64\x65ployment_options\x18\x06 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentOptionsJ\x04\x08\x07\x10\x08R\x10worker_heartbeat"\xf2\x07\n\x1dPollWorkflowTaskQueueResponse\x12\x12\n\ntask_token\x18\x01 \x01(\x0c\x12\x45\n\x12workflow_execution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12;\n\rworkflow_type\x18\x03 \x01(\x0b\x32$.temporal.api.common.v1.WorkflowType\x12!\n\x19previous_started_event_id\x18\x04 \x01(\x03\x12\x18\n\x10started_event_id\x18\x05 \x01(\x03\x12\x0f\n\x07\x61ttempt\x18\x06 \x01(\x05\x12\x1a\n\x12\x62\x61\x63klog_count_hint\x18\x07 \x01(\x03\x12\x31\n\x07history\x18\x08 \x01(\x0b\x32 .temporal.api.history.v1.History\x12\x17\n\x0fnext_page_token\x18\t \x01(\x0c\x12\x33\n\x05query\x18\n \x01(\x0b\x32$.temporal.api.query.v1.WorkflowQuery\x12K\n\x1dworkflow_execution_task_queue\x18\x0b \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12\x32\n\x0escheduled_time\x18\x0c \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x30\n\x0cstarted_time\x18\r \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\\\n\x07queries\x18\x0e \x03(\x0b\x32K.temporal.api.workflowservice.v1.PollWorkflowTaskQueueResponse.QueriesEntry\x12\x33\n\x08messages\x18\x0f \x03(\x0b\x32!.temporal.api.protocol.v1.Message\x12Q\n\x17poller_scaling_decision\x18\x10 \x01(\x0b\x32\x30.temporal.api.taskqueue.v1.PollerScalingDecision\x12\x17\n\x0fpoller_group_id\x18\x11 \x01(\t\x12\x46\n\x12poller_group_infos\x18\x12 \x03(\x0b\x32*.temporal.api.taskqueue.v1.PollerGroupInfo\x1aT\n\x0cQueriesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x33\n\x05value\x18\x02 \x01(\x0b\x32$.temporal.api.query.v1.WorkflowQuery:\x02\x38\x01"\x8a\n\n#RespondWorkflowTaskCompletedRequest\x12\x12\n\ntask_token\x18\x01 \x01(\x0c\x12\x32\n\x08\x63ommands\x18\x02 \x03(\x0b\x32 .temporal.api.command.v1.Command\x12\x10\n\x08identity\x18\x03 \x01(\t\x12O\n\x11sticky_attributes\x18\x04 \x01(\x0b\x32\x34.temporal.api.taskqueue.v1.StickyExecutionAttributes\x12 \n\x18return_new_workflow_task\x18\x05 \x01(\x08\x12&\n\x1e\x66orce_create_new_workflow_task\x18\x06 \x01(\x08\x12\x1b\n\x0f\x62inary_checksum\x18\x07 \x01(\tB\x02\x18\x01\x12m\n\rquery_results\x18\x08 \x03(\x0b\x32V.temporal.api.workflowservice.v1.RespondWorkflowTaskCompletedRequest.QueryResultsEntry\x12\x11\n\tnamespace\x18\t \x01(\t\x12\x13\n\x0bresource_id\x18\x12 \x01(\t\x12L\n\x14worker_version_stamp\x18\n \x01(\x0b\x32*.temporal.api.common.v1.WorkerVersionStampB\x02\x18\x01\x12\x33\n\x08messages\x18\x0b \x03(\x0b\x32!.temporal.api.protocol.v1.Message\x12H\n\x0csdk_metadata\x18\x0c \x01(\x0b\x32\x32.temporal.api.sdk.v1.WorkflowTaskCompletedMetadata\x12\x43\n\x11metering_metadata\x18\r \x01(\x0b\x32(.temporal.api.common.v1.MeteringMetadata\x12g\n\x0c\x63\x61pabilities\x18\x0e \x01(\x0b\x32Q.temporal.api.workflowservice.v1.RespondWorkflowTaskCompletedRequest.Capabilities\x12>\n\ndeployment\x18\x0f \x01(\x0b\x32&.temporal.api.deployment.v1.DeploymentB\x02\x18\x01\x12\x46\n\x13versioning_behavior\x18\x10 \x01(\x0e\x32).temporal.api.enums.v1.VersioningBehavior\x12O\n\x12\x64\x65ployment_options\x18\x11 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentOptions\x12\x1b\n\x13worker_instance_key\x18\x13 \x01(\t\x12!\n\x19worker_control_task_queue\x18\x14 \x01(\t\x1a_\n\x11QueryResultsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x39\n\x05value\x18\x02 \x01(\x0b\x32*.temporal.api.query.v1.WorkflowQueryResult:\x02\x38\x01\x1a\x45\n\x0c\x43\x61pabilities\x12\x35\n-discard_speculative_workflow_task_with_events\x18\x01 \x01(\x08"\xf5\x01\n$RespondWorkflowTaskCompletedResponse\x12U\n\rworkflow_task\x18\x01 \x01(\x0b\x32>.temporal.api.workflowservice.v1.PollWorkflowTaskQueueResponse\x12V\n\x0e\x61\x63tivity_tasks\x18\x02 \x03(\x0b\x32>.temporal.api.workflowservice.v1.PollActivityTaskQueueResponse\x12\x1e\n\x16reset_history_event_id\x18\x03 \x01(\x03"\x8d\x04\n RespondWorkflowTaskFailedRequest\x12\x12\n\ntask_token\x18\x01 \x01(\x0c\x12=\n\x05\x63\x61use\x18\x02 \x01(\x0e\x32..temporal.api.enums.v1.WorkflowTaskFailedCause\x12\x31\n\x07\x66\x61ilure\x18\x03 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12\x10\n\x08identity\x18\x04 \x01(\t\x12\x1b\n\x0f\x62inary_checksum\x18\x05 \x01(\tB\x02\x18\x01\x12\x11\n\tnamespace\x18\x06 \x01(\t\x12\x13\n\x0bresource_id\x18\x0b \x01(\t\x12\x33\n\x08messages\x18\x07 \x03(\x0b\x32!.temporal.api.protocol.v1.Message\x12\x46\n\x0eworker_version\x18\x08 \x01(\x0b\x32*.temporal.api.common.v1.WorkerVersionStampB\x02\x18\x01\x12>\n\ndeployment\x18\t \x01(\x0b\x32&.temporal.api.deployment.v1.DeploymentB\x02\x18\x01\x12O\n\x12\x64\x65ployment_options\x18\n \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentOptions"#\n!RespondWorkflowTaskFailedResponse"\xe6\x03\n\x1cPollActivityTaskQueueRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x38\n\ntask_queue\x18\x02 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12\x17\n\x0fpoller_group_id\x18\n \x01(\t\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x1b\n\x13worker_instance_key\x18\x08 \x01(\t\x12!\n\x19worker_control_task_queue\x18\t \x01(\t\x12I\n\x13task_queue_metadata\x18\x04 \x01(\x0b\x32,.temporal.api.taskqueue.v1.TaskQueueMetadata\x12Z\n\x1bworker_version_capabilities\x18\x05 \x01(\x0b\x32\x31.temporal.api.common.v1.WorkerVersionCapabilitiesB\x02\x18\x01\x12O\n\x12\x64\x65ployment_options\x18\x06 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentOptionsJ\x04\x08\x07\x10\x08R\x10worker_heartbeat"\xd0\x08\n\x1dPollActivityTaskQueueResponse\x12\x12\n\ntask_token\x18\x01 \x01(\x0c\x12\x1a\n\x12workflow_namespace\x18\x02 \x01(\t\x12;\n\rworkflow_type\x18\x03 \x01(\x0b\x32$.temporal.api.common.v1.WorkflowType\x12\x45\n\x12workflow_execution\x18\x04 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12;\n\ractivity_type\x18\x05 \x01(\x0b\x32$.temporal.api.common.v1.ActivityType\x12\x13\n\x0b\x61\x63tivity_id\x18\x06 \x01(\t\x12.\n\x06header\x18\x07 \x01(\x0b\x32\x1e.temporal.api.common.v1.Header\x12/\n\x05input\x18\x08 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12;\n\x11heartbeat_details\x18\t \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x32\n\x0escheduled_time\x18\n \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x42\n\x1e\x63urrent_attempt_scheduled_time\x18\x0b \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x30\n\x0cstarted_time\x18\x0c \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x0f\n\x07\x61ttempt\x18\r \x01(\x05\x12<\n\x19schedule_to_close_timeout\x18\x0e \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x39\n\x16start_to_close_timeout\x18\x0f \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x34\n\x11heartbeat_timeout\x18\x10 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x39\n\x0cretry_policy\x18\x11 \x01(\x0b\x32#.temporal.api.common.v1.RetryPolicy\x12Q\n\x17poller_scaling_decision\x18\x12 \x01(\x0b\x32\x30.temporal.api.taskqueue.v1.PollerScalingDecision\x12\x32\n\x08priority\x18\x13 \x01(\x0b\x32 .temporal.api.common.v1.Priority\x12\x17\n\x0f\x61\x63tivity_run_id\x18\x14 \x01(\t\x12\x46\n\x12poller_group_infos\x18\x15 \x03(\x0b\x32*.temporal.api.taskqueue.v1.PollerGroupInfo"\xa5\x01\n"RecordActivityTaskHeartbeatRequest\x12\x12\n\ntask_token\x18\x01 \x01(\x0c\x12\x31\n\x07\x64\x65tails\x18\x02 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x11\n\tnamespace\x18\x04 \x01(\t\x12\x13\n\x0bresource_id\x18\x05 \x01(\t"p\n#RecordActivityTaskHeartbeatResponse\x12\x18\n\x10\x63\x61ncel_requested\x18\x01 \x01(\x08\x12\x17\n\x0f\x61\x63tivity_paused\x18\x02 \x01(\x08\x12\x16\n\x0e\x61\x63tivity_reset\x18\x03 \x01(\x08"\xcf\x01\n&RecordActivityTaskHeartbeatByIdRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x12\x13\n\x0b\x61\x63tivity_id\x18\x04 \x01(\t\x12\x31\n\x07\x64\x65tails\x18\x05 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x10\n\x08identity\x18\x06 \x01(\t\x12\x13\n\x0bresource_id\x18\x07 \x01(\t"t\n\'RecordActivityTaskHeartbeatByIdResponse\x12\x18\n\x10\x63\x61ncel_requested\x18\x01 \x01(\x08\x12\x17\n\x0f\x61\x63tivity_paused\x18\x02 \x01(\x08\x12\x16\n\x0e\x61\x63tivity_reset\x18\x03 \x01(\x08"\xfe\x02\n#RespondActivityTaskCompletedRequest\x12\x12\n\ntask_token\x18\x01 \x01(\x0c\x12\x30\n\x06result\x18\x02 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x11\n\tnamespace\x18\x04 \x01(\t\x12\x13\n\x0bresource_id\x18\x08 \x01(\t\x12\x46\n\x0eworker_version\x18\x05 \x01(\x0b\x32*.temporal.api.common.v1.WorkerVersionStampB\x02\x18\x01\x12>\n\ndeployment\x18\x06 \x01(\x0b\x32&.temporal.api.deployment.v1.DeploymentB\x02\x18\x01\x12O\n\x12\x64\x65ployment_options\x18\x07 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentOptions"&\n$RespondActivityTaskCompletedResponse"\xcf\x01\n\'RespondActivityTaskCompletedByIdRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x12\x13\n\x0b\x61\x63tivity_id\x18\x04 \x01(\t\x12\x30\n\x06result\x18\x05 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x10\n\x08identity\x18\x06 \x01(\t\x12\x13\n\x0bresource_id\x18\x07 \x01(\t"*\n(RespondActivityTaskCompletedByIdResponse"\xbe\x03\n RespondActivityTaskFailedRequest\x12\x12\n\ntask_token\x18\x01 \x01(\x0c\x12\x31\n\x07\x66\x61ilure\x18\x02 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x11\n\tnamespace\x18\x04 \x01(\t\x12\x13\n\x0bresource_id\x18\t \x01(\t\x12@\n\x16last_heartbeat_details\x18\x05 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x46\n\x0eworker_version\x18\x06 \x01(\x0b\x32*.temporal.api.common.v1.WorkerVersionStampB\x02\x18\x01\x12>\n\ndeployment\x18\x07 \x01(\x0b\x32&.temporal.api.deployment.v1.DeploymentB\x02\x18\x01\x12O\n\x12\x64\x65ployment_options\x18\x08 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentOptions"W\n!RespondActivityTaskFailedResponse\x12\x32\n\x08\x66\x61ilures\x18\x01 \x03(\x0b\x32 .temporal.api.failure.v1.Failure"\x8f\x02\n$RespondActivityTaskFailedByIdRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x12\x13\n\x0b\x61\x63tivity_id\x18\x04 \x01(\t\x12\x31\n\x07\x66\x61ilure\x18\x05 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12\x10\n\x08identity\x18\x06 \x01(\t\x12@\n\x16last_heartbeat_details\x18\x07 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x13\n\x0bresource_id\x18\x08 \x01(\t"[\n%RespondActivityTaskFailedByIdResponse\x12\x32\n\x08\x66\x61ilures\x18\x01 \x03(\x0b\x32 .temporal.api.failure.v1.Failure"\xfe\x02\n"RespondActivityTaskCanceledRequest\x12\x12\n\ntask_token\x18\x01 \x01(\x0c\x12\x31\n\x07\x64\x65tails\x18\x02 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x11\n\tnamespace\x18\x04 \x01(\t\x12\x13\n\x0bresource_id\x18\x08 \x01(\t\x12\x46\n\x0eworker_version\x18\x05 \x01(\x0b\x32*.temporal.api.common.v1.WorkerVersionStampB\x02\x18\x01\x12>\n\ndeployment\x18\x06 \x01(\x0b\x32&.temporal.api.deployment.v1.DeploymentB\x02\x18\x01\x12O\n\x12\x64\x65ployment_options\x18\x07 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentOptions"%\n#RespondActivityTaskCanceledResponse"\xa0\x02\n&RespondActivityTaskCanceledByIdRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x12\x13\n\x0b\x61\x63tivity_id\x18\x04 \x01(\t\x12\x31\n\x07\x64\x65tails\x18\x05 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x10\n\x08identity\x18\x06 \x01(\t\x12O\n\x12\x64\x65ployment_options\x18\x07 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentOptions\x12\x13\n\x0bresource_id\x18\x08 \x01(\t")\n\'RespondActivityTaskCanceledByIdResponse"\x84\x02\n%RequestCancelWorkflowExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x45\n\x12workflow_execution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x12\n\nrequest_id\x18\x04 \x01(\t\x12\x1e\n\x16\x66irst_execution_run_id\x18\x05 \x01(\t\x12\x0e\n\x06reason\x18\x06 \x01(\t\x12+\n\x05links\x18\x07 \x03(\x0b\x32\x1c.temporal.api.common.v1.Link"(\n&RequestCancelWorkflowExecutionResponse"\xde\x02\n\x1eSignalWorkflowExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x45\n\x12workflow_execution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x13\n\x0bsignal_name\x18\x03 \x01(\t\x12/\n\x05input\x18\x04 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x10\n\x08identity\x18\x05 \x01(\t\x12\x12\n\nrequest_id\x18\x06 \x01(\t\x12\x13\n\x07\x63ontrol\x18\x07 \x01(\tB\x02\x18\x01\x12.\n\x06header\x18\x08 \x01(\x0b\x32\x1e.temporal.api.common.v1.Header\x12+\n\x05links\x18\n \x03(\x0b\x32\x1c.temporal.api.common.v1.LinkJ\x04\x08\t\x10\n"M\n\x1fSignalWorkflowExecutionResponse\x12*\n\x04link\x18\x01 \x01(\x0b\x32\x1c.temporal.api.common.v1.Link"\xbb\n\n\'SignalWithStartWorkflowExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12;\n\rworkflow_type\x18\x03 \x01(\x0b\x32$.temporal.api.common.v1.WorkflowType\x12\x38\n\ntask_queue\x18\x04 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12/\n\x05input\x18\x05 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12=\n\x1aworkflow_execution_timeout\x18\x06 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x37\n\x14workflow_run_timeout\x18\x07 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x38\n\x15workflow_task_timeout\x18\x08 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x10\n\x08identity\x18\t \x01(\t\x12\x12\n\nrequest_id\x18\n \x01(\t\x12N\n\x18workflow_id_reuse_policy\x18\x0b \x01(\x0e\x32,.temporal.api.enums.v1.WorkflowIdReusePolicy\x12T\n\x1bworkflow_id_conflict_policy\x18\x16 \x01(\x0e\x32/.temporal.api.enums.v1.WorkflowIdConflictPolicy\x12\x13\n\x0bsignal_name\x18\x0c \x01(\t\x12\x36\n\x0csignal_input\x18\r \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x13\n\x07\x63ontrol\x18\x0e \x01(\tB\x02\x18\x01\x12\x39\n\x0cretry_policy\x18\x0f \x01(\x0b\x32#.temporal.api.common.v1.RetryPolicy\x12\x15\n\rcron_schedule\x18\x10 \x01(\t\x12*\n\x04memo\x18\x11 \x01(\x0b\x32\x1c.temporal.api.common.v1.Memo\x12\x43\n\x11search_attributes\x18\x12 \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes\x12.\n\x06header\x18\x13 \x01(\x0b\x32\x1e.temporal.api.common.v1.Header\x12\x37\n\x14workflow_start_delay\x18\x14 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x38\n\ruser_metadata\x18\x17 \x01(\x0b\x32!.temporal.api.sdk.v1.UserMetadata\x12+\n\x05links\x18\x18 \x03(\x0b\x32\x1c.temporal.api.common.v1.Link\x12I\n\x13versioning_override\x18\x19 \x01(\x0b\x32,.temporal.api.workflow.v1.VersioningOverride\x12\x32\n\x08priority\x18\x1a \x01(\x0b\x32 .temporal.api.common.v1.Priority\x12H\n\x14time_skipping_config\x18\x1b \x01(\x0b\x32*.temporal.api.common.v1.TimeSkippingConfigJ\x04\x08\x15\x10\x16"~\n(SignalWithStartWorkflowExecutionResponse\x12\x0e\n\x06run_id\x18\x01 \x01(\t\x12\x0f\n\x07started\x18\x02 \x01(\x08\x12\x31\n\x0bsignal_link\x18\x03 \x01(\x0b\x32\x1c.temporal.api.common.v1.Link"\xc1\x03\n\x1dResetWorkflowExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x45\n\x12workflow_execution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x0e\n\x06reason\x18\x03 \x01(\t\x12%\n\x1dworkflow_task_finish_event_id\x18\x04 \x01(\x03\x12\x12\n\nrequest_id\x18\x05 \x01(\t\x12G\n\x12reset_reapply_type\x18\x06 \x01(\x0e\x32\'.temporal.api.enums.v1.ResetReapplyTypeB\x02\x18\x01\x12S\n\x1breset_reapply_exclude_types\x18\x07 \x03(\x0e\x32..temporal.api.enums.v1.ResetReapplyExcludeType\x12K\n\x15post_reset_operations\x18\x08 \x03(\x0b\x32,.temporal.api.workflow.v1.PostResetOperation\x12\x10\n\x08identity\x18\t \x01(\t"0\n\x1eResetWorkflowExecutionResponse\x12\x0e\n\x06run_id\x18\x01 \x01(\t"\x9f\x02\n!TerminateWorkflowExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x45\n\x12workflow_execution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x0e\n\x06reason\x18\x03 \x01(\t\x12\x31\n\x07\x64\x65tails\x18\x04 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x10\n\x08identity\x18\x05 \x01(\t\x12\x1e\n\x16\x66irst_execution_run_id\x18\x06 \x01(\t\x12+\n\x05links\x18\x07 \x03(\x0b\x32\x1c.temporal.api.common.v1.Link"$\n"TerminateWorkflowExecutionResponse"z\n\x1e\x44\x65leteWorkflowExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x45\n\x12workflow_execution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution"!\n\x1f\x44\x65leteWorkflowExecutionResponse"\xc9\x02\n!ListOpenWorkflowExecutionsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x19\n\x11maximum_page_size\x18\x02 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c\x12\x42\n\x11start_time_filter\x18\x04 \x01(\x0b\x32\'.temporal.api.filter.v1.StartTimeFilter\x12K\n\x10\x65xecution_filter\x18\x05 \x01(\x0b\x32/.temporal.api.filter.v1.WorkflowExecutionFilterH\x00\x12\x41\n\x0btype_filter\x18\x06 \x01(\x0b\x32*.temporal.api.filter.v1.WorkflowTypeFilterH\x00\x42\t\n\x07\x66ilters"\x82\x01\n"ListOpenWorkflowExecutionsResponse\x12\x43\n\nexecutions\x18\x01 \x03(\x0b\x32/.temporal.api.workflow.v1.WorkflowExecutionInfo\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c"\x8a\x03\n#ListClosedWorkflowExecutionsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x19\n\x11maximum_page_size\x18\x02 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c\x12\x42\n\x11start_time_filter\x18\x04 \x01(\x0b\x32\'.temporal.api.filter.v1.StartTimeFilter\x12K\n\x10\x65xecution_filter\x18\x05 \x01(\x0b\x32/.temporal.api.filter.v1.WorkflowExecutionFilterH\x00\x12\x41\n\x0btype_filter\x18\x06 \x01(\x0b\x32*.temporal.api.filter.v1.WorkflowTypeFilterH\x00\x12=\n\rstatus_filter\x18\x07 \x01(\x0b\x32$.temporal.api.filter.v1.StatusFilterH\x00\x42\t\n\x07\x66ilters"\x84\x01\n$ListClosedWorkflowExecutionsResponse\x12\x43\n\nexecutions\x18\x01 \x03(\x0b\x32/.temporal.api.workflow.v1.WorkflowExecutionInfo\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c"m\n\x1dListWorkflowExecutionsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x11\n\tpage_size\x18\x02 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c\x12\r\n\x05query\x18\x04 \x01(\t"~\n\x1eListWorkflowExecutionsResponse\x12\x43\n\nexecutions\x18\x01 \x03(\x0b\x32/.temporal.api.workflow.v1.WorkflowExecutionInfo\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c"u\n%ListArchivedWorkflowExecutionsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x11\n\tpage_size\x18\x02 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c\x12\r\n\x05query\x18\x04 \x01(\t"\x86\x01\n&ListArchivedWorkflowExecutionsResponse\x12\x43\n\nexecutions\x18\x01 \x03(\x0b\x32/.temporal.api.workflow.v1.WorkflowExecutionInfo\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c"m\n\x1dScanWorkflowExecutionsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x11\n\tpage_size\x18\x02 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c\x12\r\n\x05query\x18\x04 \x01(\t"~\n\x1eScanWorkflowExecutionsResponse\x12\x43\n\nexecutions\x18\x01 \x03(\x0b\x32/.temporal.api.workflow.v1.WorkflowExecutionInfo\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c"B\n\x1e\x43ountWorkflowExecutionsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\r\n\x05query\x18\x02 \x01(\t"\xed\x01\n\x1f\x43ountWorkflowExecutionsResponse\x12\r\n\x05\x63ount\x18\x01 \x01(\x03\x12\x61\n\x06groups\x18\x02 \x03(\x0b\x32Q.temporal.api.workflowservice.v1.CountWorkflowExecutionsResponse.AggregationGroup\x1aX\n\x10\x41ggregationGroup\x12\x35\n\x0cgroup_values\x18\x01 \x03(\x0b\x32\x1f.temporal.api.common.v1.Payload\x12\r\n\x05\x63ount\x18\x02 \x01(\x03"\x1c\n\x1aGetSearchAttributesRequest"\xc9\x01\n\x1bGetSearchAttributesResponse\x12T\n\x04keys\x18\x01 \x03(\x0b\x32\x46.temporal.api.workflowservice.v1.GetSearchAttributesResponse.KeysEntry\x1aT\n\tKeysEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x36\n\x05value\x18\x02 \x01(\x0e\x32\'.temporal.api.enums.v1.IndexedValueType:\x02\x38\x01"\xe9\x02\n RespondQueryTaskCompletedRequest\x12\x12\n\ntask_token\x18\x01 \x01(\x0c\x12>\n\x0e\x63ompleted_type\x18\x02 \x01(\x0e\x32&.temporal.api.enums.v1.QueryResultType\x12\x36\n\x0cquery_result\x18\x03 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x15\n\rerror_message\x18\x04 \x01(\t\x12\x11\n\tnamespace\x18\x06 \x01(\t\x12\x31\n\x07\x66\x61ilure\x18\x07 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12=\n\x05\x63\x61use\x18\x08 \x01(\x0e\x32..temporal.api.enums.v1.WorkflowTaskFailedCause\x12\x17\n\x0fpoller_group_id\x18\t \x01(\tJ\x04\x08\x05\x10\x06"#\n!RespondQueryTaskCompletedResponse"n\n\x1bResetStickyTaskQueueRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12<\n\texecution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution"\x1e\n\x1cResetStickyTaskQueueResponse"\x9b\x02\n\x15ShutdownWorkerRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x19\n\x11sticky_task_queue\x18\x02 \x01(\t\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x0e\n\x06reason\x18\x04 \x01(\t\x12\x41\n\x10worker_heartbeat\x18\x05 \x01(\x0b\x32\'.temporal.api.worker.v1.WorkerHeartbeat\x12\x1b\n\x13worker_instance_key\x18\x06 \x01(\t\x12\x12\n\ntask_queue\x18\x07 \x01(\t\x12>\n\x10task_queue_types\x18\x08 \x03(\x0e\x32$.temporal.api.enums.v1.TaskQueueType"\x18\n\x16ShutdownWorkerResponse"\xe9\x01\n\x14QueryWorkflowRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12<\n\texecution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x33\n\x05query\x18\x03 \x01(\x0b\x32$.temporal.api.query.v1.WorkflowQuery\x12K\n\x16query_reject_condition\x18\x04 \x01(\x0e\x32+.temporal.api.enums.v1.QueryRejectCondition"\x8d\x01\n\x15QueryWorkflowResponse\x12\x36\n\x0cquery_result\x18\x01 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12<\n\x0equery_rejected\x18\x02 \x01(\x0b\x32$.temporal.api.query.v1.QueryRejected"s\n DescribeWorkflowExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12<\n\texecution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution"\x99\x05\n!DescribeWorkflowExecutionResponse\x12K\n\x10\x65xecution_config\x18\x01 \x01(\x0b\x32\x31.temporal.api.workflow.v1.WorkflowExecutionConfig\x12P\n\x17workflow_execution_info\x18\x02 \x01(\x0b\x32/.temporal.api.workflow.v1.WorkflowExecutionInfo\x12I\n\x12pending_activities\x18\x03 \x03(\x0b\x32-.temporal.api.workflow.v1.PendingActivityInfo\x12M\n\x10pending_children\x18\x04 \x03(\x0b\x32\x33.temporal.api.workflow.v1.PendingChildExecutionInfo\x12P\n\x15pending_workflow_task\x18\x05 \x01(\x0b\x32\x31.temporal.api.workflow.v1.PendingWorkflowTaskInfo\x12\x39\n\tcallbacks\x18\x06 \x03(\x0b\x32&.temporal.api.workflow.v1.CallbackInfo\x12U\n\x18pending_nexus_operations\x18\x07 \x03(\x0b\x32\x33.temporal.api.workflow.v1.PendingNexusOperationInfo\x12W\n\x16workflow_extended_info\x18\x08 \x01(\x0b\x32\x37.temporal.api.workflow.v1.WorkflowExecutionExtendedInfo"\x90\x04\n\x18\x44\x65scribeTaskQueueRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x38\n\ntask_queue\x18\x02 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12=\n\x0ftask_queue_type\x18\x03 \x01(\x0e\x32$.temporal.api.enums.v1.TaskQueueType\x12\x14\n\x0creport_stats\x18\x08 \x01(\x08\x12\x15\n\rreport_config\x18\x0b \x01(\x08\x12%\n\x19include_task_queue_status\x18\x04 \x01(\x08\x42\x02\x18\x01\x12\x42\n\x08\x61pi_mode\x18\x05 \x01(\x0e\x32,.temporal.api.enums.v1.DescribeTaskQueueModeB\x02\x18\x01\x12J\n\x08versions\x18\x06 \x01(\x0b\x32\x34.temporal.api.taskqueue.v1.TaskQueueVersionSelectionB\x02\x18\x01\x12\x42\n\x10task_queue_types\x18\x07 \x03(\x0e\x32$.temporal.api.enums.v1.TaskQueueTypeB\x02\x18\x01\x12\x1a\n\x0ereport_pollers\x18\t \x01(\x08\x42\x02\x18\x01\x12$\n\x18report_task_reachability\x18\n \x01(\x08\x42\x02\x18\x01"\xec\x07\n\x19\x44\x65scribeTaskQueueResponse\x12\x36\n\x07pollers\x18\x01 \x03(\x0b\x32%.temporal.api.taskqueue.v1.PollerInfo\x12\x38\n\x05stats\x18\x05 \x01(\x0b\x32).temporal.api.taskqueue.v1.TaskQueueStats\x12q\n\x15stats_by_priority_key\x18\x08 \x03(\x0b\x32R.temporal.api.workflowservice.v1.DescribeTaskQueueResponse.StatsByPriorityKeyEntry\x12K\n\x0fversioning_info\x18\x04 \x01(\x0b\x32\x32.temporal.api.taskqueue.v1.TaskQueueVersioningInfo\x12:\n\x06\x63onfig\x18\x06 \x01(\x0b\x32*.temporal.api.taskqueue.v1.TaskQueueConfig\x12k\n\x14\x65\x66\x66\x65\x63tive_rate_limit\x18\x07 \x01(\x0b\x32M.temporal.api.workflowservice.v1.DescribeTaskQueueResponse.EffectiveRateLimit\x12I\n\x11task_queue_status\x18\x02 \x01(\x0b\x32*.temporal.api.taskqueue.v1.TaskQueueStatusB\x02\x18\x01\x12g\n\rversions_info\x18\x03 \x03(\x0b\x32L.temporal.api.workflowservice.v1.DescribeTaskQueueResponse.VersionsInfoEntryB\x02\x18\x01\x1a\x64\n\x17StatsByPriorityKeyEntry\x12\x0b\n\x03key\x18\x01 \x01(\x05\x12\x38\n\x05value\x18\x02 \x01(\x0b\x32).temporal.api.taskqueue.v1.TaskQueueStats:\x02\x38\x01\x1at\n\x12\x45\x66\x66\x65\x63tiveRateLimit\x12\x1b\n\x13requests_per_second\x18\x01 \x01(\x02\x12\x41\n\x11rate_limit_source\x18\x02 \x01(\x0e\x32&.temporal.api.enums.v1.RateLimitSource\x1a\x64\n\x11VersionsInfoEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12>\n\x05value\x18\x02 \x01(\x0b\x32/.temporal.api.taskqueue.v1.TaskQueueVersionInfo:\x02\x38\x01"\x17\n\x15GetClusterInfoRequest"\xd1\x03\n\x16GetClusterInfoResponse\x12h\n\x11supported_clients\x18\x01 \x03(\x0b\x32M.temporal.api.workflowservice.v1.GetClusterInfoResponse.SupportedClientsEntry\x12\x16\n\x0eserver_version\x18\x02 \x01(\t\x12\x12\n\ncluster_id\x18\x03 \x01(\t\x12:\n\x0cversion_info\x18\x04 \x01(\x0b\x32$.temporal.api.version.v1.VersionInfo\x12\x14\n\x0c\x63luster_name\x18\x05 \x01(\t\x12\x1b\n\x13history_shard_count\x18\x06 \x01(\x05\x12\x19\n\x11persistence_store\x18\x07 \x01(\t\x12\x18\n\x10visibility_store\x18\x08 \x01(\t\x12 \n\x18initial_failover_version\x18\t \x01(\x03\x12"\n\x1a\x66\x61ilover_version_increment\x18\n \x01(\x03\x1a\x37\n\x15SupportedClientsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01"\x16\n\x14GetSystemInfoRequest"\x97\x04\n\x15GetSystemInfoResponse\x12\x16\n\x0eserver_version\x18\x01 \x01(\t\x12Y\n\x0c\x63\x61pabilities\x18\x02 \x01(\x0b\x32\x43.temporal.api.workflowservice.v1.GetSystemInfoResponse.Capabilities\x1a\x8a\x03\n\x0c\x43\x61pabilities\x12\x1f\n\x17signal_and_query_header\x18\x01 \x01(\x08\x12&\n\x1einternal_error_differentiation\x18\x02 \x01(\x08\x12*\n"activity_failure_include_heartbeat\x18\x03 \x01(\x08\x12\x1a\n\x12supports_schedules\x18\x04 \x01(\x08\x12"\n\x1a\x65ncoded_failure_attributes\x18\x05 \x01(\x08\x12!\n\x19\x62uild_id_based_versioning\x18\x06 \x01(\x08\x12\x13\n\x0bupsert_memo\x18\x07 \x01(\x08\x12\x1c\n\x14\x65\x61ger_workflow_start\x18\x08 \x01(\x08\x12\x14\n\x0csdk_metadata\x18\t \x01(\x08\x12\'\n\x1f\x63ount_group_by_execution_status\x18\n \x01(\x08\x12\r\n\x05nexus\x18\x0b \x01(\x08\x12!\n\x19server_scaled_deployments\x18\x0c \x01(\x08"m\n\x1eListTaskQueuePartitionsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x38\n\ntask_queue\x18\x02 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue"\xdf\x01\n\x1fListTaskQueuePartitionsResponse\x12]\n\x1e\x61\x63tivity_task_queue_partitions\x18\x01 \x03(\x0b\x32\x35.temporal.api.taskqueue.v1.TaskQueuePartitionMetadata\x12]\n\x1eworkflow_task_queue_partitions\x18\x02 \x03(\x0b\x32\x35.temporal.api.taskqueue.v1.TaskQueuePartitionMetadata"\xcc\x02\n\x15\x43reateScheduleRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bschedule_id\x18\x02 \x01(\t\x12\x34\n\x08schedule\x18\x03 \x01(\x0b\x32".temporal.api.schedule.v1.Schedule\x12>\n\rinitial_patch\x18\x04 \x01(\x0b\x32\'.temporal.api.schedule.v1.SchedulePatch\x12\x10\n\x08identity\x18\x05 \x01(\t\x12\x12\n\nrequest_id\x18\x06 \x01(\t\x12*\n\x04memo\x18\x07 \x01(\x0b\x32\x1c.temporal.api.common.v1.Memo\x12\x43\n\x11search_attributes\x18\x08 \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes"0\n\x16\x43reateScheduleResponse\x12\x16\n\x0e\x63onflict_token\x18\x01 \x01(\x0c"A\n\x17\x44\x65scribeScheduleRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bschedule_id\x18\x02 \x01(\t"\x8f\x02\n\x18\x44\x65scribeScheduleResponse\x12\x34\n\x08schedule\x18\x01 \x01(\x0b\x32".temporal.api.schedule.v1.Schedule\x12\x34\n\x04info\x18\x02 \x01(\x0b\x32&.temporal.api.schedule.v1.ScheduleInfo\x12*\n\x04memo\x18\x03 \x01(\x0b\x32\x1c.temporal.api.common.v1.Memo\x12\x43\n\x11search_attributes\x18\x04 \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes\x12\x16\n\x0e\x63onflict_token\x18\x05 \x01(\x0c"\xa4\x02\n\x15UpdateScheduleRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bschedule_id\x18\x02 \x01(\t\x12\x34\n\x08schedule\x18\x03 \x01(\x0b\x32".temporal.api.schedule.v1.Schedule\x12\x16\n\x0e\x63onflict_token\x18\x04 \x01(\x0c\x12\x10\n\x08identity\x18\x05 \x01(\t\x12\x12\n\nrequest_id\x18\x06 \x01(\t\x12\x43\n\x11search_attributes\x18\x07 \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes\x12*\n\x04memo\x18\x08 \x01(\x0b\x32\x1c.temporal.api.common.v1.Memo"\x18\n\x16UpdateScheduleResponse"\x9c\x01\n\x14PatchScheduleRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bschedule_id\x18\x02 \x01(\t\x12\x36\n\x05patch\x18\x03 \x01(\x0b\x32\'.temporal.api.schedule.v1.SchedulePatch\x12\x10\n\x08identity\x18\x04 \x01(\t\x12\x12\n\nrequest_id\x18\x05 \x01(\t"\x17\n\x15PatchScheduleResponse"\xa8\x01\n ListScheduleMatchingTimesRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bschedule_id\x18\x02 \x01(\t\x12.\n\nstart_time\x18\x03 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12,\n\x08\x65nd_time\x18\x04 \x01(\x0b\x32\x1a.google.protobuf.Timestamp"S\n!ListScheduleMatchingTimesResponse\x12.\n\nstart_time\x18\x01 \x03(\x0b\x32\x1a.google.protobuf.Timestamp"Q\n\x15\x44\x65leteScheduleRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bschedule_id\x18\x02 \x01(\t\x12\x10\n\x08identity\x18\x03 \x01(\t"\x18\n\x16\x44\x65leteScheduleResponse"l\n\x14ListSchedulesRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x19\n\x11maximum_page_size\x18\x02 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c\x12\r\n\x05query\x18\x04 \x01(\t"p\n\x15ListSchedulesResponse\x12>\n\tschedules\x18\x01 \x03(\x0b\x32+.temporal.api.schedule.v1.ScheduleListEntry\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c"9\n\x15\x43ountSchedulesRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\r\n\x05query\x18\x02 \x01(\t"\xdb\x01\n\x16\x43ountSchedulesResponse\x12\r\n\x05\x63ount\x18\x01 \x01(\x03\x12X\n\x06groups\x18\x02 \x03(\x0b\x32H.temporal.api.workflowservice.v1.CountSchedulesResponse.AggregationGroup\x1aX\n\x10\x41ggregationGroup\x12\x35\n\x0cgroup_values\x18\x01 \x03(\x0b\x32\x1f.temporal.api.common.v1.Payload\x12\r\n\x05\x63ount\x18\x02 \x01(\x03"\x86\x05\n\'UpdateWorkerBuildIdCompatibilityRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x12\n\ntask_queue\x18\x02 \x01(\t\x12-\n#add_new_build_id_in_new_default_set\x18\x03 \x01(\tH\x00\x12\x87\x01\n\x1b\x61\x64\x64_new_compatible_build_id\x18\x04 \x01(\x0b\x32`.temporal.api.workflowservice.v1.UpdateWorkerBuildIdCompatibilityRequest.AddNewCompatibleVersionH\x00\x12!\n\x17promote_set_by_build_id\x18\x05 \x01(\tH\x00\x12%\n\x1bpromote_build_id_within_set\x18\x06 \x01(\tH\x00\x12h\n\nmerge_sets\x18\x07 \x01(\x0b\x32R.temporal.api.workflowservice.v1.UpdateWorkerBuildIdCompatibilityRequest.MergeSetsH\x00\x1ao\n\x17\x41\x64\x64NewCompatibleVersion\x12\x14\n\x0cnew_build_id\x18\x01 \x01(\t\x12$\n\x1c\x65xisting_compatible_build_id\x18\x02 \x01(\t\x12\x18\n\x10make_set_default\x18\x03 \x01(\x08\x1aI\n\tMergeSets\x12\x1c\n\x14primary_set_build_id\x18\x01 \x01(\t\x12\x1e\n\x16secondary_set_build_id\x18\x02 \x01(\tB\x0b\n\toperation"@\n(UpdateWorkerBuildIdCompatibilityResponseJ\x04\x08\x01\x10\x02R\x0eversion_set_id"_\n$GetWorkerBuildIdCompatibilityRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x12\n\ntask_queue\x18\x02 \x01(\t\x12\x10\n\x08max_sets\x18\x03 \x01(\x05"t\n%GetWorkerBuildIdCompatibilityResponse\x12K\n\x12major_version_sets\x18\x01 \x03(\x0b\x32/.temporal.api.taskqueue.v1.CompatibleVersionSet"\xb5\r\n"UpdateWorkerVersioningRulesRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x12\n\ntask_queue\x18\x02 \x01(\t\x12\x16\n\x0e\x63onflict_token\x18\x03 \x01(\x0c\x12\x81\x01\n\x16insert_assignment_rule\x18\x04 \x01(\x0b\x32_.temporal.api.workflowservice.v1.UpdateWorkerVersioningRulesRequest.InsertBuildIdAssignmentRuleH\x00\x12\x83\x01\n\x17replace_assignment_rule\x18\x05 \x01(\x0b\x32`.temporal.api.workflowservice.v1.UpdateWorkerVersioningRulesRequest.ReplaceBuildIdAssignmentRuleH\x00\x12\x81\x01\n\x16\x64\x65lete_assignment_rule\x18\x06 \x01(\x0b\x32_.temporal.api.workflowservice.v1.UpdateWorkerVersioningRulesRequest.DeleteBuildIdAssignmentRuleH\x00\x12\x8c\x01\n\x1c\x61\x64\x64_compatible_redirect_rule\x18\x07 \x01(\x0b\x32\x64.temporal.api.workflowservice.v1.UpdateWorkerVersioningRulesRequest.AddCompatibleBuildIdRedirectRuleH\x00\x12\x94\x01\n replace_compatible_redirect_rule\x18\x08 \x01(\x0b\x32h.temporal.api.workflowservice.v1.UpdateWorkerVersioningRulesRequest.ReplaceCompatibleBuildIdRedirectRuleH\x00\x12\x92\x01\n\x1f\x64\x65lete_compatible_redirect_rule\x18\t \x01(\x0b\x32g.temporal.api.workflowservice.v1.UpdateWorkerVersioningRulesRequest.DeleteCompatibleBuildIdRedirectRuleH\x00\x12l\n\x0f\x63ommit_build_id\x18\n \x01(\x0b\x32Q.temporal.api.workflowservice.v1.UpdateWorkerVersioningRulesRequest.CommitBuildIdH\x00\x1aq\n\x1bInsertBuildIdAssignmentRule\x12\x12\n\nrule_index\x18\x01 \x01(\x05\x12>\n\x04rule\x18\x02 \x01(\x0b\x32\x30.temporal.api.taskqueue.v1.BuildIdAssignmentRule\x1a\x81\x01\n\x1cReplaceBuildIdAssignmentRule\x12\x12\n\nrule_index\x18\x01 \x01(\x05\x12>\n\x04rule\x18\x02 \x01(\x0b\x32\x30.temporal.api.taskqueue.v1.BuildIdAssignmentRule\x12\r\n\x05\x66orce\x18\x03 \x01(\x08\x1a@\n\x1b\x44\x65leteBuildIdAssignmentRule\x12\x12\n\nrule_index\x18\x01 \x01(\x05\x12\r\n\x05\x66orce\x18\x02 \x01(\x08\x1aj\n AddCompatibleBuildIdRedirectRule\x12\x46\n\x04rule\x18\x01 \x01(\x0b\x32\x38.temporal.api.taskqueue.v1.CompatibleBuildIdRedirectRule\x1an\n$ReplaceCompatibleBuildIdRedirectRule\x12\x46\n\x04rule\x18\x01 \x01(\x0b\x32\x38.temporal.api.taskqueue.v1.CompatibleBuildIdRedirectRule\x1a>\n#DeleteCompatibleBuildIdRedirectRule\x12\x17\n\x0fsource_build_id\x18\x01 \x01(\t\x1a\x37\n\rCommitBuildId\x12\x17\n\x0ftarget_build_id\x18\x01 \x01(\t\x12\r\n\x05\x66orce\x18\x02 \x01(\x08\x42\x0b\n\toperation"\xfc\x01\n#UpdateWorkerVersioningRulesResponse\x12U\n\x10\x61ssignment_rules\x18\x01 \x03(\x0b\x32;.temporal.api.taskqueue.v1.TimestampedBuildIdAssignmentRule\x12\x66\n\x19\x63ompatible_redirect_rules\x18\x02 \x03(\x0b\x32\x43.temporal.api.taskqueue.v1.TimestampedCompatibleBuildIdRedirectRule\x12\x16\n\x0e\x63onflict_token\x18\x03 \x01(\x0c"H\n\x1fGetWorkerVersioningRulesRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x12\n\ntask_queue\x18\x02 \x01(\t"\xf9\x01\n GetWorkerVersioningRulesResponse\x12U\n\x10\x61ssignment_rules\x18\x01 \x03(\x0b\x32;.temporal.api.taskqueue.v1.TimestampedBuildIdAssignmentRule\x12\x66\n\x19\x63ompatible_redirect_rules\x18\x02 \x03(\x0b\x32\x43.temporal.api.taskqueue.v1.TimestampedCompatibleBuildIdRedirectRule\x12\x16\n\x0e\x63onflict_token\x18\x03 \x01(\x0c"\x9c\x01\n GetWorkerTaskReachabilityRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x11\n\tbuild_ids\x18\x02 \x03(\t\x12\x13\n\x0btask_queues\x18\x03 \x03(\t\x12=\n\x0creachability\x18\x04 \x01(\x0e\x32\'.temporal.api.enums.v1.TaskReachability"r\n!GetWorkerTaskReachabilityResponse\x12M\n\x15\x62uild_id_reachability\x18\x01 \x03(\x0b\x32..temporal.api.taskqueue.v1.BuildIdReachability"\x85\x02\n\x1eUpdateWorkflowExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x45\n\x12workflow_execution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x1e\n\x16\x66irst_execution_run_id\x18\x03 \x01(\t\x12\x37\n\x0bwait_policy\x18\x04 \x01(\x0b\x32".temporal.api.update.v1.WaitPolicy\x12\x30\n\x07request\x18\x05 \x01(\x0b\x32\x1f.temporal.api.update.v1.Request"\x83\x02\n\x1fUpdateWorkflowExecutionResponse\x12\x35\n\nupdate_ref\x18\x01 \x01(\x0b\x32!.temporal.api.update.v1.UpdateRef\x12\x30\n\x07outcome\x18\x02 \x01(\x0b\x32\x1f.temporal.api.update.v1.Outcome\x12K\n\x05stage\x18\x03 \x01(\x0e\x32<.temporal.api.enums.v1.UpdateWorkflowExecutionLifecycleStage\x12*\n\x04link\x18\x04 \x01(\x0b\x32\x1c.temporal.api.common.v1.Link"\xf4\x07\n\x1aStartBatchOperationRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x18\n\x10visibility_query\x18\x02 \x01(\t\x12\x0e\n\x06job_id\x18\x03 \x01(\t\x12\x0e\n\x06reason\x18\x04 \x01(\t\x12=\n\nexecutions\x18\x05 \x03(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12!\n\x19max_operations_per_second\x18\x06 \x01(\x02\x12Q\n\x15termination_operation\x18\n \x01(\x0b\x32\x30.temporal.api.batch.v1.BatchOperationTerminationH\x00\x12G\n\x10signal_operation\x18\x0b \x01(\x0b\x32+.temporal.api.batch.v1.BatchOperationSignalH\x00\x12S\n\x16\x63\x61ncellation_operation\x18\x0c \x01(\x0b\x32\x31.temporal.api.batch.v1.BatchOperationCancellationH\x00\x12K\n\x12\x64\x65letion_operation\x18\r \x01(\x0b\x32-.temporal.api.batch.v1.BatchOperationDeletionH\x00\x12\x45\n\x0freset_operation\x18\x0e \x01(\x0b\x32*.temporal.api.batch.v1.BatchOperationResetH\x00\x12p\n!update_workflow_options_operation\x18\x0f \x01(\x0b\x32\x43.temporal.api.batch.v1.BatchOperationUpdateWorkflowExecutionOptionsH\x00\x12^\n\x1cunpause_activities_operation\x18\x10 \x01(\x0b\x32\x36.temporal.api.batch.v1.BatchOperationUnpauseActivitiesH\x00\x12Z\n\x1areset_activities_operation\x18\x11 \x01(\x0b\x32\x34.temporal.api.batch.v1.BatchOperationResetActivitiesH\x00\x12g\n!update_activity_options_operation\x18\x12 \x01(\x0b\x32:.temporal.api.batch.v1.BatchOperationUpdateActivityOptionsH\x00\x42\x0b\n\toperation"\x1d\n\x1bStartBatchOperationResponse"`\n\x19StopBatchOperationRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x0e\n\x06job_id\x18\x02 \x01(\t\x12\x0e\n\x06reason\x18\x03 \x01(\t\x12\x10\n\x08identity\x18\x04 \x01(\t"\x1c\n\x1aStopBatchOperationResponse"B\n\x1d\x44\x65scribeBatchOperationRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x0e\n\x06job_id\x18\x02 \x01(\t"\x92\x03\n\x1e\x44\x65scribeBatchOperationResponse\x12\x41\n\x0eoperation_type\x18\x01 \x01(\x0e\x32).temporal.api.enums.v1.BatchOperationType\x12\x0e\n\x06job_id\x18\x02 \x01(\t\x12\x39\n\x05state\x18\x03 \x01(\x0e\x32*.temporal.api.enums.v1.BatchOperationState\x12.\n\nstart_time\x18\x04 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12.\n\nclose_time\x18\x05 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x1d\n\x15total_operation_count\x18\x06 \x01(\x03\x12 \n\x18\x63omplete_operation_count\x18\x07 \x01(\x03\x12\x1f\n\x17\x66\x61ilure_operation_count\x18\x08 \x01(\x03\x12\x10\n\x08identity\x18\t \x01(\t\x12\x0e\n\x06reason\x18\n \x01(\t"[\n\x1aListBatchOperationsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x11\n\tpage_size\x18\x02 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c"y\n\x1bListBatchOperationsResponse\x12\x41\n\x0eoperation_info\x18\x01 \x03(\x0b\x32).temporal.api.batch.v1.BatchOperationInfo\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c"\xb9\x01\n"PollWorkflowExecutionUpdateRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x35\n\nupdate_ref\x18\x02 \x01(\x0b\x32!.temporal.api.update.v1.UpdateRef\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x37\n\x0bwait_policy\x18\x04 \x01(\x0b\x32".temporal.api.update.v1.WaitPolicy"\xdb\x01\n#PollWorkflowExecutionUpdateResponse\x12\x30\n\x07outcome\x18\x01 \x01(\x0b\x32\x1f.temporal.api.update.v1.Outcome\x12K\n\x05stage\x18\x02 \x01(\x0e\x32<.temporal.api.enums.v1.UpdateWorkflowExecutionLifecycleStage\x12\x35\n\nupdate_ref\x18\x03 \x01(\x0b\x32!.temporal.api.update.v1.UpdateRef"\xa0\x03\n\x19PollNexusTaskQueueRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x38\n\ntask_queue\x18\x03 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12\x17\n\x0fpoller_group_id\x18\t \x01(\t\x12\x10\n\x08identity\x18\x02 \x01(\t\x12\x1b\n\x13worker_instance_key\x18\x08 \x01(\t\x12Z\n\x1bworker_version_capabilities\x18\x04 \x01(\x0b\x32\x31.temporal.api.common.v1.WorkerVersionCapabilitiesB\x02\x18\x01\x12O\n\x12\x64\x65ployment_options\x18\x06 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentOptions\x12\x41\n\x10worker_heartbeat\x18\x07 \x03(\x0b\x32\'.temporal.api.worker.v1.WorkerHeartbeat"\x95\x02\n\x1aPollNexusTaskQueueResponse\x12\x12\n\ntask_token\x18\x01 \x01(\x0c\x12/\n\x07request\x18\x02 \x01(\x0b\x32\x1e.temporal.api.nexus.v1.Request\x12Q\n\x17poller_scaling_decision\x18\x03 \x01(\x0b\x32\x30.temporal.api.taskqueue.v1.PollerScalingDecision\x12\x17\n\x0fpoller_group_id\x18\x04 \x01(\t\x12\x46\n\x12poller_group_infos\x18\x05 \x03(\x0b\x32*.temporal.api.taskqueue.v1.PollerGroupInfo"\xa7\x01\n RespondNexusTaskCompletedRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x10\n\x08identity\x18\x02 \x01(\t\x12\x12\n\ntask_token\x18\x03 \x01(\x0c\x12\x31\n\x08response\x18\x04 \x01(\x0b\x32\x1f.temporal.api.nexus.v1.Response\x12\x17\n\x0fpoller_group_id\x18\x05 \x01(\t"#\n!RespondNexusTaskCompletedResponse"\xdc\x01\n\x1dRespondNexusTaskFailedRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x10\n\x08identity\x18\x02 \x01(\t\x12\x12\n\ntask_token\x18\x03 \x01(\x0c\x12\x36\n\x05\x65rror\x18\x04 \x01(\x0b\x32#.temporal.api.nexus.v1.HandlerErrorB\x02\x18\x01\x12\x31\n\x07\x66\x61ilure\x18\x05 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12\x17\n\x0fpoller_group_id\x18\x06 \x01(\t" \n\x1eRespondNexusTaskFailedResponse"\xf4\x02\n\x1c\x45xecuteMultiOperationRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12[\n\noperations\x18\x02 \x03(\x0b\x32G.temporal.api.workflowservice.v1.ExecuteMultiOperationRequest.Operation\x12\x13\n\x0bresource_id\x18\x03 \x01(\t\x1a\xce\x01\n\tOperation\x12X\n\x0estart_workflow\x18\x01 \x01(\x0b\x32>.temporal.api.workflowservice.v1.StartWorkflowExecutionRequestH\x00\x12Z\n\x0fupdate_workflow\x18\x02 \x01(\x0b\x32?.temporal.api.workflowservice.v1.UpdateWorkflowExecutionRequestH\x00\x42\x0b\n\toperation"\xcc\x02\n\x1d\x45xecuteMultiOperationResponse\x12Z\n\tresponses\x18\x01 \x03(\x0b\x32G.temporal.api.workflowservice.v1.ExecuteMultiOperationResponse.Response\x1a\xce\x01\n\x08Response\x12Y\n\x0estart_workflow\x18\x01 \x01(\x0b\x32?.temporal.api.workflowservice.v1.StartWorkflowExecutionResponseH\x00\x12[\n\x0fupdate_workflow\x18\x02 \x01(\x0b\x32@.temporal.api.workflowservice.v1.UpdateWorkflowExecutionResponseH\x00\x42\n\n\x08response"\xd0\x02\n\x1cUpdateActivityOptionsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12<\n\texecution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x43\n\x10\x61\x63tivity_options\x18\x04 \x01(\x0b\x32).temporal.api.activity.v1.ActivityOptions\x12/\n\x0bupdate_mask\x18\x05 \x01(\x0b\x32\x1a.google.protobuf.FieldMask\x12\x0c\n\x02id\x18\x06 \x01(\tH\x00\x12\x0e\n\x04type\x18\x07 \x01(\tH\x00\x12\x13\n\tmatch_all\x18\t \x01(\x08H\x00\x12\x18\n\x10restore_original\x18\x08 \x01(\x08\x42\n\n\x08\x61\x63tivity"\xab\x02\n%UpdateActivityExecutionOptionsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12\x13\n\x0b\x61\x63tivity_id\x18\x03 \x01(\t\x12\x0e\n\x06run_id\x18\x04 \x01(\t\x12\x10\n\x08identity\x18\x05 \x01(\t\x12\x43\n\x10\x61\x63tivity_options\x18\x06 \x01(\x0b\x32).temporal.api.activity.v1.ActivityOptions\x12/\n\x0bupdate_mask\x18\x07 \x01(\x0b\x32\x1a.google.protobuf.FieldMask\x12\x18\n\x10restore_original\x18\x08 \x01(\x08\x12\x13\n\x0bresource_id\x18\t \x01(\t"d\n\x1dUpdateActivityOptionsResponse\x12\x43\n\x10\x61\x63tivity_options\x18\x01 \x01(\x0b\x32).temporal.api.activity.v1.ActivityOptions"m\n&UpdateActivityExecutionOptionsResponse\x12\x43\n\x10\x61\x63tivity_options\x18\x01 \x01(\x0b\x32).temporal.api.activity.v1.ActivityOptions"\xc7\x01\n\x14PauseActivityRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12<\n\texecution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x0c\n\x02id\x18\x04 \x01(\tH\x00\x12\x0e\n\x04type\x18\x05 \x01(\tH\x00\x12\x0e\n\x06reason\x18\x06 \x01(\t\x12\x12\n\nrequest_id\x18\x07 \x01(\tB\n\n\x08\x61\x63tivity"\xb7\x01\n\x1dPauseActivityExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12\x13\n\x0b\x61\x63tivity_id\x18\x03 \x01(\t\x12\x0e\n\x06run_id\x18\x04 \x01(\t\x12\x10\n\x08identity\x18\x05 \x01(\t\x12\x0e\n\x06reason\x18\x06 \x01(\t\x12\x13\n\x0bresource_id\x18\x07 \x01(\t\x12\x12\n\nrequest_id\x18\x08 \x01(\t"\x17\n\x15PauseActivityResponse" \n\x1ePauseActivityExecutionResponse"\x98\x02\n\x16UnpauseActivityRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12<\n\texecution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x0c\n\x02id\x18\x04 \x01(\tH\x00\x12\x0e\n\x04type\x18\x05 \x01(\tH\x00\x12\x15\n\x0bunpause_all\x18\x06 \x01(\x08H\x00\x12\x16\n\x0ereset_attempts\x18\x07 \x01(\x08\x12\x17\n\x0freset_heartbeat\x18\x08 \x01(\x08\x12)\n\x06jitter\x18\t \x01(\x0b\x32\x19.google.protobuf.DurationB\n\n\x08\x61\x63tivity"\x81\x02\n\x1fUnpauseActivityExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12\x13\n\x0b\x61\x63tivity_id\x18\x03 \x01(\t\x12\x0e\n\x06run_id\x18\x04 \x01(\t\x12\x10\n\x08identity\x18\x05 \x01(\t\x12\x16\n\x0ereset_attempts\x18\x06 \x01(\x08\x12\x17\n\x0freset_heartbeat\x18\x07 \x01(\x08\x12\x0e\n\x06reason\x18\x08 \x01(\t\x12)\n\x06jitter\x18\t \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x13\n\x0bresource_id\x18\n \x01(\t"\x19\n\x17UnpauseActivityResponse""\n UnpauseActivityExecutionResponse"\xb3\x02\n\x14ResetActivityRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12<\n\texecution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x0c\n\x02id\x18\x04 \x01(\tH\x00\x12\x0e\n\x04type\x18\x05 \x01(\tH\x00\x12\x13\n\tmatch_all\x18\n \x01(\x08H\x00\x12\x17\n\x0freset_heartbeat\x18\x06 \x01(\x08\x12\x13\n\x0bkeep_paused\x18\x07 \x01(\x08\x12)\n\x06jitter\x18\x08 \x01(\x0b\x32\x19.google.protobuf.Duration\x12 \n\x18restore_original_options\x18\t \x01(\x08\x42\n\n\x08\x61\x63tivity"\x8e\x02\n\x1dResetActivityExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12\x13\n\x0b\x61\x63tivity_id\x18\x03 \x01(\t\x12\x0e\n\x06run_id\x18\x04 \x01(\t\x12\x10\n\x08identity\x18\x05 \x01(\t\x12\x17\n\x0freset_heartbeat\x18\x06 \x01(\x08\x12\x13\n\x0bkeep_paused\x18\x07 \x01(\x08\x12)\n\x06jitter\x18\x08 \x01(\x0b\x32\x19.google.protobuf.Duration\x12 \n\x18restore_original_options\x18\t \x01(\x08\x12\x13\n\x0bresource_id\x18\n \x01(\t"\x17\n\x15ResetActivityResponse" \n\x1eResetActivityExecutionResponse"\x9c\x02\n%UpdateWorkflowExecutionOptionsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x45\n\x12workflow_execution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12V\n\x1aworkflow_execution_options\x18\x03 \x01(\x0b\x32\x32.temporal.api.workflow.v1.WorkflowExecutionOptions\x12/\n\x0bupdate_mask\x18\x04 \x01(\x0b\x32\x1a.google.protobuf.FieldMask\x12\x10\n\x08identity\x18\x05 \x01(\t"\xb1\x01\n&UpdateWorkflowExecutionOptionsResponse\x12V\n\x1aworkflow_execution_options\x18\x01 \x01(\x0b\x32\x32.temporal.api.workflow.v1.WorkflowExecutionOptions\x12/\n\x0bupdate_time\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.Timestamp"j\n\x19\x44\x65scribeDeploymentRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12:\n\ndeployment\x18\x02 \x01(\x0b\x32&.temporal.api.deployment.v1.Deployment"a\n\x1a\x44\x65scribeDeploymentResponse\x12\x43\n\x0f\x64\x65ployment_info\x18\x01 \x01(\x0b\x32*.temporal.api.deployment.v1.DeploymentInfo"\xc2\x01\n&DescribeWorkerDeploymentVersionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x07version\x18\x02 \x01(\tB\x02\x18\x01\x12O\n\x12\x64\x65ployment_version\x18\x03 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersion\x12\x1f\n\x17report_task_queue_stats\x18\x04 \x01(\x08"\x8c\x05\n\'DescribeWorkerDeploymentVersionResponse\x12_\n\x1eworker_deployment_version_info\x18\x01 \x01(\x0b\x32\x37.temporal.api.deployment.v1.WorkerDeploymentVersionInfo\x12v\n\x13version_task_queues\x18\x02 \x03(\x0b\x32Y.temporal.api.workflowservice.v1.DescribeWorkerDeploymentVersionResponse.VersionTaskQueue\x1a\x87\x03\n\x10VersionTaskQueue\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x32\n\x04type\x18\x02 \x01(\x0e\x32$.temporal.api.enums.v1.TaskQueueType\x12\x38\n\x05stats\x18\x03 \x01(\x0b\x32).temporal.api.taskqueue.v1.TaskQueueStats\x12\x90\x01\n\x15stats_by_priority_key\x18\x04 \x03(\x0b\x32q.temporal.api.workflowservice.v1.DescribeWorkerDeploymentVersionResponse.VersionTaskQueue.StatsByPriorityKeyEntry\x1a\x64\n\x17StatsByPriorityKeyEntry\x12\x0b\n\x03key\x18\x01 \x01(\x05\x12\x38\n\x05value\x18\x02 \x01(\x0b\x32).temporal.api.taskqueue.v1.TaskQueueStats:\x02\x38\x01"M\n\x1f\x44\x65scribeWorkerDeploymentRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x17\n\x0f\x64\x65ployment_name\x18\x02 \x01(\t"\x8c\x01\n DescribeWorkerDeploymentResponse\x12\x16\n\x0e\x63onflict_token\x18\x01 \x01(\x0c\x12P\n\x16worker_deployment_info\x18\x02 \x01(\x0b\x32\x30.temporal.api.deployment.v1.WorkerDeploymentInfo"l\n\x16ListDeploymentsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x11\n\tpage_size\x18\x02 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c\x12\x13\n\x0bseries_name\x18\x04 \x01(\t"w\n\x17ListDeploymentsResponse\x12\x17\n\x0fnext_page_token\x18\x01 \x01(\x0c\x12\x43\n\x0b\x64\x65ployments\x18\x02 \x03(\x0b\x32..temporal.api.deployment.v1.DeploymentListInfo"\xcd\x01\n\x1bSetCurrentDeploymentRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12:\n\ndeployment\x18\x02 \x01(\x0b\x32&.temporal.api.deployment.v1.Deployment\x12\x10\n\x08identity\x18\x03 \x01(\t\x12M\n\x0fupdate_metadata\x18\x04 \x01(\x0b\x32\x34.temporal.api.deployment.v1.UpdateDeploymentMetadata"\xb9\x01\n\x1cSetCurrentDeploymentResponse\x12K\n\x17\x63urrent_deployment_info\x18\x01 \x01(\x0b\x32*.temporal.api.deployment.v1.DeploymentInfo\x12L\n\x18previous_deployment_info\x18\x02 \x01(\x0b\x32*.temporal.api.deployment.v1.DeploymentInfo"\xe5\x01\n(SetWorkerDeploymentCurrentVersionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x17\n\x0f\x64\x65ployment_name\x18\x02 \x01(\t\x12\x13\n\x07version\x18\x03 \x01(\tB\x02\x18\x01\x12\x10\n\x08\x62uild_id\x18\x07 \x01(\t\x12\x16\n\x0e\x63onflict_token\x18\x04 \x01(\x0c\x12\x10\n\x08identity\x18\x05 \x01(\t\x12"\n\x1aignore_missing_task_queues\x18\x06 \x01(\x08\x12\x18\n\x10\x61llow_no_pollers\x18\t \x01(\x08"\xbf\x01\n)SetWorkerDeploymentCurrentVersionResponse\x12\x16\n\x0e\x63onflict_token\x18\x01 \x01(\x0c\x12\x1c\n\x10previous_version\x18\x02 \x01(\tB\x02\x18\x01\x12\\\n\x1bprevious_deployment_version\x18\x03 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersionB\x02\x18\x01"\xf9\x01\n(SetWorkerDeploymentRampingVersionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x17\n\x0f\x64\x65ployment_name\x18\x02 \x01(\t\x12\x13\n\x07version\x18\x03 \x01(\tB\x02\x18\x01\x12\x10\n\x08\x62uild_id\x18\x08 \x01(\t\x12\x12\n\npercentage\x18\x04 \x01(\x02\x12\x16\n\x0e\x63onflict_token\x18\x05 \x01(\x0c\x12\x10\n\x08identity\x18\x06 \x01(\t\x12"\n\x1aignore_missing_task_queues\x18\x07 \x01(\x08\x12\x18\n\x10\x61llow_no_pollers\x18\n \x01(\x08"\xe0\x01\n)SetWorkerDeploymentRampingVersionResponse\x12\x16\n\x0e\x63onflict_token\x18\x01 \x01(\x0c\x12\x1c\n\x10previous_version\x18\x02 \x01(\tB\x02\x18\x01\x12\\\n\x1bprevious_deployment_version\x18\x04 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersionB\x02\x18\x01\x12\x1f\n\x13previous_percentage\x18\x03 \x01(\x02\x42\x02\x18\x01"q\n\x1d\x43reateWorkerDeploymentRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x17\n\x0f\x64\x65ployment_name\x18\x02 \x01(\t\x12\x10\n\x08identity\x18\x04 \x01(\t\x12\x12\n\nrequest_id\x18\x05 \x01(\t"8\n\x1e\x43reateWorkerDeploymentResponse\x12\x16\n\x0e\x63onflict_token\x18\x01 \x01(\x0c"]\n\x1cListWorkerDeploymentsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x11\n\tpage_size\x18\x02 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c"\x9f\x05\n\x1dListWorkerDeploymentsResponse\x12\x17\n\x0fnext_page_token\x18\x01 \x01(\x0c\x12r\n\x12worker_deployments\x18\x02 \x03(\x0b\x32V.temporal.api.workflowservice.v1.ListWorkerDeploymentsResponse.WorkerDeploymentSummary\x1a\xf0\x03\n\x17WorkerDeploymentSummary\x12\x0c\n\x04name\x18\x01 \x01(\t\x12/\n\x0b\x63reate_time\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x41\n\x0erouting_config\x18\x03 \x01(\x0b\x32).temporal.api.deployment.v1.RoutingConfig\x12o\n\x16latest_version_summary\x18\x04 \x01(\x0b\x32O.temporal.api.deployment.v1.WorkerDeploymentInfo.WorkerDeploymentVersionSummary\x12p\n\x17\x63urrent_version_summary\x18\x05 \x01(\x0b\x32O.temporal.api.deployment.v1.WorkerDeploymentInfo.WorkerDeploymentVersionSummary\x12p\n\x17ramping_version_summary\x18\x06 \x01(\x0b\x32O.temporal.api.deployment.v1.WorkerDeploymentInfo.WorkerDeploymentVersionSummary"\xf0\x01\n$CreateWorkerDeploymentVersionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12O\n\x12\x64\x65ployment_version\x18\x02 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersion\x12>\n\x0e\x63ompute_config\x18\x04 \x01(\x0b\x32&.temporal.api.compute.v1.ComputeConfig\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x12\n\nrequest_id\x18\x05 \x01(\t"\'\n%CreateWorkerDeploymentVersionResponse"\xc8\x01\n$DeleteWorkerDeploymentVersionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x07version\x18\x02 \x01(\tB\x02\x18\x01\x12O\n\x12\x64\x65ployment_version\x18\x05 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersion\x12\x15\n\rskip_drainage\x18\x03 \x01(\x08\x12\x10\n\x08identity\x18\x04 \x01(\t"\'\n%DeleteWorkerDeploymentVersionResponse"]\n\x1d\x44\x65leteWorkerDeploymentRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x17\n\x0f\x64\x65ployment_name\x18\x02 \x01(\t\x12\x10\n\x08identity\x18\x03 \x01(\t" \n\x1e\x44\x65leteWorkerDeploymentResponse"\x84\x04\n1UpdateWorkerDeploymentVersionComputeConfigRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12O\n\x12\x64\x65ployment_version\x18\x02 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersion\x12\x99\x01\n\x1d\x63ompute_config_scaling_groups\x18\x06 \x03(\x0b\x32r.temporal.api.workflowservice.v1.UpdateWorkerDeploymentVersionComputeConfigRequest.ComputeConfigScalingGroupsEntry\x12,\n$remove_compute_config_scaling_groups\x18\x07 \x03(\t\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x12\n\nrequest_id\x18\x04 \x01(\t\x1a{\n\x1f\x43omputeConfigScalingGroupsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12G\n\x05value\x18\x02 \x01(\x0b\x32\x38.temporal.api.compute.v1.ComputeConfigScalingGroupUpdate:\x02\x38\x01"4\n2UpdateWorkerDeploymentVersionComputeConfigResponse"\xf4\x03\n3ValidateWorkerDeploymentVersionComputeConfigRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12O\n\x12\x64\x65ployment_version\x18\x02 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersion\x12\x9b\x01\n\x1d\x63ompute_config_scaling_groups\x18\x06 \x03(\x0b\x32t.temporal.api.workflowservice.v1.ValidateWorkerDeploymentVersionComputeConfigRequest.ComputeConfigScalingGroupsEntry\x12,\n$remove_compute_config_scaling_groups\x18\x07 \x03(\t\x12\x10\n\x08identity\x18\x03 \x01(\t\x1a{\n\x1f\x43omputeConfigScalingGroupsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12G\n\x05value\x18\x02 \x01(\x0b\x32\x38.temporal.api.compute.v1.ComputeConfigScalingGroupUpdate:\x02\x38\x01"6\n4ValidateWorkerDeploymentVersionComputeConfigResponse"\xa2\x03\n,UpdateWorkerDeploymentVersionMetadataRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x07version\x18\x02 \x01(\tB\x02\x18\x01\x12O\n\x12\x64\x65ployment_version\x18\x05 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersion\x12x\n\x0eupsert_entries\x18\x03 \x03(\x0b\x32`.temporal.api.workflowservice.v1.UpdateWorkerDeploymentVersionMetadataRequest.UpsertEntriesEntry\x12\x16\n\x0eremove_entries\x18\x04 \x03(\t\x12\x10\n\x08identity\x18\x06 \x01(\t\x1aU\n\x12UpsertEntriesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12.\n\x05value\x18\x02 \x01(\x0b\x32\x1f.temporal.api.common.v1.Payload:\x02\x38\x01"n\n-UpdateWorkerDeploymentVersionMetadataResponse\x12=\n\x08metadata\x18\x01 \x01(\x0b\x32+.temporal.api.deployment.v1.VersionMetadata"\xbd\x01\n!SetWorkerDeploymentManagerRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x17\n\x0f\x64\x65ployment_name\x18\x02 \x01(\t\x12\x1a\n\x10manager_identity\x18\x03 \x01(\tH\x00\x12\x0e\n\x04self\x18\x04 \x01(\x08H\x00\x12\x16\n\x0e\x63onflict_token\x18\x05 \x01(\x0c\x12\x10\n\x08identity\x18\x06 \x01(\tB\x16\n\x14new_manager_identity"c\n"SetWorkerDeploymentManagerResponse\x12\x16\n\x0e\x63onflict_token\x18\x01 \x01(\x0c\x12%\n\x19previous_manager_identity\x18\x02 \x01(\tB\x02\x18\x01"E\n\x1bGetCurrentDeploymentRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bseries_name\x18\x02 \x01(\t"k\n\x1cGetCurrentDeploymentResponse\x12K\n\x17\x63urrent_deployment_info\x18\x01 \x01(\x0b\x32*.temporal.api.deployment.v1.DeploymentInfo"q\n GetDeploymentReachabilityRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12:\n\ndeployment\x18\x02 \x01(\x0b\x32&.temporal.api.deployment.v1.Deployment"\xe3\x01\n!GetDeploymentReachabilityResponse\x12\x43\n\x0f\x64\x65ployment_info\x18\x01 \x01(\x0b\x32*.temporal.api.deployment.v1.DeploymentInfo\x12\x43\n\x0creachability\x18\x02 \x01(\x0e\x32-.temporal.api.enums.v1.DeploymentReachability\x12\x34\n\x10last_update_time\x18\x03 \x01(\x0b\x32\x1a.google.protobuf.Timestamp"\xb4\x01\n\x19\x43reateWorkflowRuleRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x35\n\x04spec\x18\x02 \x01(\x0b\x32\'.temporal.api.rules.v1.WorkflowRuleSpec\x12\x12\n\nforce_scan\x18\x03 \x01(\x08\x12\x12\n\nrequest_id\x18\x04 \x01(\t\x12\x10\n\x08identity\x18\x05 \x01(\t\x12\x13\n\x0b\x64\x65scription\x18\x06 \x01(\t"_\n\x1a\x43reateWorkflowRuleResponse\x12\x31\n\x04rule\x18\x01 \x01(\x0b\x32#.temporal.api.rules.v1.WorkflowRule\x12\x0e\n\x06job_id\x18\x02 \x01(\t"A\n\x1b\x44\x65scribeWorkflowRuleRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x0f\n\x07rule_id\x18\x02 \x01(\t"Q\n\x1c\x44\x65scribeWorkflowRuleResponse\x12\x31\n\x04rule\x18\x01 \x01(\x0b\x32#.temporal.api.rules.v1.WorkflowRule"?\n\x19\x44\x65leteWorkflowRuleRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x0f\n\x07rule_id\x18\x02 \x01(\t"\x1c\n\x1a\x44\x65leteWorkflowRuleResponse"F\n\x18ListWorkflowRulesRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c"h\n\x19ListWorkflowRulesResponse\x12\x32\n\x05rules\x18\x01 \x03(\x0b\x32#.temporal.api.rules.v1.WorkflowRule\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c"\xce\x01\n\x1aTriggerWorkflowRuleRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12<\n\texecution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x0c\n\x02id\x18\x04 \x01(\tH\x00\x12\x37\n\x04spec\x18\x05 \x01(\x0b\x32\'.temporal.api.rules.v1.WorkflowRuleSpecH\x00\x12\x10\n\x08identity\x18\x03 \x01(\tB\x06\n\x04rule".\n\x1bTriggerWorkflowRuleResponse\x12\x0f\n\x07\x61pplied\x18\x01 \x01(\x08"\x9b\x01\n\x1cRecordWorkerHeartbeatRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x10\n\x08identity\x18\x02 \x01(\t\x12\x41\n\x10worker_heartbeat\x18\x03 \x03(\x0b\x32\'.temporal.api.worker.v1.WorkerHeartbeat\x12\x13\n\x0bresource_id\x18\x04 \x01(\t"\x1f\n\x1dRecordWorkerHeartbeatResponse"\x82\x01\n\x12ListWorkersRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x11\n\tpage_size\x18\x02 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c\x12\r\n\x05query\x18\x04 \x01(\t\x12\x1e\n\x16include_system_workers\x18\x05 \x01(\x08"\xa5\x01\n\x13ListWorkersResponse\x12<\n\x0cworkers_info\x18\x01 \x03(\x0b\x32".temporal.api.worker.v1.WorkerInfoB\x02\x18\x01\x12\x37\n\x07workers\x18\x03 \x03(\x0b\x32&.temporal.api.worker.v1.WorkerListInfo\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c"\xd5\x05\n\x1cUpdateTaskQueueConfigRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x10\n\x08identity\x18\x02 \x01(\t\x12\x12\n\ntask_queue\x18\x03 \x01(\t\x12=\n\x0ftask_queue_type\x18\x04 \x01(\x0e\x32$.temporal.api.enums.v1.TaskQueueType\x12n\n\x17update_queue_rate_limit\x18\x05 \x01(\x0b\x32M.temporal.api.workflowservice.v1.UpdateTaskQueueConfigRequest.RateLimitUpdate\x12}\n&update_fairness_key_rate_limit_default\x18\x06 \x01(\x0b\x32M.temporal.api.workflowservice.v1.UpdateTaskQueueConfigRequest.RateLimitUpdate\x12\x84\x01\n\x1dset_fairness_weight_overrides\x18\x07 \x03(\x0b\x32].temporal.api.workflowservice.v1.UpdateTaskQueueConfigRequest.SetFairnessWeightOverridesEntry\x12\'\n\x1funset_fairness_weight_overrides\x18\x08 \x03(\t\x1a[\n\x0fRateLimitUpdate\x12\x38\n\nrate_limit\x18\x01 \x01(\x0b\x32$.temporal.api.taskqueue.v1.RateLimit\x12\x0e\n\x06reason\x18\x02 \x01(\t\x1a\x41\n\x1fSetFairnessWeightOverridesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\x02:\x02\x38\x01"[\n\x1dUpdateTaskQueueConfigResponse\x12:\n\x06\x63onfig\x18\x01 \x01(\x0b\x32*.temporal.api.taskqueue.v1.TaskQueueConfig"\x9e\x01\n\x18\x46\x65tchWorkerConfigRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x10\n\x08identity\x18\x02 \x01(\t\x12\x0e\n\x06reason\x18\x03 \x01(\t\x12\x38\n\x08selector\x18\x06 \x01(\x0b\x32&.temporal.api.common.v1.WorkerSelector\x12\x13\n\x0bresource_id\x18\x07 \x01(\t"U\n\x19\x46\x65tchWorkerConfigResponse\x12\x38\n\rworker_config\x18\x01 \x01(\x0b\x32!.temporal.api.sdk.v1.WorkerConfig"\x8a\x02\n\x19UpdateWorkerConfigRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x10\n\x08identity\x18\x02 \x01(\t\x12\x0e\n\x06reason\x18\x03 \x01(\t\x12\x38\n\rworker_config\x18\x04 \x01(\x0b\x32!.temporal.api.sdk.v1.WorkerConfig\x12/\n\x0bupdate_mask\x18\x05 \x01(\x0b\x32\x1a.google.protobuf.FieldMask\x12\x38\n\x08selector\x18\x06 \x01(\x0b\x32&.temporal.api.common.v1.WorkerSelector\x12\x13\n\x0bresource_id\x18\x07 \x01(\t"d\n\x1aUpdateWorkerConfigResponse\x12:\n\rworker_config\x18\x01 \x01(\x0b\x32!.temporal.api.sdk.v1.WorkerConfigH\x00\x42\n\n\x08response"G\n\x15\x44\x65scribeWorkerRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x1b\n\x13worker_instance_key\x18\x02 \x01(\t"Q\n\x16\x44\x65scribeWorkerResponse\x12\x37\n\x0bworker_info\x18\x01 \x01(\x0b\x32".temporal.api.worker.v1.WorkerInfo"W\n\x13\x43ountWorkersRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\r\n\x05query\x18\x02 \x01(\t\x12\x1e\n\x16include_system_workers\x18\x03 \x01(\x08"%\n\x14\x43ountWorkersResponse\x12\r\n\x05\x63ount\x18\x01 \x01(\x03"\x8d\x01\n\x1dPauseWorkflowExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x12\x10\n\x08identity\x18\x04 \x01(\t\x12\x0e\n\x06reason\x18\x05 \x01(\t\x12\x12\n\nrequest_id\x18\x06 \x01(\t" \n\x1ePauseWorkflowExecutionResponse"\x8f\x01\n\x1fUnpauseWorkflowExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x12\x10\n\x08identity\x18\x04 \x01(\t\x12\x0e\n\x06reason\x18\x05 \x01(\t\x12\x12\n\nrequest_id\x18\x06 \x01(\t""\n UnpauseWorkflowExecutionResponse"\x99\t\n\x1dStartActivityExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x10\n\x08identity\x18\x02 \x01(\t\x12\x12\n\nrequest_id\x18\x03 \x01(\t\x12\x13\n\x0b\x61\x63tivity_id\x18\x04 \x01(\t\x12;\n\ractivity_type\x18\x05 \x01(\x0b\x32$.temporal.api.common.v1.ActivityType\x12\x38\n\ntask_queue\x18\x06 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12<\n\x19schedule_to_close_timeout\x18\x07 \x01(\x0b\x32\x19.google.protobuf.Duration\x12<\n\x19schedule_to_start_timeout\x18\x08 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x39\n\x16start_to_close_timeout\x18\t \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x34\n\x11heartbeat_timeout\x18\n \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x39\n\x0cretry_policy\x18\x0b \x01(\x0b\x32#.temporal.api.common.v1.RetryPolicy\x12/\n\x05input\x18\x0c \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x45\n\x0fid_reuse_policy\x18\r \x01(\x0e\x32,.temporal.api.enums.v1.ActivityIdReusePolicy\x12K\n\x12id_conflict_policy\x18\x0e \x01(\x0e\x32/.temporal.api.enums.v1.ActivityIdConflictPolicy\x12\x43\n\x11search_attributes\x18\x0f \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes\x12.\n\x06header\x18\x10 \x01(\x0b\x32\x1e.temporal.api.common.v1.Header\x12\x38\n\ruser_metadata\x18\x11 \x01(\x0b\x32!.temporal.api.sdk.v1.UserMetadata\x12\x32\n\x08priority\x18\x12 \x01(\x0b\x32 .temporal.api.common.v1.Priority\x12>\n\x14\x63ompletion_callbacks\x18\x13 \x03(\x0b\x32 .temporal.api.common.v1.Callback\x12+\n\x05links\x18\x14 \x03(\x0b\x32\x1c.temporal.api.common.v1.Link\x12\x46\n\x13on_conflict_options\x18\x15 \x01(\x0b\x32).temporal.api.common.v1.OnConflictOptions\x12.\n\x0bstart_delay\x18\x16 \x01(\x0b\x32\x19.google.protobuf.Duration"m\n\x1eStartActivityExecutionResponse\x12\x0e\n\x06run_id\x18\x01 \x01(\t\x12\x0f\n\x07started\x18\x02 \x01(\x08\x12*\n\x04link\x18\x03 \x01(\x0b\x32\x1c.temporal.api.common.v1.Link"\xe4\x01\n DescribeActivityExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0b\x61\x63tivity_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x12\x15\n\rinclude_input\x18\x04 \x01(\x08\x12\x17\n\x0finclude_outcome\x18\x05 \x01(\x08\x12\x17\n\x0flong_poll_token\x18\x06 \x01(\x0c\x12!\n\x19include_heartbeat_details\x18\x07 \x01(\x08\x12\x1c\n\x14include_last_failure\x18\x08 \x01(\x08"\xbc\x02\n!DescribeActivityExecutionResponse\x12\x0e\n\x06run_id\x18\x01 \x01(\t\x12=\n\x04info\x18\x02 \x01(\x0b\x32/.temporal.api.activity.v1.ActivityExecutionInfo\x12/\n\x05input\x18\x03 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x43\n\x07outcome\x18\x04 \x01(\x0b\x32\x32.temporal.api.activity.v1.ActivityExecutionOutcome\x12\x17\n\x0flong_poll_token\x18\x05 \x01(\x0c\x12\x39\n\tcallbacks\x18\x06 \x03(\x0b\x32&.temporal.api.activity.v1.CallbackInfo"V\n\x1cPollActivityExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0b\x61\x63tivity_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t"t\n\x1dPollActivityExecutionResponse\x12\x0e\n\x06run_id\x18\x01 \x01(\t\x12\x43\n\x07outcome\x18\x02 \x01(\x0b\x32\x32.temporal.api.activity.v1.ActivityExecutionOutcome"m\n\x1dListActivityExecutionsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x11\n\tpage_size\x18\x02 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c\x12\r\n\x05query\x18\x04 \x01(\t"\x82\x01\n\x1eListActivityExecutionsResponse\x12G\n\nexecutions\x18\x01 \x03(\x0b\x32\x33.temporal.api.activity.v1.ActivityExecutionListInfo\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c"\xd1\x06\n#StartNexusOperationExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x10\n\x08identity\x18\x02 \x01(\t\x12\x12\n\nrequest_id\x18\x03 \x01(\t\x12\x14\n\x0coperation_id\x18\x04 \x01(\t\x12\x10\n\x08\x65ndpoint\x18\x05 \x01(\t\x12\x0f\n\x07service\x18\x06 \x01(\t\x12\x11\n\toperation\x18\x07 \x01(\t\x12<\n\x19schedule_to_close_timeout\x18\x08 \x01(\x0b\x32\x19.google.protobuf.Duration\x12<\n\x19schedule_to_start_timeout\x18\t \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x39\n\x16start_to_close_timeout\x18\n \x01(\x0b\x32\x19.google.protobuf.Duration\x12.\n\x05input\x18\x0b \x01(\x0b\x32\x1f.temporal.api.common.v1.Payload\x12K\n\x0fid_reuse_policy\x18\x0c \x01(\x0e\x32\x32.temporal.api.enums.v1.NexusOperationIdReusePolicy\x12Q\n\x12id_conflict_policy\x18\r \x01(\x0e\x32\x35.temporal.api.enums.v1.NexusOperationIdConflictPolicy\x12\x43\n\x11search_attributes\x18\x0e \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes\x12k\n\x0cnexus_header\x18\x0f \x03(\x0b\x32U.temporal.api.workflowservice.v1.StartNexusOperationExecutionRequest.NexusHeaderEntry\x12\x38\n\ruser_metadata\x18\x10 \x01(\x0b\x32!.temporal.api.sdk.v1.UserMetadata\x1a\x32\n\x10NexusHeaderEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01"G\n$StartNexusOperationExecutionResponse\x12\x0e\n\x06run_id\x18\x01 \x01(\t\x12\x0f\n\x07started\x18\x02 \x01(\x08"\xaa\x01\n&DescribeNexusOperationExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x14\n\x0coperation_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x12\x15\n\rinclude_input\x18\x04 \x01(\x08\x12\x17\n\x0finclude_outcome\x18\x05 \x01(\x08\x12\x17\n\x0flong_poll_token\x18\x06 \x01(\x0c"\xb7\x02\n\'DescribeNexusOperationExecutionResponse\x12\x0e\n\x06run_id\x18\x01 \x01(\t\x12@\n\x04info\x18\x02 \x01(\x0b\x32\x32.temporal.api.nexus.v1.NexusOperationExecutionInfo\x12.\n\x05input\x18\x03 \x01(\x0b\x32\x1f.temporal.api.common.v1.Payload\x12\x31\n\x06result\x18\x04 \x01(\x0b\x32\x1f.temporal.api.common.v1.PayloadH\x00\x12\x33\n\x07\x66\x61ilure\x18\x05 \x01(\x0b\x32 .temporal.api.failure.v1.FailureH\x00\x12\x17\n\x0flong_poll_token\x18\x06 \x01(\x0c\x42\t\n\x07outcome"\xa1\x01\n"PollNexusOperationExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x14\n\x0coperation_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x12\x42\n\nwait_stage\x18\x04 \x01(\x0e\x32..temporal.api.enums.v1.NexusOperationWaitStage"\x85\x02\n#PollNexusOperationExecutionResponse\x12\x0e\n\x06run_id\x18\x01 \x01(\t\x12\x42\n\nwait_stage\x18\x02 \x01(\x0e\x32..temporal.api.enums.v1.NexusOperationWaitStage\x12\x17\n\x0foperation_token\x18\x03 \x01(\t\x12\x31\n\x06result\x18\x04 \x01(\x0b\x32\x1f.temporal.api.common.v1.PayloadH\x00\x12\x33\n\x07\x66\x61ilure\x18\x05 \x01(\x0b\x32 .temporal.api.failure.v1.FailureH\x00\x42\t\n\x07outcome"s\n#ListNexusOperationExecutionsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x11\n\tpage_size\x18\x02 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c\x12\r\n\x05query\x18\x04 \x01(\t"\x8b\x01\n$ListNexusOperationExecutionsResponse\x12J\n\noperations\x18\x01 \x03(\x0b\x32\x36.temporal.api.nexus.v1.NexusOperationExecutionListInfo\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c"B\n\x1e\x43ountActivityExecutionsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\r\n\x05query\x18\x02 \x01(\t"\xed\x01\n\x1f\x43ountActivityExecutionsResponse\x12\r\n\x05\x63ount\x18\x01 \x01(\x03\x12\x61\n\x06groups\x18\x02 \x03(\x0b\x32Q.temporal.api.workflowservice.v1.CountActivityExecutionsResponse.AggregationGroup\x1aX\n\x10\x41ggregationGroup\x12\x35\n\x0cgroup_values\x18\x01 \x03(\x0b\x32\x1f.temporal.api.common.v1.Payload\x12\r\n\x05\x63ount\x18\x02 \x01(\x03"H\n$CountNexusOperationExecutionsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\r\n\x05query\x18\x02 \x01(\t"\xf9\x01\n%CountNexusOperationExecutionsResponse\x12\r\n\x05\x63ount\x18\x01 \x01(\x03\x12g\n\x06groups\x18\x02 \x03(\x0b\x32W.temporal.api.workflowservice.v1.CountNexusOperationExecutionsResponse.AggregationGroup\x1aX\n\x10\x41ggregationGroup\x12\x35\n\x0cgroup_values\x18\x01 \x03(\x0b\x32\x1f.temporal.api.common.v1.Payload\x12\r\n\x05\x63ount\x18\x02 \x01(\x03"\x95\x01\n%RequestCancelActivityExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0b\x61\x63tivity_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x12\x10\n\x08identity\x18\x04 \x01(\t\x12\x12\n\nrequest_id\x18\x05 \x01(\t\x12\x0e\n\x06reason\x18\x06 \x01(\t"(\n&RequestCancelActivityExecutionResponse"\x91\x01\n!TerminateActivityExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0b\x61\x63tivity_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x12\x10\n\x08identity\x18\x04 \x01(\t\x12\x12\n\nrequest_id\x18\x05 \x01(\t\x12\x0e\n\x06reason\x18\x06 \x01(\t"$\n"TerminateActivityExecutionResponse"X\n\x1e\x44\x65leteActivityExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0b\x61\x63tivity_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t"!\n\x1f\x44\x65leteActivityExecutionResponse"\x9c\x01\n+RequestCancelNexusOperationExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x14\n\x0coperation_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x12\x10\n\x08identity\x18\x04 \x01(\t\x12\x12\n\nrequest_id\x18\x05 \x01(\t\x12\x0e\n\x06reason\x18\x06 \x01(\t".\n,RequestCancelNexusOperationExecutionResponse"\x98\x01\n\'TerminateNexusOperationExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x14\n\x0coperation_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x12\x10\n\x08identity\x18\x04 \x01(\t\x12\x12\n\nrequest_id\x18\x05 \x01(\t\x12\x0e\n\x06reason\x18\x06 \x01(\t"*\n(TerminateNexusOperationExecutionResponse"_\n$DeleteNexusOperationExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x14\n\x0coperation_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t"\'\n%DeleteNexusOperationExecutionResponseB\xbe\x01\n"io.temporal.api.workflowservice.v1B\x14RequestResponseProtoP\x01Z5go.temporal.io/api/workflowservice/v1;workflowservice\xaa\x02!Temporalio.Api.WorkflowService.V1\xea\x02$Temporalio::Api::WorkflowService::V1b\x06proto3' + b'\n6temporal/api/workflowservice/v1/request_response.proto\x12\x1ftemporal.api.workflowservice.v1\x1a+temporal/api/enums/v1/batch_operation.proto\x1a"temporal/api/enums/v1/common.proto\x1a$temporal/api/enums/v1/workflow.proto\x1a%temporal/api/enums/v1/namespace.proto\x1a(temporal/api/enums/v1/failed_cause.proto\x1a!temporal/api/enums/v1/query.proto\x1a!temporal/api/enums/v1/reset.proto\x1a&temporal/api/enums/v1/task_queue.proto\x1a&temporal/api/enums/v1/deployment.proto\x1a"temporal/api/enums/v1/update.proto\x1a$temporal/api/enums/v1/activity.proto\x1a!temporal/api/enums/v1/nexus.proto\x1a&temporal/api/activity/v1/message.proto\x1a$temporal/api/common/v1/message.proto\x1a%temporal/api/history/v1/message.proto\x1a&temporal/api/workflow/v1/message.proto\x1a%temporal/api/command/v1/message.proto\x1a$temporal/api/compute/v1/config.proto\x1a(temporal/api/deployment/v1/message.proto\x1a%temporal/api/failure/v1/message.proto\x1a$temporal/api/filter/v1/message.proto\x1a&temporal/api/protocol/v1/message.proto\x1a\'temporal/api/namespace/v1/message.proto\x1a#temporal/api/query/v1/message.proto\x1a)temporal/api/replication/v1/message.proto\x1a#temporal/api/rules/v1/message.proto\x1a\'temporal/api/sdk/v1/worker_config.proto\x1a&temporal/api/schedule/v1/message.proto\x1a\'temporal/api/taskqueue/v1/message.proto\x1a$temporal/api/update/v1/message.proto\x1a%temporal/api/version/v1/message.proto\x1a#temporal/api/batch/v1/message.proto\x1a\x30temporal/api/sdk/v1/task_complete_metadata.proto\x1a\'temporal/api/sdk/v1/user_metadata.proto\x1a#temporal/api/nexus/v1/message.proto\x1a$temporal/api/worker/v1/message.proto\x1a\x1egoogle/protobuf/duration.proto\x1a google/protobuf/field_mask.proto\x1a\x1fgoogle/protobuf/timestamp.proto"\x88\x05\n\x18RegisterNamespaceRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0b\x64\x65scription\x18\x02 \x01(\t\x12\x13\n\x0bowner_email\x18\x03 \x01(\t\x12\x46\n#workflow_execution_retention_period\x18\x04 \x01(\x0b\x32\x19.google.protobuf.Duration\x12G\n\x08\x63lusters\x18\x05 \x03(\x0b\x32\x35.temporal.api.replication.v1.ClusterReplicationConfig\x12\x1b\n\x13\x61\x63tive_cluster_name\x18\x06 \x01(\t\x12Q\n\x04\x64\x61ta\x18\x07 \x03(\x0b\x32\x43.temporal.api.workflowservice.v1.RegisterNamespaceRequest.DataEntry\x12\x16\n\x0esecurity_token\x18\x08 \x01(\t\x12\x1b\n\x13is_global_namespace\x18\t \x01(\x08\x12\x44\n\x16history_archival_state\x18\n \x01(\x0e\x32$.temporal.api.enums.v1.ArchivalState\x12\x1c\n\x14history_archival_uri\x18\x0b \x01(\t\x12G\n\x19visibility_archival_state\x18\x0c \x01(\x0e\x32$.temporal.api.enums.v1.ArchivalState\x12\x1f\n\x17visibility_archival_uri\x18\r \x01(\t\x1a+\n\tDataEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01"\x1b\n\x19RegisterNamespaceResponse"\x89\x01\n\x15ListNamespacesRequest\x12\x11\n\tpage_size\x18\x01 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c\x12\x44\n\x10namespace_filter\x18\x03 \x01(\x0b\x32*.temporal.api.namespace.v1.NamespaceFilter"\x81\x01\n\x16ListNamespacesResponse\x12N\n\nnamespaces\x18\x01 \x03(\x0b\x32:.temporal.api.workflowservice.v1.DescribeNamespaceResponse\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c"S\n\x18\x44\x65scribeNamespaceRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\n\n\x02id\x18\x02 \x01(\t\x12\x18\n\x10weak_consistency\x18\x03 \x01(\x08"\x81\x04\n\x19\x44\x65scribeNamespaceResponse\x12@\n\x0enamespace_info\x18\x01 \x01(\x0b\x32(.temporal.api.namespace.v1.NamespaceInfo\x12:\n\x06\x63onfig\x18\x02 \x01(\x0b\x32*.temporal.api.namespace.v1.NamespaceConfig\x12S\n\x12replication_config\x18\x03 \x01(\x0b\x32\x37.temporal.api.replication.v1.NamespaceReplicationConfig\x12\x18\n\x10\x66\x61ilover_version\x18\x04 \x01(\x03\x12\x1b\n\x13is_global_namespace\x18\x05 \x01(\x08\x12\x45\n\x10\x66\x61ilover_history\x18\x06 \x03(\x0b\x32+.temporal.api.replication.v1.FailoverStatus\x12J\n\x12poller_group_infos\x18\x07 \x03(\x0b\x32*.temporal.api.taskqueue.v1.PollerGroupInfoB\x02\x18\x01\x12G\n\x12poller_groups_info\x18\x08 \x01(\x0b\x32+.temporal.api.taskqueue.v1.PollerGroupsInfo"\xcf\x02\n\x16UpdateNamespaceRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x43\n\x0bupdate_info\x18\x02 \x01(\x0b\x32..temporal.api.namespace.v1.UpdateNamespaceInfo\x12:\n\x06\x63onfig\x18\x03 \x01(\x0b\x32*.temporal.api.namespace.v1.NamespaceConfig\x12S\n\x12replication_config\x18\x04 \x01(\x0b\x32\x37.temporal.api.replication.v1.NamespaceReplicationConfig\x12\x16\n\x0esecurity_token\x18\x05 \x01(\t\x12\x19\n\x11\x64\x65lete_bad_binary\x18\x06 \x01(\t\x12\x19\n\x11promote_namespace\x18\x07 \x01(\x08"\xa3\x02\n\x17UpdateNamespaceResponse\x12@\n\x0enamespace_info\x18\x01 \x01(\x0b\x32(.temporal.api.namespace.v1.NamespaceInfo\x12:\n\x06\x63onfig\x18\x02 \x01(\x0b\x32*.temporal.api.namespace.v1.NamespaceConfig\x12S\n\x12replication_config\x18\x03 \x01(\x0b\x32\x37.temporal.api.replication.v1.NamespaceReplicationConfig\x12\x18\n\x10\x66\x61ilover_version\x18\x04 \x01(\x03\x12\x1b\n\x13is_global_namespace\x18\x05 \x01(\x08"F\n\x19\x44\x65precateNamespaceRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x16\n\x0esecurity_token\x18\x02 \x01(\t"\x1c\n\x1a\x44\x65precateNamespaceResponse"\xd1\x0c\n\x1dStartWorkflowExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12;\n\rworkflow_type\x18\x03 \x01(\x0b\x32$.temporal.api.common.v1.WorkflowType\x12\x38\n\ntask_queue\x18\x04 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12/\n\x05input\x18\x05 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12=\n\x1aworkflow_execution_timeout\x18\x06 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x37\n\x14workflow_run_timeout\x18\x07 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x38\n\x15workflow_task_timeout\x18\x08 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x10\n\x08identity\x18\t \x01(\t\x12\x12\n\nrequest_id\x18\n \x01(\t\x12N\n\x18workflow_id_reuse_policy\x18\x0b \x01(\x0e\x32,.temporal.api.enums.v1.WorkflowIdReusePolicy\x12T\n\x1bworkflow_id_conflict_policy\x18\x16 \x01(\x0e\x32/.temporal.api.enums.v1.WorkflowIdConflictPolicy\x12\x39\n\x0cretry_policy\x18\x0c \x01(\x0b\x32#.temporal.api.common.v1.RetryPolicy\x12\x15\n\rcron_schedule\x18\r \x01(\t\x12*\n\x04memo\x18\x0e \x01(\x0b\x32\x1c.temporal.api.common.v1.Memo\x12\x43\n\x11search_attributes\x18\x0f \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes\x12.\n\x06header\x18\x10 \x01(\x0b\x32\x1e.temporal.api.common.v1.Header\x12\x1f\n\x17request_eager_execution\x18\x11 \x01(\x08\x12;\n\x11\x63ontinued_failure\x18\x12 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12@\n\x16last_completion_result\x18\x13 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x37\n\x14workflow_start_delay\x18\x14 \x01(\x0b\x32\x19.google.protobuf.Duration\x12>\n\x14\x63ompletion_callbacks\x18\x15 \x03(\x0b\x32 .temporal.api.common.v1.Callback\x12\x38\n\ruser_metadata\x18\x17 \x01(\x0b\x32!.temporal.api.sdk.v1.UserMetadata\x12+\n\x05links\x18\x18 \x03(\x0b\x32\x1c.temporal.api.common.v1.Link\x12I\n\x13versioning_override\x18\x19 \x01(\x0b\x32,.temporal.api.workflow.v1.VersioningOverride\x12H\n\x13on_conflict_options\x18\x1a \x01(\x0b\x32+.temporal.api.workflow.v1.OnConflictOptions\x12\x32\n\x08priority\x18\x1b \x01(\x0b\x32 .temporal.api.common.v1.Priority\x12\\\n\x1f\x65\x61ger_worker_deployment_options\x18\x1c \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentOptions\x12H\n\x14time_skipping_config\x18\x1d \x01(\x0b\x32*.temporal.api.common.v1.TimeSkippingConfig"\xaa\x02\n\x1eStartWorkflowExecutionResponse\x12\x0e\n\x06run_id\x18\x01 \x01(\t\x12\x1e\n\x16\x66irst_execution_run_id\x18\x06 \x01(\t\x12\x0f\n\x07started\x18\x03 \x01(\x08\x12>\n\x06status\x18\x05 \x01(\x0e\x32..temporal.api.enums.v1.WorkflowExecutionStatus\x12[\n\x13\x65\x61ger_workflow_task\x18\x02 \x01(\x0b\x32>.temporal.api.workflowservice.v1.PollWorkflowTaskQueueResponse\x12*\n\x04link\x18\x04 \x01(\x0b\x32\x1c.temporal.api.common.v1.Link"\xaa\x02\n"GetWorkflowExecutionHistoryRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12<\n\texecution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x19\n\x11maximum_page_size\x18\x03 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x04 \x01(\x0c\x12\x16\n\x0ewait_new_event\x18\x05 \x01(\x08\x12P\n\x19history_event_filter_type\x18\x06 \x01(\x0e\x32-.temporal.api.enums.v1.HistoryEventFilterType\x12\x15\n\rskip_archival\x18\x07 \x01(\x08"\xba\x01\n#GetWorkflowExecutionHistoryResponse\x12\x31\n\x07history\x18\x01 \x01(\x0b\x32 .temporal.api.history.v1.History\x12\x35\n\x0braw_history\x18\x02 \x03(\x0b\x32 .temporal.api.common.v1.DataBlob\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c\x12\x10\n\x08\x61rchived\x18\x04 \x01(\x08"\xb0\x01\n)GetWorkflowExecutionHistoryReverseRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12<\n\texecution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x19\n\x11maximum_page_size\x18\x03 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x04 \x01(\x0c"x\n*GetWorkflowExecutionHistoryReverseResponse\x12\x31\n\x07history\x18\x01 \x01(\x0b\x32 .temporal.api.history.v1.History\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c"\xb8\x03\n\x1cPollWorkflowTaskQueueRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x38\n\ntask_queue\x18\x02 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12\x17\n\x0fpoller_group_id\x18\n \x01(\t\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x1b\n\x13worker_instance_key\x18\x08 \x01(\t\x12!\n\x19worker_control_task_queue\x18\t \x01(\t\x12\x1b\n\x0f\x62inary_checksum\x18\x04 \x01(\tB\x02\x18\x01\x12Z\n\x1bworker_version_capabilities\x18\x05 \x01(\x0b\x32\x31.temporal.api.common.v1.WorkerVersionCapabilitiesB\x02\x18\x01\x12O\n\x12\x64\x65ployment_options\x18\x06 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentOptionsJ\x04\x08\x07\x10\x08R\x10worker_heartbeat"\xbf\x08\n\x1dPollWorkflowTaskQueueResponse\x12\x12\n\ntask_token\x18\x01 \x01(\x0c\x12\x45\n\x12workflow_execution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12;\n\rworkflow_type\x18\x03 \x01(\x0b\x32$.temporal.api.common.v1.WorkflowType\x12!\n\x19previous_started_event_id\x18\x04 \x01(\x03\x12\x18\n\x10started_event_id\x18\x05 \x01(\x03\x12\x0f\n\x07\x61ttempt\x18\x06 \x01(\x05\x12\x1a\n\x12\x62\x61\x63klog_count_hint\x18\x07 \x01(\x03\x12\x31\n\x07history\x18\x08 \x01(\x0b\x32 .temporal.api.history.v1.History\x12\x17\n\x0fnext_page_token\x18\t \x01(\x0c\x12\x33\n\x05query\x18\n \x01(\x0b\x32$.temporal.api.query.v1.WorkflowQuery\x12K\n\x1dworkflow_execution_task_queue\x18\x0b \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12\x32\n\x0escheduled_time\x18\x0c \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x30\n\x0cstarted_time\x18\r \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\\\n\x07queries\x18\x0e \x03(\x0b\x32K.temporal.api.workflowservice.v1.PollWorkflowTaskQueueResponse.QueriesEntry\x12\x33\n\x08messages\x18\x0f \x03(\x0b\x32!.temporal.api.protocol.v1.Message\x12Q\n\x17poller_scaling_decision\x18\x10 \x01(\x0b\x32\x30.temporal.api.taskqueue.v1.PollerScalingDecision\x12\x17\n\x0fpoller_group_id\x18\x11 \x01(\t\x12J\n\x12poller_group_infos\x18\x12 \x03(\x0b\x32*.temporal.api.taskqueue.v1.PollerGroupInfoB\x02\x18\x01\x12G\n\x12poller_groups_info\x18\x13 \x01(\x0b\x32+.temporal.api.taskqueue.v1.PollerGroupsInfo\x1aT\n\x0cQueriesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x33\n\x05value\x18\x02 \x01(\x0b\x32$.temporal.api.query.v1.WorkflowQuery:\x02\x38\x01"\xba\n\n#RespondWorkflowTaskCompletedRequest\x12\x12\n\ntask_token\x18\x01 \x01(\x0c\x12\x32\n\x08\x63ommands\x18\x02 \x03(\x0b\x32 .temporal.api.command.v1.Command\x12\x10\n\x08identity\x18\x03 \x01(\t\x12O\n\x11sticky_attributes\x18\x04 \x01(\x0b\x32\x34.temporal.api.taskqueue.v1.StickyExecutionAttributes\x12 \n\x18return_new_workflow_task\x18\x05 \x01(\x08\x12&\n\x1e\x66orce_create_new_workflow_task\x18\x06 \x01(\x08\x12\x1b\n\x0f\x62inary_checksum\x18\x07 \x01(\tB\x02\x18\x01\x12m\n\rquery_results\x18\x08 \x03(\x0b\x32V.temporal.api.workflowservice.v1.RespondWorkflowTaskCompletedRequest.QueryResultsEntry\x12\x11\n\tnamespace\x18\t \x01(\t\x12\x13\n\x0bresource_id\x18\x12 \x01(\t\x12L\n\x14worker_version_stamp\x18\n \x01(\x0b\x32*.temporal.api.common.v1.WorkerVersionStampB\x02\x18\x01\x12\x33\n\x08messages\x18\x0b \x03(\x0b\x32!.temporal.api.protocol.v1.Message\x12H\n\x0csdk_metadata\x18\x0c \x01(\x0b\x32\x32.temporal.api.sdk.v1.WorkflowTaskCompletedMetadata\x12\x43\n\x11metering_metadata\x18\r \x01(\x0b\x32(.temporal.api.common.v1.MeteringMetadata\x12g\n\x0c\x63\x61pabilities\x18\x0e \x01(\x0b\x32Q.temporal.api.workflowservice.v1.RespondWorkflowTaskCompletedRequest.Capabilities\x12>\n\ndeployment\x18\x0f \x01(\x0b\x32&.temporal.api.deployment.v1.DeploymentB\x02\x18\x01\x12\x46\n\x13versioning_behavior\x18\x10 \x01(\x0e\x32).temporal.api.enums.v1.VersioningBehavior\x12O\n\x12\x64\x65ployment_options\x18\x11 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentOptions\x12\x1b\n\x13worker_instance_key\x18\x13 \x01(\t\x12!\n\x19worker_control_task_queue\x18\x14 \x01(\t\x12\x13\n\x0bpage_number\x18\x15 \x01(\x05\x12\x19\n\x11intermediate_page\x18\x16 \x01(\x08\x1a_\n\x11QueryResultsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x39\n\x05value\x18\x02 \x01(\x0b\x32*.temporal.api.query.v1.WorkflowQueryResult:\x02\x38\x01\x1a\x45\n\x0c\x43\x61pabilities\x12\x35\n-discard_speculative_workflow_task_with_events\x18\x01 \x01(\x08"\xf5\x01\n$RespondWorkflowTaskCompletedResponse\x12U\n\rworkflow_task\x18\x01 \x01(\x0b\x32>.temporal.api.workflowservice.v1.PollWorkflowTaskQueueResponse\x12V\n\x0e\x61\x63tivity_tasks\x18\x02 \x03(\x0b\x32>.temporal.api.workflowservice.v1.PollActivityTaskQueueResponse\x12\x1e\n\x16reset_history_event_id\x18\x03 \x01(\x03"\x8d\x04\n RespondWorkflowTaskFailedRequest\x12\x12\n\ntask_token\x18\x01 \x01(\x0c\x12=\n\x05\x63\x61use\x18\x02 \x01(\x0e\x32..temporal.api.enums.v1.WorkflowTaskFailedCause\x12\x31\n\x07\x66\x61ilure\x18\x03 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12\x10\n\x08identity\x18\x04 \x01(\t\x12\x1b\n\x0f\x62inary_checksum\x18\x05 \x01(\tB\x02\x18\x01\x12\x11\n\tnamespace\x18\x06 \x01(\t\x12\x13\n\x0bresource_id\x18\x0b \x01(\t\x12\x33\n\x08messages\x18\x07 \x03(\x0b\x32!.temporal.api.protocol.v1.Message\x12\x46\n\x0eworker_version\x18\x08 \x01(\x0b\x32*.temporal.api.common.v1.WorkerVersionStampB\x02\x18\x01\x12>\n\ndeployment\x18\t \x01(\x0b\x32&.temporal.api.deployment.v1.DeploymentB\x02\x18\x01\x12O\n\x12\x64\x65ployment_options\x18\n \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentOptions"#\n!RespondWorkflowTaskFailedResponse"\xe6\x03\n\x1cPollActivityTaskQueueRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x38\n\ntask_queue\x18\x02 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12\x17\n\x0fpoller_group_id\x18\n \x01(\t\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x1b\n\x13worker_instance_key\x18\x08 \x01(\t\x12!\n\x19worker_control_task_queue\x18\t \x01(\t\x12I\n\x13task_queue_metadata\x18\x04 \x01(\x0b\x32,.temporal.api.taskqueue.v1.TaskQueueMetadata\x12Z\n\x1bworker_version_capabilities\x18\x05 \x01(\x0b\x32\x31.temporal.api.common.v1.WorkerVersionCapabilitiesB\x02\x18\x01\x12O\n\x12\x64\x65ployment_options\x18\x06 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentOptionsJ\x04\x08\x07\x10\x08R\x10worker_heartbeat"\x9d\t\n\x1dPollActivityTaskQueueResponse\x12\x12\n\ntask_token\x18\x01 \x01(\x0c\x12\x1a\n\x12workflow_namespace\x18\x02 \x01(\t\x12;\n\rworkflow_type\x18\x03 \x01(\x0b\x32$.temporal.api.common.v1.WorkflowType\x12\x45\n\x12workflow_execution\x18\x04 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12;\n\ractivity_type\x18\x05 \x01(\x0b\x32$.temporal.api.common.v1.ActivityType\x12\x13\n\x0b\x61\x63tivity_id\x18\x06 \x01(\t\x12.\n\x06header\x18\x07 \x01(\x0b\x32\x1e.temporal.api.common.v1.Header\x12/\n\x05input\x18\x08 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12;\n\x11heartbeat_details\x18\t \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x32\n\x0escheduled_time\x18\n \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x42\n\x1e\x63urrent_attempt_scheduled_time\x18\x0b \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x30\n\x0cstarted_time\x18\x0c \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x0f\n\x07\x61ttempt\x18\r \x01(\x05\x12<\n\x19schedule_to_close_timeout\x18\x0e \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x39\n\x16start_to_close_timeout\x18\x0f \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x34\n\x11heartbeat_timeout\x18\x10 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x39\n\x0cretry_policy\x18\x11 \x01(\x0b\x32#.temporal.api.common.v1.RetryPolicy\x12Q\n\x17poller_scaling_decision\x18\x12 \x01(\x0b\x32\x30.temporal.api.taskqueue.v1.PollerScalingDecision\x12\x32\n\x08priority\x18\x13 \x01(\x0b\x32 .temporal.api.common.v1.Priority\x12\x17\n\x0f\x61\x63tivity_run_id\x18\x14 \x01(\t\x12J\n\x12poller_group_infos\x18\x15 \x03(\x0b\x32*.temporal.api.taskqueue.v1.PollerGroupInfoB\x02\x18\x01\x12G\n\x12poller_groups_info\x18\x16 \x01(\x0b\x32+.temporal.api.taskqueue.v1.PollerGroupsInfo"\xa5\x01\n"RecordActivityTaskHeartbeatRequest\x12\x12\n\ntask_token\x18\x01 \x01(\x0c\x12\x31\n\x07\x64\x65tails\x18\x02 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x11\n\tnamespace\x18\x04 \x01(\t\x12\x13\n\x0bresource_id\x18\x05 \x01(\t"p\n#RecordActivityTaskHeartbeatResponse\x12\x18\n\x10\x63\x61ncel_requested\x18\x01 \x01(\x08\x12\x17\n\x0f\x61\x63tivity_paused\x18\x02 \x01(\x08\x12\x16\n\x0e\x61\x63tivity_reset\x18\x03 \x01(\x08"\xcf\x01\n&RecordActivityTaskHeartbeatByIdRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x12\x13\n\x0b\x61\x63tivity_id\x18\x04 \x01(\t\x12\x31\n\x07\x64\x65tails\x18\x05 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x10\n\x08identity\x18\x06 \x01(\t\x12\x13\n\x0bresource_id\x18\x07 \x01(\t"t\n\'RecordActivityTaskHeartbeatByIdResponse\x12\x18\n\x10\x63\x61ncel_requested\x18\x01 \x01(\x08\x12\x17\n\x0f\x61\x63tivity_paused\x18\x02 \x01(\x08\x12\x16\n\x0e\x61\x63tivity_reset\x18\x03 \x01(\x08"\xfe\x02\n#RespondActivityTaskCompletedRequest\x12\x12\n\ntask_token\x18\x01 \x01(\x0c\x12\x30\n\x06result\x18\x02 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x11\n\tnamespace\x18\x04 \x01(\t\x12\x13\n\x0bresource_id\x18\x08 \x01(\t\x12\x46\n\x0eworker_version\x18\x05 \x01(\x0b\x32*.temporal.api.common.v1.WorkerVersionStampB\x02\x18\x01\x12>\n\ndeployment\x18\x06 \x01(\x0b\x32&.temporal.api.deployment.v1.DeploymentB\x02\x18\x01\x12O\n\x12\x64\x65ployment_options\x18\x07 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentOptions"&\n$RespondActivityTaskCompletedResponse"\xcf\x01\n\'RespondActivityTaskCompletedByIdRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x12\x13\n\x0b\x61\x63tivity_id\x18\x04 \x01(\t\x12\x30\n\x06result\x18\x05 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x10\n\x08identity\x18\x06 \x01(\t\x12\x13\n\x0bresource_id\x18\x07 \x01(\t"*\n(RespondActivityTaskCompletedByIdResponse"\xbe\x03\n RespondActivityTaskFailedRequest\x12\x12\n\ntask_token\x18\x01 \x01(\x0c\x12\x31\n\x07\x66\x61ilure\x18\x02 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x11\n\tnamespace\x18\x04 \x01(\t\x12\x13\n\x0bresource_id\x18\t \x01(\t\x12@\n\x16last_heartbeat_details\x18\x05 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x46\n\x0eworker_version\x18\x06 \x01(\x0b\x32*.temporal.api.common.v1.WorkerVersionStampB\x02\x18\x01\x12>\n\ndeployment\x18\x07 \x01(\x0b\x32&.temporal.api.deployment.v1.DeploymentB\x02\x18\x01\x12O\n\x12\x64\x65ployment_options\x18\x08 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentOptions"W\n!RespondActivityTaskFailedResponse\x12\x32\n\x08\x66\x61ilures\x18\x01 \x03(\x0b\x32 .temporal.api.failure.v1.Failure"\x8f\x02\n$RespondActivityTaskFailedByIdRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x12\x13\n\x0b\x61\x63tivity_id\x18\x04 \x01(\t\x12\x31\n\x07\x66\x61ilure\x18\x05 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12\x10\n\x08identity\x18\x06 \x01(\t\x12@\n\x16last_heartbeat_details\x18\x07 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x13\n\x0bresource_id\x18\x08 \x01(\t"[\n%RespondActivityTaskFailedByIdResponse\x12\x32\n\x08\x66\x61ilures\x18\x01 \x03(\x0b\x32 .temporal.api.failure.v1.Failure"\xfe\x02\n"RespondActivityTaskCanceledRequest\x12\x12\n\ntask_token\x18\x01 \x01(\x0c\x12\x31\n\x07\x64\x65tails\x18\x02 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x11\n\tnamespace\x18\x04 \x01(\t\x12\x13\n\x0bresource_id\x18\x08 \x01(\t\x12\x46\n\x0eworker_version\x18\x05 \x01(\x0b\x32*.temporal.api.common.v1.WorkerVersionStampB\x02\x18\x01\x12>\n\ndeployment\x18\x06 \x01(\x0b\x32&.temporal.api.deployment.v1.DeploymentB\x02\x18\x01\x12O\n\x12\x64\x65ployment_options\x18\x07 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentOptions"%\n#RespondActivityTaskCanceledResponse"\xa0\x02\n&RespondActivityTaskCanceledByIdRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x12\x13\n\x0b\x61\x63tivity_id\x18\x04 \x01(\t\x12\x31\n\x07\x64\x65tails\x18\x05 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x10\n\x08identity\x18\x06 \x01(\t\x12O\n\x12\x64\x65ployment_options\x18\x07 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentOptions\x12\x13\n\x0bresource_id\x18\x08 \x01(\t")\n\'RespondActivityTaskCanceledByIdResponse"\x84\x02\n%RequestCancelWorkflowExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x45\n\x12workflow_execution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x12\n\nrequest_id\x18\x04 \x01(\t\x12\x1e\n\x16\x66irst_execution_run_id\x18\x05 \x01(\t\x12\x0e\n\x06reason\x18\x06 \x01(\t\x12+\n\x05links\x18\x07 \x03(\x0b\x32\x1c.temporal.api.common.v1.Link"(\n&RequestCancelWorkflowExecutionResponse"\xde\x02\n\x1eSignalWorkflowExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x45\n\x12workflow_execution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x13\n\x0bsignal_name\x18\x03 \x01(\t\x12/\n\x05input\x18\x04 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x10\n\x08identity\x18\x05 \x01(\t\x12\x12\n\nrequest_id\x18\x06 \x01(\t\x12\x13\n\x07\x63ontrol\x18\x07 \x01(\tB\x02\x18\x01\x12.\n\x06header\x18\x08 \x01(\x0b\x32\x1e.temporal.api.common.v1.Header\x12+\n\x05links\x18\n \x03(\x0b\x32\x1c.temporal.api.common.v1.LinkJ\x04\x08\t\x10\n"M\n\x1fSignalWorkflowExecutionResponse\x12*\n\x04link\x18\x01 \x01(\x0b\x32\x1c.temporal.api.common.v1.Link"\xbb\n\n\'SignalWithStartWorkflowExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12;\n\rworkflow_type\x18\x03 \x01(\x0b\x32$.temporal.api.common.v1.WorkflowType\x12\x38\n\ntask_queue\x18\x04 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12/\n\x05input\x18\x05 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12=\n\x1aworkflow_execution_timeout\x18\x06 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x37\n\x14workflow_run_timeout\x18\x07 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x38\n\x15workflow_task_timeout\x18\x08 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x10\n\x08identity\x18\t \x01(\t\x12\x12\n\nrequest_id\x18\n \x01(\t\x12N\n\x18workflow_id_reuse_policy\x18\x0b \x01(\x0e\x32,.temporal.api.enums.v1.WorkflowIdReusePolicy\x12T\n\x1bworkflow_id_conflict_policy\x18\x16 \x01(\x0e\x32/.temporal.api.enums.v1.WorkflowIdConflictPolicy\x12\x13\n\x0bsignal_name\x18\x0c \x01(\t\x12\x36\n\x0csignal_input\x18\r \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x13\n\x07\x63ontrol\x18\x0e \x01(\tB\x02\x18\x01\x12\x39\n\x0cretry_policy\x18\x0f \x01(\x0b\x32#.temporal.api.common.v1.RetryPolicy\x12\x15\n\rcron_schedule\x18\x10 \x01(\t\x12*\n\x04memo\x18\x11 \x01(\x0b\x32\x1c.temporal.api.common.v1.Memo\x12\x43\n\x11search_attributes\x18\x12 \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes\x12.\n\x06header\x18\x13 \x01(\x0b\x32\x1e.temporal.api.common.v1.Header\x12\x37\n\x14workflow_start_delay\x18\x14 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x38\n\ruser_metadata\x18\x17 \x01(\x0b\x32!.temporal.api.sdk.v1.UserMetadata\x12+\n\x05links\x18\x18 \x03(\x0b\x32\x1c.temporal.api.common.v1.Link\x12I\n\x13versioning_override\x18\x19 \x01(\x0b\x32,.temporal.api.workflow.v1.VersioningOverride\x12\x32\n\x08priority\x18\x1a \x01(\x0b\x32 .temporal.api.common.v1.Priority\x12H\n\x14time_skipping_config\x18\x1b \x01(\x0b\x32*.temporal.api.common.v1.TimeSkippingConfigJ\x04\x08\x15\x10\x16"\x9e\x01\n(SignalWithStartWorkflowExecutionResponse\x12\x0e\n\x06run_id\x18\x01 \x01(\t\x12\x1e\n\x16\x66irst_execution_run_id\x18\x04 \x01(\t\x12\x0f\n\x07started\x18\x02 \x01(\x08\x12\x31\n\x0bsignal_link\x18\x03 \x01(\x0b\x32\x1c.temporal.api.common.v1.Link"\xc1\x03\n\x1dResetWorkflowExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x45\n\x12workflow_execution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x0e\n\x06reason\x18\x03 \x01(\t\x12%\n\x1dworkflow_task_finish_event_id\x18\x04 \x01(\x03\x12\x12\n\nrequest_id\x18\x05 \x01(\t\x12G\n\x12reset_reapply_type\x18\x06 \x01(\x0e\x32\'.temporal.api.enums.v1.ResetReapplyTypeB\x02\x18\x01\x12S\n\x1breset_reapply_exclude_types\x18\x07 \x03(\x0e\x32..temporal.api.enums.v1.ResetReapplyExcludeType\x12K\n\x15post_reset_operations\x18\x08 \x03(\x0b\x32,.temporal.api.workflow.v1.PostResetOperation\x12\x10\n\x08identity\x18\t \x01(\t"0\n\x1eResetWorkflowExecutionResponse\x12\x0e\n\x06run_id\x18\x01 \x01(\t"\x9f\x02\n!TerminateWorkflowExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x45\n\x12workflow_execution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x0e\n\x06reason\x18\x03 \x01(\t\x12\x31\n\x07\x64\x65tails\x18\x04 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x10\n\x08identity\x18\x05 \x01(\t\x12\x1e\n\x16\x66irst_execution_run_id\x18\x06 \x01(\t\x12+\n\x05links\x18\x07 \x03(\x0b\x32\x1c.temporal.api.common.v1.Link"$\n"TerminateWorkflowExecutionResponse"z\n\x1e\x44\x65leteWorkflowExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x45\n\x12workflow_execution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution"!\n\x1f\x44\x65leteWorkflowExecutionResponse"\xc9\x02\n!ListOpenWorkflowExecutionsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x19\n\x11maximum_page_size\x18\x02 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c\x12\x42\n\x11start_time_filter\x18\x04 \x01(\x0b\x32\'.temporal.api.filter.v1.StartTimeFilter\x12K\n\x10\x65xecution_filter\x18\x05 \x01(\x0b\x32/.temporal.api.filter.v1.WorkflowExecutionFilterH\x00\x12\x41\n\x0btype_filter\x18\x06 \x01(\x0b\x32*.temporal.api.filter.v1.WorkflowTypeFilterH\x00\x42\t\n\x07\x66ilters"\x82\x01\n"ListOpenWorkflowExecutionsResponse\x12\x43\n\nexecutions\x18\x01 \x03(\x0b\x32/.temporal.api.workflow.v1.WorkflowExecutionInfo\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c"\x8a\x03\n#ListClosedWorkflowExecutionsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x19\n\x11maximum_page_size\x18\x02 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c\x12\x42\n\x11start_time_filter\x18\x04 \x01(\x0b\x32\'.temporal.api.filter.v1.StartTimeFilter\x12K\n\x10\x65xecution_filter\x18\x05 \x01(\x0b\x32/.temporal.api.filter.v1.WorkflowExecutionFilterH\x00\x12\x41\n\x0btype_filter\x18\x06 \x01(\x0b\x32*.temporal.api.filter.v1.WorkflowTypeFilterH\x00\x12=\n\rstatus_filter\x18\x07 \x01(\x0b\x32$.temporal.api.filter.v1.StatusFilterH\x00\x42\t\n\x07\x66ilters"\x84\x01\n$ListClosedWorkflowExecutionsResponse\x12\x43\n\nexecutions\x18\x01 \x03(\x0b\x32/.temporal.api.workflow.v1.WorkflowExecutionInfo\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c"m\n\x1dListWorkflowExecutionsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x11\n\tpage_size\x18\x02 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c\x12\r\n\x05query\x18\x04 \x01(\t"~\n\x1eListWorkflowExecutionsResponse\x12\x43\n\nexecutions\x18\x01 \x03(\x0b\x32/.temporal.api.workflow.v1.WorkflowExecutionInfo\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c"u\n%ListArchivedWorkflowExecutionsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x11\n\tpage_size\x18\x02 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c\x12\r\n\x05query\x18\x04 \x01(\t"\x86\x01\n&ListArchivedWorkflowExecutionsResponse\x12\x43\n\nexecutions\x18\x01 \x03(\x0b\x32/.temporal.api.workflow.v1.WorkflowExecutionInfo\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c"m\n\x1dScanWorkflowExecutionsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x11\n\tpage_size\x18\x02 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c\x12\r\n\x05query\x18\x04 \x01(\t"~\n\x1eScanWorkflowExecutionsResponse\x12\x43\n\nexecutions\x18\x01 \x03(\x0b\x32/.temporal.api.workflow.v1.WorkflowExecutionInfo\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c"B\n\x1e\x43ountWorkflowExecutionsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\r\n\x05query\x18\x02 \x01(\t"\xed\x01\n\x1f\x43ountWorkflowExecutionsResponse\x12\r\n\x05\x63ount\x18\x01 \x01(\x03\x12\x61\n\x06groups\x18\x02 \x03(\x0b\x32Q.temporal.api.workflowservice.v1.CountWorkflowExecutionsResponse.AggregationGroup\x1aX\n\x10\x41ggregationGroup\x12\x35\n\x0cgroup_values\x18\x01 \x03(\x0b\x32\x1f.temporal.api.common.v1.Payload\x12\r\n\x05\x63ount\x18\x02 \x01(\x03"\x1c\n\x1aGetSearchAttributesRequest"\xc9\x01\n\x1bGetSearchAttributesResponse\x12T\n\x04keys\x18\x01 \x03(\x0b\x32\x46.temporal.api.workflowservice.v1.GetSearchAttributesResponse.KeysEntry\x1aT\n\tKeysEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x36\n\x05value\x18\x02 \x01(\x0e\x32\'.temporal.api.enums.v1.IndexedValueType:\x02\x38\x01"\xe9\x02\n RespondQueryTaskCompletedRequest\x12\x12\n\ntask_token\x18\x01 \x01(\x0c\x12>\n\x0e\x63ompleted_type\x18\x02 \x01(\x0e\x32&.temporal.api.enums.v1.QueryResultType\x12\x36\n\x0cquery_result\x18\x03 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x15\n\rerror_message\x18\x04 \x01(\t\x12\x11\n\tnamespace\x18\x06 \x01(\t\x12\x31\n\x07\x66\x61ilure\x18\x07 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12=\n\x05\x63\x61use\x18\x08 \x01(\x0e\x32..temporal.api.enums.v1.WorkflowTaskFailedCause\x12\x17\n\x0fpoller_group_id\x18\t \x01(\tJ\x04\x08\x05\x10\x06"#\n!RespondQueryTaskCompletedResponse"n\n\x1bResetStickyTaskQueueRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12<\n\texecution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution"\x1e\n\x1cResetStickyTaskQueueResponse"\x9b\x02\n\x15ShutdownWorkerRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x19\n\x11sticky_task_queue\x18\x02 \x01(\t\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x0e\n\x06reason\x18\x04 \x01(\t\x12\x41\n\x10worker_heartbeat\x18\x05 \x01(\x0b\x32\'.temporal.api.worker.v1.WorkerHeartbeat\x12\x1b\n\x13worker_instance_key\x18\x06 \x01(\t\x12\x12\n\ntask_queue\x18\x07 \x01(\t\x12>\n\x10task_queue_types\x18\x08 \x03(\x0e\x32$.temporal.api.enums.v1.TaskQueueType"\x18\n\x16ShutdownWorkerResponse"\xe9\x01\n\x14QueryWorkflowRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12<\n\texecution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x33\n\x05query\x18\x03 \x01(\x0b\x32$.temporal.api.query.v1.WorkflowQuery\x12K\n\x16query_reject_condition\x18\x04 \x01(\x0e\x32+.temporal.api.enums.v1.QueryRejectCondition"\x8d\x01\n\x15QueryWorkflowResponse\x12\x36\n\x0cquery_result\x18\x01 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12<\n\x0equery_rejected\x18\x02 \x01(\x0b\x32$.temporal.api.query.v1.QueryRejected"s\n DescribeWorkflowExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12<\n\texecution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution"\x99\x05\n!DescribeWorkflowExecutionResponse\x12K\n\x10\x65xecution_config\x18\x01 \x01(\x0b\x32\x31.temporal.api.workflow.v1.WorkflowExecutionConfig\x12P\n\x17workflow_execution_info\x18\x02 \x01(\x0b\x32/.temporal.api.workflow.v1.WorkflowExecutionInfo\x12I\n\x12pending_activities\x18\x03 \x03(\x0b\x32-.temporal.api.workflow.v1.PendingActivityInfo\x12M\n\x10pending_children\x18\x04 \x03(\x0b\x32\x33.temporal.api.workflow.v1.PendingChildExecutionInfo\x12P\n\x15pending_workflow_task\x18\x05 \x01(\x0b\x32\x31.temporal.api.workflow.v1.PendingWorkflowTaskInfo\x12\x39\n\tcallbacks\x18\x06 \x03(\x0b\x32&.temporal.api.workflow.v1.CallbackInfo\x12U\n\x18pending_nexus_operations\x18\x07 \x03(\x0b\x32\x33.temporal.api.workflow.v1.PendingNexusOperationInfo\x12W\n\x16workflow_extended_info\x18\x08 \x01(\x0b\x32\x37.temporal.api.workflow.v1.WorkflowExecutionExtendedInfo"\x90\x04\n\x18\x44\x65scribeTaskQueueRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x38\n\ntask_queue\x18\x02 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12=\n\x0ftask_queue_type\x18\x03 \x01(\x0e\x32$.temporal.api.enums.v1.TaskQueueType\x12\x14\n\x0creport_stats\x18\x08 \x01(\x08\x12\x15\n\rreport_config\x18\x0b \x01(\x08\x12%\n\x19include_task_queue_status\x18\x04 \x01(\x08\x42\x02\x18\x01\x12\x42\n\x08\x61pi_mode\x18\x05 \x01(\x0e\x32,.temporal.api.enums.v1.DescribeTaskQueueModeB\x02\x18\x01\x12J\n\x08versions\x18\x06 \x01(\x0b\x32\x34.temporal.api.taskqueue.v1.TaskQueueVersionSelectionB\x02\x18\x01\x12\x42\n\x10task_queue_types\x18\x07 \x03(\x0e\x32$.temporal.api.enums.v1.TaskQueueTypeB\x02\x18\x01\x12\x1a\n\x0ereport_pollers\x18\t \x01(\x08\x42\x02\x18\x01\x12$\n\x18report_task_reachability\x18\n \x01(\x08\x42\x02\x18\x01"\xec\x07\n\x19\x44\x65scribeTaskQueueResponse\x12\x36\n\x07pollers\x18\x01 \x03(\x0b\x32%.temporal.api.taskqueue.v1.PollerInfo\x12\x38\n\x05stats\x18\x05 \x01(\x0b\x32).temporal.api.taskqueue.v1.TaskQueueStats\x12q\n\x15stats_by_priority_key\x18\x08 \x03(\x0b\x32R.temporal.api.workflowservice.v1.DescribeTaskQueueResponse.StatsByPriorityKeyEntry\x12K\n\x0fversioning_info\x18\x04 \x01(\x0b\x32\x32.temporal.api.taskqueue.v1.TaskQueueVersioningInfo\x12:\n\x06\x63onfig\x18\x06 \x01(\x0b\x32*.temporal.api.taskqueue.v1.TaskQueueConfig\x12k\n\x14\x65\x66\x66\x65\x63tive_rate_limit\x18\x07 \x01(\x0b\x32M.temporal.api.workflowservice.v1.DescribeTaskQueueResponse.EffectiveRateLimit\x12I\n\x11task_queue_status\x18\x02 \x01(\x0b\x32*.temporal.api.taskqueue.v1.TaskQueueStatusB\x02\x18\x01\x12g\n\rversions_info\x18\x03 \x03(\x0b\x32L.temporal.api.workflowservice.v1.DescribeTaskQueueResponse.VersionsInfoEntryB\x02\x18\x01\x1a\x64\n\x17StatsByPriorityKeyEntry\x12\x0b\n\x03key\x18\x01 \x01(\x05\x12\x38\n\x05value\x18\x02 \x01(\x0b\x32).temporal.api.taskqueue.v1.TaskQueueStats:\x02\x38\x01\x1at\n\x12\x45\x66\x66\x65\x63tiveRateLimit\x12\x1b\n\x13requests_per_second\x18\x01 \x01(\x02\x12\x41\n\x11rate_limit_source\x18\x02 \x01(\x0e\x32&.temporal.api.enums.v1.RateLimitSource\x1a\x64\n\x11VersionsInfoEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12>\n\x05value\x18\x02 \x01(\x0b\x32/.temporal.api.taskqueue.v1.TaskQueueVersionInfo:\x02\x38\x01"\x17\n\x15GetClusterInfoRequest"\xd1\x03\n\x16GetClusterInfoResponse\x12h\n\x11supported_clients\x18\x01 \x03(\x0b\x32M.temporal.api.workflowservice.v1.GetClusterInfoResponse.SupportedClientsEntry\x12\x16\n\x0eserver_version\x18\x02 \x01(\t\x12\x12\n\ncluster_id\x18\x03 \x01(\t\x12:\n\x0cversion_info\x18\x04 \x01(\x0b\x32$.temporal.api.version.v1.VersionInfo\x12\x14\n\x0c\x63luster_name\x18\x05 \x01(\t\x12\x1b\n\x13history_shard_count\x18\x06 \x01(\x05\x12\x19\n\x11persistence_store\x18\x07 \x01(\t\x12\x18\n\x10visibility_store\x18\x08 \x01(\t\x12 \n\x18initial_failover_version\x18\t \x01(\x03\x12"\n\x1a\x66\x61ilover_version_increment\x18\n \x01(\x03\x1a\x37\n\x15SupportedClientsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01"\x16\n\x14GetSystemInfoRequest"\xc1\x04\n\x15GetSystemInfoResponse\x12\x16\n\x0eserver_version\x18\x01 \x01(\t\x12Y\n\x0c\x63\x61pabilities\x18\x02 \x01(\x0b\x32\x43.temporal.api.workflowservice.v1.GetSystemInfoResponse.Capabilities\x1a\xb4\x03\n\x0c\x43\x61pabilities\x12\x1f\n\x17signal_and_query_header\x18\x01 \x01(\x08\x12&\n\x1einternal_error_differentiation\x18\x02 \x01(\x08\x12*\n"activity_failure_include_heartbeat\x18\x03 \x01(\x08\x12\x1a\n\x12supports_schedules\x18\x04 \x01(\x08\x12"\n\x1a\x65ncoded_failure_attributes\x18\x05 \x01(\x08\x12!\n\x19\x62uild_id_based_versioning\x18\x06 \x01(\x08\x12\x13\n\x0bupsert_memo\x18\x07 \x01(\x08\x12\x1c\n\x14\x65\x61ger_workflow_start\x18\x08 \x01(\x08\x12\x14\n\x0csdk_metadata\x18\t \x01(\x08\x12\'\n\x1f\x63ount_group_by_execution_status\x18\n \x01(\x08\x12\r\n\x05nexus\x18\x0b \x01(\x08\x12!\n\x19server_scaled_deployments\x18\x0c \x01(\x08\x12(\n server_scaled_provider_cloud_run\x18\r \x01(\x08"m\n\x1eListTaskQueuePartitionsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x38\n\ntask_queue\x18\x02 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue"\xdf\x01\n\x1fListTaskQueuePartitionsResponse\x12]\n\x1e\x61\x63tivity_task_queue_partitions\x18\x01 \x03(\x0b\x32\x35.temporal.api.taskqueue.v1.TaskQueuePartitionMetadata\x12]\n\x1eworkflow_task_queue_partitions\x18\x02 \x03(\x0b\x32\x35.temporal.api.taskqueue.v1.TaskQueuePartitionMetadata"\xcc\x02\n\x15\x43reateScheduleRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bschedule_id\x18\x02 \x01(\t\x12\x34\n\x08schedule\x18\x03 \x01(\x0b\x32".temporal.api.schedule.v1.Schedule\x12>\n\rinitial_patch\x18\x04 \x01(\x0b\x32\'.temporal.api.schedule.v1.SchedulePatch\x12\x10\n\x08identity\x18\x05 \x01(\t\x12\x12\n\nrequest_id\x18\x06 \x01(\t\x12*\n\x04memo\x18\x07 \x01(\x0b\x32\x1c.temporal.api.common.v1.Memo\x12\x43\n\x11search_attributes\x18\x08 \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes"0\n\x16\x43reateScheduleResponse\x12\x16\n\x0e\x63onflict_token\x18\x01 \x01(\x0c"A\n\x17\x44\x65scribeScheduleRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bschedule_id\x18\x02 \x01(\t"\x8f\x02\n\x18\x44\x65scribeScheduleResponse\x12\x34\n\x08schedule\x18\x01 \x01(\x0b\x32".temporal.api.schedule.v1.Schedule\x12\x34\n\x04info\x18\x02 \x01(\x0b\x32&.temporal.api.schedule.v1.ScheduleInfo\x12*\n\x04memo\x18\x03 \x01(\x0b\x32\x1c.temporal.api.common.v1.Memo\x12\x43\n\x11search_attributes\x18\x04 \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes\x12\x16\n\x0e\x63onflict_token\x18\x05 \x01(\x0c"\xa4\x02\n\x15UpdateScheduleRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bschedule_id\x18\x02 \x01(\t\x12\x34\n\x08schedule\x18\x03 \x01(\x0b\x32".temporal.api.schedule.v1.Schedule\x12\x16\n\x0e\x63onflict_token\x18\x04 \x01(\x0c\x12\x10\n\x08identity\x18\x05 \x01(\t\x12\x12\n\nrequest_id\x18\x06 \x01(\t\x12\x43\n\x11search_attributes\x18\x07 \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes\x12*\n\x04memo\x18\x08 \x01(\x0b\x32\x1c.temporal.api.common.v1.Memo"\x18\n\x16UpdateScheduleResponse"\x9c\x01\n\x14PatchScheduleRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bschedule_id\x18\x02 \x01(\t\x12\x36\n\x05patch\x18\x03 \x01(\x0b\x32\'.temporal.api.schedule.v1.SchedulePatch\x12\x10\n\x08identity\x18\x04 \x01(\t\x12\x12\n\nrequest_id\x18\x05 \x01(\t"\x17\n\x15PatchScheduleResponse"\xa8\x01\n ListScheduleMatchingTimesRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bschedule_id\x18\x02 \x01(\t\x12.\n\nstart_time\x18\x03 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12,\n\x08\x65nd_time\x18\x04 \x01(\x0b\x32\x1a.google.protobuf.Timestamp"S\n!ListScheduleMatchingTimesResponse\x12.\n\nstart_time\x18\x01 \x03(\x0b\x32\x1a.google.protobuf.Timestamp"Q\n\x15\x44\x65leteScheduleRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bschedule_id\x18\x02 \x01(\t\x12\x10\n\x08identity\x18\x03 \x01(\t"\x18\n\x16\x44\x65leteScheduleResponse"l\n\x14ListSchedulesRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x19\n\x11maximum_page_size\x18\x02 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c\x12\r\n\x05query\x18\x04 \x01(\t"p\n\x15ListSchedulesResponse\x12>\n\tschedules\x18\x01 \x03(\x0b\x32+.temporal.api.schedule.v1.ScheduleListEntry\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c"9\n\x15\x43ountSchedulesRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\r\n\x05query\x18\x02 \x01(\t"\xdb\x01\n\x16\x43ountSchedulesResponse\x12\r\n\x05\x63ount\x18\x01 \x01(\x03\x12X\n\x06groups\x18\x02 \x03(\x0b\x32H.temporal.api.workflowservice.v1.CountSchedulesResponse.AggregationGroup\x1aX\n\x10\x41ggregationGroup\x12\x35\n\x0cgroup_values\x18\x01 \x03(\x0b\x32\x1f.temporal.api.common.v1.Payload\x12\r\n\x05\x63ount\x18\x02 \x01(\x03"\x86\x05\n\'UpdateWorkerBuildIdCompatibilityRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x12\n\ntask_queue\x18\x02 \x01(\t\x12-\n#add_new_build_id_in_new_default_set\x18\x03 \x01(\tH\x00\x12\x87\x01\n\x1b\x61\x64\x64_new_compatible_build_id\x18\x04 \x01(\x0b\x32`.temporal.api.workflowservice.v1.UpdateWorkerBuildIdCompatibilityRequest.AddNewCompatibleVersionH\x00\x12!\n\x17promote_set_by_build_id\x18\x05 \x01(\tH\x00\x12%\n\x1bpromote_build_id_within_set\x18\x06 \x01(\tH\x00\x12h\n\nmerge_sets\x18\x07 \x01(\x0b\x32R.temporal.api.workflowservice.v1.UpdateWorkerBuildIdCompatibilityRequest.MergeSetsH\x00\x1ao\n\x17\x41\x64\x64NewCompatibleVersion\x12\x14\n\x0cnew_build_id\x18\x01 \x01(\t\x12$\n\x1c\x65xisting_compatible_build_id\x18\x02 \x01(\t\x12\x18\n\x10make_set_default\x18\x03 \x01(\x08\x1aI\n\tMergeSets\x12\x1c\n\x14primary_set_build_id\x18\x01 \x01(\t\x12\x1e\n\x16secondary_set_build_id\x18\x02 \x01(\tB\x0b\n\toperation"@\n(UpdateWorkerBuildIdCompatibilityResponseJ\x04\x08\x01\x10\x02R\x0eversion_set_id"_\n$GetWorkerBuildIdCompatibilityRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x12\n\ntask_queue\x18\x02 \x01(\t\x12\x10\n\x08max_sets\x18\x03 \x01(\x05"t\n%GetWorkerBuildIdCompatibilityResponse\x12K\n\x12major_version_sets\x18\x01 \x03(\x0b\x32/.temporal.api.taskqueue.v1.CompatibleVersionSet"\xb5\r\n"UpdateWorkerVersioningRulesRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x12\n\ntask_queue\x18\x02 \x01(\t\x12\x16\n\x0e\x63onflict_token\x18\x03 \x01(\x0c\x12\x81\x01\n\x16insert_assignment_rule\x18\x04 \x01(\x0b\x32_.temporal.api.workflowservice.v1.UpdateWorkerVersioningRulesRequest.InsertBuildIdAssignmentRuleH\x00\x12\x83\x01\n\x17replace_assignment_rule\x18\x05 \x01(\x0b\x32`.temporal.api.workflowservice.v1.UpdateWorkerVersioningRulesRequest.ReplaceBuildIdAssignmentRuleH\x00\x12\x81\x01\n\x16\x64\x65lete_assignment_rule\x18\x06 \x01(\x0b\x32_.temporal.api.workflowservice.v1.UpdateWorkerVersioningRulesRequest.DeleteBuildIdAssignmentRuleH\x00\x12\x8c\x01\n\x1c\x61\x64\x64_compatible_redirect_rule\x18\x07 \x01(\x0b\x32\x64.temporal.api.workflowservice.v1.UpdateWorkerVersioningRulesRequest.AddCompatibleBuildIdRedirectRuleH\x00\x12\x94\x01\n replace_compatible_redirect_rule\x18\x08 \x01(\x0b\x32h.temporal.api.workflowservice.v1.UpdateWorkerVersioningRulesRequest.ReplaceCompatibleBuildIdRedirectRuleH\x00\x12\x92\x01\n\x1f\x64\x65lete_compatible_redirect_rule\x18\t \x01(\x0b\x32g.temporal.api.workflowservice.v1.UpdateWorkerVersioningRulesRequest.DeleteCompatibleBuildIdRedirectRuleH\x00\x12l\n\x0f\x63ommit_build_id\x18\n \x01(\x0b\x32Q.temporal.api.workflowservice.v1.UpdateWorkerVersioningRulesRequest.CommitBuildIdH\x00\x1aq\n\x1bInsertBuildIdAssignmentRule\x12\x12\n\nrule_index\x18\x01 \x01(\x05\x12>\n\x04rule\x18\x02 \x01(\x0b\x32\x30.temporal.api.taskqueue.v1.BuildIdAssignmentRule\x1a\x81\x01\n\x1cReplaceBuildIdAssignmentRule\x12\x12\n\nrule_index\x18\x01 \x01(\x05\x12>\n\x04rule\x18\x02 \x01(\x0b\x32\x30.temporal.api.taskqueue.v1.BuildIdAssignmentRule\x12\r\n\x05\x66orce\x18\x03 \x01(\x08\x1a@\n\x1b\x44\x65leteBuildIdAssignmentRule\x12\x12\n\nrule_index\x18\x01 \x01(\x05\x12\r\n\x05\x66orce\x18\x02 \x01(\x08\x1aj\n AddCompatibleBuildIdRedirectRule\x12\x46\n\x04rule\x18\x01 \x01(\x0b\x32\x38.temporal.api.taskqueue.v1.CompatibleBuildIdRedirectRule\x1an\n$ReplaceCompatibleBuildIdRedirectRule\x12\x46\n\x04rule\x18\x01 \x01(\x0b\x32\x38.temporal.api.taskqueue.v1.CompatibleBuildIdRedirectRule\x1a>\n#DeleteCompatibleBuildIdRedirectRule\x12\x17\n\x0fsource_build_id\x18\x01 \x01(\t\x1a\x37\n\rCommitBuildId\x12\x17\n\x0ftarget_build_id\x18\x01 \x01(\t\x12\r\n\x05\x66orce\x18\x02 \x01(\x08\x42\x0b\n\toperation"\xfc\x01\n#UpdateWorkerVersioningRulesResponse\x12U\n\x10\x61ssignment_rules\x18\x01 \x03(\x0b\x32;.temporal.api.taskqueue.v1.TimestampedBuildIdAssignmentRule\x12\x66\n\x19\x63ompatible_redirect_rules\x18\x02 \x03(\x0b\x32\x43.temporal.api.taskqueue.v1.TimestampedCompatibleBuildIdRedirectRule\x12\x16\n\x0e\x63onflict_token\x18\x03 \x01(\x0c"H\n\x1fGetWorkerVersioningRulesRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x12\n\ntask_queue\x18\x02 \x01(\t"\xf9\x01\n GetWorkerVersioningRulesResponse\x12U\n\x10\x61ssignment_rules\x18\x01 \x03(\x0b\x32;.temporal.api.taskqueue.v1.TimestampedBuildIdAssignmentRule\x12\x66\n\x19\x63ompatible_redirect_rules\x18\x02 \x03(\x0b\x32\x43.temporal.api.taskqueue.v1.TimestampedCompatibleBuildIdRedirectRule\x12\x16\n\x0e\x63onflict_token\x18\x03 \x01(\x0c"\x9c\x01\n GetWorkerTaskReachabilityRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x11\n\tbuild_ids\x18\x02 \x03(\t\x12\x13\n\x0btask_queues\x18\x03 \x03(\t\x12=\n\x0creachability\x18\x04 \x01(\x0e\x32\'.temporal.api.enums.v1.TaskReachability"r\n!GetWorkerTaskReachabilityResponse\x12M\n\x15\x62uild_id_reachability\x18\x01 \x03(\x0b\x32..temporal.api.taskqueue.v1.BuildIdReachability"\x85\x02\n\x1eUpdateWorkflowExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x45\n\x12workflow_execution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x1e\n\x16\x66irst_execution_run_id\x18\x03 \x01(\t\x12\x37\n\x0bwait_policy\x18\x04 \x01(\x0b\x32".temporal.api.update.v1.WaitPolicy\x12\x30\n\x07request\x18\x05 \x01(\x0b\x32\x1f.temporal.api.update.v1.Request"\x83\x02\n\x1fUpdateWorkflowExecutionResponse\x12\x35\n\nupdate_ref\x18\x01 \x01(\x0b\x32!.temporal.api.update.v1.UpdateRef\x12\x30\n\x07outcome\x18\x02 \x01(\x0b\x32\x1f.temporal.api.update.v1.Outcome\x12K\n\x05stage\x18\x03 \x01(\x0e\x32<.temporal.api.enums.v1.UpdateWorkflowExecutionLifecycleStage\x12*\n\x04link\x18\x04 \x01(\x0b\x32\x1c.temporal.api.common.v1.Link"\xd6\n\n\x1aStartBatchOperationRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x18\n\x10visibility_query\x18\x02 \x01(\t\x12\x0e\n\x06job_id\x18\x03 \x01(\t\x12\x0e\n\x06reason\x18\x04 \x01(\t\x12\x41\n\nexecutions\x18\x05 \x03(\x0b\x32).temporal.api.common.v1.WorkflowExecutionB\x02\x18\x01\x12<\n\x11target_executions\x18\x16 \x03(\x0b\x32!.temporal.api.common.v1.Execution\x12!\n\x19max_operations_per_second\x18\x06 \x01(\x02\x12Q\n\x15termination_operation\x18\n \x01(\x0b\x32\x30.temporal.api.batch.v1.BatchOperationTerminationH\x00\x12G\n\x10signal_operation\x18\x0b \x01(\x0b\x32+.temporal.api.batch.v1.BatchOperationSignalH\x00\x12S\n\x16\x63\x61ncellation_operation\x18\x0c \x01(\x0b\x32\x31.temporal.api.batch.v1.BatchOperationCancellationH\x00\x12K\n\x12\x64\x65letion_operation\x18\r \x01(\x0b\x32-.temporal.api.batch.v1.BatchOperationDeletionH\x00\x12\x45\n\x0freset_operation\x18\x0e \x01(\x0b\x32*.temporal.api.batch.v1.BatchOperationResetH\x00\x12p\n!update_workflow_options_operation\x18\x0f \x01(\x0b\x32\x43.temporal.api.batch.v1.BatchOperationUpdateWorkflowExecutionOptionsH\x00\x12^\n\x1cunpause_activities_operation\x18\x10 \x01(\x0b\x32\x36.temporal.api.batch.v1.BatchOperationUnpauseActivitiesH\x00\x12Z\n\x1areset_activities_operation\x18\x11 \x01(\x0b\x32\x34.temporal.api.batch.v1.BatchOperationResetActivitiesH\x00\x12g\n!update_activity_options_operation\x18\x12 \x01(\x0b\x32:.temporal.api.batch.v1.BatchOperationUpdateActivityOptionsH\x00\x12\\\n\x1b\x63\x61ncel_activities_operation\x18\x13 \x01(\x0b\x32\x35.temporal.api.batch.v1.BatchOperationCancelActivitiesH\x00\x12\x62\n\x1eterminate_activities_operation\x18\x14 \x01(\x0b\x32\x38.temporal.api.batch.v1.BatchOperationTerminateActivitiesH\x00\x12\\\n\x1b\x64\x65lete_activities_operation\x18\x15 \x01(\x0b\x32\x35.temporal.api.batch.v1.BatchOperationDeleteActivitiesH\x00\x42\x0b\n\toperation"\x1d\n\x1bStartBatchOperationResponse"`\n\x19StopBatchOperationRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x0e\n\x06job_id\x18\x02 \x01(\t\x12\x0e\n\x06reason\x18\x03 \x01(\t\x12\x10\n\x08identity\x18\x04 \x01(\t"\x1c\n\x1aStopBatchOperationResponse"B\n\x1d\x44\x65scribeBatchOperationRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x0e\n\x06job_id\x18\x02 \x01(\t"\xd8\x03\n\x1e\x44\x65scribeBatchOperationResponse\x12\x41\n\x0eoperation_type\x18\x01 \x01(\x0e\x32).temporal.api.enums.v1.BatchOperationType\x12\x0e\n\x06job_id\x18\x02 \x01(\t\x12\x39\n\x05state\x18\x03 \x01(\x0e\x32*.temporal.api.enums.v1.BatchOperationState\x12.\n\nstart_time\x18\x04 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12.\n\nclose_time\x18\x05 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x1d\n\x15total_operation_count\x18\x06 \x01(\x03\x12 \n\x18\x63omplete_operation_count\x18\x07 \x01(\x03\x12\x1f\n\x17\x66\x61ilure_operation_count\x18\x08 \x01(\x03\x12\x10\n\x08identity\x18\t \x01(\t\x12\x0e\n\x06reason\x18\n \x01(\t\x12\r\n\x05query\x18\x0b \x01(\t\x12\x35\n\nexecutions\x18\x0c \x03(\x0b\x32!.temporal.api.common.v1.Execution"[\n\x1aListBatchOperationsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x11\n\tpage_size\x18\x02 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c"y\n\x1bListBatchOperationsResponse\x12\x41\n\x0eoperation_info\x18\x01 \x03(\x0b\x32).temporal.api.batch.v1.BatchOperationInfo\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c"\xb9\x01\n"PollWorkflowExecutionUpdateRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x35\n\nupdate_ref\x18\x02 \x01(\x0b\x32!.temporal.api.update.v1.UpdateRef\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x37\n\x0bwait_policy\x18\x04 \x01(\x0b\x32".temporal.api.update.v1.WaitPolicy"\xdb\x01\n#PollWorkflowExecutionUpdateResponse\x12\x30\n\x07outcome\x18\x01 \x01(\x0b\x32\x1f.temporal.api.update.v1.Outcome\x12K\n\x05stage\x18\x02 \x01(\x0e\x32<.temporal.api.enums.v1.UpdateWorkflowExecutionLifecycleStage\x12\x35\n\nupdate_ref\x18\x03 \x01(\x0b\x32!.temporal.api.update.v1.UpdateRef"\xa0\x03\n\x19PollNexusTaskQueueRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x38\n\ntask_queue\x18\x03 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12\x17\n\x0fpoller_group_id\x18\t \x01(\t\x12\x10\n\x08identity\x18\x02 \x01(\t\x12\x1b\n\x13worker_instance_key\x18\x08 \x01(\t\x12Z\n\x1bworker_version_capabilities\x18\x04 \x01(\x0b\x32\x31.temporal.api.common.v1.WorkerVersionCapabilitiesB\x02\x18\x01\x12O\n\x12\x64\x65ployment_options\x18\x06 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentOptions\x12\x41\n\x10worker_heartbeat\x18\x07 \x03(\x0b\x32\'.temporal.api.worker.v1.WorkerHeartbeat"\xe2\x02\n\x1aPollNexusTaskQueueResponse\x12\x12\n\ntask_token\x18\x01 \x01(\x0c\x12/\n\x07request\x18\x02 \x01(\x0b\x32\x1e.temporal.api.nexus.v1.Request\x12Q\n\x17poller_scaling_decision\x18\x03 \x01(\x0b\x32\x30.temporal.api.taskqueue.v1.PollerScalingDecision\x12\x17\n\x0fpoller_group_id\x18\x04 \x01(\t\x12J\n\x12poller_group_infos\x18\x05 \x03(\x0b\x32*.temporal.api.taskqueue.v1.PollerGroupInfoB\x02\x18\x01\x12G\n\x12poller_groups_info\x18\x06 \x01(\x0b\x32+.temporal.api.taskqueue.v1.PollerGroupsInfo"\xa7\x01\n RespondNexusTaskCompletedRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x10\n\x08identity\x18\x02 \x01(\t\x12\x12\n\ntask_token\x18\x03 \x01(\x0c\x12\x31\n\x08response\x18\x04 \x01(\x0b\x32\x1f.temporal.api.nexus.v1.Response\x12\x17\n\x0fpoller_group_id\x18\x05 \x01(\t"#\n!RespondNexusTaskCompletedResponse"\xdc\x01\n\x1dRespondNexusTaskFailedRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x10\n\x08identity\x18\x02 \x01(\t\x12\x12\n\ntask_token\x18\x03 \x01(\x0c\x12\x36\n\x05\x65rror\x18\x04 \x01(\x0b\x32#.temporal.api.nexus.v1.HandlerErrorB\x02\x18\x01\x12\x31\n\x07\x66\x61ilure\x18\x05 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12\x17\n\x0fpoller_group_id\x18\x06 \x01(\t" \n\x1eRespondNexusTaskFailedResponse"\xf4\x02\n\x1c\x45xecuteMultiOperationRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12[\n\noperations\x18\x02 \x03(\x0b\x32G.temporal.api.workflowservice.v1.ExecuteMultiOperationRequest.Operation\x12\x13\n\x0bresource_id\x18\x03 \x01(\t\x1a\xce\x01\n\tOperation\x12X\n\x0estart_workflow\x18\x01 \x01(\x0b\x32>.temporal.api.workflowservice.v1.StartWorkflowExecutionRequestH\x00\x12Z\n\x0fupdate_workflow\x18\x02 \x01(\x0b\x32?.temporal.api.workflowservice.v1.UpdateWorkflowExecutionRequestH\x00\x42\x0b\n\toperation"\xcc\x02\n\x1d\x45xecuteMultiOperationResponse\x12Z\n\tresponses\x18\x01 \x03(\x0b\x32G.temporal.api.workflowservice.v1.ExecuteMultiOperationResponse.Response\x1a\xce\x01\n\x08Response\x12Y\n\x0estart_workflow\x18\x01 \x01(\x0b\x32?.temporal.api.workflowservice.v1.StartWorkflowExecutionResponseH\x00\x12[\n\x0fupdate_workflow\x18\x02 \x01(\x0b\x32@.temporal.api.workflowservice.v1.UpdateWorkflowExecutionResponseH\x00\x42\n\n\x08response"\xd0\x02\n\x1cUpdateActivityOptionsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12<\n\texecution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x43\n\x10\x61\x63tivity_options\x18\x04 \x01(\x0b\x32).temporal.api.activity.v1.ActivityOptions\x12/\n\x0bupdate_mask\x18\x05 \x01(\x0b\x32\x1a.google.protobuf.FieldMask\x12\x0c\n\x02id\x18\x06 \x01(\tH\x00\x12\x0e\n\x04type\x18\x07 \x01(\tH\x00\x12\x13\n\tmatch_all\x18\t \x01(\x08H\x00\x12\x18\n\x10restore_original\x18\x08 \x01(\x08\x42\n\n\x08\x61\x63tivity"\xab\x02\n%UpdateActivityExecutionOptionsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12\x13\n\x0b\x61\x63tivity_id\x18\x03 \x01(\t\x12\x0e\n\x06run_id\x18\x04 \x01(\t\x12\x10\n\x08identity\x18\x05 \x01(\t\x12\x43\n\x10\x61\x63tivity_options\x18\x06 \x01(\x0b\x32).temporal.api.activity.v1.ActivityOptions\x12/\n\x0bupdate_mask\x18\x07 \x01(\x0b\x32\x1a.google.protobuf.FieldMask\x12\x18\n\x10restore_original\x18\x08 \x01(\x08\x12\x13\n\x0bresource_id\x18\t \x01(\t"d\n\x1dUpdateActivityOptionsResponse\x12\x43\n\x10\x61\x63tivity_options\x18\x01 \x01(\x0b\x32).temporal.api.activity.v1.ActivityOptions"m\n&UpdateActivityExecutionOptionsResponse\x12\x43\n\x10\x61\x63tivity_options\x18\x01 \x01(\x0b\x32).temporal.api.activity.v1.ActivityOptions"\xc7\x01\n\x14PauseActivityRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12<\n\texecution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x0c\n\x02id\x18\x04 \x01(\tH\x00\x12\x0e\n\x04type\x18\x05 \x01(\tH\x00\x12\x0e\n\x06reason\x18\x06 \x01(\t\x12\x12\n\nrequest_id\x18\x07 \x01(\tB\n\n\x08\x61\x63tivity"\xb7\x01\n\x1dPauseActivityExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12\x13\n\x0b\x61\x63tivity_id\x18\x03 \x01(\t\x12\x0e\n\x06run_id\x18\x04 \x01(\t\x12\x10\n\x08identity\x18\x05 \x01(\t\x12\x0e\n\x06reason\x18\x06 \x01(\t\x12\x13\n\x0bresource_id\x18\x07 \x01(\t\x12\x12\n\nrequest_id\x18\x08 \x01(\t"\x17\n\x15PauseActivityResponse" \n\x1ePauseActivityExecutionResponse"\x98\x02\n\x16UnpauseActivityRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12<\n\texecution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x0c\n\x02id\x18\x04 \x01(\tH\x00\x12\x0e\n\x04type\x18\x05 \x01(\tH\x00\x12\x15\n\x0bunpause_all\x18\x06 \x01(\x08H\x00\x12\x16\n\x0ereset_attempts\x18\x07 \x01(\x08\x12\x17\n\x0freset_heartbeat\x18\x08 \x01(\x08\x12)\n\x06jitter\x18\t \x01(\x0b\x32\x19.google.protobuf.DurationB\n\n\x08\x61\x63tivity"\x81\x02\n\x1fUnpauseActivityExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12\x13\n\x0b\x61\x63tivity_id\x18\x03 \x01(\t\x12\x0e\n\x06run_id\x18\x04 \x01(\t\x12\x10\n\x08identity\x18\x05 \x01(\t\x12\x16\n\x0ereset_attempts\x18\x06 \x01(\x08\x12\x17\n\x0freset_heartbeat\x18\x07 \x01(\x08\x12\x0e\n\x06reason\x18\x08 \x01(\t\x12)\n\x06jitter\x18\t \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x13\n\x0bresource_id\x18\n \x01(\t"\x19\n\x17UnpauseActivityResponse""\n UnpauseActivityExecutionResponse"\xb3\x02\n\x14ResetActivityRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12<\n\texecution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x0c\n\x02id\x18\x04 \x01(\tH\x00\x12\x0e\n\x04type\x18\x05 \x01(\tH\x00\x12\x13\n\tmatch_all\x18\n \x01(\x08H\x00\x12\x17\n\x0freset_heartbeat\x18\x06 \x01(\x08\x12\x13\n\x0bkeep_paused\x18\x07 \x01(\x08\x12)\n\x06jitter\x18\x08 \x01(\x0b\x32\x19.google.protobuf.Duration\x12 \n\x18restore_original_options\x18\t \x01(\x08\x42\n\n\x08\x61\x63tivity"\xf5\x01\n\x1dResetActivityExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12\x13\n\x0b\x61\x63tivity_id\x18\x03 \x01(\t\x12\x0e\n\x06run_id\x18\x04 \x01(\t\x12\x10\n\x08identity\x18\x05 \x01(\t\x12\x13\n\x0bkeep_paused\x18\x06 \x01(\x08\x12)\n\x06jitter\x18\x07 \x01(\x0b\x32\x19.google.protobuf.Duration\x12 \n\x18restore_original_options\x18\x08 \x01(\x08\x12\x13\n\x0bresource_id\x18\t \x01(\t"\x17\n\x15ResetActivityResponse" \n\x1eResetActivityExecutionResponse"\x9c\x02\n%UpdateWorkflowExecutionOptionsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x45\n\x12workflow_execution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12V\n\x1aworkflow_execution_options\x18\x03 \x01(\x0b\x32\x32.temporal.api.workflow.v1.WorkflowExecutionOptions\x12/\n\x0bupdate_mask\x18\x04 \x01(\x0b\x32\x1a.google.protobuf.FieldMask\x12\x10\n\x08identity\x18\x05 \x01(\t"\xb1\x01\n&UpdateWorkflowExecutionOptionsResponse\x12V\n\x1aworkflow_execution_options\x18\x01 \x01(\x0b\x32\x32.temporal.api.workflow.v1.WorkflowExecutionOptions\x12/\n\x0bupdate_time\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.Timestamp"j\n\x19\x44\x65scribeDeploymentRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12:\n\ndeployment\x18\x02 \x01(\x0b\x32&.temporal.api.deployment.v1.Deployment"a\n\x1a\x44\x65scribeDeploymentResponse\x12\x43\n\x0f\x64\x65ployment_info\x18\x01 \x01(\x0b\x32*.temporal.api.deployment.v1.DeploymentInfo"\xc2\x01\n&DescribeWorkerDeploymentVersionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x07version\x18\x02 \x01(\tB\x02\x18\x01\x12O\n\x12\x64\x65ployment_version\x18\x03 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersion\x12\x1f\n\x17report_task_queue_stats\x18\x04 \x01(\x08"\x8c\x05\n\'DescribeWorkerDeploymentVersionResponse\x12_\n\x1eworker_deployment_version_info\x18\x01 \x01(\x0b\x32\x37.temporal.api.deployment.v1.WorkerDeploymentVersionInfo\x12v\n\x13version_task_queues\x18\x02 \x03(\x0b\x32Y.temporal.api.workflowservice.v1.DescribeWorkerDeploymentVersionResponse.VersionTaskQueue\x1a\x87\x03\n\x10VersionTaskQueue\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x32\n\x04type\x18\x02 \x01(\x0e\x32$.temporal.api.enums.v1.TaskQueueType\x12\x38\n\x05stats\x18\x03 \x01(\x0b\x32).temporal.api.taskqueue.v1.TaskQueueStats\x12\x90\x01\n\x15stats_by_priority_key\x18\x04 \x03(\x0b\x32q.temporal.api.workflowservice.v1.DescribeWorkerDeploymentVersionResponse.VersionTaskQueue.StatsByPriorityKeyEntry\x1a\x64\n\x17StatsByPriorityKeyEntry\x12\x0b\n\x03key\x18\x01 \x01(\x05\x12\x38\n\x05value\x18\x02 \x01(\x0b\x32).temporal.api.taskqueue.v1.TaskQueueStats:\x02\x38\x01"M\n\x1f\x44\x65scribeWorkerDeploymentRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x17\n\x0f\x64\x65ployment_name\x18\x02 \x01(\t"\x8c\x01\n DescribeWorkerDeploymentResponse\x12\x16\n\x0e\x63onflict_token\x18\x01 \x01(\x0c\x12P\n\x16worker_deployment_info\x18\x02 \x01(\x0b\x32\x30.temporal.api.deployment.v1.WorkerDeploymentInfo"l\n\x16ListDeploymentsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x11\n\tpage_size\x18\x02 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c\x12\x13\n\x0bseries_name\x18\x04 \x01(\t"w\n\x17ListDeploymentsResponse\x12\x17\n\x0fnext_page_token\x18\x01 \x01(\x0c\x12\x43\n\x0b\x64\x65ployments\x18\x02 \x03(\x0b\x32..temporal.api.deployment.v1.DeploymentListInfo"\xcd\x01\n\x1bSetCurrentDeploymentRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12:\n\ndeployment\x18\x02 \x01(\x0b\x32&.temporal.api.deployment.v1.Deployment\x12\x10\n\x08identity\x18\x03 \x01(\t\x12M\n\x0fupdate_metadata\x18\x04 \x01(\x0b\x32\x34.temporal.api.deployment.v1.UpdateDeploymentMetadata"\xb9\x01\n\x1cSetCurrentDeploymentResponse\x12K\n\x17\x63urrent_deployment_info\x18\x01 \x01(\x0b\x32*.temporal.api.deployment.v1.DeploymentInfo\x12L\n\x18previous_deployment_info\x18\x02 \x01(\x0b\x32*.temporal.api.deployment.v1.DeploymentInfo"\xe5\x01\n(SetWorkerDeploymentCurrentVersionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x17\n\x0f\x64\x65ployment_name\x18\x02 \x01(\t\x12\x13\n\x07version\x18\x03 \x01(\tB\x02\x18\x01\x12\x10\n\x08\x62uild_id\x18\x07 \x01(\t\x12\x16\n\x0e\x63onflict_token\x18\x04 \x01(\x0c\x12\x10\n\x08identity\x18\x05 \x01(\t\x12"\n\x1aignore_missing_task_queues\x18\x06 \x01(\x08\x12\x18\n\x10\x61llow_no_pollers\x18\t \x01(\x08"\xbf\x01\n)SetWorkerDeploymentCurrentVersionResponse\x12\x16\n\x0e\x63onflict_token\x18\x01 \x01(\x0c\x12\x1c\n\x10previous_version\x18\x02 \x01(\tB\x02\x18\x01\x12\\\n\x1bprevious_deployment_version\x18\x03 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersionB\x02\x18\x01"\xf9\x01\n(SetWorkerDeploymentRampingVersionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x17\n\x0f\x64\x65ployment_name\x18\x02 \x01(\t\x12\x13\n\x07version\x18\x03 \x01(\tB\x02\x18\x01\x12\x10\n\x08\x62uild_id\x18\x08 \x01(\t\x12\x12\n\npercentage\x18\x04 \x01(\x02\x12\x16\n\x0e\x63onflict_token\x18\x05 \x01(\x0c\x12\x10\n\x08identity\x18\x06 \x01(\t\x12"\n\x1aignore_missing_task_queues\x18\x07 \x01(\x08\x12\x18\n\x10\x61llow_no_pollers\x18\n \x01(\x08"\xe0\x01\n)SetWorkerDeploymentRampingVersionResponse\x12\x16\n\x0e\x63onflict_token\x18\x01 \x01(\x0c\x12\x1c\n\x10previous_version\x18\x02 \x01(\tB\x02\x18\x01\x12\\\n\x1bprevious_deployment_version\x18\x04 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersionB\x02\x18\x01\x12\x1f\n\x13previous_percentage\x18\x03 \x01(\x02\x42\x02\x18\x01"q\n\x1d\x43reateWorkerDeploymentRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x17\n\x0f\x64\x65ployment_name\x18\x02 \x01(\t\x12\x10\n\x08identity\x18\x04 \x01(\t\x12\x12\n\nrequest_id\x18\x05 \x01(\t"8\n\x1e\x43reateWorkerDeploymentResponse\x12\x16\n\x0e\x63onflict_token\x18\x01 \x01(\x0c"]\n\x1cListWorkerDeploymentsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x11\n\tpage_size\x18\x02 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c"\x9f\x05\n\x1dListWorkerDeploymentsResponse\x12\x17\n\x0fnext_page_token\x18\x01 \x01(\x0c\x12r\n\x12worker_deployments\x18\x02 \x03(\x0b\x32V.temporal.api.workflowservice.v1.ListWorkerDeploymentsResponse.WorkerDeploymentSummary\x1a\xf0\x03\n\x17WorkerDeploymentSummary\x12\x0c\n\x04name\x18\x01 \x01(\t\x12/\n\x0b\x63reate_time\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x41\n\x0erouting_config\x18\x03 \x01(\x0b\x32).temporal.api.deployment.v1.RoutingConfig\x12o\n\x16latest_version_summary\x18\x04 \x01(\x0b\x32O.temporal.api.deployment.v1.WorkerDeploymentInfo.WorkerDeploymentVersionSummary\x12p\n\x17\x63urrent_version_summary\x18\x05 \x01(\x0b\x32O.temporal.api.deployment.v1.WorkerDeploymentInfo.WorkerDeploymentVersionSummary\x12p\n\x17ramping_version_summary\x18\x06 \x01(\x0b\x32O.temporal.api.deployment.v1.WorkerDeploymentInfo.WorkerDeploymentVersionSummary"\xf0\x01\n$CreateWorkerDeploymentVersionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12O\n\x12\x64\x65ployment_version\x18\x02 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersion\x12>\n\x0e\x63ompute_config\x18\x04 \x01(\x0b\x32&.temporal.api.compute.v1.ComputeConfig\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x12\n\nrequest_id\x18\x05 \x01(\t"\'\n%CreateWorkerDeploymentVersionResponse"\xc8\x01\n$DeleteWorkerDeploymentVersionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x07version\x18\x02 \x01(\tB\x02\x18\x01\x12O\n\x12\x64\x65ployment_version\x18\x05 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersion\x12\x15\n\rskip_drainage\x18\x03 \x01(\x08\x12\x10\n\x08identity\x18\x04 \x01(\t"\'\n%DeleteWorkerDeploymentVersionResponse"]\n\x1d\x44\x65leteWorkerDeploymentRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x17\n\x0f\x64\x65ployment_name\x18\x02 \x01(\t\x12\x10\n\x08identity\x18\x03 \x01(\t" \n\x1e\x44\x65leteWorkerDeploymentResponse"\x84\x04\n1UpdateWorkerDeploymentVersionComputeConfigRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12O\n\x12\x64\x65ployment_version\x18\x02 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersion\x12\x99\x01\n\x1d\x63ompute_config_scaling_groups\x18\x06 \x03(\x0b\x32r.temporal.api.workflowservice.v1.UpdateWorkerDeploymentVersionComputeConfigRequest.ComputeConfigScalingGroupsEntry\x12,\n$remove_compute_config_scaling_groups\x18\x07 \x03(\t\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x12\n\nrequest_id\x18\x04 \x01(\t\x1a{\n\x1f\x43omputeConfigScalingGroupsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12G\n\x05value\x18\x02 \x01(\x0b\x32\x38.temporal.api.compute.v1.ComputeConfigScalingGroupUpdate:\x02\x38\x01"4\n2UpdateWorkerDeploymentVersionComputeConfigResponse"\xf4\x03\n3ValidateWorkerDeploymentVersionComputeConfigRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12O\n\x12\x64\x65ployment_version\x18\x02 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersion\x12\x9b\x01\n\x1d\x63ompute_config_scaling_groups\x18\x06 \x03(\x0b\x32t.temporal.api.workflowservice.v1.ValidateWorkerDeploymentVersionComputeConfigRequest.ComputeConfigScalingGroupsEntry\x12,\n$remove_compute_config_scaling_groups\x18\x07 \x03(\t\x12\x10\n\x08identity\x18\x03 \x01(\t\x1a{\n\x1f\x43omputeConfigScalingGroupsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12G\n\x05value\x18\x02 \x01(\x0b\x32\x38.temporal.api.compute.v1.ComputeConfigScalingGroupUpdate:\x02\x38\x01"6\n4ValidateWorkerDeploymentVersionComputeConfigResponse"\xa2\x03\n,UpdateWorkerDeploymentVersionMetadataRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x07version\x18\x02 \x01(\tB\x02\x18\x01\x12O\n\x12\x64\x65ployment_version\x18\x05 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersion\x12x\n\x0eupsert_entries\x18\x03 \x03(\x0b\x32`.temporal.api.workflowservice.v1.UpdateWorkerDeploymentVersionMetadataRequest.UpsertEntriesEntry\x12\x16\n\x0eremove_entries\x18\x04 \x03(\t\x12\x10\n\x08identity\x18\x06 \x01(\t\x1aU\n\x12UpsertEntriesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12.\n\x05value\x18\x02 \x01(\x0b\x32\x1f.temporal.api.common.v1.Payload:\x02\x38\x01"n\n-UpdateWorkerDeploymentVersionMetadataResponse\x12=\n\x08metadata\x18\x01 \x01(\x0b\x32+.temporal.api.deployment.v1.VersionMetadata"\xbd\x01\n!SetWorkerDeploymentManagerRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x17\n\x0f\x64\x65ployment_name\x18\x02 \x01(\t\x12\x1a\n\x10manager_identity\x18\x03 \x01(\tH\x00\x12\x0e\n\x04self\x18\x04 \x01(\x08H\x00\x12\x16\n\x0e\x63onflict_token\x18\x05 \x01(\x0c\x12\x10\n\x08identity\x18\x06 \x01(\tB\x16\n\x14new_manager_identity"c\n"SetWorkerDeploymentManagerResponse\x12\x16\n\x0e\x63onflict_token\x18\x01 \x01(\x0c\x12%\n\x19previous_manager_identity\x18\x02 \x01(\tB\x02\x18\x01"E\n\x1bGetCurrentDeploymentRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bseries_name\x18\x02 \x01(\t"k\n\x1cGetCurrentDeploymentResponse\x12K\n\x17\x63urrent_deployment_info\x18\x01 \x01(\x0b\x32*.temporal.api.deployment.v1.DeploymentInfo"q\n GetDeploymentReachabilityRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12:\n\ndeployment\x18\x02 \x01(\x0b\x32&.temporal.api.deployment.v1.Deployment"\xe3\x01\n!GetDeploymentReachabilityResponse\x12\x43\n\x0f\x64\x65ployment_info\x18\x01 \x01(\x0b\x32*.temporal.api.deployment.v1.DeploymentInfo\x12\x43\n\x0creachability\x18\x02 \x01(\x0e\x32-.temporal.api.enums.v1.DeploymentReachability\x12\x34\n\x10last_update_time\x18\x03 \x01(\x0b\x32\x1a.google.protobuf.Timestamp"\xb4\x01\n\x19\x43reateWorkflowRuleRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x35\n\x04spec\x18\x02 \x01(\x0b\x32\'.temporal.api.rules.v1.WorkflowRuleSpec\x12\x12\n\nforce_scan\x18\x03 \x01(\x08\x12\x12\n\nrequest_id\x18\x04 \x01(\t\x12\x10\n\x08identity\x18\x05 \x01(\t\x12\x13\n\x0b\x64\x65scription\x18\x06 \x01(\t"_\n\x1a\x43reateWorkflowRuleResponse\x12\x31\n\x04rule\x18\x01 \x01(\x0b\x32#.temporal.api.rules.v1.WorkflowRule\x12\x0e\n\x06job_id\x18\x02 \x01(\t"A\n\x1b\x44\x65scribeWorkflowRuleRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x0f\n\x07rule_id\x18\x02 \x01(\t"Q\n\x1c\x44\x65scribeWorkflowRuleResponse\x12\x31\n\x04rule\x18\x01 \x01(\x0b\x32#.temporal.api.rules.v1.WorkflowRule"?\n\x19\x44\x65leteWorkflowRuleRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x0f\n\x07rule_id\x18\x02 \x01(\t"\x1c\n\x1a\x44\x65leteWorkflowRuleResponse"F\n\x18ListWorkflowRulesRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c"h\n\x19ListWorkflowRulesResponse\x12\x32\n\x05rules\x18\x01 \x03(\x0b\x32#.temporal.api.rules.v1.WorkflowRule\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c"\xce\x01\n\x1aTriggerWorkflowRuleRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12<\n\texecution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x0c\n\x02id\x18\x04 \x01(\tH\x00\x12\x37\n\x04spec\x18\x05 \x01(\x0b\x32\'.temporal.api.rules.v1.WorkflowRuleSpecH\x00\x12\x10\n\x08identity\x18\x03 \x01(\tB\x06\n\x04rule".\n\x1bTriggerWorkflowRuleResponse\x12\x0f\n\x07\x61pplied\x18\x01 \x01(\x08"\x9b\x01\n\x1cRecordWorkerHeartbeatRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x10\n\x08identity\x18\x02 \x01(\t\x12\x41\n\x10worker_heartbeat\x18\x03 \x03(\x0b\x32\'.temporal.api.worker.v1.WorkerHeartbeat\x12\x13\n\x0bresource_id\x18\x04 \x01(\t"\x1f\n\x1dRecordWorkerHeartbeatResponse"\x82\x01\n\x12ListWorkersRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x11\n\tpage_size\x18\x02 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c\x12\r\n\x05query\x18\x04 \x01(\t\x12\x1e\n\x16include_system_workers\x18\x05 \x01(\x08"\xa5\x01\n\x13ListWorkersResponse\x12<\n\x0cworkers_info\x18\x01 \x03(\x0b\x32".temporal.api.worker.v1.WorkerInfoB\x02\x18\x01\x12\x37\n\x07workers\x18\x03 \x03(\x0b\x32&.temporal.api.worker.v1.WorkerListInfo\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c"\xd5\x05\n\x1cUpdateTaskQueueConfigRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x10\n\x08identity\x18\x02 \x01(\t\x12\x12\n\ntask_queue\x18\x03 \x01(\t\x12=\n\x0ftask_queue_type\x18\x04 \x01(\x0e\x32$.temporal.api.enums.v1.TaskQueueType\x12n\n\x17update_queue_rate_limit\x18\x05 \x01(\x0b\x32M.temporal.api.workflowservice.v1.UpdateTaskQueueConfigRequest.RateLimitUpdate\x12}\n&update_fairness_key_rate_limit_default\x18\x06 \x01(\x0b\x32M.temporal.api.workflowservice.v1.UpdateTaskQueueConfigRequest.RateLimitUpdate\x12\x84\x01\n\x1dset_fairness_weight_overrides\x18\x07 \x03(\x0b\x32].temporal.api.workflowservice.v1.UpdateTaskQueueConfigRequest.SetFairnessWeightOverridesEntry\x12\'\n\x1funset_fairness_weight_overrides\x18\x08 \x03(\t\x1a[\n\x0fRateLimitUpdate\x12\x38\n\nrate_limit\x18\x01 \x01(\x0b\x32$.temporal.api.taskqueue.v1.RateLimit\x12\x0e\n\x06reason\x18\x02 \x01(\t\x1a\x41\n\x1fSetFairnessWeightOverridesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\x02:\x02\x38\x01"[\n\x1dUpdateTaskQueueConfigResponse\x12:\n\x06\x63onfig\x18\x01 \x01(\x0b\x32*.temporal.api.taskqueue.v1.TaskQueueConfig"\x9e\x01\n\x18\x46\x65tchWorkerConfigRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x10\n\x08identity\x18\x02 \x01(\t\x12\x0e\n\x06reason\x18\x03 \x01(\t\x12\x38\n\x08selector\x18\x06 \x01(\x0b\x32&.temporal.api.common.v1.WorkerSelector\x12\x13\n\x0bresource_id\x18\x07 \x01(\t"U\n\x19\x46\x65tchWorkerConfigResponse\x12\x38\n\rworker_config\x18\x01 \x01(\x0b\x32!.temporal.api.sdk.v1.WorkerConfig"\x8a\x02\n\x19UpdateWorkerConfigRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x10\n\x08identity\x18\x02 \x01(\t\x12\x0e\n\x06reason\x18\x03 \x01(\t\x12\x38\n\rworker_config\x18\x04 \x01(\x0b\x32!.temporal.api.sdk.v1.WorkerConfig\x12/\n\x0bupdate_mask\x18\x05 \x01(\x0b\x32\x1a.google.protobuf.FieldMask\x12\x38\n\x08selector\x18\x06 \x01(\x0b\x32&.temporal.api.common.v1.WorkerSelector\x12\x13\n\x0bresource_id\x18\x07 \x01(\t"d\n\x1aUpdateWorkerConfigResponse\x12:\n\rworker_config\x18\x01 \x01(\x0b\x32!.temporal.api.sdk.v1.WorkerConfigH\x00\x42\n\n\x08response"G\n\x15\x44\x65scribeWorkerRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x1b\n\x13worker_instance_key\x18\x02 \x01(\t"Q\n\x16\x44\x65scribeWorkerResponse\x12\x37\n\x0bworker_info\x18\x01 \x01(\x0b\x32".temporal.api.worker.v1.WorkerInfo"W\n\x13\x43ountWorkersRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\r\n\x05query\x18\x02 \x01(\t\x12\x1e\n\x16include_system_workers\x18\x03 \x01(\x08"%\n\x14\x43ountWorkersResponse\x12\r\n\x05\x63ount\x18\x01 \x01(\x03"\x8d\x01\n\x1dPauseWorkflowExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x12\x10\n\x08identity\x18\x04 \x01(\t\x12\x0e\n\x06reason\x18\x05 \x01(\t\x12\x12\n\nrequest_id\x18\x06 \x01(\t" \n\x1ePauseWorkflowExecutionResponse"\x8f\x01\n\x1fUnpauseWorkflowExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x12\x10\n\x08identity\x18\x04 \x01(\t\x12\x0e\n\x06reason\x18\x05 \x01(\t\x12\x12\n\nrequest_id\x18\x06 \x01(\t""\n UnpauseWorkflowExecutionResponse"\x99\t\n\x1dStartActivityExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x10\n\x08identity\x18\x02 \x01(\t\x12\x12\n\nrequest_id\x18\x03 \x01(\t\x12\x13\n\x0b\x61\x63tivity_id\x18\x04 \x01(\t\x12;\n\ractivity_type\x18\x05 \x01(\x0b\x32$.temporal.api.common.v1.ActivityType\x12\x38\n\ntask_queue\x18\x06 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12<\n\x19schedule_to_close_timeout\x18\x07 \x01(\x0b\x32\x19.google.protobuf.Duration\x12<\n\x19schedule_to_start_timeout\x18\x08 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x39\n\x16start_to_close_timeout\x18\t \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x34\n\x11heartbeat_timeout\x18\n \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x39\n\x0cretry_policy\x18\x0b \x01(\x0b\x32#.temporal.api.common.v1.RetryPolicy\x12/\n\x05input\x18\x0c \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x45\n\x0fid_reuse_policy\x18\r \x01(\x0e\x32,.temporal.api.enums.v1.ActivityIdReusePolicy\x12K\n\x12id_conflict_policy\x18\x0e \x01(\x0e\x32/.temporal.api.enums.v1.ActivityIdConflictPolicy\x12\x43\n\x11search_attributes\x18\x0f \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes\x12.\n\x06header\x18\x10 \x01(\x0b\x32\x1e.temporal.api.common.v1.Header\x12\x38\n\ruser_metadata\x18\x11 \x01(\x0b\x32!.temporal.api.sdk.v1.UserMetadata\x12\x32\n\x08priority\x18\x12 \x01(\x0b\x32 .temporal.api.common.v1.Priority\x12>\n\x14\x63ompletion_callbacks\x18\x13 \x03(\x0b\x32 .temporal.api.common.v1.Callback\x12+\n\x05links\x18\x14 \x03(\x0b\x32\x1c.temporal.api.common.v1.Link\x12\x46\n\x13on_conflict_options\x18\x15 \x01(\x0b\x32).temporal.api.common.v1.OnConflictOptions\x12.\n\x0bstart_delay\x18\x16 \x01(\x0b\x32\x19.google.protobuf.Duration"m\n\x1eStartActivityExecutionResponse\x12\x0e\n\x06run_id\x18\x01 \x01(\t\x12\x0f\n\x07started\x18\x02 \x01(\x08\x12*\n\x04link\x18\x03 \x01(\x0b\x32\x1c.temporal.api.common.v1.Link"\xe4\x01\n DescribeActivityExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0b\x61\x63tivity_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x12\x15\n\rinclude_input\x18\x04 \x01(\x08\x12\x17\n\x0finclude_outcome\x18\x05 \x01(\x08\x12\x17\n\x0flong_poll_token\x18\x06 \x01(\x0c\x12!\n\x19include_heartbeat_details\x18\x07 \x01(\x08\x12\x1c\n\x14include_last_failure\x18\x08 \x01(\x08"\xbc\x02\n!DescribeActivityExecutionResponse\x12\x0e\n\x06run_id\x18\x01 \x01(\t\x12=\n\x04info\x18\x02 \x01(\x0b\x32/.temporal.api.activity.v1.ActivityExecutionInfo\x12/\n\x05input\x18\x03 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x43\n\x07outcome\x18\x04 \x01(\x0b\x32\x32.temporal.api.activity.v1.ActivityExecutionOutcome\x12\x17\n\x0flong_poll_token\x18\x05 \x01(\x0c\x12\x39\n\tcallbacks\x18\x06 \x03(\x0b\x32&.temporal.api.activity.v1.CallbackInfo"V\n\x1cPollActivityExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0b\x61\x63tivity_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t"t\n\x1dPollActivityExecutionResponse\x12\x0e\n\x06run_id\x18\x01 \x01(\t\x12\x43\n\x07outcome\x18\x02 \x01(\x0b\x32\x32.temporal.api.activity.v1.ActivityExecutionOutcome"m\n\x1dListActivityExecutionsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x11\n\tpage_size\x18\x02 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c\x12\r\n\x05query\x18\x04 \x01(\t"\x82\x01\n\x1eListActivityExecutionsResponse\x12G\n\nexecutions\x18\x01 \x03(\x0b\x32\x33.temporal.api.activity.v1.ActivityExecutionListInfo\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c"\xd1\x06\n#StartNexusOperationExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x10\n\x08identity\x18\x02 \x01(\t\x12\x12\n\nrequest_id\x18\x03 \x01(\t\x12\x14\n\x0coperation_id\x18\x04 \x01(\t\x12\x10\n\x08\x65ndpoint\x18\x05 \x01(\t\x12\x0f\n\x07service\x18\x06 \x01(\t\x12\x11\n\toperation\x18\x07 \x01(\t\x12<\n\x19schedule_to_close_timeout\x18\x08 \x01(\x0b\x32\x19.google.protobuf.Duration\x12<\n\x19schedule_to_start_timeout\x18\t \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x39\n\x16start_to_close_timeout\x18\n \x01(\x0b\x32\x19.google.protobuf.Duration\x12.\n\x05input\x18\x0b \x01(\x0b\x32\x1f.temporal.api.common.v1.Payload\x12K\n\x0fid_reuse_policy\x18\x0c \x01(\x0e\x32\x32.temporal.api.enums.v1.NexusOperationIdReusePolicy\x12Q\n\x12id_conflict_policy\x18\r \x01(\x0e\x32\x35.temporal.api.enums.v1.NexusOperationIdConflictPolicy\x12\x43\n\x11search_attributes\x18\x0e \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes\x12k\n\x0cnexus_header\x18\x0f \x03(\x0b\x32U.temporal.api.workflowservice.v1.StartNexusOperationExecutionRequest.NexusHeaderEntry\x12\x38\n\ruser_metadata\x18\x10 \x01(\x0b\x32!.temporal.api.sdk.v1.UserMetadata\x1a\x32\n\x10NexusHeaderEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01"G\n$StartNexusOperationExecutionResponse\x12\x0e\n\x06run_id\x18\x01 \x01(\t\x12\x0f\n\x07started\x18\x02 \x01(\x08"\xaa\x01\n&DescribeNexusOperationExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x14\n\x0coperation_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x12\x15\n\rinclude_input\x18\x04 \x01(\x08\x12\x17\n\x0finclude_outcome\x18\x05 \x01(\x08\x12\x17\n\x0flong_poll_token\x18\x06 \x01(\x0c"\xb7\x02\n\'DescribeNexusOperationExecutionResponse\x12\x0e\n\x06run_id\x18\x01 \x01(\t\x12@\n\x04info\x18\x02 \x01(\x0b\x32\x32.temporal.api.nexus.v1.NexusOperationExecutionInfo\x12.\n\x05input\x18\x03 \x01(\x0b\x32\x1f.temporal.api.common.v1.Payload\x12\x31\n\x06result\x18\x04 \x01(\x0b\x32\x1f.temporal.api.common.v1.PayloadH\x00\x12\x33\n\x07\x66\x61ilure\x18\x05 \x01(\x0b\x32 .temporal.api.failure.v1.FailureH\x00\x12\x17\n\x0flong_poll_token\x18\x06 \x01(\x0c\x42\t\n\x07outcome"\xa1\x01\n"PollNexusOperationExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x14\n\x0coperation_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x12\x42\n\nwait_stage\x18\x04 \x01(\x0e\x32..temporal.api.enums.v1.NexusOperationWaitStage"\x85\x02\n#PollNexusOperationExecutionResponse\x12\x0e\n\x06run_id\x18\x01 \x01(\t\x12\x42\n\nwait_stage\x18\x02 \x01(\x0e\x32..temporal.api.enums.v1.NexusOperationWaitStage\x12\x17\n\x0foperation_token\x18\x03 \x01(\t\x12\x31\n\x06result\x18\x04 \x01(\x0b\x32\x1f.temporal.api.common.v1.PayloadH\x00\x12\x33\n\x07\x66\x61ilure\x18\x05 \x01(\x0b\x32 .temporal.api.failure.v1.FailureH\x00\x42\t\n\x07outcome"s\n#ListNexusOperationExecutionsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x11\n\tpage_size\x18\x02 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c\x12\r\n\x05query\x18\x04 \x01(\t"\x8b\x01\n$ListNexusOperationExecutionsResponse\x12J\n\noperations\x18\x01 \x03(\x0b\x32\x36.temporal.api.nexus.v1.NexusOperationExecutionListInfo\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c"B\n\x1e\x43ountActivityExecutionsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\r\n\x05query\x18\x02 \x01(\t"\xed\x01\n\x1f\x43ountActivityExecutionsResponse\x12\r\n\x05\x63ount\x18\x01 \x01(\x03\x12\x61\n\x06groups\x18\x02 \x03(\x0b\x32Q.temporal.api.workflowservice.v1.CountActivityExecutionsResponse.AggregationGroup\x1aX\n\x10\x41ggregationGroup\x12\x35\n\x0cgroup_values\x18\x01 \x03(\x0b\x32\x1f.temporal.api.common.v1.Payload\x12\r\n\x05\x63ount\x18\x02 \x01(\x03"H\n$CountNexusOperationExecutionsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\r\n\x05query\x18\x02 \x01(\t"\xf9\x01\n%CountNexusOperationExecutionsResponse\x12\r\n\x05\x63ount\x18\x01 \x01(\x03\x12g\n\x06groups\x18\x02 \x03(\x0b\x32W.temporal.api.workflowservice.v1.CountNexusOperationExecutionsResponse.AggregationGroup\x1aX\n\x10\x41ggregationGroup\x12\x35\n\x0cgroup_values\x18\x01 \x03(\x0b\x32\x1f.temporal.api.common.v1.Payload\x12\r\n\x05\x63ount\x18\x02 \x01(\x03"\x95\x01\n%RequestCancelActivityExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0b\x61\x63tivity_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x12\x10\n\x08identity\x18\x04 \x01(\t\x12\x12\n\nrequest_id\x18\x05 \x01(\t\x12\x0e\n\x06reason\x18\x06 \x01(\t"(\n&RequestCancelActivityExecutionResponse"\x91\x01\n!TerminateActivityExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0b\x61\x63tivity_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x12\x10\n\x08identity\x18\x04 \x01(\t\x12\x12\n\nrequest_id\x18\x05 \x01(\t\x12\x0e\n\x06reason\x18\x06 \x01(\t"$\n"TerminateActivityExecutionResponse"X\n\x1e\x44\x65leteActivityExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0b\x61\x63tivity_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t"!\n\x1f\x44\x65leteActivityExecutionResponse"\x9c\x01\n+RequestCancelNexusOperationExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x14\n\x0coperation_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x12\x10\n\x08identity\x18\x04 \x01(\t\x12\x12\n\nrequest_id\x18\x05 \x01(\t\x12\x0e\n\x06reason\x18\x06 \x01(\t".\n,RequestCancelNexusOperationExecutionResponse"\x98\x01\n\'TerminateNexusOperationExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x14\n\x0coperation_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x12\x10\n\x08identity\x18\x04 \x01(\t\x12\x12\n\nrequest_id\x18\x05 \x01(\t\x12\x0e\n\x06reason\x18\x06 \x01(\t"*\n(TerminateNexusOperationExecutionResponse"_\n$DeleteNexusOperationExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x14\n\x0coperation_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t"\'\n%DeleteNexusOperationExecutionResponseB\xbe\x01\n"io.temporal.api.workflowservice.v1B\x14RequestResponseProtoP\x01Z5go.temporal.io/api/workflowservice/v1;workflowservice\xaa\x02!Temporalio.Api.WorkflowService.V1\xea\x02$Temporalio::Api::WorkflowService::V1b\x06proto3' ) @@ -3949,6 +3949,10 @@ DESCRIPTOR._serialized_options = b'\n"io.temporal.api.workflowservice.v1B\024RequestResponseProtoP\001Z5go.temporal.io/api/workflowservice/v1;workflowservice\252\002!Temporalio.Api.WorkflowService.V1\352\002$Temporalio::Api::WorkflowService::V1' _REGISTERNAMESPACEREQUEST_DATAENTRY._options = None _REGISTERNAMESPACEREQUEST_DATAENTRY._serialized_options = b"8\001" + _DESCRIBENAMESPACERESPONSE.fields_by_name["poller_group_infos"]._options = None + _DESCRIBENAMESPACERESPONSE.fields_by_name[ + "poller_group_infos" + ]._serialized_options = b"\030\001" _POLLWORKFLOWTASKQUEUEREQUEST.fields_by_name["binary_checksum"]._options = None _POLLWORKFLOWTASKQUEUEREQUEST.fields_by_name[ "binary_checksum" @@ -3961,6 +3965,10 @@ ]._serialized_options = b"\030\001" _POLLWORKFLOWTASKQUEUERESPONSE_QUERIESENTRY._options = None _POLLWORKFLOWTASKQUEUERESPONSE_QUERIESENTRY._serialized_options = b"8\001" + _POLLWORKFLOWTASKQUEUERESPONSE.fields_by_name["poller_group_infos"]._options = None + _POLLWORKFLOWTASKQUEUERESPONSE.fields_by_name[ + "poller_group_infos" + ]._serialized_options = b"\030\001" _RESPONDWORKFLOWTASKCOMPLETEDREQUEST_QUERYRESULTSENTRY._options = None _RESPONDWORKFLOWTASKCOMPLETEDREQUEST_QUERYRESULTSENTRY._serialized_options = ( b"8\001" @@ -3999,6 +4007,10 @@ _POLLACTIVITYTASKQUEUEREQUEST.fields_by_name[ "worker_version_capabilities" ]._serialized_options = b"\030\001" + _POLLACTIVITYTASKQUEUERESPONSE.fields_by_name["poller_group_infos"]._options = None + _POLLACTIVITYTASKQUEUERESPONSE.fields_by_name[ + "poller_group_infos" + ]._serialized_options = b"\030\001" _RESPONDACTIVITYTASKCOMPLETEDREQUEST.fields_by_name[ "worker_version" ]._options = None @@ -4079,12 +4091,20 @@ ]._serialized_options = b"\030\001" _GETCLUSTERINFORESPONSE_SUPPORTEDCLIENTSENTRY._options = None _GETCLUSTERINFORESPONSE_SUPPORTEDCLIENTSENTRY._serialized_options = b"8\001" + _STARTBATCHOPERATIONREQUEST.fields_by_name["executions"]._options = None + _STARTBATCHOPERATIONREQUEST.fields_by_name[ + "executions" + ]._serialized_options = b"\030\001" _POLLNEXUSTASKQUEUEREQUEST.fields_by_name[ "worker_version_capabilities" ]._options = None _POLLNEXUSTASKQUEUEREQUEST.fields_by_name[ "worker_version_capabilities" ]._serialized_options = b"\030\001" + _POLLNEXUSTASKQUEUERESPONSE.fields_by_name["poller_group_infos"]._options = None + _POLLNEXUSTASKQUEUERESPONSE.fields_by_name[ + "poller_group_infos" + ]._serialized_options = b"\030\001" _RESPONDNEXUSTASKFAILEDREQUEST.fields_by_name["error"]._options = None _RESPONDNEXUSTASKFAILEDREQUEST.fields_by_name[ "error" @@ -4176,561 +4196,561 @@ _DESCRIBENAMESPACEREQUEST._serialized_start = 2554 _DESCRIBENAMESPACEREQUEST._serialized_end = 2637 _DESCRIBENAMESPACERESPONSE._serialized_start = 2640 - _DESCRIBENAMESPACERESPONSE._serialized_end = 3076 - _UPDATENAMESPACEREQUEST._serialized_start = 3079 - _UPDATENAMESPACEREQUEST._serialized_end = 3414 - _UPDATENAMESPACERESPONSE._serialized_start = 3417 - _UPDATENAMESPACERESPONSE._serialized_end = 3708 - _DEPRECATENAMESPACEREQUEST._serialized_start = 3710 - _DEPRECATENAMESPACEREQUEST._serialized_end = 3780 - _DEPRECATENAMESPACERESPONSE._serialized_start = 3782 - _DEPRECATENAMESPACERESPONSE._serialized_end = 3810 - _STARTWORKFLOWEXECUTIONREQUEST._serialized_start = 3813 - _STARTWORKFLOWEXECUTIONREQUEST._serialized_end = 5430 - _STARTWORKFLOWEXECUTIONRESPONSE._serialized_start = 5433 - _STARTWORKFLOWEXECUTIONRESPONSE._serialized_end = 5699 - _GETWORKFLOWEXECUTIONHISTORYREQUEST._serialized_start = 5702 - _GETWORKFLOWEXECUTIONHISTORYREQUEST._serialized_end = 6000 - _GETWORKFLOWEXECUTIONHISTORYRESPONSE._serialized_start = 6003 - _GETWORKFLOWEXECUTIONHISTORYRESPONSE._serialized_end = 6189 - _GETWORKFLOWEXECUTIONHISTORYREVERSEREQUEST._serialized_start = 6192 - _GETWORKFLOWEXECUTIONHISTORYREVERSEREQUEST._serialized_end = 6368 - _GETWORKFLOWEXECUTIONHISTORYREVERSERESPONSE._serialized_start = 6370 - _GETWORKFLOWEXECUTIONHISTORYREVERSERESPONSE._serialized_end = 6490 - _POLLWORKFLOWTASKQUEUEREQUEST._serialized_start = 6493 - _POLLWORKFLOWTASKQUEUEREQUEST._serialized_end = 6933 - _POLLWORKFLOWTASKQUEUERESPONSE._serialized_start = 6936 - _POLLWORKFLOWTASKQUEUERESPONSE._serialized_end = 7946 - _POLLWORKFLOWTASKQUEUERESPONSE_QUERIESENTRY._serialized_start = 7862 - _POLLWORKFLOWTASKQUEUERESPONSE_QUERIESENTRY._serialized_end = 7946 - _RESPONDWORKFLOWTASKCOMPLETEDREQUEST._serialized_start = 7949 - _RESPONDWORKFLOWTASKCOMPLETEDREQUEST._serialized_end = 9239 - _RESPONDWORKFLOWTASKCOMPLETEDREQUEST_QUERYRESULTSENTRY._serialized_start = 9073 - _RESPONDWORKFLOWTASKCOMPLETEDREQUEST_QUERYRESULTSENTRY._serialized_end = 9168 - _RESPONDWORKFLOWTASKCOMPLETEDREQUEST_CAPABILITIES._serialized_start = 9170 - _RESPONDWORKFLOWTASKCOMPLETEDREQUEST_CAPABILITIES._serialized_end = 9239 - _RESPONDWORKFLOWTASKCOMPLETEDRESPONSE._serialized_start = 9242 - _RESPONDWORKFLOWTASKCOMPLETEDRESPONSE._serialized_end = 9487 - _RESPONDWORKFLOWTASKFAILEDREQUEST._serialized_start = 9490 - _RESPONDWORKFLOWTASKFAILEDREQUEST._serialized_end = 10015 - _RESPONDWORKFLOWTASKFAILEDRESPONSE._serialized_start = 10017 - _RESPONDWORKFLOWTASKFAILEDRESPONSE._serialized_end = 10052 - _POLLACTIVITYTASKQUEUEREQUEST._serialized_start = 10055 - _POLLACTIVITYTASKQUEUEREQUEST._serialized_end = 10541 - _POLLACTIVITYTASKQUEUERESPONSE._serialized_start = 10544 - _POLLACTIVITYTASKQUEUERESPONSE._serialized_end = 11648 - _RECORDACTIVITYTASKHEARTBEATREQUEST._serialized_start = 11651 - _RECORDACTIVITYTASKHEARTBEATREQUEST._serialized_end = 11816 - _RECORDACTIVITYTASKHEARTBEATRESPONSE._serialized_start = 11818 - _RECORDACTIVITYTASKHEARTBEATRESPONSE._serialized_end = 11930 - _RECORDACTIVITYTASKHEARTBEATBYIDREQUEST._serialized_start = 11933 - _RECORDACTIVITYTASKHEARTBEATBYIDREQUEST._serialized_end = 12140 - _RECORDACTIVITYTASKHEARTBEATBYIDRESPONSE._serialized_start = 12142 - _RECORDACTIVITYTASKHEARTBEATBYIDRESPONSE._serialized_end = 12258 - _RESPONDACTIVITYTASKCOMPLETEDREQUEST._serialized_start = 12261 - _RESPONDACTIVITYTASKCOMPLETEDREQUEST._serialized_end = 12643 - _RESPONDACTIVITYTASKCOMPLETEDRESPONSE._serialized_start = 12645 - _RESPONDACTIVITYTASKCOMPLETEDRESPONSE._serialized_end = 12683 - _RESPONDACTIVITYTASKCOMPLETEDBYIDREQUEST._serialized_start = 12686 - _RESPONDACTIVITYTASKCOMPLETEDBYIDREQUEST._serialized_end = 12893 - _RESPONDACTIVITYTASKCOMPLETEDBYIDRESPONSE._serialized_start = 12895 - _RESPONDACTIVITYTASKCOMPLETEDBYIDRESPONSE._serialized_end = 12937 - _RESPONDACTIVITYTASKFAILEDREQUEST._serialized_start = 12940 - _RESPONDACTIVITYTASKFAILEDREQUEST._serialized_end = 13386 - _RESPONDACTIVITYTASKFAILEDRESPONSE._serialized_start = 13388 - _RESPONDACTIVITYTASKFAILEDRESPONSE._serialized_end = 13475 - _RESPONDACTIVITYTASKFAILEDBYIDREQUEST._serialized_start = 13478 - _RESPONDACTIVITYTASKFAILEDBYIDREQUEST._serialized_end = 13749 - _RESPONDACTIVITYTASKFAILEDBYIDRESPONSE._serialized_start = 13751 - _RESPONDACTIVITYTASKFAILEDBYIDRESPONSE._serialized_end = 13842 - _RESPONDACTIVITYTASKCANCELEDREQUEST._serialized_start = 13845 - _RESPONDACTIVITYTASKCANCELEDREQUEST._serialized_end = 14227 - _RESPONDACTIVITYTASKCANCELEDRESPONSE._serialized_start = 14229 - _RESPONDACTIVITYTASKCANCELEDRESPONSE._serialized_end = 14266 - _RESPONDACTIVITYTASKCANCELEDBYIDREQUEST._serialized_start = 14269 - _RESPONDACTIVITYTASKCANCELEDBYIDREQUEST._serialized_end = 14557 - _RESPONDACTIVITYTASKCANCELEDBYIDRESPONSE._serialized_start = 14559 - _RESPONDACTIVITYTASKCANCELEDBYIDRESPONSE._serialized_end = 14600 - _REQUESTCANCELWORKFLOWEXECUTIONREQUEST._serialized_start = 14603 - _REQUESTCANCELWORKFLOWEXECUTIONREQUEST._serialized_end = 14863 - _REQUESTCANCELWORKFLOWEXECUTIONRESPONSE._serialized_start = 14865 - _REQUESTCANCELWORKFLOWEXECUTIONRESPONSE._serialized_end = 14905 - _SIGNALWORKFLOWEXECUTIONREQUEST._serialized_start = 14908 - _SIGNALWORKFLOWEXECUTIONREQUEST._serialized_end = 15258 - _SIGNALWORKFLOWEXECUTIONRESPONSE._serialized_start = 15260 - _SIGNALWORKFLOWEXECUTIONRESPONSE._serialized_end = 15337 - _SIGNALWITHSTARTWORKFLOWEXECUTIONREQUEST._serialized_start = 15340 - _SIGNALWITHSTARTWORKFLOWEXECUTIONREQUEST._serialized_end = 16679 - _SIGNALWITHSTARTWORKFLOWEXECUTIONRESPONSE._serialized_start = 16681 - _SIGNALWITHSTARTWORKFLOWEXECUTIONRESPONSE._serialized_end = 16807 - _RESETWORKFLOWEXECUTIONREQUEST._serialized_start = 16810 - _RESETWORKFLOWEXECUTIONREQUEST._serialized_end = 17259 - _RESETWORKFLOWEXECUTIONRESPONSE._serialized_start = 17261 - _RESETWORKFLOWEXECUTIONRESPONSE._serialized_end = 17309 - _TERMINATEWORKFLOWEXECUTIONREQUEST._serialized_start = 17312 - _TERMINATEWORKFLOWEXECUTIONREQUEST._serialized_end = 17599 - _TERMINATEWORKFLOWEXECUTIONRESPONSE._serialized_start = 17601 - _TERMINATEWORKFLOWEXECUTIONRESPONSE._serialized_end = 17637 - _DELETEWORKFLOWEXECUTIONREQUEST._serialized_start = 17639 - _DELETEWORKFLOWEXECUTIONREQUEST._serialized_end = 17761 - _DELETEWORKFLOWEXECUTIONRESPONSE._serialized_start = 17763 - _DELETEWORKFLOWEXECUTIONRESPONSE._serialized_end = 17796 - _LISTOPENWORKFLOWEXECUTIONSREQUEST._serialized_start = 17799 - _LISTOPENWORKFLOWEXECUTIONSREQUEST._serialized_end = 18128 - _LISTOPENWORKFLOWEXECUTIONSRESPONSE._serialized_start = 18131 - _LISTOPENWORKFLOWEXECUTIONSRESPONSE._serialized_end = 18261 - _LISTCLOSEDWORKFLOWEXECUTIONSREQUEST._serialized_start = 18264 - _LISTCLOSEDWORKFLOWEXECUTIONSREQUEST._serialized_end = 18658 - _LISTCLOSEDWORKFLOWEXECUTIONSRESPONSE._serialized_start = 18661 - _LISTCLOSEDWORKFLOWEXECUTIONSRESPONSE._serialized_end = 18793 - _LISTWORKFLOWEXECUTIONSREQUEST._serialized_start = 18795 - _LISTWORKFLOWEXECUTIONSREQUEST._serialized_end = 18904 - _LISTWORKFLOWEXECUTIONSRESPONSE._serialized_start = 18906 - _LISTWORKFLOWEXECUTIONSRESPONSE._serialized_end = 19032 - _LISTARCHIVEDWORKFLOWEXECUTIONSREQUEST._serialized_start = 19034 - _LISTARCHIVEDWORKFLOWEXECUTIONSREQUEST._serialized_end = 19151 - _LISTARCHIVEDWORKFLOWEXECUTIONSRESPONSE._serialized_start = 19154 - _LISTARCHIVEDWORKFLOWEXECUTIONSRESPONSE._serialized_end = 19288 - _SCANWORKFLOWEXECUTIONSREQUEST._serialized_start = 19290 - _SCANWORKFLOWEXECUTIONSREQUEST._serialized_end = 19399 - _SCANWORKFLOWEXECUTIONSRESPONSE._serialized_start = 19401 - _SCANWORKFLOWEXECUTIONSRESPONSE._serialized_end = 19527 - _COUNTWORKFLOWEXECUTIONSREQUEST._serialized_start = 19529 - _COUNTWORKFLOWEXECUTIONSREQUEST._serialized_end = 19595 - _COUNTWORKFLOWEXECUTIONSRESPONSE._serialized_start = 19598 - _COUNTWORKFLOWEXECUTIONSRESPONSE._serialized_end = 19835 - _COUNTWORKFLOWEXECUTIONSRESPONSE_AGGREGATIONGROUP._serialized_start = 19747 - _COUNTWORKFLOWEXECUTIONSRESPONSE_AGGREGATIONGROUP._serialized_end = 19835 - _GETSEARCHATTRIBUTESREQUEST._serialized_start = 19837 - _GETSEARCHATTRIBUTESREQUEST._serialized_end = 19865 - _GETSEARCHATTRIBUTESRESPONSE._serialized_start = 19868 - _GETSEARCHATTRIBUTESRESPONSE._serialized_end = 20069 - _GETSEARCHATTRIBUTESRESPONSE_KEYSENTRY._serialized_start = 19985 - _GETSEARCHATTRIBUTESRESPONSE_KEYSENTRY._serialized_end = 20069 - _RESPONDQUERYTASKCOMPLETEDREQUEST._serialized_start = 20072 - _RESPONDQUERYTASKCOMPLETEDREQUEST._serialized_end = 20433 - _RESPONDQUERYTASKCOMPLETEDRESPONSE._serialized_start = 20435 - _RESPONDQUERYTASKCOMPLETEDRESPONSE._serialized_end = 20470 - _RESETSTICKYTASKQUEUEREQUEST._serialized_start = 20472 - _RESETSTICKYTASKQUEUEREQUEST._serialized_end = 20582 - _RESETSTICKYTASKQUEUERESPONSE._serialized_start = 20584 - _RESETSTICKYTASKQUEUERESPONSE._serialized_end = 20614 - _SHUTDOWNWORKERREQUEST._serialized_start = 20617 - _SHUTDOWNWORKERREQUEST._serialized_end = 20900 - _SHUTDOWNWORKERRESPONSE._serialized_start = 20902 - _SHUTDOWNWORKERRESPONSE._serialized_end = 20926 - _QUERYWORKFLOWREQUEST._serialized_start = 20929 - _QUERYWORKFLOWREQUEST._serialized_end = 21162 - _QUERYWORKFLOWRESPONSE._serialized_start = 21165 - _QUERYWORKFLOWRESPONSE._serialized_end = 21306 - _DESCRIBEWORKFLOWEXECUTIONREQUEST._serialized_start = 21308 - _DESCRIBEWORKFLOWEXECUTIONREQUEST._serialized_end = 21423 - _DESCRIBEWORKFLOWEXECUTIONRESPONSE._serialized_start = 21426 - _DESCRIBEWORKFLOWEXECUTIONRESPONSE._serialized_end = 22091 - _DESCRIBETASKQUEUEREQUEST._serialized_start = 22094 - _DESCRIBETASKQUEUEREQUEST._serialized_end = 22622 - _DESCRIBETASKQUEUERESPONSE._serialized_start = 22625 - _DESCRIBETASKQUEUERESPONSE._serialized_end = 23629 - _DESCRIBETASKQUEUERESPONSE_STATSBYPRIORITYKEYENTRY._serialized_start = 23309 - _DESCRIBETASKQUEUERESPONSE_STATSBYPRIORITYKEYENTRY._serialized_end = 23409 - _DESCRIBETASKQUEUERESPONSE_EFFECTIVERATELIMIT._serialized_start = 23411 - _DESCRIBETASKQUEUERESPONSE_EFFECTIVERATELIMIT._serialized_end = 23527 - _DESCRIBETASKQUEUERESPONSE_VERSIONSINFOENTRY._serialized_start = 23529 - _DESCRIBETASKQUEUERESPONSE_VERSIONSINFOENTRY._serialized_end = 23629 - _GETCLUSTERINFOREQUEST._serialized_start = 23631 - _GETCLUSTERINFOREQUEST._serialized_end = 23654 - _GETCLUSTERINFORESPONSE._serialized_start = 23657 - _GETCLUSTERINFORESPONSE._serialized_end = 24122 - _GETCLUSTERINFORESPONSE_SUPPORTEDCLIENTSENTRY._serialized_start = 24067 - _GETCLUSTERINFORESPONSE_SUPPORTEDCLIENTSENTRY._serialized_end = 24122 - _GETSYSTEMINFOREQUEST._serialized_start = 24124 - _GETSYSTEMINFOREQUEST._serialized_end = 24146 - _GETSYSTEMINFORESPONSE._serialized_start = 24149 - _GETSYSTEMINFORESPONSE._serialized_end = 24684 - _GETSYSTEMINFORESPONSE_CAPABILITIES._serialized_start = 24290 - _GETSYSTEMINFORESPONSE_CAPABILITIES._serialized_end = 24684 - _LISTTASKQUEUEPARTITIONSREQUEST._serialized_start = 24686 - _LISTTASKQUEUEPARTITIONSREQUEST._serialized_end = 24795 - _LISTTASKQUEUEPARTITIONSRESPONSE._serialized_start = 24798 - _LISTTASKQUEUEPARTITIONSRESPONSE._serialized_end = 25021 - _CREATESCHEDULEREQUEST._serialized_start = 25024 - _CREATESCHEDULEREQUEST._serialized_end = 25356 - _CREATESCHEDULERESPONSE._serialized_start = 25358 - _CREATESCHEDULERESPONSE._serialized_end = 25406 - _DESCRIBESCHEDULEREQUEST._serialized_start = 25408 - _DESCRIBESCHEDULEREQUEST._serialized_end = 25473 - _DESCRIBESCHEDULERESPONSE._serialized_start = 25476 - _DESCRIBESCHEDULERESPONSE._serialized_end = 25747 - _UPDATESCHEDULEREQUEST._serialized_start = 25750 - _UPDATESCHEDULEREQUEST._serialized_end = 26042 - _UPDATESCHEDULERESPONSE._serialized_start = 26044 - _UPDATESCHEDULERESPONSE._serialized_end = 26068 - _PATCHSCHEDULEREQUEST._serialized_start = 26071 - _PATCHSCHEDULEREQUEST._serialized_end = 26227 - _PATCHSCHEDULERESPONSE._serialized_start = 26229 - _PATCHSCHEDULERESPONSE._serialized_end = 26252 - _LISTSCHEDULEMATCHINGTIMESREQUEST._serialized_start = 26255 - _LISTSCHEDULEMATCHINGTIMESREQUEST._serialized_end = 26423 - _LISTSCHEDULEMATCHINGTIMESRESPONSE._serialized_start = 26425 - _LISTSCHEDULEMATCHINGTIMESRESPONSE._serialized_end = 26508 - _DELETESCHEDULEREQUEST._serialized_start = 26510 - _DELETESCHEDULEREQUEST._serialized_end = 26591 - _DELETESCHEDULERESPONSE._serialized_start = 26593 - _DELETESCHEDULERESPONSE._serialized_end = 26617 - _LISTSCHEDULESREQUEST._serialized_start = 26619 - _LISTSCHEDULESREQUEST._serialized_end = 26727 - _LISTSCHEDULESRESPONSE._serialized_start = 26729 - _LISTSCHEDULESRESPONSE._serialized_end = 26841 - _COUNTSCHEDULESREQUEST._serialized_start = 26843 - _COUNTSCHEDULESREQUEST._serialized_end = 26900 - _COUNTSCHEDULESRESPONSE._serialized_start = 26903 - _COUNTSCHEDULESRESPONSE._serialized_end = 27122 - _COUNTSCHEDULESRESPONSE_AGGREGATIONGROUP._serialized_start = 19747 - _COUNTSCHEDULESRESPONSE_AGGREGATIONGROUP._serialized_end = 19835 - _UPDATEWORKERBUILDIDCOMPATIBILITYREQUEST._serialized_start = 27125 - _UPDATEWORKERBUILDIDCOMPATIBILITYREQUEST._serialized_end = 27771 - _UPDATEWORKERBUILDIDCOMPATIBILITYREQUEST_ADDNEWCOMPATIBLEVERSION._serialized_start = 27572 + _DESCRIBENAMESPACERESPONSE._serialized_end = 3153 + _UPDATENAMESPACEREQUEST._serialized_start = 3156 + _UPDATENAMESPACEREQUEST._serialized_end = 3491 + _UPDATENAMESPACERESPONSE._serialized_start = 3494 + _UPDATENAMESPACERESPONSE._serialized_end = 3785 + _DEPRECATENAMESPACEREQUEST._serialized_start = 3787 + _DEPRECATENAMESPACEREQUEST._serialized_end = 3857 + _DEPRECATENAMESPACERESPONSE._serialized_start = 3859 + _DEPRECATENAMESPACERESPONSE._serialized_end = 3887 + _STARTWORKFLOWEXECUTIONREQUEST._serialized_start = 3890 + _STARTWORKFLOWEXECUTIONREQUEST._serialized_end = 5507 + _STARTWORKFLOWEXECUTIONRESPONSE._serialized_start = 5510 + _STARTWORKFLOWEXECUTIONRESPONSE._serialized_end = 5808 + _GETWORKFLOWEXECUTIONHISTORYREQUEST._serialized_start = 5811 + _GETWORKFLOWEXECUTIONHISTORYREQUEST._serialized_end = 6109 + _GETWORKFLOWEXECUTIONHISTORYRESPONSE._serialized_start = 6112 + _GETWORKFLOWEXECUTIONHISTORYRESPONSE._serialized_end = 6298 + _GETWORKFLOWEXECUTIONHISTORYREVERSEREQUEST._serialized_start = 6301 + _GETWORKFLOWEXECUTIONHISTORYREVERSEREQUEST._serialized_end = 6477 + _GETWORKFLOWEXECUTIONHISTORYREVERSERESPONSE._serialized_start = 6479 + _GETWORKFLOWEXECUTIONHISTORYREVERSERESPONSE._serialized_end = 6599 + _POLLWORKFLOWTASKQUEUEREQUEST._serialized_start = 6602 + _POLLWORKFLOWTASKQUEUEREQUEST._serialized_end = 7042 + _POLLWORKFLOWTASKQUEUERESPONSE._serialized_start = 7045 + _POLLWORKFLOWTASKQUEUERESPONSE._serialized_end = 8132 + _POLLWORKFLOWTASKQUEUERESPONSE_QUERIESENTRY._serialized_start = 8048 + _POLLWORKFLOWTASKQUEUERESPONSE_QUERIESENTRY._serialized_end = 8132 + _RESPONDWORKFLOWTASKCOMPLETEDREQUEST._serialized_start = 8135 + _RESPONDWORKFLOWTASKCOMPLETEDREQUEST._serialized_end = 9473 + _RESPONDWORKFLOWTASKCOMPLETEDREQUEST_QUERYRESULTSENTRY._serialized_start = 9307 + _RESPONDWORKFLOWTASKCOMPLETEDREQUEST_QUERYRESULTSENTRY._serialized_end = 9402 + _RESPONDWORKFLOWTASKCOMPLETEDREQUEST_CAPABILITIES._serialized_start = 9404 + _RESPONDWORKFLOWTASKCOMPLETEDREQUEST_CAPABILITIES._serialized_end = 9473 + _RESPONDWORKFLOWTASKCOMPLETEDRESPONSE._serialized_start = 9476 + _RESPONDWORKFLOWTASKCOMPLETEDRESPONSE._serialized_end = 9721 + _RESPONDWORKFLOWTASKFAILEDREQUEST._serialized_start = 9724 + _RESPONDWORKFLOWTASKFAILEDREQUEST._serialized_end = 10249 + _RESPONDWORKFLOWTASKFAILEDRESPONSE._serialized_start = 10251 + _RESPONDWORKFLOWTASKFAILEDRESPONSE._serialized_end = 10286 + _POLLACTIVITYTASKQUEUEREQUEST._serialized_start = 10289 + _POLLACTIVITYTASKQUEUEREQUEST._serialized_end = 10775 + _POLLACTIVITYTASKQUEUERESPONSE._serialized_start = 10778 + _POLLACTIVITYTASKQUEUERESPONSE._serialized_end = 11959 + _RECORDACTIVITYTASKHEARTBEATREQUEST._serialized_start = 11962 + _RECORDACTIVITYTASKHEARTBEATREQUEST._serialized_end = 12127 + _RECORDACTIVITYTASKHEARTBEATRESPONSE._serialized_start = 12129 + _RECORDACTIVITYTASKHEARTBEATRESPONSE._serialized_end = 12241 + _RECORDACTIVITYTASKHEARTBEATBYIDREQUEST._serialized_start = 12244 + _RECORDACTIVITYTASKHEARTBEATBYIDREQUEST._serialized_end = 12451 + _RECORDACTIVITYTASKHEARTBEATBYIDRESPONSE._serialized_start = 12453 + _RECORDACTIVITYTASKHEARTBEATBYIDRESPONSE._serialized_end = 12569 + _RESPONDACTIVITYTASKCOMPLETEDREQUEST._serialized_start = 12572 + _RESPONDACTIVITYTASKCOMPLETEDREQUEST._serialized_end = 12954 + _RESPONDACTIVITYTASKCOMPLETEDRESPONSE._serialized_start = 12956 + _RESPONDACTIVITYTASKCOMPLETEDRESPONSE._serialized_end = 12994 + _RESPONDACTIVITYTASKCOMPLETEDBYIDREQUEST._serialized_start = 12997 + _RESPONDACTIVITYTASKCOMPLETEDBYIDREQUEST._serialized_end = 13204 + _RESPONDACTIVITYTASKCOMPLETEDBYIDRESPONSE._serialized_start = 13206 + _RESPONDACTIVITYTASKCOMPLETEDBYIDRESPONSE._serialized_end = 13248 + _RESPONDACTIVITYTASKFAILEDREQUEST._serialized_start = 13251 + _RESPONDACTIVITYTASKFAILEDREQUEST._serialized_end = 13697 + _RESPONDACTIVITYTASKFAILEDRESPONSE._serialized_start = 13699 + _RESPONDACTIVITYTASKFAILEDRESPONSE._serialized_end = 13786 + _RESPONDACTIVITYTASKFAILEDBYIDREQUEST._serialized_start = 13789 + _RESPONDACTIVITYTASKFAILEDBYIDREQUEST._serialized_end = 14060 + _RESPONDACTIVITYTASKFAILEDBYIDRESPONSE._serialized_start = 14062 + _RESPONDACTIVITYTASKFAILEDBYIDRESPONSE._serialized_end = 14153 + _RESPONDACTIVITYTASKCANCELEDREQUEST._serialized_start = 14156 + _RESPONDACTIVITYTASKCANCELEDREQUEST._serialized_end = 14538 + _RESPONDACTIVITYTASKCANCELEDRESPONSE._serialized_start = 14540 + _RESPONDACTIVITYTASKCANCELEDRESPONSE._serialized_end = 14577 + _RESPONDACTIVITYTASKCANCELEDBYIDREQUEST._serialized_start = 14580 + _RESPONDACTIVITYTASKCANCELEDBYIDREQUEST._serialized_end = 14868 + _RESPONDACTIVITYTASKCANCELEDBYIDRESPONSE._serialized_start = 14870 + _RESPONDACTIVITYTASKCANCELEDBYIDRESPONSE._serialized_end = 14911 + _REQUESTCANCELWORKFLOWEXECUTIONREQUEST._serialized_start = 14914 + _REQUESTCANCELWORKFLOWEXECUTIONREQUEST._serialized_end = 15174 + _REQUESTCANCELWORKFLOWEXECUTIONRESPONSE._serialized_start = 15176 + _REQUESTCANCELWORKFLOWEXECUTIONRESPONSE._serialized_end = 15216 + _SIGNALWORKFLOWEXECUTIONREQUEST._serialized_start = 15219 + _SIGNALWORKFLOWEXECUTIONREQUEST._serialized_end = 15569 + _SIGNALWORKFLOWEXECUTIONRESPONSE._serialized_start = 15571 + _SIGNALWORKFLOWEXECUTIONRESPONSE._serialized_end = 15648 + _SIGNALWITHSTARTWORKFLOWEXECUTIONREQUEST._serialized_start = 15651 + _SIGNALWITHSTARTWORKFLOWEXECUTIONREQUEST._serialized_end = 16990 + _SIGNALWITHSTARTWORKFLOWEXECUTIONRESPONSE._serialized_start = 16993 + _SIGNALWITHSTARTWORKFLOWEXECUTIONRESPONSE._serialized_end = 17151 + _RESETWORKFLOWEXECUTIONREQUEST._serialized_start = 17154 + _RESETWORKFLOWEXECUTIONREQUEST._serialized_end = 17603 + _RESETWORKFLOWEXECUTIONRESPONSE._serialized_start = 17605 + _RESETWORKFLOWEXECUTIONRESPONSE._serialized_end = 17653 + _TERMINATEWORKFLOWEXECUTIONREQUEST._serialized_start = 17656 + _TERMINATEWORKFLOWEXECUTIONREQUEST._serialized_end = 17943 + _TERMINATEWORKFLOWEXECUTIONRESPONSE._serialized_start = 17945 + _TERMINATEWORKFLOWEXECUTIONRESPONSE._serialized_end = 17981 + _DELETEWORKFLOWEXECUTIONREQUEST._serialized_start = 17983 + _DELETEWORKFLOWEXECUTIONREQUEST._serialized_end = 18105 + _DELETEWORKFLOWEXECUTIONRESPONSE._serialized_start = 18107 + _DELETEWORKFLOWEXECUTIONRESPONSE._serialized_end = 18140 + _LISTOPENWORKFLOWEXECUTIONSREQUEST._serialized_start = 18143 + _LISTOPENWORKFLOWEXECUTIONSREQUEST._serialized_end = 18472 + _LISTOPENWORKFLOWEXECUTIONSRESPONSE._serialized_start = 18475 + _LISTOPENWORKFLOWEXECUTIONSRESPONSE._serialized_end = 18605 + _LISTCLOSEDWORKFLOWEXECUTIONSREQUEST._serialized_start = 18608 + _LISTCLOSEDWORKFLOWEXECUTIONSREQUEST._serialized_end = 19002 + _LISTCLOSEDWORKFLOWEXECUTIONSRESPONSE._serialized_start = 19005 + _LISTCLOSEDWORKFLOWEXECUTIONSRESPONSE._serialized_end = 19137 + _LISTWORKFLOWEXECUTIONSREQUEST._serialized_start = 19139 + _LISTWORKFLOWEXECUTIONSREQUEST._serialized_end = 19248 + _LISTWORKFLOWEXECUTIONSRESPONSE._serialized_start = 19250 + _LISTWORKFLOWEXECUTIONSRESPONSE._serialized_end = 19376 + _LISTARCHIVEDWORKFLOWEXECUTIONSREQUEST._serialized_start = 19378 + _LISTARCHIVEDWORKFLOWEXECUTIONSREQUEST._serialized_end = 19495 + _LISTARCHIVEDWORKFLOWEXECUTIONSRESPONSE._serialized_start = 19498 + _LISTARCHIVEDWORKFLOWEXECUTIONSRESPONSE._serialized_end = 19632 + _SCANWORKFLOWEXECUTIONSREQUEST._serialized_start = 19634 + _SCANWORKFLOWEXECUTIONSREQUEST._serialized_end = 19743 + _SCANWORKFLOWEXECUTIONSRESPONSE._serialized_start = 19745 + _SCANWORKFLOWEXECUTIONSRESPONSE._serialized_end = 19871 + _COUNTWORKFLOWEXECUTIONSREQUEST._serialized_start = 19873 + _COUNTWORKFLOWEXECUTIONSREQUEST._serialized_end = 19939 + _COUNTWORKFLOWEXECUTIONSRESPONSE._serialized_start = 19942 + _COUNTWORKFLOWEXECUTIONSRESPONSE._serialized_end = 20179 + _COUNTWORKFLOWEXECUTIONSRESPONSE_AGGREGATIONGROUP._serialized_start = 20091 + _COUNTWORKFLOWEXECUTIONSRESPONSE_AGGREGATIONGROUP._serialized_end = 20179 + _GETSEARCHATTRIBUTESREQUEST._serialized_start = 20181 + _GETSEARCHATTRIBUTESREQUEST._serialized_end = 20209 + _GETSEARCHATTRIBUTESRESPONSE._serialized_start = 20212 + _GETSEARCHATTRIBUTESRESPONSE._serialized_end = 20413 + _GETSEARCHATTRIBUTESRESPONSE_KEYSENTRY._serialized_start = 20329 + _GETSEARCHATTRIBUTESRESPONSE_KEYSENTRY._serialized_end = 20413 + _RESPONDQUERYTASKCOMPLETEDREQUEST._serialized_start = 20416 + _RESPONDQUERYTASKCOMPLETEDREQUEST._serialized_end = 20777 + _RESPONDQUERYTASKCOMPLETEDRESPONSE._serialized_start = 20779 + _RESPONDQUERYTASKCOMPLETEDRESPONSE._serialized_end = 20814 + _RESETSTICKYTASKQUEUEREQUEST._serialized_start = 20816 + _RESETSTICKYTASKQUEUEREQUEST._serialized_end = 20926 + _RESETSTICKYTASKQUEUERESPONSE._serialized_start = 20928 + _RESETSTICKYTASKQUEUERESPONSE._serialized_end = 20958 + _SHUTDOWNWORKERREQUEST._serialized_start = 20961 + _SHUTDOWNWORKERREQUEST._serialized_end = 21244 + _SHUTDOWNWORKERRESPONSE._serialized_start = 21246 + _SHUTDOWNWORKERRESPONSE._serialized_end = 21270 + _QUERYWORKFLOWREQUEST._serialized_start = 21273 + _QUERYWORKFLOWREQUEST._serialized_end = 21506 + _QUERYWORKFLOWRESPONSE._serialized_start = 21509 + _QUERYWORKFLOWRESPONSE._serialized_end = 21650 + _DESCRIBEWORKFLOWEXECUTIONREQUEST._serialized_start = 21652 + _DESCRIBEWORKFLOWEXECUTIONREQUEST._serialized_end = 21767 + _DESCRIBEWORKFLOWEXECUTIONRESPONSE._serialized_start = 21770 + _DESCRIBEWORKFLOWEXECUTIONRESPONSE._serialized_end = 22435 + _DESCRIBETASKQUEUEREQUEST._serialized_start = 22438 + _DESCRIBETASKQUEUEREQUEST._serialized_end = 22966 + _DESCRIBETASKQUEUERESPONSE._serialized_start = 22969 + _DESCRIBETASKQUEUERESPONSE._serialized_end = 23973 + _DESCRIBETASKQUEUERESPONSE_STATSBYPRIORITYKEYENTRY._serialized_start = 23653 + _DESCRIBETASKQUEUERESPONSE_STATSBYPRIORITYKEYENTRY._serialized_end = 23753 + _DESCRIBETASKQUEUERESPONSE_EFFECTIVERATELIMIT._serialized_start = 23755 + _DESCRIBETASKQUEUERESPONSE_EFFECTIVERATELIMIT._serialized_end = 23871 + _DESCRIBETASKQUEUERESPONSE_VERSIONSINFOENTRY._serialized_start = 23873 + _DESCRIBETASKQUEUERESPONSE_VERSIONSINFOENTRY._serialized_end = 23973 + _GETCLUSTERINFOREQUEST._serialized_start = 23975 + _GETCLUSTERINFOREQUEST._serialized_end = 23998 + _GETCLUSTERINFORESPONSE._serialized_start = 24001 + _GETCLUSTERINFORESPONSE._serialized_end = 24466 + _GETCLUSTERINFORESPONSE_SUPPORTEDCLIENTSENTRY._serialized_start = 24411 + _GETCLUSTERINFORESPONSE_SUPPORTEDCLIENTSENTRY._serialized_end = 24466 + _GETSYSTEMINFOREQUEST._serialized_start = 24468 + _GETSYSTEMINFOREQUEST._serialized_end = 24490 + _GETSYSTEMINFORESPONSE._serialized_start = 24493 + _GETSYSTEMINFORESPONSE._serialized_end = 25070 + _GETSYSTEMINFORESPONSE_CAPABILITIES._serialized_start = 24634 + _GETSYSTEMINFORESPONSE_CAPABILITIES._serialized_end = 25070 + _LISTTASKQUEUEPARTITIONSREQUEST._serialized_start = 25072 + _LISTTASKQUEUEPARTITIONSREQUEST._serialized_end = 25181 + _LISTTASKQUEUEPARTITIONSRESPONSE._serialized_start = 25184 + _LISTTASKQUEUEPARTITIONSRESPONSE._serialized_end = 25407 + _CREATESCHEDULEREQUEST._serialized_start = 25410 + _CREATESCHEDULEREQUEST._serialized_end = 25742 + _CREATESCHEDULERESPONSE._serialized_start = 25744 + _CREATESCHEDULERESPONSE._serialized_end = 25792 + _DESCRIBESCHEDULEREQUEST._serialized_start = 25794 + _DESCRIBESCHEDULEREQUEST._serialized_end = 25859 + _DESCRIBESCHEDULERESPONSE._serialized_start = 25862 + _DESCRIBESCHEDULERESPONSE._serialized_end = 26133 + _UPDATESCHEDULEREQUEST._serialized_start = 26136 + _UPDATESCHEDULEREQUEST._serialized_end = 26428 + _UPDATESCHEDULERESPONSE._serialized_start = 26430 + _UPDATESCHEDULERESPONSE._serialized_end = 26454 + _PATCHSCHEDULEREQUEST._serialized_start = 26457 + _PATCHSCHEDULEREQUEST._serialized_end = 26613 + _PATCHSCHEDULERESPONSE._serialized_start = 26615 + _PATCHSCHEDULERESPONSE._serialized_end = 26638 + _LISTSCHEDULEMATCHINGTIMESREQUEST._serialized_start = 26641 + _LISTSCHEDULEMATCHINGTIMESREQUEST._serialized_end = 26809 + _LISTSCHEDULEMATCHINGTIMESRESPONSE._serialized_start = 26811 + _LISTSCHEDULEMATCHINGTIMESRESPONSE._serialized_end = 26894 + _DELETESCHEDULEREQUEST._serialized_start = 26896 + _DELETESCHEDULEREQUEST._serialized_end = 26977 + _DELETESCHEDULERESPONSE._serialized_start = 26979 + _DELETESCHEDULERESPONSE._serialized_end = 27003 + _LISTSCHEDULESREQUEST._serialized_start = 27005 + _LISTSCHEDULESREQUEST._serialized_end = 27113 + _LISTSCHEDULESRESPONSE._serialized_start = 27115 + _LISTSCHEDULESRESPONSE._serialized_end = 27227 + _COUNTSCHEDULESREQUEST._serialized_start = 27229 + _COUNTSCHEDULESREQUEST._serialized_end = 27286 + _COUNTSCHEDULESRESPONSE._serialized_start = 27289 + _COUNTSCHEDULESRESPONSE._serialized_end = 27508 + _COUNTSCHEDULESRESPONSE_AGGREGATIONGROUP._serialized_start = 20091 + _COUNTSCHEDULESRESPONSE_AGGREGATIONGROUP._serialized_end = 20179 + _UPDATEWORKERBUILDIDCOMPATIBILITYREQUEST._serialized_start = 27511 + _UPDATEWORKERBUILDIDCOMPATIBILITYREQUEST._serialized_end = 28157 + _UPDATEWORKERBUILDIDCOMPATIBILITYREQUEST_ADDNEWCOMPATIBLEVERSION._serialized_start = 27958 _UPDATEWORKERBUILDIDCOMPATIBILITYREQUEST_ADDNEWCOMPATIBLEVERSION._serialized_end = ( - 27683 + 28069 ) - _UPDATEWORKERBUILDIDCOMPATIBILITYREQUEST_MERGESETS._serialized_start = 27685 - _UPDATEWORKERBUILDIDCOMPATIBILITYREQUEST_MERGESETS._serialized_end = 27758 - _UPDATEWORKERBUILDIDCOMPATIBILITYRESPONSE._serialized_start = 27773 - _UPDATEWORKERBUILDIDCOMPATIBILITYRESPONSE._serialized_end = 27837 - _GETWORKERBUILDIDCOMPATIBILITYREQUEST._serialized_start = 27839 - _GETWORKERBUILDIDCOMPATIBILITYREQUEST._serialized_end = 27934 - _GETWORKERBUILDIDCOMPATIBILITYRESPONSE._serialized_start = 27936 - _GETWORKERBUILDIDCOMPATIBILITYRESPONSE._serialized_end = 28052 - _UPDATEWORKERVERSIONINGRULESREQUEST._serialized_start = 28055 - _UPDATEWORKERVERSIONINGRULESREQUEST._serialized_end = 29772 - _UPDATEWORKERVERSIONINGRULESREQUEST_INSERTBUILDIDASSIGNMENTRULE._serialized_start = 29107 + _UPDATEWORKERBUILDIDCOMPATIBILITYREQUEST_MERGESETS._serialized_start = 28071 + _UPDATEWORKERBUILDIDCOMPATIBILITYREQUEST_MERGESETS._serialized_end = 28144 + _UPDATEWORKERBUILDIDCOMPATIBILITYRESPONSE._serialized_start = 28159 + _UPDATEWORKERBUILDIDCOMPATIBILITYRESPONSE._serialized_end = 28223 + _GETWORKERBUILDIDCOMPATIBILITYREQUEST._serialized_start = 28225 + _GETWORKERBUILDIDCOMPATIBILITYREQUEST._serialized_end = 28320 + _GETWORKERBUILDIDCOMPATIBILITYRESPONSE._serialized_start = 28322 + _GETWORKERBUILDIDCOMPATIBILITYRESPONSE._serialized_end = 28438 + _UPDATEWORKERVERSIONINGRULESREQUEST._serialized_start = 28441 + _UPDATEWORKERVERSIONINGRULESREQUEST._serialized_end = 30158 + _UPDATEWORKERVERSIONINGRULESREQUEST_INSERTBUILDIDASSIGNMENTRULE._serialized_start = 29493 _UPDATEWORKERVERSIONINGRULESREQUEST_INSERTBUILDIDASSIGNMENTRULE._serialized_end = ( - 29220 + 29606 ) - _UPDATEWORKERVERSIONINGRULESREQUEST_REPLACEBUILDIDASSIGNMENTRULE._serialized_start = 29223 + _UPDATEWORKERVERSIONINGRULESREQUEST_REPLACEBUILDIDASSIGNMENTRULE._serialized_start = 29609 _UPDATEWORKERVERSIONINGRULESREQUEST_REPLACEBUILDIDASSIGNMENTRULE._serialized_end = ( - 29352 + 29738 ) - _UPDATEWORKERVERSIONINGRULESREQUEST_DELETEBUILDIDASSIGNMENTRULE._serialized_start = 29354 + _UPDATEWORKERVERSIONINGRULESREQUEST_DELETEBUILDIDASSIGNMENTRULE._serialized_start = 29740 _UPDATEWORKERVERSIONINGRULESREQUEST_DELETEBUILDIDASSIGNMENTRULE._serialized_end = ( - 29418 + 29804 ) - _UPDATEWORKERVERSIONINGRULESREQUEST_ADDCOMPATIBLEBUILDIDREDIRECTRULE._serialized_start = 29420 - _UPDATEWORKERVERSIONINGRULESREQUEST_ADDCOMPATIBLEBUILDIDREDIRECTRULE._serialized_end = 29526 - _UPDATEWORKERVERSIONINGRULESREQUEST_REPLACECOMPATIBLEBUILDIDREDIRECTRULE._serialized_start = 29528 - _UPDATEWORKERVERSIONINGRULESREQUEST_REPLACECOMPATIBLEBUILDIDREDIRECTRULE._serialized_end = 29638 - _UPDATEWORKERVERSIONINGRULESREQUEST_DELETECOMPATIBLEBUILDIDREDIRECTRULE._serialized_start = 29640 - _UPDATEWORKERVERSIONINGRULESREQUEST_DELETECOMPATIBLEBUILDIDREDIRECTRULE._serialized_end = 29702 - _UPDATEWORKERVERSIONINGRULESREQUEST_COMMITBUILDID._serialized_start = 29704 - _UPDATEWORKERVERSIONINGRULESREQUEST_COMMITBUILDID._serialized_end = 29759 - _UPDATEWORKERVERSIONINGRULESRESPONSE._serialized_start = 29775 - _UPDATEWORKERVERSIONINGRULESRESPONSE._serialized_end = 30027 - _GETWORKERVERSIONINGRULESREQUEST._serialized_start = 30029 - _GETWORKERVERSIONINGRULESREQUEST._serialized_end = 30101 - _GETWORKERVERSIONINGRULESRESPONSE._serialized_start = 30104 - _GETWORKERVERSIONINGRULESRESPONSE._serialized_end = 30353 - _GETWORKERTASKREACHABILITYREQUEST._serialized_start = 30356 - _GETWORKERTASKREACHABILITYREQUEST._serialized_end = 30512 - _GETWORKERTASKREACHABILITYRESPONSE._serialized_start = 30514 - _GETWORKERTASKREACHABILITYRESPONSE._serialized_end = 30628 - _UPDATEWORKFLOWEXECUTIONREQUEST._serialized_start = 30631 - _UPDATEWORKFLOWEXECUTIONREQUEST._serialized_end = 30892 - _UPDATEWORKFLOWEXECUTIONRESPONSE._serialized_start = 30895 - _UPDATEWORKFLOWEXECUTIONRESPONSE._serialized_end = 31154 - _STARTBATCHOPERATIONREQUEST._serialized_start = 31157 - _STARTBATCHOPERATIONREQUEST._serialized_end = 32169 - _STARTBATCHOPERATIONRESPONSE._serialized_start = 32171 - _STARTBATCHOPERATIONRESPONSE._serialized_end = 32200 - _STOPBATCHOPERATIONREQUEST._serialized_start = 32202 - _STOPBATCHOPERATIONREQUEST._serialized_end = 32298 - _STOPBATCHOPERATIONRESPONSE._serialized_start = 32300 - _STOPBATCHOPERATIONRESPONSE._serialized_end = 32328 - _DESCRIBEBATCHOPERATIONREQUEST._serialized_start = 32330 - _DESCRIBEBATCHOPERATIONREQUEST._serialized_end = 32396 - _DESCRIBEBATCHOPERATIONRESPONSE._serialized_start = 32399 - _DESCRIBEBATCHOPERATIONRESPONSE._serialized_end = 32801 - _LISTBATCHOPERATIONSREQUEST._serialized_start = 32803 - _LISTBATCHOPERATIONSREQUEST._serialized_end = 32894 - _LISTBATCHOPERATIONSRESPONSE._serialized_start = 32896 - _LISTBATCHOPERATIONSRESPONSE._serialized_end = 33017 - _POLLWORKFLOWEXECUTIONUPDATEREQUEST._serialized_start = 33020 - _POLLWORKFLOWEXECUTIONUPDATEREQUEST._serialized_end = 33205 - _POLLWORKFLOWEXECUTIONUPDATERESPONSE._serialized_start = 33208 - _POLLWORKFLOWEXECUTIONUPDATERESPONSE._serialized_end = 33427 - _POLLNEXUSTASKQUEUEREQUEST._serialized_start = 33430 - _POLLNEXUSTASKQUEUEREQUEST._serialized_end = 33846 - _POLLNEXUSTASKQUEUERESPONSE._serialized_start = 33849 - _POLLNEXUSTASKQUEUERESPONSE._serialized_end = 34126 - _RESPONDNEXUSTASKCOMPLETEDREQUEST._serialized_start = 34129 - _RESPONDNEXUSTASKCOMPLETEDREQUEST._serialized_end = 34296 - _RESPONDNEXUSTASKCOMPLETEDRESPONSE._serialized_start = 34298 - _RESPONDNEXUSTASKCOMPLETEDRESPONSE._serialized_end = 34333 - _RESPONDNEXUSTASKFAILEDREQUEST._serialized_start = 34336 - _RESPONDNEXUSTASKFAILEDREQUEST._serialized_end = 34556 - _RESPONDNEXUSTASKFAILEDRESPONSE._serialized_start = 34558 - _RESPONDNEXUSTASKFAILEDRESPONSE._serialized_end = 34590 - _EXECUTEMULTIOPERATIONREQUEST._serialized_start = 34593 - _EXECUTEMULTIOPERATIONREQUEST._serialized_end = 34965 - _EXECUTEMULTIOPERATIONREQUEST_OPERATION._serialized_start = 34759 - _EXECUTEMULTIOPERATIONREQUEST_OPERATION._serialized_end = 34965 - _EXECUTEMULTIOPERATIONRESPONSE._serialized_start = 34968 - _EXECUTEMULTIOPERATIONRESPONSE._serialized_end = 35300 - _EXECUTEMULTIOPERATIONRESPONSE_RESPONSE._serialized_start = 35094 - _EXECUTEMULTIOPERATIONRESPONSE_RESPONSE._serialized_end = 35300 - _UPDATEACTIVITYOPTIONSREQUEST._serialized_start = 35303 - _UPDATEACTIVITYOPTIONSREQUEST._serialized_end = 35639 - _UPDATEACTIVITYEXECUTIONOPTIONSREQUEST._serialized_start = 35642 - _UPDATEACTIVITYEXECUTIONOPTIONSREQUEST._serialized_end = 35941 - _UPDATEACTIVITYOPTIONSRESPONSE._serialized_start = 35943 - _UPDATEACTIVITYOPTIONSRESPONSE._serialized_end = 36043 - _UPDATEACTIVITYEXECUTIONOPTIONSRESPONSE._serialized_start = 36045 - _UPDATEACTIVITYEXECUTIONOPTIONSRESPONSE._serialized_end = 36154 - _PAUSEACTIVITYREQUEST._serialized_start = 36157 - _PAUSEACTIVITYREQUEST._serialized_end = 36356 - _PAUSEACTIVITYEXECUTIONREQUEST._serialized_start = 36359 - _PAUSEACTIVITYEXECUTIONREQUEST._serialized_end = 36542 - _PAUSEACTIVITYRESPONSE._serialized_start = 36544 - _PAUSEACTIVITYRESPONSE._serialized_end = 36567 - _PAUSEACTIVITYEXECUTIONRESPONSE._serialized_start = 36569 - _PAUSEACTIVITYEXECUTIONRESPONSE._serialized_end = 36601 - _UNPAUSEACTIVITYREQUEST._serialized_start = 36604 - _UNPAUSEACTIVITYREQUEST._serialized_end = 36884 - _UNPAUSEACTIVITYEXECUTIONREQUEST._serialized_start = 36887 - _UNPAUSEACTIVITYEXECUTIONREQUEST._serialized_end = 37144 - _UNPAUSEACTIVITYRESPONSE._serialized_start = 37146 - _UNPAUSEACTIVITYRESPONSE._serialized_end = 37171 - _UNPAUSEACTIVITYEXECUTIONRESPONSE._serialized_start = 37173 - _UNPAUSEACTIVITYEXECUTIONRESPONSE._serialized_end = 37207 - _RESETACTIVITYREQUEST._serialized_start = 37210 - _RESETACTIVITYREQUEST._serialized_end = 37517 - _RESETACTIVITYEXECUTIONREQUEST._serialized_start = 37520 - _RESETACTIVITYEXECUTIONREQUEST._serialized_end = 37790 - _RESETACTIVITYRESPONSE._serialized_start = 37792 - _RESETACTIVITYRESPONSE._serialized_end = 37815 - _RESETACTIVITYEXECUTIONRESPONSE._serialized_start = 37817 - _RESETACTIVITYEXECUTIONRESPONSE._serialized_end = 37849 - _UPDATEWORKFLOWEXECUTIONOPTIONSREQUEST._serialized_start = 37852 - _UPDATEWORKFLOWEXECUTIONOPTIONSREQUEST._serialized_end = 38136 - _UPDATEWORKFLOWEXECUTIONOPTIONSRESPONSE._serialized_start = 38139 - _UPDATEWORKFLOWEXECUTIONOPTIONSRESPONSE._serialized_end = 38316 - _DESCRIBEDEPLOYMENTREQUEST._serialized_start = 38318 - _DESCRIBEDEPLOYMENTREQUEST._serialized_end = 38424 - _DESCRIBEDEPLOYMENTRESPONSE._serialized_start = 38426 - _DESCRIBEDEPLOYMENTRESPONSE._serialized_end = 38523 - _DESCRIBEWORKERDEPLOYMENTVERSIONREQUEST._serialized_start = 38526 - _DESCRIBEWORKERDEPLOYMENTVERSIONREQUEST._serialized_end = 38720 - _DESCRIBEWORKERDEPLOYMENTVERSIONRESPONSE._serialized_start = 38723 - _DESCRIBEWORKERDEPLOYMENTVERSIONRESPONSE._serialized_end = 39375 - _DESCRIBEWORKERDEPLOYMENTVERSIONRESPONSE_VERSIONTASKQUEUE._serialized_start = 38984 - _DESCRIBEWORKERDEPLOYMENTVERSIONRESPONSE_VERSIONTASKQUEUE._serialized_end = 39375 - _DESCRIBEWORKERDEPLOYMENTVERSIONRESPONSE_VERSIONTASKQUEUE_STATSBYPRIORITYKEYENTRY._serialized_start = 23309 - _DESCRIBEWORKERDEPLOYMENTVERSIONRESPONSE_VERSIONTASKQUEUE_STATSBYPRIORITYKEYENTRY._serialized_end = 23409 - _DESCRIBEWORKERDEPLOYMENTREQUEST._serialized_start = 39377 - _DESCRIBEWORKERDEPLOYMENTREQUEST._serialized_end = 39454 - _DESCRIBEWORKERDEPLOYMENTRESPONSE._serialized_start = 39457 - _DESCRIBEWORKERDEPLOYMENTRESPONSE._serialized_end = 39597 - _LISTDEPLOYMENTSREQUEST._serialized_start = 39599 - _LISTDEPLOYMENTSREQUEST._serialized_end = 39707 - _LISTDEPLOYMENTSRESPONSE._serialized_start = 39709 - _LISTDEPLOYMENTSRESPONSE._serialized_end = 39828 - _SETCURRENTDEPLOYMENTREQUEST._serialized_start = 39831 - _SETCURRENTDEPLOYMENTREQUEST._serialized_end = 40036 - _SETCURRENTDEPLOYMENTRESPONSE._serialized_start = 40039 - _SETCURRENTDEPLOYMENTRESPONSE._serialized_end = 40224 - _SETWORKERDEPLOYMENTCURRENTVERSIONREQUEST._serialized_start = 40227 - _SETWORKERDEPLOYMENTCURRENTVERSIONREQUEST._serialized_end = 40456 - _SETWORKERDEPLOYMENTCURRENTVERSIONRESPONSE._serialized_start = 40459 - _SETWORKERDEPLOYMENTCURRENTVERSIONRESPONSE._serialized_end = 40650 - _SETWORKERDEPLOYMENTRAMPINGVERSIONREQUEST._serialized_start = 40653 - _SETWORKERDEPLOYMENTRAMPINGVERSIONREQUEST._serialized_end = 40902 - _SETWORKERDEPLOYMENTRAMPINGVERSIONRESPONSE._serialized_start = 40905 - _SETWORKERDEPLOYMENTRAMPINGVERSIONRESPONSE._serialized_end = 41129 - _CREATEWORKERDEPLOYMENTREQUEST._serialized_start = 41131 - _CREATEWORKERDEPLOYMENTREQUEST._serialized_end = 41244 - _CREATEWORKERDEPLOYMENTRESPONSE._serialized_start = 41246 - _CREATEWORKERDEPLOYMENTRESPONSE._serialized_end = 41302 - _LISTWORKERDEPLOYMENTSREQUEST._serialized_start = 41304 - _LISTWORKERDEPLOYMENTSREQUEST._serialized_end = 41397 - _LISTWORKERDEPLOYMENTSRESPONSE._serialized_start = 41400 - _LISTWORKERDEPLOYMENTSRESPONSE._serialized_end = 42071 - _LISTWORKERDEPLOYMENTSRESPONSE_WORKERDEPLOYMENTSUMMARY._serialized_start = 41575 - _LISTWORKERDEPLOYMENTSRESPONSE_WORKERDEPLOYMENTSUMMARY._serialized_end = 42071 - _CREATEWORKERDEPLOYMENTVERSIONREQUEST._serialized_start = 42074 - _CREATEWORKERDEPLOYMENTVERSIONREQUEST._serialized_end = 42314 - _CREATEWORKERDEPLOYMENTVERSIONRESPONSE._serialized_start = 42316 - _CREATEWORKERDEPLOYMENTVERSIONRESPONSE._serialized_end = 42355 - _DELETEWORKERDEPLOYMENTVERSIONREQUEST._serialized_start = 42358 - _DELETEWORKERDEPLOYMENTVERSIONREQUEST._serialized_end = 42558 - _DELETEWORKERDEPLOYMENTVERSIONRESPONSE._serialized_start = 42560 - _DELETEWORKERDEPLOYMENTVERSIONRESPONSE._serialized_end = 42599 - _DELETEWORKERDEPLOYMENTREQUEST._serialized_start = 42601 - _DELETEWORKERDEPLOYMENTREQUEST._serialized_end = 42694 - _DELETEWORKERDEPLOYMENTRESPONSE._serialized_start = 42696 - _DELETEWORKERDEPLOYMENTRESPONSE._serialized_end = 42728 - _UPDATEWORKERDEPLOYMENTVERSIONCOMPUTECONFIGREQUEST._serialized_start = 42731 - _UPDATEWORKERDEPLOYMENTVERSIONCOMPUTECONFIGREQUEST._serialized_end = 43247 - _UPDATEWORKERDEPLOYMENTVERSIONCOMPUTECONFIGREQUEST_COMPUTECONFIGSCALINGGROUPSENTRY._serialized_start = 43124 - _UPDATEWORKERDEPLOYMENTVERSIONCOMPUTECONFIGREQUEST_COMPUTECONFIGSCALINGGROUPSENTRY._serialized_end = 43247 - _UPDATEWORKERDEPLOYMENTVERSIONCOMPUTECONFIGRESPONSE._serialized_start = 43249 - _UPDATEWORKERDEPLOYMENTVERSIONCOMPUTECONFIGRESPONSE._serialized_end = 43301 - _VALIDATEWORKERDEPLOYMENTVERSIONCOMPUTECONFIGREQUEST._serialized_start = 43304 - _VALIDATEWORKERDEPLOYMENTVERSIONCOMPUTECONFIGREQUEST._serialized_end = 43804 - _VALIDATEWORKERDEPLOYMENTVERSIONCOMPUTECONFIGREQUEST_COMPUTECONFIGSCALINGGROUPSENTRY._serialized_start = 43124 - _VALIDATEWORKERDEPLOYMENTVERSIONCOMPUTECONFIGREQUEST_COMPUTECONFIGSCALINGGROUPSENTRY._serialized_end = 43247 - _VALIDATEWORKERDEPLOYMENTVERSIONCOMPUTECONFIGRESPONSE._serialized_start = 43806 - _VALIDATEWORKERDEPLOYMENTVERSIONCOMPUTECONFIGRESPONSE._serialized_end = 43860 - _UPDATEWORKERDEPLOYMENTVERSIONMETADATAREQUEST._serialized_start = 43863 - _UPDATEWORKERDEPLOYMENTVERSIONMETADATAREQUEST._serialized_end = 44281 - _UPDATEWORKERDEPLOYMENTVERSIONMETADATAREQUEST_UPSERTENTRIESENTRY._serialized_start = 44196 + _UPDATEWORKERVERSIONINGRULESREQUEST_ADDCOMPATIBLEBUILDIDREDIRECTRULE._serialized_start = 29806 + _UPDATEWORKERVERSIONINGRULESREQUEST_ADDCOMPATIBLEBUILDIDREDIRECTRULE._serialized_end = 29912 + _UPDATEWORKERVERSIONINGRULESREQUEST_REPLACECOMPATIBLEBUILDIDREDIRECTRULE._serialized_start = 29914 + _UPDATEWORKERVERSIONINGRULESREQUEST_REPLACECOMPATIBLEBUILDIDREDIRECTRULE._serialized_end = 30024 + _UPDATEWORKERVERSIONINGRULESREQUEST_DELETECOMPATIBLEBUILDIDREDIRECTRULE._serialized_start = 30026 + _UPDATEWORKERVERSIONINGRULESREQUEST_DELETECOMPATIBLEBUILDIDREDIRECTRULE._serialized_end = 30088 + _UPDATEWORKERVERSIONINGRULESREQUEST_COMMITBUILDID._serialized_start = 30090 + _UPDATEWORKERVERSIONINGRULESREQUEST_COMMITBUILDID._serialized_end = 30145 + _UPDATEWORKERVERSIONINGRULESRESPONSE._serialized_start = 30161 + _UPDATEWORKERVERSIONINGRULESRESPONSE._serialized_end = 30413 + _GETWORKERVERSIONINGRULESREQUEST._serialized_start = 30415 + _GETWORKERVERSIONINGRULESREQUEST._serialized_end = 30487 + _GETWORKERVERSIONINGRULESRESPONSE._serialized_start = 30490 + _GETWORKERVERSIONINGRULESRESPONSE._serialized_end = 30739 + _GETWORKERTASKREACHABILITYREQUEST._serialized_start = 30742 + _GETWORKERTASKREACHABILITYREQUEST._serialized_end = 30898 + _GETWORKERTASKREACHABILITYRESPONSE._serialized_start = 30900 + _GETWORKERTASKREACHABILITYRESPONSE._serialized_end = 31014 + _UPDATEWORKFLOWEXECUTIONREQUEST._serialized_start = 31017 + _UPDATEWORKFLOWEXECUTIONREQUEST._serialized_end = 31278 + _UPDATEWORKFLOWEXECUTIONRESPONSE._serialized_start = 31281 + _UPDATEWORKFLOWEXECUTIONRESPONSE._serialized_end = 31540 + _STARTBATCHOPERATIONREQUEST._serialized_start = 31543 + _STARTBATCHOPERATIONREQUEST._serialized_end = 32909 + _STARTBATCHOPERATIONRESPONSE._serialized_start = 32911 + _STARTBATCHOPERATIONRESPONSE._serialized_end = 32940 + _STOPBATCHOPERATIONREQUEST._serialized_start = 32942 + _STOPBATCHOPERATIONREQUEST._serialized_end = 33038 + _STOPBATCHOPERATIONRESPONSE._serialized_start = 33040 + _STOPBATCHOPERATIONRESPONSE._serialized_end = 33068 + _DESCRIBEBATCHOPERATIONREQUEST._serialized_start = 33070 + _DESCRIBEBATCHOPERATIONREQUEST._serialized_end = 33136 + _DESCRIBEBATCHOPERATIONRESPONSE._serialized_start = 33139 + _DESCRIBEBATCHOPERATIONRESPONSE._serialized_end = 33611 + _LISTBATCHOPERATIONSREQUEST._serialized_start = 33613 + _LISTBATCHOPERATIONSREQUEST._serialized_end = 33704 + _LISTBATCHOPERATIONSRESPONSE._serialized_start = 33706 + _LISTBATCHOPERATIONSRESPONSE._serialized_end = 33827 + _POLLWORKFLOWEXECUTIONUPDATEREQUEST._serialized_start = 33830 + _POLLWORKFLOWEXECUTIONUPDATEREQUEST._serialized_end = 34015 + _POLLWORKFLOWEXECUTIONUPDATERESPONSE._serialized_start = 34018 + _POLLWORKFLOWEXECUTIONUPDATERESPONSE._serialized_end = 34237 + _POLLNEXUSTASKQUEUEREQUEST._serialized_start = 34240 + _POLLNEXUSTASKQUEUEREQUEST._serialized_end = 34656 + _POLLNEXUSTASKQUEUERESPONSE._serialized_start = 34659 + _POLLNEXUSTASKQUEUERESPONSE._serialized_end = 35013 + _RESPONDNEXUSTASKCOMPLETEDREQUEST._serialized_start = 35016 + _RESPONDNEXUSTASKCOMPLETEDREQUEST._serialized_end = 35183 + _RESPONDNEXUSTASKCOMPLETEDRESPONSE._serialized_start = 35185 + _RESPONDNEXUSTASKCOMPLETEDRESPONSE._serialized_end = 35220 + _RESPONDNEXUSTASKFAILEDREQUEST._serialized_start = 35223 + _RESPONDNEXUSTASKFAILEDREQUEST._serialized_end = 35443 + _RESPONDNEXUSTASKFAILEDRESPONSE._serialized_start = 35445 + _RESPONDNEXUSTASKFAILEDRESPONSE._serialized_end = 35477 + _EXECUTEMULTIOPERATIONREQUEST._serialized_start = 35480 + _EXECUTEMULTIOPERATIONREQUEST._serialized_end = 35852 + _EXECUTEMULTIOPERATIONREQUEST_OPERATION._serialized_start = 35646 + _EXECUTEMULTIOPERATIONREQUEST_OPERATION._serialized_end = 35852 + _EXECUTEMULTIOPERATIONRESPONSE._serialized_start = 35855 + _EXECUTEMULTIOPERATIONRESPONSE._serialized_end = 36187 + _EXECUTEMULTIOPERATIONRESPONSE_RESPONSE._serialized_start = 35981 + _EXECUTEMULTIOPERATIONRESPONSE_RESPONSE._serialized_end = 36187 + _UPDATEACTIVITYOPTIONSREQUEST._serialized_start = 36190 + _UPDATEACTIVITYOPTIONSREQUEST._serialized_end = 36526 + _UPDATEACTIVITYEXECUTIONOPTIONSREQUEST._serialized_start = 36529 + _UPDATEACTIVITYEXECUTIONOPTIONSREQUEST._serialized_end = 36828 + _UPDATEACTIVITYOPTIONSRESPONSE._serialized_start = 36830 + _UPDATEACTIVITYOPTIONSRESPONSE._serialized_end = 36930 + _UPDATEACTIVITYEXECUTIONOPTIONSRESPONSE._serialized_start = 36932 + _UPDATEACTIVITYEXECUTIONOPTIONSRESPONSE._serialized_end = 37041 + _PAUSEACTIVITYREQUEST._serialized_start = 37044 + _PAUSEACTIVITYREQUEST._serialized_end = 37243 + _PAUSEACTIVITYEXECUTIONREQUEST._serialized_start = 37246 + _PAUSEACTIVITYEXECUTIONREQUEST._serialized_end = 37429 + _PAUSEACTIVITYRESPONSE._serialized_start = 37431 + _PAUSEACTIVITYRESPONSE._serialized_end = 37454 + _PAUSEACTIVITYEXECUTIONRESPONSE._serialized_start = 37456 + _PAUSEACTIVITYEXECUTIONRESPONSE._serialized_end = 37488 + _UNPAUSEACTIVITYREQUEST._serialized_start = 37491 + _UNPAUSEACTIVITYREQUEST._serialized_end = 37771 + _UNPAUSEACTIVITYEXECUTIONREQUEST._serialized_start = 37774 + _UNPAUSEACTIVITYEXECUTIONREQUEST._serialized_end = 38031 + _UNPAUSEACTIVITYRESPONSE._serialized_start = 38033 + _UNPAUSEACTIVITYRESPONSE._serialized_end = 38058 + _UNPAUSEACTIVITYEXECUTIONRESPONSE._serialized_start = 38060 + _UNPAUSEACTIVITYEXECUTIONRESPONSE._serialized_end = 38094 + _RESETACTIVITYREQUEST._serialized_start = 38097 + _RESETACTIVITYREQUEST._serialized_end = 38404 + _RESETACTIVITYEXECUTIONREQUEST._serialized_start = 38407 + _RESETACTIVITYEXECUTIONREQUEST._serialized_end = 38652 + _RESETACTIVITYRESPONSE._serialized_start = 38654 + _RESETACTIVITYRESPONSE._serialized_end = 38677 + _RESETACTIVITYEXECUTIONRESPONSE._serialized_start = 38679 + _RESETACTIVITYEXECUTIONRESPONSE._serialized_end = 38711 + _UPDATEWORKFLOWEXECUTIONOPTIONSREQUEST._serialized_start = 38714 + _UPDATEWORKFLOWEXECUTIONOPTIONSREQUEST._serialized_end = 38998 + _UPDATEWORKFLOWEXECUTIONOPTIONSRESPONSE._serialized_start = 39001 + _UPDATEWORKFLOWEXECUTIONOPTIONSRESPONSE._serialized_end = 39178 + _DESCRIBEDEPLOYMENTREQUEST._serialized_start = 39180 + _DESCRIBEDEPLOYMENTREQUEST._serialized_end = 39286 + _DESCRIBEDEPLOYMENTRESPONSE._serialized_start = 39288 + _DESCRIBEDEPLOYMENTRESPONSE._serialized_end = 39385 + _DESCRIBEWORKERDEPLOYMENTVERSIONREQUEST._serialized_start = 39388 + _DESCRIBEWORKERDEPLOYMENTVERSIONREQUEST._serialized_end = 39582 + _DESCRIBEWORKERDEPLOYMENTVERSIONRESPONSE._serialized_start = 39585 + _DESCRIBEWORKERDEPLOYMENTVERSIONRESPONSE._serialized_end = 40237 + _DESCRIBEWORKERDEPLOYMENTVERSIONRESPONSE_VERSIONTASKQUEUE._serialized_start = 39846 + _DESCRIBEWORKERDEPLOYMENTVERSIONRESPONSE_VERSIONTASKQUEUE._serialized_end = 40237 + _DESCRIBEWORKERDEPLOYMENTVERSIONRESPONSE_VERSIONTASKQUEUE_STATSBYPRIORITYKEYENTRY._serialized_start = 23653 + _DESCRIBEWORKERDEPLOYMENTVERSIONRESPONSE_VERSIONTASKQUEUE_STATSBYPRIORITYKEYENTRY._serialized_end = 23753 + _DESCRIBEWORKERDEPLOYMENTREQUEST._serialized_start = 40239 + _DESCRIBEWORKERDEPLOYMENTREQUEST._serialized_end = 40316 + _DESCRIBEWORKERDEPLOYMENTRESPONSE._serialized_start = 40319 + _DESCRIBEWORKERDEPLOYMENTRESPONSE._serialized_end = 40459 + _LISTDEPLOYMENTSREQUEST._serialized_start = 40461 + _LISTDEPLOYMENTSREQUEST._serialized_end = 40569 + _LISTDEPLOYMENTSRESPONSE._serialized_start = 40571 + _LISTDEPLOYMENTSRESPONSE._serialized_end = 40690 + _SETCURRENTDEPLOYMENTREQUEST._serialized_start = 40693 + _SETCURRENTDEPLOYMENTREQUEST._serialized_end = 40898 + _SETCURRENTDEPLOYMENTRESPONSE._serialized_start = 40901 + _SETCURRENTDEPLOYMENTRESPONSE._serialized_end = 41086 + _SETWORKERDEPLOYMENTCURRENTVERSIONREQUEST._serialized_start = 41089 + _SETWORKERDEPLOYMENTCURRENTVERSIONREQUEST._serialized_end = 41318 + _SETWORKERDEPLOYMENTCURRENTVERSIONRESPONSE._serialized_start = 41321 + _SETWORKERDEPLOYMENTCURRENTVERSIONRESPONSE._serialized_end = 41512 + _SETWORKERDEPLOYMENTRAMPINGVERSIONREQUEST._serialized_start = 41515 + _SETWORKERDEPLOYMENTRAMPINGVERSIONREQUEST._serialized_end = 41764 + _SETWORKERDEPLOYMENTRAMPINGVERSIONRESPONSE._serialized_start = 41767 + _SETWORKERDEPLOYMENTRAMPINGVERSIONRESPONSE._serialized_end = 41991 + _CREATEWORKERDEPLOYMENTREQUEST._serialized_start = 41993 + _CREATEWORKERDEPLOYMENTREQUEST._serialized_end = 42106 + _CREATEWORKERDEPLOYMENTRESPONSE._serialized_start = 42108 + _CREATEWORKERDEPLOYMENTRESPONSE._serialized_end = 42164 + _LISTWORKERDEPLOYMENTSREQUEST._serialized_start = 42166 + _LISTWORKERDEPLOYMENTSREQUEST._serialized_end = 42259 + _LISTWORKERDEPLOYMENTSRESPONSE._serialized_start = 42262 + _LISTWORKERDEPLOYMENTSRESPONSE._serialized_end = 42933 + _LISTWORKERDEPLOYMENTSRESPONSE_WORKERDEPLOYMENTSUMMARY._serialized_start = 42437 + _LISTWORKERDEPLOYMENTSRESPONSE_WORKERDEPLOYMENTSUMMARY._serialized_end = 42933 + _CREATEWORKERDEPLOYMENTVERSIONREQUEST._serialized_start = 42936 + _CREATEWORKERDEPLOYMENTVERSIONREQUEST._serialized_end = 43176 + _CREATEWORKERDEPLOYMENTVERSIONRESPONSE._serialized_start = 43178 + _CREATEWORKERDEPLOYMENTVERSIONRESPONSE._serialized_end = 43217 + _DELETEWORKERDEPLOYMENTVERSIONREQUEST._serialized_start = 43220 + _DELETEWORKERDEPLOYMENTVERSIONREQUEST._serialized_end = 43420 + _DELETEWORKERDEPLOYMENTVERSIONRESPONSE._serialized_start = 43422 + _DELETEWORKERDEPLOYMENTVERSIONRESPONSE._serialized_end = 43461 + _DELETEWORKERDEPLOYMENTREQUEST._serialized_start = 43463 + _DELETEWORKERDEPLOYMENTREQUEST._serialized_end = 43556 + _DELETEWORKERDEPLOYMENTRESPONSE._serialized_start = 43558 + _DELETEWORKERDEPLOYMENTRESPONSE._serialized_end = 43590 + _UPDATEWORKERDEPLOYMENTVERSIONCOMPUTECONFIGREQUEST._serialized_start = 43593 + _UPDATEWORKERDEPLOYMENTVERSIONCOMPUTECONFIGREQUEST._serialized_end = 44109 + _UPDATEWORKERDEPLOYMENTVERSIONCOMPUTECONFIGREQUEST_COMPUTECONFIGSCALINGGROUPSENTRY._serialized_start = 43986 + _UPDATEWORKERDEPLOYMENTVERSIONCOMPUTECONFIGREQUEST_COMPUTECONFIGSCALINGGROUPSENTRY._serialized_end = 44109 + _UPDATEWORKERDEPLOYMENTVERSIONCOMPUTECONFIGRESPONSE._serialized_start = 44111 + _UPDATEWORKERDEPLOYMENTVERSIONCOMPUTECONFIGRESPONSE._serialized_end = 44163 + _VALIDATEWORKERDEPLOYMENTVERSIONCOMPUTECONFIGREQUEST._serialized_start = 44166 + _VALIDATEWORKERDEPLOYMENTVERSIONCOMPUTECONFIGREQUEST._serialized_end = 44666 + _VALIDATEWORKERDEPLOYMENTVERSIONCOMPUTECONFIGREQUEST_COMPUTECONFIGSCALINGGROUPSENTRY._serialized_start = 43986 + _VALIDATEWORKERDEPLOYMENTVERSIONCOMPUTECONFIGREQUEST_COMPUTECONFIGSCALINGGROUPSENTRY._serialized_end = 44109 + _VALIDATEWORKERDEPLOYMENTVERSIONCOMPUTECONFIGRESPONSE._serialized_start = 44668 + _VALIDATEWORKERDEPLOYMENTVERSIONCOMPUTECONFIGRESPONSE._serialized_end = 44722 + _UPDATEWORKERDEPLOYMENTVERSIONMETADATAREQUEST._serialized_start = 44725 + _UPDATEWORKERDEPLOYMENTVERSIONMETADATAREQUEST._serialized_end = 45143 + _UPDATEWORKERDEPLOYMENTVERSIONMETADATAREQUEST_UPSERTENTRIESENTRY._serialized_start = 45058 _UPDATEWORKERDEPLOYMENTVERSIONMETADATAREQUEST_UPSERTENTRIESENTRY._serialized_end = ( - 44281 + 45143 ) - _UPDATEWORKERDEPLOYMENTVERSIONMETADATARESPONSE._serialized_start = 44283 - _UPDATEWORKERDEPLOYMENTVERSIONMETADATARESPONSE._serialized_end = 44393 - _SETWORKERDEPLOYMENTMANAGERREQUEST._serialized_start = 44396 - _SETWORKERDEPLOYMENTMANAGERREQUEST._serialized_end = 44585 - _SETWORKERDEPLOYMENTMANAGERRESPONSE._serialized_start = 44587 - _SETWORKERDEPLOYMENTMANAGERRESPONSE._serialized_end = 44686 - _GETCURRENTDEPLOYMENTREQUEST._serialized_start = 44688 - _GETCURRENTDEPLOYMENTREQUEST._serialized_end = 44757 - _GETCURRENTDEPLOYMENTRESPONSE._serialized_start = 44759 - _GETCURRENTDEPLOYMENTRESPONSE._serialized_end = 44866 - _GETDEPLOYMENTREACHABILITYREQUEST._serialized_start = 44868 - _GETDEPLOYMENTREACHABILITYREQUEST._serialized_end = 44981 - _GETDEPLOYMENTREACHABILITYRESPONSE._serialized_start = 44984 - _GETDEPLOYMENTREACHABILITYRESPONSE._serialized_end = 45211 - _CREATEWORKFLOWRULEREQUEST._serialized_start = 45214 - _CREATEWORKFLOWRULEREQUEST._serialized_end = 45394 - _CREATEWORKFLOWRULERESPONSE._serialized_start = 45396 - _CREATEWORKFLOWRULERESPONSE._serialized_end = 45491 - _DESCRIBEWORKFLOWRULEREQUEST._serialized_start = 45493 - _DESCRIBEWORKFLOWRULEREQUEST._serialized_end = 45558 - _DESCRIBEWORKFLOWRULERESPONSE._serialized_start = 45560 - _DESCRIBEWORKFLOWRULERESPONSE._serialized_end = 45641 - _DELETEWORKFLOWRULEREQUEST._serialized_start = 45643 - _DELETEWORKFLOWRULEREQUEST._serialized_end = 45706 - _DELETEWORKFLOWRULERESPONSE._serialized_start = 45708 - _DELETEWORKFLOWRULERESPONSE._serialized_end = 45736 - _LISTWORKFLOWRULESREQUEST._serialized_start = 45738 - _LISTWORKFLOWRULESREQUEST._serialized_end = 45808 - _LISTWORKFLOWRULESRESPONSE._serialized_start = 45810 - _LISTWORKFLOWRULESRESPONSE._serialized_end = 45914 - _TRIGGERWORKFLOWRULEREQUEST._serialized_start = 45917 - _TRIGGERWORKFLOWRULEREQUEST._serialized_end = 46123 - _TRIGGERWORKFLOWRULERESPONSE._serialized_start = 46125 - _TRIGGERWORKFLOWRULERESPONSE._serialized_end = 46171 - _RECORDWORKERHEARTBEATREQUEST._serialized_start = 46174 - _RECORDWORKERHEARTBEATREQUEST._serialized_end = 46329 - _RECORDWORKERHEARTBEATRESPONSE._serialized_start = 46331 - _RECORDWORKERHEARTBEATRESPONSE._serialized_end = 46362 - _LISTWORKERSREQUEST._serialized_start = 46365 - _LISTWORKERSREQUEST._serialized_end = 46495 - _LISTWORKERSRESPONSE._serialized_start = 46498 - _LISTWORKERSRESPONSE._serialized_end = 46663 - _UPDATETASKQUEUECONFIGREQUEST._serialized_start = 46666 - _UPDATETASKQUEUECONFIGREQUEST._serialized_end = 47391 - _UPDATETASKQUEUECONFIGREQUEST_RATELIMITUPDATE._serialized_start = 47233 - _UPDATETASKQUEUECONFIGREQUEST_RATELIMITUPDATE._serialized_end = 47324 + _UPDATEWORKERDEPLOYMENTVERSIONMETADATARESPONSE._serialized_start = 45145 + _UPDATEWORKERDEPLOYMENTVERSIONMETADATARESPONSE._serialized_end = 45255 + _SETWORKERDEPLOYMENTMANAGERREQUEST._serialized_start = 45258 + _SETWORKERDEPLOYMENTMANAGERREQUEST._serialized_end = 45447 + _SETWORKERDEPLOYMENTMANAGERRESPONSE._serialized_start = 45449 + _SETWORKERDEPLOYMENTMANAGERRESPONSE._serialized_end = 45548 + _GETCURRENTDEPLOYMENTREQUEST._serialized_start = 45550 + _GETCURRENTDEPLOYMENTREQUEST._serialized_end = 45619 + _GETCURRENTDEPLOYMENTRESPONSE._serialized_start = 45621 + _GETCURRENTDEPLOYMENTRESPONSE._serialized_end = 45728 + _GETDEPLOYMENTREACHABILITYREQUEST._serialized_start = 45730 + _GETDEPLOYMENTREACHABILITYREQUEST._serialized_end = 45843 + _GETDEPLOYMENTREACHABILITYRESPONSE._serialized_start = 45846 + _GETDEPLOYMENTREACHABILITYRESPONSE._serialized_end = 46073 + _CREATEWORKFLOWRULEREQUEST._serialized_start = 46076 + _CREATEWORKFLOWRULEREQUEST._serialized_end = 46256 + _CREATEWORKFLOWRULERESPONSE._serialized_start = 46258 + _CREATEWORKFLOWRULERESPONSE._serialized_end = 46353 + _DESCRIBEWORKFLOWRULEREQUEST._serialized_start = 46355 + _DESCRIBEWORKFLOWRULEREQUEST._serialized_end = 46420 + _DESCRIBEWORKFLOWRULERESPONSE._serialized_start = 46422 + _DESCRIBEWORKFLOWRULERESPONSE._serialized_end = 46503 + _DELETEWORKFLOWRULEREQUEST._serialized_start = 46505 + _DELETEWORKFLOWRULEREQUEST._serialized_end = 46568 + _DELETEWORKFLOWRULERESPONSE._serialized_start = 46570 + _DELETEWORKFLOWRULERESPONSE._serialized_end = 46598 + _LISTWORKFLOWRULESREQUEST._serialized_start = 46600 + _LISTWORKFLOWRULESREQUEST._serialized_end = 46670 + _LISTWORKFLOWRULESRESPONSE._serialized_start = 46672 + _LISTWORKFLOWRULESRESPONSE._serialized_end = 46776 + _TRIGGERWORKFLOWRULEREQUEST._serialized_start = 46779 + _TRIGGERWORKFLOWRULEREQUEST._serialized_end = 46985 + _TRIGGERWORKFLOWRULERESPONSE._serialized_start = 46987 + _TRIGGERWORKFLOWRULERESPONSE._serialized_end = 47033 + _RECORDWORKERHEARTBEATREQUEST._serialized_start = 47036 + _RECORDWORKERHEARTBEATREQUEST._serialized_end = 47191 + _RECORDWORKERHEARTBEATRESPONSE._serialized_start = 47193 + _RECORDWORKERHEARTBEATRESPONSE._serialized_end = 47224 + _LISTWORKERSREQUEST._serialized_start = 47227 + _LISTWORKERSREQUEST._serialized_end = 47357 + _LISTWORKERSRESPONSE._serialized_start = 47360 + _LISTWORKERSRESPONSE._serialized_end = 47525 + _UPDATETASKQUEUECONFIGREQUEST._serialized_start = 47528 + _UPDATETASKQUEUECONFIGREQUEST._serialized_end = 48253 + _UPDATETASKQUEUECONFIGREQUEST_RATELIMITUPDATE._serialized_start = 48095 + _UPDATETASKQUEUECONFIGREQUEST_RATELIMITUPDATE._serialized_end = 48186 _UPDATETASKQUEUECONFIGREQUEST_SETFAIRNESSWEIGHTOVERRIDESENTRY._serialized_start = ( - 47326 + 48188 ) _UPDATETASKQUEUECONFIGREQUEST_SETFAIRNESSWEIGHTOVERRIDESENTRY._serialized_end = ( - 47391 + 48253 ) - _UPDATETASKQUEUECONFIGRESPONSE._serialized_start = 47393 - _UPDATETASKQUEUECONFIGRESPONSE._serialized_end = 47484 - _FETCHWORKERCONFIGREQUEST._serialized_start = 47487 - _FETCHWORKERCONFIGREQUEST._serialized_end = 47645 - _FETCHWORKERCONFIGRESPONSE._serialized_start = 47647 - _FETCHWORKERCONFIGRESPONSE._serialized_end = 47732 - _UPDATEWORKERCONFIGREQUEST._serialized_start = 47735 - _UPDATEWORKERCONFIGREQUEST._serialized_end = 48001 - _UPDATEWORKERCONFIGRESPONSE._serialized_start = 48003 - _UPDATEWORKERCONFIGRESPONSE._serialized_end = 48103 - _DESCRIBEWORKERREQUEST._serialized_start = 48105 - _DESCRIBEWORKERREQUEST._serialized_end = 48176 - _DESCRIBEWORKERRESPONSE._serialized_start = 48178 - _DESCRIBEWORKERRESPONSE._serialized_end = 48259 - _COUNTWORKERSREQUEST._serialized_start = 48261 - _COUNTWORKERSREQUEST._serialized_end = 48348 - _COUNTWORKERSRESPONSE._serialized_start = 48350 - _COUNTWORKERSRESPONSE._serialized_end = 48387 - _PAUSEWORKFLOWEXECUTIONREQUEST._serialized_start = 48390 - _PAUSEWORKFLOWEXECUTIONREQUEST._serialized_end = 48531 - _PAUSEWORKFLOWEXECUTIONRESPONSE._serialized_start = 48533 - _PAUSEWORKFLOWEXECUTIONRESPONSE._serialized_end = 48565 - _UNPAUSEWORKFLOWEXECUTIONREQUEST._serialized_start = 48568 - _UNPAUSEWORKFLOWEXECUTIONREQUEST._serialized_end = 48711 - _UNPAUSEWORKFLOWEXECUTIONRESPONSE._serialized_start = 48713 - _UNPAUSEWORKFLOWEXECUTIONRESPONSE._serialized_end = 48747 - _STARTACTIVITYEXECUTIONREQUEST._serialized_start = 48750 - _STARTACTIVITYEXECUTIONREQUEST._serialized_end = 49927 - _STARTACTIVITYEXECUTIONRESPONSE._serialized_start = 49929 - _STARTACTIVITYEXECUTIONRESPONSE._serialized_end = 50038 - _DESCRIBEACTIVITYEXECUTIONREQUEST._serialized_start = 50041 - _DESCRIBEACTIVITYEXECUTIONREQUEST._serialized_end = 50269 - _DESCRIBEACTIVITYEXECUTIONRESPONSE._serialized_start = 50272 - _DESCRIBEACTIVITYEXECUTIONRESPONSE._serialized_end = 50588 - _POLLACTIVITYEXECUTIONREQUEST._serialized_start = 50590 - _POLLACTIVITYEXECUTIONREQUEST._serialized_end = 50676 - _POLLACTIVITYEXECUTIONRESPONSE._serialized_start = 50678 - _POLLACTIVITYEXECUTIONRESPONSE._serialized_end = 50794 - _LISTACTIVITYEXECUTIONSREQUEST._serialized_start = 50796 - _LISTACTIVITYEXECUTIONSREQUEST._serialized_end = 50905 - _LISTACTIVITYEXECUTIONSRESPONSE._serialized_start = 50908 - _LISTACTIVITYEXECUTIONSRESPONSE._serialized_end = 51038 - _STARTNEXUSOPERATIONEXECUTIONREQUEST._serialized_start = 51041 - _STARTNEXUSOPERATIONEXECUTIONREQUEST._serialized_end = 51890 - _STARTNEXUSOPERATIONEXECUTIONREQUEST_NEXUSHEADERENTRY._serialized_start = 51840 - _STARTNEXUSOPERATIONEXECUTIONREQUEST_NEXUSHEADERENTRY._serialized_end = 51890 - _STARTNEXUSOPERATIONEXECUTIONRESPONSE._serialized_start = 51892 - _STARTNEXUSOPERATIONEXECUTIONRESPONSE._serialized_end = 51963 - _DESCRIBENEXUSOPERATIONEXECUTIONREQUEST._serialized_start = 51966 - _DESCRIBENEXUSOPERATIONEXECUTIONREQUEST._serialized_end = 52136 - _DESCRIBENEXUSOPERATIONEXECUTIONRESPONSE._serialized_start = 52139 - _DESCRIBENEXUSOPERATIONEXECUTIONRESPONSE._serialized_end = 52450 - _POLLNEXUSOPERATIONEXECUTIONREQUEST._serialized_start = 52453 - _POLLNEXUSOPERATIONEXECUTIONREQUEST._serialized_end = 52614 - _POLLNEXUSOPERATIONEXECUTIONRESPONSE._serialized_start = 52617 - _POLLNEXUSOPERATIONEXECUTIONRESPONSE._serialized_end = 52878 - _LISTNEXUSOPERATIONEXECUTIONSREQUEST._serialized_start = 52880 - _LISTNEXUSOPERATIONEXECUTIONSREQUEST._serialized_end = 52995 - _LISTNEXUSOPERATIONEXECUTIONSRESPONSE._serialized_start = 52998 - _LISTNEXUSOPERATIONEXECUTIONSRESPONSE._serialized_end = 53137 - _COUNTACTIVITYEXECUTIONSREQUEST._serialized_start = 53139 - _COUNTACTIVITYEXECUTIONSREQUEST._serialized_end = 53205 - _COUNTACTIVITYEXECUTIONSRESPONSE._serialized_start = 53208 - _COUNTACTIVITYEXECUTIONSRESPONSE._serialized_end = 53445 - _COUNTACTIVITYEXECUTIONSRESPONSE_AGGREGATIONGROUP._serialized_start = 19747 - _COUNTACTIVITYEXECUTIONSRESPONSE_AGGREGATIONGROUP._serialized_end = 19835 - _COUNTNEXUSOPERATIONEXECUTIONSREQUEST._serialized_start = 53447 - _COUNTNEXUSOPERATIONEXECUTIONSREQUEST._serialized_end = 53519 - _COUNTNEXUSOPERATIONEXECUTIONSRESPONSE._serialized_start = 53522 - _COUNTNEXUSOPERATIONEXECUTIONSRESPONSE._serialized_end = 53771 - _COUNTNEXUSOPERATIONEXECUTIONSRESPONSE_AGGREGATIONGROUP._serialized_start = 19747 - _COUNTNEXUSOPERATIONEXECUTIONSRESPONSE_AGGREGATIONGROUP._serialized_end = 19835 - _REQUESTCANCELACTIVITYEXECUTIONREQUEST._serialized_start = 53774 - _REQUESTCANCELACTIVITYEXECUTIONREQUEST._serialized_end = 53923 - _REQUESTCANCELACTIVITYEXECUTIONRESPONSE._serialized_start = 53925 - _REQUESTCANCELACTIVITYEXECUTIONRESPONSE._serialized_end = 53965 - _TERMINATEACTIVITYEXECUTIONREQUEST._serialized_start = 53968 - _TERMINATEACTIVITYEXECUTIONREQUEST._serialized_end = 54113 - _TERMINATEACTIVITYEXECUTIONRESPONSE._serialized_start = 54115 - _TERMINATEACTIVITYEXECUTIONRESPONSE._serialized_end = 54151 - _DELETEACTIVITYEXECUTIONREQUEST._serialized_start = 54153 - _DELETEACTIVITYEXECUTIONREQUEST._serialized_end = 54241 - _DELETEACTIVITYEXECUTIONRESPONSE._serialized_start = 54243 - _DELETEACTIVITYEXECUTIONRESPONSE._serialized_end = 54276 - _REQUESTCANCELNEXUSOPERATIONEXECUTIONREQUEST._serialized_start = 54279 - _REQUESTCANCELNEXUSOPERATIONEXECUTIONREQUEST._serialized_end = 54435 - _REQUESTCANCELNEXUSOPERATIONEXECUTIONRESPONSE._serialized_start = 54437 - _REQUESTCANCELNEXUSOPERATIONEXECUTIONRESPONSE._serialized_end = 54483 - _TERMINATENEXUSOPERATIONEXECUTIONREQUEST._serialized_start = 54486 - _TERMINATENEXUSOPERATIONEXECUTIONREQUEST._serialized_end = 54638 - _TERMINATENEXUSOPERATIONEXECUTIONRESPONSE._serialized_start = 54640 - _TERMINATENEXUSOPERATIONEXECUTIONRESPONSE._serialized_end = 54682 - _DELETENEXUSOPERATIONEXECUTIONREQUEST._serialized_start = 54684 - _DELETENEXUSOPERATIONEXECUTIONREQUEST._serialized_end = 54779 - _DELETENEXUSOPERATIONEXECUTIONRESPONSE._serialized_start = 54781 - _DELETENEXUSOPERATIONEXECUTIONRESPONSE._serialized_end = 54820 + _UPDATETASKQUEUECONFIGRESPONSE._serialized_start = 48255 + _UPDATETASKQUEUECONFIGRESPONSE._serialized_end = 48346 + _FETCHWORKERCONFIGREQUEST._serialized_start = 48349 + _FETCHWORKERCONFIGREQUEST._serialized_end = 48507 + _FETCHWORKERCONFIGRESPONSE._serialized_start = 48509 + _FETCHWORKERCONFIGRESPONSE._serialized_end = 48594 + _UPDATEWORKERCONFIGREQUEST._serialized_start = 48597 + _UPDATEWORKERCONFIGREQUEST._serialized_end = 48863 + _UPDATEWORKERCONFIGRESPONSE._serialized_start = 48865 + _UPDATEWORKERCONFIGRESPONSE._serialized_end = 48965 + _DESCRIBEWORKERREQUEST._serialized_start = 48967 + _DESCRIBEWORKERREQUEST._serialized_end = 49038 + _DESCRIBEWORKERRESPONSE._serialized_start = 49040 + _DESCRIBEWORKERRESPONSE._serialized_end = 49121 + _COUNTWORKERSREQUEST._serialized_start = 49123 + _COUNTWORKERSREQUEST._serialized_end = 49210 + _COUNTWORKERSRESPONSE._serialized_start = 49212 + _COUNTWORKERSRESPONSE._serialized_end = 49249 + _PAUSEWORKFLOWEXECUTIONREQUEST._serialized_start = 49252 + _PAUSEWORKFLOWEXECUTIONREQUEST._serialized_end = 49393 + _PAUSEWORKFLOWEXECUTIONRESPONSE._serialized_start = 49395 + _PAUSEWORKFLOWEXECUTIONRESPONSE._serialized_end = 49427 + _UNPAUSEWORKFLOWEXECUTIONREQUEST._serialized_start = 49430 + _UNPAUSEWORKFLOWEXECUTIONREQUEST._serialized_end = 49573 + _UNPAUSEWORKFLOWEXECUTIONRESPONSE._serialized_start = 49575 + _UNPAUSEWORKFLOWEXECUTIONRESPONSE._serialized_end = 49609 + _STARTACTIVITYEXECUTIONREQUEST._serialized_start = 49612 + _STARTACTIVITYEXECUTIONREQUEST._serialized_end = 50789 + _STARTACTIVITYEXECUTIONRESPONSE._serialized_start = 50791 + _STARTACTIVITYEXECUTIONRESPONSE._serialized_end = 50900 + _DESCRIBEACTIVITYEXECUTIONREQUEST._serialized_start = 50903 + _DESCRIBEACTIVITYEXECUTIONREQUEST._serialized_end = 51131 + _DESCRIBEACTIVITYEXECUTIONRESPONSE._serialized_start = 51134 + _DESCRIBEACTIVITYEXECUTIONRESPONSE._serialized_end = 51450 + _POLLACTIVITYEXECUTIONREQUEST._serialized_start = 51452 + _POLLACTIVITYEXECUTIONREQUEST._serialized_end = 51538 + _POLLACTIVITYEXECUTIONRESPONSE._serialized_start = 51540 + _POLLACTIVITYEXECUTIONRESPONSE._serialized_end = 51656 + _LISTACTIVITYEXECUTIONSREQUEST._serialized_start = 51658 + _LISTACTIVITYEXECUTIONSREQUEST._serialized_end = 51767 + _LISTACTIVITYEXECUTIONSRESPONSE._serialized_start = 51770 + _LISTACTIVITYEXECUTIONSRESPONSE._serialized_end = 51900 + _STARTNEXUSOPERATIONEXECUTIONREQUEST._serialized_start = 51903 + _STARTNEXUSOPERATIONEXECUTIONREQUEST._serialized_end = 52752 + _STARTNEXUSOPERATIONEXECUTIONREQUEST_NEXUSHEADERENTRY._serialized_start = 52702 + _STARTNEXUSOPERATIONEXECUTIONREQUEST_NEXUSHEADERENTRY._serialized_end = 52752 + _STARTNEXUSOPERATIONEXECUTIONRESPONSE._serialized_start = 52754 + _STARTNEXUSOPERATIONEXECUTIONRESPONSE._serialized_end = 52825 + _DESCRIBENEXUSOPERATIONEXECUTIONREQUEST._serialized_start = 52828 + _DESCRIBENEXUSOPERATIONEXECUTIONREQUEST._serialized_end = 52998 + _DESCRIBENEXUSOPERATIONEXECUTIONRESPONSE._serialized_start = 53001 + _DESCRIBENEXUSOPERATIONEXECUTIONRESPONSE._serialized_end = 53312 + _POLLNEXUSOPERATIONEXECUTIONREQUEST._serialized_start = 53315 + _POLLNEXUSOPERATIONEXECUTIONREQUEST._serialized_end = 53476 + _POLLNEXUSOPERATIONEXECUTIONRESPONSE._serialized_start = 53479 + _POLLNEXUSOPERATIONEXECUTIONRESPONSE._serialized_end = 53740 + _LISTNEXUSOPERATIONEXECUTIONSREQUEST._serialized_start = 53742 + _LISTNEXUSOPERATIONEXECUTIONSREQUEST._serialized_end = 53857 + _LISTNEXUSOPERATIONEXECUTIONSRESPONSE._serialized_start = 53860 + _LISTNEXUSOPERATIONEXECUTIONSRESPONSE._serialized_end = 53999 + _COUNTACTIVITYEXECUTIONSREQUEST._serialized_start = 54001 + _COUNTACTIVITYEXECUTIONSREQUEST._serialized_end = 54067 + _COUNTACTIVITYEXECUTIONSRESPONSE._serialized_start = 54070 + _COUNTACTIVITYEXECUTIONSRESPONSE._serialized_end = 54307 + _COUNTACTIVITYEXECUTIONSRESPONSE_AGGREGATIONGROUP._serialized_start = 20091 + _COUNTACTIVITYEXECUTIONSRESPONSE_AGGREGATIONGROUP._serialized_end = 20179 + _COUNTNEXUSOPERATIONEXECUTIONSREQUEST._serialized_start = 54309 + _COUNTNEXUSOPERATIONEXECUTIONSREQUEST._serialized_end = 54381 + _COUNTNEXUSOPERATIONEXECUTIONSRESPONSE._serialized_start = 54384 + _COUNTNEXUSOPERATIONEXECUTIONSRESPONSE._serialized_end = 54633 + _COUNTNEXUSOPERATIONEXECUTIONSRESPONSE_AGGREGATIONGROUP._serialized_start = 20091 + _COUNTNEXUSOPERATIONEXECUTIONSRESPONSE_AGGREGATIONGROUP._serialized_end = 20179 + _REQUESTCANCELACTIVITYEXECUTIONREQUEST._serialized_start = 54636 + _REQUESTCANCELACTIVITYEXECUTIONREQUEST._serialized_end = 54785 + _REQUESTCANCELACTIVITYEXECUTIONRESPONSE._serialized_start = 54787 + _REQUESTCANCELACTIVITYEXECUTIONRESPONSE._serialized_end = 54827 + _TERMINATEACTIVITYEXECUTIONREQUEST._serialized_start = 54830 + _TERMINATEACTIVITYEXECUTIONREQUEST._serialized_end = 54975 + _TERMINATEACTIVITYEXECUTIONRESPONSE._serialized_start = 54977 + _TERMINATEACTIVITYEXECUTIONRESPONSE._serialized_end = 55013 + _DELETEACTIVITYEXECUTIONREQUEST._serialized_start = 55015 + _DELETEACTIVITYEXECUTIONREQUEST._serialized_end = 55103 + _DELETEACTIVITYEXECUTIONRESPONSE._serialized_start = 55105 + _DELETEACTIVITYEXECUTIONRESPONSE._serialized_end = 55138 + _REQUESTCANCELNEXUSOPERATIONEXECUTIONREQUEST._serialized_start = 55141 + _REQUESTCANCELNEXUSOPERATIONEXECUTIONREQUEST._serialized_end = 55297 + _REQUESTCANCELNEXUSOPERATIONEXECUTIONRESPONSE._serialized_start = 55299 + _REQUESTCANCELNEXUSOPERATIONEXECUTIONRESPONSE._serialized_end = 55345 + _TERMINATENEXUSOPERATIONEXECUTIONREQUEST._serialized_start = 55348 + _TERMINATENEXUSOPERATIONEXECUTIONREQUEST._serialized_end = 55500 + _TERMINATENEXUSOPERATIONEXECUTIONRESPONSE._serialized_start = 55502 + _TERMINATENEXUSOPERATIONEXECUTIONRESPONSE._serialized_end = 55544 + _DELETENEXUSOPERATIONEXECUTIONREQUEST._serialized_start = 55546 + _DELETENEXUSOPERATIONEXECUTIONREQUEST._serialized_end = 55641 + _DELETENEXUSOPERATIONEXECUTIONRESPONSE._serialized_start = 55643 + _DELETENEXUSOPERATIONEXECUTIONRESPONSE._serialized_end = 55682 # @@protoc_insertion_point(module_scope) diff --git a/temporalio/api/workflowservice/v1/request_response_pb2.pyi b/temporalio/api/workflowservice/v1/request_response_pb2.pyi index 8f1069d3d..f5f3a05bb 100644 --- a/temporalio/api/workflowservice/v1/request_response_pb2.pyi +++ b/temporalio/api/workflowservice/v1/request_response_pb2.pyi @@ -305,6 +305,7 @@ class DescribeNamespaceResponse(google.protobuf.message.Message): IS_GLOBAL_NAMESPACE_FIELD_NUMBER: builtins.int FAILOVER_HISTORY_FIELD_NUMBER: builtins.int POLLER_GROUP_INFOS_FIELD_NUMBER: builtins.int + POLLER_GROUPS_INFO_FIELD_NUMBER: builtins.int @property def namespace_info( self, @@ -332,10 +333,20 @@ class DescribeNamespaceResponse(google.protobuf.message.Message): ) -> google.protobuf.internal.containers.RepeatedCompositeFieldContainer[ temporalio.api.taskqueue.v1.message_pb2.PollerGroupInfo ]: - """The initial info that client should use for poller group assignment. This information is + """Deprecated. Use `poller_groups_info` instead, which carries a version so the client can + ignore stale updates. + The initial info that client should use for poller group assignment. This information is updated through poll response. Client is supposed to use the info received in the latest poll response. """ + @property + def poller_groups_info( + self, + ) -> temporalio.api.taskqueue.v1.message_pb2.PollerGroupsInfo: + """The initial, versioned info that client should use for poller group assignment. This + information is updated through poll responses. Client is supposed to use the info with the + highest version it has received. + """ def __init__( self, *, @@ -354,6 +365,8 @@ class DescribeNamespaceResponse(google.protobuf.message.Message): temporalio.api.taskqueue.v1.message_pb2.PollerGroupInfo ] | None = ..., + poller_groups_info: temporalio.api.taskqueue.v1.message_pb2.PollerGroupsInfo + | None = ..., ) -> None: ... def HasField( self, @@ -362,6 +375,8 @@ class DescribeNamespaceResponse(google.protobuf.message.Message): b"config", "namespace_info", b"namespace_info", + "poller_groups_info", + b"poller_groups_info", "replication_config", b"replication_config", ], @@ -381,6 +396,8 @@ class DescribeNamespaceResponse(google.protobuf.message.Message): b"namespace_info", "poller_group_infos", b"poller_group_infos", + "poller_groups_info", + b"poller_groups_info", "replication_config", b"replication_config", ], @@ -656,8 +673,8 @@ class StartWorkflowExecutionRequest(google.protobuf.message.Message): ) -> temporalio.api.common.v1.message_pb2.Payloads: ... @property def workflow_start_delay(self) -> google.protobuf.duration_pb2.Duration: - """Time to wait before dispatching the first workflow task. Cannot be used with `cron_schedule`. - If the workflow gets a signal before the delay, a workflow task will be dispatched and the rest + """Time to wait before making the first workflow task available for dispatch. Cannot be used with `cron_schedule`. + If the workflow gets a signal before the delay, a workflow task will be made available for dispatch and the rest of the delay will be ignored. """ @property @@ -869,12 +886,15 @@ class StartWorkflowExecutionResponse(google.protobuf.message.Message): DESCRIPTOR: google.protobuf.descriptor.Descriptor RUN_ID_FIELD_NUMBER: builtins.int + FIRST_EXECUTION_RUN_ID_FIELD_NUMBER: builtins.int STARTED_FIELD_NUMBER: builtins.int STATUS_FIELD_NUMBER: builtins.int EAGER_WORKFLOW_TASK_FIELD_NUMBER: builtins.int LINK_FIELD_NUMBER: builtins.int run_id: builtins.str """The run id of the workflow that was started - or used (via WorkflowIdConflictPolicy USE_EXISTING).""" + first_execution_run_id: builtins.str + """If the workflow was started as a result of a de-dupe, this field will contain the run id of the first execution in the chain.""" started: builtins.bool """If true, a new workflow was started.""" status: temporalio.api.enums.v1.workflow_pb2.WorkflowExecutionStatus.ValueType @@ -894,6 +914,7 @@ class StartWorkflowExecutionResponse(google.protobuf.message.Message): self, *, run_id: builtins.str = ..., + first_execution_run_id: builtins.str = ..., started: builtins.bool = ..., status: temporalio.api.enums.v1.workflow_pb2.WorkflowExecutionStatus.ValueType = ..., eager_workflow_task: global___PollWorkflowTaskQueueResponse | None = ..., @@ -910,6 +931,8 @@ class StartWorkflowExecutionResponse(google.protobuf.message.Message): field_name: typing_extensions.Literal[ "eager_workflow_task", b"eager_workflow_task", + "first_execution_run_id", + b"first_execution_run_id", "link", b"link", "run_id", @@ -1253,6 +1276,7 @@ class PollWorkflowTaskQueueResponse(google.protobuf.message.Message): POLLER_SCALING_DECISION_FIELD_NUMBER: builtins.int POLLER_GROUP_ID_FIELD_NUMBER: builtins.int POLLER_GROUP_INFOS_FIELD_NUMBER: builtins.int + POLLER_GROUPS_INFO_FIELD_NUMBER: builtins.int task_token: builtins.bytes """A unique identifier for this task""" @property @@ -1346,13 +1370,27 @@ class PollWorkflowTaskQueueResponse(google.protobuf.message.Message): ) -> google.protobuf.internal.containers.RepeatedCompositeFieldContainer[ temporalio.api.taskqueue.v1.message_pb2.PollerGroupInfo ]: - """The weighted list of poller groups IDs that client should use for future polls to this task + """Deprecated. Use `poller_groups_info` instead, which carries a version so the client can + ignore stale updates. + The weighted list of poller groups IDs that client should use for future polls to this task queue. Client is expected to: 1. Maintain minimum number of pollers no less than the number of groups. 2. Try to assign the next poll to a group without any pending polls, 3. If every group has some pending polls, assign the next poll to a group randomly according to the weights. """ + @property + def poller_groups_info( + self, + ) -> temporalio.api.taskqueue.v1.message_pb2.PollerGroupsInfo: + """The weighted, versioned list of poller groups IDs that client should use for future polls to + this task queue. Client should ignore this if it has already applied a snapshot with a + version greater than or equal to `poller_groups_info.version`. Client is expected to: + 1. Maintain minimum number of pollers no less than the number of groups. + 2. Try to assign the next poll to a group without any pending polls, + 3. If every group has some pending polls, assign the next poll to a group randomly + according to the weights. + """ def __init__( self, *, @@ -1386,12 +1424,16 @@ class PollWorkflowTaskQueueResponse(google.protobuf.message.Message): temporalio.api.taskqueue.v1.message_pb2.PollerGroupInfo ] | None = ..., + poller_groups_info: temporalio.api.taskqueue.v1.message_pb2.PollerGroupsInfo + | None = ..., ) -> None: ... def HasField( self, field_name: typing_extensions.Literal[ "history", b"history", + "poller_groups_info", + b"poller_groups_info", "poller_scaling_decision", b"poller_scaling_decision", "query", @@ -1425,6 +1467,8 @@ class PollWorkflowTaskQueueResponse(google.protobuf.message.Message): b"poller_group_id", "poller_group_infos", b"poller_group_infos", + "poller_groups_info", + b"poller_groups_info", "poller_scaling_decision", b"poller_scaling_decision", "previous_started_event_id", @@ -1524,6 +1568,8 @@ class RespondWorkflowTaskCompletedRequest(google.protobuf.message.Message): DEPLOYMENT_OPTIONS_FIELD_NUMBER: builtins.int WORKER_INSTANCE_KEY_FIELD_NUMBER: builtins.int WORKER_CONTROL_TASK_QUEUE_FIELD_NUMBER: builtins.int + PAGE_NUMBER_FIELD_NUMBER: builtins.int + INTERMEDIATE_PAGE_FIELD_NUMBER: builtins.int task_token: builtins.bytes """The task token as received in `PollWorkflowTaskQueueResponse`""" @property @@ -1622,6 +1668,16 @@ class RespondWorkflowTaskCompletedRequest(google.protobuf.message.Message): """A dedicated per-worker Nexus task queue on which the server sends control tasks (e.g. activity cancellation) to this specific worker instance. """ + page_number: builtins.int + """0-indexed page number when the workflow task completion is split across multiple + requests ("pages"). 0 for single-page requests. May only be set to non-zero value + when the namespace capability workflow_task_completion_pagination is true. + """ + intermediate_page: builtins.bool + """True for non-final pages of a paginated workflow task completion. The final page's + `page_number` tells the server how many intermediate pages (0..page_number-1) preceded it. + May only be used when the namespace capability workflow_task_completion_pagination is true. + """ def __init__( self, *, @@ -1660,6 +1716,8 @@ class RespondWorkflowTaskCompletedRequest(google.protobuf.message.Message): | None = ..., worker_instance_key: builtins.str = ..., worker_control_task_queue: builtins.str = ..., + page_number: builtins.int = ..., + intermediate_page: builtins.bool = ..., ) -> None: ... def HasField( self, @@ -1697,12 +1755,16 @@ class RespondWorkflowTaskCompletedRequest(google.protobuf.message.Message): b"force_create_new_workflow_task", "identity", b"identity", + "intermediate_page", + b"intermediate_page", "messages", b"messages", "metering_metadata", b"metering_metadata", "namespace", b"namespace", + "page_number", + b"page_number", "query_results", b"query_results", "resource_id", @@ -2030,6 +2092,7 @@ class PollActivityTaskQueueResponse(google.protobuf.message.Message): PRIORITY_FIELD_NUMBER: builtins.int ACTIVITY_RUN_ID_FIELD_NUMBER: builtins.int POLLER_GROUP_INFOS_FIELD_NUMBER: builtins.int + POLLER_GROUPS_INFO_FIELD_NUMBER: builtins.int task_token: builtins.bytes """A unique identifier for this task""" workflow_namespace: builtins.str @@ -2123,6 +2186,18 @@ class PollActivityTaskQueueResponse(google.protobuf.message.Message): 3. If every group has some pending polls, assign the next poll to a group randomly according to the weights. """ + @property + def poller_groups_info( + self, + ) -> temporalio.api.taskqueue.v1.message_pb2.PollerGroupsInfo: + """The weighted, versioned list of poller groups IDs that client should use for future polls to + this task queue. Client should ignore this if it has already applied a snapshot with a + version greater than or equal to `poller_groups_info.version`. Client is expected to: + 1. Maintain minimum number of pollers no less than the number of groups. + 2. Try to assign the next poll to a group without any pending polls, + 3. If every group has some pending polls, assign the next poll to a group randomly + according to the weights. + """ def __init__( self, *, @@ -2153,6 +2228,8 @@ class PollActivityTaskQueueResponse(google.protobuf.message.Message): temporalio.api.taskqueue.v1.message_pb2.PollerGroupInfo ] | None = ..., + poller_groups_info: temporalio.api.taskqueue.v1.message_pb2.PollerGroupsInfo + | None = ..., ) -> None: ... def HasField( self, @@ -2169,6 +2246,8 @@ class PollActivityTaskQueueResponse(google.protobuf.message.Message): b"heartbeat_timeout", "input", b"input", + "poller_groups_info", + b"poller_groups_info", "poller_scaling_decision", b"poller_scaling_decision", "priority", @@ -2212,6 +2291,8 @@ class PollActivityTaskQueueResponse(google.protobuf.message.Message): b"input", "poller_group_infos", b"poller_group_infos", + "poller_groups_info", + b"poller_groups_info", "poller_scaling_decision", b"poller_scaling_decision", "priority", @@ -3310,9 +3391,9 @@ class SignalWithStartWorkflowExecutionRequest(google.protobuf.message.Message): def header(self) -> temporalio.api.common.v1.message_pb2.Header: ... @property def workflow_start_delay(self) -> google.protobuf.duration_pb2.Duration: - """Time to wait before dispatching the first workflow task. Cannot be used with `cron_schedule`. + """Time to wait before making the first workflow task available for dispatch. Cannot be used with `cron_schedule`. Note that the signal will be delivered with the first workflow task. If the workflow gets - another SignalWithStartWorkflow before the delay a workflow task will be dispatched immediately + another SignalWithStartWorkflow before the delay a workflow task will be made available for dispatch immediately and the rest of the delay period will be ignored, even if that request also had a delay. Signal via SignalWorkflowExecution will not unblock the workflow. """ @@ -3482,10 +3563,13 @@ class SignalWithStartWorkflowExecutionResponse(google.protobuf.message.Message): DESCRIPTOR: google.protobuf.descriptor.Descriptor RUN_ID_FIELD_NUMBER: builtins.int + FIRST_EXECUTION_RUN_ID_FIELD_NUMBER: builtins.int STARTED_FIELD_NUMBER: builtins.int SIGNAL_LINK_FIELD_NUMBER: builtins.int run_id: builtins.str """The run id of the workflow that was started - or just signaled, if it was already running.""" + first_execution_run_id: builtins.str + """If the workflow was started as a result of a de-dupe, this field will contain the run id of the first execution in the chain.""" started: builtins.bool """If true, a new workflow was started.""" @property @@ -3498,6 +3582,7 @@ class SignalWithStartWorkflowExecutionResponse(google.protobuf.message.Message): self, *, run_id: builtins.str = ..., + first_execution_run_id: builtins.str = ..., started: builtins.bool = ..., signal_link: temporalio.api.common.v1.message_pb2.Link | None = ..., ) -> None: ... @@ -3507,7 +3592,14 @@ class SignalWithStartWorkflowExecutionResponse(google.protobuf.message.Message): def ClearField( self, field_name: typing_extensions.Literal[ - "run_id", b"run_id", "signal_link", b"signal_link", "started", b"started" + "first_execution_run_id", + b"first_execution_run_id", + "run_id", + b"run_id", + "signal_link", + b"signal_link", + "started", + b"started", ], ) -> None: ... @@ -5229,6 +5321,7 @@ class GetSystemInfoResponse(google.protobuf.message.Message): COUNT_GROUP_BY_EXECUTION_STATUS_FIELD_NUMBER: builtins.int NEXUS_FIELD_NUMBER: builtins.int SERVER_SCALED_DEPLOYMENTS_FIELD_NUMBER: builtins.int + SERVER_SCALED_PROVIDER_CLOUD_RUN_FIELD_NUMBER: builtins.int signal_and_query_header: builtins.bool """True if signal and query headers are supported.""" internal_error_differentiation: builtins.bool @@ -5270,6 +5363,11 @@ class GetSystemInfoResponse(google.protobuf.message.Message): This flag is dependent both on server version and for server-scaled deployments to be enabled via server configuration. """ + server_scaled_provider_cloud_run: builtins.bool + """True if the server supports the Cloud Run compute provider for + server-scaled deployments. Dependent on server version and the + provider being enabled via server configuration. + """ def __init__( self, *, @@ -5285,6 +5383,7 @@ class GetSystemInfoResponse(google.protobuf.message.Message): count_group_by_execution_status: builtins.bool = ..., nexus: builtins.bool = ..., server_scaled_deployments: builtins.bool = ..., + server_scaled_provider_cloud_run: builtins.bool = ..., ) -> None: ... def ClearField( self, @@ -5307,6 +5406,8 @@ class GetSystemInfoResponse(google.protobuf.message.Message): b"sdk_metadata", "server_scaled_deployments", b"server_scaled_deployments", + "server_scaled_provider_cloud_run", + b"server_scaled_provider_cloud_run", "signal_and_query_header", b"signal_and_query_header", "supports_schedules", @@ -7032,6 +7133,7 @@ class StartBatchOperationRequest(google.protobuf.message.Message): JOB_ID_FIELD_NUMBER: builtins.int REASON_FIELD_NUMBER: builtins.int EXECUTIONS_FIELD_NUMBER: builtins.int + TARGET_EXECUTIONS_FIELD_NUMBER: builtins.int MAX_OPERATIONS_PER_SECOND_FIELD_NUMBER: builtins.int TERMINATION_OPERATION_FIELD_NUMBER: builtins.int SIGNAL_OPERATION_FIELD_NUMBER: builtins.int @@ -7042,6 +7144,9 @@ class StartBatchOperationRequest(google.protobuf.message.Message): UNPAUSE_ACTIVITIES_OPERATION_FIELD_NUMBER: builtins.int RESET_ACTIVITIES_OPERATION_FIELD_NUMBER: builtins.int UPDATE_ACTIVITY_OPTIONS_OPERATION_FIELD_NUMBER: builtins.int + CANCEL_ACTIVITIES_OPERATION_FIELD_NUMBER: builtins.int + TERMINATE_ACTIVITIES_OPERATION_FIELD_NUMBER: builtins.int + DELETE_ACTIVITIES_OPERATION_FIELD_NUMBER: builtins.int namespace: builtins.str """Namespace that contains the batch operation""" visibility_query: builtins.str @@ -7060,6 +7165,16 @@ class StartBatchOperationRequest(google.protobuf.message.Message): ]: """Executions to apply the batch operation This field and `visibility_query` are mutually exclusive + DEPRECATED: Use `target_executions` instead. + """ + @property + def target_executions( + self, + ) -> google.protobuf.internal.containers.RepeatedCompositeFieldContainer[ + temporalio.api.common.v1.message_pb2.Execution + ]: + """Target executions to apply the batch operation. This field and `visibility_query` + are mutually exclusive. """ max_operations_per_second: builtins.float """Limit for the number of operations processed per second within this batch. @@ -7107,6 +7222,18 @@ class StartBatchOperationRequest(google.protobuf.message.Message): def update_activity_options_operation( self, ) -> temporalio.api.batch.v1.message_pb2.BatchOperationUpdateActivityOptions: ... + @property + def cancel_activities_operation( + self, + ) -> temporalio.api.batch.v1.message_pb2.BatchOperationCancelActivities: ... + @property + def terminate_activities_operation( + self, + ) -> temporalio.api.batch.v1.message_pb2.BatchOperationTerminateActivities: ... + @property + def delete_activities_operation( + self, + ) -> temporalio.api.batch.v1.message_pb2.BatchOperationDeleteActivities: ... def __init__( self, *, @@ -7118,6 +7245,10 @@ class StartBatchOperationRequest(google.protobuf.message.Message): temporalio.api.common.v1.message_pb2.WorkflowExecution ] | None = ..., + target_executions: collections.abc.Iterable[ + temporalio.api.common.v1.message_pb2.Execution + ] + | None = ..., max_operations_per_second: builtins.float = ..., termination_operation: temporalio.api.batch.v1.message_pb2.BatchOperationTermination | None = ..., @@ -7137,12 +7268,22 @@ class StartBatchOperationRequest(google.protobuf.message.Message): | None = ..., update_activity_options_operation: temporalio.api.batch.v1.message_pb2.BatchOperationUpdateActivityOptions | None = ..., + cancel_activities_operation: temporalio.api.batch.v1.message_pb2.BatchOperationCancelActivities + | None = ..., + terminate_activities_operation: temporalio.api.batch.v1.message_pb2.BatchOperationTerminateActivities + | None = ..., + delete_activities_operation: temporalio.api.batch.v1.message_pb2.BatchOperationDeleteActivities + | None = ..., ) -> None: ... def HasField( self, field_name: typing_extensions.Literal[ + "cancel_activities_operation", + b"cancel_activities_operation", "cancellation_operation", b"cancellation_operation", + "delete_activities_operation", + b"delete_activities_operation", "deletion_operation", b"deletion_operation", "operation", @@ -7153,6 +7294,8 @@ class StartBatchOperationRequest(google.protobuf.message.Message): b"reset_operation", "signal_operation", b"signal_operation", + "terminate_activities_operation", + b"terminate_activities_operation", "termination_operation", b"termination_operation", "unpause_activities_operation", @@ -7166,8 +7309,12 @@ class StartBatchOperationRequest(google.protobuf.message.Message): def ClearField( self, field_name: typing_extensions.Literal[ + "cancel_activities_operation", + b"cancel_activities_operation", "cancellation_operation", b"cancellation_operation", + "delete_activities_operation", + b"delete_activities_operation", "deletion_operation", b"deletion_operation", "executions", @@ -7188,6 +7335,10 @@ class StartBatchOperationRequest(google.protobuf.message.Message): b"reset_operation", "signal_operation", b"signal_operation", + "target_executions", + b"target_executions", + "terminate_activities_operation", + b"terminate_activities_operation", "termination_operation", b"termination_operation", "unpause_activities_operation", @@ -7213,6 +7364,9 @@ class StartBatchOperationRequest(google.protobuf.message.Message): "unpause_activities_operation", "reset_activities_operation", "update_activity_options_operation", + "cancel_activities_operation", + "terminate_activities_operation", + "delete_activities_operation", ] | None ): ... @@ -7313,6 +7467,8 @@ class DescribeBatchOperationResponse(google.protobuf.message.Message): FAILURE_OPERATION_COUNT_FIELD_NUMBER: builtins.int IDENTITY_FIELD_NUMBER: builtins.int REASON_FIELD_NUMBER: builtins.int + QUERY_FIELD_NUMBER: builtins.int + EXECUTIONS_FIELD_NUMBER: builtins.int operation_type: ( temporalio.api.enums.v1.batch_operation_pb2.BatchOperationType.ValueType ) @@ -7337,6 +7493,15 @@ class DescribeBatchOperationResponse(google.protobuf.message.Message): """Identity indicates the operator identity""" reason: builtins.str """Reason indicates the reason to stop a operation""" + query: builtins.str + """Query is the visibility query that defines the group of workflow to apply the batch operation""" + @property + def executions( + self, + ) -> google.protobuf.internal.containers.RepeatedCompositeFieldContainer[ + temporalio.api.common.v1.message_pb2.Execution + ]: + """Executions is the list of workflow OR standalone activity executions to apply the batch operation""" def __init__( self, *, @@ -7350,6 +7515,11 @@ class DescribeBatchOperationResponse(google.protobuf.message.Message): failure_operation_count: builtins.int = ..., identity: builtins.str = ..., reason: builtins.str = ..., + query: builtins.str = ..., + executions: collections.abc.Iterable[ + temporalio.api.common.v1.message_pb2.Execution + ] + | None = ..., ) -> None: ... def HasField( self, @@ -7364,6 +7534,8 @@ class DescribeBatchOperationResponse(google.protobuf.message.Message): b"close_time", "complete_operation_count", b"complete_operation_count", + "executions", + b"executions", "failure_operation_count", b"failure_operation_count", "identity", @@ -7372,6 +7544,8 @@ class DescribeBatchOperationResponse(google.protobuf.message.Message): b"job_id", "operation_type", b"operation_type", + "query", + b"query", "reason", b"reason", "start_time", @@ -7657,6 +7831,7 @@ class PollNexusTaskQueueResponse(google.protobuf.message.Message): POLLER_SCALING_DECISION_FIELD_NUMBER: builtins.int POLLER_GROUP_ID_FIELD_NUMBER: builtins.int POLLER_GROUP_INFOS_FIELD_NUMBER: builtins.int + POLLER_GROUPS_INFO_FIELD_NUMBER: builtins.int task_token: builtins.bytes """An opaque unique identifier for this task for correlating a completion request the embedded request.""" @property @@ -7686,6 +7861,18 @@ class PollNexusTaskQueueResponse(google.protobuf.message.Message): 3. If every group has some pending polls, assign the next poll to a group randomly according to the weights. """ + @property + def poller_groups_info( + self, + ) -> temporalio.api.taskqueue.v1.message_pb2.PollerGroupsInfo: + """The weighted, versioned list of poller groups IDs that client should use for future polls to + this task queue. Client should ignore this if it has already applied a snapshot with a + version greater than or equal to `poller_groups_info.version`. Client is expected to: + 1. Maintain minimum number of pollers no less than the number of groups. + 2. Try to assign the next poll to a group without any pending polls, + 3. If every group has some pending polls, assign the next poll to a group randomly + according to the weights. + """ def __init__( self, *, @@ -7698,11 +7885,18 @@ class PollNexusTaskQueueResponse(google.protobuf.message.Message): temporalio.api.taskqueue.v1.message_pb2.PollerGroupInfo ] | None = ..., + poller_groups_info: temporalio.api.taskqueue.v1.message_pb2.PollerGroupsInfo + | None = ..., ) -> None: ... def HasField( self, field_name: typing_extensions.Literal[ - "poller_scaling_decision", b"poller_scaling_decision", "request", b"request" + "poller_groups_info", + b"poller_groups_info", + "poller_scaling_decision", + b"poller_scaling_decision", + "request", + b"request", ], ) -> builtins.bool: ... def ClearField( @@ -7712,6 +7906,8 @@ class PollNexusTaskQueueResponse(google.protobuf.message.Message): b"poller_group_id", "poller_group_infos", b"poller_group_infos", + "poller_groups_info", + b"poller_groups_info", "poller_scaling_decision", b"poller_scaling_decision", "request", @@ -8748,7 +8944,6 @@ class ResetActivityExecutionRequest(google.protobuf.message.Message): ACTIVITY_ID_FIELD_NUMBER: builtins.int RUN_ID_FIELD_NUMBER: builtins.int IDENTITY_FIELD_NUMBER: builtins.int - RESET_HEARTBEAT_FIELD_NUMBER: builtins.int KEEP_PAUSED_FIELD_NUMBER: builtins.int JITTER_FIELD_NUMBER: builtins.int RESTORE_ORIGINAL_OPTIONS_FIELD_NUMBER: builtins.int @@ -8765,10 +8960,6 @@ class ResetActivityExecutionRequest(google.protobuf.message.Message): """Run ID of the workflow or standalone activity.""" identity: builtins.str """The identity of the client who initiated this request.""" - reset_heartbeat: builtins.bool - """Indicates that activity should reset heartbeat details. - This flag will be applied only to the new instance of the activity. - """ keep_paused: builtins.bool """If activity is paused, it will remain paused after reset""" @property @@ -8791,7 +8982,6 @@ class ResetActivityExecutionRequest(google.protobuf.message.Message): activity_id: builtins.str = ..., run_id: builtins.str = ..., identity: builtins.str = ..., - reset_heartbeat: builtins.bool = ..., keep_paused: builtins.bool = ..., jitter: google.protobuf.duration_pb2.Duration | None = ..., restore_original_options: builtins.bool = ..., @@ -8813,8 +9003,6 @@ class ResetActivityExecutionRequest(google.protobuf.message.Message): b"keep_paused", "namespace", b"namespace", - "reset_heartbeat", - b"reset_heartbeat", "resource_id", b"resource_id", "restore_original_options", @@ -11864,7 +12052,7 @@ class StartActivityExecutionRequest(google.protobuf.message.Message): """Options for handling conflicts when using ACTIVITY_ID_CONFLICT_POLICY_USE_EXISTING.""" @property def start_delay(self) -> google.protobuf.duration_pb2.Duration: - """Time to wait before dispatching the first activity task. This delay is not applied to retry attempts.""" + """Time to wait before making the first activity task available for dispatch. This delay is not applied to retry attempts.""" def __init__( self, *, diff --git a/temporalio/bridge/Cargo.lock b/temporalio/bridge/Cargo.lock index a92196ee3..330916b2b 100644 --- a/temporalio/bridge/Cargo.lock +++ b/temporalio/bridge/Cargo.lock @@ -31,19 +31,19 @@ checksum = "940b3a0ca603d1eade50a4846a2afffd5ef57a9feac2c0e2ec2e14f9ead76000" [[package]] name = "anyhow" -version = "1.0.103" +version = "1.0.104" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a4385e2e34eb35d6b3efe798b9eb88096925d87726c0798709bf56d9ed84af3" +checksum = "330a5ed07fa54e4702c9d6c4174f74427fc0ef6e214bbd677ae50a5099946470" [[package]] name = "async-trait" -version = "0.1.89" +version = "0.1.91" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9035ad2d096bed7955a320ee7e2230574d28fd3c3a0f186cbea1ff3c7eed5dbb" +checksum = "ae36dc4177970ef04fde5178d3e2429882def40e57a451f919c098f72baa6cec" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 3.0.3", ] [[package]] @@ -60,9 +60,9 @@ checksum = "f2032f911046de80f0a198e0901378627c33f59ea0ac00e363d481118bd70a53" [[package]] name = "aws-lc-rs" -version = "1.17.1" +version = "1.17.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4342d8937fc7e5dd9b1c60292261c0670c882a2cd1719cfc11b1af41731e32ad" +checksum = "00bdb5da18dac48ca2cc7cd4a98e533e8635a58e2361d13a1a4ee3888e0d72f1" dependencies = [ "aws-lc-sys", "zeroize", @@ -70,9 +70,9 @@ dependencies = [ [[package]] name = "aws-lc-sys" -version = "0.42.0" +version = "0.43.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d9ceb1da931507a12f4fccea479dccd00da1943e1b4ae72d8e502d707361444" +checksum = "43103168cc76fe62678a375e722fc9cb3a0146159ac5828bc4f0dfd755c2224c" dependencies = [ "cc", "cmake", @@ -125,14 +125,12 @@ dependencies = [ ] [[package]] -name = "backoff" -version = "0.4.0" +name = "backon" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b62ddb9cb1ec0a098ad4bbf9344d0713fa193ae1a80af55febcff2627b6a00c1" +checksum = "cffb0e931875b666fc4fcb20fee52e9bbd1ef836fd9e9e04ec21555f9f85f7ef" dependencies = [ - "getrandom 0.2.17", - "instant", - "rand 0.8.6", + "fastrand", ] [[package]] @@ -143,9 +141,9 @@ checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" [[package]] name = "bitflags" -version = "2.13.0" +version = "2.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4388bee8683e3d04af747c73422af53102d2bd24d9eadb6cbc100baef4b43f8" +checksum = "b588b76d00fde79687d7646a9b5bdf3cc0f655e0bbd080335a95d7e96f3587da" [[package]] name = "bon" @@ -169,7 +167,7 @@ dependencies = [ "proc-macro2", "quote", "rustversion", - "syn", + "syn 2.0.119", ] [[package]] @@ -180,9 +178,9 @@ checksum = "72f5acc6cb2ba439de613abc23857ec3d78374d8ed5ac84e9d11336e87da8649" [[package]] name = "bytes" -version = "1.12.0" +version = "1.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ae3f5d315924270530207e2a68396c3cc547f6dca3fbdca317cfb1a51edb593" +checksum = "fc652a48c352aef3ea3aed32080501cf3ef6ed5da78602a020c991775b0aff04" [[package]] name = "bzip2" @@ -195,9 +193,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.2.65" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e228eec9be7c17ccb640b59b36a5cd805ea2a564a4c5e162c2f659fea30d3b96" +checksum = "5add81bb678e6cb321aff7fa0dc7689ad82b112dbc032cea19f91d6b8e3582b9" dependencies = [ "find-msvc-tools", "jobserver", @@ -213,9 +211,9 @@ checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" [[package]] name = "cfg_aliases" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" +checksum = "f079e83a288787bcd14a6aea84cee5c87a67c5a3e660c30f557a3d24761b3527" [[package]] name = "chacha20" @@ -302,18 +300,18 @@ dependencies = [ [[package]] name = "crossbeam-channel" -version = "0.5.15" +version = "0.5.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82b8f8f868b36967f9606790d1903570de9ceaf870a7bf9fbbd3016d636a2cb2" +checksum = "d85363c37faeca707aef026efa9f3b34d077bce547e48f770770625c6013679e" dependencies = [ "crossbeam-utils", ] [[package]] name = "crossbeam-utils" -version = "0.8.21" +version = "0.8.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" +checksum = "61803da095bee82a81bb1a452ecc25d3b2f1416d1897eb86430c6159ef717c17" [[package]] name = "darling" @@ -335,7 +333,7 @@ dependencies = [ "proc-macro2", "quote", "strsim", - "syn", + "syn 2.0.119", ] [[package]] @@ -346,7 +344,7 @@ checksum = "ac3984ec7bd6cfa798e62b4a642426a5be0e68f9401cfc2a01e3fa9ea2fcdb8d" dependencies = [ "darling_core", "quote", - "syn", + "syn 2.0.119", ] [[package]] @@ -368,7 +366,7 @@ dependencies = [ "proc-macro2", "quote", "rustc_version", - "syn", + "syn 2.0.119", "unicode-xid", ] @@ -401,7 +399,7 @@ checksum = "1ac70aa55017e108007fbaf5aa0f54b021c98f92ff8af59d42eda9da96e3dd4f" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.119", ] [[package]] @@ -424,9 +422,9 @@ checksum = "d0881ea181b1df73ff77ffaaf9c7544ecc11e82fba9b5f27b262a3c73a332555" [[package]] name = "either" -version = "1.16.0" +version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91622ff5e7162018101f2fea40d6ebf4a78bbe5a49736a2020649edf9693679e" +checksum = "9e5e8f6c15a24b9a3ee5efec809ccd006d3b30e8b3bb63c39af737c7f87daa1d" [[package]] name = "enum-iterator" @@ -445,7 +443,7 @@ checksum = "685adfa4d6f3d765a26bc5dbc936577de9abf756c1feeb3089b01dd395034842" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.119", ] [[package]] @@ -457,7 +455,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn", + "syn 2.0.119", ] [[package]] @@ -489,9 +487,9 @@ dependencies = [ [[package]] name = "fastrand" -version = "2.4.1" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f1f227452a390804cdb637b74a86990f2a7d7ba4b7d5693aac9b4dd6defd8d6" +checksum = "da7c62ceae207dd37ea5b845da6a0696c799f85e97da1ab5b7910be3c1c80223" [[package]] name = "filetime" @@ -570,9 +568,9 @@ checksum = "42703706b716c37f96a77aea830392ad231f44c9e9a67872fa5548707e11b11c" [[package]] name = "futures" -version = "0.3.32" +version = "0.3.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b147ee9d1f6d097cef9ce628cd2ee62288d963e16fb287bd9286455b241382d" +checksum = "a88cf1f829d945f548cf8fec32c61b1f202b6d93b45848602fc02af4b12ad218" dependencies = [ "futures-channel", "futures-core", @@ -585,9 +583,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.32" +version = "0.3.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07bbe89c50d7a535e539b8c17bc0b49bdb77747034daa8087407d655f3f7cc1d" +checksum = "262590f4fe6afeb0bc83be1daa64e52657fe185690a958af7f3ad0e92085c5ae" dependencies = [ "futures-core", "futures-sink", @@ -595,15 +593,15 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.32" +version = "0.3.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e3450815272ef58cec6d564423f6e755e25379b217b0bc688e295ba24df6b1d" +checksum = "2cd50c473c80f6d7c3670a752354b8e569b1a7cbfdc0419ec88e5edad85e0dc7" [[package]] name = "futures-executor" -version = "0.3.32" +version = "0.3.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf29c38818342a3b26b5b923639e7b1f4a61fc5e76102d4b1981c6dc7a7579d" +checksum = "6754879cc9f2c66f88c6e5c35344bb0bdb0708b0352b1201815667c7eabc7458" dependencies = [ "futures-core", "futures-task", @@ -612,19 +610,19 @@ dependencies = [ [[package]] name = "futures-io" -version = "0.3.32" +version = "0.3.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cecba35d7ad927e23624b22ad55235f2239cfa44fd10428eecbeba6d6a717718" +checksum = "4577ecaa3c4f96589d473f679a71b596316f6641bc350038b962a5daf0085d7a" [[package]] name = "futures-macro" -version = "0.3.32" +version = "0.3.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e835b70203e41293343137df5c0664546da5745f82ec9b84d40be8336958447b" +checksum = "2d6d3cde68c518367be28956066ddfef33813991b77a55005a69dae04bf3b10b" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.119", ] [[package]] @@ -640,21 +638,21 @@ dependencies = [ [[package]] name = "futures-sink" -version = "0.3.32" +version = "0.3.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c39754e157331b013978ec91992bde1ac089843443c49cbc7f46150b0fad0893" +checksum = "e34418ac499d6305c2fb5ad0ed2f6ac998c5f8ca209b4510f7f94242c647e307" [[package]] name = "futures-task" -version = "0.3.32" +version = "0.3.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "037711b3d59c33004d3856fbdc83b99d4ff37a24768fa1be9ce3538a1cde4393" +checksum = "b231ed28831efb4a61a08580c4bc233ec56bc009f4cd8f52da2c3cb97df0c109" [[package]] name = "futures-util" -version = "0.3.32" +version = "0.3.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "389ca41296e6190b48053de0321d02a77f32f8a5d2461dd38762c0593805c6d6" +checksum = "a77a90a256fce34da66415271e30f94ee91c57b04b8a2c042d9cf3220179deaa" dependencies = [ "futures-channel", "futures-core", @@ -697,11 +695,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd" dependencies = [ "cfg-if", - "js-sys", "libc", "r-efi 5.3.0", "wasip2", - "wasm-bindgen", ] [[package]] @@ -711,9 +707,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "300e883d756b2e4ec94e02791f39b04b522276138852cfc41d9fb7e904106099" dependencies = [ "cfg-if", + "js-sys", "libc", "r-efi 6.0.0", "rand_core 0.10.1", + "wasm-bindgen", ] [[package]] @@ -773,9 +771,9 @@ dependencies = [ [[package]] name = "http-body" -version = "1.0.1" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" +checksum = "ca2a8f2913ee65f60facd6a5905613afaa448497a0230cc41ce022d93290bc2c" dependencies = [ "bytes", "http", @@ -783,9 +781,9 @@ dependencies = [ [[package]] name = "http-body-util" -version = "0.1.3" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b021d93e26becf5dc7e1b75b1bed1fd93124b374ceb73f43d4d4eafec896a64a" +checksum = "e9f41fd6a08e4d4ec69df65976da761afd5ad5e58a9d4acb46bd1c953a9e3ff2" dependencies = [ "bytes", "futures-core", @@ -808,9 +806,9 @@ checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" [[package]] name = "hyper" -version = "1.10.1" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55281c53a1894c864990125767da440a4e630446785086f52523b20033b74498" +checksum = "d22053281f852e11534f5198498373cbb59295120a20771d90f7ed1897490a72" dependencies = [ "atomic-waker", "bytes", @@ -998,15 +996,6 @@ dependencies = [ "hashbrown 0.17.1", ] -[[package]] -name = "instant" -version = "0.1.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0242819d153cba4b4b05a5a8f2a7e9bbf97b6055b2a002b395c96b5ff3c0222" -dependencies = [ - "cfg-if", -] - [[package]] name = "inventory" version = "0.3.24" @@ -1064,7 +1053,7 @@ dependencies = [ "quote", "rustc_version", "simd_cesu8", - "syn", + "syn 2.0.119", ] [[package]] @@ -1083,16 +1072,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "38c0b942f458fe50cdac086d2f946512305e5631e720728f2a61aabcd47a6264" dependencies = [ "quote", - "syn", + "syn 2.0.119", ] [[package]] name = "jobserver" -version = "0.1.34" +version = "0.1.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9afb3de4395d6b3e67a780b6de64b51c978ecf11cb9a462c66be7d4ca9039d33" +checksum = "1c00acbd29eabad4a2392fa0e921c874934dbbf4194312ad20f04a0ed67a3cb3" dependencies = [ - "getrandom 0.3.4", + "getrandom 0.4.3", "libc", ] @@ -1121,9 +1110,9 @@ checksum = "34b357333733e8260735ba5894eb928c02ecc69c78715f01a8019e7fa7f2db4c" [[package]] name = "libc" -version = "0.2.186" +version = "0.2.189" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68ab91017fe16c622486840e4c83c9a37afeff978bd239b5293d61ece587de66" +checksum = "3eaf3ede3fee6db1a4c2ee091bf8a8b4dccdc6d17f656fb07896ee72867612f2" [[package]] name = "libredox" @@ -1163,9 +1152,9 @@ checksum = "0ceec5bc11778974d1bcb055b18002eba7f4b3518b6a0081b3af5f21666da9ad" [[package]] name = "lru" -version = "0.18.0" +version = "0.18.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a860605968fce16869fd239cf4237a82f3ac470723415db603b0e8b6c8d4fb9" +checksum = "0b6180140927ee907000b0aa540091f6ea512ead4447c92b8fc35bc72788a5a6" dependencies = [ "hashbrown 0.17.1", ] @@ -1193,9 +1182,9 @@ checksum = "47e1ffaa40ddd1f3ed91f717a33c8c0ee23fff369e3aa8772b9605cc1d22f4c3" [[package]] name = "memchr" -version = "2.8.2" +version = "2.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88904434abc2901f197fe8cc55f0445e7ded921dba5911dad2e2b39b48e663c4" +checksum = "cf8baf1c55e62ffcace7a9f06f4bd9cd3f0c4beb022d3b367256b91b87513d98" [[package]] name = "mime" @@ -1215,9 +1204,9 @@ dependencies = [ [[package]] name = "mio" -version = "1.2.1" +version = "1.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02bd0af71c67b473010cbbc60715ee815645a4dc942899111f494b4b737d6fda" +checksum = "30d65c71f1ce40ab09135ce117d742b9f8a19ff91a41a8b57ed50bc2de59c427" dependencies = [ "libc", "wasi", @@ -1247,7 +1236,7 @@ dependencies = [ "cfg-if", "proc-macro2", "quote", - "syn", + "syn 2.0.119", ] [[package]] @@ -1384,7 +1373,7 @@ dependencies = [ "opentelemetry", "percent-encoding", "portable-atomic", - "rand 0.9.4", + "rand 0.9.5", "thiserror", "tokio", "tokio-stream", @@ -1484,7 +1473,7 @@ checksum = "c96395f0a926bc13b1c17622aaddda1ecb55d49c8f1bf9777e4d877800a43f8b" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.119", ] [[package]] @@ -1501,9 +1490,9 @@ checksum = "19f132c84eca552bf34cab8ec81f1c1dcc229b811638f9d283dceabe58c5569e" [[package]] name = "portable-atomic" -version = "1.13.1" +version = "1.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c33a9471896f1c69cecef8d20cbe2f7accd12527ce60845ff44c153bb2a21b49" +checksum = "3d20d5497ef88037a52ff98267d066e7f11fcc5e99bbfbd58a42336193aacec3" [[package]] name = "portable-atomic-util" @@ -1565,14 +1554,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b" dependencies = [ "proc-macro2", - "syn", + "syn 2.0.119", ] [[package]] name = "proc-macro2" -version = "1.0.106" +version = "1.0.107" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934" +checksum = "985e7ec9bb745e6ce6535b544d84d6cd6f7ad8bd711c398938ae983b91a766d9" dependencies = [ "unicode-ident", ] @@ -1618,7 +1607,7 @@ dependencies = [ "pulldown-cmark", "pulldown-cmark-to-cmark", "regex", - "syn", + "syn 2.0.119", "tempfile", ] @@ -1632,7 +1621,7 @@ dependencies = [ "itertools", "proc-macro2", "quote", - "syn", + "syn 2.0.119", ] [[package]] @@ -1768,7 +1757,7 @@ dependencies = [ "proc-macro2", "pyo3-macros-backend", "quote", - "syn", + "syn 2.0.119", ] [[package]] @@ -1780,7 +1769,7 @@ dependencies = [ "heck", "proc-macro2", "quote", - "syn", + "syn 2.0.119", ] [[package]] @@ -1815,15 +1804,16 @@ dependencies = [ [[package]] name = "quinn-proto" -version = "0.11.15" +version = "0.11.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fcb935c5bec503c2f0e306bdd3e58bb9029dcb14fa8d9ac76e3a5256ac0763e" +checksum = "2f4bfc015262b9df63c8845072ce59068853ff5872180c2ce2f13038b970e560" dependencies = [ "aws-lc-rs", "bytes", - "getrandom 0.3.4", + "getrandom 0.4.3", "lru-slab", - "rand 0.9.4", + "rand 0.10.2", + "rand_pcg", "ring", "rustc-hash", "rustls", @@ -1837,23 +1827,23 @@ dependencies = [ [[package]] name = "quinn-udp" -version = "0.5.14" +version = "0.5.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "addec6a0dcad8a8d96a771f815f0eaf55f9d1805756410b39f5fa81332574cbd" +checksum = "35a133f956daabe89a61a685c2649f13d82d5aa4bd5d12d1277e1072a21c0694" dependencies = [ "cfg_aliases", "libc", "once_cell", "socket2", "tracing", - "windows-sys 0.60.2", + "windows-sys 0.61.2", ] [[package]] name = "quote" -version = "1.0.46" +version = "1.0.47" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfbc457d0c7a0759a614551b11a6409e5951f6c7537be1f1b7682b9ae9230368" +checksum = "1fbf4db142a473a8d80c26bbf18454ed458bf8d26c8219c331daecfdbd079001" dependencies = [ "proc-macro2", ] @@ -1872,22 +1862,11 @@ checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf" [[package]] name = "rand" -version = "0.8.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ca0ecfa931c29007047d1bc58e623ab12e5590e8c7cc53200d5202b69266d8a" -dependencies = [ - "libc", - "rand_chacha 0.3.1", - "rand_core 0.6.4", -] - -[[package]] -name = "rand" -version = "0.9.4" +version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44c5af06bb1b7d3216d91932aed5265164bf384dc89cd6ba05cf59a35f5f76ea" +checksum = "b9ef1d0d795eb7d84685bca4f72f3649f064e6641543d3a8c415898726a57b41" dependencies = [ - "rand_chacha 0.9.0", + "rand_chacha", "rand_core 0.9.5", ] @@ -1902,16 +1881,6 @@ dependencies = [ "rand_core 0.10.1", ] -[[package]] -name = "rand_chacha" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" -dependencies = [ - "ppv-lite86", - "rand_core 0.6.4", -] - [[package]] name = "rand_chacha" version = "0.9.0" @@ -1922,15 +1891,6 @@ dependencies = [ "rand_core 0.9.5", ] -[[package]] -name = "rand_core" -version = "0.6.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" -dependencies = [ - "getrandom 0.2.17", -] - [[package]] name = "rand_core" version = "0.9.5" @@ -1946,6 +1906,15 @@ version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "63b8176103e19a2643978565ca18b50549f6101881c443590420e4dc998a3c69" +[[package]] +name = "rand_pcg" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "caa0f4137e1c0a72f4c651489402276c8e8e1cf081f3b0ba156d2cbeef09e86a" +dependencies = [ + "rand_core 0.10.1", +] + [[package]] name = "redox_syscall" version = "0.5.18" @@ -1968,9 +1937,9 @@ dependencies = [ [[package]] name = "regex" -version = "1.12.4" +version = "1.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1292b7759ae1cb9ec195452d1390a074f0cd8541ab7a5a8c31cd6db45d4a6ba" +checksum = "f020237b6c8eed93db2e2cb53c00c60a8e1bc73da7d073199a1180401450218d" dependencies = [ "aho-corasick", "memchr", @@ -1980,9 +1949,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.14" +version = "0.4.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e1dd4122fc1595e8162618945476892eefca7b88c52820e74af6262213cae8f" +checksum = "8fcfdb36bda0c880c5931cdc7a2bcdc8ba4556847b9d912bca70bc94708711ad" dependencies = [ "aho-corasick", "memchr", @@ -2085,9 +2054,9 @@ dependencies = [ [[package]] name = "ringbuf" -version = "0.5.0" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d3ecbcab081b935fb9c618b07654924f27686b4aac8818e700580a83eedcb7f" +checksum = "a158e09ede21a14b172ca6cdd6208386c6ae2cb6acef58d774368ef8c450dfa7" dependencies = [ "crossbeam-utils", "portable-atomic", @@ -2096,9 +2065,9 @@ dependencies = [ [[package]] name = "rustc-hash" -version = "2.1.2" +version = "2.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94300abf3f1ae2e2b8ffb7b58043de3d399c73fa6f4b73826402a5c457614dbe" +checksum = "6b1e7f9a428571be2dc5bc0505c13fb6bf936822b894ec87abf8a08a4e51742d" [[package]] name = "rustc_version" @@ -2124,9 +2093,9 @@ dependencies = [ [[package]] name = "rustls" -version = "0.23.41" +version = "0.23.42" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b92b125634d9b795e7beca796cc790df15a7fb38323bf3196fda83292d06b1f" +checksum = "3c54fcab019b409d04215d3a17cb438fd7fbf192ee61461f20f4fe18704bc138" dependencies = [ "aws-lc-rs", "log", @@ -2152,9 +2121,9 @@ dependencies = [ [[package]] name = "rustls-pki-types" -version = "1.15.0" +version = "1.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "764899a24af3980067ee14bc143654f297b22eaebfe3c7b6b211920a5a59b046" +checksum = "2f4925028c7eb5d1fcdaf196971378ed9d2c1c4efc7dc5d011256f76c99c0a96" dependencies = [ "web-time", "zeroize", @@ -2201,9 +2170,9 @@ dependencies = [ [[package]] name = "rustversion" -version = "1.0.22" +version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" +checksum = "cf54715a573b99ac80df0bc206da022bcd442c974952c7b9720069370852e21f" [[package]] name = "ryu" @@ -2266,9 +2235,9 @@ checksum = "8a7852d02fc848982e0c167ef163aaff9cd91dc640ba85e263cb1ce46fae51cd" [[package]] name = "serde" -version = "1.0.228" +version = "1.0.229" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" +checksum = "4148590afebada386688f18773da617792bf2ef03ffc1e4cbd2b1d45b023e0ba" dependencies = [ "serde_core", "serde_derive", @@ -2276,29 +2245,29 @@ dependencies = [ [[package]] name = "serde_core" -version = "1.0.228" +version = "1.0.229" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" +checksum = "67dca2c9c51e58a4791a4b1ed58308b39c64224d349a935ab5039aa360942a48" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.228" +version = "1.0.229" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" +checksum = "e7a5d71263a5a7d47b41f6b3f06ba276f10cc18b0931f1799f710578e2309348" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 3.0.3", ] [[package]] name = "serde_json" -version = "1.0.150" +version = "1.0.151" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8014e44b4736ed0538adeecded0fce2a272f22dc9578a7eb6b2d9993c74cfb9" +checksum = "c841b55ecdae098c80dcae9cf767f6f8a0c2cdb3416bbef72181df4d0fe73f14" dependencies = [ "itoa", "memchr", @@ -2355,15 +2324,15 @@ dependencies = [ [[package]] name = "simd-adler32" -version = "0.3.9" +version = "0.3.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "703d5c7ef118737c72f1af64ad2f6f8c5e1921f818cdcb97b8fe6fc69bf66214" +checksum = "3a219298ac11a56ea9a6d2120044824d6f01aeb034955e7af7bc16858527deea" [[package]] name = "simd_cesu8" -version = "1.1.1" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94f90157bb87cddf702797c5dadfa0be7d266cdf49e22da2fcaa32eff75b2c33" +checksum = "11031e251abf8611c80f460e19dbdeb54a66db918e49c65a7065b46ac7aec520" dependencies = [ "rustc_version", "simdutf8", @@ -2404,9 +2373,9 @@ checksum = "8ed6a63f02c8539c91a8685a86f4099661ba3da017932f6ebbea6de3f0fa7c90" [[package]] name = "socket2" -version = "0.6.4" +version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52d1cfed4120b4d927bf7c0f86d2087a4a7d6027c906d9f9d525a80573b9be51" +checksum = "c3d1e2c7f27f8d4cb10542a02c49005dbd6e93095799d6f3be745fae9f8fedd4" dependencies = [ "libc", "windows-sys 0.61.2", @@ -2432,9 +2401,20 @@ checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" [[package]] name = "syn" -version = "2.0.118" +version = "2.0.119" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b9ae57f904213ebb649ce6895b8a66c66f0203b9319718f69a5612a065b1422" +checksum = "872831b642d1a07999a962a351ed35b955ea2cfc8f3862091e2a240a84f17297" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "3.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53e9bae58849f64dfa4f5d5ae372c8341f7305f82a3868709269343628b659a3" dependencies = [ "proc-macro2", "quote", @@ -2458,7 +2438,7 @@ checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.119", ] [[package]] @@ -2533,7 +2513,7 @@ version = "0.5.0" dependencies = [ "anyhow", "async-trait", - "backoff", + "backon", "base64", "bon", "bytes", @@ -2629,7 +2609,7 @@ version = "0.5.0" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.119", ] [[package]] @@ -2659,7 +2639,7 @@ version = "0.5.0" dependencies = [ "anyhow", "async-trait", - "backoff", + "backon", "bon", "crossbeam-channel", "crossbeam-utils", @@ -2709,29 +2689,29 @@ checksum = "8f50febec83f5ee1df3015341d8bd429f2d1cc62bcba7ea2076759d315084683" [[package]] name = "thiserror" -version = "2.0.18" +version = "2.0.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4288b5bcbc7920c07a1149a35cf9590a2aa808e0bc1eafaade0b80947865fbc4" +checksum = "09a43598840e33d5b0331f38c5e30d13bb11c11210a4b58f0d9b18a5a5eefcd9" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "2.0.18" +version = "2.0.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ebc4ee7f67670e9b64d05fa4253e753e016c6c95ff35b89b7941d6b856dec1d5" +checksum = "43cbfe0cf76104d42a574802844187e84a305e531ed54455f11fbde0f10541cd" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 3.0.3", ] [[package]] name = "thread_local" -version = "1.1.9" +version = "1.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f60246a4944f24f6e018aa17cdeffb7818b76356965d03b07d6a9886e8962185" +checksum = "1ad99c4c6d32803332c548b1af0540b357b3f5fc0be8f6c6bfe8b2e6ae784070" dependencies = [ "cfg-if", ] @@ -2748,9 +2728,9 @@ dependencies = [ [[package]] name = "tinyvec" -version = "1.11.0" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e61e67053d25a4e82c844e8424039d9745781b3fc4f32b8d55ed50f5f667ef3" +checksum = "bb4ebadaa0af04fab11ae01eb5f9fdb5f9c5b875506e210e71c07873528baa7f" dependencies = [ "tinyvec_macros", ] @@ -2763,9 +2743,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.52.3" +version = "1.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fc7f01b389ac15039e4dc9531aa973a135d7a4135281b12d7c1bc79fd57fffe" +checksum = "202caea871b69668250d242070849eb495be178ed697a3e98aebce5bc81a0bed" dependencies = [ "bytes", "libc", @@ -2780,13 +2760,13 @@ dependencies = [ [[package]] name = "tokio-macros" -version = "2.7.0" +version = "2.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "385a6cb71ab9ab790c5fe8d67f1645e6c450a7ce006a33de03daa956cf70a496" +checksum = "6328af13490e73a9b4694030fafd93f8c8c6a9dede33e821c3fc63eddf8042ba" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.119", ] [[package]] @@ -2801,9 +2781,9 @@ dependencies = [ [[package]] name = "tokio-stream" -version = "0.1.18" +version = "0.1.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32da49809aab5c3bc678af03902d4ccddea2a87d028d86392a4b1560c6906c70" +checksum = "a3d06f0b082ba57c26b79407372e57cf2a1e28124f78e9479fe80322cf53420b" dependencies = [ "futures-core", "pin-project-lite", @@ -2812,22 +2792,23 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.7.18" +version = "0.7.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ae9cec805b01e8fc3fd2fe289f89149a9b66dd16786abd8b19cfa7b48cb0098" +checksum = "494815d09bf52b5548659851081238f0ca39ff638363907596da739561c62c52" dependencies = [ "bytes", "futures-core", "futures-sink", + "libc", "pin-project-lite", "tokio", ] [[package]] name = "toml" -version = "1.1.2+spec-1.1.0" +version = "1.1.3+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81f3d15e84cbcd896376e6730314d59fb5a87f31e4b038454184435cd57defee" +checksum = "53c96ecdfa941c8fc4fcaed14f99ada8ebed502eef533015095a07e3301d4c3c" dependencies = [ "indexmap", "serde_core", @@ -2858,9 +2839,9 @@ dependencies = [ [[package]] name = "toml_writer" -version = "1.1.1+spec-1.1.0" +version = "1.1.2+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "756daf9b1013ebe47a8776667b466417e2d4c5679d441c26230efd9ef78692db" +checksum = "7d56353a2a665ad0f41a421187180aab746c8c325620617ad883a99a1cbe66d2" [[package]] name = "tonic" @@ -2903,7 +2884,7 @@ dependencies = [ "prettyplease", "proc-macro2", "quote", - "syn", + "syn 2.0.119", ] [[package]] @@ -2928,7 +2909,7 @@ dependencies = [ "prost-build", "prost-types", "quote", - "syn", + "syn 2.0.119", "tempfile", "tonic-build", ] @@ -3012,7 +2993,7 @@ checksum = "7490cfa5ec963746568740651ac6781f701c9c5ea257c58e057f3ba8cf69e8da" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.119", ] [[package]] @@ -3062,9 +3043,9 @@ checksum = "bc7d623258602320d5c55d1bc22793b57daff0ec7efc270ea7d55ce1d5f5471c" [[package]] name = "typetag" -version = "0.2.22" +version = "0.2.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5a897b12c6c1151ad0b138b8db50252dc301f93bc3b027db05eec82aeed298c" +checksum = "c90e86058a30d42a1a928dfb4b49bb33c98c3a2b4909492e6b0881cd94798ec2" dependencies = [ "erased-serde", "inventory", @@ -3075,13 +3056,13 @@ dependencies = [ [[package]] name = "typetag-impl" -version = "0.2.22" +version = "0.2.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf808357c6ed7e13ba0f3277ec8d8f21b2d501274895104263985330c726c1c5" +checksum = "f153acc4e99a5f2a5aefa09fb078be54e26271b2813f6041200b224c098d8328" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 3.0.3", ] [[package]] @@ -3134,9 +3115,9 @@ checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" [[package]] name = "uuid" -version = "1.23.4" +version = "1.24.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf80a72845275afea99e7f2b434723d3bc7e38470fcd1c7ed39a599c73319a53" +checksum = "bf3923a6f5c4c6382e0b653c4117f48d631ea17f38ed86e2a828e6f7412f5239" dependencies = [ "getrandom 0.4.3", ] @@ -3229,7 +3210,7 @@ dependencies = [ "bumpalo", "proc-macro2", "quote", - "syn", + "syn 2.0.119", "wasm-bindgen-shared", ] @@ -3277,9 +3258,9 @@ dependencies = [ [[package]] name = "webpki-root-certs" -version = "1.0.8" +version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d46a5a140e6f7afeccd8eae97eff335163939eac8b929834875168b29b3d267" +checksum = "b96554aa2acc8ccdb7e1c9a58a7a68dd5d13bccc69cd124cb09406db612a1c9b" dependencies = [ "rustls-pki-types", ] @@ -3368,7 +3349,7 @@ checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.119", ] [[package]] @@ -3379,7 +3360,7 @@ checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.119", ] [[package]] @@ -3422,16 +3403,7 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ - "windows-targets 0.52.6", -] - -[[package]] -name = "windows-sys" -version = "0.60.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb" -dependencies = [ - "windows-targets 0.53.5", + "windows-targets", ] [[package]] @@ -3449,31 +3421,14 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" dependencies = [ - "windows_aarch64_gnullvm 0.52.6", - "windows_aarch64_msvc 0.52.6", - "windows_i686_gnu 0.52.6", - "windows_i686_gnullvm 0.52.6", - "windows_i686_msvc 0.52.6", - "windows_x86_64_gnu 0.52.6", - "windows_x86_64_gnullvm 0.52.6", - "windows_x86_64_msvc 0.52.6", -] - -[[package]] -name = "windows-targets" -version = "0.53.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4945f9f551b88e0d65f3db0bc25c33b8acea4d9e41163edf90dcd0b19f9069f3" -dependencies = [ - "windows-link", - "windows_aarch64_gnullvm 0.53.1", - "windows_aarch64_msvc 0.53.1", - "windows_i686_gnu 0.53.1", - "windows_i686_gnullvm 0.53.1", - "windows_i686_msvc 0.53.1", - "windows_x86_64_gnu 0.53.1", - "windows_x86_64_gnullvm 0.53.1", - "windows_x86_64_msvc 0.53.1", + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_gnullvm", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", ] [[package]] @@ -3491,101 +3446,53 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9d8416fa8b42f5c947f8482c43e7d89e73a173cead56d044f6a56104a6d1b53" - [[package]] name = "windows_aarch64_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" -[[package]] -name = "windows_aarch64_msvc" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9d782e804c2f632e395708e99a94275910eb9100b2114651e04744e9b125006" - [[package]] name = "windows_i686_gnu" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" -[[package]] -name = "windows_i686_gnu" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "960e6da069d81e09becb0ca57a65220ddff016ff2d6af6a223cf372a506593a3" - [[package]] name = "windows_i686_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" -[[package]] -name = "windows_i686_gnullvm" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa7359d10048f68ab8b09fa71c3daccfb0e9b559aed648a8f95469c27057180c" - [[package]] name = "windows_i686_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" -[[package]] -name = "windows_i686_msvc" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e7ac75179f18232fe9c285163565a57ef8d3c89254a30685b57d83a38d326c2" - [[package]] name = "windows_x86_64_gnu" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" -[[package]] -name = "windows_x86_64_gnu" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c3842cdd74a865a8066ab39c8a7a473c0778a3f29370b5fd6b4b9aa7df4a499" - [[package]] name = "windows_x86_64_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ffa179e2d07eee8ad8f57493436566c7cc30ac536a3379fdf008f47f6bb7ae1" - [[package]] name = "windows_x86_64_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" -[[package]] -name = "windows_x86_64_msvc" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6bbff5f0aada427a1e5a6da5f1f98158182f26556f345ac9e04d36d0ebed650" - [[package]] name = "winnow" -version = "1.0.3" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0592e1c9d151f854e6fd382574c3a0855250e1d9b2f99d9281c6e6391af352f1" +checksum = "23b97319f7b8343df12cc98938e5c3eb436064524c8d2b4e30a1d3a36eecdf81" [[package]] name = "wit-bindgen" @@ -3628,28 +3535,28 @@ checksum = "de844c262c8848816172cef550288e7dc6c7b7814b4ee56b3e1553f275f1858e" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.119", "synstructure", ] [[package]] name = "zerocopy" -version = "0.8.52" +version = "0.8.55" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce1022995ff5ff5d841ad7d994facc23098cd40152f2c1d11cd607c6f530653f" +checksum = "b5a105cd7b140f6eeec8acff2ea38135d3cab283ada58540f629fe51e46696eb" dependencies = [ "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.8.52" +version = "0.8.55" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ae7f38b72ec2a254e2b87ef277cf2cd4fb97cbebf944faa6f33354da0867930" +checksum = "0fe976fb70c78cd64cccfe3a6fc142244e8a77b70959b30faf9d0ac37ee228eb" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.119", ] [[package]] @@ -3669,7 +3576,7 @@ checksum = "11532158c46691caf0f2593ea8358fed6bbf68a0315e80aae9bd41fbade684a1" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.119", "synstructure", ] @@ -3709,7 +3616,7 @@ checksum = "625dc425cab0dca6dc3c3319506e6593dcb08a9f387ea3b284dbd52a92c40555" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.119", ] [[package]] @@ -3730,15 +3637,15 @@ dependencies = [ [[package]] name = "zlib-rs" -version = "0.6.5" +version = "0.6.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5431d5661c32445236631278f27946e444ddafe4684cac70b185272d4f9c52d5" +checksum = "b142a20ec14a91d5bc708c1dc21b080c550113d8aa77afa29635673a65dd02c5" [[package]] name = "zmij" -version = "1.0.21" +version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8848ee67ecc8aedbaf3e4122217aff892639231befc6a1b58d29fff4c2cabaa" +checksum = "29666d0abbfad1e3dc4dcf6144730dd3a3ab225bbbdac83319345b1b44ccfc1b" [[package]] name = "zopfli" diff --git a/temporalio/bridge/sdk-core b/temporalio/bridge/sdk-core index 3dac9013b..d2769368d 160000 --- a/temporalio/bridge/sdk-core +++ b/temporalio/bridge/sdk-core @@ -1 +1 @@ -Subproject commit 3dac9013b9031e5ffd51d7335838585b2db42efb +Subproject commit d2769368df9077a311537431ff4594c9c14db4e7 diff --git a/temporalio/bridge/src/worker.rs b/temporalio/bridge/src/worker.rs index 15518b224..d0b007dba 100644 --- a/temporalio/bridge/src/worker.rs +++ b/temporalio/bridge/src/worker.rs @@ -57,6 +57,7 @@ pub struct WorkerConfig { default_heartbeat_throttle_interval_millis: u64, max_activities_per_second: Option, max_task_queue_activities_per_second: Option, + max_eager_activity_reservations_per_workflow_task: usize, graceful_shutdown_period_millis: u64, nondeterminism_as_workflow_fail: bool, nondeterminism_as_workflow_fail_for_types: HashSet, @@ -739,6 +740,9 @@ fn convert_worker_config( )) .maybe_max_worker_activities_per_second(conf.max_activities_per_second) .maybe_max_task_queue_activities_per_second(conf.max_task_queue_activities_per_second) + .max_eager_activity_reservations_per_workflow_task( + conf.max_eager_activity_reservations_per_workflow_task, + ) // Even though grace period is optional, if it is not set then the // auto-cancel-activity behavior of shutdown will not occur, so we // always set it even if 0. diff --git a/temporalio/bridge/worker.py b/temporalio/bridge/worker.py index 6554c508c..4b7f55d09 100644 --- a/temporalio/bridge/worker.py +++ b/temporalio/bridge/worker.py @@ -52,6 +52,7 @@ class WorkerConfig: default_heartbeat_throttle_interval_millis: int max_activities_per_second: float | None max_task_queue_activities_per_second: float | None + max_eager_activity_reservations_per_workflow_task: int graceful_shutdown_period_millis: int nondeterminism_as_workflow_fail: bool nondeterminism_as_workflow_fail_for_types: set[str] diff --git a/temporalio/worker/_replayer.py b/temporalio/worker/_replayer.py index 61dcb84f4..dfd348f8a 100644 --- a/temporalio/worker/_replayer.py +++ b/temporalio/worker/_replayer.py @@ -320,6 +320,7 @@ def on_eviction_hook( default_heartbeat_throttle_interval_millis=1000, max_activities_per_second=None, max_task_queue_activities_per_second=None, + max_eager_activity_reservations_per_workflow_task=3, graceful_shutdown_period_millis=0, versioning_strategy=temporalio.bridge.worker.WorkerVersioningStrategyNone( build_id_no_versioning=self._config.get("build_id") diff --git a/temporalio/worker/_worker.py b/temporalio/worker/_worker.py index 5e2d8ce58..77c96866e 100644 --- a/temporalio/worker/_worker.py +++ b/temporalio/worker/_worker.py @@ -129,6 +129,7 @@ def __init__( default_heartbeat_throttle_interval: timedelta = timedelta(seconds=30), max_activities_per_second: float | None = None, max_task_queue_activities_per_second: float | None = None, + max_eager_activity_reservations_per_workflow_task: int = 3, graceful_shutdown_timeout: timedelta = timedelta(), workflow_failure_exception_types: Sequence[type[BaseException]] = [], shared_state_manager: SharedStateManager | None = None, @@ -267,6 +268,11 @@ def __init__( poll request. If multiple workers on the same queue have different values set, they will thrash with the last poller winning. + max_eager_activity_reservations_per_workflow_task: Maximum number of + activity slots that may be reserved for eager execution when + completing a workflow task. The default is 3 and the value must + be positive. To disable eager activity execution, set + ``disable_eager_activity_execution`` to ``True``. graceful_shutdown_timeout: Amount of time after shutdown is called that activities are given to complete before their tasks are cancelled. @@ -369,6 +375,7 @@ def __init__( default_heartbeat_throttle_interval=default_heartbeat_throttle_interval, max_activities_per_second=max_activities_per_second, max_task_queue_activities_per_second=max_task_queue_activities_per_second, + max_eager_activity_reservations_per_workflow_task=max_eager_activity_reservations_per_workflow_task, graceful_shutdown_timeout=graceful_shutdown_timeout, workflow_failure_exception_types=workflow_failure_exception_types, shared_state_manager=shared_state_manager, @@ -445,6 +452,11 @@ def _init_from_config(self, client: temporalio.client.Client, config: WorkerConf raise ValueError( "max_workflow_task_external_storage_concurrency must be positive" ) + if config.get("max_eager_activity_reservations_per_workflow_task", 3) < 1: + raise ValueError( + "max_eager_activity_reservations_per_workflow_task must be positive; " + "use disable_eager_activity_execution=True to disable eager activity execution" + ) # Prepend applicable client interceptors to the given ones client_config = config["client"].config(active_config=True) # type: ignore[reportTypedDictNotRequiredAccess] @@ -657,6 +669,9 @@ def check_activity(activity: str): max_task_queue_activities_per_second=config[ "max_task_queue_activities_per_second" ], # type: ignore[reportTypedDictNotRequiredAccess] + max_eager_activity_reservations_per_workflow_task=config[ + "max_eager_activity_reservations_per_workflow_task" + ], # type: ignore[reportTypedDictNotRequiredAccess] graceful_shutdown_period_millis=int( 1000 * config["graceful_shutdown_timeout"].total_seconds() # type: ignore[reportTypedDictNotRequiredAccess] ), @@ -977,6 +992,7 @@ class WorkerConfig(TypedDict, total=False): default_heartbeat_throttle_interval: timedelta max_activities_per_second: float | None max_task_queue_activities_per_second: float | None + max_eager_activity_reservations_per_workflow_task: int graceful_shutdown_timeout: timedelta workflow_failure_exception_types: Sequence[type[BaseException]] shared_state_manager: SharedStateManager | None diff --git a/tests/worker/test_worker.py b/tests/worker/test_worker.py index 1834af829..3a4e9165b 100644 --- a/tests/worker/test_worker.py +++ b/tests/worker/test_worker.py @@ -1744,6 +1744,37 @@ def test_worker_config_matches_init_params(): ) +async def test_worker_max_eager_activity_reservations_per_workflow_task_config( + client: Client, +): + worker = Worker( + client, + workflows=[SimpleWorkflow], + task_queue=f"task-queue-{uuid.uuid4()}", + max_eager_activity_reservations_per_workflow_task=7, + ) + assert worker.config().get("max_eager_activity_reservations_per_workflow_task") == 7 + + +@pytest.mark.parametrize("value", [0, -1]) +async def test_worker_rejects_non_positive_max_eager_activity_reservations( + client: Client, value: int +): + with pytest.raises( + ValueError, + match=( + "max_eager_activity_reservations_per_workflow_task must be positive; " + "use disable_eager_activity_execution=True to disable eager activity execution" + ), + ): + Worker( + client, + workflows=[SimpleWorkflow], + task_queue=f"task-queue-{uuid.uuid4()}", + max_eager_activity_reservations_per_workflow_task=value, + ) + + async def test_worker_debug_mode(client: Client): worker = Worker( client, From 70ef047ce6a4629732730d0114dbcde15d9739e3 Mon Sep 17 00:00:00 2001 From: Alex Mazzeo Date: Mon, 27 Jul 2026 14:30:12 -0700 Subject: [PATCH 184/226] Unify payload visitation into a single implementation by combining explicit roots and discovered system nexus roots (#1684) --- scripts/gen_payload_visitor.py | 14 +-- temporalio/bridge/_visitor.py | 22 ++++ temporalio/nexus/system/__init__.py | 2 +- temporalio/nexus/system/_payload_visitor.py | 131 -------------------- 4 files changed, 24 insertions(+), 145 deletions(-) delete mode 100644 temporalio/nexus/system/_payload_visitor.py diff --git a/scripts/gen_payload_visitor.py b/scripts/gen_payload_visitor.py index c2bc15837..fa28cb455 100644 --- a/scripts/gen_payload_visitor.py +++ b/scripts/gen_payload_visitor.py @@ -425,28 +425,18 @@ def walk(self, desc: Descriptor) -> bool: def write_bridge_visitors() -> None: out_path = base_dir / "temporalio" / "bridge" / "_visitor.py" - # Build root descriptors: WorkflowActivation, WorkflowActivationCompletion, - # and all messages from selected API modules roots: list[Descriptor] = [ WorkflowActivation.DESCRIPTOR, WorkflowActivationCompletion.DESCRIPTOR, - ] + ] + discover_system_nexus_roots() code = VisitorGenerator().generate(roots) out_path.write_text(code) -def write_system_nexus_payload_visitors() -> None: - out_path = base_dir / "temporalio" / "nexus" / "system" / "_payload_visitor.py" - code = VisitorGenerator().generate(discover_system_nexus_roots()) - out_path.write_text(code) - - if __name__ == "__main__": print("Generating temporalio/bridge/_visitor.py...", file=sys.stderr) write_bridge_visitors() - print("Generating temporalio/nexus/system/_payload_visitor.py...", file=sys.stderr) - write_system_nexus_payload_visitors() subprocess.run( [ "uv", @@ -457,7 +447,6 @@ def write_system_nexus_payload_visitors() -> None: "I", "--fix", "temporalio/bridge/_visitor.py", - "temporalio/nexus/system/_payload_visitor.py", ], cwd=base_dir, check=True, @@ -469,7 +458,6 @@ def write_system_nexus_payload_visitors() -> None: "ruff", "format", "temporalio/bridge/_visitor.py", - "temporalio/nexus/system/_payload_visitor.py", ], cwd=base_dir, check=True, diff --git a/temporalio/bridge/_visitor.py b/temporalio/bridge/_visitor.py index a9956e12b..974b4f77d 100644 --- a/temporalio/bridge/_visitor.py +++ b/temporalio/bridge/_visitor.py @@ -549,3 +549,25 @@ async def _visit_coresdk_workflow_completion_WorkflowActivationCompletion( await self._visit_coresdk_workflow_completion_Success(fs, o.successful) elif o.HasField("failed"): await self._visit_coresdk_workflow_completion_Failure(fs, o.failed) + + async def _visit_temporal_api_common_v1_Header(self, fs: VisitorFunctions, o: Any): + for v in o.fields.values(): + await self._visit_temporal_api_common_v1_Payload(fs, v) + + async def _visit_temporal_api_workflowservice_v1_SignalWithStartWorkflowExecutionRequest( + self, fs: VisitorFunctions, o: Any + ): + if o.HasField("input"): + await self._visit_temporal_api_common_v1_Payloads(fs, o.input) + if o.HasField("signal_input"): + await self._visit_temporal_api_common_v1_Payloads(fs, o.signal_input) + if o.HasField("memo"): + await self._visit_temporal_api_common_v1_Memo(fs, o.memo) + if o.HasField("search_attributes"): + await self._visit_temporal_api_common_v1_SearchAttributes( + fs, o.search_attributes + ) + if o.HasField("header"): + await self._visit_temporal_api_common_v1_Header(fs, o.header) + if o.HasField("user_metadata"): + await self._visit_temporal_api_sdk_v1_UserMetadata(fs, o.user_metadata) diff --git a/temporalio/nexus/system/__init__.py b/temporalio/nexus/system/__init__.py index 14a43cb72..7c83229c1 100644 --- a/temporalio/nexus/system/__init__.py +++ b/temporalio/nexus/system/__init__.py @@ -106,7 +106,7 @@ async def _maybe_visit_payload( # pyright: ignore[reportUnusedFunction] payload_converter = _SystemNexusOuterPayloadConverter() value = payload_converter.from_payload(payload) - from ._payload_visitor import PayloadVisitor + from temporalio.bridge._visitor import PayloadVisitor await PayloadVisitor(skip_search_attributes=skip_search_attributes).visit( visitor_functions, value diff --git a/temporalio/nexus/system/_payload_visitor.py b/temporalio/nexus/system/_payload_visitor.py deleted file mode 100644 index 4f194168f..000000000 --- a/temporalio/nexus/system/_payload_visitor.py +++ /dev/null @@ -1,131 +0,0 @@ -from __future__ import annotations - -# This file is generated by gen_payload_visitor.py. Changes should be made there. -from typing import Any - -import temporalio.nexus.system -from temporalio.api.common.v1.message_pb2 import Payload -from temporalio.bridge._visitor_functions import ( - BoundedVisitorFunctions, - PayloadSequence, - VisitorFunctions, -) - - -class PayloadVisitor: - """A visitor for payloads. - Applies a function to every payload in a tree of messages. - """ - - def __init__( - self, - *, - skip_search_attributes: bool = False, - skip_headers: bool = False, - concurrency_limit: int = 1, - ): - """Creates a new payload visitor. - - Args: - skip_search_attributes: If True, search attributes are not visited. - skip_headers: If True, headers are not visited. - concurrency_limit: Maximum number of payload visits that may run - concurrently during a single call to visit(). Defaults to 1 - (sequential). - """ - if concurrency_limit < 1: - raise ValueError("concurrency_limit must be positive") - self.skip_search_attributes = skip_search_attributes - self.skip_headers = skip_headers - self._concurrency_limit = concurrency_limit - - async def visit(self, fs: VisitorFunctions, root: Any) -> None: - """Visits the given root message with the given function.""" - method_name = "_visit_" + root.DESCRIPTOR.full_name.replace(".", "_") - method = getattr(self, method_name, None) - if method is None: - raise ValueError(f"Unknown root message type: {root.DESCRIPTOR.full_name}") - if self._concurrency_limit == 1: - await method(fs, root) - return - - bounded = BoundedVisitorFunctions(fs, self._concurrency_limit) - try: - await method(bounded, root) - finally: - await bounded.drain() - - async def _visit_nexus_operation_input_payload( - self, - fs: VisitorFunctions, - endpoint: str, - payload: Payload, - ) -> None: - new_payload = await temporalio.nexus.system._maybe_visit_payload( - endpoint, - payload, - fs, - self.skip_search_attributes, - ) - if new_payload is None: - await self._visit_temporal_api_common_v1_Payload(fs, payload) - return - - if new_payload is not payload: - payload.CopyFrom(new_payload) - await fs.visit_system_nexus_envelope(payload) - - async def _visit_temporal_api_common_v1_Payload( - self, fs: VisitorFunctions, o: Payload - ): - await fs.visit_payload(o) - - async def _visit_temporal_api_common_v1_Payloads( - self, fs: VisitorFunctions, o: Any - ): - await fs.visit_payloads(o.payloads) - - async def _visit_payload_container(self, fs: VisitorFunctions, o: PayloadSequence): - await fs.visit_payloads(o) - - async def _visit_temporal_api_common_v1_Memo(self, fs: VisitorFunctions, o: Any): - for v in o.fields.values(): - await self._visit_temporal_api_common_v1_Payload(fs, v) - - async def _visit_temporal_api_common_v1_SearchAttributes( - self, fs: VisitorFunctions, o: Any - ): - if self.skip_search_attributes: - return - for v in o.indexed_fields.values(): - await self._visit_temporal_api_common_v1_Payload(fs, v) - - async def _visit_temporal_api_common_v1_Header(self, fs: VisitorFunctions, o: Any): - for v in o.fields.values(): - await self._visit_temporal_api_common_v1_Payload(fs, v) - - async def _visit_temporal_api_sdk_v1_UserMetadata( - self, fs: VisitorFunctions, o: Any - ): - if o.HasField("summary"): - await self._visit_temporal_api_common_v1_Payload(fs, o.summary) - if o.HasField("details"): - await self._visit_temporal_api_common_v1_Payload(fs, o.details) - - async def _visit_temporal_api_workflowservice_v1_SignalWithStartWorkflowExecutionRequest( - self, fs: VisitorFunctions, o: Any - ): - if o.HasField("input"): - await self._visit_temporal_api_common_v1_Payloads(fs, o.input) - if o.HasField("signal_input"): - await self._visit_temporal_api_common_v1_Payloads(fs, o.signal_input) - if o.HasField("memo"): - await self._visit_temporal_api_common_v1_Memo(fs, o.memo) - if o.HasField("search_attributes"): - await self._visit_temporal_api_common_v1_SearchAttributes( - fs, o.search_attributes - ) - if o.HasField("header"): - await self._visit_temporal_api_common_v1_Header(fs, o.header) - if o.HasField("user_metadata"): - await self._visit_temporal_api_sdk_v1_UserMetadata(fs, o.user_metadata) From 5df71923411726656f22f89be5d4d988fd6f8020 Mon Sep 17 00:00:00 2001 From: Alex Mazzeo Date: Mon, 27 Jul 2026 15:36:13 -0700 Subject: [PATCH 185/226] Add type_hint to TransferTypeConverter.from_transfer_type (#1685) * Add type_hint to TransferTypeConverter.from_transfer_type to allow inspection of type args during conversion * Run formatter --- temporalio/converter/_payload_converter.py | 13 +++- tests/test_converter.py | 71 ++++++++++++++++++++++ 2 files changed, 81 insertions(+), 3 deletions(-) diff --git a/temporalio/converter/_payload_converter.py b/temporalio/converter/_payload_converter.py index f10b6a4e0..a8bc35e28 100644 --- a/temporalio/converter/_payload_converter.py +++ b/temporalio/converter/_payload_converter.py @@ -81,9 +81,14 @@ def to_transfer_type(self, value: ValueT) -> TransferTypeT: raise NotImplementedError @abstractmethod - def from_transfer_type(self, value: TransferTypeT) -> ValueT: + def from_transfer_type( + self, value: TransferTypeT, type_hint: type[ValueT] + ) -> ValueT: """Convert a transfer type value to its user-facing value. + ``type_hint`` is the requested user-facing type, including concrete + generic arguments. + .. warning:: This API is experimental and subject to change. """ @@ -638,8 +643,10 @@ def from_payloads( payloads, typing.cast("list[type]", inner_type_hints) ) return [ - converter.from_transfer_type(value) if converter is not None else value - for value, converter in zip(values, converters) + converter.from_transfer_type(value, type_hint) + if converter is not None + else value + for value, converter, type_hint in zip(values, converters, type_hints) ] def with_context(self, context: SerializationContext) -> Self: diff --git a/tests/test_converter.py b/tests/test_converter.py index b5e10c518..f1a056c5f 100644 --- a/tests/test_converter.py +++ b/tests/test_converter.py @@ -6,6 +6,7 @@ import logging import sys import traceback +import typing from collections import deque from collections.abc import Iterable, Mapping, MutableMapping, Sequence from dataclasses import dataclass @@ -14,8 +15,11 @@ from typing import ( Any, Dict, # type:ignore[reportDeprecated] + Generic, Literal, NewType, + TypeVar, + cast, get_args, get_type_hints, ) @@ -278,6 +282,7 @@ def to_transfer_type( def from_transfer_type( self, value: temporalio.api.common.v1.WorkflowExecution, + type_hint: type[TemporalTransferTypeValue], ) -> TemporalTransferTypeValue: return TemporalTransferTypeValue(value=value.workflow_id) @@ -305,6 +310,7 @@ def to_transfer_type( def from_transfer_type( self, value: temporalio.api.common.v1.WorkflowExecution, + type_hint: type[TemporalTransferTypeValueWithoutHint], ) -> TemporalTransferTypeValueWithoutHint: return TemporalTransferTypeValueWithoutHint(value=value.workflow_id) @@ -315,6 +321,47 @@ class TemporalTransferTypeValueWithoutHint: value: str +T = TypeVar("T") + + +@dataclass +class TemporalTransferTypeGenericValue(Generic[T]): + value: T + + +class TemporalTransferTypeGenericValueConverter( + TransferTypeConverter[ + TemporalTransferTypeGenericValue[T], + temporalio.api.common.v1.WorkflowExecution, + ] +): + transfer_type = temporalio.api.common.v1.WorkflowExecution + + def to_transfer_type( + self, value: TemporalTransferTypeGenericValue[T] + ) -> temporalio.api.common.v1.WorkflowExecution: + return temporalio.api.common.v1.WorkflowExecution( + workflow_id=str(value.value), + run_id="run-id", + ) + + def from_transfer_type( + self, + value: temporalio.api.common.v1.WorkflowExecution, + type_hint: type[TemporalTransferTypeGenericValue[T]], + ) -> TemporalTransferTypeGenericValue[T]: + converted_value: str | int = value.workflow_id + if typing.get_args(type_hint)[0] is int: + converted_value = int(converted_value) + return TemporalTransferTypeGenericValue(value=cast(T, converted_value)) + + +# Register after both classes are defined so the generic type can be resolved. +transfer_type_convertible(TemporalTransferTypeGenericValueConverter)( + TemporalTransferTypeGenericValue +) + + class CustomDefaultPayloadConverter(DefaultPayloadConverter): pass @@ -358,6 +405,30 @@ def test_temporal_transfer_type_payload_converter_without_transfer_type_hint(): ) +@pytest.mark.parametrize( + ("value", "type_hint"), + [ + ( + TemporalTransferTypeGenericValue("workflow-id"), + TemporalTransferTypeGenericValue[str], + ), + ( + TemporalTransferTypeGenericValue(123), + TemporalTransferTypeGenericValue[int], + ), + ], +) +def test_temporal_transfer_type_payload_converter_with_generic_value( + value: TemporalTransferTypeGenericValue[T], + type_hint: type[TemporalTransferTypeGenericValue[T]], +): + converter = DataConverter.default.payload_converter + + payload = converter.to_payload(value) + + assert converter.from_payload(payload, type_hint) == value + + def test_transfer_type_convertible_rejects_existing_converter(): with pytest.raises(TypeError, match="already has a transfer type converter"): transfer_type_convertible(TemporalTransferTypeValueConverter)( From a66bca14a59686174e89fcd0eac75d5f3ef03fea Mon Sep 17 00:00:00 2001 From: Spencer Judge Date: Mon, 27 Jul 2026 15:37:20 -0700 Subject: [PATCH 186/226] Fix cancellations being swallowed in some circumstances (#1671) * Reintroduce applying all jobs in activation * Dedupe await logic * Avoid monkeypatching / expand coverage * Remove query-specific job handling * Fix tests on java server --- CHANGELOG.md | 9 + temporalio/worker/_replayer.py | 19 +- temporalio/worker/_worker.py | 12 + temporalio/worker/_workflow.py | 17 + temporalio/worker/_workflow_instance.py | 294 ++++++----- tests/worker/test_replayer.py | 127 ++++- ...cing_double_sig_at_start_single_batch.json | 433 ++++++++++++++++ ...t_replayer_event_tracing_single_batch.json | 479 ++++++++++++++++++ tests/worker/test_workflow.py | 364 ++++++++++++- 9 files changed, 1600 insertions(+), 154 deletions(-) create mode 100644 tests/worker/test_replayer_event_tracing_double_sig_at_start_single_batch.json create mode 100644 tests/worker/test_replayer_event_tracing_single_batch.json diff --git a/CHANGELOG.md b/CHANGELOG.md index 0de28b563..d04c73594 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -41,6 +41,15 @@ to include examples, links to docs, or any other relevant information. ### Changed +- Prepared replay-safe workflow activation scheduling that prevents cancellation + from being lost when another event becomes ready in the same workflow task. The + behavior is guarded by internal workflow logic flag 2 and remains disabled by + default during its compatibility rollout. + **Maintainer reminder:** keep flag 2 default-disabled for the first two published + SDK releases that recognize it; enable it in the third release, remove the explicit + overrides for this flag from `tests/worker/test_workflow.py`, and replace this rollout + note with a `Fixed` entry announcing the behavior change. + ### Deprecated ### Breaking Changes diff --git a/temporalio/worker/_replayer.py b/temporalio/worker/_replayer.py index dfd348f8a..b3eb1a4d1 100644 --- a/temporalio/worker/_replayer.py +++ b/temporalio/worker/_replayer.py @@ -24,7 +24,12 @@ from ._interceptor import Interceptor from ._worker import load_default_build_id from ._workflow import _WorkflowWorker -from ._workflow_instance import UnsandboxedWorkflowRunner, WorkflowRunner +from ._workflow_instance import ( + _DEFAULT_ENABLED_WORKFLOW_LOGIC_FLAGS, + UnsandboxedWorkflowRunner, + WorkflowRunner, + _WorkflowLogicFlag, +) from .workflow_sandbox import SandboxedWorkflowRunner logger = logging.getLogger(__name__) @@ -83,6 +88,7 @@ def __init__( header_codec_behavior=header_codec_behavior, ) self._initial_config = self._config.copy() + self._default_workflow_logic_flags = set(_DEFAULT_ENABLED_WORKFLOW_LOGIC_FLAGS) # Apply plugin configuration self.plugins = plugins @@ -93,6 +99,14 @@ def __init__( if not self._config.get("workflows"): raise ValueError("At least one workflow must be specified") + def _set_default_workflow_logic_flag( + self, flag: _WorkflowLogicFlag, *, enabled: bool + ) -> None: + if enabled: + self._default_workflow_logic_flags.add(flag) + else: + self._default_workflow_logic_flags.discard(flag) + def config(self, *, active_config: bool = False) -> ReplayerConfig: """Config, as a dictionary, used to create this replayer. @@ -270,6 +284,9 @@ def on_eviction_hook( ) != HeaderCodecBehavior.NO_CODEC, max_workflow_task_external_storage_concurrency=1, + default_workflow_logic_flags=frozenset( + self._default_workflow_logic_flags + ), ) external_storage = data_converter.external_storage storage_driver_types = ( diff --git a/temporalio/worker/_worker.py b/temporalio/worker/_worker.py index 77c96866e..60f824c4d 100644 --- a/temporalio/worker/_worker.py +++ b/temporalio/worker/_worker.py @@ -43,6 +43,7 @@ PatchActivationInput, UnsandboxedWorkflowRunner, WorkflowRunner, + _WorkflowLogicFlag, ) from .workflow_sandbox import SandboxedWorkflowRunner @@ -750,6 +751,17 @@ def client(self, value: temporalio.client.Client) -> None: if self._nexus_worker: self._nexus_worker._client = value + def _set_default_workflow_logic_flag( + self, flag: _WorkflowLogicFlag, *, enabled: bool + ) -> None: + if self._started: + raise RuntimeError( + "Cannot set default workflow logic flags after the worker has started" + ) + if not self._workflow_worker: + raise RuntimeError("Cannot set workflow logic flags without workflows") + self._workflow_worker._set_default_workflow_logic_flag(flag, enabled=enabled) + @property def is_running(self) -> bool: """Whether the worker is running. diff --git a/temporalio/worker/_workflow.py b/temporalio/worker/_workflow.py index 900d14b43..c031b5653 100644 --- a/temporalio/worker/_workflow.py +++ b/temporalio/worker/_workflow.py @@ -40,11 +40,13 @@ WorkflowInterceptorClassInput, ) from ._workflow_instance import ( + _DEFAULT_ENABLED_WORKFLOW_LOGIC_FLAGS, PatchActivationInput, WorkflowInstance, WorkflowInstanceDetails, WorkflowRunner, _WorkflowExternFunctions, + _WorkflowLogicFlag, ) logger = logging.getLogger(__name__) @@ -90,6 +92,7 @@ def __init__( assert_local_activity_valid: Callable[[str], None], encode_headers: bool, max_workflow_task_external_storage_concurrency: int, + default_workflow_logic_flags: frozenset[_WorkflowLogicFlag] | None = None, ) -> None: # Debug mode is enabled if specified or if the TEMPORAL_DEBUG env var is truthy debug_mode = debug_mode or bool(os.environ.get("TEMPORAL_DEBUG")) @@ -97,6 +100,11 @@ def __init__( self._bridge_worker = bridge_worker self._namespace = namespace self._task_queue = task_queue + self._default_workflow_logic_flags = set( + _DEFAULT_ENABLED_WORKFLOW_LOGIC_FLAGS + if default_workflow_logic_flags is None + else default_workflow_logic_flags + ) self._workflow_task_executor = ( workflow_task_executor or concurrent.futures.ThreadPoolExecutor( @@ -788,6 +796,7 @@ def _create_workflow_instance( patch_activation_callback=self._patch_activation_callback, last_completion_result=init.last_completion_result, last_failure=last_failure, + default_workflow_logic_flags=frozenset(self._default_workflow_logic_flags), ) if defn.sandboxed: return self._workflow_runner.create_instance(det) @@ -800,6 +809,14 @@ def nondeterminism_as_workflow_fail(self) -> bool: for typ in self._workflow_failure_exception_types ) + def _set_default_workflow_logic_flag( + self, flag: _WorkflowLogicFlag, *, enabled: bool + ) -> None: + if enabled: + self._default_workflow_logic_flags.add(flag) + else: + self._default_workflow_logic_flags.discard(flag) + def nondeterminism_as_workflow_fail_for_types(self) -> set[str]: return { k diff --git a/temporalio/worker/_workflow_instance.py b/temporalio/worker/_workflow_instance.py index 76b3304ef..d0b10ccae 100644 --- a/temporalio/worker/_workflow_instance.py +++ b/temporalio/worker/_workflow_instance.py @@ -27,7 +27,7 @@ Sequence, ) from contextlib import contextmanager -from dataclasses import dataclass +from dataclasses import dataclass, field from datetime import timedelta from enum import IntEnum from typing import ( @@ -169,6 +169,9 @@ class WorkflowInstanceDetails: patch_activation_callback: Callable[[PatchActivationInput], bool] | None last_completion_result: temporalio.api.common.v1.Payloads last_failure: Failure | None + default_workflow_logic_flags: frozenset[_WorkflowLogicFlag] = field( + default_factory=lambda: _DEFAULT_ENABLED_WORKFLOW_LOGIC_FLAGS + ) class WorkflowInstance(ABC): @@ -288,7 +291,9 @@ def __init__(self, det: WorkflowInstanceDetails) -> None: det.worker_level_failure_exception_types ) self._patch_activation_callback = det.patch_activation_callback + self._default_workflow_logic_flags = det.default_workflow_logic_flags self._primary_task: asyncio.Task[None] | None = None + self._cancel_primary_task_pending = False self._time_ns = 0 self._cancel_reason: str | None = None self._deployment_version_for_current_task: None | ( @@ -459,6 +464,9 @@ def activate( self._is_replaying = act.is_replaying self._current_thread_id = threading.get_ident() self._current_internal_flags = act.available_internal_flags + self._single_batch_activation = self._workflow_logic_flag_enabled( + _WorkflowLogicFlag.PROCESS_WORKFLOW_ACTIVATION_JOBS_AS_SINGLE_BATCH + ) activation_err: Exception | None = None try: # Split into job sets with patches, then signals + updates, then @@ -479,21 +487,39 @@ def activate( else: job_sets[3].append(job) + # Core guarantees query-only activations. Fail the workflow task if violated. + assert not job_sets[3] or not any(job_sets[:3]), ( + "Query jobs must not share an activation with non-query jobs. " + "This is an SDK Core bug." + ) + if start_job: self._workflow_input = self._make_workflow_input(start_job) - # Apply every job set, running after each set - for index, job_set in enumerate(job_sets): - if not job_set: - continue - for job in job_set: - # Let errors bubble out of these to the caller to fail the task - self._apply(job) - - # Run one iteration of the loop. We do not allow conditions to - # be checked in patch jobs (first index) or query jobs (last - # index). - self._run_once(check_conditions=index == 1 or index == 2) + if self._single_batch_activation: + # Applying every job before giving workflow tasks a chance to + # run prevents their order in the activation from hiding state + # that arrived in the same workflow task. + for job_set in job_sets: + for job in job_set: + # Let errors bubble out of these to the caller to fail the task + self._apply(job) + if any(job_sets): + self._run_once(check_conditions=bool(job_sets[1] or job_sets[2])) + else: + # Preserve the legacy scheduling order for histories which do + # not contain the single-batch workflow logic flag. + for index, job_set in enumerate(job_sets): + if not job_set: + continue + for job in job_set: + # Let errors bubble out of these to the caller to fail the task + self._apply(job) + + # Run one iteration of the loop. We do not allow conditions to + # be checked in patch jobs (first index) or query jobs (last + # index). + self._run_once(check_conditions=index == 1 or index == 2) except Exception as err: # We want some errors during activation, like those that can happen # during payload conversion, to be able to fail the workflow not the @@ -628,6 +654,10 @@ def _apply_cancel_workflow( # workflow the ability to receive the cancellation, so we must defer # this cancellation to the next iteration of the event loop. self.call_soon(self._primary_task.cancel) + elif self._single_batch_activation: + # Initialization is the only job that creates the primary task, so + # retain a same-activation cancellation until that task exists. + self._cancel_primary_task_pending = True def _apply_do_update( self, job: temporalio.bridge.proto.workflow_activation.DoUpdate @@ -1121,6 +1151,9 @@ async def run_workflow(input: ExecuteWorkflowInput) -> None: self._run_top_level_workflow_function(run_workflow(self._workflow_input)), name="run", ) + if self._cancel_primary_task_pending: + self._cancel_primary_task_pending = False + self.call_soon(self._primary_task.cancel) def _apply_update_random_seed( self, job: temporalio.bridge.proto.workflow_activation.UpdateRandomSeed @@ -1832,6 +1865,19 @@ async def workflow_wait_condition( timeout_summary: str | None = None, ) -> None: self._assert_not_read_only("wait condition") + cancellation_requested_before = self._cancel_reason is not None + + # Some asyncio.wait_for implementations can prefer a ready condition + # result or timeout over task cancellation that becomes ready in the same + # event-loop turn. Only detect a new request so workflows can catch + # cancellation and keep going. + def cancellation_arrived() -> bool: + return ( + self._single_batch_activation + and not cancellation_requested_before + and self._cancel_reason is not None + ) + fut = self.create_future() self._conditions.append((fn, fut)) user_metadata = ( @@ -1849,7 +1895,14 @@ async def in_context(): _TimerOptionsCtxVar.set(_TimerOptions(user_metadata=user_metadata)) await asyncio.wait_for(fut, timeout) - await ctxvars.run(in_context) + try: + await ctxvars.run(in_context) + except asyncio.TimeoutError: + if cancellation_arrived(): + raise asyncio.CancelledError() + raise + if cancellation_arrived(): + raise asyncio.CancelledError() def workflow_get_current_details(self) -> str: return self._current_details @@ -1938,10 +1991,11 @@ async def run_activity() -> Any: # be marked as unstarted handle._started = True try: - # We use _shield_await instead of asyncio.shield to prevent - # the underlying result future from being cancelled while avoiding - # a spurious error log on Python 3.11+ (see issue #1600). - return await _shield_await(handle._result_fut) + return await self._await_temporal_operation( + handle._result_fut, + lambda _err, command: handle._apply_cancel_command(command), + completed_cancellation_flag=_WorkflowLogicFlag.RAISE_ON_CANCELLING_COMPLETED_ACTIVITY, + ) except _ActivityDoBackoffError as err: # We have to sleep then reschedule. Note this sleep can be # cancelled like any other timer. @@ -1952,28 +2006,6 @@ async def run_activity() -> Any: # We have to put the handle back on the pending activity # dict with its new seq self._pending_activities[handle._seq] = handle - except asyncio.CancelledError: - # If an activity future completes at the same time as a cancellation is being processed, the cancellation would be swallowed - # _WorkflowLogicFlag.RAISE_ON_CANCELLING_COMPLETED_ACTIVITY will correctly reraise the exception - if handle._result_fut.done(): - if ( - not self._is_replaying - or _WorkflowLogicFlag.RAISE_ON_CANCELLING_COMPLETED_ACTIVITY - in self._current_internal_flags - ): - self._current_completion.successful.used_internal_flags.append( - _WorkflowLogicFlag.RAISE_ON_CANCELLING_COMPLETED_ACTIVITY - ) - raise - # Send a cancel request to the activity - handle._apply_cancel_command(self._add_command()) - # Clear the cancellation counter on Python 3.11+ so the - # next await does not immediately re-raise CancelledError - if ( - sys.version_info >= (3, 11) - and (t := asyncio.current_task()) is not None - ): - t.uncancel() # type: ignore[union-attr] # Create the handle and set as pending handle = _ActivityHandle(self, input, run_activity()) @@ -2030,11 +2062,13 @@ async def _outbound_start_child_workflow( handle: _ChildWorkflowHandle # Common code for handling cancel for start and run - def apply_child_cancel_error(err: asyncio.CancelledError) -> None: + def apply_child_cancel_error( + err: asyncio.CancelledError, + cancel_command: temporalio.bridge.proto.workflow_commands.WorkflowCommand, + ) -> None: # Send a cancel request to the child, forwarding the msg passed to # Task.cancel(msg) (if any) as the cancellation reason. reason = err.args[0] if err.args and isinstance(err.args[0], str) else "" - cancel_command = self._add_command() handle._apply_cancel_command(cancel_command, reason=reason) # If the cancel command is for external workflow, we # have to add a seq and mark it pending @@ -2053,21 +2087,9 @@ def apply_child_cancel_error(err: asyncio.CancelledError) -> None: # Function that runs in the handle async def run_child() -> Any: - while True: - try: - # We use _shield_await instead of asyncio.shield to prevent - # the future itself from being cancelled while avoiding a - # spurious error log on Python 3.11+ (see issue #1600). - return await _shield_await(handle._result_fut) - except asyncio.CancelledError as err: - apply_child_cancel_error(err) - # Clear the cancellation counter on Python 3.11+ so the - # next await does not immediately re-raise CancelledError - if ( - sys.version_info >= (3, 11) - and (t := asyncio.current_task()) is not None - ): - t.uncancel() # type: ignore[union-attr] + return await self._await_temporal_operation( + handle._result_fut, apply_child_cancel_error + ) # Create the handle and set as pending handle = _ChildWorkflowHandle( @@ -2077,24 +2099,12 @@ async def run_child() -> Any: self._pending_child_workflows[handle._seq] = handle # Wait on start before returning - while True: - try: - # We use _shield_await instead of asyncio.shield to prevent - # the future itself from being cancelled while avoiding a - # spurious error log on Python 3.11+ (see issue #1600). - await _shield_await(handle._start_fut) - return handle - except asyncio.CancelledError as err: - apply_child_cancel_error(err) - # Clear the cancellation counter on Python 3.11+ so the - # next await does not immediately re-raise CancelledError - if ( - sys.version_info >= (3, 11) - and (t := asyncio.current_task()) is not None - ): - t.uncancel() # type: ignore[union-attr] - if self._cancel_reason is not None or self._deleting: - raise + await self._await_temporal_operation( + handle._start_fut, + apply_child_cancel_error, + reraise_on_workflow_cancellation=True, + ) + return handle async def _outbound_start_nexus_operation( self, input: StartNexusOperationInput[Any, OutputT] @@ -2115,19 +2125,13 @@ async def _outbound_start_nexus_operation( handle: _NexusOperationHandle[OutputT] async def operation_handle_fn() -> OutputT: - while True: - try: - return cast(OutputT, await _shield_await(handle._result_fut)) - except asyncio.CancelledError: - cancel_command = self._add_command() - handle._apply_cancel_command(cancel_command) - # Clear the cancellation counter on Python 3.11+ so the - # next await does not immediately re-raise CancelledError - if ( - sys.version_info >= (3, 11) - and (t := asyncio.current_task()) is not None - ): - t.uncancel() # type: ignore[union-attr] + return cast( + OutputT, + await self._await_temporal_operation( + handle._result_fut, + lambda _err, command: handle._apply_cancel_command(command), + ), + ) payload_converter = ( temporalio.nexus.system._get_payload_converter( @@ -2146,25 +2150,12 @@ async def operation_handle_fn() -> OutputT: handle._apply_schedule_command() self._pending_nexus_operations[handle._seq] = handle - while True: - try: - # We use _shield_await instead of asyncio.shield to prevent - # the future itself from being cancelled while avoiding a - # spurious error log on Python 3.11+ (see issue #1600). - await _shield_await(handle._start_fut) - return handle - except asyncio.CancelledError: - cancel_command = self._add_command() - handle._apply_cancel_command(cancel_command) - # Clear the cancellation counter on Python 3.11+ so the - # next await does not immediately re-raise CancelledError - if ( - sys.version_info >= (3, 11) - and (t := asyncio.current_task()) is not None - ): - t.uncancel() # type: ignore[union-attr] - if self._cancel_reason is not None or self._deleting: - raise + await self._await_temporal_operation( + handle._start_fut, + lambda _err, command: handle._apply_cancel_command(command), + reraise_on_workflow_cancellation=True, + ) + return handle #### Miscellaneous helpers #### # These are in alphabetical order. @@ -2173,6 +2164,14 @@ def _add_command(self) -> temporalio.bridge.proto.workflow_commands.WorkflowComm self._assert_not_read_only("add command") return self._current_completion.successful.commands.add() + def _workflow_logic_flag_enabled(self, flag: _WorkflowLogicFlag) -> bool: + if flag in self._current_internal_flags: + return True + if self._is_replaying or flag not in self._default_workflow_logic_flags: + return False + self._current_completion.successful.used_internal_flags.append(flag) + return True + @contextmanager def _as_read_only(self, *, in_query_or_validator: bool) -> Iterator[None]: prev_read_only = self._read_only @@ -2197,6 +2196,56 @@ def _assert_not_read_only( f"While in read-only function, action attempted: {action_attempted}" ) + async def _await_temporal_operation( + self, + fut: asyncio.Future[_T], + apply_cancel: Callable[ + [ + asyncio.CancelledError, + temporalio.bridge.proto.workflow_commands.WorkflowCommand, + ], + None, + ], + *, + completed_cancellation_flag: _WorkflowLogicFlag | None = None, + reraise_on_workflow_cancellation: bool = False, + ) -> _T: + while True: + try: + # Protect the operation's result from task cancellation so a + # Temporal cancellation command can decide its outcome. The + # custom shield also avoids spurious error logs on Python 3.11+. + return await _shield_await(fut) + except asyncio.CancelledError as err: + if fut.done(): + # Retrying the shield after both futures become ready would + # return the result and erase the task cancellation. + if self._single_batch_activation: + raise + if completed_cancellation_flag is not None and ( + not self._is_replaying + or completed_cancellation_flag in self._current_internal_flags + ): + self._current_completion.successful.used_internal_flags.append( + completed_cancellation_flag + ) + raise + + apply_cancel(err, self._add_command()) + + # Clear the cancellation counter on Python 3.11+ so the next + # await does not immediately re-raise CancelledError. + if ( + sys.version_info >= (3, 11) + and (task := asyncio.current_task()) is not None + ): + task.uncancel() # type: ignore[union-attr] + + if reraise_on_workflow_cancellation and ( + self._cancel_reason is not None or self._deleting + ): + raise + async def _cancel_external_workflow( self, # Should not have seq set @@ -2687,23 +2736,14 @@ async def _signal_external_workflow( ) self._pending_external_signals[seq] = (done_fut, target_workflow_id) + def apply_cancel( + _err: asyncio.CancelledError, + command: temporalio.bridge.proto.workflow_commands.WorkflowCommand, + ) -> None: + command.cancel_signal_workflow.seq = seq + # Wait until completed or cancelled - while True: - try: - # We use _shield_await instead of asyncio.shield to prevent - # the future itself from being cancelled while avoiding a - # spurious error log on Python 3.11+ (see issue #1600). - return await _shield_await(done_fut) - except asyncio.CancelledError: - cancel_command = self._add_command() - cancel_command.cancel_signal_workflow.seq = seq - # Clear the cancellation counter on Python 3.11+ so the - # next await does not immediately re-raise CancelledError - if ( - sys.version_info >= (3, 11) - and (t := asyncio.current_task()) is not None - ): - t.uncancel() # type: ignore[union-attr] + return await self._await_temporal_operation(done_fut, apply_cancel) def _stack_trace(self) -> str: stacks = [] @@ -3896,3 +3936,11 @@ class _WorkflowLogicFlag(IntEnum): """Flags that may be set on task/activation completion to differentiate new from old workflow behavior.""" RAISE_ON_CANCELLING_COMPLETED_ACTIVITY = 1 + PROCESS_WORKFLOW_ACTIVATION_JOBS_AS_SINGLE_BATCH = 2 + + +# TODO: Enable PROCESS_WORKFLOW_ACTIVATION_JOBS_AS_SINGLE_BATCH by default after +# two published SDK releases have recognized flag 2. When enabling it, remove the +# explicit overrides for this flag from tests/worker/test_workflow.py, then remove +# this reminder. +_DEFAULT_ENABLED_WORKFLOW_LOGIC_FLAGS: frozenset[_WorkflowLogicFlag] = frozenset() diff --git a/tests/worker/test_replayer.py b/tests/worker/test_replayer.py index 22d771556..137b32c3e 100644 --- a/tests/worker/test_replayer.py +++ b/tests/worker/test_replayer.py @@ -10,6 +10,7 @@ import pytest +import temporalio.worker._workflow_instance from temporalio import activity, workflow from temporalio.client import Client, WorkflowFailureError, WorkflowHistory from temporalio.exceptions import ApplicationError @@ -81,6 +82,24 @@ def waiting(self) -> bool: return self._waiting +_WorkflowLogicFlag = temporalio.worker._workflow_instance._WorkflowLogicFlag +_SINGLE_BATCH_WORKFLOW_LOGIC_FLAG = ( + _WorkflowLogicFlag.PROCESS_WORKFLOW_ACTIVATION_JOBS_AS_SINGLE_BATCH +) + + +def _history_uses_workflow_logic_flag( + history: WorkflowHistory, + flag: _WorkflowLogicFlag, +) -> bool: + return any( + event.HasField("workflow_task_completed_event_attributes") + and int(flag) + in event.workflow_task_completed_event_attributes.sdk_metadata.lang_used_flags + for event in history.events + ) + + @pytest.mark.skipif(sys.version_info < (3, 12), reason="Skipping for < 3.12") async def test_replayer_workflow_complete(client: Client) -> None: # This test skips for versions < 3.12 because this is flaky due to CPython reimport issue: @@ -427,15 +446,12 @@ async def execute_workflow(self, input: ExecuteWorkflowInput) -> Any: return res -async def test_replayer_async_ordering() -> None: - """ - This test verifies that the order that asyncio tasks/coroutines are woken up matches the - order they were before changes to apply all jobs and then run the event loop, where previously - the event loop was ran after each "batch" of jobs. - """ - histories_and_expecteds = [ - ( +@pytest.mark.parametrize( + ("history_filename", "uses_single_batch", "expected"), + [ + pytest.param( "test_replayer_event_tracing.json", + False, [ "sig-before-sync", "sig-before-1", @@ -453,9 +469,33 @@ async def test_replayer_async_ordering() -> None: "timer-1", "timer-2", ], + id="legacy-event-tracing", ), - ( + pytest.param( + "test_replayer_event_tracing_single_batch.json", + True, + [ + "sig-before-sync", + "sig-before-1", + "timer-sync", + "act-sync", + "sig-before-2", + "act-1", + "act-2", + "sig-1-sync", + "sig-1-1", + "sig-1-2", + "update-1-sync", + "update-1-1", + "update-1-2", + "timer-1", + "timer-2", + ], + id="single-batch-event-tracing", + ), + pytest.param( "test_replayer_event_tracing_double_sig_at_start.json", + False, [ "sig-before-sync", "sig-before-1", @@ -473,29 +513,72 @@ async def test_replayer_async_ordering() -> None: "timer-1", "timer-2", ], + id="legacy-double-signal-at-start", ), - ] - for history, expected in histories_and_expecteds: - with Path(__file__).with_name(history).open() as f: - history = f.read() - await Replayer( - workflows=[SignalsActivitiesTimersUpdatesTracingWorkflow], - interceptors=[WorkerWorkflowResultInterceptor()], - ).replay_workflow(WorkflowHistory.from_json("fake", history)) - assert test_replayer_workflow_res == expected + pytest.param( + "test_replayer_event_tracing_double_sig_at_start_single_batch.json", + True, + [ + "sig-before-sync", + "sig-before-1", + "sig-1-sync", + "sig-1-1", + "timer-sync", + "act-sync", + "sig-before-2", + "sig-1-2", + "act-1", + "act-2", + "update-1-sync", + "update-1-1", + "update-1-2", + "timer-1", + "timer-2", + ], + id="single-batch-double-signal-at-start", + ), + ], +) +async def test_replayer_async_ordering( + history_filename: str, + uses_single_batch: bool, + expected: list[str], +) -> None: + """ + Verify legacy and single-batch histories replay with the asyncio scheduling order that their + original executions observed. + """ + with Path(__file__).with_name(history_filename).open() as f: + history = WorkflowHistory.from_json("fake", f.read()) + assert ( + _history_uses_workflow_logic_flag(history, _SINGLE_BATCH_WORKFLOW_LOGIC_FLAG) + is uses_single_batch + ) + await Replayer( + workflows=[SignalsActivitiesTimersUpdatesTracingWorkflow], + interceptors=[WorkerWorkflowResultInterceptor()], + ).replay_workflow(history) + assert test_replayer_workflow_res == expected -async def test_replayer_alternate_async_ordering() -> None: +async def test_replayer_unflagged_history_uses_legacy_async_ordering() -> None: with ( Path(__file__) .with_name("test_replayer_event_tracing_alternate.json") .open() as f ): - history = f.read() - await Replayer( + history = WorkflowHistory.from_json("fake", f.read()) + assert not _history_uses_workflow_logic_flag( + history, _SINGLE_BATCH_WORKFLOW_LOGIC_FLAG + ) + replayer = Replayer( workflows=[ActivityAndSignalsWhileWorkflowDown], interceptors=[WorkerWorkflowResultInterceptor()], - ).replay_workflow(WorkflowHistory.from_json("fake", history)) + ) + replayer._set_default_workflow_logic_flag( + _SINGLE_BATCH_WORKFLOW_LOGIC_FLAG, enabled=True + ) + await replayer.replay_workflow(history) assert test_replayer_workflow_res == [ "act-start", "sig-1", diff --git a/tests/worker/test_replayer_event_tracing_double_sig_at_start_single_batch.json b/tests/worker/test_replayer_event_tracing_double_sig_at_start_single_batch.json new file mode 100644 index 000000000..ed0eae143 --- /dev/null +++ b/tests/worker/test_replayer_event_tracing_double_sig_at_start_single_batch.json @@ -0,0 +1,433 @@ +{ + "events": [ + { + "eventId": "1", + "eventTime": "2026-07-22T17:46:09.820508351Z", + "eventType": "EVENT_TYPE_WORKFLOW_EXECUTION_STARTED", + "taskId": "1048655", + "workflowExecutionStartedEventAttributes": { + "workflowType": { + "name": "SignalsActivitiesTimersUpdatesTracingWorkflow" + }, + "taskQueue": { + "name": "tq-104f9b8b-4835-4705-8f36-3fb3f0b9bce7", + "kind": "TASK_QUEUE_KIND_NORMAL" + }, + "workflowTaskTimeout": "10s", + "originalExecutionRunId": "019f8aef-5a1c-77c0-8c6f-4c42b8984e71", + "identity": "2468547@monolith", + "firstExecutionRunId": "019f8aef-5a1c-77c0-8c6f-4c42b8984e71", + "attempt": 1, + "firstWorkflowTaskBackoff": "0s", + "workflowId": "wf-50105b28-aad3-488b-b8b5-6cd3c168369c", + "priority": {} + } + }, + { + "eventId": "2", + "eventTime": "2026-07-22T17:46:09.820553958Z", + "eventType": "EVENT_TYPE_WORKFLOW_TASK_SCHEDULED", + "taskId": "1048656", + "workflowTaskScheduledEventAttributes": { + "taskQueue": { + "name": "tq-104f9b8b-4835-4705-8f36-3fb3f0b9bce7", + "kind": "TASK_QUEUE_KIND_NORMAL" + }, + "startToCloseTimeout": "10s", + "attempt": 1 + } + }, + { + "eventId": "3", + "eventTime": "2026-07-22T17:46:09.823263829Z", + "eventType": "EVENT_TYPE_WORKFLOW_EXECUTION_SIGNALED", + "taskId": "1048661", + "workflowExecutionSignaledEventAttributes": { + "signalName": "dosig", + "input": { + "payloads": [ + { + "metadata": { + "encoding": "anNvbi9wbGFpbg==" + }, + "data": "ImJlZm9yZSI=" + } + ] + }, + "identity": "2468547@monolith", + "requestId": "0f1accfe-ffda-4af1-bc26-2a4b43007ef5" + } + }, + { + "eventId": "4", + "eventTime": "2026-07-22T17:46:09.826228197Z", + "eventType": "EVENT_TYPE_WORKFLOW_EXECUTION_SIGNALED", + "taskId": "1048663", + "workflowExecutionSignaledEventAttributes": { + "signalName": "dosig", + "input": { + "payloads": [ + { + "metadata": { + "encoding": "anNvbi9wbGFpbg==" + }, + "data": "IjEi" + } + ] + }, + "identity": "2468547@monolith", + "requestId": "7c76e2c6-c5c9-4bfa-9ef8-680e5fa0fdac" + } + }, + { + "eventId": "5", + "eventTime": "2026-07-22T17:46:09.911987108Z", + "eventType": "EVENT_TYPE_WORKFLOW_TASK_STARTED", + "taskId": "1048665", + "workflowTaskStartedEventAttributes": { + "scheduledEventId": "2", + "identity": "2468547@monolith", + "requestId": "eb18fba3-0020-4bee-9824-68dee535759c", + "historySizeBytes": "600", + "workerVersion": { + "buildId": "d7dd3d4f7dae90ccfe98229c9f116c9a" + } + } + }, + { + "eventId": "6", + "eventTime": "2026-07-22T17:46:10.029696095Z", + "eventType": "EVENT_TYPE_WORKFLOW_TASK_COMPLETED", + "taskId": "1048669", + "workflowTaskCompletedEventAttributes": { + "scheduledEventId": "2", + "startedEventId": "5", + "identity": "2468547@monolith", + "workerVersion": { + "buildId": "d7dd3d4f7dae90ccfe98229c9f116c9a" + }, + "sdkMetadata": { + "coreUsedFlags": [ + 2, + 3, + 1 + ], + "langUsedFlags": [ + 2 + ], + "sdkName": "temporal-python", + "sdkVersion": "1.30.0" + }, + "meteringMetadata": {} + } + }, + { + "eventId": "7", + "eventTime": "2026-07-22T17:46:10.029723573Z", + "eventType": "EVENT_TYPE_TIMER_STARTED", + "taskId": "1048670", + "timerStartedEventAttributes": { + "timerId": "1", + "startToFireTimeout": "0.100s", + "workflowTaskCompletedEventId": "6" + } + }, + { + "eventId": "8", + "eventTime": "2026-07-22T17:46:10.029791694Z", + "eventType": "EVENT_TYPE_ACTIVITY_TASK_SCHEDULED", + "taskId": "1048671", + "activityTaskScheduledEventAttributes": { + "activityId": "1", + "activityType": { + "name": "say_hello" + }, + "taskQueue": { + "name": "tq-104f9b8b-4835-4705-8f36-3fb3f0b9bce7", + "kind": "TASK_QUEUE_KIND_NORMAL" + }, + "header": {}, + "input": { + "payloads": [ + { + "metadata": { + "encoding": "anNvbi9wbGFpbg==" + }, + "data": "IkVuY2hpIg==" + } + ] + }, + "scheduleToCloseTimeout": "30s", + "scheduleToStartTimeout": "30s", + "startToCloseTimeout": "30s", + "heartbeatTimeout": "0s", + "workflowTaskCompletedEventId": "6", + "retryPolicy": { + "initialInterval": "1s", + "backoffCoefficient": 2.0, + "maximumInterval": "100s" + }, + "useWorkflowBuildId": true, + "priority": {} + } + }, + { + "eventId": "9", + "eventTime": "2026-07-22T17:46:10.031520468Z", + "eventType": "EVENT_TYPE_ACTIVITY_TASK_STARTED", + "taskId": "1048679", + "activityTaskStartedEventAttributes": { + "scheduledEventId": "8", + "identity": "2468547@monolith", + "requestId": "58a7bab7-a808-49ba-b906-3c07a281f078", + "attempt": 1, + "workerVersion": { + "buildId": "d7dd3d4f7dae90ccfe98229c9f116c9a" + } + } + }, + { + "eventId": "10", + "eventTime": "2026-07-22T17:46:10.034867651Z", + "eventType": "EVENT_TYPE_ACTIVITY_TASK_COMPLETED", + "taskId": "1048680", + "activityTaskCompletedEventAttributes": { + "result": { + "payloads": [ + { + "metadata": { + "encoding": "anNvbi9wbGFpbg==" + }, + "data": "IkhlbGxvLCBFbmNoaSEi" + } + ] + }, + "scheduledEventId": "8", + "startedEventId": "9", + "identity": "2468547@monolith" + } + }, + { + "eventId": "11", + "eventTime": "2026-07-22T17:46:10.034876231Z", + "eventType": "EVENT_TYPE_WORKFLOW_TASK_SCHEDULED", + "taskId": "1048681", + "workflowTaskScheduledEventAttributes": { + "taskQueue": { + "name": "2468547@monolith-af9e32c231d44027a7fbb997838520bf", + "kind": "TASK_QUEUE_KIND_STICKY", + "normalName": "tq-104f9b8b-4835-4705-8f36-3fb3f0b9bce7" + }, + "startToCloseTimeout": "10s", + "attempt": 1 + } + }, + { + "eventId": "12", + "eventTime": "2026-07-22T17:46:10.035716599Z", + "eventType": "EVENT_TYPE_WORKFLOW_TASK_STARTED", + "taskId": "1048685", + "workflowTaskStartedEventAttributes": { + "scheduledEventId": "11", + "identity": "2468547@monolith", + "requestId": "cf2bd6a2-3498-427d-920a-daf350415c70", + "historySizeBytes": "1389", + "workerVersion": { + "buildId": "d7dd3d4f7dae90ccfe98229c9f116c9a" + } + } + }, + { + "eventId": "13", + "eventTime": "2026-07-22T17:46:10.039414094Z", + "eventType": "EVENT_TYPE_WORKFLOW_TASK_COMPLETED", + "taskId": "1048689", + "workflowTaskCompletedEventAttributes": { + "scheduledEventId": "11", + "startedEventId": "12", + "identity": "2468547@monolith", + "workerVersion": { + "buildId": "d7dd3d4f7dae90ccfe98229c9f116c9a" + }, + "sdkMetadata": {}, + "meteringMetadata": {} + } + }, + { + "eventId": "14", + "eventTime": "2026-07-22T17:46:10.112263987Z", + "eventType": "EVENT_TYPE_WORKFLOW_TASK_SCHEDULED", + "taskId": "1048695", + "workflowTaskScheduledEventAttributes": { + "taskQueue": { + "name": "2468547@monolith-af9e32c231d44027a7fbb997838520bf", + "kind": "TASK_QUEUE_KIND_STICKY", + "normalName": "tq-104f9b8b-4835-4705-8f36-3fb3f0b9bce7" + }, + "startToCloseTimeout": "10s", + "attempt": 1 + } + }, + { + "eventId": "15", + "eventTime": "2026-07-22T17:46:10.112924510Z", + "eventType": "EVENT_TYPE_WORKFLOW_TASK_STARTED", + "taskId": "1048696", + "workflowTaskStartedEventAttributes": { + "scheduledEventId": "14", + "identity": "2468547@monolith", + "requestId": "6e079d38-0b99-48eb-b1e9-1b8236232fb1", + "historySizeBytes": "1598", + "workerVersion": { + "buildId": "d7dd3d4f7dae90ccfe98229c9f116c9a" + } + } + }, + { + "eventId": "16", + "eventTime": "2026-07-22T17:46:10.118047317Z", + "eventType": "EVENT_TYPE_WORKFLOW_TASK_COMPLETED", + "taskId": "1048697", + "workflowTaskCompletedEventAttributes": { + "scheduledEventId": "14", + "startedEventId": "15", + "identity": "2468547@monolith", + "workerVersion": { + "buildId": "d7dd3d4f7dae90ccfe98229c9f116c9a" + }, + "sdkMetadata": {}, + "meteringMetadata": {} + } + }, + { + "eventId": "17", + "eventTime": "2026-07-22T17:46:10.118078114Z", + "eventType": "EVENT_TYPE_WORKFLOW_EXECUTION_UPDATE_ACCEPTED", + "taskId": "1048698", + "workflowExecutionUpdateAcceptedEventAttributes": { + "protocolInstanceId": "3078b22e-fa4a-4bb3-bf21-7502464f3f8e", + "acceptedRequestMessageId": "3078b22e-fa4a-4bb3-bf21-7502464f3f8e/request", + "acceptedRequestSequencingEventId": "14", + "acceptedRequest": { + "meta": { + "updateId": "3078b22e-fa4a-4bb3-bf21-7502464f3f8e", + "identity": "2468547@monolith" + }, + "input": { + "name": "doupdate", + "args": { + "payloads": [ + { + "metadata": { + "encoding": "anNvbi9wbGFpbg==" + }, + "data": "IjEi" + } + ] + } + } + } + } + }, + { + "eventId": "18", + "eventTime": "2026-07-22T17:46:10.118094048Z", + "eventType": "EVENT_TYPE_WORKFLOW_EXECUTION_UPDATE_COMPLETED", + "taskId": "1048699", + "workflowExecutionUpdateCompletedEventAttributes": { + "meta": { + "updateId": "3078b22e-fa4a-4bb3-bf21-7502464f3f8e", + "identity": "2468547@monolith" + }, + "outcome": { + "success": { + "payloads": [ + { + "metadata": { + "encoding": "YmluYXJ5L251bGw=" + } + } + ] + } + }, + "acceptedEventId": "17" + } + }, + { + "eventId": "19", + "eventTime": "2026-07-22T17:46:10.822704848Z", + "eventType": "EVENT_TYPE_TIMER_FIRED", + "taskId": "1048702", + "timerFiredEventAttributes": { + "timerId": "1", + "startedEventId": "7" + } + }, + { + "eventId": "20", + "eventTime": "2026-07-22T17:46:10.822723284Z", + "eventType": "EVENT_TYPE_WORKFLOW_TASK_SCHEDULED", + "taskId": "1048703", + "workflowTaskScheduledEventAttributes": { + "taskQueue": { + "name": "2468547@monolith-af9e32c231d44027a7fbb997838520bf", + "kind": "TASK_QUEUE_KIND_STICKY", + "normalName": "tq-104f9b8b-4835-4705-8f36-3fb3f0b9bce7" + }, + "startToCloseTimeout": "10s", + "attempt": 1 + } + }, + { + "eventId": "21", + "eventTime": "2026-07-22T17:46:10.827860954Z", + "eventType": "EVENT_TYPE_WORKFLOW_TASK_STARTED", + "taskId": "1048707", + "workflowTaskStartedEventAttributes": { + "scheduledEventId": "20", + "identity": "2468547@monolith", + "requestId": "facf828f-060f-4a8b-87cf-bdbb3a3297e9", + "historySizeBytes": "2430", + "workerVersion": { + "buildId": "d7dd3d4f7dae90ccfe98229c9f116c9a" + } + } + }, + { + "eventId": "22", + "eventTime": "2026-07-22T17:46:10.843601707Z", + "eventType": "EVENT_TYPE_WORKFLOW_TASK_COMPLETED", + "taskId": "1048711", + "workflowTaskCompletedEventAttributes": { + "scheduledEventId": "20", + "startedEventId": "21", + "identity": "2468547@monolith", + "workerVersion": { + "buildId": "d7dd3d4f7dae90ccfe98229c9f116c9a" + }, + "sdkMetadata": {}, + "meteringMetadata": {} + } + }, + { + "eventId": "23", + "eventTime": "2026-07-22T17:46:10.843661263Z", + "eventType": "EVENT_TYPE_WORKFLOW_EXECUTION_COMPLETED", + "taskId": "1048712", + "workflowExecutionCompletedEventAttributes": { + "result": { + "payloads": [ + { + "metadata": { + "encoding": "anNvbi9wbGFpbg==" + }, + "data": "WyJzaWctYmVmb3JlLXN5bmMiLCJzaWctYmVmb3JlLTEiLCJzaWctMS1zeW5jIiwic2lnLTEtMSIsInRpbWVyLXN5bmMiLCJhY3Qtc3luYyIsInNpZy1iZWZvcmUtMiIsInNpZy0xLTIiLCJhY3QtMSIsImFjdC0yIiwidXBkYXRlLTEtc3luYyIsInVwZGF0ZS0xLTEiLCJ1cGRhdGUtMS0yIiwidGltZXItMSIsInRpbWVyLTIiXQ==" + } + ] + }, + "workflowTaskCompletedEventId": "22" + } + } + ] +} + diff --git a/tests/worker/test_replayer_event_tracing_single_batch.json b/tests/worker/test_replayer_event_tracing_single_batch.json new file mode 100644 index 000000000..42bab0b4f --- /dev/null +++ b/tests/worker/test_replayer_event_tracing_single_batch.json @@ -0,0 +1,479 @@ +{ + "events": [ + { + "eventId": "1", + "eventTime": "2026-07-22T17:46:08.798556582Z", + "eventType": "EVENT_TYPE_WORKFLOW_EXECUTION_STARTED", + "taskId": "1048587", + "workflowExecutionStartedEventAttributes": { + "workflowType": { + "name": "SignalsActivitiesTimersUpdatesTracingWorkflow" + }, + "taskQueue": { + "name": "tq-7049fd3e-356e-49d5-9047-2b97b454562e", + "kind": "TASK_QUEUE_KIND_NORMAL" + }, + "workflowTaskTimeout": "10s", + "originalExecutionRunId": "019f8aef-561e-787b-8565-31e78b4a889a", + "identity": "2468547@monolith", + "firstExecutionRunId": "019f8aef-561e-787b-8565-31e78b4a889a", + "attempt": 1, + "firstWorkflowTaskBackoff": "0s", + "workflowId": "wf-2dd53446-a657-4f47-9e47-a3edeb302c5f", + "priority": {} + } + }, + { + "eventId": "2", + "eventTime": "2026-07-22T17:46:08.798633092Z", + "eventType": "EVENT_TYPE_WORKFLOW_TASK_SCHEDULED", + "taskId": "1048588", + "workflowTaskScheduledEventAttributes": { + "taskQueue": { + "name": "tq-7049fd3e-356e-49d5-9047-2b97b454562e", + "kind": "TASK_QUEUE_KIND_NORMAL" + }, + "startToCloseTimeout": "10s", + "attempt": 1 + } + }, + { + "eventId": "3", + "eventTime": "2026-07-22T17:46:08.801258084Z", + "eventType": "EVENT_TYPE_WORKFLOW_EXECUTION_SIGNALED", + "taskId": "1048593", + "workflowExecutionSignaledEventAttributes": { + "signalName": "dosig", + "input": { + "payloads": [ + { + "metadata": { + "encoding": "anNvbi9wbGFpbg==" + }, + "data": "ImJlZm9yZSI=" + } + ] + }, + "identity": "2468547@monolith", + "requestId": "c78a6332-adb5-4ff1-af4b-f55e1180d4d8" + } + }, + { + "eventId": "4", + "eventTime": "2026-07-22T17:46:08.949831498Z", + "eventType": "EVENT_TYPE_WORKFLOW_TASK_STARTED", + "taskId": "1048595", + "workflowTaskStartedEventAttributes": { + "scheduledEventId": "2", + "identity": "2468547@monolith", + "requestId": "1e30e279-6cc7-497a-89f5-3e032d169c49", + "historySizeBytes": "477", + "workerVersion": { + "buildId": "d7dd3d4f7dae90ccfe98229c9f116c9a" + } + } + }, + { + "eventId": "5", + "eventTime": "2026-07-22T17:46:09.032870384Z", + "eventType": "EVENT_TYPE_WORKFLOW_TASK_COMPLETED", + "taskId": "1048599", + "workflowTaskCompletedEventAttributes": { + "scheduledEventId": "2", + "startedEventId": "4", + "identity": "2468547@monolith", + "workerVersion": { + "buildId": "d7dd3d4f7dae90ccfe98229c9f116c9a" + }, + "sdkMetadata": { + "coreUsedFlags": [ + 3, + 1, + 2 + ], + "langUsedFlags": [ + 2 + ], + "sdkName": "temporal-python", + "sdkVersion": "1.30.0" + }, + "meteringMetadata": {} + } + }, + { + "eventId": "6", + "eventTime": "2026-07-22T17:46:09.032946093Z", + "eventType": "EVENT_TYPE_TIMER_STARTED", + "taskId": "1048600", + "timerStartedEventAttributes": { + "timerId": "1", + "startToFireTimeout": "0.100s", + "workflowTaskCompletedEventId": "5" + } + }, + { + "eventId": "7", + "eventTime": "2026-07-22T17:46:09.033008651Z", + "eventType": "EVENT_TYPE_ACTIVITY_TASK_SCHEDULED", + "taskId": "1048601", + "activityTaskScheduledEventAttributes": { + "activityId": "1", + "activityType": { + "name": "say_hello" + }, + "taskQueue": { + "name": "tq-7049fd3e-356e-49d5-9047-2b97b454562e", + "kind": "TASK_QUEUE_KIND_NORMAL" + }, + "header": {}, + "input": { + "payloads": [ + { + "metadata": { + "encoding": "anNvbi9wbGFpbg==" + }, + "data": "IkVuY2hpIg==" + } + ] + }, + "scheduleToCloseTimeout": "30s", + "scheduleToStartTimeout": "30s", + "startToCloseTimeout": "30s", + "heartbeatTimeout": "0s", + "workflowTaskCompletedEventId": "5", + "retryPolicy": { + "initialInterval": "1s", + "backoffCoefficient": 2.0, + "maximumInterval": "100s" + }, + "useWorkflowBuildId": true, + "priority": {} + } + }, + { + "eventId": "8", + "eventTime": "2026-07-22T17:46:09.035163378Z", + "eventType": "EVENT_TYPE_ACTIVITY_TASK_STARTED", + "taskId": "1048609", + "activityTaskStartedEventAttributes": { + "scheduledEventId": "7", + "identity": "2468547@monolith", + "requestId": "bd46ae91-1b79-4c8b-9366-e24395d0da8b", + "attempt": 1, + "workerVersion": { + "buildId": "d7dd3d4f7dae90ccfe98229c9f116c9a" + } + } + }, + { + "eventId": "9", + "eventTime": "2026-07-22T17:46:09.039131108Z", + "eventType": "EVENT_TYPE_ACTIVITY_TASK_COMPLETED", + "taskId": "1048610", + "activityTaskCompletedEventAttributes": { + "result": { + "payloads": [ + { + "metadata": { + "encoding": "anNvbi9wbGFpbg==" + }, + "data": "IkhlbGxvLCBFbmNoaSEi" + } + ] + }, + "scheduledEventId": "7", + "startedEventId": "8", + "identity": "2468547@monolith" + } + }, + { + "eventId": "10", + "eventTime": "2026-07-22T17:46:09.039143351Z", + "eventType": "EVENT_TYPE_WORKFLOW_TASK_SCHEDULED", + "taskId": "1048611", + "workflowTaskScheduledEventAttributes": { + "taskQueue": { + "name": "2468547@monolith-3a1c4b9f82644345a21e1663c393c0d0", + "kind": "TASK_QUEUE_KIND_STICKY", + "normalName": "tq-7049fd3e-356e-49d5-9047-2b97b454562e" + }, + "startToCloseTimeout": "10s", + "attempt": 1 + } + }, + { + "eventId": "11", + "eventTime": "2026-07-22T17:46:09.040109929Z", + "eventType": "EVENT_TYPE_WORKFLOW_TASK_STARTED", + "taskId": "1048615", + "workflowTaskStartedEventAttributes": { + "scheduledEventId": "10", + "identity": "2468547@monolith", + "requestId": "d3d3c3c3-5c9f-4570-8d8b-cce1f5856a4f", + "historySizeBytes": "1266", + "workerVersion": { + "buildId": "d7dd3d4f7dae90ccfe98229c9f116c9a" + } + } + }, + { + "eventId": "12", + "eventTime": "2026-07-22T17:46:09.043328426Z", + "eventType": "EVENT_TYPE_WORKFLOW_TASK_COMPLETED", + "taskId": "1048619", + "workflowTaskCompletedEventAttributes": { + "scheduledEventId": "10", + "startedEventId": "11", + "identity": "2468547@monolith", + "workerVersion": { + "buildId": "d7dd3d4f7dae90ccfe98229c9f116c9a" + }, + "sdkMetadata": {}, + "meteringMetadata": {} + } + }, + { + "eventId": "13", + "eventTime": "2026-07-22T17:46:09.146751311Z", + "eventType": "EVENT_TYPE_WORKFLOW_EXECUTION_SIGNALED", + "taskId": "1048621", + "workflowExecutionSignaledEventAttributes": { + "signalName": "dosig", + "input": { + "payloads": [ + { + "metadata": { + "encoding": "anNvbi9wbGFpbg==" + }, + "data": "IjEi" + } + ] + }, + "identity": "2468547@monolith", + "requestId": "f18a65f6-8773-425d-b8f6-d1099056f758" + } + }, + { + "eventId": "14", + "eventTime": "2026-07-22T17:46:09.146757799Z", + "eventType": "EVENT_TYPE_WORKFLOW_TASK_SCHEDULED", + "taskId": "1048622", + "workflowTaskScheduledEventAttributes": { + "taskQueue": { + "name": "2468547@monolith-3a1c4b9f82644345a21e1663c393c0d0", + "kind": "TASK_QUEUE_KIND_STICKY", + "normalName": "tq-7049fd3e-356e-49d5-9047-2b97b454562e" + }, + "startToCloseTimeout": "10s", + "attempt": 1 + } + }, + { + "eventId": "15", + "eventTime": "2026-07-22T17:46:09.147668735Z", + "eventType": "EVENT_TYPE_WORKFLOW_TASK_STARTED", + "taskId": "1048626", + "workflowTaskStartedEventAttributes": { + "scheduledEventId": "14", + "identity": "2468547@monolith", + "requestId": "7f9aa9f0-4bef-44a3-93f4-744ff1db8eb4", + "historySizeBytes": "1724", + "workerVersion": { + "buildId": "d7dd3d4f7dae90ccfe98229c9f116c9a" + } + } + }, + { + "eventId": "16", + "eventTime": "2026-07-22T17:46:09.151221140Z", + "eventType": "EVENT_TYPE_WORKFLOW_TASK_COMPLETED", + "taskId": "1048630", + "workflowTaskCompletedEventAttributes": { + "scheduledEventId": "14", + "startedEventId": "15", + "identity": "2468547@monolith", + "workerVersion": { + "buildId": "d7dd3d4f7dae90ccfe98229c9f116c9a" + }, + "sdkMetadata": {}, + "meteringMetadata": {} + } + }, + { + "eventId": "17", + "eventTime": "2026-07-22T17:46:09.151638714Z", + "eventType": "EVENT_TYPE_WORKFLOW_TASK_SCHEDULED", + "taskId": "1048633", + "workflowTaskScheduledEventAttributes": { + "taskQueue": { + "name": "2468547@monolith-3a1c4b9f82644345a21e1663c393c0d0", + "kind": "TASK_QUEUE_KIND_STICKY", + "normalName": "tq-7049fd3e-356e-49d5-9047-2b97b454562e" + }, + "startToCloseTimeout": "10s", + "attempt": 1 + } + }, + { + "eventId": "18", + "eventTime": "2026-07-22T17:46:09.151645790Z", + "eventType": "EVENT_TYPE_WORKFLOW_TASK_STARTED", + "taskId": "1048634", + "workflowTaskStartedEventAttributes": { + "scheduledEventId": "17", + "identity": "2468547@monolith", + "requestId": "request-from-RespondWorkflowTaskCompleted", + "historySizeBytes": "1933", + "workerVersion": { + "buildId": "d7dd3d4f7dae90ccfe98229c9f116c9a" + } + } + }, + { + "eventId": "19", + "eventTime": "2026-07-22T17:46:09.155070433Z", + "eventType": "EVENT_TYPE_WORKFLOW_TASK_COMPLETED", + "taskId": "1048635", + "workflowTaskCompletedEventAttributes": { + "scheduledEventId": "17", + "startedEventId": "18", + "identity": "2468547@monolith", + "workerVersion": { + "buildId": "d7dd3d4f7dae90ccfe98229c9f116c9a" + }, + "sdkMetadata": {}, + "meteringMetadata": {} + } + }, + { + "eventId": "20", + "eventTime": "2026-07-22T17:46:09.155126964Z", + "eventType": "EVENT_TYPE_WORKFLOW_EXECUTION_UPDATE_ACCEPTED", + "taskId": "1048636", + "workflowExecutionUpdateAcceptedEventAttributes": { + "protocolInstanceId": "dd163639-396a-440a-b950-00ac2f2ee490", + "acceptedRequestMessageId": "dd163639-396a-440a-b950-00ac2f2ee490/request", + "acceptedRequestSequencingEventId": "17", + "acceptedRequest": { + "meta": { + "updateId": "dd163639-396a-440a-b950-00ac2f2ee490", + "identity": "2468547@monolith" + }, + "input": { + "name": "doupdate", + "args": { + "payloads": [ + { + "metadata": { + "encoding": "anNvbi9wbGFpbg==" + }, + "data": "IjEi" + } + ] + } + } + } + } + }, + { + "eventId": "21", + "eventTime": "2026-07-22T17:46:09.155192377Z", + "eventType": "EVENT_TYPE_WORKFLOW_EXECUTION_UPDATE_COMPLETED", + "taskId": "1048637", + "workflowExecutionUpdateCompletedEventAttributes": { + "meta": { + "updateId": "dd163639-396a-440a-b950-00ac2f2ee490", + "identity": "2468547@monolith" + }, + "outcome": { + "success": { + "payloads": [ + { + "metadata": { + "encoding": "YmluYXJ5L251bGw=" + } + } + ] + } + }, + "acceptedEventId": "20" + } + }, + { + "eventId": "22", + "eventTime": "2026-07-22T17:46:09.801318803Z", + "eventType": "EVENT_TYPE_TIMER_FIRED", + "taskId": "1048640", + "timerFiredEventAttributes": { + "timerId": "1", + "startedEventId": "6" + } + }, + { + "eventId": "23", + "eventTime": "2026-07-22T17:46:09.801325729Z", + "eventType": "EVENT_TYPE_WORKFLOW_TASK_SCHEDULED", + "taskId": "1048641", + "workflowTaskScheduledEventAttributes": { + "taskQueue": { + "name": "2468547@monolith-3a1c4b9f82644345a21e1663c393c0d0", + "kind": "TASK_QUEUE_KIND_STICKY", + "normalName": "tq-7049fd3e-356e-49d5-9047-2b97b454562e" + }, + "startToCloseTimeout": "10s", + "attempt": 1 + } + }, + { + "eventId": "24", + "eventTime": "2026-07-22T17:46:09.802775220Z", + "eventType": "EVENT_TYPE_WORKFLOW_TASK_STARTED", + "taskId": "1048645", + "workflowTaskStartedEventAttributes": { + "scheduledEventId": "23", + "identity": "2468547@monolith", + "requestId": "3d1c5327-09f4-4434-8880-f181a287c207", + "historySizeBytes": "2770", + "workerVersion": { + "buildId": "d7dd3d4f7dae90ccfe98229c9f116c9a" + } + } + }, + { + "eventId": "25", + "eventTime": "2026-07-22T17:46:09.808121470Z", + "eventType": "EVENT_TYPE_WORKFLOW_TASK_COMPLETED", + "taskId": "1048649", + "workflowTaskCompletedEventAttributes": { + "scheduledEventId": "23", + "startedEventId": "24", + "identity": "2468547@monolith", + "workerVersion": { + "buildId": "d7dd3d4f7dae90ccfe98229c9f116c9a" + }, + "sdkMetadata": {}, + "meteringMetadata": {} + } + }, + { + "eventId": "26", + "eventTime": "2026-07-22T17:46:09.808174063Z", + "eventType": "EVENT_TYPE_WORKFLOW_EXECUTION_COMPLETED", + "taskId": "1048650", + "workflowExecutionCompletedEventAttributes": { + "result": { + "payloads": [ + { + "metadata": { + "encoding": "anNvbi9wbGFpbg==" + }, + "data": "WyJzaWctYmVmb3JlLXN5bmMiLCJzaWctYmVmb3JlLTEiLCJ0aW1lci1zeW5jIiwiYWN0LXN5bmMiLCJzaWctYmVmb3JlLTIiLCJhY3QtMSIsImFjdC0yIiwic2lnLTEtc3luYyIsInNpZy0xLTEiLCJzaWctMS0yIiwidXBkYXRlLTEtc3luYyIsInVwZGF0ZS0xLTEiLCJ1cGRhdGUtMS0yIiwidGltZXItMSIsInRpbWVyLTIiXQ==" + } + ] + }, + "workflowTaskCompletedEventId": "25" + } + } + ] +} + diff --git a/tests/worker/test_workflow.py b/tests/worker/test_workflow.py index dbd85ef20..9c742d5c6 100644 --- a/tests/worker/test_workflow.py +++ b/tests/worker/test_workflow.py @@ -41,6 +41,7 @@ import temporalio.converter._extstore import temporalio.worker import temporalio.worker._command_aware_visitor +import temporalio.worker._workflow_instance import temporalio.workflow from temporalio import activity, workflow from temporalio.api.common.v1 import Payload, Payloads, WorkflowExecution @@ -114,6 +115,7 @@ from temporalio.worker import ( ExecuteWorkflowInput, HandleSignalInput, + Replayer, UnsandboxedWorkflowRunner, Worker, WorkflowInstance, @@ -1246,7 +1248,103 @@ async def run(self) -> str: return "cancelled" -async def test_workflow_cancel_before_run(client: Client): +_WorkflowLogicFlag = temporalio.worker._workflow_instance._WorkflowLogicFlag +_SINGLE_BATCH_WORKFLOW_LOGIC_FLAG = ( + _WorkflowLogicFlag.PROCESS_WORKFLOW_ACTIVATION_JOBS_AS_SINGLE_BATCH +) + + +def test_single_batch_workflow_activation_jobs_default_disabled() -> None: + assert ( + _SINGLE_BATCH_WORKFLOW_LOGIC_FLAG + not in temporalio.worker._workflow_instance._DEFAULT_ENABLED_WORKFLOW_LOGIC_FLAGS + ) + + +@workflow.defn +class EnableWorkflowLogicFlagAfterReplayWorkflow: + def __init__(self) -> None: + self._ready = False + self._finish = False + + @workflow.run + async def run(self) -> str: + self._ready = True + await workflow.wait_condition(lambda: self._finish) + return "done" + + @workflow.signal + def finish(self) -> None: + self._finish = True + + @workflow.query + def ready(self) -> bool: + return self._ready + + +async def test_workflow_logic_flag_enabled_after_replay(client: Client) -> None: + task_queue = str(uuid.uuid4()) + handle = await client.start_workflow( + EnableWorkflowLogicFlagAfterReplayWorkflow.run, + id=f"workflow-{uuid.uuid4()}", + task_queue=task_queue, + ) + + async with new_worker( + client, + EnableWorkflowLogicFlagAfterReplayWorkflow, + task_queue=task_queue, + # The Java test server does not reliably reschedule an abandoned sticky + # task after its timeout, so keep events sent after this worker stops on + # the normal queue. + max_cached_workflows=0, + ): + + async def ready() -> bool: + return await handle.query(EnableWorkflowLogicFlagAfterReplayWorkflow.ready) + + await assert_eq_eventually(True, ready) + + await handle.signal(EnableWorkflowLogicFlagAfterReplayWorkflow.finish) + + runner = CustomWorkflowRunner() + worker = new_worker( + client, + EnableWorkflowLogicFlagAfterReplayWorkflow, + task_queue=task_queue, + workflow_runner=runner, + ) + worker._set_default_workflow_logic_flag( + _SINGLE_BATCH_WORKFLOW_LOGIC_FLAG, enabled=True + ) + async with worker: + assert await handle.result() == "done" + + assert any(activation.is_replaying for activation, _ in runner._pairs) + assert any( + not activation.is_replaying + and _SINGLE_BATCH_WORKFLOW_LOGIC_FLAG + in completion.successful.used_internal_flags + for activation, completion in runner._pairs + ) + + history = await handle.fetch_history() + workflow_task_flags = [ + event.workflow_task_completed_event_attributes.sdk_metadata.lang_used_flags + for event in history.events + if event.HasField("workflow_task_completed_event_attributes") + ] + assert _SINGLE_BATCH_WORKFLOW_LOGIC_FLAG not in workflow_task_flags[0] + assert any( + _SINGLE_BATCH_WORKFLOW_LOGIC_FLAG in flags for flags in workflow_task_flags[1:] + ) + await Replayer( + workflows=[EnableWorkflowLogicFlagAfterReplayWorkflow] + ).replay_workflow(history) + + +@pytest.mark.parametrize("single_batch", [False, True]) +async def test_workflow_cancel_before_run(client: Client, single_batch: bool): # Start the workflow _and_ send cancel before even starting the workflow task_queue = str(uuid.uuid4()) handle = await client.start_workflow( @@ -1256,10 +1354,248 @@ async def test_workflow_cancel_before_run(client: Client): ) await handle.cancel() # Start worker and wait for result - async with new_worker(client, TrapCancelWorkflow, task_queue=task_queue): + worker = new_worker(client, TrapCancelWorkflow, task_queue=task_queue) + if single_batch: + worker._set_default_workflow_logic_flag( + _SINGLE_BATCH_WORKFLOW_LOGIC_FLAG, enabled=True + ) + async with worker: assert "cancelled" == await handle.result() +@workflow.defn +class CancelAtWaitConditionWorkflow: + def __init__(self) -> None: + self._ready = False + self._proceed = False + self._waiting_after_cancel = False + self._finish_after_cancel = False + + @workflow.run + async def run(self, timeout: bool) -> str: + self._ready = True + try: + await workflow.wait_condition( + lambda: self._proceed, timeout=1000 if timeout else None + ) + except asyncio.CancelledError: + # A caught cancellation must not be raised again merely because a + # later wait sees the already-recorded workflow cancellation. + self._waiting_after_cancel = True + await workflow.wait_condition(lambda: self._finish_after_cancel) + return "cancelled" + return "condition" + + @workflow.signal + def proceed(self) -> None: + self._proceed = True + + @workflow.signal + def finish_after_cancel(self) -> None: + self._finish_after_cancel = True + + @workflow.query + def ready(self) -> bool: + return self._ready + + @workflow.query + def waiting_after_cancel(self) -> bool: + return self._waiting_after_cancel + + +@pytest.mark.parametrize("timeout", [False, True]) +async def test_workflow_cancel_and_condition_ready_in_same_activation( + client: Client, timeout: bool +): + task_queue = str(uuid.uuid4()) + runner = CustomWorkflowRunner() + handle = await client.start_workflow( + CancelAtWaitConditionWorkflow.run, + timeout, + id=f"workflow-{uuid.uuid4()}", + task_queue=task_queue, + ) + + worker = new_worker( + client, + CancelAtWaitConditionWorkflow, + task_queue=task_queue, + workflow_runner=runner, + # The Java test server does not reliably reschedule an abandoned sticky + # task after its timeout, so keep events sent after this worker stops on + # the normal queue. + max_cached_workflows=0, + ) + worker._set_default_workflow_logic_flag( + _SINGLE_BATCH_WORKFLOW_LOGIC_FLAG, enabled=True + ) + async with worker: + + async def ready() -> bool: + return await handle.query(CancelAtWaitConditionWorkflow.ready) + + await assert_eq_eventually(True, ready) + + # Keep the worker offline so the signal and cancellation are delivered in + # one activation when polling resumes. + await handle.signal(CancelAtWaitConditionWorkflow.proceed) + await handle.cancel() + + worker = new_worker( + client, + CancelAtWaitConditionWorkflow, + task_queue=task_queue, + workflow_runner=runner, + ) + worker._set_default_workflow_logic_flag( + _SINGLE_BATCH_WORKFLOW_LOGIC_FLAG, enabled=True + ) + async with worker: + + async def waiting_after_cancel() -> bool: + return await handle.query( + CancelAtWaitConditionWorkflow.waiting_after_cancel + ) + + await assert_eq_eventually(True, waiting_after_cancel) + await handle.signal(CancelAtWaitConditionWorkflow.finish_after_cancel) + assert await handle.result() == "cancelled" + + assert any( + _SINGLE_BATCH_WORKFLOW_LOGIC_FLAG in completion.successful.used_internal_flags + for _, completion in runner._pairs + ) + assert any( + {"signal_workflow", "cancel_workflow"}.issubset( + {job.WhichOneof("variant") for job in activation.jobs} + ) + for activation, _ in runner._pairs + ) + await Replayer(workflows=[CancelAtWaitConditionWorkflow]).replay_workflow( + await handle.fetch_history() + ) + + +@workflow.defn +class CompleteChildOnSignalWorkflow: + def __init__(self) -> None: + self._finish = False + + @workflow.run + async def run(self) -> str: + await workflow.wait_condition(lambda: self._finish) + return "child complete" + + @workflow.signal + def finish(self) -> None: + self._finish = True + + +@workflow.defn +class CancelAtChildCompletionWorkflow: + def __init__(self) -> None: + self._child_started = False + + @workflow.run + async def run(self, child_task_queue: str) -> str: + child = await workflow.start_child_workflow( + CompleteChildOnSignalWorkflow.run, + id=f"{workflow.info().workflow_id}-child", + task_queue=child_task_queue, + ) + self._child_started = True + return await child + + @workflow.query + def child_started(self) -> bool: + return self._child_started + + +async def test_workflow_cancel_and_child_completion_in_same_activation( + client: Client, +): + parent_task_queue = str(uuid.uuid4()) + child_task_queue = str(uuid.uuid4()) + workflow_id = f"workflow-{uuid.uuid4()}" + child_id = f"{workflow_id}-child" + runner = CustomWorkflowRunner() + + child_worker = new_worker( + client, + CompleteChildOnSignalWorkflow, + task_queue=child_task_queue, + ) + child_worker._set_default_workflow_logic_flag( + _SINGLE_BATCH_WORKFLOW_LOGIC_FLAG, enabled=True + ) + async with child_worker: + handle = await client.start_workflow( + CancelAtChildCompletionWorkflow.run, + child_task_queue, + id=workflow_id, + task_queue=parent_task_queue, + ) + parent_worker = new_worker( + client, + CancelAtChildCompletionWorkflow, + task_queue=parent_task_queue, + workflow_runner=runner, + # The Java test server does not reliably reschedule an abandoned + # sticky task after its timeout, so keep events sent after this + # worker stops on the normal queue. + max_cached_workflows=0, + ) + parent_worker._set_default_workflow_logic_flag( + _SINGLE_BATCH_WORKFLOW_LOGIC_FLAG, enabled=True + ) + async with parent_worker: + + async def child_started() -> bool: + return await handle.query(CancelAtChildCompletionWorkflow.child_started) + + await assert_eq_eventually(True, child_started) + + child_handle = client.get_workflow_handle(child_id) + await child_handle.signal(CompleteChildOnSignalWorkflow.finish) + assert await child_handle.result() == "child complete" + + async def child_completion_recorded() -> None: + async for event in handle.fetch_history_events(): + if ( + event.event_type + == EventType.EVENT_TYPE_CHILD_WORKFLOW_EXECUTION_COMPLETED + ): + return + raise AssertionError("Child completion is not in parent history") + + await assert_eventually(child_completion_recorded) + await handle.cancel() + + parent_worker = new_worker( + client, + CancelAtChildCompletionWorkflow, + task_queue=parent_task_queue, + workflow_runner=runner, + ) + parent_worker._set_default_workflow_logic_flag( + _SINGLE_BATCH_WORKFLOW_LOGIC_FLAG, enabled=True + ) + async with parent_worker: + with pytest.raises(WorkflowFailureError) as err: + await handle.result() + assert isinstance(err.value.cause, CancelledError) + + assert any( + {"resolve_child_workflow_execution", "cancel_workflow"}.issubset( + {job.WhichOneof("variant") for job in activation.jobs} + ) + for activation, _ in runner._pairs + ) + await Replayer(workflows=[CancelAtChildCompletionWorkflow]).replay_workflow( + await handle.fetch_history() + ) + + @activity.defn async def wait_forever() -> NoReturn: await asyncio.Future() @@ -3945,8 +4281,16 @@ def check_condition(self) -> bool: return True -async def test_workflow_query_does_not_run_condition(client: Client): - async with new_worker(client, QueryAffectConditionWorkflow) as worker: +@pytest.mark.parametrize("single_batch", [False, True]) +async def test_workflow_query_does_not_run_condition( + client: Client, single_batch: bool +): + worker = new_worker(client, QueryAffectConditionWorkflow) + if single_batch: + worker._set_default_workflow_logic_flag( + _SINGLE_BATCH_WORKFLOW_LOGIC_FLAG, enabled=True + ) + async with worker: handle = await client.start_workflow( QueryAffectConditionWorkflow.run, id=f"workflow-{uuid.uuid4()}", @@ -7334,8 +7678,8 @@ async def run_act(self): async def test_async_loop_ordering(client: Client, env: WorkflowEnvironment): - """This test mostly exists to generate histories for test_replayer_async_ordering. - See that test for more.""" + """This test mostly exists to generate PROCESS_WORKFLOW_ACTIVATION_JOBS_AS_SINGLE_BATCH + histories for test_replayer_async_ordering. See that test for more.""" if env.supports_time_skipping: pytest.skip("This test doesn't work right with time skipping for some reason") @@ -7347,12 +7691,16 @@ async def test_async_loop_ordering(client: Client, env: WorkflowEnvironment): ) await handle.signal(SignalsActivitiesTimersUpdatesTracingWorkflow.dosig, "before") - async with new_worker( + worker = new_worker( client, SignalsActivitiesTimersUpdatesTracingWorkflow, activities=[say_hello], task_queue=task_queue, - ): + ) + worker._set_default_workflow_logic_flag( + _SINGLE_BATCH_WORKFLOW_LOGIC_FLAG, enabled=True + ) + async with worker: await asyncio.sleep(0.2) await handle.signal(SignalsActivitiesTimersUpdatesTracingWorkflow.dosig, "1") await handle.execute_update( From 44511c53d1763d3615df9800f0a4aa18954d117b Mon Sep 17 00:00:00 2001 From: Tim Conley Date: Mon, 27 Jul 2026 16:22:43 -0700 Subject: [PATCH 187/226] Mark system Nexus envelope payloads (#1667) * Mark system Nexus envelope payloads * Fix concurrent system payload visits * Simplify visitor checkpoint handling * Update system Nexus visitor test helper * Update temporalio/nexus/system/__init__.py Co-authored-by: Dan Plyukhin --------- Co-authored-by: Dan Plyukhin --- CHANGELOG.md | 3 ++ scripts/gen_payload_visitor.py | 36 ++++++++-------- temporalio/bridge/_visitor.py | 18 ++++---- temporalio/bridge/_visitor_functions.py | 37 +++++++++++++--- temporalio/nexus/system/__init__.py | 38 ++++++++++++++--- tests/nexus/test_temporal_system_nexus.py | 30 ++++++++++--- tests/worker/test_visitor.py | 52 +++++++++++++++++++++++ 7 files changed, 168 insertions(+), 46 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d04c73594..f8fe94d4b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -69,6 +69,9 @@ to include examples, links to docs, or any other relevant information. ### Fixed +- Marked system Nexus envelope payloads so nested payloads can be detected and + visited after the envelope is already stored as a payload. + ### Security ## [1.30.0] - 2026-07-01 diff --git a/scripts/gen_payload_visitor.py b/scripts/gen_payload_visitor.py index fa28cb455..f782616cf 100644 --- a/scripts/gen_payload_visitor.py +++ b/scripts/gen_payload_visitor.py @@ -188,22 +188,9 @@ async def visit( async def _visit_nexus_operation_input_payload( self, fs: VisitorFunctions, - endpoint: str, payload: Payload, ) -> None: - new_payload = await temporalio.nexus.system._maybe_visit_payload( - endpoint, - payload, - fs, - self.skip_search_attributes, - ) - if new_payload is None: - await self._visit_temporal_api_common_v1_Payload(fs, payload) - return - - if new_payload is not payload: - payload.CopyFrom(new_payload) - await fs.visit_system_nexus_envelope(payload) + await self._visit_temporal_api_common_v1_Payload(fs, payload) """ @@ -218,8 +205,21 @@ def __init__(self): self.in_progress: set[str] = set() self.methods: list[str] = [ """\ - async def _visit_temporal_api_common_v1_Payload(self, fs: VisitorFunctions, o: Payload): - await fs.visit_payload(o) + async def _visit_temporal_api_common_v1_Payload( + self, fs: VisitorFunctions, payload: Payload + ) -> None: + new_payload = await temporalio.nexus.system.maybe_visit_payload( + payload, + fs, + self.skip_search_attributes, + ) + if new_payload is None: + await fs.visit_payload(payload) + return + + if new_payload is not payload: + payload.CopyFrom(new_payload) + await fs.visit_system_nexus_envelope(payload) """, """\ async def _visit_temporal_api_common_v1_Payloads(self, fs: VisitorFunctions, o: Any): @@ -403,11 +403,11 @@ def walk(self, desc: Descriptor) -> bool: ) ) elif item[0] == "system_nexus": - _, field_name, endpoint_expr, payload_expr = item + _, field_name, _endpoint_expr, payload_expr = item lines.append( f' if o.HasField("{field_name}"):\n' " await self._visit_nexus_operation_input_payload(\n" - f" fs, {endpoint_expr}, {payload_expr}\n" + f" fs, {payload_expr}\n" " )" ) else: # oneof_group diff --git a/temporalio/bridge/_visitor.py b/temporalio/bridge/_visitor.py index 974b4f77d..e5e48ea16 100644 --- a/temporalio/bridge/_visitor.py +++ b/temporalio/bridge/_visitor.py @@ -58,28 +58,26 @@ async def visit(self, fs: VisitorFunctions, root: Any) -> None: async def _visit_nexus_operation_input_payload( self, fs: VisitorFunctions, - endpoint: str, payload: Payload, ) -> None: - new_payload = await temporalio.nexus.system._maybe_visit_payload( - endpoint, + await self._visit_temporal_api_common_v1_Payload(fs, payload) + + async def _visit_temporal_api_common_v1_Payload( + self, fs: VisitorFunctions, payload: Payload + ) -> None: + new_payload = await temporalio.nexus.system.maybe_visit_payload( payload, fs, self.skip_search_attributes, ) if new_payload is None: - await self._visit_temporal_api_common_v1_Payload(fs, payload) + await fs.visit_payload(payload) return if new_payload is not payload: payload.CopyFrom(new_payload) await fs.visit_system_nexus_envelope(payload) - async def _visit_temporal_api_common_v1_Payload( - self, fs: VisitorFunctions, o: Payload - ): - await fs.visit_payload(o) - async def _visit_temporal_api_common_v1_Payloads( self, fs: VisitorFunctions, o: Any ): @@ -474,7 +472,7 @@ async def _visit_coresdk_workflow_commands_ScheduleNexusOperation( self, fs: VisitorFunctions, o: Any ): if o.HasField("input"): - await self._visit_nexus_operation_input_payload(fs, o.endpoint, o.input) + await self._visit_nexus_operation_input_payload(fs, o.input) async def _visit_coresdk_workflow_commands_WorkflowCommand( self, fs: VisitorFunctions, o: Any diff --git a/temporalio/bridge/_visitor_functions.py b/temporalio/bridge/_visitor_functions.py index 548a0ea94..da8c67ae2 100644 --- a/temporalio/bridge/_visitor_functions.py +++ b/temporalio/bridge/_visitor_functions.py @@ -1,7 +1,7 @@ from __future__ import annotations import asyncio -from typing import Protocol +from abc import ABC, abstractmethod from google.protobuf.internal.containers import RepeatedCompositeFieldContainer @@ -10,21 +10,31 @@ PayloadSequence = list[Payload] | RepeatedCompositeFieldContainer[Payload] -class VisitorFunctions(Protocol): +class VisitorFunctions(ABC): """Functions invoked by generated payload visitors.""" + @abstractmethod async def visit_payload(self, payload: Payload) -> None: """Visit a single payload.""" ... + @abstractmethod async def visit_payloads(self, payloads: PayloadSequence) -> None: """Visit a sequence of payloads together.""" ... - async def visit_system_nexus_envelope(self, payload: Payload) -> None: + async def visit_system_nexus_envelope(self, _payload: Payload) -> None: """Visit a recognized system Nexus envelope payload.""" return None + def checkpoint(self) -> int | None: + """Return a marker for visits scheduled after this point, if supported.""" + return None + + async def drain_since(self, _checkpoint: int) -> None: + """Wait for visits scheduled after ``checkpoint`` to finish.""" + return None + class BoundedVisitorFunctions(VisitorFunctions): """Wraps VisitorFunctions to cap concurrent payload visits via a semaphore. @@ -74,16 +84,33 @@ async def _run() -> None: self._tasks.append(asyncio.create_task(_run())) + def checkpoint(self) -> int: + """Return a marker for tasks scheduled after this point.""" + return len(self._tasks) + + async def drain_since(self, checkpoint: int) -> None: + """Wait for tasks scheduled after ``checkpoint`` to finish. + + This lets system-envelope traversal finish mutating its decoded value + before that value is serialized again, without waiting for unrelated + visits that were already in progress. + """ + await self._drain_tasks(self._tasks[checkpoint:]) + async def drain(self) -> None: """Wait for all in-flight background tasks to complete. On cancellation or error, cancels all remaining tasks and awaits them so their finally blocks run before this coroutine returns. """ - if not self._tasks: + await self._drain_tasks(self._tasks) + + async def _drain_tasks(self, tasks: list[asyncio.Task[None]]) -> None: + """Wait for the given tasks, cancelling all tasks if one fails.""" + if not tasks: return try: - await asyncio.gather(*self._tasks) + await asyncio.gather(*tasks) except BaseException: for task in self._tasks: task.cancel() diff --git a/temporalio/nexus/system/__init__.py b/temporalio/nexus/system/__init__.py index 7c83229c1..b3d4d2d6f 100644 --- a/temporalio/nexus/system/__init__.py +++ b/temporalio/nexus/system/__init__.py @@ -12,6 +12,7 @@ from typing import Any import temporalio.api.common.v1 +import temporalio.common import temporalio.converter from temporalio.bridge._visitor_functions import VisitorFunctions from temporalio.converter import BinaryProtoPayloadConverter, CompositePayloadConverter @@ -23,6 +24,8 @@ _user_payload_converter: contextvars.ContextVar[ temporalio.converter.PayloadConverter | None ] = contextvars.ContextVar("temporal-system-nexus-user-payload-converter", default=None) +_SYSTEM_PAYLOAD_METADATA_KEY = "__temporal_system_payload" +_SYSTEM_PAYLOAD_METADATA_VALUE = b"true" @contextlib.contextmanager @@ -52,6 +55,19 @@ def __init__(self) -> None: """Create a payload converter for system Nexus outer envelopes.""" super().__init__(BinaryProtoPayloadConverter()) + def to_payloads( + self, values: Sequence[Any] + ) -> list[temporalio.api.common.v1.Payload]: + """See base class.""" + payloads = super().to_payloads(values) + for value, payload in zip(values, payloads): + if isinstance(value, temporalio.common.RawValue): + continue + payload.metadata[_SYSTEM_PAYLOAD_METADATA_KEY] = ( + _SYSTEM_PAYLOAD_METADATA_VALUE + ) + return payloads + class _SystemNexusPayloadConverter(temporalio.converter.PayloadConverter): """Payload converter for system Nexus outer envelopes.""" @@ -94,23 +110,31 @@ def is_system_endpoint(endpoint: str) -> bool: return endpoint == TEMPORAL_SYSTEM_ENDPOINT -async def _maybe_visit_payload( # pyright: ignore[reportUnusedFunction] - endpoint: str, +def _is_system_payload(payload: temporalio.api.common.v1.Payload) -> bool: + return ( + payload.metadata.get(_SYSTEM_PAYLOAD_METADATA_KEY) + == _SYSTEM_PAYLOAD_METADATA_VALUE + ) + + +async def maybe_visit_payload( payload: temporalio.api.common.v1.Payload, visitor_functions: VisitorFunctions, skip_search_attributes: bool, ) -> temporalio.api.common.v1.Payload | None: - """Visit nested payloads if the payload is for the Temporal system endpoint.""" - if not is_system_endpoint(endpoint): + """Visit nested payloads if the payload is a Temporal system Nexus envelope.""" + if not _is_system_payload(payload): return None payload_converter = _SystemNexusOuterPayloadConverter() value = payload_converter.from_payload(payload) from temporalio.bridge._visitor import PayloadVisitor - await PayloadVisitor(skip_search_attributes=skip_search_attributes).visit( - visitor_functions, value - ) + payload_visitor = PayloadVisitor(skip_search_attributes=skip_search_attributes) + checkpoint = visitor_functions.checkpoint() + await payload_visitor.visit(visitor_functions, value) + if checkpoint is not None: + await visitor_functions.drain_since(checkpoint) return payload_converter.to_payload(value) diff --git a/tests/nexus/test_temporal_system_nexus.py b/tests/nexus/test_temporal_system_nexus.py index eb8ee603c..ec86689d7 100644 --- a/tests/nexus/test_temporal_system_nexus.py +++ b/tests/nexus/test_temporal_system_nexus.py @@ -16,6 +16,7 @@ import temporalio.nexus.system as nexus_system from temporalio import workflow from temporalio.bridge._visitor import PayloadVisitor +from temporalio.bridge._visitor_functions import VisitorFunctions from temporalio.bridge.proto.workflow_completion.workflow_completion_pb2 import ( WorkflowActivationCompletion, ) @@ -34,6 +35,7 @@ from tests.test_extstore import InMemoryTestDriver interceptor_traces: list[tuple[str, object]] = [] +SYSTEM_NEXUS_PAYLOAD_METADATA_KEY = "__temporal_system_payload" @workflow.defn @@ -143,7 +145,7 @@ def _assert_start_nexus_operation_interceptor_trace() -> None: assert request.workflow_type.name == "test-workflow" -class _MarkingPayloadVisitor: +class _MarkingPayloadVisitor(VisitorFunctions): def __init__(self) -> None: self.visited_payload_count = 0 self.system_envelope_count = 0 @@ -193,9 +195,15 @@ def _new_system_nexus_request_payload() -> temporalio.api.common.v1.Payload: return payload -async def test_schedule_system_nexus_endpoint_ignores_operation_registry() -> None: +def _new_unmarked_system_nexus_request_payload() -> temporalio.api.common.v1.Payload: + payload = _new_system_nexus_request_payload() + del payload.metadata[SYSTEM_NEXUS_PAYLOAD_METADATA_KEY] + return payload + + +async def test_schedule_marked_system_nexus_payload_ignores_endpoint() -> None: completion = _new_schedule_nexus_completion( - nexus_system.TEMPORAL_SYSTEM_ENDPOINT, + "not-the-system-endpoint", _new_system_nexus_request_payload(), ) visitor = _MarkingPayloadVisitor() @@ -215,10 +223,12 @@ async def test_schedule_system_nexus_endpoint_ignores_operation_registry() -> No assert visitor.system_envelope_count == 1 -async def test_schedule_non_system_nexus_visits_input_as_regular_payload() -> None: +async def test_schedule_unmarked_system_nexus_payload_visits_input_as_regular_payload() -> ( + None +): completion = _new_schedule_nexus_completion( - "not-the-system-endpoint", - _new_system_nexus_request_payload(), + nexus_system.TEMPORAL_SYSTEM_ENDPOINT, + _new_unmarked_system_nexus_request_payload(), ) visitor = _MarkingPayloadVisitor() @@ -226,6 +236,13 @@ async def test_schedule_non_system_nexus_visits_input_as_regular_payload() -> No schedule = completion.successful.commands[0].schedule_nexus_operation assert schedule.input.metadata["visited"] == b"true" + decoded = nexus_system._get_payload_converter( + temporalio.converter.default().payload_converter + ).from_payload(schedule.input) + assert isinstance( + decoded, workflowservice_pb2.SignalWithStartWorkflowExecutionRequest + ) + assert "visited" not in decoded.input.payloads[0].metadata assert visitor.visited_payload_count == 1 assert visitor.system_envelope_count == 0 @@ -351,6 +368,7 @@ def test_system_nexus_proto_roundtrip(message_type: type[Message]) -> None: assert payload is not None assert payload.metadata["encoding"] == b"binary/protobuf" assert payload.metadata["messageType"] == message_type.DESCRIPTOR.full_name.encode() + assert payload.metadata[SYSTEM_NEXUS_PAYLOAD_METADATA_KEY] == b"true" roundtripped = payload_converter.from_payload(payload, message_type) assert isinstance(roundtripped, message_type) assert roundtripped == proto_value diff --git a/tests/worker/test_visitor.py b/tests/worker/test_visitor.py index 3c3df42c1..d9606624e 100644 --- a/tests/worker/test_visitor.py +++ b/tests/worker/test_visitor.py @@ -212,6 +212,58 @@ async def test_visit_payloads_on_other_commands(): assert ur.completed.metadata["visited"] +async def test_system_nexus_envelope_is_detected_in_generic_payload_field(): + class SystemNexusVisitor(Visitor): + def __init__(self) -> None: + self.visited_payload_count = 0 + self.system_envelope_count = 0 + + async def visit_payload(self, payload: Payload) -> None: + self.visited_payload_count += 1 + await super().visit_payload(payload) + + async def visit_payloads(self, payloads: MutableSequence[Payload]) -> None: + self.visited_payload_count += len(payloads) + await super().visit_payloads(payloads) + + async def visit_system_nexus_envelope(self, payload: Payload) -> None: + _ = payload + self.system_envelope_count += 1 + + system_request = workflowservice_pb2.SignalWithStartWorkflowExecutionRequest( + input=Payloads(payloads=[Payload(data=b"workflow-input")]), + ) + payload_converter = nexus_system._get_payload_converter( + temporalio.converter.default().payload_converter + ) + system_payload = payload_converter.to_payload(system_request) + assert system_payload is not None + comp = WorkflowActivationCompletion( + run_id="3", + successful=Success( + commands=[ + WorkflowCommand( + update_response=UpdateResponse(completed=system_payload), + ) + ] + ), + ) + visitor = SystemNexusVisitor() + + await PayloadVisitor(concurrency_limit=3).visit(visitor, comp) + + completed = comp.successful.commands[0].update_response.completed + assert completed.metadata["__temporal_system_payload"] == b"true" + assert "visited" not in completed.metadata + decoded = payload_converter.from_payload(completed) + assert isinstance( + decoded, workflowservice_pb2.SignalWithStartWorkflowExecutionRequest + ) + assert decoded.input.payloads[0].metadata["visited"] == b"True" + assert visitor.visited_payload_count == 1 + assert visitor.system_envelope_count == 1 + + async def test_concurrent_throughput(): """Demonstrate that concurrent visitation is faster than serialized for I/O-bound codecs.""" N_CMDS = 10 From 7d52c78dad7d604fd505f23bf7b3fb6826c7ef70 Mon Sep 17 00:00:00 2001 From: xumaple <45406854+xumaple@users.noreply.github.com> Date: Tue, 28 Jul 2026 16:53:33 -0400 Subject: [PATCH 188/226] AI-374: Warn against passing secrets through MCP factory_argument (#1688) * AI-374: Warn against passing secrets through MCP factory_argument `factory_argument` is serialized as an activity argument and therefore recorded in workflow history, which is not obvious from the API surface. Document that in the docstrings and READMEs for the MCP support in the openai_agents and google_adk_agents contrib plugins, and point users at resolving credentials worker-side inside the factory instead. * AI-374: Correct and tighten the factory_argument secrets warning Fix the claim that factory_argument is sent to every MCP activity, which holds for stateless servers but not stateful ones, and document that a zero-parameter stateless factory silently discards the value while it is still written to history. Drop the maturity-badge glyph, qualify the web UI claim for users running a payload codec, and state the factory-side contract on the three provider docstrings. * fix AI slop --- temporalio/contrib/google_adk_agents/README.md | 4 ++++ temporalio/contrib/google_adk_agents/_mcp.py | 9 ++++++++- temporalio/contrib/openai_agents/README.md | 8 ++++++++ temporalio/contrib/openai_agents/_mcp.py | 6 ++++-- temporalio/contrib/openai_agents/workflow.py | 18 ++++++++++++++++-- 5 files changed, 40 insertions(+), 5 deletions(-) diff --git a/temporalio/contrib/google_adk_agents/README.md b/temporalio/contrib/google_adk_agents/README.md index 40ebb9aee..92fd1cea7 100644 --- a/temporalio/contrib/google_adk_agents/README.md +++ b/temporalio/contrib/google_adk_agents/README.md @@ -166,6 +166,10 @@ worker = Worker( ) ``` +`TemporalMcpToolSet` also accepts an optional `factory_argument`. It is sent to the toolset activities and passed to the registered `toolset_factory` when the `McpToolset` is created. + +**Do not pass secrets, credentials, or API keys through `factory_argument`.** It is an activity argument, so it is recorded in workflow history and, without a payload codec, visible in the web UI. Resolve credentials worker-side inside the toolset factory instead. + ### Local ADK Runs The same agent definitions can also be exercised outside Temporal with diff --git a/temporalio/contrib/google_adk_agents/_mcp.py b/temporalio/contrib/google_adk_agents/_mcp.py index 92bf994dd..2f9e694a8 100644 --- a/temporalio/contrib/google_adk_agents/_mcp.py +++ b/temporalio/contrib/google_adk_agents/_mcp.py @@ -221,10 +221,17 @@ def __init__( ): """Initializes the Temporal MCP toolset. + .. warning:: + Do not pass secrets, credentials, or API keys through ``factory_argument``. It + is an activity argument, so it is recorded in workflow history and, without a + payload codec, visible in the web UI. Resolve credentials worker-side inside the + toolset factory instead. + Args: name: Name of the toolset (used for activity naming). config: Optional activity configuration. - factory_argument: Optional argument passed to toolset factory. + factory_argument: Optional argument passed to ``toolset_factory``. + Must not contain secrets. not_in_workflow_toolset: Optional factory that returns the underlying ``McpToolset`` to use when this wrapper executes outside ``workflow.in_workflow()``, such as local ADK runs. diff --git a/temporalio/contrib/openai_agents/README.md b/temporalio/contrib/openai_agents/README.md index 31f668b16..e392bf3e3 100644 --- a/temporalio/contrib/openai_agents/README.md +++ b/temporalio/contrib/openai_agents/README.md @@ -447,6 +447,14 @@ For implementation details and examples, see the [samples repository](https://gi When using stateful servers, the dedicated worker maintaining the connection may fail due to network issues or server problems. When this happens, Temporal raises an `ApplicationError` and cannot automatically recover because it cannot restore the lost server state. To recover from such failures, you need to implement your own application-level retry logic. +### Factory Arguments + +Both `stateless_mcp_server()` and `stateful_mcp_server()` accept an optional `factory_argument`, which is passed to the registered server factory when the MCP server is created. + +A stateless factory that declares no parameters — like the `lambda: MCPServerStdio(...)` example above — ignores the value, but it is still recorded in history. + +**Do not pass secrets, credentials, or API keys through `factory_argument`.** It is an activity argument, so it is recorded in workflow history and, without a payload codec, visible in the web UI. Resolve credentials worker-side inside the server factory instead. + ### Hosted MCP Tool For network-accessible MCP servers, you can also use `HostedMCPTool` from the OpenAI Agents SDK, which uses an MCP client hosted by OpenAI. diff --git a/temporalio/contrib/openai_agents/_mcp.py b/temporalio/contrib/openai_agents/_mcp.py index 487634d13..8f5294c42 100644 --- a/temporalio/contrib/openai_agents/_mcp.py +++ b/temporalio/contrib/openai_agents/_mcp.py @@ -152,7 +152,8 @@ def __init__( Args: name: The name of the MCP server. server_factory: A function which will produce MCPServer instances. It should return a new server each time - so that state is not shared between workflow runs. + so that state is not shared between workflow runs. It may accept a single positional parameter, which + receives a ``factory_argument`` from the workflow. """ self._server_factory = server_factory @@ -437,7 +438,8 @@ def __init__( Args: name: The name of the MCP server. server_factory: A function which will produce MCPServer instances. It should return a new server each time - so that state is not shared between workflow runs + so that state is not shared between workflow runs. It receives an optional ``factory_argument`` from the + workflow. """ self._server_factory = server_factory self._name = name + "-stateful" diff --git a/temporalio/contrib/openai_agents/workflow.py b/temporalio/contrib/openai_agents/workflow.py index b37a82bdc..d99028d68 100644 --- a/temporalio/contrib/openai_agents/workflow.py +++ b/temporalio/contrib/openai_agents/workflow.py @@ -291,12 +291,19 @@ def stateless_mcp_server( and you don't need to maintain state between operations. It should be preferred to stateful when possible due to its superior durability guarantees. + .. warning:: + Do not pass secrets, credentials, or API keys through ``factory_argument``. It is an + activity argument, so it is recorded in workflow history and, without a payload codec, + visible in the web UI. Resolve credentials worker-side inside the server factory + instead. + Args: name: A string name for the server. Should match that provided in the plugin. config: Optional activity configuration for MCP operation activities. Defaults to 1-minute start-to-close timeout. cache_tools_list: If true, the list of tools will be cached for the duration of the server - factory_argument: Optional argument to be provided to the factory when producing an MCPServer + factory_argument: Optional argument to be provided to the factory when producing an MCPServer. + Must not contain secrets. """ from temporalio.contrib.openai_agents._mcp import ( _StatelessMCPServerReference, @@ -326,13 +333,20 @@ def stateful_mcp_server( The caller will have to handle cases where the dedicated worker fails, as Temporal is unable to seamlessly recreate any lost state in that case. + .. warning:: + Do not pass secrets, credentials, or API keys through ``factory_argument``. It is an + activity argument, so it is recorded in workflow history and, without a payload codec, + visible in the web UI. Resolve credentials worker-side inside the server factory + instead. + Args: name: A string name for the server. Should match that provided in the plugin. config: Optional activity configuration for MCP operation activities. Defaults to 1-minute start-to-close and 30-second schedule-to-start timeouts. server_session_config: Optional activity configuration for the connection activity. Defaults to 1-hour start-to-close timeout. - factory_argument: Optional argument to be provided to the factory when producing an MCPServer + factory_argument: Optional argument to be provided to the factory when producing an MCPServer. + Must not contain secrets. """ from temporalio.contrib.openai_agents._mcp import ( _StatefulMCPServerReference, From 84b519e0ff407b049da88ac7d1711f110494ff4d Mon Sep 17 00:00:00 2001 From: Thomas Hardy Date: Wed, 29 Jul 2026 12:51:23 -0400 Subject: [PATCH 189/226] Prepare release 1.31.0 (#1693) --- CHANGELOG.md | 18 ++++++++++++++---- pyproject.toml | 2 +- temporalio/service.py | 2 +- uv.lock | 2 +- 4 files changed, 17 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f8fe94d4b..5ba9c669d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,6 +20,20 @@ to include examples, links to docs, or any other relevant information. ### Added +### Changed + +### Deprecated + +### Breaking Changes + +### Fixed + +### Security + +## [1.31.0] - 2026-07-29 + +### Added + - Added the `Worker` `max_eager_activity_reservations_per_workflow_task` option for configuring the number of activity slots reserved for eager execution per workflow task. Configured values must be positive; use `disable_eager_activity_execution` to disable eager activity execution. @@ -50,8 +64,6 @@ to include examples, links to docs, or any other relevant information. overrides for this flag from `tests/worker/test_workflow.py`, and replace this rollout note with a `Fixed` entry announcing the behavior change. -### Deprecated - ### Breaking Changes - Custom workflow runners that construct `WorkflowInstanceDetails` must now pass @@ -72,8 +84,6 @@ to include examples, links to docs, or any other relevant information. - Marked system Nexus envelope payloads so nested payloads can be detected and visited after the envelope is already stored as a payload. -### Security - ## [1.30.0] - 2026-07-01 ### Added diff --git a/pyproject.toml b/pyproject.toml index ba0abfc3d..2303bdf00 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "temporalio" -version = "1.30.0" +version = "1.31.0" description = "Temporal.io Python SDK" authors = [{ name = "Temporal Technologies Inc", email = "sdk@temporal.io" }] requires-python = ">=3.10" diff --git a/temporalio/service.py b/temporalio/service.py index bddcf97fc..130b5d295 100644 --- a/temporalio/service.py +++ b/temporalio/service.py @@ -24,7 +24,7 @@ import temporalio.runtime from temporalio.bridge.client import RPCError as BridgeRPCError -__version__ = "1.30.0" +__version__ = "1.31.0" ServiceRequest = TypeVar("ServiceRequest", bound=google.protobuf.message.Message) ServiceResponse = TypeVar("ServiceResponse", bound=google.protobuf.message.Message) diff --git a/uv.lock b/uv.lock index f3b9f8c9d..7641ad8e8 100644 --- a/uv.lock +++ b/uv.lock @@ -4659,7 +4659,7 @@ wheels = [ [[package]] name = "temporalio" -version = "1.30.0" +version = "1.31.0" source = { virtual = "." } dependencies = [ { name = "nexus-rpc" }, From ca3a3885228c290498e4e1398374b99edece51d3 Mon Sep 17 00:00:00 2001 From: Tim Conley Date: Wed, 29 Jul 2026 11:02:07 -0700 Subject: [PATCH 190/226] Automate release preparation (#1692) --- scripts/prepare_release.py | 94 ++++++++++++++++++++++++++- tests/test_prepare_release.py | 118 ++++++++++++++++++++++++++++++++++ 2 files changed, 211 insertions(+), 1 deletion(-) diff --git a/scripts/prepare_release.py b/scripts/prepare_release.py index 22305aa8a..2965f8da1 100644 --- a/scripts/prepare_release.py +++ b/scripts/prepare_release.py @@ -24,6 +24,13 @@ VERSION_RE = re.compile(r"[0-9]+(?:\.[0-9]+)+(?:[a-zA-Z0-9_.+-]+)?") _CHANGELOG_HEADING_RE = re.compile(r"^## \[(?P[^\]]+)\](?:\s+-\s+.*)?\s*$") _CHANGELOG_SUBHEADING_RE = re.compile(r"^### (?P
    .+?)\s*$") +_RELEASE_FILES = ( + "CHANGELOG.md", + "pyproject.toml", + "temporalio/service.py", + "uv.lock", +) +_RELEASE_FILE_SET = frozenset(_RELEASE_FILES) def validate_version(version: str) -> str: @@ -94,6 +101,82 @@ def replace_service_version(text: str, version: str) -> str: ) +def create_release_branch(repo_root: pathlib.Path, version: str) -> None: + subprocess.run(["git", "fetch", "origin", "main"], cwd=repo_root, check=True) + subprocess.run( + ["git", "switch", "--create", f"chore/release-{version}", "origin/main"], + cwd=repo_root, + check=True, + ) + + +def changed_files(repo_root: pathlib.Path) -> set[str]: + result = subprocess.run( + ["git", "status", "--porcelain"], + cwd=repo_root, + check=True, + capture_output=True, + text=True, + ) + return {line[3:] for line in result.stdout.splitlines()} + + +def ensure_clean_worktree(repo_root: pathlib.Path) -> None: + changes = changed_files(repo_root) + if changes: + raise RuntimeError( + "Release preparation requires a clean worktree; found changes in " + + ", ".join(sorted(changes)) + ) + + +def ensure_only_release_changes(repo_root: pathlib.Path) -> None: + unexpected_files = changed_files(repo_root) - _RELEASE_FILE_SET + if unexpected_files: + raise RuntimeError( + "Release preparation changed unexpected files: " + + ", ".join(sorted(unexpected_files)) + ) + + +def commit_release_changes(repo_root: pathlib.Path, version: str) -> None: + subprocess.run( + ["git", "commit", "-m", f"Prepare release {version}", "--", *_RELEASE_FILES], + cwd=repo_root, + check=True, + ) + + +def push_release_branch(repo_root: pathlib.Path, version: str) -> None: + branch = f"chore/release-{version}" + subprocess.run( + ["git", "push", "--set-upstream", "origin", branch], + cwd=repo_root, + check=True, + ) + + +def create_release_pr(repo_root: pathlib.Path, version: str) -> None: + branch = f"chore/release-{version}" + subprocess.run( + [ + "gh", + "pr", + "create", + "--base", + "main", + "--head", + branch, + "--title", + f"Prepare release {version}", + "--body", + f"Prepare release {version}.", + ], + cwd=repo_root, + check=True, + ) + + def _seeded_unreleased_lines() -> list[str]: lines = ["## [Unreleased]", ""] for header in CHANGELOG_HEADERS: @@ -197,6 +280,8 @@ def main(argv: Sequence[str] | None = None) -> None: repo_root = pathlib.Path(__file__).resolve().parents[1] version = validate_version(args.version) release_date = parse_date(args.date) + ensure_clean_worktree(repo_root) + create_release_branch(repo_root, version) changelog_path = repo_root / "CHANGELOG.md" pyproject_path = repo_root / "pyproject.toml" service_path = repo_root / "temporalio" / "service.py" @@ -228,7 +313,14 @@ def main(argv: Sequence[str] | None = None) -> None: if not args.skip_lock: subprocess.run(["uv", "lock"], cwd=repo_root, check=True) - print(f"Prepared release {version} dated {release_date.isoformat()}") + ensure_only_release_changes(repo_root) + commit_release_changes(repo_root, version) + push_release_branch(repo_root, version) + create_release_pr(repo_root, version) + + print( + f"Prepared release {version} dated {release_date.isoformat()} and opened a PR" + ) if __name__ == "__main__": diff --git a/tests/test_prepare_release.py b/tests/test_prepare_release.py index b971d499a..6dae0794f 100644 --- a/tests/test_prepare_release.py +++ b/tests/test_prepare_release.py @@ -1,9 +1,18 @@ from __future__ import annotations import datetime +import pathlib +import subprocess + +import pytest from scripts.prepare_release import ( + create_release_branch, + create_release_pr, + ensure_clean_worktree, + ensure_only_release_changes, finalize_changelog_release, + push_release_branch, replace_project_version, replace_service_version, ) @@ -80,3 +89,112 @@ def test_replace_versions() -> None: ) == '__version__ = "1.30.0"\n\nServiceRequest = TypeVar("ServiceRequest")' ) + + +def test_create_release_branch_fetches_main_and_branches_from_it( + monkeypatch: pytest.MonkeyPatch, +) -> None: + calls: list[tuple[list[str], pathlib.Path, bool]] = [] + + def run(command: list[str], *, cwd: pathlib.Path, check: bool) -> None: + calls.append((command, cwd, check)) + + monkeypatch.setattr(subprocess, "run", run) + + repo_root = pathlib.Path("/repo") + create_release_branch(repo_root, "1.30.0") + + assert calls == [ + (["git", "fetch", "origin", "main"], repo_root, True), + ( + ["git", "switch", "--create", "chore/release-1.30.0", "origin/main"], + repo_root, + True, + ), + ] + + +def test_ensure_clean_worktree_rejects_existing_changes( + monkeypatch: pytest.MonkeyPatch, +) -> None: + monkeypatch.setattr( + subprocess, + "run", + lambda *_args, **_kwargs: subprocess.CompletedProcess( + args=[], returncode=0, stdout=" M temporalio/service.py\n" + ), + ) + + with pytest.raises(RuntimeError, match="clean worktree"): + ensure_clean_worktree(pathlib.Path("/repo")) + + +def test_ensure_only_release_changes_rejects_unexpected_files( + monkeypatch: pytest.MonkeyPatch, +) -> None: + monkeypatch.setattr( + subprocess, + "run", + lambda *_args, **_kwargs: subprocess.CompletedProcess( + args=[], returncode=0, stdout=" M unrelated.txt\n" + ), + ) + + with pytest.raises(RuntimeError, match="unexpected files: unrelated.txt"): + ensure_only_release_changes(pathlib.Path("/repo")) + + +def test_create_release_pr_uses_versioned_branch( + monkeypatch: pytest.MonkeyPatch, +) -> None: + calls: list[tuple[list[str], pathlib.Path, bool]] = [] + + def run(command: list[str], *, cwd: pathlib.Path, check: bool) -> None: + calls.append((command, cwd, check)) + + monkeypatch.setattr(subprocess, "run", run) + + repo_root = pathlib.Path("/repo") + create_release_pr(repo_root, "1.30.0") + + assert calls == [ + ( + [ + "gh", + "pr", + "create", + "--base", + "main", + "--head", + "chore/release-1.30.0", + "--title", + "Prepare release 1.30.0", + "--body", + "Prepare release 1.30.0.", + ], + repo_root, + True, + ) + ] + + +def test_push_release_branch_uses_versioned_branch( + monkeypatch: pytest.MonkeyPatch, +) -> None: + calls: list[tuple[list[str], pathlib.Path, bool]] = [] + + def run(command: list[str], *, cwd: pathlib.Path, check: bool) -> None: + calls.append((command, cwd, check)) + + monkeypatch.setattr(subprocess, "run", run) + + repo_root = pathlib.Path("/repo") + push_release_branch(repo_root, "1.30.0") + + assert calls == [ + ( + ["git", "push", "--set-upstream", "origin", "chore/release-1.30.0"], + repo_root, + True, + ) + ] From febf6ab40335bdf03013ba3c70c56dc181e3e5d1 Mon Sep 17 00:00:00 2001 From: Tim Conley Date: Wed, 29 Jul 2026 12:04:16 -0700 Subject: [PATCH 191/226] Mark breaking change headers (#1694) --- CHANGELOG.md | 10 +++++----- scripts/prepare_release.py | 2 +- tests/test_prepare_release.py | 4 +++- 3 files changed, 9 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5ba9c669d..9db966f52 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,7 +9,7 @@ to include examples, links to docs, or any other relevant information. ### Added — new features ### Changed — changes in existing functionality ### Deprecated — soon-to-be-removed features -### Breaking Changes — removed or backwards-incompatible features +### :boom: Breaking Changes — removed or backwards-incompatible features ### Fixed — notable bug fixes ### Security — notable security fixes --> @@ -24,7 +24,7 @@ to include examples, links to docs, or any other relevant information. ### Deprecated -### Breaking Changes +### :boom: Breaking Changes ### Fixed @@ -64,7 +64,7 @@ to include examples, links to docs, or any other relevant information. overrides for this flag from `tests/worker/test_workflow.py`, and replace this rollout note with a `Fixed` entry announcing the behavior change. -### Breaking Changes +### :boom: Breaking Changes - Custom workflow runners that construct `WorkflowInstanceDetails` must now pass `payload_converter_factory` instead of `payload_converter_class`. The factory @@ -104,7 +104,7 @@ to include examples, links to docs, or any other relevant information. with the selected optional dependencies. - Standalone Nexus operation links are now forwarded on start workflow and signal requests. -### Breaking Changes +### :boom: Breaking Changes - AWS Lambda worker `configure` parameter has been changed to be invoked per-invocation of the worker instead of only at startup. It is advised that @@ -127,7 +127,7 @@ to include examples, links to docs, or any other relevant information. Pass `grpc_compression=GrpcCompression.NONE` to `Client.connect` or `CloudOperationsClient.connect` to disable it. -### Breaking Changes +### :boom: Breaking Changes - `StartWorkflowUpdateWithStartInput` now owns the authoritative `rpc_metadata` and `rpc_timeout` fields for diff --git a/scripts/prepare_release.py b/scripts/prepare_release.py index 2965f8da1..51dc34496 100644 --- a/scripts/prepare_release.py +++ b/scripts/prepare_release.py @@ -17,7 +17,7 @@ "Added", "Changed", "Deprecated", - "Breaking Changes", + ":boom: Breaking Changes", "Fixed", "Security", ) diff --git a/tests/test_prepare_release.py b/tests/test_prepare_release.py index 6dae0794f..ee42cf8a0 100644 --- a/tests/test_prepare_release.py +++ b/tests/test_prepare_release.py @@ -29,6 +29,8 @@ def test_finalize_changelog_release_seeds_unreleased_and_versions_notes() -> Non - Changed a thing. +### :boom: Breaking Changes + ### Fixed ## [1.29.0] - 2026-06-17 @@ -55,7 +57,7 @@ def test_finalize_changelog_release_seeds_unreleased_and_versions_notes() -> Non ### Deprecated -### Breaking Changes +### :boom: Breaking Changes ### Fixed From 63eadc729df1873cec2e5427c81d881ef7a0f1c5 Mon Sep 17 00:00:00 2001 From: Alex Mazzeo Date: Thu, 30 Jul 2026 07:29:25 -0700 Subject: [PATCH 192/226] Add eventual assertion to link test to account for eventual consistency in visibility (#1696) --- tests/nexus/test_standalone_operations.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tests/nexus/test_standalone_operations.py b/tests/nexus/test_standalone_operations.py index 8193ba7ba..c71337b20 100644 --- a/tests/nexus/test_standalone_operations.py +++ b/tests/nexus/test_standalone_operations.py @@ -308,8 +308,10 @@ async def test_started_workflow_has_link_to_standalone_nexus_operation( workflow_history = await _assert_workflow_started_with_nexus_operation_link( client, workflow_id, handle ) - await _assert_nexus_operation_has_link_to_started_workflow( - client, workflow_history, handle + await assert_eventually( + lambda: _assert_nexus_operation_has_link_to_started_workflow( + client, workflow_history, handle + ) ) workflow_handle = client.get_workflow_handle(workflow_id) From 2777500a5affe16611c1a17c95b83c69adf4fec4 Mon Sep 17 00:00:00 2001 From: Justin Anderson <44687433+jmaeagle99@users.noreply.github.com> Date: Thu, 30 Jul 2026 08:40:45 -0700 Subject: [PATCH 193/226] feat(extstore): Add support for Nexus task handling (#1676) --- CHANGELOG.md | 1 + scripts/gen_payload_visitor.py | 4 + temporalio/bridge/_visitor.py | 52 +++++ temporalio/converter/_data_converter.py | 4 +- temporalio/converter/_extstore.py | 8 +- temporalio/worker/_nexus.py | 134 +++++++++--- tests/nexus/test_temporal_extstore.py | 270 ++++++++++++++++++++++++ 7 files changed, 437 insertions(+), 36 deletions(-) create mode 100644 tests/nexus/test_temporal_extstore.py diff --git a/CHANGELOG.md b/CHANGELOG.md index 9db966f52..483c73d1d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -52,6 +52,7 @@ to include examples, links to docs, or any other relevant information. - Added the experimental `Worker` `patch_activation_callback` option, allowing workers to decide whether a first non-replay `workflow.patched` call should activate a patch during rolling deployments. +- Added external storage support to Nexus task handling. ### Changed diff --git a/scripts/gen_payload_visitor.py b/scripts/gen_payload_visitor.py index f782616cf..0001659f7 100644 --- a/scripts/gen_payload_visitor.py +++ b/scripts/gen_payload_visitor.py @@ -12,6 +12,7 @@ sys.path.insert(0, str(base_dir)) from temporalio.api.common.v1.message_pb2 import Payload, Payloads, SearchAttributes +from temporalio.bridge.proto.nexus import NexusTaskCompletion from temporalio.bridge.proto.workflow_activation.workflow_activation_pb2 import ( WorkflowActivation, ) @@ -425,9 +426,12 @@ def walk(self, desc: Descriptor) -> bool: def write_bridge_visitors() -> None: out_path = base_dir / "temporalio" / "bridge" / "_visitor.py" + # Build root descriptors: WorkflowActivation, WorkflowActivationCompletion, + # NexusTaskCompletion, and the system Nexus operation roots. roots: list[Descriptor] = [ WorkflowActivation.DESCRIPTOR, WorkflowActivationCompletion.DESCRIPTOR, + NexusTaskCompletion.DESCRIPTOR, ] + discover_system_nexus_roots() code = VisitorGenerator().generate(roots) diff --git a/temporalio/bridge/_visitor.py b/temporalio/bridge/_visitor.py index e5e48ea16..ef1e21dbd 100644 --- a/temporalio/bridge/_visitor.py +++ b/temporalio/bridge/_visitor.py @@ -548,6 +548,58 @@ async def _visit_coresdk_workflow_completion_WorkflowActivationCompletion( elif o.HasField("failed"): await self._visit_coresdk_workflow_completion_Failure(fs, o.failed) + async def _visit_temporal_api_nexus_v1_StartOperationResponse_Sync( + self, fs: VisitorFunctions, o: Any + ): + if o.HasField("payload"): + await self._visit_temporal_api_common_v1_Payload(fs, o.payload) + + async def _visit_temporal_api_nexus_v1_Failure(self, fs: VisitorFunctions, o: Any): + if o.HasField("cause"): + await self._visit_temporal_api_nexus_v1_Failure(fs, o.cause) + + async def _visit_temporal_api_nexus_v1_UnsuccessfulOperationError( + self, fs: VisitorFunctions, o: Any + ): + if o.HasField("failure"): + await self._visit_temporal_api_nexus_v1_Failure(fs, o.failure) + + async def _visit_temporal_api_nexus_v1_StartOperationResponse( + self, fs: VisitorFunctions, o: Any + ): + if o.HasField("sync_success"): + await self._visit_temporal_api_nexus_v1_StartOperationResponse_Sync( + fs, o.sync_success + ) + elif o.HasField("operation_error"): + await self._visit_temporal_api_nexus_v1_UnsuccessfulOperationError( + fs, o.operation_error + ) + elif o.HasField("failure"): + await self._visit_temporal_api_failure_v1_Failure(fs, o.failure) + + async def _visit_temporal_api_nexus_v1_Response(self, fs: VisitorFunctions, o: Any): + if o.HasField("start_operation"): + await self._visit_temporal_api_nexus_v1_StartOperationResponse( + fs, o.start_operation + ) + + async def _visit_temporal_api_nexus_v1_HandlerError( + self, fs: VisitorFunctions, o: Any + ): + if o.HasField("failure"): + await self._visit_temporal_api_nexus_v1_Failure(fs, o.failure) + + async def _visit_coresdk_nexus_NexusTaskCompletion( + self, fs: VisitorFunctions, o: Any + ): + if o.HasField("completed"): + await self._visit_temporal_api_nexus_v1_Response(fs, o.completed) + elif o.HasField("error"): + await self._visit_temporal_api_nexus_v1_HandlerError(fs, o.error) + elif o.HasField("failure"): + await self._visit_temporal_api_failure_v1_Failure(fs, o.failure) + async def _visit_temporal_api_common_v1_Header(self, fs: VisitorFunctions, o: Any): for v in o.fields.values(): await self._visit_temporal_api_common_v1_Payload(fs, v) diff --git a/temporalio/converter/_data_converter.py b/temporalio/converter/_data_converter.py index 6425d6b61..8604ea196 100644 --- a/temporalio/converter/_data_converter.py +++ b/temporalio/converter/_data_converter.py @@ -13,9 +13,9 @@ import temporalio.api.common.v1 import temporalio.api.failure.v1 import temporalio.common -from temporalio.api.sdk.v1.external_storage_pb2 import ExternalStorageReference from temporalio.converter._extstore import ( _REFERENCE_ENCODING, + _REFERENCE_MESSAGE_TYPE, ExternalStorage, StorageDriverStoreContext, ) @@ -35,8 +35,6 @@ WithSerializationContext, ) -_REFERENCE_MESSAGE_TYPE = ExternalStorageReference.DESCRIPTOR.full_name.encode() - def _is_reference_payload(p: temporalio.api.common.v1.Payload) -> bool: """Return True if *p* is an external-storage reference payload.""" diff --git a/temporalio/converter/_extstore.py b/temporalio/converter/_extstore.py index c31424acf..a946b2c0f 100644 --- a/temporalio/converter/_extstore.py +++ b/temporalio/converter/_extstore.py @@ -27,6 +27,7 @@ _T = TypeVar("_T") _REFERENCE_ENCODING = b"json/external-storage-reference" +_REFERENCE_MESSAGE_TYPE = ExternalStorageReference.DESCRIPTOR.full_name.encode() @dataclass @@ -455,8 +456,6 @@ async def _store_payload_sequence( def _decode_reference(self, payload: Payload) -> ExternalStorageReference | None: """Decode an external storage reference from a payload.""" - if len(payload.external_payloads) == 0: - return None encoding = payload.metadata.get("encoding", b"") if encoding == _REFERENCE_ENCODING: legacy = self._legacy_claim_converter.from_payload( @@ -468,6 +467,11 @@ def _decode_reference(self, payload: Payload) -> ExternalStorageReference | None driver_name=legacy.driver_name, claim_data=legacy.driver_claim.claim_data, ) + if not ( + encoding == b"json/protobuf" + and payload.metadata.get("messageType") == _REFERENCE_MESSAGE_TYPE + ): + return None ref = self._claim_converter.from_payload(payload, ExternalStorageReference) return ref if isinstance(ref, ExternalStorageReference) else None diff --git a/temporalio/worker/_nexus.py b/temporalio/worker/_nexus.py index 08ecd2f81..131e50862 100644 --- a/temporalio/worker/_nexus.py +++ b/temporalio/worker/_nexus.py @@ -6,7 +6,7 @@ import concurrent.futures import contextvars import threading -from collections.abc import Callable, Mapping, Sequence +from collections.abc import Awaitable, Callable, Mapping, Sequence from dataclasses import dataclass from datetime import datetime, timezone from functools import reduce @@ -30,6 +30,8 @@ import temporalio.common import temporalio.converter import temporalio.nexus +from temporalio.bridge._visitor import PayloadVisitor +from temporalio.bridge._visitor_functions import PayloadSequence, VisitorFunctions from temporalio.bridge.worker import PollShutdownError from temporalio.exceptions import ( ApplicationError, @@ -216,6 +218,19 @@ async def _complete_task( ): await asyncio.shield(self._bridge_worker().complete_nexus_task(completion)) + async def _encode_completion( + self, completion: temporalio.bridge.proto.nexus.NexusTaskCompletion + ) -> None: + """Apply the payload codec then external storage to the completion's payloads.""" + dc = self._data_converter + await PayloadVisitor(skip_search_attributes=True, skip_headers=True).visit( + _PayloadTransformVisitor(dc._encode_payload_sequence), completion + ) + await PayloadVisitor(skip_search_attributes=True).visit( + _PayloadTransformVisitor(dc._external_store_payload_sequence), + completion, + ) + # TODO(nexus-preview): stack trace pruning. See sdk-typescript NexusHandler.execute # "Any call up to this function and including this one will be trimmed out of stack traces."" @@ -260,6 +275,14 @@ async def _handle_cancel_operation_task( try: try: await self._handler.cancel_operation(ctx, request.operation_token) + completion = temporalio.bridge.proto.nexus.NexusTaskCompletion( + task_token=task_token, + completed=temporalio.api.nexus.v1.Response( + cancel_operation=temporalio.api.nexus.v1.CancelOperationResponse() + ), + ) + # No-op but keeps the cancel covered if it ever carries a payload. + await self._encode_completion(completion) except asyncio.CancelledError: completion = temporalio.bridge.proto.nexus.NexusTaskCompletion( task_token=task_token, @@ -271,16 +294,12 @@ async def _handle_cancel_operation_task( completion = temporalio.bridge.proto.nexus.NexusTaskCompletion( task_token=task_token, ) - await self._data_converter.encode_failure( - handler_error, completion.failure - ) - else: - completion = temporalio.bridge.proto.nexus.NexusTaskCompletion( - task_token=task_token, - completed=temporalio.api.nexus.v1.Response( - cancel_operation=temporalio.api.nexus.v1.CancelOperationResponse() - ), + self._data_converter.failure_converter.to_failure( + handler_error, + self._data_converter.payload_converter, + completion.failure, ) + await self._encode_completion(completion) await self._complete_task(completion) except Exception: logger.exception("Failed to send Nexus task completion") @@ -315,6 +334,13 @@ async def _handle_start_operation_task( request_deadline, endpoint, ) + completion = temporalio.bridge.proto.nexus.NexusTaskCompletion( + task_token=task_token, + completed=temporalio.api.nexus.v1.Response( + start_operation=start_response + ), + ) + await self._encode_completion(completion) except asyncio.CancelledError: completion = temporalio.bridge.proto.nexus.NexusTaskCompletion( task_token=task_token, @@ -326,19 +352,15 @@ async def _handle_start_operation_task( task_token=task_token, ) handler_error = _exception_to_handler_error(err) - await self._data_converter.encode_failure( - handler_error, completion.failure + self._data_converter.failure_converter.to_failure( + handler_error, + self._data_converter.payload_converter, + completion.failure, ) if isinstance(err, concurrent.futures.BrokenExecutor): self._fail_worker_exception_queue.put_nowait(err) - else: - completion = temporalio.bridge.proto.nexus.NexusTaskCompletion( - task_token=task_token, - completed=temporalio.api.nexus.v1.Response( - start_operation=start_response - ), - ) + await self._encode_completion(completion) await self._complete_task(completion) except Exception: @@ -417,7 +439,9 @@ async def _start_operation( ) ) elif isinstance(result, nexusrpc.handler.StartOperationResultSync): - [payload] = await self._data_converter.encode([result.value]) + [payload] = self._data_converter.payload_converter.to_payloads( + [result.value] + ) return temporalio.api.nexus.v1.StartOperationResponse( sync_success=temporalio.api.nexus.v1.StartOperationResponse.Sync( payload=payload, @@ -446,10 +470,41 @@ async def _start_operation( ) from err.__cause__ except FailureError as new_err: response = temporalio.api.nexus.v1.StartOperationResponse() - await self._data_converter.encode_failure(new_err, response.failure) + self._data_converter.failure_converter.to_failure( + new_err, + self._data_converter.payload_converter, + response.failure, + ) return response +class _PayloadTransformVisitor(VisitorFunctions): + """Adapts a payload-sequence transform for use with :class:`PayloadVisitor`.""" + + def __init__( + self, + f: Callable[ + [Sequence[temporalio.api.common.v1.Payload]], + Awaitable[list[temporalio.api.common.v1.Payload]], + ], + ) -> None: + self._f = f + + async def visit_payload(self, payload: temporalio.api.common.v1.Payload) -> None: + new_payload = (await self._f([payload]))[0] + if new_payload is not payload: + payload.CopyFrom(new_payload) + + async def visit_payloads(self, payloads: PayloadSequence) -> None: + if len(payloads) == 0: + return + new_payloads = await self._f(payloads) + if new_payloads is payloads: + return + del payloads[:] + payloads.extend(new_payloads) + + @dataclass class _DummyPayloadSerializer: data_converter: temporalio.converter.DataConverter @@ -465,18 +520,35 @@ async def deserialize( content: nexusrpc.Content, # type:ignore[reportUnusedParameter] as_type: type[Any] | None = None, ) -> Any: - payload = self.payload - if self.data_converter.payload_codec: - try: - [payload] = await self.data_converter.payload_codec.decode([payload]) - except Exception as err: - raise nexusrpc.HandlerError( - "Payload codec failed to decode Nexus operation input", - type=nexusrpc.HandlerErrorType.INTERNAL, - ) from err + dc = self.data_converter + # The visitor mutates in place, so work on a copy to leave the request + # payload untouched. + payload = temporalio.api.common.v1.Payload() + payload.CopyFrom(self.payload) + try: + await PayloadVisitor(skip_search_attributes=True).visit( + _PayloadTransformVisitor(dc._external_retrieve_payload_sequence), + payload, + ) + except Exception as err: + raise nexusrpc.HandlerError( + "Failed to retrieve Nexus operation input from external storage", + type=nexusrpc.HandlerErrorType.INTERNAL, + retryable_override=True, + ) from err + + try: + await PayloadVisitor(skip_search_attributes=True, skip_headers=True).visit( + _PayloadTransformVisitor(dc._decode_payload_sequence), payload + ) + except Exception as err: + raise nexusrpc.HandlerError( + "Payload codec failed to decode Nexus operation input", + type=nexusrpc.HandlerErrorType.INTERNAL, + ) from err try: - [input] = self.data_converter.payload_converter.from_payloads( + [input] = dc.payload_converter.from_payloads( [payload], type_hints=[as_type] if as_type else None, ) diff --git a/tests/nexus/test_temporal_extstore.py b/tests/nexus/test_temporal_extstore.py new file mode 100644 index 000000000..2afbac44c --- /dev/null +++ b/tests/nexus/test_temporal_extstore.py @@ -0,0 +1,270 @@ +"""Integration tests for external storage with Nexus task processing. + +Mirrors sdk-typescript's test-integration-extstore-nexus. A caller workflow +invokes a Nexus operation whose input and/or result is large enough to be +offloaded to external storage. Verifies that the offloaded input is retrieved +before the handler runs, that a large synchronous result is offloaded when +completing the task (and retrieved by the caller), and that a transient +storage-driver failure fails the Nexus task retryably and then recovers. +""" + +from __future__ import annotations + +import dataclasses +import uuid +from collections.abc import Sequence +from datetime import timedelta +from typing import Any + +import nexusrpc +import pytest +from nexusrpc.handler import ( + StartOperationContext, + service_handler, + sync_operation, +) + +import temporalio.converter +from temporalio import workflow +from temporalio.api.common.v1 import Payload +from temporalio.client import Client, WorkflowFailureError +from temporalio.converter import ( + ExternalStorage, + StorageDriverClaim, + StorageDriverRetrieveContext, + StorageDriverStoreContext, +) +from temporalio.exceptions import ApplicationError, NexusOperationError +from temporalio.testing import WorkflowEnvironment +from temporalio.types import MethodAsyncSingleParam +from temporalio.worker import UnsandboxedWorkflowRunner, Worker +from tests.helpers.nexus import make_nexus_endpoint_name +from tests.test_extstore import InMemoryTestDriver + +PAYLOAD_SIZE = 4096 +PAYLOAD_SIZE_THRESHOLD = 1024 +_STORE_FAILURE_MESSAGE = "external storage store failed" + + +@nexusrpc.service +class ExtStoreNexusService: + size_op: nexusrpc.Operation[str, int] + big_result_op: nexusrpc.Operation[int, str] + + +@service_handler(service=ExtStoreNexusService) +class ExtStoreNexusServiceHandler: + @sync_operation + async def size_op(self, _ctx: StartOperationContext, data: str) -> int: + return len(data) + + @sync_operation + async def big_result_op(self, _ctx: StartOperationContext, size: int) -> str: + return "x" * size + + +@workflow.defn +class SizeOpCallerWorkflow: + """Calls ``size_op`` with a large input (offloaded) and returns its length.""" + + @workflow.run + async def run(self, task_queue: str) -> int: + nexus_client = workflow.create_nexus_client( + service=ExtStoreNexusService, + endpoint=make_nexus_endpoint_name(task_queue), + ) + return await nexus_client.execute_operation( + ExtStoreNexusService.size_op, "x" * PAYLOAD_SIZE + ) + + +@workflow.defn +class BigResultOpCallerWorkflow: + """Calls ``big_result_op`` (whose result is offloaded) and returns its length.""" + + @workflow.run + async def run(self, task_queue: str) -> int: + nexus_client = workflow.create_nexus_client( + service=ExtStoreNexusService, + endpoint=make_nexus_endpoint_name(task_queue), + ) + result = await nexus_client.execute_operation( + ExtStoreNexusService.big_result_op, PAYLOAD_SIZE + ) + return len(result) + + +class TransientFailureDriver(InMemoryTestDriver): + """In-memory driver that fails the first store and/or retrieve call, then + behaves normally. Simulates a transient storage-driver outage.""" + + def __init__( + self, + *, + fail_first_store: bool = False, + fail_first_retrieve: bool = False, + driver_name: str = "test-driver", + ): + super().__init__(driver_name=driver_name) + self._fail_first_store = fail_first_store + self._fail_first_retrieve = fail_first_retrieve + self.store_attempts = 0 + self.retrieve_attempts = 0 + + async def store( + self, + context: StorageDriverStoreContext, + payloads: Sequence[Payload], + ) -> list[StorageDriverClaim]: + self.store_attempts += 1 + if self._fail_first_store and self.store_attempts == 1: + raise RuntimeError("transient store failure") + return await super().store(context, payloads) + + async def retrieve( + self, + context: StorageDriverRetrieveContext, + claims: Sequence[StorageDriverClaim], + ) -> list[Payload]: + self.retrieve_attempts += 1 + if self._fail_first_retrieve and self.retrieve_attempts == 1: + raise RuntimeError("transient retrieve failure") + return await super().retrieve(context, claims) + + +def _client_with_extstore( + env: WorkflowEnvironment, driver: InMemoryTestDriver +) -> Client: + config = env.client.config() + config["data_converter"] = dataclasses.replace( + temporalio.converter.default(), + external_storage=ExternalStorage( + drivers=[driver], + payload_size_threshold=PAYLOAD_SIZE_THRESHOLD, + ), + ) + return Client(**config) + + +async def _run_caller( + env: WorkflowEnvironment, + driver: InMemoryTestDriver, + workflow_run: MethodAsyncSingleParam[Any, str, int], +) -> int: + client = _client_with_extstore(env, driver) + task_queue = str(uuid.uuid4()) + async with Worker( + client, + task_queue=task_queue, + workflows=[SizeOpCallerWorkflow, BigResultOpCallerWorkflow], + nexus_service_handlers=[ExtStoreNexusServiceHandler()], + workflow_runner=UnsandboxedWorkflowRunner(), + ): + await env.create_nexus_endpoint( + make_nexus_endpoint_name(task_queue), task_queue + ) + return await client.execute_workflow( + workflow_run, + task_queue, + id=str(uuid.uuid4()), + task_queue=task_queue, + execution_timeout=timedelta(seconds=30), + ) + + +def _cause_chain(err: BaseException) -> list[BaseException]: + chain: list[BaseException] = [] + e: BaseException | None = err + while e is not None: + chain.append(e) + e = e.__cause__ + return chain + + +async def test_nexus_operation_input_offloaded_and_retrieved(env: WorkflowEnvironment): + """The offloaded operation input is retrieved before the handler runs.""" + if env.supports_time_skipping: + pytest.skip("Nexus tests don't work with the Java test server") + + driver = InMemoryTestDriver() + result = await _run_caller(env, driver, SizeOpCallerWorkflow.run) + + assert result == PAYLOAD_SIZE + assert driver._store_calls >= 1 + assert driver._retrieve_calls >= 1 + + +async def test_nexus_operation_sync_result_offloaded_and_retrieved( + env: WorkflowEnvironment, +): + """A large synchronous result is offloaded and retrieved by the caller.""" + if env.supports_time_skipping: + pytest.skip("Nexus tests don't work with the Java test server") + + driver = InMemoryTestDriver() + result = await _run_caller(env, driver, BigResultOpCallerWorkflow.run) + + assert result == PAYLOAD_SIZE + assert driver._store_calls >= 1 + assert driver._retrieve_calls >= 1 + + +async def test_nexus_operation_transient_retrieve_failure_recovers( + env: WorkflowEnvironment, +): + """A transient retrieve failure fails the task retryably; it then recovers.""" + if env.supports_time_skipping: + pytest.skip("Nexus tests don't work with the Java test server") + + driver = TransientFailureDriver(fail_first_retrieve=True) + result = await _run_caller(env, driver, SizeOpCallerWorkflow.run) + + assert result == PAYLOAD_SIZE + assert driver.retrieve_attempts >= 2 + + +async def test_nexus_operation_transient_store_failure_recovers( + env: WorkflowEnvironment, +): + """A transient store failure fails the task retryably; it then recovers.""" + if env.supports_time_skipping: + pytest.skip("Nexus tests don't work with the Java test server") + + driver = TransientFailureDriver(fail_first_store=True) + result = await _run_caller(env, driver, BigResultOpCallerWorkflow.run) + + assert result == PAYLOAD_SIZE + assert driver.store_attempts >= 2 + + +class PermanentFailStoreDriver(InMemoryTestDriver): + """Store always fails non-retryably, so the Nexus operation fails permanently.""" + + async def store( + self, + context: StorageDriverStoreContext, + payloads: Sequence[Payload], + ) -> list[StorageDriverClaim]: + raise ApplicationError(_STORE_FAILURE_MESSAGE, non_retryable=True) + + +async def test_nexus_operation_store_failure_fails_operation( + env: WorkflowEnvironment, +): + """A non-retryable store failure fails the operation and surfaces the driver + error to the caller (deterministically, with no retries).""" + if env.supports_time_skipping: + pytest.skip("Nexus tests don't work with the Java test server") + + driver = PermanentFailStoreDriver() + with pytest.raises(WorkflowFailureError) as exc_info: + await _run_caller(env, driver, BigResultOpCallerWorkflow.run) + + causes = _cause_chain(exc_info.value) + assert [type(c) for c in causes] == [ + WorkflowFailureError, + NexusOperationError, + nexusrpc.HandlerError, + ApplicationError, + ] + assert _STORE_FAILURE_MESSAGE in str(causes[-1]) From cafd35760797086d635594807be3579531a1f817 Mon Sep 17 00:00:00 2001 From: Justin Anderson <44687433+jmaeagle99@users.noreply.github.com> Date: Thu, 30 Jul 2026 09:58:22 -0700 Subject: [PATCH 194/226] fix: revert testmodule proto gen to mypy-protobuf 3.3.0 format (#1699) * fix: revert testmodule proto gen to mypy-protobuf 3.3.0 format * fix: add tests dir to git diff check --- .github/workflows/ci.yml | 2 +- .../testmodules/proto/proto_message_pb2.py | 40 +++++++++---------- .../testmodules/proto/proto_message_pb2.pyi | 10 ++--- 3 files changed, 24 insertions(+), 28 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 86dbe6253..49052107d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -159,7 +159,7 @@ jobs: - run: poe gen-protos - name: Check generation unchanged run: | - [[ -z $(git status --porcelain temporalio) ]] || (git diff temporalio; echo "Protos changed"; exit 1) + [[ -z $(git status --porcelain temporalio tests) ]] || (git diff temporalio tests; echo "Protos changed"; exit 1) - name: Test with protobuf 3.x run: poe test -s --ignore=tests/contrib/google_adk_agents/ env: diff --git a/tests/worker/workflow_sandbox/testmodules/proto/proto_message_pb2.py b/tests/worker/workflow_sandbox/testmodules/proto/proto_message_pb2.py index 73e1d2b1e..19a1c69b2 100644 --- a/tests/worker/workflow_sandbox/testmodules/proto/proto_message_pb2.py +++ b/tests/worker/workflow_sandbox/testmodules/proto/proto_message_pb2.py @@ -1,24 +1,14 @@ # -*- coding: utf-8 -*- # Generated by the protocol buffer compiler. DO NOT EDIT! -# NO CHECKED-IN PROTOBUF GENCODE # source: worker/workflow_sandbox/testmodules/proto/proto_message.proto -# Protobuf Python Version: 6.33.5 """Generated protocol buffer code.""" from google.protobuf import descriptor as _descriptor from google.protobuf import descriptor_pool as _descriptor_pool -from google.protobuf import runtime_version as _runtime_version +from google.protobuf import message as _message +from google.protobuf import reflection as _reflection from google.protobuf import symbol_database as _symbol_database -from google.protobuf.internal import builder as _builder - -_runtime_version.ValidateProtobufRuntimeVersion( - _runtime_version.Domain.PUBLIC, - 6, - 33, - 5, - "", - "worker/workflow_sandbox/testmodules/proto/proto_message.proto", -) + # @@protoc_insertion_point(imports) _sym_db = _symbol_database.Default() @@ -30,13 +20,21 @@ b'\n=worker/workflow_sandbox/testmodules/proto/proto_message.proto\x12)worker.workflow_sandbox.testmodules.proto\x1a\x1egoogle/protobuf/duration.proto"?\n\x0bSomeMessage\x12\x30\n\rsome_duration\x18\x01 \x01(\x0b\x32\x19.google.protobuf.Durationb\x06proto3' ) -_globals = globals() -_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) -_builder.BuildTopDescriptorsAndMessages( - DESCRIPTOR, "worker.workflow_sandbox.testmodules.proto.proto_message_pb2", _globals + +_SOMEMESSAGE = DESCRIPTOR.message_types_by_name["SomeMessage"] +SomeMessage = _reflection.GeneratedProtocolMessageType( + "SomeMessage", + (_message.Message,), + { + "DESCRIPTOR": _SOMEMESSAGE, + "__module__": "worker.workflow_sandbox.testmodules.proto.proto_message_pb2", + # @@protoc_insertion_point(class_scope:worker.workflow_sandbox.testmodules.proto.SomeMessage) + }, ) -if not _descriptor._USE_C_DESCRIPTORS: - DESCRIPTOR._loaded_options = None - _globals["_SOMEMESSAGE"]._serialized_start = 140 - _globals["_SOMEMESSAGE"]._serialized_end = 203 +_sym_db.RegisterMessage(SomeMessage) + +if _descriptor._USE_C_DESCRIPTORS == False: + DESCRIPTOR._options = None + _SOMEMESSAGE._serialized_start = 140 + _SOMEMESSAGE._serialized_end = 203 # @@protoc_insertion_point(module_scope) diff --git a/tests/worker/workflow_sandbox/testmodules/proto/proto_message_pb2.pyi b/tests/worker/workflow_sandbox/testmodules/proto/proto_message_pb2.pyi index b2c6f24a9..db5f796b3 100644 --- a/tests/worker/workflow_sandbox/testmodules/proto/proto_message_pb2.pyi +++ b/tests/worker/workflow_sandbox/testmodules/proto/proto_message_pb2.pyi @@ -5,20 +5,18 @@ isort:skip_file import builtins import sys -import typing import google.protobuf.descriptor import google.protobuf.duration_pb2 import google.protobuf.message -if sys.version_info >= (3, 10): +if sys.version_info >= (3, 8): import typing as typing_extensions else: import typing_extensions DESCRIPTOR: google.protobuf.descriptor.FileDescriptor -@typing.final class SomeMessage(google.protobuf.message.Message): DESCRIPTOR: google.protobuf.descriptor.Descriptor @@ -31,10 +29,10 @@ class SomeMessage(google.protobuf.message.Message): some_duration: google.protobuf.duration_pb2.Duration | None = ..., ) -> None: ... def HasField( - self, field_name: typing.Literal["some_duration", b"some_duration"] + self, field_name: typing_extensions.Literal["some_duration", b"some_duration"] ) -> builtins.bool: ... def ClearField( - self, field_name: typing.Literal["some_duration", b"some_duration"] + self, field_name: typing_extensions.Literal["some_duration", b"some_duration"] ) -> None: ... -Global___SomeMessage: typing_extensions.TypeAlias = SomeMessage +global___SomeMessage = SomeMessage From f6594f1b79ad1522a17bb03b57570975f586651d Mon Sep 17 00:00:00 2001 From: Tim Conley Date: Thu, 30 Jul 2026 10:00:26 -0700 Subject: [PATCH 195/226] test: run integration suite against Cloud (#1687) * test: run integration suite against Cloud * test: scope Cloud integration coverage * test: fix remaining Cloud test failures * test: reenable Cloud start-delay coverage * test: scope replayer history test to local server * test: wait for schedule action cleanup * test: synchronize unfinished handler termination * test: buffer schedule completion result action * test: scope schedule completion result test to local server * test: scope unfinished handler test to local server --- .github/workflows/ci.yml | 17 ++-- temporalio/testing/_workflow.py | 21 ++++ tests/conftest.py | 40 +++++++- .../aws/s3driver/test_s3driver_worker.py | 43 +++++--- tests/contrib/langsmith/test_integration.py | 3 + tests/contrib/langsmith/test_plugin.py | 1 + .../langsmith/test_tracing_env_override.py | 1 + tests/contrib/openai_agents/test_openai.py | 1 + .../opentelemetry/test_opentelemetry.py | 1 + .../test_opentelemetry_plugin.py | 1 + .../workflow_streams/test_workflow_streams.py | 4 +- ...ynamic_creation_of_user_handler_classes.py | 2 + tests/nexus/test_nexus_client_updates.py | 7 +- tests/nexus/test_nexus_worker_shutdown.py | 2 + .../nexus/test_signal_link_propagation_e2e.py | 2 + tests/nexus/test_standalone_operations.py | 3 + tests/nexus/test_temporal_operation.py | 2 + .../test_use_existing_conflict_policy.py | 3 + tests/nexus/test_workflow_caller.py | 11 +-- ...test_workflow_caller_cancellation_types.py | 2 + ...llation_types_when_cancel_handler_fails.py | 2 + .../test_workflow_caller_error_chains.py | 2 + tests/nexus/test_workflow_caller_errors.py | 2 + tests/nexus/test_workflow_run_operation.py | 2 + tests/test_client.py | 98 +++++++------------ tests/test_cloud.py | 67 +------------ tests/test_envconfig.py | 84 ++++++++++++++++ tests/test_plugins.py | 1 + tests/test_runtime.py | 29 ++---- tests/test_serialization_context.py | 35 +++---- tests/test_service.py | 1 + tests/testing/test_workflow.py | 1 + tests/worker/test_extstore.py | 49 +++------- tests/worker/test_interceptor.py | 1 + tests/worker/test_payload_size_limits.py | 14 +-- tests/worker/test_replayer.py | 9 ++ tests/worker/test_update_with_start.py | 10 +- tests/worker/test_worker.py | 18 ++-- tests/worker/test_workflow.py | 34 ++++--- 39 files changed, 352 insertions(+), 274 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 49052107d..bcf42e8af 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -204,10 +204,10 @@ jobs: path: junit-xml retention-days: 14 - # Run tests against Temporal Cloud (skipped on forks) + # Run the test suite against Temporal Cloud (skipped on forks) cloud-test: if: ${{ github.event.pull_request.head.repo.full_name == '' || github.event.pull_request.head.repo.full_name == 'temporalio/sdk-python' }} - timeout-minutes: 15 + timeout-minutes: 30 runs-on: ubuntu-latest steps: - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 @@ -230,16 +230,19 @@ jobs: - run: uv tool install poethepoet - run: uv sync --all-extras - run: poe build-develop - - run: poe test -s tests/test_cloud.py --junit-xml=junit-xml/cloud.xml - timeout-minutes: 10 + - run: mkdir junit-xml + - run: poe test -s --workflow-environment envconfig --junit-xml=junit-xml/cloud.xml + timeout-minutes: 15 env: + TEMPORAL_ADDRESS: sdk-ci.a2dd6.tmprl.cloud:7233 + TEMPORAL_NAMESPACE: sdk-ci.a2dd6 + TEMPORAL_API_KEY: ${{ secrets.TEMPORAL_CLIENT_CLOUD_API_KEY }} + TEMPORAL_TLS_CLIENT_CERT_DATA: ${{ secrets.TEMPORAL_CLIENT_CERT }} + TEMPORAL_TLS_CLIENT_KEY_DATA: ${{ secrets.TEMPORAL_CLIENT_KEY }} TEMPORAL_IS_CLOUD_TESTS: true TEMPORAL_CLIENT_CLOUD_API_KEY: ${{ secrets.TEMPORAL_CLIENT_CLOUD_API_KEY }} TEMPORAL_CLIENT_CLOUD_API_VERSION: 2024-05-13-00 TEMPORAL_CLIENT_CLOUD_NAMESPACE: sdk-ci.a2dd6 - TEMPORAL_CLIENT_CLOUD_TARGET: sdk-ci.a2dd6.tmprl.cloud:7233 - TEMPORAL_CLIENT_CERT: ${{ secrets.TEMPORAL_CLIENT_CERT }} - TEMPORAL_CLIENT_KEY: ${{ secrets.TEMPORAL_CLIENT_KEY }} - name: "Upload junit-xml artifacts" uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4 if: always() diff --git a/temporalio/testing/_workflow.py b/temporalio/testing/_workflow.py index 979222dea..3ab07e5aa 100644 --- a/temporalio/testing/_workflow.py +++ b/temporalio/testing/_workflow.py @@ -373,6 +373,27 @@ def client(self) -> temporalio.client.Client: """Client to this environment.""" return self._client + async def connect_client(self, **kwargs: Any) -> temporalio.client.Client: + """Create another client connected to this environment. + + Namespace and connection credentials from this environment's client are + used by default. + Keyword arguments are forwarded to :py:meth:`temporalio.client.Client.connect` + and override those defaults. + """ + config = self.client.service_client.config + connect_kwargs: dict[str, Any] = { + "namespace": self.client.namespace, + "api_key": config.api_key, + "tls": config.tls, + "rpc_metadata": config.rpc_metadata, + "runtime": config.runtime or temporalio.runtime.Runtime.default(), + } + connect_kwargs.update(kwargs) + return await temporalio.client.Client.connect( + config.target_host, **connect_kwargs + ) + async def shutdown(self) -> None: """Shut down this environment.""" pass diff --git a/tests/conftest.py b/tests/conftest.py index bfe005ede..9c57bc0d1 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -10,6 +10,7 @@ from opentelemetry.util._once import Once from temporalio.client import Client +from temporalio.envconfig import ClientConfigProfile from temporalio.testing import WorkflowEnvironment from temporalio.worker import SharedStateManager from tests.helpers.worker import ExternalPythonWorker, ExternalWorker @@ -58,10 +59,43 @@ def pytest_addoption(parser): # type: ignore[reportMissingParameterType] "-E", "--workflow-environment", default="local", - help="Which workflow environment to use ('local', 'time-skipping', or ip:port for existing server)", + help="Which workflow environment to use ('local', 'time-skipping', 'envconfig', or ip:port for existing server)", ) +def _uses_envconfig_server(env_type: str) -> bool: + return env_type == "envconfig" + + +def pytest_configure(config: pytest.Config) -> None: + config.addinivalue_line( + "markers", + "requires_local_server: test requires local-server-only behavior and cannot run against an envconfig server", + ) + + +def pytest_collection_modifyitems( + config: pytest.Config, items: list[pytest.Item] +) -> None: + if not _uses_envconfig_server(config.getoption("--workflow-environment")): + return + skip_local_only = pytest.mark.skip( + reason="requires a local Temporal server, not the configured envconfig server" + ) + for item in items: + if item.get_closest_marker("requires_local_server"): + item.add_marker(skip_local_only) + + +async def _create_env_from_envconfig() -> WorkflowEnvironment: + config = ClientConfigProfile.load().to_client_connect_config() + if not config.get("target_host"): + raise ValueError( + "An envconfig workflow environment requires TEMPORAL_ADDRESS or an envconfig profile with an address" + ) + return WorkflowEnvironment.from_client(await Client.connect(**config)) + + @pytest.fixture(scope="session") def event_loop(): loop = asyncio.get_event_loop_policy().new_event_loop() # type: ignore[reportDeprecated] @@ -100,7 +134,9 @@ def env_type(request: pytest.FixtureRequest) -> str: @pytest_asyncio.fixture(scope="session") # type: ignore[reportUntypedFunctionDecorator] async def env(env_type: str) -> AsyncGenerator[WorkflowEnvironment, None]: - if env_type == "local": + if _uses_envconfig_server(env_type): + env = await _create_env_from_envconfig() + elif env_type == "local": env = await WorkflowEnvironment.start_local( dev_server_extra_args=[ "--dynamic-config-value", diff --git a/tests/contrib/aws/s3driver/test_s3driver_worker.py b/tests/contrib/aws/s3driver/test_s3driver_worker.py index 61729535f..fcf17fc16 100644 --- a/tests/contrib/aws/s3driver/test_s3driver_worker.py +++ b/tests/contrib/aws/s3driver/test_s3driver_worker.py @@ -62,9 +62,7 @@ async def tmprl_client( ) -> AsyncIterator[Client]: """Temporal client wired with ExternalStorage backed by the moto S3 server.""" driver = S3StorageDriver(client=new_aioboto3_client(aioboto3_client), bucket=BUCKET) - yield await Client.connect( - env.client.service_client.config.target_host, - namespace=env.client.namespace, + yield await env.connect_client( data_converter=dataclasses.replace( temporalio.converter.default(), external_storage=ExternalStorage( @@ -112,7 +110,8 @@ async def test_s3_driver_workflow_input_key( # worker stores activity input with ri=run_id — same bytes, two S3 objects. assert len(keys) == 2 assert all( - f"/ns/default/wt/LargeIOWorkflow/wi/{workflow_id}/ri/" in k for k in keys + f"/ns/{tmprl_client.namespace}/wt/LargeIOWorkflow/wi/{workflow_id}/ri/" in k + for k in keys ) # Client-side store: ri=null because run ID is not yet known. assert sum(1 for k in keys if "/ri/null/" in k) == 1 @@ -138,7 +137,10 @@ async def test_s3_driver_workflow_output_key( keys = await _list_keys(aioboto3_client) # Activity result and workflow result dedup to same key assert len(keys) == 1 - assert f"/ns/default/wt/LargeIOWorkflow/wi/{workflow_id}/ri/" in keys[0] + assert ( + f"/ns/{tmprl_client.namespace}/wt/LargeIOWorkflow/wi/{workflow_id}/ri/" + in keys[0] + ) # Run ID is known for both activity completion and workflow completion assert "/ri/null/" not in keys[0] @@ -162,7 +164,8 @@ async def test_s3_driver_workflow_activity_input_key( assert len(keys) == 2 # Both keys are under the workflow wi/ri prefix, not the activity. assert all( - f"/ns/default/wt/LargeIOWorkflow/wi/{workflow_id}/ri/" in k for k in keys + f"/ns/{tmprl_client.namespace}/wt/LargeIOWorkflow/wi/{workflow_id}/ri/" in k + for k in keys ) # Activity input is keyed under the scheduling workflow, not the activity. assert all("/ai/" not in k for k in keys) @@ -185,7 +188,10 @@ async def test_s3_driver_workflow_activity_output_key( keys = await _list_keys(aioboto3_client) # Activity result and workflow result are both LARGE so they deduplicate to one object. assert len(keys) == 1 - assert f"/ns/default/wt/LargeIOWorkflow/wi/{workflow_id}/ri/" in keys[0] + assert ( + f"/ns/{tmprl_client.namespace}/wt/LargeIOWorkflow/wi/{workflow_id}/ri/" + in keys[0] + ) # ri=run_id for both stores (run ID is known by the time the activity completes). assert "/ri/null/" not in keys[0] @@ -214,7 +220,8 @@ async def test_s3_driver_standalone_activity_input_key( assert len(keys) == 2 # Both keyed under the activity, not a workflow. assert all( - f"/ns/default/at/large_io_activity/ai/{activity_id}/ri/" in k for k in keys + f"/ns/{tmprl_client.namespace}/at/large_io_activity/ai/{activity_id}/ri/" in k + for k in keys ) assert all("/wt/" not in k for k in keys) # Client-side store does not have run ID information @@ -244,7 +251,10 @@ async def test_s3_driver_standalone_activity_output_key( keys = await _list_keys(aioboto3_client) # Only the output is large; keyed under the activity. assert len(keys) == 1 - assert f"/ns/default/at/large_output_activity/ai/{activity_id}/ri/" in keys[0] + assert ( + f"/ns/{tmprl_client.namespace}/at/large_output_activity/ai/{activity_id}/ri/" + in keys[0] + ) assert "/ri/null/" not in keys[0] assert "/wt/" not in keys[0] @@ -337,7 +347,10 @@ async def test_s3_driver_child_workflow_input_key( # Child input is the only large payload — stored under the child's wi/ri. assert len(keys) == 1 # Keyed under the child: child input is stored in the child's context. - assert f"/ns/default/wt/ChildWorkflow/wi/{child_workflow_id}/ri/" in keys[0] + assert ( + f"/ns/{tmprl_client.namespace}/wt/ChildWorkflow/wi/{child_workflow_id}/ri/" + in keys[0] + ) async def test_s3_driver_identified_casing( @@ -359,7 +372,8 @@ async def test_s3_driver_identified_casing( assert len(keys) == 2 # Workflow ID is percent-encoded but casing is preserved verbatim. assert all( - f"/ns/default/wt/LargeIOWorkflow/wi/{workflow_id}/ri/" in k for k in keys + f"/ns/{tmprl_client.namespace}/wt/LargeIOWorkflow/wi/{workflow_id}/ri/" in k + for k in keys ), "Workflow ID should preserve original case in the key" @@ -386,7 +400,8 @@ async def test_s3_driver_content_dedup( assert len(keys) == 2 # Both are under the same workflow wi/ri prefix despite crossing activity boundaries. assert all( - f"/ns/default/wt/DocumentIngestionWorkflow/wi/{workflow_id}/ri/" in k + f"/ns/{tmprl_client.namespace}/wt/DocumentIngestionWorkflow/wi/{workflow_id}/ri/" + in k for k in keys ) # The two keys differ by content hash only. @@ -469,9 +484,7 @@ async def test_s3_store_failure_surfaces_in_workflow_history( aws_secret_access_key="testing", ) as client: driver = S3StorageDriver(client=new_aioboto3_client(client), bucket=bad_bucket) - bad_client = await Client.connect( - env.client.service_client.config.target_host, - namespace=env.client.namespace, + bad_client = await env.connect_client( data_converter=dataclasses.replace( temporalio.converter.default(), external_storage=ExternalStorage( diff --git a/tests/contrib/langsmith/test_integration.py b/tests/contrib/langsmith/test_integration.py index a89d1ea4a..426b9a3af 100644 --- a/tests/contrib/langsmith/test_integration.py +++ b/tests/contrib/langsmith/test_integration.py @@ -572,6 +572,7 @@ async def test_benign_error_not_marked( class TestComprehensiveTracing: + @pytest.mark.requires_local_server async def test_comprehensive_with_temporal_runs( self, client: Client, env: WorkflowEnvironment ) -> None: @@ -765,6 +766,7 @@ async def user_pipeline() -> WorkflowHandle[Any, Any]: " HandleUpdate:my_unvalidated_update", ] + @pytest.mark.requires_local_server async def test_comprehensive_without_temporal_runs( self, client: Client, env: WorkflowEnvironment ) -> None: @@ -1138,6 +1140,7 @@ async def run(self) -> str: class TestNexusInboundTracing: """Verifies nexus handlers receive tracing_context for @traceable collection.""" + @pytest.mark.requires_local_server async def test_nexus_direct_traceable_without_temporal_runs( self, client: Client, diff --git a/tests/contrib/langsmith/test_plugin.py b/tests/contrib/langsmith/test_plugin.py index 17c21cb7c..0dad5566f 100644 --- a/tests/contrib/langsmith/test_plugin.py +++ b/tests/contrib/langsmith/test_plugin.py @@ -53,6 +53,7 @@ def test_construction_stores_all_config(self) -> None: class TestPluginIntegration: """End-to-end test using LangSmithPlugin as a Temporal client plugin.""" + @pytest.mark.requires_local_server async def test_comprehensive_plugin_trace_hierarchy( self, client: Client, env: WorkflowEnvironment ) -> None: diff --git a/tests/contrib/langsmith/test_tracing_env_override.py b/tests/contrib/langsmith/test_tracing_env_override.py index 9d871e1d3..c8aaa2fb0 100644 --- a/tests/contrib/langsmith/test_tracing_env_override.py +++ b/tests/contrib/langsmith/test_tracing_env_override.py @@ -162,6 +162,7 @@ async def test_no_runs_when_langchain_tracing_v2_disabled( f"{[r.name for r in collector.runs]}" ) + @pytest.mark.requires_local_server async def test_no_runs_when_tracing_disabled_for_nexus_start( self, client: Client, diff --git a/tests/contrib/openai_agents/test_openai.py b/tests/contrib/openai_agents/test_openai.py index 96cc25133..23c8939a5 100644 --- a/tests/contrib/openai_agents/test_openai.py +++ b/tests/contrib/openai_agents/test_openai.py @@ -471,6 +471,7 @@ async def test_tool_failure_workflow(client: Client): @pytest.mark.parametrize("use_local_model", [True, False]) +@pytest.mark.requires_local_server async def test_nexus_tool_workflow( client: Client, env: WorkflowEnvironment, use_local_model: bool ): diff --git a/tests/contrib/opentelemetry/test_opentelemetry.py b/tests/contrib/opentelemetry/test_opentelemetry.py index 71e2fa41d..1bab931ac 100644 --- a/tests/contrib/opentelemetry/test_opentelemetry.py +++ b/tests/contrib/opentelemetry/test_opentelemetry.py @@ -457,6 +457,7 @@ async def test_opentelemetry_tracing_update_with_start( ] +@pytest.mark.requires_local_server async def test_opentelemetry_tracing_nexus(client: Client, env: WorkflowEnvironment): if env.supports_time_skipping: pytest.skip( diff --git a/tests/contrib/opentelemetry/test_opentelemetry_plugin.py b/tests/contrib/opentelemetry/test_opentelemetry_plugin.py index 3fd50e89b..337270d0c 100644 --- a/tests/contrib/opentelemetry/test_opentelemetry_plugin.py +++ b/tests/contrib/opentelemetry/test_opentelemetry_plugin.py @@ -233,6 +233,7 @@ def validate_update_status(self, status: str) -> None: raise ValueError("Status cannot be empty") +@pytest.mark.requires_local_server async def test_opentelemetry_comprehensive_tracing( client: Client, env: WorkflowEnvironment, diff --git a/tests/contrib/workflow_streams/test_workflow_streams.py b/tests/contrib/workflow_streams/test_workflow_streams.py index 12026ff1a..e7cedd038 100644 --- a/tests/contrib/workflow_streams/test_workflow_streams.py +++ b/tests/contrib/workflow_streams/test_workflow_streams.py @@ -2699,6 +2699,7 @@ async def test_subscribe_iterates_through_more_ready(client: Client) -> None: @pytest.mark.asyncio +@pytest.mark.requires_local_server async def test_cross_namespace_nexus_stream( client: Client, env: WorkflowEnvironment ) -> None: @@ -2722,8 +2723,7 @@ async def test_cross_namespace_nexus_stream( ) ) - handler_client = await Client.connect( - client.service_client.config.target_host, + handler_client = await env.connect_client( namespace=handler_ns, ) diff --git a/tests/nexus/test_dynamic_creation_of_user_handler_classes.py b/tests/nexus/test_dynamic_creation_of_user_handler_classes.py index f7306a46b..22c1a818b 100644 --- a/tests/nexus/test_dynamic_creation_of_user_handler_classes.py +++ b/tests/nexus/test_dynamic_creation_of_user_handler_classes.py @@ -10,6 +10,8 @@ from temporalio.worker import Worker from tests.helpers.nexus import make_nexus_endpoint_name +pytestmark = pytest.mark.requires_local_server + @workflow.defn class MyWorkflow: diff --git a/tests/nexus/test_nexus_client_updates.py b/tests/nexus/test_nexus_client_updates.py index f63d5482c..c99822770 100644 --- a/tests/nexus/test_nexus_client_updates.py +++ b/tests/nexus/test_nexus_client_updates.py @@ -3,6 +3,7 @@ import uuid import nexusrpc +import pytest from nexusrpc.handler import StartOperationContext, service_handler, sync_operation import temporalio.nexus @@ -11,6 +12,8 @@ from temporalio.testing import WorkflowEnvironment from temporalio.worker import Worker +pytestmark = pytest.mark.requires_local_server + @nexusrpc.service class ClientTestService: @@ -48,9 +51,7 @@ async def test_nexus_client_updates_when_worker_client_changes( """Test that Nexus operations get the updated client when worker.client is changed.""" # Create a second client (simulating a new client after cert rotation) # Must use the same runtime - client2 = await Client.connect( - env.client.service_client.config.target_host, - namespace=env.client.namespace, + client2 = await env.connect_client( data_converter=env.client.data_converter, runtime=env.client.service_client.config.runtime, ) diff --git a/tests/nexus/test_nexus_worker_shutdown.py b/tests/nexus/test_nexus_worker_shutdown.py index bd9063237..45dfcb8ad 100644 --- a/tests/nexus/test_nexus_worker_shutdown.py +++ b/tests/nexus/test_nexus_worker_shutdown.py @@ -23,6 +23,8 @@ make_nexus_endpoint_name, ) +pytestmark = pytest.mark.requires_local_server + @nexusrpc.service class ShutdownTestService: diff --git a/tests/nexus/test_signal_link_propagation_e2e.py b/tests/nexus/test_signal_link_propagation_e2e.py index e489ad8a7..e7906f7a5 100644 --- a/tests/nexus/test_signal_link_propagation_e2e.py +++ b/tests/nexus/test_signal_link_propagation_e2e.py @@ -56,6 +56,8 @@ workflow_event_link_event_type, ) +pytestmark = pytest.mark.requires_local_server + EventType = temporalio.api.enums.v1.EventType diff --git a/tests/nexus/test_standalone_operations.py b/tests/nexus/test_standalone_operations.py index c71337b20..ed62c2387 100644 --- a/tests/nexus/test_standalone_operations.py +++ b/tests/nexus/test_standalone_operations.py @@ -71,6 +71,9 @@ # --------------------------------------------------------------------------- +pytestmark = pytest.mark.requires_local_server + + @dataclass class EchoInput: value: str diff --git a/tests/nexus/test_temporal_operation.py b/tests/nexus/test_temporal_operation.py index b6b1a92c7..0d1b7d63e 100644 --- a/tests/nexus/test_temporal_operation.py +++ b/tests/nexus/test_temporal_operation.py @@ -20,6 +20,8 @@ from tests.helpers import EventType, assert_event_subsequence, assert_eventually from tests.helpers.nexus import make_nexus_endpoint_name +pytestmark = pytest.mark.requires_local_server + @dataclass class Input: diff --git a/tests/nexus/test_use_existing_conflict_policy.py b/tests/nexus/test_use_existing_conflict_policy.py index e7cee9e1c..94a3821ba 100644 --- a/tests/nexus/test_use_existing_conflict_policy.py +++ b/tests/nexus/test_use_existing_conflict_policy.py @@ -4,6 +4,7 @@ import uuid from dataclasses import dataclass +import pytest from nexusrpc.handler import service_handler from temporalio import nexus, workflow @@ -13,6 +14,8 @@ from temporalio.worker import Worker from tests.helpers.nexus import make_nexus_endpoint_name +pytestmark = pytest.mark.requires_local_server + @dataclass class OpInput: diff --git a/tests/nexus/test_workflow_caller.py b/tests/nexus/test_workflow_caller.py index 89ce2719a..f776e6e18 100644 --- a/tests/nexus/test_workflow_caller.py +++ b/tests/nexus/test_workflow_caller.py @@ -90,6 +90,9 @@ class OpDefinitionType(IntEnum): LONGHAND = 1 +pytestmark = pytest.mark.requires_local_server + + @dataclass class SyncResponse: op_definition_type: OpDefinitionType @@ -1979,9 +1982,7 @@ async def test_workflow_caller_custom_metrics(client: Client, env: WorkflowEnvir ) # New client with the runtime - client = await Client.connect( - client.service_client.config.target_host, - namespace=client.namespace, + client = await env.connect_client( runtime=runtime, ) @@ -2052,9 +2053,7 @@ async def test_workflow_caller_buffered_metrics( assert not buffer.retrieve_updates() # Create a new client on the runtime and execute the custom metric workflow - client = await Client.connect( - client.service_client.config.target_host, - namespace=client.namespace, + client = await env.connect_client( runtime=runtime, ) task_queue = str(uuid.uuid4()) diff --git a/tests/nexus/test_workflow_caller_cancellation_types.py b/tests/nexus/test_workflow_caller_cancellation_types.py index bf33983a5..fa39009a5 100644 --- a/tests/nexus/test_workflow_caller_cancellation_types.py +++ b/tests/nexus/test_workflow_caller_cancellation_types.py @@ -25,6 +25,8 @@ from tests.helpers import LogCapturer, assert_event_subsequence, assert_eventually from tests.helpers.nexus import make_nexus_endpoint_name +pytestmark = pytest.mark.requires_local_server + @dataclass class TestContext: diff --git a/tests/nexus/test_workflow_caller_cancellation_types_when_cancel_handler_fails.py b/tests/nexus/test_workflow_caller_cancellation_types_when_cancel_handler_fails.py index 4cdeeeb15..5a0970c95 100644 --- a/tests/nexus/test_workflow_caller_cancellation_types_when_cancel_handler_fails.py +++ b/tests/nexus/test_workflow_caller_cancellation_types_when_cancel_handler_fails.py @@ -30,6 +30,8 @@ has_event, ) +pytestmark = pytest.mark.requires_local_server + @dataclass class TestContext: diff --git a/tests/nexus/test_workflow_caller_error_chains.py b/tests/nexus/test_workflow_caller_error_chains.py index 9ff84f405..18868288a 100644 --- a/tests/nexus/test_workflow_caller_error_chains.py +++ b/tests/nexus/test_workflow_caller_error_chains.py @@ -25,6 +25,8 @@ from temporalio.worker import Worker from tests.helpers.nexus import make_nexus_endpoint_name +pytestmark = pytest.mark.requires_local_server + @dataclass class ExpectedError: diff --git a/tests/nexus/test_workflow_caller_errors.py b/tests/nexus/test_workflow_caller_errors.py index 9246b9fd7..eb85155fe 100644 --- a/tests/nexus/test_workflow_caller_errors.py +++ b/tests/nexus/test_workflow_caller_errors.py @@ -42,6 +42,8 @@ from tests.helpers import LogCapturer, assert_eq_eventually from tests.helpers.nexus import make_nexus_endpoint_name +pytestmark = pytest.mark.requires_local_server + operation_invocation_counts = Counter[str]() logger = getLogger(__name__) diff --git a/tests/nexus/test_workflow_run_operation.py b/tests/nexus/test_workflow_run_operation.py index 851f408ec..51032a23a 100644 --- a/tests/nexus/test_workflow_run_operation.py +++ b/tests/nexus/test_workflow_run_operation.py @@ -23,6 +23,8 @@ from temporalio.worker import Worker from tests.helpers.nexus import make_nexus_endpoint_name +pytestmark = pytest.mark.requires_local_server + @dataclass class Input: diff --git a/tests/test_client.py b/tests/test_client.py index d611eda3a..15324cf78 100644 --- a/tests/test_client.py +++ b/tests/test_client.py @@ -556,7 +556,7 @@ async def test_interceptor(client: Client, worker: ExternalWorker): assert interceptor.traces[4][1].id == handle.id -async def test_lazy_client(client: Client, env: WorkflowEnvironment): +async def test_lazy_client(env: WorkflowEnvironment): # TODO(cretz): Fix if env.supports_time_skipping: pytest.skip( @@ -564,23 +564,17 @@ async def test_lazy_client(client: Client, env: WorkflowEnvironment): ) # Create another client that is lazy. This test just makes sure the # functionality continues to work. - lazy_client = await Client.connect( - client.service_client.config.target_host, - namespace=client.namespace, - lazy=True, - ) + lazy_client = await env.connect_client(lazy=True) assert not lazy_client.service_client.worker_service_client._bridge_client await lazy_client.workflow_service.get_system_info(GetSystemInfoRequest()) assert lazy_client.service_client.worker_service_client._bridge_client -async def test_client_connected_skips_connect_lock(client: Client): +async def test_client_connected_skips_connect_lock(env: WorkflowEnvironment): # Once connected, RPCs must not touch the lazy-connect lock. Acquiring it # per-RPC put an event-loop-bound primitive on the hot path, pinning a # connected client to the loop it connected on. - other = await Client.connect( - client.service_client.config.target_host, namespace=client.namespace - ) + other = await env.connect_client() svc = other.service_client.worker_service_client assert svc._bridge_client @@ -599,18 +593,13 @@ async def acquire(self) -> Literal[True]: assert counting.acquire_count == 0 -def test_client_reuse_across_event_loops(client: Client): +def test_client_reuse_across_event_loops(env: WorkflowEnvironment): # A connected client must not be pinned to the loop (or thread) it # connected on. This mirrors the long-lived-loop reuse pattern used by # gevent/gunicorn and synchronous services. - target_host = client.service_client.config.target_host - namespace = client.namespace - connect_loop = asyncio.new_event_loop() try: - reused_client = connect_loop.run_until_complete( - Client.connect(target_host, namespace=namespace) - ) + reused_client = connect_loop.run_until_complete(env.connect_client()) finally: connect_loop.close() @@ -668,21 +657,24 @@ async def test_list_workflows_and_fetch_history( ) expected_id_and_input.append((workflow_id, f'"user{i}"')) - # List them and get their history - actual_id_and_input = sorted( - [ - ( - hist.workflow_id, - hist.events[0] - .workflow_execution_started_event_attributes.input.payloads[0] - .data.decode(), - ) - async for hist in client.list_workflows( - f"WorkflowId = '{workflow_id}'" - ).map_histories() - ] - ) - assert actual_id_and_input == expected_id_and_input + # Visibility is eventually consistent, so wait for all runs before fetching + # their histories. + async def list_id_and_input() -> list[tuple[str, str]]: + return sorted( + [ + ( + hist.workflow_id, + hist.events[0] + .workflow_execution_started_event_attributes.input.payloads[0] + .data.decode(), + ) + async for hist in client.list_workflows( + f"WorkflowId = '{workflow_id}'" + ).map_histories() + ] + ) + + await assert_eq_eventually(expected_id_and_input, list_id_and_input) # Verify listing can limit results limited = [ @@ -837,6 +829,7 @@ def test_history_from_json(): ) +@pytest.mark.requires_local_server async def test_schedule_basics( client: Client, worker: ExternalWorker, env: WorkflowEnvironment ): @@ -844,8 +837,6 @@ async def test_schedule_basics( pytest.skip("Java test server doesn't support schedules") elif os.getenv("TEMPORAL_TEST_PROTO3"): pytest.skip("Older proto library cannot compare repeated fields") - await assert_no_schedules(client) - # Create a schedule with a lot of stuff schedule = Schedule( action=ScheduleActionStartWorkflow( @@ -1083,10 +1074,9 @@ async def list_ids() -> list[str]: assert list_descs[0].id in [f"{handle.id}-3", f"{handle.id}-4"] assert list_descs[1].id in [f"{handle.id}-3", f"{handle.id}-4"] - # Delete all of the schedules - for id in await list_ids(): + # Delete the schedules created by this test. + for id in expected_ids: await client.get_schedule_handle(id).delete() - await assert_no_schedules(client) async def test_schedule_calendar_spec_defaults( @@ -1094,8 +1084,6 @@ async def test_schedule_calendar_spec_defaults( ): if env.supports_time_skipping: pytest.skip("Java test server doesn't support schedules") - await assert_no_schedules(client) - handle = await client.create_schedule( f"schedule-{uuid.uuid4()}", Schedule( @@ -1124,7 +1112,6 @@ async def test_schedule_calendar_spec_defaults( assert time == desc.info.next_action_times[i - 1] + timedelta(days=1) await handle.delete() - await assert_no_schedules(client) async def test_schedule_trigger_immediately( @@ -1132,8 +1119,6 @@ async def test_schedule_trigger_immediately( ): if env.supports_time_skipping: pytest.skip("Java test server doesn't support schedules") - await assert_no_schedules(client) - # Create paused schedule that triggers immediately handle = await client.create_schedule( f"schedule-{uuid.uuid4()}", @@ -1165,7 +1150,6 @@ async def test_schedule_trigger_immediately( ) await handle.delete() - await assert_no_schedules(client) async def test_schedule_backfill( @@ -1173,8 +1157,6 @@ async def test_schedule_backfill( ): if env.supports_time_skipping: pytest.skip("Java test server doesn't support schedules") - await assert_no_schedules(client) - begin = datetime(year=2020, month=1, day=20, hour=5) # Create paused schedule that runs every minute and has two backfills @@ -1225,7 +1207,6 @@ async def test_schedule_backfill( ) finally: await handle.delete() - await assert_no_schedules(client) async def test_schedule_create_limited_actions_validation( @@ -1251,13 +1232,12 @@ async def test_schedule_create_limited_actions_validation( assert "are remaining actions set" in str(err.value) +@pytest.mark.requires_local_server async def test_schedule_workflow_search_attribute_update( client: Client, env: WorkflowEnvironment ): if env.supports_time_skipping: pytest.skip("Java test server doesn't support schedules") - await assert_no_schedules(client) - # Put search attribute on server text_attr_key = SearchAttributeKey.for_text("python-test-schedule-text") untyped_keyword_key = SearchAttributeKey.for_keyword("python-test-schedule-keyword") @@ -1350,7 +1330,6 @@ def update_schedule_typed_attrs( assert desc.typed_search_attributes[text_attr_key] == "some-schedule-attr1" await handle.delete() - await assert_no_schedules(client) @pytest.mark.parametrize( @@ -1362,13 +1341,12 @@ def update_schedule_typed_attrs( "partial-new-values-overwrites-and-drops", ], ) +@pytest.mark.requires_local_server async def test_schedule_search_attribute_update( client: Client, env: WorkflowEnvironment, test_case: str ): if env.supports_time_skipping: pytest.skip("Java test server doesn't support schedules") - await assert_no_schedules(client) - # Put search attributes on server key_1 = SearchAttributeKey.for_text("python-test-schedule-sa-update-key-1") key_2 = SearchAttributeKey.for_keyword("python-test-schedule-sa-update-key-2") @@ -1486,15 +1464,6 @@ async def expectation() -> bool: raise ValueError(f"Invalid test case: {test_case}") await handle.delete() - await assert_no_schedules(client) - - -async def assert_no_schedules(client: Client) -> None: - # Listing appears eventually consistent - async def schedule_count() -> int: - return len([d async for d in await client.list_schedules()]) - - await assert_eq_eventually(0, schedule_count) async def test_build_id_interactions(client: Client, env: WorkflowEnvironment): @@ -1556,6 +1525,9 @@ async def run(self) -> str: return "My First Result" +# Cloud does not reliably provide a prior completion result to manually +# triggered schedule actions. +@pytest.mark.requires_local_server async def test_schedule_last_completion_result( client: Client, env: WorkflowEnvironment ): @@ -1590,12 +1562,14 @@ async def get_schedule_result() -> tuple[int, str | None]: result = await workflow_handle.result() return length, result - assert await get_schedule_result() == (1, "My First Result") + expected_first_result: tuple[int, str | None] = (1, "My First Result") + await assert_eq_eventually(expected_first_result, get_schedule_result) await handle.trigger() - assert await get_schedule_result() == ( + expected_second_result: tuple[int, str | None] = ( 2, "From last completion: My First Result", ) + await assert_eq_eventually(expected_second_result, get_schedule_result) await handle.delete() diff --git a/tests/test_cloud.py b/tests/test_cloud.py index b701bdf94..d7fefb4da 100644 --- a/tests/test_cloud.py +++ b/tests/test_cloud.py @@ -1,18 +1,11 @@ -"""Tests that run against Temporal Cloud.""" +"""Tests that run against the Temporal Cloud Operations API.""" -import multiprocessing import os -from collections.abc import AsyncGenerator, Iterator import pytest -import pytest_asyncio from temporalio.api.cloud.cloudservice.v1 import GetNamespaceRequest -from temporalio.client import Client, CloudOperationsClient -from temporalio.service import TLSConfig -from temporalio.testing import WorkflowEnvironment -from temporalio.worker import SharedStateManager -from tests.helpers.worker import ExternalPythonWorker, ExternalWorker +from temporalio.client import CloudOperationsClient # Skip entire module unless explicitly enabled pytestmark = pytest.mark.skipif( @@ -21,54 +14,6 @@ ) -@pytest_asyncio.fixture(scope="module") # type: ignore[reportUntypedFunctionDecorator] -async def env() -> AsyncGenerator[WorkflowEnvironment, None]: - tls_config: bool | TLSConfig = True - client_cert = os.environ.get("TEMPORAL_CLIENT_CERT") - client_key = os.environ.get("TEMPORAL_CLIENT_KEY") - if client_cert and client_key: - tls_config = TLSConfig( - client_cert=client_cert.encode(), - client_private_key=client_key.encode(), - ) - client = await Client.connect( - os.environ["TEMPORAL_CLIENT_CLOUD_TARGET"], - namespace=os.environ["TEMPORAL_CLIENT_CLOUD_NAMESPACE"], - api_key=os.environ.get("TEMPORAL_CLIENT_CLOUD_API_KEY"), - tls=tls_config, - ) - env = WorkflowEnvironment.from_client(client) - yield env - await env.shutdown() - - -@pytest_asyncio.fixture # type: ignore[reportUntypedFunctionDecorator] -async def client(env: WorkflowEnvironment) -> Client: - return env.client - - -@pytest_asyncio.fixture(scope="module") # type: ignore[reportUntypedFunctionDecorator] -async def worker( - env: WorkflowEnvironment, -) -> AsyncGenerator[ExternalWorker, None]: - w = ExternalPythonWorker(env) - yield w - await w.close() - - -@pytest.fixture(scope="module") -def shared_state_manager() -> Iterator[SharedStateManager]: - mp_mgr = multiprocessing.Manager() - mgr = SharedStateManager.create_from_multiprocessing(mp_mgr) - try: - yield mgr - finally: - mp_mgr.shutdown() - - -# --- Cloud-specific tests --- - - async def test_cloud_client_simple(): client = await CloudOperationsClient.connect( api_key=os.environ["TEMPORAL_CLIENT_CLOUD_API_KEY"], @@ -78,11 +23,3 @@ async def test_cloud_client_simple(): GetNamespaceRequest(namespace=os.environ["TEMPORAL_CLIENT_CLOUD_NAMESPACE"]) ) assert os.environ["TEMPORAL_CLIENT_CLOUD_NAMESPACE"] == result.namespace.namespace - - -# --- Delegated tests --- -# Import test functions to re-run them against cloud fixtures. - -from tests.worker.test_activity import ( # noqa: E402 - test_activity_info, # pyright: ignore[reportUnusedImport] # noqa: F401 -) diff --git a/tests/test_envconfig.py b/tests/test_envconfig.py index c1a7e32ab..0b44db731 100644 --- a/tests/test_envconfig.py +++ b/tests/test_envconfig.py @@ -1,12 +1,20 @@ import os import textwrap from pathlib import Path +from types import SimpleNamespace +from unittest.mock import AsyncMock import pytest +import temporalio.runtime +import temporalio.service from temporalio.client import Client from temporalio.envconfig import ClientConfig, ClientConfigProfile, ClientConfigTLS from temporalio.service import TLSConfig +from temporalio.testing import WorkflowEnvironment +from tests import conftest + +pytestmark = pytest.mark.requires_local_server # A base TOML config with a default and a custom profile TOML_CONFIG_BASE = textwrap.dedent( @@ -147,6 +155,82 @@ def test_load_profile_from_data_env_overrides(): assert config.get("target_host") == "env-address" +@pytest.mark.parametrize( + ("env_type", "expected"), + [ + ("envconfig", True), + ("local", False), + ("time-skipping", False), + ], +) +def test_envconfig_server_selection( + env_type: str, + expected: bool, +): + assert conftest._uses_envconfig_server(env_type) is expected + + +async def test_envconfig_workflow_environment_uses_client_connect_config( + monkeypatch: pytest.MonkeyPatch, +): + monkeypatch.setenv("TEMPORAL_ADDRESS", "env-address") + monkeypatch.setenv("TEMPORAL_NAMESPACE", "env-namespace") + monkeypatch.setenv("TEMPORAL_API_KEY", "env-api-key") + monkeypatch.setenv("TEMPORAL_TLS", "false") + monkeypatch.setenv("TEMPORAL_GRPC_META_TEST_HEADER", "env-value") + client = object() + environment = object() + connect = AsyncMock(return_value=client) + monkeypatch.setattr(Client, "connect", connect) + monkeypatch.setattr( + WorkflowEnvironment, + "from_client", + lambda actual_client: environment, + ) + + assert await conftest._create_env_from_envconfig() is environment + connect.assert_awaited_once_with( + target_host="env-address", + namespace="env-namespace", + api_key="env-api-key", + tls=False, + rpc_metadata={"test-header": "env-value"}, + ) + + +async def test_workflow_environment_connect_client_inherits_connection_options( + monkeypatch: pytest.MonkeyPatch, +): + runtime = temporalio.runtime.Runtime.default() + source_client = SimpleNamespace( + namespace="env-namespace", + service_client=SimpleNamespace( + config=temporalio.service.ConnectConfig( + target_host="env-address", + api_key="env-api-key", + tls=False, + rpc_metadata={"test-header": "env-value"}, + runtime=runtime, + ) + ), + ) + environment = WorkflowEnvironment(source_client) # type: ignore[arg-type] + connect = AsyncMock(return_value=object()) + monkeypatch.setattr(Client, "connect", connect) + + await environment.connect_client(lazy=True) + + connect.assert_awaited_once_with( + "env-address", + namespace="env-namespace", + api_key="env-api-key", + tls=False, + rpc_metadata={"test-header": "env-value"}, + runtime=runtime, + lazy=True, + ) + + def test_load_profile_env_overrides(base_config_file: Path): """Test that environment variables correctly override file settings.""" env = { diff --git a/tests/test_plugins.py b/tests/test_plugins.py index e8823af27..9414e8df0 100644 --- a/tests/test_plugins.py +++ b/tests/test_plugins.py @@ -60,6 +60,7 @@ async def connect_service_client( return await next(config) +@pytest.mark.requires_local_server async def test_client_plugin(client: Client, env: WorkflowEnvironment): if env.supports_time_skipping: pytest.skip("Client connect is only designed for local") diff --git a/tests/test_runtime.py b/tests/test_runtime.py index 55501883d..6416ce930 100644 --- a/tests/test_runtime.py +++ b/tests/test_runtime.py @@ -21,6 +21,7 @@ TelemetryFilter, _RuntimeRef, ) +from temporalio.testing import WorkflowEnvironment from temporalio.worker import Worker from tests.helpers import ( LogHandler, @@ -37,22 +38,18 @@ async def run(self, name: str) -> str: return f"Hello, {name}!" -async def test_different_runtimes(client: Client): +async def test_different_runtimes(env: WorkflowEnvironment): # Create two workers in separate runtimes and run workflows on them. # Confirm they each have different Prometheus addresses. prom_addr1 = f"127.0.0.1:{find_free_port()}" - client1 = await Client.connect( - client.service_client.config.target_host, - namespace=client.namespace, + client1 = await env.connect_client( runtime=Runtime( telemetry=TelemetryConfig(metrics=PrometheusConfig(bind_address=prom_addr1)) ), ) prom_addr2 = f"127.0.0.1:{find_free_port()}" - client2 = await Client.connect( - client.service_client.config.target_host, - namespace=client.namespace, + client2 = await env.connect_client( runtime=Runtime( telemetry=TelemetryConfig(metrics=PrometheusConfig(bind_address=prom_addr2)) ), @@ -151,16 +148,14 @@ async def run(self) -> None: raise RuntimeError("Intentional error") -async def test_runtime_task_fail_log_forwarding(client: Client): +async def test_runtime_task_fail_log_forwarding(env: WorkflowEnvironment): # Client with lo capturing runtime log_queue: queue.Queue[logging.LogRecord] = queue.Queue() log_queue_list = cast(list[logging.LogRecord], log_queue.queue) handler = logging.handlers.QueueHandler(log_queue) logger = logging.getLogger(f"log-{uuid.uuid4()}") logger.setLevel(logging.WARN) - client = await Client.connect( - client.service_client.config.target_host, - namespace=client.namespace, + client = await env.connect_client( runtime=Runtime( telemetry=TelemetryConfig( logging=LoggingConfig( @@ -199,7 +194,7 @@ async def has_log() -> bool: assert record.temporal_log.fields["run_id"] == handle.result_run_id # type: ignore -async def test_prometheus_histogram_bucket_overrides(client: Client): +async def test_prometheus_histogram_bucket_overrides(env: WorkflowEnvironment): # Set up a Prometheus configuration with custom histogram bucket overrides prom_addr = f"127.0.0.1:{find_free_port()}" special_value = float(1234.5678) @@ -229,9 +224,7 @@ async def test_prometheus_histogram_bucket_overrides(client: Client): custom_histogram.record(600) # Create client with overrides - client_with_overrides = await Client.connect( - client.service_client.config.target_host, - namespace=client.namespace, + client_with_overrides = await env.connect_client( runtime=runtime, ) @@ -270,7 +263,7 @@ async def check_metrics() -> None: await assert_eventually(check_metrics) -async def test_opentelemetry_histogram_bucket_overrides(client: Client): +async def test_opentelemetry_histogram_bucket_overrides(env: WorkflowEnvironment): # Set up an OpenTelemetry configuration with custom histogram bucket overrides import threading from http.server import BaseHTTPRequestHandler, HTTPServer @@ -336,9 +329,7 @@ def do_POST(self): # Run a workflow so built-in histograms (e.g. temporal_long_request_latency) # are recorded and exported. - client_with_overrides = await Client.connect( - client.service_client.config.target_host, - namespace=client.namespace, + client_with_overrides = await env.connect_client( runtime=runtime, ) task_queue = f"task-queue-{uuid.uuid4()}" diff --git a/tests/test_serialization_context.py b/tests/test_serialization_context.py index 0fde2aa96..8d65d5f1f 100644 --- a/tests/test_serialization_context.py +++ b/tests/test_serialization_context.py @@ -217,19 +217,19 @@ async def test_payload_conversion_calls_follow_expected_sequence_and_contexts( workflow_context = dataclasses.asdict( WorkflowSerializationContext( - namespace="default", + namespace=client.namespace, workflow_id=workflow_id, ) ) child_workflow_context = dataclasses.asdict( WorkflowSerializationContext( - namespace="default", + namespace=client.namespace, workflow_id=f"{workflow_id}_child", ) ) activity_context = dataclasses.asdict( ActivitySerializationContext( - namespace="default", + namespace=client.namespace, workflow_id=workflow_id, workflow_type=PayloadConversionWorkflow.__name__, activity_type=passthrough_activity.__name__, @@ -363,14 +363,14 @@ async def test_heartbeat_details_payload_conversion(client: Client): workflow_context = dataclasses.asdict( WorkflowSerializationContext( - namespace="default", + namespace=client.namespace, workflow_id=workflow_id, ) ) activity_context = dataclasses.asdict( ActivitySerializationContext( - namespace="default", + namespace=client.namespace, workflow_id=workflow_id, workflow_type=HeartbeatDetailsSerializationContextTestWorkflow.__name__, activity_type=activity_with_heartbeat_details.__name__, @@ -455,13 +455,13 @@ async def test_local_activity_payload_conversion(client: Client): workflow_context = dataclasses.asdict( WorkflowSerializationContext( - namespace="default", + namespace=client.namespace, workflow_id=workflow_id, ) ) local_activity_context = dataclasses.asdict( ActivitySerializationContext( - namespace="default", + namespace=client.namespace, workflow_id=workflow_id, workflow_type=LocalActivityWorkflow.__name__, activity_type=local_activity.__name__, @@ -572,11 +572,11 @@ async def test_async_activity_completion_payload_conversion( workflow_runner=UnsandboxedWorkflowRunner(), # so that we can use isinstance ): workflow_context = WorkflowSerializationContext( - namespace="default", + namespace=client.namespace, workflow_id=workflow_id, ) activity_context = ActivitySerializationContext( - namespace="default", + namespace=client.namespace, workflow_id=workflow_id, workflow_type=AsyncActivityCompletionSerializationContextTestWorkflow.__name__, activity_type=async_activity.__name__, @@ -649,7 +649,7 @@ def my_method(self) -> None: def test_subclassed_async_activity_handle(client: Client): activity_context = ActivitySerializationContext( - namespace="default", + namespace=client.namespace, workflow_id="workflow-id", workflow_type="workflow-type", activity_type="activity-type", @@ -742,7 +742,7 @@ async def test_signal_payload_conversion( workflow_context = dataclasses.asdict( WorkflowSerializationContext( - namespace="default", + namespace=client.namespace, workflow_id=workflow_id, ) ) @@ -811,7 +811,7 @@ async def test_query_payload_conversion( workflow_context = dataclasses.asdict( WorkflowSerializationContext( - namespace="default", + namespace=client.namespace, workflow_id=workflow_id, ) ) @@ -909,7 +909,7 @@ async def test_update_payload_conversion( workflow_context = dataclasses.asdict( WorkflowSerializationContext( - namespace="default", + namespace=client.namespace, workflow_id=workflow_id, ) ) @@ -1016,13 +1016,13 @@ async def test_external_workflow_signal_and_cancel_payload_conversion( signaler_context = dataclasses.asdict( WorkflowSerializationContext( - namespace="default", + namespace=client.namespace, workflow_id=signaler_workflow_id, ) ) target_context = dataclasses.asdict( WorkflowSerializationContext( - namespace="default", + namespace=client.namespace, workflow_id=target_workflow_id, ) ) @@ -1157,13 +1157,13 @@ async def test_failure_converter_with_context(client: Client): workflow_context = dataclasses.asdict( WorkflowSerializationContext( - namespace="default", + namespace=client.namespace, workflow_id=workflow_id, ) ) activity_context = dataclasses.asdict( ActivitySerializationContext( - namespace="default", + namespace=client.namespace, workflow_id=workflow_id, workflow_type=FailureConverterTestWorkflow.__name__, activity_type=failing_activity.__name__, @@ -1731,6 +1731,7 @@ async def run(self, _data: str) -> None: ) +@pytest.mark.requires_local_server async def test_nexus_payload_codec_operations_lack_context( env: WorkflowEnvironment, ): diff --git a/tests/test_service.py b/tests/test_service.py index 0cf06fae0..954c87092 100644 --- a/tests/test_service.py +++ b/tests/test_service.py @@ -149,6 +149,7 @@ async def test_check_health(client: Client): assert err.value.status == temporalio.service.RPCStatusCode.NOT_FOUND +@pytest.mark.requires_local_server async def test_grpc_status(client: Client, env: WorkflowEnvironment): if env.supports_time_skipping: pytest.skip( diff --git a/tests/testing/test_workflow.py b/tests/testing/test_workflow.py index d5f2aae5c..b47d0ac05 100644 --- a/tests/testing/test_workflow.py +++ b/tests/testing/test_workflow.py @@ -252,6 +252,7 @@ def assert_proper_error(err: BaseException | None) -> None: assert_proper_error(err.value.cause) +@pytest.mark.requires_local_server async def test_search_attributes_on_dev_server( client: Client, env: WorkflowEnvironment ): diff --git a/tests/worker/test_extstore.py b/tests/worker/test_extstore.py index 998a2bd27..2f8fde5fe 100644 --- a/tests/worker/test_extstore.py +++ b/tests/worker/test_extstore.py @@ -181,9 +181,7 @@ async def test_extstore_activity_input_no_retrieve( WorkflowFailureError wrapping an ActivityError.""" driver = BadTestDriver(no_retrieve=True) - client = await Client.connect( - env.client.service_client.config.target_host, - namespace=env.client.namespace, + client = await env.connect_client( data_converter=dataclasses.replace( temporalio.converter.default(), external_storage=ExternalStorage( @@ -225,9 +223,7 @@ async def test_extstore_activity_result_no_store( terminates with a WorkflowFailureError wrapping an ActivityError.""" driver = BadTestDriver(no_store=True) - client = await Client.connect( - env.client.service_client.config.target_host, - namespace=env.client.namespace, + client = await env.connect_client( data_converter=dataclasses.replace( temporalio.converter.default(), external_storage=ExternalStorage( @@ -274,9 +270,7 @@ async def test_extstore_worker_missing_driver( """ driver = InMemoryTestDriver() - far_client = await Client.connect( - env.client.service_client.config.target_host, - namespace=env.client.namespace, + far_client = await env.connect_client( data_converter=dataclasses.replace( temporalio.converter.default(), external_storage=ExternalStorage( @@ -286,10 +280,7 @@ async def test_extstore_worker_missing_driver( ), ) - worker_client = await Client.connect( - env.client.service_client.config.target_host, - namespace=env.client.namespace, - ) + worker_client = await env.connect_client() async with new_worker( worker_client, ExtStoreWorkflow, activities=[ext_store_activity] @@ -315,9 +306,7 @@ async def test_extstore_payload_not_found_fails_workflow( """When a non-retryable ApplicationError is raised while retrieving workflow input, the workflow must fail terminally (not retry as a task failure). """ - client = await Client.connect( - env.client.service_client.config.target_host, - namespace=env.client.namespace, + client = await env.connect_client( data_converter=dataclasses.replace( temporalio.converter.default(), external_storage=ExternalStorage( @@ -363,9 +352,7 @@ async def _run_extstore_workflow_and_fetch_history( activity_output_size: int = 10, ) -> WorkflowHandle: """Helper: run ExtStoreWorkflow with the given driver and return its history handle.""" - extstore_client = await Client.connect( - env.client.service_client.config.target_host, - namespace=env.client.namespace, + extstore_client = await env.connect_client( data_converter=dataclasses.replace( temporalio.converter.default(), external_storage=ExternalStorage( @@ -515,9 +502,7 @@ async def test_extstore_chained_activities( """ driver = InMemoryTestDriver() - client = await Client.connect( - env.client.service_client.config.target_host, - namespace=env.client.namespace, + client = await env.connect_client( data_converter=dataclasses.replace( temporalio.converter.default(), external_storage=ExternalStorage( @@ -567,9 +552,7 @@ def __init__(self, driver_name: str): driver2 = InMemoryTestDriver(driver_name="driver2") driver3 = DifferentTestDriver(driver_name="driver3") - client = await Client.connect( - env.client.service_client.config.target_host, - namespace=env.client.namespace, + client = await env.connect_client( data_converter=dataclasses.replace( temporalio.converter.default(), external_storage=ExternalStorage( @@ -685,9 +668,7 @@ async def test_tmprl1104_with_extstore_download(env: WorkflowEnvironment) -> Non payload_size_threshold=512, ), ) - client = await Client.connect( - env.client.service_client.config.target_host, - namespace=env.client.namespace, + client = await env.connect_client( data_converter=data_converter, ) @@ -737,9 +718,7 @@ async def test_tmprl1104_with_extstore_upload(env: WorkflowEnvironment) -> None: payload_size_threshold=512, ), ) - client = await Client.connect( - env.client.service_client.config.target_host, - namespace=env.client.namespace, + client = await env.connect_client( data_converter=data_converter, ) @@ -791,9 +770,7 @@ async def test_tmprl1104_with_extstore_download_and_upload( payload_size_threshold=512, ), ) - client = await Client.connect( - env.client.service_client.config.target_host, - namespace=env.client.namespace, + client = await env.connect_client( data_converter=data_converter, ) @@ -914,9 +891,7 @@ async def _make_tracking_client( env: WorkflowEnvironment, ) -> tuple[Client, ContextTrackingStorageDriver]: driver = ContextTrackingStorageDriver() - client = await Client.connect( - env.client.service_client.config.target_host, - namespace=env.client.namespace, + client = await env.connect_client( data_converter=dataclasses.replace( temporalio.converter.default(), external_storage=ExternalStorage( diff --git a/tests/worker/test_interceptor.py b/tests/worker/test_interceptor.py index 431f8280d..4a1da399d 100644 --- a/tests/worker/test_interceptor.py +++ b/tests/worker/test_interceptor.py @@ -269,6 +269,7 @@ def update_validated_validator(self, param: str) -> None: raise ApplicationError("Invalid update") +@pytest.mark.requires_local_server async def test_worker_interceptor(client: Client, env: WorkflowEnvironment): # TODO(cretz): Fix if env.supports_time_skipping: diff --git a/tests/worker/test_payload_size_limits.py b/tests/worker/test_payload_size_limits.py index b527f429c..18cc7e75a 100644 --- a/tests/worker/test_payload_size_limits.py +++ b/tests/worker/test_payload_size_limits.py @@ -7,7 +7,7 @@ import temporalio.api.enums.v1 from temporalio import activity, workflow -from temporalio.client import Client, PayloadLimitsConfig, WorkflowFailureError +from temporalio.client import PayloadLimitsConfig, WorkflowFailureError from temporalio.exceptions import ( TerminatedError, TimeoutError, @@ -91,9 +91,7 @@ async def test_oversized_payload_fails_task_with_error_log(env: WorkflowEnvironm dev_server_download_version=DEV_SERVER_DOWNLOAD_VERSION, ) as env: worker_logger = logging.getLogger(f"log-{uuid.uuid4()}") - worker_client = await Client.connect( - env.client.service_client.config.target_host, - namespace=env.client.namespace, + worker_client = await env.connect_client( runtime=_forwarding_runtime(worker_logger), ) @@ -179,9 +177,7 @@ async def test_disable_payload_error_limit_sends_to_server(env: WorkflowEnvironm async def test_payload_size_warning_forwarded(env: WorkflowEnvironment): """The connection's warn threshold produces a forwarded [TMPRL1103] warning for over-threshold payloads.""" worker_logger = logging.getLogger(f"log-{uuid.uuid4()}") - worker_client = await Client.connect( - env.client.service_client.config.target_host, - namespace=env.client.namespace, + worker_client = await env.connect_client( runtime=_forwarding_runtime(worker_logger), payload_limits=PayloadLimitsConfig(payloads_warn_size=1024), ) @@ -219,9 +215,7 @@ async def test_memo_size_warning_forwarded(env: WorkflowEnvironment): """The connection's memo warn threshold produces a forwarded [TMPRL1103] warning for an over-threshold memo.""" worker_logger = logging.getLogger(f"log-{uuid.uuid4()}") - worker_client = await Client.connect( - env.client.service_client.config.target_host, - namespace=env.client.namespace, + worker_client = await env.connect_client( runtime=_forwarding_runtime(worker_logger), payload_limits=PayloadLimitsConfig(memo_warn_size=1024), ) diff --git a/tests/worker/test_replayer.py b/tests/worker/test_replayer.py index 137b32c3e..52fed7416 100644 --- a/tests/worker/test_replayer.py +++ b/tests/worker/test_replayer.py @@ -302,6 +302,7 @@ async def test_replayer_workflow_not_registered(client: Client) -> None: assert "SayHelloWorkflow is not registered" in str(err.value) +@pytest.mark.requires_local_server async def test_replayer_multiple_from_client( client: Client, env: WorkflowEnvironment ) -> None: @@ -330,6 +331,14 @@ async def test_replayer_multiple_from_client( ) await handle.result() + async def visible_run_ids() -> set[str]: + return { + workflow.run_id + async for workflow in client.list_workflows(f"WorkflowId = '{workflow_id}'") + } + + await assert_eq_eventually(set(expected_runs_and_non_det), visible_run_ids) + # Run replayer with list iterator mapped to histories and collect results async with Replayer(workflows=[SayHelloWorkflow]).workflow_replay_iterator( client.list_workflows(f"WorkflowId = '{workflow_id}'").map_histories() diff --git a/tests/worker/test_update_with_start.py b/tests/worker/test_update_with_start.py index 2ceb5e91b..0b3368725 100644 --- a/tests/worker/test_update_with_start.py +++ b/tests/worker/test_update_with_start.py @@ -192,6 +192,7 @@ async def _do_test( id_conflict_policy: WorkflowIDConflictPolicy, expect_error_when_workflow_exists: ExpectErrorWhenWorkflowExists, ): + workflow_id = f"{workflow_id}-{uuid.uuid4()}" await self._do_execute_update_test( client, workflow_id + "-execute-update", @@ -336,6 +337,7 @@ async def test_update_with_start_sets_first_execution_run_id( WorkflowForUpdateWithStartTest, activities=[activity_called_by_update], ) as worker: + workflow_id_prefix = f"wid-{uuid.uuid4()}" def make_start_op(workflow_id: str): return WithStartWorkflowOperation( @@ -348,7 +350,7 @@ def make_start_op(workflow_id: str): # conflict policy is FAIL # First UWS succeeds and sets the first execution run ID - start_op_1 = make_start_op("wid-1") + start_op_1 = make_start_op(f"{workflow_id_prefix}-1") update_handle_1 = await client.start_update_with_start_workflow( WorkflowForUpdateWithStartTest.my_non_blocking_update, "1", @@ -360,7 +362,7 @@ def make_start_op(workflow_id: str): # Second UWS start fails because the workflow already exists # first execution run ID is not set on the second UWS handle - start_op_2 = make_start_op("wid-1") + start_op_2 = make_start_op(f"{workflow_id_prefix}-1") for aw in [ client.start_update_with_start_workflow( @@ -375,7 +377,7 @@ def make_start_op(workflow_id: str): await aw # Third UWS start succeeds, but the update fails after acceptance - start_op_3 = make_start_op("wid-2") + start_op_3 = make_start_op(f"{workflow_id_prefix}-2") update_handle_3 = await client.start_update_with_start_workflow( WorkflowForUpdateWithStartTest.my_non_blocking_update, "fail-after-acceptance", @@ -394,7 +396,7 @@ def make_start_op(workflow_id: str): assert await wf_handle_3.result() == "workflow-result-0" # Fourth UWS is same as third, but we use execute_update instead of start_update. - start_op_4 = make_start_op("wid-3") + start_op_4 = make_start_op(f"{workflow_id_prefix}-3") with pytest.raises(WorkflowUpdateFailedError): await client.execute_update_with_start_workflow( WorkflowForUpdateWithStartTest.my_non_blocking_update, diff --git a/tests/worker/test_worker.py b/tests/worker/test_worker.py index 3a4e9165b..b6ce37c8b 100644 --- a/tests/worker/test_worker.py +++ b/tests/worker/test_worker.py @@ -399,6 +399,7 @@ def my_signal(self, value: str) -> None: workflow.logger.info(f"Signal: {value}") +@pytest.mark.requires_local_server async def test_custom_slot_supplier(client: Client, env: WorkflowEnvironment): if env.supports_time_skipping: pytest.skip("Nexus tests don't work under Java test server") @@ -1206,7 +1207,9 @@ async def test_workflows_can_use_versioning_override( ) -async def test_can_run_autoscaling_polling_worker(client: Client): +async def test_can_run_autoscaling_polling_worker( + client: Client, env: WorkflowEnvironment +): # Create new runtime with Prom server prom_addr = f"127.0.0.1:{find_free_port()}" runtime = Runtime( @@ -1214,9 +1217,7 @@ async def test_can_run_autoscaling_polling_worker(client: Client): metrics=PrometheusConfig(bind_address=prom_addr), ) ) - client = await Client.connect( - client.service_client.config.target_host, - namespace=client.namespace, + client = await env.connect_client( runtime=runtime, ) @@ -1467,15 +1468,14 @@ def test_fork_use_worker( self.run(mp_fork_ctx) -async def test_activity_client_updates_when_worker_client_changes(client: Client): +async def test_activity_client_updates_when_worker_client_changes( + client: Client, env: WorkflowEnvironment +): """Test that activities get the updated client when worker.client is changed.""" # Create a second client (simulating a new client after cert rotation) # Must use the same runtime - client2 = await Client.connect( - client.service_client.config.target_host, - namespace=client.namespace, + client2 = await env.connect_client( data_converter=client.data_converter, - runtime=client.service_client.config.runtime, ) captured_clients: list[Client] = [] diff --git a/tests/worker/test_workflow.py b/tests/worker/test_workflow.py index 9c742d5c6..5bb2b13e1 100644 --- a/tests/worker/test_workflow.py +++ b/tests/worker/test_workflow.py @@ -308,6 +308,7 @@ def get_history_info(self) -> HistoryInfo: ) +@pytest.mark.requires_local_server async def test_workflow_history_info( client: Client, env: WorkflowEnvironment, continue_as_new_suggest_history_count: int ): @@ -2352,6 +2353,7 @@ def do_search_attribute_update_typed(self) -> None: ) +@pytest.mark.requires_local_server async def test_workflow_search_attributes(client: Client, env_type: str): if env_type != "local": pytest.skip("Only testing search attributes on local which disables cache") @@ -2537,6 +2539,7 @@ async def run(self) -> None: # All we need to do is complete +@pytest.mark.requires_local_server async def test_workflow_no_initial_search_attributes(client: Client, env_type: str): if env_type != "local": pytest.skip("Only testing search attributes on local which disables cache") @@ -4957,7 +4960,7 @@ async def run(self) -> None: ) -async def test_workflow_custom_metrics(client: Client): +async def test_workflow_custom_metrics(client: Client, env: WorkflowEnvironment): # Run worker with default runtime which is noop meter just to confirm it # doesn't fail async with new_worker( @@ -4983,9 +4986,7 @@ async def test_workflow_custom_metrics(client: Client): assert str(err.value).startswith("Invalid value type for key") # New client with the runtime - client = await Client.connect( - client.service_client.config.target_host, - namespace=client.namespace, + client = await env.connect_client( runtime=runtime, ) @@ -5062,7 +5063,7 @@ async def test_workflow_custom_metrics(client: Client): ) -async def test_workflow_buffered_metrics(client: Client): +async def test_workflow_buffered_metrics(client: Client, env: WorkflowEnvironment): # Create runtime with metric buffer buffer = MetricBuffer(10000) runtime = Runtime( @@ -5123,9 +5124,7 @@ async def test_workflow_buffered_metrics(client: Client): assert runtime_updates2[1].value == 400 # Create a new client on the runtime and execute the custom metric workflow - client = await Client.connect( - client.service_client.config.target_host, - namespace=client.namespace, + client = await env.connect_client( runtime=runtime, ) async with new_worker( @@ -5186,12 +5185,10 @@ async def test_workflow_buffered_metrics(client: Client): ) -async def test_workflow_metrics_other_types(client: Client): +async def test_workflow_metrics_other_types(env: WorkflowEnvironment): async def do_stuff(buffer: MetricBuffer) -> None: runtime = Runtime(telemetry=TelemetryConfig(metrics=buffer)) - new_client = await Client.connect( - client.service_client.config.target_host, - namespace=client.namespace, + new_client = await env.connect_client( runtime=runtime, ) async with new_worker(new_client, HelloWorkflow) as worker: @@ -6211,6 +6208,7 @@ async def run(self) -> None: await asyncio.sleep(0.1) +@pytest.mark.requires_local_server async def test_workflow_replace_worker_client(client: Client, env: WorkflowEnvironment): if env.supports_time_skipping: pytest.skip("Only testing against two real servers") @@ -6266,11 +6264,11 @@ async def any_task_completed(handle: WorkflowHandle) -> bool: await handle2.terminate() -async def test_workflow_replace_worker_client_diff_runtimes_fail(client: Client): +async def test_workflow_replace_worker_client_diff_runtimes_fail( + client: Client, env: WorkflowEnvironment +): other_runtime = Runtime(telemetry=TelemetryConfig()) - other_client = await Client.connect( - client.service_client.config.target_host, - namespace=client.namespace, + other_client = await env.connect_client( runtime=other_runtime, ) async with new_worker(client, HelloWorkflow) as worker: @@ -6711,6 +6709,9 @@ async def my_dynamic_signal(self, _name: str, _args: Sequence[RawValue]) -> None await workflow.wait_condition(lambda: self.handlers_may_finish) +# Cloud cancels in-flight dynamic handlers before SDK teardown can emit the +# unfinished-handler warning this test asserts. +@pytest.mark.requires_local_server @pytest.mark.parametrize("handler_type", ["-signal-", "-update-"]) @pytest.mark.parametrize( "handler_registration", ["-late-registered-", "-not-late-registered-"] @@ -9404,6 +9405,7 @@ async def run(self, name: str) -> str: return f"Hello from child, {name}" +@pytest.mark.requires_local_server async def test_search_attribute_codec(client: Client, env_type: str): if env_type != "local": pytest.skip("Only testing search attributes on local which disables cache") From 245847db474a90dbbd969821851cb5bd6ecfc960 Mon Sep 17 00:00:00 2001 From: Justin Anderson <44687433+jmaeagle99@users.noreply.github.com> Date: Thu, 30 Jul 2026 10:41:21 -0700 Subject: [PATCH 196/226] refactor: move workflow task duration logging to core (#1698) --- temporalio/bridge/proto/common/__init__.py | 2 + temporalio/bridge/proto/common/common_pb2.py | 20 +- temporalio/bridge/proto/common/common_pb2.pyi | 53 ++++++ .../workflow_completion_pb2.py | 12 +- .../workflow_completion_pb2.pyi | 36 +++- temporalio/bridge/sdk-core | 2 +- temporalio/worker/_workflow.py | 105 +++-------- tests/worker/test_extstore.py | 174 ++++++++---------- 8 files changed, 218 insertions(+), 186 deletions(-) diff --git a/temporalio/bridge/proto/common/__init__.py b/temporalio/bridge/proto/common/__init__.py index 5622fffb8..a8506090d 100644 --- a/temporalio/bridge/proto/common/__init__.py +++ b/temporalio/bridge/proto/common/__init__.py @@ -1,10 +1,12 @@ from .common_pb2 import ( + ExternalStorageMetrics, NamespacedWorkflowExecution, VersioningIntent, WorkerDeploymentVersion, ) __all__ = [ + "ExternalStorageMetrics", "NamespacedWorkflowExecution", "VersioningIntent", "WorkerDeploymentVersion", diff --git a/temporalio/bridge/proto/common/common_pb2.py b/temporalio/bridge/proto/common/common_pb2.py index c56456fce..481cf216d 100644 --- a/temporalio/bridge/proto/common/common_pb2.py +++ b/temporalio/bridge/proto/common/common_pb2.py @@ -18,7 +18,7 @@ from google.protobuf import duration_pb2 as google_dot_protobuf_dot_duration__pb2 DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile( - b'\n%temporal/sdk/core/common/common.proto\x12\x0e\x63oresdk.common\x1a\x1egoogle/protobuf/duration.proto"U\n\x1bNamespacedWorkflowExecution\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t"D\n\x17WorkerDeploymentVersion\x12\x17\n\x0f\x64\x65ployment_name\x18\x01 \x01(\t\x12\x10\n\x08\x62uild_id\x18\x02 \x01(\t*@\n\x10VersioningIntent\x12\x0f\n\x0bUNSPECIFIED\x10\x00\x12\x0e\n\nCOMPATIBLE\x10\x01\x12\x0b\n\x07\x44\x45\x46\x41ULT\x10\x02\x42,\xea\x02)Temporalio::Internal::Bridge::Api::Commonb\x06proto3' + b'\n%temporal/sdk/core/common/common.proto\x12\x0e\x63oresdk.common\x1a\x1egoogle/protobuf/duration.proto"U\n\x1bNamespacedWorkflowExecution\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t"D\n\x17WorkerDeploymentVersion\x12\x17\n\x0f\x64\x65ployment_name\x18\x01 \x01(\t\x12\x10\n\x08\x62uild_id\x18\x02 \x01(\t"\x92\x01\n\x16\x45xternalStorageMetrics\x12\x15\n\rpayload_count\x18\x01 \x01(\x04\x12\x18\n\x10total_size_bytes\x18\x02 \x01(\x04\x12\x31\n\x0etotal_duration\x18\x03 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x14\n\x0c\x64river_names\x18\x04 \x03(\t*@\n\x10VersioningIntent\x12\x0f\n\x0bUNSPECIFIED\x10\x00\x12\x0e\n\nCOMPATIBLE\x10\x01\x12\x0b\n\x07\x44\x45\x46\x41ULT\x10\x02\x42,\xea\x02)Temporalio::Internal::Bridge::Api::Commonb\x06proto3' ) _VERSIONINGINTENT = DESCRIPTOR.enum_types_by_name["VersioningIntent"] @@ -32,6 +32,7 @@ "NamespacedWorkflowExecution" ] _WORKERDEPLOYMENTVERSION = DESCRIPTOR.message_types_by_name["WorkerDeploymentVersion"] +_EXTERNALSTORAGEMETRICS = DESCRIPTOR.message_types_by_name["ExternalStorageMetrics"] NamespacedWorkflowExecution = _reflection.GeneratedProtocolMessageType( "NamespacedWorkflowExecution", (_message.Message,), @@ -54,15 +55,28 @@ ) _sym_db.RegisterMessage(WorkerDeploymentVersion) +ExternalStorageMetrics = _reflection.GeneratedProtocolMessageType( + "ExternalStorageMetrics", + (_message.Message,), + { + "DESCRIPTOR": _EXTERNALSTORAGEMETRICS, + "__module__": "temporal.sdk.core.common.common_pb2", + # @@protoc_insertion_point(class_scope:coresdk.common.ExternalStorageMetrics) + }, +) +_sym_db.RegisterMessage(ExternalStorageMetrics) + if _descriptor._USE_C_DESCRIPTORS == False: DESCRIPTOR._options = None DESCRIPTOR._serialized_options = ( b"\352\002)Temporalio::Internal::Bridge::Api::Common" ) - _VERSIONINGINTENT._serialized_start = 246 - _VERSIONINGINTENT._serialized_end = 310 + _VERSIONINGINTENT._serialized_start = 395 + _VERSIONINGINTENT._serialized_end = 459 _NAMESPACEDWORKFLOWEXECUTION._serialized_start = 89 _NAMESPACEDWORKFLOWEXECUTION._serialized_end = 174 _WORKERDEPLOYMENTVERSION._serialized_start = 176 _WORKERDEPLOYMENTVERSION._serialized_end = 244 + _EXTERNALSTORAGEMETRICS._serialized_start = 247 + _EXTERNALSTORAGEMETRICS._serialized_end = 393 # @@protoc_insertion_point(module_scope) diff --git a/temporalio/bridge/proto/common/common_pb2.pyi b/temporalio/bridge/proto/common/common_pb2.pyi index 739a129e1..8862fa036 100644 --- a/temporalio/bridge/proto/common/common_pb2.pyi +++ b/temporalio/bridge/proto/common/common_pb2.pyi @@ -4,10 +4,13 @@ isort:skip_file """ import builtins +import collections.abc import sys import typing import google.protobuf.descriptor +import google.protobuf.duration_pb2 +import google.protobuf.internal.containers import google.protobuf.internal.enum_type_wrapper import google.protobuf.message @@ -121,3 +124,53 @@ class WorkerDeploymentVersion(google.protobuf.message.Message): ) -> None: ... global___WorkerDeploymentVersion = WorkerDeploymentVersion + +class ExternalStorageMetrics(google.protobuf.message.Message): + """Metrics for a set of external payload storage operations (all uploads and downloads) + performed while processing a task, so core can emit unified logging and metrics. + """ + + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + PAYLOAD_COUNT_FIELD_NUMBER: builtins.int + TOTAL_SIZE_BYTES_FIELD_NUMBER: builtins.int + TOTAL_DURATION_FIELD_NUMBER: builtins.int + DRIVER_NAMES_FIELD_NUMBER: builtins.int + payload_count: builtins.int + """Number of payloads stored or retrieved externally.""" + total_size_bytes: builtins.int + """Total size in bytes of the externally stored or retrieved payloads.""" + @property + def total_duration(self) -> google.protobuf.duration_pb2.Duration: + """Wall-clock time spent on the external storage operations.""" + @property + def driver_names( + self, + ) -> google.protobuf.internal.containers.RepeatedScalarFieldContainer[builtins.str]: + """Names of the drivers that participated in the operations.""" + def __init__( + self, + *, + payload_count: builtins.int = ..., + total_size_bytes: builtins.int = ..., + total_duration: google.protobuf.duration_pb2.Duration | None = ..., + driver_names: collections.abc.Iterable[builtins.str] | None = ..., + ) -> None: ... + def HasField( + self, field_name: typing_extensions.Literal["total_duration", b"total_duration"] + ) -> builtins.bool: ... + def ClearField( + self, + field_name: typing_extensions.Literal[ + "driver_names", + b"driver_names", + "payload_count", + b"payload_count", + "total_duration", + b"total_duration", + "total_size_bytes", + b"total_size_bytes", + ], + ) -> None: ... + +global___ExternalStorageMetrics = ExternalStorageMetrics diff --git a/temporalio/bridge/proto/workflow_completion/workflow_completion_pb2.py b/temporalio/bridge/proto/workflow_completion/workflow_completion_pb2.py index ce26b220d..057b301e4 100644 --- a/temporalio/bridge/proto/workflow_completion/workflow_completion_pb2.py +++ b/temporalio/bridge/proto/workflow_completion/workflow_completion_pb2.py @@ -31,7 +31,7 @@ ) DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile( - b'\n?temporal/sdk/core/workflow_completion/workflow_completion.proto\x12\x1b\x63oresdk.workflow_completion\x1a%temporal/api/failure/v1/message.proto\x1a(temporal/api/enums/v1/failed_cause.proto\x1a$temporal/api/enums/v1/workflow.proto\x1a%temporal/sdk/core/common/common.proto\x1a;temporal/sdk/core/workflow_commands/workflow_commands.proto"\xac\x01\n\x1cWorkflowActivationCompletion\x12\x0e\n\x06run_id\x18\x01 \x01(\t\x12:\n\nsuccessful\x18\x02 \x01(\x0b\x32$.coresdk.workflow_completion.SuccessH\x00\x12\x36\n\x06\x66\x61iled\x18\x03 \x01(\x0b\x32$.coresdk.workflow_completion.FailureH\x00\x42\x08\n\x06status"\xac\x01\n\x07Success\x12<\n\x08\x63ommands\x18\x01 \x03(\x0b\x32*.coresdk.workflow_commands.WorkflowCommand\x12\x1b\n\x13used_internal_flags\x18\x06 \x03(\r\x12\x46\n\x13versioning_behavior\x18\x07 \x01(\x0e\x32).temporal.api.enums.v1.VersioningBehavior"\x81\x01\n\x07\x46\x61ilure\x12\x31\n\x07\x66\x61ilure\x18\x01 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12\x43\n\x0b\x66orce_cause\x18\x02 \x01(\x0e\x32..temporal.api.enums.v1.WorkflowTaskFailedCauseB8\xea\x02\x35Temporalio::Internal::Bridge::Api::WorkflowCompletionb\x06proto3' + b'\n?temporal/sdk/core/workflow_completion/workflow_completion.proto\x12\x1b\x63oresdk.workflow_completion\x1a%temporal/api/failure/v1/message.proto\x1a(temporal/api/enums/v1/failed_cause.proto\x1a$temporal/api/enums/v1/workflow.proto\x1a%temporal/sdk/core/common/common.proto\x1a;temporal/sdk/core/workflow_commands/workflow_commands.proto"\xbe\x02\n\x1cWorkflowActivationCompletion\x12\x0e\n\x06run_id\x18\x01 \x01(\t\x12:\n\nsuccessful\x18\x02 \x01(\x0b\x32$.coresdk.workflow_completion.SuccessH\x00\x12\x36\n\x06\x66\x61iled\x18\x03 \x01(\x0b\x32$.coresdk.workflow_completion.FailureH\x00\x12H\n\x18payload_download_metrics\x18\x04 \x01(\x0b\x32&.coresdk.common.ExternalStorageMetrics\x12\x46\n\x16payload_upload_metrics\x18\x05 \x01(\x0b\x32&.coresdk.common.ExternalStorageMetricsB\x08\n\x06status"\xac\x01\n\x07Success\x12<\n\x08\x63ommands\x18\x01 \x03(\x0b\x32*.coresdk.workflow_commands.WorkflowCommand\x12\x1b\n\x13used_internal_flags\x18\x06 \x03(\r\x12\x46\n\x13versioning_behavior\x18\x07 \x01(\x0e\x32).temporal.api.enums.v1.VersioningBehavior"\x81\x01\n\x07\x46\x61ilure\x12\x31\n\x07\x66\x61ilure\x18\x01 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12\x43\n\x0b\x66orce_cause\x18\x02 \x01(\x0e\x32..temporal.api.enums.v1.WorkflowTaskFailedCauseB8\xea\x02\x35Temporalio::Internal::Bridge::Api::WorkflowCompletionb\x06proto3' ) @@ -79,9 +79,9 @@ b"\352\0025Temporalio::Internal::Bridge::Api::WorkflowCompletion" ) _WORKFLOWACTIVATIONCOMPLETION._serialized_start = 316 - _WORKFLOWACTIVATIONCOMPLETION._serialized_end = 488 - _SUCCESS._serialized_start = 491 - _SUCCESS._serialized_end = 663 - _FAILURE._serialized_start = 666 - _FAILURE._serialized_end = 795 + _WORKFLOWACTIVATIONCOMPLETION._serialized_end = 634 + _SUCCESS._serialized_start = 637 + _SUCCESS._serialized_end = 809 + _FAILURE._serialized_start = 812 + _FAILURE._serialized_end = 941 # @@protoc_insertion_point(module_scope) diff --git a/temporalio/bridge/proto/workflow_completion/workflow_completion_pb2.pyi b/temporalio/bridge/proto/workflow_completion/workflow_completion_pb2.pyi index 5b438f360..8e12736aa 100644 --- a/temporalio/bridge/proto/workflow_completion/workflow_completion_pb2.pyi +++ b/temporalio/bridge/proto/workflow_completion/workflow_completion_pb2.pyi @@ -14,6 +14,7 @@ import google.protobuf.message import temporalio.api.enums.v1.failed_cause_pb2 import temporalio.api.enums.v1.workflow_pb2 import temporalio.api.failure.v1.message_pb2 +import temporalio.bridge.proto.common.common_pb2 import temporalio.bridge.proto.workflow_commands.workflow_commands_pb2 if sys.version_info >= (3, 8): @@ -31,23 +32,52 @@ class WorkflowActivationCompletion(google.protobuf.message.Message): RUN_ID_FIELD_NUMBER: builtins.int SUCCESSFUL_FIELD_NUMBER: builtins.int FAILED_FIELD_NUMBER: builtins.int + PAYLOAD_DOWNLOAD_METRICS_FIELD_NUMBER: builtins.int + PAYLOAD_UPLOAD_METRICS_FIELD_NUMBER: builtins.int run_id: builtins.str """The run id from the workflow activation you are completing""" @property def successful(self) -> global___Success: ... @property def failed(self) -> global___Failure: ... + @property + def payload_download_metrics( + self, + ) -> temporalio.bridge.proto.common.common_pb2.ExternalStorageMetrics: + """Metrics for external payload storage downloads (retrievals) performed while processing + this activation. Only set when external storage retrieved payloads. + """ + @property + def payload_upload_metrics( + self, + ) -> temporalio.bridge.proto.common.common_pb2.ExternalStorageMetrics: + """Metrics for external payload storage uploads (stores) performed while processing this + activation. Only set when external storage stored payloads. + """ def __init__( self, *, run_id: builtins.str = ..., successful: global___Success | None = ..., failed: global___Failure | None = ..., + payload_download_metrics: temporalio.bridge.proto.common.common_pb2.ExternalStorageMetrics + | None = ..., + payload_upload_metrics: temporalio.bridge.proto.common.common_pb2.ExternalStorageMetrics + | None = ..., ) -> None: ... def HasField( self, field_name: typing_extensions.Literal[ - "failed", b"failed", "status", b"status", "successful", b"successful" + "failed", + b"failed", + "payload_download_metrics", + b"payload_download_metrics", + "payload_upload_metrics", + b"payload_upload_metrics", + "status", + b"status", + "successful", + b"successful", ], ) -> builtins.bool: ... def ClearField( @@ -55,6 +85,10 @@ class WorkflowActivationCompletion(google.protobuf.message.Message): field_name: typing_extensions.Literal[ "failed", b"failed", + "payload_download_metrics", + b"payload_download_metrics", + "payload_upload_metrics", + b"payload_upload_metrics", "run_id", b"run_id", "status", diff --git a/temporalio/bridge/sdk-core b/temporalio/bridge/sdk-core index d2769368d..ce69d10f0 160000 --- a/temporalio/bridge/sdk-core +++ b/temporalio/bridge/sdk-core @@ -1 +1 @@ -Subproject commit d2769368df9077a311537431ff4594c9c14db4e7 +Subproject commit ce69d10f0e80ec154264c3a7ed395af1e18aa796 diff --git a/temporalio/worker/_workflow.py b/temporalio/worker/_workflow.py index c031b5653..1b217b4a5 100644 --- a/temporalio/worker/_workflow.py +++ b/temporalio/worker/_workflow.py @@ -9,13 +9,13 @@ import os import sys import threading -import time from collections.abc import Awaitable, Callable, MutableMapping, Sequence from dataclasses import dataclass -from datetime import timedelta, timezone +from datetime import timezone from types import TracebackType import temporalio.api.common.v1 +import temporalio.bridge.proto.common import temporalio.bridge.proto.workflow_activation import temporalio.bridge.proto.workflow_completion import temporalio.bridge.runtime @@ -64,6 +64,17 @@ _DEFAULT_WORKFLOW_TASK_EXTERNAL_STORAGE_CONCURRENCY: int = 3 +def _set_external_storage_metrics( + target: temporalio.bridge.proto.common.ExternalStorageMetrics, + metrics: temporalio.converter._extstore.StorageOperationMetrics, +) -> None: + """Populate a proto ``ExternalStorageMetrics`` from measured storage metrics.""" + target.payload_count = metrics.payload_count + target.total_size_bytes = metrics.total_size + target.total_duration.FromTimedelta(metrics.total_duration) + target.driver_names.extend(sorted(metrics.driver_names)) + + class _WorkflowWorker: # type:ignore[reportUnusedClass] def __init__( self, @@ -325,7 +336,6 @@ async def _handle_activation( completion.successful.SetInParent() workflow = None data_converter = self._data_converter - task_start_time = time.monotonic() download_metrics = temporalio.converter._extstore.StorageOperationMetrics() try: if LOG_PROTOS: @@ -500,6 +510,17 @@ async def _handle_activation( completion.failed.Clear() completion.failed.failure.message = f"Failed encoding completion: {err}" + # Reported on the completion so core can include them in its workflow-task duration + # log; core measures the duration itself. + if download_metrics.payload_count > 0: + _set_external_storage_metrics( + completion.payload_download_metrics, download_metrics + ) + if upload_metrics.payload_count > 0: + _set_external_storage_metrics( + completion.payload_upload_metrics, upload_metrics + ) + # Send off completion if LOG_PROTOS: logger.debug("Sending workflow completion:\n%s", completion) @@ -511,84 +532,6 @@ async def _handle_activation( "Failed completing activation on workflow with run ID %s", act.run_id ) - # Log workflow task duration with external storage metrics - self._log_workflow_task_duration( - act, workflow, task_start_time, download_metrics, upload_metrics - ) - - def _log_workflow_task_duration( - self, - act: temporalio.bridge.proto.workflow_activation.WorkflowActivation, - workflow: _RunningWorkflow | None, - task_start_time: float, - download_metrics: temporalio.converter._extstore.StorageOperationMetrics, - upload_metrics: temporalio.converter._extstore.StorageOperationMetrics, - ) -> None: - task_duration = timedelta(seconds=time.monotonic() - task_start_time) - - def _fmt_duration(td: timedelta) -> str: - secs = td.total_seconds() - if secs >= 1: - return f"{secs:.3f}s" - return f"{secs * 1000:.3f}ms" - - completed_event_id = act.history_length + 1 - _info = workflow.get_info() if workflow is not None else None - attempt = _info.attempt if _info is not None else "unknown" - log_id = f"{act.run_id}:{completed_event_id}:{attempt}" - msg_details, extra = temporalio.workflow._build_log_context( - _info._logger_details() if _info is not None else None, - full_workflow_info=_info, - ) - msg_details["event_id"] = completed_event_id - msg_details["workflow_task_duration"] = _fmt_duration(task_duration) - msg_details["workflow_history_size"] = act.history_size_bytes - extra["event_id"] = completed_event_id - extra["workflow_task_duration"] = task_duration - extra["workflow_history_size"] = act.history_size_bytes - if download_metrics.payload_count > 0: - msg_details["payload_download_count"] = download_metrics.payload_count - msg_details["payload_download_size"] = download_metrics.total_size - msg_details["payload_download_duration"] = _fmt_duration( - download_metrics.total_duration - ) - msg_details["payload_download_drivers"] = sorted( - download_metrics.driver_names - ) - extra["payload_download_count"] = download_metrics.payload_count - extra["payload_download_size"] = download_metrics.total_size - extra["payload_download_duration"] = download_metrics.total_duration - extra["payload_download_drivers"] = sorted(download_metrics.driver_names) - if upload_metrics.payload_count > 0: - msg_details["payload_upload_count"] = upload_metrics.payload_count - msg_details["payload_upload_size"] = upload_metrics.total_size - msg_details["payload_upload_duration"] = _fmt_duration( - upload_metrics.total_duration - ) - msg_details["payload_upload_drivers"] = sorted(upload_metrics.driver_names) - extra["payload_upload_count"] = upload_metrics.payload_count - extra["payload_upload_size"] = upload_metrics.total_size - extra["payload_upload_duration"] = upload_metrics.total_duration - extra["payload_upload_drivers"] = sorted(upload_metrics.driver_names) - if task_duration.total_seconds() > 10: - logger.warning( - f"[TMPRL1104] {log_id} Workflow task exceeded 10 seconds (%s)", - msg_details, - extra=extra, - ) - elif task_duration.total_seconds() > 5: - logger.info( - f"[TMPRL1104] {log_id} Workflow task exceeded 5 seconds (%s)", - msg_details, - extra=extra, - ) - else: - logger.debug( - f"[TMPRL1104] {log_id} Workflow task duration information (%s)", - msg_details, - extra=extra, - ) - async def _handle_cache_eviction( self, act: temporalio.bridge.proto.workflow_activation.WorkflowActivation, diff --git a/tests/worker/test_extstore.py b/tests/worker/test_extstore.py index 2f8fde5fe..e8ef8edb2 100644 --- a/tests/worker/test_extstore.py +++ b/tests/worker/test_extstore.py @@ -1,8 +1,7 @@ +import contextlib import dataclasses -import logging -import re import uuid -from collections.abc import Sequence +from collections.abc import Iterator, Sequence from dataclasses import dataclass from datetime import timedelta from unittest import mock @@ -11,10 +10,10 @@ import temporalio import temporalio.bridge.client +import temporalio.bridge.proto.workflow_completion import temporalio.bridge.worker import temporalio.client import temporalio.converter -import temporalio.worker._workflow from temporalio import activity, workflow from temporalio.api.common.v1 import Payload from temporalio.client import Client, WorkflowFailureError, WorkflowHandle @@ -31,7 +30,7 @@ from temporalio.exceptions import ActivityError, ApplicationError from temporalio.testing._workflow import WorkflowEnvironment from temporalio.worker import Replayer -from tests.helpers import LogCapturer, assert_task_fail_eventually, new_worker +from tests.helpers import assert_task_fail_eventually, new_worker from tests.test_extstore import InMemoryTestDriver @@ -599,19 +598,32 @@ async def test_worker_storage_drivers_empty_without_external_storage( # TMPRL1104 workflow task duration logging # --------------------------------------------------------------------------- -_workflow_logger = logging.getLogger(temporalio.worker._workflow.__name__) +# The duration log itself is emitted (and tested) in sdk-core. The Python worker's part is +# attaching the external-storage metrics to the completion, so these tests capture the +# completion and assert on its fields directly rather than on core's asynchronously +# forwarded log, which would be nondeterministic to observe here. -def _tmprl1104_records(capturer: LogCapturer) -> list[logging.LogRecord]: - """Return all TMPRL1104 log records from the capturer.""" - return capturer.find_all(lambda r: r.getMessage().startswith("[TMPRL1104]")) +@contextlib.contextmanager +def _capture_completions() -> Iterator[ + list[temporalio.bridge.proto.workflow_completion.WorkflowActivationCompletion] +]: + """Capture every WorkflowActivationCompletion the worker hands to core.""" + completions: list[ + temporalio.bridge.proto.workflow_completion.WorkflowActivationCompletion + ] = [] + original = temporalio.bridge.worker.Worker.complete_workflow_activation + async def capturing(self, completion): # type: ignore[no-untyped-def] + completions.append(completion) + return await original(self, completion) -# Accept any duration-bucket wording: a loaded host can push a trivial task past 5s. -_TMPRL1104_DURATION_MESSAGE = re.compile( - r"\[TMPRL1104\] [^:]+:\d+:\d+ Workflow task " - r"(?:duration information|exceeded \d+ seconds) \(" -) + with mock.patch.object( + temporalio.bridge.worker.Worker, + "complete_workflow_activation", + capturing, + ): + yield completions async def _expected_payload_size( @@ -622,44 +634,33 @@ async def _expected_payload_size( return payloads[0].ByteSize() -@workflow.defn -class SimpleWorkflow: - """Minimal workflow for testing logging without external storage.""" - - @workflow.run - async def run(self) -> str: - return "done" - - async def test_tmprl1104_no_extstore(env: WorkflowEnvironment) -> None: - """Without external storage, TMPRL1104 logs contain duration but no - download/upload metrics.""" - with LogCapturer().logs_captured(_workflow_logger, level=logging.DEBUG) as capturer: - async with new_worker(env.client, SimpleWorkflow) as worker: + """Without external storage configured, completions carry no storage metrics.""" + with _capture_completions() as completions: + async with new_worker( + env.client, ExtStoreWorkflow, activities=[ext_store_activity] + ) as worker: await env.client.execute_workflow( - SimpleWorkflow.run, + ExtStoreWorkflow.run, + ExtStoreWorkflowInput( + input_data="small", + activity_input_size=10, + activity_output_size=10, + output_size=10, + ), id=f"workflow-{uuid.uuid4()}", task_queue=worker.task_queue, ) - records = _tmprl1104_records(capturer) - assert len(records) == 1 - record = records[0] - assert _TMPRL1104_DURATION_MESSAGE.match(record.getMessage()) - assert hasattr(record, "workflow_task_duration") - assert hasattr(record, "event_id") - # No external storage — download/upload fields must be absent - assert not hasattr(record, "payload_download_count") - assert not hasattr(record, "payload_download_size") - assert not hasattr(record, "payload_download_duration") - assert not hasattr(record, "payload_upload_count") - assert not hasattr(record, "payload_upload_size") - assert not hasattr(record, "payload_upload_duration") + assert completions, "expected the worker to complete at least one activation" + for c in completions: + assert not c.HasField("payload_download_metrics") + assert not c.HasField("payload_upload_metrics") async def test_tmprl1104_with_extstore_download(env: WorkflowEnvironment) -> None: - """When external storage decodes payloads, TMPRL1104 logs include download - metrics on the activation that retrieves them.""" + """When external storage retrieves payloads, the completion for the WFT that + retrieved them carries download metrics.""" driver = InMemoryTestDriver() data_converter = dataclasses.replace( temporalio.converter.default(), @@ -680,7 +681,7 @@ async def test_tmprl1104_with_extstore_download(env: WorkflowEnvironment) -> Non ) expected_input_size = await _expected_payload_size(data_converter, wf_input) - with LogCapturer().logs_captured(_workflow_logger, level=logging.DEBUG) as capturer: + with _capture_completions() as completions: async with new_worker( client, ExtStoreWorkflow, activities=[ext_store_activity] ) as worker: @@ -691,25 +692,19 @@ async def test_tmprl1104_with_extstore_download(env: WorkflowEnvironment) -> Non task_queue=worker.task_queue, ) - records = _tmprl1104_records(capturer) - assert len(records) == 2 - - # WFT 1: retrieves the externalized workflow input - assert _TMPRL1104_DURATION_MESSAGE.match(records[0].getMessage()) - assert getattr(records[0], "payload_download_count") == 1 - assert getattr(records[0], "payload_download_size") == expected_input_size - assert getattr(records[0], "payload_download_duration") > timedelta(0) - assert not hasattr(records[0], "payload_upload_count") - - # WFT 2: activity result is small — no external storage - assert _TMPRL1104_DURATION_MESSAGE.match(records[1].getMessage()) - assert not hasattr(records[1], "payload_download_count") - assert not hasattr(records[1], "payload_upload_count") + downloads = [c for c in completions if c.HasField("payload_download_metrics")] + assert len(downloads) == 1 + m = downloads[0].payload_download_metrics + assert m.payload_count == 1 + assert m.total_size_bytes == expected_input_size + assert m.total_duration.ToTimedelta() > timedelta(0) + assert list(m.driver_names) == [driver.name()] + assert not any(c.HasField("payload_upload_metrics") for c in completions) async def test_tmprl1104_with_extstore_upload(env: WorkflowEnvironment) -> None: - """When external storage encodes payloads, TMPRL1104 logs include upload - metrics on the WFT that produces them.""" + """When external storage stores payloads, the completion for the WFT that + produced them carries upload metrics.""" driver = InMemoryTestDriver() data_converter = dataclasses.replace( temporalio.converter.default(), @@ -725,7 +720,7 @@ async def test_tmprl1104_with_extstore_upload(env: WorkflowEnvironment) -> None: wf_output = "wo" * 1024 # 2048 bytes → stored externally expected_output_size = await _expected_payload_size(data_converter, wf_output) - with LogCapturer().logs_captured(_workflow_logger, level=logging.DEBUG) as capturer: + with _capture_completions() as completions: async with new_worker( client, ExtStoreWorkflow, activities=[ext_store_activity] ) as worker: @@ -741,27 +736,21 @@ async def test_tmprl1104_with_extstore_upload(env: WorkflowEnvironment) -> None: task_queue=worker.task_queue, ) - records = _tmprl1104_records(capturer) - assert len(records) == 2 - - # WFT 1: small input — no external storage - assert _TMPRL1104_DURATION_MESSAGE.match(records[0].getMessage()) - assert not hasattr(records[0], "payload_download_count") - assert not hasattr(records[0], "payload_upload_count") - - # WFT 2: workflow returns large result → uploaded - assert _TMPRL1104_DURATION_MESSAGE.match(records[1].getMessage()) - assert not hasattr(records[1], "payload_download_count") - assert getattr(records[1], "payload_upload_count") == 1 - assert getattr(records[1], "payload_upload_size") == expected_output_size - assert getattr(records[1], "payload_upload_duration") > timedelta(0) + uploads = [c for c in completions if c.HasField("payload_upload_metrics")] + assert len(uploads) == 1 + m = uploads[0].payload_upload_metrics + assert m.payload_count == 1 + assert m.total_size_bytes == expected_output_size + assert m.total_duration.ToTimedelta() > timedelta(0) + assert list(m.driver_names) == [driver.name()] + assert not any(c.HasField("payload_download_metrics") for c in completions) async def test_tmprl1104_with_extstore_download_and_upload( env: WorkflowEnvironment, ) -> None: - """When both download and upload happen across WFTs, TMPRL1104 logs include - both sets of metrics.""" + """When both download and upload happen across WFTs, the respective completions + carry the matching metrics.""" driver = InMemoryTestDriver() data_converter = dataclasses.replace( temporalio.converter.default(), @@ -784,7 +773,7 @@ async def test_tmprl1104_with_extstore_download_and_upload( wf_output = "wo" * 1024 expected_output_size = await _expected_payload_size(data_converter, wf_output) - with LogCapturer().logs_captured(_workflow_logger, level=logging.DEBUG) as capturer: + with _capture_completions() as completions: async with new_worker( client, ExtStoreWorkflow, activities=[ext_store_activity] ) as worker: @@ -795,22 +784,19 @@ async def test_tmprl1104_with_extstore_download_and_upload( task_queue=worker.task_queue, ) - records = _tmprl1104_records(capturer) - assert len(records) == 2 - - # WFT 1: retrieves externalized workflow input - assert _TMPRL1104_DURATION_MESSAGE.match(records[0].getMessage()) - assert getattr(records[0], "payload_download_count") == 1 - assert getattr(records[0], "payload_download_size") == expected_input_size - assert getattr(records[0], "payload_download_duration") > timedelta(0) - assert not hasattr(records[0], "payload_upload_count") - - # WFT 2: uploads externalized workflow result - assert _TMPRL1104_DURATION_MESSAGE.match(records[1].getMessage()) - assert not hasattr(records[1], "payload_download_count") - assert getattr(records[1], "payload_upload_count") == 1 - assert getattr(records[1], "payload_upload_size") == expected_output_size - assert getattr(records[1], "payload_upload_duration") > timedelta(0) + downloads = [c for c in completions if c.HasField("payload_download_metrics")] + assert len(downloads) == 1 + dm = downloads[0].payload_download_metrics + assert dm.payload_count == 1 + assert dm.total_size_bytes == expected_input_size + assert dm.total_duration.ToTimedelta() > timedelta(0) + + uploads = [c for c in completions if c.HasField("payload_upload_metrics")] + assert len(uploads) == 1 + um = uploads[0].payload_upload_metrics + assert um.payload_count == 1 + assert um.total_size_bytes == expected_output_size + assert um.total_duration.ToTimedelta() > timedelta(0) # --------------------------------------------------------------------------- From eeac0fadb5a9f4fdcc071c15f84c5e8724b66af3 Mon Sep 17 00:00:00 2001 From: Tim Conley Date: Thu, 30 Jul 2026 10:57:12 -0700 Subject: [PATCH 197/226] chore: update uv lockfile (#1700) * chore: update uv lockfile * fix: retain Python 3.14-compatible litellm --- uv.lock | 2684 +++++++++++++++++++++++++++---------------------------- 1 file changed, 1303 insertions(+), 1381 deletions(-) diff --git a/uv.lock b/uv.lock index 7641ad8e8..c825d5488 100644 --- a/uv.lock +++ b/uv.lock @@ -9,7 +9,7 @@ resolution-markers = [ ] [options] -exclude-newer = "0001-01-01T00:00:00Z" # This has no effect and is included for backwards compatibility when using relative exclude-newer values. +exclude-newer = "2026-07-16T16:18:47.494197Z" exclude-newer-span = "P2W" [[package]] @@ -59,11 +59,11 @@ wheels = [ [[package]] name = "aiohappyeyeballs" -version = "2.6.2" +version = "2.7.1" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/33/c6/61a2d7b7572279226bb2e7f61d7a19ca7c90da0329c93fa0d560cbf288d8/aiohappyeyeballs-2.6.2.tar.gz", hash = "sha256:e202810ee718bd01fc6ef49e8ea53d023d5cb6b581076d7925aa499fa55dbe64", size = 22591, upload-time = "2026-05-20T15:12:24.631Z" } +sdist = { url = "https://files.pythonhosted.org/packages/ce/f4/eec0465c2f67b2664688d0240b3212d5196fd89e741df67ddb81f8d35658/aiohappyeyeballs-2.7.1.tar.gz", hash = "sha256:065665c041c42a5938ed220bdcd7230f22527fbec085e1853d2402c8a3615d9d", size = 24757, upload-time = "2026-07-01T17:11:55.501Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/5f/fc/a7bf5b6e4e617b45f90f2d9d2a68519c249c81dd4fc2658c7a2a61c4f4b7/aiohappyeyeballs-2.6.2-py3-none-any.whl", hash = "sha256:4708045e2d7a6c6bdf8aafa8ed39649eaf926a4543b54560659129e3365953c4", size = 15062, upload-time = "2026-05-20T15:12:23.328Z" }, + { url = "https://files.pythonhosted.org/packages/71/43/1947f06babed6b3f1d7f38b0c767f52df66bfb2bc10b468c4a7de9eceff2/aiohappyeyeballs-2.7.1-py3-none-any.whl", hash = "sha256:9243213661e29250eb41368e5daa826fc017156c3b8a11440826b2e3ed376472", size = 15038, upload-time = "2026-07-01T17:11:54.055Z" }, ] [[package]] @@ -263,16 +263,16 @@ wheels = [ [[package]] name = "anyio" -version = "4.13.0" +version = "4.14.2" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "exceptiongroup", marker = "python_full_version < '3.11'" }, { name = "idna" }, { name = "typing-extensions", marker = "python_full_version < '3.13'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/19/14/2c5dd9f512b66549ae92767a9c7b330ae88e1932ca57876909410251fe13/anyio-4.13.0.tar.gz", hash = "sha256:334b70e641fd2221c1505b3890c69882fe4a2df910cba14d97019b90b24439dc", size = 231622, upload-time = "2026-03-24T12:59:09.671Z" } +sdist = { url = "https://files.pythonhosted.org/packages/61/cc/a381afa6efea9f496eff839d4a6a1aed3bfafc7b3ab4b0d1b243a12573dd/anyio-4.14.2.tar.gz", hash = "sha256:cfa139f3ed1a23ee8f88a145ddb5ac7605b8bbfd8592baacd7ce3d8bb4313c7f", size = 260176, upload-time = "2026-07-12T20:29:07.082Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/da/42/e921fccf5015463e32a3cf6ee7f980a6ed0f395ceeaa45060b61d86486c2/anyio-4.13.0-py3-none-any.whl", hash = "sha256:08b310f9e24a9594186fd75b4f73f4a4152069e3853f1ed8bfbf58369f4ad708", size = 114353, upload-time = "2026-03-24T12:59:08.246Z" }, + { url = "https://files.pythonhosted.org/packages/da/35/f2287558c17e29fafc8ef3daf819bb9834061cfa43bff8014f7df7f63bdc/anyio-4.14.2-py3-none-any.whl", hash = "sha256:9f505dda5ac9f0c8309b5e8bd445a8c2bf7246f3ce950121e45ea15bc41d1494", size = 125813, upload-time = "2026-07-12T20:29:05.763Z" }, ] [[package]] @@ -329,7 +329,7 @@ wheels = [ [[package]] name = "aws-sam-translator" -version = "1.110.0" +version = "1.111.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "boto3" }, @@ -337,9 +337,9 @@ dependencies = [ { name = "pydantic" }, { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/6e/2f/adeed2ce2bc62eca7ead7b3ae70fdd2cf84eecd582cd69a9529e6da89876/aws_sam_translator-1.110.0.tar.gz", hash = "sha256:466ee0e8200992c51b7fd5ede5e56ca2e8dd5473cc551e8495c14f2f4d636127", size = 368671, upload-time = "2026-05-19T21:21:06.959Z" } +sdist = { url = "https://files.pythonhosted.org/packages/8e/31/4e6d6f0b9d4ead8eaa1c13a14d86834e7691acf5726fb49de98f8e195028/aws_sam_translator-1.111.0.tar.gz", hash = "sha256:6884d94e28dc20384e5e0396e9386a456fe59303d706924deb2646329b4d97d3", size = 374368, upload-time = "2026-07-02T00:31:39.601Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/42/6f/286e3e49d3b6b181473fefa5d9fc02e10d98ccc417e0de74e396db951fd9/aws_sam_translator-1.110.0-py3-none-any.whl", hash = "sha256:69b09aacf2d305ac747037b7b913224cb8a9d653f47a0306509c1d20e420b670", size = 431671, upload-time = "2026-05-19T21:21:05.26Z" }, + { url = "https://files.pythonhosted.org/packages/c1/e3/505c9db9c4a4270ad12bac621f370cb02eabb224886c1b81960c658d9baa/aws_sam_translator-1.111.0-py3-none-any.whl", hash = "sha256:510d0ad8cd40b245a62004f2dc974ddbb6ff0d496bdec0bc7d9cd209b46d5fad", size = 440579, upload-time = "2026-07-02T00:31:38.077Z" }, ] [[package]] @@ -449,11 +449,11 @@ wheels = [ [[package]] name = "bracex" -version = "2.6" +version = "3.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/63/9a/fec38644694abfaaeca2798b58e276a8e61de49e2e37494ace423395febc/bracex-2.6.tar.gz", hash = "sha256:98f1347cd77e22ee8d967a30ad4e310b233f7754dbf31ff3fceb76145ba47dc7", size = 26642, upload-time = "2025-06-22T19:12:31.254Z" } +sdist = { url = "https://files.pythonhosted.org/packages/d0/f5/4473ad9b48cd0420a2d762a3750fa0e078e23e060b1af72662e5987e5530/bracex-3.0.tar.gz", hash = "sha256:b73f718d6bd98d8419e45df02426c86e9967c179949f779340d6c3a8c83b9111", size = 43162, upload-time = "2026-06-30T00:43:35.279Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/9d/2a/9186535ce58db529927f6cf5990a849aa9e052eea3e2cfefe20b9e1802da/bracex-2.6-py3-none-any.whl", hash = "sha256:0b0049264e7340b3ec782b5cb99beb325f36c3782a32e36e876452fd49a09952", size = 11508, upload-time = "2025-06-22T19:12:29.781Z" }, + { url = "https://files.pythonhosted.org/packages/f5/2e/68781b78e764e5ccc4af1e3d27e060069c73af90234853fa80000e7ee79d/bracex-3.0-py3-none-any.whl", hash = "sha256:3833e61c2f092d5aa0468fa2e6c6e990a306185abf763b6d122f0158e59c58a5", size = 11738, upload-time = "2026-06-30T00:43:34.196Z" }, ] [[package]] @@ -476,98 +476,126 @@ filecache = [ [[package]] name = "certifi" -version = "2026.5.20" +version = "2026.6.17" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/f3/ce/ee2ecad540810a79593028e88299baeae54d346cc7a0d94b6199988b89b1/certifi-2026.5.20.tar.gz", hash = "sha256:69dea482ab64caa7b9f6aba1c6bf48bb6a5448d1c0f1b17ab42ad8c763a5344d", size = 135422, upload-time = "2026-05-20T11:46:50.073Z" } +sdist = { url = "https://files.pythonhosted.org/packages/c9/c7/424b75da314c1045981bd9777432fad05a9e0c69daa4ed7e308bbaffe405/certifi-2026.6.17.tar.gz", hash = "sha256:024c88eeec92ca068db80f02b8b07c9cef7b9fe261d1d535abfd5abd6f6af432", size = 134594, upload-time = "2026-06-17T10:31:07.894Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/59/8c/57e832b7af6d7c5abe66eb3fbe3a3a32f4d11ea23a1aa7131371035be991/certifi-2026.5.20-py3-none-any.whl", hash = "sha256:3c52e209ba0a4ad7aebe60436a4ab349c39e1e602e8c134221e546902ad25897", size = 134134, upload-time = "2026-05-20T11:46:48.578Z" }, + { url = "https://files.pythonhosted.org/packages/ef/2f/c5464532e965badff2f4c4c1a3a83f5697f0d7c407ed0cda44aaa99bb451/certifi-2026.6.17-py3-none-any.whl", hash = "sha256:2227dcbaafe0d2f59279d1762ddddc37783ed4354594f194ffc31d20f41fc3db", size = 133289, upload-time = "2026-06-17T10:31:06.348Z" }, ] [[package]] name = "cffi" -version = "2.0.0" +version = "2.1.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "pycparser", marker = "implementation_name != 'PyPy'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/eb/56/b1ba7935a17738ae8453301356628e8147c79dbb825bcbc73dc7401f9846/cffi-2.0.0.tar.gz", hash = "sha256:44d1b5909021139fe36001ae048dbdde8214afa20200eda0f64c068cac5d5529", size = 523588, upload-time = "2025-09-08T23:24:04.541Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/93/d7/516d984057745a6cd96575eea814fe1edd6646ee6efd552fb7b0921dec83/cffi-2.0.0-cp310-cp310-macosx_10_13_x86_64.whl", hash = "sha256:0cf2d91ecc3fcc0625c2c530fe004f82c110405f101548512cce44322fa8ac44", size = 184283, upload-time = "2025-09-08T23:22:08.01Z" }, - { url = "https://files.pythonhosted.org/packages/9e/84/ad6a0b408daa859246f57c03efd28e5dd1b33c21737c2db84cae8c237aa5/cffi-2.0.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:f73b96c41e3b2adedc34a7356e64c8eb96e03a3782b535e043a986276ce12a49", size = 180504, upload-time = "2025-09-08T23:22:10.637Z" }, - { url = "https://files.pythonhosted.org/packages/50/bd/b1a6362b80628111e6653c961f987faa55262b4002fcec42308cad1db680/cffi-2.0.0-cp310-cp310-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:53f77cbe57044e88bbd5ed26ac1d0514d2acf0591dd6bb02a3ae37f76811b80c", size = 208811, upload-time = "2025-09-08T23:22:12.267Z" }, - { url = "https://files.pythonhosted.org/packages/4f/27/6933a8b2562d7bd1fb595074cf99cc81fc3789f6a6c05cdabb46284a3188/cffi-2.0.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:3e837e369566884707ddaf85fc1744b47575005c0a229de3327f8f9a20f4efeb", size = 216402, upload-time = "2025-09-08T23:22:13.455Z" }, - { url = "https://files.pythonhosted.org/packages/05/eb/b86f2a2645b62adcfff53b0dd97e8dfafb5c8aa864bd0d9a2c2049a0d551/cffi-2.0.0-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:5eda85d6d1879e692d546a078b44251cdd08dd1cfb98dfb77b670c97cee49ea0", size = 203217, upload-time = "2025-09-08T23:22:14.596Z" }, - { url = "https://files.pythonhosted.org/packages/9f/e0/6cbe77a53acf5acc7c08cc186c9928864bd7c005f9efd0d126884858a5fe/cffi-2.0.0-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:9332088d75dc3241c702d852d4671613136d90fa6881da7d770a483fd05248b4", size = 203079, upload-time = "2025-09-08T23:22:15.769Z" }, - { url = "https://files.pythonhosted.org/packages/98/29/9b366e70e243eb3d14a5cb488dfd3a0b6b2f1fb001a203f653b93ccfac88/cffi-2.0.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:fc7de24befaeae77ba923797c7c87834c73648a05a4bde34b3b7e5588973a453", size = 216475, upload-time = "2025-09-08T23:22:17.427Z" }, - { url = "https://files.pythonhosted.org/packages/21/7a/13b24e70d2f90a322f2900c5d8e1f14fa7e2a6b3332b7309ba7b2ba51a5a/cffi-2.0.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:cf364028c016c03078a23b503f02058f1814320a56ad535686f90565636a9495", size = 218829, upload-time = "2025-09-08T23:22:19.069Z" }, - { url = "https://files.pythonhosted.org/packages/60/99/c9dc110974c59cc981b1f5b66e1d8af8af764e00f0293266824d9c4254bc/cffi-2.0.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:e11e82b744887154b182fd3e7e8512418446501191994dbf9c9fc1f32cc8efd5", size = 211211, upload-time = "2025-09-08T23:22:20.588Z" }, - { url = "https://files.pythonhosted.org/packages/49/72/ff2d12dbf21aca1b32a40ed792ee6b40f6dc3a9cf1644bd7ef6e95e0ac5e/cffi-2.0.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:8ea985900c5c95ce9db1745f7933eeef5d314f0565b27625d9a10ec9881e1bfb", size = 218036, upload-time = "2025-09-08T23:22:22.143Z" }, - { url = "https://files.pythonhosted.org/packages/e2/cc/027d7fb82e58c48ea717149b03bcadcbdc293553edb283af792bd4bcbb3f/cffi-2.0.0-cp310-cp310-win32.whl", hash = "sha256:1f72fb8906754ac8a2cc3f9f5aaa298070652a0ffae577e0ea9bd480dc3c931a", size = 172184, upload-time = "2025-09-08T23:22:23.328Z" }, - { url = "https://files.pythonhosted.org/packages/33/fa/072dd15ae27fbb4e06b437eb6e944e75b068deb09e2a2826039e49ee2045/cffi-2.0.0-cp310-cp310-win_amd64.whl", hash = "sha256:b18a3ed7d5b3bd8d9ef7a8cb226502c6bf8308df1525e1cc676c3680e7176739", size = 182790, upload-time = "2025-09-08T23:22:24.752Z" }, - { url = "https://files.pythonhosted.org/packages/12/4a/3dfd5f7850cbf0d06dc84ba9aa00db766b52ca38d8b86e3a38314d52498c/cffi-2.0.0-cp311-cp311-macosx_10_13_x86_64.whl", hash = "sha256:b4c854ef3adc177950a8dfc81a86f5115d2abd545751a304c5bcf2c2c7283cfe", size = 184344, upload-time = "2025-09-08T23:22:26.456Z" }, - { url = "https://files.pythonhosted.org/packages/4f/8b/f0e4c441227ba756aafbe78f117485b25bb26b1c059d01f137fa6d14896b/cffi-2.0.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:2de9a304e27f7596cd03d16f1b7c72219bd944e99cc52b84d0145aefb07cbd3c", size = 180560, upload-time = "2025-09-08T23:22:28.197Z" }, - { url = "https://files.pythonhosted.org/packages/b1/b7/1200d354378ef52ec227395d95c2576330fd22a869f7a70e88e1447eb234/cffi-2.0.0-cp311-cp311-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:baf5215e0ab74c16e2dd324e8ec067ef59e41125d3eade2b863d294fd5035c92", size = 209613, upload-time = "2025-09-08T23:22:29.475Z" }, - { url = "https://files.pythonhosted.org/packages/b8/56/6033f5e86e8cc9bb629f0077ba71679508bdf54a9a5e112a3c0b91870332/cffi-2.0.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:730cacb21e1bdff3ce90babf007d0a0917cc3e6492f336c2f0134101e0944f93", size = 216476, upload-time = "2025-09-08T23:22:31.063Z" }, - { url = "https://files.pythonhosted.org/packages/dc/7f/55fecd70f7ece178db2f26128ec41430d8720f2d12ca97bf8f0a628207d5/cffi-2.0.0-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:6824f87845e3396029f3820c206e459ccc91760e8fa24422f8b0c3d1731cbec5", size = 203374, upload-time = "2025-09-08T23:22:32.507Z" }, - { url = "https://files.pythonhosted.org/packages/84/ef/a7b77c8bdc0f77adc3b46888f1ad54be8f3b7821697a7b89126e829e676a/cffi-2.0.0-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:9de40a7b0323d889cf8d23d1ef214f565ab154443c42737dfe52ff82cf857664", size = 202597, upload-time = "2025-09-08T23:22:34.132Z" }, - { url = "https://files.pythonhosted.org/packages/d7/91/500d892b2bf36529a75b77958edfcd5ad8e2ce4064ce2ecfeab2125d72d1/cffi-2.0.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:8941aaadaf67246224cee8c3803777eed332a19d909b47e29c9842ef1e79ac26", size = 215574, upload-time = "2025-09-08T23:22:35.443Z" }, - { url = "https://files.pythonhosted.org/packages/44/64/58f6255b62b101093d5df22dcb752596066c7e89dd725e0afaed242a61be/cffi-2.0.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:a05d0c237b3349096d3981b727493e22147f934b20f6f125a3eba8f994bec4a9", size = 218971, upload-time = "2025-09-08T23:22:36.805Z" }, - { url = "https://files.pythonhosted.org/packages/ab/49/fa72cebe2fd8a55fbe14956f9970fe8eb1ac59e5df042f603ef7c8ba0adc/cffi-2.0.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:94698a9c5f91f9d138526b48fe26a199609544591f859c870d477351dc7b2414", size = 211972, upload-time = "2025-09-08T23:22:38.436Z" }, - { url = "https://files.pythonhosted.org/packages/0b/28/dd0967a76aab36731b6ebfe64dec4e981aff7e0608f60c2d46b46982607d/cffi-2.0.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:5fed36fccc0612a53f1d4d9a816b50a36702c28a2aa880cb8a122b3466638743", size = 217078, upload-time = "2025-09-08T23:22:39.776Z" }, - { url = "https://files.pythonhosted.org/packages/2b/c0/015b25184413d7ab0a410775fdb4a50fca20f5589b5dab1dbbfa3baad8ce/cffi-2.0.0-cp311-cp311-win32.whl", hash = "sha256:c649e3a33450ec82378822b3dad03cc228b8f5963c0c12fc3b1e0ab940f768a5", size = 172076, upload-time = "2025-09-08T23:22:40.95Z" }, - { url = "https://files.pythonhosted.org/packages/ae/8f/dc5531155e7070361eb1b7e4c1a9d896d0cb21c49f807a6c03fd63fc877e/cffi-2.0.0-cp311-cp311-win_amd64.whl", hash = "sha256:66f011380d0e49ed280c789fbd08ff0d40968ee7b665575489afa95c98196ab5", size = 182820, upload-time = "2025-09-08T23:22:42.463Z" }, - { url = "https://files.pythonhosted.org/packages/95/5c/1b493356429f9aecfd56bc171285a4c4ac8697f76e9bbbbb105e537853a1/cffi-2.0.0-cp311-cp311-win_arm64.whl", hash = "sha256:c6638687455baf640e37344fe26d37c404db8b80d037c3d29f58fe8d1c3b194d", size = 177635, upload-time = "2025-09-08T23:22:43.623Z" }, - { url = "https://files.pythonhosted.org/packages/ea/47/4f61023ea636104d4f16ab488e268b93008c3d0bb76893b1b31db1f96802/cffi-2.0.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:6d02d6655b0e54f54c4ef0b94eb6be0607b70853c45ce98bd278dc7de718be5d", size = 185271, upload-time = "2025-09-08T23:22:44.795Z" }, - { url = "https://files.pythonhosted.org/packages/df/a2/781b623f57358e360d62cdd7a8c681f074a71d445418a776eef0aadb4ab4/cffi-2.0.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8eca2a813c1cb7ad4fb74d368c2ffbbb4789d377ee5bb8df98373c2cc0dee76c", size = 181048, upload-time = "2025-09-08T23:22:45.938Z" }, - { url = "https://files.pythonhosted.org/packages/ff/df/a4f0fbd47331ceeba3d37c2e51e9dfc9722498becbeec2bd8bc856c9538a/cffi-2.0.0-cp312-cp312-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:21d1152871b019407d8ac3985f6775c079416c282e431a4da6afe7aefd2bccbe", size = 212529, upload-time = "2025-09-08T23:22:47.349Z" }, - { url = "https://files.pythonhosted.org/packages/d5/72/12b5f8d3865bf0f87cf1404d8c374e7487dcf097a1c91c436e72e6badd83/cffi-2.0.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:b21e08af67b8a103c71a250401c78d5e0893beff75e28c53c98f4de42f774062", size = 220097, upload-time = "2025-09-08T23:22:48.677Z" }, - { url = "https://files.pythonhosted.org/packages/c2/95/7a135d52a50dfa7c882ab0ac17e8dc11cec9d55d2c18dda414c051c5e69e/cffi-2.0.0-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:1e3a615586f05fc4065a8b22b8152f0c1b00cdbc60596d187c2a74f9e3036e4e", size = 207983, upload-time = "2025-09-08T23:22:50.06Z" }, - { url = "https://files.pythonhosted.org/packages/3a/c8/15cb9ada8895957ea171c62dc78ff3e99159ee7adb13c0123c001a2546c1/cffi-2.0.0-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:81afed14892743bbe14dacb9e36d9e0e504cd204e0b165062c488942b9718037", size = 206519, upload-time = "2025-09-08T23:22:51.364Z" }, - { url = "https://files.pythonhosted.org/packages/78/2d/7fa73dfa841b5ac06c7b8855cfc18622132e365f5b81d02230333ff26e9e/cffi-2.0.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:3e17ed538242334bf70832644a32a7aae3d83b57567f9fd60a26257e992b79ba", size = 219572, upload-time = "2025-09-08T23:22:52.902Z" }, - { url = "https://files.pythonhosted.org/packages/07/e0/267e57e387b4ca276b90f0434ff88b2c2241ad72b16d31836adddfd6031b/cffi-2.0.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:3925dd22fa2b7699ed2617149842d2e6adde22b262fcbfada50e3d195e4b3a94", size = 222963, upload-time = "2025-09-08T23:22:54.518Z" }, - { url = "https://files.pythonhosted.org/packages/b6/75/1f2747525e06f53efbd878f4d03bac5b859cbc11c633d0fb81432d98a795/cffi-2.0.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:2c8f814d84194c9ea681642fd164267891702542f028a15fc97d4674b6206187", size = 221361, upload-time = "2025-09-08T23:22:55.867Z" }, - { url = "https://files.pythonhosted.org/packages/7b/2b/2b6435f76bfeb6bbf055596976da087377ede68df465419d192acf00c437/cffi-2.0.0-cp312-cp312-win32.whl", hash = "sha256:da902562c3e9c550df360bfa53c035b2f241fed6d9aef119048073680ace4a18", size = 172932, upload-time = "2025-09-08T23:22:57.188Z" }, - { url = "https://files.pythonhosted.org/packages/f8/ed/13bd4418627013bec4ed6e54283b1959cf6db888048c7cf4b4c3b5b36002/cffi-2.0.0-cp312-cp312-win_amd64.whl", hash = "sha256:da68248800ad6320861f129cd9c1bf96ca849a2771a59e0344e88681905916f5", size = 183557, upload-time = "2025-09-08T23:22:58.351Z" }, - { url = "https://files.pythonhosted.org/packages/95/31/9f7f93ad2f8eff1dbc1c3656d7ca5bfd8fb52c9d786b4dcf19b2d02217fa/cffi-2.0.0-cp312-cp312-win_arm64.whl", hash = "sha256:4671d9dd5ec934cb9a73e7ee9676f9362aba54f7f34910956b84d727b0d73fb6", size = 177762, upload-time = "2025-09-08T23:22:59.668Z" }, - { url = "https://files.pythonhosted.org/packages/4b/8d/a0a47a0c9e413a658623d014e91e74a50cdd2c423f7ccfd44086ef767f90/cffi-2.0.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:00bdf7acc5f795150faa6957054fbbca2439db2f775ce831222b66f192f03beb", size = 185230, upload-time = "2025-09-08T23:23:00.879Z" }, - { url = "https://files.pythonhosted.org/packages/4a/d2/a6c0296814556c68ee32009d9c2ad4f85f2707cdecfd7727951ec228005d/cffi-2.0.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:45d5e886156860dc35862657e1494b9bae8dfa63bf56796f2fb56e1679fc0bca", size = 181043, upload-time = "2025-09-08T23:23:02.231Z" }, - { url = "https://files.pythonhosted.org/packages/b0/1e/d22cc63332bd59b06481ceaac49d6c507598642e2230f201649058a7e704/cffi-2.0.0-cp313-cp313-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:07b271772c100085dd28b74fa0cd81c8fb1a3ba18b21e03d7c27f3436a10606b", size = 212446, upload-time = "2025-09-08T23:23:03.472Z" }, - { url = "https://files.pythonhosted.org/packages/a9/f5/a2c23eb03b61a0b8747f211eb716446c826ad66818ddc7810cc2cc19b3f2/cffi-2.0.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:d48a880098c96020b02d5a1f7d9251308510ce8858940e6fa99ece33f610838b", size = 220101, upload-time = "2025-09-08T23:23:04.792Z" }, - { url = "https://files.pythonhosted.org/packages/f2/7f/e6647792fc5850d634695bc0e6ab4111ae88e89981d35ac269956605feba/cffi-2.0.0-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:f93fd8e5c8c0a4aa1f424d6173f14a892044054871c771f8566e4008eaa359d2", size = 207948, upload-time = "2025-09-08T23:23:06.127Z" }, - { url = "https://files.pythonhosted.org/packages/cb/1e/a5a1bd6f1fb30f22573f76533de12a00bf274abcdc55c8edab639078abb6/cffi-2.0.0-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:dd4f05f54a52fb558f1ba9f528228066954fee3ebe629fc1660d874d040ae5a3", size = 206422, upload-time = "2025-09-08T23:23:07.753Z" }, - { url = "https://files.pythonhosted.org/packages/98/df/0a1755e750013a2081e863e7cd37e0cdd02664372c754e5560099eb7aa44/cffi-2.0.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:c8d3b5532fc71b7a77c09192b4a5a200ea992702734a2e9279a37f2478236f26", size = 219499, upload-time = "2025-09-08T23:23:09.648Z" }, - { url = "https://files.pythonhosted.org/packages/50/e1/a969e687fcf9ea58e6e2a928ad5e2dd88cc12f6f0ab477e9971f2309b57c/cffi-2.0.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:d9b29c1f0ae438d5ee9acb31cadee00a58c46cc9c0b2f9038c6b0b3470877a8c", size = 222928, upload-time = "2025-09-08T23:23:10.928Z" }, - { url = "https://files.pythonhosted.org/packages/36/54/0362578dd2c9e557a28ac77698ed67323ed5b9775ca9d3fe73fe191bb5d8/cffi-2.0.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:6d50360be4546678fc1b79ffe7a66265e28667840010348dd69a314145807a1b", size = 221302, upload-time = "2025-09-08T23:23:12.42Z" }, - { url = "https://files.pythonhosted.org/packages/eb/6d/bf9bda840d5f1dfdbf0feca87fbdb64a918a69bca42cfa0ba7b137c48cb8/cffi-2.0.0-cp313-cp313-win32.whl", hash = "sha256:74a03b9698e198d47562765773b4a8309919089150a0bb17d829ad7b44b60d27", size = 172909, upload-time = "2025-09-08T23:23:14.32Z" }, - { url = "https://files.pythonhosted.org/packages/37/18/6519e1ee6f5a1e579e04b9ddb6f1676c17368a7aba48299c3759bbc3c8b3/cffi-2.0.0-cp313-cp313-win_amd64.whl", hash = "sha256:19f705ada2530c1167abacb171925dd886168931e0a7b78f5bffcae5c6b5be75", size = 183402, upload-time = "2025-09-08T23:23:15.535Z" }, - { url = "https://files.pythonhosted.org/packages/cb/0e/02ceeec9a7d6ee63bb596121c2c8e9b3a9e150936f4fbef6ca1943e6137c/cffi-2.0.0-cp313-cp313-win_arm64.whl", hash = "sha256:256f80b80ca3853f90c21b23ee78cd008713787b1b1e93eae9f3d6a7134abd91", size = 177780, upload-time = "2025-09-08T23:23:16.761Z" }, - { url = "https://files.pythonhosted.org/packages/92/c4/3ce07396253a83250ee98564f8d7e9789fab8e58858f35d07a9a2c78de9f/cffi-2.0.0-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:fc33c5141b55ed366cfaad382df24fe7dcbc686de5be719b207bb248e3053dc5", size = 185320, upload-time = "2025-09-08T23:23:18.087Z" }, - { url = "https://files.pythonhosted.org/packages/59/dd/27e9fa567a23931c838c6b02d0764611c62290062a6d4e8ff7863daf9730/cffi-2.0.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:c654de545946e0db659b3400168c9ad31b5d29593291482c43e3564effbcee13", size = 181487, upload-time = "2025-09-08T23:23:19.622Z" }, - { url = "https://files.pythonhosted.org/packages/d6/43/0e822876f87ea8a4ef95442c3d766a06a51fc5298823f884ef87aaad168c/cffi-2.0.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:24b6f81f1983e6df8db3adc38562c83f7d4a0c36162885ec7f7b77c7dcbec97b", size = 220049, upload-time = "2025-09-08T23:23:20.853Z" }, - { url = "https://files.pythonhosted.org/packages/b4/89/76799151d9c2d2d1ead63c2429da9ea9d7aac304603de0c6e8764e6e8e70/cffi-2.0.0-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:12873ca6cb9b0f0d3a0da705d6086fe911591737a59f28b7936bdfed27c0d47c", size = 207793, upload-time = "2025-09-08T23:23:22.08Z" }, - { url = "https://files.pythonhosted.org/packages/bb/dd/3465b14bb9e24ee24cb88c9e3730f6de63111fffe513492bf8c808a3547e/cffi-2.0.0-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:d9b97165e8aed9272a6bb17c01e3cc5871a594a446ebedc996e2397a1c1ea8ef", size = 206300, upload-time = "2025-09-08T23:23:23.314Z" }, - { url = "https://files.pythonhosted.org/packages/47/d9/d83e293854571c877a92da46fdec39158f8d7e68da75bf73581225d28e90/cffi-2.0.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:afb8db5439b81cf9c9d0c80404b60c3cc9c3add93e114dcae767f1477cb53775", size = 219244, upload-time = "2025-09-08T23:23:24.541Z" }, - { url = "https://files.pythonhosted.org/packages/2b/0f/1f177e3683aead2bb00f7679a16451d302c436b5cbf2505f0ea8146ef59e/cffi-2.0.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:737fe7d37e1a1bffe70bd5754ea763a62a066dc5913ca57e957824b72a85e205", size = 222828, upload-time = "2025-09-08T23:23:26.143Z" }, - { url = "https://files.pythonhosted.org/packages/c6/0f/cafacebd4b040e3119dcb32fed8bdef8dfe94da653155f9d0b9dc660166e/cffi-2.0.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:38100abb9d1b1435bc4cc340bb4489635dc2f0da7456590877030c9b3d40b0c1", size = 220926, upload-time = "2025-09-08T23:23:27.873Z" }, - { url = "https://files.pythonhosted.org/packages/3e/aa/df335faa45b395396fcbc03de2dfcab242cd61a9900e914fe682a59170b1/cffi-2.0.0-cp314-cp314-win32.whl", hash = "sha256:087067fa8953339c723661eda6b54bc98c5625757ea62e95eb4898ad5e776e9f", size = 175328, upload-time = "2025-09-08T23:23:44.61Z" }, - { url = "https://files.pythonhosted.org/packages/bb/92/882c2d30831744296ce713f0feb4c1cd30f346ef747b530b5318715cc367/cffi-2.0.0-cp314-cp314-win_amd64.whl", hash = "sha256:203a48d1fb583fc7d78a4c6655692963b860a417c0528492a6bc21f1aaefab25", size = 185650, upload-time = "2025-09-08T23:23:45.848Z" }, - { url = "https://files.pythonhosted.org/packages/9f/2c/98ece204b9d35a7366b5b2c6539c350313ca13932143e79dc133ba757104/cffi-2.0.0-cp314-cp314-win_arm64.whl", hash = "sha256:dbd5c7a25a7cb98f5ca55d258b103a2054f859a46ae11aaf23134f9cc0d356ad", size = 180687, upload-time = "2025-09-08T23:23:47.105Z" }, - { url = "https://files.pythonhosted.org/packages/3e/61/c768e4d548bfa607abcda77423448df8c471f25dbe64fb2ef6d555eae006/cffi-2.0.0-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:9a67fc9e8eb39039280526379fb3a70023d77caec1852002b4da7e8b270c4dd9", size = 188773, upload-time = "2025-09-08T23:23:29.347Z" }, - { url = "https://files.pythonhosted.org/packages/2c/ea/5f76bce7cf6fcd0ab1a1058b5af899bfbef198bea4d5686da88471ea0336/cffi-2.0.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:7a66c7204d8869299919db4d5069a82f1561581af12b11b3c9f48c584eb8743d", size = 185013, upload-time = "2025-09-08T23:23:30.63Z" }, - { url = "https://files.pythonhosted.org/packages/be/b4/c56878d0d1755cf9caa54ba71e5d049479c52f9e4afc230f06822162ab2f/cffi-2.0.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:7cc09976e8b56f8cebd752f7113ad07752461f48a58cbba644139015ac24954c", size = 221593, upload-time = "2025-09-08T23:23:31.91Z" }, - { url = "https://files.pythonhosted.org/packages/e0/0d/eb704606dfe8033e7128df5e90fee946bbcb64a04fcdaa97321309004000/cffi-2.0.0-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:92b68146a71df78564e4ef48af17551a5ddd142e5190cdf2c5624d0c3ff5b2e8", size = 209354, upload-time = "2025-09-08T23:23:33.214Z" }, - { url = "https://files.pythonhosted.org/packages/d8/19/3c435d727b368ca475fb8742ab97c9cb13a0de600ce86f62eab7fa3eea60/cffi-2.0.0-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:b1e74d11748e7e98e2f426ab176d4ed720a64412b6a15054378afdb71e0f37dc", size = 208480, upload-time = "2025-09-08T23:23:34.495Z" }, - { url = "https://files.pythonhosted.org/packages/d0/44/681604464ed9541673e486521497406fadcc15b5217c3e326b061696899a/cffi-2.0.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:28a3a209b96630bca57cce802da70c266eb08c6e97e5afd61a75611ee6c64592", size = 221584, upload-time = "2025-09-08T23:23:36.096Z" }, - { url = "https://files.pythonhosted.org/packages/25/8e/342a504ff018a2825d395d44d63a767dd8ebc927ebda557fecdaca3ac33a/cffi-2.0.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:7553fb2090d71822f02c629afe6042c299edf91ba1bf94951165613553984512", size = 224443, upload-time = "2025-09-08T23:23:37.328Z" }, - { url = "https://files.pythonhosted.org/packages/e1/5e/b666bacbbc60fbf415ba9988324a132c9a7a0448a9a8f125074671c0f2c3/cffi-2.0.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:6c6c373cfc5c83a975506110d17457138c8c63016b563cc9ed6e056a82f13ce4", size = 223437, upload-time = "2025-09-08T23:23:38.945Z" }, - { url = "https://files.pythonhosted.org/packages/a0/1d/ec1a60bd1a10daa292d3cd6bb0b359a81607154fb8165f3ec95fe003b85c/cffi-2.0.0-cp314-cp314t-win32.whl", hash = "sha256:1fc9ea04857caf665289b7a75923f2c6ed559b8298a1b8c49e59f7dd95c8481e", size = 180487, upload-time = "2025-09-08T23:23:40.423Z" }, - { url = "https://files.pythonhosted.org/packages/bf/41/4c1168c74fac325c0c8156f04b6749c8b6a8f405bbf91413ba088359f60d/cffi-2.0.0-cp314-cp314t-win_amd64.whl", hash = "sha256:d68b6cef7827e8641e8ef16f4494edda8b36104d79773a334beaa1e3521430f6", size = 191726, upload-time = "2025-09-08T23:23:41.742Z" }, - { url = "https://files.pythonhosted.org/packages/ae/3a/dbeec9d1ee0844c679f6bb5d6ad4e9f198b1224f4e7a32825f47f6192b0c/cffi-2.0.0-cp314-cp314t-win_arm64.whl", hash = "sha256:0a1527a803f0a659de1af2e1fd700213caba79377e27e4693648c2923da066f9", size = 184195, upload-time = "2025-09-08T23:23:43.004Z" }, +sdist = { url = "https://files.pythonhosted.org/packages/57/5f/ff100cae70ebe9d8df1c01a00e510e45d9adb5c1fdda84791b199141de97/cffi-2.1.0.tar.gz", hash = "sha256:efc1cdd798b1aaf39b4610bba7aad28c9bea9b910f25c784ccf9ec1fa719d1f9", size = 531036, upload-time = "2026-07-06T21:34:30.382Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c0/e9/6d7724983b3d5a0908dbf74f64038ade77c18646ff6636ec7894fd392ce1/cffi-2.1.0-cp310-cp310-macosx_10_15_x86_64.whl", hash = "sha256:b65f590ef2a44640f9a05dbb548a429b4ade77913ce683ac8b1480777658a6c0", size = 183837, upload-time = "2026-07-06T21:32:09.655Z" }, + { url = "https://files.pythonhosted.org/packages/69/aa/24580a278de21fd7322635556334d9b535f1cbc00b0a3919447cdf464c65/cffi-2.1.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:164bff1657b2a74f0b6d54e11c9b375bc97b931f2ca9c43fcf875838da1570dd", size = 184226, upload-time = "2026-07-06T21:32:11.196Z" }, + { url = "https://files.pythonhosted.org/packages/88/a9/02cae418ec4beb282ace11958d9d4737793439d561fadc7e6d56f2e2b354/cffi-2.1.0-cp310-cp310-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:c941bb58d5a6e1c3892d86e42927ed6c180302f07e6d395d08c416e594b98b46", size = 211107, upload-time = "2026-07-06T21:32:12.328Z" }, + { url = "https://files.pythonhosted.org/packages/3b/30/c806937ed5e4c2c7ac30d9d6b76b5dc57ff8b75d83800d9bb11a8253cf2a/cffi-2.1.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:a016194dbe13d14ee9556e734b772d8d67b947092b268d757fd4290e3ba2dfc2", size = 218733, upload-time = "2026-07-06T21:32:13.67Z" }, + { url = "https://files.pythonhosted.org/packages/f9/cf/398272b8bbfd58aa314fda5a7f1cdbb26d1d78ae324a11211521315dd1f0/cffi-2.1.0-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:03e9810d18c646077e501f661b682fbf5dee4676048527ca3cffe66faa9960dd", size = 205543, upload-time = "2026-07-06T21:32:15.148Z" }, + { url = "https://files.pythonhosted.org/packages/45/ca/f91641185cdd90c36d317a9dc7f85e88ef8682d8b300977baff5e23c35d8/cffi-2.1.0-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:19c54ac121cad98450b4896fa9a43ee0180d57bc4bc911a33db6cab1efab6cd3", size = 205460, upload-time = "2026-07-06T21:32:16.479Z" }, + { url = "https://files.pythonhosted.org/packages/38/66/04781a77b411f0bb5b234d62c1814754ab75ebe455ccff1b08e8d7aae98f/cffi-2.1.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:4d433a51f1870e43a13b6732f92aaf540ff77c2015097c78556f75a2d6c030e0", size = 218760, upload-time = "2026-07-06T21:32:17.98Z" }, + { url = "https://files.pythonhosted.org/packages/d0/9a/bb1d5ed9c3fcae158e9f6391bf309c95d98c2ac37ed56573228471d0af5e/cffi-2.1.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:3d7f118b5adbfdfead90c25822690b02bc8074fba949bb7858bec4ebd55adb43", size = 221230, upload-time = "2026-07-06T21:32:19.407Z" }, + { url = "https://files.pythonhosted.org/packages/41/aa/3c1409cdd26094efacd1c36c66e0a6eb9d4296e4fd4f9901b8b2042f4323/cffi-2.1.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:c5f5df567f6eb216de69be06ce55c8b714090fae02b18a3b40da8163b8c5fa9c", size = 213524, upload-time = "2026-07-06T21:32:20.828Z" }, + { url = "https://files.pythonhosted.org/packages/fa/75/74dfb7c3fc6ebbd408038476bd4c1d7e925c62614e7b9c534ecc34218288/cffi-2.1.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:11b3fb55f4f8ad92274ed26705f65d8f91457de71f5380061eb6d125a768fecd", size = 220341, upload-time = "2026-07-06T21:32:21.9Z" }, + { url = "https://files.pythonhosted.org/packages/70/b6/9003c33a3e7d2c1306f5962e646457dcfe5a8cd8fce6bbe02d7af25db783/cffi-2.1.0-cp310-cp310-win32.whl", hash = "sha256:9d72af0cf10a76a600a9690078fe31c63b9588c8e86bf9fd353f713c84b5db0f", size = 174578, upload-time = "2026-07-06T21:32:23.073Z" }, + { url = "https://files.pythonhosted.org/packages/8a/26/710688310447531c7a22f857c7f79d9855ec18b03e04494ced723fb37e2f/cffi-2.1.0-cp310-cp310-win_amd64.whl", hash = "sha256:fb62edb5bb52cca65fab91a63afa7561607120d26090a7e8fda6fb9f064726da", size = 185071, upload-time = "2026-07-06T21:32:24.671Z" }, + { url = "https://files.pythonhosted.org/packages/d3/67/85c89a59ba36a671e79638f44d466749f08179266a57e4f2ffdf92174072/cffi-2.1.0-cp311-cp311-macosx_10_15_x86_64.whl", hash = "sha256:02cb7ff33ded4f1532476731f89ede53e2e488a8e6205515a82144246ffa7dcc", size = 183845, upload-time = "2026-07-06T21:32:26.32Z" }, + { url = "https://files.pythonhosted.org/packages/ea/dd/e3b0baa2d3d6a857ac72b7efbf18e32e487c9cdafcc13049ad765495b15e/cffi-2.1.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f5bce581e6b8c235e566a14768a943b172ada3ed73537bb0c0be1edee312d4e7", size = 184186, upload-time = "2026-07-06T21:32:28.025Z" }, + { url = "https://files.pythonhosted.org/packages/65/68/9f3ef890cf3c6ab97bd531c5677f67613d302165d16f8142b2811782a614/cffi-2.1.0-cp311-cp311-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:30b65779d598c370374fefabf138d456fd6f3216bfa7bedfab1ba82025b0cd93", size = 211892, upload-time = "2026-07-06T21:32:29.565Z" }, + { url = "https://files.pythonhosted.org/packages/22/d7/1a74539db16d8bfd839ff1515948948efbb162e574650fd3d846896eea95/cffi-2.1.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:88023dfe18799507b73f1dbb0d14326a17465de1bc9c9c7655c22845e9ddc3a2", size = 218793, upload-time = "2026-07-06T21:32:30.951Z" }, + { url = "https://files.pythonhosted.org/packages/ec/d1/9a5b7169499e8e8d8e636de70b97ac7c9447104d2ff1a2cd94790cea5162/cffi-2.1.0-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:0a96b74cda968eebbad56d973efe5098974f0a9fb323865bf99ea1fd24e3e64c", size = 205737, upload-time = "2026-07-06T21:32:32.216Z" }, + { url = "https://files.pythonhosted.org/packages/ba/b0/e131a9c41f10607926278453d9596163594fe1c4ebc46efe3b5e5b34eb84/cffi-2.1.0-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:a5781494d4d400a3f47f8f1da94b324f6e6b440a53387774002890a2a2f4b50f", size = 204909, upload-time = "2026-07-06T21:32:33.655Z" }, + { url = "https://files.pythonhosted.org/packages/fb/d2/4398416cd699b35167947c6e22aca52c47e69ad5695073c9f1f2c52e04aa/cffi-2.1.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:aa7a1b53a2a4452ada2d1b5dade9960b2522f1e61293a811a077439e39029565", size = 217883, upload-time = "2026-07-06T21:32:35.173Z" }, + { url = "https://files.pythonhosted.org/packages/a2/a5/d4fe77b589e5e82d43ebc809bf2e6474afe8e48e32ea050b9357645b6471/cffi-2.1.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:9d8272c0e483b024e1b9ad029821470ed8ec65631dbd90217469da0e7cd89f1c", size = 221251, upload-time = "2026-07-06T21:32:36.527Z" }, + { url = "https://files.pythonhosted.org/packages/22/f0/a2fc43084c0433caf7f461bccc013e28f848d04ee1c5ed7fce71423cf4d9/cffi-2.1.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:7762faa47e8ff7eb80bd261d9a7d8eea2d8baa69de5e95b70c1f338bbe712f02", size = 214250, upload-time = "2026-07-06T21:32:37.852Z" }, + { url = "https://files.pythonhosted.org/packages/04/8c/b925975448cf20634a9fbd5efceb807219db452653648d2897c0989cab2d/cffi-2.1.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:89095c1968b4ba8285840e131bf2891b09ae137fe2146905acae0354fbce1b5e", size = 219441, upload-time = "2026-07-06T21:32:39.146Z" }, + { url = "https://files.pythonhosted.org/packages/eb/da/5c4918a2d61d86fa927d716cb3d8e4626ef8dc8f605a599d32f33897f59a/cffi-2.1.0-cp311-cp311-win32.whl", hash = "sha256:64c753a0f87a256020004f37a1c8c02c480e725f910f0b2a0f3f07debd1b2479", size = 174496, upload-time = "2026-07-06T21:32:40.467Z" }, + { url = "https://files.pythonhosted.org/packages/f9/c8/6c2de1d55cf35ef8b92885d5ef280790f0fb9634d87ea1cc315176aecd61/cffi-2.1.0-cp311-cp311-win_amd64.whl", hash = "sha256:4f26194e3d95e06501b942642855aed4f953d55e95d7d01b7c4483db3ecff458", size = 185113, upload-time = "2026-07-06T21:32:41.761Z" }, + { url = "https://files.pythonhosted.org/packages/9e/4e/e8d7cb5783f1841a3c8fb3a7735838d7484d08ec08c9f984b14cac1ac0e9/cffi-2.1.0-cp311-cp311-win_arm64.whl", hash = "sha256:35aaea0c7ee0e58a5cd8c2fd1a48fdf7ece0d2699b7ecdda08194e9ce5dd9b3d", size = 179927, upload-time = "2026-07-06T21:32:42.961Z" }, + { url = "https://files.pythonhosted.org/packages/1e/85/990925db5df586ec90beb97529c853497e7f85ba0234830447faf41c3057/cffi-2.1.0-cp312-cp312-macosx_10_15_x86_64.whl", hash = "sha256:df2b82571a1b30f58a87bf4e5a9e78d2b1eff6c6ce8fd3aa3757221f93f0863f", size = 184829, upload-time = "2026-07-06T21:32:44.324Z" }, + { url = "https://files.pythonhosted.org/packages/4b/92/e7bb136ad6b5352603732cf907ef862ca103f20f2031c1735a46300c20c9/cffi-2.1.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:78474632761faa0fb96f30b1c928c84ebcf68713cbb80d15bab09dfe61640fde", size = 184728, upload-time = "2026-07-06T21:32:45.683Z" }, + { url = "https://files.pythonhosted.org/packages/c3/c0/d1ec30ffb370f748f2fb54425972bfef9871e0132e82fb589c46b6676049/cffi-2.1.0-cp312-cp312-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:5972433ad71a9e46516584ef60a0fda12d9dc459938d1539c3ddecf9bdc1368d", size = 214815, upload-time = "2026-07-06T21:32:48.557Z" }, + { url = "https://files.pythonhosted.org/packages/1b/dc/5620cf930688be01f2d673804291de757a934c90b946dbdc3d84130c2ea4/cffi-2.1.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:b6422532152adf4e59b110cb2808cee7a033800952f5c036b4af047ee43199e7", size = 222429, upload-time = "2026-07-06T21:32:49.848Z" }, + { url = "https://files.pythonhosted.org/packages/4b/a4/77b53abbf7a1e0beb9637edbef2a94d15f9c822f591e85d439ffd91519a6/cffi-2.1.0-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:46b1c8db8f6122420f32d02fffb924c2fe9bc772d228c7c711748fff56aabb2b", size = 210315, upload-time = "2026-07-06T21:32:51.221Z" }, + { url = "https://files.pythonhosted.org/packages/58/0c/f528df19cc94b675087324d4760d9e6d5bfae97d6217aa4fac43de4f5fcc/cffi-2.1.0-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:d9fafc5aa2e2a39aaf7f8cc0c1f044a9b07fca12e558dca53a3cc5c654ad67a7", size = 208859, upload-time = "2026-07-06T21:32:52.512Z" }, + { url = "https://files.pythonhosted.org/packages/62/f2/c9522a81c32132799a1972c39f5c5f8b4c8b9f00488a23feaa6c06f07741/cffi-2.1.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:1e9f50d192a3e525b15a75ab5114e442d83d657b7ec29182a991bc9a88fd3a66", size = 221844, upload-time = "2026-07-06T21:32:53.704Z" }, + { url = "https://files.pythonhosted.org/packages/6e/28/bd53988b9833e8f8ad539d26f4c07a6b3f6bcb1e9e02e7ca038250b3428d/cffi-2.1.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:98fff996e983a36d3aa2eca83af40c5821202e7e6f32d13ae94e3d2286f10cfe", size = 225287, upload-time = "2026-07-06T21:32:54.907Z" }, + { url = "https://files.pythonhosted.org/packages/79/99/0d0fd37f055224085f42bbb2c022d002e17dde4a97972822327b07d84101/cffi-2.1.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:379de10ce1ba048b1448599d1b37b24caee16309d1ac98d3982fc997f768700b", size = 223681, upload-time = "2026-07-06T21:32:56.329Z" }, + { url = "https://files.pythonhosted.org/packages/b0/80/c138990aa2a70b1a269f6e06348729836d733d6f970867943f61d367f8cc/cffi-2.1.0-cp312-cp312-win32.whl", hash = "sha256:9b8f0f26ca4e7513c534d351eca551947d053fac438f2a04ac96d882909b0d3a", size = 175269, upload-time = "2026-07-06T21:32:57.777Z" }, + { url = "https://files.pythonhosted.org/packages/a8/eb/f636456ff21a83fc13c032b58cc5dde061691546ac79efa284b2989b7982/cffi-2.1.0-cp312-cp312-win_amd64.whl", hash = "sha256:c97f080ea627e2863524c5af3836e2270b5f5dfff1f104392b959f8df0c5d384", size = 185881, upload-time = "2026-07-06T21:32:59.253Z" }, + { url = "https://files.pythonhosted.org/packages/dd/2c/400ea43e721727dca8a65c4521390e9196757caba4a45643acb2b63271b8/cffi-2.1.0-cp312-cp312-win_arm64.whl", hash = "sha256:6d194185eabd279f1c05ebe3504265ddfc5ad2b58d0714f7db9f01da592e9eb6", size = 180088, upload-time = "2026-07-06T21:33:02.278Z" }, + { url = "https://files.pythonhosted.org/packages/96/88/a996879e2eeccb815f6e3a5967b12a308257412acec882039d386bd2aa7b/cffi-2.1.0-cp313-cp313-ios_13_0_arm64_iphoneos.whl", hash = "sha256:10537b1df4967ca26d21e5072d7d54188354483b91dc75058968d3f0cf13fbda", size = 194331, upload-time = "2026-07-06T21:33:03.697Z" }, + { url = "https://files.pythonhosted.org/packages/58/85/7ae00d5c8dd6266f4e944c3db630f3c5c9a98b61d469c714d848b1d8138a/cffi-2.1.0-cp313-cp313-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:a95b05f9baf29b91171b3a8bd2020b028835243e7b0ff6bb23e2a3c228518b1b", size = 196966, upload-time = "2026-07-06T21:33:05.353Z" }, + { url = "https://files.pythonhosted.org/packages/8c/e9/45c3a76ad8d43ad9261f4c95436da61128d3ca545d72b9612c0ab5be0b1c/cffi-2.1.0-cp313-cp313-macosx_10_15_x86_64.whl", hash = "sha256:15faec4adfff450819f3aee0e2e02c812de6edb88203aa58807955db2003472a", size = 184795, upload-time = "2026-07-06T21:33:06.699Z" }, + { url = "https://files.pythonhosted.org/packages/84/4c/82f132cb4418ee6d953d982b19191e87e2a6372c8a4ce36e50b69d6ade4a/cffi-2.1.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:716ff8ec22f20b4d988b12884086bcef0fc99737043e503f7a3935a6be99b1ea", size = 184746, upload-time = "2026-07-06T21:33:08.071Z" }, + { url = "https://files.pythonhosted.org/packages/a0/1c/4ed5a0e5bdca6cbc275556de3328dd1b76fd0c11cc13c88fe66d1d8715f2/cffi-2.1.0-cp313-cp313-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:63960549e4f8dc41e31accb97b975abaecfc44c03e396c093a6436763c2ea7db", size = 214747, upload-time = "2026-07-06T21:33:09.671Z" }, + { url = "https://files.pythonhosted.org/packages/3a/a6/e879bb68cc23a2bc9ba8f4b7d8019f0c2694bad2ab6c4a3701d429439f58/cffi-2.1.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:ff067a8d8d880e7809e4ac88eb009bb848870115317b306666502ccad30b147f", size = 222392, upload-time = "2026-07-06T21:33:10.896Z" }, + { url = "https://files.pythonhosted.org/packages/88/f6/01890cfd63c08f8eb96a8319b0443690197d240a8bd6346048cf7bde9190/cffi-2.1.0-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:3b926723c13eba9f81d2ef3820d63aeceec3b2d4639906047bf675cb8a7a500d", size = 210285, upload-time = "2026-07-06T21:33:12.251Z" }, + { url = "https://files.pythonhosted.org/packages/a6/cf/2b684132056f438567b61e19d690dd31cd0921ace051e0a458be6074369e/cffi-2.1.0-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:47ff3a8bfd8cb9da1af7524b965127095055654c177fcfc7578debcb015eecd0", size = 208801, upload-time = "2026-07-06T21:33:13.617Z" }, + { url = "https://files.pythonhosted.org/packages/6f/08/f2e7d62c460faae0926f2d6e423694aa409ced3bc1fe2927a0a6e5f05416/cffi-2.1.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:799416bae98336e400981ff6e532d67d5c709cfb30afb79865a1315f94b0e224", size = 221808, upload-time = "2026-07-06T21:33:15.466Z" }, + { url = "https://files.pythonhosted.org/packages/38/37/04f54b8e63a02f3d908332c9effbf8c366167c6f733ed8a3d4f79b7e2a1e/cffi-2.1.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:961be50688f7fba2fa65f63712d3b9b341a22311f5253460ce933f52f0de1c8c", size = 225241, upload-time = "2026-07-06T21:33:16.869Z" }, + { url = "https://files.pythonhosted.org/packages/a9/d6/c72eecca433cd3e681c65ed313ab4835d9d4a379704d0f628a6a05f51c2e/cffi-2.1.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:bf5c6cf48238b0eb4c086978c492ad1cbc22373fc5b2d7353b3a598ce6db887a", size = 223588, upload-time = "2026-07-06T21:33:18.239Z" }, + { url = "https://files.pythonhosted.org/packages/c6/4b/e706f67279140f92939da3475ad610df18bfd52d50f14953a8e5fede71d5/cffi-2.1.0-cp313-cp313-win32.whl", hash = "sha256:db3eb7d46527159a878ec3460e9d40615bc25ba337d477db681aea6e4f05c5d2", size = 175248, upload-time = "2026-07-06T21:33:19.799Z" }, + { url = "https://files.pythonhosted.org/packages/5a/47/59eb7975cb0e4ef0afa764ea945b29a5bb4537a9f771cb7d6c8a5dd74c95/cffi-2.1.0-cp313-cp313-win_amd64.whl", hash = "sha256:8e74a6135550c4748af665b1b1118b6aab33b1fc6a16f9aff630af107c3b4512", size = 185717, upload-time = "2026-07-06T21:33:21.47Z" }, + { url = "https://files.pythonhosted.org/packages/5a/af/34fee85c48f8d94efc8597bc09470c9dd274c145f1c12e0fbc6ab6d38d74/cffi-2.1.0-cp313-cp313-win_arm64.whl", hash = "sha256:2282cd5e38aa8accd03e99d1256af8411c84cdbee6a89d841b563fdbd1f3e50f", size = 180114, upload-time = "2026-07-06T21:33:22.515Z" }, + { url = "https://files.pythonhosted.org/packages/d8/f0/81478e482afa03f6d18dc8f2afb5edc45b3080853b634b5ed91961be0998/cffi-2.1.0-cp314-cp314-ios_13_0_arm64_iphoneos.whl", hash = "sha256:d2117334c3af3bdcb9a88522b844a2bdb5efdc4f71c6c822df55486ae1c3347a", size = 194142, upload-time = "2026-07-06T21:33:23.657Z" }, + { url = "https://files.pythonhosted.org/packages/7d/95/8de304305cd9204974b0ca051b86d307cafca13aa575a0ef1b44d92c0d8c/cffi-2.1.0-cp314-cp314-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:702c436735fbe99d59ada02a1f65cfc0d31c0ee8b7290912f8fbc5cd1e4b16c3", size = 196819, upload-time = "2026-07-06T21:33:25.007Z" }, + { url = "https://files.pythonhosted.org/packages/20/71/7c8372d30e42415602ed9f268f7cfd66f1b855fed881ecd168bcb45dbc0b/cffi-2.1.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:1ff3456eab0d889592d1936d6125bbfbc7ae4d3354a700f8bd80450a66445d4d", size = 184965, upload-time = "2026-07-06T21:33:26.605Z" }, + { url = "https://files.pythonhosted.org/packages/d6/5c/584e626835f0375c928176c04137c96927165cb8733cdb3150ec04e5ee5e/cffi-2.1.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:c4165821e131d6d4ca444347c2b694e2311bcfa3fe5a861cc72968f28867beac", size = 184952, upload-time = "2026-07-06T21:33:27.823Z" }, + { url = "https://files.pythonhosted.org/packages/2e/d2/065fcae1c73979fac8e054462478d0ff8a29c40cdc2ed7ea5676a061df53/cffi-2.1.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:276f20fffd7b396e12516ba8edf9509210ac248cbbc5acbc39cd512f9f59ebe6", size = 222353, upload-time = "2026-07-06T21:33:29.178Z" }, + { url = "https://files.pythonhosted.org/packages/ed/a5/e8bbb1ce5b3ac2f53ad6a10bde44318a5a8d99d4f4a000d44a6e39aeb3e4/cffi-2.1.0-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:7d5980a3433d4b71a5e120f9dd551403d7824e31e2e67124fe2769c404c06913", size = 210051, upload-time = "2026-07-06T21:33:30.534Z" }, + { url = "https://files.pythonhosted.org/packages/28/ed/c127d3ac36e899c965e3361357c3befacd6578c03f40125183e41c3b219e/cffi-2.1.0-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:6ca4919c6e4f89aa99c42510b42cf54596892c00b3f9077f6bdd1505e24b9c8d", size = 208630, upload-time = "2026-07-06T21:33:31.753Z" }, + { url = "https://files.pythonhosted.org/packages/cc/d7/97d3136f81db489ec8d1d67748c110d6c994268fd7528014aa9f2b085e4e/cffi-2.1.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:d53d10f7da99ae46f7373b9150393e9c5eab9b224909982b43832668de4779f5", size = 221593, upload-time = "2026-07-06T21:33:33.044Z" }, + { url = "https://files.pythonhosted.org/packages/d3/27/93195977168ee63aed233a1a0993a2178798654d1f4bddcdd321d6fd3b21/cffi-2.1.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:c351efb95e832a853a29361675f33a7ce53de1a109cd73fd47af0712213aa4ce", size = 225146, upload-time = "2026-07-06T21:33:34.224Z" }, + { url = "https://files.pythonhosted.org/packages/b3/c1/6dbd291ee2ae5a50a034aa057207081f545923bbf15dad4511e985aafff5/cffi-2.1.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:dbf7c7a88e2bac086f06d14577332760bdeecc42bdec8ac4077f6260557d9326", size = 223240, upload-time = "2026-07-06T21:33:35.57Z" }, + { url = "https://files.pythonhosted.org/packages/0f/6f/ade5ce9863a57992a6ea3d0d10d7e29b8749fc127204b3d493d667b2815f/cffi-2.1.0-cp314-cp314-win32.whl", hash = "sha256:1854b724d00f6654c742097d5387569021be12d3a0f770eae1df8f8acfcc6acd", size = 177723, upload-time = "2026-07-06T21:33:51.626Z" }, + { url = "https://files.pythonhosted.org/packages/41/de/92b9eeed4ae4a21d6fd9b2a2c8505cbed573299902ea73981cc13f7ff62c/cffi-2.1.0-cp314-cp314-win_amd64.whl", hash = "sha256:1b96bfe2c4bd825681b7d311ad6d9b7280a091f43e8f63da5729638083cd3bfb", size = 187937, upload-time = "2026-07-06T21:33:53.403Z" }, + { url = "https://files.pythonhosted.org/packages/2e/1a/cc6ae6c2913a03aab8898eee57963cf1035b8df5872ed8b9115fcc7e2be8/cffi-2.1.0-cp314-cp314-win_arm64.whl", hash = "sha256:7d28dff1db6764108bc30788d85d61c876beff416d9a49cb9dd7c5a9f34f5804", size = 183001, upload-time = "2026-07-06T21:33:54.74Z" }, + { url = "https://files.pythonhosted.org/packages/14/f0/134c00ce0779ec86dea2aa1aac69339c2741a8045072676763512363a2ea/cffi-2.1.0-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:7ea6b3e2c4250ff1de21c630fe72d0f63eb95c2c32ffbf64a358cf4a8836d714", size = 188538, upload-time = "2026-07-06T21:33:36.792Z" }, + { url = "https://files.pythonhosted.org/packages/50/d8/3b86aba791cb610d24e8a3e1b2cd529e71fa15096b04e4d4e360049d4a4c/cffi-2.1.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:6af371f3767faeffc6ac1ef57cdfd25844403e9d3f476c5537caee499de96376", size = 188230, upload-time = "2026-07-06T21:33:38.011Z" }, + { url = "https://files.pythonhosted.org/packages/14/d0/117dcd9209255ad8571fbc8c92ef32593a1d294dcec91ddc4e4db50606f2/cffi-2.1.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:eb4e8997a49aa2c08a3e43c9045d224448b8941d88e7ac163c7d383e560cbf98", size = 223899, upload-time = "2026-07-06T21:33:39.514Z" }, + { url = "https://files.pythonhosted.org/packages/b6/3d/f20f8b886b254e3ad10e15cd4186d3aed49f3e6a35ab37aab9f8f25f7c03/cffi-2.1.0-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:bf01d8c84cbea96b944c73b22182e6c7c432b3475632b8111dbfdc95ddad6e13", size = 211652, upload-time = "2026-07-06T21:33:40.851Z" }, + { url = "https://files.pythonhosted.org/packages/28/3b/fad54de07260b93ddeef4b96d0131d57ea900675df1d410ae1deee52d7a6/cffi-2.1.0-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:33eb1ad83ebe8f313e0df035c406227d55a79456704a863fad9842136af5ad7d", size = 210755, upload-time = "2026-07-06T21:33:42.183Z" }, + { url = "https://files.pythonhosted.org/packages/cc/82/3d5c705acb7abbba9bbd7d79b8e62e0f25b6120eb7ae6ac49f1b721722fe/cffi-2.1.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:ac0f1a2d0cfa7eea3f2aaf006ab6e70e8feeb16b75d65b7e5939982ca2f11056", size = 223933, upload-time = "2026-07-06T21:33:43.603Z" }, + { url = "https://files.pythonhosted.org/packages/6c/d0/47e338384ab6b1004241002fa616301020cea4fc95f283506565d252f276/cffi-2.1.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:c16914df9fb7f500e440e6875fa23ff5e0b31db01fa9c06af98d59a91f0dc2e4", size = 226749, upload-time = "2026-07-06T21:33:45.046Z" }, + { url = "https://files.pythonhosted.org/packages/70/25/65bd5b58ea4bfdfc15cde02cb5365f89ef8ab8b2adfb8fe5c4bd4233382f/cffi-2.1.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:5ecbd0499275d57506d397eebe1981cee87b47fcd9ef5c22cab7ed7644a39a94", size = 225703, upload-time = "2026-07-06T21:33:46.374Z" }, + { url = "https://files.pythonhosted.org/packages/dc/78/aa01ac599a8a4322533d45a1f9bc93b338276d2d59dabbe7c6d92a775c81/cffi-2.1.0-cp314-cp314t-win32.whl", hash = "sha256:7d034dcffa09e9a46c93fa3a3be402096cb5354ac6e41ab8e5cc9cd8b642ad76", size = 182857, upload-time = "2026-07-06T21:33:47.696Z" }, + { url = "https://files.pythonhosted.org/packages/b9/26/d00496b22de4d4228f32dde94ad996f350c8aad676d63bcca0743c8dea4d/cffi-2.1.0-cp314-cp314t-win_amd64.whl", hash = "sha256:0582a58f3051372229ca8e7f5f589f9e5632678208d8636fea3676711fdf7fe5", size = 194065, upload-time = "2026-07-06T21:33:48.953Z" }, + { url = "https://files.pythonhosted.org/packages/d5/dd/0c7dbf815a579ff005008a2d815a55d6bb047c349eef536d9dc53d3f0a8d/cffi-2.1.0-cp314-cp314t-win_arm64.whl", hash = "sha256:510aeeeac94811b138077451da1fb18b308a5feab47dd2b603af55804155e1c8", size = 186404, upload-time = "2026-07-06T21:33:50.309Z" }, + { url = "https://files.pythonhosted.org/packages/55/c7/8c8c50cb11c6750051daf12164098a9a6f027ac4356967fd4d800a07f242/cffi-2.1.0-cp315-cp315-ios_13_0_arm64_iphoneos.whl", hash = "sha256:2e9dabb9abcb7ad15938c7196ad5c1718a4e6d33cc79b4c0209bdb64c4a54a5c", size = 194121, upload-time = "2026-07-06T21:33:56.109Z" }, + { url = "https://files.pythonhosted.org/packages/99/e2/67680bf19a6b60d2bb7ff83baefa2a4c3d2d7dc0f3277034b802e1fc504c/cffi-2.1.0-cp315-cp315-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:37f525a7e7e50c017fdebe58b787be310ad59357ae43a053943a6e1a6c526001", size = 196820, upload-time = "2026-07-06T21:33:57.288Z" }, + { url = "https://files.pythonhosted.org/packages/ed/da/4bbe583a3b3a5c8c60892124fe17f3fa3656523faf0d3484eae90f091853/cffi-2.1.0-cp315-cp315-macosx_10_15_x86_64.whl", hash = "sha256:95f2954c2c9473d892eca6e0409f3568b37ab62a8eedb122461f73cc273476e3", size = 184936, upload-time = "2026-07-06T21:33:58.765Z" }, + { url = "https://files.pythonhosted.org/packages/e5/4b/1f4c36ab273980d7aa75bb126ea4f8971f24a96108acad3a0a084028c57b/cffi-2.1.0-cp315-cp315-macosx_11_0_arm64.whl", hash = "sha256:cdf2448aab5f661c9315308ec8b93f4e8a1a67a3c733f8631067a2b67d5913dc", size = 185045, upload-time = "2026-07-06T21:34:00.085Z" }, + { url = "https://files.pythonhosted.org/packages/ef/c3/ad299dc38f3583f8d916b299f028af418a9ec98bc695fcbebeae7420691c/cffi-2.1.0-cp315-cp315-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:90bec57cf82089383bd06a605b3eb8daebf7e5a668520beaf6e327a83a947699", size = 222342, upload-time = "2026-07-06T21:34:01.814Z" }, + { url = "https://files.pythonhosted.org/packages/eb/d8/df4543cc087245044ed02ef3ad8e0a26619d0075ac7a77a12dc81177851b/cffi-2.1.0-cp315-cp315-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:6274dcb2d15cef48daa73ed1be5a40d501d74dccd0cd6db364776d12cb6ba022", size = 210073, upload-time = "2026-07-06T21:34:03.255Z" }, + { url = "https://files.pythonhosted.org/packages/2c/0e/fac738d73728c6cea2a88a2883dca54892496cbba88a1dc1f2909cb8a6f5/cffi-2.1.0-cp315-cp315-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:2b71d409cccee78310ab5dec549aed052aaea483346e282c7b02362596e01bb0", size = 208551, upload-time = "2026-07-06T21:34:04.433Z" }, + { url = "https://files.pythonhosted.org/packages/e6/3f/0b04a700dd64f465c93020253a793a82c9b4dff9961f48facd0df945d9b8/cffi-2.1.0-cp315-cp315-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:7d3538f9c0e50670f4deb93dbb696576e60590369cae2faf7de681e597a8a1f1", size = 221649, upload-time = "2026-07-06T21:34:06.157Z" }, + { url = "https://files.pythonhosted.org/packages/5d/7c/b7379a5704c79eda57ce075869ba70a0368d1c850f803b3c0d078d39dcaf/cffi-2.1.0-cp315-cp315-musllinux_1_2_aarch64.whl", hash = "sha256:8f9ec95b8a043d3dfbc74d9abc6f7baf524dd27a8dc160b0a32ff9cdab650c28", size = 225203, upload-time = "2026-07-06T21:34:07.489Z" }, + { url = "https://files.pythonhosted.org/packages/5a/02/d5e6c43ea85c41bda2a184a3418f195fe7cf602967a8d2b94e085b83deef/cffi-2.1.0-cp315-cp315-musllinux_1_2_x86_64.whl", hash = "sha256:af5e2915d41fe6c961694d7bfdc8562942638200f3ce2765dfb8b745cf997629", size = 223263, upload-time = "2026-07-06T21:34:08.712Z" }, + { url = "https://files.pythonhosted.org/packages/2c/d8/772b8259bf75749adffb1c546828978381fb516f60cf701f6c83daf60c85/cffi-2.1.0-cp315-cp315-win32.whl", hash = "sha256:0a42c688d19fca6e095a53c6a6e2295a5b050a8b289f109adab02a9e61a25de6", size = 177696, upload-time = "2026-07-06T21:34:26.355Z" }, + { url = "https://files.pythonhosted.org/packages/2f/dd/afa2191fc6d57fedd26e5844a2fe2fcc0bbfa00961bbaa5a41e4921e7cca/cffi-2.1.0-cp315-cp315-win_amd64.whl", hash = "sha256:bccbbb5ee76a61f9d99b5bf3846a51d7fca4b6a732fe46f89295610edaf41853", size = 187914, upload-time = "2026-07-06T21:34:27.58Z" }, + { url = "https://files.pythonhosted.org/packages/05/ef/6cd4f8c671517162379dc79cfae5aea9106bc38abb89628d5c16adf6a838/cffi-2.1.0-cp315-cp315-win_arm64.whl", hash = "sha256:8d35c139744adb3e727cd51b1a18324bbe44b8bd41bf8322bca4d41289f48eda", size = 183004, upload-time = "2026-07-06T21:34:28.905Z" }, + { url = "https://files.pythonhosted.org/packages/11/b6/12fc55092817a5faa26fb8c40c7f9d662e11a46ee248c137aafc42517d92/cffi-2.1.0-cp315-cp315t-macosx_10_15_x86_64.whl", hash = "sha256:f9912624a0c0b834b7520d7769b3644453aabc0a7e1c839da7359f050750e9bc", size = 188378, upload-time = "2026-07-06T21:34:09.926Z" }, + { url = "https://files.pythonhosted.org/packages/8d/2e/cdac88979f295fde5daa69622c7d2111e56e7ceb94f211357fbe452339e4/cffi-2.1.0-cp315-cp315t-macosx_11_0_arm64.whl", hash = "sha256:df92f2aba50eb4d96718b68ef76f2e57a57b54f2fa62333496d16c6d585a85ca", size = 188319, upload-time = "2026-07-06T21:34:11.101Z" }, + { url = "https://files.pythonhosted.org/packages/e0/27/1d0b408497e41a74795af122d7b603c418c5fed0171450f899afd04e594f/cffi-2.1.0-cp315-cp315t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:0520e1f4c35f44e209cbbb421b67eec42e6a157f59444dfb6058874ff3610e5d", size = 223904, upload-time = "2026-07-06T21:34:12.606Z" }, + { url = "https://files.pythonhosted.org/packages/8b/31/e115c985105dd7ffb32444505f18ceb874bb42d992af05d5dced7ecf1980/cffi-2.1.0-cp315-cp315t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:3681e031db29958a7502f5c0c9d6bbc4c36cb20f7b104086fa642d1799631ff8", size = 211554, upload-time = "2026-07-06T21:34:13.987Z" }, + { url = "https://files.pythonhosted.org/packages/5a/67/9e6e09409336d9e515c58367e7cfcf4f89df06ad25252675595a58eb59d5/cffi-2.1.0-cp315-cp315t-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:762f99479dcb369f60ab9017ad4ab97a36a1dd7c1ee5a3b15db0f4b8659120cd", size = 210795, upload-time = "2026-07-06T21:34:15.972Z" }, + { url = "https://files.pythonhosted.org/packages/19/e5/d3cc82a4a0be7902af279c04181ad038449c096734464a5ae1de3e1401bd/cffi-2.1.0-cp315-cp315t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:0611e7ebf90573a535ebdc33ae9da222d037853983e13359f580fab781ca017f", size = 223843, upload-time = "2026-07-06T21:34:17.509Z" }, + { url = "https://files.pythonhosted.org/packages/b9/65/b434abc97ce7cecc2c640fde160507c0ecc7e21544b483ba3325d2e2ea17/cffi-2.1.0-cp315-cp315t-musllinux_1_2_aarch64.whl", hash = "sha256:86cf8755a791f72c85dc287128cc62d4f24d392e3f1e15837245623f4a33cccc", size = 226773, upload-time = "2026-07-06T21:34:19.05Z" }, + { url = "https://files.pythonhosted.org/packages/b5/9f/d4dc66ca651eb1145a133314cda721abf13cfac3d28c4a0402263ae6ad75/cffi-2.1.0-cp315-cp315t-musllinux_1_2_x86_64.whl", hash = "sha256:ba00f661f8ba35d075c937174e27c2c421cec3942fd2e0ea3e66996757c0fdd9", size = 225719, upload-time = "2026-07-06T21:34:20.576Z" }, + { url = "https://files.pythonhosted.org/packages/68/5a/e536c528bc8057496c360c0978559a2dc45653f89dd6151078aa7d8fca1a/cffi-2.1.0-cp315-cp315t-win32.whl", hash = "sha256:cb96698e3c7413d906ce83f8ffd245ec1bd94707541f299d0ce4d6b0193e982b", size = 182760, upload-time = "2026-07-06T21:34:22.059Z" }, + { url = "https://files.pythonhosted.org/packages/d3/0b/0ffe8b82d3875bced5fa1e7986a7a46b748262a40ab7f60b475eb9fb1bb3/cffi-2.1.0-cp315-cp315t-win_amd64.whl", hash = "sha256:f146d154428a2523f9cc7936c02353c2459b8f6cf07d3cd1ee1c0a611109c5d5", size = 193769, upload-time = "2026-07-06T21:34:23.589Z" }, + { url = "https://files.pythonhosted.org/packages/a0/17/1073b53b68c9b5ca6914adf5f8bf55aacc2d3be102418c90700160ea8605/cffi-2.1.0-cp315-cp315t-win_arm64.whl", hash = "sha256:cbb7640ce37159548d2147b5b8c241f962143d4c71231431820783f4dc78f210", size = 186405, upload-time = "2026-07-06T21:34:24.857Z" }, ] [[package]] name = "cfn-lint" -version = "1.51.4" +version = "1.53.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "aws-sam-translator" }, @@ -579,114 +607,96 @@ dependencies = [ { name = "sympy" }, { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/22/7d/77cb6921776aff87b261a48610b977b1f3d790c2caee9d6d8c6d251329d1/cfn_lint-1.51.4.tar.gz", hash = "sha256:d37c48645e03abecfd826b8588103b06991abd838fe05c641f2853812289c021", size = 4156267, upload-time = "2026-06-03T15:17:06.006Z" } +sdist = { url = "https://files.pythonhosted.org/packages/d1/93/36cea246a0ec155eaa16444386675260bbfd38d259cfa26deffc8f417628/cfn_lint-1.53.0.tar.gz", hash = "sha256:dcf285939dea3c15e06bcb23a817bbdecb6c3e0ab19d98147877f04e02b5b07c", size = 4517403, upload-time = "2026-07-09T18:09:16.298Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/26/7f/a541df327c5c25c4e59e8bc35961f6c244837f9d0f3f2f22f94272e5fd11/cfn_lint-1.51.4-py3-none-any.whl", hash = "sha256:4897321a7d90c6e48859fde0c7c7c3c919815a947ddc85d0584dc12ad5bc544c", size = 6162327, upload-time = "2026-06-03T15:17:03.659Z" }, + { url = "https://files.pythonhosted.org/packages/86/eb/f9e2ce6888b5e77072169d884afcd957e69d3f293b03b4eb4dfad48fe358/cfn_lint-1.53.0-py3-none-any.whl", hash = "sha256:8a91d1f0d8d18614410a0c1676213df8cd0ac55fa462f3f6369fb9fdaa7ae28d", size = 5049598, upload-time = "2026-07-09T18:09:14.108Z" }, ] [[package]] name = "charset-normalizer" -version = "3.4.7" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/e7/a1/67fe25fac3c7642725500a3f6cfe5821ad557c3abb11c9d20d12c7008d3e/charset_normalizer-3.4.7.tar.gz", hash = "sha256:ae89db9e5f98a11a4bf50407d4363e7b09b31e55bc117b4f7d80aab97ba009e5", size = 144271, upload-time = "2026-04-02T09:28:39.342Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/26/08/0f303cb0b529e456bb116f2d50565a482694fbb94340bf56d44677e7ed03/charset_normalizer-3.4.7-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:cdd68a1fb318e290a2077696b7eb7a21a49163c455979c639bf5a5dcdc46617d", size = 315182, upload-time = "2026-04-02T09:25:40.673Z" }, - { url = "https://files.pythonhosted.org/packages/24/47/b192933e94b546f1b1fe4df9cc1f84fcdbf2359f8d1081d46dd029b50207/charset_normalizer-3.4.7-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e17b8d5d6a8c47c85e68ca8379def1303fd360c3e22093a807cd34a71cd082b8", size = 209329, upload-time = "2026-04-02T09:25:42.354Z" }, - { url = "https://files.pythonhosted.org/packages/c2/b4/01fa81c5ca6141024d89a8fc15968002b71da7f825dd14113207113fabbd/charset_normalizer-3.4.7-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:511ef87c8aec0783e08ac18565a16d435372bc1ac25a91e6ac7f5ef2b0bff790", size = 231230, upload-time = "2026-04-02T09:25:44.281Z" }, - { url = "https://files.pythonhosted.org/packages/20/f7/7b991776844dfa058017e600e6e55ff01984a063290ca5622c0b63162f68/charset_normalizer-3.4.7-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:007d05ec7321d12a40227aae9e2bc6dca73f3cb21058999a1df9e193555a9dcc", size = 225890, upload-time = "2026-04-02T09:25:45.475Z" }, - { url = "https://files.pythonhosted.org/packages/20/e7/bed0024a0f4ab0c8a9c64d4445f39b30c99bd1acd228291959e3de664247/charset_normalizer-3.4.7-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:cf29836da5119f3c8a8a70667b0ef5fdca3bb12f80fd06487cfa575b3909b393", size = 216930, upload-time = "2026-04-02T09:25:46.58Z" }, - { url = "https://files.pythonhosted.org/packages/e2/ab/b18f0ab31cdd7b3ddb8bb76c4a414aeb8160c9810fdf1bc62f269a539d87/charset_normalizer-3.4.7-cp310-cp310-manylinux_2_31_armv7l.whl", hash = "sha256:12d8baf840cc7889b37c7c770f478adea7adce3dcb3944d02ec87508e2dcf153", size = 202109, upload-time = "2026-04-02T09:25:48.031Z" }, - { url = "https://files.pythonhosted.org/packages/82/e5/7e9440768a06dfb3075936490cb82dbf0ee20a133bf0dd8551fa096914ec/charset_normalizer-3.4.7-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:d560742f3c0d62afaccf9f41fe485ed69bd7661a241f86a3ef0f0fb8b1a397af", size = 214684, upload-time = "2026-04-02T09:25:49.245Z" }, - { url = "https://files.pythonhosted.org/packages/71/94/8c61d8da9f062fdf457c80acfa25060ec22bf1d34bbeaca4350f13bcfd07/charset_normalizer-3.4.7-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:b14b2d9dac08e28bb8046a1a0434b1750eb221c8f5b87a68f4fa11a6f97b5e34", size = 212785, upload-time = "2026-04-02T09:25:50.671Z" }, - { url = "https://files.pythonhosted.org/packages/66/cd/6e9889c648e72c0ab2e5967528bb83508f354d706637bc7097190c874e13/charset_normalizer-3.4.7-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:bc17a677b21b3502a21f66a8cc64f5bfad4df8a0b8434d661666f8ce90ac3af1", size = 203055, upload-time = "2026-04-02T09:25:51.802Z" }, - { url = "https://files.pythonhosted.org/packages/92/2e/7a951d6a08aefb7eb8e1b54cdfb580b1365afdd9dd484dc4bee9e5d8f258/charset_normalizer-3.4.7-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:750e02e074872a3fad7f233b47734166440af3cdea0add3e95163110816d6752", size = 232502, upload-time = "2026-04-02T09:25:53.388Z" }, - { url = "https://files.pythonhosted.org/packages/58/d5/abcf2d83bf8e0a1286df55cd0dc1d49af0da4282aa77e986df343e7de124/charset_normalizer-3.4.7-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:4e5163c14bffd570ef2affbfdd77bba66383890797df43dc8b4cc7d6f500bf53", size = 214295, upload-time = "2026-04-02T09:25:54.765Z" }, - { url = "https://files.pythonhosted.org/packages/47/3a/7d4cd7ed54be99973a0dc176032cba5cb1f258082c31fa6df35cff46acfc/charset_normalizer-3.4.7-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:6ed74185b2db44f41ef35fd1617c5888e59792da9bbc9190d6c7300617182616", size = 227145, upload-time = "2026-04-02T09:25:55.904Z" }, - { url = "https://files.pythonhosted.org/packages/1d/98/3a45bf8247889cf28262ebd3d0872edff11565b2a1e3064ccb132db3fbb0/charset_normalizer-3.4.7-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:94e1885b270625a9a828c9793b4d52a64445299baa1fea5a173bf1d3dd9a1a5a", size = 218884, upload-time = "2026-04-02T09:25:57.074Z" }, - { url = "https://files.pythonhosted.org/packages/ad/80/2e8b7f8915ed5c9ef13aa828d82738e33888c485b65ebf744d615040c7ea/charset_normalizer-3.4.7-cp310-cp310-win32.whl", hash = "sha256:6785f414ae0f3c733c437e0f3929197934f526d19dfaa75e18fdb4f94c6fb374", size = 148343, upload-time = "2026-04-02T09:25:58.199Z" }, - { url = "https://files.pythonhosted.org/packages/35/1b/3b8c8c77184af465ee9ad88b5aea46ea6b2e1f7b9dc9502891e37af21e30/charset_normalizer-3.4.7-cp310-cp310-win_amd64.whl", hash = "sha256:6696b7688f54f5af4462118f0bfa7c1621eeb87154f77fa04b9295ce7a8f2943", size = 159174, upload-time = "2026-04-02T09:25:59.322Z" }, - { url = "https://files.pythonhosted.org/packages/be/c1/feb40dca40dbb21e0a908801782d9288c64fc8d8e562c2098e9994c8c21b/charset_normalizer-3.4.7-cp310-cp310-win_arm64.whl", hash = "sha256:66671f93accb62ed07da56613636f3641f1a12c13046ce91ffc923721f23c008", size = 147805, upload-time = "2026-04-02T09:26:00.756Z" }, - { url = "https://files.pythonhosted.org/packages/c2/d7/b5b7020a0565c2e9fa8c09f4b5fa6232feb326b8c20081ccded47ea368fd/charset_normalizer-3.4.7-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:7641bb8895e77f921102f72833904dcd9901df5d6d72a2ab8f31d04b7e51e4e7", size = 309705, upload-time = "2026-04-02T09:26:02.191Z" }, - { url = "https://files.pythonhosted.org/packages/5a/53/58c29116c340e5456724ecd2fff4196d236b98f3da97b404bc5e51ac3493/charset_normalizer-3.4.7-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:202389074300232baeb53ae2569a60901f7efadd4245cf3a3bf0617d60b439d7", size = 206419, upload-time = "2026-04-02T09:26:03.583Z" }, - { url = "https://files.pythonhosted.org/packages/b2/02/e8146dc6591a37a00e5144c63f29fb7c97a734ea8a111190783c0e60ab63/charset_normalizer-3.4.7-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:30b8d1d8c52a48c2c5690e152c169b673487a2a58de1ec7393196753063fcd5e", size = 227901, upload-time = "2026-04-02T09:26:04.738Z" }, - { url = "https://files.pythonhosted.org/packages/fb/73/77486c4cd58f1267bf17db420e930c9afa1b3be3fe8c8b8ebbebc9624359/charset_normalizer-3.4.7-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:532bc9bf33a68613fd7d65e4b1c71a6a38d7d42604ecf239c77392e9b4e8998c", size = 222742, upload-time = "2026-04-02T09:26:06.36Z" }, - { url = "https://files.pythonhosted.org/packages/a1/fa/f74eb381a7d94ded44739e9d94de18dc5edc9c17fb8c11f0a6890696c0a9/charset_normalizer-3.4.7-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:2fe249cb4651fd12605b7288b24751d8bfd46d35f12a20b1ba33dea122e690df", size = 214061, upload-time = "2026-04-02T09:26:08.347Z" }, - { url = "https://files.pythonhosted.org/packages/dc/92/42bd3cefcf7687253fb86694b45f37b733c97f59af3724f356fa92b8c344/charset_normalizer-3.4.7-cp311-cp311-manylinux_2_31_armv7l.whl", hash = "sha256:65bcd23054beab4d166035cabbc868a09c1a49d1efe458fe8e4361215df40265", size = 199239, upload-time = "2026-04-02T09:26:09.823Z" }, - { url = "https://files.pythonhosted.org/packages/4c/3d/069e7184e2aa3b3cddc700e3dd267413dc259854adc3380421c805c6a17d/charset_normalizer-3.4.7-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:08e721811161356f97b4059a9ba7bafb23ea5ee2255402c42881c214e173c6b4", size = 210173, upload-time = "2026-04-02T09:26:10.953Z" }, - { url = "https://files.pythonhosted.org/packages/62/51/9d56feb5f2e7074c46f93e0ebdbe61f0848ee246e2f0d89f8e20b89ebb8f/charset_normalizer-3.4.7-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:e060d01aec0a910bdccb8be71faf34e7799ce36950f8294c8bf612cba65a2c9e", size = 209841, upload-time = "2026-04-02T09:26:12.142Z" }, - { url = "https://files.pythonhosted.org/packages/d2/59/893d8f99cc4c837dda1fe2f1139079703deb9f321aabcb032355de13b6c7/charset_normalizer-3.4.7-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:38c0109396c4cfc574d502df99742a45c72c08eff0a36158b6f04000043dbf38", size = 200304, upload-time = "2026-04-02T09:26:13.711Z" }, - { url = "https://files.pythonhosted.org/packages/7d/1d/ee6f3be3464247578d1ed5c46de545ccc3d3ff933695395c402c21fa6b77/charset_normalizer-3.4.7-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:1c2a768fdd44ee4a9339a9b0b130049139b8ce3c01d2ce09f67f5a68048d477c", size = 229455, upload-time = "2026-04-02T09:26:14.941Z" }, - { url = "https://files.pythonhosted.org/packages/54/bb/8fb0a946296ea96a488928bdce8ef99023998c48e4713af533e9bb98ef07/charset_normalizer-3.4.7-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:1a87ca9d5df6fe460483d9a5bbf2b18f620cbed41b432e2bddb686228282d10b", size = 210036, upload-time = "2026-04-02T09:26:16.478Z" }, - { url = "https://files.pythonhosted.org/packages/9a/bc/015b2387f913749f82afd4fcba07846d05b6d784dd16123cb66860e0237d/charset_normalizer-3.4.7-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:d635aab80466bc95771bb78d5370e74d36d1fe31467b6b29b8b57b2a3cd7d22c", size = 224739, upload-time = "2026-04-02T09:26:17.751Z" }, - { url = "https://files.pythonhosted.org/packages/17/ab/63133691f56baae417493cba6b7c641571a2130eb7bceba6773367ab9ec5/charset_normalizer-3.4.7-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:ae196f021b5e7c78e918242d217db021ed2a6ace2bc6ae94c0fc596221c7f58d", size = 216277, upload-time = "2026-04-02T09:26:18.981Z" }, - { url = "https://files.pythonhosted.org/packages/06/6d/3be70e827977f20db77c12a97e6a9f973631a45b8d186c084527e53e77a4/charset_normalizer-3.4.7-cp311-cp311-win32.whl", hash = "sha256:adb2597b428735679446b46c8badf467b4ca5f5056aae4d51a19f9570301b1ad", size = 147819, upload-time = "2026-04-02T09:26:20.295Z" }, - { url = "https://files.pythonhosted.org/packages/20/d9/5f67790f06b735d7c7637171bbfd89882ad67201891b7275e51116ed8207/charset_normalizer-3.4.7-cp311-cp311-win_amd64.whl", hash = "sha256:8e385e4267ab76874ae30db04c627faaaf0b509e1ccc11a95b3fc3e83f855c00", size = 159281, upload-time = "2026-04-02T09:26:21.74Z" }, - { url = "https://files.pythonhosted.org/packages/ca/83/6413f36c5a34afead88ce6f66684d943d91f233d76dd083798f9602b75ae/charset_normalizer-3.4.7-cp311-cp311-win_arm64.whl", hash = "sha256:d4a48e5b3c2a489fae013b7589308a40146ee081f6f509e047e0e096084ceca1", size = 147843, upload-time = "2026-04-02T09:26:22.901Z" }, - { url = "https://files.pythonhosted.org/packages/0c/eb/4fc8d0a7110eb5fc9cc161723a34a8a6c200ce3b4fbf681bc86feee22308/charset_normalizer-3.4.7-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:eca9705049ad3c7345d574e3510665cb2cf844c2f2dcfe675332677f081cbd46", size = 311328, upload-time = "2026-04-02T09:26:24.331Z" }, - { url = "https://files.pythonhosted.org/packages/f8/e3/0fadc706008ac9d7b9b5be6dc767c05f9d3e5df51744ce4cc9605de7b9f4/charset_normalizer-3.4.7-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6178f72c5508bfc5fd446a5905e698c6212932f25bcdd4b47a757a50605a90e2", size = 208061, upload-time = "2026-04-02T09:26:25.568Z" }, - { url = "https://files.pythonhosted.org/packages/42/f0/3dd1045c47f4a4604df85ec18ad093912ae1344ac706993aff91d38773a2/charset_normalizer-3.4.7-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:e1421b502d83040e6d7fb2fb18dff63957f720da3d77b2fbd3187ceb63755d7b", size = 229031, upload-time = "2026-04-02T09:26:26.865Z" }, - { url = "https://files.pythonhosted.org/packages/dc/67/675a46eb016118a2fbde5a277a5d15f4f69d5f3f5f338e5ee2f8948fcf43/charset_normalizer-3.4.7-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:edac0f1ab77644605be2cbba52e6b7f630731fc42b34cb0f634be1a6eface56a", size = 225239, upload-time = "2026-04-02T09:26:28.044Z" }, - { url = "https://files.pythonhosted.org/packages/4b/f8/d0118a2f5f23b02cd166fa385c60f9b0d4f9194f574e2b31cef350ad7223/charset_normalizer-3.4.7-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5649fd1c7bade02f320a462fdefd0b4bd3ce036065836d4f42e0de958038e116", size = 216589, upload-time = "2026-04-02T09:26:29.239Z" }, - { url = "https://files.pythonhosted.org/packages/b1/f1/6d2b0b261b6c4ceef0fcb0d17a01cc5bc53586c2d4796fa04b5c540bc13d/charset_normalizer-3.4.7-cp312-cp312-manylinux_2_31_armv7l.whl", hash = "sha256:203104ed3e428044fd943bc4bf45fa73c0730391f9621e37fe39ecf477b128cb", size = 202733, upload-time = "2026-04-02T09:26:30.5Z" }, - { url = "https://files.pythonhosted.org/packages/6f/c0/7b1f943f7e87cc3db9626ba17807d042c38645f0a1d4415c7a14afb5591f/charset_normalizer-3.4.7-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:298930cec56029e05497a76988377cbd7457ba864beeea92ad7e844fe74cd1f1", size = 212652, upload-time = "2026-04-02T09:26:31.709Z" }, - { url = "https://files.pythonhosted.org/packages/38/dd/5a9ab159fe45c6e72079398f277b7d2b523e7f716acc489726115a910097/charset_normalizer-3.4.7-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:708838739abf24b2ceb208d0e22403dd018faeef86ddac04319a62ae884c4f15", size = 211229, upload-time = "2026-04-02T09:26:33.282Z" }, - { url = "https://files.pythonhosted.org/packages/d5/ff/531a1cad5ca855d1c1a8b69cb71abfd6d85c0291580146fda7c82857caa1/charset_normalizer-3.4.7-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:0f7eb884681e3938906ed0434f20c63046eacd0111c4ba96f27b76084cd679f5", size = 203552, upload-time = "2026-04-02T09:26:34.845Z" }, - { url = "https://files.pythonhosted.org/packages/c1/4c/a5fb52d528a8ca41f7598cb619409ece30a169fbdf9cdce592e53b46c3a6/charset_normalizer-3.4.7-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:4dc1e73c36828f982bfe79fadf5919923f8a6f4df2860804db9a98c48824ce8d", size = 230806, upload-time = "2026-04-02T09:26:36.152Z" }, - { url = "https://files.pythonhosted.org/packages/59/7a/071feed8124111a32b316b33ae4de83d36923039ef8cf48120266844285b/charset_normalizer-3.4.7-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:aed52fea0513bac0ccde438c188c8a471c4e0f457c2dd20cdbf6ea7a450046c7", size = 212316, upload-time = "2026-04-02T09:26:37.672Z" }, - { url = "https://files.pythonhosted.org/packages/fd/35/f7dba3994312d7ba508e041eaac39a36b120f32d4c8662b8814dab876431/charset_normalizer-3.4.7-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:fea24543955a6a729c45a73fe90e08c743f0b3334bbf3201e6c4bc1b0c7fa464", size = 227274, upload-time = "2026-04-02T09:26:38.93Z" }, - { url = "https://files.pythonhosted.org/packages/8a/2d/a572df5c9204ab7688ec1edc895a73ebded3b023bb07364710b05dd1c9be/charset_normalizer-3.4.7-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:bb6d88045545b26da47aa879dd4a89a71d1dce0f0e549b1abcb31dfe4a8eac49", size = 218468, upload-time = "2026-04-02T09:26:40.17Z" }, - { url = "https://files.pythonhosted.org/packages/86/eb/890922a8b03a568ca2f336c36585a4713c55d4d67bf0f0c78924be6315ca/charset_normalizer-3.4.7-cp312-cp312-win32.whl", hash = "sha256:2257141f39fe65a3fdf38aeccae4b953e5f3b3324f4ff0daf9f15b8518666a2c", size = 148460, upload-time = "2026-04-02T09:26:41.416Z" }, - { url = "https://files.pythonhosted.org/packages/35/d9/0e7dffa06c5ab081f75b1b786f0aefc88365825dfcd0ac544bdb7b2b6853/charset_normalizer-3.4.7-cp312-cp312-win_amd64.whl", hash = "sha256:5ed6ab538499c8644b8a3e18debabcd7ce684f3fa91cf867521a7a0279cab2d6", size = 159330, upload-time = "2026-04-02T09:26:42.554Z" }, - { url = "https://files.pythonhosted.org/packages/9e/5d/481bcc2a7c88ea6b0878c299547843b2521ccbc40980cb406267088bc701/charset_normalizer-3.4.7-cp312-cp312-win_arm64.whl", hash = "sha256:56be790f86bfb2c98fb742ce566dfb4816e5a83384616ab59c49e0604d49c51d", size = 147828, upload-time = "2026-04-02T09:26:44.075Z" }, - { url = "https://files.pythonhosted.org/packages/c1/3b/66777e39d3ae1ddc77ee606be4ec6d8cbd4c801f65e5a1b6f2b11b8346dd/charset_normalizer-3.4.7-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:f496c9c3cc02230093d8330875c4c3cdfc3b73612a5fd921c65d39cbcef08063", size = 309627, upload-time = "2026-04-02T09:26:45.198Z" }, - { url = "https://files.pythonhosted.org/packages/2e/4e/b7f84e617b4854ade48a1b7915c8ccfadeba444d2a18c291f696e37f0d3b/charset_normalizer-3.4.7-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0ea948db76d31190bf08bd371623927ee1339d5f2a0b4b1b4a4439a65298703c", size = 207008, upload-time = "2026-04-02T09:26:46.824Z" }, - { url = "https://files.pythonhosted.org/packages/c4/bb/ec73c0257c9e11b268f018f068f5d00aa0ef8c8b09f7753ebd5f2880e248/charset_normalizer-3.4.7-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:a277ab8928b9f299723bc1a2dabb1265911b1a76341f90a510368ca44ad9ab66", size = 228303, upload-time = "2026-04-02T09:26:48.397Z" }, - { url = "https://files.pythonhosted.org/packages/85/fb/32d1f5033484494619f701e719429c69b766bfc4dbc61aa9e9c8c166528b/charset_normalizer-3.4.7-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:3bec022aec2c514d9cf199522a802bd007cd588ab17ab2525f20f9c34d067c18", size = 224282, upload-time = "2026-04-02T09:26:49.684Z" }, - { url = "https://files.pythonhosted.org/packages/fa/07/330e3a0dda4c404d6da83b327270906e9654a24f6c546dc886a0eb0ffb23/charset_normalizer-3.4.7-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e044c39e41b92c845bc815e5ae4230804e8e7bc29e399b0437d64222d92809dd", size = 215595, upload-time = "2026-04-02T09:26:50.915Z" }, - { url = "https://files.pythonhosted.org/packages/e3/7c/fc890655786e423f02556e0216d4b8c6bcb6bdfa890160dc66bf52dee468/charset_normalizer-3.4.7-cp313-cp313-manylinux_2_31_armv7l.whl", hash = "sha256:f495a1652cf3fbab2eb0639776dad966c2fb874d79d87ca07f9d5f059b8bd215", size = 201986, upload-time = "2026-04-02T09:26:52.197Z" }, - { url = "https://files.pythonhosted.org/packages/d8/97/bfb18b3db2aed3b90cf54dc292ad79fdd5ad65c4eae454099475cbeadd0d/charset_normalizer-3.4.7-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:e712b419df8ba5e42b226c510472b37bd57b38e897d3eca5e8cfd410a29fa859", size = 211711, upload-time = "2026-04-02T09:26:53.49Z" }, - { url = "https://files.pythonhosted.org/packages/6f/a5/a581c13798546a7fd557c82614a5c65a13df2157e9ad6373166d2a3e645d/charset_normalizer-3.4.7-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:7804338df6fcc08105c7745f1502ba68d900f45fd770d5bdd5288ddccb8a42d8", size = 210036, upload-time = "2026-04-02T09:26:54.975Z" }, - { url = "https://files.pythonhosted.org/packages/8c/bf/b3ab5bcb478e4193d517644b0fb2bf5497fbceeaa7a1bc0f4d5b50953861/charset_normalizer-3.4.7-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:481551899c856c704d58119b5025793fa6730adda3571971af568f66d2424bb5", size = 202998, upload-time = "2026-04-02T09:26:56.303Z" }, - { url = "https://files.pythonhosted.org/packages/e7/4e/23efd79b65d314fa320ec6017b4b5834d5c12a58ba4610aa353af2e2f577/charset_normalizer-3.4.7-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:f59099f9b66f0d7145115e6f80dd8b1d847176df89b234a5a6b3f00437aa0832", size = 230056, upload-time = "2026-04-02T09:26:57.554Z" }, - { url = "https://files.pythonhosted.org/packages/b9/9f/1e1941bc3f0e01df116e68dc37a55c4d249df5e6fa77f008841aef68264f/charset_normalizer-3.4.7-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:f59ad4c0e8f6bba240a9bb85504faa1ab438237199d4cce5f622761507b8f6a6", size = 211537, upload-time = "2026-04-02T09:26:58.843Z" }, - { url = "https://files.pythonhosted.org/packages/80/0f/088cbb3020d44428964a6c97fe1edfb1b9550396bf6d278330281e8b709c/charset_normalizer-3.4.7-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:3dedcc22d73ec993f42055eff4fcfed9318d1eeb9a6606c55892a26964964e48", size = 226176, upload-time = "2026-04-02T09:27:00.437Z" }, - { url = "https://files.pythonhosted.org/packages/6a/9f/130394f9bbe06f4f63e22641d32fc9b202b7e251c9aef4db044324dac493/charset_normalizer-3.4.7-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:64f02c6841d7d83f832cd97ccf8eb8a906d06eb95d5276069175c696b024b60a", size = 217723, upload-time = "2026-04-02T09:27:02.021Z" }, - { url = "https://files.pythonhosted.org/packages/73/55/c469897448a06e49f8fa03f6caae97074fde823f432a98f979cc42b90e69/charset_normalizer-3.4.7-cp313-cp313-win32.whl", hash = "sha256:4042d5c8f957e15221d423ba781e85d553722fc4113f523f2feb7b188cc34c5e", size = 148085, upload-time = "2026-04-02T09:27:03.192Z" }, - { url = "https://files.pythonhosted.org/packages/5d/78/1b74c5bbb3f99b77a1715c91b3e0b5bdb6fe302d95ace4f5b1bec37b0167/charset_normalizer-3.4.7-cp313-cp313-win_amd64.whl", hash = "sha256:3946fa46a0cf3e4c8cb1cc52f56bb536310d34f25f01ca9b6c16afa767dab110", size = 158819, upload-time = "2026-04-02T09:27:04.454Z" }, - { url = "https://files.pythonhosted.org/packages/68/86/46bd42279d323deb8687c4a5a811fd548cb7d1de10cf6535d099877a9a9f/charset_normalizer-3.4.7-cp313-cp313-win_arm64.whl", hash = "sha256:80d04837f55fc81da168b98de4f4b797ef007fc8a79ab71c6ec9bc4dd662b15b", size = 147915, upload-time = "2026-04-02T09:27:05.971Z" }, - { url = "https://files.pythonhosted.org/packages/97/c8/c67cb8c70e19ef1960b97b22ed2a1567711de46c4ddf19799923adc836c2/charset_normalizer-3.4.7-cp314-cp314-macosx_10_15_universal2.whl", hash = "sha256:c36c333c39be2dbca264d7803333c896ab8fa7d4d6f0ab7edb7dfd7aea6e98c0", size = 309234, upload-time = "2026-04-02T09:27:07.194Z" }, - { url = "https://files.pythonhosted.org/packages/99/85/c091fdee33f20de70d6c8b522743b6f831a2f1cd3ff86de4c6a827c48a76/charset_normalizer-3.4.7-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1c2aed2e5e41f24ea8ef1590b8e848a79b56f3a5564a65ceec43c9d692dc7d8a", size = 208042, upload-time = "2026-04-02T09:27:08.749Z" }, - { url = "https://files.pythonhosted.org/packages/87/1c/ab2ce611b984d2fd5d86a5a8a19c1ae26acac6bad967da4967562c75114d/charset_normalizer-3.4.7-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:54523e136b8948060c0fa0bc7b1b50c32c186f2fceee897a495406bb6e311d2b", size = 228706, upload-time = "2026-04-02T09:27:09.951Z" }, - { url = "https://files.pythonhosted.org/packages/a8/29/2b1d2cb00bf085f59d29eb773ce58ec2d325430f8c216804a0a5cd83cbca/charset_normalizer-3.4.7-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:715479b9a2802ecac752a3b0efa2b0b60285cf962ee38414211abdfccc233b41", size = 224727, upload-time = "2026-04-02T09:27:11.175Z" }, - { url = "https://files.pythonhosted.org/packages/47/5c/032c2d5a07fe4d4855fea851209cca2b6f03ebeb6d4e3afdb3358386a684/charset_normalizer-3.4.7-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:bd6c2a1c7573c64738d716488d2cdd3c00e340e4835707d8fdb8dc1a66ef164e", size = 215882, upload-time = "2026-04-02T09:27:12.446Z" }, - { url = "https://files.pythonhosted.org/packages/2c/c2/356065d5a8b78ed04499cae5f339f091946a6a74f91e03476c33f0ab7100/charset_normalizer-3.4.7-cp314-cp314-manylinux_2_31_armv7l.whl", hash = "sha256:c45e9440fb78f8ddabcf714b68f936737a121355bf59f3907f4e17721b9d1aae", size = 200860, upload-time = "2026-04-02T09:27:13.721Z" }, - { url = "https://files.pythonhosted.org/packages/0c/cd/a32a84217ced5039f53b29f460962abb2d4420def55afabe45b1c3c7483d/charset_normalizer-3.4.7-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:3534e7dcbdcf757da6b85a0bbf5b6868786d5982dd959b065e65481644817a18", size = 211564, upload-time = "2026-04-02T09:27:15.272Z" }, - { url = "https://files.pythonhosted.org/packages/44/86/58e6f13ce26cc3b8f4a36b94a0f22ae2f00a72534520f4ae6857c4b81f89/charset_normalizer-3.4.7-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:e8ac484bf18ce6975760921bb6148041faa8fef0547200386ea0b52b5d27bf7b", size = 211276, upload-time = "2026-04-02T09:27:16.834Z" }, - { url = "https://files.pythonhosted.org/packages/8f/fe/d17c32dc72e17e155e06883efa84514ca375f8a528ba2546bee73fc4df81/charset_normalizer-3.4.7-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:a5fe03b42827c13cdccd08e6c0247b6a6d4b5e3cdc53fd1749f5896adcdc2356", size = 201238, upload-time = "2026-04-02T09:27:18.229Z" }, - { url = "https://files.pythonhosted.org/packages/6a/29/f33daa50b06525a237451cdb6c69da366c381a3dadcd833fa5676bc468b3/charset_normalizer-3.4.7-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:2d6eb928e13016cea4f1f21d1e10c1cebd5a421bc57ddf5b1142ae3f86824fab", size = 230189, upload-time = "2026-04-02T09:27:19.445Z" }, - { url = "https://files.pythonhosted.org/packages/b6/6e/52c84015394a6a0bdcd435210a7e944c5f94ea1055f5cc5d56c5fe368e7b/charset_normalizer-3.4.7-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:e74327fb75de8986940def6e8dee4f127cc9752bee7355bb323cc5b2659b6d46", size = 211352, upload-time = "2026-04-02T09:27:20.79Z" }, - { url = "https://files.pythonhosted.org/packages/8c/d7/4353be581b373033fb9198bf1da3cf8f09c1082561e8e922aa7b39bf9fe8/charset_normalizer-3.4.7-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:d6038d37043bced98a66e68d3aa2b6a35505dc01328cd65217cefe82f25def44", size = 227024, upload-time = "2026-04-02T09:27:22.063Z" }, - { url = "https://files.pythonhosted.org/packages/30/45/99d18aa925bd1740098ccd3060e238e21115fffbfdcb8f3ece837d0ace6c/charset_normalizer-3.4.7-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:7579e913a5339fb8fa133f6bbcfd8e6749696206cf05acdbdca71a1b436d8e72", size = 217869, upload-time = "2026-04-02T09:27:23.486Z" }, - { url = "https://files.pythonhosted.org/packages/5c/05/5ee478aa53f4bb7996482153d4bfe1b89e0f087f0ab6b294fcf92d595873/charset_normalizer-3.4.7-cp314-cp314-win32.whl", hash = "sha256:5b77459df20e08151cd6f8b9ef8ef1f961ef73d85c21a555c7eed5b79410ec10", size = 148541, upload-time = "2026-04-02T09:27:25.146Z" }, - { url = "https://files.pythonhosted.org/packages/48/77/72dcb0921b2ce86420b2d79d454c7022bf5be40202a2a07906b9f2a35c97/charset_normalizer-3.4.7-cp314-cp314-win_amd64.whl", hash = "sha256:92a0a01ead5e668468e952e4238cccd7c537364eb7d851ab144ab6627dbbe12f", size = 159634, upload-time = "2026-04-02T09:27:26.642Z" }, - { url = "https://files.pythonhosted.org/packages/c6/a3/c2369911cd72f02386e4e340770f6e158c7980267da16af8f668217abaa0/charset_normalizer-3.4.7-cp314-cp314-win_arm64.whl", hash = "sha256:67f6279d125ca0046a7fd386d01b311c6363844deac3e5b069b514ba3e63c246", size = 148384, upload-time = "2026-04-02T09:27:28.271Z" }, - { url = "https://files.pythonhosted.org/packages/94/09/7e8a7f73d24dba1f0035fbbf014d2c36828fc1bf9c88f84093e57d315935/charset_normalizer-3.4.7-cp314-cp314t-macosx_10_15_universal2.whl", hash = "sha256:effc3f449787117233702311a1b7d8f59cba9ced946ba727bdc329ec69028e24", size = 330133, upload-time = "2026-04-02T09:27:29.474Z" }, - { url = "https://files.pythonhosted.org/packages/8d/da/96975ddb11f8e977f706f45cddd8540fd8242f71ecdb5d18a80723dcf62c/charset_normalizer-3.4.7-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:fbccdc05410c9ee21bbf16a35f4c1d16123dcdeb8a1d38f33654fa21d0234f79", size = 216257, upload-time = "2026-04-02T09:27:30.793Z" }, - { url = "https://files.pythonhosted.org/packages/e5/e8/1d63bf8ef2d388e95c64b2098f45f84758f6d102a087552da1485912637b/charset_normalizer-3.4.7-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:733784b6d6def852c814bce5f318d25da2ee65dd4839a0718641c696e09a2960", size = 234851, upload-time = "2026-04-02T09:27:32.44Z" }, - { url = "https://files.pythonhosted.org/packages/9b/40/e5ff04233e70da2681fa43969ad6f66ca5611d7e669be0246c4c7aaf6dc8/charset_normalizer-3.4.7-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:a89c23ef8d2c6b27fd200a42aa4ac72786e7c60d40efdc76e6011260b6e949c4", size = 233393, upload-time = "2026-04-02T09:27:34.03Z" }, - { url = "https://files.pythonhosted.org/packages/be/c1/06c6c49d5a5450f76899992f1ee40b41d076aee9279b49cf9974d2f313d5/charset_normalizer-3.4.7-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6c114670c45346afedc0d947faf3c7f701051d2518b943679c8ff88befe14f8e", size = 223251, upload-time = "2026-04-02T09:27:35.369Z" }, - { url = "https://files.pythonhosted.org/packages/2b/9f/f2ff16fb050946169e3e1f82134d107e5d4ae72647ec8a1b1446c148480f/charset_normalizer-3.4.7-cp314-cp314t-manylinux_2_31_armv7l.whl", hash = "sha256:a180c5e59792af262bf263b21a3c49353f25945d8d9f70628e73de370d55e1e1", size = 206609, upload-time = "2026-04-02T09:27:36.661Z" }, - { url = "https://files.pythonhosted.org/packages/69/d5/a527c0cd8d64d2eab7459784fb4169a0ac76e5a6fc5237337982fd61347e/charset_normalizer-3.4.7-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:3c9a494bc5ec77d43cea229c4f6db1e4d8fe7e1bbffa8b6f0f0032430ff8ab44", size = 220014, upload-time = "2026-04-02T09:27:38.019Z" }, - { url = "https://files.pythonhosted.org/packages/7e/80/8a7b8104a3e203074dc9aa2c613d4b726c0e136bad1cc734594b02867972/charset_normalizer-3.4.7-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:8d828b6667a32a728a1ad1d93957cdf37489c57b97ae6c4de2860fa749b8fc1e", size = 218979, upload-time = "2026-04-02T09:27:39.37Z" }, - { url = "https://files.pythonhosted.org/packages/02/9a/b759b503d507f375b2b5c153e4d2ee0a75aa215b7f2489cf314f4541f2c0/charset_normalizer-3.4.7-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:cf1493cd8607bec4d8a7b9b004e699fcf8f9103a9284cc94962cb73d20f9d4a3", size = 209238, upload-time = "2026-04-02T09:27:40.722Z" }, - { url = "https://files.pythonhosted.org/packages/c2/4e/0f3f5d47b86bdb79256e7290b26ac847a2832d9a4033f7eb2cd4bcf4bb5b/charset_normalizer-3.4.7-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:0c96c3b819b5c3e9e165495db84d41914d6894d55181d2d108cc1a69bfc9cce0", size = 236110, upload-time = "2026-04-02T09:27:42.33Z" }, - { url = "https://files.pythonhosted.org/packages/96/23/bce28734eb3ed2c91dcf93abeb8a5cf393a7b2749725030bb630e554fdd8/charset_normalizer-3.4.7-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:752a45dc4a6934060b3b0dab47e04edc3326575f82be64bc4fc293914566503e", size = 219824, upload-time = "2026-04-02T09:27:43.924Z" }, - { url = "https://files.pythonhosted.org/packages/2c/6f/6e897c6984cc4d41af319b077f2f600fc8214eb2fe2d6bcb79141b882400/charset_normalizer-3.4.7-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:8778f0c7a52e56f75d12dae53ae320fae900a8b9b4164b981b9c5ce059cd1fcb", size = 233103, upload-time = "2026-04-02T09:27:45.348Z" }, - { url = "https://files.pythonhosted.org/packages/76/22/ef7bd0fe480a0ae9b656189ec00744b60933f68b4f42a7bb06589f6f576a/charset_normalizer-3.4.7-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:ce3412fbe1e31eb81ea42f4169ed94861c56e643189e1e75f0041f3fe7020abe", size = 225194, upload-time = "2026-04-02T09:27:46.706Z" }, - { url = "https://files.pythonhosted.org/packages/c5/a7/0e0ab3e0b5bc1219bd80a6a0d4d72ca74d9250cb2382b7c699c147e06017/charset_normalizer-3.4.7-cp314-cp314t-win32.whl", hash = "sha256:c03a41a8784091e67a39648f70c5f97b5b6a37f216896d44d2cdcb82615339a0", size = 159827, upload-time = "2026-04-02T09:27:48.053Z" }, - { url = "https://files.pythonhosted.org/packages/7a/1d/29d32e0fb40864b1f878c7f5a0b343ae676c6e2b271a2d55cc3a152391da/charset_normalizer-3.4.7-cp314-cp314t-win_amd64.whl", hash = "sha256:03853ed82eeebbce3c2abfdbc98c96dc205f32a79627688ac9a27370ea61a49c", size = 174168, upload-time = "2026-04-02T09:27:49.795Z" }, - { url = "https://files.pythonhosted.org/packages/de/32/d92444ad05c7a6e41fb2036749777c163baf7a0301a040cb672d6b2b1ae9/charset_normalizer-3.4.7-cp314-cp314t-win_arm64.whl", hash = "sha256:c35abb8bfff0185efac5878da64c45dafd2b37fb0383add1be155a763c1f083d", size = 153018, upload-time = "2026-04-02T09:27:51.116Z" }, - { url = "https://files.pythonhosted.org/packages/db/8f/61959034484a4a7c527811f4721e75d02d653a35afb0b6054474d8185d4c/charset_normalizer-3.4.7-py3-none-any.whl", hash = "sha256:3dce51d0f5e7951f8bb4900c257dad282f49190fdbebecd4ba99bcc41fef404d", size = 61958, upload-time = "2026-04-02T09:28:37.794Z" }, +version = "3.4.9" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/bd/2a/23f34ec9d04624958e137efdc394888716353190e75f25dd22c7a2c7a8aa/charset_normalizer-3.4.9.tar.gz", hash = "sha256:673611bbd43f0810bec0b0f028ddeaaa501190339cac411f347ac76917c3ae7b", size = 152439, upload-time = "2026-07-07T14:34:58.454Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ad/81/8e983840c6e5b93b33c2ba81aa3d52c2e42f0e9a690ce7607a2e61da4a5c/charset_normalizer-3.4.9-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:cd6280cf040f233bd7d3407b743b4b4c74f70e8e1c4199cb112a62c941c0772a", size = 322240, upload-time = "2026-07-07T14:32:36.236Z" }, + { url = "https://files.pythonhosted.org/packages/de/d1/b4319dc3229d8272fba305e206fc0a148e2de8d4087917ce62ae6382f359/charset_normalizer-3.4.9-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:aa99adc8f081b475a12843953db36831eaf83ec33eb46a90629ca6a5de45a616", size = 216475, upload-time = "2026-07-07T14:32:38.142Z" }, + { url = "https://files.pythonhosted.org/packages/80/33/6c99c1b3e6b8bf730e1bc809b9a2608f224145069114c479a2e9e1494346/charset_normalizer-3.4.9-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:c1225416b463483160e4af85d5fc3a9690ccb53fd4b1865a6437825f5ede3209", size = 238670, upload-time = "2026-07-07T14:32:39.658Z" }, + { url = "https://files.pythonhosted.org/packages/7f/f4/ffbb83546e1f198ecc70ecd372b65cf2b50f9068b380abd67640f17a8e18/charset_normalizer-3.4.9-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:16d10d789dd9bcca1173c95af82c58433122564b7bc39385124be735a35cbe99", size = 233476, upload-time = "2026-07-07T14:32:41.155Z" }, + { url = "https://files.pythonhosted.org/packages/e8/5f/b98b8da398637b551e427e7be922bdec19177dc54d6811dcdaa503f23aac/charset_normalizer-3.4.9-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9bb41182d93ea91f60b4bc8fbf4c820c69ef8a12ab2d917f3f1834f1acad07e8", size = 223817, upload-time = "2026-07-07T14:32:42.592Z" }, + { url = "https://files.pythonhosted.org/packages/36/31/a276bb2e66243072a3fd06fdcab9cbb61a305b02143d70d2bda21d888fa8/charset_normalizer-3.4.9-cp310-cp310-manylinux_2_31_armv7l.whl", hash = "sha256:bcf74c1df76758a395bf0af608c04c82257523f55c9868b334f06270d0f2112b", size = 207974, upload-time = "2026-07-07T14:32:44.258Z" }, + { url = "https://files.pythonhosted.org/packages/5e/be/7ee4453d7e88dfbc4104ccd34900b9f2c7c17dac22881865fe0e82424a25/charset_normalizer-3.4.9-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:b5314963fce9b0b12743891de876e724997864ee22aa496f903f426c7e2fa5b2", size = 221655, upload-time = "2026-07-07T14:32:45.64Z" }, + { url = "https://files.pythonhosted.org/packages/1d/85/181c652953eb5276d198f375b1dd641047392050098100a3a02d6534f657/charset_normalizer-3.4.9-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:e9701d0049d92c16703a42771b98d560b95248949f23f8cf7b4eddd201814fb9", size = 219229, upload-time = "2026-07-07T14:32:47.376Z" }, + { url = "https://files.pythonhosted.org/packages/0c/e7/aaf6da33fc9f4691cda8f7efbc9f69179d3d39ec8a4799baf273ee1d8db0/charset_normalizer-3.4.9-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:65a7ff3f705e57d392f7261b6d0550fe137c3019477431f1c355e0db0a7d3e15", size = 209704, upload-time = "2026-07-07T14:32:48.855Z" }, + { url = "https://files.pythonhosted.org/packages/63/01/f2fb3bd3a73be48b173ee0c6aa8d2497af97d5663a8c4c4b491de4c62f7a/charset_normalizer-3.4.9-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:79580094b00d1789d1f93ea55bc43cb2f611910c72235b7657f3482ddcc1b22d", size = 226243, upload-time = "2026-07-07T14:32:50.239Z" }, + { url = "https://files.pythonhosted.org/packages/c4/02/c57a22739fe05246b0b5783b3bfb6afaac4eebb46f3ececdfb2f048f780e/charset_normalizer-3.4.9-cp310-cp310-win32.whl", hash = "sha256:432786d3561e69aeeae6c7e8648964ce0ad05736120135601f87ac26b9c83381", size = 150935, upload-time = "2026-07-07T14:32:51.676Z" }, + { url = "https://files.pythonhosted.org/packages/37/8d/ca39a7559a4797505530d084fd3a49a2c959efbbbff146302fb7be4e3b35/charset_normalizer-3.4.9-cp310-cp310-win_amd64.whl", hash = "sha256:8c041122946b7ba21bb32c45b1aa57b1be35527690aeb3c5c234521085632eee", size = 162314, upload-time = "2026-07-07T14:32:53.193Z" }, + { url = "https://files.pythonhosted.org/packages/01/da/a44bd7a13d426e69e4894557106cd58669097bfad4a8681123b618fbfc5d/charset_normalizer-3.4.9-cp310-cp310-win_arm64.whl", hash = "sha256:375b83ed0aecfce76c16d198fbc21f3b11b337d68662bea0a995046682a11419", size = 153075, upload-time = "2026-07-07T14:32:54.554Z" }, + { url = "https://files.pythonhosted.org/packages/0b/e3/85ec501f206fb049259288c1f3506e53876937fb00edb47009348e66756b/charset_normalizer-3.4.9-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:0e94703ec9684807f20cfb5eed95c70f67f2a8f21ad620146d7b5a13677b93e5", size = 317075, upload-time = "2026-07-07T14:32:56.021Z" }, + { url = "https://files.pythonhosted.org/packages/c3/69/2a5385192e67175f7d8bd5ce4f57c24bc956439adeae5c13a99aa28a53d1/charset_normalizer-3.4.9-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:2a441ea71902098ffe78c5abe6c494f44160b4af614ed16c3d9a3b1d17fd8ee2", size = 213837, upload-time = "2026-07-07T14:32:57.78Z" }, + { url = "https://files.pythonhosted.org/packages/b3/46/03ddc7da576d814fe0a36dd1f0fd3258e95404b4b2e3c026b7923d7e133f/charset_normalizer-3.4.9-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:304b13570067b2547562e308af560b3963857b1fa90bd6afd978130130fe2d6a", size = 235503, upload-time = "2026-07-07T14:32:59.205Z" }, + { url = "https://files.pythonhosted.org/packages/4e/6e/de0229a7ef40f6f9d28a837eebf4ec47bdca5dab4e900c84f22919af636a/charset_normalizer-3.4.9-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:4773092f8019072343a7447203308b176e10199920eb02d6195e81bbb3274c29", size = 229944, upload-time = "2026-07-07T14:33:00.803Z" }, + { url = "https://files.pythonhosted.org/packages/a5/34/49b9060e8418b14fb5cba9cf6bfb383111e2538a03a1fb18e66a95aeb3d5/charset_normalizer-3.4.9-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:04ce310cb89c15df659582aee80a0603788732a5e017d5bd5c81158106ce249c", size = 221276, upload-time = "2026-07-07T14:33:02.199Z" }, + { url = "https://files.pythonhosted.org/packages/44/95/80282cce0fae9c3061203d723ee87da996aed79679e65d8935050ee7ca1f/charset_normalizer-3.4.9-cp311-cp311-manylinux_2_31_armv7l.whl", hash = "sha256:c0323c9daef75ef2e5083624b4585018a0c9d5e3b40f607eed81a311270b934b", size = 205260, upload-time = "2026-07-07T14:33:03.698Z" }, + { url = "https://files.pythonhosted.org/packages/0c/74/2f62c8821b969ea3bd67cc2e6976834f48ca5d12664d2559ebcd9bcfbed7/charset_normalizer-3.4.9-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:871ff67ea1aad4dfd91736464934d56b32dac49f9fbe16cddba36198a7b3a0db", size = 217786, upload-time = "2026-07-07T14:33:05.12Z" }, + { url = "https://files.pythonhosted.org/packages/d9/8d/feabb82cb49fcad14515b1d7d1ca4787b0da7fc723a212bf89bc9e0fac52/charset_normalizer-3.4.9-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:67830fc78e67501f47bb950471b2dcb9b35b140084429318e862895a8e89c993", size = 216798, upload-time = "2026-07-07T14:33:06.629Z" }, + { url = "https://files.pythonhosted.org/packages/a5/ff/c946d63bc3786d5b84d960b0f7ab7e25b828486a946b5aa997625bcaf6a6/charset_normalizer-3.4.9-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:3d92613ec25e43b05f042302531ec0f00b8445190e43325880cbd6ab7c2581da", size = 206429, upload-time = "2026-07-07T14:33:08.006Z" }, + { url = "https://files.pythonhosted.org/packages/af/ba/5e5007c370702f85d2ef75791fac7943ed41e080364a673b20142e430e3e/charset_normalizer-3.4.9-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:280081916dc341820640489a66e4696049401ef1cf6dd672f672e70ad915aca3", size = 223066, upload-time = "2026-07-07T14:33:09.783Z" }, + { url = "https://files.pythonhosted.org/packages/83/d5/9096aa3cf532dfad237861544eb47a0f20d5adbf1039760fed8eaae935d9/charset_normalizer-3.4.9-cp311-cp311-win32.whl", hash = "sha256:ac351b3b8014eead140e77e9717e2992c6bbe30b63bc3422422eb84865412e3d", size = 150456, upload-time = "2026-07-07T14:33:11.217Z" }, + { url = "https://files.pythonhosted.org/packages/ed/a1/e29995109e455dc8eff8d0fac6ae509be39561318a7cfeac5d33ad029213/charset_normalizer-3.4.9-cp311-cp311-win_amd64.whl", hash = "sha256:6366a16e1a25018694d6a5d784d09b046edc9eac40ea2b54065c3052672516a1", size = 161410, upload-time = "2026-07-07T14:33:12.743Z" }, + { url = "https://files.pythonhosted.org/packages/4f/8d/1569f4d0032d6ba2a4fe4591c35bf87868c600c41a71eb5c2e1ffa8464c2/charset_normalizer-3.4.9-cp311-cp311-win_arm64.whl", hash = "sha256:1d22856ffbe153a602df38e4a5464f0b748a54002e0d69ac6d2ad0a197cc99ec", size = 152649, upload-time = "2026-07-07T14:33:14.173Z" }, + { url = "https://files.pythonhosted.org/packages/70/4a/ecbd131485c07fcdfad54e28946d513e3da22ef3b4bd854dcafae54ec739/charset_normalizer-3.4.9-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:45b0cc4e3556cd875e09102988d1ab8356c998b596c9fced84547c8138b487a0", size = 319300, upload-time = "2026-07-07T14:33:15.666Z" }, + { url = "https://files.pythonhosted.org/packages/ec/96/5d9364e3342d69f3a045e1777bc47c85c383e6e9466d561b33fdb419d1f9/charset_normalizer-3.4.9-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:9b2aff1c7b3884512b9512c3eaadd9bab39fb45042ffaaa1dd08ff2b9f8109d9", size = 215802, upload-time = "2026-07-07T14:33:17.031Z" }, + { url = "https://files.pythonhosted.org/packages/4b/4c/5361f9aa7f2cb58d94f2ab831b3d493f69efb1d239654b4744e3c09527cb/charset_normalizer-3.4.9-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:9104ed0bd76a429d46f9ec0dbc9b08ad1d2dcdf2b00a5a0daa1c145329b35b44", size = 237171, upload-time = "2026-07-07T14:33:18.576Z" }, + { url = "https://files.pythonhosted.org/packages/50/78/ce342ca4ff30b2eb49fe6d9578df85974f90c67d294113e94efdd9664cbd/charset_normalizer-3.4.9-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:7b86a2b16095d250c6f58b3d9b2eee6f4147754344f3dab0922f7c9bf7d226c9", size = 233075, upload-time = "2026-07-07T14:33:20.084Z" }, + { url = "https://files.pythonhosted.org/packages/01/c4/4fa4c8b3097a11f3c5f09a35b72ed6855fb1d332469504962ab7bafcc702/charset_normalizer-3.4.9-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5e226f6218febc71f6c1fc2fafb91c226f75bdc1d8fb12d66823716e891608fd", size = 224256, upload-time = "2026-07-07T14:33:21.747Z" }, + { url = "https://files.pythonhosted.org/packages/87/3a/ad914516df7e358a81aae018caa5e0470ba827fa6d763b1d2e87d920a5f6/charset_normalizer-3.4.9-cp312-cp312-manylinux_2_31_armv7l.whl", hash = "sha256:90c44bc373b7687f6948b693cceaea1348ae0975d7474746559494468e3c1d84", size = 208784, upload-time = "2026-07-07T14:33:23.313Z" }, + { url = "https://files.pythonhosted.org/packages/d7/74/3c12f9755717dfe5c5c87da63f35d765fa0c00382ec26bf23f7fae34f2ba/charset_normalizer-3.4.9-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:9cdef90ae47919cae358d8ab15797a800ed41da7aba5d72419fb510729e2ed4b", size = 219928, upload-time = "2026-07-07T14:33:24.814Z" }, + { url = "https://files.pythonhosted.org/packages/33/9a/895095b83e7907abd6d3d99aad3a38ad0d9686cc186cb0c94c24320fe63e/charset_normalizer-3.4.9-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:60f44ade2cf573dad7a277e6f8ca9a51a21dda572b13bd7d8539bb3cd5dbedde", size = 218489, upload-time = "2026-07-07T14:33:26.42Z" }, + { url = "https://files.pythonhosted.org/packages/a1/34/ef5c05f412f42520d7709b7d3784d19640839eb7366ded1755511585429f/charset_normalizer-3.4.9-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:a1786910334ed46ab1dd73222f2cd1e05c2c3bb39f6dddb4f8b36fc382058a39", size = 210267, upload-time = "2026-07-07T14:33:27.952Z" }, + { url = "https://files.pythonhosted.org/packages/83/dc/9b29fa4412b318bf3bfea985c35d67eb55e04b59a7c3f2237168b0e0be6f/charset_normalizer-3.4.9-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:03d07803992c6c7bbc976327f34b18b6160327fc81cb82c9d504720ac0be3b62", size = 226030, upload-time = "2026-07-07T14:33:29.397Z" }, + { url = "https://files.pythonhosted.org/packages/0e/42/6dbc00b8cd16011691203e33570fa42ed5746599a2e878112d16eab403a3/charset_normalizer-3.4.9-cp312-cp312-win32.whl", hash = "sha256:78841cccf1af7b40f6f716338d50c0902dbe88d9f800b3c973b7a9a0a693a642", size = 151185, upload-time = "2026-07-07T14:33:30.781Z" }, + { url = "https://files.pythonhosted.org/packages/80/cc/f920afd1a23c58ccd53c1d36085a71893a4737ff5e66e0371efab6809850/charset_normalizer-3.4.9-cp312-cp312-win_amd64.whl", hash = "sha256:4b3dac63058cc36820b0dd072f89898604e2d39686fe05321729d00d8ac185a0", size = 162557, upload-time = "2026-07-07T14:33:32.176Z" }, + { url = "https://files.pythonhosted.org/packages/f0/e6/0386d43a261ff4e4b30c5857af7df877254b46bec7b9d1b74b6bf969a90b/charset_normalizer-3.4.9-cp312-cp312-win_arm64.whl", hash = "sha256:78fa18e436a1a0e58dbd7e02fc4473f3f32cceb12df9dfca542d075961c307d2", size = 152665, upload-time = "2026-07-07T14:33:33.711Z" }, + { url = "https://files.pythonhosted.org/packages/b2/06/97ec2aeae780b31d742b6352218b43841a6871e2564578ca522dce4a45c3/charset_normalizer-3.4.9-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:440eede837960000d74978f0eba527be106b5b9aee0daf779d395276ed0b0614", size = 317688, upload-time = "2026-07-07T14:33:35.408Z" }, + { url = "https://files.pythonhosted.org/packages/d0/39/8ff066c672434225f8d25f8b739f992af250944392173dcc88362681c9bf/charset_normalizer-3.4.9-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:21e764fd1e70b6a3e205a0e46f3051701f98a8cb3fad66eeb80e48bb502f8698", size = 214982, upload-time = "2026-07-07T14:33:36.996Z" }, + { url = "https://files.pythonhosted.org/packages/92/8f/3a47a3667c83c2df9483d91644c6c107de3bf8874aa1793da9d3012eb986/charset_normalizer-3.4.9-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:e4fd89cc178bced6ad29cb3e6dd4aa63fa5017c3524dbd0b25998fb64a87cc8b", size = 236460, upload-time = "2026-07-07T14:33:38.536Z" }, + { url = "https://files.pythonhosted.org/packages/f1/60/b22cdbee7e4013dab8b0d7647fc6181120fbbbc8f7025c226d15bd5a47fc/charset_normalizer-3.4.9-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:bd47ba7fc3ca94896759ea0109775132d3e7ab921fbf54038e1bab2e46c313c9", size = 232003, upload-time = "2026-07-07T14:33:40.059Z" }, + { url = "https://files.pythonhosted.org/packages/ea/f8/72eb13dcabe7257035cea8aefd922caad2f110d252bf9f67c4c2ca763aee/charset_normalizer-3.4.9-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:84fd18bcc17526fc2b3c1af7d2b9217d32c9c04448c16ec693b9b4f1985c3d33", size = 223149, upload-time = "2026-07-07T14:33:41.631Z" }, + { url = "https://files.pythonhosted.org/packages/b0/3e/faee8f9de92b14ee1198e9163252bb15efee7301b31256a3b6d9ebfdd0dd/charset_normalizer-3.4.9-cp313-cp313-manylinux_2_31_armv7l.whl", hash = "sha256:5b10cd92fc5c498b35a8635df6d5a100207f88b63a4dc1de7ef9a548e1e2cd63", size = 207901, upload-time = "2026-07-07T14:33:43.209Z" }, + { url = "https://files.pythonhosted.org/packages/3a/25/45f30093ae27dd7b92a793b61882a38685f993700113ca36e0c9c14965e1/charset_normalizer-3.4.9-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:a4fbdde9dd4a9ce5fd52c2b3a347bb50cc89483ef783f1cb00d408c13f7a96c0", size = 219176, upload-time = "2026-07-07T14:33:44.725Z" }, + { url = "https://files.pythonhosted.org/packages/48/18/c8f397329c35e32f6a837e488986f4ae03bd2abebc453b48714991630c2f/charset_normalizer-3.4.9-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:416c229f77e5ea25b3dfd4b582f8d73d7e43c22320302b9ab128a2d3a0b38efe", size = 217356, upload-time = "2026-07-07T14:33:46.192Z" }, + { url = "https://files.pythonhosted.org/packages/86/7e/5ce0bba863470fd1902d5e5843968951bddf38abe4742fc97116ef4598b3/charset_normalizer-3.4.9-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:75286256590a6320cf106a0d28970d3560aad9ee09aa7b34fb40524792436d35", size = 209614, upload-time = "2026-07-07T14:33:47.705Z" }, + { url = "https://files.pythonhosted.org/packages/6c/ef/2473d3c4d869155be4af1191111d59c4d5c4e0173026f7e85b176e23bf65/charset_normalizer-3.4.9-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:69b157c5d3292bcd443faca052f3096f637f1e074b98212a933c074ae23dc3b8", size = 224991, upload-time = "2026-07-07T14:33:49.238Z" }, + { url = "https://files.pythonhosted.org/packages/d0/a3/53ddae3db108a088156aa8ddfafd411ebbc1340f48c5573f697b27f69a39/charset_normalizer-3.4.9-cp313-cp313-win32.whl", hash = "sha256:51307f5c71007673a2bf8232ad973483d281e74cb99c8c5a990af1eefa6277d9", size = 150622, upload-time = "2026-07-07T14:33:50.711Z" }, + { url = "https://files.pythonhosted.org/packages/e8/ef/6953a77c7cf2c2ff9998e6f575ab3e380119f100223381565a4f94c1f836/charset_normalizer-3.4.9-cp313-cp313-win_amd64.whl", hash = "sha256:fe2c7201c642b7c308f1675355ad7ff7b66acfe3541625efe5a3ad38f29d6115", size = 161947, upload-time = "2026-07-07T14:33:52.197Z" }, + { url = "https://files.pythonhosted.org/packages/6e/fb/d560d1d1555debbfe7849d9cac6145c1b537709d79576bf22557ed803b82/charset_normalizer-3.4.9-cp313-cp313-win_arm64.whl", hash = "sha256:611057cc5d5c0afc743ba8be6bd828c17e0aaa8643f9d0a9b9bb7dea80eb8012", size = 152594, upload-time = "2026-07-07T14:33:53.486Z" }, + { url = "https://files.pythonhosted.org/packages/7e/8d/496817fa0944239ecae662dd57ea765cfeaec6a735f9f025d4b7b72e7143/charset_normalizer-3.4.9-cp314-cp314-macosx_10_15_universal2.whl", hash = "sha256:0327fcd59a935777d83410750c50600ee9571af2846f71ce40f25b13da1ef380", size = 317253, upload-time = "2026-07-07T14:33:54.994Z" }, + { url = "https://files.pythonhosted.org/packages/2b/f9/ef4a69ea338ad3c0deceea0f5f7d2380ae8b52132b06d652cb0d2cd86706/charset_normalizer-3.4.9-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8a79d9f4d8001473a30c163556b3c3bfebec837495a412dde78b51672f6134f9", size = 215898, upload-time = "2026-07-07T14:33:56.334Z" }, + { url = "https://files.pythonhosted.org/packages/8c/e7/5ddfd76fc061eb52de219658a4aa431cbacadf0a0219c8854f00da50d289/charset_normalizer-3.4.9-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:33bdcc2a32c0a0e861f60841a512c8acc658c87c2ac59d89e3a46dacf7d866e4", size = 236718, upload-time = "2026-07-07T14:33:57.9Z" }, + { url = "https://files.pythonhosted.org/packages/49/ba/768fa3f36048d81c477a0ce61f813bc1454d80917ccfe550abd9f44f5e24/charset_normalizer-3.4.9-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:f840ed6d8ecba8255df8c42b87fadeda98ddfc6eeec05e2dc66e26d46dd6f58a", size = 232519, upload-time = "2026-07-07T14:33:59.811Z" }, + { url = "https://files.pythonhosted.org/packages/f4/c4/b3e049d2aa3766180c78507110543d9d50894cc97f57de543f1be521dcdc/charset_normalizer-3.4.9-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c25fe15c70c59eb7c5ce8c06a1f3fa1da0ecc5ea1e7a5922c40fd2fa9b0d5046", size = 223143, upload-time = "2026-07-07T14:34:01.517Z" }, + { url = "https://files.pythonhosted.org/packages/19/79/55c32d06d76ae4feafe053f061f3e3ab70bcf19f4007797ce8c3efda7830/charset_normalizer-3.4.9-cp314-cp314-manylinux_2_31_armv7l.whl", hash = "sha256:f7fb7d750cfa0a070d2c24e831fd3481019a60dd317ea2b39acbcebc08b6ed81", size = 206742, upload-time = "2026-07-07T14:34:03.04Z" }, + { url = "https://files.pythonhosted.org/packages/10/e0/47c079dd82d217c807479cd59ffd30af56307ea31c108b75758970459ad3/charset_normalizer-3.4.9-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:4d1c96a7a18b9690a4d46df09e3e3382406ae3213727cd1019ebade1c4a81917", size = 219191, upload-time = "2026-07-07T14:34:04.657Z" }, + { url = "https://files.pythonhosted.org/packages/42/ab/b9bc2e77d6b44a7e46ef62ec5cac1c9a6ba7b9135a5d560f002696ec9995/charset_normalizer-3.4.9-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:a4cfde78a9f2880208d16a93b795726a3017d5977e08d1e162a7a31322479c41", size = 218328, upload-time = "2026-07-07T14:34:06.115Z" }, + { url = "https://files.pythonhosted.org/packages/f1/78/c9c71d599f5aa2d42bcdd35cbbd46d7f535351a57e40ff7d8e5a7e219401/charset_normalizer-3.4.9-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:d4d6fcde76f94f5cb9e43e9e9a61f16dacefd228cbbf6f1a09bd9b219a92f1a1", size = 207406, upload-time = "2026-07-07T14:34:07.554Z" }, + { url = "https://files.pythonhosted.org/packages/f6/39/c914445c321a845097ce4f6ac7de9a18228a77b766272125a1ce00d851eb/charset_normalizer-3.4.9-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:898f0e9068ca27d37f8e83a5b962821df851532e6c4a7d615c1c033f9da6eedf", size = 225157, upload-time = "2026-07-07T14:34:09.061Z" }, + { url = "https://files.pythonhosted.org/packages/9b/f2/c0d4b8508565a36bc5c624e88ed297f5b0b1095011034d7f5b83a69908b5/charset_normalizer-3.4.9-cp314-cp314-win32.whl", hash = "sha256:c1c948747b03be832dceed96ca815cef7360de9aa19d37c730f8e3f6101aca48", size = 151095, upload-time = "2026-07-07T14:34:10.901Z" }, + { url = "https://files.pythonhosted.org/packages/49/fd/a1d26144398c67486422a72bf5812cda22cb4ccfcd95a290fb41ceb4b8e2/charset_normalizer-3.4.9-cp314-cp314-win_amd64.whl", hash = "sha256:16b65ea0f2465b6fb52aa22de5eca612aa964ddfec00a912e26f4656cbef890b", size = 162796, upload-time = "2026-07-07T14:34:12.47Z" }, + { url = "https://files.pythonhosted.org/packages/20/95/d75e82f8ce9fd323ebf059c16c9aadefb22a1ecde13b7840b35835e4886c/charset_normalizer-3.4.9-cp314-cp314-win_arm64.whl", hash = "sha256:40a126142a56b2dfc0aacbad1de8310cbf60da7656db0e6b16eebd48e3e93519", size = 153334, upload-time = "2026-07-07T14:34:14.044Z" }, + { url = "https://files.pythonhosted.org/packages/00/5e/17398df3a139985ba9d11ed072531986f408c8fca952835ef1ab1820c02b/charset_normalizer-3.4.9-cp314-cp314t-macosx_10_15_universal2.whl", hash = "sha256:609b3ba8fcc0fb5ab7af00719d0fb6ad0cb518e48e7712d12fd68f1327951198", size = 338848, upload-time = "2026-07-07T14:34:15.688Z" }, + { url = "https://files.pythonhosted.org/packages/cd/91/7253a32e86b7e1d1239b1b36ba6dd0f021a21107ab33054b53119cc083b9/charset_normalizer-3.4.9-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:51447e9aa2684679af07ca5021c3db526e0284347ebf4ffcec1154c3350cfe32", size = 223022, upload-time = "2026-07-07T14:34:17.248Z" }, + { url = "https://files.pythonhosted.org/packages/cb/32/2e64bd2be10e89c61e57ebe6a93fd98ae88eb7ebe414b5121f22c96c69eb/charset_normalizer-3.4.9-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:cc1b0fff8ead343dae06305f954eb8468ba0ec1a97881f42489d198e4ce3c632", size = 241590, upload-time = "2026-07-07T14:34:18.813Z" }, + { url = "https://files.pythonhosted.org/packages/3d/ef/d96ec496cfea0c21db43b0ad03891308b02388d054cc902cf0e5a1ad6a88/charset_normalizer-3.4.9-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:fa36ec09ef71d158186bc79e359ff5fdd6e7996fe8ab638f00d6b93139ba4fcf", size = 239584, upload-time = "2026-07-07T14:34:20.52Z" }, + { url = "https://files.pythonhosted.org/packages/d4/ce/9af95f7876194bd7a14e3dfe4a4de2e0bff02666a3910d72beafd06cc297/charset_normalizer-3.4.9-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:df115d4d83168fdf2cae48ef1ff6d1cb4c466364e30861b37121de0f3bf1b990", size = 230224, upload-time = "2026-07-07T14:34:22.189Z" }, + { url = "https://files.pythonhosted.org/packages/52/94/af74dde74a3996bd959c350709bfe50e297823d70a8c1cbd54b838880863/charset_normalizer-3.4.9-cp314-cp314t-manylinux_2_31_armv7l.whl", hash = "sha256:f86c6358749bd4fda175388691e3ba8c46e24c5347d0afd20f9b7edfc9faf07d", size = 212667, upload-time = "2026-07-07T14:34:23.857Z" }, + { url = "https://files.pythonhosted.org/packages/ee/f0/f1c4fe746c395922961b5916ed1d7d6e7d4c84851d19ed43cc89980ec953/charset_normalizer-3.4.9-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:32286a2c8d167e897177b673176c1e3e00d4057caf5d2b64eef9a3666b03018e", size = 227179, upload-time = "2026-07-07T14:34:25.586Z" }, + { url = "https://files.pythonhosted.org/packages/e4/56/6c745619ac397e8871e2bcd3cea1eec86b877488f33888b3aef5c3ed506e/charset_normalizer-3.4.9-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:83aed2c10721ddd90f68140685391b50811a880af20654c59af6b6c66c40513c", size = 225372, upload-time = "2026-07-07T14:34:27.212Z" }, + { url = "https://files.pythonhosted.org/packages/78/ad/98aae8630ac71f16711968e38a5acfecce41b778bf2f0312851020f565a8/charset_normalizer-3.4.9-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:cd6c3d4b783c556fa00bf540854e42f135e2f256abd29669fcd0da0f2dec79c2", size = 215222, upload-time = "2026-07-07T14:34:28.774Z" }, + { url = "https://files.pythonhosted.org/packages/f7/40/9593d54209765207a7f11073c06494c1721e4ca4a0a426c597679bf7f91e/charset_normalizer-3.4.9-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:ee2f2a527e3c1a6e6411eb4209642e138b544a2d72fe5d0d76daf77b24063534", size = 231958, upload-time = "2026-07-07T14:34:30.345Z" }, + { url = "https://files.pythonhosted.org/packages/b1/27/693ee5e8a18191eb38647360c51cd505013e2bd3b366aa43fd5344c21e3c/charset_normalizer-3.4.9-cp314-cp314t-win32.whl", hash = "sha256:0d861473f743244d349b50f850d10eb87aeb22bbdcc8e64f79273c94af5a8226", size = 155580, upload-time = "2026-07-07T14:34:31.884Z" }, + { url = "https://files.pythonhosted.org/packages/80/3f/bd97d3d9c613013d07cb7733d299385b41df37f0471310f5a73dc359f0b8/charset_normalizer-3.4.9-cp314-cp314t-win_amd64.whl", hash = "sha256:9b8e0f3107e2200b76f6054de99016eac3ee6762713587b36baaa7e4bd2ae177", size = 167620, upload-time = "2026-07-07T14:34:33.438Z" }, + { url = "https://files.pythonhosted.org/packages/3d/c6/eee9dca4439b1061f76373f06ea855678cc4a64c1c3c90b50e479edbb8eb/charset_normalizer-3.4.9-cp314-cp314t-win_arm64.whl", hash = "sha256:19ac87f93086ce37b86e098888555c4b4bc48102279bae3350098c0ed664b501", size = 158037, upload-time = "2026-07-07T14:34:35.018Z" }, + { url = "https://files.pythonhosted.org/packages/98/2b/f97f1c193fb855c345d678f5077d6926034db0722df74c8f057020e05a25/charset_normalizer-3.4.9-py3-none-any.whl", hash = "sha256:68e5f26a1ad57ded6d1cfb85331d1c1a195314756471d97758c48498bb4dcdf5", size = 64538, upload-time = "2026-07-07T14:34:56.993Z" }, ] [[package]] @@ -711,14 +721,14 @@ wheels = [ [[package]] name = "click" -version = "8.4.1" +version = "8.4.2" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "colorama", marker = "sys_platform == 'win32'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/9b/98/518d8e5081007684232226f475082b30087d0f585e8457db087298259f49/click-8.4.1.tar.gz", hash = "sha256:918b5633eddf6b41c32d4f454bf0de810065c74e3f7dbf8ee5452f8be88d3e96", size = 353007, upload-time = "2026-05-22T04:08:37.769Z" } +sdist = { url = "https://files.pythonhosted.org/packages/76/d4/81420972a676e8ffea40450d8c8c92943e7218a78fe9b64359836cc9876b/click-8.4.2.tar.gz", hash = "sha256:9a6cea6e60b17ebe0a44c5cc636d94f09bd66142c1cd7d8b4cd731c4917a15f6", size = 338000, upload-time = "2026-06-24T17:45:15.148Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/c7/0d/67e5b4109ea4a837e80daa87c2c696711955e40449a97e8926672534def2/click-8.4.1-py3-none-any.whl", hash = "sha256:482be17c6991b8c19c5429a1e995d9b0efdbb63172824c41f99965dc0ade8ec2", size = 116639, upload-time = "2026-05-22T04:08:35.26Z" }, + { url = "https://files.pythonhosted.org/packages/fb/e2/79c688af8b210d232694e31e59da9f6ec747bae31c3f5946e4e9b98860d5/click-8.4.2-py3-none-any.whl", hash = "sha256:e6f9f66136c816745b9d65817da91d61d957fb16e02e4dcd0552553c5a197b76", size = 119243, upload-time = "2026-06-24T17:45:13.73Z" }, ] [[package]] @@ -750,115 +760,100 @@ wheels = [ [[package]] name = "coverage" -version = "7.14.1" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/54/fd/0ab2772530e946e1be1abd0bc09e647ec9b02e88f0867857601fefca8953/coverage-7.14.1.tar.gz", hash = "sha256:30c08f7d90415aa98b3c990385dea2939b0da55f38515e5b369b83655f8523be", size = 920132, upload-time = "2026-05-26T20:41:36.783Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/92/69/0d2ef01ff4b8fcecd4cba920d11e92fa4f96ae412441d3b56a90a258e69b/coverage-7.14.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:3e3680291c4a1d0dadfa84a2c459576a4af5133abb617905714339a0c73138cf", size = 219722, upload-time = "2026-05-26T20:38:14.002Z" }, - { url = "https://files.pythonhosted.org/packages/f8/ae/9afdeaa31b9d9ce98124b6abf8bb49119bf71aecae04f8567c189d91299f/coverage-7.14.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:a5274669f37f2343635a347b91a60777621341ab3378e9c6ac9335eee704bddf", size = 220240, upload-time = "2026-05-26T20:38:17.424Z" }, - { url = "https://files.pythonhosted.org/packages/51/69/c998589871df7ea7dba865cc5ee32b5a3e1d47ba6c68ef91104c7c46fa5e/coverage-7.14.1-cp310-cp310-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:cfe5a5fec635799ef33428f1e5e61bafa45a92a96190ba731561ba558ccc214d", size = 246981, upload-time = "2026-05-26T20:38:19.266Z" }, - { url = "https://files.pythonhosted.org/packages/fc/10/1c7d04c13040dac531d21b712bbe08f902e6dd9b58f5d77875c4d030f8f2/coverage-7.14.1-cp310-cp310-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:62a9f70b52e0b5a95cfef4a5c5641b06983cadc5e538a3feeb5c00211f523ac2", size = 248812, upload-time = "2026-05-26T20:38:20.75Z" }, - { url = "https://files.pythonhosted.org/packages/c1/65/2a38a4607ef27cadcfbcee034dba5830ae2569f90144a0f4c7dbf47d30b0/coverage-7.14.1-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3c18ebc343e15be53049b3a2dce38fe82d58f37e20ab9094b3a39c0aa4f6bb47", size = 250675, upload-time = "2026-05-26T20:38:22.159Z" }, - { url = "https://files.pythonhosted.org/packages/c9/a2/a446ed9752a4a59b79e0fb6cbb319f6facb2183045c0725462625e66f87e/coverage-7.14.1-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:b84ffdf877644e7096aa936991efeed873f7f3df57b9cd001312b7668ab08550", size = 252590, upload-time = "2026-05-26T20:38:23.63Z" }, - { url = "https://files.pythonhosted.org/packages/9e/fd/e81fbd7ba752365546e9842b1cbdaad3d6919d2a522c590aef16a281ec5e/coverage-7.14.1-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:e854312c4103f2ad4c0dc023b69b77ebfd2c89db5f86c4c94dc2353f9a92167e", size = 247691, upload-time = "2026-05-26T20:38:25.057Z" }, - { url = "https://files.pythonhosted.org/packages/53/35/f3c26fdaae9ea937d154ca4d372e5ea0a4167ff70d36c6074ac2eacb2f83/coverage-7.14.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:c643734307300234fafa36bf2a040a7235f8f177ea1fd6ec1423aea6fb7b929f", size = 248716, upload-time = "2026-05-26T20:38:26.406Z" }, - { url = "https://files.pythonhosted.org/packages/2e/14/940b6c49551fd343e8507ee2b0ba7af5d0aa04ed5bf768285cb7c72a9884/coverage-7.14.1-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:84ac9499e48700399a5dd0ea7085b5091961fec52c68d66b4ec0d3cf7f4441b1", size = 246721, upload-time = "2026-05-26T20:38:28.282Z" }, - { url = "https://files.pythonhosted.org/packages/aa/2c/40fc0634186c28292a662dff578866b3913983d6c375a3c2a74020938719/coverage-7.14.1-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:7f02d09f70776579b926d889a4c9c235070a1f47c40458aeaca563fae5acfdb5", size = 250533, upload-time = "2026-05-26T20:38:29.753Z" }, - { url = "https://files.pythonhosted.org/packages/de/e3/2c26bf1e811f9df991ff2a9bdddebdd13ee0665d564df7d05979f9146297/coverage-7.14.1-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:ce66d8e46da2bb5ee313a745cbd2e391d319176c1f7a9451bfcd3a2fb920859b", size = 246990, upload-time = "2026-05-26T20:38:31.516Z" }, - { url = "https://files.pythonhosted.org/packages/a8/b0/060260ef56bd92363ebdce0c7095ce422b06e69aae71828efeca473ab1ca/coverage-7.14.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:c912c259304cfb5ee584481cfb7ce1ff932b4d61e6c9140b8f19cb7b5ed82332", size = 247593, upload-time = "2026-05-26T20:38:33.065Z" }, - { url = "https://files.pythonhosted.org/packages/63/f3/501502046efeb0d6d94b5ca54941d95f1184183dd6bdb7f283985783bb4a/coverage-7.14.1-cp310-cp310-win32.whl", hash = "sha256:1238cb94638e610e972c60dac68e813f868dc7d6e982535270558443058d9d59", size = 222330, upload-time = "2026-05-26T20:38:35.36Z" }, - { url = "https://files.pythonhosted.org/packages/a0/5d/1bf99f2c558f128faf7906817ccbdb576ba815d3b41ce2ac1719b70a3663/coverage-7.14.1-cp310-cp310-win_amd64.whl", hash = "sha256:fc459e5d73be2d6332fcfe8dbf3d8994671fe33c700f4565988ecfa511547253", size = 223261, upload-time = "2026-05-26T20:38:37.196Z" }, - { url = "https://files.pythonhosted.org/packages/7d/d7/477ad149490e6cb849f28abea1dabb9c823cea72e7500c81b4240ce619c0/coverage-7.14.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:478b5bcd63c2e1357c5c7e16c070690df7b07f676b1c114d7b93e533c664309f", size = 219848, upload-time = "2026-05-26T20:38:38.715Z" }, - { url = "https://files.pythonhosted.org/packages/91/82/a5eb47257c50601bb7b9a9d2857c67b7a3a85ad74180eb2c98bb1fbe0ce5/coverage-7.14.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:a24a81f9715ee42ef59a316cc11611c98fe23920f7c81861315c9f3ff4a230f4", size = 220354, upload-time = "2026-05-26T20:38:40.232Z" }, - { url = "https://files.pythonhosted.org/packages/43/8b/78419b5391a5cb706b6544390507e469d83ffc9a8248b02c4011aceb9365/coverage-7.14.1-cp311-cp311-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:196a13319ad88d6d8ef5ab489ec4f44ddde2143c0c7d5b27786f6c3ffd56a7e1", size = 250771, upload-time = "2026-05-26T20:38:41.782Z" }, - { url = "https://files.pythonhosted.org/packages/77/63/e77aaacd491182210d639636b7a8bba23ffffa9b82aa3762da9431855fa9/coverage-7.14.1-cp311-cp311-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:3d452fd08b5c72c5167c93e6867b5c08500bd40f2a21e1e854a500550b6cc36f", size = 252683, upload-time = "2026-05-26T20:38:43.305Z" }, - { url = "https://files.pythonhosted.org/packages/65/1c/a022e3cfbec2ac241640003cb3a817e161d9c7f5aa9b49173756cdc03204/coverage-7.14.1-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:23bf7fa51ac02e07fc7c96849b82946da47ae862dc8f86d183b2a4864fc38129", size = 254791, upload-time = "2026-05-26T20:38:45.361Z" }, - { url = "https://files.pythonhosted.org/packages/61/d6/967e408aca4c1ceb88cb0cc677169110ae7f5995fb5eaf5fb1f5a1bb8f5d/coverage-7.14.1-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:bcaa50684dcaadfa599ac48f81103c756d791cfd85c97203d2217c593d48b860", size = 256748, upload-time = "2026-05-26T20:38:46.91Z" }, - { url = "https://files.pythonhosted.org/packages/b8/be/869188f7fe28638078ec479331ace6dc5f7b40b7153eb616f47ab79404d8/coverage-7.14.1-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:4ea1c034f95c9b056e856b794630b17f9fa3d57e4800ff1e503d3be0f9c9078c", size = 250907, upload-time = "2026-05-26T20:38:48.493Z" }, - { url = "https://files.pythonhosted.org/packages/07/aa/adb7d3b4278d690e68703abcd76ab1b948242e3668d921711551b78f9ddb/coverage-7.14.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:c7e057326434e441306226fbeb5d1aaf14a2637efe97ba668306635835f32ad7", size = 252483, upload-time = "2026-05-26T20:38:50.074Z" }, - { url = "https://files.pythonhosted.org/packages/43/61/331c74103c62dcb0c4b9b3a0de9a61aca016208b0a90f109592a9f9ecc28/coverage-7.14.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:59baf88468dbc8d63b1887afd92bda52e40bb1561696e5819670601403810cec", size = 250545, upload-time = "2026-05-26T20:38:51.613Z" }, - { url = "https://files.pythonhosted.org/packages/f6/b6/c5dae3c104d89be04828f61810e6b3473825482e4c288cc4ed04553e08ae/coverage-7.14.1-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:d34d75f892b3ab73ba11cab5442cce7b3e168fd64162b16f0e1e0d09c508edef", size = 254310, upload-time = "2026-05-26T20:38:53.503Z" }, - { url = "https://files.pythonhosted.org/packages/ad/a1/2b9d5863e3b83c01ad8199e3c597802fbb3a9dc90b058885804c20296d31/coverage-7.14.1-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:3a56abc20a472baf0304c455721bc601477440d28ecfde8a03dde79ede07e0df", size = 250266, upload-time = "2026-05-26T20:38:55.414Z" }, - { url = "https://files.pythonhosted.org/packages/7f/5e/0e511fbdb269359be26fe678a1c3fa1f2aa2a01573cc3f54268c8d6d4797/coverage-7.14.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:6a3cb83d1552c0cd1b4906655b6a33fd4a8473229633a901c6b73bf86914dee9", size = 251174, upload-time = "2026-05-26T20:38:57.141Z" }, - { url = "https://files.pythonhosted.org/packages/85/10/e55307b622b3dd9671cb321824502dc10f93e72f2802b9946159a8edadeb/coverage-7.14.1-cp311-cp311-win32.whl", hash = "sha256:10274a1fbeb8ec5d72966e17bb198a3104257aca4ac09d98667c5f8aca8c8548", size = 222354, upload-time = "2026-05-26T20:38:58.727Z" }, - { url = "https://files.pythonhosted.org/packages/71/cf/107421693cfb71e4f1ca5bf70443f64d4161878068d07a3e51c7ad21d17b/coverage-7.14.1-cp311-cp311-win_amd64.whl", hash = "sha256:87ebdf787d4888e3f3f2d523eadc6e18c6d18c6d0eb173801a189641627fb37e", size = 223290, upload-time = "2026-05-26T20:39:00.413Z" }, - { url = "https://files.pythonhosted.org/packages/b8/1d/3e3644585eb29e9dafefb19555078529a4d7cce12bd21929664eea989277/coverage-7.14.1-cp311-cp311-win_arm64.whl", hash = "sha256:dd34767fa19848d35659ffc0a75314f58c7af3f1cd87ec521e8292a1238398a3", size = 221953, upload-time = "2026-05-26T20:39:02.159Z" }, - { url = "https://files.pythonhosted.org/packages/3d/b7/bdbb725ba02c5b42825b200c940f38b7a54fcad24627b7192f78f8110d76/coverage-7.14.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:a06c76364a9360e33d6d23769aefdf7f66f38e2ffb60ceb1baaa4989d83b695c", size = 220022, upload-time = "2026-05-26T20:39:03.702Z" }, - { url = "https://files.pythonhosted.org/packages/72/81/fdc0898a55c6219223291ec1a1fe89966ef212ce82276aa0899df84b5de0/coverage-7.14.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:fad54e871165f6ec2f536063ac74c3104508a12963e64072ba44bd822de52b0c", size = 220379, upload-time = "2026-05-26T20:39:05.381Z" }, - { url = "https://files.pythonhosted.org/packages/de/72/de048c4a25e13bce59ac6a339351c10bdf2515e07459afcdaf04dc3143a2/coverage-7.14.1-cp312-cp312-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:84b535f00655ecafe1d929d1fb00ed5d6fa3051ea643ab2c161a3887b86f294b", size = 251888, upload-time = "2026-05-26T20:39:07.367Z" }, - { url = "https://files.pythonhosted.org/packages/28/30/300c343f68beb9d4cbb64ec81e58c5b6b80b56927f72d2b38654ac26e013/coverage-7.14.1-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:6b6b0853b895fe0e98cbfc580d1ec3393d9302b4b1e96a77b3f5c91fdab899e6", size = 254624, upload-time = "2026-05-26T20:39:09.037Z" }, - { url = "https://files.pythonhosted.org/packages/b1/ed/7b25642496e8170b6bac14adce00537c6e5fa2d586159401a4de3e8b49e6/coverage-7.14.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:442cc9c952b2df400cda54bb04ab87330cf2cd08a8692cbbea36773531eb6f37", size = 255739, upload-time = "2026-05-26T20:39:10.889Z" }, - { url = "https://files.pythonhosted.org/packages/7f/a2/abd210b8c4e29c24e4624916db97bb519097a91034aaeb767f937e7da794/coverage-7.14.1-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:8270544c361ed405a27a060dbc9ed2c124b084d96dfdc2d9a2510482aef981ad", size = 257998, upload-time = "2026-05-26T20:39:12.722Z" }, - { url = "https://files.pythonhosted.org/packages/7f/24/7c50beed3792fe62f6ce0545c6686ce83379719e2c0276179333d97eae92/coverage-7.14.1-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:48b283b1dd6372e8de2a7a9a4c4d5dc06f4d4fd209b876f3c88a7a205a0c8f84", size = 252296, upload-time = "2026-05-26T20:39:14.259Z" }, - { url = "https://files.pythonhosted.org/packages/15/05/0f874628ebcbfc77ead559ff210281ef06a97db08481832e7dd39274a135/coverage-7.14.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:5b0c99ba93a07d56f6df340bb79be53202a082b2fdb81bfe6190b741a3470d54", size = 253658, upload-time = "2026-05-26T20:39:15.923Z" }, - { url = "https://files.pythonhosted.org/packages/99/6f/ca6ad067364b337ef997802115e7ecad2abd2248b05471464b0dea02b4d4/coverage-7.14.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:e471bc5769ff073b058cfadb0d736b56ce067c8560eabeb0da88462df98c23e7", size = 251803, upload-time = "2026-05-26T20:39:17.537Z" }, - { url = "https://files.pythonhosted.org/packages/c0/30/b9b4d377cd9f40baf228068f5a81faf8450c6228503011bd499708483a50/coverage-7.14.1-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:f497a1ea81d4cd7c10ddcaa685135b9aabd291af3d55775a9ddf3cb7a364cdd9", size = 255873, upload-time = "2026-05-26T20:39:19.414Z" }, - { url = "https://files.pythonhosted.org/packages/3c/21/7c721a9e5e6bb88547d30a787aefb97512d3f54c1324c7488d9b3743f7f9/coverage-7.14.1-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:2222be86d0b54f5dd5a38f45f17f315f737245e857bf0bdedc70734f84a13c02", size = 251372, upload-time = "2026-05-26T20:39:21.169Z" }, - { url = "https://files.pythonhosted.org/packages/9d/8c/f8ae5a2200130e1503cd7661a6cd3b2b7bacef98277fbf3571fb13f8b766/coverage-7.14.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:85e85586565842f6932abebd4c18bcb1074223dc0b3576e7d173ca710622813a", size = 253245, upload-time = "2026-05-26T20:39:23.097Z" }, - { url = "https://files.pythonhosted.org/packages/34/62/70a9024672a5f6910517d9628c52c9afbdd3cf8f46426af52bb148a56fff/coverage-7.14.1-cp312-cp312-win32.whl", hash = "sha256:4a28fd227808366b196a75476dced2eb35b351d6766ba9c858dc93319e87f4f1", size = 222567, upload-time = "2026-05-26T20:39:24.868Z" }, - { url = "https://files.pythonhosted.org/packages/f6/81/8b7cd386839b039ebe1855733b9f9449a8dec5d79564018234f185a7fa70/coverage-7.14.1-cp312-cp312-win_amd64.whl", hash = "sha256:54acdb6674a4661768d7bf7db32dfb9f46ab1d764f8aba6df75ce1a6a088724e", size = 223372, upload-time = "2026-05-26T20:39:26.603Z" }, - { url = "https://files.pythonhosted.org/packages/ae/ba/b44d472022f620d289d95fa830143235c0c36461c6f2437ea8d51e5481ed/coverage-7.14.1-cp312-cp312-win_arm64.whl", hash = "sha256:99cd41ff91afd94896fea3bc002706b6ae4ce95727d06e4a0f39c0a8d8bd8b1a", size = 221989, upload-time = "2026-05-26T20:39:28.242Z" }, - { url = "https://files.pythonhosted.org/packages/8a/9e/5f6d56327c62b185225d145191c607e07515294a0aa6338e58805cd4a5ac/coverage-7.14.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:be9f2c802dcfce3f71298303aa5dad0dce440a76c52f2f60dacd8656dab78793", size = 220044, upload-time = "2026-05-26T20:39:29.902Z" }, - { url = "https://files.pythonhosted.org/packages/75/92/e82aca356744cbbc0f77a0b623e38918c1872361963413a3bab5d0340393/coverage-7.14.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:6223a72fd0e4c7156353ec0f08a5f93623e1d3034d0e2683b9bb8ea674131b1d", size = 220412, upload-time = "2026-05-26T20:39:31.561Z" }, - { url = "https://files.pythonhosted.org/packages/27/c9/385bde0bf7ed0f4bf3a7ee5367060a86b5d218718cfd6fb943c0f836b34f/coverage-7.14.1-cp313-cp313-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:7279d2110a28cebc738b6459ecda2771735a4c18465fbbd36b3288fe5ed92247", size = 251412, upload-time = "2026-05-26T20:39:33.337Z" }, - { url = "https://files.pythonhosted.org/packages/51/8c/23faf6a2343a0d17f960a4bd56c43bc7eb4cf312f774dd6ceebd82c7d8fc/coverage-7.14.1-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:9eeb3fcbc13ba40dfbdb22d01d196a28e9cef9ed4c29b60061a1e0e823a9929d", size = 254008, upload-time = "2026-05-26T20:39:35.009Z" }, - { url = "https://files.pythonhosted.org/packages/42/06/36f4aa9ca8a815e6036156e80706a67828bb97bd826948244f6996dda957/coverage-7.14.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5f0cfc27c539f07cf5c0a4cfe211d0b6cae039f8f40526dbaa71944e64b50a7b", size = 255241, upload-time = "2026-05-26T20:39:36.71Z" }, - { url = "https://files.pythonhosted.org/packages/ca/79/95266316352f90f6b1c6736bb413302edfde2453fb32422d3911642691b3/coverage-7.14.1-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:221c70f316241a78e77e607c227cefc8808d4e08f28d99c04f35694690e940be", size = 257373, upload-time = "2026-05-26T20:39:38.412Z" }, - { url = "https://files.pythonhosted.org/packages/e3/9c/58316d1f66c488b5fca8a0eb3e98348807813efa8a0d0833b9021be27488/coverage-7.14.1-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:da028256b04ec30e5e0114b6f76172938c313991f0a2d3d894271315cf5d5e43", size = 251635, upload-time = "2026-05-26T20:39:40.268Z" }, - { url = "https://files.pythonhosted.org/packages/ef/5a/ca2398a568e16fed7bb713e84ba3603a7164fb65779abe645c565ec890d5/coverage-7.14.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:76a085d7005236a767e3426148b2c407e53ad61695c562f8a81da2d373324901", size = 253373, upload-time = "2026-05-26T20:39:42.145Z" }, - { url = "https://files.pythonhosted.org/packages/6e/2c/0396562c32deaebe7be51d865b3a41e9a87d7561acafe1a28f53b07e019a/coverage-7.14.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:b553d04b5e778a8e56d57eb134aff42a92718ecba45e79c4764ecfa40efd92ff", size = 251341, upload-time = "2026-05-26T20:39:43.907Z" }, - { url = "https://files.pythonhosted.org/packages/fd/8f/a94f9221184c9cae1ee115820e3798e48b6b17777a9f19e46fb9a0c8dc74/coverage-7.14.1-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:46f714d2fb8ae2f4f29f23ada7f1e79b759fff5a70f94a1dac23af204c3ec9e4", size = 255497, upload-time = "2026-05-26T20:39:46.166Z" }, - { url = "https://files.pythonhosted.org/packages/71/69/505d70e47db1eaebcd002c39759707621ef184cd6b1ae084d9f41293f323/coverage-7.14.1-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:1896f5e19ff3f0431c7ce2172adc54890fd97f86b59ced8ca1649145d9ffe35d", size = 251159, upload-time = "2026-05-26T20:39:48.03Z" }, - { url = "https://files.pythonhosted.org/packages/e0/aa/58681c383aa33a9d2ed40a02d7a22fbf780d1fa4d575396365777828198c/coverage-7.14.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:62fd185ef9df3c33d1c8178c5af105f762afbad96038de9a4ae100aa6297ca33", size = 252934, upload-time = "2026-05-26T20:39:49.872Z" }, - { url = "https://files.pythonhosted.org/packages/eb/fd/11c928cd6bdffc7074bb5965c173d9ebf517fb00205e1da524b98d29ef92/coverage-7.14.1-cp313-cp313-win32.whl", hash = "sha256:ab4af6352741a604c431c6072fce5bee33bf0f20dc7a56618d6bf6bb89e9810c", size = 222584, upload-time = "2026-05-26T20:39:51.68Z" }, - { url = "https://files.pythonhosted.org/packages/6f/92/fb416fc26d340dcba19518c418d6048e913186e17243982c5e435e41fa7a/coverage-7.14.1-cp313-cp313-win_amd64.whl", hash = "sha256:7af486dabe8954d03b087f0021540897afe084f04e16ff5579e08cc46f871416", size = 223394, upload-time = "2026-05-26T20:39:53.472Z" }, - { url = "https://files.pythonhosted.org/packages/73/c6/02d56e3867972f77d5036de924643f26c056e848f00452cafb4dbc3c29b4/coverage-7.14.1-cp313-cp313-win_arm64.whl", hash = "sha256:2224f89ffd0c5605ccce1ed7a584da162bc7c55f601ab1c946bc9de31a486b42", size = 222015, upload-time = "2026-05-26T20:39:55.374Z" }, - { url = "https://files.pythonhosted.org/packages/4d/9e/fcc77914050df73f7662fa1f00902774c79c075a8388ab334074574bf77e/coverage-7.14.1-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:de286598cc65d2b489411174b1faec2f5a7775fb3201fd925db2a76b4030f37d", size = 220733, upload-time = "2026-05-26T20:39:57.189Z" }, - { url = "https://files.pythonhosted.org/packages/f7/67/2963cbdaf5cbadec44efa3a1e39eaa1f02df4079585f05387607a221e126/coverage-7.14.1-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:042c46ded7c288aeb07cf14a28b6c1e10b78fcba40171c3fa1e939377eeef0b5", size = 221086, upload-time = "2026-05-26T20:39:59.019Z" }, - { url = "https://files.pythonhosted.org/packages/c8/c5/8701645574e11881f2f47d8930f98bc48b5d43b25eb5b4430dfc4a2f9f48/coverage-7.14.1-cp313-cp313t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:f4ddbe407477f04c45115d1a4e5bc480f753553b534d338d4c3358b1cdd0ea52", size = 262381, upload-time = "2026-05-26T20:40:00.822Z" }, - { url = "https://files.pythonhosted.org/packages/7c/28/7a64d73598263e0c5abd5084211a8474488d31b3c552ff531c719dfcff62/coverage-7.14.1-cp313-cp313t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:d13e6725992e2d2fd7d81d4f5241952d13740121dfd501da09201be39b2c003a", size = 264458, upload-time = "2026-05-26T20:40:02.506Z" }, - { url = "https://files.pythonhosted.org/packages/fa/d8/4969179db9f7eb4df218e69540adf829d1c835f59452513d065d15446802/coverage-7.14.1-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f747dc8edcfe740130f28f32f3995e955494285717e86ee25af51db2219df08a", size = 266884, upload-time = "2026-05-26T20:40:04.421Z" }, - { url = "https://files.pythonhosted.org/packages/a6/78/a45d5794dbc9bafd97afc96a4377c86c7820d78b6cf51b89bc1d4e919275/coverage-7.14.1-cp313-cp313t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:ced2f09ef276fd58611a1ef502164ad266d2b75174e5a40cabbdb4033f9f6cf2", size = 268022, upload-time = "2026-05-26T20:40:06.298Z" }, - { url = "https://files.pythonhosted.org/packages/21/cb/4f5e354e9e3e67af96bd4e57113e6db6b22298c7168b13eec408a549903d/coverage-7.14.1-cp313-cp313t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:b84800013769a78ccb9ef4659402e26d06867e337b61ec365f77ad008adea80e", size = 261631, upload-time = "2026-05-26T20:40:08.226Z" }, - { url = "https://files.pythonhosted.org/packages/ec/49/eced49af4cb996d5d8b7e94e736175c513e4facd3398507b89892b4326d8/coverage-7.14.1-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:ea8cd6ca0ee9f616aaef3afc6882e32c2cbf18b00d96313ffd76af650574034d", size = 264443, upload-time = "2026-05-26T20:40:10.137Z" }, - { url = "https://files.pythonhosted.org/packages/f1/d8/5603a88a7c5913a6b54f6cb1a8c46f7b39cbb30f27cd3f492908da09b2d7/coverage-7.14.1-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:aa5e304a873fabddc11e484e9b6b738bd38bd7bed17b09aa84eecf5332e8b8bb", size = 262069, upload-time = "2026-05-26T20:40:11.999Z" }, - { url = "https://files.pythonhosted.org/packages/f0/59/2ae3cb79da554a06c8619d6c88ea19dd1e4aed4b834b6a83bb1fa243bdc5/coverage-7.14.1-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:5a1c5215be81035e629d5bc756650634d0bf31991038db7a0eccb90f025ce16d", size = 265780, upload-time = "2026-05-26T20:40:13.858Z" }, - { url = "https://files.pythonhosted.org/packages/af/5f/b130c1dc999031f2648bd25317fbce505ad8d5562079b4ed81e736a84967/coverage-7.14.1-cp313-cp313t-musllinux_1_2_riscv64.whl", hash = "sha256:79058c47dae6788504b5effb319961bcd72d7240551464b91d474bc0ed186d69", size = 260970, upload-time = "2026-05-26T20:40:16.142Z" }, - { url = "https://files.pythonhosted.org/packages/87/d1/ec13ccddeb48ec963bdfa72a11224bac2584bd045ba13beca82f8113e9c7/coverage-7.14.1-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:370c5afae3fa0658e11694a32b24c2778f6bc2d17718121f94ee185e69f26b54", size = 263157, upload-time = "2026-05-26T20:40:18.382Z" }, - { url = "https://files.pythonhosted.org/packages/cf/c2/cd91ead503045161092d3845f7bb95ea2f25131ce96d3e314dd835d91b9c/coverage-7.14.1-cp313-cp313t-win32.whl", hash = "sha256:3758dd0a7f1fa57365ef2e781df0f0731d38b6e3772259d13dae4bd8a958d4b1", size = 223259, upload-time = "2026-05-26T20:40:20.381Z" }, - { url = "https://files.pythonhosted.org/packages/71/9f/1e28d97e6bd2c76b07f38b7c02870f1371255ff6717f54eca578fcbbdd0e/coverage-7.14.1-cp313-cp313t-win_amd64.whl", hash = "sha256:6ff665fb023a77386fe11685190cee1f60a7d635994a30d9b0a061533d470fce", size = 224320, upload-time = "2026-05-26T20:40:22.316Z" }, - { url = "https://files.pythonhosted.org/packages/a9/e0/d936e908f0e1efa55e52b91e01b52f1055cef5e1ab2718493390ed8e2fb8/coverage-7.14.1-cp313-cp313t-win_arm64.whl", hash = "sha256:17a5a241e5997621a956a7f402a7433ef4221e5152809b785bec79e2323799f1", size = 222577, upload-time = "2026-05-26T20:40:24.894Z" }, - { url = "https://files.pythonhosted.org/packages/d6/34/fc2f101b151af3799a101f0550b0454aa008afdc0add677394ec4aa8ea10/coverage-7.14.1-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:d5ed429d0b8edaac649e889b4ffcedb6c80b06629a3f93050e3dddfb99235bee", size = 220091, upload-time = "2026-05-26T20:40:27.249Z" }, - { url = "https://files.pythonhosted.org/packages/3d/a7/1ebae2ab5b961b5c79bb09fe7b3ac99edb190d8be4a8c510b2cf66f46468/coverage-7.14.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:8011224a62280e50dab346960c03cf47aca1a1e09e608c0fb33fd6e0cc8e9500", size = 220421, upload-time = "2026-05-26T20:40:30.084Z" }, - { url = "https://files.pythonhosted.org/packages/5e/90/92aca9cf0acc95123c96cd1eb1f08917897a7f5dee01e15738922971ec31/coverage-7.14.1-cp314-cp314-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:12c42ec1e14f553c4f817e989365982e646e27211f10a0f717855b94a79c8906", size = 251466, upload-time = "2026-05-26T20:40:32.542Z" }, - { url = "https://files.pythonhosted.org/packages/26/2b/78048cbe3b999f6cbf9cc0d90abba6a88a3e0863a8c1c6cbc762f3f8802f/coverage-7.14.1-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:06144cd511cf2624873a035c5069cf297144f6e77a73ee3d7a55b605ec5efb42", size = 253973, upload-time = "2026-05-26T20:40:34.473Z" }, - { url = "https://files.pythonhosted.org/packages/8e/21/c2e33b29d1cfde484a19d437afc343c6cd30b08d78cbbf9f5aff14e57b2b/coverage-7.14.1-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a311d8e1da24be5c1ccf85cbfb06315dbaa1703d5a1eab3f6432c72b837917c8", size = 255318, upload-time = "2026-05-26T20:40:38.154Z" }, - { url = "https://files.pythonhosted.org/packages/8e/ee/aad2f108d63b769121005302f16bf66db8625c88ceaba466942e09a2607e/coverage-7.14.1-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:c79cead5b5bc584d9c71451cb984d0e3a84e0c0937379c8efcbf27c8d661b851", size = 257633, upload-time = "2026-05-26T20:40:40.164Z" }, - { url = "https://files.pythonhosted.org/packages/c2/f8/11a2c29b4fd76d9849f81d0bb812ec0017a9396df3217214e38934a8c837/coverage-7.14.1-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:dcbf65f1f66a26cdd88c35cf68fb4729c5d1cd2e88added72420541dfb212034", size = 251488, upload-time = "2026-05-26T20:40:42.631Z" }, - { url = "https://files.pythonhosted.org/packages/c9/b8/9a5820de4b8ac2b71d85e3b5fb49108d7469c665f0e2ad0dd7569023e305/coverage-7.14.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:fd86572566fb40189a8260446158235159bc7a82dfbc87a3b39cf4fb57fcec1c", size = 253329, upload-time = "2026-05-26T20:40:45.208Z" }, - { url = "https://files.pythonhosted.org/packages/6b/ff/f33e4823667e27548e8fd8df44217515303f9808d0ff29817db56f87d990/coverage-7.14.1-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:7771b601718fdde84832c3a434ca9bbf4ae9adbc49d84198b4110700c3c77c36", size = 251291, upload-time = "2026-05-26T20:40:47.502Z" }, - { url = "https://files.pythonhosted.org/packages/68/9b/489db0ebb209054766b90a9014a45f6d26eb724c02ec21311c3733b5a644/coverage-7.14.1-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:39b21e212c55af06fa375e3dbf90a8a8e38792f3a910c580066d23563830ddd5", size = 255564, upload-time = "2026-05-26T20:40:49.372Z" }, - { url = "https://files.pythonhosted.org/packages/27/b5/16bc2d4c2409b23c7737edb68c83bc89e345f378050549fe1d75ac7d34d5/coverage-7.14.1-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:f2302660e32562a532b442480121aef8aa61a5bdb20b30bf0adab29f10a5a4b4", size = 251107, upload-time = "2026-05-26T20:40:51.677Z" }, - { url = "https://files.pythonhosted.org/packages/7d/0c/2629997469a00cd069d588a41c9dc887610f2775ae89d250c4791e65272a/coverage-7.14.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:03a6f93c1ec3b7f2e77b5dbcc5573a2c21f12529a5c6bbe0f16f72303cc2fa4d", size = 252764, upload-time = "2026-05-26T20:40:54.267Z" }, - { url = "https://files.pythonhosted.org/packages/d2/ee/f78d63c8f079e0d7211c7e2401fa17e311514534ba61bae03e4b287ce4ab/coverage-7.14.1-cp314-cp314-win32.whl", hash = "sha256:8a3ce026d73290f42f08dafecbd82c193a74df280461fbf97300fec51fd133ee", size = 222837, upload-time = "2026-05-26T20:40:56.496Z" }, - { url = "https://files.pythonhosted.org/packages/dc/b9/be539854f93a70dfbeec69117f33ec70dc42ff0b65b5b07ab8d40d04228e/coverage-7.14.1-cp314-cp314-win_amd64.whl", hash = "sha256:114c95ef29302423b87d159075805f4ab973254a2638a5d7d046c94887cc87d7", size = 223650, upload-time = "2026-05-26T20:40:58.351Z" }, - { url = "https://files.pythonhosted.org/packages/fe/9e/24e2842fef40f35ac82ba3a7719c8023d011bf3bf652d0675316a9d088a1/coverage-7.14.1-cp314-cp314-win_arm64.whl", hash = "sha256:a07891c3f4805442b31b71e84ba3cf29ed1aa9a428284e06deeb4b23e5b46343", size = 222218, upload-time = "2026-05-26T20:41:00.321Z" }, - { url = "https://files.pythonhosted.org/packages/0a/1d/ac0a9df5fe31c1e8bdd658074905fc12844a05c1a7e3fdb8417e97c31e23/coverage-7.14.1-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:1101a5ebb083aecb625ebb6209d4105b58f647b093cb2dc8122d7b33f743cfe1", size = 220822, upload-time = "2026-05-26T20:41:02.281Z" }, - { url = "https://files.pythonhosted.org/packages/32/cf/f964fd9aff20323f9f1a726c97135f8a76bcd87b92dad141a456a43f3c64/coverage-7.14.1-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:851b9e1e4e8a4608e77c79714b2e77c0970d2ed7202a05e92ae407817481887b", size = 221084, upload-time = "2026-05-26T20:41:04.593Z" }, - { url = "https://files.pythonhosted.org/packages/d8/5e/7e5ef2aba844de2b80d678619fcf0841b42e3f37f16411226f3fe4c1016f/coverage-7.14.1-cp314-cp314t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:d5b89cdfb2ee051b71e8c3c70bd81a9eff81100f736a269136fe1a68efe00474", size = 262454, upload-time = "2026-05-26T20:41:06.641Z" }, - { url = "https://files.pythonhosted.org/packages/64/62/75809bded87015cc4935524218a2a8ed8dd1a8498bfed30a2f4f7a4b4d34/coverage-7.14.1-cp314-cp314t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:0177614a0370f227888b4e436a7c55686d6a9f90eb1ade2b624ba685a1686e86", size = 264578, upload-time = "2026-05-26T20:41:08.556Z" }, - { url = "https://files.pythonhosted.org/packages/f3/42/d33392dc14633525012d2d504fa1a33b05538bf535f5c1d64675e5754b78/coverage-7.14.1-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:2d69af5dea2de76fc485a83032a630523f985198b7e25be901ec60181587b01e", size = 266981, upload-time = "2026-05-26T20:41:10.824Z" }, - { url = "https://files.pythonhosted.org/packages/2a/49/0157c4428c2aca7f1e09d5565930586fd5ae36f1655f08b0daa7cf1fcae1/coverage-7.14.1-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:35ab22d91de736e8966b980dc355cbcdd2c6dbbcfe275f9a2991bc8a91b3df65", size = 268112, upload-time = "2026-05-26T20:41:12.966Z" }, - { url = "https://files.pythonhosted.org/packages/96/26/86b9ce71f4092b1ed325ce1421698081df1286b833400b6836912834d6e0/coverage-7.14.1-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:357d4e32935c36588aaba057d734fa32428c360c9fc2e4442afbf1b646beee6e", size = 261558, upload-time = "2026-05-26T20:41:15Z" }, - { url = "https://files.pythonhosted.org/packages/20/4c/c311210c5472cf5401d8422b0d7812cdd520f24417673afabda6c323faca/coverage-7.14.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:51bd64741cc6fa065abd300ede1afe5a5291ece9c31da8b24884deda48bcc3f8", size = 264447, upload-time = "2026-05-26T20:41:17.369Z" }, - { url = "https://files.pythonhosted.org/packages/fb/71/59513f8710ed3e6b0ac0a050a5b7e977bb9c9e880354863b5d00d8809256/coverage-7.14.1-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:9132cd363a68a4c3daa7c8704a654b1e39d3360f6f5b8ddd470608a945236c07", size = 262048, upload-time = "2026-05-26T20:41:19.309Z" }, - { url = "https://files.pythonhosted.org/packages/84/8d/bceed32dc494f5bbf50f775cd2e78ca814953942b5ea28d3c1c3ac316f14/coverage-7.14.1-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:07c6290b1697b862c0478eab545eec949a0d0e4d6d03497f446d706da3b4f2de", size = 265781, upload-time = "2026-05-26T20:41:21.559Z" }, - { url = "https://files.pythonhosted.org/packages/e7/c5/9348fe40dbfd4991aaf78df2c6c3098bfb2cc834d1fd362a64b4efef855a/coverage-7.14.1-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:5ea0c297e27133853b4d8a3eb799bff5a2dbd9f2f41537a240d337ac9b4df890", size = 260896, upload-time = "2026-05-26T20:41:23.428Z" }, - { url = "https://files.pythonhosted.org/packages/ca/92/1ea0f03929da7cf87206b1fa24f4c8e9c158be0455481af29ec0a1f3503f/coverage-7.14.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:01b7733daad0237daa01ef80fe2dfceffc911e6a17fa7b55d14aa8214eaaaecd", size = 263214, upload-time = "2026-05-26T20:41:25.419Z" }, - { url = "https://files.pythonhosted.org/packages/f6/a9/b2493c054c0e01a643266742ab45e15744e60743f9260cd930c7142b1124/coverage-7.14.1-cp314-cp314t-win32.whl", hash = "sha256:6adc5a36984624a70bf11d7184e20fa0a49aa7c47ffab43804106a1a695ea22e", size = 223624, upload-time = "2026-05-26T20:41:27.795Z" }, - { url = "https://files.pythonhosted.org/packages/fc/bd/3e1e6a57fccd2d7c83fcdf338e93ba98eb85c6e877dd34731ac585375490/coverage-7.14.1-cp314-cp314t-win_amd64.whl", hash = "sha256:ddf799247318f34dbcd2efa8c95a8d0642674e926bb1774cf9b63dfd2a389d1c", size = 224728, upload-time = "2026-05-26T20:41:30.098Z" }, - { url = "https://files.pythonhosted.org/packages/bb/d7/31066cf1d2f0c6c797fce911bcfa01dd35642dc6da992a950256097c5860/coverage-7.14.1-cp314-cp314t-win_arm64.whl", hash = "sha256:145986fe66647eb489f18d9a997567a3fd358584c4b5a808769113abc07466af", size = 222752, upload-time = "2026-05-26T20:41:32.123Z" }, - { url = "https://files.pythonhosted.org/packages/8a/3c/1a983b9a745d7f83d53f057bcc5bf79ba6a2bbc08266b3f0c7d6fe630c9b/coverage-7.14.1-py3-none-any.whl", hash = "sha256:a252f21c27e38347e60111a3266b03827422a7d5525951aceee313aa68bab1d2", size = 211815, upload-time = "2026-05-26T20:41:34.078Z" }, +version = "7.15.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/76/d0/55fe630f4cf94e3fcba868240fad8c8cdd1f764e2a932f8926347e6ec4cd/coverage-7.15.2.tar.gz", hash = "sha256:3df60dc267f0a2ca23cb7a9ab1109c62b9335ffbf519fcfe167157c28c09b81d", size = 927741, upload-time = "2026-07-15T18:56:19.558Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/10/03/060ce69008ac97bbc01b1411b3e55b61f6f015659400b46749b662107831/coverage-7.15.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:9b5bd92ff1ec22e535eab0de75fa6db021992791f461a2aceb7822c625a1187d", size = 221284, upload-time = "2026-07-15T18:53:29.52Z" }, + { url = "https://files.pythonhosted.org/packages/fc/a3/d936e8b53edd9684100a6aefaf3fcabaa54728fe33324436c8d279c047aa/coverage-7.15.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:44826758cfe73fcd0e6af5deb4ba6d5417cc1d13df3acb35c93484a11160f846", size = 221799, upload-time = "2026-07-15T18:53:31.708Z" }, + { url = "https://files.pythonhosted.org/packages/ae/a3/ca234b06aec7ee28226f11d39a696b4481fe5eddfce8e03bf39979bb8ffb/coverage-7.15.2-cp310-cp310-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:09f5c6ec5901f667bd97dd140b5b9a2586b10efec66f46fb1e6d8135f8b95bdf", size = 248544, upload-time = "2026-07-15T18:53:33.212Z" }, + { url = "https://files.pythonhosted.org/packages/2b/89/dda79527bb7573ba91828b2fb91b3105d87378d6a2749ca0c0924ce0addd/coverage-7.15.2-cp310-cp310-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:1d16e3a7104ea84f03e614611b3edbf6fb6892554b3ab0fe7fbb3f2b2ef04376", size = 250374, upload-time = "2026-07-15T18:53:34.683Z" }, + { url = "https://files.pythonhosted.org/packages/67/c6/c33755a34572f81f49a8c0cdf6b622f35ccb3238b136e1909daf0cdd4319/coverage-7.15.2-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d46e62cb35d91e6e2589fda6d28074426b0e276422b5d2ebef2c6b11dc60dbfd", size = 252239, upload-time = "2026-07-15T18:53:36.205Z" }, + { url = "https://files.pythonhosted.org/packages/b9/6f/dc341741b375be53a5baeee5b4bf0f0e525d38caed428f7932d23bb7bcb1/coverage-7.15.2-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:dfd3db045e95960ae3683059571e597fda7cc610106a8916f77c5839048c1deb", size = 254150, upload-time = "2026-07-15T18:53:37.863Z" }, + { url = "https://files.pythonhosted.org/packages/e9/8d/966a18a5b195cb4e77b14c53f5f3dce22b5da05e6de7fafd1e08f2d2067a/coverage-7.15.2-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:affd532502d34c0472d0cdb181325c89f1d2c44992fef0c17e88e7b1576259a1", size = 249234, upload-time = "2026-07-15T18:53:39.394Z" }, + { url = "https://files.pythonhosted.org/packages/c5/8b/8b2e367496ab48484d48e79984fec76cdc1b7cb5d3a00ee799a5602e3ec9/coverage-7.15.2-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:d17d7512151fedfcc64c1821a8977fc9be0dbf495754669afcab7b57abc98ae9", size = 250276, upload-time = "2026-07-15T18:53:41.027Z" }, + { url = "https://files.pythonhosted.org/packages/63/92/1199318a200eb6c8c6ce0192c892c8710ac791abbe0f35099294620bbfda/coverage-7.15.2-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:e26ff680768b8095e8874aabe0e9d3a47a2a9f176a8340d05f8604c56457c23a", size = 248283, upload-time = "2026-07-15T18:53:42.557Z" }, + { url = "https://files.pythonhosted.org/packages/56/da/be284a55c5619bda891a89c27dfd59324a2c6a14d755cf6aac6960ceebeb/coverage-7.15.2-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:7e8f27131dc7cd53de2c137dd207b3720919320b3c20d499dc30aa9ee6173287", size = 252093, upload-time = "2026-07-15T18:53:44.271Z" }, + { url = "https://files.pythonhosted.org/packages/d4/53/ee112da833ddd77b73c6d781a98029b45b584b136615b4900ed0569f887e/coverage-7.15.2-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:728a33676d4c3f0db977990a4bd421dcaa3be3e53b5b6273036fff6666008e89", size = 248552, upload-time = "2026-07-15T18:53:45.7Z" }, + { url = "https://files.pythonhosted.org/packages/82/6a/802cfc802e9113494c80bf3f284cd4d72faeb1f24e244f61046af364f2ca/coverage-7.15.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:29c052f7c83ccfcc5c577eaae025d2e4a9bb80daf03c0ac31c996e83b000ce88", size = 249154, upload-time = "2026-07-15T18:53:47.256Z" }, + { url = "https://files.pythonhosted.org/packages/2c/65/529808e91d651147edae408fd9e894abc3b8cad7f3e594bbc36719a3e13a/coverage-7.15.2-cp310-cp310-win32.whl", hash = "sha256:1268ac8fb9ddcd783d3948dbabaf80a5d53bfdaa0575e873e2139a692f797443", size = 223334, upload-time = "2026-07-15T18:53:48.768Z" }, + { url = "https://files.pythonhosted.org/packages/68/0f/0e1829d7001130876dfbc0b4e1c737ea7c155b809e3e4a98a0aa268e2369/coverage-7.15.2-cp310-cp310-win_amd64.whl", hash = "sha256:9f4432898c4bf2fba0435bbe35dd4437d7264565e5a88a21f5b49d8662a6b629", size = 223959, upload-time = "2026-07-15T18:53:50.429Z" }, + { url = "https://files.pythonhosted.org/packages/7d/3a/54536704f507d4573bf9161c4d0dd3dd59b6d85e48c664e901b6844d8e33/coverage-7.15.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:2f1ec6f304b156669cfde653b4e9a953f5de87e247ea02ac599bce0ab2744036", size = 221414, upload-time = "2026-07-15T18:53:51.941Z" }, + { url = "https://files.pythonhosted.org/packages/b6/d9/8ba925d29743e3577b21e4d8c11a702b76bc93c41e7fdfd1177af63d4b8d/coverage-7.15.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:4d3361879d736f469f45723c11ea1a5bbdaf1f6928f0e632c940378b5aa9b660", size = 221913, upload-time = "2026-07-15T18:53:53.682Z" }, + { url = "https://files.pythonhosted.org/packages/09/54/a855f3aa0187f2b431ade4e4791b77b56282cfb5d201c83ec26a31b5b36a/coverage-7.15.2-cp311-cp311-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:c6a98d698f9e2c8008d0370ec7fc452ebfcc530002ae2d0061170d768b992589", size = 252332, upload-time = "2026-07-15T18:53:55.467Z" }, + { url = "https://files.pythonhosted.org/packages/8e/d3/13ac97b4370640ba3452fc8559b06cc2f479ce3ba4a0b632a73e44c38a7d/coverage-7.15.2-cp311-cp311-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:d50dd325e18ec25bfcc10cd7f99b04df1ab9ec76b0918c260e60817ad0643dee", size = 254243, upload-time = "2026-07-15T18:53:57.055Z" }, + { url = "https://files.pythonhosted.org/packages/88/83/5eca144942d8d0659d3f55176517f4a59cdc65eefd17146a0770935a3ebd/coverage-7.15.2-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:67d7602480a47bdf5b675635403625553ebaa70d5a62a657c035149fd401cea0", size = 256352, upload-time = "2026-07-15T18:53:58.83Z" }, + { url = "https://files.pythonhosted.org/packages/4e/ba/d3db2e01a50fc88cdb4c0f19542bcf6f61489e34dc9aa3538413e2459a38/coverage-7.15.2-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:cee0f89f4767a6057c8fbf168f8135f18be651300496086bd873e3189fed0487", size = 258313, upload-time = "2026-07-15T18:54:00.497Z" }, + { url = "https://files.pythonhosted.org/packages/78/b3/aba83416e9177df28e5186d856c19158c59fc0e7e814aaa61a4a2354ad1b/coverage-7.15.2-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:a29ec5305a7335aacee2d799e3422e91e1c8a12474986e2b3b07e315c91be82f", size = 252449, upload-time = "2026-07-15T18:54:02.456Z" }, + { url = "https://files.pythonhosted.org/packages/6a/a5/4b00ecac0194431ab451b0f6710f8e2517d04cef60f821b14dec4637d575/coverage-7.15.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:48ccc6395958eda89093ecdc35644c86f23a8b23a7f4d44958812b721aad67c1", size = 254043, upload-time = "2026-07-15T18:54:04.072Z" }, + { url = "https://files.pythonhosted.org/packages/75/b6/cfa209b4313ee7f1b34da47efcd789ea51c024ad35af390e00f5a3c10a2e/coverage-7.15.2-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:81f382c5a94b434ec1f6da607edb904c76d7212e618cd4d1bc9f97bed4120ef5", size = 252107, upload-time = "2026-07-15T18:54:06.745Z" }, + { url = "https://files.pythonhosted.org/packages/36/67/e8cac5a6954038c98d7fe7eb9802afe7ab3ecb637bb7cc00e69b4148b56d/coverage-7.15.2-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:bbc808daf4f5cd567af8075ecc72d21c6dfef9a254709a621a84c217c935ebc0", size = 255873, upload-time = "2026-07-15T18:54:08.48Z" }, + { url = "https://files.pythonhosted.org/packages/2c/92/395cca9f330a86c3fe3471d73e2c102116c4c58fdc619dbbc125c6e93a54/coverage-7.15.2-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:a4c46b247b5d4b78f613bd89fea926d32b25c6cc61a50bd1e99ba310348f3dad", size = 251826, upload-time = "2026-07-15T18:54:10.083Z" }, + { url = "https://files.pythonhosted.org/packages/51/60/3e91b20295439652424f426b7086ec5bf4fbe3f604c73eda22b986c4fd6b/coverage-7.15.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:094dd37f3ef7b2da8b068b583d1f4c40f91c65197e16c52a71962d5d537fc5db", size = 252735, upload-time = "2026-07-15T18:54:11.878Z" }, + { url = "https://files.pythonhosted.org/packages/a5/eb/8c07839005e5e3c6b3877d3a6e2a80ce766589f31dd2b6882b78d59a7b8c/coverage-7.15.2-cp311-cp311-win32.whl", hash = "sha256:a63b9e190711134d581c4d703df5df09851b1acf99792c7aacbbe9f41f0283c9", size = 223500, upload-time = "2026-07-15T18:54:13.525Z" }, + { url = "https://files.pythonhosted.org/packages/2e/98/59d83c257cd59f0fbaf9d9ddb26b744a576760dfd1ae16e516408894a02b/coverage-7.15.2-cp311-cp311-win_amd64.whl", hash = "sha256:8bb9f4b4279187560796a4cdaca3b0a93dd97e48ee667df005f4ed9a97403688", size = 223973, upload-time = "2026-07-15T18:54:15.163Z" }, + { url = "https://files.pythonhosted.org/packages/ea/09/2d285c8bef5c4f695d120c1c96dc11715638aa8e134069f210bb6a62a9fe/coverage-7.15.2-cp311-cp311-win_arm64.whl", hash = "sha256:8c726b232659cbd2ae57ade46509eb068c9bd7a06df9fcbff6fe484870006934", size = 223519, upload-time = "2026-07-15T18:54:16.803Z" }, + { url = "https://files.pythonhosted.org/packages/6a/50/eb5bf42e531611a9f8d272556b1ed4de503f84a91413584094487cf69f8f/coverage-7.15.2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:1adac78e5abc7c5438f7a209c9ca69d06542f0bf481d728b6989ea80b813fdf9", size = 221587, upload-time = "2026-07-15T18:54:18.439Z" }, + { url = "https://files.pythonhosted.org/packages/06/d1/da99af464c335d4e023a6efcd7ec30f63b88a43c93745154ab74ffb31cea/coverage-7.15.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:b868acc62aa5de3be7a9d05c2333bf8359ca987e43f9cb30ff8fbda6a024ab73", size = 221943, upload-time = "2026-07-15T18:54:20.062Z" }, + { url = "https://files.pythonhosted.org/packages/5b/8a/13c42723d61ca447eafa18732e8141dd6a63f2732e1c7e1502c182dd88d7/coverage-7.15.2-cp312-cp312-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:6f6966fc30e6f06ca8f98fb0ce51eda6b111b3ee8d066a8b1ec9e77fa06ab55d", size = 253450, upload-time = "2026-07-15T18:54:21.765Z" }, + { url = "https://files.pythonhosted.org/packages/d7/29/99021303f98fbdcb63504b4d07bea4cc025b9b2dd907c4f07c85d50a0dab/coverage-7.15.2-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:68af907f595ab01a78f794932ff3bdf929c316d3000810d38dbc247129e26f8b", size = 256187, upload-time = "2026-07-15T18:54:23.4Z" }, + { url = "https://files.pythonhosted.org/packages/f9/a8/fd503715ed6ca9c5d742923aa5209257340b367a867b2ced0c7d4ba8a0b9/coverage-7.15.2-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:afa29e2eff3d5729267e2cb2fd4ce9d61c952932fb2694e34ccb5d9540c6a296", size = 257301, upload-time = "2026-07-15T18:54:25.183Z" }, + { url = "https://files.pythonhosted.org/packages/da/40/3f4b8fb409810036ebc2857d36adc0498c6e957b5df0290c5036b2e143f1/coverage-7.15.2-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:bbf44513ceb1589e31948e20eafbde9deaface90e1a1afa5f5f77b4423d17ce6", size = 259562, upload-time = "2026-07-15T18:54:27.204Z" }, + { url = "https://files.pythonhosted.org/packages/0b/8a/9bdffbef47db77cce3d6b02a28f7e919b19f0106c4b080c2c2246040f885/coverage-7.15.2-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:9deddf09eecb717b7f980414b43d90a5b22ff3967d2949ab29cb0aa83d9e9098", size = 253841, upload-time = "2026-07-15T18:54:29.134Z" }, + { url = "https://files.pythonhosted.org/packages/1b/1e/9031efde019d31a06646261fce6dfc5c3c74e951e27a71e5c9a424563178/coverage-7.15.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:ae901f7e55ba405c84ee1cab3d3e962e4e871e4a2bcb9c90911adbd69b42ac5a", size = 255221, upload-time = "2026-07-15T18:54:31.142Z" }, + { url = "https://files.pythonhosted.org/packages/56/db/787acde872389fc84a9ef9d8cd1ccc658e391ab4cb5b28092a714426a394/coverage-7.15.2-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:a0f47002c6eeb7c280228467a4cb0cc15ca2103a8421b986b2d3ec04a0f9bd8b", size = 253366, upload-time = "2026-07-15T18:54:32.886Z" }, + { url = "https://files.pythonhosted.org/packages/2f/9b/6f57bc4b93c842eef1695f8cdaf2318e35e7ba54f5ba80d84be213ab7858/coverage-7.15.2-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:1cd7a5beb7af3e864a13b1f0fb26efd3695da43ef0daf71e586adfffaf34d5b2", size = 257434, upload-time = "2026-07-15T18:54:34.7Z" }, + { url = "https://files.pythonhosted.org/packages/88/26/b3186a21b2acc83e451118978905c81c7072c3333707804db09a78c096a2/coverage-7.15.2-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:97a5c5457a9fb1d6c4e06cfb5dc835871fbfb6a6a51addc9e925bdeff5ef7440", size = 252935, upload-time = "2026-07-15T18:54:36.548Z" }, + { url = "https://files.pythonhosted.org/packages/20/c2/c9f3376b2e717ea69ed7a6e9a5fcab968fb0b290db6cf4bd9a1fc7541b75/coverage-7.15.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:0901cfe6c13bcd2302da4f83e884555d2a22bda6e4c476f09ef204ba20ca536e", size = 254807, upload-time = "2026-07-15T18:54:38.296Z" }, + { url = "https://files.pythonhosted.org/packages/f0/e1/dfc15401f4a8aaeb486e1ba3e9e3c40522a6e38bd0ecf0b3f29cb8082957/coverage-7.15.2-cp312-cp312-win32.whl", hash = "sha256:b171bdd71cb7ff792bf32e376173b0ace7e7963e7e57c58dfc42063a6a7174cd", size = 223641, upload-time = "2026-07-15T18:54:40.103Z" }, + { url = "https://files.pythonhosted.org/packages/91/40/81b6d809d320cd366ec5bdf8176575e897dcb8efe7fb4b489ef9e93e4d13/coverage-7.15.2-cp312-cp312-win_amd64.whl", hash = "sha256:582edc45c2040543fef83341be23c43024a3ab3ae0c2d8bc498a06282905ad40", size = 224172, upload-time = "2026-07-15T18:54:41.882Z" }, + { url = "https://files.pythonhosted.org/packages/ef/28/9f14ec438149f7de557f45518f09b4a7917b795cc37083aa7db482693f8c/coverage-7.15.2-cp312-cp312-win_arm64.whl", hash = "sha256:a638db90c61cd219aeee65e83a24fdaa57269a741ae0cf773309208ac862cee3", size = 223556, upload-time = "2026-07-15T18:54:43.674Z" }, + { url = "https://files.pythonhosted.org/packages/fc/d5/f8c838e6b7282976f7c918884b792df7a0c42c5bba5d99c60ad2d221d56d/coverage-7.15.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:1121caa19159a38b5463eaae4b1e1fde81e525b15ecc5e000cd5b1a108f743a8", size = 221606, upload-time = "2026-07-15T18:54:45.448Z" }, + { url = "https://files.pythonhosted.org/packages/bf/37/97c926376364f66298cc44893b89cdf17b8bc406376497c4061ae4b8a8ff/coverage-7.15.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:a300c6934e0989c327b9e8a1e110329da4641149f872bbe9f70168be66da76c1", size = 221982, upload-time = "2026-07-15T18:54:47.341Z" }, + { url = "https://files.pythonhosted.org/packages/b7/30/a36050a6e83c2135ee0776f452ca3948224befc6d7f26acecc082d0c106a/coverage-7.15.2-cp313-cp313-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:2617f8799d268fabdeef42a7e89ac3a23e1deee9025427db2df970f99a89a578", size = 252972, upload-time = "2026-07-15T18:54:49.2Z" }, + { url = "https://files.pythonhosted.org/packages/31/d3/06b5f1daf95f0f15ab05bd75f26ba5f3c8b33d0bb72f3aaa3cf41d1bad3a/coverage-7.15.2-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:7dc2950a2992cd676d35c20ae63522836deeb034f08874699d14068710af3dc1", size = 255569, upload-time = "2026-07-15T18:54:51.098Z" }, + { url = "https://files.pythonhosted.org/packages/81/1c/9afb3f8de2b8d36960391c48559a2e3ff96594b58099f115921549ea8d0d/coverage-7.15.2-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:9e36686f7a442185db2400b3df171aac520869faf9deb59df687d28659eda2a6", size = 256806, upload-time = "2026-07-15T18:54:53.145Z" }, + { url = "https://files.pythonhosted.org/packages/64/d8/b989f96061a5e32d82fddd1b1b9ff48a7c8f8ae7606f0e80fd9de54b1e33/coverage-7.15.2-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:7d29ca7bd67af6e12e74632d65f026eabc1364da5c254494cd914446a28a3ef7", size = 258936, upload-time = "2026-07-15T18:54:55.015Z" }, + { url = "https://files.pythonhosted.org/packages/b8/fa/f99771f5110457c7b511c1935ca49ddf288218eaa84322e028b9334146ae/coverage-7.15.2-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:db9c8438057e5b0f6a22a0af99c0c1d26b57fbbdbd1be5861ddb8f897fcc3a2d", size = 253178, upload-time = "2026-07-15T18:54:57.527Z" }, + { url = "https://files.pythonhosted.org/packages/f6/96/c098a6044d119c751ceede7be91035fa8310170ec24a6523aff72f0a5793/coverage-7.15.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:63022c4c8dec1d0342f05c3ede99842fe3d007689acc45e86f123a1746e4a026", size = 254934, upload-time = "2026-07-15T18:54:59.41Z" }, + { url = "https://files.pythonhosted.org/packages/b2/a2/1457b3a7a50c8d77500103b97a046db863e2f59a1cf6d2f814595f349885/coverage-7.15.2-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:6c0be82b4d4aa5b2704e08518e2252f3e3d110164bcca826816801052e48a7aa", size = 252898, upload-time = "2026-07-15T18:55:01.338Z" }, + { url = "https://files.pythonhosted.org/packages/6c/0e/76958874c471ecfcdde0d2b2747bb2c61bdbf34a40636f4ce9db9923e643/coverage-7.15.2-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:4510fb9cdf6bb02dfa6af0be4a534b8102d086e22e4a33f8836df663da3d660d", size = 257056, upload-time = "2026-07-15T18:55:03.243Z" }, + { url = "https://files.pythonhosted.org/packages/7c/7c/3d7c4e3bf58baa40327dc7edc2272b17cf02299366d52763db1b0ca1556a/coverage-7.15.2-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:42ec3d989421b174a2ab607c1539f24127ad362757b7f1c0c0d7a2993f7eb37b", size = 252718, upload-time = "2026-07-15T18:55:05.029Z" }, + { url = "https://files.pythonhosted.org/packages/c8/b8/1cecffed9ce14fb25be9ba42d37b6bb61485c9a3ddd43cd3dde36b6087d8/coverage-7.15.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:e8f91bce78e32343af184c3b7fa28fcf5a9e2641f4b6623d392038f804939188", size = 254490, upload-time = "2026-07-15T18:55:06.889Z" }, + { url = "https://files.pythonhosted.org/packages/6c/2c/42984561bc7f4c045dca67516a0c50ee5ef8d84352dbeb5559dc86c4823e/coverage-7.15.2-cp313-cp313-win32.whl", hash = "sha256:434e68d531858205895eb0d74b73d20b84260de426387d53c422a5acda2cf050", size = 223647, upload-time = "2026-07-15T18:55:08.941Z" }, + { url = "https://files.pythonhosted.org/packages/41/9f/39c7c9245efc583beddf89a87683574e663ed93637f3afb6cd7b88405676/coverage-7.15.2-cp313-cp313-win_amd64.whl", hash = "sha256:26c3b04a6377fd7c09800921fa934e3a17c0020439cd59df73e73ae1d4b6a78c", size = 224190, upload-time = "2026-07-15T18:55:10.789Z" }, + { url = "https://files.pythonhosted.org/packages/c7/de/3a2883cf8a213659280ef4b403059e17a9acaeb7fc7fd4105e1226ff2e6d/coverage-7.15.2-cp313-cp313-win_arm64.whl", hash = "sha256:3ed010aa1b69cda8e827aabfca9866216c980e2dca82ab9a78c5f83689964c8b", size = 223583, upload-time = "2026-07-15T18:55:12.678Z" }, + { url = "https://files.pythonhosted.org/packages/81/5f/aed265fd7a3551a394f36dfe41868aee709b7f95db4052205b4ad1563ac3/coverage-7.15.2-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:40f633c5c5fc783732f6312280122e859538fa24461235597c13d803ea9a108a", size = 221650, upload-time = "2026-07-15T18:55:14.527Z" }, + { url = "https://files.pythonhosted.org/packages/6b/2c/222ba12a545189017120f8eddfc1a0bd4616b47d5d4a8d99421edb2fe4c6/coverage-7.15.2-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:075560438765b7a2ef43bf7aa7758661b53d889df47f062a31bda6c1ade553a2", size = 221988, upload-time = "2026-07-15T18:55:16.674Z" }, + { url = "https://files.pythonhosted.org/packages/aa/38/304b5877ab46e6c290b4292cfcf3fe28245f0e5597cad7f6acc91fc7e0a4/coverage-7.15.2-cp314-cp314-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:25fd15dd40a0a2c51a500d664ca29053c09c3259d998407bf982b6e114696138", size = 253029, upload-time = "2026-07-15T18:55:18.856Z" }, + { url = "https://files.pythonhosted.org/packages/6c/58/821b533b8db9e44cf1d8a97bd525149ced40dde1d0093da02cb78e715244/coverage-7.15.2-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:b9a6367e4aff723e8ee8190836836124284e8fcd4265e307c844010cfa074f3f", size = 255536, upload-time = "2026-07-15T18:55:21.027Z" }, + { url = "https://files.pythonhosted.org/packages/f1/f2/7aa06604c389d32ea7f0a6a988359a7eafc3cd3f8e7bc2e88cd2fdf0b877/coverage-7.15.2-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:9854ca62c152874b2060772503535be2e8f53f70b8aaa7686b094888d872f984", size = 256881, upload-time = "2026-07-15T18:55:23.125Z" }, + { url = "https://files.pythonhosted.org/packages/a2/4f/1ef342339c7916d0096bc5888cc0f653882cc7bc8f897d5cb89143287c9b/coverage-7.15.2-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:913b6c56e110da40e035bbd168353bf7aaa2544a5eaccea5d98a4629aac156c7", size = 259196, upload-time = "2026-07-15T18:55:25.099Z" }, + { url = "https://files.pythonhosted.org/packages/fe/f4/7ed055d7a9c5ec13b161773a115a5ccc6b0081d568c31fad830806306cc7/coverage-7.15.2-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:aaccad4129d735a8a4d526f26929894c9a4e8ef7034566f210b176749d6906e3", size = 253036, upload-time = "2026-07-15T18:55:27.018Z" }, + { url = "https://files.pythonhosted.org/packages/14/79/ea82cca18c242a3a38b6c017da39726aa62dcb64aa635abf79b92009975c/coverage-7.15.2-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:a164b50081fc7357331c4024ef4d17b78ba325f8380d05f5a69599a7e05257ee", size = 254887, upload-time = "2026-07-15T18:55:29.084Z" }, + { url = "https://files.pythonhosted.org/packages/a4/ba/a136db3c0d9562b00e10b72540dbf3a33cd3bc5b95060c9308e247494623/coverage-7.15.2-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:bfd341ccf78128e72c094bc70cc25b3ef309c33c7c2c66ba3ed4309549e02de1", size = 252852, upload-time = "2026-07-15T18:55:31.184Z" }, + { url = "https://files.pythonhosted.org/packages/17/17/ea334246b16b7d059953fad6fdefa11e33c68efbd3fe37b1098120a1fac2/coverage-7.15.2-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:1473b3ba8e7ee0f076117b1a72c23f579a2b9e2bb742f48a8d86ea27ca93f91a", size = 257128, upload-time = "2026-07-15T18:55:33.163Z" }, + { url = "https://files.pythonhosted.org/packages/ed/c3/074fb66d46d607855f710876b117cbda562c5ab08363528e78820449f937/coverage-7.15.2-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:17c432b5f73ad52ef46fb06019f6fa7c66ce381961cf0f7dfd1d3a4bd3a98145", size = 252668, upload-time = "2026-07-15T18:55:35.063Z" }, + { url = "https://files.pythonhosted.org/packages/e1/c1/f620850ada9b36435921c9a3a8057013422b1d964eb4bf37fe138724d192/coverage-7.15.2-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:77f0ef5011df53a4bd1b35211ab122287f8d9b8d7aa1c4553e5c2deb24b1d446", size = 254325, upload-time = "2026-07-15T18:55:37.125Z" }, + { url = "https://files.pythonhosted.org/packages/cc/31/a729ca3689404493af82ef8e6ff70bd88bdda8da89aeef6ca9b387aeb2b4/coverage-7.15.2-cp314-cp314-win32.whl", hash = "sha256:f653e5d7248c1191ec988a85c72edeab46c3ff44f90639a4ed4874ec0be90243", size = 223844, upload-time = "2026-07-15T18:55:39.078Z" }, + { url = "https://files.pythonhosted.org/packages/c6/83/5d809dc808fb1698c671f3e372259bb9158e64b7ea526fc6ab7de64de9fe/coverage-7.15.2-cp314-cp314-win_amd64.whl", hash = "sha256:9911f31aad8906abe337c271343485cf20df5e70df5d2f57f9f136e7b55f26bc", size = 224331, upload-time = "2026-07-15T18:55:41.346Z" }, + { url = "https://files.pythonhosted.org/packages/16/4e/35e488548e952795829e129995c4174df33bf432b591d1aa42c8d9e4e7ad/coverage-7.15.2-cp314-cp314-win_arm64.whl", hash = "sha256:e38def96ad59853824c97953fdcd2c320a84ba3ce99b417db78af8bb6c3db635", size = 223760, upload-time = "2026-07-15T18:55:43.518Z" }, + { url = "https://files.pythonhosted.org/packages/ed/49/dd2c86cd6374038f6e415fb5bfb86db5218553209c081384a020369dee79/coverage-7.15.2-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:835ec4e20b45f0a7f63ed78f94065aca00de033403df8377bfe8b9c6abc0a7be", size = 222384, upload-time = "2026-07-15T18:55:45.569Z" }, + { url = "https://files.pythonhosted.org/packages/d3/74/173ff17a1c0808e5a438f549f6f145d5ac7528f2791310b63523e3200ac7/coverage-7.15.2-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:7466cc7ab6dc0db871d264bf99e8779f0917ee63d40730af0552f71535a6e072", size = 222647, upload-time = "2026-07-15T18:55:47.544Z" }, + { url = "https://files.pythonhosted.org/packages/84/f8/b8cba872162356fb44ac79c10309d987206a4461e32072fc29228dad7331/coverage-7.15.2-cp314-cp314t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:e370c12133095ff18432de8c044962be85a5a96d90c6fcbce8e17e76236d2328", size = 264013, upload-time = "2026-07-15T18:55:49.768Z" }, + { url = "https://files.pythonhosted.org/packages/ee/67/a807a7586d0b8cae485308ddd55756f0806c92f8e0b411bacbf23c48edf3/coverage-7.15.2-cp314-cp314t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:fe41909c9515c3bfdb5f02c4d1f857dba322d9a9a1178069b91eea77889df63a", size = 266135, upload-time = "2026-07-15T18:55:51.941Z" }, + { url = "https://files.pythonhosted.org/packages/ce/67/cd78771dc985f7e4ebdcc82b1a96d9a932af9e806f01f2f91a89f4c72e80/coverage-7.15.2-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6aa28cfb6488e5453b5b762d65f73aa586380f6693a04d58078ce228a29b06c0", size = 268555, upload-time = "2026-07-15T18:55:54.065Z" }, + { url = "https://files.pythonhosted.org/packages/18/3e/10134cf81275188c58568f324fc74aedff32c63ca4d5bbc513a91944a6f0/coverage-7.15.2-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:bcc0aae933921d03096f53b0b03eeb702129fd406dee59f08d2efacc68681fa5", size = 269674, upload-time = "2026-07-15T18:55:56.066Z" }, + { url = "https://files.pythonhosted.org/packages/75/4a/771b77de446cba985dc414bbc5844bd21604da05dbc044286df8318a48a7/coverage-7.15.2-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:7c63387e21ab21f512c69c9756a8c7dadd322c7275edb064064433c9a09c3743", size = 263101, upload-time = "2026-07-15T18:55:58.107Z" }, + { url = "https://files.pythonhosted.org/packages/5f/b5/70a7011da15f4071943361183aefa27847f3e3aec4fd335f1cb3d3a622b1/coverage-7.15.2-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:0e55510bc98ae943cece9e667a6c0fe94c6a92913720dea34243657a17993d0c", size = 266007, upload-time = "2026-07-15T18:56:00.468Z" }, + { url = "https://files.pythonhosted.org/packages/b4/0d/f9547e804ce7ad49646ffeffac26699510efbe6c0f751b66fdc960c4e825/coverage-7.15.2-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:2ff08701be2d1556fc78b326c80a3e8042da09352ecb3819105f8e386c8a3071", size = 263611, upload-time = "2026-07-15T18:56:02.615Z" }, + { url = "https://files.pythonhosted.org/packages/ac/59/f576a396659c0efd351f5c1544f67c3560e89c7761cabf7f65e412beeda5/coverage-7.15.2-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:38c9518b7103826c403a461544e3c2e77151e8676d06eaed85911a97e962584a", size = 267344, upload-time = "2026-07-15T18:56:04.622Z" }, + { url = "https://files.pythonhosted.org/packages/7c/5d/c2e4fce3579c0cb635024293f1a32bbe26df101b3e3a69f22243d1352b6c/coverage-7.15.2-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:dee88b1ed88587abd8c0269a1fc1f4cc77f7750d1dfde2869e2a123af420e67d", size = 262456, upload-time = "2026-07-15T18:56:06.641Z" }, + { url = "https://files.pythonhosted.org/packages/bb/dd/956287d69436b66094bc4b57ac2da71e43bfd2a5524e958900b9f582fcf8/coverage-7.15.2-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:2fbeeeecea279727f8ac16c8e1133ddfeee793e985c86ae343d6a5ce744eef8c", size = 264771, upload-time = "2026-07-15T18:56:08.795Z" }, + { url = "https://files.pythonhosted.org/packages/2c/5a/6f979530c2734c575de77cf58f5f28d51f7123a94b5030fd9156fe5f363c/coverage-7.15.2-cp314-cp314t-win32.whl", hash = "sha256:cb0fddaa6884be6aae36ced9544b5e90f7d5f03845a2853bf47a14953a4e8688", size = 224151, upload-time = "2026-07-15T18:56:10.856Z" }, + { url = "https://files.pythonhosted.org/packages/54/7e/27f6b2a74d484742f4017553e710b01e396b23d809df3e95ca0bb9a2824b/coverage-7.15.2-cp314-cp314t-win_amd64.whl", hash = "sha256:77f091ea3a9cc611cd29f433565476bc1936c084ac8eee00ea0e7e70c27e4199", size = 224981, upload-time = "2026-07-15T18:56:12.928Z" }, + { url = "https://files.pythonhosted.org/packages/b1/48/284863423aa474240f6842bd00d680da22f4e6ea2e466618ef7c9c9e69a9/coverage-7.15.2-cp314-cp314t-win_arm64.whl", hash = "sha256:6fc448c377d6eeb00a47c673494bd9bae29280ca53987e1869e67ebedfe20658", size = 224294, upload-time = "2026-07-15T18:56:15.156Z" }, + { url = "https://files.pythonhosted.org/packages/ec/82/32e3bd191d498e64f6f911ad55d14006a0861e54869d2d32452326399e65/coverage-7.15.2-py3-none-any.whl", hash = "sha256:eb6bcae8d1a9d305351ecb108232441d11c5cfe9de840a04388ba5d2db8d735c", size = 213375, upload-time = "2026-07-15T18:56:17.305Z" }, ] [package.optional-dependencies] @@ -956,16 +951,16 @@ wheels = [ [[package]] name = "docker" -version = "7.1.0" +version = "7.2.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "pywin32", marker = "sys_platform == 'win32'" }, { name = "requests" }, { name = "urllib3" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/91/9b/4a2ea29aeba62471211598dac5d96825bb49348fa07e906ea930394a83ce/docker-7.1.0.tar.gz", hash = "sha256:ad8c70e6e3f8926cb8a92619b832b4ea5299e2831c14284663184e200546fa6c", size = 117834, upload-time = "2024-05-23T11:13:57.216Z" } +sdist = { url = "https://files.pythonhosted.org/packages/88/7f/731ff914b0255d3d065f45fd4e626d4b8c95dbcbaada049f337a6ac16410/docker-7.2.0.tar.gz", hash = "sha256:cebb93773d334f778e023a7ee352a8d6e13ab1bd3b863a4d4a59dec897df43ac", size = 118731, upload-time = "2026-07-09T14:53:46.39Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/e3/26/57c6fb270950d476074c087527a558ccb6f4436657314bfb6cdf484114c4/docker-7.1.0-py3-none-any.whl", hash = "sha256:c96b93b7f0a746f9e77d325bcfb87422a3d8bd4f03136ae8a85b37f1898d5fc0", size = 147774, upload-time = "2024-05-23T11:13:55.01Z" }, + { url = "https://files.pythonhosted.org/packages/75/23/529140fe1aab80fc6992f93a706deec709140a6397439139a054e1515c45/docker-7.2.0-py3-none-any.whl", hash = "sha256:a3f45fdeb9165e2d25d9a1d02ddf3bc70fb572cf5ebbf9b58558c22caf29b71f", size = 148775, upload-time = "2026-07-09T14:53:45.224Z" }, ] [[package]] @@ -1009,7 +1004,7 @@ wheels = [ [[package]] name = "fastapi" -version = "0.137.1" +version = "0.139.2" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "annotated-doc" }, @@ -1018,9 +1013,9 @@ dependencies = [ { name = "typing-extensions" }, { name = "typing-inspection" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/d5/b1/e5b92c59d2c37817e77c1a8c2fc1f79cdcc04c68253e5406b43e3204cba7/fastapi-0.137.1.tar.gz", hash = "sha256:822360704230d9533d8d9475399613525968aa2f0b5bd2a3ccc9f18c88fd541c", size = 408293, upload-time = "2026-06-15T11:28:20.79Z" } +sdist = { url = "https://files.pythonhosted.org/packages/cd/95/d3f0ae10836324a2eab98a52b61210ac609f08200bf4bb0dc8132d32f78a/fastapi-0.139.2.tar.gz", hash = "sha256:333145a6891e9b5b3cfceb69baf817e8240cde4d4588ae5a10bf56ffacb6255e", size = 423428, upload-time = "2026-07-16T15:06:17.912Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/da/35/380b9a5922f4340e51c309cde09e5bd32e62f02302971bee30dc15aa0624/fastapi-0.137.1-py3-none-any.whl", hash = "sha256:64f6983c59e45c4b9fdc44e57cb8035c2451ee91ea8e8ec042aca37de7cf6b69", size = 121877, upload-time = "2026-06-15T11:28:19.523Z" }, + { url = "https://files.pythonhosted.org/packages/5f/c7/cb03251d9dfb177246a9809a76f189d21df32dbd4a845951881d11323b7f/fastapi-0.139.2-py3-none-any.whl", hash = "sha256:b9ad015a835173d59865e2f5d8296fbc2b317bf56a2ba1a5bfbdd03de2fd4b1c", size = 130234, upload-time = "2026-07-16T15:06:19.557Z" }, ] [[package]] @@ -1088,11 +1083,11 @@ wheels = [ [[package]] name = "filelock" -version = "3.29.4" +version = "3.30.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/e6/dc/be6cbe99670cd6e4ad387123647cb08e0c32975e223f82551e914c5568a6/filelock-3.29.4.tar.gz", hash = "sha256:10cdb3656fc44541cdf30652a93fb10ec6b05325620eb316bd26893e4201538a", size = 63028, upload-time = "2026-06-13T16:12:00.744Z" } +sdist = { url = "https://files.pythonhosted.org/packages/83/2b/8b6480a70a647035334a604d0931926de4b5cd1f57835d45ad5eed2b1a1e/filelock-3.30.0.tar.gz", hash = "sha256:1774e682dbe443bd60f9609162fc596e2c80dc84ffc2957068953406d0520090", size = 174927, upload-time = "2026-07-16T03:53:58.152Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/13/37/a065dc3bd6e49423a6532c642ca7378d3f467b1ef44c2800c937af7f9739/filelock-3.29.4-py3-none-any.whl", hash = "sha256:dac1648087d5115554850d113e7dd8c83ab2d38e3435dde2d4f163847e57b767", size = 42757, upload-time = "2026-06-13T16:11:59.582Z" }, + { url = "https://files.pythonhosted.org/packages/52/af/9b01bcf5c91e81899bb890b87bd9077732a9b3365c098e67fe77958c39ed/filelock-3.30.0-py3-none-any.whl", hash = "sha256:40632998f0772e64183bb819f086a1b9def6be1090cf1dcb9d45f46806ef279b", size = 93131, upload-time = "2026-07-16T03:53:56.727Z" }, ] [[package]] @@ -1249,16 +1244,16 @@ wheels = [ [[package]] name = "fsspec" -version = "2026.4.0" +version = "2026.6.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/d5/8d/1c51c094345df128ca4a990d633fe1a0ff28726c9e6b3c41ba65087bba1d/fsspec-2026.4.0.tar.gz", hash = "sha256:301d8ac70ae90ef3ad05dcf94d6c3754a097f9b5fe4667d2787aa359ec7df7e4", size = 312760, upload-time = "2026-04-29T20:42:38.635Z" } +sdist = { url = "https://files.pythonhosted.org/packages/10/a1/ae4e3e5003468d6391d2c77b6fa1cd73bd5d13511d81c642d7b28ac90ed4/fsspec-2026.6.0.tar.gz", hash = "sha256:f5bac145310fe30e16e1471bd6840b2d990d609e872251d7e674241822abf01a", size = 313646, upload-time = "2026-06-16T01:57:28.105Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/d5/0c/043d5e551459da400957a1395e0febbf771446ff34291afcbe3d8be2a279/fsspec-2026.4.0-py3-none-any.whl", hash = "sha256:11ef7bb35dab8a394fde6e608221d5cf3e8499401c249bebaeaad760a1a8dec2", size = 203402, upload-time = "2026-04-29T20:42:36.842Z" }, + { url = "https://files.pythonhosted.org/packages/e5/22/4222d7ddf3da30f363edaa98e329c2bce6c65497c9cb2810931c8b2c0fbc/fsspec-2026.6.0-py3-none-any.whl", hash = "sha256:02e0b71817df9b2169dc30a16832045764def1191b43dcff5bb85bdee212d2a1", size = 203949, upload-time = "2026-06-16T01:57:26.358Z" }, ] [[package]] name = "google-adk" -version = "2.2.0" +version = "2.4.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "aiosqlite" }, @@ -1286,27 +1281,27 @@ dependencies = [ { name = "watchdog" }, { name = "websockets" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/4a/65/3ff3f50b10dac3323ddecd694515e9f9ed345886e0eaf666d0e42c90748b/google_adk-2.2.0.tar.gz", hash = "sha256:04cb6318aba8829fe7c941ee1b456ccb4745253898c13595708c9eb07b4582ff", size = 3391545, upload-time = "2026-06-04T22:15:12.9Z" } +sdist = { url = "https://files.pythonhosted.org/packages/2a/a1/6048b1c22817859bafc1101f8ba26f704233d9acb07e715dff5fb41b9b55/google_adk-2.4.0.tar.gz", hash = "sha256:5a2996b288d591deefcb277eeeeb7da838d72056675763bfef52ad3b36975dde", size = 3566788, upload-time = "2026-07-07T19:46:14.802Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/64/f5/44a3b20b17bac130497f2d1dde8b93c90cfc026983cd94f24488d540ea70/google_adk-2.2.0-py3-none-any.whl", hash = "sha256:ebdf3d931dc2b9c5b30d995358fc2ae99d59594c48a4aaf7496869ccd2c5f245", size = 3912613, upload-time = "2026-06-04T22:15:15.411Z" }, + { url = "https://files.pythonhosted.org/packages/fd/ab/12ec18054990ac69f37dae8327f5d8d5e04557bada0d8d725afd872d3020/google_adk-2.4.0-py3-none-any.whl", hash = "sha256:fba91f1a693e5fc2fd13dc40d625562bd52e44a7baaeecedb01811a68063d847", size = 4123277, upload-time = "2026-07-07T19:46:13.026Z" }, ] [[package]] name = "google-auth" -version = "2.54.0" +version = "2.56.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "cryptography" }, { name = "pyasn1-modules" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/15/f6/494e18317546d7def90c957b71d68b025d24f0e22e486c2606bc57765c48/google_auth-2.54.0.tar.gz", hash = "sha256:130f6fd5e3f497fdad897a23ed9489973437edf561238c4b92a4d02c435f8af9", size = 343161, upload-time = "2026-06-12T18:03:17.606Z" } +sdist = { url = "https://files.pythonhosted.org/packages/58/66/b4ba60005743e01933e22b4f62313e063f7460458b7d8a358427b4930013/google_auth-2.56.0.tar.gz", hash = "sha256:f90fa030b569a92654b9d690665a073841df33d57487be53db583a9a0867a553", size = 364629, upload-time = "2026-07-13T19:09:57.143Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/70/c5/d53bddd2c0949833fcb4ea06f9d5dd1c40575a1a4214cd1021eff57ba301/google_auth-2.54.0-py3-none-any.whl", hash = "sha256:784e9837f92244141250470d47c893df50cbab485ce491aca5e9deb558ad2b48", size = 249878, upload-time = "2026-06-12T18:02:57.58Z" }, + { url = "https://files.pythonhosted.org/packages/a8/7d/cd3e187f14ce832e419e70709bfcc40cb0dc11517d5d03c9d3919bcc3101/google_auth-2.56.0-py3-none-any.whl", hash = "sha256:6e88c10217e07a92bfd01cac8ee99e32ccfb08414c3102e6c5b8d58f37a0d1e0", size = 257976, upload-time = "2026-07-13T19:09:42.685Z" }, ] [package.optional-dependencies] pyopenssl = [ - { name = "pyopenssl" }, + { name = "cryptography" }, ] requests = [ { name = "requests" }, @@ -1314,7 +1309,7 @@ requests = [ [[package]] name = "google-genai" -version = "2.10.0" +version = "2.11.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "anyio" }, @@ -1328,9 +1323,9 @@ dependencies = [ { name = "typing-extensions" }, { name = "websockets" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/cd/fe/b796087493c3c55371aa58b9f264841ace5bfdf8c668cafa7afa33c44bec/google_genai-2.10.0.tar.gz", hash = "sha256:77912cd558cd7dfd5b75c25fd1c609e78d7954dde583331104022a46ea90f9ee", size = 600039, upload-time = "2026-06-24T01:33:18.157Z" } +sdist = { url = "https://files.pythonhosted.org/packages/a6/01/e7b5f3aac89200c78318ed7643401e7f5ed3131b0cd353c07483606b1e61/google_genai-2.11.0.tar.gz", hash = "sha256:4c5e524d24b145c96be327f9a7f8f04b0fe4efee0533877795e9848afed01749", size = 622366, upload-time = "2026-07-09T17:49:43.862Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/e0/39/00bcfd94de255d24249401efff4f48d77bf6066b46447e519fa193c0c299/google_genai-2.10.0-py3-none-any.whl", hash = "sha256:d5350311567ae660c24cbc1752aee4b3d660f89c0106d2dcd2a69978c35afe1e", size = 957974, upload-time = "2026-06-24T01:33:16.296Z" }, + { url = "https://files.pythonhosted.org/packages/93/ef/d296c23390160a8b0b1dafb36dd3cb36a39ed40c81cd27e04e6233334186/google_genai-2.11.0-py3-none-any.whl", hash = "sha256:5bc8186100e1d34d691fbe0cba392b7e04e98d286ca952323a6672d054accf95", size = 984162, upload-time = "2026-07-09T17:49:42.15Z" }, ] [[package]] @@ -1365,72 +1360,72 @@ wheels = [ [[package]] name = "griffelib" -version = "2.0.2" +version = "2.1.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/9d/82/74f4a3310cdabfbb10da554c3a672847f1ed33c6f61dd472681ce7f1fe67/griffelib-2.0.2.tar.gz", hash = "sha256:3cf20b3bc470e83763ffbf236e0076b1211bac1bc67de13daf494640f2de707e", size = 166461, upload-time = "2026-03-27T11:34:51.091Z" } +sdist = { url = "https://files.pythonhosted.org/packages/33/e4/8d187ea29c2e30b3a09505c567513077d6117861bde1fbd997a167f262ec/griffelib-2.1.0.tar.gz", hash = "sha256:762a186d2c6fd6794d4ea20d428d597ffb857cb56b66421651cbba15bdd5e813", size = 216234, upload-time = "2026-06-19T12:05:42.278Z" } 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" }, + { url = "https://files.pythonhosted.org/packages/e4/d3/5268aeabf2ad82658c4e2ff3a060648d0f02f3926cb53247c0e4d0dab49e/griffelib-2.1.0-py3-none-any.whl", hash = "sha256:cc7b3d2d2865ad0b909fcc38086e3f554b5ea7acbaa7bbb7ecaa3f5dfb7d9f00", size = 142560, upload-time = "2026-06-19T12:05:38.742Z" }, ] [[package]] name = "grpcio" -version = "1.81.1" +version = "1.82.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/b0/b5/1ff353970a87eda4c98251e34d2dfd214abd4982dc89119c9252a2a482d2/grpcio-1.81.1.tar.gz", hash = "sha256:6fa10a767143a5e82e8eaab53918af0cd8909a57a27f8cb2288b80a613ac671b", size = 13026582, upload-time = "2026-06-11T12:46:51.673Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/9a/d5/f2b159d8eec08be2a855ef698f5b6f7f9fdda022e4dd9e4f5d968affd678/grpcio-1.81.1-cp310-cp310-linux_armv7l.whl", hash = "sha256:6f9a0c9c1cc15c112d1c053064fd032b64917062292c3d70aea280e02ae10b77", size = 6086868, upload-time = "2026-06-11T12:44:19.364Z" }, - { url = "https://files.pythonhosted.org/packages/80/41/9c95232b94b219ed8b14029d9cd000e0381cafba869c451dda60af84f4ba/grpcio-1.81.1-cp310-cp310-macosx_11_0_universal2.whl", hash = "sha256:69ef28e54fc85397f91b8c19592b8ef3d81952080366914823bd8572a2958120", size = 12062291, upload-time = "2026-06-11T12:44:27.142Z" }, - { url = "https://files.pythonhosted.org/packages/83/8b/bd9284bdd665ddf877a3e8bc2930d1bcf6ebdbae7b0da5c783dc26bd6e33/grpcio-1.81.1-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:15641444eca4a29358107b3dceb74c1c6305c55c822fd199b458aaea4068a7fb", size = 6635242, upload-time = "2026-06-11T12:44:30.741Z" }, - { url = "https://files.pythonhosted.org/packages/60/24/78fa025517a925f1a17da71c4ef9d5f1c6f9fa65af22dfb523c5c6317a21/grpcio-1.81.1-cp310-cp310-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:d4b2dddfc219f54f956ccd53cf76a1d338ffe68fc7f2849ec9c7feb9927ff692", size = 7332974, upload-time = "2026-06-11T12:44:33.72Z" }, - { url = "https://files.pythonhosted.org/packages/f7/11/402295b388dd35861007f8a26a37c2e2f284212d57bdf407c31f36043746/grpcio-1.81.1-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:ca1cc11d82677b9662082e5478b7528e2b7db7beaa6bdff42bd62789d81be399", size = 6836597, upload-time = "2026-06-11T12:44:36.108Z" }, - { url = "https://files.pythonhosted.org/packages/4d/71/37b10fd4fd579ffade6e695c14e9df5e8cba9e2365b81c131da438b67c34/grpcio-1.81.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:aa2ba7d2ad6df4d80127cea65e5b8d5e2c3adbf153ff4804452836328aca7c54", size = 7440660, upload-time = "2026-06-11T12:44:38.664Z" }, - { url = "https://files.pythonhosted.org/packages/4a/d5/40203f828abc83d458b634666df6df13778032f178c03845ad5a93682388/grpcio-1.81.1-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:592b5fee597faa91cce2dd294dd7d9a1c83d76c4dbf877e33ec1adb866b2fbed", size = 8443171, upload-time = "2026-06-11T12:44:41.678Z" }, - { url = "https://files.pythonhosted.org/packages/eb/2c/0ed82ea35b5ec595e10444940c1db8c0e0ef57aa46bc8797d5ff838a219e/grpcio-1.81.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:62481553b1793a27e9b9c3cf9e5bd483ef045ca72462592074b46d42b0c4d9b9", size = 7868905, upload-time = "2026-06-11T12:44:44.854Z" }, - { url = "https://files.pythonhosted.org/packages/9e/1f/dcbdc1a68a07cc2b631c3098953794f17d75f93426a019240b90ce5423d6/grpcio-1.81.1-cp310-cp310-win32.whl", hash = "sha256:bb693b1e3d9a2f3fd228e2110daf4b5aeedb36761ca1e4282f74725f6d89f611", size = 4202215, upload-time = "2026-06-11T12:44:47.165Z" }, - { url = "https://files.pythonhosted.org/packages/75/a1/d7ab9f1f42efcb7d9e6111d38be6b367737a72ea2c534e1f55c81e1b6436/grpcio-1.81.1-cp310-cp310-win_amd64.whl", hash = "sha256:88268ca418cacea64cecb0d1d600d3c6b3a8038fcba02e1e205178c5b1f47661", size = 4936582, upload-time = "2026-06-11T12:44:49.479Z" }, - { url = "https://files.pythonhosted.org/packages/52/ea/1c2fa386b718ff493225e61cfc052ef400b4d6ffc54cbe261026432624b5/grpcio-1.81.1-cp311-cp311-linux_armv7l.whl", hash = "sha256:d71d30f2d92f67d944631c523713934fee37292469e182ebcd2c1dd8a64ce53f", size = 6093112, upload-time = "2026-06-11T12:44:52.131Z" }, - { url = "https://files.pythonhosted.org/packages/2b/18/acf45fa8bd1bc5d7b0c2fd3dc4c209379fbd5bb396b440b68a83342226b7/grpcio-1.81.1-cp311-cp311-macosx_11_0_universal2.whl", hash = "sha256:b137f4bf3ada9dc44d411478decc6ff09a79ed30b306cd2abaa98408c3588137", size = 12074277, upload-time = "2026-06-11T12:44:55.354Z" }, - { url = "https://files.pythonhosted.org/packages/48/d7/ee86a60699b7db039f772a2c4a7e4facc7138984ff42c0130933a0063884/grpcio-1.81.1-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:a3acb384427816dd5d470f47e62137b87f74da694faa8a50147012cf40df276a", size = 6640348, upload-time = "2026-06-11T12:44:59.223Z" }, - { url = "https://files.pythonhosted.org/packages/26/ee/d2de5e47378ffc207d476c230fea3be4d2601edbce9995f4fe45535d4896/grpcio-1.81.1-cp311-cp311-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:f9a0ebbe45c29b5e5866593c12b78bd9035f0f0f0d4bc8361680cd580d99db49", size = 7331842, upload-time = "2026-06-11T12:45:02.001Z" }, - { url = "https://files.pythonhosted.org/packages/23/d6/abeda5c2b896a0b341584fe5ac411bbf72e197a9a374c355fb90965e08d2/grpcio-1.81.1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:0a37165cc80b1a368384b383e63a4c38116a10467ae44c904d2d7468c4470ec2", size = 6842229, upload-time = "2026-06-11T12:45:04.76Z" }, - { url = "https://files.pythonhosted.org/packages/10/1c/1f0da7d590b4aeee006826ba568d0e419ca14b23e18f901a3da3e9fba613/grpcio-1.81.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:6282caffb41ec326d4cb67ca9cf53b739d1b2f975a2acb498c7418e9f7d9a416", size = 7446096, upload-time = "2026-06-11T12:45:07.499Z" }, - { url = "https://files.pythonhosted.org/packages/6a/81/5c505d508f7c887aa7982d21443a4126597c80d34b0bcf40f9cec576d7f3/grpcio-1.81.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:a35009284d0d3d5c2c9601c164a911b8b4331608d98a9a66d47d97bb2f522b70", size = 8445238, upload-time = "2026-06-11T12:45:10.243Z" }, - { url = "https://files.pythonhosted.org/packages/f7/b2/524847365122ee509ca17bcc4e092198b700e94af7bfd5bb5e6dd9f3ee66/grpcio-1.81.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:1b22c80559854b789a01fd89e8929b3798a156c0829b5282a8939f33ad4115ad", size = 7873989, upload-time = "2026-06-11T12:45:13.102Z" }, - { url = "https://files.pythonhosted.org/packages/18/fa/07c037c50b006909d1d13a5848774f8aa7b242f70dc03a035c64eea0e6db/grpcio-1.81.1-cp311-cp311-win32.whl", hash = "sha256:428bec0161b48d8cf583c068591bc0016d0d9cfff52462b72b3884861ea768c5", size = 4202223, upload-time = "2026-06-11T12:45:16.166Z" }, - { url = "https://files.pythonhosted.org/packages/41/ed/6bff15376920942fac6b95b9802752b837437172c9e8fc2d3170546b89cc/grpcio-1.81.1-cp311-cp311-win_amd64.whl", hash = "sha256:30e825f6848d9f18bba350ed6c75c1b02a0b5184474a31db9a32b1fa66fd8c79", size = 4941303, upload-time = "2026-06-11T12:45:18.724Z" }, - { url = "https://files.pythonhosted.org/packages/85/07/9a979c81738863a738dc23d65177056e71fbb2db817740ed870b33434e7a/grpcio-1.81.1-cp312-cp312-linux_armv7l.whl", hash = "sha256:8b39472beafc0bdcafc4c8c73ad082ebfdb449d566897a61e7acb4fa88089115", size = 6053264, upload-time = "2026-06-11T12:45:21.017Z" }, - { url = "https://files.pythonhosted.org/packages/75/95/539706ca0d3bd40dbad583dc56fd883da941f37556b629132da5762781b9/grpcio-1.81.1-cp312-cp312-macosx_11_0_universal2.whl", hash = "sha256:12b7524c88d4026d3dcb7b0ebe16b6714f3b4af402ddd0f0639ab064a00c87c3", size = 12052560, upload-time = "2026-06-11T12:45:23.652Z" }, - { url = "https://files.pythonhosted.org/packages/e0/44/f257b7e0bd69c93b06c6cb8ac8d1b901ccb42bedabd83c1a4c77a71f8810/grpcio-1.81.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:1e123f9b37edb8375fd74130d1f69c944bbf0a7b06761ae7211154b8759e94d2", size = 6595983, upload-time = "2026-06-11T12:45:26.963Z" }, - { url = "https://files.pythonhosted.org/packages/b9/f3/19782aa04c960968bef8c5539329d8e3bbc3364e2e46d19eb5e5cc5e43b7/grpcio-1.81.1-cp312-cp312-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:2c2e2ae6867c2966b8daccc836d54a13218e0007e9a490aeb81dd05be64d22d7", size = 7303455, upload-time = "2026-06-11T12:45:29.707Z" }, - { url = "https://files.pythonhosted.org/packages/eb/8c/dea020b6d91508cd84463917a63149ec196ee7db505d032ae43fcb3303b9/grpcio-1.81.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:766bc7c9a9c340342f4c864ccbda8e78111e4751f13b895812b9c148fb79e9d0", size = 6809167, upload-time = "2026-06-11T12:45:32.52Z" }, - { url = "https://files.pythonhosted.org/packages/1c/c7/3030dd940408083bd32cd95d634777a71605ade4887154d93e8a89244946/grpcio-1.81.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:b259a04a737cb3496be0901328eb8b7552ed8df4865d8c8f1cf1bffcfc0776a3", size = 7412536, upload-time = "2026-06-11T12:45:35.403Z" }, - { url = "https://files.pythonhosted.org/packages/e0/dd/1172a9e42b168edcafefad6115346ef619a3fc02158bb170e66ced24bcdd/grpcio-1.81.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:85b10a45b8993d195c4f3ff57025b8d1e11834909ee475c403bfa60cb4caefaf", size = 8408276, upload-time = "2026-06-11T12:45:37.78Z" }, - { url = "https://files.pythonhosted.org/packages/25/7a/71437c7f3596e5246155c515852795a85a1a8d228190212432b13b97a95d/grpcio-1.81.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:8ea1936c26b99999b27479853039a7f34713f56c49375ad52b38535ec93a796c", size = 7849660, upload-time = "2026-06-11T12:45:40.627Z" }, - { url = "https://files.pythonhosted.org/packages/65/40/7debc0da45d2efebafb82da75644be347497fe4ee250514b8cd3b86ae8bf/grpcio-1.81.1-cp312-cp312-win32.whl", hash = "sha256:a185a04039df6cae8648bc8ab6d6fde7bf94f7188ecf7828e76ac52eef1e41d6", size = 4185819, upload-time = "2026-06-11T12:45:43.027Z" }, - { url = "https://files.pythonhosted.org/packages/2e/b9/8fe3ba5ed462067774ebc1f9c7f26aa7ebcc280ddd476be107153de1339e/grpcio-1.81.1-cp312-cp312-win_amd64.whl", hash = "sha256:3ad74f8bb1a18963914c5452d289422830b39459e8776ebbcd207be1fbfb1d94", size = 4930461, upload-time = "2026-06-11T12:45:45.775Z" }, - { url = "https://files.pythonhosted.org/packages/7a/42/dcc2e4b600538ef18327c0839d56b7d3c3812337c5d710df5877dbb39b1e/grpcio-1.81.1-cp313-cp313-linux_armv7l.whl", hash = "sha256:b10e1ff4756ed27d5a29d7fc79cfce7ef1ff56ad20025b89bac7cf79e09abbbe", size = 6054466, upload-time = "2026-06-11T12:45:48.43Z" }, - { url = "https://files.pythonhosted.org/packages/7b/4a/a36e03210183a8a7d4c80c3936acee679f4bd77d5861f369db47b2cc5f05/grpcio-1.81.1-cp313-cp313-macosx_11_0_universal2.whl", hash = "sha256:819edbdcb42ab8598b494bcf0222684bbb7a3c772bd1b1f0be7e029a6063c28e", size = 12048795, upload-time = "2026-06-11T12:45:54.011Z" }, - { url = "https://files.pythonhosted.org/packages/b0/d5/d68e30b29098f63beab6fe501100fe82674ff142b32c672532da86a99b3a/grpcio-1.81.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:c5bf2dc311127d91230cc79b92188c082634a06cf66c5234db49a43b910183b0", size = 6599094, upload-time = "2026-06-11T12:45:57.799Z" }, - { url = "https://files.pythonhosted.org/packages/3d/b3/e837954d279754f638a11cca5dcf6b24a005efb398984cefaf7735945a54/grpcio-1.81.1-cp313-cp313-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:e8ca6a1fcdb2943c9cbc1804a1baf3acb6071d72a471591678ded84218006e14", size = 7307182, upload-time = "2026-06-11T12:46:00.568Z" }, - { url = "https://files.pythonhosted.org/packages/0d/1e/b47957057e729adc6cdf519a47f8be2562b7140e280f1418443eb4022192/grpcio-1.81.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:e64dd101d380a115cc5a0c7856788adb535f1a4e21fc543775602f8be95180ae", size = 6810962, upload-time = "2026-06-11T12:46:03.312Z" }, - { url = "https://files.pythonhosted.org/packages/40/26/569868e364e05b19ec8f969da53d230bcd89c962cd198f7c29943155c4d3/grpcio-1.81.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:98a07f9bf591e3a8919797bee1c53f026ba4acd587e5a4404c8e57c9ec36b2a5", size = 7415698, upload-time = "2026-06-11T12:46:06.005Z" }, - { url = "https://files.pythonhosted.org/packages/36/0c/5440a0582cb5653fc42a6e262eeb22700943313f8076f9dc927491b20a59/grpcio-1.81.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:c261d74b1a945cf895a9d6eccd1685a8e837531beaab782da4d630a8d12deffb", size = 8407779, upload-time = "2026-06-11T12:46:08.84Z" }, - { url = "https://files.pythonhosted.org/packages/ff/aa/66fe9f39871d766987d869a03ee0842a026f499c7b1e62decb9e78a8088e/grpcio-1.81.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:58ad1131c300d3c9b933802b3cc4dc69d380822935ba50b28703156ea826fbf7", size = 7844521, upload-time = "2026-06-11T12:46:12.171Z" }, - { url = "https://files.pythonhosted.org/packages/f0/9e/69bb7194861bcd28fb3193261d4f9c3831b4446993f002cf59068943e7ab/grpcio-1.81.1-cp313-cp313-win32.whl", hash = "sha256:78e29211f26da2fdd0e9c6d2b79f489476140cf7029b6a64808ade7ca4156a42", size = 4182786, upload-time = "2026-06-11T12:46:15.192Z" }, - { url = "https://files.pythonhosted.org/packages/0d/20/3da8bb0d637feccdc3e1e419bb511ce93651ce7d54164f95de22cc0b8b34/grpcio-1.81.1-cp313-cp313-win_amd64.whl", hash = "sha256:edb59506291b647a30884b1d51a599d605f40b20af4a7dc3d33786a47a31de60", size = 4928648, upload-time = "2026-06-11T12:46:17.823Z" }, - { url = "https://files.pythonhosted.org/packages/b6/58/19414622b1bf6981bc9c05a365bd548e71876c89000083b3af489251e9c0/grpcio-1.81.1-cp314-cp314-linux_armv7l.whl", hash = "sha256:506f48f2f9c29b143fca3dad7b0d518c188b6c9648c75a2ae6e2d9f2c13a060b", size = 6055336, upload-time = "2026-06-11T12:46:20.557Z" }, - { url = "https://files.pythonhosted.org/packages/32/f1/2ec88adb92b0eba970dd0e0e7dd086341daa3c75eba4f735f9e44bf684b0/grpcio-1.81.1-cp314-cp314-macosx_11_0_universal2.whl", hash = "sha256:d865db4a6318e1c1bea83292e0ed231090538fc4ca45425b0f0480eb338bbc6e", size = 12056279, upload-time = "2026-06-11T12:46:24.255Z" }, - { url = "https://files.pythonhosted.org/packages/41/36/e8c5f8c6ec71de73733695ebc809e98b178b534ec6d8eaa31a7ebab4ad4c/grpcio-1.81.1-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:e2aa72e3ce1770317ef534f63d397b55e130725f5149bd36077c3b539019db27", size = 6608225, upload-time = "2026-06-11T12:46:27.601Z" }, - { url = "https://files.pythonhosted.org/packages/30/22/96fc577a845ab093326d9ab1adb874bd4936c8cf98ac8ed2f3db13a0a2fb/grpcio-1.81.1-cp314-cp314-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:0490c30c261eded63f3f354979f9dc4502a9fb944cccb60cd9dc85f5a7349854", size = 7306576, upload-time = "2026-06-11T12:46:30.514Z" }, - { url = "https://files.pythonhosted.org/packages/76/7b/61dab5d5969f28d97fb1009cead1df0a5cd987d3315e1b37f18a4449f8bc/grpcio-1.81.1-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:410482da976329fe5f4067270401b12cf2bd552ff8020f054ecfaddb5475f9d6", size = 6812165, upload-time = "2026-06-11T12:46:33.699Z" }, - { url = "https://files.pythonhosted.org/packages/82/78/6e501929d4f5f96462fd82fd9f0f06e5f9612207582b862868d68757b27d/grpcio-1.81.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:e3657301562ac3cb8018d30d0d3ebfa39932239f7b5703422057ef14b69949f5", size = 7422962, upload-time = "2026-06-11T12:46:36.511Z" }, - { url = "https://files.pythonhosted.org/packages/2a/7e/f2157589e66daa78ebb3165942d05a08bdea93b9d11c2bc1e172aef89685/grpcio-1.81.1-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:24c8e57504c8f45b237e40b99262d181071e5099a07053695b75d97bb53053a0", size = 8408176, upload-time = "2026-06-11T12:46:39.803Z" }, - { url = "https://files.pythonhosted.org/packages/da/df/c6717fef716e00d235ffb96123baf6dce76d6004f6233fa767c502861460/grpcio-1.81.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:b427c19380991a4eaab2f6144b64b99b412043314c6bf4ab544f97bb31ee4190", size = 7846681, upload-time = "2026-06-11T12:46:43.013Z" }, - { url = "https://files.pythonhosted.org/packages/36/84/3502e9f210a6a5c4438c8aca3f88edd2e04f6a27f3d41b26cf0a0024b096/grpcio-1.81.1-cp314-cp314-win32.whl", hash = "sha256:61233fe8951e5c85dff81c2458b6528624760166946b5b47ea150a589168411f", size = 4264615, upload-time = "2026-06-11T12:46:45.741Z" }, - { url = "https://files.pythonhosted.org/packages/ff/b0/4af731ff7492c68a96e4c71bfd0f4590acde92b31c6fe4894e6465c10ff6/grpcio-1.81.1-cp314-cp314-win_amd64.whl", hash = "sha256:3768a5ff1b2125e6f552e561b6b2dca0e64982d8949689b4df145cf8b98d7821", size = 5070275, upload-time = "2026-06-11T12:46:48.486Z" }, +sdist = { url = "https://files.pythonhosted.org/packages/90/bc/656b89387d6f4ed7e0686c7b64c2ae7e554a759aa58122c8e5fb99392c32/grpcio-1.82.1.tar.gz", hash = "sha256:707b24abd90fcb1e45bcc080577da1dbf9971d107490589b9539af8e1e77b4b5", size = 13187300, upload-time = "2026-07-08T12:36:16.588Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/a3/14/5d05bfd85c101cbe44a12d7c1cea9c40698e0438cddf3a70019f735b5a27/grpcio-1.82.1-cp310-cp310-linux_armv7l.whl", hash = "sha256:91859d1cac5f47caec5fc40e9f827500cdb54ce5b36450dc9a65616b5af49c17", size = 6177087, upload-time = "2026-07-08T12:34:06.825Z" }, + { url = "https://files.pythonhosted.org/packages/19/2e/c906f8e6d0b54c0137885fff6f7b5883c6bbc381b44a0ba5ea07d7d1579b/grpcio-1.82.1-cp310-cp310-macosx_11_0_universal2.whl", hash = "sha256:c80c9741dcef192f669876a81957cf7713b441c2f0c43631350d75fa49321d31", size = 11960907, upload-time = "2026-07-08T12:34:10.583Z" }, + { url = "https://files.pythonhosted.org/packages/de/be/ec4aa76cdf25539b9e960cbb9d5739f892ea6cde58078b5293860c1159d3/grpcio-1.82.1-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:b89cff456796d2f0581783726ad017a2c70aff2d27b0f05504c34e2e417f7560", size = 6754802, upload-time = "2026-07-08T12:34:13.082Z" }, + { url = "https://files.pythonhosted.org/packages/e6/dd/47519c2a8fd9db47ec4493f44bd9f5b0175307e07089b1132e54b7b5b19c/grpcio-1.82.1-cp310-cp310-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:d6e8a08f7038ba7a77f71e250804e4aba84fe91d22cfc54ff43c07b7529c4728", size = 7484535, upload-time = "2026-07-08T12:34:15.164Z" }, + { url = "https://files.pythonhosted.org/packages/63/99/659711e9689c4dd553bcd4eacff9cb9f458f34b60edf7afb3bbc1b0a58a2/grpcio-1.82.1-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:50fd2fe83426b1b1c6cdc4d72d555223b7dddf8ce07c5bac218b13fc6d684c6f", size = 6919066, upload-time = "2026-07-08T12:34:17.367Z" }, + { url = "https://files.pythonhosted.org/packages/29/39/f2b772356b4f593ffe439795509fcbf675b0ff98211ae8ce2a180f2e559f/grpcio-1.82.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:b758540a24d5394a9c578bf9f6126389f474b106ac3d9df1d53de56cb14c9fd9", size = 7525855, upload-time = "2026-07-08T12:34:19.479Z" }, + { url = "https://files.pythonhosted.org/packages/a7/06/b28cfffb989a84d8272593498bddd2d68148cce1813ad55189c469b0f1f8/grpcio-1.82.1-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:c4ba4aac238f685743575d9d700003ac16537cce26e7c774993134f530652464", size = 8565122, upload-time = "2026-07-08T12:34:21.951Z" }, + { url = "https://files.pythonhosted.org/packages/97/f9/54956cb0c701190cbc9d7e535c3f84acf0285c6b9ed198a902766e17c3cd/grpcio-1.82.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:ed6fc621d6f366c88a60f0b971d5afd21d441d9aa561ee688de5b7acdb2cf901", size = 7933872, upload-time = "2026-07-08T12:34:24.539Z" }, + { url = "https://files.pythonhosted.org/packages/76/85/5f9cd1f965bbe4329556a212f178ae0c072b18b446cae05ed32fa8847c53/grpcio-1.82.1-cp310-cp310-win32.whl", hash = "sha256:bd2f45e46fff5b91c10997d0743a987517a7dde67c64c592835c2dcaac66f587", size = 4257373, upload-time = "2026-07-08T12:34:26.566Z" }, + { url = "https://files.pythonhosted.org/packages/93/b0/c4f42f7c69c53d27ed41643421b55908bcbe885b68f5a208135c72917c98/grpcio-1.82.1-cp310-cp310-win_amd64.whl", hash = "sha256:5e171d5f0d6a0af78ea7512783f170a44f80c165259d8773e3a354a7f991f2b5", size = 5006571, upload-time = "2026-07-08T12:34:28.778Z" }, + { url = "https://files.pythonhosted.org/packages/26/5b/e5092af97fa671ca279b3e373251af4bf87d5fbda7dc85f6a616899562a7/grpcio-1.82.1-cp311-cp311-linux_armv7l.whl", hash = "sha256:0ddb18a9a9e1f46692b3567ae4abb3f8d117ce6afea48650f8eca06d8ab5d06f", size = 6181472, upload-time = "2026-07-08T12:34:31.009Z" }, + { url = "https://files.pythonhosted.org/packages/c1/8f/18053a3a2ca03d0c2a1b8cc7271e705007a16aa5dae84bac00935c5b1a7f/grpcio-1.82.1-cp311-cp311-macosx_11_0_universal2.whl", hash = "sha256:cf855b1af246720f567b0ce5d0724d45dfa4188eecc3296a2a69257b11b9e94b", size = 11970995, upload-time = "2026-07-08T12:34:33.603Z" }, + { url = "https://files.pythonhosted.org/packages/5b/7e/21b1acb052876ad00959ec4d1b05fe08607d650bcfa282073bb164c2703c/grpcio-1.82.1-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:ddb30cb13e25bc13cea70ffc69d6d90c49d36ea6c1d4549e6912f70177834cac", size = 6760127, upload-time = "2026-07-08T12:34:36.122Z" }, + { url = "https://files.pythonhosted.org/packages/3e/12/25eef9c245c54f0061317d13a302357fe8ea03bac240b2b02ececcf54da4/grpcio-1.82.1-cp311-cp311-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:1e822b2774f719c017cbe700b6e47173b6ae290fb84906f52a5a3c2c60b62e1e", size = 7484377, upload-time = "2026-07-08T12:34:38.368Z" }, + { url = "https://files.pythonhosted.org/packages/a0/41/1a348767eb9d9bd7765dc4fa8a01723d3bb386d67f981ee5c6f9c02b8b1c/grpcio-1.82.1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:5dafb1ece8ed45dee7c738f166ec82e19673221ed5ab8967f72858a4685345b2", size = 6924269, upload-time = "2026-07-08T12:34:40.583Z" }, + { url = "https://files.pythonhosted.org/packages/e4/b9/3aae7a03d34c86ea27988db859a6087c186f6c3f53f9b551e07afd989bfa/grpcio-1.82.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:e06503106e7271e0a49fd5a1ac04747f1e47e87d900476db6fe45bc87ee411f4", size = 7531848, upload-time = "2026-07-08T12:34:43.277Z" }, + { url = "https://files.pythonhosted.org/packages/3c/2e/3c4afa625d0dac9090707966916284c035fc5b2fb3e2c51e156accee6735/grpcio-1.82.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:ff99bc8cafb6a952201c37b995f425e641c93ffa6e072258525feab57290141d", size = 8568217, upload-time = "2026-07-08T12:34:45.502Z" }, + { url = "https://files.pythonhosted.org/packages/20/9c/d8489c628e73e20a3d034e7f66912de7b1acb405f01d388f056a88e47924/grpcio-1.82.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:644ae1b94266ac785330f4590a69e52b6a7eb73029043a02209db81c81397d69", size = 7938771, upload-time = "2026-07-08T12:34:48.323Z" }, + { url = "https://files.pythonhosted.org/packages/4b/b7/0a92cfd1658f3a896d4aa12d4efeb7dd4ddfc723725ae22741a5241ea710/grpcio-1.82.1-cp311-cp311-win32.whl", hash = "sha256:e203d2e19d471630084a16c815616f8211dff21c268ab3c5f5bf38417832e074", size = 4256432, upload-time = "2026-07-08T12:34:50.432Z" }, + { url = "https://files.pythonhosted.org/packages/c7/6a/2872c761b025d9ec74386f22a4a7d59c5a5b00ebf718761b33739ffc45de/grpcio-1.82.1-cp311-cp311-win_amd64.whl", hash = "sha256:0d8299c285fe6cc6a1f56badf8d3bc5078c8d20273ee64bafa3783b4bc29a769", size = 5009633, upload-time = "2026-07-08T12:34:52.67Z" }, + { url = "https://files.pythonhosted.org/packages/dc/88/d1350bf3343a2ed87d801584e40609f6c6bd3087926eeca03de50348cf4a/grpcio-1.82.1-cp312-cp312-linux_armv7l.whl", hash = "sha256:c09bd5fa0d5b1fbd773ec349fe61441c3e4ebf168c229aa7538a820bdfad6a58", size = 6144689, upload-time = "2026-07-08T12:34:55.567Z" }, + { url = "https://files.pythonhosted.org/packages/e6/33/71875cdecd27c24ac1385d4783a09853f01b84a825a36aec2a2bc7d0d080/grpcio-1.82.1-cp312-cp312-macosx_11_0_universal2.whl", hash = "sha256:1eae24810720734598e3e6a1a528d5de0f265fe3fc86575e9ecce424b9ec7379", size = 11952034, upload-time = "2026-07-08T12:34:58.128Z" }, + { url = "https://files.pythonhosted.org/packages/82/b2/d9125df3d8a140dec12cc82c05b7deafedeababcff6496f28b2fd5634d10/grpcio-1.82.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:a6bd5daf5bde7b24d7ad2cbaf8bf9eac620d96222016bb5e7ddde930dec0673f", size = 6710772, upload-time = "2026-07-08T12:35:01.33Z" }, + { url = "https://files.pythonhosted.org/packages/88/9b/69e2d1627398b964f34437dc476a5aff5a2cc8e7f247d26272b5674b5faf/grpcio-1.82.1-cp312-cp312-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:1ecfde669cb687ac020d31ff76debe5dc7a62213335f02262eb6625628da1c03", size = 7450677, upload-time = "2026-07-08T12:35:03.926Z" }, + { url = "https://files.pythonhosted.org/packages/e4/e7/8f855ca29c294956122a2a73023655b9b02602d5111dad2b9b00e7631c68/grpcio-1.82.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:011c8badee95734dee8bf05ce3464756a0ac3ebb8d443afd20c0e2b5e4640ad9", size = 6886855, upload-time = "2026-07-08T12:35:06.174Z" }, + { url = "https://files.pythonhosted.org/packages/5f/f0/fa87e85f49925f44c479d07e58b051e69bcfef6b6d5fbc6749d140f6730a/grpcio-1.82.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:b85f4564926fb23114d239392bdcae200db1e6179629edd7d7ab0ab89c96a197", size = 7501323, upload-time = "2026-07-08T12:35:08.49Z" }, + { url = "https://files.pythonhosted.org/packages/67/55/2e0b10ae1d3ef9dcc480b91dc2158f4931fc4675d3af0a2836e39b2a744f/grpcio-1.82.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:2c0c8270833395644c3fe6b6a806397955a2bc0538000a19a78b90c05a6c16e0", size = 8536899, upload-time = "2026-07-08T12:35:10.975Z" }, + { url = "https://files.pythonhosted.org/packages/bd/95/a3d8b0431fa221efc51ee39d73595ede74ba82a43b7c4313192e580face2/grpcio-1.82.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:2ba199205ff46c7778290fe1673c91ac8e7e45678dd5c86e9e56fa33ec8788f6", size = 7913892, upload-time = "2026-07-08T12:35:13.944Z" }, + { url = "https://files.pythonhosted.org/packages/b8/92/f2651ec704d9852a56faef394775038afba435b50ce82ab2404d119c3355/grpcio-1.82.1-cp312-cp312-win32.whl", hash = "sha256:06127691866e295c14e84a1fb86356dd962254f6abd0da4ca4b001eea9e89438", size = 4240985, upload-time = "2026-07-08T12:35:16.048Z" }, + { url = "https://files.pythonhosted.org/packages/96/4f/a5fe8bf0d0a1b24855f370293075c931f27de4eb55f0f158786095bf3c11/grpcio-1.82.1-cp312-cp312-win_amd64.whl", hash = "sha256:1fa3223a3a2e1db74f4c2b255189eb7ea875dfba56e221d252ee3fc7b204778e", size = 5001580, upload-time = "2026-07-08T12:35:18.689Z" }, + { url = "https://files.pythonhosted.org/packages/1b/3e/496992d08c0aaa11272eb6228dc8ab947da01fe835de243cd00521bce4c4/grpcio-1.82.1-cp313-cp313-linux_armv7l.whl", hash = "sha256:b454a2d97bfab7565683a02345f86bd182ab69fd7c2bdb7414171e7538f266b1", size = 6146068, upload-time = "2026-07-08T12:35:21.365Z" }, + { url = "https://files.pythonhosted.org/packages/e7/8f/f263d6f14fdba6b56cfadd91fd3e158a52682b72c6016d1f8723d435659f/grpcio-1.82.1-cp313-cp313-macosx_11_0_universal2.whl", hash = "sha256:3dde70abfc80b3be11de53ba0d601c439e7fb2afd3583ad1788d1146bec92fdc", size = 11948600, upload-time = "2026-07-08T12:35:24.312Z" }, + { url = "https://files.pythonhosted.org/packages/8c/14/3a02e6ee49c2d85bc15eaae321e0e11ab3542cad3c5b2de121ecce0c4296/grpcio-1.82.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:f5523099c98c292ea1ae08e617249db760c56a78f8deae879027fe7d1ffbcbf6", size = 6714591, upload-time = "2026-07-08T12:35:27.027Z" }, + { url = "https://files.pythonhosted.org/packages/69/80/58e3738696f48ab7645347b98d8a7f93d10e00e6218388fbfcd6c9310e3d/grpcio-1.82.1-cp313-cp313-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:5e5c4dc0a59b0f8490a6bdfd6fc8395b9d8ad8a8407c7d67ca7b5bba15c0877f", size = 7454995, upload-time = "2026-07-08T12:35:29.599Z" }, + { url = "https://files.pythonhosted.org/packages/f3/6c/2557c1a889363072fbf2285ecd0e8c44860d4dbd60f017a32537c5b863e2/grpcio-1.82.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:c40d94ba820329cc191981bc22fa6f6eed0799c6d921f3c6709521d59d4a2fd7", size = 6888621, upload-time = "2026-07-08T12:35:32.38Z" }, + { url = "https://files.pythonhosted.org/packages/d2/66/907706ccaff1223f1e10fd5b37fc16faead43392fccb4e786e7e390ac141/grpcio-1.82.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:4c816180e31e273caaec6f8bd86a8392499d5bbb26f41da44e3dce48bde69095", size = 7505069, upload-time = "2026-07-08T12:35:35.072Z" }, + { url = "https://files.pythonhosted.org/packages/b3/7c/ff97b0d0f635987ee5ec80dfedafa1aad629303745d48e8637d10eec5b80/grpcio-1.82.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:e31fd780b261830720cb70b0fd8f0aa51d49e75a66d7464ad2e31d4b765f2580", size = 8535384, upload-time = "2026-07-08T12:35:37.954Z" }, + { url = "https://files.pythonhosted.org/packages/62/9e/a97fddd970a8d1588cade06eca20443761c1858b0ad6590a5c835aa18062/grpcio-1.82.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:9d76152d7c31d7210d4a106e5d8b64da5bba5d6abf11be30e2f7b0a0c59bbcbf", size = 7910707, upload-time = "2026-07-08T12:35:40.797Z" }, + { url = "https://files.pythonhosted.org/packages/20/e4/eaba1517888af483a88d449eb7566f0f7f63446d46f339c5891798435875/grpcio-1.82.1-cp313-cp313-win32.whl", hash = "sha256:38e9dcb5258226fb3282630b31b16a968df52c8c6ad514af540646e0a4578f8a", size = 4240363, upload-time = "2026-07-08T12:35:43.298Z" }, + { url = "https://files.pythonhosted.org/packages/b0/42/66a98d47732e35290bef722f6149fed3709cd4cf61166f6f53a12f417302/grpcio-1.82.1-cp313-cp313-win_amd64.whl", hash = "sha256:3dbfb52c36d9511ac2b8e6c94fdde837b393ae520cc321f52a333a2deedf5a90", size = 5000980, upload-time = "2026-07-08T12:35:46.262Z" }, + { url = "https://files.pythonhosted.org/packages/b4/cb/cf9ae9e164c6e6dc8a494faa9771763df9da150eefe19671009624d1559f/grpcio-1.82.1-cp314-cp314-linux_armv7l.whl", hash = "sha256:35f990f7784c8fd2872644f07f96ebb4d9e48e145a190ab80d0280af91a1bfb2", size = 6146901, upload-time = "2026-07-08T12:35:49.261Z" }, + { url = "https://files.pythonhosted.org/packages/3b/2a/eccf26dbcfb7f7cab8027c5490a16c8937c5aa7a2ec20a3eab2cf7a43165/grpcio-1.82.1-cp314-cp314-macosx_11_0_universal2.whl", hash = "sha256:46536a4a1f4434df3c851b9254ff6fc7df5705b273681a15ca277d5921c178a0", size = 11954756, upload-time = "2026-07-08T12:35:52.196Z" }, + { url = "https://files.pythonhosted.org/packages/ad/75/3b3b4a3cc9f084b026af96e1d3e539b1af29ec7f41ed0dfff3cb99cc8626/grpcio-1.82.1-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:d6650a7c1ebb7921c70e12a385439a8118efb99e669fa9ed31cf25db1843937c", size = 6723087, upload-time = "2026-07-08T12:35:54.973Z" }, + { url = "https://files.pythonhosted.org/packages/9c/8b/b0f0c9b1400a99a4da4c09b114f101b192f8f11192e76f620b8962f5d90b/grpcio-1.82.1-cp314-cp314-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:b8e110c66df5204c0506d6c8787b35d48b8b699ef5aa366d6c4d67325c67fe9a", size = 7454542, upload-time = "2026-07-08T12:35:57.586Z" }, + { url = "https://files.pythonhosted.org/packages/b7/bd/428e38868382aa193697a5aa53973f29c58e58ba4268aa0c86a2715ee58b/grpcio-1.82.1-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:f853eae07235a51a27bb5d6a9a175a59ca55dc9b99edc6ce2f76f07332d333ae", size = 6889588, upload-time = "2026-07-08T12:36:00.012Z" }, + { url = "https://files.pythonhosted.org/packages/49/ce/03e01d5e10259bf5c08ee50570cc94724e79c956f61fd2f09b341af0956c/grpcio-1.82.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:60b0f2c95337694fc094b77d9f60f50566c84b5677393e342eb98daeee242d98", size = 7514166, upload-time = "2026-07-08T12:36:02.693Z" }, + { url = "https://files.pythonhosted.org/packages/ff/59/278b4b600329e2ba3849f3c1ea3c820b3a01b38a7ad184ba09595e8d2733/grpcio-1.82.1-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:b064fc444812bdaa9825d33c26f8d732d63ee6a5d78557c1faf92c98687fed27", size = 8536166, upload-time = "2026-07-08T12:36:05.349Z" }, + { url = "https://files.pythonhosted.org/packages/44/27/7ccf2ef00f27a8e47a79d641c8ceaf7d3028c7a03d9a97b4c8a9a783c086/grpcio-1.82.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:7d7ede11d747b4e1bd05e3bc0260e155b65a88735a895a10f6521f19b889511e", size = 7912572, upload-time = "2026-07-08T12:36:08.393Z" }, + { url = "https://files.pythonhosted.org/packages/0d/be/33742482d2753f2d3a1b7641664b6622262d44f2f3b609f13425dd86d36f/grpcio-1.82.1-cp314-cp314-win32.whl", hash = "sha256:3d21f19838dc255ecbb79321b15ae9b98fbddff4c3d4aedb0a81bdd7f4ab572a", size = 4321856, upload-time = "2026-07-08T12:36:10.899Z" }, + { url = "https://files.pythonhosted.org/packages/cc/67/03329c847172c78ddeb1eb9be6b444fdbc12775a84c958b27e427e7b926d/grpcio-1.82.1-cp314-cp314-win_amd64.whl", hash = "sha256:e20f1edbb15f99e3128ec86433f9785fd5a451d8f115e74fe0056134f092a9d5", size = 5141114, upload-time = "2026-07-08T12:36:13.595Z" }, ] [[package]] @@ -1576,7 +1571,7 @@ wheels = [ [[package]] name = "huggingface-hub" -version = "1.19.0" +version = "1.23.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "click" }, @@ -1587,12 +1582,11 @@ dependencies = [ { name = "packaging" }, { name = "pyyaml" }, { name = "tqdm" }, - { name = "typer" }, { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/88/27/629cfe58c582f92ded066c4a07d1a057ff617118ab7973200f770bd853cb/huggingface_hub-1.19.0.tar.gz", hash = "sha256:fd771622182d40977272a923953ee3b1b13538f9f8a7f5d78398f10af0f1c0bd", size = 824721, upload-time = "2026-06-11T12:33:18.665Z" } +sdist = { url = "https://files.pythonhosted.org/packages/1a/8f/999e4dda11c6187c78f090eac00895a47e11a0049308f07579bcb7aa3aa2/huggingface_hub-1.23.0.tar.gz", hash = "sha256:c04997fb8bbdace1e57b7703d30ed7678af51f70d00d241819ff411b92ae9a88", size = 919163, upload-time = "2026-07-09T14:49:32.315Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/b2/a5/558da89f66464d8d0229ff497e8b8666977de2d8cf48c28a2862ecf1250f/huggingface_hub-1.19.0-py3-none-any.whl", hash = "sha256:1dc72e1f6b4d6df6b30eb72e57d00514ef453d660f04af2b87f0e67267f31ee0", size = 693398, upload-time = "2026-06-11T12:33:16.695Z" }, + { url = "https://files.pythonhosted.org/packages/f1/ce/13b2ba57838b8db1e6bd033c1b21ce0b9f6153b87d4e4939f77074e41eb0/huggingface_hub-1.23.0-py3-none-any.whl", hash = "sha256:b1d604788f5adc7f0eb246e03e0ec19011ca06e38400218c347dccc3dffa64a2", size = 770336, upload-time = "2026-07-09T14:49:30.597Z" }, ] [[package]] @@ -1618,14 +1612,14 @@ wheels = [ [[package]] name = "importlib-metadata" -version = "8.7.1" +version = "8.9.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "zipp" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/f3/49/3b30cad09e7771a4982d9975a8cbf64f00d4a1ececb53297f1d9a7be1b10/importlib_metadata-8.7.1.tar.gz", hash = "sha256:49fef1ae6440c182052f407c8d34a68f72efc36db9ca90dc0113398f2fdde8bb", size = 57107, upload-time = "2025-12-21T10:00:19.278Z" } +sdist = { url = "https://files.pythonhosted.org/packages/e7/72/c600ae4f68c28fc19f9c31b9403053e5dbb8cace2e6842c7b7c3e4d42fe9/importlib_metadata-8.9.0.tar.gz", hash = "sha256:58850626cef4bd2df100378b0f2aea9724a7b92f10770d547725b047078f99ee", size = 56140, upload-time = "2026-03-20T16:56:26.362Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/fa/5e/f8e9a1d23b9c20a551a8a02ea3637b4642e22c2626e3a13a9a29cdea99eb/importlib_metadata-8.7.1-py3-none-any.whl", hash = "sha256:5a1f80bf1daa489495071efbb095d75a634cf28a8bc299581244063b53176151", size = 27865, upload-time = "2025-12-21T10:00:18.329Z" }, + { url = "https://files.pythonhosted.org/packages/7d/f9/97f2ca8bb3ec6e4b1d64f983ebe98b9a192faddff67fac3d6303a537e670/importlib_metadata-8.9.0-py3-none-any.whl", hash = "sha256:e0f761b6ea91ced3b0844c14c9d955224d538105921f8e6754c00f6ca79fba7f", size = 27220, upload-time = "2026-03-20T16:56:25.07Z" }, ] [[package]] @@ -1685,14 +1679,14 @@ wheels = [ [[package]] name = "jaraco-functools" -version = "4.5.0" +version = "4.6.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "more-itertools" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/36/cf/ea4ef2920830dea3f5ab2ea4da6fb67724e6dca80ee2553788c3607243d0/jaraco_functools-4.5.0.tar.gz", hash = "sha256:3bb5665ea4a020cf78a7040e89154c77edadb3ca74f366479669c5999aa70b03", size = 20272, upload-time = "2026-05-15T21:34:10.025Z" } +sdist = { url = "https://files.pythonhosted.org/packages/6c/1f/c23395957d41ccf27c4e535c3d334c4051e5395b3752057ba4cbaec35c56/jaraco_functools-4.6.0.tar.gz", hash = "sha256:880c577ec9720b3a052d5bc611fb9f2269b3d87902ef42440df443b88e443280", size = 20837, upload-time = "2026-07-14T01:28:02.544Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/96/9a/982e48afcffcd727a9144506720ffd4224b6b7e355c98641866f38b7c043/jaraco_functools-4.5.0-py3-none-any.whl", hash = "sha256:79ce39246eddbde4b3a03b77ea5f0f7878dc669b166a66cf3fa8e266aa3fa2f4", size = 10594, upload-time = "2026-05-15T21:34:08.595Z" }, + { url = "https://files.pythonhosted.org/packages/02/36/ecc85bc96c273dc8a11273ed4782272975e6338d4a3e9228621175edf0e3/jaraco_functools-4.6.0-py3-none-any.whl", hash = "sha256:99e3dc0060c5cbe8fcd1cdb36258e2a65ca40f1566b2033b12abb1bb44dd3c30", size = 11677, upload-time = "2026-07-14T01:28:01.59Z" }, ] [[package]] @@ -1718,105 +1712,101 @@ wheels = [ [[package]] name = "jiter" -version = "0.15.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/66/b5/55f06bb281d92fb3cc86d14e1def2bd908bb77693183e7cb1f5a3c388b0c/jiter-0.15.0.tar.gz", hash = "sha256:4251acc80e2b7c9b7b8823456ea0fceeb0734dac2df7636d3c711b38476b5a76", size = 166640, upload-time = "2026-05-19T10:09:48.361Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/1d/da/76a2c7e510ba15fe323d9509c223ab272da79ea59f54488f4a78da6426db/jiter-0.15.0-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:edebcf7d1f601199084bb6e844d7dc67e03e04f6ac786b0332d616635c4ff7a4", size = 310849, upload-time = "2026-05-19T10:06:51.944Z" }, - { url = "https://files.pythonhosted.org/packages/5d/8e/827be942883a4dc0862c48626ff41af3320b1902d136a0bf4b9041f2c567/jiter-0.15.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9f924585cdacf631cd382b657966847bb537bf9ed0a6f9b991da5f05a631480f", size = 314991, upload-time = "2026-05-19T10:06:53.522Z" }, - { url = "https://files.pythonhosted.org/packages/6d/38/be2832be361ba1b9517c76f46d30b64e985be1dd43c974f4c3a4b1844436/jiter-0.15.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:abbf258599526ad0326fe51e252e24f2bd6f24f1852681b4b78feda3808f1d18", size = 340843, upload-time = "2026-05-19T10:06:55.071Z" }, - { url = "https://files.pythonhosted.org/packages/6d/d8/90f01fb83c0c7ba509303ec93e32a308fbfa167d264860b01c0fd0dbbd06/jiter-0.15.0-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:7c468136b8bd6bb18c8786e4236a1fa27362f24cb23450ba0cb204ab379b8e6f", size = 365116, upload-time = "2026-05-19T10:06:56.893Z" }, - { url = "https://files.pythonhosted.org/packages/91/38/94593d34f8c67a0b6f6cbc027f016ffa9780b3a858a7a86f6fd7a15bcc1e/jiter-0.15.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:05906b93d72f03339e6bb7cf8dc10ebda64a0266126eed6beba79e20abcf5fd4", size = 457970, upload-time = "2026-05-19T10:06:58.707Z" }, - { url = "https://files.pythonhosted.org/packages/df/04/d79962dd49d00c97e2a9b4cacea1947904d02135936960351f9a96d4c1a6/jiter-0.15.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:30ce785d2adb8e32c3f7741442370a74834ec4c01f3c48f0750227a0b4ef27d6", size = 375744, upload-time = "2026-05-19T10:07:00.471Z" }, - { url = "https://files.pythonhosted.org/packages/c3/2e/5d37abe2be0e819c21e2338bebd410e481763ce526a9138c8c3652fa0123/jiter-0.15.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2fd73e3da91a0a722d67165e849ce2cdc10de0e0d48738c142be8c6c5f310f4c", size = 349609, upload-time = "2026-05-19T10:07:01.829Z" }, - { url = "https://files.pythonhosted.org/packages/7a/90/98768ad2ed90c1fda15d64157de2dfbf73c1c074d4b1bfaca915480bc7cf/jiter-0.15.0-cp310-cp310-manylinux_2_31_riscv64.whl", hash = "sha256:ceb8fc27d38793f9c97149be8302720c5b22e5c195a37bf2c45dc36c4600a512", size = 354366, upload-time = "2026-05-19T10:07:03.587Z" }, - { url = "https://files.pythonhosted.org/packages/d6/c4/fbfb806209f1fe4b7dccdfb07bc62bb044300734a945b06fd64db446ef6a/jiter-0.15.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d726e3ceeb337191324b49de298142f27c3ad10886341555d1d5315b5f252c6a", size = 393519, upload-time = "2026-05-19T10:07:05.08Z" }, - { url = "https://files.pythonhosted.org/packages/37/1c/b9c257cd70cb453b6d10f3ebf0402cdb11669ab455389096f09839670290/jiter-0.15.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:2c8aea7781d2a372227871de4e1a1332aa96f5a89fd76c5e835dafdbad102887", size = 519952, upload-time = "2026-05-19T10:07:06.589Z" }, - { url = "https://files.pythonhosted.org/packages/a9/1a/aa85027db7ab15829c12feebbc33b404f53fc399bd559d85fd0d6365ff0d/jiter-0.15.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:cf4bd113a69c0a740e27cb962ce10630c36d2b8f59d759a651b955ee9d18a823", size = 550770, upload-time = "2026-05-19T10:07:08.228Z" }, - { url = "https://files.pythonhosted.org/packages/d4/54/8c3f65c8a5687925e84708f19d63f7f37d28e2b86a48d951702ad94424d8/jiter-0.15.0-cp310-cp310-win32.whl", hash = "sha256:d92a5cd21fdb083931d546c207aa29633787c5dc5b02daab2d32b843f88a2c53", size = 209303, upload-time = "2026-05-19T10:07:10.006Z" }, - { url = "https://files.pythonhosted.org/packages/d5/72/0528a1eb9f42dd2d8228a0711458628f35924d131f623eaebc35fd23d3d4/jiter-0.15.0-cp310-cp310-win_amd64.whl", hash = "sha256:e58585a58209d72691ce2d62a9147445f5a87beb0bde97fde284c96ae392a3d1", size = 200404, upload-time = "2026-05-19T10:07:11.426Z" }, - { url = "https://files.pythonhosted.org/packages/e4/13/daa722f5765c393576f466378f9dfd29d77c9bed939e0688f96afa3601ea/jiter-0.15.0-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:0f862193b8696249d22ec433e85fd2ab0ad9596bc3e45e6c0bc55e8aeba97be2", size = 310899, upload-time = "2026-05-19T10:07:12.89Z" }, - { url = "https://files.pythonhosted.org/packages/7f/82/2d2551829b082f4b6d82b9f939b031fb808a10aab1ec0664f82e150bb9a2/jiter-0.15.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:1303d4d68a9b051ea90502402063ecf3807da00ad2affa19ca1ae3b90b3c5f67", size = 314963, upload-time = "2026-05-19T10:07:14.539Z" }, - { url = "https://files.pythonhosted.org/packages/2a/0a/8b1a51466f7fe9f31dbe4bc7e0ca848674f9825e0f737b929b97e8c60aa7/jiter-0.15.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:392b8ab019e5502d08aff85c6272209c24bc2cbe706ea82a56368f524236614a", size = 341730, upload-time = "2026-05-19T10:07:15.869Z" }, - { url = "https://files.pythonhosted.org/packages/f6/2a/e71dea19822e2e404e83992a08c1d6b9b617bb944f28c9c2fbd85d02c91e/jiter-0.15.0-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:773b6eb282ce11ee19f05f6b2d4404fa308e5bbd353b0b80a0262caad6db2cd7", size = 366214, upload-time = "2026-05-19T10:07:17.259Z" }, - { url = "https://files.pythonhosted.org/packages/c4/59/97e1fa539d124a509a00ab7f669289d1c1d236ecabf12948a18f16c91082/jiter-0.15.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8d2c0c44d569ce0f2850f5c926f8caeb5f245fbc84475aeb36efccc2103e6dbd", size = 459527, upload-time = "2026-05-19T10:07:18.741Z" }, - { url = "https://files.pythonhosted.org/packages/d1/7a/4a68d331aef8cf2e2393c14a3aacb635c62aa86071b0229899fb5baaa907/jiter-0.15.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:032396229564bca02440396bd327710719f724f5e7b7e9f7a8eb3faa4a2c2281", size = 375451, upload-time = "2026-05-19T10:07:20.208Z" }, - { url = "https://files.pythonhosted.org/packages/7b/7e/1c445c2b6f0e30a274dc8082e0c3c7825411cce80d726bccd697c98cc8d3/jiter-0.15.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f3d37768fce7f88dd2a8c6091f2325dea27d30d30d5c6e7a1c0f0af77723b708", size = 349428, upload-time = "2026-05-19T10:07:22.372Z" }, - { url = "https://files.pythonhosted.org/packages/00/94/e20d38984fc17a636371bffd2ae0f698124fdc8e75ef969cd2da6ba7cea7/jiter-0.15.0-cp311-cp311-manylinux_2_31_riscv64.whl", hash = "sha256:2c9cb907439d20bd0c7d7565ca01ee52234203208433749bae5b516907526928", size = 355405, upload-time = "2026-05-19T10:07:23.916Z" }, - { url = "https://files.pythonhosted.org/packages/94/fa/4d09f814779d0ea80a28ed8e4c6662ec9a4a8ecef0ac52190ebac6262d14/jiter-0.15.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:9100ddbec09741cc66feb0fc6773f8bdbd0e3c345689368f260082ff85dcc0cd", size = 393688, upload-time = "2026-05-19T10:07:25.854Z" }, - { url = "https://files.pythonhosted.org/packages/54/9d/8eb5d4fb8bf7e93a75964a5da71a75c67c864baf7fa3f98598187b3c7e57/jiter-0.15.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:ae1b0d82ac2d987f9ea512b1c9adfcc71a28de3dea3a6039b54d76cffda9901e", size = 520853, upload-time = "2026-05-19T10:07:27.303Z" }, - { url = "https://files.pythonhosted.org/packages/e7/2c/5e07874e59e623a943a0acf1552a80d05b70f31b402287a8fc6d7ec634c7/jiter-0.15.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:8020c99ec13a7db2b6f96cbe82ef4721c88b426a4892f27478044af0284615ef", size = 551016, upload-time = "2026-05-19T10:07:28.846Z" }, - { url = "https://files.pythonhosted.org/packages/22/ed/d2d34422143474cadc15b60d482b1c35683dbc5c63c24346ddd0df09bcaf/jiter-0.15.0-cp311-cp311-win32.whl", hash = "sha256:42bfb257930800cf43e7c62c832402c704ab60797c992faf88d20e903eac8f32", size = 209518, upload-time = "2026-05-19T10:07:30.431Z" }, - { url = "https://files.pythonhosted.org/packages/1d/7d/52778b930e5cc3e52a37d950b1c10494244308b4329b25a0ff0d88303a81/jiter-0.15.0-cp311-cp311-win_amd64.whl", hash = "sha256:860a74063284a2ae9bfedd694f299cc2c68e2696c5f3d440cc9d18bb81b9dd04", size = 200565, upload-time = "2026-05-19T10:07:32.125Z" }, - { url = "https://files.pythonhosted.org/packages/3b/4f/d9b4067feb69b3fa6eb0488e1b59e2ad5b463fe39f59e527eab2aca00bb0/jiter-0.15.0-cp311-cp311-win_arm64.whl", hash = "sha256:37a10c377ce3a4a85f4a67f28b7afe093154cde77eaf248a72e856aa08b4d865", size = 195488, upload-time = "2026-05-19T10:07:33.846Z" }, - { url = "https://files.pythonhosted.org/packages/44/53/4f6bddbcde3c71e56d0aa1337ec95950f3d27dd4153e25aadf0feac71751/jiter-0.15.0-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:0e90a1c315a0226ec822d973817967f9223b7701546c8c2a7913e7ab0926294d", size = 308793, upload-time = "2026-05-19T10:07:35.25Z" }, - { url = "https://files.pythonhosted.org/packages/01/84/c01099b59a285a1ebba64ae93f62bfa036675340fd1b0045ae65890a0442/jiter-0.15.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8c9004af7c8d67cce7f1aae1026fb55607f4aa600710d08ede3a3ce4aeefe7e0", size = 309570, upload-time = "2026-05-19T10:07:36.919Z" }, - { url = "https://files.pythonhosted.org/packages/58/64/8fb7f9d45bb98190355454cd04dad8d8f27223d6bd52f83af07f637168a6/jiter-0.15.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c210f8b35dc6f30aafd4b4365ca89b9d1189f21ab49b8e68fa6322a847aef138", size = 336783, upload-time = "2026-05-19T10:07:38.694Z" }, - { url = "https://files.pythonhosted.org/packages/c3/b6/f5739011d009b3a30f6a53c5240979030ba29ae46a8c67e3a15759f7c37d/jiter-0.15.0-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5f30bae8bc1c2d613e28e5af3e8cceb09b742f1c8a8a5f839fb67afaffc03b61", size = 363555, upload-time = "2026-05-19T10:07:40.832Z" }, - { url = "https://files.pythonhosted.org/packages/e5/12/98a9d9f766665e8a3b6252454e17cb0c464606a28cf2fa09399b003345fa/jiter-0.15.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c60e71b6d10cfc284c9bf36bd885e8d44c46f688ce50aa91b5edd90181dea687", size = 452255, upload-time = "2026-05-19T10:07:42.62Z" }, - { url = "https://files.pythonhosted.org/packages/e8/d5/60f972840f79c5e7544fce567c56f1e4e50468f996baba3e78d823dd62a6/jiter-0.15.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0ab068bce62a45aa3e7367eceaffb5dde60b7eb853be8dece45132e3d0ff4879", size = 373559, upload-time = "2026-05-19T10:07:44.201Z" }, - { url = "https://files.pythonhosted.org/packages/ee/cf/d46ef1234ba335aabc2f013210db8e0821a22f5e644a2e9449df199ecc23/jiter-0.15.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fa248c9eb220197d363f688818dac2fd4b2f0cd7d843ca7105d652034823427d", size = 346055, upload-time = "2026-05-19T10:07:46.005Z" }, - { url = "https://files.pythonhosted.org/packages/f0/63/4d2749d8d54d230bad9b3a6b0d00cc28c6ff6b2fdffc26a8ccf76cc5a974/jiter-0.15.0-cp312-cp312-manylinux_2_31_riscv64.whl", hash = "sha256:2a77aadd57cac1682e4401a72724d2796d89a4ba129b1a5812aa94ee480826eb", size = 351406, upload-time = "2026-05-19T10:07:47.855Z" }, - { url = "https://files.pythonhosted.org/packages/d9/b9/9965b990035d8773328e0a8c8b457a87bf2b19f6c4126d9d99296be5d16a/jiter-0.15.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2ae901f3a55bfafdde31d289590fa25e3245735a2b1e8c7cc15871710a002871", size = 389357, upload-time = "2026-05-19T10:07:49.665Z" }, - { url = "https://files.pythonhosted.org/packages/2d/55/9ddf903deda1413e87fed792f416b7123daee5b8efbad6a202a7421c36a5/jiter-0.15.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:f0b271b462769543716f92d3a4f90527df6ef5ed05ee95ec4137f513e21e1b77", size = 517263, upload-time = "2026-05-19T10:07:51.537Z" }, - { url = "https://files.pythonhosted.org/packages/e8/76/a0c40ad064d3a20a4fde231e35d56e9a01ce82164278180e82d5daf85469/jiter-0.15.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:2fb6a5d26af81fc0f00f9360a891e05cf755e149bba391c4d563adc54812973d", size = 548646, upload-time = "2026-05-19T10:07:53.196Z" }, - { url = "https://files.pythonhosted.org/packages/23/4f/eca9b954942916ba2f453891b8593ab444cd872396fe66a3936616f236f3/jiter-0.15.0-cp312-cp312-win32.whl", hash = "sha256:c2f6bb8b5216ab9e7873bc08b5d7bef2b8abbb578a3069bf1cd14a45d71d771d", size = 206427, upload-time = "2026-05-19T10:07:55.307Z" }, - { url = "https://files.pythonhosted.org/packages/95/bf/8ead82a87495149542748e828d153fd232a512a22c83b02c4815c1a9c7d8/jiter-0.15.0-cp312-cp312-win_amd64.whl", hash = "sha256:40b2c7e92c44a84d748d21706c68dc6ff8161d80b59c99d774721a0d2317d7c7", size = 197300, upload-time = "2026-05-19T10:07:56.651Z" }, - { url = "https://files.pythonhosted.org/packages/f4/e4/9b8a78fb2d894471bc344e37f1949bdd784bd914d031dba0ba3a40c71dd7/jiter-0.15.0-cp312-cp312-win_arm64.whl", hash = "sha256:cc0bc345cf2df9d1c00ac443f50d543c1ccfa8b0422cb85b1ab70d681c0b255b", size = 192702, upload-time = "2026-05-19T10:07:58.307Z" }, - { url = "https://files.pythonhosted.org/packages/e5/f4/f708c900ecee41b2025ef8413d5351e5649eb2125c506f6720cc69b06f5c/jiter-0.15.0-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:1c11465f97e2abf45a014b83b730222f8f1c5335e802c7055a67d50de6f1f4e3", size = 307829, upload-time = "2026-05-19T10:07:59.704Z" }, - { url = "https://files.pythonhosted.org/packages/86/59/db537c0949e83668c38481d426b9f2fd5ab758c4ee53a811dd0a510626a0/jiter-0.15.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:d1e7b1776f0797956c509e123d0952d10d293a9492dea9f288ab9570ec01d1a5", size = 308445, upload-time = "2026-05-19T10:08:01.184Z" }, - { url = "https://files.pythonhosted.org/packages/37/38/ea0e13b18c30ef951da0d47d39e7fa9edb82a93a62990ffbd7cea9b622d4/jiter-0.15.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:351a341c2105aa430b7047e30f1bf7975f6313b00165d3fc07be2edaf741f279", size = 336181, upload-time = "2026-05-19T10:08:02.688Z" }, - { url = "https://files.pythonhosted.org/packages/58/fc/2303901b16c4ba05865588990a420c0b4156270b44379c20931544a1d962/jiter-0.15.0-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:4ab395feec8d249ec4044e228e98a7033f043426a265df439dc3698823f0a4e4", size = 362985, upload-time = "2026-05-19T10:08:04.394Z" }, - { url = "https://files.pythonhosted.org/packages/5b/6f/11bace093c52e7d4d26c8e606ccd7ae8c972189622469ec0d9e28161e28b/jiter-0.15.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a2a438005b6f22d0273413484d6094d7c2c5d10ec1b3a3bf128e0d1d3ba53258", size = 453292, upload-time = "2026-05-19T10:08:05.967Z" }, - { url = "https://files.pythonhosted.org/packages/22/db/987f2f086ca4d7a6582eb4ccd513f9b26b42d9e4243a087609a3137a8fc7/jiter-0.15.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f18f85e4218d1b40f000f42a92239a7a61a902cd42c65e6c360dbd17dcb20894", size = 373501, upload-time = "2026-05-19T10:08:07.857Z" }, - { url = "https://files.pythonhosted.org/packages/8f/7c/89fbcabb2739b7a5b8dc959a1b6c5761f6484f5fed3486854b3c789bb1de/jiter-0.15.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d1aa62e277fc1cbd80e6deacae6f4d983b41b3d7728e0645c5d741a6149bba45", size = 344683, upload-time = "2026-05-19T10:08:09.431Z" }, - { url = "https://files.pythonhosted.org/packages/30/6f/6cca7692e7dddfec6d8d76c54dc97f2af2a41df4ac0674b999df1f09a5f3/jiter-0.15.0-cp313-cp313-manylinux_2_31_riscv64.whl", hash = "sha256:6550fa135c7deb8ead6af49ed7ff648532ea8334a1447fe34a36315ef79c5c29", size = 350892, upload-time = "2026-05-19T10:08:11.352Z" }, - { url = "https://files.pythonhosted.org/packages/39/14/0338d6190cb8e6d22e677ab1d4eabd4117f67cca70c54cd04b82ff64e068/jiter-0.15.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:066f8f33f18b2419cd8213b2436fa7fbc9c499f315971cfa3ce1f9820c001b1b", size = 388723, upload-time = "2026-05-19T10:08:12.912Z" }, - { url = "https://files.pythonhosted.org/packages/90/31/cc19f4a1bdb6afb09ce6a2f2615aa8d44d994eba0d8e6105ed1af920e736/jiter-0.15.0-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:75e8a04e91432dde9f1838373cf93d23726c79d3e908d319acf0e796f85592e7", size = 516648, upload-time = "2026-05-19T10:08:14.808Z" }, - { url = "https://files.pythonhosted.org/packages/49/9f/833c541512cd091b63c10c0381973dfe11bc7a503a818c16384417e0c81e/jiter-0.15.0-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:a97261f1fccb8e50ecd2890a96e46efdc3f57c80a197324c6777827231eca712", size = 547382, upload-time = "2026-05-19T10:08:16.927Z" }, - { url = "https://files.pythonhosted.org/packages/d2/11/e7b70e91f90bc4477e8eee9e8a5f7cf3cb41b4525d6394dc98a714eb8f7f/jiter-0.15.0-cp313-cp313-win32.whl", hash = "sha256:c77496cb10bd7549690fbbab3e5ec05857b83e49276f4a9423a766ddd2afcd4c", size = 205845, upload-time = "2026-05-19T10:08:18.401Z" }, - { url = "https://files.pythonhosted.org/packages/4b/23/5c20d9ad6f02c493e4023e5d2d09e1c1f15fe2753c9102c544aff068a88e/jiter-0.15.0-cp313-cp313-win_amd64.whl", hash = "sha256:b15741f501469009ae0ae90b7147958a664a7dede40aa7ff174a8a4645f546d0", size = 196842, upload-time = "2026-05-19T10:08:20.131Z" }, - { url = "https://files.pythonhosted.org/packages/6b/11/1eb400ef248e8c925fd883fbe325daf5e42cd1b0d308539dd332bd4f7ffc/jiter-0.15.0-cp313-cp313-win_arm64.whl", hash = "sha256:5d6a60072b44c3c2b797a7ddcbcbbf2b34ea3cfd4721580fbfd2a09d9d9b84ba", size = 192212, upload-time = "2026-05-19T10:08:21.807Z" }, - { url = "https://files.pythonhosted.org/packages/8a/60/2fd8d7c79da8acf9b7b277c7616847773779356b92acfc9bb158452174da/jiter-0.15.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:ef1fd24d9413f6209e00d3d5a453e67acfe004a25cc6c8e8484faed4311ab9e8", size = 315065, upload-time = "2026-05-19T10:08:23.218Z" }, - { url = "https://files.pythonhosted.org/packages/46/f4/008fb7d65e8ac2abf00811651a661e025c4ba80bbc6f378450384ddd3aed/jiter-0.15.0-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:144f8e72cb53dab146347b91cceac01f5481237f2b93b4a339a1ee8f8878b67c", size = 339444, upload-time = "2026-05-19T10:08:24.701Z" }, - { url = "https://files.pythonhosted.org/packages/00/55/90b0c7b9c6896c0f2a591dd36d36b71d22e09674bfef178fa03ba3f81499/jiter-0.15.0-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:553fcac2ef2cb990877f9fc0833b8b629a3e6a5670b6b5fd58219b41a653ddc4", size = 347779, upload-time = "2026-05-19T10:08:26.408Z" }, - { url = "https://files.pythonhosted.org/packages/51/6b/69666cec5000fd57734c118437394516c749ae8dbeea9fb66d6fef9c4775/jiter-0.15.0-cp313-cp313t-win_amd64.whl", hash = "sha256:774f93f65031856bf14ad9f59bdcab8b8cad501e5ceabd51ba3525f76937a25b", size = 200395, upload-time = "2026-05-19T10:08:28.055Z" }, - { url = "https://files.pythonhosted.org/packages/39/04/a6aa62cd27e8149b0d28df5561f10f6cceaf7935a9ccf3f1c5a05f9a0cd8/jiter-0.15.0-cp313-cp313t-win_arm64.whl", hash = "sha256:f1e1754960f38ec40613a07e5e372df67acb3b890fb383b6fb3de3e49ddbf3c7", size = 190516, upload-time = "2026-05-19T10:08:29.35Z" }, - { url = "https://files.pythonhosted.org/packages/eb/d2/079f350ebf7859d081de30aa890f9e3be68516f754f3ba32366ffff4dcee/jiter-0.15.0-cp314-cp314-macosx_10_12_x86_64.whl", hash = "sha256:ac0d9ddea4350974be7a221fc25895f251a8fee748c889bdced2141c0fec1a49", size = 308884, upload-time = "2026-05-19T10:08:31.667Z" }, - { url = "https://files.pythonhosted.org/packages/04/4e/a2c30a7f69b48c03b20935d647479106fe932f6e63f75faf53937197e05d/jiter-0.15.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:01a8222cf05ab1128e239421156c207949808acaaea2bdfd33130ae666786e86", size = 310028, upload-time = "2026-05-19T10:08:33.304Z" }, - { url = "https://files.pythonhosted.org/packages/40/90/2e7cdfd3cf8ca967be38c48f5cf474d79f089efaf559a40f15984a77ae69/jiter-0.15.0-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:182226cbc930c9fab81bc2e41a4da672f89539906dadb05e75670ac07b94f71f", size = 337485, upload-time = "2026-05-19T10:08:35.259Z" }, - { url = "https://files.pythonhosted.org/packages/9b/11/15a1aa28b120b8ee5b4f1fb894c125046225f09847738bd64233d3b84883/jiter-0.15.0-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:71683c38c825452999b5717fcae07ea708e8c93003e808be4319c1b02e3d176e", size = 364223, upload-time = "2026-05-19T10:08:36.694Z" }, - { url = "https://files.pythonhosted.org/packages/b7/25/f442e8af5f3d0dcf47b39e83a0efd9ee45ea946aa6d04625dc3181eae3b6/jiter-0.15.0-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:30f2218e6a9e5c18bc10fe6d41ac189c442c88eacf11bad9f28ef95a9bef00e6", size = 456387, upload-time = "2026-05-19T10:08:38.143Z" }, - { url = "https://files.pythonhosted.org/packages/da/f4/37f2d2c9f64f49af7da652ed7532bb5a2372e588e6927c3fdd76f911db65/jiter-0.15.0-cp314-cp314-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5157de9f76eb4bc5ea74a1219366a25f945ad305641d74e04f59c54087091aa9", size = 374461, upload-time = "2026-05-19T10:08:39.869Z" }, - { url = "https://files.pythonhosted.org/packages/60/28/edcfbbbf0cb15436f36664a8908a0df47ab9006298d4cd937dc08ea932d6/jiter-0.15.0-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:90c5db5527c221249a876160663ab891ace358c17f7b9c93ec1478b7f0550e5c", size = 345924, upload-time = "2026-05-19T10:08:41.668Z" }, - { url = "https://files.pythonhosted.org/packages/47/13/89fba6398dab7f202b7278c4b4aac122399d2c0183971c4a57a3b7088df5/jiter-0.15.0-cp314-cp314-manylinux_2_31_riscv64.whl", hash = "sha256:3e4540b8e74e4268811ac05db226a6a128ff572e7e0ce3f1163b693cadb184cd", size = 352283, upload-time = "2026-05-19T10:08:43.091Z" }, - { url = "https://files.pythonhosted.org/packages/1b/da/0f6af8cef2c565a1ab44d970f268c43ccaa72707386ea6388e6fe2b6cd26/jiter-0.15.0-cp314-cp314-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:62ebd14e47e9aed9df4472afcb2663668ce4d74891cd54f86bf6e44029d6dc89", size = 389985, upload-time = "2026-05-19T10:08:44.915Z" }, - { url = "https://files.pythonhosted.org/packages/a1/ec/b9cb7d6d29e24ee14910266157d2a279d7a8f60ee0df7fa840882976ba64/jiter-0.15.0-cp314-cp314-musllinux_1_1_aarch64.whl", hash = "sha256:0be6f5ad41a809f303f416d17cec92a7a725902fb9b4f3de3d19362ac0ef8554", size = 517695, upload-time = "2026-05-19T10:08:46.486Z" }, - { url = "https://files.pythonhosted.org/packages/64/5e/6d1bda880723aae0ad86b4b763f044362448efe31e3e819635d41cb03451/jiter-0.15.0-cp314-cp314-musllinux_1_1_x86_64.whl", hash = "sha256:813dfbb17d65328bf86e5f0905dd277ba2265d3ca20556e86c0c7035b7182e5a", size = 548868, upload-time = "2026-05-19T10:08:48.026Z" }, - { url = "https://files.pythonhosted.org/packages/0c/72/7de501cf38dcacaf35098796f3a50e0f2e338baba18a58946c618544b809/jiter-0.15.0-cp314-cp314-win32.whl", hash = "sha256:50e51156192722a9c58db112837d3f8ef96fb3c5ecc14e95f409134b08b158ec", size = 206380, upload-time = "2026-05-19T10:08:49.738Z" }, - { url = "https://files.pythonhosted.org/packages/1e/a9/e19addf4b0c1bdce52c6da12351e6bc42c340c45e7c09e2158e46d293ccc/jiter-0.15.0-cp314-cp314-win_amd64.whl", hash = "sha256:30ce1a5d16b5641dc935d50ef775af6a0871e3d14ab05d6fc54dff371b78e558", size = 197687, upload-time = "2026-05-19T10:08:51.088Z" }, - { url = "https://files.pythonhosted.org/packages/f2/c9/776b1db01db25fc6c1d58d1979a37b0a9fe787e5f5b1d062d2eaacb77923/jiter-0.15.0-cp314-cp314-win_arm64.whl", hash = "sha256:510c8b3c17a0ed9ac69850c0438dada3c9b82d9c4d589fcb62002a5a9cf3a866", size = 192571, upload-time = "2026-05-19T10:08:52.451Z" }, - { url = "https://files.pythonhosted.org/packages/a0/f6/45bb4670bacf300fd2c7abadbfb3af376e5f1b6ae75fd9bc069891d15870/jiter-0.15.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:7553333dd0930c104a5a0db8df72bf7219fe663d731383b576bb6ed6351c984d", size = 317151, upload-time = "2026-05-19T10:08:53.867Z" }, - { url = "https://files.pythonhosted.org/packages/d7/68/ed635ad5acd7b73e454283083bbb7c8205ad10e88b0d9d7d793b09fe8226/jiter-0.15.0-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f2143ab06181d2b029eedcb6af3cebe95f11bbac62441781860f98ee9330a6a6", size = 341243, upload-time = "2026-05-19T10:08:55.383Z" }, - { url = "https://files.pythonhosted.org/packages/5d/db/3ff4176b817b8ea33879e71e13d8bc2b0d481a7ed3fe9e080f333d415c16/jiter-0.15.0-cp314-cp314t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:6eac374c5c975709b69c10f09afd199df74150172156ad10c8d4fd785b7da995", size = 363629, upload-time = "2026-05-19T10:08:56.928Z" }, - { url = "https://files.pythonhosted.org/packages/ab/24/5f8270e0ba9c883582f96f722f8a0b58015c7ce1f8c6d4571cf394e99b6b/jiter-0.15.0-cp314-cp314t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b3b3b775e33d3bfaec9899edc526ae97b0da0bf9d071a46124ba419149a414f8", size = 456198, upload-time = "2026-05-19T10:08:58.618Z" }, - { url = "https://files.pythonhosted.org/packages/45/5b/76fc02b0b5c54c3d18c60653156e2f76fde1816f9b4722db68d6ee2c897e/jiter-0.15.0-cp314-cp314t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:eda3071db3346334beae1360b46da4606da57bf3528c167b3c38533afaf9f2c5", size = 373710, upload-time = "2026-05-19T10:09:00.151Z" }, - { url = "https://files.pythonhosted.org/packages/c4/52/4310821b0ea9277994d3e1f49fc6a4b34e4800caebacb2c0af81da59a454/jiter-0.15.0-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c6694a173ecabc12eb60efbc0b474464ead1951ff65cd8b1e72100715c64512b", size = 349901, upload-time = "2026-05-19T10:09:01.621Z" }, - { url = "https://files.pythonhosted.org/packages/93/fe/67648c35b3594fba8854ac64cc8a826d8bcd18324bbdb53d77697c60b6ef/jiter-0.15.0-cp314-cp314t-manylinux_2_31_riscv64.whl", hash = "sha256:a254e10b593624d230c365b6d616b22ca0ad65e63a16e6631c2b3466022e6ba8", size = 352438, upload-time = "2026-05-19T10:09:03.216Z" }, - { url = "https://files.pythonhosted.org/packages/cb/28/0a1879d07ad6b3e025a2750027363452ced93c2d16d1c9d4b153ffd51c91/jiter-0.15.0-cp314-cp314t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d8d2955167274e15d79a7a020afdd9b39c990eb80b2d89fca695d92dcfdd38ec", size = 388152, upload-time = "2026-05-19T10:09:04.741Z" }, - { url = "https://files.pythonhosted.org/packages/c1/78/46c6f6b56ba85c90021f4afd72ed42f691f8f84daacb5fe27277070e3858/jiter-0.15.0-cp314-cp314t-musllinux_1_1_aarch64.whl", hash = "sha256:acf4ee4d1fc55917239fe72972fb292dd773055d05eb040d36f4326e02cc2c0e", size = 517707, upload-time = "2026-05-19T10:09:06.231Z" }, - { url = "https://files.pythonhosted.org/packages/ca/cb/720662d4c88fcad606e826fef5424365527ba43ce4868a479aed8f8c507e/jiter-0.15.0-cp314-cp314t-musllinux_1_1_x86_64.whl", hash = "sha256:e7196e56f1cd69af1dbb07dff02dcfb260a50b45a82d409d92a06fedb32473b5", size = 548241, upload-time = "2026-05-19T10:09:08.093Z" }, - { url = "https://files.pythonhosted.org/packages/60/e3/935b8034fd143f21125c87d51404a9e0e1449186a494405721ff5d1d695e/jiter-0.15.0-cp314-cp314t-win32.whl", hash = "sha256:7f6163c0f10b055245f814dcc59f4818da60dfe72f3e72ab89fc24b6bd5e9c52", size = 207950, upload-time = "2026-05-19T10:09:09.616Z" }, - { url = "https://files.pythonhosted.org/packages/93/59/984fd9ece895953dad3e0880a650e766f5a2da2c5514f0eafdaaabbeb5f9/jiter-0.15.0-cp314-cp314t-win_amd64.whl", hash = "sha256:980c256edb05b78a111b99c4de3b1d32e31634b867fd1fc2cf726e7b7bba9854", size = 200055, upload-time = "2026-05-19T10:09:11.367Z" }, - { url = "https://files.pythonhosted.org/packages/0e/a4/cf8d779feb133a27a2e3bc833bccb9e13aa332cdf820497ebf72c10ce8c3/jiter-0.15.0-cp314-cp314t-win_arm64.whl", hash = "sha256:66b1880df2d01e206e8339769d1c7c1753bcb653efd6289e203f6f24ebada0c0", size = 191244, upload-time = "2026-05-19T10:09:12.74Z" }, - { url = "https://files.pythonhosted.org/packages/65/43/1fc62172aa98b50a7de9a25554060db510f85c89cfbed0dfe13e1907a139/jiter-0.15.0-graalpy311-graalpy242_311_native-macosx_10_12_x86_64.whl", hash = "sha256:411fa4dfa5a7ae3d11491027ffb9beadec3996010a986862db70d91abba1c750", size = 305585, upload-time = "2026-05-19T10:09:35.995Z" }, - { url = "https://files.pythonhosted.org/packages/e8/c4/dd58fcd9e2df83666e5c1c1347bef58ce919cd8efc3ffa38aeea62ce493b/jiter-0.15.0-graalpy311-graalpy242_311_native-macosx_11_0_arm64.whl", hash = "sha256:2b0074e2f56eb2dacca1689760fd2852a068f85a0547a157b82cb4cafeb6768b", size = 306936, upload-time = "2026-05-19T10:09:37.435Z" }, - { url = "https://files.pythonhosted.org/packages/39/86/b695e16f1180c07f43ea98e73ecd21cf63fa2e1b0c1103739013784d11ae/jiter-0.15.0-graalpy311-graalpy242_311_native-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:913d02d29c9606643418d9ccfc3b72492ab25a6bf7889934e09a3490f8d3438b", size = 342453, upload-time = "2026-05-19T10:09:39.294Z" }, - { url = "https://files.pythonhosted.org/packages/34/56/55d76614af37fe3f22a3347d1e410d2a15da581997cb2da499a625000bb5/jiter-0.15.0-graalpy311-graalpy242_311_native-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b15d3ec9b0449c40e85319bdb4caa8b77ab526e74f5532ed94bec15e2f66822c", size = 345606, upload-time = "2026-05-19T10:09:40.727Z" }, - { url = "https://files.pythonhosted.org/packages/73/38/505941b2b092fd5bbbd60a52a880db1173f1690ae6751bed3af1c9ddcb4e/jiter-0.15.0-graalpy312-graalpy250_312_native-macosx_10_12_x86_64.whl", hash = "sha256:631f13a3d04e97d4e083993b10f4b99530e3a10d953e2eb5e196b7dc7f812ce0", size = 303769, upload-time = "2026-05-19T10:09:42.203Z" }, - { url = "https://files.pythonhosted.org/packages/e7/95/a06692b29e77473f286e1ec1f426d3ca44d7b5843be8ad21d7a5f3fcdcc0/jiter-0.15.0-graalpy312-graalpy250_312_native-macosx_11_0_arm64.whl", hash = "sha256:b6c0ffae686c39bf3737be60793783267628783ea42545632c10b291105aee45", size = 305128, upload-time = "2026-05-19T10:09:43.657Z" }, - { url = "https://files.pythonhosted.org/packages/23/85/7270d7ad41d6061a25b950c6bf91d638bd9aacb113200a8c8d57a055fd67/jiter-0.15.0-graalpy312-graalpy250_312_native-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1d54fb5b31dea401a41af3f8a7d2512e9b6a6a005491e6166c7e4ffab9639a9c", size = 340459, upload-time = "2026-05-19T10:09:45.452Z" }, - { url = "https://files.pythonhosted.org/packages/c8/8d/302cb2057b7513327b4d575cff6b1d066ee6431a5357fc3f8867cd684406/jiter-0.15.0-graalpy312-graalpy250_312_native-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:54d5d6090cdc1b7c9e780dfb04949a990adb1e301a2fc0bbcee7de4638d33f9a", size = 344469, upload-time = "2026-05-19T10:09:46.864Z" }, +version = "0.16.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/1d/1f/10936e16d8860c70698a1aa939a46aa0224813b782bce4e000e637da0b2d/jiter-0.16.0.tar.gz", hash = "sha256:7b24c3492c5f4f84a37946ad9cf504910cf6a782d6a4e0689b6673c5894b4a1c", size = 176431, upload-time = "2026-06-29T13:05:13.657Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/76/d8/b959609e44012a42b1f3e5ba98ea3b33c7e41e6d4b77cd8f00fd19b1d3ad/jiter-0.16.0-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:c5fc4f8def331036a7b8e981b4347ebe409981edbc8308a5ea842b8c3614fa6c", size = 310082, upload-time = "2026-06-29T13:02:31.356Z" }, + { url = "https://files.pythonhosted.org/packages/c6/3d/4d7f5667ea0e0548534ba880b84bb3d12924fd133aa83ad6c6c80fca3d76/jiter-0.16.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:5a71d0d2014c3275043e1170bf3d4e771493cb0dcf07be54c567155f4d8ee64b", size = 315643, upload-time = "2026-06-29T13:02:33.204Z" }, + { url = "https://files.pythonhosted.org/packages/9b/83/bed2dcb5c9f3e1ccfcbc67dda48265fe7d5ad0c9cadda5fe95f6e3b87f94/jiter-0.16.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:741eed508c233a76313a1c7b001f8f21b82f14327e9196ae8bd29a2cc164ae84", size = 341363, upload-time = "2026-06-29T13:02:34.853Z" }, + { url = "https://files.pythonhosted.org/packages/f4/2f/6bb3c3dda668ebc0445689c81a2b0f26a82b10843d67ed9c9b2c3edc177f/jiter-0.16.0-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:3fb7bc819187b56dc48aa5c833aaf92257da8e07efdb9306156667bd2eeb491c", size = 365483, upload-time = "2026-06-29T13:02:36.295Z" }, + { url = "https://files.pythonhosted.org/packages/92/35/8a045ccb39164e70dcdae696413b661771f148b68b12b175c3a04d901937/jiter-0.16.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7c9610fd25ebccb43fca584136f5c2fbb26802447eccd430dfdbab95a0fd5126", size = 461219, upload-time = "2026-06-29T13:02:38.116Z" }, + { url = "https://files.pythonhosted.org/packages/e7/99/22292dbbf0ed0c610cfe5ddc7f3bd67237a412f121318f865196e62a07bd/jiter-0.16.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4a1d68ff7ca1d3b5dee20a97a3decda7d5f15003823bf6d140c81f8561d3bc5c", size = 374905, upload-time = "2026-06-29T13:02:40.357Z" }, + { url = "https://files.pythonhosted.org/packages/29/ac/2f55ccb1f0eeafa6d89d24caf52f6f0944a59290ee199e9ade62177dca42/jiter-0.16.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fb08c276dd02dac3a284acdd02cacc630d2e3cd6572a4b85519f35cbd133c3de", size = 348320, upload-time = "2026-06-29T13:02:41.923Z" }, + { url = "https://files.pythonhosted.org/packages/50/e3/7d88b9174c40064fabc07c84a9b62e6b10f5644562ec0e0a29392edbe978/jiter-0.16.0-cp310-cp310-manylinux_2_31_riscv64.whl", hash = "sha256:8fc4d94713c4697347e38faf7d6ef91547c142219bdcfc7220c4870879974244", size = 356519, upload-time = "2026-06-29T13:02:43.436Z" }, + { url = "https://files.pythonhosted.org/packages/27/57/c4a33aeef513a9d5e26e31534e0bcc752d6ea0e54c94ddb7b68bade669c2/jiter-0.16.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:1a0f05e229edb29e68cdd0ccb83cea13b64263416120cf943767a6fd72e6787f", size = 394204, upload-time = "2026-06-29T13:02:44.987Z" }, + { url = "https://files.pythonhosted.org/packages/9d/70/c6c23e76ebb3766b111bc399437bbc9f870a76e2a92e10b2a5f561d57372/jiter-0.16.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:2c842cbf374a8daf50b2c04212995bee34ca2ac2cdc29a901b4cdb072c9c4131", size = 521477, upload-time = "2026-06-29T13:02:46.724Z" }, + { url = "https://files.pythonhosted.org/packages/2a/d3/0001c8c0c5976af2625bb1cfb1895e8ec693b6589fe4574b8e6fc2c85501/jiter-0.16.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:5ed466aee31294d7cdcd4d37dfe5c42c97bc29d9a5f00eacf24504358309cb9b", size = 552187, upload-time = "2026-06-29T13:02:48.144Z" }, + { url = "https://files.pythonhosted.org/packages/f6/76/311b718e07e85740e48619c0632b36f7e0b8d113984499e436452ed13a9a/jiter-0.16.0-cp310-cp310-win32.whl", hash = "sha256:b42e9ff5376819c053da25809a8d4b6fa6e473b4856ebe42e298ac958be3d7f9", size = 206513, upload-time = "2026-06-29T13:02:49.515Z" }, + { url = "https://files.pythonhosted.org/packages/db/7f/ac680eeb0777dc0eb7dc824800ba27880d7f6bc712e362d34ad8ee559f36/jiter-0.16.0-cp310-cp310-win_amd64.whl", hash = "sha256:10438939205546132189c8e74a2d536a707841f3a25cd7c74ee91fe503407a26", size = 199505, upload-time = "2026-06-29T13:02:50.829Z" }, + { url = "https://files.pythonhosted.org/packages/4e/3f/fae6cc967d120ec89e31c5418a51176d8278b3087fbb384a9176754f353c/jiter-0.16.0-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:67fddeda1688f0cce2d2ae83ccf8a80f79936f2d2997d6cc2261f82fdb54a4d3", size = 309289, upload-time = "2026-06-29T13:02:52.301Z" }, + { url = "https://files.pythonhosted.org/packages/c8/e3/97c6c3562c077f6247d6e6ce5c82562500b6316c0d928e97e106b7a1321a/jiter-0.16.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:c90c0f63df322be920eda6ce622e3083d8906ba267f8220fe7873213b8b4430e", size = 315181, upload-time = "2026-06-29T13:02:53.964Z" }, + { url = "https://files.pythonhosted.org/packages/7b/89/d8d073f8aa2667e46c6c0873f86fe4a512bba4293cc730f626a076211a62/jiter-0.16.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:64c0203212098470032aabcde9356fc168f377aade3e43def61dfe17e92f2037", size = 340939, upload-time = "2026-06-29T13:02:55.412Z" }, + { url = "https://files.pythonhosted.org/packages/87/c9/db4fda3ed73fb864139305e935e5b8b38a5a24692a5a9dd356c22f1b9c8d/jiter-0.16.0-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:12288303c9844e61e1651d02a9a6f6633e47d39f897d6991d1427161ce6b746e", size = 364932, upload-time = "2026-06-29T13:02:57.28Z" }, + { url = "https://files.pythonhosted.org/packages/a2/74/52b5e86241057f52ddd7c9a580f90effb51f9d06239f6fc612279b91a838/jiter-0.16.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5cf109d010b4b05a105afb3d43be36a21322d345ad3111e13d15f680afef0e5b", size = 461132, upload-time = "2026-06-29T13:02:58.994Z" }, + { url = "https://files.pythonhosted.org/packages/a9/87/544a700f7447c1f31c5d7833821a4daa5683165c2d5a094fbf5b5800c3dc/jiter-0.16.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:62c1b7fe1f77925acf5af68b6140b8810fa87dfd4dc0a9c8568ec2fa2a10429c", size = 374857, upload-time = "2026-06-29T13:03:00.455Z" }, + { url = "https://files.pythonhosted.org/packages/40/cd/0fcc3f7d39183674d5bfa9ec640faaeb506c60be7c8f94625dfba366e37c/jiter-0.16.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8597d23c87f59294f83bcb6229b9ed1fccee13dbba967b46930d2f1759466fee", size = 347053, upload-time = "2026-06-29T13:03:02.045Z" }, + { url = "https://files.pythonhosted.org/packages/5c/ae/c7e64e7932ad597fa395b61440b249ada6366716e25c6e08dd2afbd021e6/jiter-0.16.0-cp311-cp311-manylinux_2_31_riscv64.whl", hash = "sha256:3126a5dbad56401989ac769aca0cb56005bfb3e2366eea0ca99d1a91c3c1ee03", size = 356153, upload-time = "2026-06-29T13:03:03.706Z" }, + { url = "https://files.pythonhosted.org/packages/d4/1c/1c719044f14da814e1a060191ab19b96f3e99207bc5b4bfc6d6be34b3f80/jiter-0.16.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:c4b4717bdb35ae456f831a6b08d01880fff399887a6bbc526a583a406e484eea", size = 393956, upload-time = "2026-06-29T13:03:05.165Z" }, + { url = "https://files.pythonhosted.org/packages/3b/dc/7b2f303a2847207e265503853a2d964a55354cffd62a5f2936c155486798/jiter-0.16.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:adff21bc78edfe086c15eb495b900306076de378dc2337c132401fc39bd79c91", size = 521081, upload-time = "2026-06-29T13:03:06.886Z" }, + { url = "https://files.pythonhosted.org/packages/c2/5f/501cf6e1e09caeb420195179ffc6f62aca603f1220ec53fd80d0d70b3e56/jiter-0.16.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:dab907db06fc593645e73109acf4581ba5b548897d28b9348dc41ddc8343b2d3", size = 552085, upload-time = "2026-06-29T13:03:08.339Z" }, + { url = "https://files.pythonhosted.org/packages/79/54/aa5be86520113b79455c3877f3d1f07a348098df4083ba3688e9537e52dd/jiter-0.16.0-cp311-cp311-win32.whl", hash = "sha256:560b2cf3fb03240cd34f27409a238547488708f05b7c3924f571a60422251ec7", size = 206755, upload-time = "2026-06-29T13:03:09.653Z" }, + { url = "https://files.pythonhosted.org/packages/64/ec/2feb893eb330bd69b413866f4d5daada33c3962f1c6f270c91ca2d87fdf9/jiter-0.16.0-cp311-cp311-win_amd64.whl", hash = "sha256:e431cfc9caf44c1d5459ff77d4e64cbf85fddb6a35dad836a15c6a9ec23087c1", size = 199155, upload-time = "2026-06-29T13:03:10.979Z" }, + { url = "https://files.pythonhosted.org/packages/b9/9c/ca040d94415048a3666fc237774df8151c96f8d2b661cbe3b184acc95876/jiter-0.16.0-cp311-cp311-win_arm64.whl", hash = "sha256:2a8e9e39cf083016137aa5cadafe3188adc2ba6ba1fbf1e5d18889ad3e9ad056", size = 194403, upload-time = "2026-06-29T13:03:12.341Z" }, + { url = "https://files.pythonhosted.org/packages/83/2b/52ace16ed031354f0539749a49e4bf33797d82bea5137910835fa4b09793/jiter-0.16.0-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:67c3bc1760f8c99d805dcab4e644027142a53b1d5d861f18780ebdbd5d40b72a", size = 306943, upload-time = "2026-06-29T13:03:14.035Z" }, + { url = "https://files.pythonhosted.org/packages/94/2e/34957c2c1b661c252ba9bcc60ae0bddc27e0f7202c6073326a13c5390eec/jiter-0.16.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:5af7780e4a26bd7d0d989592bf9ef12ebf806b74ab709223ecca37c749872ea9", size = 307779, upload-time = "2026-06-29T13:03:15.418Z" }, + { url = "https://files.pythonhosted.org/packages/88/6c/59bd309cab4460c54cf1079f3eb7fe7af6a4c895c5c957a53378693bad2b/jiter-0.16.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d5bf78d0e05e45cfdd66558893938d59afe3d1b1a824a202039b20e607d25a72", size = 335826, upload-time = "2026-06-29T13:03:17.11Z" }, + { url = "https://files.pythonhosted.org/packages/3b/8c/f5ef7b65f0df47afa16596969defb281ebb86e96df346d62be6fd853d620/jiter-0.16.0-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:f4444a83f946605990c98f625cdd3d2725bfb818158760c5748c653170a20e0e", size = 362573, upload-time = "2026-06-29T13:03:18.781Z" }, + { url = "https://files.pythonhosted.org/packages/2b/0b/ace4354da061ee38844a0c27dc2c21eecd27aea119e8da324bea987522d0/jiter-0.16.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3a23f0e4f957e1be65752d2dfac9a5a06b1917af8dc85deb639c3b9d02e31290", size = 457979, upload-time = "2026-06-29T13:03:20.293Z" }, + { url = "https://files.pythonhosted.org/packages/55/40/c0253d3772eb9dcd8e6606ee9b2d53ec8e5b814589c47f140aa585f21eaa/jiter-0.16.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c22a488f7b9218e245a0025a9ba6b100e2e54700831cf4cf16833a27fba3ad01", size = 372302, upload-time = "2026-06-29T13:03:21.739Z" }, + { url = "https://files.pythonhosted.org/packages/a8/d2/4839422241aa12860ce597b20068727094ba0bc480723c74924ca5bad483/jiter-0.16.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:46add52f4ad47a08bfb1219f3e673da972191489a33016edefdb5ea55bfa8c48", size = 343805, upload-time = "2026-06-29T13:03:23.384Z" }, + { url = "https://files.pythonhosted.org/packages/e2/59/e196888a05befdda7dbe299b722d56f2f6eec65402bc34c0a3306d595feb/jiter-0.16.0-cp312-cp312-manylinux_2_31_riscv64.whl", hash = "sha256:9c8a956fd72c2cf1e730d01ea080341f13aa0a97a4a33b51abebe725b7ae9ca9", size = 351107, upload-time = "2026-06-29T13:03:24.815Z" }, + { url = "https://files.pythonhosted.org/packages/ec/74/4cd9e0fca65232136400354b630fbfcd2de634e22ccbb96567725981b548/jiter-0.16.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:561926e0573ffe4a32498420a76d64b16c513e1ab413b9d28158a8764ac701e5", size = 388441, upload-time = "2026-06-29T13:03:26.266Z" }, + { url = "https://files.pythonhosted.org/packages/d9/8c/554691e48bc711299c0a293dd8a6179e24b2d66a54dc295421fcf64569c0/jiter-0.16.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:44d019fa8cdaf89bf29c71b39e3712143fdd0ac76725c6ef954f9957a5ea8730", size = 516354, upload-time = "2026-06-29T13:03:28.02Z" }, + { url = "https://files.pythonhosted.org/packages/a4/cb/01e9d69dc2cc6759d4f91e230b34489c4fdb2518992650633f9e20bece89/jiter-0.16.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:0df91907609837f33341b8e6fe73b95991fdaa57caf1a0fbd343dffe826f386f", size = 547880, upload-time = "2026-06-29T13:03:29.534Z" }, + { url = "https://files.pythonhosted.org/packages/79/70/2953195f1c6ad00f49fa67e13df7e60acb3dd4f387101bc15abccddd905e/jiter-0.16.0-cp312-cp312-win32.whl", hash = "sha256:51d7b836acb0108d7c77df1742332cac2a1fa04a74d6dacec46e7091f0e91274", size = 203473, upload-time = "2026-06-29T13:03:31.025Z" }, + { url = "https://files.pythonhosted.org/packages/2d/05/2909a8b10699a4d560f8c502b6b2c5f3991b682b1922c1eedda242b225bd/jiter-0.16.0-cp312-cp312-win_amd64.whl", hash = "sha256:1878349266f8ee36ecb1375cc5ba2f115f35fd9f0a1a4119e725e379126647f7", size = 196905, upload-time = "2026-06-29T13:03:32.472Z" }, + { url = "https://files.pythonhosted.org/packages/e9/a9/6b82bb1c8d7790d602489b967b982a909e5d092875a6c2ade96444c8dfc5/jiter-0.16.0-cp312-cp312-win_arm64.whl", hash = "sha256:2ed5738ae4af18271a51a528b8811b0cbfa4a1858de9d83359e4169855d6a331", size = 190618, upload-time = "2026-06-29T13:03:34.672Z" }, + { url = "https://files.pythonhosted.org/packages/91/c0/555fc60473d30d66894ba825e63615e3be7524fac23858356afa7a38906c/jiter-0.16.0-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:41977aa5654023948c2dae2a81cbf9c43343954bef1cd59a154dd15a4d84c195", size = 306203, upload-time = "2026-06-29T13:03:36.243Z" }, + { url = "https://files.pythonhosted.org/packages/d0/2b/c3eaf16f5d7c9bad66ea32f40a95bd169b29a91217fcc7f081375157e99c/jiter-0.16.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:d28bb3c26762358dadf3e5bf0bccd29ae987d65e6988d2e6f49829c76b003c09", size = 306489, upload-time = "2026-06-29T13:03:37.846Z" }, + { url = "https://files.pythonhosted.org/packages/96/3f/02fdfc6705cad96127d883af5c34e4867f554f29ec7705ec1a46156400a9/jiter-0.16.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0542a7189c26920778658fc8fcf2af8bae05bae9924577f71804acef37996536", size = 335453, upload-time = "2026-06-29T13:03:39.221Z" }, + { url = "https://files.pythonhosted.org/packages/b2/a6/e4bda5920d4b0d7c5dfb7174ce4a6b2e4d3e11c9162c452ef0eab4cdbdbd/jiter-0.16.0-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:8fb8de1e23a0cb2a7f53c335049c7b72b6db41aa6227cdcc0972a1de5cb39450", size = 361625, upload-time = "2026-06-29T13:03:40.597Z" }, + { url = "https://files.pythonhosted.org/packages/b7/97/4e6b59b2c6e55cbb3e183595f81ad65dcfb21c915fee5e19e335df21bc55/jiter-0.16.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b72d0b2990ca754a9102779ac98d8597b7cb31678958562214a007f909eab78e", size = 456958, upload-time = "2026-06-29T13:03:42.074Z" }, + { url = "https://files.pythonhosted.org/packages/15/e0/97e9557686d2f94f4b93786eccb7eed28e9228ad132ea8237f44727314a7/jiter-0.16.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d5f91b1c27fc22a57993d5a5cb8a627cb8ed4b10502716fac1ffbfe1d19d84e8", size = 372017, upload-time = "2026-06-29T13:03:43.658Z" }, + { url = "https://files.pythonhosted.org/packages/0f/94/db768b6938e0df35c86beeba3dfbbb025c9ee5c19e1aa271f2396e50864d/jiter-0.16.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c682bea068a90b764577bdb78a60a4c1d1606daf9cd4c893832a37c7cc9d9026", size = 343320, upload-time = "2026-06-29T13:03:45.226Z" }, + { url = "https://files.pythonhosted.org/packages/c1/d6/5a59d938244a30735fe62d9433fd325f9021ea29d89780ea4596ea93bc89/jiter-0.16.0-cp313-cp313-manylinux_2_31_riscv64.whl", hash = "sha256:8d031aabecc4f1b6276adfb42e3aabb77c89d468bf616600e8d3a11328929053", size = 350520, upload-time = "2026-06-29T13:03:46.671Z" }, + { url = "https://files.pythonhosted.org/packages/67/f8/c4a857f49c9af125f6bbcac7e3eee7f7978ed89682833062e2dbf62576b1/jiter-0.16.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:eab2cd170150e70153de16896a1774e3a1dca80154c56b54d7a812c479a7165e", size = 387550, upload-time = "2026-06-29T13:03:48.361Z" }, + { url = "https://files.pythonhosted.org/packages/8b/d6/5fbc2f7d6b67b754caa61a993a2e626e815dec47ffc2f9e35f01adfebec7/jiter-0.16.0-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:6edb63a46e65a82c26800a868e49b2cac30dd5a4218b88d74bc2c848c8ad60bb", size = 515424, upload-time = "2026-06-29T13:03:49.881Z" }, + { url = "https://files.pythonhosted.org/packages/ed/54/284f0164b64a5fed915fea6ba7e9ba9b3d8d37c67d59cf2e3bb99d45cdfe/jiter-0.16.0-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:659039cc50b5addcc35fcc87ae2c1833b7c0a8e5326ef631a75e4478447bcf84", size = 546981, upload-time = "2026-06-29T13:03:51.363Z" }, + { url = "https://files.pythonhosted.org/packages/13/c5/2a467585a576594384e1d2c43e1224deaafc085f24e243529cf98beef8e1/jiter-0.16.0-cp313-cp313-win32.whl", hash = "sha256:c9c53be232c2e206ef9cdbad81a48bfa74c3d3f08bcf8124630a8a748aad993e", size = 202853, upload-time = "2026-06-29T13:03:53.015Z" }, + { url = "https://files.pythonhosted.org/packages/88/6a/de61d04b9eec69c71719968d2f716532a3bc121170c44a39e14979c6be81/jiter-0.16.0-cp313-cp313-win_amd64.whl", hash = "sha256:baad945ed47f163ad833314f8e3288c396118934f94e7bbb9e243ce4b341a4fd", size = 196160, upload-time = "2026-06-29T13:03:54.447Z" }, + { url = "https://files.pythonhosted.org/packages/19/4b/b390ed59bafb3f31d008d1218578f10327714484b334439947f7e5b11e7f/jiter-0.16.0-cp313-cp313-win_arm64.whl", hash = "sha256:3c1fd2dbe1b0af19e987f03fe66c5f5bd105a2229c1aff4ab14890b24f41d21a", size = 189862, upload-time = "2026-06-29T13:03:55.754Z" }, + { url = "https://files.pythonhosted.org/packages/a7/89/bc4f1b57d5da938fd344a466396541e586d161320d70bffd929aaafcd8f4/jiter-0.16.0-cp314-cp314-macosx_10_12_x86_64.whl", hash = "sha256:b2c61484666ad42726029af0c00ef4541f0f3b5cdc550221f56c2343208018ee", size = 308239, upload-time = "2026-06-29T13:03:57.205Z" }, + { url = "https://files.pythonhosted.org/packages/65/7a/c415453e5213001bf3b411ff65dec3d303b0e76a4a2cfea9768cd4960994/jiter-0.16.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:63efadc657488f45db1c676d81e704cac2abf3fdb892def1faea61db053127e2", size = 308928, upload-time = "2026-06-29T13:03:58.643Z" }, + { url = "https://files.pythonhosted.org/packages/11/fc/1f4fb7ebf9a724c7741994f4aae18fba1e2f3133df14521a79194952c34a/jiter-0.16.0-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cf0d73f50e7b6935677854f6e8e31d499ca7064dd24734f703e060f5b237d883", size = 336998, upload-time = "2026-06-29T13:04:00.071Z" }, + { url = "https://files.pythonhosted.org/packages/a0/8d/72cadaac05ccfa7cc3a0a2232862e6c72443ca40cf300ba8b57f9f18b69b/jiter-0.16.0-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:bf3ea07d9bc8e7d03a9fbc051295462e6dbc295b894fd72457c3136e3e43d898", size = 362112, upload-time = "2026-06-29T13:04:01.52Z" }, + { url = "https://files.pythonhosted.org/packages/58/4a/c4b0d5f651fda90a24ffce9f8d56cde462a2e09d31ae3de3c68cef34c04e/jiter-0.16.0-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:26798522707abb47d767db536e4148ceac1b14446bf028ee85e579a2e043cfe5", size = 459807, upload-time = "2026-06-29T13:04:03.214Z" }, + { url = "https://files.pythonhosted.org/packages/80/58/ef77879ea9aa56b50824edc5a445e226422c7a8d211f3fd2a56bcb9493cf/jiter-0.16.0-cp314-cp314-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:bc837c1b9631be10abfe0191537fe8009838204cec7e44827401ace390ddb567", size = 373181, upload-time = "2026-06-29T13:04:04.629Z" }, + { url = "https://files.pythonhosted.org/packages/49/2e/ffbc3f254e4d8a66da3062c624a7df4b7c2b2cf9e1fe43cf394b3e104041/jiter-0.16.0-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:49060fd70737fad59d33ba9dcc0d83247dc9e77187de26053a19c16c9f32bd69", size = 344927, upload-time = "2026-06-29T13:04:06.067Z" }, + { url = "https://files.pythonhosted.org/packages/9a/f6/0be5dc6d64a89f80aa8fec984f94dedb2973e251edcae55841d60786d578/jiter-0.16.0-cp314-cp314-manylinux_2_31_riscv64.whl", hash = "sha256:adbb8edeadd431bc4477879d5d371ece7cb1334486584e0f252656dd7ffada29", size = 352754, upload-time = "2026-06-29T13:04:07.477Z" }, + { url = "https://files.pythonhosted.org/packages/da/6e/7d31243b3b91cd261dd19e9d3557fc3251a80883d3d8049c86174e7ab7af/jiter-0.16.0-cp314-cp314-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:31aaee5b80f672c1dc21272bcfb9cbdcfc1ea04ff50f00ed5af500b80c44fa93", size = 390553, upload-time = "2026-06-29T13:04:08.92Z" }, + { url = "https://files.pythonhosted.org/packages/25/33/51ae371fde3c88897520f62b4d5f8b27ad7103e2bb10812ff52195609853/jiter-0.16.0-cp314-cp314-musllinux_1_1_aarch64.whl", hash = "sha256:6722bcef4ffc86c835574b1b2fac6b33b9fb4a889c781e67950e891591f3c55a", size = 516900, upload-time = "2026-06-29T13:04:10.407Z" }, + { url = "https://files.pythonhosted.org/packages/a0/45/6449b3d123ea439ba79507c657288f461d55049e7bcbdc2cf8eb8210f491/jiter-0.16.0-cp314-cp314-musllinux_1_1_x86_64.whl", hash = "sha256:5ab4f50ff971b611d656554ea10b75f80097392c827bc32923c6eeb6386c8b00", size = 548754, upload-time = "2026-06-29T13:04:12.046Z" }, + { url = "https://files.pythonhosted.org/packages/9b/e7/fd2fb11ae3e2649333da3aa170d04d7b3000bbdc3b270f6513382fdf4e04/jiter-0.16.0-cp314-cp314-pyemscripten_2026_0_wasm32.whl", hash = "sha256:710cc51d4ebdcd3c1f70b232c1db1ea1344a075770422bbd4bede5708335acbe", size = 122381, upload-time = "2026-06-29T13:04:13.413Z" }, + { url = "https://files.pythonhosted.org/packages/26/80/f0b147a62c315a164ed2168908286ca302310824c218d3aae52b06c0c9a9/jiter-0.16.0-cp314-cp314-win32.whl", hash = "sha256:57b37fc887a32d44798e4d8ebfa7c9683ff3da1d5bf38f08d1bb3573ccb39106", size = 204578, upload-time = "2026-06-29T13:04:14.813Z" }, + { url = "https://files.pythonhosted.org/packages/5e/e6/4758a14304b4523a6f5adb2419340086aa3593bd4327c2b25b5948a90548/jiter-0.16.0-cp314-cp314-win_amd64.whl", hash = "sha256:cbd18dd5e2df96b580487b5745adf57ef64ad89ba2d9662fc3c19386acce7db8", size = 198154, upload-time = "2026-06-29T13:04:16.272Z" }, + { url = "https://files.pythonhosted.org/packages/26/be/41fa54a2e7ea41d6c99f1dc5b1f0fd4cb474680304b5d268dd518e81da3a/jiter-0.16.0-cp314-cp314-win_arm64.whl", hash = "sha256:a32d2027a9fa67f109ff245a3252ece3ccc32cc56703e1deab6cc846a59e0585", size = 191458, upload-time = "2026-06-29T13:04:17.707Z" }, + { url = "https://files.pythonhosted.org/packages/81/6b/59127338b86d9fe4d99418f5a15118bea778103ee0fe9d9dd7e0af174e95/jiter-0.16.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:2577196f4474ef3fc4779a088a23b0897bbf86f9ea3679c372d45b8383b43207", size = 316739, upload-time = "2026-06-29T13:04:19.663Z" }, + { url = "https://files.pythonhosted.org/packages/2d/95/49461034d5388196d3dabf98748935f017b7785d8f3f5349f834bcc4ed0d/jiter-0.16.0-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:616e89e008a93c01104161c75b4988e58716b01d62307ebfe161e52a56d2a818", size = 340911, upload-time = "2026-06-29T13:04:21.257Z" }, + { url = "https://files.pythonhosted.org/packages/cd/97/a4369f2fb82cb3dda13b98622f31249b2e014b223fe64ee534413ad72294/jiter-0.16.0-cp314-cp314t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:0e2e9efbe042210df657bade597f66d6d75723e3d8f45a12ea6d8167ff8bbce3", size = 361747, upload-time = "2026-06-29T13:04:22.677Z" }, + { url = "https://files.pythonhosted.org/packages/28/51/49b6ed456261646e1906016a6760367a28aacd3c24805e4e5fe64116c1db/jiter-0.16.0-cp314-cp314t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3f4d9e473a5ce7d27fef8b848df4dc16e283893d3f53b4a585e72c9595f3c284", size = 460225, upload-time = "2026-06-29T13:04:24.441Z" }, + { url = "https://files.pythonhosted.org/packages/33/b5/5689aff4f66c5b60be63106e591dbfcba2190df97d2c9c7cf052361ddb98/jiter-0.16.0-cp314-cp314t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8d30a4a1c87713060c8d1cc59a7b6c8fb6b8ef0a6900368014c76c87922a2929", size = 373169, upload-time = "2026-06-29T13:04:25.884Z" }, + { url = "https://files.pythonhosted.org/packages/a2/96/3ae1b85ee0d6d6cab254fb7f8da018272b932bbf2d69b07e98aa2a96c746/jiter-0.16.0-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bae96332410f866e5900d809298b1ed82735932986c672495f9701daacd80620", size = 350332, upload-time = "2026-06-29T13:04:27.302Z" }, + { url = "https://files.pythonhosted.org/packages/15/32/c99d7bafd78986556c95bf60ce84c6cc98786eac56066c12d7f828bb6747/jiter-0.16.0-cp314-cp314t-manylinux_2_31_riscv64.whl", hash = "sha256:da3d7ec75dc83bb18bca888b5edfae0656a26849056c59e05a7728badd17e7af", size = 353377, upload-time = "2026-06-29T13:04:28.731Z" }, + { url = "https://files.pythonhosted.org/packages/0e/4b/f99a8e571287c3dec766bcc18528bbe8e8fb5365522ab5e6d64c93e87066/jiter-0.16.0-cp314-cp314t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:ee6162b77d49a9939229df666dfa8af3e656b6701b54c4c84966d740e189264e", size = 387746, upload-time = "2026-06-29T13:04:30.319Z" }, + { url = "https://files.pythonhosted.org/packages/75/69/c78a5b3f71040e34eb5917df26fb7ae9a2174cad1ccbf277512507c53a6e/jiter-0.16.0-cp314-cp314t-musllinux_1_1_aarch64.whl", hash = "sha256:63ffdbdae7d4499f4cda14eadc12ddcabef0fc0c081191bdc2247489cb698077", size = 517292, upload-time = "2026-06-29T13:04:31.709Z" }, + { url = "https://files.pythonhosted.org/packages/c2/f7/095b38eda4c70d03651c403f29a5590f16d12ddc5d544aac9f9cddf72277/jiter-0.16.0-cp314-cp314t-musllinux_1_1_x86_64.whl", hash = "sha256:a111256a7193bea0759267b10385e5870949c239ed7b6ddbaaf57573edb38734", size = 549259, upload-time = "2026-06-29T13:04:33.721Z" }, + { url = "https://files.pythonhosted.org/packages/2e/c5/6a0207d90e5f656d95af98ebd0934f382d37674416f215aeda2ff8063e51/jiter-0.16.0-cp314-cp314t-win32.whl", hash = "sha256:de5ba8763e56b793561f43bed197c9ea55776daa5e9a6b91eed68a909bc9cdbf", size = 206523, upload-time = "2026-06-29T13:04:35.068Z" }, + { url = "https://files.pythonhosted.org/packages/a5/31/c757d5f30a8980fd945ce7b98be10be9e4ff59c7c42f5fd86804c2e87db8/jiter-0.16.0-cp314-cp314t-win_amd64.whl", hash = "sha256:b8a3f9a6008048fe9def7bf465180564a6e458047d2ce499149cfbe73c3ae9db", size = 200366, upload-time = "2026-06-29T13:04:36.61Z" }, + { url = "https://files.pythonhosted.org/packages/7c/a2/d88de6d313d734a544a7901353ad5db67cb38dcfcd91713b7979dafc345d/jiter-0.16.0-cp314-cp314t-win_arm64.whl", hash = "sha256:0fa25b09b13075c46f5bc174f2690525a925a4fc2f7c82969a2bbabff22386ce", size = 190516, upload-time = "2026-06-29T13:04:38.004Z" }, + { url = "https://files.pythonhosted.org/packages/06/d3/8e278946d43eeca2585b4dd0834a887cd71136329b837f3a16ed86a8b4b0/jiter-0.16.0-graalpy311-graalpy242_311_native-macosx_10_12_x86_64.whl", hash = "sha256:850ccb1d7eedb4200f4014b1c0e8a577de114fc3cd88faad646dcc9bc4bb12ad", size = 304518, upload-time = "2026-06-29T13:05:00.172Z" }, + { url = "https://files.pythonhosted.org/packages/72/43/28d4ef495028bf0506a413d4db3f4eb3e7288a382e0f065f306a17bbeb5e/jiter-0.16.0-graalpy311-graalpy242_311_native-macosx_11_0_arm64.whl", hash = "sha256:e34e97bda77eb63242a410243c071e28ac7e0d8c0948c5ee658498690a4b2f2f", size = 310207, upload-time = "2026-06-29T13:05:02.123Z" }, + { url = "https://files.pythonhosted.org/packages/e0/ca/c366b1012da1d640de975d9683acd44e4d150d9068845d0ca2610435253f/jiter-0.16.0-graalpy311-graalpy242_311_native-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b7dc85ea77d4abbae8bad0d3538678aedee75bceec4e2f6c8dfb1c74772e5aa5", size = 342771, upload-time = "2026-06-29T13:05:03.55Z" }, + { url = "https://files.pythonhosted.org/packages/16/52/50cc4056fc1ae02e7154704e7ecc89df0afb8300222cfe8a52d3f67e4730/jiter-0.16.0-graalpy311-graalpy242_311_native-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:17ca7fae79f6d99cd9a042b75f917eaada7b895cfc7dd2ee3a16089dcaec7a85", size = 346468, upload-time = "2026-06-29T13:05:05.452Z" }, + { url = "https://files.pythonhosted.org/packages/98/ab/664fd8c4be028b2bedd3d2ff08769c4ede23d0dbc87a77c62384a0515b5d/jiter-0.16.0-graalpy312-graalpy250_312_native-macosx_10_12_x86_64.whl", hash = "sha256:f17d61a28b4b3e0e3e2ba98490c70501403b4d196f78732439160e7fd3678127", size = 303106, upload-time = "2026-06-29T13:05:07.118Z" }, + { url = "https://files.pythonhosted.org/packages/1a/07/421f1d5b65493a76e16027b848aba6a7d28073ae75944fa4289cc914d39f/jiter-0.16.0-graalpy312-graalpy250_312_native-macosx_11_0_arm64.whl", hash = "sha256:96e38eea538c8ddf853a35727c7be0741c76c13f04148ac5c116222f50ece3b3", size = 304658, upload-time = "2026-06-29T13:05:08.708Z" }, + { url = "https://files.pythonhosted.org/packages/0a/db/bba1155f01a01c3c37a89425d571da751bbedf5c54247b831a04cb971798/jiter-0.16.0-graalpy312-graalpy250_312_native-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d284fb8d94d5855d60c44fefcab4bf966f1da6fada73992b01f6f0c9bc0c6702", size = 339719, upload-time = "2026-06-29T13:05:10.41Z" }, + { url = "https://files.pythonhosted.org/packages/78/f7/18a1afcd64f35314b68c1f23afcd9994d0bc13e65cc77517afff4e83986d/jiter-0.16.0-graalpy312-graalpy250_312_native-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:64d613743df53199b1aa256a7d328340da6d7078aac7705a7db9d7a791e9cfd2", size = 343885, upload-time = "2026-06-29T13:05:12.087Z" }, ] [[package]] @@ -1830,14 +1820,14 @@ wheels = [ [[package]] name = "joserfc" -version = "1.7.1" +version = "1.7.3" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "cryptography" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/44/90/25cb27518750218e4f850be63d8bbb2343efaad1c01c3571aaa4b3c33bd7/joserfc-1.7.1.tar.gz", hash = "sha256:77d0b76514879c68c6f433bc5b7357a4ab72008ff1e33d8379fd11d72bd8ca81", size = 233181, upload-time = "2026-06-08T07:21:33.412Z" } +sdist = { url = "https://files.pythonhosted.org/packages/d4/c6/b1cac0280f8efc57626ea8804866b37099f23cae11b1485a42b213245e31/joserfc-1.7.3.tar.gz", hash = "sha256:116955c2587139dba20621fd0bd7fc9255fa960c9fe7f43c43ebef2e801dcfcf", size = 233821, upload-time = "2026-07-08T12:41:42.66Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/b3/00/fa62404c3e347f946faa13aa21085205f9cc06ad17671e37f81a51662ae8/joserfc-1.7.1-py3-none-any.whl", hash = "sha256:b3e3d655612e2e1ef67b2600f2f420e12e537b020208fab1761fad647319c164", size = 70423, upload-time = "2026-06-08T07:21:32.001Z" }, + { url = "https://files.pythonhosted.org/packages/7d/f5/650b59d1b74f5befb7a7a7e7d7c92a26b94256df3541e2b4914152cd177a/joserfc-1.7.3-py3-none-any.whl", hash = "sha256:7c39f3f2c943dbc03122747fa8ebbd8e156e54904cf25651b452f4d2634a6075", size = 70982, upload-time = "2026-07-08T12:41:41.521Z" }, ] [[package]] @@ -1879,7 +1869,7 @@ dependencies = [ { name = "jsonschema-specifications" }, { name = "referencing" }, { name = "rpds-py", version = "0.30.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.11'" }, - { name = "rpds-py", version = "2026.5.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" }, + { name = "rpds-py", version = "2026.6.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/b3/fc/e067678238fa451312d4c62bf6e6cf5ec56375422aee02f9cb5f909b3047/jsonschema-4.26.0.tar.gz", hash = "sha256:0c26707e2efad8aa1bfc5b7ce170f3fccc2e4918ff85989ba9ffa9facb2be326", size = 366583, upload-time = "2026-01-07T13:41:07.246Z" } wheels = [ @@ -1933,7 +1923,7 @@ wheels = [ [[package]] name = "langchain-core" -version = "1.4.7" +version = "1.4.9" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "jsonpatch" }, @@ -1946,26 +1936,26 @@ dependencies = [ { name = "typing-extensions" }, { name = "uuid-utils" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/ee/2b/fffaff399d20a56d40b9562fa19701e91abd72d8c9d9bc8c2673077b56b6/langchain_core-1.4.7.tar.gz", hash = "sha256:7a825d77de0a3f39adbd9d09612a75e85527e14a52c1601089bcc062972d9f2b", size = 952522, upload-time = "2026-06-12T19:23:57.588Z" } +sdist = { url = "https://files.pythonhosted.org/packages/2a/b9/e937d0a90b26540bff07e7a7c64349f3b29c2dcc36257cd1cd3fdce17f2a/langchain_core-1.4.9.tar.gz", hash = "sha256:f8078901145bed0466755277500a5a22822a7b628808c4c0a28d4fc88895fcf2", size = 967294, upload-time = "2026-07-08T20:06:54.191Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/de/3e/dcdffa60078ae7b3a00ebb4cbbf1a204a14c3609983c604886523a7d4418/langchain_core-1.4.7-py3-none-any.whl", hash = "sha256:bcadd51951140ecdcba98311dbd931ba5de02a5ba8a2288dad5069c1eea2a13d", size = 554941, upload-time = "2026-06-12T19:23:55.826Z" }, + { url = "https://files.pythonhosted.org/packages/84/70/ade2fada52772798ef815b6352b59e71b116aa0c32c3aef5be3dc2cbed12/langchain_core-1.4.9-py3-none-any.whl", hash = "sha256:28e3909e2a10cc81504952d795ac0a9e014c0018121ef89d48dd396fa09ec624", size = 558293, upload-time = "2026-07-08T20:06:52.382Z" }, ] [[package]] name = "langchain-protocol" -version = "0.0.17" +version = "0.0.18" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/44/b3/4e2429876c7a35585618caa2b9f9089f7162a6b50562b614ad82ac11c17e/langchain_protocol-0.0.17.tar.gz", hash = "sha256:e7cbe58c205df4b4fd87dc6d5bb23f10e13b236d0e2e1b0b9d05bc2b648f3eea", size = 6026, upload-time = "2026-06-12T18:39:51.923Z" } +sdist = { url = "https://files.pythonhosted.org/packages/d2/59/b5959aea96faa9146e2e49a7a22882b3528c62efafe9a6a95beab30c2305/langchain_protocol-0.0.18.tar.gz", hash = "sha256:ec3e11782f1ed0c9db38e5a9ed01b0e7a0d3fba406faa8aef6594b73c56a63e6", size = 6150, upload-time = "2026-06-18T17:08:26.959Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/13/0a/a1bfe72c6ec856e99773bbd96c8086421e554b3693d0142b9ea009c6ac92/langchain_protocol-0.0.17-py3-none-any.whl", hash = "sha256:982a08fe152586ed10d4ff3d538c2e0b5766e5f307cdea325e10be3f2c17cae6", size = 7096, upload-time = "2026-06-12T18:39:50.973Z" }, + { url = "https://files.pythonhosted.org/packages/99/2e/d82db9eec13ad0f72e7aaad5c4bc730ab111934fdc83c85523206eb9b0a0/langchain_protocol-0.0.18-py3-none-any.whl", hash = "sha256:70b53a86fbf9cedc863555effe44da192ab02d556ddbf2cf95b8873adcf41b5a", size = 7221, upload-time = "2026-06-18T17:08:25.996Z" }, ] [[package]] name = "langgraph" -version = "1.2.5" +version = "1.2.9" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "langchain-core" }, @@ -1975,9 +1965,9 @@ dependencies = [ { name = "pydantic" }, { name = "xxhash" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/77/9d/7c9ebd17b95569122e2d2e641f535cf086c870d66bb8e59be33cdba856b3/langgraph-1.2.5.tar.gz", hash = "sha256:09a3bdec6fdb3228623fc78b6f69a1400d383f66348d0b04d0efb692022cc6ef", size = 712532, upload-time = "2026-06-12T20:30:58.498Z" } +sdist = { url = "https://files.pythonhosted.org/packages/41/4b/0d1130e26b41a99dcc88353bbe7162a1f255c4db746bd94024268e6af27b/langgraph-1.2.9.tar.gz", hash = "sha256:385f87bc1802c35af7e0aa479278ecba8582d103515eb48256cb2ddcd42d0bd4", size = 722869, upload-time = "2026-07-10T01:30:14.985Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/a2/03/187281cf61845c5a9c397ae6cd9cd73bb54b39435e5575a7b83c853e5b76/langgraph-1.2.5-py3-none-any.whl", hash = "sha256:9286bb5def82fc865959c14378fe473518dc097d586225f622f029637a2a4bb9", size = 246150, upload-time = "2026-06-12T20:30:57.018Z" }, + { url = "https://files.pythonhosted.org/packages/41/16/0b8dc48823f1326f3e0c8012a3c07a40da6f194299e2ec080df236287baf/langgraph-1.2.9-py3-none-any.whl", hash = "sha256:c2d98ad94333937922ba04148641c1da2bfe45b5b8e55d7b6dcb0bb2df809e76", size = 247473, upload-time = "2026-07-10T01:30:13.733Z" }, ] [[package]] @@ -2024,7 +2014,7 @@ wheels = [ [[package]] name = "langsmith" -version = "0.8.16" +version = "0.8.18" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "httpx" }, @@ -2038,9 +2028,9 @@ dependencies = [ { name = "xxhash" }, { name = "zstandard" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/6f/19/1ed2af9c6d5d7a148e6b3e809b0af8ce8848e1f66a0726c8223d30e5292b/langsmith-0.8.16.tar.gz", hash = "sha256:8c943f0c9185fe2a9637b5b442828b7efd823b1de28d50d14c136c79660f909b", size = 4513275, upload-time = "2026-06-15T17:41:24.413Z" } +sdist = { url = "https://files.pythonhosted.org/packages/9a/d9/a6681aa9847bbbc5ec21abe20a5e233b94e5edcfe39624db607ac7e8ccb4/langsmith-0.8.18.tar.gz", hash = "sha256:32dde9c0e67e053e0fb738921fc8ced768af7b8fa83d7a0e3fd63597cf8776dd", size = 4526988, upload-time = "2026-06-19T13:12:17.123Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/c3/13/8186a9867c67f3fef9958a1d60b45f46c1a9b5d28f67d8fd136f28ceab3f/langsmith-0.8.16-py3-none-any.whl", hash = "sha256:081e57c0175d142192683288740a796eb0eb32d9e703b4bf9133678ceefe3286", size = 500303, upload-time = "2026-06-15T17:41:22.33Z" }, + { url = "https://files.pythonhosted.org/packages/03/70/0e0cc80a3b064c8d6c8d697c3125ed86e39d5a7393ec6dc8b07cb1cf13c4/langsmith-0.8.18-py3-none-any.whl", hash = "sha256:3940183349993faef48e6c7d08e4822ee9cefd906b362d0e3c2d650314d2f282", size = 508108, upload-time = "2026-06-19T13:12:15.348Z" }, ] [[package]] @@ -2090,7 +2080,7 @@ wheels = [ [[package]] name = "litellm" -version = "1.89.0" +version = "1.91.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "aiohttp" }, @@ -2106,9 +2096,9 @@ dependencies = [ { name = "tiktoken" }, { name = "tokenizers" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/86/4b/15d4cb75f054933c1f19bcfd5683e139cdf792099b995ae55916b26094dc/litellm-1.89.0.tar.gz", hash = "sha256:eb1910a23497044b4375a0500c65f4c60d291a575d7b679c7566a5df9b9a5fcb", size = 14062606, upload-time = "2026-06-13T23:45:53.723Z" } +sdist = { url = "https://files.pythonhosted.org/packages/86/1e/90cfeada42170986a290feebaca0a90923b3c310cddeb0f8690abd239ad4/litellm-1.91.0.tar.gz", hash = "sha256:4fd469fe7356ba8fcc86f4efdf332e3426b760962ab12331fdaf1a01aeec065f", size = 14872290, upload-time = "2026-07-04T19:18:28.466Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/eb/86/49cf94af8c51cacc15fd9bff1e6f9de1fb07ab10b8bb09961675ab389af4/litellm-1.89.0-py3-none-any.whl", hash = "sha256:63b33e2de386ab2a83fed7ed852c755e59d461a21b16c79fc17993f1b8c3d154", size = 15475805, upload-time = "2026-06-13T23:45:46.037Z" }, + { url = "https://files.pythonhosted.org/packages/a4/15/81fc2d162513803fe08b359c2e2a98f7a33195034fb94b005e263e272c6b/litellm-1.91.0-py3-none-any.whl", hash = "sha256:c3eb52dd2c6a5779e9efd67350f3640f9055d9c05d4b572fc1dd01a217e562ad", size = 16669331, upload-time = "2026-07-04T19:18:25.203Z" }, ] [[package]] @@ -2134,15 +2124,15 @@ wheels = [ [[package]] name = "markdownify" -version = "1.2.2" +version = "1.2.3" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "beautifulsoup4" }, { name = "six" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/3f/bc/c8c8eea5335341306b0fa7e1cb33c5e1c8d24ef70ddd684da65f41c49c92/markdownify-1.2.2.tar.gz", hash = "sha256:b274f1b5943180b031b699b199cbaeb1e2ac938b75851849a31fd0c3d6603d09", size = 18816, upload-time = "2025-11-16T19:21:18.565Z" } +sdist = { url = "https://files.pythonhosted.org/packages/92/ab/d1297139c0e2ceb151ae564c8c4f57ac0155d8f1f8b4cbd5d6523c82ea36/markdownify-1.2.3.tar.gz", hash = "sha256:1a176f05522c8a2cb1dd3ab9d307dcdadbed5c26ae717855bfc42b3b6d38d937", size = 18852, upload-time = "2026-06-30T20:27:39.06Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/43/ce/f1e3e9d959db134cedf06825fae8d5b294bd368aacdd0831a3975b7c4d55/markdownify-1.2.2-py3-none-any.whl", hash = "sha256:3f02d3cc52714084d6e589f70397b6fc9f2f3a8531481bf35e8cc39f975e186a", size = 15724, upload-time = "2025-11-16T19:21:17.622Z" }, + { url = "https://files.pythonhosted.org/packages/04/10/fa543d484e8b1199243fe20eedd02cc5af050edebce98a7293a5773df592/markdownify-1.2.3-py3-none-any.whl", hash = "sha256:a189a0bedfd14009030fde5f85bb6f77c56897cb839b5c25315dd7d4e3e290ba", size = 15732, upload-time = "2026-06-30T20:27:38.094Z" }, ] [[package]] @@ -2232,31 +2222,31 @@ wheels = [ [[package]] name = "maturin" -version = "1.14.0" +version = "1.14.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "tomli", marker = "python_full_version < '3.11'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/a7/d0/b7c8b7778cc44df3efbc96eb23acaa995e06ea1a60eb9b02f29858fcbd08/maturin-1.14.0.tar.gz", hash = "sha256:f7f82a6aca4a6c402bf00b99200be199d4874d04b9b9e74e825726a3478bba7f", size = 367010, upload-time = "2026-06-12T00:13:30.811Z" } +sdist = { url = "https://files.pythonhosted.org/packages/e7/b3/addd877f871fb1860d46d3a4f206ecb10b946c85846805e6367631926fd3/maturin-1.14.1.tar.gz", hash = "sha256:9d6577a62cd08e0ceba7a0db06fb098e0c9b1b3429bad747a4f3a18215a1b3df", size = 369637, upload-time = "2026-06-19T05:19:49.774Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/88/51/49367dcd8f6ec139e69ef0c695c8ff5075223673382101812b4affa53216/maturin-1.14.0-py3-none-linux_armv6l.whl", hash = "sha256:019ea3ec7e71f4c9759a367d4d21022ed5a3a621a2ce123abf3fb114ab3711ca", size = 10204135, upload-time = "2026-06-12T00:13:34.308Z" }, - { url = "https://files.pythonhosted.org/packages/dd/2a/487ce56c838d25e0ce64350e75ec4e3dc89544c0a6233221c229d6aa1a84/maturin-1.14.0-py3-none-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:6948a10f5f3470b791f79319be51debdd8bfd1778b36f2409f98e1314bc3859b", size = 19736800, upload-time = "2026-06-12T00:13:40.456Z" }, - { url = "https://files.pythonhosted.org/packages/a8/a5/12f2efc18f419edce3282a93629cba16278bb502135dac95cd04ef7c2eae/maturin-1.14.0-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:1506e86b1e273a98074a62e281b13f27ac96f8cdef85f7f98d3e3589a9387a23", size = 10201144, upload-time = "2026-06-12T00:13:26.842Z" }, - { url = "https://files.pythonhosted.org/packages/bf/95/3789e72273fd8bc80c33a11c787634b3251c4989d7a7203a92438836d4ff/maturin-1.14.0-py3-none-manylinux_2_12_i686.manylinux2010_i686.musllinux_1_1_i686.whl", hash = "sha256:df10ce4f7ba97fd3423f624f39b94c888ae3e5b470642a91918e1ccec81282fd", size = 10182394, upload-time = "2026-06-12T00:13:13.693Z" }, - { url = "https://files.pythonhosted.org/packages/40/79/15957eb4e055597f217e6310963a9c1371372e63c5b4a3e30803365addd2/maturin-1.14.0-py3-none-manylinux_2_12_x86_64.manylinux2010_x86_64.musllinux_1_1_x86_64.whl", hash = "sha256:75bcd4468a7fe597652cc2980c6bb16ce4bb8c411e3eb85dac2c4418cef0e95a", size = 10616603, upload-time = "2026-06-12T00:13:22.795Z" }, - { url = "https://files.pythonhosted.org/packages/3e/4b/d1822f88cd5e855640f0e10ee00c39b9be614c1ef2f827e9792332d94b9f/maturin-1.14.0-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.musllinux_1_1_aarch64.whl", hash = "sha256:2d123337e817f8dfe23755d6760139c01104137bb63e9e20c289c547e25ec857", size = 10075309, upload-time = "2026-06-12T00:13:38.274Z" }, - { url = "https://files.pythonhosted.org/packages/c0/82/c1b160d2163e8784489285e82a5c811fdcef3e0704e35b34c1cfe1828de3/maturin-1.14.0-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.musllinux_1_1_armv7l.whl", hash = "sha256:107f84110d890090a01bb1ecd01761fdfae925c23c659ba492c9b83dd179eab4", size = 10024058, upload-time = "2026-06-12T00:13:16.49Z" }, - { url = "https://files.pythonhosted.org/packages/0c/e8/88a9d1872997d4535af10ebe79f550e834880bf613cf8e50b50d2d938e3b/maturin-1.14.0-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.musllinux_1_1_ppc64le.whl", hash = "sha256:9a84277aa907961cd47ad26fef1539e79efa30611972eaf7499606e773e991b2", size = 13302073, upload-time = "2026-06-12T00:13:29.027Z" }, - { url = "https://files.pythonhosted.org/packages/4a/13/3f6d28bb7b744558b9bc78c995c1855d7e5ff21ad475f46d9de5c3dab039/maturin-1.14.0-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:095714b2a904927e3c868a1c5d078257ff0443c5049f7623777352966768306e", size = 10863616, upload-time = "2026-06-12T00:13:32.191Z" }, - { url = "https://files.pythonhosted.org/packages/24/06/39352d2b402efa3a7dd01d4ed197b301ea35eec10208ba2b8c649101f4df/maturin-1.14.0-py3-none-manylinux_2_31_riscv64.musllinux_1_1_riscv64.whl", hash = "sha256:20229d332f87166b930e4ca07cdbee8a1726f2eea87a337610aa25bba3ddf4b4", size = 10399943, upload-time = "2026-06-12T00:13:36.273Z" }, - { url = "https://files.pythonhosted.org/packages/58/77/641504541336240fef3836b2d15a785eaeb33c941fb118513c267dd70840/maturin-1.14.0-py3-none-win32.whl", hash = "sha256:4ba1e3c3f33609f461d587b7549104c81a15fd6d42ba63a73cea9376a1e9876e", size = 8905117, upload-time = "2026-06-12T00:13:18.38Z" }, - { url = "https://files.pythonhosted.org/packages/02/4a/ca247a0c43069b2f48cf783c5b13c3a9eb92c8f596dc7fbdb9f75fea4414/maturin-1.14.0-py3-none-win_amd64.whl", hash = "sha256:cb09a313f097adeb4dda0082277871a28d1bd26615dbadab42e6234b6df6fe69", size = 10309099, upload-time = "2026-06-12T00:13:20.523Z" }, - { url = "https://files.pythonhosted.org/packages/8b/a4/f14a3f6086cc3caaa90d12e832e4aa41de771c310041959f0d35dd4efe17/maturin-1.14.0-py3-none-win_arm64.whl", hash = "sha256:8c1a8188195f5b6ce1aab99ae2d92e342900298f901456b43ca028947fd3b288", size = 9719100, upload-time = "2026-06-12T00:13:24.741Z" }, + { url = "https://files.pythonhosted.org/packages/f4/f0/97c5a5bd9c71653a066c0976a484eaaae50b9369557838a4176b7b0bdaa5/maturin-1.14.1-py3-none-linux_armv6l.whl", hash = "sha256:522292398945442cdafa9daeb2271b2340fbde57027b818f923f88eab04174f8", size = 10207496, upload-time = "2026-06-19T05:19:09.321Z" }, + { url = "https://files.pythonhosted.org/packages/fe/83/294bca639b0e052f1e2f65199b3db258780c7d4e31408b934c9c974a1379/maturin-1.14.1-py3-none-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:ffe5ad71f21d1e6603c4dd75f7fee34adf5ed5ebcebb692886549888ebb329ed", size = 19680113, upload-time = "2026-06-19T05:19:13.43Z" }, + { url = "https://files.pythonhosted.org/packages/43/b6/79c881410a3b1c187f7eb3d407aecae646c6a4433d630d72200359015e83/maturin-1.14.1-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:f3306078070c1508fd715b9116070cbcaff5959024272a9f1e6f5cb29768b86c", size = 10169205, upload-time = "2026-06-19T05:19:16.615Z" }, + { url = "https://files.pythonhosted.org/packages/93/9d/44b6f26dcb7f7a04c5501ac2dbb6ca1490150682baa525ca5860504f9eab/maturin-1.14.1-py3-none-manylinux_2_12_i686.manylinux2010_i686.musllinux_1_1_i686.whl", hash = "sha256:cd457cd88961156e26379e1155bd287cc0ec1c8b2f1582b0660fb31b87c8842d", size = 10188098, upload-time = "2026-06-19T05:19:19.736Z" }, + { url = "https://files.pythonhosted.org/packages/1a/bd/9c0d5d6983905ce2c9edaa073a7e89355a9cf7f396988e05d32f1c37785d/maturin-1.14.1-py3-none-manylinux_2_12_x86_64.manylinux2010_x86_64.musllinux_1_1_x86_64.whl", hash = "sha256:dfc54ae32e6fcb18302193ab9a30b0b25eefffba994ae13238974805533ef75e", size = 10627576, upload-time = "2026-06-19T05:19:22.713Z" }, + { url = "https://files.pythonhosted.org/packages/e5/33/b096412bd6a7cb399652b260666f901adf88a687181a6dbd6a3f89f0a94e/maturin-1.14.1-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.musllinux_1_1_aarch64.whl", hash = "sha256:a131d912b5267e640bc96d70f4914e10590aed64082ec9abacba7cea52004224", size = 10085181, upload-time = "2026-06-19T05:19:25.69Z" }, + { url = "https://files.pythonhosted.org/packages/56/8d/08c3bf469c38a23c9e6c877e338193001eb604d010fedc08341974e38528/maturin-1.14.1-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.musllinux_1_1_armv7l.whl", hash = "sha256:be18fc568fb76884c0205456336892a75105ec398e6b667cd777c6268bd06d69", size = 10026363, upload-time = "2026-06-19T05:19:28.904Z" }, + { url = "https://files.pythonhosted.org/packages/3a/a4/c4d1a92839f8745ab4aab988a7db884a79d6d710bd3b286fcf9316dece1a/maturin-1.14.1-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.musllinux_1_1_ppc64le.whl", hash = "sha256:994a0c8ba3ad8a92b3a9ee1b02645d200d610216b15cff5102b0fe65e8e08666", size = 13321347, upload-time = "2026-06-19T05:19:32.411Z" }, + { url = "https://files.pythonhosted.org/packages/b3/fa/170f04624d03fd07d2a8b1b67de83a127af93aef9eaa425839553347297b/maturin-1.14.1-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:be80866363e605d137991b491a741a84cde9ae350183c4c85f49690ca9aaaa65", size = 10877609, upload-time = "2026-06-19T05:19:35.448Z" }, + { url = "https://files.pythonhosted.org/packages/61/ad/1ae2e1d0ded282bf2c55ac13f0811d87deb425e200ae64a15785675dede9/maturin-1.14.1-py3-none-manylinux_2_31_riscv64.musllinux_1_1_riscv64.whl", hash = "sha256:5282dffd4b539d2be245f4e5b1a5ab6bc1033b58f4a4872f5833f9d43c954aa4", size = 10417316, upload-time = "2026-06-19T05:19:38.28Z" }, + { url = "https://files.pythonhosted.org/packages/fb/27/bf677183920718da49cd7982d6a3ffc440aad8919329f571d189f81b7bdf/maturin-1.14.1-py3-none-win32.whl", hash = "sha256:1a04de0a20188f95c721b5702eed18140bdcccb28c386797093eca3f62f4d4e0", size = 8931293, upload-time = "2026-06-19T05:19:41.183Z" }, + { url = "https://files.pythonhosted.org/packages/63/4b/585adeb9167b08d3cdff0032a938b0e72655c92003df4f52c3f696a1bcc2/maturin-1.14.1-py3-none-win_amd64.whl", hash = "sha256:3c9f94640ecc4895e94abaf834a0684430032c865b2748a36c12461fd9252fdd", size = 10314067, upload-time = "2026-06-19T05:19:44.389Z" }, + { url = "https://files.pythonhosted.org/packages/51/d4/dac8c0720ae246be1700afb6fbdbbea20fe35b13f6570b2f70faa005df77/maturin-1.14.1-py3-none-win_arm64.whl", hash = "sha256:15cea8fcb3ba47dd636f50092bb34baea8b04ac777392f23e6bf8a9a61efb894", size = 9718943, upload-time = "2026-06-19T05:19:47.49Z" }, ] [[package]] name = "mcp" -version = "1.27.2" +version = "1.28.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "anyio" }, @@ -2274,9 +2264,9 @@ dependencies = [ { name = "typing-inspection" }, { name = "uvicorn", marker = "sys_platform != 'emscripten'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/27/3c/347cf965d313f5d41764e7d46bea6ffe7d9ef13b983cc429b0340962a082/mcp-1.27.2.tar.gz", hash = "sha256:8e02db104096d1c25b28e64bde29a5c32b31bc241710213e12fd4d84985bdfef", size = 621116, upload-time = "2026-05-29T17:16:04.039Z" } +sdist = { url = "https://files.pythonhosted.org/packages/6e/77/9450b8f251a13affb6281997d0523c4615f8a8b35d0b21ff30db3a5aac9d/mcp-1.28.1.tar.gz", hash = "sha256:d51e36a5f5644faea4f85ea649bfffa6bc6c26770d42798ad6a3de3d2ba69683", size = 638501, upload-time = "2026-06-26T12:57:29.093Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/c9/11/252c6f971dc4f16af1d98a1c469d8ba523aab00d1bb76b4d3bc1ff32eacc/mcp-1.27.2-py3-none-any.whl", hash = "sha256:d6ff5160c6ca65d93013626efb3fc249de683c30b2d8570755ceddd490344de5", size = 220498, upload-time = "2026-05-29T17:16:02.442Z" }, + { url = "https://files.pythonhosted.org/packages/e2/5e/d118fce19f87a2e7d8101c35c8ae0ec289098a4df0ff244cec23e415aca0/mcp-1.28.1-py3-none-any.whl", hash = "sha256:2726bca5e7193f61c5dde8b12500a6de2d9acf6d1a1c0be9e8c2e706437991df", size = 222620, upload-time = "2026-06-26T12:57:27.218Z" }, ] [[package]] @@ -2348,75 +2338,75 @@ wheels = [ [[package]] name = "msgpack" -version = "1.2.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/92/23/6139781ca7aadf656fa8e384fa84693ffb13f299e6931b6526427fe5e297/msgpack-1.2.0.tar.gz", hash = "sha256:8e17af38197bf58e7e819041678f6178f4491493f5b8c8580414f40f7c2c3c41", size = 183017, upload-time = "2026-06-11T04:16:10.775Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/0f/52/fed22bca455ff3ed28c0ee0d1117398b7cb3ce440270050e85b09240fa8d/msgpack-1.2.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:ed8c9495a0f12d17a2b4b69e23f895b88f26aabe40911c86594d3fbddecfff08", size = 82473, upload-time = "2026-06-11T04:14:38.484Z" }, - { url = "https://files.pythonhosted.org/packages/3b/09/0b54d386024a9fa2073135212c11d1e83b059d98459d943d5a82ba9dcdc9/msgpack-1.2.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:d7384859c90b45a28a4b31aa50b49cca84504c9f27df459cea6e072627650dcb", size = 82150, upload-time = "2026-06-11T04:14:39.985Z" }, - { url = "https://files.pythonhosted.org/packages/44/ba/c6310a6f37e9bf9279b492640ec425e6f6e68a94e4cac4782ab518b05d64/msgpack-1.2.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:63b35e8e65f04ff7ad5c9c70885da587c74f51e4b4eb3db624eac6d250e8cf59", size = 398355, upload-time = "2026-06-11T04:14:41.493Z" }, - { url = "https://files.pythonhosted.org/packages/d8/1b/f4bad0e9dea608b14d36065c44e347e4b10c0392f92cca441496cc0598ef/msgpack-1.2.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9004c5a02acd3eca4e15e1ae7b461c32e3711105a28b1ad78be2f6facff4c523", size = 405162, upload-time = "2026-06-11T04:14:42.957Z" }, - { url = "https://files.pythonhosted.org/packages/63/34/4653bc7f426bd6ce9803f75133aa362232639e5adb8c6b99550107c71ed5/msgpack-1.2.0-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:7e2032dacb0a973fcbf7bd088415a369dae31c5af40e199d234806be22e86765", size = 372720, upload-time = "2026-06-11T04:14:44.532Z" }, - { url = "https://files.pythonhosted.org/packages/13/3c/8c607e10db2225af52107ffa918280483248363819fecb4437a35a1f4ae2/msgpack-1.2.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:c1feb100651fbe4b39826207cb20af065dfbfbfa43b1bafd7eaa2252abf7acfd", size = 390946, upload-time = "2026-06-11T04:14:46.054Z" }, - { url = "https://files.pythonhosted.org/packages/96/05/c4cb5fb30569cff4b4c7be4574adddb0faf7faaf3049bbab000b6f07da5b/msgpack-1.2.0-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:82487709d4c597d252311a65370220675fb1cc859e7da9269a3060c03ac02cf6", size = 374062, upload-time = "2026-06-11T04:14:47.817Z" }, - { url = "https://files.pythonhosted.org/packages/40/d7/b51b11e58277e6b678ba5a2f6608f88fdb0778973391a39d7f1a385f5bde/msgpack-1.2.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:0268c67a74f5f913f545a0fdbbfaa3f6ebcf23b4c3209bb99704a2ea87e13f90", size = 405458, upload-time = "2026-06-11T04:14:49.618Z" }, - { url = "https://files.pythonhosted.org/packages/2c/0e/9eca2961be302a6fc77a3fcb15faec749e325c9f0a8fe9c4c4576fc2cad5/msgpack-1.2.0-cp310-cp310-win32.whl", hash = "sha256:7df87173b0e13ddd134919731f13525dbbf75204145597decf1cb86887ebb492", size = 64010, upload-time = "2026-06-11T04:14:51.071Z" }, - { url = "https://files.pythonhosted.org/packages/e7/e3/55b14ae13ed056ed35364ff71144c6a12af25227c20093045a945d08273a/msgpack-1.2.0-cp310-cp310-win_amd64.whl", hash = "sha256:6371edb47788fbfd8a22016f9a97b5616dd9849bc50abcbb8e82d38f71efa096", size = 69863, upload-time = "2026-06-11T04:14:52.376Z" }, - { url = "https://files.pythonhosted.org/packages/ee/23/35de3182a647fcc84ab304160169edfa5dac7bbd8913fbed0a505ddc0d55/msgpack-1.2.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:ec35cd3f127f50806aa10c3f74bf27b749f13ddf1d2217964ada8f38042d1653", size = 82368, upload-time = "2026-06-11T04:14:53.57Z" }, - { url = "https://files.pythonhosted.org/packages/aa/79/8d9bfdab933b1c7a02aba9518605a81aa30d38e9efd4915ec1a6b2d55778/msgpack-1.2.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:317eb298297121bfad9173d748124a04a36af27b6ac39c2bbc1db1ce57608dcf", size = 82095, upload-time = "2026-06-11T04:14:54.784Z" }, - { url = "https://files.pythonhosted.org/packages/d2/e1/b5accbc1354edbcee107fb35ec247db0547e91c3f90e4fabdeaee500a5a6/msgpack-1.2.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:50fe6434de89073273026dd032a62e8b63f8857a261d7a2df5b07c9e72f3a8f7", size = 413818, upload-time = "2026-06-11T04:14:56.1Z" }, - { url = "https://files.pythonhosted.org/packages/82/31/1141cbbf7118d525834f20dcd614d1b85f1f2ffd33bc2a5ce710e6dd2516/msgpack-1.2.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:106c6d333ff3d4eda075b7d4b9695d1752c5bcc635e40d0dbaf4e276c9ed80e1", size = 423790, upload-time = "2026-06-11T04:14:57.509Z" }, - { url = "https://files.pythonhosted.org/packages/04/e7/9582f2bd4d7546139fe297740de49bd1f7ef2d195eb0bb9fa5efeee88158/msgpack-1.2.0-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:67055a611e871cb1bd0acb732f2e9f64ca8155ca0bba1d0a5bb362e7209e5541", size = 387521, upload-time = "2026-06-11T04:14:59.08Z" }, - { url = "https://files.pythonhosted.org/packages/7d/12/5aadd08ff068bfd42e2ac0be6a20aa9819965df8622e87c1f0c6119c1c22/msgpack-1.2.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:ceec7f8e633d5a4b4a32b0416bef90ee3cd1017ea36247f705e523072e576119", size = 406324, upload-time = "2026-06-11T04:15:00.686Z" }, - { url = "https://files.pythonhosted.org/packages/39/ee/3041564f0cc4c2fe7c53315aec0edf3d84807fc9b9ea714e6ac07dbdb1db/msgpack-1.2.0-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:7ec5851160a3c2c0f77d68ddec620318cd8e7d88d94f9c058190e8ce0dfa1d31", size = 384242, upload-time = "2026-06-11T04:15:02.121Z" }, - { url = "https://files.pythonhosted.org/packages/5d/d4/de94b3dbc266229f4c2ce84485eeb221220351b7f1931029e875995bb232/msgpack-1.2.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:dd7140f7b09dbe1984a0dff3189375d840247e3e4cf4ac45c5a499b3b599c8d2", size = 420392, upload-time = "2026-06-11T04:15:03.692Z" }, - { url = "https://files.pythonhosted.org/packages/f7/5d/c4a3fde69a292eecb202caaa87c29df7728644a65118614b821bcaddc05a/msgpack-1.2.0-cp311-cp311-win32.whl", hash = "sha256:cbfd54018d386da0951c7a2be13de0f58559d251313e613b2155e52ed1cbd8f1", size = 63976, upload-time = "2026-06-11T04:15:05.355Z" }, - { url = "https://files.pythonhosted.org/packages/18/fa/df47f83115375e7717c985265a30f3ba096c5331518e28fb647b55c46d31/msgpack-1.2.0-cp311-cp311-win_amd64.whl", hash = "sha256:653373c4614c31463ba486a67776e4bb396af289921bd5353e209534b71467fa", size = 70273, upload-time = "2026-06-11T04:15:06.529Z" }, - { url = "https://files.pythonhosted.org/packages/54/d1/ffd02e54c064aa73b6b53aa08171f92dc406727077ff275d7050c6aca28a/msgpack-1.2.0-cp311-cp311-win_arm64.whl", hash = "sha256:7a260aea1e5e7d6c7f1d9284c7360d29021627b61dc4dd7df144b81210810537", size = 64783, upload-time = "2026-06-11T04:15:07.677Z" }, - { url = "https://files.pythonhosted.org/packages/44/07/dcb13f37e670257c8d0e944f116c799c34ac6968ecb48c83619f7e91d8b5/msgpack-1.2.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:e2d6047ccd11a12c96a69f2bfe026471abef67334c3d0494a93e5310e45140a2", size = 82888, upload-time = "2026-06-11T04:15:08.992Z" }, - { url = "https://files.pythonhosted.org/packages/84/5f/6643b2a6a36ca4bc73c7674831be1d4d581cceecc7eb019dba1915951739/msgpack-1.2.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:0347e3ac0dfee99086d3b68fe959da3f5f657c0019ddbaeaaa259a85f8603422", size = 82223, upload-time = "2026-06-11T04:15:10.182Z" }, - { url = "https://files.pythonhosted.org/packages/2c/c8/9e1668b9897358e5ab39a18142e38be3cf15807e643757782da9f4a53cb3/msgpack-1.2.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:25552ff1f2ff3dc8333e27eabb94f702da5929ed0e07969688194a3e9f12e151", size = 409700, upload-time = "2026-06-11T04:15:11.441Z" }, - { url = "https://files.pythonhosted.org/packages/38/ed/b7728573156d70b6b094233b0f38d876fc37340826cf852347ec2c7ca8ca/msgpack-1.2.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a0d94420d9d52c56568159a69200af7e45eadb29615fa9d09fada140de1c38c7", size = 420090, upload-time = "2026-06-11T04:15:12.868Z" }, - { url = "https://files.pythonhosted.org/packages/3f/f7/5ea755a89868c04f9cdf6d96d2d99da4b3d198af10e76a6082dd0fceccc0/msgpack-1.2.0-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:d16e1f2db4a9eebc07b7cc91898d71e710f2eed8358711a605fee802caff8923", size = 378538, upload-time = "2026-06-11T04:15:14.511Z" }, - { url = "https://files.pythonhosted.org/packages/80/2d/126e59332a439c94ffd682c38ca0102b23480e2784b3dac48d8959b0bbac/msgpack-1.2.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:e9cb2e700e85f1e27bbb5c9de6cc1c9a4bc5ac64d5404bdcbcb37a0dc7a947a3", size = 399468, upload-time = "2026-06-11T04:15:16.133Z" }, - { url = "https://files.pythonhosted.org/packages/da/f9/7abcef683a0ad2e5ab3a4940344aad9f20cdf1f42057ecb0982cf55085d6/msgpack-1.2.0-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:717d0b166dd176a5f786aeafff081f6439680acf5af193eb63e6266c12b04d3d", size = 374212, upload-time = "2026-06-11T04:15:17.536Z" }, - { url = "https://files.pythonhosted.org/packages/27/23/2d62cf0e971678e96f8a3cfa9bd77fb719ddb98da73790f63c53fd847ad8/msgpack-1.2.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:e87c7a21654d18111eb1a89bd5c42baba42e61887365d9e89585e112b4203f9e", size = 414361, upload-time = "2026-06-11T04:15:18.99Z" }, - { url = "https://files.pythonhosted.org/packages/32/fb/f5c153f614037aaf802d291a4653ba1bb731f56feacba886f7c21c109e56/msgpack-1.2.0-cp312-cp312-win32.whl", hash = "sha256:967e0c891f5f23ab65762f2e5dc95922759c79f1ef99ef4c7e1fdd863e0d0af9", size = 64389, upload-time = "2026-06-11T04:15:20.237Z" }, - { url = "https://files.pythonhosted.org/packages/90/af/8aafce6e5544b43b84cb670aca40c8bea7eb5ae8f42bfcbdc7098739987a/msgpack-1.2.0-cp312-cp312-win_amd64.whl", hash = "sha256:6c23e33cee28dcffa112ae205661da4636fd7b06bd9ad1559a890623b92d060b", size = 71185, upload-time = "2026-06-11T04:15:21.51Z" }, - { url = "https://files.pythonhosted.org/packages/ba/08/9cc94be1fc1fe3d1379d439326259aef0344274f64623a8138feb54dff68/msgpack-1.2.0-cp312-cp312-win_arm64.whl", hash = "sha256:6eeb771571f63f68045433b1a35c0256b946f31ed62f006997e40b8ad8b735af", size = 64481, upload-time = "2026-06-11T04:15:22.639Z" }, - { url = "https://files.pythonhosted.org/packages/7d/26/2902c6946ab5c8fe1e46e40842dfc32b8824464ad5cd4725364fd83f7a58/msgpack-1.2.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:3a1d30df1f302f2b7a7404afbac2ab76d510036c34cf34dffb01f704a7288e45", size = 82621, upload-time = "2026-06-11T04:15:23.844Z" }, - { url = "https://files.pythonhosted.org/packages/c9/59/7e6b812629d2f919e586041bffc130e1af32079f71bb20699eed54ed6d92/msgpack-1.2.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:581e317112260d8ca488d490cad9290a5682276f309c41c7de237a85ed8799c8", size = 81866, upload-time = "2026-06-11T04:15:25.032Z" }, - { url = "https://files.pythonhosted.org/packages/31/13/8c291196e60aafdbae38f482205d79432297749ac5d412fe638154fb6f1d/msgpack-1.2.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c6827d12eacc16873eba62408a1b7bbe8ecfb4a8f7ed78a631ae9bae6ad43cf2", size = 405618, upload-time = "2026-06-11T04:15:26.235Z" }, - { url = "https://files.pythonhosted.org/packages/fb/63/68f5d0ea81e167db5f59ddb94dc6f837667062113feff1c73fabf8907061/msgpack-1.2.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a186027e4279efa4c8bf06ce30605498d7d0d3af0fba0b9799dce85a3fd4a93c", size = 416468, upload-time = "2026-06-11T04:15:27.732Z" }, - { url = "https://files.pythonhosted.org/packages/73/58/567dddf5c5a2790f673bcd7d80c83466d68e5ee9a9674ebca3db8101c0c8/msgpack-1.2.0-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:a96142c14a11cf1a509e8b9aaf72858a3b742b7613e095ce646913e88ce7bd99", size = 374464, upload-time = "2026-06-11T04:15:29.286Z" }, - { url = "https://files.pythonhosted.org/packages/0d/30/0c2342fc9092e4498045f5f60bca6ccbe4f4d87789778c2300e6fd6efe82/msgpack-1.2.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:50c220579b68a6085b95408b2eaa486b259520f55d8e363ddc9b5d7ba5a6ac6d", size = 395879, upload-time = "2026-06-11T04:15:30.973Z" }, - { url = "https://files.pythonhosted.org/packages/b9/11/9565b29b58ce3c33e177b490478b7aaeb8f726ecaaeda26d815893c1db5a/msgpack-1.2.0-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:4dcb9d12ab100ecacdfaaf37a3d72fe8392eacc7054afc1916b12d1b747c8446", size = 371749, upload-time = "2026-06-11T04:15:32.418Z" }, - { url = "https://files.pythonhosted.org/packages/f2/da/7bade19d60b73e2ef73fb76aaf4504c112a70cb760951b7202a0c64b5111/msgpack-1.2.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:a804727188ab0ebb237fadb303b743f04925a69d8c3247292d1e33e679767c15", size = 410416, upload-time = "2026-06-11T04:15:34.053Z" }, - { url = "https://files.pythonhosted.org/packages/6d/14/c0c619571c02432208a5977a8dbdd3fc65fe1369f8226ca4b6d08cca87d8/msgpack-1.2.0-cp313-cp313-win32.whl", hash = "sha256:1a1ac6ae1fe23298f79380e7b144c8a454e5d05616b0096584f353ba2d750114", size = 64357, upload-time = "2026-06-11T04:15:35.535Z" }, - { url = "https://files.pythonhosted.org/packages/50/a5/de06718460909aa965737fec4cfe8a15dedc6544a8c55feeb6956fa0d6e3/msgpack-1.2.0-cp313-cp313-win_amd64.whl", hash = "sha256:1c3c80949d79578f9dc85fd9fb91edfe6694e8a729cd5744634d59d8455fdde3", size = 71057, upload-time = "2026-06-11T04:15:36.83Z" }, - { url = "https://files.pythonhosted.org/packages/c7/52/73446b0141c94a856e22b787c56709c0815fc34f185326577e15b26d8cfe/msgpack-1.2.0-cp313-cp313-win_arm64.whl", hash = "sha256:fcf8f76fa587c2395fd0057c7232dbf071241f9ad280b235adb7ab585289989e", size = 64490, upload-time = "2026-06-11T04:15:38.001Z" }, - { url = "https://files.pythonhosted.org/packages/35/3d/a7e3cdafa8c0cf36c81e2fa848ec4d30cf089459af45b390ad03f9ce6f49/msgpack-1.2.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:f854fa1a8b55d75d82ef9a905d9cdbeffdf7897c088f6020bd221867da5e56a5", size = 83032, upload-time = "2026-06-11T04:15:39.38Z" }, - { url = "https://files.pythonhosted.org/packages/ca/aa/53ddfba0e347cc4b484e95f629c5850b9e800ca8390c91ffc604407acf87/msgpack-1.2.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:e90df581f80f53b372d5d9d9349078d729851a3a0d0bd74f53ccb598d01e45b8", size = 82600, upload-time = "2026-06-11T04:15:40.609Z" }, - { url = "https://files.pythonhosted.org/packages/59/fd/e64c2c776e6dbad0af3c963fe0c0dd1ee1ba09efac478b233ab1db41868f/msgpack-1.2.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b276ed50d8ac75d1f134a433ae79af8557d0fa25ee5b4737da533dfc2ce382e8", size = 404342, upload-time = "2026-06-11T04:15:41.87Z" }, - { url = "https://files.pythonhosted.org/packages/1b/60/fb9a08e6ccba882dfd370a5837fe3a07572938fdfe954f0f17fdf3e574b9/msgpack-1.2.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:544d972459c92aa32e63b800d07c2d9cf2734a3be29cee3a0b478a622850e9f5", size = 412351, upload-time = "2026-06-11T04:15:43.253Z" }, - { url = "https://files.pythonhosted.org/packages/37/4d/df5c575c274fedc68ac9c6c61d045161899efad2afcdc25138efa7edde69/msgpack-1.2.0-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:a070147cc2cf6b8a891734e0f5c8fe8f70ed8739ab30ba140b058005a6e86af4", size = 373331, upload-time = "2026-06-11T04:15:44.754Z" }, - { url = "https://files.pythonhosted.org/packages/7d/a4/c8b98f8191e985ed2003d87664ce3c95cca41db5d0cf6bf4f54327d32ec8/msgpack-1.2.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:7685e23b0f51745a751629c31713fbefdef8896b31b2bb38299dfa4ae6c0740c", size = 394654, upload-time = "2026-06-11T04:15:46.423Z" }, - { url = "https://files.pythonhosted.org/packages/d4/49/76f036720a602ea24428cfec5ec806f2487c0380b1bff0a2aa3094e15f87/msgpack-1.2.0-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:b9204daeee8d91a7ae5acf2d2a8e3983be9a3025f38aa21bfaefbd7eea84a7dc", size = 370624, upload-time = "2026-06-11T04:15:48.062Z" }, - { url = "https://files.pythonhosted.org/packages/9f/38/40af3d29232833705a43b0fce0d07425cc280a7b92ab2b29932425b40df4/msgpack-1.2.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:bfc057248609742ebbabf6bcd27fea4fd99c4980584e613c168c9b002318298f", size = 408038, upload-time = "2026-06-11T04:15:49.669Z" }, - { url = "https://files.pythonhosted.org/packages/30/b2/f140ca450524dff4d8d0eb81eb9ed75f8f3e0b1f12e49c5b01617cfa0b1c/msgpack-1.2.0-cp314-cp314-win32.whl", hash = "sha256:a3faa7edf2388337ae849239878e92f0298b4dab4488e4f1834062f9d0c410c9", size = 65823, upload-time = "2026-06-11T04:15:51.062Z" }, - { url = "https://files.pythonhosted.org/packages/4d/13/6517bf966b841c7675ded30701a068ce141f3e698a27aaa35c702d8e078b/msgpack-1.2.0-cp314-cp314-win_amd64.whl", hash = "sha256:1a3effc392a57744e4681e55d05f97d5ee7b598747d718340a9b4b8a970c40e1", size = 72484, upload-time = "2026-06-11T04:15:52.289Z" }, - { url = "https://files.pythonhosted.org/packages/45/8c/1d948420fdaa24de4efdb8012a6a5bebe09c82ee002b8c2ca745e9917f1f/msgpack-1.2.0-cp314-cp314-win_arm64.whl", hash = "sha256:56a318f7df6bec7b40928d6b0519961f20a510d8baabf6baa393a70444588f0a", size = 66657, upload-time = "2026-06-11T04:15:53.583Z" }, - { url = "https://files.pythonhosted.org/packages/39/16/1674faa1b7bddc19e79b465fd8e88e2cf4e3f7cae90723740701e8541068/msgpack-1.2.0-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:afa4a65ab2097795e771a74a3a81ea49534aaeba874eaf426a3332268e045ae6", size = 86093, upload-time = "2026-06-11T04:15:54.98Z" }, - { url = "https://files.pythonhosted.org/packages/dd/24/f241bcfdd9e96b2246289357c5a5e5a496189fd41c5844bee802c116aac7/msgpack-1.2.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:409550770632bb28daa70a11d0ed5763f7db38f40b06f7db9f11dd2794d01102", size = 86372, upload-time = "2026-06-11T04:15:56.381Z" }, - { url = "https://files.pythonhosted.org/packages/94/c9/57f8ab98a1b21808c27b6dd6029053e0a796ffbb9b371e460dbe997011a9/msgpack-1.2.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:bf47e3cd11ce044965a9736a322afdd390b31ed602d1c1b10211d1a841f1d587", size = 428207, upload-time = "2026-06-11T04:15:57.739Z" }, - { url = "https://files.pythonhosted.org/packages/17/6b/4fd4aa739f131ded751ca7167c8ee87d2aab32506ebbeea893b60b51d343/msgpack-1.2.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:204bc9f5d6e59c1718c0a4a84fc8ff71b5b4562faac257c1a68bca611ecf9b72", size = 426082, upload-time = "2026-06-11T04:15:59.356Z" }, - { url = "https://files.pythonhosted.org/packages/f9/00/db88e9a08fcd6513decaad06cbd5c168142bc3e662fb2f1aca3a563b7aa1/msgpack-1.2.0-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:610154307b27267266368bc1d1c7bb8aeb71da7be9356d403cb2442d9e6399f5", size = 378355, upload-time = "2026-06-11T04:16:00.916Z" }, - { url = "https://files.pythonhosted.org/packages/54/84/eee4dd703d7a600cf46159d621c070b0b9468cf3dbade4ea8272bf5232a4/msgpack-1.2.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:6799f157bb63e79f11e2e590cfdb28423fc18dd60c270c3914b5b4586ae36f7e", size = 410848, upload-time = "2026-06-11T04:16:02.745Z" }, - { url = "https://files.pythonhosted.org/packages/12/0a/195e2c549fd4631eb7f157d016ff15a10c4c1cf82b6d0a9b1edaef5174b1/msgpack-1.2.0-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:72bd844902cf0a5ac3af2ef742f253cd0b1e5bcd184f49b4fb9a6a1f7bf305e8", size = 376152, upload-time = "2026-06-11T04:16:04.041Z" }, - { url = "https://files.pythonhosted.org/packages/45/9b/bdd143fa79baec411dc658f5686fed680a18b36fcea5fccb6af1b8c7d832/msgpack-1.2.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:3c0bd450f78d0d81722c80da6cdbf674a856967870a9db2f6c4debc4d8b3c67c", size = 417061, upload-time = "2026-06-11T04:16:05.63Z" }, - { url = "https://files.pythonhosted.org/packages/2d/ce/011ffcd8b919f55196ec53f12ae162e21c879d95afba226894314ff62c07/msgpack-1.2.0-cp314-cp314t-win32.whl", hash = "sha256:378caf74c4c718dfc17590ce68a6d710ed398ff6fcf08237de23b77755730b55", size = 70782, upload-time = "2026-06-11T04:16:07.105Z" }, - { url = "https://files.pythonhosted.org/packages/57/a8/9b8791ca96b1be6b9f659c718271e2cb7f99f73f58aad2dd0b30f750f6c0/msgpack-1.2.0-cp314-cp314t-win_amd64.whl", hash = "sha256:553b42598165c4dd3235994fd6e4b0dfb1ce5f3fd33d94ba9609442643015f38", size = 77899, upload-time = "2026-06-11T04:16:08.353Z" }, - { url = "https://files.pythonhosted.org/packages/5b/04/3fa2dffb87bf598696b86bde7cd642d0a7590520c3fa24cd19611dfebeb7/msgpack-1.2.0-cp314-cp314t-win_arm64.whl", hash = "sha256:2825bb1da548d214ab8a810906b7dd69a10f3838b615a2cc46e5172d3cb44f6e", size = 71004, upload-time = "2026-06-11T04:16:09.556Z" }, +version = "1.2.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/31/f9/c0a1c127f9049db9155afc316952ea571720dd01833ff5e4d7e8e6352dbb/msgpack-1.2.1.tar.gz", hash = "sha256:04c721c2c7448767e9e3f2520a475663d8ee0f09c31890f6d2bd70fd636a9647", size = 183960, upload-time = "2026-06-18T16:13:52.594Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/5b/16/f70100614b69feb3ade7285f08c9c52d6cda0a5c03f3f5e2facd63acb211/msgpack-1.2.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:8c7b398c56ff125feae96c2737abfec5595f1fa0aa186df60c56040b8accb95c", size = 82926, upload-time = "2026-06-18T16:12:31.531Z" }, + { url = "https://files.pythonhosted.org/packages/e4/3c/08ecd5cdfe4e2de43aec79062028ad0f7b2d9b1fea5430068c198ba570da/msgpack-1.2.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:1548006a91aa93c5da81f3bdcebc1a0d10cea2d25969754fbe848da622b2b895", size = 82730, upload-time = "2026-06-18T16:12:32.894Z" }, + { url = "https://files.pythonhosted.org/packages/19/9f/a70c9cb1a04ecc134005149367dcfe35d167284e8f65035a1e4156ad17b5/msgpack-1.2.1-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1dabedcd0f23559f3596428c6589c1cd8c6eaed3a0d720795b07b0225d769203", size = 400729, upload-time = "2026-06-18T16:12:34.052Z" }, + { url = "https://files.pythonhosted.org/packages/fa/7f/5ce020168cf0439041526e95aa068c722c016aee21624e331aeabeee2e8e/msgpack-1.2.1-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:83efa1c898e0fc5380fc0cabbf75164c52e3b5cbb45973710d75821928380c73", size = 407625, upload-time = "2026-06-18T16:12:35.239Z" }, + { url = "https://files.pythonhosted.org/packages/79/70/fb7668ce0386819303047057aef6fc1da73b584291d9cff82b821744e2ef/msgpack-1.2.1-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:01e2dd6c9b19d333a00282330cc8a73d38d8dabc306dc5b42cd668c3ac82e833", size = 377891, upload-time = "2026-06-18T16:12:36.684Z" }, + { url = "https://files.pythonhosted.org/packages/3d/dc/9ebe654a73c3aed2e40aa6b52e3c2a02b5f53ef0085fa235a45d5b367f87/msgpack-1.2.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:350cb813d0af6e65d2f7ef0d729f7ff5be5a8bce03665892f43e5883d4ecc1b8", size = 391987, upload-time = "2026-06-18T16:12:37.839Z" }, + { url = "https://files.pythonhosted.org/packages/42/eb/b67cf64218a2fa25e1c671fe1d3dbb06cbeb973e71bc4b822da079862d0b/msgpack-1.2.1-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:ee1d9ed27d0497b848923746cf762ed2e7db24f4be7eec8e5cbe8c766aa707b7", size = 374603, upload-time = "2026-06-18T16:12:39.221Z" }, + { url = "https://files.pythonhosted.org/packages/a2/2e/9ee200cde32fd1a0101b4006202fde554c1860adfb9bf7bff31ea4c08df8/msgpack-1.2.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:633727297ed063441fd1cda2288865487f33ad14eeb8831afb5f0c396a62cfce", size = 405121, upload-time = "2026-06-18T16:12:40.524Z" }, + { url = "https://files.pythonhosted.org/packages/43/b6/f10117be7ca7a51e8feed699a907b8e663a8cd66e115ae6b4fb30cc7945c/msgpack-1.2.1-cp310-cp310-win32.whl", hash = "sha256:298872ecf9e61950f1c6af4ca969b859ee91783bb920ef6e6172697d0c8aad74", size = 64088, upload-time = "2026-06-18T16:12:41.762Z" }, + { url = "https://files.pythonhosted.org/packages/ba/93/89976c696fb0224662239d952c47b4d1661b34d79a332ef5584facaa8579/msgpack-1.2.1-cp310-cp310-win_amd64.whl", hash = "sha256:2ff164c1b0bcb740b073b99e945234d0212852fa378e44a208c425379140dbeb", size = 70113, upload-time = "2026-06-18T16:12:42.78Z" }, + { url = "https://files.pythonhosted.org/packages/f4/6b/e9b1cdc042c4458801d2545ed782a95f3d6ba8e270cce8745b8603c7f748/msgpack-1.2.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:29a3f6e9667868429d8240dfd063ea5ffdc1321c13d783aa23827a38de0dcb22", size = 82812, upload-time = "2026-06-18T16:12:45.022Z" }, + { url = "https://files.pythonhosted.org/packages/0c/3a/dd518a1bf78ed1e9ad8afe57307c079a00eafe4b3068932a27ca1ea56b4f/msgpack-1.2.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:aded5bdf32609dc7987a49bbbd15a8ef096193f96dd8bbeb791de729e650acf5", size = 82739, upload-time = "2026-06-18T16:12:46.025Z" }, + { url = "https://files.pythonhosted.org/packages/70/e0/7ba9e1542bf0771a27b8b37c1316e3f95ae9d748fd765284655c476ad4ef/msgpack-1.2.1-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:146ee4e9ce80b365c6d4c47073da9da7bcec473e58194ceee5dd7620ace77e06", size = 414233, upload-time = "2026-06-18T16:12:47.029Z" }, + { url = "https://files.pythonhosted.org/packages/03/8d/671d81534ea0e2b0e8a121be100020da09eb78861fe3aa8f3ef7dcd3bed1/msgpack-1.2.1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a28d076ca7c82b9c8728ad90b7147489449557038bed50e4241eb832395169b4", size = 423843, upload-time = "2026-06-18T16:12:48.19Z" }, + { url = "https://files.pythonhosted.org/packages/d2/b6/e5c737515ed1f166664b87601b532f58cbb73d8aa6a90b99f7c2c5037e8e/msgpack-1.2.1-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:7d31c0ac0c640f877804c67cb2bc9f4e23dc2db97e96c2e67fa27d38283b41f8", size = 390772, upload-time = "2026-06-18T16:12:49.624Z" }, + { url = "https://files.pythonhosted.org/packages/a8/46/62ed8c2e87d7021eab19921594d961ef3aa3794eec76c716dc30f3bfd433/msgpack-1.2.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:8ff92d7feeaf5bc26c51495b69e2f99ed97ab79346fb6555f44be7dd2ac6503b", size = 409559, upload-time = "2026-06-18T16:12:50.936Z" }, + { url = "https://files.pythonhosted.org/packages/70/ff/59aa3887b860bbf43532835e192b1c388a17590d6068ae4f8b2bc74c906e/msgpack-1.2.1-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:779197a6513bab3c3632265e3d0f7cb3227e62510841a6f34f1eaa37efbb345e", size = 387838, upload-time = "2026-06-18T16:12:52.161Z" }, + { url = "https://files.pythonhosted.org/packages/09/11/f8563e471093420cf6478cb3271a0175d8402b82d879783d4035d2d03360/msgpack-1.2.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:67f6dd22fa72a93752643f07889796d62739a13415ee630169a8ce764f86cf9f", size = 421732, upload-time = "2026-06-18T16:12:53.556Z" }, + { url = "https://files.pythonhosted.org/packages/57/cf/e673683c4c6c90c1022b24c65af4b03eda72b182a1176ef6449069d66acc/msgpack-1.2.1-cp311-cp311-win32.whl", hash = "sha256:91054a783328e0ea7954b8771095705c8d2243b814743fbaadf14552c9c52c5d", size = 64091, upload-time = "2026-06-18T16:12:54.821Z" }, + { url = "https://files.pythonhosted.org/packages/3f/07/ca212739d179f9083bff2c7c08c24101c3555a334fadc2b876b18768a3ae/msgpack-1.2.1-cp311-cp311-win_amd64.whl", hash = "sha256:2eda0b7ebb1283a98d3e4492ac933c8af6aff59fd3df1c3ed024f536af4b1dc8", size = 70462, upload-time = "2026-06-18T16:12:55.898Z" }, + { url = "https://files.pythonhosted.org/packages/6d/be/6798347b425e26f35db82e69dd83c09716c856a3714e7bffc4c0860fd830/msgpack-1.2.1-cp311-cp311-win_arm64.whl", hash = "sha256:6ee967f7c7e1df2890c671ff2ee51a28ded0efc95da3e507176dee881ce36c66", size = 65059, upload-time = "2026-06-18T16:12:57.053Z" }, + { url = "https://files.pythonhosted.org/packages/bc/dd/9e8cbd8f5582ca4b590336f2b91ee5662f6a6ca562b565abaf696a0f81ff/msgpack-1.2.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:2ef59c659f289eddf8aa6623823f19fa2f40a4029266889eac7a2505dd210c35", size = 83531, upload-time = "2026-06-18T16:12:58.249Z" }, + { url = "https://files.pythonhosted.org/packages/50/2e/ebdb85a8da151397a2790363676b7ed7c125924fe618e4c6d8befb0cc62c/msgpack-1.2.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:d3567748a5107cb40cdf66a275430c2f87c07777698f4bfd25c35f44d533258c", size = 82657, upload-time = "2026-06-18T16:12:59.396Z" }, + { url = "https://files.pythonhosted.org/packages/26/aa/753ad8b007b464e1d8aa0c8e650b9c5f4f725e658fc5ac8a7635c55b7f6e/msgpack-1.2.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:60926b75d00c8e816ef98f3034f484a8bc64242d66839cef4cf7e503142316a0", size = 410634, upload-time = "2026-06-18T16:13:00.383Z" }, + { url = "https://files.pythonhosted.org/packages/6a/fd/6adabd4f6d5e686f97dd02ce7fce3fe4cf672cbac36b8f67ff4040e8ad8b/msgpack-1.2.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:020e881a764b20d8d7ca1a54fc01b8175519d108e3c3f194fddc200bda95951a", size = 419989, upload-time = "2026-06-18T16:13:01.776Z" }, + { url = "https://files.pythonhosted.org/packages/5a/cc/85039b7b0eb168aaad7383a23c97e291a11f08351cb45a606ce865e4e3f1/msgpack-1.2.1-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:4202c74688ca06591f78cb18988228bd4cca2cc75d57b60008372892d2f1e6e6", size = 377544, upload-time = "2026-06-18T16:13:03.637Z" }, + { url = "https://files.pythonhosted.org/packages/ed/bf/35963899493b32030c85fc513b723ae66144ac70c11ebc52e889e16e3d99/msgpack-1.2.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:8b267ce94efb76fbd1b3373511420074ee3187f0f7811bf394531de13294735a", size = 400842, upload-time = "2026-06-18T16:13:05.012Z" }, + { url = "https://files.pythonhosted.org/packages/a6/df/8e2ac970c8f99264cd9997d1c73df5466bc19da3301d7dc5500862a9b089/msgpack-1.2.1-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:e4f1d0f8f98ade9634e01fb704a408f9336c0a8f1117b369f5db83dc7551d8b1", size = 374108, upload-time = "2026-06-18T16:13:06.232Z" }, + { url = "https://files.pythonhosted.org/packages/17/dd/fa8bd265110dfa51c20cb529f9e6d240a16fafe7e645004c6af2d01353ba/msgpack-1.2.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:f02cf17a6ca1abe29b5f980644f7551f94d71f2011509b26d8625ce038f0df64", size = 414939, upload-time = "2026-06-18T16:13:07.478Z" }, + { url = "https://files.pythonhosted.org/packages/2e/b9/8377a5ad8953fc0437c70cc98d9ae29f27fe5ac5109fbec0812085865735/msgpack-1.2.1-cp312-cp312-win32.whl", hash = "sha256:0c0d9802354507bcba62af19c17918e3eb437cc25e6f50657d511b5856a77aac", size = 64504, upload-time = "2026-06-18T16:13:08.822Z" }, + { url = "https://files.pythonhosted.org/packages/57/7f/ce1e377df7e62461fefd9eb23bfb93a4a523f40a517b377b8f844d836828/msgpack-1.2.1-cp312-cp312-win_amd64.whl", hash = "sha256:5c24aa15d5963051e1a5c62b12c50cd705992502b5ec1f3bece6046f33c9fc24", size = 71421, upload-time = "2026-06-18T16:13:09.828Z" }, + { url = "https://files.pythonhosted.org/packages/8f/32/ebfe84c9929f08f188d56c7a2fd913406a9ddad76a634697c1c43b8112e6/msgpack-1.2.1-cp312-cp312-win_arm64.whl", hash = "sha256:4227224aaec8f7fbcbfbd4272319347b2bb4030366502600f8c45588c5187b07", size = 64775, upload-time = "2026-06-18T16:13:11.056Z" }, + { url = "https://files.pythonhosted.org/packages/b0/ac/dcddcab6f6c20ecb387ca5e980371cdb3f87ff69aeca388be97eebc4c074/msgpack-1.2.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:0a70e3cf2804a300d921bb0940426e35f4e489a23adfb77a808892241db0a064", size = 83151, upload-time = "2026-06-18T16:13:12.173Z" }, + { url = "https://files.pythonhosted.org/packages/64/71/fbcfa83a1d6a9c6091942d1cfd070962244664b87427a9a49a6897b1b219/msgpack-1.2.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:491cc39455ca765fad51fb451bf2915eb2cf41192ab5801ce8d67c1d614fe056", size = 82351, upload-time = "2026-06-18T16:13:13.194Z" }, + { url = "https://files.pythonhosted.org/packages/e3/10/ddf7b06db879e8792d13934ddda09ff20bd2a583fd84c9b59aae9b0e650b/msgpack-1.2.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f310233ef7fb9c14e201c93639fe5f5260b005f56f0b29048e999c30935596cc", size = 407518, upload-time = "2026-06-18T16:13:14.233Z" }, + { url = "https://files.pythonhosted.org/packages/79/d3/36a46a8ed992b781acbc05928bd5bee3c810cb0c3563bf81a7b0c04a1a76/msgpack-1.2.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:787c9bebb5833e8f6fc8abca3c0597683d8d87f56a8842b6b89c75a5f3176e2d", size = 416405, upload-time = "2026-06-18T16:13:15.435Z" }, + { url = "https://files.pythonhosted.org/packages/f9/84/e8e9598b557c0ba6ddae901a73780a4c75ac667dddf59414b1e56a42fb34/msgpack-1.2.1-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:dc871b997a9370d855b7394465f2f350e847a5b806dd38dcc9c989e7d87da155", size = 376257, upload-time = "2026-06-18T16:13:17.022Z" }, + { url = "https://files.pythonhosted.org/packages/40/16/738fe6d875ad7e2a9429c165322a4ec088f4f273cdfae63d96a89c467961/msgpack-1.2.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:85f57e960d877f2977f6430896191b04a21f8901b3b4baf2e4604329f4db5402", size = 397469, upload-time = "2026-06-18T16:13:18.287Z" }, + { url = "https://files.pythonhosted.org/packages/ca/be/6d5952df75a7f24f35833af764c3a6860780364cb3a0030beb8099e1b2b4/msgpack-1.2.1-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:1233ee2dd0cefba127583de50ea654677277047d238303521db35def3d7b2e7c", size = 372802, upload-time = "2026-06-18T16:13:19.685Z" }, + { url = "https://files.pythonhosted.org/packages/e1/39/e2ef7dbf0473bcb8dc7c50bf782a892d67414877b63e47fc88eb189ef5e6/msgpack-1.2.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:e3dc2feb0876209d9c38aa56cb1de169bd6c4348f1aa48271f241226590993e6", size = 411273, upload-time = "2026-06-18T16:13:21.028Z" }, + { url = "https://files.pythonhosted.org/packages/ef/c5/133f4512a56e983a93445c836c9d94d88f3bc2e0980ff4b9e577bd8416ce/msgpack-1.2.1-cp313-cp313-win32.whl", hash = "sha256:6d09badf350af2be9d189184e04e64cf54ad93569ab3d96fca58bd3e84aad707", size = 64471, upload-time = "2026-06-18T16:13:22.293Z" }, + { url = "https://files.pythonhosted.org/packages/e2/98/577e10b055096a7dd40732358cabaf7180a20c79ed1dcdbb618e4b9deac7/msgpack-1.2.1-cp313-cp313-win_amd64.whl", hash = "sha256:33f14fba63278b714efe6ad07e50ea5f03d91537aa6a1c5f1ceca4cf44013ca9", size = 71274, upload-time = "2026-06-18T16:13:23.455Z" }, + { url = "https://files.pythonhosted.org/packages/ba/ee/0c0048e7cfbef23c6a94791b8959ab28155232e7956de8a305b5ff588f05/msgpack-1.2.1-cp313-cp313-win_arm64.whl", hash = "sha256:afc5febcd4c99effbc02b528e49d6fd0760b2b7d48c05239e345a5fa6e743d9a", size = 64795, upload-time = "2026-06-18T16:13:24.687Z" }, + { url = "https://files.pythonhosted.org/packages/77/58/cce442852c6b9e1639c7c8ac8fd9143121cb32dab0f308df4d1426a8eb9c/msgpack-1.2.1-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:05f340e47e7e47d2da8db9b53e1bb1d294369e9ef45a747441309f6650b8351d", size = 83610, upload-time = "2026-06-18T16:13:25.724Z" }, + { url = "https://files.pythonhosted.org/packages/60/5c/15b4c7a0182f75ffa90751958ba36a9c01cafee367d49a3edc10ed140b01/msgpack-1.2.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:810b916696c86ef0deb3b74588480224df4c1b071136c34183e4a2a4284d7ac7", size = 83138, upload-time = "2026-06-18T16:13:26.781Z" }, + { url = "https://files.pythonhosted.org/packages/b8/a6/99e58722feaffc5f2fbcc0c8c0d1451ab9f84097f7af87291b46af2390f4/msgpack-1.2.1-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ca0dacff965c47afdc3749a8469d7302a8f801d6a28758d55120d75e66ce6889", size = 406090, upload-time = "2026-06-18T16:13:28.072Z" }, + { url = "https://files.pythonhosted.org/packages/19/03/8c63e8cf52958534ef688625965ab04c269a6cadd8caef16758b380a821a/msgpack-1.2.1-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0e2bf9280bceb5efca998435904b5d3e9fdbcc11d90dc9df30aec7973252b720", size = 412106, upload-time = "2026-06-18T16:13:29.427Z" }, + { url = "https://files.pythonhosted.org/packages/63/d2/155d9e71b40e41fd934bc0c48b9b2770f22263e1ac20aad8e29fdca7be3f/msgpack-1.2.1-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:aa6c4be5d1c02a42b066ca6ddb71adf36432868fdcdb6ee87e634e86e0674190", size = 374851, upload-time = "2026-06-18T16:13:30.631Z" }, + { url = "https://files.pythonhosted.org/packages/98/48/deaf2326262a8d5ea3295ce9649912ecd3f551ba7ec8e33c665d2ba583f3/msgpack-1.2.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:ec0e675d59150a6269ddc9139087c722292664a37d071a849c05c473350f1f2d", size = 396168, upload-time = "2026-06-18T16:13:31.977Z" }, + { url = "https://files.pythonhosted.org/packages/10/2a/b4410f906c2ec0008f1608d3ab5143afc3ad3f4e6da0fed3ea2231d0bef4/msgpack-1.2.1-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:dd3bfe82d53edfe4b7fc9a7ec9761e23a7a5b1dac22264505af428253c29ed24", size = 371959, upload-time = "2026-06-18T16:13:33.282Z" }, + { url = "https://files.pythonhosted.org/packages/59/86/1edc67270099a528fa2093ea60fe191233cd238e4bd30cfacf7db79fc959/msgpack-1.2.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:5ad5467fc3f68b5468e06c5f788d712e9f8ffc8b0cd1bcb160c105c1ee92dae7", size = 408457, upload-time = "2026-06-18T16:13:34.567Z" }, + { url = "https://files.pythonhosted.org/packages/82/90/8b630fef07d8c5ab457b71ff2c217910c83d333c7a68472c186e87cc504a/msgpack-1.2.1-cp314-cp314-win32.whl", hash = "sha256:98b58bdb89c46190e4609bb36abe17c6d4105ad13f9c5f8f6f64d320f8ced3fb", size = 65942, upload-time = "2026-06-18T16:13:36.056Z" }, + { url = "https://files.pythonhosted.org/packages/16/f1/467b81e98b24dd3885d7b1857728797b4ffc76a7a7483af4fb321a07de3c/msgpack-1.2.1-cp314-cp314-win_amd64.whl", hash = "sha256:74847557e28ce71bd3c438a447ca90e4b507e997ddbdef8a12a7b283b86c156b", size = 72627, upload-time = "2026-06-18T16:13:37.079Z" }, + { url = "https://files.pythonhosted.org/packages/a7/1d/5d8c4c89985feb6acefb82a09e501c60392261856d2408d20bfe4f0360b1/msgpack-1.2.1-cp314-cp314-win_arm64.whl", hash = "sha256:b50b727bd652bdc37d950336c848ef20ec54a4cafc38dce19b1cd86ad625d0f7", size = 66908, upload-time = "2026-06-18T16:13:38.23Z" }, + { url = "https://files.pythonhosted.org/packages/1b/02/ad2afb678b4de94496cd432b581759b756a92c1192d8c767edd6b132efdc/msgpack-1.2.1-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:8d00f177ca88a77c1cf848d204a38f249751650b601cb6532acc68805d8a8273", size = 86000, upload-time = "2026-06-18T16:13:39.44Z" }, + { url = "https://files.pythonhosted.org/packages/54/74/0b797484013128837f3b1cbb6cea019277c4de4e377dc512b4d9a0f92940/msgpack-1.2.1-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:5bb9c386f0a329c035ddbab4b72d1028bf9627add8dda41070288563d57ed1b1", size = 86544, upload-time = "2026-06-18T16:13:40.447Z" }, + { url = "https://files.pythonhosted.org/packages/a9/b4/b774d7eb95561739907fec675582f83203cf41c597a418c2589b4bfb8e9d/msgpack-1.2.1-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:20466cca18c49c7292a8984bc15d65857b171e7264bdcb5f96baf8be238791fc", size = 427661, upload-time = "2026-06-18T16:13:41.574Z" }, + { url = "https://files.pythonhosted.org/packages/b2/f9/3243191dc9937e00756c8bc1b0272fed8f23758e43df2a3b46f533e5090f/msgpack-1.2.1-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:196300e7e5d6e74d50f1607ab9c06c4a1484c383cd22defd727902591f7e8dde", size = 426375, upload-time = "2026-06-18T16:13:42.936Z" }, + { url = "https://files.pythonhosted.org/packages/23/c7/1693111db9944ba4ad4b67a1e788400d78a0b6af7a6523dc7e4e58f8274b/msgpack-1.2.1-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:575957e79cd51903a4e8495a242442949641e08f1efd5197b43bebd3ea7682b4", size = 380495, upload-time = "2026-06-18T16:13:44.306Z" }, + { url = "https://files.pythonhosted.org/packages/3e/2b/92f86956a0c13e8662f7e2ad630c4eb4db07497b967589bd5245e018b2c1/msgpack-1.2.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:8c2ed1e48cc0f460bf3c7780e7137ff21a4e18433451916f2442c1b21036cd7d", size = 410897, upload-time = "2026-06-18T16:13:45.629Z" }, + { url = "https://files.pythonhosted.org/packages/da/ea/1479f72d200313a76fc2f823a79d1e07ed052ab7b8a0280640aa7b95de42/msgpack-1.2.1-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:5f6277e5f783c36786a145e0247fc189a03f35f84b251646e53592d2bc12b355", size = 378519, upload-time = "2026-06-18T16:13:46.998Z" }, + { url = "https://files.pythonhosted.org/packages/f5/4d/fa006060ffa1011d32bfae826fe766fe73e02982183601633b7121058ab3/msgpack-1.2.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:f9389552ecf4784886345ead0647e4edc96bee37cbab05b75540f542f766c48c", size = 419815, upload-time = "2026-06-18T16:13:48.205Z" }, + { url = "https://files.pythonhosted.org/packages/2f/e1/aab6c946570496b78e67804721f3d5e2d62a93081b9b37df77764ef56347/msgpack-1.2.1-cp314-cp314t-win32.whl", hash = "sha256:c1c79a604a2969a868a78b6ebd27a887e00c624f14f66b3038e0590cb23332d1", size = 70914, upload-time = "2026-06-18T16:13:49.385Z" }, + { url = "https://files.pythonhosted.org/packages/13/0a/e608956488a2af014cfe6e3d665e090b8ee42aa14b07f8f95b8880d66b09/msgpack-1.2.1-cp314-cp314t-win_amd64.whl", hash = "sha256:f12038a35fabd52e56a3547bab42401af49a45caa6dd00b34c44de235bc93ee2", size = 77999, upload-time = "2026-06-18T16:13:50.467Z" }, + { url = "https://files.pythonhosted.org/packages/d2/8a/27e2e57055176e366a46b85d02d68e7a5bcfbdd8474c9706375d965f24d3/msgpack-1.2.1-cp314-cp314t-win_arm64.whl", hash = "sha256:0adcf06ffde0777c0e1a9b771a2b1c4226ba1bbf748c8efcc02fcdeca3299107", size = 71160, upload-time = "2026-06-18T16:13:51.498Z" }, ] [[package]] @@ -2664,36 +2654,36 @@ wheels = [ [[package]] name = "nh3" -version = "0.3.5" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/9c/5f/1d19bdc7d27238e37f3672cdc02cb77c56a4a86d140cd4f4f23c90df6e16/nh3-0.3.5.tar.gz", hash = "sha256:45855e14ff056064fec77133bfcf7cd691838168e5e17bbef075394954dc9dc8", size = 20743, upload-time = "2026-04-25T10:44:16.066Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/63/b0/8587ac42a9627ab88e7e221601f1dfccbf4db80b2a29222ea63266dc9abc/nh3-0.3.5-cp314-cp314t-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:23a312224875f72cd16bde417f49071451877e29ef646a60e50fcb69407cc18a", size = 1420126, upload-time = "2026-04-25T10:43:39.834Z" }, - { url = "https://files.pythonhosted.org/packages/c0/1b/1dbc4d0c43f12e8c1784ede17eaee6f061d4fbe5505757c65c49b2ceab95/nh3-0.3.5-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:387abd011e81959d5a35151a11350a0795c6edeb53ebfa02d2e882dc01299263", size = 793943, upload-time = "2026-04-25T10:43:41.363Z" }, - { url = "https://files.pythonhosted.org/packages/47/9f/d6758d7a14ee964bf439cc35ae4fa24a763a93399c8ef6f22bd11d532d29/nh3-0.3.5-cp314-cp314t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:48f45e3e914be93a596431aa143dedf1582557bf41a58153c296048d6e3798c9", size = 841150, upload-time = "2026-04-25T10:43:43.007Z" }, - { url = "https://files.pythonhosted.org/packages/b6/36/d5d1ae8374612c98f390e1ea7c610fa6c9716259a03bbf4d15b269f40073/nh3-0.3.5-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:0a09f51806fd51b4fedbf9ea2b61fef388f19aef0d62fe51199d41648be14588", size = 1008415, upload-time = "2026-04-25T10:43:44.324Z" }, - { url = "https://files.pythonhosted.org/packages/ba/8f/d13a9c3fd2d9c131a2a281737380e9379eb0f8c33fea24c2b923aaafbb15/nh3-0.3.5-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:c357f1d042c67f135a5e6babb2b0e3b9d9224ff4a3543240f597767b01384ffd", size = 1092706, upload-time = "2026-04-25T10:43:45.653Z" }, - { url = "https://files.pythonhosted.org/packages/bb/57/2f3add7f8680fcc896afa6a675cb2bab09982853ee8af40bad621f6b61c4/nh3-0.3.5-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:38748140bf76383ab7ce2dce0ad4cb663855d8fbc9098f7f3483673d09616a17", size = 1048346, upload-time = "2026-04-25T10:43:46.974Z" }, - { url = "https://files.pythonhosted.org/packages/c1/c3/2f9e4ffa82863074d1361bfe949bc46393d91b3411579dfbbd090b24cac5/nh3-0.3.5-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:84bdeb082544fbcb77a12c034dd77d7da0556fdc0727b787eb6214b958c15e29", size = 1029038, upload-time = "2026-04-25T10:43:48.569Z" }, - { url = "https://files.pythonhosted.org/packages/e8/10/2804deb3f3315184c9cae41702e293c87524b5a21f766b07d7fe3ffbcfbb/nh3-0.3.5-cp314-cp314t-win32.whl", hash = "sha256:c3aae321f67ae66cff2a627115f106a377d4475d10b0e13d97959a13486b9a88", size = 603263, upload-time = "2026-04-25T10:43:49.851Z" }, - { url = "https://files.pythonhosted.org/packages/eb/a2/f6685248b49f7548fc9a8c335ab3a52f68610b72e8a61576447151e4e2e6/nh3-0.3.5-cp314-cp314t-win_amd64.whl", hash = "sha256:c88605d8d468f7fc1b31e06129bc91d6c96f6c621776c9b504a0da9beac9df5f", size = 616866, upload-time = "2026-04-25T10:43:51.005Z" }, - { url = "https://files.pythonhosted.org/packages/ca/b6/d8c9018635d4acfefde6b68470daa510eed715a350cbaa2f928ba0609f81/nh3-0.3.5-cp314-cp314t-win_arm64.whl", hash = "sha256:72c5bdedec27fa33de6a5326346ea8aa3fe54f6ac294d54c4b204fb66a9f1e79", size = 602566, upload-time = "2026-04-25T10:43:52.283Z" }, - { url = "https://files.pythonhosted.org/packages/85/30/d162e99746a2fb1d98bb0ef23af3e201b156cf09f7de867c7390c8fe1c06/nh3-0.3.5-cp38-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:3bb854485c9b33e5bb143ff3e49e577073bc6bc320f0ff8fc316dd89c0d3c101", size = 1442393, upload-time = "2026-04-25T10:43:53.556Z" }, - { url = "https://files.pythonhosted.org/packages/25/8c/072120d506978ab053e1732d0efa7c86cb478fee0ee098fda0ac0d31cb34/nh3-0.3.5-cp38-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:50d401ab2d8e86d59e2126e3ab2a2f45840c405842b626d9a51624b3a33b6878", size = 837722, upload-time = "2026-04-25T10:43:55.073Z" }, - { url = "https://files.pythonhosted.org/packages/52/86/d4e06e28c5ad1c4b065f89737d02631bd49f1660b6ebcf17a87ffcd201da/nh3-0.3.5-cp38-abi3-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:acfd354e61accbe4c74f8017c6e397a776916dfe47c48643cf7fd84ade826f93", size = 822872, upload-time = "2026-04-25T10:43:56.581Z" }, - { url = "https://files.pythonhosted.org/packages/0a/62/50659255213f241ec5797ae7427464c969397373e83b3659372b341ae869/nh3-0.3.5-cp38-abi3-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:52d877980d7ca01dc3baf3936bf844828bc6f332962227a684ed79c18cce14c3", size = 1100031, upload-time = "2026-04-25T10:43:58.098Z" }, - { url = "https://files.pythonhosted.org/packages/00/7a/a12ae77593b2fcf3be25df7bc1c01967d0de448bdb4b6c7ec80fe4f5a74f/nh3-0.3.5-cp38-abi3-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:207c01801d3e9bb8ec08f08689346bdd30ce15b8bf60013a925d08b5388962a4", size = 1057669, upload-time = "2026-04-25T10:43:59.328Z" }, - { url = "https://files.pythonhosted.org/packages/2d/71/5647dc04c0233192a3956fc91708822b21403a06508cacf78083c68e7bf0/nh3-0.3.5-cp38-abi3-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ea232933394d1d58bf7c4bb348dc4660eae6604e1ae81cd2ba6d9ed80d390f3b", size = 914795, upload-time = "2026-04-25T10:44:00.52Z" }, - { url = "https://files.pythonhosted.org/packages/1b/0e/bf298920729f216adcb002acf7ea01b90842603d2e4e2ce9b900d9ee8fab/nh3-0.3.5-cp38-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fe3a787dc76b50de6bee54ef242f26c41dfe47654428e3e94f0fae5bb6dd2cc1", size = 806976, upload-time = "2026-04-25T10:44:01.743Z" }, - { url = "https://files.pythonhosted.org/packages/85/01/26761e1dc2b848e65a62c19e5d39ad446283287cd4afddc89f364ab86bc9/nh3-0.3.5-cp38-abi3-manylinux_2_31_riscv64.whl", hash = "sha256:488928988caad25ba14b1eb5bc74e25e21f3b5e40341d956f3ce4a8bc19460dc", size = 834904, upload-time = "2026-04-25T10:44:03.454Z" }, - { url = "https://files.pythonhosted.org/packages/33/53/0766113e679540ac1edc1b82b1295aecd321eeb75d6fead70109a838b6ee/nh3-0.3.5-cp38-abi3-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2c069570b06aa848457713ad7af4a9905691291548c4466a9ad78ee95808382b", size = 857159, upload-time = "2026-04-25T10:44:05.003Z" }, - { url = "https://files.pythonhosted.org/packages/58/36/734d353dfaf292fed574b8b3092f0ef79dc6404f3879f7faaa61a4701fad/nh3-0.3.5-cp38-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:eeedc90ed8c42c327e8e10e621ccfa314fc6cce35d5929f4297ff1cdb89667c4", size = 1018600, upload-time = "2026-04-25T10:44:06.18Z" }, - { url = "https://files.pythonhosted.org/packages/6b/aa/d9c59c1b49669fcb7bababa55df82385f029ad5c2651f583c3a1141cfdd1/nh3-0.3.5-cp38-abi3-musllinux_1_2_armv7l.whl", hash = "sha256:de8e8621853b6470fe928c684ee0d3f39ea8086cebafe4c416486488dea7b68d", size = 1103530, upload-time = "2026-04-25T10:44:07.68Z" }, - { url = "https://files.pythonhosted.org/packages/90/b0/cdd210bfb8d9d43fb02fc3c868336b9955934d8e15e66eb1d15a147b8af0/nh3-0.3.5-cp38-abi3-musllinux_1_2_i686.whl", hash = "sha256:6ea58cc44d274c643b83547ca9654a0b1a817609b160601356f76a2b744c49ad", size = 1061754, upload-time = "2026-04-25T10:44:09.362Z" }, - { url = "https://files.pythonhosted.org/packages/ce/cb/7a39e72e668c8445bdd95e494b3e21cfdddc68329be8ea3522c8befb46c4/nh3-0.3.5-cp38-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:e49c9b564e6bcb03ecd2f057213df9a0de15a95812ac9db9600b590db23d3ae9", size = 1040938, upload-time = "2026-04-25T10:44:10.775Z" }, - { url = "https://files.pythonhosted.org/packages/af/4c/fc2f9ed208a3801a319f59b5fea03cdc20cf3bd8af14be930d3a8de01224/nh3-0.3.5-cp38-abi3-win32.whl", hash = "sha256:559e4c73b689e9a7aa97ac9760b1bc488038d7c1a575aa4ab5a0e19ee9630c0f", size = 611445, upload-time = "2026-04-25T10:44:12.317Z" }, - { url = "https://files.pythonhosted.org/packages/db/1a/e4c9b5e2ae13e6092c9ec16d8ca30646cb01fcdea245f36c5b08fd21fbd5/nh3-0.3.5-cp38-abi3-win_amd64.whl", hash = "sha256:45e6a65dc88a300a2e3502cb9c8e6d1d6b831d6fba7470643333609c6aab1f30", size = 626502, upload-time = "2026-04-25T10:44:13.682Z" }, - { url = "https://files.pythonhosted.org/packages/80/7c/19cd0671d1ba2762fb388fc149697d20d0568ccfeef833b11280a619e526/nh3-0.3.5-cp38-abi3-win_arm64.whl", hash = "sha256:8f85285700a18e9f3fc5bff41fe573fa84f81542ef13b48a89f9fecca0474d3b", size = 611069, upload-time = "2026-04-25T10:44:14.934Z" }, +version = "0.3.6" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/5e/1b/ef84624f14954d270f74060a19fc550dd4f06656399447569afb584d8c06/nh3-0.3.6.tar.gz", hash = "sha256:f3736c9dd3d1856f80cd031715b84ca75cda2bbb1ac802c3da26bfce590838d7", size = 24684, upload-time = "2026-06-22T00:47:02.008Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/99/3e/6506aa4f23dc7b7993a2d0a45dca3ce864ec48380adfe15a173e643c63e8/nh3-0.3.6-cp314-cp314t-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:2411e8c3cee81a1ddd62c2a5d50585c28aa5566d373ad1db92536b95ddb24ef2", size = 1421679, upload-time = "2026-06-22T00:46:20.248Z" }, + { url = "https://files.pythonhosted.org/packages/e3/e1/e96e7864a7a53bd6b6fab7e9632467382a2a2c1f3fed951918ad131542fb/nh3-0.3.6-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e196fa70c2ff2eb4de7d3df3108f8f358c1d69dff20d45b11f20a5aa227ffb6d", size = 792570, upload-time = "2026-06-22T00:46:22.179Z" }, + { url = "https://files.pythonhosted.org/packages/59/62/5b6108bedaef2b2637fed04c87bdbcb5967b9961758b41f0e466ef22a022/nh3-0.3.6-cp314-cp314t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:34d2b0d934156b87ee114f599a3ba9b8b9e17b5d79652ba3a13fa50903de965e", size = 842243, upload-time = "2026-06-22T00:46:23.801Z" }, + { url = "https://files.pythonhosted.org/packages/4b/4a/526f199626bfcb496bc01a268051b44737962005553b158e985ed7e64865/nh3-0.3.6-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:f2f14b7ae1fca99c4a66c981aac3974e7fbc1ca30a12673d223ae1df76680917", size = 1001468, upload-time = "2026-06-22T00:46:25.481Z" }, + { url = "https://files.pythonhosted.org/packages/49/09/0d8e3101636d9ad88cdefb2914e764cb8e876ebdbb4286bfc251277d9c67/nh3-0.3.6-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:889932a97fb4abb6f95fef1914c0d269ebfb60011e67121c1163059b9449dbb4", size = 1082933, upload-time = "2026-06-22T00:46:27.15Z" }, + { url = "https://files.pythonhosted.org/packages/09/a1/ea83abe738a3fbaa203dfdb836ca7cbab0e7e9609faaee4fe1d4652599c0/nh3-0.3.6-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:edb2b4a1a27523e6cc7c417f8d21ce3d005243548b93e56b762b66b0c7f589f9", size = 1043120, upload-time = "2026-06-22T00:46:28.89Z" }, + { url = "https://files.pythonhosted.org/packages/66/69/0654482b8635012fbae67826bd6c381abb05d841ac7388b9b4666300fdad/nh3-0.3.6-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:43bc1ed3fa0716295fabee29ba42b2667e4a51d140b0a68e092170a765474fa6", size = 1023824, upload-time = "2026-06-22T00:46:30.453Z" }, + { url = "https://files.pythonhosted.org/packages/ed/a6/1f7285ffadc8307c4dbeb08d21b920536d5117785056d1079e998c4dfa44/nh3-0.3.6-cp314-cp314t-win32.whl", hash = "sha256:597a8e843bea00b2eb5520658dc24a9bb032e7fc9e7c2c0c4cd29420220c9796", size = 599253, upload-time = "2026-06-22T00:46:32.072Z" }, + { url = "https://files.pythonhosted.org/packages/36/ea/5542f3c45da4c00290d9d67a65e996702e23e613c4b627de3e09cb9fe357/nh3-0.3.6-cp314-cp314t-win_amd64.whl", hash = "sha256:4713502748f564fee0633b37b3403783ce0a3af3a3d148ad91025a5bdadb7bc6", size = 612553, upload-time = "2026-06-22T00:46:33.53Z" }, + { url = "https://files.pythonhosted.org/packages/66/35/26bd47e6af5915a628281dccdac354ddf4e32f7397047894270acd8c9870/nh3-0.3.6-cp314-cp314t-win_arm64.whl", hash = "sha256:69bbb92865a693d909db3a700d3c01537533844d0948c1e9323561ce06ecda41", size = 595151, upload-time = "2026-06-22T00:46:34.878Z" }, + { url = "https://files.pythonhosted.org/packages/f3/ab/a7653bce9a3b204be6a6931767a9e23595807bb84790ce6685e4d7e5bd08/nh3-0.3.6-cp38-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:a43ebd7543555c3ac1bc353023d0794e75cb76f6f18f19c32e95441496c0cc25", size = 1443564, upload-time = "2026-06-22T00:46:36.66Z" }, + { url = "https://files.pythonhosted.org/packages/41/21/e1084ab18eb589506335c7c7576f2d4643e9a0c0e33983ef0e549a256b96/nh3-0.3.6-cp38-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e1b160831c9cdb06a6c79c2f9cdb11386602938f9af260d1c457a85add4f6f69", size = 838002, upload-time = "2026-06-22T00:46:38.101Z" }, + { url = "https://files.pythonhosted.org/packages/b0/94/f48d08e6f72a406300fa11d8acd929fea1a80d4bf750fa292cb10785f126/nh3-0.3.6-cp38-abi3-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d14bf7982e7a77c0c775634c29c07ce08b38a046df73e1c1f139b3e82f18a38e", size = 823045, upload-time = "2026-06-22T00:46:39.495Z" }, + { url = "https://files.pythonhosted.org/packages/25/bb/431615ba1d1d3eb63cde0f974f2114edf863a8a3f6049a12fed23fc241d3/nh3-0.3.6-cp38-abi3-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:44673b27010051ab5a5e438a86ec31bbda61d4a77d7e900af6b7be3037c1abae", size = 1093171, upload-time = "2026-06-22T00:46:41.21Z" }, + { url = "https://files.pythonhosted.org/packages/0e/24/a0d80182a18919665fefd19c1c06f1d1df1c9a6455d0252de40c034a0bc3/nh3-0.3.6-cp38-abi3-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e6b7beece07525dc6e6b0fc2f104442de2ba328360ad00e50cbe2e1fd620447d", size = 1049217, upload-time = "2026-06-22T00:46:42.804Z" }, + { url = "https://files.pythonhosted.org/packages/0a/13/6f1e302ca674ac74362e150848ad56a1be5145391204f74facdb8e94df12/nh3-0.3.6-cp38-abi3-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:455469a29951edc92bc48b47ac2281c3f2609e6c4f6a047056449f8c2c23facf", size = 917372, upload-time = "2026-06-22T00:46:44.495Z" }, + { url = "https://files.pythonhosted.org/packages/5b/67/314f6151bad77a93d751978a344033e1fc890822f05f0416079338e34231/nh3-0.3.6-cp38-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:905f877dc66dd7aea4a76e54bcb26acb5ff8216f720c0017ccf63e0e6035698e", size = 806699, upload-time = "2026-06-22T00:46:45.99Z" }, + { url = "https://files.pythonhosted.org/packages/3c/a6/bfaa00046e58603507dcfc266c4778e3ab7adf68a5dedd73b6274b8d9314/nh3-0.3.6-cp38-abi3-manylinux_2_31_riscv64.whl", hash = "sha256:25c733bee928530556b1db0ea46c52cf5aa686146e38e60a6fc7cb801ef91cec", size = 835165, upload-time = "2026-06-22T00:46:47.617Z" }, + { url = "https://files.pythonhosted.org/packages/30/a8/fb2c38845efb703a9173bffdfc745fc64d2b0e55cfc73a3647d2f028250c/nh3-0.3.6-cp38-abi3-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2f90d9a0cfdbee218994fdaaeeb5a0fde62d08f35e4eef0378ec1e2200172fd0", size = 858282, upload-time = "2026-06-22T00:46:49.276Z" }, + { url = "https://files.pythonhosted.org/packages/68/17/06e72a18ee9b572914447338237ca7eb164c0df901f141bc10d1282247a2/nh3-0.3.6-cp38-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:82ca5bf427ad1b216b65ede1a2e2d87dc49bec417ceba0f297213107d3cd9d78", size = 1014328, upload-time = "2026-06-22T00:46:51.026Z" }, + { url = "https://files.pythonhosted.org/packages/11/f9/3966c61455668c08853bf5e33b4bed93c421f3194ce4de896dc248d6f6ce/nh3-0.3.6-cp38-abi3-musllinux_1_2_armv7l.whl", hash = "sha256:f5ed5fe84aee7f39db95c214a7421bf0499fbf500fec6d86a4e29bfc37971438", size = 1098207, upload-time = "2026-06-22T00:46:52.674Z" }, + { url = "https://files.pythonhosted.org/packages/19/d3/479cb4ae440424825735d60525b53e3c77fd60fd6e6afc0e984f00eb0178/nh3-0.3.6-cp38-abi3-musllinux_1_2_i686.whl", hash = "sha256:082675ff87b9385ec430ffe6d5847ba7456cc39b73720cd4add472f9f4cffd56", size = 1056961, upload-time = "2026-06-22T00:46:54.335Z" }, + { url = "https://files.pythonhosted.org/packages/17/0c/6cdb5ee1e127be50dc8391e54bddc1f64e87bf4bfad0c55633320e2e02db/nh3-0.3.6-cp38-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:36d06341bd501240d320f5942481ed5e6846136b666e1ba4faf802b78ebc875f", size = 1033829, upload-time = "2026-06-22T00:46:56.258Z" }, + { url = "https://files.pythonhosted.org/packages/e9/55/9de666ad975d6ccd77d799ea0add55ee2347aa81286ce21b2a97c070746b/nh3-0.3.6-cp38-abi3-win32.whl", hash = "sha256:5276ef17bdba9ad8040575c74072008b13aae429436e9d0429e718bb5f90f4da", size = 609081, upload-time = "2026-06-22T00:46:57.665Z" }, + { url = "https://files.pythonhosted.org/packages/82/fa/2b5d684e3edf1e81bfd02d298c78c3e3da77ca1d8a2be3183a79544a7548/nh3-0.3.6-cp38-abi3-win_amd64.whl", hash = "sha256:f338ac7d594c067679f1e99b4f5ec3906842979560f9d8f15d6bdfa39a353b10", size = 624461, upload-time = "2026-06-22T00:46:59.163Z" }, + { url = "https://files.pythonhosted.org/packages/7b/e5/7cafee2f0413ca4cb0ef3bd111e94d408a48810008b283ad8aee00dd1809/nh3-0.3.6-cp38-abi3-win_arm64.whl", hash = "sha256:69f365963f63a1e9bff53bdbb3c542c7c2efed3e163c9d5d83a772a2ac468c21", size = 603060, upload-time = "2026-06-22T00:47:00.596Z" }, ] [[package]] @@ -2723,7 +2713,7 @@ wheels = [ [[package]] name = "openai" -version = "2.41.1" +version = "2.45.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "anyio" }, @@ -2735,14 +2725,14 @@ dependencies = [ { name = "tqdm" }, { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/40/36/4c926a91554483977608951360c18c2e911592785eb87a6437813f6123f7/openai-2.41.1.tar.gz", hash = "sha256:23d617a0432457ad844973bee8f540be9da90894f7c5686852d2d365da058f57", size = 783584, upload-time = "2026-06-10T16:10:37.667Z" } +sdist = { url = "https://files.pythonhosted.org/packages/78/60/d4219875289b11d2c2f7da93c36283da224a2e55865ed865ab64e0ce9217/openai-2.45.0.tar.gz", hash = "sha256:10d34ca9c5643bce775852fddbfc172505cb1d4de1ccd101696c3ecff358765d", size = 1109653, upload-time = "2026-07-09T18:02:44.091Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/20/74/925d7b3892927e9804aaf58d374a45dc28e4420ff90e992272b77286343e/openai-2.41.1-py3-none-any.whl", hash = "sha256:a939565f350cb7443cb843b801b88c716ac8024b492fb94ca269d5f6b1bbefd6", size = 1353380, upload-time = "2026-06-10T16:10:35.756Z" }, + { url = "https://files.pythonhosted.org/packages/f1/b0/2291689e3ec4723fbf5bbf3b54afcd7b160f9ddc98ca7aedfd0132af5677/openai-2.45.0-py3-none-any.whl", hash = "sha256:5df105f5f8c9b711fcb9d06d2d3888cebc82506db216484c14a4e53cdf651777", size = 1629470, upload-time = "2026-07-09T18:02:42.21Z" }, ] [[package]] name = "openai-agents" -version = "0.17.7" +version = "0.18.2" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "griffelib" }, @@ -2753,9 +2743,9 @@ dependencies = [ { name = "typing-extensions" }, { name = "websockets" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/d4/b2/235cbfdefe86623fc77f65fc1d016686372f61d4a1bf3fc66151de2eb847/openai_agents-0.17.7.tar.gz", hash = "sha256:ca76e7f882c9d8f06e3dfb8064cc33bcb5a5f34a29816cb9af863f395964ff0c", size = 5485068, upload-time = "2026-06-24T05:15:33.705Z" } +sdist = { url = "https://files.pythonhosted.org/packages/05/0c/52e9aeff5549b225d5666a0eb84a8a22b4c47db08b6f44dbd45876fcfba3/openai_agents-0.18.2.tar.gz", hash = "sha256:9f418bb563eddff1e01f245ae8a4964b7649396f444b569b4113d105e41ca1d3", size = 5546139, upload-time = "2026-07-11T01:08:18.537Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/1e/2e/2e96ca6928951fe1d16744c22dc1355eda1dd5b0dd920ca1d3ab602929f8/openai_agents-0.17.7-py3-none-any.whl", hash = "sha256:51b5ae43756eea37032e430f95979ba3999af6b1ade397df6c0ffeaf1939646a", size = 856074, upload-time = "2026-06-24T05:15:31.741Z" }, + { url = "https://files.pythonhosted.org/packages/9c/23/b5b6b80a3e36f021ca2a8c4637684f0d722d646b19d3616768a68802c302/openai_agents-0.18.2-py3-none-any.whl", hash = "sha256:c7aea341b256a90b87b17b7e444bab29a12655864a2f0094f65561223d867185", size = 874310, upload-time = "2026-07-11T01:08:16.851Z" }, ] [package.optional-dependencies] @@ -2799,7 +2789,7 @@ wheels = [ [[package]] name = "openinference-instrumentation" -version = "0.1.53" +version = "0.1.54" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "openinference-semantic-conventions" }, @@ -2807,14 +2797,14 @@ dependencies = [ { name = "opentelemetry-sdk" }, { name = "wrapt" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/f9/b6/c0e7e047ae4962f2755a3bc9141fdd6272c75c74e47dfc6aa71978a9b78f/openinference_instrumentation-0.1.53.tar.gz", hash = "sha256:3c0c145cf6e13cfa630b29d0e3ca806f3821470ffca7922f1590e3970fadd4da", size = 33712, upload-time = "2026-06-02T16:37:21.771Z" } +sdist = { url = "https://files.pythonhosted.org/packages/c1/cc/62c1175ee7edc2cbdf95b5b73e0b0f305e759d407bf1bc353ff30a763365/openinference_instrumentation-0.1.54.tar.gz", hash = "sha256:9af9817bb38816ed32856fb4cd813c1a5d9f530ab589c3473b37e06cf406ab28", size = 33938, upload-time = "2026-06-30T19:23:15.648Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/13/bb/01262d9945c476e15aa21bb9ca05b18604e525d73d9761cadb677f485198/openinference_instrumentation-0.1.53-py3-none-any.whl", hash = "sha256:f43695080eded47b1e03ff1b19cb5c23ea4409459cfe16c5b5748d5656832eb1", size = 40958, upload-time = "2026-06-02T16:37:20.69Z" }, + { url = "https://files.pythonhosted.org/packages/38/e3/c7aa7bb4845e0cfdf477ff87f9a3ec0cd2aa55a34a9f31be84d724cabbb7/openinference_instrumentation-0.1.54-py3-none-any.whl", hash = "sha256:8bc991865c90c804ac9983ef93aa6081a7a2397dd113d3d38b5465cca17892bb", size = 41197, upload-time = "2026-06-30T19:23:14.315Z" }, ] [[package]] name = "openinference-instrumentation-google-adk" -version = "0.1.15" +version = "0.1.17" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "openinference-instrumentation" }, @@ -2825,9 +2815,9 @@ dependencies = [ { name = "typing-extensions" }, { name = "wrapt" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/1b/1a/f35f3f38dba763e3ab41a73c15125de6107b3dd1aacbff50201b945e7d89/openinference_instrumentation_google_adk-0.1.15.tar.gz", hash = "sha256:1c0c73ad3b128858486f2066ceba3690061cbb8755bcd97a58220d9a5a42cf8e", size = 14739, upload-time = "2026-05-22T21:10:48.449Z" } +sdist = { url = "https://files.pythonhosted.org/packages/3b/c2/8400125398ac568efe49bc8a9411a4c860b27112279d52d2bb8acbc70126/openinference_instrumentation_google_adk-0.1.17.tar.gz", hash = "sha256:8235d2cf3fce5edaf213136fbd00e876db183add362b2edede87cd42b21ab112", size = 14844, upload-time = "2026-07-01T15:44:19.524Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/49/24/dbddd058a5b837c5f50a42dd94b4d9e338dc362c3cf067a6620c18a7f5c3/openinference_instrumentation_google_adk-0.1.15-py3-none-any.whl", hash = "sha256:be6db6bb68922acae5103bbb72fda9b880a809309b49289fa23d685742de8ebe", size = 16661, upload-time = "2026-05-22T21:10:46.054Z" }, + { url = "https://files.pythonhosted.org/packages/27/c0/b0c301a0a1de9fe377e666e89b9e87fa368bd5ac1341ab125624e2bbc081/openinference_instrumentation_google_adk-0.1.17-py3-none-any.whl", hash = "sha256:3f45e38cfd5ffb41c18deddc747e48c68595d4dfa1a89b7b1aa1f3d31e46ce0d", size = 16755, upload-time = "2026-07-01T15:44:18.364Z" }, ] [[package]] @@ -2859,32 +2849,31 @@ wheels = [ [[package]] name = "opentelemetry-api" -version = "1.41.1" +version = "1.42.1" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "importlib-metadata" }, { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/fa/fc/b7564cbef36601aef0d6c9bc01f7badb64be8e862c2e1c3c5c3b43b53e4f/opentelemetry_api-1.41.1.tar.gz", hash = "sha256:0ad1814d73b875f84494387dae86ce0b12c68556331ce6ce8fe789197c949621", size = 71416, upload-time = "2026-04-24T13:15:38.262Z" } +sdist = { url = "https://files.pythonhosted.org/packages/b4/1c/125e1c936c0873796771b7f04f6c93b9f1bf5d424cea90fda94a99f61da8/opentelemetry_api-1.42.1.tar.gz", hash = "sha256:56c63bea9f77b62856be8c47600474acad853b2924b99b1687c4cb6297166716", size = 72296, upload-time = "2026-05-21T16:32:49.335Z" } 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" }, + { url = "https://files.pythonhosted.org/packages/a3/ca/9520cc1f3dfbbd03ac5903bbf55833e257bc64b1cf30fa8b0d6df374d821/opentelemetry_api-1.42.1-py3-none-any.whl", hash = "sha256:51a69edacadbc03a8950ace1c4c21099cacc538820ac2c9e36277e78cebba714", size = 61311, upload-time = "2026-05-21T16:32:28.822Z" }, ] [[package]] name = "opentelemetry-exporter-otlp-proto-common" -version = "1.41.1" +version = "1.42.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "opentelemetry-proto" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/ae/fa/f9e3bd3c4d692b3ce9a2880a167d1f79681a1bea11f00d5bf76adc03e6ea/opentelemetry_exporter_otlp_proto_common-1.41.1.tar.gz", hash = "sha256:0e253156ea9c36b0bd3d2440c5c9ba7dd1f3fb64ba7a08fc85fbac536b56e1fb", size = 20409, upload-time = "2026-04-24T13:15:40.924Z" } +sdist = { url = "https://files.pythonhosted.org/packages/0e/9c/216acfeaedadf2e1937f4373929b20f73197c5c4a2546d4f584b7fa63813/opentelemetry_exporter_otlp_proto_common-1.42.1.tar.gz", hash = "sha256:04f1f01fb597c4249dfcd7f8b861c902c2102369d376d9d346ff38de4469a2ee", size = 21433, upload-time = "2026-05-21T16:32:55.526Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/29/48/bce76d3ea772b609757e9bc844e02ab408a6446609bf74fb562062ba6b71/opentelemetry_exporter_otlp_proto_common-1.41.1-py3-none-any.whl", hash = "sha256:10da74dad6a49344b9b7b21b6182e3060373a235fde1528616d5f01f92e66aa9", size = 18366, upload-time = "2026-04-24T13:15:18.917Z" }, + { url = "https://files.pythonhosted.org/packages/d6/43/2375e7612e1121a4518c17603b6e0b03ad94f565aafad53f464dc5be2bf6/opentelemetry_exporter_otlp_proto_common-1.42.1-py3-none-any.whl", hash = "sha256:f48d395ab815b444da118868977e9798ea354c25737d5cf39578ae894011c140", size = 17327, upload-time = "2026-05-21T16:32:33.387Z" }, ] [[package]] name = "opentelemetry-exporter-otlp-proto-grpc" -version = "1.41.1" +version = "1.42.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "googleapis-common-protos" }, @@ -2895,14 +2884,14 @@ dependencies = [ { name = "opentelemetry-sdk" }, { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/1e/9b/e4503060b8695579dbaad187dc8cef4554188de68748c88060599b77489e/opentelemetry_exporter_otlp_proto_grpc-1.41.1.tar.gz", hash = "sha256:b05df8fa1333dc9a3fda36b676b96b5095ab6016d3f0c3296d430d629ba1443b", size = 25755, upload-time = "2026-04-24T13:15:41.93Z" } +sdist = { url = "https://files.pythonhosted.org/packages/87/87/ca7fc790dfdbcf4f9e9aab14a39ef1b7508ead13707e283de0b3131478d2/opentelemetry_exporter_otlp_proto_grpc-1.42.1.tar.gz", hash = "sha256:975c4461f167dd8ed8857d68d3b6b25f3d272eab896f6a9470d0f5b90e2faf15", size = 27140, upload-time = "2026-05-21T16:32:56.162Z" } 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" }, + { url = "https://files.pythonhosted.org/packages/89/2b/28ba5b128f47fe8c3bab541000d6feb4b5a9bd26623ca013406f01c0fb60/opentelemetry_exporter_otlp_proto_grpc-1.42.1-py3-none-any.whl", hash = "sha256:0ae1177e2038b18a929b3098215243631ef91136cba26b7e2b12790ceb7e87cc", size = 19617, upload-time = "2026-05-21T16:32:34.278Z" }, ] [[package]] name = "opentelemetry-instrumentation" -version = "0.62b1" +version = "0.63b1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "opentelemetry-api" }, @@ -2910,49 +2899,49 @@ dependencies = [ { name = "packaging" }, { name = "wrapt" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/52/cb/0523b92c112a6cc70be43724343dc45225d3af134419844d7879a07755d4/opentelemetry_instrumentation-0.62b1.tar.gz", hash = "sha256:90e92a905ba4f84db06ac3aec96701df6c079b2d66e9379f8739f0a1bdcc7f45", size = 34043, upload-time = "2026-04-24T13:22:31.997Z" } +sdist = { url = "https://files.pythonhosted.org/packages/da/6d/4de72d97ff54db1ed270c7a59c9b904b917c0ac7af429c086c388b824ddb/opentelemetry_instrumentation-0.63b1.tar.gz", hash = "sha256:32368d6ae52c8de20aa790a6ad86b10a76f09956092337ae37d675773990e541", size = 41081, upload-time = "2026-05-21T16:36:14.206Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/4d/0f/45adbaea1f81b847cffdcee4f4b5f89297e42facf7fac78c7aaac4c38e75/opentelemetry_instrumentation-0.62b1-py3-none-any.whl", hash = "sha256:976fc6e640f2006599e97429c949e622c108d0c17c2059347d1e6c93c707f257", size = 34163, upload-time = "2026-04-24T13:21:31.722Z" }, + { url = "https://files.pythonhosted.org/packages/35/a1/9314e621c143e4d82a5bf7a43c2ff7a745d31023506336857607c8c543cc/opentelemetry_instrumentation-0.63b1-py3-none-any.whl", hash = "sha256:f1986716d52cc316ea5f60189098726a9071d8ecc0eee96c9ed110be08bade9c", size = 35577, upload-time = "2026-05-21T16:34:56.818Z" }, ] [[package]] name = "opentelemetry-instrumentation-threading" -version = "0.62b1" +version = "0.63b1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "opentelemetry-api" }, { name = "opentelemetry-instrumentation" }, { name = "wrapt" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/e7/2d/2537d5990fa341198cbc8ae70b2c3637037061b8ab1196af1d924a275f55/opentelemetry_instrumentation_threading-0.62b1.tar.gz", hash = "sha256:4b3c876907657e3b8b977bfe15d248f2c02db56302c51883724e7ac2f8ce26d2", size = 9180, upload-time = "2026-04-24T13:23:06.15Z" } +sdist = { url = "https://files.pythonhosted.org/packages/d9/90/7b0279192fab614d57af3d57584ef7ac9e38fa3df0b1d412224f6f55a85b/opentelemetry_instrumentation_threading-0.63b1.tar.gz", hash = "sha256:afa8c2cada8ed136f07b04dc8739bc861a15e9a5edea1a65e4c5e1919c62946c", size = 9080, upload-time = "2026-05-21T16:36:49.977Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/aa/37/a80fb13b76f85b4e433ff44b4ba177615823c36c28dca12e94d2c37de681/opentelemetry_instrumentation_threading-0.62b1-py3-none-any.whl", hash = "sha256:4596e79c47de122eb2e85877c1a8bfed1cd6ab06bd2c29d120ebcf8a708a433a", size = 9335, upload-time = "2026-04-24T13:22:19.419Z" }, + { url = "https://files.pythonhosted.org/packages/c9/3d/3a991a4fcdf5ac82c04215e38cea4e73ad63713707014f9a70d1ab257f5f/opentelemetry_instrumentation_threading-0.63b1-py3-none-any.whl", hash = "sha256:33059298e68c94b13c38b562ad28799ec16a2fd06182ebfc762bb4e956e55d94", size = 8486, upload-time = "2026-05-21T16:35:58.084Z" }, ] [[package]] name = "opentelemetry-proto" -version = "1.41.1" +version = "1.42.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "protobuf" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/99/e8/633c6d8a9c8840338b105907e55c32d3da1983abab5e52f899f72a82c3d1/opentelemetry_proto-1.41.1.tar.gz", hash = "sha256:4b9d2eb631237ea43b80e16c073af438554e32bc7e9e3f8ca4a9582f900020e5", size = 45670, upload-time = "2026-04-24T13:15:49.768Z" } +sdist = { url = "https://files.pythonhosted.org/packages/b4/55/63eac3e1089b768ba014091fdd2ae8a9a440c821ef5e2b786909c94c8836/opentelemetry_proto-1.42.1.tar.gz", hash = "sha256:c6a51e6b4f05ae63565f3a113217f3d2bfaec68f78c02d7a6c85f9010d1cfca6", size = 45839, upload-time = "2026-05-21T16:33:03.937Z" } 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" }, + { url = "https://files.pythonhosted.org/packages/41/9d/171c02c84a76940b7e601805b3bb536985aded9168fbcc9ba52f0a730fa2/opentelemetry_proto-1.42.1-py3-none-any.whl", hash = "sha256:dedb74cba2886c59c7789b227a7a670613025a07489040050aedff6e5c0fb43c", size = 71782, upload-time = "2026-05-21T16:32:44.867Z" }, ] [[package]] name = "opentelemetry-sdk" -version = "1.41.1" +version = "1.42.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "opentelemetry-api" }, { name = "opentelemetry-semantic-conventions" }, { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/58/d0/54ee30dab82fb0acda23d144502771ff76ef8728459c83c3e89ef9fb1825/opentelemetry_sdk-1.41.1.tar.gz", hash = "sha256:724b615e1215b5aeacda0abb8a6a8922c9a1853068948bd0bd225a56d0c792e6", size = 230180, upload-time = "2026-04-24T13:15:50.991Z" } +sdist = { url = "https://files.pythonhosted.org/packages/40/f7/b390bd9bfd703bf98a68fea1f27786c6872331fd617164a54b8a59bdc008/opentelemetry_sdk-1.42.1.tar.gz", hash = "sha256:8c834e8f8c9ba4171d4ec843d0cb8a67e4c7394d3f9e9297e582cbd9456ddbf7", size = 239262, upload-time = "2026-05-21T16:33:04.641Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/b4/e7/a1420b698aad018e1cf60fdbaaccbe49021fb415e2a0d81c242f4c518f54/opentelemetry_sdk-1.41.1-py3-none-any.whl", hash = "sha256:edee379c126c1bce952b0c812b48fe8ff35b30df0eecf17e98afa4d598b7d85d", size = 180213, upload-time = "2026-04-24T13:15:33.767Z" }, + { url = "https://files.pythonhosted.org/packages/8f/6b/4287766cfbde577ae2272e8884abac325aeaac0d64f41c61d5b8cc595105/opentelemetry_sdk-1.42.1-py3-none-any.whl", hash = "sha256:083cd4bbfaa5aa7b5a9e552430d9951219967cfb27aa61feb13a77aba1fc839d", size = 170907, upload-time = "2026-05-21T16:32:45.894Z" }, ] [[package]] @@ -2969,15 +2958,15 @@ wheels = [ [[package]] name = "opentelemetry-semantic-conventions" -version = "0.62b1" +version = "0.63b1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "opentelemetry-api" }, { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/9e/de/911ac9e309052aca1b20b2d5549d3db45d1011e1a610e552c6ccdd1b64f8/opentelemetry_semantic_conventions-0.62b1.tar.gz", hash = "sha256:c5cc6e04a7f8c7cdd30be2ed81499fa4e75bfbd52c9cb70d40af1f9cd3619802", size = 145750, upload-time = "2026-04-24T13:15:52.236Z" } +sdist = { url = "https://files.pythonhosted.org/packages/93/99/4d7dd6df64795951413ce6e815f8cf1eb191daf7196ae86574589643d5f3/opentelemetry_semantic_conventions-0.63b1.tar.gz", hash = "sha256:3daf963611334b365e98a57438183eb012d3bfb40b2d931a9af613476b8701a9", size = 148340, upload-time = "2026-05-21T16:33:05.455Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/eb/a6/83dc2ab6fa397ee66fba04fe2e74bdf7be3b3870005359ceb7689103c058/opentelemetry_semantic_conventions-0.62b1-py3-none-any.whl", hash = "sha256:cf506938103d331fbb78eded0d9788095f7fd59016f2bda813c3324e5a74a93c", size = 231620, upload-time = "2026-04-24T13:15:35.454Z" }, + { url = "https://files.pythonhosted.org/packages/cb/7a/7fe66f5f3682b1dd47d88cc4e11f1c6c0966b737de2d16671146e23c39a5/opentelemetry_semantic_conventions-0.63b1-py3-none-any.whl", hash = "sha256:dfe5ef4dee82586b746f522b818ceb298d00b3d59f660042bd79404bff8d0682", size = 203713, upload-time = "2026-05-21T16:32:47.016Z" }, ] [[package]] @@ -3146,100 +3135,96 @@ wheels = [ [[package]] name = "pillow" -version = "12.2.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/8c/21/c2bcdd5906101a30244eaffc1b6e6ce71a31bd0742a01eb89e660ebfac2d/pillow-12.2.0.tar.gz", hash = "sha256:a830b1a40919539d07806aa58e1b114df53ddd43213d9c8b75847eee6c0182b5", size = 46987819, upload-time = "2026-04-01T14:46:17.687Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/3a/aa/d0b28e1c811cd4d5f5c2bfe2e022292bd255ae5744a3b9ac7d6c8f72dd75/pillow-12.2.0-cp310-cp310-macosx_10_10_x86_64.whl", hash = "sha256:a4e8f36e677d3336f35089648c8955c51c6d386a13cf6ee9c189c5f5bd713a9f", size = 5354355, upload-time = "2026-04-01T14:42:15.402Z" }, - { url = "https://files.pythonhosted.org/packages/27/8e/1d5b39b8ae2bd7650d0c7b6abb9602d16043ead9ebbfef4bc4047454da2a/pillow-12.2.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:2e589959f10d9824d39b350472b92f0ce3b443c0a3442ebf41c40cb8361c5b97", size = 4695871, upload-time = "2026-04-01T14:42:18.234Z" }, - { url = "https://files.pythonhosted.org/packages/f0/c5/dcb7a6ca6b7d3be41a76958e90018d56c8462166b3ef223150360850c8da/pillow-12.2.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:a52edc8bfff4429aaabdf4d9ee0daadbbf8562364f940937b941f87a4290f5ff", size = 6269734, upload-time = "2026-04-01T14:42:20.608Z" }, - { url = "https://files.pythonhosted.org/packages/ea/f1/aa1bb13b2f4eba914e9637893c73f2af8e48d7d4023b9d3750d4c5eb2d0c/pillow-12.2.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:975385f4776fafde056abb318f612ef6285b10a1f12b8570f3647ad0d74b48ec", size = 8076080, upload-time = "2026-04-01T14:42:23.095Z" }, - { url = "https://files.pythonhosted.org/packages/a1/2a/8c79d6a53169937784604a8ae8d77e45888c41537f7f6f65ed1f407fe66d/pillow-12.2.0-cp310-cp310-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:bd9c0c7a0c681a347b3194c500cb1e6ca9cab053ea4d82a5cf45b6b754560136", size = 6382236, upload-time = "2026-04-01T14:42:25.82Z" }, - { url = "https://files.pythonhosted.org/packages/b5/42/bbcb6051030e1e421d103ce7a8ecadf837aa2f39b8f82ef1a8d37c3d4ebc/pillow-12.2.0-cp310-cp310-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:88d387ff40b3ff7c274947ed3125dedf5262ec6919d83946753b5f3d7c67ea4c", size = 7070220, upload-time = "2026-04-01T14:42:28.68Z" }, - { url = "https://files.pythonhosted.org/packages/3f/e1/c2a7d6dd8cfa6b231227da096fd2d58754bab3603b9d73bf609d3c18b64f/pillow-12.2.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:51c4167c34b0d8ba05b547a3bb23578d0ba17b80a5593f93bd8ecb123dd336a3", size = 6493124, upload-time = "2026-04-01T14:42:31.579Z" }, - { url = "https://files.pythonhosted.org/packages/5f/41/7c8617da5d32e1d2f026e509484fdb6f3ad7efaef1749a0c1928adbb099e/pillow-12.2.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:34c0d99ecccea270c04882cb3b86e7b57296079c9a4aff88cb3b33563d95afaa", size = 7194324, upload-time = "2026-04-01T14:42:34.615Z" }, - { url = "https://files.pythonhosted.org/packages/2d/de/a777627e19fd6d62f84070ee1521adde5eeda4855b5cf60fe0b149118bca/pillow-12.2.0-cp310-cp310-win32.whl", hash = "sha256:b85f66ae9eb53e860a873b858b789217ba505e5e405a24b85c0464822fe88032", size = 6376363, upload-time = "2026-04-01T14:42:37.19Z" }, - { url = "https://files.pythonhosted.org/packages/e7/34/fc4cb5204896465842767b96d250c08410f01f2f28afc43b257de842eed5/pillow-12.2.0-cp310-cp310-win_amd64.whl", hash = "sha256:673aa32138f3e7531ccdbca7b3901dba9b70940a19ccecc6a37c77d5fdeb05b5", size = 7083523, upload-time = "2026-04-01T14:42:39.62Z" }, - { url = "https://files.pythonhosted.org/packages/2d/a0/32852d36bc7709f14dc3f64f929a275e958ad8c19a6deba9610d458e28b3/pillow-12.2.0-cp310-cp310-win_arm64.whl", hash = "sha256:3e080565d8d7c671db5802eedfb438e5565ffa40115216eabb8cd52d0ecce024", size = 2463318, upload-time = "2026-04-01T14:42:42.063Z" }, - { url = "https://files.pythonhosted.org/packages/68/e1/748f5663efe6edcfc4e74b2b93edfb9b8b99b67f21a854c3ae416500a2d9/pillow-12.2.0-cp311-cp311-macosx_10_10_x86_64.whl", hash = "sha256:8be29e59487a79f173507c30ddf57e733a357f67881430449bb32614075a40ab", size = 5354347, upload-time = "2026-04-01T14:42:44.255Z" }, - { url = "https://files.pythonhosted.org/packages/47/a1/d5ff69e747374c33a3b53b9f98cca7889fce1fd03d79cdc4e1bccc6c5a87/pillow-12.2.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:71cde9a1e1551df7d34a25462fc60325e8a11a82cc2e2f54578e5e9a1e153d65", size = 4695873, upload-time = "2026-04-01T14:42:46.452Z" }, - { url = "https://files.pythonhosted.org/packages/df/21/e3fbdf54408a973c7f7f89a23b2cb97a7ef30c61ab4142af31eee6aebc88/pillow-12.2.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:f490f9368b6fc026f021db16d7ec2fbf7d89e2edb42e8ec09d2c60505f5729c7", size = 6280168, upload-time = "2026-04-01T14:42:49.228Z" }, - { url = "https://files.pythonhosted.org/packages/d3/f1/00b7278c7dd52b17ad4329153748f87b6756ec195ff786c2bdf12518337d/pillow-12.2.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:8bd7903a5f2a4545f6fd5935c90058b89d30045568985a71c79f5fd6edf9b91e", size = 8088188, upload-time = "2026-04-01T14:42:51.735Z" }, - { url = "https://files.pythonhosted.org/packages/ad/cf/220a5994ef1b10e70e85748b75649d77d506499352be135a4989c957b701/pillow-12.2.0-cp311-cp311-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3997232e10d2920a68d25191392e3a4487d8183039e1c74c2297f00ed1c50705", size = 6394401, upload-time = "2026-04-01T14:42:54.343Z" }, - { url = "https://files.pythonhosted.org/packages/e9/bd/e51a61b1054f09437acfbc2ff9106c30d1eb76bc1453d428399946781253/pillow-12.2.0-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e74473c875d78b8e9d5da2a70f7099549f9eb37ded4e2f6a463e60125bccd176", size = 7079655, upload-time = "2026-04-01T14:42:56.954Z" }, - { url = "https://files.pythonhosted.org/packages/6b/3d/45132c57d5fb4b5744567c3817026480ac7fc3ce5d4c47902bc0e7f6f853/pillow-12.2.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:56a3f9c60a13133a98ecff6197af34d7824de9b7b38c3654861a725c970c197b", size = 6503105, upload-time = "2026-04-01T14:42:59.847Z" }, - { url = "https://files.pythonhosted.org/packages/7d/2e/9df2fc1e82097b1df3dce58dc43286aa01068e918c07574711fcc53e6fb4/pillow-12.2.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:90e6f81de50ad6b534cab6e5aef77ff6e37722b2f5d908686f4a5c9eba17a909", size = 7203402, upload-time = "2026-04-01T14:43:02.664Z" }, - { url = "https://files.pythonhosted.org/packages/bd/2e/2941e42858ebb67e50ae741473de81c2984e6eff7b397017623c676e2e8d/pillow-12.2.0-cp311-cp311-win32.whl", hash = "sha256:8c984051042858021a54926eb597d6ee3012393ce9c181814115df4c60b9a808", size = 6378149, upload-time = "2026-04-01T14:43:05.274Z" }, - { url = "https://files.pythonhosted.org/packages/69/42/836b6f3cd7f3e5fa10a1f1a5420447c17966044c8fbf589cc0452d5502db/pillow-12.2.0-cp311-cp311-win_amd64.whl", hash = "sha256:6e6b2a0c538fc200b38ff9eb6628228b77908c319a005815f2dde585a0664b60", size = 7082626, upload-time = "2026-04-01T14:43:08.557Z" }, - { url = "https://files.pythonhosted.org/packages/c2/88/549194b5d6f1f494b485e493edc6693c0a16f4ada488e5bd974ed1f42fad/pillow-12.2.0-cp311-cp311-win_arm64.whl", hash = "sha256:9a8a34cc89c67a65ea7437ce257cea81a9dad65b29805f3ecee8c8fe8ff25ffe", size = 2463531, upload-time = "2026-04-01T14:43:10.743Z" }, - { url = "https://files.pythonhosted.org/packages/58/be/7482c8a5ebebbc6470b3eb791812fff7d5e0216c2be3827b30b8bb6603ed/pillow-12.2.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:2d192a155bbcec180f8564f693e6fd9bccff5a7af9b32e2e4bf8c9c69dbad6b5", size = 5308279, upload-time = "2026-04-01T14:43:13.246Z" }, - { url = "https://files.pythonhosted.org/packages/d8/95/0a351b9289c2b5cbde0bacd4a83ebc44023e835490a727b2a3bd60ddc0f4/pillow-12.2.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:f3f40b3c5a968281fd507d519e444c35f0ff171237f4fdde090dd60699458421", size = 4695490, upload-time = "2026-04-01T14:43:15.584Z" }, - { url = "https://files.pythonhosted.org/packages/de/af/4e8e6869cbed569d43c416fad3dc4ecb944cb5d9492defaed89ddd6fe871/pillow-12.2.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:03e7e372d5240cc23e9f07deca4d775c0817bffc641b01e9c3af208dbd300987", size = 6284462, upload-time = "2026-04-01T14:43:18.268Z" }, - { url = "https://files.pythonhosted.org/packages/e9/9e/c05e19657fd57841e476be1ab46c4d501bffbadbafdc31a6d665f8b737b6/pillow-12.2.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:b86024e52a1b269467a802258c25521e6d742349d760728092e1bc2d135b4d76", size = 8094744, upload-time = "2026-04-01T14:43:20.716Z" }, - { url = "https://files.pythonhosted.org/packages/2b/54/1789c455ed10176066b6e7e6da1b01e50e36f94ba584dc68d9eebfe9156d/pillow-12.2.0-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:7371b48c4fa448d20d2714c9a1f775a81155050d383333e0a6c15b1123dda005", size = 6398371, upload-time = "2026-04-01T14:43:23.443Z" }, - { url = "https://files.pythonhosted.org/packages/43/e3/fdc657359e919462369869f1c9f0e973f353f9a9ee295a39b1fea8ee1a77/pillow-12.2.0-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:62f5409336adb0663b7caa0da5c7d9e7bdbaae9ce761d34669420c2a801b2780", size = 7087215, upload-time = "2026-04-01T14:43:26.758Z" }, - { url = "https://files.pythonhosted.org/packages/8b/f8/2f6825e441d5b1959d2ca5adec984210f1ec086435b0ed5f52c19b3b8a6e/pillow-12.2.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:01afa7cf67f74f09523699b4e88c73fb55c13346d212a59a2db1f86b0a63e8c5", size = 6509783, upload-time = "2026-04-01T14:43:29.56Z" }, - { url = "https://files.pythonhosted.org/packages/67/f9/029a27095ad20f854f9dba026b3ea6428548316e057e6fc3545409e86651/pillow-12.2.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:fc3d34d4a8fbec3e88a79b92e5465e0f9b842b628675850d860b8bd300b159f5", size = 7212112, upload-time = "2026-04-01T14:43:32.091Z" }, - { url = "https://files.pythonhosted.org/packages/be/42/025cfe05d1be22dbfdb4f264fe9de1ccda83f66e4fc3aac94748e784af04/pillow-12.2.0-cp312-cp312-win32.whl", hash = "sha256:58f62cc0f00fd29e64b29f4fd923ffdb3859c9f9e6105bfc37ba1d08994e8940", size = 6378489, upload-time = "2026-04-01T14:43:34.601Z" }, - { url = "https://files.pythonhosted.org/packages/5d/7b/25a221d2c761c6a8ae21bfa3874988ff2583e19cf8a27bf2fee358df7942/pillow-12.2.0-cp312-cp312-win_amd64.whl", hash = "sha256:7f84204dee22a783350679a0333981df803dac21a0190d706a50475e361c93f5", size = 7084129, upload-time = "2026-04-01T14:43:37.213Z" }, - { url = "https://files.pythonhosted.org/packages/10/e1/542a474affab20fd4a0f1836cb234e8493519da6b76899e30bcc5d990b8b/pillow-12.2.0-cp312-cp312-win_arm64.whl", hash = "sha256:af73337013e0b3b46f175e79492d96845b16126ddf79c438d7ea7ff27783a414", size = 2463612, upload-time = "2026-04-01T14:43:39.421Z" }, - { url = "https://files.pythonhosted.org/packages/4a/01/53d10cf0dbad820a8db274d259a37ba50b88b24768ddccec07355382d5ad/pillow-12.2.0-cp313-cp313-ios_13_0_arm64_iphoneos.whl", hash = "sha256:8297651f5b5679c19968abefd6bb84d95fe30ef712eb1b2d9b2d31ca61267f4c", size = 4100837, upload-time = "2026-04-01T14:43:41.506Z" }, - { url = "https://files.pythonhosted.org/packages/0f/98/f3a6657ecb698c937f6c76ee564882945f29b79bad496abcba0e84659ec5/pillow-12.2.0-cp313-cp313-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:50d8520da2a6ce0af445fa6d648c4273c3eeefbc32d7ce049f22e8b5c3daecc2", size = 4176528, upload-time = "2026-04-01T14:43:43.773Z" }, - { url = "https://files.pythonhosted.org/packages/69/bc/8986948f05e3ea490b8442ea1c1d4d990b24a7e43d8a51b2c7d8b1dced36/pillow-12.2.0-cp313-cp313-ios_13_0_x86_64_iphonesimulator.whl", hash = "sha256:766cef22385fa1091258ad7e6216792b156dc16d8d3fa607e7545b2b72061f1c", size = 3640401, upload-time = "2026-04-01T14:43:45.87Z" }, - { url = "https://files.pythonhosted.org/packages/34/46/6c717baadcd62bc8ed51d238d521ab651eaa74838291bda1f86fe1f864c9/pillow-12.2.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:5d2fd0fa6b5d9d1de415060363433f28da8b1526c1c129020435e186794b3795", size = 5308094, upload-time = "2026-04-01T14:43:48.438Z" }, - { url = "https://files.pythonhosted.org/packages/71/43/905a14a8b17fdb1ccb58d282454490662d2cb89a6bfec26af6d3520da5ec/pillow-12.2.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:56b25336f502b6ed02e889f4ece894a72612fe885889a6e8c4c80239ff6e5f5f", size = 4695402, upload-time = "2026-04-01T14:43:51.292Z" }, - { url = "https://files.pythonhosted.org/packages/73/dd/42107efcb777b16fa0393317eac58f5b5cf30e8392e266e76e51cff28c3d/pillow-12.2.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:f1c943e96e85df3d3478f7b691f229887e143f81fedab9b20205349ab04d73ed", size = 6280005, upload-time = "2026-04-01T14:43:54.242Z" }, - { url = "https://files.pythonhosted.org/packages/a8/68/b93e09e5e8549019e61acf49f65b1a8530765a7f812c77a7461bca7e4494/pillow-12.2.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:03f6fab9219220f041c74aeaa2939ff0062bd5c364ba9ce037197f4c6d498cd9", size = 8090669, upload-time = "2026-04-01T14:43:57.335Z" }, - { url = "https://files.pythonhosted.org/packages/4b/6e/3ccb54ce8ec4ddd1accd2d89004308b7b0b21c4ac3d20fa70af4760a4330/pillow-12.2.0-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5cdfebd752ec52bf5bb4e35d9c64b40826bc5b40a13df7c3cda20a2c03a0f5ed", size = 6395194, upload-time = "2026-04-01T14:43:59.864Z" }, - { url = "https://files.pythonhosted.org/packages/67/ee/21d4e8536afd1a328f01b359b4d3997b291ffd35a237c877b331c1c3b71c/pillow-12.2.0-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:eedf4b74eda2b5a4b2b2fb4c006d6295df3bf29e459e198c90ea48e130dc75c3", size = 7082423, upload-time = "2026-04-01T14:44:02.74Z" }, - { url = "https://files.pythonhosted.org/packages/78/5f/e9f86ab0146464e8c133fe85df987ed9e77e08b29d8d35f9f9f4d6f917ba/pillow-12.2.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:00a2865911330191c0b818c59103b58a5e697cae67042366970a6b6f1b20b7f9", size = 6505667, upload-time = "2026-04-01T14:44:05.381Z" }, - { url = "https://files.pythonhosted.org/packages/ed/1e/409007f56a2fdce61584fd3acbc2bbc259857d555196cedcadc68c015c82/pillow-12.2.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:1e1757442ed87f4912397c6d35a0db6a7b52592156014706f17658ff58bbf795", size = 7208580, upload-time = "2026-04-01T14:44:08.39Z" }, - { url = "https://files.pythonhosted.org/packages/23/c4/7349421080b12fb35414607b8871e9534546c128a11965fd4a7002ccfbee/pillow-12.2.0-cp313-cp313-win32.whl", hash = "sha256:144748b3af2d1b358d41286056d0003f47cb339b8c43a9ea42f5fea4d8c66b6e", size = 6375896, upload-time = "2026-04-01T14:44:11.197Z" }, - { url = "https://files.pythonhosted.org/packages/3f/82/8a3739a5e470b3c6cbb1d21d315800d8e16bff503d1f16b03a4ec3212786/pillow-12.2.0-cp313-cp313-win_amd64.whl", hash = "sha256:390ede346628ccc626e5730107cde16c42d3836b89662a115a921f28440e6a3b", size = 7081266, upload-time = "2026-04-01T14:44:13.947Z" }, - { url = "https://files.pythonhosted.org/packages/c3/25/f968f618a062574294592f668218f8af564830ccebdd1fa6200f598e65c5/pillow-12.2.0-cp313-cp313-win_arm64.whl", hash = "sha256:8023abc91fba39036dbce14a7d6535632f99c0b857807cbbbf21ecc9f4717f06", size = 2463508, upload-time = "2026-04-01T14:44:16.312Z" }, - { url = "https://files.pythonhosted.org/packages/4d/a4/b342930964e3cb4dce5038ae34b0eab4653334995336cd486c5a8c25a00c/pillow-12.2.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:042db20a421b9bafecc4b84a8b6e444686bd9d836c7fd24542db3e7df7baad9b", size = 5309927, upload-time = "2026-04-01T14:44:18.89Z" }, - { url = "https://files.pythonhosted.org/packages/9f/de/23198e0a65a9cf06123f5435a5d95cea62a635697f8f03d134d3f3a96151/pillow-12.2.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:dd025009355c926a84a612fecf58bb315a3f6814b17ead51a8e48d3823d9087f", size = 4698624, upload-time = "2026-04-01T14:44:21.115Z" }, - { url = "https://files.pythonhosted.org/packages/01/a6/1265e977f17d93ea37aa28aa81bad4fa597933879fac2520d24e021c8da3/pillow-12.2.0-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:88ddbc66737e277852913bd1e07c150cc7bb124539f94c4e2df5344494e0a612", size = 6321252, upload-time = "2026-04-01T14:44:23.663Z" }, - { url = "https://files.pythonhosted.org/packages/3c/83/5982eb4a285967baa70340320be9f88e57665a387e3a53a7f0db8231a0cd/pillow-12.2.0-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:d362d1878f00c142b7e1a16e6e5e780f02be8195123f164edf7eddd911eefe7c", size = 8126550, upload-time = "2026-04-01T14:44:26.772Z" }, - { url = "https://files.pythonhosted.org/packages/4e/48/6ffc514adce69f6050d0753b1a18fd920fce8cac87620d5a31231b04bfc5/pillow-12.2.0-cp313-cp313t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:2c727a6d53cb0018aadd8018c2b938376af27914a68a492f59dfcaca650d5eea", size = 6433114, upload-time = "2026-04-01T14:44:29.615Z" }, - { url = "https://files.pythonhosted.org/packages/36/a3/f9a77144231fb8d40ee27107b4463e205fa4677e2ca2548e14da5cf18dce/pillow-12.2.0-cp313-cp313t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:efd8c21c98c5cc60653bcb311bef2ce0401642b7ce9d09e03a7da87c878289d4", size = 7115667, upload-time = "2026-04-01T14:44:32.773Z" }, - { url = "https://files.pythonhosted.org/packages/c1/fc/ac4ee3041e7d5a565e1c4fd72a113f03b6394cc72ab7089d27608f8aaccb/pillow-12.2.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:9f08483a632889536b8139663db60f6724bfcb443c96f1b18855860d7d5c0fd4", size = 6538966, upload-time = "2026-04-01T14:44:35.252Z" }, - { url = "https://files.pythonhosted.org/packages/c0/a8/27fb307055087f3668f6d0a8ccb636e7431d56ed0750e07a60547b1e083e/pillow-12.2.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:dac8d77255a37e81a2efcbd1fc05f1c15ee82200e6c240d7e127e25e365c39ea", size = 7238241, upload-time = "2026-04-01T14:44:37.875Z" }, - { url = "https://files.pythonhosted.org/packages/ad/4b/926ab182c07fccae9fcb120043464e1ff1564775ec8864f21a0ebce6ac25/pillow-12.2.0-cp313-cp313t-win32.whl", hash = "sha256:ee3120ae9dff32f121610bb08e4313be87e03efeadfc6c0d18f89127e24d0c24", size = 6379592, upload-time = "2026-04-01T14:44:40.336Z" }, - { url = "https://files.pythonhosted.org/packages/c2/c4/f9e476451a098181b30050cc4c9a3556b64c02cf6497ea421ac047e89e4b/pillow-12.2.0-cp313-cp313t-win_amd64.whl", hash = "sha256:325ca0528c6788d2a6c3d40e3568639398137346c3d6e66bb61db96b96511c98", size = 7085542, upload-time = "2026-04-01T14:44:43.251Z" }, - { url = "https://files.pythonhosted.org/packages/00/a4/285f12aeacbe2d6dc36c407dfbbe9e96d4a80b0fb710a337f6d2ad978c75/pillow-12.2.0-cp313-cp313t-win_arm64.whl", hash = "sha256:2e5a76d03a6c6dcef67edabda7a52494afa4035021a79c8558e14af25313d453", size = 2465765, upload-time = "2026-04-01T14:44:45.996Z" }, - { url = "https://files.pythonhosted.org/packages/bf/98/4595daa2365416a86cb0d495248a393dfc84e96d62ad080c8546256cb9c0/pillow-12.2.0-cp314-cp314-ios_13_0_arm64_iphoneos.whl", hash = "sha256:3adc9215e8be0448ed6e814966ecf3d9952f0ea40eb14e89a102b87f450660d8", size = 4100848, upload-time = "2026-04-01T14:44:48.48Z" }, - { url = "https://files.pythonhosted.org/packages/0b/79/40184d464cf89f6663e18dfcf7ca21aae2491fff1a16127681bf1fa9b8cf/pillow-12.2.0-cp314-cp314-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:6a9adfc6d24b10f89588096364cc726174118c62130c817c2837c60cf08a392b", size = 4176515, upload-time = "2026-04-01T14:44:51.353Z" }, - { url = "https://files.pythonhosted.org/packages/b0/63/703f86fd4c422a9cf722833670f4f71418fb116b2853ff7da722ea43f184/pillow-12.2.0-cp314-cp314-ios_13_0_x86_64_iphonesimulator.whl", hash = "sha256:6a6e67ea2e6feda684ed370f9a1c52e7a243631c025ba42149a2cc5934dec295", size = 3640159, upload-time = "2026-04-01T14:44:53.588Z" }, - { url = "https://files.pythonhosted.org/packages/71/e0/fb22f797187d0be2270f83500aab851536101b254bfa1eae10795709d283/pillow-12.2.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:2bb4a8d594eacdfc59d9e5ad972aa8afdd48d584ffd5f13a937a664c3e7db0ed", size = 5312185, upload-time = "2026-04-01T14:44:56.039Z" }, - { url = "https://files.pythonhosted.org/packages/ba/8c/1a9e46228571de18f8e28f16fabdfc20212a5d019f3e3303452b3f0a580d/pillow-12.2.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:80b2da48193b2f33ed0c32c38140f9d3186583ce7d516526d462645fd98660ae", size = 4695386, upload-time = "2026-04-01T14:44:58.663Z" }, - { url = "https://files.pythonhosted.org/packages/70/62/98f6b7f0c88b9addd0e87c217ded307b36be024d4ff8869a812b241d1345/pillow-12.2.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:22db17c68434de69d8ecfc2fe821569195c0c373b25cccb9cbdacf2c6e53c601", size = 6280384, upload-time = "2026-04-01T14:45:01.5Z" }, - { url = "https://files.pythonhosted.org/packages/5e/03/688747d2e91cfbe0e64f316cd2e8005698f76ada3130d0194664174fa5de/pillow-12.2.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:7b14cc0106cd9aecda615dd6903840a058b4700fcb817687d0ee4fc8b6e389be", size = 8091599, upload-time = "2026-04-01T14:45:04.5Z" }, - { url = "https://files.pythonhosted.org/packages/f6/35/577e22b936fcdd66537329b33af0b4ccfefaeabd8aec04b266528cddb33c/pillow-12.2.0-cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8cbeb542b2ebc6fcdacabf8aca8c1a97c9b3ad3927d46b8723f9d4f033288a0f", size = 6396021, upload-time = "2026-04-01T14:45:07.117Z" }, - { url = "https://files.pythonhosted.org/packages/11/8d/d2532ad2a603ca2b93ad9f5135732124e57811d0168155852f37fbce2458/pillow-12.2.0-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4bfd07bc812fbd20395212969e41931001fd59eb55a60658b0e5710872e95286", size = 7083360, upload-time = "2026-04-01T14:45:09.763Z" }, - { url = "https://files.pythonhosted.org/packages/5e/26/d325f9f56c7e039034897e7380e9cc202b1e368bfd04d4cbe6a441f02885/pillow-12.2.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:9aba9a17b623ef750a4d11b742cbafffeb48a869821252b30ee21b5e91392c50", size = 6507628, upload-time = "2026-04-01T14:45:12.378Z" }, - { url = "https://files.pythonhosted.org/packages/5f/f7/769d5632ffb0988f1c5e7660b3e731e30f7f8ec4318e94d0a5d674eb65a4/pillow-12.2.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:deede7c263feb25dba4e82ea23058a235dcc2fe1f6021025dc71f2b618e26104", size = 7209321, upload-time = "2026-04-01T14:45:15.122Z" }, - { url = "https://files.pythonhosted.org/packages/6a/7a/c253e3c645cd47f1aceea6a8bacdba9991bf45bb7dfe927f7c893e89c93c/pillow-12.2.0-cp314-cp314-win32.whl", hash = "sha256:632ff19b2778e43162304d50da0181ce24ac5bb8180122cbe1bf4673428328c7", size = 6479723, upload-time = "2026-04-01T14:45:17.797Z" }, - { url = "https://files.pythonhosted.org/packages/cd/8b/601e6566b957ca50e28725cb6c355c59c2c8609751efbecd980db44e0349/pillow-12.2.0-cp314-cp314-win_amd64.whl", hash = "sha256:4e6c62e9d237e9b65fac06857d511e90d8461a32adcc1b9065ea0c0fa3a28150", size = 7217400, upload-time = "2026-04-01T14:45:20.529Z" }, - { url = "https://files.pythonhosted.org/packages/d6/94/220e46c73065c3e2951bb91c11a1fb636c8c9ad427ac3ce7d7f3359b9b2f/pillow-12.2.0-cp314-cp314-win_arm64.whl", hash = "sha256:b1c1fbd8a5a1af3412a0810d060a78b5136ec0836c8a4ef9aa11807f2a22f4e1", size = 2554835, upload-time = "2026-04-01T14:45:23.162Z" }, - { url = "https://files.pythonhosted.org/packages/b6/ab/1b426a3974cb0e7da5c29ccff4807871d48110933a57207b5a676cccc155/pillow-12.2.0-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:57850958fe9c751670e49b2cecf6294acc99e562531f4bd317fa5ddee2068463", size = 5314225, upload-time = "2026-04-01T14:45:25.637Z" }, - { url = "https://files.pythonhosted.org/packages/19/1e/dce46f371be2438eecfee2a1960ee2a243bbe5e961890146d2dee1ff0f12/pillow-12.2.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:d5d38f1411c0ed9f97bcb49b7bd59b6b7c314e0e27420e34d99d844b9ce3b6f3", size = 4698541, upload-time = "2026-04-01T14:45:28.355Z" }, - { url = "https://files.pythonhosted.org/packages/55/c3/7fbecf70adb3a0c33b77a300dc52e424dc22ad8cdc06557a2e49523b703d/pillow-12.2.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:5c0a9f29ca8e79f09de89293f82fc9b0270bb4af1d58bc98f540cc4aedf03166", size = 6322251, upload-time = "2026-04-01T14:45:30.924Z" }, - { url = "https://files.pythonhosted.org/packages/1c/3c/7fbc17cfb7e4fe0ef1642e0abc17fc6c94c9f7a16be41498e12e2ba60408/pillow-12.2.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:1610dd6c61621ae1cf811bef44d77e149ce3f7b95afe66a4512f8c59f25d9ebe", size = 8127807, upload-time = "2026-04-01T14:45:33.908Z" }, - { url = "https://files.pythonhosted.org/packages/ff/c3/a8ae14d6defd2e448493ff512fae903b1e9bd40b72efb6ec55ce0048c8ce/pillow-12.2.0-cp314-cp314t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0a34329707af4f73cf1782a36cd2289c0368880654a2c11f027bcee9052d35dd", size = 6433935, upload-time = "2026-04-01T14:45:36.623Z" }, - { url = "https://files.pythonhosted.org/packages/6e/32/2880fb3a074847ac159d8f902cb43278a61e85f681661e7419e6596803ed/pillow-12.2.0-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8e9c4f5b3c546fa3458a29ab22646c1c6c787ea8f5ef51300e5a60300736905e", size = 7116720, upload-time = "2026-04-01T14:45:39.258Z" }, - { url = "https://files.pythonhosted.org/packages/46/87/495cc9c30e0129501643f24d320076f4cc54f718341df18cc70ec94c44e1/pillow-12.2.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:fb043ee2f06b41473269765c2feae53fc2e2fbf96e5e22ca94fb5ad677856f06", size = 6540498, upload-time = "2026-04-01T14:45:41.879Z" }, - { url = "https://files.pythonhosted.org/packages/18/53/773f5edca692009d883a72211b60fdaf8871cbef075eaa9d577f0a2f989e/pillow-12.2.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:f278f034eb75b4e8a13a54a876cc4a5ab39173d2cdd93a638e1b467fc545ac43", size = 7239413, upload-time = "2026-04-01T14:45:44.705Z" }, - { url = "https://files.pythonhosted.org/packages/c9/e4/4b64a97d71b2a83158134abbb2f5bd3f8a2ea691361282f010998f339ec7/pillow-12.2.0-cp314-cp314t-win32.whl", hash = "sha256:6bb77b2dcb06b20f9f4b4a8454caa581cd4dd0643a08bacf821216a16d9c8354", size = 6482084, upload-time = "2026-04-01T14:45:47.568Z" }, - { url = "https://files.pythonhosted.org/packages/ba/13/306d275efd3a3453f72114b7431c877d10b1154014c1ebbedd067770d629/pillow-12.2.0-cp314-cp314t-win_amd64.whl", hash = "sha256:6562ace0d3fb5f20ed7290f1f929cae41b25ae29528f2af1722966a0a02e2aa1", size = 7225152, upload-time = "2026-04-01T14:45:50.032Z" }, - { url = "https://files.pythonhosted.org/packages/ff/6e/cf826fae916b8658848d7b9f38d88da6396895c676e8086fc0988073aaf8/pillow-12.2.0-cp314-cp314t-win_arm64.whl", hash = "sha256:aa88ccfe4e32d362816319ed727a004423aab09c5cea43c01a4b435643fa34eb", size = 2556579, upload-time = "2026-04-01T14:45:52.529Z" }, - { url = "https://files.pythonhosted.org/packages/4e/b7/2437044fb910f499610356d1352e3423753c98e34f915252aafecc64889f/pillow-12.2.0-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:0538bd5e05efec03ae613fd89c4ce0368ecd2ba239cc25b9f9be7ed426b0af1f", size = 5273969, upload-time = "2026-04-01T14:45:55.538Z" }, - { url = "https://files.pythonhosted.org/packages/f6/f4/8316e31de11b780f4ac08ef3654a75555e624a98db1056ecb2122d008d5a/pillow-12.2.0-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:394167b21da716608eac917c60aa9b969421b5dcbbe02ae7f013e7b85811c69d", size = 4659674, upload-time = "2026-04-01T14:45:58.093Z" }, - { url = "https://files.pythonhosted.org/packages/d4/37/664fca7201f8bb2aa1d20e2c3d5564a62e6ae5111741966c8319ca802361/pillow-12.2.0-pp311-pypy311_pp73-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:5d04bfa02cc2d23b497d1e90a0f927070043f6cbf303e738300532379a4b4e0f", size = 5288479, upload-time = "2026-04-01T14:46:01.141Z" }, - { url = "https://files.pythonhosted.org/packages/49/62/5b0ed78fce87346be7a5cfcfaaad91f6a1f98c26f86bdbafa2066c647ef6/pillow-12.2.0-pp311-pypy311_pp73-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:0c838a5125cee37e68edec915651521191cef1e6aa336b855f495766e77a366e", size = 7032230, upload-time = "2026-04-01T14:46:03.874Z" }, - { url = "https://files.pythonhosted.org/packages/c3/28/ec0fc38107fc32536908034e990c47914c57cd7c5a3ece4d8d8f7ffd7e27/pillow-12.2.0-pp311-pypy311_pp73-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4a6c9fa44005fa37a91ebfc95d081e8079757d2e904b27103f4f5fa6f0bf78c0", size = 5355404, upload-time = "2026-04-01T14:46:06.33Z" }, - { url = "https://files.pythonhosted.org/packages/5e/8b/51b0eddcfa2180d60e41f06bd6d0a62202b20b59c68f5a132e615b75aecf/pillow-12.2.0-pp311-pypy311_pp73-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:25373b66e0dd5905ed63fa3cae13c82fbddf3079f2c8bf15c6fb6a35586324c1", size = 6002215, upload-time = "2026-04-01T14:46:08.83Z" }, - { url = "https://files.pythonhosted.org/packages/bc/60/5382c03e1970de634027cee8e1b7d39776b778b81812aaf45b694dfe9e28/pillow-12.2.0-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:bfa9c230d2fe991bed5318a5f119bd6780cda2915cca595393649fc118ab895e", size = 7080946, upload-time = "2026-04-01T14:46:11.734Z" }, +version = "12.3.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/1c/3d/bb7fca845737cf9d7dbde16ed1843984665ff2e0a518f5db43e77ec540b9/pillow-12.3.0.tar.gz", hash = "sha256:3b8182a766685eaa002637e28b4ec8d6b18819a0c71f579bf0dbaa5830297cce", size = 47025035, upload-time = "2026-07-01T11:56:38.965Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/25/c2/669d88644cddb1485bd9534e63e8cf476c8e51cb3c3a1297677023505c0e/pillow-12.3.0-cp310-cp310-macosx_10_10_x86_64.whl", hash = "sha256:6c0016e7b354317c4e9e525b937ac8596c38d2d232b419529b9cd7a1cd46e39a", size = 5392418, upload-time = "2026-07-01T11:53:27.808Z" }, + { url = "https://files.pythonhosted.org/packages/6b/ba/3762f376a2948e3036488d773a146e0ae6ecc2ca03ac20e2615bd0b2ba02/pillow-12.3.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:bcc33feacfaefce60c12fd500a277533bdc02b10a19f7f6d348763d8140bbba7", size = 4785287, upload-time = "2026-07-01T11:53:29.761Z" }, + { url = "https://files.pythonhosted.org/packages/07/50/b5d688cc9c52d4482f3d5bcab6ce20bc2a74a85d2343841c907444a3be2c/pillow-12.3.0-cp310-cp310-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5594fc43d548a7ed94949d139aa1341b270f1863f11cfd37f5a6c8b778a6b67f", size = 6253754, upload-time = "2026-07-01T11:53:32.298Z" }, + { url = "https://files.pythonhosted.org/packages/4e/89/36f4cd76cf4baf05c50ababb976249153f18c959171c7f6ba09a6f217260/pillow-12.3.0-cp310-cp310-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f0606c8bf2cdefea14a43530f7657cbbb7ecf1c4222512492ef4a4434a9501ec", size = 6925605, upload-time = "2026-07-01T11:53:34.487Z" }, + { url = "https://files.pythonhosted.org/packages/eb/c0/4de58cf6633b9e3a6061ef4be6fb91fc3c90b812ece886f531e3c523d777/pillow-12.3.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:85f998ea1848bc6757289e739cfbdda3a04adfd58b02fc018ce54d754a5ce468", size = 6327788, upload-time = "2026-07-01T11:53:36.433Z" }, + { url = "https://files.pythonhosted.org/packages/87/3c/14d53682a19550dbbaf3b598f807d5457646c510805a44c7d7891cd1cd1a/pillow-12.3.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:25b9b82bb22e6e2b3cd07b39c68b7b862001226cb3dff7130d1cb914121b39ed", size = 7036288, upload-time = "2026-07-01T11:53:38.712Z" }, + { url = "https://files.pythonhosted.org/packages/38/1d/36279e3c77efe034e4cc2b0393ee74ffdb5a62391dacbf9b916154f5f0b8/pillow-12.3.0-cp310-cp310-win32.whl", hash = "sha256:37dc8f7bbb66efe481bb60defacef820c950c24713fb44962ed6aa2a50966de1", size = 6472396, upload-time = "2026-07-01T11:53:40.781Z" }, + { url = "https://files.pythonhosted.org/packages/48/7c/8fa0039574c476d7c6fa57dd7c32a130436877c6ec1e5ce1cc8ec44878c1/pillow-12.3.0-cp310-cp310-win_amd64.whl", hash = "sha256:300557495eb45ebb8aec96c2da9c4be642fbf7cd937278b4013ba894ea8eb0eb", size = 7226887, upload-time = "2026-07-01T11:53:42.764Z" }, + { url = "https://files.pythonhosted.org/packages/fa/17/e324be141d173c1c919428066c3259f21c1b8982e564e01a4a81e96dbdcf/pillow-12.3.0-cp310-cp310-win_arm64.whl", hash = "sha256:514435a37670e3e5e08f3945b68718b6ed329bb84367777e16f9f4dfe1e61a0f", size = 2568039, upload-time = "2026-07-01T11:53:45.372Z" }, + { url = "https://files.pythonhosted.org/packages/fb/c8/0a78b0e02d7ac54bc03e5321c9220da52f0c2ea83b21f7c40e7f3169c502/pillow-12.3.0-cp311-cp311-macosx_10_10_x86_64.whl", hash = "sha256:00808c5e14ef63ac5161091d242999076604ff74b883423a11e5d7bbb38bf756", size = 5392415, upload-time = "2026-07-01T11:53:47.162Z" }, + { url = "https://files.pythonhosted.org/packages/b2/5b/a02d30018abd97ced9f5a6c63d28597694a00d066516b9c1c6de45859fc9/pillow-12.3.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:37d6d0a00072fd2948eb22bce7e1475f34569d90c87c59f7a2ec59541b77f7a6", size = 4785266, upload-time = "2026-07-01T11:53:49.079Z" }, + { url = "https://files.pythonhosted.org/packages/c8/98/766667a4be768150a202836acd9fad19c06824ca86c4286d3cf6b274964e/pillow-12.3.0-cp311-cp311-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:bcb46e2f9feff8d06323983bd83ed00c201fdcab3d74973e7072a889b3979fcd", size = 6263814, upload-time = "2026-07-01T11:53:51.32Z" }, + { url = "https://files.pythonhosted.org/packages/3b/2d/ede717bc1144f63886c21fd349bb95860b0d1a21149ff16f2bb362b612b6/pillow-12.3.0-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:23d27a3e0307ec2244cc51e7287b919aa68d097504ebe19df4e76a98a3eea5bd", size = 6934408, upload-time = "2026-07-01T11:53:53.487Z" }, + { url = "https://files.pythonhosted.org/packages/a3/48/9c58b685e69d49c31af6c8eb9012055fab7e665785165c84796e2c73ce72/pillow-12.3.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:4f883547d4b7f0495ebe7056b0cc2aea76094e7a4abc8e933540f3271df27d9c", size = 6337160, upload-time = "2026-07-01T11:53:55.457Z" }, + { url = "https://files.pythonhosted.org/packages/ff/fa/dc2a5c0ba6df93f67c31d34b808b7ce440b40cdbf96f0b81cde1d1e6fa93/pillow-12.3.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:236ff70b9312fb68943c703aa842ca6a758abfa45ac187a5e7c1452e96ef72b5", size = 7045172, upload-time = "2026-07-01T11:53:57.736Z" }, + { url = "https://files.pythonhosted.org/packages/86/a5/444817a4d4c4c2417df00513086ca196f388d8f9ef40c2e4ccd1ad1af54b/pillow-12.3.0-cp311-cp311-win32.whl", hash = "sha256:10e41f0fbf1eec8cfd234b8fe17a4caac7c9d0db4c204d3c173a8f9f6ef3232b", size = 6472232, upload-time = "2026-07-01T11:53:59.767Z" }, + { url = "https://files.pythonhosted.org/packages/63/c6/4bad1b18d132a50b27e1365e1ab163616f7a5bb56d330f66f9d1d9d4f9d4/pillow-12.3.0-cp311-cp311-win_amd64.whl", hash = "sha256:8e95e1385e4998ae9694eeaa4730ba5457ff61185b3a55e2e7bea0880aef452a", size = 7233653, upload-time = "2026-07-01T11:54:02.066Z" }, + { url = "https://files.pythonhosted.org/packages/fd/16/00f91ab7760dc842f5aad55217e80fc4a7067a0604535249bc8a2d6d9870/pillow-12.3.0-cp311-cp311-win_arm64.whl", hash = "sha256:ebaea975e03d3141d9d3a507df75c9b3ec90fa9d2ffd07567b3a978d9d790b26", size = 2568195, upload-time = "2026-07-01T11:54:04.622Z" }, + { url = "https://files.pythonhosted.org/packages/37/bf/fb3ebff8ddcb76aac5a01389251bbbb9519922a9b520d8247c1ca864a25d/pillow-12.3.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:ba09209fbe443b4acccebe845d8a138b89a8f4fbaeedd44953490b5315d5e965", size = 5345969, upload-time = "2026-07-01T11:54:06.397Z" }, + { url = "https://files.pythonhosted.org/packages/d8/66/9a386a92561f402389a4fc70c18838bf6d35eb5eb5c6850b4b2dc64f5048/pillow-12.3.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ffd0c5368496f41b0944be820fcb7a838aa6e623d250b01acf2643939c3f99d7", size = 4780323, upload-time = "2026-07-01T11:54:09.351Z" }, + { url = "https://files.pythonhosted.org/packages/25/27/ac8f99618ffd3dde21db0f4d4b1d2ab00c0880595bfd17df103f7f39fd0c/pillow-12.3.0-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d9c7f76c0673154f044e9d78c8655fb4213f6ca31a836df48b40fe5d187717b9", size = 6266838, upload-time = "2026-07-01T11:54:11.71Z" }, + { url = "https://files.pythonhosted.org/packages/84/21/a35af28dcc61f37ed850a2d64c65c701321dfbf25085e469d5559360cbbf/pillow-12.3.0-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:78cb2c6865a35ab8ff8b75fd122f6033b92a62c82801110e48ddd6c936a45d91", size = 6940830, upload-time = "2026-07-01T11:54:13.732Z" }, + { url = "https://files.pythonhosted.org/packages/eb/51/8b08617af3ad95e33ce6d7dd2c99ed6c8298f7fb131636303956be022e25/pillow-12.3.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:e491916b378fba47242221bb9ead245211b70d504f495d105d17b14a24b4907c", size = 6344383, upload-time = "2026-07-01T11:54:15.756Z" }, + { url = "https://files.pythonhosted.org/packages/1d/72/cf78ac9780bb93c28328f408973845a309d4d145041665f734572ced1b52/pillow-12.3.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:0dd2064cbc55aaec028ef5fbb60fa47bb6c3e7918e07ff17935284b227a9d2df", size = 7052934, upload-time = "2026-07-01T11:54:17.721Z" }, + { url = "https://files.pythonhosted.org/packages/20/20/25e0f4dc178a6bc0696793720055519a0de89e7661dae886992decbd2f81/pillow-12.3.0-cp312-cp312-win32.whl", hash = "sha256:dbce0b29841537a2fa4a214c2bbf14de3587c9680caa9b4e217568472490b28f", size = 6472684, upload-time = "2026-07-01T11:54:19.839Z" }, + { url = "https://files.pythonhosted.org/packages/45/89/da2f7971a317f83d807fdd4065c0af40208e59e692cc43d315a71a0e96d1/pillow-12.3.0-cp312-cp312-win_amd64.whl", hash = "sha256:a2b55dd6b2a4c4b7d87ffa56bdb33fdc5fdb9a462173861a7bc097f17d91cb09", size = 7227137, upload-time = "2026-07-01T11:54:22.025Z" }, + { url = "https://files.pythonhosted.org/packages/de/47/4845a0a6c0dbf1db8456bd9fc791f13c5ced7ced20606d08a0aacfd25b49/pillow-12.3.0-cp312-cp312-win_arm64.whl", hash = "sha256:331b624368d4f1d069149002f25f44bc61c8919ce8ddb3c45bdad8f6e2d89510", size = 2568267, upload-time = "2026-07-01T11:54:24.051Z" }, + { url = "https://files.pythonhosted.org/packages/9d/ac/31fb64e1e7efb5a4b50cd3d92049ba89ac6e4d8d3bb6a74e15048ca3353e/pillow-12.3.0-cp313-cp313-ios_13_0_arm64_iphoneos.whl", hash = "sha256:21900ce7ba264168cd50defae43cd75d25c833ad4ad6e73ffc5596d12e25ac89", size = 4161684, upload-time = "2026-07-01T11:54:25.934Z" }, + { url = "https://files.pythonhosted.org/packages/87/b4/9805e23d2b4d77842b468513841fda254ee42f0289d25088340e4ff46e2d/pillow-12.3.0-cp313-cp313-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:4e8c2a84d977f50b9daed6eeaf3baef67d00d5d74d932288f02cb94518ee3ace", size = 4255487, upload-time = "2026-07-01T11:54:27.935Z" }, + { url = "https://files.pythonhosted.org/packages/df/39/ecf519435a200c693fe053a6ee4d835b41cf963a4dfc2551c4e637cb2a71/pillow-12.3.0-cp313-cp313-ios_13_0_x86_64_iphonesimulator.whl", hash = "sha256:ae26d61dfa7a47befdc7572b521024e8745f3d809bd95ca9505a7bba9ef849ec", size = 3696433, upload-time = "2026-07-01T11:54:29.813Z" }, + { url = "https://files.pythonhosted.org/packages/42/92/2fc3ffad878ae8dd5469ec1bc8eb83b71f48e13efdf68f02709003982a32/pillow-12.3.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:7a743ff716f746fc19a9557f60dab1600d4613255f8a7aeb3cdde4db7eb15a66", size = 5345889, upload-time = "2026-07-01T11:54:31.97Z" }, + { url = "https://files.pythonhosted.org/packages/10/76/8803c13605b763d33d156c4678fc77f8443389c0c51c8aef707bb02015f4/pillow-12.3.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:d69141514cc30b774ceea5e3ed3a6635c8d8a96edf664689b890f4089111fb35", size = 4780109, upload-time = "2026-07-01T11:54:34.026Z" }, + { url = "https://files.pythonhosted.org/packages/1f/01/e18aff37cb0b4aac47ac90f016d347a49aca667ef97f190b06ac2aabc928/pillow-12.3.0-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f7401aebd7f581d7f83a439d87d474999317ee099218e5ad25d125290990ba65", size = 6263736, upload-time = "2026-07-01T11:54:36.131Z" }, + { url = "https://files.pythonhosted.org/packages/f7/62/de5bdd77d935331f4f802edc11e4d82950f642caad6cb2f949837b8560e2/pillow-12.3.0-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0847a763afefb695bc912d7c131e7e0632d4edc1d8698f58ddabec8e46b8b6d3", size = 6937129, upload-time = "2026-07-01T11:54:38.216Z" }, + { url = "https://files.pythonhosted.org/packages/70/4d/105627a13300c5e0df1d174230b32fd1273062c96f7745fd552b945d1e1d/pillow-12.3.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:571b9fcb07b97ef3a492028fb3d2dc0993ca23a06138b0315286566d29ef718a", size = 6339562, upload-time = "2026-07-01T11:54:40.354Z" }, + { url = "https://files.pythonhosted.org/packages/6b/1d/f13de01a553988ab895ba1c722e06cf3144d4f57656fd5b81b6d881f1179/pillow-12.3.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:756c768d0c9c2955feb7a56c37ea24aea2e369f8d36a88da270b6a9f19e62b5e", size = 7049439, upload-time = "2026-07-01T11:54:42.489Z" }, + { url = "https://files.pythonhosted.org/packages/c9/f9/066794cca041b969964f779ee5fa66a9498bbf34248ac39c5d7954e4198f/pillow-12.3.0-cp313-cp313-win32.whl", hash = "sha256:a876864214e136f0eb367788dbd7df045f4806801518e2cfe9e13229cfe06d8f", size = 6473287, upload-time = "2026-07-01T11:54:44.9Z" }, + { url = "https://files.pythonhosted.org/packages/a6/9b/7a58e61d62be561da3a356fe2384d4059a6345fc130e23ef1c36a5b81d24/pillow-12.3.0-cp313-cp313-win_amd64.whl", hash = "sha256:1cca606cd25738df4ed873d5ad46bbdb3d83b5cbca291f6b4ff13a4df6b0bbe8", size = 7239691, upload-time = "2026-07-01T11:54:47.141Z" }, + { url = "https://files.pythonhosted.org/packages/aa/b0/c4ed4f0ef8f8fa5ee8351537db6650bb8189f7e118842978dd6589065692/pillow-12.3.0-cp313-cp313-win_arm64.whl", hash = "sha256:b629de27fda84b42cde7edef0d85f13b958b47f6e9bbcbba9b673c562a89bd8b", size = 2568185, upload-time = "2026-07-01T11:54:49.137Z" }, + { url = "https://files.pythonhosted.org/packages/dc/01/001f65b68192f0228cc1dbbc8d2530ab5d58b61037ba0587f946fea607cd/pillow-12.3.0-cp314-cp314-ios_13_0_arm64_iphoneos.whl", hash = "sha256:9cf95fe4d0f84c82d282745d9bb08ad9f926efa00be4697e767b814ce40d4330", size = 4161736, upload-time = "2026-07-01T11:54:51.156Z" }, + { url = "https://files.pythonhosted.org/packages/1a/d2/0219746d0fd16fc8a84498e79452375be3797d3ce4044596ce565164b84f/pillow-12.3.0-cp314-cp314-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:8728f216dcdb6e6d555cf971cb34076139ad74b31fc2c14da4fafc741c5f6217", size = 4255435, upload-time = "2026-07-01T11:54:53.414Z" }, + { url = "https://files.pythonhosted.org/packages/c8/02/8d0bc62ef0302318c46ff2a512822d2610e81c7aa46c9b3abe6cbaca5ad0/pillow-12.3.0-cp314-cp314-ios_13_0_x86_64_iphonesimulator.whl", hash = "sha256:a45650e8ce7fafffd731db8550230db6b0d306d181a90b67d3e6bca2f1990930", size = 3696262, upload-time = "2026-07-01T11:54:55.739Z" }, + { url = "https://files.pythonhosted.org/packages/85/e2/73c77d218410b14f5f2d565e8a998d5317b7b9c75368d29985139f7a46f0/pillow-12.3.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:ba54cfebe86920a559a7c4d6b9050791c20513650a1952ebe3368c7dc70306f8", size = 5350344, upload-time = "2026-07-01T11:54:57.657Z" }, + { url = "https://files.pythonhosted.org/packages/c7/da/32c752228ae345f489e3a42499d817b6c3996da7e8a3bc7a04fc806b243b/pillow-12.3.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:e158cb00350dc278f3b91551101aa7d12415a66ebf2c91d8d5ac14e56ddd3ad0", size = 4780131, upload-time = "2026-07-01T11:54:59.713Z" }, + { url = "https://files.pythonhosted.org/packages/b1/9d/8b2c807dbef61a5197c047afe99823787eb66f63daf9fb2432f91d6f0462/pillow-12.3.0-cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e9aeb04d6aef139de265b29683e119b638208f88cf73cdd1658aa07221165321", size = 6263757, upload-time = "2026-07-01T11:55:01.778Z" }, + { url = "https://files.pythonhosted.org/packages/5c/44/c85361f65dbe00eea8576ee467c768d25129989efb76e94f205e9ca9bb46/pillow-12.3.0-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:251bf95b67017e27b13d82f5b326234ca62d70f9cf4c2b9032de2358a3b12c7b", size = 6936962, upload-time = "2026-07-01T11:55:03.93Z" }, + { url = "https://files.pythonhosted.org/packages/18/7e/e483414b35800b86b6f08dbbc7803fb5cd52c4d6f897f47d53ea2c7e6f65/pillow-12.3.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:fe3cca2e4e8a592be0f269a1ca4835c25199d9f3ce815c8491048f785b0a0198", size = 6339171, upload-time = "2026-07-01T11:55:05.989Z" }, + { url = "https://files.pythonhosted.org/packages/f0/f4/68c491844841ede6bed70189546b3ee9731cf9f2cbad396faff5e1ccba45/pillow-12.3.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:23aceaa007d6172b02c277f0cd359c79492bbb14f7072b4ede9fbcaf20648130", size = 7048116, upload-time = "2026-07-01T11:55:08.131Z" }, + { url = "https://files.pythonhosted.org/packages/a3/34/77f3f793fed8efc7d243f21b33c5a3f0d1c97ee70346d3db855587e155ff/pillow-12.3.0-cp314-cp314-win32.whl", hash = "sha256:af8d94b0db561cf68b88a267c5c44b49e134f525d0dc2cb7ed413a66bc23559a", size = 6467209, upload-time = "2026-07-01T11:55:10.408Z" }, + { url = "https://files.pythonhosted.org/packages/f1/e0/492879f69d94f91f60fc8cd05ba03650e9520afebb2fb7aa12777d7c7f38/pillow-12.3.0-cp314-cp314-win_amd64.whl", hash = "sha256:fdafc9cce40277e0f7a0feabce0ee50dd2fa1800f3b38015e51296b5e814048d", size = 7237707, upload-time = "2026-07-01T11:55:12.745Z" }, + { url = "https://files.pythonhosted.org/packages/c9/ac/6b11f2875f1c2ac040d84e1bbf9cf22a88038f901ca1037898b280b38365/pillow-12.3.0-cp314-cp314-win_arm64.whl", hash = "sha256:e91206ee562682b51b98ef4b26a6ef48fd84e15fd4c4bc5ec768eb641d206838", size = 2565995, upload-time = "2026-07-01T11:55:14.736Z" }, + { url = "https://files.pythonhosted.org/packages/52/69/c2208e56af9bfc1913afb24020297a691eb1d4ef688474c8a04913f65e04/pillow-12.3.0-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:164b31cd1a0490ab6efae01aa5df49da7061be0af1b30e035b6e9a1bfe34ee6e", size = 5352503, upload-time = "2026-07-01T11:55:17.076Z" }, + { url = "https://files.pythonhosted.org/packages/07/70/e5686d753e898a45d778ff1718dba8516ead6ab6b95d85fc8c4b70650cf2/pillow-12.3.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:5afb51d599ea772b8365ae807ae557f18bccfe46ab261fd1c2a9ed700fc6eb17", size = 4782956, upload-time = "2026-07-01T11:55:19.448Z" }, + { url = "https://files.pythonhosted.org/packages/d5/37/25c6692f06927ee973ff18c8d9ee98ad0b4d84ee67a09610c2dd1447958e/pillow-12.3.0-cp314-cp314t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3edce1d53195db527e0191f84b71d02022de0540bf43a16ed734ed7537b07385", size = 6322855, upload-time = "2026-07-01T11:55:21.613Z" }, + { url = "https://files.pythonhosted.org/packages/cc/91/420637fcb8f1bc11029e403b4538e6694744428d8246118e45719f944556/pillow-12.3.0-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:bf16ba1b4d0b6b7c8e534936632270cf70eb00dbe09005bc345b2677b726855c", size = 6989642, upload-time = "2026-07-01T11:55:24.006Z" }, + { url = "https://files.pythonhosted.org/packages/10/08/b94d7811281ccf0d143a1cf768d1c49e1e54af63e7b708ab2ee3eb87face/pillow-12.3.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:24870b09b224f7ae3c39ed07d10e819d06f8720bc551847b1d623832b5b0e28d", size = 6391281, upload-time = "2026-07-01T11:55:26.252Z" }, + { url = "https://files.pythonhosted.org/packages/d2/87/24233f785f55474dc02ce3e739c5528a77e3a862e9333d1dd7a25cc31f70/pillow-12.3.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:30f2aa603c41533cc25c05acd0da21636e84a315768feb631c937177db558931", size = 7096716, upload-time = "2026-07-01T11:55:28.318Z" }, + { url = "https://files.pythonhosted.org/packages/23/26/fcb2f6e37175b04f53570b59937867e2b80ee1685e744023153028fc14f9/pillow-12.3.0-cp314-cp314t-win32.whl", hash = "sha256:4b0a7fe987b14c31ebda6083f74f22b561fd3739bc0ac51e019622e3d72668c7", size = 6474125, upload-time = "2026-07-01T11:55:30.956Z" }, + { url = "https://files.pythonhosted.org/packages/90/de/3634abee5f1c9e13c56787b7d5517b0ba8d6de51700b95578cf338349c9f/pillow-12.3.0-cp314-cp314t-win_amd64.whl", hash = "sha256:962864dc93511324d51ddbb5b9f8731bf71675b93ca612a07441896f4688fb8c", size = 7242939, upload-time = "2026-07-01T11:55:34.044Z" }, + { url = "https://files.pythonhosted.org/packages/ce/2a/fd13f8eb24de5714a6eb444a3d67e2842c6c576e159a43793adf23051351/pillow-12.3.0-cp314-cp314t-win_arm64.whl", hash = "sha256:0740a512dc522224c77d9aa5a8d70d8b7d73fb91f2c21125d8d025d3b8990e45", size = 2567506, upload-time = "2026-07-01T11:55:35.988Z" }, + { url = "https://files.pythonhosted.org/packages/5d/dc/8fdce34ec725a33c81c6ba122b904d6b9024e50ea9ac7bede62fab54506c/pillow-12.3.0-cp315-cp315-ios_13_0_arm64_iphoneos.whl", hash = "sha256:0feb2e9d6ad6c9e3c06effe9d00f3f1e618a6643273576b016f591e9315a7139", size = 4162063, upload-time = "2026-07-01T11:55:37.941Z" }, + { url = "https://files.pythonhosted.org/packages/76/66/2044b9a63d3b84ff048228dfcb7cd9bf0df983e8470971bf7d4c57b693de/pillow-12.3.0-cp315-cp315-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:9e881fca225083806662a5c43d627d215f258ff43c890f831966c7d7ba9c7402", size = 4255549, upload-time = "2026-07-01T11:55:40.022Z" }, + { url = "https://files.pythonhosted.org/packages/52/7e/1f67e6f4ece6b582ee4b539decbcc9f848dc245a93ed8cd7338bafef72f1/pillow-12.3.0-cp315-cp315-ios_13_0_x86_64_iphonesimulator.whl", hash = "sha256:4998562bf62a445225f22e07c896bb04b35b1b1f2eb6d760584c9c51d7a5f78c", size = 3696331, upload-time = "2026-07-01T11:55:41.98Z" }, + { url = "https://files.pythonhosted.org/packages/12/40/d306fc2c8e4d45d7f175c77edca7063be7b86fe7fe6e68f4353bf71d808c/pillow-12.3.0-cp315-cp315-macosx_10_15_x86_64.whl", hash = "sha256:dc624f6bc473dacdf7ef7eb8678d0d08edf15cd94fad6ae5c7d6cc67a4e4902f", size = 5350370, upload-time = "2026-07-01T11:55:44.028Z" }, + { url = "https://files.pythonhosted.org/packages/dd/44/668fb1437e8ce420f62d6106eb66e44a5971602a4d794615bdf79315d82d/pillow-12.3.0-cp315-cp315-macosx_11_0_arm64.whl", hash = "sha256:71d6097b330eea8fd15097780c8e89cb1a8ce7838669f48c5bacd6f663dd4701", size = 4780147, upload-time = "2026-07-01T11:55:46.073Z" }, + { url = "https://files.pythonhosted.org/packages/0c/08/93fa2e70e30a2d81547e481b6ee2bb9522117221fb1e0ce4b5df70967677/pillow-12.3.0-cp315-cp315-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:28ce87c5ab450a9dd970b52e5aca5fe63ed432d18a2eaddd1979a00a1ba24ace", size = 6273659, upload-time = "2026-07-01T11:55:48.264Z" }, + { url = "https://files.pythonhosted.org/packages/f8/6d/043e96ff814fc31a33077e4cba86082167db520c93632afdf2042febbb0c/pillow-12.3.0-cp315-cp315-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6b02afb9b97f65fbca5f31db6a2a3ba21aa93030225f150fa3f249717e938fb4", size = 6947439, upload-time = "2026-07-01T11:55:50.503Z" }, + { url = "https://files.pythonhosted.org/packages/af/92/ba71d2ee2ac0edf3fa33bd9d5ee9ee080da70b1766f3ca3934f9938ddac9/pillow-12.3.0-cp315-cp315-musllinux_1_2_aarch64.whl", hash = "sha256:1182d52bc2d5e5d7d0949503aa7e36d12f42205dc287e4883f407b1988820d39", size = 6353577, upload-time = "2026-07-01T11:55:52.697Z" }, + { url = "https://files.pythonhosted.org/packages/0f/ce/e63064e2122923ff687c8ad792d0d736a7b3920a56a46982e81a7fdd25d6/pillow-12.3.0-cp315-cp315-musllinux_1_2_x86_64.whl", hash = "sha256:e795b7eb908249c4e43c7c99fac7c2c75dab0c43566e37db472a355f63693d71", size = 7060394, upload-time = "2026-07-01T11:55:55.149Z" }, + { url = "https://files.pythonhosted.org/packages/54/76/a09cc3ccc8d773a7283d34c38bec1708f9e3cc932093cbc4c5e71ac4060b/pillow-12.3.0-cp315-cp315-win32.whl", hash = "sha256:57b3d78c95ba9059768b10e28b813002261d3f3dfc55cc48b0c988f625175827", size = 6467375, upload-time = "2026-07-01T11:55:57.769Z" }, + { url = "https://files.pythonhosted.org/packages/3e/03/1846c49ba3b1d5550392a4bbd06d6fb4578e1cd91a803198b5c90f5f7d53/pillow-12.3.0-cp315-cp315-win_amd64.whl", hash = "sha256:fa4ecea169a355be7a3ade2c783e2ed12f0e40d2c5621cda8b3297faf7fbb9f5", size = 7237048, upload-time = "2026-07-01T11:55:59.975Z" }, + { url = "https://files.pythonhosted.org/packages/fb/bb/89f35dcc79610423f9f195504d7def7f0d1416a711541b42867e25fe3412/pillow-12.3.0-cp315-cp315-win_arm64.whl", hash = "sha256:877c3f311ff35410f690861c4409e7ccbf0cd2f878e50628a28e5a0bb689e658", size = 2566006, upload-time = "2026-07-01T11:56:02.143Z" }, + { url = "https://files.pythonhosted.org/packages/30/88/707027ba09942dfa2c28759b5c222d769290a41c6d20ea60ec250801941f/pillow-12.3.0-cp315-cp315t-macosx_10_15_x86_64.whl", hash = "sha256:e9871b1ffbfa9656b60aeee92ed5136a5742696006fa322b29ea3d8da0ecc9cf", size = 5352509, upload-time = "2026-07-01T11:56:04.2Z" }, + { url = "https://files.pythonhosted.org/packages/b0/6d/00352fa25332c2569cd387851f568cc5a4b75a9adbfb37ac4fbce4c02eec/pillow-12.3.0-cp315-cp315t-macosx_11_0_arm64.whl", hash = "sha256:53aa02d20d10c3d814d536aa4e5ac9b84ca0ff5a88377963b085ad6822f93e64", size = 4783167, upload-time = "2026-07-01T11:56:06.631Z" }, + { url = "https://files.pythonhosted.org/packages/13/4f/9e049dfa21af7c22427275720e2490267ba8138120add5c4c574deb69782/pillow-12.3.0-cp315-cp315t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:446c34dcc4324b084a53b705127dc15717b22c5e140ae0a3c38349d4efec071e", size = 6329237, upload-time = "2026-07-01T11:56:08.868Z" }, + { url = "https://files.pythonhosted.org/packages/36/16/cf6eeaae8d0fce8dd390a33437cf68c5d5bd73834a2bc6e2f14efda0ab45/pillow-12.3.0-cp315-cp315t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:cf1845d02ad822a369a49f2bb9345b1614744267682e7a03527dc3bf6eea1777", size = 6997047, upload-time = "2026-07-01T11:56:11.379Z" }, + { url = "https://files.pythonhosted.org/packages/1e/69/dbf769bdd55f48bf5733cac28edc6364ffaa072ec9ba336266e4fe66be55/pillow-12.3.0-cp315-cp315t-musllinux_1_2_aarch64.whl", hash = "sha256:186941b6aef820ad110fb01fb06eb925374dc3a21b17e37ec9a53b250c6fe2d1", size = 6400440, upload-time = "2026-07-01T11:56:13.908Z" }, + { url = "https://files.pythonhosted.org/packages/a0/e1/ffc9cfc2eea0d178da8018e18e959301ad9d6bc9f3edb7181e748a474b97/pillow-12.3.0-cp315-cp315t-musllinux_1_2_x86_64.whl", hash = "sha256:f13c32a3abd6079a66d9526e18dad9b6d280384d49d7c54040cd57b6424041d9", size = 7105895, upload-time = "2026-07-01T11:56:16.575Z" }, + { url = "https://files.pythonhosted.org/packages/18/f0/a5595c1e8c3ae44b9828cb2f0fa8155e5095ef04d6327b8f61cf44a3df85/pillow-12.3.0-cp315-cp315t-win32.whl", hash = "sha256:1657923d2d45afb66526e5b933e5b3052e6bdea196c90d3abb2424e18c77dae8", size = 6474384, upload-time = "2026-07-01T11:56:18.855Z" }, + { url = "https://files.pythonhosted.org/packages/e4/04/62bcd9f844984c5938d3b05264a61d797a29d3e0812341a8204af70bbdee/pillow-12.3.0-cp315-cp315t-win_amd64.whl", hash = "sha256:8cd2f7bdda092d99c9fc2fb7391354f306d01443d22785d0cbfafa2e2c8bb418", size = 7243537, upload-time = "2026-07-01T11:56:21.214Z" }, + { url = "https://files.pythonhosted.org/packages/3d/68/1f3066acedf37673694a7141381d8f811ae97f30d34413d236abe7d489f1/pillow-12.3.0-cp315-cp315t-win_arm64.whl", hash = "sha256:06ff022112bc9cbf83b60f8e028d94ad87b60621706487e65f673de61610ab59", size = 2567491, upload-time = "2026-07-01T11:56:23.506Z" }, + { url = "https://files.pythonhosted.org/packages/75/18/2e8b40223153ccbc60df07f9e8928dc0c76202aa4e55ae9f53962b6510d6/pillow-12.3.0-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:b3c777e849237620b022f7f297dd67705f9f5cf1685f09f02e46f93e92725468", size = 5302510, upload-time = "2026-07-01T11:56:25.736Z" }, + { url = "https://files.pythonhosted.org/packages/46/3e/51fabf59d5ab801ceab709453d3ab6b180083496579549de4c45ced6528a/pillow-12.3.0-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:b343699e8308bdc51978310e1c959c584e7869cc8c40780058c87da7781a1e94", size = 4736058, upload-time = "2026-07-01T11:56:28.041Z" }, + { url = "https://files.pythonhosted.org/packages/bf/20/22fe9384b7949e25fb1293bcfc84fb82590ff4ea6b37c95b24d26d793d86/pillow-12.3.0-pp311-pypy311_pp73-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:fbd139c8447d25dd750ab79ee274cc5e1fe80fc56340ab10b18a195e1b6eca3e", size = 5237776, upload-time = "2026-07-01T11:56:30.263Z" }, + { url = "https://files.pythonhosted.org/packages/08/14/f6ba68107680ffa74b39985f3f30884e41318fbc4250caa423c79b4788bb/pillow-12.3.0-pp311-pypy311_pp73-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e7e480451b9fa137494bccd3a7d69adbe8ac65a87d97be61e11f1b1050a5bac3", size = 5860358, upload-time = "2026-07-01T11:56:32.68Z" }, + { url = "https://files.pythonhosted.org/packages/36/54/0169bc772ec491108b62f644f8ecf1fe5d8ae5ebafde2ee2142210166903/pillow-12.3.0-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:04f01d28a6aaff387bf842a13be313df23ba0597a44f1a976c9feb3c6ff4711a", size = 7231786, upload-time = "2026-07-01T11:56:35.046Z" }, ] [[package]] @@ -3449,11 +3434,11 @@ wheels = [ [[package]] name = "pyasn1" -version = "0.6.3" +version = "0.6.4" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/5c/5f/6583902b6f79b399c9c40674ac384fd9cd77805f9e6205075f828ef11fb2/pyasn1-0.6.3.tar.gz", hash = "sha256:697a8ecd6d98891189184ca1fa05d1bb00e2f84b5977c481452050549c8a72cf", size = 148685, upload-time = "2026-03-17T01:06:53.382Z" } +sdist = { url = "https://files.pythonhosted.org/packages/a4/9a/23310166d960def5897e91fe20e5b724601b02a22e84ba1f94232c0b7f67/pyasn1-0.6.4.tar.gz", hash = "sha256:9c447d8431c947fe4c8febc4ed9e760bc29011a5b01e5c74b67025bd9fb8ce81", size = 151262, upload-time = "2026-07-09T01:12:33.988Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/5d/a0/7d793dce3fa811fe047d6ae2431c672364b462850c6235ae306c0efd025f/pyasn1-0.6.3-py3-none-any.whl", hash = "sha256:a80184d120f0864a52a073acc6fc642847d0be408e7c7252f31390c0f4eadcde", size = 83997, upload-time = "2026-03-17T01:06:52.036Z" }, + { url = "https://files.pythonhosted.org/packages/9a/3b/6163796d69c3977d1e4287bea4a6979161cbbdd170ebb430511e8e1999ce/pyasn1-0.6.4-py3-none-any.whl", hash = "sha256:deda9277cfd454080ec40b207fb6df82206a3a2688735233cdcd8d3d565f088b", size = 84410, upload-time = "2026-07-09T01:12:32.92Z" }, ] [[package]] @@ -3610,16 +3595,16 @@ wheels = [ [[package]] name = "pydantic-settings" -version = "2.14.1" +version = "2.14.2" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "pydantic" }, { name = "python-dotenv" }, { name = "typing-inspection" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/07/60/1d1e59c9c90d54591469ada7d268251f71c24bdb765f1a8a832cee8c6653/pydantic_settings-2.14.1.tar.gz", hash = "sha256:e874d3bec7e787b0c9958277956ed9b4dd5de6a80e162188fdaff7c5e26fd5fa", size = 235551, upload-time = "2026-05-08T13:40:06.542Z" } +sdist = { url = "https://files.pythonhosted.org/packages/5c/b5/8f48e906c3e0205276e8bd8cb7512217a87b2685304d64be27cad5b3019f/pydantic_settings-2.14.2.tar.gz", hash = "sha256:c19dd64b19097f1de80184f0cc7b0272a13ae6e170cbf240a3e27e381ed14a5f", size = 237700, upload-time = "2026-06-19T13:44:56.324Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/ae/8d/f1af3832f5e6eb13ba94ee809e72b8ecb5eef226d27ee0bef7d963d943c7/pydantic_settings-2.14.1-py3-none-any.whl", hash = "sha256:6e3c7edfd8277687cdc598f56e5cff0e9bfff0910a3749deaa8d4401c3a2b9de", size = 60964, upload-time = "2026-05-08T13:40:04.958Z" }, + { url = "https://files.pythonhosted.org/packages/77/c1/6e422f34e569cf8e18df68d1939c81c099d2b61e4f7d9621c8a77560799c/pydantic_settings-2.14.2-py3-none-any.whl", hash = "sha256:a20c97b37910b6550d5ea50fbcc2d4187defe58cd57070b73863d069419c9440", size = 61715, upload-time = "2026-06-19T13:44:55.02Z" }, ] [[package]] @@ -3681,19 +3666,6 @@ crypto = [ { name = "cryptography" }, ] -[[package]] -name = "pyopenssl" -version = "26.3.0" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "cryptography" }, - { name = "typing-extensions", marker = "python_full_version < '3.13'" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/74/b7/da07bae88f5a9506b4def6f2f4903cf4c3b8831e560dba8fa18ca08f758f/pyopenssl-26.3.0.tar.gz", hash = "sha256:589de7fae1c9ea670d18422ed00fc04da787bbde8e1454aea872aa57b49ad341", size = 182024, upload-time = "2026-06-12T20:28:07.458Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/54/18/1dd71c9b43192ab83f1d531ad6002dc81108ac36c475f79fb7a295abe2f4/pyopenssl-26.3.0-py3-none-any.whl", hash = "sha256:46367f8f66b92271e6d218da9c87607e1ef5a0bc5c8dea5bb3db82f395c385a3", size = 56008, upload-time = "2026-06-12T20:28:05.999Z" }, -] - [[package]] name = "pyparsing" version = "3.3.2" @@ -3718,7 +3690,7 @@ wheels = [ [[package]] name = "pytest" -version = "9.0.3" +version = "9.1.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "colorama", marker = "sys_platform == 'win32'" }, @@ -3729,9 +3701,9 @@ dependencies = [ { name = "pygments" }, { name = "tomli", marker = "python_full_version < '3.11'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/7d/0d/549bd94f1a0a402dc8cf64563a117c0f3765662e2e668477624baeec44d5/pytest-9.0.3.tar.gz", hash = "sha256:b86ada508af81d19edeb213c681b1d48246c1a91d304c6c81a427674c17eb91c", size = 1572165, upload-time = "2026-04-07T17:16:18.027Z" } +sdist = { url = "https://files.pythonhosted.org/packages/e4/47/b9efed96c114afcfa3c9d3fe98a76a1d14c74a9e266d397cf6eb64be5e01/pytest-9.1.1.tar.gz", hash = "sha256:1088fbde8f2b49d95a549a195707afa7a76a3ce9bcadc26b6d71f0ffda5fe313", size = 1636369, upload-time = "2026-06-19T10:58:32.857Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/d4/24/a372aaf5c9b7208e7112038812994107bc65a84cd00e0354a88c2c77a617/pytest-9.0.3-py3-none-any.whl", hash = "sha256:2c5efc453d45394fdd706ade797c0a81091eccd1d6e4bccfcd476e2b8e0ab5d9", size = 375249, upload-time = "2026-04-07T17:16:16.13Z" }, + { url = "https://files.pythonhosted.org/packages/24/25/1de2678b631f5a49215c6c96fff41ba892b0a34df68d6d80292b1b48aa7f/pytest-9.1.1-py3-none-any.whl", hash = "sha256:37a86b45efb9a47a61a36449063e8e18d0cab3161329fc099eb21783169c4f0c", size = 386536, upload-time = "2026-06-19T10:58:31.347Z" }, ] [[package]] @@ -3787,15 +3759,15 @@ wheels = [ [[package]] name = "pytest-rerunfailures" -version = "16.3" +version = "16.4" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "packaging" }, { name = "pytest" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/4d/f0/74f8e685be7ecd1572c1256132f18fce3a665d7e07649a3f23b7eb2d3bec/pytest_rerunfailures-16.3.tar.gz", hash = "sha256:37c9b1231c8083e9f4e724f50f7a21241822f9516c15c700ebbf218d6452355c", size = 34148, upload-time = "2026-05-22T06:51:22.292Z" } +sdist = { url = "https://files.pythonhosted.org/packages/47/60/a90ca1cc6cffcb97b4260ed0ad2b7934b999d7c48abe4ea0840344862a3b/pytest_rerunfailures-16.4.tar.gz", hash = "sha256:8222d17c37eb7b9e4d6fc96a3c724ff4e1a5c97a5cc7cbb2c19e9282cfd21a11", size = 36635, upload-time = "2026-07-01T06:30:56.813Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/f8/98/58a71d68d3126d7f6a6ed1944c37ec207a4ff3dc66cad3bed7b59d38df61/pytest_rerunfailures-16.3-py3-none-any.whl", hash = "sha256:6bdfb8ffb46c46072e6c16bdedee38b6c13eac620d9415ed5b63152cbf283170", size = 15396, upload-time = "2026-05-22T06:51:20.547Z" }, + { url = "https://files.pythonhosted.org/packages/ce/93/3cdcc4033444e822e01b573414b03fd37fd5533070c750477b8f5fa5224b/pytest_rerunfailures-16.4-py3-none-any.whl", hash = "sha256:f69b5beb39622c90d1e44bd945d826eff6db545dcf0b68f52b7e4ad15eaf6d6c", size = 16955, upload-time = "2026-07-01T06:30:55.333Z" }, ] [[package]] @@ -3972,7 +3944,7 @@ source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "attrs" }, { name = "rpds-py", version = "0.30.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.11'" }, - { name = "rpds-py", version = "2026.5.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" }, + { name = "rpds-py", version = "2026.6.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" }, { name = "typing-extensions", marker = "python_full_version < '3.13'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/22/f5/df4e9027acead3ecc63e50fe1e36aca1523e1719559c499951bb4b53188f/referencing-0.37.0.tar.gz", hash = "sha256:44aefc3142c5b842538163acb373e24cce6632bd54bdb01b21ad5863489f50d8", size = 78036, upload-time = "2025-10-13T15:30:48.871Z" } @@ -3982,123 +3954,123 @@ wheels = [ [[package]] name = "regex" -version = "2026.5.9" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/dc/0e/49aee608ad09480e7fd276898c99ec6192985fa331abe4eb3a986094490b/regex-2026.5.9.tar.gz", hash = "sha256:a8234aa23ec39894bfe4a3f1b85616a7032481964a13ac6fc9f10de4f6fca270", size = 416074, upload-time = "2026-05-09T23:15:19.37Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/fe/ed/0ad2c8edf634918eb4484365d3819fa7bd7f58daf807fe7fb21812c316e5/regex-2026.5.9-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:a9e1328e17c84c1a5d22ec9f785ecef4a967fab9a42b6a8dc3bcbebd0a0c9e44", size = 489438, upload-time = "2026-05-09T23:11:29.374Z" }, - { url = "https://files.pythonhosted.org/packages/89/a9/4ed972ad263963b860b7c3e86e0e1bcc791def47b43b8c8efe57e710f139/regex-2026.5.9-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:bfe1ce50cbfb569d74e1e4337da6468961f31dbea55fd85aa5de59c0947a805a", size = 291270, upload-time = "2026-05-09T23:11:33.254Z" }, - { url = "https://files.pythonhosted.org/packages/16/81/075930d9fa28c4ea1f53398dd015ee7c882f623539759113cda1257f4b82/regex-2026.5.9-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:15ee42209947f4ca045412eae98416317238163618ace2a8e54f99586a466733", size = 289198, upload-time = "2026-05-09T23:11:35.769Z" }, - { url = "https://files.pythonhosted.org/packages/d4/c8/5cdfbf0b5dc6599e1b6131eff43262e5275d4ec3469ce10216061659aadb/regex-2026.5.9-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b4bb445ff3f725f59df8f6014edb547ee928ec7023a774f6a39a3f953038cbb2", size = 784765, upload-time = "2026-05-09T23:11:37.689Z" }, - { url = "https://files.pythonhosted.org/packages/cd/ca/ae5fd6edc59b7f84b904b31d6ec39a860cbcecd10f64bd5a062ca83a4864/regex-2026.5.9-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:446ddd671e43ab535810c4b21cff7104945c701d4a14d1e6d1cd6f4e445a8bea", size = 852115, upload-time = "2026-05-09T23:11:39.973Z" }, - { url = "https://files.pythonhosted.org/packages/f6/ce/a91cf555afb51f3b74a182e24ba073b91ea7bb64592fc4b315c111bb19fd/regex-2026.5.9-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:7b92817338591505f282cf3864c145244b1edcf5381d237038df955001091538", size = 899503, upload-time = "2026-05-09T23:11:42.48Z" }, - { url = "https://files.pythonhosted.org/packages/55/7f/725a0a2b245a4cf0c4bab29d0e97c74285d94136a65d1b55a6459a583502/regex-2026.5.9-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d6b8a143aca6c39b446ea8092cde25cc8fe9304d4f5fecfbc1a9dbb0282703c2", size = 794093, upload-time = "2026-05-09T23:11:44.681Z" }, - { url = "https://files.pythonhosted.org/packages/e3/2a/996efbd59ce6b5d4a09e3af6180ceb62af171f4a9a6fb557d2f0ae0d462b/regex-2026.5.9-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:0f03aa6898aaaac4592479821df16e68e8d0e29e903e65d8f2dfb2f19028a989", size = 786234, upload-time = "2026-05-09T23:11:46.882Z" }, - { url = "https://files.pythonhosted.org/packages/4b/0a/8731e8b8806174c9cdd5903f80a14990331c1f42fc4209b540952e9e010d/regex-2026.5.9-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:ed457d8e98ae812ed7732bef7bf78de78e834eae0372a74e23ca90ef21d910f9", size = 769895, upload-time = "2026-05-09T23:11:49.324Z" }, - { url = "https://files.pythonhosted.org/packages/9a/0b/932473194bd563f342a412ae2ffbbd6da608306a2bc4e99249a41c2b0b92/regex-2026.5.9-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:71b61c5bfe1c806332defc42ad6c780b3c55f661986d7f40283a3a88274b4c00", size = 774991, upload-time = "2026-05-09T23:11:51.261Z" }, - { url = "https://files.pythonhosted.org/packages/98/80/9523d196010031df25f7177ee0a467efbee436324038e5d99def17a57515/regex-2026.5.9-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:3b1e39888c5e0c7d92cea4fc777396c4a90363b05de75d02eb459a4752200808", size = 848790, upload-time = "2026-05-09T23:11:53.232Z" }, - { url = "https://files.pythonhosted.org/packages/3c/07/56987b35e89edf47e4a38cf2845aeee476bfa688a6bdbd3e820cda461dc1/regex-2026.5.9-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:6ba42b2e7e7f46cf68cc6a5ca36fa07959f9bbd9c6bdcc47b6ee76549a590248", size = 757679, upload-time = "2026-05-09T23:11:55.82Z" }, - { url = "https://files.pythonhosted.org/packages/04/2a/ff713fff0c566507c06a4ce2dc0ae8e7eeebc88811a95fc81cf1e7d534dd/regex-2026.5.9-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:c010eb8caca74bdb40c07498d7ece26b4428fd3f04aa8a72c9ac6f79e8faaac6", size = 837116, upload-time = "2026-05-09T23:11:57.934Z" }, - { url = "https://files.pythonhosted.org/packages/77/90/df6d982b03e3614785c6937ba51b57f6733d97d2ee1c9bc7531dbfab3a54/regex-2026.5.9-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:a6a563446a41adc451393dc6b8e6ad87979efaee3c8738690a8d1b08ebead1b4", size = 782081, upload-time = "2026-05-09T23:11:59.607Z" }, - { url = "https://files.pythonhosted.org/packages/c7/8a/4e88a5f7c3e98489aac4dd23142723d907b2a595b4a6abcbacabefeded09/regex-2026.5.9-cp310-cp310-win32.whl", hash = "sha256:954cc214c04663ee6d266fc61739cad83054683048de65c5bd1d640ad28098ac", size = 266247, upload-time = "2026-05-09T23:12:01.116Z" }, - { url = "https://files.pythonhosted.org/packages/6a/40/4b224cb0582b2dca1786726e6cdabe26abbf757d7f6718332f186da155d2/regex-2026.5.9-cp310-cp310-win_amd64.whl", hash = "sha256:b310768746dd314ea6e2ff4cc89ef215426813396ff4e94ee8e6f7096c8b6e03", size = 278416, upload-time = "2026-05-09T23:12:03.2Z" }, - { url = "https://files.pythonhosted.org/packages/12/4d/014fbe803204cab0947ee428f09f658a29632053dde1d3c6176bb4f0fd4c/regex-2026.5.9-cp310-cp310-win_arm64.whl", hash = "sha256:19c16ceb4a267a8789e25733e583983eeab9f0f8664e66b0bd1c5d21f14c2d4b", size = 270413, upload-time = "2026-05-09T23:12:04.649Z" }, - { url = "https://files.pythonhosted.org/packages/c2/dc/c1f2df4027e82fc54b5a473e4b250f5139faca49a0fbe29a48668d228f34/regex-2026.5.9-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:ccf5249114cc3e772ecdd88a98a86eca0fd74c61ce32a94743758c083fc05d48", size = 489445, upload-time = "2026-05-09T23:12:06.111Z" }, - { url = "https://files.pythonhosted.org/packages/03/d2/59f01110660081cce9c0bc30ebd0b5ee250dacf658e3248ed92f01e0e8ee/regex-2026.5.9-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:46f1326ca6e65b0879d23ca302c0f2415aad42ff0309b9c818e7949fe19a41d8", size = 291271, upload-time = "2026-05-09T23:12:07.731Z" }, - { url = "https://files.pythonhosted.org/packages/58/b6/14b2c84ff90ddb370c81d27503f4a0fcf071496416f4855f6cc8c5d81c35/regex-2026.5.9-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:ef31cbfe458e21c6122ba8150ff060e0c7789ed0d26eb423f25472584920b555", size = 289212, upload-time = "2026-05-09T23:12:09.266Z" }, - { url = "https://files.pythonhosted.org/packages/03/d0/4db86529117320de0c84afd90e70bb47434625875e34fcef9d8c127c5b16/regex-2026.5.9-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:992604d02e6d9c6d786c24a706a71ecffe1020fc1ef264044474cd81fa2c3919", size = 792310, upload-time = "2026-05-09T23:12:11.416Z" }, - { url = "https://files.pythonhosted.org/packages/07/78/fe4800cd322f862ecffd2d553409b20d80650e5ed71b9d178f853d020b82/regex-2026.5.9-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:c9411dd64ca95477225734a93dfc8583b51916b8d5942f99d6cac21e09965451", size = 861721, upload-time = "2026-05-09T23:12:13.681Z" }, - { url = "https://files.pythonhosted.org/packages/b5/d0/b3618a895dd8feb897c61bb2954edd265e1767d82a01d53065d5871127a3/regex-2026.5.9-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:3dd4a3ff360dfb836fecdb93a4598f9d6e2ac81e3e397125145c6221bf58cf4c", size = 906460, upload-time = "2026-05-09T23:12:15.443Z" }, - { url = "https://files.pythonhosted.org/packages/33/6f/1481597e859ef19508b345eec4afd1416ed6e6b459c75a64026ef193aecf/regex-2026.5.9-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:2a661a7d270a61f7cf460caee8b9fa2d5ef9e5c681234bcb9e0fe14f488e7dfc", size = 799843, upload-time = "2026-05-09T23:12:16.892Z" }, - { url = "https://files.pythonhosted.org/packages/73/59/955734c803f59108deccba3597ae440c76b62a652733c0006e6243758420/regex-2026.5.9-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:f079e50a0d3cc3cd5091fa9ff45869a2e6b2cd35895731edafb0327901a8d86d", size = 773610, upload-time = "2026-05-09T23:12:19.127Z" }, - { url = "https://files.pythonhosted.org/packages/68/8f/70c04a236d651c81881dac42ef8538bddda6121434509d0a22d9e601503b/regex-2026.5.9-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:4ebe8f0b5ec5a5024dc4a4c59f444c4e9afc5f2abdbb8962065b75d27fb971f9", size = 781645, upload-time = "2026-05-09T23:12:20.806Z" }, - { url = "https://files.pythonhosted.org/packages/1d/96/05c7434d88185e5d27fe54aeb74df86bd77cd79f52f0b4eae54faa8fea70/regex-2026.5.9-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:97cf3bc1b7d7d2306772ec07366c80d9df00ff79e79cea32898883a646d2fae2", size = 854473, upload-time = "2026-05-09T23:12:22.465Z" }, - { url = "https://files.pythonhosted.org/packages/4e/c1/6e3d8202d981f3117004bf341ee74893ba4ba8a9fbaf4b94615846550a08/regex-2026.5.9-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:0f9eede6a5cbdc02d4978090186390936e1776a7d1359b21e41014c609880bcf", size = 763311, upload-time = "2026-05-09T23:12:24.351Z" }, - { url = "https://files.pythonhosted.org/packages/93/c7/e7737f1526b3fb32bd4c337fd6c71c3ebb5c8296fc34d11197e0955d2e35/regex-2026.5.9-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:01f0f5f55f4b64dacec85dc116d3c05fd23ad3ff037bbc73a2085775953c2611", size = 844593, upload-time = "2026-05-09T23:12:26.341Z" }, - { url = "https://files.pythonhosted.org/packages/a5/27/0daffb1a535bb39f422c3d200f4ab023c71110ad66a32b366bee708baba0/regex-2026.5.9-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:1268eddd8486dc561d08eee1156e40aa3a8fe10f4bdec8fa653b455fcbffd12c", size = 789167, upload-time = "2026-05-09T23:12:27.975Z" }, - { url = "https://files.pythonhosted.org/packages/ce/fc/294fe4fac4f2ed67207b17471815870c1c45b3a489e08e0ac96daea16ef6/regex-2026.5.9-cp311-cp311-win32.whl", hash = "sha256:8676474c07469d6f33dd1085ca2cd45f65785f32518f2b20e36d9953ca07f994", size = 266249, upload-time = "2026-05-09T23:12:30.141Z" }, - { url = "https://files.pythonhosted.org/packages/d0/b0/8dce459f6245bcf8f6e9f23ac9569f1a0f15c131cc0745e82b43226204cf/regex-2026.5.9-cp311-cp311-win_amd64.whl", hash = "sha256:246de9d60aa3f8538b519834dd95cbf276ea263d6a7bd5a3666dc3fa0230505b", size = 278423, upload-time = "2026-05-09T23:12:31.676Z" }, - { url = "https://files.pythonhosted.org/packages/db/8d/f9aeff6ad63a3ef720386f2907e6d34a35a510a6e498ebad28b0fb3f6ab6/regex-2026.5.9-cp311-cp311-win_arm64.whl", hash = "sha256:d726ca3f0d76969bf1e8e477d160d3d666bbf999f6860bd314889e5345782046", size = 270420, upload-time = "2026-05-09T23:12:33.194Z" }, - { url = "https://files.pythonhosted.org/packages/50/9b/6550044bc44e17c84d312c031c2ec42fbdb6a4ec4e29093be3a172d08772/regex-2026.5.9-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:57eeeb05db7979413dec5438f2db21d7ecbba787cde7a711df1a6f6df672aa06", size = 490451, upload-time = "2026-05-09T23:12:34.72Z" }, - { url = "https://files.pythonhosted.org/packages/1e/95/fc7ba4303b5a0f92446a12ee6778ef2c6c799233f5060042a31bf390cfe9/regex-2026.5.9-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:398c521292f4c7fb807001dcd54694d3a1fcafc179a36ad9cc56f98df85930b6", size = 292112, upload-time = "2026-05-09T23:12:36.285Z" }, - { url = "https://files.pythonhosted.org/packages/54/4b/ee27938d1b2c443e89a9a10e00d2d19aa5ee300cd3d61140644e93bb083e/regex-2026.5.9-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:f7a7c26137296beba7784de6eba69c6a93a63ccebc385e4962fe67e267a91225", size = 289599, upload-time = "2026-05-09T23:12:38.089Z" }, - { url = "https://files.pythonhosted.org/packages/d8/dd/ba103dc19614e25f3880800ca67ce093d6e21b325d72b8383c7bf906e9fa/regex-2026.5.9-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6441cc660d76107934a09c22167200839a0e89604a6297f78a974e66e931d2c0", size = 796732, upload-time = "2026-05-09T23:12:40.062Z" }, - { url = "https://files.pythonhosted.org/packages/cf/e7/f035b4fd858b050b0080bf302968dc0f59ba34e391872d54936758e6844e/regex-2026.5.9-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:91328f1c23d47595ca3ef0a7557fa129c5a23404b775c770697d2f35b33e0107", size = 865440, upload-time = "2026-05-09T23:12:42.059Z" }, - { url = "https://files.pythonhosted.org/packages/0a/51/8cd301ecc899aea28124357f729f4272f44de7806fc7ca02490bfbe253e8/regex-2026.5.9-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:93a7860539414dddaefba2b40f8771765ae17949d4c7182b876ce429e11a8309", size = 912329, upload-time = "2026-05-09T23:12:44.373Z" }, - { url = "https://files.pythonhosted.org/packages/cc/1e/3fbe2fa1e8cebd62f3bb7d3321cff1640aca2e240b51d9bd624aad949260/regex-2026.5.9-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:dd2810d22146b6d838acc5ec15602cb6b47920aa4e33015df3868eedfd20bab8", size = 801239, upload-time = "2026-05-09T23:12:46.268Z" }, - { url = "https://files.pythonhosted.org/packages/17/2f/6f6008682bf2cf98040a0d3153a8e557b6ab728d7713d045cee4ce544ab8/regex-2026.5.9-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:daff2bdbaf1d23e52fdff7c0b7bc2048b68f978df6a4d107ac981f94caef2e66", size = 777054, upload-time = "2026-05-09T23:12:48.051Z" }, - { url = "https://files.pythonhosted.org/packages/19/2b/eee0d20a6842ba04df4b8847a920b57ef56853f14ef85405473e586b605a/regex-2026.5.9-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:4eeb011098fcb77af513dcef521a3dbecbf8849b1e38940759d293b7a93f5026", size = 785098, upload-time = "2026-05-09T23:12:49.851Z" }, - { url = "https://files.pythonhosted.org/packages/4a/98/6fc1e6410feefb92159edaed5041992bfe390e8d26c721865434acbca558/regex-2026.5.9-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:ea9c8ecfa1b73c73b626534d6626e5340d429630943672b8480724f44e84b962", size = 860095, upload-time = "2026-05-09T23:12:51.666Z" }, - { url = "https://files.pythonhosted.org/packages/18/a3/bd855e0f2cb1a978ecf6fa6bb69632dd9c3f6ea3b81cde62fde14c9daec7/regex-2026.5.9-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:cd2846168eb9ee3c513902bc8225409cb1caab31d04728b145171fa1625d9621", size = 765762, upload-time = "2026-05-09T23:12:53.413Z" }, - { url = "https://files.pythonhosted.org/packages/dc/66/0ae8c092e60b14c79d24f8e0b7f0aea5bfbffdcab00b5483d13404d3c3a5/regex-2026.5.9-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:39617fb0cde9c0e6306dc70e3bfc096f3da793219879f7ae7aa341a69fbdcf6d", size = 852100, upload-time = "2026-05-09T23:12:55.256Z" }, - { url = "https://files.pythonhosted.org/packages/21/de/8dfde60fc1b21c946a893ba273403b72617edb261370cb1087099a83f088/regex-2026.5.9-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:fd03c4f0e33280d15cae17159b899245d6b7c53d21def19b263b39655061f5ce", size = 789479, upload-time = "2026-05-09T23:12:57.573Z" }, - { url = "https://files.pythonhosted.org/packages/c3/1c/bdcc98f9a4af4fdd166c74941174619ccff4726d3ce32faa8e9a2ecd38dd/regex-2026.5.9-cp312-cp312-win32.whl", hash = "sha256:164eba9b755ea6f244b0d881196fbc1fac09714e9782c9e2732b813142033c8e", size = 266699, upload-time = "2026-05-09T23:12:59.14Z" }, - { url = "https://files.pythonhosted.org/packages/78/87/240d36864f9e48ace85f72e79ced97ceb7f27ce87739a947dcb834b4e6bc/regex-2026.5.9-cp312-cp312-win_amd64.whl", hash = "sha256:86f40a5d6444db30a125c9c9177e6b25dad981cbc37451fd838f145e6edac92e", size = 277783, upload-time = "2026-05-09T23:13:00.789Z" }, - { url = "https://files.pythonhosted.org/packages/4f/b5/7b30f312b0669dff5beebe5b0989dc2d1a312b1a44fab852199c387a5b96/regex-2026.5.9-cp312-cp312-win_arm64.whl", hash = "sha256:96f5f58b54a063d7ea9dca08e1cf57bfe10499c4d579ee672da284f57f5f0070", size = 270513, upload-time = "2026-05-09T23:13:02.426Z" }, - { url = "https://files.pythonhosted.org/packages/aa/da/797e91ecec6f84135da778ddce78c20e0af5d2a15c26f87a81bc3eadb6db/regex-2026.5.9-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:d626b84406444b165fc0ba981604edea39f0588ff1f92baa23fe50799ea9afdb", size = 490303, upload-time = "2026-05-09T23:13:04.382Z" }, - { url = "https://files.pythonhosted.org/packages/44/da/bf30abaaa737b58f4a4b8c4a03659e02fd92092c822e0197ed9e0daab917/regex-2026.5.9-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:d7bdc0ab8f3dd7e1b4f9ab88634e13374669db86bb3c72e8292f07ae313f539f", size = 292019, upload-time = "2026-05-09T23:13:06.022Z" }, - { url = "https://files.pythonhosted.org/packages/2d/e7/d0eaf5713828417b9e5648cf81fa9bacd4961f6ab98c380c2034f8716e35/regex-2026.5.9-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:a8820737949116ffff55fe18f9fc644530063ba6ebfcb8314239416e78f1347c", size = 289468, upload-time = "2026-05-09T23:13:08.214Z" }, - { url = "https://files.pythonhosted.org/packages/d3/9b/b3fdd62b003baa1a9b593cd8c8699c9651c2e80cc21a5c715707983c42d7/regex-2026.5.9-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:aa0fbdbac82cb3e4450d0ccde7d7a35607f4cb2dd9fba4b8b69bfaf8c9fa6aed", size = 796749, upload-time = "2026-05-09T23:13:10.573Z" }, - { url = "https://files.pythonhosted.org/packages/d4/30/66ab84588765f5b4b271a9ca09ef7ce2b87caa95176ec3d2ad65d7bc4902/regex-2026.5.9-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:57e8915c7986aa33d25e4d3629cef711cd2863f2961b10409f0c04cb8b7d9020", size = 865445, upload-time = "2026-05-09T23:13:12.523Z" }, - { url = "https://files.pythonhosted.org/packages/1a/89/f05169e8588aac365f35ffc7f3bc3184f095ef4cfded7cfaa3c7fd5dbd89/regex-2026.5.9-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:508f56a89ba9cb26e4168cbc37dbd60a28d82430a9e18ad1d25fe0883c314ca2", size = 912322, upload-time = "2026-05-09T23:13:14.281Z" }, - { url = "https://files.pythonhosted.org/packages/30/e1/c93444052cf41581f3c884ab3fb5823daf0992f11cd4388d4275ca610558/regex-2026.5.9-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b6d189041f15691cfa2b6c4290448ec221244d225b3f5fe9e7771b34ffcdf6e2", size = 801269, upload-time = "2026-05-09T23:13:16.569Z" }, - { url = "https://files.pythonhosted.org/packages/50/fe/0cf96b882f540e62e8b9956599798203d599c44cf4c77917ca27400ff69b/regex-2026.5.9-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:e82db382b44d0111b22601c509c89f64434816c9e0eef9d1989cda8cc6ff1c04", size = 777085, upload-time = "2026-05-09T23:13:18.675Z" }, - { url = "https://files.pythonhosted.org/packages/23/5c/d78d4924e7fc875557b9e9b768423925fdfaac5549d06da7810019a9bd26/regex-2026.5.9-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:2acfb48634f64996b57f90f39afa692ff362162722581921fe92239a59960f3c", size = 785153, upload-time = "2026-05-09T23:13:20.525Z" }, - { url = "https://files.pythonhosted.org/packages/bf/e0/5214774090e7b4524dcea3e3c4aa74141d43043f8beb49c1599db1c8b53a/regex-2026.5.9-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:d29eebfc9525db68cad3c97eedd7f754fa265aa5cd0cf4f863b2421e1b48fc9f", size = 860164, upload-time = "2026-05-09T23:13:22.263Z" }, - { url = "https://files.pythonhosted.org/packages/6e/e1/4a57a83350319b1271f0d7a249b8672513ed928b237a741631270de6caea/regex-2026.5.9-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:debb893095e944091c16e641a6e33c1b0f4cb61ab945ec5afbf53ce7068834d8", size = 765731, upload-time = "2026-05-09T23:13:24.277Z" }, - { url = "https://files.pythonhosted.org/packages/12/f4/499e74a20c156fc75836ee04a72a38d1a063978f600937f9760467beb1b0/regex-2026.5.9-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:d659eee77986549c9ea45b861c7567e44d6287c3dc9a4565478853f7b9fe2ff6", size = 852062, upload-time = "2026-05-09T23:13:26.125Z" }, - { url = "https://files.pythonhosted.org/packages/5b/92/7eebc0d0a01e78629695f342ba17e0deaff8fb45e79cc0d7b98287da6e3e/regex-2026.5.9-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:2efa205e6d98b24d1f3ab395c11aa15cdf10935bca283d0285e0499c284fba21", size = 789577, upload-time = "2026-05-09T23:13:27.814Z" }, - { url = "https://files.pythonhosted.org/packages/05/a4/018e71f7d2ad48c1ebe6d3ae0026f9b7cb4802fd15c7cc02fdf724355102/regex-2026.5.9-cp313-cp313-win32.whl", hash = "sha256:f3844f134e834076677dd369976e9f5068679fcb8e50102fdf6b7ac96a3ec127", size = 266691, upload-time = "2026-05-09T23:13:29.549Z" }, - { url = "https://files.pythonhosted.org/packages/e6/1d/861a93719fb9ee7dbfc3761b3797b7a3e112a5d42c6129459d2d741be9b5/regex-2026.5.9-cp313-cp313-win_amd64.whl", hash = "sha256:3527bb4942d2c14552155406cdedd906567456821848aed1cb4933a391bf5eca", size = 277747, upload-time = "2026-05-09T23:13:31.859Z" }, - { url = "https://files.pythonhosted.org/packages/d9/c6/0a2436ae4da1ba76e51cb98943c6838a9a721faa40ebe2dce07694ae34e3/regex-2026.5.9-cp313-cp313-win_arm64.whl", hash = "sha256:56a33f191f17d8c417f99945ebdc1e691d3af9605d86ec68c7e54a57e3e17af6", size = 270500, upload-time = "2026-05-09T23:13:33.525Z" }, - { url = "https://files.pythonhosted.org/packages/e8/e9/d21346f7b60ed58789371358ed66b09d00f832e1bd7c06e55d9da5679882/regex-2026.5.9-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:01f28d868834624c934b8d2e0aa1c8341337e37831f4a012f18a5afcba4cbaf3", size = 494172, upload-time = "2026-05-09T23:13:35.935Z" }, - { url = "https://files.pythonhosted.org/packages/c4/43/fd1177a2032037c681baecdb3422ee4e1424aec4e4f470ef47793d325274/regex-2026.5.9-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:48036f6374aaa79eb3b754ec29c61d1c6b1606749d705a13f8854fa2539671f6", size = 293952, upload-time = "2026-05-09T23:13:38.307Z" }, - { url = "https://files.pythonhosted.org/packages/f2/7d/9fbf919768368d3f8a4f6c692cf2aa61e482b2b81ec6a298ace4cbf02480/regex-2026.5.9-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:b96350aa424e79d4fd6b567b344dcbe2b2d6bfc48dfe7717587e1fa6d43da6ff", size = 292314, upload-time = "2026-05-09T23:13:40.353Z" }, - { url = "https://files.pythonhosted.org/packages/e2/6c/e41bfeecb589716843e7c4df09ba46ff2a42961457afece19059d85caeef/regex-2026.5.9-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8f3af7a4903c5c04a11a196a5aa75cdd7dd3f8508132f9fb3259d9f5908e3b88", size = 811681, upload-time = "2026-05-09T23:13:42.543Z" }, - { url = "https://files.pythonhosted.org/packages/87/83/a5c1c525fba0aa656e88ad0face0b1829788ef4c2fb6b26df58aa1151b84/regex-2026.5.9-cp313-cp313t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:7e87577720152d2caae19fe2baaf1f8d5ca12091e9e229f03915c37d1e4b9178", size = 871135, upload-time = "2026-05-09T23:13:44.326Z" }, - { url = "https://files.pythonhosted.org/packages/18/d4/80882e799e440dd878b0979cbebf8fa4d54624a332c83037c7a701649e3f/regex-2026.5.9-cp313-cp313t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:c8b9b9d294cfea3cd19c718ade7cc93492b2c4991abd9a68d0b3477ae6d8e100", size = 917265, upload-time = "2026-05-09T23:13:47.295Z" }, - { url = "https://files.pythonhosted.org/packages/ae/ff/8db60211e2286e396aad7dc7725356c502bff0901ea05bd6cdc2e1a042b9/regex-2026.5.9-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:728d8bfd28a8845c8b6bc5dc7ce010453d206396786c0765c2740cb65f37791e", size = 816311, upload-time = "2026-05-09T23:13:49.885Z" }, - { url = "https://files.pythonhosted.org/packages/4c/47/742ef579c61730f8d268e5cf1f9ce0e37e2ea041ad0f5644724f2378e463/regex-2026.5.9-cp313-cp313t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:7e30b874d341fac767d7df5a0870540541c2c054b80cfaac116e8d367a8a7ff2", size = 785498, upload-time = "2026-05-09T23:13:52.25Z" }, - { url = "https://files.pythonhosted.org/packages/7f/ab/cb0999802dcb0fb95b1ab005e8d4163d8afdd67efc2cb6b6630ac13f8cb1/regex-2026.5.9-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:fd190e88a895a8901325fad284a3f74ea52b1da8525b76cc811fa9b1edf0ce2b", size = 801348, upload-time = "2026-05-09T23:13:54.127Z" }, - { url = "https://files.pythonhosted.org/packages/7d/62/8ca59a24c55bc34d166eefaf3717bd77772f329fdbf984d86581e0a3571c/regex-2026.5.9-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:8e76e8161ad00694cfce6767d5dea860c6391ac5b83e5c3a39661e696f11fc7e", size = 866493, upload-time = "2026-05-09T23:13:56.067Z" }, - { url = "https://files.pythonhosted.org/packages/8d/3d/30f2ae62cef3278bb5bb821f467277a55fb73f01032cf85997e15e8289a8/regex-2026.5.9-cp313-cp313t-musllinux_1_2_riscv64.whl", hash = "sha256:ddda5340e6c01a293027dd46232fa79eaff1b48058ce7a98f572b6445b088041", size = 772811, upload-time = "2026-05-09T23:13:57.867Z" }, - { url = "https://files.pythonhosted.org/packages/d8/ae/7d2089bcd78ad0c0161bc684339df50032acb438a7bd3305e7ddb1193cec/regex-2026.5.9-cp313-cp313t-musllinux_1_2_s390x.whl", hash = "sha256:205109e96b3cf5adf8f4cd62bedde9487feb282b9497a3535451e5a24cd706a0", size = 856584, upload-time = "2026-05-09T23:13:59.679Z" }, - { url = "https://files.pythonhosted.org/packages/a9/29/92ff47f75990131ea4f24ba17819e5a9d141e10819807e09addd73409af6/regex-2026.5.9-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:dfbe4579b9f08036aa7d101d1835437a20783574ac66327e6b29b4018a138081", size = 803453, upload-time = "2026-05-09T23:14:01.978Z" }, - { url = "https://files.pythonhosted.org/packages/04/99/eff29f1037dcab36702c9ee5d6858cf1ce2336ea8ea2987f64245b99ea5e/regex-2026.5.9-cp313-cp313t-win32.whl", hash = "sha256:ed2c9e8068b614c574d8d30e543d617cf5379b0535d46f97ef00e904745a08b5", size = 269951, upload-time = "2026-05-09T23:14:03.661Z" }, - { url = "https://files.pythonhosted.org/packages/0e/9d/8870b8981d27b22cda77bb26a5ac7ebfa9c7d9e0dea195a834a82380e748/regex-2026.5.9-cp313-cp313t-win_amd64.whl", hash = "sha256:b46b0f094dc1d3b90356c85a0bd2c9bafc4a6a190b9d6f8ddd5a033b6e088ed4", size = 281240, upload-time = "2026-05-09T23:14:05.56Z" }, - { url = "https://files.pythonhosted.org/packages/72/b1/3379415e8f135c13ac551353397cc4fe97b4978f3cac73c5fcbcded548b8/regex-2026.5.9-cp313-cp313t-win_arm64.whl", hash = "sha256:872acc074bd29ffc9913ecdfedf6ea77502312ca44a4aa0d3779089c6069d8de", size = 272383, upload-time = "2026-05-09T23:14:07.843Z" }, - { url = "https://files.pythonhosted.org/packages/13/3e/9c3cd292d8808b3645a2ce517e200179b6d0e903f176300bd8b542e14de5/regex-2026.5.9-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:1bd7587a2948b4085195d5a3374eaf4a425dc3e55784c038175355ecf3bbbf8a", size = 490376, upload-time = "2026-05-09T23:14:09.64Z" }, - { url = "https://files.pythonhosted.org/packages/60/70/d43ee8a2ca0a8b68d167f21658b85520ac0574617c7f320367c5047f7556/regex-2026.5.9-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:dea2e88e1cce4522496cce630e11e67b98b7076620bc4336c3f674bc21a375f4", size = 291964, upload-time = "2026-05-09T23:14:11.424Z" }, - { url = "https://files.pythonhosted.org/packages/21/91/9d50b433828d8e74196904e168a43abf1e6e88b2a15d47ed742456720c37/regex-2026.5.9-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:2099f7e7ff7b6aa3192312650a56e91cc091e49d50b04e4f6f8b6e28b3b27f1c", size = 289682, upload-time = "2026-05-09T23:14:13.123Z" }, - { url = "https://files.pythonhosted.org/packages/3e/d2/b835e3cafbb9d977736912436259ff551d60919f7d7b3d37d46659c63564/regex-2026.5.9-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ecd353045824e4477562a2ac718c25799cdaaa41f7aa925a806a8a3e6848a5b9", size = 796996, upload-time = "2026-05-09T23:14:14.923Z" }, - { url = "https://files.pythonhosted.org/packages/2c/a6/9f992d00019166b9de01c546dd4549bc679f2a68df11b877740b0760b7c2/regex-2026.5.9-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:65c8c8c37377794bd5b2f3ebe51919042bf17aec802e23c833d89782ed0c78af", size = 866089, upload-time = "2026-05-09T23:14:17.757Z" }, - { url = "https://files.pythonhosted.org/packages/e0/08/4d32af657e049b19cb62b02e46e38fe1518797bfb2203ee93a510b21b0dc/regex-2026.5.9-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:5b73ab8afcf66c622db143d1c6fda4e58e4d537ee4f125229ad47b1ab80f34c0", size = 911530, upload-time = "2026-05-09T23:14:20.353Z" }, - { url = "https://files.pythonhosted.org/packages/d9/27/2af43dd1dc201d1fecefda64a45f4ad0995855b92724f795a777b402ee69/regex-2026.5.9-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0de5cf193997384ed2ca6f1cd4f78055b255d93d82d5a8cd6ba0d11c10b167e4", size = 800643, upload-time = "2026-05-09T23:14:22.265Z" }, - { url = "https://files.pythonhosted.org/packages/a4/dd/23a249047013b5321d4a60c4d2437462086f601b061776a525e5fba2a59f/regex-2026.5.9-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:d641a8c9a61618047796d572a39a79b26167b0411d2c3031937b2fe2d081e2cf", size = 777223, upload-time = "2026-05-09T23:14:24.179Z" }, - { url = "https://files.pythonhosted.org/packages/94/6a/e85ed9538cd19586d0465076a4578a12e093ce776d15f3f8ce92733a8dd6/regex-2026.5.9-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:24b2355ef5cc9aa5b8f07d17704face1c166fdcc2290fa7bd6e6c925655a8346", size = 785760, upload-time = "2026-05-09T23:14:26.065Z" }, - { url = "https://files.pythonhosted.org/packages/2a/c4/f25473209438638e947c55f9156fd8f236f74169229028cc99116380868e/regex-2026.5.9-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:a24852d3c29ad9e47593593d8a247c44ccc3d0548ef12c822d6ed0810affe676", size = 860891, upload-time = "2026-05-09T23:14:28.17Z" }, - { url = "https://files.pythonhosted.org/packages/f9/f7/f4f86e3c74419c37370e91f150ae0c2ef7d34b2e0e4cdd5da046a02e4022/regex-2026.5.9-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:916714069da19329ef7de197dcbc77bb3104145c7c2c864dbfbe318f46b88b14", size = 765891, upload-time = "2026-05-09T23:14:30.06Z" }, - { url = "https://files.pythonhosted.org/packages/26/70/704d8e13765939146b1cd0ef4e2feb71d7929727d2290f026eed10095955/regex-2026.5.9-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:fa411799ca8da32a8d38d020a88faa5b6f91657d284761352940ecf9f7c3bbdd", size = 851380, upload-time = "2026-05-09T23:14:32.123Z" }, - { url = "https://files.pythonhosted.org/packages/26/29/1a13582a8460038edc38e49f64ceb0dd7c60f5caba77571f4bf6601965d9/regex-2026.5.9-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:1e6da47d679b7010ef27556b6e0f99771b744936db1792a10ceac6547ae1503e", size = 789350, upload-time = "2026-05-09T23:14:34.799Z" }, - { url = "https://files.pythonhosted.org/packages/73/56/3dcafe34fc72e271d62ad9a291801e88a1457bb251c132f15fcc2e5aad1a/regex-2026.5.9-cp314-cp314-win32.whl", hash = "sha256:98bd73080e8756255137e1bd3f3f00295bbc5aa383c0e0f973920e9134d7c4ad", size = 272130, upload-time = "2026-05-09T23:14:36.729Z" }, - { url = "https://files.pythonhosted.org/packages/d0/9c/02eebf0be95efe416c664db7fb8b6b05b7a0b06a7544f2884f2558b0526f/regex-2026.5.9-cp314-cp314-win_amd64.whl", hash = "sha256:ff8d372ac2acdc048d1c19916f27ee61bc5722728458ba6ca5052f2c72d51763", size = 280999, upload-time = "2026-05-09T23:14:39.126Z" }, - { url = "https://files.pythonhosted.org/packages/70/5a/1dd1abee76cb7a846a0bcf42fdc87e5720c3c33c24f3e37814310a513d9f/regex-2026.5.9-cp314-cp314-win_arm64.whl", hash = "sha256:e1d93bf647916292e8edcec150c07ddf3dc50179ccaf770c04a7f9e452155372", size = 273500, upload-time = "2026-05-09T23:14:41.059Z" }, - { url = "https://files.pythonhosted.org/packages/86/c1/c5f619b0057a7965cb78ec559c1d7a45ce8c99a35bea95483d64959a93d9/regex-2026.5.9-cp314-cp314t-macosx_10_13_universal2.whl", hash = "sha256:83d0ee4a57d1c87cb549e195ec300b8f0ec3a82eba66d835e4e2ed8634fe4499", size = 494269, upload-time = "2026-05-09T23:14:42.869Z" }, - { url = "https://files.pythonhosted.org/packages/05/2c/5d01f1aee33de4bbe60c8452945bfc8477ca7c5ae4450f6bfe711036cb36/regex-2026.5.9-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:d3d7eb5c9a7f6df82ed3cfac9beb93882a5cbcb5b8b157b56cb2b3b276574ac1", size = 293954, upload-time = "2026-05-09T23:14:44.822Z" }, - { url = "https://files.pythonhosted.org/packages/7a/fe/e8988b2ae2108c6ef71bd4aa8d87fbe257976dd0810e826cd75f701c68b6/regex-2026.5.9-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:075160bf16658e16d35233300b8453aac25de4cbea808d22348b6979668e924d", size = 292405, upload-time = "2026-05-09T23:14:47.211Z" }, - { url = "https://files.pythonhosted.org/packages/79/34/d2b0937faa7859263f7f0a3c6b103a1296306be6952dc173d0154e9a2f49/regex-2026.5.9-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:45375819235558a4ff1c4971dc32881f022613abdb180128f5cb4768c1765a1c", size = 811855, upload-time = "2026-05-09T23:14:49.21Z" }, - { url = "https://files.pythonhosted.org/packages/80/fe/daf53a47457a8486db66c66c01ceb9c2303eecee3f87197f1e77eb1a736d/regex-2026.5.9-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:ead4b163ac30a29574510cd4b3e2e985ac5290c05fc7095557d6a5f403fc31b5", size = 871189, upload-time = "2026-05-09T23:14:51.555Z" }, - { url = "https://files.pythonhosted.org/packages/1c/75/058fc4470cbfbf57d800aff1a0022b929a3f9fa553ee10a0cdf2070eb31f/regex-2026.5.9-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:8c6e4218fbdfbcd4f6c19efca40930d24a621bf4b48cb76bc6640543bd28ef20", size = 917485, upload-time = "2026-05-09T23:14:53.633Z" }, - { url = "https://files.pythonhosted.org/packages/88/e7/179cfda3a28bc843b5c6cfe7f79f23489c791ed95f151083803660878432/regex-2026.5.9-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6351571c8a42b505eb555c0dc47d740d0fb66977dc142919eea6f4325b7c56a0", size = 816369, upload-time = "2026-05-09T23:14:56.198Z" }, - { url = "https://files.pythonhosted.org/packages/41/90/6f0cc422071688266d344fca8462d787cba0a2c144acb25721f9a61ec265/regex-2026.5.9-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:002205cafd2a9e78c6290c7d1df277bf3277b3b7a30e0b4bb0dac2e2e3f7cb2d", size = 785869, upload-time = "2026-05-09T23:14:58.602Z" }, - { url = "https://files.pythonhosted.org/packages/02/67/a31f1760f09c27b251ef39e9beb541f462cf977381d067faa764c2c0e393/regex-2026.5.9-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:8abd33fef90b2a9efac5557d6033ca82d1195ed3a15fea5af15ba7b463c6a63b", size = 801427, upload-time = "2026-05-09T23:15:00.642Z" }, - { url = "https://files.pythonhosted.org/packages/e3/c4/1a80654597b6bc1e1ea0494824c31200e8a956abe290afae9b19a166a148/regex-2026.5.9-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:31037c82eccb44b7ea2e9e221d7c01429430e989a1f4b91ea5a855f6017b509a", size = 866482, upload-time = "2026-05-09T23:15:03.384Z" }, - { url = "https://files.pythonhosted.org/packages/d1/11/960724e06482c08466ff5611e242e86f80062949cdf6b4b9cc317b9dd93d/regex-2026.5.9-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:5604dfd046dc37eca90250fc3be938b076c8059fa772ac0ed6f499b0f0fb0415", size = 773022, upload-time = "2026-05-09T23:15:05.625Z" }, - { url = "https://files.pythonhosted.org/packages/50/a8/a9979c3e7918280e93159ebcab5ef1a65116dd4f3bd6091be0eae4a126e8/regex-2026.5.9-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:0e1b1b4e496afbb24f4a62aba855ee4f88f25578927697b340702e48c9ee6bc2", size = 856642, upload-time = "2026-05-09T23:15:07.966Z" }, - { url = "https://files.pythonhosted.org/packages/fe/d4/a9b732f2f0072c0ab12227483abb24fffcb9f73f8a2b203df0a6d0434735/regex-2026.5.9-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:be3372b9df6ddecff6486d37e19095a7b4973137caf5512407a89f4455361f41", size = 803552, upload-time = "2026-05-09T23:15:10.215Z" }, - { url = "https://files.pythonhosted.org/packages/d5/fe/1b3113817447a1d4155e4ac76d2e072f42c0bcba2f43fa8a0e756ea2cd91/regex-2026.5.9-cp314-cp314t-win32.whl", hash = "sha256:3ddd90103f9e5c471c49c7852ecc1fe27c7e45eb99e977aefe7caa4e779f4f58", size = 275746, upload-time = "2026-05-09T23:15:12.609Z" }, - { url = "https://files.pythonhosted.org/packages/92/73/93d42045302636c91f2e5ef588b65b84b01428f28ec77de256b1dfdfbe5c/regex-2026.5.9-cp314-cp314t-win_amd64.whl", hash = "sha256:ca518ed29c46eecba6010b15f1b9a479314d2de409536e71b6a13aa04e3b8a77", size = 285685, upload-time = "2026-05-09T23:15:15.086Z" }, - { url = "https://files.pythonhosted.org/packages/da/80/35b4c33c804a165a7f55289afda3ea9e3eb6d15800341a2d66455c0f1f30/regex-2026.5.9-cp314-cp314t-win_arm64.whl", hash = "sha256:5e41809d2683fcde7d5a8c87a6567ba1fb1ce0de9f31bff578de00a4b2d76daa", size = 275713, upload-time = "2026-05-09T23:15:16.98Z" }, +version = "2026.7.10" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/7b/37/451aaddbf50922f34d744ad5ca919ae1fcfac112123885d9728f52a484b3/regex-2026.7.10.tar.gz", hash = "sha256:1050fedf0a8a92e843971120c2f57c3a99bea86c0dfa1d63a9fac053fe54b135", size = 416282, upload-time = "2026-07-10T19:49:46.267Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b3/69/62bb7d63f26698949c905cb7ebe29c7b0659e2a7f2a50c35cc29640b0852/regex-2026.7.10-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:799a369bdab91dcf0eb424ebd7aa9650897025ce22f729248d8f2c72002c4daa", size = 494652, upload-time = "2026-07-10T19:46:28.394Z" }, + { url = "https://files.pythonhosted.org/packages/3a/f2/eed2ce38cc38def9c366d060ec739ff5f235a33647ceb73ae6be37306d39/regex-2026.7.10-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:f0192e5f1cfc70e3cb35347135dd02e7497b3e7d83e378aa226d8b3e53a93f19", size = 295920, upload-time = "2026-07-10T19:46:30.342Z" }, + { url = "https://files.pythonhosted.org/packages/36/57/4d724eeb1c440d71ccd6400d33b62b911bb62ca05385fe1961556e628319/regex-2026.7.10-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:221f2771cb780186b94bbf125a151bbeb242fa1a971da6ad59d7b0370f19de9a", size = 290696, upload-time = "2026-07-10T19:46:31.953Z" }, + { url = "https://files.pythonhosted.org/packages/c7/9d/76c6779e424c64740d2a564b7ecb389a62c77b6294127d34f52008c91ea7/regex-2026.7.10-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ab2fb1f7a2deb4ca3ddebbae6b93905d21480a3b4e11de28d79d9fb0d316fcf8", size = 784833, upload-time = "2026-07-10T19:46:33.145Z" }, + { url = "https://files.pythonhosted.org/packages/54/ec/f777841d88f0c9d46699daf16f86a8086e077e506603be212de2c4584f85/regex-2026.7.10-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:2f98ef73a13791a387d5c841416ad7f52040ae5caf10bcf46fa12bd2b3d63745", size = 852182, upload-time = "2026-07-10T19:46:34.368Z" }, + { url = "https://files.pythonhosted.org/packages/d1/de/5ba208a0826117851f6c12af9ae7fae5838ccfde69b999b26c5fdc1cedc3/regex-2026.7.10-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:9a094ed44a22f9da497453137c3118b531fd783866ab524b0b0fc146e7395e1d", size = 899571, upload-time = "2026-07-10T19:46:35.564Z" }, + { url = "https://files.pythonhosted.org/packages/7f/46/602b7b81d26a53113d3cec6dd845fd664d7b854b0ea45245bfdd6b9dc9ef/regex-2026.7.10-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:53bbbd6c610489700f7110db1d85f3623924c3f7c760f987eca033867360788a", size = 794164, upload-time = "2026-07-10T19:46:36.972Z" }, + { url = "https://files.pythonhosted.org/packages/53/cc/c21ebc520c3e17d93e495eb2de2b1c5ae5f6780ccdb298b2d8ce1e940820/regex-2026.7.10-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:87b776cf2890e356e4ab104b9df846e169da3eb5b0f110975547091f4e51854e", size = 786304, upload-time = "2026-07-10T19:46:38.238Z" }, + { url = "https://files.pythonhosted.org/packages/65/d8/69ec8c062bbba8d4d153f9eb70ab43564f591035b81fc4ea7eb059fdf71c/regex-2026.7.10-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:ab39d2c967aae3b48a412bff9cdbe7cd7559cd1e277599aceaeada7bc82b7200", size = 769958, upload-time = "2026-07-10T19:46:39.541Z" }, + { url = "https://files.pythonhosted.org/packages/af/82/c56db326ac5f852865bd78d49a275757cc367e8114b13bc1015ed2491db1/regex-2026.7.10-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:b56416091bfd7a429f958f69aaf6823c517be9a49cb5bf1daa3767ce8bf8095e", size = 775056, upload-time = "2026-07-10T19:46:40.808Z" }, + { url = "https://files.pythonhosted.org/packages/af/2a/1ba62462f679eb598d7325ff20798a264ddb9aa34a3f5d2ac388d54c6e4b/regex-2026.7.10-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:617e8f10472e34a8477931f978ff3a88d46ae2ba0e41927e580b933361f60948", size = 848857, upload-time = "2026-07-10T19:46:42.02Z" }, + { url = "https://files.pythonhosted.org/packages/84/5b/37bf2e2fe810540ca90bbfe457a2f61088721c95d442eee8bb1257165ad7/regex-2026.7.10-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:31fa17378b29519bfd0a1b8ba4e9c10cf0baf1cf4099b39b0689429e7dc2c795", size = 757747, upload-time = "2026-07-10T19:46:43.282Z" }, + { url = "https://files.pythonhosted.org/packages/9a/c5/131dd41f73f766af6b08492073b5f28bc4f907b5571230c9f9e895e88302/regex-2026.7.10-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:5c363de7c0339d39341b6181839ed32509820b85ef506deafcf2e7e43baadab4", size = 837183, upload-time = "2026-07-10T19:46:44.91Z" }, + { url = "https://files.pythonhosted.org/packages/a5/ee/00b9332c3c5d7460639f2c10fdc7197a64de6eaafff69478ec3332815335/regex-2026.7.10-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:ed7c886a2fcbf14493ceaf9579394b33521730c161ebb8dad7db9c3e9fcab1a8", size = 782151, upload-time = "2026-07-10T19:46:46.385Z" }, + { url = "https://files.pythonhosted.org/packages/e5/a7/31ce26ec6465c12e7136ea9efcc716f5c55cac616f7958c33f0bf171781e/regex-2026.7.10-cp310-cp310-win32.whl", hash = "sha256:b04583e8867136ae66353fa274f45121ab3ec3166dc45aaff3655a5db90d9f0e", size = 266770, upload-time = "2026-07-10T19:46:47.608Z" }, + { url = "https://files.pythonhosted.org/packages/71/00/22a554bb83203eef88a40ec2fe7cf9a6e5df8765d57f7a96ebe1af5d60c3/regex-2026.7.10-cp310-cp310-win_amd64.whl", hash = "sha256:e21e888a6b471b2bb1cdd4247e8d86632672232f29be583e7eafaa5f4634d34c", size = 277941, upload-time = "2026-07-10T19:46:48.915Z" }, + { url = "https://files.pythonhosted.org/packages/76/46/596a7084918ddf18cea6fb0cc047af1f00cec8790962e8f2edee9b6ec749/regex-2026.7.10-cp310-cp310-win_arm64.whl", hash = "sha256:081acf191b4d614d573a56cab69f948b6864daa5e3cc69f209ee92e26e454c2f", size = 276923, upload-time = "2026-07-10T19:46:50.829Z" }, + { url = "https://files.pythonhosted.org/packages/3d/16/bfd13770be1acd1c05506b93fc6be15c759d6417595d1ba334d355efbf26/regex-2026.7.10-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:66d2c35587cd601c95965d5c0415058ba5cfd6ffbab7624ce198bd967102b341", size = 494639, upload-time = "2026-07-10T19:46:52.207Z" }, + { url = "https://files.pythonhosted.org/packages/e6/b4/0086215709f0f705661f13ba81516287538886ef0d589c545c12b0484669/regex-2026.7.10-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:28a0973eeffff4292f5a7ee498ab65d5e94ee8cc9cea364239251eb4a260a0f1", size = 295920, upload-time = "2026-07-10T19:46:53.63Z" }, + { url = "https://files.pythonhosted.org/packages/8e/9e/8e07d0eea46d2cf36bf4d3794634bb0a820f016d31bc349dfef008d96b02/regex-2026.7.10-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:8331484450b3894298bef8abecce532171ff6ac60b71f999eed10f2c01941a8a", size = 290673, upload-time = "2026-07-10T19:46:54.863Z" }, + { url = "https://files.pythonhosted.org/packages/b7/56/d83c446de21c70ff49d2f1b2ff2196ac79a4ac6373d2cfe496011a250600/regex-2026.7.10-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0639b2488b775a0109f55a5a2172deebdedb4b6c5ab0d48c90b43cbf5de58d17", size = 792378, upload-time = "2026-07-10T19:46:56.116Z" }, + { url = "https://files.pythonhosted.org/packages/dc/0e/d265e0cc6da47aea97e90eb896be2d2e8f92d16add13bac04fa46a0fd972/regex-2026.7.10-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:be4223af640d0aa04c05db81d5d96ada3ead9c09187d892fd37f4f97829480be", size = 861790, upload-time = "2026-07-10T19:46:57.611Z" }, + { url = "https://files.pythonhosted.org/packages/b4/a5/62655f6208d1170a3e9188d6a45d4af0a5ae3b9da8b87d474818ac5ff016/regex-2026.7.10-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:d3c75d57a00109255e60bc9c623b6ececaf7905eaab845c79f036670ed4750a2", size = 906530, upload-time = "2026-07-10T19:46:59.142Z" }, + { url = "https://files.pythonhosted.org/packages/86/b7/d65aa2e9ffb18677cd0afbcf5990da8519a4e50778deb1bca49f043c5174/regex-2026.7.10-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:724ee9379568658ec06362cf24325c5315cc5a67f61dfe585bfeff58300a355b", size = 799912, upload-time = "2026-07-10T19:47:00.534Z" }, + { url = "https://files.pythonhosted.org/packages/8f/19/3a5ce23ea2eb1fe36306aef49c79746ce297e4b434aeb981b525c661413a/regex-2026.7.10-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:732c19e5828eb287d01edb83b2eb87f283ba8e5fc3441c732709d3e8cbd14aaa", size = 773675, upload-time = "2026-07-10T19:47:01.999Z" }, + { url = "https://files.pythonhosted.org/packages/fe/76/3c0eaa426700dd2ba14f2335f2b700a4e1484202254192ae440b83b8352a/regex-2026.7.10-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:982d07727c809b42a3968785354f11c3728414e4e90af0754345b431b2c32561", size = 781711, upload-time = "2026-07-10T19:47:03.425Z" }, + { url = "https://files.pythonhosted.org/packages/a4/a8/a5a3fad84f9a7f897619f0f8e0a2c64946e9709044a186a8f869fb5c332f/regex-2026.7.10-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:4574feca202f8c470bf678aed8b5d89df04aaf8dc677f3b83d92825051301c0f", size = 854539, upload-time = "2026-07-10T19:47:04.999Z" }, + { url = "https://files.pythonhosted.org/packages/f8/c7/47e9b8c8ee77723b9eda74f517b6b25d2f555cf276c063a9eeea35bd86d5/regex-2026.7.10-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:80151ca5bfc6c4524186b3e08b499e97319b2001fc265ed2d4fc12c0d5692cdf", size = 763378, upload-time = "2026-07-10T19:47:06.845Z" }, + { url = "https://files.pythonhosted.org/packages/36/09/e27e42d9d42edf71205c7e6f5b2902bc874ea03c557c80da03b8ed16c9bf/regex-2026.7.10-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:bb52e10e453b5493afe1f7702a2973bc10f4dd8901c0f2ed869ffaa3f8319296", size = 844663, upload-time = "2026-07-10T19:47:08.923Z" }, + { url = "https://files.pythonhosted.org/packages/a1/b5/2423acb98362184ad9c8eebabafa15188d6a177daab919add8f2120fc6cd/regex-2026.7.10-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:e37aba1994d73b4944053ab65a15f313bd5c28c885dd7f0d494a11749d89db6e", size = 789236, upload-time = "2026-07-10T19:47:10.303Z" }, + { url = "https://files.pythonhosted.org/packages/60/ed/b387e84c8a3d6aa115dfb56865437a3fbaf28f4a6fb3b76cc6cce38ced70/regex-2026.7.10-cp311-cp311-win32.whl", hash = "sha256:6cbedeb5112f59dbd169385459b9943310bdd241c6966c19c5f6e2295055c93a", size = 266774, upload-time = "2026-07-10T19:47:11.904Z" }, + { url = "https://files.pythonhosted.org/packages/c4/64/f30a163a65ed1f07ad12c53af00a6bd2a7251a5329fba5a08adc6f9e81a3/regex-2026.7.10-cp311-cp311-win_amd64.whl", hash = "sha256:b1963ec5ba4d52788fb0eac6aca6eb8040e8e318c7e47ebbdfc09440c802919c", size = 277959, upload-time = "2026-07-10T19:47:13.231Z" }, + { url = "https://files.pythonhosted.org/packages/2b/de/61c8174171134cebb834ca9f8fe2ff8f49d8a3dd43453b48b537d0fbb49b/regex-2026.7.10-cp311-cp311-win_arm64.whl", hash = "sha256:3750c42d47712e362158a04d0fd80131f73a55e8c715b2885442a0ff6f9fc3fc", size = 276918, upload-time = "2026-07-10T19:47:14.693Z" }, + { url = "https://files.pythonhosted.org/packages/b3/9c/2503d4ccf3452dc323f8baa3cf3ee10406037d52735c76cfced81423f183/regex-2026.7.10-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:7252b48b0c60100095088fbeb281fca9a4fcf678a4e04b1c520c3f8613c952c4", size = 497114, upload-time = "2026-07-10T19:47:16.22Z" }, + { url = "https://files.pythonhosted.org/packages/91/eb/04534f4263a4f658cd20a511e9d6124350044f2214eb24fee2db96acf318/regex-2026.7.10-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:da6ef4cb8d457aab0482b50120136ae94238aaa421863eaa7d599759742c72d6", size = 297422, upload-time = "2026-07-10T19:47:17.794Z" }, + { url = "https://files.pythonhosted.org/packages/ca/2d/35809de392ab66ba439b58c3187ae3b8b53c883233f284b59961e5725c99/regex-2026.7.10-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:fe7ff456c22725c9d9017f7a2a7df2b51af6df77314176760b22e2d05278e181", size = 292110, upload-time = "2026-07-10T19:47:19.188Z" }, + { url = "https://files.pythonhosted.org/packages/ad/1e/5ce0fbe9aab071893ce2b7df020d0f561f7b411ec334124302468d587884/regex-2026.7.10-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f3463a5f26be513a49e4d497debcf1b252a2db7b92c77d89621aa90b83d2dd38", size = 796800, upload-time = "2026-07-10T19:47:20.639Z" }, + { url = "https://files.pythonhosted.org/packages/d4/67/c1ccbada395c10e334763b583e1039b1660b142303ebb941d4269130b22f/regex-2026.7.10-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:948dfc62683a6947b9b486c4598d8f6e3ecc542478b6767b87d52be68aeb55c6", size = 865509, upload-time = "2026-07-10T19:47:22.135Z" }, + { url = "https://files.pythonhosted.org/packages/0e/06/f0b31afc16c1208f945b66290eb2a9936ab8becdfb23bbcedb91cc5f9d9b/regex-2026.7.10-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:c2cbd385d82f63bb35edb60b09b08abad3619bd0a4a492ae59e55afaf98e1b9d", size = 912395, upload-time = "2026-07-10T19:47:24.128Z" }, + { url = "https://files.pythonhosted.org/packages/0b/1c/8687de3a6c3220f4f872a9bf4bcd8dc249f2a96e7dddfa93de8bd4d16399/regex-2026.7.10-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f6222cafe00e072bb2b8f14142cd969637411fbc4dd3b1d73a90a3b817fa046f", size = 801308, upload-time = "2026-07-10T19:47:25.696Z" }, + { url = "https://files.pythonhosted.org/packages/5f/e3/60a40ec02a2315d826414a125640aceb6f30450574c530c8f352110ece0e/regex-2026.7.10-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:65ee5d1ac3cd541325f5ac92625b1c1505f4d171520dd931bda7952895c5321a", size = 777120, upload-time = "2026-07-10T19:47:27.158Z" }, + { url = "https://files.pythonhosted.org/packages/6a/9a/ec579b4f840ac59bc7c192b56e66abd4cbf385615300d59f7c94bf6863ae/regex-2026.7.10-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:aa34473fbcc108fea403074f3f45091461b18b2047d136f16ffaa4c65ad46a68", size = 785164, upload-time = "2026-07-10T19:47:28.732Z" }, + { url = "https://files.pythonhosted.org/packages/ad/1c/60d88afd5f98d4b0fb1f8b8969270628140dc01c7ff93a939f2aa83f31a6/regex-2026.7.10-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:9d028d189d8f38d7ff292f22187c0df37f2317f554d2ed9a2908ada330af57c0", size = 860161, upload-time = "2026-07-10T19:47:30.605Z" }, + { url = "https://files.pythonhosted.org/packages/2a/40/08ae3ba45fe79e48c9a888a3389a7ee7e2d8c580d2d996da5ece02dfdcb9/regex-2026.7.10-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:396ea70e4ea1f19571940add3bad9fd3eb6a19dc610d0d01f692bc1ba0c10cb4", size = 765829, upload-time = "2026-07-10T19:47:32.06Z" }, + { url = "https://files.pythonhosted.org/packages/12/e6/e613c6755d19aca9d977cdc3418a1991ffc8f386779752dd8fdfa888ea89/regex-2026.7.10-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:ebbf0d83ed5271991d666e54bb6c90ac2c55fb2ef3a88740c6af85dc85de2402", size = 852170, upload-time = "2026-07-10T19:47:33.567Z" }, + { url = "https://files.pythonhosted.org/packages/03/33/89072f2060e6b844b4916d5bc40ef01e973640c703025707869264ec75ab/regex-2026.7.10-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:58a4571b2a093f6f6ee4fd281faa8ebf645abcf575f758173ea2605c7a1e1ecb", size = 789550, upload-time = "2026-07-10T19:47:35.395Z" }, + { url = "https://files.pythonhosted.org/packages/e3/3c/4bc8be9a155035e63780ccac1da101f36194946fdc3f6fce90c7179fc6df/regex-2026.7.10-cp312-cp312-win32.whl", hash = "sha256:eac1207936555aa691ce32df1432b478f2729d54e6d93a1f4db9215bcd8eb47d", size = 267151, upload-time = "2026-07-10T19:47:37.047Z" }, + { url = "https://files.pythonhosted.org/packages/35/73/9f5aade65bb98cc6e99c336e45a49a658300720c16721f3e687f8d754fec/regex-2026.7.10-cp312-cp312-win_amd64.whl", hash = "sha256:ecae626449d00db8c08f8f1fc00047a32d6d7eb5402b3976f5c3fda2b80a7a4f", size = 277751, upload-time = "2026-07-10T19:47:38.488Z" }, + { url = "https://files.pythonhosted.org/packages/36/6f/d069dd12872ea1d50e17319d342f89e2072cae4b62f4245009a1108c74d8/regex-2026.7.10-cp312-cp312-win_arm64.whl", hash = "sha256:87794549a3f5c1c2bdfba2380c1bf87b931e375f4133d929da44f95e396bf5fe", size = 277063, upload-time = "2026-07-10T19:47:40.023Z" }, + { url = "https://files.pythonhosted.org/packages/e0/88/0c977b9f3ba9b08645516eca236388c340f56f7a87054d41a187a04e134c/regex-2026.7.10-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:4db009b4fc533d79af3e841d6c8538730423f82ea8508e353a3713725de7901c", size = 496868, upload-time = "2026-07-10T19:47:41.675Z" }, + { url = "https://files.pythonhosted.org/packages/f6/51/600882cd5d9a3cf083fd66a4064f5b7f243ba2a7de2437d42823e286edaf/regex-2026.7.10-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:b96341cb29a3faa5db05aff29c77d141d827414f145330e5d8846892119351c1", size = 297306, upload-time = "2026-07-10T19:47:43.521Z" }, + { url = "https://files.pythonhosted.org/packages/52/6f/48a912054ffcb756e374207bb8f4430c5c3e0ffa9627b3c7b6661844b30a/regex-2026.7.10-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:14d27f6bd04beb01f6a25a1153d73e58c290fd45d92ba56af1bb44199fd1010d", size = 291950, upload-time = "2026-07-10T19:47:45.267Z" }, + { url = "https://files.pythonhosted.org/packages/1a/c8/8e1c3c86ebcee7effccbd1f7fc54fe3af22aa0e9204503e2baea4a6ff001/regex-2026.7.10-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e6b6a11bf898cca3ce7bfaa17b646901107f3975677fbd5097f36e5eb5641983", size = 796817, upload-time = "2026-07-10T19:47:48.054Z" }, + { url = "https://files.pythonhosted.org/packages/65/39/3e49d9ff0e0737eb8180a00569b47aabb59b84611f48392eba4d998d91a0/regex-2026.7.10-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:234f8e0d65cf1df9becadae98648f74030ee85a8f12edcb5eb0f60a22a602197", size = 865513, upload-time = "2026-07-10T19:47:49.855Z" }, + { url = "https://files.pythonhosted.org/packages/70/57/6511ad809bb3122c65bbeeffa5b750652bb03d273d29f3acb0754109b183/regex-2026.7.10-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:91b916d495db3e1b473c7c8e68733beec4dce8e487442db61764fff94f59740e", size = 912391, upload-time = "2026-07-10T19:47:51.776Z" }, + { url = "https://files.pythonhosted.org/packages/cc/29/a1b0c109c9e878cb04b931bfe4c54332d692b93c322e127b5ae9f25b0d9e/regex-2026.7.10-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1f0d4ccf70b1d13711242de0ba78967db5c35d12ac408378c70e06295c3f6644", size = 801338, upload-time = "2026-07-10T19:47:53.38Z" }, + { url = "https://files.pythonhosted.org/packages/33/be/171c3dad4d77000e1befeff2883ca88734696dfd97b2951e5e074f32e4dd/regex-2026.7.10-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:c622f4c638a725c39abcb2e680b1bd592663c83b672a4ed350a17f806d75618e", size = 777149, upload-time = "2026-07-10T19:47:54.944Z" }, + { url = "https://files.pythonhosted.org/packages/33/61/41ab0de0e4574da1071c151f67d1eb9db3d92c43e31d64d2e6863c3d89bf/regex-2026.7.10-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:41a47c2b28d9421e2509a4583a22510dc31d83212fcf38e1508a7013140f71a8", size = 785216, upload-time = "2026-07-10T19:47:56.56Z" }, + { url = "https://files.pythonhosted.org/packages/66/28/372859ea693736f07cf7023247c7eca8f221d9c6df8697ff9f93371cca08/regex-2026.7.10-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:13fba679fe035037e9d5286620f88bbfd105df4d5fcd975942edd282ab986775", size = 860229, upload-time = "2026-07-10T19:47:58.278Z" }, + { url = "https://files.pythonhosted.org/packages/50/b1/e1d32cd944b599534ae655d35e8640d0ec790c0fa12e1fb29bf434d50f55/regex-2026.7.10-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:8e26a075fa9945b9e44a3d02cc83d776c3b76bb1ff4b133bbfa620d5650131da", size = 765797, upload-time = "2026-07-10T19:48:00.291Z" }, + { url = "https://files.pythonhosted.org/packages/0c/62/79a2cd9556a3329351e370929743ef4f0ccc0aaff6b3dc414ae5fa4a1302/regex-2026.7.10-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:d0834c84ae8750ae1c4cede59b0afd4d2f775be958e11b18a3eea24ed9d0d9f1", size = 852130, upload-time = "2026-07-10T19:48:01.972Z" }, + { url = "https://files.pythonhosted.org/packages/66/58/76fec29898cf5d359ab63face50f9d4f7135cc2eca3477139227b1d09952/regex-2026.7.10-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:64722a5031aeace7f6c8d5ea9a9b22d9368af0d6e8fa532585da8158549ea963", size = 789644, upload-time = "2026-07-10T19:48:03.748Z" }, + { url = "https://files.pythonhosted.org/packages/f6/06/3c7cec7817bda293e13c8f88aed227bbcf8b37e5990936ff6442a8fdf11a/regex-2026.7.10-cp313-cp313-win32.whl", hash = "sha256:74ae61d8573ecd51b5eeee7be2218e4c56e99c14fa8fcf97cf7519611d4be92e", size = 267130, upload-time = "2026-07-10T19:48:05.677Z" }, + { url = "https://files.pythonhosted.org/packages/88/6c/e2a6f9a6a905f923cfc912298a5949737e9504b1ca24f29eda8d04d05ece/regex-2026.7.10-cp313-cp313-win_amd64.whl", hash = "sha256:5e792367e5f9b4ffb8cad93f1beaa91837056b94da98aa5c65a0db0c1b474927", size = 277722, upload-time = "2026-07-10T19:48:07.318Z" }, + { url = "https://files.pythonhosted.org/packages/00/a6/9d8935aaa940c388496aa1a0c82669cc4b5d06291c2712d595e3f0cf16d3/regex-2026.7.10-cp313-cp313-win_arm64.whl", hash = "sha256:82ab8330e7e2e416c2d42fcec67f02c242393b8681014750d4b70b3f158e1f08", size = 277059, upload-time = "2026-07-10T19:48:08.977Z" }, + { url = "https://files.pythonhosted.org/packages/7d/e9/26decfd3e85c09e42ff7b0d23a6f51085ca4c268db15f084928ca33459c6/regex-2026.7.10-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:2b93eafd92c4128bab2f93500e8912cc9ecb3d3765f6685b902c6820d0909b6b", size = 501508, upload-time = "2026-07-10T19:48:10.668Z" }, + { url = "https://files.pythonhosted.org/packages/38/a5/5b167cebde101945690219bf34361481c9f07e858a4f46d9996b80ec1490/regex-2026.7.10-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:3f03b92fb6ec739df042e45b06423fc717ecf0063e07ffe2897f7b2d5735e1e8", size = 299705, upload-time = "2026-07-10T19:48:12.544Z" }, + { url = "https://files.pythonhosted.org/packages/f6/20/7909be4b9f449f8c282c14b6762d59aa722aeaeebe7ee4f9bb623eeaa5e0/regex-2026.7.10-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:bb5aab464a0c5e03a97abad5bdf54517061ebbf72340d576e99ff661a42575cc", size = 294605, upload-time = "2026-07-10T19:48:14.495Z" }, + { url = "https://files.pythonhosted.org/packages/82/88/e52550185d6fda68f549b01239698697de47320fd599f5e880b1986b7673/regex-2026.7.10-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:fadb07dbe36a541283ff454b1a268afd54b077d917043f2e1e5615372cb5f200", size = 811747, upload-time = "2026-07-10T19:48:16.197Z" }, + { url = "https://files.pythonhosted.org/packages/06/98/16c255c909714de1ee04da6ae30f3ee04170f300cdc0dcf57a314ee4816a/regex-2026.7.10-cp313-cp313t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:21150500b970b12202879dfd82e7fd809d8e853140fff84d08e57a90cf1e154e", size = 871203, upload-time = "2026-07-10T19:48:18.12Z" }, + { url = "https://files.pythonhosted.org/packages/3b/32/423ed27c9bae2092a453e853da2b6628a658d08bb5a6117db8d591183d85/regex-2026.7.10-cp313-cp313t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:a68b637451d64ba30ed8ae125c973fa834cc2d37dfa7f154c2b479015d477ba8", size = 917334, upload-time = "2026-07-10T19:48:19.952Z" }, + { url = "https://files.pythonhosted.org/packages/73/87/74dac8efb500db31cb000fda6bae2be45fc2fbf1fa9412f445fbb8acbe37/regex-2026.7.10-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:3e23458d8903e33e7d27196d7a311523dc4e2f4137a5f34e4dbd30c8d37ff33e", size = 816379, upload-time = "2026-07-10T19:48:21.616Z" }, + { url = "https://files.pythonhosted.org/packages/a8/9f/1859403654e3e030b288f06d49233c6a4f889d62b84c4ef3f3a28653173d/regex-2026.7.10-cp313-cp313t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:cae27622c094558e519abf3242cf4272db961d12c5c9a9ffb7a1b44b2627d5c6", size = 785563, upload-time = "2026-07-10T19:48:23.643Z" }, + { url = "https://files.pythonhosted.org/packages/6d/d8/35d30d6bdf1ef6a5430e8982607b3a6db4df1ddedbe001e43435585d88ba/regex-2026.7.10-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:ee877b6d78f9dff1da94fef51ae8cf9cce0967e043fdcc864c40b85cf293c192", size = 801415, upload-time = "2026-07-10T19:48:25.499Z" }, + { url = "https://files.pythonhosted.org/packages/f7/22/630f31f5ea4826167b2b064d9cac2093a5b3222af380aa432cfe1a5dabcd/regex-2026.7.10-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:2c66a8a1969cfd506d1e203c0005fd0fc3fe6efc83c945606566b6f9611d4851", size = 866560, upload-time = "2026-07-10T19:48:27.789Z" }, + { url = "https://files.pythonhosted.org/packages/8d/14/f5914a6d9c5bc63b9bed8c9a1169fb0be35dbe05cdc460e17d953031a366/regex-2026.7.10-cp313-cp313t-musllinux_1_2_riscv64.whl", hash = "sha256:2bc350e1c5fa250f30ab0c3e38e5cfdffcd82cb8af224df69955cab4e3003812", size = 772877, upload-time = "2026-07-10T19:48:29.563Z" }, + { url = "https://files.pythonhosted.org/packages/c1/0f/7c13999eef3e4186f7c79d4950fa56f041bf4de107682fb82c80db605ff9/regex-2026.7.10-cp313-cp313t-musllinux_1_2_s390x.whl", hash = "sha256:53f54993b462f3f91fea0f2076b46deb6619a5f45d70dbd1f543f789d8b900ef", size = 856648, upload-time = "2026-07-10T19:48:31.282Z" }, + { url = "https://files.pythonhosted.org/packages/a4/71/a48e43909b6450fb48fa94e783bef2d9a37179258bc32ef2283955df7be7/regex-2026.7.10-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:cfcec18f7da682c4e2d82112829ce906569cb8d69fa6c26f3a50dfbed5ceb682", size = 803520, upload-time = "2026-07-10T19:48:33.275Z" }, + { url = "https://files.pythonhosted.org/packages/e0/b8/f037d1bf2c133cb24ceb6e7d81d08417080390eddab6ddfd701aa7091874/regex-2026.7.10-cp313-cp313t-win32.whl", hash = "sha256:a2d6d30be35ddd70ce0f8ee259a4c25f24d6d689a45a5ac440f03e6bcc5a21d1", size = 269168, upload-time = "2026-07-10T19:48:35.353Z" }, + { url = "https://files.pythonhosted.org/packages/b6/9c/eaac34f8452a838956e7e89852ad049678cdc1af5d14f72d3b3b658b1ea5/regex-2026.7.10-cp313-cp313t-win_amd64.whl", hash = "sha256:c57b6ad3f7a1bdd101b2966f29dc161adf49727b1e8d3e1e89db2eda8a75c344", size = 280004, upload-time = "2026-07-10T19:48:37.106Z" }, + { url = "https://files.pythonhosted.org/packages/cd/a9/e22e997587bc1d588b0b2cd0572027d39dd3a006216e40bbf0361688c51c/regex-2026.7.10-cp313-cp313t-win_arm64.whl", hash = "sha256:3d8ef9df02c8083c7b4b855e3cb87c8e0ebbcfea088d98c7a886aaefdf88d837", size = 279308, upload-time = "2026-07-10T19:48:38.907Z" }, + { url = "https://files.pythonhosted.org/packages/6a/4a/a7fa3ada9bd2d2ce20d56dfceec6b2a51afeed9bf3d8286355ceec5f0628/regex-2026.7.10-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:39f81d1fdf594446495f2f4edd8e62d8eda0f7a802c77ac596dc8448ad4cc5ca", size = 497087, upload-time = "2026-07-10T19:48:40.543Z" }, + { url = "https://files.pythonhosted.org/packages/0f/7e/ca0b1a87192e5828dbc16f16ae6caca9b67f25bf729a3348468a5ff52755/regex-2026.7.10-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:441edc66a54063f8269d1494fc8474d06605e71e8a918f4bcfd079ebda4ce042", size = 297307, upload-time = "2026-07-10T19:48:42.213Z" }, + { url = "https://files.pythonhosted.org/packages/b2/6c/fb40bb34275d3cd4d7a376d5fb2ea1f0f4a96fd884fa83c0c4ae869001bf/regex-2026.7.10-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:cfeb11990f59e59a0df26c648f0adfcbf27be77241250636f5769eb08db662be", size = 292163, upload-time = "2026-07-10T19:48:43.929Z" }, + { url = "https://files.pythonhosted.org/packages/18/0b/34cbea16c8fea9a18475a7e8f5837c70af451e738bfeb4eb5b029b7dc07a/regex-2026.7.10-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:460176b2db044a292baaee6891106566739657877af89a251cded228689015a6", size = 797064, upload-time = "2026-07-10T19:48:45.623Z" }, + { url = "https://files.pythonhosted.org/packages/87/77/f6805d97f15f5a710bdfd56a768f3468c978239daf9e1b15efd8935e1967/regex-2026.7.10-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:9dc55698737aca028848bde418d6c51d74f2a5fd44872d3c8b56b626729adb89", size = 866155, upload-time = "2026-07-10T19:48:47.589Z" }, + { url = "https://files.pythonhosted.org/packages/a2/e3/a2a905807bba3bcd90d6ebbb67d27af2adf7d41708175cbc6b956a0c75f1/regex-2026.7.10-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:d3e10779f60c000213a5b53f518824bd07b3dc119333b26d70c6be1c27b5c794", size = 911596, upload-time = "2026-07-10T19:48:49.473Z" }, + { url = "https://files.pythonhosted.org/packages/a2/ca/a3126888b2c6f33c7e29144fedf85f6d5a52a400024fa045ad8fc0550ef1/regex-2026.7.10-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:38a5926601aaccf379512746b86eb0ac1d29121f6c776dac6ac5b31077432f2c", size = 800713, upload-time = "2026-07-10T19:48:51.452Z" }, + { url = "https://files.pythonhosted.org/packages/66/19/9d252fd969f726c8b56b4bacf910811cc70495a110907b3a7ccb96cd9cad/regex-2026.7.10-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:a72ecf5bfd3fc8d57927f7e3ded2487e144472f39010c3acaec3f6f3ff53f361", size = 777286, upload-time = "2026-07-10T19:48:53.443Z" }, + { url = "https://files.pythonhosted.org/packages/40/7a/5f1bf433fa446ecb3aab87bb402603dc9e171ef8052c1bb8690bb4e255a3/regex-2026.7.10-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:d50714405845c1010c871098558cfe5718fe39d2a2fab5f95c8863caeb7a82b3", size = 785826, upload-time = "2026-07-10T19:48:55.381Z" }, + { url = "https://files.pythonhosted.org/packages/99/ca/69f3a7281d86f1b592338007f3e535cc219d771448e2b61c0b56e4f9d05b/regex-2026.7.10-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:ec1c44cf9bd22079aac37a07cb49a29ced9050ab5bddf24e50aba298f1e34d90", size = 860957, upload-time = "2026-07-10T19:48:57.962Z" }, + { url = "https://files.pythonhosted.org/packages/bc/11/487ff55c8d515ec9dd60d7ba3c129eeaa9e527358ed9e8a054a9e9430f81/regex-2026.7.10-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:9e9aaef25a40d1f1e1bbb1d0eb0190c4a64a7a1750f7eb67b8399bed6f4fd2a6", size = 765959, upload-time = "2026-07-10T19:49:00.27Z" }, + { url = "https://files.pythonhosted.org/packages/73/e1/fa034e6fa8896a09bd0d5e19c81fdc024411ab37980950a0401dccee8f6d/regex-2026.7.10-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:e54e088dc64dd2766014e7cfe5f8bc45399400fd486816e494f93e3f0f55da06", size = 851447, upload-time = "2026-07-10T19:49:02.128Z" }, + { url = "https://files.pythonhosted.org/packages/ee/a5/b9427ed53b0e14c540dc436d56aaf57a19fb9183c6e7abd66f4b4368fbad/regex-2026.7.10-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:834271b1ff2cfa1f67fcd65a48bf11d11e9ab837e21bf79ce554efb648599ae8", size = 789418, upload-time = "2026-07-10T19:49:03.949Z" }, + { url = "https://files.pythonhosted.org/packages/ba/52/aab92420c8aa845c7bcbe68dc65023d4a9e9ea785abf0beb2198f0de5ba1/regex-2026.7.10-cp314-cp314-win32.whl", hash = "sha256:f988a1cec68058f71a38471813fba9e87dffe855582682e8a10e40ece12567a2", size = 272538, upload-time = "2026-07-10T19:49:05.833Z" }, + { url = "https://files.pythonhosted.org/packages/99/16/5c7050e0ef7dd8889441924ff0a2c33b7f0587c0ccb0953fe7ca997d673b/regex-2026.7.10-cp314-cp314-win_amd64.whl", hash = "sha256:2129e4a5e86f26926982d883dff815056f2e98220fdf630e59f961b578a26c43", size = 280796, upload-time = "2026-07-10T19:49:07.593Z" }, + { url = "https://files.pythonhosted.org/packages/e8/1a/4f6099d2ba271502fdb97e697bae2ed0213c0d87f2273fe7d21e2e401d12/regex-2026.7.10-cp314-cp314-win_arm64.whl", hash = "sha256:9cd5b6805396157b4cf993a6940cbb8663161f29b4df2458c1c9991f099299c5", size = 281017, upload-time = "2026-07-10T19:49:09.767Z" }, + { url = "https://files.pythonhosted.org/packages/19/02/4061fc71f64703e0df61e782c2894c3fbc089d277767eff6e16099581c73/regex-2026.7.10-cp314-cp314t-macosx_10_13_universal2.whl", hash = "sha256:103e8f3acc3dcede88c0331c8612766bdcfc47c9250c5477f0e10e0550b9da49", size = 501467, upload-time = "2026-07-10T19:49:11.952Z" }, + { url = "https://files.pythonhosted.org/packages/73/a5/8d42b2f3fd672908a05582effd0f88438bf9bb4e8e02d69a62c723e23601/regex-2026.7.10-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:538ddb143f5ca085e372def17ef3ed9d74b50ad7fc431bd85dc50a9af1a7076f", size = 299700, upload-time = "2026-07-10T19:49:14.067Z" }, + { url = "https://files.pythonhosted.org/packages/65/70/36fa4b46f73d268c0dbe77c40e62da2cd4833ee206d3b2e438c2034e1f36/regex-2026.7.10-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:6e3448e86b05ce87d4eb50f9c680860830f3b32493660b39f43957d6263e2eba", size = 294590, upload-time = "2026-07-10T19:49:15.883Z" }, + { url = "https://files.pythonhosted.org/packages/e0/a7/b6db1823f3a233c2a46f854fdc986f4fd424a84ed557b7751f2998efb266/regex-2026.7.10-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5eab9d3f981c423afd1a61db055cfe83553c3f6455949e334db04722469dd0a2", size = 811925, upload-time = "2026-07-10T19:49:17.97Z" }, + { url = "https://files.pythonhosted.org/packages/b6/7d/f8bee4c210c42c7e8b952bb9fb7099dd7fb2f4bd0f33d0d65a8ab08aafc0/regex-2026.7.10-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:177f930af3ad72e1045f8877540e0c43a38f7d328cf05f31963d0bd5f7ecf067", size = 871257, upload-time = "2026-07-10T19:49:19.943Z" }, + { url = "https://files.pythonhosted.org/packages/5d/78/22adf72e614ba0216b996e9aaef5712c23699e360ea127bb3d5ee1a7666f/regex-2026.7.10-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:dd3b6d97beb39afb412f2c79522b9e099463c31f4c49ab8347c5a2ca3531c478", size = 917551, upload-time = "2026-07-10T19:49:22.069Z" }, + { url = "https://files.pythonhosted.org/packages/03/f7/ebc15a39e81e6b58da5f913b91fc293a25c6700d353c14d5cd25fc85712a/regex-2026.7.10-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8679f0652a183d93da646fcec8da8228db0be40d1595da37e6d74c2dc8c4713c", size = 816436, upload-time = "2026-07-10T19:49:24.131Z" }, + { url = "https://files.pythonhosted.org/packages/5c/33/20bc2bdd57f7e0fcc51be37e4c4d1bca7f0b4af8dc0a148c23220e689da8/regex-2026.7.10-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:494b19a5805438aeb582de99f9d97603d8fd48e6f4cc74d0088bb292b4da3b70", size = 785935, upload-time = "2026-07-10T19:49:26.265Z" }, + { url = "https://files.pythonhosted.org/packages/b4/51/87ff99c849b56309c40214a72b54b0eef320d0516a8a516970cc8be1b725/regex-2026.7.10-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:0911e34151a5429d0325dae538ba9851ec0b62426bdfd613060cda8f1c36ec7f", size = 801494, upload-time = "2026-07-10T19:49:28.493Z" }, + { url = "https://files.pythonhosted.org/packages/16/11/fde67d49083fef489b7e0f841e2e5736516795b166c9867f05956c1e494b/regex-2026.7.10-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:b862572b7a5f5ed47d2ba5921e63bf8d9e3b682f859d8f11e0e5ca46f7e82173", size = 866549, upload-time = "2026-07-10T19:49:30.592Z" }, + { url = "https://files.pythonhosted.org/packages/e6/b5/31a156c36acf10181d88f55a66c688d5454a344e53ccc03d49f4a48a2297/regex-2026.7.10-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:3f361215e000d68a4aff375106637b83c80be36091d83ee5107ad3b32bd73f48", size = 773089, upload-time = "2026-07-10T19:49:32.661Z" }, + { url = "https://files.pythonhosted.org/packages/27/bb/734e978c904726664df47ae36ce5eca5065de5141185ae46efec063476a2/regex-2026.7.10-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:4533af6099543db32ef26abc2b2f824781d4eebb309ab9296150fd1a0c7eb07d", size = 856710, upload-time = "2026-07-10T19:49:35.289Z" }, + { url = "https://files.pythonhosted.org/packages/6d/e5/dc35cea074dbdcb9776c4b0542a3bc326ff08454af0768ef35f3fc66e7fa/regex-2026.7.10-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:668ab85105361d0200e3545bec198a1acfc6b0aeb5fff8897647a826e5a171be", size = 803621, upload-time = "2026-07-10T19:49:37.704Z" }, + { url = "https://files.pythonhosted.org/packages/a6/b2/124564af46bc0b592785610b3985315610af0a07f4cf21fa36e06c2398dd/regex-2026.7.10-cp314-cp314t-win32.whl", hash = "sha256:dd7715817a187edd7e2a2390908757f7ba42148e59cad755fb8ee1160c628eca", size = 274558, upload-time = "2026-07-10T19:49:39.926Z" }, + { url = "https://files.pythonhosted.org/packages/4e/9c/cd813ce9f3404c0443915175c1e339c5afd8fcda04310102eaf233015eef/regex-2026.7.10-cp314-cp314t-win_amd64.whl", hash = "sha256:78712d4954234df5ca24fdadb65a2ab034213f0cdfde376c272f9fc5e09866bb", size = 283687, upload-time = "2026-07-10T19:49:41.872Z" }, + { url = "https://files.pythonhosted.org/packages/1b/d3/3dae6a6ce46144940e64425e32b8573a393a009aeaf75fa6752a35399056/regex-2026.7.10-cp314-cp314t-win_arm64.whl", hash = "sha256:749b92640e1970e881fdf22a411d74bf9d049b154f4ef7232eeb9a90dd8be7f3", size = 283377, upload-time = "2026-07-10T19:49:43.985Z" }, ] [[package]] @@ -4130,16 +4102,16 @@ wheels = [ [[package]] name = "responses" -version = "0.26.1" +version = "0.26.2" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "pyyaml" }, { name = "requests" }, { name = "urllib3" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/c2/58/1fb6de3503428196df78638f991ec8095274f1ee9723e272ee4d9ff0092b/responses-0.26.1.tar.gz", hash = "sha256:2eb3218553cc8f79b57d257bac23af5e1bf381f5b9390b1767816f0843e01dc2", size = 83088, upload-time = "2026-05-21T19:56:39.747Z" } +sdist = { url = "https://files.pythonhosted.org/packages/f0/1a/4af3e6d659394b809838490b144e4ab8d7ed3b9fecc7ca78f5d2f79b1a3d/responses-0.26.2.tar.gz", hash = "sha256:9c9259b46a8349197edebf43cfa68a87e1a2802ef503ff8b2fecbabc0b45afd8", size = 84030, upload-time = "2026-07-03T16:44:50.325Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/3a/31/6a620b4427d546b9e7cca8b3b8c5f0559d9cef2bb9eedcda7f73c1473c19/responses-0.26.1-py3-none-any.whl", hash = "sha256:8aacc4586eb08fb2208ef64a9eb4258d9b0c6e6f4260845f2f018ab847495345", size = 35502, upload-time = "2026-05-21T19:56:38.046Z" }, + { url = "https://files.pythonhosted.org/packages/7c/28/693e1d9ebf72baa062ded80d837a035b86ce75eda5a269379e9e2b1008a8/responses-0.26.2-py3-none-any.whl", hash = "sha256:6fdfeabd58e5ec473b98dfe02e6d46d3173bd8dd573eff2ccccf1a05a5135364", size = 35609, upload-time = "2026-07-03T16:44:49.1Z" }, ] [[package]] @@ -4303,169 +4275,155 @@ wheels = [ [[package]] name = "rpds-py" -version = "2026.5.1" +version = "2026.6.3" source = { registry = "https://pypi.org/simple" } resolution-markers = [ "python_full_version >= '3.14'", "python_full_version == '3.13.*'", "python_full_version >= '3.11' and python_full_version < '3.13'", ] -sdist = { url = "https://files.pythonhosted.org/packages/2e/43/25a8dcd3feedd735039a8f0b5b7e3b118232b5eae288c4fd9ab200d41094/rpds_py-2026.5.1.tar.gz", hash = "sha256:07b24fea40541e28570e5b795a4a38fbdcd12550c06bd0748005ecc8116ca256", size = 64459, upload-time = "2026-05-28T12:02:13.232Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/4f/a0/acf8b6fc20bfdcd3a45bd3f57680fb198e157b7e997b9123b10763798bd2/rpds_py-2026.5.1-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:3397a5ed7174dc2786bb214030232fc36fe8e5584fec43a9952cc542b1a12036", size = 355609, upload-time = "2026-05-28T11:58:50.78Z" }, - { url = "https://files.pythonhosted.org/packages/b6/95/f8203fd997484b1690a6869cd0e503b6c3c6be55b0ecc36d1a491fe742f0/rpds_py-2026.5.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:99ab6ba7bfa2cb0f96a04e3652355bf04e3f51aceb1e943b8541dab7ba4828cc", size = 348460, upload-time = "2026-05-28T11:58:52.374Z" }, - { url = "https://files.pythonhosted.org/packages/33/8c/b47326ad2f0be545a5e5c1a55937a12afaea7d392ba2837bb9680f57e6c9/rpds_py-2026.5.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d0efbe45632665e53e3db8fe1e5692db58fc5cb9bab4459d570b83efefe11164", size = 381031, upload-time = "2026-05-28T11:58:53.775Z" }, - { url = "https://files.pythonhosted.org/packages/22/0b/e83bbd97ffac6f6389b605cd4e1c8ac5761dc7e977769c9255d8c5adb7bd/rpds_py-2026.5.1-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:01d17b29c0c23d82b1f4751147ec49cf451f1fc2554eb9ef5f957e55d2656ead", size = 387121, upload-time = "2026-05-28T11:58:55.243Z" }, - { url = "https://files.pythonhosted.org/packages/fd/0e/d285d1bc8864245919c61e1ca82263e4a66d337759c3a4cef72766ff9afc/rpds_py-2026.5.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7559f72b94ae52659086c595dfa017cde03155f7832071d30959049052cb3ece", size = 501026, upload-time = "2026-05-28T11:58:56.788Z" }, - { url = "https://files.pythonhosted.org/packages/86/06/ccb2109a1e543437b5e43816f2b43b9554cc6783145528a4e3711e05c011/rpds_py-2026.5.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9e25b7088f9ccbfc0dfcaa52bf969300ca229e10ecf758974ebcbb080a4b37bb", size = 391865, upload-time = "2026-05-28T11:58:58.298Z" }, - { url = "https://files.pythonhosted.org/packages/3d/33/237173db1cfef10105b3839a24de00eb8d2a523711add4632447cdf0aedd/rpds_py-2026.5.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:613fc4ee9eaef26dc5840666214dd6fbcebcf32f46e76f4abc473059f4e13dda", size = 378012, upload-time = "2026-05-28T11:58:59.589Z" }, - { url = "https://files.pythonhosted.org/packages/97/64/1eae54e34d5161f9969295e80bd6b62a55f2b6ac5f2a5b60d02c2140e758/rpds_py-2026.5.1-cp311-cp311-manylinux_2_31_riscv64.whl", hash = "sha256:85264a90ff4c05c1568dd65f5921c837614b67c60358fb4c17df3b7f2e90690a", size = 391111, upload-time = "2026-05-28T11:59:01.104Z" }, - { url = "https://files.pythonhosted.org/packages/d8/34/5bb334a5a0f65d77869217c4654f34c78a7d11b93938a3c076a2edeafc52/rpds_py-2026.5.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:fe71bca7d547acb17027c7fd1624ff8aae623499c498d3e7011182c4de5c25e0", size = 409225, upload-time = "2026-05-28T11:59:02.433Z" }, - { url = "https://files.pythonhosted.org/packages/16/0f/007ec21283b5b040b4ec3bd95e0402591e22bfa7d5c93dfe01c465c2d2d7/rpds_py-2026.5.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:a05fa4f41f37ec97c9c260441a940450a192f78d774d2b097eee1379f1e1246a", size = 556487, upload-time = "2026-05-28T11:59:04.012Z" }, - { url = "https://files.pythonhosted.org/packages/ff/10/5437c94508169b6b22d8418fef7a66e9ffb5f3b9e9c94460f2eedafe06ff/rpds_py-2026.5.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:df1d2a1996755b24b9ecee92cb4d36c28f86f464a6a173349c26bab41e94b8c2", size = 620798, upload-time = "2026-05-28T11:59:05.485Z" }, - { url = "https://files.pythonhosted.org/packages/e0/d5/9937dce4d6bda74157b954e7d1460db05a22f5929dccfeeba1ed27a93df0/rpds_py-2026.5.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:8895840ac4809e5f60c88fd07617cd71326e73d6e5a8aa783c5c0f7c24985de2", size = 584053, upload-time = "2026-05-28T11:59:06.837Z" }, - { url = "https://files.pythonhosted.org/packages/6c/31/750617dd0ae1752471bf43f9e41d263398fae7cde7849d23b8574a70e617/rpds_py-2026.5.1-cp311-cp311-win32.whl", hash = "sha256:3684a59b158a7683aaeb8e25352e9a9dd2122cec78f2d8530266e4f91b4c7b3f", size = 214390, upload-time = "2026-05-28T11:59:08.402Z" }, - { url = "https://files.pythonhosted.org/packages/3c/bb/3dcab0e1d9516303f2eb672a5d6f62eca5a69e2886301e9c8c54b520c39b/rpds_py-2026.5.1-cp311-cp311-win_amd64.whl", hash = "sha256:7bd530e6a530bb3ea892f194fafa455f3516ac25ecf7143fd33c09be62b0470a", size = 231097, upload-time = "2026-05-28T11:59:09.786Z" }, - { url = "https://files.pythonhosted.org/packages/49/d6/c6bbf5cb1cf12b9732df8074b57f6ef8341ba884c95d40632ae8bddb44e4/rpds_py-2026.5.1-cp311-cp311-win_arm64.whl", hash = "sha256:0a5ae4dbe43c1076983b72616496919872ae7bbe7a1e21cc48336bc3154d130b", size = 226361, upload-time = "2026-05-28T11:59:11.079Z" }, - { url = "https://files.pythonhosted.org/packages/d4/e7/a78582dc57caa592dcc7d4fb69b61390561e908eb3d2f5df5928a8e354c0/rpds_py-2026.5.1-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:3abe24a66e57adcfa645d718063a5fa5103ecc71ddbf26d78af8f9368018ff1d", size = 353040, upload-time = "2026-05-28T11:59:12.531Z" }, - { url = "https://files.pythonhosted.org/packages/a3/43/35e3f136343aef451e545ce8c38d36c2f93c0ed88703db8b64ba2b205c68/rpds_py-2026.5.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:58b1d94308ddf0b1982f61f2eb54bf92997c9ece8a8093ef014250f4a517906c", size = 345775, upload-time = "2026-05-28T11:59:13.827Z" }, - { url = "https://files.pythonhosted.org/packages/20/e1/0f2160c5982d3157734d5cb3ed63d8b2d583a73c9864f77b666449f32cf8/rpds_py-2026.5.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0fa92420128dadce7f54bd73ba1825a273e9268fe9e35dbf7e6362890efa4e08", size = 376329, upload-time = "2026-05-28T11:59:15.271Z" }, - { url = "https://files.pythonhosted.org/packages/d0/11/ee0ba42aff83bf4effdbc576673c6be64c5e173978c3f6d537e94482f77d/rpds_py-2026.5.1-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ca653c6546386227cd9800d1bef6a348099acf8db4250341da6d90f663d6dfcb", size = 383539, upload-time = "2026-05-28T11:59:16.665Z" }, - { url = "https://files.pythonhosted.org/packages/11/df/d94aa6a499d4ac40afe2d7620f2c597fd3c0f182e854ad7cf3f596a81cb6/rpds_py-2026.5.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:66c93681c4729e4e3ecba31b8179fae083ff3118841672835140338b4b9867c1", size = 494674, upload-time = "2026-05-28T11:59:17.991Z" }, - { url = "https://files.pythonhosted.org/packages/1f/75/33d30f43bb2f458de11979486a591b1bf6e5651765ed1704c6197c2dc773/rpds_py-2026.5.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:40ff257542e04796880e011e15cd4dc21c2599975df2aaa8f2c8495ca574e1a5", size = 389268, upload-time = "2026-05-28T11:59:19.434Z" }, - { url = "https://files.pythonhosted.org/packages/f4/1e/2c9096fc19d5fd084b0184ca2b651e659aa0a37e6fdbecf6ece47f147fe1/rpds_py-2026.5.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b6825cc329b290e93c5f6a9be2393118a763f6ccf6abd83704e0c102ca583644", size = 376280, upload-time = "2026-05-28T11:59:21Z" }, - { url = "https://files.pythonhosted.org/packages/b9/e5/61ec9f8be8211ea7f48448195549e4aaf02004083475493b0e137702ecb2/rpds_py-2026.5.1-cp312-cp312-manylinux_2_31_riscv64.whl", hash = "sha256:de42116e69cb53b911cc34aee5ab98f36c597b822545045d49e938818b99e5e4", size = 387233, upload-time = "2026-05-28T11:59:22.454Z" }, - { url = "https://files.pythonhosted.org/packages/0d/ca/bcec1005c4f4a234f92a29078631fee49206c7265ccae966f18fd332e80e/rpds_py-2026.5.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:c0f920015df2a504bebaba6d4c31ccf3fcf942f92655c086da30b671aad19aa6", size = 405009, upload-time = "2026-05-28T11:59:23.845Z" }, - { url = "https://files.pythonhosted.org/packages/72/e6/4d5718c5cf26c522dc7c9999e238da1e77380b81d0c5d1df11e271ddfeb1/rpds_py-2026.5.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:0408a24e44feb919423dc6d9da677cb5cddb894d2ca9e763967d156d9c60fab4", size = 553113, upload-time = "2026-05-28T11:59:25.184Z" }, - { url = "https://files.pythonhosted.org/packages/d4/25/2ee807bdb3e1f0b7eddf7782acd5665a8b5205a331a7d7244a52c4812fd9/rpds_py-2026.5.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:cea68bcd53467561ae2f96a6bdad1544299ba97b5b0ddcd5ac3d376e5c781c24", size = 618838, upload-time = "2026-05-28T11:59:26.749Z" }, - { url = "https://files.pythonhosted.org/packages/6a/c1/7d4c26f167f8c41501cc073d30ee22082b16ce358cf5b00ec97cbc7804ea/rpds_py-2026.5.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:4be8b1d2a705cc37d08256004e1d07de143fa0075c8e85a3df020b776f62b732", size = 582436, upload-time = "2026-05-28T11:59:28.11Z" }, - { url = "https://files.pythonhosted.org/packages/04/1d/9d12b0a337bab46f4769f8857f4007e3b2d639e14f9a44a0efe157696e64/rpds_py-2026.5.1-cp312-cp312-win32.whl", hash = "sha256:6736718bd4fc49cbcb538ba30516fdbef161522acefb739657d48b97bd864fed", size = 212734, upload-time = "2026-05-28T11:59:29.689Z" }, - { url = "https://files.pythonhosted.org/packages/c5/93/e4116f2de7f56bc7406a76033dc501811ddeb22b7f056b92d632871ebb0c/rpds_py-2026.5.1-cp312-cp312-win_amd64.whl", hash = "sha256:0a7d1eec967df0e9b22614a5e177622e0c89611d03727fa0cb48e45028907870", size = 229045, upload-time = "2026-05-28T11:59:31.033Z" }, - { url = "https://files.pythonhosted.org/packages/cb/53/6c3419d85eb2ec5938a37627c585b42d76a63bb731d6e42ed4b079ebf486/rpds_py-2026.5.1-cp312-cp312-win_arm64.whl", hash = "sha256:1841d067089e117142d79b98aa0df2f08b52f2ecc1819dd2700636c0db74a473", size = 223967, upload-time = "2026-05-28T11:59:32.318Z" }, - { url = "https://files.pythonhosted.org/packages/6c/32/14c961ad295f490eb0849ada8b79683e93a59b9de3afdd983eaf55fa6867/rpds_py-2026.5.1-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:efef4ac29c6ff495531eb17ee705b62841ecaa291b7c7077e848ea03e237164d", size = 352787, upload-time = "2026-05-28T11:59:33.655Z" }, - { url = "https://files.pythonhosted.org/packages/ca/bb/d1b85117967c11191441a7274ae616c65d93901d082c588f89a50a8da5ae/rpds_py-2026.5.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:c39f5b67a8a2e67179ada2a954227d670fe65fa9098457f698f56ddf248709b3", size = 345179, upload-time = "2026-05-28T11:59:35Z" }, - { url = "https://files.pythonhosted.org/packages/7c/46/d84105f062e626a1b233f863907288a4708c2d833b8b4c6fb2764bc080c0/rpds_py-2026.5.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b5c30f3f04eef4fbd362226a6f31d7c8895ca4fbb6e0b790f6890a98d8da8559", size = 376173, upload-time = "2026-05-28T11:59:36.43Z" }, - { url = "https://files.pythonhosted.org/packages/e2/ae/469d7959ce5b1201e1de135dc735b86db3b35dd0d1734f6a44246d5f061c/rpds_py-2026.5.1-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:277f6c82f0580848796c7ecc8a7173aa3bfb928e4ff831261c2f60a81dc270db", size = 383162, upload-time = "2026-05-28T11:59:37.995Z" }, - { url = "https://files.pythonhosted.org/packages/dc/a2/57853d31a1116a561aa072794602ad3f6341e18d70a8523f1bd5b9fc1e5a/rpds_py-2026.5.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:63c2c4c213f1a4e3f3de28ecab029dbdee976324e729c0d7a55211be72576b02", size = 495093, upload-time = "2026-05-28T11:59:39.453Z" }, - { url = "https://files.pythonhosted.org/packages/99/63/3a8eabcad9314b7daf5c65f451d2c33d989235cd8a5762186cf2c3f5a4f8/rpds_py-2026.5.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3350ec808fb538fe71a1f94dfaa0e29c598dfad805ce49f0caec5ae3183c652b", size = 389829, upload-time = "2026-05-28T11:59:40.896Z" }, - { url = "https://files.pythonhosted.org/packages/4b/25/05678d97fc25e2622df14dc530fb82023174ecfff6733991ed0d78f167bd/rpds_py-2026.5.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b1b964e3ab599e718dc46c018d104b1ebc007cbc6567d827c94a687fca56d77e", size = 374786, upload-time = "2026-05-28T11:59:42.626Z" }, - { url = "https://files.pythonhosted.org/packages/88/d1/8c90b6431e80a3b91b284a5c7c8c0c4f9c006444d90477a740d6e0f9c694/rpds_py-2026.5.1-cp313-cp313-manylinux_2_31_riscv64.whl", hash = "sha256:19cb09fab7b7fc96b2a6e28f2e34b72a3705ff27b37edb77455316e5d3f3dc9b", size = 386920, upload-time = "2026-05-28T11:59:44.124Z" }, - { url = "https://files.pythonhosted.org/packages/ff/99/4638f672ab356682d633ee0da9255f5b67ce6efd0b85eb94ad3e255e65a5/rpds_py-2026.5.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:abe76bcdba31e576cb83eeb8797aa0d882b738fef6dc65d0601fc753806a5b46", size = 405059, upload-time = "2026-05-28T11:59:47.177Z" }, - { url = "https://files.pythonhosted.org/packages/66/3f/3546524b6eb4cc2e1f363a3d638fa52f6c24faae3500c25fb488b02f1740/rpds_py-2026.5.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:8bff7073db3899158fff55ebf57b113a67030af26f80a18978f9f0aa60250ddf", size = 553030, upload-time = "2026-05-28T11:59:48.603Z" }, - { url = "https://files.pythonhosted.org/packages/c6/c3/7b3388c796fcf471bd17194242d4dc1a7608567c0fa422bcc1c5e79f9c1e/rpds_py-2026.5.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:8ba264fa49be666cd9cc56bf34ec7002fb3d27a4aee5bcb4d43d0d18feb1bb6f", size = 618975, upload-time = "2026-05-28T11:59:50.314Z" }, - { url = "https://files.pythonhosted.org/packages/61/1e/a3cb07f2795075d1d88efddae2f541359fde5f08c81ee114c29c2949c90a/rpds_py-2026.5.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:4860b603ddda0475a8885499b3729e90229d480105b42651962a5397d995fa89", size = 581178, upload-time = "2026-05-28T11:59:51.673Z" }, - { url = "https://files.pythonhosted.org/packages/a1/74/e758c03a5ef46f04c37f2651a2893db846d569ba8a7bca469d4b58939bcd/rpds_py-2026.5.1-cp313-cp313-win32.whl", hash = "sha256:7944270ae71383f6e2657dd7d5ce4eeb4ac2d0059a6738f0510583d462ab4842", size = 212481, upload-time = "2026-05-28T11:59:53.148Z" }, - { url = "https://files.pythonhosted.org/packages/70/ec/a2aca432db9c7359b40fa393eeeaa0d166c2f70175be956e75fa24197c44/rpds_py-2026.5.1-cp313-cp313-win_amd64.whl", hash = "sha256:88647f43a73c4e01be19b04ceef0c8d3a1958153604d13c773becd8016f2a0cf", size = 228519, upload-time = "2026-05-28T11:59:54.505Z" }, - { url = "https://files.pythonhosted.org/packages/29/60/a73bfdd45b096574556acf303bbd9fa9eed36ca8a818b514e2a5d5fe2b9d/rpds_py-2026.5.1-cp313-cp313-win_arm64.whl", hash = "sha256:453895624ecf7db7063b1004e44037522bbaef9ff6a945e59bc71662d7a03abd", size = 223446, upload-time = "2026-05-28T11:59:56.081Z" }, - { url = "https://files.pythonhosted.org/packages/18/e2/408105fd611823f00882aea810f3989a30d26b1bab8b6beb20f98c724e0e/rpds_py-2026.5.1-cp313-cp313t-macosx_10_12_x86_64.whl", hash = "sha256:b4e4bc98639ec915f512fde3aa7a95e0041d95d9c3cc86eea841fa63cb1e8600", size = 355287, upload-time = "2026-05-28T11:59:57.448Z" }, - { url = "https://files.pythonhosted.org/packages/8d/58/5c4a43436843c90d0f6d19f82c200c80e3843ca9fa07b237623327f6d384/rpds_py-2026.5.1-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:cacedb7a6e167680acba45ad5716e89067d225dc80da0d7040cae8c81d4572fa", size = 347033, upload-time = "2026-05-28T11:59:58.881Z" }, - { url = "https://files.pythonhosted.org/packages/fb/c2/1a71acdacaf4e259b10278fb87b039ded3cf80041bcd89dd8a3ea702ded6/rpds_py-2026.5.1-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:68700371c5d7ae1412862ddfa719090925c93ecf351c566d66f09d04b136ea00", size = 376891, upload-time = "2026-05-28T12:00:00.516Z" }, - { url = "https://files.pythonhosted.org/packages/c2/c8/535f3d9b65addd8e28aa87b83c6e526799c3717a88273db8ea795beeef7a/rpds_py-2026.5.1-cp313-cp313t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:296c799becfa849c779c8725494fe9ed94959ed886787df4364b058465bad7f0", size = 385646, upload-time = "2026-05-28T12:00:02.394Z" }, - { url = "https://files.pythonhosted.org/packages/1c/91/dc033f313345c354ade914dbe73cdb90b615a4409ea02430d5356794f3d8/rpds_py-2026.5.1-cp313-cp313t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d3858b908218ee108d0bbfb2095ccc237648053c9bf98affad7cb079acaf1d97", size = 498830, upload-time = "2026-05-28T12:00:04.189Z" }, - { url = "https://files.pythonhosted.org/packages/27/fc/90fcbea459dbb8ddc18a2e0fd1de9412b48bc84ffff2db771cf714bacfd6/rpds_py-2026.5.1-cp313-cp313t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4fb8d2e7cb2f850b169806d61d1b991738acec96500a75c30f49caf064ce7cef", size = 392830, upload-time = "2026-05-28T12:00:05.797Z" }, - { url = "https://files.pythonhosted.org/packages/b2/1d/46cd11a228c9750684a798d98f878be6f614aa762438da7378f035e79e35/rpds_py-2026.5.1-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:27b74c10ed6a8f190f4287f53bcfea348b92a84a9c9f70d30183d1e6172d580d", size = 379613, upload-time = "2026-05-28T12:00:07.433Z" }, - { url = "https://files.pythonhosted.org/packages/24/4a/d9b0c6af3a1de03eb93741bbe8be2bdce84d8fda8224f3005451d86df389/rpds_py-2026.5.1-cp313-cp313t-manylinux_2_31_riscv64.whl", hash = "sha256:b9a6528956191c48c52294a592dbd4a8386d7048bdb25c0efcb6b966466c6d83", size = 388183, upload-time = "2026-05-28T12:00:09.227Z" }, - { url = "https://files.pythonhosted.org/packages/c5/b4/db7aaabdda6d020afc87d981bcc2f57a434c7dec60ecfc2ab3dd50b20351/rpds_py-2026.5.1-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:af03e34e860047bc7a352b842856fcf78798fbb81132cc98bd2f907ab4eb9cd2", size = 408578, upload-time = "2026-05-28T12:00:10.779Z" }, - { url = "https://files.pythonhosted.org/packages/08/d6/070f6a41cbb343e2ac4171859bf3f3623e0ab002f72619d6d505313ec2de/rpds_py-2026.5.1-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:fea6e836d10abbe191d557d33bd58bd5987725fe63aa1eefe557d230209855bd", size = 553573, upload-time = "2026-05-28T12:00:12.443Z" }, - { url = "https://files.pythonhosted.org/packages/75/ab/1a71ea3589c4345dac0a0518f0e6a031cb42689277851b683c46d27463a5/rpds_py-2026.5.1-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:fc0c0f878ea770a0a8a462456c5ad36fc9fe6358e6b76fdadc7f17575e0b8bf1", size = 620861, upload-time = "2026-05-28T12:00:14.09Z" }, - { url = "https://files.pythonhosted.org/packages/8a/22/9bf80a56069c0c443fcfefac639a86a744550a2898817a6dfd3e26654924/rpds_py-2026.5.1-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:e0b360f316d966b048b085857630b3cc51f3db2f07b06f440eac8f695374d1e3", size = 585633, upload-time = "2026-05-28T12:00:15.66Z" }, - { url = "https://files.pythonhosted.org/packages/da/68/3b2c0a75c9e04125696f84ebdbbf304acf5a40b58ba4481cdb98a922c3ba/rpds_py-2026.5.1-cp313-cp313t-win32.whl", hash = "sha256:a2999883eedf72fdfb7520b92c7d4ec2572a71ff40239377aa604cc529eecafc", size = 210074, upload-time = "2026-05-28T12:00:17.291Z" }, - { url = "https://files.pythonhosted.org/packages/e7/8b/609157d5a25d37d4f29f92840ba531f416907c34ae5c5739dd21fc2bef98/rpds_py-2026.5.1-cp313-cp313t-win_amd64.whl", hash = "sha256:e07be2a9d7122bd6e82dea89814ef8dc893feb1aae97fec1630f3263bbb30e55", size = 228635, upload-time = "2026-05-28T12:00:18.73Z" }, - { url = "https://files.pythonhosted.org/packages/d4/6f/19c1918a4b590d8de87e712e4abe4b3875771eff60216fb6153cf6665c68/rpds_py-2026.5.1-cp314-cp314-macosx_10_12_x86_64.whl", hash = "sha256:1f2c391c3059798093b65df23aca2cac150460ae9c630d99dec83d703d9485b9", size = 349756, upload-time = "2026-05-28T12:00:20.217Z" }, - { url = "https://files.pythonhosted.org/packages/e5/60/a06fe7da34eca79dacbf958a2ba0c6eea85bc2b29de20080bf40f72f66fa/rpds_py-2026.5.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:413b424f7c4ee65ab5e5be91f5731be0f8b41a1ee2b12dfe810d716312e95a78", size = 343831, upload-time = "2026-05-28T12:00:21.711Z" }, - { url = "https://files.pythonhosted.org/packages/bf/ec/b2333b97b90e2a6ef6ca8ad386ee284968e74bcfe113b3f1a8d9036429a9/rpds_py-2026.5.1-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2c595a1d9255dce0599e13130d1440ab2506654f2b50294226ee06402f8fef63", size = 375127, upload-time = "2026-05-28T12:00:23.326Z" }, - { url = "https://files.pythonhosted.org/packages/14/7f/e00aae54067f2b488c4637961d5f58204d470795fc791085fa3f15060d2e/rpds_py-2026.5.1-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:1c27c5f6102eac8c03e7595a00827a53b271ba40a53b59ff8709170e0855ea4a", size = 379034, upload-time = "2026-05-28T12:00:24.89Z" }, - { url = "https://files.pythonhosted.org/packages/be/cc/423999bbb8ae8dc93c77fc1d5e984ade5eb89d237d3bb884ccfa72ae2890/rpds_py-2026.5.1-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6c7fcf61d44cacecaf3aea542b0e053db77972a4573e7ceda16fb2b399161195", size = 490823, upload-time = "2026-05-28T12:00:26.676Z" }, - { url = "https://files.pythonhosted.org/packages/0f/aa/c671bf660f12e68d3c52ff86c7066ed1372df5a0f4f2ff584e419b8207e7/rpds_py-2026.5.1-cp314-cp314-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2c817a189d4ee14290420e5ff051e4dd6baa13f3edf84685071dee07a6d538ee", size = 388144, upload-time = "2026-05-28T12:00:28.577Z" }, - { url = "https://files.pythonhosted.org/packages/19/c8/d63bb75b68afe77b229e3021c6031bcaf01da5db5b0e69d0d10f9ba679a7/rpds_py-2026.5.1-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:21846aac0ed2e0589f38c12dc44e77bb64e494b771eadbcf169cba00566ba7ba", size = 371959, upload-time = "2026-05-28T12:00:30.304Z" }, - { url = "https://files.pythonhosted.org/packages/82/35/c51122014d8274ff37dc606d60049c3db7d83da02b5b282511e5a906a9a6/rpds_py-2026.5.1-cp314-cp314-manylinux_2_31_riscv64.whl", hash = "sha256:b317c87a13f769a4e787819bd508aaa5d69aa09b0880de9af6d3a8a54571cdec", size = 383558, upload-time = "2026-05-28T12:00:31.764Z" }, - { url = "https://files.pythonhosted.org/packages/e3/f9/2790cb99c136a5363acdeacf5c27c56f3de0d4118a1f48fca83404c99c89/rpds_py-2026.5.1-cp314-cp314-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:ce87129d9f2c14fa6c4a8601fb80eb4488c80d38a20cd13758ef11123e14995d", size = 402789, upload-time = "2026-05-28T12:00:33.247Z" }, - { url = "https://files.pythonhosted.org/packages/e5/1b/e4fb584f8c75d35c38150ff6a332cda949e6f97acba1f4fd123b14ab56fe/rpds_py-2026.5.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:9cdddb6c1207d284d94fd1530adf57fbd797fe7c4b8704ba85f49414f2557e7d", size = 551405, upload-time = "2026-05-28T12:00:34.819Z" }, - { url = "https://files.pythonhosted.org/packages/d8/f7/a6731b4216cb3793ea1af5391da240f5683dacc0d13e034fe5fc3503f240/rpds_py-2026.5.1-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:4e237e139f94d3c036fd28eb9f564c99055476ff4ff05cd42be55ce349b5aa02", size = 616975, upload-time = "2026-05-28T12:00:36.268Z" }, - { url = "https://files.pythonhosted.org/packages/2c/ea/2e051a81d95d8e63f4b35a1c463a87e8766bc3d083c067c5dfb6bf220747/rpds_py-2026.5.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:ed0954b524873214369184a9c82b0eaa45a3fbb9a798cd95b17e0d98499e7ea0", size = 578701, upload-time = "2026-05-28T12:00:37.82Z" }, - { url = "https://files.pythonhosted.org/packages/65/56/b5f6fdb2083e32bca8a8993d89e70db114b4756c9e2c38421328126689d2/rpds_py-2026.5.1-cp314-cp314-win32.whl", hash = "sha256:2d88621d6a7d4dfa633d21abe90f280bb205274e16b1d1e61c6ad4640b2453b7", size = 209806, upload-time = "2026-05-28T12:00:39.492Z" }, - { url = "https://files.pythonhosted.org/packages/fb/80/65a5aa96c155e611d1ed844e4e1f57f3e36b021f396d9f8585d756e6b90d/rpds_py-2026.5.1-cp314-cp314-win_amd64.whl", hash = "sha256:cef8ac28d26f4dda3533060c20fbf80a325458fa9fd23ea72a73cdfa8e978838", size = 225985, upload-time = "2026-05-28T12:00:40.94Z" }, - { url = "https://files.pythonhosted.org/packages/27/7c/ad185212e87b05f196daef92bc5f3caf07298eb47c295b5585c3dd3093ac/rpds_py-2026.5.1-cp314-cp314-win_arm64.whl", hash = "sha256:eaaea962c68cdc68d4a533ba985ab8e9484277910bbfaa2ab3ef7732667bfed8", size = 221219, upload-time = "2026-05-28T12:00:43.15Z" }, - { url = "https://files.pythonhosted.org/packages/23/58/e14ae18759020334646b031e708ab4158d653a938822bfb7b95ef2e93aa3/rpds_py-2026.5.1-cp314-cp314t-macosx_10_12_x86_64.whl", hash = "sha256:21942f52dbbd5f8758bf021213d28bd45c39e873e65e2407faf5f1846f5761ad", size = 352148, upload-time = "2026-05-28T12:00:44.638Z" }, - { url = "https://files.pythonhosted.org/packages/31/9b/5f4a1e2f960bca3ac5d052b139dd31eed97b259f9d909173821760d542e8/rpds_py-2026.5.1-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:f414556f6e3958300ff941e40c9f97e3dc9774ddd1b3434c475d73dd354bbed3", size = 345196, upload-time = "2026-05-28T12:00:46.14Z" }, - { url = "https://files.pythonhosted.org/packages/1a/71/1d9574d6a2fa20ab60eaa55c7467f5aa20cbc770f341a05f09c0876f59e2/rpds_py-2026.5.1-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ef1013a8625c74043210190b246f5b1551e09757c1f356c6e4160ef96c5bc081", size = 374981, upload-time = "2026-05-28T12:00:47.531Z" }, - { url = "https://files.pythonhosted.org/packages/0c/9a/37e99f4915a80aa71670263c1267f7ae0af95f53a3f61e6c3bdc016d4515/rpds_py-2026.5.1-cp314-cp314t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:cc68e231a77a5f0d774ae278a1f8e55c0456501820847c1e4efb3829f3441df6", size = 379961, upload-time = "2026-05-28T12:00:49.216Z" }, - { url = "https://files.pythonhosted.org/packages/a8/ff/6e73f74b89d2e0715e0fc86b7dde893f9a61ae2f9b256ff3bdfe41ac4e94/rpds_py-2026.5.1-cp314-cp314t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9baffb505aff33acc69b422a19f77806680f3c8632227d79f48de8a810d1c2c5", size = 495965, upload-time = "2026-05-28T12:00:51.111Z" }, - { url = "https://files.pythonhosted.org/packages/ea/e0/425faba25f59d74d4638b267f7c7a80e8649d2ef4db10a19b0c4a71e6e6f/rpds_py-2026.5.1-cp314-cp314t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b8d2f912928d426e8cfa396f7f3f8d29a59e6689c86dcca3c420730c1096322b", size = 389526, upload-time = "2026-05-28T12:00:52.77Z" }, - { url = "https://files.pythonhosted.org/packages/c6/76/7a41960e3fddae47fab43a28684d5da981401dffd88253de0944148654cb/rpds_py-2026.5.1-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:90f628283be835db980c941767d41c9a27b5239e54ba0a9c1335247e82406964", size = 376190, upload-time = "2026-05-28T12:00:54.215Z" }, - { url = "https://files.pythonhosted.org/packages/27/60/5f38dc70824fc6951b51d35377e577a3a3a4c81a6769cc5a2de25ebe0ad1/rpds_py-2026.5.1-cp314-cp314t-manylinux_2_31_riscv64.whl", hash = "sha256:1ebb2f0ab7e16132995a72de805170e0203df0c3dd22e1ef1cd1fdd90bd7a131", size = 383921, upload-time = "2026-05-28T12:00:55.673Z" }, - { url = "https://files.pythonhosted.org/packages/60/1a/d60a38caa1505f4b9483c3fbbde12c94e1079154f4f401a6da96f7e77621/rpds_py-2026.5.1-cp314-cp314t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:f3df3d16ded76f1f8c9cdebd0e1ea55fdf4c23b812de189814da7cf229c22a81", size = 404766, upload-time = "2026-05-28T12:00:57.518Z" }, - { url = "https://files.pythonhosted.org/packages/87/ff/602fd3f174d6425f0bce05ad0dfbec0e96b38d0f7d08a79af5aa20083885/rpds_py-2026.5.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:9af8905b8f854990e40d5206aa5ac58d9b0fe0b7f351ff2bb086c20f6c8c6a47", size = 551343, upload-time = "2026-05-28T12:00:58.978Z" }, - { url = "https://files.pythonhosted.org/packages/b8/c1/1be13327acdbead3eca1fde03b6a34dbb011f1e864e217f0d32cc1779a7f/rpds_py-2026.5.1-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:036a36a87fb1cd3b214d11c4b3c4f7d2ddad933625dca1c900b56a057c07740a", size = 618502, upload-time = "2026-05-28T12:01:00.656Z" }, - { url = "https://files.pythonhosted.org/packages/f3/d7/afb49b49d7f2be8b7ba1a9f0977fa5168003437b93086726f066544e8351/rpds_py-2026.5.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:62ae3853454fe9ef283a03c96c2d835d39e84b14643a9d62c82ef0fb87d702ca", size = 581916, upload-time = "2026-05-28T12:01:02.22Z" }, - { url = "https://files.pythonhosted.org/packages/25/d1/dbef8c1f8a10f07beb62b5f054e20099fd9924b3ec001b8f0b6ac7813a85/rpds_py-2026.5.1-cp314-cp314t-win32.whl", hash = "sha256:6c3d771a46ec18b12af06ce36243a9a80b07a5d0515236332d90863ca8bb326a", size = 207855, upload-time = "2026-05-28T12:01:03.821Z" }, - { url = "https://files.pythonhosted.org/packages/2a/72/bfa4e61ab8e7dc1c8adf397e05e6cbdd4239357bd72b248d3de662f23915/rpds_py-2026.5.1-cp314-cp314t-win_amd64.whl", hash = "sha256:c93c629be4636cf54337bd5f06c104d55e42ced54d681f6fe21ae510a65116f6", size = 225422, upload-time = "2026-05-28T12:01:05.194Z" }, - { url = "https://files.pythonhosted.org/packages/27/3a/7b5da92b640f67b6717ccafc83cdd06bfa7ff2395c3685c68922bb54d703/rpds_py-2026.5.1-cp315-cp315-macosx_10_12_x86_64.whl", hash = "sha256:3574b55c604b8f75dacb007136508bbc0db406e626301778096a133327e7f2fb", size = 349576, upload-time = "2026-05-28T12:01:06.722Z" }, - { url = "https://files.pythonhosted.org/packages/d7/8a/2aafd7ad355a1bd48ca76e2262b74b15e6432b5a1efe150efd4d779cd55d/rpds_py-2026.5.1-cp315-cp315-macosx_11_0_arm64.whl", hash = "sha256:94068eb3ae6d43f5a786b7db96a406a34e6d5c24489feef32fd6e8946ea7b291", size = 343640, upload-time = "2026-05-28T12:01:08.441Z" }, - { url = "https://files.pythonhosted.org/packages/f7/7d/6c9523c1abbe840a1b7fba3c516d48e1d3487cc80fea4366c4071cf56784/rpds_py-2026.5.1-cp315-cp315-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f3a5b10e8ce894825f380a8f1b6444cf73c294dfea62afbb2d13e3a9e630cec1", size = 375322, upload-time = "2026-05-28T12:01:09.934Z" }, - { url = "https://files.pythonhosted.org/packages/5a/5d/0b7b03fb1dc509321f01de3149784ab773e34c8573022029af8076afcb9c/rpds_py-2026.5.1-cp315-cp315-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:fc09f82e63d4bcd58149572f857a431bae851dc747e313c3b5bdf7abb907fda8", size = 379066, upload-time = "2026-05-28T12:01:11.48Z" }, - { url = "https://files.pythonhosted.org/packages/d7/e2/8ef6012999ebf1cb1c22f876d9ce5e63d960fd4631d2af3202d3f480aa25/rpds_py-2026.5.1-cp315-cp315-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e10464d17df3b582745c25cec695cb9558bca2cb6ddb631aee1787fc72c767b2", size = 494586, upload-time = "2026-05-28T12:01:13.051Z" }, - { url = "https://files.pythonhosted.org/packages/80/af/1eeb029bec67582c226b7809172207cd005073af4ebd906e65ff494f4983/rpds_py-2026.5.1-cp315-cp315-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ba05adbf15d994c38ec0b7ab32e858e5110c21e9009a00a86545fd220f84e038", size = 388415, upload-time = "2026-05-28T12:01:14.631Z" }, - { url = "https://files.pythonhosted.org/packages/18/23/ffbe10711c4d766c1cab0557d6906c074f795814863c67b351355d29354a/rpds_py-2026.5.1-cp315-cp315-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:77c004fdc7b891967106f78ddfd7b076bfe6813c6139c6fff6aed3bcaa960b26", size = 372427, upload-time = "2026-05-28T12:01:16.153Z" }, - { url = "https://files.pythonhosted.org/packages/bd/3a/30ba4a6ad457e5b070c18d742a33fb77d8d922b565cc881f8a5313d63bfe/rpds_py-2026.5.1-cp315-cp315-manylinux_2_31_riscv64.whl", hash = "sha256:83bcf894486c9d78dd290d3c0124ff6dd8875d3025e2090a8ec49fcc37c55fdd", size = 383615, upload-time = "2026-05-28T12:01:17.809Z" }, - { url = "https://files.pythonhosted.org/packages/d3/69/62e242b53ce39c0814bd24e1a6e6eba6c92be716277745f317f9540a2e7b/rpds_py-2026.5.1-cp315-cp315-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:c3df104083952a0e0c6f10de33e440eabe98fb6317d23e1a58c68f6df08d01b9", size = 402786, upload-time = "2026-05-28T12:01:19.419Z" }, - { url = "https://files.pythonhosted.org/packages/38/c1/a770b9c186928a1ed0f7e6d7ae50e7f3950ed23e3f9e366dbc8e38cb55de/rpds_py-2026.5.1-cp315-cp315-musllinux_1_2_aarch64.whl", hash = "sha256:980450826cf22e133c57e0835070bdd0dd3f73b9b708c3ce223def2cb9469e14", size = 551583, upload-time = "2026-05-28T12:01:21.013Z" }, - { url = "https://files.pythonhosted.org/packages/21/7c/68e8579b95375b70d2a963103c42e705856cdb98569258bd807f4423891c/rpds_py-2026.5.1-cp315-cp315-musllinux_1_2_i686.whl", hash = "sha256:205dde846f24332ab0c1188699a043b8d165b79bb84529ce272c45048ff6be01", size = 616941, upload-time = "2026-05-28T12:01:22.548Z" }, - { url = "https://files.pythonhosted.org/packages/70/a1/a6135aed5730ff03ab957182259987ac11e55fb392a28dc6f0592048a280/rpds_py-2026.5.1-cp315-cp315-musllinux_1_2_x86_64.whl", hash = "sha256:3966b82dd563176396df030f3dd52a6e54cb69b718e95e78bd555ed3d1e0185d", size = 578349, upload-time = "2026-05-28T12:01:24.118Z" }, - { url = "https://files.pythonhosted.org/packages/09/6e/f24201a76a84e6c49d0bdfdfcb735210e21701e9b21c5bfc0ba497dd62f6/rpds_py-2026.5.1-cp315-cp315-win32.whl", hash = "sha256:7818f8d0a415be74d2be3590b0a1c1f463a642f4d0217e7d10602dceef5b79aa", size = 209922, upload-time = "2026-05-28T12:01:25.522Z" }, - { url = "https://files.pythonhosted.org/packages/9e/e4/966bc240bb0485fc265278f6de44d05834bf0b3618886e0b22e33d54c49a/rpds_py-2026.5.1-cp315-cp315-win_amd64.whl", hash = "sha256:b3cc20c0d800af78fd0fac68086e28c1856cec51ea528bb81ea851aa40d39325", size = 226003, upload-time = "2026-05-28T12:01:27.062Z" }, - { url = "https://files.pythonhosted.org/packages/5c/5c/a15a59269cd5e74472734516c73795c15eccfc841b3d4b0228c3f53f19d0/rpds_py-2026.5.1-cp315-cp315-win_arm64.whl", hash = "sha256:3609e9939a8a76cd904cf98a3f1f13b5dc7e150adeaee89e0ea09652ea213e16", size = 221245, upload-time = "2026-05-28T12:01:28.51Z" }, - { url = "https://files.pythonhosted.org/packages/e0/22/135ce03804e179a71ceb13be095deda4a279bc88f7a6b8fa161c5ad44e12/rpds_py-2026.5.1-cp315-cp315t-macosx_10_12_x86_64.whl", hash = "sha256:5d333a7127d4b307601ac37792bee01bb95c867cbfacf21b6375b804d6bbd723", size = 352015, upload-time = "2026-05-28T12:01:30.214Z" }, - { url = "https://files.pythonhosted.org/packages/3b/5f/f1f6d2652eb9d848f6eb369d8db83a2da6249bb49ad2c2a48f45d54538d3/rpds_py-2026.5.1-cp315-cp315t-macosx_11_0_arm64.whl", hash = "sha256:b5f077b44a4f7808520f66dae234988d867deb9aed9be5da057ce9ba831b2a41", size = 345016, upload-time = "2026-05-28T12:01:31.656Z" }, - { url = "https://files.pythonhosted.org/packages/88/66/b74182775691ea2290c99e52ac8d5db844e56fbec90ce421f107658c8314/rpds_py-2026.5.1-cp315-cp315t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:55d8f9b7b78c9538fc9e04e82ec0e888ff0c3cffcfad152c77e57cd09351a98a", size = 374775, upload-time = "2026-05-28T12:01:33.136Z" }, - { url = "https://files.pythonhosted.org/packages/ff/8f/15e5a61d9f0a43902d36561d4f07cae6ae9f4716be825159fd72717f33af/rpds_py-2026.5.1-cp315-cp315t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e3a8ae58895ac107ed934a6bf51e5846f95c53b9b940c2c6d310838fd5846358", size = 380270, upload-time = "2026-05-28T12:01:34.574Z" }, - { url = "https://files.pythonhosted.org/packages/02/c3/f859b12763a80540cdf2af0f15b19904cf756a71d7bdd3f82ff3e5b1bbf9/rpds_py-2026.5.1-cp315-cp315t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0957cf3c2b8632ec7aaebffebea8005b353cc2a237b6e2ae3c2cac0820704cfb", size = 495285, upload-time = "2026-05-28T12:01:36.127Z" }, - { url = "https://files.pythonhosted.org/packages/1c/c7/ff27c2ac8411d30b03b1829fd88cae8dad1a4d0da48dd25e57c4038042e6/rpds_py-2026.5.1-cp315-cp315t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c396c1304de421050b3681ea70f371874b54d41b0151e96109758144c231e30b", size = 389581, upload-time = "2026-05-28T12:01:37.635Z" }, - { url = "https://files.pythonhosted.org/packages/6e/67/fe92ee32a6cc05c77228a2f8b1762e7124f386ec20ff83d0757b762d58d0/rpds_py-2026.5.1-cp315-cp315t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:aad1bff7f666b9598e573815affd666aac6a13a585dde336f843e33350c7fadc", size = 376041, upload-time = "2026-05-28T12:01:39.307Z" }, - { url = "https://files.pythonhosted.org/packages/f8/91/b4d6685c27aba55bd82f25b278be8237038117d05f9659a6213ad3408130/rpds_py-2026.5.1-cp315-cp315t-manylinux_2_31_riscv64.whl", hash = "sha256:656a042550878f12d45752452d47094b7cfe5ad1e9d7b87b5a22ad3ae5ff8015", size = 383946, upload-time = "2026-05-28T12:01:41.043Z" }, - { url = "https://files.pythonhosted.org/packages/bd/79/2c1d832a53c8e0f8e98fc970ec257b950fecd4f62be2ab7182b500a0cbc8/rpds_py-2026.5.1-cp315-cp315t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:73c4bd4f70294737b5206a3e8e30ccadbf8a60301831c8ea23eec5dbeea1ecfa", size = 405526, upload-time = "2026-05-28T12:01:43.032Z" }, - { url = "https://files.pythonhosted.org/packages/78/c4/c98117b03c6a8581ab2c2dfccfe9a5ad82bd8128a3c28b46a6ad2d97c393/rpds_py-2026.5.1-cp315-cp315t-musllinux_1_2_aarch64.whl", hash = "sha256:43bca78665423cabae77146f2fe7ce55272b6c8d55d82cca83effd42c7e13972", size = 551165, upload-time = "2026-05-28T12:01:44.648Z" }, - { url = "https://files.pythonhosted.org/packages/3b/c1/bc479ca069200af730881b1bd525e3114b2b391a351509fcb1b772f28086/rpds_py-2026.5.1-cp315-cp315t-musllinux_1_2_i686.whl", hash = "sha256:42d0f20e85e549c870749d0e247f0c10d318a45b7e9676d575d2dcb04a1b2e66", size = 618778, upload-time = "2026-05-28T12:01:46.337Z" }, - { url = "https://files.pythonhosted.org/packages/77/65/38ab2f90df44c2febfb63cc10ced40763d9b4bc94d173e734528663fe7f5/rpds_py-2026.5.1-cp315-cp315t-musllinux_1_2_x86_64.whl", hash = "sha256:b1be5c35683684d5331b93600c210e8367c254683d8a6df6bd21bd2da3a334fb", size = 581839, upload-time = "2026-05-28T12:01:48.109Z" }, - { url = "https://files.pythonhosted.org/packages/15/2d/ce1f605fe036aadd460e5822e578c6c7ec3a860936cca37d6e0f299daa77/rpds_py-2026.5.1-cp315-cp315t-win32.whl", hash = "sha256:75808f6c38ce7749bb68cc2770161aae5045e6c6f6781a9782e74b93304399df", size = 207866, upload-time = "2026-05-28T12:01:49.648Z" }, - { url = "https://files.pythonhosted.org/packages/79/cb/966040123eb102371559746908ef2c9471f4d43e17ec9a645a2258dab64b/rpds_py-2026.5.1-cp315-cp315t-win_amd64.whl", hash = "sha256:90bd6630002a1c7f09e7843dd79f0d24f3d2897cc25a753480917865d14f15b3", size = 225441, upload-time = "2026-05-28T12:01:51.408Z" }, - { url = "https://files.pythonhosted.org/packages/42/56/3fe0fb34820ff667be791b3a3c22b85e8bcba54e9c832f47438c191fa7be/rpds_py-2026.5.1-pp311-pypy311_pp73-macosx_10_12_x86_64.whl", hash = "sha256:edf2765d84e42447f112ad877af8fe1db0089aaec5b28e88d6eab45e7fe99cea", size = 357151, upload-time = "2026-05-28T12:01:53.43Z" }, - { url = "https://files.pythonhosted.org/packages/8b/f2/3eb9ccdb9f143b8c9b003978898cb497f942a324c077401e6b8834238e63/rpds_py-2026.5.1-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:ad3773236e95f7f33991eb125224b7da66f206504d032a253a02da7e134519fb", size = 350195, upload-time = "2026-05-28T12:01:54.901Z" }, - { url = "https://files.pythonhosted.org/packages/a7/24/dbda232bc4f3ed732120692ab0d2c8402cb020516556d8bee622dcef2413/rpds_py-2026.5.1-pp311-pypy311_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a04df86b3f0fade39ec8fd0e0aab089b1da9fbd2b48df778a57ef96f5e7d38df", size = 381850, upload-time = "2026-05-28T12:01:56.601Z" }, - { url = "https://files.pythonhosted.org/packages/40/30/32e769839a358f78810c234f160f2cc21d1e4e47e1c0e0e0d535be5a0219/rpds_py-2026.5.1-pp311-pypy311_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:6142dbd80c4df62a5d899f0d616d417f84e0bc8d32526c8e5589019d75d028a7", size = 387899, upload-time = "2026-05-28T12:01:58.212Z" }, - { url = "https://files.pythonhosted.org/packages/ab/86/ec84d243aadb3b34b71dd26a010d0930b2d284ff5fc9a69fec53810ee6fd/rpds_py-2026.5.1-pp311-pypy311_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0b35217adefe87f2fe4db7e9766cabe84744bfe9616d9667be18988928c7f2dc", size = 501618, upload-time = "2026-05-28T12:01:59.888Z" }, - { url = "https://files.pythonhosted.org/packages/74/25/b60e52686bbff777a64f9e4f4d3dd57980dc846913777177a2c92e4937aa/rpds_py-2026.5.1-pp311-pypy311_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b95d5e11fc712b752081183a55a244c03cd00570489edd7014d8899f8ceb8162", size = 394003, upload-time = "2026-05-28T12:02:01.482Z" }, - { url = "https://files.pythonhosted.org/packages/9b/c7/b3a6a588cc2219510ef3f42e207483a93950bedd1e3a0fd4015c95cff9e5/rpds_py-2026.5.1-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:141c9498daf2ace9eda35d2b0e376f9ea8b058d84f2aef4f96fccfd449a2f251", size = 379778, upload-time = "2026-05-28T12:02:03.197Z" }, - { url = "https://files.pythonhosted.org/packages/31/00/c7dba3fc8a3da8cb3f6db1eb3386be4d79c2e97c6890d20eb9ac66ae8c43/rpds_py-2026.5.1-pp311-pypy311_pp73-manylinux_2_31_riscv64.whl", hash = "sha256:6f249f8b860a200ad35193af961183ebe9132710484e6f6ce0cf89fd83c63a9a", size = 392359, upload-time = "2026-05-28T12:02:04.817Z" }, - { url = "https://files.pythonhosted.org/packages/93/dd/472ba494c70753f93745992c99855bee0636daf74e6984e5e003f150316f/rpds_py-2026.5.1-pp311-pypy311_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:e4abbf391a70be864920858bf360f4fb380577c9a0f732438a1996726e2c195b", size = 412820, upload-time = "2026-05-28T12:02:06.401Z" }, - { url = "https://files.pythonhosted.org/packages/1d/6f/93831a3bfe789542ed0c1d0d74b78b440f055d6dc3ea4640eba2d95e6e23/rpds_py-2026.5.1-pp311-pypy311_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:c74005a7bb87752acf351c93897ec63ad77a07a0da7ecad9c050e32e7286ba34", size = 557243, upload-time = "2026-05-28T12:02:08.013Z" }, - { url = "https://files.pythonhosted.org/packages/1f/ff/0b3d604614ffc77522c6b288fdbce68957eb583da1002aa65ba38ac0ee40/rpds_py-2026.5.1-pp311-pypy311_pp73-musllinux_1_2_i686.whl", hash = "sha256:8213afbe8a3a906fb9acb2014423fe3359ee783d0bf90995f70623a3217bfa6c", size = 623541, upload-time = "2026-05-28T12:02:09.661Z" }, - { url = "https://files.pythonhosted.org/packages/ea/ea/e7b0251441da9adfeaebcf29601d10f2a1455fcf0772fae9e7e19032bd96/rpds_py-2026.5.1-pp311-pypy311_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:8c43a8a973270fd173bf48cdf80bbe66312421cba68d40845034f174f2389049", size = 586326, upload-time = "2026-05-28T12:02:11.47Z" }, +sdist = { url = "https://files.pythonhosted.org/packages/aa/2a/9618a122aeb2a169a28b03889a2995fe297588964333d4a7d67bdf46e147/rpds_py-2026.6.3.tar.gz", hash = "sha256:1cebd1337c242e4ec2293e541f712b2da849b29f48f0c293684b71c0632625d4", size = 64051, upload-time = "2026-06-30T07:17:53.009Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/94/1f/a2dca5ffdbf1d475ffc4e80e4d5d720ff3a00f691795910116960ee12511/rpds_py-2026.6.3-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:7b689145a1485c335569bd056464f3243a29af7ed3871c7be31ad624ba239bc7", size = 342174, upload-time = "2026-06-30T07:14:54.821Z" }, + { url = "https://files.pythonhosted.org/packages/4d/dc/323d08583c0832911768663d1944f0107fcd4088704858d84b5e06d105a0/rpds_py-2026.6.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:db08f45aecde626498fb3df07bcf6d2ec040af42e859a4f5040d79c200342911", size = 345513, upload-time = "2026-06-30T07:14:56.515Z" }, + { url = "https://files.pythonhosted.org/packages/0b/2a/e31989834d18d2f26ec1d2774c5b1eb3331df4ea8ada525175294c94b48a/rpds_py-2026.6.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:acc992ab27b15f852c76755eb2ab7dce86585ddadba6fa5946e58556088845b4", size = 373783, upload-time = "2026-06-30T07:14:57.736Z" }, + { url = "https://files.pythonhosted.org/packages/87/fe/e80107ee3639585c9941c17d6a42cd65325022f656c023191fce78c324c8/rpds_py-2026.6.3-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:7f88d653e7b3b779d71ae7454e20dcc9b6bae903f33c269db9f2be41bda3f261", size = 378316, upload-time = "2026-06-30T07:14:59.077Z" }, + { url = "https://files.pythonhosted.org/packages/22/6f/81e3adf81acfb6fa694de2a6e4e7d8863121e3e0799e0a7725e6cf5679c4/rpds_py-2026.6.3-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e52655eaf81e32593abedaa4bfe33170c8cfedf3365ed9be6e11e07f148f0278", size = 499423, upload-time = "2026-06-30T07:15:00.488Z" }, + { url = "https://files.pythonhosted.org/packages/2d/9a/41263969df0ce3d9af2a96d5005a288200af1989aed3354bfceb5fc0b21f/rpds_py-2026.6.3-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:dfcc8b909769d19db55c7cc9541eb64b9b774b1057ffffb4f1048070475bb9f9", size = 386077, upload-time = "2026-06-30T07:15:01.911Z" }, + { url = "https://files.pythonhosted.org/packages/5e/19/7e98f468bd50346faff5b10e5297374b443bfdddacc8e9fbc65984539597/rpds_py-2026.6.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9c1255b302953c86a486b81d330d5ee1d5bd937691ce271b6be0ef0e299eaab7", size = 371315, upload-time = "2026-06-30T07:15:03.317Z" }, + { url = "https://files.pythonhosted.org/packages/99/3c/2b973b4d371906a134b03decfea7f5d9835a2c6d263454392e15b64b5b18/rpds_py-2026.6.3-cp311-cp311-manylinux_2_31_riscv64.whl", hash = "sha256:8d2294a31386bfa251d8c8a39472beee17db67d4f1a6eabea665d35c9a4461c3", size = 383502, upload-time = "2026-06-30T07:15:04.627Z" }, + { url = "https://files.pythonhosted.org/packages/98/2a/12e2799500af0a307bca76b63361c51f9fe479223561489c29eea1f2ee41/rpds_py-2026.6.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:f8f23ead891a3b762f35ab3b04623da7056545b48aa60d59957e6789914545da", size = 402673, upload-time = "2026-06-30T07:15:05.856Z" }, + { url = "https://files.pythonhosted.org/packages/2d/e3/21e5872d165fe08be4f229e3d5ee9d90019c0bf0e5538de60dbd54009450/rpds_py-2026.6.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:421aba32367055614287a4292b6a17f1939c9452299f7a0209c117e990b646d4", size = 549964, upload-time = "2026-06-30T07:15:07.159Z" }, + { url = "https://files.pythonhosted.org/packages/1a/d0/5ee0fe36844297de8123bee27bc12078c1a7416ad9f1b8a8ca18d6b0c0ac/rpds_py-2026.6.3-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:1e5822dfc2f0d4ab7e745eaa6d85945069329beeccef965af3f3bb26058fcab6", size = 615446, upload-time = "2026-06-30T07:15:08.531Z" }, + { url = "https://files.pythonhosted.org/packages/b1/80/1ea5873cb683f2fbe5f21b23ea1f6d179ead19f3c5b249b7eb5dca568ef2/rpds_py-2026.6.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:83e35b57523816c8613fd0776b40cd8bb9f596b37ddd2692eb4a6bb5ab2f8c93", size = 576975, upload-time = "2026-06-30T07:15:09.97Z" }, + { url = "https://files.pythonhosted.org/packages/c9/e1/90ef639217a5ddb15b7f4f61b1c33911fd044ad03c311bafdd2bcab85582/rpds_py-2026.6.3-cp311-cp311-win32.whl", hash = "sha256:de3eceba0b683bcbb1ab93da016d0270df1f9ae7be716b40214c5dafac6ea45a", size = 204453, upload-time = "2026-06-30T07:15:11.324Z" }, + { url = "https://files.pythonhosted.org/packages/f2/b7/b7a1695d7af36f521fb11e80d6d3adbd744f73b921859bd3c2a2c0dc706f/rpds_py-2026.6.3-cp311-cp311-win_amd64.whl", hash = "sha256:2c54a076ca4d370980ab57bc0e31df57bbe8d41340436a90ef8b1219a3cbb127", size = 223219, upload-time = "2026-06-30T07:15:12.476Z" }, + { url = "https://files.pythonhosted.org/packages/d7/a2/145afacf796e4506062825941176ad9445c2dcf2b3b6a1f13d3030a15e19/rpds_py-2026.6.3-cp311-cp311-win_arm64.whl", hash = "sha256:168c733a7112e071bb7a66460e667edfcff06c017a3c523f7a8a8e08d0140804", size = 219137, upload-time = "2026-06-30T07:15:13.631Z" }, + { url = "https://files.pythonhosted.org/packages/5c/be/2e8974163072e7bab7df1a5acd54c4498e75e35d6d18b864d3a9d5dadc92/rpds_py-2026.6.3-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:a0811d33247c3d6128a3001d763f2aa056bb3425204335400ac54f89eec3a0d0", size = 343691, upload-time = "2026-06-30T07:15:14.96Z" }, + { url = "https://files.pythonhosted.org/packages/a4/73/319dfa745dd668efe89309141ded489126461fcecd2b8f3a3cda185129b6/rpds_py-2026.6.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:538949e262e46caa31ac01bdb3c1e8f642622922cacbabbae6a8445d9dc33eaf", size = 338542, upload-time = "2026-06-30T07:15:16.267Z" }, + { url = "https://files.pythonhosted.org/packages/21/63/4239893be1c4d09b709b1a8f6be4188f0870084ff547f46606b8a75f1b03/rpds_py-2026.6.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:55927d532399c2c646100ff7feb48eaa940ad70f42cd68e1328f3ded9f81ca24", size = 368180, upload-time = "2026-06-30T07:15:17.62Z" }, + { url = "https://files.pythonhosted.org/packages/1c/ca/9c5de382225234ceb37b1844ebdb140db12b2a278bb9efe2fcd19f6c82ce/rpds_py-2026.6.3-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:f56f1695bc5c0871cbc33dc0130fcf503aab0c57dcc5a6700a4f49eba4f2652e", size = 375067, upload-time = "2026-06-30T07:15:18.952Z" }, + { url = "https://files.pythonhosted.org/packages/87/dc/863f69d1bf04ade34b7fe0d59b9fdf6f0135fe2d7cbca74f1d665589559d/rpds_py-2026.6.3-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:270b293dae9058fc9fcedab50f13cebf46fb8ed1d1d54e0521a9da5d6b211975", size = 490509, upload-time = "2026-06-30T07:15:20.434Z" }, + { url = "https://files.pythonhosted.org/packages/ce/ef/eac16a12048b45ec7c7fa94f2be3438a5f26bf9cc8580b18a1cfd609b7f6/rpds_py-2026.6.3-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:127565fead0a10943b282957bd5447804ff3160ad79f2ad2635e6d249e380680", size = 382754, upload-time = "2026-06-30T07:15:21.831Z" }, + { url = "https://files.pythonhosted.org/packages/04/8f/d2f3f532616be4d06c316ef119683e832bd3d41e112bf3a88f4151c95b17/rpds_py-2026.6.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ecabd69db66de867690f9797f2f8fa27ba501bbc24540cbdbdc649cd15888ba6", size = 366189, upload-time = "2026-06-30T07:15:23.371Z" }, + { url = "https://files.pythonhosted.org/packages/e3/29/41a7b0e98a4b44cd676ab7598419623373eb43b20be68c084935c1a8cf88/rpds_py-2026.6.3-cp312-cp312-manylinux_2_31_riscv64.whl", hash = "sha256:58eadac9cd119677b60e1cf8ac4052f35949d71b8a9e5556efccbe82533cf22a", size = 377750, upload-time = "2026-06-30T07:15:24.659Z" }, + { url = "https://files.pythonhosted.org/packages/2e/05/ecda0bec46f9a1565090bcdc941d023f6a25aff85fda28f89f8d19878152/rpds_py-2026.6.3-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:7491ee23305ac3eb59e492b6945881f5cd77a6f731061a3f25b77fd40f9e99a4", size = 395576, upload-time = "2026-06-30T07:15:25.987Z" }, + { url = "https://files.pythonhosted.org/packages/68/a8/6ed52f03ee6cb854ce78785cc9a9a672eb880e83fd7224d471f667d151f1/rpds_py-2026.6.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:2c99f7e8ccb3dd6e3e4bfeac657a7b208c9bac8075f4b078c02d7404c34107fa", size = 543807, upload-time = "2026-06-30T07:15:27.356Z" }, + { url = "https://files.pythonhosted.org/packages/8f/d6/156c0d3eea27ba09b92562ba2364ba124c0a061b199e17eac637cd25a5e2/rpds_py-2026.6.3-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:62698275682bf121181861295c9181e789030a2d516071f5b8f3c23c170cd0fc", size = 611187, upload-time = "2026-06-30T07:15:28.931Z" }, + { url = "https://files.pythonhosted.org/packages/f1/31/774212ed989c62f7f310220089f9b0a3fb8f40f5443d1727abd5d9f52bc9/rpds_py-2026.6.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:a214c993455f99a89aaeadc9b21241900037adc9d97203e374d75513c5911822", size = 573030, upload-time = "2026-06-30T07:15:30.553Z" }, + { url = "https://files.pythonhosted.org/packages/c9/50/22f73127a41f1ce4f87fe39aadfb9a126345801c274aa93ae88456249327/rpds_py-2026.6.3-cp312-cp312-win32.whl", hash = "sha256:501f9f04a588d6a09179368c57071301445191767c64e4b52a6aa9871f1ef5ed", size = 202185, upload-time = "2026-06-30T07:15:32.027Z" }, + { url = "https://files.pythonhosted.org/packages/04/3a/f0ee4d4dde9d3b69dedf1b5f74e7a40017046d55052d173e418c6a94f960/rpds_py-2026.6.3-cp312-cp312-win_amd64.whl", hash = "sha256:2c958bf94822e9290a40aaf2a822d4bc5c88099093e3948ad6c571eca9272e5f", size = 220394, upload-time = "2026-06-30T07:15:33.359Z" }, + { url = "https://files.pythonhosted.org/packages/f3/83/3382fe37f809b59f02aac04dbc4e765b480b46ee0227ed516e3bdc4d3dfc/rpds_py-2026.6.3-cp312-cp312-win_arm64.whl", hash = "sha256:22bffe6042b9bcb0822bcd1955ec00e245daf17b4344e4ed8e9551b976b63e96", size = 215753, upload-time = "2026-06-30T07:15:34.778Z" }, + { url = "https://files.pythonhosted.org/packages/a4/9e/b818ee580026ec578138e961027a68820c40afeb1ec8f6819b54fb99e196/rpds_py-2026.6.3-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:3cfe765c1da0072636ca06628261e0ea05688e160d5c8a03e0217c3854037223", size = 343012, upload-time = "2026-06-30T07:15:36.005Z" }, + { url = "https://files.pythonhosted.org/packages/f3/6b/686d9dc4359a8f163cfbbf89ee0b4e586431de22fe8248edb63a8cf50d49/rpds_py-2026.6.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:f4d78253f6996be4901669ad25319f842f740eccf4d58e3c7f3dd39e6dde1d8f", size = 338203, upload-time = "2026-06-30T07:15:37.462Z" }, + { url = "https://files.pythonhosted.org/packages/9e/9b/069aa329940f8207615e091f5eedbbd40e1e15eac68a0790fd05ccdf796c/rpds_py-2026.6.3-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:54f45a148e28767bf343d33a684693c70e451c6f4c0e9904709a723fafbdfc1f", size = 367984, upload-time = "2026-06-30T07:15:39.008Z" }, + { url = "https://files.pythonhosted.org/packages/14/db/34c203e4becff3703e4d3bc121842c00b8689197f398161203a880052f4e/rpds_py-2026.6.3-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:842e7b070435622248c7a2c44ae53fa1440e073cc3023bc919fed570884097a7", size = 374815, upload-time = "2026-06-30T07:15:40.253Z" }, + { url = "https://files.pythonhosted.org/packages/ee/7d/8071067d2cc453d916ad836e828c943f575e8a44612537759002a1e07381/rpds_py-2026.6.3-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8020133a74bd81b4572dd8e4be028a6b1ebcd70e6726edc3918008c08bee6ee6", size = 490545, upload-time = "2026-06-30T07:15:41.729Z" }, + { url = "https://files.pythonhosted.org/packages/a3/42/da06c5aa8f0484ff07f270787434204d9f4535e2f8c3b51ed402267e63c3/rpds_py-2026.6.3-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cdc7e35386f3847df728fbcb5e887e2d79c19e2fa1eba9e51b6621d23e3243af", size = 382828, upload-time = "2026-06-30T07:15:43.327Z" }, + { url = "https://files.pythonhosted.org/packages/57/d7/fe978efc2ae50abe48eb7464668ea99f53c010c60aeebb7b35ad27f23661/rpds_py-2026.6.3-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:acac386b453c2516111b50985d60ce46e7fadb5ea71ae7b25f4c946935bf27cf", size = 365678, upload-time = "2026-06-30T07:15:44.992Z" }, + { url = "https://files.pythonhosted.org/packages/69/9d/1d8922e1990b2a6eb532b6ff53d3e73d2b3bbffc84116c75826bee73dfc6/rpds_py-2026.6.3-cp313-cp313-manylinux_2_31_riscv64.whl", hash = "sha256:425560c6fa0415f27261727bb20bd097568485e5eb0c121f1949417d1c516885", size = 377811, upload-time = "2026-06-30T07:15:46.523Z" }, + { url = "https://files.pythonhosted.org/packages/b1/3d/198dceafb4fb034a6a47347e1b0735d34e0bd4a50be4e898d408ee66cb14/rpds_py-2026.6.3-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:a550fb4950a06dde3beb4721f5ad4b25bf4513784665b0a8522c792e2bd822a4", size = 395382, upload-time = "2026-06-30T07:15:47.955Z" }, + { url = "https://files.pythonhosted.org/packages/1f/f1/13968e49655d40b6b19d8b9140296bbc6f1d86b3f0f6c346cf9f1adddf4b/rpds_py-2026.6.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:4f4bca01b63096f606e095734dd56e74e175f94cfbf24ff3d63281cec61f7bb7", size = 543832, upload-time = "2026-06-30T07:15:49.33Z" }, + { url = "https://files.pythonhosted.org/packages/ac/ab/289bcb1b90bd3e40a2900c561fa0e2087345ecbb094f0b870f2345142b7c/rpds_py-2026.6.3-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:ccffae9a092a00deb7efd545fe5e2c33c33b88e7c054337e9a74c179347d0b7d", size = 611011, upload-time = "2026-06-30T07:15:50.847Z" }, + { url = "https://files.pythonhosted.org/packages/1e/16/5043105e679436ccfbc8e5e0dd2d663ed18a8b8113515fd06a5e5d77c83e/rpds_py-2026.6.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:1cf01971c4f2c5553b772a542e4aaf191789cd331bc2cd4ff0e6e65ba49e1e97", size = 572431, upload-time = "2026-06-30T07:15:52.394Z" }, + { url = "https://files.pythonhosted.org/packages/85/ed/adab103321c0a6565d5ae1c2998349bc3ee175b82ccc5ae8fc04cc413075/rpds_py-2026.6.3-cp313-cp313-win32.whl", hash = "sha256:8c3d1e9c15b9d51ca0391e13da1a25a0a4df3c58a37c9dc368e0736cf7f69df0", size = 201710, upload-time = "2026-06-30T07:15:53.894Z" }, + { url = "https://files.pythonhosted.org/packages/7b/ed/a03b09668e74e5dabbf2e211f6468e1820c0552f7b0500082da31841bf7b/rpds_py-2026.6.3-cp313-cp313-win_amd64.whl", hash = "sha256:9250a9a0a6fd4648b3f868da8d91a4c52b5811a62df58e753d50ae4454a36f80", size = 219454, upload-time = "2026-06-30T07:15:55.25Z" }, + { url = "https://files.pythonhosted.org/packages/27/17/b8642c12930b71bc2b25831f6708ccf0f75abcd11883932ec9ce54ba3a78/rpds_py-2026.6.3-cp313-cp313-win_arm64.whl", hash = "sha256:900a67df3fd1660b035a4761c4ce73c382ea6b35f90f9863c36c6fd8bf8b09bb", size = 215063, upload-time = "2026-06-30T07:15:56.573Z" }, + { url = "https://files.pythonhosted.org/packages/b6/36/7fbe9dcdaf857fb3f63c2a2284b62492d95f5e8334e947e5fb6e7f68c9be/rpds_py-2026.6.3-cp314-cp314-macosx_10_12_x86_64.whl", hash = "sha256:931908d9fc855d8f74783377822be318edb6dcb19e47169dc038f9a1bf60b06e", size = 344510, upload-time = "2026-06-30T07:15:57.921Z" }, + { url = "https://files.pythonhosted.org/packages/ba/54/f785cc3d3f60839ca57a5af4927a9f347b07b2799c373fc20f7949f87c7e/rpds_py-2026.6.3-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:d7469697dce35be237db177d42e2a2ee26e6dcc5fc052078a6fefabd288c6edd", size = 339495, upload-time = "2026-06-30T07:15:59.238Z" }, + { url = "https://files.pythonhosted.org/packages/63/ef/d4cdaf309e6b095b43597103cf8c0b951d6cca2acce68c474f75ec12e0c7/rpds_py-2026.6.3-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bcfbcf66006befb9fd2aeaa9e01feaf881b4dc330a02ba07d2322b1c11be7b5d", size = 369454, upload-time = "2026-06-30T07:16:01.021Z" }, + { url = "https://files.pythonhosted.org/packages/96/4a/9559a68b7ee15db09d7981212e8c2e219d2a1d6d4faa0391d813c3496a36/rpds_py-2026.6.3-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:847927daf4cffbd4e90e42bc890069897101edd015f956cb8721b3473372edda", size = 374583, upload-time = "2026-06-30T07:16:02.287Z" }, + { url = "https://files.pythonhosted.org/packages/ef/75/8964aa7d2c6e8ac43eba8eb6e6b0fdda1f46d39f2fc3e6aa9f2cb17f485d/rpds_py-2026.6.3-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:aca6c1ef08a82bfe327cc156da694660f599923e2e6665b6d81c9c2d0ac9ffc8", size = 492919, upload-time = "2026-06-30T07:16:03.723Z" }, + { url = "https://files.pythonhosted.org/packages/8f/97/6908094ac804115e65aedfd90f1b5fee4eebebd3f6c4cfc5419939267565/rpds_py-2026.6.3-cp314-cp314-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ae50181a047c871561212bb97f7932a2d45fb53e947bd9b57ebad85b529cbc53", size = 383725, upload-time = "2026-06-30T07:16:05.305Z" }, + { url = "https://files.pythonhosted.org/packages/d1/9c/0d1fdc2e7aba23e290d603bc494e97bd205bae262ce33c6b32a69768ed5e/rpds_py-2026.6.3-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dc319e5a1de4b6913aac94bf6a2f9e847371e0a140a43dd4991db1a09bc2d504", size = 367255, upload-time = "2026-06-30T07:16:07.086Z" }, + { url = "https://files.pythonhosted.org/packages/c4/fe/f0209ca4a9ed074bc8acb44dfd0e81c3122e94c9689f5645b7973a866719/rpds_py-2026.6.3-cp314-cp314-manylinux_2_31_riscv64.whl", hash = "sha256:e4316bf32babbed84e691e352faf967ce2f0f024174a8643c37c94a1080374fc", size = 379060, upload-time = "2026-06-30T07:16:08.525Z" }, + { url = "https://files.pythonhosted.org/packages/c6/8d/f1cc54c616b9d8897de8738aac148d20afca93f68187475fe194d09a71b9/rpds_py-2026.6.3-cp314-cp314-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:8c6e5a2f750cc71c3e3b11d71661f21d6f9bc6cebc6564b1466417a1ec03ec77", size = 395960, upload-time = "2026-06-30T07:16:09.989Z" }, + { url = "https://files.pythonhosted.org/packages/fb/04/aafff00f73aeca2945f734f1d483c64ab8f472d0864ab02377fd8e89c3b2/rpds_py-2026.6.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:4470ce197d4090875cf6affbf1f853338387428df97c4fb7b7106317b8214698", size = 545356, upload-time = "2026-06-30T07:16:11.816Z" }, + { url = "https://files.pythonhosted.org/packages/fd/cc/e229663b9e4ddac5a4acbe9085dd80a71af2a5d356b8b39d6bff233f24b0/rpds_py-2026.6.3-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:ea964164cc9afa72d4d9b23cc28dafae93693c0a53e0b42acbff15b22c3f9ddd", size = 612319, upload-time = "2026-06-30T07:16:13.586Z" }, + { url = "https://files.pythonhosted.org/packages/e3/7a/8a0e6d3e6cd066af108b71b43122c3fe158dd9eb86acac626593a2582eb1/rpds_py-2026.6.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:639c8929aa0afe81be836b04de888460d6bed38b9c54cfc18da8f6bfabf5af5d", size = 573508, upload-time = "2026-06-30T07:16:15.23Z" }, + { url = "https://files.pythonhosted.org/packages/87/03/2a69ab618a789cf6cf85c86bb844c62d090e700ab1a2aa676b3741b6c516/rpds_py-2026.6.3-cp314-cp314-win32.whl", hash = "sha256:882076c00c0a608b131187055ddc5ae29f2e7eaf870d6168980420d58528a5c8", size = 202504, upload-time = "2026-06-30T07:16:16.893Z" }, + { url = "https://files.pythonhosted.org/packages/85/62/a3892ba945f4e24c78f352e5de3c7620d8479f73f211406a97263d13c7d2/rpds_py-2026.6.3-cp314-cp314-win_amd64.whl", hash = "sha256:0be972be84cfcaf46c8c6edf690ca0f154ac17babf1f6a955a51579b34ad2dc5", size = 220380, upload-time = "2026-06-30T07:16:18.108Z" }, + { url = "https://files.pythonhosted.org/packages/3d/e7/c2bd44dc831931815ad11ebb5f430b5a0a4d3caa9de837107876c30c3432/rpds_py-2026.6.3-cp314-cp314-win_arm64.whl", hash = "sha256:2a9c6f195058cb45335e8cc3802745c603d716eb96bc9625950c1aac71c0c703", size = 215976, upload-time = "2026-06-30T07:16:19.654Z" }, + { url = "https://files.pythonhosted.org/packages/79/9c/fff7b74bce9a091ec9a012a03f9ff5f69364eaf9451060dfc4486da2ffdd/rpds_py-2026.6.3-cp314-cp314t-macosx_10_12_x86_64.whl", hash = "sha256:f90938e92afda60266da758ee7d363447f7f0138c9559f9e1811629580582d90", size = 346840, upload-time = "2026-06-30T07:16:21.268Z" }, + { url = "https://files.pythonhosted.org/packages/e9/44/77bcb1168b33704908295533d27f10eb811e9e3e193e8993dc99572211d3/rpds_py-2026.6.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:ec829541c45bca16e61c7ae50c20501f213605beb75d1aba91a6ee37fbbb56a4", size = 340282, upload-time = "2026-06-30T07:16:22.875Z" }, + { url = "https://files.pythonhosted.org/packages/87/3c/7a9081c7c9e645b39efe19e4ffbeccd80add246327cd9b888aecffd72317/rpds_py-2026.6.3-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:afd70d95892096cdb26f15a00c45907b17817577aa8d1c76b2dcc2788391f9e9", size = 370403, upload-time = "2026-06-30T07:16:24.415Z" }, + { url = "https://files.pythonhosted.org/packages/f7/69/af47021eb7dad6ff3396cb001c08f0f3c4d06c20253f75be6421a59fe6b7/rpds_py-2026.6.3-cp314-cp314t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:29dfa0533a5d4c94d4dfa1b694fcb56c9c63aad8330ffdd816fd225d0a7a162f", size = 376055, upload-time = "2026-06-30T07:16:26.111Z" }, + { url = "https://files.pythonhosted.org/packages/81/fc/a3bcf517084396a6dd258c592567a3c011ba4557f2fde23dceaf26e74f2e/rpds_py-2026.6.3-cp314-cp314t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:af05d726809bff6b141be124d4c7ce998f9c9c7f30edb1f46c07aa103d540b41", size = 494419, upload-time = "2026-06-30T07:16:27.596Z" }, + { url = "https://files.pythonhosted.org/packages/c9/eb/13d529d1788135425c7bf207f8463458ca5d92e43f3f701365b83e9dffc1/rpds_py-2026.6.3-cp314-cp314t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9826217f048f620d9a712672818bf231442c1b35d96b227a07eabd11b4bb6945", size = 384848, upload-time = "2026-06-30T07:16:29.183Z" }, + { url = "https://files.pythonhosted.org/packages/8e/f4/b7ac49f30013aba8f7b9566b1dd07e81de95e708c1374b7bacc5b9bc5c9c/rpds_py-2026.6.3-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:536bceea4fa4acf7e1c61da2b5786304367c816c8895be71b8f537c480b0ea1f", size = 371369, upload-time = "2026-06-30T07:16:30.912Z" }, + { url = "https://files.pythonhosted.org/packages/31/86/6260bafa622f788b07ddec0e52d810305c8b9b0b8c27f58a2ab04bf62b4f/rpds_py-2026.6.3-cp314-cp314t-manylinux_2_31_riscv64.whl", hash = "sha256:bc0011654b91cc4fb2ae701bec0a0ba1e552c0714247fa7af6c59e0ccfa3a4e1", size = 379673, upload-time = "2026-06-30T07:16:32.486Z" }, + { url = "https://files.pythonhosted.org/packages/19/c3/03f1ee79a047b48daeca157c89a18509cde22b6b951d642b9b0af1be660a/rpds_py-2026.6.3-cp314-cp314t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:539d75de9e0d536c84ff18dfeb805398e58227001ce09231a26a08b9aed1ee0e", size = 397500, upload-time = "2026-06-30T07:16:34.471Z" }, + { url = "https://files.pythonhosted.org/packages/f0/95/8ed0cd8c377dca12aea498f119fe639fc474d1461545c39d2b5872eb1c0f/rpds_py-2026.6.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:166cf54d9f44fc6ceb53c7860258dde44a81406646de79f8ed3234fca3b6e538", size = 545978, upload-time = "2026-06-30T07:16:36.45Z" }, + { url = "https://files.pythonhosted.org/packages/d3/f2/0eb57f0eaa83f8fc152a7e03de968ab77e1f00732bebc892b190c6eebde7/rpds_py-2026.6.3-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:d34c20167764fbcf927194d532dd7e0c56772f0a5f943fa5ef9e9afbba8fb9db", size = 613350, upload-time = "2026-06-30T07:16:38.213Z" }, + { url = "https://files.pythonhosted.org/packages/5b/de/e0674bdbc3ef7634989b3f854c3f34bc1f587d36e5bfdc5c378d57034619/rpds_py-2026.6.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:ea7bb13b7c9a29791f87a0387ba7d3ad3a6d783d827e4d3f27b40a0ff44495e2", size = 576486, upload-time = "2026-06-30T07:16:39.797Z" }, + { url = "https://files.pythonhosted.org/packages/f2/f6/21101359743cd136ada781e8210a85769578422ba460672eea0e29739200/rpds_py-2026.6.3-cp314-cp314t-win32.whl", hash = "sha256:6de4744d05bd1aa1be4ed7ea1189e3979196808008113bbbf899a460966b925e", size = 201068, upload-time = "2026-06-30T07:16:41.316Z" }, + { url = "https://files.pythonhosted.org/packages/a6/b2/9574d4d44f7760c2aa32d92a0a4f41698e33f5b204a0bf5c9758f52c79d5/rpds_py-2026.6.3-cp314-cp314t-win_amd64.whl", hash = "sha256:c7b9a2f8f4d8e90af72571d3d495deebdd7e3c75451f5b41719aee166e940fc2", size = 220600, upload-time = "2026-06-30T07:16:43.091Z" }, + { url = "https://files.pythonhosted.org/packages/08/ae/f23a2697e6ee6340a578b0f136be6483657bef0c6f9497b752bb5c0964bb/rpds_py-2026.6.3-cp315-cp315-macosx_10_12_x86_64.whl", hash = "sha256:e059c5dde6452b44424bd1834557556c226b57781dee1227af23518459722b13", size = 344726, upload-time = "2026-06-30T07:16:44.5Z" }, + { url = "https://files.pythonhosted.org/packages/c3/63/e7b3a1a5358dd32c930a1062d8e15b67fd6e8922e81df9e91706d66ee5c8/rpds_py-2026.6.3-cp315-cp315-macosx_11_0_arm64.whl", hash = "sha256:2f7c26fbc5acd2522b95d4177fe4710ffd8e9b20529e703ffbf8db4d93903f05", size = 339587, upload-time = "2026-06-30T07:16:46.255Z" }, + { url = "https://files.pythonhosted.org/packages/ec/64/10a85681916ca55fffb91b0a211f84e34297c109243484dd6394660a8a7c/rpds_py-2026.6.3-cp315-cp315-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a3086b538543802f84c843911242db20447de00d8752dd0efc936dbcf02218ba", size = 369585, upload-time = "2026-06-30T07:16:48.101Z" }, + { url = "https://files.pythonhosted.org/packages/76/c2/baf95c7c38823e12ba34407c5f5767a89e5cf2233895e56f608167ae9493/rpds_py-2026.6.3-cp315-cp315-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:8f2e5c5ee828d42cb11760761c0af6507927bec42d0ad5458f97c9203b054617", size = 375479, upload-time = "2026-06-30T07:16:49.93Z" }, + { url = "https://files.pythonhosted.org/packages/6a/94/0aad06c72d65101e11d33528d438cda99a39ce0da99466e156158f2541d3/rpds_py-2026.6.3-cp315-cp315-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ed0c1e5d10cdc7135537988c74a0188da68e2f3c30813ba3744ab1e42e0480f9", size = 492418, upload-time = "2026-06-30T07:16:51.641Z" }, + { url = "https://files.pythonhosted.org/packages/b5/17/de3f5a479a1f056535d7489819639d8cd591ea6281d700390b43b1abd745/rpds_py-2026.6.3-cp315-cp315-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8c2642a7603ec0b16ed77da4555db3b4b472341904873788327c0b0d7b95f1bb", size = 384123, upload-time = "2026-06-30T07:16:53.622Z" }, + { url = "https://files.pythonhosted.org/packages/46/7d/bf09bd1b145bb2671c03e1e6d1ab8651858d90d8c7dfeadd85a37a934fd8/rpds_py-2026.6.3-cp315-cp315-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8e4320744c1ffdd95a603def63344bfab2d33edeab301c5007e7de9f9f5b3885", size = 367351, upload-time = "2026-06-30T07:16:55.241Z" }, + { url = "https://files.pythonhosted.org/packages/a3/ea/1bb734f314b8be319149ddee80b18bd41372bdcfbdf88d28131c0cd37719/rpds_py-2026.6.3-cp315-cp315-manylinux_2_31_riscv64.whl", hash = "sha256:a9f4645593036b81bbdb36b9c8e0ea0d1c3fee968c4d59db0344c14087ef143a", size = 378827, upload-time = "2026-06-30T07:16:56.841Z" }, + { url = "https://files.pythonhosted.org/packages/4b/93/d9611e5b25e26df9a3649813ed66193ace9347a7c7fc4ab7cf70e94851c0/rpds_py-2026.6.3-cp315-cp315-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:e55d236be29255554da47abe5c577637db7c24a02b8b46f0ca9524c855801868", size = 395966, upload-time = "2026-06-30T07:16:58.557Z" }, + { url = "https://files.pythonhosted.org/packages/c3/cb/99d77e16e5534ae1d90629bbe419ba6ee170833a6a85e3aa1cc41726fbbc/rpds_py-2026.6.3-cp315-cp315-musllinux_1_2_aarch64.whl", hash = "sha256:24e9c5386e16669b674a69c156c8eeefcb578f3b3397b713b08e6d60f3c7b187", size = 545680, upload-time = "2026-06-30T07:17:00.164Z" }, + { url = "https://files.pythonhosted.org/packages/59/15/11a29755f790cef7a2f755e8e14f4f0c33f39489e1893a632a2eee59672b/rpds_py-2026.6.3-cp315-cp315-musllinux_1_2_i686.whl", hash = "sha256:c60924535c75f1566b6eb75b5c31a48a43fef04fa2d0d201acbad8a9969c6107", size = 611853, upload-time = "2026-06-30T07:17:01.962Z" }, + { url = "https://files.pythonhosted.org/packages/68/86/0c27547e21644da938fb530f7e1a8148dd24d02db07e7a5f2567a17ce710/rpds_py-2026.6.3-cp315-cp315-musllinux_1_2_x86_64.whl", hash = "sha256:38a2fea2787428f811719ceb9114cb78964a3138838320c29ac39526c79c16ba", size = 573715, upload-time = "2026-06-30T07:17:03.693Z" }, + { url = "https://files.pythonhosted.org/packages/29/71/4d8fcf700931815594bce892255bbd973b94efaf0fc1932b0590df18d886/rpds_py-2026.6.3-cp315-cp315-win32.whl", hash = "sha256:d483fe17f01ad64b7bf7cc38fcefff1ca9fb83f8c2b2542b68f97ffe0611b369", size = 202864, upload-time = "2026-06-30T07:17:05.746Z" }, + { url = "https://files.pythonhosted.org/packages/eb/62/b577562de0edbb55b2be85ce5fd09c33e386b9b13eee09833af4240fd5c4/rpds_py-2026.6.3-cp315-cp315-win_amd64.whl", hash = "sha256:67e3a721ffc5d8d2210d3671872298c4a84e4b8035cfe42ffd7cde35d772b146", size = 220430, upload-time = "2026-06-30T07:17:07.471Z" }, + { url = "https://files.pythonhosted.org/packages/c8/95/d6d0b2509825141eef60669a5739eec88dbc6a48053d6c92993a5704defe/rpds_py-2026.6.3-cp315-cp315-win_arm64.whl", hash = "sha256:6e84adbcf4bf841aed8116a8264b9f50b4cb3e7bd89b516122e616ac56ca269e", size = 215877, upload-time = "2026-06-30T07:17:09.008Z" }, + { url = "https://files.pythonhosted.org/packages/b7/bf/f3ea278f0afd615c1d0f19cb69043a41526e2bb600c2b536eb192218eb27/rpds_py-2026.6.3-cp315-cp315t-macosx_10_12_x86_64.whl", hash = "sha256:ae6dd8f10bd17aad820876d24caec9efdafd80a318d16c0a48edb5e136902c6b", size = 346933, upload-time = "2026-06-30T07:17:10.762Z" }, + { url = "https://files.pythonhosted.org/packages/9d/29/9907bdf1c5346763cf10b7f6852aad86652168c259def904cbe0082c5864/rpds_py-2026.6.3-cp315-cp315t-macosx_11_0_arm64.whl", hash = "sha256:bdbd97738551fca3917c1bd7188bec1920bb520104f28e7e1007f9ceb17b7690", size = 340274, upload-time = "2026-06-30T07:17:12.266Z" }, + { url = "https://files.pythonhosted.org/packages/6f/2c/8e03767b5778ef25cebf74a7a91a2c3806f8eced4c92cb7406bbe060756d/rpds_py-2026.6.3-cp315-cp315t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8b95977e7211527ab0ba576e286d023389fbeeb32a6b7b771665d333c60e5342", size = 370763, upload-time = "2026-06-30T07:17:14.107Z" }, + { url = "https://files.pythonhosted.org/packages/2e/e1/df2a7e1ba2efd796af26194250b8d42c821b46592311595162af9ef0528d/rpds_py-2026.6.3-cp315-cp315t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d15fde0e6fb0d88a60d221204873743e5d9f0b7d29165e62cd86d0413ad74ba6", size = 376467, upload-time = "2026-06-30T07:17:15.76Z" }, + { url = "https://files.pythonhosted.org/packages/6b/de/8a0814d1946af29cb068fb259aa8622f856df1d0bab58429448726b537f5/rpds_py-2026.6.3-cp315-cp315t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a136d453475ac0fcbda502ef1e6504bd28d6d904700915d278deeab0d00fe140", size = 496689, upload-time = "2026-06-30T07:17:17.308Z" }, + { url = "https://files.pythonhosted.org/packages/df/f3/f19e0c852ba13694f5a79f3b719331051573cb5693feacf8a88ffffc3a71/rpds_py-2026.6.3-cp315-cp315t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f826877d462181e5eb1c26a0026b8d0cab05d99844ecb6d8bf3627a2ca0c0442", size = 385340, upload-time = "2026-06-30T07:17:18.928Z" }, + { url = "https://files.pythonhosted.org/packages/e2/ae/7ec3a9d2d4351f99e37bcb06b6b6f954512646bfdbf9742e1de727865daf/rpds_py-2026.6.3-cp315-cp315t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:79486287de1730dbaff3dbd124d0ca4d2ef7f9d29bf2544f1f93c09b5bcbbd12", size = 372179, upload-time = "2026-06-30T07:17:20.539Z" }, + { url = "https://files.pythonhosted.org/packages/d3/ac/9cee911dff2aaa9a5a8354f6610bf2e6a616de9197c5fff4f54f82585f1e/rpds_py-2026.6.3-cp315-cp315t-manylinux_2_31_riscv64.whl", hash = "sha256:808345f53cb952433ca2816f1604ff3515608a81784954f38d4452acfe8e61d5", size = 379993, upload-time = "2026-06-30T07:17:22.212Z" }, + { url = "https://files.pythonhosted.org/packages/83/6b/7c2a07ba88d1e9a936612f7a5d067467ed03d971d5a06f7d309dff044a7e/rpds_py-2026.6.3-cp315-cp315t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:1967debc37f64f2c4dc90a7f563aec558b471966e12adcac4e1c4240496b6ebf", size = 398909, upload-time = "2026-06-30T07:17:23.66Z" }, + { url = "https://files.pythonhosted.org/packages/97/0b/776ffcb66783637b0031f6d58d6fb55913c8b5abf00aeecd46bf933fb477/rpds_py-2026.6.3-cp315-cp315t-musllinux_1_2_aarch64.whl", hash = "sha256:f0840b5b17057f7fd918b76183a4b5a0635f43e14eb2ce60dce1d4ee4707ea00", size = 546584, upload-time = "2026-06-30T07:17:25.264Z" }, + { url = "https://files.pythonhosted.org/packages/55/33/ba3bc04d7092bd553c9b2b195624992d2cc4f3de1f380b7b93cbee67bd79/rpds_py-2026.6.3-cp315-cp315t-musllinux_1_2_i686.whl", hash = "sha256:faa679d19a6696fd54259ad321251ad77a13e70e03dd834daa762a44fb6196ef", size = 614357, upload-time = "2026-06-30T07:17:26.888Z" }, + { url = "https://files.pythonhosted.org/packages/8b/71/14edf065f04630b1a8472f7653cad03f6c478bcf95ea0e6aed55451e33ea/rpds_py-2026.6.3-cp315-cp315t-musllinux_1_2_x86_64.whl", hash = "sha256:23a439f31ccbeff1574e24889128821d1f7917470e830cf6544dced1c662262a", size = 576533, upload-time = "2026-06-30T07:17:28.546Z" }, + { url = "https://files.pythonhosted.org/packages/ba/76/65002b08596c389105720a8c0d22298b8dc25a4baf89b2ce431343c8b1de/rpds_py-2026.6.3-cp315-cp315t-win32.whl", hash = "sha256:913ca42ccad3f8cc6e292b587ae8ae49c8c823e5dce51a736252fc7c7cdfa577", size = 201204, upload-time = "2026-06-30T07:17:30.193Z" }, + { url = "https://files.pythonhosted.org/packages/8c/97/d855d6b3c322d1f27e26f5241c42016b56cf01377ea8ed348285f54652f0/rpds_py-2026.6.3-cp315-cp315t-win_amd64.whl", hash = "sha256:ae3d4fe8c0b9213624fdce7279d70e3b148b682ca20719ebd193a23ebfa47324", size = 220719, upload-time = "2026-06-30T07:17:31.788Z" }, + { url = "https://files.pythonhosted.org/packages/b4/9c/f0d19ac587fd0e4ab6b72cda355e9c5a6166b01ef7e064e437aef8eb9fef/rpds_py-2026.6.3-pp311-pypy311_pp73-macosx_10_12_x86_64.whl", hash = "sha256:4cf2d36a2357e4d07bb5a4f98801265327b48256867816cfd2ceb001e9754a8f", size = 349791, upload-time = "2026-06-30T07:17:33.315Z" }, + { url = "https://files.pythonhosted.org/packages/38/c7/1d49d204c9fd2ee6c537601dc4c1ba921e03363ca576bfab94a00254ac9a/rpds_py-2026.6.3-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:30c6dc199b24a5e3e81d50da0f00858c5bbdb2617a750395687f4339c5818171", size = 352842, upload-time = "2026-06-30T07:17:34.897Z" }, + { url = "https://files.pythonhosted.org/packages/ac/e5/c0b5dc93cd0d4c06ce1f438907649514e2ea077bcd911e3154a51e96c38e/rpds_py-2026.6.3-pp311-pypy311_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9891e594296ab9dada6551c8e7b387b2721f27a67eecd528412e8906247a7b90", size = 382094, upload-time = "2026-06-30T07:17:36.514Z" }, + { url = "https://files.pythonhosted.org/packages/0d/54/ec0e907b4ca8d541112db352409bd15f871c9b243e0c92c9b5a46ae96f01/rpds_py-2026.6.3-pp311-pypy311_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:b5c2dc92304aa48a4a60443b548bb12f12e119d4b72f314015e67b9e1be97fca", size = 388662, upload-time = "2026-06-30T07:17:38.235Z" }, + { url = "https://files.pythonhosted.org/packages/d3/f4/921c22a4fd0f1c1ac13a3996ffbf0aa67951e2c8ad0d1d9574938a2932e8/rpds_py-2026.6.3-pp311-pypy311_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:127e08c0642d880cf32ca47ec2a4a77b901f7e2dd1ad9762adb13955d72ffcc9", size = 504896, upload-time = "2026-06-30T07:17:39.689Z" }, + { url = "https://files.pythonhosted.org/packages/0b/1b/a114b972cefa1ab1cdb3c7bb177cd3844a12826c507c722d3a73516dbbaf/rpds_py-2026.6.3-pp311-pypy311_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8bb68f03f395eb793220b45c097bd4d8c32944393da0fad8b999efac0868fc8c", size = 391545, upload-time = "2026-06-30T07:17:41.336Z" }, + { url = "https://files.pythonhosted.org/packages/4e/98/af9b3db77d47fcbe6c8c1f36e2c2147ec70292819e99c325f871584a1c11/rpds_py-2026.6.3-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a3450b693fde92133e9f51060568a4c31fcca76d5e53bbd611e689ca446517e9", size = 380059, upload-time = "2026-06-30T07:17:42.857Z" }, + { url = "https://files.pythonhosted.org/packages/c9/ba/0efd8668b97c1d26a61566386c636a7a7a09829e474fdf807caa15a2c844/rpds_py-2026.6.3-pp311-pypy311_pp73-manylinux_2_31_riscv64.whl", hash = "sha256:5e8d07bddee435a2ff6f1920e18feff28d0bc4533e42f4bf6927fbd073312c41", size = 393235, upload-time = "2026-06-30T07:17:44.637Z" }, + { url = "https://files.pythonhosted.org/packages/62/90/8c139ee9690f73b0829f32647de6f40d826f8f443af6fa72644f96351aac/rpds_py-2026.6.3-pp311-pypy311_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:3a83ae6c67b7676b9878378547ca8e93ed77a580037bcbcd1d32f739e1e6089c", size = 413008, upload-time = "2026-06-30T07:17:46.225Z" }, + { url = "https://files.pythonhosted.org/packages/9c/97/0043896fdd7828ce09a1d9a8b06433714d0960fc4ff3fc4aa72b666b764e/rpds_py-2026.6.3-pp311-pypy311_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:2bfd04c19ddbd6640de0b51894d764bd2758854d5b75bd102d2ef10cb9c293a9", size = 558118, upload-time = "2026-06-30T07:17:47.759Z" }, + { url = "https://files.pythonhosted.org/packages/f6/40/02355f0e134f783a8f9814c4680a1bd311d37671577a5964ea838573ff37/rpds_py-2026.6.3-pp311-pypy311_pp73-musllinux_1_2_i686.whl", hash = "sha256:ca6546b66be9dc4738b1b043d5ebd5488c66c578c5ff0fd0e8065313fe3afb76", size = 623138, upload-time = "2026-06-30T07:17:49.355Z" }, + { url = "https://files.pythonhosted.org/packages/10/85/48f0abdcef5cce4e034c7a5b0ceeceba0b01bf0d942824f4bb720afe2dec/rpds_py-2026.6.3-pp311-pypy311_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:8e65860d238379ed982fd9ba690579b5e95af2f4840f99c772816dbe573cb826", size = 586486, upload-time = "2026-06-30T07:17:51.141Z" }, ] [[package]] name = "ruff" -version = "0.15.17" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/8c/a9/3abdf488f1bf3d24c699415e454ed554a6350d5d89ce183be1ee0a3361ac/ruff-0.15.17.tar.gz", hash = "sha256:2ec446937fd16c8c4de2674a209cc5af64d9c6f17d21fbf1151054fa0bcf5219", size = 4743346, upload-time = "2026-06-11T17:54:47.663Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/db/4d/e11259f5da07cb6afb2d074c31bf09da9671993f7329d4f15d2fdc458301/ruff-0.15.17-py3-none-linux_armv6l.whl", hash = "sha256:d9feddb927fc68bd295f5eebc587a7e42cfaf9b65f60ca4a2386febff575da8f", size = 10856677, upload-time = "2026-06-11T17:54:49.533Z" }, - { url = "https://files.pythonhosted.org/packages/29/3e/772d679e1a0dc058e58875bd2c0cb713a0530877b4a76fee3c7966df0d49/ruff-0.15.17-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:25805a226d741c47d274a35ad5c10a7dde175fcddfa511d7cf3da0a21eb3eab7", size = 11223443, upload-time = "2026-06-11T17:55:00.573Z" }, - { url = "https://files.pythonhosted.org/packages/68/58/bd41f7688b2fd5623012605130ed70e60aa7f2244baa3d5066bdd61530c8/ruff-0.15.17-py3-none-macosx_11_0_arm64.whl", hash = "sha256:f6ad73b14c2d18a3bf8ad7cb6974294d7f613a7898604826058e6ac64918ef4d", size = 10566458, upload-time = "2026-06-11T17:55:07.52Z" }, - { url = "https://files.pythonhosted.org/packages/d8/5b/733371013fcf1ec339e477ece6ab42bfe10bdd9bba8ee88a9516aa56bfc0/ruff-0.15.17-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6ba0c1e4f95bcb3869d0d30cbd5917071ef2e28665abfec970cdab0492c713ed", size = 10914483, upload-time = "2026-06-11T17:55:05.501Z" }, - { url = "https://files.pythonhosted.org/packages/bd/cc/6f24251cc0252f7239391ccb85833f320efad14ebe5b443943f37ced6332/ruff-0.15.17-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:81647960f10bff57d2e51cadd0c3950fe598400c852863a038720ef5b8cca91e", size = 10647497, upload-time = "2026-06-11T17:54:57.733Z" }, - { url = "https://files.pythonhosted.org/packages/68/dd/0d10c17ce1a1624d6fc3156309c3f834fdb5dfaad026ec90c85684f3990e/ruff-0.15.17-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0e01a84ddbc8c16c23055ba3924476850f1bbc1917cebbb9376665a63e74260d", size = 11416967, upload-time = "2026-06-11T17:54:51.461Z" }, - { url = "https://files.pythonhosted.org/packages/2f/91/556bfb156f6144f355e831c23db00b2fc4120f86b3ce81cc5f7fd2df51f3/ruff-0.15.17-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:84fe9f653152f8f294f9f7e03bf3a453d8b4a27f7a59c78c8666167f2b17b96c", size = 12335770, upload-time = "2026-06-11T17:54:45.793Z" }, - { url = "https://files.pythonhosted.org/packages/88/82/8b5999aa13355e926f06d9f42a32dcca862f623bf0363785ff89d607dffd/ruff-0.15.17-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8c0fe88a7676e7a05b73174d4d4a59cb2ac21ff8263583f87a81a6018475a978", size = 11575441, upload-time = "2026-06-11T17:54:32.661Z" }, - { url = "https://files.pythonhosted.org/packages/11/93/f10377bb04109ca0e8cbc483ff1982c54b6d418210041776f93e8cdc7fa9/ruff-0.15.17-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ecfc3c7878fff94633ab0348524e093f9ce3243080416dd7d14f8ba400174719", size = 11557614, upload-time = "2026-06-11T17:54:34.698Z" }, - { url = "https://files.pythonhosted.org/packages/c7/a6/eeeae7f7d5493df41649ab3db92f086b2d0a30199e4efdf8e3dd7a033f24/ruff-0.15.17-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:b8461180b22420b1bdc289909410930761629fddf2a5aaf60fae1ab26cedc4c4", size = 11544450, upload-time = "2026-06-11T17:54:39.042Z" }, - { url = "https://files.pythonhosted.org/packages/32/88/5991ce565129a24dd4a00db1254b3b5db2e53018cbe4018ea5a89738e727/ruff-0.15.17-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:6eccbe50a038b503e7140b441aa9c7fc8c1f36edf23ebef9f4165c2f28f568b7", size = 10892524, upload-time = "2026-06-11T17:55:09.432Z" }, - { url = "https://files.pythonhosted.org/packages/f5/1d/0fdd248313425f55223968af04b0a42125466a8d88d21c1d99c6af0a51e8/ruff-0.15.17-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:382fc0521025f5a8ad447d8bdd523545d0d7646adb718eb1c2dac5065ec27c0f", size = 10659573, upload-time = "2026-06-11T17:54:36.824Z" }, - { url = "https://files.pythonhosted.org/packages/9e/0e/072e8260deb9461062ce9311ced27a8e541229a6ffd483013dd37661e43e/ruff-0.15.17-py3-none-musllinux_1_2_i686.whl", hash = "sha256:456d41fcd1b2777ad63f09a6e7121d43f7b688bbc76a800c10f7f8fb1f912c3f", size = 11127818, upload-time = "2026-06-11T17:55:03.124Z" }, - { url = "https://files.pythonhosted.org/packages/ab/b4/55060a34163121498014696b5f656db5b8c6963768f227dbf0d76b311073/ruff-0.15.17-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:b1a04bcc94ae6194e9db05d16ad31f298a7194bfbcb08258bbe589cee1d587b8", size = 11655901, upload-time = "2026-06-11T17:54:53.562Z" }, - { url = "https://files.pythonhosted.org/packages/49/71/9b29d6b87cef468d697f43c6a91e3fae4a80185779d7d5a4ef27d173439f/ruff-0.15.17-py3-none-win32.whl", hash = "sha256:596065960ab1ff593f744220c9fe6580eda00a95003cffa9f4048bb5b1bf0392", size = 10925574, upload-time = "2026-06-11T17:54:55.723Z" }, - { url = "https://files.pythonhosted.org/packages/3d/b2/8fc77f3723228836fa5d12497eb71c808f83782e10d058d2b15cfa14640b/ruff-0.15.17-py3-none-win_amd64.whl", hash = "sha256:6769e5fa1710b179b92e0bfa5a51735b35baea9013dadb06d5f44cbcf9547084", size = 12058788, upload-time = "2026-06-11T17:54:41.042Z" }, - { url = "https://files.pythonhosted.org/packages/2d/c7/c53e8dbff9c9dc4b7928773421ae294a5d28fcb8dcda1a089579d3a7e510/ruff-0.15.17-py3-none-win_arm64.whl", hash = "sha256:f3be1fbb34bcdfd146240d8fb92a709d4c2c8191348580a3c044ec60fa0b4456", size = 11355275, upload-time = "2026-06-11T17:54:43.635Z" }, +version = "0.15.22" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/3a/06/ae069393fc66e8ff33036d4b368003833bf6e88ccf182e17e7a2f1c754fd/ruff-0.15.22.tar.gz", hash = "sha256:3f15175b1fb580126f58285a5dae6b2ea89000136d980c64499211f116b54809", size = 4785063, upload-time = "2026-07-16T15:14:13.244Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/23/18/ee54b7ae1e121be7a28ea6da4b67564ebb0530e183a54415ab7e3bcd2c4e/ruff-0.15.22-py3-none-linux_armv6l.whl", hash = "sha256:44423e73493737f5e7c5b41d475483898ff37afcdae38bc3da5085e29af1c2d8", size = 10781258, upload-time = "2026-07-16T15:13:19.452Z" }, + { url = "https://files.pythonhosted.org/packages/2f/d2/2520cb14761ddbeaf57642a76942fc36adcbdbe53b4532241995f6fc485c/ruff-0.15.22-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:b82c6482946e9eda7ff2e091d25b8bad3f718684e1916d41bd56873cee05b697", size = 10999477, upload-time = "2026-07-16T15:13:23.318Z" }, + { url = "https://files.pythonhosted.org/packages/c9/10/74e53572aa758dfaa678c2a2646b5c5515d884b7ca56be4d2ce03ca4b560/ruff-0.15.22-py3-none-macosx_11_0_arm64.whl", hash = "sha256:11c1c715af53a09f714e011106bffc419751ec8232fcb5da42173284ea3fec6f", size = 10466716, upload-time = "2026-07-16T15:13:26.162Z" }, + { url = "https://files.pythonhosted.org/packages/1e/cc/44eaaf0844e028182f2d0a8f2190d0f359159aed0a9e5ab861d892f1ae2a/ruff-0.15.22-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:742a29cf29bddb7c8327895d6a10e0e6c5b38a96dd407af9b5d0857f809c0576", size = 10892644, upload-time = "2026-07-16T15:13:29.229Z" }, + { url = "https://files.pythonhosted.org/packages/9f/21/8edf559014d2b0f82beea19cfb713993ad802ccda16868769979c6090a84/ruff-0.15.22-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:72af58b951b0ae395935ae79763dc349bc0eb706319d28f7a33ad2cfb3cfc178", size = 10576719, upload-time = "2026-07-16T15:13:32.35Z" }, + { url = "https://files.pythonhosted.org/packages/bf/1e/3a13abd392a3b50b62e5938a831f9ab6e588358cacad5c18545b716d2182/ruff-0.15.22-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:62d425005c1835eb24e2ee4161cb90e8db263415f4a71c8c72c33abaa6c0c224", size = 11376494, upload-time = "2026-07-16T15:13:35.958Z" }, + { url = "https://files.pythonhosted.org/packages/bf/3e/422d3d95bcf04dd78e1aeac22184d4f9a8fb2c01865d39d44618484a0317/ruff-0.15.22-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e8b9b3f8779a4f08c969defc3c8c35abffaa757e601ed5ae66d6d1db6519969a", size = 12208370, upload-time = "2026-07-16T15:13:39.185Z" }, + { url = "https://files.pythonhosted.org/packages/1e/91/5d065a0e0a02bf4813f5119ad278462eed081d2b832eb7c021ade0ec9e65/ruff-0.15.22-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1e0dd1b2e4d3d585f897a0d137cbf4eaf6223bef4e8ce34d6bb12556c5f9249e", size = 11581098, upload-time = "2026-07-16T15:13:42.132Z" }, + { url = "https://files.pythonhosted.org/packages/f6/f9/a0d4871d12fae702eb1f41b686caf05f1f8b124dc6db6f784f53d74918fa/ruff-0.15.22-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:365523eb91d9224e1bcb03b022fbf0facb8f9e23792a2c53d9d4b3924bdbdebb", size = 11399422, upload-time = "2026-07-16T15:13:45.2Z" }, + { url = "https://files.pythonhosted.org/packages/18/80/c843a5176cddbceb0b7e8dd41cf9993490796c1c469348d384f5a5c13c56/ruff-0.15.22-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:fabfd168afdf29fee5be98b831efa9683c94d7c5a3b58b9ce5a2e38444589a74", size = 11381683, upload-time = "2026-07-16T15:13:48.46Z" }, + { url = "https://files.pythonhosted.org/packages/d4/00/8485de0ae92239438a36cfc51350db9b9e85c9ebdfaea91b18e422706662/ruff-0.15.22-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:225dbf095a87f1d9f90f5fd7924d2613ee452a75a4308c63a8f50f761787aa7c", size = 10850295, upload-time = "2026-07-16T15:13:51.655Z" }, + { url = "https://files.pythonhosted.org/packages/fa/91/24977ec2ec72eaf15e4394ace2959fdff2dd1e14f03e005e838023407169/ruff-0.15.22-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:1877d63b9d24ed278744f1523fd11b85540566d54641f97c566d7d9dc5ca5296", size = 10579640, upload-time = "2026-07-16T15:13:54.79Z" }, + { url = "https://files.pythonhosted.org/packages/9c/47/9b51216951974df1f263ac19da550d34252e0ed7218c25f10c5ef9ed7517/ruff-0.15.22-py3-none-musllinux_1_2_i686.whl", hash = "sha256:a1606c510bd7215680d32efab38965f7cdec3ef69f5170a3f4791404ffdd5262", size = 11105077, upload-time = "2026-07-16T15:13:57.915Z" }, + { url = "https://files.pythonhosted.org/packages/c2/47/20e9d4a3b8016778acea5fc32bb50d35d207500a17ddb529ffa6996feef8/ruff-0.15.22-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:630479b18625f5ffc373f77603a22a9f8ac0acd7ff0501178b5db28ec71e9c64", size = 11490980, upload-time = "2026-07-16T15:14:01.032Z" }, + { url = "https://files.pythonhosted.org/packages/4d/76/3f72d8fc38c1cb77b38c56a70da9d0c17700cc1cc50f9649c9d3c8f5ba71/ruff-0.15.22-py3-none-win32.whl", hash = "sha256:e5ba0e4a13fd14abbed2a77b517a3911290c6c6c59ef67784328d1668fab76cf", size = 10789165, upload-time = "2026-07-16T15:14:04.16Z" }, + { url = "https://files.pythonhosted.org/packages/cb/46/4965251734c2b6fcdca1b1b187d20bcac3af0ee5b083b89c910bb961ce3a/ruff-0.15.22-py3-none-win_amd64.whl", hash = "sha256:9be63ba1eb936acd2d1342fb8337c356353706fce233b2a15a09a97037e6acde", size = 11938297, upload-time = "2026-07-16T15:14:07.316Z" }, + { url = "https://files.pythonhosted.org/packages/57/c9/e69b1ff4c8b69093ef08b8919ab767af0569666865b39c30a8795d88d3c6/ruff-0.15.22-py3-none-win_arm64.whl", hash = "sha256:e1168075b72158510839f250027659cdd78476f40507dd517892304c41318661", size = 11298172, upload-time = "2026-07-16T15:14:10.51Z" }, ] [[package]] @@ -4502,15 +4460,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/e1/e3/c164c88b2e5ce7b24d667b9bd83589cf4f3520d97cad01534cd3c4f55fdb/setuptools-81.0.0-py3-none-any.whl", hash = "sha256:fdd925d5c5d9f62e4b74b30d6dd7828ce236fd6ed998a08d81de62ce5a6310d6", size = 1062021, upload-time = "2026-02-06T21:10:37.175Z" }, ] -[[package]] -name = "shellingham" -version = "1.5.4" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/58/15/8b3609fd3830ef7b27b655beb4b4e9c62313a4e8da8c676e142cc210d58e/shellingham-1.5.4.tar.gz", hash = "sha256:8dbca0739d487e5bd35ab3ca4b36e11c4078f3a234bfce294b0a0291363404de", size = 10310, upload-time = "2023-10-24T04:13:40.426Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/e0/f9/0595336914c5619e5f28a1fb793285925a8cd4b432c9da0a987836c7f822/shellingham-1.5.4-py2.py3-none-any.whl", hash = "sha256:7ecfff8f2fd72616f7481040475a65b2bf8af90a56c89140852d1120324e8686", size = 9755, upload-time = "2023-10-24T04:13:38.866Z" }, -] - [[package]] name = "six" version = "1.17.0" @@ -4522,23 +4471,23 @@ wheels = [ [[package]] name = "slack-bolt" -version = "1.28.0" +version = "1.30.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "slack-sdk" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/5c/97/a62dde97e84027b252807f2044bed2edcda2d063a5cb0c535fb2be8d9b5d/slack_bolt-1.28.0.tar.gz", hash = "sha256:bfe367d867e8fb157a057248ebd4ac2d7f43acac6d0700fa31381db1e10f3b0f", size = 130768, upload-time = "2026-04-06T23:24:59.936Z" } +sdist = { url = "https://files.pythonhosted.org/packages/e3/4f/5ba15533d66da2e7174334cc0e2805142e5390c9f4c5f31633df78b17006/slack_bolt-1.30.0.tar.gz", hash = "sha256:af38258d41f801ad9c74503090e0f39accd66c49f667f7e55c97fcdb0e51b886", size = 131180, upload-time = "2026-07-15T20:47:33.679Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/81/a9/697b6a92c728f09d5ef6b8e83dc6c8a87bc6d59499b2933ed067f11b7e30/slack_bolt-1.28.0-py2.py3-none-any.whl", hash = "sha256:738d1ca5e7c7039b6e18103d29267ced6e18c2517053eff18991fdd593acce5c", size = 234819, upload-time = "2026-04-06T23:24:58.278Z" }, + { url = "https://files.pythonhosted.org/packages/2f/ee/1a7a286cf98fa3f4eeffaabc090e82f58f058ab4812aa1d7421d92c2637a/slack_bolt-1.30.0-py2.py3-none-any.whl", hash = "sha256:81f5bc46e79516d23d5e2a31dded6304dd1b8b6b72c0083f2f31d5d801e262c4", size = 235341, upload-time = "2026-07-15T20:47:32.113Z" }, ] [[package]] name = "slack-sdk" -version = "3.42.0" +version = "3.43.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/0e/00/16258bfa547559b2c936b50c882b4f0a36ebf6b69639eb763d8fa5e8d6cb/slack_sdk-3.42.0.tar.gz", hash = "sha256:873db9e1f632ac650ffdbf9d8ba825f3e9e7e576a1e4f9604ccb2a15b3727e3d", size = 252136, upload-time = "2026-05-18T17:50:44.727Z" } +sdist = { url = "https://files.pythonhosted.org/packages/13/75/a4964eb771a0c74d79ee7a3bee6fb5d9718909dd1b675e80d62a6a0ad90a/slack_sdk-3.43.0.tar.gz", hash = "sha256:0553152e46c4259eb69f7464cdadc35ba4802ca10f9f5a849c92cf03d6c2ba07", size = 252769, upload-time = "2026-06-30T18:04:41.59Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/ce/ef/8a1556bd4843443993fc116783790a7cc553601a37f7d965ec26eef95e76/slack_sdk-3.42.0-py2.py3-none-any.whl", hash = "sha256:eb39aff97e476e10cc5a8ac29bd2e79a9959e880d9fe0c03b4e8f05b2ac996ff", size = 315469, upload-time = "2026-05-18T17:50:41.972Z" }, + { url = "https://files.pythonhosted.org/packages/e4/55/42141b8338d46323d5b3c6095201b044c670c20f898643b322ea9b1543a1/slack_sdk-3.43.0-py2.py3-none-any.whl", hash = "sha256:4b6557c65577fc172f685af218b811f9f3b4909e24cddd839ada09565f10c585", size = 315866, upload-time = "2026-06-30T18:04:39.636Z" }, ] [[package]] @@ -4570,15 +4519,15 @@ wheels = [ [[package]] name = "sse-starlette" -version = "3.4.4" +version = "3.4.5" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "anyio" }, { name = "starlette" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/f7/2b/58abc2d1fd397e7dde08e947e05c884d8ef2f78d5e2588c17a12d42d6994/sse_starlette-3.4.4.tar.gz", hash = "sha256:07e0fa0460138baf25cdd5fb28683472c3995dc1642225191b3832d62526bcb0", size = 31819, upload-time = "2026-05-12T17:37:17.019Z" } +sdist = { url = "https://files.pythonhosted.org/packages/d2/1b/bc9e3e7a72dcdad7dc7888758f5d00f56f8909ed5cfdff822bd72bb4c520/sse_starlette-3.4.5.tar.gz", hash = "sha256:83072538bc211a2f68b7b0422226c4af3e9b62e106e07034664b832ca019842a", size = 35249, upload-time = "2026-06-20T17:36:58.322Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/dc/67/805710444ea8cc75fbf70b920ed431a560c4bf9c57f7d5a3117213189399/sse_starlette-3.4.4-py3-none-any.whl", hash = "sha256:3f4dd50d8aed2771a091f3a83000323fc3844541c16b4fe585ae2420cc6df973", size = 16514, upload-time = "2026-05-12T17:37:15.601Z" }, + { url = "https://files.pythonhosted.org/packages/78/75/c88d3f5dafd59c791da1ce27650d30bf5b70cbf1cbf01cd00e5f9e360915/sse_starlette-3.4.5-py3-none-any.whl", hash = "sha256:e71bad53323f65573c3864a6c3bd0c1eb6e5f092b2e48082b0c35927d19ca296", size = 16518, upload-time = "2026-06-20T17:36:56.729Z" }, ] [[package]] @@ -4596,7 +4545,7 @@ wheels = [ [[package]] name = "strands-agents" -version = "1.43.0" +version = "1.47.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "boto3" }, @@ -4612,14 +4561,14 @@ dependencies = [ { name = "typing-extensions" }, { name = "watchdog" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/06/e7/ba9faab3ebaa63325ef03b61a74806bc5ccb6b626428541f898b4f33fb21/strands_agents-1.43.0.tar.gz", hash = "sha256:379ad28af36d9306c7ae3f43702b086082193e8eafa53de051c9ce91496178ac", size = 922114, upload-time = "2026-06-12T14:27:57.069Z" } +sdist = { url = "https://files.pythonhosted.org/packages/2e/05/5eb8431ff340739b1c21b0da7d19ec9604b9c4953a1c4638df915321573c/strands_agents-1.47.0.tar.gz", hash = "sha256:97770cb6beb6e5fd1a58849f41201eb7edb43fd67ad3de6544ada2f342c2bcf0", size = 1157139, upload-time = "2026-07-10T14:45:05.809Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/68/35/29fc4c02293aef54dfa59a5516419153a9fb15a4857ecf8f2ce8638ae3dd/strands_agents-1.43.0-py3-none-any.whl", hash = "sha256:b934f74fe1b7103d438684b69ee044223a5bb407db2ccd2b55e5da6bf639d31b", size = 472542, upload-time = "2026-06-12T14:27:55.55Z" }, + { url = "https://files.pythonhosted.org/packages/d0/cb/ceae892c5823bea9254160efc02a4553f2ced9d183676110c03c3a9ff0f3/strands_agents-1.47.0-py3-none-any.whl", hash = "sha256:1f6ce17404ff02079244ad7a4a180a2a7150546275e4b91187d71472ba8fe3f2", size = 600611, upload-time = "2026-07-10T14:45:03.942Z" }, ] [[package]] name = "strands-agents-tools" -version = "0.8.0" +version = "0.8.3" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "aiohttp" }, @@ -4640,9 +4589,9 @@ dependencies = [ { name = "tzdata", marker = "sys_platform == 'win32'" }, { name = "watchdog" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/d4/74/aed74502a19a18ce1ddcd56e1dc4a0de6e9f2cb6babcc9f2d1969f253c0b/strands_agents_tools-0.8.0.tar.gz", hash = "sha256:fd93104d2d8dcff780505e8a2fca0cb2fa7a3da6bae01369073b60da0e08c5aa", size = 490638, upload-time = "2026-06-03T19:20:03.872Z" } +sdist = { url = "https://files.pythonhosted.org/packages/17/dd/aaa1f17ec10db4a9f49e2e48bd3cd5fb646c1c284e4fe6fa0a6a32380914/strands_agents_tools-0.8.3.tar.gz", hash = "sha256:19f6d3d617e9ef85b0a31c475f0a3f81d8ea60a2ed7dc6bd8f17fdd586c94d46", size = 511310, upload-time = "2026-07-09T19:55:59.262Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/0a/37/9f611363451cf38f912c7551b73308339e6af54bf1b5e9a3e8efc7ae0972/strands_agents_tools-0.8.0-py3-none-any.whl", hash = "sha256:7446ae423794b6f886fb36e1a0f8a62fe0546978c18b805e6f50dcdddee1559e", size = 319602, upload-time = "2026-06-03T19:20:01.92Z" }, + { url = "https://files.pythonhosted.org/packages/b1/8b/1500ae455cc8434a54f013278320042d88ba9daffb5dafaed1fa8b48c3f3/strands_agents_tools-0.8.3-py3-none-any.whl", hash = "sha256:bc17fbad5ad7957bef33538fb5e0c386f7883dab92c557e92175e7ff16b42dac", size = 327194, upload-time = "2026-07-09T19:55:57.473Z" }, ] [[package]] @@ -4989,14 +4938,14 @@ wheels = [ [[package]] name = "tqdm" -version = "4.68.2" +version = "4.68.4" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "colorama", marker = "sys_platform == 'win32'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/85/05/0d5260f1f1ca784f4a4a0def9cbe6affe587f5b4025328d446c3d67765f4/tqdm-4.68.2.tar.gz", hash = "sha256:89c230e8dbc67c7615c142487111222f878c77427ea09549960f62389e258add", size = 171923, upload-time = "2026-06-09T13:26:42.539Z" } +sdist = { url = "https://files.pythonhosted.org/packages/ae/5f/57ff8b434839e70dab45601284ea413e947a63799891b7553e5960a793a8/tqdm-4.68.4.tar.gz", hash = "sha256:19829c9673638f2a0b8617da4cdcb927e831cd88bcfcb6e78d42a4d1af131520", size = 792418, upload-time = "2026-07-07T09:58:18.369Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/eb/75/1a0392bcc21c44dcdf87b3cf2d137e7829be2c083a1e38d44efca3d57a16/tqdm-4.68.2-py3-none-any.whl", hash = "sha256:d4240441fb5353290b87d6a85968c9decc131a99b8c7faa28269d829de669ede", size = 78578, upload-time = "2026-06-09T13:26:40.731Z" }, + { url = "https://files.pythonhosted.org/packages/22/2a/5e5e750890ada51017d18d0d4c30da696e5b5bd3180947729927628fc3cb/tqdm-4.68.4-py3-none-any.whl", hash = "sha256:5168118b2368f48c561afda8020fd79195b1bdb0bdf8086b88442c267a315dc2", size = 676612, upload-time = "2026-07-07T09:58:16.256Z" }, ] [[package]] @@ -5037,21 +4986,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/a6/57/bcf4e2370dd218c9aa68a9140a65d86729c73f1d529f7e94786c2766fc72/twisted-26.4.0-py3-none-any.whl", hash = "sha256:dc25ea0ebf6511c24f03232ee9f4afa54b291c5d897990e3a39cc4d14a1ef4c0", size = 3230362, upload-time = "2026-05-11T11:24:49.5Z" }, ] -[[package]] -name = "typer" -version = "0.25.1" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "annotated-doc" }, - { name = "click" }, - { name = "rich" }, - { name = "shellingham" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/e4/51/9aed62104cea109b820bbd6c14245af756112017d309da813ef107d42e7e/typer-0.25.1.tar.gz", hash = "sha256:9616eb8853a09ffeabab1698952f33c6f29ffdbceb4eaeecf571880e8d7664cc", size = 122276, upload-time = "2026-04-30T19:32:16.964Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/3f/f9/2b3ff4e56e5fa7debfaf9eb135d0da96f3e9a1d5b27222223c7296336e5f/typer-0.25.1-py3-none-any.whl", hash = "sha256:75caa44ed46a03fb2dab8808753ffacdbfea88495e74c85a28c5eefcf5f39c89", size = 58409, upload-time = "2026-04-30T19:32:18.271Z" }, -] - [[package]] name = "types-aioboto3" version = "15.5.0" @@ -5126,11 +5060,11 @@ wheels = [ [[package]] name = "typing-extensions" -version = "4.15.0" +version = "4.16.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/72/94/1a15dd82efb362ac84269196e94cf00f187f7ed21c242792a923cdb1c61f/typing_extensions-4.15.0.tar.gz", hash = "sha256:0cea48d173cc12fa28ecabc3b837ea3cf6f38c6d1136f85cbaaf598984861466", size = 109391, upload-time = "2025-08-25T13:49:26.313Z" } +sdist = { url = "https://files.pythonhosted.org/packages/f6/cc/6253133b5bb138fc3306cebfbda2c520f545d36b5be2c7255cc528bb45d6/typing_extensions-4.16.0.tar.gz", hash = "sha256:dc983d19a509c94dba722ee6abd33940f7c05a89e243c47e907eb4db6f1a43e5", size = 113555, upload-time = "2026-07-02T08:40:05.92Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/18/67/36e9267722cc04a6b9f15c7f3441c2363321a3ea07da7ae0c0707beb2a9c/typing_extensions-4.15.0-py3-none-any.whl", hash = "sha256:f0fa19c6845758ab08074a0cfa8b7aecb71c999ca73d62883bc25cc018c4e548", size = 44614, upload-time = "2025-08-25T13:49:24.86Z" }, + { url = "https://files.pythonhosted.org/packages/49/d3/b8441a820a491ddfc024b0b0cf0393375b75ea13866d9c66727e54c2fc80/typing_extensions-4.16.0-py3-none-any.whl", hash = "sha256:481caa481374e813c1b176ada14e97f1f67a4539ce9cfeb3f350d78d6370c2e8", size = 45571, upload-time = "2026-07-02T08:40:04.659Z" }, ] [[package]] @@ -5147,23 +5081,23 @@ wheels = [ [[package]] name = "tzdata" -version = "2026.2" +version = "2026.3" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/ba/19/1b9b0e29f30c6d35cb345486df41110984ea67ae69dddbc0e8a100999493/tzdata-2026.2.tar.gz", hash = "sha256:9173fde7d80d9018e02a662e168e5a2d04f87c41ea174b139fbef642eda62d10", size = 198254, upload-time = "2026-04-24T15:22:08.651Z" } +sdist = { url = "https://files.pythonhosted.org/packages/92/ff/5a28bdfd8c3ebec42564ac7d0e54ca3db65044a9314a97f9564fa7a1e926/tzdata-2026.3.tar.gz", hash = "sha256:4a1518b8993086a7982523e071643f3c0e5f213e75b21318e78bcabfff9d1415", size = 198674, upload-time = "2026-07-10T08:50:37.887Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/ce/e4/dccd7f47c4b64213ac01ef921a1337ee6e30e8c6466046018326977efd95/tzdata-2026.2-py2.py3-none-any.whl", hash = "sha256:bbe9af844f658da81a5f95019480da3a89415801f6cc966806612cc7169bffe7", size = 349321, upload-time = "2026-04-24T15:22:05.876Z" }, + { url = "https://files.pythonhosted.org/packages/e5/6d/b53b99a9f2766d095985947a5782f1702cabb129a34f7a802d7197af832f/tzdata-2026.3-py2.py3-none-any.whl", hash = "sha256:dc096730c87af6cab1b171c9d532be840741ff5d459015e7f6947bd7d7e54931", size = 348168, upload-time = "2026-07-10T08:50:36.46Z" }, ] [[package]] name = "tzlocal" -version = "5.4" +version = "5.4.4" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "tzdata", marker = "sys_platform == 'win32'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/d8/52/ee2e6d7031687c5bad28363148cb72f2bbf38201d2e220671bd9fb830bc2/tzlocal-5.4.tar.gz", hash = "sha256:41e1293f80d4b5ff38dff222601a8fbd06b4fdcaf25e224704047ad26a39af54", size = 30922, upload-time = "2026-06-15T12:06:56.594Z" } +sdist = { url = "https://files.pythonhosted.org/packages/81/5b/879b2f932adfa7a053c360d50bc896c977fa6426109185f7c12ebdd0cb9d/tzlocal-5.4.4.tar.gz", hash = "sha256:8dbb8660838688a7b6ba4fed31d18dedf842afb4d47ca050d6d891c2c15f3be4", size = 31170, upload-time = "2026-06-29T08:03:40.026Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/1d/70/5771c9ecbdb7cc0c3f3bbded7e0fa7911ee8e872ce5b5dc48ce7dce21a11/tzlocal-5.4-py3-none-any.whl", hash = "sha256:024d11221ff83453eae1f608f09b145b9779e1345d08c15404ce8ff7917cf629", size = 28261, upload-time = "2026-06-15T12:06:54.914Z" }, + { url = "https://files.pythonhosted.org/packages/9e/a4/017a7a6cbe387d961a688ec31364ae60a5c4e22c96ae9921b79a947c855d/tzlocal-5.4.4-py3-none-any.whl", hash = "sha256:aae09f0126a8a86fa736be266eb4a471380d26a0de3bc14844e7821fee3e2a15", size = 18115, upload-time = "2026-06-29T08:03:38.666Z" }, ] [[package]] @@ -5177,129 +5111,117 @@ wheels = [ [[package]] name = "uuid-utils" -version = "0.16.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/01/a1/822ceef22d1c139cffebe4b1b660cfaa10253d5c770aa2598dc8e9497593/uuid_utils-0.16.0.tar.gz", hash = "sha256:d6902d4375dfba4c9902c736bb82d3c040417b67f7d0fa48910ddfdb1ac95de7", size = 42596, upload-time = "2026-05-19T07:44:23.28Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/fd/78/fc830a25597001586770f0436a4917aac21fcdaf7ac2824bbe168ccdc724/uuid_utils-0.16.0-cp310-cp310-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:a632fead2a6505a8df3318d5e95503739b9aa1c518521cd93d83ce00699b78f8", size = 566691, upload-time = "2026-05-19T07:45:14.2Z" }, - { url = "https://files.pythonhosted.org/packages/10/39/3f1eee6d3c3c33d6dd75441bdb49ac246de57f97f67faa7ff04cdb5e4ffe/uuid_utils-0.16.0-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:d716e5b35266400d2a2cd349697868179825f113c543e55c9d2ac304991f8d4f", size = 291039, upload-time = "2026-05-19T07:45:52.28Z" }, - { url = "https://files.pythonhosted.org/packages/c6/85/f7fb16eed216fd8085d62d4ce7179e2a81ac7649e043f34168e7700b6df4/uuid_utils-0.16.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:207c2a98ca8b065cc93378a3a59744efb88a68e9ecc2c3afefe43d59c864280a", size = 327880, upload-time = "2026-05-19T07:44:28.611Z" }, - { url = "https://files.pythonhosted.org/packages/06/ea/b2b629d29c8234677850e1ae47add9c8866dfb3864af257542989a13ba1b/uuid_utils-0.16.0-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:79824850330e450c7b2fa933572e32192240060937426052fa3fc05134ed3faa", size = 334090, upload-time = "2026-05-19T07:44:57.354Z" }, - { url = "https://files.pythonhosted.org/packages/1b/8e/a6871c6231244bb80be06a2babf3ca34396b29d893103d84ddfd3654e6e4/uuid_utils-0.16.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d89927c47e1a55509e90b7f2fd3e7ff89908c77b61f8f0deda97a89d8854e0f8", size = 448558, upload-time = "2026-05-19T07:45:03.986Z" }, - { url = "https://files.pythonhosted.org/packages/bf/d0/b606a2857f98c20c149044e80f276ff7966c9f679fc7b25f6d608bd8d48b/uuid_utils-0.16.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f7ae4168e1ca0ae69d24207645a8b3cd2b641a0ad15058eda17d2c9898aa89d3", size = 327733, upload-time = "2026-05-19T07:43:40.129Z" }, - { url = "https://files.pythonhosted.org/packages/2d/e1/7951dd47b6717b6ebb340e673d31d539be928d280a697fab4dd233bcc7fa/uuid_utils-0.16.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d363017a3223de3a57eb6fca135df6ffcef7c534836bff2e71354dce7d10987c", size = 353659, upload-time = "2026-05-19T07:44:03.551Z" }, - { url = "https://files.pythonhosted.org/packages/a2/5d/f46e91fad5f049c7bd12701293c1ac31b4460ec83606c4bdd37c05abef52/uuid_utils-0.16.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:4a87a7433b355eadaa200f150da6bb5b87bb6de0adf260883b26cb637aba0410", size = 504509, upload-time = "2026-05-19T07:44:34.147Z" }, - { url = "https://files.pythonhosted.org/packages/f4/94/ea4f559e5e87da5847ecf78ba68a78e8bb4e537e1169093ea543cab94886/uuid_utils-0.16.0-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:6da070e75b0e2424728e6f8547647cce36c83f9a6101a08da4849a8ab2b58105", size = 609358, upload-time = "2026-05-19T07:44:39.711Z" }, - { url = "https://files.pythonhosted.org/packages/bf/41/60dbac2459426a925b77e08cb8ec492d4bc82caa0f124f498d2e24409cb8/uuid_utils-0.16.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:1baab8966f9e0097cbaf9cc01ad448b38e616e7b4968ca5e49cb53a74ad91a2f", size = 569428, upload-time = "2026-05-19T07:44:46.025Z" }, - { url = "https://files.pythonhosted.org/packages/e8/90/ae39c1e1bff65dfe9c7c70cbd64b8d529a3d1cc836aeaa7accdc44e5c308/uuid_utils-0.16.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:b42014536943c1a654ff107538c0f7dc39809d8d774ec8dafd19bec05006e568", size = 532465, upload-time = "2026-05-19T07:44:05.127Z" }, - { url = "https://files.pythonhosted.org/packages/03/5c/4dc93017a095c9c314525a9abc4f9983e520d88d7eff9bd52398d81c374e/uuid_utils-0.16.0-cp310-cp310-win32.whl", hash = "sha256:228701ab6f188b6def24f2add6db64f0794adb1f06d0abacdcec40b0cda13cdf", size = 171162, upload-time = "2026-05-19T07:44:58.518Z" }, - { url = "https://files.pythonhosted.org/packages/43/df/1398f5b117d5daa4d757b156728db7aa092a3eff1271c40ec39dbe945327/uuid_utils-0.16.0-cp310-cp310-win_amd64.whl", hash = "sha256:10d3c5983f770b1b2847ad811c87a1c9e28f8155d1a27cc581abcd5abb386b64", size = 176927, upload-time = "2026-05-19T07:44:54.93Z" }, - { url = "https://files.pythonhosted.org/packages/24/24/0e18177e2fbb0b9f54f90fd48fe3302dfda731e22ad650d6e6f8f4b3d3d3/uuid_utils-0.16.0-cp311-cp311-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:04af9966ecd82b78eeba5725e29aa1e86fb8eb84b5443dd6a9935f9fadb6678e", size = 565929, upload-time = "2026-05-19T07:44:06.496Z" }, - { url = "https://files.pythonhosted.org/packages/5a/7e/bb91b04b2c8a081a4df2d50f1a50dd85502e2391c6eaed71b339ec9f2524/uuid_utils-0.16.0-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:3d86ca394e0ea21bdb53784eb99276d263b93d1586f56678cab1414b7ae1d0f3", size = 290556, upload-time = "2026-05-19T07:43:44.973Z" }, - { url = "https://files.pythonhosted.org/packages/69/2a/47ee18b294af59754ef5acfa96eb027137c98cef7521199b6f70be705de4/uuid_utils-0.16.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c9f504efeb20ffd9571621658f7c8093c646d33150406d5742e49ff7cd861615", size = 328059, upload-time = "2026-05-19T07:45:30.533Z" }, - { url = "https://files.pythonhosted.org/packages/89/7c/ed6d8bb48eeecaed6722af1187d722c5243334be750419d10d5f05dffeb2/uuid_utils-0.16.0-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:57d85f48535dc541060f6b82f277cbcd12b78c04008ccc1039546cfcec027327", size = 334759, upload-time = "2026-05-19T07:45:07.715Z" }, - { url = "https://files.pythonhosted.org/packages/ff/33/371bddf9fd47e045c375df9668eea0d96ce9201ab6a03985b0155498e376/uuid_utils-0.16.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:39453f1ebf4398fbeb71607f3437e2ac469c9e38b5921755c1e17ad0158a8907", size = 448927, upload-time = "2026-05-19T07:45:11.464Z" }, - { url = "https://files.pythonhosted.org/packages/dc/f1/b201d5ee005d4987fc072714fcb9f6e75303520cf19d4deec0b4df44bf40/uuid_utils-0.16.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:50361aca5c2a770728a6343df85109fe57f89ac026827f34fe0153563cdc9ce7", size = 327178, upload-time = "2026-05-19T07:44:02.255Z" }, - { url = "https://files.pythonhosted.org/packages/b1/6a/04b4c02ce5c24a3602baa12e59bd3ec853ae73c3e9319b706c4620f47a05/uuid_utils-0.16.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:948485c47d8569a8bf6e86f522a2599fa9134674bee9f483898e601e68c3caca", size = 352981, upload-time = "2026-05-19T07:44:25.578Z" }, - { url = "https://files.pythonhosted.org/packages/2c/19/25db019727d14630c75c2a75a8ea66dd712bb468adcf410bac8d01ff19fd/uuid_utils-0.16.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:ceef237cf8467fddbf6d8466cc1f6e2c04605ec919046ef5eba10a895b559fcf", size = 504686, upload-time = "2026-05-19T07:43:46.43Z" }, - { url = "https://files.pythonhosted.org/packages/5d/93/c000cd42ebfdd37cc74981ed31c979a1270156572bdebab8b5d61460e750/uuid_utils-0.16.0-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:24e6fa0d0ade7a9ad60a3c296022474983243df5b4e863babb4828a85ef2e52c", size = 610102, upload-time = "2026-05-19T07:45:53.765Z" }, - { url = "https://files.pythonhosted.org/packages/15/1d/7dd239909c82616722b9ee53fa1b4657c6244fb4fd026890300ebf6db22b/uuid_utils-0.16.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:1c2df42314b014c9d23330f92887e21d2fc72fde0beb170c7833cd2d22d845a1", size = 569048, upload-time = "2026-05-19T07:45:41.596Z" }, - { url = "https://files.pythonhosted.org/packages/f1/49/b6a688648368a9cc0137e183657956853a91dc06ef73deda27290d586155/uuid_utils-0.16.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:2e2f369dd734050fe96ae4905c58779b09276d47d5e9a0e5cd33ec7982784341", size = 532255, upload-time = "2026-05-19T07:45:16.936Z" }, - { url = "https://files.pythonhosted.org/packages/3f/fb/34f221ae93d5ea249a0d7056bdf45313b8d267d6aa9c5d0673ac1a4746c7/uuid_utils-0.16.0-cp311-cp311-win32.whl", hash = "sha256:733da81d51ea578862d8b9b754e8968b6da2be2b7840aee868917c23cae84015", size = 171081, upload-time = "2026-05-19T07:45:26.578Z" }, - { url = "https://files.pythonhosted.org/packages/a5/70/c2a608a813f655834ee6df4ce53ea46edad4d54f774eac1890be5c7e4e1c/uuid_utils-0.16.0-cp311-cp311-win_amd64.whl", hash = "sha256:10d21fddb086e69245c4f0f77c7b442471f3a242aa85f62954bff157baa1c5f2", size = 176770, upload-time = "2026-05-19T07:43:49.102Z" }, - { url = "https://files.pythonhosted.org/packages/fd/c3/8ab4eff328a833c065f280b2e0d9ac873505b5e5282f2bc5133a9843d4dd/uuid_utils-0.16.0-cp311-cp311-win_arm64.whl", hash = "sha256:98e2404713677070cee9a99a1f1e24afd496c18e833ee1b31a0587659452ff80", size = 175274, upload-time = "2026-05-19T07:44:27.216Z" }, - { url = "https://files.pythonhosted.org/packages/ff/4c/b4cf43a5d22bcdb91727acdf54be0d78e83e595b73c5a9a8a4291875f059/uuid_utils-0.16.0-cp312-cp312-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:727fae3f0682191ec9c8ce1cd0f71e81b471a2e26b7c5fd66712fc0f11640aa0", size = 562183, upload-time = "2026-05-19T07:45:02.683Z" }, - { url = "https://files.pythonhosted.org/packages/d6/fb/4b0d1c4b5e9f8679ca41b9cdbce5749e1d5db3d3d42a07060d6ce61ac583/uuid_utils-0.16.0-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:66a9c8cedf7695c28e700f6a66bde0809c3b2e0d8a70968be7bfd47c908952e5", size = 289018, upload-time = "2026-05-19T07:44:07.726Z" }, - { url = "https://files.pythonhosted.org/packages/de/43/2dc6c7401c8fab86e46b0b33ada6dcfde949b2fd48877ba6f880862be80e/uuid_utils-0.16.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9152bff801ec2ccf630df06d67389090a2c612dea87fbf9a887ab4b222929f6f", size = 326171, upload-time = "2026-05-19T07:45:25.186Z" }, - { url = "https://files.pythonhosted.org/packages/9b/f5/48f11fb91f36453611ca148bc441436f279870b1ec6b576dc5167fb6e680/uuid_utils-0.16.0-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:06fc7db470c37e5c1ab3fd2cd159697d6f8b279d7d23b5b96bd418b115f8caa9", size = 332222, upload-time = "2026-05-19T07:45:09.036Z" }, - { url = "https://files.pythonhosted.org/packages/30/cb/b2b49528521e4a097f129e8bf7850a26f00af46afba778832cf3458a5c00/uuid_utils-0.16.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3e1a1f57fe3631e164dad27b24aa81267810e20575f705af3b0fa734f3a21247", size = 444801, upload-time = "2026-05-19T07:45:37.517Z" }, - { url = "https://files.pythonhosted.org/packages/a9/b3/a28d9c6f7c701dfe01c8020b30e33899a28eb9e4d056b07e7388f50ebf67/uuid_utils-0.16.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3ee392fe59808a731b7b6bf4d453fb6e833774921331cceae5f254d1e9c5b97d", size = 325594, upload-time = "2026-05-19T07:44:44.682Z" }, - { url = "https://files.pythonhosted.org/packages/cf/65/e1ff41dc44966e396ead86e104ba21b35ddb07ff7a64bb55013074ee77fe/uuid_utils-0.16.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:b2e981b1258db444df4cf4bf4c79673570d081d48d35f22d0f86471e0ad795c5", size = 349312, upload-time = "2026-05-19T07:45:15.582Z" }, - { url = "https://files.pythonhosted.org/packages/ed/57/fb19b7951f66a46e03bd1943a61ee9d59c83e994e56e8c97d79aff1f0e47/uuid_utils-0.16.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:bbb92feb4db08cd76e27b4d3b1a82bfde708447317150c614eb9f761a43b387e", size = 502115, upload-time = "2026-05-19T07:43:38.756Z" }, - { url = "https://files.pythonhosted.org/packages/2f/8e/9a129c469b7b77afb62da5c6b7e92591073b845bd0c3108c0d0aa65389fb/uuid_utils-0.16.0-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:1c3c5afaaa68b1d6393d653e9fc93a2fde9da1681da01f74b4593f41d31fb5f1", size = 607433, upload-time = "2026-05-19T07:44:11.675Z" }, - { url = "https://files.pythonhosted.org/packages/4a/56/2ef71fad168cc3d894f7094fa458086c093635d7835381c91470b19c9ad3/uuid_utils-0.16.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:38126b353527c5f001e4b24db9e62351eb768d0367febcd68100a4b39a035109", size = 566076, upload-time = "2026-05-19T07:44:35.453Z" }, - { url = "https://files.pythonhosted.org/packages/95/bf/68e60ea053ca30f35df877b96001331398140d5c4983561affa1350331b1/uuid_utils-0.16.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:41a67e546d9adf11c4e4cb5c8e81f000f8b1f000c17912ced089b499855719a5", size = 530645, upload-time = "2026-05-19T07:45:49.278Z" }, - { url = "https://files.pythonhosted.org/packages/42/19/b521f7d73094fca4c0c44002f4a42bfcbcf0b770fdc3c4b9a596dda25734/uuid_utils-0.16.0-cp312-cp312-win32.whl", hash = "sha256:52d2cc8c12a3466cd1727883e0746d8bad5dddd670369eb553ba17fdc3b565ca", size = 168887, upload-time = "2026-05-19T07:45:45.502Z" }, - { url = "https://files.pythonhosted.org/packages/87/1f/4126c3ccbc2d98a613664e55f6ab6d7bd4b98424a04486e4fcc76549af15/uuid_utils-0.16.0-cp312-cp312-win_amd64.whl", hash = "sha256:c97625e5edfda8b118160ce1e88756f92b1635775f836c168be7bf10928d97fa", size = 174607, upload-time = "2026-05-19T07:43:52.938Z" }, - { url = "https://files.pythonhosted.org/packages/74/62/b83ccc8446ae39dcc0bda2cb3b525b6af6a2036383afe1d1d5fe7b234c2c/uuid_utils-0.16.0-cp312-cp312-win_arm64.whl", hash = "sha256:baf79c8050eb784b252dd34807df73f61130fe8676b61231baccab62530f20ec", size = 173021, upload-time = "2026-05-19T07:45:10.204Z" }, - { url = "https://files.pythonhosted.org/packages/60/9b/74c1f47a9b4f138a254e51528e5ffaeba6bf99ecead9f0c4b6fccccfbfcb/uuid_utils-0.16.0-cp313-cp313-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:d34cf9681e8892fad2a63e393068e544505408748cd8bf0c3517d753a01528d4", size = 563166, upload-time = "2026-05-19T07:44:10.494Z" }, - { url = "https://files.pythonhosted.org/packages/7c/1c/009e37b70f1f0ff17e7103a36bafde33d503d9ea7fe739761aa3e3c9fde6/uuid_utils-0.16.0-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:0681d1bdb7956e0c6d581e7601dabcfb2b08c25d2a65189f4e9b102c94f5ff46", size = 289529, upload-time = "2026-05-19T07:43:54.466Z" }, - { url = "https://files.pythonhosted.org/packages/5e/5e/e0323d54321166639eb2be5e8a464f5cb0fc04d72d91f3e78944bb6a1da8/uuid_utils-0.16.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ed45fb8732d216426227096b55accbb87cba57febc86a044d90780b090eb99d0", size = 326328, upload-time = "2026-05-19T07:45:31.901Z" }, - { url = "https://files.pythonhosted.org/packages/f0/a3/046f6cb958467c3bf4a163a8a53b178b64a62e21ed8ad5b2c1dacb3a2cfc/uuid_utils-0.16.0-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:b617a334bb01ef2ff8c22900f5a14125eb9063f602131494cc9dc59519beaa5b", size = 332322, upload-time = "2026-05-19T07:43:41.284Z" }, - { url = "https://files.pythonhosted.org/packages/67/80/01914e3949744db7acd0006885e5542fbebb6e39114857d007d29b3265c2/uuid_utils-0.16.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a750d8aeb8ae880aa9a2529606bde0e994bcc7448730c953107f357a28e6102e", size = 445787, upload-time = "2026-05-19T07:45:36.102Z" }, - { url = "https://files.pythonhosted.org/packages/14/ef/f6908f41279f205d70c8a0d5dcb25dd6802741d7f88e3f0123453c3584d3/uuid_utils-0.16.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9a250e111903c4368745fce5ac2aa607bd477c62d3307e45347338fdb64b38e0", size = 324678, upload-time = "2026-05-19T07:45:12.77Z" }, - { url = "https://files.pythonhosted.org/packages/11/4a/bf841ba90f829c7779d82155e0f4b88ef6726ccc25507d064d50ac2cd329/uuid_utils-0.16.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:95b7f480010ea98a29ee809857a98aa923008c68129af1b39244adccff7377fb", size = 349704, upload-time = "2026-05-19T07:44:47.172Z" }, - { url = "https://files.pythonhosted.org/packages/e6/31/3b5c60172b8c57bf4ca485484b8e4edef550ca324f9287f1183be97422e2/uuid_utils-0.16.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:420aa3ca403cedb73490b6ea3aeefeea7e0455f5ce60bbf856390ee872ae3306", size = 502456, upload-time = "2026-05-19T07:45:00.821Z" }, - { url = "https://files.pythonhosted.org/packages/88/bf/3da8d497af80fd51d8bf85551c77ede67f07825924ec5987bf9b6031014a/uuid_utils-0.16.0-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:b8a9a7b1065a12d40f2cc25b7d705ab34954cc57095034367bca39ebcf4a876b", size = 607727, upload-time = "2026-05-19T07:44:30.058Z" }, - { url = "https://files.pythonhosted.org/packages/bd/4e/7c8cf03ec15cd6f40e4cbab81b2b4a625461327f68c7971e54723280ec3e/uuid_utils-0.16.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:f235ac5827d74ac630cc87f29278cdaa5d2f273613a6e05bbd96df7aa4170776", size = 566204, upload-time = "2026-05-19T07:44:51.225Z" }, - { url = "https://files.pythonhosted.org/packages/f9/5f/af955feae69cce7fd2121ca3f790ff4b85ad2e17b2149546f50753e1a047/uuid_utils-0.16.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:c8083284488b84ad178e74add64cfd1e74e8be5e30821e5acbc5019281c658b0", size = 529986, upload-time = "2026-05-19T07:45:57.85Z" }, - { url = "https://files.pythonhosted.org/packages/10/cf/3fec757e51bef10eb41ae8075f5442c60e85ff456b42d16a3063f5dc6c80/uuid_utils-0.16.0-cp313-cp313-pyemscripten_2025_0_wasm32.whl", hash = "sha256:27a071a899ba46a551d6524dbbc5a98b88be176d0f55ddf72cf71c005326ac10", size = 98683, upload-time = "2026-05-19T07:44:16.369Z" }, - { url = "https://files.pythonhosted.org/packages/40/a7/cd1adbea7ef882a70db064c00cd93b12e11027b4cdd7ffd79e95c35fc3e3/uuid_utils-0.16.0-cp313-cp313-win32.whl", hash = "sha256:924a8de04460e4cf65998ad0b6568084f7c51740ebd3254d07a0bcde35a84af6", size = 168822, upload-time = "2026-05-19T07:44:24.09Z" }, - { url = "https://files.pythonhosted.org/packages/74/99/617ceb9e3a95b23837012740979baf71afad723b70daf34862da3f7c17a1/uuid_utils-0.16.0-cp313-cp313-win_amd64.whl", hash = "sha256:5279bc7ab3c6683f1c67314695bee14d869015acbbc677bdb0015190fe753d16", size = 174967, upload-time = "2026-05-19T07:44:56.022Z" }, - { url = "https://files.pythonhosted.org/packages/d9/d8/148ae707bfc36d482e39db679c86b81bdce264d4feb9df5d40a03b7687e3/uuid_utils-0.16.0-cp313-cp313-win_arm64.whl", hash = "sha256:61a9c4c26ad12ac66fa4bfd0fdb8494724fe7a5b98a9fcd43e78e2b388663dbb", size = 173142, upload-time = "2026-05-19T07:43:50.171Z" }, - { url = "https://files.pythonhosted.org/packages/21/05/ca6d60705e71fdeaa3431dad94e279a8213c5573cb2925e1aabf3dc0330a/uuid_utils-0.16.0-cp313-cp313t-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:73486b6aa3f755a6c97000f5ea67e7ac78d6df89bf22980789a1e943e24b74f0", size = 564408, upload-time = "2026-05-19T07:44:38.351Z" }, - { url = "https://files.pythonhosted.org/packages/eb/8c/b9a0462c38535c1662acb1025768e2d626bee5ce9e1790bad6b5381162ea/uuid_utils-0.16.0-cp313-cp313t-macosx_10_12_x86_64.whl", hash = "sha256:f1614572fd9345cdc3dde3f40c237345719fabca1aa87d2d87b321d523cfa34d", size = 289923, upload-time = "2026-05-19T07:45:19.611Z" }, - { url = "https://files.pythonhosted.org/packages/f2/33/a53afeef1a56051551a0f5a801e4bce411dd73c6a8c99bad16902651256d/uuid_utils-0.16.0-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9346ce6eb1fbd8b03a6b331d66016afcb4edcdff6eac708e21391600529a016a", size = 325762, upload-time = "2026-05-19T07:45:18.261Z" }, - { url = "https://files.pythonhosted.org/packages/72/ca/4462a4f36365d7ee72d41e05e6bcfe127e861b073ab37c25b2c8a518317c/uuid_utils-0.16.0-cp313-cp313t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:a0fc6eb3fd821466fbab69cf356c6ec2b7327266bbbc740a2eb57c77c4bef965", size = 332359, upload-time = "2026-05-19T07:45:34.886Z" }, - { url = "https://files.pythonhosted.org/packages/c5/67/9d3373fa7c5a746fdecc64e30caf915c29eb632203508d87676f9243ed03/uuid_utils-0.16.0-cp313-cp313t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:13a797e5e8f0dadc18351a5aa013815ddac25dce6864072a539d510910c95f71", size = 445483, upload-time = "2026-05-19T07:44:49.598Z" }, - { url = "https://files.pythonhosted.org/packages/57/08/ce01aa6d897fc7f875844fe58cad0a542c8ebf089d9242b654b56260ecb8/uuid_utils-0.16.0-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:57c3583b1f1c00a94f59726a5e2b988fa209221143919a1af5c2fc24e318fc98", size = 326281, upload-time = "2026-05-19T07:44:59.677Z" }, - { url = "https://files.pythonhosted.org/packages/76/ef/2c719b2c26bb5b5e5061a1435c11ad2bd33ac3cd6d4cd0c7c3ac1d3396ed/uuid_utils-0.16.0-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:caac9c8b1d50e8fbddc76e93bfefbef472978eb45adbfdb6289d578816992953", size = 350809, upload-time = "2026-05-19T07:45:28.076Z" }, - { url = "https://files.pythonhosted.org/packages/e0/9b/c1ed447328b32229cca38ac4c62d309eab006e5e9c4020e2056a175bc607/uuid_utils-0.16.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:91db59bad97ed2b9d2c6ed25082fe9762b2c422e694fe06786b28cf4e776ac4c", size = 502088, upload-time = "2026-05-19T07:44:09.208Z" }, - { url = "https://files.pythonhosted.org/packages/c1/e0/8442f4efe7bde72f0b4ae5f675d0c7fbe209ad0b54718b8ddf43c46c6fae/uuid_utils-0.16.0-cp313-cp313t-musllinux_1_2_armv7l.whl", hash = "sha256:41985e342a30e76366a8becc60bbdb07d72cd1b86ec657b1f31654e9fb1baada", size = 607631, upload-time = "2026-05-19T07:44:19.384Z" }, - { url = "https://files.pythonhosted.org/packages/f1/1e/9a9fa261edf4c972f28ae83421377e3ab8dbd0bd7db58fd316e782d09a3b/uuid_utils-0.16.0-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:1b0dcedf9266bf34a54d5cbe78648eaa627e02352f2a6923ed647530aea2f661", size = 567618, upload-time = "2026-05-19T07:43:58.478Z" }, - { url = "https://files.pythonhosted.org/packages/cc/f7/1bcfdb9d539bd42736dd6076470a42fbb5db23f79712c0a06aa0a3752f7b/uuid_utils-0.16.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:26fe23ab60f05de4ad70aaa5b6a4c2a7bbd43055e3dd6f6b31efba0532ac9c71", size = 530971, upload-time = "2026-05-19T07:45:06.348Z" }, - { url = "https://files.pythonhosted.org/packages/24/0c/18945f417d6bb4d0dd2b7652fe36c58c4e83bcf593b9b326b83aa40b853a/uuid_utils-0.16.0-cp313-cp313t-win32.whl", hash = "sha256:7f8cf49c05d58523a0f977cb7f11afc05791a0fa164d7303b8365a34750638e7", size = 169369, upload-time = "2026-05-19T07:44:32.581Z" }, - { url = "https://files.pythonhosted.org/packages/cc/cc/c0eb0c3fab2ed80d706369b750029143b53126809b77b36bcbb77da66bab/uuid_utils-0.16.0-cp313-cp313t-win_amd64.whl", hash = "sha256:e99f9a8b2420b228faba23a637e96efaf5c6a678b2e225870f24431c82707f50", size = 175384, upload-time = "2026-05-19T07:45:56.623Z" }, - { url = "https://files.pythonhosted.org/packages/b7/77/50ac87b6e18b1c686f700aa38c9471a990683c6a955f71ac1a6677ed8145/uuid_utils-0.16.0-cp314-cp314-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:6853b627983aa1b4fd95aa52d9e87136eb94a7b3b7de0fbb1db8a498d457eeec", size = 564108, upload-time = "2026-05-19T07:43:55.609Z" }, - { url = "https://files.pythonhosted.org/packages/83/16/65046676de246bb5334d9f58aa96d2feb9fc347fda3556aaff7da1c2fc7a/uuid_utils-0.16.0-cp314-cp314-macosx_10_12_x86_64.whl", hash = "sha256:f44b65ae0c329843817d9c90e36a7a3c677b413bf407c99e67db874dac49dad3", size = 289967, upload-time = "2026-05-19T07:45:38.886Z" }, - { url = "https://files.pythonhosted.org/packages/91/d6/54fa988606a15dfd2028e925d8eb9c3ee6edbf1eb7692a67b37282880b56/uuid_utils-0.16.0-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:de8a365795a76f347f5622621c2bee543cffa0c70949f3ee093bdefc9d926dcc", size = 325835, upload-time = "2026-05-19T07:44:42.02Z" }, - { url = "https://files.pythonhosted.org/packages/d5/1b/50622f967ceacea1f89fd065d9bfd395b51acb02cfb0a4ddc8fa9ff0c983/uuid_utils-0.16.0-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:426a8c9af90242d879706ccf29da56f0b0712e7739fb0bbe16baacabc75596e2", size = 332607, upload-time = "2026-05-19T07:43:42.42Z" }, - { url = "https://files.pythonhosted.org/packages/12/f5/4059706be6617e2787e375ea52994ce3c3fa3920b7d4a9c8ebf7895681a5/uuid_utils-0.16.0-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:833bc4b3c3fc24be541f67b01b4a75b6b9942a9b7137395b4eb35435948bd6da", size = 444287, upload-time = "2026-05-19T07:43:37.106Z" }, - { url = "https://files.pythonhosted.org/packages/65/d5/f44b2710563da687a368f0ce4dcbd462dfb6708bcd46439d831991d595c7/uuid_utils-0.16.0-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:efb5252d7c00d586077f10e169d6e6d0b0d0f806d8a085073f0d19b4737aef4e", size = 324949, upload-time = "2026-05-19T07:45:33.175Z" }, - { url = "https://files.pythonhosted.org/packages/3a/a7/a69e859e37d26c5603f0bc0ae481860f691224f140e5a832f325b804770d/uuid_utils-0.16.0-cp314-cp314-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:0b3377ce388fd7bf8d231ec9d1d4f58c8e87888ddea93581f60ed6f878a4f722", size = 349651, upload-time = "2026-05-19T07:43:59.998Z" }, - { url = "https://files.pythonhosted.org/packages/db/73/4139cd3ca7b81ea283c1c8769373e9b2008241c0744a8ffb25f0a1b31325/uuid_utils-0.16.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:12b6310beb38adc173ec5dc89e98812fd7e3d98f87f3ef01d2ea6ecb5d87994f", size = 502326, upload-time = "2026-05-19T07:45:40.292Z" }, - { url = "https://files.pythonhosted.org/packages/cb/8c/858101583fbad1b3fa04da88b1f7170836aa0f00b4cb712063325c44466d/uuid_utils-0.16.0-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:a49b5a75497643479c919e2e537a4a36224ac3aaa0fada61b75d87024021ac3e", size = 607689, upload-time = "2026-05-19T07:44:48.355Z" }, - { url = "https://files.pythonhosted.org/packages/5e/bd/8f3d54a4763dd91ebd0f3d7b0c2ec434e4e0b1fc667b03a44d611a465ec6/uuid_utils-0.16.0-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:63bfdf00be51b6b3b79275d6767d034ea5c7a0caa067a35d72861284100cb60a", size = 566214, upload-time = "2026-05-19T07:44:53.519Z" }, - { url = "https://files.pythonhosted.org/packages/54/76/4c9a8d9baaa243c7902d84dbba4d51b1ab51c379c66d3fd6368ff6933ecf/uuid_utils-0.16.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:7525bc59ac4579c32317d2493dd42cf134b9bb50cd0bc6a41dd9f77e4740dde6", size = 529989, upload-time = "2026-05-19T07:44:43.141Z" }, - { url = "https://files.pythonhosted.org/packages/6d/13/d32cea997f880cedde415730ce0e872ebfd7a040155ae0bbda70eccd208e/uuid_utils-0.16.0-cp314-cp314-win32.whl", hash = "sha256:fbcac6e6710aa2e4bfbb81762758e01470dc56d5048ba4253acc77c9833568ff", size = 169146, upload-time = "2026-05-19T07:45:46.655Z" }, - { url = "https://files.pythonhosted.org/packages/1c/19/9fc55172d8fe59e1f27a14d598b427fa508a7ebb35fa7b7b99c24fa0ef13/uuid_utils-0.16.0-cp314-cp314-win_amd64.whl", hash = "sha256:d23fcaf37368a1647319187ef6f8b741bf079f033065899bc2d00a44b0a1214a", size = 175364, upload-time = "2026-05-19T07:45:55.335Z" }, - { url = "https://files.pythonhosted.org/packages/89/5d/fcd9226b715c5aa0638fcdd6deaf0de6c6c3c451c692cd76bfca810c6512/uuid_utils-0.16.0-cp314-cp314-win_arm64.whl", hash = "sha256:ea3265f8e2b452a4870f3298cb1d183dc4e36a3682cbb264dbe46af31267e706", size = 173268, upload-time = "2026-05-19T07:44:31.19Z" }, - { url = "https://files.pythonhosted.org/packages/c1/64/97ec9af95e58b8187f2934008ffab26e1604d149e34fe01c388b0543a24f/uuid_utils-0.16.0-cp314-cp314t-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:99f8420c3ed59f89a086782ac197e257f4b1debb4545dffa90cf5db23f96c892", size = 564464, upload-time = "2026-05-19T07:44:40.856Z" }, - { url = "https://files.pythonhosted.org/packages/3e/6d/e4082f407484ac28923c0bf8e861e71d277118d8b7542d0a350340e45350/uuid_utils-0.16.0-cp314-cp314t-macosx_10_12_x86_64.whl", hash = "sha256:259bab73c241743d684dcc3507feb76f484d720545e4e4805582aeff8e19700b", size = 290087, upload-time = "2026-05-19T07:44:01.084Z" }, - { url = "https://files.pythonhosted.org/packages/8c/43/c5c5f273c0ff889f20f10344784f9197dd00eb81ccc294330d4b949fea7e/uuid_utils-0.16.0-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:897e8ef0dc5e4ac0b17cf9cae84bb41e560d806280ec5b93db7475b504022105", size = 325532, upload-time = "2026-05-19T07:43:47.508Z" }, - { url = "https://files.pythonhosted.org/packages/13/7f/669aa899ab5378374d28a28231e6978f739921a1af394c7ebd6cc86e2639/uuid_utils-0.16.0-cp314-cp314t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:c5af79cde16a7600dfccb7d431aec0afd3088ff170b6a09887bf3f7ab3cc7c81", size = 332209, upload-time = "2026-05-19T07:43:51.528Z" }, - { url = "https://files.pythonhosted.org/packages/2b/57/a2a32406d79a222794ef98a19254fd9a81a029a0f32d7740fba9873bff1f/uuid_utils-0.16.0-cp314-cp314t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:bece1a6f677ca36047442c465d8166643eed9818b9e43e0bf42d3cf73e92dcff", size = 445507, upload-time = "2026-05-19T07:44:20.541Z" }, - { url = "https://files.pythonhosted.org/packages/26/6b/85459a35bfa7d73e79acbc4eab1cf6aa6e4d9d022c3260ed9dea539c7f0b/uuid_utils-0.16.0-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2bb3444498e7b099499c8a607d7771377020fa55f7274e46f54106af19f752d7", size = 326154, upload-time = "2026-05-19T07:45:23.587Z" }, - { url = "https://files.pythonhosted.org/packages/84/9e/e965efdbb503ed14d6e57aec1a22b98326ed24cc2fb48e750c4d192267a0/uuid_utils-0.16.0-cp314-cp314t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:542098f6cb6874aebeff98715f3ab7646fbe0f2ffb24509ca372828c68c4ed0e", size = 350905, upload-time = "2026-05-19T07:44:36.957Z" }, - { url = "https://files.pythonhosted.org/packages/23/ae/4321867888a783d03b7c053c0b68ca45d03974d86fcebf44d4ec268db397/uuid_utils-0.16.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:7207b25fe534bcf4d57e0110f90670e61c1c38b6f4598ba855af69ab428fc118", size = 502098, upload-time = "2026-05-19T07:44:17.696Z" }, - { url = "https://files.pythonhosted.org/packages/9d/9a/914a47bf42479bff0ce3e1fa1cbe3585354708edc928e27687cf91de9c26/uuid_utils-0.16.0-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:16dc5c6e439f75b0456114e955983e2156c1f38887733e54d54205d3005223e4", size = 607032, upload-time = "2026-05-19T07:44:22.151Z" }, - { url = "https://files.pythonhosted.org/packages/85/4c/2abacd6badba61a047eaa39c8347656229d12843bd9bbe4906daa6dc752c/uuid_utils-0.16.0-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:a6d3ee32c57898d8415242b08d5dd086bc4f7bcbbb3fc102ef257f3d793eb294", size = 567664, upload-time = "2026-05-19T07:45:21.043Z" }, - { url = "https://files.pythonhosted.org/packages/53/1f/9d1a09521276424da19dc0d74456aed3311170fec181b28fa6acba45d963/uuid_utils-0.16.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:7555f120a2282d1901c9a632c2398a614101af4fe3f7c8114aa0f1d8c1978855", size = 530996, upload-time = "2026-05-19T07:45:44.229Z" }, - { url = "https://files.pythonhosted.org/packages/b4/22/14dbedb6b61f492d5524077fd10bbfb137583b0f0aafa6cd870ccb43f39a/uuid_utils-0.16.0-cp314-cp314t-win32.whl", hash = "sha256:756575d082ea4cb7d2f923d5b640c0efe7c82573aab49220c4e09b62d13737ff", size = 169358, upload-time = "2026-05-19T07:45:05.146Z" }, - { url = "https://files.pythonhosted.org/packages/25/f4/a636806c98401a1108f2456e9cc3fa39a618145bfb1d0860c57203159cfe/uuid_utils-0.16.0-cp314-cp314t-win_amd64.whl", hash = "sha256:aa50261a83991dbb570a00573741455bd8f3249444f7329e5bdcd494799d1504", size = 174813, upload-time = "2026-05-19T07:45:59.579Z" }, - { url = "https://files.pythonhosted.org/packages/75/12/3823742459d87a100deb24bb6b41692aa961b267abd130fa7739cdf7d409/uuid_utils-0.16.0-cp314-cp314t-win_arm64.whl", hash = "sha256:22a17e93a371d850ffce8fcdbacc2239f890efe73aa3262b6170c1febc08afe1", size = 171733, upload-time = "2026-05-19T07:45:29.283Z" }, - { url = "https://files.pythonhosted.org/packages/d3/89/655408a5485c56bf2c4561eb85f5bca119b1f4020370b4daaeb8d13e46fb/uuid_utils-0.16.0-pp311-pypy311_pp73-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:4e35e9a986e86806a61288fac3afbb51317f2580929feefd1661891ffd7b8c24", size = 569295, upload-time = "2026-05-19T07:45:22.325Z" }, - { url = "https://files.pythonhosted.org/packages/24/1c/a7c5506a4e2cf95ac98fec0996c56daa14e41f2ab1858f569b3556a202f9/uuid_utils-0.16.0-pp311-pypy311_pp73-macosx_10_12_x86_64.whl", hash = "sha256:b35706350cf9bd4813f1811bebe03cac09795a5a379f90cb3616171f4e9ffc9e", size = 292316, upload-time = "2026-05-19T07:43:57.044Z" }, - { url = "https://files.pythonhosted.org/packages/dd/75/4267ab8baa1e6a8ad7c262e204484b44df0fde0920025ea9b43c2b869726/uuid_utils-0.16.0-pp311-pypy311_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a4fd5c7936a876ba2606ba124603b559a5c2cea458c59b9c31677e6acc3c53cc", size = 329619, upload-time = "2026-05-19T07:44:12.928Z" }, - { url = "https://files.pythonhosted.org/packages/15/77/c794102831e331564f651099cac55006694677938d70f1033b35da451a89/uuid_utils-0.16.0-pp311-pypy311_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:130f7452c1b87b7c16d0bdc1f32a1de531ae4cc4220ed4e691402bbcfc39e0a9", size = 335121, upload-time = "2026-05-19T07:45:47.974Z" }, - { url = "https://files.pythonhosted.org/packages/8b/3e/458a0a2da75c596b151182a6c7550c6c3d30f479e14e40f69c0336579e59/uuid_utils-0.16.0-pp311-pypy311_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d5ee0bbbd4ca3968422cd8308f0072520bc73dc760cb26c6fa75ca1aca14d210", size = 449631, upload-time = "2026-05-19T07:45:50.645Z" }, - { url = "https://files.pythonhosted.org/packages/ed/15/dd1fab6f7fcd15f2c331d0c1f0f516bb1113a640216460f82be53db3dcf8/uuid_utils-0.16.0-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dc0824a31898ef46a9d84d748c3abe27cdb615ac3773c53cc1f84fc8e66dc7c4", size = 328418, upload-time = "2026-05-19T07:44:52.38Z" }, - { url = "https://files.pythonhosted.org/packages/96/56/62dcd551b140cbeb0f87522da2015b4b9e5818327b920506ad88d28562b0/uuid_utils-0.16.0-pp311-pypy311_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:abfbf5e0c47fb31b37164a99515104e449a0bee36a071dc8b105457a2b35a5e6", size = 356177, upload-time = "2026-05-19T07:45:42.856Z" }, - { url = "https://files.pythonhosted.org/packages/44/e7/3937b9a9d6745b94dbe7b86531e098db8c53b77c8d07df7daa9577a47b8e/uuid_utils-0.16.0-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:680799a9ade01d69c53cb9d41392ced24919d4f600bfab5060b61fca37510097", size = 178508, upload-time = "2026-05-19T07:43:43.774Z" }, +version = "0.17.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/e7/91/63938e0e7e7876658e5e40178e7c0735b53527886fe11797a11699c55edd/uuid_utils-0.17.0.tar.gz", hash = "sha256:abb5667a36119019b3fa320c4d10c21ebccfcc87c8a739e6a0056cee7f48dde2", size = 43220, upload-time = "2026-07-09T13:49:58.433Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/7c/60/659104207938f2ac62508b9aa595fc0515ac7452dd515c8e1d47d0b91169/uuid_utils-0.17.0-cp310-cp310-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:d2d9a63a9e6f2416ace8c109043a9280d6b34f34bb2e5421903e149403db40a6", size = 564038, upload-time = "2026-07-09T13:47:51.731Z" }, + { url = "https://files.pythonhosted.org/packages/fb/e7/e0d048a268b4163058bdd2f07a45bbe13c29e3cc6b7b88f8f00b001617ce/uuid_utils-0.17.0-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:b776c7fc8755c7de06dd5a22b47c40ae84f67d13277ebb233cc84933ba4dcbcd", size = 286680, upload-time = "2026-07-09T13:47:53.141Z" }, + { url = "https://files.pythonhosted.org/packages/84/83/e3606dc9b4224d0c9a6675d9347e7e0da7e67fa30e061bfdb686138844d0/uuid_utils-0.17.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1edf2f8732e4ed95bd7b65f2658f4aa072efaaff321144f4e0d4bf6a22709263", size = 323533, upload-time = "2026-07-09T13:47:54.433Z" }, + { url = "https://files.pythonhosted.org/packages/22/f8/aec5c34fa80c9fef09a506a098015e728080076494b72b9e8e5cfc9669c4/uuid_utils-0.17.0-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:84ed3a2d5cd3ae6db87af20bfed3331116195ba4757ad7177fc8f12c1bbce2a9", size = 330691, upload-time = "2026-07-09T13:47:55.677Z" }, + { url = "https://files.pythonhosted.org/packages/08/73/85776566863514f37b0a761648368e96b07d64981a9b6c391220aa2563a9/uuid_utils-0.17.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4bf4d9cd1e80e73922073b9b27c143bedeb109d65f94cd12712e2c87118f2b7d", size = 444094, upload-time = "2026-07-09T13:47:56.936Z" }, + { url = "https://files.pythonhosted.org/packages/68/06/e0424b4268c0932e0ff8257303d70de4053f05958843268fac4cb0f79b57/uuid_utils-0.17.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:52db0e471d3d2632d35445af352591f40a8f32959a412981d9f51e068bb9514b", size = 324548, upload-time = "2026-07-09T13:47:58.217Z" }, + { url = "https://files.pythonhosted.org/packages/db/d2/a0cb3a69ef6d9becc30a6a0594ddf6f798f6204953dfa85073cbec875b94/uuid_utils-0.17.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:344f7c755e280ea0ba6aeb08022190d867a80000b1715cacded54fc4b5633607", size = 350307, upload-time = "2026-07-09T13:47:59.418Z" }, + { url = "https://files.pythonhosted.org/packages/82/81/d82766af7db541e4a78b920bc1c4303d44995f841805d1498934088cd12c/uuid_utils-0.17.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:589d9da7de8fa7f739bb970ac4632c9a268213117d634e1c4a58c1c1e821ca05", size = 500661, upload-time = "2026-07-09T13:48:00.726Z" }, + { url = "https://files.pythonhosted.org/packages/10/71/b261cd0d38497ed8c2cce0263c5607ec9cd2bbace0f73cb19a6fc2060b6e/uuid_utils-0.17.0-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:cee808b405e9095506f4e4e89924bec7ea77eac3129b6fe36eda04364b3b343b", size = 606577, upload-time = "2026-07-09T13:48:02.539Z" }, + { url = "https://files.pythonhosted.org/packages/3b/63/9e48512bb235e9533adbb25c30fd0c9cef09f6ecefe131ba392b98572b40/uuid_utils-0.17.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:53ce348ef4c6e98c02c19c522af01334fe94476ce9af0db8c4482f9f142ae9c1", size = 567054, upload-time = "2026-07-09T13:48:03.833Z" }, + { url = "https://files.pythonhosted.org/packages/b2/cc/d7bad8799a37ec33fc21b29fcb459d63d9f88aa09056d0c3e58903ba2fb0/uuid_utils-0.17.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:9e753e81457241e2200c56a898e268e8fa25796271af0489c608f24d8e631eed", size = 529682, upload-time = "2026-07-09T13:48:05.097Z" }, + { url = "https://files.pythonhosted.org/packages/4a/3b/59b1e07ada8aadd3c046c97fe9814d85e770abb7e8cf68d5d86538bf62e9/uuid_utils-0.17.0-cp310-cp310-win32.whl", hash = "sha256:c589f5023d471ce75dd2cce61acb25ed6347e562041588a1a366808f22d7176c", size = 170595, upload-time = "2026-07-09T13:48:06.411Z" }, + { url = "https://files.pythonhosted.org/packages/8b/5c/23a2d0253ada2ee8c497d541d4ef0dd5576c3d2454ec2f9d0b8a06af9304/uuid_utils-0.17.0-cp310-cp310-win_amd64.whl", hash = "sha256:981cc10163988defea96e8d6c507df151eab8f483e7df9ae543d5a41a4be073b", size = 177225, upload-time = "2026-07-09T13:48:07.561Z" }, + { url = "https://files.pythonhosted.org/packages/d7/b2/8f03b61f0aa4afc687855c4f00db35f4d3e58c480cd885abc46f6e41308f/uuid_utils-0.17.0-cp311-cp311-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:f9b093cb3b6c9d6233ef45a05cab064d2aa0a8cb3c5777084c9e20fcb77c2371", size = 563901, upload-time = "2026-07-09T13:48:08.961Z" }, + { url = "https://files.pythonhosted.org/packages/e3/cb/88b909ffb9ac11f88d2e6ceabc592ccc660b5830b06dbcbd290ab8981f1f/uuid_utils-0.17.0-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:0bc4c431ccd59c764080ceb43b126043325fe17861b87759d026a0cdd8423bb2", size = 286383, upload-time = "2026-07-09T13:48:10.2Z" }, + { url = "https://files.pythonhosted.org/packages/a3/b8/bc5b64e9898867227c535cd0366c571c580a736748e81329437c1773e442/uuid_utils-0.17.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c00d182e31034250690f417b9068b78eab423c10d76766664e82d9860c340479", size = 323244, upload-time = "2026-07-09T13:48:11.477Z" }, + { url = "https://files.pythonhosted.org/packages/13/d9/8a17462ce066fbf89670fb737a3f0c93a77816736d2a4d134787e759d8ea/uuid_utils-0.17.0-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:570db214f6d8507587a8faa968a3fe65e957daeb7bc48b27dc7f69bc3ecdd6f1", size = 330466, upload-time = "2026-07-09T13:48:13.092Z" }, + { url = "https://files.pythonhosted.org/packages/43/37/0c65d0db3bae45183419756d938f1791a82c835fd92bf234eb4f008d2e02/uuid_utils-0.17.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:351462debd866f1f25e4d4f5c7fac89525b52151f0102a1bdfe94a999b046f5f", size = 443806, upload-time = "2026-07-09T13:48:14.372Z" }, + { url = "https://files.pythonhosted.org/packages/32/d5/7e698466d1f5254620b5ee0d711fdd20a0e9c2acd7040740c37193a8f673/uuid_utils-0.17.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:622cdde768300591ac79bfcd7bb3468e4b191b1105d5dbfe8d87c39d8f63dd46", size = 324261, upload-time = "2026-07-09T13:48:15.642Z" }, + { url = "https://files.pythonhosted.org/packages/5d/48/3a5b242d7f0b8e3ca77dcd7177f3cf73e0280cee32e2349d9796ca27f183/uuid_utils-0.17.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:75d7411e8eb9259764dd60310738540649057cda4509b4af14b36b7f663bfeb0", size = 350657, upload-time = "2026-07-09T13:48:17.273Z" }, + { url = "https://files.pythonhosted.org/packages/95/f4/f32ea82a89efed2eafee2f1d925d64687a81e550a9951933fb1b75c95ca6/uuid_utils-0.17.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:1019476b6bdc047216ef7414be5babe0fa5ccfde977c0cac4fd6c75ddec66ff7", size = 500613, upload-time = "2026-07-09T13:48:18.459Z" }, + { url = "https://files.pythonhosted.org/packages/f4/5c/c7b73ec4bbe28db162a4841d352c6eda582801e0dd9fe72f6ad5cc584ee4/uuid_utils-0.17.0-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:04452640d8b6920c480c16e5afe91ff896d236e0c972830f9247e0898d38c803", size = 606306, upload-time = "2026-07-09T13:48:19.726Z" }, + { url = "https://files.pythonhosted.org/packages/63/95/8a2777204e8691b4961e6aa619001c3e5175aa430ab43da3079142e8d310/uuid_utils-0.17.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:793229621e1ad6cac55f015cfa9f4eff102accbc3da25d607b91c6b0bec167fb", size = 567231, upload-time = "2026-07-09T13:48:21.024Z" }, + { url = "https://files.pythonhosted.org/packages/1a/6f/1d778ca3ed6d2cf35f22088e2de714675416747ab41be510f22c141043a7/uuid_utils-0.17.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:03815cea572c8a693cab5475b9d750cc161470961c7defa27e9286cad62f38f5", size = 529373, upload-time = "2026-07-09T13:48:22.312Z" }, + { url = "https://files.pythonhosted.org/packages/6e/d3/9ad1ab64b3bed0a0237d1db89dc6f5001d6116a82766753da4ac4496f979/uuid_utils-0.17.0-cp311-cp311-win32.whl", hash = "sha256:c4f845166b09acc65c5213a35551a7f81c17fa010ab467229b5813f79d17fe13", size = 169930, upload-time = "2026-07-09T13:48:23.504Z" }, + { url = "https://files.pythonhosted.org/packages/c2/1a/e01417f52eae6e2cb412260bb332b4ee4b37af2982d9c38cff4b68b2e899/uuid_utils-0.17.0-cp311-cp311-win_amd64.whl", hash = "sha256:14dc2f46abb1091260c0d203fcbdf4e045042cc07e49183fd3b255904b95eb70", size = 177242, upload-time = "2026-07-09T13:48:24.723Z" }, + { url = "https://files.pythonhosted.org/packages/35/20/396c27f996add19f8ac31e49cc4570824e51a97719087dabf94694d25bc4/uuid_utils-0.17.0-cp311-cp311-win_arm64.whl", hash = "sha256:29179ffb7b317239b6d6afb100d14c439c728770460718280b9c0a42d2561ec2", size = 177023, upload-time = "2026-07-09T13:48:25.834Z" }, + { url = "https://files.pythonhosted.org/packages/20/80/a7e685968e3cec99d6fe2fb25d0f5726310e1bba356da68c13dfd8b7d140/uuid_utils-0.17.0-cp312-cp312-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:9205068badf453d2f0821fd5d340389b4679992d7ff79d4f3e5608996dd1b287", size = 556403, upload-time = "2026-07-09T13:48:27.022Z" }, + { url = "https://files.pythonhosted.org/packages/56/47/3102d93bcb7b0bfe6bede63ff8f221a7f91348e10a37f682773be27c56d9/uuid_utils-0.17.0-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:0fcca4e838af9ac9243b3358d7c14afa4dca286a87781124c272d6c4cad9c968", size = 285608, upload-time = "2026-07-09T13:48:28.769Z" }, + { url = "https://files.pythonhosted.org/packages/55/fb/d59695f0f8db065b93c63316eaafa05a22d75a0486978a33736c52c646d5/uuid_utils-0.17.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0f3729e839209f3457d0d8b6a35a376fdf65577a5aecaf4cc3587d3305759ba6", size = 319926, upload-time = "2026-07-09T13:48:29.965Z" }, + { url = "https://files.pythonhosted.org/packages/5a/03/62fabcd1e990e07a0e220e8d552af45bc16f107fa8e55c2014a706bb1a1e/uuid_utils-0.17.0-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:3dac0ad0cd9a2818d1775215365a4e8c2f8ada215529dd26f3f8cceeb67a6988", size = 327172, upload-time = "2026-07-09T13:48:31.187Z" }, + { url = "https://files.pythonhosted.org/packages/d9/37/a5081391338b459e2f8d8b12581f00f8caa6317fab510e0e85c18c59e938/uuid_utils-0.17.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e671b2322ef09106ecb1ca0f4c398b134d5e2c1f80d7a4f3336847a3072c0e94", size = 439075, upload-time = "2026-07-09T13:48:32.295Z" }, + { url = "https://files.pythonhosted.org/packages/59/30/91795bd01e17a13661280d4899fbf38fb05e3f38e873f9aaec106ec30aa0/uuid_utils-0.17.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8eb3e5caca8d3a6f72ea4cce024583f989f6f2e9186f98800213fff0176e8bcc", size = 320247, upload-time = "2026-07-09T13:48:33.64Z" }, + { url = "https://files.pythonhosted.org/packages/e5/11/09102b78303e4eb62069d6d88ef9fd661dc523e8f429e1fd67eaa78a6f44/uuid_utils-0.17.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:8b72c2002202038666bf647f9a790906214c7c11cd0d6efef77b7d07bef3034a", size = 344738, upload-time = "2026-07-09T13:48:34.786Z" }, + { url = "https://files.pythonhosted.org/packages/74/f9/be95bad6954b60328878c3800258f01a6accd24fd75112d13f023462d53f/uuid_utils-0.17.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:4e2ac1c0b56f2c91b6f158e29ed96b1503223fe8aa6e79b1be1dc55bd8a5131c", size = 496845, upload-time = "2026-07-09T13:48:36.057Z" }, + { url = "https://files.pythonhosted.org/packages/2d/02/8a19a34e0530d987488a068a71576a236f5c8c746630b870b57f71eb24ef/uuid_utils-0.17.0-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:6c142bd0cb4dba31c10babe00d59f7ef6460f0ef55eaa9c1a9da270684af996a", size = 603233, upload-time = "2026-07-09T13:48:37.512Z" }, + { url = "https://files.pythonhosted.org/packages/f4/a8/b1abab36ff73b0248d82179816467f6d39a2e80fd64329a895ca94f3508e/uuid_utils-0.17.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:e252db239eb41c32248e096e0d170bce5896a4fd3405556362bc3dd83d912206", size = 561401, upload-time = "2026-07-09T13:48:38.977Z" }, + { url = "https://files.pythonhosted.org/packages/61/91/70e7b528b351cc03a9ca43e6116371cdde31bb12bcead7ca2ca1367366cc/uuid_utils-0.17.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:237722b6581bb5b4eb4cefbcbe5c6e2980a440aabe781fbe50ebf1cb71eee4cc", size = 525314, upload-time = "2026-07-09T13:48:40.599Z" }, + { url = "https://files.pythonhosted.org/packages/d6/f6/9167e90cf9937d6558f92d022ff3024a69d938a514d9c8faa4080f73b001/uuid_utils-0.17.0-cp312-cp312-win32.whl", hash = "sha256:46a73cacdf512f473a81f65dbf84186e08cfe6e9118fa582b6c6b33a8288a30d", size = 166831, upload-time = "2026-07-09T13:48:41.862Z" }, + { url = "https://files.pythonhosted.org/packages/5c/7d/0b889654d9ee3413f810cf4685e241285f650d98a4103ac9f3c6bcc95f29/uuid_utils-0.17.0-cp312-cp312-win_amd64.whl", hash = "sha256:e59b60a0a4cb7541480e02090d37dc2df3b72df4c2e776fff64ce3a4e3dd4637", size = 172944, upload-time = "2026-07-09T13:48:42.992Z" }, + { url = "https://files.pythonhosted.org/packages/be/35/8c6e1bf65e4d400352885dadc656ad6d0af96e89231e3f04686bc2197128/uuid_utils-0.17.0-cp312-cp312-win_arm64.whl", hash = "sha256:d561a4c5747a1e6c7fa7c49a0292e78b4e8c456332caa084fc7abad8de828652", size = 172459, upload-time = "2026-07-09T13:48:44.271Z" }, + { url = "https://files.pythonhosted.org/packages/d2/dd/614fb9912157ac0128e6050859ccf06d9f13df9a944a803e8f80f6157e38/uuid_utils-0.17.0-cp313-cp313-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:d11a7bc1e02da8984d32e6de9e0826c6edac00eac17de270f372bf32f9a0af63", size = 557259, upload-time = "2026-07-09T13:48:45.664Z" }, + { url = "https://files.pythonhosted.org/packages/3e/11/d072711704de3d21bec08b6c2f36a215200ca1d5e01a390ea1ac434080a0/uuid_utils-0.17.0-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:7a49f47ac26df3e431c56b825c1bae8e6d3d591fdbb7438c227cc9845a7e3d73", size = 286271, upload-time = "2026-07-09T13:48:47.018Z" }, + { url = "https://files.pythonhosted.org/packages/18/6d/8a63e5eb2d5a6ba69a6c2036e305075bd6f5a022e7ea25fc6ce0eb7c51d2/uuid_utils-0.17.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:32df1944808877702ceea398c103881c09a679bb672a215e01c2a84231266bf9", size = 320025, upload-time = "2026-07-09T13:48:48.208Z" }, + { url = "https://files.pythonhosted.org/packages/f7/2d/bdc2caf9719d9090d7c46043242ae6136cba4f7a7ee384992ab905ad9aa1/uuid_utils-0.17.0-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:98c88d3edd08e7245562e9815996dbc6f0bd4745e1c76462f24af5ae4e187dd1", size = 327931, upload-time = "2026-07-09T13:48:49.673Z" }, + { url = "https://files.pythonhosted.org/packages/b6/33/9219d09d51ead282b578b2a4e0a515c2cce3ec52076cada8bfb7e35727d5/uuid_utils-0.17.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5a4370089c8b2e42f1db51d76408c7fa8eaa2934bf854d17983d16179c07c098", size = 438537, upload-time = "2026-07-09T13:48:50.842Z" }, + { url = "https://files.pythonhosted.org/packages/d8/79/e8e0f8b3955f2081c116157119d87659937893242eb834aa170da04d660b/uuid_utils-0.17.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:09a55b7a5ae764985cb46467496a1787678d0a1400356157a080ad95b1a36869", size = 320656, upload-time = "2026-07-09T13:48:52.164Z" }, + { url = "https://files.pythonhosted.org/packages/d5/5e/d1ceddc430ff04b6e21704b2030d4438074a2f478b265dab43da957791c1/uuid_utils-0.17.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:56aa6488b931246fae11924e4bd0e2b32677e63945eecb71c29e3c2ca0dc3131", size = 345310, upload-time = "2026-07-09T13:48:54.076Z" }, + { url = "https://files.pythonhosted.org/packages/d5/62/89438e12f389a843e626b7e37691319a057b3d6b80914609106891faadda/uuid_utils-0.17.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:309a35f12d99dde19032bc2259cda6431c85eeac0879134dc777cc3087d7e1cb", size = 496771, upload-time = "2026-07-09T13:48:55.365Z" }, + { url = "https://files.pythonhosted.org/packages/87/d2/eedcd99f522d60e238ead03844f0d51743ba84d33044959e230b756bf212/uuid_utils-0.17.0-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:21c79b61ff750abcf057163dd764ccb6196cde7a26cda1b31b45cd97769e03b3", size = 603631, upload-time = "2026-07-09T13:48:56.746Z" }, + { url = "https://files.pythonhosted.org/packages/0e/a8/bb1b38aaddd7243b6e562c6694f499bf094800918316192fd8cb2cdc2620/uuid_utils-0.17.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:4134353bfe3026ddab8e886002dc52bc5a0ab04611aabb0eaae23c32e6e57f64", size = 562008, upload-time = "2026-07-09T13:48:58.241Z" }, + { url = "https://files.pythonhosted.org/packages/b4/77/5f7ed930dc105e293845c09e4d5bd84076318a12f45a46783e1af64906d7/uuid_utils-0.17.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:7c89359affecebe2e39e6a116d069b363c936511a9572b308402489a26957d89", size = 525527, upload-time = "2026-07-09T13:48:59.784Z" }, + { url = "https://files.pythonhosted.org/packages/fd/25/1b55697adf6811a6f92cff6340e6b03e31fd6bc51066a5c10698c29b3679/uuid_utils-0.17.0-cp313-cp313-pyemscripten_2025_0_wasm32.whl", hash = "sha256:6a019a31bc4db89a0903a3e4f6b218571f3a6ff0ad4b3d3fe1c8f91a05ff6e3e", size = 97965, upload-time = "2026-07-09T13:49:01.217Z" }, + { url = "https://files.pythonhosted.org/packages/26/bf/cd729343de4684230be8a966bad7bfc2cf10ce3e643b1189a8b5370dbe35/uuid_utils-0.17.0-cp313-cp313-win32.whl", hash = "sha256:b3131a82d0c7611f0aa480a6d36929e001a3f54ba0fc029a8118a5863cce513c", size = 167316, upload-time = "2026-07-09T13:49:02.354Z" }, + { url = "https://files.pythonhosted.org/packages/76/f0/e602ae0a1b139a7826e5189b93d91902564def06d5006324fd2faf82c8fc/uuid_utils-0.17.0-cp313-cp313-win_amd64.whl", hash = "sha256:9e311f908d2f842fca4c7dcebc4f10306b8089b204ef04cf6704b4332c9ff6ff", size = 173630, upload-time = "2026-07-09T13:49:03.529Z" }, + { url = "https://files.pythonhosted.org/packages/1a/52/024ebece265b387154115dc4f1d9727174ef82623069f4bec8b7ed7e73f7/uuid_utils-0.17.0-cp313-cp313-win_arm64.whl", hash = "sha256:c351737e2e65497c7200ab4ffb8af97e9f48be6488309abdd265fe08d66ee92f", size = 173214, upload-time = "2026-07-09T13:49:04.836Z" }, + { url = "https://files.pythonhosted.org/packages/56/44/e2fd3fdf356e1b55d2acf1b956b4f3f29ffb215a99c387eba04b1c5fba66/uuid_utils-0.17.0-cp314-cp314-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:673d89cc434cc9b97a0b4cf61272f6fca70a81f64eb0afbface2a0d9f77f06cd", size = 562232, upload-time = "2026-07-09T13:49:06.201Z" }, + { url = "https://files.pythonhosted.org/packages/19/28/65e0980d668a6d44e699f59d1acf43d6b5d4893592c115ce7c680bb4dfa1/uuid_utils-0.17.0-cp314-cp314-macosx_10_12_x86_64.whl", hash = "sha256:387cf7437c94ddec08651a0f1081381299c7075bc48a6251d8922bf39973378a", size = 287858, upload-time = "2026-07-09T13:49:07.45Z" }, + { url = "https://files.pythonhosted.org/packages/8f/8d/5e97bcebc90fb6a10f98af3dc1ba552e04183aba59e2edc0b9cf486dd998/uuid_utils-0.17.0-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:220b52746d99e11964badac3c0869016e0c24bafb70a7dd5c2c072a6be3da9cc", size = 321587, upload-time = "2026-07-09T13:49:09.489Z" }, + { url = "https://files.pythonhosted.org/packages/8b/d7/88b2a2370cc3d455ba0515fb6f5c8f7ac0c0f55a86801b6e56a432f22c17/uuid_utils-0.17.0-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:0ab4a66e7a035ad6625cfc1fbdb34f5c2d25a80ae1ef4bfee458ea2036333c6d", size = 328964, upload-time = "2026-07-09T13:49:11.292Z" }, + { url = "https://files.pythonhosted.org/packages/bd/0f/181c5da673953dfc0958cb4fb3a4984a9098673ddb05cac68e994bc8511b/uuid_utils-0.17.0-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5641071337eb11d61a001ea08793bf72216f3241f0a433ed2764804b2a3e3cc7", size = 442909, upload-time = "2026-07-09T13:49:12.644Z" }, + { url = "https://files.pythonhosted.org/packages/ec/38/5c5e665af542884a8fd3c61725c38453239e13940326b5b70f3ef8881a97/uuid_utils-0.17.0-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9082e709014946b1f6e96ae6ecd93652efca2d2a6a3ab67dbe151c8b4bf193a4", size = 323076, upload-time = "2026-07-09T13:49:13.897Z" }, + { url = "https://files.pythonhosted.org/packages/f5/35/7de97de18cbf226c2a4f2104ad15e56ca4491717c81c0b71795c0c585b4e/uuid_utils-0.17.0-cp314-cp314-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:1fd6f0e8a162dc0e9255b6aebe3cd175e76c33202f1bf39da9e6294b93db0099", size = 347360, upload-time = "2026-07-09T13:49:15.237Z" }, + { url = "https://files.pythonhosted.org/packages/26/a1/9915d5dd59fdd1957ded5d188c0ea0b9db5a1d84d42c8d8828a7b83b366e/uuid_utils-0.17.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:d63010803d7c368963bbe6f7ec379593e76dd581d7db0f29118d88713c9e0354", size = 499267, upload-time = "2026-07-09T13:49:16.774Z" }, + { url = "https://files.pythonhosted.org/packages/c0/05/88108405262ec850cea0f95733445d6873e5772af3292baabd9ef8457740/uuid_utils-0.17.0-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:a46bedc273b6f58f11dee816ff74999625ef8d007890f411b7a4975bf1c89330", size = 604940, upload-time = "2026-07-09T13:49:18.147Z" }, + { url = "https://files.pythonhosted.org/packages/89/d5/6dbcd300de47cc443cff2656cd5327a385751213dcb2101cfee7388170b2/uuid_utils-0.17.0-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:405233a5f625b3d995648f4647fa6befa4567cf3f74e1f6b9837e16f7310f0e0", size = 564172, upload-time = "2026-07-09T13:49:19.593Z" }, + { url = "https://files.pythonhosted.org/packages/ab/94/e8057f2288a415fba8a978bca4b589f5cb6b91a028a5dc07a1775938b33f/uuid_utils-0.17.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:b6c5d2d71e1f17329150ad9427d27f4a3f29a01792e7ecdc64a98ac5368fc4d5", size = 528533, upload-time = "2026-07-09T13:49:21.075Z" }, + { url = "https://files.pythonhosted.org/packages/f0/6b/31713148c77e48e62f51aa042a98a54a8be0396912ea5130f83f52ae722d/uuid_utils-0.17.0-cp314-cp314-pyemscripten_2026_0_wasm32.whl", hash = "sha256:f7e9b8728ba07a3cb2f29d5aa1a266c2664eb8ef0fd43afa34627c92f7fac8f0", size = 99197, upload-time = "2026-07-09T13:49:22.351Z" }, + { url = "https://files.pythonhosted.org/packages/f3/f3/ca6f6ac5428312df8ed632f6dd9f9e6aba23090471fcdeae53eab027e8b3/uuid_utils-0.17.0-cp314-cp314-win32.whl", hash = "sha256:58838921e377791ef22c64cc92141bfae030f43651ff9272f0f28a208a9e6a5a", size = 169540, upload-time = "2026-07-09T13:49:23.563Z" }, + { url = "https://files.pythonhosted.org/packages/c6/cd/7ede0db66411fa09817d79b680f7454ea9bee2d374e1922e4efd065760a3/uuid_utils-0.17.0-cp314-cp314-win_amd64.whl", hash = "sha256:42275ebd0e8e74e32cdbfb8bd88fc99576567d51d54a508020611fd8f4f463a0", size = 175984, upload-time = "2026-07-09T13:49:24.703Z" }, + { url = "https://files.pythonhosted.org/packages/f0/81/533b5f80cd4918c0693f4e1b7b90ceb1caa45f4266ae8b528135d7ecca5d/uuid_utils-0.17.0-cp314-cp314-win_arm64.whl", hash = "sha256:b5d11cccba076a32321ef1380dea956821f0b51794ef59df64e58fb1cd543aae", size = 174749, upload-time = "2026-07-09T13:49:25.886Z" }, + { url = "https://files.pythonhosted.org/packages/a0/13/f400ac39d06fd8be5b099c09e41bb975205926722a3e8d53348817cb7ff9/uuid_utils-0.17.0-cp314-cp314t-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:fae8b282f0cb22a5de222999f7723f4e5ec04f6fcdf4aaef879b5b36625ae2b0", size = 562610, upload-time = "2026-07-09T13:49:27.374Z" }, + { url = "https://files.pythonhosted.org/packages/03/8c/c71c8312304c56f6d0bcba87cd402fa79bec35d18ffc8c41954196ca68e5/uuid_utils-0.17.0-cp314-cp314t-macosx_10_12_x86_64.whl", hash = "sha256:967955620df45e6cffe2e9950cb9903cb455649396f896b26b04363a91a5054b", size = 289473, upload-time = "2026-07-09T13:49:28.989Z" }, + { url = "https://files.pythonhosted.org/packages/bb/cd/522117e2e5184ca1d4f0f85ee833e9e21bd8c6b99eff8a4d1a8e5a194e33/uuid_utils-0.17.0-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:375cde148430d60a4a07c03abaa0774c4fddfdd90de99b4ba02f24088bc9d750", size = 321600, upload-time = "2026-07-09T13:49:30.4Z" }, + { url = "https://files.pythonhosted.org/packages/6d/f4/0d81f9bd346fc717bc561c08fa6457e0328966eb76e536b938fe77d56459/uuid_utils-0.17.0-cp314-cp314t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:975c17da26c5b9d46c336b03c52a057ac28378d6f9d98b58d32a038589bb3912", size = 329569, upload-time = "2026-07-09T13:49:31.732Z" }, + { url = "https://files.pythonhosted.org/packages/5e/41/26e1363f36a94c9e8ec2dd21d5f63088d3e7c723adbb12dcc8fdc77be417/uuid_utils-0.17.0-cp314-cp314t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3150d836290c88f1d26eb59c4db280d87417dd3bfaadd2889c77416c8f0ff6fa", size = 442051, upload-time = "2026-07-09T13:49:33.024Z" }, + { url = "https://files.pythonhosted.org/packages/2b/a7/2c1ed1b34d7df7fdcc11c28fd26d94d44843b37d9af2435ff9fd8abdbc08/uuid_utils-0.17.0-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9472a8de37faf8bd216c628e0e68c8f6bef730d3ba0a5060f3b0fa460c992ac2", size = 324372, upload-time = "2026-07-09T13:49:34.554Z" }, + { url = "https://files.pythonhosted.org/packages/78/bf/328d3c6bb22c496944a1b3b732207d71aa6964eb604e5e3b9dcb91ed0a00/uuid_utils-0.17.0-cp314-cp314t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d27c531edb8d1f38ca2eddaa1fa24913a460aeb721f2efd4ef42a124ce94e354", size = 348548, upload-time = "2026-07-09T13:49:35.898Z" }, + { url = "https://files.pythonhosted.org/packages/3e/76/a07de5cb7b90582fdbbc830fd19be129cbbb9897cfe239fef469d7bd2d09/uuid_utils-0.17.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:5670c52a438e21483ce715776144914a4e2a2a5c62d9dee15f8a3e90cf128ae6", size = 498985, upload-time = "2026-07-09T13:49:37.142Z" }, + { url = "https://files.pythonhosted.org/packages/f4/62/9966e46ae34fcec6b06119631fb3c09705ea78835035ce3a82d3348eb61a/uuid_utils-0.17.0-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:6f29689a76fe7a49cbd629a794d0ec1eab48814e323a00a146a741b0195bde68", size = 605183, upload-time = "2026-07-09T13:49:38.648Z" }, + { url = "https://files.pythonhosted.org/packages/d7/4e/bb962ba0fe31e903b199f22cf4c1a6cba35a8987aef526d287277ab8ca8b/uuid_utils-0.17.0-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:4441600447d340ae103a353f01dbcd22ff680e5ee1a22988efe8d7b791d8fdb3", size = 565412, upload-time = "2026-07-09T13:49:40.115Z" }, + { url = "https://files.pythonhosted.org/packages/ce/9e/122adfeeeae8a84ccfd43bce627b104d12a2180a93bffd2c0e1b54dad7a6/uuid_utils-0.17.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:e7b04935a79c03c41ad08d0a5f390aac968bfb561f1268897bc5b0f077971efd", size = 529885, upload-time = "2026-07-09T13:49:41.513Z" }, + { url = "https://files.pythonhosted.org/packages/b3/4f/257304dded339dc35fc9bf35722ac68fd4fdb930f255b8f7bccdf74ebba9/uuid_utils-0.17.0-cp314-cp314t-win32.whl", hash = "sha256:239d8a281fe10bae33205b5d43185834d556b18434e0a113b5dc1dfb2fd97e91", size = 169472, upload-time = "2026-07-09T13:49:42.871Z" }, + { url = "https://files.pythonhosted.org/packages/35/c8/e78c06db7e9ce317ce7b8759ff2058333eac75caa8c22b75f0059589c9be/uuid_utils-0.17.0-cp314-cp314t-win_amd64.whl", hash = "sha256:e288a06cbbbcd01b44386e767985c9e21d2ad9bf59829aa7058d9a2a494804ab", size = 176271, upload-time = "2026-07-09T13:49:44.105Z" }, + { url = "https://files.pythonhosted.org/packages/a7/11/bd1c70e1ad3301163cebe66c8d26de26e6814d52f642a849448bd2833626/uuid_utils-0.17.0-cp314-cp314t-win_arm64.whl", hash = "sha256:1776a80d16369999b21627028cc5dbce819be83e1e079fdd7a51b587d2916db9", size = 175004, upload-time = "2026-07-09T13:49:45.591Z" }, + { url = "https://files.pythonhosted.org/packages/ee/14/4ae708968b15cac7b68d5b854bfce724b21faa1c7a5147fb96d87f468a45/uuid_utils-0.17.0-pp311-pypy311_pp73-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:7b9044ce4acbf392d4b3a503fe377641f4deff82e6c341c36ef27af0dea76cdf", size = 567823, upload-time = "2026-07-09T13:49:46.902Z" }, + { url = "https://files.pythonhosted.org/packages/4c/e2/d3af9c3d1dc6efb9ee1cffab30f3f2aacacc3892b21b495d78d34c6696bc/uuid_utils-0.17.0-pp311-pypy311_pp73-macosx_10_12_x86_64.whl", hash = "sha256:9a91c4814c7150a4d798da691b7804eacd78c4b84fb392a60fa0de21341861eb", size = 288763, upload-time = "2026-07-09T13:49:48.491Z" }, + { url = "https://files.pythonhosted.org/packages/bc/c2/f1b183e412387529893015a94a8447633c665f6d0392de20e245680e636a/uuid_utils-0.17.0-pp311-pypy311_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2dd4a21baaac9a88486f0dd166c5793feb101a0bb9f006f2c401657fff5a1343", size = 324919, upload-time = "2026-07-09T13:49:49.972Z" }, + { url = "https://files.pythonhosted.org/packages/dd/3c/d32c799bdd51f3b08b6ee95f9de921b59c69075a96767f937fab55014813/uuid_utils-0.17.0-pp311-pypy311_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:32abaafc8e91928b3d9f4d82e42d2094041e38ad6bb964066faadff28e4162f1", size = 332689, upload-time = "2026-07-09T13:49:51.402Z" }, + { url = "https://files.pythonhosted.org/packages/6f/90/b4cd455619ff276dc3c3262a7420ead63aa1e531362f00df4cdb07d90e0a/uuid_utils-0.17.0-pp311-pypy311_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:dd741c73440b328f937dc53b344ecadc46bc4f0cec0333a8f42b55f3468ce7ec", size = 445726, upload-time = "2026-07-09T13:49:52.757Z" }, + { url = "https://files.pythonhosted.org/packages/e2/f1/5cc042a37932aa9a66eb8ab4a9a5b31d80261ae4565ff0193d8cc1fb9392/uuid_utils-0.17.0-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:89a0980d49683c00539c59cd9f46b1908c538e6b5b0a48ad12187bb856d0f391", size = 325610, upload-time = "2026-07-09T13:49:54.191Z" }, + { url = "https://files.pythonhosted.org/packages/5e/72/9e800c41d766484484e97845a7a7f677ba94462df86c97183e0290229d16/uuid_utils-0.17.0-pp311-pypy311_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:de1064663aa7c839286488a319d2b3b478ca5ab5b2091ade888ed0eeca11a98a", size = 352672, upload-time = "2026-07-09T13:49:55.748Z" }, + { url = "https://files.pythonhosted.org/packages/9d/8e/86ce2c03a1d9674530f6649e49067f7c69929600127077731de590d12132/uuid_utils-0.17.0-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:2db386941cfdecdd0b5a8ceeed5cf7479c83d1730dcf64a48d43cfa018cc3310", size = 178681, upload-time = "2026-07-09T13:49:57.096Z" }, ] [[package]] name = "uvicorn" -version = "0.49.0" +version = "0.51.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "click" }, { name = "h11" }, { name = "typing-extensions", marker = "python_full_version < '3.11'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/c4/1f/fa18009dea8469069cca78a4e877a008ab78f08b064bfc9ab891579077ff/uvicorn-0.49.0.tar.gz", hash = "sha256:ebf4271aa580d9de97f93192d4595176df6e91f9aae919ca73e4fc07df1e66a3", size = 91284, upload-time = "2026-06-03T22:01:30.448Z" } +sdist = { url = "https://files.pythonhosted.org/packages/a2/65/b7c6c443ccc58678c91e1e973bbe2a878591538655d6e1d47f24ba1c51f3/uvicorn-0.51.0.tar.gz", hash = "sha256:f6f4b69b657c312f516dd2d268ab9ae6f254b11e4bac504f37b2ab58b24dd0b0", size = 94412, upload-time = "2026-07-08T10:59:05.962Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/88/fa/e1388bbcf24ef3274f45c0c1c7b501fd14971037c1b6ee23610553307497/uvicorn-0.49.0-py3-none-any.whl", hash = "sha256:ba3d14c3ee7e41c6c654c46c9eb489d33213cdd30aa1696eab1374337c13f68f", size = 71376, upload-time = "2026-06-03T22:01:29.037Z" }, + { url = "https://files.pythonhosted.org/packages/45/ec/dbb7e5a6b91f86bfb9eb7d2988a2730907b6a729875b949c7f022e8b88fa/uvicorn-0.51.0-py3-none-any.whl", hash = "sha256:5d38af6cd620f2ae3849fb44fd4879e0890aa1febe8d47eb355fb45d93fe6a5b", size = 73219, upload-time = "2026-07-08T10:59:04.44Z" }, ] [[package]] @@ -5336,11 +5258,11 @@ wheels = [ [[package]] name = "wcwidth" -version = "0.8.1" +version = "0.8.2" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/49/b4/51fe890511f0f242d07cb1ebe6a5b6db417262b9d2568b460347c57d95cc/wcwidth-0.8.1.tar.gz", hash = "sha256:faf5b4a5366a72dc49cad48cdf21f52bdf63bdda995178e483ba247ff79089b9", size = 1466072, upload-time = "2026-06-08T05:57:23.146Z" } +sdist = { url = "https://files.pythonhosted.org/packages/34/74/c6428f875774288bec1396f5bfcbc2d925700a4dad61727fd5f2b12f249d/wcwidth-0.8.2.tar.gz", hash = "sha256:91fbef97204b96a3d4d421609b80340b760cf33e26da123ff243d76b1fda8dda", size = 1466253, upload-time = "2026-06-29T18:11:11.601Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/bd/6e/95b0e537de1f4d4301f76f944642c6da50d1511cc7b3d64dc418a66c7509/wcwidth-0.8.1-py3-none-any.whl", hash = "sha256:f453740b1e4a4f3291faa37944c555d71056c4da08d59809b307ef4feba695c8", size = 323092, upload-time = "2026-06-08T05:57:21.413Z" }, + { url = "https://files.pythonhosted.org/packages/96/42/3e5985a0a7e57de470b320c6d6a1a67c844f6737a587f3d44dd13d1819e7/wcwidth-0.8.2-py3-none-any.whl", hash = "sha256:d63947694a0539a1d51e01eda7caf800c291020e6cdd7e28ad7b14dd33ad4f85", size = 323166, upload-time = "2026-06-29T18:11:09.888Z" }, ] [[package]] @@ -5494,159 +5416,159 @@ wheels = [ [[package]] name = "xxhash" -version = "3.7.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/24/2f/e183a1b407002f5af81822bee18b61cdb94b8670208ef34734d8d2b8ebe9/xxhash-3.7.0.tar.gz", hash = "sha256:6cc4eefbb542a5d6ffd6d70ea9c502957c925e800f998c5630ecc809d6702bae", size = 82022, upload-time = "2026-04-25T11:10:32.553Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/92/49/e4b575b4ed170a7f640c8bd69cfadfa81c7b700191fde5e72228762b9f73/xxhash-3.7.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:cd8ab85c916a58d5c8656ea15e3ce9df836fe2f120a74c296e01d69fab2614b4", size = 33426, upload-time = "2026-04-25T11:05:15.702Z" }, - { url = "https://files.pythonhosted.org/packages/07/61/40f0155b0b09988eb6cdbfc52652f2f371810b0c58163208cb05667757bd/xxhash-3.7.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:85f5c0e26d945b5bb475e0a3d95193117498130baa7619357bdc7869c2391b5a", size = 30859, upload-time = "2026-04-25T11:05:17.708Z" }, - { url = "https://files.pythonhosted.org/packages/12/bd/2902b7aad574e43cd85fd84849cfbce48c52cb02c7d6902b8a2b3f6e668e/xxhash-3.7.0-cp310-cp310-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:b7ffeaada9f8699be63d639536b0b60dff73b7d3325b7475c5bc8fdbf4eed47f", size = 193839, upload-time = "2026-04-25T11:05:19.364Z" }, - { url = "https://files.pythonhosted.org/packages/48/df/343ce8fd09e47ba8fba43b3bad3283ddf0deca799d5a27b084c3aa2ce502/xxhash-3.7.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:cee88dfaa6b1b2bfadd3c031fa5f05584870e62fb05dc500942e9900c44fcfda", size = 212896, upload-time = "2026-04-25T11:05:21.131Z" }, - { url = "https://files.pythonhosted.org/packages/79/cf/703e8422a8b52407864281fb4eb52c605e9f33180413b4458f05de110eba/xxhash-3.7.0-cp310-cp310-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:7426ff0dfa76eb47efc2cc59d4a717bfa9dc9938bff5e49e748bca749f6aa616", size = 235896, upload-time = "2026-04-25T11:05:22.988Z" }, - { url = "https://files.pythonhosted.org/packages/ed/bc/d4b039edbd426575add5f217abeeb2bf870e2c510d35445df81b4f457901/xxhash-3.7.0-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:e8ff6ec73110f610425caef3ea875afbfc34caa542f01df3a80f45aadeb9f906", size = 211665, upload-time = "2026-04-25T11:05:24.799Z" }, - { url = "https://files.pythonhosted.org/packages/42/24/c6f81361796814b92399a88bf079d3b65e617f531819128fcf1bd6ef0571/xxhash-3.7.0-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:0d23fd49fdc5c8af61fb7104f1ad247954499140f6cb6045b3aa5c99dadbbf28", size = 444929, upload-time = "2026-04-25T11:05:26.245Z" }, - { url = "https://files.pythonhosted.org/packages/a4/db/268012153eb7f6bf2c8a0491fdcde11e093f166990821a2ab754fe95537d/xxhash-3.7.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:12c249621af6d50a05d9f10af894b404157b15819878e18f75fcbb0213a77d07", size = 193271, upload-time = "2026-04-25T11:05:28.282Z" }, - { url = "https://files.pythonhosted.org/packages/0a/86/1d0d905d659850dad7f59c807c130249fdb204dc6f71f1fb36268f3f3e61/xxhash-3.7.0-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:6741564a923f082f3c2941c8bb920462ed5b25eaebdd1e161f162233c9a10bc5", size = 284580, upload-time = "2026-04-25T11:05:30.116Z" }, - { url = "https://files.pythonhosted.org/packages/1f/52/fc01ca7ff425a9bdb38d9e3a17f2630447ce3b45d45a929a6cd94d469334/xxhash-3.7.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:c4fd8acc6e32596350619896feb372033c0920975992d29837c32853bb1feacd", size = 210193, upload-time = "2026-04-25T11:05:31.969Z" }, - { url = "https://files.pythonhosted.org/packages/ec/96/122e0c6a3537a54b30752031dca557182576bae1a4171c0be8c532c84496/xxhash-3.7.0-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:646a69b56d8145d85f7fd2289d14fba07880c8a5bda406aa256b407481a61f35", size = 241094, upload-time = "2026-04-25T11:05:33.651Z" }, - { url = "https://files.pythonhosted.org/packages/d8/17/92e33338db8c18add33a46b56c2b7d5dcc6cc2ac076c45389f6017b1bf37/xxhash-3.7.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:11dd69b1a34b7b9af29012f390825b0cdb0617c0966560e227ca74daa7478ba9", size = 197721, upload-time = "2026-04-25T11:05:35.387Z" }, - { url = "https://files.pythonhosted.org/packages/c7/04/fd4114a0820913f336bef5c82ef851bde8d06270982ebd7b2a859961bbf2/xxhash-3.7.0-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:01cf5c5333aed26cc8d5eea33b8d6398e085e365a704b7372fabdf7ab06441a9", size = 210073, upload-time = "2026-04-25T11:05:37.405Z" }, - { url = "https://files.pythonhosted.org/packages/dd/eb/a2472b8b81cd576a9af3a4889ad8ba5784e8c5a04592587056cdaededd6c/xxhash-3.7.0-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:f1e65d52c2d526734abecb98372c256b7eacce8fdc42e0df8570417fb39e2772", size = 274960, upload-time = "2026-04-25T11:05:39.224Z" }, - { url = "https://files.pythonhosted.org/packages/3d/d3/493afc544aae50b5fb2844ceaeb3697283bb59695db1a7cb40448636de05/xxhash-3.7.0-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:8ff00fcc3eb436617ed8556cf15daf76c2b501248361a065625a588af78a0a02", size = 413113, upload-time = "2026-04-25T11:05:40.669Z" }, - { url = "https://files.pythonhosted.org/packages/50/6a/002800845a22bff32bcf5fd09caceb4d3f5c3da6b754c46edb9743ce908b/xxhash-3.7.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:b5cd29840505631c6f7dbb8a5d34b742b5e6bbda38fe0b9f54e825f3ea6b61dc", size = 190677, upload-time = "2026-04-25T11:05:42.403Z" }, - { url = "https://files.pythonhosted.org/packages/f4/0f/86ee514622a381c0dc49167c8d431a22aa93518a4063559c3e36e4b82bc8/xxhash-3.7.0-cp310-cp310-win32.whl", hash = "sha256:5bf2f1940499839b39fef1561b5ecb6ede9ac34ef4457474e1337fc7ef07c2f3", size = 30627, upload-time = "2026-04-25T11:05:44.022Z" }, - { url = "https://files.pythonhosted.org/packages/86/45/2ef2310803efb4a2d07844e8098d797e25702024793aa2e85858623a43b5/xxhash-3.7.0-cp310-cp310-win_amd64.whl", hash = "sha256:d41fcda2fa8ca682ebca134a2f2dc02575ba549267585597e73061565795f475", size = 31463, upload-time = "2026-04-25T11:05:45.218Z" }, - { url = "https://files.pythonhosted.org/packages/9e/75/40dbf8f142baf8993c38cd988c8d8f51fe0c51e6c84c5769a3c0280a651d/xxhash-3.7.0-cp310-cp310-win_arm64.whl", hash = "sha256:a845a59664d5c531525a467470220f8edc37959e0a6f8e734ffb6654da5c4bee", size = 27747, upload-time = "2026-04-25T11:05:46.422Z" }, - { url = "https://files.pythonhosted.org/packages/3b/f4/7bd35089ff1f8e2c96baa2dce05775a122aacd2e3830a73165e27a4d0848/xxhash-3.7.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:fdc7d06929ae28dda98297a18eef7b0fd38991a3b405d8d7b55c9ef24c296958", size = 33423, upload-time = "2026-04-25T11:05:47.628Z" }, - { url = "https://files.pythonhosted.org/packages/a3/26/4e00c88a6a2c8a759cfb77d2a9a405f901e8aa66e60ef1fd0aeb35edda48/xxhash-3.7.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:ea6daa712f4e094a30830cf01e9b47d03b24d05cc9dab8609f0d9a9db8454712", size = 30857, upload-time = "2026-04-25T11:05:49.189Z" }, - { url = "https://files.pythonhosted.org/packages/82/2f/eeb942c17a5a761a8f01cb9180a0b76bfb62a2c39e6f46b1f9001899027a/xxhash-3.7.0-cp311-cp311-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:9e6c0d843f1daf85ea23aeb053579135552bde575b7b98af20bfc667b6e4548d", size = 194702, upload-time = "2026-04-25T11:05:50.457Z" }, - { url = "https://files.pythonhosted.org/packages/0e/fd/96f132c08b1e5951c68691d3b9ec351ec2edc028f6a01fcd294f46b9d9f0/xxhash-3.7.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:363c139bf15e1ac5f136b981d3c077eb551299b1effede7f12faa010b8590a60", size = 213613, upload-time = "2026-04-25T11:05:52.571Z" }, - { url = "https://files.pythonhosted.org/packages/82/89/d4e92b796c5ed052d29ed324dbfc1dc1188e0c4bf64bebbf0f8fc20698df/xxhash-3.7.0-cp311-cp311-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:a778b25874cb0f862eaab5986bff4ca49ffb0def7c0a34c237b948b3c6c775b2", size = 236726, upload-time = "2026-04-25T11:05:54.395Z" }, - { url = "https://files.pythonhosted.org/packages/40/f1/81fc4361921dc6e557a9c60cb3712f36d244d06eeeb71cd2f4252ac42678/xxhash-3.7.0-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:3e1860f1e43d40e9d904cf22d93e587ea42e010ebce4160877e46bcab4bc232a", size = 212443, upload-time = "2026-04-25T11:05:56.334Z" }, - { url = "https://files.pythonhosted.org/packages/6a/d0/afeddd4cff50a332f50d4b8a2e8857673153ab0564ef472fcdeb0b5430df/xxhash-3.7.0-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:9122ad6f867c4a0f5e655f5c3bdf89103852009dbb442a3d23e688b9e699e800", size = 445793, upload-time = "2026-04-25T11:05:58.953Z" }, - { url = "https://files.pythonhosted.org/packages/f7/d0/3c91e4e6a05ca4d7df8e39ec3a75b713609258ec84705ab34be6430826a1/xxhash-3.7.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d7d9110d0c3fb02679972837a033251fd186c529aa62f19c132fc909c74052b8", size = 193937, upload-time = "2026-04-25T11:06:00.546Z" }, - { url = "https://files.pythonhosted.org/packages/4e/3a/a6b0772d9801dd4bea4ca4fd34734d6e9b51a711c8a611a24a79de26a878/xxhash-3.7.0-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:347a93f2b4ce67ce61959665e32a7447c380f8347e55e100daa23766baacf0e5", size = 285188, upload-time = "2026-04-25T11:06:01.96Z" }, - { url = "https://files.pythonhosted.org/packages/6c/f8/cf8e31fd7282230fe7367cd501a2e75b4b67b222bfc7eacccfc20d2652cb/xxhash-3.7.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:acbb48679ddf3852c45280c10ff10d52ca2cd1da2e552fb81db1ff786c75d0e4", size = 210966, upload-time = "2026-04-25T11:06:03.453Z" }, - { url = "https://files.pythonhosted.org/packages/cc/f0/fd36cc4a81bf52ee5633275daae2b93dd958aace67fd4f5d466ec83b5f35/xxhash-3.7.0-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:fe14c356f8b23ad811dc026077a6d4abccdaa7bce5ca98579605550657b6fcfb", size = 241994, upload-time = "2026-04-25T11:06:05.264Z" }, - { url = "https://files.pythonhosted.org/packages/08/e1/67f5d9c9369be42eaf99ba02c01bf14c5ecd67087b02567960bfcee43b63/xxhash-3.7.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:f420ad3d41e38194353a498bbc9561fd5a9973a27b536ce46d8583479cf44335", size = 198707, upload-time = "2026-04-25T11:06:07.044Z" }, - { url = "https://files.pythonhosted.org/packages/50/17/a4c865ca22d2da6b1bc7d739bf88cab209533cf52ba06ca9da27c3039bee/xxhash-3.7.0-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:693d02c6dc7d1aa0a45921d54cd8c1ff629e09dfdc2238471507af1f7a1c6f04", size = 210917, upload-time = "2026-04-25T11:06:08.853Z" }, - { url = "https://files.pythonhosted.org/packages/49/8b/453b35810d697abac3c96bde3528bece685869227da274eb80a4a4d4a119/xxhash-3.7.0-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:14bf7a54e43825ec131ee7fe3c60e142e7c2c1e676ad0f93fc893432d15414af", size = 275772, upload-time = "2026-04-25T11:06:10.645Z" }, - { url = "https://files.pythonhosted.org/packages/b5/ad/4eed7eab07fd3ee6678f416190f0413d097ab5d7c1278906bf1e9549d789/xxhash-3.7.0-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:ae3a39a4d96bdb6f8d154fd7f490c4ad06f0532fcd2bb656052a9a7762cf5d31", size = 414068, upload-time = "2026-04-25T11:06:12.511Z" }, - { url = "https://files.pythonhosted.org/packages/d3/4e/fd6f8a680ba248fdb83054fa71a8bfa3891225200de1708b888ef2c49829/xxhash-3.7.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:1cc07c639e3a77ef1d32987464d3e408565b8a3be57b545d3542b191054d9923", size = 191459, upload-time = "2026-04-25T11:06:14.07Z" }, - { url = "https://files.pythonhosted.org/packages/50/7c/8cb34b3bed4f44ca6827a534d50833f9bc6c006e83b0eb410ac9fa0793bd/xxhash-3.7.0-cp311-cp311-win32.whl", hash = "sha256:3281ba1d1e60ee7a382a7b958513ba03c2c0d5fcbd9a6f7517c0a81251a23422", size = 30628, upload-time = "2026-04-25T11:06:15.802Z" }, - { url = "https://files.pythonhosted.org/packages/0b/47/a49767bd7b40782bedae9ff0721bfe1d7e4dd9dc1585dea684e57ba67c20/xxhash-3.7.0-cp311-cp311-win_amd64.whl", hash = "sha256:a7f25baec4c5d851d40718d6fae52285b31683093d4ff5207e63ab306ccf14a5", size = 31461, upload-time = "2026-04-25T11:06:17.104Z" }, - { url = "https://files.pythonhosted.org/packages/7c/c6/3957bfacfb706bd687be246dfa8dd60f8df97c44186d229f7fd6e26c4b7e/xxhash-3.7.0-cp311-cp311-win_arm64.whl", hash = "sha256:4c2454448ce847c72635827bb75c15c5a3434b03ee1afd28cb6dc6fb2597d830", size = 27746, upload-time = "2026-04-25T11:06:18.716Z" }, - { url = "https://files.pythonhosted.org/packages/f2/8a/51a14cdef4728c6c2337db8a7d8704422cc65676d9199d77215464c880af/xxhash-3.7.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:082c87bfdd2b9f457606c7a4a53457f4c4b48b0cdc48de0277f4349d79bb3d7a", size = 33357, upload-time = "2026-04-25T11:06:20.44Z" }, - { url = "https://files.pythonhosted.org/packages/b9/1b/0c2c933809421ffd9bf42b59315552c143c755db5d9a816b2f1ae273e884/xxhash-3.7.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:5e7ce913b61f35b0c1c839a49ac9c8e75dd8d860150688aed353b0ce1bf409d8", size = 30869, upload-time = "2026-04-25T11:06:21.989Z" }, - { url = "https://files.pythonhosted.org/packages/03/a8/89d5fdd6ee12d70ba99451de46dd0e8010167468dcd913ec855653f4dd50/xxhash-3.7.0-cp312-cp312-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:3beb1de3b1e9694fcdd853e570ee64c631c7062435d2f8c69c1adf809bc086f0", size = 194100, upload-time = "2026-04-25T11:06:23.586Z" }, - { url = "https://files.pythonhosted.org/packages/87/ee/2f9f2ed993e77206d1e66991290a1ebe22e843351ca3ebec8e49e01ba186/xxhash-3.7.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f3e7b689c3bce16699efcf736066f5c6cc4472c3840fe4b22bd8279daf4abdac", size = 212977, upload-time = "2026-04-25T11:06:25.019Z" }, - { url = "https://files.pythonhosted.org/packages/de/60/5a91644615a9e9d4e42c2e9925f1908e3a24e4e691d9de7340d565bea024/xxhash-3.7.0-cp312-cp312-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:a6545e6b409e3d5cbafc850fb84c55a1ca26ed15a6b11e3bf07a0e0cd84517c8", size = 236373, upload-time = "2026-04-25T11:06:26.482Z" }, - { url = "https://files.pythonhosted.org/packages/22/c0/f3a9384eaaed9d14d4d062a5d953aa0da489bfe9747877aa994caa87cd0b/xxhash-3.7.0-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:31ab1461c77a11461d703c88eb949e132a1c6515933cf675d97ec680f4bd18de", size = 212229, upload-time = "2026-04-25T11:06:28.065Z" }, - { url = "https://files.pythonhosted.org/packages/2e/67/02f07a9fd79726804190f2172c4894c3ed9a4ebccaca05653c84beb58025/xxhash-3.7.0-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:7c4d596b7676f811172687ec567cbafb9e4dea2f9be1bbb4f622410cb7f40f40", size = 445462, upload-time = "2026-04-25T11:06:30.048Z" }, - { url = "https://files.pythonhosted.org/packages/40/37/558f5a90c0672fc9b4402dc25d87ac5b7406616e8969430c9ca4e52ee74d/xxhash-3.7.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:13805f0461cba0a857924e70ff91ae6d52d2598f79a884e788db80532614a4a1", size = 193932, upload-time = "2026-04-25T11:06:31.857Z" }, - { url = "https://files.pythonhosted.org/packages/d5/90/aaa09cd58661d32044dbbad7df55bbe22a623032b810e7ed3b8c569a2a6f/xxhash-3.7.0-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:1d398f372496152f1c6933a33566373f8d1b37b98b8c9d608fa6edc0976f23b2", size = 284807, upload-time = "2026-04-25T11:06:33.697Z" }, - { url = "https://files.pythonhosted.org/packages/d6/f3/53df3719ab127a02c174f0c1c74924fcd110866e89c966bc7909cfa8fa84/xxhash-3.7.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:d610aa62cdb7d4d497740741772a24a794903bf3e79eaa51d2e800082abe11e5", size = 210445, upload-time = "2026-04-25T11:06:35.488Z" }, - { url = "https://files.pythonhosted.org/packages/72/33/d219975c0e8b6fa2eb9ccd486fe47e21bf1847985b878dd2fbc3126e0d5c/xxhash-3.7.0-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:073c23900a9fbf3d26616c17c830db28af9803677cd5b33aea3224d824111514", size = 241273, upload-time = "2026-04-25T11:06:37.24Z" }, - { url = "https://files.pythonhosted.org/packages/3e/50/49b1afe610eb3964cedcb90a4d4c3d46a261ee8669cbd4f060652619ae3c/xxhash-3.7.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:418a463c3e6a590c0cdc890f8be19adb44a8c8acd175ca5b2a6de77e61d0b386", size = 197950, upload-time = "2026-04-25T11:06:39.148Z" }, - { url = "https://files.pythonhosted.org/packages/c6/75/5f42a1a4c78717d906a4b6a140c6dbf837ab1f547a54d23c4e2903310936/xxhash-3.7.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:03f8ff4474ee61c845758ce00711d7087a770d77efb36f7e74a6e867301000b8", size = 210709, upload-time = "2026-04-25T11:06:40.958Z" }, - { url = "https://files.pythonhosted.org/packages/8a/85/237e446c25abced71e9c53d269f2cef5bab8a82b3f88a12e00c5368e7368/xxhash-3.7.0-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:44fba4a5f1d179b7ddc7b3dc40f56f9209046421679b57025d4d8821b376fd8d", size = 275345, upload-time = "2026-04-25T11:06:42.525Z" }, - { url = "https://files.pythonhosted.org/packages/62/34/c2c26c0a6a9cc739bc2a5f0ae03ba8b87deb12b8bce35f7ac495e790dc6d/xxhash-3.7.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:31e3516a0f829d06ded4a2c0f3c7c5561993256bfa1c493975fb9dc7bfa828a1", size = 414056, upload-time = "2026-04-25T11:06:44.343Z" }, - { url = "https://files.pythonhosted.org/packages/a0/aa/5c58e9bc8071b8afd8dcf297ff362f723c4892168faba149f19904132bf4/xxhash-3.7.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:b59ee2ac81de57771a09ecad09191e840a1d2fae1ef684208320591055768f83", size = 191485, upload-time = "2026-04-25T11:06:46.262Z" }, - { url = "https://files.pythonhosted.org/packages/d4/69/a929cf9d1e2e65a48b818cdce72cb6b69eab2e6877f21436d0a1942aff43/xxhash-3.7.0-cp312-cp312-win32.whl", hash = "sha256:74bbd92f8c7fcc397ba0a11bfdc106bc72ad7f11e3a60277753f87e7532b4d81", size = 30671, upload-time = "2026-04-25T11:06:48.039Z" }, - { url = "https://files.pythonhosted.org/packages/b9/1b/104b41a8947f4e1d4a66ce1e628eea752f37d1890bfd7453559ca7a3d950/xxhash-3.7.0-cp312-cp312-win_amd64.whl", hash = "sha256:7bd7bc82dd4f185f28f35193c2e968ef46131628e3cac62f639dadf321cba4d1", size = 31514, upload-time = "2026-04-25T11:06:49.279Z" }, - { url = "https://files.pythonhosted.org/packages/98/a0/1fd0ea1f1b886d9e7c73f0397571e22333a7d79e31da6d7127c2a4a71d75/xxhash-3.7.0-cp312-cp312-win_arm64.whl", hash = "sha256:7d7148180ec99ba36585b42c8c5de25e9b40191613bc4be68909b4d25a77a852", size = 27761, upload-time = "2026-04-25T11:06:50.448Z" }, - { url = "https://files.pythonhosted.org/packages/c1/ca/d5174b4c36d10f64d4ca7050563138c5a599efb01a765858ddefc9c1202a/xxhash-3.7.0-cp313-cp313-android_21_arm64_v8a.whl", hash = "sha256:4b6d6b33f141158692bd4eafbb96edbc5aa0dabdb593a962db01a91983d4f8fa", size = 36813, upload-time = "2026-04-25T11:06:51.73Z" }, - { url = "https://files.pythonhosted.org/packages/41/d0/abc6c9d347ba1f1e1e1d98125d0881a0452c7f9a76a9dd03a7b5d2197f23/xxhash-3.7.0-cp313-cp313-android_21_x86_64.whl", hash = "sha256:845d347df254d6c619f616afa921331bada8614b8d373d58725c663ba97c3605", size = 35121, upload-time = "2026-04-25T11:06:53.048Z" }, - { url = "https://files.pythonhosted.org/packages/bf/11/4cc834eb3d79f2f2b3a6ef7324195208bcdfbdcf7534d2b17267aa5f3a8f/xxhash-3.7.0-cp313-cp313-ios_13_0_arm64_iphoneos.whl", hash = "sha256:fddbbb69a6fff4f421e7a0d1fa28f894b20112e9e3fab306af451e2dfd0e459b", size = 29624, upload-time = "2026-04-25T11:06:54.311Z" }, - { url = "https://files.pythonhosted.org/packages/23/83/e97d3e7b635fe73a1dfb1e91f805324dd6d930bb42041cbf18f183bc0b6d/xxhash-3.7.0-cp313-cp313-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:54876a4e45101cec2bf8f31a973cda073a23e2e108538dad224ba07f85f22487", size = 30638, upload-time = "2026-04-25T11:06:55.864Z" }, - { url = "https://files.pythonhosted.org/packages/f4/40/d84951d80c35db1f4c40a29a64a8520eea5d56e764c603906b4fe763580f/xxhash-3.7.0-cp313-cp313-ios_13_0_x86_64_iphonesimulator.whl", hash = "sha256:0c72fe9c7e3d6dfd7f1e21e224a877917fa09c465694ba4e06464b9511b65544", size = 33323, upload-time = "2026-04-25T11:06:57.336Z" }, - { url = "https://files.pythonhosted.org/packages/89/cc/c7dc6558d97e9ab023f663d69ab28b340ed9bf4d2d94f2c259cf896bb354/xxhash-3.7.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:a6d73a830b17ef49bc04e00182bd839164c1b3c59c127cd7c54fcb10c7ed8ee8", size = 33362, upload-time = "2026-04-25T11:06:58.656Z" }, - { url = "https://files.pythonhosted.org/packages/2a/6e/46b84017b1301d54091430353d4ad5901654a3e0871649877a416f7f1644/xxhash-3.7.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:91c3b07cf3362086d8f126c6aecd8e5e9396ad8b2f2219ea7e49a8250c318acd", size = 30874, upload-time = "2026-04-25T11:06:59.834Z" }, - { url = "https://files.pythonhosted.org/packages/df/5e/8f9158e3ab906ad3fec51e09b5ea0093e769f12207bfa42a368ca204e7ab/xxhash-3.7.0-cp313-cp313-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:50e879ebbac351c81565ca108db766d7832f5b8b6a5b14b8c0151f7190028e3d", size = 194185, upload-time = "2026-04-25T11:07:01.658Z" }, - { url = "https://files.pythonhosted.org/packages/f3/29/a804ded9f5d3d3758292678d23e7528b08fda7b7e750688d08b052322475/xxhash-3.7.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:921c14e93817842dd0dd9f372890a0f0c72e534650b6ab13c5be5cd0db11d47e", size = 213033, upload-time = "2026-04-25T11:07:03.606Z" }, - { url = "https://files.pythonhosted.org/packages/8b/91/1ce5a7d2fdc975267320e2c78fc1cecfe7ab735ccbcf6993ec5dd541cb2c/xxhash-3.7.0-cp313-cp313-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:e64a7c9d7dfca3e0fafcbc5e455519090706a3e36e95d655cec3e04e79f95aaa", size = 236140, upload-time = "2026-04-25T11:07:05.396Z" }, - { url = "https://files.pythonhosted.org/packages/34/04/fd595a4fd8617b05fa27bd9b684ecb4985bfed27917848eea85d54036d06/xxhash-3.7.0-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:2220af08163baf5fa36c2b8af079dc2cbe6e66ae061385267f9472362dfd53c6", size = 212291, upload-time = "2026-04-25T11:07:06.966Z" }, - { url = "https://files.pythonhosted.org/packages/03/fb/f1a379cbc372ae5b9f4ab36154c48a849ca6ebe3ac477067a57865bf3bc6/xxhash-3.7.0-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:f14bb8b22a4a91325813e3d553b8963c10cf8c756cff65ee50c194431296c655", size = 445532, upload-time = "2026-04-25T11:07:08.525Z" }, - { url = "https://files.pythonhosted.org/packages/65/59/172424b79f8cfd4b6d8a122b2193e6b8ad4b11f7159bb3b6f9b3191329bb/xxhash-3.7.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:496736f86a9bedaf64b0dc70e3539d0766df01c71ea22032698e88f3f04a1ce9", size = 193990, upload-time = "2026-04-25T11:07:10.315Z" }, - { url = "https://files.pythonhosted.org/packages/b9/19/aeac22161d953f139f07ba5586cb4a17c5b7b6dff985122803bb12933500/xxhash-3.7.0-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:0ff71596bd79816975b3de7130ab1ff4541410285a3c084584eeb1c8239996fd", size = 284876, upload-time = "2026-04-25T11:07:12.15Z" }, - { url = "https://files.pythonhosted.org/packages/77/d5/4fd0b59e7a02242953da05ff679fbb961b0a4368eac97a217e11dae110c1/xxhash-3.7.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:1ad86695c19b1d46fe106925db3c7a37f16be37669dcf58dcc70a9dd6e324676", size = 210495, upload-time = "2026-04-25T11:07:13.952Z" }, - { url = "https://files.pythonhosted.org/packages/aa/fb/976a3165c728c7faf74aa1b5ab3cf6a85e6d731612894741840524c7d28c/xxhash-3.7.0-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:970f9f8c50961d639cbd0d988c96f80ddf66006de93641719282c4fe7a87c5e6", size = 241331, upload-time = "2026-04-25T11:07:15.557Z" }, - { url = "https://files.pythonhosted.org/packages/4a/2c/6763d5901d53ac9e6ba296e5717ae599025c9d268396e8faa8b4b0a8e0ac/xxhash-3.7.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:5886ad85e9e347911783760a1d16cb6b393e8f9e3b52c982568226cb56927bdc", size = 198037, upload-time = "2026-04-25T11:07:17.563Z" }, - { url = "https://files.pythonhosted.org/packages/61/2b/876e722d533833f5f9a83473e6ba993e48745701096944e77bbecf29b2c3/xxhash-3.7.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:6e934bbae1e0ec74e27d5f0d7f37ef547ce5ff9f0a7e63fb39e559fc99526734", size = 210744, upload-time = "2026-04-25T11:07:19.055Z" }, - { url = "https://files.pythonhosted.org/packages/21/e6/d7e7baef7ce24166b4668d3c48557bb35a23b92ecadcac7e7718d099ab69/xxhash-3.7.0-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:3b6b3d28228af044ebcded71c4a3dd86e1dbd7e2f4645bf40f7b5da65bb5fb5a", size = 275406, upload-time = "2026-04-25T11:07:20.908Z" }, - { url = "https://files.pythonhosted.org/packages/92/fe/198b3763b2e01ca908f2154969a2352ec99bda892b574a11a9a151c5ede4/xxhash-3.7.0-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:6be4d70d9ab76c9f324ead9c01af6ff52c324745ea0c3731682a0cf99720f1fe", size = 414125, upload-time = "2026-04-25T11:07:23.037Z" }, - { url = "https://files.pythonhosted.org/packages/3a/6d/019a11affd5a5499137cacca53808659964785439855b5aa40dfd3412916/xxhash-3.7.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:151d7520838d4465461a0b7f4ae488b3b00de16183dd3214c1a6b14bf89d7fb6", size = 191555, upload-time = "2026-04-25T11:07:24.991Z" }, - { url = "https://files.pythonhosted.org/packages/76/21/b96d58568df2d01533244c3e0e5cbdd0c8b2b25c4bec4d72f19259a292d7/xxhash-3.7.0-cp313-cp313-win32.whl", hash = "sha256:d798c1e291bffb8e37b5bbe0dda77fc767cd19e89cadaf66e6ed5d0ff88c9fe6", size = 30668, upload-time = "2026-04-25T11:07:26.665Z" }, - { url = "https://files.pythonhosted.org/packages/99/57/d849a8d3afa1f8f4bc6a831cd89f49f9706fbbad94d2975d6140a171988c/xxhash-3.7.0-cp313-cp313-win_amd64.whl", hash = "sha256:875811ba23c543b1a1c3143c926e43996eb27ebb8f52d3500744aa608c275aed", size = 31524, upload-time = "2026-04-25T11:07:27.92Z" }, - { url = "https://files.pythonhosted.org/packages/81/52/bacc753e92dee78b058af8dcef0a50815f5f860986c664a92d75f965b6a5/xxhash-3.7.0-cp313-cp313-win_arm64.whl", hash = "sha256:54a675cb300dda83d71daae2a599389d22db8021a0f8db0dd659e14626eb3ecc", size = 27768, upload-time = "2026-04-25T11:07:29.113Z" }, - { url = "https://files.pythonhosted.org/packages/1c/47/ddbd683b7fc7e592c1a8d9d65f73ce9ab513f082b3967eee2baf549b8fc6/xxhash-3.7.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:a3b19a42111c4057c1547a4a1396a53961dca576a0f6b82bfa88a2d1561764b2", size = 33576, upload-time = "2026-04-25T11:07:30.469Z" }, - { url = "https://files.pythonhosted.org/packages/07/f2/36d3310161db7f72efb4562aadde0ed429f1d0531782dd6345b12d2da527/xxhash-3.7.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:8f4608a06e4d61b7a3425665a46d00e0579122e1a2fae97a0c52953a3aad9aa3", size = 31123, upload-time = "2026-04-25T11:07:31.989Z" }, - { url = "https://files.pythonhosted.org/packages/0d/3f/75937a5c69556ed213021e43cbedd84c8e0279d0d74e7d41a255d84ba4b1/xxhash-3.7.0-cp313-cp313t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:ad37c7792479e49cf96c1ab25517d7003fe0d93687a772ba19a097d235bbe41e", size = 196491, upload-time = "2026-04-25T11:07:33.358Z" }, - { url = "https://files.pythonhosted.org/packages/22/29/f10d7ff8c7a733d4403a43b9de18c8fabc005f98cec054644f04418659ee/xxhash-3.7.0-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:dc026e3b89d98e30a8288c95cb696e77d150b3f0fb7a51f73dcd49ee6b5577fa", size = 215793, upload-time = "2026-04-25T11:07:34.919Z" }, - { url = "https://files.pythonhosted.org/packages/8b/fd/778f60aa295f58907938f030a8b514611f391405614a525cccd2ffc00eb5/xxhash-3.7.0-cp313-cp313t-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:c9b31ab1f28b078a6a1ac1a54eb35e7d5390deddd56870d0be3a0a733d1c321c", size = 237993, upload-time = "2026-04-25T11:07:36.638Z" }, - { url = "https://files.pythonhosted.org/packages/70/f5/736db5de387b4a540e37a05b84b40dc58a1ce974bfd2b4e5754ce29b68c3/xxhash-3.7.0-cp313-cp313t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:3bb5fd680c038fd5229e44e9c493782f90df9bef632fd0499d442374688ff70b", size = 214887, upload-time = "2026-04-25T11:07:38.564Z" }, - { url = "https://files.pythonhosted.org/packages/4d/aa/09a095f22fdb9a27fbb716841fbff52119721f9ca4261952d07a912f7839/xxhash-3.7.0-cp313-cp313t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:030c0fd688fce3569fbb49a2feefd4110cbb0b650186fb4610759ecfac677548", size = 448407, upload-time = "2026-04-25T11:07:40.552Z" }, - { url = "https://files.pythonhosted.org/packages/74/8a/b745efeeca9e34a91c26fdc97ad8514c43d5a81ac78565cba80a1353870a/xxhash-3.7.0-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5b1bde10324f4c31812ae0d0502e92d916ae8917cad7209353f122b8b8f610c3", size = 196119, upload-time = "2026-04-25T11:07:42.101Z" }, - { url = "https://files.pythonhosted.org/packages/8a/5c/0cfceb024af90c191f665c7933b1f318ee234f4797858383bebd1881d52f/xxhash-3.7.0-cp313-cp313t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:503722d52a615f2604f5e7611de7d43878df010dc0053094ef91cb9a9ac3d987", size = 286751, upload-time = "2026-04-25T11:07:43.568Z" }, - { url = "https://files.pythonhosted.org/packages/0b/0a/0793e405dc3cf8f4ebe2c1acec1e4e4608cd9e7e50ea691dabbc2a95ccbb/xxhash-3.7.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:c72500a3b6d6c30ebfc135035bcace9eb5884f2dc220804efcaaba43e9f611dd", size = 212961, upload-time = "2026-04-25T11:07:45.388Z" }, - { url = "https://files.pythonhosted.org/packages/0c/7e/721118ffc63bfff94aa565bcf2555a820f9f4bdb0f001e0d609bdfad70de/xxhash-3.7.0-cp313-cp313t-musllinux_1_2_armv7l.whl", hash = "sha256:43475925a766d01ca8cd9a857fd87f3d50406983c8506a4c07c4df12adcc867f", size = 243703, upload-time = "2026-04-25T11:07:47.053Z" }, - { url = "https://files.pythonhosted.org/packages/6e/18/16f6267160488b8276fd3d449d425712512add292ba545c1b6946bfdb7dd/xxhash-3.7.0-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:8d09dfd2ab135b985daf868b594315ebe11ad86cd9fea46e6c69f19b28f7d25a", size = 200894, upload-time = "2026-04-25T11:07:48.657Z" }, - { url = "https://files.pythonhosted.org/packages/2d/94/80ba841287fd97e3e9cac1d228788c8ef623746f570404961eec748ecb5c/xxhash-3.7.0-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:c50269d0055ac1faecfd559886d2cbe4b730de236585aba0e873f9d9dadbe585", size = 213357, upload-time = "2026-04-25T11:07:50.257Z" }, - { url = "https://files.pythonhosted.org/packages/a1/7e/106d4067130c59f1e18a55ffadcd876d8c68534883a1e02685b29d3d8153/xxhash-3.7.0-cp313-cp313t-musllinux_1_2_riscv64.whl", hash = "sha256:1910df4756a5ab58cfad8744fc2d0f23926e3efcc346ee76e87b974abab922f4", size = 277600, upload-time = "2026-04-25T11:07:51.745Z" }, - { url = "https://files.pythonhosted.org/packages/c5/86/a081dd30da71d720b2612a792bfd55e45fa9a07ac76a0507f60487473c25/xxhash-3.7.0-cp313-cp313t-musllinux_1_2_s390x.whl", hash = "sha256:d006faf3b491957efcb433489be3c149efe4787b7063d5cddb8ddaefdc60e0c1", size = 416980, upload-time = "2026-04-25T11:07:53.504Z" }, - { url = "https://files.pythonhosted.org/packages/35/29/1a95221a029a3c1293773869e1ab47b07cbbdd82444a42809e8c60156626/xxhash-3.7.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:abb65b4e947e958f7b3b0d71db3ce447d1bc5f37f5eab871ce7223bda8768a04", size = 193840, upload-time = "2026-04-25T11:07:55.103Z" }, - { url = "https://files.pythonhosted.org/packages/c5/e0/db909dd0823285de2286f67e10ee4d81e96ad35d7d8e964ecb07fccd8af9/xxhash-3.7.0-cp313-cp313t-win32.whl", hash = "sha256:178959906cb1716a1ce08e0d69c82886c70a15a6f2790fc084fdd146ca30cd49", size = 30966, upload-time = "2026-04-25T11:07:56.524Z" }, - { url = "https://files.pythonhosted.org/packages/7b/ff/d705b15b22f21ee106adce239cb65d35067a158c630b240270f09b17c2e6/xxhash-3.7.0-cp313-cp313t-win_amd64.whl", hash = "sha256:2524a1e20d4c231d13b50f7cf39e44265b055669a64a7a4b9a2a44faa03f19b6", size = 31784, upload-time = "2026-04-25T11:07:57.758Z" }, - { url = "https://files.pythonhosted.org/packages/a2/1f/b2cf83c3638fd0588e0b17f22e5a9400bdfb1a3e3755324ac0aee2250b88/xxhash-3.7.0-cp313-cp313t-win_arm64.whl", hash = "sha256:37d994d0ffe81ef087bb330d392caa809bb5853c77e22ea3f71db024a0543dba", size = 27932, upload-time = "2026-04-25T11:07:59.109Z" }, - { url = "https://files.pythonhosted.org/packages/0e/cc/431db584f6fbb9312e40a173af027644e5580d39df1f73603cbb9dca4d6b/xxhash-3.7.0-cp314-cp314-android_24_arm64_v8a.whl", hash = "sha256:8c5fcfd806c335bfa2adf1cd0b3110a44fc7b6995c3a648c27489bae85801465", size = 36644, upload-time = "2026-04-25T11:08:00.658Z" }, - { url = "https://files.pythonhosted.org/packages/bc/01/255ec513e0a705d1f9a61413e78dfce4e3235203f0ed525a24c2b4b56345/xxhash-3.7.0-cp314-cp314-android_24_x86_64.whl", hash = "sha256:506a0b488f190f0a06769575e30caf71615c898ed93ab18b0dbcb6dec5c3713c", size = 35003, upload-time = "2026-04-25T11:08:02.338Z" }, - { url = "https://files.pythonhosted.org/packages/68/70/c55fc33c93445b44d8fc5a17b41ed99e3cebe92bcf8396809e63fc9a1165/xxhash-3.7.0-cp314-cp314-ios_13_0_arm64_iphoneos.whl", hash = "sha256:ec68dbba21532c0173a9872298e65c89749f7c9d21538c3a78b5bb6105871568", size = 29655, upload-time = "2026-04-25T11:08:03.701Z" }, - { url = "https://files.pythonhosted.org/packages/c2/72/ff8de73df000d74467d12a59ce6d6e2b2a368b978d41ab7b1fba5ed442be/xxhash-3.7.0-cp314-cp314-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:fa77e7ec1450d415d20129961814787c9abd9a07f98872f070b1fe96c5084611", size = 30664, upload-time = "2026-04-25T11:08:05.011Z" }, - { url = "https://files.pythonhosted.org/packages/b6/91/08416d9bd9bc3bf39d831abe8a5631ac2db5141dfd6fe81c3fe59a1f9264/xxhash-3.7.0-cp314-cp314-ios_13_0_x86_64_iphonesimulator.whl", hash = "sha256:fe32736295ea38e43e7d9424053c8c47c9f64fecfc7c895fb3da9b30b131c9ee", size = 33317, upload-time = "2026-04-25T11:08:06.413Z" }, - { url = "https://files.pythonhosted.org/packages/0e/3b/86b1caa4dee10a99f4bf9521e623359341c5e50d05158fa10c275b2bd079/xxhash-3.7.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:ab9dd2c83c4bbd63e422181a76f13502d049d3ddcac9a1bdc29196263d692bb8", size = 33457, upload-time = "2026-04-25T11:08:08.099Z" }, - { url = "https://files.pythonhosted.org/packages/ed/38/98ea14ad1517e1461292a65906951458d520689782bfbae111050145bdba/xxhash-3.7.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:3afec3a336a2286601a437cb07562ab0227685e6fbb9ec17e8c18457ff348ecf", size = 30894, upload-time = "2026-04-25T11:08:09.429Z" }, - { url = "https://files.pythonhosted.org/packages/61/a2/074654d0b893606541199993c7db70067d9fc63b748e0d60020a52a1bd36/xxhash-3.7.0-cp314-cp314-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:565df64437a9390f84465dcca33e7377114c7ede8d05cd2cf20081f831ea788e", size = 194409, upload-time = "2026-04-25T11:08:10.91Z" }, - { url = "https://files.pythonhosted.org/packages/e2/26/6d2a1afc468189f77ca28c32e1c83e1b9da1178231e05641dbc1b350e332/xxhash-3.7.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:12eca820a5d558633d423bf8bb78ce72a55394823f64089247f788a7e0ae691e", size = 213135, upload-time = "2026-04-25T11:08:12.575Z" }, - { url = "https://files.pythonhosted.org/packages/8e/0e/d8aecf95e09c42547453137be74d2f7b8b14e08f5177fa2fab6144a19061/xxhash-3.7.0-cp314-cp314-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:f262b8f7599516567e070abf607b9af649052b2c4bd6f9be02b0cb41b7024805", size = 236379, upload-time = "2026-04-25T11:08:14.206Z" }, - { url = "https://files.pythonhosted.org/packages/f2/74/8140e8210536b3dd0cc816c4faaeb5ba6e63e8125ab25af4bcddd6a037b3/xxhash-3.7.0-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:f1598916cb197681e03e601901e4ab96a9a963de398c59d0964f8a6f44a2b361", size = 212447, upload-time = "2026-04-25T11:08:15.79Z" }, - { url = "https://files.pythonhosted.org/packages/a0/d2/462001d2903b4bee5a5689598a0a55e5e7cd1ac7f4247a5545cff10d3ebb/xxhash-3.7.0-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:322b2f0622230f526aeb1738149948a7ae357a9e2ceb1383c6fd1fdaecdafa16", size = 445660, upload-time = "2026-04-25T11:08:17.441Z" }, - { url = "https://files.pythonhosted.org/packages/23/09/2bd1ed7f8689b20e51727952cac8329d50c694dc32b2eba06ba5bc742b37/xxhash-3.7.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:24cc22070880cc57b830a65cde4e65fa884c6d9b28ae4803b5ee05911e7bafba", size = 194076, upload-time = "2026-04-25T11:08:19.134Z" }, - { url = "https://files.pythonhosted.org/packages/c9/6e/692302cd0a5f4ac4e6289f37fa888dc2e1e07750b68fe3e4bfe939b8cea3/xxhash-3.7.0-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:cb5a888a968b2434abf9ecda357b5d43f10d7b5a6da6fdbbe036208473aff0e2", size = 284990, upload-time = "2026-04-25T11:08:20.618Z" }, - { url = "https://files.pythonhosted.org/packages/05/d9/e54b159b3d9df7999d2a7c676ce7b323d1b5588a64f8f51ed8172567bd87/xxhash-3.7.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:a999771ff97bec27d18341be4f3a36b163bb1ac41ec17bef6d2dabd84acd33c7", size = 210590, upload-time = "2026-04-25T11:08:22.24Z" }, - { url = "https://files.pythonhosted.org/packages/50/93/0e0df1a3a196ced4ca71de76d65ead25d8e87bbfb87b64306ea47a40c00d/xxhash-3.7.0-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:ed4a6efe2dee1655adb73e7ad40c6aa955a6892422b1e3b95de6a34de56e3cbb", size = 241442, upload-time = "2026-04-25T11:08:23.844Z" }, - { url = "https://files.pythonhosted.org/packages/9a/a9/d917a7a814e90b218f8a0d37967105eea91bf752c3303683c99a1f7bfc1f/xxhash-3.7.0-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:9fd17f14ac0faa12126c2f9ca774a8cf342957265ec3c8669c144e5e6cdb478c", size = 198356, upload-time = "2026-04-25T11:08:25.99Z" }, - { url = "https://files.pythonhosted.org/packages/89/5e/f2ba1877c39469abbefc72991d6ebdcbd4c0880db01ae8cb1f553b0c537d/xxhash-3.7.0-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:05fd1254268c59b5cb2a029dfc204275e9fc52de2913f1e53aa8d01442c96b4d", size = 210898, upload-time = "2026-04-25T11:08:27.608Z" }, - { url = "https://files.pythonhosted.org/packages/90/c6/be56b58e73de531f39a10de1355bb77ceb663900dc4bf2d6d3002a9c3f9e/xxhash-3.7.0-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:a2eae53197c6276d5b317f75a1be226bbf440c20b58bf525f36b5d0e1f657ca6", size = 275519, upload-time = "2026-04-25T11:08:29.301Z" }, - { url = "https://files.pythonhosted.org/packages/92/e2/17ddc85d5765b9c709f192009ed8f5a1fc876f4eb35bba7c307b5b1169f9/xxhash-3.7.0-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:bfe6f92e3522dcbe8c4281efd74fa7542a336cb00b0e3272c4ec0edabeaeaf67", size = 414191, upload-time = "2026-04-25T11:08:31.16Z" }, - { url = "https://files.pythonhosted.org/packages/9c/42/85f5b79f4bf1ec7ba052491164adfd4f4e9519f5dc7246de4fbd64a1bd56/xxhash-3.7.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:7ab9a49c410d8c6c786ab99e79c529938d894c01433130353dd0fe999111077a", size = 191604, upload-time = "2026-04-25T11:08:32.862Z" }, - { url = "https://files.pythonhosted.org/packages/b8/d0/6127b623aa4cca18d8b7743592b048d689fd6c6e37ff26a22cddf6cd9d7f/xxhash-3.7.0-cp314-cp314-win32.whl", hash = "sha256:040ea63668f9185b92bc74942df09c7e65703deed71431333678fc6e739a9955", size = 31271, upload-time = "2026-04-25T11:08:34.651Z" }, - { url = "https://files.pythonhosted.org/packages/64/4f/44fc4788568004c43921701cbc127f48218a1eede2c9aea231115323564d/xxhash-3.7.0-cp314-cp314-win_amd64.whl", hash = "sha256:2a61e2a3fb23c892496d587b470dee7fa1b58b248a187719c65ea8e94ec13257", size = 32284, upload-time = "2026-04-25T11:08:35.987Z" }, - { url = "https://files.pythonhosted.org/packages/6d/77/18bb895eb60a49453d16e17d67990e5caff557c78eafc90ad4e2eabf4570/xxhash-3.7.0-cp314-cp314-win_arm64.whl", hash = "sha256:c7741c7524961d8c0cb4d4c21b28957ff731a3fd5b5cd8b856dc80a40e9e5acc", size = 28701, upload-time = "2026-04-25T11:08:37.767Z" }, - { url = "https://files.pythonhosted.org/packages/45/a0/46f72244570c550fbbb7db1ef554183dd5ebe9136385f30e032b781ae8f6/xxhash-3.7.0-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:fc84bf7aa7592f31ec63a3e7b11d624f468a3f19f5238cec7282a42e838ab1d7", size = 33646, upload-time = "2026-04-25T11:08:39.109Z" }, - { url = "https://files.pythonhosted.org/packages/4a/3a/453846a7eceea11e75def361eed01ec6a0205b9822c19927ed364ccae7cc/xxhash-3.7.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:9f1563fdc8abfc389748e6932c7e4e99c89a53e4ec37d4563c24fc06f5e5644b", size = 31125, upload-time = "2026-04-25T11:08:40.467Z" }, - { url = "https://files.pythonhosted.org/packages/bd/3e/49434aba738885d512f9e486db1bdd19db28dfa40372b56da26ef7a4e738/xxhash-3.7.0-cp314-cp314t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:2d415f18becf6f153046ab6adc97da77e3643a0ee205dae61c4012604113a020", size = 196633, upload-time = "2026-04-25T11:08:41.943Z" }, - { url = "https://files.pythonhosted.org/packages/a4/e9/006cb6127baeb9f8abe6d15e62faa01349f09b34e2bfd65175b2422d026b/xxhash-3.7.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:bb16aa13ed175bc9be5c2491ba031b85a9b51c4ed90e0b3d4ebe63cf3fb54f8e", size = 215899, upload-time = "2026-04-25T11:08:43.645Z" }, - { url = "https://files.pythonhosted.org/packages/27/e4/cc57d72e66df0ae29b914335f1c6dcf61e8f3746ddf0ae3c471aa4f15e00/xxhash-3.7.0-cp314-cp314t-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:f9fd595f1e5941b3d7863e4774e4b30caa6731fc34b9277da032295aa5656ee5", size = 238116, upload-time = "2026-04-25T11:08:45.698Z" }, - { url = "https://files.pythonhosted.org/packages/af/78/3531d4a3fd8a0038cc6be1f265a69c1b3587f557a10b677dd736de2202c1/xxhash-3.7.0-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:1295325c5a98d552333fa53dc2b026b0ef0ec9c8e73ca3a952990b4c7d65d459", size = 215012, upload-time = "2026-04-25T11:08:47.355Z" }, - { url = "https://files.pythonhosted.org/packages/b4/f6/259fb1eaaec921f59b17203b0daee69829761226d3b980d5191d7723dd83/xxhash-3.7.0-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:3573a651d146912da9daa9e29e5fbc45994420daaa9ef1e2fa5823e1dc485513", size = 448534, upload-time = "2026-04-25T11:08:49.149Z" }, - { url = "https://files.pythonhosted.org/packages/7b/16/a66d0eaf6a7e68532c07714361ddc904c663ec940f3b028c1ae4a21a7b9d/xxhash-3.7.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5ec1e080a3d02d94ea9335bfab0e3374b877e25411422c18f51a943fa4b46381", size = 196217, upload-time = "2026-04-25T11:08:50.805Z" }, - { url = "https://files.pythonhosted.org/packages/8d/ef/d2efc7fc51756dc52509109d1a25cefc859d74bc4b19a167b12dbd8c2786/xxhash-3.7.0-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:84415265192072d8638a3afc3c1bc5995e310570cd9acb54dc46d3939e364fe0", size = 286906, upload-time = "2026-04-25T11:08:52.418Z" }, - { url = "https://files.pythonhosted.org/packages/fc/67/25decd1d4a4018582ec4db2a868a2b7e40640f4adb20dfeb19ac923aa825/xxhash-3.7.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:8d4dea659b57443989ef32f4295104fd6912c73d0bf26d1d148bb88a9f159b02", size = 213057, upload-time = "2026-04-25T11:08:54.105Z" }, - { url = "https://files.pythonhosted.org/packages/0d/5d/17651eb29d06786cdc40c60ae3d27d645aa5d61d2eca6237a7ba0b94789b/xxhash-3.7.0-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:05ece0fe4d9c9c2728912d1981ae1566cfc83a011571b24732cbf76e1fb70dca", size = 243886, upload-time = "2026-04-25T11:08:56.109Z" }, - { url = "https://files.pythonhosted.org/packages/8a/d4/174d9cf7502243d586e6a9ae842b1ae23026620995114f85f1380e588bc9/xxhash-3.7.0-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:fd880353cf1ffaf321bc18dd663e111976dbd0d3bbd8a66d58d2b470dfa7f396", size = 201015, upload-time = "2026-04-25T11:08:57.777Z" }, - { url = "https://files.pythonhosted.org/packages/91/8c/2254e2d06c3ac5e6fe22eaf3da791b87ea823ae9f2c17b4af66755c5752d/xxhash-3.7.0-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:4e15cc9e2817f6481160f930c62842b3ff419e20e13072bcbab12230943092bc", size = 213457, upload-time = "2026-04-25T11:08:59.826Z" }, - { url = "https://files.pythonhosted.org/packages/79/a2/e3daa762545921173e3360f3b4ff7fc63c2d27359f7230ec1a7a74e117f6/xxhash-3.7.0-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:90b9d1a8bd37d768ffc92a1f651ec69afc532a96fa1ac2ea7abbed5d630b3237", size = 277738, upload-time = "2026-04-25T11:09:01.423Z" }, - { url = "https://files.pythonhosted.org/packages/e1/4c/e186da2c46b87f5204640e008d42730bf3c1ee9f0efb71ae1ebcdfeac681/xxhash-3.7.0-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:157c49475b34ecea8809e51123d9769a534e139d1247942f7a4bc67710bb2533", size = 417127, upload-time = "2026-04-25T11:09:03.592Z" }, - { url = "https://files.pythonhosted.org/packages/17/28/3798e15007a3712d0da3d3fe70f8e11916569858b5cc371053bc26270832/xxhash-3.7.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:5a6ddec83325685e729ca119d1f5c518ec39294212ecd770e60693cdc5f7eb79", size = 193962, upload-time = "2026-04-25T11:09:06.228Z" }, - { url = "https://files.pythonhosted.org/packages/ad/95/a26baa93b5241fd7630998816a4ec47a5a0bad193b3f8fc8f3593e1a4a67/xxhash-3.7.0-cp314-cp314t-win32.whl", hash = "sha256:a04a6cab47e2166435aaf5b9e5ee41d1532cc8300efdef87f2a4d0acb7db19ed", size = 31643, upload-time = "2026-04-25T11:09:08.153Z" }, - { url = "https://files.pythonhosted.org/packages/44/36/5454f13c447e395f9b06a3e91274c59f503d31fad84e1836efe3bdb71f6a/xxhash-3.7.0-cp314-cp314t-win_amd64.whl", hash = "sha256:8653dd7c2eda020545bb2c71c7f7039b53fe7434d0fc1a0a9deb79ab3f1a4fc1", size = 32522, upload-time = "2026-04-25T11:09:09.534Z" }, - { url = "https://files.pythonhosted.org/packages/74/35/698e7e3ff38e22992ea24870a511d8762474fb6783627a2910ff22a185c2/xxhash-3.7.0-cp314-cp314t-win_arm64.whl", hash = "sha256:468f0fc114faaa4b36699f8e328bbc3bb11dc418ba94ac52c26dd736d4b6c637", size = 28807, upload-time = "2026-04-25T11:09:11.234Z" }, - { url = "https://files.pythonhosted.org/packages/54/c1/e57ac7317b1f58a92bab692da6d497e2a7ce44735b224e296347a7ecc754/xxhash-3.7.0-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:ad3aa71e12ee634f22b39a0ff439357583706e50765f17f05550f92dbf128a23", size = 31232, upload-time = "2026-04-25T11:10:21.51Z" }, - { url = "https://files.pythonhosted.org/packages/4f/4e/075559bd712bc62e84915ea46bbee859f935d285659082c129bdbff679dd/xxhash-3.7.0-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:5de686e73690cdaf72b96d4fa083c230ec9020bcc2627ce6316138e2cf2fe2d1", size = 28553, upload-time = "2026-04-25T11:10:23.1Z" }, - { url = "https://files.pythonhosted.org/packages/92/ca/a9c78cb384d4b033b0c58196bd5c8509873cabe76389e195127b0302a741/xxhash-3.7.0-pp311-pypy311_pp73-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:7fbec49f5341bbdea0c471f7d1e2fb41ae8925af9b6f28025c28defd8eb94274", size = 41109, upload-time = "2026-04-25T11:10:25.022Z" }, - { url = "https://files.pythonhosted.org/packages/bd/b1/dfe2629f7c77eb2fa234c72ff537cdd64939763df704e256446ed364a16d/xxhash-3.7.0-pp311-pypy311_pp73-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:48b542c347c2089f43dc5a6db31d2a6f3cdb04ee33505ec6e9f653834dbb0bde", size = 36307, upload-time = "2026-04-25T11:10:26.949Z" }, - { url = "https://files.pythonhosted.org/packages/e7/f7/5a484afce0f48dd8083208b42e4911f290a82c7b52458ef2927e4d421a45/xxhash-3.7.0-pp311-pypy311_pp73-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a169a036bed0995e090d1493b283cc2cc8a6f5046821086b843abefff80643bc", size = 32534, upload-time = "2026-04-25T11:10:29.01Z" }, - { url = "https://files.pythonhosted.org/packages/0f/5f/4acfcd490db9780cf36c58534d828003c564cde5350220a1c783c4d10776/xxhash-3.7.0-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:ec101643395d7f21405b640f728f6f627e6986557027d740f2f9b220955edafe", size = 31552, upload-time = "2026-04-25T11:10:30.727Z" }, +version = "3.8.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/8e/63/71aa56b151a1b28770037a61bd4e461c2619cfc8866a4fcaf1548605e325/xxhash-3.8.1.tar.gz", hash = "sha256:b0de4bf3aa66363552d52c6a89003c479911f12098cd48a53d44a0f7a25f7c46", size = 86223, upload-time = "2026-07-06T10:49:58.937Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/55/97/1a8cebf0a6650417f08a18231590e2515aacd5ce39c3ad8b9e013ebd437d/xxhash-3.8.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:27a9e475157f7315826118e3f3127909a0fe25f1b43d3d3be9c584f9d265f937", size = 34695, upload-time = "2026-07-06T10:43:40.248Z" }, + { url = "https://files.pythonhosted.org/packages/2f/cf/745b9bc0dd9c341bc074b5fc700db7bbef0f3b69ab21446492296ab37e50/xxhash-3.8.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9b2ce44bf8f4a1d01f418b3110ff8dff32fd3f3e836c0e06333c3725f243fa6c", size = 32376, upload-time = "2026-07-06T10:43:41.97Z" }, + { url = "https://files.pythonhosted.org/packages/65/a4/8512a901b1d6ad4a9838d1b40385907a879d7e005a5afbec5d39526b69f6/xxhash-3.8.1-cp310-cp310-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:942bc86e9be6fdd6e1175048f5fe8f8fdaaf2309dd1323ef1e155a69cd346780", size = 217470, upload-time = "2026-07-06T10:43:43.572Z" }, + { url = "https://files.pythonhosted.org/packages/a0/ad/0ffd8094ea29579bb2dc42fa74d08570e9ea3d95db561e6b1105e69b9ca6/xxhash-3.8.1-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0204701e6d01f64254e0e5ff4255812b1febe027ddd7dda63372e27f98b5e91f", size = 237799, upload-time = "2026-07-06T10:43:45.248Z" }, + { url = "https://files.pythonhosted.org/packages/b3/90/783c6b3f9336bd07449fe672be32cef6833633936bbfda8d3b23ee18d202/xxhash-3.8.1-cp310-cp310-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:7dc4bdf008f77c88d544849c48c1a40faf25a5eff6cc466de2e8edc37c191fce", size = 262587, upload-time = "2026-07-06T10:43:46.733Z" }, + { url = "https://files.pythonhosted.org/packages/c4/77/ba0316a7c3e661b86830a47ae4987798616ce1b15af8d2a6358e2d89ef60/xxhash-3.8.1-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:5c566b123dce7e4867ca518434cdfb9f84e5023771235b2e3107a26c9a41cbd8", size = 238484, upload-time = "2026-07-06T10:43:48.453Z" }, + { url = "https://files.pythonhosted.org/packages/09/79/33001037c1cba90f4ced38b257161c13452024c0db44208f883e2e47f3fc/xxhash-3.8.1-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:9f23083e1bd9d901f844af7a126727c486e7eada9a1a6791c8f7e73f94fac656", size = 469909, upload-time = "2026-07-06T10:43:50.188Z" }, + { url = "https://files.pythonhosted.org/packages/45/90/237eded9dd6ae638083294e5a9f77b317aaebd480a330806b39c192a0de1/xxhash-3.8.1-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:64af54dd1c3a45a27c04942f9a1a4683322bdd127f4745cca4e02549c1d2d2bb", size = 217166, upload-time = "2026-07-06T10:43:51.816Z" }, + { url = "https://files.pythonhosted.org/packages/0b/6a/8cb439dc9920e1468e1c2d69ef77cbeb4be3b1ae9f4b5344c07a2b59af18/xxhash-3.8.1-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:8ea8a141eeced4f6262ab6dd71c681ac546a558c30bb586abe087d814b5f85ea", size = 307593, upload-time = "2026-07-06T10:43:53.436Z" }, + { url = "https://files.pythonhosted.org/packages/ec/c6/c0607d373c8affea92101a3926c4fc8b026bcf8983e05fd58f3a0380ebf8/xxhash-3.8.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:a98b2f95cab589e0f5e92c48431afb4d56238b8bf6668edcc66166180e9b509b", size = 234702, upload-time = "2026-07-06T10:43:55.042Z" }, + { url = "https://files.pythonhosted.org/packages/5b/cb/f4cfd456624c1f017858168b7ba9443dad810da8aac779a612658450e827/xxhash-3.8.1-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:1b86ae798a976ccbc1d02af6ccb98f5b4d24756b1f65e995f11d10fe071f486f", size = 265749, upload-time = "2026-07-06T10:43:56.749Z" }, + { url = "https://files.pythonhosted.org/packages/33/f3/9006669c04b01206e21b2177425c649461ba188930a052c2f1728d6ec6a8/xxhash-3.8.1-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:81f4ed9ca9644bc95cd976bfe10f7a4cafab8ffdc3aed52877d4600e445be7ef", size = 221992, upload-time = "2026-07-06T10:43:58.12Z" }, + { url = "https://files.pythonhosted.org/packages/2b/0b/7e6f3eaa05df5e0b6c94aa452b0672801f7031e602081f07fd441aaaaed5/xxhash-3.8.1-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:cb3fe820c27593f170770d6c8d791936cf6275d9269405fbb7b30a55363c10c8", size = 236899, upload-time = "2026-07-06T10:43:59.562Z" }, + { url = "https://files.pythonhosted.org/packages/da/cc/bbaee4987f3aab1d7b33bb430bb49e940646160af448b9167431c931126d/xxhash-3.8.1-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:7345007c12780985de4fd740148776d1eee18c0d41407c6fa1e48c5450304fe5", size = 297934, upload-time = "2026-07-06T10:44:01.132Z" }, + { url = "https://files.pythonhosted.org/packages/a7/97/6bee358660eb8b4f73c00b00b00bc616ebde00e1ab4b67c63486ce360648/xxhash-3.8.1-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:12eaeaa9ab8b9e6033a1fa5f6b338aaf55ff4df4bee11b59fd6ee03b19186ee4", size = 439315, upload-time = "2026-07-06T10:44:02.878Z" }, + { url = "https://files.pythonhosted.org/packages/c6/50/7e35275f39256bedace0c3cd5be3c72d4ac9d5aecf5e5fdc3530337cd263/xxhash-3.8.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:e2a845687219ba3214126f14a8a5861f97c9e065a7d0b8252adb6df13eea86fb", size = 214038, upload-time = "2026-07-06T10:44:04.504Z" }, + { url = "https://files.pythonhosted.org/packages/59/2d/69d02d096ee50bdf3ef0d208d874f52c71b1aa6906066bce3c52fedb8bc6/xxhash-3.8.1-cp310-cp310-win32.whl", hash = "sha256:656256c9f9303e47f07d5cb8ae4468285370adfafd7ba48aea33a458e7697626", size = 31939, upload-time = "2026-07-06T10:44:06.213Z" }, + { url = "https://files.pythonhosted.org/packages/c9/1d/e06fca9844919ca91c6587d530cfa1e745830ec73ad38f44f04b25d1bfb7/xxhash-3.8.1-cp310-cp310-win_amd64.whl", hash = "sha256:27cfc2f1ed76f956f36dfe0c56e5f5a3e94cd91eb78b893f63e2ef2ae404fcdf", size = 32729, upload-time = "2026-07-06T10:44:07.621Z" }, + { url = "https://files.pythonhosted.org/packages/8c/c2/800648d99039927b5a86d8ae02cd86a556a5ee1678d388216f6b44c8966c/xxhash-3.8.1-cp310-cp310-win_arm64.whl", hash = "sha256:c85949d02c85adf6d786eb94858e124989a632a4e65739835b2fc5761827fac3", size = 29215, upload-time = "2026-07-06T10:44:08.916Z" }, + { url = "https://files.pythonhosted.org/packages/8a/5a/05eaa129555f85476a3e16ff869e95f81a78bbe4647eef9d0229f515a317/xxhash-3.8.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:602efcad4a42c184e81d43a2b7e6e4f524d619878f2b6ee2ba469011f47c8147", size = 34699, upload-time = "2026-07-06T10:44:10.14Z" }, + { url = "https://files.pythonhosted.org/packages/80/59/0df1133958b2228929355e022aab1e958c7b2c43e27bf7f59bc9edfa8a54/xxhash-3.8.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:131324f719957b988861714de7d6ddf57b47abec3b0cc691302ffeaba0e05e10", size = 32373, upload-time = "2026-07-06T10:44:11.353Z" }, + { url = "https://files.pythonhosted.org/packages/3e/bf/1cfda5b5e6bf26617812b4a31662ef2220d2ad04e0a55b8ff9eb36e56a5c/xxhash-3.8.1-cp311-cp311-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:db77278a6eddadbf44ce5aae2fee5ebb4d061f026b1ce2130d058cd4d7a7b670", size = 220284, upload-time = "2026-07-06T10:44:12.683Z" }, + { url = "https://files.pythonhosted.org/packages/70/93/45dc0ad7913b69e5b08bd039236cf628380e4c9cc76a8a4c6625a328e058/xxhash-3.8.1-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1c332dd48b8cb050da2bb2a3c96d72b1664168650a250ef9718e423df7989e05", size = 240980, upload-time = "2026-07-06T10:44:14.297Z" }, + { url = "https://files.pythonhosted.org/packages/e9/02/f28ba7d17f2c1410ee397982c817ab1bd5b2701070c2d2c373539aad000a/xxhash-3.8.1-cp311-cp311-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:a5cd96f6dcdf4fa657b2d95668d71d58455248f98712ecffaa9c528edf40ccae", size = 264526, upload-time = "2026-07-06T10:44:16.017Z" }, + { url = "https://files.pythonhosted.org/packages/5c/d0/f10651cec2c7981b20d693deae6bdfc438427d92be2db4ccabb6181f0021/xxhash-3.8.1-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:c959f88160b13b4e730b0d75b459b7929fc0d2225c284c9683ac95d6feeeac6a", size = 241369, upload-time = "2026-07-06T10:44:17.698Z" }, + { url = "https://files.pythonhosted.org/packages/ff/40/136e0cbaf5db51e191423b1c98643593189f02b6cd90837bf64b19113d70/xxhash-3.8.1-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:027dee4355f3fcc41481650d846cf6cfc895c85a1ab7acd063063821a0df5b4c", size = 473186, upload-time = "2026-07-06T10:44:19.354Z" }, + { url = "https://files.pythonhosted.org/packages/4b/3f/6aa808a96bdc43dba9a740dec56c744526ee3c0019e32c75e810fa90ae4d/xxhash-3.8.1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ad52a0e4bcc0ba956a953a169d1feec2734a64981d689e4fc8f490f7bf91af60", size = 220092, upload-time = "2026-07-06T10:44:20.956Z" }, + { url = "https://files.pythonhosted.org/packages/47/28/a8675e78a9ced96dab853416162268e10e05b452e95db7888cf69f58ac5f/xxhash-3.8.1-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:5d3dfb1f0ff146da7952867a9414f0c7a29762f8825a84879592612fd6139342", size = 309846, upload-time = "2026-07-06T10:44:22.543Z" }, + { url = "https://files.pythonhosted.org/packages/89/0f/7fe4d4ef4e69f0033e012396ee2a115886bca7b10b7e45ce398626436bfc/xxhash-3.8.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:4482380b462ca9e59994d072a877ecadd1cf51102daeeab2db696f96ab763723", size = 237659, upload-time = "2026-07-06T10:44:24.135Z" }, + { url = "https://files.pythonhosted.org/packages/38/8f/83e9e31d4ed57fe963b99cb5b13a23e3e0f0dad1885aa0ebd2a7819dd423/xxhash-3.8.1-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:950ac754d16daea42038f38e7465eb84cda4d08d7343c1c915771b29470f065a", size = 268737, upload-time = "2026-07-06T10:44:25.875Z" }, + { url = "https://files.pythonhosted.org/packages/57/79/7e7de46dbe5d1f49afc96a0bc42e6b8df24eae3d6bad6007b99e42f48430/xxhash-3.8.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:0418ec8b2331b9d4d575fc9284427e8e69449d7172e99e1a86fcdd1f51a0a937", size = 224955, upload-time = "2026-07-06T10:44:27.777Z" }, + { url = "https://files.pythonhosted.org/packages/ec/34/b8540839e958d5ef5c6101af6f16032109e7099698ae8edbc8dcefe4d8f4/xxhash-3.8.1-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:32a94ad2763e0263d9102037d349002c3d3c401e42770542c3eeb4801f311661", size = 239653, upload-time = "2026-07-06T10:44:29.422Z" }, + { url = "https://files.pythonhosted.org/packages/ce/87/a735d05f7f859354acadabe470ff40e2c46672275f96dcf096a761904def/xxhash-3.8.1-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:89b11a5cdd441aa463f6d34ca0241602bc09b001a76994b6059828494108c673", size = 300213, upload-time = "2026-07-06T10:44:31.401Z" }, + { url = "https://files.pythonhosted.org/packages/98/31/3e1cb020237b68117fc212dc5f9753b87f865b4dfee7c1ce62d0836955b5/xxhash-3.8.1-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:09a204dd4bb0823daf938cdd0dc8057d5f1e14fe3cbde929424255f23f9de872", size = 442508, upload-time = "2026-07-06T10:44:33.023Z" }, + { url = "https://files.pythonhosted.org/packages/23/bf/f80090622141cc734b039ce1d15ce3ff6dced375e9680249bf5b9b8c6bf9/xxhash-3.8.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:e710ad822c493fb80a4fbc1e3d0a807b1422cb90adbe64378f98291b7fa48fef", size = 216853, upload-time = "2026-07-06T10:44:34.983Z" }, + { url = "https://files.pythonhosted.org/packages/a6/a3/60157acecc307b238d3651c2483168e224b48b23a36ae6d6903588341d80/xxhash-3.8.1-cp311-cp311-win32.whl", hash = "sha256:5013be3bea7612852c62a7437f3302c1cfb91ca7e703b194459db0b2b2e0d792", size = 31936, upload-time = "2026-07-06T10:44:36.542Z" }, + { url = "https://files.pythonhosted.org/packages/59/5c/ef70c418d878d187b8da56d4cdc06aea6cf5e456b301e96e51e1d2cc8625/xxhash-3.8.1-cp311-cp311-win_amd64.whl", hash = "sha256:f377012b86c0a23a1df0cf5a1b05aa7187649e472f71c7892e5f2c2815bbe74f", size = 32724, upload-time = "2026-07-06T10:44:38.177Z" }, + { url = "https://files.pythonhosted.org/packages/2c/25/f008db952cec6b2a26445b456eeed2ebebd65e08e848ebe09ed6ac0634e6/xxhash-3.8.1-cp311-cp311-win_arm64.whl", hash = "sha256:836f11d4474d3228e9909d97216faa4f7505df41cfaf3927eb29809de785a78d", size = 29212, upload-time = "2026-07-06T10:44:39.577Z" }, + { url = "https://files.pythonhosted.org/packages/42/91/f65c34a7aa7b4e7cf4854f8e6ef3f7ee32ceac41d4f008da0780db0612f6/xxhash-3.8.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:e6e49370822c1f4d8d90e678b06dbcb08b51a026a7c4b55479e7d467f2e813bc", size = 34680, upload-time = "2026-07-06T10:44:40.932Z" }, + { url = "https://files.pythonhosted.org/packages/57/04/b10a245a4c09a9cfa88f8e9ae755029413ad1ac17047f9a61906e5ae0799/xxhash-3.8.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:220d68130f83f7cc86d6edfdeab176adc73d7200bf3a8ec10c629e8cf605c215", size = 32397, upload-time = "2026-07-06T10:44:42.196Z" }, + { url = "https://files.pythonhosted.org/packages/3a/75/45ab795b5945b6388583bd75202106af505537935566c15a1577797a0e08/xxhash-3.8.1-cp312-cp312-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:4d365ee1892c1fa803536f8c6ce21d24b29c9718ec75eb856095c07830f8c478", size = 220549, upload-time = "2026-07-06T10:44:43.603Z" }, + { url = "https://files.pythonhosted.org/packages/13/44/5ba2bd0a14ddf4193fc7d8ec29625f659f22c06d60b28f04bf46305d8330/xxhash-3.8.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:852bfe059720632e2f16a6a4745e41d20937b2bf2a42a401e2412046bb6971cc", size = 241186, upload-time = "2026-07-06T10:44:45.534Z" }, + { url = "https://files.pythonhosted.org/packages/23/32/c4147def4d1e4538b906f82731e0ba23424377fc50a7cddd03cd284c8f63/xxhash-3.8.1-cp312-cp312-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:2f8c25a7061d952de589bd0ea0eaadee32378ff83dd6a677b267f9cd86f401f8", size = 264852, upload-time = "2026-07-06T10:44:47.199Z" }, + { url = "https://files.pythonhosted.org/packages/6c/bd/71ed14f4f0318bb7fd7b2ec51999413487fa8da8d41208e84d50d1ef0f98/xxhash-3.8.1-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:868a8dcaff1a84ba78038e1cef14fc88ccf84d9b4d12ea604696e0693296aa56", size = 242663, upload-time = "2026-07-06T10:44:48.846Z" }, + { url = "https://files.pythonhosted.org/packages/91/09/70af22c565a8473b3f2ae73f88e7721af281bc4a575236dbd1970c9f76f6/xxhash-3.8.1-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:6536d8677d2fff7e64cd0b98b976df9de7aee0e69590044c2af5f51b76b7a170", size = 473510, upload-time = "2026-07-06T10:44:50.695Z" }, + { url = "https://files.pythonhosted.org/packages/18/96/34db781c8f0cf99c544ca1f2bc2e5bf55426e1eb4ca6de8ea5da56a9f352/xxhash-3.8.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:82c0cedd280eab2e8291270e6c04894dbc096f8159a39dcf1807429f026ca3cc", size = 220469, upload-time = "2026-07-06T10:44:52.422Z" }, + { url = "https://files.pythonhosted.org/packages/93/5f/9a184f615fa5a4dce30c01534f62946ce5a11ce40f73785cbd356ccabaa9/xxhash-3.8.1-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:daa86e4b68221d38e669bb236ba112d0335353829fb627c82e5909e4bbe8694c", size = 310290, upload-time = "2026-07-06T10:44:54.142Z" }, + { url = "https://files.pythonhosted.org/packages/a9/dc/9b9a9789011ee153723a5eb9e7dd7fcbae2ba9b3fe7a729249ca7c252056/xxhash-3.8.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:2bc7113e6f2b6b3922dd61796ca9f36af09da3773898e7003038dc992fc83b8d", size = 238173, upload-time = "2026-07-06T10:44:55.693Z" }, + { url = "https://files.pythonhosted.org/packages/ec/4d/71c6005ada9dcb608a4e1902e8475ecadb5f3fbfa04e1e244d276a2d0c43/xxhash-3.8.1-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:5eed32dad81d6ba8e62dc7b9ffa0500199385d7810a8dd9d4eafaceb8c6e20bb", size = 269026, upload-time = "2026-07-06T10:44:57.424Z" }, + { url = "https://files.pythonhosted.org/packages/2f/87/d6c036ba25dfbd9c8633be5aa86fc9474bbb9e2c68212a841d090abe7344/xxhash-3.8.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:83697b0ea1f10e7f5d8b26a4906fa851393c61546c63839643a2b7fe2d868061", size = 224970, upload-time = "2026-07-06T10:44:59.085Z" }, + { url = "https://files.pythonhosted.org/packages/48/62/4c1f035a41c5752aa05e195b6c904c07b94fe9061a16de61e72a6e6b135f/xxhash-3.8.1-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:36fc69160465ae75c6ec4ac9f781bb2aa16ae7ff869e73c26fee85fbb11b9887", size = 240820, upload-time = "2026-07-06T10:45:00.746Z" }, + { url = "https://files.pythonhosted.org/packages/da/14/d39d565069b87e86d21a2af2a31d04db79249d25aa8d5b62959056a89857/xxhash-3.8.1-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:445e0f5a31f2f3546ae0895d4811e159518cdc9d824c11419898d40cfadb677e", size = 300619, upload-time = "2026-07-06T10:45:02.716Z" }, + { url = "https://files.pythonhosted.org/packages/13/22/75467acc887edc8cf71c97ab1708feb3df7a88bda589b9f399765c6387d2/xxhash-3.8.1-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:dfe0580fbfd5e4af87d0cc52d2044f155d55ebd8c8a93568758a2ea7d8e15975", size = 443267, upload-time = "2026-07-06T10:45:04.653Z" }, + { url = "https://files.pythonhosted.org/packages/a4/b6/1da3baa5fa6ef705e3425fddd382be7dfc4dfba2686df90a20f16e9c7b1b/xxhash-3.8.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:095e1323fa108be1292c54c86da3ef3c7a7dc015b105a52133973bc07a6ad11a", size = 217338, upload-time = "2026-07-06T10:45:06.304Z" }, + { url = "https://files.pythonhosted.org/packages/78/dd/b5295a9f97484e7a1c2b283a742ca45e3104991c55a1ef670dde161829ba/xxhash-3.8.1-cp312-cp312-win32.whl", hash = "sha256:bf28f55e427e0483acb1f666bd0d869b6d5e5a716680c216ad7befe3d4cfba2e", size = 31970, upload-time = "2026-07-06T10:45:07.823Z" }, + { url = "https://files.pythonhosted.org/packages/ec/31/3fa0b807d7e21515cd975e7fe5c039d52ac3e9401a96d6ad68dae6305215/xxhash-3.8.1-cp312-cp312-win_amd64.whl", hash = "sha256:2256e80e4960ee282f63428adb349cb7f8bd8efe4db770d88eb815f4b9860724", size = 32741, upload-time = "2026-07-06T10:45:09.42Z" }, + { url = "https://files.pythonhosted.org/packages/b8/05/86feada74e239600e6875aa507afb40482a89b92700aa74a92da83bdcb77/xxhash-3.8.1-cp312-cp312-win_arm64.whl", hash = "sha256:9df56e6df96a60590935e22373041cccc91fd55858763dcffb55bf63b3a2b396", size = 29234, upload-time = "2026-07-06T10:45:10.809Z" }, + { url = "https://files.pythonhosted.org/packages/6b/8c/446bb782cd0d27007a917b5569a08dd73219c3e8d6e459014db104b27bdb/xxhash-3.8.1-cp313-cp313-android_21_arm64_v8a.whl", hash = "sha256:3c682fcd96eb4bf64be32a4d95f96107e1588005831bd8a741b324fdda01b913", size = 38562, upload-time = "2026-07-06T10:45:12.425Z" }, + { url = "https://files.pythonhosted.org/packages/d7/ec/c0c45627eaa6be7a5d6117423adf8f7a15b17ee74b4b17072cca5959a225/xxhash-3.8.1-cp313-cp313-android_21_x86_64.whl", hash = "sha256:036a024d8b9c01f70782e09ed98d532e76fd23f950ae7154bd950fe94e90ebec", size = 36656, upload-time = "2026-07-06T10:45:13.932Z" }, + { url = "https://files.pythonhosted.org/packages/f6/94/8324c04cc7597154caaeba6c094e01fbd2e7601d01e7a13eea9f5420e77b/xxhash-3.8.1-cp313-cp313-ios_13_0_arm64_iphoneos.whl", hash = "sha256:d6a5c0bce213b23b0166fe0d35bcbbe23ce4b968f257cc7eb6fd57cb8e1e6297", size = 31169, upload-time = "2026-07-06T10:45:15.687Z" }, + { url = "https://files.pythonhosted.org/packages/40/a4/beb6bb26e1184e126dbe7a5682330214ef54dcfbf882078aa9f4b5428d42/xxhash-3.8.1-cp313-cp313-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:5177aa44eddaa97c6ef0cc00c6d540edb64d51781d2f8fb941612ec61a92c9ed", size = 32177, upload-time = "2026-07-06T10:45:17.035Z" }, + { url = "https://files.pythonhosted.org/packages/56/0f/fc4c92a5a528f839b34b6419b2e53c8597f2a629d5a1f5d721f65bfa1fd6/xxhash-3.8.1-cp313-cp313-ios_13_0_x86_64_iphonesimulator.whl", hash = "sha256:7801b7223db017b9c0c9ccf37e44524edb35a1544a1c032add22c061c6af0276", size = 34642, upload-time = "2026-07-06T10:45:18.39Z" }, + { url = "https://files.pythonhosted.org/packages/d4/58/edbfb141d4000767ac6a9694f8ac0763e2c2e983e65c9e31620ba56e2667/xxhash-3.8.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:9e80238259655bf69d7bcd08226a970d7f42605f3157786bfa76dd13472d7fa0", size = 34684, upload-time = "2026-07-06T10:45:20.033Z" }, + { url = "https://files.pythonhosted.org/packages/07/3f/5072f1f0f5714186f0ac2a0b5a4929ce30d4b845e94886b6c01b6ebda0be/xxhash-3.8.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:bcab50a389cc04d87f90092af78a6adba2ab3deca63175a3344ca83514045315", size = 32401, upload-time = "2026-07-06T10:45:21.414Z" }, + { url = "https://files.pythonhosted.org/packages/49/c7/802ea2f9c2ed59219934d6d65c470d502b1788043eae277a52af8658bda6/xxhash-3.8.1-cp313-cp313-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:a2489d3a776fa380cb8e71f54c7fda268a9baf3de9b1395093fd280f95735907", size = 220617, upload-time = "2026-07-06T10:45:23.234Z" }, + { url = "https://files.pythonhosted.org/packages/99/a8/e10488efd31fcb13fcd6acbc6e788f10c6f8e3a0cc4ae3eb89dc19c55a12/xxhash-3.8.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:32ab1e5432690276e71192be7401b55f96db2d0eedea5d44eb1f164505669cc0", size = 241295, upload-time = "2026-07-06T10:45:25.364Z" }, + { url = "https://files.pythonhosted.org/packages/18/cc/14180b17d44892a631f8ae7323c30bfbb1328efc8209e528a480293528ac/xxhash-3.8.1-cp313-cp313-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:b30e01a0b97a4bc3f519a4d7a82da3dc53251fb0de5eeea8660dcd4ff094c0c2", size = 264688, upload-time = "2026-07-06T10:45:27.09Z" }, + { url = "https://files.pythonhosted.org/packages/a9/72/a14019d0c5f6c41ee407a503036ae32787c91325ca218a96a9b5627be651/xxhash-3.8.1-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:1f44275ddb0978b67a58a951501903f04d49335a91f7681c9ce122ecb8ccb329", size = 242740, upload-time = "2026-07-06T10:45:28.753Z" }, + { url = "https://files.pythonhosted.org/packages/68/08/92550e556c6fcfcb96c6a336945eb53a431ed43120ed749636debb16c5cf/xxhash-3.8.1-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:e3b87cbd974512c0c5fc7b469c36b2cdc9ee6d76e4ec78bccb2c7184611c49b0", size = 473599, upload-time = "2026-07-06T10:45:30.524Z" }, + { url = "https://files.pythonhosted.org/packages/29/83/e361d3c1acd1b21e1d489616de6fa4aaf843365d8179f612e3743eac20a9/xxhash-3.8.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:98ee81b4b7f3023c9cb04a78cc67610baffcb5812d92f2096cb5a5efc6f19437", size = 220559, upload-time = "2026-07-06T10:45:32.979Z" }, + { url = "https://files.pythonhosted.org/packages/05/01/006a4243c2c2a6831827f9999f6d1c23feeef100eb023c1f886022a00bf3/xxhash-3.8.1-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:2666f059a1588a99267e33605365ed89cea92f424b3522806a9f4bd8ad2e3d62", size = 310383, upload-time = "2026-07-06T10:45:35.875Z" }, + { url = "https://files.pythonhosted.org/packages/d8/20/af388e8bf9f9a0f89eeef7d2a1935d176ee1c20bc6adeda05035879379cf/xxhash-3.8.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:b0093cf7eeb91b84776e8742113afa4bdf47533d36cf719179aaaf1f56f6f8bf", size = 238228, upload-time = "2026-07-06T10:45:38.02Z" }, + { url = "https://files.pythonhosted.org/packages/63/6b/4666579a87eebd1744663c404297355fa0658617b015cedfa58810ee7036/xxhash-3.8.1-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:3a800912a2e5e975d4128969d645c4a2a80aa886ccd6c9b1c6f44529e327e8cf", size = 269137, upload-time = "2026-07-06T10:45:39.954Z" }, + { url = "https://files.pythonhosted.org/packages/de/d3/e963a8a46f900a137d91b02144d8ea07a8f812971b138204a3b2f8b8e55c/xxhash-3.8.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:0fe37f72a207223d22a4eddc3149d4298993385aa9daef25c039246ca5a309f3", size = 225068, upload-time = "2026-07-06T10:45:41.718Z" }, + { url = "https://files.pythonhosted.org/packages/aa/80/9d181dbcde4b0fe48375f48833a5832d4b8cd2b349b15110c92ee472d874/xxhash-3.8.1-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:5db43f249b4be9f99ef4b967863f37094fb40e67effafb78ba4f0356b6396104", size = 240874, upload-time = "2026-07-06T10:45:43.414Z" }, + { url = "https://files.pythonhosted.org/packages/39/15/ce3ab5a1cd27ead25a5196e55a7284220f6ad6e316da494ffd900b2b600f/xxhash-3.8.1-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:c4ed42965c2cd9081f011be22f69d0e65d3b6165fe7734072fd0c232840bbd4e", size = 300702, upload-time = "2026-07-06T10:45:45.135Z" }, + { url = "https://files.pythonhosted.org/packages/96/c0/2281a8ab5f2a62dbf57a23c58a01ccc1d98abf40f71193c8a81f59e759b5/xxhash-3.8.1-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:3557bec8fcb11738a8920eeb68974bc76b75262f6947998d3147954ce0a4b893", size = 443351, upload-time = "2026-07-06T10:45:47.188Z" }, + { url = "https://files.pythonhosted.org/packages/81/2e/071a58c1a53a52d4f7a3aa0987be0c396dffd40da8204805fe1b130a81f4/xxhash-3.8.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:00de40f3b42240db23a82a5c682b55d7263d84a26a953240c1aee463409660e3", size = 217396, upload-time = "2026-07-06T10:45:48.925Z" }, + { url = "https://files.pythonhosted.org/packages/68/44/36ab58134badd9d3433fc7b53c4ca8d113d8e807782885628640f8297a4d/xxhash-3.8.1-cp313-cp313-win32.whl", hash = "sha256:b5196cc2574cfec572a5f3fb7cfa5ade27305ae3d06516a082132441aff4c83a", size = 31974, upload-time = "2026-07-06T10:45:50.591Z" }, + { url = "https://files.pythonhosted.org/packages/96/2a/2a0b84798448e766f7b89ceed073cb0cb5a43fc9ebbacbdea74a38de18e3/xxhash-3.8.1-cp313-cp313-win_amd64.whl", hash = "sha256:538f5f865df6cd8c32dd63158a0e5b4f5dd08d732a7da8b7228a5a0776c8ce55", size = 32739, upload-time = "2026-07-06T10:45:52.221Z" }, + { url = "https://files.pythonhosted.org/packages/d4/60/bb51dbf7c363ff88a7cbd50b7959718219577ef44d7cf255929ffc4a2194/xxhash-3.8.1-cp313-cp313-win_arm64.whl", hash = "sha256:a6617f30641ba0d8baa1635fbefb1dffc5165ec36d26921bd5cee13497cd937a", size = 29239, upload-time = "2026-07-06T10:45:53.714Z" }, + { url = "https://files.pythonhosted.org/packages/56/d3/827ca123c2ee5443a6aaed3c5dd199237dc2f010e2bebd7ec09ef36f3a5f/xxhash-3.8.1-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:bfcd82852c62a60e314670a9602de354c4460f8adad916e2e42a20860c7870bc", size = 34964, upload-time = "2026-07-06T10:45:55.535Z" }, + { url = "https://files.pythonhosted.org/packages/05/67/67ae2a3ccdeb8b8ef025d35aee9edd1d26c3abe5051d47da9286232afbf8/xxhash-3.8.1-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:08ea2081f5e88615fec8622a9f87fbe21b8ea58d88cfc02163ca11026ee62a92", size = 32697, upload-time = "2026-07-06T10:45:57.288Z" }, + { url = "https://files.pythonhosted.org/packages/38/5a/3d3994346e1f45493679cb5c1ffc2bf454e410e9d1e8a662d253becee91e/xxhash-3.8.1-cp313-cp313t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:2e32855b6f9e5b18f449e59d45e3d5778bdeb660632ef2693cca267a11246c75", size = 225954, upload-time = "2026-07-06T10:45:58.897Z" }, + { url = "https://files.pythonhosted.org/packages/3f/2c/53169270309b7cd8e05504e07fe123bac053b89d00ac63617faacf0a2ec0/xxhash-3.8.1-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a6e088bd7870775624256a0d84c2a6714afd223b2eeb56b0ca58398e52a32fda", size = 249776, upload-time = "2026-07-06T10:46:00.977Z" }, + { url = "https://files.pythonhosted.org/packages/70/e0/5c551d8d592f944506f7c5185e210255c15e672a3c6008c156a1bd9b775e/xxhash-3.8.1-cp313-cp313t-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:72eb5ae575cc7ae2b23f6f8064a8b10f638c7149819ae9cc6d20ebd4d37a1629", size = 274776, upload-time = "2026-07-06T10:46:02.869Z" }, + { url = "https://files.pythonhosted.org/packages/a0/2a/d3a762270cee2d7bcd0e25e28c623e5f3f5c0dc637b66e3e47dd5b0bb3f0/xxhash-3.8.1-cp313-cp313t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:d0b48cdf690a64cedf7258c3dc9506cc41fc86edd7739c40e3098952265dc068", size = 252056, upload-time = "2026-07-06T10:46:04.688Z" }, + { url = "https://files.pythonhosted.org/packages/c1/8f/b78e4373b2cb6d1c42af60ea2d7e9146ad0710b239ac7f706d5d31d5bb98/xxhash-3.8.1-cp313-cp313t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:fb9e256a357dfcede7818c6d34e70db2d6b664394803d1de4b6984d2de76c0f1", size = 482108, upload-time = "2026-07-06T10:46:06.498Z" }, + { url = "https://files.pythonhosted.org/packages/e6/0d/642d923336ea61a15f8ce64fc7e078729e6e06c3a026e517fa79b2c23b7a/xxhash-3.8.1-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:51f71a6e2ad071e70c937e41fcb6c19f82c3f9f49831eba850ed4a106ffbb647", size = 226739, upload-time = "2026-07-06T10:46:08.598Z" }, + { url = "https://files.pythonhosted.org/packages/a6/0a/a37d6da6427d45a8d23e3ee3a0ca9c9d4a90364849c6637fe2963a755f9b/xxhash-3.8.1-cp313-cp313t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:e4a6443968c4e8dc69967e12776776a5952c119cc1bd94168ad1c5ad667c2be1", size = 319658, upload-time = "2026-07-06T10:46:10.504Z" }, + { url = "https://files.pythonhosted.org/packages/4a/51/ebbd40da8a3f1bc53b4b7a9a87f8e28bd95c5f21bc14b8a57860cf367d1b/xxhash-3.8.1-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:714503083a1f2065c9ad15340dd49ac8a8e948a505a705ffa1750cb951519113", size = 246059, upload-time = "2026-07-06T10:46:12.634Z" }, + { url = "https://files.pythonhosted.org/packages/24/4c/d9014030147e1f0bb26e7da47aa240dd9ec61c763c573e558111d869f8e1/xxhash-3.8.1-cp313-cp313t-musllinux_1_2_armv7l.whl", hash = "sha256:77f74e45a1e5574bbbf80181c8027b3a4c65c2248fffbd557bd596fff13102f9", size = 275535, upload-time = "2026-07-06T10:46:14.614Z" }, + { url = "https://files.pythonhosted.org/packages/84/86/caee2db41fadcd5a25aa4323213f9afec5a8586d4e419241e3d659362bd7/xxhash-3.8.1-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:4e0e1b0fb0259c1b75d1251ac0bb4d7ab675d36f7a6bf4ba6aa630dae94f9ffa", size = 231292, upload-time = "2026-07-06T10:46:16.452Z" }, + { url = "https://files.pythonhosted.org/packages/0b/60/f52f08bcdc904c4514ea5c25caa19e9f3214144434a6ff96dc82dc1cbddd/xxhash-3.8.1-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:10e4393ec33633c2f05ad01869e546ad080b1a18f2650503731f153774608b31", size = 250490, upload-time = "2026-07-06T10:46:18.318Z" }, + { url = "https://files.pythonhosted.org/packages/24/a0/94dc7ae310838f250669c6ad7168e6d6fca17d49dac1053f06dc232c4a56/xxhash-3.8.1-cp313-cp313t-musllinux_1_2_riscv64.whl", hash = "sha256:b3ba794c3d885803db6c3116686923f1ec13bc86e621e169a375282b63ea1cc6", size = 309861, upload-time = "2026-07-06T10:46:20.503Z" }, + { url = "https://files.pythonhosted.org/packages/8b/f9/adeead7d0eb28cdfc2832544ea639ffbc6749ccde47a8e228d667459182e/xxhash-3.8.1-cp313-cp313t-musllinux_1_2_s390x.whl", hash = "sha256:57189a69c0891e4818853feaa521c972d22c880a001453addea015f48e3c3398", size = 448739, upload-time = "2026-07-06T10:46:22.79Z" }, + { url = "https://files.pythonhosted.org/packages/04/a4/22ec0e07db57d901c9298ae98aa3cf2be45bafded6f07c13131e85b89032/xxhash-3.8.1-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:d59e71153fe9ff85648d00e18649b07e9b22c797291abb7e27274fa06df8b838", size = 223657, upload-time = "2026-07-06T10:46:24.831Z" }, + { url = "https://files.pythonhosted.org/packages/94/32/8a9531f37b59e5a013003db7cb7414baf4ce7e0e1268e0d5947cd3d6a2df/xxhash-3.8.1-cp313-cp313t-win32.whl", hash = "sha256:5b96f0024e9840f449bd91b2d005c921a4b666055a0d1b6492463799f32aae22", size = 32377, upload-time = "2026-07-06T10:46:26.86Z" }, + { url = "https://files.pythonhosted.org/packages/e7/ab/2ca45fd7f671de5f81fc297ef1c95080b40c86ec6be0cc6034b8f7707ac8/xxhash-3.8.1-cp313-cp313t-win_amd64.whl", hash = "sha256:37d5a56c36dcc0b9a87b814cd992598d33863ff683749de6c86081f278d5e629", size = 33274, upload-time = "2026-07-06T10:46:28.39Z" }, + { url = "https://files.pythonhosted.org/packages/5a/54/20d7163463ddb6438b73a427d1655a77a502cf9b9b0c3ada3599629d9c0a/xxhash-3.8.1-cp313-cp313t-win_arm64.whl", hash = "sha256:6696c8752aded28ff3b16f33ef28ce28fb5d209b80c206746f943199fcf5fd65", size = 29375, upload-time = "2026-07-06T10:46:29.962Z" }, + { url = "https://files.pythonhosted.org/packages/c2/8b/df2ba04f22a6cd6b39f96a6577329a8471a55c90ef8d8e2f7c102363613f/xxhash-3.8.1-cp314-cp314-android_24_arm64_v8a.whl", hash = "sha256:9db455cb649dcfe4504d6d68a6d83a7315a99a3ca59871dc3ff840671f99adba", size = 38430, upload-time = "2026-07-06T10:46:31.496Z" }, + { url = "https://files.pythonhosted.org/packages/b2/4f/6a059e8ad3ca8deedc91dfe335b211204900895152212c03ebbe721de68b/xxhash-3.8.1-cp314-cp314-android_24_x86_64.whl", hash = "sha256:affb37f152e55b5e4494bb9d0107f7bb08515c6704fbed82d9f61214d74adc17", size = 36558, upload-time = "2026-07-06T10:46:33.078Z" }, + { url = "https://files.pythonhosted.org/packages/cb/95/40be178205acce092ae418feb20ac737b32a02c7b864926ed0717354c9f8/xxhash-3.8.1-cp314-cp314-ios_13_0_arm64_iphoneos.whl", hash = "sha256:460261045936975193bfd20549a0de1cd52a33b405cbb972f0d80940c42266cd", size = 31181, upload-time = "2026-07-06T10:46:34.793Z" }, + { url = "https://files.pythonhosted.org/packages/3f/89/2da4dbf051bafa156c0e3f12012db2b0ac3b84ff37ca1f021f6bfffcdfbb/xxhash-3.8.1-cp314-cp314-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:38c887aedb696ef8bca19983206d270848558cfae4a91afa6a2fb05dde58ffc5", size = 32192, upload-time = "2026-07-06T10:46:36.393Z" }, + { url = "https://files.pythonhosted.org/packages/7c/4e/e000bbae3566bc8e0be771a8a0f294aa99075e3f0bc4ef43922ebffdebc8/xxhash-3.8.1-cp314-cp314-ios_13_0_x86_64_iphonesimulator.whl", hash = "sha256:594131ce1aad18db3689781f806db1b065cdaa04f4df36b4c038d2013aefd0bf", size = 34691, upload-time = "2026-07-06T10:46:38.1Z" }, + { url = "https://files.pythonhosted.org/packages/b4/4a/ea954aacc7d1c8711880ac2b55da94429a9b4296b151c4fc0966549ca1ee/xxhash-3.8.1-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:78c794b643d214f1522e7a288bcf5a2de120d26cd170516749a4009dc92722c9", size = 34807, upload-time = "2026-07-06T10:46:39.647Z" }, + { url = "https://files.pythonhosted.org/packages/ca/29/df598e738ff37558ac627264deb2e560902d9bf7f46d3bd5175c9eee593e/xxhash-3.8.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:af0c9fedc4a2c24e8664953882fe8185f3790b8338c9c700f76f5ad660817711", size = 32410, upload-time = "2026-07-06T10:46:41.359Z" }, + { url = "https://files.pythonhosted.org/packages/59/9c/81ab40e7d33ada0b3df5d1bc884894d15dbf4f805cd645b685e4606bb8e0/xxhash-3.8.1-cp314-cp314-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:115772daeb71b2f3b9381177017f53e6cf3f3439c840737fdabd21aba6e54920", size = 220564, upload-time = "2026-07-06T10:46:43.463Z" }, + { url = "https://files.pythonhosted.org/packages/fd/6f/62ae6f5c8606320a0e2a41c2dc8c6d91cc5d63d0f84dd9582e9543779dd8/xxhash-3.8.1-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:000435984a0469b0f822fe76f35bddea0f96a4d6521b3339a60a6428cdee1edc", size = 241462, upload-time = "2026-07-06T10:46:45.509Z" }, + { url = "https://files.pythonhosted.org/packages/15/a1/9c3a0ec6cb524396f551eddd102a76690a795494eb9784fc67542b0daa37/xxhash-3.8.1-cp314-cp314-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:2f1c68394818e0595569c2ff3cbc1e6d5a36a434e796f5c526b987b80c8a8c62", size = 264491, upload-time = "2026-07-06T10:46:47.655Z" }, + { url = "https://files.pythonhosted.org/packages/64/f2/700a4674e4308eb59d2fdb973977e82eae231bea5044753fee5c9eec0e0c/xxhash-3.8.1-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:46b39976d008e2a845758650f0ff7136bca004f40da0c8798bd37ac37860154f", size = 242905, upload-time = "2026-07-06T10:46:49.857Z" }, + { url = "https://files.pythonhosted.org/packages/f3/8a/72d9874375c8d4cbc64a8cd1d659d5695a8765c3db82efa82dc5bd9f14d0/xxhash-3.8.1-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:d5006c65ec507a333479e76e00e2c368781f16c24ededa764763956b32a0e93e", size = 473873, upload-time = "2026-07-06T10:46:51.953Z" }, + { url = "https://files.pythonhosted.org/packages/03/f0/6db07590ed7e0a77f186ef0bcea8d52553bf1ba57833e09467a2411f0f2d/xxhash-3.8.1-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c31a2649bcf1fe97cf11c79848d761df33ac46b3896942d31b640557b486ff6b", size = 220765, upload-time = "2026-07-06T10:46:55.41Z" }, + { url = "https://files.pythonhosted.org/packages/8f/10/00d12d8b8beabbf49a8bbc626fb9f40445145a8887eb41a6acfb69149ac4/xxhash-3.8.1-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:8f759eed402448c2bdbb492e4fba1f20668ffe29688605ea61f0f67f9e4e386d", size = 310478, upload-time = "2026-07-06T10:46:57.729Z" }, + { url = "https://files.pythonhosted.org/packages/1f/f9/12a82394eefb0f185d15a7f7b9f627c61c475a72dd83718436a5b84b42ac/xxhash-3.8.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:7b5f97ecfede10d5b2870383620e2d25c8561e217c7bf9081073802b54248d2b", size = 238393, upload-time = "2026-07-06T10:46:59.87Z" }, + { url = "https://files.pythonhosted.org/packages/20/f3/53f963e320b9ce678337aa7273f39ce692ded8b99e3d22a866ec722159ab/xxhash-3.8.1-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:1da930bbcac3e8fbe2191850e2abb57977a99348c12c4b385e1058ac1b0a9ecc", size = 268704, upload-time = "2026-07-06T10:47:01.806Z" }, + { url = "https://files.pythonhosted.org/packages/0a/50/5b5badbd87c82d9f9b5f58ac74a3f29ef08f6fc387b324b8fd482450b862/xxhash-3.8.1-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:747476436f6891b9773374ce8d48edcc8b12cb5b61b67c6fb6289633747d088f", size = 225015, upload-time = "2026-07-06T10:47:03.784Z" }, + { url = "https://files.pythonhosted.org/packages/30/93/3ca68265afe7b4e69435e08a7b6a1d9d0f2a071e889da1f8041ed00fe878/xxhash-3.8.1-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:4ef09bbc2519a93cd0f95f2ceb5f7b85919dffea643278e02362bf40e3c4bed1", size = 240951, upload-time = "2026-07-06T10:47:05.816Z" }, + { url = "https://files.pythonhosted.org/packages/dd/a6/27e19670c40f46b5e76e11f2f4713d21054804568425d870670e757172ad/xxhash-3.8.1-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:a5eed9d41995a83f3332b4e3396abb7f433cac584222bd7e305b606d8353861e", size = 300751, upload-time = "2026-07-06T10:47:07.95Z" }, + { url = "https://files.pythonhosted.org/packages/bc/fb/b33e27689959fe7ed2ae0b830af41560d65213943983afa9db3a8d481bce/xxhash-3.8.1-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:53f3ed9118397074ff63a79b66b7fec1c84c782eecde35c5bc94e420a971c231", size = 443480, upload-time = "2026-07-06T10:47:10Z" }, + { url = "https://files.pythonhosted.org/packages/26/60/0e0d973be5fe280753ef02fbc89349492ad6e903bf1dcb870b668f94b662/xxhash-3.8.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:d247b34bf433c92b41689318fd25d246313cab2275a6a47e2efac178b80d6efe", size = 217657, upload-time = "2026-07-06T10:47:12.196Z" }, + { url = "https://files.pythonhosted.org/packages/ad/68/c9e3ecef4a9a417d464cb5bd200aa12f73192dee677901b9e08e0ad0d1bb/xxhash-3.8.1-cp314-cp314-win32.whl", hash = "sha256:d58ce8b6cfa9c4d2f230557f69caf7c06369e318015d0b19485095bc2c5963ab", size = 32690, upload-time = "2026-07-06T10:47:14.204Z" }, + { url = "https://files.pythonhosted.org/packages/d7/99/e9e44588c0b62837bbec5ba7927816de0afa03406b1a0b6c7a7e1d1a30a0/xxhash-3.8.1-cp314-cp314-win_amd64.whl", hash = "sha256:6cee733fe4ccb1737e0997135283c82341e5cfa9cf214b165f9087fb663aaf4f", size = 33460, upload-time = "2026-07-06T10:47:16.021Z" }, + { url = "https://files.pythonhosted.org/packages/45/2b/64f36d86380b3657ad9031967ab814f3ef31307174650853f69c18932ebc/xxhash-3.8.1-cp314-cp314-win_arm64.whl", hash = "sha256:58346024d47e84f7d8b3e7f5d6faa1d58acbbe49a8771497872059f58c1d8ea5", size = 30092, upload-time = "2026-07-06T10:47:17.81Z" }, + { url = "https://files.pythonhosted.org/packages/92/cb/18b64bff88c58a0ca209dc533e63cf02d7ae5aa6b1b9a9fd14e81b5dbd60/xxhash-3.8.1-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:01cab782f8a0a05ecad2c63d7ef10f7ab475f660e0d6419d069418c14d88de7c", size = 35024, upload-time = "2026-07-06T10:47:19.821Z" }, + { url = "https://files.pythonhosted.org/packages/af/1d/72d8a70520e5dcddb472ea0486d299da3240745a10658290cd7b5690ede2/xxhash-3.8.1-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:717b12fdc51819833704e85e6926d76981ffa3f780ef92e33ebb8b26d46bb230", size = 32697, upload-time = "2026-07-06T10:47:21.649Z" }, + { url = "https://files.pythonhosted.org/packages/9c/b8/e041f555903c56db3d0a731b3d72a6575d75e0ed868b1bd2e5176111ca44/xxhash-3.8.1-cp314-cp314t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:ec55d80e9b8a519d742669e0b49e8ce9e6747be42bf3c138158b6543a9c8e489", size = 226044, upload-time = "2026-07-06T10:47:23.612Z" }, + { url = "https://files.pythonhosted.org/packages/3a/7e/5cdcf06bf6ec4b5d2ac073feb23432ec1d603fd438864cbd2c09c7cb45e1/xxhash-3.8.1-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:98d8ac1129b4dd39098cffed94d1284aceb61c3aa396757ccc736ac392e4cee5", size = 249899, upload-time = "2026-07-06T10:47:25.812Z" }, + { url = "https://files.pythonhosted.org/packages/c0/c0/eb7e059cb5e1dba11fd30d2fdf882f56e5a417a3eaa43669d43623767f45/xxhash-3.8.1-cp314-cp314t-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:3bc0fa90830df1e1277f33cc6e55de9990b83c0319fd8c7412866cfde38b025e", size = 274892, upload-time = "2026-07-06T10:47:27.931Z" }, + { url = "https://files.pythonhosted.org/packages/66/74/a600aaf7cd39957fd1510adeedb1749c1e7eb82bd632a1153d9c664c3135/xxhash-3.8.1-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:c73b6f652f0745425aa6378319c331293b5341756262e9408ed3d45f183375e6", size = 252243, upload-time = "2026-07-06T10:47:30.288Z" }, + { url = "https://files.pythonhosted.org/packages/ad/04/78d88fa75a6763e5d09bf1b947a392a27988903381b219006f92f3c68fc8/xxhash-3.8.1-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:f6114692261eff4266386cdec0f7d87eee24e317ab397c218b7ae6a76b4c6339", size = 482191, upload-time = "2026-07-06T10:47:32.45Z" }, + { url = "https://files.pythonhosted.org/packages/7f/06/07a8aea1108d682de8791ce608cdf367d75ff4e7e57cd3c154bdc6f47b23/xxhash-3.8.1-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4df57c0b161ec1b3ed0526a67b0db0914b557e86ee8aae51887aec941b261542", size = 226877, upload-time = "2026-07-06T10:47:34.705Z" }, + { url = "https://files.pythonhosted.org/packages/ed/b5/86bade5618a524d2c06c4041aa2fe8e5749ce16e88afba60d67c1684a21f/xxhash-3.8.1-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:9043877a917be88ccf230aa5667c1bd059bce80f4c2727e4defa1b29b7f48b08", size = 319794, upload-time = "2026-07-06T10:47:37.08Z" }, + { url = "https://files.pythonhosted.org/packages/23/69/9b1a2b89b1621bb740fbcb7beb512f60f99480c1bdc680c0c90e1f56ff75/xxhash-3.8.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:559e3cabe522231909f9de98ef06929edbd53782046bd21aae0c72db6f2a0775", size = 246202, upload-time = "2026-07-06T10:47:39.676Z" }, + { url = "https://files.pythonhosted.org/packages/08/ea/662ed6cb49f1d34078b6a3a3e0f3d29ff93fd7b5a03c0bc9ecfd9b2159c3/xxhash-3.8.1-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:264710bd335016f303763ce1275c6486df30bb57c2245c91b224c983d7ac39b8", size = 275628, upload-time = "2026-07-06T10:47:41.99Z" }, + { url = "https://files.pythonhosted.org/packages/13/f5/49fc9e4c6728a5a3bd8fe639199d2fa67609b3a84f938aff6e8568dd3e4f/xxhash-3.8.1-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:e14800b9b10bb39d7a60ad4a310e403164d7b8988a27ae933d4e40618a44088e", size = 231390, upload-time = "2026-07-06T10:47:44.233Z" }, + { url = "https://files.pythonhosted.org/packages/64/9d/3acaf8f599c0e0b30e910a3a11ba32929da53c86dc73c7c55fe6a010b4e9/xxhash-3.8.1-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:ea6a3e734b0fd41b82784a400be946821900daebe610c050a5e0760838a34f99", size = 250600, upload-time = "2026-07-06T10:47:47.611Z" }, + { url = "https://files.pythonhosted.org/packages/23/64/8acab4c5ec60dbe664b5b9858fd44c2413b07e535b09556a0a5022e78aa6/xxhash-3.8.1-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:cf399fac542a1c7a4734a435b93df2c55e858c7d31abf6c1bdf46f9ae67fbfd0", size = 310032, upload-time = "2026-07-06T10:47:49.88Z" }, + { url = "https://files.pythonhosted.org/packages/56/47/a0288d7329b1fe63e2734a32d19d444a96ae2b4810f545bc61e561224917/xxhash-3.8.1-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:44c89d915a75c11d2547eaee9098fcd80398987c4bff2974a0497a925bf92c07", size = 448882, upload-time = "2026-07-06T10:47:52.631Z" }, + { url = "https://files.pythonhosted.org/packages/01/e7/3071dfd3beb5c38204ce1cf56bf7749fce08de900fa92714b81d1d8ca1f2/xxhash-3.8.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:358650d5bda9c635da699c53adf4e8134af492ecc79c960f917eebf088bb6799", size = 223728, upload-time = "2026-07-06T10:47:55.093Z" }, + { url = "https://files.pythonhosted.org/packages/12/11/b99949f0ba2b07e9f9ffe83b9c86faa685f9080725dc21a916a607313be5/xxhash-3.8.1-cp314-cp314t-win32.whl", hash = "sha256:c240939e963653054fc7e4a17c382829cda4aa88a7daf0af841715dbded1b497", size = 33150, upload-time = "2026-07-06T10:47:57.274Z" }, + { url = "https://files.pythonhosted.org/packages/54/1c/09703eb341f8416e74e58d6c6732d4b5c46de59c942363203cb237cc95b0/xxhash-3.8.1-cp314-cp314t-win_amd64.whl", hash = "sha256:7258ee276e8772599bc19e14b36f6260306e21b637190cd7cb489a2449d48684", size = 34005, upload-time = "2026-07-06T10:47:59.434Z" }, + { url = "https://files.pythonhosted.org/packages/d6/f9/6ed7251bb6a8af10ac73b1821c60583d2826e5b2064e45a979c935287c98/xxhash-3.8.1-cp314-cp314t-win_arm64.whl", hash = "sha256:8f454166c2ffed45636c8d501741e649851ba2f346c4eb73a64c07ac00428f20", size = 30239, upload-time = "2026-07-06T10:48:01.874Z" }, + { url = "https://files.pythonhosted.org/packages/99/e4/4d8040435aeac814fc69ba63621565fbeb19229a138e2568324a26b2a45c/xxhash-3.8.1-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:39c9d5b61508b0bb68f29e54546de0ed2a74943c6a18585535a7e37356f1dd12", size = 32687, upload-time = "2026-07-06T10:49:42.803Z" }, + { url = "https://files.pythonhosted.org/packages/da/6a/975f1f2318c760e5bcec109ed379713ae645d8d856c2a3b9ec5d26857087/xxhash-3.8.1-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:83b9130b80b216d56fdf9e87131946b353c9627930c061955a101ea82b09fed9", size = 29879, upload-time = "2026-07-06T10:49:45.172Z" }, + { url = "https://files.pythonhosted.org/packages/08/0b/40a2a55ff52cf635bfdc5eae67a772bec85b4f44c6c737f73f6f528d51d1/xxhash-3.8.1-pp311-pypy311_pp73-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:8304be0982130954b7fd3aad18e2c6f8ee40254bc3d2e635991c16d77c91e2bd", size = 43246, upload-time = "2026-07-06T10:49:47.905Z" }, + { url = "https://files.pythonhosted.org/packages/9c/6d/56ed2b6b200f26fb474f3fd387d95d0601efcd5bb33430c90c68924bdd77/xxhash-3.8.1-pp311-pypy311_pp73-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4b512261801b1e5fde7b6ebf2fef7977339c620cbbca88a0040ad9ad134f4d02", size = 38202, upload-time = "2026-07-06T10:49:50.59Z" }, + { url = "https://files.pythonhosted.org/packages/0d/a3/56864d895d1161a9f17502088e9c1fb7c06bde2c2efdde620d22bb7a9c43/xxhash-3.8.1-pp311-pypy311_pp73-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:49aa8692507835dcc1e8ad8021f20c74c2dc13d83b5112e87877faa2a0035b20", size = 34448, upload-time = "2026-07-06T10:49:53.242Z" }, + { url = "https://files.pythonhosted.org/packages/6b/57/5c6e0908a47f61dca96d01c8ee6fce01ed1050611eb779083ba8758fed81/xxhash-3.8.1-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:345b07b78e2bf583d71682aa34ae5b5fab575f7a1cb31e10263ebbc6f89f8c42", size = 32869, upload-time = "2026-07-06T10:49:55.972Z" }, ] [[package]] From 1295930b7f2445ad8b92a257e84f354a829fe534 Mon Sep 17 00:00:00 2001 From: Saksham Goyal <144555727+Sakshamm-Goyal@users.noreply.github.com> Date: Thu, 30 Jul 2026 23:53:34 +0530 Subject: [PATCH 198/226] test: unskip update handler cases on time-skipping server (#1697) --- tests/worker/test_workflow.py | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/tests/worker/test_workflow.py b/tests/worker/test_workflow.py index 5bb2b13e1..283357c2d 100644 --- a/tests/worker/test_workflow.py +++ b/tests/worker/test_workflow.py @@ -6726,7 +6726,6 @@ async def my_dynamic_signal(self, _name: str, _args: Sequence[RawValue]) -> None ) async def test_unfinished_handler_on_workflow_termination( client: Client, - env: WorkflowEnvironment, handler_type: Literal["-signal-", "-update-"], handler_registration: Literal["-late-registered-", "-not-late-registered-"], handler_dynamism: Literal["-dynamic-", "-not-dynamic-"], @@ -6737,10 +6736,6 @@ async def test_unfinished_handler_on_workflow_termination( "-cancellation-", "-failure-", "-continue-as-new-" ], ): - if env.supports_time_skipping: - pytest.skip( - "Issues with update: https://github.com/temporalio/sdk-python/issues/826" - ) skip_unfinished_handler_tests_in_older_python() await _UnfinishedHandlersOnWorkflowTerminationTest( client, @@ -6833,13 +6828,24 @@ async def _run_workflow_and_get_warning(self) -> bool: if self.handler_waiting == "-wait-all-handlers-finish-": await update_task else: - with pytest.raises(WorkflowUpdateFailedError) as err_info: + with pytest.raises( + (WorkflowUpdateFailedError, RPCError) + ) as err_info: await update_task update_err = err_info.value - assert isinstance(update_err.cause, ApplicationError) - assert ( - update_err.cause.type == "AcceptedUpdateCompletedWorkflow" - ) + if isinstance(update_err, WorkflowUpdateFailedError): + assert isinstance(update_err.cause, ApplicationError) + assert ( + update_err.cause.type + == "AcceptedUpdateCompletedWorkflow" + ) + else: + assert isinstance(update_err, RPCError) + assert update_err.status == RPCStatusCode.NOT_FOUND + assert ( + str(update_err) + == "workflow execution already completed" + ) with pytest.raises(WorkflowFailureError) as err: await handle.result() From 6d3ef91be156303b6b906d288e917b898b459b77 Mon Sep 17 00:00:00 2001 From: Alex Mazzeo Date: Fri, 31 Jul 2026 09:28:25 -0700 Subject: [PATCH 199/226] Use a UUID to prefix workflow IDs in test_worker_with_worker_deployment_config to avoid conflicts with running workflows in cloud. (#1705) --- tests/worker/test_worker.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/tests/worker/test_worker.py b/tests/worker/test_worker.py index b6ce37c8b..898615809 100644 --- a/tests/worker/test_worker.py +++ b/tests/worker/test_worker.py @@ -756,6 +756,7 @@ async def test_worker_with_worker_deployment_config( pytest.skip("Test Server doesn't support worker deployments") deployment_name = f"deployment-{uuid.uuid4()}" + workflow_id_prefix = f"basic-versioning-{uuid.uuid4()}" worker_v1 = WorkerDeploymentVersion(deployment_name=deployment_name, build_id="1.0") worker_v2 = WorkerDeploymentVersion(deployment_name=deployment_name, build_id="2.0") worker_v3 = WorkerDeploymentVersion(deployment_name=deployment_name, build_id="3.0") @@ -798,7 +799,7 @@ async def test_worker_with_worker_deployment_config( # Start workflow 1 which will use the 1.0 worker on auto-upgrade wf1 = await client.start_workflow( DeploymentVersioningWorkflowV1AutoUpgrade.run, - id="basic-versioning-v1", + id=f"{workflow_id_prefix}-v1", task_queue=w1.task_queue, ) assert "v1" == await wf1.query("state") @@ -810,7 +811,7 @@ async def test_worker_with_worker_deployment_config( wf2 = await client.start_workflow( DeploymentVersioningWorkflowV2Pinned.run, - id="basic-versioning-v2", + id=f"{workflow_id_prefix}-v2", task_queue=w1.task_queue, ) assert "v2" == await wf2.query("state") @@ -822,7 +823,7 @@ async def test_worker_with_worker_deployment_config( wf3 = await client.start_workflow( DeploymentVersioningWorkflowV3AutoUpgrade.run, - id="basic-versioning-v3", + id=f"{workflow_id_prefix}-v3", task_queue=w1.task_queue, ) assert "v3" == await wf3.query("state") From 646d69e12e1f9a134f3abc1eb3a9c750e5ddfe32 Mon Sep 17 00:00:00 2001 From: Alex Mazzeo Date: Fri, 31 Jul 2026 10:51:33 -0700 Subject: [PATCH 200/226] Add pytest marker to skip nexus extstore tests (#1702) * Add pytest marker to skip nexus extstore tests * Add comment explaining why nexus tests are skipped against cloud --- tests/nexus/test_dynamic_creation_of_user_handler_classes.py | 2 ++ tests/nexus/test_nexus_client_updates.py | 2 ++ tests/nexus/test_nexus_worker_shutdown.py | 2 ++ tests/nexus/test_signal_link_propagation_e2e.py | 2 ++ tests/nexus/test_standalone_operations.py | 2 ++ tests/nexus/test_temporal_extstore.py | 4 ++++ tests/nexus/test_temporal_operation.py | 2 ++ tests/nexus/test_use_existing_conflict_policy.py | 2 ++ tests/nexus/test_workflow_caller.py | 2 ++ tests/nexus/test_workflow_caller_cancellation_types.py | 2 ++ ...low_caller_cancellation_types_when_cancel_handler_fails.py | 2 ++ tests/nexus/test_workflow_caller_error_chains.py | 2 ++ tests/nexus/test_workflow_caller_errors.py | 2 ++ tests/nexus/test_workflow_run_operation.py | 2 ++ 14 files changed, 30 insertions(+) diff --git a/tests/nexus/test_dynamic_creation_of_user_handler_classes.py b/tests/nexus/test_dynamic_creation_of_user_handler_classes.py index 22c1a818b..214e02ab9 100644 --- a/tests/nexus/test_dynamic_creation_of_user_handler_classes.py +++ b/tests/nexus/test_dynamic_creation_of_user_handler_classes.py @@ -10,6 +10,8 @@ from temporalio.worker import Worker from tests.helpers.nexus import make_nexus_endpoint_name +# Cloud CI's namespace credentials cannot manage Nexus endpoints. +# See https://github.com/temporalio/sdk-python/issues/1704. pytestmark = pytest.mark.requires_local_server diff --git a/tests/nexus/test_nexus_client_updates.py b/tests/nexus/test_nexus_client_updates.py index c99822770..97dd251da 100644 --- a/tests/nexus/test_nexus_client_updates.py +++ b/tests/nexus/test_nexus_client_updates.py @@ -12,6 +12,8 @@ from temporalio.testing import WorkflowEnvironment from temporalio.worker import Worker +# Cloud CI's namespace credentials cannot manage Nexus endpoints. +# See https://github.com/temporalio/sdk-python/issues/1704. pytestmark = pytest.mark.requires_local_server diff --git a/tests/nexus/test_nexus_worker_shutdown.py b/tests/nexus/test_nexus_worker_shutdown.py index 45dfcb8ad..2a94027d5 100644 --- a/tests/nexus/test_nexus_worker_shutdown.py +++ b/tests/nexus/test_nexus_worker_shutdown.py @@ -23,6 +23,8 @@ make_nexus_endpoint_name, ) +# Cloud CI's namespace credentials cannot manage Nexus endpoints. +# See https://github.com/temporalio/sdk-python/issues/1704. pytestmark = pytest.mark.requires_local_server diff --git a/tests/nexus/test_signal_link_propagation_e2e.py b/tests/nexus/test_signal_link_propagation_e2e.py index e7906f7a5..9e51d4b93 100644 --- a/tests/nexus/test_signal_link_propagation_e2e.py +++ b/tests/nexus/test_signal_link_propagation_e2e.py @@ -56,6 +56,8 @@ workflow_event_link_event_type, ) +# Cloud CI's namespace credentials cannot manage Nexus endpoints. +# See https://github.com/temporalio/sdk-python/issues/1704. pytestmark = pytest.mark.requires_local_server EventType = temporalio.api.enums.v1.EventType diff --git a/tests/nexus/test_standalone_operations.py b/tests/nexus/test_standalone_operations.py index ed62c2387..26a8316b4 100644 --- a/tests/nexus/test_standalone_operations.py +++ b/tests/nexus/test_standalone_operations.py @@ -71,6 +71,8 @@ # --------------------------------------------------------------------------- +# Cloud CI's namespace credentials cannot manage Nexus endpoints. +# See https://github.com/temporalio/sdk-python/issues/1704. pytestmark = pytest.mark.requires_local_server diff --git a/tests/nexus/test_temporal_extstore.py b/tests/nexus/test_temporal_extstore.py index 2afbac44c..f23a69259 100644 --- a/tests/nexus/test_temporal_extstore.py +++ b/tests/nexus/test_temporal_extstore.py @@ -41,6 +41,10 @@ from tests.helpers.nexus import make_nexus_endpoint_name from tests.test_extstore import InMemoryTestDriver +# Cloud CI's namespace credentials cannot manage Nexus endpoints. +# See https://github.com/temporalio/sdk-python/issues/1704. +pytestmark = pytest.mark.requires_local_server + PAYLOAD_SIZE = 4096 PAYLOAD_SIZE_THRESHOLD = 1024 _STORE_FAILURE_MESSAGE = "external storage store failed" diff --git a/tests/nexus/test_temporal_operation.py b/tests/nexus/test_temporal_operation.py index 0d1b7d63e..b4bf235fe 100644 --- a/tests/nexus/test_temporal_operation.py +++ b/tests/nexus/test_temporal_operation.py @@ -20,6 +20,8 @@ from tests.helpers import EventType, assert_event_subsequence, assert_eventually from tests.helpers.nexus import make_nexus_endpoint_name +# Cloud CI's namespace credentials cannot manage Nexus endpoints. +# See https://github.com/temporalio/sdk-python/issues/1704. pytestmark = pytest.mark.requires_local_server diff --git a/tests/nexus/test_use_existing_conflict_policy.py b/tests/nexus/test_use_existing_conflict_policy.py index 94a3821ba..8ffa9f8f8 100644 --- a/tests/nexus/test_use_existing_conflict_policy.py +++ b/tests/nexus/test_use_existing_conflict_policy.py @@ -14,6 +14,8 @@ from temporalio.worker import Worker from tests.helpers.nexus import make_nexus_endpoint_name +# Cloud CI's namespace credentials cannot manage Nexus endpoints. +# See https://github.com/temporalio/sdk-python/issues/1704. pytestmark = pytest.mark.requires_local_server diff --git a/tests/nexus/test_workflow_caller.py b/tests/nexus/test_workflow_caller.py index f776e6e18..0c47f17c1 100644 --- a/tests/nexus/test_workflow_caller.py +++ b/tests/nexus/test_workflow_caller.py @@ -90,6 +90,8 @@ class OpDefinitionType(IntEnum): LONGHAND = 1 +# Cloud CI's namespace credentials cannot manage Nexus endpoints. +# See https://github.com/temporalio/sdk-python/issues/1704. pytestmark = pytest.mark.requires_local_server diff --git a/tests/nexus/test_workflow_caller_cancellation_types.py b/tests/nexus/test_workflow_caller_cancellation_types.py index fa39009a5..eca269984 100644 --- a/tests/nexus/test_workflow_caller_cancellation_types.py +++ b/tests/nexus/test_workflow_caller_cancellation_types.py @@ -25,6 +25,8 @@ from tests.helpers import LogCapturer, assert_event_subsequence, assert_eventually from tests.helpers.nexus import make_nexus_endpoint_name +# Cloud CI's namespace credentials cannot manage Nexus endpoints. +# See https://github.com/temporalio/sdk-python/issues/1704. pytestmark = pytest.mark.requires_local_server diff --git a/tests/nexus/test_workflow_caller_cancellation_types_when_cancel_handler_fails.py b/tests/nexus/test_workflow_caller_cancellation_types_when_cancel_handler_fails.py index 5a0970c95..44d91a7d1 100644 --- a/tests/nexus/test_workflow_caller_cancellation_types_when_cancel_handler_fails.py +++ b/tests/nexus/test_workflow_caller_cancellation_types_when_cancel_handler_fails.py @@ -30,6 +30,8 @@ has_event, ) +# Cloud CI's namespace credentials cannot manage Nexus endpoints. +# See https://github.com/temporalio/sdk-python/issues/1704. pytestmark = pytest.mark.requires_local_server diff --git a/tests/nexus/test_workflow_caller_error_chains.py b/tests/nexus/test_workflow_caller_error_chains.py index 18868288a..1012d8a94 100644 --- a/tests/nexus/test_workflow_caller_error_chains.py +++ b/tests/nexus/test_workflow_caller_error_chains.py @@ -25,6 +25,8 @@ from temporalio.worker import Worker from tests.helpers.nexus import make_nexus_endpoint_name +# Cloud CI's namespace credentials cannot manage Nexus endpoints. +# See https://github.com/temporalio/sdk-python/issues/1704. pytestmark = pytest.mark.requires_local_server diff --git a/tests/nexus/test_workflow_caller_errors.py b/tests/nexus/test_workflow_caller_errors.py index eb85155fe..0f1b6a789 100644 --- a/tests/nexus/test_workflow_caller_errors.py +++ b/tests/nexus/test_workflow_caller_errors.py @@ -42,6 +42,8 @@ from tests.helpers import LogCapturer, assert_eq_eventually from tests.helpers.nexus import make_nexus_endpoint_name +# Cloud CI's namespace credentials cannot manage Nexus endpoints. +# See https://github.com/temporalio/sdk-python/issues/1704. pytestmark = pytest.mark.requires_local_server operation_invocation_counts = Counter[str]() diff --git a/tests/nexus/test_workflow_run_operation.py b/tests/nexus/test_workflow_run_operation.py index 51032a23a..7135fde71 100644 --- a/tests/nexus/test_workflow_run_operation.py +++ b/tests/nexus/test_workflow_run_operation.py @@ -23,6 +23,8 @@ from temporalio.worker import Worker from tests.helpers.nexus import make_nexus_endpoint_name +# Cloud CI's namespace credentials cannot manage Nexus endpoints. +# See https://github.com/temporalio/sdk-python/issues/1704. pytestmark = pytest.mark.requires_local_server From 7d550c0567e916bce9c762505c7cfed2c673fea8 Mon Sep 17 00:00:00 2001 From: Alex Mazzeo Date: Mon, 3 Aug 2026 10:35:49 -0700 Subject: [PATCH 201/226] Add SAA TemporalNexusOperation handling (#1689) * Add SAA Temporal Nexus operation handling * Use newer dev server version and add SAA callbacks dynamic config * Add static type checks for sync activities * Add synthesized back link and test * Refactor nexus specific start activity request building logic into a dedicated function * Refactor the start_activity_response logic into a function as well * Add comment --- temporalio/client/_activity.py | 5 + temporalio/client/_impl.py | 18 +- temporalio/nexus/__init__.py | 2 + temporalio/nexus/_link_conversion.py | 50 +- temporalio/nexus/_operation_context.py | 112 +++- temporalio/nexus/_operation_handlers.py | 40 ++ temporalio/nexus/_temporal_client.py | 278 ++++++++- temporalio/nexus/_token.py | 27 +- tests/__init__.py | 2 +- tests/conftest.py | 2 + tests/nexus/test_link_conversion.py | 69 +++ ...ropagation.py => test_link_propagation.py} | 99 +++- tests/nexus/test_nexus_type_errors.py | 216 ++++++- tests/nexus/test_operation_token.py | 123 +++- tests/nexus/test_temporal_operation.py | 526 +++++++++++++++++- 15 files changed, 1516 insertions(+), 53 deletions(-) rename tests/nexus/{test_signal_link_propagation.py => test_link_propagation.py} (84%) diff --git a/temporalio/client/_activity.py b/temporalio/client/_activity.py index 99c9ede31..138d09dc7 100644 --- a/temporalio/client/_activity.py +++ b/temporalio/client/_activity.py @@ -309,6 +309,9 @@ class ActivityExecutionDescription(ActivityExecution): long_poll_token: bytes | None """Token for follow-on long-poll requests. None if the activity is complete.""" + raw_callbacks: Sequence[temporalio.api.activity.v1.CallbackInfo] + """Underlying protobuf callbacks""" + @classmethod async def _from_execution_info( cls, @@ -316,6 +319,7 @@ async def _from_execution_info( long_poll_token: bytes | None, namespace: str, data_converter: temporalio.converter.DataConverter, + callbacks: Sequence[temporalio.api.activity.v1.CallbackInfo], ) -> Self: """Create from raw proto activity execution info.""" # Decode heartbeat details if present @@ -409,6 +413,7 @@ async def _from_execution_info( typed_search_attributes=temporalio.converter.decode_typed_search_attributes( info.search_attributes ), + raw_callbacks=callbacks, ) diff --git a/temporalio/client/_impl.py b/temporalio/client/_impl.py index 7ba54746f..9595351f2 100644 --- a/temporalio/client/_impl.py +++ b/temporalio/client/_impl.py @@ -246,7 +246,7 @@ async def _build_start_workflow_execution_request( # inside a Nexus operation handler must forward the inbound Nexus task links # explicitly so the started callee's WorkflowExecutionStarted event links back to # the caller. - if not temporalio.nexus._operation_context._in_nexus_backing_workflow_start_context(): + if not temporalio.nexus._operation_context._in_nexus_backing_start_context(): req.links.extend(nexus_ctx._get_request_links()) return req @@ -277,7 +277,7 @@ async def _build_signal_with_start_workflow_execution_request( # If this signal-with-start is issued from inside a Nexus operation handler (but not the # nexus-backing workflow), forward the inbound Nexus task links so both the callee's # WorkflowExecutionStarted and WorkflowExecutionSignaled events link back to the caller. - if not temporalio.nexus._operation_context._in_nexus_backing_workflow_start_context(): + if not temporalio.nexus._operation_context._in_nexus_backing_start_context(): nexus_ctx = ( temporalio.nexus._operation_context._try_start_operation_context() ) @@ -587,6 +587,13 @@ async def start_activity(self, input: StartActivityInput) -> ActivityHandle[Any] input.id, input.activity_type, run_id=details.run_id ) raise + + # Apply StartActivity response elements to the current Nexus context. + # No-ops if called outside a Nexus context. + temporalio.nexus._operation_context._apply_start_activity_response_to_nexus_context( + input.id, resp + ) + return ActivityHandle( self._client, input.id, @@ -670,6 +677,12 @@ async def _build_start_activity_execution_request( # Set priority req.priority.CopyFrom(input.priority._to_proto()) + # Add request_id, links, and completion callbacks from the Nexus context + # if not in a Nexus context, this is a no-op + temporalio.nexus._operation_context._apply_nexus_context_to_start_activity_request( + req + ) + return req async def cancel_activity(self, input: CancelActivityInput) -> None: @@ -733,6 +746,7 @@ async def describe_activity( is_local=False, ) ), + callbacks=resp.callbacks, ) def list_activities( diff --git a/temporalio/nexus/__init__.py b/temporalio/nexus/__init__.py index 003df44df..3abc9b0f2 100644 --- a/temporalio/nexus/__init__.py +++ b/temporalio/nexus/__init__.py @@ -25,6 +25,7 @@ wait_for_worker_shutdown_sync, ) from ._operation_handlers import ( + CancelActivityOptions, CancelUpdateWorkflowOptions, CancelWorkflowRunOptions, TemporalOperationHandler, @@ -34,6 +35,7 @@ __all__ = ( "workflow_run_operation", + "CancelActivityOptions", "CancelWorkflowRunOptions", "CancelUpdateWorkflowOptions", "Info", diff --git a/temporalio/nexus/_link_conversion.py b/temporalio/nexus/_link_conversion.py index 54ed3869a..e3ef3988b 100644 --- a/temporalio/nexus/_link_conversion.py +++ b/temporalio/nexus/_link_conversion.py @@ -23,6 +23,10 @@ r"^/namespaces/(?P[^/]+)/nexus-operations/(?P[^/]+)/(?P[^/]*)/details$" ) +_ACTIVITY_LINK_URL_PATH_REGEX = re.compile( + r"^/namespaces/(?P[^/]+)/activities/(?P[^/]+)/(?P[^/]+)/details$" +) + _WORKFLOW_LINK_URL_PATH_REGEX = re.compile( r"^/namespaces/(?P[^/]+)/workflows/(?P[^/]+)/(?P[^/]+)(?P/history)?$" ) @@ -32,6 +36,7 @@ class _LinkType(str, Enum): WORKFLOW_EVENT = temporalio.api.common.v1.Link.WorkflowEvent.DESCRIPTOR.full_name WORKFLOW = temporalio.api.common.v1.Link.Workflow.DESCRIPTOR.full_name NEXUS_OPERATION = temporalio.api.common.v1.Link.NexusOperation.DESCRIPTOR.full_name + ACTIVITY = temporalio.api.common.v1.Link.Activity.DESCRIPTOR.full_name LINK_EVENT_ID_PARAM_NAME = "eventID" @@ -88,6 +93,9 @@ def nexus_link_to_temporal_link( case _LinkType.NEXUS_OPERATION: return nexus_link_to_nexus_operation_link(nexus_link) + case _LinkType.ACTIVITY: + return nexus_link_to_activity_link(nexus_link) + def temporal_link_to_nexus_link( temporal_link: temporalio.api.common.v1.Link, @@ -106,10 +114,11 @@ def temporal_link_to_nexus_link( case "nexus_operation": return nexus_operation_to_nexus_link(temporal_link.nexus_operation) - case "activity" | "batch_job": - raise NotImplementedError( - "only workflow_event and nexus operation links are supported" - ) + case "activity": + return activity_link_to_nexus_link(temporal_link.activity) + + case "batch_job": + raise NotImplementedError("batch_job links are not supported") case None: logger.warning("Invalid Temporal link: missing variant") @@ -190,6 +199,17 @@ def nexus_operation_to_nexus_link( ) +def activity_link_to_nexus_link( + activity: temporalio.api.common.v1.Link.Activity, +) -> nexusrpc.Link: + """Convert an Activity link into a nexusrpc link.""" + namespace = urllib.parse.quote(activity.namespace, safe="") + activity_id = urllib.parse.quote(activity.activity_id, safe="") + run_id = urllib.parse.quote(activity.run_id, safe="") + path = f"/namespaces/{namespace}/activities/{activity_id}/{run_id}/details" + return nexusrpc.Link(url=_temporal_nexus_url(path), type=_LinkType.ACTIVITY.value) + + def _workflow_nexus_url( namespace: str, workflow_id: str, @@ -334,6 +354,28 @@ def nexus_link_to_nexus_operation_link( return temporalio.api.common.v1.Link(nexus_operation=nexus_op_link) +def nexus_link_to_activity_link( + nexus_link: nexusrpc.Link, +) -> temporalio.api.common.v1.Link | None: + """Convert a Nexus Activity link into a Temporal Activity link.""" + match = _ACTIVITY_LINK_URL_PATH_REGEX.match( + urllib.parse.urlparse(nexus_link.url).path + ) + if not match: + logger.warning( + f"Invalid Nexus link: {nexus_link}. Expected path to match {_ACTIVITY_LINK_URL_PATH_REGEX.pattern}" + ) + return None + groups = match.groupdict() + return temporalio.api.common.v1.Link( + activity=temporalio.api.common.v1.Link.Activity( + namespace=urllib.parse.unquote(groups["namespace"]), + activity_id=urllib.parse.unquote(groups["activity_id"]), + run_id=urllib.parse.unquote(groups["run_id"]), + ) + ) + + def _event_reference_to_query_params( event_ref: temporalio.api.common.v1.Link.WorkflowEvent.EventReference, ) -> str: diff --git a/temporalio/nexus/_operation_context.py b/temporalio/nexus/_operation_context.py index 7206e433e..06ffd9b0f 100644 --- a/temporalio/nexus/_operation_context.py +++ b/temporalio/nexus/_operation_context.py @@ -46,7 +46,6 @@ from ._link_conversion import ( nexus_link_to_temporal_link, temporal_link_to_nexus_link, - workflow_event_to_nexus_link, workflow_execution_started_event_link_from_workflow_handle, ) from ._token import OperationToken, OperationTokenType, WorkflowHandle @@ -66,12 +65,12 @@ ContextVar("temporal-cancel-operation-context") ) -# A Nexus start handler might start zero or more workflows as usual using a Temporal client. In -# addition, it may start one "nexus-backing" workflow, using -# WorkflowRunOperationContext.start_workflow. This context is active while the latter is being done. +# A Nexus start handler might start zero or more async Temporal actions as usual using a Temporal client. In +# addition, it may start one "nexus-backing" async Temporal action, using +# WorkflowRunOperationContext.start_workflow or methods from TemporalNexusClient. This context is active while the latter is being done. # It is thus a narrower context than _temporal_start_operation_context. -_temporal_nexus_backing_workflow_start_context: ContextVar[bool] = ContextVar( - "temporal-nexus-backing-workflow-start-context" +_temporal_nexus_backing_start_context: ContextVar[bool] = ContextVar( + "temporal-nexus-backing-start-context" ) @@ -170,21 +169,21 @@ def _try_temporal_context() -> ( def _try_start_operation_context() -> _TemporalStartOperationContext | None: # pyright: ignore[reportUnusedFunction] - """The Nexus start-operation context if a handler is currently running, else None.""" + """Return the active Nexus start-operation context, if any.""" return _temporal_start_operation_context.get(None) @contextmanager -def _nexus_backing_workflow_start_context() -> Generator[None]: - token = _temporal_nexus_backing_workflow_start_context.set(True) +def _nexus_backing_start_context() -> Generator[None]: + token = _temporal_nexus_backing_start_context.set(True) try: yield finally: - _temporal_nexus_backing_workflow_start_context.reset(token) + _temporal_nexus_backing_start_context.reset(token) -def _in_nexus_backing_workflow_start_context() -> bool: # type:ignore[reportUnusedClass] - return _temporal_nexus_backing_workflow_start_context.get(False) +def _in_nexus_backing_start_context() -> bool: # type:ignore[reportUnusedClass] + return _temporal_nexus_backing_start_context.get(False) _OperationCtxT = TypeVar("_OperationCtxT", bound=OperationContext) @@ -254,11 +253,11 @@ def _get_request_links(self) -> list[temporalio.api.common.v1.Link]: ``links`` field so the callee's history event links back to whatever scheduled this Nexus operation. """ - event_links: list[temporalio.api.common.v1.Link] = [] + links: list[temporalio.api.common.v1.Link] = [] for inbound_link in self.nexus_context.inbound_links: if link := nexus_link_to_temporal_link(inbound_link): - event_links.append(link) - return event_links + links.append(link) + return links def _add_start_workflow_response_link( self, workflow_handle: temporalio.client.WorkflowHandle[Any, Any] @@ -302,17 +301,17 @@ def _add_response_link(self, link: temporalio.api.common.v1.Link | None) -> None """Append a response link returned by an RPC the operation handler issued. ``link`` is the ``common.v1.Link`` returned on a signal, signal-with-start, or start - response (or ``None`` against a server that did not return one). When present and of the - ``workflow_event`` variant, it is converted to a Nexus link and added to the operation's - outbound links so the caller workflow's Nexus history event links to the callee event. + response (or ``None`` against a server that did not return one). When present, it is + converted to a Nexus link and added to the operation's outbound links. This is only safe to call from the single thread/task that runs the operation handler. """ - if link is None or not link.HasField("workflow_event"): - return - self.nexus_context.outbound_links.append( - workflow_event_to_nexus_link(link.workflow_event) - ) + if link is not None: + try: + if response_link := temporal_link_to_nexus_link(link): + self.nexus_context.outbound_links.append(response_link) + except Exception as e: + logger.warning(f"Failed to create Nexus link from Temporal link: {e}") class WorkflowRunOperationContext(StartOperationContext): @@ -668,7 +667,7 @@ async def _start_nexus_backing_workflow( priority: temporalio.common.Priority = temporalio.common.Priority.default, versioning_override: temporalio.common.VersioningOverride | None = None, ) -> WorkflowHandle[ReturnType]: - # We must pass nexus_completion_callbacks, workflow_event_links, and request_id, + # We must pass nexus_completion_callbacks, links, and request_id, # but these are deliberately not exposed in overloads, hence the type-check # violation. @@ -677,7 +676,7 @@ async def _start_nexus_backing_workflow( # namespace to deliver the result to the caller namespace when the workflow reaches a # terminal state) and inbound links to the caller workflow (attached to history events of # the workflow started in the handler namespace, and displayed in the UI). - with _nexus_backing_workflow_start_context(): + with _nexus_backing_start_context(): token = OperationToken( type=OperationTokenType.WORKFLOW, namespace=temporal_context.client.namespace, @@ -759,3 +758,66 @@ async def _start_nexus_operation_workflow_update( # pyright: ignore[reportUnuse links=temporal_context._get_request_links(), request_id=temporal_context.nexus_context.request_id, ) + + +def _apply_nexus_context_to_start_activity_request( # pyright: ignore[reportUnusedFunction] + req: temporalio.api.workflowservice.v1.StartActivityExecutionRequest, +) -> None: + """Apply the current Nexus operation context to an activity start request. + + This is a no-op outside a Nexus operation context. Within one, it attaches + the Nexus request ID and inbound links and configures conflict handling to + preserve the Nexus metadata. Completion callbacks are added only when the + activity is backing the Nexus operation. + """ + nexus_ctx = _try_start_operation_context() + if nexus_ctx is not None: + req.on_conflict_options.attach_request_id = True + req.on_conflict_options.attach_completion_callbacks = True + req.on_conflict_options.attach_links = True + + # Add request_id and all Nexus links if we're in a Nexus context, backing or otherwise + req.request_id = nexus_ctx.nexus_context.request_id + request_links = nexus_ctx._get_request_links() + + # Links are duplicated on request for compatibility with older server versions. + req.links.extend(request_links) + + if _in_nexus_backing_start_context(): + # Add callbacks only if we're in a backing Nexus context + callbacks = nexus_ctx._get_callbacks( + OperationToken( + type=OperationTokenType.ACTIVITY, + namespace=nexus_ctx.client.namespace, + activity_id=req.activity_id, + ).encode() + ) + req.completion_callbacks.extend( + temporalio.api.common.v1.Callback( + nexus=temporalio.api.common.v1.Callback.Nexus( + url=callback.url, + header=callback.headers, + ), + links=request_links, + ) + for callback in callbacks + ) + + +def _apply_start_activity_response_to_nexus_context( # pyright: ignore[reportUnusedFunction] + activity_id: str, + resp: temporalio.api.workflowservice.v1.StartActivityExecutionResponse, +): + nexus_ctx = _try_start_operation_context() + if nexus_ctx is not None: + if resp.HasField("link"): + response_link = resp.link + else: + response_link = temporalio.api.common.v1.Link( + activity=temporalio.api.common.v1.Link.Activity( + namespace=nexus_ctx.client.namespace, + activity_id=activity_id, + run_id=resp.run_id, + ) + ) + nexus_ctx._add_response_link(response_link) diff --git a/temporalio/nexus/_operation_handlers.py b/temporalio/nexus/_operation_handlers.py index 0ad6c267c..36c44e96c 100644 --- a/temporalio/nexus/_operation_handlers.py +++ b/temporalio/nexus/_operation_handlers.py @@ -157,6 +157,16 @@ class CancelUpdateWorkflowOptions: """The workflow runID that accepted the update.""" +@dataclass(frozen=True) +class CancelActivityOptions: + """Options for cancelling the activity backing a Nexus operation.""" + + activity_id: str + """The activity ID to cancel.""" + run_id: str + """The run ID of the activity to cancel.""" + + class TemporalOperationHandler(OperationHandler[InputT, OutputT], ABC): """Operation handler for Nexus operations that interact with Temporal. Implementations override the start_operation method. @@ -200,16 +210,19 @@ async def cancel(self, ctx: CancelOperationContext, token: str) -> None: raise HandlerError( "Unable to decode operation token to cancel", type=HandlerErrorType.INTERNAL, + retryable_override=False, ) from err cancel_ctx = TemporalCancelOperationContext._from_cancel_operation_context(ctx) match operation_token.type: case OperationTokenType.WORKFLOW: + assert operation_token.workflow_id is not None options = CancelWorkflowRunOptions( workflow_id=operation_token.workflow_id ) await self.cancel_workflow_run(cancel_ctx, options) case OperationTokenType.UPDATE_WORKFLOW: + assert operation_token.workflow_id is not None assert operation_token.update_id is not None assert operation_token.run_id is not None cancel_options = CancelUpdateWorkflowOptions( @@ -218,6 +231,22 @@ async def cancel(self, ctx: CancelOperationContext, token: str) -> None: run_id=operation_token.run_id, ) await self.cancel_workflow_update(cancel_ctx, cancel_options) + case OperationTokenType.ACTIVITY: + assert operation_token.activity_id is not None + if not operation_token.run_id: + raise HandlerError( + "Expected operation token of type ACTIVITY to have a valid run id.", + type=HandlerErrorType.INTERNAL, + retryable_override=False, + ) + + await self.cancel_activity( + cancel_ctx, + CancelActivityOptions( + activity_id=operation_token.activity_id, + run_id=operation_token.run_id, + ), + ) async def cancel_workflow_run( self, @@ -253,3 +282,14 @@ async def cancel_workflow_update( """, type=HandlerErrorType.NOT_IMPLEMENTED, ) + + async def cancel_activity( + self, + ctx: TemporalCancelOperationContext, # pyright: ignore[reportUnusedParameter] + options: CancelActivityOptions, + ) -> None: + """Requests cancellation of the standalone activity backing the operation.""" + activity_handle = temporalio.nexus.client().get_activity_handle( + options.activity_id, run_id=options.run_id + ) + await activity_handle.cancel() diff --git a/temporalio/nexus/_temporal_client.py b/temporalio/nexus/_temporal_client.py index 479d1651b..393da2fae 100644 --- a/temporalio/nexus/_temporal_client.py +++ b/temporalio/nexus/_temporal_client.py @@ -21,11 +21,17 @@ import temporalio.common from temporalio.nexus._operation_context import ( + _nexus_backing_start_context, _start_nexus_backing_workflow, _start_nexus_operation_workflow_update, _TemporalStartOperationContext, ) +from temporalio.nexus._token import OperationToken, OperationTokenType from temporalio.types import ( + CallableAsyncNoParam, + CallableAsyncSingleParam, + CallableSyncNoParam, + CallableSyncSingleParam, MethodAsyncNoParam, MethodAsyncSingleParam, MultiParamSpec, @@ -34,8 +40,6 @@ SelfType, ) -from ._token import OperationToken, OperationTokenType - if TYPE_CHECKING: import temporalio.client import temporalio.workflow @@ -368,6 +372,207 @@ async def start_workflow_update( """ ... + # async no-param activity + @overload + async def start_activity( + self, + activity: CallableAsyncNoParam[ReturnType], + *, + id: str, + task_queue: str | None = None, + schedule_to_start_timeout: timedelta | None = None, + schedule_to_close_timeout: timedelta | None = None, + start_to_close_timeout: timedelta | None = None, + heartbeat_timeout: timedelta | None = None, + start_delay: timedelta | None = None, + id_reuse_policy: temporalio.common.ActivityIDReusePolicy = temporalio.common.ActivityIDReusePolicy.ALLOW_DUPLICATE, + id_conflict_policy: temporalio.common.ActivityIDConflictPolicy = temporalio.common.ActivityIDConflictPolicy.FAIL, + retry_policy: temporalio.common.RetryPolicy | None = None, + search_attributes: temporalio.common.TypedSearchAttributes | None = None, + summary: str | None = None, + priority: temporalio.common.Priority = temporalio.common.Priority.default, + rpc_metadata: Mapping[str, str | bytes] = {}, + rpc_timeout: timedelta | None = None, + ) -> TemporalOperationResult[ReturnType]: ... + + # sync no-param activity + @overload + async def start_activity( + self, + activity: CallableSyncNoParam[ReturnType], + *, + id: str, + task_queue: str | None = None, + schedule_to_start_timeout: timedelta | None = None, + schedule_to_close_timeout: timedelta | None = None, + start_to_close_timeout: timedelta | None = None, + heartbeat_timeout: timedelta | None = None, + start_delay: timedelta | None = None, + id_reuse_policy: temporalio.common.ActivityIDReusePolicy = temporalio.common.ActivityIDReusePolicy.ALLOW_DUPLICATE, + id_conflict_policy: temporalio.common.ActivityIDConflictPolicy = temporalio.common.ActivityIDConflictPolicy.FAIL, + retry_policy: temporalio.common.RetryPolicy | None = None, + search_attributes: temporalio.common.TypedSearchAttributes | None = None, + summary: str | None = None, + priority: temporalio.common.Priority = temporalio.common.Priority.default, + rpc_metadata: Mapping[str, str | bytes] = {}, + rpc_timeout: timedelta | None = None, + ) -> TemporalOperationResult[ReturnType]: ... + + # async single-param activity + @overload + async def start_activity( + self, + activity: CallableAsyncSingleParam[ParamType, ReturnType], + arg: ParamType, + *, + id: str, + task_queue: str | None = None, + schedule_to_start_timeout: timedelta | None = None, + schedule_to_close_timeout: timedelta | None = None, + start_to_close_timeout: timedelta | None = None, + heartbeat_timeout: timedelta | None = None, + start_delay: timedelta | None = None, + id_reuse_policy: temporalio.common.ActivityIDReusePolicy = temporalio.common.ActivityIDReusePolicy.ALLOW_DUPLICATE, + id_conflict_policy: temporalio.common.ActivityIDConflictPolicy = temporalio.common.ActivityIDConflictPolicy.FAIL, + retry_policy: temporalio.common.RetryPolicy | None = None, + search_attributes: temporalio.common.TypedSearchAttributes | None = None, + summary: str | None = None, + priority: temporalio.common.Priority = temporalio.common.Priority.default, + rpc_metadata: Mapping[str, str | bytes] = {}, + rpc_timeout: timedelta | None = None, + ) -> TemporalOperationResult[ReturnType]: ... + + # sync single-param activity + @overload + async def start_activity( + self, + activity: CallableSyncSingleParam[ParamType, ReturnType], + arg: ParamType, + *, + id: str, + task_queue: str | None = None, + schedule_to_start_timeout: timedelta | None = None, + schedule_to_close_timeout: timedelta | None = None, + start_to_close_timeout: timedelta | None = None, + heartbeat_timeout: timedelta | None = None, + start_delay: timedelta | None = None, + id_reuse_policy: temporalio.common.ActivityIDReusePolicy = temporalio.common.ActivityIDReusePolicy.ALLOW_DUPLICATE, + id_conflict_policy: temporalio.common.ActivityIDConflictPolicy = temporalio.common.ActivityIDConflictPolicy.FAIL, + retry_policy: temporalio.common.RetryPolicy | None = None, + search_attributes: temporalio.common.TypedSearchAttributes | None = None, + summary: str | None = None, + priority: temporalio.common.Priority = temporalio.common.Priority.default, + rpc_metadata: Mapping[str, str | bytes] = {}, + rpc_timeout: timedelta | None = None, + ) -> TemporalOperationResult[ReturnType]: ... + + # async multi-param activity + @overload + async def start_activity( + self, + activity: Callable[..., Awaitable[ReturnType]], + *, + args: Sequence[Any], + id: str, + task_queue: str | None = None, + schedule_to_start_timeout: timedelta | None = None, + schedule_to_close_timeout: timedelta | None = None, + start_to_close_timeout: timedelta | None = None, + heartbeat_timeout: timedelta | None = None, + start_delay: timedelta | None = None, + id_reuse_policy: temporalio.common.ActivityIDReusePolicy = temporalio.common.ActivityIDReusePolicy.ALLOW_DUPLICATE, + id_conflict_policy: temporalio.common.ActivityIDConflictPolicy = temporalio.common.ActivityIDConflictPolicy.FAIL, + retry_policy: temporalio.common.RetryPolicy | None = None, + search_attributes: temporalio.common.TypedSearchAttributes | None = None, + summary: str | None = None, + priority: temporalio.common.Priority = temporalio.common.Priority.default, + rpc_metadata: Mapping[str, str | bytes] = {}, + rpc_timeout: timedelta | None = None, + ) -> TemporalOperationResult[ReturnType]: ... + + # sync multi-param activity + @overload + async def start_activity( + self, + activity: Callable[..., ReturnType], + *, + args: Sequence[Any], + id: str, + task_queue: str | None = None, + schedule_to_start_timeout: timedelta | None = None, + schedule_to_close_timeout: timedelta | None = None, + start_to_close_timeout: timedelta | None = None, + heartbeat_timeout: timedelta | None = None, + start_delay: timedelta | None = None, + id_reuse_policy: temporalio.common.ActivityIDReusePolicy = temporalio.common.ActivityIDReusePolicy.ALLOW_DUPLICATE, + id_conflict_policy: temporalio.common.ActivityIDConflictPolicy = temporalio.common.ActivityIDConflictPolicy.FAIL, + retry_policy: temporalio.common.RetryPolicy | None = None, + search_attributes: temporalio.common.TypedSearchAttributes | None = None, + summary: str | None = None, + priority: temporalio.common.Priority = temporalio.common.Priority.default, + rpc_metadata: Mapping[str, str | bytes] = {}, + rpc_timeout: timedelta | None = None, + ) -> TemporalOperationResult[ReturnType]: ... + + # string-name activity + @overload + async def start_activity( + self, + activity: str, + arg: Any = temporalio.common._arg_unset, + *, + args: Sequence[Any] = [], + id: str, + task_queue: str | None = None, + result_type: type[ReturnType] | None = None, + schedule_to_start_timeout: timedelta | None = None, + schedule_to_close_timeout: timedelta | None = None, + start_to_close_timeout: timedelta | None = None, + heartbeat_timeout: timedelta | None = None, + start_delay: timedelta | None = None, + id_reuse_policy: temporalio.common.ActivityIDReusePolicy = temporalio.common.ActivityIDReusePolicy.ALLOW_DUPLICATE, + id_conflict_policy: temporalio.common.ActivityIDConflictPolicy = temporalio.common.ActivityIDConflictPolicy.FAIL, + retry_policy: temporalio.common.RetryPolicy | None = None, + search_attributes: temporalio.common.TypedSearchAttributes | None = None, + summary: str | None = None, + priority: temporalio.common.Priority = temporalio.common.Priority.default, + rpc_metadata: Mapping[str, str | bytes] = {}, + rpc_timeout: timedelta | None = None, + ) -> TemporalOperationResult[ReturnType]: ... + + @abstractmethod + async def start_activity( + self, + activity: ( + str | Callable[..., Awaitable[ReturnType]] | Callable[..., ReturnType] + ), + arg: Any = temporalio.common._arg_unset, + *, + args: Sequence[Any] = [], + id: str, + task_queue: str | None = None, + result_type: type | None = None, + schedule_to_start_timeout: timedelta | None = None, + schedule_to_close_timeout: timedelta | None = None, + start_to_close_timeout: timedelta | None = None, + heartbeat_timeout: timedelta | None = None, + start_delay: timedelta | None = None, + id_reuse_policy: temporalio.common.ActivityIDReusePolicy = temporalio.common.ActivityIDReusePolicy.ALLOW_DUPLICATE, + id_conflict_policy: temporalio.common.ActivityIDConflictPolicy = temporalio.common.ActivityIDConflictPolicy.FAIL, + retry_policy: temporalio.common.RetryPolicy | None = None, + search_attributes: temporalio.common.TypedSearchAttributes | None = None, + summary: str | None = None, + priority: temporalio.common.Priority = temporalio.common.Priority.default, + rpc_metadata: Mapping[str, str | bytes] = {}, + rpc_timeout: timedelta | None = None, + ) -> TemporalOperationResult[ReturnType]: + """Start a standalone activity that will deliver the Nexus operation result. + + If ``task_queue`` is not specified, the Nexus worker's task queue is used. + See :py:meth:`temporalio.client.Client.start_activity` for all other arguments. + """ + ... + class _TemporalNexusClient(TemporalNexusClient): # pyright: ignore[reportUnusedClass] """Nexus-aware wrapper around a Temporal Client. @@ -518,3 +723,72 @@ async def start_workflow_update( run_id=update_handle.workflow_run_id, ).encode() return TemporalOperationResult.async_token(token) + + async def start_activity( + self, + activity: ( + str | Callable[..., Awaitable[ReturnType]] | Callable[..., ReturnType] + ), + arg: Any = temporalio.common._arg_unset, + *, + args: Sequence[Any] = [], + id: str, + task_queue: str | None = None, + result_type: type | None = None, + schedule_to_start_timeout: timedelta | None = None, + schedule_to_close_timeout: timedelta | None = None, + start_to_close_timeout: timedelta | None = None, + heartbeat_timeout: timedelta | None = None, + start_delay: timedelta | None = None, + id_reuse_policy: temporalio.common.ActivityIDReusePolicy = temporalio.common.ActivityIDReusePolicy.ALLOW_DUPLICATE, + id_conflict_policy: temporalio.common.ActivityIDConflictPolicy = temporalio.common.ActivityIDConflictPolicy.FAIL, + retry_policy: temporalio.common.RetryPolicy | None = None, + search_attributes: temporalio.common.TypedSearchAttributes | None = None, + summary: str | None = None, + priority: temporalio.common.Priority = temporalio.common.Priority.default, + rpc_metadata: Mapping[str, str | bytes] = {}, + rpc_timeout: timedelta | None = None, + ) -> TemporalOperationResult[ReturnType]: + """Start a standalone activity that will deliver the Nexus operation result. + + If ``task_queue`` is not specified, the Nexus worker's task queue is used. + See :py:meth:`temporalio.client.Client.start_activity` for all other arguments. + """ + with self._reserve_async_start(): + # Here we are starting a "nexus-backing" standalone activity. The start request + # carries the Nexus completion callback so the activity result is delivered to + # the Nexus caller when the activity reaches a terminal state. + + with _nexus_backing_start_context(): + activity_handle: temporalio.client.ActivityHandle[ + ReturnType + ] = await self._temporal_context.client.start_activity( + activity=activity, # type: ignore + arg=arg, + args=args, + id=id, + task_queue=task_queue or self._temporal_context.info().task_queue, + result_type=result_type, + schedule_to_start_timeout=schedule_to_start_timeout, + schedule_to_close_timeout=schedule_to_close_timeout, + start_to_close_timeout=start_to_close_timeout, + heartbeat_timeout=heartbeat_timeout, + start_delay=start_delay, + id_reuse_policy=id_reuse_policy, + id_conflict_policy=id_conflict_policy, + retry_policy=retry_policy, + search_attributes=search_attributes, + summary=summary, + priority=priority, + rpc_metadata=rpc_metadata, + rpc_timeout=rpc_timeout, + ) + + activity_token = OperationToken( + type=OperationTokenType.ACTIVITY, + namespace=self._temporal_context.client.namespace, + activity_id=activity_handle.id, + run_id=activity_handle.run_id, + ) + + return TemporalOperationResult.async_token(activity_token.encode()) diff --git a/temporalio/nexus/_token.py b/temporalio/nexus/_token.py index fe0a466c9..a7c732f2a 100644 --- a/temporalio/nexus/_token.py +++ b/temporalio/nexus/_token.py @@ -14,6 +14,7 @@ class OperationTokenType(IntEnum): """Type discriminator for Nexus operation tokens.""" WORKFLOW = 1 + ACTIVITY = 2 UPDATE_WORKFLOW = 3 @@ -28,7 +29,8 @@ class OperationToken: version: int | None = None type: OperationTokenType namespace: str - workflow_id: str + workflow_id: str | None = None + activity_id: str | None = None run_id: str | None = None update_id: str | None = None @@ -37,8 +39,11 @@ def encode(self) -> str: token_details: dict[str, Any] = { "t": self.type, "ns": self.namespace, - "wid": self.workflow_id, } + if self.workflow_id is not None: + token_details["wid"] = self.workflow_id + if self.activity_id is not None: + token_details["aid"] = self.activity_id if self.version is not None: token_details["v"] = self.version if self.run_id is not None: @@ -90,7 +95,7 @@ def decode(cls, token: str) -> Self: ) workflow_id = token_details.get("wid") - if not isinstance(workflow_id, str): + if workflow_id is not None and not isinstance(workflow_id, str): raise TypeError( f"invalid token: expected workflow id to be a string, got {type(workflow_id)}" ) @@ -104,6 +109,17 @@ def decode(cls, token: str) -> Self: f"invalid token: expected non-empty workflow id for token type `{token_type.name}`" ) + activity_id = token_details.get("aid") + if activity_id is not None and not isinstance(activity_id, str): + raise TypeError( + f"invalid token: expected activity id to be a string, got {type(activity_id)}" + ) + + if token_type == OperationTokenType.ACTIVITY and not activity_id: + raise TypeError( + f"invalid token: expected non-empty activity id for token type `{token_type.name}`" + ) + update_id = token_details.get("uid") if not isinstance(update_id, str | None): raise TypeError( @@ -123,7 +139,6 @@ def decode(cls, token: str) -> Self: ) run_id = token_details.get("rid") - if not isinstance(run_id, str | None): raise TypeError( f"invalid token: expected run_id to be a string or None, got {type(run_id)}" @@ -133,6 +148,7 @@ def decode(cls, token: str) -> Self: type=OperationTokenType(token_type), namespace=namespace, workflow_id=workflow_id, + activity_id=activity_id, run_id=run_id, version=version, update_id=update_id, @@ -199,6 +215,9 @@ def from_token(cls, token: str) -> WorkflowHandle[OutputT]: f"invalid workflow token type: {op_token.type}, expected: {OperationTokenType.WORKFLOW}" ) + if not op_token.workflow_id: + raise TypeError("invalid workflow token: missing workflow id") + if op_token.version is not None and op_token.version != 0: raise TypeError( "invalid workflow token: 'v' field, if present, must be 0 or null/absent" diff --git a/tests/__init__.py b/tests/__init__.py index 4725d3a7e..af97849fe 100644 --- a/tests/__init__.py +++ b/tests/__init__.py @@ -1 +1 @@ -DEV_SERVER_DOWNLOAD_VERSION = "v1.7.1-system-nexus-operations" +DEV_SERVER_DOWNLOAD_VERSION = "v1.7.4-standalone-nexus-operations" diff --git a/tests/conftest.py b/tests/conftest.py index 9c57bc0d1..a9c6abb89 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -179,6 +179,8 @@ async def env(env_type: str) -> AsyncGenerator[WorkflowEnvironment, None]: "history.enableSignalWithStartFromWorkflow=true", "--dynamic-config-value", "history.enableUpdateCallbacks=true", + "--dynamic-config-value", + "activity.enableCallbacks=true", ], dev_server_download_version=DEV_SERVER_DOWNLOAD_VERSION, ) diff --git a/tests/nexus/test_link_conversion.py b/tests/nexus/test_link_conversion.py index 4afe3367e..15fc8d77f 100644 --- a/tests/nexus/test_link_conversion.py +++ b/tests/nexus/test_link_conversion.py @@ -304,6 +304,19 @@ def test_link_conversion_workflow_to_link_and_back( url="temporal:///namespaces/ns/nexus-operations/op%2Fid//details", ), ), + ( + temporalio.api.common.v1.Link( + nexus_operation=temporalio.api.common.v1.Link.NexusOperation( + namespace="ns", + operation_id="op/id", + run_id="run/id", + ) + ), + nexusrpc.Link( + type=temporalio.api.common.v1.Link.NexusOperation.DESCRIPTOR.full_name, + url="temporal:///namespaces/ns/nexus-operations/op%2Fid/run%2Fid/details", + ), + ), ], ) def test_link_conversion_nexus_operation_to_link_and_back( @@ -342,6 +355,62 @@ def test_nexus_operation_link_with_unparseable_url_is_ignored(): assert temporalio.nexus._link_conversion.nexus_link_to_temporal_link(link) is None +@pytest.mark.parametrize( + ["link", "expected_link"], + [ + ( + nexusrpc.Link( + type=temporalio.api.common.v1.Link.Activity.DESCRIPTOR.full_name, + url="temporal:///namespaces/ns/activities/act-id/run-id/details", + ), + temporalio.api.common.v1.Link( + activity=temporalio.api.common.v1.Link.Activity( + namespace="ns", + activity_id="act-id", + run_id="run-id", + ), + ), + ), + ( + nexusrpc.Link( + type=temporalio.api.common.v1.Link.Activity.DESCRIPTOR.full_name, + url="temporal:///namespaces/ns%2F/activities/act-id%2F/run-id%3E/details", + ), + temporalio.api.common.v1.Link( + activity=temporalio.api.common.v1.Link.Activity( + namespace="ns/", + activity_id="act-id/", + run_id="run-id>", + ), + ), + ), + ], +) +def test_link_conversion_nexus_link_to_activity_link( + link: nexusrpc.Link, + expected_link: temporalio.api.common.v1.Link, +): + from_activity_link = temporalio.nexus._link_conversion.activity_link_to_nexus_link( + expected_link.activity + ) + assert link == from_activity_link + + from_temporal_link = temporalio.nexus._link_conversion.temporal_link_to_nexus_link( + expected_link + ) + assert link == from_temporal_link + + actual_activity = temporalio.nexus._link_conversion.nexus_link_to_activity_link( + link + ) + assert expected_link == actual_activity + + actual_temporal_link = ( + temporalio.nexus._link_conversion.nexus_link_to_temporal_link(link) + ) + assert expected_link == actual_temporal_link + + def test_link_conversion_utilities(): p2c = temporalio.nexus._link_conversion._event_type_pascal_case_to_constant_case c2p = temporalio.nexus._link_conversion._event_type_constant_case_to_pascal_case diff --git a/tests/nexus/test_signal_link_propagation.py b/tests/nexus/test_link_propagation.py similarity index 84% rename from tests/nexus/test_signal_link_propagation.py rename to tests/nexus/test_link_propagation.py index daff71c78..2c9f6eec7 100644 --- a/tests/nexus/test_signal_link_propagation.py +++ b/tests/nexus/test_link_propagation.py @@ -1,14 +1,14 @@ -"""Unit tests for Nexus signal-backlink propagation. +"""Unit tests for Nexus link propagation. -These exercise the in/out link propagation that happens when a Nexus operation handler issues a -signal, signal-with-start, or start-workflow RPC, against a mocked workflow service. -The corresponding end-to-end behavior requires a real server with EnableCHASMSignalBacklinks=true and is therefore -and is therefore not covered here. +These exercise link propagation when a Nexus operation handler signals or starts a +workflow or activity against a mocked workflow service. End-to-end signal backlinks +require a server with EnableCHASMSignalBacklinks enabled and are not covered here. """ from __future__ import annotations from collections.abc import Generator +from datetime import timedelta from typing import Any from unittest import mock @@ -32,9 +32,11 @@ import temporalio.converter import temporalio.nexus._link_conversion import temporalio.nexus._operation_context +import temporalio.nexus._token from temporalio.client._impl import _ClientImpl from temporalio.client._interceptor import ( SignalWorkflowInput, + StartActivityInput, StartWorkflowInput, ) from temporalio.nexus._operation_context import _TemporalStartOperationContext @@ -84,7 +86,7 @@ def nexus_ctx() -> Generator[_TemporalStartOperationContext]: operation="op", headers={}, request_id="req-id", - callback_url=None, + callback_url="https://callback.example", inbound_links=[inbound], callback_headers={}, task_cancellation=_NexusTaskCancellation(), @@ -163,6 +165,30 @@ def _start_input(start_signal: str | None = None) -> StartWorkflowInput: ) +def _start_activity_input() -> StartActivityInput: + return StartActivityInput( + activity_type="TestActivity", + args=[], + id="activity-target", + task_queue="tq", + result_type=None, + schedule_to_close_timeout=None, + start_to_close_timeout=timedelta(seconds=10), + schedule_to_start_timeout=None, + heartbeat_timeout=None, + id_reuse_policy=temporalio.common.ActivityIDReusePolicy.ALLOW_DUPLICATE, + id_conflict_policy=temporalio.common.ActivityIDConflictPolicy.FAIL, + retry_policy=None, + priority=temporalio.common.Priority.default, + search_attributes=None, + summary=None, + start_delay=None, + headers={}, + rpc_metadata={}, + rpc_timeout=None, + ) + + def _outbound_link_urls(ctx: Any) -> list[str]: return [link.url for link in ctx.nexus_context.outbound_links] @@ -433,7 +459,7 @@ async def test_backing_workflow_start_sets_on_conflict_options_without_duplicati # also re-add the context's request links. start_input = _start_input() start_input.links = [_inbound_nexus_link()] - with temporalio.nexus._operation_context._nexus_backing_workflow_start_context(): + with temporalio.nexus._operation_context._nexus_backing_start_context(): await impl.start_workflow(start_input) sent = workflow_service.start_workflow_execution.call_args.args[0] @@ -459,6 +485,65 @@ async def test_start_outside_nexus_context_leaves_on_conflict_options_unset() -> assert not sent.HasField("on_conflict_options") +# ── activity start ────────────────────────────────────────────────────────────────────────── + + +@pytest.mark.usefixtures("nexus_ctx") +async def test_activity_start_forwards_inbound_links() -> None: + impl = _make_client_impl(mock.MagicMock()) + + req = await impl._build_start_activity_execution_request(_start_activity_input()) + + assert len(req.links) == 1 + assert req.links[0] == _inbound_nexus_link() + assert req.request_id == "req-id" + assert len(req.completion_callbacks) == 0 + + +async def test_activity_start_without_server_link_synthesizes_backlink( + nexus_ctx: _TemporalStartOperationContext, +) -> None: + workflow_service = mock.MagicMock() + workflow_service.start_activity_execution = mock.AsyncMock( + return_value=temporalio.api.workflowservice.v1.StartActivityExecutionResponse( + run_id="activity-run", + ) + ) + impl = _make_client_impl(workflow_service) + + await impl.start_activity(_start_activity_input()) + + assert len(nexus_ctx.nexus_context.outbound_links) == 1 + link = nexus_ctx.nexus_context.outbound_links[0] + assert link.url == ( + "temporal:///namespaces/test-namespace/" + "activities/activity-target/activity-run/details" + ) + assert link.type == temporalio.api.common.v1.Link.Activity.DESCRIPTOR.full_name + + +@pytest.mark.usefixtures("nexus_ctx") +async def test_backing_activity_start_gets_nexus_request_fields() -> None: + impl = _make_client_impl(mock.MagicMock()) + + with temporalio.nexus._operation_context._nexus_backing_start_context(): + req = await impl._build_start_activity_execution_request( + _start_activity_input() + ) + + assert len(req.links) == 1 + assert req.links[0] == _inbound_nexus_link() + assert req.request_id == "req-id" + assert len(req.completion_callbacks) == 1 + operation_token = temporalio.nexus._token.OperationToken.decode( + req.completion_callbacks[0].nexus.header["nexus-operation-token"] + ) + assert operation_token.type is temporalio.nexus._token.OperationTokenType.ACTIVITY + assert operation_token.namespace == NAMESPACE + assert operation_token.activity_id == "activity-target" + assert list(req.completion_callbacks[0].links) == [_inbound_nexus_link()] + + # ── handler-level: backlinks land on the StartOperationResponse ────────────────────────────── # A response link that a handler stashes on ctx.outbound_links, mimicking what a signal RPC inside diff --git a/tests/nexus/test_nexus_type_errors.py b/tests/nexus/test_nexus_type_errors.py index 1486f9791..946e34035 100644 --- a/tests/nexus/test_nexus_type_errors.py +++ b/tests/nexus/test_nexus_type_errors.py @@ -11,7 +11,7 @@ import nexusrpc import temporalio.nexus -from temporalio import workflow +from temporalio import activity, workflow from temporalio.client import Client, NexusOperationHandle from temporalio.nexus import TemporalOperationStartHandlerFunc from temporalio.service import ServiceClient @@ -71,6 +71,74 @@ async def run( pass +@activity.defn +async def my_no_arg_activity() -> None: + pass + + +@activity.defn +async def my_one_arg_activity(_input: MyInput) -> None: + pass + + +@activity.defn +async def my_two_arg_activity(_input: MyInput, _arg2: int) -> None: + pass + + +@activity.defn +async def my_three_arg_activity(_input: MyInput, _arg2: int, _arg3: int) -> None: + pass + + +@activity.defn +async def my_four_arg_activity( + _input: MyInput, _arg2: int, _arg3: int, _arg4: int +) -> None: + pass + + +@activity.defn +async def my_five_arg_activity( + _input: MyInput, _arg2: int, _arg3: int, _arg4: int, _arg5: int +) -> None: + pass + + +@activity.defn +def my_sync_no_arg_activity() -> None: + pass + + +@activity.defn +def my_sync_one_arg_activity(_input: MyInput) -> None: + pass + + +@activity.defn +def my_sync_two_arg_activity(_input: MyInput, _arg2: int) -> None: + pass + + +@activity.defn +def my_sync_three_arg_activity(_input: MyInput, _arg2: int, _arg3: int) -> None: + pass + + +@activity.defn +def my_sync_four_arg_activity( + _input: MyInput, _arg2: int, _arg3: int, _arg4: int +) -> None: + pass + + +@activity.defn +def my_sync_five_arg_activity( + _input: MyInput, _arg2: int, _arg3: int, _arg4: int, _arg5: int +) -> None: + pass + + @nexusrpc.service class MyService: my_sync_operation: nexusrpc.Operation[MyInput, MyOutput] @@ -105,8 +173,9 @@ async def my_temporal_operation( input: int, ) -> temporalio.nexus.TemporalOperationResult[None]: """ - Typed proc workflow starts from a generic Temporal Nexus operation handler - infer TemporalOperationResult[None] for 0 to 5 workflow parameters. + Typed proc workflow and activity starts from a generic Temporal Nexus + operation handler infer TemporalOperationResult[None] for 0 to 5 + workflow or activity parameters. """ if input == 0: result_0: temporalio.nexus.TemporalOperationResult[ @@ -154,6 +223,147 @@ async def my_temporal_operation( id="proc-5", ) return result_5 + + # Typed activity starts infer TemporalOperationResult[None] for 0 to 5 + # activity parameters. Activities require a start_to_close_timeout. + if input == 6: + activity_result_0: temporalio.nexus.TemporalOperationResult[ + None + ] = await client.start_activity( + my_no_arg_activity, + id="activity-0", + start_to_close_timeout=timedelta(seconds=5), + ) + return activity_result_0 + if input == 7: + activity_result_1: temporalio.nexus.TemporalOperationResult[ + None + ] = await client.start_activity( + my_one_arg_activity, + MyInput(), + id="activity-1", + start_to_close_timeout=timedelta(seconds=5), + ) + return activity_result_1 + if input == 8: + activity_result_2: temporalio.nexus.TemporalOperationResult[ + None + ] = await client.start_activity( + my_two_arg_activity, + args=[MyInput(), 2], + id="activity-2", + start_to_close_timeout=timedelta(seconds=5), + ) + return activity_result_2 + if input == 9: + activity_result_3: temporalio.nexus.TemporalOperationResult[ + None + ] = await client.start_activity( + my_three_arg_activity, + args=[MyInput(), 2, 3], + id="activity-3", + start_to_close_timeout=timedelta(seconds=5), + ) + return activity_result_3 + if input == 10: + activity_result_4: temporalio.nexus.TemporalOperationResult[ + None + ] = await client.start_activity( + my_four_arg_activity, + args=[MyInput(), 2, 3, 4], + id="activity-4", + start_to_close_timeout=timedelta(seconds=5), + ) + return activity_result_4 + if input == 11: + activity_result_5: temporalio.nexus.TemporalOperationResult[ + None + ] = await client.start_activity( + my_five_arg_activity, + args=[MyInput(), 2, 3, 4, 5], + id="activity-5", + start_to_close_timeout=timedelta(seconds=5), + ) + return activity_result_5 + if input == 12: + sync_activity_result_0: temporalio.nexus.TemporalOperationResult[ + None + ] = await client.start_activity( + my_sync_no_arg_activity, + id="sync-activity-0", + start_to_close_timeout=timedelta(seconds=5), + ) + return sync_activity_result_0 + if input == 13: + sync_activity_result_1: temporalio.nexus.TemporalOperationResult[ + None + ] = await client.start_activity( + my_sync_one_arg_activity, + MyInput(), + id="sync-activity-1", + start_to_close_timeout=timedelta(seconds=5), + ) + return sync_activity_result_1 + if input == 14: + sync_activity_result_2: temporalio.nexus.TemporalOperationResult[ + None + ] = await client.start_activity( + my_sync_two_arg_activity, + args=[MyInput(), 2], + id="sync-activity-2", + start_to_close_timeout=timedelta(seconds=5), + ) + return sync_activity_result_2 + if input == 15: + sync_activity_result_3: temporalio.nexus.TemporalOperationResult[ + None + ] = await client.start_activity( + my_sync_three_arg_activity, + args=[MyInput(), 2, 3], + id="sync-activity-3", + start_to_close_timeout=timedelta(seconds=5), + ) + return sync_activity_result_3 + if input == 16: + sync_activity_result_4: temporalio.nexus.TemporalOperationResult[ + None + ] = await client.start_activity( + my_sync_four_arg_activity, + args=[MyInput(), 2, 3, 4], + id="sync-activity-4", + start_to_close_timeout=timedelta(seconds=5), + ) + return sync_activity_result_4 + if input == 17: + sync_activity_result_5: temporalio.nexus.TemporalOperationResult[ + None + ] = await client.start_activity( + my_sync_five_arg_activity, + args=[MyInput(), 2, 3, 4, 5], + id="sync-activity-5", + start_to_close_timeout=timedelta(seconds=5), + ) + return sync_activity_result_5 + if input == 18: + string_activity_result: temporalio.nexus.TemporalOperationResult[ + None + ] = await client.start_activity( + "string-activity", + id="string-activity", + result_type=type(None), + start_to_close_timeout=timedelta(seconds=5), + ) + return string_activity_result + if input == 19: + # assert-type-error-pyright: 'No overloads for "start_activity" match' + return await client.start_activity( # type: ignore + my_one_arg_activity, + # assert-type-error-pyright: 'Argument of type .+ cannot be assigned to parameter' + "wrong-input-type", # type: ignore + id="activity-wrong-input", + start_to_close_timeout=timedelta(seconds=5), + ) + # assert-type-error-pyright: 'No overloads for "start_workflow" match' return await client.start_workflow( # type: ignore MyOneArgProcWorkflow.run, diff --git a/tests/nexus/test_operation_token.py b/tests/nexus/test_operation_token.py index 385f4f872..58d4a7859 100644 --- a/tests/nexus/test_operation_token.py +++ b/tests/nexus/test_operation_token.py @@ -8,6 +8,7 @@ OperationToken, OperationTokenType, WorkflowHandle, + _base64url_decode_no_padding, ) @@ -36,6 +37,39 @@ def test_operation_token_encode_decode_round_trip(): ) +def test_operation_token_activity_encode_decode_round_trip(): + token = OperationToken( + type=OperationTokenType.ACTIVITY, + namespace="default", + activity_id="activity-id", + run_id="run-id", + version=0, + ).encode() + + assert "=" not in token + assert OperationToken.decode(token) == OperationToken( + type=OperationTokenType.ACTIVITY, + namespace="default", + activity_id="activity-id", + run_id="run-id", + version=0, + ) + + +def test_operation_token_activity_encode_uses_activity_id_and_omits_workflow_id(): + token = OperationToken( + type=OperationTokenType.ACTIVITY, + namespace="default", + activity_id="activity-id", + ).encode() + + assert json.loads(_base64url_decode_no_padding(token)) == { + "t": 2, + "ns": "default", + "aid": "activity-id", + } + + def test_workflow_handle_to_from_token_round_trip(): handle = WorkflowHandle[str](namespace="default", workflow_id="workflow-id") @@ -80,6 +114,58 @@ def test_workflow_handle_to_from_token_round_trip(): version=0, ), ), + # Activity tokens + ( + _encode_json_token( + {"t": 2, "ns": "default", "aid": "activity-id", "rid": "run-id"} + ), + OperationToken( + type=OperationTokenType.ACTIVITY, + namespace="default", + activity_id="activity-id", + run_id="run-id", + ), + ), + ( + _encode_json_token( + {"t": 2, "ns": "", "aid": "activity-id", "rid": "run-id"} + ), + OperationToken( + type=OperationTokenType.ACTIVITY, + namespace="", + activity_id="activity-id", + run_id="run-id", + ), + ), + ( + _encode_json_token( + { + "t": 2, + "ns": "default", + "aid": "activity-id", + "rid": "run-id", + "v": None, + } + ), + OperationToken( + type=OperationTokenType.ACTIVITY, + namespace="default", + activity_id="activity-id", + run_id="run-id", + ), + ), + ( + _encode_json_token( + {"t": 2, "ns": "default", "aid": "activity-id", "rid": "run-id", "v": 0} + ), + OperationToken( + type=OperationTokenType.ACTIVITY, + namespace="default", + activity_id="activity-id", + run_id="run-id", + version=0, + ), + ), ], ) def test_operation_token_decode_accepts_valid_tokens( @@ -110,7 +196,7 @@ def test_operation_token_decode_accepts_valid_tokens( ), ( _encode_json_token({"t": 1, "ns": "default"}), - "expected workflow id to be a string", + "expected non-empty workflow id for token type `WORKFLOW`", ), ( _encode_json_token({"t": 1, "ns": "default", "wid": 123}), @@ -134,6 +220,41 @@ def test_operation_token_decode_accepts_valid_tokens( ), "expected version to be an int or null", ), + # Activity tokens + ( + _encode_json_token({"t": 2, "ns": "default"}), + "expected non-empty activity id for token type `ACTIVITY`", + ), + ( + _encode_json_token({"t": 2, "ns": "default", "aid": ""}), + "expected non-empty activity id for token type `ACTIVITY`", + ), + ( + _encode_json_token({"t": 2, "ns": "default", "aid": 123}), + "expected activity id to be a string", + ), + ( + _encode_json_token( + {"t": 2, "ns": "default", "aid": "activity-id", "rid": 123} + ), + "expected run_id to be a string", + ), + ( + _encode_json_token({"t": 2, "aid": "activity-id", "rid": "run-id"}), + "expected namespace to be a string", + ), + ( + _encode_json_token( + { + "t": 2, + "ns": "default", + "aid": "activity-id", + "rid": "run-id", + "v": "0", + } + ), + "expected version to be an int or null", + ), ], ) def test_operation_token_decode_rejects_invalid_tokens(token: str, message: str): diff --git a/tests/nexus/test_temporal_operation.py b/tests/nexus/test_temporal_operation.py index b4bf235fe..d966c5cc6 100644 --- a/tests/nexus/test_temporal_operation.py +++ b/tests/nexus/test_temporal_operation.py @@ -6,14 +6,29 @@ import nexusrpc import pytest from nexusrpc import HandlerErrorType, Operation, service -from nexusrpc.handler import operation_handler, service_handler +from nexusrpc.handler import ( + CancelOperationContext, + OperationTaskCancellation, + operation_handler, + service_handler, +) from typing_extensions import override import temporalio.exceptions -from temporalio import nexus, workflow +from temporalio import activity, nexus, workflow from temporalio.api.common.v1 import Link -from temporalio.client import Client, WorkflowExecutionStatus, WorkflowFailureError -from temporalio.common import NexusOperationExecutionStatus, WorkflowIDConflictPolicy +from temporalio.client import ( + ActivityExecutionStatus, + Client, + NexusOperationFailureError, + WorkflowExecutionStatus, + WorkflowFailureError, +) +from temporalio.common import ( + NexusOperationExecutionStatus, + RetryPolicy, + WorkflowIDConflictPolicy, +) from temporalio.nexus._token import OperationToken, OperationTokenType from temporalio.testing import WorkflowEnvironment from temporalio.worker import Worker @@ -63,6 +78,29 @@ async def run(self, input: Input) -> str: return input.value +@activity.defn +async def echo_activity(input: Input) -> str: + return input.value + + +@activity.defn +async def raise_error_activity() -> None: + raise temporalio.exceptions.ApplicationError( + "test-activity-error-message", + type="test-activity-error-type", + non_retryable=True, + ) + + +@activity.defn +async def wait_for_cancel_activity() -> None: + # Heartbeat in a loop so the activity receives cancellation. Letting the + # resulting CancelledError bubble out transitions the activity to CANCELED. + while True: + await asyncio.sleep(0.3) + activity.heartbeat() + + @service class TestService: echo: Operation[Input, str] @@ -73,6 +111,12 @@ class TestService: sync_result: Operation[Input, str] custom_cancel: Operation[str, None] update_op: Operation[Input, str] + echo_activity: Operation[Input, str] + error_activity: Operation[Input, None] + blocking_activity: Operation[str, None] + custom_cancel_activity: Operation[str, None] + double_start_activity: Operation[Input, None] + mixed_start: Operation[Input, None] @service_handler(service=TestService) @@ -82,6 +126,8 @@ class TestServiceHandler: def __init__(self) -> None: self.started_custom_cancel_workflow = asyncio.Event() + self.started_custom_cancel_activity = asyncio.Event() + self.custom_cancel_activity_called = asyncio.Event() @nexus.temporal_operation async def echo( @@ -241,6 +287,130 @@ async def update_op( update_id=input.update_id, ) + @nexus.temporal_operation + async def echo_activity( + self, + _ctx: nexus.TemporalStartOperationContext, + client: nexus.TemporalNexusClient, + input: Input, + ) -> nexus.TemporalOperationResult[str]: + return await client.start_activity( + echo_activity, + input, + id=f"echo_activity-{uuid.uuid4()}", + start_to_close_timeout=timedelta(seconds=5), + ) + + @nexus.temporal_operation + async def error_activity( + self, + _ctx: nexus.TemporalStartOperationContext, + client: nexus.TemporalNexusClient, + _input: Input, + ) -> nexus.TemporalOperationResult[None]: + # The activity raises immediately. With a single permitted attempt it + # fails the backing activity, which in turn fails the Nexus operation. + return await client.start_activity( + raise_error_activity, + id=f"error_activity-{uuid.uuid4()}", + start_to_close_timeout=timedelta(seconds=5), + retry_policy=RetryPolicy(maximum_attempts=1), + ) + + @nexus.temporal_operation + async def blocking_activity( + self, + _ctx: nexus.TemporalStartOperationContext, + client: nexus.TemporalNexusClient, + input: str, + ) -> nexus.TemporalOperationResult[None]: + return await client.start_activity( + wait_for_cancel_activity, + id=input, + start_to_close_timeout=timedelta(seconds=30), + heartbeat_timeout=timedelta(seconds=1), + ) + + @nexus.temporal_operation + async def double_start_activity( + self, + _ctx: nexus.TemporalStartOperationContext, + client: nexus.TemporalNexusClient, + input: Input, + ) -> nexus.TemporalOperationResult[None]: + await client.start_activity( + echo_activity, + input, + id=f"double-start-activity-{uuid.uuid4()}", + start_to_close_timeout=timedelta(seconds=5), + ) + await client.start_activity( + echo_activity, + input, + id=f"double-start-activity-{uuid.uuid4()}", + start_to_close_timeout=timedelta(seconds=5), + ) + return nexus.TemporalOperationResult.sync(None) + + @nexus.temporal_operation + async def mixed_start( + self, + _ctx: nexus.TemporalStartOperationContext, + client: nexus.TemporalNexusClient, + input: Input, + ) -> nexus.TemporalOperationResult[None]: + # Starting a workflow reserves the single async start, so the subsequent + # start_activity must hit the same guard and raise a BAD_REQUEST error. + await client.start_workflow( + EchoWorkflow.run, input, id=f"mixed-start-{uuid.uuid4()}" + ) + await client.start_activity( + echo_activity, + input, + id=f"mixed-start-{uuid.uuid4()}", + start_to_close_timeout=timedelta(seconds=5), + ) + return nexus.TemporalOperationResult.sync(None) + + @operation_handler + def custom_cancel_activity(self) -> nexus.TemporalOperationHandler[str, None]: + started = self.started_custom_cancel_activity + cancel_called = self.custom_cancel_activity_called + + class CustomCancelActivityNexusOpHandler( + nexus.TemporalOperationHandler[str, None] + ): + @override + async def start_operation( + self, + ctx: nexus.TemporalStartOperationContext, + client: nexus.TemporalNexusClient, + input: str, + ) -> nexus.TemporalOperationResult[None]: + result = await client.start_activity( + wait_for_cancel_activity, + id=input, + start_to_close_timeout=timedelta(seconds=30), + heartbeat_timeout=timedelta(seconds=1), + ) + started.set() + return result + + @override + async def cancel_activity( + self, + ctx: nexus.TemporalCancelOperationContext, + options: nexus.CancelActivityOptions, + ): + # record that the custom override ran + cancel_called.set() + + # get a handle to the activity and cancel it + handle = nexus.client().get_activity_handle(options.activity_id) + await handle.cancel() + + return CustomCancelActivityNexusOpHandler() + @workflow.defn class EchoWorkflowCaller: @@ -560,6 +730,80 @@ async def test_temporal_operation_update_workflow_delayed( assert expected_backward_link in handler_links +async def test_temporal_operation_cancel_rejects_unknown_tokens(): + class FakeNexusTaskCancellation(OperationTaskCancellation): + def is_cancelled(self) -> bool: + return False + + def cancellation_reason(self) -> str | None: + return None + + def wait_until_cancelled_sync(self, timeout: float | None = None) -> bool: + return False + + async def wait_until_cancelled(self) -> None: + return None + + def cancel(self, _reason: str) -> bool: + return False + + cancel_ctx = CancelOperationContext( + service="TestService", + operation="echo", + headers={}, + task_cancellation=FakeNexusTaskCancellation(), + ) + + service_handler = TestServiceHandler() + + # Use a factory style operation form the handler to allow calling cancel directly + op_handler = service_handler.custom_cancel() + + # Invalid token type + token = OperationToken(type=30, namespace="default") # type: ignore + with pytest.raises(nexusrpc.HandlerError) as err: + await op_handler.cancel(cancel_ctx, token.encode()) + assert err.value.type == HandlerErrorType.INTERNAL + assert not err.value.retryable + underlying = err.value.__cause__ + assert isinstance(underlying, TypeError) + assert "unknown token type, got 30" in str(underlying) + + # Workflow ID missing from workflow type + token = OperationToken(type=OperationTokenType.WORKFLOW, namespace="default") + with pytest.raises(nexusrpc.HandlerError) as err: + await op_handler.cancel(cancel_ctx, token.encode()) + assert err.value.type == HandlerErrorType.INTERNAL + assert not err.value.retryable + underlying = err.value.__cause__ + assert isinstance(underlying, TypeError) + assert "expected non-empty workflow id for token type `WORKFLOW`" in str(underlying) + + # Activity ID missing from activity type + token = OperationToken(type=OperationTokenType.ACTIVITY, namespace="default") + with pytest.raises(nexusrpc.HandlerError) as err: + await op_handler.cancel(cancel_ctx, token.encode()) + assert err.value.type == HandlerErrorType.INTERNAL + assert not err.value.retryable + underlying = err.value.__cause__ + assert isinstance(underlying, TypeError) + assert "expected non-empty activity id for token type `ACTIVITY`" in str(underlying) + + activity_op_handler = service_handler.custom_cancel_activity() + for run_id in (None, ""): + token = OperationToken( + type=OperationTokenType.ACTIVITY, + namespace="default", + activity_id="activity-id", + run_id=run_id, + ) + with pytest.raises(nexusrpc.HandlerError) as err: + await activity_op_handler.cancel(cancel_ctx, token.encode()) + assert err.value.type == HandlerErrorType.INTERNAL + assert not err.value.retryable + assert not service_handler.custom_cancel_activity_called.is_set() + + @workflow.defn class BlockingWorkflow: def __init__(self) -> None: @@ -787,6 +1031,41 @@ async def test_temporal_operation_failed_start_allows_retry( await conflict_handle.cancel() +async def test_temporal_operation_mixed_start_raises_handler_err( + client: Client, env: WorkflowEnvironment +): + if env.supports_time_skipping: + pytest.skip( + "Standalone Nexus Operation tests don't work with time-skipping server" + ) + + task_queue = str(uuid.uuid4()) + endpoint_name = make_nexus_endpoint_name(task_queue) + await env.create_nexus_endpoint(endpoint_name, task_queue) + async with Worker( + env.client, + task_queue=task_queue, + nexus_service_handlers=[TestServiceHandler()], + workflows=[EchoWorkflow], + activities=[echo_activity], + ): + nexus_client = client.create_nexus_client(TestService, endpoint_name) + + with pytest.raises(NexusOperationFailureError) as err: + await nexus_client.execute_operation( + TestService.mixed_start, + Input(value="test", task_queue=task_queue), + id=str(uuid.uuid4()), + ) + + assert isinstance(err.value.cause, nexusrpc.HandlerError) + assert err.value.cause.type == HandlerErrorType.BAD_REQUEST + assert ( + "Only one async operation can be started per operation handler invocation" + in err.value.cause.message + ) + + @workflow.defn class SyncResultCaller: @workflow.run @@ -826,6 +1105,184 @@ async def test_temporal_operation_sync_result(client: Client, env: WorkflowEnvir ) +async def test_temporal_operation_start_activity( + client: Client, env: WorkflowEnvironment +): + if env.supports_time_skipping: + pytest.skip( + "Standalone Nexus Operation tests don't work with time-skipping server" + ) + + task_queue = str(uuid.uuid4()) + endpoint_name = make_nexus_endpoint_name(task_queue) + await env.create_nexus_endpoint(endpoint_name, task_queue) + async with Worker( + env.client, + task_queue=task_queue, + nexus_service_handlers=[TestServiceHandler()], + activities=[echo_activity], + ): + nexus_client = client.create_nexus_client(TestService, endpoint_name) + + result = await nexus_client.execute_operation( + TestService.echo_activity, + Input(value="test", task_queue=task_queue), + id=str(uuid.uuid4()), + ) + assert result == "test" + + +async def test_temporal_operation_start_activity_raises_error( + client: Client, env: WorkflowEnvironment +): + if env.supports_time_skipping: + pytest.skip( + "Standalone Nexus Operation tests don't work with time-skipping server" + ) + + task_queue = str(uuid.uuid4()) + endpoint_name = make_nexus_endpoint_name(task_queue) + await env.create_nexus_endpoint(endpoint_name, task_queue) + async with Worker( + env.client, + task_queue=task_queue, + nexus_service_handlers=[TestServiceHandler()], + activities=[raise_error_activity], + ): + nexus_client = client.create_nexus_client(TestService, endpoint_name) + + with pytest.raises(NexusOperationFailureError) as err: + await nexus_client.execute_operation( + TestService.error_activity, + Input(value="test", task_queue=task_queue), + id=str(uuid.uuid4()), + ) + + operation_err = err.value.__cause__ + assert isinstance(operation_err, temporalio.exceptions.ApplicationError) + assert operation_err.type == "OperationError" + assert "nexus operation completed unsuccessfully" in str(operation_err) + + application_err = operation_err.__cause__ + assert isinstance(application_err, temporalio.exceptions.ApplicationError) + + assert application_err.type == "test-activity-error-type" + assert "test-activity-error-message" in str(application_err) + assert application_err.__cause__ is None + + +async def test_temporal_operation_cancel_activity( + client: Client, env: WorkflowEnvironment +): + if env.supports_time_skipping: + pytest.skip( + "Standalone Nexus Operation tests don't work with time-skipping server" + ) + + task_queue = str(uuid.uuid4()) + endpoint_name = make_nexus_endpoint_name(task_queue) + await env.create_nexus_endpoint(endpoint_name, task_queue) + async with Worker( + env.client, + task_queue=task_queue, + nexus_service_handlers=[TestServiceHandler()], + activities=[wait_for_cancel_activity], + ): + nexus_client = client.create_nexus_client(TestService, endpoint_name) + + activity_id = f"blocking-activity-{uuid.uuid4()}" + op_handle = await nexus_client.start_operation( + TestService.blocking_activity, activity_id, id=str(uuid.uuid4()) + ) + + await op_handle.cancel() + + activity_handle = client.get_activity_handle(activity_id) + + async def check_cancelled(): + op_desc = await op_handle.describe() + assert op_desc.status is NexusOperationExecutionStatus.CANCELED + activity_desc = await activity_handle.describe() + assert activity_desc.status is ActivityExecutionStatus.CANCELED + + await assert_eventually(check_cancelled) + + +async def test_customized_temporal_operation_cancel_activity( + client: Client, env: WorkflowEnvironment +): + if env.supports_time_skipping: + pytest.skip( + "Standalone Nexus Operation tests don't work with time-skipping server" + ) + + task_queue = str(uuid.uuid4()) + endpoint_name = make_nexus_endpoint_name(task_queue) + await env.create_nexus_endpoint(endpoint_name, task_queue) + + service_handler = TestServiceHandler() + async with Worker( + env.client, + task_queue=task_queue, + nexus_service_handlers=[service_handler], + activities=[wait_for_cancel_activity], + ): + nexus_client = client.create_nexus_client(TestService, endpoint_name) + + activity_id = f"custom-cancel-activity-{uuid.uuid4()}" + op_handle = await nexus_client.start_operation( + TestService.custom_cancel_activity, activity_id, id=str(uuid.uuid4()) + ) + await service_handler.started_custom_cancel_activity.wait() + + await op_handle.cancel() + + activity_handle = client.get_activity_handle(activity_id) + + async def check_cancelled(): + assert service_handler.custom_cancel_activity_called.is_set() + op_desc = await op_handle.describe() + assert op_desc.status is NexusOperationExecutionStatus.CANCELED + activity_desc = await activity_handle.describe() + assert activity_desc.status is ActivityExecutionStatus.CANCELED + + await assert_eventually(check_cancelled) + + +async def test_temporal_operation_double_start_activity_raises_handler_err( + client: Client, env: WorkflowEnvironment +): + if env.supports_time_skipping: + pytest.skip( + "Standalone Nexus Operation tests don't work with time-skipping server" + ) + + task_queue = str(uuid.uuid4()) + endpoint_name = make_nexus_endpoint_name(task_queue) + await env.create_nexus_endpoint(endpoint_name, task_queue) + async with Worker( + env.client, + task_queue=task_queue, + nexus_service_handlers=[TestServiceHandler()], + activities=[echo_activity], + ): + nexus_client = client.create_nexus_client(TestService, endpoint_name) + + with pytest.raises(NexusOperationFailureError) as err: + await nexus_client.execute_operation( + TestService.double_start_activity, + Input(value="test", task_queue=task_queue), + id=str(uuid.uuid4()), + ) + + assert isinstance(err.value.cause, nexusrpc.HandlerError) + assert err.value.cause.type == HandlerErrorType.BAD_REQUEST + assert ( + "Only one async operation can be started per operation handler invocation" + in err.value.cause.message + ) + + @dataclass class TemporalOperationOverloadTestValue: value: int @@ -1071,3 +1528,64 @@ async def do_update(self, value: str) -> str: self.order_status = value update_result = f"Updated workflow status from {status} to {value}" return update_result + + +async def test_temporal_operation_includes_activity_token_in_callback( + client: Client, env: WorkflowEnvironment +): + if env.supports_time_skipping: + pytest.skip( + "Standalone Nexus Operation tests don't work with time-skipping server" + ) + task_queue = str(uuid.uuid4()) + endpoint_name = make_nexus_endpoint_name(task_queue) + await env.create_nexus_endpoint(endpoint_name, task_queue) + + @service_handler + class ActivityTokenHandler: + @nexus.temporal_operation + async def echo_activity( + self, + _ctx: nexus.TemporalStartOperationContext, + client: nexus.TemporalNexusClient, + input: Input, + ) -> nexus.TemporalOperationResult[str]: + return await client.start_activity( + echo_activity, + input, + id=input.value, + start_to_close_timeout=timedelta(seconds=10), + start_delay=timedelta(milliseconds=100), + ) + + async with Worker( + client, + task_queue=task_queue, + nexus_service_handlers=[ActivityTokenHandler()], + activities=[echo_activity], + ): + input_value = f"test-{uuid.uuid4()}" + + nexus_client = client.create_nexus_client(ActivityTokenHandler, endpoint_name) + + result = await nexus_client.execute_operation( + ActivityTokenHandler.echo_activity, + Input(value=input_value, task_queue=task_queue), + id=str(uuid.uuid4()), + ) + assert result == input_value + + activity_handle = client.get_activity_handle(input_value) + + desc = await activity_handle.describe() + token = desc.raw_callbacks[0].info.callback.nexus.header[ + "nexus-operation-token" + ] + + expected_token = OperationToken( + type=OperationTokenType.ACTIVITY, + namespace=client.namespace, + activity_id=input_value, + ).encode() + + assert token == expected_token From f5485fff17c21a2472041ae78925092ac6316ec1 Mon Sep 17 00:00:00 2001 From: Thomas Hardy Date: Mon, 3 Aug 2026 15:26:16 -0400 Subject: [PATCH 202/226] bump test timeout (#1711) --- tests/contrib/openai_agents/test_openai.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/contrib/openai_agents/test_openai.py b/tests/contrib/openai_agents/test_openai.py index 23c8939a5..df12685f0 100644 --- a/tests/contrib/openai_agents/test_openai.py +++ b/tests/contrib/openai_agents/test_openai.py @@ -461,7 +461,7 @@ async def test_tool_failure_workflow(client: Client): "What is the weather in Tokio?", id=f"tools-failure-workflow-{uuid.uuid4()}", task_queue=worker.task_queue, - execution_timeout=timedelta(seconds=2), + execution_timeout=timedelta(seconds=30), ) with pytest.raises(WorkflowFailureError) as e: await workflow_handle.result() From 24699e21dc1e4a0c8525df9164188e9c189b7d69 Mon Sep 17 00:00:00 2001 From: Saksham Goyal <144555727+Sakshamm-Goyal@users.noreply.github.com> Date: Tue, 4 Aug 2026 01:21:13 +0530 Subject: [PATCH 203/226] fix: preserve restricted proxies after in-place operations (#1706) * fix: preserve restricted proxies after in-place operations * fix(sandbox): type in-place proxy binder --- .../worker/workflow_sandbox/_restrictions.py | 6 ++++-- .../worker/workflow_sandbox/test_restrictions.py | 15 +++++++++++++++ 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/temporalio/worker/workflow_sandbox/_restrictions.py b/temporalio/worker/workflow_sandbox/_restrictions.py index 78b7a0363..34f9efee2 100644 --- a/temporalio/worker/workflow_sandbox/_restrictions.py +++ b/temporalio/worker/workflow_sandbox/_restrictions.py @@ -860,6 +860,8 @@ def set_on_proxy(self, v: _RestrictedProxy) -> None: class _RestrictedProxyLookup: + bind_func: Callable[[_RestrictedProxy, Any], Callable[..., Any]] | None + def __init__( self, access_func: Callable | None = None, @@ -951,12 +953,12 @@ def __init__( def bind_f(instance: _RestrictedProxy, obj: Any) -> Callable: def i_op(self: Any, other: Any) -> _RestrictedProxy: - f(self, other) # type: ignore + access_func(self, other) # type: ignore return instance return i_op.__get__(obj, type(obj)) # type: ignore - self.bind_f = bind_f + self.bind_func = bind_f _OpF = TypeVar("_OpF", bound=Callable[..., Any]) diff --git a/tests/worker/workflow_sandbox/test_restrictions.py b/tests/worker/workflow_sandbox/test_restrictions.py index bd1aaf749..ec001ba19 100644 --- a/tests/worker/workflow_sandbox/test_restrictions.py +++ b/tests/worker/workflow_sandbox/test_restrictions.py @@ -75,6 +75,21 @@ def test_restricted_proxy_dunder_methods(): assert f"{restricted_path_obj}" == expected_path +def test_restricted_proxy_in_place_operations_preserve_proxy(): + restricted_list = _RestrictedProxy( + "list", + list, + RestrictionContext(), + SandboxMatcher(), + ) + values = restricted_list([1]) + + values += [2] + + assert type(values) is _RestrictedProxy + assert RestrictionContext.unwrap_if_proxied(values) == [1, 2] + + def test_workflow_sandbox_restricted_proxy(): obj_class = _RestrictedProxy( "RestrictableObject", From 556485e49a737e5becd48894e2ae4491a2e8035b Mon Sep 17 00:00:00 2001 From: Tim Conley Date: Tue, 4 Aug 2026 10:26:23 -0700 Subject: [PATCH 204/226] Revert "refactor: move workflow task duration logging to core (#1698)" (#1720) This reverts commit 245847db474a90dbbd969821851cb5bd6ecfc960. --- temporalio/bridge/proto/common/__init__.py | 2 - temporalio/bridge/proto/common/common_pb2.py | 20 +- temporalio/bridge/proto/common/common_pb2.pyi | 53 ------ .../workflow_completion_pb2.py | 12 +- .../workflow_completion_pb2.pyi | 36 +--- temporalio/bridge/sdk-core | 2 +- temporalio/worker/_workflow.py | 105 ++++++++--- tests/worker/test_extstore.py | 174 ++++++++++-------- 8 files changed, 186 insertions(+), 218 deletions(-) diff --git a/temporalio/bridge/proto/common/__init__.py b/temporalio/bridge/proto/common/__init__.py index a8506090d..5622fffb8 100644 --- a/temporalio/bridge/proto/common/__init__.py +++ b/temporalio/bridge/proto/common/__init__.py @@ -1,12 +1,10 @@ from .common_pb2 import ( - ExternalStorageMetrics, NamespacedWorkflowExecution, VersioningIntent, WorkerDeploymentVersion, ) __all__ = [ - "ExternalStorageMetrics", "NamespacedWorkflowExecution", "VersioningIntent", "WorkerDeploymentVersion", diff --git a/temporalio/bridge/proto/common/common_pb2.py b/temporalio/bridge/proto/common/common_pb2.py index 481cf216d..c56456fce 100644 --- a/temporalio/bridge/proto/common/common_pb2.py +++ b/temporalio/bridge/proto/common/common_pb2.py @@ -18,7 +18,7 @@ from google.protobuf import duration_pb2 as google_dot_protobuf_dot_duration__pb2 DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile( - b'\n%temporal/sdk/core/common/common.proto\x12\x0e\x63oresdk.common\x1a\x1egoogle/protobuf/duration.proto"U\n\x1bNamespacedWorkflowExecution\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t"D\n\x17WorkerDeploymentVersion\x12\x17\n\x0f\x64\x65ployment_name\x18\x01 \x01(\t\x12\x10\n\x08\x62uild_id\x18\x02 \x01(\t"\x92\x01\n\x16\x45xternalStorageMetrics\x12\x15\n\rpayload_count\x18\x01 \x01(\x04\x12\x18\n\x10total_size_bytes\x18\x02 \x01(\x04\x12\x31\n\x0etotal_duration\x18\x03 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x14\n\x0c\x64river_names\x18\x04 \x03(\t*@\n\x10VersioningIntent\x12\x0f\n\x0bUNSPECIFIED\x10\x00\x12\x0e\n\nCOMPATIBLE\x10\x01\x12\x0b\n\x07\x44\x45\x46\x41ULT\x10\x02\x42,\xea\x02)Temporalio::Internal::Bridge::Api::Commonb\x06proto3' + b'\n%temporal/sdk/core/common/common.proto\x12\x0e\x63oresdk.common\x1a\x1egoogle/protobuf/duration.proto"U\n\x1bNamespacedWorkflowExecution\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t"D\n\x17WorkerDeploymentVersion\x12\x17\n\x0f\x64\x65ployment_name\x18\x01 \x01(\t\x12\x10\n\x08\x62uild_id\x18\x02 \x01(\t*@\n\x10VersioningIntent\x12\x0f\n\x0bUNSPECIFIED\x10\x00\x12\x0e\n\nCOMPATIBLE\x10\x01\x12\x0b\n\x07\x44\x45\x46\x41ULT\x10\x02\x42,\xea\x02)Temporalio::Internal::Bridge::Api::Commonb\x06proto3' ) _VERSIONINGINTENT = DESCRIPTOR.enum_types_by_name["VersioningIntent"] @@ -32,7 +32,6 @@ "NamespacedWorkflowExecution" ] _WORKERDEPLOYMENTVERSION = DESCRIPTOR.message_types_by_name["WorkerDeploymentVersion"] -_EXTERNALSTORAGEMETRICS = DESCRIPTOR.message_types_by_name["ExternalStorageMetrics"] NamespacedWorkflowExecution = _reflection.GeneratedProtocolMessageType( "NamespacedWorkflowExecution", (_message.Message,), @@ -55,28 +54,15 @@ ) _sym_db.RegisterMessage(WorkerDeploymentVersion) -ExternalStorageMetrics = _reflection.GeneratedProtocolMessageType( - "ExternalStorageMetrics", - (_message.Message,), - { - "DESCRIPTOR": _EXTERNALSTORAGEMETRICS, - "__module__": "temporal.sdk.core.common.common_pb2", - # @@protoc_insertion_point(class_scope:coresdk.common.ExternalStorageMetrics) - }, -) -_sym_db.RegisterMessage(ExternalStorageMetrics) - if _descriptor._USE_C_DESCRIPTORS == False: DESCRIPTOR._options = None DESCRIPTOR._serialized_options = ( b"\352\002)Temporalio::Internal::Bridge::Api::Common" ) - _VERSIONINGINTENT._serialized_start = 395 - _VERSIONINGINTENT._serialized_end = 459 + _VERSIONINGINTENT._serialized_start = 246 + _VERSIONINGINTENT._serialized_end = 310 _NAMESPACEDWORKFLOWEXECUTION._serialized_start = 89 _NAMESPACEDWORKFLOWEXECUTION._serialized_end = 174 _WORKERDEPLOYMENTVERSION._serialized_start = 176 _WORKERDEPLOYMENTVERSION._serialized_end = 244 - _EXTERNALSTORAGEMETRICS._serialized_start = 247 - _EXTERNALSTORAGEMETRICS._serialized_end = 393 # @@protoc_insertion_point(module_scope) diff --git a/temporalio/bridge/proto/common/common_pb2.pyi b/temporalio/bridge/proto/common/common_pb2.pyi index 8862fa036..739a129e1 100644 --- a/temporalio/bridge/proto/common/common_pb2.pyi +++ b/temporalio/bridge/proto/common/common_pb2.pyi @@ -4,13 +4,10 @@ isort:skip_file """ import builtins -import collections.abc import sys import typing import google.protobuf.descriptor -import google.protobuf.duration_pb2 -import google.protobuf.internal.containers import google.protobuf.internal.enum_type_wrapper import google.protobuf.message @@ -124,53 +121,3 @@ class WorkerDeploymentVersion(google.protobuf.message.Message): ) -> None: ... global___WorkerDeploymentVersion = WorkerDeploymentVersion - -class ExternalStorageMetrics(google.protobuf.message.Message): - """Metrics for a set of external payload storage operations (all uploads and downloads) - performed while processing a task, so core can emit unified logging and metrics. - """ - - DESCRIPTOR: google.protobuf.descriptor.Descriptor - - PAYLOAD_COUNT_FIELD_NUMBER: builtins.int - TOTAL_SIZE_BYTES_FIELD_NUMBER: builtins.int - TOTAL_DURATION_FIELD_NUMBER: builtins.int - DRIVER_NAMES_FIELD_NUMBER: builtins.int - payload_count: builtins.int - """Number of payloads stored or retrieved externally.""" - total_size_bytes: builtins.int - """Total size in bytes of the externally stored or retrieved payloads.""" - @property - def total_duration(self) -> google.protobuf.duration_pb2.Duration: - """Wall-clock time spent on the external storage operations.""" - @property - def driver_names( - self, - ) -> google.protobuf.internal.containers.RepeatedScalarFieldContainer[builtins.str]: - """Names of the drivers that participated in the operations.""" - def __init__( - self, - *, - payload_count: builtins.int = ..., - total_size_bytes: builtins.int = ..., - total_duration: google.protobuf.duration_pb2.Duration | None = ..., - driver_names: collections.abc.Iterable[builtins.str] | None = ..., - ) -> None: ... - def HasField( - self, field_name: typing_extensions.Literal["total_duration", b"total_duration"] - ) -> builtins.bool: ... - def ClearField( - self, - field_name: typing_extensions.Literal[ - "driver_names", - b"driver_names", - "payload_count", - b"payload_count", - "total_duration", - b"total_duration", - "total_size_bytes", - b"total_size_bytes", - ], - ) -> None: ... - -global___ExternalStorageMetrics = ExternalStorageMetrics diff --git a/temporalio/bridge/proto/workflow_completion/workflow_completion_pb2.py b/temporalio/bridge/proto/workflow_completion/workflow_completion_pb2.py index 057b301e4..ce26b220d 100644 --- a/temporalio/bridge/proto/workflow_completion/workflow_completion_pb2.py +++ b/temporalio/bridge/proto/workflow_completion/workflow_completion_pb2.py @@ -31,7 +31,7 @@ ) DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile( - b'\n?temporal/sdk/core/workflow_completion/workflow_completion.proto\x12\x1b\x63oresdk.workflow_completion\x1a%temporal/api/failure/v1/message.proto\x1a(temporal/api/enums/v1/failed_cause.proto\x1a$temporal/api/enums/v1/workflow.proto\x1a%temporal/sdk/core/common/common.proto\x1a;temporal/sdk/core/workflow_commands/workflow_commands.proto"\xbe\x02\n\x1cWorkflowActivationCompletion\x12\x0e\n\x06run_id\x18\x01 \x01(\t\x12:\n\nsuccessful\x18\x02 \x01(\x0b\x32$.coresdk.workflow_completion.SuccessH\x00\x12\x36\n\x06\x66\x61iled\x18\x03 \x01(\x0b\x32$.coresdk.workflow_completion.FailureH\x00\x12H\n\x18payload_download_metrics\x18\x04 \x01(\x0b\x32&.coresdk.common.ExternalStorageMetrics\x12\x46\n\x16payload_upload_metrics\x18\x05 \x01(\x0b\x32&.coresdk.common.ExternalStorageMetricsB\x08\n\x06status"\xac\x01\n\x07Success\x12<\n\x08\x63ommands\x18\x01 \x03(\x0b\x32*.coresdk.workflow_commands.WorkflowCommand\x12\x1b\n\x13used_internal_flags\x18\x06 \x03(\r\x12\x46\n\x13versioning_behavior\x18\x07 \x01(\x0e\x32).temporal.api.enums.v1.VersioningBehavior"\x81\x01\n\x07\x46\x61ilure\x12\x31\n\x07\x66\x61ilure\x18\x01 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12\x43\n\x0b\x66orce_cause\x18\x02 \x01(\x0e\x32..temporal.api.enums.v1.WorkflowTaskFailedCauseB8\xea\x02\x35Temporalio::Internal::Bridge::Api::WorkflowCompletionb\x06proto3' + b'\n?temporal/sdk/core/workflow_completion/workflow_completion.proto\x12\x1b\x63oresdk.workflow_completion\x1a%temporal/api/failure/v1/message.proto\x1a(temporal/api/enums/v1/failed_cause.proto\x1a$temporal/api/enums/v1/workflow.proto\x1a%temporal/sdk/core/common/common.proto\x1a;temporal/sdk/core/workflow_commands/workflow_commands.proto"\xac\x01\n\x1cWorkflowActivationCompletion\x12\x0e\n\x06run_id\x18\x01 \x01(\t\x12:\n\nsuccessful\x18\x02 \x01(\x0b\x32$.coresdk.workflow_completion.SuccessH\x00\x12\x36\n\x06\x66\x61iled\x18\x03 \x01(\x0b\x32$.coresdk.workflow_completion.FailureH\x00\x42\x08\n\x06status"\xac\x01\n\x07Success\x12<\n\x08\x63ommands\x18\x01 \x03(\x0b\x32*.coresdk.workflow_commands.WorkflowCommand\x12\x1b\n\x13used_internal_flags\x18\x06 \x03(\r\x12\x46\n\x13versioning_behavior\x18\x07 \x01(\x0e\x32).temporal.api.enums.v1.VersioningBehavior"\x81\x01\n\x07\x46\x61ilure\x12\x31\n\x07\x66\x61ilure\x18\x01 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12\x43\n\x0b\x66orce_cause\x18\x02 \x01(\x0e\x32..temporal.api.enums.v1.WorkflowTaskFailedCauseB8\xea\x02\x35Temporalio::Internal::Bridge::Api::WorkflowCompletionb\x06proto3' ) @@ -79,9 +79,9 @@ b"\352\0025Temporalio::Internal::Bridge::Api::WorkflowCompletion" ) _WORKFLOWACTIVATIONCOMPLETION._serialized_start = 316 - _WORKFLOWACTIVATIONCOMPLETION._serialized_end = 634 - _SUCCESS._serialized_start = 637 - _SUCCESS._serialized_end = 809 - _FAILURE._serialized_start = 812 - _FAILURE._serialized_end = 941 + _WORKFLOWACTIVATIONCOMPLETION._serialized_end = 488 + _SUCCESS._serialized_start = 491 + _SUCCESS._serialized_end = 663 + _FAILURE._serialized_start = 666 + _FAILURE._serialized_end = 795 # @@protoc_insertion_point(module_scope) diff --git a/temporalio/bridge/proto/workflow_completion/workflow_completion_pb2.pyi b/temporalio/bridge/proto/workflow_completion/workflow_completion_pb2.pyi index 8e12736aa..5b438f360 100644 --- a/temporalio/bridge/proto/workflow_completion/workflow_completion_pb2.pyi +++ b/temporalio/bridge/proto/workflow_completion/workflow_completion_pb2.pyi @@ -14,7 +14,6 @@ import google.protobuf.message import temporalio.api.enums.v1.failed_cause_pb2 import temporalio.api.enums.v1.workflow_pb2 import temporalio.api.failure.v1.message_pb2 -import temporalio.bridge.proto.common.common_pb2 import temporalio.bridge.proto.workflow_commands.workflow_commands_pb2 if sys.version_info >= (3, 8): @@ -32,52 +31,23 @@ class WorkflowActivationCompletion(google.protobuf.message.Message): RUN_ID_FIELD_NUMBER: builtins.int SUCCESSFUL_FIELD_NUMBER: builtins.int FAILED_FIELD_NUMBER: builtins.int - PAYLOAD_DOWNLOAD_METRICS_FIELD_NUMBER: builtins.int - PAYLOAD_UPLOAD_METRICS_FIELD_NUMBER: builtins.int run_id: builtins.str """The run id from the workflow activation you are completing""" @property def successful(self) -> global___Success: ... @property def failed(self) -> global___Failure: ... - @property - def payload_download_metrics( - self, - ) -> temporalio.bridge.proto.common.common_pb2.ExternalStorageMetrics: - """Metrics for external payload storage downloads (retrievals) performed while processing - this activation. Only set when external storage retrieved payloads. - """ - @property - def payload_upload_metrics( - self, - ) -> temporalio.bridge.proto.common.common_pb2.ExternalStorageMetrics: - """Metrics for external payload storage uploads (stores) performed while processing this - activation. Only set when external storage stored payloads. - """ def __init__( self, *, run_id: builtins.str = ..., successful: global___Success | None = ..., failed: global___Failure | None = ..., - payload_download_metrics: temporalio.bridge.proto.common.common_pb2.ExternalStorageMetrics - | None = ..., - payload_upload_metrics: temporalio.bridge.proto.common.common_pb2.ExternalStorageMetrics - | None = ..., ) -> None: ... def HasField( self, field_name: typing_extensions.Literal[ - "failed", - b"failed", - "payload_download_metrics", - b"payload_download_metrics", - "payload_upload_metrics", - b"payload_upload_metrics", - "status", - b"status", - "successful", - b"successful", + "failed", b"failed", "status", b"status", "successful", b"successful" ], ) -> builtins.bool: ... def ClearField( @@ -85,10 +55,6 @@ class WorkflowActivationCompletion(google.protobuf.message.Message): field_name: typing_extensions.Literal[ "failed", b"failed", - "payload_download_metrics", - b"payload_download_metrics", - "payload_upload_metrics", - b"payload_upload_metrics", "run_id", b"run_id", "status", diff --git a/temporalio/bridge/sdk-core b/temporalio/bridge/sdk-core index ce69d10f0..d2769368d 160000 --- a/temporalio/bridge/sdk-core +++ b/temporalio/bridge/sdk-core @@ -1 +1 @@ -Subproject commit ce69d10f0e80ec154264c3a7ed395af1e18aa796 +Subproject commit d2769368df9077a311537431ff4594c9c14db4e7 diff --git a/temporalio/worker/_workflow.py b/temporalio/worker/_workflow.py index 1b217b4a5..c031b5653 100644 --- a/temporalio/worker/_workflow.py +++ b/temporalio/worker/_workflow.py @@ -9,13 +9,13 @@ import os import sys import threading +import time from collections.abc import Awaitable, Callable, MutableMapping, Sequence from dataclasses import dataclass -from datetime import timezone +from datetime import timedelta, timezone from types import TracebackType import temporalio.api.common.v1 -import temporalio.bridge.proto.common import temporalio.bridge.proto.workflow_activation import temporalio.bridge.proto.workflow_completion import temporalio.bridge.runtime @@ -64,17 +64,6 @@ _DEFAULT_WORKFLOW_TASK_EXTERNAL_STORAGE_CONCURRENCY: int = 3 -def _set_external_storage_metrics( - target: temporalio.bridge.proto.common.ExternalStorageMetrics, - metrics: temporalio.converter._extstore.StorageOperationMetrics, -) -> None: - """Populate a proto ``ExternalStorageMetrics`` from measured storage metrics.""" - target.payload_count = metrics.payload_count - target.total_size_bytes = metrics.total_size - target.total_duration.FromTimedelta(metrics.total_duration) - target.driver_names.extend(sorted(metrics.driver_names)) - - class _WorkflowWorker: # type:ignore[reportUnusedClass] def __init__( self, @@ -336,6 +325,7 @@ async def _handle_activation( completion.successful.SetInParent() workflow = None data_converter = self._data_converter + task_start_time = time.monotonic() download_metrics = temporalio.converter._extstore.StorageOperationMetrics() try: if LOG_PROTOS: @@ -510,17 +500,6 @@ async def _handle_activation( completion.failed.Clear() completion.failed.failure.message = f"Failed encoding completion: {err}" - # Reported on the completion so core can include them in its workflow-task duration - # log; core measures the duration itself. - if download_metrics.payload_count > 0: - _set_external_storage_metrics( - completion.payload_download_metrics, download_metrics - ) - if upload_metrics.payload_count > 0: - _set_external_storage_metrics( - completion.payload_upload_metrics, upload_metrics - ) - # Send off completion if LOG_PROTOS: logger.debug("Sending workflow completion:\n%s", completion) @@ -532,6 +511,84 @@ async def _handle_activation( "Failed completing activation on workflow with run ID %s", act.run_id ) + # Log workflow task duration with external storage metrics + self._log_workflow_task_duration( + act, workflow, task_start_time, download_metrics, upload_metrics + ) + + def _log_workflow_task_duration( + self, + act: temporalio.bridge.proto.workflow_activation.WorkflowActivation, + workflow: _RunningWorkflow | None, + task_start_time: float, + download_metrics: temporalio.converter._extstore.StorageOperationMetrics, + upload_metrics: temporalio.converter._extstore.StorageOperationMetrics, + ) -> None: + task_duration = timedelta(seconds=time.monotonic() - task_start_time) + + def _fmt_duration(td: timedelta) -> str: + secs = td.total_seconds() + if secs >= 1: + return f"{secs:.3f}s" + return f"{secs * 1000:.3f}ms" + + completed_event_id = act.history_length + 1 + _info = workflow.get_info() if workflow is not None else None + attempt = _info.attempt if _info is not None else "unknown" + log_id = f"{act.run_id}:{completed_event_id}:{attempt}" + msg_details, extra = temporalio.workflow._build_log_context( + _info._logger_details() if _info is not None else None, + full_workflow_info=_info, + ) + msg_details["event_id"] = completed_event_id + msg_details["workflow_task_duration"] = _fmt_duration(task_duration) + msg_details["workflow_history_size"] = act.history_size_bytes + extra["event_id"] = completed_event_id + extra["workflow_task_duration"] = task_duration + extra["workflow_history_size"] = act.history_size_bytes + if download_metrics.payload_count > 0: + msg_details["payload_download_count"] = download_metrics.payload_count + msg_details["payload_download_size"] = download_metrics.total_size + msg_details["payload_download_duration"] = _fmt_duration( + download_metrics.total_duration + ) + msg_details["payload_download_drivers"] = sorted( + download_metrics.driver_names + ) + extra["payload_download_count"] = download_metrics.payload_count + extra["payload_download_size"] = download_metrics.total_size + extra["payload_download_duration"] = download_metrics.total_duration + extra["payload_download_drivers"] = sorted(download_metrics.driver_names) + if upload_metrics.payload_count > 0: + msg_details["payload_upload_count"] = upload_metrics.payload_count + msg_details["payload_upload_size"] = upload_metrics.total_size + msg_details["payload_upload_duration"] = _fmt_duration( + upload_metrics.total_duration + ) + msg_details["payload_upload_drivers"] = sorted(upload_metrics.driver_names) + extra["payload_upload_count"] = upload_metrics.payload_count + extra["payload_upload_size"] = upload_metrics.total_size + extra["payload_upload_duration"] = upload_metrics.total_duration + extra["payload_upload_drivers"] = sorted(upload_metrics.driver_names) + if task_duration.total_seconds() > 10: + logger.warning( + f"[TMPRL1104] {log_id} Workflow task exceeded 10 seconds (%s)", + msg_details, + extra=extra, + ) + elif task_duration.total_seconds() > 5: + logger.info( + f"[TMPRL1104] {log_id} Workflow task exceeded 5 seconds (%s)", + msg_details, + extra=extra, + ) + else: + logger.debug( + f"[TMPRL1104] {log_id} Workflow task duration information (%s)", + msg_details, + extra=extra, + ) + async def _handle_cache_eviction( self, act: temporalio.bridge.proto.workflow_activation.WorkflowActivation, diff --git a/tests/worker/test_extstore.py b/tests/worker/test_extstore.py index e8ef8edb2..2f8fde5fe 100644 --- a/tests/worker/test_extstore.py +++ b/tests/worker/test_extstore.py @@ -1,7 +1,8 @@ -import contextlib import dataclasses +import logging +import re import uuid -from collections.abc import Iterator, Sequence +from collections.abc import Sequence from dataclasses import dataclass from datetime import timedelta from unittest import mock @@ -10,10 +11,10 @@ import temporalio import temporalio.bridge.client -import temporalio.bridge.proto.workflow_completion import temporalio.bridge.worker import temporalio.client import temporalio.converter +import temporalio.worker._workflow from temporalio import activity, workflow from temporalio.api.common.v1 import Payload from temporalio.client import Client, WorkflowFailureError, WorkflowHandle @@ -30,7 +31,7 @@ from temporalio.exceptions import ActivityError, ApplicationError from temporalio.testing._workflow import WorkflowEnvironment from temporalio.worker import Replayer -from tests.helpers import assert_task_fail_eventually, new_worker +from tests.helpers import LogCapturer, assert_task_fail_eventually, new_worker from tests.test_extstore import InMemoryTestDriver @@ -598,32 +599,19 @@ async def test_worker_storage_drivers_empty_without_external_storage( # TMPRL1104 workflow task duration logging # --------------------------------------------------------------------------- -# The duration log itself is emitted (and tested) in sdk-core. The Python worker's part is -# attaching the external-storage metrics to the completion, so these tests capture the -# completion and assert on its fields directly rather than on core's asynchronously -# forwarded log, which would be nondeterministic to observe here. +_workflow_logger = logging.getLogger(temporalio.worker._workflow.__name__) -@contextlib.contextmanager -def _capture_completions() -> Iterator[ - list[temporalio.bridge.proto.workflow_completion.WorkflowActivationCompletion] -]: - """Capture every WorkflowActivationCompletion the worker hands to core.""" - completions: list[ - temporalio.bridge.proto.workflow_completion.WorkflowActivationCompletion - ] = [] - original = temporalio.bridge.worker.Worker.complete_workflow_activation +def _tmprl1104_records(capturer: LogCapturer) -> list[logging.LogRecord]: + """Return all TMPRL1104 log records from the capturer.""" + return capturer.find_all(lambda r: r.getMessage().startswith("[TMPRL1104]")) - async def capturing(self, completion): # type: ignore[no-untyped-def] - completions.append(completion) - return await original(self, completion) - with mock.patch.object( - temporalio.bridge.worker.Worker, - "complete_workflow_activation", - capturing, - ): - yield completions +# Accept any duration-bucket wording: a loaded host can push a trivial task past 5s. +_TMPRL1104_DURATION_MESSAGE = re.compile( + r"\[TMPRL1104\] [^:]+:\d+:\d+ Workflow task " + r"(?:duration information|exceeded \d+ seconds) \(" +) async def _expected_payload_size( @@ -634,33 +622,44 @@ async def _expected_payload_size( return payloads[0].ByteSize() +@workflow.defn +class SimpleWorkflow: + """Minimal workflow for testing logging without external storage.""" + + @workflow.run + async def run(self) -> str: + return "done" + + async def test_tmprl1104_no_extstore(env: WorkflowEnvironment) -> None: - """Without external storage configured, completions carry no storage metrics.""" - with _capture_completions() as completions: - async with new_worker( - env.client, ExtStoreWorkflow, activities=[ext_store_activity] - ) as worker: + """Without external storage, TMPRL1104 logs contain duration but no + download/upload metrics.""" + with LogCapturer().logs_captured(_workflow_logger, level=logging.DEBUG) as capturer: + async with new_worker(env.client, SimpleWorkflow) as worker: await env.client.execute_workflow( - ExtStoreWorkflow.run, - ExtStoreWorkflowInput( - input_data="small", - activity_input_size=10, - activity_output_size=10, - output_size=10, - ), + SimpleWorkflow.run, id=f"workflow-{uuid.uuid4()}", task_queue=worker.task_queue, ) - assert completions, "expected the worker to complete at least one activation" - for c in completions: - assert not c.HasField("payload_download_metrics") - assert not c.HasField("payload_upload_metrics") + records = _tmprl1104_records(capturer) + assert len(records) == 1 + record = records[0] + assert _TMPRL1104_DURATION_MESSAGE.match(record.getMessage()) + assert hasattr(record, "workflow_task_duration") + assert hasattr(record, "event_id") + # No external storage — download/upload fields must be absent + assert not hasattr(record, "payload_download_count") + assert not hasattr(record, "payload_download_size") + assert not hasattr(record, "payload_download_duration") + assert not hasattr(record, "payload_upload_count") + assert not hasattr(record, "payload_upload_size") + assert not hasattr(record, "payload_upload_duration") async def test_tmprl1104_with_extstore_download(env: WorkflowEnvironment) -> None: - """When external storage retrieves payloads, the completion for the WFT that - retrieved them carries download metrics.""" + """When external storage decodes payloads, TMPRL1104 logs include download + metrics on the activation that retrieves them.""" driver = InMemoryTestDriver() data_converter = dataclasses.replace( temporalio.converter.default(), @@ -681,7 +680,7 @@ async def test_tmprl1104_with_extstore_download(env: WorkflowEnvironment) -> Non ) expected_input_size = await _expected_payload_size(data_converter, wf_input) - with _capture_completions() as completions: + with LogCapturer().logs_captured(_workflow_logger, level=logging.DEBUG) as capturer: async with new_worker( client, ExtStoreWorkflow, activities=[ext_store_activity] ) as worker: @@ -692,19 +691,25 @@ async def test_tmprl1104_with_extstore_download(env: WorkflowEnvironment) -> Non task_queue=worker.task_queue, ) - downloads = [c for c in completions if c.HasField("payload_download_metrics")] - assert len(downloads) == 1 - m = downloads[0].payload_download_metrics - assert m.payload_count == 1 - assert m.total_size_bytes == expected_input_size - assert m.total_duration.ToTimedelta() > timedelta(0) - assert list(m.driver_names) == [driver.name()] - assert not any(c.HasField("payload_upload_metrics") for c in completions) + records = _tmprl1104_records(capturer) + assert len(records) == 2 + + # WFT 1: retrieves the externalized workflow input + assert _TMPRL1104_DURATION_MESSAGE.match(records[0].getMessage()) + assert getattr(records[0], "payload_download_count") == 1 + assert getattr(records[0], "payload_download_size") == expected_input_size + assert getattr(records[0], "payload_download_duration") > timedelta(0) + assert not hasattr(records[0], "payload_upload_count") + + # WFT 2: activity result is small — no external storage + assert _TMPRL1104_DURATION_MESSAGE.match(records[1].getMessage()) + assert not hasattr(records[1], "payload_download_count") + assert not hasattr(records[1], "payload_upload_count") async def test_tmprl1104_with_extstore_upload(env: WorkflowEnvironment) -> None: - """When external storage stores payloads, the completion for the WFT that - produced them carries upload metrics.""" + """When external storage encodes payloads, TMPRL1104 logs include upload + metrics on the WFT that produces them.""" driver = InMemoryTestDriver() data_converter = dataclasses.replace( temporalio.converter.default(), @@ -720,7 +725,7 @@ async def test_tmprl1104_with_extstore_upload(env: WorkflowEnvironment) -> None: wf_output = "wo" * 1024 # 2048 bytes → stored externally expected_output_size = await _expected_payload_size(data_converter, wf_output) - with _capture_completions() as completions: + with LogCapturer().logs_captured(_workflow_logger, level=logging.DEBUG) as capturer: async with new_worker( client, ExtStoreWorkflow, activities=[ext_store_activity] ) as worker: @@ -736,21 +741,27 @@ async def test_tmprl1104_with_extstore_upload(env: WorkflowEnvironment) -> None: task_queue=worker.task_queue, ) - uploads = [c for c in completions if c.HasField("payload_upload_metrics")] - assert len(uploads) == 1 - m = uploads[0].payload_upload_metrics - assert m.payload_count == 1 - assert m.total_size_bytes == expected_output_size - assert m.total_duration.ToTimedelta() > timedelta(0) - assert list(m.driver_names) == [driver.name()] - assert not any(c.HasField("payload_download_metrics") for c in completions) + records = _tmprl1104_records(capturer) + assert len(records) == 2 + + # WFT 1: small input — no external storage + assert _TMPRL1104_DURATION_MESSAGE.match(records[0].getMessage()) + assert not hasattr(records[0], "payload_download_count") + assert not hasattr(records[0], "payload_upload_count") + + # WFT 2: workflow returns large result → uploaded + assert _TMPRL1104_DURATION_MESSAGE.match(records[1].getMessage()) + assert not hasattr(records[1], "payload_download_count") + assert getattr(records[1], "payload_upload_count") == 1 + assert getattr(records[1], "payload_upload_size") == expected_output_size + assert getattr(records[1], "payload_upload_duration") > timedelta(0) async def test_tmprl1104_with_extstore_download_and_upload( env: WorkflowEnvironment, ) -> None: - """When both download and upload happen across WFTs, the respective completions - carry the matching metrics.""" + """When both download and upload happen across WFTs, TMPRL1104 logs include + both sets of metrics.""" driver = InMemoryTestDriver() data_converter = dataclasses.replace( temporalio.converter.default(), @@ -773,7 +784,7 @@ async def test_tmprl1104_with_extstore_download_and_upload( wf_output = "wo" * 1024 expected_output_size = await _expected_payload_size(data_converter, wf_output) - with _capture_completions() as completions: + with LogCapturer().logs_captured(_workflow_logger, level=logging.DEBUG) as capturer: async with new_worker( client, ExtStoreWorkflow, activities=[ext_store_activity] ) as worker: @@ -784,19 +795,22 @@ async def test_tmprl1104_with_extstore_download_and_upload( task_queue=worker.task_queue, ) - downloads = [c for c in completions if c.HasField("payload_download_metrics")] - assert len(downloads) == 1 - dm = downloads[0].payload_download_metrics - assert dm.payload_count == 1 - assert dm.total_size_bytes == expected_input_size - assert dm.total_duration.ToTimedelta() > timedelta(0) - - uploads = [c for c in completions if c.HasField("payload_upload_metrics")] - assert len(uploads) == 1 - um = uploads[0].payload_upload_metrics - assert um.payload_count == 1 - assert um.total_size_bytes == expected_output_size - assert um.total_duration.ToTimedelta() > timedelta(0) + records = _tmprl1104_records(capturer) + assert len(records) == 2 + + # WFT 1: retrieves externalized workflow input + assert _TMPRL1104_DURATION_MESSAGE.match(records[0].getMessage()) + assert getattr(records[0], "payload_download_count") == 1 + assert getattr(records[0], "payload_download_size") == expected_input_size + assert getattr(records[0], "payload_download_duration") > timedelta(0) + assert not hasattr(records[0], "payload_upload_count") + + # WFT 2: uploads externalized workflow result + assert _TMPRL1104_DURATION_MESSAGE.match(records[1].getMessage()) + assert not hasattr(records[1], "payload_download_count") + assert getattr(records[1], "payload_upload_count") == 1 + assert getattr(records[1], "payload_upload_size") == expected_output_size + assert getattr(records[1], "payload_upload_duration") > timedelta(0) # --------------------------------------------------------------------------- From 4f78fa41ba234496474c2538a0a756341084f370 Mon Sep 17 00:00:00 2001 From: Brian Strauch Date: Tue, 4 Aug 2026 11:10:22 -0700 Subject: [PATCH 205/226] Forward MCP server config through GeminiTestServer.plugin() (#1721) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit GoogleGenAIPlugin already accepts mcp_servers and mcp_connection_idle_timeout, but GeminiTestServer.plugin() constructed the plugin without them, so a test for an MCP-grounded workflow could not use the public testing helper — it had to build GoogleGenAIPlugin itself and monkeypatch genai.Client._api_client to script the model. Forward both arguments. The MCP servers are not scripted: list_tools/call_tool run for real against the given sessions while only the model HTTP layer is faked. Co-authored-by: Claude Opus 5 (1M context) --- temporalio/contrib/google_genai/testing.py | 34 +++++++++++-- tests/contrib/google_genai/test_gemini_mcp.py | 51 +++++++++++++++++++ 2 files changed, 81 insertions(+), 4 deletions(-) diff --git a/temporalio/contrib/google_genai/testing.py b/temporalio/contrib/google_genai/testing.py index d7884c636..5d4a40486 100644 --- a/temporalio/contrib/google_genai/testing.py +++ b/temporalio/contrib/google_genai/testing.py @@ -30,13 +30,17 @@ import json from collections.abc import Sequence -from typing import Any +from datetime import timedelta +from typing import TYPE_CHECKING, Any from google.genai import Client as GeminiClient from google.genai.types import HttpResponse as SdkHttpResponse from temporalio.contrib.google_genai._google_genai_plugin import GoogleGenAIPlugin +if TYPE_CHECKING: + from temporalio.contrib.google_genai._mcp import McpSessionFactory + __all__ = [ "GeminiTestServer", "function_call_response", @@ -100,7 +104,8 @@ class GeminiTestServer: Only model calls (``client.models``) are scripted. File, interaction, and agent operations are not; mock those on a ``genai.Client`` directly if a - test needs them. + test needs them. MCP servers can be registered with + ``plugin(mcp_servers=...)`` and run for real. """ def __init__(self, responses: Sequence[str]) -> None: @@ -119,12 +124,29 @@ def _next(self) -> str: ) return self._responses[idx] - def plugin(self) -> GoogleGenAIPlugin: + def plugin( + self, + *, + mcp_servers: dict[str, McpSessionFactory] | None = None, + mcp_connection_idle_timeout: timedelta | None = None, + ) -> GoogleGenAIPlugin: """Return a :class:`GoogleGenAIPlugin` whose model calls serve the script. The real plugin activities run; only the underlying HTTP layer is replaced, so request formatting and the AFC loop are exercised exactly as in production. + + Args: + mcp_servers: MCP servers to expose to workflows, as on + :class:`temporalio.contrib.google_genai.GoogleGenAIPlugin`. + These are *not* scripted — ``list_tools`` / ``call_tool`` run + for real against the given sessions — so a test can drive an + MCP tool call with a scripted + :func:`function_call_response` and assert on what the server + actually returned. + mcp_connection_idle_timeout: How long an idle worker-side MCP + connection stays open, as on + :class:`temporalio.contrib.google_genai.GoogleGenAIPlugin`. """ client = GeminiClient(api_key="fake-test-key") @@ -148,4 +170,8 @@ async def _gen() -> Any: client._api_client.async_request = fake_async_request # type: ignore[assignment] client._api_client.async_request_streamed = fake_async_request_streamed # type: ignore[assignment] - return GoogleGenAIPlugin(client) + return GoogleGenAIPlugin( + client, + mcp_servers=mcp_servers, + mcp_connection_idle_timeout=mcp_connection_idle_timeout, + ) diff --git a/tests/contrib/google_genai/test_gemini_mcp.py b/tests/contrib/google_genai/test_gemini_mcp.py index 3b32c28ca..04e36bb9d 100644 --- a/tests/contrib/google_genai/test_gemini_mcp.py +++ b/tests/contrib/google_genai/test_gemini_mcp.py @@ -15,6 +15,7 @@ from __future__ import annotations +import json import sys from collections.abc import AsyncIterator from contextlib import AbstractAsyncContextManager, asynccontextmanager @@ -36,6 +37,11 @@ TemporalMcpClientSession, ) from temporalio.contrib.google_genai._temporal_interactions import _deserialize +from temporalio.contrib.google_genai.testing import ( + GeminiTestServer, + function_call_response, + text_response, +) from temporalio.worker import Replayer from temporalio.workflow import ActivityConfig from tests.contrib.google_genai.test_gemini import ( @@ -325,6 +331,51 @@ async def test_mcp_side_effects(client: Client): } +async def test_mcp_via_gemini_test_server(client: Client): + """GeminiTestServer.plugin(mcp_servers=...) scripts the model, runs MCP for real. + + This is the public testing path — the tests above reach into + ``GeminiApiCaller`` to also count API calls, but a user testing an + MCP-grounded workflow should need nothing but ``GeminiTestServer``. + """ + server = "echo_public" + test_server = GeminiTestServer( + [ + function_call_response("echo", {"message": "durable execution"}), + text_response("The echo tool returned: durable execution"), + ] + ) + + config = client.config() + config["plugins"] = [test_server.plugin(mcp_servers={server: _echo_session})] + new_client = Client(**config) + + async with new_worker(new_client, McpToolWorkflow) as worker: + handle = await new_client.start_workflow( + McpToolWorkflow.run, + args=[server, "echo the phrase: durable execution"], + id=f"gemini-mcp-public-{uuid4()}", + task_queue=worker.task_queue, + execution_timeout=timedelta(seconds=30), + ) + result = await handle.result() + names = await _activity_names(handle) + + assert result == "The echo tool returned: durable execution" + # The MCP activities really ran; only the model HTTP layer was scripted. + assert names == [ + f"{server}-list-tools", + "gemini_api_client_async_request", + f"{server}-call-tool", + "gemini_api_client_async_request", + ] + # The echoed message reached the model as a function response. + assert any( + "durable execution" in json.dumps(request) + for request in test_server.requests[1:] + ) + + # --------------------------------------------------------------------------- # Server-side pass-through tests (no shim code) # --------------------------------------------------------------------------- From 39b820d6786cf6e75edb983fb715b13bfb7c1bae Mon Sep 17 00:00:00 2001 From: Frenchwood <46058503+JoshuaFrenchwood@users.noreply.github.com> Date: Tue, 4 Aug 2026 15:05:31 -0500 Subject: [PATCH 206/226] Updating Temporal API protos (#1719) --- temporalio/api/activity/v1/message_pb2.py | 28 +- temporalio/api/activity/v1/message_pb2.pyi | 15 +- temporalio/api/common/v1/__init__.py | 6 + temporalio/api/common/v1/message_pb2.py | 54 +- temporalio/api/common/v1/message_pb2.pyi | 235 +++- temporalio/api/enums/v1/__init__.py | 2 + temporalio/api/enums/v1/failed_cause_pb2.py | 25 +- temporalio/api/enums/v1/failed_cause_pb2.pyi | 6 + temporalio/api/enums/v1/time_skipping_pb2.py | 35 + temporalio/api/enums/v1/time_skipping_pb2.pyi | 74 ++ temporalio/api/history/v1/message_pb2.pyi | 6 +- temporalio/api/namespace/v1/message_pb2.py | 34 +- temporalio/api/namespace/v1/message_pb2.pyi | 9 + temporalio/api/worker/v1/__init__.py | 2 + temporalio/api/worker/v1/message_pb2.py | 155 ++- temporalio/api/worker/v1/message_pb2.pyi | 453 ++++++- temporalio/api/workflow/v1/message_pb2.py | 128 +- temporalio/api/workflow/v1/message_pb2.pyi | 14 + temporalio/api/workflowservice/v1/__init__.py | 4 + .../v1/request_response_pb2.py | 1149 +++++++++-------- .../v1/request_response_pb2.pyi | 165 ++- .../api/workflowservice/v1/service_pb2.py | 10 +- .../workflowservice/v1/service_pb2_grpc.py | 45 + .../workflowservice/v1/service_pb2_grpc.pyi | 10 + temporalio/bridge/sdk-core | 2 +- temporalio/bridge/services_generated.py | 18 + temporalio/bridge/src/client_rpc_generated.rs | 9 + 27 files changed, 1944 insertions(+), 749 deletions(-) create mode 100644 temporalio/api/enums/v1/time_skipping_pb2.py create mode 100644 temporalio/api/enums/v1/time_skipping_pb2.pyi diff --git a/temporalio/api/activity/v1/message_pb2.py b/temporalio/api/activity/v1/message_pb2.py index e3b6a79c6..59f79a3c5 100644 --- a/temporalio/api/activity/v1/message_pb2.py +++ b/temporalio/api/activity/v1/message_pb2.py @@ -43,7 +43,7 @@ ) DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile( - b'\n&temporal/api/activity/v1/message.proto\x12\x18temporal.api.activity.v1\x1a\x1egoogle/protobuf/duration.proto\x1a\x1fgoogle/protobuf/timestamp.proto\x1a$temporal/api/common/v1/message.proto\x1a(temporal/api/deployment/v1/message.proto\x1a$temporal/api/enums/v1/activity.proto\x1a&temporal/api/callback/v1/message.proto\x1a$temporal/api/enums/v1/workflow.proto\x1a%temporal/api/failure/v1/message.proto\x1a\'temporal/api/taskqueue/v1/message.proto\x1a\'temporal/api/sdk/v1/user_metadata.proto"\x8c\x01\n\x18\x41\x63tivityExecutionOutcome\x12\x32\n\x06result\x18\x01 \x01(\x0b\x32 .temporal.api.common.v1.PayloadsH\x00\x12\x33\n\x07\x66\x61ilure\x18\x02 \x01(\x0b\x32 .temporal.api.failure.v1.FailureH\x00\x42\x07\n\x05value"\xd7\x03\n\x0f\x41\x63tivityOptions\x12\x38\n\ntask_queue\x18\x01 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12<\n\x19schedule_to_close_timeout\x18\x02 \x01(\x0b\x32\x19.google.protobuf.Duration\x12<\n\x19schedule_to_start_timeout\x18\x03 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x39\n\x16start_to_close_timeout\x18\x04 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x34\n\x11heartbeat_timeout\x18\x05 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x39\n\x0cretry_policy\x18\x06 \x01(\x0b\x32#.temporal.api.common.v1.RetryPolicy\x12\x32\n\x08priority\x18\x07 \x01(\x0b\x32 .temporal.api.common.v1.Priority\x12.\n\x0bstart_delay\x18\x08 \x01(\x0b\x32\x19.google.protobuf.Duration"\xb6\x0e\n\x15\x41\x63tivityExecutionInfo\x12\x13\n\x0b\x61\x63tivity_id\x18\x01 \x01(\t\x12\x0e\n\x06run_id\x18\x02 \x01(\t\x12;\n\ractivity_type\x18\x03 \x01(\x0b\x32$.temporal.api.common.v1.ActivityType\x12>\n\x06status\x18\x04 \x01(\x0e\x32..temporal.api.enums.v1.ActivityExecutionStatus\x12>\n\trun_state\x18\x05 \x01(\x0e\x32+.temporal.api.enums.v1.PendingActivityState\x12\x12\n\ntask_queue\x18\x06 \x01(\t\x12<\n\x19schedule_to_close_timeout\x18\x07 \x01(\x0b\x32\x19.google.protobuf.Duration\x12<\n\x19schedule_to_start_timeout\x18\x08 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x39\n\x16start_to_close_timeout\x18\t \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x34\n\x11heartbeat_timeout\x18\n \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x39\n\x0cretry_policy\x18\x0b \x01(\x0b\x32#.temporal.api.common.v1.RetryPolicy\x12;\n\x11heartbeat_details\x18\x0c \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x37\n\x13last_heartbeat_time\x18\r \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x35\n\x11last_started_time\x18\x0e \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x0f\n\x07\x61ttempt\x18\x0f \x01(\x05\x12\x35\n\x12\x65xecution_duration\x18\x10 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x31\n\rschedule_time\x18\x11 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x33\n\x0f\x65xpiration_time\x18\x12 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12.\n\nclose_time\x18\x13 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x36\n\x0clast_failure\x18\x14 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12\x1c\n\x14last_worker_identity\x18\x15 \x01(\t\x12\x39\n\x16\x63urrent_retry_interval\x18\x16 \x01(\x0b\x32\x19.google.protobuf.Duration\x12>\n\x1alast_attempt_complete_time\x18\x17 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12>\n\x1anext_attempt_schedule_time\x18\x18 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12T\n\x17last_deployment_version\x18\x19 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersion\x12\x32\n\x08priority\x18\x1a \x01(\x0b\x32 .temporal.api.common.v1.Priority\x12\x1e\n\x16state_transition_count\x18\x1b \x01(\x03\x12\x18\n\x10state_size_bytes\x18\x1c \x01(\x03\x12\x43\n\x11search_attributes\x18\x1d \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes\x12.\n\x06header\x18\x1e \x01(\x0b\x32\x1e.temporal.api.common.v1.Header\x12\x38\n\ruser_metadata\x18\x1f \x01(\x0b\x32!.temporal.api.sdk.v1.UserMetadata\x12\x17\n\x0f\x63\x61nceled_reason\x18 \x01(\t\x12+\n\x05links\x18! \x03(\x0b\x32\x1c.temporal.api.common.v1.Link\x12\x1d\n\x15total_heartbeat_count\x18" \x01(\x03\x12\x10\n\x08sdk_name\x18# \x01(\t\x12\x13\n\x0bsdk_version\x18$ \x01(\t\x12.\n\x0bstart_delay\x18% \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x32\n\x0e\x65xecution_time\x18& \x01(\x0b\x32\x1a.google.protobuf.Timestamp"\x9e\x04\n\x19\x41\x63tivityExecutionListInfo\x12\x13\n\x0b\x61\x63tivity_id\x18\x01 \x01(\t\x12\x0e\n\x06run_id\x18\x02 \x01(\t\x12;\n\ractivity_type\x18\x03 \x01(\x0b\x32$.temporal.api.common.v1.ActivityType\x12\x31\n\rschedule_time\x18\x04 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12.\n\nclose_time\x18\x05 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12>\n\x06status\x18\x06 \x01(\x0e\x32..temporal.api.enums.v1.ActivityExecutionStatus\x12\x43\n\x11search_attributes\x18\x07 \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes\x12\x12\n\ntask_queue\x18\x08 \x01(\t\x12\x1e\n\x16state_transition_count\x18\t \x01(\x03\x12\x18\n\x10state_size_bytes\x18\n \x01(\x03\x12\x35\n\x12\x65xecution_duration\x18\x0b \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x32\n\x0e\x65xecution_time\x18\x0c \x01(\x0b\x32\x1a.google.protobuf.Timestamp"\xff\x01\n\x0c\x43\x61llbackInfo\x12?\n\x07trigger\x18\x01 \x01(\x0b\x32..temporal.api.activity.v1.CallbackInfo.Trigger\x12\x34\n\x04info\x18\x02 \x01(\x0b\x32&.temporal.api.callback.v1.CallbackInfo\x1a\x10\n\x0e\x41\x63tivityClosed\x1a\x66\n\x07Trigger\x12P\n\x0f\x61\x63tivity_closed\x18\x01 \x01(\x0b\x32\x35.temporal.api.activity.v1.CallbackInfo.ActivityClosedH\x00\x42\t\n\x07variantB\x93\x01\n\x1bio.temporal.api.activity.v1B\x0cMessageProtoP\x01Z\'go.temporal.io/api/activity/v1;activity\xaa\x02\x1aTemporalio.Api.Activity.V1\xea\x02\x1dTemporalio::Api::Activity::V1b\x06proto3' + b'\n&temporal/api/activity/v1/message.proto\x12\x18temporal.api.activity.v1\x1a\x1egoogle/protobuf/duration.proto\x1a\x1fgoogle/protobuf/timestamp.proto\x1a$temporal/api/common/v1/message.proto\x1a(temporal/api/deployment/v1/message.proto\x1a$temporal/api/enums/v1/activity.proto\x1a&temporal/api/callback/v1/message.proto\x1a$temporal/api/enums/v1/workflow.proto\x1a%temporal/api/failure/v1/message.proto\x1a\'temporal/api/taskqueue/v1/message.proto\x1a\'temporal/api/sdk/v1/user_metadata.proto"\xc4\x01\n\x18\x41\x63tivityExecutionOutcome\x12\x32\n\x06result\x18\x01 \x01(\x0b\x32 .temporal.api.common.v1.PayloadsH\x00\x12\x33\n\x07\x66\x61ilure\x18\x02 \x01(\x0b\x32 .temporal.api.failure.v1.FailureH\x00\x12\x36\n\x0bretry_state\x18\x03 \x01(\x0e\x32!.temporal.api.enums.v1.RetryStateB\x07\n\x05value"\xd7\x03\n\x0f\x41\x63tivityOptions\x12\x38\n\ntask_queue\x18\x01 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12<\n\x19schedule_to_close_timeout\x18\x02 \x01(\x0b\x32\x19.google.protobuf.Duration\x12<\n\x19schedule_to_start_timeout\x18\x03 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x39\n\x16start_to_close_timeout\x18\x04 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x34\n\x11heartbeat_timeout\x18\x05 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x39\n\x0cretry_policy\x18\x06 \x01(\x0b\x32#.temporal.api.common.v1.RetryPolicy\x12\x32\n\x08priority\x18\x07 \x01(\x0b\x32 .temporal.api.common.v1.Priority\x12.\n\x0bstart_delay\x18\x08 \x01(\x0b\x32\x19.google.protobuf.Duration"\xb6\x0e\n\x15\x41\x63tivityExecutionInfo\x12\x13\n\x0b\x61\x63tivity_id\x18\x01 \x01(\t\x12\x0e\n\x06run_id\x18\x02 \x01(\t\x12;\n\ractivity_type\x18\x03 \x01(\x0b\x32$.temporal.api.common.v1.ActivityType\x12>\n\x06status\x18\x04 \x01(\x0e\x32..temporal.api.enums.v1.ActivityExecutionStatus\x12>\n\trun_state\x18\x05 \x01(\x0e\x32+.temporal.api.enums.v1.PendingActivityState\x12\x12\n\ntask_queue\x18\x06 \x01(\t\x12<\n\x19schedule_to_close_timeout\x18\x07 \x01(\x0b\x32\x19.google.protobuf.Duration\x12<\n\x19schedule_to_start_timeout\x18\x08 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x39\n\x16start_to_close_timeout\x18\t \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x34\n\x11heartbeat_timeout\x18\n \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x39\n\x0cretry_policy\x18\x0b \x01(\x0b\x32#.temporal.api.common.v1.RetryPolicy\x12;\n\x11heartbeat_details\x18\x0c \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x37\n\x13last_heartbeat_time\x18\r \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x35\n\x11last_started_time\x18\x0e \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x0f\n\x07\x61ttempt\x18\x0f \x01(\x05\x12\x35\n\x12\x65xecution_duration\x18\x10 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x31\n\rschedule_time\x18\x11 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x33\n\x0f\x65xpiration_time\x18\x12 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12.\n\nclose_time\x18\x13 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x36\n\x0clast_failure\x18\x14 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12\x1c\n\x14last_worker_identity\x18\x15 \x01(\t\x12\x39\n\x16\x63urrent_retry_interval\x18\x16 \x01(\x0b\x32\x19.google.protobuf.Duration\x12>\n\x1alast_attempt_complete_time\x18\x17 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12>\n\x1anext_attempt_schedule_time\x18\x18 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12T\n\x17last_deployment_version\x18\x19 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersion\x12\x32\n\x08priority\x18\x1a \x01(\x0b\x32 .temporal.api.common.v1.Priority\x12\x1e\n\x16state_transition_count\x18\x1b \x01(\x03\x12\x18\n\x10state_size_bytes\x18\x1c \x01(\x03\x12\x43\n\x11search_attributes\x18\x1d \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes\x12.\n\x06header\x18\x1e \x01(\x0b\x32\x1e.temporal.api.common.v1.Header\x12\x38\n\ruser_metadata\x18\x1f \x01(\x0b\x32!.temporal.api.sdk.v1.UserMetadata\x12\x17\n\x0f\x63\x61nceled_reason\x18 \x01(\t\x12+\n\x05links\x18! \x03(\x0b\x32\x1c.temporal.api.common.v1.Link\x12\x1d\n\x15total_heartbeat_count\x18" \x01(\x03\x12\x10\n\x08sdk_name\x18# \x01(\t\x12\x13\n\x0bsdk_version\x18$ \x01(\t\x12.\n\x0bstart_delay\x18% \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x32\n\x0e\x65xecution_time\x18& \x01(\x0b\x32\x1a.google.protobuf.Timestamp"\x9e\x04\n\x19\x41\x63tivityExecutionListInfo\x12\x13\n\x0b\x61\x63tivity_id\x18\x01 \x01(\t\x12\x0e\n\x06run_id\x18\x02 \x01(\t\x12;\n\ractivity_type\x18\x03 \x01(\x0b\x32$.temporal.api.common.v1.ActivityType\x12\x31\n\rschedule_time\x18\x04 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12.\n\nclose_time\x18\x05 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12>\n\x06status\x18\x06 \x01(\x0e\x32..temporal.api.enums.v1.ActivityExecutionStatus\x12\x43\n\x11search_attributes\x18\x07 \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes\x12\x12\n\ntask_queue\x18\x08 \x01(\t\x12\x1e\n\x16state_transition_count\x18\t \x01(\x03\x12\x18\n\x10state_size_bytes\x18\n \x01(\x03\x12\x35\n\x12\x65xecution_duration\x18\x0b \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x32\n\x0e\x65xecution_time\x18\x0c \x01(\x0b\x32\x1a.google.protobuf.Timestamp"\xff\x01\n\x0c\x43\x61llbackInfo\x12?\n\x07trigger\x18\x01 \x01(\x0b\x32..temporal.api.activity.v1.CallbackInfo.Trigger\x12\x34\n\x04info\x18\x02 \x01(\x0b\x32&.temporal.api.callback.v1.CallbackInfo\x1a\x10\n\x0e\x41\x63tivityClosed\x1a\x66\n\x07Trigger\x12P\n\x0f\x61\x63tivity_closed\x18\x01 \x01(\x0b\x32\x35.temporal.api.activity.v1.CallbackInfo.ActivityClosedH\x00\x42\t\n\x07variantB\x93\x01\n\x1bio.temporal.api.activity.v1B\x0cMessageProtoP\x01Z\'go.temporal.io/api/activity/v1;activity\xaa\x02\x1aTemporalio.Api.Activity.V1\xea\x02\x1dTemporalio::Api::Activity::V1b\x06proto3' ) @@ -135,17 +135,17 @@ DESCRIPTOR._options = None DESCRIPTOR._serialized_options = b"\n\033io.temporal.api.activity.v1B\014MessageProtoP\001Z'go.temporal.io/api/activity/v1;activity\252\002\032Temporalio.Api.Activity.V1\352\002\035Temporalio::Api::Activity::V1" _ACTIVITYEXECUTIONOUTCOME._serialized_start = 451 - _ACTIVITYEXECUTIONOUTCOME._serialized_end = 591 - _ACTIVITYOPTIONS._serialized_start = 594 - _ACTIVITYOPTIONS._serialized_end = 1065 - _ACTIVITYEXECUTIONINFO._serialized_start = 1068 - _ACTIVITYEXECUTIONINFO._serialized_end = 2914 - _ACTIVITYEXECUTIONLISTINFO._serialized_start = 2917 - _ACTIVITYEXECUTIONLISTINFO._serialized_end = 3459 - _CALLBACKINFO._serialized_start = 3462 - _CALLBACKINFO._serialized_end = 3717 - _CALLBACKINFO_ACTIVITYCLOSED._serialized_start = 3597 - _CALLBACKINFO_ACTIVITYCLOSED._serialized_end = 3613 - _CALLBACKINFO_TRIGGER._serialized_start = 3615 - _CALLBACKINFO_TRIGGER._serialized_end = 3717 + _ACTIVITYEXECUTIONOUTCOME._serialized_end = 647 + _ACTIVITYOPTIONS._serialized_start = 650 + _ACTIVITYOPTIONS._serialized_end = 1121 + _ACTIVITYEXECUTIONINFO._serialized_start = 1124 + _ACTIVITYEXECUTIONINFO._serialized_end = 2970 + _ACTIVITYEXECUTIONLISTINFO._serialized_start = 2973 + _ACTIVITYEXECUTIONLISTINFO._serialized_end = 3515 + _CALLBACKINFO._serialized_start = 3518 + _CALLBACKINFO._serialized_end = 3773 + _CALLBACKINFO_ACTIVITYCLOSED._serialized_start = 3653 + _CALLBACKINFO_ACTIVITYCLOSED._serialized_end = 3669 + _CALLBACKINFO_TRIGGER._serialized_start = 3671 + _CALLBACKINFO_TRIGGER._serialized_end = 3773 # @@protoc_insertion_point(module_scope) diff --git a/temporalio/api/activity/v1/message_pb2.pyi b/temporalio/api/activity/v1/message_pb2.pyi index 46c3cef96..684233f95 100644 --- a/temporalio/api/activity/v1/message_pb2.pyi +++ b/temporalio/api/activity/v1/message_pb2.pyi @@ -36,17 +36,23 @@ class ActivityExecutionOutcome(google.protobuf.message.Message): RESULT_FIELD_NUMBER: builtins.int FAILURE_FIELD_NUMBER: builtins.int + RETRY_STATE_FIELD_NUMBER: builtins.int @property def result(self) -> temporalio.api.common.v1.message_pb2.Payloads: """The result if the activity completed successfully.""" @property def failure(self) -> temporalio.api.failure.v1.message_pb2.Failure: """The failure if the activity completed unsuccessfully.""" + retry_state: temporalio.api.enums.v1.workflow_pb2.RetryState.ValueType + """The retry state associated with an unsuccessful activity execution. + This field is only meaningful when `failure` is set. + """ def __init__( self, *, result: temporalio.api.common.v1.message_pb2.Payloads | None = ..., failure: temporalio.api.failure.v1.message_pb2.Failure | None = ..., + retry_state: temporalio.api.enums.v1.workflow_pb2.RetryState.ValueType = ..., ) -> None: ... def HasField( self, @@ -57,7 +63,14 @@ class ActivityExecutionOutcome(google.protobuf.message.Message): def ClearField( self, field_name: typing_extensions.Literal[ - "failure", b"failure", "result", b"result", "value", b"value" + "failure", + b"failure", + "result", + b"result", + "retry_state", + b"retry_state", + "value", + b"value", ], ) -> None: ... def WhichOneof( diff --git a/temporalio/api/common/v1/__init__.py b/temporalio/api/common/v1/__init__.py index 8764b274a..e613d71f8 100644 --- a/temporalio/api/common/v1/__init__.py +++ b/temporalio/api/common/v1/__init__.py @@ -4,6 +4,7 @@ Callback, DataBlob, Execution, + FastForwardConfig, Header, Link, Memo, @@ -17,6 +18,8 @@ RetryPolicy, SearchAttributes, TimeSkippingConfig, + TimeSkippingFastForwardInfo, + TimeSkippingInfo, TimeSkippingStatePropagation, WorkerSelector, WorkerVersionCapabilities, @@ -30,6 +33,7 @@ "Callback", "DataBlob", "Execution", + "FastForwardConfig", "GrpcStatus", "Header", "Link", @@ -44,6 +48,8 @@ "RetryPolicy", "SearchAttributes", "TimeSkippingConfig", + "TimeSkippingFastForwardInfo", + "TimeSkippingInfo", "TimeSkippingStatePropagation", "WorkerSelector", "WorkerVersionCapabilities", diff --git a/temporalio/api/common/v1/message_pb2.py b/temporalio/api/common/v1/message_pb2.py index ce5acffc7..538be6a23 100644 --- a/temporalio/api/common/v1/message_pb2.py +++ b/temporalio/api/common/v1/message_pb2.py @@ -29,7 +29,7 @@ ) DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile( - b'\n$temporal/api/common/v1/message.proto\x12\x16temporal.api.common.v1\x1a\x1egoogle/protobuf/duration.proto\x1a\x1bgoogle/protobuf/empty.proto\x1a\x1fgoogle/protobuf/timestamp.proto\x1a"temporal/api/enums/v1/common.proto\x1a&temporal/api/enums/v1/event_type.proto\x1a!temporal/api/enums/v1/reset.proto"T\n\x08\x44\x61taBlob\x12:\n\rencoding_type\x18\x01 \x01(\x0e\x32#.temporal.api.enums.v1.EncodingType\x12\x0c\n\x04\x64\x61ta\x18\x02 \x01(\x0c"=\n\x08Payloads\x12\x31\n\x08payloads\x18\x01 \x03(\x0b\x32\x1f.temporal.api.common.v1.Payload"\x8a\x02\n\x07Payload\x12?\n\x08metadata\x18\x01 \x03(\x0b\x32-.temporal.api.common.v1.Payload.MetadataEntry\x12\x0c\n\x04\x64\x61ta\x18\x02 \x01(\x0c\x12Q\n\x11\x65xternal_payloads\x18\x03 \x03(\x0b\x32\x36.temporal.api.common.v1.Payload.ExternalPayloadDetails\x1a/\n\rMetadataEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\x0c:\x02\x38\x01\x1a,\n\x16\x45xternalPayloadDetails\x12\x12\n\nsize_bytes\x18\x01 \x01(\x03"\xbe\x01\n\x10SearchAttributes\x12S\n\x0eindexed_fields\x18\x01 \x03(\x0b\x32;.temporal.api.common.v1.SearchAttributes.IndexedFieldsEntry\x1aU\n\x12IndexedFieldsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12.\n\x05value\x18\x02 \x01(\x0b\x32\x1f.temporal.api.common.v1.Payload:\x02\x38\x01"\x90\x01\n\x04Memo\x12\x38\n\x06\x66ields\x18\x01 \x03(\x0b\x32(.temporal.api.common.v1.Memo.FieldsEntry\x1aN\n\x0b\x46ieldsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12.\n\x05value\x18\x02 \x01(\x0b\x32\x1f.temporal.api.common.v1.Payload:\x02\x38\x01"\x94\x01\n\x06Header\x12:\n\x06\x66ields\x18\x01 \x03(\x0b\x32*.temporal.api.common.v1.Header.FieldsEntry\x1aN\n\x0b\x46ieldsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12.\n\x05value\x18\x02 \x01(\x0b\x32\x1f.temporal.api.common.v1.Payload:\x02\x38\x01"8\n\x11WorkflowExecution\x12\x13\n\x0bworkflow_id\x18\x01 \x01(\t\x12\x0e\n\x06run_id\x18\x02 \x01(\t"d\n\tExecution\x12\x32\n\x04type\x18\x01 \x01(\x0e\x32$.temporal.api.enums.v1.ExecutionType\x12\x13\n\x0b\x62usiness_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t"\x1c\n\x0cWorkflowType\x12\x0c\n\x04name\x18\x01 \x01(\t"\x1c\n\x0c\x41\x63tivityType\x12\x0c\n\x04name\x18\x01 \x01(\t"\xd1\x01\n\x0bRetryPolicy\x12\x33\n\x10initial_interval\x18\x01 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x1b\n\x13\x62\x61\x63koff_coefficient\x18\x02 \x01(\x01\x12\x33\n\x10maximum_interval\x18\x03 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x18\n\x10maximum_attempts\x18\x04 \x01(\x05\x12!\n\x19non_retryable_error_types\x18\x05 \x03(\t"F\n\x10MeteringMetadata\x12\x32\n*nonfirst_local_activity_execution_attempts\x18\r \x01(\r">\n\x12WorkerVersionStamp\x12\x10\n\x08\x62uild_id\x18\x01 \x01(\t\x12\x16\n\x0euse_versioning\x18\x03 \x01(\x08"e\n\x19WorkerVersionCapabilities\x12\x10\n\x08\x62uild_id\x18\x01 \x01(\t\x12\x16\n\x0euse_versioning\x18\x02 \x01(\x08\x12\x1e\n\x16\x64\x65ployment_series_name\x18\x04 \x01(\t"\xed\x02\n\x0cResetOptions\x12\x35\n\x13\x66irst_workflow_task\x18\x01 \x01(\x0b\x32\x16.google.protobuf.EmptyH\x00\x12\x34\n\x12last_workflow_task\x18\x02 \x01(\x0b\x32\x16.google.protobuf.EmptyH\x00\x12\x1a\n\x10workflow_task_id\x18\x03 \x01(\x03H\x00\x12\x12\n\x08\x62uild_id\x18\x04 \x01(\tH\x00\x12G\n\x12reset_reapply_type\x18\n \x01(\x0e\x32\'.temporal.api.enums.v1.ResetReapplyTypeB\x02\x18\x01\x12\x18\n\x10\x63urrent_run_only\x18\x0b \x01(\x08\x12S\n\x1breset_reapply_exclude_types\x18\x0c \x03(\x0e\x32..temporal.api.enums.v1.ResetReapplyExcludeTypeB\x08\n\x06target"\xe4\x02\n\x08\x43\x61llback\x12\x37\n\x05nexus\x18\x02 \x01(\x0b\x32&.temporal.api.common.v1.Callback.NexusH\x00\x12=\n\x08internal\x18\x03 \x01(\x0b\x32).temporal.api.common.v1.Callback.InternalH\x00\x12+\n\x05links\x18\x64 \x03(\x0b\x32\x1c.temporal.api.common.v1.Link\x1a\x87\x01\n\x05Nexus\x12\x0b\n\x03url\x18\x01 \x01(\t\x12\x42\n\x06header\x18\x02 \x03(\x0b\x32\x32.temporal.api.common.v1.Callback.Nexus.HeaderEntry\x1a-\n\x0bHeaderEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x1a\x18\n\x08Internal\x12\x0c\n\x04\x64\x61ta\x18\x01 \x01(\x0c\x42\t\n\x07variantJ\x04\x08\x01\x10\x02"\x8a\x08\n\x04Link\x12\x44\n\x0eworkflow_event\x18\x01 \x01(\x0b\x32*.temporal.api.common.v1.Link.WorkflowEventH\x00\x12:\n\tbatch_job\x18\x02 \x01(\x0b\x32%.temporal.api.common.v1.Link.BatchJobH\x00\x12\x39\n\x08\x61\x63tivity\x18\x03 \x01(\x0b\x32%.temporal.api.common.v1.Link.ActivityH\x00\x12\x46\n\x0fnexus_operation\x18\x04 \x01(\x0b\x32+.temporal.api.common.v1.Link.NexusOperationH\x00\x12\x39\n\x08workflow\x18\x05 \x01(\x0b\x32%.temporal.api.common.v1.Link.WorkflowH\x00\x1a\xb7\x03\n\rWorkflowEvent\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x12N\n\tevent_ref\x18\x64 \x01(\x0b\x32\x39.temporal.api.common.v1.Link.WorkflowEvent.EventReferenceH\x00\x12W\n\x0erequest_id_ref\x18\x65 \x01(\x0b\x32=.temporal.api.common.v1.Link.WorkflowEvent.RequestIdReferenceH\x00\x1aX\n\x0e\x45ventReference\x12\x10\n\x08\x65vent_id\x18\x01 \x01(\x03\x12\x34\n\nevent_type\x18\x02 \x01(\x0e\x32 .temporal.api.enums.v1.EventType\x1a^\n\x12RequestIdReference\x12\x12\n\nrequest_id\x18\x01 \x01(\t\x12\x34\n\nevent_type\x18\x02 \x01(\x0e\x32 .temporal.api.enums.v1.EventTypeB\x0b\n\treference\x1a\x1a\n\x08\x42\x61tchJob\x12\x0e\n\x06job_id\x18\x01 \x01(\t\x1a\x42\n\x08\x41\x63tivity\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0b\x61\x63tivity_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x1aI\n\x0eNexusOperation\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x14\n\x0coperation_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x1aR\n\x08Workflow\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x12\x0e\n\x06reason\x18\x04 \x01(\tB\t\n\x07variant"\'\n\tPrincipal\x12\x0c\n\x04type\x18\x01 \x01(\t\x12\x0c\n\x04name\x18\x02 \x01(\t"O\n\x08Priority\x12\x14\n\x0cpriority_key\x18\x01 \x01(\x05\x12\x14\n\x0c\x66\x61irness_key\x18\x02 \x01(\t\x12\x17\n\x0f\x66\x61irness_weight\x18\x03 \x01(\x02";\n\x0eWorkerSelector\x12\x1d\n\x13worker_instance_key\x18\x01 \x01(\tH\x00\x42\n\n\x08selector"i\n\x11OnConflictOptions\x12\x19\n\x11\x61ttach_request_id\x18\x01 \x01(\x08\x12#\n\x1b\x61ttach_completion_callbacks\x18\x02 \x01(\x08\x12\x14\n\x0c\x61ttach_links\x18\x03 \x01(\x08"s\n\x12TimeSkippingConfig\x12\x0f\n\x07\x65nabled\x18\x01 \x01(\x08\x12/\n\x0c\x66\x61st_forward\x18\x02 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x1b\n\x13\x64isable_propagation\x18\x03 \x01(\x08"\x99\x01\n\x1cTimeSkippingStatePropagation\x12;\n\x18initial_skipped_duration\x18\x01 \x01(\x0b\x32\x19.google.protobuf.Duration\x12<\n\x18\x66\x61st_forward_target_time\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.TimestampB\x89\x01\n\x19io.temporal.api.common.v1B\x0cMessageProtoP\x01Z#go.temporal.io/api/common/v1;common\xaa\x02\x18Temporalio.Api.Common.V1\xea\x02\x1bTemporalio::Api::Common::V1b\x06proto3' + b'\n$temporal/api/common/v1/message.proto\x12\x16temporal.api.common.v1\x1a\x1egoogle/protobuf/duration.proto\x1a\x1bgoogle/protobuf/empty.proto\x1a\x1fgoogle/protobuf/timestamp.proto\x1a"temporal/api/enums/v1/common.proto\x1a&temporal/api/enums/v1/event_type.proto\x1a!temporal/api/enums/v1/reset.proto"T\n\x08\x44\x61taBlob\x12:\n\rencoding_type\x18\x01 \x01(\x0e\x32#.temporal.api.enums.v1.EncodingType\x12\x0c\n\x04\x64\x61ta\x18\x02 \x01(\x0c"=\n\x08Payloads\x12\x31\n\x08payloads\x18\x01 \x03(\x0b\x32\x1f.temporal.api.common.v1.Payload"\x8a\x02\n\x07Payload\x12?\n\x08metadata\x18\x01 \x03(\x0b\x32-.temporal.api.common.v1.Payload.MetadataEntry\x12\x0c\n\x04\x64\x61ta\x18\x02 \x01(\x0c\x12Q\n\x11\x65xternal_payloads\x18\x03 \x03(\x0b\x32\x36.temporal.api.common.v1.Payload.ExternalPayloadDetails\x1a/\n\rMetadataEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\x0c:\x02\x38\x01\x1a,\n\x16\x45xternalPayloadDetails\x12\x12\n\nsize_bytes\x18\x01 \x01(\x03"\xbe\x01\n\x10SearchAttributes\x12S\n\x0eindexed_fields\x18\x01 \x03(\x0b\x32;.temporal.api.common.v1.SearchAttributes.IndexedFieldsEntry\x1aU\n\x12IndexedFieldsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12.\n\x05value\x18\x02 \x01(\x0b\x32\x1f.temporal.api.common.v1.Payload:\x02\x38\x01"\x90\x01\n\x04Memo\x12\x38\n\x06\x66ields\x18\x01 \x03(\x0b\x32(.temporal.api.common.v1.Memo.FieldsEntry\x1aN\n\x0b\x46ieldsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12.\n\x05value\x18\x02 \x01(\x0b\x32\x1f.temporal.api.common.v1.Payload:\x02\x38\x01"\x94\x01\n\x06Header\x12:\n\x06\x66ields\x18\x01 \x03(\x0b\x32*.temporal.api.common.v1.Header.FieldsEntry\x1aN\n\x0b\x46ieldsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12.\n\x05value\x18\x02 \x01(\x0b\x32\x1f.temporal.api.common.v1.Payload:\x02\x38\x01"8\n\x11WorkflowExecution\x12\x13\n\x0bworkflow_id\x18\x01 \x01(\t\x12\x0e\n\x06run_id\x18\x02 \x01(\t"d\n\tExecution\x12\x32\n\x04type\x18\x01 \x01(\x0e\x32$.temporal.api.enums.v1.ExecutionType\x12\x13\n\x0b\x62usiness_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t"\x1c\n\x0cWorkflowType\x12\x0c\n\x04name\x18\x01 \x01(\t"\x1c\n\x0c\x41\x63tivityType\x12\x0c\n\x04name\x18\x01 \x01(\t"\xd1\x01\n\x0bRetryPolicy\x12\x33\n\x10initial_interval\x18\x01 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x1b\n\x13\x62\x61\x63koff_coefficient\x18\x02 \x01(\x01\x12\x33\n\x10maximum_interval\x18\x03 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x18\n\x10maximum_attempts\x18\x04 \x01(\x05\x12!\n\x19non_retryable_error_types\x18\x05 \x03(\t"F\n\x10MeteringMetadata\x12\x32\n*nonfirst_local_activity_execution_attempts\x18\r \x01(\r">\n\x12WorkerVersionStamp\x12\x10\n\x08\x62uild_id\x18\x01 \x01(\t\x12\x16\n\x0euse_versioning\x18\x03 \x01(\x08"e\n\x19WorkerVersionCapabilities\x12\x10\n\x08\x62uild_id\x18\x01 \x01(\t\x12\x16\n\x0euse_versioning\x18\x02 \x01(\x08\x12\x1e\n\x16\x64\x65ployment_series_name\x18\x04 \x01(\t"\xed\x02\n\x0cResetOptions\x12\x35\n\x13\x66irst_workflow_task\x18\x01 \x01(\x0b\x32\x16.google.protobuf.EmptyH\x00\x12\x34\n\x12last_workflow_task\x18\x02 \x01(\x0b\x32\x16.google.protobuf.EmptyH\x00\x12\x1a\n\x10workflow_task_id\x18\x03 \x01(\x03H\x00\x12\x12\n\x08\x62uild_id\x18\x04 \x01(\tH\x00\x12G\n\x12reset_reapply_type\x18\n \x01(\x0e\x32\'.temporal.api.enums.v1.ResetReapplyTypeB\x02\x18\x01\x12\x18\n\x10\x63urrent_run_only\x18\x0b \x01(\x08\x12S\n\x1breset_reapply_exclude_types\x18\x0c \x03(\x0e\x32..temporal.api.enums.v1.ResetReapplyExcludeTypeB\x08\n\x06target"\xe4\x02\n\x08\x43\x61llback\x12\x37\n\x05nexus\x18\x02 \x01(\x0b\x32&.temporal.api.common.v1.Callback.NexusH\x00\x12=\n\x08internal\x18\x03 \x01(\x0b\x32).temporal.api.common.v1.Callback.InternalH\x00\x12+\n\x05links\x18\x64 \x03(\x0b\x32\x1c.temporal.api.common.v1.Link\x1a\x87\x01\n\x05Nexus\x12\x0b\n\x03url\x18\x01 \x01(\t\x12\x42\n\x06header\x18\x02 \x03(\x0b\x32\x32.temporal.api.common.v1.Callback.Nexus.HeaderEntry\x1a-\n\x0bHeaderEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x1a\x18\n\x08Internal\x12\x0c\n\x04\x64\x61ta\x18\x01 \x01(\x0c\x42\t\n\x07variantJ\x04\x08\x01\x10\x02"\x8a\x08\n\x04Link\x12\x44\n\x0eworkflow_event\x18\x01 \x01(\x0b\x32*.temporal.api.common.v1.Link.WorkflowEventH\x00\x12:\n\tbatch_job\x18\x02 \x01(\x0b\x32%.temporal.api.common.v1.Link.BatchJobH\x00\x12\x39\n\x08\x61\x63tivity\x18\x03 \x01(\x0b\x32%.temporal.api.common.v1.Link.ActivityH\x00\x12\x46\n\x0fnexus_operation\x18\x04 \x01(\x0b\x32+.temporal.api.common.v1.Link.NexusOperationH\x00\x12\x39\n\x08workflow\x18\x05 \x01(\x0b\x32%.temporal.api.common.v1.Link.WorkflowH\x00\x1a\xb7\x03\n\rWorkflowEvent\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x12N\n\tevent_ref\x18\x64 \x01(\x0b\x32\x39.temporal.api.common.v1.Link.WorkflowEvent.EventReferenceH\x00\x12W\n\x0erequest_id_ref\x18\x65 \x01(\x0b\x32=.temporal.api.common.v1.Link.WorkflowEvent.RequestIdReferenceH\x00\x1aX\n\x0e\x45ventReference\x12\x10\n\x08\x65vent_id\x18\x01 \x01(\x03\x12\x34\n\nevent_type\x18\x02 \x01(\x0e\x32 .temporal.api.enums.v1.EventType\x1a^\n\x12RequestIdReference\x12\x12\n\nrequest_id\x18\x01 \x01(\t\x12\x34\n\nevent_type\x18\x02 \x01(\x0e\x32 .temporal.api.enums.v1.EventTypeB\x0b\n\treference\x1a\x1a\n\x08\x42\x61tchJob\x12\x0e\n\x06job_id\x18\x01 \x01(\t\x1a\x42\n\x08\x41\x63tivity\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0b\x61\x63tivity_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x1aI\n\x0eNexusOperation\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x14\n\x0coperation_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x1aR\n\x08Workflow\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x12\x0e\n\x06reason\x18\x04 \x01(\tB\t\n\x07variant"\'\n\tPrincipal\x12\x0c\n\x04type\x18\x01 \x01(\t\x12\x0c\n\x04name\x18\x02 \x01(\t"O\n\x08Priority\x12\x14\n\x0cpriority_key\x18\x01 \x01(\x05\x12\x14\n\x0c\x66\x61irness_key\x18\x02 \x01(\t\x12\x17\n\x0f\x66\x61irness_weight\x18\x03 \x01(\x02";\n\x0eWorkerSelector\x12\x1d\n\x13worker_instance_key\x18\x01 \x01(\tH\x00\x42\n\n\x08selector"i\n\x11OnConflictOptions\x12\x19\n\x11\x61ttach_request_id\x18\x01 \x01(\x08\x12#\n\x1b\x61ttach_completion_callbacks\x18\x02 \x01(\x08\x12\x14\n\x0c\x61ttach_links\x18\x03 \x01(\x08"\xaa\x01\n\x12TimeSkippingConfig\x12\x0f\n\x07\x65nabled\x18\x01 \x01(\x08\x12\x46\n\x13\x66\x61st_forward_config\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.FastForwardConfig\x12\x1b\n\x13\x64isable_propagation\x18\x03 \x01(\x08\x12\x1e\n\x16max_session_skip_count\x18\x04 \x01(\x05"L\n\x11\x46\x61stForwardConfig\x12\n\n\x02id\x18\x01 \x01(\t\x12+\n\x08\x64uration\x18\x02 \x01(\x0b\x32\x19.google.protobuf.Duration"\xb5\x01\n\x1cTimeSkippingStatePropagation\x12;\n\x18initial_skipped_duration\x18\x01 \x01(\x0b\x32\x19.google.protobuf.Duration\x12<\n\x18\x66\x61st_forward_target_time\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x1a\n\x12initial_skip_count\x18\x03 \x01(\x05"\xfe\x01\n\x10TimeSkippingInfo\x12\x30\n\x0c\x63urrent_time\x18\x01 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x44\n\x10\x65\x66\x66\x65\x63tive_config\x18\x02 \x01(\x0b\x32*.temporal.api.common.v1.TimeSkippingConfig\x12N\n\x11\x66\x61st_forward_info\x18\x04 \x01(\x0b\x32\x33.temporal.api.common.v1.TimeSkippingFastForwardInfo\x12"\n\x1a\x63urrent_session_skip_count\x18\x06 \x01(\x05"\xb8\x01\n\x1bTimeSkippingFastForwardInfo\x12\x38\n\x15\x66\x61st_forward_duration\x18\x01 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x17\n\x0f\x66\x61st_forward_id\x18\x02 \x01(\t\x12/\n\x0btarget_time\x18\x03 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x15\n\rhas_completed\x18\x04 \x01(\x08\x42\x89\x01\n\x19io.temporal.api.common.v1B\x0cMessageProtoP\x01Z#go.temporal.io/api/common/v1;common\xaa\x02\x18Temporalio.Api.Common.V1\xea\x02\x1bTemporalio::Api::Common::V1b\x06proto3' ) @@ -80,9 +80,14 @@ _WORKERSELECTOR = DESCRIPTOR.message_types_by_name["WorkerSelector"] _ONCONFLICTOPTIONS = DESCRIPTOR.message_types_by_name["OnConflictOptions"] _TIMESKIPPINGCONFIG = DESCRIPTOR.message_types_by_name["TimeSkippingConfig"] +_FASTFORWARDCONFIG = DESCRIPTOR.message_types_by_name["FastForwardConfig"] _TIMESKIPPINGSTATEPROPAGATION = DESCRIPTOR.message_types_by_name[ "TimeSkippingStatePropagation" ] +_TIMESKIPPINGINFO = DESCRIPTOR.message_types_by_name["TimeSkippingInfo"] +_TIMESKIPPINGFASTFORWARDINFO = DESCRIPTOR.message_types_by_name[ + "TimeSkippingFastForwardInfo" +] DataBlob = _reflection.GeneratedProtocolMessageType( "DataBlob", (_message.Message,), @@ -475,6 +480,17 @@ ) _sym_db.RegisterMessage(TimeSkippingConfig) +FastForwardConfig = _reflection.GeneratedProtocolMessageType( + "FastForwardConfig", + (_message.Message,), + { + "DESCRIPTOR": _FASTFORWARDCONFIG, + "__module__": "temporalio.api.common.v1.message_pb2", + # @@protoc_insertion_point(class_scope:temporal.api.common.v1.FastForwardConfig) + }, +) +_sym_db.RegisterMessage(FastForwardConfig) + TimeSkippingStatePropagation = _reflection.GeneratedProtocolMessageType( "TimeSkippingStatePropagation", (_message.Message,), @@ -486,6 +502,28 @@ ) _sym_db.RegisterMessage(TimeSkippingStatePropagation) +TimeSkippingInfo = _reflection.GeneratedProtocolMessageType( + "TimeSkippingInfo", + (_message.Message,), + { + "DESCRIPTOR": _TIMESKIPPINGINFO, + "__module__": "temporalio.api.common.v1.message_pb2", + # @@protoc_insertion_point(class_scope:temporal.api.common.v1.TimeSkippingInfo) + }, +) +_sym_db.RegisterMessage(TimeSkippingInfo) + +TimeSkippingFastForwardInfo = _reflection.GeneratedProtocolMessageType( + "TimeSkippingFastForwardInfo", + (_message.Message,), + { + "DESCRIPTOR": _TIMESKIPPINGFASTFORWARDINFO, + "__module__": "temporalio.api.common.v1.message_pb2", + # @@protoc_insertion_point(class_scope:temporal.api.common.v1.TimeSkippingFastForwardInfo) + }, +) +_sym_db.RegisterMessage(TimeSkippingFastForwardInfo) + if _descriptor._USE_C_DESCRIPTORS == False: DESCRIPTOR._options = None DESCRIPTOR._serialized_options = b"\n\031io.temporal.api.common.v1B\014MessageProtoP\001Z#go.temporal.io/api/common/v1;common\252\002\030Temporalio.Api.Common.V1\352\002\033Temporalio::Api::Common::V1" @@ -573,8 +611,14 @@ _WORKERSELECTOR._serialized_end = 3794 _ONCONFLICTOPTIONS._serialized_start = 3796 _ONCONFLICTOPTIONS._serialized_end = 3901 - _TIMESKIPPINGCONFIG._serialized_start = 3903 - _TIMESKIPPINGCONFIG._serialized_end = 4018 - _TIMESKIPPINGSTATEPROPAGATION._serialized_start = 4021 - _TIMESKIPPINGSTATEPROPAGATION._serialized_end = 4174 + _TIMESKIPPINGCONFIG._serialized_start = 3904 + _TIMESKIPPINGCONFIG._serialized_end = 4074 + _FASTFORWARDCONFIG._serialized_start = 4076 + _FASTFORWARDCONFIG._serialized_end = 4152 + _TIMESKIPPINGSTATEPROPAGATION._serialized_start = 4155 + _TIMESKIPPINGSTATEPROPAGATION._serialized_end = 4336 + _TIMESKIPPINGINFO._serialized_start = 4339 + _TIMESKIPPINGINFO._serialized_end = 4593 + _TIMESKIPPINGFASTFORWARDINFO._serialized_start = 4596 + _TIMESKIPPINGFASTFORWARDINFO._serialized_end = 4780 # @@protoc_insertion_point(module_scope) diff --git a/temporalio/api/common/v1/message_pb2.pyi b/temporalio/api/common/v1/message_pb2.pyi index 37a553810..f7ed8d0fd 100644 --- a/temporalio/api/common/v1/message_pb2.pyi +++ b/temporalio/api/common/v1/message_pb2.pyi @@ -1287,15 +1287,17 @@ class OnConflictOptions(google.protobuf.message.Message): global___OnConflictOptions = OnConflictOptions class TimeSkippingConfig(google.protobuf.message.Message): - """The configuration for time skipping of a workflow execution (a chain of runs including retries, cron, continue-as-new). + """The configuration for time skipping of an execution. When time skipping is enabled, virtual time advances automatically whenever there is no in-flight work. - In-flight work includes activities, child workflows, Nexus operations, signal/cancel external workflow operations, - and possibly other features added in the future. - User timers are not classified as in-flight work and will be skipped over; the virtual clock may also skip to the - time point of the registered fast forward when there is no in-flight work. - When time is skipped, a WorkflowExecutionTimeSkippingTransitionedEvent will be - added to the workflow history to capture the state changes. + Options like fast_forward, disable_propagation, and max_session_skip_count are provided for granular + control of the execution's time skipping behavior. See each field's comment for a detailed explanation. + An example of workflows with time skipping: + For workflows, an execution is a chain of runs including retries, cron, and continue-as-new. + In-flight work includes activities, child workflows, Nexus operations, signal/cancel external workflow operations, etc. + User timers are not classified as in-flight work and will be skipped over; the virtual clock may also skip to the + time point of the registered fast-forward when there is no in-flight work. + Whenever time is skipped, the skip count is incremented by one; max_session_skip_count bounds the number of skips allowed within a single time-skipping session. For child workflows, by default, if the parent execution is skipping time, the child execution will also skip time, but a parent's fast_forward won't affect its child's execution. A flag is provided to disable propagation of the "enabled" flag to child workflows; regardless of that flag, a child workflow inherits the virtual time from the @@ -1305,39 +1307,45 @@ class TimeSkippingConfig(google.protobuf.message.Message): DESCRIPTOR: google.protobuf.descriptor.Descriptor ENABLED_FIELD_NUMBER: builtins.int - FAST_FORWARD_FIELD_NUMBER: builtins.int + FAST_FORWARD_CONFIG_FIELD_NUMBER: builtins.int DISABLE_PROPAGATION_FIELD_NUMBER: builtins.int + MAX_SESSION_SKIP_COUNT_FIELD_NUMBER: builtins.int enabled: builtins.bool """Enables or disables time skipping for this workflow execution.""" @property - def fast_forward(self) -> google.protobuf.duration_pb2.Duration: - """Optionally fast-forward the current workflow execution by this duration ahead of current workflow execution time. - After the fast-forward completes, time skipping is disabled, and this - action is recorded in the WorkflowExecutionTimeSkippingTransitionedEvent. It can be re-enabled by - setting `enabled` to true or setting `fast_forward` again via UpdateWorkflowExecutionOptions. - The current workflow execution is a chain of runs (retries, cron, continue-as-new); - child workflows are separate executions, so this fast_forward won't affect them. - - For a given workflow execution, only one active fast-forward is allowed at a time. - If a new fast-forward is set via UpdateWorkflowExecutionOptions before the previous - one completes, the new one will override the previous one. - If the fast-forward duration exceeds the remaining execution timeout, time will only - be fast-forwarded up to the end of the execution. - """ + def fast_forward_config(self) -> global___FastForwardConfig: + """An optional opt-in to control time-skipping behavior through fast-forward; see its definition for details.""" disable_propagation: builtins.bool """By default, executions started by another execution (e.g. a child workflow of a parent workflow or - a schedule with the timeskipping policy enabled), inherit the "enabled" flag and skip time when possible. + a schedule with the time-skipping policy enabled) inherit the "enabled" flag and skip time when possible. This flag disables that inheritance. """ + max_session_skip_count: builtins.int + """The maximum number of skips allowed every time this field is updated. It protects the execution from + situations like unlimited retries when backoff is skipped. + + Every time the execution skips time, the skip count is incremented by one, and when it reaches + max_session_skip_count, time skipping stops. Whenever this config field is updated, the accumulated + skip count is cleared, marking the start of a new session. + For an execution with a chain of runs (retry, cron, continue-as-new), the count is accumulated + across all runs within the same session. + + If this field is not set, the server applies a large default value (e.g. 100). The default can + be changed through dynamic config, and is overridden by this field when set. + """ def __init__( self, *, enabled: builtins.bool = ..., - fast_forward: google.protobuf.duration_pb2.Duration | None = ..., + fast_forward_config: global___FastForwardConfig | None = ..., disable_propagation: builtins.bool = ..., + max_session_skip_count: builtins.int = ..., ) -> None: ... def HasField( - self, field_name: typing_extensions.Literal["fast_forward", b"fast_forward"] + self, + field_name: typing_extensions.Literal[ + "fast_forward_config", b"fast_forward_config" + ], ) -> builtins.bool: ... def ClearField( self, @@ -1346,37 +1354,79 @@ class TimeSkippingConfig(google.protobuf.message.Message): b"disable_propagation", "enabled", b"enabled", - "fast_forward", - b"fast_forward", + "fast_forward_config", + b"fast_forward_config", + "max_session_skip_count", + b"max_session_skip_count", ], ) -> None: ... global___TimeSkippingConfig = TimeSkippingConfig +class FastForwardConfig(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + ID_FIELD_NUMBER: builtins.int + DURATION_FIELD_NUMBER: builtins.int + id: builtins.str + """A client-supplied ID, required field, set alongside `duration`. It is used to poll for + fast-forward completion via PollWorkflowExecutionTimeSkipping. + The server performs no idempotency check on this ID; the client is responsible for managing it. + """ + @property + def duration(self) -> google.protobuf.duration_pb2.Duration: + """Fast-forward the current execution by this duration ahead of the current execution time; required field. + The duration yields a target time (current execution time + duration), surfaced as `target_time` in + TimeSkippingFastForwardInfo. Once virtual time reaches that target, the fast-forward completes, time + skipping is disabled, and no further time is skipped. Time skipping can be resumed either + by updating the TimeSkippingConfig with a new FastForwardConfig, or by clearing the FastForwardConfig + to skip through to the end of the execution. + + If this duration exceeds the remaining execution timeout, time will not pass beyond the end + of the execution, and the fast-forward won't have a chance to complete. + """ + def __init__( + self, + *, + id: builtins.str = ..., + duration: google.protobuf.duration_pb2.Duration | None = ..., + ) -> None: ... + def HasField( + self, field_name: typing_extensions.Literal["duration", b"duration"] + ) -> builtins.bool: ... + def ClearField( + self, + field_name: typing_extensions.Literal["duration", b"duration", "id", b"id"], + ) -> None: ... + +global___FastForwardConfig = FastForwardConfig + class TimeSkippingStatePropagation(google.protobuf.message.Message): - """The time-skipping state that needs to be propagated from a parent workflow to a child workflow, - or through a chain of runs. + """The time-skipping state that needs to be propagated from one execution to another, or through a chain of runs + within the same execution. """ DESCRIPTOR: google.protobuf.descriptor.Descriptor INITIAL_SKIPPED_DURATION_FIELD_NUMBER: builtins.int FAST_FORWARD_TARGET_TIME_FIELD_NUMBER: builtins.int + INITIAL_SKIP_COUNT_FIELD_NUMBER: builtins.int @property def initial_skipped_duration(self) -> google.protobuf.duration_pb2.Duration: - """The time skipped by the previous execution that started this workflow. - It can happen in child workflows and a chain of runs (CaN, cron, retry). + """The time skipped by the previous run. It is propagated both to executions started by the + current execution and through a chain of runs (CaN, cron, retry). """ @property def fast_forward_target_time(self) -> google.protobuf.timestamp_pb2.Timestamp: - """If there is a fast-forward action set for the previous run in a chain of runs, - the target time should be propagated to the next run as well. - """ + """The fast-forward target time. It only propagates across a chain of runs within the same execution.""" + initial_skip_count: builtins.int + """The initial skip count. It only propagates across a chain of runs within the same execution.""" def __init__( self, *, initial_skipped_duration: google.protobuf.duration_pb2.Duration | None = ..., fast_forward_target_time: google.protobuf.timestamp_pb2.Timestamp | None = ..., + initial_skip_count: builtins.int = ..., ) -> None: ... def HasField( self, @@ -1392,9 +1442,126 @@ class TimeSkippingStatePropagation(google.protobuf.message.Message): field_name: typing_extensions.Literal[ "fast_forward_target_time", b"fast_forward_target_time", + "initial_skip_count", + b"initial_skip_count", "initial_skipped_duration", b"initial_skipped_duration", ], ) -> None: ... global___TimeSkippingStatePropagation = TimeSkippingStatePropagation + +class TimeSkippingInfo(google.protobuf.message.Message): + """Describes the current time-skipping state of a workflow execution.""" + + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + CURRENT_TIME_FIELD_NUMBER: builtins.int + EFFECTIVE_CONFIG_FIELD_NUMBER: builtins.int + FAST_FORWARD_INFO_FIELD_NUMBER: builtins.int + CURRENT_SESSION_SKIP_COUNT_FIELD_NUMBER: builtins.int + @property + def current_time(self) -> google.protobuf.timestamp_pb2.Timestamp: + """Current virtual time of the execution. If the execution hasn't skipped + any time yet, it will be the same as wall clock time. + """ + @property + def effective_config(self) -> global___TimeSkippingConfig: + """The current effective time-skipping config, which can differ from the config the user last set: + internally-defaulted fields are populated, and `enabled` reflects whether the execution is still + skipping time — e.g. it is set to false once `max_session_skip_count` is reached, the fast-forward + completes, or a client call disables time skipping. + """ + @property + def fast_forward_info(self) -> global___TimeSkippingFastForwardInfo: + """The execution's current fast-forward, if any. Unset if time skipping is enabled without a fast-forward.""" + current_session_skip_count: builtins.int + """The number of skips accumulated in the current session, bounded by `max_session_skip_count`. + A new session begins — and this resets to 0 — each time `max_session_skip_count` is updated. + """ + def __init__( + self, + *, + current_time: google.protobuf.timestamp_pb2.Timestamp | None = ..., + effective_config: global___TimeSkippingConfig | None = ..., + fast_forward_info: global___TimeSkippingFastForwardInfo | None = ..., + current_session_skip_count: builtins.int = ..., + ) -> None: ... + def HasField( + self, + field_name: typing_extensions.Literal[ + "current_time", + b"current_time", + "effective_config", + b"effective_config", + "fast_forward_info", + b"fast_forward_info", + ], + ) -> builtins.bool: ... + def ClearField( + self, + field_name: typing_extensions.Literal[ + "current_session_skip_count", + b"current_session_skip_count", + "current_time", + b"current_time", + "effective_config", + b"effective_config", + "fast_forward_info", + b"fast_forward_info", + ], + ) -> None: ... + +global___TimeSkippingInfo = TimeSkippingInfo + +class TimeSkippingFastForwardInfo(google.protobuf.message.Message): + """TimeSkippingFastForwardInfo describes the current time-skipping fast-forward on an execution.""" + + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + FAST_FORWARD_DURATION_FIELD_NUMBER: builtins.int + FAST_FORWARD_ID_FIELD_NUMBER: builtins.int + TARGET_TIME_FIELD_NUMBER: builtins.int + HAS_COMPLETED_FIELD_NUMBER: builtins.int + @property + def fast_forward_duration(self) -> google.protobuf.duration_pb2.Duration: + """The client-supplied `fast_forward` duration.""" + fast_forward_id: builtins.str + """The client-supplied ID set alongside `fast_forward` duration.""" + @property + def target_time(self) -> google.protobuf.timestamp_pb2.Timestamp: + """The target virtual time at which the fast-forward completes.""" + has_completed: builtins.bool + """True once `target_time` has been reached.""" + def __init__( + self, + *, + fast_forward_duration: google.protobuf.duration_pb2.Duration | None = ..., + fast_forward_id: builtins.str = ..., + target_time: google.protobuf.timestamp_pb2.Timestamp | None = ..., + has_completed: builtins.bool = ..., + ) -> None: ... + def HasField( + self, + field_name: typing_extensions.Literal[ + "fast_forward_duration", + b"fast_forward_duration", + "target_time", + b"target_time", + ], + ) -> builtins.bool: ... + def ClearField( + self, + field_name: typing_extensions.Literal[ + "fast_forward_duration", + b"fast_forward_duration", + "fast_forward_id", + b"fast_forward_id", + "has_completed", + b"has_completed", + "target_time", + b"target_time", + ], + ) -> None: ... + +global___TimeSkippingFastForwardInfo = TimeSkippingFastForwardInfo diff --git a/temporalio/api/enums/v1/__init__.py b/temporalio/api/enums/v1/__init__.py index 4a1e72cca..3dc3a179b 100644 --- a/temporalio/api/enums/v1/__init__.py +++ b/temporalio/api/enums/v1/__init__.py @@ -52,6 +52,7 @@ TaskQueueType, TaskReachability, ) +from .time_skipping_pb2 import FastForwardPollingResult from .update_pb2 import UpdateAdmittedEventOrigin, UpdateWorkflowExecutionLifecycleStage from .workflow_pb2 import ( ContinueAsNewInitiator, @@ -88,6 +89,7 @@ "EncodingType", "EventType", "ExecutionType", + "FastForwardPollingResult", "HistoryEventFilterType", "IndexedValueType", "NamespaceState", diff --git a/temporalio/api/enums/v1/failed_cause_pb2.py b/temporalio/api/enums/v1/failed_cause_pb2.py index 7ef32a839..03eb094f9 100644 --- a/temporalio/api/enums/v1/failed_cause_pb2.py +++ b/temporalio/api/enums/v1/failed_cause_pb2.py @@ -16,7 +16,7 @@ DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile( - b'\n(temporal/api/enums/v1/failed_cause.proto\x12\x15temporal.api.enums.v1*\xde\x13\n\x17WorkflowTaskFailedCause\x12*\n&WORKFLOW_TASK_FAILED_CAUSE_UNSPECIFIED\x10\x00\x12\x30\n,WORKFLOW_TASK_FAILED_CAUSE_UNHANDLED_COMMAND\x10\x01\x12?\n;WORKFLOW_TASK_FAILED_CAUSE_BAD_SCHEDULE_ACTIVITY_ATTRIBUTES\x10\x02\x12\x45\nAWORKFLOW_TASK_FAILED_CAUSE_BAD_REQUEST_CANCEL_ACTIVITY_ATTRIBUTES\x10\x03\x12\x39\n5WORKFLOW_TASK_FAILED_CAUSE_BAD_START_TIMER_ATTRIBUTES\x10\x04\x12:\n6WORKFLOW_TASK_FAILED_CAUSE_BAD_CANCEL_TIMER_ATTRIBUTES\x10\x05\x12;\n7WORKFLOW_TASK_FAILED_CAUSE_BAD_RECORD_MARKER_ATTRIBUTES\x10\x06\x12I\nEWORKFLOW_TASK_FAILED_CAUSE_BAD_COMPLETE_WORKFLOW_EXECUTION_ATTRIBUTES\x10\x07\x12\x45\nAWORKFLOW_TASK_FAILED_CAUSE_BAD_FAIL_WORKFLOW_EXECUTION_ATTRIBUTES\x10\x08\x12G\nCWORKFLOW_TASK_FAILED_CAUSE_BAD_CANCEL_WORKFLOW_EXECUTION_ATTRIBUTES\x10\t\x12X\nTWORKFLOW_TASK_FAILED_CAUSE_BAD_REQUEST_CANCEL_EXTERNAL_WORKFLOW_EXECUTION_ATTRIBUTES\x10\n\x12=\n9WORKFLOW_TASK_FAILED_CAUSE_BAD_CONTINUE_AS_NEW_ATTRIBUTES\x10\x0b\x12\x37\n3WORKFLOW_TASK_FAILED_CAUSE_START_TIMER_DUPLICATE_ID\x10\x0c\x12\x36\n2WORKFLOW_TASK_FAILED_CAUSE_RESET_STICKY_TASK_QUEUE\x10\r\x12@\n= (3, 10): + import typing as typing_extensions +else: + import typing_extensions + +DESCRIPTOR: google.protobuf.descriptor.FileDescriptor + +class _FastForwardPollingResult: + ValueType = typing.NewType("ValueType", builtins.int) + V: typing_extensions.TypeAlias = ValueType + +class _FastForwardPollingResultEnumTypeWrapper( + google.protobuf.internal.enum_type_wrapper._EnumTypeWrapper[ + _FastForwardPollingResult.ValueType + ], + builtins.type, +): # noqa: F821 + DESCRIPTOR: google.protobuf.descriptor.EnumDescriptor + FAST_FORWARD_POLLING_RESULT_UNSPECIFIED: _FastForwardPollingResult.ValueType # 0 + """Never returned; guards against an unset result.""" + FAST_FORWARD_POLLING_RESULT_POLL_TIMEOUT: _FastForwardPollingResult.ValueType # 1 + """The poll timed out server-side before the fast-forward completed. The caller may poll again.""" + FAST_FORWARD_POLLING_RESULT_FAST_FORWARD_COMPLETED: ( + _FastForwardPollingResult.ValueType + ) # 2 + """The fast-forward identified by the request's `fast_forward_id` reached its target time and completed.""" + FAST_FORWARD_POLLING_RESULT_FAST_FORWARD_FAILED: ( + _FastForwardPollingResult.ValueType + ) # 3 + """The fast-forward can no longer complete, which usually indicates improper usage of + fast-forward on the client side. Possible reasons: the `fast_forward_id` does not match + the execution's current fast-forward, the execution ended before the fast-forward + completed, the fast-forward config was updated while the poll was in flight, etc. + See `failed_reason` in the response for the specific cause. + """ + +class FastForwardPollingResult( + _FastForwardPollingResult, metaclass=_FastForwardPollingResultEnumTypeWrapper +): + """FastForwardPollingResult is the result of polling and waiting for a fast-forward to complete + on a time-skipping execution. + FAST_FORWARD_POLLING_RESULT_POLL_TIMEOUT and FAST_FORWARD_POLLING_RESULT_FAST_FORWARD_COMPLETED + are the normal poll outcomes; FAST_FORWARD_POLLING_RESULT_FAST_FORWARD_FAILED means the + fast-forward can no longer complete. + """ + +FAST_FORWARD_POLLING_RESULT_UNSPECIFIED: FastForwardPollingResult.ValueType # 0 +"""Never returned; guards against an unset result.""" +FAST_FORWARD_POLLING_RESULT_POLL_TIMEOUT: FastForwardPollingResult.ValueType # 1 +"""The poll timed out server-side before the fast-forward completed. The caller may poll again.""" +FAST_FORWARD_POLLING_RESULT_FAST_FORWARD_COMPLETED: ( + FastForwardPollingResult.ValueType +) # 2 +"""The fast-forward identified by the request's `fast_forward_id` reached its target time and completed.""" +FAST_FORWARD_POLLING_RESULT_FAST_FORWARD_FAILED: FastForwardPollingResult.ValueType # 3 +"""The fast-forward can no longer complete, which usually indicates improper usage of +fast-forward on the client side. Possible reasons: the `fast_forward_id` does not match +the execution's current fast-forward, the execution ended before the fast-forward +completed, the fast-forward config was updated while the poll was in flight, etc. +See `failed_reason` in the response for the specific cause. +""" +global___FastForwardPollingResult = FastForwardPollingResult diff --git a/temporalio/api/history/v1/message_pb2.pyi b/temporalio/api/history/v1/message_pb2.pyi index 9735097e2..783e9d3b6 100644 --- a/temporalio/api/history/v1/message_pb2.pyi +++ b/temporalio/api/history/v1/message_pb2.pyi @@ -3850,8 +3850,8 @@ global___WorkflowExecutionUnpausedEventAttributes = ( class WorkflowExecutionTimeSkippingTransitionedEventAttributes( google.protobuf.message.Message ): - """Attributes for an event indicating that time skipping state changed for a workflow execution, - either time was advanced or time skipping was disabled automatically due to the fast_forward completing. + """Attributes for an event indicating that time skipping state changed for a workflow execution: + either time was advanced, or time skipping was stopped automatically due to the fast_forward completing. The worker_may_ignore field in HistoryEvent should always be set true for this event. """ @@ -3864,7 +3864,7 @@ class WorkflowExecutionTimeSkippingTransitionedEventAttributes( def target_time(self) -> google.protobuf.timestamp_pb2.Timestamp: """The virtual time point that time skipping advanced to.""" disabled_after_fast_forward: builtins.bool - """When true, time skipping has been disabled automatically due to a call to fast_forward completing. + """When true, time skipping has been stopped automatically due to a call to fast_forward completing. (-- api-linter: core::0140::prepositions=disabled aip.dev/not-precedent: "after" is used to indicate temporal ordering. --) """ diff --git a/temporalio/api/namespace/v1/message_pb2.py b/temporalio/api/namespace/v1/message_pb2.py index 150a49384..43a3773f2 100644 --- a/temporalio/api/namespace/v1/message_pb2.py +++ b/temporalio/api/namespace/v1/message_pb2.py @@ -22,7 +22,7 @@ ) DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile( - b'\n\'temporal/api/namespace/v1/message.proto\x12\x19temporal.api.namespace.v1\x1a\x1egoogle/protobuf/duration.proto\x1a\x1fgoogle/protobuf/timestamp.proto\x1a%temporal/api/enums/v1/namespace.proto"\xc3\x08\n\rNamespaceInfo\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x34\n\x05state\x18\x02 \x01(\x0e\x32%.temporal.api.enums.v1.NamespaceState\x12\x13\n\x0b\x64\x65scription\x18\x03 \x01(\t\x12\x13\n\x0bowner_email\x18\x04 \x01(\t\x12@\n\x04\x64\x61ta\x18\x05 \x03(\x0b\x32\x32.temporal.api.namespace.v1.NamespaceInfo.DataEntry\x12\n\n\x02id\x18\x06 \x01(\t\x12K\n\x0c\x63\x61pabilities\x18\x07 \x01(\x0b\x32\x35.temporal.api.namespace.v1.NamespaceInfo.Capabilities\x12?\n\x06limits\x18\x08 \x01(\x0b\x32/.temporal.api.namespace.v1.NamespaceInfo.Limits\x12\x1a\n\x12supports_schedules\x18\x64 \x01(\x08\x1a+\n\tDataEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x1a\xd6\x04\n\x0c\x43\x61pabilities\x12\x1c\n\x14\x65\x61ger_workflow_start\x18\x01 \x01(\x08\x12\x13\n\x0bsync_update\x18\x02 \x01(\x08\x12\x14\n\x0c\x61sync_update\x18\x03 \x01(\x08\x12\x19\n\x11worker_heartbeats\x18\x04 \x01(\x08\x12*\n"reported_problems_search_attribute\x18\x05 \x01(\x08\x12\x16\n\x0eworkflow_pause\x18\x06 \x01(\x08\x12\x1d\n\x15standalone_activities\x18\x07 \x01(\x08\x12(\n worker_poll_complete_on_shutdown\x18\x08 \x01(\x08\x12\x1a\n\x12poller_autoscaling\x18\t \x01(\x08\x12\x17\n\x0fworker_commands\x18\n \x01(\x08\x12"\n\x1astandalone_nexus_operation\x18\x0b \x01(\x08\x12!\n\x19workflow_update_callbacks\x18\x0c \x01(\x08\x12&\n\x1epoller_autoscaling_auto_enroll\x18\r \x01(\x08\x12+\n#workflow_task_completion_pagination\x18\x0e \x01(\x08\x12\'\n\x1fstandalone_activity_start_delay\x18\x0f \x01(\x08\x12,\n$standalone_activity_batch_operations\x18\x10 \x01(\x08\x12-\n%standalone_activity_operator_commands\x18\x11 \x01(\x08\x1a\x46\n\x06Limits\x12\x1d\n\x15\x62lob_size_limit_error\x18\x01 \x01(\x03\x12\x1d\n\x15memo_size_limit_error\x18\x02 \x01(\x03"\x9e\x04\n\x0fNamespaceConfig\x12\x43\n workflow_execution_retention_ttl\x18\x01 \x01(\x0b\x32\x19.google.protobuf.Duration\x12<\n\x0c\x62\x61\x64_binaries\x18\x02 \x01(\x0b\x32&.temporal.api.namespace.v1.BadBinaries\x12\x44\n\x16history_archival_state\x18\x03 \x01(\x0e\x32$.temporal.api.enums.v1.ArchivalState\x12\x1c\n\x14history_archival_uri\x18\x04 \x01(\t\x12G\n\x19visibility_archival_state\x18\x05 \x01(\x0e\x32$.temporal.api.enums.v1.ArchivalState\x12\x1f\n\x17visibility_archival_uri\x18\x06 \x01(\t\x12u\n\x1f\x63ustom_search_attribute_aliases\x18\x07 \x03(\x0b\x32L.temporal.api.namespace.v1.NamespaceConfig.CustomSearchAttributeAliasesEntry\x1a\x43\n!CustomSearchAttributeAliasesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01"\xb0\x01\n\x0b\x42\x61\x64\x42inaries\x12\x46\n\x08\x62inaries\x18\x01 \x03(\x0b\x32\x34.temporal.api.namespace.v1.BadBinaries.BinariesEntry\x1aY\n\rBinariesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x37\n\x05value\x18\x02 \x01(\x0b\x32(.temporal.api.namespace.v1.BadBinaryInfo:\x02\x38\x01"b\n\rBadBinaryInfo\x12\x0e\n\x06reason\x18\x01 \x01(\t\x12\x10\n\x08operator\x18\x02 \x01(\t\x12/\n\x0b\x63reate_time\x18\x03 \x01(\x0b\x32\x1a.google.protobuf.Timestamp"\xea\x01\n\x13UpdateNamespaceInfo\x12\x13\n\x0b\x64\x65scription\x18\x01 \x01(\t\x12\x13\n\x0bowner_email\x18\x02 \x01(\t\x12\x46\n\x04\x64\x61ta\x18\x03 \x03(\x0b\x32\x38.temporal.api.namespace.v1.UpdateNamespaceInfo.DataEntry\x12\x34\n\x05state\x18\x04 \x01(\x0e\x32%.temporal.api.enums.v1.NamespaceState\x1a+\n\tDataEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01"*\n\x0fNamespaceFilter\x12\x17\n\x0finclude_deleted\x18\x01 \x01(\x08\x42\x98\x01\n\x1cio.temporal.api.namespace.v1B\x0cMessageProtoP\x01Z)go.temporal.io/api/namespace/v1;namespace\xaa\x02\x1bTemporalio.Api.Namespace.V1\xea\x02\x1eTemporalio::Api::Namespace::V1b\x06proto3' + b'\n\'temporal/api/namespace/v1/message.proto\x12\x19temporal.api.namespace.v1\x1a\x1egoogle/protobuf/duration.proto\x1a\x1fgoogle/protobuf/timestamp.proto\x1a%temporal/api/enums/v1/namespace.proto"\xf6\x08\n\rNamespaceInfo\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x34\n\x05state\x18\x02 \x01(\x0e\x32%.temporal.api.enums.v1.NamespaceState\x12\x13\n\x0b\x64\x65scription\x18\x03 \x01(\t\x12\x13\n\x0bowner_email\x18\x04 \x01(\t\x12@\n\x04\x64\x61ta\x18\x05 \x03(\x0b\x32\x32.temporal.api.namespace.v1.NamespaceInfo.DataEntry\x12\n\n\x02id\x18\x06 \x01(\t\x12K\n\x0c\x63\x61pabilities\x18\x07 \x01(\x0b\x32\x35.temporal.api.namespace.v1.NamespaceInfo.Capabilities\x12?\n\x06limits\x18\x08 \x01(\x0b\x32/.temporal.api.namespace.v1.NamespaceInfo.Limits\x12\x1a\n\x12supports_schedules\x18\x64 \x01(\x08\x1a+\n\tDataEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x1a\xd6\x04\n\x0c\x43\x61pabilities\x12\x1c\n\x14\x65\x61ger_workflow_start\x18\x01 \x01(\x08\x12\x13\n\x0bsync_update\x18\x02 \x01(\x08\x12\x14\n\x0c\x61sync_update\x18\x03 \x01(\x08\x12\x19\n\x11worker_heartbeats\x18\x04 \x01(\x08\x12*\n"reported_problems_search_attribute\x18\x05 \x01(\x08\x12\x16\n\x0eworkflow_pause\x18\x06 \x01(\x08\x12\x1d\n\x15standalone_activities\x18\x07 \x01(\x08\x12(\n worker_poll_complete_on_shutdown\x18\x08 \x01(\x08\x12\x1a\n\x12poller_autoscaling\x18\t \x01(\x08\x12\x17\n\x0fworker_commands\x18\n \x01(\x08\x12"\n\x1astandalone_nexus_operation\x18\x0b \x01(\x08\x12!\n\x19workflow_update_callbacks\x18\x0c \x01(\x08\x12&\n\x1epoller_autoscaling_auto_enroll\x18\r \x01(\x08\x12+\n#workflow_task_completion_pagination\x18\x0e \x01(\x08\x12\'\n\x1fstandalone_activity_start_delay\x18\x0f \x01(\x08\x12,\n$standalone_activity_batch_operations\x18\x10 \x01(\x08\x12-\n%standalone_activity_operator_commands\x18\x11 \x01(\x08\x1ay\n\x06Limits\x12\x1d\n\x15\x62lob_size_limit_error\x18\x01 \x01(\x03\x12\x1d\n\x15memo_size_limit_error\x18\x02 \x01(\x03\x12\x31\n)workflow_task_completion_size_limit_error\x18\x03 \x01(\x03"\x9e\x04\n\x0fNamespaceConfig\x12\x43\n workflow_execution_retention_ttl\x18\x01 \x01(\x0b\x32\x19.google.protobuf.Duration\x12<\n\x0c\x62\x61\x64_binaries\x18\x02 \x01(\x0b\x32&.temporal.api.namespace.v1.BadBinaries\x12\x44\n\x16history_archival_state\x18\x03 \x01(\x0e\x32$.temporal.api.enums.v1.ArchivalState\x12\x1c\n\x14history_archival_uri\x18\x04 \x01(\t\x12G\n\x19visibility_archival_state\x18\x05 \x01(\x0e\x32$.temporal.api.enums.v1.ArchivalState\x12\x1f\n\x17visibility_archival_uri\x18\x06 \x01(\t\x12u\n\x1f\x63ustom_search_attribute_aliases\x18\x07 \x03(\x0b\x32L.temporal.api.namespace.v1.NamespaceConfig.CustomSearchAttributeAliasesEntry\x1a\x43\n!CustomSearchAttributeAliasesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01"\xb0\x01\n\x0b\x42\x61\x64\x42inaries\x12\x46\n\x08\x62inaries\x18\x01 \x03(\x0b\x32\x34.temporal.api.namespace.v1.BadBinaries.BinariesEntry\x1aY\n\rBinariesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x37\n\x05value\x18\x02 \x01(\x0b\x32(.temporal.api.namespace.v1.BadBinaryInfo:\x02\x38\x01"b\n\rBadBinaryInfo\x12\x0e\n\x06reason\x18\x01 \x01(\t\x12\x10\n\x08operator\x18\x02 \x01(\t\x12/\n\x0b\x63reate_time\x18\x03 \x01(\x0b\x32\x1a.google.protobuf.Timestamp"\xea\x01\n\x13UpdateNamespaceInfo\x12\x13\n\x0b\x64\x65scription\x18\x01 \x01(\t\x12\x13\n\x0bowner_email\x18\x02 \x01(\t\x12\x46\n\x04\x64\x61ta\x18\x03 \x03(\x0b\x32\x38.temporal.api.namespace.v1.UpdateNamespaceInfo.DataEntry\x12\x34\n\x05state\x18\x04 \x01(\x0e\x32%.temporal.api.enums.v1.NamespaceState\x1a+\n\tDataEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01"*\n\x0fNamespaceFilter\x12\x17\n\x0finclude_deleted\x18\x01 \x01(\x08\x42\x98\x01\n\x1cio.temporal.api.namespace.v1B\x0cMessageProtoP\x01Z)go.temporal.io/api/namespace/v1;namespace\xaa\x02\x1bTemporalio.Api.Namespace.V1\xea\x02\x1eTemporalio::Api::Namespace::V1b\x06proto3' ) @@ -178,27 +178,27 @@ _UPDATENAMESPACEINFO_DATAENTRY._options = None _UPDATENAMESPACEINFO_DATAENTRY._serialized_options = b"8\001" _NAMESPACEINFO._serialized_start = 175 - _NAMESPACEINFO._serialized_end = 1266 + _NAMESPACEINFO._serialized_end = 1317 _NAMESPACEINFO_DATAENTRY._serialized_start = 550 _NAMESPACEINFO_DATAENTRY._serialized_end = 593 _NAMESPACEINFO_CAPABILITIES._serialized_start = 596 _NAMESPACEINFO_CAPABILITIES._serialized_end = 1194 _NAMESPACEINFO_LIMITS._serialized_start = 1196 - _NAMESPACEINFO_LIMITS._serialized_end = 1266 - _NAMESPACECONFIG._serialized_start = 1269 - _NAMESPACECONFIG._serialized_end = 1811 - _NAMESPACECONFIG_CUSTOMSEARCHATTRIBUTEALIASESENTRY._serialized_start = 1744 - _NAMESPACECONFIG_CUSTOMSEARCHATTRIBUTEALIASESENTRY._serialized_end = 1811 - _BADBINARIES._serialized_start = 1814 - _BADBINARIES._serialized_end = 1990 - _BADBINARIES_BINARIESENTRY._serialized_start = 1901 - _BADBINARIES_BINARIESENTRY._serialized_end = 1990 - _BADBINARYINFO._serialized_start = 1992 - _BADBINARYINFO._serialized_end = 2090 - _UPDATENAMESPACEINFO._serialized_start = 2093 - _UPDATENAMESPACEINFO._serialized_end = 2327 + _NAMESPACEINFO_LIMITS._serialized_end = 1317 + _NAMESPACECONFIG._serialized_start = 1320 + _NAMESPACECONFIG._serialized_end = 1862 + _NAMESPACECONFIG_CUSTOMSEARCHATTRIBUTEALIASESENTRY._serialized_start = 1795 + _NAMESPACECONFIG_CUSTOMSEARCHATTRIBUTEALIASESENTRY._serialized_end = 1862 + _BADBINARIES._serialized_start = 1865 + _BADBINARIES._serialized_end = 2041 + _BADBINARIES_BINARIESENTRY._serialized_start = 1952 + _BADBINARIES_BINARIESENTRY._serialized_end = 2041 + _BADBINARYINFO._serialized_start = 2043 + _BADBINARYINFO._serialized_end = 2141 + _UPDATENAMESPACEINFO._serialized_start = 2144 + _UPDATENAMESPACEINFO._serialized_end = 2378 _UPDATENAMESPACEINFO_DATAENTRY._serialized_start = 550 _UPDATENAMESPACEINFO_DATAENTRY._serialized_end = 593 - _NAMESPACEFILTER._serialized_start = 2329 - _NAMESPACEFILTER._serialized_end = 2371 + _NAMESPACEFILTER._serialized_start = 2380 + _NAMESPACEFILTER._serialized_end = 2422 # @@protoc_insertion_point(module_scope) diff --git a/temporalio/api/namespace/v1/message_pb2.pyi b/temporalio/api/namespace/v1/message_pb2.pyi index 51f386e39..06b1546b3 100644 --- a/temporalio/api/namespace/v1/message_pb2.pyi +++ b/temporalio/api/namespace/v1/message_pb2.pyi @@ -170,6 +170,7 @@ class NamespaceInfo(google.protobuf.message.Message): BLOB_SIZE_LIMIT_ERROR_FIELD_NUMBER: builtins.int MEMO_SIZE_LIMIT_ERROR_FIELD_NUMBER: builtins.int + WORKFLOW_TASK_COMPLETION_SIZE_LIMIT_ERROR_FIELD_NUMBER: builtins.int blob_size_limit_error: builtins.int """Maximum size in bytes for payload fields in workflow history events (e.g., workflow/activity inputs and results, failure details, signal payloads). @@ -177,11 +178,17 @@ class NamespaceInfo(google.protobuf.message.Message): """ memo_size_limit_error: builtins.int """Maximum total memo size in bytes per workflow execution.""" + workflow_task_completion_size_limit_error: builtins.int + """Maximum total size in bytes of a single RespondWorkflowTaskCompleted request. + Requests exceeding this fail the workflow task with + WORKFLOW_TASK_FAILED_CAUSE_REQUEST_TOO_LARGE. 0 means no explicit limit. + """ def __init__( self, *, blob_size_limit_error: builtins.int = ..., memo_size_limit_error: builtins.int = ..., + workflow_task_completion_size_limit_error: builtins.int = ..., ) -> None: ... def ClearField( self, @@ -190,6 +197,8 @@ class NamespaceInfo(google.protobuf.message.Message): b"blob_size_limit_error", "memo_size_limit_error", b"memo_size_limit_error", + "workflow_task_completion_size_limit_error", + b"workflow_task_completion_size_limit_error", ], ) -> None: ... diff --git a/temporalio/api/worker/v1/__init__.py b/temporalio/api/worker/v1/__init__.py index 5c1afdf4f..8b6e343e5 100644 --- a/temporalio/api/worker/v1/__init__.py +++ b/temporalio/api/worker/v1/__init__.py @@ -1,6 +1,7 @@ from .message_pb2 import ( CancelActivityCommand, CancelActivityResult, + EnvironmentInfo, PluginInfo, StorageDriverInfo, WorkerCommand, @@ -16,6 +17,7 @@ __all__ = [ "CancelActivityCommand", "CancelActivityResult", + "EnvironmentInfo", "PluginInfo", "StorageDriverInfo", "WorkerCommand", diff --git a/temporalio/api/worker/v1/message_pb2.py b/temporalio/api/worker/v1/message_pb2.py index 4de9c5b24..78b58817a 100644 --- a/temporalio/api/worker/v1/message_pb2.py +++ b/temporalio/api/worker/v1/message_pb2.py @@ -25,7 +25,7 @@ ) DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile( - b'\n$temporal/api/worker/v1/message.proto\x12\x16temporal.api.worker.v1\x1a\x1egoogle/protobuf/duration.proto\x1a\x1fgoogle/protobuf/timestamp.proto\x1a(temporal/api/deployment/v1/message.proto\x1a"temporal/api/enums/v1/common.proto"\x82\x01\n\x10WorkerPollerInfo\x12\x17\n\x0f\x63urrent_pollers\x18\x01 \x01(\x05\x12=\n\x19last_successful_poll_time\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x16\n\x0eis_autoscaling\x18\x03 \x01(\x08"\xf1\x01\n\x0fWorkerSlotsInfo\x12\x1f\n\x17\x63urrent_available_slots\x18\x01 \x01(\x05\x12\x1a\n\x12\x63urrent_used_slots\x18\x02 \x01(\x05\x12\x1a\n\x12slot_supplier_kind\x18\x03 \x01(\t\x12\x1d\n\x15total_processed_tasks\x18\x04 \x01(\x05\x12\x1a\n\x12total_failed_tasks\x18\x05 \x01(\x05\x12%\n\x1dlast_interval_processed_tasks\x18\x06 \x01(\x05\x12#\n\x1blast_interval_failure_tasks\x18\x07 \x01(\x05"\x94\x01\n\x0eWorkerHostInfo\x12\x11\n\thost_name\x18\x01 \x01(\t\x12\x1b\n\x13worker_grouping_key\x18\x05 \x01(\t\x12\x12\n\nprocess_id\x18\x02 \x01(\t\x12\x1e\n\x16\x63urrent_host_cpu_usage\x18\x03 \x01(\x02\x12\x1e\n\x16\x63urrent_host_mem_usage\x18\x04 \x01(\x02"\x8b\n\n\x0fWorkerHeartbeat\x12\x1b\n\x13worker_instance_key\x18\x01 \x01(\t\x12\x17\n\x0fworker_identity\x18\x02 \x01(\t\x12\x39\n\thost_info\x18\x03 \x01(\x0b\x32&.temporal.api.worker.v1.WorkerHostInfo\x12\x12\n\ntask_queue\x18\x04 \x01(\t\x12O\n\x12\x64\x65ployment_version\x18\x05 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersion\x12\x10\n\x08sdk_name\x18\x06 \x01(\t\x12\x13\n\x0bsdk_version\x18\x07 \x01(\t\x12\x33\n\x06status\x18\x08 \x01(\x0e\x32#.temporal.api.enums.v1.WorkerStatus\x12.\n\nstart_time\x18\t \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x32\n\x0eheartbeat_time\x18\n \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12?\n\x1c\x65lapsed_since_last_heartbeat\x18\x0b \x01(\x0b\x32\x19.google.protobuf.Duration\x12I\n\x18workflow_task_slots_info\x18\x0c \x01(\x0b\x32\'.temporal.api.worker.v1.WorkerSlotsInfo\x12I\n\x18\x61\x63tivity_task_slots_info\x18\r \x01(\x0b\x32\'.temporal.api.worker.v1.WorkerSlotsInfo\x12\x46\n\x15nexus_task_slots_info\x18\x0e \x01(\x0b\x32\'.temporal.api.worker.v1.WorkerSlotsInfo\x12J\n\x19local_activity_slots_info\x18\x0f \x01(\x0b\x32\'.temporal.api.worker.v1.WorkerSlotsInfo\x12\x46\n\x14workflow_poller_info\x18\x10 \x01(\x0b\x32(.temporal.api.worker.v1.WorkerPollerInfo\x12M\n\x1bworkflow_sticky_poller_info\x18\x11 \x01(\x0b\x32(.temporal.api.worker.v1.WorkerPollerInfo\x12\x46\n\x14\x61\x63tivity_poller_info\x18\x12 \x01(\x0b\x32(.temporal.api.worker.v1.WorkerPollerInfo\x12\x43\n\x11nexus_poller_info\x18\x13 \x01(\x0b\x32(.temporal.api.worker.v1.WorkerPollerInfo\x12\x1e\n\x16total_sticky_cache_hit\x18\x14 \x01(\x05\x12\x1f\n\x17total_sticky_cache_miss\x18\x15 \x01(\x05\x12!\n\x19\x63urrent_sticky_cache_size\x18\x16 \x01(\x05\x12\x33\n\x07plugins\x18\x17 \x03(\x0b\x32".temporal.api.worker.v1.PluginInfo\x12:\n\x07\x64rivers\x18\x18 \x03(\x0b\x32).temporal.api.worker.v1.StorageDriverInfo"O\n\nWorkerInfo\x12\x41\n\x10worker_heartbeat\x18\x01 \x01(\x0b\x32\'.temporal.api.worker.v1.WorkerHeartbeat"\xec\x03\n\x0eWorkerListInfo\x12\x1b\n\x13worker_instance_key\x18\x01 \x01(\t\x12\x17\n\x0fworker_identity\x18\x02 \x01(\t\x12\x12\n\ntask_queue\x18\x03 \x01(\t\x12O\n\x12\x64\x65ployment_version\x18\x04 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersion\x12\x10\n\x08sdk_name\x18\x05 \x01(\t\x12\x13\n\x0bsdk_version\x18\x06 \x01(\t\x12\x33\n\x06status\x18\x07 \x01(\x0e\x32#.temporal.api.enums.v1.WorkerStatus\x12.\n\nstart_time\x18\x08 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x11\n\thost_name\x18\t \x01(\t\x12\x1b\n\x13worker_grouping_key\x18\n \x01(\t\x12\x12\n\nprocess_id\x18\x0b \x01(\t\x12\x33\n\x07plugins\x18\x0c \x03(\x0b\x32".temporal.api.worker.v1.PluginInfo\x12:\n\x07\x64rivers\x18\r \x03(\x0b\x32).temporal.api.worker.v1.StorageDriverInfo"+\n\nPluginInfo\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x0f\n\x07version\x18\x02 \x01(\t"!\n\x11StorageDriverInfo\x12\x0c\n\x04type\x18\x01 \x01(\t"a\n\rWorkerCommand\x12H\n\x0f\x63\x61ncel_activity\x18\x01 \x01(\x0b\x32-.temporal.api.worker.v1.CancelActivityCommandH\x00\x42\x06\n\x04type"+\n\x15\x43\x61ncelActivityCommand\x12\x12\n\ntask_token\x18\x01 \x01(\x0c"f\n\x13WorkerCommandResult\x12G\n\x0f\x63\x61ncel_activity\x18\x01 \x01(\x0b\x32,.temporal.api.worker.v1.CancelActivityResultH\x00\x42\x06\n\x04type"\x16\n\x14\x43\x61ncelActivityResultB\x89\x01\n\x19io.temporal.api.worker.v1B\x0cMessageProtoP\x01Z#go.temporal.io/api/worker/v1;worker\xaa\x02\x18Temporalio.Api.Worker.V1\xea\x02\x1bTemporalio::Api::Worker::V1b\x06proto3' + b'\n$temporal/api/worker/v1/message.proto\x12\x16temporal.api.worker.v1\x1a\x1egoogle/protobuf/duration.proto\x1a\x1fgoogle/protobuf/timestamp.proto\x1a(temporal/api/deployment/v1/message.proto\x1a"temporal/api/enums/v1/common.proto"\x82\x01\n\x10WorkerPollerInfo\x12\x17\n\x0f\x63urrent_pollers\x18\x01 \x01(\x05\x12=\n\x19last_successful_poll_time\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x16\n\x0eis_autoscaling\x18\x03 \x01(\x08"\xf1\x01\n\x0fWorkerSlotsInfo\x12\x1f\n\x17\x63urrent_available_slots\x18\x01 \x01(\x05\x12\x1a\n\x12\x63urrent_used_slots\x18\x02 \x01(\x05\x12\x1a\n\x12slot_supplier_kind\x18\x03 \x01(\t\x12\x1d\n\x15total_processed_tasks\x18\x04 \x01(\x05\x12\x1a\n\x12total_failed_tasks\x18\x05 \x01(\x05\x12%\n\x1dlast_interval_processed_tasks\x18\x06 \x01(\x05\x12#\n\x1blast_interval_failure_tasks\x18\x07 \x01(\x05"\x94\x01\n\x0eWorkerHostInfo\x12\x11\n\thost_name\x18\x01 \x01(\t\x12\x1b\n\x13worker_grouping_key\x18\x05 \x01(\t\x12\x12\n\nprocess_id\x18\x02 \x01(\t\x12\x1e\n\x16\x63urrent_host_cpu_usage\x18\x03 \x01(\x02\x12\x1e\n\x16\x63urrent_host_mem_usage\x18\x04 \x01(\x02"\xc9\n\n\x0fWorkerHeartbeat\x12\x1b\n\x13worker_instance_key\x18\x01 \x01(\t\x12\x17\n\x0fworker_identity\x18\x02 \x01(\t\x12\x39\n\thost_info\x18\x03 \x01(\x0b\x32&.temporal.api.worker.v1.WorkerHostInfo\x12\x12\n\ntask_queue\x18\x04 \x01(\t\x12O\n\x12\x64\x65ployment_version\x18\x05 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersion\x12\x10\n\x08sdk_name\x18\x06 \x01(\t\x12\x13\n\x0bsdk_version\x18\x07 \x01(\t\x12\x33\n\x06status\x18\x08 \x01(\x0e\x32#.temporal.api.enums.v1.WorkerStatus\x12.\n\nstart_time\x18\t \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x32\n\x0eheartbeat_time\x18\n \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12?\n\x1c\x65lapsed_since_last_heartbeat\x18\x0b \x01(\x0b\x32\x19.google.protobuf.Duration\x12I\n\x18workflow_task_slots_info\x18\x0c \x01(\x0b\x32\'.temporal.api.worker.v1.WorkerSlotsInfo\x12I\n\x18\x61\x63tivity_task_slots_info\x18\r \x01(\x0b\x32\'.temporal.api.worker.v1.WorkerSlotsInfo\x12\x46\n\x15nexus_task_slots_info\x18\x0e \x01(\x0b\x32\'.temporal.api.worker.v1.WorkerSlotsInfo\x12J\n\x19local_activity_slots_info\x18\x0f \x01(\x0b\x32\'.temporal.api.worker.v1.WorkerSlotsInfo\x12\x46\n\x14workflow_poller_info\x18\x10 \x01(\x0b\x32(.temporal.api.worker.v1.WorkerPollerInfo\x12M\n\x1bworkflow_sticky_poller_info\x18\x11 \x01(\x0b\x32(.temporal.api.worker.v1.WorkerPollerInfo\x12\x46\n\x14\x61\x63tivity_poller_info\x18\x12 \x01(\x0b\x32(.temporal.api.worker.v1.WorkerPollerInfo\x12\x43\n\x11nexus_poller_info\x18\x13 \x01(\x0b\x32(.temporal.api.worker.v1.WorkerPollerInfo\x12\x1e\n\x16total_sticky_cache_hit\x18\x14 \x01(\x05\x12\x1f\n\x17total_sticky_cache_miss\x18\x15 \x01(\x05\x12!\n\x19\x63urrent_sticky_cache_size\x18\x16 \x01(\x05\x12\x33\n\x07plugins\x18\x17 \x03(\x0b\x32".temporal.api.worker.v1.PluginInfo\x12:\n\x07\x64rivers\x18\x18 \x03(\x0b\x32).temporal.api.worker.v1.StorageDriverInfo\x12<\n\x0b\x65nvironment\x18\x19 \x01(\x0b\x32\'.temporal.api.worker.v1.EnvironmentInfo"O\n\nWorkerInfo\x12\x41\n\x10worker_heartbeat\x18\x01 \x01(\x0b\x32\'.temporal.api.worker.v1.WorkerHeartbeat"\xec\x03\n\x0eWorkerListInfo\x12\x1b\n\x13worker_instance_key\x18\x01 \x01(\t\x12\x17\n\x0fworker_identity\x18\x02 \x01(\t\x12\x12\n\ntask_queue\x18\x03 \x01(\t\x12O\n\x12\x64\x65ployment_version\x18\x04 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersion\x12\x10\n\x08sdk_name\x18\x05 \x01(\t\x12\x13\n\x0bsdk_version\x18\x06 \x01(\t\x12\x33\n\x06status\x18\x07 \x01(\x0e\x32#.temporal.api.enums.v1.WorkerStatus\x12.\n\nstart_time\x18\x08 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x11\n\thost_name\x18\t \x01(\t\x12\x1b\n\x13worker_grouping_key\x18\n \x01(\t\x12\x12\n\nprocess_id\x18\x0b \x01(\t\x12\x33\n\x07plugins\x18\x0c \x03(\x0b\x32".temporal.api.worker.v1.PluginInfo\x12:\n\x07\x64rivers\x18\r \x03(\x0b\x32).temporal.api.worker.v1.StorageDriverInfo"+\n\nPluginInfo\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x0f\n\x07version\x18\x02 \x01(\t"!\n\x11StorageDriverInfo\x12\x0c\n\x04type\x18\x01 \x01(\t"\xa7\x11\n\x0f\x45nvironmentInfo\x12\x41\n\x08runtimes\x18\x01 \x03(\x0b\x32/.temporal.api.worker.v1.EnvironmentInfo.Runtime\x12X\n\x14hosting_environments\x18\x02 \x03(\x0b\x32:.temporal.api.worker.v1.EnvironmentInfo.HostingEnvironment\x12\x42\n\x08platform\x18\x03 \x01(\x0b\x32\x30.temporal.api.worker.v1.EnvironmentInfo.Platform\x1a\x94\x03\n\x07Runtime\x12I\n\x04type\x18\x01 \x01(\x0e\x32;.temporal.api.worker.v1.EnvironmentInfo.Runtime.RuntimeType\x12\x0f\n\x07version\x18\x02 \x01(\t"\xac\x02\n\x0bRuntimeType\x12\x1c\n\x18RUNTIME_TYPE_UNSPECIFIED\x10\x00\x12\x14\n\x10RUNTIME_TYPE_JVM\x10\x01\x12\x18\n\x14RUNTIME_TYPE_CPYTHON\x10\x02\x12\x15\n\x11RUNTIME_TYPE_NODE\x10\x03\x12\x14\n\x10RUNTIME_TYPE_BUN\x10\x04\x12\x16\n\x12RUNTIME_TYPE_CRUBY\x10\x05\x12\x13\n\x0fRUNTIME_TYPE_GO\x10\x06\x12!\n\x1dRUNTIME_TYPE_DOTNET_FRAMEWORK\x10\x07\x12\x1c\n\x18RUNTIME_TYPE_DOTNET_CORE\x10\x08\x12\x17\n\x13RUNTIME_TYPE_NATIVE\x10\t\x12\x1b\n\x17RUNTIME_TYPE_ROADRUNNER\x10\n\x1a\xd1\x04\n\x12HostingEnvironment\x12_\n\x04type\x18\x01 \x01(\x0e\x32Q.temporal.api.worker.v1.EnvironmentInfo.HostingEnvironment.HostingEnvironmentType\x12\x0f\n\x07version\x18\x02 \x01(\t"\xc8\x03\n\x16HostingEnvironmentType\x12(\n$HOSTING_ENVIRONMENT_TYPE_UNSPECIFIED\x10\x00\x12#\n\x1fHOSTING_ENVIRONMENT_TYPE_DOCKER\x10\x01\x12 \n\x1cHOSTING_ENVIRONMENT_TYPE_K8S\x10\x02\x12\'\n#HOSTING_ENVIRONMENT_TYPE_AWS_LAMBDA\x10\x03\x12$\n HOSTING_ENVIRONMENT_TYPE_AWS_ECS\x10\x04\x12-\n)HOSTING_ENVIRONMENT_TYPE_GOOGLE_CLOUD_RUN\x10\x06\x12.\n*HOSTING_ENVIRONMENT_TYPE_GOOGLE_APP_ENGINE\x10\x07\x12.\n*HOSTING_ENVIRONMENT_TYPE_AZURE_APP_SERVICE\x10\x08\x12,\n(HOSTING_ENVIRONMENT_TYPE_AZURE_FUNCTIONS\x10\t\x12\x31\n-HOSTING_ENVIRONMENT_TYPE_AZURE_CONTAINER_APPS\x10\n\x1a\xf1\x01\n\x08Platform\x12\x46\n\x05linux\x18\x01 \x01(\x0b\x32\x35.temporal.api.worker.v1.EnvironmentInfo.LinuxPlatformH\x00\x12\x46\n\x05macos\x18\x02 \x01(\x0b\x32\x35.temporal.api.worker.v1.EnvironmentInfo.MacOSPlatformH\x00\x12J\n\x07windows\x18\x03 \x01(\x0b\x32\x37.temporal.api.worker.v1.EnvironmentInfo.WindowsPlatformH\x00\x42\t\n\x07variant\x1a\xf3\x01\n\rLinuxPlatform\x12\x0f\n\x07version\x18\x01 \x01(\t\x12J\n\x0c\x61rchitecture\x18\x02 \x01(\x0e\x32\x34.temporal.api.worker.v1.EnvironmentInfo.Architecture\x12H\n\x04libc\x18\x03 \x01(\x0e\x32:.temporal.api.worker.v1.EnvironmentInfo.LinuxPlatform.Libc";\n\x04Libc\x12\x14\n\x10LIBC_UNSPECIFIED\x10\x00\x12\x0e\n\nLIBC_GLIBC\x10\x01\x12\r\n\tLIBC_MUSL\x10\x02\x1al\n\rMacOSPlatform\x12\x0f\n\x07version\x18\x01 \x01(\t\x12J\n\x0c\x61rchitecture\x18\x02 \x01(\x0e\x32\x34.temporal.api.worker.v1.EnvironmentInfo.Architecture\x1a\x91\x02\n\x0fWindowsPlatform\x12\x0f\n\x07version\x18\x01 \x01(\t\x12J\n\x0c\x61rchitecture\x18\x02 \x01(\x0e\x32\x34.temporal.api.worker.v1.EnvironmentInfo.Architecture\x12H\n\x03\x63rt\x18\x03 \x01(\x0e\x32;.temporal.api.worker.v1.EnvironmentInfo.WindowsPlatform.Crt"W\n\x03\x43rt\x12\x13\n\x0f\x43RT_UNSPECIFIED\x10\x00\x12\x0c\n\x08\x43RT_UCRT\x10\x01\x12\x0e\n\nCRT_MSVCRT\x10\x02\x12\r\n\tCRT_MINGW\x10\x03\x12\x0e\n\nCRT_CYGWIN\x10\x04"\\\n\x0c\x41rchitecture\x12\x1c\n\x18\x41RCHITECTURE_UNSPECIFIED\x10\x00\x12\x16\n\x12\x41RCHITECTURE_AMD64\x10\x01\x12\x16\n\x12\x41RCHITECTURE_ARM64\x10\x02"a\n\rWorkerCommand\x12H\n\x0f\x63\x61ncel_activity\x18\x01 \x01(\x0b\x32-.temporal.api.worker.v1.CancelActivityCommandH\x00\x42\x06\n\x04type"+\n\x15\x43\x61ncelActivityCommand\x12\x12\n\ntask_token\x18\x01 \x01(\x0c"f\n\x13WorkerCommandResult\x12G\n\x0f\x63\x61ncel_activity\x18\x01 \x01(\x0b\x32,.temporal.api.worker.v1.CancelActivityResultH\x00\x42\x06\n\x04type"\x16\n\x14\x43\x61ncelActivityResultB\x89\x01\n\x19io.temporal.api.worker.v1B\x0cMessageProtoP\x01Z#go.temporal.io/api/worker/v1;worker\xaa\x02\x18Temporalio.Api.Worker.V1\xea\x02\x1bTemporalio::Api::Worker::V1b\x06proto3' ) @@ -37,10 +37,34 @@ _WORKERLISTINFO = DESCRIPTOR.message_types_by_name["WorkerListInfo"] _PLUGININFO = DESCRIPTOR.message_types_by_name["PluginInfo"] _STORAGEDRIVERINFO = DESCRIPTOR.message_types_by_name["StorageDriverInfo"] +_ENVIRONMENTINFO = DESCRIPTOR.message_types_by_name["EnvironmentInfo"] +_ENVIRONMENTINFO_RUNTIME = _ENVIRONMENTINFO.nested_types_by_name["Runtime"] +_ENVIRONMENTINFO_HOSTINGENVIRONMENT = _ENVIRONMENTINFO.nested_types_by_name[ + "HostingEnvironment" +] +_ENVIRONMENTINFO_PLATFORM = _ENVIRONMENTINFO.nested_types_by_name["Platform"] +_ENVIRONMENTINFO_LINUXPLATFORM = _ENVIRONMENTINFO.nested_types_by_name["LinuxPlatform"] +_ENVIRONMENTINFO_MACOSPLATFORM = _ENVIRONMENTINFO.nested_types_by_name["MacOSPlatform"] +_ENVIRONMENTINFO_WINDOWSPLATFORM = _ENVIRONMENTINFO.nested_types_by_name[ + "WindowsPlatform" +] _WORKERCOMMAND = DESCRIPTOR.message_types_by_name["WorkerCommand"] _CANCELACTIVITYCOMMAND = DESCRIPTOR.message_types_by_name["CancelActivityCommand"] _WORKERCOMMANDRESULT = DESCRIPTOR.message_types_by_name["WorkerCommandResult"] _CANCELACTIVITYRESULT = DESCRIPTOR.message_types_by_name["CancelActivityResult"] +_ENVIRONMENTINFO_RUNTIME_RUNTIMETYPE = _ENVIRONMENTINFO_RUNTIME.enum_types_by_name[ + "RuntimeType" +] +_ENVIRONMENTINFO_HOSTINGENVIRONMENT_HOSTINGENVIRONMENTTYPE = ( + _ENVIRONMENTINFO_HOSTINGENVIRONMENT.enum_types_by_name["HostingEnvironmentType"] +) +_ENVIRONMENTINFO_LINUXPLATFORM_LIBC = _ENVIRONMENTINFO_LINUXPLATFORM.enum_types_by_name[ + "Libc" +] +_ENVIRONMENTINFO_WINDOWSPLATFORM_CRT = ( + _ENVIRONMENTINFO_WINDOWSPLATFORM.enum_types_by_name["Crt"] +) +_ENVIRONMENTINFO_ARCHITECTURE = _ENVIRONMENTINFO.enum_types_by_name["Architecture"] WorkerPollerInfo = _reflection.GeneratedProtocolMessageType( "WorkerPollerInfo", (_message.Message,), @@ -129,6 +153,77 @@ ) _sym_db.RegisterMessage(StorageDriverInfo) +EnvironmentInfo = _reflection.GeneratedProtocolMessageType( + "EnvironmentInfo", + (_message.Message,), + { + "Runtime": _reflection.GeneratedProtocolMessageType( + "Runtime", + (_message.Message,), + { + "DESCRIPTOR": _ENVIRONMENTINFO_RUNTIME, + "__module__": "temporalio.api.worker.v1.message_pb2", + # @@protoc_insertion_point(class_scope:temporal.api.worker.v1.EnvironmentInfo.Runtime) + }, + ), + "HostingEnvironment": _reflection.GeneratedProtocolMessageType( + "HostingEnvironment", + (_message.Message,), + { + "DESCRIPTOR": _ENVIRONMENTINFO_HOSTINGENVIRONMENT, + "__module__": "temporalio.api.worker.v1.message_pb2", + # @@protoc_insertion_point(class_scope:temporal.api.worker.v1.EnvironmentInfo.HostingEnvironment) + }, + ), + "Platform": _reflection.GeneratedProtocolMessageType( + "Platform", + (_message.Message,), + { + "DESCRIPTOR": _ENVIRONMENTINFO_PLATFORM, + "__module__": "temporalio.api.worker.v1.message_pb2", + # @@protoc_insertion_point(class_scope:temporal.api.worker.v1.EnvironmentInfo.Platform) + }, + ), + "LinuxPlatform": _reflection.GeneratedProtocolMessageType( + "LinuxPlatform", + (_message.Message,), + { + "DESCRIPTOR": _ENVIRONMENTINFO_LINUXPLATFORM, + "__module__": "temporalio.api.worker.v1.message_pb2", + # @@protoc_insertion_point(class_scope:temporal.api.worker.v1.EnvironmentInfo.LinuxPlatform) + }, + ), + "MacOSPlatform": _reflection.GeneratedProtocolMessageType( + "MacOSPlatform", + (_message.Message,), + { + "DESCRIPTOR": _ENVIRONMENTINFO_MACOSPLATFORM, + "__module__": "temporalio.api.worker.v1.message_pb2", + # @@protoc_insertion_point(class_scope:temporal.api.worker.v1.EnvironmentInfo.MacOSPlatform) + }, + ), + "WindowsPlatform": _reflection.GeneratedProtocolMessageType( + "WindowsPlatform", + (_message.Message,), + { + "DESCRIPTOR": _ENVIRONMENTINFO_WINDOWSPLATFORM, + "__module__": "temporalio.api.worker.v1.message_pb2", + # @@protoc_insertion_point(class_scope:temporal.api.worker.v1.EnvironmentInfo.WindowsPlatform) + }, + ), + "DESCRIPTOR": _ENVIRONMENTINFO, + "__module__": "temporalio.api.worker.v1.message_pb2", + # @@protoc_insertion_point(class_scope:temporal.api.worker.v1.EnvironmentInfo) + }, +) +_sym_db.RegisterMessage(EnvironmentInfo) +_sym_db.RegisterMessage(EnvironmentInfo.Runtime) +_sym_db.RegisterMessage(EnvironmentInfo.HostingEnvironment) +_sym_db.RegisterMessage(EnvironmentInfo.Platform) +_sym_db.RegisterMessage(EnvironmentInfo.LinuxPlatform) +_sym_db.RegisterMessage(EnvironmentInfo.MacOSPlatform) +_sym_db.RegisterMessage(EnvironmentInfo.WindowsPlatform) + WorkerCommand = _reflection.GeneratedProtocolMessageType( "WorkerCommand", (_message.Message,), @@ -183,21 +278,45 @@ _WORKERHOSTINFO._serialized_start = 585 _WORKERHOSTINFO._serialized_end = 733 _WORKERHEARTBEAT._serialized_start = 736 - _WORKERHEARTBEAT._serialized_end = 2027 - _WORKERINFO._serialized_start = 2029 - _WORKERINFO._serialized_end = 2108 - _WORKERLISTINFO._serialized_start = 2111 - _WORKERLISTINFO._serialized_end = 2603 - _PLUGININFO._serialized_start = 2605 - _PLUGININFO._serialized_end = 2648 - _STORAGEDRIVERINFO._serialized_start = 2650 - _STORAGEDRIVERINFO._serialized_end = 2683 - _WORKERCOMMAND._serialized_start = 2685 - _WORKERCOMMAND._serialized_end = 2782 - _CANCELACTIVITYCOMMAND._serialized_start = 2784 - _CANCELACTIVITYCOMMAND._serialized_end = 2827 - _WORKERCOMMANDRESULT._serialized_start = 2829 - _WORKERCOMMANDRESULT._serialized_end = 2931 - _CANCELACTIVITYRESULT._serialized_start = 2933 - _CANCELACTIVITYRESULT._serialized_end = 2955 + _WORKERHEARTBEAT._serialized_end = 2089 + _WORKERINFO._serialized_start = 2091 + _WORKERINFO._serialized_end = 2170 + _WORKERLISTINFO._serialized_start = 2173 + _WORKERLISTINFO._serialized_end = 2665 + _PLUGININFO._serialized_start = 2667 + _PLUGININFO._serialized_end = 2710 + _STORAGEDRIVERINFO._serialized_start = 2712 + _STORAGEDRIVERINFO._serialized_end = 2745 + _ENVIRONMENTINFO._serialized_start = 2748 + _ENVIRONMENTINFO._serialized_end = 4963 + _ENVIRONMENTINFO_RUNTIME._serialized_start = 2993 + _ENVIRONMENTINFO_RUNTIME._serialized_end = 3397 + _ENVIRONMENTINFO_RUNTIME_RUNTIMETYPE._serialized_start = 3097 + _ENVIRONMENTINFO_RUNTIME_RUNTIMETYPE._serialized_end = 3397 + _ENVIRONMENTINFO_HOSTINGENVIRONMENT._serialized_start = 3400 + _ENVIRONMENTINFO_HOSTINGENVIRONMENT._serialized_end = 3993 + _ENVIRONMENTINFO_HOSTINGENVIRONMENT_HOSTINGENVIRONMENTTYPE._serialized_start = 3537 + _ENVIRONMENTINFO_HOSTINGENVIRONMENT_HOSTINGENVIRONMENTTYPE._serialized_end = 3993 + _ENVIRONMENTINFO_PLATFORM._serialized_start = 3996 + _ENVIRONMENTINFO_PLATFORM._serialized_end = 4237 + _ENVIRONMENTINFO_LINUXPLATFORM._serialized_start = 4240 + _ENVIRONMENTINFO_LINUXPLATFORM._serialized_end = 4483 + _ENVIRONMENTINFO_LINUXPLATFORM_LIBC._serialized_start = 4424 + _ENVIRONMENTINFO_LINUXPLATFORM_LIBC._serialized_end = 4483 + _ENVIRONMENTINFO_MACOSPLATFORM._serialized_start = 4485 + _ENVIRONMENTINFO_MACOSPLATFORM._serialized_end = 4593 + _ENVIRONMENTINFO_WINDOWSPLATFORM._serialized_start = 4596 + _ENVIRONMENTINFO_WINDOWSPLATFORM._serialized_end = 4869 + _ENVIRONMENTINFO_WINDOWSPLATFORM_CRT._serialized_start = 4782 + _ENVIRONMENTINFO_WINDOWSPLATFORM_CRT._serialized_end = 4869 + _ENVIRONMENTINFO_ARCHITECTURE._serialized_start = 4871 + _ENVIRONMENTINFO_ARCHITECTURE._serialized_end = 4963 + _WORKERCOMMAND._serialized_start = 4965 + _WORKERCOMMAND._serialized_end = 5062 + _CANCELACTIVITYCOMMAND._serialized_start = 5064 + _CANCELACTIVITYCOMMAND._serialized_end = 5107 + _WORKERCOMMANDRESULT._serialized_start = 5109 + _WORKERCOMMANDRESULT._serialized_end = 5211 + _CANCELACTIVITYRESULT._serialized_start = 5213 + _CANCELACTIVITYRESULT._serialized_end = 5235 # @@protoc_insertion_point(module_scope) diff --git a/temporalio/api/worker/v1/message_pb2.pyi b/temporalio/api/worker/v1/message_pb2.pyi index f78916ed5..9a630f998 100644 --- a/temporalio/api/worker/v1/message_pb2.pyi +++ b/temporalio/api/worker/v1/message_pb2.pyi @@ -6,17 +6,19 @@ isort:skip_file import builtins import collections.abc import sys +import typing import google.protobuf.descriptor import google.protobuf.duration_pb2 import google.protobuf.internal.containers +import google.protobuf.internal.enum_type_wrapper import google.protobuf.message import google.protobuf.timestamp_pb2 import temporalio.api.deployment.v1.message_pb2 import temporalio.api.enums.v1.common_pb2 -if sys.version_info >= (3, 8): +if sys.version_info >= (3, 10): import typing as typing_extensions else: import typing_extensions @@ -217,6 +219,7 @@ class WorkerHeartbeat(google.protobuf.message.Message): CURRENT_STICKY_CACHE_SIZE_FIELD_NUMBER: builtins.int PLUGINS_FIELD_NUMBER: builtins.int DRIVERS_FIELD_NUMBER: builtins.int + ENVIRONMENT_FIELD_NUMBER: builtins.int worker_instance_key: builtins.str """Worker identifier, should be unique for the namespace. It is distinct from worker identity, which is not necessarily namespace-unique. @@ -287,6 +290,9 @@ class WorkerHeartbeat(google.protobuf.message.Message): global___StorageDriverInfo ]: """Storage drivers in use by this SDK.""" + @property + def environment(self) -> global___EnvironmentInfo: + """Information about the environment this SDK is running in.""" def __init__( self, *, @@ -316,6 +322,7 @@ class WorkerHeartbeat(google.protobuf.message.Message): current_sticky_cache_size: builtins.int = ..., plugins: collections.abc.Iterable[global___PluginInfo] | None = ..., drivers: collections.abc.Iterable[global___StorageDriverInfo] | None = ..., + environment: global___EnvironmentInfo | None = ..., ) -> None: ... def HasField( self, @@ -328,6 +335,8 @@ class WorkerHeartbeat(google.protobuf.message.Message): b"deployment_version", "elapsed_since_last_heartbeat", b"elapsed_since_last_heartbeat", + "environment", + b"environment", "heartbeat_time", b"heartbeat_time", "host_info", @@ -363,6 +372,8 @@ class WorkerHeartbeat(google.protobuf.message.Message): b"drivers", "elapsed_since_last_heartbeat", b"elapsed_since_last_heartbeat", + "environment", + b"environment", "heartbeat_time", b"heartbeat_time", "host_info", @@ -593,6 +604,446 @@ class StorageDriverInfo(google.protobuf.message.Message): global___StorageDriverInfo = StorageDriverInfo +class EnvironmentInfo(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + class _Architecture: + ValueType = typing.NewType("ValueType", builtins.int) + V: typing_extensions.TypeAlias = ValueType + + class _ArchitectureEnumTypeWrapper( + google.protobuf.internal.enum_type_wrapper._EnumTypeWrapper[ + EnvironmentInfo._Architecture.ValueType + ], + builtins.type, + ): # noqa: F821 + DESCRIPTOR: google.protobuf.descriptor.EnumDescriptor + ARCHITECTURE_UNSPECIFIED: EnvironmentInfo._Architecture.ValueType # 0 + ARCHITECTURE_AMD64: EnvironmentInfo._Architecture.ValueType # 1 + ARCHITECTURE_ARM64: EnvironmentInfo._Architecture.ValueType # 2 + + class Architecture(_Architecture, metaclass=_ArchitectureEnumTypeWrapper): ... + ARCHITECTURE_UNSPECIFIED: EnvironmentInfo.Architecture.ValueType # 0 + ARCHITECTURE_AMD64: EnvironmentInfo.Architecture.ValueType # 1 + ARCHITECTURE_ARM64: EnvironmentInfo.Architecture.ValueType # 2 + + class Runtime(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + class _RuntimeType: + ValueType = typing.NewType("ValueType", builtins.int) + V: typing_extensions.TypeAlias = ValueType + + class _RuntimeTypeEnumTypeWrapper( + google.protobuf.internal.enum_type_wrapper._EnumTypeWrapper[ + EnvironmentInfo.Runtime._RuntimeType.ValueType + ], + builtins.type, + ): # noqa: F821 + DESCRIPTOR: google.protobuf.descriptor.EnumDescriptor + RUNTIME_TYPE_UNSPECIFIED: ( + EnvironmentInfo.Runtime._RuntimeType.ValueType + ) # 0 + """Should never actually be set, exists to follow convention of having a default. + SDKs should just leave `runtimes` empty if none can be determined. + """ + RUNTIME_TYPE_JVM: EnvironmentInfo.Runtime._RuntimeType.ValueType # 1 + RUNTIME_TYPE_CPYTHON: EnvironmentInfo.Runtime._RuntimeType.ValueType # 2 + RUNTIME_TYPE_NODE: EnvironmentInfo.Runtime._RuntimeType.ValueType # 3 + RUNTIME_TYPE_BUN: EnvironmentInfo.Runtime._RuntimeType.ValueType # 4 + RUNTIME_TYPE_CRUBY: EnvironmentInfo.Runtime._RuntimeType.ValueType # 5 + RUNTIME_TYPE_GO: EnvironmentInfo.Runtime._RuntimeType.ValueType # 6 + RUNTIME_TYPE_DOTNET_FRAMEWORK: ( + EnvironmentInfo.Runtime._RuntimeType.ValueType + ) # 7 + RUNTIME_TYPE_DOTNET_CORE: ( + EnvironmentInfo.Runtime._RuntimeType.ValueType + ) # 8 + RUNTIME_TYPE_NATIVE: EnvironmentInfo.Runtime._RuntimeType.ValueType # 9 + RUNTIME_TYPE_ROADRUNNER: ( + EnvironmentInfo.Runtime._RuntimeType.ValueType + ) # 10 + + class RuntimeType(_RuntimeType, metaclass=_RuntimeTypeEnumTypeWrapper): ... + RUNTIME_TYPE_UNSPECIFIED: EnvironmentInfo.Runtime.RuntimeType.ValueType # 0 + """Should never actually be set, exists to follow convention of having a default. + SDKs should just leave `runtimes` empty if none can be determined. + """ + RUNTIME_TYPE_JVM: EnvironmentInfo.Runtime.RuntimeType.ValueType # 1 + RUNTIME_TYPE_CPYTHON: EnvironmentInfo.Runtime.RuntimeType.ValueType # 2 + RUNTIME_TYPE_NODE: EnvironmentInfo.Runtime.RuntimeType.ValueType # 3 + RUNTIME_TYPE_BUN: EnvironmentInfo.Runtime.RuntimeType.ValueType # 4 + RUNTIME_TYPE_CRUBY: EnvironmentInfo.Runtime.RuntimeType.ValueType # 5 + RUNTIME_TYPE_GO: EnvironmentInfo.Runtime.RuntimeType.ValueType # 6 + RUNTIME_TYPE_DOTNET_FRAMEWORK: ( + EnvironmentInfo.Runtime.RuntimeType.ValueType + ) # 7 + RUNTIME_TYPE_DOTNET_CORE: EnvironmentInfo.Runtime.RuntimeType.ValueType # 8 + RUNTIME_TYPE_NATIVE: EnvironmentInfo.Runtime.RuntimeType.ValueType # 9 + RUNTIME_TYPE_ROADRUNNER: EnvironmentInfo.Runtime.RuntimeType.ValueType # 10 + + TYPE_FIELD_NUMBER: builtins.int + VERSION_FIELD_NUMBER: builtins.int + type: global___EnvironmentInfo.Runtime.RuntimeType.ValueType + """The type of the runtime.""" + version: builtins.str + """The version of the runtime, if obtainable.""" + def __init__( + self, + *, + type: global___EnvironmentInfo.Runtime.RuntimeType.ValueType = ..., + version: builtins.str = ..., + ) -> None: ... + def ClearField( + self, + field_name: typing_extensions.Literal[ + "type", b"type", "version", b"version" + ], + ) -> None: ... + + class HostingEnvironment(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + class _HostingEnvironmentType: + ValueType = typing.NewType("ValueType", builtins.int) + V: typing_extensions.TypeAlias = ValueType + + class _HostingEnvironmentTypeEnumTypeWrapper( + google.protobuf.internal.enum_type_wrapper._EnumTypeWrapper[ + EnvironmentInfo.HostingEnvironment._HostingEnvironmentType.ValueType + ], + builtins.type, + ): # noqa: F821 + DESCRIPTOR: google.protobuf.descriptor.EnumDescriptor + HOSTING_ENVIRONMENT_TYPE_UNSPECIFIED: ( + EnvironmentInfo.HostingEnvironment._HostingEnvironmentType.ValueType + ) # 0 + """Should never actually be set, exists to follow convention of having a default. + SDKs should just leave `hosting_environments` empty if none can be determined. + """ + HOSTING_ENVIRONMENT_TYPE_DOCKER: ( + EnvironmentInfo.HostingEnvironment._HostingEnvironmentType.ValueType + ) # 1 + """Should always be in the list if we're running inside a docker container""" + HOSTING_ENVIRONMENT_TYPE_K8S: ( + EnvironmentInfo.HostingEnvironment._HostingEnvironmentType.ValueType + ) # 2 + """Should always be in the list if we're running inside any k8s environment""" + HOSTING_ENVIRONMENT_TYPE_AWS_LAMBDA: ( + EnvironmentInfo.HostingEnvironment._HostingEnvironmentType.ValueType + ) # 3 + """Detect via `AWS_LAMBDA_FUNCTION_NAME`""" + HOSTING_ENVIRONMENT_TYPE_AWS_ECS: ( + EnvironmentInfo.HostingEnvironment._HostingEnvironmentType.ValueType + ) # 4 + """Detect via `ECS_CONTAINER_METADATA_URI_V4` or `ECS_CONTAINER_METADATA_URI`""" + HOSTING_ENVIRONMENT_TYPE_GOOGLE_CLOUD_RUN: ( + EnvironmentInfo.HostingEnvironment._HostingEnvironmentType.ValueType + ) # 6 + """Detect via `K_SERVICE`""" + HOSTING_ENVIRONMENT_TYPE_GOOGLE_APP_ENGINE: ( + EnvironmentInfo.HostingEnvironment._HostingEnvironmentType.ValueType + ) # 7 + """Detect via `GAE_SERVICE`""" + HOSTING_ENVIRONMENT_TYPE_AZURE_APP_SERVICE: ( + EnvironmentInfo.HostingEnvironment._HostingEnvironmentType.ValueType + ) # 8 + """Detect via `WEBSITE_SITE_NAME`""" + HOSTING_ENVIRONMENT_TYPE_AZURE_FUNCTIONS: ( + EnvironmentInfo.HostingEnvironment._HostingEnvironmentType.ValueType + ) # 9 + """Detect via `FUNCTIONS_EXTENSION_VERSION`""" + HOSTING_ENVIRONMENT_TYPE_AZURE_CONTAINER_APPS: ( + EnvironmentInfo.HostingEnvironment._HostingEnvironmentType.ValueType + ) # 10 + """Detect via `CONTAINER_APP_NAME`""" + + class HostingEnvironmentType( + _HostingEnvironmentType, metaclass=_HostingEnvironmentTypeEnumTypeWrapper + ): + """What kind of hosting environment we're running in. This list is about what can actually be + detected reliably and is unrelated to what SDKs can actually run in. + """ + + HOSTING_ENVIRONMENT_TYPE_UNSPECIFIED: ( + EnvironmentInfo.HostingEnvironment.HostingEnvironmentType.ValueType + ) # 0 + """Should never actually be set, exists to follow convention of having a default. + SDKs should just leave `hosting_environments` empty if none can be determined. + """ + HOSTING_ENVIRONMENT_TYPE_DOCKER: ( + EnvironmentInfo.HostingEnvironment.HostingEnvironmentType.ValueType + ) # 1 + """Should always be in the list if we're running inside a docker container""" + HOSTING_ENVIRONMENT_TYPE_K8S: ( + EnvironmentInfo.HostingEnvironment.HostingEnvironmentType.ValueType + ) # 2 + """Should always be in the list if we're running inside any k8s environment""" + HOSTING_ENVIRONMENT_TYPE_AWS_LAMBDA: ( + EnvironmentInfo.HostingEnvironment.HostingEnvironmentType.ValueType + ) # 3 + """Detect via `AWS_LAMBDA_FUNCTION_NAME`""" + HOSTING_ENVIRONMENT_TYPE_AWS_ECS: ( + EnvironmentInfo.HostingEnvironment.HostingEnvironmentType.ValueType + ) # 4 + """Detect via `ECS_CONTAINER_METADATA_URI_V4` or `ECS_CONTAINER_METADATA_URI`""" + HOSTING_ENVIRONMENT_TYPE_GOOGLE_CLOUD_RUN: ( + EnvironmentInfo.HostingEnvironment.HostingEnvironmentType.ValueType + ) # 6 + """Detect via `K_SERVICE`""" + HOSTING_ENVIRONMENT_TYPE_GOOGLE_APP_ENGINE: ( + EnvironmentInfo.HostingEnvironment.HostingEnvironmentType.ValueType + ) # 7 + """Detect via `GAE_SERVICE`""" + HOSTING_ENVIRONMENT_TYPE_AZURE_APP_SERVICE: ( + EnvironmentInfo.HostingEnvironment.HostingEnvironmentType.ValueType + ) # 8 + """Detect via `WEBSITE_SITE_NAME`""" + HOSTING_ENVIRONMENT_TYPE_AZURE_FUNCTIONS: ( + EnvironmentInfo.HostingEnvironment.HostingEnvironmentType.ValueType + ) # 9 + """Detect via `FUNCTIONS_EXTENSION_VERSION`""" + HOSTING_ENVIRONMENT_TYPE_AZURE_CONTAINER_APPS: ( + EnvironmentInfo.HostingEnvironment.HostingEnvironmentType.ValueType + ) # 10 + """Detect via `CONTAINER_APP_NAME`""" + + TYPE_FIELD_NUMBER: builtins.int + VERSION_FIELD_NUMBER: builtins.int + type: ( + global___EnvironmentInfo.HostingEnvironment.HostingEnvironmentType.ValueType + ) + """The type of hosting environment.""" + version: builtins.str + """The version of the hosting environment, if obtainable.""" + def __init__( + self, + *, + type: global___EnvironmentInfo.HostingEnvironment.HostingEnvironmentType.ValueType = ..., + version: builtins.str = ..., + ) -> None: ... + def ClearField( + self, + field_name: typing_extensions.Literal[ + "type", b"type", "version", b"version" + ], + ) -> None: ... + + class Platform(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + LINUX_FIELD_NUMBER: builtins.int + MACOS_FIELD_NUMBER: builtins.int + WINDOWS_FIELD_NUMBER: builtins.int + @property + def linux(self) -> global___EnvironmentInfo.LinuxPlatform: ... + @property + def macos(self) -> global___EnvironmentInfo.MacOSPlatform: ... + @property + def windows(self) -> global___EnvironmentInfo.WindowsPlatform: ... + def __init__( + self, + *, + linux: global___EnvironmentInfo.LinuxPlatform | None = ..., + macos: global___EnvironmentInfo.MacOSPlatform | None = ..., + windows: global___EnvironmentInfo.WindowsPlatform | None = ..., + ) -> None: ... + def HasField( + self, + field_name: typing_extensions.Literal[ + "linux", + b"linux", + "macos", + b"macos", + "variant", + b"variant", + "windows", + b"windows", + ], + ) -> builtins.bool: ... + def ClearField( + self, + field_name: typing_extensions.Literal[ + "linux", + b"linux", + "macos", + b"macos", + "variant", + b"variant", + "windows", + b"windows", + ], + ) -> None: ... + def WhichOneof( + self, oneof_group: typing_extensions.Literal["variant", b"variant"] + ) -> typing_extensions.Literal["linux", "macos", "windows"] | None: ... + + class LinuxPlatform(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + class _Libc: + ValueType = typing.NewType("ValueType", builtins.int) + V: typing_extensions.TypeAlias = ValueType + + class _LibcEnumTypeWrapper( + google.protobuf.internal.enum_type_wrapper._EnumTypeWrapper[ + EnvironmentInfo.LinuxPlatform._Libc.ValueType + ], + builtins.type, + ): # noqa: F821 + DESCRIPTOR: google.protobuf.descriptor.EnumDescriptor + LIBC_UNSPECIFIED: EnvironmentInfo.LinuxPlatform._Libc.ValueType # 0 + LIBC_GLIBC: EnvironmentInfo.LinuxPlatform._Libc.ValueType # 1 + LIBC_MUSL: EnvironmentInfo.LinuxPlatform._Libc.ValueType # 2 + + class Libc(_Libc, metaclass=_LibcEnumTypeWrapper): ... + LIBC_UNSPECIFIED: EnvironmentInfo.LinuxPlatform.Libc.ValueType # 0 + LIBC_GLIBC: EnvironmentInfo.LinuxPlatform.Libc.ValueType # 1 + LIBC_MUSL: EnvironmentInfo.LinuxPlatform.Libc.ValueType # 2 + + VERSION_FIELD_NUMBER: builtins.int + ARCHITECTURE_FIELD_NUMBER: builtins.int + LIBC_FIELD_NUMBER: builtins.int + version: builtins.str + """The Linux kernel or distribution version, if obtainable.""" + architecture: global___EnvironmentInfo.Architecture.ValueType + """The architecture of the worker process.""" + libc: global___EnvironmentInfo.LinuxPlatform.Libc.ValueType + """The libc used by the worker process.""" + def __init__( + self, + *, + version: builtins.str = ..., + architecture: global___EnvironmentInfo.Architecture.ValueType = ..., + libc: global___EnvironmentInfo.LinuxPlatform.Libc.ValueType = ..., + ) -> None: ... + def ClearField( + self, + field_name: typing_extensions.Literal[ + "architecture", b"architecture", "libc", b"libc", "version", b"version" + ], + ) -> None: ... + + class MacOSPlatform(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + VERSION_FIELD_NUMBER: builtins.int + ARCHITECTURE_FIELD_NUMBER: builtins.int + version: builtins.str + """The macOS version, if obtainable.""" + architecture: global___EnvironmentInfo.Architecture.ValueType + """The architecture of the worker process.""" + def __init__( + self, + *, + version: builtins.str = ..., + architecture: global___EnvironmentInfo.Architecture.ValueType = ..., + ) -> None: ... + def ClearField( + self, + field_name: typing_extensions.Literal[ + "architecture", b"architecture", "version", b"version" + ], + ) -> None: ... + + class WindowsPlatform(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + class _Crt: + ValueType = typing.NewType("ValueType", builtins.int) + V: typing_extensions.TypeAlias = ValueType + + class _CrtEnumTypeWrapper( + google.protobuf.internal.enum_type_wrapper._EnumTypeWrapper[ + EnvironmentInfo.WindowsPlatform._Crt.ValueType + ], + builtins.type, + ): # noqa: F821 + DESCRIPTOR: google.protobuf.descriptor.EnumDescriptor + CRT_UNSPECIFIED: EnvironmentInfo.WindowsPlatform._Crt.ValueType # 0 + CRT_UCRT: EnvironmentInfo.WindowsPlatform._Crt.ValueType # 1 + CRT_MSVCRT: EnvironmentInfo.WindowsPlatform._Crt.ValueType # 2 + CRT_MINGW: EnvironmentInfo.WindowsPlatform._Crt.ValueType # 3 + CRT_CYGWIN: EnvironmentInfo.WindowsPlatform._Crt.ValueType # 4 + + class Crt(_Crt, metaclass=_CrtEnumTypeWrapper): ... + CRT_UNSPECIFIED: EnvironmentInfo.WindowsPlatform.Crt.ValueType # 0 + CRT_UCRT: EnvironmentInfo.WindowsPlatform.Crt.ValueType # 1 + CRT_MSVCRT: EnvironmentInfo.WindowsPlatform.Crt.ValueType # 2 + CRT_MINGW: EnvironmentInfo.WindowsPlatform.Crt.ValueType # 3 + CRT_CYGWIN: EnvironmentInfo.WindowsPlatform.Crt.ValueType # 4 + + VERSION_FIELD_NUMBER: builtins.int + ARCHITECTURE_FIELD_NUMBER: builtins.int + CRT_FIELD_NUMBER: builtins.int + version: builtins.str + """The Windows version, if obtainable.""" + architecture: global___EnvironmentInfo.Architecture.ValueType + """The architecture of the worker process.""" + crt: global___EnvironmentInfo.WindowsPlatform.Crt.ValueType + """The C runtime used by the worker process, if obtainable.""" + def __init__( + self, + *, + version: builtins.str = ..., + architecture: global___EnvironmentInfo.Architecture.ValueType = ..., + crt: global___EnvironmentInfo.WindowsPlatform.Crt.ValueType = ..., + ) -> None: ... + def ClearField( + self, + field_name: typing_extensions.Literal[ + "architecture", b"architecture", "crt", b"crt", "version", b"version" + ], + ) -> None: ... + + RUNTIMES_FIELD_NUMBER: builtins.int + HOSTING_ENVIRONMENTS_FIELD_NUMBER: builtins.int + PLATFORM_FIELD_NUMBER: builtins.int + @property + def runtimes( + self, + ) -> google.protobuf.internal.containers.RepeatedCompositeFieldContainer[ + global___EnvironmentInfo.Runtime + ]: + """The runtime(s) the SDK is operating in.""" + @property + def hosting_environments( + self, + ) -> google.protobuf.internal.containers.RepeatedCompositeFieldContainer[ + global___EnvironmentInfo.HostingEnvironment + ]: + """The hosting environment(s) the SDK is operating in. Repeated to allow for layering (ex: Docker inside k8s).""" + @property + def platform(self) -> global___EnvironmentInfo.Platform: + """The platform the SDK is operating on.""" + def __init__( + self, + *, + runtimes: collections.abc.Iterable[global___EnvironmentInfo.Runtime] + | None = ..., + hosting_environments: collections.abc.Iterable[ + global___EnvironmentInfo.HostingEnvironment + ] + | None = ..., + platform: global___EnvironmentInfo.Platform | None = ..., + ) -> None: ... + def HasField( + self, field_name: typing_extensions.Literal["platform", b"platform"] + ) -> builtins.bool: ... + def ClearField( + self, + field_name: typing_extensions.Literal[ + "hosting_environments", + b"hosting_environments", + "platform", + b"platform", + "runtimes", + b"runtimes", + ], + ) -> None: ... + +global___EnvironmentInfo = EnvironmentInfo + class WorkerCommand(google.protobuf.message.Message): """A command sent from the server to a worker.""" diff --git a/temporalio/api/workflow/v1/message_pb2.py b/temporalio/api/workflow/v1/message_pb2.py index 24a9f03e2..032f2b2b5 100644 --- a/temporalio/api/workflow/v1/message_pb2.py +++ b/temporalio/api/workflow/v1/message_pb2.py @@ -48,7 +48,7 @@ ) DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile( - b'\n&temporal/api/workflow/v1/message.proto\x12\x18temporal.api.workflow.v1\x1a\x1egoogle/protobuf/duration.proto\x1a\x1bgoogle/protobuf/empty.proto\x1a\x1fgoogle/protobuf/timestamp.proto\x1a google/protobuf/field_mask.proto\x1a&temporal/api/activity/v1/message.proto\x1a"temporal/api/enums/v1/common.proto\x1a&temporal/api/enums/v1/event_type.proto\x1a$temporal/api/enums/v1/workflow.proto\x1a$temporal/api/common/v1/message.proto\x1a(temporal/api/deployment/v1/message.proto\x1a%temporal/api/failure/v1/message.proto\x1a\'temporal/api/taskqueue/v1/message.proto\x1a\'temporal/api/sdk/v1/user_metadata.proto"\xf0\t\n\x15WorkflowExecutionInfo\x12<\n\texecution\x18\x01 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x32\n\x04type\x18\x02 \x01(\x0b\x32$.temporal.api.common.v1.WorkflowType\x12.\n\nstart_time\x18\x03 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12.\n\nclose_time\x18\x04 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12>\n\x06status\x18\x05 \x01(\x0e\x32..temporal.api.enums.v1.WorkflowExecutionStatus\x12\x16\n\x0ehistory_length\x18\x06 \x01(\x03\x12\x1b\n\x13parent_namespace_id\x18\x07 \x01(\t\x12\x43\n\x10parent_execution\x18\x08 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x32\n\x0e\x65xecution_time\x18\t \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12*\n\x04memo\x18\n \x01(\x0b\x32\x1c.temporal.api.common.v1.Memo\x12\x43\n\x11search_attributes\x18\x0b \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes\x12@\n\x11\x61uto_reset_points\x18\x0c \x01(\x0b\x32%.temporal.api.workflow.v1.ResetPoints\x12\x12\n\ntask_queue\x18\r \x01(\t\x12\x1e\n\x16state_transition_count\x18\x0e \x01(\x03\x12\x1a\n\x12history_size_bytes\x18\x0f \x01(\x03\x12X\n most_recent_worker_version_stamp\x18\x10 \x01(\x0b\x32*.temporal.api.common.v1.WorkerVersionStampB\x02\x18\x01\x12\x35\n\x12\x65xecution_duration\x18\x11 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x41\n\x0eroot_execution\x18\x12 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x1d\n\x11\x61ssigned_build_id\x18\x13 \x01(\tB\x02\x18\x01\x12\x1e\n\x12inherited_build_id\x18\x14 \x01(\tB\x02\x18\x01\x12\x14\n\x0c\x66irst_run_id\x18\x15 \x01(\t\x12R\n\x0fversioning_info\x18\x16 \x01(\x0b\x32\x39.temporal.api.workflow.v1.WorkflowExecutionVersioningInfo\x12\x1e\n\x16worker_deployment_name\x18\x17 \x01(\t\x12\x32\n\x08priority\x18\x18 \x01(\x0b\x32 .temporal.api.common.v1.Priority\x12#\n\x1b\x65xternal_payload_size_bytes\x18\x19 \x01(\x03\x12\x1e\n\x16\x65xternal_payload_count\x18\x1a \x01(\x03"\xc6\x04\n\x1dWorkflowExecutionExtendedInfo\x12=\n\x19\x65xecution_expiration_time\x18\x01 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x37\n\x13run_expiration_time\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x18\n\x10\x63\x61ncel_requested\x18\x03 \x01(\x08\x12\x33\n\x0flast_reset_time\x18\x04 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x37\n\x13original_start_time\x18\x05 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x14\n\x0creset_run_id\x18\x06 \x01(\t\x12\x65\n\x10request_id_infos\x18\x07 \x03(\x0b\x32K.temporal.api.workflow.v1.WorkflowExecutionExtendedInfo.RequestIdInfosEntry\x12H\n\npause_info\x18\x08 \x01(\x0b\x32\x34.temporal.api.workflow.v1.WorkflowExecutionPauseInfo\x1a^\n\x13RequestIdInfosEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x36\n\x05value\x18\x02 \x01(\x0b\x32\'.temporal.api.workflow.v1.RequestIdInfo:\x02\x38\x01"\xfb\x04\n\x1fWorkflowExecutionVersioningInfo\x12;\n\x08\x62\x65havior\x18\x01 \x01(\x0e\x32).temporal.api.enums.v1.VersioningBehavior\x12>\n\ndeployment\x18\x02 \x01(\x0b\x32&.temporal.api.deployment.v1.DeploymentB\x02\x18\x01\x12\x13\n\x07version\x18\x05 \x01(\tB\x02\x18\x01\x12O\n\x12\x64\x65ployment_version\x18\x07 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersion\x12I\n\x13versioning_override\x18\x03 \x01(\x0b\x32,.temporal.api.workflow.v1.VersioningOverride\x12Q\n\x15\x64\x65ployment_transition\x18\x04 \x01(\x0b\x32..temporal.api.workflow.v1.DeploymentTransitionB\x02\x18\x01\x12Q\n\x12version_transition\x18\x06 \x01(\x0b\x32\x35.temporal.api.workflow.v1.DeploymentVersionTransition\x12\x17\n\x0frevision_number\x18\x08 \x01(\x03\x12k\n+continue_as_new_initial_versioning_behavior\x18\t \x01(\x0e\x32\x36.temporal.api.enums.v1.ContinueAsNewVersioningBehavior"R\n\x14\x44\x65ploymentTransition\x12:\n\ndeployment\x18\x01 \x01(\x0b\x32&.temporal.api.deployment.v1.Deployment"\x83\x01\n\x1b\x44\x65ploymentVersionTransition\x12\x13\n\x07version\x18\x01 \x01(\tB\x02\x18\x01\x12O\n\x12\x64\x65ployment_version\x18\x02 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersion"\xc7\x02\n\x17WorkflowExecutionConfig\x12\x38\n\ntask_queue\x18\x01 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12=\n\x1aworkflow_execution_timeout\x18\x02 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x37\n\x14workflow_run_timeout\x18\x03 \x01(\x0b\x32\x19.google.protobuf.Duration\x12@\n\x1d\x64\x65\x66\x61ult_workflow_task_timeout\x18\x04 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x38\n\ruser_metadata\x18\x05 \x01(\x0b\x32!.temporal.api.sdk.v1.UserMetadata"\xbd\r\n\x13PendingActivityInfo\x12\x13\n\x0b\x61\x63tivity_id\x18\x01 \x01(\t\x12;\n\ractivity_type\x18\x02 \x01(\x0b\x32$.temporal.api.common.v1.ActivityType\x12:\n\x05state\x18\x03 \x01(\x0e\x32+.temporal.api.enums.v1.PendingActivityState\x12;\n\x11heartbeat_details\x18\x04 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x37\n\x13last_heartbeat_time\x18\x05 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x35\n\x11last_started_time\x18\x06 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x0f\n\x07\x61ttempt\x18\x07 \x01(\x05\x12\x18\n\x10maximum_attempts\x18\x08 \x01(\x05\x12\x32\n\x0escheduled_time\x18\t \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x33\n\x0f\x65xpiration_time\x18\n \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x36\n\x0clast_failure\x18\x0b \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12\x1c\n\x14last_worker_identity\x18\x0c \x01(\t\x12;\n\x15use_workflow_build_id\x18\r \x01(\x0b\x32\x16.google.protobuf.EmptyB\x02\x18\x01H\x00\x12\x32\n$last_independently_assigned_build_id\x18\x0e \x01(\tB\x02\x18\x01H\x00\x12Q\n\x19last_worker_version_stamp\x18\x0f \x01(\x0b\x32*.temporal.api.common.v1.WorkerVersionStampB\x02\x18\x01\x12\x39\n\x16\x63urrent_retry_interval\x18\x10 \x01(\x0b\x32\x19.google.protobuf.Duration\x12>\n\x1alast_attempt_complete_time\x18\x11 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12>\n\x1anext_attempt_schedule_time\x18\x12 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x0e\n\x06paused\x18\x13 \x01(\x08\x12\x43\n\x0flast_deployment\x18\x14 \x01(\x0b\x32&.temporal.api.deployment.v1.DeploymentB\x02\x18\x01\x12*\n\x1elast_worker_deployment_version\x18\x15 \x01(\tB\x02\x18\x01\x12T\n\x17last_deployment_version\x18\x19 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersion\x12\x32\n\x08priority\x18\x16 \x01(\x0b\x32 .temporal.api.common.v1.Priority\x12K\n\npause_info\x18\x17 \x01(\x0b\x32\x37.temporal.api.workflow.v1.PendingActivityInfo.PauseInfo\x12\x43\n\x10\x61\x63tivity_options\x18\x18 \x01(\x0b\x32).temporal.api.activity.v1.ActivityOptions\x1a\xcf\x02\n\tPauseInfo\x12.\n\npause_time\x18\x01 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12P\n\x06manual\x18\x02 \x01(\x0b\x32>.temporal.api.workflow.v1.PendingActivityInfo.PauseInfo.ManualH\x00\x12L\n\x04rule\x18\x04 \x01(\x0b\x32<.temporal.api.workflow.v1.PendingActivityInfo.PauseInfo.RuleH\x00\x1a*\n\x06Manual\x12\x10\n\x08identity\x18\x01 \x01(\t\x12\x0e\n\x06reason\x18\x02 \x01(\t\x1a\x39\n\x04Rule\x12\x0f\n\x07rule_id\x18\x01 \x01(\t\x12\x10\n\x08identity\x18\x02 \x01(\t\x12\x0e\n\x06reason\x18\x03 \x01(\tB\x0b\n\tpaused_byB\x13\n\x11\x61ssigned_build_id"\xb9\x01\n\x19PendingChildExecutionInfo\x12\x13\n\x0bworkflow_id\x18\x01 \x01(\t\x12\x0e\n\x06run_id\x18\x02 \x01(\t\x12\x1a\n\x12workflow_type_name\x18\x03 \x01(\t\x12\x14\n\x0cinitiated_id\x18\x04 \x01(\x03\x12\x45\n\x13parent_close_policy\x18\x05 \x01(\x0e\x32(.temporal.api.enums.v1.ParentClosePolicy"\x8d\x02\n\x17PendingWorkflowTaskInfo\x12>\n\x05state\x18\x01 \x01(\x0e\x32/.temporal.api.enums.v1.PendingWorkflowTaskState\x12\x32\n\x0escheduled_time\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12;\n\x17original_scheduled_time\x18\x03 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x30\n\x0cstarted_time\x18\x04 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x0f\n\x07\x61ttempt\x18\x05 \x01(\x05"G\n\x0bResetPoints\x12\x38\n\x06points\x18\x01 \x03(\x0b\x32(.temporal.api.workflow.v1.ResetPointInfo"\xef\x01\n\x0eResetPointInfo\x12\x10\n\x08\x62uild_id\x18\x07 \x01(\t\x12\x1b\n\x0f\x62inary_checksum\x18\x01 \x01(\tB\x02\x18\x01\x12\x0e\n\x06run_id\x18\x02 \x01(\t\x12(\n first_workflow_task_completed_id\x18\x03 \x01(\x03\x12/\n\x0b\x63reate_time\x18\x04 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12/\n\x0b\x65xpire_time\x18\x05 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x12\n\nresettable\x18\x06 \x01(\x08"\x85\x07\n\x18NewWorkflowExecutionInfo\x12\x13\n\x0bworkflow_id\x18\x01 \x01(\t\x12;\n\rworkflow_type\x18\x02 \x01(\x0b\x32$.temporal.api.common.v1.WorkflowType\x12\x38\n\ntask_queue\x18\x03 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12/\n\x05input\x18\x04 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12=\n\x1aworkflow_execution_timeout\x18\x05 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x37\n\x14workflow_run_timeout\x18\x06 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x38\n\x15workflow_task_timeout\x18\x07 \x01(\x0b\x32\x19.google.protobuf.Duration\x12N\n\x18workflow_id_reuse_policy\x18\x08 \x01(\x0e\x32,.temporal.api.enums.v1.WorkflowIdReusePolicy\x12\x39\n\x0cretry_policy\x18\t \x01(\x0b\x32#.temporal.api.common.v1.RetryPolicy\x12\x15\n\rcron_schedule\x18\n \x01(\t\x12*\n\x04memo\x18\x0b \x01(\x0b\x32\x1c.temporal.api.common.v1.Memo\x12\x43\n\x11search_attributes\x18\x0c \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes\x12.\n\x06header\x18\r \x01(\x0b\x32\x1e.temporal.api.common.v1.Header\x12\x38\n\ruser_metadata\x18\x0e \x01(\x0b\x32!.temporal.api.sdk.v1.UserMetadata\x12I\n\x13versioning_override\x18\x0f \x01(\x0b\x32,.temporal.api.workflow.v1.VersioningOverride\x12\x32\n\x08priority\x18\x10 \x01(\x0b\x32 .temporal.api.common.v1.Priority"\x82\x06\n\x0c\x43\x61llbackInfo\x12\x32\n\x08\x63\x61llback\x18\x01 \x01(\x0b\x32 .temporal.api.common.v1.Callback\x12?\n\x07trigger\x18\x02 \x01(\x0b\x32..temporal.api.workflow.v1.CallbackInfo.Trigger\x12\x35\n\x11registration_time\x18\x03 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x33\n\x05state\x18\x04 \x01(\x0e\x32$.temporal.api.enums.v1.CallbackState\x12\x0f\n\x07\x61ttempt\x18\x05 \x01(\x05\x12>\n\x1alast_attempt_complete_time\x18\x06 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12>\n\x14last_attempt_failure\x18\x07 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12>\n\x1anext_attempt_schedule_time\x18\x08 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x16\n\x0e\x62locked_reason\x18\t \x01(\t\x1a\x10\n\x0eWorkflowClosed\x1a\x35\n UpdateWorkflowExecutionCompleted\x12\x11\n\tupdate_id\x18\x01 \x01(\t\x1a\xde\x01\n\x07Trigger\x12P\n\x0fworkflow_closed\x18\x01 \x01(\x0b\x32\x35.temporal.api.workflow.v1.CallbackInfo.WorkflowClosedH\x00\x12v\n#update_workflow_execution_completed\x18\x02 \x01(\x0b\x32G.temporal.api.workflow.v1.CallbackInfo.UpdateWorkflowExecutionCompletedH\x00\x42\t\n\x07variant"\x8b\x06\n\x19PendingNexusOperationInfo\x12\x10\n\x08\x65ndpoint\x18\x01 \x01(\t\x12\x0f\n\x07service\x18\x02 \x01(\t\x12\x11\n\toperation\x18\x03 \x01(\t\x12\x18\n\x0coperation_id\x18\x04 \x01(\tB\x02\x18\x01\x12<\n\x19schedule_to_close_timeout\x18\x05 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x32\n\x0escheduled_time\x18\x06 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12@\n\x05state\x18\x07 \x01(\x0e\x32\x31.temporal.api.enums.v1.PendingNexusOperationState\x12\x0f\n\x07\x61ttempt\x18\x08 \x01(\x05\x12>\n\x1alast_attempt_complete_time\x18\t \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12>\n\x14last_attempt_failure\x18\n \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12>\n\x1anext_attempt_schedule_time\x18\x0b \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12S\n\x11\x63\x61ncellation_info\x18\x0c \x01(\x0b\x32\x38.temporal.api.workflow.v1.NexusOperationCancellationInfo\x12\x1a\n\x12scheduled_event_id\x18\r \x01(\x03\x12\x16\n\x0e\x62locked_reason\x18\x0e \x01(\t\x12\x17\n\x0foperation_token\x18\x0f \x01(\t\x12<\n\x19schedule_to_start_timeout\x18\x10 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x39\n\x16start_to_close_timeout\x18\x11 \x01(\x0b\x32\x19.google.protobuf.Duration"\x84\x03\n\x1eNexusOperationCancellationInfo\x12\x32\n\x0erequested_time\x18\x01 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x45\n\x05state\x18\x02 \x01(\x0e\x32\x36.temporal.api.enums.v1.NexusOperationCancellationState\x12\x0f\n\x07\x61ttempt\x18\x03 \x01(\x05\x12>\n\x1alast_attempt_complete_time\x18\x04 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12>\n\x14last_attempt_failure\x18\x05 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12>\n\x1anext_attempt_schedule_time\x18\x06 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x16\n\x0e\x62locked_reason\x18\x07 \x01(\t"\xe3\x01\n\x18WorkflowExecutionOptions\x12I\n\x13versioning_override\x18\x01 \x01(\x0b\x32,.temporal.api.workflow.v1.VersioningOverride\x12\x32\n\x08priority\x18\x02 \x01(\x0b\x32 .temporal.api.common.v1.Priority\x12H\n\x14time_skipping_config\x18\x03 \x01(\x0b\x32*.temporal.api.common.v1.TimeSkippingConfig"\xfa\x05\n\x12VersioningOverride\x12M\n\x06pinned\x18\x03 \x01(\x0b\x32;.temporal.api.workflow.v1.VersioningOverride.PinnedOverrideH\x00\x12\x16\n\x0c\x61uto_upgrade\x18\x04 \x01(\x08H\x00\x12P\n\x08one_time\x18\x05 \x01(\x0b\x32<.temporal.api.workflow.v1.VersioningOverride.OneTimeOverrideH\x00\x12?\n\x08\x62\x65havior\x18\x01 \x01(\x0e\x32).temporal.api.enums.v1.VersioningBehaviorB\x02\x18\x01\x12>\n\ndeployment\x18\x02 \x01(\x0b\x32&.temporal.api.deployment.v1.DeploymentB\x02\x18\x01\x12\x1a\n\x0epinned_version\x18\t \x01(\tB\x02\x18\x01\x1a\xad\x01\n\x0ePinnedOverride\x12U\n\x08\x62\x65havior\x18\x01 \x01(\x0e\x32\x43.temporal.api.workflow.v1.VersioningOverride.PinnedOverrideBehavior\x12\x44\n\x07version\x18\x02 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersion\x1ai\n\x0fOneTimeOverride\x12V\n\x19target_deployment_version\x18\x01 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersion"g\n\x16PinnedOverrideBehavior\x12(\n$PINNED_OVERRIDE_BEHAVIOR_UNSPECIFIED\x10\x00\x12#\n\x1fPINNED_OVERRIDE_BEHAVIOR_PINNED\x10\x01\x42\n\n\x08override"i\n\x11OnConflictOptions\x12\x19\n\x11\x61ttach_request_id\x18\x01 \x01(\x08\x12#\n\x1b\x61ttach_completion_callbacks\x18\x02 \x01(\x08\x12\x14\n\x0c\x61ttach_links\x18\x03 \x01(\x08"i\n\rRequestIdInfo\x12\x34\n\nevent_type\x18\x01 \x01(\x0e\x32 .temporal.api.enums.v1.EventType\x12\x10\n\x08\x65vent_id\x18\x02 \x01(\x03\x12\x10\n\x08\x62uffered\x18\x03 \x01(\x08"\xb7\x04\n\x12PostResetOperation\x12V\n\x0fsignal_workflow\x18\x01 \x01(\x0b\x32;.temporal.api.workflow.v1.PostResetOperation.SignalWorkflowH\x00\x12\x65\n\x17update_workflow_options\x18\x02 \x01(\x0b\x32\x42.temporal.api.workflow.v1.PostResetOperation.UpdateWorkflowOptionsH\x00\x1a\xb3\x01\n\x0eSignalWorkflow\x12\x13\n\x0bsignal_name\x18\x01 \x01(\t\x12/\n\x05input\x18\x02 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12.\n\x06header\x18\x03 \x01(\x0b\x32\x1e.temporal.api.common.v1.Header\x12+\n\x05links\x18\x04 \x03(\x0b\x32\x1c.temporal.api.common.v1.Link\x1a\xa0\x01\n\x15UpdateWorkflowOptions\x12V\n\x1aworkflow_execution_options\x18\x01 \x01(\x0b\x32\x32.temporal.api.workflow.v1.WorkflowExecutionOptions\x12/\n\x0bupdate_mask\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.FieldMaskB\t\n\x07variant"o\n\x1aWorkflowExecutionPauseInfo\x12\x10\n\x08identity\x18\x01 \x01(\t\x12/\n\x0bpaused_time\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x0e\n\x06reason\x18\x03 \x01(\tB\x93\x01\n\x1bio.temporal.api.workflow.v1B\x0cMessageProtoP\x01Z\'go.temporal.io/api/workflow/v1;workflow\xaa\x02\x1aTemporalio.Api.Workflow.V1\xea\x02\x1dTemporalio::Api::Workflow::V1b\x06proto3' + b'\n&temporal/api/workflow/v1/message.proto\x12\x18temporal.api.workflow.v1\x1a\x1egoogle/protobuf/duration.proto\x1a\x1bgoogle/protobuf/empty.proto\x1a\x1fgoogle/protobuf/timestamp.proto\x1a google/protobuf/field_mask.proto\x1a&temporal/api/activity/v1/message.proto\x1a"temporal/api/enums/v1/common.proto\x1a&temporal/api/enums/v1/event_type.proto\x1a$temporal/api/enums/v1/workflow.proto\x1a$temporal/api/common/v1/message.proto\x1a(temporal/api/deployment/v1/message.proto\x1a%temporal/api/failure/v1/message.proto\x1a\'temporal/api/taskqueue/v1/message.proto\x1a\'temporal/api/sdk/v1/user_metadata.proto"\xf0\t\n\x15WorkflowExecutionInfo\x12<\n\texecution\x18\x01 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x32\n\x04type\x18\x02 \x01(\x0b\x32$.temporal.api.common.v1.WorkflowType\x12.\n\nstart_time\x18\x03 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12.\n\nclose_time\x18\x04 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12>\n\x06status\x18\x05 \x01(\x0e\x32..temporal.api.enums.v1.WorkflowExecutionStatus\x12\x16\n\x0ehistory_length\x18\x06 \x01(\x03\x12\x1b\n\x13parent_namespace_id\x18\x07 \x01(\t\x12\x43\n\x10parent_execution\x18\x08 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x32\n\x0e\x65xecution_time\x18\t \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12*\n\x04memo\x18\n \x01(\x0b\x32\x1c.temporal.api.common.v1.Memo\x12\x43\n\x11search_attributes\x18\x0b \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes\x12@\n\x11\x61uto_reset_points\x18\x0c \x01(\x0b\x32%.temporal.api.workflow.v1.ResetPoints\x12\x12\n\ntask_queue\x18\r \x01(\t\x12\x1e\n\x16state_transition_count\x18\x0e \x01(\x03\x12\x1a\n\x12history_size_bytes\x18\x0f \x01(\x03\x12X\n most_recent_worker_version_stamp\x18\x10 \x01(\x0b\x32*.temporal.api.common.v1.WorkerVersionStampB\x02\x18\x01\x12\x35\n\x12\x65xecution_duration\x18\x11 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x41\n\x0eroot_execution\x18\x12 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x1d\n\x11\x61ssigned_build_id\x18\x13 \x01(\tB\x02\x18\x01\x12\x1e\n\x12inherited_build_id\x18\x14 \x01(\tB\x02\x18\x01\x12\x14\n\x0c\x66irst_run_id\x18\x15 \x01(\t\x12R\n\x0fversioning_info\x18\x16 \x01(\x0b\x32\x39.temporal.api.workflow.v1.WorkflowExecutionVersioningInfo\x12\x1e\n\x16worker_deployment_name\x18\x17 \x01(\t\x12\x32\n\x08priority\x18\x18 \x01(\x0b\x32 .temporal.api.common.v1.Priority\x12#\n\x1b\x65xternal_payload_size_bytes\x18\x19 \x01(\x03\x12\x1e\n\x16\x65xternal_payload_count\x18\x1a \x01(\x03"\x8c\x05\n\x1dWorkflowExecutionExtendedInfo\x12=\n\x19\x65xecution_expiration_time\x18\x01 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x37\n\x13run_expiration_time\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x18\n\x10\x63\x61ncel_requested\x18\x03 \x01(\x08\x12\x33\n\x0flast_reset_time\x18\x04 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x37\n\x13original_start_time\x18\x05 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x14\n\x0creset_run_id\x18\x06 \x01(\t\x12\x65\n\x10request_id_infos\x18\x07 \x03(\x0b\x32K.temporal.api.workflow.v1.WorkflowExecutionExtendedInfo.RequestIdInfosEntry\x12H\n\npause_info\x18\x08 \x01(\x0b\x32\x34.temporal.api.workflow.v1.WorkflowExecutionPauseInfo\x12\x44\n\x12time_skipping_info\x18\t \x01(\x0b\x32(.temporal.api.common.v1.TimeSkippingInfo\x1a^\n\x13RequestIdInfosEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x36\n\x05value\x18\x02 \x01(\x0b\x32\'.temporal.api.workflow.v1.RequestIdInfo:\x02\x38\x01"\xfb\x04\n\x1fWorkflowExecutionVersioningInfo\x12;\n\x08\x62\x65havior\x18\x01 \x01(\x0e\x32).temporal.api.enums.v1.VersioningBehavior\x12>\n\ndeployment\x18\x02 \x01(\x0b\x32&.temporal.api.deployment.v1.DeploymentB\x02\x18\x01\x12\x13\n\x07version\x18\x05 \x01(\tB\x02\x18\x01\x12O\n\x12\x64\x65ployment_version\x18\x07 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersion\x12I\n\x13versioning_override\x18\x03 \x01(\x0b\x32,.temporal.api.workflow.v1.VersioningOverride\x12Q\n\x15\x64\x65ployment_transition\x18\x04 \x01(\x0b\x32..temporal.api.workflow.v1.DeploymentTransitionB\x02\x18\x01\x12Q\n\x12version_transition\x18\x06 \x01(\x0b\x32\x35.temporal.api.workflow.v1.DeploymentVersionTransition\x12\x17\n\x0frevision_number\x18\x08 \x01(\x03\x12k\n+continue_as_new_initial_versioning_behavior\x18\t \x01(\x0e\x32\x36.temporal.api.enums.v1.ContinueAsNewVersioningBehavior"R\n\x14\x44\x65ploymentTransition\x12:\n\ndeployment\x18\x01 \x01(\x0b\x32&.temporal.api.deployment.v1.Deployment"\x83\x01\n\x1b\x44\x65ploymentVersionTransition\x12\x13\n\x07version\x18\x01 \x01(\tB\x02\x18\x01\x12O\n\x12\x64\x65ployment_version\x18\x02 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersion"\xc7\x02\n\x17WorkflowExecutionConfig\x12\x38\n\ntask_queue\x18\x01 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12=\n\x1aworkflow_execution_timeout\x18\x02 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x37\n\x14workflow_run_timeout\x18\x03 \x01(\x0b\x32\x19.google.protobuf.Duration\x12@\n\x1d\x64\x65\x66\x61ult_workflow_task_timeout\x18\x04 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x38\n\ruser_metadata\x18\x05 \x01(\x0b\x32!.temporal.api.sdk.v1.UserMetadata"\xbd\r\n\x13PendingActivityInfo\x12\x13\n\x0b\x61\x63tivity_id\x18\x01 \x01(\t\x12;\n\ractivity_type\x18\x02 \x01(\x0b\x32$.temporal.api.common.v1.ActivityType\x12:\n\x05state\x18\x03 \x01(\x0e\x32+.temporal.api.enums.v1.PendingActivityState\x12;\n\x11heartbeat_details\x18\x04 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x37\n\x13last_heartbeat_time\x18\x05 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x35\n\x11last_started_time\x18\x06 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x0f\n\x07\x61ttempt\x18\x07 \x01(\x05\x12\x18\n\x10maximum_attempts\x18\x08 \x01(\x05\x12\x32\n\x0escheduled_time\x18\t \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x33\n\x0f\x65xpiration_time\x18\n \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x36\n\x0clast_failure\x18\x0b \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12\x1c\n\x14last_worker_identity\x18\x0c \x01(\t\x12;\n\x15use_workflow_build_id\x18\r \x01(\x0b\x32\x16.google.protobuf.EmptyB\x02\x18\x01H\x00\x12\x32\n$last_independently_assigned_build_id\x18\x0e \x01(\tB\x02\x18\x01H\x00\x12Q\n\x19last_worker_version_stamp\x18\x0f \x01(\x0b\x32*.temporal.api.common.v1.WorkerVersionStampB\x02\x18\x01\x12\x39\n\x16\x63urrent_retry_interval\x18\x10 \x01(\x0b\x32\x19.google.protobuf.Duration\x12>\n\x1alast_attempt_complete_time\x18\x11 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12>\n\x1anext_attempt_schedule_time\x18\x12 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x0e\n\x06paused\x18\x13 \x01(\x08\x12\x43\n\x0flast_deployment\x18\x14 \x01(\x0b\x32&.temporal.api.deployment.v1.DeploymentB\x02\x18\x01\x12*\n\x1elast_worker_deployment_version\x18\x15 \x01(\tB\x02\x18\x01\x12T\n\x17last_deployment_version\x18\x19 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersion\x12\x32\n\x08priority\x18\x16 \x01(\x0b\x32 .temporal.api.common.v1.Priority\x12K\n\npause_info\x18\x17 \x01(\x0b\x32\x37.temporal.api.workflow.v1.PendingActivityInfo.PauseInfo\x12\x43\n\x10\x61\x63tivity_options\x18\x18 \x01(\x0b\x32).temporal.api.activity.v1.ActivityOptions\x1a\xcf\x02\n\tPauseInfo\x12.\n\npause_time\x18\x01 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12P\n\x06manual\x18\x02 \x01(\x0b\x32>.temporal.api.workflow.v1.PendingActivityInfo.PauseInfo.ManualH\x00\x12L\n\x04rule\x18\x04 \x01(\x0b\x32<.temporal.api.workflow.v1.PendingActivityInfo.PauseInfo.RuleH\x00\x1a*\n\x06Manual\x12\x10\n\x08identity\x18\x01 \x01(\t\x12\x0e\n\x06reason\x18\x02 \x01(\t\x1a\x39\n\x04Rule\x12\x0f\n\x07rule_id\x18\x01 \x01(\t\x12\x10\n\x08identity\x18\x02 \x01(\t\x12\x0e\n\x06reason\x18\x03 \x01(\tB\x0b\n\tpaused_byB\x13\n\x11\x61ssigned_build_id"\xb9\x01\n\x19PendingChildExecutionInfo\x12\x13\n\x0bworkflow_id\x18\x01 \x01(\t\x12\x0e\n\x06run_id\x18\x02 \x01(\t\x12\x1a\n\x12workflow_type_name\x18\x03 \x01(\t\x12\x14\n\x0cinitiated_id\x18\x04 \x01(\x03\x12\x45\n\x13parent_close_policy\x18\x05 \x01(\x0e\x32(.temporal.api.enums.v1.ParentClosePolicy"\x8d\x02\n\x17PendingWorkflowTaskInfo\x12>\n\x05state\x18\x01 \x01(\x0e\x32/.temporal.api.enums.v1.PendingWorkflowTaskState\x12\x32\n\x0escheduled_time\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12;\n\x17original_scheduled_time\x18\x03 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x30\n\x0cstarted_time\x18\x04 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x0f\n\x07\x61ttempt\x18\x05 \x01(\x05"G\n\x0bResetPoints\x12\x38\n\x06points\x18\x01 \x03(\x0b\x32(.temporal.api.workflow.v1.ResetPointInfo"\xef\x01\n\x0eResetPointInfo\x12\x10\n\x08\x62uild_id\x18\x07 \x01(\t\x12\x1b\n\x0f\x62inary_checksum\x18\x01 \x01(\tB\x02\x18\x01\x12\x0e\n\x06run_id\x18\x02 \x01(\t\x12(\n first_workflow_task_completed_id\x18\x03 \x01(\x03\x12/\n\x0b\x63reate_time\x18\x04 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12/\n\x0b\x65xpire_time\x18\x05 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x12\n\nresettable\x18\x06 \x01(\x08"\x85\x07\n\x18NewWorkflowExecutionInfo\x12\x13\n\x0bworkflow_id\x18\x01 \x01(\t\x12;\n\rworkflow_type\x18\x02 \x01(\x0b\x32$.temporal.api.common.v1.WorkflowType\x12\x38\n\ntask_queue\x18\x03 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12/\n\x05input\x18\x04 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12=\n\x1aworkflow_execution_timeout\x18\x05 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x37\n\x14workflow_run_timeout\x18\x06 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x38\n\x15workflow_task_timeout\x18\x07 \x01(\x0b\x32\x19.google.protobuf.Duration\x12N\n\x18workflow_id_reuse_policy\x18\x08 \x01(\x0e\x32,.temporal.api.enums.v1.WorkflowIdReusePolicy\x12\x39\n\x0cretry_policy\x18\t \x01(\x0b\x32#.temporal.api.common.v1.RetryPolicy\x12\x15\n\rcron_schedule\x18\n \x01(\t\x12*\n\x04memo\x18\x0b \x01(\x0b\x32\x1c.temporal.api.common.v1.Memo\x12\x43\n\x11search_attributes\x18\x0c \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes\x12.\n\x06header\x18\r \x01(\x0b\x32\x1e.temporal.api.common.v1.Header\x12\x38\n\ruser_metadata\x18\x0e \x01(\x0b\x32!.temporal.api.sdk.v1.UserMetadata\x12I\n\x13versioning_override\x18\x0f \x01(\x0b\x32,.temporal.api.workflow.v1.VersioningOverride\x12\x32\n\x08priority\x18\x10 \x01(\x0b\x32 .temporal.api.common.v1.Priority"\x82\x06\n\x0c\x43\x61llbackInfo\x12\x32\n\x08\x63\x61llback\x18\x01 \x01(\x0b\x32 .temporal.api.common.v1.Callback\x12?\n\x07trigger\x18\x02 \x01(\x0b\x32..temporal.api.workflow.v1.CallbackInfo.Trigger\x12\x35\n\x11registration_time\x18\x03 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x33\n\x05state\x18\x04 \x01(\x0e\x32$.temporal.api.enums.v1.CallbackState\x12\x0f\n\x07\x61ttempt\x18\x05 \x01(\x05\x12>\n\x1alast_attempt_complete_time\x18\x06 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12>\n\x14last_attempt_failure\x18\x07 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12>\n\x1anext_attempt_schedule_time\x18\x08 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x16\n\x0e\x62locked_reason\x18\t \x01(\t\x1a\x10\n\x0eWorkflowClosed\x1a\x35\n UpdateWorkflowExecutionCompleted\x12\x11\n\tupdate_id\x18\x01 \x01(\t\x1a\xde\x01\n\x07Trigger\x12P\n\x0fworkflow_closed\x18\x01 \x01(\x0b\x32\x35.temporal.api.workflow.v1.CallbackInfo.WorkflowClosedH\x00\x12v\n#update_workflow_execution_completed\x18\x02 \x01(\x0b\x32G.temporal.api.workflow.v1.CallbackInfo.UpdateWorkflowExecutionCompletedH\x00\x42\t\n\x07variant"\x8b\x06\n\x19PendingNexusOperationInfo\x12\x10\n\x08\x65ndpoint\x18\x01 \x01(\t\x12\x0f\n\x07service\x18\x02 \x01(\t\x12\x11\n\toperation\x18\x03 \x01(\t\x12\x18\n\x0coperation_id\x18\x04 \x01(\tB\x02\x18\x01\x12<\n\x19schedule_to_close_timeout\x18\x05 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x32\n\x0escheduled_time\x18\x06 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12@\n\x05state\x18\x07 \x01(\x0e\x32\x31.temporal.api.enums.v1.PendingNexusOperationState\x12\x0f\n\x07\x61ttempt\x18\x08 \x01(\x05\x12>\n\x1alast_attempt_complete_time\x18\t \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12>\n\x14last_attempt_failure\x18\n \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12>\n\x1anext_attempt_schedule_time\x18\x0b \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12S\n\x11\x63\x61ncellation_info\x18\x0c \x01(\x0b\x32\x38.temporal.api.workflow.v1.NexusOperationCancellationInfo\x12\x1a\n\x12scheduled_event_id\x18\r \x01(\x03\x12\x16\n\x0e\x62locked_reason\x18\x0e \x01(\t\x12\x17\n\x0foperation_token\x18\x0f \x01(\t\x12<\n\x19schedule_to_start_timeout\x18\x10 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x39\n\x16start_to_close_timeout\x18\x11 \x01(\x0b\x32\x19.google.protobuf.Duration"\x84\x03\n\x1eNexusOperationCancellationInfo\x12\x32\n\x0erequested_time\x18\x01 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x45\n\x05state\x18\x02 \x01(\x0e\x32\x36.temporal.api.enums.v1.NexusOperationCancellationState\x12\x0f\n\x07\x61ttempt\x18\x03 \x01(\x05\x12>\n\x1alast_attempt_complete_time\x18\x04 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12>\n\x14last_attempt_failure\x18\x05 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12>\n\x1anext_attempt_schedule_time\x18\x06 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x16\n\x0e\x62locked_reason\x18\x07 \x01(\t"\xe3\x01\n\x18WorkflowExecutionOptions\x12I\n\x13versioning_override\x18\x01 \x01(\x0b\x32,.temporal.api.workflow.v1.VersioningOverride\x12\x32\n\x08priority\x18\x02 \x01(\x0b\x32 .temporal.api.common.v1.Priority\x12H\n\x14time_skipping_config\x18\x03 \x01(\x0b\x32*.temporal.api.common.v1.TimeSkippingConfig"\xfa\x05\n\x12VersioningOverride\x12M\n\x06pinned\x18\x03 \x01(\x0b\x32;.temporal.api.workflow.v1.VersioningOverride.PinnedOverrideH\x00\x12\x16\n\x0c\x61uto_upgrade\x18\x04 \x01(\x08H\x00\x12P\n\x08one_time\x18\x05 \x01(\x0b\x32<.temporal.api.workflow.v1.VersioningOverride.OneTimeOverrideH\x00\x12?\n\x08\x62\x65havior\x18\x01 \x01(\x0e\x32).temporal.api.enums.v1.VersioningBehaviorB\x02\x18\x01\x12>\n\ndeployment\x18\x02 \x01(\x0b\x32&.temporal.api.deployment.v1.DeploymentB\x02\x18\x01\x12\x1a\n\x0epinned_version\x18\t \x01(\tB\x02\x18\x01\x1a\xad\x01\n\x0ePinnedOverride\x12U\n\x08\x62\x65havior\x18\x01 \x01(\x0e\x32\x43.temporal.api.workflow.v1.VersioningOverride.PinnedOverrideBehavior\x12\x44\n\x07version\x18\x02 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersion\x1ai\n\x0fOneTimeOverride\x12V\n\x19target_deployment_version\x18\x01 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersion"g\n\x16PinnedOverrideBehavior\x12(\n$PINNED_OVERRIDE_BEHAVIOR_UNSPECIFIED\x10\x00\x12#\n\x1fPINNED_OVERRIDE_BEHAVIOR_PINNED\x10\x01\x42\n\n\x08override"i\n\x11OnConflictOptions\x12\x19\n\x11\x61ttach_request_id\x18\x01 \x01(\x08\x12#\n\x1b\x61ttach_completion_callbacks\x18\x02 \x01(\x08\x12\x14\n\x0c\x61ttach_links\x18\x03 \x01(\x08"i\n\rRequestIdInfo\x12\x34\n\nevent_type\x18\x01 \x01(\x0e\x32 .temporal.api.enums.v1.EventType\x12\x10\n\x08\x65vent_id\x18\x02 \x01(\x03\x12\x10\n\x08\x62uffered\x18\x03 \x01(\x08"\xb7\x04\n\x12PostResetOperation\x12V\n\x0fsignal_workflow\x18\x01 \x01(\x0b\x32;.temporal.api.workflow.v1.PostResetOperation.SignalWorkflowH\x00\x12\x65\n\x17update_workflow_options\x18\x02 \x01(\x0b\x32\x42.temporal.api.workflow.v1.PostResetOperation.UpdateWorkflowOptionsH\x00\x1a\xb3\x01\n\x0eSignalWorkflow\x12\x13\n\x0bsignal_name\x18\x01 \x01(\t\x12/\n\x05input\x18\x02 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12.\n\x06header\x18\x03 \x01(\x0b\x32\x1e.temporal.api.common.v1.Header\x12+\n\x05links\x18\x04 \x03(\x0b\x32\x1c.temporal.api.common.v1.Link\x1a\xa0\x01\n\x15UpdateWorkflowOptions\x12V\n\x1aworkflow_execution_options\x18\x01 \x01(\x0b\x32\x32.temporal.api.workflow.v1.WorkflowExecutionOptions\x12/\n\x0bupdate_mask\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.FieldMaskB\t\n\x07variant"o\n\x1aWorkflowExecutionPauseInfo\x12\x10\n\x08identity\x18\x01 \x01(\t\x12/\n\x0bpaused_time\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x0e\n\x06reason\x18\x03 \x01(\tB\x93\x01\n\x1bio.temporal.api.workflow.v1B\x0cMessageProtoP\x01Z\'go.temporal.io/api/workflow/v1;workflow\xaa\x02\x1aTemporalio.Api.Workflow.V1\xea\x02\x1dTemporalio::Api::Workflow::V1b\x06proto3' ) @@ -536,67 +536,67 @@ _WORKFLOWEXECUTIONINFO._serialized_start = 552 _WORKFLOWEXECUTIONINFO._serialized_end = 1816 _WORKFLOWEXECUTIONEXTENDEDINFO._serialized_start = 1819 - _WORKFLOWEXECUTIONEXTENDEDINFO._serialized_end = 2401 - _WORKFLOWEXECUTIONEXTENDEDINFO_REQUESTIDINFOSENTRY._serialized_start = 2307 - _WORKFLOWEXECUTIONEXTENDEDINFO_REQUESTIDINFOSENTRY._serialized_end = 2401 - _WORKFLOWEXECUTIONVERSIONINGINFO._serialized_start = 2404 - _WORKFLOWEXECUTIONVERSIONINGINFO._serialized_end = 3039 - _DEPLOYMENTTRANSITION._serialized_start = 3041 - _DEPLOYMENTTRANSITION._serialized_end = 3123 - _DEPLOYMENTVERSIONTRANSITION._serialized_start = 3126 - _DEPLOYMENTVERSIONTRANSITION._serialized_end = 3257 - _WORKFLOWEXECUTIONCONFIG._serialized_start = 3260 - _WORKFLOWEXECUTIONCONFIG._serialized_end = 3587 - _PENDINGACTIVITYINFO._serialized_start = 3590 - _PENDINGACTIVITYINFO._serialized_end = 5315 - _PENDINGACTIVITYINFO_PAUSEINFO._serialized_start = 4959 - _PENDINGACTIVITYINFO_PAUSEINFO._serialized_end = 5294 - _PENDINGACTIVITYINFO_PAUSEINFO_MANUAL._serialized_start = 5180 - _PENDINGACTIVITYINFO_PAUSEINFO_MANUAL._serialized_end = 5222 - _PENDINGACTIVITYINFO_PAUSEINFO_RULE._serialized_start = 5224 - _PENDINGACTIVITYINFO_PAUSEINFO_RULE._serialized_end = 5281 - _PENDINGCHILDEXECUTIONINFO._serialized_start = 5318 - _PENDINGCHILDEXECUTIONINFO._serialized_end = 5503 - _PENDINGWORKFLOWTASKINFO._serialized_start = 5506 - _PENDINGWORKFLOWTASKINFO._serialized_end = 5775 - _RESETPOINTS._serialized_start = 5777 - _RESETPOINTS._serialized_end = 5848 - _RESETPOINTINFO._serialized_start = 5851 - _RESETPOINTINFO._serialized_end = 6090 - _NEWWORKFLOWEXECUTIONINFO._serialized_start = 6093 - _NEWWORKFLOWEXECUTIONINFO._serialized_end = 6994 - _CALLBACKINFO._serialized_start = 6997 - _CALLBACKINFO._serialized_end = 7767 - _CALLBACKINFO_WORKFLOWCLOSED._serialized_start = 7471 - _CALLBACKINFO_WORKFLOWCLOSED._serialized_end = 7487 - _CALLBACKINFO_UPDATEWORKFLOWEXECUTIONCOMPLETED._serialized_start = 7489 - _CALLBACKINFO_UPDATEWORKFLOWEXECUTIONCOMPLETED._serialized_end = 7542 - _CALLBACKINFO_TRIGGER._serialized_start = 7545 - _CALLBACKINFO_TRIGGER._serialized_end = 7767 - _PENDINGNEXUSOPERATIONINFO._serialized_start = 7770 - _PENDINGNEXUSOPERATIONINFO._serialized_end = 8549 - _NEXUSOPERATIONCANCELLATIONINFO._serialized_start = 8552 - _NEXUSOPERATIONCANCELLATIONINFO._serialized_end = 8940 - _WORKFLOWEXECUTIONOPTIONS._serialized_start = 8943 - _WORKFLOWEXECUTIONOPTIONS._serialized_end = 9170 - _VERSIONINGOVERRIDE._serialized_start = 9173 - _VERSIONINGOVERRIDE._serialized_end = 9935 - _VERSIONINGOVERRIDE_PINNEDOVERRIDE._serialized_start = 9538 - _VERSIONINGOVERRIDE_PINNEDOVERRIDE._serialized_end = 9711 - _VERSIONINGOVERRIDE_ONETIMEOVERRIDE._serialized_start = 9713 - _VERSIONINGOVERRIDE_ONETIMEOVERRIDE._serialized_end = 9818 - _VERSIONINGOVERRIDE_PINNEDOVERRIDEBEHAVIOR._serialized_start = 9820 - _VERSIONINGOVERRIDE_PINNEDOVERRIDEBEHAVIOR._serialized_end = 9923 - _ONCONFLICTOPTIONS._serialized_start = 9937 - _ONCONFLICTOPTIONS._serialized_end = 10042 - _REQUESTIDINFO._serialized_start = 10044 - _REQUESTIDINFO._serialized_end = 10149 - _POSTRESETOPERATION._serialized_start = 10152 - _POSTRESETOPERATION._serialized_end = 10719 - _POSTRESETOPERATION_SIGNALWORKFLOW._serialized_start = 10366 - _POSTRESETOPERATION_SIGNALWORKFLOW._serialized_end = 10545 - _POSTRESETOPERATION_UPDATEWORKFLOWOPTIONS._serialized_start = 10548 - _POSTRESETOPERATION_UPDATEWORKFLOWOPTIONS._serialized_end = 10708 - _WORKFLOWEXECUTIONPAUSEINFO._serialized_start = 10721 - _WORKFLOWEXECUTIONPAUSEINFO._serialized_end = 10832 + _WORKFLOWEXECUTIONEXTENDEDINFO._serialized_end = 2471 + _WORKFLOWEXECUTIONEXTENDEDINFO_REQUESTIDINFOSENTRY._serialized_start = 2377 + _WORKFLOWEXECUTIONEXTENDEDINFO_REQUESTIDINFOSENTRY._serialized_end = 2471 + _WORKFLOWEXECUTIONVERSIONINGINFO._serialized_start = 2474 + _WORKFLOWEXECUTIONVERSIONINGINFO._serialized_end = 3109 + _DEPLOYMENTTRANSITION._serialized_start = 3111 + _DEPLOYMENTTRANSITION._serialized_end = 3193 + _DEPLOYMENTVERSIONTRANSITION._serialized_start = 3196 + _DEPLOYMENTVERSIONTRANSITION._serialized_end = 3327 + _WORKFLOWEXECUTIONCONFIG._serialized_start = 3330 + _WORKFLOWEXECUTIONCONFIG._serialized_end = 3657 + _PENDINGACTIVITYINFO._serialized_start = 3660 + _PENDINGACTIVITYINFO._serialized_end = 5385 + _PENDINGACTIVITYINFO_PAUSEINFO._serialized_start = 5029 + _PENDINGACTIVITYINFO_PAUSEINFO._serialized_end = 5364 + _PENDINGACTIVITYINFO_PAUSEINFO_MANUAL._serialized_start = 5250 + _PENDINGACTIVITYINFO_PAUSEINFO_MANUAL._serialized_end = 5292 + _PENDINGACTIVITYINFO_PAUSEINFO_RULE._serialized_start = 5294 + _PENDINGACTIVITYINFO_PAUSEINFO_RULE._serialized_end = 5351 + _PENDINGCHILDEXECUTIONINFO._serialized_start = 5388 + _PENDINGCHILDEXECUTIONINFO._serialized_end = 5573 + _PENDINGWORKFLOWTASKINFO._serialized_start = 5576 + _PENDINGWORKFLOWTASKINFO._serialized_end = 5845 + _RESETPOINTS._serialized_start = 5847 + _RESETPOINTS._serialized_end = 5918 + _RESETPOINTINFO._serialized_start = 5921 + _RESETPOINTINFO._serialized_end = 6160 + _NEWWORKFLOWEXECUTIONINFO._serialized_start = 6163 + _NEWWORKFLOWEXECUTIONINFO._serialized_end = 7064 + _CALLBACKINFO._serialized_start = 7067 + _CALLBACKINFO._serialized_end = 7837 + _CALLBACKINFO_WORKFLOWCLOSED._serialized_start = 7541 + _CALLBACKINFO_WORKFLOWCLOSED._serialized_end = 7557 + _CALLBACKINFO_UPDATEWORKFLOWEXECUTIONCOMPLETED._serialized_start = 7559 + _CALLBACKINFO_UPDATEWORKFLOWEXECUTIONCOMPLETED._serialized_end = 7612 + _CALLBACKINFO_TRIGGER._serialized_start = 7615 + _CALLBACKINFO_TRIGGER._serialized_end = 7837 + _PENDINGNEXUSOPERATIONINFO._serialized_start = 7840 + _PENDINGNEXUSOPERATIONINFO._serialized_end = 8619 + _NEXUSOPERATIONCANCELLATIONINFO._serialized_start = 8622 + _NEXUSOPERATIONCANCELLATIONINFO._serialized_end = 9010 + _WORKFLOWEXECUTIONOPTIONS._serialized_start = 9013 + _WORKFLOWEXECUTIONOPTIONS._serialized_end = 9240 + _VERSIONINGOVERRIDE._serialized_start = 9243 + _VERSIONINGOVERRIDE._serialized_end = 10005 + _VERSIONINGOVERRIDE_PINNEDOVERRIDE._serialized_start = 9608 + _VERSIONINGOVERRIDE_PINNEDOVERRIDE._serialized_end = 9781 + _VERSIONINGOVERRIDE_ONETIMEOVERRIDE._serialized_start = 9783 + _VERSIONINGOVERRIDE_ONETIMEOVERRIDE._serialized_end = 9888 + _VERSIONINGOVERRIDE_PINNEDOVERRIDEBEHAVIOR._serialized_start = 9890 + _VERSIONINGOVERRIDE_PINNEDOVERRIDEBEHAVIOR._serialized_end = 9993 + _ONCONFLICTOPTIONS._serialized_start = 10007 + _ONCONFLICTOPTIONS._serialized_end = 10112 + _REQUESTIDINFO._serialized_start = 10114 + _REQUESTIDINFO._serialized_end = 10219 + _POSTRESETOPERATION._serialized_start = 10222 + _POSTRESETOPERATION._serialized_end = 10789 + _POSTRESETOPERATION_SIGNALWORKFLOW._serialized_start = 10436 + _POSTRESETOPERATION_SIGNALWORKFLOW._serialized_end = 10615 + _POSTRESETOPERATION_UPDATEWORKFLOWOPTIONS._serialized_start = 10618 + _POSTRESETOPERATION_UPDATEWORKFLOWOPTIONS._serialized_end = 10778 + _WORKFLOWEXECUTIONPAUSEINFO._serialized_start = 10791 + _WORKFLOWEXECUTIONPAUSEINFO._serialized_end = 10902 # @@protoc_insertion_point(module_scope) diff --git a/temporalio/api/workflow/v1/message_pb2.pyi b/temporalio/api/workflow/v1/message_pb2.pyi index 2aa370a8e..b390d94f4 100644 --- a/temporalio/api/workflow/v1/message_pb2.pyi +++ b/temporalio/api/workflow/v1/message_pb2.pyi @@ -326,6 +326,7 @@ class WorkflowExecutionExtendedInfo(google.protobuf.message.Message): RESET_RUN_ID_FIELD_NUMBER: builtins.int REQUEST_ID_INFOS_FIELD_NUMBER: builtins.int PAUSE_INFO_FIELD_NUMBER: builtins.int + TIME_SKIPPING_INFO_FIELD_NUMBER: builtins.int @property def execution_expiration_time(self) -> google.protobuf.timestamp_pb2.Timestamp: """Workflow execution expiration time is defined as workflow start time plus expiration timeout. @@ -358,6 +359,13 @@ class WorkflowExecutionExtendedInfo(google.protobuf.message.Message): @property def pause_info(self) -> global___WorkflowExecutionPauseInfo: """Information about the workflow execution pause operation.""" + @property + def time_skipping_info( + self, + ) -> temporalio.api.common.v1.message_pb2.TimeSkippingInfo: + """Information about time skipping of the workflow execution. + If the execution has never enabled time skipping, it will be nil. + """ def __init__( self, *, @@ -370,6 +378,8 @@ class WorkflowExecutionExtendedInfo(google.protobuf.message.Message): request_id_infos: collections.abc.Mapping[builtins.str, global___RequestIdInfo] | None = ..., pause_info: global___WorkflowExecutionPauseInfo | None = ..., + time_skipping_info: temporalio.api.common.v1.message_pb2.TimeSkippingInfo + | None = ..., ) -> None: ... def HasField( self, @@ -384,6 +394,8 @@ class WorkflowExecutionExtendedInfo(google.protobuf.message.Message): b"pause_info", "run_expiration_time", b"run_expiration_time", + "time_skipping_info", + b"time_skipping_info", ], ) -> builtins.bool: ... def ClearField( @@ -405,6 +417,8 @@ class WorkflowExecutionExtendedInfo(google.protobuf.message.Message): b"reset_run_id", "run_expiration_time", b"run_expiration_time", + "time_skipping_info", + b"time_skipping_info", ], ) -> None: ... diff --git a/temporalio/api/workflowservice/v1/__init__.py b/temporalio/api/workflowservice/v1/__init__.py index 88d7af571..ab72e6b09 100644 --- a/temporalio/api/workflowservice/v1/__init__.py +++ b/temporalio/api/workflowservice/v1/__init__.py @@ -127,6 +127,8 @@ PollNexusOperationExecutionResponse, PollNexusTaskQueueRequest, PollNexusTaskQueueResponse, + PollWorkflowExecutionTimeSkippingRequest, + PollWorkflowExecutionTimeSkippingResponse, PollWorkflowExecutionUpdateRequest, PollWorkflowExecutionUpdateResponse, PollWorkflowTaskQueueRequest, @@ -374,6 +376,8 @@ "PollNexusOperationExecutionResponse", "PollNexusTaskQueueRequest", "PollNexusTaskQueueResponse", + "PollWorkflowExecutionTimeSkippingRequest", + "PollWorkflowExecutionTimeSkippingResponse", "PollWorkflowExecutionUpdateRequest", "PollWorkflowExecutionUpdateResponse", "PollWorkflowTaskQueueRequest", diff --git a/temporalio/api/workflowservice/v1/request_response_pb2.py b/temporalio/api/workflowservice/v1/request_response_pb2.py index 8f73b5c4c..2b788efdb 100644 --- a/temporalio/api/workflowservice/v1/request_response_pb2.py +++ b/temporalio/api/workflowservice/v1/request_response_pb2.py @@ -66,6 +66,9 @@ from temporalio.api.enums.v1 import ( task_queue_pb2 as temporal_dot_api_dot_enums_dot_v1_dot_task__queue__pb2, ) +from temporalio.api.enums.v1 import ( + time_skipping_pb2 as temporal_dot_api_dot_enums_dot_v1_dot_time__skipping__pb2, +) from temporalio.api.enums.v1 import ( update_pb2 as temporal_dot_api_dot_enums_dot_v1_dot_update__pb2, ) @@ -128,7 +131,7 @@ ) DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile( - b'\n6temporal/api/workflowservice/v1/request_response.proto\x12\x1ftemporal.api.workflowservice.v1\x1a+temporal/api/enums/v1/batch_operation.proto\x1a"temporal/api/enums/v1/common.proto\x1a$temporal/api/enums/v1/workflow.proto\x1a%temporal/api/enums/v1/namespace.proto\x1a(temporal/api/enums/v1/failed_cause.proto\x1a!temporal/api/enums/v1/query.proto\x1a!temporal/api/enums/v1/reset.proto\x1a&temporal/api/enums/v1/task_queue.proto\x1a&temporal/api/enums/v1/deployment.proto\x1a"temporal/api/enums/v1/update.proto\x1a$temporal/api/enums/v1/activity.proto\x1a!temporal/api/enums/v1/nexus.proto\x1a&temporal/api/activity/v1/message.proto\x1a$temporal/api/common/v1/message.proto\x1a%temporal/api/history/v1/message.proto\x1a&temporal/api/workflow/v1/message.proto\x1a%temporal/api/command/v1/message.proto\x1a$temporal/api/compute/v1/config.proto\x1a(temporal/api/deployment/v1/message.proto\x1a%temporal/api/failure/v1/message.proto\x1a$temporal/api/filter/v1/message.proto\x1a&temporal/api/protocol/v1/message.proto\x1a\'temporal/api/namespace/v1/message.proto\x1a#temporal/api/query/v1/message.proto\x1a)temporal/api/replication/v1/message.proto\x1a#temporal/api/rules/v1/message.proto\x1a\'temporal/api/sdk/v1/worker_config.proto\x1a&temporal/api/schedule/v1/message.proto\x1a\'temporal/api/taskqueue/v1/message.proto\x1a$temporal/api/update/v1/message.proto\x1a%temporal/api/version/v1/message.proto\x1a#temporal/api/batch/v1/message.proto\x1a\x30temporal/api/sdk/v1/task_complete_metadata.proto\x1a\'temporal/api/sdk/v1/user_metadata.proto\x1a#temporal/api/nexus/v1/message.proto\x1a$temporal/api/worker/v1/message.proto\x1a\x1egoogle/protobuf/duration.proto\x1a google/protobuf/field_mask.proto\x1a\x1fgoogle/protobuf/timestamp.proto"\x88\x05\n\x18RegisterNamespaceRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0b\x64\x65scription\x18\x02 \x01(\t\x12\x13\n\x0bowner_email\x18\x03 \x01(\t\x12\x46\n#workflow_execution_retention_period\x18\x04 \x01(\x0b\x32\x19.google.protobuf.Duration\x12G\n\x08\x63lusters\x18\x05 \x03(\x0b\x32\x35.temporal.api.replication.v1.ClusterReplicationConfig\x12\x1b\n\x13\x61\x63tive_cluster_name\x18\x06 \x01(\t\x12Q\n\x04\x64\x61ta\x18\x07 \x03(\x0b\x32\x43.temporal.api.workflowservice.v1.RegisterNamespaceRequest.DataEntry\x12\x16\n\x0esecurity_token\x18\x08 \x01(\t\x12\x1b\n\x13is_global_namespace\x18\t \x01(\x08\x12\x44\n\x16history_archival_state\x18\n \x01(\x0e\x32$.temporal.api.enums.v1.ArchivalState\x12\x1c\n\x14history_archival_uri\x18\x0b \x01(\t\x12G\n\x19visibility_archival_state\x18\x0c \x01(\x0e\x32$.temporal.api.enums.v1.ArchivalState\x12\x1f\n\x17visibility_archival_uri\x18\r \x01(\t\x1a+\n\tDataEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01"\x1b\n\x19RegisterNamespaceResponse"\x89\x01\n\x15ListNamespacesRequest\x12\x11\n\tpage_size\x18\x01 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c\x12\x44\n\x10namespace_filter\x18\x03 \x01(\x0b\x32*.temporal.api.namespace.v1.NamespaceFilter"\x81\x01\n\x16ListNamespacesResponse\x12N\n\nnamespaces\x18\x01 \x03(\x0b\x32:.temporal.api.workflowservice.v1.DescribeNamespaceResponse\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c"S\n\x18\x44\x65scribeNamespaceRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\n\n\x02id\x18\x02 \x01(\t\x12\x18\n\x10weak_consistency\x18\x03 \x01(\x08"\x81\x04\n\x19\x44\x65scribeNamespaceResponse\x12@\n\x0enamespace_info\x18\x01 \x01(\x0b\x32(.temporal.api.namespace.v1.NamespaceInfo\x12:\n\x06\x63onfig\x18\x02 \x01(\x0b\x32*.temporal.api.namespace.v1.NamespaceConfig\x12S\n\x12replication_config\x18\x03 \x01(\x0b\x32\x37.temporal.api.replication.v1.NamespaceReplicationConfig\x12\x18\n\x10\x66\x61ilover_version\x18\x04 \x01(\x03\x12\x1b\n\x13is_global_namespace\x18\x05 \x01(\x08\x12\x45\n\x10\x66\x61ilover_history\x18\x06 \x03(\x0b\x32+.temporal.api.replication.v1.FailoverStatus\x12J\n\x12poller_group_infos\x18\x07 \x03(\x0b\x32*.temporal.api.taskqueue.v1.PollerGroupInfoB\x02\x18\x01\x12G\n\x12poller_groups_info\x18\x08 \x01(\x0b\x32+.temporal.api.taskqueue.v1.PollerGroupsInfo"\xcf\x02\n\x16UpdateNamespaceRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x43\n\x0bupdate_info\x18\x02 \x01(\x0b\x32..temporal.api.namespace.v1.UpdateNamespaceInfo\x12:\n\x06\x63onfig\x18\x03 \x01(\x0b\x32*.temporal.api.namespace.v1.NamespaceConfig\x12S\n\x12replication_config\x18\x04 \x01(\x0b\x32\x37.temporal.api.replication.v1.NamespaceReplicationConfig\x12\x16\n\x0esecurity_token\x18\x05 \x01(\t\x12\x19\n\x11\x64\x65lete_bad_binary\x18\x06 \x01(\t\x12\x19\n\x11promote_namespace\x18\x07 \x01(\x08"\xa3\x02\n\x17UpdateNamespaceResponse\x12@\n\x0enamespace_info\x18\x01 \x01(\x0b\x32(.temporal.api.namespace.v1.NamespaceInfo\x12:\n\x06\x63onfig\x18\x02 \x01(\x0b\x32*.temporal.api.namespace.v1.NamespaceConfig\x12S\n\x12replication_config\x18\x03 \x01(\x0b\x32\x37.temporal.api.replication.v1.NamespaceReplicationConfig\x12\x18\n\x10\x66\x61ilover_version\x18\x04 \x01(\x03\x12\x1b\n\x13is_global_namespace\x18\x05 \x01(\x08"F\n\x19\x44\x65precateNamespaceRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x16\n\x0esecurity_token\x18\x02 \x01(\t"\x1c\n\x1a\x44\x65precateNamespaceResponse"\xd1\x0c\n\x1dStartWorkflowExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12;\n\rworkflow_type\x18\x03 \x01(\x0b\x32$.temporal.api.common.v1.WorkflowType\x12\x38\n\ntask_queue\x18\x04 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12/\n\x05input\x18\x05 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12=\n\x1aworkflow_execution_timeout\x18\x06 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x37\n\x14workflow_run_timeout\x18\x07 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x38\n\x15workflow_task_timeout\x18\x08 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x10\n\x08identity\x18\t \x01(\t\x12\x12\n\nrequest_id\x18\n \x01(\t\x12N\n\x18workflow_id_reuse_policy\x18\x0b \x01(\x0e\x32,.temporal.api.enums.v1.WorkflowIdReusePolicy\x12T\n\x1bworkflow_id_conflict_policy\x18\x16 \x01(\x0e\x32/.temporal.api.enums.v1.WorkflowIdConflictPolicy\x12\x39\n\x0cretry_policy\x18\x0c \x01(\x0b\x32#.temporal.api.common.v1.RetryPolicy\x12\x15\n\rcron_schedule\x18\r \x01(\t\x12*\n\x04memo\x18\x0e \x01(\x0b\x32\x1c.temporal.api.common.v1.Memo\x12\x43\n\x11search_attributes\x18\x0f \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes\x12.\n\x06header\x18\x10 \x01(\x0b\x32\x1e.temporal.api.common.v1.Header\x12\x1f\n\x17request_eager_execution\x18\x11 \x01(\x08\x12;\n\x11\x63ontinued_failure\x18\x12 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12@\n\x16last_completion_result\x18\x13 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x37\n\x14workflow_start_delay\x18\x14 \x01(\x0b\x32\x19.google.protobuf.Duration\x12>\n\x14\x63ompletion_callbacks\x18\x15 \x03(\x0b\x32 .temporal.api.common.v1.Callback\x12\x38\n\ruser_metadata\x18\x17 \x01(\x0b\x32!.temporal.api.sdk.v1.UserMetadata\x12+\n\x05links\x18\x18 \x03(\x0b\x32\x1c.temporal.api.common.v1.Link\x12I\n\x13versioning_override\x18\x19 \x01(\x0b\x32,.temporal.api.workflow.v1.VersioningOverride\x12H\n\x13on_conflict_options\x18\x1a \x01(\x0b\x32+.temporal.api.workflow.v1.OnConflictOptions\x12\x32\n\x08priority\x18\x1b \x01(\x0b\x32 .temporal.api.common.v1.Priority\x12\\\n\x1f\x65\x61ger_worker_deployment_options\x18\x1c \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentOptions\x12H\n\x14time_skipping_config\x18\x1d \x01(\x0b\x32*.temporal.api.common.v1.TimeSkippingConfig"\xaa\x02\n\x1eStartWorkflowExecutionResponse\x12\x0e\n\x06run_id\x18\x01 \x01(\t\x12\x1e\n\x16\x66irst_execution_run_id\x18\x06 \x01(\t\x12\x0f\n\x07started\x18\x03 \x01(\x08\x12>\n\x06status\x18\x05 \x01(\x0e\x32..temporal.api.enums.v1.WorkflowExecutionStatus\x12[\n\x13\x65\x61ger_workflow_task\x18\x02 \x01(\x0b\x32>.temporal.api.workflowservice.v1.PollWorkflowTaskQueueResponse\x12*\n\x04link\x18\x04 \x01(\x0b\x32\x1c.temporal.api.common.v1.Link"\xaa\x02\n"GetWorkflowExecutionHistoryRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12<\n\texecution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x19\n\x11maximum_page_size\x18\x03 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x04 \x01(\x0c\x12\x16\n\x0ewait_new_event\x18\x05 \x01(\x08\x12P\n\x19history_event_filter_type\x18\x06 \x01(\x0e\x32-.temporal.api.enums.v1.HistoryEventFilterType\x12\x15\n\rskip_archival\x18\x07 \x01(\x08"\xba\x01\n#GetWorkflowExecutionHistoryResponse\x12\x31\n\x07history\x18\x01 \x01(\x0b\x32 .temporal.api.history.v1.History\x12\x35\n\x0braw_history\x18\x02 \x03(\x0b\x32 .temporal.api.common.v1.DataBlob\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c\x12\x10\n\x08\x61rchived\x18\x04 \x01(\x08"\xb0\x01\n)GetWorkflowExecutionHistoryReverseRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12<\n\texecution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x19\n\x11maximum_page_size\x18\x03 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x04 \x01(\x0c"x\n*GetWorkflowExecutionHistoryReverseResponse\x12\x31\n\x07history\x18\x01 \x01(\x0b\x32 .temporal.api.history.v1.History\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c"\xb8\x03\n\x1cPollWorkflowTaskQueueRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x38\n\ntask_queue\x18\x02 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12\x17\n\x0fpoller_group_id\x18\n \x01(\t\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x1b\n\x13worker_instance_key\x18\x08 \x01(\t\x12!\n\x19worker_control_task_queue\x18\t \x01(\t\x12\x1b\n\x0f\x62inary_checksum\x18\x04 \x01(\tB\x02\x18\x01\x12Z\n\x1bworker_version_capabilities\x18\x05 \x01(\x0b\x32\x31.temporal.api.common.v1.WorkerVersionCapabilitiesB\x02\x18\x01\x12O\n\x12\x64\x65ployment_options\x18\x06 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentOptionsJ\x04\x08\x07\x10\x08R\x10worker_heartbeat"\xbf\x08\n\x1dPollWorkflowTaskQueueResponse\x12\x12\n\ntask_token\x18\x01 \x01(\x0c\x12\x45\n\x12workflow_execution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12;\n\rworkflow_type\x18\x03 \x01(\x0b\x32$.temporal.api.common.v1.WorkflowType\x12!\n\x19previous_started_event_id\x18\x04 \x01(\x03\x12\x18\n\x10started_event_id\x18\x05 \x01(\x03\x12\x0f\n\x07\x61ttempt\x18\x06 \x01(\x05\x12\x1a\n\x12\x62\x61\x63klog_count_hint\x18\x07 \x01(\x03\x12\x31\n\x07history\x18\x08 \x01(\x0b\x32 .temporal.api.history.v1.History\x12\x17\n\x0fnext_page_token\x18\t \x01(\x0c\x12\x33\n\x05query\x18\n \x01(\x0b\x32$.temporal.api.query.v1.WorkflowQuery\x12K\n\x1dworkflow_execution_task_queue\x18\x0b \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12\x32\n\x0escheduled_time\x18\x0c \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x30\n\x0cstarted_time\x18\r \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\\\n\x07queries\x18\x0e \x03(\x0b\x32K.temporal.api.workflowservice.v1.PollWorkflowTaskQueueResponse.QueriesEntry\x12\x33\n\x08messages\x18\x0f \x03(\x0b\x32!.temporal.api.protocol.v1.Message\x12Q\n\x17poller_scaling_decision\x18\x10 \x01(\x0b\x32\x30.temporal.api.taskqueue.v1.PollerScalingDecision\x12\x17\n\x0fpoller_group_id\x18\x11 \x01(\t\x12J\n\x12poller_group_infos\x18\x12 \x03(\x0b\x32*.temporal.api.taskqueue.v1.PollerGroupInfoB\x02\x18\x01\x12G\n\x12poller_groups_info\x18\x13 \x01(\x0b\x32+.temporal.api.taskqueue.v1.PollerGroupsInfo\x1aT\n\x0cQueriesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x33\n\x05value\x18\x02 \x01(\x0b\x32$.temporal.api.query.v1.WorkflowQuery:\x02\x38\x01"\xba\n\n#RespondWorkflowTaskCompletedRequest\x12\x12\n\ntask_token\x18\x01 \x01(\x0c\x12\x32\n\x08\x63ommands\x18\x02 \x03(\x0b\x32 .temporal.api.command.v1.Command\x12\x10\n\x08identity\x18\x03 \x01(\t\x12O\n\x11sticky_attributes\x18\x04 \x01(\x0b\x32\x34.temporal.api.taskqueue.v1.StickyExecutionAttributes\x12 \n\x18return_new_workflow_task\x18\x05 \x01(\x08\x12&\n\x1e\x66orce_create_new_workflow_task\x18\x06 \x01(\x08\x12\x1b\n\x0f\x62inary_checksum\x18\x07 \x01(\tB\x02\x18\x01\x12m\n\rquery_results\x18\x08 \x03(\x0b\x32V.temporal.api.workflowservice.v1.RespondWorkflowTaskCompletedRequest.QueryResultsEntry\x12\x11\n\tnamespace\x18\t \x01(\t\x12\x13\n\x0bresource_id\x18\x12 \x01(\t\x12L\n\x14worker_version_stamp\x18\n \x01(\x0b\x32*.temporal.api.common.v1.WorkerVersionStampB\x02\x18\x01\x12\x33\n\x08messages\x18\x0b \x03(\x0b\x32!.temporal.api.protocol.v1.Message\x12H\n\x0csdk_metadata\x18\x0c \x01(\x0b\x32\x32.temporal.api.sdk.v1.WorkflowTaskCompletedMetadata\x12\x43\n\x11metering_metadata\x18\r \x01(\x0b\x32(.temporal.api.common.v1.MeteringMetadata\x12g\n\x0c\x63\x61pabilities\x18\x0e \x01(\x0b\x32Q.temporal.api.workflowservice.v1.RespondWorkflowTaskCompletedRequest.Capabilities\x12>\n\ndeployment\x18\x0f \x01(\x0b\x32&.temporal.api.deployment.v1.DeploymentB\x02\x18\x01\x12\x46\n\x13versioning_behavior\x18\x10 \x01(\x0e\x32).temporal.api.enums.v1.VersioningBehavior\x12O\n\x12\x64\x65ployment_options\x18\x11 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentOptions\x12\x1b\n\x13worker_instance_key\x18\x13 \x01(\t\x12!\n\x19worker_control_task_queue\x18\x14 \x01(\t\x12\x13\n\x0bpage_number\x18\x15 \x01(\x05\x12\x19\n\x11intermediate_page\x18\x16 \x01(\x08\x1a_\n\x11QueryResultsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x39\n\x05value\x18\x02 \x01(\x0b\x32*.temporal.api.query.v1.WorkflowQueryResult:\x02\x38\x01\x1a\x45\n\x0c\x43\x61pabilities\x12\x35\n-discard_speculative_workflow_task_with_events\x18\x01 \x01(\x08"\xf5\x01\n$RespondWorkflowTaskCompletedResponse\x12U\n\rworkflow_task\x18\x01 \x01(\x0b\x32>.temporal.api.workflowservice.v1.PollWorkflowTaskQueueResponse\x12V\n\x0e\x61\x63tivity_tasks\x18\x02 \x03(\x0b\x32>.temporal.api.workflowservice.v1.PollActivityTaskQueueResponse\x12\x1e\n\x16reset_history_event_id\x18\x03 \x01(\x03"\x8d\x04\n RespondWorkflowTaskFailedRequest\x12\x12\n\ntask_token\x18\x01 \x01(\x0c\x12=\n\x05\x63\x61use\x18\x02 \x01(\x0e\x32..temporal.api.enums.v1.WorkflowTaskFailedCause\x12\x31\n\x07\x66\x61ilure\x18\x03 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12\x10\n\x08identity\x18\x04 \x01(\t\x12\x1b\n\x0f\x62inary_checksum\x18\x05 \x01(\tB\x02\x18\x01\x12\x11\n\tnamespace\x18\x06 \x01(\t\x12\x13\n\x0bresource_id\x18\x0b \x01(\t\x12\x33\n\x08messages\x18\x07 \x03(\x0b\x32!.temporal.api.protocol.v1.Message\x12\x46\n\x0eworker_version\x18\x08 \x01(\x0b\x32*.temporal.api.common.v1.WorkerVersionStampB\x02\x18\x01\x12>\n\ndeployment\x18\t \x01(\x0b\x32&.temporal.api.deployment.v1.DeploymentB\x02\x18\x01\x12O\n\x12\x64\x65ployment_options\x18\n \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentOptions"#\n!RespondWorkflowTaskFailedResponse"\xe6\x03\n\x1cPollActivityTaskQueueRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x38\n\ntask_queue\x18\x02 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12\x17\n\x0fpoller_group_id\x18\n \x01(\t\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x1b\n\x13worker_instance_key\x18\x08 \x01(\t\x12!\n\x19worker_control_task_queue\x18\t \x01(\t\x12I\n\x13task_queue_metadata\x18\x04 \x01(\x0b\x32,.temporal.api.taskqueue.v1.TaskQueueMetadata\x12Z\n\x1bworker_version_capabilities\x18\x05 \x01(\x0b\x32\x31.temporal.api.common.v1.WorkerVersionCapabilitiesB\x02\x18\x01\x12O\n\x12\x64\x65ployment_options\x18\x06 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentOptionsJ\x04\x08\x07\x10\x08R\x10worker_heartbeat"\x9d\t\n\x1dPollActivityTaskQueueResponse\x12\x12\n\ntask_token\x18\x01 \x01(\x0c\x12\x1a\n\x12workflow_namespace\x18\x02 \x01(\t\x12;\n\rworkflow_type\x18\x03 \x01(\x0b\x32$.temporal.api.common.v1.WorkflowType\x12\x45\n\x12workflow_execution\x18\x04 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12;\n\ractivity_type\x18\x05 \x01(\x0b\x32$.temporal.api.common.v1.ActivityType\x12\x13\n\x0b\x61\x63tivity_id\x18\x06 \x01(\t\x12.\n\x06header\x18\x07 \x01(\x0b\x32\x1e.temporal.api.common.v1.Header\x12/\n\x05input\x18\x08 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12;\n\x11heartbeat_details\x18\t \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x32\n\x0escheduled_time\x18\n \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x42\n\x1e\x63urrent_attempt_scheduled_time\x18\x0b \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x30\n\x0cstarted_time\x18\x0c \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x0f\n\x07\x61ttempt\x18\r \x01(\x05\x12<\n\x19schedule_to_close_timeout\x18\x0e \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x39\n\x16start_to_close_timeout\x18\x0f \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x34\n\x11heartbeat_timeout\x18\x10 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x39\n\x0cretry_policy\x18\x11 \x01(\x0b\x32#.temporal.api.common.v1.RetryPolicy\x12Q\n\x17poller_scaling_decision\x18\x12 \x01(\x0b\x32\x30.temporal.api.taskqueue.v1.PollerScalingDecision\x12\x32\n\x08priority\x18\x13 \x01(\x0b\x32 .temporal.api.common.v1.Priority\x12\x17\n\x0f\x61\x63tivity_run_id\x18\x14 \x01(\t\x12J\n\x12poller_group_infos\x18\x15 \x03(\x0b\x32*.temporal.api.taskqueue.v1.PollerGroupInfoB\x02\x18\x01\x12G\n\x12poller_groups_info\x18\x16 \x01(\x0b\x32+.temporal.api.taskqueue.v1.PollerGroupsInfo"\xa5\x01\n"RecordActivityTaskHeartbeatRequest\x12\x12\n\ntask_token\x18\x01 \x01(\x0c\x12\x31\n\x07\x64\x65tails\x18\x02 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x11\n\tnamespace\x18\x04 \x01(\t\x12\x13\n\x0bresource_id\x18\x05 \x01(\t"p\n#RecordActivityTaskHeartbeatResponse\x12\x18\n\x10\x63\x61ncel_requested\x18\x01 \x01(\x08\x12\x17\n\x0f\x61\x63tivity_paused\x18\x02 \x01(\x08\x12\x16\n\x0e\x61\x63tivity_reset\x18\x03 \x01(\x08"\xcf\x01\n&RecordActivityTaskHeartbeatByIdRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x12\x13\n\x0b\x61\x63tivity_id\x18\x04 \x01(\t\x12\x31\n\x07\x64\x65tails\x18\x05 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x10\n\x08identity\x18\x06 \x01(\t\x12\x13\n\x0bresource_id\x18\x07 \x01(\t"t\n\'RecordActivityTaskHeartbeatByIdResponse\x12\x18\n\x10\x63\x61ncel_requested\x18\x01 \x01(\x08\x12\x17\n\x0f\x61\x63tivity_paused\x18\x02 \x01(\x08\x12\x16\n\x0e\x61\x63tivity_reset\x18\x03 \x01(\x08"\xfe\x02\n#RespondActivityTaskCompletedRequest\x12\x12\n\ntask_token\x18\x01 \x01(\x0c\x12\x30\n\x06result\x18\x02 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x11\n\tnamespace\x18\x04 \x01(\t\x12\x13\n\x0bresource_id\x18\x08 \x01(\t\x12\x46\n\x0eworker_version\x18\x05 \x01(\x0b\x32*.temporal.api.common.v1.WorkerVersionStampB\x02\x18\x01\x12>\n\ndeployment\x18\x06 \x01(\x0b\x32&.temporal.api.deployment.v1.DeploymentB\x02\x18\x01\x12O\n\x12\x64\x65ployment_options\x18\x07 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentOptions"&\n$RespondActivityTaskCompletedResponse"\xcf\x01\n\'RespondActivityTaskCompletedByIdRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x12\x13\n\x0b\x61\x63tivity_id\x18\x04 \x01(\t\x12\x30\n\x06result\x18\x05 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x10\n\x08identity\x18\x06 \x01(\t\x12\x13\n\x0bresource_id\x18\x07 \x01(\t"*\n(RespondActivityTaskCompletedByIdResponse"\xbe\x03\n RespondActivityTaskFailedRequest\x12\x12\n\ntask_token\x18\x01 \x01(\x0c\x12\x31\n\x07\x66\x61ilure\x18\x02 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x11\n\tnamespace\x18\x04 \x01(\t\x12\x13\n\x0bresource_id\x18\t \x01(\t\x12@\n\x16last_heartbeat_details\x18\x05 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x46\n\x0eworker_version\x18\x06 \x01(\x0b\x32*.temporal.api.common.v1.WorkerVersionStampB\x02\x18\x01\x12>\n\ndeployment\x18\x07 \x01(\x0b\x32&.temporal.api.deployment.v1.DeploymentB\x02\x18\x01\x12O\n\x12\x64\x65ployment_options\x18\x08 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentOptions"W\n!RespondActivityTaskFailedResponse\x12\x32\n\x08\x66\x61ilures\x18\x01 \x03(\x0b\x32 .temporal.api.failure.v1.Failure"\x8f\x02\n$RespondActivityTaskFailedByIdRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x12\x13\n\x0b\x61\x63tivity_id\x18\x04 \x01(\t\x12\x31\n\x07\x66\x61ilure\x18\x05 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12\x10\n\x08identity\x18\x06 \x01(\t\x12@\n\x16last_heartbeat_details\x18\x07 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x13\n\x0bresource_id\x18\x08 \x01(\t"[\n%RespondActivityTaskFailedByIdResponse\x12\x32\n\x08\x66\x61ilures\x18\x01 \x03(\x0b\x32 .temporal.api.failure.v1.Failure"\xfe\x02\n"RespondActivityTaskCanceledRequest\x12\x12\n\ntask_token\x18\x01 \x01(\x0c\x12\x31\n\x07\x64\x65tails\x18\x02 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x11\n\tnamespace\x18\x04 \x01(\t\x12\x13\n\x0bresource_id\x18\x08 \x01(\t\x12\x46\n\x0eworker_version\x18\x05 \x01(\x0b\x32*.temporal.api.common.v1.WorkerVersionStampB\x02\x18\x01\x12>\n\ndeployment\x18\x06 \x01(\x0b\x32&.temporal.api.deployment.v1.DeploymentB\x02\x18\x01\x12O\n\x12\x64\x65ployment_options\x18\x07 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentOptions"%\n#RespondActivityTaskCanceledResponse"\xa0\x02\n&RespondActivityTaskCanceledByIdRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x12\x13\n\x0b\x61\x63tivity_id\x18\x04 \x01(\t\x12\x31\n\x07\x64\x65tails\x18\x05 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x10\n\x08identity\x18\x06 \x01(\t\x12O\n\x12\x64\x65ployment_options\x18\x07 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentOptions\x12\x13\n\x0bresource_id\x18\x08 \x01(\t")\n\'RespondActivityTaskCanceledByIdResponse"\x84\x02\n%RequestCancelWorkflowExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x45\n\x12workflow_execution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x12\n\nrequest_id\x18\x04 \x01(\t\x12\x1e\n\x16\x66irst_execution_run_id\x18\x05 \x01(\t\x12\x0e\n\x06reason\x18\x06 \x01(\t\x12+\n\x05links\x18\x07 \x03(\x0b\x32\x1c.temporal.api.common.v1.Link"(\n&RequestCancelWorkflowExecutionResponse"\xde\x02\n\x1eSignalWorkflowExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x45\n\x12workflow_execution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x13\n\x0bsignal_name\x18\x03 \x01(\t\x12/\n\x05input\x18\x04 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x10\n\x08identity\x18\x05 \x01(\t\x12\x12\n\nrequest_id\x18\x06 \x01(\t\x12\x13\n\x07\x63ontrol\x18\x07 \x01(\tB\x02\x18\x01\x12.\n\x06header\x18\x08 \x01(\x0b\x32\x1e.temporal.api.common.v1.Header\x12+\n\x05links\x18\n \x03(\x0b\x32\x1c.temporal.api.common.v1.LinkJ\x04\x08\t\x10\n"M\n\x1fSignalWorkflowExecutionResponse\x12*\n\x04link\x18\x01 \x01(\x0b\x32\x1c.temporal.api.common.v1.Link"\xbb\n\n\'SignalWithStartWorkflowExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12;\n\rworkflow_type\x18\x03 \x01(\x0b\x32$.temporal.api.common.v1.WorkflowType\x12\x38\n\ntask_queue\x18\x04 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12/\n\x05input\x18\x05 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12=\n\x1aworkflow_execution_timeout\x18\x06 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x37\n\x14workflow_run_timeout\x18\x07 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x38\n\x15workflow_task_timeout\x18\x08 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x10\n\x08identity\x18\t \x01(\t\x12\x12\n\nrequest_id\x18\n \x01(\t\x12N\n\x18workflow_id_reuse_policy\x18\x0b \x01(\x0e\x32,.temporal.api.enums.v1.WorkflowIdReusePolicy\x12T\n\x1bworkflow_id_conflict_policy\x18\x16 \x01(\x0e\x32/.temporal.api.enums.v1.WorkflowIdConflictPolicy\x12\x13\n\x0bsignal_name\x18\x0c \x01(\t\x12\x36\n\x0csignal_input\x18\r \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x13\n\x07\x63ontrol\x18\x0e \x01(\tB\x02\x18\x01\x12\x39\n\x0cretry_policy\x18\x0f \x01(\x0b\x32#.temporal.api.common.v1.RetryPolicy\x12\x15\n\rcron_schedule\x18\x10 \x01(\t\x12*\n\x04memo\x18\x11 \x01(\x0b\x32\x1c.temporal.api.common.v1.Memo\x12\x43\n\x11search_attributes\x18\x12 \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes\x12.\n\x06header\x18\x13 \x01(\x0b\x32\x1e.temporal.api.common.v1.Header\x12\x37\n\x14workflow_start_delay\x18\x14 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x38\n\ruser_metadata\x18\x17 \x01(\x0b\x32!.temporal.api.sdk.v1.UserMetadata\x12+\n\x05links\x18\x18 \x03(\x0b\x32\x1c.temporal.api.common.v1.Link\x12I\n\x13versioning_override\x18\x19 \x01(\x0b\x32,.temporal.api.workflow.v1.VersioningOverride\x12\x32\n\x08priority\x18\x1a \x01(\x0b\x32 .temporal.api.common.v1.Priority\x12H\n\x14time_skipping_config\x18\x1b \x01(\x0b\x32*.temporal.api.common.v1.TimeSkippingConfigJ\x04\x08\x15\x10\x16"\x9e\x01\n(SignalWithStartWorkflowExecutionResponse\x12\x0e\n\x06run_id\x18\x01 \x01(\t\x12\x1e\n\x16\x66irst_execution_run_id\x18\x04 \x01(\t\x12\x0f\n\x07started\x18\x02 \x01(\x08\x12\x31\n\x0bsignal_link\x18\x03 \x01(\x0b\x32\x1c.temporal.api.common.v1.Link"\xc1\x03\n\x1dResetWorkflowExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x45\n\x12workflow_execution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x0e\n\x06reason\x18\x03 \x01(\t\x12%\n\x1dworkflow_task_finish_event_id\x18\x04 \x01(\x03\x12\x12\n\nrequest_id\x18\x05 \x01(\t\x12G\n\x12reset_reapply_type\x18\x06 \x01(\x0e\x32\'.temporal.api.enums.v1.ResetReapplyTypeB\x02\x18\x01\x12S\n\x1breset_reapply_exclude_types\x18\x07 \x03(\x0e\x32..temporal.api.enums.v1.ResetReapplyExcludeType\x12K\n\x15post_reset_operations\x18\x08 \x03(\x0b\x32,.temporal.api.workflow.v1.PostResetOperation\x12\x10\n\x08identity\x18\t \x01(\t"0\n\x1eResetWorkflowExecutionResponse\x12\x0e\n\x06run_id\x18\x01 \x01(\t"\x9f\x02\n!TerminateWorkflowExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x45\n\x12workflow_execution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x0e\n\x06reason\x18\x03 \x01(\t\x12\x31\n\x07\x64\x65tails\x18\x04 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x10\n\x08identity\x18\x05 \x01(\t\x12\x1e\n\x16\x66irst_execution_run_id\x18\x06 \x01(\t\x12+\n\x05links\x18\x07 \x03(\x0b\x32\x1c.temporal.api.common.v1.Link"$\n"TerminateWorkflowExecutionResponse"z\n\x1e\x44\x65leteWorkflowExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x45\n\x12workflow_execution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution"!\n\x1f\x44\x65leteWorkflowExecutionResponse"\xc9\x02\n!ListOpenWorkflowExecutionsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x19\n\x11maximum_page_size\x18\x02 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c\x12\x42\n\x11start_time_filter\x18\x04 \x01(\x0b\x32\'.temporal.api.filter.v1.StartTimeFilter\x12K\n\x10\x65xecution_filter\x18\x05 \x01(\x0b\x32/.temporal.api.filter.v1.WorkflowExecutionFilterH\x00\x12\x41\n\x0btype_filter\x18\x06 \x01(\x0b\x32*.temporal.api.filter.v1.WorkflowTypeFilterH\x00\x42\t\n\x07\x66ilters"\x82\x01\n"ListOpenWorkflowExecutionsResponse\x12\x43\n\nexecutions\x18\x01 \x03(\x0b\x32/.temporal.api.workflow.v1.WorkflowExecutionInfo\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c"\x8a\x03\n#ListClosedWorkflowExecutionsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x19\n\x11maximum_page_size\x18\x02 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c\x12\x42\n\x11start_time_filter\x18\x04 \x01(\x0b\x32\'.temporal.api.filter.v1.StartTimeFilter\x12K\n\x10\x65xecution_filter\x18\x05 \x01(\x0b\x32/.temporal.api.filter.v1.WorkflowExecutionFilterH\x00\x12\x41\n\x0btype_filter\x18\x06 \x01(\x0b\x32*.temporal.api.filter.v1.WorkflowTypeFilterH\x00\x12=\n\rstatus_filter\x18\x07 \x01(\x0b\x32$.temporal.api.filter.v1.StatusFilterH\x00\x42\t\n\x07\x66ilters"\x84\x01\n$ListClosedWorkflowExecutionsResponse\x12\x43\n\nexecutions\x18\x01 \x03(\x0b\x32/.temporal.api.workflow.v1.WorkflowExecutionInfo\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c"m\n\x1dListWorkflowExecutionsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x11\n\tpage_size\x18\x02 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c\x12\r\n\x05query\x18\x04 \x01(\t"~\n\x1eListWorkflowExecutionsResponse\x12\x43\n\nexecutions\x18\x01 \x03(\x0b\x32/.temporal.api.workflow.v1.WorkflowExecutionInfo\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c"u\n%ListArchivedWorkflowExecutionsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x11\n\tpage_size\x18\x02 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c\x12\r\n\x05query\x18\x04 \x01(\t"\x86\x01\n&ListArchivedWorkflowExecutionsResponse\x12\x43\n\nexecutions\x18\x01 \x03(\x0b\x32/.temporal.api.workflow.v1.WorkflowExecutionInfo\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c"m\n\x1dScanWorkflowExecutionsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x11\n\tpage_size\x18\x02 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c\x12\r\n\x05query\x18\x04 \x01(\t"~\n\x1eScanWorkflowExecutionsResponse\x12\x43\n\nexecutions\x18\x01 \x03(\x0b\x32/.temporal.api.workflow.v1.WorkflowExecutionInfo\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c"B\n\x1e\x43ountWorkflowExecutionsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\r\n\x05query\x18\x02 \x01(\t"\xed\x01\n\x1f\x43ountWorkflowExecutionsResponse\x12\r\n\x05\x63ount\x18\x01 \x01(\x03\x12\x61\n\x06groups\x18\x02 \x03(\x0b\x32Q.temporal.api.workflowservice.v1.CountWorkflowExecutionsResponse.AggregationGroup\x1aX\n\x10\x41ggregationGroup\x12\x35\n\x0cgroup_values\x18\x01 \x03(\x0b\x32\x1f.temporal.api.common.v1.Payload\x12\r\n\x05\x63ount\x18\x02 \x01(\x03"\x1c\n\x1aGetSearchAttributesRequest"\xc9\x01\n\x1bGetSearchAttributesResponse\x12T\n\x04keys\x18\x01 \x03(\x0b\x32\x46.temporal.api.workflowservice.v1.GetSearchAttributesResponse.KeysEntry\x1aT\n\tKeysEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x36\n\x05value\x18\x02 \x01(\x0e\x32\'.temporal.api.enums.v1.IndexedValueType:\x02\x38\x01"\xe9\x02\n RespondQueryTaskCompletedRequest\x12\x12\n\ntask_token\x18\x01 \x01(\x0c\x12>\n\x0e\x63ompleted_type\x18\x02 \x01(\x0e\x32&.temporal.api.enums.v1.QueryResultType\x12\x36\n\x0cquery_result\x18\x03 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x15\n\rerror_message\x18\x04 \x01(\t\x12\x11\n\tnamespace\x18\x06 \x01(\t\x12\x31\n\x07\x66\x61ilure\x18\x07 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12=\n\x05\x63\x61use\x18\x08 \x01(\x0e\x32..temporal.api.enums.v1.WorkflowTaskFailedCause\x12\x17\n\x0fpoller_group_id\x18\t \x01(\tJ\x04\x08\x05\x10\x06"#\n!RespondQueryTaskCompletedResponse"n\n\x1bResetStickyTaskQueueRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12<\n\texecution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution"\x1e\n\x1cResetStickyTaskQueueResponse"\x9b\x02\n\x15ShutdownWorkerRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x19\n\x11sticky_task_queue\x18\x02 \x01(\t\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x0e\n\x06reason\x18\x04 \x01(\t\x12\x41\n\x10worker_heartbeat\x18\x05 \x01(\x0b\x32\'.temporal.api.worker.v1.WorkerHeartbeat\x12\x1b\n\x13worker_instance_key\x18\x06 \x01(\t\x12\x12\n\ntask_queue\x18\x07 \x01(\t\x12>\n\x10task_queue_types\x18\x08 \x03(\x0e\x32$.temporal.api.enums.v1.TaskQueueType"\x18\n\x16ShutdownWorkerResponse"\xe9\x01\n\x14QueryWorkflowRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12<\n\texecution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x33\n\x05query\x18\x03 \x01(\x0b\x32$.temporal.api.query.v1.WorkflowQuery\x12K\n\x16query_reject_condition\x18\x04 \x01(\x0e\x32+.temporal.api.enums.v1.QueryRejectCondition"\x8d\x01\n\x15QueryWorkflowResponse\x12\x36\n\x0cquery_result\x18\x01 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12<\n\x0equery_rejected\x18\x02 \x01(\x0b\x32$.temporal.api.query.v1.QueryRejected"s\n DescribeWorkflowExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12<\n\texecution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution"\x99\x05\n!DescribeWorkflowExecutionResponse\x12K\n\x10\x65xecution_config\x18\x01 \x01(\x0b\x32\x31.temporal.api.workflow.v1.WorkflowExecutionConfig\x12P\n\x17workflow_execution_info\x18\x02 \x01(\x0b\x32/.temporal.api.workflow.v1.WorkflowExecutionInfo\x12I\n\x12pending_activities\x18\x03 \x03(\x0b\x32-.temporal.api.workflow.v1.PendingActivityInfo\x12M\n\x10pending_children\x18\x04 \x03(\x0b\x32\x33.temporal.api.workflow.v1.PendingChildExecutionInfo\x12P\n\x15pending_workflow_task\x18\x05 \x01(\x0b\x32\x31.temporal.api.workflow.v1.PendingWorkflowTaskInfo\x12\x39\n\tcallbacks\x18\x06 \x03(\x0b\x32&.temporal.api.workflow.v1.CallbackInfo\x12U\n\x18pending_nexus_operations\x18\x07 \x03(\x0b\x32\x33.temporal.api.workflow.v1.PendingNexusOperationInfo\x12W\n\x16workflow_extended_info\x18\x08 \x01(\x0b\x32\x37.temporal.api.workflow.v1.WorkflowExecutionExtendedInfo"\x90\x04\n\x18\x44\x65scribeTaskQueueRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x38\n\ntask_queue\x18\x02 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12=\n\x0ftask_queue_type\x18\x03 \x01(\x0e\x32$.temporal.api.enums.v1.TaskQueueType\x12\x14\n\x0creport_stats\x18\x08 \x01(\x08\x12\x15\n\rreport_config\x18\x0b \x01(\x08\x12%\n\x19include_task_queue_status\x18\x04 \x01(\x08\x42\x02\x18\x01\x12\x42\n\x08\x61pi_mode\x18\x05 \x01(\x0e\x32,.temporal.api.enums.v1.DescribeTaskQueueModeB\x02\x18\x01\x12J\n\x08versions\x18\x06 \x01(\x0b\x32\x34.temporal.api.taskqueue.v1.TaskQueueVersionSelectionB\x02\x18\x01\x12\x42\n\x10task_queue_types\x18\x07 \x03(\x0e\x32$.temporal.api.enums.v1.TaskQueueTypeB\x02\x18\x01\x12\x1a\n\x0ereport_pollers\x18\t \x01(\x08\x42\x02\x18\x01\x12$\n\x18report_task_reachability\x18\n \x01(\x08\x42\x02\x18\x01"\xec\x07\n\x19\x44\x65scribeTaskQueueResponse\x12\x36\n\x07pollers\x18\x01 \x03(\x0b\x32%.temporal.api.taskqueue.v1.PollerInfo\x12\x38\n\x05stats\x18\x05 \x01(\x0b\x32).temporal.api.taskqueue.v1.TaskQueueStats\x12q\n\x15stats_by_priority_key\x18\x08 \x03(\x0b\x32R.temporal.api.workflowservice.v1.DescribeTaskQueueResponse.StatsByPriorityKeyEntry\x12K\n\x0fversioning_info\x18\x04 \x01(\x0b\x32\x32.temporal.api.taskqueue.v1.TaskQueueVersioningInfo\x12:\n\x06\x63onfig\x18\x06 \x01(\x0b\x32*.temporal.api.taskqueue.v1.TaskQueueConfig\x12k\n\x14\x65\x66\x66\x65\x63tive_rate_limit\x18\x07 \x01(\x0b\x32M.temporal.api.workflowservice.v1.DescribeTaskQueueResponse.EffectiveRateLimit\x12I\n\x11task_queue_status\x18\x02 \x01(\x0b\x32*.temporal.api.taskqueue.v1.TaskQueueStatusB\x02\x18\x01\x12g\n\rversions_info\x18\x03 \x03(\x0b\x32L.temporal.api.workflowservice.v1.DescribeTaskQueueResponse.VersionsInfoEntryB\x02\x18\x01\x1a\x64\n\x17StatsByPriorityKeyEntry\x12\x0b\n\x03key\x18\x01 \x01(\x05\x12\x38\n\x05value\x18\x02 \x01(\x0b\x32).temporal.api.taskqueue.v1.TaskQueueStats:\x02\x38\x01\x1at\n\x12\x45\x66\x66\x65\x63tiveRateLimit\x12\x1b\n\x13requests_per_second\x18\x01 \x01(\x02\x12\x41\n\x11rate_limit_source\x18\x02 \x01(\x0e\x32&.temporal.api.enums.v1.RateLimitSource\x1a\x64\n\x11VersionsInfoEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12>\n\x05value\x18\x02 \x01(\x0b\x32/.temporal.api.taskqueue.v1.TaskQueueVersionInfo:\x02\x38\x01"\x17\n\x15GetClusterInfoRequest"\xd1\x03\n\x16GetClusterInfoResponse\x12h\n\x11supported_clients\x18\x01 \x03(\x0b\x32M.temporal.api.workflowservice.v1.GetClusterInfoResponse.SupportedClientsEntry\x12\x16\n\x0eserver_version\x18\x02 \x01(\t\x12\x12\n\ncluster_id\x18\x03 \x01(\t\x12:\n\x0cversion_info\x18\x04 \x01(\x0b\x32$.temporal.api.version.v1.VersionInfo\x12\x14\n\x0c\x63luster_name\x18\x05 \x01(\t\x12\x1b\n\x13history_shard_count\x18\x06 \x01(\x05\x12\x19\n\x11persistence_store\x18\x07 \x01(\t\x12\x18\n\x10visibility_store\x18\x08 \x01(\t\x12 \n\x18initial_failover_version\x18\t \x01(\x03\x12"\n\x1a\x66\x61ilover_version_increment\x18\n \x01(\x03\x1a\x37\n\x15SupportedClientsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01"\x16\n\x14GetSystemInfoRequest"\xc1\x04\n\x15GetSystemInfoResponse\x12\x16\n\x0eserver_version\x18\x01 \x01(\t\x12Y\n\x0c\x63\x61pabilities\x18\x02 \x01(\x0b\x32\x43.temporal.api.workflowservice.v1.GetSystemInfoResponse.Capabilities\x1a\xb4\x03\n\x0c\x43\x61pabilities\x12\x1f\n\x17signal_and_query_header\x18\x01 \x01(\x08\x12&\n\x1einternal_error_differentiation\x18\x02 \x01(\x08\x12*\n"activity_failure_include_heartbeat\x18\x03 \x01(\x08\x12\x1a\n\x12supports_schedules\x18\x04 \x01(\x08\x12"\n\x1a\x65ncoded_failure_attributes\x18\x05 \x01(\x08\x12!\n\x19\x62uild_id_based_versioning\x18\x06 \x01(\x08\x12\x13\n\x0bupsert_memo\x18\x07 \x01(\x08\x12\x1c\n\x14\x65\x61ger_workflow_start\x18\x08 \x01(\x08\x12\x14\n\x0csdk_metadata\x18\t \x01(\x08\x12\'\n\x1f\x63ount_group_by_execution_status\x18\n \x01(\x08\x12\r\n\x05nexus\x18\x0b \x01(\x08\x12!\n\x19server_scaled_deployments\x18\x0c \x01(\x08\x12(\n server_scaled_provider_cloud_run\x18\r \x01(\x08"m\n\x1eListTaskQueuePartitionsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x38\n\ntask_queue\x18\x02 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue"\xdf\x01\n\x1fListTaskQueuePartitionsResponse\x12]\n\x1e\x61\x63tivity_task_queue_partitions\x18\x01 \x03(\x0b\x32\x35.temporal.api.taskqueue.v1.TaskQueuePartitionMetadata\x12]\n\x1eworkflow_task_queue_partitions\x18\x02 \x03(\x0b\x32\x35.temporal.api.taskqueue.v1.TaskQueuePartitionMetadata"\xcc\x02\n\x15\x43reateScheduleRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bschedule_id\x18\x02 \x01(\t\x12\x34\n\x08schedule\x18\x03 \x01(\x0b\x32".temporal.api.schedule.v1.Schedule\x12>\n\rinitial_patch\x18\x04 \x01(\x0b\x32\'.temporal.api.schedule.v1.SchedulePatch\x12\x10\n\x08identity\x18\x05 \x01(\t\x12\x12\n\nrequest_id\x18\x06 \x01(\t\x12*\n\x04memo\x18\x07 \x01(\x0b\x32\x1c.temporal.api.common.v1.Memo\x12\x43\n\x11search_attributes\x18\x08 \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes"0\n\x16\x43reateScheduleResponse\x12\x16\n\x0e\x63onflict_token\x18\x01 \x01(\x0c"A\n\x17\x44\x65scribeScheduleRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bschedule_id\x18\x02 \x01(\t"\x8f\x02\n\x18\x44\x65scribeScheduleResponse\x12\x34\n\x08schedule\x18\x01 \x01(\x0b\x32".temporal.api.schedule.v1.Schedule\x12\x34\n\x04info\x18\x02 \x01(\x0b\x32&.temporal.api.schedule.v1.ScheduleInfo\x12*\n\x04memo\x18\x03 \x01(\x0b\x32\x1c.temporal.api.common.v1.Memo\x12\x43\n\x11search_attributes\x18\x04 \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes\x12\x16\n\x0e\x63onflict_token\x18\x05 \x01(\x0c"\xa4\x02\n\x15UpdateScheduleRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bschedule_id\x18\x02 \x01(\t\x12\x34\n\x08schedule\x18\x03 \x01(\x0b\x32".temporal.api.schedule.v1.Schedule\x12\x16\n\x0e\x63onflict_token\x18\x04 \x01(\x0c\x12\x10\n\x08identity\x18\x05 \x01(\t\x12\x12\n\nrequest_id\x18\x06 \x01(\t\x12\x43\n\x11search_attributes\x18\x07 \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes\x12*\n\x04memo\x18\x08 \x01(\x0b\x32\x1c.temporal.api.common.v1.Memo"\x18\n\x16UpdateScheduleResponse"\x9c\x01\n\x14PatchScheduleRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bschedule_id\x18\x02 \x01(\t\x12\x36\n\x05patch\x18\x03 \x01(\x0b\x32\'.temporal.api.schedule.v1.SchedulePatch\x12\x10\n\x08identity\x18\x04 \x01(\t\x12\x12\n\nrequest_id\x18\x05 \x01(\t"\x17\n\x15PatchScheduleResponse"\xa8\x01\n ListScheduleMatchingTimesRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bschedule_id\x18\x02 \x01(\t\x12.\n\nstart_time\x18\x03 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12,\n\x08\x65nd_time\x18\x04 \x01(\x0b\x32\x1a.google.protobuf.Timestamp"S\n!ListScheduleMatchingTimesResponse\x12.\n\nstart_time\x18\x01 \x03(\x0b\x32\x1a.google.protobuf.Timestamp"Q\n\x15\x44\x65leteScheduleRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bschedule_id\x18\x02 \x01(\t\x12\x10\n\x08identity\x18\x03 \x01(\t"\x18\n\x16\x44\x65leteScheduleResponse"l\n\x14ListSchedulesRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x19\n\x11maximum_page_size\x18\x02 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c\x12\r\n\x05query\x18\x04 \x01(\t"p\n\x15ListSchedulesResponse\x12>\n\tschedules\x18\x01 \x03(\x0b\x32+.temporal.api.schedule.v1.ScheduleListEntry\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c"9\n\x15\x43ountSchedulesRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\r\n\x05query\x18\x02 \x01(\t"\xdb\x01\n\x16\x43ountSchedulesResponse\x12\r\n\x05\x63ount\x18\x01 \x01(\x03\x12X\n\x06groups\x18\x02 \x03(\x0b\x32H.temporal.api.workflowservice.v1.CountSchedulesResponse.AggregationGroup\x1aX\n\x10\x41ggregationGroup\x12\x35\n\x0cgroup_values\x18\x01 \x03(\x0b\x32\x1f.temporal.api.common.v1.Payload\x12\r\n\x05\x63ount\x18\x02 \x01(\x03"\x86\x05\n\'UpdateWorkerBuildIdCompatibilityRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x12\n\ntask_queue\x18\x02 \x01(\t\x12-\n#add_new_build_id_in_new_default_set\x18\x03 \x01(\tH\x00\x12\x87\x01\n\x1b\x61\x64\x64_new_compatible_build_id\x18\x04 \x01(\x0b\x32`.temporal.api.workflowservice.v1.UpdateWorkerBuildIdCompatibilityRequest.AddNewCompatibleVersionH\x00\x12!\n\x17promote_set_by_build_id\x18\x05 \x01(\tH\x00\x12%\n\x1bpromote_build_id_within_set\x18\x06 \x01(\tH\x00\x12h\n\nmerge_sets\x18\x07 \x01(\x0b\x32R.temporal.api.workflowservice.v1.UpdateWorkerBuildIdCompatibilityRequest.MergeSetsH\x00\x1ao\n\x17\x41\x64\x64NewCompatibleVersion\x12\x14\n\x0cnew_build_id\x18\x01 \x01(\t\x12$\n\x1c\x65xisting_compatible_build_id\x18\x02 \x01(\t\x12\x18\n\x10make_set_default\x18\x03 \x01(\x08\x1aI\n\tMergeSets\x12\x1c\n\x14primary_set_build_id\x18\x01 \x01(\t\x12\x1e\n\x16secondary_set_build_id\x18\x02 \x01(\tB\x0b\n\toperation"@\n(UpdateWorkerBuildIdCompatibilityResponseJ\x04\x08\x01\x10\x02R\x0eversion_set_id"_\n$GetWorkerBuildIdCompatibilityRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x12\n\ntask_queue\x18\x02 \x01(\t\x12\x10\n\x08max_sets\x18\x03 \x01(\x05"t\n%GetWorkerBuildIdCompatibilityResponse\x12K\n\x12major_version_sets\x18\x01 \x03(\x0b\x32/.temporal.api.taskqueue.v1.CompatibleVersionSet"\xb5\r\n"UpdateWorkerVersioningRulesRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x12\n\ntask_queue\x18\x02 \x01(\t\x12\x16\n\x0e\x63onflict_token\x18\x03 \x01(\x0c\x12\x81\x01\n\x16insert_assignment_rule\x18\x04 \x01(\x0b\x32_.temporal.api.workflowservice.v1.UpdateWorkerVersioningRulesRequest.InsertBuildIdAssignmentRuleH\x00\x12\x83\x01\n\x17replace_assignment_rule\x18\x05 \x01(\x0b\x32`.temporal.api.workflowservice.v1.UpdateWorkerVersioningRulesRequest.ReplaceBuildIdAssignmentRuleH\x00\x12\x81\x01\n\x16\x64\x65lete_assignment_rule\x18\x06 \x01(\x0b\x32_.temporal.api.workflowservice.v1.UpdateWorkerVersioningRulesRequest.DeleteBuildIdAssignmentRuleH\x00\x12\x8c\x01\n\x1c\x61\x64\x64_compatible_redirect_rule\x18\x07 \x01(\x0b\x32\x64.temporal.api.workflowservice.v1.UpdateWorkerVersioningRulesRequest.AddCompatibleBuildIdRedirectRuleH\x00\x12\x94\x01\n replace_compatible_redirect_rule\x18\x08 \x01(\x0b\x32h.temporal.api.workflowservice.v1.UpdateWorkerVersioningRulesRequest.ReplaceCompatibleBuildIdRedirectRuleH\x00\x12\x92\x01\n\x1f\x64\x65lete_compatible_redirect_rule\x18\t \x01(\x0b\x32g.temporal.api.workflowservice.v1.UpdateWorkerVersioningRulesRequest.DeleteCompatibleBuildIdRedirectRuleH\x00\x12l\n\x0f\x63ommit_build_id\x18\n \x01(\x0b\x32Q.temporal.api.workflowservice.v1.UpdateWorkerVersioningRulesRequest.CommitBuildIdH\x00\x1aq\n\x1bInsertBuildIdAssignmentRule\x12\x12\n\nrule_index\x18\x01 \x01(\x05\x12>\n\x04rule\x18\x02 \x01(\x0b\x32\x30.temporal.api.taskqueue.v1.BuildIdAssignmentRule\x1a\x81\x01\n\x1cReplaceBuildIdAssignmentRule\x12\x12\n\nrule_index\x18\x01 \x01(\x05\x12>\n\x04rule\x18\x02 \x01(\x0b\x32\x30.temporal.api.taskqueue.v1.BuildIdAssignmentRule\x12\r\n\x05\x66orce\x18\x03 \x01(\x08\x1a@\n\x1b\x44\x65leteBuildIdAssignmentRule\x12\x12\n\nrule_index\x18\x01 \x01(\x05\x12\r\n\x05\x66orce\x18\x02 \x01(\x08\x1aj\n AddCompatibleBuildIdRedirectRule\x12\x46\n\x04rule\x18\x01 \x01(\x0b\x32\x38.temporal.api.taskqueue.v1.CompatibleBuildIdRedirectRule\x1an\n$ReplaceCompatibleBuildIdRedirectRule\x12\x46\n\x04rule\x18\x01 \x01(\x0b\x32\x38.temporal.api.taskqueue.v1.CompatibleBuildIdRedirectRule\x1a>\n#DeleteCompatibleBuildIdRedirectRule\x12\x17\n\x0fsource_build_id\x18\x01 \x01(\t\x1a\x37\n\rCommitBuildId\x12\x17\n\x0ftarget_build_id\x18\x01 \x01(\t\x12\r\n\x05\x66orce\x18\x02 \x01(\x08\x42\x0b\n\toperation"\xfc\x01\n#UpdateWorkerVersioningRulesResponse\x12U\n\x10\x61ssignment_rules\x18\x01 \x03(\x0b\x32;.temporal.api.taskqueue.v1.TimestampedBuildIdAssignmentRule\x12\x66\n\x19\x63ompatible_redirect_rules\x18\x02 \x03(\x0b\x32\x43.temporal.api.taskqueue.v1.TimestampedCompatibleBuildIdRedirectRule\x12\x16\n\x0e\x63onflict_token\x18\x03 \x01(\x0c"H\n\x1fGetWorkerVersioningRulesRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x12\n\ntask_queue\x18\x02 \x01(\t"\xf9\x01\n GetWorkerVersioningRulesResponse\x12U\n\x10\x61ssignment_rules\x18\x01 \x03(\x0b\x32;.temporal.api.taskqueue.v1.TimestampedBuildIdAssignmentRule\x12\x66\n\x19\x63ompatible_redirect_rules\x18\x02 \x03(\x0b\x32\x43.temporal.api.taskqueue.v1.TimestampedCompatibleBuildIdRedirectRule\x12\x16\n\x0e\x63onflict_token\x18\x03 \x01(\x0c"\x9c\x01\n GetWorkerTaskReachabilityRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x11\n\tbuild_ids\x18\x02 \x03(\t\x12\x13\n\x0btask_queues\x18\x03 \x03(\t\x12=\n\x0creachability\x18\x04 \x01(\x0e\x32\'.temporal.api.enums.v1.TaskReachability"r\n!GetWorkerTaskReachabilityResponse\x12M\n\x15\x62uild_id_reachability\x18\x01 \x03(\x0b\x32..temporal.api.taskqueue.v1.BuildIdReachability"\x85\x02\n\x1eUpdateWorkflowExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x45\n\x12workflow_execution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x1e\n\x16\x66irst_execution_run_id\x18\x03 \x01(\t\x12\x37\n\x0bwait_policy\x18\x04 \x01(\x0b\x32".temporal.api.update.v1.WaitPolicy\x12\x30\n\x07request\x18\x05 \x01(\x0b\x32\x1f.temporal.api.update.v1.Request"\x83\x02\n\x1fUpdateWorkflowExecutionResponse\x12\x35\n\nupdate_ref\x18\x01 \x01(\x0b\x32!.temporal.api.update.v1.UpdateRef\x12\x30\n\x07outcome\x18\x02 \x01(\x0b\x32\x1f.temporal.api.update.v1.Outcome\x12K\n\x05stage\x18\x03 \x01(\x0e\x32<.temporal.api.enums.v1.UpdateWorkflowExecutionLifecycleStage\x12*\n\x04link\x18\x04 \x01(\x0b\x32\x1c.temporal.api.common.v1.Link"\xd6\n\n\x1aStartBatchOperationRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x18\n\x10visibility_query\x18\x02 \x01(\t\x12\x0e\n\x06job_id\x18\x03 \x01(\t\x12\x0e\n\x06reason\x18\x04 \x01(\t\x12\x41\n\nexecutions\x18\x05 \x03(\x0b\x32).temporal.api.common.v1.WorkflowExecutionB\x02\x18\x01\x12<\n\x11target_executions\x18\x16 \x03(\x0b\x32!.temporal.api.common.v1.Execution\x12!\n\x19max_operations_per_second\x18\x06 \x01(\x02\x12Q\n\x15termination_operation\x18\n \x01(\x0b\x32\x30.temporal.api.batch.v1.BatchOperationTerminationH\x00\x12G\n\x10signal_operation\x18\x0b \x01(\x0b\x32+.temporal.api.batch.v1.BatchOperationSignalH\x00\x12S\n\x16\x63\x61ncellation_operation\x18\x0c \x01(\x0b\x32\x31.temporal.api.batch.v1.BatchOperationCancellationH\x00\x12K\n\x12\x64\x65letion_operation\x18\r \x01(\x0b\x32-.temporal.api.batch.v1.BatchOperationDeletionH\x00\x12\x45\n\x0freset_operation\x18\x0e \x01(\x0b\x32*.temporal.api.batch.v1.BatchOperationResetH\x00\x12p\n!update_workflow_options_operation\x18\x0f \x01(\x0b\x32\x43.temporal.api.batch.v1.BatchOperationUpdateWorkflowExecutionOptionsH\x00\x12^\n\x1cunpause_activities_operation\x18\x10 \x01(\x0b\x32\x36.temporal.api.batch.v1.BatchOperationUnpauseActivitiesH\x00\x12Z\n\x1areset_activities_operation\x18\x11 \x01(\x0b\x32\x34.temporal.api.batch.v1.BatchOperationResetActivitiesH\x00\x12g\n!update_activity_options_operation\x18\x12 \x01(\x0b\x32:.temporal.api.batch.v1.BatchOperationUpdateActivityOptionsH\x00\x12\\\n\x1b\x63\x61ncel_activities_operation\x18\x13 \x01(\x0b\x32\x35.temporal.api.batch.v1.BatchOperationCancelActivitiesH\x00\x12\x62\n\x1eterminate_activities_operation\x18\x14 \x01(\x0b\x32\x38.temporal.api.batch.v1.BatchOperationTerminateActivitiesH\x00\x12\\\n\x1b\x64\x65lete_activities_operation\x18\x15 \x01(\x0b\x32\x35.temporal.api.batch.v1.BatchOperationDeleteActivitiesH\x00\x42\x0b\n\toperation"\x1d\n\x1bStartBatchOperationResponse"`\n\x19StopBatchOperationRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x0e\n\x06job_id\x18\x02 \x01(\t\x12\x0e\n\x06reason\x18\x03 \x01(\t\x12\x10\n\x08identity\x18\x04 \x01(\t"\x1c\n\x1aStopBatchOperationResponse"B\n\x1d\x44\x65scribeBatchOperationRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x0e\n\x06job_id\x18\x02 \x01(\t"\xd8\x03\n\x1e\x44\x65scribeBatchOperationResponse\x12\x41\n\x0eoperation_type\x18\x01 \x01(\x0e\x32).temporal.api.enums.v1.BatchOperationType\x12\x0e\n\x06job_id\x18\x02 \x01(\t\x12\x39\n\x05state\x18\x03 \x01(\x0e\x32*.temporal.api.enums.v1.BatchOperationState\x12.\n\nstart_time\x18\x04 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12.\n\nclose_time\x18\x05 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x1d\n\x15total_operation_count\x18\x06 \x01(\x03\x12 \n\x18\x63omplete_operation_count\x18\x07 \x01(\x03\x12\x1f\n\x17\x66\x61ilure_operation_count\x18\x08 \x01(\x03\x12\x10\n\x08identity\x18\t \x01(\t\x12\x0e\n\x06reason\x18\n \x01(\t\x12\r\n\x05query\x18\x0b \x01(\t\x12\x35\n\nexecutions\x18\x0c \x03(\x0b\x32!.temporal.api.common.v1.Execution"[\n\x1aListBatchOperationsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x11\n\tpage_size\x18\x02 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c"y\n\x1bListBatchOperationsResponse\x12\x41\n\x0eoperation_info\x18\x01 \x03(\x0b\x32).temporal.api.batch.v1.BatchOperationInfo\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c"\xb9\x01\n"PollWorkflowExecutionUpdateRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x35\n\nupdate_ref\x18\x02 \x01(\x0b\x32!.temporal.api.update.v1.UpdateRef\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x37\n\x0bwait_policy\x18\x04 \x01(\x0b\x32".temporal.api.update.v1.WaitPolicy"\xdb\x01\n#PollWorkflowExecutionUpdateResponse\x12\x30\n\x07outcome\x18\x01 \x01(\x0b\x32\x1f.temporal.api.update.v1.Outcome\x12K\n\x05stage\x18\x02 \x01(\x0e\x32<.temporal.api.enums.v1.UpdateWorkflowExecutionLifecycleStage\x12\x35\n\nupdate_ref\x18\x03 \x01(\x0b\x32!.temporal.api.update.v1.UpdateRef"\xa0\x03\n\x19PollNexusTaskQueueRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x38\n\ntask_queue\x18\x03 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12\x17\n\x0fpoller_group_id\x18\t \x01(\t\x12\x10\n\x08identity\x18\x02 \x01(\t\x12\x1b\n\x13worker_instance_key\x18\x08 \x01(\t\x12Z\n\x1bworker_version_capabilities\x18\x04 \x01(\x0b\x32\x31.temporal.api.common.v1.WorkerVersionCapabilitiesB\x02\x18\x01\x12O\n\x12\x64\x65ployment_options\x18\x06 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentOptions\x12\x41\n\x10worker_heartbeat\x18\x07 \x03(\x0b\x32\'.temporal.api.worker.v1.WorkerHeartbeat"\xe2\x02\n\x1aPollNexusTaskQueueResponse\x12\x12\n\ntask_token\x18\x01 \x01(\x0c\x12/\n\x07request\x18\x02 \x01(\x0b\x32\x1e.temporal.api.nexus.v1.Request\x12Q\n\x17poller_scaling_decision\x18\x03 \x01(\x0b\x32\x30.temporal.api.taskqueue.v1.PollerScalingDecision\x12\x17\n\x0fpoller_group_id\x18\x04 \x01(\t\x12J\n\x12poller_group_infos\x18\x05 \x03(\x0b\x32*.temporal.api.taskqueue.v1.PollerGroupInfoB\x02\x18\x01\x12G\n\x12poller_groups_info\x18\x06 \x01(\x0b\x32+.temporal.api.taskqueue.v1.PollerGroupsInfo"\xa7\x01\n RespondNexusTaskCompletedRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x10\n\x08identity\x18\x02 \x01(\t\x12\x12\n\ntask_token\x18\x03 \x01(\x0c\x12\x31\n\x08response\x18\x04 \x01(\x0b\x32\x1f.temporal.api.nexus.v1.Response\x12\x17\n\x0fpoller_group_id\x18\x05 \x01(\t"#\n!RespondNexusTaskCompletedResponse"\xdc\x01\n\x1dRespondNexusTaskFailedRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x10\n\x08identity\x18\x02 \x01(\t\x12\x12\n\ntask_token\x18\x03 \x01(\x0c\x12\x36\n\x05\x65rror\x18\x04 \x01(\x0b\x32#.temporal.api.nexus.v1.HandlerErrorB\x02\x18\x01\x12\x31\n\x07\x66\x61ilure\x18\x05 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12\x17\n\x0fpoller_group_id\x18\x06 \x01(\t" \n\x1eRespondNexusTaskFailedResponse"\xf4\x02\n\x1c\x45xecuteMultiOperationRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12[\n\noperations\x18\x02 \x03(\x0b\x32G.temporal.api.workflowservice.v1.ExecuteMultiOperationRequest.Operation\x12\x13\n\x0bresource_id\x18\x03 \x01(\t\x1a\xce\x01\n\tOperation\x12X\n\x0estart_workflow\x18\x01 \x01(\x0b\x32>.temporal.api.workflowservice.v1.StartWorkflowExecutionRequestH\x00\x12Z\n\x0fupdate_workflow\x18\x02 \x01(\x0b\x32?.temporal.api.workflowservice.v1.UpdateWorkflowExecutionRequestH\x00\x42\x0b\n\toperation"\xcc\x02\n\x1d\x45xecuteMultiOperationResponse\x12Z\n\tresponses\x18\x01 \x03(\x0b\x32G.temporal.api.workflowservice.v1.ExecuteMultiOperationResponse.Response\x1a\xce\x01\n\x08Response\x12Y\n\x0estart_workflow\x18\x01 \x01(\x0b\x32?.temporal.api.workflowservice.v1.StartWorkflowExecutionResponseH\x00\x12[\n\x0fupdate_workflow\x18\x02 \x01(\x0b\x32@.temporal.api.workflowservice.v1.UpdateWorkflowExecutionResponseH\x00\x42\n\n\x08response"\xd0\x02\n\x1cUpdateActivityOptionsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12<\n\texecution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x43\n\x10\x61\x63tivity_options\x18\x04 \x01(\x0b\x32).temporal.api.activity.v1.ActivityOptions\x12/\n\x0bupdate_mask\x18\x05 \x01(\x0b\x32\x1a.google.protobuf.FieldMask\x12\x0c\n\x02id\x18\x06 \x01(\tH\x00\x12\x0e\n\x04type\x18\x07 \x01(\tH\x00\x12\x13\n\tmatch_all\x18\t \x01(\x08H\x00\x12\x18\n\x10restore_original\x18\x08 \x01(\x08\x42\n\n\x08\x61\x63tivity"\xab\x02\n%UpdateActivityExecutionOptionsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12\x13\n\x0b\x61\x63tivity_id\x18\x03 \x01(\t\x12\x0e\n\x06run_id\x18\x04 \x01(\t\x12\x10\n\x08identity\x18\x05 \x01(\t\x12\x43\n\x10\x61\x63tivity_options\x18\x06 \x01(\x0b\x32).temporal.api.activity.v1.ActivityOptions\x12/\n\x0bupdate_mask\x18\x07 \x01(\x0b\x32\x1a.google.protobuf.FieldMask\x12\x18\n\x10restore_original\x18\x08 \x01(\x08\x12\x13\n\x0bresource_id\x18\t \x01(\t"d\n\x1dUpdateActivityOptionsResponse\x12\x43\n\x10\x61\x63tivity_options\x18\x01 \x01(\x0b\x32).temporal.api.activity.v1.ActivityOptions"m\n&UpdateActivityExecutionOptionsResponse\x12\x43\n\x10\x61\x63tivity_options\x18\x01 \x01(\x0b\x32).temporal.api.activity.v1.ActivityOptions"\xc7\x01\n\x14PauseActivityRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12<\n\texecution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x0c\n\x02id\x18\x04 \x01(\tH\x00\x12\x0e\n\x04type\x18\x05 \x01(\tH\x00\x12\x0e\n\x06reason\x18\x06 \x01(\t\x12\x12\n\nrequest_id\x18\x07 \x01(\tB\n\n\x08\x61\x63tivity"\xb7\x01\n\x1dPauseActivityExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12\x13\n\x0b\x61\x63tivity_id\x18\x03 \x01(\t\x12\x0e\n\x06run_id\x18\x04 \x01(\t\x12\x10\n\x08identity\x18\x05 \x01(\t\x12\x0e\n\x06reason\x18\x06 \x01(\t\x12\x13\n\x0bresource_id\x18\x07 \x01(\t\x12\x12\n\nrequest_id\x18\x08 \x01(\t"\x17\n\x15PauseActivityResponse" \n\x1ePauseActivityExecutionResponse"\x98\x02\n\x16UnpauseActivityRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12<\n\texecution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x0c\n\x02id\x18\x04 \x01(\tH\x00\x12\x0e\n\x04type\x18\x05 \x01(\tH\x00\x12\x15\n\x0bunpause_all\x18\x06 \x01(\x08H\x00\x12\x16\n\x0ereset_attempts\x18\x07 \x01(\x08\x12\x17\n\x0freset_heartbeat\x18\x08 \x01(\x08\x12)\n\x06jitter\x18\t \x01(\x0b\x32\x19.google.protobuf.DurationB\n\n\x08\x61\x63tivity"\x81\x02\n\x1fUnpauseActivityExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12\x13\n\x0b\x61\x63tivity_id\x18\x03 \x01(\t\x12\x0e\n\x06run_id\x18\x04 \x01(\t\x12\x10\n\x08identity\x18\x05 \x01(\t\x12\x16\n\x0ereset_attempts\x18\x06 \x01(\x08\x12\x17\n\x0freset_heartbeat\x18\x07 \x01(\x08\x12\x0e\n\x06reason\x18\x08 \x01(\t\x12)\n\x06jitter\x18\t \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x13\n\x0bresource_id\x18\n \x01(\t"\x19\n\x17UnpauseActivityResponse""\n UnpauseActivityExecutionResponse"\xb3\x02\n\x14ResetActivityRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12<\n\texecution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x0c\n\x02id\x18\x04 \x01(\tH\x00\x12\x0e\n\x04type\x18\x05 \x01(\tH\x00\x12\x13\n\tmatch_all\x18\n \x01(\x08H\x00\x12\x17\n\x0freset_heartbeat\x18\x06 \x01(\x08\x12\x13\n\x0bkeep_paused\x18\x07 \x01(\x08\x12)\n\x06jitter\x18\x08 \x01(\x0b\x32\x19.google.protobuf.Duration\x12 \n\x18restore_original_options\x18\t \x01(\x08\x42\n\n\x08\x61\x63tivity"\xf5\x01\n\x1dResetActivityExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12\x13\n\x0b\x61\x63tivity_id\x18\x03 \x01(\t\x12\x0e\n\x06run_id\x18\x04 \x01(\t\x12\x10\n\x08identity\x18\x05 \x01(\t\x12\x13\n\x0bkeep_paused\x18\x06 \x01(\x08\x12)\n\x06jitter\x18\x07 \x01(\x0b\x32\x19.google.protobuf.Duration\x12 \n\x18restore_original_options\x18\x08 \x01(\x08\x12\x13\n\x0bresource_id\x18\t \x01(\t"\x17\n\x15ResetActivityResponse" \n\x1eResetActivityExecutionResponse"\x9c\x02\n%UpdateWorkflowExecutionOptionsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x45\n\x12workflow_execution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12V\n\x1aworkflow_execution_options\x18\x03 \x01(\x0b\x32\x32.temporal.api.workflow.v1.WorkflowExecutionOptions\x12/\n\x0bupdate_mask\x18\x04 \x01(\x0b\x32\x1a.google.protobuf.FieldMask\x12\x10\n\x08identity\x18\x05 \x01(\t"\xb1\x01\n&UpdateWorkflowExecutionOptionsResponse\x12V\n\x1aworkflow_execution_options\x18\x01 \x01(\x0b\x32\x32.temporal.api.workflow.v1.WorkflowExecutionOptions\x12/\n\x0bupdate_time\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.Timestamp"j\n\x19\x44\x65scribeDeploymentRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12:\n\ndeployment\x18\x02 \x01(\x0b\x32&.temporal.api.deployment.v1.Deployment"a\n\x1a\x44\x65scribeDeploymentResponse\x12\x43\n\x0f\x64\x65ployment_info\x18\x01 \x01(\x0b\x32*.temporal.api.deployment.v1.DeploymentInfo"\xc2\x01\n&DescribeWorkerDeploymentVersionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x07version\x18\x02 \x01(\tB\x02\x18\x01\x12O\n\x12\x64\x65ployment_version\x18\x03 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersion\x12\x1f\n\x17report_task_queue_stats\x18\x04 \x01(\x08"\x8c\x05\n\'DescribeWorkerDeploymentVersionResponse\x12_\n\x1eworker_deployment_version_info\x18\x01 \x01(\x0b\x32\x37.temporal.api.deployment.v1.WorkerDeploymentVersionInfo\x12v\n\x13version_task_queues\x18\x02 \x03(\x0b\x32Y.temporal.api.workflowservice.v1.DescribeWorkerDeploymentVersionResponse.VersionTaskQueue\x1a\x87\x03\n\x10VersionTaskQueue\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x32\n\x04type\x18\x02 \x01(\x0e\x32$.temporal.api.enums.v1.TaskQueueType\x12\x38\n\x05stats\x18\x03 \x01(\x0b\x32).temporal.api.taskqueue.v1.TaskQueueStats\x12\x90\x01\n\x15stats_by_priority_key\x18\x04 \x03(\x0b\x32q.temporal.api.workflowservice.v1.DescribeWorkerDeploymentVersionResponse.VersionTaskQueue.StatsByPriorityKeyEntry\x1a\x64\n\x17StatsByPriorityKeyEntry\x12\x0b\n\x03key\x18\x01 \x01(\x05\x12\x38\n\x05value\x18\x02 \x01(\x0b\x32).temporal.api.taskqueue.v1.TaskQueueStats:\x02\x38\x01"M\n\x1f\x44\x65scribeWorkerDeploymentRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x17\n\x0f\x64\x65ployment_name\x18\x02 \x01(\t"\x8c\x01\n DescribeWorkerDeploymentResponse\x12\x16\n\x0e\x63onflict_token\x18\x01 \x01(\x0c\x12P\n\x16worker_deployment_info\x18\x02 \x01(\x0b\x32\x30.temporal.api.deployment.v1.WorkerDeploymentInfo"l\n\x16ListDeploymentsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x11\n\tpage_size\x18\x02 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c\x12\x13\n\x0bseries_name\x18\x04 \x01(\t"w\n\x17ListDeploymentsResponse\x12\x17\n\x0fnext_page_token\x18\x01 \x01(\x0c\x12\x43\n\x0b\x64\x65ployments\x18\x02 \x03(\x0b\x32..temporal.api.deployment.v1.DeploymentListInfo"\xcd\x01\n\x1bSetCurrentDeploymentRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12:\n\ndeployment\x18\x02 \x01(\x0b\x32&.temporal.api.deployment.v1.Deployment\x12\x10\n\x08identity\x18\x03 \x01(\t\x12M\n\x0fupdate_metadata\x18\x04 \x01(\x0b\x32\x34.temporal.api.deployment.v1.UpdateDeploymentMetadata"\xb9\x01\n\x1cSetCurrentDeploymentResponse\x12K\n\x17\x63urrent_deployment_info\x18\x01 \x01(\x0b\x32*.temporal.api.deployment.v1.DeploymentInfo\x12L\n\x18previous_deployment_info\x18\x02 \x01(\x0b\x32*.temporal.api.deployment.v1.DeploymentInfo"\xe5\x01\n(SetWorkerDeploymentCurrentVersionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x17\n\x0f\x64\x65ployment_name\x18\x02 \x01(\t\x12\x13\n\x07version\x18\x03 \x01(\tB\x02\x18\x01\x12\x10\n\x08\x62uild_id\x18\x07 \x01(\t\x12\x16\n\x0e\x63onflict_token\x18\x04 \x01(\x0c\x12\x10\n\x08identity\x18\x05 \x01(\t\x12"\n\x1aignore_missing_task_queues\x18\x06 \x01(\x08\x12\x18\n\x10\x61llow_no_pollers\x18\t \x01(\x08"\xbf\x01\n)SetWorkerDeploymentCurrentVersionResponse\x12\x16\n\x0e\x63onflict_token\x18\x01 \x01(\x0c\x12\x1c\n\x10previous_version\x18\x02 \x01(\tB\x02\x18\x01\x12\\\n\x1bprevious_deployment_version\x18\x03 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersionB\x02\x18\x01"\xf9\x01\n(SetWorkerDeploymentRampingVersionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x17\n\x0f\x64\x65ployment_name\x18\x02 \x01(\t\x12\x13\n\x07version\x18\x03 \x01(\tB\x02\x18\x01\x12\x10\n\x08\x62uild_id\x18\x08 \x01(\t\x12\x12\n\npercentage\x18\x04 \x01(\x02\x12\x16\n\x0e\x63onflict_token\x18\x05 \x01(\x0c\x12\x10\n\x08identity\x18\x06 \x01(\t\x12"\n\x1aignore_missing_task_queues\x18\x07 \x01(\x08\x12\x18\n\x10\x61llow_no_pollers\x18\n \x01(\x08"\xe0\x01\n)SetWorkerDeploymentRampingVersionResponse\x12\x16\n\x0e\x63onflict_token\x18\x01 \x01(\x0c\x12\x1c\n\x10previous_version\x18\x02 \x01(\tB\x02\x18\x01\x12\\\n\x1bprevious_deployment_version\x18\x04 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersionB\x02\x18\x01\x12\x1f\n\x13previous_percentage\x18\x03 \x01(\x02\x42\x02\x18\x01"q\n\x1d\x43reateWorkerDeploymentRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x17\n\x0f\x64\x65ployment_name\x18\x02 \x01(\t\x12\x10\n\x08identity\x18\x04 \x01(\t\x12\x12\n\nrequest_id\x18\x05 \x01(\t"8\n\x1e\x43reateWorkerDeploymentResponse\x12\x16\n\x0e\x63onflict_token\x18\x01 \x01(\x0c"]\n\x1cListWorkerDeploymentsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x11\n\tpage_size\x18\x02 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c"\x9f\x05\n\x1dListWorkerDeploymentsResponse\x12\x17\n\x0fnext_page_token\x18\x01 \x01(\x0c\x12r\n\x12worker_deployments\x18\x02 \x03(\x0b\x32V.temporal.api.workflowservice.v1.ListWorkerDeploymentsResponse.WorkerDeploymentSummary\x1a\xf0\x03\n\x17WorkerDeploymentSummary\x12\x0c\n\x04name\x18\x01 \x01(\t\x12/\n\x0b\x63reate_time\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x41\n\x0erouting_config\x18\x03 \x01(\x0b\x32).temporal.api.deployment.v1.RoutingConfig\x12o\n\x16latest_version_summary\x18\x04 \x01(\x0b\x32O.temporal.api.deployment.v1.WorkerDeploymentInfo.WorkerDeploymentVersionSummary\x12p\n\x17\x63urrent_version_summary\x18\x05 \x01(\x0b\x32O.temporal.api.deployment.v1.WorkerDeploymentInfo.WorkerDeploymentVersionSummary\x12p\n\x17ramping_version_summary\x18\x06 \x01(\x0b\x32O.temporal.api.deployment.v1.WorkerDeploymentInfo.WorkerDeploymentVersionSummary"\xf0\x01\n$CreateWorkerDeploymentVersionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12O\n\x12\x64\x65ployment_version\x18\x02 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersion\x12>\n\x0e\x63ompute_config\x18\x04 \x01(\x0b\x32&.temporal.api.compute.v1.ComputeConfig\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x12\n\nrequest_id\x18\x05 \x01(\t"\'\n%CreateWorkerDeploymentVersionResponse"\xc8\x01\n$DeleteWorkerDeploymentVersionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x07version\x18\x02 \x01(\tB\x02\x18\x01\x12O\n\x12\x64\x65ployment_version\x18\x05 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersion\x12\x15\n\rskip_drainage\x18\x03 \x01(\x08\x12\x10\n\x08identity\x18\x04 \x01(\t"\'\n%DeleteWorkerDeploymentVersionResponse"]\n\x1d\x44\x65leteWorkerDeploymentRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x17\n\x0f\x64\x65ployment_name\x18\x02 \x01(\t\x12\x10\n\x08identity\x18\x03 \x01(\t" \n\x1e\x44\x65leteWorkerDeploymentResponse"\x84\x04\n1UpdateWorkerDeploymentVersionComputeConfigRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12O\n\x12\x64\x65ployment_version\x18\x02 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersion\x12\x99\x01\n\x1d\x63ompute_config_scaling_groups\x18\x06 \x03(\x0b\x32r.temporal.api.workflowservice.v1.UpdateWorkerDeploymentVersionComputeConfigRequest.ComputeConfigScalingGroupsEntry\x12,\n$remove_compute_config_scaling_groups\x18\x07 \x03(\t\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x12\n\nrequest_id\x18\x04 \x01(\t\x1a{\n\x1f\x43omputeConfigScalingGroupsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12G\n\x05value\x18\x02 \x01(\x0b\x32\x38.temporal.api.compute.v1.ComputeConfigScalingGroupUpdate:\x02\x38\x01"4\n2UpdateWorkerDeploymentVersionComputeConfigResponse"\xf4\x03\n3ValidateWorkerDeploymentVersionComputeConfigRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12O\n\x12\x64\x65ployment_version\x18\x02 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersion\x12\x9b\x01\n\x1d\x63ompute_config_scaling_groups\x18\x06 \x03(\x0b\x32t.temporal.api.workflowservice.v1.ValidateWorkerDeploymentVersionComputeConfigRequest.ComputeConfigScalingGroupsEntry\x12,\n$remove_compute_config_scaling_groups\x18\x07 \x03(\t\x12\x10\n\x08identity\x18\x03 \x01(\t\x1a{\n\x1f\x43omputeConfigScalingGroupsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12G\n\x05value\x18\x02 \x01(\x0b\x32\x38.temporal.api.compute.v1.ComputeConfigScalingGroupUpdate:\x02\x38\x01"6\n4ValidateWorkerDeploymentVersionComputeConfigResponse"\xa2\x03\n,UpdateWorkerDeploymentVersionMetadataRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x07version\x18\x02 \x01(\tB\x02\x18\x01\x12O\n\x12\x64\x65ployment_version\x18\x05 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersion\x12x\n\x0eupsert_entries\x18\x03 \x03(\x0b\x32`.temporal.api.workflowservice.v1.UpdateWorkerDeploymentVersionMetadataRequest.UpsertEntriesEntry\x12\x16\n\x0eremove_entries\x18\x04 \x03(\t\x12\x10\n\x08identity\x18\x06 \x01(\t\x1aU\n\x12UpsertEntriesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12.\n\x05value\x18\x02 \x01(\x0b\x32\x1f.temporal.api.common.v1.Payload:\x02\x38\x01"n\n-UpdateWorkerDeploymentVersionMetadataResponse\x12=\n\x08metadata\x18\x01 \x01(\x0b\x32+.temporal.api.deployment.v1.VersionMetadata"\xbd\x01\n!SetWorkerDeploymentManagerRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x17\n\x0f\x64\x65ployment_name\x18\x02 \x01(\t\x12\x1a\n\x10manager_identity\x18\x03 \x01(\tH\x00\x12\x0e\n\x04self\x18\x04 \x01(\x08H\x00\x12\x16\n\x0e\x63onflict_token\x18\x05 \x01(\x0c\x12\x10\n\x08identity\x18\x06 \x01(\tB\x16\n\x14new_manager_identity"c\n"SetWorkerDeploymentManagerResponse\x12\x16\n\x0e\x63onflict_token\x18\x01 \x01(\x0c\x12%\n\x19previous_manager_identity\x18\x02 \x01(\tB\x02\x18\x01"E\n\x1bGetCurrentDeploymentRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bseries_name\x18\x02 \x01(\t"k\n\x1cGetCurrentDeploymentResponse\x12K\n\x17\x63urrent_deployment_info\x18\x01 \x01(\x0b\x32*.temporal.api.deployment.v1.DeploymentInfo"q\n GetDeploymentReachabilityRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12:\n\ndeployment\x18\x02 \x01(\x0b\x32&.temporal.api.deployment.v1.Deployment"\xe3\x01\n!GetDeploymentReachabilityResponse\x12\x43\n\x0f\x64\x65ployment_info\x18\x01 \x01(\x0b\x32*.temporal.api.deployment.v1.DeploymentInfo\x12\x43\n\x0creachability\x18\x02 \x01(\x0e\x32-.temporal.api.enums.v1.DeploymentReachability\x12\x34\n\x10last_update_time\x18\x03 \x01(\x0b\x32\x1a.google.protobuf.Timestamp"\xb4\x01\n\x19\x43reateWorkflowRuleRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x35\n\x04spec\x18\x02 \x01(\x0b\x32\'.temporal.api.rules.v1.WorkflowRuleSpec\x12\x12\n\nforce_scan\x18\x03 \x01(\x08\x12\x12\n\nrequest_id\x18\x04 \x01(\t\x12\x10\n\x08identity\x18\x05 \x01(\t\x12\x13\n\x0b\x64\x65scription\x18\x06 \x01(\t"_\n\x1a\x43reateWorkflowRuleResponse\x12\x31\n\x04rule\x18\x01 \x01(\x0b\x32#.temporal.api.rules.v1.WorkflowRule\x12\x0e\n\x06job_id\x18\x02 \x01(\t"A\n\x1b\x44\x65scribeWorkflowRuleRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x0f\n\x07rule_id\x18\x02 \x01(\t"Q\n\x1c\x44\x65scribeWorkflowRuleResponse\x12\x31\n\x04rule\x18\x01 \x01(\x0b\x32#.temporal.api.rules.v1.WorkflowRule"?\n\x19\x44\x65leteWorkflowRuleRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x0f\n\x07rule_id\x18\x02 \x01(\t"\x1c\n\x1a\x44\x65leteWorkflowRuleResponse"F\n\x18ListWorkflowRulesRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c"h\n\x19ListWorkflowRulesResponse\x12\x32\n\x05rules\x18\x01 \x03(\x0b\x32#.temporal.api.rules.v1.WorkflowRule\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c"\xce\x01\n\x1aTriggerWorkflowRuleRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12<\n\texecution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x0c\n\x02id\x18\x04 \x01(\tH\x00\x12\x37\n\x04spec\x18\x05 \x01(\x0b\x32\'.temporal.api.rules.v1.WorkflowRuleSpecH\x00\x12\x10\n\x08identity\x18\x03 \x01(\tB\x06\n\x04rule".\n\x1bTriggerWorkflowRuleResponse\x12\x0f\n\x07\x61pplied\x18\x01 \x01(\x08"\x9b\x01\n\x1cRecordWorkerHeartbeatRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x10\n\x08identity\x18\x02 \x01(\t\x12\x41\n\x10worker_heartbeat\x18\x03 \x03(\x0b\x32\'.temporal.api.worker.v1.WorkerHeartbeat\x12\x13\n\x0bresource_id\x18\x04 \x01(\t"\x1f\n\x1dRecordWorkerHeartbeatResponse"\x82\x01\n\x12ListWorkersRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x11\n\tpage_size\x18\x02 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c\x12\r\n\x05query\x18\x04 \x01(\t\x12\x1e\n\x16include_system_workers\x18\x05 \x01(\x08"\xa5\x01\n\x13ListWorkersResponse\x12<\n\x0cworkers_info\x18\x01 \x03(\x0b\x32".temporal.api.worker.v1.WorkerInfoB\x02\x18\x01\x12\x37\n\x07workers\x18\x03 \x03(\x0b\x32&.temporal.api.worker.v1.WorkerListInfo\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c"\xd5\x05\n\x1cUpdateTaskQueueConfigRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x10\n\x08identity\x18\x02 \x01(\t\x12\x12\n\ntask_queue\x18\x03 \x01(\t\x12=\n\x0ftask_queue_type\x18\x04 \x01(\x0e\x32$.temporal.api.enums.v1.TaskQueueType\x12n\n\x17update_queue_rate_limit\x18\x05 \x01(\x0b\x32M.temporal.api.workflowservice.v1.UpdateTaskQueueConfigRequest.RateLimitUpdate\x12}\n&update_fairness_key_rate_limit_default\x18\x06 \x01(\x0b\x32M.temporal.api.workflowservice.v1.UpdateTaskQueueConfigRequest.RateLimitUpdate\x12\x84\x01\n\x1dset_fairness_weight_overrides\x18\x07 \x03(\x0b\x32].temporal.api.workflowservice.v1.UpdateTaskQueueConfigRequest.SetFairnessWeightOverridesEntry\x12\'\n\x1funset_fairness_weight_overrides\x18\x08 \x03(\t\x1a[\n\x0fRateLimitUpdate\x12\x38\n\nrate_limit\x18\x01 \x01(\x0b\x32$.temporal.api.taskqueue.v1.RateLimit\x12\x0e\n\x06reason\x18\x02 \x01(\t\x1a\x41\n\x1fSetFairnessWeightOverridesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\x02:\x02\x38\x01"[\n\x1dUpdateTaskQueueConfigResponse\x12:\n\x06\x63onfig\x18\x01 \x01(\x0b\x32*.temporal.api.taskqueue.v1.TaskQueueConfig"\x9e\x01\n\x18\x46\x65tchWorkerConfigRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x10\n\x08identity\x18\x02 \x01(\t\x12\x0e\n\x06reason\x18\x03 \x01(\t\x12\x38\n\x08selector\x18\x06 \x01(\x0b\x32&.temporal.api.common.v1.WorkerSelector\x12\x13\n\x0bresource_id\x18\x07 \x01(\t"U\n\x19\x46\x65tchWorkerConfigResponse\x12\x38\n\rworker_config\x18\x01 \x01(\x0b\x32!.temporal.api.sdk.v1.WorkerConfig"\x8a\x02\n\x19UpdateWorkerConfigRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x10\n\x08identity\x18\x02 \x01(\t\x12\x0e\n\x06reason\x18\x03 \x01(\t\x12\x38\n\rworker_config\x18\x04 \x01(\x0b\x32!.temporal.api.sdk.v1.WorkerConfig\x12/\n\x0bupdate_mask\x18\x05 \x01(\x0b\x32\x1a.google.protobuf.FieldMask\x12\x38\n\x08selector\x18\x06 \x01(\x0b\x32&.temporal.api.common.v1.WorkerSelector\x12\x13\n\x0bresource_id\x18\x07 \x01(\t"d\n\x1aUpdateWorkerConfigResponse\x12:\n\rworker_config\x18\x01 \x01(\x0b\x32!.temporal.api.sdk.v1.WorkerConfigH\x00\x42\n\n\x08response"G\n\x15\x44\x65scribeWorkerRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x1b\n\x13worker_instance_key\x18\x02 \x01(\t"Q\n\x16\x44\x65scribeWorkerResponse\x12\x37\n\x0bworker_info\x18\x01 \x01(\x0b\x32".temporal.api.worker.v1.WorkerInfo"W\n\x13\x43ountWorkersRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\r\n\x05query\x18\x02 \x01(\t\x12\x1e\n\x16include_system_workers\x18\x03 \x01(\x08"%\n\x14\x43ountWorkersResponse\x12\r\n\x05\x63ount\x18\x01 \x01(\x03"\x8d\x01\n\x1dPauseWorkflowExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x12\x10\n\x08identity\x18\x04 \x01(\t\x12\x0e\n\x06reason\x18\x05 \x01(\t\x12\x12\n\nrequest_id\x18\x06 \x01(\t" \n\x1ePauseWorkflowExecutionResponse"\x8f\x01\n\x1fUnpauseWorkflowExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x12\x10\n\x08identity\x18\x04 \x01(\t\x12\x0e\n\x06reason\x18\x05 \x01(\t\x12\x12\n\nrequest_id\x18\x06 \x01(\t""\n UnpauseWorkflowExecutionResponse"\x99\t\n\x1dStartActivityExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x10\n\x08identity\x18\x02 \x01(\t\x12\x12\n\nrequest_id\x18\x03 \x01(\t\x12\x13\n\x0b\x61\x63tivity_id\x18\x04 \x01(\t\x12;\n\ractivity_type\x18\x05 \x01(\x0b\x32$.temporal.api.common.v1.ActivityType\x12\x38\n\ntask_queue\x18\x06 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12<\n\x19schedule_to_close_timeout\x18\x07 \x01(\x0b\x32\x19.google.protobuf.Duration\x12<\n\x19schedule_to_start_timeout\x18\x08 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x39\n\x16start_to_close_timeout\x18\t \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x34\n\x11heartbeat_timeout\x18\n \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x39\n\x0cretry_policy\x18\x0b \x01(\x0b\x32#.temporal.api.common.v1.RetryPolicy\x12/\n\x05input\x18\x0c \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x45\n\x0fid_reuse_policy\x18\r \x01(\x0e\x32,.temporal.api.enums.v1.ActivityIdReusePolicy\x12K\n\x12id_conflict_policy\x18\x0e \x01(\x0e\x32/.temporal.api.enums.v1.ActivityIdConflictPolicy\x12\x43\n\x11search_attributes\x18\x0f \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes\x12.\n\x06header\x18\x10 \x01(\x0b\x32\x1e.temporal.api.common.v1.Header\x12\x38\n\ruser_metadata\x18\x11 \x01(\x0b\x32!.temporal.api.sdk.v1.UserMetadata\x12\x32\n\x08priority\x18\x12 \x01(\x0b\x32 .temporal.api.common.v1.Priority\x12>\n\x14\x63ompletion_callbacks\x18\x13 \x03(\x0b\x32 .temporal.api.common.v1.Callback\x12+\n\x05links\x18\x14 \x03(\x0b\x32\x1c.temporal.api.common.v1.Link\x12\x46\n\x13on_conflict_options\x18\x15 \x01(\x0b\x32).temporal.api.common.v1.OnConflictOptions\x12.\n\x0bstart_delay\x18\x16 \x01(\x0b\x32\x19.google.protobuf.Duration"m\n\x1eStartActivityExecutionResponse\x12\x0e\n\x06run_id\x18\x01 \x01(\t\x12\x0f\n\x07started\x18\x02 \x01(\x08\x12*\n\x04link\x18\x03 \x01(\x0b\x32\x1c.temporal.api.common.v1.Link"\xe4\x01\n DescribeActivityExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0b\x61\x63tivity_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x12\x15\n\rinclude_input\x18\x04 \x01(\x08\x12\x17\n\x0finclude_outcome\x18\x05 \x01(\x08\x12\x17\n\x0flong_poll_token\x18\x06 \x01(\x0c\x12!\n\x19include_heartbeat_details\x18\x07 \x01(\x08\x12\x1c\n\x14include_last_failure\x18\x08 \x01(\x08"\xbc\x02\n!DescribeActivityExecutionResponse\x12\x0e\n\x06run_id\x18\x01 \x01(\t\x12=\n\x04info\x18\x02 \x01(\x0b\x32/.temporal.api.activity.v1.ActivityExecutionInfo\x12/\n\x05input\x18\x03 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x43\n\x07outcome\x18\x04 \x01(\x0b\x32\x32.temporal.api.activity.v1.ActivityExecutionOutcome\x12\x17\n\x0flong_poll_token\x18\x05 \x01(\x0c\x12\x39\n\tcallbacks\x18\x06 \x03(\x0b\x32&.temporal.api.activity.v1.CallbackInfo"V\n\x1cPollActivityExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0b\x61\x63tivity_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t"t\n\x1dPollActivityExecutionResponse\x12\x0e\n\x06run_id\x18\x01 \x01(\t\x12\x43\n\x07outcome\x18\x02 \x01(\x0b\x32\x32.temporal.api.activity.v1.ActivityExecutionOutcome"m\n\x1dListActivityExecutionsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x11\n\tpage_size\x18\x02 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c\x12\r\n\x05query\x18\x04 \x01(\t"\x82\x01\n\x1eListActivityExecutionsResponse\x12G\n\nexecutions\x18\x01 \x03(\x0b\x32\x33.temporal.api.activity.v1.ActivityExecutionListInfo\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c"\xd1\x06\n#StartNexusOperationExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x10\n\x08identity\x18\x02 \x01(\t\x12\x12\n\nrequest_id\x18\x03 \x01(\t\x12\x14\n\x0coperation_id\x18\x04 \x01(\t\x12\x10\n\x08\x65ndpoint\x18\x05 \x01(\t\x12\x0f\n\x07service\x18\x06 \x01(\t\x12\x11\n\toperation\x18\x07 \x01(\t\x12<\n\x19schedule_to_close_timeout\x18\x08 \x01(\x0b\x32\x19.google.protobuf.Duration\x12<\n\x19schedule_to_start_timeout\x18\t \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x39\n\x16start_to_close_timeout\x18\n \x01(\x0b\x32\x19.google.protobuf.Duration\x12.\n\x05input\x18\x0b \x01(\x0b\x32\x1f.temporal.api.common.v1.Payload\x12K\n\x0fid_reuse_policy\x18\x0c \x01(\x0e\x32\x32.temporal.api.enums.v1.NexusOperationIdReusePolicy\x12Q\n\x12id_conflict_policy\x18\r \x01(\x0e\x32\x35.temporal.api.enums.v1.NexusOperationIdConflictPolicy\x12\x43\n\x11search_attributes\x18\x0e \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes\x12k\n\x0cnexus_header\x18\x0f \x03(\x0b\x32U.temporal.api.workflowservice.v1.StartNexusOperationExecutionRequest.NexusHeaderEntry\x12\x38\n\ruser_metadata\x18\x10 \x01(\x0b\x32!.temporal.api.sdk.v1.UserMetadata\x1a\x32\n\x10NexusHeaderEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01"G\n$StartNexusOperationExecutionResponse\x12\x0e\n\x06run_id\x18\x01 \x01(\t\x12\x0f\n\x07started\x18\x02 \x01(\x08"\xaa\x01\n&DescribeNexusOperationExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x14\n\x0coperation_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x12\x15\n\rinclude_input\x18\x04 \x01(\x08\x12\x17\n\x0finclude_outcome\x18\x05 \x01(\x08\x12\x17\n\x0flong_poll_token\x18\x06 \x01(\x0c"\xb7\x02\n\'DescribeNexusOperationExecutionResponse\x12\x0e\n\x06run_id\x18\x01 \x01(\t\x12@\n\x04info\x18\x02 \x01(\x0b\x32\x32.temporal.api.nexus.v1.NexusOperationExecutionInfo\x12.\n\x05input\x18\x03 \x01(\x0b\x32\x1f.temporal.api.common.v1.Payload\x12\x31\n\x06result\x18\x04 \x01(\x0b\x32\x1f.temporal.api.common.v1.PayloadH\x00\x12\x33\n\x07\x66\x61ilure\x18\x05 \x01(\x0b\x32 .temporal.api.failure.v1.FailureH\x00\x12\x17\n\x0flong_poll_token\x18\x06 \x01(\x0c\x42\t\n\x07outcome"\xa1\x01\n"PollNexusOperationExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x14\n\x0coperation_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x12\x42\n\nwait_stage\x18\x04 \x01(\x0e\x32..temporal.api.enums.v1.NexusOperationWaitStage"\x85\x02\n#PollNexusOperationExecutionResponse\x12\x0e\n\x06run_id\x18\x01 \x01(\t\x12\x42\n\nwait_stage\x18\x02 \x01(\x0e\x32..temporal.api.enums.v1.NexusOperationWaitStage\x12\x17\n\x0foperation_token\x18\x03 \x01(\t\x12\x31\n\x06result\x18\x04 \x01(\x0b\x32\x1f.temporal.api.common.v1.PayloadH\x00\x12\x33\n\x07\x66\x61ilure\x18\x05 \x01(\x0b\x32 .temporal.api.failure.v1.FailureH\x00\x42\t\n\x07outcome"s\n#ListNexusOperationExecutionsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x11\n\tpage_size\x18\x02 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c\x12\r\n\x05query\x18\x04 \x01(\t"\x8b\x01\n$ListNexusOperationExecutionsResponse\x12J\n\noperations\x18\x01 \x03(\x0b\x32\x36.temporal.api.nexus.v1.NexusOperationExecutionListInfo\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c"B\n\x1e\x43ountActivityExecutionsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\r\n\x05query\x18\x02 \x01(\t"\xed\x01\n\x1f\x43ountActivityExecutionsResponse\x12\r\n\x05\x63ount\x18\x01 \x01(\x03\x12\x61\n\x06groups\x18\x02 \x03(\x0b\x32Q.temporal.api.workflowservice.v1.CountActivityExecutionsResponse.AggregationGroup\x1aX\n\x10\x41ggregationGroup\x12\x35\n\x0cgroup_values\x18\x01 \x03(\x0b\x32\x1f.temporal.api.common.v1.Payload\x12\r\n\x05\x63ount\x18\x02 \x01(\x03"H\n$CountNexusOperationExecutionsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\r\n\x05query\x18\x02 \x01(\t"\xf9\x01\n%CountNexusOperationExecutionsResponse\x12\r\n\x05\x63ount\x18\x01 \x01(\x03\x12g\n\x06groups\x18\x02 \x03(\x0b\x32W.temporal.api.workflowservice.v1.CountNexusOperationExecutionsResponse.AggregationGroup\x1aX\n\x10\x41ggregationGroup\x12\x35\n\x0cgroup_values\x18\x01 \x03(\x0b\x32\x1f.temporal.api.common.v1.Payload\x12\r\n\x05\x63ount\x18\x02 \x01(\x03"\x95\x01\n%RequestCancelActivityExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0b\x61\x63tivity_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x12\x10\n\x08identity\x18\x04 \x01(\t\x12\x12\n\nrequest_id\x18\x05 \x01(\t\x12\x0e\n\x06reason\x18\x06 \x01(\t"(\n&RequestCancelActivityExecutionResponse"\x91\x01\n!TerminateActivityExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0b\x61\x63tivity_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x12\x10\n\x08identity\x18\x04 \x01(\t\x12\x12\n\nrequest_id\x18\x05 \x01(\t\x12\x0e\n\x06reason\x18\x06 \x01(\t"$\n"TerminateActivityExecutionResponse"X\n\x1e\x44\x65leteActivityExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0b\x61\x63tivity_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t"!\n\x1f\x44\x65leteActivityExecutionResponse"\x9c\x01\n+RequestCancelNexusOperationExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x14\n\x0coperation_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x12\x10\n\x08identity\x18\x04 \x01(\t\x12\x12\n\nrequest_id\x18\x05 \x01(\t\x12\x0e\n\x06reason\x18\x06 \x01(\t".\n,RequestCancelNexusOperationExecutionResponse"\x98\x01\n\'TerminateNexusOperationExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x14\n\x0coperation_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x12\x10\n\x08identity\x18\x04 \x01(\t\x12\x12\n\nrequest_id\x18\x05 \x01(\t\x12\x0e\n\x06reason\x18\x06 \x01(\t"*\n(TerminateNexusOperationExecutionResponse"_\n$DeleteNexusOperationExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x14\n\x0coperation_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t"\'\n%DeleteNexusOperationExecutionResponseB\xbe\x01\n"io.temporal.api.workflowservice.v1B\x14RequestResponseProtoP\x01Z5go.temporal.io/api/workflowservice/v1;workflowservice\xaa\x02!Temporalio.Api.WorkflowService.V1\xea\x02$Temporalio::Api::WorkflowService::V1b\x06proto3' + b'\n6temporal/api/workflowservice/v1/request_response.proto\x12\x1ftemporal.api.workflowservice.v1\x1a+temporal/api/enums/v1/batch_operation.proto\x1a"temporal/api/enums/v1/common.proto\x1a$temporal/api/enums/v1/workflow.proto\x1a%temporal/api/enums/v1/namespace.proto\x1a(temporal/api/enums/v1/failed_cause.proto\x1a!temporal/api/enums/v1/query.proto\x1a!temporal/api/enums/v1/reset.proto\x1a&temporal/api/enums/v1/task_queue.proto\x1a&temporal/api/enums/v1/deployment.proto\x1a"temporal/api/enums/v1/update.proto\x1a)temporal/api/enums/v1/time_skipping.proto\x1a$temporal/api/enums/v1/activity.proto\x1a!temporal/api/enums/v1/nexus.proto\x1a&temporal/api/activity/v1/message.proto\x1a$temporal/api/common/v1/message.proto\x1a%temporal/api/history/v1/message.proto\x1a&temporal/api/workflow/v1/message.proto\x1a%temporal/api/command/v1/message.proto\x1a$temporal/api/compute/v1/config.proto\x1a(temporal/api/deployment/v1/message.proto\x1a%temporal/api/failure/v1/message.proto\x1a$temporal/api/filter/v1/message.proto\x1a&temporal/api/protocol/v1/message.proto\x1a\'temporal/api/namespace/v1/message.proto\x1a#temporal/api/query/v1/message.proto\x1a)temporal/api/replication/v1/message.proto\x1a#temporal/api/rules/v1/message.proto\x1a\'temporal/api/sdk/v1/worker_config.proto\x1a&temporal/api/schedule/v1/message.proto\x1a\'temporal/api/taskqueue/v1/message.proto\x1a$temporal/api/update/v1/message.proto\x1a%temporal/api/version/v1/message.proto\x1a#temporal/api/batch/v1/message.proto\x1a\x30temporal/api/sdk/v1/task_complete_metadata.proto\x1a\'temporal/api/sdk/v1/user_metadata.proto\x1a#temporal/api/nexus/v1/message.proto\x1a$temporal/api/worker/v1/message.proto\x1a\x1egoogle/protobuf/duration.proto\x1a google/protobuf/field_mask.proto\x1a\x1fgoogle/protobuf/timestamp.proto"\x88\x05\n\x18RegisterNamespaceRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0b\x64\x65scription\x18\x02 \x01(\t\x12\x13\n\x0bowner_email\x18\x03 \x01(\t\x12\x46\n#workflow_execution_retention_period\x18\x04 \x01(\x0b\x32\x19.google.protobuf.Duration\x12G\n\x08\x63lusters\x18\x05 \x03(\x0b\x32\x35.temporal.api.replication.v1.ClusterReplicationConfig\x12\x1b\n\x13\x61\x63tive_cluster_name\x18\x06 \x01(\t\x12Q\n\x04\x64\x61ta\x18\x07 \x03(\x0b\x32\x43.temporal.api.workflowservice.v1.RegisterNamespaceRequest.DataEntry\x12\x16\n\x0esecurity_token\x18\x08 \x01(\t\x12\x1b\n\x13is_global_namespace\x18\t \x01(\x08\x12\x44\n\x16history_archival_state\x18\n \x01(\x0e\x32$.temporal.api.enums.v1.ArchivalState\x12\x1c\n\x14history_archival_uri\x18\x0b \x01(\t\x12G\n\x19visibility_archival_state\x18\x0c \x01(\x0e\x32$.temporal.api.enums.v1.ArchivalState\x12\x1f\n\x17visibility_archival_uri\x18\r \x01(\t\x1a+\n\tDataEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01"\x1b\n\x19RegisterNamespaceResponse"\x89\x01\n\x15ListNamespacesRequest\x12\x11\n\tpage_size\x18\x01 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c\x12\x44\n\x10namespace_filter\x18\x03 \x01(\x0b\x32*.temporal.api.namespace.v1.NamespaceFilter"\x81\x01\n\x16ListNamespacesResponse\x12N\n\nnamespaces\x18\x01 \x03(\x0b\x32:.temporal.api.workflowservice.v1.DescribeNamespaceResponse\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c"S\n\x18\x44\x65scribeNamespaceRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\n\n\x02id\x18\x02 \x01(\t\x12\x18\n\x10weak_consistency\x18\x03 \x01(\x08"\x81\x04\n\x19\x44\x65scribeNamespaceResponse\x12@\n\x0enamespace_info\x18\x01 \x01(\x0b\x32(.temporal.api.namespace.v1.NamespaceInfo\x12:\n\x06\x63onfig\x18\x02 \x01(\x0b\x32*.temporal.api.namespace.v1.NamespaceConfig\x12S\n\x12replication_config\x18\x03 \x01(\x0b\x32\x37.temporal.api.replication.v1.NamespaceReplicationConfig\x12\x18\n\x10\x66\x61ilover_version\x18\x04 \x01(\x03\x12\x1b\n\x13is_global_namespace\x18\x05 \x01(\x08\x12\x45\n\x10\x66\x61ilover_history\x18\x06 \x03(\x0b\x32+.temporal.api.replication.v1.FailoverStatus\x12J\n\x12poller_group_infos\x18\x07 \x03(\x0b\x32*.temporal.api.taskqueue.v1.PollerGroupInfoB\x02\x18\x01\x12G\n\x12poller_groups_info\x18\x08 \x01(\x0b\x32+.temporal.api.taskqueue.v1.PollerGroupsInfo"\xcf\x02\n\x16UpdateNamespaceRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x43\n\x0bupdate_info\x18\x02 \x01(\x0b\x32..temporal.api.namespace.v1.UpdateNamespaceInfo\x12:\n\x06\x63onfig\x18\x03 \x01(\x0b\x32*.temporal.api.namespace.v1.NamespaceConfig\x12S\n\x12replication_config\x18\x04 \x01(\x0b\x32\x37.temporal.api.replication.v1.NamespaceReplicationConfig\x12\x16\n\x0esecurity_token\x18\x05 \x01(\t\x12\x19\n\x11\x64\x65lete_bad_binary\x18\x06 \x01(\t\x12\x19\n\x11promote_namespace\x18\x07 \x01(\x08"\xa3\x02\n\x17UpdateNamespaceResponse\x12@\n\x0enamespace_info\x18\x01 \x01(\x0b\x32(.temporal.api.namespace.v1.NamespaceInfo\x12:\n\x06\x63onfig\x18\x02 \x01(\x0b\x32*.temporal.api.namespace.v1.NamespaceConfig\x12S\n\x12replication_config\x18\x03 \x01(\x0b\x32\x37.temporal.api.replication.v1.NamespaceReplicationConfig\x12\x18\n\x10\x66\x61ilover_version\x18\x04 \x01(\x03\x12\x1b\n\x13is_global_namespace\x18\x05 \x01(\x08"F\n\x19\x44\x65precateNamespaceRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x16\n\x0esecurity_token\x18\x02 \x01(\t"\x1c\n\x1a\x44\x65precateNamespaceResponse"\xd1\x0c\n\x1dStartWorkflowExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12;\n\rworkflow_type\x18\x03 \x01(\x0b\x32$.temporal.api.common.v1.WorkflowType\x12\x38\n\ntask_queue\x18\x04 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12/\n\x05input\x18\x05 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12=\n\x1aworkflow_execution_timeout\x18\x06 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x37\n\x14workflow_run_timeout\x18\x07 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x38\n\x15workflow_task_timeout\x18\x08 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x10\n\x08identity\x18\t \x01(\t\x12\x12\n\nrequest_id\x18\n \x01(\t\x12N\n\x18workflow_id_reuse_policy\x18\x0b \x01(\x0e\x32,.temporal.api.enums.v1.WorkflowIdReusePolicy\x12T\n\x1bworkflow_id_conflict_policy\x18\x16 \x01(\x0e\x32/.temporal.api.enums.v1.WorkflowIdConflictPolicy\x12\x39\n\x0cretry_policy\x18\x0c \x01(\x0b\x32#.temporal.api.common.v1.RetryPolicy\x12\x15\n\rcron_schedule\x18\r \x01(\t\x12*\n\x04memo\x18\x0e \x01(\x0b\x32\x1c.temporal.api.common.v1.Memo\x12\x43\n\x11search_attributes\x18\x0f \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes\x12.\n\x06header\x18\x10 \x01(\x0b\x32\x1e.temporal.api.common.v1.Header\x12\x1f\n\x17request_eager_execution\x18\x11 \x01(\x08\x12;\n\x11\x63ontinued_failure\x18\x12 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12@\n\x16last_completion_result\x18\x13 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x37\n\x14workflow_start_delay\x18\x14 \x01(\x0b\x32\x19.google.protobuf.Duration\x12>\n\x14\x63ompletion_callbacks\x18\x15 \x03(\x0b\x32 .temporal.api.common.v1.Callback\x12\x38\n\ruser_metadata\x18\x17 \x01(\x0b\x32!.temporal.api.sdk.v1.UserMetadata\x12+\n\x05links\x18\x18 \x03(\x0b\x32\x1c.temporal.api.common.v1.Link\x12I\n\x13versioning_override\x18\x19 \x01(\x0b\x32,.temporal.api.workflow.v1.VersioningOverride\x12H\n\x13on_conflict_options\x18\x1a \x01(\x0b\x32+.temporal.api.workflow.v1.OnConflictOptions\x12\x32\n\x08priority\x18\x1b \x01(\x0b\x32 .temporal.api.common.v1.Priority\x12\\\n\x1f\x65\x61ger_worker_deployment_options\x18\x1c \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentOptions\x12H\n\x14time_skipping_config\x18\x1d \x01(\x0b\x32*.temporal.api.common.v1.TimeSkippingConfig"\xaa\x02\n\x1eStartWorkflowExecutionResponse\x12\x0e\n\x06run_id\x18\x01 \x01(\t\x12\x1e\n\x16\x66irst_execution_run_id\x18\x06 \x01(\t\x12\x0f\n\x07started\x18\x03 \x01(\x08\x12>\n\x06status\x18\x05 \x01(\x0e\x32..temporal.api.enums.v1.WorkflowExecutionStatus\x12[\n\x13\x65\x61ger_workflow_task\x18\x02 \x01(\x0b\x32>.temporal.api.workflowservice.v1.PollWorkflowTaskQueueResponse\x12*\n\x04link\x18\x04 \x01(\x0b\x32\x1c.temporal.api.common.v1.Link"\xaa\x02\n"GetWorkflowExecutionHistoryRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12<\n\texecution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x19\n\x11maximum_page_size\x18\x03 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x04 \x01(\x0c\x12\x16\n\x0ewait_new_event\x18\x05 \x01(\x08\x12P\n\x19history_event_filter_type\x18\x06 \x01(\x0e\x32-.temporal.api.enums.v1.HistoryEventFilterType\x12\x15\n\rskip_archival\x18\x07 \x01(\x08"\xba\x01\n#GetWorkflowExecutionHistoryResponse\x12\x31\n\x07history\x18\x01 \x01(\x0b\x32 .temporal.api.history.v1.History\x12\x35\n\x0braw_history\x18\x02 \x03(\x0b\x32 .temporal.api.common.v1.DataBlob\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c\x12\x10\n\x08\x61rchived\x18\x04 \x01(\x08"\xb0\x01\n)GetWorkflowExecutionHistoryReverseRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12<\n\texecution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x19\n\x11maximum_page_size\x18\x03 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x04 \x01(\x0c"x\n*GetWorkflowExecutionHistoryReverseResponse\x12\x31\n\x07history\x18\x01 \x01(\x0b\x32 .temporal.api.history.v1.History\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c"\xb8\x03\n\x1cPollWorkflowTaskQueueRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x38\n\ntask_queue\x18\x02 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12\x17\n\x0fpoller_group_id\x18\n \x01(\t\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x1b\n\x13worker_instance_key\x18\x08 \x01(\t\x12!\n\x19worker_control_task_queue\x18\t \x01(\t\x12\x1b\n\x0f\x62inary_checksum\x18\x04 \x01(\tB\x02\x18\x01\x12Z\n\x1bworker_version_capabilities\x18\x05 \x01(\x0b\x32\x31.temporal.api.common.v1.WorkerVersionCapabilitiesB\x02\x18\x01\x12O\n\x12\x64\x65ployment_options\x18\x06 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentOptionsJ\x04\x08\x07\x10\x08R\x10worker_heartbeat"\xbf\x08\n\x1dPollWorkflowTaskQueueResponse\x12\x12\n\ntask_token\x18\x01 \x01(\x0c\x12\x45\n\x12workflow_execution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12;\n\rworkflow_type\x18\x03 \x01(\x0b\x32$.temporal.api.common.v1.WorkflowType\x12!\n\x19previous_started_event_id\x18\x04 \x01(\x03\x12\x18\n\x10started_event_id\x18\x05 \x01(\x03\x12\x0f\n\x07\x61ttempt\x18\x06 \x01(\x05\x12\x1a\n\x12\x62\x61\x63klog_count_hint\x18\x07 \x01(\x03\x12\x31\n\x07history\x18\x08 \x01(\x0b\x32 .temporal.api.history.v1.History\x12\x17\n\x0fnext_page_token\x18\t \x01(\x0c\x12\x33\n\x05query\x18\n \x01(\x0b\x32$.temporal.api.query.v1.WorkflowQuery\x12K\n\x1dworkflow_execution_task_queue\x18\x0b \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12\x32\n\x0escheduled_time\x18\x0c \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x30\n\x0cstarted_time\x18\r \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\\\n\x07queries\x18\x0e \x03(\x0b\x32K.temporal.api.workflowservice.v1.PollWorkflowTaskQueueResponse.QueriesEntry\x12\x33\n\x08messages\x18\x0f \x03(\x0b\x32!.temporal.api.protocol.v1.Message\x12Q\n\x17poller_scaling_decision\x18\x10 \x01(\x0b\x32\x30.temporal.api.taskqueue.v1.PollerScalingDecision\x12\x17\n\x0fpoller_group_id\x18\x11 \x01(\t\x12J\n\x12poller_group_infos\x18\x12 \x03(\x0b\x32*.temporal.api.taskqueue.v1.PollerGroupInfoB\x02\x18\x01\x12G\n\x12poller_groups_info\x18\x13 \x01(\x0b\x32+.temporal.api.taskqueue.v1.PollerGroupsInfo\x1aT\n\x0cQueriesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x33\n\x05value\x18\x02 \x01(\x0b\x32$.temporal.api.query.v1.WorkflowQuery:\x02\x38\x01"\xba\n\n#RespondWorkflowTaskCompletedRequest\x12\x12\n\ntask_token\x18\x01 \x01(\x0c\x12\x32\n\x08\x63ommands\x18\x02 \x03(\x0b\x32 .temporal.api.command.v1.Command\x12\x10\n\x08identity\x18\x03 \x01(\t\x12O\n\x11sticky_attributes\x18\x04 \x01(\x0b\x32\x34.temporal.api.taskqueue.v1.StickyExecutionAttributes\x12 \n\x18return_new_workflow_task\x18\x05 \x01(\x08\x12&\n\x1e\x66orce_create_new_workflow_task\x18\x06 \x01(\x08\x12\x1b\n\x0f\x62inary_checksum\x18\x07 \x01(\tB\x02\x18\x01\x12m\n\rquery_results\x18\x08 \x03(\x0b\x32V.temporal.api.workflowservice.v1.RespondWorkflowTaskCompletedRequest.QueryResultsEntry\x12\x11\n\tnamespace\x18\t \x01(\t\x12\x13\n\x0bresource_id\x18\x12 \x01(\t\x12L\n\x14worker_version_stamp\x18\n \x01(\x0b\x32*.temporal.api.common.v1.WorkerVersionStampB\x02\x18\x01\x12\x33\n\x08messages\x18\x0b \x03(\x0b\x32!.temporal.api.protocol.v1.Message\x12H\n\x0csdk_metadata\x18\x0c \x01(\x0b\x32\x32.temporal.api.sdk.v1.WorkflowTaskCompletedMetadata\x12\x43\n\x11metering_metadata\x18\r \x01(\x0b\x32(.temporal.api.common.v1.MeteringMetadata\x12g\n\x0c\x63\x61pabilities\x18\x0e \x01(\x0b\x32Q.temporal.api.workflowservice.v1.RespondWorkflowTaskCompletedRequest.Capabilities\x12>\n\ndeployment\x18\x0f \x01(\x0b\x32&.temporal.api.deployment.v1.DeploymentB\x02\x18\x01\x12\x46\n\x13versioning_behavior\x18\x10 \x01(\x0e\x32).temporal.api.enums.v1.VersioningBehavior\x12O\n\x12\x64\x65ployment_options\x18\x11 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentOptions\x12\x1b\n\x13worker_instance_key\x18\x13 \x01(\t\x12!\n\x19worker_control_task_queue\x18\x14 \x01(\t\x12\x13\n\x0bpage_number\x18\x15 \x01(\x05\x12\x19\n\x11intermediate_page\x18\x16 \x01(\x08\x1a_\n\x11QueryResultsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x39\n\x05value\x18\x02 \x01(\x0b\x32*.temporal.api.query.v1.WorkflowQueryResult:\x02\x38\x01\x1a\x45\n\x0c\x43\x61pabilities\x12\x35\n-discard_speculative_workflow_task_with_events\x18\x01 \x01(\x08"\xf5\x01\n$RespondWorkflowTaskCompletedResponse\x12U\n\rworkflow_task\x18\x01 \x01(\x0b\x32>.temporal.api.workflowservice.v1.PollWorkflowTaskQueueResponse\x12V\n\x0e\x61\x63tivity_tasks\x18\x02 \x03(\x0b\x32>.temporal.api.workflowservice.v1.PollActivityTaskQueueResponse\x12\x1e\n\x16reset_history_event_id\x18\x03 \x01(\x03"\x8d\x04\n RespondWorkflowTaskFailedRequest\x12\x12\n\ntask_token\x18\x01 \x01(\x0c\x12=\n\x05\x63\x61use\x18\x02 \x01(\x0e\x32..temporal.api.enums.v1.WorkflowTaskFailedCause\x12\x31\n\x07\x66\x61ilure\x18\x03 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12\x10\n\x08identity\x18\x04 \x01(\t\x12\x1b\n\x0f\x62inary_checksum\x18\x05 \x01(\tB\x02\x18\x01\x12\x11\n\tnamespace\x18\x06 \x01(\t\x12\x13\n\x0bresource_id\x18\x0b \x01(\t\x12\x33\n\x08messages\x18\x07 \x03(\x0b\x32!.temporal.api.protocol.v1.Message\x12\x46\n\x0eworker_version\x18\x08 \x01(\x0b\x32*.temporal.api.common.v1.WorkerVersionStampB\x02\x18\x01\x12>\n\ndeployment\x18\t \x01(\x0b\x32&.temporal.api.deployment.v1.DeploymentB\x02\x18\x01\x12O\n\x12\x64\x65ployment_options\x18\n \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentOptions"#\n!RespondWorkflowTaskFailedResponse"\xe6\x03\n\x1cPollActivityTaskQueueRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x38\n\ntask_queue\x18\x02 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12\x17\n\x0fpoller_group_id\x18\n \x01(\t\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x1b\n\x13worker_instance_key\x18\x08 \x01(\t\x12!\n\x19worker_control_task_queue\x18\t \x01(\t\x12I\n\x13task_queue_metadata\x18\x04 \x01(\x0b\x32,.temporal.api.taskqueue.v1.TaskQueueMetadata\x12Z\n\x1bworker_version_capabilities\x18\x05 \x01(\x0b\x32\x31.temporal.api.common.v1.WorkerVersionCapabilitiesB\x02\x18\x01\x12O\n\x12\x64\x65ployment_options\x18\x06 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentOptionsJ\x04\x08\x07\x10\x08R\x10worker_heartbeat"\x9d\t\n\x1dPollActivityTaskQueueResponse\x12\x12\n\ntask_token\x18\x01 \x01(\x0c\x12\x1a\n\x12workflow_namespace\x18\x02 \x01(\t\x12;\n\rworkflow_type\x18\x03 \x01(\x0b\x32$.temporal.api.common.v1.WorkflowType\x12\x45\n\x12workflow_execution\x18\x04 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12;\n\ractivity_type\x18\x05 \x01(\x0b\x32$.temporal.api.common.v1.ActivityType\x12\x13\n\x0b\x61\x63tivity_id\x18\x06 \x01(\t\x12.\n\x06header\x18\x07 \x01(\x0b\x32\x1e.temporal.api.common.v1.Header\x12/\n\x05input\x18\x08 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12;\n\x11heartbeat_details\x18\t \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x32\n\x0escheduled_time\x18\n \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x42\n\x1e\x63urrent_attempt_scheduled_time\x18\x0b \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x30\n\x0cstarted_time\x18\x0c \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x0f\n\x07\x61ttempt\x18\r \x01(\x05\x12<\n\x19schedule_to_close_timeout\x18\x0e \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x39\n\x16start_to_close_timeout\x18\x0f \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x34\n\x11heartbeat_timeout\x18\x10 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x39\n\x0cretry_policy\x18\x11 \x01(\x0b\x32#.temporal.api.common.v1.RetryPolicy\x12Q\n\x17poller_scaling_decision\x18\x12 \x01(\x0b\x32\x30.temporal.api.taskqueue.v1.PollerScalingDecision\x12\x32\n\x08priority\x18\x13 \x01(\x0b\x32 .temporal.api.common.v1.Priority\x12\x17\n\x0f\x61\x63tivity_run_id\x18\x14 \x01(\t\x12J\n\x12poller_group_infos\x18\x15 \x03(\x0b\x32*.temporal.api.taskqueue.v1.PollerGroupInfoB\x02\x18\x01\x12G\n\x12poller_groups_info\x18\x16 \x01(\x0b\x32+.temporal.api.taskqueue.v1.PollerGroupsInfo"\xa5\x01\n"RecordActivityTaskHeartbeatRequest\x12\x12\n\ntask_token\x18\x01 \x01(\x0c\x12\x31\n\x07\x64\x65tails\x18\x02 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x11\n\tnamespace\x18\x04 \x01(\t\x12\x13\n\x0bresource_id\x18\x05 \x01(\t"p\n#RecordActivityTaskHeartbeatResponse\x12\x18\n\x10\x63\x61ncel_requested\x18\x01 \x01(\x08\x12\x17\n\x0f\x61\x63tivity_paused\x18\x02 \x01(\x08\x12\x16\n\x0e\x61\x63tivity_reset\x18\x03 \x01(\x08"\xcf\x01\n&RecordActivityTaskHeartbeatByIdRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x12\x13\n\x0b\x61\x63tivity_id\x18\x04 \x01(\t\x12\x31\n\x07\x64\x65tails\x18\x05 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x10\n\x08identity\x18\x06 \x01(\t\x12\x13\n\x0bresource_id\x18\x07 \x01(\t"t\n\'RecordActivityTaskHeartbeatByIdResponse\x12\x18\n\x10\x63\x61ncel_requested\x18\x01 \x01(\x08\x12\x17\n\x0f\x61\x63tivity_paused\x18\x02 \x01(\x08\x12\x16\n\x0e\x61\x63tivity_reset\x18\x03 \x01(\x08"\xfe\x02\n#RespondActivityTaskCompletedRequest\x12\x12\n\ntask_token\x18\x01 \x01(\x0c\x12\x30\n\x06result\x18\x02 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x11\n\tnamespace\x18\x04 \x01(\t\x12\x13\n\x0bresource_id\x18\x08 \x01(\t\x12\x46\n\x0eworker_version\x18\x05 \x01(\x0b\x32*.temporal.api.common.v1.WorkerVersionStampB\x02\x18\x01\x12>\n\ndeployment\x18\x06 \x01(\x0b\x32&.temporal.api.deployment.v1.DeploymentB\x02\x18\x01\x12O\n\x12\x64\x65ployment_options\x18\x07 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentOptions"&\n$RespondActivityTaskCompletedResponse"\xcf\x01\n\'RespondActivityTaskCompletedByIdRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x12\x13\n\x0b\x61\x63tivity_id\x18\x04 \x01(\t\x12\x30\n\x06result\x18\x05 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x10\n\x08identity\x18\x06 \x01(\t\x12\x13\n\x0bresource_id\x18\x07 \x01(\t"*\n(RespondActivityTaskCompletedByIdResponse"\xbe\x03\n RespondActivityTaskFailedRequest\x12\x12\n\ntask_token\x18\x01 \x01(\x0c\x12\x31\n\x07\x66\x61ilure\x18\x02 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x11\n\tnamespace\x18\x04 \x01(\t\x12\x13\n\x0bresource_id\x18\t \x01(\t\x12@\n\x16last_heartbeat_details\x18\x05 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x46\n\x0eworker_version\x18\x06 \x01(\x0b\x32*.temporal.api.common.v1.WorkerVersionStampB\x02\x18\x01\x12>\n\ndeployment\x18\x07 \x01(\x0b\x32&.temporal.api.deployment.v1.DeploymentB\x02\x18\x01\x12O\n\x12\x64\x65ployment_options\x18\x08 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentOptions"W\n!RespondActivityTaskFailedResponse\x12\x32\n\x08\x66\x61ilures\x18\x01 \x03(\x0b\x32 .temporal.api.failure.v1.Failure"\x8f\x02\n$RespondActivityTaskFailedByIdRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x12\x13\n\x0b\x61\x63tivity_id\x18\x04 \x01(\t\x12\x31\n\x07\x66\x61ilure\x18\x05 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12\x10\n\x08identity\x18\x06 \x01(\t\x12@\n\x16last_heartbeat_details\x18\x07 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x13\n\x0bresource_id\x18\x08 \x01(\t"[\n%RespondActivityTaskFailedByIdResponse\x12\x32\n\x08\x66\x61ilures\x18\x01 \x03(\x0b\x32 .temporal.api.failure.v1.Failure"\xfe\x02\n"RespondActivityTaskCanceledRequest\x12\x12\n\ntask_token\x18\x01 \x01(\x0c\x12\x31\n\x07\x64\x65tails\x18\x02 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x11\n\tnamespace\x18\x04 \x01(\t\x12\x13\n\x0bresource_id\x18\x08 \x01(\t\x12\x46\n\x0eworker_version\x18\x05 \x01(\x0b\x32*.temporal.api.common.v1.WorkerVersionStampB\x02\x18\x01\x12>\n\ndeployment\x18\x06 \x01(\x0b\x32&.temporal.api.deployment.v1.DeploymentB\x02\x18\x01\x12O\n\x12\x64\x65ployment_options\x18\x07 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentOptions"%\n#RespondActivityTaskCanceledResponse"\xa0\x02\n&RespondActivityTaskCanceledByIdRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x12\x13\n\x0b\x61\x63tivity_id\x18\x04 \x01(\t\x12\x31\n\x07\x64\x65tails\x18\x05 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x10\n\x08identity\x18\x06 \x01(\t\x12O\n\x12\x64\x65ployment_options\x18\x07 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentOptions\x12\x13\n\x0bresource_id\x18\x08 \x01(\t")\n\'RespondActivityTaskCanceledByIdResponse"\x84\x02\n%RequestCancelWorkflowExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x45\n\x12workflow_execution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x12\n\nrequest_id\x18\x04 \x01(\t\x12\x1e\n\x16\x66irst_execution_run_id\x18\x05 \x01(\t\x12\x0e\n\x06reason\x18\x06 \x01(\t\x12+\n\x05links\x18\x07 \x03(\x0b\x32\x1c.temporal.api.common.v1.Link"(\n&RequestCancelWorkflowExecutionResponse"\xde\x02\n\x1eSignalWorkflowExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x45\n\x12workflow_execution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x13\n\x0bsignal_name\x18\x03 \x01(\t\x12/\n\x05input\x18\x04 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x10\n\x08identity\x18\x05 \x01(\t\x12\x12\n\nrequest_id\x18\x06 \x01(\t\x12\x13\n\x07\x63ontrol\x18\x07 \x01(\tB\x02\x18\x01\x12.\n\x06header\x18\x08 \x01(\x0b\x32\x1e.temporal.api.common.v1.Header\x12+\n\x05links\x18\n \x03(\x0b\x32\x1c.temporal.api.common.v1.LinkJ\x04\x08\t\x10\n"M\n\x1fSignalWorkflowExecutionResponse\x12*\n\x04link\x18\x01 \x01(\x0b\x32\x1c.temporal.api.common.v1.Link"\xbb\n\n\'SignalWithStartWorkflowExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12;\n\rworkflow_type\x18\x03 \x01(\x0b\x32$.temporal.api.common.v1.WorkflowType\x12\x38\n\ntask_queue\x18\x04 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12/\n\x05input\x18\x05 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12=\n\x1aworkflow_execution_timeout\x18\x06 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x37\n\x14workflow_run_timeout\x18\x07 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x38\n\x15workflow_task_timeout\x18\x08 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x10\n\x08identity\x18\t \x01(\t\x12\x12\n\nrequest_id\x18\n \x01(\t\x12N\n\x18workflow_id_reuse_policy\x18\x0b \x01(\x0e\x32,.temporal.api.enums.v1.WorkflowIdReusePolicy\x12T\n\x1bworkflow_id_conflict_policy\x18\x16 \x01(\x0e\x32/.temporal.api.enums.v1.WorkflowIdConflictPolicy\x12\x13\n\x0bsignal_name\x18\x0c \x01(\t\x12\x36\n\x0csignal_input\x18\r \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x13\n\x07\x63ontrol\x18\x0e \x01(\tB\x02\x18\x01\x12\x39\n\x0cretry_policy\x18\x0f \x01(\x0b\x32#.temporal.api.common.v1.RetryPolicy\x12\x15\n\rcron_schedule\x18\x10 \x01(\t\x12*\n\x04memo\x18\x11 \x01(\x0b\x32\x1c.temporal.api.common.v1.Memo\x12\x43\n\x11search_attributes\x18\x12 \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes\x12.\n\x06header\x18\x13 \x01(\x0b\x32\x1e.temporal.api.common.v1.Header\x12\x37\n\x14workflow_start_delay\x18\x14 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x38\n\ruser_metadata\x18\x17 \x01(\x0b\x32!.temporal.api.sdk.v1.UserMetadata\x12+\n\x05links\x18\x18 \x03(\x0b\x32\x1c.temporal.api.common.v1.Link\x12I\n\x13versioning_override\x18\x19 \x01(\x0b\x32,.temporal.api.workflow.v1.VersioningOverride\x12\x32\n\x08priority\x18\x1a \x01(\x0b\x32 .temporal.api.common.v1.Priority\x12H\n\x14time_skipping_config\x18\x1b \x01(\x0b\x32*.temporal.api.common.v1.TimeSkippingConfigJ\x04\x08\x15\x10\x16"\x9e\x01\n(SignalWithStartWorkflowExecutionResponse\x12\x0e\n\x06run_id\x18\x01 \x01(\t\x12\x1e\n\x16\x66irst_execution_run_id\x18\x04 \x01(\t\x12\x0f\n\x07started\x18\x02 \x01(\x08\x12\x31\n\x0bsignal_link\x18\x03 \x01(\x0b\x32\x1c.temporal.api.common.v1.Link"\xc1\x03\n\x1dResetWorkflowExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x45\n\x12workflow_execution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x0e\n\x06reason\x18\x03 \x01(\t\x12%\n\x1dworkflow_task_finish_event_id\x18\x04 \x01(\x03\x12\x12\n\nrequest_id\x18\x05 \x01(\t\x12G\n\x12reset_reapply_type\x18\x06 \x01(\x0e\x32\'.temporal.api.enums.v1.ResetReapplyTypeB\x02\x18\x01\x12S\n\x1breset_reapply_exclude_types\x18\x07 \x03(\x0e\x32..temporal.api.enums.v1.ResetReapplyExcludeType\x12K\n\x15post_reset_operations\x18\x08 \x03(\x0b\x32,.temporal.api.workflow.v1.PostResetOperation\x12\x10\n\x08identity\x18\t \x01(\t"0\n\x1eResetWorkflowExecutionResponse\x12\x0e\n\x06run_id\x18\x01 \x01(\t"\x9f\x02\n!TerminateWorkflowExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x45\n\x12workflow_execution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x0e\n\x06reason\x18\x03 \x01(\t\x12\x31\n\x07\x64\x65tails\x18\x04 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x10\n\x08identity\x18\x05 \x01(\t\x12\x1e\n\x16\x66irst_execution_run_id\x18\x06 \x01(\t\x12+\n\x05links\x18\x07 \x03(\x0b\x32\x1c.temporal.api.common.v1.Link"$\n"TerminateWorkflowExecutionResponse"z\n\x1e\x44\x65leteWorkflowExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x45\n\x12workflow_execution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution"!\n\x1f\x44\x65leteWorkflowExecutionResponse"\xc9\x02\n!ListOpenWorkflowExecutionsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x19\n\x11maximum_page_size\x18\x02 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c\x12\x42\n\x11start_time_filter\x18\x04 \x01(\x0b\x32\'.temporal.api.filter.v1.StartTimeFilter\x12K\n\x10\x65xecution_filter\x18\x05 \x01(\x0b\x32/.temporal.api.filter.v1.WorkflowExecutionFilterH\x00\x12\x41\n\x0btype_filter\x18\x06 \x01(\x0b\x32*.temporal.api.filter.v1.WorkflowTypeFilterH\x00\x42\t\n\x07\x66ilters"\x82\x01\n"ListOpenWorkflowExecutionsResponse\x12\x43\n\nexecutions\x18\x01 \x03(\x0b\x32/.temporal.api.workflow.v1.WorkflowExecutionInfo\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c"\x8a\x03\n#ListClosedWorkflowExecutionsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x19\n\x11maximum_page_size\x18\x02 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c\x12\x42\n\x11start_time_filter\x18\x04 \x01(\x0b\x32\'.temporal.api.filter.v1.StartTimeFilter\x12K\n\x10\x65xecution_filter\x18\x05 \x01(\x0b\x32/.temporal.api.filter.v1.WorkflowExecutionFilterH\x00\x12\x41\n\x0btype_filter\x18\x06 \x01(\x0b\x32*.temporal.api.filter.v1.WorkflowTypeFilterH\x00\x12=\n\rstatus_filter\x18\x07 \x01(\x0b\x32$.temporal.api.filter.v1.StatusFilterH\x00\x42\t\n\x07\x66ilters"\x84\x01\n$ListClosedWorkflowExecutionsResponse\x12\x43\n\nexecutions\x18\x01 \x03(\x0b\x32/.temporal.api.workflow.v1.WorkflowExecutionInfo\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c"m\n\x1dListWorkflowExecutionsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x11\n\tpage_size\x18\x02 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c\x12\r\n\x05query\x18\x04 \x01(\t"~\n\x1eListWorkflowExecutionsResponse\x12\x43\n\nexecutions\x18\x01 \x03(\x0b\x32/.temporal.api.workflow.v1.WorkflowExecutionInfo\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c"u\n%ListArchivedWorkflowExecutionsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x11\n\tpage_size\x18\x02 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c\x12\r\n\x05query\x18\x04 \x01(\t"\x86\x01\n&ListArchivedWorkflowExecutionsResponse\x12\x43\n\nexecutions\x18\x01 \x03(\x0b\x32/.temporal.api.workflow.v1.WorkflowExecutionInfo\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c"m\n\x1dScanWorkflowExecutionsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x11\n\tpage_size\x18\x02 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c\x12\r\n\x05query\x18\x04 \x01(\t"~\n\x1eScanWorkflowExecutionsResponse\x12\x43\n\nexecutions\x18\x01 \x03(\x0b\x32/.temporal.api.workflow.v1.WorkflowExecutionInfo\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c"B\n\x1e\x43ountWorkflowExecutionsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\r\n\x05query\x18\x02 \x01(\t"\xed\x01\n\x1f\x43ountWorkflowExecutionsResponse\x12\r\n\x05\x63ount\x18\x01 \x01(\x03\x12\x61\n\x06groups\x18\x02 \x03(\x0b\x32Q.temporal.api.workflowservice.v1.CountWorkflowExecutionsResponse.AggregationGroup\x1aX\n\x10\x41ggregationGroup\x12\x35\n\x0cgroup_values\x18\x01 \x03(\x0b\x32\x1f.temporal.api.common.v1.Payload\x12\r\n\x05\x63ount\x18\x02 \x01(\x03"\x1c\n\x1aGetSearchAttributesRequest"\xc9\x01\n\x1bGetSearchAttributesResponse\x12T\n\x04keys\x18\x01 \x03(\x0b\x32\x46.temporal.api.workflowservice.v1.GetSearchAttributesResponse.KeysEntry\x1aT\n\tKeysEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x36\n\x05value\x18\x02 \x01(\x0e\x32\'.temporal.api.enums.v1.IndexedValueType:\x02\x38\x01"\xe9\x02\n RespondQueryTaskCompletedRequest\x12\x12\n\ntask_token\x18\x01 \x01(\x0c\x12>\n\x0e\x63ompleted_type\x18\x02 \x01(\x0e\x32&.temporal.api.enums.v1.QueryResultType\x12\x36\n\x0cquery_result\x18\x03 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x15\n\rerror_message\x18\x04 \x01(\t\x12\x11\n\tnamespace\x18\x06 \x01(\t\x12\x31\n\x07\x66\x61ilure\x18\x07 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12=\n\x05\x63\x61use\x18\x08 \x01(\x0e\x32..temporal.api.enums.v1.WorkflowTaskFailedCause\x12\x17\n\x0fpoller_group_id\x18\t \x01(\tJ\x04\x08\x05\x10\x06"#\n!RespondQueryTaskCompletedResponse"n\n\x1bResetStickyTaskQueueRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12<\n\texecution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution"\x1e\n\x1cResetStickyTaskQueueResponse"\x9b\x02\n\x15ShutdownWorkerRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x19\n\x11sticky_task_queue\x18\x02 \x01(\t\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x0e\n\x06reason\x18\x04 \x01(\t\x12\x41\n\x10worker_heartbeat\x18\x05 \x01(\x0b\x32\'.temporal.api.worker.v1.WorkerHeartbeat\x12\x1b\n\x13worker_instance_key\x18\x06 \x01(\t\x12\x12\n\ntask_queue\x18\x07 \x01(\t\x12>\n\x10task_queue_types\x18\x08 \x03(\x0e\x32$.temporal.api.enums.v1.TaskQueueType"\x18\n\x16ShutdownWorkerResponse"\xe9\x01\n\x14QueryWorkflowRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12<\n\texecution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x33\n\x05query\x18\x03 \x01(\x0b\x32$.temporal.api.query.v1.WorkflowQuery\x12K\n\x16query_reject_condition\x18\x04 \x01(\x0e\x32+.temporal.api.enums.v1.QueryRejectCondition"\xb9\x01\n\x15QueryWorkflowResponse\x12\x36\n\x0cquery_result\x18\x01 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12<\n\x0equery_rejected\x18\x02 \x01(\x0b\x32$.temporal.api.query.v1.QueryRejected\x12*\n\x04link\x18\x03 \x01(\x0b\x32\x1c.temporal.api.common.v1.Link"s\n DescribeWorkflowExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12<\n\texecution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution"\x99\x05\n!DescribeWorkflowExecutionResponse\x12K\n\x10\x65xecution_config\x18\x01 \x01(\x0b\x32\x31.temporal.api.workflow.v1.WorkflowExecutionConfig\x12P\n\x17workflow_execution_info\x18\x02 \x01(\x0b\x32/.temporal.api.workflow.v1.WorkflowExecutionInfo\x12I\n\x12pending_activities\x18\x03 \x03(\x0b\x32-.temporal.api.workflow.v1.PendingActivityInfo\x12M\n\x10pending_children\x18\x04 \x03(\x0b\x32\x33.temporal.api.workflow.v1.PendingChildExecutionInfo\x12P\n\x15pending_workflow_task\x18\x05 \x01(\x0b\x32\x31.temporal.api.workflow.v1.PendingWorkflowTaskInfo\x12\x39\n\tcallbacks\x18\x06 \x03(\x0b\x32&.temporal.api.workflow.v1.CallbackInfo\x12U\n\x18pending_nexus_operations\x18\x07 \x03(\x0b\x32\x33.temporal.api.workflow.v1.PendingNexusOperationInfo\x12W\n\x16workflow_extended_info\x18\x08 \x01(\x0b\x32\x37.temporal.api.workflow.v1.WorkflowExecutionExtendedInfo"\x90\x04\n\x18\x44\x65scribeTaskQueueRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x38\n\ntask_queue\x18\x02 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12=\n\x0ftask_queue_type\x18\x03 \x01(\x0e\x32$.temporal.api.enums.v1.TaskQueueType\x12\x14\n\x0creport_stats\x18\x08 \x01(\x08\x12\x15\n\rreport_config\x18\x0b \x01(\x08\x12%\n\x19include_task_queue_status\x18\x04 \x01(\x08\x42\x02\x18\x01\x12\x42\n\x08\x61pi_mode\x18\x05 \x01(\x0e\x32,.temporal.api.enums.v1.DescribeTaskQueueModeB\x02\x18\x01\x12J\n\x08versions\x18\x06 \x01(\x0b\x32\x34.temporal.api.taskqueue.v1.TaskQueueVersionSelectionB\x02\x18\x01\x12\x42\n\x10task_queue_types\x18\x07 \x03(\x0e\x32$.temporal.api.enums.v1.TaskQueueTypeB\x02\x18\x01\x12\x1a\n\x0ereport_pollers\x18\t \x01(\x08\x42\x02\x18\x01\x12$\n\x18report_task_reachability\x18\n \x01(\x08\x42\x02\x18\x01"\xec\x07\n\x19\x44\x65scribeTaskQueueResponse\x12\x36\n\x07pollers\x18\x01 \x03(\x0b\x32%.temporal.api.taskqueue.v1.PollerInfo\x12\x38\n\x05stats\x18\x05 \x01(\x0b\x32).temporal.api.taskqueue.v1.TaskQueueStats\x12q\n\x15stats_by_priority_key\x18\x08 \x03(\x0b\x32R.temporal.api.workflowservice.v1.DescribeTaskQueueResponse.StatsByPriorityKeyEntry\x12K\n\x0fversioning_info\x18\x04 \x01(\x0b\x32\x32.temporal.api.taskqueue.v1.TaskQueueVersioningInfo\x12:\n\x06\x63onfig\x18\x06 \x01(\x0b\x32*.temporal.api.taskqueue.v1.TaskQueueConfig\x12k\n\x14\x65\x66\x66\x65\x63tive_rate_limit\x18\x07 \x01(\x0b\x32M.temporal.api.workflowservice.v1.DescribeTaskQueueResponse.EffectiveRateLimit\x12I\n\x11task_queue_status\x18\x02 \x01(\x0b\x32*.temporal.api.taskqueue.v1.TaskQueueStatusB\x02\x18\x01\x12g\n\rversions_info\x18\x03 \x03(\x0b\x32L.temporal.api.workflowservice.v1.DescribeTaskQueueResponse.VersionsInfoEntryB\x02\x18\x01\x1a\x64\n\x17StatsByPriorityKeyEntry\x12\x0b\n\x03key\x18\x01 \x01(\x05\x12\x38\n\x05value\x18\x02 \x01(\x0b\x32).temporal.api.taskqueue.v1.TaskQueueStats:\x02\x38\x01\x1at\n\x12\x45\x66\x66\x65\x63tiveRateLimit\x12\x1b\n\x13requests_per_second\x18\x01 \x01(\x02\x12\x41\n\x11rate_limit_source\x18\x02 \x01(\x0e\x32&.temporal.api.enums.v1.RateLimitSource\x1a\x64\n\x11VersionsInfoEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12>\n\x05value\x18\x02 \x01(\x0b\x32/.temporal.api.taskqueue.v1.TaskQueueVersionInfo:\x02\x38\x01"\x17\n\x15GetClusterInfoRequest"\xd1\x03\n\x16GetClusterInfoResponse\x12h\n\x11supported_clients\x18\x01 \x03(\x0b\x32M.temporal.api.workflowservice.v1.GetClusterInfoResponse.SupportedClientsEntry\x12\x16\n\x0eserver_version\x18\x02 \x01(\t\x12\x12\n\ncluster_id\x18\x03 \x01(\t\x12:\n\x0cversion_info\x18\x04 \x01(\x0b\x32$.temporal.api.version.v1.VersionInfo\x12\x14\n\x0c\x63luster_name\x18\x05 \x01(\t\x12\x1b\n\x13history_shard_count\x18\x06 \x01(\x05\x12\x19\n\x11persistence_store\x18\x07 \x01(\t\x12\x18\n\x10visibility_store\x18\x08 \x01(\t\x12 \n\x18initial_failover_version\x18\t \x01(\x03\x12"\n\x1a\x66\x61ilover_version_increment\x18\n \x01(\x03\x1a\x37\n\x15SupportedClientsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01"\x16\n\x14GetSystemInfoRequest"\xc1\x04\n\x15GetSystemInfoResponse\x12\x16\n\x0eserver_version\x18\x01 \x01(\t\x12Y\n\x0c\x63\x61pabilities\x18\x02 \x01(\x0b\x32\x43.temporal.api.workflowservice.v1.GetSystemInfoResponse.Capabilities\x1a\xb4\x03\n\x0c\x43\x61pabilities\x12\x1f\n\x17signal_and_query_header\x18\x01 \x01(\x08\x12&\n\x1einternal_error_differentiation\x18\x02 \x01(\x08\x12*\n"activity_failure_include_heartbeat\x18\x03 \x01(\x08\x12\x1a\n\x12supports_schedules\x18\x04 \x01(\x08\x12"\n\x1a\x65ncoded_failure_attributes\x18\x05 \x01(\x08\x12!\n\x19\x62uild_id_based_versioning\x18\x06 \x01(\x08\x12\x13\n\x0bupsert_memo\x18\x07 \x01(\x08\x12\x1c\n\x14\x65\x61ger_workflow_start\x18\x08 \x01(\x08\x12\x14\n\x0csdk_metadata\x18\t \x01(\x08\x12\'\n\x1f\x63ount_group_by_execution_status\x18\n \x01(\x08\x12\r\n\x05nexus\x18\x0b \x01(\x08\x12!\n\x19server_scaled_deployments\x18\x0c \x01(\x08\x12(\n server_scaled_provider_cloud_run\x18\r \x01(\x08"m\n\x1eListTaskQueuePartitionsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x38\n\ntask_queue\x18\x02 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue"\xdf\x01\n\x1fListTaskQueuePartitionsResponse\x12]\n\x1e\x61\x63tivity_task_queue_partitions\x18\x01 \x03(\x0b\x32\x35.temporal.api.taskqueue.v1.TaskQueuePartitionMetadata\x12]\n\x1eworkflow_task_queue_partitions\x18\x02 \x03(\x0b\x32\x35.temporal.api.taskqueue.v1.TaskQueuePartitionMetadata"\xcc\x02\n\x15\x43reateScheduleRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bschedule_id\x18\x02 \x01(\t\x12\x34\n\x08schedule\x18\x03 \x01(\x0b\x32".temporal.api.schedule.v1.Schedule\x12>\n\rinitial_patch\x18\x04 \x01(\x0b\x32\'.temporal.api.schedule.v1.SchedulePatch\x12\x10\n\x08identity\x18\x05 \x01(\t\x12\x12\n\nrequest_id\x18\x06 \x01(\t\x12*\n\x04memo\x18\x07 \x01(\x0b\x32\x1c.temporal.api.common.v1.Memo\x12\x43\n\x11search_attributes\x18\x08 \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes"0\n\x16\x43reateScheduleResponse\x12\x16\n\x0e\x63onflict_token\x18\x01 \x01(\x0c"A\n\x17\x44\x65scribeScheduleRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bschedule_id\x18\x02 \x01(\t"\x8f\x02\n\x18\x44\x65scribeScheduleResponse\x12\x34\n\x08schedule\x18\x01 \x01(\x0b\x32".temporal.api.schedule.v1.Schedule\x12\x34\n\x04info\x18\x02 \x01(\x0b\x32&.temporal.api.schedule.v1.ScheduleInfo\x12*\n\x04memo\x18\x03 \x01(\x0b\x32\x1c.temporal.api.common.v1.Memo\x12\x43\n\x11search_attributes\x18\x04 \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes\x12\x16\n\x0e\x63onflict_token\x18\x05 \x01(\x0c"\xa4\x02\n\x15UpdateScheduleRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bschedule_id\x18\x02 \x01(\t\x12\x34\n\x08schedule\x18\x03 \x01(\x0b\x32".temporal.api.schedule.v1.Schedule\x12\x16\n\x0e\x63onflict_token\x18\x04 \x01(\x0c\x12\x10\n\x08identity\x18\x05 \x01(\t\x12\x12\n\nrequest_id\x18\x06 \x01(\t\x12\x43\n\x11search_attributes\x18\x07 \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes\x12*\n\x04memo\x18\x08 \x01(\x0b\x32\x1c.temporal.api.common.v1.Memo"\x18\n\x16UpdateScheduleResponse"\x9c\x01\n\x14PatchScheduleRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bschedule_id\x18\x02 \x01(\t\x12\x36\n\x05patch\x18\x03 \x01(\x0b\x32\'.temporal.api.schedule.v1.SchedulePatch\x12\x10\n\x08identity\x18\x04 \x01(\t\x12\x12\n\nrequest_id\x18\x05 \x01(\t"\x17\n\x15PatchScheduleResponse"\xa8\x01\n ListScheduleMatchingTimesRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bschedule_id\x18\x02 \x01(\t\x12.\n\nstart_time\x18\x03 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12,\n\x08\x65nd_time\x18\x04 \x01(\x0b\x32\x1a.google.protobuf.Timestamp"S\n!ListScheduleMatchingTimesResponse\x12.\n\nstart_time\x18\x01 \x03(\x0b\x32\x1a.google.protobuf.Timestamp"Q\n\x15\x44\x65leteScheduleRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bschedule_id\x18\x02 \x01(\t\x12\x10\n\x08identity\x18\x03 \x01(\t"\x18\n\x16\x44\x65leteScheduleResponse"l\n\x14ListSchedulesRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x19\n\x11maximum_page_size\x18\x02 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c\x12\r\n\x05query\x18\x04 \x01(\t"p\n\x15ListSchedulesResponse\x12>\n\tschedules\x18\x01 \x03(\x0b\x32+.temporal.api.schedule.v1.ScheduleListEntry\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c"9\n\x15\x43ountSchedulesRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\r\n\x05query\x18\x02 \x01(\t"\xdb\x01\n\x16\x43ountSchedulesResponse\x12\r\n\x05\x63ount\x18\x01 \x01(\x03\x12X\n\x06groups\x18\x02 \x03(\x0b\x32H.temporal.api.workflowservice.v1.CountSchedulesResponse.AggregationGroup\x1aX\n\x10\x41ggregationGroup\x12\x35\n\x0cgroup_values\x18\x01 \x03(\x0b\x32\x1f.temporal.api.common.v1.Payload\x12\r\n\x05\x63ount\x18\x02 \x01(\x03"\x86\x05\n\'UpdateWorkerBuildIdCompatibilityRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x12\n\ntask_queue\x18\x02 \x01(\t\x12-\n#add_new_build_id_in_new_default_set\x18\x03 \x01(\tH\x00\x12\x87\x01\n\x1b\x61\x64\x64_new_compatible_build_id\x18\x04 \x01(\x0b\x32`.temporal.api.workflowservice.v1.UpdateWorkerBuildIdCompatibilityRequest.AddNewCompatibleVersionH\x00\x12!\n\x17promote_set_by_build_id\x18\x05 \x01(\tH\x00\x12%\n\x1bpromote_build_id_within_set\x18\x06 \x01(\tH\x00\x12h\n\nmerge_sets\x18\x07 \x01(\x0b\x32R.temporal.api.workflowservice.v1.UpdateWorkerBuildIdCompatibilityRequest.MergeSetsH\x00\x1ao\n\x17\x41\x64\x64NewCompatibleVersion\x12\x14\n\x0cnew_build_id\x18\x01 \x01(\t\x12$\n\x1c\x65xisting_compatible_build_id\x18\x02 \x01(\t\x12\x18\n\x10make_set_default\x18\x03 \x01(\x08\x1aI\n\tMergeSets\x12\x1c\n\x14primary_set_build_id\x18\x01 \x01(\t\x12\x1e\n\x16secondary_set_build_id\x18\x02 \x01(\tB\x0b\n\toperation"@\n(UpdateWorkerBuildIdCompatibilityResponseJ\x04\x08\x01\x10\x02R\x0eversion_set_id"_\n$GetWorkerBuildIdCompatibilityRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x12\n\ntask_queue\x18\x02 \x01(\t\x12\x10\n\x08max_sets\x18\x03 \x01(\x05"t\n%GetWorkerBuildIdCompatibilityResponse\x12K\n\x12major_version_sets\x18\x01 \x03(\x0b\x32/.temporal.api.taskqueue.v1.CompatibleVersionSet"\xb5\r\n"UpdateWorkerVersioningRulesRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x12\n\ntask_queue\x18\x02 \x01(\t\x12\x16\n\x0e\x63onflict_token\x18\x03 \x01(\x0c\x12\x81\x01\n\x16insert_assignment_rule\x18\x04 \x01(\x0b\x32_.temporal.api.workflowservice.v1.UpdateWorkerVersioningRulesRequest.InsertBuildIdAssignmentRuleH\x00\x12\x83\x01\n\x17replace_assignment_rule\x18\x05 \x01(\x0b\x32`.temporal.api.workflowservice.v1.UpdateWorkerVersioningRulesRequest.ReplaceBuildIdAssignmentRuleH\x00\x12\x81\x01\n\x16\x64\x65lete_assignment_rule\x18\x06 \x01(\x0b\x32_.temporal.api.workflowservice.v1.UpdateWorkerVersioningRulesRequest.DeleteBuildIdAssignmentRuleH\x00\x12\x8c\x01\n\x1c\x61\x64\x64_compatible_redirect_rule\x18\x07 \x01(\x0b\x32\x64.temporal.api.workflowservice.v1.UpdateWorkerVersioningRulesRequest.AddCompatibleBuildIdRedirectRuleH\x00\x12\x94\x01\n replace_compatible_redirect_rule\x18\x08 \x01(\x0b\x32h.temporal.api.workflowservice.v1.UpdateWorkerVersioningRulesRequest.ReplaceCompatibleBuildIdRedirectRuleH\x00\x12\x92\x01\n\x1f\x64\x65lete_compatible_redirect_rule\x18\t \x01(\x0b\x32g.temporal.api.workflowservice.v1.UpdateWorkerVersioningRulesRequest.DeleteCompatibleBuildIdRedirectRuleH\x00\x12l\n\x0f\x63ommit_build_id\x18\n \x01(\x0b\x32Q.temporal.api.workflowservice.v1.UpdateWorkerVersioningRulesRequest.CommitBuildIdH\x00\x1aq\n\x1bInsertBuildIdAssignmentRule\x12\x12\n\nrule_index\x18\x01 \x01(\x05\x12>\n\x04rule\x18\x02 \x01(\x0b\x32\x30.temporal.api.taskqueue.v1.BuildIdAssignmentRule\x1a\x81\x01\n\x1cReplaceBuildIdAssignmentRule\x12\x12\n\nrule_index\x18\x01 \x01(\x05\x12>\n\x04rule\x18\x02 \x01(\x0b\x32\x30.temporal.api.taskqueue.v1.BuildIdAssignmentRule\x12\r\n\x05\x66orce\x18\x03 \x01(\x08\x1a@\n\x1b\x44\x65leteBuildIdAssignmentRule\x12\x12\n\nrule_index\x18\x01 \x01(\x05\x12\r\n\x05\x66orce\x18\x02 \x01(\x08\x1aj\n AddCompatibleBuildIdRedirectRule\x12\x46\n\x04rule\x18\x01 \x01(\x0b\x32\x38.temporal.api.taskqueue.v1.CompatibleBuildIdRedirectRule\x1an\n$ReplaceCompatibleBuildIdRedirectRule\x12\x46\n\x04rule\x18\x01 \x01(\x0b\x32\x38.temporal.api.taskqueue.v1.CompatibleBuildIdRedirectRule\x1a>\n#DeleteCompatibleBuildIdRedirectRule\x12\x17\n\x0fsource_build_id\x18\x01 \x01(\t\x1a\x37\n\rCommitBuildId\x12\x17\n\x0ftarget_build_id\x18\x01 \x01(\t\x12\r\n\x05\x66orce\x18\x02 \x01(\x08\x42\x0b\n\toperation"\xfc\x01\n#UpdateWorkerVersioningRulesResponse\x12U\n\x10\x61ssignment_rules\x18\x01 \x03(\x0b\x32;.temporal.api.taskqueue.v1.TimestampedBuildIdAssignmentRule\x12\x66\n\x19\x63ompatible_redirect_rules\x18\x02 \x03(\x0b\x32\x43.temporal.api.taskqueue.v1.TimestampedCompatibleBuildIdRedirectRule\x12\x16\n\x0e\x63onflict_token\x18\x03 \x01(\x0c"H\n\x1fGetWorkerVersioningRulesRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x12\n\ntask_queue\x18\x02 \x01(\t"\xf9\x01\n GetWorkerVersioningRulesResponse\x12U\n\x10\x61ssignment_rules\x18\x01 \x03(\x0b\x32;.temporal.api.taskqueue.v1.TimestampedBuildIdAssignmentRule\x12\x66\n\x19\x63ompatible_redirect_rules\x18\x02 \x03(\x0b\x32\x43.temporal.api.taskqueue.v1.TimestampedCompatibleBuildIdRedirectRule\x12\x16\n\x0e\x63onflict_token\x18\x03 \x01(\x0c"\x9c\x01\n GetWorkerTaskReachabilityRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x11\n\tbuild_ids\x18\x02 \x03(\t\x12\x13\n\x0btask_queues\x18\x03 \x03(\t\x12=\n\x0creachability\x18\x04 \x01(\x0e\x32\'.temporal.api.enums.v1.TaskReachability"r\n!GetWorkerTaskReachabilityResponse\x12M\n\x15\x62uild_id_reachability\x18\x01 \x03(\x0b\x32..temporal.api.taskqueue.v1.BuildIdReachability"\x85\x02\n\x1eUpdateWorkflowExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x45\n\x12workflow_execution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x1e\n\x16\x66irst_execution_run_id\x18\x03 \x01(\t\x12\x37\n\x0bwait_policy\x18\x04 \x01(\x0b\x32".temporal.api.update.v1.WaitPolicy\x12\x30\n\x07request\x18\x05 \x01(\x0b\x32\x1f.temporal.api.update.v1.Request"\x83\x02\n\x1fUpdateWorkflowExecutionResponse\x12\x35\n\nupdate_ref\x18\x01 \x01(\x0b\x32!.temporal.api.update.v1.UpdateRef\x12\x30\n\x07outcome\x18\x02 \x01(\x0b\x32\x1f.temporal.api.update.v1.Outcome\x12K\n\x05stage\x18\x03 \x01(\x0e\x32<.temporal.api.enums.v1.UpdateWorkflowExecutionLifecycleStage\x12*\n\x04link\x18\x04 \x01(\x0b\x32\x1c.temporal.api.common.v1.Link"\xd6\n\n\x1aStartBatchOperationRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x18\n\x10visibility_query\x18\x02 \x01(\t\x12\x0e\n\x06job_id\x18\x03 \x01(\t\x12\x0e\n\x06reason\x18\x04 \x01(\t\x12\x41\n\nexecutions\x18\x05 \x03(\x0b\x32).temporal.api.common.v1.WorkflowExecutionB\x02\x18\x01\x12<\n\x11target_executions\x18\x16 \x03(\x0b\x32!.temporal.api.common.v1.Execution\x12!\n\x19max_operations_per_second\x18\x06 \x01(\x02\x12Q\n\x15termination_operation\x18\n \x01(\x0b\x32\x30.temporal.api.batch.v1.BatchOperationTerminationH\x00\x12G\n\x10signal_operation\x18\x0b \x01(\x0b\x32+.temporal.api.batch.v1.BatchOperationSignalH\x00\x12S\n\x16\x63\x61ncellation_operation\x18\x0c \x01(\x0b\x32\x31.temporal.api.batch.v1.BatchOperationCancellationH\x00\x12K\n\x12\x64\x65letion_operation\x18\r \x01(\x0b\x32-.temporal.api.batch.v1.BatchOperationDeletionH\x00\x12\x45\n\x0freset_operation\x18\x0e \x01(\x0b\x32*.temporal.api.batch.v1.BatchOperationResetH\x00\x12p\n!update_workflow_options_operation\x18\x0f \x01(\x0b\x32\x43.temporal.api.batch.v1.BatchOperationUpdateWorkflowExecutionOptionsH\x00\x12^\n\x1cunpause_activities_operation\x18\x10 \x01(\x0b\x32\x36.temporal.api.batch.v1.BatchOperationUnpauseActivitiesH\x00\x12Z\n\x1areset_activities_operation\x18\x11 \x01(\x0b\x32\x34.temporal.api.batch.v1.BatchOperationResetActivitiesH\x00\x12g\n!update_activity_options_operation\x18\x12 \x01(\x0b\x32:.temporal.api.batch.v1.BatchOperationUpdateActivityOptionsH\x00\x12\\\n\x1b\x63\x61ncel_activities_operation\x18\x13 \x01(\x0b\x32\x35.temporal.api.batch.v1.BatchOperationCancelActivitiesH\x00\x12\x62\n\x1eterminate_activities_operation\x18\x14 \x01(\x0b\x32\x38.temporal.api.batch.v1.BatchOperationTerminateActivitiesH\x00\x12\\\n\x1b\x64\x65lete_activities_operation\x18\x15 \x01(\x0b\x32\x35.temporal.api.batch.v1.BatchOperationDeleteActivitiesH\x00\x42\x0b\n\toperation"\x1d\n\x1bStartBatchOperationResponse"`\n\x19StopBatchOperationRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x0e\n\x06job_id\x18\x02 \x01(\t\x12\x0e\n\x06reason\x18\x03 \x01(\t\x12\x10\n\x08identity\x18\x04 \x01(\t"\x1c\n\x1aStopBatchOperationResponse"B\n\x1d\x44\x65scribeBatchOperationRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x0e\n\x06job_id\x18\x02 \x01(\t"\xd8\x03\n\x1e\x44\x65scribeBatchOperationResponse\x12\x41\n\x0eoperation_type\x18\x01 \x01(\x0e\x32).temporal.api.enums.v1.BatchOperationType\x12\x0e\n\x06job_id\x18\x02 \x01(\t\x12\x39\n\x05state\x18\x03 \x01(\x0e\x32*.temporal.api.enums.v1.BatchOperationState\x12.\n\nstart_time\x18\x04 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12.\n\nclose_time\x18\x05 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x1d\n\x15total_operation_count\x18\x06 \x01(\x03\x12 \n\x18\x63omplete_operation_count\x18\x07 \x01(\x03\x12\x1f\n\x17\x66\x61ilure_operation_count\x18\x08 \x01(\x03\x12\x10\n\x08identity\x18\t \x01(\t\x12\x0e\n\x06reason\x18\n \x01(\t\x12\r\n\x05query\x18\x0b \x01(\t\x12\x35\n\nexecutions\x18\x0c \x03(\x0b\x32!.temporal.api.common.v1.Execution"[\n\x1aListBatchOperationsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x11\n\tpage_size\x18\x02 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c"y\n\x1bListBatchOperationsResponse\x12\x41\n\x0eoperation_info\x18\x01 \x03(\x0b\x32).temporal.api.batch.v1.BatchOperationInfo\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c"\xb9\x01\n"PollWorkflowExecutionUpdateRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x35\n\nupdate_ref\x18\x02 \x01(\x0b\x32!.temporal.api.update.v1.UpdateRef\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x37\n\x0bwait_policy\x18\x04 \x01(\x0b\x32".temporal.api.update.v1.WaitPolicy"\xdb\x01\n#PollWorkflowExecutionUpdateResponse\x12\x30\n\x07outcome\x18\x01 \x01(\x0b\x32\x1f.temporal.api.update.v1.Outcome\x12K\n\x05stage\x18\x02 \x01(\x0e\x32<.temporal.api.enums.v1.UpdateWorkflowExecutionLifecycleStage\x12\x35\n\nupdate_ref\x18\x03 \x01(\x0b\x32!.temporal.api.update.v1.UpdateRef"\xa0\x03\n\x19PollNexusTaskQueueRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x38\n\ntask_queue\x18\x03 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12\x17\n\x0fpoller_group_id\x18\t \x01(\t\x12\x10\n\x08identity\x18\x02 \x01(\t\x12\x1b\n\x13worker_instance_key\x18\x08 \x01(\t\x12Z\n\x1bworker_version_capabilities\x18\x04 \x01(\x0b\x32\x31.temporal.api.common.v1.WorkerVersionCapabilitiesB\x02\x18\x01\x12O\n\x12\x64\x65ployment_options\x18\x06 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentOptions\x12\x41\n\x10worker_heartbeat\x18\x07 \x03(\x0b\x32\'.temporal.api.worker.v1.WorkerHeartbeat"\xe2\x02\n\x1aPollNexusTaskQueueResponse\x12\x12\n\ntask_token\x18\x01 \x01(\x0c\x12/\n\x07request\x18\x02 \x01(\x0b\x32\x1e.temporal.api.nexus.v1.Request\x12Q\n\x17poller_scaling_decision\x18\x03 \x01(\x0b\x32\x30.temporal.api.taskqueue.v1.PollerScalingDecision\x12\x17\n\x0fpoller_group_id\x18\x04 \x01(\t\x12J\n\x12poller_group_infos\x18\x05 \x03(\x0b\x32*.temporal.api.taskqueue.v1.PollerGroupInfoB\x02\x18\x01\x12G\n\x12poller_groups_info\x18\x06 \x01(\x0b\x32+.temporal.api.taskqueue.v1.PollerGroupsInfo"\xa7\x01\n RespondNexusTaskCompletedRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x10\n\x08identity\x18\x02 \x01(\t\x12\x12\n\ntask_token\x18\x03 \x01(\x0c\x12\x31\n\x08response\x18\x04 \x01(\x0b\x32\x1f.temporal.api.nexus.v1.Response\x12\x17\n\x0fpoller_group_id\x18\x05 \x01(\t"#\n!RespondNexusTaskCompletedResponse"\xdc\x01\n\x1dRespondNexusTaskFailedRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x10\n\x08identity\x18\x02 \x01(\t\x12\x12\n\ntask_token\x18\x03 \x01(\x0c\x12\x36\n\x05\x65rror\x18\x04 \x01(\x0b\x32#.temporal.api.nexus.v1.HandlerErrorB\x02\x18\x01\x12\x31\n\x07\x66\x61ilure\x18\x05 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12\x17\n\x0fpoller_group_id\x18\x06 \x01(\t" \n\x1eRespondNexusTaskFailedResponse"\xf4\x02\n\x1c\x45xecuteMultiOperationRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12[\n\noperations\x18\x02 \x03(\x0b\x32G.temporal.api.workflowservice.v1.ExecuteMultiOperationRequest.Operation\x12\x13\n\x0bresource_id\x18\x03 \x01(\t\x1a\xce\x01\n\tOperation\x12X\n\x0estart_workflow\x18\x01 \x01(\x0b\x32>.temporal.api.workflowservice.v1.StartWorkflowExecutionRequestH\x00\x12Z\n\x0fupdate_workflow\x18\x02 \x01(\x0b\x32?.temporal.api.workflowservice.v1.UpdateWorkflowExecutionRequestH\x00\x42\x0b\n\toperation"\xcc\x02\n\x1d\x45xecuteMultiOperationResponse\x12Z\n\tresponses\x18\x01 \x03(\x0b\x32G.temporal.api.workflowservice.v1.ExecuteMultiOperationResponse.Response\x1a\xce\x01\n\x08Response\x12Y\n\x0estart_workflow\x18\x01 \x01(\x0b\x32?.temporal.api.workflowservice.v1.StartWorkflowExecutionResponseH\x00\x12[\n\x0fupdate_workflow\x18\x02 \x01(\x0b\x32@.temporal.api.workflowservice.v1.UpdateWorkflowExecutionResponseH\x00\x42\n\n\x08response"\xd0\x02\n\x1cUpdateActivityOptionsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12<\n\texecution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x43\n\x10\x61\x63tivity_options\x18\x04 \x01(\x0b\x32).temporal.api.activity.v1.ActivityOptions\x12/\n\x0bupdate_mask\x18\x05 \x01(\x0b\x32\x1a.google.protobuf.FieldMask\x12\x0c\n\x02id\x18\x06 \x01(\tH\x00\x12\x0e\n\x04type\x18\x07 \x01(\tH\x00\x12\x13\n\tmatch_all\x18\t \x01(\x08H\x00\x12\x18\n\x10restore_original\x18\x08 \x01(\x08\x42\n\n\x08\x61\x63tivity"\xbf\x02\n%UpdateActivityExecutionOptionsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12\x13\n\x0b\x61\x63tivity_id\x18\x03 \x01(\t\x12\x0e\n\x06run_id\x18\x04 \x01(\t\x12\x10\n\x08identity\x18\x05 \x01(\t\x12\x43\n\x10\x61\x63tivity_options\x18\x06 \x01(\x0b\x32).temporal.api.activity.v1.ActivityOptions\x12/\n\x0bupdate_mask\x18\x07 \x01(\x0b\x32\x1a.google.protobuf.FieldMask\x12\x18\n\x10restore_original\x18\x08 \x01(\x08\x12\x13\n\x0bresource_id\x18\t \x01(\t\x12\x12\n\nrequest_id\x18\n \x01(\t"d\n\x1dUpdateActivityOptionsResponse\x12\x43\n\x10\x61\x63tivity_options\x18\x01 \x01(\x0b\x32).temporal.api.activity.v1.ActivityOptions"m\n&UpdateActivityExecutionOptionsResponse\x12\x43\n\x10\x61\x63tivity_options\x18\x01 \x01(\x0b\x32).temporal.api.activity.v1.ActivityOptions"\xc7\x01\n\x14PauseActivityRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12<\n\texecution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x0c\n\x02id\x18\x04 \x01(\tH\x00\x12\x0e\n\x04type\x18\x05 \x01(\tH\x00\x12\x0e\n\x06reason\x18\x06 \x01(\t\x12\x12\n\nrequest_id\x18\x07 \x01(\tB\n\n\x08\x61\x63tivity"\xb7\x01\n\x1dPauseActivityExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12\x13\n\x0b\x61\x63tivity_id\x18\x03 \x01(\t\x12\x0e\n\x06run_id\x18\x04 \x01(\t\x12\x10\n\x08identity\x18\x05 \x01(\t\x12\x0e\n\x06reason\x18\x06 \x01(\t\x12\x13\n\x0bresource_id\x18\x07 \x01(\t\x12\x12\n\nrequest_id\x18\x08 \x01(\t"\x17\n\x15PauseActivityResponse" \n\x1ePauseActivityExecutionResponse"\x98\x02\n\x16UnpauseActivityRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12<\n\texecution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x0c\n\x02id\x18\x04 \x01(\tH\x00\x12\x0e\n\x04type\x18\x05 \x01(\tH\x00\x12\x15\n\x0bunpause_all\x18\x06 \x01(\x08H\x00\x12\x16\n\x0ereset_attempts\x18\x07 \x01(\x08\x12\x17\n\x0freset_heartbeat\x18\x08 \x01(\x08\x12)\n\x06jitter\x18\t \x01(\x0b\x32\x19.google.protobuf.DurationB\n\n\x08\x61\x63tivity"\x91\x02\n\x1fUnpauseActivityExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12\x13\n\x0b\x61\x63tivity_id\x18\x03 \x01(\t\x12\x0e\n\x06run_id\x18\x04 \x01(\t\x12\x10\n\x08identity\x18\x05 \x01(\t\x12\x0e\n\x06reason\x18\x08 \x01(\t\x12)\n\x06jitter\x18\t \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x13\n\x0bresource_id\x18\n \x01(\t\x12\x12\n\nrequest_id\x18\x0b \x01(\tJ\x04\x08\x06\x10\x07J\x04\x08\x07\x10\x08R\x0ereset_attemptsR\x0freset_heartbeat"\x19\n\x17UnpauseActivityResponse""\n UnpauseActivityExecutionResponse"\xb3\x02\n\x14ResetActivityRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12<\n\texecution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x0c\n\x02id\x18\x04 \x01(\tH\x00\x12\x0e\n\x04type\x18\x05 \x01(\tH\x00\x12\x13\n\tmatch_all\x18\n \x01(\x08H\x00\x12\x17\n\x0freset_heartbeat\x18\x06 \x01(\x08\x12\x13\n\x0bkeep_paused\x18\x07 \x01(\x08\x12)\n\x06jitter\x18\x08 \x01(\x0b\x32\x19.google.protobuf.Duration\x12 \n\x18restore_original_options\x18\t \x01(\x08\x42\n\n\x08\x61\x63tivity"\x89\x02\n\x1dResetActivityExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12\x13\n\x0b\x61\x63tivity_id\x18\x03 \x01(\t\x12\x0e\n\x06run_id\x18\x04 \x01(\t\x12\x10\n\x08identity\x18\x05 \x01(\t\x12\x13\n\x0bkeep_paused\x18\x06 \x01(\x08\x12)\n\x06jitter\x18\x07 \x01(\x0b\x32\x19.google.protobuf.Duration\x12 \n\x18restore_original_options\x18\x08 \x01(\x08\x12\x13\n\x0bresource_id\x18\t \x01(\t\x12\x12\n\nrequest_id\x18\n \x01(\t"\x17\n\x15ResetActivityResponse" \n\x1eResetActivityExecutionResponse"\x9c\x02\n%UpdateWorkflowExecutionOptionsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x45\n\x12workflow_execution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12V\n\x1aworkflow_execution_options\x18\x03 \x01(\x0b\x32\x32.temporal.api.workflow.v1.WorkflowExecutionOptions\x12/\n\x0bupdate_mask\x18\x04 \x01(\x0b\x32\x1a.google.protobuf.FieldMask\x12\x10\n\x08identity\x18\x05 \x01(\t"\xb1\x01\n&UpdateWorkflowExecutionOptionsResponse\x12V\n\x1aworkflow_execution_options\x18\x01 \x01(\x0b\x32\x32.temporal.api.workflow.v1.WorkflowExecutionOptions\x12/\n\x0bupdate_time\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.Timestamp"j\n\x19\x44\x65scribeDeploymentRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12:\n\ndeployment\x18\x02 \x01(\x0b\x32&.temporal.api.deployment.v1.Deployment"a\n\x1a\x44\x65scribeDeploymentResponse\x12\x43\n\x0f\x64\x65ployment_info\x18\x01 \x01(\x0b\x32*.temporal.api.deployment.v1.DeploymentInfo"\xc2\x01\n&DescribeWorkerDeploymentVersionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x07version\x18\x02 \x01(\tB\x02\x18\x01\x12O\n\x12\x64\x65ployment_version\x18\x03 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersion\x12\x1f\n\x17report_task_queue_stats\x18\x04 \x01(\x08"\x8c\x05\n\'DescribeWorkerDeploymentVersionResponse\x12_\n\x1eworker_deployment_version_info\x18\x01 \x01(\x0b\x32\x37.temporal.api.deployment.v1.WorkerDeploymentVersionInfo\x12v\n\x13version_task_queues\x18\x02 \x03(\x0b\x32Y.temporal.api.workflowservice.v1.DescribeWorkerDeploymentVersionResponse.VersionTaskQueue\x1a\x87\x03\n\x10VersionTaskQueue\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x32\n\x04type\x18\x02 \x01(\x0e\x32$.temporal.api.enums.v1.TaskQueueType\x12\x38\n\x05stats\x18\x03 \x01(\x0b\x32).temporal.api.taskqueue.v1.TaskQueueStats\x12\x90\x01\n\x15stats_by_priority_key\x18\x04 \x03(\x0b\x32q.temporal.api.workflowservice.v1.DescribeWorkerDeploymentVersionResponse.VersionTaskQueue.StatsByPriorityKeyEntry\x1a\x64\n\x17StatsByPriorityKeyEntry\x12\x0b\n\x03key\x18\x01 \x01(\x05\x12\x38\n\x05value\x18\x02 \x01(\x0b\x32).temporal.api.taskqueue.v1.TaskQueueStats:\x02\x38\x01"M\n\x1f\x44\x65scribeWorkerDeploymentRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x17\n\x0f\x64\x65ployment_name\x18\x02 \x01(\t"\x8c\x01\n DescribeWorkerDeploymentResponse\x12\x16\n\x0e\x63onflict_token\x18\x01 \x01(\x0c\x12P\n\x16worker_deployment_info\x18\x02 \x01(\x0b\x32\x30.temporal.api.deployment.v1.WorkerDeploymentInfo"l\n\x16ListDeploymentsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x11\n\tpage_size\x18\x02 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c\x12\x13\n\x0bseries_name\x18\x04 \x01(\t"w\n\x17ListDeploymentsResponse\x12\x17\n\x0fnext_page_token\x18\x01 \x01(\x0c\x12\x43\n\x0b\x64\x65ployments\x18\x02 \x03(\x0b\x32..temporal.api.deployment.v1.DeploymentListInfo"\xcd\x01\n\x1bSetCurrentDeploymentRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12:\n\ndeployment\x18\x02 \x01(\x0b\x32&.temporal.api.deployment.v1.Deployment\x12\x10\n\x08identity\x18\x03 \x01(\t\x12M\n\x0fupdate_metadata\x18\x04 \x01(\x0b\x32\x34.temporal.api.deployment.v1.UpdateDeploymentMetadata"\xb9\x01\n\x1cSetCurrentDeploymentResponse\x12K\n\x17\x63urrent_deployment_info\x18\x01 \x01(\x0b\x32*.temporal.api.deployment.v1.DeploymentInfo\x12L\n\x18previous_deployment_info\x18\x02 \x01(\x0b\x32*.temporal.api.deployment.v1.DeploymentInfo"\xe5\x01\n(SetWorkerDeploymentCurrentVersionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x17\n\x0f\x64\x65ployment_name\x18\x02 \x01(\t\x12\x13\n\x07version\x18\x03 \x01(\tB\x02\x18\x01\x12\x10\n\x08\x62uild_id\x18\x07 \x01(\t\x12\x16\n\x0e\x63onflict_token\x18\x04 \x01(\x0c\x12\x10\n\x08identity\x18\x05 \x01(\t\x12"\n\x1aignore_missing_task_queues\x18\x06 \x01(\x08\x12\x18\n\x10\x61llow_no_pollers\x18\t \x01(\x08"\xbf\x01\n)SetWorkerDeploymentCurrentVersionResponse\x12\x16\n\x0e\x63onflict_token\x18\x01 \x01(\x0c\x12\x1c\n\x10previous_version\x18\x02 \x01(\tB\x02\x18\x01\x12\\\n\x1bprevious_deployment_version\x18\x03 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersionB\x02\x18\x01"\xf9\x01\n(SetWorkerDeploymentRampingVersionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x17\n\x0f\x64\x65ployment_name\x18\x02 \x01(\t\x12\x13\n\x07version\x18\x03 \x01(\tB\x02\x18\x01\x12\x10\n\x08\x62uild_id\x18\x08 \x01(\t\x12\x12\n\npercentage\x18\x04 \x01(\x02\x12\x16\n\x0e\x63onflict_token\x18\x05 \x01(\x0c\x12\x10\n\x08identity\x18\x06 \x01(\t\x12"\n\x1aignore_missing_task_queues\x18\x07 \x01(\x08\x12\x18\n\x10\x61llow_no_pollers\x18\n \x01(\x08"\xe0\x01\n)SetWorkerDeploymentRampingVersionResponse\x12\x16\n\x0e\x63onflict_token\x18\x01 \x01(\x0c\x12\x1c\n\x10previous_version\x18\x02 \x01(\tB\x02\x18\x01\x12\\\n\x1bprevious_deployment_version\x18\x04 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersionB\x02\x18\x01\x12\x1f\n\x13previous_percentage\x18\x03 \x01(\x02\x42\x02\x18\x01"q\n\x1d\x43reateWorkerDeploymentRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x17\n\x0f\x64\x65ployment_name\x18\x02 \x01(\t\x12\x10\n\x08identity\x18\x04 \x01(\t\x12\x12\n\nrequest_id\x18\x05 \x01(\t"8\n\x1e\x43reateWorkerDeploymentResponse\x12\x16\n\x0e\x63onflict_token\x18\x01 \x01(\x0c"]\n\x1cListWorkerDeploymentsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x11\n\tpage_size\x18\x02 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c"\x9f\x05\n\x1dListWorkerDeploymentsResponse\x12\x17\n\x0fnext_page_token\x18\x01 \x01(\x0c\x12r\n\x12worker_deployments\x18\x02 \x03(\x0b\x32V.temporal.api.workflowservice.v1.ListWorkerDeploymentsResponse.WorkerDeploymentSummary\x1a\xf0\x03\n\x17WorkerDeploymentSummary\x12\x0c\n\x04name\x18\x01 \x01(\t\x12/\n\x0b\x63reate_time\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x41\n\x0erouting_config\x18\x03 \x01(\x0b\x32).temporal.api.deployment.v1.RoutingConfig\x12o\n\x16latest_version_summary\x18\x04 \x01(\x0b\x32O.temporal.api.deployment.v1.WorkerDeploymentInfo.WorkerDeploymentVersionSummary\x12p\n\x17\x63urrent_version_summary\x18\x05 \x01(\x0b\x32O.temporal.api.deployment.v1.WorkerDeploymentInfo.WorkerDeploymentVersionSummary\x12p\n\x17ramping_version_summary\x18\x06 \x01(\x0b\x32O.temporal.api.deployment.v1.WorkerDeploymentInfo.WorkerDeploymentVersionSummary"\xf0\x01\n$CreateWorkerDeploymentVersionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12O\n\x12\x64\x65ployment_version\x18\x02 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersion\x12>\n\x0e\x63ompute_config\x18\x04 \x01(\x0b\x32&.temporal.api.compute.v1.ComputeConfig\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x12\n\nrequest_id\x18\x05 \x01(\t"\'\n%CreateWorkerDeploymentVersionResponse"\xc8\x01\n$DeleteWorkerDeploymentVersionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x07version\x18\x02 \x01(\tB\x02\x18\x01\x12O\n\x12\x64\x65ployment_version\x18\x05 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersion\x12\x15\n\rskip_drainage\x18\x03 \x01(\x08\x12\x10\n\x08identity\x18\x04 \x01(\t"\'\n%DeleteWorkerDeploymentVersionResponse"]\n\x1d\x44\x65leteWorkerDeploymentRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x17\n\x0f\x64\x65ployment_name\x18\x02 \x01(\t\x12\x10\n\x08identity\x18\x03 \x01(\t" \n\x1e\x44\x65leteWorkerDeploymentResponse"\x84\x04\n1UpdateWorkerDeploymentVersionComputeConfigRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12O\n\x12\x64\x65ployment_version\x18\x02 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersion\x12\x99\x01\n\x1d\x63ompute_config_scaling_groups\x18\x06 \x03(\x0b\x32r.temporal.api.workflowservice.v1.UpdateWorkerDeploymentVersionComputeConfigRequest.ComputeConfigScalingGroupsEntry\x12,\n$remove_compute_config_scaling_groups\x18\x07 \x03(\t\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x12\n\nrequest_id\x18\x04 \x01(\t\x1a{\n\x1f\x43omputeConfigScalingGroupsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12G\n\x05value\x18\x02 \x01(\x0b\x32\x38.temporal.api.compute.v1.ComputeConfigScalingGroupUpdate:\x02\x38\x01"4\n2UpdateWorkerDeploymentVersionComputeConfigResponse"\xf4\x03\n3ValidateWorkerDeploymentVersionComputeConfigRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12O\n\x12\x64\x65ployment_version\x18\x02 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersion\x12\x9b\x01\n\x1d\x63ompute_config_scaling_groups\x18\x06 \x03(\x0b\x32t.temporal.api.workflowservice.v1.ValidateWorkerDeploymentVersionComputeConfigRequest.ComputeConfigScalingGroupsEntry\x12,\n$remove_compute_config_scaling_groups\x18\x07 \x03(\t\x12\x10\n\x08identity\x18\x03 \x01(\t\x1a{\n\x1f\x43omputeConfigScalingGroupsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12G\n\x05value\x18\x02 \x01(\x0b\x32\x38.temporal.api.compute.v1.ComputeConfigScalingGroupUpdate:\x02\x38\x01"6\n4ValidateWorkerDeploymentVersionComputeConfigResponse"\xa2\x03\n,UpdateWorkerDeploymentVersionMetadataRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x07version\x18\x02 \x01(\tB\x02\x18\x01\x12O\n\x12\x64\x65ployment_version\x18\x05 \x01(\x0b\x32\x33.temporal.api.deployment.v1.WorkerDeploymentVersion\x12x\n\x0eupsert_entries\x18\x03 \x03(\x0b\x32`.temporal.api.workflowservice.v1.UpdateWorkerDeploymentVersionMetadataRequest.UpsertEntriesEntry\x12\x16\n\x0eremove_entries\x18\x04 \x03(\t\x12\x10\n\x08identity\x18\x06 \x01(\t\x1aU\n\x12UpsertEntriesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12.\n\x05value\x18\x02 \x01(\x0b\x32\x1f.temporal.api.common.v1.Payload:\x02\x38\x01"n\n-UpdateWorkerDeploymentVersionMetadataResponse\x12=\n\x08metadata\x18\x01 \x01(\x0b\x32+.temporal.api.deployment.v1.VersionMetadata"\xbd\x01\n!SetWorkerDeploymentManagerRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x17\n\x0f\x64\x65ployment_name\x18\x02 \x01(\t\x12\x1a\n\x10manager_identity\x18\x03 \x01(\tH\x00\x12\x0e\n\x04self\x18\x04 \x01(\x08H\x00\x12\x16\n\x0e\x63onflict_token\x18\x05 \x01(\x0c\x12\x10\n\x08identity\x18\x06 \x01(\tB\x16\n\x14new_manager_identity"c\n"SetWorkerDeploymentManagerResponse\x12\x16\n\x0e\x63onflict_token\x18\x01 \x01(\x0c\x12%\n\x19previous_manager_identity\x18\x02 \x01(\tB\x02\x18\x01"E\n\x1bGetCurrentDeploymentRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bseries_name\x18\x02 \x01(\t"k\n\x1cGetCurrentDeploymentResponse\x12K\n\x17\x63urrent_deployment_info\x18\x01 \x01(\x0b\x32*.temporal.api.deployment.v1.DeploymentInfo"q\n GetDeploymentReachabilityRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12:\n\ndeployment\x18\x02 \x01(\x0b\x32&.temporal.api.deployment.v1.Deployment"\xe3\x01\n!GetDeploymentReachabilityResponse\x12\x43\n\x0f\x64\x65ployment_info\x18\x01 \x01(\x0b\x32*.temporal.api.deployment.v1.DeploymentInfo\x12\x43\n\x0creachability\x18\x02 \x01(\x0e\x32-.temporal.api.enums.v1.DeploymentReachability\x12\x34\n\x10last_update_time\x18\x03 \x01(\x0b\x32\x1a.google.protobuf.Timestamp"\xb4\x01\n\x19\x43reateWorkflowRuleRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x35\n\x04spec\x18\x02 \x01(\x0b\x32\'.temporal.api.rules.v1.WorkflowRuleSpec\x12\x12\n\nforce_scan\x18\x03 \x01(\x08\x12\x12\n\nrequest_id\x18\x04 \x01(\t\x12\x10\n\x08identity\x18\x05 \x01(\t\x12\x13\n\x0b\x64\x65scription\x18\x06 \x01(\t"_\n\x1a\x43reateWorkflowRuleResponse\x12\x31\n\x04rule\x18\x01 \x01(\x0b\x32#.temporal.api.rules.v1.WorkflowRule\x12\x0e\n\x06job_id\x18\x02 \x01(\t"A\n\x1b\x44\x65scribeWorkflowRuleRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x0f\n\x07rule_id\x18\x02 \x01(\t"Q\n\x1c\x44\x65scribeWorkflowRuleResponse\x12\x31\n\x04rule\x18\x01 \x01(\x0b\x32#.temporal.api.rules.v1.WorkflowRule"?\n\x19\x44\x65leteWorkflowRuleRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x0f\n\x07rule_id\x18\x02 \x01(\t"\x1c\n\x1a\x44\x65leteWorkflowRuleResponse"F\n\x18ListWorkflowRulesRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c"h\n\x19ListWorkflowRulesResponse\x12\x32\n\x05rules\x18\x01 \x03(\x0b\x32#.temporal.api.rules.v1.WorkflowRule\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c"\xce\x01\n\x1aTriggerWorkflowRuleRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12<\n\texecution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x0c\n\x02id\x18\x04 \x01(\tH\x00\x12\x37\n\x04spec\x18\x05 \x01(\x0b\x32\'.temporal.api.rules.v1.WorkflowRuleSpecH\x00\x12\x10\n\x08identity\x18\x03 \x01(\tB\x06\n\x04rule".\n\x1bTriggerWorkflowRuleResponse\x12\x0f\n\x07\x61pplied\x18\x01 \x01(\x08"\x9b\x01\n\x1cRecordWorkerHeartbeatRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x10\n\x08identity\x18\x02 \x01(\t\x12\x41\n\x10worker_heartbeat\x18\x03 \x03(\x0b\x32\'.temporal.api.worker.v1.WorkerHeartbeat\x12\x13\n\x0bresource_id\x18\x04 \x01(\t"\x1f\n\x1dRecordWorkerHeartbeatResponse"\x82\x01\n\x12ListWorkersRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x11\n\tpage_size\x18\x02 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c\x12\r\n\x05query\x18\x04 \x01(\t\x12\x1e\n\x16include_system_workers\x18\x05 \x01(\x08"\xa5\x01\n\x13ListWorkersResponse\x12<\n\x0cworkers_info\x18\x01 \x03(\x0b\x32".temporal.api.worker.v1.WorkerInfoB\x02\x18\x01\x12\x37\n\x07workers\x18\x03 \x03(\x0b\x32&.temporal.api.worker.v1.WorkerListInfo\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c"\xd5\x05\n\x1cUpdateTaskQueueConfigRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x10\n\x08identity\x18\x02 \x01(\t\x12\x12\n\ntask_queue\x18\x03 \x01(\t\x12=\n\x0ftask_queue_type\x18\x04 \x01(\x0e\x32$.temporal.api.enums.v1.TaskQueueType\x12n\n\x17update_queue_rate_limit\x18\x05 \x01(\x0b\x32M.temporal.api.workflowservice.v1.UpdateTaskQueueConfigRequest.RateLimitUpdate\x12}\n&update_fairness_key_rate_limit_default\x18\x06 \x01(\x0b\x32M.temporal.api.workflowservice.v1.UpdateTaskQueueConfigRequest.RateLimitUpdate\x12\x84\x01\n\x1dset_fairness_weight_overrides\x18\x07 \x03(\x0b\x32].temporal.api.workflowservice.v1.UpdateTaskQueueConfigRequest.SetFairnessWeightOverridesEntry\x12\'\n\x1funset_fairness_weight_overrides\x18\x08 \x03(\t\x1a[\n\x0fRateLimitUpdate\x12\x38\n\nrate_limit\x18\x01 \x01(\x0b\x32$.temporal.api.taskqueue.v1.RateLimit\x12\x0e\n\x06reason\x18\x02 \x01(\t\x1a\x41\n\x1fSetFairnessWeightOverridesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\x02:\x02\x38\x01"[\n\x1dUpdateTaskQueueConfigResponse\x12:\n\x06\x63onfig\x18\x01 \x01(\x0b\x32*.temporal.api.taskqueue.v1.TaskQueueConfig"\x9e\x01\n\x18\x46\x65tchWorkerConfigRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x10\n\x08identity\x18\x02 \x01(\t\x12\x0e\n\x06reason\x18\x03 \x01(\t\x12\x38\n\x08selector\x18\x06 \x01(\x0b\x32&.temporal.api.common.v1.WorkerSelector\x12\x13\n\x0bresource_id\x18\x07 \x01(\t"U\n\x19\x46\x65tchWorkerConfigResponse\x12\x38\n\rworker_config\x18\x01 \x01(\x0b\x32!.temporal.api.sdk.v1.WorkerConfig"\x8a\x02\n\x19UpdateWorkerConfigRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x10\n\x08identity\x18\x02 \x01(\t\x12\x0e\n\x06reason\x18\x03 \x01(\t\x12\x38\n\rworker_config\x18\x04 \x01(\x0b\x32!.temporal.api.sdk.v1.WorkerConfig\x12/\n\x0bupdate_mask\x18\x05 \x01(\x0b\x32\x1a.google.protobuf.FieldMask\x12\x38\n\x08selector\x18\x06 \x01(\x0b\x32&.temporal.api.common.v1.WorkerSelector\x12\x13\n\x0bresource_id\x18\x07 \x01(\t"d\n\x1aUpdateWorkerConfigResponse\x12:\n\rworker_config\x18\x01 \x01(\x0b\x32!.temporal.api.sdk.v1.WorkerConfigH\x00\x42\n\n\x08response"G\n\x15\x44\x65scribeWorkerRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x1b\n\x13worker_instance_key\x18\x02 \x01(\t"Q\n\x16\x44\x65scribeWorkerResponse\x12\x37\n\x0bworker_info\x18\x01 \x01(\x0b\x32".temporal.api.worker.v1.WorkerInfo"W\n\x13\x43ountWorkersRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\r\n\x05query\x18\x02 \x01(\t\x12\x1e\n\x16include_system_workers\x18\x03 \x01(\x08"%\n\x14\x43ountWorkersResponse\x12\r\n\x05\x63ount\x18\x01 \x01(\x03"\x8d\x01\n\x1dPauseWorkflowExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x12\x10\n\x08identity\x18\x04 \x01(\t\x12\x0e\n\x06reason\x18\x05 \x01(\t\x12\x12\n\nrequest_id\x18\x06 \x01(\t" \n\x1ePauseWorkflowExecutionResponse"\x8f\x01\n\x1fUnpauseWorkflowExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x12\x10\n\x08identity\x18\x04 \x01(\t\x12\x0e\n\x06reason\x18\x05 \x01(\t\x12\x12\n\nrequest_id\x18\x06 \x01(\t""\n UnpauseWorkflowExecutionResponse"\x99\t\n\x1dStartActivityExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x10\n\x08identity\x18\x02 \x01(\t\x12\x12\n\nrequest_id\x18\x03 \x01(\t\x12\x13\n\x0b\x61\x63tivity_id\x18\x04 \x01(\t\x12;\n\ractivity_type\x18\x05 \x01(\x0b\x32$.temporal.api.common.v1.ActivityType\x12\x38\n\ntask_queue\x18\x06 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12<\n\x19schedule_to_close_timeout\x18\x07 \x01(\x0b\x32\x19.google.protobuf.Duration\x12<\n\x19schedule_to_start_timeout\x18\x08 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x39\n\x16start_to_close_timeout\x18\t \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x34\n\x11heartbeat_timeout\x18\n \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x39\n\x0cretry_policy\x18\x0b \x01(\x0b\x32#.temporal.api.common.v1.RetryPolicy\x12/\n\x05input\x18\x0c \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x45\n\x0fid_reuse_policy\x18\r \x01(\x0e\x32,.temporal.api.enums.v1.ActivityIdReusePolicy\x12K\n\x12id_conflict_policy\x18\x0e \x01(\x0e\x32/.temporal.api.enums.v1.ActivityIdConflictPolicy\x12\x43\n\x11search_attributes\x18\x0f \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes\x12.\n\x06header\x18\x10 \x01(\x0b\x32\x1e.temporal.api.common.v1.Header\x12\x38\n\ruser_metadata\x18\x11 \x01(\x0b\x32!.temporal.api.sdk.v1.UserMetadata\x12\x32\n\x08priority\x18\x12 \x01(\x0b\x32 .temporal.api.common.v1.Priority\x12>\n\x14\x63ompletion_callbacks\x18\x13 \x03(\x0b\x32 .temporal.api.common.v1.Callback\x12+\n\x05links\x18\x14 \x03(\x0b\x32\x1c.temporal.api.common.v1.Link\x12\x46\n\x13on_conflict_options\x18\x15 \x01(\x0b\x32).temporal.api.common.v1.OnConflictOptions\x12.\n\x0bstart_delay\x18\x16 \x01(\x0b\x32\x19.google.protobuf.Duration"m\n\x1eStartActivityExecutionResponse\x12\x0e\n\x06run_id\x18\x01 \x01(\t\x12\x0f\n\x07started\x18\x02 \x01(\x08\x12*\n\x04link\x18\x03 \x01(\x0b\x32\x1c.temporal.api.common.v1.Link"\xe4\x01\n DescribeActivityExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0b\x61\x63tivity_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x12\x15\n\rinclude_input\x18\x04 \x01(\x08\x12\x17\n\x0finclude_outcome\x18\x05 \x01(\x08\x12\x17\n\x0flong_poll_token\x18\x06 \x01(\x0c\x12!\n\x19include_heartbeat_details\x18\x07 \x01(\x08\x12\x1c\n\x14include_last_failure\x18\x08 \x01(\x08"\xbc\x02\n!DescribeActivityExecutionResponse\x12\x0e\n\x06run_id\x18\x01 \x01(\t\x12=\n\x04info\x18\x02 \x01(\x0b\x32/.temporal.api.activity.v1.ActivityExecutionInfo\x12/\n\x05input\x18\x03 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x43\n\x07outcome\x18\x04 \x01(\x0b\x32\x32.temporal.api.activity.v1.ActivityExecutionOutcome\x12\x17\n\x0flong_poll_token\x18\x05 \x01(\x0c\x12\x39\n\tcallbacks\x18\x06 \x03(\x0b\x32&.temporal.api.activity.v1.CallbackInfo"V\n\x1cPollActivityExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0b\x61\x63tivity_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t"t\n\x1dPollActivityExecutionResponse\x12\x0e\n\x06run_id\x18\x01 \x01(\t\x12\x43\n\x07outcome\x18\x02 \x01(\x0b\x32\x32.temporal.api.activity.v1.ActivityExecutionOutcome"m\n\x1dListActivityExecutionsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x11\n\tpage_size\x18\x02 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c\x12\r\n\x05query\x18\x04 \x01(\t"\x82\x01\n\x1eListActivityExecutionsResponse\x12G\n\nexecutions\x18\x01 \x03(\x0b\x32\x33.temporal.api.activity.v1.ActivityExecutionListInfo\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c"\xd1\x06\n#StartNexusOperationExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x10\n\x08identity\x18\x02 \x01(\t\x12\x12\n\nrequest_id\x18\x03 \x01(\t\x12\x14\n\x0coperation_id\x18\x04 \x01(\t\x12\x10\n\x08\x65ndpoint\x18\x05 \x01(\t\x12\x0f\n\x07service\x18\x06 \x01(\t\x12\x11\n\toperation\x18\x07 \x01(\t\x12<\n\x19schedule_to_close_timeout\x18\x08 \x01(\x0b\x32\x19.google.protobuf.Duration\x12<\n\x19schedule_to_start_timeout\x18\t \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x39\n\x16start_to_close_timeout\x18\n \x01(\x0b\x32\x19.google.protobuf.Duration\x12.\n\x05input\x18\x0b \x01(\x0b\x32\x1f.temporal.api.common.v1.Payload\x12K\n\x0fid_reuse_policy\x18\x0c \x01(\x0e\x32\x32.temporal.api.enums.v1.NexusOperationIdReusePolicy\x12Q\n\x12id_conflict_policy\x18\r \x01(\x0e\x32\x35.temporal.api.enums.v1.NexusOperationIdConflictPolicy\x12\x43\n\x11search_attributes\x18\x0e \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes\x12k\n\x0cnexus_header\x18\x0f \x03(\x0b\x32U.temporal.api.workflowservice.v1.StartNexusOperationExecutionRequest.NexusHeaderEntry\x12\x38\n\ruser_metadata\x18\x10 \x01(\x0b\x32!.temporal.api.sdk.v1.UserMetadata\x1a\x32\n\x10NexusHeaderEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01"G\n$StartNexusOperationExecutionResponse\x12\x0e\n\x06run_id\x18\x01 \x01(\t\x12\x0f\n\x07started\x18\x02 \x01(\x08"\xaa\x01\n&DescribeNexusOperationExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x14\n\x0coperation_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x12\x15\n\rinclude_input\x18\x04 \x01(\x08\x12\x17\n\x0finclude_outcome\x18\x05 \x01(\x08\x12\x17\n\x0flong_poll_token\x18\x06 \x01(\x0c"\xb7\x02\n\'DescribeNexusOperationExecutionResponse\x12\x0e\n\x06run_id\x18\x01 \x01(\t\x12@\n\x04info\x18\x02 \x01(\x0b\x32\x32.temporal.api.nexus.v1.NexusOperationExecutionInfo\x12.\n\x05input\x18\x03 \x01(\x0b\x32\x1f.temporal.api.common.v1.Payload\x12\x31\n\x06result\x18\x04 \x01(\x0b\x32\x1f.temporal.api.common.v1.PayloadH\x00\x12\x33\n\x07\x66\x61ilure\x18\x05 \x01(\x0b\x32 .temporal.api.failure.v1.FailureH\x00\x12\x17\n\x0flong_poll_token\x18\x06 \x01(\x0c\x42\t\n\x07outcome"\xa1\x01\n"PollNexusOperationExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x14\n\x0coperation_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x12\x42\n\nwait_stage\x18\x04 \x01(\x0e\x32..temporal.api.enums.v1.NexusOperationWaitStage"\x85\x02\n#PollNexusOperationExecutionResponse\x12\x0e\n\x06run_id\x18\x01 \x01(\t\x12\x42\n\nwait_stage\x18\x02 \x01(\x0e\x32..temporal.api.enums.v1.NexusOperationWaitStage\x12\x17\n\x0foperation_token\x18\x03 \x01(\t\x12\x31\n\x06result\x18\x04 \x01(\x0b\x32\x1f.temporal.api.common.v1.PayloadH\x00\x12\x33\n\x07\x66\x61ilure\x18\x05 \x01(\x0b\x32 .temporal.api.failure.v1.FailureH\x00\x42\t\n\x07outcome"s\n#ListNexusOperationExecutionsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x11\n\tpage_size\x18\x02 \x01(\x05\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\x0c\x12\r\n\x05query\x18\x04 \x01(\t"\x8b\x01\n$ListNexusOperationExecutionsResponse\x12J\n\noperations\x18\x01 \x03(\x0b\x32\x36.temporal.api.nexus.v1.NexusOperationExecutionListInfo\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\x0c"B\n\x1e\x43ountActivityExecutionsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\r\n\x05query\x18\x02 \x01(\t"\xed\x01\n\x1f\x43ountActivityExecutionsResponse\x12\r\n\x05\x63ount\x18\x01 \x01(\x03\x12\x61\n\x06groups\x18\x02 \x03(\x0b\x32Q.temporal.api.workflowservice.v1.CountActivityExecutionsResponse.AggregationGroup\x1aX\n\x10\x41ggregationGroup\x12\x35\n\x0cgroup_values\x18\x01 \x03(\x0b\x32\x1f.temporal.api.common.v1.Payload\x12\r\n\x05\x63ount\x18\x02 \x01(\x03"H\n$CountNexusOperationExecutionsRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\r\n\x05query\x18\x02 \x01(\t"\xf9\x01\n%CountNexusOperationExecutionsResponse\x12\r\n\x05\x63ount\x18\x01 \x01(\x03\x12g\n\x06groups\x18\x02 \x03(\x0b\x32W.temporal.api.workflowservice.v1.CountNexusOperationExecutionsResponse.AggregationGroup\x1aX\n\x10\x41ggregationGroup\x12\x35\n\x0cgroup_values\x18\x01 \x03(\x0b\x32\x1f.temporal.api.common.v1.Payload\x12\r\n\x05\x63ount\x18\x02 \x01(\x03"\x95\x01\n%RequestCancelActivityExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0b\x61\x63tivity_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x12\x10\n\x08identity\x18\x04 \x01(\t\x12\x12\n\nrequest_id\x18\x05 \x01(\t\x12\x0e\n\x06reason\x18\x06 \x01(\t"(\n&RequestCancelActivityExecutionResponse"\x91\x01\n!TerminateActivityExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0b\x61\x63tivity_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x12\x10\n\x08identity\x18\x04 \x01(\t\x12\x12\n\nrequest_id\x18\x05 \x01(\t\x12\x0e\n\x06reason\x18\x06 \x01(\t"$\n"TerminateActivityExecutionResponse"X\n\x1e\x44\x65leteActivityExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0b\x61\x63tivity_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t"!\n\x1f\x44\x65leteActivityExecutionResponse"\x9c\x01\n+RequestCancelNexusOperationExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x14\n\x0coperation_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x12\x10\n\x08identity\x18\x04 \x01(\t\x12\x12\n\nrequest_id\x18\x05 \x01(\t\x12\x0e\n\x06reason\x18\x06 \x01(\t".\n,RequestCancelNexusOperationExecutionResponse"\x98\x01\n\'TerminateNexusOperationExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x14\n\x0coperation_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t\x12\x10\n\x08identity\x18\x04 \x01(\t\x12\x12\n\nrequest_id\x18\x05 \x01(\t\x12\x0e\n\x06reason\x18\x06 \x01(\t"*\n(TerminateNexusOperationExecutionResponse"_\n$DeleteNexusOperationExecutionRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x14\n\x0coperation_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t"\'\n%DeleteNexusOperationExecutionResponse"\x9d\x01\n(PollWorkflowExecutionTimeSkippingRequest\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x45\n\x12workflow_execution\x18\x02 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x17\n\x0f\x66\x61st_forward_id\x18\x03 \x01(\t"\xe8\x01\n)PollWorkflowExecutionTimeSkippingResponse\x12T\n\x1b\x66\x61st_forward_polling_result\x18\x01 \x01(\x0e\x32/.temporal.api.enums.v1.FastForwardPollingResult\x12\x15\n\rfailed_reason\x18\x02 \x01(\t\x12N\n\x11\x66\x61st_forward_info\x18\x03 \x01(\x0b\x32\x33.temporal.api.common.v1.TimeSkippingFastForwardInfoB\xbe\x01\n"io.temporal.api.workflowservice.v1B\x14RequestResponseProtoP\x01Z5go.temporal.io/api/workflowservice/v1;workflowservice\xaa\x02!Temporalio.Api.WorkflowService.V1\xea\x02$Temporalio::Api::WorkflowService::V1b\x06proto3' ) @@ -902,6 +905,12 @@ _DELETENEXUSOPERATIONEXECUTIONRESPONSE = DESCRIPTOR.message_types_by_name[ "DeleteNexusOperationExecutionResponse" ] +_POLLWORKFLOWEXECUTIONTIMESKIPPINGREQUEST = DESCRIPTOR.message_types_by_name[ + "PollWorkflowExecutionTimeSkippingRequest" +] +_POLLWORKFLOWEXECUTIONTIMESKIPPINGRESPONSE = DESCRIPTOR.message_types_by_name[ + "PollWorkflowExecutionTimeSkippingResponse" +] RegisterNamespaceRequest = _reflection.GeneratedProtocolMessageType( "RegisterNamespaceRequest", (_message.Message,), @@ -3944,6 +3953,28 @@ ) _sym_db.RegisterMessage(DeleteNexusOperationExecutionResponse) +PollWorkflowExecutionTimeSkippingRequest = _reflection.GeneratedProtocolMessageType( + "PollWorkflowExecutionTimeSkippingRequest", + (_message.Message,), + { + "DESCRIPTOR": _POLLWORKFLOWEXECUTIONTIMESKIPPINGREQUEST, + "__module__": "temporalio.api.workflowservice.v1.request_response_pb2", + # @@protoc_insertion_point(class_scope:temporal.api.workflowservice.v1.PollWorkflowExecutionTimeSkippingRequest) + }, +) +_sym_db.RegisterMessage(PollWorkflowExecutionTimeSkippingRequest) + +PollWorkflowExecutionTimeSkippingResponse = _reflection.GeneratedProtocolMessageType( + "PollWorkflowExecutionTimeSkippingResponse", + (_message.Message,), + { + "DESCRIPTOR": _POLLWORKFLOWEXECUTIONTIMESKIPPINGRESPONSE, + "__module__": "temporalio.api.workflowservice.v1.request_response_pb2", + # @@protoc_insertion_point(class_scope:temporal.api.workflowservice.v1.PollWorkflowExecutionTimeSkippingResponse) + }, +) +_sym_db.RegisterMessage(PollWorkflowExecutionTimeSkippingResponse) + if _descriptor._USE_C_DESCRIPTORS == False: DESCRIPTOR._options = None DESCRIPTOR._serialized_options = b'\n"io.temporal.api.workflowservice.v1B\024RequestResponseProtoP\001Z5go.temporal.io/api/workflowservice/v1;workflowservice\252\002!Temporalio.Api.WorkflowService.V1\352\002$Temporalio::Api::WorkflowService::V1' @@ -4183,574 +4214,578 @@ _UPDATETASKQUEUECONFIGREQUEST_SETFAIRNESSWEIGHTOVERRIDESENTRY._serialized_options = b"8\001" _STARTNEXUSOPERATIONEXECUTIONREQUEST_NEXUSHEADERENTRY._options = None _STARTNEXUSOPERATIONEXECUTIONREQUEST_NEXUSHEADERENTRY._serialized_options = b"8\001" - _REGISTERNAMESPACEREQUEST._serialized_start = 1603 - _REGISTERNAMESPACEREQUEST._serialized_end = 2251 - _REGISTERNAMESPACEREQUEST_DATAENTRY._serialized_start = 2208 - _REGISTERNAMESPACEREQUEST_DATAENTRY._serialized_end = 2251 - _REGISTERNAMESPACERESPONSE._serialized_start = 2253 - _REGISTERNAMESPACERESPONSE._serialized_end = 2280 - _LISTNAMESPACESREQUEST._serialized_start = 2283 - _LISTNAMESPACESREQUEST._serialized_end = 2420 - _LISTNAMESPACESRESPONSE._serialized_start = 2423 - _LISTNAMESPACESRESPONSE._serialized_end = 2552 - _DESCRIBENAMESPACEREQUEST._serialized_start = 2554 - _DESCRIBENAMESPACEREQUEST._serialized_end = 2637 - _DESCRIBENAMESPACERESPONSE._serialized_start = 2640 - _DESCRIBENAMESPACERESPONSE._serialized_end = 3153 - _UPDATENAMESPACEREQUEST._serialized_start = 3156 - _UPDATENAMESPACEREQUEST._serialized_end = 3491 - _UPDATENAMESPACERESPONSE._serialized_start = 3494 - _UPDATENAMESPACERESPONSE._serialized_end = 3785 - _DEPRECATENAMESPACEREQUEST._serialized_start = 3787 - _DEPRECATENAMESPACEREQUEST._serialized_end = 3857 - _DEPRECATENAMESPACERESPONSE._serialized_start = 3859 - _DEPRECATENAMESPACERESPONSE._serialized_end = 3887 - _STARTWORKFLOWEXECUTIONREQUEST._serialized_start = 3890 - _STARTWORKFLOWEXECUTIONREQUEST._serialized_end = 5507 - _STARTWORKFLOWEXECUTIONRESPONSE._serialized_start = 5510 - _STARTWORKFLOWEXECUTIONRESPONSE._serialized_end = 5808 - _GETWORKFLOWEXECUTIONHISTORYREQUEST._serialized_start = 5811 - _GETWORKFLOWEXECUTIONHISTORYREQUEST._serialized_end = 6109 - _GETWORKFLOWEXECUTIONHISTORYRESPONSE._serialized_start = 6112 - _GETWORKFLOWEXECUTIONHISTORYRESPONSE._serialized_end = 6298 - _GETWORKFLOWEXECUTIONHISTORYREVERSEREQUEST._serialized_start = 6301 - _GETWORKFLOWEXECUTIONHISTORYREVERSEREQUEST._serialized_end = 6477 - _GETWORKFLOWEXECUTIONHISTORYREVERSERESPONSE._serialized_start = 6479 - _GETWORKFLOWEXECUTIONHISTORYREVERSERESPONSE._serialized_end = 6599 - _POLLWORKFLOWTASKQUEUEREQUEST._serialized_start = 6602 - _POLLWORKFLOWTASKQUEUEREQUEST._serialized_end = 7042 - _POLLWORKFLOWTASKQUEUERESPONSE._serialized_start = 7045 - _POLLWORKFLOWTASKQUEUERESPONSE._serialized_end = 8132 - _POLLWORKFLOWTASKQUEUERESPONSE_QUERIESENTRY._serialized_start = 8048 - _POLLWORKFLOWTASKQUEUERESPONSE_QUERIESENTRY._serialized_end = 8132 - _RESPONDWORKFLOWTASKCOMPLETEDREQUEST._serialized_start = 8135 - _RESPONDWORKFLOWTASKCOMPLETEDREQUEST._serialized_end = 9473 - _RESPONDWORKFLOWTASKCOMPLETEDREQUEST_QUERYRESULTSENTRY._serialized_start = 9307 - _RESPONDWORKFLOWTASKCOMPLETEDREQUEST_QUERYRESULTSENTRY._serialized_end = 9402 - _RESPONDWORKFLOWTASKCOMPLETEDREQUEST_CAPABILITIES._serialized_start = 9404 - _RESPONDWORKFLOWTASKCOMPLETEDREQUEST_CAPABILITIES._serialized_end = 9473 - _RESPONDWORKFLOWTASKCOMPLETEDRESPONSE._serialized_start = 9476 - _RESPONDWORKFLOWTASKCOMPLETEDRESPONSE._serialized_end = 9721 - _RESPONDWORKFLOWTASKFAILEDREQUEST._serialized_start = 9724 - _RESPONDWORKFLOWTASKFAILEDREQUEST._serialized_end = 10249 - _RESPONDWORKFLOWTASKFAILEDRESPONSE._serialized_start = 10251 - _RESPONDWORKFLOWTASKFAILEDRESPONSE._serialized_end = 10286 - _POLLACTIVITYTASKQUEUEREQUEST._serialized_start = 10289 - _POLLACTIVITYTASKQUEUEREQUEST._serialized_end = 10775 - _POLLACTIVITYTASKQUEUERESPONSE._serialized_start = 10778 - _POLLACTIVITYTASKQUEUERESPONSE._serialized_end = 11959 - _RECORDACTIVITYTASKHEARTBEATREQUEST._serialized_start = 11962 - _RECORDACTIVITYTASKHEARTBEATREQUEST._serialized_end = 12127 - _RECORDACTIVITYTASKHEARTBEATRESPONSE._serialized_start = 12129 - _RECORDACTIVITYTASKHEARTBEATRESPONSE._serialized_end = 12241 - _RECORDACTIVITYTASKHEARTBEATBYIDREQUEST._serialized_start = 12244 - _RECORDACTIVITYTASKHEARTBEATBYIDREQUEST._serialized_end = 12451 - _RECORDACTIVITYTASKHEARTBEATBYIDRESPONSE._serialized_start = 12453 - _RECORDACTIVITYTASKHEARTBEATBYIDRESPONSE._serialized_end = 12569 - _RESPONDACTIVITYTASKCOMPLETEDREQUEST._serialized_start = 12572 - _RESPONDACTIVITYTASKCOMPLETEDREQUEST._serialized_end = 12954 - _RESPONDACTIVITYTASKCOMPLETEDRESPONSE._serialized_start = 12956 - _RESPONDACTIVITYTASKCOMPLETEDRESPONSE._serialized_end = 12994 - _RESPONDACTIVITYTASKCOMPLETEDBYIDREQUEST._serialized_start = 12997 - _RESPONDACTIVITYTASKCOMPLETEDBYIDREQUEST._serialized_end = 13204 - _RESPONDACTIVITYTASKCOMPLETEDBYIDRESPONSE._serialized_start = 13206 - _RESPONDACTIVITYTASKCOMPLETEDBYIDRESPONSE._serialized_end = 13248 - _RESPONDACTIVITYTASKFAILEDREQUEST._serialized_start = 13251 - _RESPONDACTIVITYTASKFAILEDREQUEST._serialized_end = 13697 - _RESPONDACTIVITYTASKFAILEDRESPONSE._serialized_start = 13699 - _RESPONDACTIVITYTASKFAILEDRESPONSE._serialized_end = 13786 - _RESPONDACTIVITYTASKFAILEDBYIDREQUEST._serialized_start = 13789 - _RESPONDACTIVITYTASKFAILEDBYIDREQUEST._serialized_end = 14060 - _RESPONDACTIVITYTASKFAILEDBYIDRESPONSE._serialized_start = 14062 - _RESPONDACTIVITYTASKFAILEDBYIDRESPONSE._serialized_end = 14153 - _RESPONDACTIVITYTASKCANCELEDREQUEST._serialized_start = 14156 - _RESPONDACTIVITYTASKCANCELEDREQUEST._serialized_end = 14538 - _RESPONDACTIVITYTASKCANCELEDRESPONSE._serialized_start = 14540 - _RESPONDACTIVITYTASKCANCELEDRESPONSE._serialized_end = 14577 - _RESPONDACTIVITYTASKCANCELEDBYIDREQUEST._serialized_start = 14580 - _RESPONDACTIVITYTASKCANCELEDBYIDREQUEST._serialized_end = 14868 - _RESPONDACTIVITYTASKCANCELEDBYIDRESPONSE._serialized_start = 14870 - _RESPONDACTIVITYTASKCANCELEDBYIDRESPONSE._serialized_end = 14911 - _REQUESTCANCELWORKFLOWEXECUTIONREQUEST._serialized_start = 14914 - _REQUESTCANCELWORKFLOWEXECUTIONREQUEST._serialized_end = 15174 - _REQUESTCANCELWORKFLOWEXECUTIONRESPONSE._serialized_start = 15176 - _REQUESTCANCELWORKFLOWEXECUTIONRESPONSE._serialized_end = 15216 - _SIGNALWORKFLOWEXECUTIONREQUEST._serialized_start = 15219 - _SIGNALWORKFLOWEXECUTIONREQUEST._serialized_end = 15569 - _SIGNALWORKFLOWEXECUTIONRESPONSE._serialized_start = 15571 - _SIGNALWORKFLOWEXECUTIONRESPONSE._serialized_end = 15648 - _SIGNALWITHSTARTWORKFLOWEXECUTIONREQUEST._serialized_start = 15651 - _SIGNALWITHSTARTWORKFLOWEXECUTIONREQUEST._serialized_end = 16990 - _SIGNALWITHSTARTWORKFLOWEXECUTIONRESPONSE._serialized_start = 16993 - _SIGNALWITHSTARTWORKFLOWEXECUTIONRESPONSE._serialized_end = 17151 - _RESETWORKFLOWEXECUTIONREQUEST._serialized_start = 17154 - _RESETWORKFLOWEXECUTIONREQUEST._serialized_end = 17603 - _RESETWORKFLOWEXECUTIONRESPONSE._serialized_start = 17605 - _RESETWORKFLOWEXECUTIONRESPONSE._serialized_end = 17653 - _TERMINATEWORKFLOWEXECUTIONREQUEST._serialized_start = 17656 - _TERMINATEWORKFLOWEXECUTIONREQUEST._serialized_end = 17943 - _TERMINATEWORKFLOWEXECUTIONRESPONSE._serialized_start = 17945 - _TERMINATEWORKFLOWEXECUTIONRESPONSE._serialized_end = 17981 - _DELETEWORKFLOWEXECUTIONREQUEST._serialized_start = 17983 - _DELETEWORKFLOWEXECUTIONREQUEST._serialized_end = 18105 - _DELETEWORKFLOWEXECUTIONRESPONSE._serialized_start = 18107 - _DELETEWORKFLOWEXECUTIONRESPONSE._serialized_end = 18140 - _LISTOPENWORKFLOWEXECUTIONSREQUEST._serialized_start = 18143 - _LISTOPENWORKFLOWEXECUTIONSREQUEST._serialized_end = 18472 - _LISTOPENWORKFLOWEXECUTIONSRESPONSE._serialized_start = 18475 - _LISTOPENWORKFLOWEXECUTIONSRESPONSE._serialized_end = 18605 - _LISTCLOSEDWORKFLOWEXECUTIONSREQUEST._serialized_start = 18608 - _LISTCLOSEDWORKFLOWEXECUTIONSREQUEST._serialized_end = 19002 - _LISTCLOSEDWORKFLOWEXECUTIONSRESPONSE._serialized_start = 19005 - _LISTCLOSEDWORKFLOWEXECUTIONSRESPONSE._serialized_end = 19137 - _LISTWORKFLOWEXECUTIONSREQUEST._serialized_start = 19139 - _LISTWORKFLOWEXECUTIONSREQUEST._serialized_end = 19248 - _LISTWORKFLOWEXECUTIONSRESPONSE._serialized_start = 19250 - _LISTWORKFLOWEXECUTIONSRESPONSE._serialized_end = 19376 - _LISTARCHIVEDWORKFLOWEXECUTIONSREQUEST._serialized_start = 19378 - _LISTARCHIVEDWORKFLOWEXECUTIONSREQUEST._serialized_end = 19495 - _LISTARCHIVEDWORKFLOWEXECUTIONSRESPONSE._serialized_start = 19498 - _LISTARCHIVEDWORKFLOWEXECUTIONSRESPONSE._serialized_end = 19632 - _SCANWORKFLOWEXECUTIONSREQUEST._serialized_start = 19634 - _SCANWORKFLOWEXECUTIONSREQUEST._serialized_end = 19743 - _SCANWORKFLOWEXECUTIONSRESPONSE._serialized_start = 19745 - _SCANWORKFLOWEXECUTIONSRESPONSE._serialized_end = 19871 - _COUNTWORKFLOWEXECUTIONSREQUEST._serialized_start = 19873 - _COUNTWORKFLOWEXECUTIONSREQUEST._serialized_end = 19939 - _COUNTWORKFLOWEXECUTIONSRESPONSE._serialized_start = 19942 - _COUNTWORKFLOWEXECUTIONSRESPONSE._serialized_end = 20179 - _COUNTWORKFLOWEXECUTIONSRESPONSE_AGGREGATIONGROUP._serialized_start = 20091 - _COUNTWORKFLOWEXECUTIONSRESPONSE_AGGREGATIONGROUP._serialized_end = 20179 - _GETSEARCHATTRIBUTESREQUEST._serialized_start = 20181 - _GETSEARCHATTRIBUTESREQUEST._serialized_end = 20209 - _GETSEARCHATTRIBUTESRESPONSE._serialized_start = 20212 - _GETSEARCHATTRIBUTESRESPONSE._serialized_end = 20413 - _GETSEARCHATTRIBUTESRESPONSE_KEYSENTRY._serialized_start = 20329 - _GETSEARCHATTRIBUTESRESPONSE_KEYSENTRY._serialized_end = 20413 - _RESPONDQUERYTASKCOMPLETEDREQUEST._serialized_start = 20416 - _RESPONDQUERYTASKCOMPLETEDREQUEST._serialized_end = 20777 - _RESPONDQUERYTASKCOMPLETEDRESPONSE._serialized_start = 20779 - _RESPONDQUERYTASKCOMPLETEDRESPONSE._serialized_end = 20814 - _RESETSTICKYTASKQUEUEREQUEST._serialized_start = 20816 - _RESETSTICKYTASKQUEUEREQUEST._serialized_end = 20926 - _RESETSTICKYTASKQUEUERESPONSE._serialized_start = 20928 - _RESETSTICKYTASKQUEUERESPONSE._serialized_end = 20958 - _SHUTDOWNWORKERREQUEST._serialized_start = 20961 - _SHUTDOWNWORKERREQUEST._serialized_end = 21244 - _SHUTDOWNWORKERRESPONSE._serialized_start = 21246 - _SHUTDOWNWORKERRESPONSE._serialized_end = 21270 - _QUERYWORKFLOWREQUEST._serialized_start = 21273 - _QUERYWORKFLOWREQUEST._serialized_end = 21506 - _QUERYWORKFLOWRESPONSE._serialized_start = 21509 - _QUERYWORKFLOWRESPONSE._serialized_end = 21650 - _DESCRIBEWORKFLOWEXECUTIONREQUEST._serialized_start = 21652 - _DESCRIBEWORKFLOWEXECUTIONREQUEST._serialized_end = 21767 - _DESCRIBEWORKFLOWEXECUTIONRESPONSE._serialized_start = 21770 - _DESCRIBEWORKFLOWEXECUTIONRESPONSE._serialized_end = 22435 - _DESCRIBETASKQUEUEREQUEST._serialized_start = 22438 - _DESCRIBETASKQUEUEREQUEST._serialized_end = 22966 - _DESCRIBETASKQUEUERESPONSE._serialized_start = 22969 - _DESCRIBETASKQUEUERESPONSE._serialized_end = 23973 - _DESCRIBETASKQUEUERESPONSE_STATSBYPRIORITYKEYENTRY._serialized_start = 23653 - _DESCRIBETASKQUEUERESPONSE_STATSBYPRIORITYKEYENTRY._serialized_end = 23753 - _DESCRIBETASKQUEUERESPONSE_EFFECTIVERATELIMIT._serialized_start = 23755 - _DESCRIBETASKQUEUERESPONSE_EFFECTIVERATELIMIT._serialized_end = 23871 - _DESCRIBETASKQUEUERESPONSE_VERSIONSINFOENTRY._serialized_start = 23873 - _DESCRIBETASKQUEUERESPONSE_VERSIONSINFOENTRY._serialized_end = 23973 - _GETCLUSTERINFOREQUEST._serialized_start = 23975 - _GETCLUSTERINFOREQUEST._serialized_end = 23998 - _GETCLUSTERINFORESPONSE._serialized_start = 24001 - _GETCLUSTERINFORESPONSE._serialized_end = 24466 - _GETCLUSTERINFORESPONSE_SUPPORTEDCLIENTSENTRY._serialized_start = 24411 - _GETCLUSTERINFORESPONSE_SUPPORTEDCLIENTSENTRY._serialized_end = 24466 - _GETSYSTEMINFOREQUEST._serialized_start = 24468 - _GETSYSTEMINFOREQUEST._serialized_end = 24490 - _GETSYSTEMINFORESPONSE._serialized_start = 24493 - _GETSYSTEMINFORESPONSE._serialized_end = 25070 - _GETSYSTEMINFORESPONSE_CAPABILITIES._serialized_start = 24634 - _GETSYSTEMINFORESPONSE_CAPABILITIES._serialized_end = 25070 - _LISTTASKQUEUEPARTITIONSREQUEST._serialized_start = 25072 - _LISTTASKQUEUEPARTITIONSREQUEST._serialized_end = 25181 - _LISTTASKQUEUEPARTITIONSRESPONSE._serialized_start = 25184 - _LISTTASKQUEUEPARTITIONSRESPONSE._serialized_end = 25407 - _CREATESCHEDULEREQUEST._serialized_start = 25410 - _CREATESCHEDULEREQUEST._serialized_end = 25742 - _CREATESCHEDULERESPONSE._serialized_start = 25744 - _CREATESCHEDULERESPONSE._serialized_end = 25792 - _DESCRIBESCHEDULEREQUEST._serialized_start = 25794 - _DESCRIBESCHEDULEREQUEST._serialized_end = 25859 - _DESCRIBESCHEDULERESPONSE._serialized_start = 25862 - _DESCRIBESCHEDULERESPONSE._serialized_end = 26133 - _UPDATESCHEDULEREQUEST._serialized_start = 26136 - _UPDATESCHEDULEREQUEST._serialized_end = 26428 - _UPDATESCHEDULERESPONSE._serialized_start = 26430 - _UPDATESCHEDULERESPONSE._serialized_end = 26454 - _PATCHSCHEDULEREQUEST._serialized_start = 26457 - _PATCHSCHEDULEREQUEST._serialized_end = 26613 - _PATCHSCHEDULERESPONSE._serialized_start = 26615 - _PATCHSCHEDULERESPONSE._serialized_end = 26638 - _LISTSCHEDULEMATCHINGTIMESREQUEST._serialized_start = 26641 - _LISTSCHEDULEMATCHINGTIMESREQUEST._serialized_end = 26809 - _LISTSCHEDULEMATCHINGTIMESRESPONSE._serialized_start = 26811 - _LISTSCHEDULEMATCHINGTIMESRESPONSE._serialized_end = 26894 - _DELETESCHEDULEREQUEST._serialized_start = 26896 - _DELETESCHEDULEREQUEST._serialized_end = 26977 - _DELETESCHEDULERESPONSE._serialized_start = 26979 - _DELETESCHEDULERESPONSE._serialized_end = 27003 - _LISTSCHEDULESREQUEST._serialized_start = 27005 - _LISTSCHEDULESREQUEST._serialized_end = 27113 - _LISTSCHEDULESRESPONSE._serialized_start = 27115 - _LISTSCHEDULESRESPONSE._serialized_end = 27227 - _COUNTSCHEDULESREQUEST._serialized_start = 27229 - _COUNTSCHEDULESREQUEST._serialized_end = 27286 - _COUNTSCHEDULESRESPONSE._serialized_start = 27289 - _COUNTSCHEDULESRESPONSE._serialized_end = 27508 - _COUNTSCHEDULESRESPONSE_AGGREGATIONGROUP._serialized_start = 20091 - _COUNTSCHEDULESRESPONSE_AGGREGATIONGROUP._serialized_end = 20179 - _UPDATEWORKERBUILDIDCOMPATIBILITYREQUEST._serialized_start = 27511 - _UPDATEWORKERBUILDIDCOMPATIBILITYREQUEST._serialized_end = 28157 - _UPDATEWORKERBUILDIDCOMPATIBILITYREQUEST_ADDNEWCOMPATIBLEVERSION._serialized_start = 27958 + _REGISTERNAMESPACEREQUEST._serialized_start = 1646 + _REGISTERNAMESPACEREQUEST._serialized_end = 2294 + _REGISTERNAMESPACEREQUEST_DATAENTRY._serialized_start = 2251 + _REGISTERNAMESPACEREQUEST_DATAENTRY._serialized_end = 2294 + _REGISTERNAMESPACERESPONSE._serialized_start = 2296 + _REGISTERNAMESPACERESPONSE._serialized_end = 2323 + _LISTNAMESPACESREQUEST._serialized_start = 2326 + _LISTNAMESPACESREQUEST._serialized_end = 2463 + _LISTNAMESPACESRESPONSE._serialized_start = 2466 + _LISTNAMESPACESRESPONSE._serialized_end = 2595 + _DESCRIBENAMESPACEREQUEST._serialized_start = 2597 + _DESCRIBENAMESPACEREQUEST._serialized_end = 2680 + _DESCRIBENAMESPACERESPONSE._serialized_start = 2683 + _DESCRIBENAMESPACERESPONSE._serialized_end = 3196 + _UPDATENAMESPACEREQUEST._serialized_start = 3199 + _UPDATENAMESPACEREQUEST._serialized_end = 3534 + _UPDATENAMESPACERESPONSE._serialized_start = 3537 + _UPDATENAMESPACERESPONSE._serialized_end = 3828 + _DEPRECATENAMESPACEREQUEST._serialized_start = 3830 + _DEPRECATENAMESPACEREQUEST._serialized_end = 3900 + _DEPRECATENAMESPACERESPONSE._serialized_start = 3902 + _DEPRECATENAMESPACERESPONSE._serialized_end = 3930 + _STARTWORKFLOWEXECUTIONREQUEST._serialized_start = 3933 + _STARTWORKFLOWEXECUTIONREQUEST._serialized_end = 5550 + _STARTWORKFLOWEXECUTIONRESPONSE._serialized_start = 5553 + _STARTWORKFLOWEXECUTIONRESPONSE._serialized_end = 5851 + _GETWORKFLOWEXECUTIONHISTORYREQUEST._serialized_start = 5854 + _GETWORKFLOWEXECUTIONHISTORYREQUEST._serialized_end = 6152 + _GETWORKFLOWEXECUTIONHISTORYRESPONSE._serialized_start = 6155 + _GETWORKFLOWEXECUTIONHISTORYRESPONSE._serialized_end = 6341 + _GETWORKFLOWEXECUTIONHISTORYREVERSEREQUEST._serialized_start = 6344 + _GETWORKFLOWEXECUTIONHISTORYREVERSEREQUEST._serialized_end = 6520 + _GETWORKFLOWEXECUTIONHISTORYREVERSERESPONSE._serialized_start = 6522 + _GETWORKFLOWEXECUTIONHISTORYREVERSERESPONSE._serialized_end = 6642 + _POLLWORKFLOWTASKQUEUEREQUEST._serialized_start = 6645 + _POLLWORKFLOWTASKQUEUEREQUEST._serialized_end = 7085 + _POLLWORKFLOWTASKQUEUERESPONSE._serialized_start = 7088 + _POLLWORKFLOWTASKQUEUERESPONSE._serialized_end = 8175 + _POLLWORKFLOWTASKQUEUERESPONSE_QUERIESENTRY._serialized_start = 8091 + _POLLWORKFLOWTASKQUEUERESPONSE_QUERIESENTRY._serialized_end = 8175 + _RESPONDWORKFLOWTASKCOMPLETEDREQUEST._serialized_start = 8178 + _RESPONDWORKFLOWTASKCOMPLETEDREQUEST._serialized_end = 9516 + _RESPONDWORKFLOWTASKCOMPLETEDREQUEST_QUERYRESULTSENTRY._serialized_start = 9350 + _RESPONDWORKFLOWTASKCOMPLETEDREQUEST_QUERYRESULTSENTRY._serialized_end = 9445 + _RESPONDWORKFLOWTASKCOMPLETEDREQUEST_CAPABILITIES._serialized_start = 9447 + _RESPONDWORKFLOWTASKCOMPLETEDREQUEST_CAPABILITIES._serialized_end = 9516 + _RESPONDWORKFLOWTASKCOMPLETEDRESPONSE._serialized_start = 9519 + _RESPONDWORKFLOWTASKCOMPLETEDRESPONSE._serialized_end = 9764 + _RESPONDWORKFLOWTASKFAILEDREQUEST._serialized_start = 9767 + _RESPONDWORKFLOWTASKFAILEDREQUEST._serialized_end = 10292 + _RESPONDWORKFLOWTASKFAILEDRESPONSE._serialized_start = 10294 + _RESPONDWORKFLOWTASKFAILEDRESPONSE._serialized_end = 10329 + _POLLACTIVITYTASKQUEUEREQUEST._serialized_start = 10332 + _POLLACTIVITYTASKQUEUEREQUEST._serialized_end = 10818 + _POLLACTIVITYTASKQUEUERESPONSE._serialized_start = 10821 + _POLLACTIVITYTASKQUEUERESPONSE._serialized_end = 12002 + _RECORDACTIVITYTASKHEARTBEATREQUEST._serialized_start = 12005 + _RECORDACTIVITYTASKHEARTBEATREQUEST._serialized_end = 12170 + _RECORDACTIVITYTASKHEARTBEATRESPONSE._serialized_start = 12172 + _RECORDACTIVITYTASKHEARTBEATRESPONSE._serialized_end = 12284 + _RECORDACTIVITYTASKHEARTBEATBYIDREQUEST._serialized_start = 12287 + _RECORDACTIVITYTASKHEARTBEATBYIDREQUEST._serialized_end = 12494 + _RECORDACTIVITYTASKHEARTBEATBYIDRESPONSE._serialized_start = 12496 + _RECORDACTIVITYTASKHEARTBEATBYIDRESPONSE._serialized_end = 12612 + _RESPONDACTIVITYTASKCOMPLETEDREQUEST._serialized_start = 12615 + _RESPONDACTIVITYTASKCOMPLETEDREQUEST._serialized_end = 12997 + _RESPONDACTIVITYTASKCOMPLETEDRESPONSE._serialized_start = 12999 + _RESPONDACTIVITYTASKCOMPLETEDRESPONSE._serialized_end = 13037 + _RESPONDACTIVITYTASKCOMPLETEDBYIDREQUEST._serialized_start = 13040 + _RESPONDACTIVITYTASKCOMPLETEDBYIDREQUEST._serialized_end = 13247 + _RESPONDACTIVITYTASKCOMPLETEDBYIDRESPONSE._serialized_start = 13249 + _RESPONDACTIVITYTASKCOMPLETEDBYIDRESPONSE._serialized_end = 13291 + _RESPONDACTIVITYTASKFAILEDREQUEST._serialized_start = 13294 + _RESPONDACTIVITYTASKFAILEDREQUEST._serialized_end = 13740 + _RESPONDACTIVITYTASKFAILEDRESPONSE._serialized_start = 13742 + _RESPONDACTIVITYTASKFAILEDRESPONSE._serialized_end = 13829 + _RESPONDACTIVITYTASKFAILEDBYIDREQUEST._serialized_start = 13832 + _RESPONDACTIVITYTASKFAILEDBYIDREQUEST._serialized_end = 14103 + _RESPONDACTIVITYTASKFAILEDBYIDRESPONSE._serialized_start = 14105 + _RESPONDACTIVITYTASKFAILEDBYIDRESPONSE._serialized_end = 14196 + _RESPONDACTIVITYTASKCANCELEDREQUEST._serialized_start = 14199 + _RESPONDACTIVITYTASKCANCELEDREQUEST._serialized_end = 14581 + _RESPONDACTIVITYTASKCANCELEDRESPONSE._serialized_start = 14583 + _RESPONDACTIVITYTASKCANCELEDRESPONSE._serialized_end = 14620 + _RESPONDACTIVITYTASKCANCELEDBYIDREQUEST._serialized_start = 14623 + _RESPONDACTIVITYTASKCANCELEDBYIDREQUEST._serialized_end = 14911 + _RESPONDACTIVITYTASKCANCELEDBYIDRESPONSE._serialized_start = 14913 + _RESPONDACTIVITYTASKCANCELEDBYIDRESPONSE._serialized_end = 14954 + _REQUESTCANCELWORKFLOWEXECUTIONREQUEST._serialized_start = 14957 + _REQUESTCANCELWORKFLOWEXECUTIONREQUEST._serialized_end = 15217 + _REQUESTCANCELWORKFLOWEXECUTIONRESPONSE._serialized_start = 15219 + _REQUESTCANCELWORKFLOWEXECUTIONRESPONSE._serialized_end = 15259 + _SIGNALWORKFLOWEXECUTIONREQUEST._serialized_start = 15262 + _SIGNALWORKFLOWEXECUTIONREQUEST._serialized_end = 15612 + _SIGNALWORKFLOWEXECUTIONRESPONSE._serialized_start = 15614 + _SIGNALWORKFLOWEXECUTIONRESPONSE._serialized_end = 15691 + _SIGNALWITHSTARTWORKFLOWEXECUTIONREQUEST._serialized_start = 15694 + _SIGNALWITHSTARTWORKFLOWEXECUTIONREQUEST._serialized_end = 17033 + _SIGNALWITHSTARTWORKFLOWEXECUTIONRESPONSE._serialized_start = 17036 + _SIGNALWITHSTARTWORKFLOWEXECUTIONRESPONSE._serialized_end = 17194 + _RESETWORKFLOWEXECUTIONREQUEST._serialized_start = 17197 + _RESETWORKFLOWEXECUTIONREQUEST._serialized_end = 17646 + _RESETWORKFLOWEXECUTIONRESPONSE._serialized_start = 17648 + _RESETWORKFLOWEXECUTIONRESPONSE._serialized_end = 17696 + _TERMINATEWORKFLOWEXECUTIONREQUEST._serialized_start = 17699 + _TERMINATEWORKFLOWEXECUTIONREQUEST._serialized_end = 17986 + _TERMINATEWORKFLOWEXECUTIONRESPONSE._serialized_start = 17988 + _TERMINATEWORKFLOWEXECUTIONRESPONSE._serialized_end = 18024 + _DELETEWORKFLOWEXECUTIONREQUEST._serialized_start = 18026 + _DELETEWORKFLOWEXECUTIONREQUEST._serialized_end = 18148 + _DELETEWORKFLOWEXECUTIONRESPONSE._serialized_start = 18150 + _DELETEWORKFLOWEXECUTIONRESPONSE._serialized_end = 18183 + _LISTOPENWORKFLOWEXECUTIONSREQUEST._serialized_start = 18186 + _LISTOPENWORKFLOWEXECUTIONSREQUEST._serialized_end = 18515 + _LISTOPENWORKFLOWEXECUTIONSRESPONSE._serialized_start = 18518 + _LISTOPENWORKFLOWEXECUTIONSRESPONSE._serialized_end = 18648 + _LISTCLOSEDWORKFLOWEXECUTIONSREQUEST._serialized_start = 18651 + _LISTCLOSEDWORKFLOWEXECUTIONSREQUEST._serialized_end = 19045 + _LISTCLOSEDWORKFLOWEXECUTIONSRESPONSE._serialized_start = 19048 + _LISTCLOSEDWORKFLOWEXECUTIONSRESPONSE._serialized_end = 19180 + _LISTWORKFLOWEXECUTIONSREQUEST._serialized_start = 19182 + _LISTWORKFLOWEXECUTIONSREQUEST._serialized_end = 19291 + _LISTWORKFLOWEXECUTIONSRESPONSE._serialized_start = 19293 + _LISTWORKFLOWEXECUTIONSRESPONSE._serialized_end = 19419 + _LISTARCHIVEDWORKFLOWEXECUTIONSREQUEST._serialized_start = 19421 + _LISTARCHIVEDWORKFLOWEXECUTIONSREQUEST._serialized_end = 19538 + _LISTARCHIVEDWORKFLOWEXECUTIONSRESPONSE._serialized_start = 19541 + _LISTARCHIVEDWORKFLOWEXECUTIONSRESPONSE._serialized_end = 19675 + _SCANWORKFLOWEXECUTIONSREQUEST._serialized_start = 19677 + _SCANWORKFLOWEXECUTIONSREQUEST._serialized_end = 19786 + _SCANWORKFLOWEXECUTIONSRESPONSE._serialized_start = 19788 + _SCANWORKFLOWEXECUTIONSRESPONSE._serialized_end = 19914 + _COUNTWORKFLOWEXECUTIONSREQUEST._serialized_start = 19916 + _COUNTWORKFLOWEXECUTIONSREQUEST._serialized_end = 19982 + _COUNTWORKFLOWEXECUTIONSRESPONSE._serialized_start = 19985 + _COUNTWORKFLOWEXECUTIONSRESPONSE._serialized_end = 20222 + _COUNTWORKFLOWEXECUTIONSRESPONSE_AGGREGATIONGROUP._serialized_start = 20134 + _COUNTWORKFLOWEXECUTIONSRESPONSE_AGGREGATIONGROUP._serialized_end = 20222 + _GETSEARCHATTRIBUTESREQUEST._serialized_start = 20224 + _GETSEARCHATTRIBUTESREQUEST._serialized_end = 20252 + _GETSEARCHATTRIBUTESRESPONSE._serialized_start = 20255 + _GETSEARCHATTRIBUTESRESPONSE._serialized_end = 20456 + _GETSEARCHATTRIBUTESRESPONSE_KEYSENTRY._serialized_start = 20372 + _GETSEARCHATTRIBUTESRESPONSE_KEYSENTRY._serialized_end = 20456 + _RESPONDQUERYTASKCOMPLETEDREQUEST._serialized_start = 20459 + _RESPONDQUERYTASKCOMPLETEDREQUEST._serialized_end = 20820 + _RESPONDQUERYTASKCOMPLETEDRESPONSE._serialized_start = 20822 + _RESPONDQUERYTASKCOMPLETEDRESPONSE._serialized_end = 20857 + _RESETSTICKYTASKQUEUEREQUEST._serialized_start = 20859 + _RESETSTICKYTASKQUEUEREQUEST._serialized_end = 20969 + _RESETSTICKYTASKQUEUERESPONSE._serialized_start = 20971 + _RESETSTICKYTASKQUEUERESPONSE._serialized_end = 21001 + _SHUTDOWNWORKERREQUEST._serialized_start = 21004 + _SHUTDOWNWORKERREQUEST._serialized_end = 21287 + _SHUTDOWNWORKERRESPONSE._serialized_start = 21289 + _SHUTDOWNWORKERRESPONSE._serialized_end = 21313 + _QUERYWORKFLOWREQUEST._serialized_start = 21316 + _QUERYWORKFLOWREQUEST._serialized_end = 21549 + _QUERYWORKFLOWRESPONSE._serialized_start = 21552 + _QUERYWORKFLOWRESPONSE._serialized_end = 21737 + _DESCRIBEWORKFLOWEXECUTIONREQUEST._serialized_start = 21739 + _DESCRIBEWORKFLOWEXECUTIONREQUEST._serialized_end = 21854 + _DESCRIBEWORKFLOWEXECUTIONRESPONSE._serialized_start = 21857 + _DESCRIBEWORKFLOWEXECUTIONRESPONSE._serialized_end = 22522 + _DESCRIBETASKQUEUEREQUEST._serialized_start = 22525 + _DESCRIBETASKQUEUEREQUEST._serialized_end = 23053 + _DESCRIBETASKQUEUERESPONSE._serialized_start = 23056 + _DESCRIBETASKQUEUERESPONSE._serialized_end = 24060 + _DESCRIBETASKQUEUERESPONSE_STATSBYPRIORITYKEYENTRY._serialized_start = 23740 + _DESCRIBETASKQUEUERESPONSE_STATSBYPRIORITYKEYENTRY._serialized_end = 23840 + _DESCRIBETASKQUEUERESPONSE_EFFECTIVERATELIMIT._serialized_start = 23842 + _DESCRIBETASKQUEUERESPONSE_EFFECTIVERATELIMIT._serialized_end = 23958 + _DESCRIBETASKQUEUERESPONSE_VERSIONSINFOENTRY._serialized_start = 23960 + _DESCRIBETASKQUEUERESPONSE_VERSIONSINFOENTRY._serialized_end = 24060 + _GETCLUSTERINFOREQUEST._serialized_start = 24062 + _GETCLUSTERINFOREQUEST._serialized_end = 24085 + _GETCLUSTERINFORESPONSE._serialized_start = 24088 + _GETCLUSTERINFORESPONSE._serialized_end = 24553 + _GETCLUSTERINFORESPONSE_SUPPORTEDCLIENTSENTRY._serialized_start = 24498 + _GETCLUSTERINFORESPONSE_SUPPORTEDCLIENTSENTRY._serialized_end = 24553 + _GETSYSTEMINFOREQUEST._serialized_start = 24555 + _GETSYSTEMINFOREQUEST._serialized_end = 24577 + _GETSYSTEMINFORESPONSE._serialized_start = 24580 + _GETSYSTEMINFORESPONSE._serialized_end = 25157 + _GETSYSTEMINFORESPONSE_CAPABILITIES._serialized_start = 24721 + _GETSYSTEMINFORESPONSE_CAPABILITIES._serialized_end = 25157 + _LISTTASKQUEUEPARTITIONSREQUEST._serialized_start = 25159 + _LISTTASKQUEUEPARTITIONSREQUEST._serialized_end = 25268 + _LISTTASKQUEUEPARTITIONSRESPONSE._serialized_start = 25271 + _LISTTASKQUEUEPARTITIONSRESPONSE._serialized_end = 25494 + _CREATESCHEDULEREQUEST._serialized_start = 25497 + _CREATESCHEDULEREQUEST._serialized_end = 25829 + _CREATESCHEDULERESPONSE._serialized_start = 25831 + _CREATESCHEDULERESPONSE._serialized_end = 25879 + _DESCRIBESCHEDULEREQUEST._serialized_start = 25881 + _DESCRIBESCHEDULEREQUEST._serialized_end = 25946 + _DESCRIBESCHEDULERESPONSE._serialized_start = 25949 + _DESCRIBESCHEDULERESPONSE._serialized_end = 26220 + _UPDATESCHEDULEREQUEST._serialized_start = 26223 + _UPDATESCHEDULEREQUEST._serialized_end = 26515 + _UPDATESCHEDULERESPONSE._serialized_start = 26517 + _UPDATESCHEDULERESPONSE._serialized_end = 26541 + _PATCHSCHEDULEREQUEST._serialized_start = 26544 + _PATCHSCHEDULEREQUEST._serialized_end = 26700 + _PATCHSCHEDULERESPONSE._serialized_start = 26702 + _PATCHSCHEDULERESPONSE._serialized_end = 26725 + _LISTSCHEDULEMATCHINGTIMESREQUEST._serialized_start = 26728 + _LISTSCHEDULEMATCHINGTIMESREQUEST._serialized_end = 26896 + _LISTSCHEDULEMATCHINGTIMESRESPONSE._serialized_start = 26898 + _LISTSCHEDULEMATCHINGTIMESRESPONSE._serialized_end = 26981 + _DELETESCHEDULEREQUEST._serialized_start = 26983 + _DELETESCHEDULEREQUEST._serialized_end = 27064 + _DELETESCHEDULERESPONSE._serialized_start = 27066 + _DELETESCHEDULERESPONSE._serialized_end = 27090 + _LISTSCHEDULESREQUEST._serialized_start = 27092 + _LISTSCHEDULESREQUEST._serialized_end = 27200 + _LISTSCHEDULESRESPONSE._serialized_start = 27202 + _LISTSCHEDULESRESPONSE._serialized_end = 27314 + _COUNTSCHEDULESREQUEST._serialized_start = 27316 + _COUNTSCHEDULESREQUEST._serialized_end = 27373 + _COUNTSCHEDULESRESPONSE._serialized_start = 27376 + _COUNTSCHEDULESRESPONSE._serialized_end = 27595 + _COUNTSCHEDULESRESPONSE_AGGREGATIONGROUP._serialized_start = 20134 + _COUNTSCHEDULESRESPONSE_AGGREGATIONGROUP._serialized_end = 20222 + _UPDATEWORKERBUILDIDCOMPATIBILITYREQUEST._serialized_start = 27598 + _UPDATEWORKERBUILDIDCOMPATIBILITYREQUEST._serialized_end = 28244 + _UPDATEWORKERBUILDIDCOMPATIBILITYREQUEST_ADDNEWCOMPATIBLEVERSION._serialized_start = 28045 _UPDATEWORKERBUILDIDCOMPATIBILITYREQUEST_ADDNEWCOMPATIBLEVERSION._serialized_end = ( - 28069 + 28156 ) - _UPDATEWORKERBUILDIDCOMPATIBILITYREQUEST_MERGESETS._serialized_start = 28071 - _UPDATEWORKERBUILDIDCOMPATIBILITYREQUEST_MERGESETS._serialized_end = 28144 - _UPDATEWORKERBUILDIDCOMPATIBILITYRESPONSE._serialized_start = 28159 - _UPDATEWORKERBUILDIDCOMPATIBILITYRESPONSE._serialized_end = 28223 - _GETWORKERBUILDIDCOMPATIBILITYREQUEST._serialized_start = 28225 - _GETWORKERBUILDIDCOMPATIBILITYREQUEST._serialized_end = 28320 - _GETWORKERBUILDIDCOMPATIBILITYRESPONSE._serialized_start = 28322 - _GETWORKERBUILDIDCOMPATIBILITYRESPONSE._serialized_end = 28438 - _UPDATEWORKERVERSIONINGRULESREQUEST._serialized_start = 28441 - _UPDATEWORKERVERSIONINGRULESREQUEST._serialized_end = 30158 - _UPDATEWORKERVERSIONINGRULESREQUEST_INSERTBUILDIDASSIGNMENTRULE._serialized_start = 29493 + _UPDATEWORKERBUILDIDCOMPATIBILITYREQUEST_MERGESETS._serialized_start = 28158 + _UPDATEWORKERBUILDIDCOMPATIBILITYREQUEST_MERGESETS._serialized_end = 28231 + _UPDATEWORKERBUILDIDCOMPATIBILITYRESPONSE._serialized_start = 28246 + _UPDATEWORKERBUILDIDCOMPATIBILITYRESPONSE._serialized_end = 28310 + _GETWORKERBUILDIDCOMPATIBILITYREQUEST._serialized_start = 28312 + _GETWORKERBUILDIDCOMPATIBILITYREQUEST._serialized_end = 28407 + _GETWORKERBUILDIDCOMPATIBILITYRESPONSE._serialized_start = 28409 + _GETWORKERBUILDIDCOMPATIBILITYRESPONSE._serialized_end = 28525 + _UPDATEWORKERVERSIONINGRULESREQUEST._serialized_start = 28528 + _UPDATEWORKERVERSIONINGRULESREQUEST._serialized_end = 30245 + _UPDATEWORKERVERSIONINGRULESREQUEST_INSERTBUILDIDASSIGNMENTRULE._serialized_start = 29580 _UPDATEWORKERVERSIONINGRULESREQUEST_INSERTBUILDIDASSIGNMENTRULE._serialized_end = ( - 29606 + 29693 ) - _UPDATEWORKERVERSIONINGRULESREQUEST_REPLACEBUILDIDASSIGNMENTRULE._serialized_start = 29609 + _UPDATEWORKERVERSIONINGRULESREQUEST_REPLACEBUILDIDASSIGNMENTRULE._serialized_start = 29696 _UPDATEWORKERVERSIONINGRULESREQUEST_REPLACEBUILDIDASSIGNMENTRULE._serialized_end = ( - 29738 + 29825 ) - _UPDATEWORKERVERSIONINGRULESREQUEST_DELETEBUILDIDASSIGNMENTRULE._serialized_start = 29740 + _UPDATEWORKERVERSIONINGRULESREQUEST_DELETEBUILDIDASSIGNMENTRULE._serialized_start = 29827 _UPDATEWORKERVERSIONINGRULESREQUEST_DELETEBUILDIDASSIGNMENTRULE._serialized_end = ( - 29804 + 29891 ) - _UPDATEWORKERVERSIONINGRULESREQUEST_ADDCOMPATIBLEBUILDIDREDIRECTRULE._serialized_start = 29806 - _UPDATEWORKERVERSIONINGRULESREQUEST_ADDCOMPATIBLEBUILDIDREDIRECTRULE._serialized_end = 29912 - _UPDATEWORKERVERSIONINGRULESREQUEST_REPLACECOMPATIBLEBUILDIDREDIRECTRULE._serialized_start = 29914 - _UPDATEWORKERVERSIONINGRULESREQUEST_REPLACECOMPATIBLEBUILDIDREDIRECTRULE._serialized_end = 30024 - _UPDATEWORKERVERSIONINGRULESREQUEST_DELETECOMPATIBLEBUILDIDREDIRECTRULE._serialized_start = 30026 - _UPDATEWORKERVERSIONINGRULESREQUEST_DELETECOMPATIBLEBUILDIDREDIRECTRULE._serialized_end = 30088 - _UPDATEWORKERVERSIONINGRULESREQUEST_COMMITBUILDID._serialized_start = 30090 - _UPDATEWORKERVERSIONINGRULESREQUEST_COMMITBUILDID._serialized_end = 30145 - _UPDATEWORKERVERSIONINGRULESRESPONSE._serialized_start = 30161 - _UPDATEWORKERVERSIONINGRULESRESPONSE._serialized_end = 30413 - _GETWORKERVERSIONINGRULESREQUEST._serialized_start = 30415 - _GETWORKERVERSIONINGRULESREQUEST._serialized_end = 30487 - _GETWORKERVERSIONINGRULESRESPONSE._serialized_start = 30490 - _GETWORKERVERSIONINGRULESRESPONSE._serialized_end = 30739 - _GETWORKERTASKREACHABILITYREQUEST._serialized_start = 30742 - _GETWORKERTASKREACHABILITYREQUEST._serialized_end = 30898 - _GETWORKERTASKREACHABILITYRESPONSE._serialized_start = 30900 - _GETWORKERTASKREACHABILITYRESPONSE._serialized_end = 31014 - _UPDATEWORKFLOWEXECUTIONREQUEST._serialized_start = 31017 - _UPDATEWORKFLOWEXECUTIONREQUEST._serialized_end = 31278 - _UPDATEWORKFLOWEXECUTIONRESPONSE._serialized_start = 31281 - _UPDATEWORKFLOWEXECUTIONRESPONSE._serialized_end = 31540 - _STARTBATCHOPERATIONREQUEST._serialized_start = 31543 - _STARTBATCHOPERATIONREQUEST._serialized_end = 32909 - _STARTBATCHOPERATIONRESPONSE._serialized_start = 32911 - _STARTBATCHOPERATIONRESPONSE._serialized_end = 32940 - _STOPBATCHOPERATIONREQUEST._serialized_start = 32942 - _STOPBATCHOPERATIONREQUEST._serialized_end = 33038 - _STOPBATCHOPERATIONRESPONSE._serialized_start = 33040 - _STOPBATCHOPERATIONRESPONSE._serialized_end = 33068 - _DESCRIBEBATCHOPERATIONREQUEST._serialized_start = 33070 - _DESCRIBEBATCHOPERATIONREQUEST._serialized_end = 33136 - _DESCRIBEBATCHOPERATIONRESPONSE._serialized_start = 33139 - _DESCRIBEBATCHOPERATIONRESPONSE._serialized_end = 33611 - _LISTBATCHOPERATIONSREQUEST._serialized_start = 33613 - _LISTBATCHOPERATIONSREQUEST._serialized_end = 33704 - _LISTBATCHOPERATIONSRESPONSE._serialized_start = 33706 - _LISTBATCHOPERATIONSRESPONSE._serialized_end = 33827 - _POLLWORKFLOWEXECUTIONUPDATEREQUEST._serialized_start = 33830 - _POLLWORKFLOWEXECUTIONUPDATEREQUEST._serialized_end = 34015 - _POLLWORKFLOWEXECUTIONUPDATERESPONSE._serialized_start = 34018 - _POLLWORKFLOWEXECUTIONUPDATERESPONSE._serialized_end = 34237 - _POLLNEXUSTASKQUEUEREQUEST._serialized_start = 34240 - _POLLNEXUSTASKQUEUEREQUEST._serialized_end = 34656 - _POLLNEXUSTASKQUEUERESPONSE._serialized_start = 34659 - _POLLNEXUSTASKQUEUERESPONSE._serialized_end = 35013 - _RESPONDNEXUSTASKCOMPLETEDREQUEST._serialized_start = 35016 - _RESPONDNEXUSTASKCOMPLETEDREQUEST._serialized_end = 35183 - _RESPONDNEXUSTASKCOMPLETEDRESPONSE._serialized_start = 35185 - _RESPONDNEXUSTASKCOMPLETEDRESPONSE._serialized_end = 35220 - _RESPONDNEXUSTASKFAILEDREQUEST._serialized_start = 35223 - _RESPONDNEXUSTASKFAILEDREQUEST._serialized_end = 35443 - _RESPONDNEXUSTASKFAILEDRESPONSE._serialized_start = 35445 - _RESPONDNEXUSTASKFAILEDRESPONSE._serialized_end = 35477 - _EXECUTEMULTIOPERATIONREQUEST._serialized_start = 35480 - _EXECUTEMULTIOPERATIONREQUEST._serialized_end = 35852 - _EXECUTEMULTIOPERATIONREQUEST_OPERATION._serialized_start = 35646 - _EXECUTEMULTIOPERATIONREQUEST_OPERATION._serialized_end = 35852 - _EXECUTEMULTIOPERATIONRESPONSE._serialized_start = 35855 - _EXECUTEMULTIOPERATIONRESPONSE._serialized_end = 36187 - _EXECUTEMULTIOPERATIONRESPONSE_RESPONSE._serialized_start = 35981 - _EXECUTEMULTIOPERATIONRESPONSE_RESPONSE._serialized_end = 36187 - _UPDATEACTIVITYOPTIONSREQUEST._serialized_start = 36190 - _UPDATEACTIVITYOPTIONSREQUEST._serialized_end = 36526 - _UPDATEACTIVITYEXECUTIONOPTIONSREQUEST._serialized_start = 36529 - _UPDATEACTIVITYEXECUTIONOPTIONSREQUEST._serialized_end = 36828 - _UPDATEACTIVITYOPTIONSRESPONSE._serialized_start = 36830 - _UPDATEACTIVITYOPTIONSRESPONSE._serialized_end = 36930 - _UPDATEACTIVITYEXECUTIONOPTIONSRESPONSE._serialized_start = 36932 - _UPDATEACTIVITYEXECUTIONOPTIONSRESPONSE._serialized_end = 37041 - _PAUSEACTIVITYREQUEST._serialized_start = 37044 - _PAUSEACTIVITYREQUEST._serialized_end = 37243 - _PAUSEACTIVITYEXECUTIONREQUEST._serialized_start = 37246 - _PAUSEACTIVITYEXECUTIONREQUEST._serialized_end = 37429 - _PAUSEACTIVITYRESPONSE._serialized_start = 37431 - _PAUSEACTIVITYRESPONSE._serialized_end = 37454 - _PAUSEACTIVITYEXECUTIONRESPONSE._serialized_start = 37456 - _PAUSEACTIVITYEXECUTIONRESPONSE._serialized_end = 37488 - _UNPAUSEACTIVITYREQUEST._serialized_start = 37491 - _UNPAUSEACTIVITYREQUEST._serialized_end = 37771 - _UNPAUSEACTIVITYEXECUTIONREQUEST._serialized_start = 37774 - _UNPAUSEACTIVITYEXECUTIONREQUEST._serialized_end = 38031 - _UNPAUSEACTIVITYRESPONSE._serialized_start = 38033 - _UNPAUSEACTIVITYRESPONSE._serialized_end = 38058 - _UNPAUSEACTIVITYEXECUTIONRESPONSE._serialized_start = 38060 - _UNPAUSEACTIVITYEXECUTIONRESPONSE._serialized_end = 38094 - _RESETACTIVITYREQUEST._serialized_start = 38097 - _RESETACTIVITYREQUEST._serialized_end = 38404 - _RESETACTIVITYEXECUTIONREQUEST._serialized_start = 38407 - _RESETACTIVITYEXECUTIONREQUEST._serialized_end = 38652 - _RESETACTIVITYRESPONSE._serialized_start = 38654 - _RESETACTIVITYRESPONSE._serialized_end = 38677 - _RESETACTIVITYEXECUTIONRESPONSE._serialized_start = 38679 - _RESETACTIVITYEXECUTIONRESPONSE._serialized_end = 38711 - _UPDATEWORKFLOWEXECUTIONOPTIONSREQUEST._serialized_start = 38714 - _UPDATEWORKFLOWEXECUTIONOPTIONSREQUEST._serialized_end = 38998 - _UPDATEWORKFLOWEXECUTIONOPTIONSRESPONSE._serialized_start = 39001 - _UPDATEWORKFLOWEXECUTIONOPTIONSRESPONSE._serialized_end = 39178 - _DESCRIBEDEPLOYMENTREQUEST._serialized_start = 39180 - _DESCRIBEDEPLOYMENTREQUEST._serialized_end = 39286 - _DESCRIBEDEPLOYMENTRESPONSE._serialized_start = 39288 - _DESCRIBEDEPLOYMENTRESPONSE._serialized_end = 39385 - _DESCRIBEWORKERDEPLOYMENTVERSIONREQUEST._serialized_start = 39388 - _DESCRIBEWORKERDEPLOYMENTVERSIONREQUEST._serialized_end = 39582 - _DESCRIBEWORKERDEPLOYMENTVERSIONRESPONSE._serialized_start = 39585 - _DESCRIBEWORKERDEPLOYMENTVERSIONRESPONSE._serialized_end = 40237 - _DESCRIBEWORKERDEPLOYMENTVERSIONRESPONSE_VERSIONTASKQUEUE._serialized_start = 39846 - _DESCRIBEWORKERDEPLOYMENTVERSIONRESPONSE_VERSIONTASKQUEUE._serialized_end = 40237 - _DESCRIBEWORKERDEPLOYMENTVERSIONRESPONSE_VERSIONTASKQUEUE_STATSBYPRIORITYKEYENTRY._serialized_start = 23653 - _DESCRIBEWORKERDEPLOYMENTVERSIONRESPONSE_VERSIONTASKQUEUE_STATSBYPRIORITYKEYENTRY._serialized_end = 23753 - _DESCRIBEWORKERDEPLOYMENTREQUEST._serialized_start = 40239 - _DESCRIBEWORKERDEPLOYMENTREQUEST._serialized_end = 40316 - _DESCRIBEWORKERDEPLOYMENTRESPONSE._serialized_start = 40319 - _DESCRIBEWORKERDEPLOYMENTRESPONSE._serialized_end = 40459 - _LISTDEPLOYMENTSREQUEST._serialized_start = 40461 - _LISTDEPLOYMENTSREQUEST._serialized_end = 40569 - _LISTDEPLOYMENTSRESPONSE._serialized_start = 40571 - _LISTDEPLOYMENTSRESPONSE._serialized_end = 40690 - _SETCURRENTDEPLOYMENTREQUEST._serialized_start = 40693 - _SETCURRENTDEPLOYMENTREQUEST._serialized_end = 40898 - _SETCURRENTDEPLOYMENTRESPONSE._serialized_start = 40901 - _SETCURRENTDEPLOYMENTRESPONSE._serialized_end = 41086 - _SETWORKERDEPLOYMENTCURRENTVERSIONREQUEST._serialized_start = 41089 - _SETWORKERDEPLOYMENTCURRENTVERSIONREQUEST._serialized_end = 41318 - _SETWORKERDEPLOYMENTCURRENTVERSIONRESPONSE._serialized_start = 41321 - _SETWORKERDEPLOYMENTCURRENTVERSIONRESPONSE._serialized_end = 41512 - _SETWORKERDEPLOYMENTRAMPINGVERSIONREQUEST._serialized_start = 41515 - _SETWORKERDEPLOYMENTRAMPINGVERSIONREQUEST._serialized_end = 41764 - _SETWORKERDEPLOYMENTRAMPINGVERSIONRESPONSE._serialized_start = 41767 - _SETWORKERDEPLOYMENTRAMPINGVERSIONRESPONSE._serialized_end = 41991 - _CREATEWORKERDEPLOYMENTREQUEST._serialized_start = 41993 - _CREATEWORKERDEPLOYMENTREQUEST._serialized_end = 42106 - _CREATEWORKERDEPLOYMENTRESPONSE._serialized_start = 42108 - _CREATEWORKERDEPLOYMENTRESPONSE._serialized_end = 42164 - _LISTWORKERDEPLOYMENTSREQUEST._serialized_start = 42166 - _LISTWORKERDEPLOYMENTSREQUEST._serialized_end = 42259 - _LISTWORKERDEPLOYMENTSRESPONSE._serialized_start = 42262 - _LISTWORKERDEPLOYMENTSRESPONSE._serialized_end = 42933 - _LISTWORKERDEPLOYMENTSRESPONSE_WORKERDEPLOYMENTSUMMARY._serialized_start = 42437 - _LISTWORKERDEPLOYMENTSRESPONSE_WORKERDEPLOYMENTSUMMARY._serialized_end = 42933 - _CREATEWORKERDEPLOYMENTVERSIONREQUEST._serialized_start = 42936 - _CREATEWORKERDEPLOYMENTVERSIONREQUEST._serialized_end = 43176 - _CREATEWORKERDEPLOYMENTVERSIONRESPONSE._serialized_start = 43178 - _CREATEWORKERDEPLOYMENTVERSIONRESPONSE._serialized_end = 43217 - _DELETEWORKERDEPLOYMENTVERSIONREQUEST._serialized_start = 43220 - _DELETEWORKERDEPLOYMENTVERSIONREQUEST._serialized_end = 43420 - _DELETEWORKERDEPLOYMENTVERSIONRESPONSE._serialized_start = 43422 - _DELETEWORKERDEPLOYMENTVERSIONRESPONSE._serialized_end = 43461 - _DELETEWORKERDEPLOYMENTREQUEST._serialized_start = 43463 - _DELETEWORKERDEPLOYMENTREQUEST._serialized_end = 43556 - _DELETEWORKERDEPLOYMENTRESPONSE._serialized_start = 43558 - _DELETEWORKERDEPLOYMENTRESPONSE._serialized_end = 43590 - _UPDATEWORKERDEPLOYMENTVERSIONCOMPUTECONFIGREQUEST._serialized_start = 43593 - _UPDATEWORKERDEPLOYMENTVERSIONCOMPUTECONFIGREQUEST._serialized_end = 44109 - _UPDATEWORKERDEPLOYMENTVERSIONCOMPUTECONFIGREQUEST_COMPUTECONFIGSCALINGGROUPSENTRY._serialized_start = 43986 - _UPDATEWORKERDEPLOYMENTVERSIONCOMPUTECONFIGREQUEST_COMPUTECONFIGSCALINGGROUPSENTRY._serialized_end = 44109 - _UPDATEWORKERDEPLOYMENTVERSIONCOMPUTECONFIGRESPONSE._serialized_start = 44111 - _UPDATEWORKERDEPLOYMENTVERSIONCOMPUTECONFIGRESPONSE._serialized_end = 44163 - _VALIDATEWORKERDEPLOYMENTVERSIONCOMPUTECONFIGREQUEST._serialized_start = 44166 - _VALIDATEWORKERDEPLOYMENTVERSIONCOMPUTECONFIGREQUEST._serialized_end = 44666 - _VALIDATEWORKERDEPLOYMENTVERSIONCOMPUTECONFIGREQUEST_COMPUTECONFIGSCALINGGROUPSENTRY._serialized_start = 43986 - _VALIDATEWORKERDEPLOYMENTVERSIONCOMPUTECONFIGREQUEST_COMPUTECONFIGSCALINGGROUPSENTRY._serialized_end = 44109 - _VALIDATEWORKERDEPLOYMENTVERSIONCOMPUTECONFIGRESPONSE._serialized_start = 44668 - _VALIDATEWORKERDEPLOYMENTVERSIONCOMPUTECONFIGRESPONSE._serialized_end = 44722 - _UPDATEWORKERDEPLOYMENTVERSIONMETADATAREQUEST._serialized_start = 44725 - _UPDATEWORKERDEPLOYMENTVERSIONMETADATAREQUEST._serialized_end = 45143 - _UPDATEWORKERDEPLOYMENTVERSIONMETADATAREQUEST_UPSERTENTRIESENTRY._serialized_start = 45058 + _UPDATEWORKERVERSIONINGRULESREQUEST_ADDCOMPATIBLEBUILDIDREDIRECTRULE._serialized_start = 29893 + _UPDATEWORKERVERSIONINGRULESREQUEST_ADDCOMPATIBLEBUILDIDREDIRECTRULE._serialized_end = 29999 + _UPDATEWORKERVERSIONINGRULESREQUEST_REPLACECOMPATIBLEBUILDIDREDIRECTRULE._serialized_start = 30001 + _UPDATEWORKERVERSIONINGRULESREQUEST_REPLACECOMPATIBLEBUILDIDREDIRECTRULE._serialized_end = 30111 + _UPDATEWORKERVERSIONINGRULESREQUEST_DELETECOMPATIBLEBUILDIDREDIRECTRULE._serialized_start = 30113 + _UPDATEWORKERVERSIONINGRULESREQUEST_DELETECOMPATIBLEBUILDIDREDIRECTRULE._serialized_end = 30175 + _UPDATEWORKERVERSIONINGRULESREQUEST_COMMITBUILDID._serialized_start = 30177 + _UPDATEWORKERVERSIONINGRULESREQUEST_COMMITBUILDID._serialized_end = 30232 + _UPDATEWORKERVERSIONINGRULESRESPONSE._serialized_start = 30248 + _UPDATEWORKERVERSIONINGRULESRESPONSE._serialized_end = 30500 + _GETWORKERVERSIONINGRULESREQUEST._serialized_start = 30502 + _GETWORKERVERSIONINGRULESREQUEST._serialized_end = 30574 + _GETWORKERVERSIONINGRULESRESPONSE._serialized_start = 30577 + _GETWORKERVERSIONINGRULESRESPONSE._serialized_end = 30826 + _GETWORKERTASKREACHABILITYREQUEST._serialized_start = 30829 + _GETWORKERTASKREACHABILITYREQUEST._serialized_end = 30985 + _GETWORKERTASKREACHABILITYRESPONSE._serialized_start = 30987 + _GETWORKERTASKREACHABILITYRESPONSE._serialized_end = 31101 + _UPDATEWORKFLOWEXECUTIONREQUEST._serialized_start = 31104 + _UPDATEWORKFLOWEXECUTIONREQUEST._serialized_end = 31365 + _UPDATEWORKFLOWEXECUTIONRESPONSE._serialized_start = 31368 + _UPDATEWORKFLOWEXECUTIONRESPONSE._serialized_end = 31627 + _STARTBATCHOPERATIONREQUEST._serialized_start = 31630 + _STARTBATCHOPERATIONREQUEST._serialized_end = 32996 + _STARTBATCHOPERATIONRESPONSE._serialized_start = 32998 + _STARTBATCHOPERATIONRESPONSE._serialized_end = 33027 + _STOPBATCHOPERATIONREQUEST._serialized_start = 33029 + _STOPBATCHOPERATIONREQUEST._serialized_end = 33125 + _STOPBATCHOPERATIONRESPONSE._serialized_start = 33127 + _STOPBATCHOPERATIONRESPONSE._serialized_end = 33155 + _DESCRIBEBATCHOPERATIONREQUEST._serialized_start = 33157 + _DESCRIBEBATCHOPERATIONREQUEST._serialized_end = 33223 + _DESCRIBEBATCHOPERATIONRESPONSE._serialized_start = 33226 + _DESCRIBEBATCHOPERATIONRESPONSE._serialized_end = 33698 + _LISTBATCHOPERATIONSREQUEST._serialized_start = 33700 + _LISTBATCHOPERATIONSREQUEST._serialized_end = 33791 + _LISTBATCHOPERATIONSRESPONSE._serialized_start = 33793 + _LISTBATCHOPERATIONSRESPONSE._serialized_end = 33914 + _POLLWORKFLOWEXECUTIONUPDATEREQUEST._serialized_start = 33917 + _POLLWORKFLOWEXECUTIONUPDATEREQUEST._serialized_end = 34102 + _POLLWORKFLOWEXECUTIONUPDATERESPONSE._serialized_start = 34105 + _POLLWORKFLOWEXECUTIONUPDATERESPONSE._serialized_end = 34324 + _POLLNEXUSTASKQUEUEREQUEST._serialized_start = 34327 + _POLLNEXUSTASKQUEUEREQUEST._serialized_end = 34743 + _POLLNEXUSTASKQUEUERESPONSE._serialized_start = 34746 + _POLLNEXUSTASKQUEUERESPONSE._serialized_end = 35100 + _RESPONDNEXUSTASKCOMPLETEDREQUEST._serialized_start = 35103 + _RESPONDNEXUSTASKCOMPLETEDREQUEST._serialized_end = 35270 + _RESPONDNEXUSTASKCOMPLETEDRESPONSE._serialized_start = 35272 + _RESPONDNEXUSTASKCOMPLETEDRESPONSE._serialized_end = 35307 + _RESPONDNEXUSTASKFAILEDREQUEST._serialized_start = 35310 + _RESPONDNEXUSTASKFAILEDREQUEST._serialized_end = 35530 + _RESPONDNEXUSTASKFAILEDRESPONSE._serialized_start = 35532 + _RESPONDNEXUSTASKFAILEDRESPONSE._serialized_end = 35564 + _EXECUTEMULTIOPERATIONREQUEST._serialized_start = 35567 + _EXECUTEMULTIOPERATIONREQUEST._serialized_end = 35939 + _EXECUTEMULTIOPERATIONREQUEST_OPERATION._serialized_start = 35733 + _EXECUTEMULTIOPERATIONREQUEST_OPERATION._serialized_end = 35939 + _EXECUTEMULTIOPERATIONRESPONSE._serialized_start = 35942 + _EXECUTEMULTIOPERATIONRESPONSE._serialized_end = 36274 + _EXECUTEMULTIOPERATIONRESPONSE_RESPONSE._serialized_start = 36068 + _EXECUTEMULTIOPERATIONRESPONSE_RESPONSE._serialized_end = 36274 + _UPDATEACTIVITYOPTIONSREQUEST._serialized_start = 36277 + _UPDATEACTIVITYOPTIONSREQUEST._serialized_end = 36613 + _UPDATEACTIVITYEXECUTIONOPTIONSREQUEST._serialized_start = 36616 + _UPDATEACTIVITYEXECUTIONOPTIONSREQUEST._serialized_end = 36935 + _UPDATEACTIVITYOPTIONSRESPONSE._serialized_start = 36937 + _UPDATEACTIVITYOPTIONSRESPONSE._serialized_end = 37037 + _UPDATEACTIVITYEXECUTIONOPTIONSRESPONSE._serialized_start = 37039 + _UPDATEACTIVITYEXECUTIONOPTIONSRESPONSE._serialized_end = 37148 + _PAUSEACTIVITYREQUEST._serialized_start = 37151 + _PAUSEACTIVITYREQUEST._serialized_end = 37350 + _PAUSEACTIVITYEXECUTIONREQUEST._serialized_start = 37353 + _PAUSEACTIVITYEXECUTIONREQUEST._serialized_end = 37536 + _PAUSEACTIVITYRESPONSE._serialized_start = 37538 + _PAUSEACTIVITYRESPONSE._serialized_end = 37561 + _PAUSEACTIVITYEXECUTIONRESPONSE._serialized_start = 37563 + _PAUSEACTIVITYEXECUTIONRESPONSE._serialized_end = 37595 + _UNPAUSEACTIVITYREQUEST._serialized_start = 37598 + _UNPAUSEACTIVITYREQUEST._serialized_end = 37878 + _UNPAUSEACTIVITYEXECUTIONREQUEST._serialized_start = 37881 + _UNPAUSEACTIVITYEXECUTIONREQUEST._serialized_end = 38154 + _UNPAUSEACTIVITYRESPONSE._serialized_start = 38156 + _UNPAUSEACTIVITYRESPONSE._serialized_end = 38181 + _UNPAUSEACTIVITYEXECUTIONRESPONSE._serialized_start = 38183 + _UNPAUSEACTIVITYEXECUTIONRESPONSE._serialized_end = 38217 + _RESETACTIVITYREQUEST._serialized_start = 38220 + _RESETACTIVITYREQUEST._serialized_end = 38527 + _RESETACTIVITYEXECUTIONREQUEST._serialized_start = 38530 + _RESETACTIVITYEXECUTIONREQUEST._serialized_end = 38795 + _RESETACTIVITYRESPONSE._serialized_start = 38797 + _RESETACTIVITYRESPONSE._serialized_end = 38820 + _RESETACTIVITYEXECUTIONRESPONSE._serialized_start = 38822 + _RESETACTIVITYEXECUTIONRESPONSE._serialized_end = 38854 + _UPDATEWORKFLOWEXECUTIONOPTIONSREQUEST._serialized_start = 38857 + _UPDATEWORKFLOWEXECUTIONOPTIONSREQUEST._serialized_end = 39141 + _UPDATEWORKFLOWEXECUTIONOPTIONSRESPONSE._serialized_start = 39144 + _UPDATEWORKFLOWEXECUTIONOPTIONSRESPONSE._serialized_end = 39321 + _DESCRIBEDEPLOYMENTREQUEST._serialized_start = 39323 + _DESCRIBEDEPLOYMENTREQUEST._serialized_end = 39429 + _DESCRIBEDEPLOYMENTRESPONSE._serialized_start = 39431 + _DESCRIBEDEPLOYMENTRESPONSE._serialized_end = 39528 + _DESCRIBEWORKERDEPLOYMENTVERSIONREQUEST._serialized_start = 39531 + _DESCRIBEWORKERDEPLOYMENTVERSIONREQUEST._serialized_end = 39725 + _DESCRIBEWORKERDEPLOYMENTVERSIONRESPONSE._serialized_start = 39728 + _DESCRIBEWORKERDEPLOYMENTVERSIONRESPONSE._serialized_end = 40380 + _DESCRIBEWORKERDEPLOYMENTVERSIONRESPONSE_VERSIONTASKQUEUE._serialized_start = 39989 + _DESCRIBEWORKERDEPLOYMENTVERSIONRESPONSE_VERSIONTASKQUEUE._serialized_end = 40380 + _DESCRIBEWORKERDEPLOYMENTVERSIONRESPONSE_VERSIONTASKQUEUE_STATSBYPRIORITYKEYENTRY._serialized_start = 23740 + _DESCRIBEWORKERDEPLOYMENTVERSIONRESPONSE_VERSIONTASKQUEUE_STATSBYPRIORITYKEYENTRY._serialized_end = 23840 + _DESCRIBEWORKERDEPLOYMENTREQUEST._serialized_start = 40382 + _DESCRIBEWORKERDEPLOYMENTREQUEST._serialized_end = 40459 + _DESCRIBEWORKERDEPLOYMENTRESPONSE._serialized_start = 40462 + _DESCRIBEWORKERDEPLOYMENTRESPONSE._serialized_end = 40602 + _LISTDEPLOYMENTSREQUEST._serialized_start = 40604 + _LISTDEPLOYMENTSREQUEST._serialized_end = 40712 + _LISTDEPLOYMENTSRESPONSE._serialized_start = 40714 + _LISTDEPLOYMENTSRESPONSE._serialized_end = 40833 + _SETCURRENTDEPLOYMENTREQUEST._serialized_start = 40836 + _SETCURRENTDEPLOYMENTREQUEST._serialized_end = 41041 + _SETCURRENTDEPLOYMENTRESPONSE._serialized_start = 41044 + _SETCURRENTDEPLOYMENTRESPONSE._serialized_end = 41229 + _SETWORKERDEPLOYMENTCURRENTVERSIONREQUEST._serialized_start = 41232 + _SETWORKERDEPLOYMENTCURRENTVERSIONREQUEST._serialized_end = 41461 + _SETWORKERDEPLOYMENTCURRENTVERSIONRESPONSE._serialized_start = 41464 + _SETWORKERDEPLOYMENTCURRENTVERSIONRESPONSE._serialized_end = 41655 + _SETWORKERDEPLOYMENTRAMPINGVERSIONREQUEST._serialized_start = 41658 + _SETWORKERDEPLOYMENTRAMPINGVERSIONREQUEST._serialized_end = 41907 + _SETWORKERDEPLOYMENTRAMPINGVERSIONRESPONSE._serialized_start = 41910 + _SETWORKERDEPLOYMENTRAMPINGVERSIONRESPONSE._serialized_end = 42134 + _CREATEWORKERDEPLOYMENTREQUEST._serialized_start = 42136 + _CREATEWORKERDEPLOYMENTREQUEST._serialized_end = 42249 + _CREATEWORKERDEPLOYMENTRESPONSE._serialized_start = 42251 + _CREATEWORKERDEPLOYMENTRESPONSE._serialized_end = 42307 + _LISTWORKERDEPLOYMENTSREQUEST._serialized_start = 42309 + _LISTWORKERDEPLOYMENTSREQUEST._serialized_end = 42402 + _LISTWORKERDEPLOYMENTSRESPONSE._serialized_start = 42405 + _LISTWORKERDEPLOYMENTSRESPONSE._serialized_end = 43076 + _LISTWORKERDEPLOYMENTSRESPONSE_WORKERDEPLOYMENTSUMMARY._serialized_start = 42580 + _LISTWORKERDEPLOYMENTSRESPONSE_WORKERDEPLOYMENTSUMMARY._serialized_end = 43076 + _CREATEWORKERDEPLOYMENTVERSIONREQUEST._serialized_start = 43079 + _CREATEWORKERDEPLOYMENTVERSIONREQUEST._serialized_end = 43319 + _CREATEWORKERDEPLOYMENTVERSIONRESPONSE._serialized_start = 43321 + _CREATEWORKERDEPLOYMENTVERSIONRESPONSE._serialized_end = 43360 + _DELETEWORKERDEPLOYMENTVERSIONREQUEST._serialized_start = 43363 + _DELETEWORKERDEPLOYMENTVERSIONREQUEST._serialized_end = 43563 + _DELETEWORKERDEPLOYMENTVERSIONRESPONSE._serialized_start = 43565 + _DELETEWORKERDEPLOYMENTVERSIONRESPONSE._serialized_end = 43604 + _DELETEWORKERDEPLOYMENTREQUEST._serialized_start = 43606 + _DELETEWORKERDEPLOYMENTREQUEST._serialized_end = 43699 + _DELETEWORKERDEPLOYMENTRESPONSE._serialized_start = 43701 + _DELETEWORKERDEPLOYMENTRESPONSE._serialized_end = 43733 + _UPDATEWORKERDEPLOYMENTVERSIONCOMPUTECONFIGREQUEST._serialized_start = 43736 + _UPDATEWORKERDEPLOYMENTVERSIONCOMPUTECONFIGREQUEST._serialized_end = 44252 + _UPDATEWORKERDEPLOYMENTVERSIONCOMPUTECONFIGREQUEST_COMPUTECONFIGSCALINGGROUPSENTRY._serialized_start = 44129 + _UPDATEWORKERDEPLOYMENTVERSIONCOMPUTECONFIGREQUEST_COMPUTECONFIGSCALINGGROUPSENTRY._serialized_end = 44252 + _UPDATEWORKERDEPLOYMENTVERSIONCOMPUTECONFIGRESPONSE._serialized_start = 44254 + _UPDATEWORKERDEPLOYMENTVERSIONCOMPUTECONFIGRESPONSE._serialized_end = 44306 + _VALIDATEWORKERDEPLOYMENTVERSIONCOMPUTECONFIGREQUEST._serialized_start = 44309 + _VALIDATEWORKERDEPLOYMENTVERSIONCOMPUTECONFIGREQUEST._serialized_end = 44809 + _VALIDATEWORKERDEPLOYMENTVERSIONCOMPUTECONFIGREQUEST_COMPUTECONFIGSCALINGGROUPSENTRY._serialized_start = 44129 + _VALIDATEWORKERDEPLOYMENTVERSIONCOMPUTECONFIGREQUEST_COMPUTECONFIGSCALINGGROUPSENTRY._serialized_end = 44252 + _VALIDATEWORKERDEPLOYMENTVERSIONCOMPUTECONFIGRESPONSE._serialized_start = 44811 + _VALIDATEWORKERDEPLOYMENTVERSIONCOMPUTECONFIGRESPONSE._serialized_end = 44865 + _UPDATEWORKERDEPLOYMENTVERSIONMETADATAREQUEST._serialized_start = 44868 + _UPDATEWORKERDEPLOYMENTVERSIONMETADATAREQUEST._serialized_end = 45286 + _UPDATEWORKERDEPLOYMENTVERSIONMETADATAREQUEST_UPSERTENTRIESENTRY._serialized_start = 45201 _UPDATEWORKERDEPLOYMENTVERSIONMETADATAREQUEST_UPSERTENTRIESENTRY._serialized_end = ( - 45143 + 45286 ) - _UPDATEWORKERDEPLOYMENTVERSIONMETADATARESPONSE._serialized_start = 45145 - _UPDATEWORKERDEPLOYMENTVERSIONMETADATARESPONSE._serialized_end = 45255 - _SETWORKERDEPLOYMENTMANAGERREQUEST._serialized_start = 45258 - _SETWORKERDEPLOYMENTMANAGERREQUEST._serialized_end = 45447 - _SETWORKERDEPLOYMENTMANAGERRESPONSE._serialized_start = 45449 - _SETWORKERDEPLOYMENTMANAGERRESPONSE._serialized_end = 45548 - _GETCURRENTDEPLOYMENTREQUEST._serialized_start = 45550 - _GETCURRENTDEPLOYMENTREQUEST._serialized_end = 45619 - _GETCURRENTDEPLOYMENTRESPONSE._serialized_start = 45621 - _GETCURRENTDEPLOYMENTRESPONSE._serialized_end = 45728 - _GETDEPLOYMENTREACHABILITYREQUEST._serialized_start = 45730 - _GETDEPLOYMENTREACHABILITYREQUEST._serialized_end = 45843 - _GETDEPLOYMENTREACHABILITYRESPONSE._serialized_start = 45846 - _GETDEPLOYMENTREACHABILITYRESPONSE._serialized_end = 46073 - _CREATEWORKFLOWRULEREQUEST._serialized_start = 46076 - _CREATEWORKFLOWRULEREQUEST._serialized_end = 46256 - _CREATEWORKFLOWRULERESPONSE._serialized_start = 46258 - _CREATEWORKFLOWRULERESPONSE._serialized_end = 46353 - _DESCRIBEWORKFLOWRULEREQUEST._serialized_start = 46355 - _DESCRIBEWORKFLOWRULEREQUEST._serialized_end = 46420 - _DESCRIBEWORKFLOWRULERESPONSE._serialized_start = 46422 - _DESCRIBEWORKFLOWRULERESPONSE._serialized_end = 46503 - _DELETEWORKFLOWRULEREQUEST._serialized_start = 46505 - _DELETEWORKFLOWRULEREQUEST._serialized_end = 46568 - _DELETEWORKFLOWRULERESPONSE._serialized_start = 46570 - _DELETEWORKFLOWRULERESPONSE._serialized_end = 46598 - _LISTWORKFLOWRULESREQUEST._serialized_start = 46600 - _LISTWORKFLOWRULESREQUEST._serialized_end = 46670 - _LISTWORKFLOWRULESRESPONSE._serialized_start = 46672 - _LISTWORKFLOWRULESRESPONSE._serialized_end = 46776 - _TRIGGERWORKFLOWRULEREQUEST._serialized_start = 46779 - _TRIGGERWORKFLOWRULEREQUEST._serialized_end = 46985 - _TRIGGERWORKFLOWRULERESPONSE._serialized_start = 46987 - _TRIGGERWORKFLOWRULERESPONSE._serialized_end = 47033 - _RECORDWORKERHEARTBEATREQUEST._serialized_start = 47036 - _RECORDWORKERHEARTBEATREQUEST._serialized_end = 47191 - _RECORDWORKERHEARTBEATRESPONSE._serialized_start = 47193 - _RECORDWORKERHEARTBEATRESPONSE._serialized_end = 47224 - _LISTWORKERSREQUEST._serialized_start = 47227 - _LISTWORKERSREQUEST._serialized_end = 47357 - _LISTWORKERSRESPONSE._serialized_start = 47360 - _LISTWORKERSRESPONSE._serialized_end = 47525 - _UPDATETASKQUEUECONFIGREQUEST._serialized_start = 47528 - _UPDATETASKQUEUECONFIGREQUEST._serialized_end = 48253 - _UPDATETASKQUEUECONFIGREQUEST_RATELIMITUPDATE._serialized_start = 48095 - _UPDATETASKQUEUECONFIGREQUEST_RATELIMITUPDATE._serialized_end = 48186 + _UPDATEWORKERDEPLOYMENTVERSIONMETADATARESPONSE._serialized_start = 45288 + _UPDATEWORKERDEPLOYMENTVERSIONMETADATARESPONSE._serialized_end = 45398 + _SETWORKERDEPLOYMENTMANAGERREQUEST._serialized_start = 45401 + _SETWORKERDEPLOYMENTMANAGERREQUEST._serialized_end = 45590 + _SETWORKERDEPLOYMENTMANAGERRESPONSE._serialized_start = 45592 + _SETWORKERDEPLOYMENTMANAGERRESPONSE._serialized_end = 45691 + _GETCURRENTDEPLOYMENTREQUEST._serialized_start = 45693 + _GETCURRENTDEPLOYMENTREQUEST._serialized_end = 45762 + _GETCURRENTDEPLOYMENTRESPONSE._serialized_start = 45764 + _GETCURRENTDEPLOYMENTRESPONSE._serialized_end = 45871 + _GETDEPLOYMENTREACHABILITYREQUEST._serialized_start = 45873 + _GETDEPLOYMENTREACHABILITYREQUEST._serialized_end = 45986 + _GETDEPLOYMENTREACHABILITYRESPONSE._serialized_start = 45989 + _GETDEPLOYMENTREACHABILITYRESPONSE._serialized_end = 46216 + _CREATEWORKFLOWRULEREQUEST._serialized_start = 46219 + _CREATEWORKFLOWRULEREQUEST._serialized_end = 46399 + _CREATEWORKFLOWRULERESPONSE._serialized_start = 46401 + _CREATEWORKFLOWRULERESPONSE._serialized_end = 46496 + _DESCRIBEWORKFLOWRULEREQUEST._serialized_start = 46498 + _DESCRIBEWORKFLOWRULEREQUEST._serialized_end = 46563 + _DESCRIBEWORKFLOWRULERESPONSE._serialized_start = 46565 + _DESCRIBEWORKFLOWRULERESPONSE._serialized_end = 46646 + _DELETEWORKFLOWRULEREQUEST._serialized_start = 46648 + _DELETEWORKFLOWRULEREQUEST._serialized_end = 46711 + _DELETEWORKFLOWRULERESPONSE._serialized_start = 46713 + _DELETEWORKFLOWRULERESPONSE._serialized_end = 46741 + _LISTWORKFLOWRULESREQUEST._serialized_start = 46743 + _LISTWORKFLOWRULESREQUEST._serialized_end = 46813 + _LISTWORKFLOWRULESRESPONSE._serialized_start = 46815 + _LISTWORKFLOWRULESRESPONSE._serialized_end = 46919 + _TRIGGERWORKFLOWRULEREQUEST._serialized_start = 46922 + _TRIGGERWORKFLOWRULEREQUEST._serialized_end = 47128 + _TRIGGERWORKFLOWRULERESPONSE._serialized_start = 47130 + _TRIGGERWORKFLOWRULERESPONSE._serialized_end = 47176 + _RECORDWORKERHEARTBEATREQUEST._serialized_start = 47179 + _RECORDWORKERHEARTBEATREQUEST._serialized_end = 47334 + _RECORDWORKERHEARTBEATRESPONSE._serialized_start = 47336 + _RECORDWORKERHEARTBEATRESPONSE._serialized_end = 47367 + _LISTWORKERSREQUEST._serialized_start = 47370 + _LISTWORKERSREQUEST._serialized_end = 47500 + _LISTWORKERSRESPONSE._serialized_start = 47503 + _LISTWORKERSRESPONSE._serialized_end = 47668 + _UPDATETASKQUEUECONFIGREQUEST._serialized_start = 47671 + _UPDATETASKQUEUECONFIGREQUEST._serialized_end = 48396 + _UPDATETASKQUEUECONFIGREQUEST_RATELIMITUPDATE._serialized_start = 48238 + _UPDATETASKQUEUECONFIGREQUEST_RATELIMITUPDATE._serialized_end = 48329 _UPDATETASKQUEUECONFIGREQUEST_SETFAIRNESSWEIGHTOVERRIDESENTRY._serialized_start = ( - 48188 + 48331 ) _UPDATETASKQUEUECONFIGREQUEST_SETFAIRNESSWEIGHTOVERRIDESENTRY._serialized_end = ( - 48253 + 48396 ) - _UPDATETASKQUEUECONFIGRESPONSE._serialized_start = 48255 - _UPDATETASKQUEUECONFIGRESPONSE._serialized_end = 48346 - _FETCHWORKERCONFIGREQUEST._serialized_start = 48349 - _FETCHWORKERCONFIGREQUEST._serialized_end = 48507 - _FETCHWORKERCONFIGRESPONSE._serialized_start = 48509 - _FETCHWORKERCONFIGRESPONSE._serialized_end = 48594 - _UPDATEWORKERCONFIGREQUEST._serialized_start = 48597 - _UPDATEWORKERCONFIGREQUEST._serialized_end = 48863 - _UPDATEWORKERCONFIGRESPONSE._serialized_start = 48865 - _UPDATEWORKERCONFIGRESPONSE._serialized_end = 48965 - _DESCRIBEWORKERREQUEST._serialized_start = 48967 - _DESCRIBEWORKERREQUEST._serialized_end = 49038 - _DESCRIBEWORKERRESPONSE._serialized_start = 49040 - _DESCRIBEWORKERRESPONSE._serialized_end = 49121 - _COUNTWORKERSREQUEST._serialized_start = 49123 - _COUNTWORKERSREQUEST._serialized_end = 49210 - _COUNTWORKERSRESPONSE._serialized_start = 49212 - _COUNTWORKERSRESPONSE._serialized_end = 49249 - _PAUSEWORKFLOWEXECUTIONREQUEST._serialized_start = 49252 - _PAUSEWORKFLOWEXECUTIONREQUEST._serialized_end = 49393 - _PAUSEWORKFLOWEXECUTIONRESPONSE._serialized_start = 49395 - _PAUSEWORKFLOWEXECUTIONRESPONSE._serialized_end = 49427 - _UNPAUSEWORKFLOWEXECUTIONREQUEST._serialized_start = 49430 - _UNPAUSEWORKFLOWEXECUTIONREQUEST._serialized_end = 49573 - _UNPAUSEWORKFLOWEXECUTIONRESPONSE._serialized_start = 49575 - _UNPAUSEWORKFLOWEXECUTIONRESPONSE._serialized_end = 49609 - _STARTACTIVITYEXECUTIONREQUEST._serialized_start = 49612 - _STARTACTIVITYEXECUTIONREQUEST._serialized_end = 50789 - _STARTACTIVITYEXECUTIONRESPONSE._serialized_start = 50791 - _STARTACTIVITYEXECUTIONRESPONSE._serialized_end = 50900 - _DESCRIBEACTIVITYEXECUTIONREQUEST._serialized_start = 50903 - _DESCRIBEACTIVITYEXECUTIONREQUEST._serialized_end = 51131 - _DESCRIBEACTIVITYEXECUTIONRESPONSE._serialized_start = 51134 - _DESCRIBEACTIVITYEXECUTIONRESPONSE._serialized_end = 51450 - _POLLACTIVITYEXECUTIONREQUEST._serialized_start = 51452 - _POLLACTIVITYEXECUTIONREQUEST._serialized_end = 51538 - _POLLACTIVITYEXECUTIONRESPONSE._serialized_start = 51540 - _POLLACTIVITYEXECUTIONRESPONSE._serialized_end = 51656 - _LISTACTIVITYEXECUTIONSREQUEST._serialized_start = 51658 - _LISTACTIVITYEXECUTIONSREQUEST._serialized_end = 51767 - _LISTACTIVITYEXECUTIONSRESPONSE._serialized_start = 51770 - _LISTACTIVITYEXECUTIONSRESPONSE._serialized_end = 51900 - _STARTNEXUSOPERATIONEXECUTIONREQUEST._serialized_start = 51903 - _STARTNEXUSOPERATIONEXECUTIONREQUEST._serialized_end = 52752 - _STARTNEXUSOPERATIONEXECUTIONREQUEST_NEXUSHEADERENTRY._serialized_start = 52702 - _STARTNEXUSOPERATIONEXECUTIONREQUEST_NEXUSHEADERENTRY._serialized_end = 52752 - _STARTNEXUSOPERATIONEXECUTIONRESPONSE._serialized_start = 52754 - _STARTNEXUSOPERATIONEXECUTIONRESPONSE._serialized_end = 52825 - _DESCRIBENEXUSOPERATIONEXECUTIONREQUEST._serialized_start = 52828 - _DESCRIBENEXUSOPERATIONEXECUTIONREQUEST._serialized_end = 52998 - _DESCRIBENEXUSOPERATIONEXECUTIONRESPONSE._serialized_start = 53001 - _DESCRIBENEXUSOPERATIONEXECUTIONRESPONSE._serialized_end = 53312 - _POLLNEXUSOPERATIONEXECUTIONREQUEST._serialized_start = 53315 - _POLLNEXUSOPERATIONEXECUTIONREQUEST._serialized_end = 53476 - _POLLNEXUSOPERATIONEXECUTIONRESPONSE._serialized_start = 53479 - _POLLNEXUSOPERATIONEXECUTIONRESPONSE._serialized_end = 53740 - _LISTNEXUSOPERATIONEXECUTIONSREQUEST._serialized_start = 53742 - _LISTNEXUSOPERATIONEXECUTIONSREQUEST._serialized_end = 53857 - _LISTNEXUSOPERATIONEXECUTIONSRESPONSE._serialized_start = 53860 - _LISTNEXUSOPERATIONEXECUTIONSRESPONSE._serialized_end = 53999 - _COUNTACTIVITYEXECUTIONSREQUEST._serialized_start = 54001 - _COUNTACTIVITYEXECUTIONSREQUEST._serialized_end = 54067 - _COUNTACTIVITYEXECUTIONSRESPONSE._serialized_start = 54070 - _COUNTACTIVITYEXECUTIONSRESPONSE._serialized_end = 54307 - _COUNTACTIVITYEXECUTIONSRESPONSE_AGGREGATIONGROUP._serialized_start = 20091 - _COUNTACTIVITYEXECUTIONSRESPONSE_AGGREGATIONGROUP._serialized_end = 20179 - _COUNTNEXUSOPERATIONEXECUTIONSREQUEST._serialized_start = 54309 - _COUNTNEXUSOPERATIONEXECUTIONSREQUEST._serialized_end = 54381 - _COUNTNEXUSOPERATIONEXECUTIONSRESPONSE._serialized_start = 54384 - _COUNTNEXUSOPERATIONEXECUTIONSRESPONSE._serialized_end = 54633 - _COUNTNEXUSOPERATIONEXECUTIONSRESPONSE_AGGREGATIONGROUP._serialized_start = 20091 - _COUNTNEXUSOPERATIONEXECUTIONSRESPONSE_AGGREGATIONGROUP._serialized_end = 20179 - _REQUESTCANCELACTIVITYEXECUTIONREQUEST._serialized_start = 54636 - _REQUESTCANCELACTIVITYEXECUTIONREQUEST._serialized_end = 54785 - _REQUESTCANCELACTIVITYEXECUTIONRESPONSE._serialized_start = 54787 - _REQUESTCANCELACTIVITYEXECUTIONRESPONSE._serialized_end = 54827 - _TERMINATEACTIVITYEXECUTIONREQUEST._serialized_start = 54830 - _TERMINATEACTIVITYEXECUTIONREQUEST._serialized_end = 54975 - _TERMINATEACTIVITYEXECUTIONRESPONSE._serialized_start = 54977 - _TERMINATEACTIVITYEXECUTIONRESPONSE._serialized_end = 55013 - _DELETEACTIVITYEXECUTIONREQUEST._serialized_start = 55015 - _DELETEACTIVITYEXECUTIONREQUEST._serialized_end = 55103 - _DELETEACTIVITYEXECUTIONRESPONSE._serialized_start = 55105 - _DELETEACTIVITYEXECUTIONRESPONSE._serialized_end = 55138 - _REQUESTCANCELNEXUSOPERATIONEXECUTIONREQUEST._serialized_start = 55141 - _REQUESTCANCELNEXUSOPERATIONEXECUTIONREQUEST._serialized_end = 55297 - _REQUESTCANCELNEXUSOPERATIONEXECUTIONRESPONSE._serialized_start = 55299 - _REQUESTCANCELNEXUSOPERATIONEXECUTIONRESPONSE._serialized_end = 55345 - _TERMINATENEXUSOPERATIONEXECUTIONREQUEST._serialized_start = 55348 - _TERMINATENEXUSOPERATIONEXECUTIONREQUEST._serialized_end = 55500 - _TERMINATENEXUSOPERATIONEXECUTIONRESPONSE._serialized_start = 55502 - _TERMINATENEXUSOPERATIONEXECUTIONRESPONSE._serialized_end = 55544 - _DELETENEXUSOPERATIONEXECUTIONREQUEST._serialized_start = 55546 - _DELETENEXUSOPERATIONEXECUTIONREQUEST._serialized_end = 55641 - _DELETENEXUSOPERATIONEXECUTIONRESPONSE._serialized_start = 55643 - _DELETENEXUSOPERATIONEXECUTIONRESPONSE._serialized_end = 55682 + _UPDATETASKQUEUECONFIGRESPONSE._serialized_start = 48398 + _UPDATETASKQUEUECONFIGRESPONSE._serialized_end = 48489 + _FETCHWORKERCONFIGREQUEST._serialized_start = 48492 + _FETCHWORKERCONFIGREQUEST._serialized_end = 48650 + _FETCHWORKERCONFIGRESPONSE._serialized_start = 48652 + _FETCHWORKERCONFIGRESPONSE._serialized_end = 48737 + _UPDATEWORKERCONFIGREQUEST._serialized_start = 48740 + _UPDATEWORKERCONFIGREQUEST._serialized_end = 49006 + _UPDATEWORKERCONFIGRESPONSE._serialized_start = 49008 + _UPDATEWORKERCONFIGRESPONSE._serialized_end = 49108 + _DESCRIBEWORKERREQUEST._serialized_start = 49110 + _DESCRIBEWORKERREQUEST._serialized_end = 49181 + _DESCRIBEWORKERRESPONSE._serialized_start = 49183 + _DESCRIBEWORKERRESPONSE._serialized_end = 49264 + _COUNTWORKERSREQUEST._serialized_start = 49266 + _COUNTWORKERSREQUEST._serialized_end = 49353 + _COUNTWORKERSRESPONSE._serialized_start = 49355 + _COUNTWORKERSRESPONSE._serialized_end = 49392 + _PAUSEWORKFLOWEXECUTIONREQUEST._serialized_start = 49395 + _PAUSEWORKFLOWEXECUTIONREQUEST._serialized_end = 49536 + _PAUSEWORKFLOWEXECUTIONRESPONSE._serialized_start = 49538 + _PAUSEWORKFLOWEXECUTIONRESPONSE._serialized_end = 49570 + _UNPAUSEWORKFLOWEXECUTIONREQUEST._serialized_start = 49573 + _UNPAUSEWORKFLOWEXECUTIONREQUEST._serialized_end = 49716 + _UNPAUSEWORKFLOWEXECUTIONRESPONSE._serialized_start = 49718 + _UNPAUSEWORKFLOWEXECUTIONRESPONSE._serialized_end = 49752 + _STARTACTIVITYEXECUTIONREQUEST._serialized_start = 49755 + _STARTACTIVITYEXECUTIONREQUEST._serialized_end = 50932 + _STARTACTIVITYEXECUTIONRESPONSE._serialized_start = 50934 + _STARTACTIVITYEXECUTIONRESPONSE._serialized_end = 51043 + _DESCRIBEACTIVITYEXECUTIONREQUEST._serialized_start = 51046 + _DESCRIBEACTIVITYEXECUTIONREQUEST._serialized_end = 51274 + _DESCRIBEACTIVITYEXECUTIONRESPONSE._serialized_start = 51277 + _DESCRIBEACTIVITYEXECUTIONRESPONSE._serialized_end = 51593 + _POLLACTIVITYEXECUTIONREQUEST._serialized_start = 51595 + _POLLACTIVITYEXECUTIONREQUEST._serialized_end = 51681 + _POLLACTIVITYEXECUTIONRESPONSE._serialized_start = 51683 + _POLLACTIVITYEXECUTIONRESPONSE._serialized_end = 51799 + _LISTACTIVITYEXECUTIONSREQUEST._serialized_start = 51801 + _LISTACTIVITYEXECUTIONSREQUEST._serialized_end = 51910 + _LISTACTIVITYEXECUTIONSRESPONSE._serialized_start = 51913 + _LISTACTIVITYEXECUTIONSRESPONSE._serialized_end = 52043 + _STARTNEXUSOPERATIONEXECUTIONREQUEST._serialized_start = 52046 + _STARTNEXUSOPERATIONEXECUTIONREQUEST._serialized_end = 52895 + _STARTNEXUSOPERATIONEXECUTIONREQUEST_NEXUSHEADERENTRY._serialized_start = 52845 + _STARTNEXUSOPERATIONEXECUTIONREQUEST_NEXUSHEADERENTRY._serialized_end = 52895 + _STARTNEXUSOPERATIONEXECUTIONRESPONSE._serialized_start = 52897 + _STARTNEXUSOPERATIONEXECUTIONRESPONSE._serialized_end = 52968 + _DESCRIBENEXUSOPERATIONEXECUTIONREQUEST._serialized_start = 52971 + _DESCRIBENEXUSOPERATIONEXECUTIONREQUEST._serialized_end = 53141 + _DESCRIBENEXUSOPERATIONEXECUTIONRESPONSE._serialized_start = 53144 + _DESCRIBENEXUSOPERATIONEXECUTIONRESPONSE._serialized_end = 53455 + _POLLNEXUSOPERATIONEXECUTIONREQUEST._serialized_start = 53458 + _POLLNEXUSOPERATIONEXECUTIONREQUEST._serialized_end = 53619 + _POLLNEXUSOPERATIONEXECUTIONRESPONSE._serialized_start = 53622 + _POLLNEXUSOPERATIONEXECUTIONRESPONSE._serialized_end = 53883 + _LISTNEXUSOPERATIONEXECUTIONSREQUEST._serialized_start = 53885 + _LISTNEXUSOPERATIONEXECUTIONSREQUEST._serialized_end = 54000 + _LISTNEXUSOPERATIONEXECUTIONSRESPONSE._serialized_start = 54003 + _LISTNEXUSOPERATIONEXECUTIONSRESPONSE._serialized_end = 54142 + _COUNTACTIVITYEXECUTIONSREQUEST._serialized_start = 54144 + _COUNTACTIVITYEXECUTIONSREQUEST._serialized_end = 54210 + _COUNTACTIVITYEXECUTIONSRESPONSE._serialized_start = 54213 + _COUNTACTIVITYEXECUTIONSRESPONSE._serialized_end = 54450 + _COUNTACTIVITYEXECUTIONSRESPONSE_AGGREGATIONGROUP._serialized_start = 20134 + _COUNTACTIVITYEXECUTIONSRESPONSE_AGGREGATIONGROUP._serialized_end = 20222 + _COUNTNEXUSOPERATIONEXECUTIONSREQUEST._serialized_start = 54452 + _COUNTNEXUSOPERATIONEXECUTIONSREQUEST._serialized_end = 54524 + _COUNTNEXUSOPERATIONEXECUTIONSRESPONSE._serialized_start = 54527 + _COUNTNEXUSOPERATIONEXECUTIONSRESPONSE._serialized_end = 54776 + _COUNTNEXUSOPERATIONEXECUTIONSRESPONSE_AGGREGATIONGROUP._serialized_start = 20134 + _COUNTNEXUSOPERATIONEXECUTIONSRESPONSE_AGGREGATIONGROUP._serialized_end = 20222 + _REQUESTCANCELACTIVITYEXECUTIONREQUEST._serialized_start = 54779 + _REQUESTCANCELACTIVITYEXECUTIONREQUEST._serialized_end = 54928 + _REQUESTCANCELACTIVITYEXECUTIONRESPONSE._serialized_start = 54930 + _REQUESTCANCELACTIVITYEXECUTIONRESPONSE._serialized_end = 54970 + _TERMINATEACTIVITYEXECUTIONREQUEST._serialized_start = 54973 + _TERMINATEACTIVITYEXECUTIONREQUEST._serialized_end = 55118 + _TERMINATEACTIVITYEXECUTIONRESPONSE._serialized_start = 55120 + _TERMINATEACTIVITYEXECUTIONRESPONSE._serialized_end = 55156 + _DELETEACTIVITYEXECUTIONREQUEST._serialized_start = 55158 + _DELETEACTIVITYEXECUTIONREQUEST._serialized_end = 55246 + _DELETEACTIVITYEXECUTIONRESPONSE._serialized_start = 55248 + _DELETEACTIVITYEXECUTIONRESPONSE._serialized_end = 55281 + _REQUESTCANCELNEXUSOPERATIONEXECUTIONREQUEST._serialized_start = 55284 + _REQUESTCANCELNEXUSOPERATIONEXECUTIONREQUEST._serialized_end = 55440 + _REQUESTCANCELNEXUSOPERATIONEXECUTIONRESPONSE._serialized_start = 55442 + _REQUESTCANCELNEXUSOPERATIONEXECUTIONRESPONSE._serialized_end = 55488 + _TERMINATENEXUSOPERATIONEXECUTIONREQUEST._serialized_start = 55491 + _TERMINATENEXUSOPERATIONEXECUTIONREQUEST._serialized_end = 55643 + _TERMINATENEXUSOPERATIONEXECUTIONRESPONSE._serialized_start = 55645 + _TERMINATENEXUSOPERATIONEXECUTIONRESPONSE._serialized_end = 55687 + _DELETENEXUSOPERATIONEXECUTIONREQUEST._serialized_start = 55689 + _DELETENEXUSOPERATIONEXECUTIONREQUEST._serialized_end = 55784 + _DELETENEXUSOPERATIONEXECUTIONRESPONSE._serialized_start = 55786 + _DELETENEXUSOPERATIONEXECUTIONRESPONSE._serialized_end = 55825 + _POLLWORKFLOWEXECUTIONTIMESKIPPINGREQUEST._serialized_start = 55828 + _POLLWORKFLOWEXECUTIONTIMESKIPPINGREQUEST._serialized_end = 55985 + _POLLWORKFLOWEXECUTIONTIMESKIPPINGRESPONSE._serialized_start = 55988 + _POLLWORKFLOWEXECUTIONTIMESKIPPINGRESPONSE._serialized_end = 56220 # @@protoc_insertion_point(module_scope) diff --git a/temporalio/api/workflowservice/v1/request_response_pb2.pyi b/temporalio/api/workflowservice/v1/request_response_pb2.pyi index f5f3a05bb..98c752eb8 100644 --- a/temporalio/api/workflowservice/v1/request_response_pb2.pyi +++ b/temporalio/api/workflowservice/v1/request_response_pb2.pyi @@ -30,6 +30,7 @@ import temporalio.api.enums.v1.nexus_pb2 import temporalio.api.enums.v1.query_pb2 import temporalio.api.enums.v1.reset_pb2 import temporalio.api.enums.v1.task_queue_pb2 +import temporalio.api.enums.v1.time_skipping_pb2 import temporalio.api.enums.v1.update_pb2 import temporalio.api.enums.v1.workflow_pb2 import temporalio.api.failure.v1.message_pb2 @@ -4686,26 +4687,41 @@ class QueryWorkflowResponse(google.protobuf.message.Message): QUERY_RESULT_FIELD_NUMBER: builtins.int QUERY_REJECTED_FIELD_NUMBER: builtins.int + LINK_FIELD_NUMBER: builtins.int @property def query_result(self) -> temporalio.api.common.v1.message_pb2.Payloads: ... @property def query_rejected(self) -> temporalio.api.query.v1.message_pb2.QueryRejected: ... + @property + def link(self) -> temporalio.api.common.v1.message_pb2.Link: + """Holds the link to the Workflow execution that processed the Query.""" def __init__( self, *, query_result: temporalio.api.common.v1.message_pb2.Payloads | None = ..., query_rejected: temporalio.api.query.v1.message_pb2.QueryRejected | None = ..., + link: temporalio.api.common.v1.message_pb2.Link | None = ..., ) -> None: ... def HasField( self, field_name: typing_extensions.Literal[ - "query_rejected", b"query_rejected", "query_result", b"query_result" + "link", + b"link", + "query_rejected", + b"query_rejected", + "query_result", + b"query_result", ], ) -> builtins.bool: ... def ClearField( self, field_name: typing_extensions.Literal[ - "query_rejected", b"query_rejected", "query_result", b"query_result" + "link", + b"link", + "query_rejected", + b"query_rejected", + "query_result", + b"query_result", ], ) -> None: ... @@ -8336,6 +8352,7 @@ class UpdateActivityExecutionOptionsRequest(google.protobuf.message.Message): UPDATE_MASK_FIELD_NUMBER: builtins.int RESTORE_ORIGINAL_FIELD_NUMBER: builtins.int RESOURCE_ID_FIELD_NUMBER: builtins.int + REQUEST_ID_FIELD_NUMBER: builtins.int namespace: builtins.str """Namespace of the workflow which scheduled this activity""" workflow_id: builtins.str @@ -8345,7 +8362,7 @@ class UpdateActivityExecutionOptionsRequest(google.protobuf.message.Message): activity_id: builtins.str """The ID of the activity to target.""" run_id: builtins.str - """Run ID of the workflow or standalone activity.""" + """Run ID of the workflow or standalone activity. If empty, targets the latest run.""" identity: builtins.str """The identity of the client who initiated this request""" @property @@ -8365,6 +8382,8 @@ class UpdateActivityExecutionOptionsRequest(google.protobuf.message.Message): """ resource_id: builtins.str """Resource ID for routing. Contains "workflow:{workflow_id}" for workflow activities or "activity:{activity_id}" for standalone activities.""" + request_id: builtins.str + """Used to de-dupe update requests.""" def __init__( self, *, @@ -8378,6 +8397,7 @@ class UpdateActivityExecutionOptionsRequest(google.protobuf.message.Message): update_mask: google.protobuf.field_mask_pb2.FieldMask | None = ..., restore_original: builtins.bool = ..., resource_id: builtins.str = ..., + request_id: builtins.str = ..., ) -> None: ... def HasField( self, @@ -8396,6 +8416,8 @@ class UpdateActivityExecutionOptionsRequest(google.protobuf.message.Message): b"identity", "namespace", b"namespace", + "request_id", + b"request_id", "resource_id", b"resource_id", "restore_original", @@ -8565,7 +8587,7 @@ class PauseActivityExecutionRequest(google.protobuf.message.Message): activity_id: builtins.str """The ID of the activity to target.""" run_id: builtins.str - """Run ID of the workflow or standalone activity.""" + """Run ID of the workflow or standalone activity. If empty, targets the latest run.""" identity: builtins.str """The identity of the client who initiated this request.""" reason: builtins.str @@ -8733,11 +8755,10 @@ class UnpauseActivityExecutionRequest(google.protobuf.message.Message): ACTIVITY_ID_FIELD_NUMBER: builtins.int RUN_ID_FIELD_NUMBER: builtins.int IDENTITY_FIELD_NUMBER: builtins.int - RESET_ATTEMPTS_FIELD_NUMBER: builtins.int - RESET_HEARTBEAT_FIELD_NUMBER: builtins.int REASON_FIELD_NUMBER: builtins.int JITTER_FIELD_NUMBER: builtins.int RESOURCE_ID_FIELD_NUMBER: builtins.int + REQUEST_ID_FIELD_NUMBER: builtins.int namespace: builtins.str """Namespace of the workflow which scheduled this activity.""" workflow_id: builtins.str @@ -8747,13 +8768,9 @@ class UnpauseActivityExecutionRequest(google.protobuf.message.Message): activity_id: builtins.str """The ID of the activity to target.""" run_id: builtins.str - """Run ID of the workflow or standalone activity.""" + """Run ID of the workflow or standalone activity. If empty, targets the latest run.""" identity: builtins.str """The identity of the client who initiated this request.""" - reset_attempts: builtins.bool - """Providing this flag will also reset the number of attempts.""" - reset_heartbeat: builtins.bool - """Providing this flag will also reset the heartbeat details.""" reason: builtins.str """Reason to unpause the activity.""" @property @@ -8761,6 +8778,8 @@ class UnpauseActivityExecutionRequest(google.protobuf.message.Message): """If set, the activity will start at a random time within the specified jitter duration.""" resource_id: builtins.str """Resource ID for routing. Contains "workflow:{workflow_id}" for workflow activities or "activity:{activity_id}" for standalone activities.""" + request_id: builtins.str + """Used to de-dupe unpause requests.""" def __init__( self, *, @@ -8769,11 +8788,10 @@ class UnpauseActivityExecutionRequest(google.protobuf.message.Message): activity_id: builtins.str = ..., run_id: builtins.str = ..., identity: builtins.str = ..., - reset_attempts: builtins.bool = ..., - reset_heartbeat: builtins.bool = ..., reason: builtins.str = ..., jitter: google.protobuf.duration_pb2.Duration | None = ..., resource_id: builtins.str = ..., + request_id: builtins.str = ..., ) -> None: ... def HasField( self, field_name: typing_extensions.Literal["jitter", b"jitter"] @@ -8791,10 +8809,8 @@ class UnpauseActivityExecutionRequest(google.protobuf.message.Message): b"namespace", "reason", b"reason", - "reset_attempts", - b"reset_attempts", - "reset_heartbeat", - b"reset_heartbeat", + "request_id", + b"request_id", "resource_id", b"resource_id", "run_id", @@ -8948,6 +8964,7 @@ class ResetActivityExecutionRequest(google.protobuf.message.Message): JITTER_FIELD_NUMBER: builtins.int RESTORE_ORIGINAL_OPTIONS_FIELD_NUMBER: builtins.int RESOURCE_ID_FIELD_NUMBER: builtins.int + REQUEST_ID_FIELD_NUMBER: builtins.int namespace: builtins.str """Namespace of the workflow which scheduled this activity.""" workflow_id: builtins.str @@ -8957,7 +8974,7 @@ class ResetActivityExecutionRequest(google.protobuf.message.Message): activity_id: builtins.str """The ID of the activity to target.""" run_id: builtins.str - """Run ID of the workflow or standalone activity.""" + """Run ID of the workflow or standalone activity. If empty, targets the latest run.""" identity: builtins.str """The identity of the client who initiated this request.""" keep_paused: builtins.bool @@ -8974,6 +8991,8 @@ class ResetActivityExecutionRequest(google.protobuf.message.Message): """ resource_id: builtins.str """Resource ID for routing. Contains "workflow:{workflow_id}" for workflow activities or "activity:{activity_id}" for standalone activities.""" + request_id: builtins.str + """Used to de-dupe reset requests.""" def __init__( self, *, @@ -8986,6 +9005,7 @@ class ResetActivityExecutionRequest(google.protobuf.message.Message): jitter: google.protobuf.duration_pb2.Duration | None = ..., restore_original_options: builtins.bool = ..., resource_id: builtins.str = ..., + request_id: builtins.str = ..., ) -> None: ... def HasField( self, field_name: typing_extensions.Literal["jitter", b"jitter"] @@ -9003,6 +9023,8 @@ class ResetActivityExecutionRequest(google.protobuf.message.Message): b"keep_paused", "namespace", b"namespace", + "request_id", + b"request_id", "resource_id", b"resource_id", "restore_original_options", @@ -9125,6 +9147,9 @@ class UpdateWorkflowExecutionOptionsResponse(google.protobuf.message.Message): def update_time(self) -> google.protobuf.timestamp_pb2.Timestamp: """The Workflow Execution time when the options were updated. When time skipping is enabled, this is the workflow's virtual time rather than wall-clock time. + + This timestamp cannot be used for time-skipping fast-forward verification, + use `fast_forward_id` in `PollWorkflowExecutionTimeSkippingRequest` instead. """ def __init__( self, @@ -13196,7 +13221,7 @@ class RequestCancelActivityExecutionRequest(google.protobuf.message.Message): namespace: builtins.str activity_id: builtins.str run_id: builtins.str - """Activity run ID, targets the latest run if run_id is empty.""" + """Activity run ID. If empty, targets the latest run.""" identity: builtins.str """The identity of the worker/client.""" request_id: builtins.str @@ -13256,7 +13281,7 @@ class TerminateActivityExecutionRequest(google.protobuf.message.Message): namespace: builtins.str activity_id: builtins.str run_id: builtins.str - """Activity run ID, targets the latest run if run_id is empty.""" + """Activity run ID. If empty, targets the latest run.""" identity: builtins.str """The identity of the worker/client.""" request_id: builtins.str @@ -13505,3 +13530,103 @@ class DeleteNexusOperationExecutionResponse(google.protobuf.message.Message): ) -> None: ... global___DeleteNexusOperationExecutionResponse = DeleteNexusOperationExecutionResponse + +class PollWorkflowExecutionTimeSkippingRequest(google.protobuf.message.Message): + """A long-poll request that blocks according to a time-skipping waiting policy on the workflow + execution. Currently the only supported policy is waiting for completion of the fast-forward + identified by `fast_forward_id`; the poll also returns once anything else settles that outcome + (e.g. the execution ends or time skipping is disabled). + """ + + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + NAMESPACE_FIELD_NUMBER: builtins.int + WORKFLOW_EXECUTION_FIELD_NUMBER: builtins.int + FAST_FORWARD_ID_FIELD_NUMBER: builtins.int + namespace: builtins.str + @property + def workflow_execution( + self, + ) -> temporalio.api.common.v1.message_pb2.WorkflowExecution: ... + fast_forward_id: builtins.str + """Required. Identifies the fast-forward whose completion the caller wants to wait for. + Must match the `fast_forward_id` set in the execution's TimeSkippingConfig. + """ + def __init__( + self, + *, + namespace: builtins.str = ..., + workflow_execution: temporalio.api.common.v1.message_pb2.WorkflowExecution + | None = ..., + fast_forward_id: builtins.str = ..., + ) -> None: ... + def HasField( + self, + field_name: typing_extensions.Literal[ + "workflow_execution", b"workflow_execution" + ], + ) -> builtins.bool: ... + def ClearField( + self, + field_name: typing_extensions.Literal[ + "fast_forward_id", + b"fast_forward_id", + "namespace", + b"namespace", + "workflow_execution", + b"workflow_execution", + ], + ) -> None: ... + +global___PollWorkflowExecutionTimeSkippingRequest = ( + PollWorkflowExecutionTimeSkippingRequest +) + +class PollWorkflowExecutionTimeSkippingResponse(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + FAST_FORWARD_POLLING_RESULT_FIELD_NUMBER: builtins.int + FAILED_REASON_FIELD_NUMBER: builtins.int + FAST_FORWARD_INFO_FIELD_NUMBER: builtins.int + fast_forward_polling_result: ( + temporalio.api.enums.v1.time_skipping_pb2.FastForwardPollingResult.ValueType + ) + """The outcome of the poll for the fast-forward identified by the request's `fast_forward_id`.""" + failed_reason: builtins.str + """Set only when the result is FAST_FORWARD_POLLING_RESULT_FAST_FORWARD_FAILED; explains why + the fast-forward can no longer complete. + """ + @property + def fast_forward_info( + self, + ) -> temporalio.api.common.v1.message_pb2.TimeSkippingFastForwardInfo: + """The execution's current fast-forward, if any.""" + def __init__( + self, + *, + fast_forward_polling_result: temporalio.api.enums.v1.time_skipping_pb2.FastForwardPollingResult.ValueType = ..., + failed_reason: builtins.str = ..., + fast_forward_info: temporalio.api.common.v1.message_pb2.TimeSkippingFastForwardInfo + | None = ..., + ) -> None: ... + def HasField( + self, + field_name: typing_extensions.Literal[ + "fast_forward_info", b"fast_forward_info" + ], + ) -> builtins.bool: ... + def ClearField( + self, + field_name: typing_extensions.Literal[ + "failed_reason", + b"failed_reason", + "fast_forward_info", + b"fast_forward_info", + "fast_forward_polling_result", + b"fast_forward_polling_result", + ], + ) -> None: ... + +global___PollWorkflowExecutionTimeSkippingResponse = ( + PollWorkflowExecutionTimeSkippingResponse +) diff --git a/temporalio/api/workflowservice/v1/service_pb2.py b/temporalio/api/workflowservice/v1/service_pb2.py index 502f68ba6..92da5d6c2 100644 --- a/temporalio/api/workflowservice/v1/service_pb2.py +++ b/temporalio/api/workflowservice/v1/service_pb2.py @@ -27,7 +27,7 @@ ) DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile( - b'\n-temporal/api/workflowservice/v1/service.proto\x12\x1ftemporal.api.workflowservice.v1\x1a\x1cgoogle/api/annotations.proto\x1a!nexusannotations/v1/options.proto\x1a+temporal/api/protometa/v1/annotations.proto\x1a\x36temporal/api/workflowservice/v1/request_response.proto2\x98\xaf\x02\n\x0fWorkflowService\x12\xc3\x01\n\x11RegisterNamespace\x12\x39.temporal.api.workflowservice.v1.RegisterNamespaceRequest\x1a:.temporal.api.workflowservice.v1.RegisterNamespaceResponse"7\x82\xd3\xe4\x93\x02\x31"\x13/cluster/namespaces:\x01*Z\x17"\x12/api/v1/namespaces:\x01*\x12\xd5\x01\n\x11\x44\x65scribeNamespace\x12\x39.temporal.api.workflowservice.v1.DescribeNamespaceRequest\x1a:.temporal.api.workflowservice.v1.DescribeNamespaceResponse"I\x82\xd3\xe4\x93\x02\x43\x12\x1f/cluster/namespaces/{namespace}Z \x12\x1e/api/v1/namespaces/{namespace}\x12\xb4\x01\n\x0eListNamespaces\x12\x36.temporal.api.workflowservice.v1.ListNamespacesRequest\x1a\x37.temporal.api.workflowservice.v1.ListNamespacesResponse"1\x82\xd3\xe4\x93\x02+\x12\x13/cluster/namespacesZ\x14\x12\x12/api/v1/namespaces\x12\xe3\x01\n\x0fUpdateNamespace\x12\x37.temporal.api.workflowservice.v1.UpdateNamespaceRequest\x1a\x38.temporal.api.workflowservice.v1.UpdateNamespaceResponse"]\x82\xd3\xe4\x93\x02W"&/cluster/namespaces/{namespace}/update:\x01*Z*"%/api/v1/namespaces/{namespace}/update:\x01*\x12\x8f\x01\n\x12\x44\x65precateNamespace\x12:.temporal.api.workflowservice.v1.DeprecateNamespaceRequest\x1a;.temporal.api.workflowservice.v1.DeprecateNamespaceResponse"\x00\x12\xc6\x02\n\x16StartWorkflowExecution\x12>.temporal.api.workflowservice.v1.StartWorkflowExecutionRequest\x1a?.temporal.api.workflowservice.v1.StartWorkflowExecutionResponse"\xaa\x01\x82\xd3\xe4\x93\x02q"//namespaces/{namespace}/workflows/{workflow_id}:\x01*Z;"6/api/v1/namespaces/{namespace}/workflows/{workflow_id}:\x01*\x8a\x9d\xcc\x1b.\n\x14temporal-resource-id\x12\x16workflow:{workflow_id}\x12\xc2\x01\n\x15\x45xecuteMultiOperation\x12=.temporal.api.workflowservice.v1.ExecuteMultiOperationRequest\x1a>.temporal.api.workflowservice.v1.ExecuteMultiOperationResponse"*\x8a\x9d\xcc\x1b%\n\x14temporal-resource-id\x12\r{resource_id}\x12\xfe\x02\n\x1bGetWorkflowExecutionHistory\x12\x43.temporal.api.workflowservice.v1.GetWorkflowExecutionHistoryRequest\x1a\x44.temporal.api.workflowservice.v1.GetWorkflowExecutionHistoryResponse"\xd3\x01\x82\xd3\xe4\x93\x02\x8f\x01\x12\x41/namespaces/{namespace}/workflows/{execution.workflow_id}/historyZJ\x12H/api/v1/namespaces/{namespace}/workflows/{execution.workflow_id}/history\x8a\x9d\xcc\x1b\x38\n\x14temporal-resource-id\x12 workflow:{execution.workflow_id}\x12\xa3\x03\n"GetWorkflowExecutionHistoryReverse\x12J.temporal.api.workflowservice.v1.GetWorkflowExecutionHistoryReverseRequest\x1aK.temporal.api.workflowservice.v1.GetWorkflowExecutionHistoryReverseResponse"\xe3\x01\x82\xd3\xe4\x93\x02\x9f\x01\x12I/namespaces/{namespace}/workflows/{execution.workflow_id}/history-reverseZR\x12P/api/v1/namespaces/{namespace}/workflows/{execution.workflow_id}/history-reverse\x8a\x9d\xcc\x1b\x38\n\x14temporal-resource-id\x12 workflow:{execution.workflow_id}\x12\xcd\x01\n\x15PollWorkflowTaskQueue\x12=.temporal.api.workflowservice.v1.PollWorkflowTaskQueueRequest\x1a>.temporal.api.workflowservice.v1.PollWorkflowTaskQueueResponse"5\x8a\x9d\xcc\x1b\x30\n\x14temporal-resource-id\x12\x18poller:{poller_group_id}\x12\xd7\x01\n\x1cRespondWorkflowTaskCompleted\x12\x44.temporal.api.workflowservice.v1.RespondWorkflowTaskCompletedRequest\x1a\x45.temporal.api.workflowservice.v1.RespondWorkflowTaskCompletedResponse"*\x8a\x9d\xcc\x1b%\n\x14temporal-resource-id\x12\r{resource_id}\x12\xce\x01\n\x19RespondWorkflowTaskFailed\x12\x41.temporal.api.workflowservice.v1.RespondWorkflowTaskFailedRequest\x1a\x42.temporal.api.workflowservice.v1.RespondWorkflowTaskFailedResponse"*\x8a\x9d\xcc\x1b%\n\x14temporal-resource-id\x12\r{resource_id}\x12\xcd\x01\n\x15PollActivityTaskQueue\x12=.temporal.api.workflowservice.v1.PollActivityTaskQueueRequest\x1a>.temporal.api.workflowservice.v1.PollActivityTaskQueueResponse"5\x8a\x9d\xcc\x1b\x30\n\x14temporal-resource-id\x12\x18poller:{poller_group_id}\x12\xc2\x02\n\x1bRecordActivityTaskHeartbeat\x12\x43.temporal.api.workflowservice.v1.RecordActivityTaskHeartbeatRequest\x1a\x44.temporal.api.workflowservice.v1.RecordActivityTaskHeartbeatResponse"\x97\x01\x82\xd3\xe4\x93\x02g"*/namespaces/{namespace}/activity-heartbeat:\x01*Z6"1/api/v1/namespaces/{namespace}/activity-heartbeat:\x01*\x8a\x9d\xcc\x1b%\n\x14temporal-resource-id\x12\r{resource_id}\x12\xa8\x04\n\x1fRecordActivityTaskHeartbeatById\x12G.temporal.api.workflowservice.v1.RecordActivityTaskHeartbeatByIdRequest\x1aH.temporal.api.workflowservice.v1.RecordActivityTaskHeartbeatByIdResponse"\xf1\x02\x82\xd3\xe4\x93\x02\xc0\x02":/namespaces/{namespace}/activities/{activity_id}/heartbeat:\x01*ZF"A/api/v1/namespaces/{namespace}/activities/{activity_id}/heartbeat:\x01*ZW"R/namespaces/{namespace}/workflows/{workflow_id}/activities/{activity_id}/heartbeat:\x01*Z^"Y/api/v1/namespaces/{namespace}/workflows/{workflow_id}/activities/{activity_id}/heartbeat:\x01*\x8a\x9d\xcc\x1b%\n\x14temporal-resource-id\x12\r{resource_id}\x12\xc3\x02\n\x1cRespondActivityTaskCompleted\x12\x44.temporal.api.workflowservice.v1.RespondActivityTaskCompletedRequest\x1a\x45.temporal.api.workflowservice.v1.RespondActivityTaskCompletedResponse"\x95\x01\x82\xd3\xe4\x93\x02\x65")/namespaces/{namespace}/activity-complete:\x01*Z5"0/api/v1/namespaces/{namespace}/activity-complete:\x01*\x8a\x9d\xcc\x1b%\n\x14temporal-resource-id\x12\r{resource_id}\x12\xa7\x04\n RespondActivityTaskCompletedById\x12H.temporal.api.workflowservice.v1.RespondActivityTaskCompletedByIdRequest\x1aI.temporal.api.workflowservice.v1.RespondActivityTaskCompletedByIdResponse"\xed\x02\x82\xd3\xe4\x93\x02\xbc\x02"9/namespaces/{namespace}/activities/{activity_id}/complete:\x01*ZE"@/api/v1/namespaces/{namespace}/activities/{activity_id}/complete:\x01*ZV"Q/namespaces/{namespace}/workflows/{workflow_id}/activities/{activity_id}/complete:\x01*Z]"X/api/v1/namespaces/{namespace}/workflows/{workflow_id}/activities/{activity_id}/complete:\x01*\x8a\x9d\xcc\x1b%\n\x14temporal-resource-id\x12\r{resource_id}\x12\xb2\x02\n\x19RespondActivityTaskFailed\x12\x41.temporal.api.workflowservice.v1.RespondActivityTaskFailedRequest\x1a\x42.temporal.api.workflowservice.v1.RespondActivityTaskFailedResponse"\x8d\x01\x82\xd3\xe4\x93\x02]"%/namespaces/{namespace}/activity-fail:\x01*Z1",/api/v1/namespaces/{namespace}/activity-fail:\x01*\x8a\x9d\xcc\x1b%\n\x14temporal-resource-id\x12\r{resource_id}\x12\x8e\x04\n\x1dRespondActivityTaskFailedById\x12\x45.temporal.api.workflowservice.v1.RespondActivityTaskFailedByIdRequest\x1a\x46.temporal.api.workflowservice.v1.RespondActivityTaskFailedByIdResponse"\xdd\x02\x82\xd3\xe4\x93\x02\xac\x02"5/namespaces/{namespace}/activities/{activity_id}/fail:\x01*ZA".temporal.api.workflowservice.v1.ResetWorkflowExecutionRequest\x1a?.temporal.api.workflowservice.v1.ResetWorkflowExecutionResponse"\xf0\x01\x82\xd3\xe4\x93\x02\xa3\x01"H/namespaces/{namespace}/workflows/{workflow_execution.workflow_id}/reset:\x01*ZT"O/api/v1/namespaces/{namespace}/workflows/{workflow_execution.workflow_id}/reset:\x01*\x8a\x9d\xcc\x1b\x41\n\x14temporal-resource-id\x12)workflow:{workflow_execution.workflow_id}\x12\xa0\x03\n\x1aTerminateWorkflowExecution\x12\x42.temporal.api.workflowservice.v1.TerminateWorkflowExecutionRequest\x1a\x43.temporal.api.workflowservice.v1.TerminateWorkflowExecutionResponse"\xf8\x01\x82\xd3\xe4\x93\x02\xab\x01"L/namespaces/{namespace}/workflows/{workflow_execution.workflow_id}/terminate:\x01*ZX"S/api/v1/namespaces/{namespace}/workflows/{workflow_execution.workflow_id}/terminate:\x01*\x8a\x9d\xcc\x1b\x41\n\x14temporal-resource-id\x12)workflow:{workflow_execution.workflow_id}\x12\xe4\x01\n\x17\x44\x65leteWorkflowExecution\x12?.temporal.api.workflowservice.v1.DeleteWorkflowExecutionRequest\x1a@.temporal.api.workflowservice.v1.DeleteWorkflowExecutionResponse"F\x8a\x9d\xcc\x1b\x41\n\x14temporal-resource-id\x12)workflow:{workflow_execution.workflow_id}\x12\xa7\x01\n\x1aListOpenWorkflowExecutions\x12\x42.temporal.api.workflowservice.v1.ListOpenWorkflowExecutionsRequest\x1a\x43.temporal.api.workflowservice.v1.ListOpenWorkflowExecutionsResponse"\x00\x12\xad\x01\n\x1cListClosedWorkflowExecutions\x12\x44.temporal.api.workflowservice.v1.ListClosedWorkflowExecutionsRequest\x1a\x45.temporal.api.workflowservice.v1.ListClosedWorkflowExecutionsResponse"\x00\x12\xf0\x01\n\x16ListWorkflowExecutions\x12>.temporal.api.workflowservice.v1.ListWorkflowExecutionsRequest\x1a?.temporal.api.workflowservice.v1.ListWorkflowExecutionsResponse"U\x82\xd3\xe4\x93\x02O\x12!/namespaces/{namespace}/workflowsZ*\x12(/api/v1/namespaces/{namespace}/workflows\x12\x9a\x02\n\x1eListArchivedWorkflowExecutions\x12\x46.temporal.api.workflowservice.v1.ListArchivedWorkflowExecutionsRequest\x1aG.temporal.api.workflowservice.v1.ListArchivedWorkflowExecutionsResponse"g\x82\xd3\xe4\x93\x02\x61\x12*/namespaces/{namespace}/archived-workflowsZ3\x12\x31/api/v1/namespaces/{namespace}/archived-workflows\x12\x9b\x01\n\x16ScanWorkflowExecutions\x12>.temporal.api.workflowservice.v1.ScanWorkflowExecutionsRequest\x1a?.temporal.api.workflowservice.v1.ScanWorkflowExecutionsResponse"\x00\x12\xfd\x01\n\x17\x43ountWorkflowExecutions\x12?.temporal.api.workflowservice.v1.CountWorkflowExecutionsRequest\x1a@.temporal.api.workflowservice.v1.CountWorkflowExecutionsResponse"_\x82\xd3\xe4\x93\x02Y\x12&/namespaces/{namespace}/workflow-countZ/\x12-/api/v1/namespaces/{namespace}/workflow-count\x12\x92\x01\n\x13GetSearchAttributes\x12;.temporal.api.workflowservice.v1.GetSearchAttributesRequest\x1a<.temporal.api.workflowservice.v1.GetSearchAttributesResponse"\x00\x12\xd9\x01\n\x19RespondQueryTaskCompleted\x12\x41.temporal.api.workflowservice.v1.RespondQueryTaskCompletedRequest\x1a\x42.temporal.api.workflowservice.v1.RespondQueryTaskCompletedResponse"5\x8a\x9d\xcc\x1b\x30\n\x14temporal-resource-id\x12\x18poller:{poller_group_id}\x12\xd2\x01\n\x14ResetStickyTaskQueue\x12<.temporal.api.workflowservice.v1.ResetStickyTaskQueueRequest\x1a=.temporal.api.workflowservice.v1.ResetStickyTaskQueueResponse"=\x8a\x9d\xcc\x1b\x38\n\x14temporal-resource-id\x12 workflow:{execution.workflow_id}\x12\x83\x01\n\x0eShutdownWorker\x12\x36.temporal.api.workflowservice.v1.ShutdownWorkerRequest\x1a\x37.temporal.api.workflowservice.v1.ShutdownWorkerResponse"\x00\x12\xfc\x02\n\rQueryWorkflow\x12\x35.temporal.api.workflowservice.v1.QueryWorkflowRequest\x1a\x36.temporal.api.workflowservice.v1.QueryWorkflowResponse"\xfb\x01\x82\xd3\xe4\x93\x02\xb7\x01"R/namespaces/{namespace}/workflows/{execution.workflow_id}/query/{query.query_type}:\x01*Z^"Y/api/v1/namespaces/{namespace}/workflows/{execution.workflow_id}/query/{query.query_type}:\x01*\x8a\x9d\xcc\x1b\x38\n\x14temporal-resource-id\x12 workflow:{execution.workflow_id}\x12\xe7\x02\n\x19\x44\x65scribeWorkflowExecution\x12\x41.temporal.api.workflowservice.v1.DescribeWorkflowExecutionRequest\x1a\x42.temporal.api.workflowservice.v1.DescribeWorkflowExecutionResponse"\xc2\x01\x82\xd3\xe4\x93\x02\x7f\x12\x39/namespaces/{namespace}/workflows/{execution.workflow_id}ZB\x12@/api/v1/namespaces/{namespace}/workflows/{execution.workflow_id}\x8a\x9d\xcc\x1b\x38\n\x14temporal-resource-id\x12 workflow:{execution.workflow_id}\x12\xc2\x02\n\x11\x44\x65scribeTaskQueue\x12\x39.temporal.api.workflowservice.v1.DescribeTaskQueueRequest\x1a:.temporal.api.workflowservice.v1.DescribeTaskQueueResponse"\xb5\x01\x82\xd3\xe4\x93\x02w\x12\x35/namespaces/{namespace}/task-queues/{task_queue.name}Z>\x12/namespaces/{namespace}/schedules/{schedule_id}/matching-timesZG\x12\x45/api/v1/namespaces/{namespace}/schedules/{schedule_id}/matching-times\x8a\x9d\xcc\x1b.\n\x14temporal-resource-id\x12\x16schedule:{schedule_id}\x12\xa8\x02\n\x0e\x44\x65leteSchedule\x12\x36.temporal.api.workflowservice.v1.DeleteScheduleRequest\x1a\x37.temporal.api.workflowservice.v1.DeleteScheduleResponse"\xa4\x01\x82\xd3\xe4\x93\x02k*//namespaces/{namespace}/schedules/{schedule_id}Z8*6/api/v1/namespaces/{namespace}/schedules/{schedule_id}\x8a\x9d\xcc\x1b.\n\x14temporal-resource-id\x12\x16schedule:{schedule_id}\x12\xd5\x01\n\rListSchedules\x12\x35.temporal.api.workflowservice.v1.ListSchedulesRequest\x1a\x36.temporal.api.workflowservice.v1.ListSchedulesResponse"U\x82\xd3\xe4\x93\x02O\x12!/namespaces/{namespace}/schedulesZ*\x12(/api/v1/namespaces/{namespace}/schedules\x12\xe2\x01\n\x0e\x43ountSchedules\x12\x36.temporal.api.workflowservice.v1.CountSchedulesRequest\x1a\x37.temporal.api.workflowservice.v1.CountSchedulesResponse"_\x82\xd3\xe4\x93\x02Y\x12&/namespaces/{namespace}/schedule-countZ/\x12-/api/v1/namespaces/{namespace}/schedule-count\x12\xb9\x01\n UpdateWorkerBuildIdCompatibility\x12H.temporal.api.workflowservice.v1.UpdateWorkerBuildIdCompatibilityRequest\x1aI.temporal.api.workflowservice.v1.UpdateWorkerBuildIdCompatibilityResponse"\x00\x12\xe1\x02\n\x1dGetWorkerBuildIdCompatibility\x12\x45.temporal.api.workflowservice.v1.GetWorkerBuildIdCompatibilityRequest\x1a\x46.temporal.api.workflowservice.v1.GetWorkerBuildIdCompatibilityResponse"\xb0\x01\x82\xd3\xe4\x93\x02\xa9\x01\x12N/namespaces/{namespace}/task-queues/{task_queue}/worker-build-id-compatibilityZW\x12U/api/v1/namespaces/{namespace}/task-queues/{task_queue}/worker-build-id-compatibility\x12\xaa\x01\n\x1bUpdateWorkerVersioningRules\x12\x43.temporal.api.workflowservice.v1.UpdateWorkerVersioningRulesRequest\x1a\x44.temporal.api.workflowservice.v1.UpdateWorkerVersioningRulesResponse"\x00\x12\xc6\x02\n\x18GetWorkerVersioningRules\x12@.temporal.api.workflowservice.v1.GetWorkerVersioningRulesRequest\x1a\x41.temporal.api.workflowservice.v1.GetWorkerVersioningRulesResponse"\xa4\x01\x82\xd3\xe4\x93\x02\x9d\x01\x12H/namespaces/{namespace}/task-queues/{task_queue}/worker-versioning-rulesZQ\x12O/api/v1/namespaces/{namespace}/task-queues/{task_queue}/worker-versioning-rules\x12\x97\x02\n\x19GetWorkerTaskReachability\x12\x41.temporal.api.workflowservice.v1.GetWorkerTaskReachabilityRequest\x1a\x42.temporal.api.workflowservice.v1.GetWorkerTaskReachabilityResponse"s\x82\xd3\xe4\x93\x02m\x12\x30/namespaces/{namespace}/worker-task-reachabilityZ9\x12\x37/api/v1/namespaces/{namespace}/worker-task-reachability\x12\xc8\x02\n\x12\x44\x65scribeDeployment\x12:.temporal.api.workflowservice.v1.DescribeDeploymentRequest\x1a;.temporal.api.workflowservice.v1.DescribeDeploymentResponse"\xb8\x01\x82\xd3\xe4\x93\x02\xb1\x01\x12R/namespaces/{namespace}/deployments/{deployment.series_name}/{deployment.build_id}Z[\x12Y/api/v1/namespaces/{namespace}/deployments/{deployment.series_name}/{deployment.build_id}\x12\x81\x04\n\x1f\x44\x65scribeWorkerDeploymentVersion\x12G.temporal.api.workflowservice.v1.DescribeWorkerDeploymentVersionRequest\x1aH.temporal.api.workflowservice.v1.DescribeWorkerDeploymentVersionResponse"\xca\x02\x82\xd3\xe4\x93\x02\xf7\x01\x12u/namespaces/{namespace}/worker-deployment-versions/{deployment_version.deployment_name}/{deployment_version.build_id}Z~\x12|/api/v1/namespaces/{namespace}/worker-deployment-versions/{deployment_version.deployment_name}/{deployment_version.build_id}\x8a\x9d\xcc\x1bG\n\x14temporal-resource-id\x12/deployment:{deployment_version.deployment_name}\x12\xdf\x01\n\x0fListDeployments\x12\x37.temporal.api.workflowservice.v1.ListDeploymentsRequest\x1a\x38.temporal.api.workflowservice.v1.ListDeploymentsResponse"Y\x82\xd3\xe4\x93\x02S\x12#/namespaces/{namespace}/deploymentsZ,\x12*/api/v1/namespaces/{namespace}/deployments\x12\xf7\x02\n\x19GetDeploymentReachability\x12\x41.temporal.api.workflowservice.v1.GetDeploymentReachabilityRequest\x1a\x42.temporal.api.workflowservice.v1.GetDeploymentReachabilityResponse"\xd2\x01\x82\xd3\xe4\x93\x02\xcb\x01\x12_/namespaces/{namespace}/deployments/{deployment.series_name}/{deployment.build_id}/reachabilityZh\x12\x66/api/v1/namespaces/{namespace}/deployments/{deployment.series_name}/{deployment.build_id}/reachability\x12\x99\x02\n\x14GetCurrentDeployment\x12<.temporal.api.workflowservice.v1.GetCurrentDeploymentRequest\x1a=.temporal.api.workflowservice.v1.GetCurrentDeploymentResponse"\x83\x01\x82\xd3\xe4\x93\x02}\x12\x38/namespaces/{namespace}/current-deployment/{series_name}ZA\x12?/api/v1/namespaces/{namespace}/current-deployment/{series_name}\x12\xb6\x02\n\x14SetCurrentDeployment\x12<.temporal.api.workflowservice.v1.SetCurrentDeploymentRequest\x1a=.temporal.api.workflowservice.v1.SetCurrentDeploymentResponse"\xa0\x01\x82\xd3\xe4\x93\x02\x99\x01"C/namespaces/{namespace}/current-deployment/{deployment.series_name}:\x01*ZO"J/api/v1/namespaces/{namespace}/current-deployment/{deployment.series_name}:\x01*\x12\xb0\x03\n!SetWorkerDeploymentCurrentVersion\x12I.temporal.api.workflowservice.v1.SetWorkerDeploymentCurrentVersionRequest\x1aJ.temporal.api.workflowservice.v1.SetWorkerDeploymentCurrentVersionResponse"\xf3\x01\x82\xd3\xe4\x93\x02\xb3\x01"P/namespaces/{namespace}/worker-deployments/{deployment_name}/set-current-version:\x01*Z\\"W/api/v1/namespaces/{namespace}/worker-deployments/{deployment_name}/set-current-version:\x01*\x8a\x9d\xcc\x1b\x34\n\x14temporal-resource-id\x12\x1c\x64\x65ployment:{deployment_name}\x12\xe7\x02\n\x18\x44\x65scribeWorkerDeployment\x12@.temporal.api.workflowservice.v1.DescribeWorkerDeploymentRequest\x1a\x41.temporal.api.workflowservice.v1.DescribeWorkerDeploymentResponse"\xc5\x01\x82\xd3\xe4\x93\x02\x85\x01\x12.temporal.api.workflowservice.v1.DeleteWorkerDeploymentRequest\x1a?.temporal.api.workflowservice.v1.DeleteWorkerDeploymentResponse"\xc5\x01\x82\xd3\xe4\x93\x02\x85\x01*.temporal.api.workflowservice.v1.ListWorkerDeploymentsResponse"g\x82\xd3\xe4\x93\x02\x61\x12*/namespaces/{namespace}/worker-deploymentsZ3\x12\x31/api/v1/namespaces/{namespace}/worker-deployments\x12\xae\x02\n\x16\x43reateWorkerDeployment\x12>.temporal.api.workflowservice.v1.CreateWorkerDeploymentRequest\x1a?.temporal.api.workflowservice.v1.CreateWorkerDeploymentResponse"\x92\x01\x82\xd3\xe4\x93\x02\x8b\x01".temporal.api.workflowservice.v1.DescribeBatchOperationRequest\x1a?.temporal.api.workflowservice.v1.DescribeBatchOperationResponse"\xa0\x01\x82\xd3\xe4\x93\x02o\x12\x31/namespaces/{namespace}/batch-operations/{job_id}Z:\x12\x38/api/v1/namespaces/{namespace}/batch-operations/{job_id}\x8a\x9d\xcc\x1b&\n\x14temporal-resource-id\x12\x0e\x62\x61tch:{job_id}\x12\xf5\x01\n\x13ListBatchOperations\x12;.temporal.api.workflowservice.v1.ListBatchOperationsRequest\x1a<.temporal.api.workflowservice.v1.ListBatchOperationsResponse"c\x82\xd3\xe4\x93\x02]\x12(/namespaces/{namespace}/batch-operationsZ1\x12//api/v1/namespaces/{namespace}/batch-operations\x12\xc4\x01\n\x12PollNexusTaskQueue\x12:.temporal.api.workflowservice.v1.PollNexusTaskQueueRequest\x1a;.temporal.api.workflowservice.v1.PollNexusTaskQueueResponse"5\x8a\x9d\xcc\x1b\x30\n\x14temporal-resource-id\x12\x18poller:{poller_group_id}\x12\xd9\x01\n\x19RespondNexusTaskCompleted\x12\x41.temporal.api.workflowservice.v1.RespondNexusTaskCompletedRequest\x1a\x42.temporal.api.workflowservice.v1.RespondNexusTaskCompletedResponse"5\x8a\x9d\xcc\x1b\x30\n\x14temporal-resource-id\x12\x18poller:{poller_group_id}\x12\xd0\x01\n\x16RespondNexusTaskFailed\x12>.temporal.api.workflowservice.v1.RespondNexusTaskFailedRequest\x1a?.temporal.api.workflowservice.v1.RespondNexusTaskFailedResponse"5\x8a\x9d\xcc\x1b\x30\n\x14temporal-resource-id\x12\x18poller:{poller_group_id}\x12\xe8\x02\n\x15UpdateActivityOptions\x12=.temporal.api.workflowservice.v1.UpdateActivityOptionsRequest\x1a>.temporal.api.workflowservice.v1.UpdateActivityOptionsResponse"\xcf\x01\x82\xd3\xe4\x93\x02\x8b\x01".temporal.api.workflowservice.v1.RecordWorkerHeartbeatResponse"\x95\x01\x82\xd3\xe4\x93\x02\x65")/namespaces/{namespace}/workers/heartbeat:\x01*Z5"0/api/v1/namespaces/{namespace}/workers/heartbeat:\x01*\x8a\x9d\xcc\x1b%\n\x14temporal-resource-id\x12\r{resource_id}\x12\xcb\x01\n\x0bListWorkers\x12\x33.temporal.api.workflowservice.v1.ListWorkersRequest\x1a\x34.temporal.api.workflowservice.v1.ListWorkersResponse"Q\x82\xd3\xe4\x93\x02K\x12\x1f/namespaces/{namespace}/workersZ(\x12&/api/v1/namespaces/{namespace}/workers\x12\xd8\x01\n\x0c\x43ountWorkers\x12\x34.temporal.api.workflowservice.v1.CountWorkersRequest\x1a\x35.temporal.api.workflowservice.v1.CountWorkersResponse"[\x82\xd3\xe4\x93\x02U\x12$/namespaces/{namespace}/worker-countZ-\x12+/api/v1/namespaces/{namespace}/worker-count\x12\xe2\x02\n\x15UpdateTaskQueueConfig\x12=.temporal.api.workflowservice.v1.UpdateTaskQueueConfigRequest\x1a>.temporal.api.workflowservice.v1.UpdateTaskQueueConfigResponse"\xc9\x01\x82\xd3\xe4\x93\x02\x8f\x01">/namespaces/{namespace}/task-queues/{task_queue}/update-config:\x01*ZJ"E/api/v1/namespaces/{namespace}/task-queues/{task_queue}/update-config:\x01*\x8a\x9d\xcc\x1b.\n\x14temporal-resource-id\x12\x16taskqueue:{task_queue}\x12\xa8\x02\n\x11\x46\x65tchWorkerConfig\x12\x39.temporal.api.workflowservice.v1.FetchWorkerConfigRequest\x1a:.temporal.api.workflowservice.v1.FetchWorkerConfigResponse"\x9b\x01\x82\xd3\xe4\x93\x02k",/namespaces/{namespace}/workers/fetch-config:\x01*Z8"3/api/v1/namespaces/{namespace}/workers/fetch-config:\x01*\x8a\x9d\xcc\x1b%\n\x14temporal-resource-id\x12\r{resource_id}\x12\xad\x02\n\x12UpdateWorkerConfig\x12:.temporal.api.workflowservice.v1.UpdateWorkerConfigRequest\x1a;.temporal.api.workflowservice.v1.UpdateWorkerConfigResponse"\x9d\x01\x82\xd3\xe4\x93\x02m"-/namespaces/{namespace}/workers/update-config:\x01*Z9"4/api/v1/namespaces/{namespace}/workers/update-config:\x01*\x8a\x9d\xcc\x1b%\n\x14temporal-resource-id\x12\r{resource_id}\x12\xcd\x02\n\x0e\x44\x65scribeWorker\x12\x36.temporal.api.workflowservice.v1.DescribeWorkerRequest\x1a\x37.temporal.api.workflowservice.v1.DescribeWorkerResponse"\xc9\x01\x82\xd3\xe4\x93\x02\x89\x01\x12>/namespaces/{namespace}/workers/describe/{worker_instance_key}ZG\x12\x45/api/v1/namespaces/{namespace}/workers/describe/{worker_instance_key}\x8a\x9d\xcc\x1b\x34\n\x14temporal-resource-id\x12\x1cworker:{worker_instance_key}\x12\xd2\x02\n\x16PauseWorkflowExecution\x12>.temporal.api.workflowservice.v1.PauseWorkflowExecutionRequest\x1a?.temporal.api.workflowservice.v1.PauseWorkflowExecutionResponse"\xb6\x01\x82\xd3\xe4\x93\x02}"5/namespaces/{namespace}/workflows/{workflow_id}/pause:\x01*ZA"/api/v1/namespaces/{namespace}/workflows/{workflow_id}/unpause:\x01*\x8a\x9d\xcc\x1b.\n\x14temporal-resource-id\x12\x16workflow:{workflow_id}\x12\xc8\x02\n\x16StartActivityExecution\x12>.temporal.api.workflowservice.v1.StartActivityExecutionRequest\x1a?.temporal.api.workflowservice.v1.StartActivityExecutionResponse"\xac\x01\x82\xd3\xe4\x93\x02s"0/namespaces/{namespace}/activities/{activity_id}:\x01*Z<"7/api/v1/namespaces/{namespace}/activities/{activity_id}:\x01*\x8a\x9d\xcc\x1b.\n\x14temporal-resource-id\x12\x16\x61\x63tivity:{activity_id}\x12\xb6\x02\n\x1cStartNexusOperationExecution\x12\x44.temporal.api.workflowservice.v1.StartNexusOperationExecutionRequest\x1a\x45.temporal.api.workflowservice.v1.StartNexusOperationExecutionResponse"\x88\x01\x82\xd3\xe4\x93\x02\x81\x01"7/namespaces/{namespace}/nexus-operations/{operation_id}:\x01*ZC">/api/v1/namespaces/{namespace}/nexus-operations/{operation_id}:\x01*\x12\xcb\x02\n\x19\x44\x65scribeActivityExecution\x12\x41.temporal.api.workflowservice.v1.DescribeActivityExecutionRequest\x1a\x42.temporal.api.workflowservice.v1.DescribeActivityExecutionResponse"\xa6\x01\x82\xd3\xe4\x93\x02m\x12\x30/namespaces/{namespace}/activities/{activity_id}Z9\x12\x37/api/v1/namespaces/{namespace}/activities/{activity_id}\x8a\x9d\xcc\x1b.\n\x14temporal-resource-id\x12\x16\x61\x63tivity:{activity_id}\x12\xb8\x02\n\x1f\x44\x65scribeNexusOperationExecution\x12G.temporal.api.workflowservice.v1.DescribeNexusOperationExecutionRequest\x1aH.temporal.api.workflowservice.v1.DescribeNexusOperationExecutionResponse"\x81\x01\x82\xd3\xe4\x93\x02{\x12\x37/namespaces/{namespace}/nexus-operations/{operation_id}Z@\x12>/api/v1/namespaces/{namespace}/nexus-operations/{operation_id}\x12\xcf\x02\n\x15PollActivityExecution\x12=.temporal.api.workflowservice.v1.PollActivityExecutionRequest\x1a>.temporal.api.workflowservice.v1.PollActivityExecutionResponse"\xb6\x01\x82\xd3\xe4\x93\x02}\x12\x38/namespaces/{namespace}/activities/{activity_id}/outcomeZA\x12?/api/v1/namespaces/{namespace}/activities/{activity_id}/outcome\x8a\x9d\xcc\x1b.\n\x14temporal-resource-id\x12\x16\x61\x63tivity:{activity_id}\x12\xb7\x02\n\x1bPollNexusOperationExecution\x12\x43.temporal.api.workflowservice.v1.PollNexusOperationExecutionRequest\x1a\x44.temporal.api.workflowservice.v1.PollNexusOperationExecutionResponse"\x8c\x01\x82\xd3\xe4\x93\x02\x85\x01\x12.temporal.api.workflowservice.v1.ListActivityExecutionsRequest\x1a?.temporal.api.workflowservice.v1.ListActivityExecutionsResponse"W\x82\xd3\xe4\x93\x02Q\x12"/namespaces/{namespace}/activitiesZ+\x12)/api/v1/namespaces/{namespace}/activities\x12\x90\x02\n\x1cListNexusOperationExecutions\x12\x44.temporal.api.workflowservice.v1.ListNexusOperationExecutionsRequest\x1a\x45.temporal.api.workflowservice.v1.ListNexusOperationExecutionsResponse"c\x82\xd3\xe4\x93\x02]\x12(/namespaces/{namespace}/nexus-operationsZ1\x12//api/v1/namespaces/{namespace}/nexus-operations\x12\xfd\x01\n\x17\x43ountActivityExecutions\x12?.temporal.api.workflowservice.v1.CountActivityExecutionsRequest\x1a@.temporal.api.workflowservice.v1.CountActivityExecutionsResponse"_\x82\xd3\xe4\x93\x02Y\x12&/namespaces/{namespace}/activity-countZ/\x12-/api/v1/namespaces/{namespace}/activity-count\x12\x9d\x02\n\x1d\x43ountNexusOperationExecutions\x12\x45.temporal.api.workflowservice.v1.CountNexusOperationExecutionsRequest\x1a\x46.temporal.api.workflowservice.v1.CountNexusOperationExecutionsResponse"m\x82\xd3\xe4\x93\x02g\x12-/namespaces/{namespace}/nexus-operation-countZ6\x12\x34/api/v1/namespaces/{namespace}/nexus-operation-count\x12\xef\x02\n\x1eRequestCancelActivityExecution\x12\x46.temporal.api.workflowservice.v1.RequestCancelActivityExecutionRequest\x1aG.temporal.api.workflowservice.v1.RequestCancelActivityExecutionResponse"\xbb\x01\x82\xd3\xe4\x93\x02\x81\x01"7/namespaces/{namespace}/activities/{activity_id}/cancel:\x01*ZC">/api/v1/namespaces/{namespace}/activities/{activity_id}/cancel:\x01*\x8a\x9d\xcc\x1b.\n\x14temporal-resource-id\x12\x16\x61\x63tivity:{activity_id}\x12\xdc\x02\n$RequestCancelNexusOperationExecution\x12L.temporal.api.workflowservice.v1.RequestCancelNexusOperationExecutionRequest\x1aM.temporal.api.workflowservice.v1.RequestCancelNexusOperationExecutionResponse"\x96\x01\x82\xd3\xe4\x93\x02\x8f\x01">/namespaces/{namespace}/nexus-operations/{operation_id}/cancel:\x01*ZJ"E/api/v1/namespaces/{namespace}/nexus-operations/{operation_id}/cancel:\x01*\x12\xe9\x02\n\x1aTerminateActivityExecution\x12\x42.temporal.api.workflowservice.v1.TerminateActivityExecutionRequest\x1a\x43.temporal.api.workflowservice.v1.TerminateActivityExecutionResponse"\xc1\x01\x82\xd3\xe4\x93\x02\x87\x01":/namespaces/{namespace}/activities/{activity_id}/terminate:\x01*ZF"A/api/v1/namespaces/{namespace}/activities/{activity_id}/terminate:\x01*\x8a\x9d\xcc\x1b.\n\x14temporal-resource-id\x12\x16\x61\x63tivity:{activity_id}\x12\x9e\x01\n\x17\x44\x65leteActivityExecution\x12?.temporal.api.workflowservice.v1.DeleteActivityExecutionRequest\x1a@.temporal.api.workflowservice.v1.DeleteActivityExecutionResponse"\x00\x12\xfd\x03\n\x16PauseActivityExecution\x12>.temporal.api.workflowservice.v1.PauseActivityExecutionRequest\x1a?.temporal.api.workflowservice.v1.PauseActivityExecutionResponse"\xe1\x02\x82\xd3\xe4\x93\x02\xb0\x02"6/namespaces/{namespace}/activities/{activity_id}/pause:\x01*ZB"=/api/v1/namespaces/{namespace}/activities/{activity_id}/pause:\x01*ZS"N/namespaces/{namespace}/workflows/{workflow_id}/activities/{activity_id}/pause:\x01*ZZ"U/api/v1/namespaces/{namespace}/workflows/{workflow_id}/activities/{activity_id}/pause:\x01*\x8a\x9d\xcc\x1b%\n\x14temporal-resource-id\x12\r{resource_id}\x12\xfd\x03\n\x16ResetActivityExecution\x12>.temporal.api.workflowservice.v1.ResetActivityExecutionRequest\x1a?.temporal.api.workflowservice.v1.ResetActivityExecutionResponse"\xe1\x02\x82\xd3\xe4\x93\x02\xb0\x02"6/namespaces/{namespace}/activities/{activity_id}/reset:\x01*ZB"=/api/v1/namespaces/{namespace}/activities/{activity_id}/reset:\x01*ZS"N/namespaces/{namespace}/workflows/{workflow_id}/activities/{activity_id}/reset:\x01*ZZ"U/api/v1/namespaces/{namespace}/workflows/{workflow_id}/activities/{activity_id}/reset:\x01*\x8a\x9d\xcc\x1b%\n\x14temporal-resource-id\x12\r{resource_id}\x12\x8b\x04\n\x18UnpauseActivityExecution\x12@.temporal.api.workflowservice.v1.UnpauseActivityExecutionRequest\x1a\x41.temporal.api.workflowservice.v1.UnpauseActivityExecutionResponse"\xe9\x02\x82\xd3\xe4\x93\x02\xb8\x02"8/namespaces/{namespace}/activities/{activity_id}/unpause:\x01*ZD"?/api/v1/namespaces/{namespace}/activities/{activity_id}/unpause:\x01*ZU"P/namespaces/{namespace}/workflows/{workflow_id}/activities/{activity_id}/unpause:\x01*Z\\"W/api/v1/namespaces/{namespace}/workflows/{workflow_id}/activities/{activity_id}/unpause:\x01*\x8a\x9d\xcc\x1b%\n\x14temporal-resource-id\x12\r{resource_id}\x12\xb9\x04\n\x1eUpdateActivityExecutionOptions\x12\x46.temporal.api.workflowservice.v1.UpdateActivityExecutionOptionsRequest\x1aG.temporal.api.workflowservice.v1.UpdateActivityExecutionOptionsResponse"\x85\x03\x82\xd3\xe4\x93\x02\xd4\x02"?/namespaces/{namespace}/activities/{activity_id}/update-options:\x01*ZK"F/api/v1/namespaces/{namespace}/activities/{activity_id}/update-options:\x01*Z\\"W/namespaces/{namespace}/workflows/{workflow_id}/activities/{activity_id}/update-options:\x01*Zc"^/api/v1/namespaces/{namespace}/workflows/{workflow_id}/activities/{activity_id}/update-options:\x01*\x8a\x9d\xcc\x1b%\n\x14temporal-resource-id\x12\r{resource_id}\x12\xd6\x02\n TerminateNexusOperationExecution\x12H.temporal.api.workflowservice.v1.TerminateNexusOperationExecutionRequest\x1aI.temporal.api.workflowservice.v1.TerminateNexusOperationExecutionResponse"\x9c\x01\x82\xd3\xe4\x93\x02\x95\x01"A/namespaces/{namespace}/nexus-operations/{operation_id}/terminate:\x01*ZM"H/api/v1/namespaces/{namespace}/nexus-operations/{operation_id}/terminate:\x01*\x12\xb0\x01\n\x1d\x44\x65leteNexusOperationExecution\x12\x45.temporal.api.workflowservice.v1.DeleteNexusOperationExecutionRequest\x1a\x46.temporal.api.workflowservice.v1.DeleteNexusOperationExecutionResponse"\x00\x42\xb6\x01\n"io.temporal.api.workflowservice.v1B\x0cServiceProtoP\x01Z5go.temporal.io/api/workflowservice/v1;workflowservice\xaa\x02!Temporalio.Api.WorkflowService.V1\xea\x02$Temporalio::Api::WorkflowService::V1b\x06proto3' + b'\n-temporal/api/workflowservice/v1/service.proto\x12\x1ftemporal.api.workflowservice.v1\x1a\x1cgoogle/api/annotations.proto\x1a!nexusannotations/v1/options.proto\x1a+temporal/api/protometa/v1/annotations.proto\x1a\x36temporal/api/workflowservice/v1/request_response.proto2\xdc\xb2\x02\n\x0fWorkflowService\x12\xc3\x01\n\x11RegisterNamespace\x12\x39.temporal.api.workflowservice.v1.RegisterNamespaceRequest\x1a:.temporal.api.workflowservice.v1.RegisterNamespaceResponse"7\x82\xd3\xe4\x93\x02\x31"\x13/cluster/namespaces:\x01*Z\x17"\x12/api/v1/namespaces:\x01*\x12\xd5\x01\n\x11\x44\x65scribeNamespace\x12\x39.temporal.api.workflowservice.v1.DescribeNamespaceRequest\x1a:.temporal.api.workflowservice.v1.DescribeNamespaceResponse"I\x82\xd3\xe4\x93\x02\x43\x12\x1f/cluster/namespaces/{namespace}Z \x12\x1e/api/v1/namespaces/{namespace}\x12\xb4\x01\n\x0eListNamespaces\x12\x36.temporal.api.workflowservice.v1.ListNamespacesRequest\x1a\x37.temporal.api.workflowservice.v1.ListNamespacesResponse"1\x82\xd3\xe4\x93\x02+\x12\x13/cluster/namespacesZ\x14\x12\x12/api/v1/namespaces\x12\xe3\x01\n\x0fUpdateNamespace\x12\x37.temporal.api.workflowservice.v1.UpdateNamespaceRequest\x1a\x38.temporal.api.workflowservice.v1.UpdateNamespaceResponse"]\x82\xd3\xe4\x93\x02W"&/cluster/namespaces/{namespace}/update:\x01*Z*"%/api/v1/namespaces/{namespace}/update:\x01*\x12\x8f\x01\n\x12\x44\x65precateNamespace\x12:.temporal.api.workflowservice.v1.DeprecateNamespaceRequest\x1a;.temporal.api.workflowservice.v1.DeprecateNamespaceResponse"\x00\x12\xc6\x02\n\x16StartWorkflowExecution\x12>.temporal.api.workflowservice.v1.StartWorkflowExecutionRequest\x1a?.temporal.api.workflowservice.v1.StartWorkflowExecutionResponse"\xaa\x01\x82\xd3\xe4\x93\x02q"//namespaces/{namespace}/workflows/{workflow_id}:\x01*Z;"6/api/v1/namespaces/{namespace}/workflows/{workflow_id}:\x01*\x8a\x9d\xcc\x1b.\n\x14temporal-resource-id\x12\x16workflow:{workflow_id}\x12\xc2\x01\n\x15\x45xecuteMultiOperation\x12=.temporal.api.workflowservice.v1.ExecuteMultiOperationRequest\x1a>.temporal.api.workflowservice.v1.ExecuteMultiOperationResponse"*\x8a\x9d\xcc\x1b%\n\x14temporal-resource-id\x12\r{resource_id}\x12\xfe\x02\n\x1bGetWorkflowExecutionHistory\x12\x43.temporal.api.workflowservice.v1.GetWorkflowExecutionHistoryRequest\x1a\x44.temporal.api.workflowservice.v1.GetWorkflowExecutionHistoryResponse"\xd3\x01\x82\xd3\xe4\x93\x02\x8f\x01\x12\x41/namespaces/{namespace}/workflows/{execution.workflow_id}/historyZJ\x12H/api/v1/namespaces/{namespace}/workflows/{execution.workflow_id}/history\x8a\x9d\xcc\x1b\x38\n\x14temporal-resource-id\x12 workflow:{execution.workflow_id}\x12\xa3\x03\n"GetWorkflowExecutionHistoryReverse\x12J.temporal.api.workflowservice.v1.GetWorkflowExecutionHistoryReverseRequest\x1aK.temporal.api.workflowservice.v1.GetWorkflowExecutionHistoryReverseResponse"\xe3\x01\x82\xd3\xe4\x93\x02\x9f\x01\x12I/namespaces/{namespace}/workflows/{execution.workflow_id}/history-reverseZR\x12P/api/v1/namespaces/{namespace}/workflows/{execution.workflow_id}/history-reverse\x8a\x9d\xcc\x1b\x38\n\x14temporal-resource-id\x12 workflow:{execution.workflow_id}\x12\xcd\x01\n\x15PollWorkflowTaskQueue\x12=.temporal.api.workflowservice.v1.PollWorkflowTaskQueueRequest\x1a>.temporal.api.workflowservice.v1.PollWorkflowTaskQueueResponse"5\x8a\x9d\xcc\x1b\x30\n\x14temporal-resource-id\x12\x18poller:{poller_group_id}\x12\xd7\x01\n\x1cRespondWorkflowTaskCompleted\x12\x44.temporal.api.workflowservice.v1.RespondWorkflowTaskCompletedRequest\x1a\x45.temporal.api.workflowservice.v1.RespondWorkflowTaskCompletedResponse"*\x8a\x9d\xcc\x1b%\n\x14temporal-resource-id\x12\r{resource_id}\x12\xce\x01\n\x19RespondWorkflowTaskFailed\x12\x41.temporal.api.workflowservice.v1.RespondWorkflowTaskFailedRequest\x1a\x42.temporal.api.workflowservice.v1.RespondWorkflowTaskFailedResponse"*\x8a\x9d\xcc\x1b%\n\x14temporal-resource-id\x12\r{resource_id}\x12\xcd\x01\n\x15PollActivityTaskQueue\x12=.temporal.api.workflowservice.v1.PollActivityTaskQueueRequest\x1a>.temporal.api.workflowservice.v1.PollActivityTaskQueueResponse"5\x8a\x9d\xcc\x1b\x30\n\x14temporal-resource-id\x12\x18poller:{poller_group_id}\x12\xc2\x02\n\x1bRecordActivityTaskHeartbeat\x12\x43.temporal.api.workflowservice.v1.RecordActivityTaskHeartbeatRequest\x1a\x44.temporal.api.workflowservice.v1.RecordActivityTaskHeartbeatResponse"\x97\x01\x82\xd3\xe4\x93\x02g"*/namespaces/{namespace}/activity-heartbeat:\x01*Z6"1/api/v1/namespaces/{namespace}/activity-heartbeat:\x01*\x8a\x9d\xcc\x1b%\n\x14temporal-resource-id\x12\r{resource_id}\x12\xa8\x04\n\x1fRecordActivityTaskHeartbeatById\x12G.temporal.api.workflowservice.v1.RecordActivityTaskHeartbeatByIdRequest\x1aH.temporal.api.workflowservice.v1.RecordActivityTaskHeartbeatByIdResponse"\xf1\x02\x82\xd3\xe4\x93\x02\xc0\x02":/namespaces/{namespace}/activities/{activity_id}/heartbeat:\x01*ZF"A/api/v1/namespaces/{namespace}/activities/{activity_id}/heartbeat:\x01*ZW"R/namespaces/{namespace}/workflows/{workflow_id}/activities/{activity_id}/heartbeat:\x01*Z^"Y/api/v1/namespaces/{namespace}/workflows/{workflow_id}/activities/{activity_id}/heartbeat:\x01*\x8a\x9d\xcc\x1b%\n\x14temporal-resource-id\x12\r{resource_id}\x12\xc3\x02\n\x1cRespondActivityTaskCompleted\x12\x44.temporal.api.workflowservice.v1.RespondActivityTaskCompletedRequest\x1a\x45.temporal.api.workflowservice.v1.RespondActivityTaskCompletedResponse"\x95\x01\x82\xd3\xe4\x93\x02\x65")/namespaces/{namespace}/activity-complete:\x01*Z5"0/api/v1/namespaces/{namespace}/activity-complete:\x01*\x8a\x9d\xcc\x1b%\n\x14temporal-resource-id\x12\r{resource_id}\x12\xa7\x04\n RespondActivityTaskCompletedById\x12H.temporal.api.workflowservice.v1.RespondActivityTaskCompletedByIdRequest\x1aI.temporal.api.workflowservice.v1.RespondActivityTaskCompletedByIdResponse"\xed\x02\x82\xd3\xe4\x93\x02\xbc\x02"9/namespaces/{namespace}/activities/{activity_id}/complete:\x01*ZE"@/api/v1/namespaces/{namespace}/activities/{activity_id}/complete:\x01*ZV"Q/namespaces/{namespace}/workflows/{workflow_id}/activities/{activity_id}/complete:\x01*Z]"X/api/v1/namespaces/{namespace}/workflows/{workflow_id}/activities/{activity_id}/complete:\x01*\x8a\x9d\xcc\x1b%\n\x14temporal-resource-id\x12\r{resource_id}\x12\xb2\x02\n\x19RespondActivityTaskFailed\x12\x41.temporal.api.workflowservice.v1.RespondActivityTaskFailedRequest\x1a\x42.temporal.api.workflowservice.v1.RespondActivityTaskFailedResponse"\x8d\x01\x82\xd3\xe4\x93\x02]"%/namespaces/{namespace}/activity-fail:\x01*Z1",/api/v1/namespaces/{namespace}/activity-fail:\x01*\x8a\x9d\xcc\x1b%\n\x14temporal-resource-id\x12\r{resource_id}\x12\x8e\x04\n\x1dRespondActivityTaskFailedById\x12\x45.temporal.api.workflowservice.v1.RespondActivityTaskFailedByIdRequest\x1a\x46.temporal.api.workflowservice.v1.RespondActivityTaskFailedByIdResponse"\xdd\x02\x82\xd3\xe4\x93\x02\xac\x02"5/namespaces/{namespace}/activities/{activity_id}/fail:\x01*ZA".temporal.api.workflowservice.v1.ResetWorkflowExecutionRequest\x1a?.temporal.api.workflowservice.v1.ResetWorkflowExecutionResponse"\xf0\x01\x82\xd3\xe4\x93\x02\xa3\x01"H/namespaces/{namespace}/workflows/{workflow_execution.workflow_id}/reset:\x01*ZT"O/api/v1/namespaces/{namespace}/workflows/{workflow_execution.workflow_id}/reset:\x01*\x8a\x9d\xcc\x1b\x41\n\x14temporal-resource-id\x12)workflow:{workflow_execution.workflow_id}\x12\xa0\x03\n\x1aTerminateWorkflowExecution\x12\x42.temporal.api.workflowservice.v1.TerminateWorkflowExecutionRequest\x1a\x43.temporal.api.workflowservice.v1.TerminateWorkflowExecutionResponse"\xf8\x01\x82\xd3\xe4\x93\x02\xab\x01"L/namespaces/{namespace}/workflows/{workflow_execution.workflow_id}/terminate:\x01*ZX"S/api/v1/namespaces/{namespace}/workflows/{workflow_execution.workflow_id}/terminate:\x01*\x8a\x9d\xcc\x1b\x41\n\x14temporal-resource-id\x12)workflow:{workflow_execution.workflow_id}\x12\xe4\x01\n\x17\x44\x65leteWorkflowExecution\x12?.temporal.api.workflowservice.v1.DeleteWorkflowExecutionRequest\x1a@.temporal.api.workflowservice.v1.DeleteWorkflowExecutionResponse"F\x8a\x9d\xcc\x1b\x41\n\x14temporal-resource-id\x12)workflow:{workflow_execution.workflow_id}\x12\xa7\x01\n\x1aListOpenWorkflowExecutions\x12\x42.temporal.api.workflowservice.v1.ListOpenWorkflowExecutionsRequest\x1a\x43.temporal.api.workflowservice.v1.ListOpenWorkflowExecutionsResponse"\x00\x12\xad\x01\n\x1cListClosedWorkflowExecutions\x12\x44.temporal.api.workflowservice.v1.ListClosedWorkflowExecutionsRequest\x1a\x45.temporal.api.workflowservice.v1.ListClosedWorkflowExecutionsResponse"\x00\x12\xf0\x01\n\x16ListWorkflowExecutions\x12>.temporal.api.workflowservice.v1.ListWorkflowExecutionsRequest\x1a?.temporal.api.workflowservice.v1.ListWorkflowExecutionsResponse"U\x82\xd3\xe4\x93\x02O\x12!/namespaces/{namespace}/workflowsZ*\x12(/api/v1/namespaces/{namespace}/workflows\x12\x9a\x02\n\x1eListArchivedWorkflowExecutions\x12\x46.temporal.api.workflowservice.v1.ListArchivedWorkflowExecutionsRequest\x1aG.temporal.api.workflowservice.v1.ListArchivedWorkflowExecutionsResponse"g\x82\xd3\xe4\x93\x02\x61\x12*/namespaces/{namespace}/archived-workflowsZ3\x12\x31/api/v1/namespaces/{namespace}/archived-workflows\x12\x9b\x01\n\x16ScanWorkflowExecutions\x12>.temporal.api.workflowservice.v1.ScanWorkflowExecutionsRequest\x1a?.temporal.api.workflowservice.v1.ScanWorkflowExecutionsResponse"\x00\x12\xfd\x01\n\x17\x43ountWorkflowExecutions\x12?.temporal.api.workflowservice.v1.CountWorkflowExecutionsRequest\x1a@.temporal.api.workflowservice.v1.CountWorkflowExecutionsResponse"_\x82\xd3\xe4\x93\x02Y\x12&/namespaces/{namespace}/workflow-countZ/\x12-/api/v1/namespaces/{namespace}/workflow-count\x12\x92\x01\n\x13GetSearchAttributes\x12;.temporal.api.workflowservice.v1.GetSearchAttributesRequest\x1a<.temporal.api.workflowservice.v1.GetSearchAttributesResponse"\x00\x12\xd9\x01\n\x19RespondQueryTaskCompleted\x12\x41.temporal.api.workflowservice.v1.RespondQueryTaskCompletedRequest\x1a\x42.temporal.api.workflowservice.v1.RespondQueryTaskCompletedResponse"5\x8a\x9d\xcc\x1b\x30\n\x14temporal-resource-id\x12\x18poller:{poller_group_id}\x12\xd2\x01\n\x14ResetStickyTaskQueue\x12<.temporal.api.workflowservice.v1.ResetStickyTaskQueueRequest\x1a=.temporal.api.workflowservice.v1.ResetStickyTaskQueueResponse"=\x8a\x9d\xcc\x1b\x38\n\x14temporal-resource-id\x12 workflow:{execution.workflow_id}\x12\x83\x01\n\x0eShutdownWorker\x12\x36.temporal.api.workflowservice.v1.ShutdownWorkerRequest\x1a\x37.temporal.api.workflowservice.v1.ShutdownWorkerResponse"\x00\x12\xfc\x02\n\rQueryWorkflow\x12\x35.temporal.api.workflowservice.v1.QueryWorkflowRequest\x1a\x36.temporal.api.workflowservice.v1.QueryWorkflowResponse"\xfb\x01\x82\xd3\xe4\x93\x02\xb7\x01"R/namespaces/{namespace}/workflows/{execution.workflow_id}/query/{query.query_type}:\x01*Z^"Y/api/v1/namespaces/{namespace}/workflows/{execution.workflow_id}/query/{query.query_type}:\x01*\x8a\x9d\xcc\x1b\x38\n\x14temporal-resource-id\x12 workflow:{execution.workflow_id}\x12\xe7\x02\n\x19\x44\x65scribeWorkflowExecution\x12\x41.temporal.api.workflowservice.v1.DescribeWorkflowExecutionRequest\x1a\x42.temporal.api.workflowservice.v1.DescribeWorkflowExecutionResponse"\xc2\x01\x82\xd3\xe4\x93\x02\x7f\x12\x39/namespaces/{namespace}/workflows/{execution.workflow_id}ZB\x12@/api/v1/namespaces/{namespace}/workflows/{execution.workflow_id}\x8a\x9d\xcc\x1b\x38\n\x14temporal-resource-id\x12 workflow:{execution.workflow_id}\x12\xc2\x02\n\x11\x44\x65scribeTaskQueue\x12\x39.temporal.api.workflowservice.v1.DescribeTaskQueueRequest\x1a:.temporal.api.workflowservice.v1.DescribeTaskQueueResponse"\xb5\x01\x82\xd3\xe4\x93\x02w\x12\x35/namespaces/{namespace}/task-queues/{task_queue.name}Z>\x12/namespaces/{namespace}/schedules/{schedule_id}/matching-timesZG\x12\x45/api/v1/namespaces/{namespace}/schedules/{schedule_id}/matching-times\x8a\x9d\xcc\x1b.\n\x14temporal-resource-id\x12\x16schedule:{schedule_id}\x12\xa8\x02\n\x0e\x44\x65leteSchedule\x12\x36.temporal.api.workflowservice.v1.DeleteScheduleRequest\x1a\x37.temporal.api.workflowservice.v1.DeleteScheduleResponse"\xa4\x01\x82\xd3\xe4\x93\x02k*//namespaces/{namespace}/schedules/{schedule_id}Z8*6/api/v1/namespaces/{namespace}/schedules/{schedule_id}\x8a\x9d\xcc\x1b.\n\x14temporal-resource-id\x12\x16schedule:{schedule_id}\x12\xd5\x01\n\rListSchedules\x12\x35.temporal.api.workflowservice.v1.ListSchedulesRequest\x1a\x36.temporal.api.workflowservice.v1.ListSchedulesResponse"U\x82\xd3\xe4\x93\x02O\x12!/namespaces/{namespace}/schedulesZ*\x12(/api/v1/namespaces/{namespace}/schedules\x12\xe2\x01\n\x0e\x43ountSchedules\x12\x36.temporal.api.workflowservice.v1.CountSchedulesRequest\x1a\x37.temporal.api.workflowservice.v1.CountSchedulesResponse"_\x82\xd3\xe4\x93\x02Y\x12&/namespaces/{namespace}/schedule-countZ/\x12-/api/v1/namespaces/{namespace}/schedule-count\x12\xb9\x01\n UpdateWorkerBuildIdCompatibility\x12H.temporal.api.workflowservice.v1.UpdateWorkerBuildIdCompatibilityRequest\x1aI.temporal.api.workflowservice.v1.UpdateWorkerBuildIdCompatibilityResponse"\x00\x12\xe1\x02\n\x1dGetWorkerBuildIdCompatibility\x12\x45.temporal.api.workflowservice.v1.GetWorkerBuildIdCompatibilityRequest\x1a\x46.temporal.api.workflowservice.v1.GetWorkerBuildIdCompatibilityResponse"\xb0\x01\x82\xd3\xe4\x93\x02\xa9\x01\x12N/namespaces/{namespace}/task-queues/{task_queue}/worker-build-id-compatibilityZW\x12U/api/v1/namespaces/{namespace}/task-queues/{task_queue}/worker-build-id-compatibility\x12\xaa\x01\n\x1bUpdateWorkerVersioningRules\x12\x43.temporal.api.workflowservice.v1.UpdateWorkerVersioningRulesRequest\x1a\x44.temporal.api.workflowservice.v1.UpdateWorkerVersioningRulesResponse"\x00\x12\xc6\x02\n\x18GetWorkerVersioningRules\x12@.temporal.api.workflowservice.v1.GetWorkerVersioningRulesRequest\x1a\x41.temporal.api.workflowservice.v1.GetWorkerVersioningRulesResponse"\xa4\x01\x82\xd3\xe4\x93\x02\x9d\x01\x12H/namespaces/{namespace}/task-queues/{task_queue}/worker-versioning-rulesZQ\x12O/api/v1/namespaces/{namespace}/task-queues/{task_queue}/worker-versioning-rules\x12\x97\x02\n\x19GetWorkerTaskReachability\x12\x41.temporal.api.workflowservice.v1.GetWorkerTaskReachabilityRequest\x1a\x42.temporal.api.workflowservice.v1.GetWorkerTaskReachabilityResponse"s\x82\xd3\xe4\x93\x02m\x12\x30/namespaces/{namespace}/worker-task-reachabilityZ9\x12\x37/api/v1/namespaces/{namespace}/worker-task-reachability\x12\xc8\x02\n\x12\x44\x65scribeDeployment\x12:.temporal.api.workflowservice.v1.DescribeDeploymentRequest\x1a;.temporal.api.workflowservice.v1.DescribeDeploymentResponse"\xb8\x01\x82\xd3\xe4\x93\x02\xb1\x01\x12R/namespaces/{namespace}/deployments/{deployment.series_name}/{deployment.build_id}Z[\x12Y/api/v1/namespaces/{namespace}/deployments/{deployment.series_name}/{deployment.build_id}\x12\x81\x04\n\x1f\x44\x65scribeWorkerDeploymentVersion\x12G.temporal.api.workflowservice.v1.DescribeWorkerDeploymentVersionRequest\x1aH.temporal.api.workflowservice.v1.DescribeWorkerDeploymentVersionResponse"\xca\x02\x82\xd3\xe4\x93\x02\xf7\x01\x12u/namespaces/{namespace}/worker-deployment-versions/{deployment_version.deployment_name}/{deployment_version.build_id}Z~\x12|/api/v1/namespaces/{namespace}/worker-deployment-versions/{deployment_version.deployment_name}/{deployment_version.build_id}\x8a\x9d\xcc\x1bG\n\x14temporal-resource-id\x12/deployment:{deployment_version.deployment_name}\x12\xdf\x01\n\x0fListDeployments\x12\x37.temporal.api.workflowservice.v1.ListDeploymentsRequest\x1a\x38.temporal.api.workflowservice.v1.ListDeploymentsResponse"Y\x82\xd3\xe4\x93\x02S\x12#/namespaces/{namespace}/deploymentsZ,\x12*/api/v1/namespaces/{namespace}/deployments\x12\xf7\x02\n\x19GetDeploymentReachability\x12\x41.temporal.api.workflowservice.v1.GetDeploymentReachabilityRequest\x1a\x42.temporal.api.workflowservice.v1.GetDeploymentReachabilityResponse"\xd2\x01\x82\xd3\xe4\x93\x02\xcb\x01\x12_/namespaces/{namespace}/deployments/{deployment.series_name}/{deployment.build_id}/reachabilityZh\x12\x66/api/v1/namespaces/{namespace}/deployments/{deployment.series_name}/{deployment.build_id}/reachability\x12\x99\x02\n\x14GetCurrentDeployment\x12<.temporal.api.workflowservice.v1.GetCurrentDeploymentRequest\x1a=.temporal.api.workflowservice.v1.GetCurrentDeploymentResponse"\x83\x01\x82\xd3\xe4\x93\x02}\x12\x38/namespaces/{namespace}/current-deployment/{series_name}ZA\x12?/api/v1/namespaces/{namespace}/current-deployment/{series_name}\x12\xb6\x02\n\x14SetCurrentDeployment\x12<.temporal.api.workflowservice.v1.SetCurrentDeploymentRequest\x1a=.temporal.api.workflowservice.v1.SetCurrentDeploymentResponse"\xa0\x01\x82\xd3\xe4\x93\x02\x99\x01"C/namespaces/{namespace}/current-deployment/{deployment.series_name}:\x01*ZO"J/api/v1/namespaces/{namespace}/current-deployment/{deployment.series_name}:\x01*\x12\xb0\x03\n!SetWorkerDeploymentCurrentVersion\x12I.temporal.api.workflowservice.v1.SetWorkerDeploymentCurrentVersionRequest\x1aJ.temporal.api.workflowservice.v1.SetWorkerDeploymentCurrentVersionResponse"\xf3\x01\x82\xd3\xe4\x93\x02\xb3\x01"P/namespaces/{namespace}/worker-deployments/{deployment_name}/set-current-version:\x01*Z\\"W/api/v1/namespaces/{namespace}/worker-deployments/{deployment_name}/set-current-version:\x01*\x8a\x9d\xcc\x1b\x34\n\x14temporal-resource-id\x12\x1c\x64\x65ployment:{deployment_name}\x12\xe7\x02\n\x18\x44\x65scribeWorkerDeployment\x12@.temporal.api.workflowservice.v1.DescribeWorkerDeploymentRequest\x1a\x41.temporal.api.workflowservice.v1.DescribeWorkerDeploymentResponse"\xc5\x01\x82\xd3\xe4\x93\x02\x85\x01\x12.temporal.api.workflowservice.v1.DeleteWorkerDeploymentRequest\x1a?.temporal.api.workflowservice.v1.DeleteWorkerDeploymentResponse"\xc5\x01\x82\xd3\xe4\x93\x02\x85\x01*.temporal.api.workflowservice.v1.ListWorkerDeploymentsResponse"g\x82\xd3\xe4\x93\x02\x61\x12*/namespaces/{namespace}/worker-deploymentsZ3\x12\x31/api/v1/namespaces/{namespace}/worker-deployments\x12\xae\x02\n\x16\x43reateWorkerDeployment\x12>.temporal.api.workflowservice.v1.CreateWorkerDeploymentRequest\x1a?.temporal.api.workflowservice.v1.CreateWorkerDeploymentResponse"\x92\x01\x82\xd3\xe4\x93\x02\x8b\x01".temporal.api.workflowservice.v1.DescribeBatchOperationRequest\x1a?.temporal.api.workflowservice.v1.DescribeBatchOperationResponse"\xa0\x01\x82\xd3\xe4\x93\x02o\x12\x31/namespaces/{namespace}/batch-operations/{job_id}Z:\x12\x38/api/v1/namespaces/{namespace}/batch-operations/{job_id}\x8a\x9d\xcc\x1b&\n\x14temporal-resource-id\x12\x0e\x62\x61tch:{job_id}\x12\xf5\x01\n\x13ListBatchOperations\x12;.temporal.api.workflowservice.v1.ListBatchOperationsRequest\x1a<.temporal.api.workflowservice.v1.ListBatchOperationsResponse"c\x82\xd3\xe4\x93\x02]\x12(/namespaces/{namespace}/batch-operationsZ1\x12//api/v1/namespaces/{namespace}/batch-operations\x12\xc4\x01\n\x12PollNexusTaskQueue\x12:.temporal.api.workflowservice.v1.PollNexusTaskQueueRequest\x1a;.temporal.api.workflowservice.v1.PollNexusTaskQueueResponse"5\x8a\x9d\xcc\x1b\x30\n\x14temporal-resource-id\x12\x18poller:{poller_group_id}\x12\xd9\x01\n\x19RespondNexusTaskCompleted\x12\x41.temporal.api.workflowservice.v1.RespondNexusTaskCompletedRequest\x1a\x42.temporal.api.workflowservice.v1.RespondNexusTaskCompletedResponse"5\x8a\x9d\xcc\x1b\x30\n\x14temporal-resource-id\x12\x18poller:{poller_group_id}\x12\xd0\x01\n\x16RespondNexusTaskFailed\x12>.temporal.api.workflowservice.v1.RespondNexusTaskFailedRequest\x1a?.temporal.api.workflowservice.v1.RespondNexusTaskFailedResponse"5\x8a\x9d\xcc\x1b\x30\n\x14temporal-resource-id\x12\x18poller:{poller_group_id}\x12\xe8\x02\n\x15UpdateActivityOptions\x12=.temporal.api.workflowservice.v1.UpdateActivityOptionsRequest\x1a>.temporal.api.workflowservice.v1.UpdateActivityOptionsResponse"\xcf\x01\x82\xd3\xe4\x93\x02\x8b\x01".temporal.api.workflowservice.v1.RecordWorkerHeartbeatResponse"\x95\x01\x82\xd3\xe4\x93\x02\x65")/namespaces/{namespace}/workers/heartbeat:\x01*Z5"0/api/v1/namespaces/{namespace}/workers/heartbeat:\x01*\x8a\x9d\xcc\x1b%\n\x14temporal-resource-id\x12\r{resource_id}\x12\xcb\x01\n\x0bListWorkers\x12\x33.temporal.api.workflowservice.v1.ListWorkersRequest\x1a\x34.temporal.api.workflowservice.v1.ListWorkersResponse"Q\x82\xd3\xe4\x93\x02K\x12\x1f/namespaces/{namespace}/workersZ(\x12&/api/v1/namespaces/{namespace}/workers\x12\xd8\x01\n\x0c\x43ountWorkers\x12\x34.temporal.api.workflowservice.v1.CountWorkersRequest\x1a\x35.temporal.api.workflowservice.v1.CountWorkersResponse"[\x82\xd3\xe4\x93\x02U\x12$/namespaces/{namespace}/worker-countZ-\x12+/api/v1/namespaces/{namespace}/worker-count\x12\xe2\x02\n\x15UpdateTaskQueueConfig\x12=.temporal.api.workflowservice.v1.UpdateTaskQueueConfigRequest\x1a>.temporal.api.workflowservice.v1.UpdateTaskQueueConfigResponse"\xc9\x01\x82\xd3\xe4\x93\x02\x8f\x01">/namespaces/{namespace}/task-queues/{task_queue}/update-config:\x01*ZJ"E/api/v1/namespaces/{namespace}/task-queues/{task_queue}/update-config:\x01*\x8a\x9d\xcc\x1b.\n\x14temporal-resource-id\x12\x16taskqueue:{task_queue}\x12\xa8\x02\n\x11\x46\x65tchWorkerConfig\x12\x39.temporal.api.workflowservice.v1.FetchWorkerConfigRequest\x1a:.temporal.api.workflowservice.v1.FetchWorkerConfigResponse"\x9b\x01\x82\xd3\xe4\x93\x02k",/namespaces/{namespace}/workers/fetch-config:\x01*Z8"3/api/v1/namespaces/{namespace}/workers/fetch-config:\x01*\x8a\x9d\xcc\x1b%\n\x14temporal-resource-id\x12\r{resource_id}\x12\xad\x02\n\x12UpdateWorkerConfig\x12:.temporal.api.workflowservice.v1.UpdateWorkerConfigRequest\x1a;.temporal.api.workflowservice.v1.UpdateWorkerConfigResponse"\x9d\x01\x82\xd3\xe4\x93\x02m"-/namespaces/{namespace}/workers/update-config:\x01*Z9"4/api/v1/namespaces/{namespace}/workers/update-config:\x01*\x8a\x9d\xcc\x1b%\n\x14temporal-resource-id\x12\r{resource_id}\x12\xcd\x02\n\x0e\x44\x65scribeWorker\x12\x36.temporal.api.workflowservice.v1.DescribeWorkerRequest\x1a\x37.temporal.api.workflowservice.v1.DescribeWorkerResponse"\xc9\x01\x82\xd3\xe4\x93\x02\x89\x01\x12>/namespaces/{namespace}/workers/describe/{worker_instance_key}ZG\x12\x45/api/v1/namespaces/{namespace}/workers/describe/{worker_instance_key}\x8a\x9d\xcc\x1b\x34\n\x14temporal-resource-id\x12\x1cworker:{worker_instance_key}\x12\xd2\x02\n\x16PauseWorkflowExecution\x12>.temporal.api.workflowservice.v1.PauseWorkflowExecutionRequest\x1a?.temporal.api.workflowservice.v1.PauseWorkflowExecutionResponse"\xb6\x01\x82\xd3\xe4\x93\x02}"5/namespaces/{namespace}/workflows/{workflow_id}/pause:\x01*ZA"/api/v1/namespaces/{namespace}/workflows/{workflow_id}/unpause:\x01*\x8a\x9d\xcc\x1b.\n\x14temporal-resource-id\x12\x16workflow:{workflow_id}\x12\xc8\x02\n\x16StartActivityExecution\x12>.temporal.api.workflowservice.v1.StartActivityExecutionRequest\x1a?.temporal.api.workflowservice.v1.StartActivityExecutionResponse"\xac\x01\x82\xd3\xe4\x93\x02s"0/namespaces/{namespace}/activities/{activity_id}:\x01*Z<"7/api/v1/namespaces/{namespace}/activities/{activity_id}:\x01*\x8a\x9d\xcc\x1b.\n\x14temporal-resource-id\x12\x16\x61\x63tivity:{activity_id}\x12\xb6\x02\n\x1cStartNexusOperationExecution\x12\x44.temporal.api.workflowservice.v1.StartNexusOperationExecutionRequest\x1a\x45.temporal.api.workflowservice.v1.StartNexusOperationExecutionResponse"\x88\x01\x82\xd3\xe4\x93\x02\x81\x01"7/namespaces/{namespace}/nexus-operations/{operation_id}:\x01*ZC">/api/v1/namespaces/{namespace}/nexus-operations/{operation_id}:\x01*\x12\xcb\x02\n\x19\x44\x65scribeActivityExecution\x12\x41.temporal.api.workflowservice.v1.DescribeActivityExecutionRequest\x1a\x42.temporal.api.workflowservice.v1.DescribeActivityExecutionResponse"\xa6\x01\x82\xd3\xe4\x93\x02m\x12\x30/namespaces/{namespace}/activities/{activity_id}Z9\x12\x37/api/v1/namespaces/{namespace}/activities/{activity_id}\x8a\x9d\xcc\x1b.\n\x14temporal-resource-id\x12\x16\x61\x63tivity:{activity_id}\x12\xb8\x02\n\x1f\x44\x65scribeNexusOperationExecution\x12G.temporal.api.workflowservice.v1.DescribeNexusOperationExecutionRequest\x1aH.temporal.api.workflowservice.v1.DescribeNexusOperationExecutionResponse"\x81\x01\x82\xd3\xe4\x93\x02{\x12\x37/namespaces/{namespace}/nexus-operations/{operation_id}Z@\x12>/api/v1/namespaces/{namespace}/nexus-operations/{operation_id}\x12\xcf\x02\n\x15PollActivityExecution\x12=.temporal.api.workflowservice.v1.PollActivityExecutionRequest\x1a>.temporal.api.workflowservice.v1.PollActivityExecutionResponse"\xb6\x01\x82\xd3\xe4\x93\x02}\x12\x38/namespaces/{namespace}/activities/{activity_id}/outcomeZA\x12?/api/v1/namespaces/{namespace}/activities/{activity_id}/outcome\x8a\x9d\xcc\x1b.\n\x14temporal-resource-id\x12\x16\x61\x63tivity:{activity_id}\x12\xb7\x02\n\x1bPollNexusOperationExecution\x12\x43.temporal.api.workflowservice.v1.PollNexusOperationExecutionRequest\x1a\x44.temporal.api.workflowservice.v1.PollNexusOperationExecutionResponse"\x8c\x01\x82\xd3\xe4\x93\x02\x85\x01\x12.temporal.api.workflowservice.v1.ListActivityExecutionsRequest\x1a?.temporal.api.workflowservice.v1.ListActivityExecutionsResponse"W\x82\xd3\xe4\x93\x02Q\x12"/namespaces/{namespace}/activitiesZ+\x12)/api/v1/namespaces/{namespace}/activities\x12\x90\x02\n\x1cListNexusOperationExecutions\x12\x44.temporal.api.workflowservice.v1.ListNexusOperationExecutionsRequest\x1a\x45.temporal.api.workflowservice.v1.ListNexusOperationExecutionsResponse"c\x82\xd3\xe4\x93\x02]\x12(/namespaces/{namespace}/nexus-operationsZ1\x12//api/v1/namespaces/{namespace}/nexus-operations\x12\xfd\x01\n\x17\x43ountActivityExecutions\x12?.temporal.api.workflowservice.v1.CountActivityExecutionsRequest\x1a@.temporal.api.workflowservice.v1.CountActivityExecutionsResponse"_\x82\xd3\xe4\x93\x02Y\x12&/namespaces/{namespace}/activity-countZ/\x12-/api/v1/namespaces/{namespace}/activity-count\x12\x9d\x02\n\x1d\x43ountNexusOperationExecutions\x12\x45.temporal.api.workflowservice.v1.CountNexusOperationExecutionsRequest\x1a\x46.temporal.api.workflowservice.v1.CountNexusOperationExecutionsResponse"m\x82\xd3\xe4\x93\x02g\x12-/namespaces/{namespace}/nexus-operation-countZ6\x12\x34/api/v1/namespaces/{namespace}/nexus-operation-count\x12\xef\x02\n\x1eRequestCancelActivityExecution\x12\x46.temporal.api.workflowservice.v1.RequestCancelActivityExecutionRequest\x1aG.temporal.api.workflowservice.v1.RequestCancelActivityExecutionResponse"\xbb\x01\x82\xd3\xe4\x93\x02\x81\x01"7/namespaces/{namespace}/activities/{activity_id}/cancel:\x01*ZC">/api/v1/namespaces/{namespace}/activities/{activity_id}/cancel:\x01*\x8a\x9d\xcc\x1b.\n\x14temporal-resource-id\x12\x16\x61\x63tivity:{activity_id}\x12\xdc\x02\n$RequestCancelNexusOperationExecution\x12L.temporal.api.workflowservice.v1.RequestCancelNexusOperationExecutionRequest\x1aM.temporal.api.workflowservice.v1.RequestCancelNexusOperationExecutionResponse"\x96\x01\x82\xd3\xe4\x93\x02\x8f\x01">/namespaces/{namespace}/nexus-operations/{operation_id}/cancel:\x01*ZJ"E/api/v1/namespaces/{namespace}/nexus-operations/{operation_id}/cancel:\x01*\x12\xe9\x02\n\x1aTerminateActivityExecution\x12\x42.temporal.api.workflowservice.v1.TerminateActivityExecutionRequest\x1a\x43.temporal.api.workflowservice.v1.TerminateActivityExecutionResponse"\xc1\x01\x82\xd3\xe4\x93\x02\x87\x01":/namespaces/{namespace}/activities/{activity_id}/terminate:\x01*ZF"A/api/v1/namespaces/{namespace}/activities/{activity_id}/terminate:\x01*\x8a\x9d\xcc\x1b.\n\x14temporal-resource-id\x12\x16\x61\x63tivity:{activity_id}\x12\x9e\x01\n\x17\x44\x65leteActivityExecution\x12?.temporal.api.workflowservice.v1.DeleteActivityExecutionRequest\x1a@.temporal.api.workflowservice.v1.DeleteActivityExecutionResponse"\x00\x12\xfd\x03\n\x16PauseActivityExecution\x12>.temporal.api.workflowservice.v1.PauseActivityExecutionRequest\x1a?.temporal.api.workflowservice.v1.PauseActivityExecutionResponse"\xe1\x02\x82\xd3\xe4\x93\x02\xb0\x02"6/namespaces/{namespace}/activities/{activity_id}/pause:\x01*ZB"=/api/v1/namespaces/{namespace}/activities/{activity_id}/pause:\x01*ZS"N/namespaces/{namespace}/workflows/{workflow_id}/activities/{activity_id}/pause:\x01*ZZ"U/api/v1/namespaces/{namespace}/workflows/{workflow_id}/activities/{activity_id}/pause:\x01*\x8a\x9d\xcc\x1b%\n\x14temporal-resource-id\x12\r{resource_id}\x12\xfd\x03\n\x16ResetActivityExecution\x12>.temporal.api.workflowservice.v1.ResetActivityExecutionRequest\x1a?.temporal.api.workflowservice.v1.ResetActivityExecutionResponse"\xe1\x02\x82\xd3\xe4\x93\x02\xb0\x02"6/namespaces/{namespace}/activities/{activity_id}/reset:\x01*ZB"=/api/v1/namespaces/{namespace}/activities/{activity_id}/reset:\x01*ZS"N/namespaces/{namespace}/workflows/{workflow_id}/activities/{activity_id}/reset:\x01*ZZ"U/api/v1/namespaces/{namespace}/workflows/{workflow_id}/activities/{activity_id}/reset:\x01*\x8a\x9d\xcc\x1b%\n\x14temporal-resource-id\x12\r{resource_id}\x12\x8b\x04\n\x18UnpauseActivityExecution\x12@.temporal.api.workflowservice.v1.UnpauseActivityExecutionRequest\x1a\x41.temporal.api.workflowservice.v1.UnpauseActivityExecutionResponse"\xe9\x02\x82\xd3\xe4\x93\x02\xb8\x02"8/namespaces/{namespace}/activities/{activity_id}/unpause:\x01*ZD"?/api/v1/namespaces/{namespace}/activities/{activity_id}/unpause:\x01*ZU"P/namespaces/{namespace}/workflows/{workflow_id}/activities/{activity_id}/unpause:\x01*Z\\"W/api/v1/namespaces/{namespace}/workflows/{workflow_id}/activities/{activity_id}/unpause:\x01*\x8a\x9d\xcc\x1b%\n\x14temporal-resource-id\x12\r{resource_id}\x12\xb9\x04\n\x1eUpdateActivityExecutionOptions\x12\x46.temporal.api.workflowservice.v1.UpdateActivityExecutionOptionsRequest\x1aG.temporal.api.workflowservice.v1.UpdateActivityExecutionOptionsResponse"\x85\x03\x82\xd3\xe4\x93\x02\xd4\x02"?/namespaces/{namespace}/activities/{activity_id}/update-options:\x01*ZK"F/api/v1/namespaces/{namespace}/activities/{activity_id}/update-options:\x01*Z\\"W/namespaces/{namespace}/workflows/{workflow_id}/activities/{activity_id}/update-options:\x01*Zc"^/api/v1/namespaces/{namespace}/workflows/{workflow_id}/activities/{activity_id}/update-options:\x01*\x8a\x9d\xcc\x1b%\n\x14temporal-resource-id\x12\r{resource_id}\x12\xd6\x02\n TerminateNexusOperationExecution\x12H.temporal.api.workflowservice.v1.TerminateNexusOperationExecutionRequest\x1aI.temporal.api.workflowservice.v1.TerminateNexusOperationExecutionResponse"\x9c\x01\x82\xd3\xe4\x93\x02\x95\x01"A/namespaces/{namespace}/nexus-operations/{operation_id}/terminate:\x01*ZM"H/api/v1/namespaces/{namespace}/nexus-operations/{operation_id}/terminate:\x01*\x12\xb0\x01\n\x1d\x44\x65leteNexusOperationExecution\x12\x45.temporal.api.workflowservice.v1.DeleteNexusOperationExecutionRequest\x1a\x46.temporal.api.workflowservice.v1.DeleteNexusOperationExecutionResponse"\x00\x12\xc1\x03\n!PollWorkflowExecutionTimeSkipping\x12I.temporal.api.workflowservice.v1.PollWorkflowExecutionTimeSkippingRequest\x1aJ.temporal.api.workflowservice.v1.PollWorkflowExecutionTimeSkippingResponse"\x84\x02\x82\xd3\xe4\x93\x02\xb7\x01\x12U/namespaces/{namespace}/workflows/{workflow_execution.workflow_id}/time-skipping/pollZ^\x12\\/api/v1/namespaces/{namespace}/workflows/{workflow_execution.workflow_id}/time-skipping/poll\x8a\x9d\xcc\x1b\x41\n\x14temporal-resource-id\x12)workflow:{workflow_execution.workflow_id}B\xb6\x01\n"io.temporal.api.workflowservice.v1B\x0cServiceProtoP\x01Z5go.temporal.io/api/workflowservice/v1;workflowservice\xaa\x02!Temporalio.Api.WorkflowService.V1\xea\x02$Temporalio::Api::WorkflowService::V1b\x06proto3' ) @@ -519,6 +519,12 @@ _WORKFLOWSERVICE.methods_by_name[ "TerminateNexusOperationExecution" ]._serialized_options = b'\202\323\344\223\002\225\001"A/namespaces/{namespace}/nexus-operations/{operation_id}/terminate:\001*ZM"H/api/v1/namespaces/{namespace}/nexus-operations/{operation_id}/terminate:\001*' + _WORKFLOWSERVICE.methods_by_name[ + "PollWorkflowExecutionTimeSkipping" + ]._options = None + _WORKFLOWSERVICE.methods_by_name[ + "PollWorkflowExecutionTimeSkipping" + ]._serialized_options = b"\202\323\344\223\002\267\001\022U/namespaces/{namespace}/workflows/{workflow_execution.workflow_id}/time-skipping/pollZ^\022\\/api/v1/namespaces/{namespace}/workflows/{workflow_execution.workflow_id}/time-skipping/poll\212\235\314\033A\n\024temporal-resource-id\022)workflow:{workflow_execution.workflow_id}" _WORKFLOWSERVICE._serialized_start = 250 - _WORKFLOWSERVICE._serialized_end = 39058 + _WORKFLOWSERVICE._serialized_end = 39510 # @@protoc_insertion_point(module_scope) diff --git a/temporalio/api/workflowservice/v1/service_pb2_grpc.py b/temporalio/api/workflowservice/v1/service_pb2_grpc.py index f0b093213..486c6a394 100644 --- a/temporalio/api/workflowservice/v1/service_pb2_grpc.py +++ b/temporalio/api/workflowservice/v1/service_pb2_grpc.py @@ -638,6 +638,11 @@ def __init__(self, channel): request_serializer=temporal_dot_api_dot_workflowservice_dot_v1_dot_request__response__pb2.DeleteNexusOperationExecutionRequest.SerializeToString, response_deserializer=temporal_dot_api_dot_workflowservice_dot_v1_dot_request__response__pb2.DeleteNexusOperationExecutionResponse.FromString, ) + self.PollWorkflowExecutionTimeSkipping = channel.unary_unary( + "/temporal.api.workflowservice.v1.WorkflowService/PollWorkflowExecutionTimeSkipping", + request_serializer=temporal_dot_api_dot_workflowservice_dot_v1_dot_request__response__pb2.PollWorkflowExecutionTimeSkippingRequest.SerializeToString, + response_deserializer=temporal_dot_api_dot_workflowservice_dot_v1_dot_request__response__pb2.PollWorkflowExecutionTimeSkippingResponse.FromString, + ) class WorkflowServiceServicer(object): @@ -1926,6 +1931,12 @@ def DeleteNexusOperationExecution(self, request, context): context.set_details("Method not implemented!") raise NotImplementedError("Method not implemented!") + def PollWorkflowExecutionTimeSkipping(self, request, context): + """Missing associated documentation comment in .proto file.""" + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details("Method not implemented!") + raise NotImplementedError("Method not implemented!") + def add_WorkflowServiceServicer_to_server(servicer, server): rpc_method_handlers = { @@ -2539,6 +2550,11 @@ def add_WorkflowServiceServicer_to_server(servicer, server): request_deserializer=temporal_dot_api_dot_workflowservice_dot_v1_dot_request__response__pb2.DeleteNexusOperationExecutionRequest.FromString, response_serializer=temporal_dot_api_dot_workflowservice_dot_v1_dot_request__response__pb2.DeleteNexusOperationExecutionResponse.SerializeToString, ), + "PollWorkflowExecutionTimeSkipping": grpc.unary_unary_rpc_method_handler( + servicer.PollWorkflowExecutionTimeSkipping, + request_deserializer=temporal_dot_api_dot_workflowservice_dot_v1_dot_request__response__pb2.PollWorkflowExecutionTimeSkippingRequest.FromString, + response_serializer=temporal_dot_api_dot_workflowservice_dot_v1_dot_request__response__pb2.PollWorkflowExecutionTimeSkippingResponse.SerializeToString, + ), } generic_handler = grpc.method_handlers_generic_handler( "temporal.api.workflowservice.v1.WorkflowService", rpc_method_handlers @@ -6098,3 +6114,32 @@ def DeleteNexusOperationExecution( timeout, metadata, ) + + @staticmethod + def PollWorkflowExecutionTimeSkipping( + request, + target, + options=(), + channel_credentials=None, + call_credentials=None, + insecure=False, + compression=None, + wait_for_ready=None, + timeout=None, + metadata=None, + ): + return grpc.experimental.unary_unary( + request, + target, + "/temporal.api.workflowservice.v1.WorkflowService/PollWorkflowExecutionTimeSkipping", + temporal_dot_api_dot_workflowservice_dot_v1_dot_request__response__pb2.PollWorkflowExecutionTimeSkippingRequest.SerializeToString, + temporal_dot_api_dot_workflowservice_dot_v1_dot_request__response__pb2.PollWorkflowExecutionTimeSkippingResponse.FromString, + options, + channel_credentials, + insecure, + call_credentials, + compression, + wait_for_ready, + timeout, + metadata, + ) diff --git a/temporalio/api/workflowservice/v1/service_pb2_grpc.pyi b/temporalio/api/workflowservice/v1/service_pb2_grpc.pyi index 9c9713144..d25f044b4 100644 --- a/temporalio/api/workflowservice/v1/service_pb2_grpc.pyi +++ b/temporalio/api/workflowservice/v1/service_pb2_grpc.pyi @@ -1174,6 +1174,10 @@ class WorkflowServiceStub: (-- api-linter: core::0127::http-annotation=disabled aip.dev/not-precedent: Nexus operation deletion not exposed to HTTP, users should use cancel or terminate. --) """ + PollWorkflowExecutionTimeSkipping: grpc.UnaryUnaryMultiCallable[ + temporalio.api.workflowservice.v1.request_response_pb2.PollWorkflowExecutionTimeSkippingRequest, + temporalio.api.workflowservice.v1.request_response_pb2.PollWorkflowExecutionTimeSkippingResponse, + ] class WorkflowServiceServicer(metaclass=abc.ABCMeta): """WorkflowService API defines how Temporal SDKs and other clients interact with the Temporal server @@ -2595,6 +2599,12 @@ class WorkflowServiceServicer(metaclass=abc.ABCMeta): (-- api-linter: core::0127::http-annotation=disabled aip.dev/not-precedent: Nexus operation deletion not exposed to HTTP, users should use cancel or terminate. --) """ + @abc.abstractmethod + def PollWorkflowExecutionTimeSkipping( + self, + request: temporalio.api.workflowservice.v1.request_response_pb2.PollWorkflowExecutionTimeSkippingRequest, + context: grpc.ServicerContext, + ) -> temporalio.api.workflowservice.v1.request_response_pb2.PollWorkflowExecutionTimeSkippingResponse: ... def add_WorkflowServiceServicer_to_server( servicer: WorkflowServiceServicer, server: grpc.Server diff --git a/temporalio/bridge/sdk-core b/temporalio/bridge/sdk-core index d2769368d..21fcc2952 160000 --- a/temporalio/bridge/sdk-core +++ b/temporalio/bridge/sdk-core @@ -1 +1 @@ -Subproject commit d2769368df9077a311537431ff4594c9c14db4e7 +Subproject commit 21fcc2952257478489bd6e74cd0a65eb0b2c63be diff --git a/temporalio/bridge/services_generated.py b/temporalio/bridge/services_generated.py index 2f0fef8ac..c9960fcb5 100644 --- a/temporalio/bridge/services_generated.py +++ b/temporalio/bridge/services_generated.py @@ -1179,6 +1179,24 @@ async def poll_nexus_task_queue( timeout=timeout, ) + async def poll_workflow_execution_time_skipping( + self, + req: temporalio.api.workflowservice.v1.PollWorkflowExecutionTimeSkippingRequest, + retry: bool = False, + metadata: Mapping[str, str | bytes] = {}, + timeout: timedelta | None = None, + ) -> temporalio.api.workflowservice.v1.PollWorkflowExecutionTimeSkippingResponse: + """Invokes the WorkflowService.poll_workflow_execution_time_skipping rpc method.""" + return await self._client._rpc_call( + rpc="poll_workflow_execution_time_skipping", + req=req, + service=self._service, + resp_type=temporalio.api.workflowservice.v1.PollWorkflowExecutionTimeSkippingResponse, + retry=retry, + metadata=metadata, + timeout=timeout, + ) + async def poll_workflow_execution_update( self, req: temporalio.api.workflowservice.v1.PollWorkflowExecutionUpdateRequest, diff --git a/temporalio/bridge/src/client_rpc_generated.rs b/temporalio/bridge/src/client_rpc_generated.rs index a6f95b124..ea00d4fd5 100644 --- a/temporalio/bridge/src/client_rpc_generated.rs +++ b/temporalio/bridge/src/client_rpc_generated.rs @@ -596,6 +596,15 @@ impl ClientRef { poll_nexus_task_queue ) } + "poll_workflow_execution_time_skipping" => { + rpc_call!( + connection, + call, + WorkflowService, + workflow_service, + poll_workflow_execution_time_skipping + ) + } "poll_workflow_execution_update" => { rpc_call!( connection, From 2eea030551707015d09500d4044d7393f8eee5ef Mon Sep 17 00:00:00 2001 From: Vijay Wankhede <47521537+wankhede04@users.noreply.github.com> Date: Thu, 6 Aug 2026 00:55:21 +0530 Subject: [PATCH 207/226] fix(contrib): pool and idle-evict MCP connections in google_adk_agents (#1664) * fix(contrib): pool and idle-evict MCP connections in google_adk_agents TemporalMcpToolSetProvider's list-tools and call-tool activities called self._toolset_factory(...) on every invocation, constructing a brand-new McpToolset (and therefore a new MCPSessionManager/subprocess for stdio servers) each time with no cleanup. This leaked a spawned process per activity execution under sustained load. Pool one McpToolset per activity name, reused across calls and refcounted so idle eviction (default 5 minutes, overridable via the new mcp_connection_idle_timeout constructor parameter) only fires once no calls are in flight. A failed get_tools()/run_async() call evicts the connection so the next call reconnects instead of reusing a dead session. This brings google_adk_agents to parity with the pooling already shipped in the strands and google_genai contribs. Closes #1663 * test(contrib): cover MCP connection reuse, idle eviction, and error eviction in google_adk_agents Regression tests against a fake McpToolset asserting: N sequential call_tool executions against the same name reuse one toolset instead of creating N; list-tools and call-tool share a connection; idle connections close after the configured timeout but not while a call is in flight; and a failed call evicts the broken connection so the next call reconnects. * fix(contrib): make google_adk_agents MCP toolsets stateless (fixes factory_argument mis-routing) The previous fix pooled a single McpToolset per provider name in a worker-process-wide dict shared across all workflow executions, and only consulted factory_argument the first time a connection opened for that name. Every later call -- including calls from a different workflow run passing a different factory_argument -- silently reused that first connection, causing silent mis-routing for callers that use factory_argument to select a tenant/credential/backend. Remove the cross-workflow pool (_ConnectionRecord, _CONNECTIONS, get_connection, _evict_connection, and the mcp_connection_idle_timeout parameter) and make TemporalMcpToolSetProvider stateless, mirroring openai_agents' StatelessMCPServerProvider: each list-tools/call-tool activity builds a fresh McpToolset via toolset_factory(factory_argument), runs the operation, and always closes it in a finally block. This fixes the MCP session/subprocess leak from #1663 while honoring factory_argument on every call with zero cross-workflow sharing. Tests rewritten accordingly (test_mcp_pool.py -> test_mcp.py): prove a fresh toolset per call, close() on every path (success, error, no-match), and that a later call with a different factory_argument routes with its own argument. Fixes #1663 * feat(contrib): add stateful pooled MCP toolset provider for google_adk_agents Add an opt-in TemporalStatefulMcpToolSetProvider (plus the workflow-side TemporalStatefulMcpToolSet handle) mirroring openai_agents' StatefulMCPServerProvider, for callers who genuinely need a persistent MCP connection reused across tool calls within a single workflow run. The workflow-side handle, used as an async context manager, starts a dedicated {name}-server-session activity on a task queue scoped to the specific run (name@run_id). That activity builds the McpToolset once via toolset_factory(factory_argument), holds it open, and runs a nested Worker (PollerBehaviorSimpleMaximum(1)) serving the run-scoped -list-tools/-call-tool activities. The toolset is closed in a finally when the workflow cancels the session handle on cleanup. A heartbeat loop lets the workflow detect a dead dedicated worker; schedule-to-start and heartbeat timeouts surface as ApplicationError(type="DedicatedWorkerFailure") via a _handle_worker_failure decorator. This honors factory_argument exactly once per run with zero cross-run sharing, so it carries none of the silent mis-routing risk of a worker-wide pool, while offering connection reuse the stateless provider intentionally forgoes. The GoogleAdkPlugin now accepts either provider type. Adds CI-safe integration tests driving the real connect -> dedicated-worker -> get_tools path against an in-memory fake toolset (no subprocess): one toolset per run, factory_argument consumed once, no cross-run sharing, teardown on completion. * fix(contrib): guarantee heartbeat task cleanup in stateful MCP server-session activity The dedicated -server-session activity created its heartbeat task before the duplicate-connect guard, and only cancelled it inside the same finally block as toolset.close(). Two paths could leak the heartbeat task, leaving it calling activity.heartbeat() forever after the activity had already exited: 1. A duplicate connect() for an already-running server_id raised before the try/finally that cancels the heartbeat task was ever entered. 2. If toolset.close() itself raised during normal teardown, the subsequent heartbeat_task.cancel() in the same finally block was skipped. Move heartbeat_task creation after the duplicate-connect check (so the already-running case never creates one) and move its cancellation into an outermost finally that runs regardless of how the nested worker/toolset teardown exits. * Update temporalio/contrib/google_adk_agents/_mcp.py * fix(contrib): fix duplicate-tool error wording in stateful call_tool Applies the same wording fix @brianstrauch made in 02f2cd7 for the stateless call_tool to the stateful call_tool's identical duplicate-name error, which was missed since it's a separate code path. * fix(contrib): fix pyright/basedpyright errors in google_adk_agents MCP tests The fake toolset factories in test_mcp.py and test_stateful_mcp.py were annotated as returning _FakeToolset, which pyright/basedpyright correctly flagged as incompatible with TemporalMcpToolSetProvider's/ TemporalStatefulMcpToolSetProvider's toolset_factory parameter type of Callable[[Any | None], McpToolset], since _FakeToolset is a structurally similar stand-in but not a subclass of McpToolset. Annotate the factories as returning McpToolset and cast the fake instance through object first (as basedpyright's reportInvalidCast requires for unrelated concrete types), matching CI's build-lint-test/test-latest-deps failure on PR #1664. * fix(contrib): silence basedpyright reportUnusedParameter in MCP test fakes basedpyright exits non-zero on warnings, and the tool_context parameter in the mocked run_async fakes must keep its name to match the real McpTool interface, so suppress the warning instead of renaming it. * Add missing docstrings to __aenter__/__aexit__ to fix pydocstyle CI failure * Add __init__.py to tests/contrib/google_adk_agents The new tests/contrib/google_adk_agents/test_mcp.py has the same basename as tests/contrib/strands/test_mcp.py. Without an __init__.py, pytest imports both under the bare module name `test_mcp`, so collection failed with "import file mismatch" on every build-lint-test job. Adding __init__.py makes the module name fully qualified (tests.contrib.google_adk_agents.test_mcp), matching what the langgraph, langsmith, aws, workflow_streams and google_genai test packages already do. Co-Authored-By: Claude Opus 5 (1M context) * Use pydoctor-resolvable form of Worker cross-reference pydoctor does not resolve the `~`-prefixed shorthand role, which failed the API docs build. Co-Authored-By: Claude Opus 5 (1M context) --------- Co-authored-by: Brian Strauch Co-authored-by: Tim Conley Co-authored-by: wankhede04 Co-authored-by: Claude Opus 5 (1M context) --- .../contrib/google_adk_agents/__init__.py | 4 + temporalio/contrib/google_adk_agents/_mcp.py | 490 ++++++++++++++++-- .../contrib/google_adk_agents/_plugin.py | 15 +- tests/contrib/google_adk_agents/__init__.py | 0 tests/contrib/google_adk_agents/test_mcp.py | 228 ++++++++ .../google_adk_agents/test_stateful_mcp.py | 194 +++++++ 6 files changed, 897 insertions(+), 34 deletions(-) create mode 100644 tests/contrib/google_adk_agents/__init__.py create mode 100644 tests/contrib/google_adk_agents/test_mcp.py create mode 100644 tests/contrib/google_adk_agents/test_stateful_mcp.py diff --git a/temporalio/contrib/google_adk_agents/__init__.py b/temporalio/contrib/google_adk_agents/__init__.py index 3f236516b..d4c969fb3 100644 --- a/temporalio/contrib/google_adk_agents/__init__.py +++ b/temporalio/contrib/google_adk_agents/__init__.py @@ -6,6 +6,8 @@ from temporalio.contrib.google_adk_agents._mcp import ( TemporalMcpToolSet, TemporalMcpToolSetProvider, + TemporalStatefulMcpToolSet, + TemporalStatefulMcpToolSetProvider, ) from temporalio.contrib.google_adk_agents._model import TemporalModel from temporalio.contrib.google_adk_agents._plugin import ( @@ -16,5 +18,7 @@ "GoogleAdkPlugin", "TemporalMcpToolSet", "TemporalMcpToolSetProvider", + "TemporalStatefulMcpToolSet", + "TemporalStatefulMcpToolSetProvider", "TemporalModel", ] diff --git a/temporalio/contrib/google_adk_agents/_mcp.py b/temporalio/contrib/google_adk_agents/_mcp.py index 2f9e694a8..b342c9c3c 100644 --- a/temporalio/contrib/google_adk_agents/_mcp.py +++ b/temporalio/contrib/google_adk_agents/_mcp.py @@ -1,6 +1,9 @@ +import asyncio +import functools from collections.abc import Sequence from dataclasses import dataclass from datetime import timedelta +from types import TracebackType from typing import Any, Callable from google.adk.agents.readonly_context import ReadonlyContext @@ -14,8 +17,17 @@ from google.genai.types import FunctionDeclaration from temporalio import activity, workflow -from temporalio.exceptions import ApplicationError -from temporalio.workflow import ActivityConfig +from temporalio.api.enums.v1.workflow_pb2 import ( + TIMEOUT_TYPE_HEARTBEAT, + TIMEOUT_TYPE_SCHEDULE_TO_START, +) +from temporalio.exceptions import ( + ActivityError, + ApplicationError, + is_cancelled_exception, +) +from temporalio.worker import PollerBehaviorSimpleMaximum, Worker +from temporalio.workflow import ActivityConfig, ActivityHandle @dataclass @@ -88,16 +100,28 @@ class TemporalMcpToolSetProvider: Manages the creation of toolset activities and handles tool execution within Temporal workflows. + + This provider is *stateless*: every ``list-tools``/``call-tool`` activity + invocation builds a fresh ``McpToolset`` via ``toolset_factory``, runs the + operation, and always closes the toolset in a ``finally`` block. This means + ``factory_argument`` is honored on every single call (no cross-workflow + connection sharing or silent mis-routing) and no MCP session or stdio + subprocess is leaked. State is not maintained across calls; if a persistent + connection is required, use :class:`TemporalStatefulMcpToolSetProvider`. """ def __init__( - self, name: str, toolset_factory: Callable[[Any | None], McpToolset] + self, + name: str, + toolset_factory: Callable[[Any | None], McpToolset], ) -> None: """Initializes the toolset provider. Args: name: Name prefix for the generated activities. toolset_factory: Factory function that creates McpToolset instances. + It should return a new toolset each time so that no state is + shared between workflow runs. """ super().__init__() self._name = name @@ -108,42 +132,52 @@ def _get_activities(self) -> Sequence[Callable]: async def get_tools( args: _GetToolsArguments, ) -> list[_ToolResult]: + # Build a fresh toolset per call, honoring this call's + # ``factory_argument``, and always close it so no MCP session + # (or stdio subprocess) leaks. See issue #1663. toolset = self._toolset_factory(args.factory_argument) - tools = await toolset.get_tools() - return [ - _ToolResult( - tool.name, - tool.description, - tool.is_long_running, - tool.custom_metadata, - tool._get_declaration(), - ) - for tool in tools - ] + try: + tools = await toolset.get_tools() + return [ + _ToolResult( + tool.name, + tool.description, + tool.is_long_running, + tool.custom_metadata, + tool._get_declaration(), + ) + for tool in tools + ] + finally: + await toolset.close() @activity.defn(name=self._name + "-call-tool") async def call_tool( args: _CallToolArguments, ) -> _CallToolResult: toolset = self._toolset_factory(args.factory_argument) - tools = await toolset.get_tools() - tool_match = [tool for tool in tools if tool.name == args.name] - if len(tool_match) == 0: - raise ApplicationError( - f"Unable to find matching mcp tool by name: {args.name}" + try: + tools = await toolset.get_tools() + + tool_match = [tool for tool in tools if tool.name == args.name] + if len(tool_match) == 0: + raise ApplicationError( + f"Unable to find matching mcp tool by name: {args.name}" + ) + if len(tool_match) > 1: + raise ApplicationError( + f"Found multiple MCP tools with the same name: {args.name}" + ) + tool = tool_match[0] + + # We cannot provide a full-fledged ToolContext so we need to provide only what is needed by the tool + result = await tool.run_async( + args=args.arguments, + tool_context=args.tool_context, # type:ignore ) - if len(tool_match) > 1: - raise ApplicationError( - f"Unable too many matching mcp tools by name: {args.name}" - ) - tool = tool_match[0] - - # We cannot provide a full-fledged ToolContext so we need to provide only what is needed by the tool - result = await tool.run_async( - args=args.arguments, - tool_context=args.tool_context, # type:ignore - ) - return _CallToolResult(result=result, tool_context=args.tool_context) + return _CallToolResult(result=result, tool_context=args.tool_context) + finally: + await toolset.close() return get_tools, call_tool @@ -288,3 +322,397 @@ async def get_tools( ) for tool_result in tool_results ] + + +def _handle_worker_failure(func: Callable) -> Callable: + """Surface dedicated-worker failures on the run-scoped task queue. + + A schedule-to-start timeout means the dedicated ``-server-session`` worker + never picked the activity up (it is gone); a heartbeat timeout means it + died mid-session. Either way Temporal cannot recreate the in-memory toolset + state, so we re-raise as an ``ApplicationError`` of type + ``"DedicatedWorkerFailure"`` for the caller to handle. + + Duplicated (rather than shared) from ``openai_agents._mcp`` on purpose: + these two contribs do not currently share internal code, and importing + across them would create an unwanted dependency. + """ + + @functools.wraps(func) + async def wrapper(*args: Any, **kwargs: Any): + try: + return await func(*args, **kwargs) + except ActivityError as e: + failure = e.failure + if failure: + cause = failure.cause + if cause: + if ( + cause.timeout_failure_info.timeout_type + == TIMEOUT_TYPE_SCHEDULE_TO_START + ): + raise ApplicationError( + "MCP Stateful Server Worker failed to schedule activity.", + type="DedicatedWorkerFailure", + ) from e + if ( + cause.timeout_failure_info.timeout_type + == TIMEOUT_TYPE_HEARTBEAT + ): + raise ApplicationError( + "MCP Stateful Server Worker failed to heartbeat.", + type="DedicatedWorkerFailure", + ) from e + raise e + + return wrapper + + +@dataclass +class _StatefulServerSessionArguments: + factory_argument: Any | None + + +@dataclass +class _StatefulCallToolArguments: + name: str + arguments: dict[str, Any] + tool_context: TemporalToolContext + + +class TemporalStatefulMcpToolSetProvider: + """Provider for a stateful, pooled MCP toolset backed by a dedicated worker. + + .. warning:: + This class is experimental and may change in future versions. + Use with caution in production environments. + + Unlike :class:`TemporalMcpToolSetProvider` (which builds and closes a fresh + ``McpToolset`` per activity call), this provider maintains a single + ``McpToolset`` for the lifetime of a workflow run. The workflow-side + :class:`TemporalStatefulMcpToolSet` starts a dedicated ``-server-session`` + activity on a task queue scoped to that specific run + (``name@run_id``); that activity builds the toolset once via + ``toolset_factory(factory_argument)``, holds it open, and runs a nested + :py:class:`temporalio.worker.Worker` serving the ``-list-tools``/``-call-tool`` + activities off the same run-scoped queue. The toolset is closed when the + workflow cancels the session activity on cleanup. + + Because state lives in a dedicated worker's memory, the caller must handle + the case where that worker fails, as Temporal cannot seamlessly recreate the + lost toolset. Failure surfaces as an ``ApplicationError`` with + ``type="DedicatedWorkerFailure"``. Prefer the stateless + :class:`TemporalMcpToolSetProvider` unless a persistent connection is + genuinely required. + """ + + def __init__( + self, + name: str, + toolset_factory: Callable[[Any | None], McpToolset], + ) -> None: + """Initializes the stateful toolset provider. + + Args: + name: Name prefix for the generated activities. It is suffixed with + ``-stateful`` so it never collides with a stateless provider of + the same base name registered on the same worker. + toolset_factory: Factory function that creates McpToolset instances. + It should return a new toolset each time so that no state is + shared between workflow runs. + """ + super().__init__() + self._name = name + "-stateful" + self._toolset_factory = toolset_factory + self._toolsets: dict[str, McpToolset] = {} + + @property + def name(self) -> str: + """The activity-name prefix (base name with the ``-stateful`` suffix).""" + return self._name + + def _get_activities(self) -> Sequence[Callable]: + def _server_id() -> str: + return self._name + "@" + (activity.info().workflow_run_id or "") + + @activity.defn(name=self._name + "-list-tools") + async def get_tools() -> list[_ToolResult]: + toolset = self._toolsets[_server_id()] + tools = await toolset.get_tools() + return [ + _ToolResult( + tool.name, + tool.description, + tool.is_long_running, + tool.custom_metadata, + tool._get_declaration(), + ) + for tool in tools + ] + + @activity.defn(name=self._name + "-call-tool") + async def call_tool(args: _StatefulCallToolArguments) -> _CallToolResult: + toolset = self._toolsets[_server_id()] + tools = await toolset.get_tools() + + tool_match = [tool for tool in tools if tool.name == args.name] + if len(tool_match) == 0: + raise ApplicationError( + f"Unable to find matching mcp tool by name: {args.name}" + ) + if len(tool_match) > 1: + raise ApplicationError( + f"Found multiple MCP tools with the same name: {args.name}" + ) + tool = tool_match[0] + + # We cannot provide a full-fledged ToolContext so we need to provide only what is needed by the tool + result = await tool.run_async( + args=args.arguments, + tool_context=args.tool_context, # type:ignore + ) + return _CallToolResult(result=result, tool_context=args.tool_context) + + async def heartbeat_every(delay: float, *details: Any) -> None: + """Heartbeat every ``delay`` seconds until cancelled.""" + while True: + await asyncio.sleep(delay) + activity.heartbeat(*details) + + @activity.defn(name=self._name + "-server-session") + async def connect( + args: _StatefulServerSessionArguments | None = None, + ) -> None: + server_id = self._name + "@" + (activity.info().workflow_run_id or "") + if server_id in self._toolsets: + raise ApplicationError( + "Cannot connect to an already running toolset. Use a distinct " + "name if running multiple stateful toolsets in one workflow." + ) + + # Created only once the duplicate-connect check has passed, and + # cancelled in the outermost ``finally`` below so it is torn down + # on every exit path -- including a ``toolset.close()`` failure, + # which would otherwise leave it heartbeating forever after this + # activity has already exited. + heartbeat_task = asyncio.create_task(heartbeat_every(30)) + try: + toolset = self._toolset_factory(args.factory_argument if args else None) + try: + self._toolsets[server_id] = toolset + try: + worker = Worker( + activity.client(), + task_queue=server_id, + activities=[get_tools, call_tool], + activity_task_poller_behavior=PollerBehaviorSimpleMaximum( + 1 + ), + ) + await worker.run() + finally: + await toolset.close() + finally: + del self._toolsets[server_id] + finally: + heartbeat_task.cancel() + try: + await heartbeat_task + except asyncio.CancelledError: + pass + + return (connect,) + + +class _TemporalStatefulTool(BaseTool): + def __init__( + self, + set_name: str, + config: ActivityConfig, + declaration: FunctionDeclaration | None, + *, + name: str, + description: str, + is_long_running: bool = False, + custom_metadata: dict[str, Any] | None = None, + ): + super().__init__( + name=name, + description=description, + is_long_running=is_long_running, + custom_metadata=custom_metadata, + ) + self._set_name = set_name + self._config = config + self._declaration = declaration + + def _get_declaration(self) -> types.FunctionDeclaration | None: + return self._declaration + + @_handle_worker_failure + async def run_async( + self, *, args: dict[str, Any], tool_context: ToolContext + ) -> Any: + result: _CallToolResult = await workflow.execute_activity( + self._set_name + "-call-tool", + _StatefulCallToolArguments( + self.name, + arguments=args, + tool_context=TemporalToolContext( + tool_confirmation=tool_context.tool_confirmation, + function_call_id=tool_context.function_call_id, + event_actions=tool_context._event_actions, + ), + ), + result_type=_CallToolResult, + **self._config, + ) + + # We need to propagate any event actions back to the main context + tool_context._event_actions = result.tool_context.event_actions + return result.result + + +class TemporalStatefulMcpToolSet(BaseToolset): + """Workflow-side handle for a stateful MCP toolset. + + .. warning:: + This class is experimental and may change in future versions. + Use with caution in production environments. + + Use it as an async context manager inside a workflow so the dedicated + ``-server-session`` worker is started on ``connect`` and torn down on + ``cleanup``:: + + async with TemporalStatefulMcpToolSet("my-tools") as toolset: + agent = Agent(..., tools=[toolset]) + await runner.run(...) + + The connection (and any MCP subprocess) lives for the duration of the + ``async with`` block and is reused across every tool call in that block, + then closed on exit. Callers must be prepared to handle + ``ApplicationError(type="DedicatedWorkerFailure")`` should the dedicated + worker die mid-run. + """ + + def __init__( + self, + name: str, + config: ActivityConfig | None = None, + server_session_config: ActivityConfig | None = None, + factory_argument: Any | None = None, + not_in_workflow_toolset: Callable[[Any | None], McpToolset] | None = None, + ): + """Initializes the stateful Temporal MCP toolset handle. + + Args: + name: Base name of the toolset. Must match the ``name`` passed to + the :class:`TemporalStatefulMcpToolSetProvider` (the + ``-stateful`` suffix is applied here automatically). + config: Optional activity configuration for the per-operation + (``-list-tools``/``-call-tool``) activities. A + ``schedule_to_start_timeout`` is used to detect a dead + dedicated worker. + server_session_config: Optional activity configuration for the + long-running ``-server-session`` activity. + factory_argument: Optional argument passed once to the toolset + factory when the session connects. + not_in_workflow_toolset: Optional factory that returns the + underlying ``McpToolset`` to use when this wrapper executes + outside ``workflow.in_workflow()``, such as local ADK runs. + """ + super().__init__() + self._name = name + "-stateful" + self._config = config or ActivityConfig( + start_to_close_timeout=timedelta(minutes=1), + schedule_to_start_timeout=timedelta(seconds=30), + ) + self._server_session_config = server_session_config or ActivityConfig( + start_to_close_timeout=timedelta(hours=1), + ) + self._factory_argument = factory_argument + self._not_in_workflow_toolset = not_in_workflow_toolset + self._connect_handle: ActivityHandle | None = None + + async def connect(self) -> None: + """Starts the dedicated ``-server-session`` activity for this run.""" + if not workflow.in_workflow(): + return + self._config["task_queue"] = self._name + "@" + workflow.info().run_id + self._connect_handle = workflow.start_activity( + self._name + "-server-session", + _StatefulServerSessionArguments(self._factory_argument), + **self._server_session_config, + ) + + async def cleanup(self) -> None: + """Cancels the dedicated session activity and awaits its teardown.""" + if self._connect_handle: + self._connect_handle.cancel() + try: + await self._connect_handle + except Exception as e: + if not is_cancelled_exception(e): + raise + finally: + self._connect_handle = None + + async def close(self) -> None: + """``BaseToolset`` teardown hook; delegates to :meth:`cleanup`.""" + await self.cleanup() + + async def __aenter__(self) -> "TemporalStatefulMcpToolSet": + """Connects the toolset and returns it for use as a context manager.""" + await self.connect() + return self + + async def __aexit__( + self, + exc_type: type[BaseException] | None, + exc_value: BaseException | None, + traceback: TracebackType | None, + ) -> None: + """Cleans up the toolset when exiting the context manager.""" + await self.cleanup() + + @_handle_worker_failure + async def get_tools( + self, readonly_context: ReadonlyContext | None = None + ) -> list[BaseTool]: + """Retrieves available tools from the stateful MCP toolset.""" + # If executed outside a workflow, like when doing local adk runs, use the mcp server directly + if not workflow.in_workflow(): + if self._not_in_workflow_toolset is None: + raise ValueError( + "Attempted to use TemporalStatefulMcpToolSet outside a " + "workflow, but no not_in_workflow_toolset was provided. " + "Either use McpToolSet directly or pass a factory that " + "returns the underlying McpToolset for non-workflow execution." + ) + return await self._not_in_workflow_toolset( + self._factory_argument + ).get_tools(readonly_context) + + if not self._connect_handle: + raise ApplicationError( + "Stateful MCP toolset not connected. Use it as an async context " + "manager (async with ...) or call connect() first." + ) + + tool_results: list[_ToolResult] = await workflow.execute_activity( + self._name + "-list-tools", + result_type=list[_ToolResult], + **self._config, + ) + return [ + _TemporalStatefulTool( + set_name=self._name, + config=self._config, + declaration=tool_result.function_declaration, + name=tool_result.name, + description=tool_result.description, + is_long_running=tool_result.is_long_running, + custom_metadata=tool_result.custom_metadata, + ) + for tool_result in tool_results + ] diff --git a/temporalio/contrib/google_adk_agents/_plugin.py b/temporalio/contrib/google_adk_agents/_plugin.py index 7344485c8..15b6613e3 100644 --- a/temporalio/contrib/google_adk_agents/_plugin.py +++ b/temporalio/contrib/google_adk_agents/_plugin.py @@ -8,7 +8,10 @@ from typing import Any from temporalio import workflow -from temporalio.contrib.google_adk_agents._mcp import TemporalMcpToolSetProvider +from temporalio.contrib.google_adk_agents._mcp import ( + TemporalMcpToolSetProvider, + TemporalStatefulMcpToolSetProvider, +) from temporalio.contrib.google_adk_agents._model import ( invoke_model, invoke_model_streaming, @@ -72,12 +75,18 @@ class GoogleAdkPlugin(SimplePlugin): def __init__( self, - toolset_providers: list[TemporalMcpToolSetProvider] | None = None, + toolset_providers: list[ + TemporalMcpToolSetProvider | TemporalStatefulMcpToolSetProvider + ] + | None = None, ): """Initializes the Temporal ADK Plugin. Args: - toolset_providers: Optional list of toolset providers for MCP integration. + toolset_providers: Optional list of stateless + (:class:`TemporalMcpToolSetProvider`) or stateful + (:class:`TemporalStatefulMcpToolSetProvider`) toolset providers + for MCP integration. """ @asynccontextmanager diff --git a/tests/contrib/google_adk_agents/__init__.py b/tests/contrib/google_adk_agents/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/tests/contrib/google_adk_agents/test_mcp.py b/tests/contrib/google_adk_agents/test_mcp.py new file mode 100644 index 000000000..38303ffee --- /dev/null +++ b/tests/contrib/google_adk_agents/test_mcp.py @@ -0,0 +1,228 @@ +# Copyright 2025 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Unit tests for the stateless MCP toolset support in +``temporalio.contrib.google_adk_agents._mcp``. + +These exercise ``TemporalMcpToolSetProvider``'s generated activities directly +against a fake ``McpToolset``, so they don't require a real MCP server, a +Temporal test server, or a full ``Worker``. They are targeted regression tests +for the connection-leak fix (issue #1663): every call builds its own toolset, +honors that call's ``factory_argument``, and always closes the toolset. +""" + +from typing import Any, cast + +import pytest +from google.adk.events import EventActions +from google.adk.tools.mcp_tool import McpToolset + +from temporalio.contrib.google_adk_agents._mcp import ( + TemporalMcpToolSetProvider, + TemporalToolContext, + _CallToolArguments, + _GetToolsArguments, +) + + +class _FakeTool: + def __init__(self, name: str, *, fail_run: bool = False) -> None: + self.name = name + self.description = "a fake tool" + self.is_long_running = False + self.custom_metadata: dict[str, Any] | None = None + self._fail_run = fail_run + + def _get_declaration(self) -> None: + return None + + async def run_async( + self, + *, + args: dict[str, Any], + tool_context: Any, # pyright: ignore[reportUnusedParameter] + ) -> Any: + if self._fail_run: + raise RuntimeError("tool call failed") + return {"echo": args} + + +class _FakeToolset: + """Stands in for ``google.adk.tools.mcp_tool.McpToolset``. + + Tracks whether ``close()`` was called so tests can assert the stateless + path always tears the toolset down, and records the ``factory_argument`` + it was created with so tests can prove each call routes with its own + argument. + """ + + def __init__( + self, + factory_argument: Any = None, + *, + fail_get_tools: bool = False, + fail_run: bool = False, + ) -> None: + self.factory_argument = factory_argument + self.closed = False + self._fail_get_tools = fail_get_tools + self._fail_run = fail_run + + async def get_tools(self) -> list[_FakeTool]: + if self._fail_get_tools: + raise RuntimeError("get_tools failed") + return [_FakeTool("echo", fail_run=self._fail_run)] + + async def close(self) -> None: + self.closed = True + + +def _tool_context() -> TemporalToolContext: + return TemporalToolContext( + tool_confirmation=None, + function_call_id=None, + event_actions=EventActions(), + ) + + +def _call_tool_args(factory_argument: Any = None) -> _CallToolArguments: + return _CallToolArguments( + factory_argument=factory_argument, + name="echo", + arguments={"x": 1}, + tool_context=_tool_context(), + ) + + +async def test_call_tool_creates_and_closes_fresh_toolset_each_call(): + """Each call_tool builds its own toolset and closes it, every time.""" + created: list[_FakeToolset] = [] + + def factory(arg: Any) -> McpToolset: + toolset = _FakeToolset(arg) + created.append(toolset) + return cast(McpToolset, cast(object, toolset)) + + provider = TemporalMcpToolSetProvider("stateless_reuse", factory) + _, call_tool = provider._get_activities() + + for _ in range(5): + result = await call_tool(_call_tool_args()) + assert result.result == {"echo": {"x": 1}} + + # One fresh toolset per call, and every one was closed. + assert len(created) == 5 + assert all(t.closed for t in created) + + +async def test_get_tools_creates_and_closes_fresh_toolset(): + created: list[_FakeToolset] = [] + + def factory(arg: Any) -> McpToolset: + toolset = _FakeToolset(arg) + created.append(toolset) + return cast(McpToolset, cast(object, toolset)) + + provider = TemporalMcpToolSetProvider("stateless_list", factory) + get_tools, _ = provider._get_activities() + + tools = await get_tools(_GetToolsArguments(factory_argument=None)) + assert [t.name for t in tools] == ["echo"] + + assert len(created) == 1 + assert created[0].closed + + +async def test_factory_argument_honored_on_every_call(): + """The bug the reviewer flagged: a later call with a different + ``factory_argument`` must route with *its own* argument, never silently + reuse a connection opened for an earlier argument. + """ + created: list[_FakeToolset] = [] + + def factory(arg: Any) -> McpToolset: + toolset = _FakeToolset(arg) + created.append(toolset) + return cast(McpToolset, cast(object, toolset)) + + provider = TemporalMcpToolSetProvider("stateless_routing", factory) + _, call_tool = provider._get_activities() + + await call_tool(_call_tool_args(factory_argument="tenant-a")) + await call_tool(_call_tool_args(factory_argument="tenant-b")) + + assert [t.factory_argument for t in created] == ["tenant-a", "tenant-b"] + assert all(t.closed for t in created) + + +async def test_call_tool_closes_toolset_on_error(): + """A failure mid-call still closes the toolset (no leak on the error path).""" + created: list[_FakeToolset] = [] + + def factory(arg: Any) -> McpToolset: + toolset = _FakeToolset(arg, fail_run=True) + created.append(toolset) + return cast(McpToolset, cast(object, toolset)) + + provider = TemporalMcpToolSetProvider("stateless_run_error", factory) + _, call_tool = provider._get_activities() + + with pytest.raises(RuntimeError, match="tool call failed"): + await call_tool(_call_tool_args()) + + assert len(created) == 1 + assert created[0].closed + + +async def test_get_tools_closes_toolset_on_error(): + created: list[_FakeToolset] = [] + + def factory(arg: Any) -> McpToolset: + toolset = _FakeToolset(arg, fail_get_tools=True) + created.append(toolset) + return cast(McpToolset, cast(object, toolset)) + + provider = TemporalMcpToolSetProvider("stateless_list_error", factory) + get_tools, _ = provider._get_activities() + + with pytest.raises(RuntimeError, match="get_tools failed"): + await get_tools(_GetToolsArguments(factory_argument=None)) + + assert len(created) == 1 + assert created[0].closed + + +async def test_call_tool_no_matching_tool_still_closes(): + """A business-logic ApplicationError still closes the fresh toolset.""" + created: list[_FakeToolset] = [] + + def factory(arg: Any) -> McpToolset: + toolset = _FakeToolset(arg) + created.append(toolset) + return cast(McpToolset, cast(object, toolset)) + + provider = TemporalMcpToolSetProvider("stateless_no_match", factory) + _, call_tool = provider._get_activities() + + args = _CallToolArguments( + factory_argument=None, + name="does_not_exist", + arguments={}, + tool_context=_tool_context(), + ) + with pytest.raises(Exception, match="Unable to find matching mcp tool"): + await call_tool(args) + + assert len(created) == 1 + assert created[0].closed diff --git a/tests/contrib/google_adk_agents/test_stateful_mcp.py b/tests/contrib/google_adk_agents/test_stateful_mcp.py new file mode 100644 index 000000000..994598df9 --- /dev/null +++ b/tests/contrib/google_adk_agents/test_stateful_mcp.py @@ -0,0 +1,194 @@ +# Copyright 2025 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Integration tests for the stateful (pooled) MCP toolset support in +``temporalio.contrib.google_adk_agents._mcp``. + +These drive the real ``connect`` -> dedicated-worker -> ``get_tools`` path +through a Temporal workflow, but against an in-memory fake ``McpToolset`` (no +subprocess, no real MCP server) so they run in CI. They prove the properties +the reviewer asked for: one toolset is built per workflow run, ``factory_argument`` +is consumed exactly once per run, distinct runs never share a toolset, and the +toolset is torn down when the workflow completes. +""" + +import uuid +from datetime import timedelta +from typing import Any, cast + +from google.adk.tools.mcp_tool import McpToolset + +from temporalio import workflow +from temporalio.client import Client +from temporalio.worker import Worker + +with workflow.unsafe.imports_passed_through(): + from temporalio.contrib.google_adk_agents import ( + GoogleAdkPlugin, + TemporalStatefulMcpToolSet, + TemporalStatefulMcpToolSetProvider, + ) + +# Populated inside the activity worker process (same process as the test) each +# time the toolset factory runs, so tests can inspect what was built. +CREATED: list["_FakeToolset"] = [] + + +class _FakeTool: + def __init__(self, name: str) -> None: + self.name = name + self.description = "a fake tool" + self.is_long_running = False + self.custom_metadata: dict[str, Any] | None = None + + def _get_declaration(self) -> None: + return None + + async def run_async( + self, + *, + args: dict[str, Any], + tool_context: Any, # pyright: ignore[reportUnusedParameter] + ) -> Any: + return {"echo": args} + + +class _FakeToolset: + """In-memory stand-in for ``google.adk.tools.mcp_tool.McpToolset``.""" + + def __init__(self, factory_argument: Any = None) -> None: + self.factory_argument = factory_argument + self.get_tools_calls = 0 + self.closed = False + + async def get_tools(self) -> list[_FakeTool]: + self.get_tools_calls += 1 + return [_FakeTool("echo")] + + async def close(self) -> None: + self.closed = True + + +def _factory(arg: Any) -> McpToolset: + toolset = _FakeToolset(arg) + CREATED.append(toolset) + return cast(McpToolset, cast(object, toolset)) + + +@workflow.defn +class StatefulMcpWorkflow: + @workflow.run + async def run(self, factory_argument: Any | None) -> list[str]: + async with TemporalStatefulMcpToolSet( + "stateful_set", + factory_argument=factory_argument, + ) as toolset: + # Two calls against the same persistent toolset -- exercises reuse. + tools_1 = await toolset.get_tools() + tools_2 = await toolset.get_tools() + return [t.name for t in tools_1] + [t.name for t in tools_2] + + +def _make_client( + client: Client, provider: TemporalStatefulMcpToolSetProvider +) -> Client: + new_config = client.config() + new_config["plugins"] = [GoogleAdkPlugin(toolset_providers=[provider])] + return Client(**new_config) + + +async def test_stateful_one_toolset_per_run_and_teardown(client: Client): + CREATED.clear() + provider = TemporalStatefulMcpToolSetProvider("stateful_set", _factory) + client = _make_client(client, provider) + + async with Worker( + client, + task_queue="adk-stateful-mcp", + workflows=[StatefulMcpWorkflow], + max_cached_workflows=0, + ): + result = await client.execute_workflow( + StatefulMcpWorkflow.run, + None, + id=f"stateful-mcp-{uuid.uuid4()}", + task_queue="adk-stateful-mcp", + execution_timeout=timedelta(seconds=60), + ) + + assert result == ["echo", "echo"] + # Exactly one toolset built for the whole run... + assert len(CREATED) == 1 + # ...reused across both get_tools calls (state maintained, not per-call)... + assert CREATED[0].get_tools_calls == 2 + # ...and closed when the workflow completed (no leak). + assert CREATED[0].closed + # The dedicated-worker toolset registry is empty after teardown. + assert provider._toolsets == {} + + +async def test_stateful_factory_argument_consumed_once(client: Client): + CREATED.clear() + provider = TemporalStatefulMcpToolSetProvider("stateful_set", _factory) + client = _make_client(client, provider) + + async with Worker( + client, + task_queue="adk-stateful-mcp-arg", + workflows=[StatefulMcpWorkflow], + max_cached_workflows=0, + ): + await client.execute_workflow( + StatefulMcpWorkflow.run, + {"tenant": "acme"}, + id=f"stateful-mcp-{uuid.uuid4()}", + task_queue="adk-stateful-mcp-arg", + execution_timeout=timedelta(seconds=60), + ) + + assert len(CREATED) == 1 + assert CREATED[0].factory_argument == {"tenant": "acme"} + + +async def test_stateful_no_cross_run_sharing(client: Client): + CREATED.clear() + provider = TemporalStatefulMcpToolSetProvider("stateful_set", _factory) + client = _make_client(client, provider) + + async with Worker( + client, + task_queue="adk-stateful-mcp-iso", + workflows=[StatefulMcpWorkflow], + max_cached_workflows=0, + ): + await client.execute_workflow( + StatefulMcpWorkflow.run, + "tenant-a", + id=f"stateful-mcp-a-{uuid.uuid4()}", + task_queue="adk-stateful-mcp-iso", + execution_timeout=timedelta(seconds=60), + ) + await client.execute_workflow( + StatefulMcpWorkflow.run, + "tenant-b", + id=f"stateful-mcp-b-{uuid.uuid4()}", + task_queue="adk-stateful-mcp-iso", + execution_timeout=timedelta(seconds=60), + ) + + # Two distinct runs -> two distinct toolsets, each with its own argument. + assert len(CREATED) == 2 + assert {t.factory_argument for t in CREATED} == {"tenant-a", "tenant-b"} + assert all(t.closed for t in CREATED) + assert provider._toolsets == {} From b1325adddd07f8cf2c2875c0b2d45e688e599ff5 Mon Sep 17 00:00:00 2001 From: Alex Mazzeo Date: Wed, 5 Aug 2026 14:26:32 -0700 Subject: [PATCH 208/226] Fix duplicate links for Nexus backing SAA (#1725) --- temporalio/nexus/_operation_context.py | 13 ++--- tests/nexus/test_link_propagation.py | 3 +- tests/nexus/test_temporal_operation.py | 68 +++++++++++++++++++++++++- 3 files changed, 73 insertions(+), 11 deletions(-) diff --git a/temporalio/nexus/_operation_context.py b/temporalio/nexus/_operation_context.py index 06ffd9b0f..54f8a987d 100644 --- a/temporalio/nexus/_operation_context.py +++ b/temporalio/nexus/_operation_context.py @@ -766,9 +766,9 @@ def _apply_nexus_context_to_start_activity_request( # pyright: ignore[reportUnu """Apply the current Nexus operation context to an activity start request. This is a no-op outside a Nexus operation context. Within one, it attaches - the Nexus request ID and inbound links and configures conflict handling to - preserve the Nexus metadata. Completion callbacks are added only when the - activity is backing the Nexus operation. + the Nexus request ID and configures conflict handling to preserve the Nexus + metadata. Inbound links are attached to the completion callback when the + activity backs the operation and to the request otherwise. """ nexus_ctx = _try_start_operation_context() if nexus_ctx is not None: @@ -776,15 +776,10 @@ def _apply_nexus_context_to_start_activity_request( # pyright: ignore[reportUnu req.on_conflict_options.attach_completion_callbacks = True req.on_conflict_options.attach_links = True - # Add request_id and all Nexus links if we're in a Nexus context, backing or otherwise req.request_id = nexus_ctx.nexus_context.request_id request_links = nexus_ctx._get_request_links() - # Links are duplicated on request for compatibility with older server versions. - req.links.extend(request_links) - if _in_nexus_backing_start_context(): - # Add callbacks only if we're in a backing Nexus context callbacks = nexus_ctx._get_callbacks( OperationToken( type=OperationTokenType.ACTIVITY, @@ -802,6 +797,8 @@ def _apply_nexus_context_to_start_activity_request( # pyright: ignore[reportUnu ) for callback in callbacks ) + else: + req.links.extend(request_links) def _apply_start_activity_response_to_nexus_context( # pyright: ignore[reportUnusedFunction] diff --git a/tests/nexus/test_link_propagation.py b/tests/nexus/test_link_propagation.py index 2c9f6eec7..a7b78426c 100644 --- a/tests/nexus/test_link_propagation.py +++ b/tests/nexus/test_link_propagation.py @@ -531,8 +531,7 @@ async def test_backing_activity_start_gets_nexus_request_fields() -> None: _start_activity_input() ) - assert len(req.links) == 1 - assert req.links[0] == _inbound_nexus_link() + assert len(req.links) == 0 assert req.request_id == "req-id" assert len(req.completion_callbacks) == 1 operation_token = temporalio.nexus._token.OperationToken.decode( diff --git a/tests/nexus/test_temporal_operation.py b/tests/nexus/test_temporal_operation.py index d966c5cc6..70254542d 100644 --- a/tests/nexus/test_temporal_operation.py +++ b/tests/nexus/test_temporal_operation.py @@ -16,6 +16,7 @@ import temporalio.exceptions from temporalio import activity, nexus, workflow +from temporalio.api.activity.v1 import ActivityExecutionInfo from temporalio.api.common.v1 import Link from temporalio.client import ( ActivityExecutionStatus, @@ -33,7 +34,11 @@ from temporalio.testing import WorkflowEnvironment from temporalio.worker import Worker from tests.helpers import EventType, assert_event_subsequence, assert_eventually -from tests.helpers.nexus import make_nexus_endpoint_name +from tests.helpers.nexus import ( + assert_links_match, + expected_nexus_operation_link, + make_nexus_endpoint_name, +) # Cloud CI's namespace credentials cannot manage Nexus endpoints. # See https://github.com/temporalio/sdk-python/issues/1704. @@ -1132,6 +1137,67 @@ async def test_temporal_operation_start_activity( assert result == "test" +async def test_temporal_operation_backing_activity_does_not_duplicate_links( + client: Client, env: WorkflowEnvironment +): + if env.supports_time_skipping: + pytest.skip( + "Standalone Nexus Operation tests don't work with time-skipping server" + ) + + task_queue = str(uuid.uuid4()) + endpoint_name = make_nexus_endpoint_name(task_queue) + await env.create_nexus_endpoint(endpoint_name, task_queue) + activity_id = f"link-activity-{uuid.uuid4()}" + + @service_handler + class LinkActivityHandler: + @nexus.temporal_operation + async def echo_activity( + self, + _ctx: nexus.TemporalStartOperationContext, + client: nexus.TemporalNexusClient, + input: Input, + ) -> nexus.TemporalOperationResult[str]: + return await client.start_activity( + echo_activity, + input, + id=activity_id, + start_to_close_timeout=timedelta(seconds=5), + ) + + async with Worker( + env.client, + task_queue=task_queue, + nexus_service_handlers=[LinkActivityHandler()], + activities=[echo_activity], + ): + nexus_client = client.create_nexus_client(LinkActivityHandler, endpoint_name) + operation_handle = await nexus_client.start_operation( + LinkActivityHandler.echo_activity, + Input(value="test", task_queue=task_queue), + id=str(uuid.uuid4()), + ) + + assert await operation_handle.result() == "test" + activity_description = await client.get_activity_handle(activity_id).describe() + assert isinstance(activity_description.raw_info, ActivityExecutionInfo) + assert operation_handle.run_id is not None + callback_links = [ + link + for callback in activity_description.raw_callbacks + for link in callback.info.callback.links + ] + assert_links_match( + [*activity_description.raw_info.links, *callback_links], + expected_nexus_operation_link( + namespace=client.namespace, + operation_id=operation_handle.operation_id, + run_id=operation_handle.run_id, + ), + ) + + async def test_temporal_operation_start_activity_raises_error( client: Client, env: WorkflowEnvironment ): From d5642db7b47f1f8bd1d6e0423a24ffbc6871d8ec Mon Sep 17 00:00:00 2001 From: Tim Conley Date: Wed, 5 Aug 2026 18:32:41 -0700 Subject: [PATCH 209/226] Test Strands with unique task queues (#1729) --- tests/contrib/strands/test_hooks.py | 2 +- tests/contrib/strands/test_interrupt.py | 2 +- tests/contrib/strands/test_interrupt_exception.py | 4 ++-- tests/contrib/strands/test_invocation_state.py | 5 +++-- tests/contrib/strands/test_mcp.py | 8 ++++---- tests/contrib/strands/test_model.py | 2 +- tests/contrib/strands/test_model_streaming.py | 2 +- tests/contrib/strands/test_structured_output.py | 2 +- tests/contrib/strands/test_tool.py | 2 +- 9 files changed, 15 insertions(+), 14 deletions(-) diff --git a/tests/contrib/strands/test_hooks.py b/tests/contrib/strands/test_hooks.py index 19976cb44..7bcf0172f 100644 --- a/tests/contrib/strands/test_hooks.py +++ b/tests/contrib/strands/test_hooks.py @@ -67,7 +67,7 @@ async def run(self, prompt: str) -> list[str]: async def test_hooks(client: Client): _AUDIT_LOG.clear() - task_queue = "test_hooks" + task_queue = f"test_hooks-{uuid4()}" plugin = StrandsPlugin( models={ "mock": lambda: MockModel( diff --git a/tests/contrib/strands/test_interrupt.py b/tests/contrib/strands/test_interrupt.py index 64f72bc07..b5c76add0 100644 --- a/tests/contrib/strands/test_interrupt.py +++ b/tests/contrib/strands/test_interrupt.py @@ -65,7 +65,7 @@ async def run(self, prompt: str) -> str: async def test_interrupt(client: Client): - task_queue = "test_interrupt" + task_queue = f"test_interrupt-{uuid4()}" plugin = StrandsPlugin( models={ "mock": lambda: MockModel( diff --git a/tests/contrib/strands/test_interrupt_exception.py b/tests/contrib/strands/test_interrupt_exception.py index ed858b32b..e7492f286 100644 --- a/tests/contrib/strands/test_interrupt_exception.py +++ b/tests/contrib/strands/test_interrupt_exception.py @@ -99,7 +99,7 @@ async def run(self, prompt: str) -> str: async def test_in_workflow_tool_interrupt(client: Client): - task_queue = "test_in_workflow_tool_interrupt" + task_queue = f"test_in_workflow_tool_interrupt-{uuid4()}" plugin = StrandsPlugin( models={ "mock": lambda: MockModel( @@ -140,7 +140,7 @@ async def test_in_workflow_tool_interrupt(client: Client): async def test_activity_tool_interrupt(client: Client): global _activity_delete_calls _activity_delete_calls = 0 - task_queue = "test_activity_tool_interrupt" + task_queue = f"test_activity_tool_interrupt-{uuid4()}" plugin = StrandsPlugin( models={ "mock": lambda: MockModel( diff --git a/tests/contrib/strands/test_invocation_state.py b/tests/contrib/strands/test_invocation_state.py index 01fd4e004..84b5531a4 100644 --- a/tests/contrib/strands/test_invocation_state.py +++ b/tests/contrib/strands/test_invocation_state.py @@ -58,11 +58,12 @@ async def run(self, prompt: str) -> str: async def test_invocation_state_round_trip(client: Client): _RECEIVED.clear() + task_queue = f"test_invocation_state-{uuid4()}" plugin = StrandsPlugin(models={"recording": lambda: _RecordingModel()}) async with Worker( client, - task_queue="test_invocation_state", + task_queue=task_queue, workflows=[_InvocationStateWorkflow], plugins=[plugin], max_cached_workflows=0, @@ -71,7 +72,7 @@ async def test_invocation_state_round_trip(client: Client): _InvocationStateWorkflow.run, "hi", id=f"test_invocation_state_{uuid4()}", - task_queue="test_invocation_state", + task_queue=task_queue, ) # The serializable key crosses the activity boundary; the non-serializable diff --git a/tests/contrib/strands/test_mcp.py b/tests/contrib/strands/test_mcp.py index 0f989cd83..9849e6dda 100644 --- a/tests/contrib/strands/test_mcp.py +++ b/tests/contrib/strands/test_mcp.py @@ -52,7 +52,7 @@ async def run(self, prompt: str) -> str: async def test_mcp(client: Client): - task_queue = "test_mcp" + task_queue = f"test_mcp-{uuid4()}" plugin = StrandsPlugin( models={ "mock": lambda: MockModel( @@ -125,7 +125,7 @@ async def run(self, prompt: str) -> str: async def test_mcp_reuses_connection(client: Client): """Successive MCP tool calls reuse one cached worker-side connection.""" - task_queue = "test_mcp_reuses_connection" + task_queue = f"test_mcp_reuses_connection-{uuid4()}" # Count how often the worker opens a connection. One lazily-opened # connection serves the list-tools discovery and both tool calls (1); # reconnecting per call would make it more. @@ -206,7 +206,7 @@ async def run(self, prompt: str) -> str: async def test_mcp_connection_idle_timeout(client: Client): """A short idle timeout evicts the cached connection while the worker runs.""" - task_queue = "test_mcp_connection_idle_timeout" + task_queue = f"test_mcp_connection_idle_timeout-{uuid4()}" factory_calls = [0] def counting_factory() -> MCPClient: @@ -282,7 +282,7 @@ async def run(self, prompt: str) -> str: async def test_mcp_lists_tools_each_turn_when_uncached(client: Client): """With cache_tools=False the tool list is re-fetched on every model call.""" - task_queue = "test_mcp_lists_tools_each_turn_when_uncached" + task_queue = f"test_mcp_lists_tools_each_turn_when_uncached-{uuid4()}" plugin = StrandsPlugin( models={ "mock": lambda: MockModel( diff --git a/tests/contrib/strands/test_model.py b/tests/contrib/strands/test_model.py index 68d578e5c..c96d4c0d7 100644 --- a/tests/contrib/strands/test_model.py +++ b/tests/contrib/strands/test_model.py @@ -24,7 +24,7 @@ async def run(self, prompt: str) -> str: async def test_model(client: Client): - task_queue = "test_model" + task_queue = f"test_model-{uuid4()}" plugin = StrandsPlugin(models={"mock": lambda: MockModel(["Done!"])}) async with Worker( diff --git a/tests/contrib/strands/test_model_streaming.py b/tests/contrib/strands/test_model_streaming.py index 41f3ff2f1..1a0b84447 100644 --- a/tests/contrib/strands/test_model_streaming.py +++ b/tests/contrib/strands/test_model_streaming.py @@ -30,7 +30,7 @@ async def run(self, prompt: str) -> str: async def test_model_streaming(client: Client): - task_queue = "test_model_streaming" + task_queue = f"test_model_streaming-{uuid4()}" plugin = StrandsPlugin(models={"mock": lambda: MockModel(["Done!"])}) workflow_id = f"test_model_streaming_{uuid4()}" diff --git a/tests/contrib/strands/test_structured_output.py b/tests/contrib/strands/test_structured_output.py index 18c77c553..eafe2b364 100644 --- a/tests/contrib/strands/test_structured_output.py +++ b/tests/contrib/strands/test_structured_output.py @@ -33,7 +33,7 @@ async def run(self, prompt: str) -> PersonInfo: async def test_structured_output(client: Client): - task_queue = "test_structured_output" + task_queue = f"test_structured_output-{uuid4()}" plugin = StrandsPlugin( models={ "mock": lambda: MockModel( diff --git a/tests/contrib/strands/test_tool.py b/tests/contrib/strands/test_tool.py index 39985e2df..d13fcbec1 100644 --- a/tests/contrib/strands/test_tool.py +++ b/tests/contrib/strands/test_tool.py @@ -59,7 +59,7 @@ async def run(self, prompt: str) -> str: async def test_tool(client: Client, tmp_path: Path): - task_queue = "test_tool" + task_queue = f"test_tool-{uuid4()}" fixture = tmp_path / "greeting.txt" fixture.write_text("hello\n") From 069bf54d28c5ec556e27aaaba14184e28ecb859d Mon Sep 17 00:00:00 2001 From: Nathan Gage <54559789+nathan-gage@users.noreply.github.com> Date: Thu, 6 Aug 2026 12:01:44 -0400 Subject: [PATCH 210/226] fix(contrib/pydantic): reuse TypeAdapters across payloads (#1703) * fix(contrib/pydantic): reuse TypeAdapters across payloads PydanticJSONPlainPayloadConverter.from_payload constructed a fresh pydantic TypeAdapter for every payload, rebuilding the core schema each time for non-class hints such as discriminated unions and generic collections. Cache adapters per converter instance, keyed on hashable type hints; unhashable hints keep constructing fresh adapters. The cache is unbounded by default and configurable via the new keyword-only max_cached_type_adapters option on PydanticJSONPlainPayloadConverter and PydanticPayloadConverter (positive bounds with LRU eviction, zero disables caching, negative raises ValueError). Fixes #1695 * fix(contrib/pydantic): default type adapter cache bound to 1024 Bound the per-converter type adapter cache to 1024 entries by default with LRU eviction, capping worst-case memory even with runtime-generated hints while never evicting for typical static hint sets. None remains available for an unbounded cache and zero still disables caching. * test(contrib/pydantic): cover re-imported class cache isolation The workflow sandbox re-imports user modules, producing distinct class objects with identical names. Verify each gets its own cache slot and validates to its own world's class, even when one converter is shared. * fix(contrib/pydantic): avoid double hash on cached decode path Address review: try the cache directly instead of pre-hashing every hint. On TypeError, hash the hint once only to distinguish an unhashable hint (bypass the cache with a fresh adapter) from a TypeError raised during adapter construction (re-raise), keeping adapter errors unsuppressed. --- CHANGELOG.md | 11 ++ temporalio/contrib/pydantic.py | 72 ++++++++++- tests/contrib/pydantic/test_pydantic.py | 158 +++++++++++++++++++++++- 3 files changed, 234 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 483c73d1d..12cfe91fe 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,6 +22,17 @@ to include examples, links to docs, or any other relevant information. ### Changed +- `temporalio.contrib.pydantic` converters now reuse Pydantic type adapters + for repeated type hints instead of rebuilding their schemas for every + payload, greatly speeding up decode of non-model hints such as discriminated + unions ([#1695](https://github.com/temporalio/sdk-python/issues/1695)). Up + to 1024 type adapters are cached per converter instance by default, with + least-recently-used eviction. To change the bound, pass + ``max_cached_type_adapters`` to ``PydanticPayloadConverter`` (or + ``PydanticJSONPlainPayloadConverter``) from a nullary subclass used as the + ``DataConverter.payload_converter_class``; ``None`` makes the cache + unbounded and zero disables caching. + ### Deprecated ### :boom: Breaking Changes diff --git a/temporalio/contrib/pydantic.py b/temporalio/contrib/pydantic.py index c5f2deb41..dd5d0e67a 100644 --- a/temporalio/contrib/pydantic.py +++ b/temporalio/contrib/pydantic.py @@ -13,6 +13,7 @@ Pydantic v1 is not supported. """ +import functools from dataclasses import dataclass from typing import Any @@ -53,10 +54,28 @@ class PydanticJSONPlainPayloadConverter(EncodingPayloadConverter): See https://docs.pydantic.dev/latest/api/standard_library_types/ """ - def __init__(self, to_json_options: ToJsonOptions | None = None): - """Create a new payload converter.""" + def __init__( + self, + to_json_options: ToJsonOptions | None = None, + *, + max_cached_type_adapters: int | None = 1024, + ) -> None: + """Create a new payload converter. + + Args: + to_json_options: Options for serializing values to JSON. + max_cached_type_adapters: Maximum number of type adapters to + cache, with least-recently-used eviction. Defaults to 1024. + If ``None``, the cache is unbounded. If zero, caching is + disabled. + """ + if max_cached_type_adapters is not None and max_cached_type_adapters < 0: + raise ValueError("max_cached_type_adapters cannot be negative") self._schema_serializer = SchemaSerializer(any_schema()) self._to_json_options = to_json_options + self._type_adapter = functools.lru_cache(maxsize=max_cached_type_adapters)( + TypeAdapter + ) @property def encoding(self) -> str: @@ -91,12 +110,26 @@ def from_payload( Uses ``pydantic.TypeAdapter.validate_json`` to construct an instance of the type specified by ``type_hint`` from the JSON payload. + Type adapters are cached per hashable type hint; see + ``max_cached_type_adapters`` on the constructor. See https://docs.pydantic.dev/latest/api/type_adapter/#pydantic.type_adapter.TypeAdapter.validate_json. """ _type_hint = type_hint if type_hint is not None else Any - return TypeAdapter(_type_hint).validate_json(payload.data) + type_adapter: TypeAdapter[Any] + try: + type_adapter = self._type_adapter(_type_hint) + except TypeError: + # Distinguish an unhashable hint (bypass the cache) from a + # TypeError raised while constructing the adapter (re-raise). + try: + hash(_type_hint) + except TypeError: + type_adapter = TypeAdapter(_type_hint) + else: + raise + return type_adapter.validate_json(payload.data) class PydanticPayloadConverter(CompositePayloadConverter): @@ -106,9 +139,36 @@ class PydanticPayloadConverter(CompositePayloadConverter): :py:class:`PydanticJSONPlainPayloadConverter`. """ - def __init__(self, to_json_options: ToJsonOptions | None = None) -> None: - """Initialize object""" - json_payload_converter = PydanticJSONPlainPayloadConverter(to_json_options) + def __init__( + self, + to_json_options: ToJsonOptions | None = None, + *, + max_cached_type_adapters: int | None = 1024, + ) -> None: + """Initialize object. + + Args: + to_json_options: Options for serializing values to JSON. + max_cached_type_adapters: Maximum number of type adapters to + cache, with least-recently-used eviction. Defaults to 1024. + If ``None``, the cache is unbounded. If zero, caching is + disabled. + + To configure this through a :py:class:`DataConverter`, use a + nullary subclass as the payload converter class:: + + class MyPayloadConverter(PydanticPayloadConverter): + def __init__(self) -> None: + super().__init__(max_cached_type_adapters=128) + + my_data_converter = DataConverter( + payload_converter_class=MyPayloadConverter + ) + """ + json_payload_converter = PydanticJSONPlainPayloadConverter( + to_json_options, + max_cached_type_adapters=max_cached_type_adapters, + ) super().__init__( *( c diff --git a/tests/contrib/pydantic/test_pydantic.py b/tests/contrib/pydantic/test_pydantic.py index 69a723a56..7d70dfd19 100644 --- a/tests/contrib/pydantic/test_pydantic.py +++ b/tests/contrib/pydantic/test_pydantic.py @@ -2,6 +2,7 @@ import datetime import os import pathlib +import typing import uuid import pydantic @@ -9,7 +10,11 @@ from pydantic import BaseModel from temporalio.client import Client -from temporalio.contrib.pydantic import pydantic_data_converter +from temporalio.contrib.pydantic import ( + PydanticJSONPlainPayloadConverter, + PydanticPayloadConverter, + pydantic_data_converter, +) from temporalio.worker import Worker from temporalio.worker.workflow_sandbox._restrictions import ( RestrictionContext, @@ -41,6 +46,157 @@ clone_objects, ) +_MANY_TYPE_HINTS = tuple( + typing.cast(type, typing.cast(object, typing.Annotated[list[int], index])) + for index in range(1025) +) +_UNHASHABLE_TYPE_HINT = typing.cast( + type, typing.cast(object, typing.Annotated[list[int], []]) +) + + +@pytest.mark.parametrize( + ( + "converter_kwargs", + "type_hints", + "expected_type_adapter_constructions", + ), + [ + # Default caches repeated hints + ({}, (list[int], list[int]), 1), + # Zero disables caching + ({"max_cached_type_adapters": 0}, (list[int], list[int]), 2), + # Unhashable hints bypass the cache + ({}, (_UNHASHABLE_TYPE_HINT, _UNHASHABLE_TYPE_HINT), 2), + # Default bound is 1024: 1025 distinct hints evict the first + ({}, _MANY_TYPE_HINTS + (_MANY_TYPE_HINTS[0],), 1026), + # None is unbounded: no eviction + ( + {"max_cached_type_adapters": None}, + _MANY_TYPE_HINTS + (_MANY_TYPE_HINTS[0],), + 1025, + ), + # Explicit bound evicts least recently used + ( + {"max_cached_type_adapters": 1}, + (list[int], _MANY_TYPE_HINTS[0], list[int]), + 3, + ), + ], +) +def test_type_adapter_reuse( + monkeypatch: pytest.MonkeyPatch, + converter_kwargs: dict[str, typing.Any], + type_hints: tuple[type, ...], + expected_type_adapter_constructions: int, +): + actual_type_adapter = pydantic.TypeAdapter + type_adapter_constructions = 0 + + def counting_type_adapter( + type_hint: typing.Any, + ) -> pydantic.TypeAdapter[typing.Any]: + nonlocal type_adapter_constructions + type_adapter_constructions += 1 + return actual_type_adapter(type_hint) + + monkeypatch.setattr( + "temporalio.contrib.pydantic.TypeAdapter", counting_type_adapter + ) + converter = PydanticJSONPlainPayloadConverter(**converter_kwargs) + payload = converter.to_payload([1]) + assert payload is not None + for type_hint in type_hints: + assert converter.from_payload(payload, type_hint) == [1] + assert type_adapter_constructions == expected_type_adapter_constructions + + +@pytest.mark.parametrize( + ("max_cached_type_adapters", "expected_type_adapter_constructions"), + [(None, 1), (0, 2)], +) +def test_composite_converter_forwards_type_adapter_cache_size( + monkeypatch: pytest.MonkeyPatch, + max_cached_type_adapters: int | None, + expected_type_adapter_constructions: int, +): + actual_type_adapter = pydantic.TypeAdapter + type_adapter_constructions = 0 + + def counting_type_adapter( + type_hint: typing.Any, + ) -> pydantic.TypeAdapter[typing.Any]: + nonlocal type_adapter_constructions + type_adapter_constructions += 1 + return actual_type_adapter(type_hint) + + monkeypatch.setattr( + "temporalio.contrib.pydantic.TypeAdapter", counting_type_adapter + ) + converter = PydanticPayloadConverter( + max_cached_type_adapters=max_cached_type_adapters + ) + payloads = converter.to_payloads([[1], [2]]) + assert converter.from_payloads(payloads, [list[int], list[int]]) == [[1], [2]] + assert type_adapter_constructions == expected_type_adapter_constructions + + +def test_type_adapter_reuse_across_threads_with_deferred_build(): + import concurrent.futures + + class DeferredModel(BaseModel): + model_config = pydantic.ConfigDict(defer_build=True) + value: int + + converter = PydanticJSONPlainPayloadConverter() + payload = converter.to_payload(DeferredModel(value=1)) + assert payload is not None + + def decode() -> DeferredModel: + return converter.from_payload(payload, DeferredModel) + + with concurrent.futures.ThreadPoolExecutor(max_workers=8) as executor: + results = list(executor.map(lambda _: decode(), range(64))) + assert all(result == DeferredModel(value=1) for result in results) + + +def test_type_adapter_cache_distinguishes_reimported_classes(): + # The workflow sandbox re-imports user modules, producing distinct class + # objects with identical names. Class hints hash by identity, so each + # world's class must get its own cache slot and validate to itself. + import types + + source = "from pydantic import BaseModel\n\nclass Foo(BaseModel):\n name: str\n" + + def load_module() -> types.ModuleType: + module = types.ModuleType("test_reimported_models") + exec(compile(source, "test_reimported_models.py", "exec"), module.__dict__) + return module + + foo_outside = load_module().Foo + foo_sandbox = load_module().Foo + assert foo_outside is not foo_sandbox + assert hash(foo_outside) != hash(foo_sandbox) + + # Worst case: one converter shared across both worlds (the real sandbox + # creates a separate converter per workflow instance). + converter = PydanticJSONPlainPayloadConverter() + payload = converter.to_payload(foo_outside(name="x")) + assert payload is not None + decoded_outside = converter.from_payload(payload, foo_outside) + decoded_sandbox = converter.from_payload(payload, foo_sandbox) + assert type(decoded_outside) is foo_outside + assert type(decoded_sandbox) is foo_sandbox + + +@pytest.mark.parametrize( + "converter_type", + [PydanticJSONPlainPayloadConverter, PydanticPayloadConverter], +) +def test_type_adapter_cache_rejects_negative_size(converter_type: type): + with pytest.raises(ValueError, match="max_cached_type_adapters cannot be negative"): + converter_type(max_cached_type_adapters=-1) + async def test_instantiation_outside_sandbox(): make_list_of_pydantic_objects() From 0022df1d5f597ca1495993c4c001e7a7030c0a43 Mon Sep 17 00:00:00 2001 From: Alex Mazzeo Date: Fri, 7 Aug 2026 08:10:41 -0700 Subject: [PATCH 211/226] Fix race in nexus double start test (#1728) --- tests/nexus/test_temporal_operation.py | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/tests/nexus/test_temporal_operation.py b/tests/nexus/test_temporal_operation.py index 70254542d..85948deb3 100644 --- a/tests/nexus/test_temporal_operation.py +++ b/tests/nexus/test_temporal_operation.py @@ -341,19 +341,21 @@ async def double_start_activity( self, _ctx: nexus.TemporalStartOperationContext, client: nexus.TemporalNexusClient, - input: Input, + _input: Input, ) -> nexus.TemporalOperationResult[None]: + # Keep the first activity running so its callback cannot race the + # handler error raised by the second start. await client.start_activity( - echo_activity, - input, + wait_for_cancel_activity, id=f"double-start-activity-{uuid.uuid4()}", - start_to_close_timeout=timedelta(seconds=5), + start_to_close_timeout=timedelta(seconds=30), + heartbeat_timeout=timedelta(seconds=1), ) await client.start_activity( - echo_activity, - input, + wait_for_cancel_activity, id=f"double-start-activity-{uuid.uuid4()}", - start_to_close_timeout=timedelta(seconds=5), + start_to_close_timeout=timedelta(seconds=30), + heartbeat_timeout=timedelta(seconds=1), ) return nexus.TemporalOperationResult.sync(None) @@ -1330,7 +1332,7 @@ async def test_temporal_operation_double_start_activity_raises_handler_err( env.client, task_queue=task_queue, nexus_service_handlers=[TestServiceHandler()], - activities=[echo_activity], + activities=[wait_for_cancel_activity], ): nexus_client = client.create_nexus_client(TestService, endpoint_name) From 259c9e84e94214c9e3b636776fdf2a58b0ffdc4e Mon Sep 17 00:00:00 2001 From: Tim Conley Date: Fri, 7 Aug 2026 08:53:01 -0700 Subject: [PATCH 212/226] Wait for deployment ramp propagation (#1730) --- tests/worker/test_worker.py | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/tests/worker/test_worker.py b/tests/worker/test_worker.py index 898615809..57614c21e 100644 --- a/tests/worker/test_worker.py +++ b/tests/worker/test_worker.py @@ -875,9 +875,15 @@ async def test_worker_deployment_ramp(client: Client, env: WorkflowEnvironment): client, describe_resp.conflict_token, v1 ) ).conflict_token + await wait_for_worker_deployment_routing_config_propagation( + client, deployment_name, v1.build_id + ) conflict_token = ( await set_ramping_version(client, conflict_token, v2, 100) ).conflict_token + await wait_for_worker_deployment_routing_config_propagation( + client, deployment_name, v1.build_id, v2.build_id, 100 + ) # Run workflows and verify they run on v2 for i in range(3): @@ -894,6 +900,9 @@ async def test_worker_deployment_ramp(client: Client, env: WorkflowEnvironment): conflict_token = ( await set_ramping_version(client, conflict_token, v2, 0) ).conflict_token + await wait_for_worker_deployment_routing_config_propagation( + client, deployment_name, v1.build_id, v2.build_id, 0 + ) for i in range(3): wfa = await client.start_workflow( DeploymentVersioningWorkflowV1AutoUpgrade.run, @@ -906,6 +915,9 @@ async def test_worker_deployment_ramp(client: Client, env: WorkflowEnvironment): # Set ramp to 50 and eventually verify workflows run on both versions await set_ramping_version(client, conflict_token, v2, 50) + await wait_for_worker_deployment_routing_config_propagation( + client, deployment_name, v1.build_id, v2.build_id, 50 + ) seen_results = set() async def run_and_record(): @@ -1319,6 +1331,7 @@ async def wait_for_worker_deployment_routing_config_propagation( deployment_name: str, expected_current_build_id: str, expected_ramping_build_id: str = "", + expected_ramping_percentage: float | None = None, ) -> None: """Wait for routing config to be propagated to all task queues.""" import temporalio.api.enums.v1 @@ -1341,6 +1354,11 @@ async def check() -> bool: != expected_ramping_build_id ): return False + if ( + expected_ramping_percentage is not None + and routing_config.ramping_version_percentage != expected_ramping_percentage + ): + return False state = resp.worker_deployment_info.routing_config_update_state if ( state From 2c659cb4c99f335d4df4bff91a535f0be3eadada Mon Sep 17 00:00:00 2001 From: Tim Conley Date: Fri, 7 Aug 2026 10:32:28 -0700 Subject: [PATCH 213/226] test: provision Cloud namespace per CI run (#1731) * test: provision Cloud namespace per CI run * fix: use current Cloud API for namespace lifecycle * fix: use latest Cloud API version in CI * test: skip Cloud-incompatible feature tests --- .github/scripts/cloud_namespace.py | 110 ++++++++++++++++++++++ .github/workflows/ci.yml | 41 ++++++-- tests/nexus/test_temporal_system_nexus.py | 2 + tests/test_activity.py | 4 + 4 files changed, 150 insertions(+), 7 deletions(-) create mode 100644 .github/scripts/cloud_namespace.py diff --git a/.github/scripts/cloud_namespace.py b/.github/scripts/cloud_namespace.py new file mode 100644 index 000000000..c13d1e65e --- /dev/null +++ b/.github/scripts/cloud_namespace.py @@ -0,0 +1,110 @@ +"""Create and delete an isolated Temporal Cloud namespace for CI.""" + +import asyncio +import os +import sys +import time +from pathlib import Path + +from temporalio.api.cloud.cloudservice.v1 import ( + CreateNamespaceRequest, + DeleteNamespaceRequest, + GetAsyncOperationRequest, + GetNamespaceRequest, +) +from temporalio.api.cloud.namespace.v1 import MtlsAuthSpec, NamespaceSpec +from temporalio.api.cloud.operation.v1 import AsyncOperation +from temporalio.client import CloudOperationsClient + + +async def wait_for_operation( + client: CloudOperationsClient, operation: AsyncOperation +) -> None: + deadline = time.monotonic() + 10 * 60 + while True: + operation = ( + await client.cloud_service.get_async_operation( + GetAsyncOperationRequest(async_operation_id=operation.id) + ) + ).async_operation + if operation.state == AsyncOperation.STATE_FULFILLED: + return + if operation.state in { + AsyncOperation.STATE_FAILED, + AsyncOperation.STATE_CANCELLED, + AsyncOperation.STATE_REJECTED, + }: + raise RuntimeError( + "Cloud operation " + f"{operation.id} {AsyncOperation.State.Name(operation.state).lower()}: " + f"{operation.failure_reason}" + ) + if time.monotonic() >= deadline: + raise TimeoutError(f"Timed out waiting for Cloud operation {operation.id}") + delay = max( + operation.check_duration.seconds + + operation.check_duration.nanos / 1_000_000_000, + 1, + ) + await asyncio.sleep(min(delay, deadline - time.monotonic())) + + +async def create() -> None: + client = await cloud_client() + namespace_name = "sdk-python-ci-{}-{}".format( + os.environ["GITHUB_RUN_ID"], os.environ["GITHUB_RUN_ATTEMPT"] + ) + result = await client.cloud_service.create_namespace( + CreateNamespaceRequest( + spec=NamespaceSpec( + name=namespace_name, + regions=["aws-ca-central-1"], + retention_days=1, + mtls_auth=MtlsAuthSpec( + accepted_client_ca=Path( + os.environ["TEMPORAL_CLOUD_CLIENT_CA_PATH"] + ).read_bytes(), + enabled=True, + ), + ) + ) + ) + # Make cleanup possible even if provisioning fails after Cloud accepts the request. + with open(os.environ["GITHUB_OUTPUT"], "a") as output: + output.write(f"namespace={result.namespace}\n") + await wait_for_operation(client, result.async_operation) + + +async def delete(namespace: str) -> None: + client = await cloud_client() + existing = await client.cloud_service.get_namespace( + GetNamespaceRequest(namespace=namespace) + ) + result = await client.cloud_service.delete_namespace( + DeleteNamespaceRequest( + namespace=namespace, + resource_version=existing.namespace.resource_version, + ) + ) + await wait_for_operation(client, result.async_operation) + + +async def cloud_client() -> CloudOperationsClient: + return await CloudOperationsClient.connect( + api_key=os.environ["TEMPORAL_CLIENT_CLOUD_API_KEY"], + version=os.environ["TEMPORAL_CLIENT_CLOUD_API_VERSION"], + ) + + +async def main() -> None: + match sys.argv[1:]: + case ["create"]: + await create() + case ["delete", namespace]: + await delete(namespace) + case _: + raise ValueError("Usage: cloud_namespace.py create|delete ") + + +if __name__ == "__main__": + asyncio.run(main()) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index bcf42e8af..b1098dcdc 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -230,19 +230,46 @@ jobs: - run: uv tool install poethepoet - run: uv sync --all-extras - run: poe build-develop + - name: Generate Cloud test certificates + run: | + cert_dir="$RUNNER_TEMP/cloud-test-certs" + mkdir "$cert_dir" + openssl req -x509 -newkey rsa:2048 -nodes -days 1 \ + -keyout "$cert_dir/ca.key" -out "$cert_dir/ca.pem" \ + -subj '/CN=Temporal Python SDK Cloud CI CA' + openssl req -newkey rsa:2048 -nodes \ + -keyout "$cert_dir/client.key" -out "$cert_dir/client.csr" \ + -subj '/CN=Temporal Python SDK Cloud CI' + openssl x509 -req -days 1 -in "$cert_dir/client.csr" \ + -CA "$cert_dir/ca.pem" -CAkey "$cert_dir/ca.key" -CAcreateserial \ + -out "$cert_dir/client.pem" -extfile <(printf 'extendedKeyUsage=clientAuth') + { + echo "TEMPORAL_CLOUD_CLIENT_CA_PATH=$cert_dir/ca.pem" + echo "TEMPORAL_TLS_CLIENT_CERT_PATH=$cert_dir/client.pem" + echo "TEMPORAL_TLS_CLIENT_KEY_PATH=$cert_dir/client.key" + } >> "$GITHUB_ENV" + - name: Create Cloud namespace + id: create-cloud-namespace + run: uv run python .github/scripts/cloud_namespace.py create + env: + TEMPORAL_CLIENT_CLOUD_API_KEY: ${{ secrets.TEMPORAL_CLIENT_CLOUD_API_KEY }} + TEMPORAL_CLIENT_CLOUD_API_VERSION: v0.19.1 - run: mkdir junit-xml - run: poe test -s --workflow-environment envconfig --junit-xml=junit-xml/cloud.xml timeout-minutes: 15 env: - TEMPORAL_ADDRESS: sdk-ci.a2dd6.tmprl.cloud:7233 - TEMPORAL_NAMESPACE: sdk-ci.a2dd6 - TEMPORAL_API_KEY: ${{ secrets.TEMPORAL_CLIENT_CLOUD_API_KEY }} - TEMPORAL_TLS_CLIENT_CERT_DATA: ${{ secrets.TEMPORAL_CLIENT_CERT }} - TEMPORAL_TLS_CLIENT_KEY_DATA: ${{ secrets.TEMPORAL_CLIENT_KEY }} + TEMPORAL_ADDRESS: ${{ steps.create-cloud-namespace.outputs.namespace }}.tmprl.cloud:7233 + TEMPORAL_NAMESPACE: ${{ steps.create-cloud-namespace.outputs.namespace }} TEMPORAL_IS_CLOUD_TESTS: true TEMPORAL_CLIENT_CLOUD_API_KEY: ${{ secrets.TEMPORAL_CLIENT_CLOUD_API_KEY }} - TEMPORAL_CLIENT_CLOUD_API_VERSION: 2024-05-13-00 - TEMPORAL_CLIENT_CLOUD_NAMESPACE: sdk-ci.a2dd6 + TEMPORAL_CLIENT_CLOUD_API_VERSION: v0.19.1 + TEMPORAL_CLIENT_CLOUD_NAMESPACE: ${{ steps.create-cloud-namespace.outputs.namespace }} + - name: Delete Cloud namespace + if: ${{ always() && steps.create-cloud-namespace.outputs.namespace != '' }} + run: uv run python .github/scripts/cloud_namespace.py delete "${{ steps.create-cloud-namespace.outputs.namespace }}" + env: + TEMPORAL_CLIENT_CLOUD_API_KEY: ${{ secrets.TEMPORAL_CLIENT_CLOUD_API_KEY }} + TEMPORAL_CLIENT_CLOUD_API_VERSION: v0.19.1 - name: "Upload junit-xml artifacts" uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4 if: always() diff --git a/tests/nexus/test_temporal_system_nexus.py b/tests/nexus/test_temporal_system_nexus.py index ec86689d7..ff6b36e41 100644 --- a/tests/nexus/test_temporal_system_nexus.py +++ b/tests/nexus/test_temporal_system_nexus.py @@ -374,6 +374,8 @@ def test_system_nexus_proto_roundtrip(message_type: type[Message]) -> None: assert roundtripped == proto_value +# Cloud namespaces created by CI do not have the System Nexus dynamic config. +@pytest.mark.requires_local_server async def test_external_workflow_handle_signal_with_start_workflow_uses_system_nexus( env: WorkflowEnvironment, ): diff --git a/tests/test_activity.py b/tests/test_activity.py index 6efa0d644..6a6d14206 100644 --- a/tests/test_activity.py +++ b/tests/test_activity.py @@ -202,6 +202,8 @@ async def count_activities(self, input: CountActivitiesInput): return await super().count_activities(input) +# Cloud namespaces created by CI do not have the activity start-delay dynamic config. +@pytest.mark.requires_local_server async def test_start_activity_calls_interceptor( client: Client, env: WorkflowEnvironment ): @@ -461,6 +463,8 @@ async def test_get_result(client: Client, env: WorkflowEnvironment): assert await result_via_execute_activity == 2 +# Cloud namespaces created by CI do not have the activity start-delay dynamic config. +@pytest.mark.requires_local_server async def test_start_activity_start_delay(client: Client, env: WorkflowEnvironment): if env.supports_time_skipping: pytest.skip( From b66cf29885485e4383273425e6e7b596c508433f Mon Sep 17 00:00:00 2001 From: Tim Conley Date: Fri, 7 Aug 2026 11:45:02 -0700 Subject: [PATCH 214/226] test: tolerate trace start-run ordering (#1714) * test: tolerate trace start-run ordering * test: resolve trace helper type warning --- tests/contrib/langsmith/conftest.py | 41 ++--- tests/contrib/langsmith/test_integration.py | 176 ++++++++++---------- tests/contrib/langsmith/test_plugin.py | 100 ++++++----- tests/helpers/trace.py | 111 ++++++++++++ 4 files changed, 270 insertions(+), 158 deletions(-) create mode 100644 tests/helpers/trace.py diff --git a/tests/contrib/langsmith/conftest.py b/tests/contrib/langsmith/conftest.py index 1d90bae5e..1711c0446 100644 --- a/tests/contrib/langsmith/conftest.py +++ b/tests/contrib/langsmith/conftest.py @@ -8,6 +8,8 @@ import pytest +from tests.helpers.trace import TraceNode + @pytest.fixture(autouse=True) def _clear_langsmith_env_cache() -> Any: # pyright: ignore[reportUnusedFunction] @@ -92,13 +94,8 @@ def clear(self) -> None: self._by_id.clear() -def dump_traces(collector: InMemoryRunCollector) -> list[list[str]]: - """Reconstruct parent-child hierarchy grouped by root trace. - - Returns a list of traces, where each trace is a list of indented - strings (same format as dump_runs). Each trace starts from a - different root run. - """ +def build_trace_trees(collector: InMemoryRunCollector) -> list[TraceNode]: + """Build trace trees from the collector's run parent relationships.""" runs = collector.runs children: dict[str | None, list[_RunRecord]] = {} for r in runs: @@ -113,30 +110,18 @@ def dump_traces(collector: InMemoryRunCollector) -> list[list[str]]: f"which is not in the collected runs — dangling parent reference" ) - traces: list[list[str]] = [] - for root in children.get(None, []): - trace: list[str] = [] - - def _walk(parent_id: str | None, depth: int) -> None: - for child in children.get(parent_id, []): - trace.append(" " * depth + child.name) - _walk(child.id, depth + 1) - - trace.append(root.name) - _walk(root.id, 1) - traces.append(trace) - - return traces - + def build_tree(run: _RunRecord) -> TraceNode: + return TraceNode( + run.name, + [build_tree(child) for child in children.get(run.id, [])], + ) -def dump_runs(collector: InMemoryRunCollector) -> list[str]: - """Flat list of all runs across all traces.""" - return [run for trace in dump_traces(collector) for run in trace] + return [build_tree(root) for root in children.get(None, [])] -def find_traces(traces: list[list[str]], root_name: str) -> list[list[str]]: - """Filter traces by exact root name match.""" - return [t for t in traces if t[0] == root_name] +def find_trace_trees(traces: list[TraceNode], root_name: str) -> list[TraceNode]: + """Filter trace trees by exact root run name.""" + return [trace for trace in traces if trace.name == root_name] def make_mock_ls_client(collector: InMemoryRunCollector) -> MagicMock: diff --git a/tests/contrib/langsmith/test_integration.py b/tests/contrib/langsmith/test_integration.py index 426b9a3af..bfffdb0a0 100644 --- a/tests/contrib/langsmith/test_integration.py +++ b/tests/contrib/langsmith/test_integration.py @@ -26,13 +26,13 @@ from temporalio.testing import WorkflowEnvironment from tests.contrib.langsmith.conftest import ( InMemoryRunCollector, - dump_runs, - dump_traces, - find_traces, + build_trace_trees, + find_trace_trees, make_mock_ls_client, ) from tests.helpers import new_worker from tests.helpers.nexus import make_nexus_endpoint_name +from tests.helpers.trace import assert_trace_hierarchy # --------------------------------------------------------------------------- # Shared @traceable functions and activities @@ -359,7 +359,6 @@ async def test_workflow_activity_trace_hierarchy( ) assert await result.result() == "activity-done" - hierarchy = dump_runs(collector) expected = [ "StartWorkflow:SimpleWorkflow", "RunWorkflow:SimpleWorkflow", @@ -367,9 +366,7 @@ async def test_workflow_activity_trace_hierarchy( " RunActivity:simple_activity", " simple_activity", ] - assert hierarchy == expected, ( - f"Hierarchy mismatch.\nExpected:\n{expected}\nActual:\n{hierarchy}" - ) + assert_trace_hierarchy(build_trace_trees(collector), expected) # Verify run_type: RunActivity is "tool", others are "chain" for run in collector.runs: @@ -421,7 +418,6 @@ async def test_no_duplicate_traces_on_replay( # Workflow→activity→@traceable flow should produce exactly these runs # with no duplicates from replay: - hierarchy = dump_runs(collector) expected = [ "StartWorkflow:TraceableActivityWorkflow", "RunWorkflow:TraceableActivityWorkflow", @@ -430,10 +426,7 @@ async def test_no_duplicate_traces_on_replay( " traceable_activity", " inner_llm_call", ] - assert hierarchy == expected, ( - f"Hierarchy mismatch (possible replay duplicates).\n" - f"Expected:\n{expected}\nActual:\n{hierarchy}" - ) + assert_trace_hierarchy(build_trace_trees(collector), expected) # --------------------------------------------------------------------------- @@ -467,7 +460,6 @@ async def test_activity_failure_marked( with pytest.raises(WorkflowFailureError): await handle.result() - hierarchy = dump_runs(collector) expected = [ "StartWorkflow:ActivityFailureWorkflow", "RunWorkflow:ActivityFailureWorkflow", @@ -475,9 +467,7 @@ async def test_activity_failure_marked( " RunActivity:failing_activity", " failing_activity", ] - assert hierarchy == expected, ( - f"Hierarchy mismatch.\nExpected:\n{expected}\nActual:\n{hierarchy}" - ) + assert_trace_hierarchy(build_trace_trees(collector), expected) # Verify the RunActivity run has an error activity_runs = [ r for r in collector.runs if r.name == "RunActivity:failing_activity" @@ -509,14 +499,11 @@ async def test_workflow_failure_marked( with pytest.raises(WorkflowFailureError): await handle.result() - hierarchy = dump_runs(collector) expected = [ "StartWorkflow:FailingWorkflow", "RunWorkflow:FailingWorkflow", ] - assert hierarchy == expected, ( - f"Hierarchy mismatch.\nExpected:\n{expected}\nActual:\n{hierarchy}" - ) + assert_trace_hierarchy(build_trace_trees(collector), expected) # Verify the RunWorkflow run has an error wf_runs = [r for r in collector.runs if r.name == "RunWorkflow:FailingWorkflow"] assert len(wf_runs) == 1 @@ -547,7 +534,6 @@ async def test_benign_error_not_marked( with pytest.raises(WorkflowFailureError): await handle.result() - hierarchy = dump_runs(collector) expected = [ "StartWorkflow:BenignErrorWorkflow", "RunWorkflow:BenignErrorWorkflow", @@ -555,9 +541,7 @@ async def test_benign_error_not_marked( " RunActivity:benign_failing_activity", " benign_failing_activity", ] - assert hierarchy == expected, ( - f"Hierarchy mismatch.\nExpected:\n{expected}\nActual:\n{hierarchy}" - ) + assert_trace_hierarchy(build_trace_trees(collector), expected) # The RunActivity run for benign error should NOT have error set activity_runs = [ r for r in collector.runs if r.name == "RunActivity:benign_failing_activity" @@ -651,12 +635,12 @@ async def user_pipeline() -> WorkflowHandle[Any, Any]: assert result == "comprehensive-done" - traces = dump_traces(collector) + trace_trees = build_trace_trees(collector) # user_pipeline trace: StartWorkflow + full workflow execution tree - workflow_traces = find_traces(traces, "user_pipeline") - assert len(workflow_traces) == 1 - assert workflow_traces[0] == [ + workflow_trace_trees = find_trace_trees(trace_trees, "user_pipeline") + assert len(workflow_trace_trees) == 1 + expected_workflow = [ "user_pipeline", " StartWorkflow:ComprehensiveWorkflow", " RunWorkflow:ComprehensiveWorkflow", @@ -718,53 +702,73 @@ async def user_pipeline() -> WorkflowHandle[Any, Any]: " outer_chain", " inner_llm_call", ] + assert_trace_hierarchy(workflow_trace_trees, expected_workflow) # poll_query trace (separate root, variable number of iterations) - poll_traces = find_traces(traces, "poll_query") - assert len(poll_traces) == 1 - poll = poll_traces[0] - assert poll[0] == "poll_query" - poll_children = poll[1:] - for i in range(0, len(poll_children), 2): - assert poll_children[i] == " QueryWorkflow:is_waiting_for_signal" - assert poll_children[i + 1] == " HandleQuery:is_waiting_for_signal" + poll_trace_trees = find_trace_trees(trace_trees, "poll_query") + assert len(poll_trace_trees) == 1 + poll = poll_trace_trees[0] + assert poll.name == "poll_query" + poll_children = poll.children + for poll_child in poll_children: + assert poll_child.name == "QueryWorkflow:is_waiting_for_signal" + assert [child.name for child in poll_child.children] == [ + "HandleQuery:is_waiting_for_signal" + ] + assert not poll_child.children[0].children # Raw-client query — no parent context, appears as root - raw_query_traces = [t for t in traces if t[0].startswith("HandleQuery:")] - assert len(raw_query_traces) == 1 + raw_query_trace_trees = [ + trace for trace in trace_trees if trace.name.startswith("HandleQuery:") + ] + assert len(raw_query_trace_trees) == 1 # Phase 2: each operation is its own root trace - query_traces = find_traces(traces, "QueryWorkflow:my_query") - assert len(query_traces) == 1 - assert query_traces[0] == [ - "QueryWorkflow:my_query", - " HandleQuery:my_query", - ] + query_trace_trees = find_trace_trees(trace_trees, "QueryWorkflow:my_query") + assert len(query_trace_trees) == 1 + assert_trace_hierarchy( + query_trace_trees, + [ + "QueryWorkflow:my_query", + " HandleQuery:my_query", + ], + ) - signal_traces = find_traces(traces, "SignalWorkflow:my_signal") - assert len(signal_traces) == 1 - assert signal_traces[0] == [ - "SignalWorkflow:my_signal", - " HandleSignal:my_signal", - ] + signal_trace_trees = find_trace_trees(trace_trees, "SignalWorkflow:my_signal") + assert len(signal_trace_trees) == 1 + assert_trace_hierarchy( + signal_trace_trees, + [ + "SignalWorkflow:my_signal", + " HandleSignal:my_signal", + ], + ) - update_traces = find_traces(traces, "StartWorkflowUpdate:my_update") - assert len(update_traces) == 1 - assert update_traces[0] == [ - "StartWorkflowUpdate:my_update", - " ValidateUpdate:my_update", - " HandleUpdate:my_update", - ] + update_trace_trees = find_trace_trees( + trace_trees, "StartWorkflowUpdate:my_update" + ) + assert len(update_trace_trees) == 1 + assert_trace_hierarchy( + update_trace_trees, + [ + "StartWorkflowUpdate:my_update", + " ValidateUpdate:my_update", + " HandleUpdate:my_update", + ], + ) # Update without a validator — no ValidateUpdate trace - unvalidated_traces = find_traces( - traces, "StartWorkflowUpdate:my_unvalidated_update" + unvalidated_trace_trees = find_trace_trees( + trace_trees, "StartWorkflowUpdate:my_unvalidated_update" + ) + assert len(unvalidated_trace_trees) == 1 + assert_trace_hierarchy( + unvalidated_trace_trees, + [ + "StartWorkflowUpdate:my_unvalidated_update", + " HandleUpdate:my_unvalidated_update", + ], ) - assert len(unvalidated_traces) == 1 - assert unvalidated_traces[0] == [ - "StartWorkflowUpdate:my_unvalidated_update", - " HandleUpdate:my_unvalidated_update", - ] @pytest.mark.requires_local_server async def test_comprehensive_without_temporal_runs( @@ -843,11 +847,11 @@ async def user_pipeline() -> WorkflowHandle[Any, Any]: assert result == "comprehensive-done" - traces = dump_traces(collector) + trace_trees = build_trace_trees(collector) # Main workflow trace (only @traceable runs, nested under user_pipeline) - workflow_traces = find_traces(traces, "user_pipeline") - assert len(workflow_traces) == 1 + workflow_trace_trees = find_trace_trees(trace_trees, "user_pipeline") + assert len(workflow_trace_trees) == 1 expected_workflow = [ "user_pipeline", " nested_traceable_activity", @@ -877,15 +881,12 @@ async def user_pipeline() -> WorkflowHandle[Any, Any]: " outer_chain", " inner_llm_call", ] - assert workflow_traces[0] == expected_workflow, ( - f"Workflow trace mismatch.\n" - f"Expected:\n{expected_workflow}\nActual:\n{workflow_traces[0]}" - ) + assert_trace_hierarchy(workflow_trace_trees, expected_workflow) # Poll query — separate root, just the @traceable wrapper, no Temporal children - poll_traces = find_traces(traces, "poll_query") - assert len(poll_traces) == 1 - assert poll_traces[0] == ["poll_query"] + poll_trace_trees = find_trace_trees(trace_trees, "poll_query") + assert len(poll_trace_trees) == 1 + assert_trace_hierarchy(poll_trace_trees, ["poll_query"]) # --------------------------------------------------------------------------- @@ -978,7 +979,6 @@ async def test_factory_traceable_no_external_context( == "response to: async|sync-response to: sync|sync-response to: mixed" ) - hierarchy = dump_runs(collector) expected = [ "outer_chain", " inner_llm_call", @@ -990,9 +990,7 @@ async def test_factory_traceable_no_external_context( " outer_chain", " inner_llm_call", ] - assert hierarchy == expected, ( - f"Hierarchy mismatch.\nExpected:\n{expected}\nActual:\n{hierarchy}" - ) + assert_trace_hierarchy(build_trace_trees(collector), expected) # Verify no duplicate run IDs (replay safety with max_cached_workflows=0) run_ids = [r.id for r in collector.runs] @@ -1065,7 +1063,6 @@ async def test_mixed_sync_async_traceable_with_temporal_runs( == "response to: async|sync-response to: sync|sync-response to: mixed" ) - hierarchy = dump_runs(collector) # With add_temporal_runs=True, Temporal operations get their own runs. # @traceable calls nest under the RunWorkflow run. expected = [ @@ -1083,9 +1080,7 @@ async def test_mixed_sync_async_traceable_with_temporal_runs( " outer_chain", " inner_llm_call", ] - assert hierarchy == expected, ( - f"Hierarchy mismatch.\nExpected:\n{expected}\nActual:\n{hierarchy}" - ) + assert_trace_hierarchy(build_trace_trees(collector), expected) # Verify no duplicate run IDs (replay safety with max_cached_workflows=0) run_ids = [r.id for r in collector.runs] @@ -1186,16 +1181,13 @@ async def test_nexus_direct_traceable_without_temporal_runs( assert result == "response to: nexus-input" - hierarchy = dump_runs(collector) # @traceable runs from inside the nexus handler should be collected # via the interceptor's tracing_context setup. expected = [ "nexus_direct_traceable", " inner_llm_call", ] - assert hierarchy == expected, ( - f"Hierarchy mismatch.\nExpected:\n{expected}\nActual:\n{hierarchy}" - ) + assert_trace_hierarchy(build_trace_trees(collector), expected) # --------------------------------------------------------------------------- @@ -1281,8 +1273,10 @@ async def test_temporal_prefixed_query_not_traced( assert await handle.result() == "done" # Built-in queries should be absent; only user query and signal remain. - traces = dump_traces(collector) - assert traces == [ - ["HandleQuery:my_query"], - ["HandleSignal:complete"], - ], f"Unexpected traces: {traces}" + assert_trace_hierarchy( + build_trace_trees(collector), + [ + "HandleQuery:my_query", + "HandleSignal:complete", + ], + ) diff --git a/tests/contrib/langsmith/test_plugin.py b/tests/contrib/langsmith/test_plugin.py index 0dad5566f..6e3cb2e86 100644 --- a/tests/contrib/langsmith/test_plugin.py +++ b/tests/contrib/langsmith/test_plugin.py @@ -12,7 +12,10 @@ from temporalio.client import Client, WorkflowHandle from temporalio.contrib.langsmith import LangSmithInterceptor, LangSmithPlugin from temporalio.testing import WorkflowEnvironment -from tests.contrib.langsmith.conftest import dump_traces, find_traces +from tests.contrib.langsmith.conftest import ( + build_trace_trees, + find_trace_trees, +) from tests.contrib.langsmith.test_integration import ( ComprehensiveWorkflow, NexusService, @@ -24,6 +27,7 @@ ) from tests.helpers import new_worker from tests.helpers.nexus import make_nexus_endpoint_name +from tests.helpers.trace import assert_trace_hierarchy class TestPluginConstruction: @@ -111,12 +115,12 @@ async def user_pipeline() -> WorkflowHandle[Any, Any]: assert result == "comprehensive-done" - traces = dump_traces(collector) + trace_trees = build_trace_trees(collector) # user_pipeline trace: StartWorkflow + full workflow execution tree - workflow_traces = find_traces(traces, "user_pipeline") - assert len(workflow_traces) == 1 - assert workflow_traces[0] == [ + workflow_trace_trees = find_trace_trees(trace_trees, "user_pipeline") + assert len(workflow_trace_trees) == 1 + expected_workflow = [ "user_pipeline", " StartWorkflow:ComprehensiveWorkflow", " RunWorkflow:ComprehensiveWorkflow", @@ -178,46 +182,64 @@ async def user_pipeline() -> WorkflowHandle[Any, Any]: " outer_chain", " inner_llm_call", ] + assert_trace_hierarchy(workflow_trace_trees, expected_workflow) # poll_query trace (separate root, variable number of iterations) - poll_traces = find_traces(traces, "poll_query") - assert len(poll_traces) == 1 - poll = poll_traces[0] - assert poll[0] == "poll_query" - poll_children = poll[1:] - for i in range(0, len(poll_children), 2): - assert poll_children[i] == " QueryWorkflow:is_waiting_for_signal" - assert poll_children[i + 1] == " HandleQuery:is_waiting_for_signal" + poll_trace_trees = find_trace_trees(trace_trees, "poll_query") + assert len(poll_trace_trees) == 1 + poll = poll_trace_trees[0] + assert poll.name == "poll_query" + poll_children = poll.children + for poll_child in poll_children: + assert poll_child.name == "QueryWorkflow:is_waiting_for_signal" + assert [child.name for child in poll_child.children] == [ + "HandleQuery:is_waiting_for_signal" + ] + assert not poll_child.children[0].children # Each remaining operation is its own root trace - query_traces = find_traces(traces, "QueryWorkflow:my_query") - assert len(query_traces) == 1 - assert query_traces[0] == [ - "QueryWorkflow:my_query", - " HandleQuery:my_query", - ] + query_trace_trees = find_trace_trees(trace_trees, "QueryWorkflow:my_query") + assert len(query_trace_trees) == 1 + assert_trace_hierarchy( + query_trace_trees, + [ + "QueryWorkflow:my_query", + " HandleQuery:my_query", + ], + ) - signal_traces = find_traces(traces, "SignalWorkflow:my_signal") - assert len(signal_traces) == 1 - assert signal_traces[0] == [ - "SignalWorkflow:my_signal", - " HandleSignal:my_signal", - ] + signal_trace_trees = find_trace_trees(trace_trees, "SignalWorkflow:my_signal") + assert len(signal_trace_trees) == 1 + assert_trace_hierarchy( + signal_trace_trees, + [ + "SignalWorkflow:my_signal", + " HandleSignal:my_signal", + ], + ) - update_traces = find_traces(traces, "StartWorkflowUpdate:my_update") - assert len(update_traces) == 1 - assert update_traces[0] == [ - "StartWorkflowUpdate:my_update", - " ValidateUpdate:my_update", - " HandleUpdate:my_update", - ] + update_trace_trees = find_trace_trees( + trace_trees, "StartWorkflowUpdate:my_update" + ) + assert len(update_trace_trees) == 1 + assert_trace_hierarchy( + update_trace_trees, + [ + "StartWorkflowUpdate:my_update", + " ValidateUpdate:my_update", + " HandleUpdate:my_update", + ], + ) # Update without a validator — no ValidateUpdate trace - unvalidated_traces = find_traces( - traces, "StartWorkflowUpdate:my_unvalidated_update" + unvalidated_trace_trees = find_trace_trees( + trace_trees, "StartWorkflowUpdate:my_unvalidated_update" + ) + assert len(unvalidated_trace_trees) == 1 + assert_trace_hierarchy( + unvalidated_trace_trees, + [ + "StartWorkflowUpdate:my_unvalidated_update", + " HandleUpdate:my_unvalidated_update", + ], ) - assert len(unvalidated_traces) == 1 - assert unvalidated_traces[0] == [ - "StartWorkflowUpdate:my_unvalidated_update", - " HandleUpdate:my_unvalidated_update", - ] diff --git a/tests/helpers/trace.py b/tests/helpers/trace.py new file mode 100644 index 000000000..913bd27da --- /dev/null +++ b/tests/helpers/trace.py @@ -0,0 +1,111 @@ +"""Helpers for asserting indented trace hierarchies.""" + +from __future__ import annotations + +from collections.abc import Sequence +from dataclasses import dataclass, field + + +@dataclass +class TraceNode: + name: str + children: list[TraceNode] = field(default_factory=list) + + +def format_trace_hierarchy(roots: Sequence[TraceNode]) -> list[str]: + """Render a trace forest as indented lines.""" + lines: list[str] = [] + + def render(node: TraceNode, depth: int) -> None: + lines.append(" " * depth + node.name) + for child in node.children: + render(child, depth + 1) + + for root in roots: + render(root, 0) + return lines + + +def assert_trace_hierarchy( + actual: Sequence[TraceNode], expected: Sequence[str] +) -> None: + """Assert a trace hierarchy, allowing matching Start/Run siblings to swap. + + Activity execution can begin before the asynchronously published Start span + reaches an in-memory exporter. The two spans retain the same parent, so this + accepts only that sibling transposition and preserves all other ordering. + """ + actual_tree = TraceNode("", list(actual)) + expected_tree = _parse_trace(expected) + assert _nodes_match(actual_tree, expected_tree), ( + "Trace hierarchy differed.\n" + f"Actual:\n{chr(10).join(format_trace_hierarchy(actual))}\n" + f"Expected:\n{chr(10).join(expected)}" + ) + + +def _parse_trace(trace: Sequence[str]) -> TraceNode: + root = TraceNode("") + stack: list[tuple[int, TraceNode]] = [(-1, root)] + for line in trace: + name = line.lstrip() + indent = len(line) - len(name) + assert name and indent % 2 == 0, f"Invalid trace line: {line!r}" + depth = indent // 2 + while stack[-1][0] >= depth: + stack.pop() + assert depth == stack[-1][0] + 1, f"Invalid trace nesting: {line!r}" + node = TraceNode(name) + stack[-1][1].children.append(node) + stack.append((depth, node)) + return root + + +def _nodes_match(actual: TraceNode, expected: TraceNode) -> bool: + if actual.name != expected.name or len(actual.children) != len(expected.children): + return False + + index = 0 + while index < len(actual.children): + actual_child = actual.children[index] + expected_child = expected.children[index] + if _nodes_match(actual_child, expected_child): + index += 1 + continue + + if index + 1 == len(actual.children): + return False + actual_pair = actual.children[index : index + 2] + expected_pair = expected.children[index : index + 2] + if not _is_start_run_pair(*actual_pair) or not _is_start_run_pair( + *expected_pair + ): + return False + expected_by_name = {node.name: node for node in expected_pair} + if any(node.name not in expected_by_name for node in actual_pair): + return False + if not all( + _nodes_match(node, expected_by_name[node.name]) for node in actual_pair + ): + return False + index += 2 + + return True + + +def _is_start_run_pair(first: TraceNode, second: TraceNode) -> bool: + first_start = _start_run_suffix(first.name) + second_start = _start_run_suffix(second.name) + first_run = _run_suffix(first.name) + second_run = _run_suffix(second.name) + return (first_start is not None and first_start == second_run) or ( + second_start is not None and second_start == first_run + ) + + +def _start_run_suffix(name: str) -> str | None: + return name.removeprefix("Start") if name.startswith("Start") else None + + +def _run_suffix(name: str) -> str | None: + return name.removeprefix("Run") if name.startswith("Run") else None From 65a03263b0f38e3569cce20fc5eb573647073a44 Mon Sep 17 00:00:00 2001 From: Tim Conley Date: Mon, 10 Aug 2026 10:22:39 -0700 Subject: [PATCH 215/226] Test LangSmith built-in query filtering (#1727) --- tests/contrib/langsmith/test_integration.py | 2 - tests/contrib/langsmith/test_interceptor.py | 44 +++++++++++++++++++++ 2 files changed, 44 insertions(+), 2 deletions(-) diff --git a/tests/contrib/langsmith/test_integration.py b/tests/contrib/langsmith/test_integration.py index bfffdb0a0..f48d9d6ac 100644 --- a/tests/contrib/langsmith/test_integration.py +++ b/tests/contrib/langsmith/test_integration.py @@ -1263,8 +1263,6 @@ async def test_temporal_prefixed_query_not_traced( # Built-in queries — should NOT be traced await handle.query("__temporal_workflow_metadata") - await handle.query("__stack_trace") - await handle.query("__enhanced_stack_trace") # User query — should be traced await handle.query(QueryFilteringWorkflow.my_query) diff --git a/tests/contrib/langsmith/test_interceptor.py b/tests/contrib/langsmith/test_interceptor.py index 45d86bc5f..4c18c3f9f 100644 --- a/tests/contrib/langsmith/test_interceptor.py +++ b/tests/contrib/langsmith/test_interceptor.py @@ -16,9 +16,11 @@ HEADER_KEY, _extract_context, _inject_context, + _LangSmithWorkflowInboundInterceptor, _maybe_run, _ReplaySafeRunTree, ) +from temporalio.worker import HandleQueryInput # --------------------------------------------------------------------------- # Helpers @@ -88,6 +90,48 @@ def _get_runtree_metadata(MockRunTree: MagicMock) -> dict[str, Any]: return kwargs.get("metadata", {}) +# =================================================================== +# TestBuiltinQueryFiltering +# =================================================================== + + +class _RecordingWorkflowInboundInterceptor: + def __init__(self) -> None: + self.queries: list[HandleQueryInput] = [] + + async def handle_query(self, input: HandleQueryInput) -> str: + self.queries.append(input) + return "forwarded" + + +class TestBuiltinQueryFiltering: + async def test_builtin_queries_bypass_tracing(self) -> None: + next_interceptor = _RecordingWorkflowInboundInterceptor() + interceptor = _LangSmithWorkflowInboundInterceptor( + next_interceptor # type: ignore[arg-type] + ) + + with patch.object(interceptor, "_workflow_maybe_run") as maybe_run: + for query in ( + "__temporal_workflow_metadata", + "__stack_trace", + "__enhanced_stack_trace", + ): + assert ( + await interceptor.handle_query( + HandleQueryInput(id="id", query=query, args=[], headers={}) + ) + == "forwarded" + ) + + assert [input.query for input in next_interceptor.queries] == [ + "__temporal_workflow_metadata", + "__stack_trace", + "__enhanced_stack_trace", + ] + maybe_run.assert_not_called() + + # =================================================================== # TestContextPropagation # =================================================================== From 3ac74808ba623b2e614fc6af42e9d4c02e271273 Mon Sep 17 00:00:00 2001 From: David Hyde Date: Mon, 10 Aug 2026 12:54:35 -0500 Subject: [PATCH 216/226] [AI-163] google_adk_agents: support ToolContext session state in activity_tool (#1683) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Support ToolContext session state in activity_tool via ToolContextSnapshot Activities wrapped with activity_tool could not access the ADK ToolContext: declaring a tool_context parameter put it in the LLM-facing tool schema and then failed at runtime trying to serialize the live ToolContext as an activity argument (#1470). An activity can now declare a parameter named tool_context annotated with the new ToolContextSnapshot dataclass. Exactly like a native ADK function tool's tool_context parameter, it is excluded from the tool schema (ADK reserves the name) and filled at invocation time — with a serializable snapshot of the live ToolContext (session state as a plain dict, plus the function-call id) taken workflow-side before the activity is scheduled. The live ToolContext never crosses the activity boundary. Annotating the parameter with an ADK context type raises an actionable error at wrap time instead of failing at serialization time. The snapshot is one-way by design: activities may run on different workers, so session-state modifications must happen workflow-side using information returned from the activity. Closes #1470 * Harden tool_context validation, close annotation-based injection bypass ADK detects the context parameter annotation-first across all parameters (find_context_parameter), falling back to the name 'tool_context', so the previous name-only validation missed cases where ADK would still inject the live, non-serializable context: - Reject an ADK context annotation on any parameter, not just 'tool_context' (e.g. 'ctx: ToolContext' previously passed wrap-time validation, then failed payload serialization at runtime — the exact failure mode from #1470 — and, when combined with a 'tool_context: ToolContextSnapshot' parameter, leaked that parameter into the LLM-facing tool schema as required). - Reject ToolContextSnapshot on a parameter not named 'tool_context' (ADK never injects it there, so it would leak into the tool schema). - Reject an unannotated 'tool_context' (public docs already required the annotation; without it the activity decoded the snapshot as a plain dict under Temporal but received a ToolContextSnapshot in local runs). - Route Optional[ToolContext] to the ADK-specific error message and render union annotations readably. Docs: state serializability/payload-size constraints under Temporal and read-only snapshot semantics (nested values may alias live session state in local runs); add missing timedelta import to the README snippet. Tests: new wrap-time acceptance/rejection matrix (Optional form, ADK context under any name, misplaced snapshot, unannotated), legacy (non-JSON-schema) declaration path, context-only tool schema, mixed-type session state round-trip, and an in-activity marker proving the snapshot crosses a real activity boundary; drop incorrect copyright header. Verified against google-adk 2.2.0 (locked) and 2.5.0. * README: note local-run nested state aliasing in the read-only caveat --- .../contrib/google_adk_agents/README.md | 47 +++ .../contrib/google_adk_agents/workflow.py | 196 +++++++++- .../test_adk_tool_context.py | 342 ++++++++++++++++++ 3 files changed, 584 insertions(+), 1 deletion(-) create mode 100644 tests/contrib/google_adk_agents/test_adk_tool_context.py diff --git a/temporalio/contrib/google_adk_agents/README.md b/temporalio/contrib/google_adk_agents/README.md index 92fd1cea7..5de5d6f03 100644 --- a/temporalio/contrib/google_adk_agents/README.md +++ b/temporalio/contrib/google_adk_agents/README.md @@ -170,6 +170,53 @@ worker = Worker( **Do not pass secrets, credentials, or API keys through `factory_argument`.** It is an activity argument, so it is recorded in workflow history and, without a payload codec, visible in the web UI. Resolve credentials worker-side inside the toolset factory instead. +### Reading Session State in Activity Tools + +ADK's live `ToolContext` holds non-serializable objects, so it cannot be an +activity argument. To read the serializable subset from an activity-backed +tool, declare a parameter named `tool_context` annotated with +`ToolContextSnapshot`: + +```python +from datetime import timedelta + +from temporalio import activity +from temporalio.contrib.google_adk_agents.workflow import ( + ToolContextSnapshot, + activity_tool, +) + + +@activity.defn +async def get_weather(query: str, tool_context: ToolContextSnapshot) -> dict: + db_url = tool_context.state.get("url", "") + ... + + +weather_tool = activity_tool(get_weather, start_to_close_timeout=timedelta(seconds=30)) +``` + +Exactly like a native ADK function tool's `tool_context` parameter, it is +excluded from the LLM-facing tool schema; at invocation the wrapper snapshots +the live `ToolContext` (session state as a plain dict, plus the function-call +id) and passes it to the activity. Annotating any parameter with a live ADK +context type raises `ValueError` at wrap time, since ADK would inject the +non-serializable context into it regardless of its name. + +When running under Temporal, the entire session state crosses the activity +boundary: every value in it must be serializable by the configured data +converter and the total size must fit within payload limits, even for keys +the tool never reads. Local ADK runs pass the snapshot in memory and have no +such constraint. + +The snapshot is one-way and should be treated as read-only: mutations inside +the activity do not propagate back to the session, because the activity may +run on a different worker (and in local ADK runs, where the snapshot is +passed in memory, nested state values may alias the live session state, so +mutating them can corrupt the session). To modify session state, return the +needed information from the activity and apply it in workflow-side code (for +example an ADK callback or a plain tool function). + ### Local ADK Runs The same agent definitions can also be exercised outside Temporal with diff --git a/temporalio/contrib/google_adk_agents/workflow.py b/temporalio/contrib/google_adk_agents/workflow.py index b1d150391..13bca4de3 100644 --- a/temporalio/contrib/google_adk_agents/workflow.py +++ b/temporalio/contrib/google_adk_agents/workflow.py @@ -2,11 +2,190 @@ import functools import inspect -from typing import Any, Callable +import types +import typing +from dataclasses import dataclass, field +from typing import Any, Callable, cast import temporalio.workflow from temporalio import workflow +_TOOL_CONTEXT_PARAM = "tool_context" + + +@dataclass(frozen=True) +class ToolContextSnapshot: + """Serializable snapshot of the ADK ``ToolContext`` for activity-backed tools. + + .. warning:: + This class is experimental and may change in future versions. + Use with caution in production environments. + + ADK's ``ToolContext`` holds live, non-serializable objects, so it cannot + cross the activity boundary: activity inputs are sent to the server and + may run on a different worker than the workflow. This snapshot carries the + serializable subset instead. + + Declare a parameter named ``tool_context`` annotated with this type (or + ``ToolContextSnapshot | None``) on an activity wrapped by + :func:`activity_tool`: + + .. code-block:: python + + @activity.defn + async def get_weather(query: str, tool_context: ToolContextSnapshot) -> dict: + db_url = tool_context.state.get("url", "") + ... + + Exactly like a native ADK function tool's ``tool_context`` parameter, it + is excluded from the LLM-facing tool schema and filled in at invocation + time — here with a snapshot taken from the live ``ToolContext`` before the + activity is scheduled. + + When running under Temporal, the entire session state crosses the + activity boundary: every value in it must be serializable by the + configured data converter and the total size must fit within payload + limits, even for keys the tool never reads. A non-serializable value + fails the workflow task when the activity is scheduled. Local ADK runs + pass the snapshot in memory and have no such constraint. + + The snapshot is one-way and should be treated as read-only: mutating it + inside the activity does not propagate back to the session (and in local + runs nested values may alias the live session state, so mutating them can + corrupt the session). To modify session state, return the needed + information from the activity and apply it in workflow-side code (for + example an ADK callback or a plain tool function). + + Attributes: + state: The session state visible to this tool call, as a plain dict. + function_call_id: The id of the function call being handled, when + available. + """ + + state: dict[str, Any] = field(default_factory=dict) + function_call_id: str | None = None + + +def _annotation_members(annotation: Any) -> tuple[Any, ...]: + """Returns a union annotation's members, or the annotation itself.""" + origin = typing.get_origin(annotation) + if origin is typing.Union or origin is types.UnionType: # pyright: ignore[reportDeprecated] + return typing.get_args(annotation) + return (annotation,) + + +def _annotation_display(members: tuple[Any, ...]) -> str: + """Renders annotation members for error messages.""" + return " | ".join( + "None" if member is type(None) else getattr(member, "__name__", str(member)) + for member in members + ) + + +def _adk_context_error( + activity_def: Callable, name: str, annotation_name: str +) -> ValueError: + """Builds the error for a parameter annotated with a live ADK context.""" + return ValueError( + f"Activity '{activity_def.__name__}' declares '{name}:" + f" {annotation_name}', but ADK context objects are not serializable" + " and cannot be activity arguments. Declare a parameter named" + " 'tool_context' annotated with ToolContextSnapshot instead to receive" + " the serializable subset (session state and function-call id)." + ) + + +def _validated_tool_context_parameter( + activity_def: Callable, parameter: inspect.Parameter, members: tuple[Any, ...] +) -> inspect.Parameter: + """Returns the ``tool_context`` parameter after validating its annotation. + + The parameter must be annotated with :class:`ToolContextSnapshot` or + ``ToolContextSnapshot | None``. + """ + if parameter.annotation is inspect.Parameter.empty: + raise ValueError( + f"Activity '{activity_def.__name__}' has an unannotated" + " 'tool_context' parameter. Annotate it with ToolContextSnapshot" + " to receive the serializable subset of the ADK tool context" + " (session state and function-call id)." + ) + non_none = [member for member in members if member is not type(None)] + if non_none == [ToolContextSnapshot]: + return parameter + annotation_name = _annotation_display(members) + if any( + getattr(member, "__module__", "").startswith("google.adk") + for member in non_none + ): + raise _adk_context_error(activity_def, _TOOL_CONTEXT_PARAM, annotation_name) + raise ValueError( + f"Activity '{activity_def.__name__}' has a 'tool_context' parameter" + f" annotated with {annotation_name}. The name 'tool_context' is" + " reserved by ADK for context injection; annotate the parameter with" + " ToolContextSnapshot to receive the serializable subset of the tool" + " context." + ) + + +def _tool_context_parameter(activity_def: Callable) -> inspect.Parameter | None: + """Validates context-related parameters and returns the ``tool_context`` one. + + ADK injects the live context into the first parameter annotated with an + ADK context type (regardless of name), or failing that into one named + ``tool_context``, and excludes that parameter from the LLM-facing tool + schema. Live context objects cannot cross the activity boundary, so the + only supported declaration is a parameter named ``tool_context`` annotated + with :class:`ToolContextSnapshot` (or ``ToolContextSnapshot | None``); + anything else ADK would treat as a context parameter is rejected at wrap + time, as is a misplaced ToolContextSnapshot annotation that would leak + into the tool schema. + """ + try: + hints = typing.get_type_hints(activity_def) + except Exception: + hints = {} + adk_context: type[Any] | None + try: + from google.adk.tools.tool_context import ToolContext + + adk_context = ToolContext + except ImportError: + adk_context = None + tool_context_parameter: inspect.Parameter | None = None + for name, parameter in inspect.signature(activity_def).parameters.items(): + members = _annotation_members(hints.get(name, parameter.annotation)) + if name == _TOOL_CONTEXT_PARAM: + tool_context_parameter = _validated_tool_context_parameter( + activity_def, parameter, members + ) + elif adk_context is not None and any( + member is adk_context for member in members + ): + raise _adk_context_error(activity_def, name, _annotation_display(members)) + elif any(member is ToolContextSnapshot for member in members): + raise ValueError( + f"Activity '{activity_def.__name__}' annotates parameter" + f" '{name}' with ToolContextSnapshot, but ADK only injects the" + " tool context into a parameter named 'tool_context'; under" + " any other name it would appear in the LLM-facing tool" + " schema. Rename the parameter to 'tool_context'." + ) + return tool_context_parameter + + +def _snapshot_tool_context(tool_context: Any) -> ToolContextSnapshot: + """Builds the serializable snapshot from a live ADK ``ToolContext``.""" + state: dict[str, Any] = {} + state_object = getattr(tool_context, "state", None) + if state_object is not None: + to_dict = getattr(state_object, "to_dict", None) + state = dict(cast(Any, to_dict() if callable(to_dict) else state_object)) + return ToolContextSnapshot( + state=state, + function_call_id=getattr(tool_context, "function_call_id", None), + ) + def activity_tool(activity_def: Callable, **kwargs: Any) -> Callable: """Decorator/Wrapper to wrap a Temporal Activity as an ADK Tool. @@ -17,10 +196,25 @@ def activity_tool(activity_def: Callable, **kwargs: Any) -> Callable: This ensures the activity's signature is preserved for ADK's tool schema generation while marking it as a tool that executes via 'workflow.execute_activity'. + + If the activity declares a parameter named ``tool_context``, it must be + annotated with :class:`ToolContextSnapshot` (or ``ToolContextSnapshot | + None``). ADK excludes the parameter from the tool schema and injects the + live ``ToolContext`` into the wrapper, which passes the activity a + serializable snapshot of it (session state and function-call id) in that + parameter's position. Annotating any parameter with a live ADK context + type raises ``ValueError`` at wrap time, since ADK would inject the + non-serializable context into it regardless of its name. """ + tool_context_param = _tool_context_parameter(activity_def) @functools.wraps(activity_def) async def wrapper(*args: Any, **kw: Any): + # ADK injects the live ToolContext by name; replace it with the + # serializable snapshot the activity actually declares. + if tool_context_param is not None and _TOOL_CONTEXT_PARAM in kw: + kw[_TOOL_CONTEXT_PARAM] = _snapshot_tool_context(kw[_TOOL_CONTEXT_PARAM]) + # Inspect signature to bind arguments sig = inspect.signature(activity_def) bound = sig.bind(*args, **kw) diff --git a/tests/contrib/google_adk_agents/test_adk_tool_context.py b/tests/contrib/google_adk_agents/test_adk_tool_context.py new file mode 100644 index 000000000..be5b8a891 --- /dev/null +++ b/tests/contrib/google_adk_agents/test_adk_tool_context.py @@ -0,0 +1,342 @@ +"""Tests for ToolContextSnapshot injection into activity-backed tools. + +Covers https://github.com/temporalio/sdk-python/issues/1470: activities +wrapped with activity_tool can read the serializable subset of the ADK +ToolContext (session state and function-call id) without the live, +non-serializable ToolContext ever crossing the activity boundary, and +without the parameter leaking into the LLM-facing tool schema. +""" + +import uuid +from collections.abc import AsyncGenerator +from datetime import timedelta +from typing import Any, Optional # pyright: ignore[reportDeprecated] + +import pytest +from google.adk import Agent +from google.adk.features import FeatureName, override_feature_enabled +from google.adk.models import BaseLlm, LLMRegistry +from google.adk.models.llm_request import LlmRequest +from google.adk.models.llm_response import LlmResponse +from google.adk.runners import InMemoryRunner +from google.adk.tools.function_tool import FunctionTool +from google.adk.tools.tool_context import ToolContext +from google.adk.utils.context_utils import Aclosing +from google.genai import types +from google.genai.types import Content, FunctionCall, Part + +from temporalio import activity, workflow +from temporalio.client import Client +from temporalio.contrib.google_adk_agents import GoogleAdkPlugin, TemporalModel +from temporalio.contrib.google_adk_agents.workflow import ( + ToolContextSnapshot, + activity_tool, +) +from temporalio.worker import Worker + +TASK_QUEUE = "adk-tool-context-task-queue" + +SESSION_STATE: dict[str, Any] = { + "db_url": "postgres://config", + "retries": 3, + "regions": {"primary": "us-east1", "replicas": ["eu-west1"]}, +} + + +@activity.defn +async def lookup_weather( + city: str, tool_context: ToolContextSnapshot, units: str = "celsius" +) -> str: + """Activity that reads tool configuration from session state. + + Mirrors the shape reported in issue #1470, with tool_context deliberately + in the middle of the parameter list to prove positional slotting. The + returned string also records whether the code ran inside a real activity, + so tests can tell the activity boundary was actually crossed (or not). + """ + db_url = tool_context.state.get("db_url", "") + retries = tool_context.state.get("retries", -1) + region = tool_context.state.get("regions", {}).get("primary", "") + has_function_call_id = "yes" if tool_context.function_call_id else "no" + in_act = "yes" if activity.in_activity() else "no" + return f"{city}|{units}|{db_url}|{retries}|{region}|fc={has_function_call_id}|act={in_act}" + + +def weather_agent(model_name: str) -> Agent: + return Agent( + name="state_agent", + model=TemporalModel(model_name), + tools=[ + activity_tool(lookup_weather, start_to_close_timeout=timedelta(seconds=30)) + ], + ) + + +class StateToolModel(BaseLlm): + """Scripted model: call lookup_weather once, then echo its response.""" + + async def generate_content_async( + self, llm_request: LlmRequest, stream: bool = False + ) -> AsyncGenerator[LlmResponse, None]: + tool_response = None + for content in llm_request.contents: + for part in content.parts or []: + if ( + part.function_response is not None + and part.function_response.name == "lookup_weather" + ): + tool_response = part.function_response + if tool_response is None: + yield LlmResponse( + content=Content( + role="model", + parts=[ + Part( + function_call=FunctionCall( + name="lookup_weather", args={"city": "NYC"} + ) + ) + ], + ) + ) + else: + yield LlmResponse( + content=Content( + role="model", + parts=[Part(text=f"done:{tool_response.response}")], + ) + ) + + @classmethod + def supported_models(cls) -> list[str]: + return ["state_tool_model"] + + +async def run_state_agent(model_name: str) -> str: + """Runs the agent against a session seeded with state; returns final text.""" + runner = InMemoryRunner(agent=weather_agent(model_name), app_name="test_app") + session = await runner.session_service.create_session( + app_name="test_app", + user_id="test", + state=SESSION_STATE, + ) + final_text = "" + async with Aclosing( + runner.run_async( + user_id="test", + session_id=session.id, + new_message=types.Content( + role="user", parts=[types.Part(text="weather in NYC?")] + ), + ) + ) as agen: + async for event in agen: + if event.content and event.content.parts and event.content.parts[0].text: + final_text = event.content.parts[0].text + return final_text + + +@workflow.defn +class StateToolWorkflow: + @workflow.run + async def run(self, model_name: str) -> str: + return await run_state_agent(model_name) + + +@pytest.mark.asyncio +async def test_activity_tool_receives_tool_context_snapshot(client: Client): + new_config = client.config() + new_config["plugins"] = [GoogleAdkPlugin()] + client = Client(**new_config) + + async with Worker( + client, + task_queue=TASK_QUEUE, + activities=[lookup_weather], + workflows=[StateToolWorkflow], + max_cached_workflows=0, + ): + LLMRegistry.register(StateToolModel) + result = await client.execute_workflow( + StateToolWorkflow.run, + "state_tool_model", + id=f"tool-context-{uuid.uuid4()}", + task_queue=TASK_QUEUE, + execution_timeout=timedelta(seconds=30), + ) + # The activity saw mixed-type session state (string, int, nested dict), + # the default parameter value, and a populated function-call id — none of + # which came from the LLM — and act=yes proves the snapshot crossed a + # real activity boundary rather than running inline in the workflow. + assert "NYC|celsius|postgres://config|3|us-east1|fc=yes|act=yes" in result + + +@pytest.mark.asyncio +async def test_activity_tool_snapshot_outside_workflow(): + """Local ADK runs (no Temporal) receive the same snapshot.""" + LLMRegistry.register(StateToolModel) + result = await run_state_agent("state_tool_model") + assert "NYC|celsius|postgres://config|3|us-east1|fc=yes|act=no" in result + + +def _declared_properties(tool: FunctionTool) -> dict[str, Any]: + """Property names in the LLM-facing declaration, across schema styles.""" + declaration = tool._get_declaration() + assert declaration is not None + if declaration.parameters_json_schema is not None: + return declaration.parameters_json_schema.get("properties", {}) + assert declaration.parameters is not None + return declaration.parameters.properties or {} + + +def test_tool_schema_excludes_tool_context(): + """The tool_context parameter never appears in the LLM-facing schema.""" + tool = FunctionTool( + func=activity_tool(lookup_weather, start_to_close_timeout=timedelta(seconds=30)) + ) + properties = _declared_properties(tool) + assert "city" in properties + assert "units" in properties + assert "tool_context" not in properties + + +def test_tool_schema_excludes_tool_context_legacy_declaration(): + """Exclusion also holds on the legacy (non-JSON-schema) declaration path.""" + override_feature_enabled(FeatureName.JSON_SCHEMA_FOR_FUNC_DECL, False) + try: + tool = FunctionTool( + func=activity_tool( + lookup_weather, start_to_close_timeout=timedelta(seconds=30) + ) + ) + declaration = tool._get_declaration() + assert declaration is not None + assert declaration.parameters is not None + properties = declaration.parameters.properties or {} + assert "city" in properties + assert "units" in properties + assert "tool_context" not in properties + finally: + # The flag is default-on across the supported google-adk range. + override_feature_enabled(FeatureName.JSON_SCHEMA_FOR_FUNC_DECL, True) + + +def test_tool_schema_context_only_parameter(): + """A tool whose only parameter is tool_context exposes no LLM arguments.""" + + @activity.defn + async def ctx_only_tool(tool_context: ToolContextSnapshot) -> str: + return str(tool_context.state) + + tool = FunctionTool( + func=activity_tool(ctx_only_tool, start_to_close_timeout=timedelta(seconds=30)) + ) + declaration = tool._get_declaration() + if declaration is not None: + json_properties = (declaration.parameters_json_schema or {}).get( + "properties", {} + ) + legacy_properties = ( + (declaration.parameters.properties or {}) if declaration.parameters else {} + ) + assert not json_properties + assert not legacy_properties + + +def test_activity_tool_accepts_optional_snapshot_annotation(): + """ToolContextSnapshot | None is accepted and still excluded from the schema.""" + + @activity.defn + async def optional_tool( + query: str, + tool_context: ToolContextSnapshot | None = None, # pyright: ignore[reportUnusedParameter] + ) -> str: + return query + + tool = FunctionTool( + func=activity_tool(optional_tool, start_to_close_timeout=timedelta(seconds=30)) + ) + properties = _declared_properties(tool) + assert set(properties) == {"query"} + + +def test_activity_tool_rejects_adk_tool_context_annotation(): + """Annotating with the live ADK ToolContext gives an actionable error.""" + + @activity.defn + async def bad_tool(query: str, tool_context: ToolContext) -> str: # pyright: ignore[reportUnusedParameter] + return query + + with pytest.raises(ValueError, match="ToolContextSnapshot"): + activity_tool(bad_tool, start_to_close_timeout=timedelta(seconds=30)) + + +def test_activity_tool_rejects_optional_adk_tool_context_annotation(): + """Optional[ToolContext] is rejected with the ADK-specific message.""" + + @activity.defn + async def optional_bad_tool( + query: str, + tool_context: Optional[ToolContext] = None, # pyright: ignore[reportUnusedParameter, reportDeprecated] + ) -> str: + return query + + with pytest.raises(ValueError, match="not serializable"): + activity_tool(optional_bad_tool, start_to_close_timeout=timedelta(seconds=30)) + + +def test_activity_tool_rejects_adk_context_under_any_name(): + """ADK injects into any param annotated with a context type, so all are rejected.""" + + @activity.defn + async def sneaky_tool(query: str, ctx: ToolContext) -> str: # pyright: ignore[reportUnusedParameter] + return query + + with pytest.raises(ValueError, match="not serializable"): + activity_tool(sneaky_tool, start_to_close_timeout=timedelta(seconds=30)) + + +def test_activity_tool_rejects_snapshot_under_other_name(): + """ToolContextSnapshot on a differently-named param would leak into the schema.""" + + @activity.defn + async def misnamed_tool(query: str, snap: ToolContextSnapshot) -> str: # pyright: ignore[reportUnusedParameter] + return query + + with pytest.raises(ValueError, match="named 'tool_context'"): + activity_tool(misnamed_tool, start_to_close_timeout=timedelta(seconds=30)) + + +def test_activity_tool_rejects_unannotated_tool_context(): + """The reserved name without an annotation gives an actionable error.""" + + @activity.defn + async def untyped_tool(query: str, tool_context) -> str: # type: ignore[no-untyped-def] # pyright: ignore[reportUnusedParameter, reportMissingParameterType] + return query + + with pytest.raises(ValueError, match="unannotated 'tool_context'"): + activity_tool(untyped_tool, start_to_close_timeout=timedelta(seconds=30)) + + +def test_activity_tool_rejects_other_tool_context_annotation(): + """The reserved name with an unrelated annotation gives an actionable error.""" + + @activity.defn + async def confused_tool(query: str, tool_context: dict[str, Any]) -> str: # pyright: ignore[reportUnusedParameter] + return query + + with pytest.raises(ValueError, match="reserved by ADK"): + activity_tool(confused_tool, start_to_close_timeout=timedelta(seconds=30)) + + +def test_activity_tool_without_tool_context_unchanged(): + """Activities without a tool_context parameter keep their exact schema.""" + + @activity.defn + async def plain_tool(query: str) -> str: + return query + + tool = FunctionTool( + func=activity_tool(plain_tool, start_to_close_timeout=timedelta(seconds=30)) + ) + assert set(_declared_properties(tool)) == {"query"} From 8d8f34628386f972b936d0471e7c3f8c5e155daf Mon Sep 17 00:00:00 2001 From: David Hyde Date: Mon, 10 Aug 2026 15:31:18 -0500 Subject: [PATCH 217/226] Add mcp dependency to google-adk extra (#1736) --- CHANGELOG.md | 6 ++++++ pyproject.toml | 2 +- uv.lock | 2 ++ 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 12cfe91fe..358bd9bb2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -39,6 +39,12 @@ to include examples, links to docs, or any other relevant information. ### Fixed +- The `google-adk` extra now depends on `mcp`, so fresh installs of + `temporalio[google-adk]` can import `temporalio.contrib.google_adk_agents` + without separately installing `mcp`. Previously the import failed with an + `ImportError` because `google.adk.tools.mcp_tool` only exports `McpToolset` + when `mcp` is installed. + ### Security ## [1.31.0] - 2026-07-29 diff --git a/pyproject.toml b/pyproject.toml index 2303bdf00..8e496e379 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -29,7 +29,7 @@ grpc = ["grpcio>=1.48.2,<2"] opentelemetry = ["opentelemetry-api>=1.11.1,<2", "opentelemetry-sdk>=1.11.1,<2"] pydantic = ["pydantic>=2.0.0,<3"] openai-agents = ["openai-agents>=0.17.5", "mcp>=1.9.4, <2"] -google-adk = ["google-adk>=2.2.0,<3"] +google-adk = ["google-adk>=2.2.0,<3", "mcp>=1.24,<2"] langgraph = ["langgraph>=1.1.0"] langsmith = ["langsmith>=0.7.34,<0.9"] lambda-worker-otel = [ diff --git a/uv.lock b/uv.lock index c825d5488..8a3afd1fe 100644 --- a/uv.lock +++ b/uv.lock @@ -4625,6 +4625,7 @@ aioboto3 = [ ] google-adk = [ { name = "google-adk" }, + { name = "mcp" }, ] google-genai = [ { name = "google-genai" }, @@ -4712,6 +4713,7 @@ requires-dist = [ { name = "grpcio", marker = "extra == 'grpc'", specifier = ">=1.48.2,<2" }, { name = "langgraph", marker = "extra == 'langgraph'", specifier = ">=1.1.0" }, { name = "langsmith", marker = "extra == 'langsmith'", specifier = ">=0.7.34,<0.9" }, + { name = "mcp", marker = "extra == 'google-adk'", specifier = ">=1.24,<2" }, { name = "mcp", marker = "extra == 'openai-agents'", specifier = ">=1.9.4,<2" }, { name = "nexus-rpc", specifier = "==1.4.0" }, { name = "openai-agents", marker = "extra == 'openai-agents'", specifier = ">=0.17.5" }, From b425e66180a697a29296e09e52898e1babd0ae98 Mon Sep 17 00:00:00 2001 From: David Hyde Date: Mon, 10 Aug 2026 21:04:35 -0500 Subject: [PATCH 218/226] contrib/google_adk_agents: rename activity_tool to activity_as_tool (#1735) BREAKING CHANGE: `temporalio.contrib.google_adk_agents.workflow.activity_tool` is renamed to `activity_as_tool`, with no compatibility alias. Every other Temporal plugin that wraps an activity as an agent tool names the helper `activity_as_tool`: openai_agents, strands (plus `activity_as_hook`), and google_genai. google_adk_agents was the only outlier at `activity_tool`. The divergence is also cross-language. sdk-go's plugin for the same framework already uses `ActivityAsTool`, with `ActivityToolOptions` for the options struct and `activityTool` for the private impl type -- the verb names the conversion, the noun names the result. Python used the noun for the verb. sdk-typescript uses `activityAsTool` in its openai-agents and strands plugins. Left alone, a Go user and a Python user reading Temporal's Google ADK guide see different names for the same primitive. No compatibility alias. The ADK integration is Pre-release at every level -- the docs page carries a prerelease banner, the 1.24.0 release notes list it under Pre-release, and the function docstring warns it is experimental -- and Temporal's published policy for that stage is "Experimental; API is subject to change". This matches how prior plugin renames landed (#1139 made `set_open_ai_agent_temporal_overrides` private, #947 privatized the openai_agents module layout), neither of which shipped an alias. Mechanical only. `**kwargs: Any` on this helper is still out of step with the siblings, which enumerate activity options explicitly or take an `ActivityConfig`, and the docstring's "Decorator/Wrapper" claim is wrong (`@activity_as_tool(...)` parameterized use fails). Both are left for a follow-up so this diff stays reviewable as a rename. Docs and samples PRs follow once this merges: temporalio/documentation (docs/develop/python/integrations/google-adk.mdx), samples-python (google_adk_agents/), and google/adk-docs (docs/integrations/temporal.md). --- .../contrib/google_adk_agents/README.md | 8 ++- .../contrib/google_adk_agents/workflow.py | 4 +- .../test_adk_tool_context.py | 58 +++++++++++-------- .../test_google_adk_agents.py | 18 +++--- 4 files changed, 50 insertions(+), 38 deletions(-) diff --git a/temporalio/contrib/google_adk_agents/README.md b/temporalio/contrib/google_adk_agents/README.md index 5de5d6f03..d1ba2133a 100644 --- a/temporalio/contrib/google_adk_agents/README.md +++ b/temporalio/contrib/google_adk_agents/README.md @@ -183,7 +183,7 @@ from datetime import timedelta from temporalio import activity from temporalio.contrib.google_adk_agents.workflow import ( ToolContextSnapshot, - activity_tool, + activity_as_tool, ) @@ -193,7 +193,9 @@ async def get_weather(query: str, tool_context: ToolContextSnapshot) -> dict: ... -weather_tool = activity_tool(get_weather, start_to_close_timeout=timedelta(seconds=30)) +weather_tool = activity_as_tool( + get_weather, start_to_close_timeout=timedelta(seconds=30) +) ``` Exactly like a native ADK function tool's `tool_context` parameter, it is @@ -222,7 +224,7 @@ example an ADK callback or a plain tool function). The same agent definitions can also be exercised outside Temporal with `adk run` or `adk web`. -- `TemporalModel` and `activity_tool(...)` work in local ADK runs without +- `TemporalModel` and `activity_as_tool(...)` work in local ADK runs without additional configuration. - If the agent uses `TemporalMcpToolSet`, define a shared toolset factory, register it with `TemporalMcpToolSetProvider(...)` for workflow runs, and diff --git a/temporalio/contrib/google_adk_agents/workflow.py b/temporalio/contrib/google_adk_agents/workflow.py index 13bca4de3..23b254123 100644 --- a/temporalio/contrib/google_adk_agents/workflow.py +++ b/temporalio/contrib/google_adk_agents/workflow.py @@ -28,7 +28,7 @@ class ToolContextSnapshot: Declare a parameter named ``tool_context`` annotated with this type (or ``ToolContextSnapshot | None``) on an activity wrapped by - :func:`activity_tool`: + :func:`activity_as_tool`: .. code-block:: python @@ -187,7 +187,7 @@ def _snapshot_tool_context(tool_context: Any) -> ToolContextSnapshot: ) -def activity_tool(activity_def: Callable, **kwargs: Any) -> Callable: +def activity_as_tool(activity_def: Callable, **kwargs: Any) -> Callable: """Decorator/Wrapper to wrap a Temporal Activity as an ADK Tool. .. warning:: diff --git a/tests/contrib/google_adk_agents/test_adk_tool_context.py b/tests/contrib/google_adk_agents/test_adk_tool_context.py index be5b8a891..2f5d340d8 100644 --- a/tests/contrib/google_adk_agents/test_adk_tool_context.py +++ b/tests/contrib/google_adk_agents/test_adk_tool_context.py @@ -1,7 +1,7 @@ """Tests for ToolContextSnapshot injection into activity-backed tools. Covers https://github.com/temporalio/sdk-python/issues/1470: activities -wrapped with activity_tool can read the serializable subset of the ADK +wrapped with activity_as_tool can read the serializable subset of the ADK ToolContext (session state and function-call id) without the live, non-serializable ToolContext ever crossing the activity boundary, and without the parameter leaking into the LLM-facing tool schema. @@ -30,7 +30,7 @@ from temporalio.contrib.google_adk_agents import GoogleAdkPlugin, TemporalModel from temporalio.contrib.google_adk_agents.workflow import ( ToolContextSnapshot, - activity_tool, + activity_as_tool, ) from temporalio.worker import Worker @@ -67,7 +67,9 @@ def weather_agent(model_name: str) -> Agent: name="state_agent", model=TemporalModel(model_name), tools=[ - activity_tool(lookup_weather, start_to_close_timeout=timedelta(seconds=30)) + activity_as_tool( + lookup_weather, start_to_close_timeout=timedelta(seconds=30) + ) ], ) @@ -144,7 +146,7 @@ async def run(self, model_name: str) -> str: @pytest.mark.asyncio -async def test_activity_tool_receives_tool_context_snapshot(client: Client): +async def test_activity_as_tool_receives_tool_context_snapshot(client: Client): new_config = client.config() new_config["plugins"] = [GoogleAdkPlugin()] client = Client(**new_config) @@ -172,7 +174,7 @@ async def test_activity_tool_receives_tool_context_snapshot(client: Client): @pytest.mark.asyncio -async def test_activity_tool_snapshot_outside_workflow(): +async def test_activity_as_tool_snapshot_outside_workflow(): """Local ADK runs (no Temporal) receive the same snapshot.""" LLMRegistry.register(StateToolModel) result = await run_state_agent("state_tool_model") @@ -192,7 +194,9 @@ def _declared_properties(tool: FunctionTool) -> dict[str, Any]: def test_tool_schema_excludes_tool_context(): """The tool_context parameter never appears in the LLM-facing schema.""" tool = FunctionTool( - func=activity_tool(lookup_weather, start_to_close_timeout=timedelta(seconds=30)) + func=activity_as_tool( + lookup_weather, start_to_close_timeout=timedelta(seconds=30) + ) ) properties = _declared_properties(tool) assert "city" in properties @@ -205,7 +209,7 @@ def test_tool_schema_excludes_tool_context_legacy_declaration(): override_feature_enabled(FeatureName.JSON_SCHEMA_FOR_FUNC_DECL, False) try: tool = FunctionTool( - func=activity_tool( + func=activity_as_tool( lookup_weather, start_to_close_timeout=timedelta(seconds=30) ) ) @@ -229,7 +233,9 @@ async def ctx_only_tool(tool_context: ToolContextSnapshot) -> str: return str(tool_context.state) tool = FunctionTool( - func=activity_tool(ctx_only_tool, start_to_close_timeout=timedelta(seconds=30)) + func=activity_as_tool( + ctx_only_tool, start_to_close_timeout=timedelta(seconds=30) + ) ) declaration = tool._get_declaration() if declaration is not None: @@ -243,7 +249,7 @@ async def ctx_only_tool(tool_context: ToolContextSnapshot) -> str: assert not legacy_properties -def test_activity_tool_accepts_optional_snapshot_annotation(): +def test_activity_as_tool_accepts_optional_snapshot_annotation(): """ToolContextSnapshot | None is accepted and still excluded from the schema.""" @activity.defn @@ -254,13 +260,15 @@ async def optional_tool( return query tool = FunctionTool( - func=activity_tool(optional_tool, start_to_close_timeout=timedelta(seconds=30)) + func=activity_as_tool( + optional_tool, start_to_close_timeout=timedelta(seconds=30) + ) ) properties = _declared_properties(tool) assert set(properties) == {"query"} -def test_activity_tool_rejects_adk_tool_context_annotation(): +def test_activity_as_tool_rejects_adk_tool_context_annotation(): """Annotating with the live ADK ToolContext gives an actionable error.""" @activity.defn @@ -268,10 +276,10 @@ async def bad_tool(query: str, tool_context: ToolContext) -> str: # pyright: ig return query with pytest.raises(ValueError, match="ToolContextSnapshot"): - activity_tool(bad_tool, start_to_close_timeout=timedelta(seconds=30)) + activity_as_tool(bad_tool, start_to_close_timeout=timedelta(seconds=30)) -def test_activity_tool_rejects_optional_adk_tool_context_annotation(): +def test_activity_as_tool_rejects_optional_adk_tool_context_annotation(): """Optional[ToolContext] is rejected with the ADK-specific message.""" @activity.defn @@ -282,10 +290,12 @@ async def optional_bad_tool( return query with pytest.raises(ValueError, match="not serializable"): - activity_tool(optional_bad_tool, start_to_close_timeout=timedelta(seconds=30)) + activity_as_tool( + optional_bad_tool, start_to_close_timeout=timedelta(seconds=30) + ) -def test_activity_tool_rejects_adk_context_under_any_name(): +def test_activity_as_tool_rejects_adk_context_under_any_name(): """ADK injects into any param annotated with a context type, so all are rejected.""" @activity.defn @@ -293,10 +303,10 @@ async def sneaky_tool(query: str, ctx: ToolContext) -> str: # pyright: ignore[r return query with pytest.raises(ValueError, match="not serializable"): - activity_tool(sneaky_tool, start_to_close_timeout=timedelta(seconds=30)) + activity_as_tool(sneaky_tool, start_to_close_timeout=timedelta(seconds=30)) -def test_activity_tool_rejects_snapshot_under_other_name(): +def test_activity_as_tool_rejects_snapshot_under_other_name(): """ToolContextSnapshot on a differently-named param would leak into the schema.""" @activity.defn @@ -304,10 +314,10 @@ async def misnamed_tool(query: str, snap: ToolContextSnapshot) -> str: # pyrigh return query with pytest.raises(ValueError, match="named 'tool_context'"): - activity_tool(misnamed_tool, start_to_close_timeout=timedelta(seconds=30)) + activity_as_tool(misnamed_tool, start_to_close_timeout=timedelta(seconds=30)) -def test_activity_tool_rejects_unannotated_tool_context(): +def test_activity_as_tool_rejects_unannotated_tool_context(): """The reserved name without an annotation gives an actionable error.""" @activity.defn @@ -315,10 +325,10 @@ async def untyped_tool(query: str, tool_context) -> str: # type: ignore[no-unty return query with pytest.raises(ValueError, match="unannotated 'tool_context'"): - activity_tool(untyped_tool, start_to_close_timeout=timedelta(seconds=30)) + activity_as_tool(untyped_tool, start_to_close_timeout=timedelta(seconds=30)) -def test_activity_tool_rejects_other_tool_context_annotation(): +def test_activity_as_tool_rejects_other_tool_context_annotation(): """The reserved name with an unrelated annotation gives an actionable error.""" @activity.defn @@ -326,10 +336,10 @@ async def confused_tool(query: str, tool_context: dict[str, Any]) -> str: # pyr return query with pytest.raises(ValueError, match="reserved by ADK"): - activity_tool(confused_tool, start_to_close_timeout=timedelta(seconds=30)) + activity_as_tool(confused_tool, start_to_close_timeout=timedelta(seconds=30)) -def test_activity_tool_without_tool_context_unchanged(): +def test_activity_as_tool_without_tool_context_unchanged(): """Activities without a tool_context parameter keep their exact schema.""" @activity.defn @@ -337,6 +347,6 @@ async def plain_tool(query: str) -> str: return query tool = FunctionTool( - func=activity_tool(plain_tool, start_to_close_timeout=timedelta(seconds=30)) + func=activity_as_tool(plain_tool, start_to_close_timeout=timedelta(seconds=30)) ) assert set(_declared_properties(tool)) == {"query"} diff --git a/tests/contrib/google_adk_agents/test_google_adk_agents.py b/tests/contrib/google_adk_agents/test_google_adk_agents.py index 7be7ec8c6..2a1cf6aa1 100644 --- a/tests/contrib/google_adk_agents/test_google_adk_agents.py +++ b/tests/contrib/google_adk_agents/test_google_adk_agents.py @@ -69,7 +69,7 @@ async def get_weather(city: str) -> str: # type: ignore[reportUnusedParameter] def weather_agent(model_name: str) -> Agent: # Wraps 'get_weather' activity as a Tool - weather_tool = temporalio.contrib.google_adk_agents.workflow.activity_tool( + weather_tool = temporalio.contrib.google_adk_agents.workflow.activity_as_tool( get_weather, start_to_close_timeout=timedelta(seconds=60) ) @@ -700,7 +700,7 @@ def test_summary_and_summary_fn_raises(): @pytest.mark.asyncio async def test_agent_outside_workflow(): - """Test that an agent using TemporalModel and activity_tool works outside a Temporal workflow.""" + """Test that an agent using TemporalModel and activity_as_tool works outside a Temporal workflow.""" LLMRegistry.register(WeatherModel) agent = weather_agent("weather_model") @@ -827,13 +827,13 @@ async def run(self, prompt: str, model_name: str) -> str: name="complex_input_agent", model=TemporalModel(model_name), tools=[ - temporalio.contrib.google_adk_agents.workflow.activity_tool( + temporalio.contrib.google_adk_agents.workflow.activity_as_tool( book_trip, start_to_close_timeout=timedelta(seconds=60) ), - temporalio.contrib.google_adk_agents.workflow.activity_tool( + temporalio.contrib.google_adk_agents.workflow.activity_as_tool( summarize_payload, start_to_close_timeout=timedelta(seconds=60) ), - temporalio.contrib.google_adk_agents.workflow.activity_tool( + temporalio.contrib.google_adk_agents.workflow.activity_as_tool( method_holder.annotate_trip, start_to_close_timeout=timedelta(seconds=60), ), @@ -934,7 +934,7 @@ def supported_models(cls) -> list[str]: @pytest.mark.asyncio -async def test_activity_tool_supports_complex_inputs_via_adk(client: Client): +async def test_activity_as_tool_supports_complex_inputs_via_adk(client: Client): new_config = client.config() new_config["plugins"] = [GoogleAdkPlugin()] client = Client(**new_config) @@ -1122,8 +1122,8 @@ def test_explicitly_set_none_preserved() -> None: assert serialized["cache_config"] is None -def test_activity_tool_preserves_metadata() -> None: - """activity_tool wrapper preserves the original function's metadata. +def test_activity_as_tool_preserves_metadata() -> None: + """activity_as_tool wrapper preserves the original function's metadata. This ensures ADK's tool schema generation can inspect __annotations__ and __module__ on the wrapper, which are needed by @@ -1135,7 +1135,7 @@ async def my_activity(city: str, count: int = 1) -> str: """Get info for a city.""" return f"{city}: {count}" - tool = temporalio.contrib.google_adk_agents.workflow.activity_tool( + tool = temporalio.contrib.google_adk_agents.workflow.activity_as_tool( my_activity, start_to_close_timeout=timedelta(seconds=30) ) From c5baec9164d940dacda0a7ef8f96a53cdff2f8e7 Mon Sep 17 00:00:00 2001 From: David Hyde Date: Tue, 11 Aug 2026 12:04:21 -0500 Subject: [PATCH 219/226] Accept dict run_config in openai_agents Temporal runner (#1739) --- CHANGELOG.md | 3 + .../contrib/openai_agents/_openai_runner.py | 27 +++++- tests/contrib/openai_agents/test_openai.py | 90 ++++++++++++++++++- 3 files changed, 114 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 358bd9bb2..d146f045b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -44,6 +44,9 @@ to include examples, links to docs, or any other relevant information. without separately installing `mcp`. Previously the import failed with an `ImportError` because `google.adk.tools.mcp_tool` only exports `McpToolset` when `mcp` is installed. +- `temporalio.contrib.openai_agents` no longer crashes when a plain `dict` + is passed for `run_config`. (openai-agents >= 0.19.0 accepts `dict` run + configs at its public runner API) ### Security diff --git a/temporalio/contrib/openai_agents/_openai_runner.py b/temporalio/contrib/openai_agents/_openai_runner.py index 478217c8f..ea2e6e5df 100644 --- a/temporalio/contrib/openai_agents/_openai_runner.py +++ b/temporalio/contrib/openai_agents/_openai_runner.py @@ -99,6 +99,28 @@ def _has_sandbox_agent(agent: Agent[Any], seen: set[int] | None = None) -> bool: return False +def _coerce_run_config(value: object) -> RunConfig: + """openai-agents >= 0.19 also accepts a plain dict for ``run_config``. + + This function normalizes to a RunConfig instance. + """ + if isinstance(value, RunConfig): + return value + if not isinstance(value, dict): + raise TypeError( + f"run_config must be a RunConfig instance or a dict, got {type(value).__name__}" + ) + field_names = { + config_field.name + for config_field in dataclasses.fields(RunConfig) + if config_field.init + } + unknown_fields = sorted(str(name) for name in value if name not in field_names) + if unknown_fields: + raise TypeError(f"Unknown run_config settings: {', '.join(unknown_fields)}") + return RunConfig(**value) + + class TemporalOpenAIRunner(AgentRunner): """Temporal Runner for OpenAI agents. @@ -148,8 +170,9 @@ def _prepare_workflow_run( raise ValueError("Temporal workflows don't support SQLite sessions.") run_config = kwargs.get("run_config") - if run_config is None: - run_config = RunConfig() + run_config = ( + RunConfig() if run_config is None else _coerce_run_config(run_config) + ) if run_config.model and not isinstance(run_config.model, _TemporalModelStub): if not isinstance(run_config.model, str): diff --git a/tests/contrib/openai_agents/test_openai.py b/tests/contrib/openai_agents/test_openai.py index df12685f0..25597ee55 100644 --- a/tests/contrib/openai_agents/test_openai.py +++ b/tests/contrib/openai_agents/test_openai.py @@ -89,7 +89,10 @@ ) from temporalio.contrib.openai_agents._invoke_model_activity import _build_tool from temporalio.contrib.openai_agents._model_parameters import ModelSummaryProvider -from temporalio.contrib.openai_agents._openai_runner import _convert_agent +from temporalio.contrib.openai_agents._openai_runner import ( + _coerce_run_config, + _convert_agent, +) from temporalio.contrib.openai_agents._temporal_model_stub import ( _TemporalModelStub, ) @@ -2074,13 +2077,14 @@ def get_model(self, model_name: str | None) -> Model: return self._model +MULTIPLE_MODELS_FINAL_RESPONSE = "I'm here to help! Was there a specific task you needed assistance with regarding the storeroom?" + + def multiple_models_mock_model(): return TestModel.returning_responses( [ ResponseBuilders.tool_call("{}", "transfer_to_underling"), - ResponseBuilders.output_message( - "I'm here to help! Was there a specific task you needed assistance with regarding the storeroom?" - ), + ResponseBuilders.output_message(MULTIPLE_MODELS_FINAL_RESPONSE), ] ) @@ -2160,6 +2164,84 @@ async def test_run_config_models(client: Client): assert provider.model_names == {"gpt-4o"} +@workflow.defn +class DictRunConfigWorkflow: + """Same agents as MultipleModelWorkflow, but passes run_config as a plain + dict, which openai-agents >= 0.19 accepts at its public runner boundaries.""" + + @workflow.run + async def run(self) -> str: + underling = Agent[None]( + name="Underling", + instructions="You do all the work you are told.", + ) + + starting_agent = Agent[None]( + name="Lazy Assistant", + model="gpt-4o-mini", + instructions="You delegate all your work to another agent.", + handoffs=[underling], + ) + # Typed as Any so this also type-checks against openai-agents + # versions whose run_config annotation does not include dict. + dict_run_config: Any = {"model": "gpt-4o"} + result = await Runner.run( + starting_agent=starting_agent, + input="Have you cleaned the store room yet?", + run_config=dict_run_config, + ) + return result.final_output + + +async def test_dict_run_config_models(client: Client): + # A dict run_config must behave identically to the equivalent + # RunConfig(model="gpt-4o") in test_run_config_models above. + provider = AssertDifferentModelProvider(multiple_models_mock_model()) + async with AgentEnvironment( + model_params=ModelActivityParameters( + start_to_close_timeout=timedelta(seconds=120) + ), + model_provider=provider, + ) as env: + client = env.applied_on_client(client) + + async with new_worker( + client, + DictRunConfigWorkflow, + ) as worker: + workflow_handle = await client.start_workflow( + DictRunConfigWorkflow.run, + id=f"dict-run-config-model-{uuid.uuid4()}", + task_queue=worker.task_queue, + execution_timeout=timedelta(seconds=10), + ) + result = await workflow_handle.result() + + # Only the model from the runconfig override is used + assert provider.model_names == {"gpt-4o"} + assert result == MULTIPLE_MODELS_FINAL_RESPONSE + + +def test_coerce_run_config_validation(): + # Mirrors upstream agents' normalization: equivalent RunConfig out of a + # dict, and the same TypeErrors for invalid input. + coerced = _coerce_run_config({"model": "gpt-4o", "workflow_name": "wf"}) + assert isinstance(coerced, RunConfig) + assert coerced.model == "gpt-4o" + assert coerced.workflow_name == "wf" + + run_config = RunConfig(model="gpt-4o") + assert _coerce_run_config(run_config) is run_config + + with pytest.raises(TypeError, match="Unknown run_config settings: bogus_setting"): + _coerce_run_config({"model": "gpt-4o", "bogus_setting": True}) + + with pytest.raises( + TypeError, match="run_config must be a RunConfig instance or a dict, got int" + ): + _coerce_run_config(42) + + async def test_summary_provider(client: Client): class SummaryProvider(ModelSummaryProvider): def provide( From 2ec17b891c4a79d5800dd7a85350c85659ac6bea Mon Sep 17 00:00:00 2001 From: Tim Conley Date: Tue, 11 Aug 2026 11:39:23 -0700 Subject: [PATCH 220/226] docs: clarify AI contribution expectations (#1737) --- CONTRIBUTING.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index fcc672866..057901ff5 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -82,6 +82,12 @@ Avoid changes that make review harder without improving the contribution: Using AI tools while contributing is acceptable. You are responsible for the correctness, quality, and maintainability of everything you submit. +Contributors must fully understand the issue they are fixing and be able to explain +the proposed change. We expect that human understanding to be evident in pull +request responses and design discussions. If a contribution's interaction appears +entirely AI-driven, maintainers may close it: it does not provide a benefit over +maintainers using AI tooling themselves. + Thoroughly self-review AI-generated code and documentation before opening a pull request. Make sure it is correct, tested where appropriate, and consistent with the style and patterns of the codebase. From dabf0fa4b1fa38fc2d35065e6526cfccdd16d443 Mon Sep 17 00:00:00 2001 From: David Hyde Date: Tue, 11 Aug 2026 17:19:03 -0500 Subject: [PATCH 221/226] [AI-250] Add Deep Agents plugin (#1644) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Add Deep Agents contrib plugin temporalio.contrib.deepagents makes LangChain Deep Agents durable: unmodified create_deep_agent(...).ainvoke(...) code runs inside a workflow with plugins=[DeepAgentsPlugin()], routing every model turn, I/O tool call, and backend file/shell op through Temporal activities while the agent loop replays deterministically. Includes explicit per-tool workflow-vs-activity choice (activity_as_tool / tool_as_activity), TemporalBackend interception of the full backend protocol (sync + async + execute) with typed protocol-dataclass round-trip, continue-as-new state carry via run_deep_agent, streaming through workflow_streams, and native LangGraph interrupt/resume for human-in-the-loop. Ships as the temporalio[deepagents] extra (Python >= 3.11, matching deepagents' own floor). * Run backend protocol async defaults inline in workflows deepagents' BackendProtocol implements every async method's DEFAULT as asyncio.to_thread(sync_twin, ...), and neither StateBackend nor FilesystemBackend overrides any of them. The deterministic workflow event loop has no thread executor, so an agent's first built-in tool call against an unwrapped in-workflow backend — e.g. a model spontaneously invoking grep on the default state backend — failed the workflow task with NotImplementedError. Scripted-model tests never invoke built-ins on the default backend, so only a live-model run surfaced it. The plugin now patches the protocol's async defaults at worker start (same seam pattern as the resolve_model patch): inside a workflow the sync twin runs inline, which for state-only backends is deterministic and semantically identical to the upstream default; outside a workflow the upstream thread-hop default is untouched, as are subclasses that override an async method natively. * Return tool content so the node stamps the model's tool_call_id tool_as_activity returned the ToolMessage assembled inside the invoke_tool activity, whose tool_call_id is workflow-generated — the activity cannot know the id the model minted for the call. A real provider (Anthropic) rejects the next model turn with 400 "unexpected tool_use_id found in tool_result blocks" because the tool_result does not pair with any tool_use in the previous message. Offline fakes never validate the pairing, so only a live-model run surfaced it. The wrapper now returns the tool result CONTENT and lets the tool node stamp the model's own tool_call_id — the same path unwrapped tools take. activity_as_tool already returned raw content and is unaffected. The regression test records the fake model's second-turn request and asserts the tool_result rides under the scripted id. * Satisfy lint on 3.10 and basedpyright's warning gate Two CI-only failure classes the local scoped runs missed: - basedpyright fails on warnings repo-wide. Replace deprecated typing aliases (Mapping/Sequence/AsyncIterator/Iterator/List/Optional/Union) with collections.abc / PEP 604 forms, type the test fixtures the way the rest of the suite does, drop unused imports/params, and keep the interpreter-floor warning behind a module constant so newer runtimes do not narrow it into unreachable code. - Python 3.10 jobs cannot install deepagents (its floor is 3.11), so pyright cannot resolve those imports there. Runtime imports of deepagents/langchain in module code go through importlib (attribute access on ModuleType is dynamic; monkeypatch writes use setattr), and the deepagents test modules carry a file-level pyright directive alongside their existing importorskip guards. langchain-core stays statically imported — it resolves everywhere via the langgraph extra. * Fix pydoctor docstring syntax and 3.10 implicit-relative lint The API-docs build rejects an inline literal whose end-string is followed by a letter (``Serializable``s), and cannot resolve a :class: link to the package re-export, so both become plain prose / literals. On 3.10, where the real deepagents package cannot install, basedpyright resolves `from deepagents import ...` in tests/contrib/deepagents/ implicitly relative to the same-named test directory — extend the existing file-level directive; Python 3 has no implicit relative imports at runtime and collection is already importorskip-gated. * Bind deepagents test symbols via importorskip, not static imports The previous round's file-level directive used reportImplicitRelativeImport, which is basedpyright-only vocabulary — plain pyright hard-errors on unknown rules in pyright comments, taking every lint leg down. Rather than juggle two checkers' rule sets, drop the static `from deepagents import ...` lines from the tests entirely: symbols now bind off the module object pytest.importorskip already returns, which is dynamically typed for every checker, resolves nothing against the same-named test directory on 3.10, and lets the directives (and the now-moot protocol cast) be deleted outright. * Tighten worker-lifetime cleanup in the deepagents plugin - Await the cancelled heartbeat task so no pending task outlives an activity at event-loop shutdown. - Catch only ImportError when installing the create_deep_agent patches and include the original error in the warning; genuine installation bugs now surface at worker startup. - Keep the LangSmith aio_to_thread override installed for the process lifetime: the override slot is global and resetting it would strip a composed contrib.langsmith plugin's identical override. - Unregister a TemporalBackend's registry entry when the wrapper is garbage-collected, identity-guarded so a replay's re-registration of the same deterministic ref survives the evicted wrapper's cleanup. * Address review feedback: explicit factory, suggested CAN default, README overhaul - Add create_temporal_deep_agent(), a thin wrapper over create_deep_agent that scopes activity_options to one agent's model calls — the explicit, other-plugins-shaped construction path; drop-in vanilla create_deep_agent still works. - run_deep_agent now defaults continue_as_new_after=None to the server's is_continue_as_new_suggested() signal (accounts for history size, not just count); fixed thresholds remain available. - README: uv add install, guard-free imports (the plugin's sandbox passthrough already made imports_passed_through unnecessary — now proven by a test that imports deepagents bare in a workflow module), dedicated sections with snippets for tools/backends/HITL/streaming/options, and the plugin-ordering claim removed from the composition section. * Fix CI type-check failures on the Python floor and ceiling On 3.10 (deepagents not installed) pyright mis-resolves the static `from deepagents import create_deep_agent` inside the new factory and reports the symbol uncallable; use the module-attribute access pattern _model.py already relies on. On 3.14 and latest-deps, basedpyright gates on warnings and flagged the sandbox-passthrough test's deliberately-bare `import deepagents` as unused — the noqa only covered ruff; add the pyright ignore alongside it. * Fix remaining CI failures: Any-bind the factory, env-gate the suggest-CAN test Pyright on 3.10 (deepagents absent) resolves the module attribute itself as an uncallable object, so bind deepagents.create_deep_agent through an Any-typed local before calling. The suggested-mode continue-as-new e2e requires the local dev server's low suggestContinueAsNew threshold, so skip it under the time-skipping environment, following the existing env_type gating precedent in tests/worker/test_workflow.py. * Fix implicit-relative import resolution and a pydoctor link target basedpyright resolves a static `import deepagents` from inside this same-named package directory (and the same-named test directory) as implicitly relative when the real package is absent (Python 3.10 CI) — which is also what produced the earlier uncallable-object error: the name resolved to our own lazy __getattr__. Load the module through importlib.import_module in the factory, and rule-ignore the deliberately-bare import in the sandbox-passthrough test. Also replace the :class: link to the lazily re-exported TemporalModel with a plain literal — pydoctor cannot resolve lazy re-exports as link targets and the API-docs step gates on it. --- .github/CODEOWNERS | 2 + pyproject.toml | 9 + temporalio/contrib/deepagents/README.md | 339 ++++++++++++ temporalio/contrib/deepagents/__init__.py | 68 +++ temporalio/contrib/deepagents/_activity.py | 363 ++++++++++++ temporalio/contrib/deepagents/_model.py | 372 +++++++++++++ temporalio/contrib/deepagents/_plugin.py | 296 ++++++++++ temporalio/contrib/deepagents/_serde.py | 410 ++++++++++++++ temporalio/contrib/deepagents/_tools.py | 517 ++++++++++++++++++ temporalio/contrib/deepagents/py.typed | 0 temporalio/contrib/deepagents/testing.py | 141 +++++ temporalio/contrib/deepagents/workflow.py | 317 +++++++++++ tests/contrib/deepagents/__init__.py | 0 tests/contrib/deepagents/helpers.py | 16 + tests/contrib/deepagents/test_backends.py | 315 +++++++++++ tests/contrib/deepagents/test_checkpointer.py | 98 ++++ .../deepagents/test_continue_as_new.py | 167 ++++++ tests/contrib/deepagents/test_failures.py | 119 ++++ tests/contrib/deepagents/test_hitl.py | 139 +++++ .../contrib/deepagents/test_model_activity.py | 103 ++++ tests/contrib/deepagents/test_native_e2e.py | 141 +++++ tests/contrib/deepagents/test_readme.py | 36 ++ tests/contrib/deepagents/test_replay.py | 65 +++ .../deepagents/test_sandbox_passthrough.py | 89 +++ tests/contrib/deepagents/test_side_effects.py | 74 +++ tests/contrib/deepagents/test_streaming.py | 107 ++++ tests/contrib/deepagents/test_subagents.py | 90 +++ tests/contrib/deepagents/test_tools.py | 238 ++++++++ uv.lock | 124 ++++- 29 files changed, 4751 insertions(+), 4 deletions(-) create mode 100644 temporalio/contrib/deepagents/README.md create mode 100644 temporalio/contrib/deepagents/__init__.py create mode 100644 temporalio/contrib/deepagents/_activity.py create mode 100644 temporalio/contrib/deepagents/_model.py create mode 100644 temporalio/contrib/deepagents/_plugin.py create mode 100644 temporalio/contrib/deepagents/_serde.py create mode 100644 temporalio/contrib/deepagents/_tools.py create mode 100644 temporalio/contrib/deepagents/py.typed create mode 100644 temporalio/contrib/deepagents/testing.py create mode 100644 temporalio/contrib/deepagents/workflow.py create mode 100644 tests/contrib/deepagents/__init__.py create mode 100644 tests/contrib/deepagents/helpers.py create mode 100644 tests/contrib/deepagents/test_backends.py create mode 100644 tests/contrib/deepagents/test_checkpointer.py create mode 100644 tests/contrib/deepagents/test_continue_as_new.py create mode 100644 tests/contrib/deepagents/test_failures.py create mode 100644 tests/contrib/deepagents/test_hitl.py create mode 100644 tests/contrib/deepagents/test_model_activity.py create mode 100644 tests/contrib/deepagents/test_native_e2e.py create mode 100644 tests/contrib/deepagents/test_readme.py create mode 100644 tests/contrib/deepagents/test_replay.py create mode 100644 tests/contrib/deepagents/test_sandbox_passthrough.py create mode 100644 tests/contrib/deepagents/test_side_effects.py create mode 100644 tests/contrib/deepagents/test_streaming.py create mode 100644 tests/contrib/deepagents/test_subagents.py create mode 100644 tests/contrib/deepagents/test_tools.py diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 2c01cc259..7a5c2ab46 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -10,6 +10,7 @@ # other than the SDK team. For each one, we add the owning team, # as well as @temporalio/sdk, so the SDK team can continue to # manage repo-wide concerns. +/temporalio/contrib/deepagents/ @temporalio/ai-sdk @temporalio/sdk /temporalio/contrib/google_adk_agents/ @temporalio/ai-sdk @temporalio/sdk /temporalio/contrib/google_genai/ @temporalio/ai-sdk @temporalio/sdk /temporalio/contrib/langgraph/ @temporalio/ai-sdk @temporalio/sdk @@ -17,6 +18,7 @@ /temporalio/contrib/openai_agents/ @temporalio/ai-sdk @temporalio/sdk /temporalio/contrib/strands/ @temporalio/ai-sdk @temporalio/sdk /temporalio/contrib/workflow_streams/ @temporalio/ai-sdk @temporalio/sdk +/tests/contrib/deepagents/ @temporalio/ai-sdk @temporalio/sdk /tests/contrib/google_adk_agents/ @temporalio/ai-sdk @temporalio/sdk /tests/contrib/google_genai/ @temporalio/ai-sdk @temporalio/sdk /tests/contrib/langgraph/ @temporalio/ai-sdk @temporalio/sdk diff --git a/pyproject.toml b/pyproject.toml index 8e496e379..ab9f2638e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -32,6 +32,11 @@ openai-agents = ["openai-agents>=0.17.5", "mcp>=1.9.4, <2"] google-adk = ["google-adk>=2.2.0,<3", "mcp>=1.24,<2"] langgraph = ["langgraph>=1.1.0"] langsmith = ["langsmith>=0.7.34,<0.9"] +deepagents = [ + "deepagents>=0.6.12,<0.7; python_version >= '3.11'", + "langchain>=1.3.11,<2; python_version >= '3.11'", + "langchain-core>=1.4.8,<2; python_version >= '3.11'", +] lambda-worker-otel = [ "opentelemetry-api>=1.11.1,<2", "opentelemetry-sdk>=1.11.1,<2", @@ -82,6 +87,10 @@ dev = [ "moto[s3,server]>=5", "langgraph>=1.1.0", "langsmith>=0.7.34,<0.9", + "deepagents>=0.6.12,<0.7; python_version >= '3.11'", + "langchain>=1.3.11,<2; python_version >= '3.11'", + "langchain-core>=1.4.8,<2; python_version >= '3.11'", + "langchain-anthropic>=1.4.7; python_version >= '3.11'", "setuptools<82", "opentelemetry-exporter-otlp-proto-grpc>=1.11.1,<2", "opentelemetry-semantic-conventions>=0.40b0,<1", diff --git a/temporalio/contrib/deepagents/README.md b/temporalio/contrib/deepagents/README.md new file mode 100644 index 000000000..da9092978 --- /dev/null +++ b/temporalio/contrib/deepagents/README.md @@ -0,0 +1,339 @@ +# DeepAgentsPlugin — Temporal plugin for LangChain Deep Agents + +Make a [Deep Agent](https://github.com/langchain-ai/deepagents) durable by adding +one plugin. Build your agent with `create_temporal_deep_agent(...)` (or vanilla +`create_deep_agent(...)`) inside a `@workflow.defn`, add +`plugins=[DeepAgentsPlugin(...)]` to your Client (or Worker), and each LLM call +and each I/O tool call becomes a Temporal Activity — while the agent's control +loop runs, and deterministically replays, inside the Workflow. + +The code you already wrote against `deepagents` does not change: sub-agents, +planning/todo state, the filesystem middleware, human-in-the-loop interrupts, and +`agent.ainvoke(...)` all keep working. You get crash-durability, resumable +human-in-the-loop, and bounded history on top. + +> This package is experimental and may change in future versions. + +## Install + +```bash +uv add "temporalio[deepagents]" +``` + +(or `pip install "temporalio[deepagents]"`). Requires Python ≥ 3.11 (the same +floor `deepagents` sets). + +## Hello world + +```python +import asyncio +from datetime import timedelta + +from deepagents import create_deep_agent # no import guard needed; see below +from temporalio import workflow +from temporalio.client import Client +from temporalio.contrib.deepagents import ( + DeepAgentsPlugin, + create_temporal_deep_agent, +) +from temporalio.worker import Worker + + +@workflow.defn +class ResearchAgent: + @workflow.run + async def run(self, question: str) -> str: + # create_temporal_deep_agent wraps deepagents' create_deep_agent and + # scopes this agent's model-call activity options explicitly. + agent = create_temporal_deep_agent( + model="anthropic:claude-sonnet-4-5", + system_prompt="You are a careful research assistant.", + activity_options={"start_to_close_timeout": timedelta(minutes=5)}, + ) + result = await agent.ainvoke( + {"messages": [{"role": "user", "content": question}]} + ) + return result["messages"][-1].content + + +async def main() -> None: + # API keys live on the worker via the model provider, never in workflow + # inputs or history. The default provider is LangChain's init_chat_model. + plugin = DeepAgentsPlugin() + # Add the plugin on ONE side. The SDK propagates a Client plugin to any + # Worker built from that Client, so the Worker below inherits it. + client = await Client.connect("localhost:7233", plugins=[plugin]) + worker = Worker( + client, + task_queue="deepagents-task-queue", + workflows=[ResearchAgent], + ) + await worker.run() + + +if __name__ == "__main__": + asyncio.run(main()) +``` + +Two things worth noticing: + +- **No `workflow.unsafe.imports_passed_through()` guard.** The plugin + configures the workflow sandbox to pass the `deepagents` / LangChain import + tree through, so workflow files import them like any other module. +- **Vanilla `create_deep_agent(...)` also works.** The plugin substitutes the + durable model automatically whenever `model=` is a name string; use + `create_temporal_deep_agent` when you want to scope `activity_options` to one + agent instead of configuring plugin-wide defaults. + +## What this plugin gives you + +- **Drop-in durability.** `create_deep_agent(...).ainvoke(...)` runs unchanged + inside a Workflow. The loop replays deterministically; every nondeterministic + step (LLM, I/O tool, real filesystem/shell op) is an Activity. +- **One LLM call per Activity.** The Workflow ships only the model *name*; the + worker's `model_provider` builds the real client. Temporal owns retries and + timeouts (LLM-SDK retries are disabled). +- **Sub-agents inherit durability.** Because sub-agents inherit the parent's + `model` object and tools, substituting them once propagates to the whole agent + tree — no per-sub-agent wiring. +- Tools, real-I/O backends, human-in-the-loop, streaming, and continue-as-new + each get a section below. + +## Configuring activity options + +Per agent (recommended): `create_temporal_deep_agent(..., activity_options=...)` +as in Hello world above. Plugin-wide defaults use two keyed maps, because model +calls and tool calls have different timeout profiles: + +```python +from datetime import timedelta + +from temporalio.contrib.deepagents import DeepAgentsPlugin + +plugin = DeepAgentsPlugin( + # A single config, or a map keyed by MODEL name (thinking-mode models get + # longer timeouts than fast ones). + model_activity_options={"start_to_close_timeout": timedelta(minutes=5)}, + # A single config, or a map keyed by TOOL name. + tool_activity_options={"start_to_close_timeout": timedelta(seconds=30)}, +) +``` + +## Tools: the Workflow-vs-Activity choice, made explicit + +A tool that only mutates agent state can run in-workflow; a tool that does real +I/O must not. Both directions are one call: + +```python +from datetime import timedelta + +from langchain_core.tools import tool +from temporalio import activity +from temporalio.contrib.deepagents import activity_as_tool, tool_as_activity + + +@activity.defn +async def get_weather(city: str) -> str: + """Return the current weather for a city.""" + return f"It is sunny and 22C in {city}." + + +@tool +def web_search(query: str) -> str: + """Search the web for a query.""" + return f"Top result for {query!r}: ..." + + +# An existing Temporal activity, exposed to the agent as a tool: +weather_tool = activity_as_tool( + get_weather, start_to_close_timeout=timedelta(seconds=30) +) +# A LangChain tool whose body does I/O, moved into an activity: +search_tool = tool_as_activity( + web_search, start_to_close_timeout=timedelta(seconds=30) +) +``` + +Pass both to `create_temporal_deep_agent(..., tools=[weather_tool, +search_tool])`. An unwrapped, non-builtin tool runs in-workflow and the plugin +warns at construction, so the choice is never silent. Deep Agents' pure +built-ins (`write_todos`, state-backed file tools) stay in-workflow by design. + +## Durable file and shell backends + +Wrap a real-I/O backend (`FilesystemBackend` / `LocalShellBackend` / +`StoreBackend`) in `TemporalBackend` and the agent's *built-in* file and shell +tools execute as durable `deepagents.backend_op` Activities instead of touching +disk from workflow code: + +```python +from datetime import timedelta + +from deepagents.backends import FilesystemBackend +from temporalio import workflow +from temporalio.contrib.deepagents import TemporalBackend, create_temporal_deep_agent + + +@workflow.defn +class FilesystemAgent: + @workflow.run + async def run(self, root_dir: str) -> str: + backend = TemporalBackend( + FilesystemBackend(root_dir=root_dir, virtual_mode=True), + activity_options={"start_to_close_timeout": timedelta(seconds=30)}, + ) + agent = create_temporal_deep_agent( + model="anthropic:claude-sonnet-4-5", + backend=backend, + ) + result = await agent.ainvoke( + {"messages": [{"role": "user", "content": "Take notes as you work."}]} + ) + return result["messages"][-1].content +``` + +State-only backends (the default) need no wrapping — they are pure workflow +state, replayed deterministically. + +## Human-in-the-loop + +With `interrupt_on=...`, the agent pauses before a guarded tool and +`ainvoke(...)` returns the pending approval under the SDK-native +`__interrupt__` key — directly in your workflow. Expose it via a Query and +resume with an Update; no shim exception, the native LangGraph resume protocol +is used as-is: + +```python +from langgraph.checkpoint.memory import InMemorySaver +from langgraph.types import Command +from temporalio import workflow +from temporalio.contrib.deepagents import create_temporal_deep_agent + + +@workflow.defn +class ApprovalAgent: + def __init__(self) -> None: + self._pending: str | None = None + self._decision: str | None = None + + @workflow.run + async def run(self, request: str) -> str: + agent = create_temporal_deep_agent( + model="anthropic:claude-sonnet-4-5", + interrupt_on={"book_trip": True}, + checkpointer=InMemorySaver(), + ) + config = {"configurable": {"thread_id": workflow.info().workflow_id}} + result = await agent.ainvoke( + {"messages": [{"role": "user", "content": request}]}, config=config + ) + if result.get("__interrupt__"): + self._pending = str(result["__interrupt__"][0].value) + await workflow.wait_condition(lambda: self._decision is not None) + result = await agent.ainvoke( + Command(resume={"decisions": [{"type": self._decision}]}), + config=config, + ) + return result["messages"][-1].content + + @workflow.query + def pending_approval(self) -> str | None: + return self._pending + + @workflow.update + async def resume(self, decision: str) -> None: + self._decision = decision +``` + +A client polls `pending_approval`, shows it to a person, and calls the +`resume` update with `"approve"` / `"reject"`. + +## Streaming + +Set `streaming_topic=` on the plugin and model dispatch switches to a streaming +Activity that publishes chunk batches to a +`temporalio.contrib.workflow_streams` topic for live subscribers — while the +aggregated final message still returns to the workflow, so the durable result +is identical to the non-streaming path: + +```python +from temporalio.contrib.deepagents import DeepAgentsPlugin + +plugin = DeepAgentsPlugin(streaming_topic="agent-stream") +``` + +Subscribers read the topic with `WorkflowStreamClient`; each item is an +`AIMessageChunk` in `langchain_core.load.dumpd` form. + +## Continue-as-new: what carries and what does not + +Long conversations bloat workflow history. `run_deep_agent(agent, input, +state_snapshot=...)` snapshots state and continues into a fresh run when the +turn ends with pending todos and the server recommends continuing +(`workflow.info().is_continue_as_new_suggested()`, the default and recommended +mode — it accounts for history length *and* size): + +```python +from deepagents import create_deep_agent +from temporalio import workflow +from temporalio.contrib.deepagents import run_deep_agent + + +@workflow.defn +class LongResearchAgent: + @workflow.run + async def run(self, input: dict, state_snapshot: dict | None = None) -> dict: + agent = create_deep_agent(model="anthropic:claude-sonnet-4-5") + return await run_deep_agent( + agent, + input, + state_snapshot=state_snapshot, + ) +``` + +Pass `continue_as_new_after=N` instead to trigger on a fixed history-event +count. + +- **Carries forward:** the accumulated messages and the model/tool result cache + (so an LLM/tool call completed before the continue-as-new is *not* re-run + after it). Your `@workflow.run` must accept `state_snapshot=None` as shown. +- **Does not carry forward:** anything held only in an in-memory checkpointer's + own structures beyond the messages/todos snapshot. The default in-workflow + `InMemorySaver` is rehydrated for free by deterministic replay; a durable + checkpointer that does its own I/O is not replay-safe from inside a workflow, + and the plugin warns if you pass one — prefer the snapshot + continue-as-new + path above. + +## Runtime behavior + +While a worker built with this plugin is running, the plugin wraps +`deepagents.create_deep_agent` so a bare `model="provider:name"` string is +auto-routed through an Activity. The wrapper only rewrites arguments when called +*inside a workflow*, so importing `deepagents` on a plain client or activity +worker is unaffected, and the original function is restored when the worker +stops. If you would rather be explicit, use `create_temporal_deep_agent` or +pass `TemporalModel("provider:name")` yourself. + +## Composing with other plugins + +This plugin carries no tracing context of its own. For observability, compose it +with `temporalio.contrib.langsmith` or `temporalio.contrib.opentelemetry` — +registration order does not matter: + +```python +from temporalio.client import Client +from temporalio.contrib.deepagents import DeepAgentsPlugin + + +async def connect(): + return await Client.connect( + "localhost:7233", + plugins=[ + # LangSmithPlugin(), # or OpenTelemetryPlugin(), in either order + DeepAgentsPlugin(), + ], + ) +``` + +For agents built directly as LangGraph graphs (rather than a compiled Deep +Agent), see `temporalio.contrib.langgraph`. diff --git a/temporalio/contrib/deepagents/__init__.py b/temporalio/contrib/deepagents/__init__.py new file mode 100644 index 000000000..26febecb3 --- /dev/null +++ b/temporalio/contrib/deepagents/__init__.py @@ -0,0 +1,68 @@ +"""Temporal plugin for LangChain Deep Agents. + +Make an existing Deep Agent durable by adding one plugin: build your agent with +``create_deep_agent(...)`` inside a ``@workflow.defn`` and add +``plugins=[DeepAgentsPlugin(...)]`` to your Client or Worker. Each LLM call and +each I/O tool call becomes a Temporal activity, while the agent's control loop +runs — and deterministically replays — inside the workflow. + +.. warning:: + This package is experimental and may change in future versions. + +The public names are imported lazily so ``import temporalio.contrib.deepagents`` +succeeds before LangChain is installed; touching a name that needs LangChain +imports it on first access. +""" + +from __future__ import annotations + +from typing import TYPE_CHECKING + +__all__ = [ + "DeepAgentsPlugin", + "TemporalModel", + "TemporalBackend", + "activity_as_tool", + "tool_as_activity", + "run_deep_agent", + "create_temporal_deep_agent", + "DeepAgentsWorkflowError", +] + +if TYPE_CHECKING: + from temporalio.contrib.deepagents._model import TemporalModel + from temporalio.contrib.deepagents._plugin import DeepAgentsPlugin + from temporalio.contrib.deepagents._tools import ( + TemporalBackend, + activity_as_tool, + tool_as_activity, + ) + from temporalio.contrib.deepagents.workflow import ( + DeepAgentsWorkflowError, + create_temporal_deep_agent, + run_deep_agent, + ) + + +def __getattr__(name: str) -> object: + if name == "DeepAgentsPlugin": + from temporalio.contrib.deepagents._plugin import DeepAgentsPlugin + + return DeepAgentsPlugin + if name == "TemporalModel": + from temporalio.contrib.deepagents._model import TemporalModel + + return TemporalModel + if name in ("TemporalBackend", "activity_as_tool", "tool_as_activity"): + from temporalio.contrib.deepagents import _tools + + return getattr(_tools, name) + if name in ( + "DeepAgentsWorkflowError", + "run_deep_agent", + "create_temporal_deep_agent", + ): + from temporalio.contrib.deepagents import workflow + + return getattr(workflow, name) + raise AttributeError(f"module {__name__!r} has no attribute {name!r}") diff --git a/temporalio/contrib/deepagents/_activity.py b/temporalio/contrib/deepagents/_activity.py new file mode 100644 index 000000000..3c1501a42 --- /dev/null +++ b/temporalio/contrib/deepagents/_activity.py @@ -0,0 +1,363 @@ +"""The activities that carry every nondeterministic Deep Agents operation. + +The Deep Agents control loop runs *inside* the workflow; the operations that +must not run there — talking to an LLM, executing a tool that does real I/O, or +touching a real filesystem / shell backend — are moved out to these activities. + +Each activity is a method on :class:`DeepAgentActivities` so the worker-only +dependencies (the ``model_provider`` that builds real chat models from a name, +the streaming batch interval) can be captured on the instance rather than +smuggled through activity inputs. API keys therefore live on the worker, never +in a workflow input or in history. + +Every method: + +* takes a single serializable dataclass in and returns a single dataclass out + (LangChain objects travel as their ``dumpd`` JSON form via + :mod:`temporalio.contrib.deepagents._serde`); +* translates the LLM SDK's HTTP error into Temporal's retry contract so a 429 + honors the upstream ``retry-after`` instead of hammering it; +* heartbeats on a background task so a slow (thinking-mode / long-context) call + is not mistaken for a stuck worker. +""" + +from __future__ import annotations + +import asyncio +import dataclasses +import importlib +from datetime import timedelta +from functools import wraps +from typing import Any, Callable + +from temporalio import activity +from temporalio.contrib.deepagents import _serde +from temporalio.exceptions import ApplicationError + +# Activity type names. The workflow dispatches by these strings, so the +# in-workflow model / tool stubs never import the activity class itself. +INVOKE_MODEL = "deepagents.invoke_model" +INVOKE_MODEL_STREAMING = "deepagents.invoke_model_streaming" +INVOKE_TOOL = "deepagents.invoke_tool" +BACKEND_OP = "deepagents.backend_op" + + +# --------------------------------------------------------------------------- +# Boundary payloads +# --------------------------------------------------------------------------- + + +@dataclasses.dataclass +class ModelActivityInput: + """A single LLM request. + + ``model_name`` is resolved to a real model by the worker's + ``model_provider``; the workflow never ships credentials. + """ + + model_name: str + messages: list[Any] + """Messages in ``langchain_core.load.dumpd`` form.""" + tool_schemas: list[dict[str, Any]] = dataclasses.field(default_factory=list) + """OpenAI-format tool advertisements (name + description + argument schema).""" + bind_kwargs: dict[str, Any] = dataclasses.field(default_factory=dict) + config: dict[str, Any] = dataclasses.field(default_factory=dict) + """A stripped ``RunnableConfig`` (see :func:`_serde.strip_runnable_config`).""" + streaming_topic: str | None = None + + +@dataclasses.dataclass +class ModelActivityOutput: + """The model's reply. + + ``message`` is an ``AIMessage`` in ``dumpd`` form, carrying tool calls, + usage, and response metadata. + """ + + message: Any + + +@dataclasses.dataclass +class ToolActivityInput: + """One tool execution routed to an activity.""" + + tool_name: str + tool_call_id: str + args: dict[str, Any] + config: dict[str, Any] = dataclasses.field(default_factory=dict) + + +@dataclasses.dataclass +class ToolActivityOutput: + """A tool result as a ``ToolMessage`` in ``dumpd`` form.""" + + message: Any + + +@dataclasses.dataclass +class BackendOpInput: + """A single filesystem / shell / store operation for a wrapped backend.""" + + backend_ref: str + """Key identifying which registered backend to act on.""" + op: str + """Backend method name, e.g. ``ls`` / ``read_file`` / ``write_file`` / ``execute``.""" + args: list[Any] = dataclasses.field(default_factory=list) + kwargs: dict[str, Any] = dataclasses.field(default_factory=dict) + + +@dataclasses.dataclass +class BackendOpOutput: + """The backend operation's return value. + + Deepagents protocol dataclasses (``WriteResult`` / ``ReadResult`` / …) + ride in the tagged form produced by ``_serde.dump_backend_result`` so the + in-workflow stub can rebuild the real type; plain JSON values pass + through unchanged. + """ + + result: Any + + +# --------------------------------------------------------------------------- +# Heartbeating + error translation +# --------------------------------------------------------------------------- + + +def _auto_heartbeater(fn: Callable) -> Callable: + """Heartbeat at half the configured ``heartbeat_timeout`` while ``fn`` runs. + + Long LLM calls (thinking mode, long context, streaming accumulation) can run + well past a scheduler's patience; without a heartbeat Temporal would cancel + them and surface a ``HeartbeatTimeoutError`` instead of the real problem. + """ + + @wraps(fn) + async def wrapped(*args: Any, **kwargs: Any) -> Any: + heartbeat_timeout = activity.info().heartbeat_timeout + beat_task: asyncio.Task | None = None + if heartbeat_timeout: + interval = heartbeat_timeout.total_seconds() / 2 + + async def beat() -> None: + while True: + activity.heartbeat() + await asyncio.sleep(interval) + + beat_task = asyncio.create_task(beat()) + try: + return await fn(*args, **kwargs) + finally: + if beat_task is not None: + beat_task.cancel() + # Let the cancellation land before returning so no pending task + # outlives the activity (a bare ``cancel()`` leaves the task to + # be destroyed while pending if the loop shuts down first). + # ``asyncio.wait`` never re-raises the task's CancelledError. + await asyncio.wait([beat_task]) + + return wrapped + + +def _translate_api_error(exc: Exception) -> ApplicationError | None: + """Map an LLM SDK HTTP error onto Temporal's retry contract. + + Works by duck typing so neither ``openai`` nor ``anthropic`` needs to be + imported here: both expose ``status_code`` and ``response.headers``. Returns + ``None`` when ``exc`` is not a recognizable HTTP status error, so the caller + can fall through to its generic handling. + """ + status = getattr(exc, "status_code", None) + if status is None: + return None + headers: dict[str, Any] = {} + response = getattr(exc, "response", None) + if response is not None: + headers = dict(getattr(response, "headers", {}) or {}) + # Case-insensitive header access. + lower = {str(k).lower(): v for k, v in headers.items()} + + retryable = status in (408, 409, 429) or 500 <= status < 600 + should_retry = lower.get("x-should-retry") + if should_retry == "false": + retryable = False + elif should_retry == "true": + retryable = True + + delay_ms = lower.get("retry-after-ms") + retry_after = lower.get("retry-after") + next_delay: timedelta | None = None + try: + if delay_ms is not None: + next_delay = timedelta(milliseconds=int(delay_ms)) + elif retry_after is not None: + next_delay = timedelta(seconds=int(retry_after)) + except (TypeError, ValueError): + next_delay = None + + return ApplicationError( + str(exc), + type=type(exc).__name__, + non_retryable=not retryable, + next_retry_delay=next_delay, + ) + + +# --------------------------------------------------------------------------- +# The activities +# --------------------------------------------------------------------------- + + +def _default_model_provider(model_name: str) -> Any: + """Build a chat model from a name string with LLM-SDK retries disabled. + + Temporal owns retries; the model client must not also retry, or a single + logical attempt fans out into nested retry storms that Temporal can neither + see nor bound. + """ + # importlib: `langchain` (unlike langchain-core) is absent on Python 3.10 + # environments where the deepagents extra cannot install; a static import + # here fails type-checking there. + init_chat_model = importlib.import_module("langchain.chat_models").init_chat_model + + return init_chat_model(model_name, max_retries=0) + + +class DeepAgentActivities: + """Holds the worker-side dependencies and exposes the four activities. + + An instance is created by ``DeepAgentsPlugin`` + and its bound methods are registered on the worker. + """ + + def __init__( + self, + *, + model_provider: Callable[[str], Any] | None = None, + streaming_batch_interval: timedelta = timedelta(milliseconds=100), + ) -> None: + """Store the worker-side model provider + streaming configuration.""" + self._model_provider = model_provider or _default_model_provider + self._streaming_batch_interval = streaming_batch_interval + + def _build_bound_model(self, input: ModelActivityInput) -> Any: + model = self._model_provider(input.model_name) + if input.bind_kwargs: + model = model.bind(**input.bind_kwargs) + if input.tool_schemas: + model = model.bind_tools(input.tool_schemas) + return model + + @activity.defn(name=INVOKE_MODEL) + @_auto_heartbeater + async def invoke_model(self, input: ModelActivityInput) -> ModelActivityOutput: + """Run exactly one LLM call and return the resulting ``AIMessage``.""" + messages = _serde.load_messages(input.messages) + config = _serde.rebuild_runnable_config(input.config) + model = self._build_bound_model(input) + try: + message = await model.ainvoke(messages, config=config) + except Exception as exc: + translated = _translate_api_error(exc) + if translated is not None: + activity.logger.warning( + "Model call failed with an HTTP status error", exc_info=True + ) + raise translated from exc + raise + return ModelActivityOutput(message=_serde.dump_object(message)) + + @activity.defn(name=INVOKE_MODEL_STREAMING) + @_auto_heartbeater + async def invoke_model_streaming( + self, input: ModelActivityInput + ) -> ModelActivityOutput: + """Stream one LLM call, publishing chunk batches to ``streaming_topic``. + + Token-level deltas are coalesced at ``streaming_batch_interval`` and + pushed to external subscribers via the shared workflow-streams topic; the + aggregated final ``AIMessage`` is returned to the workflow so the + durable result is identical to the non-streaming path. + """ + from temporalio.contrib.workflow_streams import WorkflowStreamClient + + messages = _serde.load_messages(input.messages) + config = _serde.rebuild_runnable_config(input.config) + model = self._build_bound_model(input) + + final: Any = None + try: + async with WorkflowStreamClient.from_within_activity( + batch_interval=self._streaming_batch_interval + ) as client: + topic = ( + client.topic(input.streaming_topic) + if input.streaming_topic + else None + ) + async for chunk in model.astream(messages, config=config): + if topic is not None: + topic.publish(_serde.dump_object(chunk)) + final = chunk if final is None else final + chunk + except Exception as exc: + translated = _translate_api_error(exc) + if translated is not None: + activity.logger.warning( + "Streaming model call failed with an HTTP status error", + exc_info=True, + ) + raise translated from exc + raise + return ModelActivityOutput(message=_serde.dump_object(final)) + + @activity.defn(name=INVOKE_TOOL) + @_auto_heartbeater + async def invoke_tool(self, input: ToolActivityInput) -> ToolActivityOutput: + """Execute one registered tool and return its ``ToolMessage``.""" + from temporalio.contrib.deepagents._tools import get_registered_tool + + tool = get_registered_tool(input.tool_name) + if tool is None: + raise ApplicationError( + f"Tool {input.tool_name!r} is not registered on this worker. " + f"Wrap it with tool_as_activity(...) or activity_as_tool(...).", + type="DeepAgentsUnknownTool", + non_retryable=True, + ) + config = _serde.rebuild_runnable_config(input.config) + tool_call = { + "name": input.tool_name, + "args": input.args, + "id": input.tool_call_id, + "type": "tool_call", + } + message = await tool.ainvoke(tool_call, config=config) + return ToolActivityOutput(message=_serde.dump_object(message)) + + @activity.defn(name=BACKEND_OP) + @_auto_heartbeater + async def backend_op(self, input: BackendOpInput) -> BackendOpOutput: + """Run one operation against a registered (real-I/O) backend.""" + from temporalio.contrib.deepagents._tools import registered_backends + + backend = registered_backends().get(input.backend_ref) + if backend is None: + raise ApplicationError( + f"Backend {input.backend_ref!r} is not registered on this worker.", + type="DeepAgentsUnknownBackend", + non_retryable=True, + ) + method = getattr(backend, input.op, None) + if method is None: + raise ApplicationError( + f"Backend {input.backend_ref!r} has no operation {input.op!r}.", + type="DeepAgentsUnknownBackendOp", + non_retryable=True, + ) + result = method(*input.args, **input.kwargs) + if asyncio.iscoroutine(result): + result = await result + # Protocol results are plain dataclasses whose attributes the + # middleware reads in-workflow — tag them so the stub can rebuild + # the real type instead of receiving a decayed dict. + return BackendOpOutput(result=_serde.dump_backend_result(result)) diff --git a/temporalio/contrib/deepagents/_model.py b/temporalio/contrib/deepagents/_model.py new file mode 100644 index 000000000..2d97f992d --- /dev/null +++ b/temporalio/contrib/deepagents/_model.py @@ -0,0 +1,372 @@ +"""The model seam: a chat model whose every call becomes a Temporal activity. + +:class:`TemporalModel` is a real ``BaseChatModel``. Placed anywhere Deep Agents +expects a model, it routes each generation through the ``deepagents.invoke_model`` +activity instead of calling the provider inline. Because Deep Agents' sub-agents +inherit the parent's ``model`` instance by default, substituting this one object +makes every model call in the whole agent tree durable — no middleware injection +that a sub-agent could silently miss. + +Two ways to get one: + +* explicit — the user writes ``TemporalModel("anthropic:claude-...")`` and hands + it to ``create_deep_agent(model=...)``; this is the public type users assert + against; +* implicit — while running inside a workflow, the plugin patches + ``create_deep_agent`` so a bare ``model="anthropic:..."`` string is wrapped + automatically (see :func:`install_model_patch`). + +Worker-wide dispatch defaults (activity options, streaming topic) live in +:class:`temporalio.contrib.deepagents._serde.Settings`, a module global set by +the plugin. They live in ``_serde`` (not here) so the plugin can configure them +without importing this module — which would drag LangChain into plugin +construction. This module is under ``temporalio``, which the workflow sandbox +passes through, so the object the workflow reads is the same one the plugin set. +""" + +from __future__ import annotations + +import importlib +from collections.abc import AsyncIterator, Iterator, Mapping, Sequence +from datetime import timedelta +from typing import Any + +from temporalio import workflow +from temporalio.contrib.deepagents import _activity, _serde + +with workflow.unsafe.imports_passed_through(): + from langchain_core.callbacks import ( + AsyncCallbackManagerForLLMRun, + CallbackManagerForLLMRun, + ) + from langchain_core.language_models import BaseChatModel + from langchain_core.messages import AIMessageChunk, BaseMessage + from langchain_core.outputs import ChatGeneration, ChatGenerationChunk, ChatResult + + +def _as_message_chunk(message: Any) -> Any: + """Re-shape a finished ``AIMessage`` as the ``AIMessageChunk`` a stream yields.""" + return AIMessageChunk( + content=getattr(message, "content", ""), + additional_kwargs=getattr(message, "additional_kwargs", {}) or {}, + response_metadata=getattr(message, "response_metadata", {}) or {}, + id=getattr(message, "id", None), + tool_calls=getattr(message, "tool_calls", []) or [], + usage_metadata=getattr(message, "usage_metadata", None), + ) + + +# --------------------------------------------------------------------------- +# Activity-option resolution (worker-wide defaults live in _serde.Settings) +# --------------------------------------------------------------------------- + + +_DEFAULT_MODEL_TIMEOUT = timedelta(minutes=5) + + +def _resolve_activity_options( + model_name: str, instance_options: Mapping[str, Any] | None +) -> dict[str, Any]: + """Merge worker defaults with a per-instance override into execute_activity kwargs.""" + opts: dict[str, Any] = {} + default = _serde.get_settings().model_activity_options + if isinstance(default, Mapping) and not _looks_like_activity_config(default): + # Mapping[model_name, ActivityConfig]: pick this model's entry. + chosen = default.get(model_name) + if isinstance(chosen, Mapping): + opts.update(chosen) + elif isinstance(default, Mapping): + opts.update(default) + if instance_options: + opts.update(instance_options) + opts.setdefault("start_to_close_timeout", _DEFAULT_MODEL_TIMEOUT) + return opts + + +def _looks_like_activity_config(m: Mapping[str, Any]) -> bool: + """A single ``ActivityConfig`` has known option keys; a per-model map does not.""" + known = { + "task_queue", + "schedule_to_close_timeout", + "schedule_to_start_timeout", + "start_to_close_timeout", + "heartbeat_timeout", + "retry_policy", + "cancellation_type", + "activity_id", + "versioning_intent", + "summary", + "priority", + } + return bool(m) and all(k in known for k in m) + + +# --------------------------------------------------------------------------- +# The model +# --------------------------------------------------------------------------- + + +class TemporalModel(BaseChatModel): + """A ``BaseChatModel`` that runs each generation as a Temporal activity. + + Args: + model: The provider model name resolved worker-side by the plugin's + ``model_provider`` (e.g. ``"anthropic:claude-sonnet-4-5"``). Only the + name crosses the workflow boundary; credentials stay on the worker. + activity_options: Optional per-model ``execute_activity`` overrides + (timeouts, retry policy). Falls back to the plugin's + ``model_activity_options``. + """ + + model: str + activity_options: dict[str, Any] | None = None + + # ``protected_namespaces=()`` silences pydantic's warning about the ``model`` + # field colliding with its ``model_`` namespace. + model_config = {"arbitrary_types_allowed": True, "protected_namespaces": ()} + + @property + def _llm_type(self) -> str: + return "temporal-deepagents" + + def bind_tools( + self, + tools: Sequence[Any], + *, + tool_choice: Any | None = None, + **kwargs: Any, + ) -> Any: + """Bind tools to the model the way LangChain's ``create_agent`` expects. + + ``BaseChatModel.bind_tools`` is abstract (raises ``NotImplementedError``), + but the agent factory calls ``model.bind_tools(tools, ...)`` on every model + node — so a durable model must implement it or the whole loop dies. The + tools are converted to their JSON schema *now* (at bind time) so the bound + object is serialization-safe, and carried as the ``tools`` kwarg that + :meth:`_build_input` already reads and forwards to the activity, where the + real provider model is what actually binds them. + """ + schemas = [ + t if isinstance(t, dict) else _serde.tool_to_schema(t) for t in tools + ] + if tool_choice is not None: + kwargs["tool_choice"] = tool_choice + return self.bind(tools=schemas, **kwargs) + + def _summary(self) -> str: + return f"invoke_model[{self.model}]" + + def _build_input( + self, + messages: Sequence[BaseMessage], + streaming_topic: str | None, + **kwargs: Any, + ) -> _activity.ModelActivityInput: + tools = kwargs.get("tools") or [] + tool_schemas = [ + t if isinstance(t, dict) else _serde.tool_to_schema(t) for t in tools + ] + bind_kwargs = { + k: v + for k, v in kwargs.items() + if k not in ("tools", "config", "run_manager", "stop", "callbacks") + and _serde._is_jsonish(v) + } + if kwargs.get("stop"): + bind_kwargs["stop"] = kwargs["stop"] + return _activity.ModelActivityInput( + model_name=self.model, + messages=_serde.dump_messages(messages), + tool_schemas=tool_schemas, + bind_kwargs=bind_kwargs, + config=_serde.strip_runnable_config(kwargs.get("config") or {}), + streaming_topic=streaming_topic, + ) + + def _generate( + self, + messages: list[BaseMessage], + stop: list[str] | None = None, + run_manager: CallbackManagerForLLMRun | None = None, + **kwargs: Any, + ) -> ChatResult: + raise NotImplementedError( + "TemporalModel is async-only inside a Temporal workflow. Drive the " + "agent with `await agent.ainvoke(...)` / `.astream(...)`, which uses " + "the async model path." + ) + + async def _agenerate( + self, + messages: list[BaseMessage], + stop: list[str] | None = None, + run_manager: AsyncCallbackManagerForLLMRun | None = None, + **kwargs: Any, + ) -> ChatResult: + from temporalio.contrib.deepagents.workflow import call_model + + activity_input = self._build_input(messages, None, stop=stop, **kwargs) + opts = _resolve_activity_options(self.model, self.activity_options) + output = await call_model( + _activity.INVOKE_MODEL, + activity_input, + summary=self._summary(), + **opts, + ) + message = _serde.load_object(output.message) + return ChatResult(generations=[ChatGeneration(message=message)]) + + async def _astream( + self, + messages: list[BaseMessage], + stop: list[str] | None = None, + run_manager: AsyncCallbackManagerForLLMRun | None = None, + **kwargs: Any, + ) -> AsyncIterator[ChatGenerationChunk]: + from temporalio.contrib.deepagents.workflow import call_model + + topic = _serde.get_settings().streaming_topic + opts = _resolve_activity_options(self.model, self.activity_options) + if topic: + activity_input = self._build_input(messages, topic, stop=stop, **kwargs) + output = await call_model( + _activity.INVOKE_MODEL_STREAMING, + activity_input, + summary=f"invoke_model_streaming[{self.model}]", + **opts, + ) + else: + # No topic configured: fall back to a single response-level chunk. + activity_input = self._build_input(messages, None, stop=stop, **kwargs) + output = await call_model( + _activity.INVOKE_MODEL, + activity_input, + summary=self._summary(), + **opts, + ) + message = _serde.load_object(output.message) + yield ChatGenerationChunk(message=_as_message_chunk(message)) + + def _stream( + self, + messages: list[BaseMessage], + stop: list[str] | None = None, + run_manager: CallbackManagerForLLMRun | None = None, + **kwargs: Any, + ) -> Iterator[ChatGenerationChunk]: + raise NotImplementedError( + "TemporalModel streaming is async-only; use `agent.astream(...)`." + ) + + +# --------------------------------------------------------------------------- +# create_deep_agent model patch (implicit wrapping) +# --------------------------------------------------------------------------- +# +# The durability seam is ``deepagents._models.resolve_model``, which +# ``create_deep_agent`` calls to turn a ``model=`` string (or instance) into a +# ``BaseChatModel`` — for both the top-level agent and every ``SubAgent`` +# (``graph.py`` lines 592 and 634). We patch it on the ``deepagents.graph`` +# module, where ``create_deep_agent``'s body resolves the ``resolve_model`` name +# at call time. +# +# Patching *this* seam (not ``deepagents.create_deep_agent``) is what makes the +# rewrite survive the user's import style. A user who writes the idiomatic +# ``from deepagents import create_deep_agent`` binds the *original* function +# object into their module; rebinding the ``deepagents.create_deep_agent`` +# attribute would never be seen by that already-bound reference, so string +# models would reach the real provider inside the workflow (a hang / non- +# determinism). ``create_deep_agent``'s body, by contrast, always looks up +# ``resolve_model`` in the ``deepagents.graph`` globals afresh on each call, so +# rebinding it there is observed no matter how the caller imported the factory. +# It also preserves ``_model_spec`` (the original string), which the factory +# reads *before* calling ``resolve_model`` for harness-profile lookup. +# +# ``create_deep_agent`` is still wrapped separately, best-effort, purely to fire +# the construction-time warnings that need the ``tools`` / ``checkpointer`` +# kwargs (those warnings are advisory and carry no durability weight). + +_original_create_deep_agent: Any = None +_original_resolve_model: Any = None + + +def _wrap_model_arg(model: Any) -> Any: + """Resolve a ``create_deep_agent`` model argument to a durable model. + + A name string becomes a :class:`TemporalModel`. A :class:`TemporalModel` + passes through. Any other live ``BaseChatModel`` instance is rejected at the + workflow boundary: it has no name the activity could rebuild from, so it would + run its provider call *inside the workflow* — nondeterministic and unsafe. + """ + from temporalio.contrib.deepagents.workflow import DeepAgentsWorkflowError + + if isinstance(model, str): + return TemporalModel(model=model) + if isinstance(model, TemporalModel): + return model + if isinstance(model, BaseChatModel): + raise DeepAgentsWorkflowError( + f"create_deep_agent received a live {type(model).__name__} model " + f"instance, which would run inside the workflow (nondeterministic). " + f'Pass model="provider:name" (auto-routed through an activity) or ' + f"wrap it as TemporalModel(...) instead." + ) + return model + + +def install_model_patch() -> None: + """Route Deep Agents' model resolution through :class:`TemporalModel`. + + Patches ``deepagents.graph.resolve_model`` (the seam ``create_deep_agent`` + uses for the main agent *and* every sub-agent) so a bare ``model="..."`` + string becomes a durable :class:`TemporalModel`, and additionally wraps + ``deepagents.create_deep_agent`` to fire the advisory tool / checkpointer + warnings. Both only act when called inside a workflow, so importing + deepagents on a plain client / activity worker is unaffected. Idempotent. + """ + global _original_create_deep_agent, _original_resolve_model + # importlib: `deepagents` is absent on Python 3.10 environments (its floor + # is 3.11), so static imports here fail type-checking there. + deepagents = importlib.import_module("deepagents") + _graph = importlib.import_module("deepagents.graph") + + if _original_resolve_model is None: + _original_resolve_model = _graph.resolve_model + + def patched_resolve_model(model: Any) -> Any: + if workflow.in_workflow(): + return _wrap_model_arg(model) + return _original_resolve_model(model) + + setattr(_graph, "resolve_model", patched_resolve_model) + + if _original_create_deep_agent is None: + _original_create_deep_agent = deepagents.create_deep_agent + + def patched(*args: Any, **kwargs: Any) -> Any: + if workflow.in_workflow(): + from temporalio.contrib.deepagents._tools import warn_unwrapped_tools + from temporalio.contrib.deepagents.workflow import ( + warn_durable_checkpointer, + ) + + warn_unwrapped_tools(kwargs.get("tools")) + warn_durable_checkpointer(kwargs.get("checkpointer")) + return _original_create_deep_agent(*args, **kwargs) + + setattr(deepagents, "create_deep_agent", patched) + + +def uninstall_model_patch() -> None: + """Restore the original ``resolve_model`` / ``create_deep_agent``.""" + global _original_create_deep_agent, _original_resolve_model + if _original_resolve_model is not None: + _graph = importlib.import_module("deepagents.graph") + + setattr(_graph, "resolve_model", _original_resolve_model) + _original_resolve_model = None + if _original_create_deep_agent is not None: + deepagents = importlib.import_module("deepagents") + + setattr(deepagents, "create_deep_agent", _original_create_deep_agent) + _original_create_deep_agent = None diff --git a/temporalio/contrib/deepagents/_plugin.py b/temporalio/contrib/deepagents/_plugin.py new file mode 100644 index 000000000..3b95fcdaf --- /dev/null +++ b/temporalio/contrib/deepagents/_plugin.py @@ -0,0 +1,296 @@ +"""The plugin object users add to ``plugins=[...]``. + +:class:`DeepAgentsPlugin` wires everything together so that existing +``deepagents`` code — ``create_deep_agent(...).ainvoke(...)`` — runs durably +inside a ``@workflow.defn`` with no other changes: + +* registers the four activities that carry the nondeterministic work; +* installs the LangChain-aware data converter (composing, never clobbering, a + user converter); +* passes the LangChain / LangGraph / deepagents import tree through the workflow + sandbox; +* wraps the worker run in a ``run_context`` that patches Deep Agents' model + resolution seam (``deepagents.graph.resolve_model``) to auto-route bare + ``model=`` strings through activities — regardless of how the user imported + ``create_deep_agent``; +* registers :class:`DeepAgentsWorkflowError` as a workflow-failure type; +* pushes the model / tool dispatch defaults down to the seams that read them. + +The plugin auto-propagates from a ``Client`` to any ``Worker`` built from it, so +add it on exactly one side. ``configure_worker`` additionally de-duplicates +activities by name, so a user who mistakenly adds it on both sides gets a clean +no-op instead of a "More than one activity named ..." crash. +""" + +from __future__ import annotations + +import sys +import warnings +from collections.abc import AsyncIterator, Sequence +from contextlib import asynccontextmanager +from dataclasses import replace +from datetime import timedelta +from typing import Any, Callable + +from temporalio import activity as activity_mod +from temporalio.contrib.deepagents import _serde, _tools +from temporalio.contrib.deepagents._activity import DeepAgentActivities +from temporalio.contrib.deepagents.workflow import DeepAgentsWorkflowError +from temporalio.plugin import SimplePlugin +from temporalio.worker import WorkflowRunner +from temporalio.worker.workflow_sandbox import SandboxedWorkflowRunner + +# Runtime floor for the Deep Agents control loop. Kept in a constant so +# static checkers do not narrow `sys.version_info` comparisons into +# unreachable-code findings on new interpreters. +_MIN_PYTHON = (3, 11) + + +class DeepAgentsPlugin(SimplePlugin): + """Temporal plugin that makes LangChain Deep Agents durable. + + Args: + model_provider: Builds a real chat model from a name string, worker-side. + This is where API keys live; only the model name ever crosses the + workflow boundary. Defaults to LangChain's ``init_chat_model`` with + LLM-SDK retries disabled (Temporal owns retries). + model_activity_options: ``ActivityConfig`` (or ``Mapping[model_name, + ActivityConfig]``) for the model activities — timeouts, retry policy. + tool_activity_options: ``ActivityConfig`` (or ``Mapping[tool_name, + ActivityConfig]``) default for tools wrapped with ``tool_as_activity``. + streaming_topic: When set, model calls stream through the streaming + activity and publish chunk batches to this workflow-streams topic. + streaming_batch_interval: How long the streaming activity coalesces + chunks before publishing a batch. + passthrough_modules: Extra sandbox-passthrough modules, merged with the + plugin's LangChain/deepagents defaults. + data_converter: Override the default LangChain-aware converter. ``None`` + installs the default; the SDK default is upgraded in place; any other + converter raises (fold ``DeepAgentsPayloadConverter`` into your own). + """ + + def __init__( + self, + *, + model_provider: Callable[[str], Any] | None = None, + model_activity_options: Any = None, + tool_activity_options: Any = None, + streaming_topic: str | None = None, + streaming_batch_interval: timedelta = timedelta(milliseconds=100), + passthrough_modules: Sequence[str] | None = None, + data_converter: Any = None, + ) -> None: + """Configure the plugin; see the class docstring for parameters.""" + if sys.version_info < _MIN_PYTHON: + warnings.warn( + "DeepAgentsPlugin requires Python >= 3.11 (deepagents pins " + ">=3.11); the Deep Agents control loop relies on contextvars " + "propagation through asyncio that older versions lack.", + stacklevel=2, + ) + + self._passthrough_modules = passthrough_modules + # Held on the instance so the wiring is statically traceable: each is + # passed straight into the call that consumes it (below), not stashed as + # dead config. + self._tool_activity_options = tool_activity_options + self._data_converter = data_converter + + # Push dispatch defaults down to the model and tool seams that read them. + # These live in ``_serde`` / ``_tools`` (langchain-free modules) so + # constructing the plugin never imports LangChain. ``tool_activity_options`` + # is stored under ``_tools._tool_defaults`` and read back on the tool + # dispatch path by ``_tools._resolve_tool_options(...)`` — which + # ``tool_as_activity`` calls to compute each tool activity's timeout/retry + # when the caller does not override ``activity_options``. + _serde.set_settings( + model_activity_options=model_activity_options, + streaming_topic=streaming_topic, + ) + # wired-via-composition: consumed on the tool dispatch path in _tools.py + # (_resolve_tool_options), renamed to ``options`` at the callsite. + _tools.set_tool_defaults(self._tool_activity_options) + + # The activities that carry the nondeterministic work. model_provider and + # the batch interval are captured here so API keys never enter an input. + self._activities = DeepAgentActivities( + model_provider=model_provider, + streaming_batch_interval=streaming_batch_interval, + ) + activities = [ + self._activities.invoke_model, + self._activities.invoke_model_streaming, + self._activities.invoke_tool, + self._activities.backend_op, + ] + + super().__init__( + "langchain.DeepAgentsPlugin", + activities=activities, + # wired-via-composition: ``data_converter`` flows into SimplePlugin's + # own ``data_converter`` kwarg (renamed to ``user_converter`` inside + # build_data_converter), which installs it on the client/worker. + data_converter=_serde.build_data_converter(self._data_converter), + workflow_runner=self._make_workflow_runner(), + workflow_failure_exception_types=[DeepAgentsWorkflowError], + run_context=self._run_context, + ) + + # -- sandbox passthrough ------------------------------------------------- + + def _make_workflow_runner( + self, + ) -> Callable[[WorkflowRunner | None], WorkflowRunner]: + modules = _serde.resolve_passthrough_modules(self._passthrough_modules) + + def workflow_runner(runner: WorkflowRunner | None) -> WorkflowRunner: + if runner is None: + raise ValueError("No WorkflowRunner provided to DeepAgentsPlugin.") + if isinstance(runner, SandboxedWorkflowRunner): + return replace( + runner, + restrictions=runner.restrictions.with_passthrough_modules(*modules), + ) + return runner + + return workflow_runner + + # -- run context --------------------------------------------------------- + + @asynccontextmanager + async def _run_context(self) -> AsyncIterator[None]: + """Patch Deep Agents' model resolution seam for the worker's lifetime. + + The patch (on ``deepagents.graph.resolve_model``, the seam + ``create_deep_agent`` uses for the agent and every sub-agent) only + rewrites ``model=`` strings when running inside a workflow, so it is inert + on plain clients / activity workers. Determinism itself + rides on the same mechanism ``contrib.langgraph`` uses — the loop is + in-workflow and every nondeterministic call is an activity — so no + speculative time/uuid shims are installed here. + + One shim *is* required: LangChain's ``create_agent`` factory wraps every + model node with LangSmith's ``@traceable``, whose async path hops onto a + thread via ``asyncio.run_in_executor`` — which the deterministic workflow + event loop does not implement (it raises ``NotImplementedError``). Tracing + is an observability concern that must not run in-workflow, so we install + LangSmith's own Temporal escape hatch (``set_runtime_overrides``) to run + that setup inline when ``in_workflow()``, and defer to the default thread + hop everywhere else (activities / clients, where tracing is fine). + """ + # Imported lazily (not at module top) so plugin construction stays + # langchain-free; the patch is only needed once the worker is running. + # The import itself is inside the guard: on a worker without LangChain + # installed (e.g. one that only runs the plugin's determinism / failure + # paths) importing ``_model`` raises ``ModuleNotFoundError``, and the + # worker must still start — it simply runs without the auto-wrap patch. + patched = False + try: + from temporalio.contrib.deepagents import _model, _tools + + _model.install_model_patch() + _tools.install_backend_async_patch() + patched = True + except ImportError as exc: # LangChain / deepagents absent on this worker + # Deliberately ImportError only: a *missing* optional dependency + # must not stop the worker, but a genuine patch-installation bug + # (e.g. upstream renaming the seam raises AttributeError) must + # surface at startup, not degrade into silent in-workflow calls. + warnings.warn( + f"DeepAgentsPlugin could not patch create_deep_agent ({exc}); " + "use explicit TemporalModel(...) instances to route model calls " + "through activities.", + stacklevel=2, + ) + # Installed for the life of the process, never uninstalled — see + # _install_langsmith_temporal_override for why. + _install_langsmith_temporal_override() + try: + yield + finally: + if patched: + # Import is cached: patched=True implies the import above succeeded. + from temporalio.contrib.deepagents import _model, _tools + + _model.uninstall_model_patch() + _tools.uninstall_backend_async_patch() + + # -- worker config ------------------------------------------------------- + + def configure_worker(self, config: Any) -> Any: + """Deduplicate activity registrations after the base configuration.""" + config = super().configure_worker(config) + activities = config.get("activities") + if activities: + config["activities"] = _dedupe_activities(activities) + return config + + +async def _temporal_aio_to_thread( + default_aio_to_thread: Callable[..., Any], + ctx: Any, + func: Callable[..., Any], + /, + *args: Any, + **kwargs: Any, +) -> Any: + """Run LangSmith's ``aio_to_thread`` seam safely inside a workflow. + + Outside a workflow (activities, clients) we defer to LangSmith's default + thread hop. Inside a workflow the deterministic event loop cannot spawn a + thread, so we run the setup inline in the requested context. ``func`` here is + LangSmith's own run-tree bookkeeping — cheap and side-effect-free with respect + to workflow determinism. + """ + from temporalio import workflow + + if not workflow.in_workflow(): + return await default_aio_to_thread(ctx, func, *args, **kwargs) + with workflow.unsafe.sandbox_unrestricted(): + return ctx.run(func, *args, **kwargs) + + +def _install_langsmith_temporal_override() -> None: + """Route LangSmith's thread hop inline while in a workflow. + + ``set_runtime_overrides`` mutates a module global in the sandbox-passthrough + ``langsmith`` package, so the in-workflow tracer sees it too. No-op (and + harmless) when LangSmith is not installed or too old to expose + ``set_runtime_overrides``. + + The override is deliberately installed for the life of the process and + never uninstalled: LangSmith exposes a single process-wide override slot + (each ``set_runtime_overrides`` call replaces it wholesale), and + ``temporalio.contrib.langsmith`` installs a behaviorally identical override + exactly once, without reinstalling. Resetting the slot on this worker's + shutdown would therefore permanently strip a composed LangSmith plugin's + workflow-safety override. Leaving it installed is safe: the override defers + to LangSmith's default thread hop whenever ``workflow.in_workflow()`` is + false, so it is inert outside workflows. + """ + try: + import langsmith + + langsmith.set_runtime_overrides(aio_to_thread=_temporal_aio_to_thread) + except Exception: + pass + + +def _dedupe_activities(activities: Sequence[Any]) -> list[Any]: + """Drop duplicate activity registrations by defn name, keeping the first. + + Guards the "plugin added on both Client and Worker" trap, where the plugin's + activities would otherwise be appended twice and the worker would reject the + duplicate names. + """ + seen: set[str] = set() + out: list[Any] = [] + for act in activities: + defn = activity_mod._Definition.from_callable(act) + name = defn.name if defn is not None else getattr(act, "__name__", repr(act)) + key = name or repr(act) + if key in seen: + continue + seen.add(key) + out.append(act) + return out diff --git a/temporalio/contrib/deepagents/_serde.py b/temporalio/contrib/deepagents/_serde.py new file mode 100644 index 000000000..13ed0d1c6 --- /dev/null +++ b/temporalio/contrib/deepagents/_serde.py @@ -0,0 +1,410 @@ +"""Serialization helpers, a result cache, and worker-runtime configuration. + +The Deep Agents control loop runs *inside* the Temporal workflow, so the values +that actually cross the workflow⇄activity boundary are a small set of LangChain +types: chat messages, tool-call descriptors, and the ``RunnableConfig`` metadata +attached to each model / tool call. LangChain messages are polymorphic +``Serializable`` models (an ``AIMessage`` must not be rehydrated as a +``ToolMessage``) and ``RunnableConfig`` carries live callback / checkpointer +references, so neither survives a naive round-trip. This module owns: + +* message (de)serialization via ``langchain_core.load.dumpd`` / ``load`` — the + round-trip that preserves message subtype and tool-call structure; +* the strip → ship → rebuild dance for ``RunnableConfig``; +* tool → JSON-schema advertisement (full name + description + argument schema, + never ``{name, description}`` alone — without the argument schema the model + picks the right tool but hallucinates its arguments); +* the Pydantic data converter (``exclude_unset=True``) the plugin installs on + the client and replayer, so message payloads stay small and round-trip + cleanly; +* a workflow-scoped result cache so model / tool results computed before a + ``continue_as_new`` are reused rather than recomputed after it; +* the sandbox passthrough module list covering LangChain's transitive + eager-import tree. + +LangChain imports are deferred into the functions that need them, so importing +this module — and constructing the plugin — does not require LangChain to be +installed on the machine assembling the worker. +""" + +from __future__ import annotations + +import contextvars +import dataclasses +import hashlib +import json +from typing import TYPE_CHECKING, Any, cast + +if TYPE_CHECKING: + from langchain_core.runnables import RunnableConfig + +from temporalio.contrib.pydantic import PydanticPayloadConverter, ToJsonOptions +from temporalio.converter import DataConverter + +# --------------------------------------------------------------------------- +# Worker-wide dispatch settings +# --------------------------------------------------------------------------- +# +# These are fixed for the worker's lifetime (not per-workflow state), so a module +# global is correct. This module lives under ``temporalio``, which the workflow +# sandbox passes through, so the object the in-workflow model stub reads is the +# same one the plugin configured. They live here (not in ``_model``) so that +# ``DeepAgentsPlugin`` can push them down without importing ``_model`` — which +# would drag in LangChain at plugin-construction time. + + +@dataclasses.dataclass +class Settings: + """Dispatch defaults shared by every ``TemporalModel`` on the worker.""" + + model_activity_options: Any = None + """``ActivityConfig`` or ``Mapping[model_name, ActivityConfig]``.""" + streaming_topic: str | None = None + + +_settings = Settings() + + +def set_settings( + *, + model_activity_options: Any = None, + streaming_topic: str | None = None, +) -> None: + """Install the worker-wide model dispatch defaults (called by the plugin).""" + _settings.model_activity_options = model_activity_options + _settings.streaming_topic = streaming_topic + + +def get_settings() -> Settings: + """Return the active dispatch settings.""" + return _settings + + +# --------------------------------------------------------------------------- +# Data converter +# --------------------------------------------------------------------------- + + +class DeepAgentsPayloadConverter(PydanticPayloadConverter): + """Pydantic payload converter pinned to ``exclude_unset=True``. + + LangChain request/response types (and ``DeepAgentState``) are deeply nested + with many ``Optional[...] = None`` fields. Shipping every unset default + inflates payloads several-fold and some peers reject the explicit nulls on + round-trip, so we exclude unset fields by convention. + """ + + def __init__(self) -> None: + """Construct the converter with ``exclude_unset`` serialization.""" + super().__init__(ToJsonOptions(exclude_unset=True)) + + +data_converter = DataConverter(payload_converter_class=DeepAgentsPayloadConverter) +"""The plugin's default data converter (LangChain messages are shipped as their +``dumpd`` JSON form, so the Pydantic converter only ever sees plain containers).""" + + +def build_data_converter( + user_converter: DataConverter | None, +) -> DataConverter: + """Compose the plugin's converter with whatever the caller already set. + + * ``None`` — install the plugin default. + * the SDK default converter — swap in the LangChain-aware Pydantic + converter via :func:`dataclasses.replace`. + * a custom converter — refuse rather than silently clobber it; the caller + must fold :class:`DeepAgentsPayloadConverter` into their own converter. + """ + if user_converter is None: + return data_converter + if user_converter is DataConverter.default: + return dataclasses.replace( + user_converter, payload_converter_class=DeepAgentsPayloadConverter + ) + raise ValueError( + "DeepAgentsPlugin cannot compose with a custom data_converter " + "automatically. Set payload_converter_class=DeepAgentsPayloadConverter " + "on your own DataConverter (so LangChain messages serialize with " + "exclude_unset=True), or omit data_converter to use the plugin default." + ) + + +# --------------------------------------------------------------------------- +# LangChain object (de)serialization +# --------------------------------------------------------------------------- + + +def dump_object(obj: Any) -> Any: + """Serialize a single LangChain ``Serializable`` (message, tool call, …).""" + from langchain_core.load import dumpd + + return dumpd(obj) + + +def load_object(data: Any) -> Any: + """Rehydrate a value produced by :func:`dump_object`, preserving subtype.""" + from langchain_core.load import load + + return load(data) + + +# --------------------------------------------------------------------------- +# Backend protocol result (de)serialization +# --------------------------------------------------------------------------- + +_BACKEND_DATACLASS_KEY = "__deepagents_dataclass__" + + +def dump_backend_result(value: Any) -> Any: + """Encode a backend op's return value for the activity boundary. + + Backend protocol results (``WriteResult`` / ``ReadResult`` / ``GrepResult`` + and their nested ``FileInfo`` / ``GrepMatch`` items, …) are plain + dataclasses — not LangChain ``Serializable`` objects — and the filesystem + middleware reads their ATTRIBUTES in-workflow, so a plain JSON round-trip + (which decays them to dicts) breaks the seam at the first real backend op. + Tag deepagents dataclasses with their import path so + :func:`load_backend_result` rebuilds the real type; anything else (str, + dict, a custom backend's own types) passes through with today's + plain-JSON behavior. + """ + import dataclasses + + if dataclasses.is_dataclass(value) and not isinstance(value, type): + cls = type(value) + dumped_fields = { + f.name: dump_backend_result(getattr(value, f.name)) + for f in dataclasses.fields(value) + } + if cls.__module__.split(".", 1)[0] == "deepagents": + return { + _BACKEND_DATACLASS_KEY: f"{cls.__module__}:{cls.__qualname__}", + "fields": dumped_fields, + } + return dumped_fields + if isinstance(value, (list, tuple)): + return [dump_backend_result(v) for v in value] + if isinstance(value, dict): + return {k: dump_backend_result(v) for k, v in value.items()} + return value + + +def load_backend_result(value: Any) -> Any: + """Rebuild a value produced by :func:`dump_backend_result`. + + Only ``deepagents.*`` dataclasses are reconstructed (the tag is written + exclusively for them); anything else would mean a forged payload, so + refuse rather than import arbitrary types. Reconstruction suppresses + ``DeprecationWarning``: this is transport, not user code — the backend + already constructed the object once on the activity side, and required + deprecated fields (e.g. ``WriteResult.files_update``) would otherwise + warn on every op. Field values equal to a declared default are omitted + from the constructor call. + """ + import dataclasses + import importlib + import warnings + + if isinstance(value, dict) and _BACKEND_DATACLASS_KEY in value: + path = value[_BACKEND_DATACLASS_KEY] + module_name, _, qualname = path.partition(":") + if module_name.split(".", 1)[0] != "deepagents": + raise ValueError(f"refusing to rebuild non-deepagents type {path!r}") + obj: Any = importlib.import_module(module_name) + for part in qualname.split("."): + obj = getattr(obj, part) + if not (isinstance(obj, type) and dataclasses.is_dataclass(obj)): + raise ValueError(f"{path!r} is not a dataclass") + loaded = {k: load_backend_result(v) for k, v in value["fields"].items()} + kwargs = {} + for f in dataclasses.fields(obj): + if f.name not in loaded: + continue + if f.default is not dataclasses.MISSING and loaded[f.name] == f.default: + continue + kwargs[f.name] = loaded[f.name] + with warnings.catch_warnings(): + warnings.simplefilter("ignore", DeprecationWarning) + return obj(**kwargs) + if isinstance(value, list): + return [load_backend_result(v) for v in value] + if isinstance(value, dict): + return {k: load_backend_result(v) for k, v in value.items()} + return value + + +def dump_messages(messages: Any) -> list[Any]: + """Serialize a sequence of LangChain messages to their ``dumpd`` form.""" + from langchain_core.load import dumpd + + return [dumpd(m) for m in messages] + + +def load_messages(dumped: list[Any]) -> list[Any]: + """Rehydrate messages serialized by :func:`dump_messages`.""" + from langchain_core.load import load + + return [load(d) for d in dumped] + + +def tool_to_schema(tool: Any) -> dict[str, Any]: + """Advertise a tool to the model as a full OpenAI tool schema. + + Carries name + description + argument JSON schema so the model can build + valid arguments, not just select the tool by name. + """ + from langchain_core.utils.function_calling import convert_to_openai_tool + + return convert_to_openai_tool(tool) + + +# --------------------------------------------------------------------------- +# RunnableConfig strip / rebuild +# --------------------------------------------------------------------------- + + +def _is_jsonish(value: Any) -> bool: + if value is None or isinstance(value, (str, int, float, bool)): + return True + if isinstance(value, (list, tuple)): + return all(_is_jsonish(v) for v in value) + if isinstance(value, dict): + return all(isinstance(k, str) and _is_jsonish(v) for k, v in value.items()) + return False + + +def strip_runnable_config(config: Any) -> dict[str, Any]: + """Reduce a live ``RunnableConfig`` to its JSON-safe subset for shipping. + + Keeps ``tags``, ``run_name``, ``run_id``, ``recursion_limit``, JSON-safe + ``metadata`` and the JSON-safe (non-dunder) ``configurable`` keys. Drops + callbacks, checkpointer / store / cache handles and every other live + reference — those are reconstructed activity-side. + """ + if not config: + return {} + out: dict[str, Any] = {} + if config.get("tags"): + out["tags"] = list(config["tags"]) + for key in ("run_id", "run_name"): + if config.get(key) is not None: + out[key] = str(config[key]) + if config.get("recursion_limit") is not None: + out["recursion_limit"] = config["recursion_limit"] + metadata = config.get("metadata") + if isinstance(metadata, dict): + out["metadata"] = {k: v for k, v in metadata.items() if _is_jsonish(v)} + configurable = config.get("configurable") + if isinstance(configurable, dict): + kept = { + k: v + for k, v in configurable.items() + if not k.startswith("__") and _is_jsonish(v) + } + if kept: + out["configurable"] = kept + return out + + +def rebuild_runnable_config(data: dict[str, Any]) -> "RunnableConfig": + """Reconstruct a minimal ``RunnableConfig`` from :func:`strip_runnable_config`.""" + config: dict[str, Any] = {"metadata": dict(data.get("metadata", {}))} + if data.get("tags"): + config["tags"] = list(data["tags"]) + for key in ("run_id", "run_name"): + if data.get(key) is not None: + config[key] = data[key] + if data.get("recursion_limit") is not None: + config["recursion_limit"] = data["recursion_limit"] + if data.get("configurable"): + config["configurable"] = dict(data["configurable"]) + # Double cast: a TypedDict and dict[str, Any] "insufficiently overlap" + # for basedpyright's reportInvalidCast; object is the sanctioned bridge. + return cast("RunnableConfig", cast(object, config)) + + +# --------------------------------------------------------------------------- +# Result cache (continue-as-new dedup) +# --------------------------------------------------------------------------- + +# Per-workflow state: set at the top of the workflow run, read by the model and +# tool dispatch paths, snapshotted for continue-as-new. A ContextVar (not a +# module-global keyed by run id) so update / signal handler tasks spawned by the +# workflow inherit the same cache automatically. +_result_cache: contextvars.ContextVar[dict[str, Any] | None] = contextvars.ContextVar( + "_deepagents_result_cache", default=None +) + + +def set_result_cache(cache: dict[str, Any] | None) -> None: + """Seed the workflow-scoped result cache (e.g. carried across CAN).""" + _result_cache.set(dict(cache) if cache else {}) + + +def result_cache_snapshot() -> dict[str, Any] | None: + """Return a serializable copy of the cache, or ``None`` when empty.""" + cache = _result_cache.get() + return dict(cache) if cache else None + + +def cache_key(kind: str, call_id: str, args: Any) -> str: + """Stable key over ``(kind, call_id, args)`` for cache lookups.""" + blob = json.dumps([kind, call_id, args], default=str, sort_keys=True) + return hashlib.sha256(blob.encode("utf-8")).hexdigest() + + +def cache_lookup(key: str) -> tuple[bool, Any]: + """Return ``(hit, value)`` for ``key`` in the active cache.""" + cache = _result_cache.get() + if cache is not None and key in cache: + return True, cache[key] + return False, None + + +def cache_put(key: str, value: Any) -> None: + """Record ``value`` under ``key`` when a cache is active for this run.""" + cache = _result_cache.get() + if cache is not None: + cache[key] = value + + +# --------------------------------------------------------------------------- +# Sandbox passthrough +# --------------------------------------------------------------------------- + +# The workflow sandbox re-imports modules per run; LangChain / LangGraph / +# deepagents build large class hierarchies with eager import side effects, and +# LangSmith pulls in numpy. Passing them through means "import once in the host +# and share", which is both faster and required for identity checks +# (isinstance across the sandbox boundary) to hold. +_DEFAULT_PASSTHROUGH: tuple[str, ...] = ( + "langchain", + "langchain_core", + "langchain_anthropic", + "langgraph", + "deepagents", + "langsmith", + "numpy", + "pydantic", + "pydantic_core", + "anthropic", + "tiktoken", + "jsonpatch", + "jsonpointer", + "tenacity", + "orjson", + "httpx", + "httpcore", +) + + +def default_passthrough_modules() -> tuple[str, ...]: + """The LangChain / deepagents transitive import tree passed through the sandbox.""" + return _DEFAULT_PASSTHROUGH + + +def resolve_passthrough_modules(user: Any) -> tuple[str, ...]: + """Merge caller-supplied passthrough modules with the plugin defaults.""" + merged = [*_DEFAULT_PASSTHROUGH, *(user or ())] + # dict.fromkeys preserves order while de-duplicating. + return tuple(dict.fromkeys(merged)) diff --git a/temporalio/contrib/deepagents/_tools.py b/temporalio/contrib/deepagents/_tools.py new file mode 100644 index 000000000..1235224c6 --- /dev/null +++ b/temporalio/contrib/deepagents/_tools.py @@ -0,0 +1,517 @@ +"""The tool + backend seams: the explicit per-unit Workflow-vs-Activity choice. + +Deep Agents holds its tools and filesystem/shell backends in-workflow. A tool or +backend op that only reads and writes ``DeepAgentState`` is pure and belongs in +the workflow (deterministic, replay-safe). One that does real I/O — a web +search, a shell command, a disk write — must not run there. This module gives +the user three explicit ways to move that work to an activity: + +* :func:`activity_as_tool` — expose an existing ``@activity.defn`` as a Deep + Agents tool (Temporal adopters already have activities; don't make them + re-declare); +* :func:`tool_as_activity` — wrap a LangChain ``BaseTool`` / callable so its + execution runs as an activity; +* :class:`TemporalBackend` — wrap a real-I/O backend so each file/exec op runs + as an activity. + +The choice is always explicit: an unwrapped non-builtin tool runs in-workflow, +and the plugin warns at construction so that is a conscious decision, never a +silent one. + +Registries here live in a ``temporalio``-namespaced (sandbox-passthrough) module, +so the object the worker's activity sees is the same one the module-level +``tool_as_activity(...)`` / ``TemporalBackend(...)`` call populated. They hold +worker-wide wiring, not per-workflow state. +""" + +from __future__ import annotations + +import importlib +import threading +import uuid as _uuid +import warnings +import weakref +from collections.abc import Mapping +from datetime import timedelta +from functools import wraps +from typing import TYPE_CHECKING, Any, Callable + +from temporalio import activity as activity_mod +from temporalio import workflow +from temporalio.contrib.deepagents import _activity, _serde + +# LangChain is a runtime dependency of the *tool seam*, but importing this module +# must not require it (the plugin imports it just to read tool defaults). So the +# ``langchain_core.tools`` symbols are imported lazily inside the functions that +# actually build tools; ``from __future__ import annotations`` keeps the type +# hints below as strings so they never touch LangChain at import time. +if TYPE_CHECKING: + from langchain_core.tools import BaseTool + + +# --------------------------------------------------------------------------- +# Tool registry (worker-side execution targets) +# --------------------------------------------------------------------------- + +_TOOL_REGISTRY: dict[str, "BaseTool"] = {} +_BACKEND_REGISTRY: dict[str, Any] = {} +# Serializes registration against the GC-time unregister in +# _unregister_backend, which may run on another thread. +_BACKEND_REGISTRY_LOCK = threading.Lock() + +# Worker-wide default activity options for tools wrapped with tool_as_activity, +# set by the plugin. Not per-workflow state: fixed for the worker's lifetime, and +# this module is sandbox-passthrough so the workflow sees the configured value. +_tool_defaults: dict[str, Any] = {} + + +def set_tool_defaults(options: Any) -> None: + """Install the plugin's default ``tool_activity_options`` (called by the plugin). + + Accepts a single ``ActivityConfig`` or a ``Mapping[tool_name, ActivityConfig]``. + """ + _tool_defaults.clear() + if options: + _tool_defaults["__value__"] = options + + +def _resolve_tool_options( + tool_name: str, instance_options: Mapping[str, Any] | None +) -> dict[str, Any]: + """Merge plugin tool defaults (possibly per-tool) with a per-call override.""" + opts: dict[str, Any] = {} + default = _tool_defaults.get("__value__") + if isinstance(default, Mapping): + per_tool = default.get(tool_name) + if isinstance(per_tool, Mapping): + opts.update(per_tool) + elif not any(isinstance(v, Mapping) for v in default.values()): + opts.update(default) + if instance_options: + opts.update(instance_options) + return opts + + +# Names of tools that route through Temporal (activity_as_tool / tool_as_activity), +# used to warn about unwrapped non-builtin tools at workflow build time. +_ROUTED_TOOL_NAMES: set[str] = set() + +# Deep Agents' built-in tools run in-workflow (pure state mutations); they are +# not expected to be wrapped, so they never trigger the unwrapped-tool warning. +# These are the LLM-facing TOOL names (``read_file``, ``write_file``, …) — +# NOT the backend protocol method names in ``_BACKEND_OPS`` (``read``, +# ``aread``, …); the two namespaces intentionally differ. +_BUILTIN_TOOL_NAMES = frozenset( + { + "write_todos", + "ls", + "read_file", + "write_file", + "edit_file", + "glob", + "grep", + "execute", + "task", + } +) + + +def register_tool(tool: BaseTool) -> None: + """Record ``tool`` so :meth:`DeepAgentActivities.invoke_tool` can run it.""" + _TOOL_REGISTRY[tool.name] = tool + + +def warn_unwrapped_tools(tools: Any) -> None: + """Warn once per unwrapped, non-builtin tool passed to ``create_deep_agent``. + + Running a tool in-workflow is only safe if it is pure/deterministic. The + Workflow-vs-Activity choice must be conscious, so any user tool that was not + routed through :func:`tool_as_activity` / :func:`activity_as_tool` gets a + construction-time warning rather than silently executing in the workflow. + """ + for tool in tools or (): + name = getattr(tool, "name", getattr(tool, "__name__", None)) + if name is None or name in _BUILTIN_TOOL_NAMES or name in _ROUTED_TOOL_NAMES: + continue + warnings.warn( + f"Tool {name!r} is passed to create_deep_agent unwrapped and will run " + f"inside the workflow. That is only safe if it is pure/deterministic. " + f"If it does I/O, wrap it with tool_as_activity(...) or expose an " + f"existing activity with activity_as_tool(...).", + stacklevel=3, + ) + + +def get_registered_tool(name: str) -> BaseTool | None: + """Look up a tool registered by :func:`register_tool`.""" + return _TOOL_REGISTRY.get(name) + + +def register_backend(ref: str, backend: Any) -> None: + """Record a backend so :meth:`DeepAgentActivities.backend_op` can reach it.""" + with _BACKEND_REGISTRY_LOCK: + _BACKEND_REGISTRY[ref] = backend + + +def _unregister_backend(ref: str, inner: Any) -> None: + """Drop ``ref`` from the registry if it still maps to ``inner``. + + GC hook for :class:`TemporalBackend` (via ``weakref.finalize``): a wrapper + is typically constructed per workflow run, so without cleanup a long-lived + worker accumulates one registry entry per run. The identity guard is + load-bearing: refs are deterministic per run, so after a cache eviction a + replay re-registers the *same* ref with a fresh inner backend — the evicted + wrapper's finalizer must not remove that live registration. + """ + with _BACKEND_REGISTRY_LOCK: + if _BACKEND_REGISTRY.get(ref) is inner: + del _BACKEND_REGISTRY[ref] + + +def registered_backends() -> dict[str, Any]: + """Return the live backend registry (read by the plugin at worker build).""" + return _BACKEND_REGISTRY + + +# --------------------------------------------------------------------------- +# activity_as_tool +# --------------------------------------------------------------------------- + + +def activity_as_tool( + activity: Callable, + *, + start_to_close_timeout: timedelta, + name: str | None = None, + description: str | None = None, + retry_policy: Any = None, + summary: str | None = None, +) -> BaseTool: + """Expose an existing Temporal activity as a Deep Agents tool. + + The returned tool advertises the activity's argument schema to the model and, + when called in-workflow, dispatches to the activity via + ``workflow.execute_activity`` — Temporal owns its retries and timeout. + + Args: + activity: A function decorated with ``@activity.defn``. + start_to_close_timeout: Required per-call timeout for the activity. + name: Override the tool name advertised to the model (defaults to + the activity definition name). + description: Override the tool description advertised to the model + (defaults to the activity docstring). + retry_policy: Optional Temporal retry policy for the activity. + summary: Optional ``summary=`` recorded on each activity invocation. + """ + with workflow.unsafe.imports_passed_through(): + from langchain_core.tools import StructuredTool + + defn = activity_mod._Definition.from_callable(activity) + if defn is None: + raise ValueError( + "activity_as_tool requires a function decorated with @activity.defn; " + f"{getattr(activity, '__name__', activity)!r} is not an activity." + ) + tool_name = name or defn.name + if tool_name is None: + raise ValueError( + "activity_as_tool requires a named activity (dynamic activities " + "have no definition name); pass name= explicitly." + ) + tool_desc = description or (activity.__doc__ or f"Temporal activity {tool_name}.") + act_summary = summary or f"tool:{tool_name}" + + # Temporal activities take a single positional argument. StructuredTool infers + # the model-facing schema from ``_run``'s signature, so we mirror the activity's + # own parameter names onto ``_run`` (via ``@wraps``) and then collapse the + # keyword call the model produces back into that single positional payload. + import inspect + + params = [ + p for p in inspect.signature(activity).parameters if p not in ("self", "cls") + ] + + @wraps(activity) + async def _run(*args: Any, **kwargs: Any) -> Any: + if args and not kwargs: + payload: Any = args[0] if len(args) == 1 else list(args) + elif len(params) == 1 and len(kwargs) == 1: + # Single-argument activity: pass the value directly, not {"arg": value}. + payload = next(iter(kwargs.values())) + else: + payload = kwargs + return await workflow.execute_activity( + activity, + payload, + start_to_close_timeout=start_to_close_timeout, + retry_policy=retry_policy, + summary=act_summary, + ) + + _ROUTED_TOOL_NAMES.add(tool_name) + return StructuredTool.from_function( + coroutine=_run, + name=tool_name, + description=tool_desc, + ) + + +# --------------------------------------------------------------------------- +# tool_as_activity +# --------------------------------------------------------------------------- + + +def tool_as_activity( + tool: BaseTool | Callable, + *, + start_to_close_timeout: timedelta, + activity_options: Mapping[str, Any] | None = None, +) -> BaseTool: + """Wrap a LangChain tool / callable so its execution runs as an activity. + + The underlying tool is registered on the worker; the returned tool keeps the + same name and argument schema (so the model's calls are unchanged) but, when + invoked in-workflow, dispatches ``deepagents.invoke_tool`` instead of running + the tool body inline. + """ + with workflow.unsafe.imports_passed_through(): + from langchain_core.tools import BaseTool, StructuredTool + + base_tool: BaseTool + if isinstance(tool, BaseTool): + base_tool = tool + else: + base_tool = StructuredTool.from_function( + tool if not _is_coroutine(tool) else None, + coroutine=tool if _is_coroutine(tool) else None, + ) + register_tool(base_tool) + + tool_name = base_tool.name + opts = _resolve_tool_options(tool_name, activity_options) + opts.setdefault("start_to_close_timeout", start_to_close_timeout) + + async def _run(**kwargs: Any) -> Any: + from temporalio.contrib.deepagents.workflow import call_tool + + tool_call_id = kwargs.pop("__tool_call_id__", None) or workflow.uuid4().hex + activity_input = _activity.ToolActivityInput( + tool_name=tool_name, + tool_call_id=tool_call_id, + args=kwargs, + ) + output = await call_tool( + activity_input, + summary=f"tool:{tool_name}", + **opts, + ) + message = _serde.load_object(output.message) + # Return CONTENT, not the pre-built ToolMessage: the activity cannot + # know the model's real tool_call_id, so a ToolMessage assembled there + # carries a generated id that a real provider rejects as an unpaired + # tool_result. Given plain content, the tool node stamps the model's + # own id — exactly as it does for unwrapped tools. + with workflow.unsafe.imports_passed_through(): + from langchain_core.messages import ToolMessage + + if isinstance(message, ToolMessage): + return message.content + return message + + _ROUTED_TOOL_NAMES.add(tool_name) + return StructuredTool( + name=tool_name, + description=base_tool.description, + args_schema=base_tool.args_schema, # type: ignore[arg-type] + coroutine=_run, + ) + + +def _is_coroutine(fn: Any) -> bool: + import inspect + + return inspect.iscoroutinefunction(fn) + + +# --------------------------------------------------------------------------- +# TemporalBackend +# --------------------------------------------------------------------------- + +# Async protocol methods and their sync twins. deepagents' ``BackendProtocol`` +# implements each async DEFAULT as ``asyncio.to_thread(sync_twin, ...)``; the +# deterministic workflow event loop has no thread executor, so any built-in +# tool call against an unwrapped in-workflow backend (e.g. the default +# ``StateBackend``) raises ``NotImplementedError``. A real model hits this on +# its first spontaneous ``grep``/``read_file`` call; scripted-model tests that +# never call built-ins sail past it. +_ASYNC_TO_SYNC_OPS: dict[str, str] = { + "als": "ls", + "als_info": "ls_info", + "aread": "read", + "awrite": "write", + "aedit": "edit", + "aglob": "glob", + "aglob_info": "glob_info", + "agrep": "grep", + "agrep_raw": "grep_raw", + "adownload_files": "download_files", + "aupload_files": "upload_files", + "aexecute": "execute", +} + +_original_backend_async_defaults: dict[str, Any] = {} + + +def install_backend_async_patch() -> None: + """Make ``BackendProtocol``'s async defaults workflow-safe. + + Inside a workflow, run the sync twin inline: for state-only backends that + is deterministic and semantically identical to the upstream default, + which merely moves the same sync call onto a worker thread. Outside a + workflow (activities, clients) the upstream default — thread hop plus + timeout guard — is used unchanged. Subclasses that override an async + method natively are unaffected; only the protocol defaults are replaced. + Idempotent. + """ + # importlib: `deepagents` is absent on Python 3.10 environments (its floor + # is 3.11), so a static import here fails type-checking there. + BackendProtocol = importlib.import_module( + "deepagents.backends.protocol" + ).BackendProtocol + + if _original_backend_async_defaults: + return + for async_name, sync_name in _ASYNC_TO_SYNC_OPS.items(): + original = BackendProtocol.__dict__.get(async_name) + if original is None: + continue + + def _make(sync_name: str, original: Any) -> Any: + async def patched(self: Any, *args: Any, **kwargs: Any) -> Any: + if workflow.in_workflow(): + return getattr(self, sync_name)(*args, **kwargs) + return await original(self, *args, **kwargs) + + return patched + + _original_backend_async_defaults[async_name] = original + setattr(BackendProtocol, async_name, _make(sync_name, original)) + + +def uninstall_backend_async_patch() -> None: + """Restore ``BackendProtocol``'s upstream async defaults.""" + if not _original_backend_async_defaults: + return + BackendProtocol = importlib.import_module( + "deepagents.backends.protocol" + ).BackendProtocol + + for async_name, original in _original_backend_async_defaults.items(): + setattr(BackendProtocol, async_name, original) + _original_backend_async_defaults.clear() + + +# Backend METHOD names (deepagents ``BackendProtocol`` + +# ``SandboxBackendProtocol``) whose calls must cross the activity boundary: +# every sync I/O method, its async ``a``-prefixed twin, and the sandbox/shell +# execute pair. The async twins are load-bearing — deepagents' filesystem +# middleware drives backends through ``als``/``aread``/``awrite``/… — so +# intercepting only sync names lets an agent's built-in file tools run I/O +# in-workflow. These are backend PROTOCOL method names, distinct from the +# LLM-facing tool names in ``_BUILTIN_TOOL_NAMES`` (``read_file`` etc.). +_BACKEND_OPS = ( + # Sync protocol surface. + "ls", + "ls_info", + "read", + "write", + "edit", + "glob", + "glob_info", + "grep", + "grep_raw", + "download_files", + "upload_files", + "execute", + # Async twins (what FilesystemMiddleware actually calls). + "als", + "als_info", + "aread", + "awrite", + "aedit", + "aglob", + "aglob_info", + "agrep", + "agrep_raw", + "adownload_files", + "aupload_files", + "aexecute", +) + + +class TemporalBackend: + """Route a real-I/O backend's operations through Temporal activities. + + Wrap a ``FilesystemBackend`` / ``LocalShellBackend`` / ``StoreBackend`` / + ``CompositeBackend`` so each file or shell operation becomes a durable + ``deepagents.backend_op`` activity instead of touching disk / shell from the + workflow. State-only backends (``StateBackend``) need no wrapping — they are + pure workflow state and run in-workflow. + + Unknown attribute access is forwarded to the inner backend so backend + metadata / configuration the agent reads (but that does no I/O) still works. + """ + + def __init__( + self, + inner: Any, + *, + activity_options: Mapping[str, Any] | None = None, + ) -> None: + """Wrap ``inner`` so its I/O ops dispatch as durable activities.""" + self._inner = inner + # A deterministic id: workflow.uuid4() is seeded per-run, so the ref is + # identical across replays (unlike id(inner)). Falls back to a plain uuid + # when a backend is wrapped outside a workflow (e.g. in a plain test). + if workflow.in_workflow(): + self._ref = f"backend:{workflow.uuid4().hex}" + else: + self._ref = f"backend:{_uuid.uuid4().hex}" + self._opts: dict[str, Any] = dict(activity_options or {}) + self._opts.setdefault("start_to_close_timeout", timedelta(minutes=1)) + register_backend(self._ref, inner) + # Balance the registration when this wrapper is garbage-collected + # (workflow completion / cache eviction) so per-run backends do not + # accumulate in the worker-global registry. The finalizer captures + # (ref, inner) — not ``self`` — so it cannot keep the wrapper alive, + # and it only removes its own registration (see _unregister_backend). + self._finalizer = weakref.finalize(self, _unregister_backend, self._ref, inner) + + async def _dispatch(self, op: str, *args: Any, **kwargs: Any) -> Any: + from temporalio.contrib.deepagents.workflow import call_backend_op + + activity_input = _activity.BackendOpInput( + backend_ref=self._ref, + op=op, + args=list(args), + kwargs=dict(kwargs), + ) + output = await call_backend_op( + activity_input, + summary=f"backend:{op}", + **self._opts, + ) + return _serde.load_backend_result(output.result) + + def __getattr__(self, name: str) -> Any: + """Bound-method access for a known I/O op returns an activity dispatcher. + + Everything else forwards to the inner backend unchanged. + """ + if name in _BACKEND_OPS: + + async def _op(*args: Any, **kwargs: Any) -> Any: + return await self._dispatch(name, *args, **kwargs) + + return _op + return getattr(self._inner, name) diff --git a/temporalio/contrib/deepagents/py.typed b/temporalio/contrib/deepagents/py.typed new file mode 100644 index 000000000..e69de29bb diff --git a/temporalio/contrib/deepagents/testing.py b/temporalio/contrib/deepagents/testing.py new file mode 100644 index 000000000..749b1ab96 --- /dev/null +++ b/temporalio/contrib/deepagents/testing.py @@ -0,0 +1,141 @@ +"""Test helpers for users adopting :class:`DeepAgentsPlugin`. + +Unit-testing a Deep Agent under Temporal should not require a live LLM endpoint +or a paid API key. This module ships: + +* :class:`FakeModel` — a real ``BaseChatModel`` returning scripted replies (plain + text or full ``AIMessage`` objects carrying ``tool_calls``), cycling when + exhausted; +* :func:`fake_model_factory` — a one-liner for the common text-only case; +* :func:`mock_model_provider` — a ``model_provider`` (name → model) you pass to + ``DeepAgentsPlugin(model_provider=...)`` so the model activity runs offline; +* :class:`MockTool` — a scripted ``BaseTool`` for exercising the tool seam. + +Importing this module has no process-wide side effects. +""" + +from __future__ import annotations + +from collections.abc import Callable, Sequence +from typing import Any + +from langchain_core.callbacks import ( + AsyncCallbackManagerForLLMRun, + CallbackManagerForLLMRun, +) +from langchain_core.language_models.chat_models import BaseChatModel +from langchain_core.messages import AIMessage, BaseMessage +from langchain_core.outputs import ChatGeneration, ChatResult +from langchain_core.tools import BaseTool +from pydantic import PrivateAttr + +__all__ = ["FakeModel", "fake_model_factory", "mock_model_provider", "MockTool"] + +Response = str | AIMessage + + +class FakeModel(BaseChatModel): + """A ``BaseChatModel`` returning scripted responses, for offline tests. + + Args: + responses: Replies returned one per call, cycling when exhausted. Each is + either a string (becomes an ``AIMessage``) or an ``AIMessage`` (so you + can script ``tool_calls`` to drive the agent's tool path). + """ + + responses: list[Any] + _cursor: int = PrivateAttr(default=0) + + def __init__(self, responses: Sequence[Response], **kwargs: Any) -> None: + """Validate and store the scripted responses.""" + resp = list(responses) + if not resp: + raise ValueError("FakeModel needs at least one scripted response.") + super().__init__(responses=resp, **kwargs) # type: ignore[call-arg] + + @property + def _llm_type(self) -> str: + return "temporalio-deepagents-fake-model" + + def bind_tools(self, tools: Sequence[Any], **kwargs: Any) -> "FakeModel": + """Ignore the tool set; the fake just replays its script. + + Returning ``self`` keeps ``model.bind_tools(...)`` chainable like a + real model. + """ + return self + + def _next(self) -> AIMessage: + item = self.responses[self._cursor % len(self.responses)] + self._cursor += 1 + return item if isinstance(item, AIMessage) else AIMessage(content=item) + + def _generate( + self, + messages: list[BaseMessage], + stop: list[str] | None = None, + run_manager: CallbackManagerForLLMRun | None = None, + **kwargs: Any, + ) -> ChatResult: + return ChatResult(generations=[ChatGeneration(message=self._next())]) + + async def _agenerate( + self, + messages: list[BaseMessage], + stop: list[str] | None = None, + run_manager: AsyncCallbackManagerForLLMRun | None = None, + **kwargs: Any, + ) -> ChatResult: + return ChatResult(generations=[ChatGeneration(message=self._next())]) + + +def fake_model_factory(responses: Sequence[Response]) -> FakeModel: + """One-liner scripted fake chat model. + + Example:: + + model = fake_model_factory(["The capital of France is Paris."]) + """ + return FakeModel(responses) + + +def mock_model_provider( + responses: Sequence[Response], +) -> Callable[[str], FakeModel]: + """A ``model_provider`` that hands out the scripted responses one call at a time. + + Each model activity invocation (main agent, a sub-agent, a follow-up turn + after a tool call) advances through ``responses`` and cycles when exhausted, + so a multi-turn agent can be scripted deterministically. The model activity + builds a fresh model per call, so the cursor lives on the provider closure + (shared for the worker's lifetime) rather than on any one model instance. + + Pass to the plugin so the model activity runs offline:: + + plugin = DeepAgentsPlugin(model_provider=mock_model_provider(["Paris."])) + """ + resp = list(responses) + if not resp: + raise ValueError("mock_model_provider needs at least one response.") + cursor = {"i": 0} + + def provider(_model_name: str) -> FakeModel: + reply = resp[cursor["i"] % len(resp)] + cursor["i"] += 1 + return FakeModel([reply]) + + return provider + + +class MockTool(BaseTool): + """A scripted ``BaseTool`` whose call returns a fixed value, for tests.""" + + name: str = "mock_tool" + description: str = "A mock tool that returns a scripted result." + result: Any = "ok" + + def _run(self, *args: Any, **kwargs: Any) -> Any: + return self.result + + async def _arun(self, *args: Any, **kwargs: Any) -> Any: + return self.result diff --git a/temporalio/contrib/deepagents/workflow.py b/temporalio/contrib/deepagents/workflow.py new file mode 100644 index 000000000..cb3e45b03 --- /dev/null +++ b/temporalio/contrib/deepagents/workflow.py @@ -0,0 +1,317 @@ +"""Workflow-side surface: the failure type, the dispatch helpers, and the runner. + +Everything here runs *inside* the workflow. The dispatch helpers +(:func:`call_model` / :func:`call_tool` / :func:`call_backend_op`) are the single +choke point through which the in-workflow model / tool / backend stubs reach +their activities; they also consult the continue-as-new result cache so work +done before a ``continue_as_new`` is reused rather than repeated after it. + +:func:`run_deep_agent` is the optional driver that adds continue-as-new +state-carry around a native ``agent.ainvoke(...)`` — plain ``agent.ainvoke(...)`` +still works without it. +""" + +from __future__ import annotations + +import importlib +import warnings +from collections.abc import Mapping +from typing import Any + +from temporalio import workflow +from temporalio.contrib.deepagents import _activity, _serde +from temporalio.exceptions import ApplicationError + +# Reserved key under which the CAN result cache rides inside a state snapshot. +_CACHE_KEY = "__temporal_cache__" + +# Checkpointer classes that keep their state in the workflow's own memory and are +# therefore rehydrated for free by deterministic replay. Anything else does its +# own I/O and is not replay-safe from inside the workflow. +_IN_WORKFLOW_SAVERS = frozenset({"InMemorySaver", "MemorySaver"}) + + +def warn_durable_checkpointer(checkpointer: Any) -> None: + """Warn when a user hands ``create_deep_agent`` a durable checkpointer. + + The Deep Agents loop runs inside the workflow, so a checkpointer that does + its own database / disk I/O would run that I/O from workflow code — not + replay-safe. We respect the user's choice (a warning, not a hard failure), + and point them at the durability path that *is* safe: the default in-workflow + ``InMemorySaver`` rehydrated by replay, plus + :func:`run_deep_agent` with ``continue_as_new_after`` for long conversations. + """ + if checkpointer is None: + return + if type(checkpointer).__name__ in _IN_WORKFLOW_SAVERS: + return + warnings.warn( + f"create_deep_agent received a durable checkpointer " + f"{type(checkpointer).__name__!r}. The agent loop runs inside the " + f"workflow, so this checkpointer's I/O would run from workflow code, " + f"which is not replay-safe. Prefer the default in-workflow InMemorySaver " + f"(rehydrated by replay) plus run_deep_agent(continue_as_new_after=...) " + f"for long-conversation durability.", + stacklevel=3, + ) + + +class DeepAgentsWorkflowError(ApplicationError): + """Raised for non-retryable Deep Agents failures surfaced in the workflow. + + This is the type registered in the plugin's + ``workflow_failure_exception_types``, so a model / tool failure that Temporal + has exhausted (or an invalid agent configuration) fails the workflow with a + stable ``ApplicationError.type`` — never a stringified peer exception. + """ + + TYPE = "deepagents.DeepAgentsWorkflowError" + + def __init__(self, message: str, *, non_retryable: bool = True) -> None: + """Construct the error with the plugin's stable failure ``type``.""" + super().__init__(message, type=self.TYPE, non_retryable=non_retryable) + + +# --------------------------------------------------------------------------- +# Dispatch helpers (the model / tool / backend choke point) +# --------------------------------------------------------------------------- + + +async def call_model( + activity_name: str, + activity_input: _activity.ModelActivityInput, + *, + summary: str, + **opts: Any, +) -> _activity.ModelActivityOutput: + """Dispatch one model call, reusing a cached result across continue-as-new.""" + key = _serde.cache_key( + "model", + activity_input.model_name, + [activity_input.messages, activity_input.tool_schemas], + ) + hit, cached = _serde.cache_lookup(key) + if hit: + return _activity.ModelActivityOutput(message=cached) + output = await workflow.execute_activity( + activity_name, + activity_input, + result_type=_activity.ModelActivityOutput, + summary=summary, + **opts, + ) + _serde.cache_put(key, output.message) + return output + + +async def call_tool( + activity_input: _activity.ToolActivityInput, + *, + summary: str, + **opts: Any, +) -> _activity.ToolActivityOutput: + """Dispatch one tool call, reusing a cached result across continue-as-new.""" + key = _serde.cache_key("tool", activity_input.tool_name, activity_input.args) + hit, cached = _serde.cache_lookup(key) + if hit: + return _activity.ToolActivityOutput(message=cached) + output = await workflow.execute_activity( + _activity.INVOKE_TOOL, + activity_input, + result_type=_activity.ToolActivityOutput, + summary=summary, + **opts, + ) + _serde.cache_put(key, output.message) + return output + + +async def call_backend_op( + activity_input: _activity.BackendOpInput, + *, + summary: str, + **opts: Any, +) -> _activity.BackendOpOutput: + """Dispatch one backend op, reusing a cached result across continue-as-new.""" + key = _serde.cache_key( + f"backend:{activity_input.backend_ref}", + activity_input.op, + [activity_input.args, activity_input.kwargs], + ) + hit, cached = _serde.cache_lookup(key) + if hit: + return _activity.BackendOpOutput(result=cached) + output = await workflow.execute_activity( + _activity.BACKEND_OP, + activity_input, + result_type=_activity.BackendOpOutput, + summary=summary, + **opts, + ) + _serde.cache_put(key, output.result) + return output + + +# --------------------------------------------------------------------------- +# run_deep_agent (continue-as-new state carry) +# --------------------------------------------------------------------------- + + +def _merge_snapshot(input: Any, snapshot: Mapping[str, Any]) -> Any: + """Prepend a snapshot's carried messages onto the next turn's input.""" + raw_prior: Any = snapshot.get("messages") or [] + prior = list(raw_prior) + if not prior: + return input + if isinstance(input, Mapping): + merged = dict(input) + raw_next: Any = input.get("messages") or [] + merged["messages"] = [*prior, *list(raw_next)] + return merged + return {"messages": [*prior, *_as_message_list(input)]} + + +def _as_message_list(input: Any) -> list[Any]: + if isinstance(input, (list, tuple)): + return list(input) + return [input] + + +async def run_deep_agent( + agent: Any, + input: Any, + *, + continue_as_new_after: int | None = None, + state_snapshot: Mapping[str, Any] | None = None, +) -> Any: + """Drive ``agent.ainvoke(input)`` with continue-as-new state carry. + + Once the completed turn leaves pending todos AND history has grown past the + limit, the turn's state (messages + the model/tool result cache) is + snapshotted and carried into a fresh run via ``workflow.continue_as_new``, + so long conversations do not accumulate unbounded history. + + By default (``continue_as_new_after=None``) the limit is the server's own + recommendation — ``workflow.info().is_continue_as_new_suggested()`` — which + accounts for both history length and size; this is the recommended mode. + Pass an explicit ``continue_as_new_after=N`` to trigger on a fixed history + event count instead. To run an agent with NO continue-as-new behavior, call + ``agent.ainvoke(...)`` directly rather than using this driver. + + The enclosing ``@workflow.run`` method must accept the continued call — i.e. + its signature is ``(input, state_snapshot=None)`` — because that is how the + carried state is threaded into the next run. + """ + # Resume path: rehydrate the result cache and fold carried messages in. + if state_snapshot is not None: + _serde.set_result_cache(dict(state_snapshot.get(_CACHE_KEY) or {})) + input = _merge_snapshot(input, state_snapshot) + else: + _serde.set_result_cache({}) + + try: + result = await agent.ainvoke(input) + except ApplicationError: + raise + except Exception as exc: + # If the framework wrapped a Temporal failure, surface the registered + # workflow-failure type rather than the framework's generic exception. + cause = exc.__cause__ + if cause is not None and workflow.is_failure_exception(cause): + raise DeepAgentsWorkflowError(f"Deep Agents run failed: {exc}") from cause + raise + + if continue_as_new_after is None: + # Default: follow the server's judgement. The suggestion accounts for + # history count AND size limits, which a fixed event threshold cannot. + should_continue = workflow.info().is_continue_as_new_suggested() + else: + should_continue = ( + workflow.info().get_current_history_length() >= continue_as_new_after + ) + if should_continue and _has_pending_work(result): + snapshot = { + "messages": _extract_messages(result), + _CACHE_KEY: _serde.result_cache_snapshot() or {}, + } + # ``continue_as_new`` threads positional args into the next run via + # ``args=``; the enclosing ``@workflow.run`` receives them as + # ``(input, state_snapshot)``. + workflow.continue_as_new(args=[input, snapshot]) + + return result + + +def _extract_messages(result: Any) -> list[Any]: + if isinstance(result, Mapping): + raw: Any = result.get("messages") or [] + return list(raw) + return [] + + +def _has_pending_work(result: Any) -> bool: + """True when the agent left unfinished todos worth carrying past a CAN. + + A finished single-shot run has no pending todos, so this returns False and the + driver returns the result instead of looping on continue-as-new forever. + """ + if isinstance(result, Mapping): + todos: Any = result.get("todos") or [] + return any( + isinstance(t, Mapping) and t.get("status") not in ("completed", "done") + for t in todos + ) + return False + + +def create_temporal_deep_agent( + *args: Any, + activity_options: Mapping[str, Any] | None = None, + **kwargs: Any, +) -> Any: + """Build a Deep Agent whose model calls run as durable activities. + + A thin wrapper over ``deepagents.create_deep_agent`` that makes the + Temporal wiring explicit: a ``model=`` name string is wrapped in + ``TemporalModel`` carrying this + agent's ``activity_options`` (``execute_activity`` overrides — timeouts, + retry policy — for its model calls). Every other argument — tools, + backend, sub-agents, ``interrupt_on`` — is forwarded unchanged. + + Unmodified ``create_deep_agent(...)`` also works inside a workflow (the + plugin substitutes the durable model automatically, using the plugin's + ``model_activity_options``); use this wrapper to scope activity options + to one agent instead of configuring them plugin-wide. + """ + with workflow.unsafe.imports_passed_through(): + # importlib keeps this resolution absolute: a static + # `import deepagents` from inside this same-named package directory + # is flagged (and on 3.10, mis-resolved) as implicitly relative. + deepagents_mod: Any = importlib.import_module("deepagents") + + from temporalio.contrib.deepagents._model import TemporalModel + + model = args[0] if args else kwargs.pop("model", None) + if isinstance(model, str): + model = TemporalModel( + model=model, + activity_options=( + dict(activity_options) if activity_options is not None else None + ), + ) + elif activity_options is not None: + if isinstance(model, TemporalModel): + model = TemporalModel( + model=model.model, activity_options=dict(activity_options) + ) + else: + raise ValueError( + "activity_options requires model= to be a model-name string " + "or a TemporalModel; got " + f"{type(model).__name__ if model is not None else 'no model'}." + ) + if args: + args = (model, *args[1:]) + else: + kwargs["model"] = model + return deepagents_mod.create_deep_agent(*args, **kwargs) diff --git a/tests/contrib/deepagents/__init__.py b/tests/contrib/deepagents/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/tests/contrib/deepagents/helpers.py b/tests/contrib/deepagents/helpers.py new file mode 100644 index 000000000..eb5ba295b --- /dev/null +++ b/tests/contrib/deepagents/helpers.py @@ -0,0 +1,16 @@ +"""Shared helpers for the Deep Agents plugin test suite.""" + +from collections import Counter + +from temporalio.api.enums.v1 import EventType +from temporalio.client import WorkflowHandle + + +async def count_scheduled_activities(handle: WorkflowHandle) -> Counter: + """Count ``ActivityTaskScheduled`` events by activity-type name.""" + counts: Counter = Counter() + async for event in handle.fetch_history_events(): + if event.event_type == EventType.EVENT_TYPE_ACTIVITY_TASK_SCHEDULED: + name = event.activity_task_scheduled_event_attributes.activity_type.name + counts[name] += 1 + return counts diff --git a/tests/contrib/deepagents/test_backends.py b/tests/contrib/deepagents/test_backends.py new file mode 100644 index 000000000..b32a6f12b --- /dev/null +++ b/tests/contrib/deepagents/test_backends.py @@ -0,0 +1,315 @@ +"""``TemporalBackend`` routes real-I/O backend ops through activities. + +A backend that touches disk or a shell must not run its operations from workflow +code. ``TemporalBackend`` wraps such a backend so each op becomes a +``deepagents.backend_op`` activity. The wrapped backend here is a plain object +(no LangChain / deepagents needed), so this boots a real server and proves the +op crosses the activity boundary. + +A state-only backend needs no wrapping — that path is covered against the real +``deepagents.StateBackend`` when it is importable. +""" + +from __future__ import annotations + +import gc +import sys +import uuid +from datetime import timedelta +from pathlib import Path + +import pytest + +from temporalio.testing import WorkflowEnvironment + +pytestmark = pytest.mark.skipif( + sys.version_info < (3, 11), reason="deepagents requires Python >= 3.11" +) +pytest.importorskip("deepagents") +pytest.importorskip("langchain_core") + +from temporalio import workflow +from temporalio.contrib.deepagents import DeepAgentsPlugin, TemporalBackend +from temporalio.contrib.deepagents._tools import ( + register_backend, + registered_backends, +) +from temporalio.worker import Worker +from tests.contrib.deepagents.helpers import count_scheduled_activities + +BACKEND_OP = "deepagents.backend_op" + + +class RecordingBackend: + """A minimal backend doing 'real' work off-workflow, exposing both halves + of the deepagents backend protocol: a sync op (``read``) and its async + twin (``aread``). The async twin is the regression-critical case — + deepagents' filesystem middleware calls ``aread``/``awrite``/…, and an + earlier op list intercepted only sync names, so agent-driven file tools + ran their I/O in-workflow.""" + + def read(self, file_path: str) -> str: + return f"contents of {file_path}" + + async def aread(self, file_path: str) -> str: + return f"acontents of {file_path}" + + +@workflow.defn +class BackendWorkflow: + @workflow.run + async def run(self, path: str) -> str: + backend = TemporalBackend( + RecordingBackend(), + activity_options={"start_to_close_timeout": timedelta(seconds=10)}, + ) + sync_out = await backend.read(path) + async_out = await backend.aread(path) + return f"{sync_out}|{async_out}" + + +# Bind deepagents symbols off the module importorskip returns: a static +# `from deepagents import ...` cannot resolve on Python 3.10 (deepagents +# needs >= 3.11), and with the package absent the type checkers mis-resolve +# the name against this same-named test directory. +_deepagents_mod = pytest.importorskip("deepagents") +_backends_mod = pytest.importorskip("deepagents.backends") +create_deep_agent = _deepagents_mod.create_deep_agent +FilesystemBackend = _backends_mod.FilesystemBackend +StateBackend = _backends_mod.StateBackend + + +# A state-only backend is pure workflow state and must NOT schedule an activity. +@workflow.defn +class StateBackendWorkflow: + @workflow.run + async def run(self) -> str: + backend = StateBackend() + # Merely holding a StateBackend schedules no activity; it is not + # wrapped. Return the class provenance so the assertion is on a real + # runtime property rather than a statically-decidable comparison. + return type(backend).__module__ + + +# The full agent-level seam: a REAL Deep Agent whose BUILT-IN file tools drive a +# REAL FilesystemBackend through TemporalBackend. This is the path a fake-backend +# test cannot cover: deepagents' filesystem middleware calls the ASYNC protocol +# (`awrite` / `aread`), and the ops return protocol dataclasses (WriteResult / +# ReadResult) that must survive the activity boundary as real objects — the +# middleware reads their attributes in-workflow. +@workflow.defn +class FilesystemAgentWorkflow: + @workflow.run + async def run(self, root_dir: str) -> str: + backend = TemporalBackend( + FilesystemBackend(root_dir=root_dir, virtual_mode=True), + activity_options={"start_to_close_timeout": timedelta(seconds=10)}, + ) + agent = create_deep_agent( + model="anthropic:claude-sonnet-4-5", + backend=backend, + system_prompt="Write the note, read it back, then report it.", + ) + result = await agent.ainvoke( + {"messages": [{"role": "user", "content": "Note 'hello' down."}]} + ) + return str(result["messages"][-1].content) + + +@pytest.mark.asyncio +async def test_temporal_backend_op_activity(env: WorkflowEnvironment) -> None: + plugin = DeepAgentsPlugin() + async with Worker( + env.client, + task_queue="da-backend", + workflows=[BackendWorkflow], + plugins=[plugin], + ): + handle = await env.client.start_workflow( + BackendWorkflow.run, + "notes.txt", + id=f"da-backend-{uuid.uuid4()}", + task_queue="da-backend", + ) + out = await handle.result() + + assert out == "contents of notes.txt|acontents of notes.txt" + counts = await count_scheduled_activities(handle) + # One activity per op — the sync read AND the async aread both cross. + assert counts[BACKEND_OP] == 2, counts + + +def test_temporal_backend_unregisters_on_gc() -> None: + # A wrapper is typically constructed per workflow run; its registry entry + # must not outlive it, or a long-lived worker leaks one entry per run. + inner = RecordingBackend() + before = set(registered_backends()) + wrapper = TemporalBackend(inner) + (ref,) = set(registered_backends()) - before + assert registered_backends()[ref] is inner + del wrapper + gc.collect() + assert ref not in registered_backends() + + +def test_temporal_backend_gc_keeps_reregistered_ref() -> None: + # Refs are deterministic per run: after a cache eviction, a replay + # re-registers the SAME ref with a fresh inner backend. The evicted + # wrapper's GC cleanup must leave that live registration alone. + before = set(registered_backends()) + wrapper = TemporalBackend(RecordingBackend()) + (ref,) = set(registered_backends()) - before + replacement = RecordingBackend() + register_backend(ref, replacement) + del wrapper + gc.collect() + assert registered_backends().get(ref) is replacement + registered_backends().pop(ref, None) + + +@pytest.mark.asyncio +async def test_state_backend_in_workflow(env: WorkflowEnvironment) -> None: + # A state-only backend is pure workflow state and must NOT schedule an + # activity. Exercised against the real StateBackend when deepagents is present. + plugin = DeepAgentsPlugin() + async with Worker( + env.client, + task_queue="da-state-backend", + workflows=[StateBackendWorkflow], + plugins=[plugin], + ): + handle = await env.client.start_workflow( + StateBackendWorkflow.run, + id=f"da-state-backend-{uuid.uuid4()}", + task_queue="da-state-backend", + ) + assert (await handle.result()).startswith("deepagents") + counts = await count_scheduled_activities(handle) + assert counts[BACKEND_OP] == 0, counts + + +@pytest.mark.asyncio +async def test_agent_builtin_file_tools_route_backend_ops( + env: WorkflowEnvironment, tmp_path: Path +) -> None: + """An unmodified agent's built-in write_file/read_file tools cross the + activity boundary when the backend is TemporalBackend-wrapped — under + ``max_cached_workflows=0``, so every workflow task replays from history. + + Regression: an earlier op list intercepted only sync method names, so the + middleware's async calls (`awrite`/`aread`) forwarded to the inner backend + and ran real disk I/O in-workflow. This test fails if that recurs, if the + protocol result dataclasses stop surviving the activity boundary, or if + replay diverges. + """ + from langchain_core.messages import AIMessage # real lib; guarded above + + write_turn = AIMessage( + content="", + tool_calls=[ + { + "name": "write_file", + "args": {"file_path": "/notes.txt", "content": "hello"}, + "id": "call-write", + } + ], + ) + read_turn = AIMessage( + content="", + tool_calls=[ + { + "name": "read_file", + "args": {"file_path": "/notes.txt"}, + "id": "call-read", + } + ], + ) + final = AIMessage(content="The note says: hello") + from temporalio.contrib.deepagents.testing import mock_model_provider + + plugin = DeepAgentsPlugin( + model_provider=mock_model_provider([write_turn, read_turn, final]), + ) + async with Worker( + env.client, + task_queue="da-fs-agent", + workflows=[FilesystemAgentWorkflow], + plugins=[plugin], + max_cached_workflows=0, + ): + handle = await env.client.start_workflow( + FilesystemAgentWorkflow.run, + str(tmp_path), + id=f"da-fs-agent-{uuid.uuid4()}", + task_queue="da-fs-agent", + ) + out = await handle.result() + + assert "hello" in out + # The write really happened on disk — in the activity, not the workflow. + assert (tmp_path / "notes.txt").read_text() == "hello" + counts = await count_scheduled_activities(handle) + # Exactly one backend_op per file tool call (awrite + aread), three model turns. + assert counts[BACKEND_OP] == 2, counts + assert counts["deepagents.invoke_model"] == 3, counts + + +@workflow.defn +class DefaultBackendGrepWorkflow: + @workflow.run + async def run(self, prompt: str) -> str: + # No backend argument: deepagents uses its default state-only backend. + agent = create_deep_agent(model="anthropic:claude-sonnet-4-5") + result = await agent.ainvoke( + {"messages": [{"role": "user", "content": prompt}]} + ) + return str(result["messages"][-1].content) + + +@pytest.mark.asyncio +async def test_builtin_tool_on_default_backend_runs_in_workflow( + env: WorkflowEnvironment, +) -> None: + """A built-in tool call (grep) on the DEFAULT state backend runs inline + in the workflow — no activity, no thread hop — under + ``max_cached_workflows=0`` so every task replays from history. + + Regression: ``BackendProtocol``'s async defaults wrap their sync twins in + ``asyncio.to_thread``, which the deterministic workflow event loop + rejects with ``NotImplementedError``. A real model's first spontaneous + ``grep``/``read_file`` call crashed the workflow task; scripted tests + that never invoked built-ins on the default backend sailed past it. The + plugin now runs the sync twin inline when ``workflow.in_workflow()``. + """ + from langchain_core.messages import AIMessage + + from temporalio.contrib.deepagents.testing import mock_model_provider + + grep_turn = AIMessage( + content="", + tool_calls=[{"name": "grep", "args": {"pattern": "hello"}, "id": "call-grep"}], + ) + final = AIMessage(content="No matches found; done.") + plugin = DeepAgentsPlugin( + model_provider=mock_model_provider([grep_turn, final]), + ) + async with Worker( + env.client, + task_queue="da-default-backend", + workflows=[DefaultBackendGrepWorkflow], + plugins=[plugin], + max_cached_workflows=0, + ): + handle = await env.client.start_workflow( + DefaultBackendGrepWorkflow.run, + "Grep the workspace for 'hello'.", + id=f"da-default-backend-{uuid.uuid4()}", + task_queue="da-default-backend", + ) + out = await handle.result() + + assert "done" in out + counts = await count_scheduled_activities(handle) + # The state-backend op stays in-workflow: model turns are the ONLY activities. + assert counts[BACKEND_OP] == 0, counts + assert counts["deepagents.invoke_model"] == 2, counts diff --git a/tests/contrib/deepagents/test_checkpointer.py b/tests/contrib/deepagents/test_checkpointer.py new file mode 100644 index 000000000..851bbb018 --- /dev/null +++ b/tests/contrib/deepagents/test_checkpointer.py @@ -0,0 +1,98 @@ +"""Checkpointing follows the ``contrib.langgraph`` precedent. + +The zero-config default is an in-workflow ``InMemorySaver`` rehydrated by +deterministic replay; no bespoke checkpointer adapter ships. A user-supplied +durable checkpointer would run its own I/O from workflow code, which is not +replay-safe, so the plugin warns (respecting the choice rather than hard-failing) +and points at the snapshot + continue-as-new path. +""" + +from __future__ import annotations + +import sys +import uuid +import warnings + +import pytest + +from temporalio.testing import WorkflowEnvironment + +pytestmark = pytest.mark.skipif( + sys.version_info < (3, 11), reason="deepagents requires Python >= 3.11" +) +pytest.importorskip("deepagents") +pytest.importorskip("langchain_core") + +from temporalio import workflow +from temporalio.contrib.deepagents.workflow import warn_durable_checkpointer + +# Bind deepagents symbols off the module importorskip returns: a static +# `from deepagents import ...` cannot resolve on Python 3.10 (deepagents +# needs >= 3.11), and with the package absent the type checkers mis-resolve +# the name against this same-named test directory. +create_deep_agent = pytest.importorskip("deepagents").create_deep_agent + + +class _DurableSaver: + """Stand-in for a checkpointer that does its own database I/O.""" + + +class InMemorySaver: + """Same class name LangGraph's in-workflow saver uses.""" + + +@workflow.defn +class CheckpointWorkflow: + @workflow.run + async def run(self, prompt: str) -> str: + agent = create_deep_agent(model="fake:model") + result = await agent.ainvoke( + {"messages": [{"role": "user", "content": prompt}]} + ) + return str(result["messages"][-1].content) + + +def test_durable_checkpointer_warns() -> None: + # None and in-workflow savers are silent... + with warnings.catch_warnings(record=True) as records: + warnings.simplefilter("always") + warn_durable_checkpointer(None) + warn_durable_checkpointer(InMemorySaver()) + assert not records, [str(r.message) for r in records] + + # ...a durable saver warns (respect the choice, do not hard-fail). + with pytest.warns(UserWarning, match="durable checkpointer"): + warn_durable_checkpointer(_DurableSaver()) + + +@pytest.mark.asyncio +async def test_default_saver_rehydrates(env: WorkflowEnvironment) -> None: + # Against the real deepagents default (in-workflow InMemorySaver): the agent + # runs and its recorded history replays cleanly, proving replay rehydrates + # the in-workflow checkpoint state with no external checkpointer. + pytest.importorskip("deepagents") + pytest.importorskip("langchain_core") + + from temporalio.contrib.deepagents import DeepAgentsPlugin + from temporalio.contrib.deepagents.testing import mock_model_provider + from temporalio.worker import Replayer, Worker + + plugin = DeepAgentsPlugin(model_provider=mock_model_provider(["Checkpointed."])) + async with Worker( + env.client, + task_queue="da-ckpt", + workflows=[CheckpointWorkflow], + plugins=[plugin], + ): + handle = await env.client.start_workflow( + CheckpointWorkflow.run, + "hello", + id=f"da-ckpt-{uuid.uuid4()}", + task_queue="da-ckpt", + ) + await handle.result() + history = await handle.fetch_history() + + await Replayer( + workflows=[CheckpointWorkflow], plugins=[DeepAgentsPlugin()] + ).replay_workflow(history) diff --git a/tests/contrib/deepagents/test_continue_as_new.py b/tests/contrib/deepagents/test_continue_as_new.py new file mode 100644 index 000000000..c5add7cf7 --- /dev/null +++ b/tests/contrib/deepagents/test_continue_as_new.py @@ -0,0 +1,167 @@ +"""Continue-as-new state carry for long-running Deep Agents. + +``run_deep_agent(continue_as_new_after=...)`` keeps a long conversation from +bloating workflow history: once the current turn finishes past the threshold and +there is still pending work, it snapshots the accumulated messages plus the +model/tool result cache and continues into a fresh run. These tests use a plain +fake agent (no LangChain needed) so they boot a real Temporal server and exercise +the continue-as-new machinery end to end. +""" + +from __future__ import annotations + +import sys +import uuid +from typing import Any + +import pytest + +from temporalio.testing import WorkflowEnvironment + +pytestmark = pytest.mark.skipif( + sys.version_info < (3, 11), reason="deepagents requires Python >= 3.11" +) +from temporalio import workflow +from temporalio.contrib.deepagents import DeepAgentsPlugin, _serde, run_deep_agent +from temporalio.worker import Worker + + +class FakeAgent: + """A stand-in compiled agent that appends a step and reports a todo. + + It is *not* a LangChain object — it just satisfies the ``ainvoke`` shape + ``run_deep_agent`` drives, so the continue-as-new path can be tested without + a model provider or the LangChain import tree. + """ + + async def ainvoke(self, input: Any) -> dict: + messages = list(input.get("messages", [])) if isinstance(input, dict) else [] + messages = [*messages, "step"] + done = len(messages) >= 3 + return { + "messages": messages, + "todos": [ + {"content": "work", "status": "completed" if done else "pending"} + ], + } + + +@workflow.defn +class ContinueAsNewWorkflow: + @workflow.run + async def run(self, input: dict, state_snapshot: dict | None = None) -> dict: + # Threshold of 1 means: continue-as-new as soon as there is pending work, + # which the fake agent reports until the conversation reaches 3 messages. + return await run_deep_agent( + FakeAgent(), + input, + continue_as_new_after=1, + state_snapshot=state_snapshot, + ) + + +@pytest.mark.asyncio +async def test_can_threshold_and_cache(env: WorkflowEnvironment) -> None: + plugin = DeepAgentsPlugin() + async with Worker( + env.client, + task_queue="da-can", + workflows=[ContinueAsNewWorkflow], + plugins=[plugin], + ): + handle = await env.client.start_workflow( + ContinueAsNewWorkflow.run, + {"messages": ["start"]}, + id=f"da-can-{uuid.uuid4()}", + task_queue="da-can", + ) + result = await handle.result() + + # The only way the conversation reaches >= 3 messages is if the snapshot from + # the pre-continue-as-new run was carried into the continued run and merged. + assert len(result["messages"]) >= 3, result + assert result["todos"][0]["status"] == "completed" + + +def test_state_snapshot_roundtrip() -> None: + # The result cache carried in a snapshot rehydrates to the same hits, so work + # done before a continue-as-new is reused, not recomputed, afterwards. + _serde.set_result_cache({}) + key = _serde.cache_key("model", "fake:model", [["m"], []]) + _serde.cache_put(key, {"dumped": "message"}) + snapshot = _serde.result_cache_snapshot() + assert snapshot and key in snapshot + + # Simulate the continued run: a fresh cache seeded from the snapshot. + _serde.set_result_cache(dict(snapshot)) + hit, value = _serde.cache_lookup(key) + assert hit and value == {"dumped": "message"} + + +class SlowFakeAgent: + """Like ``FakeAgent`` but each turn burns timers so a single run's history + grows past the dev server's continue-as-new suggestion threshold (the test + env pins ``limit.historyCount.suggestContinueAsNew`` low).""" + + async def ainvoke(self, input: Any) -> dict: + for _ in range(20): + await workflow.sleep(0.001) + messages = list(input.get("messages", [])) if isinstance(input, dict) else [] + messages = [*messages, "step"] + done = len(messages) >= 3 + return { + "messages": messages, + "todos": [ + {"content": "work", "status": "completed" if done else "pending"} + ], + } + + +@workflow.defn +class SuggestedCanWorkflow: + @workflow.run + async def run(self, input: dict, state_snapshot: dict | None = None) -> dict: + # No continue_as_new_after: the default follows the server's own + # is_continue_as_new_suggested() signal. + return await run_deep_agent( + SlowFakeAgent(), + input, + state_snapshot=state_snapshot, + ) + + +@pytest.mark.asyncio +async def test_can_defaults_to_server_suggestion( + env: WorkflowEnvironment, env_type: str +) -> None: + """With ``continue_as_new_after`` unset, the driver continues-as-new when + the SERVER suggests it (history count/size), not on a fixed threshold.""" + if env_type != "local": + pytest.skip("needs the local dev server's low suggestContinueAsNew threshold") + plugin = DeepAgentsPlugin() + async with Worker( + env.client, + task_queue="da-can-suggested", + workflows=[SuggestedCanWorkflow], + plugins=[plugin], + ): + handle = await env.client.start_workflow( + SuggestedCanWorkflow.run, + {"messages": ["start"]}, + id=f"da-can-suggested-{uuid.uuid4()}", + task_queue="da-can-suggested", + ) + result = await handle.result() + + # Carry across the suggested continue-as-new: the conversation only reaches + # 3 messages if snapshots crossed run boundaries. + assert len(result["messages"]) >= 3, result + assert result["todos"][0]["status"] == "completed" + # The first run really did continue-as-new (not complete). + first = env.client.get_workflow_handle( + handle.id, run_id=handle.first_execution_run_id + ) + desc = await first.describe() + assert desc.status is not None and desc.status.name == "CONTINUED_AS_NEW", ( + desc.status + ) diff --git a/tests/contrib/deepagents/test_failures.py b/tests/contrib/deepagents/test_failures.py new file mode 100644 index 000000000..6cfe6e5ff --- /dev/null +++ b/tests/contrib/deepagents/test_failures.py @@ -0,0 +1,119 @@ +"""Error handling: retry classification and the workflow-failure type. + +Two dep-free paths run against a real server: the HTTP-error → Temporal retry +translation, and that a raised :class:`DeepAgentsWorkflowError` surfaces to the +client as a non-retryable failure with a stable ``ApplicationError.type`` (never +a stringified peer exception). The model-instance validation error needs +LangChain and guards on its import. +""" + +from __future__ import annotations + +import sys +import uuid +from datetime import timedelta + +import pytest + +from temporalio.testing import WorkflowEnvironment + +pytestmark = pytest.mark.skipif( + sys.version_info < (3, 11), reason="deepagents requires Python >= 3.11" +) +from temporalio import workflow +from temporalio.client import WorkflowFailureError +from temporalio.contrib.deepagents import DeepAgentsPlugin, DeepAgentsWorkflowError +from temporalio.contrib.deepagents._activity import _translate_api_error +from temporalio.exceptions import ApplicationError +from temporalio.worker import Worker + + +class _FakeResponse: + def __init__(self, headers: dict) -> None: + self.headers = headers + + +class _FakeHTTPError(Exception): + def __init__(self, status_code: int, headers: dict | None = None) -> None: + super().__init__(f"HTTP {status_code}") + self.status_code = status_code + self.response = _FakeResponse(headers or {}) + + +def test_error_classification() -> None: + # 429 is retryable and honors the upstream Retry-After. + err = _translate_api_error(_FakeHTTPError(429, {"retry-after": "7"})) + assert isinstance(err, ApplicationError) + assert err.non_retryable is False + assert err.next_retry_delay == timedelta(seconds=7) + + # 400 is a client error: non-retryable. + e400 = _translate_api_error(_FakeHTTPError(400)) + assert isinstance(e400, ApplicationError) + assert e400.non_retryable is True + + # 503 is retryable by default... + e503 = _translate_api_error(_FakeHTTPError(503)) + assert isinstance(e503, ApplicationError) + assert e503.non_retryable is False + # ...unless the server explicitly says not to. + forced = _translate_api_error(_FakeHTTPError(503, {"x-should-retry": "false"})) + assert isinstance(forced, ApplicationError) + assert forced.non_retryable is True + + # retry-after-ms wins over retry-after when both are present. + ms = _translate_api_error( + _FakeHTTPError(429, {"retry-after-ms": "250", "retry-after": "7"}) + ) + assert isinstance(ms, ApplicationError) + assert ms.next_retry_delay == timedelta(milliseconds=250) + + # A non-HTTP exception is not recognized, so the caller falls through. + assert _translate_api_error(ValueError("nope")) is None + + +@workflow.defn +class FailingWorkflow: + @workflow.run + async def run(self) -> None: + raise DeepAgentsWorkflowError("deliberate non-retryable failure") + + +@pytest.mark.asyncio +async def test_workflow_failure_type(env: WorkflowEnvironment) -> None: + plugin = DeepAgentsPlugin() + async with Worker( + env.client, + task_queue="da-fail", + workflows=[FailingWorkflow], + plugins=[plugin], + ): + handle = await env.client.start_workflow( + FailingWorkflow.run, + id=f"da-fail-{uuid.uuid4()}", + task_queue="da-fail", + ) + with pytest.raises(WorkflowFailureError) as excinfo: + await handle.result() + + cause = excinfo.value.cause + assert isinstance(cause, ApplicationError) + assert cause.type == "deepagents.DeepAgentsWorkflowError" + assert cause.non_retryable is True + + +@pytest.mark.asyncio +async def test_unwrappable_model_instance() -> None: + pytest.importorskip("langchain_core") + from langchain_core.language_models.fake_chat_models import FakeListChatModel + + # A string is auto-wrapped; a TemporalModel passes through; a live model + # instance is rejected at the workflow boundary with the typed failure. + from temporalio.contrib.deepagents import TemporalModel + from temporalio.contrib.deepagents._model import _wrap_model_arg + + assert isinstance(_wrap_model_arg("anthropic:claude"), TemporalModel) + tm = TemporalModel(model="anthropic:claude") + assert _wrap_model_arg(tm) is tm + with pytest.raises(DeepAgentsWorkflowError): + _wrap_model_arg(FakeListChatModel(responses=["hi"])) diff --git a/tests/contrib/deepagents/test_hitl.py b/tests/contrib/deepagents/test_hitl.py new file mode 100644 index 000000000..6124d41f1 --- /dev/null +++ b/tests/contrib/deepagents/test_hitl.py @@ -0,0 +1,139 @@ +"""Human-in-the-loop: SDK-native interrupt mapped to Query + Update. + +``interrupt_on={...}`` makes Deep Agents pause before a guarded tool runs. With a +checkpointer configured, LangGraph does *not* raise out of ``ainvoke`` — it +returns the current state with an ``__interrupt__`` entry describing the pending +approval (verified against deepagents 0.6.12 / langchain 1.x). Because the loop +runs in the workflow, that pause surfaces directly in workflow code. The plugin's +recommended mapping — used here — is: detect the returned ``__interrupt__``, +expose its payload via a Query, and resume with a Workflow Update carrying the +human's decision through ``Command(resume=...)``. No shim exception is invented; +the native LangGraph resume protocol (``{"decisions": [{"type": ...}]}``) is used +as-is. + +State lives on the workflow instance (per-execution), which is the idiomatic +Temporal pattern for state shared between the run method and its handlers. +""" + +from __future__ import annotations + +import asyncio +import sys +import uuid +from datetime import timedelta +from typing import Any + +import pytest + +from temporalio.testing import WorkflowEnvironment + +pytestmark = pytest.mark.skipif( + sys.version_info < (3, 11), reason="deepagents requires Python >= 3.11" +) + +pytest.importorskip("deepagents") +pytest.importorskip("langchain_core") +pytest.importorskip("langgraph") + +from temporalio import workflow # noqa: E402 +from temporalio.worker import Worker # noqa: E402 + +# Bind deepagents symbols off the module importorskip returns: a static +# `from deepagents import ...` cannot resolve on Python 3.10 (deepagents +# needs >= 3.11), and with the package absent the type checkers mis-resolve +# the name against this same-named test directory. +create_deep_agent = pytest.importorskip("deepagents").create_deep_agent + +with workflow.unsafe.imports_passed_through(): + from langchain_core.messages import AIMessage + from langchain_core.runnables import RunnableConfig + from langgraph.checkpoint.memory import InMemorySaver + from langgraph.types import Command + + from temporalio.contrib.deepagents import DeepAgentsPlugin, tool_as_activity + from temporalio.contrib.deepagents.testing import mock_model_provider + + +@workflow.defn +class HitlWorkflow: + def __init__(self) -> None: + self._interrupt: str | None = None + self._resume_value: str | None = None + self._resumed = False + + @workflow.run + async def run(self, city: str) -> str: + def book_trip(city: str) -> str: + """Book a trip to a city (requires human approval).""" + return f"Booked a trip to {city}." + + trip_tool = tool_as_activity( + book_trip, start_to_close_timeout=timedelta(seconds=30) + ) + agent = create_deep_agent( + model="anthropic:claude-sonnet-4-5", + tools=[trip_tool], + interrupt_on={"book_trip": True}, + checkpointer=InMemorySaver(), + ) + config: RunnableConfig = { + "configurable": {"thread_id": workflow.info().workflow_id} + } + payload: Any = {"messages": [{"role": "user", "content": f"Book {city}."}]} + result = await agent.ainvoke(payload, config=config) + # LangGraph returns (not raises) the pending approval under __interrupt__. + pending = result.get("__interrupt__") + if pending: + self._interrupt = str(getattr(pending[0], "value", pending[0])) + await workflow.wait_condition(lambda: self._resumed) + result = await agent.ainvoke( + Command(resume={"decisions": [{"type": self._resume_value}]}), + config=config, + ) + return result["messages"][-1].content + + @workflow.query + def pending_interrupt(self) -> str | None: + return self._interrupt + + @workflow.update + async def resume(self, decision: str) -> None: + self._resume_value = decision + self._resumed = True + + +@pytest.mark.asyncio +async def test_interrupt_query_then_resume(env: WorkflowEnvironment) -> None: + approve = AIMessage( + content="", + tool_calls=[{"name": "book_trip", "args": {"city": "Rome"}, "id": "c1"}], + ) + done = AIMessage(content="Booked a trip to Rome.") + plugin = DeepAgentsPlugin(model_provider=mock_model_provider([approve, done])) + async with Worker( + env.client, + task_queue="da-hitl", + workflows=[HitlWorkflow], + plugins=[plugin], + ): + handle = await env.client.start_workflow( + HitlWorkflow.run, + "Rome", + id=f"da-hitl-{uuid.uuid4()}", + task_queue="da-hitl", + ) + + # Wait for the agent to hit the interrupt (surfaced via the Query), then + # approve via an Update. A bounded poll with a sleep, so a regression that + # never raises the interrupt fails fast instead of busy-spinning. + for _ in range(100): + if await handle.query(HitlWorkflow.pending_interrupt) is not None: + break + await asyncio.sleep(0.1) + else: + pytest.fail("workflow never surfaced the HITL interrupt via the query") + + await handle.execute_update(HitlWorkflow.resume, "approve") + out = await handle.result() + + assert "Rome" in out diff --git a/tests/contrib/deepagents/test_model_activity.py b/tests/contrib/deepagents/test_model_activity.py new file mode 100644 index 000000000..37a98ef00 --- /dev/null +++ b/tests/contrib/deepagents/test_model_activity.py @@ -0,0 +1,103 @@ +"""The model seam: every ``TemporalModel`` generation is one activity. + +These exercise the seam directly through ``TemporalModel`` (no full agent +needed), so they depend only on LangChain, not on deepagents. +""" + +from __future__ import annotations + +import sys +import uuid +from datetime import timedelta + +import pytest + +from temporalio.testing import WorkflowEnvironment + +pytestmark = pytest.mark.skipif( + sys.version_info < (3, 11), reason="deepagents requires Python >= 3.11" +) + +pytest.importorskip("langchain_core") + +from temporalio import workflow # noqa: E402 +from temporalio.worker import Worker # noqa: E402 +from tests.contrib.deepagents.helpers import count_scheduled_activities # noqa: E402 + +with workflow.unsafe.imports_passed_through(): + from langchain_core.messages import HumanMessage + + from temporalio.contrib.deepagents import DeepAgentsPlugin, TemporalModel + from temporalio.contrib.deepagents.testing import mock_model_provider + +INVOKE_MODEL = "deepagents.invoke_model" + + +@workflow.defn +class ModelWorkflow: + @workflow.run + async def run(self, prompt: str) -> str: + model = TemporalModel(model="fake:model") + message = await model.ainvoke([HumanMessage(content=prompt)]) + return str(message.content) + + +@workflow.defn +class ExplicitTimeoutWorkflow: + @workflow.run + async def run(self, prompt: str) -> str: + model = TemporalModel( + model="fake:model", + activity_options={"start_to_close_timeout": timedelta(seconds=20)}, + ) + message = await model.ainvoke([HumanMessage(content=prompt)]) + return str(message.content) + + +@pytest.mark.asyncio +async def test_model_call_is_activity(env: WorkflowEnvironment) -> None: + plugin = DeepAgentsPlugin( + model_provider=mock_model_provider(["The capital of France is Paris."]), + model_activity_options={"start_to_close_timeout": timedelta(seconds=30)}, + ) + async with Worker( + env.client, + task_queue="da-model", + workflows=[ModelWorkflow], + plugins=[plugin], + ): + handle = await env.client.start_workflow( + ModelWorkflow.run, + "What is the capital of France?", + id=f"da-model-{uuid.uuid4()}", + task_queue="da-model", + ) + out = await handle.result() + assert "Paris" in out + counts = await count_scheduled_activities(handle) + assert counts[INVOKE_MODEL] == 1, counts + + +@pytest.mark.asyncio +async def test_temporal_model_explicit(env: WorkflowEnvironment) -> None: + # The explicit escape hatch routes through the same activity, with a + # per-model timeout override rather than the plugin default. + plugin = DeepAgentsPlugin( + model_provider=mock_model_provider(["Bonjour."]), + ) + async with Worker( + env.client, + task_queue="da-model-explicit", + workflows=[ExplicitTimeoutWorkflow], + plugins=[plugin], + ): + handle = await env.client.start_workflow( + ExplicitTimeoutWorkflow.run, + "hi", + id=f"da-model-x-{uuid.uuid4()}", + task_queue="da-model-explicit", + ) + out = await handle.result() + assert out == "Bonjour." + counts = await count_scheduled_activities(handle) + assert counts[INVOKE_MODEL] == 1, counts diff --git a/tests/contrib/deepagents/test_native_e2e.py b/tests/contrib/deepagents/test_native_e2e.py new file mode 100644 index 000000000..29b373da6 --- /dev/null +++ b/tests/contrib/deepagents/test_native_e2e.py @@ -0,0 +1,141 @@ +"""Cardinal end-to-end test: unmodified ``deepagents`` code, made durable. + +Builds a real Deep Agent with ``create_deep_agent(...)`` and drives it with +``agent.ainvoke(...)`` inside a ``@workflow.defn`` — the only addition is +``plugins=[DeepAgentsPlugin(...)]``. No user call to +``workflow.execute_activity``; the plugin routes model and tool calls to +activities under the hood. + +Guards on the ``deepagents`` / ``langchain_core`` imports (capability detection), +because they are the plugin's own runtime dependency and may be absent on a +docs-only checkout — there is no env-var gate. +""" + +from __future__ import annotations + +import sys +import uuid +from datetime import timedelta + +import pytest + +from temporalio.testing import WorkflowEnvironment + +pytestmark = pytest.mark.skipif( + sys.version_info < (3, 11), reason="deepagents requires Python >= 3.11" +) + +pytest.importorskip("deepagents") +pytest.importorskip("langchain_core") + +from temporalio import workflow # noqa: E402 +from temporalio.worker import Worker # noqa: E402 +from tests.contrib.deepagents.helpers import count_scheduled_activities # noqa: E402 + +# Bind deepagents symbols off the module importorskip returns: a static +# `from deepagents import ...` cannot resolve on Python 3.10 (deepagents +# needs >= 3.11), and with the package absent the type checkers mis-resolve +# the name against this same-named test directory. +create_deep_agent = pytest.importorskip("deepagents").create_deep_agent + +with workflow.unsafe.imports_passed_through(): + from langchain_core.messages import AIMessage + + from temporalio.contrib.deepagents import DeepAgentsPlugin, tool_as_activity + from temporalio.contrib.deepagents.testing import mock_model_provider + +INVOKE_MODEL = "deepagents.invoke_model" +INVOKE_TOOL = "deepagents.invoke_tool" + + +@workflow.defn +class DeepAgentWorkflow: + @workflow.run + async def run(self, question: str) -> str: + agent = create_deep_agent( + model="anthropic:claude-sonnet-4-5", + system_prompt="You are a helpful assistant.", + ) + result = await agent.ainvoke( + {"messages": [{"role": "user", "content": question}]} + ) + return result["messages"][-1].content + + +@workflow.defn +class ToolLoopWorkflow: + @workflow.run + async def run(self, city: str) -> str: + def get_weather(city: str) -> str: + """Return the weather for a city.""" + return f"It is sunny in {city}." + + weather_tool = tool_as_activity( + get_weather, start_to_close_timeout=timedelta(seconds=30) + ) + agent = create_deep_agent( + model="anthropic:claude-sonnet-4-5", + tools=[weather_tool], + system_prompt="Use the weather tool to answer.", + ) + result = await agent.ainvoke( + {"messages": [{"role": "user", "content": f"Weather in {city}?"}]} + ) + return result["messages"][-1].content + + +@pytest.mark.asyncio +async def test_deep_agent_runs_via_plugin(env: WorkflowEnvironment) -> None: + plugin = DeepAgentsPlugin( + model_provider=mock_model_provider(["The answer is 42."]), + ) + async with Worker( + env.client, + task_queue="da-native", + workflows=[DeepAgentWorkflow], + plugins=[plugin], + ): + handle = await env.client.start_workflow( + DeepAgentWorkflow.run, + "What is the meaning of life?", + id=f"da-native-{uuid.uuid4()}", + task_queue="da-native", + ) + out = await handle.result() + + assert "42" in out + counts = await count_scheduled_activities(handle) + # The model call was made durable as an activity, with no user wiring. + assert counts[INVOKE_MODEL] >= 1, counts + + +@pytest.mark.asyncio +async def test_agent_tool_loop_routes_to_activities(env: WorkflowEnvironment) -> None: + # Script the model: first turn asks for the tool, second turn answers. This + # forces model -> tool -> model, proving each call routes through an activity. + tool_call = AIMessage( + content="", + tool_calls=[{"name": "get_weather", "args": {"city": "Paris"}, "id": "call-1"}], + ) + final = AIMessage(content="It is sunny in Paris.") + plugin = DeepAgentsPlugin( + model_provider=mock_model_provider([tool_call, final]), + ) + async with Worker( + env.client, + task_queue="da-tool-loop", + workflows=[ToolLoopWorkflow], + plugins=[plugin], + ): + handle = await env.client.start_workflow( + ToolLoopWorkflow.run, + "Paris", + id=f"da-tool-loop-{uuid.uuid4()}", + task_queue="da-tool-loop", + ) + out = await handle.result() + + assert "Paris" in out + counts = await count_scheduled_activities(handle) + assert counts[INVOKE_MODEL] == 2, counts + assert counts[INVOKE_TOOL] == 1, counts diff --git a/tests/contrib/deepagents/test_readme.py b/tests/contrib/deepagents/test_readme.py new file mode 100644 index 000000000..7aa8ddd7a --- /dev/null +++ b/tests/contrib/deepagents/test_readme.py @@ -0,0 +1,36 @@ +"""The README's code blocks must stay valid Python. + +A copy-paste example that does not even parse is worse than no example. This +compiles every ```python fenced block in the README so a stale snippet fails the +suite. Compilation (not execution) keeps the check dependency-free. +""" + +from __future__ import annotations + +import re +from pathlib import Path + +README = ( + Path(__file__).resolve().parents[3] + / "temporalio" + / "contrib" + / "deepagents" + / "README.md" +) + +_BLOCK = re.compile(r"```python\n(.*?)```", re.DOTALL) + + +def _python_blocks() -> list[str]: + return _BLOCK.findall(README.read_text(encoding="utf-8")) + + +def test_readme_has_python_blocks() -> None: + blocks = _python_blocks() + assert len(blocks) >= 3, "expected the hello-world and composition examples" + + +def test_readme_hello_world_constructs() -> None: + # Every documented snippet must compile as written. + for i, block in enumerate(_python_blocks()): + compile(block, f"", "exec") diff --git a/tests/contrib/deepagents/test_replay.py b/tests/contrib/deepagents/test_replay.py new file mode 100644 index 000000000..ac43a4034 --- /dev/null +++ b/tests/contrib/deepagents/test_replay.py @@ -0,0 +1,65 @@ +"""Recorded histories replay cleanly through the plugin. + +The Deep Agents control loop runs in the workflow, so replay determinism is the +core safety property. This records the history of a real run (a plain fake agent +driven by ``run_deep_agent``, no LangChain needed) and feeds it back through a +``Replayer`` configured with the plugin. A nondeterministic seam would raise on +replay; a clean pass proves the in-workflow dispatch is deterministic. +""" + +from __future__ import annotations + +import sys +import uuid +from typing import Any + +import pytest + +from temporalio.testing import WorkflowEnvironment + +pytestmark = pytest.mark.skipif( + sys.version_info < (3, 11), reason="deepagents requires Python >= 3.11" +) +from temporalio import workflow +from temporalio.contrib.deepagents import DeepAgentsPlugin, run_deep_agent +from temporalio.worker import Replayer, Worker + + +class FakeAgent: + async def ainvoke(self, input: Any) -> dict: + messages = list(input.get("messages", [])) if isinstance(input, dict) else [] + return {"messages": [*messages, "answered"], "todos": []} + + +@workflow.defn +class ReplayWorkflow: + @workflow.run + async def run(self, input: dict) -> dict: + return await run_deep_agent(FakeAgent(), input) + + +@pytest.mark.asyncio +async def test_replay_with_plugin(env: WorkflowEnvironment) -> None: + plugin = DeepAgentsPlugin() + async with Worker( + env.client, + task_queue="da-replay", + workflows=[ReplayWorkflow], + plugins=[plugin], + ): + handle = await env.client.start_workflow( + ReplayWorkflow.run, + {"messages": ["question"]}, + id=f"da-replay-{uuid.uuid4()}", + task_queue="da-replay", + ) + await handle.result() + history = await handle.fetch_history() + + # A fresh replayer (new worker identity) must replay the recorded history + # without a nondeterminism error. + replayer = Replayer( + workflows=[ReplayWorkflow], + plugins=[DeepAgentsPlugin()], + ) + await replayer.replay_workflow(history) diff --git a/tests/contrib/deepagents/test_sandbox_passthrough.py b/tests/contrib/deepagents/test_sandbox_passthrough.py new file mode 100644 index 000000000..26a5ce2e6 --- /dev/null +++ b/tests/contrib/deepagents/test_sandbox_passthrough.py @@ -0,0 +1,89 @@ +"""The plugin's sandbox passthrough makes explicit import guards unnecessary. + +This module imports ``deepagents`` at the top WITHOUT +``workflow.unsafe.imports_passed_through()``. The workflow sandbox re-imports +the defining module of every workflow, so if the plugin's passthrough +configuration did not cover deepagents' import tree, worker registration +below would fail. This is the executable proof behind the README's +guard-free examples. + +Also the e2e for ``create_temporal_deep_agent``: the explicit construction +path that scopes ``activity_options`` to one agent. +""" + +from __future__ import annotations + +import sys +import uuid +from datetime import timedelta + +import pytest + +from temporalio.testing import WorkflowEnvironment + +pytestmark = pytest.mark.skipif( + sys.version_info < (3, 11), reason="deepagents requires Python >= 3.11" +) +pytest.importorskip("deepagents") +pytest.importorskip("langchain_core") + +import deepagents # noqa: F401 # pyright: ignore[reportUnusedImport, reportImplicitRelativeImport] + +from temporalio import workflow +from temporalio.contrib.deepagents import ( + DeepAgentsPlugin, + create_temporal_deep_agent, +) +from temporalio.worker import Worker +from tests.contrib.deepagents.helpers import count_scheduled_activities + + +@workflow.defn +class GuardFreeAgentWorkflow: + @workflow.run + async def run(self, question: str) -> str: + agent = create_temporal_deep_agent( + model="anthropic:claude-sonnet-4-5", + activity_options={"start_to_close_timeout": timedelta(minutes=2)}, + ) + result = await agent.ainvoke( + {"messages": [{"role": "user", "content": question}]} + ) + return str(result["messages"][-1].content) + + +@pytest.mark.asyncio +async def test_guard_free_import_and_explicit_agent( + env: WorkflowEnvironment, +) -> None: + from temporalio.contrib.deepagents.testing import mock_model_provider + + plugin = DeepAgentsPlugin( + model_provider=mock_model_provider(["The answer is 42."]), + ) + async with Worker( + env.client, + task_queue="da-guard-free", + workflows=[GuardFreeAgentWorkflow], + plugins=[plugin], + max_cached_workflows=0, + ): + handle = await env.client.start_workflow( + GuardFreeAgentWorkflow.run, + "What is the meaning of life?", + id=f"da-guard-free-{uuid.uuid4()}", + task_queue="da-guard-free", + ) + out = await handle.result() + + assert "42" in out + counts = await count_scheduled_activities(handle) + assert counts["deepagents.invoke_model"] == 1, counts + + +def test_wrapper_rejects_options_without_wrappable_model() -> None: + with pytest.raises(ValueError, match="activity_options requires"): + create_temporal_deep_agent( + model=object(), + activity_options={"start_to_close_timeout": timedelta(minutes=1)}, + ) diff --git a/tests/contrib/deepagents/test_side_effects.py b/tests/contrib/deepagents/test_side_effects.py new file mode 100644 index 000000000..2b32b9dee --- /dev/null +++ b/tests/contrib/deepagents/test_side_effects.py @@ -0,0 +1,74 @@ +"""Determinism: no unexpected side effects and a bounded activity count. + +Running the worker with ``max_cached_workflows=0`` forces the workflow to be +replayed from history on every activation. If the in-workflow dispatch did +anything nondeterministic, replay would diverge and the workflow would fail. A +clean completion plus an exact ``backend_op`` schedule count proves the seam +schedules one activity per op and nothing more. +""" + +from __future__ import annotations + +import sys +import uuid +from datetime import timedelta + +import pytest + +from temporalio.testing import WorkflowEnvironment + +pytestmark = pytest.mark.skipif( + sys.version_info < (3, 11), reason="deepagents requires Python >= 3.11" +) +from temporalio import workflow +from temporalio.contrib.deepagents import DeepAgentsPlugin, TemporalBackend +from temporalio.worker import Worker +from tests.contrib.deepagents.helpers import count_scheduled_activities + +BACKEND_OP = "deepagents.backend_op" + + +class TwoOpBackend: + """Protocol-named ops: one async (``awrite``, as the filesystem + middleware calls it) and one sync (``read``).""" + + async def awrite(self, file_path: str, _content: str) -> str: + return f"wrote:{file_path}" + + def read(self, file_path: str) -> str: + return f"read:{file_path}" + + +@workflow.defn +class TwoOpWorkflow: + @workflow.run + async def run(self) -> str: + backend = TemporalBackend( + TwoOpBackend(), + activity_options={"start_to_close_timeout": timedelta(seconds=10)}, + ) + await backend.awrite("a.txt", "hello") + return await backend.read("a.txt") + + +@pytest.mark.asyncio +async def test_activity_schedule_counts(env: WorkflowEnvironment) -> None: + plugin = DeepAgentsPlugin() + async with Worker( + env.client, + task_queue="da-side-effects", + workflows=[TwoOpWorkflow], + plugins=[plugin], + max_cached_workflows=0, + ): + handle = await env.client.start_workflow( + TwoOpWorkflow.run, + id=f"da-side-effects-{uuid.uuid4()}", + task_queue="da-side-effects", + ) + out = await handle.result() + + assert out == "read:a.txt" + counts = await count_scheduled_activities(handle) + # Exactly the two backend ops, each scheduled once — no hidden replays of work. + assert counts[BACKEND_OP] == 2, counts diff --git a/tests/contrib/deepagents/test_streaming.py b/tests/contrib/deepagents/test_streaming.py new file mode 100644 index 000000000..6b65aa0af --- /dev/null +++ b/tests/contrib/deepagents/test_streaming.py @@ -0,0 +1,107 @@ +"""Streaming: model calls route through the streaming activity when a topic is set. + +Setting ``streaming_topic`` flips model dispatch from ``invoke_model`` to +``invoke_model_streaming``, which streams chunks out of the activity and returns +the aggregated final message to the workflow (so the durable result matches the +non-streaming path). These assert the observable effects: which activity is +scheduled, the aggregated content, and that a custom batch interval is threaded +into the streaming activity. +""" + +from __future__ import annotations + +import sys +import uuid +from datetime import timedelta + +import pytest + +from temporalio.testing import WorkflowEnvironment + +pytestmark = pytest.mark.skipif( + sys.version_info < (3, 11), reason="deepagents requires Python >= 3.11" +) + +pytest.importorskip("langchain_core") + +from temporalio import workflow # noqa: E402 +from temporalio.worker import Worker # noqa: E402 +from tests.contrib.deepagents.helpers import count_scheduled_activities # noqa: E402 + +with workflow.unsafe.imports_passed_through(): + from langchain_core.messages import HumanMessage + + from temporalio.contrib.deepagents import DeepAgentsPlugin, TemporalModel + from temporalio.contrib.deepagents.testing import mock_model_provider + +INVOKE_MODEL = "deepagents.invoke_model" +INVOKE_MODEL_STREAMING = "deepagents.invoke_model_streaming" + + +@workflow.defn +class StreamWorkflow: + @workflow.run + async def run(self, prompt: str) -> str: + model = TemporalModel(model="fake:model") + parts: list[str] = [] + async for chunk in model.astream([HumanMessage(content=prompt)]): + parts.append(str(chunk.content)) + return "".join(parts) + + +@pytest.mark.asyncio +async def test_stream_chunks_published(env: WorkflowEnvironment) -> None: + plugin = DeepAgentsPlugin( + model_provider=mock_model_provider(["Streamed answer."]), + streaming_topic="da-stream-topic", + model_activity_options={"start_to_close_timeout": timedelta(seconds=30)}, + ) + async with Worker( + env.client, + task_queue="da-stream", + workflows=[StreamWorkflow], + plugins=[plugin], + ): + handle = await env.client.start_workflow( + StreamWorkflow.run, + "stream please", + id=f"da-stream-{uuid.uuid4()}", + task_queue="da-stream", + ) + out = await handle.result() + + assert "Streamed answer." in out + counts = await count_scheduled_activities(handle) + # The topic is set, so dispatch used the streaming activity, not invoke_model. + assert counts[INVOKE_MODEL_STREAMING] == 1, counts + assert counts[INVOKE_MODEL] == 0, counts + + +@pytest.mark.asyncio +async def test_batch_interval_coalesces(env: WorkflowEnvironment) -> None: + # A custom batch interval is threaded into the streaming activity that + # coalesces chunks; streaming still returns the aggregated message. + plugin = DeepAgentsPlugin( + model_provider=mock_model_provider(["Batched."]), + streaming_topic="da-batch-topic", + streaming_batch_interval=timedelta(milliseconds=500), + ) + assert plugin._activities._streaming_batch_interval == timedelta(milliseconds=500) + + async with Worker( + env.client, + task_queue="da-batch", + workflows=[StreamWorkflow], + plugins=[plugin], + ): + handle = await env.client.start_workflow( + StreamWorkflow.run, + "batch please", + id=f"da-batch-{uuid.uuid4()}", + task_queue="da-batch", + ) + out = await handle.result() + + assert "Batched." in out + counts = await count_scheduled_activities(handle) + assert counts[INVOKE_MODEL_STREAMING] == 1, counts diff --git a/tests/contrib/deepagents/test_subagents.py b/tests/contrib/deepagents/test_subagents.py new file mode 100644 index 000000000..49a407e9d --- /dev/null +++ b/tests/contrib/deepagents/test_subagents.py @@ -0,0 +1,90 @@ +"""Sub-agents inherit the activity seams. + +Deep Agents builds sub-agents as separate graphs, but they inherit the parent's +``model`` object and tools by default. Because the plugin substitutes the model +*object*, every sub-agent's model call routes through an activity without any +per-sub-agent wiring. This runs a real agent configured with a sub-agent and +asserts model calls still land on the activity seam. + +The exact number of hops depends on ``deepagents`` internals we do not pin, so +the assertion is the robust invariant: the configured agent runs and at least one +model call went through an activity. +""" + +from __future__ import annotations + +import sys +import uuid + +import pytest + +from temporalio.testing import WorkflowEnvironment + +pytestmark = pytest.mark.skipif( + sys.version_info < (3, 11), reason="deepagents requires Python >= 3.11" +) + +pytest.importorskip("deepagents") +pytest.importorskip("langchain_core") + +from temporalio import workflow # noqa: E402 +from temporalio.worker import Worker # noqa: E402 +from tests.contrib.deepagents.helpers import count_scheduled_activities # noqa: E402 + +# Bind deepagents symbols off the module importorskip returns: a static +# `from deepagents import ...` cannot resolve on Python 3.10 (deepagents +# needs >= 3.11), and with the package absent the type checkers mis-resolve +# the name against this same-named test directory. +create_deep_agent = pytest.importorskip("deepagents").create_deep_agent + +with workflow.unsafe.imports_passed_through(): + from temporalio.contrib.deepagents import DeepAgentsPlugin + from temporalio.contrib.deepagents.testing import mock_model_provider + +INVOKE_MODEL = "deepagents.invoke_model" + + +@workflow.defn +class SubAgentWorkflow: + @workflow.run + async def run(self, question: str) -> str: + agent = create_deep_agent( + model="anthropic:claude-sonnet-4-5", + system_prompt="You coordinate research.", + subagents=[ + { + "name": "researcher", + "description": "Researches a topic in depth.", + "system_prompt": "You research topics.", + } + ], + ) + result = await agent.ainvoke( + {"messages": [{"role": "user", "content": question}]} + ) + return result["messages"][-1].content + + +@pytest.mark.asyncio +async def test_subagent_calls_route_to_activities(env: WorkflowEnvironment) -> None: + plugin = DeepAgentsPlugin( + model_provider=mock_model_provider(["Coordinated answer."]), + ) + async with Worker( + env.client, + task_queue="da-subagent", + workflows=[SubAgentWorkflow], + plugins=[plugin], + ): + handle = await env.client.start_workflow( + SubAgentWorkflow.run, + "Investigate the topic.", + id=f"da-subagent-{uuid.uuid4()}", + task_queue="da-subagent", + ) + out = await handle.result() + + assert out + counts = await count_scheduled_activities(handle) + # A model instance shared with the sub-agent means model calls are activities. + assert counts[INVOKE_MODEL] >= 1, counts diff --git a/tests/contrib/deepagents/test_tools.py b/tests/contrib/deepagents/test_tools.py new file mode 100644 index 000000000..1fc1ff212 --- /dev/null +++ b/tests/contrib/deepagents/test_tools.py @@ -0,0 +1,238 @@ +"""The tool seam: existing activities and wrapped tools route to activities. + +These need LangChain (a tool is a ``BaseTool``) and guard on its import. Each +runs a real workflow that invokes the wrapped tool and asserts it scheduled the +expected activity. +""" + +from __future__ import annotations + +import sys +import uuid +from collections.abc import Sequence +from datetime import timedelta +from types import SimpleNamespace +from typing import Any + +import pytest + +from temporalio.testing import WorkflowEnvironment + +pytestmark = pytest.mark.skipif( + sys.version_info < (3, 11), reason="deepagents requires Python >= 3.11" +) + +pytest.importorskip("langchain_core") + +from temporalio import activity, workflow # noqa: E402 +from temporalio.worker import Worker # noqa: E402 +from tests.contrib.deepagents.helpers import count_scheduled_activities # noqa: E402 + +with workflow.unsafe.imports_passed_through(): + from temporalio.contrib.deepagents import ( # noqa: E402 + DeepAgentsPlugin, + activity_as_tool, + tool_as_activity, + ) + from temporalio.contrib.deepagents._tools import warn_unwrapped_tools # noqa: E402 + +INVOKE_TOOL = "deepagents.invoke_tool" + +# Bind deepagents symbols off the module importorskip returns: a static +# `from deepagents import ...` cannot resolve on Python 3.10 (deepagents +# needs >= 3.11), and with the package absent the type checkers mis-resolve +# the name against this same-named test directory. +create_deep_agent = pytest.importorskip("deepagents").create_deep_agent + + +def pairing_weather(city: str) -> str: + """Return the weather for a city.""" + return f"weather:{city}" + + +@activity.defn +async def echo_activity(text: str) -> str: + return f"echo:{text}" + + +@workflow.defn +class ActivityAsToolWorkflow: + @workflow.run + async def run(self, text: str) -> str: + tool = activity_as_tool( + echo_activity, start_to_close_timeout=timedelta(seconds=10) + ) + return await tool.ainvoke({"text": text}) + + +@workflow.defn +class ToolAsActivityWorkflow: + @workflow.run + async def run(self, city: str) -> str: + def get_weather(city: str) -> str: + """Look up the weather for a city.""" + return f"sunny in {city}" + + tool = tool_as_activity( + get_weather, start_to_close_timeout=timedelta(seconds=10) + ) + # The wrapper returns plain CONTENT (the tool node stamps the model's + # tool_call_id onto it) — not a pre-built ToolMessage. + return str(await tool.ainvoke({"city": city})) + + +@pytest.mark.asyncio +async def test_activity_as_tool(env: WorkflowEnvironment) -> None: + plugin = DeepAgentsPlugin() + async with Worker( + env.client, + task_queue="da-act-tool", + workflows=[ActivityAsToolWorkflow], + activities=[echo_activity], + plugins=[plugin], + ): + handle = await env.client.start_workflow( + ActivityAsToolWorkflow.run, + "hi", + id=f"da-act-tool-{uuid.uuid4()}", + task_queue="da-act-tool", + ) + out = await handle.result() + + assert out == "echo:hi" + counts = await count_scheduled_activities(handle) + assert counts["echo_activity"] == 1, counts + + +@pytest.mark.asyncio +async def test_tool_as_activity(env: WorkflowEnvironment) -> None: + plugin = DeepAgentsPlugin() + async with Worker( + env.client, + task_queue="da-tool-act", + workflows=[ToolAsActivityWorkflow], + plugins=[plugin], + ): + handle = await env.client.start_workflow( + ToolAsActivityWorkflow.run, + "Paris", + id=f"da-tool-act-{uuid.uuid4()}", + task_queue="da-tool-act", + ) + out = await handle.result() + + assert "sunny in Paris" in out + counts = await count_scheduled_activities(handle) + assert counts[INVOKE_TOOL] == 1, counts + + +def test_builtin_tool_in_workflow(recwarn: pytest.WarningsRecorder) -> None: + # Built-in tool names never warn (they are pure, in-workflow); an unwrapped + # user tool does warn so the Workflow-vs-Activity choice is conscious. + warn_unwrapped_tools([SimpleNamespace(name="write_todos")]) + assert len(recwarn) == 0 + + warn_unwrapped_tools([SimpleNamespace(name="scrape_website")]) + assert any("scrape_website" in str(w.message) for w in recwarn) + + +# Turn-2 requests observed by the fake model, captured activity-side. Module +# state is shared with the in-process worker, same as the tool registries. +_captured_requests: list[list] = [] + + +@workflow.defn +class ToolCallIdPairingWorkflow: + @workflow.run + async def run(self, city: str) -> str: + weather_tool = tool_as_activity( + pairing_weather, start_to_close_timeout=timedelta(seconds=10) + ) + agent = create_deep_agent( + model="anthropic:claude-sonnet-4-5", + tools=[weather_tool], + system_prompt="Use the weather tool.", + ) + result = await agent.ainvoke( + {"messages": [{"role": "user", "content": f"Weather in {city}?"}]} + ) + return str(result["messages"][-1].content) + + +@pytest.mark.asyncio +async def test_wrapped_tool_result_pairs_with_model_tool_call_id( + env: WorkflowEnvironment, +) -> None: + """The tool_result the model sees on turn 2 must carry the model's OWN + tool_call_id. Regression: ``tool_as_activity`` returned the activity-built + ``ToolMessage`` whose workflow-generated id a real provider (Anthropic) + rejects as an unpaired ``tool_result`` — offline fakes never validate the + pairing, so only a live-model run surfaced it. The wrapper now returns + plain content and the tool node stamps the correct id. + """ + from langchain_core.messages import AIMessage, ToolMessage + + from temporalio.contrib.deepagents.testing import FakeModel + + _captured_requests.clear() + + class RecordingModel(FakeModel): + def __init__(self, responses: Sequence[Any]) -> None: + super().__init__(responses) + + async def _agenerate( + self, + messages: list[Any], + stop: list[str] | None = None, + run_manager: Any = None, + **kwargs: Any, + ) -> Any: + _captured_requests.append(list(messages)) + return await super()._agenerate( + messages, stop=stop, run_manager=run_manager, **kwargs + ) + + tool_turn = AIMessage( + content="", + tool_calls=[ + { + "name": "pairing_weather", + "args": {"city": "Paris"}, + "id": "toolu_scripted_pairing_id", + } + ], + ) + final = AIMessage(content="It is sunny in Paris.") + responses = [tool_turn, final] + cursor = {"i": 0} + + def provider(_model_name: str) -> RecordingModel: + reply = responses[cursor["i"] % len(responses)] + cursor["i"] += 1 + return RecordingModel([reply]) + + plugin = DeepAgentsPlugin(model_provider=provider) + async with Worker( + env.client, + task_queue="da-toolcall-pairing", + workflows=[ToolCallIdPairingWorkflow], + plugins=[plugin], + max_cached_workflows=0, + ): + handle = await env.client.start_workflow( + ToolCallIdPairingWorkflow.run, + "Paris", + id=f"da-toolcall-pairing-{uuid.uuid4()}", + task_queue="da-toolcall-pairing", + ) + out = await handle.result() + + assert "sunny" in out.lower() + # Turn 2's request must contain the tool result under the MODEL's id. + assert len(_captured_requests) >= 2, len(_captured_requests) + tool_messages = [m for m in _captured_requests[1] if isinstance(m, ToolMessage)] + assert tool_messages, _captured_requests[1] + assert tool_messages[0].tool_call_id == "toolu_scripted_pairing_id", tool_messages[ + 0 + ].tool_call_id + assert "weather:Paris" in str(tool_messages[0].content) diff --git a/uv.lock b/uv.lock index 8a3afd1fe..f64424dca 100644 --- a/uv.lock +++ b/uv.lock @@ -9,7 +9,7 @@ resolution-markers = [ ] [options] -exclude-newer = "2026-07-16T16:18:47.494197Z" +exclude-newer = "0001-01-01T00:00:00Z" # This has no effect and is included for backwards compatibility when using relative exclude-newer values. exclude-newer-span = "P2W" [[package]] @@ -252,6 +252,25 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/78/b6/6307fbef88d9b5ee7421e68d78a9f162e0da4900bc5f5793f6d3d0e34fb8/annotated_types-0.7.0-py3-none-any.whl", hash = "sha256:1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53", size = 13643, upload-time = "2024-05-20T21:33:24.1Z" }, ] +[[package]] +name = "anthropic" +version = "0.117.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "anyio" }, + { name = "distro" }, + { name = "docstring-parser" }, + { name = "httpx" }, + { name = "jiter" }, + { name = "pydantic" }, + { name = "sniffio" }, + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/41/0d/8f71d535edb0d438f023bd825fb65f67c14fa88a2bd6b75f292a58a63de4/anthropic-0.117.0.tar.gz", hash = "sha256:98107f2b76439641e0ae2a1754087534b8f178dbab99d6eb1bc4b7bc8c744496", size = 989933, upload-time = "2026-07-16T19:36:13.07Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b7/4c/917d21d6619a4475cdafc6d13a69fdb3b901ddac57e76caca5a25c117b6d/anthropic-0.117.0-py3-none-any.whl", hash = "sha256:451a0a6905f11dff7663d13e4ee5dbf909eb8942b1d049803c7b937a13ac47ec", size = 998327, upload-time = "2026-07-16T19:36:11.225Z" }, +] + [[package]] name = "antlr4-python3-runtime" version = "4.13.2" @@ -918,6 +937,23 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/aa/50/a9caea39ad19c431c1a3f8a31114df65b260cdfe67786b6c7e7c040c4c44/cryptography-49.0.0-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:be9fcb48a55f023493482827d4f459bd263cc20efde64f204b97c123201850c6", size = 3783731, upload-time = "2026-06-12T20:02:43.319Z" }, ] +[[package]] +name = "deepagents" +version = "0.6.12" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "langchain" }, + { name = "langchain-anthropic" }, + { name = "langchain-core" }, + { name = "langchain-google-genai" }, + { name = "langsmith" }, + { name = "wcmatch" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/e0/db/a6acdc72a9e90c3f07ed10de35c951734a02d4facb693bb59684ad368801/deepagents-0.6.12.tar.gz", hash = "sha256:1f281c0bc5a63132f62e2ee345c1dc593b23188da6e23016401f6879fbe54b5f", size = 211364, upload-time = "2026-06-25T17:26:52.775Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/98/49/af7219b3c13520fee047bb807cfaefba17f8e4584c551d946773589a4f08/deepagents-0.6.12-py3-none-any.whl", hash = "sha256:28b8fa0119ca0a689e3e18e288c4634e4046062acfc87a1cb34289d3af3a1c88", size = 236120, upload-time = "2026-06-25T17:26:51.736Z" }, +] + [[package]] name = "dependency-groups" version = "1.3.1" @@ -986,7 +1022,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 = [ @@ -1090,6 +1126,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/52/af/9b01bcf5c91e81899bb890b87bd9077732a9b3365c098e67fe77958c39ed/filelock-3.30.0-py3-none-any.whl", hash = "sha256:40632998f0772e64183bb819f086a1b9def6be1090cf1dcb9d45f46806ef279b", size = 93131, upload-time = "2026-07-16T03:53:56.727Z" }, ] +[[package]] +name = "filetype" +version = "1.2.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/bb/29/745f7d30d47fe0f251d3ad3dc2978a23141917661998763bebb6da007eb1/filetype-1.2.0.tar.gz", hash = "sha256:66b56cd6474bf41d8c54660347d37afcc3f7d1970648de365c102ef77548aadb", size = 998020, upload-time = "2022-11-02T17:34:04.141Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/18/79/1b8fa1bb3568781e84c9200f951c735f3f157429f44be0495da55894d620/filetype-1.2.0-py2.py3-none-any.whl", hash = "sha256:7ce71b6880181241cf7ac8697a2f1eb6a8bd9b429f7ad6d27b8db9ba5f1c2d25", size = 19970, upload-time = "2022-11-02T17:34:01.425Z" }, +] + [[package]] name = "flask" version = "3.1.3" @@ -1921,6 +1966,34 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/81/db/e655086b7f3a705df045bf0933bdd9c2f79bb3c97bfef1384598bb79a217/keyring-25.7.0-py3-none-any.whl", hash = "sha256:be4a0b195f149690c166e850609a477c532ddbfbaed96a404d4e43f8d5e2689f", size = 39160, upload-time = "2025-11-16T16:26:08.402Z" }, ] +[[package]] +name = "langchain" +version = "1.3.14" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "langchain-core" }, + { name = "langgraph" }, + { name = "pydantic" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/29/68/a6dbad9c22df4087a0f9e79ddd46226c442b30128bfeee538d5889492a73/langchain-1.3.14.tar.gz", hash = "sha256:1b6696c72ba3bbbce54d745e0180742c9f6ece8bbc59ed5a46c3e20b9a435929", size = 645181, upload-time = "2026-07-16T13:28:18.29Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/a9/ec/0f942e78a621f8e3162ff1ed24284f469aaf51fb4607ee5831c626f2b2bc/langchain-1.3.14-py3-none-any.whl", hash = "sha256:4d10dbe91005952cddd56d0dc77aa108964da6bae90ab20063653957e901f782", size = 139560, upload-time = "2026-07-16T13:28:16.498Z" }, +] + +[[package]] +name = "langchain-anthropic" +version = "1.4.8" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "anthropic" }, + { name = "langchain-core" }, + { name = "pydantic" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/98/22/40ab129b08329ca295b391aa1d48267692b42594757084c6918e22b655ac/langchain_anthropic-1.4.8.tar.gz", hash = "sha256:c76891b2044d56105ff13c106ed12650637b53bd598a4bdf15b4796eefa2a4ec", size = 708524, upload-time = "2026-06-26T21:28:46.916Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b7/14/746235c4da89d9bc6a608c5f489f628e03feb8f697195c146e452c8f23c8/langchain_anthropic-1.4.8-py3-none-any.whl", hash = "sha256:778e9301b6fd517824f76ec1776975ce8add97a1f6a36c50ae3c2f4b03a66f7f", size = 52366, upload-time = "2026-06-26T21:28:45.535Z" }, +] + [[package]] name = "langchain-core" version = "1.4.9" @@ -1941,6 +2014,21 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/84/70/ade2fada52772798ef815b6352b59e71b116aa0c32c3aef5be3dc2cbed12/langchain_core-1.4.9-py3-none-any.whl", hash = "sha256:28e3909e2a10cc81504952d795ac0a9e014c0018121ef89d48dd396fa09ec624", size = 558293, upload-time = "2026-07-08T20:06:52.382Z" }, ] +[[package]] +name = "langchain-google-genai" +version = "4.2.7" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "filetype" }, + { name = "google-genai" }, + { name = "langchain-core" }, + { name = "pydantic" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/1d/0c/bc60dabc362ca7c6ffe8c4bcc2f724c7e566b43eb230cee51419f88f784c/langchain_google_genai-4.2.7.tar.gz", hash = "sha256:03b1463ffe4d42435f43c7870467f2215f684bb46400d2543435d10157c80ac7", size = 281605, upload-time = "2026-07-06T13:51:58.724Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b2/f9/d73d1e712591723aaddb7a7b1e94978cd2320c29acfe0d26b6169a2f26f0/langchain_google_genai-4.2.7-py3-none-any.whl", hash = "sha256:0d9c388d0e6c629718fca6abb19c6fdca728a9a7873d0324c1ec821288b5b571", size = 70702, upload-time = "2026-07-06T13:51:57.499Z" }, +] + [[package]] name = "langchain-protocol" version = "0.0.18" @@ -2750,7 +2838,7 @@ wheels = [ [package.optional-dependencies] litellm = [ - { name = "litellm", marker = "python_full_version < '3.14'" }, + { name = "litellm" }, ] [[package]] @@ -4623,6 +4711,11 @@ aioboto3 = [ { name = "aioboto3" }, { name = "types-aioboto3", extra = ["s3"] }, ] +deepagents = [ + { name = "deepagents", marker = "python_full_version >= '3.11'" }, + { name = "langchain", marker = "python_full_version >= '3.11'" }, + { name = "langchain-core", marker = "python_full_version >= '3.11'" }, +] google-adk = [ { name = "google-adk" }, { name = "mcp" }, @@ -4667,9 +4760,13 @@ dev = [ { name = "basedpyright" }, { name = "cibuildwheel" }, { name = "cryptography" }, + { name = "deepagents", marker = "python_full_version >= '3.11'" }, { name = "googleapis-common-protos" }, { name = "grpcio-tools" }, { name = "httpx" }, + { name = "langchain", marker = "python_full_version >= '3.11'" }, + { name = "langchain-anthropic", marker = "python_full_version >= '3.11'" }, + { name = "langchain-core", marker = "python_full_version >= '3.11'" }, { name = "langgraph" }, { name = "langsmith" }, { name = "litellm" }, @@ -4708,9 +4805,12 @@ dev = [ [package.metadata] requires-dist = [ { name = "aioboto3", marker = "extra == 'aioboto3'", specifier = ">=10.4.0" }, + { name = "deepagents", marker = "python_full_version >= '3.11' and extra == 'deepagents'", specifier = ">=0.6.12,<0.7" }, { name = "google-adk", marker = "extra == 'google-adk'", specifier = ">=2.2.0,<3" }, { name = "google-genai", marker = "extra == 'google-genai'", specifier = ">=2.10.0,<3.0.0" }, { name = "grpcio", marker = "extra == 'grpc'", specifier = ">=1.48.2,<2" }, + { name = "langchain", marker = "python_full_version >= '3.11' and extra == 'deepagents'", specifier = ">=1.3.11,<2" }, + { name = "langchain-core", marker = "python_full_version >= '3.11' and extra == 'deepagents'", specifier = ">=1.4.8,<2" }, { name = "langgraph", marker = "extra == 'langgraph'", specifier = ">=1.1.0" }, { name = "langsmith", marker = "extra == 'langsmith'", specifier = ">=0.7.34,<0.9" }, { name = "mcp", marker = "extra == 'google-adk'", specifier = ">=1.24,<2" }, @@ -4732,7 +4832,7 @@ requires-dist = [ { name = "types-protobuf", specifier = ">=3.20,<8.0.0" }, { name = "typing-extensions", specifier = ">=4.2.0,<5" }, ] -provides-extras = ["grpc", "opentelemetry", "pydantic", "openai-agents", "google-adk", "langgraph", "langsmith", "lambda-worker-otel", "aioboto3", "google-genai", "strands-agents"] +provides-extras = ["grpc", "opentelemetry", "pydantic", "openai-agents", "google-adk", "langgraph", "langsmith", "deepagents", "lambda-worker-otel", "aioboto3", "google-genai", "strands-agents"] [package.metadata.requires-dev] dev = [ @@ -4740,9 +4840,13 @@ dev = [ { name = "basedpyright", specifier = "==1.34.0" }, { name = "cibuildwheel", specifier = ">=2.22.0,<3" }, { name = "cryptography", specifier = ">=46" }, + { name = "deepagents", marker = "python_full_version >= '3.11'", specifier = ">=0.6.12,<0.7" }, { name = "googleapis-common-protos", specifier = ">=1.75.0,<2" }, { name = "grpcio-tools", specifier = ">=1.48.2,<2" }, { name = "httpx", specifier = ">=0.28.1" }, + { name = "langchain", marker = "python_full_version >= '3.11'", specifier = ">=1.3.11,<2" }, + { name = "langchain-anthropic", marker = "python_full_version >= '3.11'", specifier = ">=1.4.7" }, + { name = "langchain-core", marker = "python_full_version >= '3.11'", specifier = ">=1.4.8,<2" }, { name = "langgraph", specifier = ">=1.1.0" }, { name = "langsmith", specifier = ">=0.7.34,<0.9" }, { name = "litellm", specifier = ">=1.83.0" }, @@ -5258,6 +5362,18 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/33/e8/e40370e6d74ddba47f002a32919d91310d6074130fe4e17dabcafc15cbf1/watchdog-6.0.0-py3-none-win_ia64.whl", hash = "sha256:a1914259fa9e1454315171103c6a30961236f508b9b623eae470268bbcc6a22f", size = 79067, upload-time = "2024-11-01T14:07:11.845Z" }, ] +[[package]] +name = "wcmatch" +version = "11.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "bracex" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/16/25/1da725838132221e33568973da484ff43813662ccc06ebf7f6e3abddfcd5/wcmatch-11.0.tar.gz", hash = "sha256:55d95c2447789712774b198ceec72939e88b5618f1f8f0a9b605bf7740b63b96", size = 141360, upload-time = "2026-07-10T05:50:24.183Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/28/12/f38b6fee116274d7221743caab07d765032e1370bb54cad8714f87aeb0e8/wcmatch-11.0-py3-none-any.whl", hash = "sha256:3a5977ace27e075eef67eb03d539563f1a19018b62881949a42932cf66926934", size = 42914, upload-time = "2026-07-10T05:50:22.995Z" }, +] + [[package]] name = "wcwidth" version = "0.8.2" From da04dc9768e5579b0c52ff15dc815fbd33857b03 Mon Sep 17 00:00:00 2001 From: Justin Anderson <44687433+jmaeagle99@users.noreply.github.com> Date: Tue, 11 Aug 2026 17:17:33 -0700 Subject: [PATCH 222/226] chore: update sdk-core submodule to latest (#1738) * chore: update sdk-core submodule to latest * fix: update sdk-core to pending change sdk-rust * chore: update sdk-core submodule to latest --- temporalio/bridge/Cargo.lock | 214 +----------------- temporalio/bridge/Cargo.toml | 6 +- temporalio/bridge/proto/common/__init__.py | 2 + temporalio/bridge/proto/common/common_pb2.py | 20 +- temporalio/bridge/proto/common/common_pb2.pyi | 53 +++++ .../workflow_completion_pb2.py | 12 +- .../workflow_completion_pb2.pyi | 36 ++- temporalio/bridge/sdk-core | 2 +- temporalio/bridge/src/client.rs | 80 +++---- temporalio/bridge/src/envconfig.rs | 22 +- temporalio/bridge/src/worker.rs | 29 +-- 11 files changed, 195 insertions(+), 281 deletions(-) diff --git a/temporalio/bridge/Cargo.lock b/temporalio/bridge/Cargo.lock index 330916b2b..10632afb2 100644 --- a/temporalio/bridge/Cargo.lock +++ b/temporalio/bridge/Cargo.lock @@ -58,29 +58,6 @@ version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f2032f911046de80f0a198e0901378627c33f59ea0ac00e363d481118bd70a53" -[[package]] -name = "aws-lc-rs" -version = "1.17.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00bdb5da18dac48ca2cc7cd4a98e533e8635a58e2361d13a1a4ee3888e0d72f1" -dependencies = [ - "aws-lc-sys", - "zeroize", -] - -[[package]] -name = "aws-lc-sys" -version = "0.43.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43103168cc76fe62678a375e722fc9cb3a0146159ac5828bc4f0dfd755c2224c" -dependencies = [ - "cc", - "cmake", - "dunce", - "fs_extra", - "pkg-config", -] - [[package]] name = "axum" version = "0.8.9" @@ -209,12 +186,6 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" -[[package]] -name = "cfg_aliases" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f079e83a288787bcd14a6aea84cee5c87a67c5a3e660c30f557a3d24761b3527" - [[package]] name = "chacha20" version = "0.10.1" @@ -236,15 +207,6 @@ dependencies = [ "serde", ] -[[package]] -name = "cmake" -version = "0.1.58" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0f78a02292a74a88ac736019ab962ece0bc380e3f977bf72e376c5d78ff0678" -dependencies = [ - "cc", -] - [[package]] name = "combine" version = "4.6.7" @@ -408,12 +370,6 @@ version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1435fa1053d8b2fbbe9be7e97eca7f33d37b28409959813daefc1446a14247f1" -[[package]] -name = "dunce" -version = "1.0.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92773504d58c093f6de2459af4af33faa518c13451eb8f2b5698ed3d36e7c813" - [[package]] name = "dyn-clone" version = "1.0.20" @@ -560,12 +516,6 @@ dependencies = [ "futures-core", ] -[[package]] -name = "fs_extra" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42703706b716c37f96a77aea830392ad231f44c9e9a67872fa5548707e11b11c" - [[package]] name = "futures" version = "0.3.33" @@ -682,10 +632,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ff2abc00be7fca6ebc474524697ae276ad847ad0a6b3faa4bcb027e9a4614ad0" dependencies = [ "cfg-if", - "js-sys", "libc", "wasi", - "wasm-bindgen", ] [[package]] @@ -707,11 +655,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "300e883d756b2e4ec94e02791f39b04b522276138852cfc41d9fb7e904106099" dependencies = [ "cfg-if", - "js-sys", "libc", "r-efi 6.0.0", "rand_core 0.10.1", - "wasm-bindgen", ] [[package]] @@ -1159,12 +1105,6 @@ dependencies = [ "hashbrown 0.17.1", ] -[[package]] -name = "lru-slab" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "112b39cec0b298b6c1999fee3e31427f74f676e4cb9879ed1a121b43661a4154" - [[package]] name = "matchers" version = "0.2.0" @@ -1326,7 +1266,7 @@ dependencies = [ "bytes", "http", "opentelemetry", - "reqwest 0.13.4", + "reqwest", ] [[package]] @@ -1341,7 +1281,7 @@ dependencies = [ "opentelemetry-proto", "opentelemetry_sdk", "prost", - "reqwest 0.13.4", + "reqwest", "thiserror", "tokio", "tonic", @@ -1782,63 +1722,6 @@ dependencies = [ "serde", ] -[[package]] -name = "quinn" -version = "0.11.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c1a41e437b6bbd489372cd4971de128e85c855f56c57f283d20ff016cf7c0a8" -dependencies = [ - "bytes", - "cfg_aliases", - "pin-project-lite", - "quinn-proto", - "quinn-udp", - "rustc-hash", - "rustls", - "socket2", - "thiserror", - "tokio", - "tracing", - "web-time", -] - -[[package]] -name = "quinn-proto" -version = "0.11.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f4bfc015262b9df63c8845072ce59068853ff5872180c2ce2f13038b970e560" -dependencies = [ - "aws-lc-rs", - "bytes", - "getrandom 0.4.3", - "lru-slab", - "rand 0.10.2", - "rand_pcg", - "ring", - "rustc-hash", - "rustls", - "rustls-pki-types", - "slab", - "thiserror", - "tinyvec", - "tracing", - "web-time", -] - -[[package]] -name = "quinn-udp" -version = "0.5.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35a133f956daabe89a61a685c2649f13d82d5aa4bd5d12d1277e1072a21c0694" -dependencies = [ - "cfg_aliases", - "libc", - "once_cell", - "socket2", - "tracing", - "windows-sys 0.61.2", -] - [[package]] name = "quote" version = "1.0.47" @@ -1906,15 +1789,6 @@ version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "63b8176103e19a2643978565ca18b50549f6101881c443590420e4dc998a3c69" -[[package]] -name = "rand_pcg" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "caa0f4137e1c0a72f4c651489402276c8e8e1cf081f3b0ba156d2cbeef09e86a" -dependencies = [ - "rand_core 0.10.1", -] - [[package]] name = "redox_syscall" version = "0.5.18" @@ -1964,38 +1838,6 @@ version = "0.8.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d6f6ff9a378485b298a5286656da665ba74413d36db0979633275d2e708145d4" -[[package]] -name = "reqwest" -version = "0.12.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eddd3ca559203180a307f12d114c268abf583f59b03cb906fd0b3ff8646c1147" -dependencies = [ - "base64", - "bytes", - "futures-core", - "http", - "http-body", - "http-body-util", - "hyper", - "hyper-util", - "js-sys", - "log", - "percent-encoding", - "pin-project-lite", - "serde", - "serde_json", - "serde_urlencoded", - "sync_wrapper", - "tokio", - "tower", - "tower-http", - "tower-service", - "url", - "wasm-bindgen", - "wasm-bindgen-futures", - "web-sys", -] - [[package]] name = "reqwest" version = "0.13.4" @@ -2017,7 +1859,6 @@ dependencies = [ "log", "percent-encoding", "pin-project-lite", - "quinn", "rustls", "rustls-pki-types", "rustls-platform-verifier", @@ -2063,12 +1904,6 @@ dependencies = [ "portable-atomic-util", ] -[[package]] -name = "rustc-hash" -version = "2.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b1e7f9a428571be2dc5bc0505c13fb6bf936822b894ec87abf8a08a4e51742d" - [[package]] name = "rustc_version" version = "0.4.1" @@ -2097,7 +1932,6 @@ version = "0.23.42" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3c54fcab019b409d04215d3a17cb438fd7fbf192ee61461f20f4fe18704bc138" dependencies = [ - "aws-lc-rs", "log", "once_cell", "ring", @@ -2125,7 +1959,6 @@ version = "1.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2f4925028c7eb5d1fcdaf196971378ed9d2c1c4efc7dc5d011256f76c99c0a96" dependencies = [ - "web-time", "zeroize", ] @@ -2162,7 +1995,6 @@ version = "0.103.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "61c429a8649f110dddef65e2a5ad240f747e85f7758a6bccc7e5777bd33f756e" dependencies = [ - "aws-lc-rs", "ring", "rustls-pki-types", "untrusted", @@ -2509,7 +2341,7 @@ dependencies = [ [[package]] name = "temporalio-client" -version = "0.5.0" +version = "0.6.0" dependencies = [ "anyhow", "async-trait", @@ -2540,7 +2372,7 @@ dependencies = [ [[package]] name = "temporalio-common" -version = "0.5.0" +version = "0.6.0" dependencies = [ "anyhow", "async-trait", @@ -2561,8 +2393,9 @@ dependencies = [ "prometheus", "prost", "prost-types", - "reqwest 0.12.28", + "reqwest", "ringbuf", + "rustls", "serde", "serde_json", "temporalio-common-wasm", @@ -2580,7 +2413,7 @@ dependencies = [ [[package]] name = "temporalio-common-wasm" -version = "0.5.0" +version = "0.6.0" dependencies = [ "anyhow", "async-trait", @@ -2605,7 +2438,7 @@ dependencies = [ [[package]] name = "temporalio-macros" -version = "0.5.0" +version = "0.6.0" dependencies = [ "proc-macro2", "quote", @@ -2614,7 +2447,7 @@ dependencies = [ [[package]] name = "temporalio-protos" -version = "0.5.0" +version = "0.6.0" dependencies = [ "anyhow", "base64", @@ -2635,7 +2468,7 @@ dependencies = [ [[package]] name = "temporalio-sdk-core" -version = "0.5.0" +version = "0.6.0" dependencies = [ "anyhow", "async-trait", @@ -2660,7 +2493,7 @@ dependencies = [ "prost", "prost-wkt-types", "rand 0.10.2", - "reqwest 0.13.4", + "reqwest", "serde", "serde_json", "siphasher", @@ -2726,21 +2559,6 @@ dependencies = [ "zerovec", ] -[[package]] -name = "tinyvec" -version = "1.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb4ebadaa0af04fab11ae01eb5f9fdb5f9c5b875506e210e71c07873528baa7f" -dependencies = [ - "tinyvec_macros", -] - -[[package]] -name = "tinyvec_macros" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" - [[package]] name = "tokio" version = "1.53.1" @@ -3246,16 +3064,6 @@ dependencies = [ "wasm-bindgen", ] -[[package]] -name = "web-time" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a6580f308b1fad9207618087a65c04e7a10bc77e02c8e84e9b00dd4b12fa0bb" -dependencies = [ - "js-sys", - "wasm-bindgen", -] - [[package]] name = "webpki-root-certs" version = "1.0.9" diff --git a/temporalio/bridge/Cargo.toml b/temporalio/bridge/Cargo.toml index 5984d9546..4cf6a02fe 100644 --- a/temporalio/bridge/Cargo.toml +++ b/temporalio/bridge/Cargo.toml @@ -28,11 +28,11 @@ pyo3 = { version = "0.29", features = [ ] } pyo3-async-runtimes = { version = "0.29", features = ["tokio-runtime"] } pythonize = "0.29" -temporalio-client = { version = "0.5", path = "./sdk-core/crates/client" } -temporalio-common = { version = "0.5", path = "./sdk-core/crates/common", features = [ +temporalio-client = { version = "0.6", path = "./sdk-core/crates/client" } +temporalio-common = { version = "0.6", path = "./sdk-core/crates/common", features = [ "envconfig", "otel" ]} -temporalio-sdk-core = { version = "0.5", path = "./sdk-core/crates/sdk-core", features = [ +temporalio-sdk-core = { version = "0.6", path = "./sdk-core/crates/sdk-core", features = [ "ephemeral-server", ] } tokio = "1.26" diff --git a/temporalio/bridge/proto/common/__init__.py b/temporalio/bridge/proto/common/__init__.py index 5622fffb8..a8506090d 100644 --- a/temporalio/bridge/proto/common/__init__.py +++ b/temporalio/bridge/proto/common/__init__.py @@ -1,10 +1,12 @@ from .common_pb2 import ( + ExternalStorageMetrics, NamespacedWorkflowExecution, VersioningIntent, WorkerDeploymentVersion, ) __all__ = [ + "ExternalStorageMetrics", "NamespacedWorkflowExecution", "VersioningIntent", "WorkerDeploymentVersion", diff --git a/temporalio/bridge/proto/common/common_pb2.py b/temporalio/bridge/proto/common/common_pb2.py index c56456fce..481cf216d 100644 --- a/temporalio/bridge/proto/common/common_pb2.py +++ b/temporalio/bridge/proto/common/common_pb2.py @@ -18,7 +18,7 @@ from google.protobuf import duration_pb2 as google_dot_protobuf_dot_duration__pb2 DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile( - b'\n%temporal/sdk/core/common/common.proto\x12\x0e\x63oresdk.common\x1a\x1egoogle/protobuf/duration.proto"U\n\x1bNamespacedWorkflowExecution\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t"D\n\x17WorkerDeploymentVersion\x12\x17\n\x0f\x64\x65ployment_name\x18\x01 \x01(\t\x12\x10\n\x08\x62uild_id\x18\x02 \x01(\t*@\n\x10VersioningIntent\x12\x0f\n\x0bUNSPECIFIED\x10\x00\x12\x0e\n\nCOMPATIBLE\x10\x01\x12\x0b\n\x07\x44\x45\x46\x41ULT\x10\x02\x42,\xea\x02)Temporalio::Internal::Bridge::Api::Commonb\x06proto3' + b'\n%temporal/sdk/core/common/common.proto\x12\x0e\x63oresdk.common\x1a\x1egoogle/protobuf/duration.proto"U\n\x1bNamespacedWorkflowExecution\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\t"D\n\x17WorkerDeploymentVersion\x12\x17\n\x0f\x64\x65ployment_name\x18\x01 \x01(\t\x12\x10\n\x08\x62uild_id\x18\x02 \x01(\t"\x92\x01\n\x16\x45xternalStorageMetrics\x12\x15\n\rpayload_count\x18\x01 \x01(\x04\x12\x18\n\x10total_size_bytes\x18\x02 \x01(\x04\x12\x31\n\x0etotal_duration\x18\x03 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x14\n\x0c\x64river_names\x18\x04 \x03(\t*@\n\x10VersioningIntent\x12\x0f\n\x0bUNSPECIFIED\x10\x00\x12\x0e\n\nCOMPATIBLE\x10\x01\x12\x0b\n\x07\x44\x45\x46\x41ULT\x10\x02\x42,\xea\x02)Temporalio::Internal::Bridge::Api::Commonb\x06proto3' ) _VERSIONINGINTENT = DESCRIPTOR.enum_types_by_name["VersioningIntent"] @@ -32,6 +32,7 @@ "NamespacedWorkflowExecution" ] _WORKERDEPLOYMENTVERSION = DESCRIPTOR.message_types_by_name["WorkerDeploymentVersion"] +_EXTERNALSTORAGEMETRICS = DESCRIPTOR.message_types_by_name["ExternalStorageMetrics"] NamespacedWorkflowExecution = _reflection.GeneratedProtocolMessageType( "NamespacedWorkflowExecution", (_message.Message,), @@ -54,15 +55,28 @@ ) _sym_db.RegisterMessage(WorkerDeploymentVersion) +ExternalStorageMetrics = _reflection.GeneratedProtocolMessageType( + "ExternalStorageMetrics", + (_message.Message,), + { + "DESCRIPTOR": _EXTERNALSTORAGEMETRICS, + "__module__": "temporal.sdk.core.common.common_pb2", + # @@protoc_insertion_point(class_scope:coresdk.common.ExternalStorageMetrics) + }, +) +_sym_db.RegisterMessage(ExternalStorageMetrics) + if _descriptor._USE_C_DESCRIPTORS == False: DESCRIPTOR._options = None DESCRIPTOR._serialized_options = ( b"\352\002)Temporalio::Internal::Bridge::Api::Common" ) - _VERSIONINGINTENT._serialized_start = 246 - _VERSIONINGINTENT._serialized_end = 310 + _VERSIONINGINTENT._serialized_start = 395 + _VERSIONINGINTENT._serialized_end = 459 _NAMESPACEDWORKFLOWEXECUTION._serialized_start = 89 _NAMESPACEDWORKFLOWEXECUTION._serialized_end = 174 _WORKERDEPLOYMENTVERSION._serialized_start = 176 _WORKERDEPLOYMENTVERSION._serialized_end = 244 + _EXTERNALSTORAGEMETRICS._serialized_start = 247 + _EXTERNALSTORAGEMETRICS._serialized_end = 393 # @@protoc_insertion_point(module_scope) diff --git a/temporalio/bridge/proto/common/common_pb2.pyi b/temporalio/bridge/proto/common/common_pb2.pyi index 739a129e1..8862fa036 100644 --- a/temporalio/bridge/proto/common/common_pb2.pyi +++ b/temporalio/bridge/proto/common/common_pb2.pyi @@ -4,10 +4,13 @@ isort:skip_file """ import builtins +import collections.abc import sys import typing import google.protobuf.descriptor +import google.protobuf.duration_pb2 +import google.protobuf.internal.containers import google.protobuf.internal.enum_type_wrapper import google.protobuf.message @@ -121,3 +124,53 @@ class WorkerDeploymentVersion(google.protobuf.message.Message): ) -> None: ... global___WorkerDeploymentVersion = WorkerDeploymentVersion + +class ExternalStorageMetrics(google.protobuf.message.Message): + """Metrics for a set of external payload storage operations (all uploads and downloads) + performed while processing a task, so core can emit unified logging and metrics. + """ + + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + PAYLOAD_COUNT_FIELD_NUMBER: builtins.int + TOTAL_SIZE_BYTES_FIELD_NUMBER: builtins.int + TOTAL_DURATION_FIELD_NUMBER: builtins.int + DRIVER_NAMES_FIELD_NUMBER: builtins.int + payload_count: builtins.int + """Number of payloads stored or retrieved externally.""" + total_size_bytes: builtins.int + """Total size in bytes of the externally stored or retrieved payloads.""" + @property + def total_duration(self) -> google.protobuf.duration_pb2.Duration: + """Wall-clock time spent on the external storage operations.""" + @property + def driver_names( + self, + ) -> google.protobuf.internal.containers.RepeatedScalarFieldContainer[builtins.str]: + """Names of the drivers that participated in the operations.""" + def __init__( + self, + *, + payload_count: builtins.int = ..., + total_size_bytes: builtins.int = ..., + total_duration: google.protobuf.duration_pb2.Duration | None = ..., + driver_names: collections.abc.Iterable[builtins.str] | None = ..., + ) -> None: ... + def HasField( + self, field_name: typing_extensions.Literal["total_duration", b"total_duration"] + ) -> builtins.bool: ... + def ClearField( + self, + field_name: typing_extensions.Literal[ + "driver_names", + b"driver_names", + "payload_count", + b"payload_count", + "total_duration", + b"total_duration", + "total_size_bytes", + b"total_size_bytes", + ], + ) -> None: ... + +global___ExternalStorageMetrics = ExternalStorageMetrics diff --git a/temporalio/bridge/proto/workflow_completion/workflow_completion_pb2.py b/temporalio/bridge/proto/workflow_completion/workflow_completion_pb2.py index ce26b220d..057b301e4 100644 --- a/temporalio/bridge/proto/workflow_completion/workflow_completion_pb2.py +++ b/temporalio/bridge/proto/workflow_completion/workflow_completion_pb2.py @@ -31,7 +31,7 @@ ) DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile( - b'\n?temporal/sdk/core/workflow_completion/workflow_completion.proto\x12\x1b\x63oresdk.workflow_completion\x1a%temporal/api/failure/v1/message.proto\x1a(temporal/api/enums/v1/failed_cause.proto\x1a$temporal/api/enums/v1/workflow.proto\x1a%temporal/sdk/core/common/common.proto\x1a;temporal/sdk/core/workflow_commands/workflow_commands.proto"\xac\x01\n\x1cWorkflowActivationCompletion\x12\x0e\n\x06run_id\x18\x01 \x01(\t\x12:\n\nsuccessful\x18\x02 \x01(\x0b\x32$.coresdk.workflow_completion.SuccessH\x00\x12\x36\n\x06\x66\x61iled\x18\x03 \x01(\x0b\x32$.coresdk.workflow_completion.FailureH\x00\x42\x08\n\x06status"\xac\x01\n\x07Success\x12<\n\x08\x63ommands\x18\x01 \x03(\x0b\x32*.coresdk.workflow_commands.WorkflowCommand\x12\x1b\n\x13used_internal_flags\x18\x06 \x03(\r\x12\x46\n\x13versioning_behavior\x18\x07 \x01(\x0e\x32).temporal.api.enums.v1.VersioningBehavior"\x81\x01\n\x07\x46\x61ilure\x12\x31\n\x07\x66\x61ilure\x18\x01 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12\x43\n\x0b\x66orce_cause\x18\x02 \x01(\x0e\x32..temporal.api.enums.v1.WorkflowTaskFailedCauseB8\xea\x02\x35Temporalio::Internal::Bridge::Api::WorkflowCompletionb\x06proto3' + b'\n?temporal/sdk/core/workflow_completion/workflow_completion.proto\x12\x1b\x63oresdk.workflow_completion\x1a%temporal/api/failure/v1/message.proto\x1a(temporal/api/enums/v1/failed_cause.proto\x1a$temporal/api/enums/v1/workflow.proto\x1a%temporal/sdk/core/common/common.proto\x1a;temporal/sdk/core/workflow_commands/workflow_commands.proto"\xbe\x02\n\x1cWorkflowActivationCompletion\x12\x0e\n\x06run_id\x18\x01 \x01(\t\x12:\n\nsuccessful\x18\x02 \x01(\x0b\x32$.coresdk.workflow_completion.SuccessH\x00\x12\x36\n\x06\x66\x61iled\x18\x03 \x01(\x0b\x32$.coresdk.workflow_completion.FailureH\x00\x12H\n\x18payload_download_metrics\x18\x04 \x01(\x0b\x32&.coresdk.common.ExternalStorageMetrics\x12\x46\n\x16payload_upload_metrics\x18\x05 \x01(\x0b\x32&.coresdk.common.ExternalStorageMetricsB\x08\n\x06status"\xac\x01\n\x07Success\x12<\n\x08\x63ommands\x18\x01 \x03(\x0b\x32*.coresdk.workflow_commands.WorkflowCommand\x12\x1b\n\x13used_internal_flags\x18\x06 \x03(\r\x12\x46\n\x13versioning_behavior\x18\x07 \x01(\x0e\x32).temporal.api.enums.v1.VersioningBehavior"\x81\x01\n\x07\x46\x61ilure\x12\x31\n\x07\x66\x61ilure\x18\x01 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12\x43\n\x0b\x66orce_cause\x18\x02 \x01(\x0e\x32..temporal.api.enums.v1.WorkflowTaskFailedCauseB8\xea\x02\x35Temporalio::Internal::Bridge::Api::WorkflowCompletionb\x06proto3' ) @@ -79,9 +79,9 @@ b"\352\0025Temporalio::Internal::Bridge::Api::WorkflowCompletion" ) _WORKFLOWACTIVATIONCOMPLETION._serialized_start = 316 - _WORKFLOWACTIVATIONCOMPLETION._serialized_end = 488 - _SUCCESS._serialized_start = 491 - _SUCCESS._serialized_end = 663 - _FAILURE._serialized_start = 666 - _FAILURE._serialized_end = 795 + _WORKFLOWACTIVATIONCOMPLETION._serialized_end = 634 + _SUCCESS._serialized_start = 637 + _SUCCESS._serialized_end = 809 + _FAILURE._serialized_start = 812 + _FAILURE._serialized_end = 941 # @@protoc_insertion_point(module_scope) diff --git a/temporalio/bridge/proto/workflow_completion/workflow_completion_pb2.pyi b/temporalio/bridge/proto/workflow_completion/workflow_completion_pb2.pyi index 5b438f360..8e12736aa 100644 --- a/temporalio/bridge/proto/workflow_completion/workflow_completion_pb2.pyi +++ b/temporalio/bridge/proto/workflow_completion/workflow_completion_pb2.pyi @@ -14,6 +14,7 @@ import google.protobuf.message import temporalio.api.enums.v1.failed_cause_pb2 import temporalio.api.enums.v1.workflow_pb2 import temporalio.api.failure.v1.message_pb2 +import temporalio.bridge.proto.common.common_pb2 import temporalio.bridge.proto.workflow_commands.workflow_commands_pb2 if sys.version_info >= (3, 8): @@ -31,23 +32,52 @@ class WorkflowActivationCompletion(google.protobuf.message.Message): RUN_ID_FIELD_NUMBER: builtins.int SUCCESSFUL_FIELD_NUMBER: builtins.int FAILED_FIELD_NUMBER: builtins.int + PAYLOAD_DOWNLOAD_METRICS_FIELD_NUMBER: builtins.int + PAYLOAD_UPLOAD_METRICS_FIELD_NUMBER: builtins.int run_id: builtins.str """The run id from the workflow activation you are completing""" @property def successful(self) -> global___Success: ... @property def failed(self) -> global___Failure: ... + @property + def payload_download_metrics( + self, + ) -> temporalio.bridge.proto.common.common_pb2.ExternalStorageMetrics: + """Metrics for external payload storage downloads (retrievals) performed while processing + this activation. Only set when external storage retrieved payloads. + """ + @property + def payload_upload_metrics( + self, + ) -> temporalio.bridge.proto.common.common_pb2.ExternalStorageMetrics: + """Metrics for external payload storage uploads (stores) performed while processing this + activation. Only set when external storage stored payloads. + """ def __init__( self, *, run_id: builtins.str = ..., successful: global___Success | None = ..., failed: global___Failure | None = ..., + payload_download_metrics: temporalio.bridge.proto.common.common_pb2.ExternalStorageMetrics + | None = ..., + payload_upload_metrics: temporalio.bridge.proto.common.common_pb2.ExternalStorageMetrics + | None = ..., ) -> None: ... def HasField( self, field_name: typing_extensions.Literal[ - "failed", b"failed", "status", b"status", "successful", b"successful" + "failed", + b"failed", + "payload_download_metrics", + b"payload_download_metrics", + "payload_upload_metrics", + b"payload_upload_metrics", + "status", + b"status", + "successful", + b"successful", ], ) -> builtins.bool: ... def ClearField( @@ -55,6 +85,10 @@ class WorkflowActivationCompletion(google.protobuf.message.Message): field_name: typing_extensions.Literal[ "failed", b"failed", + "payload_download_metrics", + b"payload_download_metrics", + "payload_upload_metrics", + b"payload_upload_metrics", "run_id", b"run_id", "status", diff --git a/temporalio/bridge/sdk-core b/temporalio/bridge/sdk-core index 21fcc2952..78ac17e4b 160000 --- a/temporalio/bridge/sdk-core +++ b/temporalio/bridge/sdk-core @@ -1 +1 @@ -Subproject commit 21fcc2952257478489bd6e74cd0a65eb0b2c63be +Subproject commit 78ac17e4bdaffdb54eb1c925a07d1fd40ce7b7f6 diff --git a/temporalio/bridge/src/client.rs b/temporalio/bridge/src/client.rs index 37bfc796d..aec5c0ef8 100644 --- a/temporalio/bridge/src/client.rs +++ b/temporalio/bridge/src/client.rs @@ -280,10 +280,12 @@ impl ClientConfig { .maybe_http_connect_proxy(self.http_connect_proxy_config.map(Into::into)) .dns_load_balancing(dns_load_balancing) .grpc_compression(grpc_compression_from_str(&self.grpc_compression)?) - .payload_limits(temporalio_client::PayloadLimitsOptions { - payloads_warn_size: self.payloads_warn_size, - memo_warn_size: self.memo_warn_size, - }) + .payload_limits( + temporalio_client::PayloadLimitsOptions::builder() + .payloads_warn_size(self.payloads_warn_size) + .memo_warn_size(self.memo_warn_size) + .build(), + ) .headers(ascii_headers) .binary_headers(binary_headers) .maybe_api_key(self.api_key) @@ -325,25 +327,26 @@ impl TryFrom for temporalio_client::TlsOptions { Some(fixed_server_name_verifier(&name, &ca_cert)?) } }; - Ok(temporalio_client::TlsOptions { - server_root_ca_cert, - domain: conf.domain, - client_tls_options: match (conf.client_cert, conf.client_private_key) { - (None, None) => None, - (Some(client_cert), Some(client_private_key)) => { - Some(temporalio_client::ClientTlsOptions { - client_cert, - client_private_key, - }) - } - _ => { - return Err(PyValueError::new_err( - "Must have both client cert and private key or neither", - )) - } - }, - server_cert_verifier, - }) + let client_tls_options = match (conf.client_cert, conf.client_private_key) { + (None, None) => None, + (Some(client_cert), Some(client_private_key)) => Some( + temporalio_client::ClientTlsOptions::builder() + .client_cert(client_cert) + .client_private_key(client_private_key) + .build(), + ), + _ => { + return Err(PyValueError::new_err( + "Must have both client cert and private key or neither", + )) + } + }; + Ok(temporalio_client::TlsOptions::builder() + .maybe_server_root_ca_cert(server_root_ca_cert) + .maybe_domain(conf.domain) + .maybe_client_tls_options(client_tls_options) + .maybe_server_cert_verifier(server_cert_verifier) + .build()) } } @@ -430,32 +433,31 @@ impl ServerCertVerifier for FixedServerNameVerifier { impl From for RetryOptions { fn from(conf: ClientRetryConfig) -> Self { - RetryOptions { - initial_interval: Duration::from_millis(conf.initial_interval_millis), - randomization_factor: conf.randomization_factor, - multiplier: conf.multiplier, - max_interval: Duration::from_millis(conf.max_interval_millis), - max_elapsed_time: conf.max_elapsed_time_millis.map(Duration::from_millis), - max_retries: conf.max_retries, - } + RetryOptions::builder() + .initial_interval(Duration::from_millis(conf.initial_interval_millis)) + .randomization_factor(conf.randomization_factor) + .multiplier(conf.multiplier) + .max_interval(Duration::from_millis(conf.max_interval_millis)) + .max_elapsed_time(conf.max_elapsed_time_millis.map(Duration::from_millis)) + .max_retries(conf.max_retries) + .build() } } impl From for CoreClientKeepAliveConfig { fn from(conf: ClientKeepAliveConfig) -> Self { - CoreClientKeepAliveConfig { - interval: Duration::from_millis(conf.interval_millis), - timeout: Duration::from_millis(conf.timeout_millis), - } + CoreClientKeepAliveConfig::builder() + .interval(Duration::from_millis(conf.interval_millis)) + .timeout(Duration::from_millis(conf.timeout_millis)) + .build() } } impl From for HttpConnectProxyOptions { fn from(conf: ClientHttpConnectProxyConfig) -> Self { - HttpConnectProxyOptions { - target_addr: conf.target_host, - basic_auth: conf.basic_auth, - } + HttpConnectProxyOptions::new(conf.target_host) + .maybe_basic_auth(conf.basic_auth) + .build() } } diff --git a/temporalio/bridge/src/envconfig.rs b/temporalio/bridge/src/envconfig.rs index 40ef9b638..7ce2f4664 100644 --- a/temporalio/bridge/src/envconfig.rs +++ b/temporalio/bridge/src/envconfig.rs @@ -91,10 +91,10 @@ fn load_client_config_inner( config_file_strict: bool, env_vars: Option>, ) -> PyResult> { - let options = LoadClientConfigOptions { - config_source, - config_file_strict, - }; + let options = LoadClientConfigOptions::builder() + .maybe_config_source(config_source) + .config_file_strict(config_file_strict) + .build(); let core_config = core_load_client_config(options, env_vars.as_ref()) .map_err(|e| ConfigError::new_err(format!("{e}")))?; @@ -110,13 +110,13 @@ fn load_client_connect_config_inner( config_file_strict: bool, env_vars: Option>, ) -> PyResult> { - let options = LoadClientConfigProfileOptions { - config_source, - config_file_profile: profile, - config_file_strict, - disable_file, - disable_env, - }; + let options = LoadClientConfigProfileOptions::builder() + .maybe_config_source(config_source) + .maybe_config_file_profile(profile) + .config_file_strict(config_file_strict) + .disable_file(disable_file) + .disable_env(disable_env) + .build(); let profile = core_load_client_config_profile(options, env_vars.as_ref()) .map_err(|e| ConfigError::new_err(format!("{e}")))?; diff --git a/temporalio/bridge/src/worker.rs b/temporalio/bridge/src/worker.rs index d0b007dba..321dc6560 100644 --- a/temporalio/bridge/src/worker.rs +++ b/temporalio/bridge/src/worker.rs @@ -899,24 +899,25 @@ fn convert_versioning_strategy( }, WorkerVersioningStrategy::DeploymentBased(options) => { temporalio_sdk_core::WorkerVersioningStrategy::WorkerDeploymentBased( - temporalio_common::worker::WorkerDeploymentOptions { - version: temporalio_common::worker::WorkerDeploymentVersion { + temporalio_common::worker::WorkerDeploymentOptions::new( + temporalio_common::worker::WorkerDeploymentVersion { deployment_name: options.version.deployment_name, build_id: options.version.build_id, }, - use_worker_versioning: options.use_worker_versioning, - default_versioning_behavior: if options.use_worker_versioning { - Some( - temporalio_common::protos::temporal::api::enums::v1::VersioningBehavior::try_from( - options.default_versioning_behavior, - ) - .unwrap_or_default() - .into(), + ) + .use_worker_versioning(options.use_worker_versioning) + .maybe_default_versioning_behavior(if options.use_worker_versioning { + Some( + temporalio_common::protos::temporal::api::enums::v1::VersioningBehavior::try_from( + options.default_versioning_behavior, ) - } else { - None - }, - }, + .unwrap_or_default() + .into(), + ) + } else { + None + }) + .build(), ) } WorkerVersioningStrategy::LegacyBuildIdBased(lb) => { From f35f4a1ef6c293cf1032eb05a811447b3f606ada Mon Sep 17 00:00:00 2001 From: Ribhav Jain Date: Wed, 12 Aug 2026 04:27:15 +0400 Subject: [PATCH 223/226] Add workflow.uuid7() (#1733) * Add workflow.uuid7() * Suppress unreachable-code warning on pre-3.14 type checks --------- Co-authored-by: Tim Conley --- CHANGELOG.md | 8 +++ .../worker/workflow_sandbox/_restrictions.py | 4 +- temporalio/workflow/__init__.py | 2 + temporalio/workflow/_context.py | 28 ++++++++ tests/worker/test_workflow.py | 67 +++++++++++++++++++ tests/worker/workflow_sandbox/test_runner.py | 4 ++ 6 files changed, 112 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d146f045b..614fd8e01 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,6 +20,14 @@ to include examples, links to docs, or any other relevant information. ### Added +- `temporalio.workflow.uuid7()` generates a determinism-safe, time-sortable + UUIDv7 (RFC 9562) from workflow time and the workflow's deterministic random + generator, complementing the existing `workflow.uuid4()` + ([#1450](https://github.com/temporalio/sdk-python/issues/1450)). The + workflow sandbox now also restricts the non-deterministic `uuid.uuid7()` + added to the standard library in Python 3.14, matching the existing + `uuid.uuid1()`/`uuid.uuid4()` restrictions. + ### Changed - `temporalio.contrib.pydantic` converters now reuse Pydantic type adapters diff --git a/temporalio/worker/workflow_sandbox/_restrictions.py b/temporalio/worker/workflow_sandbox/_restrictions.py index 34f9efee2..23774fcd2 100644 --- a/temporalio/worker/workflow_sandbox/_restrictions.py +++ b/temporalio/worker/workflow_sandbox/_restrictions.py @@ -769,7 +769,9 @@ def _public_callables(parent: Any, *, exclude: set[str] = set()) -> set[str]: "urllib": SandboxMatcher( children={"request": SandboxMatcher.all_uses}, ), - "uuid": SandboxMatcher(use={"uuid1", "uuid4"}, only_runtime=True), + # uuid7 only exists in the stdlib on Python 3.14+; matching a + # nonexistent attribute is harmless on older versions + "uuid": SandboxMatcher(use={"uuid1", "uuid4", "uuid7"}, only_runtime=True), "webbrowser": SandboxMatcher.all_uses, "xmlrpc": SandboxMatcher.all_uses, "zipfile": SandboxMatcher( diff --git a/temporalio/workflow/__init__.py b/temporalio/workflow/__init__.py index 3d5a65c77..fa2681139 100644 --- a/temporalio/workflow/__init__.py +++ b/temporalio/workflow/__init__.py @@ -94,6 +94,7 @@ upsert_memo, upsert_search_attributes, uuid4, + uuid7, wait_condition, ) from ._definition import ( @@ -225,6 +226,7 @@ "upsert_memo", "upsert_search_attributes", "uuid4", + "uuid7", "wait_condition", "DynamicWorkflowConfig", "defn", diff --git a/temporalio/workflow/_context.py b/temporalio/workflow/_context.py index d2ec0d633..b33f83150 100644 --- a/temporalio/workflow/_context.py +++ b/temporalio/workflow/_context.py @@ -65,6 +65,7 @@ "upsert_memo", "upsert_search_attributes", "uuid4", + "uuid7", "wait_condition", ] @@ -901,6 +902,33 @@ def uuid4() -> uuid.UUID: return uuid.UUID(bytes=random().getrandbits(16 * 8).to_bytes(16, "big"), version=4) +def uuid7() -> uuid.UUID: + """Get a new, determinism-safe v7 UUID based on :py:func:`time_ns` and + :py:func:`random`. + + Per RFC 9562, the UUID's leading 48 bits are the current workflow time as + milliseconds since the epoch, so UUIDs from successive workflow tasks sort + by creation time. The remaining 74 bits are random. UUIDs generated within + the same workflow task share the same workflow time and are not guaranteed + to be monotonically ordered with respect to one another. + + Note, this UUID is not cryptographically safe and should not be used for + security purposes. + + Returns: + A deterministically-seeded v7 UUID. + """ + # uuid.UUID's version parameter only accepts 1-5 before Python 3.14, so + # the version and variant bits are set manually. + unix_ts_ms = (time_ns() // 1_000_000) & 0xFFFF_FFFF_FFFF + rand = random() + rand_a = rand.getrandbits(12) + rand_b = rand.getrandbits(62) + return uuid.UUID( + int=(unix_ts_ms << 80) | (0x7 << 76) | (rand_a << 64) | (0b10 << 62) | rand_b + ) + + async def sleep(duration: float | timedelta, *, summary: str | None = None) -> None: """Sleep for the given duration. diff --git a/tests/worker/test_workflow.py b/tests/worker/test_workflow.py index 283357c2d..39e648e60 100644 --- a/tests/worker/test_workflow.py +++ b/tests/worker/test_workflow.py @@ -3934,6 +3934,73 @@ async def test_workflow_uuid(client: Client): assert handle2_query_result == await handle2.query(UUIDWorkflow.result) +@workflow.defn +class UUID7Workflow: + def __init__(self) -> None: + self._result = "" + self._time_ms = -1 + + @workflow.run + async def run(self) -> None: + self._time_ms = workflow.time_ns() // 1_000_000 + self._result = str(workflow.uuid7()) + + @workflow.query + def result(self) -> str: + return self._result + + @workflow.query + def time_ms(self) -> int: + return self._time_ms + + +async def test_workflow_uuid7(client: Client): + task_queue = str(uuid.uuid4()) + async with new_worker( + client, UUID7Workflow, task_queue=task_queue, max_cached_workflows=0 + ): + # Get two handle UUID results. Need to disable workflow cache since we + # restart the worker and don't want to pay the sticky queue penalty. + handle1 = await client.start_workflow( + UUID7Workflow.run, id=f"workflow-{uuid.uuid4()}", task_queue=task_queue + ) + await handle1.result() + handle1_query_result = await handle1.query(UUID7Workflow.result) + + handle2 = await client.start_workflow( + UUID7Workflow.run, + id=f"workflow-{uuid.uuid4()}", + task_queue=task_queue, + ) + await handle2.result() + handle2_query_result = await handle2.query(UUID7Workflow.result) + + # Confirm they aren't equal to each other but they are equal to retries + # of the same query + assert handle1_query_result != handle2_query_result + assert handle1_query_result == await handle1.query(UUID7Workflow.result) + assert handle2_query_result == await handle2.query(UUID7Workflow.result) + + # Confirm RFC 9562 shape: version 7, RFC variant, and the leading 48 + # bits are the workflow time in milliseconds at generation + for handle, query_result in ( + (handle1, handle1_query_result), + (handle2, handle2_query_result), + ): + result_uuid = uuid.UUID(query_result) + assert result_uuid.version == 7 + assert result_uuid.variant == uuid.RFC_4122 + workflow_time_ms = await handle.query(UUID7Workflow.time_ms) + assert int(result_uuid) >> 80 == workflow_time_ms + + # Now confirm those results are the same even on a new worker + async with new_worker( + client, UUID7Workflow, task_queue=task_queue, max_cached_workflows=0 + ): + assert handle1_query_result == await handle1.query(UUID7Workflow.result) + assert handle2_query_result == await handle2.query(UUID7Workflow.result) + + @activity.defn(name="custom-name") class CallableClassActivity: def __init__(self, orig_field1: str) -> None: diff --git a/tests/worker/workflow_sandbox/test_runner.py b/tests/worker/workflow_sandbox/test_runner.py index 288da0861..024ab7273 100644 --- a/tests/worker/workflow_sandbox/test_runner.py +++ b/tests/worker/workflow_sandbox/test_runner.py @@ -197,6 +197,10 @@ async def test_workflow_sandbox_restrictions(client: Client): if sys.version_info < (3, 14): invalid_code_to_check.append("import os.path\nos.path.abspath('foo')") # type: ignore[reportUnreachable] + # uuid7 was only added to the stdlib in 3.14 + if sys.version_info >= (3, 14): + invalid_code_to_check.append("import uuid\nuuid.uuid7()") # type: ignore[reportUnreachable] + for code in invalid_code_to_check: with pytest.raises(WorkflowFailureError) as err: await client.execute_workflow( From ad58f0aa7c7fe4590fea97af0e1041017e828910 Mon Sep 17 00:00:00 2001 From: jaeyoung <43835297+jaeyoung0509@users.noreply.github.com> Date: Thu, 13 Aug 2026 01:06:52 +0900 Subject: [PATCH 224/226] docs: clarify OpenAI Agents tool execution (#1741) * docs(openai-agents): clarify tool execution boundaries * docs(openai-agents): refine tool execution model * docs(openai-agents): preserve activity diagram structure --- temporalio/contrib/openai_agents/README.md | 46 +++++++++++++++++----- 1 file changed, 37 insertions(+), 9 deletions(-) diff --git a/temporalio/contrib/openai_agents/README.md b/temporalio/contrib/openai_agents/README.md index e392bf3e3..83539044c 100644 --- a/temporalio/contrib/openai_agents/README.md +++ b/temporalio/contrib/openai_agents/README.md @@ -130,11 +130,10 @@ The key to making this work is to separate the applications repeatable (determin Workflow code can run for extended periods and, if interrupted, resume exactly where it left off. Activity code faces no restrictions on I/O or external interactions, but if it fails part-way through it restarts from the beginning. -In the AI-agent example above, model invocations and tool calls run inside activities, while the logic that coordinates them lives in the workflow. +In this integration, model invocations are automatically routed through Temporal activities, while the logic that coordinates them lives in the workflow. +Tools that perform I/O or other non-deterministic work should run as Temporal activities, while deterministic, workflow-safe tools can run directly in the workflow. This pattern generalizes to more sophisticated agents. -We refer to that coordinating logic as _agent orchestration_. - -As a general rule, agent orchestration code executes within the Temporal workflow, whereas model calls and any I/O-bound tool invocations execute as Temporal activities. +We refer to the coordinating logic as _agent orchestration_. The diagram below shows the overall architecture of an agentic application in Temporal. The Temporal Server is responsible to tracking program execution and making sure associated state is preserved reliably (i.e., stored to a database, possibly replicated across cloud regions). @@ -154,13 +153,14 @@ Temporal Server manages data in encrypted form, so all data processing occurs on | Worker | | +----------------------------------------------+ | | | Workflow Code | | -| | (Agent Orchestration Loop) | | +| | (Agent orchestration + deterministic tools) | | | +----------------------------------------------+ | | | | | | | v v v | | +-----------+ +-----------+ +-------------+ | | | Activity | | Activity | | Activity | | -| | (Tool 1) | | (Tool 2) | | (Model API) | | +| | (I/O Tool | | (I/O Tool | | (Model API) | | +| | 1) | | 2) | | | | | +-----------+ +-----------+ +-------------+ | | | | | | +------------------------------------------------------+ @@ -267,10 +267,22 @@ To run this example, see the detailed instructions in the [Temporal Python Sampl ## Tool Calling +Model invocations are automatically routed through Temporal activities. +OpenAI-hosted tools are passed through the model invocation and executed by the model provider. +User-defined `FunctionTool`s, including tools created with `@function_tool`, are not automatically converted into Temporal activities; they execute in the workflow unless explicitly backed by a Temporal activity. +Where a tool executes depends on how it is defined: + +| Tool | Execution | Use for | +| --- | --- | --- | +| `activity_as_tool()` | Temporal activity | External I/O and non-deterministic operations | +| `FunctionTool` / `@function_tool` | Workflow | Deterministic, workflow-safe computation | +| OpenAI-hosted tool | Model provider | Provider-hosted features executed as part of the model invocation | + ### Temporal Activities as OpenAI Agents Tools One of the powerful features of this integration is the ability to convert Temporal activities into agent tools using `activity_as_tool`. This allows your agent to leverage Temporal's durable execution for tool calls. +`activity_as_tool()` creates an OpenAI Agents `FunctionTool` whose invocation schedules the underlying Temporal activity. In the example below, we apply the `@activity.defn` decorator to the `get_weather` function to create a Temporal activity. We then pass this through the `activity_as_tool` helper function to create an OpenAI Agents tool that is passed to the `Agent`. @@ -311,9 +323,23 @@ class WeatherAgent: return result.final_output ``` +The activity must also be registered with a Worker. +`activity_as_tool()` controls how the Agent invokes the activity; it does not register the activity with the Worker. + +```python +from temporalio.worker import Worker + +worker = Worker( + client, + task_queue="my-task-queue", + workflows=[WeatherAgent], + activities=[get_weather], +) +``` + ### Calling OpenAI Agents Tools inside Temporal Workflows -For simple computations that don't involve external calls you can call the tool directly from the workflow by using the standard OpenAI Agents SDK `@functiontool` annotation. +For simple computations that don't involve external calls, you can call the tool directly from the workflow by using the standard OpenAI Agents SDK `@function_tool` decorator. ```python from temporalio import workflow @@ -339,8 +365,10 @@ class MathAssistantAgent: return result.final_output ``` -Note that any tools that run in the workflow must respect the workflow execution restrictions, meaning no I/O or non-deterministic operations. -Of course, code running in the workflow can invoke a Temporal activity at any time. +Use regular `@function_tool` tools only for deterministic, workflow-safe logic. +Do not perform network, database, filesystem, or other external I/O directly from these tools. +Use a Temporal activity with `activity_as_tool()` instead. +Code running in the workflow can also invoke a Temporal activity directly when needed. Tools that run in the workflow can also update OpenAI Agents context, which is read-only for tools run as Temporal activities. From d489a5dd679094f6580556dc531c9f1e1515b804 Mon Sep 17 00:00:00 2001 From: Justin Anderson <44687433+jmaeagle99@users.noreply.github.com> Date: Wed, 12 Aug 2026 09:27:18 -0700 Subject: [PATCH 225/226] chore: update sdk-core submodule to latest (#1742) --- temporalio/bridge/Cargo.lock | 1 + temporalio/bridge/sdk-core | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/temporalio/bridge/Cargo.lock b/temporalio/bridge/Cargo.lock index 10632afb2..97a247eb4 100644 --- a/temporalio/bridge/Cargo.lock +++ b/temporalio/bridge/Cargo.lock @@ -2359,6 +2359,7 @@ dependencies = [ "hyper-util", "parking_lot", "rand 0.10.2", + "serde_json", "temporalio-common", "thiserror", "tokio", diff --git a/temporalio/bridge/sdk-core b/temporalio/bridge/sdk-core index 78ac17e4b..999e5a7dc 160000 --- a/temporalio/bridge/sdk-core +++ b/temporalio/bridge/sdk-core @@ -1 +1 @@ -Subproject commit 78ac17e4bdaffdb54eb1c925a07d1fd40ce7b7f6 +Subproject commit 999e5a7dc8bbb8c457322ccb8e1806a0e780be95 From 060e0266f292db772d919508010026ba02750c59 Mon Sep 17 00:00:00 2001 From: Alex Mazzeo Date: Wed, 12 Aug 2026 11:30:39 -0700 Subject: [PATCH 226/226] Add missing entry for Nexus invoked SAA (#1746) --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 614fd8e01..17a52311d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -27,6 +27,8 @@ to include examples, links to docs, or any other relevant information. workflow sandbox now also restricts the non-deterministic `uuid.uuid7()` added to the standard library in Python 3.14, matching the existing `uuid.uuid1()`/`uuid.uuid4()` restrictions. +- **Experimental**: `TemporalOperationHandler` can now use Standalone Activities as asynchronous + Nexus Operation backing executions through `TemporalNexusClient.start_activity`. ### Changed